aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2006-01-19 16:39:33 +0000
committerAnton Altaparmakov <aia21@cantab.net>2006-01-19 16:39:33 +0000
commit944d79559d154c12becde0dab327016cf438f46c (patch)
tree50c101806f4d3b6585222dda060559eb4f3e005a
parentMerge branch 'master' of /usr/src/ntfs-2.6/ (diff)
parentMerge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6 (diff)
downloadlinux-dev-944d79559d154c12becde0dab327016cf438f46c.tar.xz
linux-dev-944d79559d154c12becde0dab327016cf438f46c.zip
Merge branch 'master' of /usr/src/ntfs-2.6/
-rw-r--r--.gitignore2
-rw-r--r--CREDITS3
-rw-r--r--Documentation/Changes31
-rw-r--r--Documentation/CodingStyle43
-rw-r--r--Documentation/DocBook/.gitignore6
-rw-r--r--Documentation/DocBook/kernel-api.tmpl6
-rw-r--r--Documentation/DocBook/kernel-locking.tmpl22
-rw-r--r--Documentation/DocBook/usb.tmpl1
-rw-r--r--Documentation/DocBook/videobook.tmpl4
-rw-r--r--Documentation/RCU/rcuref.txt87
-rw-r--r--Documentation/SubmittingDrivers24
-rw-r--r--Documentation/SubmittingPatches68
-rw-r--r--Documentation/applying-patches.txt81
-rw-r--r--Documentation/block/barrier.txt271
-rw-r--r--Documentation/block/biodoc.txt12
-rw-r--r--Documentation/block/stat.txt82
-rw-r--r--Documentation/cachetlb.txt2
-rw-r--r--Documentation/cpu-freq/governors.txt62
-rw-r--r--Documentation/cpu-hotplug.txt357
-rw-r--r--Documentation/cpusets.txt165
-rw-r--r--Documentation/drivers/edac/edac.txt673
-rw-r--r--Documentation/dvb/avermedia.txt3
-rw-r--r--Documentation/dvb/get_dvb_firmware23
-rw-r--r--Documentation/dvb/ttusb-dec.txt3
-rw-r--r--Documentation/fb/cyblafb/bugs1
-rw-r--r--Documentation/fb/cyblafb/fb.modes57
-rw-r--r--Documentation/fb/cyblafb/performance1
-rw-r--r--Documentation/fb/cyblafb/todo5
-rw-r--r--Documentation/fb/cyblafb/usage33
-rw-r--r--Documentation/fb/cyblafb/whatsnew29
-rw-r--r--Documentation/feature-removal-schedule.txt29
-rw-r--r--Documentation/filesystems/00-INDEX8
-rw-r--r--Documentation/filesystems/configfs/configfs.txt434
-rw-r--r--Documentation/filesystems/configfs/configfs_example.c474
-rw-r--r--Documentation/filesystems/dlmfs.txt130
-rw-r--r--Documentation/filesystems/ext3.txt181
-rw-r--r--Documentation/filesystems/fuse.txt63
-rw-r--r--Documentation/filesystems/ocfs2.txt55
-rw-r--r--Documentation/filesystems/proc.txt19
-rw-r--r--Documentation/filesystems/ramfs-rootfs-initramfs.txt72
-rw-r--r--Documentation/filesystems/relayfs.txt126
-rw-r--r--Documentation/filesystems/spufs.txt521
-rw-r--r--Documentation/filesystems/sysfs-pci.txt21
-rw-r--r--Documentation/filesystems/tmpfs.txt12
-rw-r--r--Documentation/filesystems/vfs.txt5
-rw-r--r--Documentation/hpet.txt2
-rw-r--r--Documentation/hrtimers.txt178
-rw-r--r--Documentation/hwmon/w83627hf19
-rw-r--r--Documentation/i2c/busses/i2c-nforce23
-rw-r--r--Documentation/i2c/busses/i2c-parport1
-rw-r--r--Documentation/i2c/porting-clients90
-rw-r--r--Documentation/i2c/writing-clients20
-rw-r--r--Documentation/i2o/ioctl2
-rw-r--r--Documentation/input/appletouch.txt5
-rw-r--r--Documentation/input/ff.txt2
-rw-r--r--Documentation/ioctl/hdio.txt2
-rw-r--r--Documentation/kbuild/makefiles.txt4
-rw-r--r--Documentation/kbuild/modules.txt66
-rw-r--r--Documentation/kdump/gdbmacros.txt22
-rw-r--r--Documentation/kdump/kdump.txt149
-rw-r--r--Documentation/kernel-parameters.txt88
-rw-r--r--Documentation/keys-request-key.txt22
-rw-r--r--Documentation/keys.txt61
-rw-r--r--Documentation/kprobes.txt3
-rw-r--r--Documentation/laptop-mode.txt8
-rw-r--r--Documentation/locks.txt17
-rw-r--r--Documentation/md.txt120
-rw-r--r--Documentation/mutex-design.txt135
-rw-r--r--Documentation/networking/bonding.txt2
-rw-r--r--Documentation/networking/gianfar.txt72
-rw-r--r--Documentation/networking/ip-sysctl.txt23
-rw-r--r--Documentation/networking/sk98lin.txt4
-rw-r--r--Documentation/oops-tracing.txt8
-rw-r--r--Documentation/pci-error-recovery.txt246
-rw-r--r--Documentation/pcmcia/driver-changes.txt11
-rw-r--r--Documentation/pm.txt2
-rw-r--r--Documentation/power/interface.txt11
-rw-r--r--Documentation/power/swsusp.txt9
-rw-r--r--Documentation/powerpc/00-INDEX10
-rw-r--r--Documentation/powerpc/eeh-pci-error-recovery.txt31
-rw-r--r--Documentation/scsi/ChangeLog.megaraid35
-rw-r--r--Documentation/scsi/aacraid.txt108
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt39
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt194
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl592
-rw-r--r--Documentation/sound/alsa/Procfile.txt16
-rw-r--r--Documentation/sound/alsa/hda_codec.txt14
-rw-r--r--Documentation/spi/butterfly57
-rw-r--r--Documentation/spi/spi-summary457
-rw-r--r--Documentation/stable_kernel_rules.txt60
-rw-r--r--Documentation/sysctl/vm.txt38
-rw-r--r--Documentation/sysrq.txt6
-rw-r--r--Documentation/video4linux/CARDLIST.bttv2
-rw-r--r--Documentation/video4linux/CARDLIST.cx8812
-rw-r--r--Documentation/video4linux/CARDLIST.saa71345
-rw-r--r--Documentation/video4linux/CARDLIST.tuner7
-rw-r--r--Documentation/x86_64/boot-options.txt4
-rw-r--r--Documentation/x86_64/cpu-hotplug-spec21
-rw-r--r--Kbuild5
-rw-r--r--MAINTAINERS163
-rw-r--r--Makefile156
-rw-r--r--README37
-rw-r--r--arch/alpha/Kconfig16
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c2
-rw-r--r--arch/alpha/kernel/irq.c630
-rw-r--r--arch/alpha/kernel/osf_sys.c2
-rw-r--r--arch/alpha/kernel/pci-noop.c1
-rw-r--r--arch/alpha/kernel/process.c34
-rw-r--r--arch/alpha/kernel/ptrace.c71
-rw-r--r--arch/alpha/kernel/smp.c2
-rw-r--r--arch/alpha/kernel/sys_alcor.c3
-rw-r--r--arch/alpha/kernel/sys_sio.c6
-rw-r--r--arch/alpha/mm/init.c1
-rw-r--r--arch/arm/Kconfig70
-rw-r--r--arch/arm/Makefile24
-rw-r--r--arch/arm/boot/Makefile2
-rw-r--r--arch/arm/boot/compressed/Makefile8
-rw-r--r--arch/arm/boot/compressed/head-at91rm9200.S57
-rw-r--r--arch/arm/boot/compressed/head-epxa10db.S5
-rw-r--r--arch/arm/boot/compressed/head.S48
-rw-r--r--arch/arm/common/Kconfig10
-rw-r--r--arch/arm/common/Makefile3
-rw-r--r--arch/arm/common/locomo.c4
-rw-r--r--arch/arm/common/rtctime.c16
-rw-r--r--arch/arm/common/sa1111.c4
-rw-r--r--arch/arm/common/scoop.c3
-rw-r--r--arch/arm/common/sharpsl_pm.c839
-rw-r--r--arch/arm/common/vic.c92
-rw-r--r--arch/arm/configs/assabet_defconfig1
-rw-r--r--arch/arm/configs/at91rm9200dk_defconfig1009
-rw-r--r--arch/arm/configs/at91rm9200ek_defconfig998
-rw-r--r--arch/arm/configs/badge4_defconfig1
-rw-r--r--arch/arm/configs/bast_defconfig1
-rw-r--r--arch/arm/configs/cerfcube_defconfig1
-rw-r--r--arch/arm/configs/clps7500_defconfig1
-rw-r--r--arch/arm/configs/collie_defconfig1
-rw-r--r--arch/arm/configs/corgi_defconfig1
-rw-r--r--arch/arm/configs/csb337_defconfig1136
-rw-r--r--arch/arm/configs/csb637_defconfig1116
-rw-r--r--arch/arm/configs/ebsa110_defconfig1
-rw-r--r--arch/arm/configs/edb7211_defconfig1
-rw-r--r--arch/arm/configs/enp2611_defconfig1
-rw-r--r--arch/arm/configs/ep80219_defconfig2
-rw-r--r--arch/arm/configs/footbridge_defconfig1
-rw-r--r--arch/arm/configs/fortunet_defconfig1
-rw-r--r--arch/arm/configs/h3600_defconfig1
-rw-r--r--arch/arm/configs/h7201_defconfig1
-rw-r--r--arch/arm/configs/h7202_defconfig1
-rw-r--r--arch/arm/configs/hackkit_defconfig1
-rw-r--r--arch/arm/configs/integrator_defconfig1
-rw-r--r--arch/arm/configs/iq31244_defconfig2
-rw-r--r--arch/arm/configs/iq80321_defconfig2
-rw-r--r--arch/arm/configs/iq80331_defconfig2
-rw-r--r--arch/arm/configs/iq80332_defconfig2
-rw-r--r--arch/arm/configs/ixdp2400_defconfig1
-rw-r--r--arch/arm/configs/ixdp2401_defconfig1
-rw-r--r--arch/arm/configs/ixdp2800_defconfig1
-rw-r--r--arch/arm/configs/ixdp2801_defconfig1
-rw-r--r--arch/arm/configs/ixp4xx_defconfig85
-rw-r--r--arch/arm/configs/jornada720_defconfig1
-rw-r--r--arch/arm/configs/lart_defconfig1
-rw-r--r--arch/arm/configs/lpd7a400_defconfig1
-rw-r--r--arch/arm/configs/lpd7a404_defconfig1
-rw-r--r--arch/arm/configs/lubbock_defconfig1
-rw-r--r--arch/arm/configs/lusl7200_defconfig1
-rw-r--r--arch/arm/configs/mainstone_defconfig1
-rw-r--r--arch/arm/configs/mx1ads_defconfig1
-rw-r--r--arch/arm/configs/neponset_defconfig1
-rw-r--r--arch/arm/configs/netwinder_defconfig1
-rw-r--r--arch/arm/configs/omap_h2_1610_defconfig1
-rw-r--r--arch/arm/configs/pleb_defconfig1
-rw-r--r--arch/arm/configs/pxa255-idp_defconfig1
-rw-r--r--arch/arm/configs/realview_defconfig1
-rw-r--r--arch/arm/configs/rpc_defconfig1
-rw-r--r--arch/arm/configs/s3c2410_defconfig1
-rw-r--r--arch/arm/configs/shannon_defconfig1
-rw-r--r--arch/arm/configs/shark_defconfig1
-rw-r--r--arch/arm/configs/simpad_defconfig1
-rw-r--r--arch/arm/configs/smdk2410_defconfig1
-rw-r--r--arch/arm/configs/spitz_defconfig1
-rw-r--r--arch/arm/configs/versatile_defconfig1
-rw-r--r--arch/arm/kernel/Makefile6
-rw-r--r--arch/arm/kernel/apm.c20
-rw-r--r--arch/arm/kernel/armksyms.c22
-rw-r--r--arch/arm/kernel/asm-offsets.c9
-rw-r--r--arch/arm/kernel/calls.S59
-rw-r--r--arch/arm/kernel/dma-isa.c22
-rw-r--r--arch/arm/kernel/dma.c73
-rw-r--r--arch/arm/kernel/ecard.c21
-rw-r--r--arch/arm/kernel/entry-armv.S31
-rw-r--r--arch/arm/kernel/entry-common.S146
-rw-r--r--arch/arm/kernel/entry-header.S1
-rw-r--r--arch/arm/kernel/fiq.c4
-rw-r--r--arch/arm/kernel/head.S9
-rw-r--r--arch/arm/kernel/irq.c17
-rw-r--r--arch/arm/kernel/process.c16
-rw-r--r--arch/arm/kernel/ptrace.c52
-rw-r--r--arch/arm/kernel/semaphore.c17
-rw-r--r--arch/arm/kernel/setup.c17
-rw-r--r--arch/arm/kernel/signal.c29
-rw-r--r--arch/arm/kernel/signal.h2
-rw-r--r--arch/arm/kernel/smp.c4
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c339
-rw-r--r--arch/arm/kernel/time.c3
-rw-r--r--arch/arm/kernel/traps.c7
-rw-r--r--arch/arm/kernel/vmlinux.lds.S12
-rw-r--r--arch/arm/lib/ashldi3.S1
-rw-r--r--arch/arm/lib/ashrdi3.S1
-rw-r--r--arch/arm/lib/csumpartialcopy.S6
-rw-r--r--arch/arm/lib/csumpartialcopygeneric.S6
-rw-r--r--arch/arm/lib/csumpartialcopyuser.S8
-rw-r--r--arch/arm/lib/lib1funcs.S27
-rw-r--r--arch/arm/lib/lshrdi3.S1
-rw-r--r--arch/arm/lib/muldi3.S1
-rw-r--r--arch/arm/lib/ucmpdi2.S14
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c1
-rw-r--r--arch/arm/mach-aaec2000/clock.c28
-rw-r--r--arch/arm/mach-aaec2000/core.c2
-rw-r--r--arch/arm/mach-aaec2000/core.h2
-rw-r--r--arch/arm/mach-at91rm9200/Kconfig54
-rw-r--r--arch/arm/mach-at91rm9200/Makefile27
-rw-r--r--arch/arm/mach-at91rm9200/Makefile.boot9
-rw-r--r--arch/arm/mach-at91rm9200/board-csb337.c142
-rw-r--r--arch/arm/mach-at91rm9200/board-csb637.c115
-rw-r--r--arch/arm/mach-at91rm9200/board-dk.c137
-rw-r--r--arch/arm/mach-at91rm9200/board-ek.c130
-rw-r--r--arch/arm/mach-at91rm9200/clock.c620
-rw-r--r--arch/arm/mach-at91rm9200/common.c115
-rw-r--r--arch/arm/mach-at91rm9200/devices.c291
-rw-r--r--arch/arm/mach-at91rm9200/generic.h18
-rw-r--r--arch/arm/mach-at91rm9200/gpio.c302
-rw-r--r--arch/arm/mach-at91rm9200/irq.c170
-rw-r--r--arch/arm/mach-at91rm9200/time.c127
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c1
-rw-r--r--arch/arm/mach-clps711x/cdb89712.c1
-rw-r--r--arch/arm/mach-clps711x/ceiva.c1
-rw-r--r--arch/arm/mach-clps711x/clep7312.c1
-rw-r--r--arch/arm/mach-clps711x/dma.c27
-rw-r--r--arch/arm/mach-clps711x/edb7211-arch.c1
-rw-r--r--arch/arm/mach-clps711x/fortunet.c1
-rw-r--r--arch/arm/mach-clps711x/p720t.c1
-rw-r--r--arch/arm/mach-clps7500/core.c1
-rw-r--r--arch/arm/mach-ebsa110/core.c1
-rw-r--r--arch/arm/mach-epxa10db/Kconfig23
-rw-r--r--arch/arm/mach-epxa10db/Makefile11
-rw-r--r--arch/arm/mach-epxa10db/Makefile.boot2
-rw-r--r--arch/arm/mach-epxa10db/arch.c74
-rw-r--r--arch/arm/mach-epxa10db/irq.c82
-rw-r--r--arch/arm/mach-epxa10db/mm.c71
-rw-r--r--arch/arm/mach-epxa10db/time.c78
-rw-r--r--arch/arm/mach-footbridge/cats-hw.c1
-rw-r--r--arch/arm/mach-footbridge/co285.c1
-rw-r--r--arch/arm/mach-footbridge/dma.c1
-rw-r--r--arch/arm/mach-footbridge/ebsa285.c1
-rw-r--r--arch/arm/mach-footbridge/netwinder-hw.c2
-rw-r--r--arch/arm/mach-footbridge/personal.c1
-rw-r--r--arch/arm/mach-h720x/h7201-eval.c1
-rw-r--r--arch/arm/mach-h720x/h7202-eval.c1
-rw-r--r--arch/arm/mach-imx/mx1ads.c56
-rw-r--r--arch/arm/mach-integrator/clock.c28
-rw-r--r--arch/arm/mach-integrator/core.c2
-rw-r--r--arch/arm/mach-integrator/dma.c35
-rw-r--r--arch/arm/mach-integrator/impd1.c4
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c5
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c7
-rw-r--r--arch/arm/mach-integrator/lm.c36
-rw-r--r--arch/arm/mach-integrator/time.c7
-rw-r--r--arch/arm/mach-iop3xx/iop321-setup.c2
-rw-r--r--arch/arm/mach-iop3xx/iop331-setup.c96
-rw-r--r--arch/arm/mach-ixp2000/core.c10
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2400.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2800.c1
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x01.c2
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig8
-rw-r--r--arch/arm/mach-ixp4xx/Makefile1
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c23
-rw-r--r--arch/arm/mach-ixp4xx/common.c21
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c12
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c16
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c5
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c17
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c3
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-pci.c71
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-power.c67
-rw-r--r--arch/arm/mach-ixp4xx/nas100d-setup.c134
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-pci.c8
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-power.c3
-rw-r--r--arch/arm/mach-ixp4xx/nslu2-setup.c1
-rw-r--r--arch/arm/mach-l7200/core.c1
-rw-r--r--arch/arm/mach-lh7a40x/arch-kev7a400.c1
-rw-r--r--arch/arm/mach-lh7a40x/arch-lpd7a40x.c2
-rw-r--r--arch/arm/mach-omap1/board-generic.c1
-rw-r--r--arch/arm/mach-omap1/board-h2.c1
-rw-r--r--arch/arm/mach-omap1/board-h3.c1
-rw-r--r--arch/arm/mach-omap1/board-innovator.c1
-rw-r--r--arch/arm/mach-omap1/board-netstar.c1
-rw-r--r--arch/arm/mach-omap1/board-osk.c1
-rw-r--r--arch/arm/mach-omap1/board-palmte.c3
-rw-r--r--arch/arm/mach-omap1/board-perseus2.c3
-rw-r--r--arch/arm/mach-omap1/board-voiceblue.c1
-rw-r--r--arch/arm/mach-omap1/clock.c46
-rw-r--r--arch/arm/mach-omap1/clock.h168
-rw-r--r--arch/arm/mach-omap1/serial.c11
-rw-r--r--arch/arm/mach-omap2/board-generic.c1
-rw-r--r--arch/arm/mach-omap2/board-h4.c1
-rw-r--r--arch/arm/mach-omap2/clock.c34
-rw-r--r--arch/arm/mach-omap2/clock.h12
-rw-r--r--arch/arm/mach-omap2/serial.c14
-rw-r--r--arch/arm/mach-omap2/timer-gp.c5
-rw-r--r--arch/arm/mach-pxa/Kconfig2
-rw-r--r--arch/arm/mach-pxa/akita-ioexp.c7
-rw-r--r--arch/arm/mach-pxa/corgi.c10
-rw-r--r--arch/arm/mach-pxa/corgi_pm.c44
-rw-r--r--arch/arm/mach-pxa/idp.c1
-rw-r--r--arch/arm/mach-pxa/lubbock.c1
-rw-r--r--arch/arm/mach-pxa/mainstone.c28
-rw-r--r--arch/arm/mach-pxa/poodle.c8
-rw-r--r--arch/arm/mach-pxa/pxa27x.c6
-rw-r--r--arch/arm/mach-pxa/sharpsl.h101
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c824
-rw-r--r--arch/arm/mach-pxa/spitz.c45
-rw-r--r--arch/arm/mach-pxa/spitz_pm.c46
-rw-r--r--arch/arm/mach-pxa/ssp.c17
-rw-r--r--arch/arm/mach-pxa/tosa.c1
-rw-r--r--arch/arm/mach-realview/Kconfig1
-rw-r--r--arch/arm/mach-realview/clock.c28
-rw-r--r--arch/arm/mach-realview/core.c4
-rw-r--r--arch/arm/mach-realview/core.h3
-rw-r--r--arch/arm/mach-realview/localtimer.c1
-rw-r--r--arch/arm/mach-realview/realview_eb.c3
-rw-r--r--arch/arm/mach-rpc/dma.c19
-rw-r--r--arch/arm/mach-rpc/riscpc.c1
-rw-r--r--arch/arm/mach-s3c2410/clock.c235
-rw-r--r--arch/arm/mach-s3c2410/clock.h1
-rw-r--r--arch/arm/mach-s3c2410/mach-anubis.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-nexcoder.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-rx3715.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2440.c1
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c1
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c3
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c2
-rw-r--r--arch/arm/mach-s3c2410/time.c3
-rw-r--r--arch/arm/mach-s3c2410/usb-simtec.c6
-rw-r--r--arch/arm/mach-sa1100/assabet.c1
-rw-r--r--arch/arm/mach-sa1100/badge4.c1
-rw-r--r--arch/arm/mach-sa1100/cerf.c1
-rw-r--r--arch/arm/mach-sa1100/collie.c1
-rw-r--r--arch/arm/mach-sa1100/h3600.c3
-rw-r--r--arch/arm/mach-sa1100/hackkit.c1
-rw-r--r--arch/arm/mach-sa1100/jornada720.c1
-rw-r--r--arch/arm/mach-sa1100/lart.c1
-rw-r--r--arch/arm/mach-sa1100/pleb.c1
-rw-r--r--arch/arm/mach-sa1100/pm.c18
-rw-r--r--arch/arm/mach-sa1100/shannon.c1
-rw-r--r--arch/arm/mach-sa1100/simpad.c1
-rw-r--r--arch/arm/mach-shark/core.c1
-rw-r--r--arch/arm/mach-versatile/Kconfig1
-rw-r--r--arch/arm/mach-versatile/clock.c28
-rw-r--r--arch/arm/mach-versatile/core.c62
-rw-r--r--arch/arm/mach-versatile/core.h2
-rw-r--r--arch/arm/mach-versatile/versatile_ab.c3
-rw-r--r--arch/arm/mach-versatile/versatile_pb.c3
-rw-r--r--arch/arm/mm/Kconfig8
-rw-r--r--arch/arm/mm/consistent.c54
-rw-r--r--arch/arm/mm/discontig.c4
-rw-r--r--arch/arm/mm/ioremap.c49
-rw-r--r--arch/arm/mm/mm-armv.c1
-rw-r--r--arch/arm/nwfpe/fpa11.h4
-rw-r--r--arch/arm/plat-omap/Kconfig3
-rw-r--r--arch/arm/plat-omap/clock.c58
-rw-r--r--arch/arm/plat-omap/common.c2
-rw-r--r--arch/arm/plat-omap/cpu-omap.c3
-rw-r--r--arch/arm/plat-omap/dma.c2
-rw-r--r--arch/arm/plat-omap/gpio.c8
-rw-r--r--arch/arm/plat-omap/mcbsp.c15
-rw-r--r--arch/arm/plat-omap/ocpi.c6
-rw-r--r--arch/arm/tools/mach-types30
-rw-r--r--arch/arm26/Kconfig4
-rw-r--r--arch/arm26/kernel/armksyms.c1
-rw-r--r--arch/arm26/kernel/asm-offsets.c7
-rw-r--r--arch/arm26/kernel/irq.c3
-rw-r--r--arch/arm26/kernel/process.c5
-rw-r--r--arch/arm26/kernel/ptrace.c29
-rw-r--r--arch/arm26/kernel/traps.c8
-rw-r--r--arch/arm26/nwfpe/fpmodule.c3
-rw-r--r--arch/cris/Kconfig4
-rw-r--r--arch/cris/arch-v10/drivers/ds1302.c1
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c1
-rw-r--r--arch/cris/arch-v10/kernel/kgdb.c6
-rw-r--r--arch/cris/arch-v10/kernel/process.c4
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c4
-rw-r--r--arch/cris/arch-v32/kernel/process.c6
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c6
-rw-r--r--arch/cris/arch-v32/kernel/smp.c4
-rw-r--r--arch/cris/arch-v32/mm/tlb.c4
-rw-r--r--arch/cris/kernel/crisksyms.c2
-rw-r--r--arch/cris/kernel/process.c28
-rw-r--r--arch/frv/Kconfig27
-rw-r--r--arch/frv/Kconfig.debug22
-rw-r--r--arch/frv/Makefile6
-rw-r--r--arch/frv/boot/Makefile4
-rw-r--r--arch/frv/kernel/Makefile2
-rw-r--r--arch/frv/kernel/entry.S2
-rw-r--r--arch/frv/kernel/frv_ksyms.c27
-rw-r--r--arch/frv/kernel/futex.c242
-rw-r--r--arch/frv/kernel/irq.c17
-rw-r--r--arch/frv/kernel/module.c80
-rw-r--r--arch/frv/kernel/pm.c2
-rw-r--r--arch/frv/kernel/process.c26
-rw-r--r--arch/frv/kernel/setup.c2
-rw-r--r--arch/frv/kernel/signal.c239
-rw-r--r--arch/frv/kernel/time.c3
-rw-r--r--arch/frv/kernel/traps.c3
-rw-r--r--arch/frv/kernel/uaccess.c7
-rw-r--r--arch/frv/kernel/vmlinux.lds.S1
-rw-r--r--arch/frv/lib/Makefile2
-rw-r--r--arch/frv/lib/__ucmpdi2.S45
-rw-r--r--arch/frv/lib/atomic-ops.S92
-rw-r--r--arch/frv/lib/checksum.c31
-rw-r--r--arch/frv/mb93090-mb00/Makefile2
-rw-r--r--arch/frv/mb93090-mb00/pci-dma-nommu.c8
-rw-r--r--arch/frv/mb93090-mb00/pci-dma.c10
-rw-r--r--arch/frv/mb93090-mb00/pci-frv.c8
-rw-r--r--arch/frv/mb93090-mb00/pci-iomap.c29
-rw-r--r--arch/frv/mb93090-mb00/pci-irq.c4
-rw-r--r--arch/frv/mm/cache-page.c5
-rw-r--r--arch/frv/mm/extable.c34
-rw-r--r--arch/frv/mm/highmem.c8
-rw-r--r--arch/h8300/Kconfig4
-rw-r--r--arch/h8300/kernel/gpio.c4
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c7
-rw-r--r--arch/h8300/kernel/process.c30
-rw-r--r--arch/h8300/mm/memory.c13
-rw-r--r--arch/h8300/platform/h8300h/ptrace_h8300h.c12
-rw-r--r--arch/h8300/platform/h8s/ints.c4
-rw-r--r--arch/h8300/platform/h8s/ints_h8s.c4
-rw-r--r--arch/i386/Kconfig86
-rw-r--r--arch/i386/Kconfig.cpu14
-rw-r--r--arch/i386/Kconfig.debug10
-rw-r--r--arch/i386/Makefile16
-rw-r--r--arch/i386/Makefile.cpu10
-rw-r--r--arch/i386/boot/Makefile4
-rw-r--r--arch/i386/boot/compressed/misc.c2
-rw-r--r--arch/i386/boot/install.sh14
-rw-r--r--arch/i386/boot/video.S5
-rw-r--r--arch/i386/crypto/aes-i586-asm.S40
-rw-r--r--arch/i386/crypto/aes.c56
-rw-r--r--arch/i386/defconfig2
-rw-r--r--arch/i386/kernel/Makefile7
-rw-r--r--arch/i386/kernel/acpi/boot.c2
-rw-r--r--arch/i386/kernel/apic.c131
-rw-r--r--arch/i386/kernel/apm.c102
-rw-r--r--arch/i386/kernel/cpu/amd.c14
-rw-r--r--arch/i386/kernel/cpu/changelog63
-rw-r--r--arch/i386/kernel/cpu/common.c27
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c5
-rw-r--r--arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c3
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c54
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h9
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c5
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h25
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-ich.c47
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c32
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.h1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c1
-rw-r--r--arch/i386/kernel/cpu/cyrix.c27
-rw-r--r--arch/i386/kernel/cpu/intel.c5
-rw-r--r--arch/i386/kernel/cpu/mtrr/changelog229
-rw-r--r--arch/i386/kernel/cpu/mtrr/if.c1
-rw-r--r--arch/i386/kernel/cpu/proc.c33
-rw-r--r--arch/i386/kernel/cpuid.c3
-rw-r--r--arch/i386/kernel/crash.c50
-rw-r--r--arch/i386/kernel/crash_dump.c74
-rw-r--r--arch/i386/kernel/dmi_scan.c16
-rw-r--r--arch/i386/kernel/entry.S3
-rw-r--r--arch/i386/kernel/head.S27
-rw-r--r--arch/i386/kernel/i386_ksyms.c3
-rw-r--r--arch/i386/kernel/init_task.c2
-rw-r--r--arch/i386/kernel/io_apic.c6
-rw-r--r--arch/i386/kernel/ioport.c1
-rw-r--r--arch/i386/kernel/irq.c2
-rw-r--r--arch/i386/kernel/kprobes.c23
-rw-r--r--arch/i386/kernel/microcode.c5
-rw-r--r--arch/i386/kernel/mpparse.c26
-rw-r--r--arch/i386/kernel/msr.c3
-rw-r--r--arch/i386/kernel/process.c43
-rw-r--r--arch/i386/kernel/ptrace.c9
-rw-r--r--arch/i386/kernel/quirks.c9
-rw-r--r--arch/i386/kernel/reboot.c13
-rw-r--r--arch/i386/kernel/scx200.c2
-rw-r--r--arch/i386/kernel/setup.c14
-rw-r--r--arch/i386/kernel/signal.c109
-rw-r--r--arch/i386/kernel/smpboot.c10
-rw-r--r--arch/i386/kernel/syscall_table.S17
-rw-r--r--arch/i386/kernel/time.c6
-rw-r--r--arch/i386/kernel/time_hpet.c2
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c2
-rw-r--r--arch/i386/kernel/traps.c143
-rw-r--r--arch/i386/kernel/vm86.c5
-rw-r--r--arch/i386/mm/init.c26
-rw-r--r--arch/i386/mm/pageattr.c31
-rw-r--r--arch/i386/pci/acpi.c2
-rw-r--r--arch/i386/pci/fixup.c23
-rw-r--r--arch/i386/pci/irq.c44
-rw-r--r--arch/ia64/Makefile7
-rw-r--r--arch/ia64/configs/gensparse_defconfig3
-rw-r--r--arch/ia64/configs/sn2_defconfig2
-rw-r--r--arch/ia64/configs/tiger_defconfig1
-rw-r--r--arch/ia64/configs/zx1_defconfig1
-rw-r--r--arch/ia64/defconfig1
-rw-r--r--arch/ia64/hp/sim/simserial.c12
-rw-r--r--arch/ia64/ia32/Makefile4
-rw-r--r--arch/ia64/ia32/elfcore32.h3
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/ia32/ia32_ioctl.c45
-rw-r--r--arch/ia64/ia32/ia32_signal.c4
-rw-r--r--arch/ia64/ia32/ia32_support.c4
-rw-r--r--arch/ia64/ia32/sys_ia32.c57
-rw-r--r--arch/ia64/kernel/efi.c160
-rw-r--r--arch/ia64/kernel/entry.S1
-rw-r--r--arch/ia64/kernel/fsys.S1
-rw-r--r--arch/ia64/kernel/head.S2
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c2
-rw-r--r--arch/ia64/kernel/jprobes.S27
-rw-r--r--arch/ia64/kernel/kprobes.c68
-rw-r--r--arch/ia64/kernel/mca.c4
-rw-r--r--arch/ia64/kernel/mca_asm.S2
-rw-r--r--arch/ia64/kernel/perfmon.c35
-rw-r--r--arch/ia64/kernel/perfmon_montecito.h269
-rw-r--r--arch/ia64/kernel/process.c12
-rw-r--r--arch/ia64/kernel/ptrace.c33
-rw-r--r--arch/ia64/kernel/salinfo.c171
-rw-r--r--arch/ia64/kernel/setup.c26
-rw-r--r--arch/ia64/kernel/signal.c10
-rw-r--r--arch/ia64/kernel/sys_ia64.c2
-rw-r--r--arch/ia64/kernel/traps.c26
-rw-r--r--arch/ia64/mm/init.c36
-rw-r--r--arch/ia64/mm/tlb.c2
-rw-r--r--arch/ia64/oprofile/backtrace.c2
-rw-r--r--arch/ia64/pci/pci.c21
-rw-r--r--arch/ia64/sn/include/xtalk/hubdev.h26
-rw-r--r--arch/ia64/sn/include/xtalk/xbow.h206
-rw-r--r--arch/ia64/sn/include/xtalk/xwidgetdev.h46
-rw-r--r--arch/ia64/sn/kernel/bte_error.c58
-rw-r--r--arch/ia64/sn/kernel/huberror.c9
-rw-r--r--arch/ia64/sn/kernel/io_init.c104
-rw-r--r--arch/ia64/sn/kernel/irq.c10
-rw-r--r--arch/ia64/sn/kernel/tiocx.c37
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c24
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c189
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c10
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_ate.c16
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c76
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c32
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_reg.c28
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c36
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c68
-rw-r--r--arch/m32r/Kconfig30
-rw-r--r--arch/m32r/boot/compressed/head.S5
-rw-r--r--arch/m32r/boot/setup.S24
-rw-r--r--arch/m32r/kernel/Makefile1
-rw-r--r--arch/m32r/kernel/entry.S19
-rw-r--r--arch/m32r/kernel/io_m32104ut.c298
-rw-r--r--arch/m32r/kernel/io_m32700ut.c24
-rw-r--r--arch/m32r/kernel/io_mappi.c2
-rw-r--r--arch/m32r/kernel/io_mappi2.c24
-rw-r--r--arch/m32r/kernel/io_mappi3.c51
-rw-r--r--arch/m32r/kernel/io_oaks32r.c2
-rw-r--r--arch/m32r/kernel/io_opsput.c6
-rw-r--r--arch/m32r/kernel/m32r_ksyms.c3
-rw-r--r--arch/m32r/kernel/process.c17
-rw-r--r--arch/m32r/kernel/ptrace.c47
-rw-r--r--arch/m32r/kernel/setup.c7
-rw-r--r--arch/m32r/kernel/setup_m32104ut.c156
-rw-r--r--arch/m32r/kernel/setup_m32700ut.c8
-rw-r--r--arch/m32r/kernel/setup_mappi.c6
-rw-r--r--arch/m32r/kernel/setup_mappi2.c6
-rw-r--r--arch/m32r/kernel/setup_mappi3.c6
-rw-r--r--arch/m32r/kernel/setup_oaks32r.c6
-rw-r--r--arch/m32r/kernel/setup_opsput.c8
-rw-r--r--arch/m32r/kernel/setup_usrv.c6
-rw-r--r--arch/m32r/kernel/smpboot.c2
-rw-r--r--arch/m32r/kernel/time.c4
-rw-r--r--arch/m32r/m32104ut/defconfig.m32104ut (renamed from arch/arm/configs/epxa10db_defconfig)511
-rw-r--r--arch/m32r/mm/cache.c36
-rw-r--r--arch/m68k/Kconfig4
-rw-r--r--arch/m68k/amiga/amiints.c46
-rw-r--r--arch/m68k/amiga/amisound.c2
-rw-r--r--arch/m68k/amiga/cia.c8
-rw-r--r--arch/m68k/amiga/config.c27
-rw-r--r--arch/m68k/apollo/config.c3
-rw-r--r--arch/m68k/atari/config.c9
-rw-r--r--arch/m68k/bvme6000/rtc.c7
-rw-r--r--arch/m68k/hp300/config.c3
-rw-r--r--arch/m68k/kernel/asm-offsets.c2
-rw-r--r--arch/m68k/kernel/head.S2
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c2
-rw-r--r--arch/m68k/kernel/process.c7
-rw-r--r--arch/m68k/kernel/setup.c19
-rw-r--r--arch/m68k/kernel/signal.c62
-rw-r--r--arch/m68k/kernel/sys_m68k.c40
-rw-r--r--arch/m68k/kernel/traps.c38
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds1
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds3
-rw-r--r--arch/m68k/lib/checksum.c2
-rw-r--r--arch/m68k/mac/config.c3
-rw-r--r--arch/m68k/mac/iop.c4
-rw-r--r--arch/m68k/mac/misc.c326
-rw-r--r--arch/m68k/math-emu/multi_arith.h2
-rw-r--r--arch/m68k/mm/kmap.c12
-rw-r--r--arch/m68k/mvme16x/rtc.c7
-rw-r--r--arch/m68k/q40/config.c5
-rw-r--r--arch/m68k/sun3/config.c3
-rw-r--r--arch/m68k/sun3x/config.c4
-rw-r--r--arch/m68knommu/Kconfig4
-rw-r--r--arch/m68knommu/Makefile1
-rw-r--r--arch/m68knommu/kernel/m68k_ksyms.c4
-rw-r--r--arch/m68knommu/kernel/process.c51
-rw-r--r--arch/m68knommu/kernel/ptrace.c2
-rw-r--r--arch/m68knommu/kernel/setup.c2
-rw-r--r--arch/m68knommu/kernel/signal.c8
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S2
-rw-r--r--arch/mips/Kconfig10
-rw-r--r--arch/mips/Makefile1
-rw-r--r--arch/mips/configs/bigsur_defconfig1
-rw-r--r--arch/mips/configs/cobalt_defconfig1
-rw-r--r--arch/mips/configs/ddb5476_defconfig1
-rw-r--r--arch/mips/configs/ddb5477_defconfig1
-rw-r--r--arch/mips/configs/ev64120_defconfig1
-rw-r--r--arch/mips/configs/ev96100_defconfig1
-rw-r--r--arch/mips/configs/ip22_defconfig1
-rw-r--r--arch/mips/configs/ip27_defconfig1
-rw-r--r--arch/mips/configs/ip32_defconfig1
-rw-r--r--arch/mips/configs/it8172_defconfig1
-rw-r--r--arch/mips/configs/ivr_defconfig1
-rw-r--r--arch/mips/configs/jaguar-atx_defconfig1
-rw-r--r--arch/mips/configs/lasat200_defconfig1
-rw-r--r--arch/mips/configs/malta_defconfig10
-rw-r--r--arch/mips/configs/ocelot_3_defconfig1
-rw-r--r--arch/mips/configs/ocelot_c_defconfig1
-rw-r--r--arch/mips/configs/ocelot_defconfig1
-rw-r--r--arch/mips/configs/ocelot_g_defconfig1
-rw-r--r--arch/mips/configs/pnx8550-v2pci_defconfig1
-rw-r--r--arch/mips/configs/rbhma4500_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig1
-rw-r--r--arch/mips/configs/yosemite_defconfig1
-rw-r--r--arch/mips/defconfig1
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/cpu-probe.c39
-rw-r--r--arch/mips/kernel/ioctl32.c50
-rw-r--r--arch/mips/kernel/linux32.c4
-rw-r--r--arch/mips/kernel/process.c12
-rw-r--r--arch/mips/kernel/ptrace.c22
-rw-r--r--arch/mips/kernel/ptrace32.c44
-rw-r--r--arch/mips/kernel/reset.c6
-rw-r--r--arch/mips/kernel/signal32.c2
-rw-r--r--arch/mips/kernel/smp_mt.c7
-rw-r--r--arch/mips/kernel/syscall.c3
-rw-r--r--arch/mips/kernel/sysirix.c1
-rw-r--r--arch/mips/kernel/time.c32
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/kernel/vpe.c11
-rw-r--r--arch/mips/lib/iomap.c2
-rw-r--r--arch/mips/math-emu/dp_fint.c2
-rw-r--r--arch/mips/math-emu/dp_flong.c2
-rw-r--r--arch/mips/math-emu/sp_fint.c2
-rw-r--r--arch/mips/math-emu/sp_flong.c2
-rw-r--r--arch/mips/mips-boards/generic/time.c33
-rw-r--r--arch/mips/mm/c-r4k.c4
-rw-r--r--arch/mips/oprofile/common.c3
-rw-r--r--arch/mips/oprofile/op_impl.h4
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c22
-rw-r--r--arch/mips/pci/fixup-capcella.c2
-rw-r--r--arch/mips/pci/fixup-mpc30x.c2
-rw-r--r--arch/mips/pci/fixup-tb0219.c2
-rw-r--r--arch/mips/pci/fixup-tb0226.c2
-rw-r--r--arch/mips/pci/fixup-tb0287.c2
-rw-r--r--arch/mips/pci/ops-vr41xx.c2
-rw-r--r--arch/mips/pci/pci-vr41xx.c2
-rw-r--r--arch/mips/pci/pci-vr41xx.h2
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c4
-rw-r--r--arch/mips/sgi-ip27/ip27-berr.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-smp.c4
-rw-r--r--arch/mips/sibyte/cfe/smp.c2
-rw-r--r--arch/mips/vr41xx/casio-e55/setup.c2
-rw-r--r--arch/mips/vr41xx/common/bcu.c4
-rw-r--r--arch/mips/vr41xx/common/cmu.c4
-rw-r--r--arch/mips/vr41xx/common/icu.c4
-rw-r--r--arch/mips/vr41xx/common/init.c2
-rw-r--r--arch/mips/vr41xx/common/int-handler.S2
-rw-r--r--arch/mips/vr41xx/common/irq.c2
-rw-r--r--arch/mips/vr41xx/common/pmu.c2
-rw-r--r--arch/mips/vr41xx/common/type.c2
-rw-r--r--arch/mips/vr41xx/common/vrc4173.c4
-rw-r--r--arch/mips/vr41xx/ibm-workpad/setup.c2
-rw-r--r--arch/parisc/Kconfig3
-rw-r--r--arch/parisc/configs/a500_defconfig1
-rw-r--r--arch/parisc/configs/c3000_defconfig1
-rw-r--r--arch/parisc/hpux/sys_hpux.c1
-rw-r--r--arch/parisc/kernel/Makefile3
-rw-r--r--arch/parisc/kernel/cache.c20
-rw-r--r--arch/parisc/kernel/drivers.c17
-rw-r--r--arch/parisc/kernel/firmware.c2
-rw-r--r--arch/parisc/kernel/hardware.c1
-rw-r--r--arch/parisc/kernel/inventory.c6
-rw-r--r--arch/parisc/kernel/ioctl32.c60
-rw-r--r--arch/parisc/kernel/pci-dma.c6
-rw-r--r--arch/parisc/kernel/pdc_chassis.c13
-rw-r--r--arch/parisc/kernel/perf.c7
-rw-r--r--arch/parisc/kernel/process.c8
-rw-r--r--arch/parisc/kernel/processor.c8
-rw-r--r--arch/parisc/kernel/setup.c10
-rw-r--r--arch/parisc/kernel/smp.c18
-rw-r--r--arch/parisc/kernel/time.c4
-rw-r--r--arch/parisc/kernel/topology.c3
-rw-r--r--arch/parisc/kernel/unaligned.c2
-rw-r--r--arch/parisc/kernel/unwind.c2
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S15
-rw-r--r--arch/parisc/mm/init.c29
-rw-r--r--arch/parisc/mm/ioremap.c100
-rw-r--r--arch/powerpc/Kconfig92
-rw-r--r--arch/powerpc/Kconfig.debug42
-rw-r--r--arch/powerpc/Makefile15
-rw-r--r--arch/powerpc/boot/.gitignore20
-rw-r--r--arch/powerpc/boot/Makefile98
-rw-r--r--arch/powerpc/boot/crt0.S21
-rw-r--r--arch/powerpc/boot/dummy.c4
-rw-r--r--arch/powerpc/boot/hack-coff.c84
-rw-r--r--arch/powerpc/boot/main.c46
-rw-r--r--arch/powerpc/boot/prom.c538
-rw-r--r--arch/powerpc/boot/prom.h36
-rw-r--r--arch/powerpc/boot/rs6000.h243
-rw-r--r--arch/powerpc/boot/stdio.c325
-rw-r--r--arch/powerpc/boot/stdio.h6
-rw-r--r--arch/powerpc/boot/string.S20
-rw-r--r--arch/powerpc/boot/zImage.coff.lds46
-rw-r--r--arch/powerpc/configs/cell_defconfig1
-rw-r--r--arch/powerpc/configs/g5_defconfig1
-rw-r--r--arch/powerpc/configs/iseries_defconfig1
-rw-r--r--arch/powerpc/configs/maple_defconfig1
-rw-r--r--arch/powerpc/configs/mpc834x_sys_defconfig911
-rw-r--r--arch/powerpc/configs/pmac32_defconfig1744
-rw-r--r--arch/powerpc/configs/ppc64_defconfig5
-rw-r--r--arch/powerpc/configs/pseries_defconfig1
-rw-r--r--arch/powerpc/kernel/Makefile32
-rw-r--r--arch/powerpc/kernel/asm-offsets.c8
-rw-r--r--arch/powerpc/kernel/btext.c136
-rw-r--r--arch/powerpc/kernel/cpu_setup_power4.S4
-rw-r--r--arch/powerpc/kernel/cputable.c278
-rw-r--r--arch/powerpc/kernel/crash.c197
-rw-r--r--arch/powerpc/kernel/crash_dump.c111
-rw-r--r--arch/powerpc/kernel/dma_64.c9
-rw-r--r--arch/powerpc/kernel/entry_32.S173
-rw-r--r--arch/powerpc/kernel/entry_64.S229
-rw-r--r--arch/powerpc/kernel/fpu.S10
-rw-r--r--arch/powerpc/kernel/head_32.S56
-rw-r--r--arch/powerpc/kernel/head_64.S137
-rw-r--r--arch/powerpc/kernel/ibmebus.c396
-rw-r--r--arch/powerpc/kernel/idle_power4.S8
-rw-r--r--arch/powerpc/kernel/ioctl32.c45
-rw-r--r--arch/powerpc/kernel/irq.c77
-rw-r--r--arch/powerpc/kernel/kprobes.c27
-rw-r--r--arch/powerpc/kernel/legacy_serial.c557
-rw-r--r--arch/powerpc/kernel/lparcfg.c13
-rw-r--r--arch/powerpc/kernel/lparmap.c12
-rw-r--r--arch/powerpc/kernel/machine_kexec.c61
-rw-r--r--arch/powerpc/kernel/machine_kexec_32.c65
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c43
-rw-r--r--arch/powerpc/kernel/misc_32.S117
-rw-r--r--arch/powerpc/kernel/misc_64.S10
-rw-r--r--arch/powerpc/kernel/nvram_64.c106
-rw-r--r--arch/powerpc/kernel/of_device.c4
-rw-r--r--arch/powerpc/kernel/paca.c47
-rw-r--r--arch/powerpc/kernel/pci_32.c1897
-rw-r--r--arch/powerpc/kernel/pci_64.c97
-rw-r--r--arch/powerpc/kernel/pmc.c5
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c9
-rw-r--r--arch/powerpc/kernel/process.c22
-rw-r--r--arch/powerpc/kernel/prom.c577
-rw-r--r--arch/powerpc/kernel/prom_init.c69
-rw-r--r--arch/powerpc/kernel/prom_parse.c548
-rw-r--r--arch/powerpc/kernel/ptrace-common.h4
-rw-r--r--arch/powerpc/kernel/ptrace32.c28
-rw-r--r--arch/powerpc/kernel/rtas.c111
-rw-r--r--arch/powerpc/kernel/rtas_pci.c51
-rw-r--r--arch/powerpc/kernel/setup-common.c138
-rw-r--r--arch/powerpc/kernel/setup_32.c34
-rw-r--r--arch/powerpc/kernel/setup_64.c267
-rw-r--r--arch/powerpc/kernel/signal_32.c149
-rw-r--r--arch/powerpc/kernel/signal_64.c93
-rw-r--r--arch/powerpc/kernel/smp.c35
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c56
-rw-r--r--arch/powerpc/kernel/syscalls.c28
-rw-r--r--arch/powerpc/kernel/systbl.S24
-rw-r--r--arch/powerpc/kernel/time.c6
-rw-r--r--arch/powerpc/kernel/traps.c25
-rw-r--r--arch/powerpc/kernel/udbg.c52
-rw-r--r--arch/powerpc/kernel/udbg_16550.c71
-rw-r--r--arch/powerpc/kernel/vdso32/.gitignore1
-rw-r--r--arch/powerpc/kernel/vdso64/.gitignore1
-rw-r--r--arch/powerpc/kernel/vio.c10
-rw-r--r--arch/powerpc/lib/locks.c8
-rw-r--r--arch/powerpc/mm/fault.c7
-rw-r--r--arch/powerpc/mm/hash_utils_64.c9
-rw-r--r--arch/powerpc/mm/hugetlbpage.c42
-rw-r--r--arch/powerpc/mm/imalloc.c2
-rw-r--r--arch/powerpc/mm/init_32.c5
-rw-r--r--arch/powerpc/mm/mem.c13
-rw-r--r--arch/powerpc/mm/numa.c139
-rw-r--r--arch/powerpc/mm/pgtable_64.c2
-rw-r--r--arch/powerpc/mm/slb.c16
-rw-r--r--arch/powerpc/mm/slb_low.S6
-rw-r--r--arch/powerpc/mm/stab.c16
-rw-r--r--arch/powerpc/mm/tlb_64.c2
-rw-r--r--arch/powerpc/oprofile/Makefile1
-rw-r--r--arch/powerpc/oprofile/common.c83
-rw-r--r--arch/powerpc/oprofile/op_model_7450.c206
-rw-r--r--arch/powerpc/oprofile/op_model_power4.c4
-rw-r--r--arch/powerpc/oprofile/op_model_rs64.c3
-rw-r--r--arch/powerpc/platforms/83xx/Kconfig27
-rw-r--r--arch/powerpc/platforms/83xx/Makefile4
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.c243
-rw-r--r--arch/powerpc/platforms/83xx/mpc834x_sys.h23
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h14
-rw-r--r--arch/powerpc/platforms/83xx/pci.c99
-rw-r--r--arch/powerpc/platforms/Makefile1
-rw-r--r--arch/powerpc/platforms/cell/Kconfig13
-rw-r--r--arch/powerpc/platforms/cell/Makefile8
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c42
-rw-r--r--arch/powerpc/platforms/cell/interrupt.h1
-rw-r--r--arch/powerpc/platforms/cell/iommu.c225
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c229
-rw-r--r--arch/powerpc/platforms/cell/pervasive.h62
-rw-r--r--arch/powerpc/platforms/cell/setup.c95
-rw-r--r--arch/powerpc/platforms/cell/smp.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c711
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1.c133
-rw-r--r--arch/powerpc/platforms/cell/spu_syscalls.c88
-rw-r--r--arch/powerpc/platforms/cell/spufs/Makefile54
-rw-r--r--arch/powerpc/platforms/cell/spufs/backing_ops.c308
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c167
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c794
-rw-r--r--arch/powerpc/platforms/cell/spufs/hw_ops.c255
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c486
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c131
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c461
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_restore.c336
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_restore_crt0.S116
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped231
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_save.c195
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_save_crt0.S102
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped191
-rw-r--r--arch/powerpc/platforms/cell/spufs/spu_utils.h160
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h163
-rw-r--r--arch/powerpc/platforms/cell/spufs/switch.c2204
-rw-r--r--arch/powerpc/platforms/cell/spufs/syscalls.c103
-rw-r--r--arch/powerpc/platforms/chrp/pci.c27
-rw-r--r--arch/powerpc/platforms/chrp/setup.c23
-rw-r--r--arch/powerpc/platforms/chrp/time.c7
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig18
-rw-r--r--arch/powerpc/platforms/iseries/Makefile4
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c2
-rw-r--r--arch/powerpc/platforms/iseries/iommu.h35
-rw-r--r--arch/powerpc/platforms/iseries/irq.c346
-rw-r--r--arch/powerpc/platforms/iseries/irq.h1
-rw-r--r--arch/powerpc/platforms/iseries/lpardata.c12
-rw-r--r--arch/powerpc/platforms/iseries/lpevents.c12
-rw-r--r--arch/powerpc/platforms/iseries/mf.c16
-rw-r--r--arch/powerpc/platforms/iseries/misc.S3
-rw-r--r--arch/powerpc/platforms/iseries/pci.c1
-rw-r--r--arch/powerpc/platforms/iseries/setup.c55
-rw-r--r--arch/powerpc/platforms/iseries/smp.c2
-rw-r--r--arch/powerpc/platforms/iseries/vio.c2
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c12
-rw-r--r--arch/powerpc/platforms/maple/pci.c1
-rw-r--r--arch/powerpc/platforms/maple/setup.c110
-rw-r--r--arch/powerpc/platforms/maple/time.c23
-rw-r--r--arch/powerpc/platforms/powermac/Makefile7
-rw-r--r--arch/powerpc/platforms/powermac/bootx_init.c547
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c498
-rw-r--r--arch/powerpc/platforms/powermac/feature.c367
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c1414
-rw-r--r--arch/powerpc/platforms/powermac/nvram.c53
-rw-r--r--arch/powerpc/platforms/powermac/pci.c299
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_base.c405
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c989
-rw-r--r--arch/powerpc/platforms/powermac/pic.c474
-rw-r--r--arch/powerpc/platforms/powermac/pmac.h6
-rw-r--r--arch/powerpc/platforms/powermac/setup.c109
-rw-r--r--arch/powerpc/platforms/powermac/smp.c382
-rw-r--r--arch/powerpc/platforms/powermac/time.c15
-rw-r--r--arch/powerpc/platforms/powermac/udbg_adb.c221
-rw-r--r--arch/powerpc/platforms/powermac/udbg_scc.c (renamed from arch/powerpc/kernel/udbg_scc.c)68
-rw-r--r--arch/powerpc/platforms/pseries/Makefile4
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c516
-rw-r--r--arch/powerpc/platforms/pseries/eeh_cache.c316
-rw-r--r--arch/powerpc/platforms/pseries/eeh_driver.c376
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c39
-rw-r--r--arch/powerpc/platforms/pseries/hvcserver.c4
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c14
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c80
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c174
-rw-r--r--arch/powerpc/platforms/pseries/ras.c11
-rw-r--r--arch/powerpc/platforms/pseries/ras.h9
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c100
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c4
-rw-r--r--arch/powerpc/platforms/pseries/setup.c77
-rw-r--r--arch/powerpc/platforms/pseries/smp.c6
-rw-r--r--arch/powerpc/platforms/pseries/xics.c4
-rw-r--r--arch/powerpc/sysdev/Makefile4
-rw-r--r--arch/powerpc/sysdev/dart.h41
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c (renamed from arch/powerpc/sysdev/u3_iommu.c)174
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c317
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h8
-rw-r--r--arch/powerpc/sysdev/ipic.c (renamed from arch/ppc/syslib/ipic.c)0
-rw-r--r--arch/powerpc/sysdev/ipic.h (renamed from arch/ppc/syslib/ipic.h)0
-rw-r--r--arch/powerpc/sysdev/mpic.c247
-rw-r--r--arch/powerpc/xmon/Makefile8
-rw-r--r--arch/powerpc/xmon/start.c (renamed from arch/powerpc/xmon/start_64.c)0
-rw-r--r--arch/powerpc/xmon/start_32.c441
-rw-r--r--arch/powerpc/xmon/start_8xx.c44
-rw-r--r--arch/powerpc/xmon/xmon.c22
-rw-r--r--arch/ppc/4xx_io/serial_sicc.c2
-rw-r--r--arch/ppc/Kconfig80
-rw-r--r--arch/ppc/Makefile3
-rw-r--r--arch/ppc/amiga/amiints.c40
-rw-r--r--arch/ppc/amiga/cia.c8
-rw-r--r--arch/ppc/amiga/config.c24
-rw-r--r--arch/ppc/boot/Makefile2
-rw-r--r--arch/ppc/boot/common/util.S6
-rw-r--r--arch/ppc/boot/images/Makefile2
-rw-r--r--arch/ppc/boot/openfirmware/Makefile96
-rw-r--r--arch/ppc/boot/openfirmware/coffmain.c101
-rw-r--r--arch/ppc/boot/openfirmware/newworldmain.c94
-rw-r--r--arch/ppc/boot/simple/Makefile2
-rw-r--r--arch/ppc/configs/TQM8540_defconfig973
-rw-r--r--arch/ppc/configs/TQM8541_defconfig986
-rw-r--r--arch/ppc/configs/TQM8555_defconfig983
-rw-r--r--arch/ppc/configs/TQM8560_defconfig992
-rw-r--r--arch/ppc/configs/bamboo_defconfig1
-rw-r--r--arch/ppc/configs/katana_defconfig1
-rw-r--r--arch/ppc/configs/mpc834x_sys_defconfig1
-rw-r--r--arch/ppc/configs/power3_defconfig1
-rw-r--r--arch/ppc/kernel/Makefile5
-rw-r--r--arch/ppc/kernel/asm-offsets.c2
-rw-r--r--arch/ppc/kernel/entry.S167
-rw-r--r--arch/ppc/kernel/head_8xx.S77
-rw-r--r--arch/ppc/kernel/idle.c4
-rw-r--r--arch/ppc/kernel/machine_kexec.c6
-rw-r--r--arch/ppc/kernel/misc.S78
-rw-r--r--arch/ppc/kernel/pci.c289
-rw-r--r--arch/ppc/kernel/ppc_htab.c1
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c15
-rw-r--r--arch/ppc/kernel/process.c851
-rw-r--r--arch/ppc/kernel/setup.c35
-rw-r--r--arch/ppc/kernel/smp.c4
-rw-r--r--arch/ppc/kernel/traps.c13
-rw-r--r--arch/ppc/mm/init.c29
-rw-r--r--arch/ppc/platforms/4xx/ibm440gx.c2
-rw-r--r--arch/ppc/platforms/4xx/ibm440sp.c1
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c10
-rw-r--r--arch/ppc/platforms/85xx/Kconfig28
-rw-r--r--arch/ppc/platforms/85xx/Makefile4
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c14
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c11
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c27
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c10
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c10
-rw-r--r--arch/ppc/platforms/85xx/tqm85xx.c415
-rw-r--r--arch/ppc/platforms/85xx/tqm85xx.h56
-rw-r--r--arch/ppc/platforms/Makefile11
-rw-r--r--arch/ppc/platforms/apus_setup.c30
-rw-r--r--arch/ppc/platforms/chrp_pci.c2
-rw-r--r--arch/ppc/platforms/chrp_setup.c74
-rw-r--r--arch/ppc/platforms/chrp_time.c64
-rw-r--r--arch/ppc/platforms/lite5200.c2
-rw-r--r--arch/ppc/platforms/mpc5200.c53
-rw-r--r--arch/ppc/platforms/pmac_backlight.c202
-rw-r--r--arch/ppc/platforms/pmac_cache.S359
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c735
-rw-r--r--arch/ppc/platforms/pmac_feature.c3023
-rw-r--r--arch/ppc/platforms/pmac_low_i2c.c511
-rw-r--r--arch/ppc/platforms/pmac_nvram.c584
-rw-r--r--arch/ppc/platforms/pmac_pci.c1124
-rw-r--r--arch/ppc/platforms/pmac_pic.c693
-rw-r--r--arch/ppc/platforms/pmac_pic.h11
-rw-r--r--arch/ppc/platforms/pmac_setup.c745
-rw-r--r--arch/ppc/platforms/pmac_sleep.S396
-rw-r--r--arch/ppc/platforms/pmac_smp.c692
-rw-r--r--arch/ppc/platforms/pmac_time.c291
-rw-r--r--arch/ppc/platforms/prep_setup.c2
-rw-r--r--arch/ppc/syslib/Makefile4
-rw-r--r--arch/ppc/syslib/m8xx_setup.c15
-rw-r--r--arch/ppc/syslib/m8xx_wdt.c92
-rw-r--r--arch/ppc/syslib/m8xx_wdt.h4
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c95
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c6
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c10
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c10
-rw-r--r--arch/ppc/syslib/ocp.c4
-rw-r--r--arch/ppc/syslib/prom.c21
-rw-r--r--arch/ppc/xmon/start.c161
-rw-r--r--arch/ppc/xmon/xmon.c15
-rw-r--r--arch/s390/Kconfig37
-rw-r--r--arch/s390/Makefile6
-rw-r--r--arch/s390/appldata/appldata_base.c8
-rw-r--r--arch/s390/appldata/appldata_os.c14
-rw-r--r--arch/s390/crypto/Makefile8
-rw-r--r--arch/s390/crypto/aes_s390.c276
-rw-r--r--arch/s390/crypto/crypt_s390.h (renamed from arch/s390/crypto/crypt_z990.h)267
-rw-r--r--arch/s390/crypto/crypt_s390_query.c129
-rw-r--r--arch/s390/crypto/crypt_z990_query.c111
-rw-r--r--arch/s390/crypto/des_s390.c466
-rw-r--r--arch/s390/crypto/des_z990.c284
-rw-r--r--arch/s390/crypto/sha1_s390.c (renamed from arch/s390/crypto/sha1_z990.c)32
-rw-r--r--arch/s390/crypto/sha256_s390.c166
-rw-r--r--arch/s390/defconfig65
-rw-r--r--arch/s390/kernel/Makefile18
-rw-r--r--arch/s390/kernel/binfmt_elf32.c2
-rw-r--r--arch/s390/kernel/compat_ioctl.c81
-rw-r--r--arch/s390/kernel/compat_linux.c35
-rw-r--r--arch/s390/kernel/compat_signal.c2
-rw-r--r--arch/s390/kernel/compat_wrapper.S2
-rw-r--r--arch/s390/kernel/cpcmd.c16
-rw-r--r--arch/s390/kernel/crash.c2
-rw-r--r--arch/s390/kernel/entry64.S18
-rw-r--r--arch/s390/kernel/head.S4
-rw-r--r--arch/s390/kernel/machine_kexec.c2
-rw-r--r--arch/s390/kernel/module.c12
-rw-r--r--arch/s390/kernel/process.c59
-rw-r--r--arch/s390/kernel/ptrace.c79
-rw-r--r--arch/s390/kernel/reipl_diag.c2
-rw-r--r--arch/s390/kernel/s390_ksyms.c1
-rw-r--r--arch/s390/kernel/setup.c25
-rw-r--r--arch/s390/kernel/signal.c8
-rw-r--r--arch/s390/kernel/smp.c16
-rw-r--r--arch/s390/kernel/sys_s390.c12
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/kernel/traps.c16
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
-rw-r--r--arch/s390/kernel/vtime.c27
-rw-r--r--arch/s390/lib/Makefile4
-rw-r--r--arch/s390/lib/spinlock.c9
-rw-r--r--arch/s390/mm/extmem.c2
-rw-r--r--arch/s390/mm/fault.c18
-rw-r--r--arch/s390/mm/init.c8
-rw-r--r--arch/s390/mm/mmap.c2
-rw-r--r--arch/s390/oprofile/Makefile2
-rw-r--r--arch/s390/oprofile/backtrace.c79
-rw-r--r--arch/s390/oprofile/init.c4
-rw-r--r--arch/sh/Kconfig541
-rw-r--r--arch/sh/Kconfig.debug2
-rw-r--r--arch/sh/Makefile60
-rw-r--r--arch/sh/boards/hp6xx/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp620/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp620/mach.c52
-rw-r--r--arch/sh/boards/hp6xx/hp620/setup.c45
-rw-r--r--arch/sh/boards/hp6xx/hp680/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp690/Makefile6
-rw-r--r--arch/sh/boards/hp6xx/hp690/mach.c48
-rw-r--r--arch/sh/boards/hp6xx/mach.c (renamed from arch/sh/boards/hp6xx/hp680/mach.c)15
-rw-r--r--arch/sh/boards/hp6xx/setup.c (renamed from arch/sh/boards/hp6xx/hp680/setup.c)18
-rw-r--r--arch/sh/boards/overdrive/Makefile2
-rw-r--r--arch/sh/boards/overdrive/setup.c6
-rw-r--r--arch/sh/boards/overdrive/time.c119
-rw-r--r--arch/sh/configs/hp6xx_defconfig (renamed from arch/sh/configs/hp680_defconfig)333
-rw-r--r--arch/sh/drivers/dma/dma-api.c51
-rw-r--r--arch/sh/drivers/dma/dma-g2.c3
-rw-r--r--arch/sh/drivers/dma/dma-isa.c20
-rw-r--r--arch/sh/drivers/dma/dma-pvr2.c3
-rw-r--r--arch/sh/drivers/dma/dma-sh.c134
-rw-r--r--arch/sh/drivers/dma/dma-sh.h44
-rw-r--r--arch/sh/drivers/dma/dma-sysfs.c31
-rw-r--r--arch/sh/kernel/Makefile4
-rw-r--r--arch/sh/kernel/cpu/Makefile9
-rw-r--r--arch/sh/kernel/cpu/bus.c36
-rw-r--r--arch/sh/kernel/cpu/clock.c287
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile7
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c (renamed from arch/sh/kernel/cpu/irq_imask.c)16
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c284
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c (renamed from arch/sh/kernel/cpu/irq_ipr.c)217
-rw-r--r--arch/sh/kernel/cpu/irq/pint.c169
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile7
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh3.c89
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7300.c78
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7705.c84
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7709.c96
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile11
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c179
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4.c80
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh73180.c81
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh7770.c73
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh7780.c126
-rw-r--r--arch/sh/kernel/cpu/sh4/irq_intc2.c222
-rw-r--r--arch/sh/kernel/io.c41
-rw-r--r--arch/sh/kernel/io_generic.c192
-rw-r--r--arch/sh/kernel/irq.c64
-rw-r--r--arch/sh/kernel/machine_kexec.c112
-rw-r--r--arch/sh/kernel/process.c76
-rw-r--r--arch/sh/kernel/ptrace.c14
-rw-r--r--arch/sh/kernel/relocate_kernel.S102
-rw-r--r--arch/sh/kernel/sh_ksyms.c2
-rw-r--r--arch/sh/kernel/smp.c2
-rw-r--r--arch/sh/kernel/time.c518
-rw-r--r--arch/sh/kernel/timers/Makefile8
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c229
-rw-r--r--arch/sh/kernel/timers/timer.c50
-rw-r--r--arch/sh/mm/Kconfig233
-rw-r--r--arch/sh/mm/ioremap.c99
-rw-r--r--arch/sh/tools/mach-types5
-rw-r--r--arch/sh64/Kconfig4
-rw-r--r--arch/sh64/kernel/process.c24
-rw-r--r--arch/sh64/kernel/sh_ksyms.c2
-rw-r--r--arch/sh64/kernel/time.c7
-rw-r--r--arch/sh64/lib/dbg.c2
-rw-r--r--arch/sparc/Kconfig4
-rw-r--r--arch/sparc/kernel/process.c12
-rw-r--r--arch/sparc/kernel/ptrace.c39
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c2
-rw-r--r--arch/sparc/kernel/sun4d_smp.c2
-rw-r--r--arch/sparc/kernel/sun4m_smp.c2
-rw-r--r--arch/sparc/kernel/sys_sunos.c1
-rw-r--r--arch/sparc/kernel/traps.c4
-rw-r--r--arch/sparc/mm/iommu.c13
-rw-r--r--arch/sparc64/Kconfig7
-rw-r--r--arch/sparc64/defconfig2077
-rw-r--r--arch/sparc64/kernel/Makefile4
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c2
-rw-r--r--arch/sparc64/kernel/ebus.c15
-rw-r--r--arch/sparc64/kernel/entry.S7
-rw-r--r--arch/sparc64/kernel/ioctl32.c39
-rw-r--r--arch/sparc64/kernel/kprobes.c18
-rw-r--r--arch/sparc64/kernel/power.c4
-rw-r--r--arch/sparc64/kernel/process.c14
-rw-r--r--arch/sparc64/kernel/ptrace.c80
-rw-r--r--arch/sparc64/kernel/setup.c4
-rw-r--r--arch/sparc64/kernel/smp.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c41
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c1
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/sparc64/kernel/time.c22
-rw-r--r--arch/sparc64/kernel/traps.c4
-rw-r--r--arch/sparc64/prom/console.c8
-rw-r--r--arch/sparc64/solaris/fs.c1
-rw-r--r--arch/um/Kconfig41
-rw-r--r--arch/um/Kconfig.i3866
-rw-r--r--arch/um/Makefile28
-rw-r--r--arch/um/drivers/chan_kern.c275
-rw-r--r--arch/um/drivers/daemon_kern.c4
-rw-r--r--arch/um/drivers/daemon_user.c6
-rw-r--r--arch/um/drivers/fd.c1
-rw-r--r--arch/um/drivers/line.c298
-rw-r--r--arch/um/drivers/mconsole_kern.c232
-rw-r--r--arch/um/drivers/mconsole_user.c12
-rw-r--r--arch/um/drivers/net_kern.c29
-rw-r--r--arch/um/drivers/ssl.c47
-rw-r--r--arch/um/drivers/stdio_console.c33
-rw-r--r--arch/um/drivers/ubd_kern.c96
-rw-r--r--arch/um/include/chan_kern.h25
-rw-r--r--arch/um/include/choose-mode.h3
-rw-r--r--arch/um/include/irq_user.h13
-rw-r--r--arch/um/include/kern.h13
-rw-r--r--arch/um/include/kern_util.h23
-rw-r--r--arch/um/include/line.h37
-rw-r--r--arch/um/include/longjmp.h19
-rw-r--r--arch/um/include/mconsole.h8
-rw-r--r--arch/um/include/mode_kern.h15
-rw-r--r--arch/um/include/os.h91
-rw-r--r--arch/um/include/signal_user.h28
-rw-r--r--arch/um/include/skas/mm_id.h (renamed from arch/um/kernel/skas/include/mm_id.h)0
-rw-r--r--arch/um/include/skas/mmu-skas.h24
-rw-r--r--arch/um/include/skas/mode-skas.h19
-rw-r--r--arch/um/include/skas/mode_kern_skas.h (renamed from arch/um/kernel/skas/include/mode_kern-skas.h)12
-rw-r--r--arch/um/include/skas/proc_mm.h (renamed from arch/um/kernel/skas/include/proc_mm.h)17
-rw-r--r--arch/um/include/skas/skas.h26
-rw-r--r--arch/um/include/skas/stub-data.h (renamed from arch/um/kernel/skas/include/stub-data.h)0
-rw-r--r--arch/um/include/skas/uaccess-skas.h (renamed from arch/um/kernel/skas/include/uaccess-skas.h)11
-rw-r--r--arch/um/include/sysdep-i386/checksum.h4
-rw-r--r--arch/um/include/sysdep-i386/kernel-offsets.h (renamed from arch/um/sys-i386/kernel-offsets.c)5
-rw-r--r--arch/um/include/sysdep-x86_64/kernel-offsets.h (renamed from arch/um/sys-x86_64/kernel-offsets.c)2
-rw-r--r--arch/um/include/time_user.h19
-rw-r--r--arch/um/include/tt/debug.h (renamed from arch/um/kernel/tt/include/debug.h)2
-rw-r--r--arch/um/include/tt/mmu-tt.h12
-rw-r--r--arch/um/include/tt/mode-tt.h23
-rw-r--r--arch/um/include/tt/mode_kern_tt.h41
-rw-r--r--arch/um/include/tt/tt.h (renamed from arch/um/kernel/tt/include/tt.h)12
-rw-r--r--arch/um/include/tt/uaccess-tt.h (renamed from arch/um/kernel/tt/include/uaccess-tt.h)11
-rw-r--r--arch/um/include/user.h1
-rw-r--r--arch/um/include/user_util.h29
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/asm-offsets.c2
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/irq_user.c49
-rw-r--r--arch/um/kernel/process_kern.c29
-rw-r--r--arch/um/kernel/reboot.c2
-rw-r--r--arch/um/kernel/sigio_user.c85
-rw-r--r--arch/um/kernel/signal_kern.c92
-rw-r--r--arch/um/kernel/signal_user.c157
-rw-r--r--arch/um/kernel/skas/Makefile8
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h35
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h33
-rw-r--r--arch/um/kernel/skas/include/skas.h50
-rw-r--r--arch/um/kernel/skas/mmu.c8
-rw-r--r--arch/um/kernel/skas/process.c16
-rw-r--r--arch/um/kernel/skas/process_kern.c40
-rw-r--r--arch/um/kernel/skas/uaccess.c2
-rw-r--r--arch/um/kernel/syscall.c4
-rw-r--r--arch/um/kernel/time.c9
-rw-r--r--arch/um/kernel/time_kern.c132
-rw-r--r--arch/um/kernel/trap_kern.c25
-rw-r--r--arch/um/kernel/trap_user.c98
-rw-r--r--arch/um/kernel/tt/exec_kern.c4
-rw-r--r--arch/um/kernel/tt/gdb.c1
-rw-r--r--arch/um/kernel/tt/include/mmu-tt.h23
-rw-r--r--arch/um/kernel/tt/process_kern.c10
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c1
-rw-r--r--arch/um/kernel/tt/tracer.c1
-rw-r--r--arch/um/kernel/tt/trap_user.c21
-rw-r--r--arch/um/kernel/um_arch.c15
-rw-r--r--arch/um/kernel/umid.c323
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/aio.c467
-rw-r--r--arch/um/os-Linux/helper.c4
-rw-r--r--arch/um/os-Linux/main.c14
-rw-r--r--arch/um/os-Linux/process.c31
-rw-r--r--arch/um/os-Linux/signal.c246
-rw-r--r--arch/um/os-Linux/skas/Makefile10
-rw-r--r--arch/um/os-Linux/skas/mem.c (renamed from arch/um/kernel/skas/mem_user.c)202
-rw-r--r--arch/um/os-Linux/skas/process.c566
-rw-r--r--arch/um/os-Linux/skas/trap.c (renamed from arch/um/kernel/skas/trap_user.c)49
-rw-r--r--arch/um/os-Linux/start_up.c2
-rw-r--r--arch/um/os-Linux/time.c131
-rw-r--r--arch/um/os-Linux/trap.c41
-rw-r--r--arch/um/os-Linux/tt.c64
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/umid.c335
-rw-r--r--arch/um/os-Linux/util.c (renamed from arch/um/kernel/user_util.c)69
-rw-r--r--arch/um/sys-i386/ldt.c26
-rw-r--r--arch/um/sys-i386/signal.c1
-rw-r--r--arch/v850/Kconfig3
-rw-r--r--arch/v850/kernel/process.c26
-rw-r--r--arch/v850/kernel/ptrace.c2
-rw-r--r--arch/v850/kernel/v850_ksyms.c2
-rw-r--r--arch/x86_64/Kconfig90
-rw-r--r--arch/x86_64/Kconfig.debug10
-rw-r--r--arch/x86_64/Makefile12
-rw-r--r--arch/x86_64/boot/.gitignore3
-rw-r--r--arch/x86_64/boot/Makefile2
-rw-r--r--arch/x86_64/boot/compressed/misc.c2
-rw-r--r--arch/x86_64/boot/compressed/miscsetup.h39
-rw-r--r--arch/x86_64/boot/install.sh40
-rw-r--r--arch/x86_64/boot/tools/.gitignore1
-rw-r--r--arch/x86_64/crypto/aes.c25
-rw-r--r--arch/x86_64/defconfig132
-rw-r--r--arch/x86_64/ia32/Makefile7
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c24
-rw-r--r--arch/x86_64/ia32/ia32_ioctl.c79
-rw-r--r--arch/x86_64/ia32/ia32_signal.c26
-rw-r--r--arch/x86_64/ia32/ia32entry.S56
-rw-r--r--arch/x86_64/ia32/mmap32.c78
-rw-r--r--arch/x86_64/ia32/ptrace32.c59
-rw-r--r--arch/x86_64/ia32/sys_ia32.c19
-rw-r--r--arch/x86_64/ia32/vsyscall-sigreturn.S1
-rw-r--r--arch/x86_64/ia32/vsyscall-syscall.S1
-rw-r--r--arch/x86_64/ia32/vsyscall-sysenter.S1
-rw-r--r--arch/x86_64/kernel/Makefile9
-rw-r--r--arch/x86_64/kernel/aperture.c3
-rw-r--r--arch/x86_64/kernel/apic.c198
-rw-r--r--arch/x86_64/kernel/asm-offsets.c4
-rw-r--r--arch/x86_64/kernel/crash.c156
-rw-r--r--arch/x86_64/kernel/crash_dump.c (renamed from kernel/crash_dump.c)32
-rw-r--r--arch/x86_64/kernel/e820.c21
-rw-r--r--arch/x86_64/kernel/early_printk.c4
-rw-r--r--arch/x86_64/kernel/entry.S42
-rw-r--r--arch/x86_64/kernel/genapic_cluster.c5
-rw-r--r--arch/x86_64/kernel/genapic_flat.c10
-rw-r--r--arch/x86_64/kernel/head.S122
-rw-r--r--arch/x86_64/kernel/head64.c5
-rw-r--r--arch/x86_64/kernel/i387.c2
-rw-r--r--arch/x86_64/kernel/i8259.c5
-rw-r--r--arch/x86_64/kernel/init_task.c2
-rw-r--r--arch/x86_64/kernel/io_apic.c167
-rw-r--r--arch/x86_64/kernel/ioport.c1
-rw-r--r--arch/x86_64/kernel/irq.c6
-rw-r--r--arch/x86_64/kernel/kprobes.c16
-rw-r--r--arch/x86_64/kernel/mce.c35
-rw-r--r--arch/x86_64/kernel/mce_amd.c6
-rw-r--r--arch/x86_64/kernel/mce_intel.c6
-rw-r--r--arch/x86_64/kernel/nmi.c8
-rw-r--r--arch/x86_64/kernel/pci-dma.c286
-rw-r--r--arch/x86_64/kernel/pci-gart.c413
-rw-r--r--arch/x86_64/kernel/pci-nommu.c145
-rw-r--r--arch/x86_64/kernel/pci-swiotlb.c42
-rw-r--r--arch/x86_64/kernel/process.c87
-rw-r--r--arch/x86_64/kernel/ptrace.c19
-rw-r--r--arch/x86_64/kernel/reboot.c10
-rw-r--r--arch/x86_64/kernel/setup.c116
-rw-r--r--arch/x86_64/kernel/setup64.c48
-rw-r--r--arch/x86_64/kernel/smp.c7
-rw-r--r--arch/x86_64/kernel/smpboot.c61
-rw-r--r--arch/x86_64/kernel/suspend.c2
-rw-r--r--arch/x86_64/kernel/syscall.c2
-rw-r--r--arch/x86_64/kernel/time.c121
-rw-r--r--arch/x86_64/kernel/trampoline.S11
-rw-r--r--arch/x86_64/kernel/traps.c164
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S4
-rw-r--r--arch/x86_64/kernel/vsmp.c45
-rw-r--r--arch/x86_64/kernel/vsyscall.c14
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c33
-rw-r--r--arch/x86_64/lib/copy_user.S244
-rw-r--r--arch/x86_64/lib/delay.c2
-rw-r--r--arch/x86_64/lib/usercopy.c12
-rw-r--r--arch/x86_64/mm/Makefile2
-rw-r--r--arch/x86_64/mm/fault.c54
-rw-r--r--arch/x86_64/mm/init.c206
-rw-r--r--arch/x86_64/mm/mmap.c30
-rw-r--r--arch/x86_64/mm/numa.c75
-rw-r--r--arch/x86_64/mm/pageattr.c9
-rw-r--r--arch/x86_64/mm/srat.c67
-rw-r--r--arch/x86_64/pci/Makefile-BUS22
-rw-r--r--arch/xtensa/Kconfig4
-rw-r--r--arch/xtensa/kernel/process.c4
-rw-r--r--arch/xtensa/kernel/ptrace.c12
-rw-r--r--arch/xtensa/kernel/time.c2
-rw-r--r--block/Kconfig2
-rw-r--r--block/as-iosched.c144
-rw-r--r--block/cfq-iosched.c16
-rw-r--r--block/deadline-iosched.c8
-rw-r--r--block/elevator.c100
-rw-r--r--block/genhd.c154
-rw-r--r--block/ioctl.c24
-rw-r--r--block/ll_rw_blk.c699
-rw-r--r--block/scsi_ioctl.c18
-rw-r--r--crypto/Kconfig45
-rw-r--r--crypto/aes.c63
-rw-r--r--crypto/anubis.c39
-rw-r--r--crypto/api.c54
-rw-r--r--crypto/blowfish.c3
-rw-r--r--crypto/cast5.c47
-rw-r--r--crypto/cast6.c83
-rw-r--r--crypto/cipher.c5
-rw-r--r--crypto/crc32c.c1
-rw-r--r--crypto/des.c3
-rw-r--r--crypto/internal.h6
-rw-r--r--crypto/khazad.c46
-rw-r--r--crypto/md4.c1
-rw-r--r--crypto/md5.c1
-rw-r--r--crypto/michael_mic.c40
-rw-r--r--crypto/proc.c6
-rw-r--r--crypto/serpent.c2
-rw-r--r--crypto/sha1.c66
-rw-r--r--crypto/sha256.c31
-rw-r--r--crypto/sha512.c54
-rw-r--r--crypto/tcrypt.c4
-rw-r--r--crypto/tcrypt.h64
-rw-r--r--crypto/tea.c98
-rw-r--r--crypto/tgr192.c64
-rw-r--r--crypto/twofish.c13
-rw-r--r--crypto/wp512.c32
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/acorn/block/mfmhd.c36
-rw-r--r--drivers/acorn/char/i2c.c1
-rw-r--r--drivers/acorn/char/pcf8583.c5
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/container.c8
-rw-r--r--drivers/acpi/ec.c2
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/pci_irq.c7
-rw-r--r--drivers/acpi/processor_core.c8
-rw-r--r--drivers/acpi/processor_idle.c15
-rw-r--r--drivers/acpi/scan.c41
-rw-r--r--drivers/acpi/tables.c4
-rw-r--r--drivers/amba/Makefile2
-rw-r--r--drivers/amba/bus.c (renamed from arch/arm/common/amba.c)9
-rw-r--r--drivers/atm/nicstar.c5
-rw-r--r--drivers/atm/zatm.c12
-rw-r--r--drivers/base/Kconfig4
-rw-r--r--drivers/base/bus.c41
-rw-r--r--drivers/base/class.c66
-rw-r--r--drivers/base/core.c46
-rw-r--r--drivers/base/cpu.c34
-rw-r--r--drivers/base/dd.c27
-rw-r--r--drivers/base/driver.c5
-rw-r--r--drivers/base/firmware_class.c48
-rw-r--r--drivers/base/memory.c21
-rw-r--r--drivers/base/platform.c68
-rw-r--r--drivers/base/power/runtime.c3
-rw-r--r--drivers/base/power/shutdown.c9
-rw-r--r--drivers/block/DAC960.c41
-rw-r--r--drivers/block/Kconfig5
-rw-r--r--drivers/block/acsi.c26
-rw-r--r--drivers/block/amiflop.c55
-rw-r--r--drivers/block/aoe/aoeblk.c26
-rw-r--r--drivers/block/ataflop.c29
-rw-r--r--drivers/block/cciss.c198
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/cpqarray.c42
-rw-r--r--drivers/block/floppy.c47
-rw-r--r--drivers/block/loop.c56
-rw-r--r--drivers/block/nbd.c125
-rw-r--r--drivers/block/paride/Kconfig5
-rw-r--r--drivers/block/paride/pd.c34
-rw-r--r--drivers/block/paride/pf.c50
-rw-r--r--drivers/block/pktcdvd.c16
-rw-r--r--drivers/block/ps2esdi.c26
-rw-r--r--drivers/block/rd.c4
-rw-r--r--drivers/block/swim3.c38
-rw-r--r--drivers/block/sx8.c51
-rw-r--r--drivers/block/ub.c439
-rw-r--r--drivers/block/umem.c43
-rw-r--r--drivers/block/viodasd.c78
-rw-r--r--drivers/block/xd.c31
-rw-r--r--drivers/bluetooth/bcm203x.c1
-rw-r--r--drivers/bluetooth/bfusb.c1
-rw-r--r--drivers/bluetooth/bluecard_cs.c109
-rw-r--r--drivers/bluetooth/bpa10x.c1
-rw-r--r--drivers/bluetooth/bt3c_cs.c110
-rw-r--r--drivers/bluetooth/btuart_cs.c110
-rw-r--r--drivers/bluetooth/dtl1_cs.c111
-rw-r--r--drivers/bluetooth/hci_bcsp.c2
-rw-r--r--drivers/bluetooth/hci_ldisc.c16
-rw-r--r--drivers/bluetooth/hci_usb.c1
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/cdrom/cdu31a.c2
-rw-r--r--drivers/cdrom/cm206.c2
-rw-r--r--drivers/cdrom/viocd.c6
-rw-r--r--drivers/char/.gitignore2
-rw-r--r--drivers/char/Kconfig41
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/sworks-agp.c1
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/cs5535_gpio.c250
-rw-r--r--drivers/char/cyclades.c91
-rw-r--r--drivers/char/drm/Makefile4
-rw-r--r--drivers/char/drm/ati_pcigart.c23
-rw-r--r--drivers/char/drm/drm.h4
-rw-r--r--drivers/char/drm/drmP.h122
-rw-r--r--drivers/char/drm/drm_agpsupport.c133
-rw-r--r--drivers/char/drm/drm_bufs.c49
-rw-r--r--drivers/char/drm/drm_context.c2
-rw-r--r--drivers/char/drm/drm_core.h4
-rw-r--r--drivers/char/drm/drm_drv.c152
-rw-r--r--drivers/char/drm/drm_fops.c317
-rw-r--r--drivers/char/drm/drm_init.c53
-rw-r--r--drivers/char/drm/drm_ioc32.c1
-rw-r--r--drivers/char/drm/drm_ioctl.c27
-rw-r--r--drivers/char/drm/drm_lock.c1
-rw-r--r--drivers/char/drm/drm_memory.c8
-rw-r--r--drivers/char/drm/drm_memory_debug.h269
-rw-r--r--drivers/char/drm/drm_os_linux.h1
-rw-r--r--drivers/char/drm/drm_pciids.h12
-rw-r--r--drivers/char/drm/drm_proc.c16
-rw-r--r--drivers/char/drm/drm_stub.c63
-rw-r--r--drivers/char/drm/drm_sysfs.c68
-rw-r--r--drivers/char/drm/i810_dma.c49
-rw-r--r--drivers/char/drm/i810_drv.c60
-rw-r--r--drivers/char/drm/i810_drv.h10
-rw-r--r--drivers/char/drm/i830_dma.c47
-rw-r--r--drivers/char/drm/i830_drv.c57
-rw-r--r--drivers/char/drm/i830_drv.h8
-rw-r--r--drivers/char/drm/i915_dma.c52
-rw-r--r--drivers/char/drm/i915_drm.h6
-rw-r--r--drivers/char/drm/i915_drv.c66
-rw-r--r--drivers/char/drm/i915_drv.h44
-rw-r--r--drivers/char/drm/i915_ioc32.c1
-rw-r--r--drivers/char/drm/i915_irq.c48
-rw-r--r--drivers/char/drm/i915_mem.c5
-rw-r--r--drivers/char/drm/mga_dma.c158
-rw-r--r--drivers/char/drm/mga_drv.c58
-rw-r--r--drivers/char/drm/mga_drv.h14
-rw-r--r--drivers/char/drm/mga_ioc32.c1
-rw-r--r--drivers/char/drm/mga_state.c26
-rw-r--r--drivers/char/drm/r128_cce.c15
-rw-r--r--drivers/char/drm/r128_drm.h4
-rw-r--r--drivers/char/drm/r128_drv.c48
-rw-r--r--drivers/char/drm/r128_drv.h8
-rw-r--r--drivers/char/drm/r128_ioc32.c1
-rw-r--r--drivers/char/drm/r128_irq.c4
-rw-r--r--drivers/char/drm/r128_state.c44
-rw-r--r--drivers/char/drm/r300_cmdbuf.c38
-rw-r--r--drivers/char/drm/r300_reg.h1
-rw-r--r--drivers/char/drm/radeon_cp.c106
-rw-r--r--drivers/char/drm/radeon_drm.h6
-rw-r--r--drivers/char/drm/radeon_drv.c62
-rw-r--r--drivers/char/drm/radeon_drv.h41
-rw-r--r--drivers/char/drm/radeon_ioc32.c1
-rw-r--r--drivers/char/drm/radeon_state.c246
-rw-r--r--drivers/char/drm/savage_bci.c81
-rw-r--r--drivers/char/drm/savage_drv.c50
-rw-r--r--drivers/char/drm/savage_drv.h29
-rw-r--r--drivers/char/drm/savage_state.c324
-rw-r--r--drivers/char/drm/sis_drm.h25
-rw-r--r--drivers/char/drm/sis_drv.c42
-rw-r--r--drivers/char/drm/sis_drv.h4
-rw-r--r--drivers/char/drm/sis_ds.h7
-rw-r--r--drivers/char/drm/sis_mm.c30
-rw-r--r--drivers/char/drm/tdfx_drv.c42
-rw-r--r--drivers/char/drm/tdfx_drv.h7
-rw-r--r--drivers/char/drm/via_dma.c38
-rw-r--r--drivers/char/drm/via_dmablit.c805
-rw-r--r--drivers/char/drm/via_dmablit.h140
-rw-r--r--drivers/char/drm/via_drm.h60
-rw-r--r--drivers/char/drm/via_drv.c63
-rw-r--r--drivers/char/drm/via_drv.h56
-rw-r--r--drivers/char/drm/via_ds.c9
-rw-r--r--drivers/char/drm/via_irq.c53
-rw-r--r--drivers/char/drm/via_map.c47
-rw-r--r--drivers/char/drm/via_mm.c20
-rw-r--r--drivers/char/drm/via_verifier.c6
-rw-r--r--drivers/char/drm/via_verifier.h4
-rw-r--r--drivers/char/drm/via_video.c7
-rw-r--r--drivers/char/dsp56k.c29
-rw-r--r--drivers/char/epca.c17
-rw-r--r--drivers/char/esp.c70
-rw-r--r--drivers/char/ftape/Kconfig12
-rw-r--r--drivers/char/generic_serial.c1
-rw-r--r--drivers/char/hangcheck-timer.c2
-rw-r--r--drivers/char/hvc_console.c6
-rw-r--r--drivers/char/hvcs.c10
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/hw_random.c71
-rw-r--r--drivers/char/ip2/i2lib.c2
-rw-r--r--drivers/char/ip2/i2pack.h2
-rw-r--r--drivers/char/ip2main.c26
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c6
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c3
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c10
-rw-r--r--drivers/char/isicom.c2084
-rw-r--r--drivers/char/istallion.c45
-rw-r--r--drivers/char/mem.c54
-rw-r--r--drivers/char/mmtimer.c90
-rw-r--r--drivers/char/moxa.c77
-rw-r--r--drivers/char/mxser.c4
-rw-r--r--drivers/char/n_hdlc.c21
-rw-r--r--drivers/char/n_r3964.c10
-rw-r--r--drivers/char/n_tty.c66
-rw-r--r--drivers/char/nvram.c12
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c162
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c151
-rw-r--r--drivers/char/pcmcia/synclink_cs.c164
-rw-r--r--drivers/char/pty.c4
-rw-r--r--drivers/char/random.c12
-rw-r--r--drivers/char/rio/board.h83
-rw-r--r--drivers/char/rio/bootpkt.h11
-rw-r--r--drivers/char/rio/brates.h107
-rw-r--r--drivers/char/rio/chan.h33
-rw-r--r--drivers/char/rio/cirrus.h178
-rw-r--r--drivers/char/rio/cmd.h84
-rw-r--r--drivers/char/rio/cmdblk.h19
-rw-r--r--drivers/char/rio/cmdpkt.h213
-rw-r--r--drivers/char/rio/control.h7
-rw-r--r--drivers/char/rio/daemon.h162
-rw-r--r--drivers/char/rio/data.h40
-rw-r--r--drivers/char/rio/debug.h39
-rw-r--r--drivers/char/rio/defaults.h7
-rw-r--r--drivers/char/rio/eisa.h104
-rw-r--r--drivers/char/rio/enable.h50
-rw-r--r--drivers/char/rio/error.h3
-rw-r--r--drivers/char/rio/errors.h2
-rw-r--r--drivers/char/rio/formpkt.h154
-rw-r--r--drivers/char/rio/func.h51
-rw-r--r--drivers/char/rio/host.h93
-rw-r--r--drivers/char/rio/hosthw.h57
-rw-r--r--drivers/char/rio/link.h152
-rw-r--r--drivers/char/rio/linux_compat.h46
-rw-r--r--drivers/char/rio/list.h6
-rw-r--r--drivers/char/rio/lrt.h55
-rw-r--r--drivers/char/rio/ltt.h55
-rw-r--r--drivers/char/rio/lttwake.h53
-rw-r--r--drivers/char/rio/map.h27
-rw-r--r--drivers/char/rio/mca.h73
-rw-r--r--drivers/char/rio/mesg.h41
-rw-r--r--drivers/char/rio/param.h27
-rw-r--r--drivers/char/rio/parmmap.h79
-rw-r--r--drivers/char/rio/pci.h2
-rw-r--r--drivers/char/rio/phb.h285
-rw-r--r--drivers/char/rio/pkt.h72
-rw-r--r--drivers/char/rio/poll.h76
-rw-r--r--drivers/char/rio/port.h294
-rw-r--r--drivers/char/rio/proto.h244
-rw-r--r--drivers/char/rio/protsts.h2
-rw-r--r--drivers/char/rio/qbuf.h15
-rw-r--r--drivers/char/rio/rio.h15
-rw-r--r--drivers/char/rio/rio_linux.c1498
-rw-r--r--drivers/char/rio/rio_linux.h57
-rw-r--r--drivers/char/rio/rioboard.h204
-rw-r--r--drivers/char/rio/rioboot.c61
-rw-r--r--drivers/char/rio/riocmd.c900
-rw-r--r--drivers/char/rio/rioctrl.c3064
-rw-r--r--drivers/char/rio/riodrvr.h128
-rw-r--r--drivers/char/rio/rioinfo.h30
-rw-r--r--drivers/char/rio/rioinit.c1152
-rw-r--r--drivers/char/rio/riointr.c1510
-rw-r--r--drivers/char/rio/rioioctl.h18
-rw-r--r--drivers/char/rio/riolocks.h43
-rw-r--r--drivers/char/rio/rioparam.c578
-rw-r--r--drivers/char/rio/riopcicopy.c6
-rw-r--r--drivers/char/rio/rioroute.c1574
-rw-r--r--drivers/char/rio/riospace.h31
-rw-r--r--drivers/char/rio/riotable.c1021
-rw-r--r--drivers/char/rio/riotime.h63
-rw-r--r--drivers/char/rio/riotty.c1217
-rw-r--r--drivers/char/rio/riotypes.h71
-rw-r--r--drivers/char/rio/riowinif.h1335
-rw-r--r--drivers/char/rio/riscos.h63
-rw-r--r--drivers/char/rio/rom.h22
-rw-r--r--drivers/char/rio/route.h61
-rw-r--r--drivers/char/rio/rtahw.h75
-rw-r--r--drivers/char/rio/rup.h39
-rw-r--r--drivers/char/rio/rupstat.h51
-rw-r--r--drivers/char/rio/sam.h13
-rw-r--r--drivers/char/rio/selftest.h73
-rw-r--r--drivers/char/rio/space.h2
-rw-r--r--drivers/char/rio/sysmap.h63
-rw-r--r--drivers/char/rio/timeouts.h51
-rw-r--r--drivers/char/rio/top.h9
-rw-r--r--drivers/char/rio/typdef.h36
-rw-r--r--drivers/char/rio/unixrup.h21
-rw-r--r--drivers/char/riscom8.c48
-rw-r--r--drivers/char/rocket.c19
-rw-r--r--drivers/char/rtc.c14
-rw-r--r--drivers/char/s3c2410-rtc.c2
-rw-r--r--drivers/char/scc.h2
-rw-r--r--drivers/char/selection.c5
-rw-r--r--drivers/char/ser_a2232.c8
-rw-r--r--drivers/char/serial167.c38
-rw-r--r--drivers/char/sonypi.c381
-rw-r--r--drivers/char/specialix.c41
-rw-r--r--drivers/char/stallion.c193
-rw-r--r--drivers/char/sx.c19
-rw-r--r--drivers/char/synclink.c52
-rw-r--r--drivers/char/synclink_gt.c4491
-rw-r--r--drivers/char/synclinkmp.c38
-rw-r--r--drivers/char/sysrq.c19
-rw-r--r--drivers/char/tb0219.c4
-rw-r--r--drivers/char/tlclk.c108
-rw-r--r--drivers/char/tpm/Makefile3
-rw-r--r--drivers/char/tpm/tpm.c3
-rw-r--r--drivers/char/tpm/tpm.h15
-rw-r--r--drivers/char/tpm/tpm_bios.c540
-rw-r--r--drivers/char/tty_io.c266
-rw-r--r--drivers/char/viocons.c45
-rw-r--r--drivers/char/vme_scc.c20
-rw-r--r--drivers/char/vr41xx_giu.c8
-rw-r--r--drivers/char/vr41xx_rtc.c9
-rw-r--r--drivers/char/vt.c33
-rw-r--r--drivers/char/watchdog/Kconfig28
-rw-r--r--drivers/char/watchdog/Makefile2
-rw-r--r--drivers/char/watchdog/cpu5wdt.c9
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c4
-rw-r--r--drivers/char/watchdog/mpc83xx_wdt.c229
-rw-r--r--drivers/char/watchdog/mpc8xx_wdt.c20
-rw-r--r--drivers/char/watchdog/pcwd_usb.c1
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c4
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c12
-rw-r--r--drivers/char/watchdog/sbc_epx_c3.c216
-rw-r--r--drivers/char/watchdog/wdt977.c216
-rw-r--r--drivers/connector/cn_proc.c15
-rw-r--r--drivers/cpufreq/cpufreq.c31
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c10
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c10
-rw-r--r--drivers/crypto/padlock-aes.c26
-rw-r--r--drivers/crypto/padlock.h2
-rw-r--r--drivers/dio/dio-driver.c4
-rw-r--r--drivers/edac/Kconfig102
-rw-r--r--drivers/edac/Makefile18
-rw-r--r--drivers/edac/amd76x_edac.c356
-rw-r--r--drivers/edac/e752x_edac.c1071
-rw-r--r--drivers/edac/e7xxx_edac.c558
-rw-r--r--drivers/edac/edac_mc.c2209
-rw-r--r--drivers/edac/edac_mc.h448
-rw-r--r--drivers/edac/i82860_edac.c299
-rw-r--r--drivers/edac/i82875p_edac.c532
-rw-r--r--drivers/edac/r82600_edac.c407
-rw-r--r--drivers/firmware/dell_rbu.c26
-rw-r--r--drivers/firmware/efivars.c2
-rw-r--r--drivers/hwmon/Kconfig12
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/adm1021.c6
-rw-r--r--drivers/hwmon/adm1025.c10
-rw-r--r--drivers/hwmon/adm1026.c10
-rw-r--r--drivers/hwmon/adm1031.c6
-rw-r--r--drivers/hwmon/adm9240.c6
-rw-r--r--drivers/hwmon/asb100.c6
-rw-r--r--drivers/hwmon/atxp1.c6
-rw-r--r--drivers/hwmon/ds1621.c6
-rw-r--r--drivers/hwmon/fscher.c6
-rw-r--r--drivers/hwmon/fscpos.c6
-rw-r--r--drivers/hwmon/gl518sm.c6
-rw-r--r--drivers/hwmon/gl520sm.c6
-rw-r--r--drivers/hwmon/hwmon-vid.c69
-rw-r--r--drivers/hwmon/it87.c18
-rw-r--r--drivers/hwmon/lm63.c6
-rw-r--r--drivers/hwmon/lm75.c6
-rw-r--r--drivers/hwmon/lm77.c6
-rw-r--r--drivers/hwmon/lm78.c13
-rw-r--r--drivers/hwmon/lm80.c6
-rw-r--r--drivers/hwmon/lm83.c6
-rw-r--r--drivers/hwmon/lm85.c50
-rw-r--r--drivers/hwmon/lm87.c6
-rw-r--r--drivers/hwmon/lm90.c6
-rw-r--r--drivers/hwmon/lm92.c6
-rw-r--r--drivers/hwmon/max1619.c6
-rw-r--r--drivers/hwmon/pc87360.c7
-rw-r--r--drivers/hwmon/sis5595.c8
-rw-r--r--drivers/hwmon/smsc47b397.c8
-rw-r--r--drivers/hwmon/smsc47m1.c7
-rw-r--r--drivers/hwmon/via686a.c8
-rw-r--r--drivers/hwmon/vt8231.c862
-rw-r--r--drivers/hwmon/w83627ehf.c7
-rw-r--r--drivers/hwmon/w83627hf.c23
-rw-r--r--drivers/hwmon/w83781d.c13
-rw-r--r--drivers/hwmon/w83792d.c83
-rw-r--r--drivers/hwmon/w83l785ts.c6
-rw-r--r--drivers/i2c/busses/Kconfig24
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-i801.c6
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-isa.c10
-rw-r--r--drivers/i2c/busses/i2c-keywest.c751
-rw-r--r--drivers/i2c/busses/i2c-keywest.h108
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c33
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-parport.h12
-rw-r--r--drivers/i2c/busses/i2c-pmac-smu.c315
-rw-r--r--drivers/i2c/busses/i2c-powermac.c290
-rw-r--r--drivers/i2c/busses/i2c-pxa.c10
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c4
-rw-r--r--drivers/i2c/chips/ds1337.c43
-rw-r--r--drivers/i2c/chips/ds1374.c6
-rw-r--r--drivers/i2c/chips/eeprom.c6
-rw-r--r--drivers/i2c/chips/isp1301_omap.c6
-rw-r--r--drivers/i2c/chips/m41t00.c6
-rw-r--r--drivers/i2c/chips/max6875.c6
-rw-r--r--drivers/i2c/chips/pca9539.c6
-rw-r--r--drivers/i2c/chips/pcf8574.c6
-rw-r--r--drivers/i2c/chips/pcf8591.c6
-rw-r--r--drivers/i2c/chips/rtc8564.c43
-rw-r--r--drivers/i2c/chips/tps65010.c17
-rw-r--r--drivers/i2c/chips/x1205.c6
-rw-r--r--drivers/i2c/i2c-core.c90
-rw-r--r--drivers/i2c/i2c-dev.c63
-rw-r--r--drivers/ide/ide-cd.c35
-rw-r--r--drivers/ide/ide-disk.c174
-rw-r--r--drivers/ide/ide-floppy.c27
-rw-r--r--drivers/ide/ide-io.c20
-rw-r--r--drivers/ide/ide-probe.c4
-rw-r--r--drivers/ide/ide-tape.c19
-rw-r--r--drivers/ide/ide-taskfile.c2
-rw-r--r--drivers/ide/ide.c112
-rw-r--r--drivers/ide/legacy/hd.c24
-rw-r--r--drivers/ide/legacy/ide-cs.c132
-rw-r--r--drivers/ide/pci/pdc202xx_new.c2
-rw-r--r--drivers/ide/pci/serverworks.c2
-rw-r--r--drivers/ide/pci/via82cxxx.c2
-rw-r--r--drivers/ide/ppc/pmac.c6
-rw-r--r--drivers/ieee1394/.gitignore1
-rw-r--r--drivers/ieee1394/Kconfig23
-rw-r--r--drivers/ieee1394/Makefile2
-rw-r--r--drivers/ieee1394/amdtp.c1298
-rw-r--r--drivers/ieee1394/amdtp.h84
-rw-r--r--drivers/ieee1394/cmp.c311
-rw-r--r--drivers/ieee1394/cmp.h31
-rw-r--r--drivers/ieee1394/csr1212.c21
-rw-r--r--drivers/ieee1394/csr1212.h2
-rw-r--r--drivers/ieee1394/dma.c73
-rw-r--r--drivers/ieee1394/dv1394.c14
-rw-r--r--drivers/ieee1394/eth1394.c20
-rw-r--r--drivers/ieee1394/highlevel.c18
-rw-r--r--drivers/ieee1394/hosts.c30
-rw-r--r--drivers/ieee1394/hosts.h162
-rw-r--r--drivers/ieee1394/ieee1394-ioctl.h8
-rw-r--r--drivers/ieee1394/ieee1394.h19
-rw-r--r--drivers/ieee1394/ieee1394_core.c827
-rw-r--r--drivers/ieee1394/ieee1394_core.h100
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c389
-rw-r--r--drivers/ieee1394/iso.c102
-rw-r--r--drivers/ieee1394/nodemgr.c70
-rw-r--r--drivers/ieee1394/nodemgr.h18
-rw-r--r--drivers/ieee1394/ohci1394.c43
-rw-r--r--drivers/ieee1394/ohci1394.h4
-rw-r--r--drivers/ieee1394/pcilynx.c2
-rw-r--r--drivers/ieee1394/raw1394.c79
-rw-r--r--drivers/ieee1394/sbp2.c1040
-rw-r--r--drivers/ieee1394/sbp2.h70
-rw-r--r--drivers/ieee1394/video1394.c107
-rw-r--r--drivers/infiniband/core/cm.c49
-rw-r--r--drivers/infiniband/core/device.c23
-rw-r--r--drivers/infiniband/core/sysfs.c32
-rw-r--r--drivers/infiniband/core/ucm.c23
-rw-r--r--drivers/infiniband/core/user_mad.c4
-rw-r--r--drivers/infiniband/core/uverbs.h5
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c173
-rw-r--r--drivers/infiniband/core/uverbs_main.c8
-rw-r--r--drivers/infiniband/core/verbs.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_av.c10
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c19
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c23
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c32
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mcg.c54
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c132
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c267
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c31
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c14
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c107
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c10
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c24
-rw-r--r--drivers/input/evdev.c501
-rw-r--r--drivers/input/gameport/Kconfig7
-rw-r--r--drivers/input/gameport/gameport.c12
-rw-r--r--drivers/input/input.c77
-rw-r--r--drivers/input/joystick/amijoy.c4
-rw-r--r--drivers/input/joystick/grip_mp.c9
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c1
-rw-r--r--drivers/input/keyboard/Kconfig10
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atkbd.c2
-rw-r--r--drivers/input/keyboard/corgikbd.c6
-rw-r--r--drivers/input/keyboard/spitzkbd.c27
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c9
-rw-r--r--drivers/input/misc/m68kspkr.c102
-rw-r--r--drivers/input/misc/pcspkr.c86
-rw-r--r--drivers/input/misc/sparcspkr.c162
-rw-r--r--drivers/input/misc/wistron_btns.c139
-rw-r--r--drivers/input/mouse/Kconfig10
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/alps.c39
-rw-r--r--drivers/input/mouse/amimouse.c6
-rw-r--r--drivers/input/mouse/lifebook.c7
-rw-r--r--drivers/input/mouse/logips2pp.c4
-rw-r--r--drivers/input/mouse/maplemouse.c101
-rw-r--r--drivers/input/mouse/psmouse-base.c331
-rw-r--r--drivers/input/mouse/psmouse.h9
-rw-r--r--drivers/input/mouse/synaptics.c2
-rw-r--r--drivers/input/mousedev.c10
-rw-r--r--drivers/input/serio/ambakmi.c15
-rw-r--r--drivers/input/serio/ct82c710.c89
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h22
-rw-r--r--drivers/input/serio/i8042.c116
-rw-r--r--drivers/input/serio/maceps2.c68
-rw-r--r--drivers/input/serio/q40kbd.c89
-rw-r--r--drivers/input/serio/sa1111ps2.c1
-rw-r--r--drivers/input/serio/serio.c34
-rw-r--r--drivers/input/serio/serport.c13
-rw-r--r--drivers/input/touchscreen/Kconfig15
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ads7846.c625
-rw-r--r--drivers/isdn/act2000/act2000.h6
-rw-r--r--drivers/isdn/act2000/capi.h90
-rw-r--r--drivers/isdn/capi/capi.c3
-rw-r--r--drivers/isdn/capi/capifs.c8
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c145
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c3
-rw-r--r--drivers/isdn/hardware/eicon/os_bri.c1
-rw-r--r--drivers/isdn/hardware/eicon/os_pri.c1
-rw-r--r--drivers/isdn/hisax/Kconfig10
-rw-r--r--drivers/isdn/hisax/avm_pci.c2
-rw-r--r--drivers/isdn/hisax/avma1_cs.c150
-rw-r--r--drivers/isdn/hisax/diva.c2
-rw-r--r--drivers/isdn/hisax/elsa_cs.c158
-rw-r--r--drivers/isdn/hisax/hfc_usb.c1
-rw-r--r--drivers/isdn/hisax/hisax.h18
-rw-r--r--drivers/isdn/hisax/hisax_fcpcipnp.h18
-rw-r--r--drivers/isdn/hisax/hscx_irq.c4
-rw-r--r--drivers/isdn/hisax/jade_irq.c2
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c169
-rw-r--r--drivers/isdn/hisax/st5481_init.c1
-rw-r--r--drivers/isdn/hisax/teles_cs.c149
-rw-r--r--drivers/isdn/i4l/isdn_common.c112
-rw-r--r--drivers/isdn/i4l/isdn_common.h1
-rw-r--r--drivers/isdn/i4l/isdn_tty.c75
-rw-r--r--drivers/isdn/sc/command.c1
-rw-r--r--drivers/macintosh/Kconfig10
-rw-r--r--drivers/macintosh/adb-iop.c2
-rw-r--r--drivers/macintosh/macio-adb.c13
-rw-r--r--drivers/macintosh/macio_asic.c264
-rw-r--r--drivers/macintosh/mediabay.c8
-rw-r--r--drivers/macintosh/smu.c50
-rw-r--r--drivers/macintosh/therm_adt746x.c45
-rw-r--r--drivers/macintosh/therm_pm72.c17
-rw-r--r--drivers/macintosh/therm_windtunnel.c6
-rw-r--r--drivers/macintosh/via-cuda.c52
-rw-r--r--drivers/macintosh/via-macii.c4
-rw-r--r--drivers/macintosh/via-maciisi.c22
-rw-r--r--drivers/macintosh/via-pmu.c364
-rw-r--r--drivers/macintosh/via-pmu68k.c4
-rw-r--r--drivers/macintosh/windfarm_lm75_sensor.c63
-rw-r--r--drivers/macintosh/windfarm_pm81.c2
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c1
-rw-r--r--drivers/macintosh/windfarm_smu_sensors.c1
-rw-r--r--drivers/md/.gitignore4
-rw-r--r--drivers/md/bitmap.c116
-rw-r--r--drivers/md/dm-crypt.c7
-rw-r--r--drivers/md/dm-io.h3
-rw-r--r--drivers/md/dm-ioctl.c25
-rw-r--r--drivers/md/dm-log.c2
-rw-r--r--drivers/md/dm-raid1.c13
-rw-r--r--drivers/md/dm-snap.c27
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm.c98
-rw-r--r--drivers/md/dm.h5
-rw-r--r--drivers/md/faulty.c9
-rw-r--r--drivers/md/kcopyd.c4
-rw-r--r--drivers/md/linear.c14
-rw-r--r--drivers/md/md.c927
-rw-r--r--drivers/md/multipath.c29
-rw-r--r--drivers/md/raid0.c32
-rw-r--r--drivers/md/raid1.c730
-rw-r--r--drivers/md/raid10.c548
-rw-r--r--drivers/md/raid5.c182
-rw-r--r--drivers/md/raid6main.c356
-rw-r--r--drivers/media/common/saa7146_core.c9
-rw-r--r--drivers/media/common/saa7146_fops.c44
-rw-r--r--drivers/media/common/saa7146_hlp.c13
-rw-r--r--drivers/media/common/saa7146_vbi.c6
-rw-r--r--drivers/media/common/saa7146_video.c9
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c33
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h4
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c1
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c6
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c2
-rw-r--r--drivers/media/dvb/bt8xx/dst.c52
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c3
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c44
-rw-r--r--drivers/media/dvb/cinergyT2/Kconfig20
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c85
-rw-r--r--drivers/media/dvb/dvb-core/Kconfig2
-rw-r--r--drivers/media/dvb/dvb-core/Makefile2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c12
-rw-r--r--drivers/media/dvb/dvb-core/dvb_filter.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c318
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.h16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c32
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h8
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c44
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig24
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c1
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c445
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c47
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c1
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c3
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c7
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h31
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h2
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c154
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c8
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h14
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c57
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c9
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h29
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c8
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c1
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x-fe.c5
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.c1
-rw-r--r--drivers/media/dvb/dvb-usb/vp702x.h43
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c3
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c3
-rw-r--r--drivers/media/dvb/frontends/Kconfig46
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c9
-rw-r--r--drivers/media/dvb/frontends/cx22702.c22
-rw-r--r--drivers/media/dvb/frontends/cx24110.c23
-rw-r--r--drivers/media/dvb/frontends/cx24123.c889
-rw-r--r--drivers/media/dvb/frontends/cx24123.h51
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c3
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c3
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c34
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h3
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c6
-rw-r--r--drivers/media/dvb/frontends/mt312.c3
-rw-r--r--drivers/media/dvb/frontends/mt352.c3
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c3
-rw-r--r--drivers/media/dvb/frontends/nxt200x.c3
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c10
-rw-r--r--drivers/media/dvb/frontends/or51211.c5
-rw-r--r--drivers/media/dvb/frontends/s5h1420.c4
-rw-r--r--drivers/media/dvb/frontends/sp8870.c3
-rw-r--r--drivers/media/dvb/frontends/sp887x.c5
-rw-r--r--drivers/media/dvb/frontends/stv0299.c12
-rw-r--r--drivers/media/dvb/frontends/stv0299.h1
-rw-r--r--drivers/media/dvb/frontends/tda10021.c4
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c141
-rw-r--r--drivers/media/dvb/pluto2/Kconfig2
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c3
-rw-r--r--drivers/media/dvb/ttpci/Kconfig7
-rw-r--r--drivers/media/dvb/ttpci/Makefile2
-rw-r--r--drivers/media/dvb/ttpci/av7110.c141
-rw-r--r--drivers/media/dvb/ttpci/av7110.h17
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c12
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c47
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h15
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c14
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c118
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c313
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.c13
-rw-r--r--drivers/media/dvb/ttpci/budget.h3
-rw-r--r--drivers/media/dvb/ttpci/ttpci-eeprom.c2
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c4
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig13
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c24
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusbdecfe.c53
-rw-r--r--drivers/media/radio/miropcm20-radio.c1
-rw-r--r--drivers/media/radio/radio-aimslab.c1
-rw-r--r--drivers/media/radio/radio-aztech.c1
-rw-r--r--drivers/media/radio/radio-cadet.c1
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c6
-rw-r--r--drivers/media/radio/radio-gemtek.c1
-rw-r--r--drivers/media/radio/radio-maestro.c391
-rw-r--r--drivers/media/radio/radio-maxiradio.c3
-rw-r--r--drivers/media/radio/radio-rtrack2.c1
-rw-r--r--drivers/media/radio/radio-sf16fmi.c1
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c3
-rw-r--r--drivers/media/radio/radio-terratec.c1
-rw-r--r--drivers/media/radio/radio-trust.c1
-rw-r--r--drivers/media/radio/radio-typhoon.c1
-rw-r--r--drivers/media/radio/radio-zoltrix.c1
-rw-r--r--drivers/media/video/Kconfig13
-rw-r--r--drivers/media/video/Makefile13
-rw-r--r--drivers/media/video/adv7170.c13
-rw-r--r--drivers/media/video/adv7175.c13
-rw-r--r--drivers/media/video/arv.c7
-rw-r--r--drivers/media/video/bt819.c14
-rw-r--r--drivers/media/video/bt832.c78
-rw-r--r--drivers/media/video/bt856.c13
-rw-r--r--drivers/media/video/btcx-risc.c2
-rw-r--r--drivers/media/video/bttv-cards.c365
-rw-r--r--drivers/media/video/bttv-driver.c155
-rw-r--r--drivers/media/video/bttv-gpio.c45
-rw-r--r--drivers/media/video/bttv-i2c.c23
-rw-r--r--drivers/media/video/bttv-input.c (renamed from drivers/media/video/ir-kbd-gpio.c)262
-rw-r--r--drivers/media/video/bttv-vbi.c57
-rw-r--r--drivers/media/video/bttv.h40
-rw-r--r--drivers/media/video/bttvp.h18
-rw-r--r--drivers/media/video/bw-qcam.c1
-rw-r--r--drivers/media/video/c-qcam.c1
-rw-r--r--drivers/media/video/compat_ioctl32.c879
-rw-r--r--drivers/media/video/cpia.c1
-rw-r--r--drivers/media/video/cpia_pp.c33
-rw-r--r--drivers/media/video/cpia_usb.c5
-rw-r--r--drivers/media/video/cs53l32a.c101
-rw-r--r--drivers/media/video/cx25840/cx25840-audio.c91
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c398
-rw-r--r--drivers/media/video/cx25840/cx25840-firmware.c36
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c4
-rw-r--r--drivers/media/video/cx25840/cx25840.h80
-rw-r--r--drivers/media/video/cx88/Kconfig24
-rw-r--r--drivers/media/video/cx88/Makefile5
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c847
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c24
-rw-r--r--drivers/media/video/cx88/cx88-cards.c232
-rw-r--r--drivers/media/video/cx88/cx88-core.c85
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c218
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c15
-rw-r--r--drivers/media/video/cx88/cx88-input.c143
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c5
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c18
-rw-r--r--drivers/media/video/cx88/cx88-video.c100
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c177
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.h35
-rw-r--r--drivers/media/video/cx88/cx88.h17
-rw-r--r--drivers/media/video/dpc7146.c3
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c8
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c61
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c77
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c178
-rw-r--r--drivers/media/video/em28xx/em28xx.h6
-rw-r--r--drivers/media/video/hexium_gemini.c3
-rw-r--r--drivers/media/video/hexium_orion.c3
-rw-r--r--drivers/media/video/indycam.c13
-rw-r--r--drivers/media/video/ir-kbd-i2c.c21
-rw-r--r--drivers/media/video/meye.c1
-rw-r--r--drivers/media/video/msp3400-driver.c1274
-rw-r--r--drivers/media/video/msp3400-kthreads.c1010
-rw-r--r--drivers/media/video/msp3400.c2229
-rw-r--r--drivers/media/video/msp3400.h106
-rw-r--r--drivers/media/video/mt20xx.c22
-rw-r--r--drivers/media/video/mxb.c4
-rw-r--r--drivers/media/video/ovcamchip/ov6x20.c3
-rw-r--r--drivers/media/video/ovcamchip/ov6x30.c3
-rw-r--r--drivers/media/video/ovcamchip/ov76be.c3
-rw-r--r--drivers/media/video/ovcamchip/ov7x10.c3
-rw-r--r--drivers/media/video/ovcamchip/ov7x20.c3
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c9
-rw-r--r--drivers/media/video/planb.c4
-rw-r--r--drivers/media/video/pms.c1
-rw-r--r--drivers/media/video/saa5246a.c16
-rw-r--r--drivers/media/video/saa5249.c19
-rw-r--r--drivers/media/video/saa6588.c27
-rw-r--r--drivers/media/video/saa7110.c13
-rw-r--r--drivers/media/video/saa7111.c13
-rw-r--r--drivers/media/video/saa7114.c13
-rw-r--r--drivers/media/video/saa7115.c331
-rw-r--r--drivers/media/video/saa711x.c17
-rw-r--r--drivers/media/video/saa7127.c93
-rw-r--r--drivers/media/video/saa7134/Kconfig2
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c91
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c158
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c3
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c7
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c39
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c40
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c11
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c10
-rw-r--r--drivers/media/video/saa7134/saa7134.h10
-rw-r--r--drivers/media/video/saa7146.h1
-rw-r--r--drivers/media/video/saa7185.c13
-rw-r--r--drivers/media/video/saa7191.c13
-rw-r--r--drivers/media/video/stradis.c1137
-rw-r--r--drivers/media/video/tda7432.c50
-rw-r--r--drivers/media/video/tda8290.c10
-rw-r--r--drivers/media/video/tda9840.c8
-rw-r--r--drivers/media/video/tda9875.c14
-rw-r--r--drivers/media/video/tda9887.c234
-rw-r--r--drivers/media/video/tea5767.c23
-rw-r--r--drivers/media/video/tea6415c.c8
-rw-r--r--drivers/media/video/tea6420.c11
-rw-r--r--drivers/media/video/tuner-3036.c9
-rw-r--r--drivers/media/video/tuner-core.c221
-rw-r--r--drivers/media/video/tuner-simple.c309
-rw-r--r--drivers/media/video/tuner-types.c1406
-rw-r--r--drivers/media/video/tvaudio.c185
-rw-r--r--drivers/media/video/tveeprom.c58
-rw-r--r--drivers/media/video/tvmixer.c26
-rw-r--r--drivers/media/video/tvp5150.c547
-rw-r--r--drivers/media/video/v4l1-compat.c35
-rw-r--r--drivers/media/video/v4l2-common.c220
-rw-r--r--drivers/media/video/video-buf.c9
-rw-r--r--drivers/media/video/videocodec.c11
-rw-r--r--drivers/media/video/videodev.c40
-rw-r--r--drivers/media/video/vino.c4
-rw-r--r--drivers/media/video/vpx3220.c14
-rw-r--r--drivers/media/video/w9966.c1
-rw-r--r--drivers/media/video/wm8775.c98
-rw-r--r--drivers/media/video/zoran_card.c9
-rw-r--r--drivers/media/video/zoran_driver.c18
-rw-r--r--drivers/media/video/zr36016.c3
-rw-r--r--drivers/media/video/zr36050.c3
-rw-r--r--drivers/media/video/zr36060.c3
-rw-r--r--drivers/media/video/zr36120.c1
-rw-r--r--drivers/message/fusion/Kconfig1
-rw-r--r--drivers/message/fusion/lsi/mpi.h10
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h158
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt77
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h8
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h122
-rw-r--r--drivers/message/fusion/lsi/mpi_log_fc.h89
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h162
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h30
-rw-r--r--drivers/message/fusion/mptbase.c62
-rw-r--r--drivers/message/fusion/mptbase.h64
-rw-r--r--drivers/message/fusion/mptctl.c18
-rw-r--r--drivers/message/fusion/mptfc.c599
-rw-r--r--drivers/message/fusion/mptlan.c18
-rw-r--r--drivers/message/fusion/mptsas.c453
-rw-r--r--drivers/message/fusion/mptscsih.c994
-rw-r--r--drivers/message/fusion/mptscsih.h2
-rw-r--r--drivers/message/fusion/mptspi.c46
-rw-r--r--drivers/message/i2o/Kconfig12
-rw-r--r--drivers/message/i2o/README.ioctl2
-rw-r--r--drivers/message/i2o/bus-osm.c23
-rw-r--r--drivers/message/i2o/config-osm.c2
-rw-r--r--drivers/message/i2o/core.h20
-rw-r--r--drivers/message/i2o/device.c339
-rw-r--r--drivers/message/i2o/driver.c12
-rw-r--r--drivers/message/i2o/exec-osm.c114
-rw-r--r--drivers/message/i2o/i2o_block.c208
-rw-r--r--drivers/message/i2o/i2o_config.c196
-rw-r--r--drivers/message/i2o/i2o_lan.h38
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/message/i2o/i2o_scsi.c89
-rw-r--r--drivers/message/i2o/iop.c356
-rw-r--r--drivers/message/i2o/pci.c17
-rw-r--r--drivers/mfd/mcp-core.c4
-rw-r--r--drivers/mfd/ucb1x00-core.c32
-rw-r--r--drivers/mfd/ucb1x00-ts.c1
-rw-r--r--drivers/misc/ibmasm/ibmasm.h6
-rw-r--r--drivers/misc/ibmasm/remote.c77
-rw-r--r--drivers/mmc/mmc.c11
-rw-r--r--drivers/mmc/mmc_block.c226
-rw-r--r--drivers/mmc/mmc_sysfs.c28
-rw-r--r--drivers/mmc/mmci.c30
-rw-r--r--drivers/mmc/mmci.h4
-rw-r--r--drivers/mmc/wbsd.c552
-rw-r--r--drivers/mtd/chips/Kconfig7
-rw-r--r--drivers/mtd/devices/Kconfig17
-rw-r--r--drivers/mtd/devices/Makefile2
-rw-r--r--drivers/mtd/devices/doc2000.c2
-rw-r--r--drivers/mtd/devices/doc2001.c2
-rw-r--r--drivers/mtd/devices/doc2001plus.c2
-rw-r--r--drivers/mtd/devices/m25p80.c582
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c629
-rw-r--r--drivers/mtd/maps/Kconfig8
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/epxa10db-flash.c179
-rw-r--r--drivers/mtd/maps/pcmciamtd.c121
-rw-r--r--drivers/mtd/mtd_blkdevs.c25
-rw-r--r--drivers/mtd/nand/au1550nd.c2
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/mtd/nand/rtc_from4.c2
-rw-r--r--drivers/mtd/nand/s3c2410.c4
-rw-r--r--drivers/mtd/nand/spia.c2
-rw-r--r--drivers/mtd/onenand/generic.c1
-rw-r--r--drivers/mtd/rfd_ftl.c1
-rw-r--r--drivers/net/3c503.c16
-rw-r--r--drivers/net/3c527.h50
-rw-r--r--drivers/net/8139too.c88
-rw-r--r--drivers/net/Kconfig54
-rw-r--r--drivers/net/Makefile8
-rw-r--r--drivers/net/ac3200.c16
-rw-r--r--drivers/net/arm/Kconfig13
-rw-r--r--drivers/net/arm/Makefile1
-rw-r--r--drivers/net/arm/am79c961a.c12
-rw-r--r--drivers/net/arm/ether00.c1017
-rw-r--r--drivers/net/arm/ether3.c1
-rw-r--r--drivers/net/arm/etherh.c1
-rw-r--r--drivers/net/b44.c2
-rw-r--r--drivers/net/bonding/Makefile2
-rw-r--r--drivers/net/bonding/bond_3ad.c106
-rw-r--r--drivers/net/bonding/bond_3ad.h13
-rw-r--r--drivers/net/bonding/bond_alb.c79
-rw-r--r--drivers/net/bonding/bond_alb.h9
-rw-r--r--drivers/net/bonding/bond_main.c781
-rw-r--r--drivers/net/bonding/bond_sysfs.c1358
-rw-r--r--drivers/net/bonding/bonding.h60
-rw-r--r--drivers/net/cassini.c40
-rw-r--r--drivers/net/chelsio/sge.c19
-rw-r--r--drivers/net/chelsio/sge.h2
-rw-r--r--drivers/net/cs89x0.c171
-rw-r--r--drivers/net/cs89x0.h19
-rw-r--r--drivers/net/e100.c192
-rw-r--r--drivers/net/e1000/e1000.h55
-rw-r--r--drivers/net/e1000/e1000_ethtool.c541
-rw-r--r--drivers/net/e1000/e1000_hw.c138
-rw-r--r--drivers/net/e1000/e1000_hw.h49
-rw-r--r--drivers/net/e1000/e1000_main.c1674
-rw-r--r--drivers/net/e1000/e1000_osdep.h2
-rw-r--r--drivers/net/e1000/e1000_param.c68
-rw-r--r--drivers/net/e2100.c14
-rw-r--r--drivers/net/es3210.c14
-rw-r--r--drivers/net/forcedeth.c164
-rw-r--r--drivers/net/gianfar.c237
-rw-r--r--drivers/net/gianfar.h73
-rw-r--r--drivers/net/gianfar_ethtool.c2
-rw-r--r--drivers/net/gianfar_mii.c5
-rw-r--r--drivers/net/gianfar_mii.h1
-rw-r--r--drivers/net/gianfar_sysfs.c311
-rw-r--r--drivers/net/hamradio/6pack.c7
-rw-r--r--drivers/net/hamradio/mkiss.c8
-rw-r--r--drivers/net/hp-plus.c12
-rw-r--r--drivers/net/hp.c12
-rw-r--r--drivers/net/hp100.c2
-rw-r--r--drivers/net/hplance.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac.h3
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c2
-rw-r--r--drivers/net/ifb.c294
-rw-r--r--drivers/net/irda/Kconfig3
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/irda-usb.c1
-rw-r--r--drivers/net/irda/irport.c15
-rw-r--r--drivers/net/irda/irtty-sir.c18
-rw-r--r--drivers/net/irda/sir-dev.h2
-rw-r--r--drivers/net/irda/sir_core.c56
-rw-r--r--drivers/net/irda/sir_dev.c10
-rw-r--r--drivers/net/irda/sir_dongle.c2
-rw-r--r--drivers/net/irda/sir_kthread.c11
-rw-r--r--drivers/net/irda/stir4200.c1
-rw-r--r--drivers/net/irda/vlsi_ir.h4
-rw-r--r--drivers/net/iseries_veth.c4
-rw-r--r--drivers/net/ixp2000/Kconfig6
-rw-r--r--drivers/net/ixp2000/Makefile3
-rw-r--r--drivers/net/ixp2000/caleb.c137
-rw-r--r--drivers/net/ixp2000/caleb.h22
-rw-r--r--drivers/net/ixp2000/enp2611.c245
-rw-r--r--drivers/net/ixp2000/ixp2400-msf.c213
-rw-r--r--drivers/net/ixp2000/ixp2400-msf.h115
-rw-r--r--drivers/net/ixp2000/ixp2400_rx.uc408
-rw-r--r--drivers/net/ixp2000/ixp2400_rx.ucode130
-rw-r--r--drivers/net/ixp2000/ixp2400_tx.uc272
-rw-r--r--drivers/net/ixp2000/ixp2400_tx.ucode98
-rw-r--r--drivers/net/ixp2000/ixpdev.c421
-rw-r--r--drivers/net/ixp2000/ixpdev.h27
-rw-r--r--drivers/net/ixp2000/ixpdev_priv.h57
-rw-r--r--drivers/net/ixp2000/pm3386.c334
-rw-r--r--drivers/net/ixp2000/pm3386.h28
-rw-r--r--drivers/net/lance.c22
-rw-r--r--drivers/net/lne390.c14
-rw-r--r--drivers/net/mac8390.c31
-rw-r--r--drivers/net/mv643xx_eth.c682
-rw-r--r--drivers/net/ne.c18
-rw-r--r--drivers/net/ne2.c16
-rw-r--r--drivers/net/ns83820.c1
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/3c574_cs.c124
-rw-r--r--drivers/net/pcmcia/3c589_cs.c136
-rw-r--r--drivers/net/pcmcia/axnet_cs.c128
-rw-r--r--drivers/net/pcmcia/com20020_cs.c142
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c128
-rw-r--r--drivers/net/pcmcia/ibmtr_cs.c152
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c134
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c129
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c195
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c160
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/phy/mdio_bus.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/plip.c2
-rw-r--r--drivers/net/ppp_async.c9
-rw-r--r--drivers/net/ppp_synctty.c9
-rw-r--r--drivers/net/pppoe.c31
-rw-r--r--drivers/net/pppox.c10
-rw-r--r--drivers/net/r8169.c2
-rw-r--r--drivers/net/s2io.c200
-rw-r--r--drivers/net/s2io.h3
-rw-r--r--drivers/net/sb1000.c4
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/sis900.c73
-rw-r--r--drivers/net/sis900.h45
-rw-r--r--drivers/net/sk98lin/Makefile3
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h9
-rw-r--r--drivers/net/sk98lin/h/skvpd.h8
-rw-r--r--drivers/net/sk98lin/skdim.c2
-rw-r--r--drivers/net/sk98lin/skethtool.c48
-rw-r--r--drivers/net/sk98lin/skge.c340
-rw-r--r--drivers/net/sk98lin/skgepnmi.c8
-rw-r--r--drivers/net/sk98lin/skproc.c265
-rw-r--r--drivers/net/skge.c101
-rw-r--r--drivers/net/skge.h73
-rw-r--r--drivers/net/sky2.c3315
-rw-r--r--drivers/net/sky2.h1922
-rw-r--r--drivers/net/slip.c11
-rw-r--r--drivers/net/smc-ultra.c24
-rw-r--r--drivers/net/smc91x.c5
-rw-r--r--drivers/net/smc91x.h18
-rw-r--r--drivers/net/spider_net.c512
-rw-r--r--drivers/net/spider_net.h75
-rw-r--r--drivers/net/spider_net_ethtool.c19
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/tg3.c85
-rw-r--r--drivers/net/tg3.h1
-rw-r--r--drivers/net/tlan.c4
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/tulip/uli526x.c6
-rw-r--r--drivers/net/via-velocity.c2
-rw-r--r--drivers/net/wan/.gitignore1
-rw-r--r--drivers/net/wan/lmc/lmc_main.c2
-rw-r--r--drivers/net/wan/lmc/lmc_prot.h15
-rw-r--r--drivers/net/wan/pc300_tty.c2
-rw-r--r--drivers/net/wan/sdla.c6
-rw-r--r--drivers/net/wan/x25_asy.c7
-rw-r--r--drivers/net/wd.c14
-rw-r--r--drivers/net/wireless/Kconfig16
-rw-r--r--drivers/net/wireless/airo.c36
-rw-r--r--drivers/net/wireless/airo_cs.c161
-rw-r--r--drivers/net/wireless/atmel.c1719
-rw-r--r--drivers/net/wireless/atmel_cs.c156
-rw-r--r--drivers/net/wireless/hostap/Kconfig22
-rw-r--r--drivers/net/wireless/hostap/Makefile2
-rw-r--r--drivers/net/wireless/hostap/hostap.h37
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c21
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c36
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h3
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h13
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c156
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c3
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c12
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c (renamed from drivers/net/wireless/hostap/hostap.c)60
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c7
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h4
-rw-r--r--drivers/net/wireless/ipw2100.c505
-rw-r--r--drivers/net/wireless/ipw2100.h2
-rw-r--r--drivers/net/wireless/ipw2200.c92
-rw-r--r--drivers/net/wireless/ipw2200.h6
-rw-r--r--drivers/net/wireless/netwave_cs.c184
-rw-r--r--drivers/net/wireless/orinoco_cs.c208
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c2
-rw-r--r--drivers/net/wireless/ray_cs.c156
-rw-r--r--drivers/net/wireless/spectrum_cs.c175
-rw-r--r--drivers/net/wireless/strip.c10
-rw-r--r--drivers/net/wireless/wavelan.c38
-rw-r--r--drivers/net/wireless/wavelan_cs.c185
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h11
-rw-r--r--drivers/net/wireless/wl3501_cs.c133
-rw-r--r--drivers/oprofile/buffer_sync.c30
-rw-r--r--drivers/oprofile/cpu_buffer.c3
-rw-r--r--drivers/oprofile/event_buffer.c1
-rw-r--r--drivers/parisc/dino.c30
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/eisa_eeprom.c2
-rw-r--r--drivers/parisc/lasi.c2
-rw-r--r--drivers/parisc/lba_pci.c115
-rw-r--r--drivers/parisc/led.c21
-rw-r--r--drivers/parisc/pdc_stable.c46
-rw-r--r--drivers/parisc/power.c12
-rw-r--r--drivers/parport/Kconfig5
-rw-r--r--drivers/parport/daisy.c51
-rw-r--r--drivers/parport/ieee1284_ops.c62
-rw-r--r--drivers/parport/parport_cs.c120
-rw-r--r--drivers/parport/parport_pc.c36
-rw-r--r--drivers/parport/parport_serial.c2
-rw-r--r--drivers/parport/probe.c199
-rw-r--r--drivers/parport/share.c1
-rw-r--r--drivers/pci/hotplug.c44
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c6
-rw-r--r--drivers/pci/hotplug/cpqphp.h8
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c127
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c28
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c138
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c92
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c22
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c52
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c13
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c27
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c47
-rw-r--r--drivers/pci/hotplug/shpchp.h4
-rw-r--r--drivers/pci/hotplug/shpchp_core.c16
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c37
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c138
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c19
-rw-r--r--drivers/pci/pci-driver.c10
-rw-r--r--drivers/pci/pci.c7
-rw-r--r--drivers/pci/pci.h9
-rw-r--r--drivers/pci/pcie/portdrv_core.c4
-rw-r--r--drivers/pci/probe.c49
-rw-r--r--drivers/pci/proc.c7
-rw-r--r--drivers/pci/quirks.c61
-rw-r--r--drivers/pci/remove.c3
-rw-r--r--drivers/pcmcia/Kconfig32
-rw-r--r--drivers/pcmcia/au1000_generic.c21
-rw-r--r--drivers/pcmcia/cistpl.c36
-rw-r--r--drivers/pcmcia/cs.c112
-rw-r--r--drivers/pcmcia/cs_internal.h4
-rw-r--r--drivers/pcmcia/ds.c442
-rw-r--r--drivers/pcmcia/hd64465_ss.c13
-rw-r--r--drivers/pcmcia/i82092.c73
-rw-r--r--drivers/pcmcia/i82092aa.h1
-rw-r--r--drivers/pcmcia/i82365.c83
-rw-r--r--drivers/pcmcia/m32r_cfc.c32
-rw-r--r--drivers/pcmcia/m32r_pcc.c20
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c114
-rw-r--r--drivers/pcmcia/pd6729.c74
-rw-r--r--drivers/pcmcia/pxa2xx_mainstone.c16
-rw-r--r--drivers/pcmcia/pxa2xx_sharpsl.c44
-rw-r--r--drivers/pcmcia/rsrc_mgr.c108
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c140
-rw-r--r--drivers/pcmcia/soc_common.c23
-rw-r--r--drivers/pcmcia/socket_sysfs.c55
-rw-r--r--drivers/pcmcia/tcic.c61
-rw-r--r--drivers/pcmcia/ti113x.h4
-rw-r--r--drivers/pcmcia/vrc4171_card.c74
-rw-r--r--drivers/pcmcia/vrc4173_cardu.c49
-rw-r--r--drivers/pcmcia/vrc4173_cardu.h2
-rw-r--r--drivers/pcmcia/yenta_socket.c140
-rw-r--r--drivers/pnp/card.c25
-rw-r--r--drivers/pnp/driver.c51
-rw-r--r--drivers/pnp/manager.c78
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c45
-rw-r--r--drivers/pnp/pnpbios/core.c8
-rw-r--r--drivers/rapidio/rio-driver.c6
-rw-r--r--drivers/rapidio/rio-scan.c2
-rw-r--r--drivers/rapidio/rio-sysfs.c1
-rw-r--r--drivers/rapidio/rio.c1
-rw-r--r--drivers/s390/Makefile2
-rw-r--r--drivers/s390/block/Kconfig8
-rw-r--r--drivers/s390/block/dasd.c60
-rw-r--r--drivers/s390/block/dasd_diag.c11
-rw-r--r--drivers/s390/block/dasd_diag.h31
-rw-r--r--drivers/s390/block/dasd_eckd.c9
-rw-r--r--drivers/s390/block/dasd_fba.c6
-rw-r--r--drivers/s390/block/dasd_int.h4
-rw-r--r--drivers/s390/block/dasd_ioctl.c45
-rw-r--r--drivers/s390/block/dcssblk.c2
-rw-r--r--drivers/s390/block/xpram.c22
-rw-r--r--drivers/s390/char/con3215.c25
-rw-r--r--drivers/s390/char/fs3270.c20
-rw-r--r--drivers/s390/char/sclp_cpi.c2
-rw-r--r--drivers/s390/char/sclp_quiesce.c2
-rw-r--r--drivers/s390/char/sclp_tty.c21
-rw-r--r--drivers/s390/char/sclp_vt220.c12
-rw-r--r--drivers/s390/char/tape_block.c4
-rw-r--r--drivers/s390/char/tape_char.c20
-rw-r--r--drivers/s390/char/vmwatchdog.c2
-rw-r--r--drivers/s390/cio/airq.c4
-rw-r--r--drivers/s390/cio/blacklist.c236
-rw-r--r--drivers/s390/cio/blacklist.h2
-rw-r--r--drivers/s390/cio/ccwgroup.c26
-rw-r--r--drivers/s390/cio/chsc.c475
-rw-r--r--drivers/s390/cio/chsc.h13
-rw-r--r--drivers/s390/cio/cio.c170
-rw-r--r--drivers/s390/cio/cio.h11
-rw-r--r--drivers/s390/cio/cmf.c8
-rw-r--r--drivers/s390/cio/css.c325
-rw-r--r--drivers/s390/cio/css.h47
-rw-r--r--drivers/s390/cio/device.c101
-rw-r--r--drivers/s390/cio/device.h1
-rw-r--r--drivers/s390/cio/device_fsm.c31
-rw-r--r--drivers/s390/cio/device_id.c28
-rw-r--r--drivers/s390/cio/device_ops.c6
-rw-r--r--drivers/s390/cio/device_pgid.c58
-rw-r--r--drivers/s390/cio/device_status.c16
-rw-r--r--drivers/s390/cio/ioasm.h86
-rw-r--r--drivers/s390/cio/qdio.c715
-rw-r--r--drivers/s390/cio/qdio.h144
-rw-r--r--drivers/s390/cio/schid.h26
-rw-r--r--drivers/s390/crypto/z90common.h9
-rw-r--r--drivers/s390/crypto/z90crypt.h13
-rw-r--r--drivers/s390/crypto/z90hardware.c309
-rw-r--r--drivers/s390/crypto/z90main.c113
-rw-r--r--drivers/s390/net/Kconfig2
-rw-r--r--drivers/s390/net/claw.c6
-rw-r--r--drivers/s390/net/ctcmain.c8
-rw-r--r--drivers/s390/net/ctctty.c28
-rw-r--r--drivers/s390/net/cu3088.c5
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/netiucv.c9
-rw-r--r--drivers/s390/net/qeth_main.c21
-rw-r--r--drivers/s390/s390_rdev.c53
-rw-r--r--drivers/s390/s390mach.c66
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h4
-rw-r--r--drivers/s390/scsi/zfcp_erp.c4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c84
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h13
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c188
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c15
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c4
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c2
-rw-r--r--drivers/s390/sysinfo.c2
-rw-r--r--drivers/sbus/char/aurora.c1
-rw-r--r--drivers/scsi/.gitignore3
-rw-r--r--drivers/scsi/3w-9xxx.c7
-rw-r--r--drivers/scsi/3w-9xxx.h2
-rw-r--r--drivers/scsi/3w-xxxx.c7
-rw-r--r--drivers/scsi/3w-xxxx.h2
-rw-r--r--drivers/scsi/53c700.c6
-rw-r--r--drivers/scsi/53c700.h22
-rw-r--r--drivers/scsi/53c7xx.c7
-rw-r--r--drivers/scsi/BusLogic.c3
-rw-r--r--drivers/scsi/FlashPoint.c2
-rw-r--r--drivers/scsi/Kconfig23
-rw-r--r--drivers/scsi/Makefile5
-rw-r--r--drivers/scsi/NCR5380.c7
-rw-r--r--drivers/scsi/NCR53C9x.c5
-rw-r--r--drivers/scsi/aacraid/README74
-rw-r--r--drivers/scsi/aacraid/aacraid.h7
-rw-r--r--drivers/scsi/aacraid/commctrl.c4
-rw-r--r--drivers/scsi/aacraid/linit.c36
-rw-r--r--drivers/scsi/aha152x.c7
-rw-r--r--drivers/scsi/ahci.c25
-rw-r--r--drivers/scsi/aic7xxx/.gitignore6
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx4
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.h39
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.reg60
-rw-r--r--drivers/scsi/aic7xxx/aic79xx.seq241
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c771
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_inline.h38
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c73
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h2
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.h5
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg.h_shipped646
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped507
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_seq.h_shipped1250
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c46
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h25
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c24
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.h1
-rw-r--r--drivers/scsi/aic7xxx_old.c4
-rw-r--r--drivers/scsi/arm/Kconfig1
-rw-r--r--drivers/scsi/arm/acornscsi.c8
-rw-r--r--drivers/scsi/arm/arxescsi.c1
-rw-r--r--drivers/scsi/arm/cumana_1.c1
-rw-r--r--drivers/scsi/arm/cumana_2.c1
-rw-r--r--drivers/scsi/arm/eesox.c1
-rw-r--r--drivers/scsi/arm/powertec.c1
-rw-r--r--drivers/scsi/ata_piix.c135
-rw-r--r--drivers/scsi/atari_NCR5380.c7
-rw-r--r--drivers/scsi/blz1230.c4
-rw-r--r--drivers/scsi/blz2060.c4
-rw-r--r--drivers/scsi/ch.c38
-rw-r--r--drivers/scsi/constants.c118
-rw-r--r--drivers/scsi/cyberstorm.c4
-rw-r--r--drivers/scsi/cyberstormII.c4
-rw-r--r--drivers/scsi/dpt_i2o.c45
-rw-r--r--drivers/scsi/fastlane.c4
-rw-r--r--drivers/scsi/gdth.c2
-rw-r--r--drivers/scsi/hosts.c17
-rw-r--r--drivers/scsi/ide-scsi.c4
-rw-r--r--drivers/scsi/ipr.c19
-rw-r--r--drivers/scsi/ipr.h5
-rw-r--r--drivers/scsi/ips.c3
-rw-r--r--drivers/scsi/iscsi_tcp.c420
-rw-r--r--drivers/scsi/iscsi_tcp.h9
-rw-r--r--drivers/scsi/libata-core.c580
-rw-r--r--drivers/scsi/libata-scsi.c72
-rw-r--r--drivers/scsi/libata.h5
-rw-r--r--drivers/scsi/lpfc/lpfc.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c92
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h40
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c183
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c69
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c297
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c217
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h2
-rw-r--r--drivers/scsi/mac53c94.c22
-rw-r--r--drivers/scsi/megaraid.c33
-rw-r--r--drivers/scsi/megaraid.h4
-rw-r--r--drivers/scsi/megaraid/Kconfig.megaraid2
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c92
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.h1
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c25
-rw-r--r--drivers/scsi/mesh.c3
-rw-r--r--drivers/scsi/ncr53c8xx.c749
-rw-r--r--drivers/scsi/ncr53c8xx.h1263
-rw-r--r--drivers/scsi/oktagon_esp.c2
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c99
-rw-r--r--drivers/scsi/pcmcia/fdomain_stub.c117
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c167
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.h4
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c127
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c133
-rw-r--r--drivers/scsi/pdc_adma.c11
-rw-r--r--drivers/scsi/qla2xxx/Kconfig79
-rw-r--r--drivers/scsi/qla2xxx/Makefile5
-rw-r--r--drivers/scsi/qla2xxx/ql2400.c111
-rw-r--r--drivers/scsi/qla2xxx/ql2400_fw.c12376
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c105
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h24
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c272
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c107
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c202
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/raid_class.c4
-rw-r--r--drivers/scsi/sata_mv.c12
-rw-r--r--drivers/scsi/sata_nv.c31
-rw-r--r--drivers/scsi/sata_promise.c37
-rw-r--r--drivers/scsi/sata_qstor.c9
-rw-r--r--drivers/scsi/sata_sil.c3
-rw-r--r--drivers/scsi/sata_sil24.c16
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c2
-rw-r--r--drivers/scsi/sata_sx4.c18
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c1
-rw-r--r--drivers/scsi/scsi.c122
-rw-r--r--drivers/scsi/scsi_debug.c4
-rw-r--r--drivers/scsi/scsi_devinfo.c5
-rw-r--r--drivers/scsi/scsi_error.c47
-rw-r--r--drivers/scsi/scsi_lib.c358
-rw-r--r--drivers/scsi/scsi_priv.h11
-rw-r--r--drivers/scsi/scsi_proc.c17
-rw-r--r--drivers/scsi/scsi_scan.c34
-rw-r--r--drivers/scsi/scsi_sysfs.c44
-rw-r--r--drivers/scsi/scsi_transport_fc.c34
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c859
-rw-r--r--drivers/scsi/scsi_transport_sas.c58
-rw-r--r--drivers/scsi/scsi_transport_spi.c146
-rw-r--r--drivers/scsi/sd.c173
-rw-r--r--drivers/scsi/sg.c688
-rw-r--r--drivers/scsi/sr.c47
-rw-r--r--drivers/scsi/sr_ioctl.c202
-rw-r--r--drivers/scsi/sr_vendor.c4
-rw-r--r--drivers/scsi/st.c309
-rw-r--r--drivers/scsi/st.h14
-rw-r--r--drivers/scsi/sun3_NCR5380.c7
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.c18
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw.h6
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw1.h48
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_fw2.h52
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c117
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c164
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h104
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c4
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c29
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.h4
-rw-r--r--drivers/scsi/sym53c8xx_comm.h792
-rw-r--r--drivers/scsi/sym53c8xx_defs.h1320
-rw-r--r--drivers/scsi/wd33c93.c4
-rw-r--r--drivers/serial/21285.c9
-rw-r--r--drivers/serial/68328serial.c19
-rw-r--r--drivers/serial/68360serial.c54
-rw-r--r--drivers/serial/8250.c133
-rw-r--r--drivers/serial/8250.h6
-rw-r--r--drivers/serial/8250_pci.c134
-rw-r--r--drivers/serial/Kconfig80
-rw-r--r--drivers/serial/Makefile3
-rw-r--r--drivers/serial/amba-pl010.c13
-rw-r--r--drivers/serial/amba-pl011.c22
-rw-r--r--drivers/serial/at91_serial.c892
-rw-r--r--drivers/serial/au1x00_uart.c31
-rw-r--r--drivers/serial/clps711x.c2
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c2
-rw-r--r--drivers/serial/crisv10.c11
-rw-r--r--drivers/serial/dz.c2
-rw-r--r--drivers/serial/icom.c57
-rw-r--r--drivers/serial/imx.c5
-rw-r--r--drivers/serial/ioc3_serial.c2197
-rw-r--r--drivers/serial/ioc4_serial.c10
-rw-r--r--drivers/serial/ip22zilog.c34
-rw-r--r--drivers/serial/m32r_sio.c31
-rw-r--r--drivers/serial/mcfserial.c25
-rw-r--r--drivers/serial/mpc52xx_uart.c74
-rw-r--r--drivers/serial/mpsc.c6
-rw-r--r--drivers/serial/mux.c9
-rw-r--r--drivers/serial/pmac_zilog.c86
-rw-r--r--drivers/serial/pxa.c8
-rw-r--r--drivers/serial/s3c2410.c17
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_core.c78
-rw-r--r--drivers/serial/serial_cs.c121
-rw-r--r--drivers/serial/serial_lh7a40x.c9
-rw-r--r--drivers/serial/serial_txx9.c24
-rw-r--r--drivers/serial/sh-sci.c81
-rw-r--r--drivers/serial/sn_console.c6
-rw-r--r--drivers/serial/suncore.c34
-rw-r--r--drivers/serial/sunsab.c45
-rw-r--r--drivers/serial/sunsu.c32
-rw-r--r--drivers/serial/sunzilog.c34
-rw-r--r--drivers/serial/uart00.c782
-rw-r--r--drivers/serial/vr41xx_siu.c7
-rw-r--r--drivers/sh/superhyway/superhyway.c4
-rw-r--r--drivers/sn/Kconfig14
-rw-r--r--drivers/sn/Makefile1
-rw-r--r--drivers/sn/ioc3.c851
-rw-r--r--drivers/spi/Kconfig109
-rw-r--r--drivers/spi/Makefile25
-rw-r--r--drivers/spi/spi.c642
-rw-r--r--drivers/spi/spi_bitbang.c472
-rw-r--r--drivers/spi/spi_butterfly.c423
-rw-r--r--drivers/telephony/ixj_pcmcia.c112
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/atm/Kconfig13
-rw-r--r--drivers/usb/atm/Makefile1
-rw-r--r--drivers/usb/atm/cxacru.c1
-rw-r--r--drivers/usb/atm/speedtch.c5
-rw-r--r--drivers/usb/atm/ueagle-atm.c1820
-rw-r--r--drivers/usb/atm/usbatm.c8
-rw-r--r--drivers/usb/atm/xusbatm.c1
-rw-r--r--drivers/usb/class/audio.c1
-rw-r--r--drivers/usb/class/cdc-acm.c227
-rw-r--r--drivers/usb/class/cdc-acm.h33
-rw-r--r--drivers/usb/class/usb-midi.c1
-rw-r--r--drivers/usb/class/usblp.c47
-rw-r--r--drivers/usb/core/Makefile2
-rw-r--r--drivers/usb/core/buffer.c3
-rw-r--r--drivers/usb/core/devices.c24
-rw-r--r--drivers/usb/core/devio.c3
-rw-r--r--drivers/usb/core/driver.c472
-rw-r--r--drivers/usb/core/hcd.c10
-rw-r--r--drivers/usb/core/hcd.h1
-rw-r--r--drivers/usb/core/hub.c486
-rw-r--r--drivers/usb/core/hub.h3
-rw-r--r--drivers/usb/core/inode.c34
-rw-r--r--drivers/usb/core/message.c6
-rw-r--r--drivers/usb/core/usb.c544
-rw-r--r--drivers/usb/core/usb.h6
-rw-r--r--drivers/usb/gadget/dummy_hcd.c91
-rw-r--r--drivers/usb/gadget/ether.c3
-rw-r--r--drivers/usb/gadget/file_storage.c97
-rw-r--r--drivers/usb/gadget/inode.c7
-rw-r--r--drivers/usb/gadget/serial.c24
-rw-r--r--drivers/usb/gadget/zero.c3
-rw-r--r--drivers/usb/host/Kconfig10
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-hcd.c9
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c20
-rw-r--r--drivers/usb/host/ehci-q.c14
-rw-r--r--drivers/usb/host/hc_crisv10.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c422
-rw-r--r--drivers/usb/host/isp116x.h83
-rw-r--r--drivers/usb/host/ohci-au1xxx.c1
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-hub.c2
-rw-r--r--drivers/usb/host/ohci-lh7a404.c1
-rw-r--r--drivers/usb/host/ohci-omap.c2
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ohci-pxa27x.c121
-rw-r--r--drivers/usb/host/ohci-s3c2410.c4
-rw-r--r--drivers/usb/host/pci-quirks.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c14
-rw-r--r--drivers/usb/host/sl811_cs.c115
-rw-r--r--drivers/usb/host/uhci-debug.c14
-rw-r--r--drivers/usb/host/uhci-hcd.c32
-rw-r--r--drivers/usb/host/uhci-hcd.h32
-rw-r--r--drivers/usb/host/uhci-q.c30
-rw-r--r--drivers/usb/image/mdc800.c1
-rw-r--r--drivers/usb/image/microtek.c3
-rw-r--r--drivers/usb/input/Kconfig24
-rw-r--r--drivers/usb/input/Makefile1
-rw-r--r--drivers/usb/input/acecad.c1
-rw-r--r--drivers/usb/input/aiptek.c7
-rw-r--r--drivers/usb/input/appletouch.c146
-rw-r--r--drivers/usb/input/ati_remote.c22
-rw-r--r--drivers/usb/input/ati_remote2.c477
-rw-r--r--drivers/usb/input/fixp-arith.h2
-rw-r--r--drivers/usb/input/hid-core.c33
-rw-r--r--drivers/usb/input/hid-debug.h15
-rw-r--r--drivers/usb/input/hid-input.c183
-rw-r--r--drivers/usb/input/hid.h30
-rw-r--r--drivers/usb/input/hiddev.c1
-rw-r--r--drivers/usb/input/itmtouch.c1
-rw-r--r--drivers/usb/input/kbtab.c1
-rw-r--r--drivers/usb/input/keyspan_remote.c3
-rw-r--r--drivers/usb/input/mtouchusb.c1
-rw-r--r--drivers/usb/input/pid.c2
-rw-r--r--drivers/usb/input/powermate.c1
-rw-r--r--drivers/usb/input/touchkitusb.c149
-rw-r--r--drivers/usb/input/usbkbd.c1
-rw-r--r--drivers/usb/input/usbmouse.c1
-rw-r--r--drivers/usb/input/wacom.c15
-rw-r--r--drivers/usb/input/xpad.c7
-rw-r--r--drivers/usb/input/yealink.c1
-rw-r--r--drivers/usb/media/dabusb.c1
-rw-r--r--drivers/usb/media/dsbr100.c2
-rw-r--r--drivers/usb/media/ibmcam.c2
-rw-r--r--drivers/usb/media/konicawc.c6
-rw-r--r--drivers/usb/media/ov511.c4
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c2
-rw-r--r--drivers/usb/media/pwc/pwc-if.c2
-rw-r--r--drivers/usb/media/se401.c2
-rw-r--r--drivers/usb/media/sn9c102_core.c24
-rw-r--r--drivers/usb/media/stv680.c2
-rw-r--r--drivers/usb/media/stv680.h6
-rw-r--r--drivers/usb/media/usbvideo.c5
-rw-r--r--drivers/usb/media/vicam.c2
-rw-r--r--drivers/usb/media/w9968cf.c12
-rw-r--r--drivers/usb/misc/auerswald.c5
-rw-r--r--drivers/usb/misc/cytherm.c1
-rw-r--r--drivers/usb/misc/emi26.c1
-rw-r--r--drivers/usb/misc/emi62.c1
-rw-r--r--drivers/usb/misc/idmouse.c1
-rw-r--r--drivers/usb/misc/ldusb.c1
-rw-r--r--drivers/usb/misc/legousbtower.c1
-rw-r--r--drivers/usb/misc/phidgetkit.c1
-rw-r--r--drivers/usb/misc/phidgetservo.c1
-rw-r--r--drivers/usb/misc/rio500.c5
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c11
-rw-r--r--drivers/usb/misc/usblcd.c1
-rw-r--r--drivers/usb/misc/usbled.c1
-rw-r--r--drivers/usb/misc/usbtest.c1
-rw-r--r--drivers/usb/misc/uss720.c1
-rw-r--r--drivers/usb/mon/mon_text.c19
-rw-r--r--drivers/usb/net/asix.c5
-rw-r--r--drivers/usb/net/catc.c1
-rw-r--r--drivers/usb/net/cdc_ether.c1
-rw-r--r--drivers/usb/net/cdc_subset.c1
-rw-r--r--drivers/usb/net/gl620a.c1
-rw-r--r--drivers/usb/net/kaweth.c1
-rw-r--r--drivers/usb/net/net1080.c1
-rw-r--r--drivers/usb/net/pegasus.c144
-rw-r--r--drivers/usb/net/plusb.c1
-rw-r--r--drivers/usb/net/rndis_host.c1
-rw-r--r--drivers/usb/net/rtl8150.c1
-rw-r--r--drivers/usb/net/zaurus.c1
-rw-r--r--drivers/usb/net/zd1201.c11
-rw-r--r--drivers/usb/serial/Kconfig2
-rw-r--r--drivers/usb/serial/airprime.c2
-rw-r--r--drivers/usb/serial/anydata.c2
-rw-r--r--drivers/usb/serial/belkin_sa.c2
-rw-r--r--drivers/usb/serial/bus.c15
-rw-r--r--drivers/usb/serial/cp2101.c2
-rw-r--r--drivers/usb/serial/cyberjack.c13
-rw-r--r--drivers/usb/serial/cypress_m8.c7
-rw-r--r--drivers/usb/serial/digi_acceleport.c30
-rw-r--r--drivers/usb/serial/empeg.c18
-rw-r--r--drivers/usb/serial/ftdi_sio.c21
-rw-r--r--drivers/usb/serial/ftdi_sio.h15
-rw-r--r--drivers/usb/serial/garmin_gps.c15
-rw-r--r--drivers/usb/serial/generic.c13
-rw-r--r--drivers/usb/serial/hp4x.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c26
-rw-r--r--drivers/usb/serial/io_edgeport.h3
-rw-r--r--drivers/usb/serial/io_fw_boot2.h2
-rw-r--r--drivers/usb/serial/io_ti.c24
-rw-r--r--drivers/usb/serial/ipaq.c14
-rw-r--r--drivers/usb/serial/ipw.c13
-rw-r--r--drivers/usb/serial/ir-usb.c2
-rw-r--r--drivers/usb/serial/keyspan.h2
-rw-r--r--drivers/usb/serial/keyspan_pda.c2
-rw-r--r--drivers/usb/serial/kl5kusb105.c15
-rw-r--r--drivers/usb/serial/kobil_sct.c13
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/option.c11
-rw-r--r--drivers/usb/serial/pl2303.c14
-rw-r--r--drivers/usb/serial/safe_serial.c6
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c29
-rw-r--r--drivers/usb/serial/usb-serial.c50
-rw-r--r--drivers/usb/serial/usb-serial.h4
-rw-r--r--drivers/usb/serial/visor.c13
-rw-r--r--drivers/usb/serial/whiteheat.c13
-rw-r--r--drivers/usb/storage/Kconfig23
-rw-r--r--drivers/usb/storage/Makefile5
-rw-r--r--drivers/usb/storage/alauda.c1119
-rw-r--r--drivers/usb/storage/alauda.h100
-rw-r--r--drivers/usb/storage/debug.c1
-rw-r--r--drivers/usb/storage/initializers.h4
-rw-r--r--drivers/usb/storage/libusual.c266
-rw-r--r--drivers/usb/storage/onetouch.c27
-rw-r--r--drivers/usb/storage/protocol.h14
-rw-r--r--drivers/usb/storage/sddr09.c214
-rw-r--r--drivers/usb/storage/sddr09.h15
-rw-r--r--drivers/usb/storage/transport.h31
-rw-r--r--drivers/usb/storage/unusual_devs.h74
-rw-r--r--drivers/usb/storage/usb.c160
-rw-r--r--drivers/usb/storage/usb.h40
-rw-r--r--drivers/usb/usb-skeleton.c29
-rw-r--r--drivers/video/68328fb.c6
-rw-r--r--drivers/video/Kconfig12
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/amba-clcd.c18
-rw-r--r--drivers/video/amifb.c45
-rw-r--r--drivers/video/arcfb.c13
-rw-r--r--drivers/video/asiliantfb.c2
-rw-r--r--drivers/video/atafb.c3
-rw-r--r--drivers/video/aty/Makefile1
-rw-r--r--drivers/video/aty/aty128fb.c6
-rw-r--r--drivers/video/aty/atyfb.h2
-rw-r--r--drivers/video/aty/atyfb_base.c257
-rw-r--r--drivers/video/aty/mach64_ct.c17
-rw-r--r--drivers/video/aty/radeon_base.c20
-rw-r--r--drivers/video/aty/radeon_monitor.c2
-rw-r--r--drivers/video/aty/radeon_pm.c6
-rw-r--r--drivers/video/aty/xlinit.c359
-rw-r--r--drivers/video/au1100fb.c2
-rw-r--r--drivers/video/backlight/corgi_bl.c1
-rw-r--r--drivers/video/bw2.c10
-rw-r--r--drivers/video/cg14.c10
-rw-r--r--drivers/video/cg3.c10
-rw-r--r--drivers/video/cg6.c10
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/bitblit.c14
-rw-r--r--drivers/video/console/fbcon.c83
-rw-r--r--drivers/video/console/fbcon.h11
-rw-r--r--drivers/video/console/fbcon_ccw.c17
-rw-r--r--drivers/video/console/fbcon_cw.c17
-rw-r--r--drivers/video/console/fbcon_rotate.c9
-rw-r--r--drivers/video/console/fbcon_rotate.h2
-rw-r--r--drivers/video/console/fbcon_ud.c19
-rw-r--r--drivers/video/console/softcursor.c2
-rw-r--r--drivers/video/console/tileblit.c17
-rw-r--r--drivers/video/console/vgacon.c36
-rw-r--r--drivers/video/controlfb.c118
-rw-r--r--drivers/video/cyber2000fb.c1
-rw-r--r--drivers/video/cyblafb.c1524
-rw-r--r--drivers/video/fbcvt.c3
-rw-r--r--drivers/video/fbmem.c43
-rw-r--r--drivers/video/fbmon.c129
-rw-r--r--drivers/video/fbsysfs.c81
-rw-r--r--drivers/video/ffb.c10
-rw-r--r--drivers/video/gbefb.c3
-rw-r--r--drivers/video/geode/gx1fb_core.c11
-rw-r--r--drivers/video/hgafb.c107
-rw-r--r--drivers/video/i810/i810-i2c.c3
-rw-r--r--drivers/video/i810/i810_accel.c27
-rw-r--r--drivers/video/i810/i810_gtf.c1
-rw-r--r--drivers/video/i810/i810_main.c137
-rw-r--r--drivers/video/i810/i810_main.h56
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/imsttfb.c59
-rw-r--r--drivers/video/imxfb.c6
-rw-r--r--drivers/video/intelfb/intelfbdrv.c8
-rw-r--r--drivers/video/kyro/STG4000InitDevice.c1
-rw-r--r--drivers/video/kyro/STG4000Interface.h3
-rw-r--r--drivers/video/kyro/STG4000OverlayDevice.c1
-rw-r--r--drivers/video/kyro/fbdev.c37
-rw-r--r--drivers/video/leo.c10
-rw-r--r--drivers/video/logo/Makefile2
-rw-r--r--drivers/video/macfb.c15
-rw-r--r--drivers/video/matrox/matroxfb_base.c5
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c9
-rw-r--r--drivers/video/matrox/matroxfb_g450.c2
-rw-r--r--drivers/video/matrox/matroxfb_maven.c13
-rw-r--r--drivers/video/matrox/matroxfb_misc.c8
-rw-r--r--drivers/video/neofb.c38
-rw-r--r--drivers/video/nvidia/nv_hw.c82
-rw-r--r--drivers/video/nvidia/nv_i2c.c12
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c37
-rw-r--r--drivers/video/nvidia/nvidia.c117
-rw-r--r--drivers/video/offb.c122
-rw-r--r--drivers/video/p9100.c11
-rw-r--r--drivers/video/platinumfb.c98
-rw-r--r--drivers/video/platinumfb.h4
-rw-r--r--drivers/video/pm2fb.c21
-rw-r--r--drivers/video/pm3fb.c8
-rw-r--r--drivers/video/pmag-aa-fb.c3
-rw-r--r--drivers/video/pxafb.c2
-rw-r--r--drivers/video/radeonfb.c4
-rw-r--r--drivers/video/riva/fbdev.c68
-rw-r--r--drivers/video/riva/rivafb-i2c.c8
-rw-r--r--drivers/video/s3c2410fb.c15
-rw-r--r--drivers/video/sa1100fb.c17
-rw-r--r--drivers/video/savage/savagefb-i2c.c44
-rw-r--r--drivers/video/savage/savagefb_accel.c8
-rw-r--r--drivers/video/savage/savagefb_driver.c53
-rw-r--r--drivers/video/sbuslib.c25
-rw-r--r--drivers/video/sbuslib.h4
-rw-r--r--drivers/video/sgivwfb.c5
-rw-r--r--drivers/video/sis/sis_main.c28
-rw-r--r--drivers/video/sis/sis_main.h5
-rw-r--r--drivers/video/skeletonfb.c482
-rw-r--r--drivers/video/sstfb.c63
-rw-r--r--drivers/video/stifb.c65
-rw-r--r--drivers/video/tcx.c11
-rw-r--r--drivers/video/tdfxfb.c59
-rw-r--r--drivers/video/valkyriefb.c12
-rw-r--r--drivers/video/vesafb.c47
-rw-r--r--drivers/video/vfb.c4
-rw-r--r--drivers/video/vga16fb.c8
-rw-r--r--drivers/video/vgastate.c5
-rw-r--r--drivers/w1/Kconfig2
-rw-r--r--drivers/w1/dscore.c1
-rw-r--r--drivers/w1/w1.c14
-rw-r--r--drivers/zorro/proc.c2
-rw-r--r--drivers/zorro/zorro-driver.c4
-rw-r--r--fs/9p/9p.c314
-rw-r--r--fs/9p/9p.h77
-rw-r--r--fs/9p/Makefile11
-rw-r--r--fs/9p/conv.c906
-rw-r--r--fs/9p/conv.h35
-rw-r--r--fs/9p/debug.h23
-rw-r--r--fs/9p/error.c10
-rw-r--r--fs/9p/error.h2
-rw-r--r--fs/9p/fid.c5
-rw-r--r--fs/9p/mux.c1145
-rw-r--r--fs/9p/mux.h41
-rw-r--r--fs/9p/trans_fd.c53
-rw-r--r--fs/9p/trans_sock.c161
-rw-r--r--fs/9p/transport.h4
-rw-r--r--fs/9p/v9fs.c59
-rw-r--r--fs/9p/v9fs.h17
-rw-r--r--fs/9p/v9fs_vfs.h6
-rw-r--r--fs/9p/vfs_addr.c109
-rw-r--r--fs/9p/vfs_dentry.c15
-rw-r--r--fs/9p/vfs_dir.c47
-rw-r--r--fs/9p/vfs_file.c32
-rw-r--r--fs/9p/vfs_inode.c620
-rw-r--r--fs/9p/vfs_super.c14
-rw-r--r--fs/Kconfig68
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/Makefile6
-rw-r--r--fs/affs/inode.c4
-rw-r--r--fs/afs/cmservice.c2
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/afs/volume.h4
-rw-r--r--fs/aio.c3
-rw-r--r--fs/attr.c26
-rw-r--r--fs/autofs/root.c5
-rw-r--r--fs/autofs4/autofs_i.h2
-rw-r--r--fs/autofs4/expire.c12
-rw-r--r--fs/autofs4/inode.c4
-rw-r--r--fs/autofs4/root.c28
-rw-r--r--fs/binfmt_aout.c2
-rw-r--r--fs/binfmt_elf.c30
-rw-r--r--fs/binfmt_elf_fdpic.c2
-rw-r--r--fs/binfmt_flat.c19
-rw-r--r--fs/binfmt_misc.c14
-rw-r--r--fs/bio.c67
-rw-r--r--fs/block_dev.c4
-rw-r--r--fs/buffer.c91
-rw-r--r--fs/char_dev.c96
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/README12
-rw-r--r--fs/cifs/cifs_debug.c51
-rw-r--r--fs/cifs/cifs_fs_sb.h5
-rw-r--r--fs/cifs/cifs_uniupr.h2
-rw-r--r--fs/cifs/cifsacl.h38
-rw-r--r--fs/cifs/cifsencrypt.c55
-rw-r--r--fs/cifs/cifsfs.c34
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h18
-rw-r--r--fs/cifs/cifspdu.h97
-rw-r--r--fs/cifs/cifsproto.h23
-rw-r--r--fs/cifs/cifssmb.c294
-rw-r--r--fs/cifs/connect.c89
-rw-r--r--fs/cifs/dir.c8
-rw-r--r--fs/cifs/file.c79
-rw-r--r--fs/cifs/inode.c20
-rw-r--r--fs/cifs/misc.c17
-rw-r--r--fs/cifs/readdir.c17
-rw-r--r--fs/cifs/rfc1002pdu.h4
-rw-r--r--fs/cifs/transport.c40
-rw-r--r--fs/cifs/xattr.c22
-rw-r--r--fs/coda/cache.c2
-rw-r--r--fs/coda/dir.c4
-rw-r--r--fs/coda/file.c8
-rw-r--r--fs/compat.c336
-rw-r--r--fs/compat_ioctl.c395
-rw-r--r--fs/configfs/Makefile7
-rw-r--r--fs/configfs/configfs_internal.h142
-rw-r--r--fs/configfs/dir.c1102
-rw-r--r--fs/configfs/file.c360
-rw-r--r--fs/configfs/inode.c162
-rw-r--r--fs/configfs/item.c227
-rw-r--r--fs/configfs/mount.c159
-rw-r--r--fs/configfs/symlink.c281
-rw-r--r--fs/dcache.c43
-rw-r--r--fs/dcookies.c1
-rw-r--r--fs/debugfs/inode.c8
-rw-r--r--fs/devfs/base.c22
-rw-r--r--fs/devpts/inode.c8
-rw-r--r--fs/direct-io.c30
-rw-r--r--fs/dquot.c17
-rw-r--r--fs/drop_caches.c68
-rw-r--r--fs/efs/super.c5
-rw-r--r--fs/exec.c24
-rw-r--r--fs/exportfs/expfs.c91
-rw-r--r--fs/ext2/acl.c11
-rw-r--r--fs/ext2/balloc.c1
-rw-r--r--fs/ext2/bitmap.c7
-rw-r--r--fs/ext2/dir.c2
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/ioctl.c1
-rw-r--r--fs/ext2/namei.c5
-rw-r--r--fs/ext2/super.c4
-rw-r--r--fs/ext2/xattr.c6
-rw-r--r--fs/ext2/xattr_trusted.c5
-rw-r--r--fs/ext2/xattr_user.c14
-rw-r--r--fs/ext3/acl.c11
-rw-r--r--fs/ext3/balloc.c3
-rw-r--r--fs/ext3/bitmap.c8
-rw-r--r--fs/ext3/bitmap.h8
-rw-r--r--fs/ext3/ialloc.c7
-rw-r--r--fs/ext3/ioctl.c1
-rw-r--r--fs/ext3/namei.c7
-rw-r--r--fs/ext3/resize.c32
-rw-r--r--fs/ext3/super.c60
-rw-r--r--fs/ext3/xattr.c6
-rw-r--r--fs/ext3/xattr_trusted.c5
-rw-r--r--fs/ext3/xattr_user.c15
-rw-r--r--fs/fat/cache.c14
-rw-r--r--fs/fat/dir.c28
-rw-r--r--fs/fat/fatent.c10
-rw-r--r--fs/fat/file.c38
-rw-r--r--fs/fat/inode.c119
-rw-r--r--fs/fat/misc.c8
-rw-r--r--fs/fcntl.c9
-rw-r--r--fs/fifo.c6
-rw-r--r--fs/file_table.c9
-rw-r--r--fs/freevxfs/vxfs_immed.c4
-rw-r--r--fs/fuse/dev.c237
-rw-r--r--fs/fuse/dir.c294
-rw-r--r--fs/fuse/file.c134
-rw-r--r--fs/fuse/fuse_i.h106
-rw-r--r--fs/fuse/inode.c282
-rw-r--r--fs/hfs/bfind.c3
-rw-r--r--fs/hfs/bnode.c6
-rw-r--r--fs/hfs/brec.c2
-rw-r--r--fs/hfs/btree.c10
-rw-r--r--fs/hfs/catalog.c2
-rw-r--r--fs/hfs/dir.c12
-rw-r--r--fs/hfs/hfs_fs.h3
-rw-r--r--fs/hfs/inode.c5
-rw-r--r--fs/hfs/mdb.c22
-rw-r--r--fs/hfs/super.c40
-rw-r--r--fs/hfsplus/bfind.c3
-rw-r--r--fs/hfsplus/bitmap.c8
-rw-r--r--fs/hfsplus/bnode.c11
-rw-r--r--fs/hfsplus/brec.c2
-rw-r--r--fs/hfsplus/btree.c37
-rw-r--r--fs/hfsplus/catalog.c44
-rw-r--r--fs/hfsplus/dir.c47
-rw-r--r--fs/hfsplus/extents.c6
-rw-r--r--fs/hfsplus/hfsplus_fs.h15
-rw-r--r--fs/hfsplus/hfsplus_raw.h13
-rw-r--r--fs/hfsplus/inode.c25
-rw-r--r--fs/hfsplus/ioctl.c1
-rw-r--r--fs/hfsplus/options.c18
-rw-r--r--fs/hfsplus/super.c75
-rw-r--r--fs/hfsplus/unicode.c30
-rw-r--r--fs/hfsplus/wrapper.c17
-rw-r--r--fs/hpfs/dir.c6
-rw-r--r--fs/hppfs/hppfs_kern.c6
-rw-r--r--fs/hugetlbfs/inode.c10
-rw-r--r--fs/inode.c57
-rw-r--r--fs/inotify.c1
-rw-r--r--fs/ioctl.c1
-rw-r--r--fs/ioprio.c1
-rw-r--r--fs/isofs/namei.c5
-rw-r--r--fs/jbd/checkpoint.c418
-rw-r--r--fs/jbd/commit.c3
-rw-r--r--fs/jffs/inode-v23.c6
-rw-r--r--fs/jffs2/build.c2
-rw-r--r--fs/jffs2/fs.c1
-rw-r--r--fs/jffs2/nodelist.c4
-rw-r--r--fs/jfs/jfs_dmap.c3
-rw-r--r--fs/jfs/jfs_imap.c6
-rw-r--r--fs/jfs/jfs_incore.h4
-rw-r--r--fs/jfs/jfs_txnmgr.c6
-rw-r--r--fs/jfs/jfs_umount.c6
-rw-r--r--fs/jfs/resize.c3
-rw-r--r--fs/jfs/super.c3
-rw-r--r--fs/jfs/xattr.c67
-rw-r--r--fs/libfs.c20
-rw-r--r--fs/lockd/clntproc.c41
-rw-r--r--fs/lockd/host.c4
-rw-r--r--fs/lockd/mon.c1
-rw-r--r--fs/lockd/svc.c4
-rw-r--r--fs/lockd/svc4proc.c15
-rw-r--r--fs/lockd/svclock.c42
-rw-r--r--fs/lockd/svcproc.c14
-rw-r--r--fs/lockd/xdr.c6
-rw-r--r--fs/lockd/xdr4.c4
-rw-r--r--fs/locks.c27
-rw-r--r--fs/mbcache.c6
-rw-r--r--fs/mpage.c6
-rw-r--r--fs/namei.c271
-rw-r--r--fs/namespace.c36
-rw-r--r--fs/ncpfs/dir.c2
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/ncpfs/inode.c19
-rw-r--r--fs/ncpfs/ioctl.c21
-rw-r--r--fs/ncpfs/ncplib_kernel.h4
-rw-r--r--fs/nfs/Makefile1
-rw-r--r--fs/nfs/callback.c6
-rw-r--r--fs/nfs/callback.h1
-rw-r--r--fs/nfs/callback_proc.c4
-rw-r--r--fs/nfs/delegation.c47
-rw-r--r--fs/nfs/delegation.h2
-rw-r--r--fs/nfs/dir.c14
-rw-r--r--fs/nfs/direct.c57
-rw-r--r--fs/nfs/idmap.c9
-rw-r--r--fs/nfs/inode.c203
-rw-r--r--fs/nfs/mount_clnt.c1
-rw-r--r--fs/nfs/nfs2xdr.c21
-rw-r--r--fs/nfs/nfs3proc.c70
-rw-r--r--fs/nfs/nfs3xdr.c2
-rw-r--r--fs/nfs/nfs4_fs.h20
-rw-r--r--fs/nfs/nfs4proc.c1480
-rw-r--r--fs/nfs/nfs4renewd.c14
-rw-r--r--fs/nfs/nfs4state.c183
-rw-r--r--fs/nfs/nfs4xdr.c187
-rw-r--r--fs/nfs/nfsroot.c8
-rw-r--r--fs/nfs/proc.c31
-rw-r--r--fs/nfs/read.c16
-rw-r--r--fs/nfs/sysctl.c84
-rw-r--r--fs/nfs/unlink.c30
-rw-r--r--fs/nfs/write.c89
-rw-r--r--fs/nfsctl.c1
-rw-r--r--fs/nfsd/nfs3proc.c11
-rw-r--r--fs/nfsd/nfs3xdr.c47
-rw-r--r--fs/nfsd/nfs4callback.c11
-rw-r--r--fs/nfsd/nfs4proc.c55
-rw-r--r--fs/nfsd/nfs4recover.c30
-rw-r--r--fs/nfsd/nfs4state.c220
-rw-r--r--fs/nfsd/nfs4xdr.c10
-rw-r--r--fs/nfsd/nfsproc.c37
-rw-r--r--fs/nfsd/nfsxdr.c52
-rw-r--r--fs/nfsd/vfs.c250
-rw-r--r--fs/ntfs/ChangeLog2
-rw-r--r--fs/ntfs/attrib.c4
-rw-r--r--fs/ntfs/dir.c8
-rw-r--r--fs/ntfs/file.c20
-rw-r--r--fs/ntfs/index.c6
-rw-r--r--fs/ntfs/inode.c28
-rw-r--r--fs/ntfs/namei.c6
-rw-r--r--fs/ntfs/quota.c6
-rw-r--r--fs/ntfs/super.c44
-rw-r--r--fs/ocfs2/Makefile33
-rw-r--r--fs/ocfs2/alloc.c2040
-rw-r--r--fs/ocfs2/alloc.h82
-rw-r--r--fs/ocfs2/aops.c643
-rw-r--r--fs/ocfs2/aops.h41
-rw-r--r--fs/ocfs2/buffer_head_io.c232
-rw-r--r--fs/ocfs2/buffer_head_io.h73
-rw-r--r--fs/ocfs2/cluster/Makefile4
-rw-r--r--fs/ocfs2/cluster/endian.h30
-rw-r--r--fs/ocfs2/cluster/heartbeat.c1797
-rw-r--r--fs/ocfs2/cluster/heartbeat.h82
-rw-r--r--fs/ocfs2/cluster/masklog.c166
-rw-r--r--fs/ocfs2/cluster/masklog.h274
-rw-r--r--fs/ocfs2/cluster/nodemanager.c791
-rw-r--r--fs/ocfs2/cluster/nodemanager.h64
-rw-r--r--fs/ocfs2/cluster/ocfs2_heartbeat.h37
-rw-r--r--fs/ocfs2/cluster/ocfs2_nodemanager.h39
-rw-r--r--fs/ocfs2/cluster/quorum.c315
-rw-r--r--fs/ocfs2/cluster/quorum.h36
-rw-r--r--fs/ocfs2/cluster/sys.c124
-rw-r--r--fs/ocfs2/cluster/sys.h33
-rw-r--r--fs/ocfs2/cluster/tcp.c1829
-rw-r--r--fs/ocfs2/cluster/tcp.h113
-rw-r--r--fs/ocfs2/cluster/tcp_internal.h174
-rw-r--r--fs/ocfs2/cluster/ver.c42
-rw-r--r--fs/ocfs2/cluster/ver.h31
-rw-r--r--fs/ocfs2/dcache.c91
-rw-r--r--fs/ocfs2/dcache.h31
-rw-r--r--fs/ocfs2/dir.c618
-rw-r--r--fs/ocfs2/dir.h54
-rw-r--r--fs/ocfs2/dlm/Makefile8
-rw-r--r--fs/ocfs2/dlm/dlmapi.h214
-rw-r--r--fs/ocfs2/dlm/dlmast.c466
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h884
-rw-r--r--fs/ocfs2/dlm/dlmconvert.c530
-rw-r--r--fs/ocfs2/dlm/dlmconvert.h35
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c246
-rw-r--r--fs/ocfs2/dlm/dlmdebug.h30
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c1469
-rw-r--r--fs/ocfs2/dlm/dlmdomain.h36
-rw-r--r--fs/ocfs2/dlm/dlmfs.c640
-rw-r--r--fs/ocfs2/dlm/dlmfsver.c42
-rw-r--r--fs/ocfs2/dlm/dlmfsver.h31
-rw-r--r--fs/ocfs2/dlm/dlmlock.c676
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c2664
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c2132
-rw-r--r--fs/ocfs2/dlm/dlmthread.c692
-rw-r--r--fs/ocfs2/dlm/dlmunlock.c672
-rw-r--r--fs/ocfs2/dlm/dlmver.c42
-rw-r--r--fs/ocfs2/dlm/dlmver.h31
-rw-r--r--fs/ocfs2/dlm/userdlm.c658
-rw-r--r--fs/ocfs2/dlm/userdlm.h111
-rw-r--r--fs/ocfs2/dlmglue.c2904
-rw-r--r--fs/ocfs2/dlmglue.h111
-rw-r--r--fs/ocfs2/endian.h45
-rw-r--r--fs/ocfs2/export.c248
-rw-r--r--fs/ocfs2/export.h31
-rw-r--r--fs/ocfs2/extent_map.c994
-rw-r--r--fs/ocfs2/extent_map.h46
-rw-r--r--fs/ocfs2/file.c1238
-rw-r--r--fs/ocfs2/file.h57
-rw-r--r--fs/ocfs2/heartbeat.c378
-rw-r--r--fs/ocfs2/heartbeat.h67
-rw-r--r--fs/ocfs2/inode.c1140
-rw-r--r--fs/ocfs2/inode.h145
-rw-r--r--fs/ocfs2/journal.c1652
-rw-r--r--fs/ocfs2/journal.h457
-rw-r--r--fs/ocfs2/localalloc.c983
-rw-r--r--fs/ocfs2/localalloc.h56
-rw-r--r--fs/ocfs2/mmap.c98
-rw-r--r--fs/ocfs2/mmap.h6
-rw-r--r--fs/ocfs2/namei.c2264
-rw-r--r--fs/ocfs2/namei.h58
-rw-r--r--fs/ocfs2/ocfs1_fs_compat.h109
-rw-r--r--fs/ocfs2/ocfs2.h464
-rw-r--r--fs/ocfs2/ocfs2_fs.h638
-rw-r--r--fs/ocfs2/ocfs2_lockid.h73
-rw-r--r--fs/ocfs2/slot_map.c303
-rw-r--r--fs/ocfs2/slot_map.h66
-rw-r--r--fs/ocfs2/suballoc.c1651
-rw-r--r--fs/ocfs2/suballoc.h132
-rw-r--r--fs/ocfs2/super.c1733
-rw-r--r--fs/ocfs2/super.h44
-rw-r--r--fs/ocfs2/symlink.c180
-rw-r--r--fs/ocfs2/symlink.h42
-rw-r--r--fs/ocfs2/sysfile.c131
-rw-r--r--fs/ocfs2/sysfile.h33
-rw-r--r--fs/ocfs2/uptodate.c544
-rw-r--r--fs/ocfs2/uptodate.h44
-rw-r--r--fs/ocfs2/ver.c43
-rw-r--r--fs/ocfs2/ver.h31
-rw-r--r--fs/ocfs2/vote.c1202
-rw-r--r--fs/ocfs2/vote.h56
-rw-r--r--fs/open.c123
-rw-r--r--fs/partitions/Kconfig29
-rw-r--r--fs/partitions/Makefile1
-rw-r--r--fs/partitions/check.c37
-rw-r--r--fs/partitions/ibm.c30
-rw-r--r--fs/partitions/karma.c57
-rw-r--r--fs/partitions/karma.h8
-rw-r--r--fs/pipe.c50
-rw-r--r--fs/pnode.c2
-rw-r--r--fs/proc/array.c8
-rw-r--r--fs/proc/base.c1
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/inode.c2
-rw-r--r--fs/proc/internal.h4
-rw-r--r--fs/proc/kcore.c1
-rw-r--r--fs/proc/proc_devtree.c24
-rw-r--r--fs/proc/proc_misc.c164
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/proc/task_mmu.c127
-rw-r--r--fs/proc/vmcore.c6
-rw-r--r--fs/qnx4/bitmap.c2
-rw-r--r--fs/quota.c7
-rw-r--r--fs/quota_v2.c3
-rw-r--r--fs/ramfs/Makefile4
-rw-r--r--fs/ramfs/file-mmu.c57
-rw-r--r--fs/ramfs/file-nommu.c292
-rw-r--r--fs/ramfs/inode.c22
-rw-r--r--fs/ramfs/internal.h15
-rw-r--r--fs/read_write.c38
-rw-r--r--fs/readdir.c4
-rw-r--r--fs/reiserfs/file.c12
-rw-r--r--fs/reiserfs/inode.c14
-rw-r--r--fs/reiserfs/ioctl.c5
-rw-r--r--fs/reiserfs/journal.c5
-rw-r--r--fs/reiserfs/namei.c6
-rw-r--r--fs/reiserfs/super.c4
-rw-r--r--fs/reiserfs/tail_conversion.c2
-rw-r--r--fs/reiserfs/xattr.c60
-rw-r--r--fs/reiserfs/xattr_acl.c7
-rw-r--r--fs/reiserfs/xattr_trusted.c1
-rw-r--r--fs/reiserfs/xattr_user.c30
-rw-r--r--fs/relayfs/buffers.c3
-rw-r--r--fs/relayfs/inode.c226
-rw-r--r--fs/relayfs/relay.c69
-rw-r--r--fs/relayfs/relay.h4
-rw-r--r--fs/romfs/inode.c6
-rw-r--r--fs/select.c348
-rw-r--r--fs/smbfs/Makefile1
-rw-r--r--fs/smbfs/cache.c4
-rw-r--r--fs/smbfs/file.c7
-rw-r--r--fs/smbfs/inode.c35
-rw-r--r--fs/smbfs/proc.c3
-rw-r--r--fs/smbfs/request.c13
-rw-r--r--fs/stat.c66
-rw-r--r--fs/super.c20
-rw-r--r--fs/sysfs/dir.c37
-rw-r--r--fs/sysfs/file.c17
-rw-r--r--fs/sysfs/inode.c9
-rw-r--r--fs/sysfs/symlink.c5
-rw-r--r--fs/sysv/ChangeLog2
-rw-r--r--fs/sysv/dir.c4
-rw-r--r--fs/udf/balloc.c7
-rw-r--r--fs/udf/crc.c5
-rw-r--r--fs/udf/dir.c5
-rw-r--r--fs/udf/directory.c5
-rw-r--r--fs/udf/file.c6
-rw-r--r--fs/udf/fsync.c5
-rw-r--r--fs/udf/ialloc.c5
-rw-r--r--fs/udf/inode.c10
-rw-r--r--fs/udf/lowlevel.c5
-rw-r--r--fs/udf/misc.c5
-rw-r--r--fs/udf/namei.c5
-rw-r--r--fs/udf/partition.c5
-rw-r--r--fs/udf/super.c5
-rw-r--r--fs/udf/symlink.c5
-rw-r--r--fs/udf/truncate.c5
-rw-r--r--fs/udf/unicode.c5
-rw-r--r--fs/ufs/balloc.c20
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/ialloc.c4
-rw-r--r--fs/ufs/inode.c11
-rw-r--r--fs/ufs/super.c65
-rw-r--r--fs/ufs/util.h28
-rw-r--r--fs/xattr.c199
-rw-r--r--fs/xfs/Kbuild6
-rw-r--r--fs/xfs/linux-2.6/mutex.h18
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c1111
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h10
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c1373
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h696
-rw-r--r--fs/xfs/linux-2.6/xfs_cred.h4
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_fs_subr.c3
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c16
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c137
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.h5
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c76
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_stats.h18
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c19
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h19
-rw-r--r--fs/xfs/quota/xfs_dquot.c4
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c4
-rw-r--r--fs/xfs/quota/xfs_qm.c142
-rw-r--r--fs/xfs/quota/xfs_qm.h2
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c2
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c11
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h2
-rw-r--r--fs/xfs/support/debug.c60
-rw-r--r--fs/xfs/support/debug.h25
-rw-r--r--fs/xfs/support/uuid.c29
-rw-r--r--fs/xfs/xfs_acl.c1
-rw-r--r--fs/xfs/xfs_arch.h22
-rw-r--r--fs/xfs/xfs_attr.c32
-rw-r--r--fs/xfs/xfs_attr_leaf.c12
-rw-r--r--fs/xfs/xfs_attr_leaf.h79
-rw-r--r--fs/xfs/xfs_bmap.c412
-rw-r--r--fs/xfs/xfs_bmap.h7
-rw-r--r--fs/xfs/xfs_clnt.h2
-rw-r--r--fs/xfs/xfs_dfrag.c16
-rw-r--r--fs/xfs/xfs_dinode.h22
-rw-r--r--fs/xfs/xfs_dir.c2
-rw-r--r--fs/xfs/xfs_dir.h2
-rw-r--r--fs/xfs/xfs_dir2.h3
-rw-r--r--fs/xfs/xfs_dir_leaf.c96
-rw-r--r--fs/xfs/xfs_dir_leaf.h64
-rw-r--r--fs/xfs/xfs_dmapi.h14
-rw-r--r--fs/xfs/xfs_error.c1
-rw-r--r--fs/xfs/xfs_error.h8
-rw-r--r--fs/xfs/xfs_fs.h10
-rw-r--r--fs/xfs/xfs_fsops.c30
-rw-r--r--fs/xfs/xfs_fsops.h1
-rw-r--r--fs/xfs/xfs_iget.c5
-rw-r--r--fs/xfs/xfs_inode.c61
-rw-r--r--fs/xfs/xfs_inode.h4
-rw-r--r--fs/xfs/xfs_inode_item.c9
-rw-r--r--fs/xfs/xfs_iomap.c426
-rw-r--r--fs/xfs/xfs_itable.c5
-rw-r--r--fs/xfs/xfs_log.c175
-rw-r--r--fs/xfs/xfs_log.h19
-rw-r--r--fs/xfs/xfs_log_priv.h77
-rw-r--r--fs/xfs/xfs_log_recover.c12
-rw-r--r--fs/xfs/xfs_mount.c73
-rw-r--r--fs/xfs/xfs_mount.h5
-rw-r--r--fs/xfs/xfs_rename.c7
-rw-r--r--fs/xfs/xfs_rw.c9
-rw-r--r--fs/xfs/xfs_sb.h17
-rw-r--r--fs/xfs/xfs_trans.c14
-rw-r--r--fs/xfs/xfs_trans.h1
-rw-r--r--fs/xfs/xfs_trans_item.c22
-rw-r--r--fs/xfs/xfs_utils.c9
-rw-r--r--fs/xfs/xfs_vfsops.c50
-rw-r--r--fs/xfs/xfs_vnodeops.c255
-rw-r--r--include/asm-alpha/atomic.h2
-rw-r--r--include/asm-alpha/bitops.h1
-rw-r--r--include/asm-alpha/cache.h1
-rw-r--r--include/asm-alpha/compiler.h2
-rw-r--r--include/asm-alpha/dma-mapping.h2
-rw-r--r--include/asm-alpha/futex.h49
-rw-r--r--include/asm-alpha/hardirq.h2
-rw-r--r--include/asm-alpha/mman.h1
-rw-r--r--include/asm-alpha/mmu_context.h6
-rw-r--r--include/asm-alpha/mutex.h9
-rw-r--r--include/asm-alpha/processor.h34
-rw-r--r--include/asm-alpha/ptrace.h6
-rw-r--r--include/asm-alpha/system.h18
-rw-r--r--include/asm-alpha/thread_info.h2
-rw-r--r--include/asm-arm/arch-aaec2000/dma.h8
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200.h261
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h36
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_sys.h328
-rw-r--r--include/asm-arm/arch-at91rm9200/at91rm9200_usart.h123
-rw-r--r--include/asm-arm/arch-at91rm9200/board.h80
-rw-r--r--include/asm-arm/arch-at91rm9200/debug-macro.S38
-rw-r--r--include/asm-arm/arch-at91rm9200/dma.h (renamed from include/asm-arm/arch-epxa10db/dma.h)13
-rw-r--r--include/asm-arm/arch-at91rm9200/entry-macro.S25
-rw-r--r--include/asm-arm/arch-at91rm9200/gpio.h193
-rw-r--r--include/asm-arm/arch-at91rm9200/hardware.h92
-rw-r--r--include/asm-arm/arch-at91rm9200/io.h (renamed from arch/arm/mach-epxa10db/dma.c)23
-rw-r--r--include/asm-arm/arch-at91rm9200/irqs.h52
-rw-r--r--include/asm-arm/arch-at91rm9200/memory.h (renamed from include/asm-arm/arch-epxa10db/memory.h)19
-rw-r--r--include/asm-arm/arch-at91rm9200/param.h (renamed from include/asm-arm/arch-epxa10db/param.h)13
-rw-r--r--include/asm-arm/arch-at91rm9200/pio.h115
-rw-r--r--include/asm-arm/arch-at91rm9200/system.h (renamed from include/asm-arm/arch-epxa10db/system.h)28
-rw-r--r--include/asm-arm/arch-at91rm9200/timex.h (renamed from include/asm-arm/arch-epxa10db/timex.h)18
-rw-r--r--include/asm-arm/arch-at91rm9200/uncompress.h55
-rw-r--r--include/asm-arm/arch-at91rm9200/vmalloc.h (renamed from include/asm-arm/arch-epxa10db/vmalloc.h)12
-rw-r--r--include/asm-arm/arch-cl7500/dma.h1
-rw-r--r--include/asm-arm/arch-cl7500/entry-macro.S2
-rw-r--r--include/asm-arm/arch-clps711x/dma.h9
-rw-r--r--include/asm-arm/arch-clps711x/entry-macro.S1
-rw-r--r--include/asm-arm/arch-clps711x/system.h2
-rw-r--r--include/asm-arm/arch-ebsa110/dma.h8
-rw-r--r--include/asm-arm/arch-ebsa285/dma.h5
-rw-r--r--include/asm-arm/arch-ebsa285/entry-macro.S2
-rw-r--r--include/asm-arm/arch-epxa10db/debug-macro.S41
-rw-r--r--include/asm-arm/arch-epxa10db/entry-macro.S25
-rw-r--r--include/asm-arm/arch-epxa10db/ether00.h482
-rw-r--r--include/asm-arm/arch-epxa10db/excalibur.h91
-rw-r--r--include/asm-arm/arch-epxa10db/hardware.h64
-rw-r--r--include/asm-arm/arch-epxa10db/int_ctrl00.h288
-rw-r--r--include/asm-arm/arch-epxa10db/io.h41
-rw-r--r--include/asm-arm/arch-epxa10db/irqs.h45
-rw-r--r--include/asm-arm/arch-epxa10db/mode_ctrl00.h80
-rw-r--r--include/asm-arm/arch-epxa10db/platform.h7
-rw-r--r--include/asm-arm/arch-epxa10db/pld_conf00.h73
-rw-r--r--include/asm-arm/arch-epxa10db/tdkphy.h209
-rw-r--r--include/asm-arm/arch-epxa10db/timer00.h98
-rw-r--r--include/asm-arm/arch-epxa10db/uart00.h181
-rw-r--r--include/asm-arm/arch-epxa10db/uncompress.h54
-rw-r--r--include/asm-arm/arch-imx/dma.h4
-rw-r--r--include/asm-arm/arch-imx/entry-macro.S2
-rw-r--r--include/asm-arm/arch-integrator/debug-macro.S2
-rw-r--r--include/asm-arm/arch-integrator/dma.h9
-rw-r--r--include/asm-arm/arch-integrator/entry-macro.S2
-rw-r--r--include/asm-arm/arch-iop3xx/dma.h7
-rw-r--r--include/asm-arm/arch-iop3xx/entry-macro.S1
-rw-r--r--include/asm-arm/arch-ixp2000/dma.h9
-rw-r--r--include/asm-arm/arch-ixp2000/enp2611.h6
-rw-r--r--include/asm-arm/arch-ixp2000/entry-macro.S1
-rw-r--r--include/asm-arm/arch-ixp2000/io.h98
-rw-r--r--include/asm-arm/arch-ixp2000/ixp2000-regs.h18
-rw-r--r--include/asm-arm/arch-ixp4xx/coyote.h5
-rw-r--r--include/asm-arm/arch-ixp4xx/dma.h3
-rw-r--r--include/asm-arm/arch-ixp4xx/entry-macro.S1
-rw-r--r--include/asm-arm/arch-ixp4xx/gtwx5715.h4
-rw-r--r--include/asm-arm/arch-ixp4xx/hardware.h1
-rw-r--r--include/asm-arm/arch-ixp4xx/irqs.h9
-rw-r--r--include/asm-arm/arch-ixp4xx/ixdp425.h3
-rw-r--r--include/asm-arm/arch-ixp4xx/memory.h25
-rw-r--r--include/asm-arm/arch-ixp4xx/nas100d.h72
-rw-r--r--include/asm-arm/arch-ixp4xx/nslu2.h3
-rw-r--r--include/asm-arm/arch-ixp4xx/platform.h24
-rw-r--r--include/asm-arm/arch-l7200/dma.h1
-rw-r--r--include/asm-arm/arch-l7200/system.h2
-rw-r--r--include/asm-arm/arch-lh7a40x/dma.h8
-rw-r--r--include/asm-arm/arch-lh7a40x/entry-macro.S2
-rw-r--r--include/asm-arm/arch-omap/clock.h2
-rw-r--r--include/asm-arm/arch-omap/dma.h3
-rw-r--r--include/asm-arm/arch-omap/entry-macro.S2
-rw-r--r--include/asm-arm/arch-omap/system.h3
-rw-r--r--include/asm-arm/arch-pxa/dma.h5
-rw-r--r--include/asm-arm/arch-pxa/entry-macro.S2
-rw-r--r--include/asm-arm/arch-pxa/ohci.h18
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h26
-rw-r--r--include/asm-arm/arch-realview/debug-macro.S2
-rw-r--r--include/asm-arm/arch-realview/dma.h7
-rw-r--r--include/asm-arm/arch-realview/entry-macro.S2
-rw-r--r--include/asm-arm/arch-rpc/entry-macro.S2
-rw-r--r--include/asm-arm/arch-s3c2410/dma.h8
-rw-r--r--include/asm-arm/arch-s3c2410/entry-macro.S2
-rw-r--r--include/asm-arm/arch-sa1100/dma.h14
-rw-r--r--include/asm-arm/arch-versatile/debug-macro.S2
-rw-r--r--include/asm-arm/arch-versatile/dma.h7
-rw-r--r--include/asm-arm/arch-versatile/entry-macro.S5
-rw-r--r--include/asm-arm/arch-versatile/platform.h23
-rw-r--r--include/asm-arm/atomic.h3
-rw-r--r--include/asm-arm/bitops.h2
-rw-r--r--include/asm-arm/byteorder.h25
-rw-r--r--include/asm-arm/cache.h5
-rw-r--r--include/asm-arm/cacheflush.h1
-rw-r--r--include/asm-arm/dma.h11
-rw-r--r--include/asm-arm/futex.h49
-rw-r--r--include/asm-arm/hardware/sharpsl_pm.h94
-rw-r--r--include/asm-arm/hardware/vic.h45
-rw-r--r--include/asm-arm/io.h6
-rw-r--r--include/asm-arm/ioctl.h75
-rw-r--r--include/asm-arm/irq.h12
-rw-r--r--include/asm-arm/mach/arch.h4
-rw-r--r--include/asm-arm/mach/dma.h4
-rw-r--r--include/asm-arm/mach/map.h3
-rw-r--r--include/asm-arm/mach/serial_at91rm9200.h36
-rw-r--r--include/asm-arm/memory.h15
-rw-r--r--include/asm-arm/mman.h1
-rw-r--r--include/asm-arm/mutex.h128
-rw-r--r--include/asm-arm/page.h7
-rw-r--r--include/asm-arm/processor.h15
-rw-r--r--include/asm-arm/ptrace.h11
-rw-r--r--include/asm-arm/scatterlist.h1
-rw-r--r--include/asm-arm/stat.h11
-rw-r--r--include/asm-arm/statfs.h38
-rw-r--r--include/asm-arm/system.h12
-rw-r--r--include/asm-arm/thread_info.h7
-rw-r--r--include/asm-arm/unistd.h65
-rw-r--r--include/asm-arm26/atomic.h3
-rw-r--r--include/asm-arm26/bitops.h1
-rw-r--r--include/asm-arm26/cache.h3
-rw-r--r--include/asm-arm26/futex.h49
-rw-r--r--include/asm-arm26/ioctl.h75
-rw-r--r--include/asm-arm26/mman.h1
-rw-r--r--include/asm-arm26/system.h12
-rw-r--r--include/asm-arm26/thread_info.h12
-rw-r--r--include/asm-cris/arch-v10/cache.h1
-rw-r--r--include/asm-cris/arch-v10/processor.h2
-rw-r--r--include/asm-cris/arch-v32/cache.h1
-rw-r--r--include/asm-cris/arch-v32/processor.h2
-rw-r--r--include/asm-cris/atomic.h3
-rw-r--r--include/asm-cris/bitops.h1
-rw-r--r--include/asm-cris/dma-mapping.h2
-rw-r--r--include/asm-cris/futex.h49
-rw-r--r--include/asm-cris/ioctl.h84
-rw-r--r--include/asm-cris/mman.h1
-rw-r--r--include/asm-cris/mutex.h9
-rw-r--r--include/asm-cris/processor.h3
-rw-r--r--include/asm-cris/thread_info.h2
-rw-r--r--include/asm-frv/atomic.h98
-rw-r--r--include/asm-frv/bitops.h1
-rw-r--r--include/asm-frv/bug.h1
-rw-r--r--include/asm-frv/dma-mapping.h2
-rw-r--r--include/asm-frv/futex.h42
-rw-r--r--include/asm-frv/io.h123
-rw-r--r--include/asm-frv/ioctl.h81
-rw-r--r--include/asm-frv/mb-regs.h4
-rw-r--r--include/asm-frv/mc146818rtc.h16
-rw-r--r--include/asm-frv/mman.h1
-rw-r--r--include/asm-frv/module.h16
-rw-r--r--include/asm-frv/mutex.h9
-rw-r--r--include/asm-frv/pci.h8
-rw-r--r--include/asm-frv/pgtable.h5
-rw-r--r--include/asm-frv/signal.h1
-rw-r--r--include/asm-frv/thread_info.h4
-rw-r--r--include/asm-frv/types.h1
-rw-r--r--include/asm-frv/uaccess.h8
-rw-r--r--include/asm-frv/unistd.h3
-rw-r--r--include/asm-frv/vga.h17
-rw-r--r--include/asm-frv/xor.h1
-rw-r--r--include/asm-generic/atomic.h117
-rw-r--r--include/asm-generic/bitops.h1
-rw-r--r--include/asm-generic/dma-mapping.h2
-rw-r--r--include/asm-generic/futex.h53
-rw-r--r--include/asm-generic/ioctl.h80
-rw-r--r--include/asm-generic/mutex-dec.h110
-rw-r--r--include/asm-generic/mutex-null.h24
-rw-r--r--include/asm-generic/mutex-xchg.h117
-rw-r--r--include/asm-generic/vmlinux.lds.h4
-rw-r--r--include/asm-h8300/atomic.h3
-rw-r--r--include/asm-h8300/bitops.h1
-rw-r--r--include/asm-h8300/futex.h49
-rw-r--r--include/asm-h8300/ioctl.h81
-rw-r--r--include/asm-h8300/irq.h5
-rw-r--r--include/asm-h8300/mman.h1
-rw-r--r--include/asm-h8300/mutex.h9
-rw-r--r--include/asm-h8300/page.h6
-rw-r--r--include/asm-h8300/thread_info.h2
-rw-r--r--include/asm-i386/apic.h5
-rw-r--r--include/asm-i386/atomic.h2
-rw-r--r--include/asm-i386/bitops.h53
-rw-r--r--include/asm-i386/bugs.h23
-rw-r--r--include/asm-i386/cache.h2
-rw-r--r--include/asm-i386/cacheflush.h4
-rw-r--r--include/asm-i386/cpufeature.h1
-rw-r--r--include/asm-i386/current.h2
-rw-r--r--include/asm-i386/desc.h8
-rw-r--r--include/asm-i386/dma-mapping.h14
-rw-r--r--include/asm-i386/edac.h18
-rw-r--r--include/asm-i386/futex.h2
-rw-r--r--include/asm-i386/i387.h8
-rw-r--r--include/asm-i386/io.h5
-rw-r--r--include/asm-i386/ioctl.h86
-rw-r--r--include/asm-i386/irq.h2
-rw-r--r--include/asm-i386/kexec.h47
-rw-r--r--include/asm-i386/kprobes.h9
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h79
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apicdef.h4
-rw-r--r--include/asm-i386/mach-default/mach_ipi.h4
-rw-r--r--include/asm-i386/mman.h1
-rw-r--r--include/asm-i386/mmzone.h5
-rw-r--r--include/asm-i386/module.h4
-rw-r--r--include/asm-i386/mpspec_def.h2
-rw-r--r--include/asm-i386/mutex.h136
-rw-r--r--include/asm-i386/processor.h26
-rw-r--r--include/asm-i386/ptrace.h3
-rw-r--r--include/asm-i386/segment.h14
-rw-r--r--include/asm-i386/signal.h1
-rw-r--r--include/asm-i386/string.h8
-rw-r--r--include/asm-i386/system.h40
-rw-r--r--include/asm-i386/thread_info.h4
-rw-r--r--include/asm-i386/topology.h1
-rw-r--r--include/asm-i386/uaccess.h8
-rw-r--r--include/asm-i386/unistd.h21
-rw-r--r--include/asm-i386/vm86.h20
-rw-r--r--include/asm-ia64/atomic.h2
-rw-r--r--include/asm-ia64/bitops.h1
-rw-r--r--include/asm-ia64/bug.h6
-rw-r--r--include/asm-ia64/cache.h2
-rw-r--r--include/asm-ia64/compat.h2
-rw-r--r--include/asm-ia64/futex.h49
-rw-r--r--include/asm-ia64/io.h1
-rw-r--r--include/asm-ia64/ioctl.h78
-rw-r--r--include/asm-ia64/kprobes.h20
-rw-r--r--include/asm-ia64/mman.h1
-rw-r--r--include/asm-ia64/mutex.h9
-rw-r--r--include/asm-ia64/pal.h2
-rw-r--r--include/asm-ia64/processor.h6
-rw-r--r--include/asm-ia64/ptrace.h4
-rw-r--r--include/asm-ia64/sn/intr.h2
-rw-r--r--include/asm-ia64/sn/ioc3.h241
-rw-r--r--include/asm-ia64/sn/pcibr_provider.h48
-rw-r--r--include/asm-ia64/sn/pcibus_provider_defs.h14
-rw-r--r--include/asm-ia64/sn/pcidev.h4
-rw-r--r--include/asm-ia64/sn/pic.h204
-rw-r--r--include/asm-ia64/sn/shubio.h1620
-rw-r--r--include/asm-ia64/sn/sn_sal.h17
-rw-r--r--include/asm-ia64/sn/tioca.h82
-rw-r--r--include/asm-ia64/sn/tioca_provider.h56
-rw-r--r--include/asm-ia64/sn/tioce.h662
-rw-r--r--include/asm-ia64/sn/tioce_provider.h30
-rw-r--r--include/asm-ia64/sn/tiocp.h254
-rw-r--r--include/asm-ia64/sn/tiocx.h14
-rw-r--r--include/asm-ia64/sn/xp.h4
-rw-r--r--include/asm-ia64/sn/xpc.h (renamed from arch/ia64/sn/kernel/xpc.h)11
-rw-r--r--include/asm-ia64/spinlock.h2
-rw-r--r--include/asm-ia64/system.h9
-rw-r--r--include/asm-ia64/thread_info.h13
-rw-r--r--include/asm-ia64/topology.h2
-rw-r--r--include/asm-ia64/unistd.h5
-rw-r--r--include/asm-m32r/assembler.h10
-rw-r--r--include/asm-m32r/atomic.h2
-rw-r--r--include/asm-m32r/bitops.h1
-rw-r--r--include/asm-m32r/cache.h2
-rw-r--r--include/asm-m32r/cacheflush.h2
-rw-r--r--include/asm-m32r/futex.h49
-rw-r--r--include/asm-m32r/ioctl.h79
-rw-r--r--include/asm-m32r/irq.h16
-rw-r--r--include/asm-m32r/m32102.h38
-rw-r--r--include/asm-m32r/m32104ut/m32104ut_pld.h163
-rw-r--r--include/asm-m32r/m32r.h8
-rw-r--r--include/asm-m32r/mman.h1
-rw-r--r--include/asm-m32r/mutex.h9
-rw-r--r--include/asm-m32r/ptrace.h3
-rw-r--r--include/asm-m32r/system.h22
-rw-r--r--include/asm-m32r/thread_info.h2
-rw-r--r--include/asm-m32r/unistd.h12
-rw-r--r--include/asm-m68k/amigahw.h12
-rw-r--r--include/asm-m68k/amigaints.h2
-rw-r--r--include/asm-m68k/atomic.h2
-rw-r--r--include/asm-m68k/bitops.h1
-rw-r--r--include/asm-m68k/cache.h2
-rw-r--r--include/asm-m68k/checksum.h2
-rw-r--r--include/asm-m68k/dsp56k.h2
-rw-r--r--include/asm-m68k/floppy.h2
-rw-r--r--include/asm-m68k/futex.h49
-rw-r--r--include/asm-m68k/hardirq.h9
-rw-r--r--include/asm-m68k/io.h49
-rw-r--r--include/asm-m68k/ioctl.h81
-rw-r--r--include/asm-m68k/irq.h11
-rw-r--r--include/asm-m68k/machdep.h1
-rw-r--r--include/asm-m68k/mman.h1
-rw-r--r--include/asm-m68k/mutex.h9
-rw-r--r--include/asm-m68k/raw_io.h40
-rw-r--r--include/asm-m68k/signal.h2
-rw-r--r--include/asm-m68k/sun3_pgtable.h2
-rw-r--r--include/asm-m68k/sun3ints.h1
-rw-r--r--include/asm-m68k/sun3xflop.h4
-rw-r--r--include/asm-m68k/thread_info.h1
-rw-r--r--include/asm-m68k/uaccess.h20
-rw-r--r--include/asm-m68k/zorro.h8
-rw-r--r--include/asm-m68knommu/atomic.h2
-rw-r--r--include/asm-m68knommu/bitops.h3
-rw-r--r--include/asm-m68knommu/futex.h49
-rw-r--r--include/asm-m68knommu/ioctl.h2
-rw-r--r--include/asm-m68knommu/irq.h6
-rw-r--r--include/asm-m68knommu/machdep.h1
-rw-r--r--include/asm-m68knommu/mutex.h9
-rw-r--r--include/asm-m68knommu/sigcontext.h1
-rw-r--r--include/asm-m68knommu/thread_info.h2
-rw-r--r--include/asm-mips/.gitignore1
-rw-r--r--include/asm-mips/atomic.h45
-rw-r--r--include/asm-mips/bitops.h2
-rw-r--r--include/asm-mips/cache.h1
-rw-r--r--include/asm-mips/cpu-features.h21
-rw-r--r--include/asm-mips/cpu.h20
-rw-r--r--include/asm-mips/delay.h6
-rw-r--r--include/asm-mips/dsp.h4
-rw-r--r--include/asm-mips/elf.h4
-rw-r--r--include/asm-mips/hazards.h20
-rw-r--r--include/asm-mips/interrupt.h1
-rw-r--r--include/asm-mips/mach-au1x00/au1000.h7
-rw-r--r--include/asm-mips/mach-ip22/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-ip27/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-ip27/topology.h1
-rw-r--r--include/asm-mips/mach-ip32/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-ja/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-ocelot3/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-rm200/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mach-yosemite/cpu-feature-overrides.h5
-rw-r--r--include/asm-mips/mipsregs.h2
-rw-r--r--include/asm-mips/mman.h1
-rw-r--r--include/asm-mips/mutex.h9
-rw-r--r--include/asm-mips/processor.h11
-rw-r--r--include/asm-mips/riscos-syscall.h979
-rw-r--r--include/asm-mips/system.h12
-rw-r--r--include/asm-mips/thread_info.h2
-rw-r--r--include/asm-mips/vr41xx/capcella.h2
-rw-r--r--include/asm-mips/vr41xx/e55.h2
-rw-r--r--include/asm-mips/vr41xx/giu.h2
-rw-r--r--include/asm-mips/vr41xx/mpc30x.h2
-rw-r--r--include/asm-mips/vr41xx/pci.h2
-rw-r--r--include/asm-mips/vr41xx/siu.h2
-rw-r--r--include/asm-mips/vr41xx/tb0219.h2
-rw-r--r--include/asm-mips/vr41xx/tb0226.h2
-rw-r--r--include/asm-mips/vr41xx/vr41xx.h2
-rw-r--r--include/asm-mips/vr41xx/vrc4173.h2
-rw-r--r--include/asm-mips/vr41xx/workpad.h2
-rw-r--r--include/asm-parisc/atomic.h2
-rw-r--r--include/asm-parisc/bitops.h1
-rw-r--r--include/asm-parisc/cache.h9
-rw-r--r--include/asm-parisc/futex.h49
-rw-r--r--include/asm-parisc/io.h2
-rw-r--r--include/asm-parisc/mman.h1
-rw-r--r--include/asm-parisc/mutex.h9
-rw-r--r--include/asm-parisc/page.h7
-rw-r--r--include/asm-parisc/pci.h8
-rw-r--r--include/asm-parisc/processor.h18
-rw-r--r--include/asm-parisc/system.h9
-rw-r--r--include/asm-parisc/thread_info.h3
-rw-r--r--include/asm-parisc/tlbflush.h1
-rw-r--r--include/asm-powerpc/abs_addr.h2
-rw-r--r--include/asm-powerpc/agp.h2
-rw-r--r--include/asm-powerpc/asm-compat.h3
-rw-r--r--include/asm-powerpc/atomic.h48
-rw-r--r--include/asm-powerpc/bitops.h7
-rw-r--r--include/asm-powerpc/bootx.h171
-rw-r--r--include/asm-powerpc/btext.h19
-rw-r--r--include/asm-powerpc/bug.h2
-rw-r--r--include/asm-powerpc/cache.h1
-rw-r--r--include/asm-powerpc/checksum.h2
-rw-r--r--include/asm-powerpc/compat.h2
-rw-r--r--include/asm-powerpc/cputable.h40
-rw-r--r--include/asm-powerpc/current.h2
-rw-r--r--include/asm-powerpc/delay.h2
-rw-r--r--include/asm-powerpc/dma-mapping.h4
-rw-r--r--include/asm-powerpc/dma.h2
-rw-r--r--include/asm-powerpc/eeh.h23
-rw-r--r--include/asm-powerpc/eeh_event.h9
-rw-r--r--include/asm-powerpc/elf.h20
-rw-r--r--include/asm-powerpc/firmware.h6
-rw-r--r--include/asm-powerpc/floppy.h2
-rw-r--r--include/asm-powerpc/futex.h2
-rw-r--r--include/asm-powerpc/grackle.h5
-rw-r--r--include/asm-powerpc/hardirq.h2
-rw-r--r--include/asm-powerpc/heathrow.h5
-rw-r--r--include/asm-powerpc/hvcall.h7
-rw-r--r--include/asm-powerpc/hvconsole.h2
-rw-r--r--include/asm-powerpc/hvcserver.h2
-rw-r--r--include/asm-powerpc/i8259.h2
-rw-r--r--include/asm-powerpc/ibmebus.h85
-rw-r--r--include/asm-powerpc/io.h6
-rw-r--r--include/asm-powerpc/iommu.h27
-rw-r--r--include/asm-powerpc/ipic.h (renamed from include/asm-ppc/ipic.h)0
-rw-r--r--include/asm-powerpc/iseries/hv_call.h4
-rw-r--r--include/asm-powerpc/iseries/hv_call_event.h134
-rw-r--r--include/asm-powerpc/iseries/hv_call_sc.h1
-rw-r--r--include/asm-powerpc/iseries/hv_lp_config.h1
-rw-r--r--include/asm-powerpc/iseries/hv_lp_event.h42
-rw-r--r--include/asm-powerpc/iseries/hv_types.h1
-rw-r--r--include/asm-powerpc/iseries/iseries_io.h14
-rw-r--r--include/asm-powerpc/iseries/it_exp_vpd_panel.h1
-rw-r--r--include/asm-powerpc/iseries/it_lp_naca.h22
-rw-r--r--include/asm-powerpc/iseries/it_lp_queue.h1
-rw-r--r--include/asm-powerpc/iseries/it_lp_reg_save.h5
-rw-r--r--include/asm-powerpc/iseries/lpar_map.h1
-rw-r--r--include/asm-powerpc/iseries/mf.h1
-rw-r--r--include/asm-powerpc/iseries/vio.h1
-rw-r--r--include/asm-powerpc/kdebug.h2
-rw-r--r--include/asm-powerpc/kdump.h13
-rw-r--r--include/asm-powerpc/kexec.h91
-rw-r--r--include/asm-powerpc/keylargo.h15
-rw-r--r--include/asm-powerpc/kprobes.h16
-rw-r--r--include/asm-powerpc/lmb.h2
-rw-r--r--include/asm-powerpc/lppaca.h8
-rw-r--r--include/asm-powerpc/machdep.h12
-rw-r--r--include/asm-powerpc/macio.h2
-rw-r--r--include/asm-powerpc/mman.h1
-rw-r--r--include/asm-powerpc/mmu.h9
-rw-r--r--include/asm-powerpc/mmu_context.h2
-rw-r--r--include/asm-powerpc/mmzone.h2
-rw-r--r--include/asm-powerpc/module.h2
-rw-r--r--include/asm-powerpc/mpic.h6
-rw-r--r--include/asm-powerpc/mutex.h9
-rw-r--r--include/asm-powerpc/numnodes.h2
-rw-r--r--include/asm-powerpc/nvram.h4
-rw-r--r--include/asm-powerpc/of_device.h2
-rw-r--r--include/asm-powerpc/ohare.h6
-rw-r--r--include/asm-powerpc/oprofile_impl.h33
-rw-r--r--include/asm-powerpc/pSeries_reconfig.h2
-rw-r--r--include/asm-powerpc/paca.h36
-rw-r--r--include/asm-powerpc/page.h34
-rw-r--r--include/asm-powerpc/page_32.h2
-rw-r--r--include/asm-powerpc/page_64.h12
-rw-r--r--include/asm-powerpc/param.h2
-rw-r--r--include/asm-powerpc/parport.h30
-rw-r--r--include/asm-powerpc/pci-bridge.h35
-rw-r--r--include/asm-powerpc/pci.h2
-rw-r--r--include/asm-powerpc/percpu.h56
-rw-r--r--include/asm-powerpc/pgalloc.h2
-rw-r--r--include/asm-powerpc/pgtable-64k.h6
-rw-r--r--include/asm-powerpc/pgtable.h13
-rw-r--r--include/asm-powerpc/pmac_feature.h25
-rw-r--r--include/asm-powerpc/pmac_low_i2c.h92
-rw-r--r--include/asm-powerpc/pmac_pfunc.h253
-rw-r--r--include/asm-powerpc/pmc.h2
-rw-r--r--include/asm-powerpc/ppc-pci.h25
-rw-r--r--include/asm-powerpc/ppc_asm.h79
-rw-r--r--include/asm-powerpc/processor.h5
-rw-r--r--include/asm-powerpc/prom.h79
-rw-r--r--include/asm-powerpc/ptrace.h2
-rw-r--r--include/asm-powerpc/reg.h58
-rw-r--r--include/asm-powerpc/rtas.h3
-rw-r--r--include/asm-powerpc/seccomp.h4
-rw-r--r--include/asm-powerpc/sections.h2
-rw-r--r--include/asm-powerpc/serial.h6
-rw-r--r--include/asm-powerpc/signal.h7
-rw-r--r--include/asm-powerpc/smu.h40
-rw-r--r--include/asm-powerpc/sparsemem.h10
-rw-r--r--include/asm-powerpc/spinlock.h23
-rw-r--r--include/asm-powerpc/spu.h600
-rw-r--r--include/asm-powerpc/spu_csa.h255
-rw-r--r--include/asm-powerpc/synch.h25
-rw-r--r--include/asm-powerpc/system.h29
-rw-r--r--include/asm-powerpc/tce.h2
-rw-r--r--include/asm-powerpc/thread_info.h18
-rw-r--r--include/asm-powerpc/time.h5
-rw-r--r--include/asm-powerpc/tlb.h2
-rw-r--r--include/asm-powerpc/topology.h7
-rw-r--r--include/asm-powerpc/udbg.h26
-rw-r--r--include/asm-powerpc/unistd.h8
-rw-r--r--include/asm-powerpc/vdso_datapage.h2
-rw-r--r--include/asm-powerpc/vio.h2
-rw-r--r--include/asm-ppc/bseip.h38
-rw-r--r--include/asm-ppc/btext.h2
-rw-r--r--include/asm-ppc/ibm_ocp.h1
-rw-r--r--include/asm-ppc/io.h2
-rw-r--r--include/asm-ppc/machdep.h4
-rw-r--r--include/asm-ppc/mpc52xx.h13
-rw-r--r--include/asm-ppc/mpc85xx.h4
-rw-r--r--include/asm-ppc/pci-bridge.h9
-rw-r--r--include/asm-ppc/prom.h40
-rw-r--r--include/asm-ppc/system.h22
-rw-r--r--include/asm-s390/atomic.h176
-rw-r--r--include/asm-s390/bitops.h1
-rw-r--r--include/asm-s390/cache.h1
-rw-r--r--include/asm-s390/ccwdev.h3
-rw-r--r--include/asm-s390/elf.h2
-rw-r--r--include/asm-s390/futex.h49
-rw-r--r--include/asm-s390/ioctl.h89
-rw-r--r--include/asm-s390/kexec.h5
-rw-r--r--include/asm-s390/mman.h1
-rw-r--r--include/asm-s390/mutex.h9
-rw-r--r--include/asm-s390/processor.h8
-rw-r--r--include/asm-s390/qdio.h8
-rw-r--r--include/asm-s390/s390_rdev.h15
-rw-r--r--include/asm-s390/sigcontext.h2
-rw-r--r--include/asm-s390/system.h15
-rw-r--r--include/asm-s390/thread_info.h2
-rw-r--r--include/asm-s390/uaccess.h14
-rw-r--r--include/asm-s390/unistd.h2
-rw-r--r--include/asm-s390/vtoc.h24
-rw-r--r--include/asm-sh/atomic.h3
-rw-r--r--include/asm-sh/bitops.h1
-rw-r--r--include/asm-sh/bus-sh.h1
-rw-r--r--include/asm-sh/cache.h2
-rw-r--r--include/asm-sh/clock.h61
-rw-r--r--include/asm-sh/cpu-sh3/dma.h31
-rw-r--r--include/asm-sh/cpu-sh4/dma.h52
-rw-r--r--include/asm-sh/cpu-sh4/freq.h2
-rw-r--r--include/asm-sh/dma-mapping.h25
-rw-r--r--include/asm-sh/dma.h14
-rw-r--r--include/asm-sh/freq.h11
-rw-r--r--include/asm-sh/futex.h49
-rw-r--r--include/asm-sh/io.h283
-rw-r--r--include/asm-sh/io_generic.h96
-rw-r--r--include/asm-sh/ioctl.h76
-rw-r--r--include/asm-sh/irq-sh7780.h349
-rw-r--r--include/asm-sh/irq.h143
-rw-r--r--include/asm-sh/kexec.h33
-rw-r--r--include/asm-sh/machvec.h66
-rw-r--r--include/asm-sh/mman.h1
-rw-r--r--include/asm-sh/mutex.h9
-rw-r--r--include/asm-sh/ptrace.h10
-rw-r--r--include/asm-sh/system.h10
-rw-r--r--include/asm-sh/thread_info.h2
-rw-r--r--include/asm-sh/timer.h42
-rw-r--r--include/asm-sh64/atomic.h3
-rw-r--r--include/asm-sh64/bitops.h1
-rw-r--r--include/asm-sh64/cache.h2
-rw-r--r--include/asm-sh64/futex.h49
-rw-r--r--include/asm-sh64/io.h8
-rw-r--r--include/asm-sh64/ioctl.h84
-rw-r--r--include/asm-sh64/mmu_context.h2
-rw-r--r--include/asm-sh64/mutex.h9
-rw-r--r--include/asm-sh64/pgalloc.h14
-rw-r--r--include/asm-sh64/pgtable.h24
-rw-r--r--include/asm-sh64/processor.h4
-rw-r--r--include/asm-sh64/system.h4
-rw-r--r--include/asm-sh64/thread_info.h2
-rw-r--r--include/asm-sh64/tlbflush.h2
-rw-r--r--include/asm-sh64/uaccess.h2
-rw-r--r--include/asm-sparc/atomic.h2
-rw-r--r--include/asm-sparc/bitops.h1
-rw-r--r--include/asm-sparc/cache.h1
-rw-r--r--include/asm-sparc/futex.h49
-rw-r--r--include/asm-sparc/mman.h1
-rw-r--r--include/asm-sparc/mutex.h9
-rw-r--r--include/asm-sparc/system.h12
-rw-r--r--include/asm-sparc/thread_info.h3
-rw-r--r--include/asm-sparc64/atomic.h2
-rw-r--r--include/asm-sparc64/bitops.h1
-rw-r--r--include/asm-sparc64/cache.h1
-rw-r--r--include/asm-sparc64/elf.h2
-rw-r--r--include/asm-sparc64/futex.h49
-rw-r--r--include/asm-sparc64/kprobes.h10
-rw-r--r--include/asm-sparc64/mman.h1
-rw-r--r--include/asm-sparc64/mmu_context.h2
-rw-r--r--include/asm-sparc64/mutex.h9
-rw-r--r--include/asm-sparc64/oplib.h2
-rw-r--r--include/asm-sparc64/processor.h5
-rw-r--r--include/asm-sparc64/system.h18
-rw-r--r--include/asm-um/cache.h3
-rw-r--r--include/asm-um/futex.h12
-rw-r--r--include/asm-um/io.h16
-rw-r--r--include/asm-um/mutex.h9
-rw-r--r--include/asm-um/processor-generic.h1
-rw-r--r--include/asm-um/rwsem.h4
-rw-r--r--include/asm-um/thread_info.h16
-rw-r--r--include/asm-um/unistd.h1
-rw-r--r--include/asm-v850/atomic.h3
-rw-r--r--include/asm-v850/bitops.h1
-rw-r--r--include/asm-v850/cache.h2
-rw-r--r--include/asm-v850/futex.h49
-rw-r--r--include/asm-v850/ioctl.h81
-rw-r--r--include/asm-v850/mman.h1
-rw-r--r--include/asm-v850/mutex.h9
-rw-r--r--include/asm-v850/processor.h8
-rw-r--r--include/asm-v850/ptrace.h2
-rw-r--r--include/asm-v850/thread_info.h2
-rw-r--r--include/asm-v850/unistd.h18
-rw-r--r--include/asm-x86_64/apic.h17
-rw-r--r--include/asm-x86_64/apicdef.h1
-rw-r--r--include/asm-x86_64/atomic.h3
-rw-r--r--include/asm-x86_64/bitops.h70
-rw-r--r--include/asm-x86_64/cache.h13
-rw-r--r--include/asm-x86_64/cacheflush.h4
-rw-r--r--include/asm-x86_64/compat.h7
-rw-r--r--include/asm-x86_64/cpufeature.h3
-rw-r--r--include/asm-x86_64/desc.h18
-rw-r--r--include/asm-x86_64/dma-mapping.h221
-rw-r--r--include/asm-x86_64/dwarf2.h4
-rw-r--r--include/asm-x86_64/e820.h1
-rw-r--r--include/asm-x86_64/edac.h18
-rw-r--r--include/asm-x86_64/fixmap.h2
-rw-r--r--include/asm-x86_64/gart-mapping.h16
-rw-r--r--include/asm-x86_64/hw_irq.h10
-rw-r--r--include/asm-x86_64/i387.h68
-rw-r--r--include/asm-x86_64/ia32.h2
-rw-r--r--include/asm-x86_64/ia32_unistd.h16
-rw-r--r--include/asm-x86_64/idle.h14
-rw-r--r--include/asm-x86_64/io.h5
-rw-r--r--include/asm-x86_64/ioctl.h76
-rw-r--r--include/asm-x86_64/ipi.h4
-rw-r--r--include/asm-x86_64/irq.h2
-rw-r--r--include/asm-x86_64/kdebug.h13
-rw-r--r--include/asm-x86_64/kexec.h37
-rw-r--r--include/asm-x86_64/kprobes.h4
-rw-r--r--include/asm-x86_64/mman.h1
-rw-r--r--include/asm-x86_64/mmu_context.h9
-rw-r--r--include/asm-x86_64/mmzone.h16
-rw-r--r--include/asm-x86_64/mpspec.h2
-rw-r--r--include/asm-x86_64/mutex.h113
-rw-r--r--include/asm-x86_64/numa.h5
-rw-r--r--include/asm-x86_64/page.h22
-rw-r--r--include/asm-x86_64/pci.h11
-rw-r--r--include/asm-x86_64/pda.h11
-rw-r--r--include/asm-x86_64/percpu.h2
-rw-r--r--include/asm-x86_64/pgtable.h34
-rw-r--r--include/asm-x86_64/processor.h21
-rw-r--r--include/asm-x86_64/proto.h15
-rw-r--r--include/asm-x86_64/segment.h4
-rw-r--r--include/asm-x86_64/smp.h1
-rw-r--r--include/asm-x86_64/swiotlb.h16
-rw-r--r--include/asm-x86_64/system.h59
-rw-r--r--include/asm-x86_64/thread_info.h3
-rw-r--r--include/asm-x86_64/timex.h16
-rw-r--r--include/asm-x86_64/topology.h1
-rw-r--r--include/asm-x86_64/uaccess.h7
-rw-r--r--include/asm-x86_64/unistd.h31
-rw-r--r--include/asm-x86_64/vsyscall.h4
-rw-r--r--include/asm-xtensa/atomic.h2
-rw-r--r--include/asm-xtensa/bitops.h1
-rw-r--r--include/asm-xtensa/ioctl.h84
-rw-r--r--include/asm-xtensa/mman.h1
-rw-r--r--include/asm-xtensa/mutex.h9
-rw-r--r--include/asm-xtensa/processor.h6
-rw-r--r--include/asm-xtensa/ptrace.h4
-rw-r--r--include/asm-xtensa/thread_info.h2
-rw-r--r--include/keys/user-type.h1
-rw-r--r--include/linux/aio.h12
-rw-r--r--include/linux/amba/bus.h (renamed from include/asm-arm/hardware/amba.h)0
-rw-r--r--include/linux/amba/clcd.h (renamed from include/asm-arm/hardware/amba_clcd.h)0
-rw-r--r--include/linux/amba/kmi.h (renamed from include/asm-arm/hardware/amba_kmi.h)0
-rw-r--r--include/linux/amba/serial.h (renamed from include/asm-arm/hardware/amba_serial.h)0
-rw-r--r--include/linux/ata.h8
-rw-r--r--include/linux/atalk.h18
-rw-r--r--include/linux/auxvec.h2
-rw-r--r--include/linux/bio.h2
-rw-r--r--include/linux/bitops.h9
-rw-r--r--include/linux/blkdev.h118
-rw-r--r--include/linux/bootmem.h46
-rw-r--r--include/linux/buffer_head.h3
-rw-r--r--include/linux/byteorder/generic.h2
-rw-r--r--include/linux/byteorder/swab.h2
-rw-r--r--include/linux/byteorder/swabb.h2
-rw-r--r--include/linux/cache.h19
-rw-r--r--include/linux/calc64.h49
-rw-r--r--include/linux/capability.h3
-rw-r--r--include/linux/clk.h (renamed from include/asm-arm/hardware/clock.h)30
-rw-r--r--include/linux/compat_ioctl.h34
-rw-r--r--include/linux/compiler-gcc.h17
-rw-r--r--include/linux/compiler-gcc2.h29
-rw-r--r--include/linux/compiler-gcc3.h18
-rw-r--r--include/linux/compiler-gcc4.h18
-rw-r--r--include/linux/compiler.h2
-rw-r--r--include/linux/configfs.h205
-rw-r--r--include/linux/cpufreq.h10
-rw-r--r--include/linux/cpuset.h46
-rw-r--r--include/linux/crypto.h5
-rw-r--r--include/linux/cycx_x25.h66
-rw-r--r--include/linux/dcache.h9
-rw-r--r--include/linux/dccp.h7
-rw-r--r--include/linux/device.h17
-rw-r--r--include/linux/dm-ioctl.h11
-rw-r--r--include/linux/dmi.h5
-rw-r--r--include/linux/dvb/frontend.h10
-rw-r--r--include/linux/elevator.h5
-rw-r--r--include/linux/elf.h2
-rw-r--r--include/linux/etherdevice.h3
-rw-r--r--include/linux/ext3_fs_i.h2
-rw-r--r--include/linux/fb.h10
-rw-r--r--include/linux/fcntl.h7
-rw-r--r--include/linux/filter.h2
-rw-r--r--include/linux/firmware.h2
-rw-r--r--include/linux/fs.h96
-rw-r--r--include/linux/fsl_devices.h6
-rw-r--r--include/linux/fuse.h24
-rw-r--r--include/linux/gfp.h5
-rw-r--r--include/linux/hardirq.h4
-rw-r--r--include/linux/hrtimer.h139
-rw-r--r--include/linux/hugetlb.h4
-rw-r--r--include/linux/hwmon-vid.h6
-rw-r--r--include/linux/i2c-id.h25
-rw-r--r--include/linux/i2c.h41
-rw-r--r--include/linux/i2o.h976
-rw-r--r--include/linux/ide.h12
-rw-r--r--include/linux/if_ether.h1
-rw-r--r--include/linux/if_frad.h12
-rw-r--r--include/linux/if_pppox.h3
-rw-r--r--include/linux/inet.h2
-rw-r--r--include/linux/init.h12
-rw-r--r--include/linux/input.h79
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--include/linux/ioc3.h93
-rw-r--r--include/linux/ip.h131
-rw-r--r--include/linux/ipv6.h83
-rw-r--r--include/linux/irq.h13
-rw-r--r--include/linux/isdnif.h70
-rw-r--r--include/linux/isicom.h59
-rw-r--r--include/linux/jbd.h8
-rw-r--r--include/linux/jffs2_fs_i.h4
-rw-r--r--include/linux/jiffies.h18
-rw-r--r--include/linux/kbd_kern.h2
-rw-r--r--include/linux/kernel.h18
-rw-r--r--include/linux/kexec.h5
-rw-r--r--include/linux/key.h20
-rw-r--r--include/linux/keyctl.h3
-rw-r--r--include/linux/kobject.h54
-rw-r--r--include/linux/kobject_uevent.h57
-rw-r--r--include/linux/kprobes.h6
-rw-r--r--include/linux/ktime.h284
-rw-r--r--include/linux/libata.h35
-rw-r--r--include/linux/list.h14
-rw-r--r--include/linux/lockd/lockd.h2
-rw-r--r--include/linux/loop.h4
-rw-r--r--include/linux/memory.h8
-rw-r--r--include/linux/mempolicy.h96
-rw-r--r--include/linux/mm.h112
-rw-r--r--include/linux/mm_inline.h1
-rw-r--r--include/linux/mmc/card.h5
-rw-r--r--include/linux/mmc/mmc.h6
-rw-r--r--include/linux/mmzone.h64
-rw-r--r--include/linux/moduleparam.h2
-rw-r--r--include/linux/mount.h9
-rw-r--r--include/linux/msdos_fs.h3
-rw-r--r--include/linux/mutex-debug.h23
-rw-r--r--include/linux/mutex.h120
-rw-r--r--include/linux/namei.h9
-rw-r--r--include/linux/nbd.h8
-rw-r--r--include/linux/ncp.h126
-rw-r--r--include/linux/ncp_fs.h28
-rw-r--r--include/linux/net.h4
-rw-r--r--include/linux/netdevice.h11
-rw-r--r--include/linux/netfilter.h92
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h3
-rw-r--r--include/linux/netfilter/nfnetlink_conntrack.h5
-rw-r--r--include/linux/netfilter/x_tables.h224
-rw-r--r--include/linux/netfilter/xt_CLASSIFY.h8
-rw-r--r--include/linux/netfilter/xt_CONNMARK.h25
-rw-r--r--include/linux/netfilter/xt_MARK.h21
-rw-r--r--include/linux/netfilter/xt_NFQUEUE.h16
-rw-r--r--include/linux/netfilter/xt_comment.h10
-rw-r--r--include/linux/netfilter/xt_connbytes.h25
-rw-r--r--include/linux/netfilter/xt_connmark.h18
-rw-r--r--include/linux/netfilter/xt_conntrack.h63
-rw-r--r--include/linux/netfilter/xt_dccp.h23
-rw-r--r--include/linux/netfilter/xt_helper.h8
-rw-r--r--include/linux/netfilter/xt_length.h9
-rw-r--r--include/linux/netfilter/xt_limit.h21
-rw-r--r--include/linux/netfilter/xt_mac.h8
-rw-r--r--include/linux/netfilter/xt_mark.h9
-rw-r--r--include/linux/netfilter/xt_physdev.h24
-rw-r--r--include/linux/netfilter/xt_pkttype.h8
-rw-r--r--include/linux/netfilter/xt_realm.h10
-rw-r--r--include/linux/netfilter/xt_sctp.h107
-rw-r--r--include/linux/netfilter/xt_state.h13
-rw-r--r--include/linux/netfilter/xt_string.h18
-rw-r--r--include/linux/netfilter/xt_tcpmss.h9
-rw-r--r--include/linux/netfilter/xt_tcpudp.h36
-rw-r--r--include/linux/netfilter_arp/arp_tables.h123
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_nat_protocol.h7
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h217
-rw-r--r--include/linux/netfilter_ipv4/ipt_CLASSIFY.h5
-rw-r--r--include/linux/netfilter_ipv4/ipt_CONNMARK.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_MARK.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_NFQUEUE.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_comment.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_connbytes.h31
-rw-r--r--include/linux/netfilter_ipv4/ipt_connmark.h15
-rw-r--r--include/linux/netfilter_ipv4/ipt_conntrack.h66
-rw-r--r--include/linux/netfilter_ipv4/ipt_dccp.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_helper.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_length.h6
-rw-r--r--include/linux/netfilter_ipv4/ipt_limit.h19
-rw-r--r--include/linux/netfilter_ipv4/ipt_mac.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_mark.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_physdev.h27
-rw-r--r--include/linux/netfilter_ipv4/ipt_pkttype.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_policy.h52
-rw-r--r--include/linux/netfilter_ipv4/ipt_realm.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_state.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_string.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_tcpmss.h6
-rw-r--r--include/linux/netfilter_ipv6.h5
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h214
-rw-r--r--include/linux/netfilter_ipv6/ip6t_MARK.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_ah.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_esp.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_frag.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_length.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6t_limit.h21
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mac.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mark.h8
-rw-r--r--include/linux/netfilter_ipv6/ip6t_opts.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_physdev.h27
-rw-r--r--include/linux/netfilter_ipv6/ip6t_policy.h52
-rw-r--r--include/linux/netfilter_ipv6/ip6t_rt.h9
-rw-r--r--include/linux/nfs_fs.h65
-rw-r--r--include/linux/nfs_idmap.h2
-rw-r--r--include/linux/nfs_page.h12
-rw-r--r--include/linux/nfs_xdr.h89
-rw-r--r--include/linux/nfsd/nfsd.h2
-rw-r--r--include/linux/nfsd/nfsfh.h6
-rw-r--r--include/linux/nfsd/xdr.h3
-rw-r--r--include/linux/nfsd/xdr3.h1
-rw-r--r--include/linux/nfsd/xdr4.h5
-rw-r--r--include/linux/page-flags.h91
-rw-r--r--include/linux/pagevec.h5
-rw-r--r--include/linux/parport.h3
-rw-r--r--include/linux/parport_pc.h4
-rw-r--r--include/linux/pci.h69
-rw-r--r--include/linux/pci_ids.h52
-rw-r--r--include/linux/pci_regs.h1
-rw-r--r--include/linux/percpu.h8
-rw-r--r--include/linux/pfkeyv2.h15
-rw-r--r--include/linux/phy.h3
-rw-r--r--include/linux/pipe_fs_i.h2
-rw-r--r--include/linux/pkt_sched.h7
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/pmu.h8
-rw-r--r--include/linux/pnp.h9
-rw-r--r--include/linux/poll.h6
-rw-r--r--include/linux/posix-timers.h90
-rw-r--r--include/linux/proc_fs.h5
-rw-r--r--include/linux/ptrace.h4
-rw-r--r--include/linux/radix-tree.h1
-rw-r--r--include/linux/raid/md.h4
-rw-r--r--include/linux/raid/md_k.h80
-rw-r--r--include/linux/raid/raid1.h14
-rw-r--r--include/linux/raid/raid10.h22
-rw-r--r--include/linux/raid/raid5.h7
-rw-r--r--include/linux/raid_class.h2
-rw-r--r--include/linux/ramfs.h10
-rw-r--r--include/linux/random.h6
-rw-r--r--include/linux/rcupdate.h37
-rw-r--r--include/linux/rcuref.h220
-rw-r--r--include/linux/reiserfs_fs.h2
-rw-r--r--include/linux/relayfs_fs.h65
-rw-r--r--include/linux/rio_drv.h5
-rw-r--r--include/linux/rmap.h1
-rw-r--r--include/linux/rtc.h3
-rw-r--r--include/linux/sched.h99
-rw-r--r--include/linux/screen_info.h76
-rw-r--r--include/linux/sdla.h64
-rw-r--r--include/linux/seccomp.h6
-rw-r--r--include/linux/security.h132
-rw-r--r--include/linux/serial_core.h6
-rw-r--r--include/linux/shmem_fs.h2
-rw-r--r--include/linux/signal.h30
-rw-r--r--include/linux/skbuff.h9
-rw-r--r--include/linux/slab.h35
-rw-r--r--include/linux/smb_fs.h47
-rw-r--r--include/linux/socket.h4
-rw-r--r--include/linux/spi/ads7846.h18
-rw-r--r--include/linux/spi/flash.h31
-rw-r--r--include/linux/spi/spi.h668
-rw-r--r--include/linux/spi/spi_bitbang.h135
-rw-r--r--include/linux/spinlock.h3
-rw-r--r--include/linux/spinlock_types_up.h14
-rw-r--r--include/linux/sunrpc/clnt.h5
-rw-r--r--include/linux/sunrpc/gss_spkm3.h2
-rw-r--r--include/linux/sunrpc/sched.h48
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--include/linux/sunrpc/xdr.h6
-rw-r--r--include/linux/sunrpc/xprt.h12
-rw-r--r--include/linux/suspend.h8
-rw-r--r--include/linux/swap.h28
-rw-r--r--include/linux/synclink.h9
-rw-r--r--include/linux/syscalls.h24
-rw-r--r--include/linux/sysctl.h6
-rw-r--r--include/linux/tcp.h21
-rw-r--r--include/linux/time.h186
-rw-r--r--include/linux/timer.h2
-rw-r--r--include/linux/tipc.h212
-rw-r--r--include/linux/tipc_config.h410
-rw-r--r--include/linux/topology.h10
-rw-r--r--include/linux/tty.h97
-rw-r--r--include/linux/tty_flip.h20
-rw-r--r--include/linux/tty_ldisc.h9
-rw-r--r--include/linux/udf_fs.h5
-rw-r--r--include/linux/udf_fs_i.h5
-rw-r--r--include/linux/udf_fs_sb.h5
-rw-r--r--include/linux/udp.h6
-rw-r--r--include/linux/usb.h35
-rw-r--r--include/linux/usb_usual.h126
-rw-r--r--include/linux/video_decoder.h2
-rw-r--r--include/linux/videodev2.h16
-rw-r--r--include/linux/wavefront.h36
-rw-r--r--include/linux/workqueue.h1
-rw-r--r--include/linux/writeback.h19
-rw-r--r--include/linux/xattr.h19
-rw-r--r--include/linux/xfrm.h29
-rw-r--r--include/linux/zlib.h11
-rw-r--r--include/media/audiochip.h16
-rw-r--r--include/media/saa7146.h6
-rw-r--r--include/media/saa7146_vv.h2
-rw-r--r--include/media/tuner-types.h55
-rw-r--r--include/media/tuner.h109
-rw-r--r--include/media/v4l2-common.h91
-rw-r--r--include/net/act_api.h2
-rw-r--r--include/net/af_unix.h12
-rw-r--r--include/net/atmclip.h2
-rw-r--r--include/net/dn_dev.h84
-rw-r--r--include/net/dn_nsp.h74
-rw-r--r--include/net/dst.h12
-rw-r--r--include/net/flow.h7
-rw-r--r--include/net/genetlink.h3
-rw-r--r--include/net/icmp.h9
-rw-r--r--include/net/ieee80211.h6
-rw-r--r--include/net/ieee80211_crypt.h10
-rw-r--r--include/net/inet6_connection_sock.h42
-rw-r--r--include/net/inet6_hashtables.h32
-rw-r--r--include/net/inet_common.h4
-rw-r--r--include/net/inet_connection_sock.h47
-rw-r--r--include/net/inet_ecn.h2
-rw-r--r--include/net/inet_hashtables.h24
-rw-r--r--include/net/inet_sock.h193
-rw-r--r--include/net/inet_timewait_sock.h8
-rw-r--r--include/net/inetpeer.h1
-rw-r--r--include/net/ip.h28
-rw-r--r--include/net/ip_fib.h2
-rw-r--r--include/net/ip_vs.h12
-rw-r--r--include/net/ipv6.h14
-rw-r--r--include/net/iw_handler.h2
-rw-r--r--include/net/ndisc.h17
-rw-r--r--include/net/neighbour.h2
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h32
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h2
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h15
-rw-r--r--include/net/netfilter/nf_conntrack_protocol.h26
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h2
-rw-r--r--include/net/pkt_act.h1
-rw-r--r--include/net/pkt_sched.h23
-rw-r--r--include/net/protocol.h5
-rw-r--r--include/net/raw.h2
-rw-r--r--include/net/request_sock.h2
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/sctp/structs.h76
-rw-r--r--include/net/sctp/user.h30
-rw-r--r--include/net/sock.h36
-rw-r--r--include/net/tcp.h246
-rw-r--r--include/net/tcp_states.h16
-rw-r--r--include/net/timewait_sock.h31
-rw-r--r--include/net/tipc/tipc.h257
-rw-r--r--include/net/tipc/tipc_bearer.h121
-rw-r--r--include/net/tipc/tipc_msg.h223
-rw-r--r--include/net/tipc/tipc_port.h108
-rw-r--r--include/net/transp_v6.h2
-rw-r--r--include/net/udp.h4
-rw-r--r--include/net/xfrm.h39
-rw-r--r--include/pcmcia/cs.h2
-rw-r--r--include/pcmcia/ds.h13
-rw-r--r--include/pcmcia/ss.h4
-rw-r--r--include/rdma/ib_verbs.h2
-rw-r--r--include/scsi/iscsi_if.h6
-rw-r--r--include/scsi/scsi.h6
-rw-r--r--include/scsi/scsi_cmnd.h1
-rw-r--r--include/scsi/scsi_dbg.h1
-rw-r--r--include/scsi/scsi_device.h12
-rw-r--r--include/scsi/scsi_driver.h1
-rw-r--r--include/scsi/scsi_host.h10
-rw-r--r--include/scsi/scsi_transport.h7
-rw-r--r--include/scsi/scsi_transport_fc.h4
-rw-r--r--include/scsi/scsi_transport_iscsi.h75
-rw-r--r--include/scsi/scsi_transport_spi.h7
-rw-r--r--include/sound/ac97_codec.h169
-rw-r--r--include/sound/ad1816a.h22
-rw-r--r--include/sound/ad1848.h33
-rw-r--r--include/sound/ainstr_fm.h28
-rw-r--r--include/sound/ainstr_gf1.h46
-rw-r--r--include/sound/ainstr_iw.h115
-rw-r--r--include/sound/ainstr_simple.h35
-rw-r--r--include/sound/ak4114.h30
-rw-r--r--include/sound/ak4117.h24
-rw-r--r--include/sound/ak4531_codec.h17
-rw-r--r--include/sound/ak4xxx-adda.h22
-rw-r--r--include/sound/asequencer.h378
-rw-r--r--include/sound/asound.h566
-rw-r--r--include/sound/asound_fm.h24
-rw-r--r--include/sound/control.h94
-rw-r--r--include/sound/core.h226
-rw-r--r--include/sound/cs4231.h113
-rw-r--r--include/sound/cs46xx.h89
-rw-r--r--include/sound/cs46xx_dsp_scb_types.h145
-rw-r--r--include/sound/cs46xx_dsp_spos.h119
-rw-r--r--include/sound/cs46xx_dsp_task_types.h35
-rw-r--r--include/sound/cs8403.h8
-rw-r--r--include/sound/cs8427.h17
-rw-r--r--include/sound/driver.h7
-rw-r--r--include/sound/emu10k1.h371
-rw-r--r--include/sound/emu10k1_synth.h6
-rw-r--r--include/sound/emu8000.h39
-rw-r--r--include/sound/emux_synth.h105
-rw-r--r--include/sound/es1688.h22
-rw-r--r--include/sound/gus.h379
-rw-r--r--include/sound/hdsp.h51
-rw-r--r--include/sound/hdspm.h45
-rw-r--r--include/sound/hwdep.h43
-rw-r--r--include/sound/i2c.h78
-rw-r--r--include/sound/info.h107
-rw-r--r--include/sound/initval.h14
-rw-r--r--include/sound/minors.h29
-rw-r--r--include/sound/mixer_oss.h54
-rw-r--r--include/sound/mpu401.h26
-rw-r--r--include/sound/opl3.h57
-rw-r--r--include/sound/opl4.h6
-rw-r--r--include/sound/pcm-indirect.h28
-rw-r--r--include/sound/pcm.h476
-rw-r--r--include/sound/pcm_oss.h41
-rw-r--r--include/sound/pcm_params.h86
-rw-r--r--include/sound/rawmidi.h125
-rw-r--r--include/sound/sb.h74
-rw-r--r--include/sound/sb16_csp.h52
-rw-r--r--include/sound/seq_device.h18
-rw-r--r--include/sound/seq_instr.h64
-rw-r--r--include/sound/seq_kernel.h125
-rw-r--r--include/sound/seq_midi_emul.h44
-rw-r--r--include/sound/seq_midi_event.h22
-rw-r--r--include/sound/seq_oss.h30
-rw-r--r--include/sound/seq_virmidi.h22
-rw-r--r--include/sound/sfnt_info.h36
-rw-r--r--include/sound/snd_wavefront.h20
-rw-r--r--include/sound/soundfont.h75
-rw-r--r--include/sound/tea575x-tuner.h12
-rw-r--r--include/sound/tea6330t.h17
-rw-r--r--include/sound/timer.h94
-rw-r--r--include/sound/trident.h153
-rw-r--r--include/sound/typedefs.h173
-rw-r--r--include/sound/uda1341.h109
-rw-r--r--include/sound/util_mem.h32
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/vx_core.h131
-rw-r--r--include/sound/wavefront.h36
-rw-r--r--include/sound/ymfpci.h112
-rw-r--r--include/video/cyblafb.h4
-rw-r--r--include/video/kyro.h1
-rw-r--r--include/video/neomagic.h1
-rw-r--r--include/video/newport.h5
-rw-r--r--include/video/sstfb.h1
-rw-r--r--include/video/tdfx.h86
-rw-r--r--init/Kconfig84
-rw-r--r--init/do_mounts_md.c22
-rw-r--r--init/do_mounts_rd.c4
-rw-r--r--init/main.c34
-rw-r--r--ipc/mqueue.c68
-rw-r--r--ipc/msg.c3
-rw-r--r--ipc/sem.c3
-rw-r--r--ipc/shm.c41
-rw-r--r--ipc/util.c3
-rw-r--r--ipc/util.h2
-rw-r--r--kernel/.gitignore5
-rw-r--r--kernel/Makefile8
-rw-r--r--kernel/acct.c17
-rw-r--r--kernel/audit.c4
-rw-r--r--kernel/auditsc.c2
-rw-r--r--kernel/capability.c1
-rw-r--r--kernel/compat.c48
-rw-r--r--kernel/configs.c2
-rw-r--r--kernel/cpuset.c582
-rw-r--r--kernel/exit.c63
-rw-r--r--kernel/fork.c50
-rw-r--r--kernel/futex.c7
-rw-r--r--kernel/hrtimer.c826
-rw-r--r--kernel/irq/manage.c2
-rw-r--r--kernel/irq/proc.c6
-rw-r--r--kernel/itimer.c106
-rw-r--r--kernel/kexec.c21
-rw-r--r--kernel/kprobes.c137
-rw-r--r--kernel/ksysfs.c37
-rw-r--r--kernel/module.c60
-rw-r--r--kernel/mutex-debug.c462
-rw-r--r--kernel/mutex-debug.h134
-rw-r--r--kernel/mutex.c315
-rw-r--r--kernel/mutex.h35
-rw-r--r--kernel/panic.c4
-rw-r--r--kernel/pid.c22
-rw-r--r--kernel/posix-cpu-timers.c76
-rw-r--r--kernel/posix-timers.c895
-rw-r--r--kernel/power/Kconfig2
-rw-r--r--kernel/power/disk.c92
-rw-r--r--kernel/power/power.h24
-rw-r--r--kernel/power/snapshot.c89
-rw-r--r--kernel/power/swsusp.c1020
-rw-r--r--kernel/printk.c8
-rw-r--r--kernel/ptrace.c78
-rw-r--r--kernel/rcupdate.c135
-rw-r--r--kernel/rcutorture.c99
-rw-r--r--kernel/resource.c2
-rw-r--r--kernel/sched.c561
-rw-r--r--kernel/signal.c168
-rw-r--r--kernel/stop_machine.c6
-rw-r--r--kernel/sys.c75
-rw-r--r--kernel/sys_ni.c24
-rw-r--r--kernel/sysctl.c48
-rw-r--r--kernel/time.c118
-rw-r--r--kernel/timer.c58
-rw-r--r--kernel/uid16.c1
-rw-r--r--kernel/workqueue.c42
-rw-r--r--lib/Kconfig.debug43
-rw-r--r--lib/bitmap.c89
-rw-r--r--lib/dec_and_lock.c49
-rw-r--r--lib/find_next_bit.c3
-rw-r--r--lib/klist.c2
-rw-r--r--lib/kobject.c4
-rw-r--r--lib/kobject_uevent.c349
-rw-r--r--lib/radix-tree.c143
-rw-r--r--lib/spinlock_debug.c18
-rw-r--r--lib/swiotlb.c5
-rw-r--r--lib/zlib_deflate/deflate.c6
-rw-r--r--lib/zlib_deflate/deflate_syms.c2
-rw-r--r--lib/zlib_inflate/infblock.c4
-rw-r--r--lib/zlib_inflate/infblock.h4
-rw-r--r--lib/zlib_inflate/inflate_syms.c2
-rw-r--r--lib/zlib_inflate/inflate_sync.c4
-rw-r--r--mm/Kconfig9
-rw-r--r--mm/Makefile6
-rw-r--r--mm/bootmem.c58
-rw-r--r--mm/fadvise.c5
-rw-r--r--mm/filemap.c160
-rw-r--r--mm/filemap_xip.c8
-rw-r--r--mm/hugetlb.c194
-rw-r--r--mm/internal.h21
-rw-r--r--mm/madvise.c35
-rw-r--r--mm/memory.c34
-rw-r--r--mm/memory_hotplug.c1
-rw-r--r--mm/mempolicy.c692
-rw-r--r--mm/mlock.c1
-rw-r--r--mm/mmap.c1
-rw-r--r--mm/mremap.c1
-rw-r--r--mm/msync.c2
-rw-r--r--mm/nommu.c7
-rw-r--r--mm/oom_kill.c8
-rw-r--r--mm/page-writeback.c17
-rw-r--r--mm/page_alloc.c503
-rw-r--r--mm/pdflush.c2
-rw-r--r--mm/readahead.c15
-rw-r--r--mm/rmap.c74
-rw-r--r--mm/shmem.c81
-rw-r--r--mm/slab.c1194
-rw-r--r--mm/slob.c385
-rw-r--r--mm/sparse.c4
-rw-r--r--mm/swap.c55
-rw-r--r--mm/swap_state.c8
-rw-r--r--mm/swapfile.c60
-rw-r--r--mm/tiny-shmem.c29
-rw-r--r--mm/truncate.c45
-rw-r--r--mm/util.c39
-rw-r--r--mm/vmscan.c450
-rw-r--r--net/802/Makefile4
-rw-r--r--net/8021q/vlan.c1
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/appletalk/ddp.c24
-rw-r--r--net/atm/br2684.c7
-rw-r--r--net/atm/clip.c1
-rw-r--r--net/atm/ioctl.c1
-rw-r--r--net/atm/lec.c10
-rw-r--r--net/atm/mpc.c3
-rw-r--r--net/atm/pppoatm.c1
-rw-r--r--net/atm/pvc.c2
-rw-r--r--net/atm/raw.c1
-rw-r--r--net/atm/resources.c1
-rw-r--r--net/atm/svc.c2
-rw-r--r--net/ax25/af_ax25.c7
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/ax25/ax25_uid.c2
-rw-r--r--net/bluetooth/af_bluetooth.c5
-rw-r--r--net/bluetooth/bnep/core.c6
-rw-r--r--net/bluetooth/bnep/sock.c3
-rw-r--r--net/bluetooth/cmtp/sock.c3
-rw-r--r--net/bluetooth/hci_conn.c2
-rw-r--r--net/bluetooth/hci_sock.c3
-rw-r--r--net/bluetooth/hci_sysfs.c4
-rw-r--r--net/bluetooth/hidp/sock.c3
-rw-r--r--net/bluetooth/l2cap.c10
-rw-r--r--net/bluetooth/rfcomm/sock.c4
-rw-r--r--net/bluetooth/rfcomm/tty.c10
-rw-r--r--net/bluetooth/sco.c9
-rw-r--r--net/bridge/br.c1
-rw-r--r--net/bridge/br_device.c91
-rw-r--r--net/bridge/br_if.c60
-rw-r--r--net/bridge/br_input.c13
-rw-r--r--net/bridge/br_ioctl.c1
-rw-r--r--net/bridge/br_netfilter.c17
-rw-r--r--net/bridge/br_notify.c14
-rw-r--r--net/bridge/br_private.h7
-rw-r--r--net/bridge/br_stp_if.c5
-rw-r--r--net/bridge/br_sysfs_br.c1
-rw-r--r--net/bridge/br_sysfs_if.c5
-rw-r--r--net/bridge/netfilter/Kconfig6
-rw-r--r--net/bridge/netfilter/ebt_ip.c7
-rw-r--r--net/bridge/netfilter/ebt_log.c78
-rw-r--r--net/bridge/netfilter/ebt_stp.c5
-rw-r--r--net/bridge/netfilter/ebt_ulog.c53
-rw-r--r--net/bridge/netfilter/ebtables.c4
-rw-r--r--net/core/datagram.c36
-rw-r--r--net/core/dev.c14
-rw-r--r--net/core/dev_mcast.c2
-rw-r--r--net/core/dv.c3
-rw-r--r--net/core/ethtool.c1
-rw-r--r--net/core/filter.c139
-rw-r--r--net/core/flow.c8
-rw-r--r--net/core/net-sysfs.c105
-rw-r--r--net/core/netpoll.c3
-rw-r--r--net/core/pktgen.c52
-rw-r--r--net/core/scm.c1
-rw-r--r--net/core/skbuff.c42
-rw-r--r--net/core/sock.c22
-rw-r--r--net/core/stream.c10
-rw-r--r--net/core/utils.c4
-rw-r--r--net/core/wireless.c3
-rw-r--r--net/dccp/Makefile4
-rw-r--r--net/dccp/ackvec.c35
-rw-r--r--net/dccp/ackvec.h12
-rw-r--r--net/dccp/ccid.h2
-rw-r--r--net/dccp/dccp.h24
-rw-r--r--net/dccp/diag.c2
-rw-r--r--net/dccp/input.c79
-rw-r--r--net/dccp/ipv4.c306
-rw-r--r--net/dccp/ipv6.c1262
-rw-r--r--net/dccp/ipv6.h37
-rw-r--r--net/dccp/minisocks.c23
-rw-r--r--net/dccp/output.c47
-rw-r--r--net/dccp/proto.c56
-rw-r--r--net/decnet/af_decnet.c7
-rw-r--r--net/decnet/dn_dev.c1
-rw-r--r--net/decnet/dn_neigh.c13
-rw-r--r--net/decnet/dn_nsp_in.c17
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c2
-rw-r--r--net/econet/af_econet.c9
-rw-r--r--net/ethernet/eth.c7
-rw-r--r--net/ieee80211/ieee80211_crypt_wep.c61
-rw-r--r--net/ieee80211/ieee80211_module.c4
-rw-r--r--net/ieee80211/ieee80211_rx.c33
-rw-r--r--net/ieee80211/ieee80211_tx.c6
-rw-r--r--net/ieee80211/ieee80211_wx.c4
-rw-r--r--net/ipv4/Kconfig8
-rw-r--r--net/ipv4/Makefile5
-rw-r--r--net/ipv4/af_inet.c20
-rw-r--r--net/ipv4/ah4.c1
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/devinet.c2
-rw-r--r--net/ipv4/esp4.c1
-rw-r--r--net/ipv4/fib_frontend.c8
-rw-r--r--net/ipv4/fib_hash.c1
-rw-r--r--net/ipv4/fib_rules.c1
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/fib_trie.c8
-rw-r--r--net/ipv4/icmp.c4
-rw-r--r--net/ipv4/igmp.c169
-rw-r--r--net/ipv4/inet_connection_sock.c25
-rw-r--r--net/ipv4/inet_diag.c251
-rw-r--r--net/ipv4/inet_hashtables.c178
-rw-r--r--net/ipv4/inet_timewait_sock.c5
-rw-r--r--net/ipv4/inetpeer.c7
-rw-r--r--net/ipv4/ip_fragment.c70
-rw-r--r--net/ipv4/ip_gre.c40
-rw-r--r--net/ipv4/ip_input.c16
-rw-r--r--net/ipv4/ip_options.c2
-rw-r--r--net/ipv4/ip_output.c46
-rw-r--r--net/ipv4/ip_sockglue.c20
-rw-r--r--net/ipv4/ipcomp.c1
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/ipip.c23
-rw-r--r--net/ipv4/ipmr.c27
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c28
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c22
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c7
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c11
-rw-r--r--net/ipv4/ipvs/ip_vs_dh.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_est.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_lblc.c29
-rw-r--r--net/ipv4/ipvs/ip_vs_lblcr.c29
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_ah.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_esp.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c24
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c3
-rw-r--r--net/ipv4/ipvs/ip_vs_sched.c1
-rw-r--r--net/ipv4/ipvs/ip_vs_sh.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c2
-rw-r--r--net/ipv4/netfilter.c25
-rw-r--r--net/ipv4/netfilter/Kconfig256
-rw-r--r--net/ipv4/netfilter/Makefile23
-rw-r--r--net/ipv4/netfilter/arp_tables.c502
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c7
-rw-r--r--net/ipv4/netfilter/arptable_filter.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c36
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_generic.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c50
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c17
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c25
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c57
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c81
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c38
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c34
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c36
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c36
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_unknown.c16
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c126
-rw-r--r--net/ipv4/netfilter/ip_tables.c918
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c3
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c3
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c4
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c2
-rw-r--r--net/ipv4/netfilter/ipt_NFQUEUE.c70
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c5
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c2
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c2
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c12
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c4
-rw-r--r--net/ipv4/netfilter/ipt_ah.c6
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c4
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c5
-rw-r--r--net/ipv4/netfilter/ipt_esp.c6
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c3
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c4
-rw-r--r--net/ipv4/netfilter/ipt_length.c64
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c10
-rw-r--r--net/ipv4/netfilter/ipt_owner.c3
-rw-r--r--net/ipv4/netfilter/ipt_physdev.c134
-rw-r--r--net/ipv4/netfilter/ipt_policy.c173
-rw-r--r--net/ipv4/netfilter/ipt_recent.c26
-rw-r--r--net/ipv4/netfilter/ipt_tos.c3
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c3
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c83
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c97
-rw-r--r--net/ipv4/proc.c1
-rw-r--r--net/ipv4/raw.c3
-rw-r--r--net/ipv4/route.c15
-rw-r--r--net/ipv4/syncookies.c4
-rw-r--r--net/ipv4/sysctl_net_ipv4.c11
-rw-r--r--net/ipv4/tcp.c10
-rw-r--r--net/ipv4/tcp_bic.c85
-rw-r--r--net/ipv4/tcp_cong.c28
-rw-r--r--net/ipv4/tcp_cubic.c411
-rw-r--r--net/ipv4/tcp_input.c101
-rw-r--r--net/ipv4/tcp_ipv4.c270
-rw-r--r--net/ipv4/tcp_minisocks.c16
-rw-r--r--net/ipv4/tcp_output.c118
-rw-r--r--net/ipv4/tcp_vegas.c4
-rw-r--r--net/ipv4/udp.c24
-rw-r--r--net/ipv4/xfrm4_input.c31
-rw-r--r--net/ipv4/xfrm4_output.c72
-rw-r--r--net/ipv4/xfrm4_state.c15
-rw-r--r--net/ipv6/Makefile3
-rw-r--r--net/ipv6/addrconf.c7
-rw-r--r--net/ipv6/af_inet6.c95
-rw-r--r--net/ipv6/ah6.c4
-rw-r--r--net/ipv6/anycast.c5
-rw-r--r--net/ipv6/datagram.c1
-rw-r--r--net/ipv6/esp6.c4
-rw-r--r--net/ipv6/exthdrs.c23
-rw-r--r--net/ipv6/icmp.c6
-rw-r--r--net/ipv6/inet6_connection_sock.c200
-rw-r--r--net/ipv6/inet6_hashtables.c183
-rw-r--r--net/ipv6/ip6_flowlabel.c11
-rw-r--r--net/ipv6/ip6_input.c23
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/ip6_tunnel.c27
-rw-r--r--net/ipv6/ipcomp6.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c27
-rw-r--r--net/ipv6/mcast.c20
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter.c29
-rw-r--r--net/ipv6/netfilter/Kconfig74
-rw-r--r--net/ipv6/netfilter/Makefile8
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1019
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c8
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c81
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c5
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c155
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c5
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c68
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c159
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c155
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c81
-rw-r--r--net/ipv6/netfilter/ip6t_length.c66
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c147
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c80
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c66
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c3
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c28
-rw-r--r--net/ipv6/netfilter/ip6t_policy.c175
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c219
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c61
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c77
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c49
-rw-r--r--net/ipv6/raw.c16
-rw-r--r--net/ipv6/reassembly.c11
-rw-r--r--net/ipv6/route.c1
-rw-r--r--net/ipv6/sit.c26
-rw-r--r--net/ipv6/tcp_ipv6.c661
-rw-r--r--net/ipv6/udp.c18
-rw-r--r--net/ipv6/xfrm6_input.c21
-rw-r--r--net/ipv6/xfrm6_output.c76
-rw-r--r--net/ipv6/xfrm6_state.c17
-rw-r--r--net/ipv6/xfrm6_tunnel.c14
-rw-r--r--net/ipx/af_ipx.c7
-rw-r--r--net/irda/af_irda.c24
-rw-r--r--net/irda/irda_device.c1
-rw-r--r--net/irda/iriap.c2
-rw-r--r--net/irda/irias_object.c12
-rw-r--r--net/irda/irnet/irnet.h1
-rw-r--r--net/key/af_key.c205
-rw-r--r--net/llc/af_llc.c11
-rw-r--r--net/netfilter/Kconfig265
-rw-r--r--net/netfilter/Makefile40
-rw-r--r--net/netfilter/nf_conntrack_core.c239
-rw-r--r--net/netfilter/nf_conntrack_ftp.c6
-rw-r--r--net/netfilter/nf_conntrack_netlink.c1653
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c18
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c95
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c14
-rw-r--r--net/netfilter/nf_conntrack_standalone.c70
-rw-r--r--net/netfilter/nfnetlink.c2
-rw-r--r--net/netfilter/nfnetlink_log.c2
-rw-r--r--net/netfilter/nfnetlink_queue.c81
-rw-r--r--net/netfilter/x_tables.c624
-rw-r--r--net/netfilter/xt_CLASSIFY.c (renamed from net/ipv4/netfilter/ipt_CLASSIFY.c)41
-rw-r--r--net/netfilter/xt_CONNMARK.c (renamed from net/ipv4/netfilter/ipt_CONNMARK.c)51
-rw-r--r--net/netfilter/xt_MARK.c (renamed from net/ipv4/netfilter/ipt_MARK.c)79
-rw-r--r--net/netfilter/xt_NFQUEUE.c107
-rw-r--r--net/netfilter/xt_NOTRACK.c (renamed from net/ipv4/netfilter/ipt_NOTRACK.c)38
-rw-r--r--net/netfilter/xt_comment.c (renamed from net/ipv4/netfilter/ipt_comment.c)35
-rw-r--r--net/netfilter/xt_connbytes.c (renamed from net/ipv4/netfilter/ipt_connbytes.c)73
-rw-r--r--net/netfilter/xt_connmark.c (renamed from net/ipv4/netfilter/ipt_connmark.c)41
-rw-r--r--net/netfilter/xt_conntrack.c (renamed from net/ipv4/netfilter/ipt_conntrack.c)110
-rw-r--r--net/netfilter/xt_dccp.c (renamed from net/ipv4/netfilter/ipt_dccp.c)105
-rw-r--r--net/netfilter/xt_helper.c (renamed from net/ipv4/netfilter/ipt_helper.c)55
-rw-r--r--net/netfilter/xt_length.c99
-rw-r--r--net/netfilter/xt_limit.c (renamed from net/ipv4/netfilter/ipt_limit.c)48
-rw-r--r--net/netfilter/xt_mac.c (renamed from net/ipv4/netfilter/ipt_mac.c)43
-rw-r--r--net/netfilter/xt_mark.c (renamed from net/ipv4/netfilter/ipt_mark.c)38
-rw-r--r--net/netfilter/xt_physdev.c (renamed from net/ipv6/netfilter/ip6t_physdev.c)82
-rw-r--r--net/netfilter/xt_pkttype.c (renamed from net/ipv4/netfilter/ipt_pkttype.c)46
-rw-r--r--net/netfilter/xt_realm.c (renamed from net/ipv4/netfilter/ipt_realm.c)25
-rw-r--r--net/netfilter/xt_sctp.c (renamed from net/ipv4/netfilter/ipt_sctp.c)109
-rw-r--r--net/netfilter/xt_state.c (renamed from net/ipv4/netfilter/ipt_state.c)50
-rw-r--r--net/netfilter/xt_string.c (renamed from net/ipv4/netfilter/ipt_string.c)40
-rw-r--r--net/netfilter/xt_tcpmss.c (renamed from net/ipv4/netfilter/ipt_tcpmss.c)69
-rw-r--r--net/netfilter/xt_tcpudp.c334
-rw-r--r--net/netlink/af_netlink.c9
-rw-r--r--net/netlink/genetlink.c9
-rw-r--r--net/netrom/af_netrom.c17
-rw-r--r--net/nonet.c5
-rw-r--r--net/packet/af_packet.c13
-rw-r--r--net/rose/af_rose.c4
-rw-r--r--net/rxrpc/connection.c14
-rw-r--r--net/rxrpc/krxtimod.c2
-rw-r--r--net/rxrpc/proc.c12
-rw-r--r--net/sched/Kconfig4
-rw-r--r--net/sched/Makefile14
-rw-r--r--net/sched/act_api.c4
-rw-r--r--net/sched/act_gact.c (renamed from net/sched/gact.c)3
-rw-r--r--net/sched/act_ipt.c (renamed from net/sched/ipt.c)8
-rw-r--r--net/sched/act_mirred.c (renamed from net/sched/mirred.c)3
-rw-r--r--net/sched/act_pedit.c (renamed from net/sched/pedit.c)5
-rw-r--r--net/sched/act_police.c (renamed from net/sched/police.c)17
-rw-r--r--net/sched/act_simple.c (renamed from net/sched/simple.c)3
-rw-r--r--net/sched/ematch.c1
-rw-r--r--net/sched/sch_cbq.c4
-rw-r--r--net/sched/sch_hfsc.c12
-rw-r--r--net/sched/sch_htb.c4
-rw-r--r--net/sched/sch_netem.c49
-rw-r--r--net/sched/sch_prio.c14
-rw-r--r--net/sched/sch_sfq.c4
-rw-r--r--net/sched/sch_teql.c13
-rw-r--r--net/sctp/associola.c81
-rw-r--r--net/sctp/input.c37
-rw-r--r--net/sctp/ipv6.c28
-rw-r--r--net/sctp/output.c17
-rw-r--r--net/sctp/protocol.c3
-rw-r--r--net/sctp/sm_make_chunk.c2
-rw-r--r--net/sctp/sm_sideeffect.c29
-rw-r--r--net/sctp/sm_statefuns.c24
-rw-r--r--net/sctp/socket.c696
-rw-r--r--net/sctp/transport.c32
-rw-r--r--net/socket.c245
-rw-r--r--net/sunrpc/auth.c2
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c10
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c10
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_seal.c11
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_token.c3
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_unseal.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c38
-rw-r--r--net/sunrpc/auth_unix.c2
-rw-r--r--net/sunrpc/cache.c5
-rw-r--r--net/sunrpc/clnt.c114
-rw-r--r--net/sunrpc/pmap_clnt.c17
-rw-r--r--net/sunrpc/rpc_pipe.c69
-rw-r--r--net/sunrpc/sched.c222
-rw-r--r--net/sunrpc/sunrpc_syms.c4
-rw-r--r--net/sunrpc/svc.c9
-rw-r--r--net/sunrpc/svcauth_unix.c14
-rw-r--r--net/sunrpc/svcsock.c6
-rw-r--r--net/sunrpc/xdr.c21
-rw-r--r--net/sunrpc/xprt.c66
-rw-r--r--net/sunrpc/xprtsock.c31
-rw-r--r--net/tipc/Kconfig117
-rw-r--r--net/tipc/Makefile13
-rw-r--r--net/tipc/addr.c94
-rw-r--r--net/tipc/addr.h128
-rw-r--r--net/tipc/bcast.c806
-rw-r--r--net/tipc/bcast.h223
-rw-r--r--net/tipc/bearer.c699
-rw-r--r--net/tipc/bearer.h170
-rw-r--r--net/tipc/cluster.c576
-rw-r--r--net/tipc/cluster.h92
-rw-r--r--net/tipc/config.c718
-rw-r--r--net/tipc/config.h79
-rw-r--r--net/tipc/core.c284
-rw-r--r--net/tipc/core.h321
-rw-r--r--net/tipc/dbg.c395
-rw-r--r--net/tipc/dbg.h59
-rw-r--r--net/tipc/discover.c318
-rw-r--r--net/tipc/discover.h58
-rw-r--r--net/tipc/eth_media.c297
-rw-r--r--net/tipc/handler.c132
-rw-r--r--net/tipc/link.c3166
-rw-r--r--net/tipc/link.h295
-rw-r--r--net/tipc/msg.c323
-rw-r--r--net/tipc/msg.h818
-rw-r--r--net/tipc/name_distr.c309
-rw-r--r--net/tipc/name_distr.h48
-rw-r--r--net/tipc/name_table.c1079
-rw-r--r--net/tipc/name_table.h108
-rw-r--r--net/tipc/net.c311
-rw-r--r--net/tipc/net.h64
-rw-r--r--net/tipc/netlink.c112
-rw-r--r--net/tipc/node.c678
-rw-r--r--net/tipc/node.h144
-rw-r--r--net/tipc/node_subscr.c79
-rw-r--r--net/tipc/node_subscr.h63
-rw-r--r--net/tipc/port.c1708
-rw-r--r--net/tipc/port.h209
-rw-r--r--net/tipc/ref.c189
-rw-r--r--net/tipc/ref.h131
-rw-r--r--net/tipc/socket.c1724
-rw-r--r--net/tipc/subscr.c527
-rw-r--r--net/tipc/subscr.h80
-rw-r--r--net/tipc/user_reg.c265
-rw-r--r--net/tipc/user_reg.h48
-rw-r--r--net/tipc/zone.c169
-rw-r--r--net/tipc/zone.h71
-rw-r--r--net/unix/af_unix.c59
-rw-r--r--net/unix/garbage.c4
-rw-r--r--net/wanrouter/af_wanpipe.c7
-rw-r--r--net/wanrouter/wanmain.c1
-rw-r--r--net/x25/af_x25.c14
-rw-r--r--net/xfrm/xfrm_algo.c6
-rw-r--r--net/xfrm/xfrm_policy.c105
-rw-r--r--net/xfrm/xfrm_state.c9
-rw-r--r--net/xfrm/xfrm_user.c149
-rw-r--r--scripts/.gitignore5
-rw-r--r--scripts/Kbuild.include13
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.build4
-rw-r--r--scripts/Makefile.lib8
-rw-r--r--scripts/Makefile.modpost2
-rw-r--r--scripts/basic/fixdep.c15
-rw-r--r--scripts/binoffset.c2
-rw-r--r--scripts/bloat-o-meter58
-rwxr-xr-xscripts/checkversion.pl2
-rw-r--r--scripts/genksyms/.gitignore4
-rw-r--r--scripts/genksyms/keywords.c_shipped210
-rw-r--r--scripts/genksyms/lex.c_shipped168
-rw-r--r--scripts/genksyms/parse.c_shipped2924
-rw-r--r--scripts/genksyms/parse.h_shipped166
-rw-r--r--scripts/genksyms/parse.y1
-rw-r--r--scripts/kconfig/.gitignore1
-rw-r--r--scripts/kconfig/Makefile11
-rw-r--r--scripts/kconfig/conf.c18
-rw-r--r--scripts/kconfig/confdata.c2
-rw-r--r--scripts/kconfig/gconf.c2
-rw-r--r--scripts/kconfig/lxdialog/.gitignore4
-rw-r--r--scripts/kconfig/lxdialog/BIG.FAT.WARNING (renamed from scripts/lxdialog/BIG.FAT.WARNING)0
-rw-r--r--scripts/kconfig/lxdialog/Makefile18
-rw-r--r--scripts/kconfig/lxdialog/check-lxdialog.sh80
-rw-r--r--scripts/kconfig/lxdialog/checklist.c334
-rw-r--r--scripts/kconfig/lxdialog/colors.h (renamed from scripts/lxdialog/colors.h)1
-rw-r--r--scripts/kconfig/lxdialog/dialog.h (renamed from scripts/lxdialog/dialog.h)70
-rw-r--r--scripts/kconfig/lxdialog/inputbox.c224
-rw-r--r--scripts/kconfig/lxdialog/lxdialog.c204
-rw-r--r--scripts/kconfig/lxdialog/menubox.c425
-rw-r--r--scripts/kconfig/lxdialog/msgbox.c71
-rw-r--r--scripts/kconfig/lxdialog/textbox.c533
-rw-r--r--scripts/kconfig/lxdialog/util.c362
-rw-r--r--scripts/kconfig/lxdialog/yesno.c102
-rw-r--r--scripts/kconfig/mconf.c4
-rw-r--r--scripts/kconfig/qconf.h6
-rw-r--r--scripts/kconfig/symbol.c4
-rw-r--r--scripts/kconfig/util.c4
-rwxr-xr-xscripts/kernel-doc12
-rw-r--r--scripts/lxdialog/Makefile42
-rw-r--r--scripts/lxdialog/checklist.c373
-rw-r--r--scripts/lxdialog/inputbox.c240
-rw-r--r--scripts/lxdialog/lxdialog.c226
-rw-r--r--scripts/lxdialog/menubox.c445
-rw-r--r--scripts/lxdialog/msgbox.c85
-rw-r--r--scripts/lxdialog/textbox.c556
-rw-r--r--scripts/lxdialog/util.c359
-rw-r--r--scripts/lxdialog/yesno.c118
-rw-r--r--scripts/mksysmap2
-rw-r--r--scripts/mod/file2alias.c62
-rw-r--r--scripts/mod/modpost.c7
-rw-r--r--scripts/package/Makefile2
-rw-r--r--scripts/package/buildtar31
-rwxr-xr-xscripts/patch-kernel4
-rw-r--r--scripts/reference_discarded.pl6
-rw-r--r--scripts/setlocalversion68
-rw-r--r--security/Kconfig13
-rw-r--r--security/capability.c6
-rw-r--r--security/commoncap.c1
-rw-r--r--security/dummy.c46
-rw-r--r--security/inode.c8
-rw-r--r--security/keys/compat.c6
-rw-r--r--security/keys/internal.h6
-rw-r--r--security/keys/key.c58
-rw-r--r--security/keys/keyctl.c152
-rw-r--r--security/keys/keyring.c198
-rw-r--r--security/keys/permission.c32
-rw-r--r--security/keys/process_keys.c71
-rw-r--r--security/keys/request_key.c108
-rw-r--r--security/keys/request_key_auth.c192
-rw-r--r--security/keys/user_defined.c33
-rw-r--r--security/security.c1
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/avc.c5
-rw-r--r--security/selinux/hooks.c43
-rw-r--r--security/selinux/include/av_perm_to_string.h1
-rw-r--r--security/selinux/include/av_permissions.h1
-rw-r--r--security/selinux/include/xfrm.h54
-rw-r--r--security/selinux/selinuxfs.c6
-rw-r--r--security/selinux/ss/avtab.c2
-rw-r--r--security/selinux/ss/policydb.c2
-rw-r--r--security/selinux/ss/services.c6
-rw-r--r--security/selinux/xfrm.c305
-rw-r--r--sound/Kconfig8
-rw-r--r--sound/arm/Kconfig1
-rw-r--r--sound/arm/aaci.c86
-rw-r--r--sound/arm/aaci.h6
-rw-r--r--sound/arm/devdma.c12
-rw-r--r--sound/arm/devdma.h6
-rw-r--r--sound/arm/pxa2xx-ac97.c119
-rw-r--r--sound/arm/pxa2xx-pcm.c59
-rw-r--r--sound/arm/pxa2xx-pcm.h20
-rw-r--r--sound/arm/sa11xx-uda1341.c209
-rw-r--r--sound/core/Kconfig23
-rw-r--r--sound/core/control.c338
-rw-r--r--sound/core/control_compat.c73
-rw-r--r--sound/core/device.c47
-rw-r--r--sound/core/hwdep.c222
-rw-r--r--sound/core/hwdep_compat.c15
-rw-r--r--sound/core/info.c123
-rw-r--r--sound/core/info_oss.c11
-rw-r--r--sound/core/init.c334
-rw-r--r--sound/core/memalloc.c4
-rw-r--r--sound/core/oss/copy.c16
-rw-r--r--sound/core/oss/io.c28
-rw-r--r--sound/core/oss/linear.c38
-rw-r--r--sound/core/oss/mixer_oss.c256
-rw-r--r--sound/core/oss/mulaw.c54
-rw-r--r--sound/core/oss/pcm_oss.c391
-rw-r--r--sound/core/oss/pcm_plugin.c164
-rw-r--r--sound/core/oss/pcm_plugin.h286
-rw-r--r--sound/core/oss/rate.c85
-rw-r--r--sound/core/oss/route.c158
-rw-r--r--sound/core/pcm.c454
-rw-r--r--sound/core/pcm_compat.c110
-rw-r--r--sound/core/pcm_lib.c327
-rw-r--r--sound/core/pcm_memory.c82
-rw-r--r--sound/core/pcm_misc.c2
-rw-r--r--sound/core/pcm_native.c720
-rw-r--r--sound/core/pcm_timer.c30
-rw-r--r--sound/core/rawmidi.c387
-rw-r--r--sound/core/rawmidi_compat.c22
-rw-r--r--sound/core/rtctimer.c22
-rw-r--r--sound/core/seq/instr/ainstr_fm.c26
-rw-r--r--sound/core/seq/instr/ainstr_gf1.c76
-rw-r--r--sound/core/seq/instr/ainstr_iw.c146
-rw-r--r--sound/core/seq/instr/ainstr_simple.c50
-rw-r--r--sound/core/seq/oss/seq_oss.c43
-rw-r--r--sound/core/seq/oss/seq_oss_device.h60
-rw-r--r--sound/core/seq/oss/seq_oss_event.c60
-rw-r--r--sound/core/seq/oss/seq_oss_event.h50
-rw-r--r--sound/core/seq/oss/seq_oss_init.c74
-rw-r--r--sound/core/seq/oss/seq_oss_ioctl.c12
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c99
-rw-r--r--sound/core/seq/oss/seq_oss_midi.h27
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c34
-rw-r--r--sound/core/seq/oss/seq_oss_readq.h24
-rw-r--r--sound/core/seq/oss/seq_oss_rw.c18
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c95
-rw-r--r--sound/core/seq/oss/seq_oss_synth.h32
-rw-r--r--sound/core/seq/oss/seq_oss_timer.c34
-rw-r--r--sound/core/seq/oss/seq_oss_timer.h22
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.c34
-rw-r--r--sound/core/seq/oss/seq_oss_writeq.h18
-rw-r--r--sound/core/seq/seq.c4
-rw-r--r--sound/core/seq/seq_clientmgr.c529
-rw-r--r--sound/core/seq/seq_clientmgr.h41
-rw-r--r--sound/core/seq/seq_compat.c22
-rw-r--r--sound/core/seq/seq_device.c128
-rw-r--r--sound/core/seq/seq_dummy.c42
-rw-r--r--sound/core/seq/seq_fifo.c40
-rw-r--r--sound/core/seq/seq_fifo.h26
-rw-r--r--sound/core/seq/seq_info.c26
-rw-r--r--sound/core/seq/seq_info.h12
-rw-r--r--sound/core/seq/seq_instr.c162
-rw-r--r--sound/core/seq/seq_memory.c75
-rw-r--r--sound/core/seq/seq_memory.h37
-rw-r--r--sound/core/seq/seq_midi.c132
-rw-r--r--sound/core/seq/seq_midi_emul.c86
-rw-r--r--sound/core/seq/seq_midi_event.c98
-rw-r--r--sound/core/seq/seq_ports.c152
-rw-r--r--sound/core/seq/seq_ports.h64
-rw-r--r--sound/core/seq/seq_prioq.c52
-rw-r--r--sound/core/seq/seq_prioq.h26
-rw-r--r--sound/core/seq/seq_queue.c108
-rw-r--r--sound/core/seq/seq_queue.h22
-rw-r--r--sound/core/seq/seq_system.c34
-rw-r--r--sound/core/seq/seq_system.h2
-rw-r--r--sound/core/seq/seq_timer.c71
-rw-r--r--sound/core/seq/seq_timer.h54
-rw-r--r--sound/core/seq/seq_virmidi.c124
-rw-r--r--sound/core/sound.c238
-rw-r--r--sound/core/sound_oss.c138
-rw-r--r--sound/core/timer.c407
-rw-r--r--sound/core/timer_compat.c22
-rw-r--r--sound/drivers/Kconfig16
-rw-r--r--sound/drivers/dummy.c364
-rw-r--r--sound/drivers/mpu401/mpu401.c108
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c78
-rw-r--r--sound/drivers/mtpav.c306
-rw-r--r--sound/drivers/opl3/opl3_drums.c45
-rw-r--r--sound/drivers/opl3/opl3_lib.c90
-rw-r--r--sound/drivers/opl3/opl3_midi.c75
-rw-r--r--sound/drivers/opl3/opl3_oss.c68
-rw-r--r--sound/drivers/opl3/opl3_seq.c65
-rw-r--r--sound/drivers/opl3/opl3_synth.c50
-rw-r--r--sound/drivers/opl3/opl3_voice.h24
-rw-r--r--sound/drivers/opl4/opl4_lib.c40
-rw-r--r--sound/drivers/opl4/opl4_local.h68
-rw-r--r--sound/drivers/opl4/opl4_mixer.c16
-rw-r--r--sound/drivers/opl4/opl4_proc.c24
-rw-r--r--sound/drivers/opl4/opl4_seq.c53
-rw-r--r--sound/drivers/opl4/opl4_synth.c76
-rw-r--r--sound/drivers/opl4/yrw801.c262
-rw-r--r--sound/drivers/serial-u16550.c122
-rw-r--r--sound/drivers/virmidi.c92
-rw-r--r--sound/drivers/vx/vx_core.c87
-rw-r--r--sound/drivers/vx/vx_hwdep.c24
-rw-r--r--sound/drivers/vx/vx_mixer.c162
-rw-r--r--sound/drivers/vx/vx_pcm.c200
-rw-r--r--sound/drivers/vx/vx_uer.c22
-rw-r--r--sound/i2c/cs8427.c142
-rw-r--r--sound/i2c/i2c.c79
-rw-r--r--sound/i2c/l3/uda1341.c233
-rw-r--r--sound/i2c/other/ak4114.c122
-rw-r--r--sound/i2c/other/ak4117.c122
-rw-r--r--sound/i2c/other/ak4xxx-adda.c49
-rw-r--r--sound/i2c/other/tea575x-tuner.c8
-rw-r--r--sound/i2c/tea6330t.c88
-rw-r--r--sound/isa/Kconfig171
-rw-r--r--sound/isa/ad1816a/Makefile5
-rw-r--r--sound/isa/ad1816a/ad1816a.c26
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c209
-rw-r--r--sound/isa/ad1848/ad1848.c105
-rw-r--r--sound/isa/ad1848/ad1848_lib.c206
-rw-r--r--sound/isa/als100.c57
-rw-r--r--sound/isa/azt2320.c52
-rw-r--r--sound/isa/cmi8330.c299
-rw-r--r--sound/isa/cs423x/cs4231.c110
-rw-r--r--sound/isa/cs423x/cs4231_lib.c334
-rw-r--r--sound/isa/cs423x/cs4236.c591
-rw-r--r--sound/isa/cs423x/cs4236_lib.c106
-rw-r--r--sound/isa/dt019x.c57
-rw-r--r--sound/isa/es1688/es1688.c130
-rw-r--r--sound/isa/es1688/es1688_lib.c158
-rw-r--r--sound/isa/es18xx.c630
-rw-r--r--sound/isa/gus/gus_dma.c24
-rw-r--r--sound/isa/gus/gus_dram.c8
-rw-r--r--sound/isa/gus/gus_instr.c42
-rw-r--r--sound/isa/gus/gus_io.c72
-rw-r--r--sound/isa/gus/gus_irq.c16
-rw-r--r--sound/isa/gus/gus_main.c54
-rw-r--r--sound/isa/gus/gus_mem.c64
-rw-r--r--sound/isa/gus/gus_mem_proc.c26
-rw-r--r--sound/isa/gus/gus_mixer.c28
-rw-r--r--sound/isa/gus/gus_pcm.c202
-rw-r--r--sound/isa/gus/gus_reset.c54
-rw-r--r--sound/isa/gus/gus_sample.c42
-rw-r--r--sound/isa/gus/gus_simple.c86
-rw-r--r--sound/isa/gus/gus_synth.c90
-rw-r--r--sound/isa/gus/gus_timer.c44
-rw-r--r--sound/isa/gus/gus_uart.c38
-rw-r--r--sound/isa/gus/gus_volume.c4
-rw-r--r--sound/isa/gus/gusclassic.c136
-rw-r--r--sound/isa/gus/gusextreme.c150
-rw-r--r--sound/isa/gus/gusmax.c153
-rw-r--r--sound/isa/gus/interwave.c368
-rw-r--r--sound/isa/opl3sa2.c556
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c720
-rw-r--r--sound/isa/sb/emu8000.c121
-rw-r--r--sound/isa/sb/emu8000_callback.c107
-rw-r--r--sound/isa/sb/emu8000_local.h13
-rw-r--r--sound/isa/sb/emu8000_patch.c20
-rw-r--r--sound/isa/sb/emu8000_pcm.c104
-rw-r--r--sound/isa/sb/emu8000_synth.c17
-rw-r--r--sound/isa/sb/es968.c53
-rw-r--r--sound/isa/sb/sb16.c369
-rw-r--r--sound/isa/sb/sb16_csp.c174
-rw-r--r--sound/isa/sb/sb16_main.c130
-rw-r--r--sound/isa/sb/sb8.c176
-rw-r--r--sound/isa/sb/sb8_main.c94
-rw-r--r--sound/isa/sb/sb8_midi.c44
-rw-r--r--sound/isa/sb/sb_common.c28
-rw-r--r--sound/isa/sb/sb_mixer.c262
-rw-r--r--sound/isa/sgalaxy.c117
-rw-r--r--sound/isa/sscape.c373
-rw-r--r--sound/isa/wavefront/wavefront.c316
-rw-r--r--sound/isa/wavefront/wavefront_fx.c8
-rw-r--r--sound/isa/wavefront/wavefront_midi.c22
-rw-r--r--sound/isa/wavefront/wavefront_synth.c31
-rw-r--r--sound/mips/Kconfig1
-rw-r--r--sound/mips/au1x00.c389
-rw-r--r--sound/oss/ad1848.c92
-rw-r--r--sound/oss/ad1889.c2
-rw-r--r--sound/oss/btaudio.c2
-rw-r--r--sound/oss/cmpci.c2
-rw-r--r--sound/oss/cs4281/cs4281m.c23
-rw-r--r--sound/oss/cs4281/cs4281pm-24.c39
-rw-r--r--sound/oss/cs46xx.c62
-rw-r--r--sound/oss/cs46xxpm-24.h4
-rw-r--r--sound/oss/dmasound/dac3550a.c6
-rw-r--r--sound/oss/dmasound/dmasound.h1
-rw-r--r--sound/oss/dmasound/dmasound_atari.c112
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c81
-rw-r--r--sound/oss/dmasound/dmasound_paula.c14
-rw-r--r--sound/oss/dmasound/dmasound_q40.c18
-rw-r--r--sound/oss/dmasound/tas_common.c6
-rw-r--r--sound/oss/dmasound/trans_16.c1
-rw-r--r--sound/oss/emu10k1/main.c2
-rw-r--r--sound/oss/es1370.c2
-rw-r--r--sound/oss/es1371.c2
-rw-r--r--sound/oss/esssolo1.c2
-rw-r--r--sound/oss/harmony.c4
-rw-r--r--sound/oss/i810_audio.c22
-rw-r--r--sound/oss/ite8172.c2
-rw-r--r--sound/oss/kahlua.c2
-rw-r--r--sound/oss/maestro.c151
-rw-r--r--sound/oss/nec_vrc5477.c2
-rw-r--r--sound/oss/nm256_audio.c49
-rw-r--r--sound/oss/opl3sa2.c112
-rw-r--r--sound/oss/rme96xx.c2
-rw-r--r--sound/oss/sonicvibes.c2
-rw-r--r--sound/oss/trident.c18
-rw-r--r--sound/oss/ymfpci.c2
-rw-r--r--sound/parisc/harmony.c270
-rw-r--r--sound/parisc/harmony.h14
-rw-r--r--sound/pci/Kconfig404
-rw-r--r--sound/pci/Makefile2
-rw-r--r--sound/pci/ac97/ac97_bus.c2
-rw-r--r--sound/pci/ac97/ac97_codec.c400
-rw-r--r--sound/pci/ac97/ac97_local.h55
-rw-r--r--sound/pci/ac97/ac97_patch.c414
-rw-r--r--sound/pci/ac97/ac97_patch.h74
-rw-r--r--sound/pci/ac97/ac97_pcm.c38
-rw-r--r--sound/pci/ac97/ac97_proc.c74
-rw-r--r--sound/pci/ac97/ak4531_codec.c101
-rw-r--r--sound/pci/ad1889.c95
-rw-r--r--sound/pci/ali5451/ali5451.c491
-rw-r--r--sound/pci/als4000.c289
-rw-r--r--sound/pci/atiixp.c344
-rw-r--r--sound/pci/atiixp_modem.c309
-rw-r--r--sound/pci/au88x0/au88x0.c12
-rw-r--r--sound/pci/au88x0/au88x0.h22
-rw-r--r--sound/pci/au88x0/au88x0_a3d.c32
-rw-r--r--sound/pci/au88x0/au88x0_core.c8
-rw-r--r--sound/pci/au88x0/au88x0_eq.c28
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c6
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c4
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c50
-rw-r--r--sound/pci/azt3328.c225
-rw-r--r--sound/pci/bt87x.c138
-rw-r--r--sound/pci/ca0106/ca0106.h55
-rw-r--r--sound/pci/ca0106/ca0106_main.c390
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c500
-rw-r--r--sound/pci/ca0106/ca0106_proc.c63
-rw-r--r--sound/pci/ca0106/ca_midi.c49
-rw-r--r--sound/pci/ca0106/ca_midi.h25
-rw-r--r--sound/pci/cmipci.c618
-rw-r--r--sound/pci/cs4281.c357
-rw-r--r--sound/pci/cs46xx/cs46xx.c10
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c641
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.h221
-rw-r--r--sound/pci/cs46xx/dsp_spos.c266
-rw-r--r--sound/pci/cs46xx/dsp_spos.h18
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c342
-rw-r--r--sound/pci/cs46xx/imgs/cwc4630.h6
-rw-r--r--sound/pci/cs46xx/imgs/cwcasync.h6
-rw-r--r--sound/pci/cs46xx/imgs/cwcbinhack.h6
-rw-r--r--sound/pci/cs46xx/imgs/cwcdma.h6
-rw-r--r--sound/pci/cs46xx/imgs/cwcemb80.h6
-rw-r--r--sound/pci/cs46xx/imgs/cwcsnoop.h6
-rw-r--r--sound/pci/cs5535audio/Makefile8
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c402
-rw-r--r--sound/pci/cs5535audio/cs5535audio.h123
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c419
-rw-r--r--sound/pci/emu10k1/emu10k1.c154
-rw-r--r--sound/pci/emu10k1/emu10k1_callback.c105
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c589
-rw-r--r--sound/pci/emu10k1/emu10k1_patch.c13
-rw-r--r--sound/pci/emu10k1/emu10k1_synth.c19
-rw-r--r--sound/pci/emu10k1/emu10k1_synth_local.h15
-rw-r--r--sound/pci/emu10k1/emu10k1x.c406
-rw-r--r--sound/pci/emu10k1/emufx.c376
-rw-r--r--sound/pci/emu10k1/emumixer.c245
-rw-r--r--sound/pci/emu10k1/emumpu401.c72
-rw-r--r--sound/pci/emu10k1/emupcm.c405
-rw-r--r--sound/pci/emu10k1/emuproc.c115
-rw-r--r--sound/pci/emu10k1/io.c78
-rw-r--r--sound/pci/emu10k1/irq.c8
-rw-r--r--sound/pci/emu10k1/memory.c94
-rw-r--r--sound/pci/emu10k1/p16v.c564
-rw-r--r--sound/pci/emu10k1/timer.c18
-rw-r--r--sound/pci/emu10k1/tina2.h36
-rw-r--r--sound/pci/emu10k1/voice.c13
-rw-r--r--sound/pci/ens1370.c686
-rw-r--r--sound/pci/es1938.c348
-rw-r--r--sound/pci/es1968.c320
-rw-r--r--sound/pci/fm801.c478
-rw-r--r--sound/pci/hda/hda_codec.c341
-rw-r--r--sound/pci/hda/hda_codec.h32
-rw-r--r--sound/pci/hda/hda_generic.c43
-rw-r--r--sound/pci/hda/hda_intel.c220
-rw-r--r--sound/pci/hda/hda_local.h81
-rw-r--r--sound/pci/hda/hda_proc.c13
-rw-r--r--sound/pci/hda/patch_analog.c1338
-rw-r--r--sound/pci/hda/patch_cmedia.c107
-rw-r--r--sound/pci/hda/patch_realtek.c2601
-rw-r--r--sound/pci/hda/patch_si3054.c21
-rw-r--r--sound/pci/hda/patch_sigmatel.c424
-rw-r--r--sound/pci/ice1712/ak4xxx.c26
-rw-r--r--sound/pci/ice1712/amp.c6
-rw-r--r--sound/pci/ice1712/aureon.c242
-rw-r--r--sound/pci/ice1712/delta.c82
-rw-r--r--sound/pci/ice1712/envy24ht.h4
-rw-r--r--sound/pci/ice1712/ews.c146
-rw-r--r--sound/pci/ice1712/hoontech.c30
-rw-r--r--sound/pci/ice1712/ice1712.c578
-rw-r--r--sound/pci/ice1712/ice1712.h118
-rw-r--r--sound/pci/ice1712/ice1724.c532
-rw-r--r--sound/pci/ice1712/juli.c33
-rw-r--r--sound/pci/ice1712/phase.c110
-rw-r--r--sound/pci/ice1712/pontis.c130
-rw-r--r--sound/pci/ice1712/prodigy192.c82
-rw-r--r--sound/pci/ice1712/revo.c61
-rw-r--r--sound/pci/ice1712/revo.h4
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c4
-rw-r--r--sound/pci/intel8x0.c505
-rw-r--r--sound/pci/intel8x0m.c272
-rw-r--r--sound/pci/korg1212/korg1212.c935
-rw-r--r--sound/pci/maestro3.c243
-rw-r--r--sound/pci/mixart/mixart.c211
-rw-r--r--sound/pci/mixart/mixart.h69
-rw-r--r--sound/pci/mixart/mixart_core.c49
-rw-r--r--sound/pci/mixart/mixart_core.h120
-rw-r--r--sound/pci/mixart/mixart_hwdep.c76
-rw-r--r--sound/pci/mixart/mixart_hwdep.h2
-rw-r--r--sound/pci/mixart/mixart_mixer.c108
-rw-r--r--sound/pci/mixart/mixart_mixer.h6
-rw-r--r--sound/pci/nm256/nm256.c298
-rw-r--r--sound/pci/pcxhr/Makefile2
-rw-r--r--sound/pci/pcxhr/pcxhr.c1367
-rw-r--r--sound/pci/pcxhr/pcxhr.h188
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c1214
-rw-r--r--sound/pci/pcxhr/pcxhr_core.h200
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c438
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.h40
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c1020
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.h29
-rw-r--r--sound/pci/rme32.c332
-rw-r--r--sound/pci/rme96.c320
-rw-r--r--sound/pci/rme9652/hdsp.c744
-rw-r--r--sound/pci/rme9652/hdspm.c603
-rw-r--r--sound/pci/rme9652/rme9652.c372
-rw-r--r--sound/pci/sonicvibes.c235
-rw-r--r--sound/pci/trident/trident.c10
-rw-r--r--sound/pci/trident/trident_main.c773
-rw-r--r--sound/pci/trident/trident_memory.c92
-rw-r--r--sound/pci/trident/trident_synth.c175
-rw-r--r--sound/pci/via82xx.c423
-rw-r--r--sound/pci/via82xx_modem.c244
-rw-r--r--sound/pci/vx222/vx222.c49
-rw-r--r--sound/pci/vx222/vx222.h2
-rw-r--r--sound/pci/vx222/vx222_ops.c98
-rw-r--r--sound/pci/ymfpci/ymfpci.c49
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c517
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c182
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.h30
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_core.c42
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_irq.c6
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c64
-rw-r--r--sound/pcmcia/vx/vxp_mixer.c26
-rw-r--r--sound/pcmcia/vx/vxp_ops.c58
-rw-r--r--sound/pcmcia/vx/vxpocket.c186
-rw-r--r--sound/pcmcia/vx/vxpocket.h8
-rw-r--r--sound/ppc/Kconfig1
-rw-r--r--sound/ppc/awacs.c175
-rw-r--r--sound/ppc/beep.c34
-rw-r--r--sound/ppc/burgundy.c75
-rw-r--r--sound/ppc/daca.c72
-rw-r--r--sound/ppc/keywest.c11
-rw-r--r--sound/ppc/pmac.c371
-rw-r--r--sound/ppc/pmac.h101
-rw-r--r--sound/ppc/powermac.c71
-rw-r--r--sound/ppc/toonie.c32
-rw-r--r--sound/ppc/tumbler.c244
-rw-r--r--sound/sparc/Kconfig3
-rw-r--r--sound/sparc/amd7930.c142
-rw-r--r--sound/sparc/cs4231.c354
-rw-r--r--sound/sparc/dbri.c233
-rw-r--r--sound/synth/emux/emux.c45
-rw-r--r--sound/synth/emux/emux_effect.c44
-rw-r--r--sound/synth/emux/emux_hwdep.c23
-rw-r--r--sound/synth/emux/emux_nrpn.c30
-rw-r--r--sound/synth/emux/emux_oss.c90
-rw-r--r--sound/synth/emux/emux_proc.c14
-rw-r--r--sound/synth/emux/emux_seq.c101
-rw-r--r--sound/synth/emux/emux_synth.c144
-rw-r--r--sound/synth/emux/emux_voice.h67
-rw-r--r--sound/synth/emux/soundfont.c248
-rw-r--r--sound/synth/util_mem.c39
-rw-r--r--sound/usb/usbaudio.c375
-rw-r--r--sound/usb/usbaudio.h16
-rw-r--r--sound/usb/usbmidi.c211
-rw-r--r--sound/usb/usbmixer.c183
-rw-r--r--sound/usb/usbquirks.h310
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c65
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.h2
-rw-r--r--sound/usb/usx2y/usbus428ctldefs.h36
-rw-r--r--sound/usb/usx2y/usbusx2y.c50
-rw-r--r--sound/usb/usx2y/usbusx2y.h45
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c383
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c206
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.h1
5651 files changed, 332147 insertions, 159255 deletions
diff --git a/.gitignore b/.gitignore
index 5014bfa48ac1..3f8fb686b59c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
*.a
*.s
*.ko
+*.so
*.mod.c
#
@@ -23,6 +24,7 @@ Module.symvers
# Generated include files
#
include/asm
+include/asm-*/asm-offsets.h
include/config
include/linux/autoconf.h
include/linux/compile.h
diff --git a/CREDITS b/CREDITS
index 1b4f8694fa48..8e577ce4abeb 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1883,6 +1883,7 @@ N: Jaya Kumar
E: jayalk@intworks.biz
W: http://www.intworks.biz
D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
+D: pirq addr, CS5535 alsa audio driver
S: Gurgaon, India
S: Kuala Lumpur, Malaysia
@@ -3202,7 +3203,7 @@ N: Eugene Surovegin
E: ebs@ebshome.net
W: http://kernel.ebshome.net/
P: 1024D/AE5467F1 FF22 39F1 6728 89F6 6E6C 2365 7602 F33D AE54 67F1
-D: Embedded PowerPC 4xx: I2C, PIC and random hacks/fixes
+D: Embedded PowerPC 4xx: EMAC, I2C, PIC and random hacks/fixes
S: Sunnyvale, California 94085
S: USA
diff --git a/Documentation/Changes b/Documentation/Changes
index 86b86399d61d..fe5ae0f55020 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -31,8 +31,6 @@ al español de este documento en varios formatos.
Eine deutsche Version dieser Datei finden Sie unter
<http://www.stefan-winter.de/Changes-2.4.0.txt>.
-Last updated: October 29th, 2002
-
Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
Current Minimal Requirements
@@ -48,7 +46,7 @@ necessary on all systems; obviously, if you don't have any ISDN
hardware, for example, you probably needn't concern yourself with
isdn4k-utils.
-o Gnu C 2.95.3 # gcc --version
+o Gnu C 3.2 # gcc --version
o Gnu make 3.79.1 # make --version
o binutils 2.12 # ld -v
o util-linux 2.10o # fdformat --version
@@ -74,26 +72,7 @@ GCC
---
The gcc version requirements may vary depending on the type of CPU in your
-computer. The next paragraph applies to users of x86 CPUs, but not
-necessarily to users of other CPUs. Users of other CPUs should obtain
-information about their gcc version requirements from another source.
-
-The recommended compiler for the kernel is gcc 2.95.x (x >= 3), and it
-should be used when you need absolute stability. You may use gcc 3.0.x
-instead if you wish, although it may cause problems. Later versions of gcc
-have not received much testing for Linux kernel compilation, and there are
-almost certainly bugs (mainly, but not exclusively, in the kernel) that
-will need to be fixed in order to use these compilers. In any case, using
-pgcc instead of plain gcc is just asking for trouble.
-
-The Red Hat gcc 2.96 compiler subtree can also be used to build this tree.
-You should ensure you use gcc-2.96-74 or later. gcc-2.96-54 will not build
-the kernel correctly.
-
-In addition, please pay attention to compiler optimization. Anything
-greater than -O2 may not be wise. Similarly, if you choose to use gcc-2.95.x
-or derivatives, be sure not to use -fstrict-aliasing (which, depending on
-your version of gcc 2.95.x, may necessitate using -fno-strict-aliasing).
+computer.
Make
----
@@ -322,9 +301,9 @@ Getting updated software
Kernel compilation
******************
-gcc 2.95.3
-----------
-o <ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3.tar.gz>
+gcc
+---
+o <ftp://ftp.gnu.org/gnu/gcc/>
Make
----
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index eb7db3c19227..ce5d2c038cf5 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -199,7 +199,7 @@ The rationale is:
modifications are prevented
- saves the compiler work to optimize redundant code away ;)
-int fun(int )
+int fun(int a)
{
int result = 0;
char *buffer = kmalloc(SIZE);
@@ -344,7 +344,7 @@ Remember: if another thread can find your data structure, and you don't
have a reference count on it, you almost certainly have a bug.
- Chapter 11: Macros, Enums, Inline functions and RTL
+ Chapter 11: Macros, Enums and RTL
Names of macros defining constants and labels in enums are capitalized.
@@ -429,7 +429,35 @@ from void pointer to any other pointer type is guaranteed by the C programming
language.
- Chapter 14: References
+ Chapter 14: The inline disease
+
+There appears to be a common misperception that gcc has a magic "make me
+faster" speedup option called "inline". While the use of inlines can be
+appropriate (for example as a means of replacing macros, see Chapter 11), it
+very often is not. Abundant use of the inline keyword leads to a much bigger
+kernel, which in turn slows the system as a whole down, due to a bigger
+icache footprint for the CPU and simply because there is less memory
+available for the pagecache. Just think about it; a pagecache miss causes a
+disk seek, which easily takes 5 miliseconds. There are a LOT of cpu cycles
+that can go into these 5 miliseconds.
+
+A reasonable rule of thumb is to not put inline at functions that have more
+than 3 lines of code in them. An exception to this rule are the cases where
+a parameter is known to be a compiletime constant, and as a result of this
+constantness you *know* the compiler will be able to optimize most of your
+function away at compile time. For a good example of this later case, see
+the kmalloc() inline function.
+
+Often people argue that adding inline to functions that are static and used
+only once is always a win since there is no space tradeoff. While this is
+technically correct, gcc is capable of inlining these automatically without
+help, and the maintenance issue of removing the inline when a second user
+appears outweighs the potential value of the hint that tells gcc to do
+something it would have done anyway.
+
+
+
+ Chapter 15: References
The C Programming Language, Second Edition
by Brian W. Kernighan and Dennis M. Ritchie.
@@ -444,10 +472,13 @@ ISBN 0-201-61586-X.
URL: http://cm.bell-labs.com/cm/cs/tpop/
GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
-gcc internals and indent, all available from http://www.gnu.org
+gcc internals and indent, all available from http://www.gnu.org/manual/
WG14 is the international standardization working group for the programming
-language C, URL: http://std.dkuug.dk/JTC1/SC22/WG14/
+language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel CodingStyle, by greg@kroah.com at OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
--
-Last updated on 16 February 2004 by a community effort on LKML.
+Last updated on 30 December 2005 by a community effort on LKML.
diff --git a/Documentation/DocBook/.gitignore b/Documentation/DocBook/.gitignore
new file mode 100644
index 000000000000..c102c02ecf89
--- /dev/null
+++ b/Documentation/DocBook/.gitignore
@@ -0,0 +1,6 @@
+*.xml
+*.ps
+*.pdf
+*.html
+*.9.gz
+*.9
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 767433bdbc40..8c9c6704e85b 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -54,6 +54,11 @@
!Ekernel/sched.c
!Ekernel/timer.c
</sect1>
+ <sect1><title>High-resolution timers</title>
+!Iinclude/linux/ktime.h
+!Iinclude/linux/hrtimer.h
+!Ekernel/hrtimer.c
+ </sect1>
<sect1><title>Internal Functions</title>
!Ikernel/exit.c
!Ikernel/signal.c
@@ -369,6 +374,7 @@ X!Edrivers/acpi/motherboard.c
X!Edrivers/acpi/bus.c
-->
!Edrivers/acpi/scan.c
+!Idrivers/acpi/scan.c
<!-- No correct structured comments
X!Edrivers/acpi/pci_bind.c
-->
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 90dc2de8e0af..158ffe9bfade 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -222,7 +222,7 @@
<title>Two Main Types of Kernel Locks: Spinlocks and Semaphores</title>
<para>
- There are two main types of kernel locks. The fundamental type
+ There are three main types of kernel locks. The fundamental type
is the spinlock
(<filename class="headerfile">include/asm/spinlock.h</filename>),
which is a very simple single-holder lock: if you can't get the
@@ -230,16 +230,22 @@
very small and fast, and can be used anywhere.
</para>
<para>
- The second type is a semaphore
+ The second type is a mutex
+ (<filename class="headerfile">include/linux/mutex.h</filename>): it
+ is like a spinlock, but you may block holding a mutex.
+ If you can't lock a mutex, your task will suspend itself, and be woken
+ up when the mutex is released. This means the CPU can do something
+ else while you are waiting. There are many cases when you simply
+ can't sleep (see <xref linkend="sleeping-things"/>), and so have to
+ use a spinlock instead.
+ </para>
+ <para>
+ The third type is a semaphore
(<filename class="headerfile">include/asm/semaphore.h</filename>): it
can have more than one holder at any time (the number decided at
initialization time), although it is most commonly used as a
- single-holder lock (a mutex). If you can't get a semaphore,
- your task will put itself on the queue, and be woken up when the
- semaphore is released. This means the CPU will do something
- else while you are waiting, but there are many cases when you
- simply can't sleep (see <xref linkend="sleeping-things"/>), and so
- have to use a spinlock instead.
+ single-holder lock (a mutex). If you can't get a semaphore, your
+ task will be suspended and later on woken up - just like for mutexes.
</para>
<para>
Neither type of lock is recursive: see
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 15ce0f21e5e0..320af25de3a2 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -253,6 +253,7 @@
!Edrivers/usb/core/urb.c
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
+!Edrivers/usb/core/driver.c
!Edrivers/usb/core/usb.c
!Edrivers/usb/core/hub.c
</chapter>
diff --git a/Documentation/DocBook/videobook.tmpl b/Documentation/DocBook/videobook.tmpl
index 3ec6c875588a..fdff984a5161 100644
--- a/Documentation/DocBook/videobook.tmpl
+++ b/Documentation/DocBook/videobook.tmpl
@@ -229,7 +229,7 @@ int __init myradio_init(struct video_init *v)
static int users = 0;
-static int radio_open(stuct video_device *dev, int flags)
+static int radio_open(struct video_device *dev, int flags)
{
if(users)
return -EBUSY;
@@ -949,7 +949,7 @@ int __init mycamera_init(struct video_init *v)
static int users = 0;
-static int camera_open(stuct video_device *dev, int flags)
+static int camera_open(struct video_device *dev, int flags)
{
if(users)
return -EBUSY;
diff --git a/Documentation/RCU/rcuref.txt b/Documentation/RCU/rcuref.txt
index a23fee66064d..3f60db41b2f0 100644
--- a/Documentation/RCU/rcuref.txt
+++ b/Documentation/RCU/rcuref.txt
@@ -1,74 +1,67 @@
-Refcounter framework for elements of lists/arrays protected by
-RCU.
+Refcounter design 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); }
+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);
- ...
+ ... 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
+in search_and_reference to rcu_read_lock(), the atomic_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
+has already been deleted from the list/array. atomic_inc_not_zero 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();
+ alloc_object rcu_read_lock();
+ ... search_for_element
+ atomic_set(&el->rc, 1); if (atomic_inc_not_zero(&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);
- ...
+ ... write_lock(&list_lock);
+ atomic_dec(&el->rc, relfunc) ...
+ ... delete_element
+} write_unlock(&list_lock);
+ ...
+ if (atomic_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
+update (write) stream. In such cases, atomic_inc_not_zero might be an
+overkill since the spinlock serialising list updates are held. atomic_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/SubmittingDrivers b/Documentation/SubmittingDrivers
index c3cca924e94b..6bd30fdd0786 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -27,18 +27,17 @@ Who To Submit Drivers To
------------------------
Linux 2.0:
- No new drivers are accepted for this kernel tree
+ No new drivers are accepted for this kernel tree.
Linux 2.2:
+ No new drivers are accepted for this kernel tree.
+
+Linux 2.4:
If the code area has a general maintainer then please submit it to
the maintainer listed in MAINTAINERS in the kernel file. If the
maintainer does not respond or you cannot find the appropriate
- maintainer then please contact the 2.2 kernel maintainer:
- Marc-Christian Petersen <m.c.p@wolk-project.de>.
-
-Linux 2.4:
- The same rules apply as 2.2. The final contact point for Linux 2.4
- submissions is Marcelo Tosatti <marcelo.tosatti@cyclades.com>.
+ maintainer then please contact Marcelo Tosatti
+ <marcelo.tosatti@cyclades.com>.
Linux 2.6:
The same rules apply as 2.4 except that you should follow linux-kernel
@@ -53,6 +52,7 @@ Licensing: The code must be released to us under the
of exclusive GPL licensing, and if you wish the driver
to be useful to other communities such as BSD you may well
wish to release under multiple licenses.
+ See accepted licenses at include/linux/module.h
Copyright: The copyright owner must agree to use of GPL.
It's best if the submitter and copyright owner
@@ -143,5 +143,13 @@ KernelNewbies:
http://kernelnewbies.org/
Linux USB project:
- http://sourceforge.net/projects/linux-usb/
+ http://www.linux-usb.org/
+
+How to NOT write kernel driver by arjanv@redhat.com
+ http://people.redhat.com/arjanv/olspaper.pdf
+
+Kernel Janitor:
+ http://janitor.kernelnewbies.org/
+--
+Last updated on 17 Nov 2005.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 237d54c44bc5..c2c85bcb3d43 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -78,7 +78,9 @@ Randy Dunlap's patch scripts:
http://www.xenotime.net/linux/scripts/patching-scripts-002.tar.gz
Andrew Morton's patch scripts:
-http://www.zip.com.au/~akpm/linux/patches/patch-scripts-0.20
+http://www.zip.com.au/~akpm/linux/patches/
+Instead of these scripts, quilt is the recommended patch management
+tool (see above).
@@ -97,7 +99,7 @@ need to split up your patch. See #3, next.
3) Separate your changes.
-Separate each logical change into its own patch.
+Separate _logical changes_ into a single patch file.
For example, if your changes include both bug fixes and performance
enhancements for a single driver, separate those changes into two
@@ -112,6 +114,10 @@ If one patch depends on another patch in order for a change to be
complete, that is OK. Simply note "this patch depends on patch X"
in your patch description.
+If you cannot condense your patch set into a smaller set of patches,
+then only post say 15 or so at a time and wait for review and integration.
+
+
4) Select e-mail destination.
@@ -124,6 +130,10 @@ your patch to the primary Linux kernel developer's mailing list,
linux-kernel@vger.kernel.org. Most kernel developers monitor this
e-mail list, and can comment on your changes.
+
+Do not send more than 15 patches at once to the vger mailing lists!!!
+
+
Linus Torvalds is the final arbiter of all changes accepted into the
Linux kernel. His e-mail address is <torvalds@osdl.org>. He gets
a lot of e-mail, so typically you should do your best to -avoid- sending
@@ -149,6 +159,9 @@ USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the
MAINTAINERS file for a mailing list that relates specifically to
your change.
+Majordomo lists of VGER.KERNEL.ORG at:
+ <http://vger.kernel.org/vger-lists.html>
+
If changes affect userland-kernel interfaces, please send
the MAN-PAGES maintainer (as listed in the MAINTAINERS file)
a man-pages patch, or at least a notification of the change,
@@ -158,7 +171,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS
copy the maintainer when you change their code.
For small patches you may want to CC the Trivial Patch Monkey
-trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
+trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
patches. Trivial patches must qualify for one of the following rules:
Spelling fixes in documentation
Spelling fixes which could break grep(1).
@@ -171,7 +184,7 @@ patches. Trivial patches must qualify for one of the following rules:
since people copy, as long as it's trivial)
Any fix by the author/maintainer of the file. (ie. patch monkey
in re-transmission mode)
-URL: <http://www.kernel.org/pub/linux/kernel/people/rusty/trivial/>
+URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
@@ -373,27 +386,14 @@ a diffstat, to show what files have changed, and the number of inserted
and deleted lines per file. A diffstat is especially useful on bigger
patches. Other comments relevant only to the moment or the maintainer,
not suitable for the permanent changelog, should also go here.
+Use diffstat options "-p 1 -w 70" so that filenames are listed from the
+top of the kernel source tree and don't use too much horizontal space
+(easily fit in 80 columns, maybe with some indentation).
See more details on the proper patch format in the following
references.
-13) More references for submitting patches
-
-Andrew Morton, "The perfect patch" (tpp).
- <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
-
-Jeff Garzik, "Linux kernel patch submission format."
- <http://linux.yyz.us/patch-format.html>
-
-Greg KH, "How to piss off a kernel subsystem maintainer"
- <http://www.kroah.com/log/2005/03/31/>
-
-Kernel Documentation/CodingStyle
- <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
-
-Linus Torvald's mail on the canonical patch format:
- <http://lkml.org/lkml/2005/4/7/183>
-----------------------------------
@@ -466,3 +466,31 @@ and 'extern __inline__'.
Don't try to anticipate nebulous future cases which may or may not
be useful: "Make it as simple as you can, and no simpler."
+
+
+----------------------
+SECTION 3 - REFERENCES
+----------------------
+
+Andrew Morton, "The perfect patch" (tpp).
+ <http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format."
+ <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman "How to piss off a kernel subsystem maintainer".
+ <http://www.kroah.com/log/2005/03/31/>
+ <http://www.kroah.com/log/2005/07/08/>
+ <http://www.kroah.com/log/2005/10/19/>
+ <http://www.kroah.com/log/2006/01/11/>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!.
+ <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
+
+Kernel Documentation/CodingStyle
+ <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
+
+Linus Torvald's mail on the canonical patch format:
+ <http://lkml.org/lkml/2005/4/7/183>
+--
+Last updated on 17 Nov 2005.
diff --git a/Documentation/applying-patches.txt b/Documentation/applying-patches.txt
index 681e426e2482..a083ba35d1ad 100644
--- a/Documentation/applying-patches.txt
+++ b/Documentation/applying-patches.txt
@@ -2,8 +2,8 @@
Applying Patches To The Linux Kernel
------------------------------------
- (Written by Jesper Juhl, August 2005)
-
+ Original by: Jesper Juhl, August 2005
+ Last update: 2006-01-05
A frequently asked question on the Linux Kernel Mailing List is how to apply
@@ -76,7 +76,7 @@ instead:
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 or bunzip2 on the file -- like this:
gunzip patch-x.y.z.gz
bunzip2 patch-x.y.z.bz2
@@ -94,7 +94,7 @@ 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
+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.
@@ -118,16 +118,16 @@ 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
+read this file to see exactly 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
+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
+re-downloading 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.
@@ -136,7 +136,7 @@ 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
+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
@@ -167,22 +167,28 @@ 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.
+the file you fed to it. Either your download is broken, you tried to feed
+patch a compressed patch file without uncompressing it first, or the patch
+file that you are using has been mangled by a mail client or mail transfer
+agent along the way somewhere, e.g., by splitting a long line into two lines.
+Often these warnings can easily be fixed by joining (concatenating) the
+two lines that had been split.
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
+assume that either your patch file or your tree is broken and I'd advise 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.
+ 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
@@ -197,10 +203,10 @@ 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
+ 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.
@@ -225,8 +231,8 @@ The -mm kernels live at
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.
+less bandwidth used globally and less load on the main kernel.org servers --
+these are good things, so do use mirrors when possible.
The 2.6.x kernels
@@ -234,14 +240,14 @@ 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
+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
+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
+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:
@@ -258,12 +264,12 @@ $ 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
+$ mv linux-2.6.11.1 linux-2.6.12 # rename source dir
The 2.6.x.y kernels
---
- Kernels with 4 digit versions are -stable kernels. They contain small(ish)
+ 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.
@@ -274,9 +280,14 @@ versions.
If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is
the current stable kernel.
+ note: the -stable team usually do make incremental patches available as well
+ as patches against the latest mainline release, but I only cover the
+ non-incremental ones below. The incremental ones can be found at
+ ftp://ftp.kernel.org/pub/linux/kernel/v2.6/incr/
+
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.
+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.
@@ -342,12 +353,12 @@ The -git kernels
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
+Linus's 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 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.
@@ -390,12 +401,12 @@ 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
+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
+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
@@ -433,7 +444,11 @@ $ 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.
+This concludes this list of explanations of the various kernel trees.
+I hope you are now clear on how to apply the various patches and help testing
+the kernel.
+
+Thank you's to Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
+Johannes Stezenbach, Grant Coady, Pavel Machek and others that I may have
+forgotten for their reviews and contributions to this document.
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
new file mode 100644
index 000000000000..03971518b222
--- /dev/null
+++ b/Documentation/block/barrier.txt
@@ -0,0 +1,271 @@
+I/O Barriers
+============
+Tejun Heo <htejun@gmail.com>, July 22 2005
+
+I/O barrier requests are used to guarantee ordering around the barrier
+requests. Unless you're crazy enough to use disk drives for
+implementing synchronization constructs (wow, sounds interesting...),
+the ordering is meaningful only for write requests for things like
+journal checkpoints. All requests queued before a barrier request
+must be finished (made it to the physical medium) before the barrier
+request is started, and all requests queued after the barrier request
+must be started only after the barrier request is finished (again,
+made it to the physical medium).
+
+In other words, I/O barrier requests have the following two properties.
+
+1. Request ordering
+
+Requests cannot pass the barrier request. Preceding requests are
+processed before the barrier and following requests after.
+
+Depending on what features a drive supports, this can be done in one
+of the following three ways.
+
+i. For devices which have queue depth greater than 1 (TCQ devices) and
+support ordered tags, block layer can just issue the barrier as an
+ordered request and the lower level driver, controller and drive
+itself are responsible for making sure that the ordering contraint is
+met. Most modern SCSI controllers/drives should support this.
+
+NOTE: SCSI ordered tag isn't currently used due to limitation in the
+ SCSI midlayer, see the following random notes section.
+
+ii. For devices which have queue depth greater than 1 but don't
+support ordered tags, block layer ensures that the requests preceding
+a barrier request finishes before issuing the barrier request. Also,
+it defers requests following the barrier until the barrier request is
+finished. Older SCSI controllers/drives and SATA drives fall in this
+category.
+
+iii. Devices which have queue depth of 1. This is a degenerate case
+of ii. Just keeping issue order suffices. Ancient SCSI
+controllers/drives and IDE drives are in this category.
+
+2. Forced flushing to physcial medium
+
+Again, if you're not gonna do synchronization with disk drives (dang,
+it sounds even more appealing now!), the reason you use I/O barriers
+is mainly to protect filesystem integrity when power failure or some
+other events abruptly stop the drive from operating and possibly make
+the drive lose data in its cache. So, I/O barriers need to guarantee
+that requests actually get written to non-volatile medium in order.
+
+There are four cases,
+
+i. No write-back cache. Keeping requests ordered is enough.
+
+ii. Write-back cache but no flush operation. There's no way to
+gurantee physical-medium commit order. This kind of devices can't to
+I/O barriers.
+
+iii. Write-back cache and flush operation but no FUA (forced unit
+access). We need two cache flushes - before and after the barrier
+request.
+
+iv. Write-back cache, flush operation and FUA. We still need one
+flush to make sure requests preceding a barrier are written to medium,
+but post-barrier flush can be avoided by using FUA write on the
+barrier itself.
+
+
+How to support barrier requests in drivers
+------------------------------------------
+
+All barrier handling is done inside block layer proper. All low level
+drivers have to are implementing its prepare_flush_fn and using one
+the following two functions to indicate what barrier type it supports
+and how to prepare flush requests. Note that the term 'ordered' is
+used to indicate the whole sequence of performing barrier requests
+including draining and flushing.
+
+typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
+
+int blk_queue_ordered(request_queue_t *q, unsigned ordered,
+ prepare_flush_fn *prepare_flush_fn,
+ unsigned gfp_mask);
+
+int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
+ prepare_flush_fn *prepare_flush_fn,
+ unsigned gfp_mask);
+
+The only difference between the two functions is whether or not the
+caller is holding q->queue_lock on entry. The latter expects the
+caller is holding the lock.
+
+@q : the queue in question
+@ordered : the ordered mode the driver/device supports
+@prepare_flush_fn : this function should prepare @rq such that it
+ flushes cache to physical medium when executed
+@gfp_mask : gfp_mask used when allocating data structures
+ for ordered processing
+
+For example, SCSI disk driver's prepare_flush_fn looks like the
+following.
+
+static void sd_prepare_flush(request_queue_t *q, struct request *rq)
+{
+ memset(rq->cmd, 0, sizeof(rq->cmd));
+ rq->flags |= REQ_BLOCK_PC;
+ rq->timeout = SD_TIMEOUT;
+ rq->cmd[0] = SYNCHRONIZE_CACHE;
+}
+
+The following seven ordered modes are supported. The following table
+shows which mode should be used depending on what features a
+device/driver supports. In the leftmost column of table,
+QUEUE_ORDERED_ prefix is omitted from the mode names to save space.
+
+The table is followed by description of each mode. Note that in the
+descriptions of QUEUE_ORDERED_DRAIN*, '=>' is used whereas '->' is
+used for QUEUE_ORDERED_TAG* descriptions. '=>' indicates that the
+preceding step must be complete before proceeding to the next step.
+'->' indicates that the next step can start as soon as the previous
+step is issued.
+
+ write-back cache ordered tag flush FUA
+-----------------------------------------------------------------------
+NONE yes/no N/A no N/A
+DRAIN no no N/A N/A
+DRAIN_FLUSH yes no yes no
+DRAIN_FUA yes no yes yes
+TAG no yes N/A N/A
+TAG_FLUSH yes yes yes no
+TAG_FUA yes yes yes yes
+
+
+QUEUE_ORDERED_NONE
+ I/O barriers are not needed and/or supported.
+
+ Sequence: N/A
+
+QUEUE_ORDERED_DRAIN
+ Requests are ordered by draining the request queue and cache
+ flushing isn't needed.
+
+ Sequence: drain => barrier
+
+QUEUE_ORDERED_DRAIN_FLUSH
+ Requests are ordered by draining the request queue and both
+ pre-barrier and post-barrier cache flushings are needed.
+
+ Sequence: drain => preflush => barrier => postflush
+
+QUEUE_ORDERED_DRAIN_FUA
+ Requests are ordered by draining the request queue and
+ pre-barrier cache flushing is needed. By using FUA on barrier
+ request, post-barrier flushing can be skipped.
+
+ Sequence: drain => preflush => barrier
+
+QUEUE_ORDERED_TAG
+ Requests are ordered by ordered tag and cache flushing isn't
+ needed.
+
+ Sequence: barrier
+
+QUEUE_ORDERED_TAG_FLUSH
+ Requests are ordered by ordered tag and both pre-barrier and
+ post-barrier cache flushings are needed.
+
+ Sequence: preflush -> barrier -> postflush
+
+QUEUE_ORDERED_TAG_FUA
+ Requests are ordered by ordered tag and pre-barrier cache
+ flushing is needed. By using FUA on barrier request,
+ post-barrier flushing can be skipped.
+
+ Sequence: preflush -> barrier
+
+
+Random notes/caveats
+--------------------
+
+* SCSI layer currently can't use TAG ordering even if the drive,
+controller and driver support it. The problem is that SCSI midlayer
+request dispatch function is not atomic. It releases queue lock and
+switch to SCSI host lock during issue and it's possible and likely to
+happen in time that requests change their relative positions. Once
+this problem is solved, TAG ordering can be enabled.
+
+* Currently, no matter which ordered mode is used, there can be only
+one barrier request in progress. All I/O barriers are held off by
+block layer until the previous I/O barrier is complete. This doesn't
+make any difference for DRAIN ordered devices, but, for TAG ordered
+devices with very high command latency, passing multiple I/O barriers
+to low level *might* be helpful if they are very frequent. Well, this
+certainly is a non-issue. I'm writing this just to make clear that no
+two I/O barrier is ever passed to low-level driver.
+
+* Completion order. Requests in ordered sequence are issued in order
+but not required to finish in order. Barrier implementation can
+handle out-of-order completion of ordered sequence. IOW, the requests
+MUST be processed in order but the hardware/software completion paths
+are allowed to reorder completion notifications - eg. current SCSI
+midlayer doesn't preserve completion order during error handling.
+
+* Requeueing order. Low-level drivers are free to requeue any request
+after they removed it from the request queue with
+blkdev_dequeue_request(). As barrier sequence should be kept in order
+when requeued, generic elevator code takes care of putting requests in
+order around barrier. See blk_ordered_req_seq() and
+ELEVATOR_INSERT_REQUEUE handling in __elv_add_request() for details.
+
+Note that block drivers must not requeue preceding requests while
+completing latter requests in an ordered sequence. Currently, no
+error checking is done against this.
+
+* Error handling. Currently, block layer will report error to upper
+layer if any of requests in an ordered sequence fails. Unfortunately,
+this doesn't seem to be enough. Look at the following request flow.
+QUEUE_ORDERED_TAG_FLUSH is in use.
+
+ [0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >
+ still in elevator
+
+Let's say request [2], [3] are write requests to update file system
+metadata (journal or whatever) and [barrier] is used to mark that
+those updates are valid. Consider the following sequence.
+
+ i. Requests [0] ~ [post] leaves the request queue and enters
+ low-level driver.
+ ii. After a while, unfortunately, something goes wrong and the
+ drive fails [2]. Note that any of [0], [1] and [3] could have
+ completed by this time, but [pre] couldn't have been finished
+ as the drive must process it in order and it failed before
+ processing that command.
+ iii. Error handling kicks in and determines that the error is
+ unrecoverable and fails [2], and resumes operation.
+ iv. [pre] [barrier] [post] gets processed.
+ v. *BOOM* power fails
+
+The problem here is that the barrier request is *supposed* to indicate
+that filesystem update requests [2] and [3] made it safely to the
+physical medium and, if the machine crashes after the barrier is
+written, filesystem recovery code can depend on that. Sadly, that
+isn't true in this case anymore. IOW, the success of a I/O barrier
+should also be dependent on success of some of the preceding requests,
+where only upper layer (filesystem) knows what 'some' is.
+
+This can be solved by implementing a way to tell the block layer which
+requests affect the success of the following barrier request and
+making lower lever drivers to resume operation on error only after
+block layer tells it to do so.
+
+As the probability of this happening is very low and the drive should
+be faulty, implementing the fix is probably an overkill. But, still,
+it's there.
+
+* In previous drafts of barrier implementation, there was fallback
+mechanism such that, if FUA or ordered TAG fails, less fancy ordered
+mode can be selected and the failed barrier request is retried
+automatically. The rationale for this feature was that as FUA is
+pretty new in ATA world and ordered tag was never used widely, there
+could be devices which report to support those features but choke when
+actually given such requests.
+
+ This was removed for two reasons 1. it's an overkill 2. it's
+impossible to implement properly when TAG ordering is used as low
+level drivers resume after an error automatically. If it's ever
+needed adding it back and modifying low level drivers accordingly
+shouldn't be difficult.
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 0fe01c805480..8e63831971d5 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -31,7 +31,7 @@ The following people helped with review comments and inputs for this
document:
Christoph Hellwig <hch@infradead.org>
Arjan van de Ven <arjanv@redhat.com>
- Randy Dunlap <rddunlap@osdl.org>
+ Randy Dunlap <rdunlap@xenotime.net>
Andre Hedrick <andre@linux-ide.org>
The following people helped with fixes/contributions to the bio patches
@@ -263,14 +263,8 @@ A flag in the bio structure, BIO_BARRIER is used to identify a barrier i/o.
The generic i/o scheduler would make sure that it places the barrier request and
all other requests coming after it after all the previous requests in the
queue. Barriers may be implemented in different ways depending on the
-driver. A SCSI driver for example could make use of ordered tags to
-preserve the necessary ordering with a lower impact on throughput. For IDE
-this might be two sync cache flush: a pre and post flush when encountering
-a barrier write.
-
-There is a provision for queues to indicate what kind of barriers they
-can provide. This is as of yet unmerged, details will be added here once it
-is in the kernel.
+driver. For more details regarding I/O barriers, please read barrier.txt
+in this directory.
1.2.2 Request Priority/Latency
diff --git a/Documentation/block/stat.txt b/Documentation/block/stat.txt
new file mode 100644
index 000000000000..0dbc946de2ea
--- /dev/null
+++ b/Documentation/block/stat.txt
@@ -0,0 +1,82 @@
+Block layer statistics in /sys/block/<dev>/stat
+===============================================
+
+This file documents the contents of the /sys/block/<dev>/stat file.
+
+The stat file provides several statistics about the state of block
+device <dev>.
+
+Q. Why are there multiple statistics in a single file? Doesn't sysfs
+ normally contain a single value per file?
+A. By having a single file, the kernel can guarantee that the statistics
+ represent a consistent snapshot of the state of the device. If the
+ statistics were exported as multiple files containing one statistic
+ each, it would be impossible to guarantee that a set of readings
+ represent a single point in time.
+
+The stat file consists of a single line of text containing 11 decimal
+values separated by whitespace. The fields are summarized in the
+following table, and described in more detail below.
+
+Name units description
+---- ----- -----------
+read I/Os requests number of read I/Os processed
+read merges requests number of read I/Os merged with in-queue I/O
+read sectors sectors number of sectors read
+read ticks milliseconds total wait time for read requests
+write I/Os requests number of write I/Os processed
+write merges requests number of write I/Os merged with in-queue I/O
+write sectors sectors number of sectors written
+write ticks milliseconds total wait time for write requests
+in_flight requests number of I/Os currently in flight
+io_ticks milliseconds total time this block device has been active
+time_in_queue milliseconds total wait time for all requests
+
+read I/Os, write I/Os
+=====================
+
+These values increment when an I/O request completes.
+
+read merges, write merges
+=========================
+
+These values increment when an I/O request is merged with an
+already-queued I/O request.
+
+read sectors, write sectors
+===========================
+
+These values count the number of sectors read from or written to this
+block device. The "sectors" in question are the standard UNIX 512-byte
+sectors, not any device- or filesystem-specific block size. The
+counters are incremented when the I/O completes.
+
+read ticks, write ticks
+=======================
+
+These values count the number of milliseconds that I/O requests have
+waited on this block device. If there are multiple I/O requests waiting,
+these values will increase at a rate greater than 1000/second; for
+example, if 60 read requests wait for an average of 30 ms, the read_ticks
+field will increase by 60*30 = 1800.
+
+in_flight
+=========
+
+This value counts the number of I/O requests that have been issued to
+the device driver but have not yet completed. It does not include I/O
+requests that are in the queue but not yet issued to the device driver.
+
+io_ticks
+========
+
+This value counts the number of milliseconds during which the device has
+had I/O requests queued.
+
+time_in_queue
+=============
+
+This value counts the number of milliseconds that I/O requests have waited
+on this block device. If there are multiple I/O requests waiting, this
+value will increase as the product of the number of milliseconds times the
+number of requests waiting (see "read ticks" above for an example).
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 7eb715e07eda..4ae418889b88 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -136,7 +136,7 @@ changes occur:
8) void lazy_mmu_prot_update(pte_t pte)
This interface is called whenever the protection on
any user PTEs change. This interface provides a notification
- to architecture specific code to take appropiate action.
+ to architecture specific code to take appropriate action.
Next, we have the cache flushing interfaces. In general, when Linux
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 933fae74c337..f4b8dc4237e6 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -27,6 +27,7 @@ Contents:
2.2 Powersave
2.3 Userspace
2.4 Ondemand
+2.5 Conservative
3. The Governor Interface in the CPUfreq Core
@@ -110,9 +111,64 @@ directory.
The CPUfreq govenor "ondemand" sets the CPU depending on the
current usage. To do this the CPU must have the capability to
-switch the frequency very fast.
-
-
+switch the frequency very quickly. There are a number of sysfs file
+accessible parameters:
+
+sampling_rate: measured in uS (10^-6 seconds), this is how often you
+want the kernel to look at the CPU usage and to make decisions on
+what to do about the frequency. Typically this is set to values of
+around '10000' or more.
+
+show_sampling_rate_(min|max): the minimum and maximum sampling rates
+available that you may set 'sampling_rate' to.
+
+up_threshold: defines what the average CPU usaged between the samplings
+of 'sampling_rate' needs to be for the kernel to make a decision on
+whether it should increase the frequency. For example when it is set
+to its default value of '80' it means that between the checking
+intervals the CPU needs to be on average more than 80% in use to then
+decide that the CPU frequency needs to be increased.
+
+sampling_down_factor: this parameter controls the rate that the CPU
+makes a decision on when to decrease the frequency. When set to its
+default value of '5' it means that at 1/5 the sampling_rate the kernel
+makes a decision to lower the frequency. Five "lower rate" decisions
+have to be made in a row before the CPU frequency is actually lower.
+If set to '1' then the frequency decreases as quickly as it increases,
+if set to '2' it decreases at half the rate of the increase.
+
+ignore_nice_load: this parameter takes a value of '0' or '1', when set
+to '0' (its default) then all processes are counted towards towards the
+'cpu utilisation' value. When set to '1' then processes that are
+run with a 'nice' value will not count (and thus be ignored) in the
+overal usage calculation. This is useful if you are running a CPU
+intensive calculation on your laptop that you do not care how long it
+takes to complete as you can 'nice' it and prevent it from taking part
+in the deciding process of whether to increase your CPU frequency.
+
+
+2.5 Conservative
+----------------
+
+The CPUfreq governor "conservative", much like the "ondemand"
+governor, sets the CPU depending on the current usage. It differs in
+behaviour in that it gracefully increases and decreases the CPU speed
+rather than jumping to max speed the moment there is any load on the
+CPU. This behaviour more suitable in a battery powered environment.
+The governor is tweaked in the same manner as the "ondemand" governor
+through sysfs with the addition of:
+
+freq_step: this describes what percentage steps the cpu freq should be
+increased and decreased smoothly by. By default the cpu frequency will
+increase in 5% chunks of your maximum cpu frequency. You can change this
+value to anywhere between 0 and 100 where '0' will effectively lock your
+CPU at a speed regardless of its load whilst '100' will, in theory, make
+it behave identically to the "ondemand" governor.
+
+down_threshold: same as the 'up_threshold' found for the "ondemand"
+governor but for the opposite direction. For example when set to its
+default value of '20' it means that if the CPU usage needs to be below
+20% between samples to have the frequency decreased.
3. The Governor Interface in the CPUfreq Core
=============================================
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
new file mode 100644
index 000000000000..08c5d04f3086
--- /dev/null
+++ b/Documentation/cpu-hotplug.txt
@@ -0,0 +1,357 @@
+ CPU hotplug Support in Linux(tm) Kernel
+
+ Maintainers:
+ CPU Hotplug Core:
+ Rusty Russell <rusty@rustycorp.com.au>
+ Srivatsa Vaddagiri <vatsa@in.ibm.com>
+ i386:
+ Zwane Mwaikambo <zwane@arm.linux.org.uk>
+ ppc64:
+ Nathan Lynch <nathanl@austin.ibm.com>
+ Joel Schopp <jschopp@austin.ibm.com>
+ ia64/x86_64:
+ Ashok Raj <ashok.raj@intel.com>
+
+Authors: Ashok Raj <ashok.raj@intel.com>
+Lots of feedback: Nathan Lynch <nathanl@austin.ibm.com>,
+ Joel Schopp <jschopp@austin.ibm.com>
+
+Introduction
+
+Modern advances in system architectures have introduced advanced error
+reporting and correction capabilities in processors. CPU architectures permit
+partitioning support, where compute resources of a single CPU could be made
+available to virtual machine environments. There are couple OEMS that
+support NUMA hardware which are hot pluggable as well, where physical
+node insertion and removal require support for CPU hotplug.
+
+Such advances require CPUs available to a kernel to be removed either for
+provisioning reasons, or for RAS purposes to keep an offending CPU off
+system execution path. Hence the need for CPU hotplug support in the
+Linux kernel.
+
+A more novel use of CPU-hotplug support is its use today in suspend
+resume support for SMP. Dual-core and HT support makes even
+a laptop run SMP kernels which didn't support these methods. SMP support
+for suspend/resume is a work in progress.
+
+General Stuff about CPU Hotplug
+--------------------------------
+
+Command Line Switches
+---------------------
+maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using
+ maxcpus=2 will only boot 2. You can choose to bring the
+ other cpus later online, read FAQ's for more info.
+
+additional_cpus=n [x86_64 only] use this to limit hotpluggable cpus.
+ This option sets
+ cpu_possible_map = cpu_present_map + additional_cpus
+
+CPU maps and such
+-----------------
+[More on cpumaps and primitive to manipulate, please check
+include/linux/cpumask.h that has more descriptive text.]
+
+cpu_possible_map: Bitmap of possible CPUs that can ever be available in the
+system. This is used to allocate some boot time memory for per_cpu variables
+that aren't designed to grow/shrink as CPUs are made available or removed.
+Once set during boot time discovery phase, the map is static, i.e no bits
+are added or removed anytime. Trimming it accurately for your system needs
+upfront can save some boot time memory. See below for how we use heuristics
+in x86_64 case to keep this under check.
+
+cpu_online_map: Bitmap of all CPUs currently online. Its set in __cpu_up()
+after a cpu is available for kernel scheduling and ready to receive
+interrupts from devices. Its cleared when a cpu is brought down using
+__cpu_disable(), before which all OS services including interrupts are
+migrated to another target CPU.
+
+cpu_present_map: Bitmap of CPUs currently present in the system. Not all
+of them may be online. When physical hotplug is processed by the relevant
+subsystem (e.g ACPI) can change and new bit either be added or removed
+from the map depending on the event is hot-add/hot-remove. There are currently
+no locking rules as of now. Typical usage is to init topology during boot,
+at which time hotplug is disabled.
+
+You really dont need to manipulate any of the system cpu maps. They should
+be read-only for most use. When setting up per-cpu resources almost always use
+cpu_possible_map/for_each_cpu() to iterate.
+
+Never use anything other than cpumask_t to represent bitmap of CPUs.
+
+#include <linux/cpumask.h>
+
+for_each_cpu - Iterate over cpu_possible_map
+for_each_online_cpu - Iterate over cpu_online_map
+for_each_present_cpu - Iterate over cpu_present_map
+for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
+
+#include <linux/cpu.h>
+lock_cpu_hotplug() and unlock_cpu_hotplug():
+
+The above calls are used to inhibit cpu hotplug operations. While holding the
+cpucontrol mutex, cpu_online_map will not change. If you merely need to avoid
+cpus going away, you could also use preempt_disable() and preempt_enable()
+for those sections. Just remember the critical section cannot call any
+function that can sleep or schedule this process away. The preempt_disable()
+will work as long as stop_machine_run() is used to take a cpu down.
+
+CPU Hotplug - Frequently Asked Questions.
+
+Q: How to i enable my kernel to support CPU hotplug?
+A: When doing make defconfig, Enable CPU hotplug support
+
+ "Processor type and Features" -> Support for Hotpluggable CPUs
+
+Make sure that you have CONFIG_HOTPLUG, and CONFIG_SMP turned on as well.
+
+You would need to enable CONFIG_HOTPLUG_CPU for SMP suspend/resume support
+as well.
+
+Q: What architectures support CPU hotplug?
+A: As of 2.6.14, the following architectures support CPU hotplug.
+
+i386 (Intel), ppc, ppc64, parisc, s390, ia64 and x86_64
+
+Q: How to test if hotplug is supported on the newly built kernel?
+A: You should now notice an entry in sysfs.
+
+Check if sysfs is mounted, using the "mount" command. You should notice
+an entry as shown below in the output.
+
+....
+none on /sys type sysfs (rw)
+....
+
+if this is not mounted, do the following.
+
+#mkdir /sysfs
+#mount -t sysfs sys /sys
+
+now you should see entries for all present cpu, the following is an example
+in a 8-way system.
+
+#pwd
+#/sys/devices/system/cpu
+#ls -l
+total 0
+drwxr-xr-x 10 root root 0 Sep 19 07:44 .
+drwxr-xr-x 13 root root 0 Sep 19 07:45 ..
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu0
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu1
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu2
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu3
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu4
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu5
+drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu6
+drwxr-xr-x 3 root root 0 Sep 19 07:48 cpu7
+
+Under each directory you would find an "online" file which is the control
+file to logically online/offline a processor.
+
+Q: Does hot-add/hot-remove refer to physical add/remove of cpus?
+A: The usage of hot-add/remove may not be very consistently used in the code.
+CONFIG_CPU_HOTPLUG enables logical online/offline capability in the kernel.
+To support physical addition/removal, one would need some BIOS hooks and
+the platform should have something like an attention button in PCI hotplug.
+CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs.
+
+Q: How do i logically offline a CPU?
+A: Do the following.
+
+#echo 0 > /sys/devices/system/cpu/cpuX/online
+
+once the logical offline is successful, check
+
+#cat /proc/interrupts
+
+you should now not see the CPU that you removed. Also online file will report
+the state as 0 when a cpu if offline and 1 when its online.
+
+#To display the current cpu state.
+#cat /sys/devices/system/cpu/cpuX/online
+
+Q: Why cant i remove CPU0 on some systems?
+A: Some architectures may have some special dependency on a certain CPU.
+
+For e.g in IA64 platforms we have ability to sent platform interrupts to the
+OS. a.k.a Corrected Platform Error Interrupts (CPEI). In current ACPI
+specifications, we didn't have a way to change the target CPU. Hence if the
+current ACPI version doesn't support such re-direction, we disable that CPU
+by making it not-removable.
+
+In such cases you will also notice that the online file is missing under cpu0.
+
+Q: How do i find out if a particular CPU is not removable?
+A: Depending on the implementation, some architectures may show this by the
+absence of the "online" file. This is done if it can be determined ahead of
+time that this CPU cannot be removed.
+
+In some situations, this can be a run time check, i.e if you try to remove the
+last CPU, this will not be permitted. You can find such failures by
+investigating the return value of the "echo" command.
+
+Q: What happens when a CPU is being logically offlined?
+A: The following happen, listed in no particular order :-)
+
+- A notification is sent to in-kernel registered modules by sending an event
+ CPU_DOWN_PREPARE
+- All process is migrated away from this outgoing CPU to a new CPU
+- All interrupts targeted to this CPU is migrated to a new CPU
+- timers/bottom half/task lets are also migrated to a new CPU
+- Once all services are migrated, kernel calls an arch specific routine
+ __cpu_disable() to perform arch specific cleanup.
+- Once this is successful, an event for successful cleanup is sent by an event
+ CPU_DEAD.
+
+ "It is expected that each service cleans up when the CPU_DOWN_PREPARE
+ notifier is called, when CPU_DEAD is called its expected there is nothing
+ running on behalf of this CPU that was offlined"
+
+Q: If i have some kernel code that needs to be aware of CPU arrival and
+ departure, how to i arrange for proper notification?
+A: This is what you would need in your kernel code to receive notifications.
+
+ #include <linux/cpu.h>
+ static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+ {
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ foobar_online_action(cpu);
+ break;
+ case CPU_DEAD:
+ foobar_dead_action(cpu);
+ break;
+ }
+ return NOTIFY_OK;
+ }
+
+ static struct notifier_block foobar_cpu_notifer =
+ {
+ .notifier_call = foobar_cpu_callback,
+ };
+
+
+In your init function,
+
+ register_cpu_notifier(&foobar_cpu_notifier);
+
+You can fail PREPARE notifiers if something doesn't work to prepare resources.
+This will stop the activity and send a following CANCELED event back.
+
+CPU_DEAD should not be failed, its just a goodness indication, but bad
+things will happen if a notifier in path sent a BAD notify code.
+
+Q: I don't see my action being called for all CPUs already up and running?
+A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
+ If you need to perform some action for each cpu already in the system, then
+
+ for_each_online_cpu(i) {
+ foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i);
+ foobar_cpu_callback(&foobar-cpu_notifier, CPU_ONLINE, i);
+ }
+
+Q: If i would like to develop cpu hotplug support for a new architecture,
+ what do i need at a minimum?
+A: The following are what is required for CPU hotplug infrastructure to work
+ correctly.
+
+ - Make sure you have an entry in Kconfig to enable CONFIG_HOTPLUG_CPU
+ - __cpu_up() - Arch interface to bring up a CPU
+ - __cpu_disable() - Arch interface to shutdown a CPU, no more interrupts
+ can be handled by the kernel after the routine
+ returns. Including local APIC timers etc are
+ shutdown.
+ - __cpu_die() - This actually supposed to ensure death of the CPU.
+ Actually look at some example code in other arch
+ that implement CPU hotplug. The processor is taken
+ down from the idle() loop for that specific
+ architecture. __cpu_die() typically waits for some
+ per_cpu state to be set, to ensure the processor
+ dead routine is called to be sure positively.
+
+Q: I need to ensure that a particular cpu is not removed when there is some
+ work specific to this cpu is in progress.
+A: First switch the current thread context to preferred cpu
+
+ int my_func_on_cpu(int cpu)
+ {
+ cpumask_t saved_mask, new_mask = CPU_MASK_NONE;
+ int curr_cpu, err = 0;
+
+ saved_mask = current->cpus_allowed;
+ cpu_set(cpu, new_mask);
+ err = set_cpus_allowed(current, new_mask);
+
+ if (err)
+ return err;
+
+ /*
+ * If we got scheduled out just after the return from
+ * set_cpus_allowed() before running the work, this ensures
+ * we stay locked.
+ */
+ curr_cpu = get_cpu();
+
+ if (curr_cpu != cpu) {
+ err = -EAGAIN;
+ goto ret;
+ } else {
+ /*
+ * Do work : But cant sleep, since get_cpu() disables preempt
+ */
+ }
+ ret:
+ put_cpu();
+ set_cpus_allowed(current, saved_mask);
+ return err;
+ }
+
+
+Q: How do we determine how many CPUs are available for hotplug.
+A: There is no clear spec defined way from ACPI that can give us that
+ information today. Based on some input from Natalie of Unisys,
+ that the ACPI MADT (Multiple APIC Description Tables) marks those possible
+ CPUs in a system with disabled status.
+
+ Andi implemented some simple heuristics that count the number of disabled
+ CPUs in MADT as hotpluggable CPUS. In the case there are no disabled CPUS
+ we assume 1/2 the number of CPUs currently present can be hotplugged.
+
+ Caveat: Today's ACPI MADT can only provide 256 entries since the apicid field
+ in MADT is only 8 bits.
+
+User Space Notification
+
+Hotplug support for devices is common in Linux today. Its being used today to
+support automatic configuration of network, usb and pci devices. A hotplug
+event can be used to invoke an agent script to perform the configuration task.
+
+You can add /etc/hotplug/cpu.agent to handle hotplug notification user space
+scripts.
+
+ #!/bin/bash
+ # $Id: cpu.agent
+ # Kernel hotplug params include:
+ #ACTION=%s [online or offline]
+ #DEVPATH=%s
+ #
+ cd /etc/hotplug
+ . ./hotplug.functions
+
+ case $ACTION in
+ online)
+ echo `date` ":cpu.agent" add cpu >> /tmp/hotplug.txt
+ ;;
+ offline)
+ echo `date` ":cpu.agent" remove cpu >>/tmp/hotplug.txt
+ ;;
+ *)
+ debug_mesg CPU $ACTION event not supported
+ exit 1
+ ;;
+ esac
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index a09a8eb80665..990998ee10b6 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -14,7 +14,10 @@ CONTENTS:
1.1 What are cpusets ?
1.2 Why are cpusets needed ?
1.3 How are cpusets implemented ?
- 1.4 How do I use cpusets ?
+ 1.4 What are exclusive cpusets ?
+ 1.5 What does notify_on_release do ?
+ 1.6 What is memory_pressure ?
+ 1.7 How do I use cpusets ?
2. Usage Examples and Syntax
2.1 Basic Usage
2.2 Adding/removing cpus
@@ -49,29 +52,6 @@ its cpus_allowed vector, and the kernel page allocator will not
allocate a page on a node that is not allowed in the requesting tasks
mems_allowed vector.
-If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct
-ancestor or descendent, may share any of the same CPUs or Memory Nodes.
-A cpuset that is cpu exclusive has a sched domain associated with it.
-The sched domain consists of all cpus in the current cpuset that are not
-part of any exclusive child cpusets.
-This ensures that the scheduler load balacing code only balances
-against the cpus that are in the sched domain as defined above and not
-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,
@@ -155,7 +135,7 @@ Cpusets extends these two mechanisms as follows:
The implementation of cpusets requires a few, simple hooks
into the rest of the kernel, none in performance critical paths:
- - in main/init.c, to initialize the root cpuset at system boot.
+ - in init/main.c, to initialize the root cpuset at system boot.
- in fork and exit, to attach and detach a task from its cpuset.
- in sched_setaffinity, to mask the requested CPUs by what's
allowed in that tasks cpuset.
@@ -166,7 +146,7 @@ into the rest of the kernel, none in performance critical paths:
and related changes in both sched.c and arch/ia64/kernel/domain.c
- in the mbind and set_mempolicy system calls, to mask the requested
Memory Nodes by what's allowed in that tasks cpuset.
- - in page_alloc, to restrict memory to allowed nodes.
+ - in page_alloc.c, to restrict memory to allowed nodes.
- in vmscan.c, to restrict page recovery to the current cpuset.
In addition a new file system, of type "cpuset" may be mounted,
@@ -192,9 +172,15 @@ containing the following files describing that cpuset:
- cpus: list of CPUs in that cpuset
- mems: list of Memory Nodes in that cpuset
+ - memory_migrate flag: if set, move pages to cpusets nodes
- cpu_exclusive flag: is cpu placement exclusive?
- mem_exclusive flag: is memory placement exclusive?
- tasks: list of tasks (by pid) attached to that cpuset
+ - notify_on_release flag: run /sbin/cpuset_release_agent on exit?
+ - memory_pressure: measure of how much paging pressure in cpuset
+
+In addition, the root cpuset only has the following file:
+ - memory_pressure_enabled flag: compute memory_pressure?
New cpusets are created using the mkdir system call or shell
command. The properties of a cpuset, such as its flags, allowed
@@ -228,7 +214,108 @@ exclusive cpuset. Also, the use of a Linux virtual file system (vfs)
to represent the cpuset hierarchy provides for a familiar permission
and name space for cpusets, with a minimum of additional kernel code.
-1.4 How do I use cpusets ?
+
+1.4 What are exclusive cpusets ?
+--------------------------------
+
+If a cpuset is cpu or mem exclusive, no other cpuset, other than
+a direct ancestor or descendent, may share any of the same CPUs or
+Memory Nodes.
+
+A cpuset that is cpu_exclusive has a scheduler (sched) domain
+associated with it. The sched domain consists of all CPUs in the
+current cpuset that are not part of any exclusive child cpusets.
+This ensures that the scheduler load balancing code only balances
+against the CPUs that are in the sched domain as defined above and
+not 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.
+
+
+1.5 What does notify_on_release do ?
+------------------------------------
+
+If the notify_on_release flag is enabled (1) in a cpuset, then whenever
+the last task in the cpuset leaves (exits or attaches to some other
+cpuset) and the last child cpuset of that cpuset is removed, then
+the kernel runs the command /sbin/cpuset_release_agent, supplying the
+pathname (relative to the mount point of the cpuset file system) of the
+abandoned cpuset. This enables automatic removal of abandoned cpusets.
+The default value of notify_on_release in the root cpuset at system
+boot is disabled (0). The default value of other cpusets at creation
+is the current value of their parents notify_on_release setting.
+
+
+1.6 What is memory_pressure ?
+-----------------------------
+The memory_pressure of a cpuset provides a simple per-cpuset metric
+of the rate that the tasks in a cpuset are attempting to free up in
+use memory on the nodes of the cpuset to satisfy additional memory
+requests.
+
+This enables batch managers monitoring jobs running in dedicated
+cpusets to efficiently detect what level of memory pressure that job
+is causing.
+
+This is useful both on tightly managed systems running a wide mix of
+submitted jobs, which may choose to terminate or re-prioritize jobs that
+are trying to use more memory than allowed on the nodes assigned them,
+and with tightly coupled, long running, massively parallel scientific
+computing jobs that will dramatically fail to meet required performance
+goals if they start to use more memory than allowed to them.
+
+This mechanism provides a very economical way for the batch manager
+to monitor a cpuset for signs of memory pressure. It's up to the
+batch manager or other user code to decide what to do about it and
+take action.
+
+==> Unless this feature is enabled by writing "1" to the special file
+ /dev/cpuset/memory_pressure_enabled, the hook in the rebalance
+ code of __alloc_pages() for this metric reduces to simply noticing
+ that the cpuset_memory_pressure_enabled flag is zero. So only
+ systems that enable this feature will compute the metric.
+
+Why a per-cpuset, running average:
+
+ Because this meter is per-cpuset, rather than per-task or mm,
+ the system load imposed by a batch scheduler monitoring this
+ metric is sharply reduced on large systems, because a scan of
+ the tasklist can be avoided on each set of queries.
+
+ Because this meter is a running average, instead of an accumulating
+ counter, a batch scheduler can detect memory pressure with a
+ single read, instead of having to read and accumulate results
+ for a period of time.
+
+ Because this meter is per-cpuset rather than per-task or mm,
+ the batch scheduler can obtain the key information, memory
+ pressure in a cpuset, with a single read, rather than having to
+ query and accumulate results over all the (dynamically changing)
+ set of tasks in the cpuset.
+
+A per-cpuset simple digital filter (requires a spinlock and 3 words
+of data per-cpuset) is kept, and updated by any task attached to that
+cpuset, if it enters the synchronous (direct) page reclaim code.
+
+A per-cpuset file provides an integer number representing the recent
+(half-life of 10 seconds) rate of direct page reclaims caused by
+the tasks in the cpuset, in units of reclaims attempted per second,
+times 1000.
+
+
+1.7 How do I use cpusets ?
--------------------------
In order to minimize the impact of cpusets on critical kernel
@@ -277,6 +364,30 @@ 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.
+Normally, once a page is allocated (given a physical page
+of main memory) then that page stays on whatever node it
+was allocated, so long as it remains allocated, even if the
+cpusets memory placement policy 'mems' subsequently changes.
+If the cpuset flag file 'memory_migrate' is set true, then when
+tasks are attached to that cpuset, any pages that task had
+allocated to it on nodes in its previous cpuset are migrated
+to the tasks new cpuset. Depending on the implementation,
+this migration may either be done by swapping the page out,
+so that the next time the page is referenced, it will be paged
+into the tasks new cpuset, usually on the node where it was
+referenced, or this migration may be done by directly copying
+the pages from the tasks previous cpuset to the new cpuset,
+where possible to the same node, relative to the new cpuset,
+as the node that held the page, relative to the old cpuset.
+Also if 'memory_migrate' is set true, then if that cpusets
+'mems' file is modified, pages allocated to tasks in that
+cpuset, that were on nodes in the previous setting of 'mems',
+will be moved to nodes in the new setting of 'mems.' Again,
+depending on the implementation, this might be done by swapping,
+or by direct copying. In either case, pages that were not in
+the tasks prior cpuset, or in the cpusets prior 'mems' setting,
+will not be moved.
+
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
diff --git a/Documentation/drivers/edac/edac.txt b/Documentation/drivers/edac/edac.txt
new file mode 100644
index 000000000000..d37191fe5681
--- /dev/null
+++ b/Documentation/drivers/edac/edac.txt
@@ -0,0 +1,673 @@
+
+
+EDAC - Error Detection And Correction
+
+Written by Doug Thompson <norsk5@xmission.com>
+7 Dec 2005
+
+
+EDAC was written by:
+ Thayne Harbaugh,
+ modified by Dave Peterson, Doug Thompson, et al,
+ from the bluesmoke.sourceforge.net project.
+
+
+============================================================================
+EDAC PURPOSE
+
+The 'edac' kernel module goal is to detect and report errors that occur
+within the computer system. In the initial release, memory Correctable Errors
+(CE) and Uncorrectable Errors (UE) are the primary errors being harvested.
+
+Detecting CE events, then harvesting those events and reporting them,
+CAN be a predictor of future UE events. With CE events, the system can
+continue to operate, but with less safety. Preventive maintainence and
+proactive part replacement of memory DIMMs exhibiting CEs can reduce
+the likelihood of the dreaded UE events and system 'panics'.
+
+
+In addition, PCI Bus Parity and SERR Errors are scanned for on PCI devices
+in order to determine if errors are occurring on data transfers.
+The presence of PCI Parity errors must be examined with a grain of salt.
+There are several addin adapters that do NOT follow the PCI specification
+with regards to Parity generation and reporting. The specification says
+the vendor should tie the parity status bits to 0 if they do not intend
+to generate parity. Some vendors do not do this, and thus the parity bit
+can "float" giving false positives.
+
+The PCI Parity EDAC device has the ability to "skip" known flakey
+cards during the parity scan. These are set by the parity "blacklist"
+interface in the sysfs for PCI Parity. (See the PCI section in the sysfs
+section below.) There is also a parity "whitelist" which is used as
+an explicit list of devices to scan, while the blacklist is a list
+of devices to skip.
+
+EDAC will have future error detectors that will be added or integrated
+into EDAC in the following list:
+
+ MCE Machine Check Exception
+ MCA Machine Check Architecture
+ NMI NMI notification of ECC errors
+ MSRs Machine Specific Register error cases
+ and other mechanisms.
+
+These errors are usually bus errors, ECC errors, thermal throttling
+and the like.
+
+
+============================================================================
+EDAC VERSIONING
+
+EDAC is composed of a "core" module (edac_mc.ko) and several Memory
+Controller (MC) driver modules. On a given system, the CORE
+is loaded and one MC driver will be loaded. Both the CORE and
+the MC driver have individual versions that reflect current release
+level of their respective modules. Thus, to "report" on what version
+a system is running, one must report both the CORE's and the
+MC driver's versions.
+
+
+LOADING
+
+If 'edac' was statically linked with the kernel then no loading is
+necessary. If 'edac' was built as modules then simply modprobe the
+'edac' pieces that you need. You should be able to modprobe
+hardware-specific modules and have the dependencies load the necessary core
+modules.
+
+Example:
+
+$> modprobe amd76x_edac
+
+loads both the amd76x_edac.ko memory controller module and the edac_mc.ko
+core module.
+
+
+============================================================================
+EDAC sysfs INTERFACE
+
+EDAC presents a 'sysfs' interface for control, reporting and attribute
+reporting purposes.
+
+EDAC lives in the /sys/devices/system/edac directory. Within this directory
+there currently reside 2 'edac' components:
+
+ mc memory controller(s) system
+ pci PCI status system
+
+
+============================================================================
+Memory Controller (mc) Model
+
+First a background on the memory controller's model abstracted in EDAC.
+Each mc device controls a set of DIMM memory modules. These modules are
+layed out in a Chip-Select Row (csrowX) and Channel table (chX). There can
+be multiple csrows and two channels.
+
+Memory controllers allow for several csrows, with 8 csrows being a typical value.
+Yet, the actual number of csrows depends on the electrical "loading"
+of a given motherboard, memory controller and DIMM characteristics.
+
+Dual channels allows for 128 bit data transfers to the CPU from memory.
+
+
+ Channel 0 Channel 1
+ ===================================
+ csrow0 | DIMM_A0 | DIMM_B0 |
+ csrow1 | DIMM_A0 | DIMM_B0 |
+ ===================================
+
+ ===================================
+ csrow2 | DIMM_A1 | DIMM_B1 |
+ csrow3 | DIMM_A1 | DIMM_B1 |
+ ===================================
+
+In the above example table there are 4 physical slots on the motherboard
+for memory DIMMs:
+
+ DIMM_A0
+ DIMM_B0
+ DIMM_A1
+ DIMM_B1
+
+Labels for these slots are usually silk screened on the motherboard. Slots
+labeled 'A' are channel 0 in this example. Slots labled 'B'
+are channel 1. Notice that there are two csrows possible on a
+physical DIMM. These csrows are allocated their csrow assignment
+based on the slot into which the memory DIMM is placed. Thus, when 1 DIMM
+is placed in each Channel, the csrows cross both DIMMs.
+
+Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
+Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
+will have 1 csrow, csrow0. csrow1 will be empty. On the other hand,
+when 2 dual ranked DIMMs are similiaryly placed, then both csrow0 and
+csrow1 will be populated. The pattern repeats itself for csrow2 and
+csrow3.
+
+The representation of the above is reflected in the directory tree
+in EDAC's sysfs interface. Starting in directory
+/sys/devices/system/edac/mc each memory controller will be represented
+by its own 'mcX' directory, where 'X" is the index of the MC.
+
+
+ ..../edac/mc/
+ |
+ |->mc0
+ |->mc1
+ |->mc2
+ ....
+
+Under each 'mcX' directory each 'csrowX' is again represented by a
+'csrowX', where 'X" is the csrow index:
+
+
+ .../mc/mc0/
+ |
+ |->csrow0
+ |->csrow2
+ |->csrow3
+ ....
+
+Notice that there is no csrow1, which indicates that csrow0 is
+composed of a single ranked DIMMs. This should also apply in both
+Channels, in order to have dual-channel mode be operational. Since
+both csrow2 and csrow3 are populated, this indicates a dual ranked
+set of DIMMs for channels 0 and 1.
+
+
+Within each of the 'mc','mcX' and 'csrowX' directories are several
+EDAC control and attribute files.
+
+
+============================================================================
+DIRECTORY 'mc'
+
+In directory 'mc' are EDAC system overall control and attribute files:
+
+
+Panic on UE control file:
+
+ 'panic_on_ue'
+
+ An uncorrectable error will cause a machine panic. This is usually
+ desirable. It is a bad idea to continue when an uncorrectable error
+ occurs - it is indeterminate what was uncorrected and the operating
+ system context might be so mangled that continuing will lead to further
+ corruption. If the kernel has MCE configured, then EDAC will never
+ notice the UE.
+
+ LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
+
+ RUN TIME: echo "1" >/sys/devices/system/edac/mc/panic_on_ue
+
+
+Log UE control file:
+
+ 'log_ue'
+
+ Generate kernel messages describing uncorrectable errors. These errors
+ are reported through the system message log system. UE statistics
+ will be accumulated even when UE logging is disabled.
+
+ LOAD TIME: module/kernel parameter: log_ue=[0|1]
+
+ RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ue
+
+
+Log CE control file:
+
+ 'log_ce'
+
+ Generate kernel messages describing correctable errors. These
+ errors are reported through the system message log system.
+ CE statistics will be accumulated even when CE logging is disabled.
+
+ LOAD TIME: module/kernel parameter: log_ce=[0|1]
+
+ RUN TIME: echo "1" >/sys/devices/system/edac/mc/log_ce
+
+
+Polling period control file:
+
+ 'poll_msec'
+
+ The time period, in milliseconds, for polling for error information.
+ Too small a value wastes resources. Too large a value might delay
+ necessary handling of errors and might loose valuable information for
+ locating the error. 1000 milliseconds (once each second) is about
+ right for most uses.
+
+ LOAD TIME: module/kernel parameter: poll_msec=[0|1]
+
+ RUN TIME: echo "1000" >/sys/devices/system/edac/mc/poll_msec
+
+
+Module Version read-only attribute file:
+
+ 'mc_version'
+
+ The EDAC CORE modules's version and compile date are shown here to
+ indicate what EDAC is running.
+
+
+
+============================================================================
+'mcX' DIRECTORIES
+
+
+In 'mcX' directories are EDAC control and attribute files for
+this 'X" instance of the memory controllers:
+
+
+Counter reset control file:
+
+ 'reset_counters'
+
+ This write-only control file will zero all the statistical counters
+ for UE and CE errors. Zeroing the counters will also reset the timer
+ indicating how long since the last counter zero. This is useful
+ for computing errors/time. Since the counters are always reset at
+ driver initialization time, no module/kernel parameter is available.
+
+ RUN TIME: echo "anything" >/sys/devices/system/edac/mc/mc0/counter_reset
+
+ This resets the counters on memory controller 0
+
+
+Seconds since last counter reset control file:
+
+ 'seconds_since_reset'
+
+ This attribute file displays how many seconds have elapsed since the
+ last counter reset. This can be used with the error counters to
+ measure error rates.
+
+
+
+DIMM capability attribute file:
+
+ 'edac_capability'
+
+ The EDAC (Error Detection and Correction) capabilities/modes of
+ the memory controller hardware.
+
+
+DIMM Current Capability attribute file:
+
+ 'edac_current_capability'
+
+ The EDAC capabilities available with the hardware
+ configuration. This may not be the same as "EDAC capability"
+ if the correct memory is not used. If a memory controller is
+ capable of EDAC, but DIMMs without check bits are in use, then
+ Parity, SECDED, S4ECD4ED capabilities will not be available
+ even though the memory controller might be capable of those
+ modes with the proper memory loaded.
+
+
+Memory Type supported on this controller attribute file:
+
+ 'supported_mem_type'
+
+ This attribute file displays the memory type, usually
+ buffered and unbuffered DIMMs.
+
+
+Memory Controller name attribute file:
+
+ 'mc_name'
+
+ This attribute file displays the type of memory controller
+ that is being utilized.
+
+
+Memory Controller Module name attribute file:
+
+ 'module_name'
+
+ This attribute file displays the memory controller module name,
+ version and date built. The name of the memory controller
+ hardware - some drivers work with multiple controllers and
+ this field shows which hardware is present.
+
+
+Total memory managed by this memory controller attribute file:
+
+ 'size_mb'
+
+ This attribute file displays, in count of megabytes, of memory
+ that this instance of memory controller manages.
+
+
+Total Uncorrectable Errors count attribute file:
+
+ 'ue_count'
+
+ This attribute file displays the total count of uncorrectable
+ errors that have occurred on this memory controller. If panic_on_ue
+ is set this counter will not have a chance to increment,
+ since EDAC will panic the system.
+
+
+Total UE count that had no information attribute fileY:
+
+ 'ue_noinfo_count'
+
+ This attribute file displays the number of UEs that
+ have occurred have occurred with no informations as to which DIMM
+ slot is having errors.
+
+
+Total Correctable Errors count attribute file:
+
+ 'ce_count'
+
+ This attribute file displays the total count of correctable
+ errors that have occurred on this memory controller. This
+ count is very important to examine. CEs provide early
+ indications that a DIMM is beginning to fail. This count
+ field should be monitored for non-zero values and report
+ such information to the system administrator.
+
+
+Total Correctable Errors count attribute file:
+
+ 'ce_noinfo_count'
+
+ This attribute file displays the number of CEs that
+ have occurred wherewith no informations as to which DIMM slot
+ is having errors. Memory is handicapped, but operational,
+ yet no information is available to indicate which slot
+ the failing memory is in. This count field should be also
+ be monitored for non-zero values.
+
+Device Symlink:
+
+ 'device'
+
+ Symlink to the memory controller device
+
+
+
+============================================================================
+'csrowX' DIRECTORIES
+
+In the 'csrowX' directories are EDAC control and attribute files for
+this 'X" instance of csrow:
+
+
+Total Uncorrectable Errors count attribute file:
+
+ 'ue_count'
+
+ This attribute file displays the total count of uncorrectable
+ errors that have occurred on this csrow. If panic_on_ue is set
+ this counter will not have a chance to increment, since EDAC
+ will panic the system.
+
+
+Total Correctable Errors count attribute file:
+
+ 'ce_count'
+
+ This attribute file displays the total count of correctable
+ errors that have occurred on this csrow. This
+ count is very important to examine. CEs provide early
+ indications that a DIMM is beginning to fail. This count
+ field should be monitored for non-zero values and report
+ such information to the system administrator.
+
+
+Total memory managed by this csrow attribute file:
+
+ 'size_mb'
+
+ This attribute file displays, in count of megabytes, of memory
+ that this csrow contatins.
+
+
+Memory Type attribute file:
+
+ 'mem_type'
+
+ This attribute file will display what type of memory is currently
+ on this csrow. Normally, either buffered or unbuffered memory.
+
+
+EDAC Mode of operation attribute file:
+
+ 'edac_mode'
+
+ This attribute file will display what type of Error detection
+ and correction is being utilized.
+
+
+Device type attribute file:
+
+ 'dev_type'
+
+ This attribute file will display what type of DIMM device is
+ being utilized. Example: x4
+
+
+Channel 0 CE Count attribute file:
+
+ 'ch0_ce_count'
+
+ This attribute file will display the count of CEs on this
+ DIMM located in channel 0.
+
+
+Channel 0 UE Count attribute file:
+
+ 'ch0_ue_count'
+
+ This attribute file will display the count of UEs on this
+ DIMM located in channel 0.
+
+
+Channel 0 DIMM Label control file:
+
+ 'ch0_dimm_label'
+
+ This control file allows this DIMM to have a label assigned
+ to it. With this label in the module, when errors occur
+ the output can provide the DIMM label in the system log.
+ This becomes vital for panic events to isolate the
+ cause of the UE event.
+
+ DIMM Labels must be assigned after booting, with information
+ that correctly identifies the physical slot with its
+ silk screen label. This information is currently very
+ motherboard specific and determination of this information
+ must occur in userland at this time.
+
+
+Channel 1 CE Count attribute file:
+
+ 'ch1_ce_count'
+
+ This attribute file will display the count of CEs on this
+ DIMM located in channel 1.
+
+
+Channel 1 UE Count attribute file:
+
+ 'ch1_ue_count'
+
+ This attribute file will display the count of UEs on this
+ DIMM located in channel 0.
+
+
+Channel 1 DIMM Label control file:
+
+ 'ch1_dimm_label'
+
+ This control file allows this DIMM to have a label assigned
+ to it. With this label in the module, when errors occur
+ the output can provide the DIMM label in the system log.
+ This becomes vital for panic events to isolate the
+ cause of the UE event.
+
+ DIMM Labels must be assigned after booting, with information
+ that correctly identifies the physical slot with its
+ silk screen label. This information is currently very
+ motherboard specific and determination of this information
+ must occur in userland at this time.
+
+
+============================================================================
+SYSTEM LOGGING
+
+If logging for UEs and CEs are enabled then system logs will have
+error notices indicating errors that have been detected:
+
+MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0,
+channel 1 "DIMM_B1": amd76x_edac
+
+MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0,
+channel 1 "DIMM_B1": amd76x_edac
+
+
+The structure of the message is:
+ the memory controller (MC0)
+ Error type (CE)
+ memory page (0x283)
+ offset in the page (0xce0)
+ the byte granularity (grain 8)
+ or resolution of the error
+ the error syndrome (0xb741)
+ memory row (row 0)
+ memory channel (channel 1)
+ DIMM label, if set prior (DIMM B1
+ and then an optional, driver-specific message that may
+ have additional information.
+
+Both UEs and CEs with no info will lack all but memory controller,
+error type, a notice of "no info" and then an optional,
+driver-specific error message.
+
+
+
+============================================================================
+PCI Bus Parity Detection
+
+
+On Header Type 00 devices the primary status is looked at
+for any parity error regardless of whether Parity is enabled on the
+device. (The spec indicates parity is generated in some cases).
+On Header Type 01 bridges, the secondary status register is also
+looked at to see if parity ocurred on the bus on the other side of
+the bridge.
+
+
+SYSFS CONFIGURATION
+
+Under /sys/devices/system/edac/pci are control and attribute files as follows:
+
+
+Enable/Disable PCI Parity checking control file:
+
+ 'check_pci_parity'
+
+
+ This control file enables or disables the PCI Bus Parity scanning
+ operation. Writing a 1 to this file enables the scanning. Writing
+ a 0 to this file disables the scanning.
+
+ Enable:
+ echo "1" >/sys/devices/system/edac/pci/check_pci_parity
+
+ Disable:
+ echo "0" >/sys/devices/system/edac/pci/check_pci_parity
+
+
+
+Panic on PCI PARITY Error:
+
+ 'panic_on_pci_parity'
+
+
+ This control files enables or disables panic'ing when a parity
+ error has been detected.
+
+
+ module/kernel parameter: panic_on_pci_parity=[0|1]
+
+ Enable:
+ echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
+
+ Disable:
+ echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
+
+
+Parity Count:
+
+ 'pci_parity_count'
+
+ This attribute file will display the number of parity errors that
+ have been detected.
+
+
+
+PCI Device Whitelist:
+
+ 'pci_parity_whitelist'
+
+ This control file allows for an explicit list of PCI devices to be
+ scanned for parity errors. Only devices found on this list will
+ be examined. The list is a line of hexadecimel VENDOR and DEVICE
+ ID tuples:
+
+ 1022:7450,1434:16a6
+
+ One or more can be inserted, seperated by a comma.
+
+ To write the above list doing the following as one command line:
+
+ echo "1022:7450,1434:16a6"
+ > /sys/devices/system/edac/pci/pci_parity_whitelist
+
+
+
+ To display what the whitelist is, simply 'cat' the same file.
+
+
+PCI Device Blacklist:
+
+ 'pci_parity_blacklist'
+
+ This control file allows for a list of PCI devices to be
+ skipped for scanning.
+ The list is a line of hexadecimel VENDOR and DEVICE ID tuples:
+
+ 1022:7450,1434:16a6
+
+ One or more can be inserted, seperated by a comma.
+
+ To write the above list doing the following as one command line:
+
+ echo "1022:7450,1434:16a6"
+ > /sys/devices/system/edac/pci/pci_parity_blacklist
+
+
+ To display what the whitelist current contatins,
+ simply 'cat' the same file.
+
+=======================================================================
+
+PCI Vendor and Devices IDs can be obtained with the lspci command. Using
+the -n option lspci will display the vendor and device IDs. The system
+adminstrator will have to determine which devices should be scanned or
+skipped.
+
+
+
+The two lists (white and black) are prioritized. blacklist is the lower
+priority and will NOT be utilized when a whitelist has been set.
+Turn OFF a whitelist by an empty echo command:
+
+ echo > /sys/devices/system/edac/pci/pci_parity_whitelist
+
+and any previous blacklist will be utililzed.
+
diff --git a/Documentation/dvb/avermedia.txt b/Documentation/dvb/avermedia.txt
index 2dc260b2b0a4..068070ff13cd 100644
--- a/Documentation/dvb/avermedia.txt
+++ b/Documentation/dvb/avermedia.txt
@@ -150,7 +150,8 @@ Getting the card going
The frontend module sp887x.o, requires an external firmware.
Please use the command "get_dvb_firmware sp887x" to download
- it. Then copy it to /usr/lib/hotplug/firmware.
+ it. Then copy it to /usr/lib/hotplug/firmware or /lib/firmware/
+ (depending on configuration of firmware hotplug).
Receiving DVB-T in Australia
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index be6eb4c75991..75c28a174092 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -23,7 +23,7 @@ use IO::Handle;
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t",
"dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
- "or51211", "or51132_qam", "or51132_vsb");
+ "or51211", "or51132_qam", "or51132_vsb", "bluebird");
# Check args
syntax() if (scalar(@ARGV) != 1);
@@ -34,7 +34,11 @@ for ($i=0; $i < scalar(@components); $i++) {
if ($cid eq $components[$i]) {
$outfile = eval($cid);
die $@ if $@;
- print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n";
+ print STDERR <<EOF;
+Firmware $outfile extracted successfully.
+Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware
+(depending on configuration of firmware hotplug).
+EOF
exit(0);
}
}
@@ -243,7 +247,7 @@ sub nxt2002 {
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
checkstandard();
-
+
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
verify("$tmpdir/SkyNETU.sys", $hash);
@@ -308,6 +312,19 @@ sub or51132_vsb {
$fwfile;
}
+sub bluebird {
+ my $url = "http://www.linuxtv.org/download/dvb/firmware/dvb-usb-bluebird-01.fw";
+ my $outfile = "dvb-usb-bluebird-01.fw";
+ my $hash = "658397cb9eba9101af9031302671f49d";
+
+ checkstandard();
+
+ wgetfile($outfile, $url);
+ verify($outfile,$hash);
+
+ $outfile;
+}
+
# ---------------------------------------------------------------
# Utilities
diff --git a/Documentation/dvb/ttusb-dec.txt b/Documentation/dvb/ttusb-dec.txt
index 5c1e984c26a7..b2f271cd784b 100644
--- a/Documentation/dvb/ttusb-dec.txt
+++ b/Documentation/dvb/ttusb-dec.txt
@@ -41,4 +41,5 @@ Hotplug Firmware Loading for 2.6 kernels
For 2.6 kernels the firmware is loaded at the point that the driver module is
loaded. See linux/Documentation/dvb/firmware.txt for more information.
-Copy the three files downloaded above into the /usr/lib/hotplug/firmware directory.
+Copy the three files downloaded above into the /usr/lib/hotplug/firmware or
+/lib/firmware directory (depending on configuration of firmware hotplug).
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs
index f90cc66ea919..9443a6d72cdd 100644
--- a/Documentation/fb/cyblafb/bugs
+++ b/Documentation/fb/cyblafb/bugs
@@ -11,4 +11,3 @@ 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/fb.modes b/Documentation/fb/cyblafb/fb.modes
index cf4351fc32ff..fe0e5223ba86 100644
--- a/Documentation/fb/cyblafb/fb.modes
+++ b/Documentation/fb/cyblafb/fb.modes
@@ -14,142 +14,141 @@
#
mode "640x480-50"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 47619 4294967256 24 17 0 216 3
endmode
mode "640x480-60"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 39682 4294967256 24 17 0 216 3
endmode
mode "640x480-70"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 34013 4294967256 24 17 0 216 3
endmode
mode "640x480-72"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 33068 4294967256 24 17 0 216 3
endmode
mode "640x480-75"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 31746 4294967256 24 17 0 216 3
endmode
mode "640x480-80"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 29761 4294967256 24 17 0 216 3
endmode
mode "640x480-85"
- geometry 640 480 640 3756 8
+ geometry 640 480 2048 4096 8
timings 28011 4294967256 24 17 0 216 3
endmode
mode "800x600-50"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 30303 96 24 14 0 136 11
endmode
mode "800x600-60"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 25252 96 24 14 0 136 11
endmode
mode "800x600-70"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 21645 96 24 14 0 136 11
endmode
mode "800x600-72"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 21043 96 24 14 0 136 11
endmode
mode "800x600-75"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 20202 96 24 14 0 136 11
endmode
mode "800x600-80"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 18939 96 24 14 0 136 11
endmode
mode "800x600-85"
- geometry 800 600 800 3221 8
+ geometry 800 600 2048 4096 8
timings 17825 96 24 14 0 136 11
endmode
mode "1024x768-50"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 19054 144 24 29 0 120 3
endmode
mode "1024x768-60"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 15880 144 24 29 0 120 3
endmode
mode "1024x768-70"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 13610 144 24 29 0 120 3
endmode
mode "1024x768-72"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 13232 144 24 29 0 120 3
endmode
mode "1024x768-75"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 12703 144 24 29 0 120 3
endmode
mode "1024x768-80"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 11910 144 24 29 0 120 3
endmode
mode "1024x768-85"
- geometry 1024 768 1024 2815 8
+ geometry 1024 768 2048 4096 8
timings 11209 144 24 29 0 120 3
endmode
mode "1280x1024-50"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 11114 232 16 39 0 160 3
endmode
mode "1280x1024-60"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 9262 232 16 39 0 160 3
endmode
mode "1280x1024-70"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 7939 232 16 39 0 160 3
endmode
mode "1280x1024-72"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 7719 232 16 39 0 160 3
endmode
mode "1280x1024-75"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 7410 232 16 39 0 160 3
endmode
mode "1280x1024-80"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 6946 232 16 39 0 160 3
endmode
mode "1280x1024-85"
- geometry 1280 1024 1280 2662 8
+ geometry 1280 1024 2048 4096 8
timings 6538 232 16 39 0 160 3
endmode
-
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance
index eb4e47a9cea6..8d15d5dfc6b3 100644
--- a/Documentation/fb/cyblafb/performance
+++ b/Documentation/fb/cyblafb/performance
@@ -77,4 +77,3 @@ patch that speeds up kernel bitblitting a lot ( > 20%).
| | | | |
| | | | |
+-----------+-----------------+-----------------+-----------------+
-
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo
index 80fb2f89b6c1..c5f6d0eae545 100644
--- a/Documentation/fb/cyblafb/todo
+++ b/Documentation/fb/cyblafb/todo
@@ -22,11 +22,10 @@ accelerated color blitting Who needs it? The console driver does use color
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
+TV-out Will be done later. Use "vga= " at boot time
+ to set a suitable video mode.
??? Feel free to contact me if you have any
feature requests
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage
index e627c8f54211..a39bb3d402a2 100644
--- a/Documentation/fb/cyblafb/usage
+++ b/Documentation/fb/cyblafb/usage
@@ -40,6 +40,16 @@ Selecting Modes
None of the modes possible to select as startup modes are affected by
the problems described at the end of the next subsection.
+ For all startup modes cyblafb chooses a virtual x resolution of 2048,
+ the only exception is mode 1280x1024 in combination with 32 bpp. This
+ allows ywrap scrolling for all those modes if rotation is 0 or 2, and
+ also fast scrolling if rotation is 1 or 3. The default virtual y reso-
+ lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32,
+ again with the only exception of 1280x1024 at 32 bpp.
+
+ Please do set your video memory size to 8 Mb in the Bios setup. Other
+ values will work, but performace is decreased for a lot of modes.
+
Mode changes using fbset
========================
@@ -54,20 +64,26 @@ Selecting Modes
- 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.
+ - cyblafb will allow you to select very high resolutions as
+ long as the hardware can be programmed to these modes. The
+ documented limit 1600x1200 is not enforced, but don't expect
+ perfect signal quality.
- Any request that violates the rules given above will be ignored and
- fbset will return an error.
+ Any request that violates the rules given above will be either changed
+ to something the hardware supports or an error value will be returned.
If you program a virtual y resolution higher than the hardware limit,
cyblafb will silently decrease that value to the highest possible
- value.
+ value. The same is true for a virtual x resolution that is not
+ supported by the hardware. Cyblafb tries to adapt vyres first because
+ vxres decides if ywrap scrolling is possible or not.
- Attempts to disable acceleration are ignored.
+ Attempts to disable acceleration are ignored, I believe that this is
+ safe.
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
@@ -129,10 +145,6 @@ mode 640x480 or 800x600 or 1024x768 or 1280x1024
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
=================
@@ -195,7 +207,7 @@ 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
+ modprobe cyblafb
con2fb /dev/fb1 /dev/tty1
Unloading cyblafb works without problems after you assign vesafb to all
@@ -203,4 +215,3 @@ ttys again, e.g.:
con2fb /dev/fb0 /dev/tty1
rmmod cyblafb
-
diff --git a/Documentation/fb/cyblafb/whatsnew b/Documentation/fb/cyblafb/whatsnew
new file mode 100644
index 000000000000..76c07a26e044
--- /dev/null
+++ b/Documentation/fb/cyblafb/whatsnew
@@ -0,0 +1,29 @@
+0.62
+====
+
+ - the vesafb parameter has been removed as I decided to allow the
+ feature without any special parameter.
+
+ - Cyblafb does not use the vga style of panning any longer, now the
+ "right view" register in the graphics engine IO space is used. Without
+ that change it was impossible to use all available memory, and without
+ access to all available memory it is impossible to ywrap.
+
+ - The imageblit function now uses hardware acceleration for all font
+ widths. Hardware blitting across pixel column 2048 is broken in the
+ cyberblade/i1 graphics core, but we work around that hardware bug.
+
+ - modes with vxres != xres are supported now.
+
+ - ywrap scrolling is supported now and the default. This is a big
+ performance gain.
+
+ - default video modes use vyres > yres and vxres > xres to allow
+ almost optimal scrolling speed for normal and rotated screens
+
+ - some features mainly usefull for debugging the upper layers of the
+ framebuffer system have been added, have a look at the code
+
+ - fixed: Oops after unloading cyblafb when reading /proc/io*
+
+ - we work around some bugs of the higher framebuffer layers.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9b743198f77a..b4a1ea762698 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -47,17 +47,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
---------------------------
-What: IEEE1394 Audio and Music Data Transmission Protocol driver,
- Connection Management Procedures driver
-When: November 2005
-Files: drivers/ieee1394/{amdtp,cmp}*
-Why: These are incomplete, have never worked, and are better implemented
- in userland via raw1394 (see http://freebob.sourceforge.net/ for
- example.)
-Who: Jody McIntyre <scjody@steamballoon.com>
-
----------------------------
-
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
When: November 2005
Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
@@ -82,15 +71,6 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
---------------------------
-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
-Why: Match the other drivers' name for the same function, duplicate names
- will be available until removal of old names.
-Who: Grant Coady <gcoady@gmail.com>
-
----------------------------
-
What: remove EXPORT_SYMBOL(panic_timeout)
When: April 2006
Files: kernel/panic.c
@@ -143,6 +123,15 @@ Who: Christoph Hellwig <hch@lst.de>
---------------------------
+What: CONFIG_FORCED_INLINING
+When: June 2006
+Why: Config option is there to see if gcc is good enough. (in january
+ 2006). If it is, the behavior should just be the default. If it's not,
+ the option should just go away entirely.
+Who: Arjan van de Ven
+
+---------------------------
+
What: START_ARRAY ioctl for md
When: July 2006
Files: drivers/md/md.c
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index bcfbab899b37..74052d22d868 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -12,14 +12,16 @@ cifs.txt
- description of the CIFS filesystem
coda.txt
- description of the CODA filesystem.
+configfs/
+ - directory containing configfs documentation and example code.
cramfs.txt
- info on the cram filesystem for small storage (ROMs etc)
devfs/
- directory containing devfs documentation.
+dlmfs.txt
+ - info on the userspace interface to the OCFS2 DLM.
ext2.txt
- info, mount options and specifications for the Ext2 filesystem.
-fat_cvf.txt
- - info on the Compressed Volume Files extension to the FAT filesystem
hpfs.txt
- info and mount options for the OS/2 HPFS.
isofs.txt
@@ -32,6 +34,8 @@ ntfs.txt
- info and mount options for the NTFS filesystem (Windows NT).
proc.txt
- info on Linux's /proc filesystem.
+ocfs2.txt
+ - info and mount options for the OCFS2 clustered filesystem.
romfs.txt
- Description of the ROMFS filesystem.
smbfs.txt
diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
new file mode 100644
index 000000000000..c4ff96b7c4e0
--- /dev/null
+++ b/Documentation/filesystems/configfs/configfs.txt
@@ -0,0 +1,434 @@
+
+configfs - Userspace-driven kernel object configuation.
+
+Joel Becker <joel.becker@oracle.com>
+
+Updated: 31 March 2005
+
+Copyright (c) 2005 Oracle Corporation,
+ Joel Becker <joel.becker@oracle.com>
+
+
+[What is configfs?]
+
+configfs is a ram-based filesystem that provides the converse of
+sysfs's functionality. Where sysfs is a filesystem-based view of
+kernel objects, configfs is a filesystem-based manager of kernel
+objects, or config_items.
+
+With sysfs, an object is created in kernel (for example, when a device
+is discovered) and it is registered with sysfs. Its attributes then
+appear in sysfs, allowing userspace to read the attributes via
+readdir(3)/read(2). It may allow some attributes to be modified via
+write(2). The important point is that the object is created and
+destroyed in kernel, the kernel controls the lifecycle of the sysfs
+representation, and sysfs is merely a window on all this.
+
+A configfs config_item is created via an explicit userspace operation:
+mkdir(2). It is destroyed via rmdir(2). The attributes appear at
+mkdir(2) time, and can be read or modified via read(2) and write(2).
+As with sysfs, readdir(3) queries the list of items and/or attributes.
+symlink(2) can be used to group items together. Unlike sysfs, the
+lifetime of the representation is completely driven by userspace. The
+kernel modules backing the items must respond to this.
+
+Both sysfs and configfs can and should exist together on the same
+system. One is not a replacement for the other.
+
+[Using configfs]
+
+configfs can be compiled as a module or into the kernel. You can access
+it by doing
+
+ mount -t configfs none /config
+
+The configfs tree will be empty unless client modules are also loaded.
+These are modules that register their item types with configfs as
+subsystems. Once a client subsystem is loaded, it will appear as a
+subdirectory (or more than one) under /config. Like sysfs, the
+configfs tree is always there, whether mounted on /config or not.
+
+An item is created via mkdir(2). The item's attributes will also
+appear at this time. readdir(3) can determine what the attributes are,
+read(2) can query their default values, and write(2) can store new
+values. Like sysfs, attributes should be ASCII text files, preferably
+with only one value per file. The same efficiency caveats from sysfs
+apply. Don't mix more than one attribute in one attribute file.
+
+Like sysfs, configfs expects write(2) to store the entire buffer at
+once. When writing to configfs attributes, userspace processes should
+first read the entire file, modify the portions they wish to change, and
+then write the entire buffer back. Attribute files have a maximum size
+of one page (PAGE_SIZE, 4096 on i386).
+
+When an item needs to be destroyed, remove it with rmdir(2). An
+item cannot be destroyed if any other item has a link to it (via
+symlink(2)). Links can be removed via unlink(2).
+
+[Configuring FakeNBD: an Example]
+
+Imagine there's a Network Block Device (NBD) driver that allows you to
+access remote block devices. Call it FakeNBD. FakeNBD uses configfs
+for its configuration. Obviously, there will be a nice program that
+sysadmins use to configure FakeNBD, but somehow that program has to tell
+the driver about it. Here's where configfs comes in.
+
+When the FakeNBD driver is loaded, it registers itself with configfs.
+readdir(3) sees this just fine:
+
+ # ls /config
+ fakenbd
+
+A fakenbd connection can be created with mkdir(2). The name is
+arbitrary, but likely the tool will make some use of the name. Perhaps
+it is a uuid or a disk name:
+
+ # mkdir /config/fakenbd/disk1
+ # ls /config/fakenbd/disk1
+ target device rw
+
+The target attribute contains the IP address of the server FakeNBD will
+connect to. The device attribute is the device on the server.
+Predictably, the rw attribute determines whether the connection is
+read-only or read-write.
+
+ # echo 10.0.0.1 > /config/fakenbd/disk1/target
+ # echo /dev/sda1 > /config/fakenbd/disk1/device
+ # echo 1 > /config/fakenbd/disk1/rw
+
+That's it. That's all there is. Now the device is configured, via the
+shell no less.
+
+[Coding With configfs]
+
+Every object in configfs is a config_item. A config_item reflects an
+object in the subsystem. It has attributes that match values on that
+object. configfs handles the filesystem representation of that object
+and its attributes, allowing the subsystem to ignore all but the
+basic show/store interaction.
+
+Items are created and destroyed inside a config_group. A group is a
+collection of items that share the same attributes and operations.
+Items are created by mkdir(2) and removed by rmdir(2), but configfs
+handles that. The group has a set of operations to perform these tasks
+
+A subsystem is the top level of a client module. During initialization,
+the client module registers the subsystem with configfs, the subsystem
+appears as a directory at the top of the configfs filesystem. A
+subsystem is also a config_group, and can do everything a config_group
+can.
+
+[struct config_item]
+
+ struct config_item {
+ char *ci_name;
+ char ci_namebuf[UOBJ_NAME_LEN];
+ struct kref ci_kref;
+ struct list_head ci_entry;
+ struct config_item *ci_parent;
+ struct config_group *ci_group;
+ struct config_item_type *ci_type;
+ struct dentry *ci_dentry;
+ };
+
+ void config_item_init(struct config_item *);
+ void config_item_init_type_name(struct config_item *,
+ const char *name,
+ struct config_item_type *type);
+ struct config_item *config_item_get(struct config_item *);
+ void config_item_put(struct config_item *);
+
+Generally, struct config_item is embedded in a container structure, a
+structure that actually represents what the subsystem is doing. The
+config_item portion of that structure is how the object interacts with
+configfs.
+
+Whether statically defined in a source file or created by a parent
+config_group, a config_item must have one of the _init() functions
+called on it. This initializes the reference count and sets up the
+appropriate fields.
+
+All users of a config_item should have a reference on it via
+config_item_get(), and drop the reference when they are done via
+config_item_put().
+
+By itself, a config_item cannot do much more than appear in configfs.
+Usually a subsystem wants the item to display and/or store attributes,
+among other things. For that, it needs a type.
+
+[struct config_item_type]
+
+ struct configfs_item_operations {
+ void (*release)(struct config_item *);
+ ssize_t (*show_attribute)(struct config_item *,
+ struct configfs_attribute *,
+ char *);
+ ssize_t (*store_attribute)(struct config_item *,
+ struct configfs_attribute *,
+ const char *, size_t);
+ int (*allow_link)(struct config_item *src,
+ struct config_item *target);
+ int (*drop_link)(struct config_item *src,
+ struct config_item *target);
+ };
+
+ struct config_item_type {
+ struct module *ct_owner;
+ struct configfs_item_operations *ct_item_ops;
+ struct configfs_group_operations *ct_group_ops;
+ struct configfs_attribute **ct_attrs;
+ };
+
+The most basic function of a config_item_type is to define what
+operations can be performed on a config_item. All items that have been
+allocated dynamically will need to provide the ct_item_ops->release()
+method. This method is called when the config_item's reference count
+reaches zero. Items that wish to display an attribute need to provide
+the ct_item_ops->show_attribute() method. Similarly, storing a new
+attribute value uses the store_attribute() method.
+
+[struct configfs_attribute]
+
+ struct configfs_attribute {
+ char *ca_name;
+ struct module *ca_owner;
+ mode_t ca_mode;
+ };
+
+When a config_item wants an attribute to appear as a file in the item's
+configfs directory, it must define a configfs_attribute describing it.
+It then adds the attribute to the NULL-terminated array
+config_item_type->ct_attrs. When the item appears in configfs, the
+attribute file will appear with the configfs_attribute->ca_name
+filename. configfs_attribute->ca_mode specifies the file permissions.
+
+If an attribute is readable and the config_item provides a
+ct_item_ops->show_attribute() method, that method will be called
+whenever userspace asks for a read(2) on the attribute. The converse
+will happen for write(2).
+
+[struct config_group]
+
+A config_item cannot live in a vaccum. The only way one can be created
+is via mkdir(2) on a config_group. This will trigger creation of a
+child item.
+
+ struct config_group {
+ struct config_item cg_item;
+ struct list_head cg_children;
+ struct configfs_subsystem *cg_subsys;
+ struct config_group **default_groups;
+ };
+
+ void config_group_init(struct config_group *group);
+ void config_group_init_type_name(struct config_group *group,
+ const char *name,
+ struct config_item_type *type);
+
+
+The config_group structure contains a config_item. Properly configuring
+that item means that a group can behave as an item in its own right.
+However, it can do more: it can create child items or groups. This is
+accomplished via the group operations specified on the group's
+config_item_type.
+
+ struct configfs_group_operations {
+ struct config_item *(*make_item)(struct config_group *group,
+ const char *name);
+ struct config_group *(*make_group)(struct config_group *group,
+ const char *name);
+ int (*commit_item)(struct config_item *item);
+ void (*drop_item)(struct config_group *group,
+ struct config_item *item);
+ };
+
+A group creates child items by providing the
+ct_group_ops->make_item() method. If provided, this method is called from mkdir(2) in the group's directory. The subsystem allocates a new
+config_item (or more likely, its container structure), initializes it,
+and returns it to configfs. Configfs will then populate the filesystem
+tree to reflect the new item.
+
+If the subsystem wants the child to be a group itself, the subsystem
+provides ct_group_ops->make_group(). Everything else behaves the same,
+using the group _init() functions on the group.
+
+Finally, when userspace calls rmdir(2) on the item or group,
+ct_group_ops->drop_item() is called. As a config_group is also a
+config_item, it is not necessary for a seperate drop_group() method.
+The subsystem must config_item_put() the reference that was initialized
+upon item allocation. If a subsystem has no work to do, it may omit
+the ct_group_ops->drop_item() method, and configfs will call
+config_item_put() on the item on behalf of the subsystem.
+
+IMPORTANT: drop_item() is void, and as such cannot fail. When rmdir(2)
+is called, configfs WILL remove the item from the filesystem tree
+(assuming that it has no children to keep it busy). The subsystem is
+responsible for responding to this. If the subsystem has references to
+the item in other threads, the memory is safe. It may take some time
+for the item to actually disappear from the subsystem's usage. But it
+is gone from configfs.
+
+A config_group cannot be removed while it still has child items. This
+is implemented in the configfs rmdir(2) code. ->drop_item() will not be
+called, as the item has not been dropped. rmdir(2) will fail, as the
+directory is not empty.
+
+[struct configfs_subsystem]
+
+A subsystem must register itself, ususally at module_init time. This
+tells configfs to make the subsystem appear in the file tree.
+
+ struct configfs_subsystem {
+ struct config_group su_group;
+ struct semaphore su_sem;
+ };
+
+ int configfs_register_subsystem(struct configfs_subsystem *subsys);
+ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+
+ A subsystem consists of a toplevel config_group and a semaphore.
+The group is where child config_items are created. For a subsystem,
+this group is usually defined statically. Before calling
+configfs_register_subsystem(), the subsystem must have initialized the
+group via the usual group _init() functions, and it must also have
+initialized the semaphore.
+ When the register call returns, the subsystem is live, and it
+will be visible via configfs. At that point, mkdir(2) can be called and
+the subsystem must be ready for it.
+
+[An Example]
+
+The best example of these basic concepts is the simple_children
+subsystem/group and the simple_child item in configfs_example.c It
+shows a trivial object displaying and storing an attribute, and a simple
+group creating and destroying these children.
+
+[Hierarchy Navigation and the Subsystem Semaphore]
+
+There is an extra bonus that configfs provides. The config_groups and
+config_items are arranged in a hierarchy due to the fact that they
+appear in a filesystem. A subsystem is NEVER to touch the filesystem
+parts, but the subsystem might be interested in this hierarchy. For
+this reason, the hierarchy is mirrored via the config_group->cg_children
+and config_item->ci_parent structure members.
+
+A subsystem can navigate the cg_children list and the ci_parent pointer
+to see the tree created by the subsystem. This can race with configfs'
+management of the hierarchy, so configfs uses the subsystem semaphore to
+protect modifications. Whenever a subsystem wants to navigate the
+hierarchy, it must do so under the protection of the subsystem
+semaphore.
+
+A subsystem will be prevented from acquiring the semaphore while a newly
+allocated item has not been linked into this hierarchy. Similarly, it
+will not be able to acquire the semaphore while a dropping item has not
+yet been unlinked. This means that an item's ci_parent pointer will
+never be NULL while the item is in configfs, and that an item will only
+be in its parent's cg_children list for the same duration. This allows
+a subsystem to trust ci_parent and cg_children while they hold the
+semaphore.
+
+[Item Aggregation Via symlink(2)]
+
+configfs provides a simple group via the group->item parent/child
+relationship. Often, however, a larger environment requires aggregation
+outside of the parent/child connection. This is implemented via
+symlink(2).
+
+A config_item may provide the ct_item_ops->allow_link() and
+ct_item_ops->drop_link() methods. If the ->allow_link() method exists,
+symlink(2) may be called with the config_item as the source of the link.
+These links are only allowed between configfs config_items. Any
+symlink(2) attempt outside the configfs filesystem will be denied.
+
+When symlink(2) is called, the source config_item's ->allow_link()
+method is called with itself and a target item. If the source item
+allows linking to target item, it returns 0. A source item may wish to
+reject a link if it only wants links to a certain type of object (say,
+in its own subsystem).
+
+When unlink(2) is called on the symbolic link, the source item is
+notified via the ->drop_link() method. Like the ->drop_item() method,
+this is a void function and cannot return failure. The subsystem is
+responsible for responding to the change.
+
+A config_item cannot be removed while it links to any other item, nor
+can it be removed while an item links to it. Dangling symlinks are not
+allowed in configfs.
+
+[Automatically Created Subgroups]
+
+A new config_group may want to have two types of child config_items.
+While this could be codified by magic names in ->make_item(), it is much
+more explicit to have a method whereby userspace sees this divergence.
+
+Rather than have a group where some items behave differently than
+others, configfs provides a method whereby one or many subgroups are
+automatically created inside the parent at its creation. Thus,
+mkdir("parent) results in "parent", "parent/subgroup1", up through
+"parent/subgroupN". Items of type 1 can now be created in
+"parent/subgroup1", and items of type N can be created in
+"parent/subgroupN".
+
+These automatic subgroups, or default groups, do not preclude other
+children of the parent group. If ct_group_ops->make_group() exists,
+other child groups can be created on the parent group directly.
+
+A configfs subsystem specifies default groups by filling in the
+NULL-terminated array default_groups on the config_group structure.
+Each group in that array is populated in the configfs tree at the same
+time as the parent group. Similarly, they are removed at the same time
+as the parent. No extra notification is provided. When a ->drop_item()
+method call notifies the subsystem the parent group is going away, it
+also means every default group child associated with that parent group.
+
+As a consequence of this, default_groups cannot be removed directly via
+rmdir(2). They also are not considered when rmdir(2) on the parent
+group is checking for children.
+
+[Committable Items]
+
+NOTE: Committable items are currently unimplemented.
+
+Some config_items cannot have a valid initial state. That is, no
+default values can be specified for the item's attributes such that the
+item can do its work. Userspace must configure one or more attributes,
+after which the subsystem can start whatever entity this item
+represents.
+
+Consider the FakeNBD device from above. Without a target address *and*
+a target device, the subsystem has no idea what block device to import.
+The simple example assumes that the subsystem merely waits until all the
+appropriate attributes are configured, and then connects. This will,
+indeed, work, but now every attribute store must check if the attributes
+are initialized. Every attribute store must fire off the connection if
+that condition is met.
+
+Far better would be an explicit action notifying the subsystem that the
+config_item is ready to go. More importantly, an explicit action allows
+the subsystem to provide feedback as to whether the attibutes are
+initialized in a way that makes sense. configfs provides this as
+committable items.
+
+configfs still uses only normal filesystem operations. An item is
+committed via rename(2). The item is moved from a directory where it
+can be modified to a directory where it cannot.
+
+Any group that provides the ct_group_ops->commit_item() method has
+committable items. When this group appears in configfs, mkdir(2) will
+not work directly in the group. Instead, the group will have two
+subdirectories: "live" and "pending". The "live" directory does not
+support mkdir(2) or rmdir(2) either. It only allows rename(2). The
+"pending" directory does allow mkdir(2) and rmdir(2). An item is
+created in the "pending" directory. Its attributes can be modified at
+will. Userspace commits the item by renaming it into the "live"
+directory. At this point, the subsystem recieves the ->commit_item()
+callback. If all required attributes are filled to satisfaction, the
+method returns zero and the item is moved to the "live" directory.
+
+As rmdir(2) does not work in the "live" directory, an item must be
+shutdown, or "uncommitted". Again, this is done via rename(2), this
+time from the "live" directory back to the "pending" one. The subsystem
+is notified by the ct_group_ops->uncommit_object() method.
+
+
diff --git a/Documentation/filesystems/configfs/configfs_example.c b/Documentation/filesystems/configfs/configfs_example.c
new file mode 100644
index 000000000000..f3c6e4946f98
--- /dev/null
+++ b/Documentation/filesystems/configfs/configfs_example.c
@@ -0,0 +1,474 @@
+/*
+ * vim: noexpandtab ts=8 sts=0 sw=8:
+ *
+ * configfs_example.c - This file is a demonstration module containing
+ * a number of configfs subsystems.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+
+
+
+/*
+ * 01-childless
+ *
+ * This first example is a childless subsystem. It cannot create
+ * any config_items. It just has attributes.
+ *
+ * Note that we are enclosing the configfs_subsystem inside a container.
+ * This is not necessary if a subsystem has no attributes directly
+ * on the subsystem. See the next example, 02-simple-children, for
+ * such a subsystem.
+ */
+
+struct childless {
+ struct configfs_subsystem subsys;
+ int showme;
+ int storeme;
+};
+
+struct childless_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct childless *, char *);
+ ssize_t (*store)(struct childless *, const char *, size_t);
+};
+
+static inline struct childless *to_childless(struct config_item *item)
+{
+ return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
+}
+
+static ssize_t childless_showme_read(struct childless *childless,
+ char *page)
+{
+ ssize_t pos;
+
+ pos = sprintf(page, "%d\n", childless->showme);
+ childless->showme++;
+
+ return pos;
+}
+
+static ssize_t childless_storeme_read(struct childless *childless,
+ char *page)
+{
+ return sprintf(page, "%d\n", childless->storeme);
+}
+
+static ssize_t childless_storeme_write(struct childless *childless,
+ const char *page,
+ size_t count)
+{
+ unsigned long tmp;
+ char *p = (char *) page;
+
+ tmp = simple_strtoul(p, &p, 10);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp > INT_MAX)
+ return -ERANGE;
+
+ childless->storeme = tmp;
+
+ return count;
+}
+
+static ssize_t childless_description_read(struct childless *childless,
+ char *page)
+{
+ return sprintf(page,
+"[01-childless]\n"
+"\n"
+"The childless subsystem is the simplest possible subsystem in\n"
+"configfs. It does not support the creation of child config_items.\n"
+"It only has a few attributes. In fact, it isn't much different\n"
+"than a directory in /proc.\n");
+}
+
+static struct childless_attribute childless_attr_showme = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
+ .show = childless_showme_read,
+};
+static struct childless_attribute childless_attr_storeme = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
+ .show = childless_storeme_read,
+ .store = childless_storeme_write,
+};
+static struct childless_attribute childless_attr_description = {
+ .attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
+ .show = childless_description_read,
+};
+
+static struct configfs_attribute *childless_attrs[] = {
+ &childless_attr_showme.attr,
+ &childless_attr_storeme.attr,
+ &childless_attr_description.attr,
+ NULL,
+};
+
+static ssize_t childless_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct childless *childless = to_childless(item);
+ struct childless_attribute *childless_attr =
+ container_of(attr, struct childless_attribute, attr);
+ ssize_t ret = 0;
+
+ if (childless_attr->show)
+ ret = childless_attr->show(childless, page);
+ return ret;
+}
+
+static ssize_t childless_attr_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct childless *childless = to_childless(item);
+ struct childless_attribute *childless_attr =
+ container_of(attr, struct childless_attribute, attr);
+ ssize_t ret = -EINVAL;
+
+ if (childless_attr->store)
+ ret = childless_attr->store(childless, page, count);
+ return ret;
+}
+
+static struct configfs_item_operations childless_item_ops = {
+ .show_attribute = childless_attr_show,
+ .store_attribute = childless_attr_store,
+};
+
+static struct config_item_type childless_type = {
+ .ct_item_ops = &childless_item_ops,
+ .ct_attrs = childless_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct childless childless_subsys = {
+ .subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "01-childless",
+ .ci_type = &childless_type,
+ },
+ },
+ },
+};
+
+
+/* ----------------------------------------------------------------- */
+
+/*
+ * 02-simple-children
+ *
+ * This example merely has a simple one-attribute child. Note that
+ * there is no extra attribute structure, as the child's attribute is
+ * known from the get-go. Also, there is no container for the
+ * subsystem, as it has no attributes of its own.
+ */
+
+struct simple_child {
+ struct config_item item;
+ int storeme;
+};
+
+static inline struct simple_child *to_simple_child(struct config_item *item)
+{
+ return item ? container_of(item, struct simple_child, item) : NULL;
+}
+
+static struct configfs_attribute simple_child_attr_storeme = {
+ .ca_owner = THIS_MODULE,
+ .ca_name = "storeme",
+ .ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute *simple_child_attrs[] = {
+ &simple_child_attr_storeme,
+ NULL,
+};
+
+static ssize_t simple_child_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ ssize_t count;
+ struct simple_child *simple_child = to_simple_child(item);
+
+ count = sprintf(page, "%d\n", simple_child->storeme);
+
+ return count;
+}
+
+static ssize_t simple_child_attr_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct simple_child *simple_child = to_simple_child(item);
+ unsigned long tmp;
+ char *p = (char *) page;
+
+ tmp = simple_strtoul(p, &p, 10);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp > INT_MAX)
+ return -ERANGE;
+
+ simple_child->storeme = tmp;
+
+ return count;
+}
+
+static void simple_child_release(struct config_item *item)
+{
+ kfree(to_simple_child(item));
+}
+
+static struct configfs_item_operations simple_child_item_ops = {
+ .release = simple_child_release,
+ .show_attribute = simple_child_attr_show,
+ .store_attribute = simple_child_attr_store,
+};
+
+static struct config_item_type simple_child_type = {
+ .ct_item_ops = &simple_child_item_ops,
+ .ct_attrs = simple_child_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+
+static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
+{
+ struct simple_child *simple_child;
+
+ simple_child = kmalloc(sizeof(struct simple_child), GFP_KERNEL);
+ if (!simple_child)
+ return NULL;
+
+ memset(simple_child, 0, sizeof(struct simple_child));
+
+ config_item_init_type_name(&simple_child->item, name,
+ &simple_child_type);
+
+ simple_child->storeme = 0;
+
+ return &simple_child->item;
+}
+
+static struct configfs_attribute simple_children_attr_description = {
+ .ca_owner = THIS_MODULE,
+ .ca_name = "description",
+ .ca_mode = S_IRUGO,
+};
+
+static struct configfs_attribute *simple_children_attrs[] = {
+ &simple_children_attr_description,
+ NULL,
+};
+
+static ssize_t simple_children_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ return sprintf(page,
+"[02-simple-children]\n"
+"\n"
+"This subsystem allows the creation of child config_items. These\n"
+"items have only one attribute that is readable and writeable.\n");
+}
+
+static struct configfs_item_operations simple_children_item_ops = {
+ .show_attribute = simple_children_attr_show,
+};
+
+/*
+ * Note that, since no extra work is required on ->drop_item(),
+ * no ->drop_item() is provided.
+ */
+static struct configfs_group_operations simple_children_group_ops = {
+ .make_item = simple_children_make_item,
+};
+
+static struct config_item_type simple_children_type = {
+ .ct_item_ops = &simple_children_item_ops,
+ .ct_group_ops = &simple_children_group_ops,
+ .ct_attrs = simple_children_attrs,
+};
+
+static struct configfs_subsystem simple_children_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "02-simple-children",
+ .ci_type = &simple_children_type,
+ },
+ },
+};
+
+
+/* ----------------------------------------------------------------- */
+
+/*
+ * 03-group-children
+ *
+ * This example reuses the simple_children group from above. However,
+ * the simple_children group is not the subsystem itself, it is a
+ * child of the subsystem. Creation of a group in the subsystem creates
+ * a new simple_children group. That group can then have simple_child
+ * children of its own.
+ */
+
+struct simple_children {
+ struct config_group group;
+};
+
+static struct config_group *group_children_make_group(struct config_group *group, const char *name)
+{
+ struct simple_children *simple_children;
+
+ simple_children = kmalloc(sizeof(struct simple_children),
+ GFP_KERNEL);
+ if (!simple_children)
+ return NULL;
+
+ memset(simple_children, 0, sizeof(struct simple_children));
+
+ config_group_init_type_name(&simple_children->group, name,
+ &simple_children_type);
+
+ return &simple_children->group;
+}
+
+static struct configfs_attribute group_children_attr_description = {
+ .ca_owner = THIS_MODULE,
+ .ca_name = "description",
+ .ca_mode = S_IRUGO,
+};
+
+static struct configfs_attribute *group_children_attrs[] = {
+ &group_children_attr_description,
+ NULL,
+};
+
+static ssize_t group_children_attr_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ return sprintf(page,
+"[03-group-children]\n"
+"\n"
+"This subsystem allows the creation of child config_groups. These\n"
+"groups are like the subsystem simple-children.\n");
+}
+
+static struct configfs_item_operations group_children_item_ops = {
+ .show_attribute = group_children_attr_show,
+};
+
+/*
+ * Note that, since no extra work is required on ->drop_item(),
+ * no ->drop_item() is provided.
+ */
+static struct configfs_group_operations group_children_group_ops = {
+ .make_group = group_children_make_group,
+};
+
+static struct config_item_type group_children_type = {
+ .ct_item_ops = &group_children_item_ops,
+ .ct_group_ops = &group_children_group_ops,
+ .ct_attrs = group_children_attrs,
+};
+
+static struct configfs_subsystem group_children_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "03-group-children",
+ .ci_type = &group_children_type,
+ },
+ },
+};
+
+/* ----------------------------------------------------------------- */
+
+/*
+ * We're now done with our subsystem definitions.
+ * For convenience in this module, here's a list of them all. It
+ * allows the init function to easily register them. Most modules
+ * will only have one subsystem, and will only call register_subsystem
+ * on it directly.
+ */
+static struct configfs_subsystem *example_subsys[] = {
+ &childless_subsys.subsys,
+ &simple_children_subsys,
+ &group_children_subsys,
+ NULL,
+};
+
+static int __init configfs_example_init(void)
+{
+ int ret;
+ int i;
+ struct configfs_subsystem *subsys;
+
+ for (i = 0; example_subsys[i]; i++) {
+ subsys = example_subsys[i];
+
+ config_group_init(&subsys->su_group);
+ init_MUTEX(&subsys->su_sem);
+ ret = configfs_register_subsystem(subsys);
+ if (ret) {
+ printk(KERN_ERR "Error %d while registering subsystem %s\n",
+ ret,
+ subsys->su_group.cg_item.ci_namebuf);
+ goto out_unregister;
+ }
+ }
+
+ return 0;
+
+out_unregister:
+ for (; i >= 0; i--) {
+ configfs_unregister_subsystem(example_subsys[i]);
+ }
+
+ return ret;
+}
+
+static void __exit configfs_example_exit(void)
+{
+ int i;
+
+ for (i = 0; example_subsys[i]; i++) {
+ configfs_unregister_subsystem(example_subsys[i]);
+ }
+}
+
+module_init(configfs_example_init);
+module_exit(configfs_example_exit);
+MODULE_LICENSE("GPL");
diff --git a/Documentation/filesystems/dlmfs.txt b/Documentation/filesystems/dlmfs.txt
new file mode 100644
index 000000000000..9afab845a906
--- /dev/null
+++ b/Documentation/filesystems/dlmfs.txt
@@ -0,0 +1,130 @@
+dlmfs
+==================
+A minimal DLM userspace interface implemented via a virtual file
+system.
+
+dlmfs is built with OCFS2 as it requires most of its infrastructure.
+
+Project web page: http://oss.oracle.com/projects/ocfs2
+Tools web page: http://oss.oracle.com/projects/ocfs2-tools
+OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
+
+All code copyright 2005 Oracle except when otherwise noted.
+
+CREDITS
+=======
+
+Some code taken from ramfs which is Copyright (C) 2000 Linus Torvalds
+and Transmeta Corp.
+
+Mark Fasheh <mark.fasheh@oracle.com>
+
+Caveats
+=======
+- Right now it only works with the OCFS2 DLM, though support for other
+ DLM implementations should not be a major issue.
+
+Mount options
+=============
+None
+
+Usage
+=====
+
+If you're just interested in OCFS2, then please see ocfs2.txt. The
+rest of this document will be geared towards those who want to use
+dlmfs for easy to setup and easy to use clustered locking in
+userspace.
+
+Setup
+=====
+
+dlmfs requires that the OCFS2 cluster infrastructure be in
+place. Please download ocfs2-tools from the above url and configure a
+cluster.
+
+You'll want to start heartbeating on a volume which all the nodes in
+your lockspace can access. The easiest way to do this is via
+ocfs2_hb_ctl (distributed with ocfs2-tools). Right now it requires
+that an OCFS2 file system be in place so that it can automatically
+find it's heartbeat area, though it will eventually support heartbeat
+against raw disks.
+
+Please see the ocfs2_hb_ctl and mkfs.ocfs2 manual pages distributed
+with ocfs2-tools.
+
+Once you're heartbeating, DLM lock 'domains' can be easily created /
+destroyed and locks within them accessed.
+
+Locking
+=======
+
+Users may access dlmfs via standard file system calls, or they can use
+'libo2dlm' (distributed with ocfs2-tools) which abstracts the file
+system calls and presents a more traditional locking api.
+
+dlmfs handles lock caching automatically for the user, so a lock
+request for an already acquired lock will not generate another DLM
+call. Userspace programs are assumed to handle their own local
+locking.
+
+Two levels of locks are supported - Shared Read, and Exlcusive.
+Also supported is a Trylock operation.
+
+For information on the libo2dlm interface, please see o2dlm.h,
+distributed with ocfs2-tools.
+
+Lock value blocks can be read and written to a resource via read(2)
+and write(2) against the fd obtained via your open(2) call. The
+maximum currently supported LVB length is 64 bytes (though that is an
+OCFS2 DLM limitation). Through this mechanism, users of dlmfs can share
+small amounts of data amongst their nodes.
+
+mkdir(2) signals dlmfs to join a domain (which will have the same name
+as the resulting directory)
+
+rmdir(2) signals dlmfs to leave the domain
+
+Locks for a given domain are represented by regular inodes inside the
+domain directory. Locking against them is done via the open(2) system
+call.
+
+The open(2) call will not return until your lock has been granted or
+an error has occurred, unless it has been instructed to do a trylock
+operation. If the lock succeeds, you'll get an fd.
+
+open(2) with O_CREAT to ensure the resource inode is created - dlmfs does
+not automatically create inodes for existing lock resources.
+
+Open Flag Lock Request Type
+--------- -----------------
+O_RDONLY Shared Read
+O_RDWR Exclusive
+
+Open Flag Resulting Locking Behavior
+--------- --------------------------
+O_NONBLOCK Trylock operation
+
+You must provide exactly one of O_RDONLY or O_RDWR.
+
+If O_NONBLOCK is also provided and the trylock operation was valid but
+could not lock the resource then open(2) will return ETXTBUSY.
+
+close(2) drops the lock associated with your fd.
+
+Modes passed to mkdir(2) or open(2) are adhered to locally. Chown is
+supported locally as well. This means you can use them to restrict
+access to the resources via dlmfs on your local node only.
+
+The resource LVB may be read from the fd in either Shared Read or
+Exclusive modes via the read(2) system call. It can be written via
+write(2) only when open in Exclusive mode.
+
+Once written, an LVB will be visible to other nodes who obtain Read
+Only or higher level locks on the resource.
+
+See Also
+========
+http://opendlm.sourceforge.net/cvsmirror/opendlm/docs/dlmbook_final.pdf
+
+For more information on the VMS distributed locking API.
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index 9840d5b8d5b9..afb1335c05d6 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -2,11 +2,11 @@
Ext3 Filesystem
===============
-ext3 was originally released in September 1999. Written by Stephen Tweedie
-for 2.2 branch, and ported to 2.4 kernels by Peter Braam, Andreas Dilger,
+Ext3 was originally released in September 1999. Written by Stephen Tweedie
+for the 2.2 branch, and ported to 2.4 kernels by Peter Braam, Andreas Dilger,
Andrew Morton, Alexander Viro, Ted Ts'o and Stephen Tweedie.
-ext3 is ext2 filesystem enhanced with journalling capabilities.
+Ext3 is the ext2 filesystem enhanced with journalling capabilities.
Options
=======
@@ -14,76 +14,81 @@ Options
When mounting an ext3 filesystem, the following option are accepted:
(*) == default
-jounal=update Update the ext3 file system's journal to the
- current format.
+journal=update Update the ext3 file system's journal to the current
+ format.
-journal=inum When a journal already exists, this option is
- ignored. Otherwise, it specifies the number of
- the inode which will represent the ext3 file
- system's journal file.
+journal=inum When a journal already exists, this option is ignored.
+ Otherwise, it specifies the number of the inode which
+ will represent the ext3 file system's journal file.
+
+journal_dev=devnum When the external journal device's major/minor numbers
+ have changed, this option allows the user to specify
+ the new journal location. The journal device is
+ identified through its new major/minor numbers encoded
+ in devnum.
noload Don't load the journal on mounting.
-data=journal All data are committed into the journal prior
- to being written into the main file system.
+data=journal All data are committed into the journal prior to being
+ written into the main file system.
data=ordered (*) All data are forced directly out to the main file
- system prior to its metadata being committed to
- the journal.
+ system prior to its metadata being committed to the
+ journal.
-data=writeback Data ordering is not preserved, data may be
- written into the main file system after its
- metadata has been committed to the journal.
+data=writeback Data ordering is not preserved, data may be written
+ into the main file system after its metadata has been
+ committed to the journal.
commit=nrsec (*) Ext3 can be told to sync all its data and metadata
every 'nrsec' seconds. The default value is 5 seconds.
- This means that if you lose your power, you will lose,
- as much, the latest 5 seconds of work (your filesystem
- will not be damaged though, thanks to journaling). This
- default value (or any low value) will hurt performance,
- but it's good for data-safety. Setting it to 0 will
- have the same effect than leaving the default 5 sec.
+ This means that if you lose your power, you will lose
+ as much as the latest 5 seconds of work (your
+ filesystem will not be damaged though, thanks to the
+ journaling). This default value (or any low value)
+ will hurt performance, but it's good for data-safety.
+ Setting it to 0 will have the same effect as leaving
+ it at the default (5 seconds).
Setting it to very large values will improve
performance.
-barrier=1 This enables/disables barriers. barrier=0 disables it,
- barrier=1 enables it.
+barrier=1 This enables/disables barriers. barrier=0 disables
+ it, barrier=1 enables it.
-orlov (*) This enables the new Orlov block allocator. It's enabled
- by default.
+orlov (*) This enables the new Orlov block allocator. It is
+ enabled by default.
-oldalloc This disables the Orlov block allocator and enables the
- old block allocator. Orlov should have better performance,
- we'd like to get some feedback if it's the contrary for
- you.
+oldalloc This disables the Orlov block allocator and enables
+ the old block allocator. Orlov should have better
+ performance - we'd like to get some feedback if it's
+ the contrary for you.
-user_xattr Enables Extended User Attributes. Additionally, you need
- to have extended attribute support enabled in the kernel
- configuration (CONFIG_EXT3_FS_XATTR). See the attr(5)
- manual page and http://acl.bestbits.at to learn more
- about extended attributes.
+user_xattr Enables Extended User Attributes. Additionally, you
+ need to have extended attribute support enabled in the
+ kernel configuration (CONFIG_EXT3_FS_XATTR). See the
+ attr(5) manual page and http://acl.bestbits.at/ to
+ learn more about extended attributes.
nouser_xattr Disables Extended User Attributes.
-acl Enables POSIX Access Control Lists support. Additionally,
- you need to have ACL support enabled in the kernel
- configuration (CONFIG_EXT3_FS_POSIX_ACL). See the acl(5)
- manual page and http://acl.bestbits.at for more
- information.
+acl Enables POSIX Access Control Lists support.
+ Additionally, you need to have ACL support enabled in
+ the kernel configuration (CONFIG_EXT3_FS_POSIX_ACL).
+ See the acl(5) manual page and http://acl.bestbits.at/
+ for more information.
-noacl This option disables POSIX Access Control List support.
+noacl This option disables POSIX Access Control List
+ support.
reservation
noreservation
-resize=
-
bsddf (*) Make 'df' act like BSD.
minixdf Make 'df' act like Minix.
check=none Don't do extra checking of bitmaps on mount.
-nocheck
+nocheck
debug Extra debugging information is sent to syslog.
@@ -92,7 +97,7 @@ errors=continue Keep going on a filesystem error.
errors=panic Panic and halt the machine if an error occurs.
grpid Give objects the same group ID as their creator.
-bsdgroups
+bsdgroups
nogrpid (*) New objects have the group ID of their creator.
sysvgroups
@@ -103,81 +108,83 @@ resuid=n The user ID which may use the reserved blocks.
sb=n Use alternate superblock at this location.
-quota Quota options are currently silently ignored.
-noquota (see fs/ext3/super.c, line 594)
+quota
+noquota
grpquota
usrquota
Specification
=============
-ext3 shares all disk implementation with ext2 filesystem, and add
-transactions capabilities to ext2. Journaling is done by the
-Journaling block device layer.
+Ext3 shares all disk implementation with the ext2 filesystem, and adds
+transactions capabilities to ext2. Journaling is done by the Journaling Block
+Device layer.
Journaling Block Device layer
-----------------------------
-The Journaling Block Device layer (JBD) isn't ext3 specific. It was
-design to add journaling capabilities on a block device. The ext3
-filesystem code will inform the JBD of modifications it is performing
-(Call a transaction). the journal support the transactions start and
-stop, and in case of crash, the journal can replayed the transactions
-to put the partition on a consistent state fastly.
+The Journaling Block Device layer (JBD) isn't ext3 specific. It was design to
+add journaling capabilities on a block device. The ext3 filesystem code will
+inform the JBD of modifications it is performing (called a transaction). The
+journal supports the transactions start and stop, and in case of crash, the
+journal can replayed the transactions to put the partition back in a
+consistent state fast.
-handles represent a single atomic update to a filesystem. JBD can
-handle external journal on a block device.
+Handles represent a single atomic update to a filesystem. JBD can handle an
+external journal on a block device.
Data Mode
---------
-There's 3 different data modes:
+There are 3 different data modes:
* writeback mode
-In data=writeback mode, ext3 does not journal data at all. This mode
-provides a similar level of journaling as XFS, JFS, and ReiserFS in its
-default mode - metadata journaling. A crash+recovery can cause
-incorrect data to appear in files which were written shortly before the
-crash. This mode will typically provide the best ext3 performance.
+In data=writeback mode, ext3 does not journal data at all. This mode provides
+a similar level of journaling as that of XFS, JFS, and ReiserFS in its default
+mode - metadata journaling. A crash+recovery can cause incorrect data to
+appear in files which were written shortly before the crash. This mode will
+typically provide the best ext3 performance.
* ordered mode
-In data=ordered mode, ext3 only officially journals metadata, but it
-logically groups metadata and data blocks into a single unit called a
-transaction. When it's time to write the new metadata out to disk, the
-associated data blocks are written first. In general, this mode
-perform slightly slower than writeback but significantly faster than
-journal mode.
+In data=ordered mode, ext3 only officially journals metadata, but it logically
+groups metadata and data blocks into a single unit called a transaction. When
+it's time to write the new metadata out to disk, the associated data blocks
+are written first. In general, this mode performs slightly slower than
+writeback but significantly faster than journal mode.
* journal mode
-data=journal mode provides full data and metadata journaling. All new
-data is written to the journal first, and then to its final location.
-In the event of a crash, the journal can be replayed, bringing both
-data and metadata into a consistent state. This mode is the slowest
-except when data needs to be read from and written to disk at the same
-time where it outperform all others mode.
+data=journal mode provides full data and metadata journaling. All new data is
+written to the journal first, and then to its final location.
+In the event of a crash, the journal can be replayed, bringing both data and
+metadata into a consistent state. This mode is the slowest except when data
+needs to be read from and written to disk at the same time where it
+outperforms all others modes.
Compatibility
-------------
Ext2 partitions can be easily convert to ext3, with `tune2fs -j <dev>`.
-Ext3 is fully compatible with Ext2. Ext3 partitions can easily be
-mounted as Ext2.
+Ext3 is fully compatible with Ext2. Ext3 partitions can easily be mounted as
+Ext2.
+
External Tools
==============
-see manual pages to know more.
+See manual pages to learn more.
+
+tune2fs: create a ext3 journal on a ext2 partition with the -j flag.
+mke2fs: create a ext3 partition with the -j flag.
+debugfs: ext2 and ext3 file system debugger.
+ext2online: online (mounted) ext2 and ext3 filesystem resizer
-tune2fs: create a ext3 journal on a ext2 partition with the -j flags
-mke2fs: create a ext3 partition with the -j flags
-debugfs: ext2 and ext3 file system debugger
References
==========
-kernel source: file:/usr/src/linux/fs/ext3
- file:/usr/src/linux/fs/jbd
+kernel source: <file:fs/ext3/>
+ <file:fs/jbd/>
-programs: http://e2fsprogs.sourceforge.net
+programs: http://e2fsprogs.sourceforge.net/
+ http://ext2resize.sourceforge.net
-useful link:
- http://www.zip.com.au/~akpm/linux/ext3/ext3-usage.html
+useful links: http://www.zip.com.au/~akpm/linux/ext3/ext3-usage.html
http://www-106.ibm.com/developerworks/linux/library/l-fs7/
http://www-106.ibm.com/developerworks/linux/library/l-fs8/
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
index 6b5741e651a2..33f74310d161 100644
--- a/Documentation/filesystems/fuse.txt
+++ b/Documentation/filesystems/fuse.txt
@@ -86,6 +86,62 @@ Mount options
The default is infinite. Note that the size of read requests is
limited anyway to 32 pages (which is 128kbyte on i386).
+Sysfs
+~~~~~
+
+FUSE sets up the following hierarchy in sysfs:
+
+ /sys/fs/fuse/connections/N/
+
+where N is an increasing number allocated to each new connection.
+
+For each connection the following attributes are defined:
+
+ 'waiting'
+
+ The number of requests which are waiting to be transfered to
+ userspace or being processed by the filesystem daemon. If there is
+ no filesystem activity and 'waiting' is non-zero, then the
+ filesystem is hung or deadlocked.
+
+ 'abort'
+
+ Writing anything into this file will abort the filesystem
+ connection. This means that all waiting requests will be aborted an
+ error returned for all aborted and new requests.
+
+Only a privileged user may read or write these attributes.
+
+Aborting a filesystem connection
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is possible to get into certain situations where the filesystem is
+not responding. Reasons for this may be:
+
+ a) Broken userspace filesystem implementation
+
+ b) Network connection down
+
+ c) Accidental deadlock
+
+ d) Malicious deadlock
+
+(For more on c) and d) see later sections)
+
+In either of these cases it may be useful to abort the connection to
+the filesystem. There are several ways to do this:
+
+ - Kill the filesystem daemon. Works in case of a) and b)
+
+ - Kill the filesystem daemon and all users of the filesystem. Works
+ in all cases except some malicious deadlocks
+
+ - Use forced umount (umount -f). Works in all cases but only if
+ filesystem is still attached (it hasn't been lazy unmounted)
+
+ - Abort filesystem through the sysfs interface. Most powerful
+ method, always works.
+
How do non-privileged mounts work?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -313,3 +369,10 @@ 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.
+Scenario 3 - Tricky deadlock with asynchronous read
+---------------------------------------------------
+
+The same situation as above, except thread-1 will wait on page lock
+and hence it will be uninterruptible as well. The solution is to
+abort the connection with forced umount (if mount is attached) or
+through the abort attribute in sysfs.
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
new file mode 100644
index 000000000000..f2595caf052e
--- /dev/null
+++ b/Documentation/filesystems/ocfs2.txt
@@ -0,0 +1,55 @@
+OCFS2 filesystem
+==================
+OCFS2 is a general purpose extent based shared disk cluster file
+system with many similarities to ext3. It supports 64 bit inode
+numbers, and has automatically extending metadata groups which may
+also make it attractive for non-clustered use.
+
+You'll want to install the ocfs2-tools package in order to at least
+get "mount.ocfs2" and "ocfs2_hb_ctl".
+
+Project web page: http://oss.oracle.com/projects/ocfs2
+Tools web page: http://oss.oracle.com/projects/ocfs2-tools
+OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
+
+All code copyright 2005 Oracle except when otherwise noted.
+
+CREDITS:
+Lots of code taken from ext3 and other projects.
+
+Authors in alphabetical order:
+Joel Becker <joel.becker@oracle.com>
+Zach Brown <zach.brown@oracle.com>
+Mark Fasheh <mark.fasheh@oracle.com>
+Kurt Hackel <kurt.hackel@oracle.com>
+Sunil Mushran <sunil.mushran@oracle.com>
+Manish Singh <manish.singh@oracle.com>
+
+Caveats
+=======
+Features which OCFS2 does not support yet:
+ - sparse files
+ - extended attributes
+ - shared writeable mmap
+ - loopback is supported, but data written will not
+ be cluster coherent.
+ - quotas
+ - cluster aware flock
+ - Directory change notification (F_NOTIFY)
+ - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
+ - POSIX ACLs
+ - readpages / writepages (not user visible)
+
+Mount options
+=============
+
+OCFS2 supports the following mount options:
+(*) == default
+
+barrier=1 This enables/disables barriers. barrier=0 disables it,
+ barrier=1 enables it.
+errors=remount-ro(*) Remount the filesystem read-only on an error.
+errors=panic Panic and halt the machine if an error occurs.
+intr (*) Allow signals to interrupt cluster operations.
+nointr Do not allow signals to interrupt cluster
+ operations.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index d4773565ea2f..944cf109a6f5 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -418,7 +418,7 @@ VmallocChunk: 111088 kB
Dirty: Memory which is waiting to get written back to the disk
Writeback: Memory which is actively being written back to the disk
Mapped: files which have been mmaped, such as libraries
- Slab: in-kernel data structures cache
+ Slab: in-kernel data structures cache
CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'),
this is the total amount of memory currently available to
be allocated on the system. This limit is only adhered to
@@ -1302,6 +1302,23 @@ VM has token based thrashing control mechanism and uses the token to prevent
unnecessary page faults in thrashing situation. The unit of the value is
second. The value would be useful to tune thrashing behavior.
+drop_caches
+-----------
+
+Writing to this will cause the kernel to drop clean caches, dentries and
+inodes from memory, causing that memory to become free.
+
+To free pagecache:
+ echo 1 > /proc/sys/vm/drop_caches
+To free dentries and inodes:
+ echo 2 > /proc/sys/vm/drop_caches
+To free pagecache, dentries and inodes:
+ echo 3 > /proc/sys/vm/drop_caches
+
+As this is a non-destructive operation and dirty objects are not freeable, the
+user should run `sync' first.
+
+
2.5 /proc/sys/dev - Device specific parameters
----------------------------------------------
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
index b3404a032596..60ab61e54e8a 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -143,12 +143,26 @@ as the following example:
dir /mnt 755 0 0
file /init initramfs/init.sh 755 0 0
+Run "usr/gen_init_cpio" (after the kernel build) to get a usage message
+documenting the above file format.
+
One advantage of the text file is that root access is not required to
set permissions or create device nodes in the new archive. (Note that those
two example "file" entries expect to find files named "init.sh" and "busybox" in
a directory called "initramfs", under the linux-2.6.* directory. See
Documentation/early-userspace/README for more details.)
+The kernel does not depend on external cpio tools, gen_init_cpio is created
+from usr/gen_init_cpio.c which is entirely self-contained, and the kernel's
+boot-time extractor is also (obviously) self-contained. However, if you _do_
+happen to have cpio installed, the following command line can extract the
+generated cpio image back into its component files:
+
+ cpio -i -d -H newc -F initramfs_data.cpio --no-absolute-filenames
+
+Contents of initramfs:
+----------------------
+
If you don't already understand what shared libraries, devices, and paths
you need to get a minimal root filesystem up and running, here are some
references:
@@ -161,13 +175,69 @@ designed to be a tiny C library to statically link early userspace
code against, along with some related utilities. It is BSD licensed.
I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net)
-myself. These are LGPL and GPL, respectively.
+myself. These are LGPL and GPL, respectively. (A self-contained initramfs
+package is planned for the busybox 1.2 release.)
In theory you could use glibc, but that's not well suited for small embedded
uses like this. (A "hello world" program statically linked against glibc is
over 400k. With uClibc it's 7k. Also note that glibc dlopens libnss to do
name lookups, even when otherwise statically linked.)
+Why cpio rather than tar?
+-------------------------
+
+This decision was made back in December, 2001. The discussion started here:
+
+ http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1538.html
+
+And spawned a second thread (specifically on tar vs cpio), starting here:
+
+ http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1587.html
+
+The quick and dirty summary version (which is no substitute for reading
+the above threads) is:
+
+1) cpio is a standard. It's decades old (from the AT&T days), and already
+ widely used on Linux (inside RPM, Red Hat's device driver disks). Here's
+ a Linux Journal article about it from 1996:
+
+ http://www.linuxjournal.com/article/1213
+
+ It's not as popular as tar because the traditional cpio command line tools
+ require _truly_hideous_ command line arguments. But that says nothing
+ either way about the archive format, and there are alternative tools,
+ such as:
+
+ http://freshmeat.net/projects/afio/
+
+2) The cpio archive format chosen by the kernel is simpler and cleaner (and
+ thus easier to create and parse) than any of the (literally dozens of)
+ various tar archive formats. The complete initramfs archive format is
+ explained in buffer-format.txt, created in usr/gen_init_cpio.c, and
+ extracted in init/initramfs.c. All three together come to less than 26k
+ total of human-readable text.
+
+3) The GNU project standardizing on tar is approximately as relevant as
+ Windows standardizing on zip. Linux is not part of either, and is free
+ to make its own technical decisions.
+
+4) Since this is a kernel internal format, it could easily have been
+ something brand new. The kernel provides its own tools to create and
+ extract this format anyway. Using an existing standard was preferable,
+ but not essential.
+
+5) Al Viro made the decision (quote: "tar is ugly as hell and not going to be
+ supported on the kernel side"):
+
+ http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1540.html
+
+ explained his reasoning:
+
+ http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1550.html
+ http://www.uwsg.iu.edu/hypermail/linux/kernel/0112.2/1638.html
+
+ and, most importantly, designed and implemented the initramfs code.
+
Future directions:
------------------
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
index d803abed29f0..5832377b7340 100644
--- a/Documentation/filesystems/relayfs.txt
+++ b/Documentation/filesystems/relayfs.txt
@@ -44,30 +44,41 @@ 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.
+userspace and kernel, allowing the kernel side to remain simple and
+not impose a single interface on userspace. It does provide a set of
+examples and a separate helper though, described below.
+
+klog and relay-apps example code
+================================
+
+relayfs itself is ready to use, but to make things easier, a couple
+simple utility functions and a set of examples are provided.
+
+The relay-apps example tarball, available on the relayfs sourceforge
+site, contains a set of self-contained examples, each consisting of a
+pair of .c files containing boilerplate code for each of the user and
+kernel sides of a relayfs application; combined these two sets of
+boilerplate code provide glue to easily stream data to disk, without
+having to bother with mundane housekeeping chores.
+
+The 'klog debugging functions' patch (klog.patch in the relay-apps
+tarball) provides a couple of high-level logging functions to the
+kernel which allow writing formatted text or raw data to a channel,
+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. These functions allow you to put unconditional 'trace'
+statements anywhere in the kernel or kernel modules; only when there
+is a 'klog handler' registered will data actually be logged (see the
+klog and kleak examples for details).
+
+It is of course possible to use relayfs from scratch i.e. without
+using any of the relay-apps example code or klog, 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 and the relay-apps examples can be found in the relay-apps
+tarball on http://relayfs.sourceforge.net
-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
==========================
@@ -125,6 +136,8 @@ Here's a summary of the API relayfs provides to in-kernel clients:
relay_reset(chan)
relayfs_create_dir(name, parent)
relayfs_remove_dir(dentry)
+ relayfs_create_file(name, parent, mode, fops, data)
+ relayfs_remove_file(dentry)
channel management typically called on instigation of userspace:
@@ -141,6 +154,8 @@ Here's a summary of the API relayfs provides to in-kernel clients:
subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
buf_mapped(buf, filp)
buf_unmapped(buf, filp)
+ create_buf_file(filename, parent, mode, buf, is_global)
+ remove_buf_file(dentry)
helper functions:
@@ -320,6 +335,71 @@ 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.
+Creating non-relay files
+------------------------
+
+relay_open() automatically creates files in the relayfs filesystem to
+represent the per-cpu kernel buffers; it's often useful for
+applications to be able to create their own files alongside the relay
+files in the relayfs filesystem as well e.g. 'control' files much like
+those created in /proc or debugfs for similar purposes, used to
+communicate control information between the kernel and user sides of a
+relayfs application. For this purpose the relayfs_create_file() and
+relayfs_remove_file() API functions exist. For relayfs_create_file(),
+the caller passes in a set of user-defined file operations to be used
+for the file and an optional void * to a user-specified data item,
+which will be accessible via inode->u.generic_ip (see the relay-apps
+tarball for examples). The file_operations are a required parameter
+to relayfs_create_file() and thus the semantics of these files are
+completely defined by the caller.
+
+See the relay-apps tarball at http://relayfs.sourceforge.net for
+examples of how these non-relay files are meant to be used.
+
+Creating relay files in other filesystems
+-----------------------------------------
+
+By default of course, relay_open() creates relay files in the relayfs
+filesystem. Because relay_file_operations is exported, however, it's
+also possible to create and use relay files in other pseudo-filesytems
+such as debugfs.
+
+For this purpose, two callback functions are provided,
+create_buf_file() and remove_buf_file(). create_buf_file() is called
+once for each per-cpu buffer from relay_open() to allow the client to
+create a file to be used to represent the corresponding buffer; if
+this callback is not defined, the default implementation will create
+and return a file in the relayfs filesystem to represent the buffer.
+The callback should return the dentry of the file created to represent
+the relay buffer. Note that the parent directory passed to
+relay_open() (and passed along to the callback), if specified, must
+exist in the same filesystem the new relay file is created in. If
+create_buf_file() is defined, remove_buf_file() must also be defined;
+it's responsible for deleting the file(s) created in create_buf_file()
+and is called during relay_close().
+
+The create_buf_file() implementation can also be defined in such a way
+as to allow the creation of a single 'global' buffer instead of the
+default per-cpu set. This can be useful for applications interested
+mainly in seeing the relative ordering of system-wide events without
+the need to bother with saving explicit timestamps for the purpose of
+merging/sorting per-cpu files in a postprocessing step.
+
+To have relay_open() create a global buffer, the create_buf_file()
+implementation should set the value of the is_global outparam to a
+non-zero value in addition to creating the file that will be used to
+represent the single buffer. In the case of a global buffer,
+create_buf_file() and remove_buf_file() will be called only once. The
+normal channel-writing functions e.g. relay_write() can still be used
+- writes from any cpu will transparently end up in the global buffer -
+but since it is a global buffer, callers should make sure they use the
+proper locking for such a buffer, either by wrapping writes in a
+spinlock, or by copying a write function from relayfs_fs.h and
+creating a local version that internally does the proper locking.
+
+See the 'exported-relayfile' examples in the relay-apps tarball for
+examples of creating and using relay files in debugfs.
+
Misc
----
diff --git a/Documentation/filesystems/spufs.txt b/Documentation/filesystems/spufs.txt
new file mode 100644
index 000000000000..8edc3952eff4
--- /dev/null
+++ b/Documentation/filesystems/spufs.txt
@@ -0,0 +1,521 @@
+SPUFS(2) Linux Programmer's Manual SPUFS(2)
+
+
+
+NAME
+ spufs - the SPU file system
+
+
+DESCRIPTION
+ The SPU file system is used on PowerPC machines that implement the Cell
+ Broadband Engine Architecture in order to access Synergistic Processor
+ Units (SPUs).
+
+ The file system provides a name space similar to posix shared memory or
+ message queues. Users that have write permissions on the file system
+ can use spu_create(2) to establish SPU contexts in the spufs root.
+
+ Every SPU context is represented by a directory containing a predefined
+ set of files. These files can be used for manipulating the state of the
+ logical SPU. Users can change permissions on those files, but not actu-
+ ally add or remove files.
+
+
+MOUNT OPTIONS
+ uid=<uid>
+ set the user owning the mount point, the default is 0 (root).
+
+ gid=<gid>
+ set the group owning the mount point, the default is 0 (root).
+
+
+FILES
+ The files in spufs mostly follow the standard behavior for regular sys-
+ tem calls like read(2) or write(2), but often support only a subset of
+ the operations supported on regular file systems. This list details the
+ supported operations and the deviations from the behaviour in the
+ respective man pages.
+
+ All files that support the read(2) operation also support readv(2) and
+ all files that support the write(2) operation also support writev(2).
+ All files support the access(2) and stat(2) family of operations, but
+ only the st_mode, st_nlink, st_uid and st_gid fields of struct stat
+ contain reliable information.
+
+ All files support the chmod(2)/fchmod(2) and chown(2)/fchown(2) opera-
+ tions, but will not be able to grant permissions that contradict the
+ possible operations, e.g. read access on the wbox file.
+
+ The current set of files is:
+
+
+ /mem
+ the contents of the local storage memory of the SPU. This can be
+ accessed like a regular shared memory file and contains both code and
+ data in the address space of the SPU. The possible operations on an
+ open mem file are:
+
+ read(2), pread(2), write(2), pwrite(2), lseek(2)
+ These operate as documented, with the exception that seek(2),
+ write(2) and pwrite(2) are not supported beyond the end of the
+ file. The file size is the size of the local storage of the SPU,
+ which normally is 256 kilobytes.
+
+ mmap(2)
+ Mapping mem into the process address space gives access to the
+ SPU local storage within the process address space. Only
+ MAP_SHARED mappings are allowed.
+
+
+ /mbox
+ The first SPU to CPU communication mailbox. This file is read-only and
+ can be read in units of 32 bits. The file can only be used in non-
+ blocking mode and it even poll() will not block on it. The possible
+ operations on an open mbox file are:
+
+ read(2)
+ If a count smaller than four is requested, read returns -1 and
+ sets errno to EINVAL. If there is no data available in the mail
+ box, the return value is set to -1 and errno becomes EAGAIN.
+ When data has been read successfully, four bytes are placed in
+ the data buffer and the value four is returned.
+
+
+ /ibox
+ The second SPU to CPU communication mailbox. This file is similar to
+ the first mailbox file, but can be read in blocking I/O mode, and the
+ poll familiy of system calls can be used to wait for it. The possible
+ operations on an open ibox file are:
+
+ read(2)
+ If a count smaller than four is requested, read returns -1 and
+ sets errno to EINVAL. If there is no data available in the mail
+ box and the file descriptor has been opened with O_NONBLOCK, the
+ return value is set to -1 and errno becomes EAGAIN.
+
+ If there is no data available in the mail box and the file
+ descriptor has been opened without O_NONBLOCK, the call will
+ block until the SPU writes to its interrupt mailbox channel.
+ When data has been read successfully, four bytes are placed in
+ the data buffer and the value four is returned.
+
+ poll(2)
+ Poll on the ibox file returns (POLLIN | POLLRDNORM) whenever
+ data is available for reading.
+
+
+ /wbox
+ The CPU to SPU communation mailbox. It is write-only can can be written
+ in units of 32 bits. If the mailbox is full, write() will block and
+ poll can be used to wait for it becoming empty again. The possible
+ operations on an open wbox file are: write(2) If a count smaller than
+ four is requested, write returns -1 and sets errno to EINVAL. If there
+ is no space available in the mail box and the file descriptor has been
+ opened with O_NONBLOCK, the return value is set to -1 and errno becomes
+ EAGAIN.
+
+ If there is no space available in the mail box and the file descriptor
+ has been opened without O_NONBLOCK, the call will block until the SPU
+ reads from its PPE mailbox channel. When data has been read success-
+ fully, four bytes are placed in the data buffer and the value four is
+ returned.
+
+ poll(2)
+ Poll on the ibox file returns (POLLOUT | POLLWRNORM) whenever
+ space is available for writing.
+
+
+ /mbox_stat
+ /ibox_stat
+ /wbox_stat
+ Read-only files that contain the length of the current queue, i.e. how
+ many words can be read from mbox or ibox or how many words can be
+ written to wbox without blocking. The files can be read only in 4-byte
+ units and return a big-endian binary integer number. The possible
+ operations on an open *box_stat file are:
+
+ read(2)
+ If a count smaller than four is requested, read returns -1 and
+ sets errno to EINVAL. Otherwise, a four byte value is placed in
+ the data buffer, containing the number of elements that can be
+ read from (for mbox_stat and ibox_stat) or written to (for
+ wbox_stat) the respective mail box without blocking or resulting
+ in EAGAIN.
+
+
+ /npc
+ /decr
+ /decr_status
+ /spu_tag_mask
+ /event_mask
+ /srr0
+ Internal registers of the SPU. The representation is an ASCII string
+ with the numeric value of the next instruction to be executed. These
+ can be used in read/write mode for debugging, but normal operation of
+ programs should not rely on them because access to any of them except
+ npc requires an SPU context save and is therefore very inefficient.
+
+ The contents of these files are:
+
+ npc Next Program Counter
+
+ decr SPU Decrementer
+
+ decr_status Decrementer Status
+
+ spu_tag_mask MFC tag mask for SPU DMA
+
+ event_mask Event mask for SPU interrupts
+
+ srr0 Interrupt Return address register
+
+
+ The possible operations on an open npc, decr, decr_status,
+ spu_tag_mask, event_mask or srr0 file are:
+
+ read(2)
+ When the count supplied to the read call is shorter than the
+ required length for the pointer value plus a newline character,
+ subsequent reads from the same file descriptor will result in
+ completing the string, regardless of changes to the register by
+ a running SPU task. When a complete string has been read, all
+ subsequent read operations will return zero bytes and a new file
+ descriptor needs to be opened to read the value again.
+
+ write(2)
+ A write operation on the file results in setting the register to
+ the value given in the string. The string is parsed from the
+ beginning to the first non-numeric character or the end of the
+ buffer. Subsequent writes to the same file descriptor overwrite
+ the previous setting.
+
+
+ /fpcr
+ This file gives access to the Floating Point Status and Control Regis-
+ ter as a four byte long file. The operations on the fpcr file are:
+
+ read(2)
+ If a count smaller than four is requested, read returns -1 and
+ sets errno to EINVAL. Otherwise, a four byte value is placed in
+ the data buffer, containing the current value of the fpcr regis-
+ ter.
+
+ write(2)
+ If a count smaller than four is requested, write returns -1 and
+ sets errno to EINVAL. Otherwise, a four byte value is copied
+ from the data buffer, updating the value of the fpcr register.
+
+
+ /signal1
+ /signal2
+ The two signal notification channels of an SPU. These are read-write
+ files that operate on a 32 bit word. Writing to one of these files
+ triggers an interrupt on the SPU. The value writting to the signal
+ files can be read from the SPU through a channel read or from host user
+ space through the file. After the value has been read by the SPU, it
+ is reset to zero. The possible operations on an open signal1 or sig-
+ nal2 file are:
+
+ read(2)
+ If a count smaller than four is requested, read returns -1 and
+ sets errno to EINVAL. Otherwise, a four byte value is placed in
+ the data buffer, containing the current value of the specified
+ signal notification register.
+
+ write(2)
+ If a count smaller than four is requested, write returns -1 and
+ sets errno to EINVAL. Otherwise, a four byte value is copied
+ from the data buffer, updating the value of the specified signal
+ notification register. The signal notification register will
+ either be replaced with the input data or will be updated to the
+ bitwise OR or the old value and the input data, depending on the
+ contents of the signal1_type, or signal2_type respectively,
+ file.
+
+
+ /signal1_type
+ /signal2_type
+ These two files change the behavior of the signal1 and signal2 notifi-
+ cation files. The contain a numerical ASCII string which is read as
+ either "1" or "0". In mode 0 (overwrite), the hardware replaces the
+ contents of the signal channel with the data that is written to it. in
+ mode 1 (logical OR), the hardware accumulates the bits that are subse-
+ quently written to it. The possible operations on an open signal1_type
+ or signal2_type file are:
+
+ read(2)
+ When the count supplied to the read call is shorter than the
+ required length for the digit plus a newline character, subse-
+ quent reads from the same file descriptor will result in com-
+ pleting the string. When a complete string has been read, all
+ subsequent read operations will return zero bytes and a new file
+ descriptor needs to be opened to read the value again.
+
+ write(2)
+ A write operation on the file results in setting the register to
+ the value given in the string. The string is parsed from the
+ beginning to the first non-numeric character or the end of the
+ buffer. Subsequent writes to the same file descriptor overwrite
+ the previous setting.
+
+
+EXAMPLES
+ /etc/fstab entry
+ none /spu spufs gid=spu 0 0
+
+
+AUTHORS
+ Arnd Bergmann <arndb@de.ibm.com>, Mark Nutter <mnutter@us.ibm.com>,
+ Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+SEE ALSO
+ capabilities(7), close(2), spu_create(2), spu_run(2), spufs(7)
+
+
+
+Linux 2005-09-28 SPUFS(2)
+
+------------------------------------------------------------------------------
+
+SPU_RUN(2) Linux Programmer's Manual SPU_RUN(2)
+
+
+
+NAME
+ spu_run - execute an spu context
+
+
+SYNOPSIS
+ #include <sys/spu.h>
+
+ int spu_run(int fd, unsigned int *npc, unsigned int *event);
+
+DESCRIPTION
+ The spu_run system call is used on PowerPC machines that implement the
+ Cell Broadband Engine Architecture in order to access Synergistic Pro-
+ cessor Units (SPUs). It uses the fd that was returned from spu_cre-
+ ate(2) to address a specific SPU context. When the context gets sched-
+ uled to a physical SPU, it starts execution at the instruction pointer
+ passed in npc.
+
+ Execution of SPU code happens synchronously, meaning that spu_run does
+ not return while the SPU is still running. If there is a need to exe-
+ cute SPU code in parallel with other code on either the main CPU or
+ other SPUs, you need to create a new thread of execution first, e.g.
+ using the pthread_create(3) call.
+
+ When spu_run returns, the current value of the SPU instruction pointer
+ is written back to npc, so you can call spu_run again without updating
+ the pointers.
+
+ event can be a NULL pointer or point to an extended status code that
+ gets filled when spu_run returns. It can be one of the following con-
+ stants:
+
+ SPE_EVENT_DMA_ALIGNMENT
+ A DMA alignment error
+
+ SPE_EVENT_SPE_DATA_SEGMENT
+ A DMA segmentation error
+
+ SPE_EVENT_SPE_DATA_STORAGE
+ A DMA storage error
+
+ If NULL is passed as the event argument, these errors will result in a
+ signal delivered to the calling process.
+
+RETURN VALUE
+ spu_run returns the value of the spu_status register or -1 to indicate
+ an error and set errno to one of the error codes listed below. The
+ spu_status register value contains a bit mask of status codes and
+ optionally a 14 bit code returned from the stop-and-signal instruction
+ on the SPU. The bit masks for the status codes are:
+
+ 0x02 SPU was stopped by stop-and-signal.
+
+ 0x04 SPU was stopped by halt.
+
+ 0x08 SPU is waiting for a channel.
+
+ 0x10 SPU is in single-step mode.
+
+ 0x20 SPU has tried to execute an invalid instruction.
+
+ 0x40 SPU has tried to access an invalid channel.
+
+ 0x3fff0000
+ The bits masked with this value contain the code returned from
+ stop-and-signal.
+
+ There are always one or more of the lower eight bits set or an error
+ code is returned from spu_run.
+
+ERRORS
+ EAGAIN or EWOULDBLOCK
+ fd is in non-blocking mode and spu_run would block.
+
+ EBADF fd is not a valid file descriptor.
+
+ EFAULT npc is not a valid pointer or status is neither NULL nor a valid
+ pointer.
+
+ EINTR A signal occured while spu_run was in progress. The npc value
+ has been updated to the new program counter value if necessary.
+
+ EINVAL fd is not a file descriptor returned from spu_create(2).
+
+ ENOMEM Insufficient memory was available to handle a page fault result-
+ ing from an MFC direct memory access.
+
+ ENOSYS the functionality is not provided by the current system, because
+ either the hardware does not provide SPUs or the spufs module is
+ not loaded.
+
+
+NOTES
+ spu_run is meant to be used from libraries that implement a more
+ abstract interface to SPUs, not to be used from regular applications.
+ See http://www.bsc.es/projects/deepcomputing/linuxoncell/ for the rec-
+ ommended libraries.
+
+
+CONFORMING TO
+ This call is Linux specific and only implemented by the ppc64 architec-
+ ture. Programs using this system call are not portable.
+
+
+BUGS
+ The code does not yet fully implement all features lined out here.
+
+
+AUTHOR
+ Arnd Bergmann <arndb@de.ibm.com>
+
+SEE ALSO
+ capabilities(7), close(2), spu_create(2), spufs(7)
+
+
+
+Linux 2005-09-28 SPU_RUN(2)
+
+------------------------------------------------------------------------------
+
+SPU_CREATE(2) Linux Programmer's Manual SPU_CREATE(2)
+
+
+
+NAME
+ spu_create - create a new spu context
+
+
+SYNOPSIS
+ #include <sys/types.h>
+ #include <sys/spu.h>
+
+ int spu_create(const char *pathname, int flags, mode_t mode);
+
+DESCRIPTION
+ The spu_create system call is used on PowerPC machines that implement
+ the Cell Broadband Engine Architecture in order to access Synergistic
+ Processor Units (SPUs). It creates a new logical context for an SPU in
+ pathname and returns a handle to associated with it. pathname must
+ point to a non-existing directory in the mount point of the SPU file
+ system (spufs). When spu_create is successful, a directory gets cre-
+ ated on pathname and it is populated with files.
+
+ The returned file handle can only be passed to spu_run(2) or closed,
+ other operations are not defined on it. When it is closed, all associ-
+ ated directory entries in spufs are removed. When the last file handle
+ pointing either inside of the context directory or to this file
+ descriptor is closed, the logical SPU context is destroyed.
+
+ The parameter flags can be zero or any bitwise or'd combination of the
+ following constants:
+
+ SPU_RAWIO
+ Allow mapping of some of the hardware registers of the SPU into
+ user space. This flag requires the CAP_SYS_RAWIO capability, see
+ capabilities(7).
+
+ The mode parameter specifies the permissions used for creating the new
+ directory in spufs. mode is modified with the user's umask(2) value
+ and then used for both the directory and the files contained in it. The
+ file permissions mask out some more bits of mode because they typically
+ support only read or write access. See stat(2) for a full list of the
+ possible mode values.
+
+
+RETURN VALUE
+ spu_create returns a new file descriptor. It may return -1 to indicate
+ an error condition and set errno to one of the error codes listed
+ below.
+
+
+ERRORS
+ EACCESS
+ The current user does not have write access on the spufs mount
+ point.
+
+ EEXIST An SPU context already exists at the given path name.
+
+ EFAULT pathname is not a valid string pointer in the current address
+ space.
+
+ EINVAL pathname is not a directory in the spufs mount point.
+
+ ELOOP Too many symlinks were found while resolving pathname.
+
+ EMFILE The process has reached its maximum open file limit.
+
+ ENAMETOOLONG
+ pathname was too long.
+
+ ENFILE The system has reached the global open file limit.
+
+ ENOENT Part of pathname could not be resolved.
+
+ ENOMEM The kernel could not allocate all resources required.
+
+ ENOSPC There are not enough SPU resources available to create a new
+ context or the user specific limit for the number of SPU con-
+ texts has been reached.
+
+ ENOSYS the functionality is not provided by the current system, because
+ either the hardware does not provide SPUs or the spufs module is
+ not loaded.
+
+ ENOTDIR
+ A part of pathname is not a directory.
+
+
+
+NOTES
+ spu_create is meant to be used from libraries that implement a more
+ abstract interface to SPUs, not to be used from regular applications.
+ See http://www.bsc.es/projects/deepcomputing/linuxoncell/ for the rec-
+ ommended libraries.
+
+
+FILES
+ pathname must point to a location beneath the mount point of spufs. By
+ convention, it gets mounted in /spu.
+
+
+CONFORMING TO
+ This call is Linux specific and only implemented by the ppc64 architec-
+ ture. Programs using this system call are not portable.
+
+
+BUGS
+ The code does not yet fully implement all features lined out here.
+
+
+AUTHOR
+ Arnd Bergmann <arndb@de.ibm.com>
+
+SEE ALSO
+ capabilities(7), close(2), spu_run(2), spufs(7)
+
+
+
+Linux 2005-09-28 SPU_CREATE(2)
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index 988a62fae11f..7ba2baa165ff 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -1,4 +1,5 @@
Accessing PCI device resources through sysfs
+--------------------------------------------
sysfs, usually mounted at /sys, provides access to PCI resources on platforms
that support it. For example, a given bus might look like this:
@@ -47,14 +48,21 @@ files, each with their own function.
binary - file contains binary data
cpumask - file contains a cpumask type
-The read only files are informational, writes to them will be ignored.
-Writable files can be used to perform actions on the device (e.g. changing
-config space, detaching a device). mmapable files are available via an
-mmap of the file at offset 0 and can be used to do actual device programming
-from userspace. Note that some platforms don't support mmapping of certain
-resources, so be sure to check the return value from any attempted mmap.
+The read only files are informational, writes to them will be ignored, with
+the exception of the 'rom' file. Writable files can be used to perform
+actions on the device (e.g. changing config space, detaching a device).
+mmapable files are available via an mmap of the file at offset 0 and can be
+used to do actual device programming from userspace. Note that some platforms
+don't support mmapping of certain resources, so be sure to check the return
+value from any attempted mmap.
+
+The 'rom' file is special in that it provides read-only access to the device's
+ROM file, if available. It's disabled by default, however, so applications
+should write the string "1" to the file to enable it before attempting a read
+call, and disable it following the access by writing "0" to the file.
Accessing legacy resources through sysfs
+----------------------------------------
Legacy I/O port and ISA memory resources are also provided in sysfs if the
underlying platform supports them. They're located in the PCI class heirarchy,
@@ -75,6 +83,7 @@ simply dereference the returned pointer (after checking for errors of course)
to access legacy memory space.
Supporting PCI access on new platforms
+--------------------------------------
In order to support PCI resource mapping as described above, Linux platform
code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 0d783c504ead..dbe4d87d2615 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -78,6 +78,18 @@ use up all the memory on the machine; but enhances the scalability of
that instance in a system with many cpus making intensive use of it.
+tmpfs has a mount option to set the NUMA memory allocation policy for
+all files in that instance:
+mpol=interleave prefers to allocate memory from each node in turn
+mpol=default prefers to allocate memory from the local node
+mpol=bind prefers to allocate from mpol_nodelist
+mpol=preferred prefers to allocate from first node in mpol_nodelist
+
+The following mount option is used in conjunction with mpol=interleave,
+mpol=bind or mpol=preferred:
+mpol_nodelist: nodelist suitable for parsing with nodelist_parse.
+
+
To specify the initial root directory you can use the following mount
options:
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index ee4c0a8b8db7..e56e842847d3 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -162,9 +162,8 @@ 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:
+Usually, a filesystem uses 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
diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt
index e52457581f47..b7a3dc38dd52 100644
--- a/Documentation/hpet.txt
+++ b/Documentation/hpet.txt
@@ -2,7 +2,7 @@
The High Precision Event Timer (HPET) hardware is the future replacement
for the 8254 and Real Time Clock (RTC) periodic timer functionality.
-Each HPET can have up two 32 timers. It is possible to configure the
+Each HPET can have up to 32 timers. It is possible to configure the
first two timers as legacy replacements for 8254 and RTC periodic timers.
A specification done by Intel and Microsoft can be found at
<http://www.intel.com/hardwaredesign/hpetspec.htm>.
diff --git a/Documentation/hrtimers.txt b/Documentation/hrtimers.txt
new file mode 100644
index 000000000000..7620ff735faf
--- /dev/null
+++ b/Documentation/hrtimers.txt
@@ -0,0 +1,178 @@
+
+hrtimers - subsystem for high-resolution kernel timers
+----------------------------------------------------
+
+This patch introduces a new subsystem for high-resolution kernel timers.
+
+One might ask the question: we already have a timer subsystem
+(kernel/timers.c), why do we need two timer subsystems? After a lot of
+back and forth trying to integrate high-resolution and high-precision
+features into the existing timer framework, and after testing various
+such high-resolution timer implementations in practice, we came to the
+conclusion that the timer wheel code is fundamentally not suitable for
+such an approach. We initially didnt believe this ('there must be a way
+to solve this'), and spent a considerable effort trying to integrate
+things into the timer wheel, but we failed. In hindsight, there are
+several reasons why such integration is hard/impossible:
+
+- the forced handling of low-resolution and high-resolution timers in
+ the same way leads to a lot of compromises, macro magic and #ifdef
+ mess. The timers.c code is very "tightly coded" around jiffies and
+ 32-bitness assumptions, and has been honed and micro-optimized for a
+ relatively narrow use case (jiffies in a relatively narrow HZ range)
+ for many years - and thus even small extensions to it easily break
+ the wheel concept, leading to even worse compromises. The timer wheel
+ code is very good and tight code, there's zero problems with it in its
+ current usage - but it is simply not suitable to be extended for
+ high-res timers.
+
+- the unpredictable [O(N)] overhead of cascading leads to delays which
+ necessiate a more complex handling of high resolution timers, which
+ in turn decreases robustness. Such a design still led to rather large
+ timing inaccuracies. Cascading is a fundamental property of the timer
+ wheel concept, it cannot be 'designed out' without unevitably
+ degrading other portions of the timers.c code in an unacceptable way.
+
+- the implementation of the current posix-timer subsystem on top of
+ the timer wheel has already introduced a quite complex handling of
+ the required readjusting of absolute CLOCK_REALTIME timers at
+ settimeofday or NTP time - further underlying our experience by
+ example: that the timer wheel data structure is too rigid for high-res
+ timers.
+
+- the timer wheel code is most optimal for use cases which can be
+ identified as "timeouts". Such timeouts are usually set up to cover
+ error conditions in various I/O paths, such as networking and block
+ I/O. The vast majority of those timers never expire and are rarely
+ recascaded because the expected correct event arrives in time so they
+ can be removed from the timer wheel before any further processing of
+ them becomes necessary. Thus the users of these timeouts can accept
+ the granularity and precision tradeoffs of the timer wheel, and
+ largely expect the timer subsystem to have near-zero overhead.
+ Accurate timing for them is not a core purpose - in fact most of the
+ timeout values used are ad-hoc. For them it is at most a necessary
+ evil to guarantee the processing of actual timeout completions
+ (because most of the timeouts are deleted before completion), which
+ should thus be as cheap and unintrusive as possible.
+
+The primary users of precision timers are user-space applications that
+utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel
+users like drivers and subsystems which require precise timed events
+(e.g. multimedia) can benefit from the availability of a seperate
+high-resolution timer subsystem as well.
+
+While this subsystem does not offer high-resolution clock sources just
+yet, the hrtimer subsystem can be easily extended with high-resolution
+clock capabilities, and patches for that exist and are maturing quickly.
+The increasing demand for realtime and multimedia applications along
+with other potential users for precise timers gives another reason to
+separate the "timeout" and "precise timer" subsystems.
+
+Another potential benefit is that such a seperation allows even more
+special-purpose optimization of the existing timer wheel for the low
+resolution and low precision use cases - once the precision-sensitive
+APIs are separated from the timer wheel and are migrated over to
+hrtimers. E.g. we could decrease the frequency of the timeout subsystem
+from 250 Hz to 100 HZ (or even smaller).
+
+hrtimer subsystem implementation details
+----------------------------------------
+
+the basic design considerations were:
+
+- simplicity
+
+- data structure not bound to jiffies or any other granularity. All the
+ kernel logic works at 64-bit nanoseconds resolution - no compromises.
+
+- simplification of existing, timing related kernel code
+
+another basic requirement was the immediate enqueueing and ordering of
+timers at activation time. After looking at several possible solutions
+such as radix trees and hashes, we chose the red black tree as the basic
+data structure. Rbtrees are available as a library in the kernel and are
+used in various performance-critical areas of e.g. memory management and
+file systems. The rbtree is solely used for time sorted ordering, while
+a separate list is used to give the expiry code fast access to the
+queued timers, without having to walk the rbtree.
+
+(This seperate list is also useful for later when we'll introduce
+high-resolution clocks, where we need seperate pending and expired
+queues while keeping the time-order intact.)
+
+Time-ordered enqueueing is not purely for the purposes of
+high-resolution clocks though, it also simplifies the handling of
+absolute timers based on a low-resolution CLOCK_REALTIME. The existing
+implementation needed to keep an extra list of all armed absolute
+CLOCK_REALTIME timers along with complex locking. In case of
+settimeofday and NTP, all the timers (!) had to be dequeued, the
+time-changing code had to fix them up one by one, and all of them had to
+be enqueued again. The time-ordered enqueueing and the storage of the
+expiry time in absolute time units removes all this complex and poorly
+scaling code from the posix-timer implementation - the clock can simply
+be set without having to touch the rbtree. This also makes the handling
+of posix-timers simpler in general.
+
+The locking and per-CPU behavior of hrtimers was mostly taken from the
+existing timer wheel code, as it is mature and well suited. Sharing code
+was not really a win, due to the different data structures. Also, the
+hrtimer functions now have clearer behavior and clearer names - such as
+hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
+equivalent to del_timer() and del_timer_sync()] - so there's no direct
+1:1 mapping between them on the algorithmical level, and thus no real
+potential for code sharing either.
+
+Basic data types: every time value, absolute or relative, is in a
+special nanosecond-resolution type: ktime_t. The kernel-internal
+representation of ktime_t values and operations is implemented via
+macros and inline functions, and can be switched between a "hybrid
+union" type and a plain "scalar" 64bit nanoseconds representation (at
+compile time). The hybrid union type optimizes time conversions on 32bit
+CPUs. This build-time-selectable ktime_t storage format was implemented
+to avoid the performance impact of 64-bit multiplications and divisions
+on 32bit CPUs. Such operations are frequently necessary to convert
+between the storage formats provided by kernel and userspace interfaces
+and the internal time format. (See include/linux/ktime.h for further
+details.)
+
+hrtimers - rounding of timer values
+-----------------------------------
+
+the hrtimer code will round timer events to lower-resolution clocks
+because it has to. Otherwise it will do no artificial rounding at all.
+
+one question is, what resolution value should be returned to the user by
+the clock_getres() interface. This will return whatever real resolution
+a given clock has - be it low-res, high-res, or artificially-low-res.
+
+hrtimers - testing and verification
+----------------------------------
+
+We used the high-resolution clock subsystem ontop of hrtimers to verify
+the hrtimer implementation details in praxis, and we also ran the posix
+timer tests in order to ensure specification compliance. We also ran
+tests on low-resolution clocks.
+
+The hrtimer patch converts the following kernel functionality to use
+hrtimers:
+
+ - nanosleep
+ - itimers
+ - posix-timers
+
+The conversion of nanosleep and posix-timers enabled the unification of
+nanosleep and clock_nanosleep.
+
+The code was successfully compiled for the following platforms:
+
+ i386, x86_64, ARM, PPC, PPC64, IA64
+
+The code was run-tested on the following platforms:
+
+ i386(UP/SMP), x86_64(UP/SMP), ARM, PPC
+
+hrtimers were also integrated into the -rt tree, along with a
+hrtimers-based high-resolution clock implementation, so the hrtimers
+code got a healthy amount of testing and use in practice.
+
+ Thomas Gleixner, Ingo Molnar
diff --git a/Documentation/hwmon/w83627hf b/Documentation/hwmon/w83627hf
index 78f37c2d602e..5d23776e9907 100644
--- a/Documentation/hwmon/w83627hf
+++ b/Documentation/hwmon/w83627hf
@@ -54,13 +54,16 @@ If you really want i2c accesses for these Super I/O chips,
use the w83781d driver. However this is not the preferred method
now that this ISA driver has been developed.
-Technically, the w83627thf does not support a VID reading. However, it's
-possible or even likely that your mainboard maker has routed these signals
-to a specific set of general purpose IO pins (the Asus P4C800-E is one such
-board). The w83627thf driver now interprets these as VID. If the VID on
-your board doesn't work, first see doc/vid in the lm_sensors package. If
-that still doesn't help, email us at lm-sensors@lm-sensors.org.
+The w83627_HF_ uses pins 110-106 as VID0-VID4. The w83627_THF_ uses the
+same pins as GPIO[0:4]. Technically, the w83627_THF_ does not support a
+VID reading. However the two chips have the identical 128 pin package. So,
+it is possible or even likely for a w83627thf to have the VID signals routed
+to these pins despite their not being labeled for that purpose. Therefore,
+the w83627thf driver interprets these as VID. If the VID on your board
+doesn't work, first see doc/vid in the lm_sensors package[1]. If that still
+doesn't help, you may just ignore the bogus VID reading with no harm done.
-For further information on this driver see the w83781d driver
-documentation.
+For further information on this driver see the w83781d driver documentation.
+
+[1] http://www2.lm-sensors.nu/~lm78/cvs/browse.cgi/lm_sensors2/doc/vid
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index e379e182e64f..d751282d9b2a 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -5,7 +5,8 @@ Supported adapters:
* nForce2 Ultra 400 MCP 10de:0084
* nForce3 Pro150 MCP 10de:00D4
* nForce3 250Gb MCP 10de:00E4
- * nForce4 MCP 10de:0052
+ * nForce4 MCP 10de:0052
+ * nForce4 MCP-04 10de:0034
Datasheet: not publically available, but seems to be similar to the
AMD-8111 SMBus 2.0 adapter.
diff --git a/Documentation/i2c/busses/i2c-parport b/Documentation/i2c/busses/i2c-parport
index 9f1d0082da18..d9f23c0763f1 100644
--- a/Documentation/i2c/busses/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -17,6 +17,7 @@ It currently supports the following devices:
* Velleman K8000 adapter
* ELV adapter
* Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
+ * Barco LPT->DVI (K5800236) adapter
These devices use different pinout configurations, so you have to tell
the driver what you have, using the type module parameter. There is no
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index 184fac2377aa..f03c2a02f806 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -1,10 +1,13 @@
-Revision 5, 2005-07-29
+Revision 6, 2005-11-20
Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com>
This is a guide on how to convert I2C chip drivers from Linux 2.4 to
Linux 2.6. I have been using existing drivers (lm75, lm78) as examples.
Then I converted a driver myself (lm83) and updated this document.
+Note that this guide is strongly oriented towards hardware monitoring
+drivers. Many points are still valid for other type of drivers, but
+others may be irrelevant.
There are two sets of points below. The first set concerns technical
changes. The second set concerns coding policy. Both are mandatory.
@@ -22,16 +25,20 @@ Technical changes:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
+ #include <linux/jiffies.h>
#include <linux/i2c.h>
+ #include <linux/i2c-isa.h> /* for ISA drivers */
#include <linux/hwmon.h> /* for hardware monitoring drivers */
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> /* if you need VRM support */
+ #include <linux/err.h> /* for class registration */
#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, ISA addresses
- are no more handled by the i2c core.
+ are no more handled by the i2c core. Address ranges are no more
+ supported either, define each individual address separately.
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
* [Client data] Get rid of sysctl_id. Try using standard names for
@@ -48,23 +55,23 @@ Technical changes:
int kind);
static void lm75_init_client(struct i2c_client *client);
static int lm75_detach_client(struct i2c_client *client);
- static void lm75_update_client(struct i2c_client *client);
+ static struct lm75_data lm75_update_device(struct device *dev);
* [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
and functions). Instead, you have to define show and set functions for
each sysfs file. Only define set for writable values. Take a look at an
- existing 2.6 driver for details (lm78 for example). Don't forget
+ existing 2.6 driver for details (it87 for example). Don't forget
to define the attributes for each file (this is that step that
links callback functions). Use the file names specified in
- Documentation/i2c/sysfs-interface for the individual files. Also
+ Documentation/hwmon/sysfs-interface for the individual files. Also
convert the units these files read and write to the specified ones.
If you need to add a new type of file, please discuss it on the
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
- patch to the Documentation/i2c/sysfs-interface file.
+ patch to the Documentation/hwmon/sysfs-interface file.
* [Attach] For I2C drivers, the attach function should make sure
- that the adapter's class has I2C_CLASS_HWMON, using the
- following construct:
+ that the adapter's class has I2C_CLASS_HWMON (or whatever class is
+ suitable for your driver), using the following construct:
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
ISA-only drivers of course don't need this.
@@ -72,63 +79,72 @@ Technical changes:
* [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").
+ name string, which will be filled with a lowercase, short string.
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
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
- ERROR0, ERROR1 and ERROR2. Don't forget to properly set err before
+ The labels used for error paths are reduced to the number needed.
+ It is advised that the labels are given descriptive names such as
+ exit and exit_free. Don't forget to properly set err before
jumping to error labels. By the way, labels should be left-aligned.
Use kzalloc instead of kmalloc.
Use i2c_set_clientdata to set the client data (as opposed to
a direct access to client->data).
- Use strlcpy instead of strcpy to copy the client name.
+ Use strlcpy instead of strcpy or snprintf to copy the client name.
Replace the sysctl directory registration by calls to
device_create_file. Move the driver initialization before any
sysfs file creation.
+ Register the client with the hwmon class (using hwmon_device_register)
+ if applicable.
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.
+ Don't add I2C_CLIENT_ALLOW_USE to client->flags, it's the default now.
* [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
- parameter may be used to force is), and initialization should be
+ parameter may be used to force it), and initialization should be
limited to the strictly necessary steps.
-* [Detach] Get rid of data, remove the call to
- 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.
-
-* [Interface] Init function should not print anything. Make sure
- there is a MODULE_LICENSE() line, at the bottom of the file
- (after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this order).
+* [Detach] Remove the call to i2c_deregister_entry. Do not log an
+ error message if i2c_detach_client fails, as i2c-core will now do
+ it for you.
+ Unregister from the hwmon class if applicable.
+
+* [Update] The function prototype changed, it is now
+ passed a device structure, which you have to convert to a client
+ using to_i2c_client(dev). The update function should return a
+ pointer to the client data.
+ Don't access client->data directly, use i2c_get_clientdata(client)
+ instead.
+ Use time_after() instead of direct jiffies comparison.
+
+* [Interface] Make sure there is a MODULE_LICENSE() line, at the bottom
+ of the file (after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this
+ order).
+
+* [Driver] The flags field of the i2c_driver structure is gone.
+ I2C_DF_NOTIFY is now the default behavior.
+ The i2c_driver structure has a driver member, which is itself a
+ structure, those name member should be initialized to a driver name
+ string. i2c_driver itself has no name member anymore.
Coding policy:
* [Copyright] Use (C), not (c), for copyright.
* [Debug/log] Get rid of #ifdef DEBUG/#endif constructs whenever you
- can. Calls to printk/pr_debug for debugging purposes are replaced
- by calls to dev_dbg. Here is an example on how to call it (taken
- from lm75_detect):
+ can. Calls to printk for debugging purposes are replaced by calls to
+ dev_dbg where possible, else to pr_debug. Here is an example of how
+ to call it (taken from lm75_detect):
dev_dbg(&client->dev, "Starting lm75 update\n");
Replace other printk calls with the dev_info, dev_err or dev_warn
function, as appropriate.
-* [Constants] Constants defines (registers, conversions, initial
- values) should be aligned. This greatly improves readability.
- Same goes for variables declarations. Alignments are achieved by the
- means of tabs, not spaces. Remember that tabs are set to 8 in the
- Linux kernel code.
-
-* [Structure definition] The name field should be standardized. All
- lowercase and as simple as the driver name itself (e.g. "lm75").
+* [Constants] Constants defines (registers, conversions) should be
+ aligned. This greatly improves readability.
+ Alignments are achieved by the means of tabs, not spaces. Remember
+ that tabs are set to 8 in the Linux kernel code.
* [Layout] Avoid extra empty lines between comments and what they
comment. Respect the coding style (see Documentation/CodingStyle),
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index d19993cc0604..3a057c8e5507 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -25,9 +25,9 @@ routines, a client structure specific information like the actual I2C
address.
static struct i2c_driver foo_driver = {
- .owner = THIS_MODULE,
- .name = "Foo version 2.3 driver",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "foo",
+ },
.attach_adapter = &foo_attach_adapter,
.detach_client = &foo_detach_client,
.command = &foo_command /* may be NULL */
@@ -36,10 +36,6 @@ static struct i2c_driver foo_driver = {
The name field must match the driver name, including the case. It must not
contain spaces, and may be up to 31 characters long.
-Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
-means that your driver will be notified when new adapters are found.
-This is almost always what you want.
-
All other fields are for call-back functions which will be explained
below.
@@ -496,17 +492,13 @@ Note that some functions are marked by `__init', and some data structures
by `__init_data'. Hose functions and structures can be removed after
kernel booting (or module loading) is completed.
+
Command function
================
A generic ioctl-like function call back is supported. You will seldom
-need this. You may even set it to NULL.
-
- /* No commands defined */
- int foo_command(struct i2c_client *client, unsigned int cmd, void *arg)
- {
- return 0;
- }
+need this, and its use is deprecated anyway, so newer design should not
+use it. Set it to NULL.
Sending and receiving
diff --git a/Documentation/i2o/ioctl b/Documentation/i2o/ioctl
index 3e174978997d..1e77fac4e120 100644
--- a/Documentation/i2o/ioctl
+++ b/Documentation/i2o/ioctl
@@ -185,7 +185,7 @@ VII. Getting Parameters
ENOMEM Kernel memory allocation error
A return value of 0 does not mean that the value was actually
- properly retreived. The user should check the result list
+ properly retrieved. The user should check the result list
to determine the specific status of the transaction.
VIII. Downloading Software
diff --git a/Documentation/input/appletouch.txt b/Documentation/input/appletouch.txt
index b48d11d0326d..4f7c633a76d2 100644
--- a/Documentation/input/appletouch.txt
+++ b/Documentation/input/appletouch.txt
@@ -3,7 +3,7 @@ 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.
+February 2005 and October 2005 Apple Aluminium Powerbooks.
This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
been improved in some areas:
@@ -13,7 +13,8 @@ been improved in some areas:
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.
+information about the inner workings of the touchpad sensors. Michael
+Hanselmann added support for the October 2005 models.
Usage:
------
diff --git a/Documentation/input/ff.txt b/Documentation/input/ff.txt
index efa7dd6751f3..c7e10eaff203 100644
--- a/Documentation/input/ff.txt
+++ b/Documentation/input/ff.txt
@@ -120,7 +120,7 @@ to the unique id assigned by the driver. This data is required for performing
some operations (removing an effect, controlling the playback).
This if field must be set to -1 by the user in order to tell the driver to
allocate a new effect.
-See <linux/input.h> for a description of the ff_effect stuct. You should also
+See <linux/input.h> for a description of the ff_effect struct. You should also
find help in a few sketches, contained in files shape.fig and interactive.fig.
You need xfig to visualize these files.
diff --git a/Documentation/ioctl/hdio.txt b/Documentation/ioctl/hdio.txt
index 9a7aea0636a5..11c9be49f37c 100644
--- a/Documentation/ioctl/hdio.txt
+++ b/Documentation/ioctl/hdio.txt
@@ -946,7 +946,7 @@ HDIO_SCAN_HWIF register and (re)scan interface
This ioctl initializes the addresses and irq for a disk
controller, probes for drives, and creates /proc/ide
- interfaces as appropiate.
+ interfaces as appropriate.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index d802ce88bedc..443230b43e09 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1033,9 +1033,9 @@ When kbuild executes the following steps are followed (roughly):
Example:
#arch/i386/Makefile
- GCC_VERSION := $(call cc-version)
cflags-y += $(shell \
- if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+ if [ $(call cc-version) -ge 0300 ] ; then \
+ echo "-mregparm=3"; fi ;)
In the above example -mregparm=3 is only used for gcc version greater
than or equal to gcc 3.0.
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index c91caf7eb303..7e77f93634ea 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -18,6 +18,7 @@ In this document you will find information about:
=== 5. Include files
--- 5.1 How to include files from the kernel include dir
--- 5.2 External modules using an include/ dir
+ --- 5.3 External modules using several directories
=== 6. Module installation
--- 6.1 INSTALL_MOD_PATH
--- 6.2 INSTALL_MOD_DIR
@@ -38,7 +39,7 @@ included in the kernel tree.
What is covered within this file is mainly information to authors
of modules. The author of an external modules should supply
a makefile that hides most of the complexity so one only has to type
-'make' to buld the module. A complete example will be present in
+'make' to build the module. A complete example will be present in
chapter ¤. Creating a kbuild file for an external module".
@@ -69,7 +70,7 @@ when building an external module.
--- 2.2 Available targets
- $KDIR refers to path to kernel source top-level directory
+ $KDIR refers to the path to the kernel source top-level directory
make -C $KDIR M=`pwd`
Will build the module(s) located in current directory.
@@ -87,11 +88,11 @@ when building an external module.
make -C $KDIR M=$PWD modules_install
Install the external module(s).
Installation default is in /lib/modules/<kernel-version>/extra,
- but may be prefixed with INSTALL_MOD_PATH - see separate chater.
+ but may be prefixed with INSTALL_MOD_PATH - see separate chapter.
make -C $KDIR M=$PWD clean
Remove all generated files for the module - the kernel
- source directory is not moddified.
+ source directory is not modified.
make -C $KDIR M=`pwd` help
help will list the available target when building external
@@ -99,7 +100,7 @@ when building an external module.
--- 2.3 Available options:
- $KDIR refer to path to kernel src
+ $KDIR refers to the path to the kernel source top-level directory
make -C $KDIR
Used to specify where to find the kernel source.
@@ -206,11 +207,11 @@ following files:
KERNELDIR := /lib/modules/`uname -r`/build
all::
- $(MAKE) -C $KERNELDIR M=`pwd` $@
+ $(MAKE) -C $(KERNELDIR) M=`pwd` $@
# Module specific targets
genbin:
- echo "X" > 8123_bini.o_shipped
+ echo "X" > 8123_bin.o_shipped
endif
@@ -341,13 +342,52 @@ directory and therefore needs to deal with this in their kbuild file.
EXTRA_CFLAGS := -Iinclude
8123-y := 8123_if.o 8123_pci.o 8123_bin.o
- Note that in the assingment there is no space between -I and the path.
- This is a kbuild limitation and no space must be present.
-
+ Note that in the assignment there is no space between -I and the path.
+ This is a kbuild limitation: there must be no space present.
+
+--- 5.3 External modules using several directories
+
+ If an external module does not follow the usual kernel style but
+ decide to spread files over several directories then kbuild can
+ support this too.
+
+ Consider the following example:
+
+ |
+ +- src/complex_main.c
+ | +- hal/hardwareif.c
+ | +- hal/include/hardwareif.h
+ +- include/complex.h
+
+ To build a single module named complex.ko we then need the following
+ kbuild file:
+
+ Kbuild:
+ obj-m := complex.o
+ complex-y := src/complex_main.o
+ complex-y += src/hal/hardwareif.o
+
+ EXTRA_CFLAGS := -I$(src)/include
+ EXTRA_CFLAGS += -I$(src)src/hal/include
+
+
+ kbuild knows how to handle .o files located in another directory -
+ although this is NOT reccommended practice. The syntax is to specify
+ the directory relative to the directory where the Kbuild file is
+ located.
+
+ To find the .h files we have to explicitly tell kbuild where to look
+ for the .h files. When kbuild executes current directory is always
+ the root of the kernel tree (argument to -C) and therefore we have to
+ tell kbuild how to find the .h files using absolute paths.
+ $(src) will specify the absolute path to the directory where the
+ Kbuild file are located when being build as an external module.
+ Therefore -I$(src)/ is used to point out the directory of the Kbuild
+ file and any additional path are just appended.
=== 6. Module installation
-Modules which are included in the kernel is installed in the directory:
+Modules which are included in the kernel are installed in the directory:
/lib/modules/$(KERNELRELEASE)/kernel
@@ -365,7 +405,7 @@ External modules are installed in the directory:
=> Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel
INSTALL_MOD_PATH may be set as an ordinary shell variable or as in the
- example above be specified on the commandline when calling make.
+ example above be specified on the command line when calling make.
INSTALL_MOD_PATH has effect both when installing modules included in
the kernel as well as when installing external modules.
@@ -384,7 +424,7 @@ External modules are installed in the directory:
=== 7. Module versioning
-Module versioning are enabled by the CONFIG_MODVERSIONS tag.
+Module versioning is enabled by the CONFIG_MODVERSIONS tag.
Module versioning is used as a simple ABI consistency check. The Module
versioning creates a CRC value of the full prototype for an exported symbol and
diff --git a/Documentation/kdump/gdbmacros.txt b/Documentation/kdump/gdbmacros.txt
index bc1b9eb92ae1..dcf5580380ab 100644
--- a/Documentation/kdump/gdbmacros.txt
+++ b/Documentation/kdump/gdbmacros.txt
@@ -177,3 +177,25 @@ document trapinfo
'trapinfo <pid>' will tell you by which trap & possibly
addresthe kernel paniced.
end
+
+
+define dmesg
+ set $i = 0
+ set $end_idx = (log_end - 1) & (log_buf_len - 1)
+
+ while ($i < logged_chars)
+ set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1)
+
+ if ($idx + 100 <= $end_idx) || \
+ ($end_idx <= $idx && $idx + 100 < log_buf_len)
+ printf "%.100s", &log_buf[$idx]
+ set $i = $i + 100
+ else
+ printf "%c", log_buf[$idx]
+ set $i = $i + 1
+ end
+ end
+end
+document dmesg
+ print the kernel ring buffer
+end
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 5f08f9ce6046..212cf3c21abf 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -4,10 +4,10 @@ Documentation for kdump - the kexec-based crash dumping solution
DESIGN
======
-Kdump uses kexec to reboot to a second kernel whenever a dump needs to be taken.
-This second kernel is booted with very little memory. The first kernel reserves
-the section of memory that the second kernel uses. This ensures that on-going
-DMA from the first kernel does not corrupt the second kernel.
+Kdump uses kexec to reboot to a second kernel whenever a dump needs to be
+taken. This second kernel is booted with very little memory. The first kernel
+reserves the section of memory that the second kernel uses. This ensures that
+on-going DMA from the first kernel does not corrupt the second kernel.
All the necessary information about Core image is encoded in ELF format and
stored in reserved area of memory before crash. Physical address of start of
@@ -35,77 +35,82 @@ In the second kernel, "old memory" can be accessed in two ways.
SETUP
=====
-1) Download http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
- and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
- and after that build the source.
+1) Download the upstream kexec-tools userspace package from
+ http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz.
-2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernel.
+ Apply the latest consolidated kdump patch on top of kexec-tools-1.101
+ from http://lse.sourceforge.net/kdump/. This arrangment has been made
+ till all the userspace patches supporting kdump are integrated with
+ upstream kexec-tools userspace.
+2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernels.
Two kernels need to be built in order to get this feature working.
+ Following are the steps to properly configure the two kernels specific
+ to kexec and kdump features:
- A) First kernel:
+ A) First kernel or regular kernel:
+ ----------------------------------
a) Enable "kexec system call" feature (in Processor type and features).
- CONFIG_KEXEC=y
- b) This kernel's physical load address should be the default value of
- 0x100000 (0x100000, 1 MB) (in Processor type and features).
- CONFIG_PHYSICAL_START=0x100000
- c) Enable "sysfs file system support" (in Pseudo filesystems).
- CONFIG_SYSFS=y
+ CONFIG_KEXEC=y
+ b) Enable "sysfs file system support" (in Pseudo filesystems).
+ CONFIG_SYSFS=y
+ c) make
d) Boot into first kernel with the command line parameter "crashkernel=Y@X".
Use appropriate values for X and Y. Y denotes how much memory to reserve
- for the second kernel, and X denotes at what physical address the reserved
- memory section starts. For example: "crashkernel=64M@16M".
-
- B) Second kernel:
- a) Enable "kernel crash dumps" feature (in Processor type and features).
- CONFIG_CRASH_DUMP=y
- b) Specify a suitable value for "Physical address where the kernel is
- loaded" (in Processor type and features). Typically this value
- should be same as X (See option d) above, e.g., 16 MB or 0x1000000.
- CONFIG_PHYSICAL_START=0x1000000
- 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
- e) Enable "Local APIC support on uniprocessors".
- CONFIG_X86_UP_APIC=y
- f) Enable "IO-APIC support on uniprocessors"
- CONFIG_X86_UP_IOAPIC=y
-
- Note: i) Options a) and b) depend upon "Configure standard kernel features
- (for small systems)" (under General setup).
- ii) Option a) also depends on CONFIG_HIGHMEM (under Processor
- type and features).
- iii) Both option a) and b) are under "Processor type and features".
-
-3) Boot into the first kernel. You are now ready to try out kexec-based crash
- dumps.
-
-4) Load the second kernel to be booted using:
+ for the second kernel, and X denotes at what physical address the
+ reserved memory section starts. For example: "crashkernel=64M@16M".
+
+
+ B) Second kernel or dump capture kernel:
+ ---------------------------------------
+ a) For i386 architecture enable Highmem support
+ CONFIG_HIGHMEM=y
+ b) Enable "kernel crash dumps" feature (under "Processor type and features")
+ CONFIG_CRASH_DUMP=y
+ c) Make sure a suitable value for "Physical address where the kernel is
+ loaded" (under "Processor type and features"). By default this value
+ is 0x1000000 (16MB) and it should be same as X (See option d above),
+ e.g., 16 MB or 0x1000000.
+ CONFIG_PHYSICAL_START=0x1000000
+ d) Enable "/proc/vmcore support" (Optional, under "Pseudo filesystems").
+ CONFIG_PROC_VMCORE=y
+
+3) After booting to regular kernel or first kernel, load the second kernel
+ using the following command:
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 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
- dump for testing purposes.
-
-6) Write out the dump file using
+ --append="root=<root-dev> init 1 irqpoll maxcpus=1"
+
+ Notes:
+ ======
+ i) <second-kernel> has to be a vmlinux image ie uncompressed elf image.
+ bzImage will not work, as of now.
+ ii) --args-linux has to be speicfied as if kexec it loading an elf image,
+ it needs to know that the arguments supplied are of linux type.
+ iii) By default ELF headers are stored in ELF64 format to support systems
+ with more than 4GB memory. Option --elf32-core-headers forces generation
+ of ELF32 headers. The reason for this option being, as of now gdb can
+ not open vmcore file with ELF64 headers on a 32 bit systems. So ELF32
+ headers can be used if one has non-PAE systems and hence memory less
+ than 4GB.
+ iv) Specify "irqpoll" as command line parameter. This reduces driver
+ initialization failures in second kernel due to shared interrupts.
+ v) <root-dev> needs to be specified in a format corresponding to the root
+ device name in the output of mount command.
+ vi) If you have built the drivers required to mount root file system as
+ modules in <second-kernel>, then, specify
+ --initrd=<initrd-for-second-kernel>.
+ vii) Specify maxcpus=1 as, if during first kernel run, if panic happens on
+ non-boot cpus, second kernel doesn't seem to be boot up all the cpus.
+ The other option is to always built the second kernel without SMP
+ support ie CONFIG_SMP=n
+
+4) After successfully loading the second kernel as above, if a panic occurs
+ system reboots into the second kernel. A module can be written to force
+ the panic or "ALT-SysRq-c" can be used initiate a crash dump for testing
+ purposes.
+
+5) Once the second kernel has booted, write out the dump file using
cp /proc/vmcore <dump-file>
@@ -119,9 +124,9 @@ SETUP
Entire memory: dd if=/dev/oldmem of=oldmem.001
+
ANALYSIS
========
-
Limited analysis can be done using gdb on the dump file copied out of
/proc/vmcore. Use vmlinux built with -g and run
@@ -132,15 +137,19 @@ work fine.
Note: gdb cannot analyse core files generated in ELF64 format for i386.
+Latest "crash" (crash-4.0-2.18) as available on Dave Anderson's site
+http://people.redhat.com/~anderson/ works well with kdump format.
+
+
TODO
====
-
1) Provide a kernel pages filtering mechanism so that core file size is not
insane on systems having huge memory banks.
-2) Modify "crash" tool to make it recognize this dump.
+2) Relocatable kernel can help in maintaining multiple kernels for crashdump
+ and same kernel as the first kernel can be used to capture the dump.
+
CONTACT
=======
-
Vivek Goyal (vgoyal@in.ibm.com)
Maneesh Soni (maneesh@in.ibm.com)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 5dffcfefc3c7..1cbcf65b764b 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -471,14 +471,15 @@ running once the system is up.
arch/i386/kernel/cpu/cpufreq/elanfreq.c.
elevator= [IOSCHED]
- Format: {"as" | "cfq" | "deadline" | "noop"}
+ Format: {"anticipatory" | "cfq" | "deadline" | "noop"}
See Documentation/block/as-iosched.txt and
Documentation/block/deadline-iosched.txt for details.
- elfcorehdr= [IA-32]
+ elfcorehdr= [IA-32, X86_64]
Specifies physical address of start of kernel core
- image elf header.
- See Documentation/kdump.txt for details.
+ image elf header. Generally kexec loader will
+ pass this option to capture kernel.
+ See Documentation/kdump/kdump.txt for details.
enforcing [SELINUX] Set initial enforcing status.
Format: {"0" | "1"}
@@ -633,6 +634,14 @@ running once the system is up.
inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
Format: <irq>
+ combined_mode= [HW] control which driver uses IDE ports in combined
+ mode: legacy IDE driver, libata, or both
+ (in the libata case, libata.atapi_enabled=1 may be
+ useful as well). Note that using the ide or libata
+ options may affect your device naming (e.g. by
+ changing hdc to sdb).
+ Format: combined (default), ide, or libata
+
inttest= [IA64]
io7= [HW] IO7 for Marvel based alpha systems
@@ -703,9 +712,17 @@ running once the system is up.
load_ramdisk= [RAM] List of ramdisks to load from floppy
See Documentation/ramdisk.txt.
- lockd.udpport= [NFS]
+ lockd.nlm_grace_period=P [NFS] Assign grace period.
+ Format: <integer>
+
+ lockd.nlm_tcpport=N [NFS] Assign TCP port.
+ Format: <integer>
+
+ lockd.nlm_timeout=T [NFS] Assign timeout value.
+ Format: <integer>
- lockd.tcpport= [NFS]
+ lockd.nlm_udpport=M [NFS] Assign UDP port.
+ Format: <integer>
logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver
Format: <irq>
@@ -824,7 +841,7 @@ running once the system is up.
mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel
memory.
- memmap=exactmap [KNL,IA-32] Enable setting of an exact
+ memmap=exactmap [KNL,IA-32,X86_64] Enable setting of an exact
E820 memory map, as specified by the user.
Such memmap=exactmap lines can be constructed based on
BIOS output or other requirements. See the memmap=nn@ss
@@ -847,6 +864,49 @@ running once the system is up.
mga= [HW,DRM]
+ migration_cost=
+ [KNL,SMP] debug: override scheduler migration costs
+ Format: <level-1-usecs>,<level-2-usecs>,...
+ This debugging option can be used to override the
+ default scheduler migration cost matrix. The numbers
+ are indexed by 'CPU domain distance'.
+ E.g. migration_cost=1000,2000,3000 on an SMT NUMA
+ box will set up an intra-core migration cost of
+ 1 msec, an inter-core migration cost of 2 msecs,
+ and an inter-node migration cost of 3 msecs.
+
+ WARNING: using the wrong values here can break
+ scheduler performance, so it's only for scheduler
+ development purposes, not production environments.
+
+ migration_debug=
+ [KNL,SMP] migration cost auto-detect verbosity
+ Format=<0|1|2>
+ If a system's migration matrix reported at bootup
+ seems erroneous then this option can be used to
+ increase verbosity of the detection process.
+ We default to 0 (no extra messages), 1 will print
+ some more information, and 2 will be really
+ verbose (probably only useful if you also have a
+ serial console attached to the system).
+
+ migration_factor=
+ [KNL,SMP] multiply/divide migration costs by a factor
+ Format=<percent>
+ This debug option can be used to proportionally
+ increase or decrease the auto-detected migration
+ costs for all entries of the migration matrix.
+ E.g. migration_factor=150 will increase migration
+ costs by 50%. (and thus the scheduler will be less
+ eager migrating cache-hot tasks)
+ migration_factor=80 will decrease migration costs
+ by 20%. (thus the scheduler will be more eager to
+ migrate tasks)
+
+ WARNING: using the wrong values here can break
+ scheduler performance, so it's only for scheduler
+ development purposes, not production environments.
+
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
@@ -902,6 +962,14 @@ running once the system is up.
nfsroot= [NFS] nfs root filesystem for disk-less boxes.
See Documentation/nfsroot.txt.
+ nfs.callback_tcpport=
+ [NFS] set the TCP port on which the NFSv4 callback
+ channel should listen.
+
+ nfs.idmap_cache_timeout=
+ [NFS] set the maximum lifetime for idmapper cache
+ entries.
+
nmi_watchdog= [KNL,BUGS=IA-32] Debugging features for SMP kernels
no387 [BUGS=IA-32] Tells the kernel to use the 387 maths
@@ -982,6 +1050,8 @@ running once the system is up.
nowb [ARM]
+ nr_uarts= [SERIAL] maximum number of UARTs to be registered.
+
opl3= [HW,OSS]
Format: <io>
@@ -1160,6 +1230,10 @@ running once the system is up.
Limit processor to maximum C-state
max_cstate=9 overrides any DMI blacklist limit.
+ processor.nocst [HW,ACPI]
+ Ignore the _CST method to determine C-states,
+ instead using the legacy FADT method
+
prompt_ramdisk= [RAM] List of RAM disks to prompt for floppy disk
before loading.
See Documentation/ramdisk.txt.
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 5f2b9c5edbb5..22488d791168 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -56,10 +56,12 @@ A request proceeds in the following manner:
(4) request_key() then forks and executes /sbin/request-key with a new session
keyring that contains a link to auth key V.
- (5) /sbin/request-key execs an appropriate program to perform the actual
+ (5) /sbin/request-key assumes the authority associated with key U.
+
+ (6) /sbin/request-key execs an appropriate program to perform the actual
instantiation.
- (6) The program may want to access another key from A's context (say a
+ (7) The program may want to access another key from A's context (say a
Kerberos TGT key). It just requests the appropriate key, and the keyring
search notes that the session keyring has auth key V in its bottom level.
@@ -67,19 +69,19 @@ A request proceeds in the following manner:
UID, GID, groups and security info of process A as if it was process A,
and come up with key W.
- (7) The program then does what it must to get the data with which to
+ (8) The program then does what it must to get the data with which to
instantiate key U, using key W as a reference (perhaps it contacts a
Kerberos server using the TGT) and then instantiates key U.
- (8) Upon instantiating key U, auth key V is automatically revoked so that it
+ (9) Upon instantiating key U, auth key V is automatically revoked so that it
may not be used again.
- (9) The program then exits 0 and request_key() deletes key V and returns key
+(10) The program then exits 0 and request_key() deletes key V and returns key
U to the caller.
-This also extends further. If key W (step 5 above) didn't exist, key W would be
-created uninstantiated, another auth key (X) would be created [as per step 3]
-and another copy of /sbin/request-key spawned [as per step 4]; but the context
+This also extends further. If key W (step 7 above) didn't exist, key W would be
+created uninstantiated, another auth key (X) would be created (as per step 3)
+and another copy of /sbin/request-key spawned (as per step 4); but the context
specified by auth key X will still be process A, as it was in auth key V.
This is because process A's keyrings can't simply be attached to
@@ -138,8 +140,8 @@ until one succeeds:
(3) The process's session keyring is searched.
- (4) If the process has a request_key() authorisation key in its session
- keyring then:
+ (4) If the process has assumed the authority associated with a request_key()
+ authorisation key then:
(a) If extant, the calling process's thread keyring is searched.
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 31154882000a..aaa01b0e3ee9 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -308,6 +308,8 @@ process making the call:
KEY_SPEC_USER_KEYRING -4 UID-specific keyring
KEY_SPEC_USER_SESSION_KEYRING -5 UID-session keyring
KEY_SPEC_GROUP_KEYRING -6 GID-specific keyring
+ KEY_SPEC_REQKEY_AUTH_KEY -7 assumed request_key()
+ authorisation key
The main syscalls are:
@@ -498,7 +500,11 @@ The keyctl syscall functions are:
keyring is full, error ENFILE will result.
The link procedure checks the nesting of the keyrings, returning ELOOP if
- it appears to deep or EDEADLK if the link would introduce a cycle.
+ it appears too deep or EDEADLK if the link would introduce a cycle.
+
+ Any links within the keyring to keys that match the new key in terms of
+ type and description will be discarded from the keyring as the new one is
+ added.
(*) Unlink a key or keyring from another keyring:
@@ -628,6 +634,41 @@ The keyctl syscall functions are:
there is one, otherwise the user default session keyring.
+ (*) Set the timeout on a key.
+
+ long keyctl(KEYCTL_SET_TIMEOUT, key_serial_t key, unsigned timeout);
+
+ This sets or clears the timeout on a key. The timeout can be 0 to clear
+ the timeout or a number of seconds to set the expiry time that far into
+ the future.
+
+ The process must have attribute modification access on a key to set its
+ timeout. Timeouts may not be set with this function on negative, revoked
+ or expired keys.
+
+
+ (*) Assume the authority granted to instantiate a key
+
+ long keyctl(KEYCTL_ASSUME_AUTHORITY, key_serial_t key);
+
+ This assumes or divests the authority required to instantiate the
+ specified key. Authority can only be assumed if the thread has the
+ authorisation key associated with the specified key in its keyrings
+ somewhere.
+
+ Once authority is assumed, searches for keys will also search the
+ requester's keyrings using the requester's security label, UID, GID and
+ groups.
+
+ If the requested authority is unavailable, error EPERM will be returned,
+ likewise if the authority has been revoked because the target key is
+ already instantiated.
+
+ If the specified key is 0, then any assumed authority will be divested.
+
+ The assumed authorititive key is inherited across fork and exec.
+
+
===============
KERNEL SERVICES
===============
@@ -860,24 +901,6 @@ The structure has a number of fields, some of which are mandatory:
It is safe to sleep in this method.
- (*) int (*duplicate)(struct key *key, const struct key *source);
-
- If this type of key can be duplicated, then this method should be
- provided. It is called to copy the payload attached to the source into the
- new key. The data length on the new key will have been updated and the
- quota adjusted already.
-
- This method will be called with the source key's semaphore read-locked to
- prevent its payload from being changed, thus RCU constraints need not be
- applied to the source key.
-
- This method does not have to lock the destination key in order to attach a
- payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
- prevents anything else from gaining access to the key.
-
- It is safe to sleep in this method.
-
-
(*) int (*update)(struct key *key, const void *data, size_t datalen);
If this type of key can be updated, then this method should be provided.
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 0541fe1de704..0ea5a0c6e827 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -411,7 +411,8 @@ int init_module(void)
printk("Couldn't find %s to plant kprobe\n", "do_fork");
return -1;
}
- if ((ret = register_kprobe(&kp) < 0)) {
+ ret = register_kprobe(&kp);
+ if (ret < 0) {
printk("register_kprobe failed, returned %d\n", ret);
return -1;
}
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index dc4e810afdcd..b18e21675906 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -3,7 +3,7 @@ How to conserve battery power using laptop-mode
Document Author: Bart Samwel (bart@samwel.tk)
Date created: January 2, 2004
-Last modified: July 10, 2004
+Last modified: December 06, 2004
Introduction
------------
@@ -33,7 +33,7 @@ or anything. Simply install all the files included in this document, and
laptop mode will automatically be started when you're on battery. For
your convenience, a tarball containing an installer can be downloaded at:
-http://www.xs4all.nl/~bsamwel/laptop_mode/tools
+http://www.xs4all.nl/~bsamwel/laptop_mode/tools/
To configure laptop mode, you need to edit the configuration file, which is
located in /etc/default/laptop-mode on Debian-based systems, or in
@@ -357,7 +357,7 @@ MAX_AGE=${MAX_AGE:-'600'}
# Read-ahead, in kilobytes
READAHEAD=${READAHEAD:-'4096'}
-# Shall we remount journaled fs. with appropiate commit interval? (1=yes)
+# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
DO_REMOUNTS=${DO_REMOUNTS:-'1'}
# And shall we add the "noatime" option to that as well? (1=yes)
@@ -912,7 +912,7 @@ void usage()
exit(0);
}
-int main(int ac, char **av)
+int main(int argc, char **argv)
{
int fd;
char *disk = 0;
diff --git a/Documentation/locks.txt b/Documentation/locks.txt
index ce1be79edfb8..e3b402ef33bd 100644
--- a/Documentation/locks.txt
+++ b/Documentation/locks.txt
@@ -65,20 +65,3 @@ The default is to disallow mandatory locking. The intention is that
mandatory locking only be enabled on a local filesystem as the specific need
arises.
-Until an updated version of mount(8) becomes available you may have to apply
-this patch to the mount sources (based on the version distributed with Rick
-Faith's util-linux-2.5 package):
-
-*** mount.c.orig Sat Jun 8 09:14:31 1996
---- mount.c Sat Jun 8 09:13:02 1996
-***************
-*** 100,105 ****
---- 100,107 ----
- { "noauto", 0, MS_NOAUTO }, /* Can only be mounted explicitly */
- { "user", 0, MS_USER }, /* Allow ordinary user to mount */
- { "nouser", 1, MS_USER }, /* Forbid ordinary user to mount */
-+ { "mand", 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
-+ { "nomand", 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
- /* add new options here */
- #ifdef MS_NOSUB
- { "sub", 1, MS_NOSUB }, /* allow submounts */
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 23e6cce40f9c..03a13c462cf2 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time.
The kernel parameter "raid=partitionable" (or "raid=part") means
that all auto-detected arrays are assembled as partitionable.
+Boot time assembly of degraded/dirty arrays
+-------------------------------------------
+
+If a raid5 or raid6 array is both dirty and degraded, it could have
+undetectable data corruption. This is because the fact that it is
+'dirty' means that the parity cannot be trusted, and the fact that it
+is degraded means that some datablocks are missing and cannot reliably
+be reconstructed (due to no parity).
+
+For this reason, md will normally refuse to start such an array. This
+requires the sysadmin to take action to explicitly start the array
+desipite possible corruption. This is normally done with
+ mdadm --assemble --force ....
+
+This option is not really available if the array has the root
+filesystem on it. In order to support this booting from such an
+array, md supports a module parameter "start_dirty_degraded" which,
+when set to 1, bypassed the checks and will allows dirty degraded
+arrays to be started.
+
+So, to boot with a root filesystem of a dirty degraded raid[56], use
+
+ md-mod.start_dirty_degraded=1
+
Superblock formats
------------------
@@ -141,6 +165,70 @@ All md devices contain:
in a fully functional array. If this is not yet known, the file
will be empty. If an array is being resized (not currently
possible) this will contain the larger of the old and new sizes.
+ Some raid level (RAID1) allow this value to be set while the
+ array is active. This will reconfigure the array. Otherwise
+ it can only be set while assembling an array.
+
+ chunk_size
+ This is the size if bytes for 'chunks' and is only relevant to
+ raid levels that involve striping (1,4,5,6,10). The address space
+ of the array is conceptually divided into chunks and consecutive
+ chunks are striped onto neighbouring devices.
+ The size should be atleast PAGE_SIZE (4k) and should be a power
+ of 2. This can only be set while assembling an array
+
+ component_size
+ For arrays with data redundancy (i.e. not raid0, linear, faulty,
+ multipath), all components must be the same size - or at least
+ there must a size that they all provide space for. This is a key
+ part or the geometry of the array. It is measured in sectors
+ and can be read from here. Writing to this value may resize
+ the array if the personality supports it (raid1, raid5, raid6),
+ and if the component drives are large enough.
+
+ metadata_version
+ This indicates the format that is being used to record metadata
+ about the array. It can be 0.90 (traditional format), 1.0, 1.1,
+ 1.2 (newer format in varying locations) or "none" indicating that
+ the kernel isn't managing metadata at all.
+
+ level
+ The raid 'level' for this array. The name will often (but not
+ always) be the same as the name of the module that implements the
+ level. To be auto-loaded the module must have an alias
+ md-$LEVEL e.g. md-raid5
+ This can be written only while the array is being assembled, not
+ after it is started.
+
+ new_dev
+ This file can be written but not read. The value written should
+ be a block device number as major:minor. e.g. 8:0
+ This will cause that device to be attached to the array, if it is
+ available. It will then appear at md/dev-XXX (depending on the
+ name of the device) and further configuration is then possible.
+
+ sync_speed_min
+ sync_speed_max
+ This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
+ however they only apply to the particular array.
+ If no value has been written to these, of if the word 'system'
+ is written, then the system-wide value is used. If a value,
+ in kibibytes-per-second is written, then it is used.
+ When the files are read, they show the currently active value
+ followed by "(local)" or "(system)" depending on whether it is
+ a locally set or system-wide value.
+
+ sync_completed
+ This shows the number of sectors that have been completed of
+ whatever the current sync_action is, followed by the number of
+ sectors in total that could need to be processed. The two
+ numbers are separated by a '/' thus effectively showing one
+ value, a fraction of the process that is complete.
+
+ sync_speed
+ This shows the current actual speed, in K/sec, of the current
+ sync_action. It is averaged over the last 30 seconds.
+
As component devices are added to an md array, they appear in the 'md'
directory as new directories named
@@ -167,6 +255,38 @@ Each directory contains:
of being recoverred to
This list make grow in future.
+ errors
+ An approximate count of read errors that have been detected on
+ this device but have not caused the device to be evicted from
+ the array (either because they were corrected or because they
+ happened while the array was read-only). When using version-1
+ metadata, this value persists across restarts of the array.
+
+ This value can be written while assembling an array thus
+ providing an ongoing count for arrays with metadata managed by
+ userspace.
+
+ slot
+ This gives the role that the device has in the array. It will
+ either be 'none' if the device is not active in the array
+ (i.e. is a spare or has failed) or an integer less than the
+ 'raid_disks' number for the array indicating which possition
+ it currently fills. This can only be set while assembling an
+ array. A device for which this is set is assumed to be working.
+
+ offset
+ This gives the location in the device (in sectors from the
+ start) where data from the array will be stored. Any part of
+ the device before this offset us not touched, unless it is
+ used for storing metadata (Formats 1.1 and 1.2).
+
+ size
+ The amount of the device, after the offset, that can be used
+ for storage of data. This will normally be the same as the
+ component_size. This can be written while assembling an
+ array. If a value less than the current component_size is
+ written, component_size will be reduced to this value.
+
An active md device will also contain and entry for each active device
in the array. These are named
diff --git a/Documentation/mutex-design.txt b/Documentation/mutex-design.txt
new file mode 100644
index 000000000000..cbf79881a41c
--- /dev/null
+++ b/Documentation/mutex-design.txt
@@ -0,0 +1,135 @@
+Generic Mutex Subsystem
+
+started by Ingo Molnar <mingo@redhat.com>
+
+ "Why on earth do we need a new mutex subsystem, and what's wrong
+ with semaphores?"
+
+firstly, there's nothing wrong with semaphores. But if the simpler
+mutex semantics are sufficient for your code, then there are a couple
+of advantages of mutexes:
+
+ - 'struct mutex' is smaller on most architectures: .e.g on x86,
+ 'struct semaphore' is 20 bytes, 'struct mutex' is 16 bytes.
+ A smaller structure size means less RAM footprint, and better
+ CPU-cache utilization.
+
+ - tighter code. On x86 i get the following .text sizes when
+ switching all mutex-alike semaphores in the kernel to the mutex
+ subsystem:
+
+ text data bss dec hex filename
+ 3280380 868188 396860 4545428 455b94 vmlinux-semaphore
+ 3255329 865296 396732 4517357 44eded vmlinux-mutex
+
+ that's 25051 bytes of code saved, or a 0.76% win - off the hottest
+ codepaths of the kernel. (The .data savings are 2892 bytes, or 0.33%)
+ Smaller code means better icache footprint, which is one of the
+ major optimization goals in the Linux kernel currently.
+
+ - the mutex subsystem is slightly faster and has better scalability for
+ contended workloads. On an 8-way x86 system, running a mutex-based
+ kernel and testing creat+unlink+close (of separate, per-task files)
+ in /tmp with 16 parallel tasks, the average number of ops/sec is:
+
+ Semaphores: Mutexes:
+
+ $ ./test-mutex V 16 10 $ ./test-mutex V 16 10
+ 8 CPUs, running 16 tasks. 8 CPUs, running 16 tasks.
+ checking VFS performance. checking VFS performance.
+ avg loops/sec: 34713 avg loops/sec: 84153
+ CPU utilization: 63% CPU utilization: 22%
+
+ i.e. in this workload, the mutex based kernel was 2.4 times faster
+ than the semaphore based kernel, _and_ it also had 2.8 times less CPU
+ utilization. (In terms of 'ops per CPU cycle', the semaphore kernel
+ performed 551 ops/sec per 1% of CPU time used, while the mutex kernel
+ performed 3825 ops/sec per 1% of CPU time used - it was 6.9 times
+ more efficient.)
+
+ the scalability difference is visible even on a 2-way P4 HT box:
+
+ Semaphores: Mutexes:
+
+ $ ./test-mutex V 16 10 $ ./test-mutex V 16 10
+ 4 CPUs, running 16 tasks. 8 CPUs, running 16 tasks.
+ checking VFS performance. checking VFS performance.
+ avg loops/sec: 127659 avg loops/sec: 181082
+ CPU utilization: 100% CPU utilization: 34%
+
+ (the straight performance advantage of mutexes is 41%, the per-cycle
+ efficiency of mutexes is 4.1 times better.)
+
+ - there are no fastpath tradeoffs, the mutex fastpath is just as tight
+ as the semaphore fastpath. On x86, the locking fastpath is 2
+ instructions:
+
+ c0377ccb <mutex_lock>:
+ c0377ccb: f0 ff 08 lock decl (%eax)
+ c0377cce: 78 0e js c0377cde <.text.lock.mutex>
+ c0377cd0: c3 ret
+
+ the unlocking fastpath is equally tight:
+
+ c0377cd1 <mutex_unlock>:
+ c0377cd1: f0 ff 00 lock incl (%eax)
+ c0377cd4: 7e 0f jle c0377ce5 <.text.lock.mutex+0x7>
+ c0377cd6: c3 ret
+
+ - 'struct mutex' semantics are well-defined and are enforced if
+ CONFIG_DEBUG_MUTEXES is turned on. Semaphores on the other hand have
+ virtually no debugging code or instrumentation. The mutex subsystem
+ checks and enforces the following rules:
+
+ * - only one task can hold the mutex at a time
+ * - only the owner can unlock the mutex
+ * - multiple unlocks are not permitted
+ * - recursive locking is not permitted
+ * - a mutex object must be initialized via the API
+ * - a mutex object must not be initialized via memset or copying
+ * - task may not exit with mutex held
+ * - memory areas where held locks reside must not be freed
+ * - held mutexes must not be reinitialized
+ * - mutexes may not be used in irq contexts
+
+ furthermore, there are also convenience features in the debugging
+ code:
+
+ * - uses symbolic names of mutexes, whenever they are printed in debug output
+ * - point-of-acquire tracking, symbolic lookup of function names
+ * - list of all locks held in the system, printout of them
+ * - owner tracking
+ * - detects self-recursing locks and prints out all relevant info
+ * - detects multi-task circular deadlocks and prints out all affected
+ * locks and tasks (and only those tasks)
+
+Disadvantages
+-------------
+
+The stricter mutex API means you cannot use mutexes the same way you
+can use semaphores: e.g. they cannot be used from an interrupt context,
+nor can they be unlocked from a different context that which acquired
+it. [ I'm not aware of any other (e.g. performance) disadvantages from
+using mutexes at the moment, please let me know if you find any. ]
+
+Implementation of mutexes
+-------------------------
+
+'struct mutex' is the new mutex type, defined in include/linux/mutex.h
+and implemented in kernel/mutex.c. It is a counter-based mutex with a
+spinlock and a wait-list. The counter has 3 states: 1 for "unlocked",
+0 for "locked" and negative numbers (usually -1) for "locked, potential
+waiters queued".
+
+the APIs of 'struct mutex' have been streamlined:
+
+ DEFINE_MUTEX(name);
+
+ mutex_init(mutex);
+
+ void mutex_lock(struct mutex *lock);
+ int mutex_lock_interruptible(struct mutex *lock);
+ int mutex_trylock(struct mutex *lock);
+ void mutex_unlock(struct mutex *lock);
+ int mutex_is_locked(struct mutex *lock);
+
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index b0fe41da007b..8d8b4e5ea184 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -945,7 +945,6 @@ bond0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
collisions:0 txqueuelen:0
eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
- inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
RX packets:3573025 errors:0 dropped:0 overruns:0 frame:0
TX packets:1643167 errors:1 dropped:0 overruns:1 carrier:0
@@ -953,7 +952,6 @@ eth0 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
Interrupt:10 Base address:0x1080
eth1 Link encap:Ethernet HWaddr 00:C0:F0:1F:37:B4
- inet addr:XXX.XXX.XXX.YYY Bcast:XXX.XXX.XXX.255 Mask:255.255.252.0
UP BROADCAST RUNNING SLAVE MULTICAST MTU:1500 Metric:1
RX packets:3651769 errors:0 dropped:0 overruns:0 frame:0
TX packets:1643480 errors:0 dropped:0 overruns:0 carrier:0
diff --git a/Documentation/networking/gianfar.txt b/Documentation/networking/gianfar.txt
new file mode 100644
index 000000000000..ad474ea07d07
--- /dev/null
+++ b/Documentation/networking/gianfar.txt
@@ -0,0 +1,72 @@
+The Gianfar Ethernet Driver
+Sysfs File description
+
+Author: Andy Fleming <afleming@freescale.com>
+Updated: 2005-07-28
+
+SYSFS
+
+Several of the features of the gianfar driver are controlled
+through sysfs files. These are:
+
+bd_stash:
+To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
+bd_stash, echo 'off' or '0' to disable
+
+rx_stash_len:
+To stash the first n bytes of the packet in L2, echo the number
+of bytes to buf_stash_len. echo 0 to disable.
+
+WARNING: You could really screw these up if you set them too low or high!
+fifo_threshold:
+To change the number of bytes the controller needs in the
+fifo before it starts transmission, echo the number of bytes to
+fifo_thresh. Range should be 0-511.
+
+fifo_starve:
+When the FIFO has less than this many bytes during a transmit, it
+enters starve mode, and increases the priority of TX memory
+transactions. To change, echo the number of bytes to
+fifo_starve. Range should be 0-511.
+
+fifo_starve_off:
+Once in starve mode, the FIFO remains there until it has this
+many bytes. To change, echo the number of bytes to
+fifo_starve_off. Range should be 0-511.
+
+CHECKSUM OFFLOADING
+
+The eTSEC controller (first included in parts from late 2005 like
+the 8548) has the ability to perform TCP, UDP, and IP checksums
+in hardware. The Linux kernel only offloads the TCP and UDP
+checksums (and always performs the pseudo header checksums), so
+the driver only supports checksumming for TCP/IP and UDP/IP
+packets. Use ethtool to enable or disable this feature for RX
+and TX.
+
+VLAN
+
+In order to use VLAN, please consult Linux documentation on
+configuring VLANs. The gianfar driver supports hardware insertion and
+extraction of VLAN headers, but not filtering. Filtering will be
+done by the kernel.
+
+MULTICASTING
+
+The gianfar driver supports using the group hash table on the
+TSEC (and the extended hash table on the eTSEC) for multicast
+filtering. On the eTSEC, the exact-match MAC registers are used
+before the hash tables. See Linux documentation on how to join
+multicast groups.
+
+PADDING
+
+The gianfar driver supports padding received frames with 2 bytes
+to align the IP header to a 16-byte boundary, when supported by
+hardware.
+
+ETHTOOL
+
+The gianfar driver supports the use of ethtool for many
+configuration options. You must run ethtool only on currently
+open interfaces. See ethtool documentation for details.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ebc09a159f62..2b7cf19a06ad 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -46,6 +46,29 @@ ipfrag_secret_interval - INTEGER
for the hash secret) for IP fragments.
Default: 600
+ipfrag_max_dist - INTEGER
+ ipfrag_max_dist is a non-negative integer value which defines the
+ maximum "disorder" which is allowed among fragments which share a
+ common IP source address. Note that reordering of packets is
+ not unusual, but if a large number of fragments arrive from a source
+ IP address while a particular fragment queue remains incomplete, it
+ probably indicates that one or more fragments belonging to that queue
+ have been lost. When ipfrag_max_dist is positive, an additional check
+ is done on fragments before they are added to a reassembly queue - if
+ ipfrag_max_dist (or more) fragments have arrived from a particular IP
+ address between additions to any IP fragment queue using that source
+ address, it's presumed that one or more fragments in the queue are
+ lost. The existing fragment queue will be dropped, and a new one
+ started. An ipfrag_max_dist value of zero disables this check.
+
+ Using a very small value, e.g. 1 or 2, for ipfrag_max_dist can
+ result in unnecessarily dropping fragment queues when normal
+ reordering of packets occurs, which could lead to poor application
+ performance. Using a very large value, e.g. 50000, increases the
+ likelihood of incorrectly reassembling IP fragments that originate
+ from different IP datagrams, which could result in data corruption.
+ Default: 64
+
INET peer storage:
inet_peer_threshold - INTEGER
diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
index 851fc97bb22f..7837c53fd5fe 100644
--- a/Documentation/networking/sk98lin.txt
+++ b/Documentation/networking/sk98lin.txt
@@ -91,7 +91,7 @@ To use the driver as a module, proceed as follows:
with (M)
5. Execute the command "make modules".
6. Execute the command "make modules_install".
- The appropiate modules will be installed.
+ The appropriate modules will be installed.
7. Reboot your system.
@@ -245,7 +245,7 @@ Default: Both
This parameters is only relevant if auto-negotiation for this port is
not set to "Sense". If auto-negotiation is set to "On", all three values
are possible. If it is set to "Off", only "Full" and "Half" are allowed.
-This parameter is usefull if your link partner does not support all
+This parameter is useful if your link partner does not support all
possible combinations.
Flow Control
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 05960f8a748e..2503404ae5c2 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -41,11 +41,9 @@ the disk is not available then you have three options :-
run a null modem to a second machine and capture the output there
using your favourite communication program. Minicom works well.
-(3) Patch the kernel with one of the crash dump patches. These save
- data to a floppy disk or video rom or a swap partition. None of
- these are standard kernel patches so you have to find and apply
- them yourself. Search kernel archives for kmsgdump, lkcd and
- oops+smram.
+(3) Use Kdump (see Documentation/kdump/kdump.txt),
+ extract the kernel ring buffer from old memory with using dmesg
+ gdbmacro in Documentation/kdump/gdbmacros.txt.
Full Information
diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt
new file mode 100644
index 000000000000..d089967e4948
--- /dev/null
+++ b/Documentation/pci-error-recovery.txt
@@ -0,0 +1,246 @@
+
+ PCI Error Recovery
+ ------------------
+ May 31, 2005
+
+ Current document maintainer:
+ Linas Vepstas <linas@austin.ibm.com>
+
+
+Some PCI bus controllers are able to detect certain "hard" PCI errors
+on the bus, such as parity errors on the data and address busses, as
+well as SERR and PERR errors. These chipsets are then able to disable
+I/O to/from the affected device, so that, for example, a bad DMA
+address doesn't end up corrupting system memory. These same chipsets
+are also able to reset the affected PCI device, and return it to
+working condition. This document describes a generic API form
+performing error recovery.
+
+The core idea is that after a PCI error has been detected, there must
+be a way for the kernel to coordinate with all affected device drivers
+so that the pci card can be made operational again, possibly after
+performing a full electrical #RST of the PCI card. The API below
+provides a generic API for device drivers to be notified of PCI
+errors, and to be notified of, and respond to, a reset sequence.
+
+Preliminary sketch of API, cut-n-pasted-n-modified email from
+Ben Herrenschmidt, circa 5 april 2005
+
+The error recovery API support is exposed to the driver in the form of
+a structure of function pointers pointed to by a new field in struct
+pci_driver. The absence of this pointer in pci_driver denotes an
+"non-aware" driver, behaviour on these is platform dependant.
+Platforms like ppc64 can try to simulate pci hotplug remove/add.
+
+The definition of "pci_error_token" is not covered here. It is based on
+Seto's work on the synchronous error detection. We still need to define
+functions for extracting infos out of an opaque error token. This is
+separate from this API.
+
+This structure has the form:
+
+struct pci_error_handlers
+{
+ int (*error_detected)(struct pci_dev *dev, pci_error_token error);
+ int (*mmio_enabled)(struct pci_dev *dev);
+ int (*resume)(struct pci_dev *dev);
+ int (*link_reset)(struct pci_dev *dev);
+ int (*slot_reset)(struct pci_dev *dev);
+};
+
+A driver doesn't have to implement all of these callbacks. The
+only mandatory one is error_detected(). If a callback is not
+implemented, the corresponding feature is considered unsupported.
+For example, if mmio_enabled() and resume() aren't there, then the
+driver is assumed as not doing any direct recovery and requires
+a reset. If link_reset() is not implemented, the card is assumed as
+not caring about link resets, in which case, if recover is supported,
+the core can try recover (but not slot_reset() unless it really did
+reset the slot). If slot_reset() is not supported, link_reset() can
+be called instead on a slot reset.
+
+At first, the call will always be :
+
+ 1) error_detected()
+
+ Error detected. This is sent once after an error has been detected. At
+this point, the device might not be accessible anymore depending on the
+platform (the slot will be isolated on ppc64). The driver may already
+have "noticed" the error because of a failing IO, but this is the proper
+"synchronisation point", that is, it gives a chance to the driver to
+cleanup, waiting for pending stuff (timers, whatever, etc...) to
+complete; it can take semaphores, schedule, etc... everything but touch
+the device. Within this function and after it returns, the driver
+shouldn't do any new IOs. Called in task context. This is sort of a
+"quiesce" point. See note about interrupts at the end of this doc.
+
+ Result codes:
+ - PCIERR_RESULT_CAN_RECOVER:
+ Driever returns this if it thinks it might be able to recover
+ the HW by just banging IOs or if it wants to be given
+ a chance to extract some diagnostic informations (see
+ below).
+ - PCIERR_RESULT_NEED_RESET:
+ Driver returns this if it thinks it can't recover unless the
+ slot is reset.
+ - PCIERR_RESULT_DISCONNECT:
+ Return this if driver thinks it won't recover at all,
+ (this will detach the driver ? or just leave it
+ dangling ? to be decided)
+
+So at this point, we have called error_detected() for all drivers
+on the segment that had the error. On ppc64, the slot is isolated. What
+happens now typically depends on the result from the drivers. If all
+drivers on the segment/slot return PCIERR_RESULT_CAN_RECOVER, we would
+re-enable IOs on the slot (or do nothing special if the platform doesn't
+isolate slots) and call 2). If not and we can reset slots, we go to 4),
+if neither, we have a dead slot. If it's an hotplug slot, we might
+"simulate" reset by triggering HW unplug/replug though.
+
+>>> Current ppc64 implementation assumes that a device driver will
+>>> *not* schedule or semaphore in this routine; the current ppc64
+>>> implementation uses one kernel thread to notify all devices;
+>>> thus, of one device sleeps/schedules, all devices are affected.
+>>> Doing better requires complex multi-threaded logic in the error
+>>> recovery implementation (e.g. waiting for all notification threads
+>>> to "join" before proceeding with recovery.) This seems excessively
+>>> complex and not worth implementing.
+
+>>> The current ppc64 implementation doesn't much care if the device
+>>> attempts i/o at this point, or not. I/O's will fail, returning
+>>> a value of 0xff on read, and writes will be dropped. If the device
+>>> driver attempts more than 10K I/O's to a frozen adapter, it will
+>>> assume that the device driver has gone into an infinite loop, and
+>>> it will panic the the kernel.
+
+ 2) mmio_enabled()
+
+ This is the "early recovery" call. IOs are allowed again, but DMA is
+not (hrm... to be discussed, I prefer not), with some restrictions. This
+is NOT a callback for the driver to start operations again, only to
+peek/poke at the device, extract diagnostic information, if any, and
+eventually do things like trigger a device local reset or some such,
+but not restart operations. This is sent if all drivers on a segment
+agree that they can try to recover and no automatic link reset was
+performed by the HW. If the platform can't just re-enable IOs without
+a slot reset or a link reset, it doesn't call this callback and goes
+directly to 3) or 4). All IOs should be done _synchronously_ from
+within this callback, errors triggered by them will be returned via
+the normal pci_check_whatever() api, no new error_detected() callback
+will be issued due to an error happening here. However, such an error
+might cause IOs to be re-blocked for the whole segment, and thus
+invalidate the recovery that other devices on the same segment might
+have done, forcing the whole segment into one of the next states,
+that is link reset or slot reset.
+
+ Result codes:
+ - PCIERR_RESULT_RECOVERED
+ Driver returns this if it thinks the device is fully
+ functionnal and thinks it is ready to start
+ normal driver operations again. There is no
+ guarantee that the driver will actually be
+ allowed to proceed, as another driver on the
+ same segment might have failed and thus triggered a
+ slot reset on platforms that support it.
+
+ - PCIERR_RESULT_NEED_RESET
+ Driver returns this if it thinks the device is not
+ recoverable in it's current state and it needs a slot
+ reset to proceed.
+
+ - PCIERR_RESULT_DISCONNECT
+ Same as above. Total failure, no recovery even after
+ reset driver dead. (To be defined more precisely)
+
+>>> The current ppc64 implementation does not implement this callback.
+
+ 3) link_reset()
+
+ This is called after the link has been reset. This is typically
+a PCI Express specific state at this point and is done whenever a
+non-fatal error has been detected that can be "solved" by resetting
+the link. This call informs the driver of the reset and the driver
+should check if the device appears to be in working condition.
+This function acts a bit like 2) mmio_enabled(), in that the driver
+is not supposed to restart normal driver I/O operations right away.
+Instead, it should just "probe" the device to check it's recoverability
+status. If all is right, then the core will call resume() once all
+drivers have ack'd link_reset().
+
+ Result codes:
+ (identical to mmio_enabled)
+
+>>> The current ppc64 implementation does not implement this callback.
+
+ 4) slot_reset()
+
+ This is called after the slot has been soft or hard reset by the
+platform. A soft reset consists of asserting the adapter #RST line
+and then restoring the PCI BARs and PCI configuration header. If the
+platform supports PCI hotplug, then it might instead perform a hard
+reset by toggling power on the slot off/on. This call gives drivers
+the chance to re-initialize the hardware (re-download firmware, etc.),
+but drivers shouldn't restart normal I/O processing operations at
+this point. (See note about interrupts; interrupts aren't guaranteed
+to be delivered until the resume() callback has been called). If all
+device drivers report success on this callback, the patform will call
+resume() to complete the error handling and let the driver restart
+normal I/O processing.
+
+A driver can still return a critical failure for this function if
+it can't get the device operational after reset. If the platform
+previously tried a soft reset, it migh now try a hard reset (power
+cycle) and then call slot_reset() again. It the device still can't
+be recovered, there is nothing more that can be done; the platform
+will typically report a "permanent failure" in such a case. The
+device will be considered "dead" in this case.
+
+ Result codes:
+ - PCIERR_RESULT_DISCONNECT
+ Same as above.
+
+>>> The current ppc64 implementation does not try a power-cycle reset
+>>> if the driver returned PCIERR_RESULT_DISCONNECT. However, it should.
+
+ 5) resume()
+
+ This is called if all drivers on the segment have returned
+PCIERR_RESULT_RECOVERED from one of the 3 prevous callbacks.
+That basically tells the driver to restart activity, tht everything
+is back and running. No result code is taken into account here. If
+a new error happens, it will restart a new error handling process.
+
+That's it. I think this covers all the possibilities. The way those
+callbacks are called is platform policy. A platform with no slot reset
+capability for example may want to just "ignore" drivers that can't
+recover (disconnect them) and try to let other cards on the same segment
+recover. Keep in mind that in most real life cases, though, there will
+be only one driver per segment.
+
+Now, there is a note about interrupts. If you get an interrupt and your
+device is dead or has been isolated, there is a problem :)
+
+After much thinking, I decided to leave that to the platform. That is,
+the recovery API only precies that:
+
+ - There is no guarantee that interrupt delivery can proceed from any
+device on the segment starting from the error detection and until the
+restart callback is sent, at which point interrupts are expected to be
+fully operational.
+
+ - There is no guarantee that interrupt delivery is stopped, that is, ad
+river that gets an interrupts after detecting an error, or that detects
+and error within the interrupt handler such that it prevents proper
+ack'ing of the interrupt (and thus removal of the source) should just
+return IRQ_NOTHANDLED. It's up to the platform to deal with taht
+condition, typically by masking the irq source during the duration of
+the error handling. It is expected that the platform "knows" which
+interrupts are routed to error-management capable slots and can deal
+with temporarily disabling that irq number during error processing (this
+isn't terribly complex). That means some IRQ latency for other devices
+sharing the interrupt, but there is simply no other way. High end
+platforms aren't supposed to share interrupts between many devices
+anyway :)
+
+
+Revised: 31 May 2005 Linas Vepstas <linas@austin.ibm.com>
diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 403e7b4dcdd4..97420f08c786 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,5 +1,16 @@
This file details changes in 2.6 which affect PCMCIA card driver authors:
+* Unify detach and REMOVAL event code, as well as attach and INSERTION
+ code (as of 2.6.16)
+ void (*remove) (struct pcmcia_device *dev);
+ int (*probe) (struct pcmcia_device *dev);
+
+* Move suspend, resume and reset out of event handler (as of 2.6.16)
+ int (*suspend) (struct pcmcia_device *dev);
+ int (*resume) (struct pcmcia_device *dev);
+ should be initialized in struct pcmcia_driver, and handle
+ (SUSPEND == RESET_PHYSICAL) and (RESUME == CARD_RESET) events
+
* event handler initialization in struct pcmcia_driver (as of 2.6.13)
The event handler is notified of all events, and must be initialized
as the event() callback in the driver's struct pcmcia_driver.
diff --git a/Documentation/pm.txt b/Documentation/pm.txt
index 2ea1149bf6b0..79c0f32a760e 100644
--- a/Documentation/pm.txt
+++ b/Documentation/pm.txt
@@ -218,7 +218,7 @@ proceed in the opposite direction.
Q: Who do I contact for additional information about
enabling power management for my specific driver/device?
-ACPI Development mailing list: acpi-devel@lists.sourceforge.net
+ACPI Development mailing list: linux-acpi@vger.kernel.org
System Interface -- OBSOLETE, DO NOT USE!
----------------*************************
diff --git a/Documentation/power/interface.txt b/Documentation/power/interface.txt
index f5ebda5f4276..bd4ffb5bd49a 100644
--- a/Documentation/power/interface.txt
+++ b/Documentation/power/interface.txt
@@ -41,3 +41,14 @@ to. Writing to this file will accept one of
It will only change to 'firmware' or 'platform' if the system supports
it.
+/sys/power/image_size controls the size of the image created by
+the suspend-to-disk mechanism. It can be written a string
+representing a non-negative integer that will be used as an upper
+limit of the image size, in megabytes. The suspend-to-disk mechanism will
+do its best to ensure the image size will not exceed that number. However,
+if this turns out to be impossible, it will try to suspend anyway using the
+smallest image possible. In particular, if "0" is written to this file, the
+suspend image will be as small as possible.
+
+Reading from this file will display the current image size limit, which
+is set to 500 MB by default.
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index b0d50840788e..08c79d4dc540 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -27,6 +27,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
echo platform > /sys/power/disk; echo disk > /sys/power/state
+If you want to limit the suspend image size to N megabytes, do
+
+echo N > /sys/power/image_size
+
+before suspend (it is limited to 500 MB by default).
Encrypted suspend image:
------------------------
@@ -207,7 +212,7 @@ A: Try running
cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null
-after resume. swapoff -a; swapon -a may also be usefull.
+after resume. swapoff -a; swapon -a may also be useful.
Q: What happens to devices during swsusp? They seem to be resumed
during system suspend?
@@ -318,7 +323,7 @@ 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?
+Q: What information is useful 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
diff --git a/Documentation/powerpc/00-INDEX b/Documentation/powerpc/00-INDEX
index e7bea0a407b4..d6d65b9bcfe3 100644
--- a/Documentation/powerpc/00-INDEX
+++ b/Documentation/powerpc/00-INDEX
@@ -8,12 +8,18 @@ please mail me.
cpu_features.txt
- info on how we support a variety of CPUs with minimal compile-time
options.
+eeh-pci-error-recovery.txt
+ - info on PCI Bus EEH Error Recovery
+hvcs.txt
+ - IBM "Hypervisor Virtual Console Server" Installation Guide
+mpc52xx.txt
+ - Linux 2.6.x on MPC52xx family
ppc_htab.txt
- info about the Linux/PPC /proc/ppc_htab entry
-smp.txt
- - use and state info about Linux/PPC on MP machines
SBC8260_memory_mapping.txt
- EST SBC8260 board info
+smp.txt
+ - use and state info about Linux/PPC on MP machines
sound.txt
- info on sound support under Linux/PPC
zImage_layout.txt
diff --git a/Documentation/powerpc/eeh-pci-error-recovery.txt b/Documentation/powerpc/eeh-pci-error-recovery.txt
index e75d7474322c..67a11a36270c 100644
--- a/Documentation/powerpc/eeh-pci-error-recovery.txt
+++ b/Documentation/powerpc/eeh-pci-error-recovery.txt
@@ -115,7 +115,7 @@ Current PPC64 Linux EEH Implementation
At this time, a generic EEH recovery mechanism has been implemented,
so that individual device drivers do not need to be modified to support
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
-infrastructure, and percolates events up through the hotplug/udev
+infrastructure, and percolates events up through the userspace/udev
infrastructure. Followiing is a detailed description of how this is
accomplished.
@@ -172,7 +172,7 @@ A handler for the EEH notifier_block events is implemented in
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
This last call causes the device driver for the card to be stopped,
-which causes hotplug events to go out to user space. This triggers
+which causes uevents to go out to user space. This triggers
user-space scripts that might issue commands such as "ifdown eth0"
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
hoping to give the user-space scripts enough time to complete.
@@ -258,29 +258,30 @@ rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
calls
pci_destroy_dev (struct pci_dev *) {
calls
- device_unregister (&dev->dev) { // in /drivers/base/core.c
+ device_unregister (&dev->dev) { // in /drivers/base/core.c
calls
- device_del(struct device * dev) { // in /drivers/base/core.c
+ device_del(struct device * dev) { // in /drivers/base/core.c
calls
- kobject_del() { //in /libs/kobject.c
+ kobject_del() { //in /libs/kobject.c
calls
- kobject_hotplug() { // in /libs/kobject.c
+ kobject_uevent() { // in /libs/kobject.c
calls
- kset_hotplug() { // in /lib/kobject.c
+ kset_uevent() { // in /lib/kobject.c
calls
- kset->hotplug_ops->hotplug() which is really just
+ kset->uevent_ops->uevent() // which is really just
a call to
- dev_hotplug() { // in /drivers/base/core.c
+ dev_uevent() { // in /drivers/base/core.c
calls
- dev->bus->hotplug() which is really just a call to
- pci_hotplug () { // in drivers/pci/hotplug.c
+ dev->bus->uevent() which is really just a call to
+ pci_uevent () { // in drivers/pci/hotplug.c
which prints device name, etc....
}
}
- then kset_hotplug() calls
- call_usermodehelper () with
- argv[0]=hotplug_path[] which is "/sbin/hotplug"
- --> event to userspace,
+ then kobject_uevent() sends a netlink uevent to userspace
+ --> userspace uevent
+ (during early boot, nobody listens to netlink events and
+ kobject_uevent() executes uevent_helper[], which runs the
+ event process /sbin/hotplug)
}
}
kobject_del() then calls sysfs_remove_dir(), which would
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index 5331d91432c7..09f6300eda4b 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,38 @@
+Release Date : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
+Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
+
+1. Sorted out PCI IDs to remove megaraid support overlaps.
+ Based on the patch from Daniel, sorted out PCI IDs along with
+ charactor node name change from 'megadev' to 'megadev_legacy' to avoid
+ conflict.
+ ---
+ Hopefully we'll be getting the build restriction zapped much sooner,
+ but we should also be thinking about totally removing the hardware
+ support overlap in the megaraid drivers.
+
+ This patch pencils in a date of Feb 06 for this, and performs some
+ printk abuse in hope that existing legacy users might pick up on what's
+ going on.
+
+ Signed-off-by: Daniel Drake <dsd@gentoo.org>
+ ---
+
+2. Fixed a issue: megaraid always fails to reset handler.
+ ---
+ I found that the megaraid driver always fails to reset the
+ adapter with the following message:
+ megaraid: resetting the host...
+ megaraid mbox: reset sequence completed successfully
+ megaraid: fast sync command timed out
+ megaraid: reservation reset failed
+ when the "Cluster mode" of the adapter BIOS is enabled.
+ So, whenever the reset occurs, the adapter goes to
+ offline and just become unavailable.
+
+ Jun'ichi Nomura [mailto:jnomura@mtc.biglobe.ne.jp]
+ ---
+
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
new file mode 100644
index 000000000000..820fd0793502
--- /dev/null
+++ b/Documentation/scsi/aacraid.txt
@@ -0,0 +1,108 @@
+AACRAID Driver for Linux (take two)
+
+Introduction
+-------------------------
+The aacraid driver adds support for Adaptec (http://www.adaptec.com)
+RAID controllers. This is a major rewrite from the original
+Adaptec supplied driver. It has signficantly cleaned up both the code
+and the running binary size (the module is less than half the size of
+the original).
+
+Supported Cards/Chipsets
+-------------------------
+ PCI ID (pci.ids) OEM Product
+ 9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)
+ 9005:0285:9005:028e Adaptec 2020SA (Skyhawk)
+ 9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
+ 9005:0285:9005:028f Adaptec 2025SA (Terminator)
+ 9005:0285:9005:0286 Adaptec 2120S (Crusader)
+ 9005:0286:9005:028d Adaptec 2130S (Lancer)
+ 9005:0285:9005:0285 Adaptec 2200S (Vulcan)
+ 9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)
+ 9005:0286:9005:028c Adaptec 2230S (Lancer)
+ 9005:0286:9005:028c Adaptec 2230SLP (Lancer)
+ 9005:0285:9005:0296 Adaptec 2240S (SabreExpress)
+ 9005:0285:9005:0290 Adaptec 2410SA (Jaguar)
+ 9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
+ 9005:0285:103c:3227 Adaptec 2610SA (Bearcat)
+ 9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)
+ 9005:0285:9005:0294 Adaptec Prowler
+ 9005:0286:9005:029d Adaptec 2420SA (Intruder)
+ 9005:0286:9005:029c Adaptec 2620SA (Intruder)
+ 9005:0286:9005:029b Adaptec 2820SA (Intruder)
+ 9005:0286:9005:02a7 Adaptec 2830SA (Skyray)
+ 9005:0286:9005:02a8 Adaptec 2430SA (Skyray)
+ 9005:0285:9005:0288 Adaptec 3230S (Harrier)
+ 9005:0285:9005:0289 Adaptec 3240S (Tornado)
+ 9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)
+ 9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)
+ 9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)
+ 9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)
+ 9005:0286:9005:02a2 Adaptec 4810SAS (Hurricane)
+ 1011:0046:9005:0364 Adaptec 5400S (Mustang)
+ 1011:0046:9005:0365 Adaptec 5400S (Mustang)
+ 9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware)
+ 9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware)
+ 9005:0287:9005:0800 Adaptec Themisto (Jupiter)
+ 9005:0200:9005:0200 Adaptec Themisto (Jupiter)
+ 9005:0286:9005:0800 Adaptec Callisto (Jupiter)
+ 1011:0046:9005:1364 Dell PERC 2/QC (Quad Channel, Mustang)
+ 1028:0001:1028:0001 Dell PERC 2/Si (Iguana)
+ 1028:0003:1028:0003 Dell PERC 3/Si (SlimFast)
+ 1028:0002:1028:0002 Dell PERC 3/Di (Opal)
+ 1028:0004:1028:0004 Dell PERC 3/DiF (Iguana)
+ 1028:0002:1028:00d1 Dell PERC 3/DiV (Viper)
+ 1028:0002:1028:00d9 Dell PERC 3/DiL (Lexus)
+ 1028:000a:1028:0106 Dell PERC 3/DiJ (Jaguar)
+ 1028:000a:1028:011b Dell PERC 3/DiD (Dagger)
+ 1028:000a:1028:0121 Dell PERC 3/DiB (Boxster)
+ 9005:0285:1028:0287 Dell PERC 320/DC (Vulcan)
+ 9005:0285:1028:0291 Dell CERC 2 (DellCorsair)
+ 1011:0046:103c:10c2 HP NetRAID-4M (Mustang)
+ 9005:0285:17aa:0286 Legend S220 (Crusader)
+ 9005:0285:17aa:0287 Legend S230 (Vulcan)
+ 9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar)
+ 9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark)
+ 9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite)
+ 9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)
+ 9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite)
+ 9005:0286:9005:029f ICP ICP9014R0 (Lancer)
+ 9005:0286:9005:029e ICP ICP9024R0 (Lancer)
+ 9005:0286:9005:02a0 ICP ICP9047MA (Lancer)
+ 9005:0286:9005:02a1 ICP ICP9087MA (Lancer)
+ 9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X)
+ 9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E)
+ 9005:0286:9005:02a3 ICP ICP5085AU (Hurricane)
+ 9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6)
+ 9005:0286:9005:02a9 ICP ICP5087AU (Skyray)
+ 9005:0286:9005:02aa ICP ICP5047AU (Skyray)
+
+People
+-------------------------
+Alan Cox <alan@redhat.com>
+Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,
+ small cleanups/fixes)
+Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)
+Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
+ added new ioctls, changed scsi interface to use new error handler,
+ increased the number of fibs and outstanding commands to a container)
+
+ (fixed 64bit and 64G memory model, changed confusing naming convention
+ where fibs that go to the hardware are consistently called hw_fibs and
+ not just fibs like the name of the driver tracking structure)
+Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
+
+Original Driver
+-------------------------
+Adaptec Unix OEM Product Group
+
+Mailing List
+-------------------------
+linux-scsi@vger.kernel.org (Interested parties troll here)
+Also note this is very different to Brian's original driver
+so don't expect him to support it.
+Adaptec does support this driver. Contact Adaptec tech support or
+aacraid@adaptec.com
+
+Original by Brian Boerner February 2001
+Rewritten by Alan Cox, November 2001
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 66565d42288f..8bbae3e1abdf 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -150,7 +150,8 @@ scsi devices of which only the first 2 respond:
LLD mid level LLD
===-------------------=========--------------------===------
scsi_host_alloc() -->
-scsi_add_host() --------+
+scsi_add_host() ---->
+scsi_scan_host() -------+
|
slave_alloc()
slave_configure() --> scsi_adjust_queue_depth()
@@ -196,7 +197,7 @@ of the issues involved. See the section on reference counting below.
The hotplug concept may be extended to SCSI devices. Currently, when an
-HBA is added, the scsi_add_host() function causes a scan for SCSI devices
+HBA is added, the scsi_scan_host() function causes a scan for SCSI devices
attached to the HBA's SCSI transport. On newer SCSI transports the HBA
may become aware of a new SCSI device _after_ the scan has completed.
An LLD can use this sequence to make the mid level aware of a SCSI device:
@@ -372,7 +373,7 @@ names all start with "scsi_".
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_host - perform sysfs registration and set up transport class
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
@@ -386,6 +387,7 @@ Summary:
scsi_remove_device - detach and remove a SCSI device
scsi_remove_host - detach and remove all SCSI devices owned by host
scsi_report_bus_reset - report scsi _bus_ reset observed
+ scsi_scan_host - scan SCSI bus
scsi_track_queue_full - track successive QUEUE_FULL events
scsi_unblock_requests - allow further commands to be queued to given host
scsi_unregister - [calls scsi_host_put()]
@@ -425,10 +427,10 @@ void scsi_activate_tcq(struct scsi_device *sdev, int depth)
* Might block: yes
*
* Notes: This call is usually performed internally during a scsi
- * bus scan when an HBA is added (i.e. scsi_add_host()). So it
+ * bus scan when an HBA is added (i.e. scsi_scan_host()). So it
* should only be called if the HBA becomes aware of a new scsi
- * device (lu) after scsi_add_host() has completed. If successful
- * this call we lead to slave_alloc() and slave_configure() callbacks
+ * device (lu) after scsi_scan_host() has completed. If successful
+ * this call can lead to slave_alloc() and slave_configure() callbacks
* into the LLD.
*
* Defined in: drivers/scsi/scsi_scan.c
@@ -439,7 +441,7 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
/**
- * scsi_add_host - perform sysfs registration and SCSI bus scan.
+ * scsi_add_host - perform sysfs registration and set up transport class
* @shost: pointer to scsi host instance
* @dev: pointer to struct device of type scsi class
*
@@ -448,7 +450,11 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
* Might block: no
*
* Notes: Only required in "hotplug initialization model" after a
- * successful call to scsi_host_alloc().
+ * successful call to scsi_host_alloc(). This function does not
+ * scan the bus; this can be done by calling scsi_scan_host() or
+ * in some other transport-specific way. The LLD must set up
+ * the transport template before calling this function and may only
+ * access the transport class data after this function has been called.
*
* Defined in: drivers/scsi/hosts.c
**/
@@ -559,7 +565,7 @@ void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
* area for the LLD's exclusive use.
* Both associated refcounting objects have their refcount set to 1.
* Full registration (in sysfs) and a bus scan are performed later when
- * scsi_add_host() is called.
+ * scsi_add_host() and scsi_scan_host() are called.
*
* Defined in: drivers/scsi/hosts.c .
**/
@@ -699,6 +705,19 @@ void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
/**
+ * scsi_scan_host - scan SCSI bus
+ * @shost: a pointer to a scsi host instance
+ *
+ * Might block: yes
+ *
+ * Notes: Should be called after scsi_add_host()
+ *
+ * Defined in: drivers/scsi/scsi_scan.c
+ **/
+void scsi_scan_host(struct Scsi_Host *shost)
+
+
+/**
* scsi_track_queue_full - track successive QUEUE_FULL events on given
* device to determine if and when there is a need
* to adjust the queue depth on the device.
@@ -1433,7 +1452,7 @@ The following people have contributed to this document:
Christoph Hellwig <hch at infradead dot org>
Doug Ledford <dledford at redhat dot com>
Andries Brouwer <Andries dot Brouwer at cwi dot nl>
- Randy Dunlap <rddunlap at osdl dot org>
+ Randy Dunlap <rdunlap at xenotime dot net>
Alan Stern <stern at rowland dot harvard dot edu>
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 2f27f391c7cc..d2578013e829 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -105,7 +105,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Each of top level sound card module takes the following options.
index - index (slot #) of sound card
- - Values: 0 through 7 or negative
+ - Values: 0 through 31 or negative
- If nonnegative, assign that index number
- if negative, interpret as a bitmask of permissible
indices; the first free permitted index is assigned
@@ -134,7 +134,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
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.
+ This module supports multiple cards, autoprobe and PnP.
Module snd-ad1848
-----------------
@@ -145,9 +145,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
irq - IRQ # for AD1848 chip
dma1 - DMA # for AD1848 chip (0,1,3)
- Module supports up to 8 cards. This module does not support autoprobe
+ This module supports multiple cards. It does not support autoprobe
thus main port must be specified!!! Other ports are optional.
+ The power-management is supported.
+
Module snd-ad1889
-----------------
@@ -156,7 +158,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ac97_quirk - AC'97 workaround for strange hardware
See the description of intel8x0 module for details.
- This module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-ali5451
------------------
@@ -184,7 +186,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_irq - IRQ # for MPU-401 (PnP setup)
fm_port - port # for OPL3 FM (PnP setup)
- Module supports up to 8 cards, autoprobe and PnP.
+ This module supports multiple cards, autoprobe and PnP.
+
+ The power-management is supported.
Module snd-als4000
------------------
@@ -194,7 +198,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
joystick_port - port # for legacy joystick support.
0 = disabled (default), 1 = auto-detect
- Module supports up to 8 cards, autoprobe and PnP.
+ This module supports multiple cards, autoprobe and PnP.
+
+ The power-management is supported.
Module snd-atiixp
-----------------
@@ -213,6 +219,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
implementation depends on the motherboard, and you'll need to
choose the correct one via spdif_aclink module option.
+ The power-management is supported.
+
Module snd-atiixp-modem
-----------------------
@@ -223,6 +231,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: The default index value of this module is -2, i.e. the first
slot is excluded.
+ The power-management is supported.
+
Module snd-au8810, snd-au8820, snd-au8830
-----------------------------------------
@@ -263,8 +273,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma1 - 1st DMA # for AZT2320 (WSS) chip (PnP setup)
dma2 - 2nd DMA # for AZT2320 (WSS) chip (PnP setup)
- Module supports up to 8 cards, PnP and autoprobe.
+ This module supports multiple cards, PnP and autoprobe.
+ The power-management is supported.
+
Module snd-azt3328
------------------
@@ -272,7 +284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
joystick - Enable joystick (default off)
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-bt87x
----------------
@@ -282,7 +294,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
digital_rate - Override the default digital rate (Hz)
load_all - Load the driver even if the card model isn't known
- Module supports up to 8 cards.
+ This module supports multiple cards.
Note: The default index value of this module is -2, i.e. the first
slot is excluded.
@@ -292,7 +304,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for Creative Audigy LS and SB Live 24bit
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-cmi8330
@@ -308,7 +320,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
sbdma8 - 8bit DMA # for CMI8330 chip (SB16)
sbdma16 - 16bit DMA # for CMI8330 chip (SB16)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
+
+ The power-management is supported.
Module snd-cmipci
-----------------
@@ -321,8 +335,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
(default = 1)
joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
- Module supports autoprobe and multiple chips (max 8).
+ This module supports autoprobe and multiple cards.
+ The power-management is supported.
+
Module snd-cs4231
-----------------
@@ -335,7 +351,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma1 - first DMA # for CS4231 chip
dma2 - second DMA # for CS4231 chip
- Module supports up to 8 cards. This module does not support autoprobe
+ This module supports multiple cards. This module does not support autoprobe
thus main port must be specified!!! Other ports are optional.
The power-management is supported.
@@ -355,7 +371,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards. This module does not support autoprobe
+ This module supports multiple cards. This module does not support autoprobe
thus main port must be specified!!! Other ports are optional.
The power-management is supported.
@@ -376,7 +392,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - second DMA # for CS4236 chip (0,1,3), -1 = disable
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards. This module does not support autoprobe
+ This module supports multiple cards. This module does not support autoprobe
(if ISA PnP is not used) thus main port and control port must be
specified!!! Other ports are optional.
@@ -389,7 +405,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dual_codec - Secondary codec ID (0 = disable, default)
- Module supports up to 8 cards.
+ This module supports multiple cards.
The power-management is supported.
@@ -403,13 +419,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
thinkpad - Force to enable Thinkpad's CLKRUN control.
mmap_valid - Support OSS mmap mode (default = 0).
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Usually external amp and CLKRUN controls are detected automatically
from PCI sub vendor/device ids. If they don't work, give the options
above explicitly.
The power-management is supported.
+ Module snd-cs5535audio
+ ----------------------
+
+ Module for multifunction CS5535 companion PCI device
+
+ This module supports multiple cards.
+
Module snd-dt019x
-----------------
@@ -423,9 +446,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_irq - IRQ # for MPU-401 (PnP setup)
dma8 - DMA # (PnP setup)
- Module supports up to 8 cards. This module is enabled only with
+ This module supports multiple cards. This module is enabled only with
ISA PnP support.
+ The power-management is supported.
+
Module snd-dummy
----------------
@@ -433,6 +458,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
or input, but you may use this module for any application which
requires a sound card (like RealPlayer).
+ The power-management is supported.
+
Module snd-emu10k1
------------------
@@ -450,7 +477,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
given in MB unit. Default value is 128.
enable_ir - enable IR
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Input & Output configurations [extin/extout]
* Creative Card wo/Digital out [0x0003/0x1f03]
@@ -466,12 +493,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff]
* Creative Card all ins and outs [0x3fff/0x7fff]
+ The power-management is supported.
+
Module snd-emu10k1x
-------------------
Module for Creative Emu10k1X (SB Live Dell OEM version)
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-ens1370
------------------
@@ -482,7 +511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
joystick - Enable joystick (default off)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Module snd-ens1371
------------------
@@ -495,7 +524,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
joystick_port - port # for joystick (0x200,0x208,0x210,0x218),
0 = disable (default), 1 = auto-detect
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Module snd-es968
----------------
@@ -506,8 +535,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
irq - IRQ # for ES968 (SB8) chip (PnP setup)
dma1 - DMA # for ES968 (SB8) chip (PnP setup)
- Module supports up to 8 cards, PnP and autoprobe.
+ This module supports multiple cards, PnP and autoprobe.
+ The power-management is supported.
+
Module snd-es1688
-----------------
@@ -519,7 +550,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
dma8 - DMA # for ES-1688 chip (0,1,3)
- Module supports up to 8 cards and autoprobe (without MPU-401 port).
+ This module supports multiple cards and autoprobe (without MPU-401 port).
Module snd-es18xx
-----------------
@@ -534,8 +565,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - first DMA # for ES-18xx chip (0,1,3)
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards ISA PnP and autoprobe (without MPU-401 port
- if native ISA PnP routines are not used).
+ This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
+ port if native ISA PnP routines are not used).
When dma2 is equal with dma1, the driver works as half-duplex.
The power-management is supported.
@@ -545,7 +576,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
+
+ The power-management is supported.
Module snd-es1968
-----------------
@@ -561,7 +594,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
enable_mpu - enable MPU401 (0 = off, 1 = on, 2 = auto (default))
joystick - enable joystick (default off)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
The power-management is supported.
@@ -577,8 +610,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
- High 16-bits are video (radio) device number + 1
- example: 0x10002 (MediaForte 256-PCPR, device 1)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
+ The power-management is supported.
+
Module snd-gusclassic
---------------------
@@ -592,7 +627,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
voices - GF1 voices limit (14-32)
pcm_voices - reserved PCM voices
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Module snd-gusextreme
---------------------
@@ -611,7 +646,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
voices - GF1 voices limit (14-32)
pcm_voices - reserved PCM voices
- Module supports up to 8 cards and autoprobe (without MPU-401 port).
+ This module supports multiple cards and autoprobe (without MPU-401 port).
Module snd-gusmax
-----------------
@@ -626,7 +661,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
voices - GF1 voices limit (14-32)
pcm_voices - reserved PCM voices
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Module snd-hda-intel
--------------------
@@ -688,12 +723,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
(Usually SD_LPLIB register is more accurate than the
position buffer.)
+ The power-management is supported.
+
Module snd-hdsp
---------------
Module for RME Hammerfall DSP audio interface(s)
- Module supports up to 8 cards.
+ This module supports multiple cards.
Note: The firmware data can be automatically loaded via hotplug
when CONFIG_FW_LOADER is set. Otherwise, you need to load
@@ -751,7 +788,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
in msec resolution, default value is 500 (0.5 sec)
- Module supports up to 8 cards and autoprobe. Note: The consumer part
+ This module supports multiple cards and autoprobe. Note: The consumer part
is not used with all Envy24 based cards (for example in the MidiMan Delta
serie).
@@ -787,7 +824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
aureon71, universe, k8x800, phase22, phase28, ms300,
av710
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Note: The supported board is detected by reading EEPROM or PCI
SSID (if EEPROM isn't available). You can override the
@@ -839,6 +876,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: The default index value of this module is -2, i.e. the first
slot is excluded.
+ The power-management is supported.
+
Module snd-interwave
--------------------
@@ -855,7 +894,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
effect - 1 = InterWave effects enable (default 0);
requires 8 voices
- Module supports up to 8 cards, autoprobe and ISA PnP.
+ This module supports multiple cards, autoprobe and ISA PnP.
Module snd-interwave-stb
------------------------
@@ -875,14 +914,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
effect - 1 = InterWave effects enable (default 0);
requires 8 voices
- Module supports up to 8 cards, autoprobe and ISA PnP.
+ This module supports multiple cards, autoprobe and ISA PnP.
Module snd-korg1212
-------------------
Module for Korg 1212 IO PCI card
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-maestro3
-------------------
@@ -894,7 +933,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-1 for default pin (8 for allegro, 1 for
others)
- Module supports autoprobe and multiple chips (max 8).
+ This module supports autoprobe and multiple chips.
Note: the binding of amplifier is dependent on hardware.
If there is no sound even though all channels are unmuted, try to
@@ -909,7 +948,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for Digigram miXart8 sound cards.
- Module supports multiple cards.
+ This module supports multiple cards.
Note: One miXart8 board will be represented as 4 alsa cards.
See MIXART.txt for details.
@@ -928,7 +967,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
irq - IRQ number or -1 (disable)
pnp - PnP detection - 0 = disable, 1 = enable (default)
- Module supports multiple devices (max 8) and PnP.
+ This module supports multiple devices and PnP.
Module snd-mtpav
----------------
@@ -1014,7 +1053,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards and ISA PnP. This module does not support
+ This module supports multiple cards and ISA PnP. It does not support
autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
The power-management is supported.
@@ -1064,6 +1103,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
This module supports only one card, autoprobe and PnP.
+ Module snd-pcxhr
+ ----------------
+
+ Module for Digigram PCXHR boards
+
+ This module supports multiple cards.
+
Module snd-powermac (on ppc only)
---------------------------------
@@ -1084,20 +1130,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
For ARM architecture only.
+ The power-management is supported.
+
Module snd-rme32
----------------
Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
Prodif96 and Prodif Gold) sound cards.
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-rme96
----------------
Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-rme9652
------------------
@@ -1107,7 +1155,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
precise_ptr - Enable precise pointer (doesn't work reliably).
(default = 0)
- Module supports up to 8 cards.
+ This module supports multiple cards.
Note: snd-page-alloc module does the job which snd-hammerfall-mem
module did formerly. It will allocate the buffers in advance
@@ -1124,6 +1172,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module supports only one card.
Module has no enable and index options.
+ The power-management is supported.
+
Module snd-sb8
--------------
@@ -1135,8 +1185,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
irq - IRQ # for SB DSP chip (5,7,9,10)
dma8 - DMA # for SB DSP chip (1,3)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
+ The power-management is supported.
+
Module snd-sb16 and snd-sbawe
-----------------------------
@@ -1155,7 +1207,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards, autoprobe and ISA PnP.
+ This module supports multiple cards, autoprobe and ISA PnP.
Note: To use Vibra16X cards in 16-bit half duplex mode, you must
disable 16bit DMA with dma16 = -1 module parameter.
@@ -1163,6 +1215,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
half duplex mode through 8-bit DMA channel by disabling their
16-bit DMA channel.
+ The power-management is supported.
+
Module snd-sgalaxy
------------------
@@ -1173,7 +1227,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
irq - IRQ # (7,9,10,11)
dma1 - DMA #
- Module supports up to 8 cards.
+ This module supports multiple cards.
+
+ The power-management is supported.
Module snd-sscape
-----------------
@@ -1185,7 +1241,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mpu_irq - MPU-401 IRQ # (PnP setup)
dma - DMA # (PnP setup)
- Module supports up to 8 cards. ISA PnP must be enabled.
+ This module supports multiple cards. ISA PnP must be enabled.
You need sscape_ctl tool in alsa-tools package for loading
the microcode.
@@ -1194,21 +1250,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module for AMD7930 sound chips found on Sparcs.
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-sun-cs4231 (on sparc only)
-------------------------------------
Module for CS4231 sound chips found on Sparcs.
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-sun-dbri (on sparc only)
-----------------------------------
Module for DBRI sound chips found on Sparcs.
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-wavefront
--------------------
@@ -1228,7 +1284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
dma2 - DMA2 # for CS4232 PCM interface.
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
- Module supports up to 8 cards and ISA PnP.
+ This module supports multiple cards and ISA PnP.
Module snd-sonicvibes
---------------------
@@ -1240,7 +1296,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
- SoundCard must have onboard SRAM for this.
mge - Mic Gain Enable - 1 = enable, 0 = disable (default)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
Module snd-serial-u16550
------------------------
@@ -1259,7 +1315,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
3 = MS-124W M/B, 4 = Generic
- Module supports up to 8 cards. This module does not support autoprobe
+ This module supports multiple cards. This module does not support autoprobe
thus the main port must be specified!!! Other options are optional.
Module snd-trident
@@ -1278,7 +1334,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
pcm_channels - max channels (voices) reserved for PCM
wavetable_size - max wavetable size in kB (4-?kb)
- Module supports up to 8 cards and autoprobe.
+ This module supports multiple cards and autoprobe.
The power-management is supported.
@@ -1290,14 +1346,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
vid - Vendor ID for the device (optional)
pid - Product ID for the device (optional)
- This module supports up to 8 cards, autoprobe and hotplugging.
+ This module supports multiple devices, autoprobe and hotplugging.
Module snd-usb-usx2y
--------------------
Module for Tascam USB US-122, US-224 and US-428 devices.
- This module supports up to 8 cards, autoprobe and hotplugging.
+ This module supports multiple devices, autoprobe and hotplugging.
Note: you need to load the firmware via usx2yloader utility included
in alsa-tools and alsa-firmware packages.
@@ -1356,6 +1412,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
additionally. The mpu_port option is for VIA686 chips only.
+ The power-management is supported.
+
Module snd-via82xx-modem
------------------------
@@ -1368,6 +1426,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note: The default index value of this module is -2, i.e. the first
slot is excluded.
+ The power-management is supported.
+
Module snd-virmidi
------------------
@@ -1375,9 +1435,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
This module creates virtual rawmidi devices which communicate
to the corresponding ALSA sequencer ports.
- midi_devs - MIDI devices # (1-8, default=4)
+ midi_devs - MIDI devices # (1-4, default=4)
- Module supports up to 8 cards.
+ This module supports multiple cards.
Module snd-vx222
----------------
@@ -1387,7 +1447,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mic - Enable Microphone on V222 Mic (NYI)
ibl - Capture IBL size. (default = 0, minimum size)
- Module supports up to 8 cards.
+ This module supports multiple cards.
When the driver is compiled as a module and the hotplug firmware
is supported, the firmware data is loaded via hotplug automatically.
@@ -1406,6 +1466,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
size is chosen. The possible IBL values can be found in
/proc/asound/cardX/vx-status proc file.
+ The power-management is supported.
+
Module snd-vxpocket
-------------------
@@ -1413,7 +1475,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ibl - Capture IBL size. (default = 0, minimum size)
- Module supports up to 8 cards. The module is compiled only when
+ This module supports multiple cards. The module is compiled only when
PCMCIA is supported on kernel.
With the older 2.6.x kernel, to activate the driver via the card
@@ -1434,6 +1496,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
ALSA 1.0.10.
+ The power-management is supported.
+
Module snd-ymfpci
-----------------
@@ -1447,7 +1511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1 (auto-detect)
rear_switch - enable shared rear/line-in switch (bool)
- Module supports autoprobe and multiple chips (max 8).
+ This module supports autoprobe and multiple chips.
The power-management is supported.
@@ -1458,6 +1522,8 @@ 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.
+ The power-management is supported.
+
AC97 Quirk Option
=================
@@ -1474,7 +1540,7 @@ the proper value with this option.
The following strings are accepted:
- default Don't override the default setting
- - disable Disable the quirk
+ - none 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
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 260334c98d95..e651ed8d1e6f 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -18,8 +18,8 @@
</affiliation>
</author>
- <date>October 6, 2005</date>
- <edition>0.3.5</edition>
+ <date>November 17, 2005</date>
+ <edition>0.3.6</edition>
<abstract>
<para>
@@ -403,9 +403,8 @@
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
/* definition of the chip-specific record */
- typedef struct snd_mychip mychip_t;
- struct snd_mychip {
- snd_card_t *card;
+ struct mychip {
+ struct snd_card *card;
// rest of implementation will be in the section
// "PCI Resource Managements"
};
@@ -413,7 +412,7 @@
/* chip-specific destructor
* (see "PCI Resource Managements")
*/
- static int snd_mychip_free(mychip_t *chip)
+ static int snd_mychip_free(struct mychip *chip)
{
.... // will be implemented later...
}
@@ -421,22 +420,21 @@
/* component-destructor
* (see "Management of Cards and Components")
*/
- static int snd_mychip_dev_free(snd_device_t *device)
+ static int snd_mychip_dev_free(struct snd_device *device)
{
- mychip_t *chip = device->device_data;
- return snd_mychip_free(chip);
+ return snd_mychip_free(device->device_data);
}
/* chip-specific constructor
* (see "Management of Cards and Components")
*/
- static int __devinit snd_mychip_create(snd_card_t *card,
+ static int __devinit snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
- mychip_t **rchip)
+ struct mychip **rchip)
{
- mychip_t *chip;
+ struct mychip *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
@@ -474,8 +472,8 @@
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- mychip_t *chip;
+ struct snd_card *card;
+ struct mychip *chip;
int err;
/* (1) */
@@ -582,7 +580,7 @@
<informalexample>
<programlisting>
<![CDATA[
- snd_card_t *card;
+ struct snd_card *card;
....
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
]]>
@@ -605,7 +603,7 @@
<informalexample>
<programlisting>
<![CDATA[
- mychip_t *chip;
+ struct mychip *chip;
....
if ((err = snd_mychip_create(card, pci, &chip)) < 0) {
snd_card_free(card);
@@ -806,7 +804,7 @@
<informalexample>
<programlisting>
<![CDATA[
- snd_card_t *card;
+ struct snd_card *card;
card = snd_card_new(index, id, module, extra_size);
]]>
</programlisting>
@@ -830,7 +828,7 @@
<para>
After the card is created, you can attach the components
(devices) to the card instance. On ALSA driver, a component is
- represented as a <type>snd_device_t</type> object.
+ represented as a struct <structname>snd_device</structname> object.
A component can be a PCM instance, a control interface, a raw
MIDI interface, etc. Each of such instances has one component
entry.
@@ -891,14 +889,11 @@
The chip-specific information, e.g. the i/o port address, its
resource pointer, or the irq number, is stored in the
chip-specific record.
- Usually, the chip-specific record is typedef'ed as
- <type>xxx_t</type> like the following:
<informalexample>
<programlisting>
<![CDATA[
- typedef struct snd_mychip mychip_t;
- struct snd_mychip {
+ struct mychip {
....
};
]]>
@@ -918,12 +913,12 @@
<informalexample>
<programlisting>
<![CDATA[
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(mychip_t));
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip));
]]>
</programlisting>
</informalexample>
- whether <type>mychip_t</type> is the type of the chip record.
+ whether struct <structname>mychip</structname> is the type of the chip record.
</para>
<para>
@@ -932,7 +927,7 @@
<informalexample>
<programlisting>
<![CDATA[
- mychip_t *chip = (mychip_t *)card->private_data;
+ struct mychip *chip = (struct mychip *)card->private_data;
]]>
</programlisting>
</informalexample>
@@ -954,8 +949,8 @@
<informalexample>
<programlisting>
<![CDATA[
- snd_card_t *card;
- mychip_t *chip;
+ struct snd_card *card;
+ struct mychip *chip;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
.....
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -971,8 +966,8 @@
<informalexample>
<programlisting>
<![CDATA[
- struct snd_mychip {
- snd_card_t *card;
+ struct mychip {
+ struct snd_card *card;
....
};
]]>
@@ -1000,7 +995,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
....
@@ -1018,10 +1013,9 @@
<informalexample>
<programlisting>
<![CDATA[
- static int snd_mychip_dev_free(snd_device_t *device)
+ static int snd_mychip_dev_free(struct snd_device *device)
{
- mychip_t *chip = device->device_data;
- return snd_mychip_free(chip);
+ return snd_mychip_free(device->device_data);
}
]]>
</programlisting>
@@ -1087,15 +1081,15 @@
<title>PCI Resource Managements Example</title>
<programlisting>
<![CDATA[
- struct snd_mychip {
- snd_card_t *card;
+ struct mychip {
+ struct snd_card *card;
struct pci_dev *pci;
unsigned long port;
int irq;
};
- static int snd_mychip_free(mychip_t *chip)
+ static int snd_mychip_free(struct mychip *chip)
{
/* disable hardware here if any */
.... // (not implemented in this document)
@@ -1113,13 +1107,13 @@
}
/* chip-specific constructor */
- static int __devinit snd_mychip_create(snd_card_t *card,
+ static int __devinit snd_mychip_create(struct snd_card *card,
struct pci_dev *pci,
- mychip_t **rchip)
+ struct mychip **rchip)
{
- mychip_t *chip;
+ struct mychip *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_mychip_dev_free,
};
@@ -1155,8 +1149,7 @@
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip",
- (void *)chip)) {
+ SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1268,14 +1261,14 @@
<para>
Now assume that this PCI device has an I/O port with 8 bytes
- and an interrupt. Then <type>mychip_t</type> will have the
+ and an interrupt. Then struct <structname>mychip</structname> will have the
following fields:
<informalexample>
<programlisting>
<![CDATA[
- struct snd_mychip {
- snd_card_t *card;
+ struct mychip {
+ struct snd_card *card;
unsigned long port;
int irq;
@@ -1330,8 +1323,7 @@
<programlisting>
<![CDATA[
if (request_irq(pci->irq, snd_mychip_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "My Chip",
- (void *)chip)) {
+ SA_INTERRUPT|SA_SHIRQ, "My Chip", chip)) {
printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
snd_mychip_free(chip);
return -EBUSY;
@@ -1372,7 +1364,7 @@
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
....
return IRQ_HANDLED;
}
@@ -1487,7 +1479,7 @@
<informalexample>
<programlisting>
<![CDATA[
- struct snd_mychip {
+ struct mychip {
....
unsigned long iobase_phys;
void __iomem *iobase_virt;
@@ -1517,7 +1509,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static int snd_mychip_free(mychip_t *chip)
+ static int snd_mychip_free(struct mychip *chip)
{
....
if (chip->iobase_virt)
@@ -1537,7 +1529,7 @@
<title>Registration of Device Struct</title>
<para>
At some point, typically after calling <function>snd_device_new()</function>,
- you need to register the <structname>struct device</structname> of the chip
+ you need to register the struct <structname>device</structname> of the chip
you're handling for udev and co. ALSA provides a macro for compatibility with
older kernels. Simply call like the following:
<informalexample>
@@ -1739,7 +1731,7 @@
....
/* hardware definition */
- static snd_pcm_hardware_t snd_mychip_playback_hw = {
+ static struct snd_pcm_hardware snd_mychip_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1758,7 +1750,7 @@
};
/* hardware definition */
- static snd_pcm_hardware_t snd_mychip_capture_hw = {
+ static struct snd_pcm_hardware snd_mychip_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1777,10 +1769,10 @@
};
/* open callback */
- static int snd_mychip_playback_open(snd_pcm_substream_t *substream)
+ static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_playback_hw;
// more hardware-initialization will be done here
@@ -1788,19 +1780,19 @@
}
/* close callback */
- static int snd_mychip_playback_close(snd_pcm_substream_t *substream)
+ static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
// the hardware-specific codes will be here
return 0;
}
/* open callback */
- static int snd_mychip_capture_open(snd_pcm_substream_t *substream)
+ static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_capture_hw;
// more hardware-initialization will be done here
@@ -1808,33 +1800,33 @@
}
/* close callback */
- static int snd_mychip_capture_close(snd_pcm_substream_t *substream)
+ static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
// the hardware-specific codes will be here
return 0;
}
/* hw_params callback */
- static int snd_mychip_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+ static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
/* hw_free callback */
- static int snd_mychip_pcm_hw_free(snd_pcm_substream_t *substream)
+ static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
/* prepare callback */
- static int snd_mychip_pcm_prepare(snd_pcm_substream_t *substream)
+ static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
/* set up the hardware with the current configuration
* for example...
@@ -1849,7 +1841,7 @@
}
/* trigger callback */
- static int snd_mychip_pcm_trigger(snd_pcm_substream_t *substream,
+ static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
{
switch (cmd) {
@@ -1866,9 +1858,9 @@
/* pointer callback */
static snd_pcm_uframes_t
- snd_mychip_pcm_pointer(snd_pcm_substream_t *substream)
+ snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
unsigned int current_ptr;
/* get the current hardware pointer */
@@ -1877,7 +1869,7 @@
}
/* operators */
- static snd_pcm_ops_t snd_mychip_playback_ops = {
+ static struct snd_pcm_ops snd_mychip_playback_ops = {
.open = snd_mychip_playback_open,
.close = snd_mychip_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1889,7 +1881,7 @@
};
/* operators */
- static snd_pcm_ops_t snd_mychip_capture_ops = {
+ static struct snd_pcm_ops snd_mychip_capture_ops = {
.open = snd_mychip_capture_open,
.close = snd_mychip_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1905,9 +1897,9 @@
*/
/* create a pcm device */
- static int __devinit snd_mychip_new_pcm(mychip_t *chip)
+ static int __devinit snd_mychip_new_pcm(struct mychip *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1,
@@ -1944,9 +1936,9 @@
<informalexample>
<programlisting>
<![CDATA[
- static int __devinit snd_mychip_new_pcm(mychip_t *chip)
+ static int __devinit snd_mychip_new_pcm(struct mychip *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1,
@@ -1989,13 +1981,13 @@
specify more numbers, but they must be handled properly in
open/close, etc. callbacks. When you need to know which
substream you are referring to, then it can be obtained from
- <type>snd_pcm_substream_t</type> data passed to each callback
+ struct <structname>snd_pcm_substream</structname> data passed to each callback
as follows:
<informalexample>
<programlisting>
<![CDATA[
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int index = substream->number;
]]>
</programlisting>
@@ -2024,7 +2016,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static snd_pcm_ops_t snd_mychip_playback_ops = {
+ static struct snd_pcm_ops snd_mychip_playback_ops = {
.open = snd_mychip_pcm_open,
.close = snd_mychip_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -2102,18 +2094,18 @@
<title>PCM Instance with a Destructor</title>
<programlisting>
<![CDATA[
- static void mychip_pcm_free(snd_pcm_t *pcm)
+ static void mychip_pcm_free(struct snd_pcm *pcm)
{
- mychip_t *chip = snd_pcm_chip(pcm);
+ struct mychip *chip = snd_pcm_chip(pcm);
/* free your own data */
kfree(chip->my_private_pcm_data);
// do what you like else
....
}
- static int __devinit snd_mychip_new_pcm(mychip_t *chip)
+ static int __devinit snd_mychip_new_pcm(struct mychip *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
....
/* allocate your own data */
chip->my_private_pcm_data = kmalloc(...);
@@ -2149,7 +2141,7 @@
<![CDATA[
struct _snd_pcm_runtime {
/* -- Status -- */
- snd_pcm_substream_t *trigger_master;
+ struct snd_pcm_substream *trigger_master;
snd_timestamp_t trigger_tstamp; /* trigger timestamp */
int overrange;
snd_pcm_uframes_t avail_max;
@@ -2192,8 +2184,8 @@ struct _snd_pcm_runtime {
snd_pcm_sync_id_t sync; /* hardware synchronization ID */
/* -- mmap -- */
- volatile snd_pcm_mmap_status_t *status;
- volatile snd_pcm_mmap_control_t *control;
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
atomic_t mmap_count;
/* -- locking / scheduling -- */
@@ -2204,15 +2196,15 @@ struct _snd_pcm_runtime {
/* -- private section -- */
void *private_data;
- void (*private_free)(snd_pcm_runtime_t *runtime);
+ void (*private_free)(struct snd_pcm_runtime *runtime);
/* -- hardware description -- */
- snd_pcm_hardware_t hw;
- snd_pcm_hw_constraints_t hw_constraints;
+ struct snd_pcm_hardware hw;
+ struct snd_pcm_hw_constraints hw_constraints;
/* -- interrupt callbacks -- */
- void (*transfer_ack_begin)(snd_pcm_substream_t *substream);
- void (*transfer_ack_end)(snd_pcm_substream_t *substream);
+ void (*transfer_ack_begin)(struct snd_pcm_substream *substream);
+ void (*transfer_ack_end)(struct snd_pcm_substream *substream);
/* -- timer -- */
unsigned int timer_resolution; /* timer resolution */
@@ -2226,7 +2218,7 @@ struct _snd_pcm_runtime {
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
- snd_pcm_oss_runtime_t oss;
+ struct snd_pcm_oss_runtime oss;
#endif
};
]]>
@@ -2252,7 +2244,7 @@ struct _snd_pcm_runtime {
<section id="pcm-interface-runtime-hw">
<title>Hardware Description</title>
<para>
- The hardware descriptor (<type>snd_pcm_hardware_t</type>)
+ The hardware descriptor (struct <structname>snd_pcm_hardware</structname>)
contains the definitions of the fundamental hardware
configuration. Above all, you'll need to define this in
<link linkend="pcm-interface-operators-open-callback"><citetitle>
@@ -2267,7 +2259,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
...
runtime->hw = snd_mychip_playback_hw; /* common definition */
if (chip->model == VERY_OLD_ONE)
@@ -2282,7 +2274,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static snd_pcm_hardware_t snd_mychip_playback_hw = {
+ static struct snd_pcm_hardware snd_mychip_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -2337,9 +2329,14 @@ struct _snd_pcm_runtime {
<constant>PAUSE</constant> bit means that the pcm supports the
<quote>pause</quote> operation, while the
<constant>RESUME</constant> bit means that the pcm supports
- the <quote>suspend/resume</quote> operation. If these flags
- are set, the <structfield>trigger</structfield> callback below
- must handle the corresponding commands.
+ the full <quote>suspend/resume</quote> operation.
+ If <constant>PAUSE</constant> flag is set,
+ the <structfield>trigger</structfield> callback below
+ must handle the corresponding (pause push/release) commands.
+ The suspend/resume trigger commands can be defined even without
+ <constant>RESUME</constant> flag. See <link
+ linkend="power-management"><citetitle>
+ Power Management</citetitle></link> section for details.
</para>
<para>
@@ -2512,7 +2509,7 @@ struct _snd_pcm_runtime {
<title>Running Status</title>
<para>
The running status can be referred via <constant>runtime-&gt;status</constant>.
- This is the pointer to <type>snd_pcm_mmap_status_t</type>
+ This is the pointer to struct <structname>snd_pcm_mmap_status</structname>
record. For example, you can get the current DMA hardware
pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
</para>
@@ -2520,7 +2517,7 @@ struct _snd_pcm_runtime {
<para>
The DMA application pointer can be referred via
<constant>runtime-&gt;control</constant>, which points
- <type>snd_pcm_mmap_control_t</type> record.
+ struct <structname>snd_pcm_mmap_control</structname> record.
However, accessing directly to this value is not recommended.
</para>
</section>
@@ -2542,9 +2539,9 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_open(snd_pcm_substream_t *substream)
+ static int snd_xxx_open(struct snd_pcm_substream *substream)
{
- my_pcm_data_t *data;
+ struct my_pcm_data *data;
....
data = kmalloc(sizeof(*data), GFP_KERNEL);
substream->runtime->private_data = data;
@@ -2586,7 +2583,7 @@ struct _snd_pcm_runtime {
<para>
The callback function takes at least the argument with
- <type>snd_pcm_substream_t</type> pointer. For retrieving the
+ <structname>snd_pcm_substream</structname> pointer. For retrieving the
chip record from the given substream instance, you can use the
following macro.
@@ -2594,7 +2591,7 @@ struct _snd_pcm_runtime {
<programlisting>
<![CDATA[
int xxx() {
- mychip_t *chip = snd_pcm_substream_chip(substream);
+ struct mychip *chip = snd_pcm_substream_chip(substream);
....
}
]]>
@@ -2616,7 +2613,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_open(snd_pcm_substream_t *substream);
+ static int snd_xxx_open(struct snd_pcm_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -2631,10 +2628,10 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_open(snd_pcm_substream_t *substream)
+ static int snd_xxx_open(struct snd_pcm_substream *substream)
{
- mychip_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct mychip *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->hw = snd_mychip_playback_hw;
return 0;
@@ -2667,7 +2664,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_close(snd_pcm_substream_t *substream);
+ static int snd_xxx_close(struct snd_pcm_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -2682,7 +2679,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_close(snd_pcm_substream_t *substream)
+ static int snd_xxx_close(struct snd_pcm_substream *substream)
{
....
kfree(substream->runtime->private_data);
@@ -2709,8 +2706,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params);
+ static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params);
]]>
</programlisting>
</informalexample>
@@ -2785,7 +2782,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_hw_free(snd_pcm_substream_t * substream);
+ static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -2820,7 +2817,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_prepare(snd_pcm_substream_t * substream);
+ static int snd_xxx_prepare(struct snd_pcm_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -2869,7 +2866,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_trigger(snd_pcm_substream_t * substream, int cmd);
+ static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
]]>
</programlisting>
</informalexample>
@@ -2911,8 +2908,8 @@ struct _snd_pcm_runtime {
</para>
<para>
- When the pcm supports the suspend/resume operation
- (i.e. <constant>SNDRV_PCM_INFO_RESUME</constant> flag is set),
+ When the pcm supports the suspend/resume operation,
+ regardless of full or partial suspend/resume support,
<constant>SUSPEND</constant> and <constant>RESUME</constant>
commands must be handled, too.
These commands are issued when the power-management status is
@@ -2921,6 +2918,8 @@ struct _snd_pcm_runtime {
do suspend and resume of the pcm substream, and usually, they
are identical with <constant>STOP</constant> and
<constant>START</constant> commands, respectively.
+ See <link linkend="power-management"><citetitle>
+ Power Management</citetitle></link> section for details.
</para>
<para>
@@ -2939,7 +2938,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static snd_pcm_uframes_t snd_xxx_pointer(snd_pcm_substream_t * substream)
+ static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
]]>
</programlisting>
</informalexample>
@@ -3067,7 +3066,7 @@ struct _snd_pcm_runtime {
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
spin_lock(&chip->lock);
....
if (pcm_irq_invoked(chip)) {
@@ -3111,7 +3110,7 @@ struct _snd_pcm_runtime {
static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- mychip_t *chip = dev_id;
+ struct mychip *chip = dev_id;
spin_lock(&chip->lock);
....
if (pcm_irq_invoked(chip)) {
@@ -3221,13 +3220,13 @@ struct _snd_pcm_runtime {
<![CDATA[
static unsigned int rates[] =
{4000, 10000, 22050, 44100};
- static snd_pcm_hw_constraint_list_t constraints_rates = {
+ static struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
- static int snd_mychip_pcm_open(snd_pcm_substream_t *substream)
+ static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
{
int err;
....
@@ -3249,19 +3248,20 @@ struct _snd_pcm_runtime {
You can even define your own constraint rules.
For example, let's suppose my_chip can manage a substream of 1 channel
if and only if the format is S16_LE, otherwise it supports any format
- specified in the <type>snd_pcm_hardware_t</type> stucture (or in any
+ specified in the <structname>snd_pcm_hardware</structname> stucture (or in any
other constraint_list). You can build a rule like this:
<example>
<title>Example of Hardware Constraints for Channels</title>
<programlisting>
<![CDATA[
- static int hw_rule_format_by_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_mask_t *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- snd_mask_t fmt;
+ struct snd_interval *c = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_mask fmt;
snd_mask_any(&fmt); /* Init the struct */
if (c->min < 2) {
@@ -3298,12 +3298,13 @@ struct _snd_pcm_runtime {
<title>Example of Hardware Constraints for Channels</title>
<programlisting>
<![CDATA[
- static int hw_rule_channels_by_format(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+ static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_mask_t *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
- snd_interval_t ch;
+ struct snd_interval *c = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_interval ch;
snd_interval_any(&ch);
if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
@@ -3376,13 +3377,13 @@ struct _snd_pcm_runtime {
callbacks: <structfield>info</structfield>,
<structfield>get</structfield> and
<structfield>put</structfield>. Then, define a
- <type>snd_kcontrol_new_t</type> record, such as:
+ struct <structname>snd_kcontrol_new</structname> record, such as:
<example>
<title>Definition of a Control</title>
<programlisting>
<![CDATA[
- static snd_kcontrol_new_t my_control __devinitdata = {
+ static struct snd_kcontrol_new my_control __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -3599,7 +3600,7 @@ struct _snd_pcm_runtime {
<para>
The <structfield>info</structfield> callback is used to get
the detailed information of this control. This must store the
- values of the given <type>snd_ctl_elem_info_t</type>
+ values of the given struct <structname>snd_ctl_elem_info</structname>
object. For example, for a boolean control with a single
element will be:
@@ -3607,8 +3608,8 @@ struct _snd_pcm_runtime {
<title>Example of info callback</title>
<programlisting>
<![CDATA[
- static int snd_myctl_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+ static int snd_myctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -3642,8 +3643,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_myctl_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+ static int snd_myctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"First", "Second", "Third", "Fourth"
@@ -3678,10 +3679,10 @@ struct _snd_pcm_runtime {
<title>Example of get callback</title>
<programlisting>
<![CDATA[
- static int snd_myctl_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+ static int snd_myctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- mychip_t *chip = snd_kcontrol_chip(kcontrol);
+ struct mychip *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = get_some_value(chip);
return 0;
}
@@ -3717,8 +3718,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_sbmixer_get_single(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+ static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0xff;
@@ -3754,10 +3755,10 @@ struct _snd_pcm_runtime {
<title>Example of put callback</title>
<programlisting>
<![CDATA[
- static int snd_myctl_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+ static int snd_myctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- mychip_t *chip = snd_kcontrol_chip(kcontrol);
+ struct mychip *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
if (chip->current_value !=
ucontrol->value.integer.value[0]) {
@@ -3814,7 +3815,7 @@ struct _snd_pcm_runtime {
</informalexample>
where <parameter>my_control</parameter> is the
- <type>snd_kcontrol_new_t</type> object defined above, and chip
+ struct <structname>snd_kcontrol_new</structname> object defined above, and chip
is the object pointer to be passed to
kcontrol-&gt;private_data
which can be referred in callbacks.
@@ -3822,7 +3823,7 @@ struct _snd_pcm_runtime {
<para>
<function>snd_ctl_new1()</function> allocates a new
- <type>snd_kcontrol_t</type> instance (that's why the definition
+ <structname>snd_kcontrol</structname> instance (that's why the definition
of <parameter>my_control</parameter> can be with
<parameter>__devinitdata</parameter>
prefix), and <function>snd_ctl_add</function> assigns the given
@@ -3849,7 +3850,7 @@ struct _snd_pcm_runtime {
control id pointer for the notification. The event-mask
specifies the types of notification, for example, in the above
example, the change of control values is notified.
- The id pointer is the pointer of <type>snd_ctl_elem_id_t</type>
+ The id pointer is the pointer of struct <structname>snd_ctl_elem_id</structname>
to be notified.
You can find some examples in <filename>es1938.c</filename> or
<filename>es1968.c</filename> for hardware volume interrupts.
@@ -3882,35 +3883,35 @@ struct _snd_pcm_runtime {
<title>Example of AC97 Interface</title>
<programlisting>
<![CDATA[
- struct snd_mychip {
+ struct mychip {
....
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
....
};
- static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
+ static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- mychip_t *chip = ac97->private_data;
+ struct mychip *chip = ac97->private_data;
....
// read a register value here from the codec
return the_register_value;
}
- static void snd_mychip_ac97_write(ac97_t *ac97,
+ static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- mychip_t *chip = ac97->private_data;
+ struct mychip *chip = ac97->private_data;
....
// write the given register value to the codec
}
- static int snd_mychip_ac97(mychip_t *chip)
+ static int snd_mychip_ac97(struct mychip *chip)
{
- ac97_bus_t *bus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *bus;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_mychip_ac97_write,
.read = snd_mychip_ac97_read,
};
@@ -3937,8 +3938,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- ac97_bus_t *bus;
- static ac97_bus_ops_t ops = {
+ struct snd_ac97_bus *bus;
+ static struct snd_ac97_bus_ops ops = {
.write = snd_mychip_ac97_write,
.read = snd_mychip_ac97_read,
};
@@ -3952,13 +3953,14 @@ struct _snd_pcm_runtime {
</para>
<para>
- And then call <function>snd_ac97_mixer()</function> with an <type>ac97_template_t</type>
+ And then call <function>snd_ac97_mixer()</function> with an
+ struct <structname>snd_ac97_template</structname>
record together with the bus pointer created above.
<informalexample>
<programlisting>
<![CDATA[
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
int err;
memset(&ac97, 0, sizeof(ac97));
@@ -3995,10 +3997,10 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
+ static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- mychip_t *chip = ac97->private_data;
+ struct mychip *chip = ac97->private_data;
....
return the_register_value;
}
@@ -4016,7 +4018,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void snd_mychip_ac97_write(ac97_t *ac97,
+ static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
]]>
</programlisting>
@@ -4163,7 +4165,7 @@ struct _snd_pcm_runtime {
<title>Multiple Codecs</title>
<para>
When there are several codecs on the same card, you need to
- call <function>snd_ac97_new()</function> multiple times with
+ call <function>snd_ac97_mixer()</function> multiple times with
ac97.num=1 or greater. The <structfield>num</structfield> field
specifies the codec
number.
@@ -4212,7 +4214,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, integrated,
irq, irq_flags, &rmidi);
]]>
@@ -4253,17 +4255,17 @@ struct _snd_pcm_runtime {
Usually, the port address corresponds to the command port and
port + 1 corresponds to the data port. If not, you may change
the <structfield>cport</structfield> field of
- <type>mpu401_t</type> manually
- afterward. However, <type>mpu401_t</type> pointer is not
+ struct <structname>snd_mpu401</structname> manually
+ afterward. However, <structname>snd_mpu401</structname> pointer is not
returned explicitly by
<function>snd_mpu401_uart_new()</function>. You need to cast
rmidi-&gt;private_data to
- <type>mpu401_t</type> explicitly,
+ <structname>snd_mpu401</structname> explicitly,
<informalexample>
<programlisting>
<![CDATA[
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
mpu = rmidi->private_data;
]]>
</programlisting>
@@ -4359,7 +4361,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
if (err < 0)
return err;
@@ -4419,7 +4421,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static snd_rawmidi_ops_t snd_mymidi_output_ops = {
+ static struct snd_rawmidi_ops snd_mymidi_output_ops = {
.open = snd_mymidi_output_open,
.close = snd_mymidi_output_close,
.trigger = snd_mymidi_output_trigger,
@@ -4439,9 +4441,9 @@ struct _snd_pcm_runtime {
<programlisting>
<![CDATA[
struct list_head *list;
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
}
/* same for SNDRV_RAWMIDI_STREAM_INPUT */
@@ -4463,12 +4465,12 @@ struct _snd_pcm_runtime {
<para>
If there is more than one port, your callbacks can determine the
- port index from the snd_rawmidi_substream_t data passed to each
+ port index from the struct snd_rawmidi_substream data passed to each
callback:
<informalexample>
<programlisting>
<![CDATA[
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
int index = substream->number;
]]>
</programlisting>
@@ -4481,7 +4483,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_open(snd_rawmidi_substream_t *substream);
+ static int snd_xxx_open(struct snd_rawmidi_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -4499,7 +4501,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int snd_xxx_close(snd_rawmidi_substream_t *substream);
+ static int snd_xxx_close(struct snd_rawmidi_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -4522,7 +4524,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void snd_xxx_output_trigger(snd_rawmidi_substream_t *substream, int up);
+ static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
]]>
</programlisting>
</informalexample>
@@ -4547,7 +4549,7 @@ struct _snd_pcm_runtime {
<![CDATA[
unsigned char data;
while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
- if (mychip_try_to_transmit(data))
+ if (snd_mychip_try_to_transmit(data))
snd_rawmidi_transmit_ack(substream, 1);
else
break; /* hardware FIFO full */
@@ -4564,11 +4566,11 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- while (mychip_transmit_possible()) {
+ while (snd_mychip_transmit_possible()) {
unsigned char data;
if (snd_rawmidi_transmit(substream, &data, 1) != 1)
break; /* no more data */
- mychip_transmit(data);
+ snd_mychip_transmit(data);
}
]]>
</programlisting>
@@ -4603,7 +4605,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void snd_xxx_input_trigger(snd_rawmidi_substream_t *substream, int up);
+ static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
]]>
</programlisting>
</informalexample>
@@ -4647,7 +4649,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void snd_xxx_drain(snd_rawmidi_substream_t *substream);
+ static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
]]>
</programlisting>
</informalexample>
@@ -4661,7 +4663,7 @@ struct _snd_pcm_runtime {
<para>
This callback is optional. If you do not set
- <structfield>drain</structfield> in the snd_rawmidi_ops_t
+ <structfield>drain</structfield> in the struct snd_rawmidi_ops
structure, ALSA will simply wait for 50&nbsp;milliseconds
instead.
</para>
@@ -4703,7 +4705,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
integrated, &opl3);
]]>
@@ -4736,7 +4738,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
]]>
</programlisting>
@@ -4767,7 +4769,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_hwdep_t *opl3hwdep;
+ struct snd_hwdep *opl3hwdep;
snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
]]>
</programlisting>
@@ -4804,7 +4806,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
snd_hwdep_new(card, "My HWDEP", 0, &hw);
]]>
</programlisting>
@@ -4823,7 +4825,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- mydata_t *p = kmalloc(sizeof(*p), GFP_KERNEL);
+ struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
hw->private_data = p;
hw->private_free = mydata_free;
]]>
@@ -4835,9 +4837,9 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void mydata_free(snd_hwdep_t *hw)
+ static void mydata_free(struct snd_hwdep *hw)
{
- mydata_t *p = hw->private_data;
+ struct mydata *p = hw->private_data;
kfree(p);
}
]]>
@@ -5061,9 +5063,9 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int playback_copy(snd_pcm_substream_t *substream, int channel,
+ static int playback_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
- static int capture_copy(snd_pcm_substream_t *substream, int channel,
+ static int capture_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
]]>
</programlisting>
@@ -5144,7 +5146,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int silence(snd_pcm_substream_t *substream, int channel,
+ static int silence(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
]]>
</programlisting>
@@ -5211,7 +5213,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_pcm_sgbuf_t *sgbuf = (snd_pcm_sgbuf_t*)substream->dma_private;
+ struct snd_sg_buf *sgbuf = (struct snd_sg_buf_t*)substream->dma_private;
]]>
</programlisting>
</informalexample>
@@ -5266,7 +5268,7 @@ struct _snd_pcm_runtime {
#include <linux/vmalloc.h>
/* get the physical page pointer on the given offset */
- static struct page *mychip_page(snd_pcm_substream_t *substream,
+ static struct page *mychip_page(struct snd_pcm_substream *substream,
unsigned long offset)
{
void *pageptr = substream->runtime->dma_area + offset;
@@ -5301,7 +5303,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
int err = snd_card_proc_new(card, "my-file", &entry);
]]>
</programlisting>
@@ -5345,8 +5347,8 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void my_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer);
+ static void my_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer);
]]>
</programlisting>
</informalexample>
@@ -5361,10 +5363,10 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void my_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+ static void my_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- chip_t *chip = entry->private_data;
+ struct my_chip *chip = entry->private_data;
snd_iprintf(buffer, "This is my chip!\n");
snd_iprintf(buffer, "Port = %ld\n", chip->port);
@@ -5453,7 +5455,7 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static long my_file_io_read(snd_info_entry_t *entry,
+ static long my_file_io_read(struct snd_info_entry *entry,
void *file_private_data,
struct file *file,
char *buf,
@@ -5488,22 +5490,60 @@ struct _snd_pcm_runtime {
<constant>CONFIG_PM</constant>.
</para>
+ <para>
+ If the driver supports the suspend/resume
+ <emphasis>fully</emphasis>, that is, the device can be
+ properly resumed to the status at the suspend is called,
+ you can set <constant>SNDRV_PCM_INFO_RESUME</constant> flag
+ to pcm info field. Usually, this is possible when the
+ registers of ths chip can be safely saved and restored to the
+ RAM. If this is set, the trigger callback is called with
+ <constant>SNDRV_PCM_TRIGGER_RESUME</constant> after resume
+ callback is finished.
+ </para>
+
+ <para>
+ Even if the driver doesn't support PM fully but only the
+ partial suspend/resume is possible, it's still worthy to
+ implement suspend/resume callbacks. In such a case, applications
+ would reset the status by calling
+ <function>snd_pcm_prepare()</function> and restart the stream
+ appropriately. Hence, you can define suspend/resume callbacks
+ below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant>
+ info flag to the PCM.
+ </para>
+
+ <para>
+ Note that the trigger with SUSPEND can be always called when
+ <function>snd_pcm_suspend_all</function> is called,
+ regardless of <constant>SNDRV_PCM_INFO_RESUME</constant> flag.
+ The <constant>RESUME</constant> flag affects only the behavior
+ of <function>snd_pcm_resume()</function>.
+ (Thus, in theory,
+ <constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed
+ to be handled in the trigger callback when no
+ <constant>SNDRV_PCM_INFO_RESUME</constant> flag is set. But,
+ it's better to keep it for compatibility reason.)
+ </para>
<para>
- ALSA provides the common power-management layer. Each card driver
- needs to have only low-level suspend and resume callbacks.
+ In the earlier version of ALSA drivers, a common
+ power-management layer was provided, but it has been removed.
+ The driver needs to define the suspend/resume hooks according to
+ the bus the device is assigned. In the case of PCI driver, the
+ callbacks look like below:
<informalexample>
<programlisting>
<![CDATA[
#ifdef CONFIG_PM
- static int snd_my_suspend(snd_card_t *card, pm_message_t state)
+ static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
{
- .... // do things for suspsend
+ .... /* do things for suspsend */
return 0;
}
- static int snd_my_resume(snd_card_t *card)
+ static int snd_my_resume(struct pci_dev *pci)
{
- .... // do things for suspsend
+ .... /* do things for suspsend */
return 0;
}
#endif
@@ -5516,11 +5556,18 @@ struct _snd_pcm_runtime {
The scheme of the real suspend job is as following.
<orderedlist>
- <listitem><para>Retrieve the chip data from pm_private_data field.</para></listitem>
+ <listitem><para>Retrieve the card and the chip data.</para></listitem>
+ <listitem><para>Call <function>snd_power_change_state()</function> with
+ <constant>SNDRV_CTL_POWER_D3hot</constant> to change the
+ power status.</para></listitem>
<listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
+ <listitem><para>If AC97 codecs are used, call
+ <function>snd_ac97_resume()</function> for each codec.</para></listitem>
<listitem><para>Save the register values if necessary.</para></listitem>
<listitem><para>Stop the hardware if necessary.</para></listitem>
- <listitem><para>Disable the PCI device by calling <function>pci_disable_device()</function>.</para></listitem>
+ <listitem><para>Disable the PCI device by calling
+ <function>pci_disable_device()</function>. Then, call
+ <function>pci_save_state()</function> at last.</para></listitem>
</orderedlist>
</para>
@@ -5530,18 +5577,24 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static int mychip_suspend(snd_card_t *card, pm_message_t state)
+ static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
{
/* (1) */
- mychip_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
/* (2) */
- snd_pcm_suspend_all(chip->pcm);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
/* (3) */
- snd_mychip_save_registers(chip);
+ snd_pcm_suspend_all(chip->pcm);
/* (4) */
- snd_mychip_stop_hardware(chip);
+ snd_ac97_suspend(chip->ac97);
/* (5) */
- pci_disable_device(chip->pci);
+ snd_mychip_save_registers(chip);
+ /* (6) */
+ snd_mychip_stop_hardware(chip);
+ /* (7) */
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
]]>
@@ -5553,14 +5606,17 @@ struct _snd_pcm_runtime {
The scheme of the real resume job is as following.
<orderedlist>
- <listitem><para>Retrieve the chip data from pm_private_data field.</para></listitem>
- <listitem><para>Enable the pci device again by calling
- <function>pci_enable_device()</function>.</para></listitem>
+ <listitem><para>Retrieve the card and the chip data.</para></listitem>
+ <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>.
+ Then enable the pci device again by calling <function>pci_enable_device()</function>.
+ Call <function>pci_set_master()</function> if necessary, too.</para></listitem>
<listitem><para>Re-initialize the chip.</para></listitem>
<listitem><para>Restore the saved registers if necessary.</para></listitem>
<listitem><para>Resume the mixer, e.g. calling
<function>snd_ac97_resume()</function>.</para></listitem>
<listitem><para>Restart the hardware (if any).</para></listitem>
+ <listitem><para>Call <function>snd_power_change_state()</function> with
+ <constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem>
</orderedlist>
</para>
@@ -5570,12 +5626,15 @@ struct _snd_pcm_runtime {
<informalexample>
<programlisting>
<![CDATA[
- static void mychip_resume(mychip_t *chip)
+ static int mychip_resume(struct pci_dev *pci)
{
/* (1) */
- mychip_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct mychip *chip = card->private_data;
/* (2) */
- pci_enable_device(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
/* (3) */
snd_mychip_reinit_chip(chip);
/* (4) */
@@ -5584,6 +5643,8 @@ struct _snd_pcm_runtime {
snd_ac97_resume(chip->ac97);
/* (6) */
snd_mychip_restart_chip(chip);
+ /* (7) */
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
]]>
@@ -5592,8 +5653,23 @@ struct _snd_pcm_runtime {
</para>
<para>
- OK, we have all callbacks now. Let's set up them now. In the
- initialization of the card, add the following:
+ As shown in the above, it's better to save registers after
+ suspending the PCM operations via
+ <function>snd_pcm_suspend_all()</function> or
+ <function>snd_pcm_suspend()</function>. It means that the PCM
+ streams are already stoppped when the register snapshot is
+ taken. But, remind that you don't have to restart the PCM
+ stream in the resume callback. It'll be restarted via
+ trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant>
+ when necessary.
+ </para>
+
+ <para>
+ OK, we have all callbacks now. Let's set them up. In the
+ initialization of the card, make sure that you can get the chip
+ data from the card instance, typically via
+ <structfield>private_data</structfield> field, in case you
+ created the chip data individually.
<informalexample>
<programlisting>
@@ -5602,33 +5678,56 @@ struct _snd_pcm_runtime {
const struct pci_device_id *pci_id)
{
....
- snd_card_t *card;
- mychip_t *chip;
+ struct snd_card *card;
+ struct mychip *chip;
....
- snd_card_set_pm_callback(card, snd_my_suspend, snd_my_resume, chip);
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+ ....
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ ....
+ card->private_data = chip;
+ ....
+ }
+]]>
+ </programlisting>
+ </informalexample>
+
+ When you created the chip data with
+ <function>snd_card_new()</function>, it's anyway accessible
+ via <structfield>private_data</structfield> field.
+
+ <informalexample>
+ <programlisting>
+<![CDATA[
+ static int __devinit snd_mychip_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+ {
+ ....
+ struct snd_card *card;
+ struct mychip *chip;
+ ....
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct mychip));
+ ....
+ chip = card->private_data;
....
}
]]>
</programlisting>
</informalexample>
- Here you don't have to put ifdef CONFIG_PM around, since it's already
- checked in the header and expanded to empty if not needed.
</para>
<para>
- If you need a space for saving the registers, you'll need to
- allocate the buffer for it here, too, since it would be fatal
+ If you need a space for saving the registers, allocate the
+ buffer for it here, too, since it would be fatal
if you cannot allocate a memory in the suspend phase.
The allocated buffer should be released in the corresponding
destructor.
</para>
<para>
- And next, set suspend/resume callbacks to the pci_driver,
- This can be done by passing a macro SND_PCI_PM_CALLBACKS
- in the pci_driver struct. This macro is expanded to the correct
- (global) callbacks if CONFIG_PM is set.
+ And next, set suspend/resume callbacks to the pci_driver.
<informalexample>
<programlisting>
@@ -5638,7 +5737,10 @@ struct _snd_pcm_runtime {
.id_table = snd_my_ids,
.probe = snd_my_probe,
.remove = __devexit_p(snd_my_remove),
- SND_PCI_PM_CALLBACKS
+ #ifdef CONFIG_PM
+ .suspend = snd_my_suspend,
+ .resume = snd_my_resume,
+ #endif
};
]]>
</programlisting>
diff --git a/Documentation/sound/alsa/Procfile.txt b/Documentation/sound/alsa/Procfile.txt
index 25c5d648aef6..1fe48846d78f 100644
--- a/Documentation/sound/alsa/Procfile.txt
+++ b/Documentation/sound/alsa/Procfile.txt
@@ -138,6 +138,22 @@ card*/codec97#0/ac97#?-?+regs
# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
+USB Audio Streams
+-----------------
+
+card*/stream*
+ Shows the assignment and the current status of each audio stream
+ of the given card. This information is very useful for debugging.
+
+
+HD-Audio Codecs
+---------------
+
+card*/codec#*
+ Shows the general codec information and the attribute of each
+ widget node.
+
+
Sequencer Information
---------------------
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
index e9d07b8f1acb..0be57ed81302 100644
--- a/Documentation/sound/alsa/hda_codec.txt
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -63,7 +63,7 @@ The bus instance is created via snd_hda_bus_new(). You need to pass
the card instance, the template, and the pointer to store the
resultant bus instance.
-int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
struct hda_bus **busp);
It returns zero if successful. A negative return value means any
@@ -166,14 +166,14 @@ The ops field contains the following callback functions:
struct hda_pcm_ops {
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
unsigned int stream_tag, unsigned int format,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
};
All are non-NULL, so you can call them safely without NULL check.
@@ -284,7 +284,7 @@ parameter, and PCI subsystem IDs. If the matching entry is found, it
returns the config field value.
snd_hda_add_new_ctls() can be used to create and add control entries.
-Pass the zero-terminated array of snd_kcontrol_new_t. The same array
+Pass the zero-terminated array of struct snd_kcontrol_new. The same array
can be passed to snd_hda_resume_ctls() for resume.
Note that this will call control->put callback of these entries. So,
put callback should check codec->in_resume and force to restore the
@@ -292,7 +292,7 @@ given value if it's non-zero even if the value is identical with the
cached value.
Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
-used for the entry of snd_kcontrol_new_t.
+used for the entry of struct snd_kcontrol_new.
The input MUX helper callbacks for such a control are provided, too:
snd_hda_input_mux_info() and snd_hda_input_mux_put(). See
diff --git a/Documentation/spi/butterfly b/Documentation/spi/butterfly
new file mode 100644
index 000000000000..a2e8c8d90e35
--- /dev/null
+++ b/Documentation/spi/butterfly
@@ -0,0 +1,57 @@
+spi_butterfly - parport-to-butterfly adapter driver
+===================================================
+
+This is a hardware and software project that includes building and using
+a parallel port adapter cable, together with an "AVR Butterfly" to run
+firmware for user interfacing and/or sensors. A Butterfly is a $US20
+battery powered card with an AVR microcontroller and lots of goodies:
+sensors, LCD, flash, toggle stick, and more. You can use AVR-GCC to
+develop firmware for this, and flash it using this adapter cable.
+
+You can make this adapter from an old printer cable and solder things
+directly to the Butterfly. Or (if you have the parts and skills) you
+can come up with something fancier, providing ciruit protection to the
+Butterfly and the printer port, or with a better power supply than two
+signal pins from the printer port.
+
+
+The first cable connections will hook Linux up to one SPI bus, with the
+AVR and a DataFlash chip; and to the AVR reset line. This is all you
+need to reflash the firmware, and the pins are the standard Atmel "ISP"
+connector pins (used also on non-Butterfly AVR boards).
+
+ Signal Butterfly Parport (DB-25)
+ ------ --------- ---------------
+ SCK = J403.PB1/SCK = pin 2/D0
+ RESET = J403.nRST = pin 3/D1
+ VCC = J403.VCC_EXT = pin 8/D6
+ MOSI = J403.PB2/MOSI = pin 9/D7
+ MISO = J403.PB3/MISO = pin 11/S7,nBUSY
+ GND = J403.GND = pin 23/GND
+
+Then to let Linux master that bus to talk to the DataFlash chip, you must
+(a) flash new firmware that disables SPI (set PRR.2, and disable pullups
+by clearing PORTB.[0-3]); (b) configure the mtd_dataflash driver; and
+(c) cable in the chipselect.
+
+ Signal Butterfly Parport (DB-25)
+ ------ --------- ---------------
+ VCC = J400.VCC_EXT = pin 7/D5
+ SELECT = J400.PB0/nSS = pin 17/C3,nSELECT
+ GND = J400.GND = pin 24/GND
+
+The "USI" controller, using J405, can be used for a second SPI bus. That
+would let you talk to the AVR over SPI, running firmware that makes it act
+as an SPI slave, while letting either Linux or the AVR use the DataFlash.
+There are plenty of spare parport pins to wire this one up, such as:
+
+ Signal Butterfly Parport (DB-25)
+ ------ --------- ---------------
+ SCK = J403.PE4/USCK = pin 5/D3
+ MOSI = J403.PE5/DI = pin 6/D4
+ MISO = J403.PE6/DO = pin 12/S5,nPAPEROUT
+ GND = J403.GND = pin 22/GND
+
+ IRQ = J402.PF4 = pin 10/S6,ACK
+ GND = J402.GND(P2) = pin 25/GND
+
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
new file mode 100644
index 000000000000..a5ffba33a351
--- /dev/null
+++ b/Documentation/spi/spi-summary
@@ -0,0 +1,457 @@
+Overview of Linux kernel SPI support
+====================================
+
+02-Dec-2005
+
+What is SPI?
+------------
+The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial
+link used to connect microcontrollers to sensors, memory, and peripherals.
+
+The three signal wires hold a clock (SCLK, often on the order of 10 MHz),
+and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In,
+Slave Out" (MISO) signals. (Other names are also used.) There are four
+clocking modes through which data is exchanged; mode-0 and mode-3 are most
+commonly used. Each clock cycle shifts data out and data in; the clock
+doesn't cycle except when there is data to shift.
+
+SPI masters may use a "chip select" line to activate a given SPI slave
+device, so those three signal wires may be connected to several chips
+in parallel. All SPI slaves support chipselects. Some devices have
+other signals, often including an interrupt to the master.
+
+Unlike serial busses like USB or SMBUS, even low level protocols for
+SPI slave functions are usually not interoperable between vendors
+(except for cases like SPI memory chips).
+
+ - SPI may be used for request/response style device protocols, as with
+ touchscreen sensors and memory chips.
+
+ - It may also be used to stream data in either direction (half duplex),
+ or both of them at the same time (full duplex).
+
+ - Some devices may use eight bit words. Others may different word
+ lengths, such as streams of 12-bit or 20-bit digital samples.
+
+In the same way, SPI slaves will only rarely support any kind of automatic
+discovery/enumeration protocol. The tree of slave devices accessible from
+a given SPI master will normally be set up manually, with configuration
+tables.
+
+SPI is only one of the names used by such four-wire protocols, and
+most controllers have no problem handling "MicroWire" (think of it as
+half-duplex SPI, for request/response protocols), SSP ("Synchronous
+Serial Protocol"), PSP ("Programmable Serial Protocol"), and other
+related protocols.
+
+Microcontrollers often support both master and slave sides of the SPI
+protocol. This document (and Linux) currently only supports the master
+side of SPI interactions.
+
+
+Who uses it? On what kinds of systems?
+---------------------------------------
+Linux developers using SPI are probably writing device drivers for embedded
+systems boards. SPI is used to control external chips, and it is also a
+protocol supported by every MMC or SD memory card. (The older "DataFlash"
+cards, predating MMC cards but using the same connectors and card shape,
+support only SPI.) Some PC hardware uses SPI flash for BIOS code.
+
+SPI slave chips range from digital/analog converters used for analog
+sensors and codecs, to memory, to peripherals like USB controllers
+or Ethernet adapters; and more.
+
+Most systems using SPI will integrate a few devices on a mainboard.
+Some provide SPI links on expansion connectors; in cases where no
+dedicated SPI controller exists, GPIO pins can be used to create a
+low speed "bitbanging" adapter. Very few systems will "hotplug" an SPI
+controller; the reasons to use SPI focus on low cost and simple operation,
+and if dynamic reconfiguration is important, USB will often be a more
+appropriate low-pincount peripheral bus.
+
+Many microcontrollers that can run Linux integrate one or more I/O
+interfaces with SPI modes. Given SPI support, they could use MMC or SD
+cards without needing a special purpose MMC/SD/SDIO controller.
+
+
+How do these driver programming interfaces work?
+------------------------------------------------
+The <linux/spi/spi.h> header file includes kerneldoc, as does the
+main source code, and you should certainly read that. This is just
+an overview, so you get the big picture before the details.
+
+SPI requests always go into I/O queues. Requests for a given SPI device
+are always executed in FIFO order, and complete asynchronously through
+completion callbacks. There are also some simple synchronous wrappers
+for those calls, including ones for common transaction types like writing
+a command and then reading its response.
+
+There are two types of SPI driver, here called:
+
+ Controller drivers ... these are often built in to System-On-Chip
+ processors, and often support both Master and Slave roles.
+ These drivers touch hardware registers and may use DMA.
+ Or they can be PIO bitbangers, needing just GPIO pins.
+
+ Protocol drivers ... these pass messages through the controller
+ driver to communicate with a Slave or Master device on the
+ other side of an SPI link.
+
+So for example one protocol driver might talk to the MTD layer to export
+data to filesystems stored on SPI flash like DataFlash; and others might
+control audio interfaces, present touchscreen sensors as input interfaces,
+or monitor temperature and voltage levels during industrial processing.
+And those might all be sharing the same controller driver.
+
+A "struct spi_device" encapsulates the master-side interface between
+those two types of driver. At this writing, Linux has no slave side
+programming interface.
+
+There is a minimal core of SPI programming interfaces, focussing on
+using driver model to connect controller and protocol drivers using
+device tables provided by board specific initialization code. SPI
+shows up in sysfs in several locations:
+
+ /sys/devices/.../CTLR/spiB.C ... spi_device for on bus "B",
+ chipselect C, accessed through CTLR.
+
+ /sys/devices/.../CTLR/spiB.C/modalias ... identifies the driver
+ that should be used with this device (for hotplug/coldplug)
+
+ /sys/bus/spi/devices/spiB.C ... symlink to the physical
+ spiB-C device
+
+ /sys/bus/spi/drivers/D ... driver for one or more spi*.* devices
+
+ /sys/class/spi_master/spiB ... class device for the controller
+ managing bus "B". All the spiB.* devices share the same
+ physical SPI bus segment, with SCLK, MOSI, and MISO.
+
+
+How does board-specific init code declare SPI devices?
+------------------------------------------------------
+Linux needs several kinds of information to properly configure SPI devices.
+That information is normally provided by board-specific code, even for
+chips that do support some of automated discovery/enumeration.
+
+DECLARE CONTROLLERS
+
+The first kind of information is a list of what SPI controllers exist.
+For System-on-Chip (SOC) based boards, these will usually be platform
+devices, and the controller may need some platform_data in order to
+operate properly. The "struct platform_device" will include resources
+like the physical address of the controller's first register and its IRQ.
+
+Platforms will often abstract the "register SPI controller" operation,
+maybe coupling it with code to initialize pin configurations, so that
+the arch/.../mach-*/board-*.c files for several boards can all share the
+same basic controller setup code. This is because most SOCs have several
+SPI-capable controllers, and only the ones actually usable on a given
+board should normally be set up and registered.
+
+So for example arch/.../mach-*/board-*.c files might have code like:
+
+ #include <asm/arch/spi.h> /* for mysoc_spi_data */
+
+ /* if your mach-* infrastructure doesn't support kernels that can
+ * run on multiple boards, pdata wouldn't benefit from "__init".
+ */
+ static struct mysoc_spi_data __init pdata = { ... };
+
+ static __init board_init(void)
+ {
+ ...
+ /* this board only uses SPI controller #2 */
+ mysoc_register_spi(2, &pdata);
+ ...
+ }
+
+And SOC-specific utility code might look something like:
+
+ #include <asm/arch/spi.h>
+
+ static struct platform_device spi2 = { ... };
+
+ void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata)
+ {
+ struct mysoc_spi_data *pdata2;
+
+ pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL);
+ *pdata2 = pdata;
+ ...
+ if (n == 2) {
+ spi2->dev.platform_data = pdata2;
+ register_platform_device(&spi2);
+
+ /* also: set up pin modes so the spi2 signals are
+ * visible on the relevant pins ... bootloaders on
+ * production boards may already have done this, but
+ * developer boards will often need Linux to do it.
+ */
+ }
+ ...
+ }
+
+Notice how the platform_data for boards may be different, even if the
+same SOC controller is used. For example, on one board SPI might use
+an external clock, where another derives the SPI clock from current
+settings of some master clock.
+
+
+DECLARE SLAVE DEVICES
+
+The second kind of information is a list of what SPI slave devices exist
+on the target board, often with some board-specific data needed for the
+driver to work correctly.
+
+Normally your arch/.../mach-*/board-*.c files would provide a small table
+listing the SPI devices on each board. (This would typically be only a
+small handful.) That might look like:
+
+ static struct ads7846_platform_data ads_info = {
+ .vref_delay_usecs = 100,
+ .x_plate_ohms = 580,
+ .y_plate_ohms = 410,
+ };
+
+ static struct spi_board_info spi_board_info[] __initdata = {
+ {
+ .modalias = "ads7846",
+ .platform_data = &ads_info,
+ .mode = SPI_MODE_0,
+ .irq = GPIO_IRQ(31),
+ .max_speed_hz = 120000 /* max sample rate at 3V */ * 16,
+ .bus_num = 1,
+ .chip_select = 0,
+ },
+ };
+
+Again, notice how board-specific information is provided; each chip may need
+several types. This example shows generic constraints like the fastest SPI
+clock to allow (a function of board voltage in this case) or how an IRQ pin
+is wired, plus chip-specific constraints like an important delay that's
+changed by the capacitance at one pin.
+
+(There's also "controller_data", information that may be useful to the
+controller driver. An example would be peripheral-specific DMA tuning
+data or chipselect callbacks. This is stored in spi_device later.)
+
+The board_info should provide enough information to let the system work
+without the chip's driver being loaded. The most troublesome aspect of
+that is likely the SPI_CS_HIGH bit in the spi_device.mode field, since
+sharing a bus with a device that interprets chipselect "backwards" is
+not possible.
+
+Then your board initialization code would register that table with the SPI
+infrastructure, so that it's available later when the SPI master controller
+driver is registered:
+
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
+Like with other static board-specific setup, you won't unregister those.
+
+The widely used "card" style computers bundle memory, cpu, and little else
+onto a card that's maybe just thirty square centimeters. On such systems,
+your arch/.../mach-.../board-*.c file would primarily provide information
+about the devices on the mainboard into which such a card is plugged. That
+certainly includes SPI devices hooked up through the card connectors!
+
+
+NON-STATIC CONFIGURATIONS
+
+Developer boards often play by different rules than product boards, and one
+example is the potential need to hotplug SPI devices and/or controllers.
+
+For those cases you might need to use use spi_busnum_to_master() to look
+up the spi bus master, and will likely need spi_new_device() to provide the
+board info based on the board that was hotplugged. Of course, you'd later
+call at least spi_unregister_device() when that board is removed.
+
+When Linux includes support for MMC/SD/SDIO/DataFlash cards through SPI, those
+configurations will also be dynamic. Fortunately, those devices all support
+basic device identification probes, so that support should hotplug normally.
+
+
+How do I write an "SPI Protocol Driver"?
+----------------------------------------
+All SPI drivers are currently kernel drivers. A userspace driver API
+would just be another kernel driver, probably offering some lowlevel
+access through aio_read(), aio_write(), and ioctl() calls and using the
+standard userspace sysfs mechanisms to bind to a given SPI device.
+
+SPI protocol drivers somewhat resemble platform device drivers:
+
+ static struct spi_driver CHIP_driver = {
+ .driver = {
+ .name = "CHIP",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = CHIP_probe,
+ .remove = __devexit_p(CHIP_remove),
+ .suspend = CHIP_suspend,
+ .resume = CHIP_resume,
+ };
+
+The driver core will autmatically attempt to bind this driver to any SPI
+device whose board_info gave a modalias of "CHIP". Your probe() code
+might look like this unless you're creating a class_device:
+
+ static int __devinit CHIP_probe(struct spi_device *spi)
+ {
+ struct CHIP *chip;
+ struct CHIP_platform_data *pdata;
+
+ /* assuming the driver requires board-specific data: */
+ pdata = &spi->dev.platform_data;
+ if (!pdata)
+ return -ENODEV;
+
+ /* get memory for driver's per-chip state */
+ chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+ dev_set_drvdata(&spi->dev, chip);
+
+ ... etc
+ return 0;
+ }
+
+As soon as it enters probe(), the driver may issue I/O requests to
+the SPI device using "struct spi_message". When remove() returns,
+the driver guarantees that it won't submit any more such messages.
+
+ - An spi_message is a sequence of of protocol operations, executed
+ as one atomic sequence. SPI driver controls include:
+
+ + when bidirectional reads and writes start ... by how its
+ sequence of spi_transfer requests is arranged;
+
+ + optionally defining short delays after transfers ... using
+ the spi_transfer.delay_usecs setting;
+
+ + whether the chipselect becomes inactive after a transfer and
+ any delay ... by using the spi_transfer.cs_change flag;
+
+ + hinting whether the next message is likely to go to this same
+ device ... using the spi_transfer.cs_change flag on the last
+ transfer in that atomic group, and potentially saving costs
+ for chip deselect and select operations.
+
+ - Follow standard kernel rules, and provide DMA-safe buffers in
+ your messages. That way controller drivers using DMA aren't forced
+ to make extra copies unless the hardware requires it (e.g. working
+ around hardware errata that force the use of bounce buffering).
+
+ If standard dma_map_single() handling of these buffers is inappropriate,
+ you can use spi_message.is_dma_mapped to tell the controller driver
+ that you've already provided the relevant DMA addresses.
+
+ - The basic I/O primitive is spi_async(). Async requests may be
+ issued in any context (irq handler, task, etc) and completion
+ is reported using a callback provided with the message.
+ After any detected error, the chip is deselected and processing
+ of that spi_message is aborted.
+
+ - There are also synchronous wrappers like spi_sync(), and wrappers
+ like spi_read(), spi_write(), and spi_write_then_read(). These
+ may be issued only in contexts that may sleep, and they're all
+ clean (and small, and "optional") layers over spi_async().
+
+ - The spi_write_then_read() call, and convenience wrappers around
+ it, should only be used with small amounts of data where the
+ cost of an extra copy may be ignored. It's designed to support
+ common RPC-style requests, such as writing an eight bit command
+ and reading a sixteen bit response -- spi_w8r16() being one its
+ wrappers, doing exactly that.
+
+Some drivers may need to modify spi_device characteristics like the
+transfer mode, wordsize, or clock rate. This is done with spi_setup(),
+which would normally be called from probe() before the first I/O is
+done to the device.
+
+While "spi_device" would be the bottom boundary of the driver, the
+upper boundaries might include sysfs (especially for sensor readings),
+the input layer, ALSA, networking, MTD, the character device framework,
+or other Linux subsystems.
+
+Note that there are two types of memory your driver must manage as part
+of interacting with SPI devices.
+
+ - I/O buffers use the usual Linux rules, and must be DMA-safe.
+ You'd normally allocate them from the heap or free page pool.
+ Don't use the stack, or anything that's declared "static".
+
+ - The spi_message and spi_transfer metadata used to glue those
+ I/O buffers into a group of protocol transactions. These can
+ be allocated anywhere it's convenient, including as part of
+ other allocate-once driver data structures. Zero-init these.
+
+If you like, spi_message_alloc() and spi_message_free() convenience
+routines are available to allocate and zero-initialize an spi_message
+with several transfers.
+
+
+How do I write an "SPI Master Controller Driver"?
+-------------------------------------------------
+An SPI controller will probably be registered on the platform_bus; write
+a driver to bind to the device, whichever bus is involved.
+
+The main task of this type of driver is to provide an "spi_master".
+Use spi_alloc_master() to allocate the master, and class_get_devdata()
+to get the driver-private data allocated for that device.
+
+ struct spi_master *master;
+ struct CONTROLLER *c;
+
+ master = spi_alloc_master(dev, sizeof *c);
+ if (!master)
+ return -ENODEV;
+
+ c = class_get_devdata(&master->cdev);
+
+The driver will initialize the fields of that spi_master, including the
+bus number (maybe the same as the platform device ID) and three methods
+used to interact with the SPI core and SPI protocol drivers. It will
+also initialize its own internal state.
+
+ master->setup(struct spi_device *spi)
+ This sets up the device clock rate, SPI mode, and word sizes.
+ Drivers may change the defaults provided by board_info, and then
+ call spi_setup(spi) to invoke this routine. It may sleep.
+
+ master->transfer(struct spi_device *spi, struct spi_message *message)
+ This must not sleep. Its responsibility is arrange that the
+ transfer happens and its complete() callback is issued; the two
+ will normally happen later, after other transfers complete.
+
+ master->cleanup(struct spi_device *spi)
+ Your controller driver may use spi_device.controller_state to hold
+ state it dynamically associates with that device. If you do that,
+ be sure to provide the cleanup() method to free that state.
+
+The bulk of the driver will be managing the I/O queue fed by transfer().
+
+That queue could be purely conceptual. For example, a driver used only
+for low-frequency sensor acess might be fine using synchronous PIO.
+
+But the queue will probably be very real, using message->queue, PIO,
+often DMA (especially if the root filesystem is in SPI flash), and
+execution contexts like IRQ handlers, tasklets, or workqueues (such
+as keventd). Your driver can be as fancy, or as simple, as you need.
+
+
+THANKS TO
+---------
+Contributors to Linux-SPI discussions include (in alphabetical order,
+by last name):
+
+David Brownell
+Russell King
+Dmitry Pervushin
+Stephen Street
+Mark Underwood
+Andrew Victor
+Vitaly Wool
+
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 2c81305090df..e409e5d07486 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -1,58 +1,56 @@
Everything you ever wanted to know about Linux 2.6 -stable releases.
-Rules on what kind of patches are accepted, and what ones are not, into
-the "-stable" tree:
+Rules on what kind of patches are accepted, and which ones are not, into the
+"-stable" tree:
- It must be obviously correct and tested.
- - It can not bigger than 100 lines, with context.
+ - It can not be bigger than 100 lines, with context.
- It must fix only one thing.
- It must fix a real bug that bothers people (not a, "This could be a
- problem..." type thing.)
+ problem..." type thing).
- It must fix a problem that causes a build error (but not for things
marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
- security issue, or some "oh, that's not good" issue. In short,
- something critical.
- - No "theoretical race condition" issues, unless an explanation of how
- the race can be exploited.
+ security issue, or some "oh, that's not good" issue. In short, something
+ critical.
+ - No "theoretical race condition" issues, unless an explanation of how the
+ race can be exploited is also provided.
- It can not contain any "trivial" fixes in it (spelling changes,
- whitespace cleanups, etc.)
+ whitespace cleanups, etc).
- It must be accepted by the relevant subsystem maintainer.
- - It must follow Documentation/SubmittingPatches rules.
+ - It must follow the Documentation/SubmittingPatches rules.
Procedure for submitting patches to the -stable tree:
- Send the patch, after verifying that it follows the above rules, to
stable@kernel.org.
- - The sender will receive an ack when the patch has been accepted into
- the queue, or a nak if the patch is rejected. This response might
- take a few days, according to the developer's schedules.
- - If accepted, the patch will be added to the -stable queue, for review
- by other developers.
+ - The sender will receive an ACK when the patch has been accepted into the
+ queue, or a NAK if the patch is rejected. This response might take a few
+ days, according to the developer's schedules.
+ - If accepted, the patch will be added to the -stable queue, for review by
+ other developers.
- Security patches should not be sent to this alias, but instead to the
- documented security@kernel.org.
+ documented security@kernel.org address.
Review cycle:
- - When the -stable maintainers decide for a review cycle, the patches
- will be sent to the review committee, and the maintainer of the
- affected area of the patch (unless the submitter is the maintainer of
- the area) and CC: to the linux-kernel mailing list.
- - The review committee has 48 hours in which to ack or nak the patch.
+ - When the -stable maintainers decide for a review cycle, the patches will be
+ sent to the review committee, and the maintainer of the affected area of
+ the patch (unless the submitter is the maintainer of the area) and CC: to
+ the linux-kernel mailing list.
+ - The review committee has 48 hours in which to ACK or NAK the patch.
- If the patch is rejected by a member of the committee, or linux-kernel
- members object to the patch, bringing up issues that the maintainers
- and members did not realize, the patch will be dropped from the
- queue.
- - At the end of the review cycle, the acked patches will be added to
- the latest -stable release, and a new -stable release will happen.
- - Security patches will be accepted into the -stable tree directly from
- the security kernel team, and not go through the normal review cycle.
+ members object to the patch, bringing up issues that the maintainers and
+ members did not realize, the patch will be dropped from the queue.
+ - At the end of the review cycle, the ACKed patches will be added to the
+ latest -stable release, and a new -stable release will happen.
+ - Security patches will be accepted into the -stable tree directly from the
+ security kernel team, and not go through the normal review cycle.
Contact the kernel security team for more details on this procedure.
Review committe:
- - This will be made up of a number of kernel developers who have
- volunteered for this task, and a few that haven't.
-
+ - This is made up of a number of kernel developers who have volunteered for
+ this task, and a few that haven't.
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 2f1aae32a5d9..391dd64363e7 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -26,12 +26,14 @@ Currently, these files are in /proc/sys/vm:
- min_free_kbytes
- laptop_mode
- block_dump
+- drop-caches
+- zone_reclaim_mode
==============================================================
dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
-block_dump, swap_token_timeout:
+block_dump, swap_token_timeout, drop-caches:
See Documentation/filesystems/proc.txt
@@ -102,3 +104,37 @@ This is used to force the Linux VM to keep a minimum number
of kilobytes free. The VM uses this number to compute a pages_min
value for each lowmem zone in the system. Each lowmem zone gets
a number of reserved free pages based proportionally on its size.
+
+==============================================================
+
+percpu_pagelist_fraction
+
+This is the fraction of pages at most (high mark pcp->high) in each zone that
+are allocated for each per cpu page list. The min value for this is 8. It
+means that we don't allow more than 1/8th of pages in each zone to be
+allocated in any single per_cpu_pagelist. This entry only changes the value
+of hot per cpu pagelists. User can specify a number like 100 to allocate
+1/100th of each zone to each per cpu page list.
+
+The batch value of each per cpu pagelist is also updated as a result. It is
+set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8)
+
+The initial value is zero. Kernel does not use this value at boot time to set
+the high water marks for each per cpu page list.
+
+===============================================================
+
+zone_reclaim_mode:
+
+This is set during bootup to 1 if it is determined that pages from
+remote zones will cause a significant performance reduction. The
+page allocator will then reclaim easily reusable pages (those page
+cache pages that are currently not used) before going off node.
+
+The user can override this setting. It may be beneficial to switch
+off zone reclaim if the system is used for a file server and all
+of memory should be used for caching files from disk.
+
+It may be beneficial to switch this on if one wants to do zone
+reclaim regardless of the numa distances in the system.
+
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index baf17b381588..ad0bedf678b3 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -202,17 +202,13 @@ you must call __handle_sysrq_nolock instead.
* I have more questions, who can I ask?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-You may feel free to send email to myrdraal@deathsdoor.com, and I will
-respond as soon as possible.
- -Myrdraal
-
And I'll answer any questions about the registration system you got, also
responding as soon as possible.
-Crutcher
* Credits
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Written by Mydraal <myrdraal@deathsdoor.com>
+Written by Mydraal <vulpyne@vulpyne.net>
Updated by Adam Sulmicki <adam@cfar.umd.edu>
Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index 330246ac80f8..b72706c58a44 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -141,3 +141,5 @@
140 -> Osprey 440 [0070:ff07]
141 -> Asound Skyeye PCTV
142 -> Sabrent TV-FM (bttv version)
+143 -> Hauppauge ImpactVCB (bt878) [0070:13eb]
+144 -> MagicTV
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index a1017d1a85d4..56e194f1a0b0 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -16,10 +16,10 @@
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
16 -> KWorld LTV883RF
17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810]
- 18 -> Hauppauge Nova-T DVB-T [0070:9002]
+ 18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001]
19 -> Conexant DVB-T reference design [14f1:0187]
20 -> Provideo PV259 [1540:2580]
- 21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10]
+ 21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10,18ac:db11]
22 -> pcHDTV HD3000 HDTV [7063:3000]
23 -> digitalnow DNTV Live! DVB-T [17de:a8a6]
24 -> Hauppauge WinTV 28xxx (Roslyn) models [0070:2801]
@@ -35,3 +35,11 @@
34 -> ATI HDTV Wonder [1002:a101]
35 -> WinFast DTV1000-T [107d:665f]
36 -> AVerTV 303 (M126) [1461:000a]
+ 37 -> Hauppauge Nova-S-Plus DVB-S [0070:9201,0070:9202]
+ 38 -> Hauppauge Nova-SE2 DVB-S [0070:9200]
+ 39 -> KWorld DVB-S 100 [17de:08b2]
+ 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402]
+ 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802]
+ 42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025]
+ 43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1]
+ 44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index efb708ec116a..cb3a59bbeb17 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -56,7 +56,7 @@
55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306]
56 -> Avermedia AVerTV 307 [1461:a70a]
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
- 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0370,1421:1370]
+ 58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370]
59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502]
61 -> Philips TOUGH DVB-T reference design [1131:2004]
@@ -81,4 +81,5 @@
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
82 -> MSI TV@Anywhere plus [1462:6231]
-
+ 83 -> Terratec Cinergy 250 PCI TV [153b:1160]
+ 84 -> LifeView FlyDVB Trio [5168:0319]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index 9d6544ea9f41..f6d0cf7b7922 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -40,7 +40,7 @@ tuner=38 - Philips PAL/SECAM multi (FM1216ME MK3)
tuner=39 - LG NTSC (newer TAPC series)
tuner=40 - HITACHI V7-J180AT
tuner=41 - Philips PAL_MK (FI1216 MK)
-tuner=42 - Philips 1236D ATSC/NTSC daul in
+tuner=42 - Philips 1236D ATSC/NTSC dual in
tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
tuner=45 - Microtune 4049 FM5
@@ -50,7 +50,7 @@ tuner=48 - Tenna TNF 8831 BGFF)
tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
tuner=50 - TCL 2002N
tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
-tuner=52 - Thomson DDT 7610 (ATSC/NTSC)
+tuner=52 - Thomson DTT 7610 (ATSC/NTSC)
tuner=53 - Philips FQ1286
tuner=54 - tda8290+75
tuner=55 - TCL 2002MB
@@ -58,7 +58,7 @@ tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
tuner=57 - Philips FQ1236A MK4
tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF
tuner=59 - Ymec TVision TVF-5533MF
-tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
+tuner=60 - Thomson DTT 761X (ATSC/NTSC)
tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
tuner=62 - Philips TEA5767HN FM Radio
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
@@ -68,3 +68,4 @@ tuner=66 - LG NTSC (TALN mini series)
tuner=67 - Philips TD1316 Hybrid Tuner
tuner=68 - Philips TUV1236D ATSC/NTSC dual in
tuner=69 - Tena TNF 5335 MF
+tuner=70 - Samsung TCPN 2121P30A
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index e566affeed7f..9c5fc15d03d1 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -125,7 +125,7 @@ SMP
cpumask=MASK only use cpus with bits set in mask
additional_cpus=NUM Allow NUM more CPUs for hotplug
- (defaults are specified by the BIOS or half the available CPUs)
+ (defaults are specified by the BIOS, see Documentation/x86_64/cpu-hotplug-spec)
NUMA
@@ -198,6 +198,6 @@ Debugging
Misc
- noreplacement Don't replace instructions with more appropiate ones
+ noreplacement Don't replace instructions with more appropriate ones
for the CPU. This may be useful on asymmetric MP systems
where some CPU have less capabilities than the others.
diff --git a/Documentation/x86_64/cpu-hotplug-spec b/Documentation/x86_64/cpu-hotplug-spec
new file mode 100644
index 000000000000..5c0fa345e556
--- /dev/null
+++ b/Documentation/x86_64/cpu-hotplug-spec
@@ -0,0 +1,21 @@
+Firmware support for CPU hotplug under Linux/x86-64
+---------------------------------------------------
+
+Linux/x86-64 supports CPU hotplug now. For various reasons Linux wants to
+know in advance boot time the maximum number of CPUs that could be plugged
+into the system. ACPI 3.0 currently has no official way to supply
+this information from the firmware to the operating system.
+
+In ACPI each CPU needs an LAPIC object in the MADT table (5.2.11.5 in the
+ACPI 3.0 specification). ACPI already has the concept of disabled LAPIC
+objects by setting the Enabled bit in the LAPIC object to zero.
+
+For CPU hotplug Linux/x86-64 expects now that any possible future hotpluggable
+CPU is already available in the MADT. If the CPU is not available yet
+it should have its LAPIC Enabled bit set to 0. Linux will use the number
+of disabled LAPICs to compute the maximum number of future CPUs.
+
+In the worst case the user can overwrite this choice using a command line
+option (additional_cpus=...), but it is recommended to supply the correct
+number (or a reasonable approximation of it, with erring towards more not less)
+in the MADT to avoid manual configuration.
diff --git a/Kbuild b/Kbuild
index 79003918f37f..95d6a00bace0 100644
--- a/Kbuild
+++ b/Kbuild
@@ -22,8 +22,6 @@ 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__"; \
@@ -34,7 +32,7 @@ define cmd_offsets
echo " *"; \
echo " */"; \
echo ""; \
- sed -ne $(sed-y); \
+ sed -ne $(sed-y) $<; \
echo ""; \
echo "#endif" ) > $@
endef
@@ -45,5 +43,6 @@ arch/$(ARCH)/kernel/asm-offsets.s: arch/$(ARCH)/kernel/asm-offsets.c FORCE
$(call if_changed_dep,cc_s_c)
$(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
+ $(Q)mkdir -p $(dir $@)
$(call cmd,offsets)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6af683025ae0..3f8a90ac47d7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -182,7 +182,7 @@ S: Supported
ACPI
P: Len Brown
M: len.brown@intel.com
-L: acpi-devel@lists.sourceforge.net
+L: linux-acpi@vger.kernel.org
W: http://acpi.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Maintained
@@ -258,6 +258,13 @@ P: Ivan Kokshaysky
M: ink@jurassic.park.msu.ru
S: Maintained for 2.4; PCI support for 2.6.
+AMD GEODE PROCESSOR/CHIPSET SUPPORT
+P: Jordan Crouse
+M: info-linux@geode.amd.com
+L: info-linux@geode.amd.com
+W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
+S: Supported
+
APM DRIVER
P: Stephen Rothwell
M: sfr@canb.auug.org.au
@@ -539,21 +546,20 @@ W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
S: Maintained
-BUSLOGIC SCSI DRIVER
-P: Leonard N. Zubkoff
-M: Leonard N. Zubkoff <lnz@dandelion.com>
-L: linux-scsi@vger.kernel.org
-W: http://www.dandelion.com/Linux/
-S: Maintained
-
COMMON INTERNET FILE SYSTEM (CIFS)
P: Steve French
M: sfrench@samba.org
+L: linux-cifs-client@lists.samba.org
L: samba-technical@lists.samba.org
W: http://us1.samba.org/samba/Linux_CIFS_client.html
T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
S: Supported
+CONFIGFS
+P: Joel Becker
+M: Joel Becker <joel.becker@oracle.com>
+S: Supported
+
CIRRUS LOGIC GENERIC FBDEV DRIVER
P: Jeff Garzik
M: jgarzik@pobox.com
@@ -650,6 +656,11 @@ L: linux-crypto@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
S: Maintained
+CS5535 Audio ALSA driver
+P: Jaya Kumar
+M: jayakumar.alsa@gmail.com
+S: Maintained
+
CYBERPRO FB DRIVER
P: Russell King
M: rmk@arm.linux.org.uk
@@ -679,13 +690,6 @@ M: pc300@cyclades.com
W: http://www.cyclades.com/
S: Supported
-DAC960 RAID CONTROLLER DRIVER
-P: Dave Olien
-M dmo@osdl.org
-W: http://www.osdl.org/archive/dmo/DAC960
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
DAMA SLAVE for AX.25
P: Joerg Reuter
M: jreuter@yaina.de
@@ -801,6 +805,7 @@ S: Maintained
DOCBOOK FOR DOCUMENTATION
P: Martin Waitz
M: tali@admingilde.org
+T: git http://tali.admingilde.org/git/linux-docbook.git
S: Maintained
DOUBLETALK DRIVER
@@ -862,6 +867,15 @@ L: ebtables-devel@lists.sourceforge.net
W: http://ebtables.sourceforge.net/
S: Maintained
+EDAC-CORE
+P: Doug Thompson
+M: norsk5@xmission.com, dthompson@linuxnetworx.com
+P: Dave Peterson
+M: dsp@llnl.gov, dave_peterson@pobox.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
+
EEPRO100 NETWORK DRIVER
P: Andrey V. Savochkin
M: saw@saw.sw.com.sg
@@ -917,7 +931,6 @@ S: Maintained
FARSYNC SYNCHRONOUS DRIVER
P: Kevin Curtis
M: kevin.curtis@farsite.co.uk
-M: kevin.curtis@farsite.co.uk
W: http://www.farsite.co.uk/
S: Supported
@@ -1225,7 +1238,7 @@ IEEE 1394 SUBSYSTEM
P: Ben Collins
M: bcollins@debian.org
P: Jody McIntyre
-M: scjody@steamballoon.com
+M: scjody@modernduck.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
T: git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
@@ -1235,14 +1248,14 @@ IEEE 1394 OHCI DRIVER
P: Ben Collins
M: bcollins@debian.org
P: Jody McIntyre
-M: scjody@steamballoon.com
+M: scjody@modernduck.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
IEEE 1394 PCILYNX DRIVER
P: Jody McIntyre
-M: scjody@steamballoon.com
+M: scjody@modernduck.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
@@ -1297,6 +1310,12 @@ M: ttb@tentacle.dhs.org and rml@novell.com
L: linux-kernel@vger.kernel.org
S: Maintained
+INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
+P: Sylvain Meyer
+M: sylvain.meyer@worldonline.fr
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
+
INTEL 810/815 FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@pol.net
@@ -1388,7 +1407,7 @@ IRDA SUBSYSTEM
P: Jean Tourrilhes
L: irda-users@lists.sourceforge.net (subscribers-only)
W: http://irda.sourceforge.net/
-S: Maintained
+S: Odd Fixes
ISAPNP
P: Jaroslav Kysela
@@ -1465,7 +1484,6 @@ P: Several
L: kernel-janitors@osdl.org
W: http://www.kerneljanitors.org/
W: http://sf.net/projects/kernel-janitor/
-W: http://developer.osdl.org/rddunlap/kj-patches/
S: Maintained
KERNEL NFSD
@@ -1476,17 +1494,11 @@ W: http://nfs.sourceforge.net/
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
S: Maintained
-KERNEL EVENT LAYER (KOBJECT_UEVENT)
-P: Robert Love
-M: rml@novell.com
-L: linux-kernel@vger.kernel.org
-S: Maintained
-
KEXEC
P: Eric Biederman
P: Randy Dunlap
M: ebiederm@xmission.com
-M: rddunlap@osdl.org
+M: rdunlap@xenotime.net
W: http://www.xmission.com/~ebiederm/files/kexec/
L: linux-kernel@vger.kernel.org
L: fastboot@osdl.org
@@ -1693,12 +1705,13 @@ M: mtk-manpages@gmx.net
W: ftp://ftp.kernel.org/pub/linux/docs/manpages
S: Maintained
-MARVELL MV64340 ETHERNET DRIVER
+MARVELL MV643XX ETHERNET DRIVER
+P: Dale Farnsworth
+M: dale@farnsworth.org
P: Manish Lachwani
-M: Manish_Lachwani@pmc-sierra.com
-L: linux-mips@linux-mips.org
+M: mlachwani@mvista.com
L: netdev@vger.kernel.org
-S: Supported
+S: Odd Fixes for 2.4; Maintained for 2.6.
MATROX FRAMEBUFFER DRIVER
P: Petr Vandrovec
@@ -1839,7 +1852,14 @@ M: yoshfuji@linux-ipv6.org
P: Patrick McHardy
M: kaber@coreworks.de
L: netdev@vger.kernel.org
-T: git kernel.org:/pub/scm/linux/kernel/davem/net-2.6.git
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git
+S: Maintained
+
+NETWORKING [WIRELESS]
+P: John W. Linville
+M: linville@tuxdriver.com
+L: netdev@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
IPVS
@@ -1894,11 +1914,20 @@ W: http://linux-ntfs.sf.net/
T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
S: Maintained
-NVIDIA (RIVA) FRAMEBUFFER DRIVER
-P: Ani Joshi
-M: ajoshi@shell.unixbox.com
-L: linux-nvidia@lists.surfsouth.com
-S: Maintained
+NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
+P: Antonino Daplas
+M: adaplas@pol.net
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
+
+ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
+P: Mark Fasheh
+M: mark.fasheh@oracle.com
+P: Kurt Hackel
+M: kurt.hackel@oracle.com
+L: ocfs2-devel@oss.oracle.com
+W: http://oss.oracle.com/projects/ocfs2/
+S: Supported
OLYMPIC NETWORK DRIVER
P: Peter De Shrijver
@@ -1984,6 +2013,13 @@ M: hch@infradead.org
L: linux-abi-devel@lists.sourceforge.net
S: Maintained
+PCI ERROR RECOVERY
+P: Linas Vepstas
+M: linas@austin.ibm.com
+L: linux-kernel@vger.kernel.org
+L: linux-pci@atrey.karlin.mff.cuni.cz
+S: Supported
+
PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES)
P: Thomas Sailer
M: sailer@ife.ee.ethz.ch
@@ -2042,7 +2078,7 @@ S: Maintained
POSIX CLOCKS and TIMERS
P: George Anzinger
M: george@mvista.com
-L: netdev@vger.kernel.org
+L: linux-kernel@vger.kernel.org
S: Supported
POWERPC 4xx EMAC DRIVER
@@ -2177,6 +2213,12 @@ L: rtl@rtlinux.org
W: www.rtlinux.org
S: Maintained
+S3 SAVAGE FRAMEBUFFER DRIVER
+P: Antonino Daplas
+M: adaplas@pol.net
+L: linux-fbdev-devel@lists.sourceforge.net
+S: Maintained
+
S390
P: Martin Schwidefsky
M: schwidefsky@de.ibm.com
@@ -2348,13 +2390,6 @@ P: Nicolas Pitre
M: nico@cam.org
S: Maintained
-SNA NETWORK LAYER
-P: Jay Schulist
-M: jschlst@samba.org
-L: linux-sna@turbolinux.com
-W: http://www.linux-sna.org
-S: Supported
-
SOFTWARE RAID (Multiple Disks) SUPPORT
P: Ingo Molnar
M: mingo@redhat.com
@@ -2476,7 +2511,7 @@ P: Paul Mundt
M: lethal@linux-sh.org
P: Kazumoto Kojima
M: kkojima@rr.iij4u.or.jp
-L: linux-sh@m17n.org
+L: linuxsh-dev@lists.sourceforge.net
W: http://www.linux-sh.org
W: http://www.m17n.org/linux-sh/
W: http://www.rr.iij4u.or.jp/~kkojima/linux-sh4.html
@@ -2515,6 +2550,19 @@ P: Romain Lievin
M: roms@lpg.ticalc.org
S: Maintained
+TIPC NETWORK LAYER
+P: Per Liden
+M: per.liden@ericsson.com
+P: Jon Maloy
+M: jon.maloy@ericsson.com
+P: Allan Stephens
+M: allan.stephens@windriver.com
+L: tipc-discussion@lists.sourceforge.net
+W: http://tipc.sourceforge.net/
+W: http://tipc.cslab.ericsson.net/
+T: git tipc.cslab.ericsson.net:/pub/git/tipc.git
+S: Maintained
+
TLAN NETWORK DRIVER
P: Samuel Chessman
M: chessman@tux.org
@@ -2587,7 +2635,6 @@ S: Maintained
UDF FILESYSTEM
P: Ben Fennema
M: bfennema@falcon.csc.calpoly.edu
-L: linux_udf@hpesjro.fc.hp.com
W: http://linux-udf.sourceforge.net
S: Maintained
@@ -2640,6 +2687,12 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
+USB ISP116X DRIVER
+P: Olav Kongas
+M: ok@artecdesign.ee
+L: linux-usb-devel@lists.sourceforge.net
+S: Maintained
+
USB KAWASAKI LSI DRIVER
P: Oliver Neukum
M: oliver@neukum.name
@@ -2651,7 +2704,7 @@ USB MASS STORAGE DRIVER
P: Matthew Dharm
M: mdharm-usb@one-eyed-alien.net
L: linux-usb-users@lists.sourceforge.net
-L: linux-usb-devel@lists.sourceforge.net
+L: usb-storage@lists.one-eyed-alien.net
S: Maintained
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
@@ -2899,6 +2952,12 @@ W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
S: Maintained
+VT8231 HARDWARE MONITOR DRIVER
+P: Roger Lucas
+M: roger@planbit.co.uk
+L: lm-sensors@lm-sensors.org
+S: Maintained
+
W1 DALLAS'S 1-WIRE BUS
P: Evgeniy Polyakov
M: johnpol@2ka.mipt.ru
@@ -2925,6 +2984,12 @@ M: dm@sangoma.com
W: http://www.sangoma.com
S: Supported
+WATCHDOG DEVICE DRIVERS
+P: Wim Van Sebroeck
+M: wim@iguana.be
+T: git kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git
+S: Maintained
+
WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
P: Jean Tourrilhes
M: jt@hpl.hp.com
diff --git a/Makefile b/Makefile
index 497884d3d556..252a659896f3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 15
-EXTRAVERSION =
+SUBLEVEL = 16
+EXTRAVERSION =-rc1
NAME=Sliding Snow Leopard
# *DOCUMENTATION*
@@ -106,12 +106,13 @@ KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
$(error output directory "$(saved-output)" does not exist))
-.PHONY: $(MAKECMDGOALS)
+.PHONY: $(MAKECMDGOALS) cdbuilddir
+$(MAKECMDGOALS) _all: cdbuilddir
-$(filter-out _all,$(MAKECMDGOALS)) _all:
+cdbuilddir:
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
KBUILD_SRC=$(CURDIR) \
- KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
+ KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $(MAKECMDGOALS)
# Leave processing to above invocation of make
skip-makefile := 1
@@ -141,24 +142,6 @@ VPATH := $(srctree)
export srctree objtree VPATH TOPDIR
-nullstring :=
-space := $(nullstring) # end of line
-
-# Take the contents of any files called localversion* and the config
-# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be
-# careful not to include files twice if building in the source
-# directory. LOCALVERSION from the command line override all of this
-
-localver := $(objtree)/localversion* $(srctree)/localversion*
-localver := $(sort $(wildcard $(localver)))
-# skip backup files (containing '~')
-localver := $(foreach f, $(localver), $(if $(findstring ~, $(f)),,$(f)))
-
-LOCALVERSION = $(subst $(space),, \
- $(shell cat /dev/null $(localver)) \
- $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-
-KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
# SUBARCH tells the usermode build what the underlying arch is. That is set
# first, and if a usermode build is happening, the "ARCH=um" on the command
@@ -169,7 +152,7 @@ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
- -e s/ppc64/powerpc/ )
+ -e s/ppc.*/powerpc/ )
# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
@@ -251,7 +234,7 @@ export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
# If it is set to "silent_", nothing wil be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
-# A simple variant is to prefix commands with $(Q) - that's usefull
+# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
# $(Q)ln $@ :<
@@ -280,16 +263,19 @@ export quiet Q KBUILD_VERBOSE
# cc support functions to be used (only) in arch/$(ARCH)/Makefile
# See documentation in Documentation/kbuild/makefiles.txt
+# as-option
+# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
+
+as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
+ -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
+ else echo "$(2)"; fi ;)
+
# cc-option
# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-# For backward compatibility
-check_gcc = $(warning check_gcc is deprecated - use cc-option) \
- $(call cc-option, $(1),$(2))
-
# cc-option-yn
# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
@@ -357,7 +343,11 @@ CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-ffreestanding
AFLAGS := -D__ASSEMBLY__
-export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
+# Read KERNELRELEASE from .kernelrelease (if it exists)
+KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
+KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
@@ -452,6 +442,7 @@ export KBUILD_DEFCONFIG
config %config: scripts_basic outputmakefile FORCE
$(Q)mkdir -p include/linux
$(Q)$(MAKE) $(build)=scripts/kconfig $@
+ $(Q)$(MAKE) .kernelrelease
else
# ===========================================================================
@@ -481,18 +472,20 @@ ifeq ($(dot-config),1)
# Read in dependencies to all Kconfig* files, make sure to run
# oldconfig if changes are detected.
--include .config.cmd
+-include .kconfig.d
include .config
# If .config needs to be updated, it will be done via the dependency
# that autoconf has on .config.
# To avoid any implicit rule to kick in, define an empty command
-.config: ;
+.config .kconfig.d: ;
# If .config is newer than include/linux/autoconf.h, someone tinkered
-# with it and forgot to run make oldconfig
-include/linux/autoconf.h: .config
+# with it and forgot to run make oldconfig.
+# If kconfig.d is missing then we are probarly in a cleaned tree so
+# we execute the config step to be sure to catch updated Kconfig files
+include/linux/autoconf.h: .kconfig.d .config
$(Q)mkdir -p include/linux
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
else
@@ -553,33 +546,13 @@ 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
# makefile but the arguement can be passed to make if needed.
#
-MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
@@ -784,6 +757,48 @@ $(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
$(vmlinux-dirs): prepare scripts
$(Q)$(MAKE) $(build)=$@
+# Build the kernel release string
+# The KERNELRELEASE is stored in a file named .kernelrelease
+# to be used when executing for example make install or make modules_install
+#
+# Take the contents of any files called localversion* and the config
+# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE.
+# LOCALVERSION from the command line override all of this
+
+nullstring :=
+space := $(nullstring) # end of line
+
+___localver = $(objtree)/localversion* $(srctree)/localversion*
+__localver = $(sort $(wildcard $(___localver)))
+# skip backup files (containing '~')
+_localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
+
+localver = $(subst $(space),, \
+ $(shell cat /dev/null $(_localver)) \
+ $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
+
+# If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
+# and if the SCM is know a tag from the SCM is appended.
+# The appended tag is determinded by the SCM used.
+#
+# Currently, only git is supported.
+# Other SCMs can edit scripts/setlocalversion and add the appropriate
+# checks as needed.
+ifdef CONFIG_LOCALVERSION_AUTO
+ _localver-auto = $(shell $(CONFIG_SHELL) \
+ $(srctree)/scripts/setlocalversion $(srctree))
+ localver-auto = $(LOCALVERSION)$(_localver-auto)
+endif
+
+localver-full = $(localver)$(localver-auto)
+
+# Store (new) KERNELRELASE string in .kernelrelease
+kernelrelease = $(KERNELVERSION)$(localver-full)
+.kernelrelease: FORCE
+ $(Q)rm -f $@
+ $(Q)echo $(kernelrelease) > $@
+
+
# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
@@ -800,8 +815,7 @@ $(vmlinux-dirs): prepare scripts
# 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
-
-prepare3:
+prepare3: .kernelrelease
ifneq ($(KBUILD_SRC),)
@echo ' Using $(srctree) as source for kernel'
$(Q)if [ -f $(srctree)/.config ]; then \
@@ -892,7 +906,7 @@ define filechk_version.h
)
endef
-include/linux/version.h: $(srctree)/Makefile FORCE
+include/linux/version.h: $(srctree)/Makefile .config FORCE
$(call filechk,version.h)
# ---------------------------------------------------------------------------
@@ -986,9 +1000,9 @@ CLEAN_FILES += vmlinux System.map \
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include2
-MRPROPER_FILES += .config .config.old include/asm .version \
+MRPROPER_FILES += .config .config.old include/asm .version .old_version \
include/linux/autoconf.h include/linux/version.h \
- Module.symvers tags TAGS cscope*
+ .kernelrelease Module.symvers tags TAGS cscope*
# clean - Delete most, but leave enough to build external modules
#
@@ -1066,7 +1080,7 @@ help:
@echo ' all - Build all targets marked with [*]'
@echo '* vmlinux - Build the bare kernel'
@echo '* modules - Build all modules'
- @echo ' modules_install - Install all modules'
+ @echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
@echo ' dir/ - Build all files in dir and below'
@echo ' dir/file.[ois] - Build specified target only'
@echo ' dir/file.ko - Build module including final link'
@@ -1074,6 +1088,7 @@ help:
@echo ' tags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ' kernelrelease - Output the release version string'
+ @echo ' kernelversion - Output the version stored in Makefile'
@echo ''
@echo 'Static analysers'
@echo ' buildcheck - List dangling references to vmlinux discarded sections'
@@ -1240,8 +1255,11 @@ cscope: FORCE
quiet_cmd_TAGS = MAKE $@
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
+ ETAGSF=`etags --version | grep -i exuberant >/dev/null && \
+ echo "-I __initdata,__exitdata,__acquires,__releases \
+ -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
+ --extra=+f --c-kinds=+px"`; \
+ $(all-sources) | xargs etags $$ETAGSF -a
endef
TAGS: FORCE
@@ -1251,8 +1269,11 @@ TAGS: FORCE
quiet_cmd_tags = MAKE $@
define cmd_tags
rm -f $@; \
- CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
- $(all-sources) | xargs ctags $$CTAGSF -a
+ CTAGSF=`ctags --version | grep -i exuberant >/dev/null && \
+ echo "-I __initdata,__exitdata,__acquires,__releases \
+ -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
+ --extra=+f --c-kinds=+px"`; \
+ $(all-sources) | xargs ctags $$CTAGSF -a
endef
tags: FORCE
@@ -1288,7 +1309,10 @@ checkstack:
$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
kernelrelease:
- @echo $(KERNELRELEASE)
+ $(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
+ $(error kernelrelease not valid - run 'make *config' to update it))
+kernelversion:
+ @echo $(KERNELVERSION)
# FIXME Should go into a make.lib or something
# ===========================================================================
diff --git a/README b/README
index 61c4f7429233..0d318abaf7fd 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
- Linux kernel release 2.6.xx
+ Linux kernel release 2.6.xx <http://kernel.org>
These are the release notes for Linux version 2.6. Read them carefully,
as they tell you what this is all about, explain how to install the
@@ -6,23 +6,31 @@ kernel, and what to do if something goes wrong.
WHAT IS LINUX?
- Linux is a Unix clone written from scratch by Linus Torvalds with
- assistance from a loosely-knit team of hackers across the Net.
- It aims towards POSIX compliance.
+ Linux is a clone of the operating system Unix, written from scratch by
+ Linus Torvalds with assistance from a loosely-knit team of hackers across
+ the Net. It aims towards POSIX and Single UNIX Specification compliance.
- It has all the features you would expect in a modern fully-fledged
- Unix, including true multitasking, virtual memory, shared libraries,
- demand loading, shared copy-on-write executables, proper memory
- management and TCP/IP networking.
+ It has all the features you would expect in a modern fully-fledged Unix,
+ including true multitasking, virtual memory, shared libraries, demand
+ loading, shared copy-on-write executables, proper memory management,
+ and multistack networking including IPv4 and IPv6.
It is distributed under the GNU General Public License - see the
accompanying COPYING file for more details.
ON WHAT HARDWARE DOES IT RUN?
- Linux was first developed for 386/486-based PCs. These days it also
- runs on ARMs, DEC Alphas, SUN Sparcs, M68000 machines (like Atari and
- Amiga), MIPS and PowerPC, and others.
+ Although originally developed first for 32-bit x86-based PCs (386 or higher),
+ today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
+ UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH,
+ IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
+ and Renesas M32R architectures.
+
+ Linux is easily portable to most general-purpose 32- or 64-bit architectures
+ as long as they have a paged memory management unit (PMMU) and a port of the
+ GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
+ also been ported to a number of architectures without a PMMU, although
+ functionality is then obviously somewhat limited.
DOCUMENTATION:
@@ -183,11 +191,8 @@ CONFIGURING the kernel:
COMPILING the kernel:
- - Make sure you have gcc 2.95.3 available.
- gcc 2.91.66 (egcs-1.1.2), and gcc 2.7.2.3 are known to miscompile
- some parts of the kernel, and are *no longer supported*.
- Also remember to upgrade your binutils package (for as/ld/nm and company)
- if necessary. For more information, refer to Documentation/Changes.
+ - Make sure you have at least gcc 3.2 available.
+ For more information, refer to Documentation/Changes.
Please note that you can still run a.out user programs with this kernel.
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 786491f9ceb2..eedf41bf7057 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -18,9 +18,6 @@ config MMU
bool
default y
-config UID16
- bool
-
config RWSEM_GENERIC_SPINLOCK
bool
@@ -40,6 +37,19 @@ config GENERIC_IOMAP
bool
default n
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config AUTO_IRQ_AFFINITY
+ bool
+ depends on SMP
+ default y
+
source "init/Kconfig"
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 24ae9a366073..1898ea79d0e2 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -40,7 +40,6 @@
#include <asm/unistd.h>
extern struct hwrpb_struct *hwrpb;
-extern void dump_thread(struct pt_regs *, struct user *);
extern spinlock_t rtc_lock;
/* these are C runtime functions with special calling conventions: */
@@ -175,7 +174,6 @@ EXPORT_SYMBOL(up);
*/
#ifdef CONFIG_SMP
-EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(flush_tlb_mm);
EXPORT_SYMBOL(flush_tlb_range);
EXPORT_SYMBOL(flush_tlb_page);
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index b6114f5c0d2b..76be5cf0de13 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -32,214 +32,25 @@
#include <asm/io.h>
#include <asm/uaccess.h>
-/*
- * Controller mappings for all interrupt sources:
- */
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
- [0 ... NR_IRQS-1] = {
- .handler = &no_irq_type,
- .lock = SPIN_LOCK_UNLOCKED
- }
-};
-
-static void register_irq_proc(unsigned int irq);
-
volatile unsigned long irq_err_count;
-/*
- * Special irq handlers.
- */
-
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- return IRQ_NONE;
-}
-
-/*
- * Generic no controller code
- */
-
-static void no_irq_enable_disable(unsigned int irq) { }
-static unsigned int no_irq_startup(unsigned int irq) { return 0; }
-
-static void
-no_irq_ack(unsigned int irq)
+void ack_bad_irq(unsigned int irq)
{
irq_err_count++;
printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
}
-struct hw_interrupt_type no_irq_type = {
- .typename = "none",
- .startup = no_irq_startup,
- .shutdown = no_irq_enable_disable,
- .enable = no_irq_enable_disable,
- .disable = no_irq_enable_disable,
- .ack = no_irq_ack,
- .end = no_irq_enable_disable,
-};
-
-int
-handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
- struct irqaction *action)
-{
- int status = 1; /* Force the "do bottom halves" bit */
- int ret;
-
- do {
- if (!(action->flags & SA_INTERRUPT))
- local_irq_enable();
- else
- local_irq_disable();
-
- ret = action->handler(irq, action->dev_id, regs);
- if (ret == IRQ_HANDLED)
- status |= action->flags;
- action = action->next;
- } while (action);
- if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- local_irq_disable();
-
- return status;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
- */
-void inline
-disable_irq_nosync(unsigned int irq)
-{
- irq_desc_t *desc = irq_desc + irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- if (!desc->depth++) {
- desc->status |= IRQ_DISABLED;
- desc->handler->disable(irq);
- }
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
- * Synchronous version of the above, making sure the IRQ is
- * no longer running on any other IRQ..
- */
-void
-disable_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- synchronize_irq(irq);
-}
-
-void
-enable_irq(unsigned int irq)
-{
- irq_desc_t *desc = irq_desc + irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- switch (desc->depth) {
- case 1: {
- unsigned int status = desc->status & ~IRQ_DISABLED;
- desc->status = status;
- if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
- desc->status = status | IRQ_REPLAY;
- hw_resend_irq(desc->handler,irq);
- }
- desc->handler->enable(irq);
- /* fall-through */
- }
- default:
- desc->depth--;
- break;
- case 0:
- printk(KERN_ERR "enable_irq() unbalanced from %p\n",
- __builtin_return_address(0));
- }
- spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-int
-setup_irq(unsigned int irq, struct irqaction * new)
-{
- int shared = 0;
- struct irqaction *old, **p;
- unsigned long flags;
- irq_desc_t *desc = irq_desc + irq;
-
- if (desc->handler == &no_irq_type)
- return -ENOSYS;
-
- /*
- * Some drivers like serial.c use request_irq() heavily,
- * so we have to be careful not to interfere with a
- * running system.
- */
- if (new->flags & SA_SAMPLE_RANDOM) {
- /*
- * This function might sleep, we want to call it first,
- * outside of the atomic block.
- * Yes, this might clear the entropy pool if the wrong
- * driver is attempted to be loaded, without actually
- * installing a new handler, but is this really a problem,
- * only the sysadmin is able to do this.
- */
- rand_initialize_irq(irq);
- }
-
- /*
- * The following block of code has to be executed atomically
- */
- spin_lock_irqsave(&desc->lock,flags);
- p = &desc->action;
- if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ)) {
- spin_unlock_irqrestore(&desc->lock,flags);
- return -EBUSY;
- }
-
- /* add new interrupt at end of irq queue */
- do {
- p = &old->next;
- old = *p;
- } while (old);
- shared = 1;
- }
-
- *p = new;
-
- if (!shared) {
- desc->depth = 0;
- desc->status &=
- ~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS);
- desc->handler->startup(irq);
- }
- spin_unlock_irqrestore(&desc->lock,flags);
-
- return 0;
-}
-
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir[NR_IRQS];
-
#ifdef CONFIG_SMP
-static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
static char irq_user_affinity[NR_IRQS];
-static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
-static void
-select_smp_affinity(int irq)
+int
+select_smp_affinity(unsigned int irq)
{
static int last_cpu;
int cpu = last_cpu + 1;
- if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
- return;
+ if (!irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
+ return 1;
while (!cpu_possible(cpu))
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
@@ -247,208 +58,10 @@ select_smp_affinity(int irq)
irq_affinity[irq] = cpumask_of_cpu(cpu);
irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu));
+ return 0;
}
-
-static int
-irq_affinity_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
- if (count - len < 2)
- return -EINVAL;
- len += sprintf(page + len, "\n");
- return len;
-}
-
-static int
-irq_affinity_write_proc(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- int irq = (long) data, full_count = count, err;
- cpumask_t new_value;
-
- if (!irq_desc[irq].handler->set_affinity)
- return -EIO;
-
- err = cpumask_parse(buffer, count, new_value);
-
- /* The special value 0 means release control of the
- affinity to kernel. */
- cpus_and(new_value, new_value, cpu_online_map);
- if (cpus_empty(new_value)) {
- irq_user_affinity[irq] = 0;
- select_smp_affinity(irq);
- }
- /* Do not allow disabling IRQs completely - it's a too easy
- way to make the system unusable accidentally :-) At least
- one online CPU still has to be targeted. */
- else {
- irq_affinity[irq] = new_value;
- irq_user_affinity[irq] = 1;
- irq_desc[irq].handler->set_affinity(irq, new_value);
- }
-
- return full_count;
-}
-
#endif /* CONFIG_SMP */
-#define MAX_NAMELEN 10
-
-static void
-register_irq_proc (unsigned int irq)
-{
- char name [MAX_NAMELEN];
-
- if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
- irq_dir[irq])
- return;
-
- memset(name, 0, MAX_NAMELEN);
- sprintf(name, "%d", irq);
-
- /* create /proc/irq/1234 */
- irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-
-#ifdef CONFIG_SMP
- if (irq_desc[irq].handler->set_affinity) {
- struct proc_dir_entry *entry;
- /* create /proc/irq/1234/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
- if (entry) {
- entry->nlink = 1;
- entry->data = (void *)(long)irq;
- entry->read_proc = irq_affinity_read_proc;
- entry->write_proc = irq_affinity_write_proc;
- }
-
- smp_affinity_entry[irq] = entry;
- }
-#endif
-}
-
-void
-init_irq_proc (void)
-{
- int i;
-
- /* create /proc/irq */
- root_irq_dir = proc_mkdir("irq", NULL);
-
-#ifdef CONFIG_SMP
- /* create /proc/irq/prof_cpu_mask */
- create_prof_cpu_mask(root_irq_dir);
-#endif
-
- /*
- * Create entries for all existing IRQs.
- */
- for (i = 0; i < ACTUAL_NR_IRQS; i++) {
- if (irq_desc[i].handler == &no_irq_type)
- continue;
- register_irq_proc(i);
- }
-}
-
-int
-request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
-{
- int retval;
- struct irqaction * action;
-
- if (irq >= ACTUAL_NR_IRQS)
- return -EINVAL;
- if (!handler)
- return -EINVAL;
-
-#if 1
- /*
- * Sanity-check: shared interrupts should REALLY pass in
- * a real dev-ID, otherwise we'll have trouble later trying
- * to figure out which interrupt is which (messes up the
- * interrupt freeing logic etc).
- */
- if ((irqflags & SA_SHIRQ) && !dev_id) {
- printk(KERN_ERR
- "Bad boy: %s (at %p) called us without a dev_id!\n",
- devname, __builtin_return_address(0));
- }
-#endif
-
- action = (struct irqaction *)
- kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
-
- action->handler = handler;
- action->flags = irqflags;
- cpus_clear(action->mask);
- action->name = devname;
- action->next = NULL;
- action->dev_id = dev_id;
-
-#ifdef CONFIG_SMP
- select_smp_affinity(irq);
-#endif
-
- retval = setup_irq(irq, action);
- if (retval)
- kfree(action);
- return retval;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void
-free_irq(unsigned int irq, void *dev_id)
-{
- irq_desc_t *desc;
- struct irqaction **p;
- unsigned long flags;
-
- if (irq >= ACTUAL_NR_IRQS) {
- printk(KERN_CRIT "Trying to free IRQ%d\n", irq);
- return;
- }
-
- desc = irq_desc + irq;
- spin_lock_irqsave(&desc->lock,flags);
- p = &desc->action;
- for (;;) {
- struct irqaction * action = *p;
- if (action) {
- struct irqaction **pp = p;
- p = &action->next;
- if (action->dev_id != dev_id)
- continue;
-
- /* Found - now remove it from the list of entries. */
- *pp = action->next;
- if (!desc->action) {
- desc->status |= IRQ_DISABLED;
- desc->handler->shutdown(irq);
- }
- spin_unlock_irqrestore(&desc->lock,flags);
-
-#ifdef CONFIG_SMP
- /* Wait to make sure it's not being used on
- another CPU. */
- while (desc->status & IRQ_INPROGRESS)
- barrier();
-#endif
- kfree(action);
- return;
- }
- printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
- spin_unlock_irqrestore(&desc->lock,flags);
- return;
- }
-}
-
-EXPORT_SYMBOL(free_irq);
-
int
show_interrupts(struct seq_file *p, void *v)
{
@@ -531,10 +144,6 @@ handle_irq(int irq, struct pt_regs * regs)
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
- int cpu = smp_processor_id();
- irq_desc_t *desc = irq_desc + irq;
- struct irqaction * action;
- unsigned int status;
static unsigned int illegal_count=0;
if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
@@ -546,229 +155,8 @@ handle_irq(int irq, struct pt_regs * regs)
}
irq_enter();
- kstat_cpu(cpu).irqs[irq]++;
- spin_lock_irq(&desc->lock); /* mask also the higher prio events */
- desc->handler->ack(irq);
- /*
- * REPLAY is when Linux resends an IRQ that was dropped earlier.
- * WAITING is used by probe to mark irqs that are being tested.
- */
- status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
- status |= IRQ_PENDING; /* we _want_ to handle it */
-
- /*
- * If the IRQ is disabled for whatever reason, we cannot
- * use the action we have.
- */
- action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- action = desc->action;
- status &= ~IRQ_PENDING; /* we commit to handling */
- status |= IRQ_INPROGRESS; /* we are handling it */
- }
- desc->status = status;
-
- /*
- * If there is no IRQ handler or it was disabled, exit early.
- * Since we set PENDING, if another processor is handling
- * a different instance of this same irq, the other processor
- * will take care of it.
- */
- if (!action)
- goto out;
-
- /*
- * Edge triggered interrupts need to remember pending events.
- * This applies to any hw interrupts that allow a second
- * instance of the same irq to arrive while we are in handle_irq
- * or in the handler. But the code here only handles the _second_
- * instance of the irq, not the third or fourth. So it is mostly
- * useful for irq hardware that does not mask cleanly in an
- * SMP environment.
- */
- for (;;) {
- spin_unlock(&desc->lock);
- handle_IRQ_event(irq, regs, action);
- spin_lock(&desc->lock);
-
- if (!(desc->status & IRQ_PENDING)
- || (desc->status & IRQ_LEVEL))
- break;
- desc->status &= ~IRQ_PENDING;
- }
- desc->status &= ~IRQ_INPROGRESS;
-out:
- /*
- * The ->end() handler has to deal with interrupts which got
- * disabled while the handler was running.
- */
- desc->handler->end(irq);
- spin_unlock(&desc->lock);
-
+ local_irq_disable();
+ __do_IRQ(irq, regs);
+ local_irq_enable();
irq_exit();
}
-
-/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that
- * comes in on to an unassigned handler will get stuck
- * with "IRQ_WAITING" cleared and the interrupt
- * disabled.
- */
-unsigned long
-probe_irq_on(void)
-{
- int i;
- irq_desc_t *desc;
- unsigned long delay;
- unsigned long val;
-
- /* Something may have generated an irq long ago and we want to
- flush such a longstanding irq before considering it as spurious. */
- for (i = NR_IRQS-1; i >= 0; i--) {
- desc = irq_desc + i;
-
- spin_lock_irq(&desc->lock);
- if (!irq_desc[i].action)
- irq_desc[i].handler->startup(i);
- spin_unlock_irq(&desc->lock);
- }
-
- /* Wait for longstanding interrupts to trigger. */
- for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
- /* about 20ms delay */ barrier();
-
- /* enable any unassigned irqs (we must startup again here because
- if a longstanding irq happened in the previous stage, it may have
- masked itself) first, enable any unassigned irqs. */
- for (i = NR_IRQS-1; i >= 0; i--) {
- desc = irq_desc + i;
-
- spin_lock_irq(&desc->lock);
- if (!desc->action) {
- desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
- if (desc->handler->startup(i))
- desc->status |= IRQ_PENDING;
- }
- spin_unlock_irq(&desc->lock);
- }
-
- /*
- * Wait for spurious interrupts to trigger
- */
- for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
- /* about 100ms delay */ barrier();
-
- /*
- * Now filter out any obviously spurious interrupts
- */
- val = 0;
- for (i=0; i<NR_IRQS; i++) {
- irq_desc_t *desc = irq_desc + i;
- unsigned int status;
-
- spin_lock_irq(&desc->lock);
- status = desc->status;
-
- if (status & IRQ_AUTODETECT) {
- /* It triggered already - consider it spurious. */
- if (!(status & IRQ_WAITING)) {
- desc->status = status & ~IRQ_AUTODETECT;
- desc->handler->shutdown(i);
- } else
- if (i < 32)
- val |= 1 << i;
- }
- spin_unlock_irq(&desc->lock);
- }
-
- return val;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-/*
- * Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
- */
-unsigned int
-probe_irq_mask(unsigned long val)
-{
- int i;
- unsigned int mask;
-
- mask = 0;
- for (i = 0; i < NR_IRQS; i++) {
- irq_desc_t *desc = irq_desc + i;
- unsigned int status;
-
- spin_lock_irq(&desc->lock);
- status = desc->status;
-
- if (status & IRQ_AUTODETECT) {
- /* We only react to ISA interrupts */
- if (!(status & IRQ_WAITING)) {
- if (i < 16)
- mask |= 1 << i;
- }
-
- desc->status = status & ~IRQ_AUTODETECT;
- desc->handler->shutdown(i);
- }
- spin_unlock_irq(&desc->lock);
- }
-
- return mask & val;
-}
-
-/*
- * Get the result of the IRQ probe.. A negative result means that
- * we have several candidates (but we return the lowest-numbered
- * one).
- */
-
-int
-probe_irq_off(unsigned long val)
-{
- int i, irq_found, nr_irqs;
-
- nr_irqs = 0;
- irq_found = 0;
- for (i=0; i<NR_IRQS; i++) {
- irq_desc_t *desc = irq_desc + i;
- unsigned int status;
-
- spin_lock_irq(&desc->lock);
- status = desc->status;
-
- if (status & IRQ_AUTODETECT) {
- if (!(status & IRQ_WAITING)) {
- if (!nr_irqs)
- irq_found = i;
- nr_irqs++;
- }
- desc->status = status & ~IRQ_AUTODETECT;
- desc->handler->shutdown(i);
- }
- spin_unlock_irq(&desc->lock);
- }
-
- if (nr_irqs > 1)
- irq_found = -irq_found;
- return irq_found;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-#ifdef CONFIG_SMP
-void synchronize_irq(unsigned int irq)
-{
- /* is there anything to synchronize with? */
- if (!irq_desc[irq].action)
- return;
-
- while (irq_desc[irq].status & IRQ_INPROGRESS)
- barrier();
-}
-#endif
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 01fe990d3e54..7fb14f42a125 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -960,7 +960,7 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs)
return -EFAULT;
}
- return do_utimes(filename, tvs ? ktvs : NULL);
+ return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL);
}
#define MAX_SELECT_SECONDS \
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 9903e3a79102..fff5cf93e816 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -7,6 +7,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/sched.h>
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index a8682612abc0..9924fd07743a 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -43,6 +43,11 @@
#include "proto.h"
#include "pci_impl.h"
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void) = machine_power_off;
+
void
cpu_idle(void)
{
@@ -271,7 +276,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
{
extern void ret_from_fork(void);
- struct thread_info *childti = p->thread_info;
+ struct thread_info *childti = task_thread_info(p);
struct pt_regs * childregs;
struct switch_stack * childstack, *stack;
unsigned long stack_offset, settls;
@@ -280,7 +285,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
if (!(regs->ps & 8))
stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
childregs = (struct pt_regs *)
- (stack_offset + PAGE_SIZE + (long) childti);
+ (stack_offset + PAGE_SIZE + task_stack_page(p));
*childregs = *regs;
settls = regs->r20;
@@ -423,30 +428,15 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
int
dump_elf_task(elf_greg_t *dest, struct task_struct *task)
{
- struct thread_info *ti;
- struct pt_regs *pt;
-
- ti = task->thread_info;
- pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
-
- dump_elf_thread(dest, pt, ti);
-
+ dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task));
return 1;
}
int
dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
{
- struct thread_info *ti;
- struct pt_regs *pt;
- struct switch_stack *sw;
-
- ti = task->thread_info;
- pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
- sw = (struct switch_stack *)pt - 1;
-
+ struct switch_stack *sw = (struct switch_stack *)task_pt_regs(task) - 1;
memcpy(dest, sw->fp, 32 * 8);
-
return 1;
}
@@ -487,8 +477,8 @@ out:
unsigned long
thread_saved_pc(task_t *t)
{
- unsigned long base = (unsigned long)t->thread_info;
- unsigned long fp, sp = t->thread_info->pcb.ksp;
+ unsigned long base = (unsigned long)task_stack_page(t);
+ unsigned long fp, sp = task_thread_info(t)->pcb.ksp;
if (sp > base && sp+6*8 < base + 16*1024) {
fp = ((unsigned long*)sp)[6];
@@ -518,7 +508,7 @@ get_wchan(struct task_struct *p)
pc = thread_saved_pc(p);
if (in_sched_functions(pc)) {
- schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
+ schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6];
return ((unsigned long *)schedule_frame)[12];
}
return pc;
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index bbd37536d14e..0cd060598f9a 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -72,6 +72,13 @@ enum {
REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
};
+#define PT_REG(reg) \
+ (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg))
+
+#define SW_REG(reg) \
+ (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
+ + offsetof(struct switch_stack, reg))
+
static int regoff[] = {
PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3),
PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7),
@@ -103,14 +110,14 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
unsigned long *addr;
if (regno == 30) {
- addr = &task->thread_info->pcb.usp;
+ addr = &task_thread_info(task)->pcb.usp;
} else if (regno == 65) {
- addr = &task->thread_info->pcb.unique;
+ addr = &task_thread_info(task)->pcb.unique;
} else if (regno == 31 || regno > 65) {
zero = 0;
addr = &zero;
} else {
- addr = (void *)task->thread_info + regoff[regno];
+ addr = task_stack_page(task) + regoff[regno];
}
return addr;
}
@@ -125,7 +132,7 @@ get_reg(struct task_struct * task, unsigned long regno)
if (regno == 63) {
unsigned long fpcr = *get_reg_addr(task, regno);
unsigned long swcr
- = task->thread_info->ieee_state & IEEE_SW_MASK;
+ = task_thread_info(task)->ieee_state & IEEE_SW_MASK;
swcr = swcr_update_status(swcr, fpcr);
return fpcr | swcr;
}
@@ -139,8 +146,8 @@ static int
put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
{
if (regno == 63) {
- task->thread_info->ieee_state
- = ((task->thread_info->ieee_state & ~IEEE_SW_MASK)
+ task_thread_info(task)->ieee_state
+ = ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK)
| (data & IEEE_SW_MASK));
data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
}
@@ -188,35 +195,35 @@ ptrace_set_bpt(struct task_struct * child)
* branch (emulation can be tricky for fp branches).
*/
displ = ((s32)(insn << 11)) >> 9;
- child->thread_info->bpt_addr[nsaved++] = pc + 4;
+ task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
if (displ) /* guard against unoptimized code */
- child->thread_info->bpt_addr[nsaved++]
+ task_thread_info(child)->bpt_addr[nsaved++]
= pc + 4 + displ;
DBG(DBG_BPT, ("execing branch\n"));
} else if (op_code == 0x1a) {
reg_b = (insn >> 16) & 0x1f;
- child->thread_info->bpt_addr[nsaved++] = get_reg(child, reg_b);
+ task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b);
DBG(DBG_BPT, ("execing jump\n"));
} else {
- child->thread_info->bpt_addr[nsaved++] = pc + 4;
+ task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
DBG(DBG_BPT, ("execing normal insn\n"));
}
/* install breakpoints: */
for (i = 0; i < nsaved; ++i) {
- res = read_int(child, child->thread_info->bpt_addr[i],
+ res = read_int(child, task_thread_info(child)->bpt_addr[i],
(int *) &insn);
if (res < 0)
return res;
- child->thread_info->bpt_insn[i] = insn;
+ task_thread_info(child)->bpt_insn[i] = insn;
DBG(DBG_BPT, (" -> next_pc=%lx\n",
- child->thread_info->bpt_addr[i]));
- res = write_int(child, child->thread_info->bpt_addr[i],
+ task_thread_info(child)->bpt_addr[i]));
+ res = write_int(child, task_thread_info(child)->bpt_addr[i],
BREAKINST);
if (res < 0)
return res;
}
- child->thread_info->bpt_nsaved = nsaved;
+ task_thread_info(child)->bpt_nsaved = nsaved;
return 0;
}
@@ -227,9 +234,9 @@ ptrace_set_bpt(struct task_struct * child)
int
ptrace_cancel_bpt(struct task_struct * child)
{
- int i, nsaved = child->thread_info->bpt_nsaved;
+ int i, nsaved = task_thread_info(child)->bpt_nsaved;
- child->thread_info->bpt_nsaved = 0;
+ task_thread_info(child)->bpt_nsaved = 0;
if (nsaved > 2) {
printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
@@ -237,8 +244,8 @@ ptrace_cancel_bpt(struct task_struct * child)
}
for (i = 0; i < nsaved; ++i) {
- write_int(child, child->thread_info->bpt_addr[i],
- child->thread_info->bpt_insn[i]);
+ write_int(child, task_thread_info(child)->bpt_addr[i],
+ task_thread_info(child)->bpt_insn[i]);
}
return (nsaved != 0);
}
@@ -265,30 +272,16 @@ do_sys_ptrace(long request, long pid, long addr, long data,
lock_kernel();
DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
request, pid, addr, data));
- ret = -EPERM;
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out_notsk;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out_notsk;
- /* set the ptrace bit in the process ptrace flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
+ ret = ptrace_traceme();
goto out_notsk;
}
- if (pid == 1) /* you may not mess with init */
- goto out_notsk;
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
goto out_notsk;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
@@ -369,7 +362,7 @@ do_sys_ptrace(long request, long pid, long addr, long data,
if (!valid_signal(data))
break;
/* Mark single stepping. */
- child->thread_info->bpt_nsaved = -1;
+ task_thread_info(child)->bpt_nsaved = -1;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
wake_up_process(child);
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index da0be3465791..4b873527ce1c 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -302,7 +302,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
+ hwrpb->processor_offset
+ cpuid * hwrpb->processor_size);
hwpcb = (struct pcb_struct *) cpu->hwpcb;
- ipcb = &idle->thread_info->pcb;
+ ipcb = &task_thread_info(idle)->pcb;
/* Initialize the CPU's HWPCB to something just good enough for
us to get started. Immediately after starting, we'll swpctx
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index 145dcde143ae..d7f0e97fe56f 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -254,7 +254,7 @@ alcor_init_pci(void)
* motherboard, by looking for a 21040 TULIP in slot 6, which is
* built into XLT and BRET/MAVERICK, but not available on ALCOR.
*/
- dev = pci_find_device(PCI_VENDOR_ID_DEC,
+ dev = pci_get_device(PCI_VENDOR_ID_DEC,
PCI_DEVICE_ID_DEC_TULIP,
NULL);
if (dev && dev->devfn == PCI_DEVFN(6,0)) {
@@ -262,6 +262,7 @@ alcor_init_pci(void)
printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
__FUNCTION__);
}
+ pci_dev_put(dev);
}
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 47df48a6ddb7..131a2d9f79d3 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -105,7 +105,7 @@ sio_collect_irq_levels(void)
struct pci_dev *dev = NULL;
/* Iterate through the devices, collecting IRQ levels. */
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ for_each_pci_dev(dev) {
if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
(dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
continue;
@@ -229,8 +229,8 @@ alphabook1_init_pci(void)
*/
dev = NULL;
- while ((dev = pci_find_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
- if (dev->device == PCI_DEVICE_ID_NCR_53C810
+ while ((dev = pci_get_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
+ if (dev->device == PCI_DEVICE_ID_NCR_53C810
|| dev->device == PCI_DEVICE_ID_NCR_53C815
|| dev->device == PCI_DEVICE_ID_NCR_53C820
|| dev->device == PCI_DEVICE_ID_NCR_53C825) {
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 90752f6d8867..486d7945583d 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -7,6 +7,7 @@
/* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
#include <linux/config.h>
+#include <linux/pagemap.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4b15f5f1e254..5959e36c3b4c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -46,10 +46,6 @@ config MCA
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -103,13 +99,6 @@ config ARCH_EBSA110
Ethernet interface, two PCMCIA sockets, two serial ports and a
parallel port.
-config ARCH_CAMELOT
- bool "Epxa10db"
- help
- This enables support for Altera's Excalibur XA10 development board.
- If you would like to build your kernel to run on one of these boards
- then you must say 'Y' here. Otherwise say 'N'
-
config ARCH_FOOTBRIDGE
bool "FootBridge"
select FOOTBRIDGE
@@ -154,6 +143,7 @@ config ARCH_RPC
select FIQ
select TIMER_ACORN
select ARCH_MAY_HAVE_PC_FDC
+ select ISA_DMA_API
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.
@@ -190,6 +180,7 @@ config ARCH_OMAP
config ARCH_VERSATILE
bool "Versatile"
select ARM_AMBA
+ select ARM_VIC
select ICST307
help
This enables support for ARM Ltd Versatile board.
@@ -206,6 +197,7 @@ config ARCH_IMX
config ARCH_H720X
bool "Hynix-HMS720x-based"
+ select ISA_DMA_API
help
This enables support for systems based on the Hynix HMS720x
@@ -215,12 +207,16 @@ config ARCH_AAEC2000
help
This enables support for systems based on the Agilent AAEC-2000
+config ARCH_AT91RM9200
+ bool "AT91RM9200"
+ help
+ Say Y here if you intend to run this kernel on an AT91RM9200-based
+ board.
+
endchoice
source "arch/arm/mach-clps711x/Kconfig"
-source "arch/arm/mach-epxa10db/Kconfig"
-
source "arch/arm/mach-footbridge/Kconfig"
source "arch/arm/mach-integrator/Kconfig"
@@ -255,6 +251,8 @@ source "arch/arm/mach-aaec2000/Kconfig"
source "arch/arm/mach-realview/Kconfig"
+source "arch/arm/mach-at91rm9200/Kconfig"
+
# Definitions to make life easier
config ARCH_ACORN
bool
@@ -290,12 +288,14 @@ config ISA
(MCA) or VESA. ISA is an older system, now being displaced by PCI;
newer boards don't support it. If you have ISA, say Y, otherwise N.
+# Select ISA DMA controller support
config ISA_DMA
bool
+ select ISA_DMA_API
+# Select ISA DMA interface
config ISA_DMA_API
bool
- default y
config PCI
bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
@@ -401,6 +401,38 @@ config NO_IDLE_HZ
Currently at least OMAP, PXA2xx and SA11x0 platforms are known
to have accurate timekeeping with dynamic tick.
+config AEABI
+ bool "Use the ARM EABI to compile the kernel"
+ help
+ This option allows for the kernel to be compiled using the latest
+ ARM ABI (aka EABI). This is only useful if you are using a user
+ space environment that is also compiled with EABI.
+
+ Since there are major incompatibilities between the legacy ABI and
+ EABI, especially with regard to structure member alignment, this
+ option also changes the kernel syscall calling convention to
+ disambiguate both ABIs and allow for backward compatibility support
+ (selected with CONFIG_OABI_COMPAT).
+
+ To use this you need GCC version 4.0.0 or later.
+
+config OABI_COMPAT
+ bool "Allow old ABI binaries to run with this kernel"
+ depends on AEABI
+ default y
+ help
+ This option preserves the old syscall interface along with the
+ new (ARM EABI) one. It also provides a compatibility layer to
+ intercept syscalls that have structure arguments which layout
+ in memory differs between the legacy ABI and the new ARM EABI
+ (only for non "thumb" binaries). This option adds a tiny
+ overhead to all syscalls and produces a slightly larger kernel.
+ If you know you'll be using only pure EABI user space then you
+ can say N here. If this option is not selected and you attempt
+ to execute a legacy ABI binary then the result will be
+ UNPREDICTABLE (in fact it can be predicted that it won't work
+ at all). If in doubt say Y.
+
config ARCH_DISCONTIGMEM_ENABLE
bool
default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
@@ -418,7 +450,8 @@ config LEDS
ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
- ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE
+ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
+ ARCH_AT91RM9200
help
If you say Y here, the LEDs on your machine will be used
to provide useful information about your current system status.
@@ -586,6 +619,7 @@ comment "At least one emulation must be selected"
config FPE_NWFPE
bool "NWFPE math emulation"
+ depends on !AEABI || OABI_COMPAT
---help---
Say Y to include the NWFPE floating point emulator in the kernel.
This is necessary to run most binaries. Linux does not currently
@@ -609,7 +643,7 @@ config FPE_NWFPE_XP
config FPE_FASTFPE
bool "FastFPE math emulation (EXPERIMENTAL)"
- depends on !CPU_32v3 && EXPERIMENTAL
+ depends on (!AEABI || OABI_COMPAT) && !CPU_32v3 && EXPERIMENTAL
---help---
Say Y here to include the FAST floating point emulator in the kernel.
This is an experimental much faster emulator which now also has full
@@ -641,6 +675,7 @@ source "fs/Kconfig.binfmt"
config ARTHUR
tristate "RISC OS personality"
+ depends on !AEABI
help
Say Y here to include the kernel code necessary if you want to run
Acorn RISC OS/Arthur binaries under Linux. This code is still very
@@ -656,7 +691,6 @@ source "kernel/power/Kconfig"
config APM
tristate "Advanced Power Management Emulation"
- depends on PM_LEGACY
---help---
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
@@ -730,6 +764,8 @@ source "drivers/char/Kconfig"
source "drivers/i2c/Kconfig"
+source "drivers/spi/Kconfig"
+
source "drivers/hwmon/Kconfig"
#source "drivers/l3/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 81bd2193fe6d..fbfc14a56b96 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -8,7 +8,7 @@
# Copyright (C) 1995-2001 by Russell King
LDFLAGS_vmlinux :=-p --no-undefined -X
-CPPFLAGS_vmlinux.lds = -DKERNEL_RAM_ADDR=$(TEXTADDR)
+CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
OBJCOPYFLAGS :=-O binary -R .note -R .comment -S
GZFLAGS :=-9
#CFLAGS +=-pipe
@@ -56,8 +56,13 @@ tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
-# Need -Uarm for gcc < 3.x
+ifeq ($(CONFIG_AEABI),y)
+CFLAGS_ABI :=-mabi=aapcs -mno-thumb-interwork
+else
CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
+endif
+
+# Need -Uarm for gcc < 3.x
CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float
@@ -65,7 +70,7 @@ CHECKFLAGS += -D__arm__
#Default value
head-y := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
-textaddr-y := 0xC0008000
+textofs-y := 0x00008000
machine-$(CONFIG_ARCH_RPC) := rpc
machine-$(CONFIG_ARCH_EBSA110) := ebsa110
@@ -73,22 +78,19 @@ textaddr-y := 0xC0008000
incdir-$(CONFIG_ARCH_CLPS7500) := cl7500
machine-$(CONFIG_FOOTBRIDGE) := footbridge
incdir-$(CONFIG_FOOTBRIDGE) := ebsa285
-textaddr-$(CONFIG_ARCH_CO285) := 0x60008000
machine-$(CONFIG_ARCH_CO285) := footbridge
incdir-$(CONFIG_ARCH_CO285) := ebsa285
machine-$(CONFIG_ARCH_SHARK) := shark
machine-$(CONFIG_ARCH_SA1100) := sa1100
ifeq ($(CONFIG_ARCH_SA1100),y)
# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
-textaddr-$(CONFIG_SA1111) := 0xc0208000
+ textofs-$(CONFIG_SA1111) := 0x00208000
endif
machine-$(CONFIG_ARCH_PXA) := pxa
machine-$(CONFIG_ARCH_L7200) := l7200
machine-$(CONFIG_ARCH_INTEGRATOR) := integrator
- machine-$(CONFIG_ARCH_CAMELOT) := epxa10db
-textaddr-$(CONFIG_ARCH_CLPS711X) := 0xc0028000
+ textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
machine-$(CONFIG_ARCH_CLPS711X) := clps711x
-textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_IOP3XX) := iop3xx
machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
machine-$(CONFIG_ARCH_IXP2000) := ixp2000
@@ -102,6 +104,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
machine-$(CONFIG_ARCH_REALVIEW) := realview
+ machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
@@ -110,7 +113,8 @@ CFLAGS_3c589_cs.o :=-DISA_SIXTEEN_BIT_PERIPHERAL
export CFLAGS_3c589_cs.o
endif
-TEXTADDR := $(textaddr-y)
+# The byte offset of the kernel image in RAM from the start of RAM.
+TEXT_OFFSET := $(textofs-y)
ifeq ($(incdir-y),)
incdir-y := $(machine-y)
@@ -123,7 +127,7 @@ else
MACHINE :=
endif
-export TEXTADDR GZFLAGS
+export TEXT_OFFSET GZFLAGS
# Do we have FASTFPE?
FASTFPE :=arch/arm/fastfpe
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 937a353bc37c..a174d63395ea 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -15,7 +15,7 @@ include $(srctree)/$(MACHINE)/Makefile.boot
endif
# Note: the following conditions must always be true:
-# ZRELADDR == virt_to_phys(TEXTADDR)
+# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
# PARAMS_PHYS must be within 4MB of ZRELADDR
# INITRD_PHYS must be in RAM
ZRELADDR := $(zreladdr-y)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 6b505ce41a75..35ffe0f4ece7 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -21,10 +21,6 @@ ifeq ($(CONFIG_ARCH_SHARK),y)
OBJS += head-shark.o ofw-shark.o
endif
-ifeq ($(CONFIG_ARCH_CAMELOT),y)
-OBJS += head-epxa10db.o
-endif
-
ifeq ($(CONFIG_ARCH_L7200),y)
OBJS += head-l7200.o
endif
@@ -50,6 +46,10 @@ ifeq ($(CONFIG_PXA_SHARPSL),y)
OBJS += head-sharpsl.o
endif
+ifeq ($(CONFIG_ARCH_AT91RM9200),y)
+OBJS += head-at91rm9200.o
+endif
+
ifeq ($(CONFIG_DEBUG_ICEDCC),y)
OBJS += ice-dcc.o
endif
diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S
new file mode 100644
index 000000000000..2119ea62b547
--- /dev/null
+++ b/arch/arm/boot/compressed/head-at91rm9200.S
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/arm/boot/compressed/head-at91rm9200.S
+ *
+ * Copyright (C) 2003 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/mach-types.h>
+
+ .section ".start", "ax"
+
+ @ Atmel AT91RM9200-DK : 262
+ mov r3, #(MACH_TYPE_AT91RM9200DK & 0xff)
+ orr r3, r3, #(MACH_TYPE_AT91RM9200DK & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ Cogent CSB337 : 399
+ mov r3, #(MACH_TYPE_CSB337 & 0xff)
+ orr r3, r3, #(MACH_TYPE_CSB337 & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ Cogent CSB637 : 648
+ mov r3, #(MACH_TYPE_CSB637 & 0xff)
+ orr r3, r3, #(MACH_TYPE_CSB637 & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ Atmel AT91RM9200-EK : 705
+ mov r3, #(MACH_TYPE_AT91RM9200EK & 0xff)
+ orr r3, r3, #(MACH_TYPE_AT91RM9200EK & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ Conitec Carmeva : 769
+ mov r3, #(MACH_TYPE_CARMEVA & 0xff)
+ orr r3, r3, #(MACH_TYPE_CARMEVA & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ KwikByte KB920x : 612
+ mov r3, #(MACH_TYPE_KB9200 & 0xff)
+ orr r3, r3, #(MACH_TYPE_KB9200 & 0xff00)
+ cmp r7, r3
+ beq 99f
+
+ @ Unknown board, use the AT91RM9200DK board
+ @ mov r7, #MACH_TYPE_AT91RM9200
+ mov r7, #(MACH_TYPE_AT91RM9200DK & 0xff)
+ orr r7, r7, #(MACH_TYPE_AT91RM9200DK & 0xff00)
+
+99:
diff --git a/arch/arm/boot/compressed/head-epxa10db.S b/arch/arm/boot/compressed/head-epxa10db.S
deleted file mode 100644
index 757681f12a39..000000000000
--- a/arch/arm/boot/compressed/head-epxa10db.S
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <asm/mach-types.h>
-#include <asm/arch/excalibur.h>
-
- .section ".start", "ax"
- mov r7, #MACH_TYPE_CAMELOT
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 6abafb6f1844..db3389d8e027 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -84,7 +84,7 @@
kputc #'\n'
kphex r5, 8 /* decompressed kernel start */
kputc #'-'
- kphex r8, 8 /* decompressed kernel end */
+ kphex r9, 8 /* decompressed kernel end */
kputc #'>'
kphex r4, 8 /* kernel execution address */
kputc #'\n'
@@ -116,7 +116,7 @@ start:
.word start @ absolute load/run zImage address
.word _edata @ zImage end address
1: mov r7, r1 @ save architecture ID
- mov r8, #0 @ save r0
+ mov r8, r2 @ save atags pointer
#ifndef __ARM_ARCH_2__
/*
@@ -144,7 +144,7 @@ not_angel:
/*
* some architecture specific code can be inserted
- * by the linker here, but it should preserve r7 and r8.
+ * by the linker here, but it should preserve r7, r8, and r9.
*/
.text
@@ -249,16 +249,17 @@ not_relocated: mov r0, #0
* r5 = decompressed kernel start
* r6 = processor ID
* r7 = architecture ID
- * r8-r14 = unused
+ * r8 = atags pointer
+ * r9-r14 = corrupted
*/
add r1, r5, r0 @ end of decompressed kernel
adr r2, reloc_start
ldr r3, LC1
add r3, r2, r3
-1: ldmia r2!, {r8 - r13} @ copy relocation code
- stmia r1!, {r8 - r13}
- ldmia r2!, {r8 - r13}
- stmia r1!, {r8 - r13}
+1: ldmia r2!, {r9 - r14} @ copy relocation code
+ stmia r1!, {r9 - r14}
+ ldmia r2!, {r9 - r14}
+ stmia r1!, {r9 - r14}
cmp r2, r3
blo 1b
@@ -308,11 +309,12 @@ params: ldr r0, =params_phys
* r4 = kernel execution address
* r6 = processor ID
* r7 = architecture number
- * r8 = run-time address of "start"
+ * r8 = atags pointer
+ * r9 = run-time address of "start" (???)
* On exit,
- * r1, r2, r3, r8, r9, r12 corrupted
+ * r1, r2, r3, r9, r10, r12 corrupted
* This routine must preserve:
- * r4, r5, r6, r7
+ * r4, r5, r6, r7, r8
*/
.align 5
cache_on: mov r3, #8 @ cache_on function
@@ -326,15 +328,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
* bits for the RAM area only.
*/
mov r0, r3
- mov r8, r0, lsr #18
- mov r8, r8, lsl #18 @ start of RAM
- add r9, r8, #0x10000000 @ a reasonable RAM size
+ mov r9, r0, lsr #18
+ mov r9, r9, lsl #18 @ start of RAM
+ add r10, r9, #0x10000000 @ a reasonable RAM size
mov r1, #0x12
orr r1, r1, #3 << 10
add r2, r3, #16384
-1: cmp r1, r8 @ if virt > start of RAM
+1: cmp r1, r9 @ if virt > start of RAM
orrhs r1, r1, #0x0c @ set cacheable, bufferable
- cmp r1, r9 @ if virt > end of RAM
+ cmp r1, r10 @ if virt > end of RAM
bichs r1, r1, #0x0c @ clear cacheable, bufferable
str r1, [r0], #4 @ 1:1 mapping
add r1, r1, #1048576
@@ -403,26 +405,28 @@ __common_cache_on:
* r5 = decompressed kernel start
* r6 = processor ID
* r7 = architecture ID
- * r8-r14 = unused
+ * r8 = atags pointer
+ * r9-r14 = corrupted
*/
.align 5
-reloc_start: add r8, r5, r0
+reloc_start: add r9, r5, r0
debug_reloc_start
mov r1, r4
1:
.rept 4
- ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel
- stmia r1!, {r0, r2, r3, r9 - r13}
+ ldmia r5!, {r0, r2, r3, r10 - r14} @ relocate kernel
+ stmia r1!, {r0, r2, r3, r10 - r14}
.endr
- cmp r5, r8
+ cmp r5, r9
blo 1b
debug_reloc_end
call_kernel: bl cache_clean_flush
bl cache_off
- mov r0, #0
+ mov r0, #0 @ must be zero
mov r1, r7 @ restore architecture number
+ mov r2, r8 @ restore atags pointer
mov pc, r4 @ call kernel
/*
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 666ba393575b..5e34ca6d38b6 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,7 +1,10 @@
-config ICST525
+config ARM_GIC
bool
-config ARM_GIC
+config ARM_VIC
+ bool
+
+config ICST525
bool
config ICST307
@@ -23,5 +26,8 @@ config SHARP_LOCOMO
config SHARP_PARAM
bool
+config SHARPSL_PM
+ bool
+
config SHARP_SCOOP
bool
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index a87886564b19..c81a2ff6b5be 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -3,8 +3,8 @@
#
obj-y += rtctime.o
-obj-$(CONFIG_ARM_AMBA) += amba.o
obj-$(CONFIG_ARM_GIC) += gic.o
+obj-$(CONFIG_ARM_VIC) += vic.o
obj-$(CONFIG_ICST525) += icst525.o
obj-$(CONFIG_ICST307) += icst307.o
obj-$(CONFIG_SA1111) += sa1111.o
@@ -13,4 +13,5 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_TIMER_ACORN) += time-acorn.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
+obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 1b7eaab02b9e..159ad7ed7a40 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -1103,14 +1103,14 @@ static int locomo_bus_remove(struct device *dev)
struct bus_type locomo_bus_type = {
.name = "locomo-bus",
.match = locomo_match,
+ .probe = locomo_bus_probe,
+ .remove = locomo_bus_remove,
.suspend = locomo_bus_suspend,
.resume = locomo_bus_resume,
};
int locomo_driver_register(struct locomo_driver *driver)
{
- driver->drv.probe = locomo_bus_probe;
- driver->drv.remove = locomo_bus_remove;
driver->drv.bus = &locomo_bus_type;
return driver_register(&driver->drv);
}
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 72b03f201eb9..48b1e19b131f 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -17,7 +17,9 @@
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
+#include <linux/capability.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/rtc.h>
#include <asm/semaphore.h>
@@ -34,7 +36,7 @@ static unsigned long rtc_irq_data;
/*
* rtc_sem protects rtc_inuse and rtc_ops
*/
-static DECLARE_MUTEX(rtc_sem);
+static DEFINE_MUTEX(rtc_mutex);
static unsigned long rtc_inuse;
static struct rtc_ops *rtc_ops;
@@ -355,7 +357,7 @@ static int rtc_open(struct inode *inode, struct file *file)
{
int ret;
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc_inuse) {
ret = -EBUSY;
@@ -373,7 +375,7 @@ static int rtc_open(struct inode *inode, struct file *file)
rtc_inuse = 1;
}
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
return ret;
}
@@ -479,7 +481,7 @@ int register_rtc(struct rtc_ops *ops)
{
int ret = -EBUSY;
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc_ops == NULL) {
rtc_ops = ops;
@@ -488,7 +490,7 @@ int register_rtc(struct rtc_ops *ops)
create_proc_read_entry("driver/rtc", 0, NULL,
rtc_read_proc, ops);
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
return ret;
}
@@ -496,12 +498,12 @@ EXPORT_SYMBOL(register_rtc);
void unregister_rtc(struct rtc_ops *rtc)
{
- down(&rtc_sem);
+ mutex_lock(&rtc_mutex);
if (rtc == rtc_ops) {
remove_proc_entry("driver/rtc", NULL);
misc_deregister(&rtc_miscdev);
rtc_ops = NULL;
}
- up(&rtc_sem);
+ mutex_unlock(&rtc_mutex);
}
EXPORT_SYMBOL(unregister_rtc);
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index d0d6e6d2d649..1475089f9b42 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1247,14 +1247,14 @@ static int sa1111_bus_remove(struct device *dev)
struct bus_type sa1111_bus_type = {
.name = "sa1111-rab",
.match = sa1111_match,
+ .probe = sa1111_bus_probe,
+ .remove = sa1111_bus_remove,
.suspend = sa1111_bus_suspend,
.resume = sa1111_bus_resume,
};
int sa1111_driver_register(struct sa1111_driver *driver)
{
- driver->drv.probe = sa1111_bus_probe;
- driver->drv.remove = sa1111_bus_remove;
driver->drv.bus = &sa1111_bus_type;
return driver_register(&driver->drv);
}
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 0c3cbd9a388b..a2dfe0b0f1ec 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -13,6 +13,7 @@
#include <linux/device.h>
#include <linux/string.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/hardware/scoop.h>
@@ -33,7 +34,6 @@ void reset_scoop(struct device *dev)
SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00
SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04
- SCOOP_REG(sdev->base,SCOOP_CPR) = 0x0000; // 0C
SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10
SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18
SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14
@@ -154,6 +154,7 @@ int __init scoop_probe(struct platform_device *pdev)
SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
reset_scoop(&pdev->dev);
+ SCOOP_REG(devptr->base, SCOOP_CPR) = 0x0000;
SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
new file mode 100644
index 000000000000..978d32e82d39
--- /dev/null
+++ b/arch/arm/common/sharpsl_pm.c
@@ -0,0 +1,839 @@
+/*
+ * Battery and Power Management code for the Sharp SL-C7xx and SL-Cxx00
+ * series of PDAs
+ *
+ * Copyright (c) 2004-2005 Richard Purdie
+ *
+ * Based on code written by Sharp for 2.4 kernels
+ *
+ * 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.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/apm_bios.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/apm.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/hardware/sharpsl_pm.h>
+
+/*
+ * Constants
+ */
+#define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */
+#define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */
+#define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */
+#define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */
+#define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */
+#define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */
+#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */
+#define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */
+#define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */
+#define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */
+
+#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
+#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */
+#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */
+#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */
+#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */
+#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */
+
+/*
+ * Prototypes
+ */
+static int sharpsl_off_charge_battery(void);
+static int sharpsl_check_battery_temp(void);
+static int sharpsl_check_battery_voltage(void);
+static int sharpsl_ac_check(void);
+static int sharpsl_fatal_check(void);
+static int sharpsl_average_value(int ad);
+static void sharpsl_average_clear(void);
+static void sharpsl_charge_toggle(void *private_);
+static void sharpsl_battery_thread(void *private_);
+
+
+/*
+ * Variables
+ */
+struct sharpsl_pm_status sharpsl_pm;
+DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL);
+DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL);
+
+
+static int get_percentage(int voltage)
+{
+ int i = sharpsl_pm.machinfo->bat_levels - 1;
+ struct battery_thresh *thresh;
+
+ if (sharpsl_pm.charge_mode == CHRG_ON)
+ thresh=sharpsl_pm.machinfo->bat_levels_acin;
+ else
+ thresh=sharpsl_pm.machinfo->bat_levels_noac;
+
+ while (i > 0 && (voltage > thresh[i].voltage))
+ i--;
+
+ return thresh[i].percentage;
+}
+
+static int get_apm_status(int voltage)
+{
+ int low_thresh, high_thresh;
+
+ if (sharpsl_pm.charge_mode == CHRG_ON) {
+ high_thresh = sharpsl_pm.machinfo->status_high_acin;
+ low_thresh = sharpsl_pm.machinfo->status_low_acin;
+ } else {
+ high_thresh = sharpsl_pm.machinfo->status_high_noac;
+ low_thresh = sharpsl_pm.machinfo->status_low_noac;
+ }
+
+ if (voltage >= high_thresh)
+ return APM_BATTERY_STATUS_HIGH;
+ if (voltage >= low_thresh)
+ return APM_BATTERY_STATUS_LOW;
+ return APM_BATTERY_STATUS_CRITICAL;
+}
+
+void sharpsl_battery_kick(void)
+{
+ schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
+}
+EXPORT_SYMBOL(sharpsl_battery_kick);
+
+
+static void sharpsl_battery_thread(void *private_)
+{
+ int voltage, percent, apm_status, i = 0;
+
+ if (!sharpsl_pm.machinfo)
+ return;
+
+ sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
+
+ /* Corgi cannot confirm when battery fully charged so periodically kick! */
+ if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON)
+ && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL))
+ schedule_work(&toggle_charger);
+
+ while(1) {
+ voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+
+ if (voltage > 0) break;
+ if (i++ > 5) {
+ voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
+ dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
+ break;
+ }
+ }
+
+ voltage = sharpsl_average_value(voltage);
+ apm_status = get_apm_status(voltage);
+ percent = get_percentage(voltage);
+
+ /* At low battery voltages, the voltage has a tendency to start
+ creeping back up so we try to avoid this here */
+ if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) || percent <= sharpsl_pm.battstat.mainbat_percent) {
+ sharpsl_pm.battstat.mainbat_voltage = voltage;
+ sharpsl_pm.battstat.mainbat_status = apm_status;
+ sharpsl_pm.battstat.mainbat_percent = percent;
+ }
+
+ dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %d\n", voltage,
+ sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
+
+ /* If battery is low. limit backlight intensity to save power. */
+ if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+ && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
+ (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
+ if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
+ corgibl_limit_intensity(1);
+ sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
+ }
+ } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
+ corgibl_limit_intensity(0);
+ sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
+ }
+
+ /* Suspend if critical battery level */
+ if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
+ && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
+ && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
+ sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+ dev_err(sharpsl_pm.dev, "Fatal Off\n");
+ apm_queue_event(APM_CRITICAL_SUSPEND);
+ }
+
+ schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
+}
+
+void sharpsl_pm_led(int val)
+{
+ if (val == SHARPSL_LED_ERROR) {
+ dev_err(sharpsl_pm.dev, "Charging Error!\n");
+ } else if (val == SHARPSL_LED_ON) {
+ dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
+
+ } else {
+ dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
+
+ }
+}
+
+static void sharpsl_charge_on(void)
+{
+ dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
+
+ sharpsl_pm.full_count = 0;
+ sharpsl_pm.charge_mode = CHRG_ON;
+ schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
+ schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
+}
+
+static void sharpsl_charge_off(void)
+{
+ dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
+
+ sharpsl_pm.machinfo->charge(0);
+ sharpsl_pm_led(SHARPSL_LED_OFF);
+ sharpsl_pm.charge_mode = CHRG_OFF;
+
+ schedule_work(&sharpsl_bat);
+}
+
+static void sharpsl_charge_error(void)
+{
+ sharpsl_pm_led(SHARPSL_LED_ERROR);
+ sharpsl_pm.machinfo->charge(0);
+ sharpsl_pm.charge_mode = CHRG_ERROR;
+}
+
+static void sharpsl_charge_toggle(void *private_)
+{
+ dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
+
+ if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+ sharpsl_charge_off();
+ return;
+ } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
+ sharpsl_charge_error();
+ return;
+ }
+
+ sharpsl_pm_led(SHARPSL_LED_ON);
+ sharpsl_pm.machinfo->charge(0);
+ mdelay(SHARPSL_CHARGE_WAIT_TIME);
+ sharpsl_pm.machinfo->charge(1);
+
+ sharpsl_pm.charge_start_time = jiffies;
+}
+
+static void sharpsl_ac_timer(unsigned long data)
+{
+ int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+ dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
+
+ sharpsl_average_clear();
+ if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
+ sharpsl_charge_on();
+ else if (sharpsl_pm.charge_mode == CHRG_ON)
+ sharpsl_charge_off();
+
+ schedule_work(&sharpsl_bat);
+}
+
+
+irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp)
+{
+ /* Delay the event slightly to debounce */
+ /* Must be a smaller delay than the chrg_full_isr below */
+ mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+ return IRQ_HANDLED;
+}
+
+static void sharpsl_chrg_full_timer(unsigned long data)
+{
+ dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
+
+ sharpsl_pm.full_count++;
+
+ if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
+ dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
+ if (sharpsl_pm.charge_mode == CHRG_ON)
+ sharpsl_charge_off();
+ } else if (sharpsl_pm.full_count < 2) {
+ dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
+ schedule_work(&toggle_charger);
+ } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
+ dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
+ schedule_work(&toggle_charger);
+ } else {
+ sharpsl_charge_off();
+ sharpsl_pm.charge_mode = CHRG_DONE;
+ dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
+ }
+}
+
+/* Charging Finished Interrupt (Not present on Corgi) */
+/* Can trigger at the same time as an AC staus change so
+ delay until after that has been processed */
+irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp)
+{
+ if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
+ return IRQ_HANDLED;
+
+ /* delay until after any ac interrupt */
+ mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp)
+{
+ int is_fatal = 0;
+
+ if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) {
+ dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
+ is_fatal = 1;
+ }
+
+ if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) {
+ dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
+ is_fatal = 1;
+ }
+
+ if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
+ sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
+ apm_queue_event(APM_CRITICAL_SUSPEND);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Maintain an average of the last 10 readings
+ */
+#define SHARPSL_CNV_VALUE_NUM 10
+static int sharpsl_ad_index;
+
+static void sharpsl_average_clear(void)
+{
+ sharpsl_ad_index = 0;
+}
+
+static int sharpsl_average_value(int ad)
+{
+ int i, ad_val = 0;
+ static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
+
+ if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
+ sharpsl_ad_index = 0;
+ return ad;
+ }
+
+ sharpsl_ad[sharpsl_ad_index] = ad;
+ sharpsl_ad_index++;
+ if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
+ for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
+ sharpsl_ad[i] = sharpsl_ad[i+1];
+ sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
+ }
+ for (i=0; i < sharpsl_ad_index; i++)
+ ad_val += sharpsl_ad[i];
+
+ return (ad_val / sharpsl_ad_index);
+}
+
+/*
+ * Take an array of 5 integers, remove the maximum and minimum values
+ * and return the average.
+ */
+static int get_select_val(int *val)
+{
+ int i, j, k, temp, sum = 0;
+
+ /* Find MAX val */
+ temp = val[0];
+ j=0;
+ for (i=1; i<5; i++) {
+ if (temp < val[i]) {
+ temp = val[i];
+ j = i;
+ }
+ }
+
+ /* Find MIN val */
+ temp = val[4];
+ k=4;
+ for (i=3; i>=0; i--) {
+ if (temp > val[i]) {
+ temp = val[i];
+ k = i;
+ }
+ }
+
+ for (i=0; i<5; i++)
+ if (i != j && i != k )
+ sum += val[i];
+
+ dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
+
+ return (sum/3);
+}
+
+static int sharpsl_check_battery_temp(void)
+{
+ int val, i, buff[5];
+
+ /* Check battery temperature */
+ for (i=0; i<5; i++) {
+ mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+ sharpsl_pm.machinfo->measure_temp(1);
+ mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
+ buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP);
+ sharpsl_pm.machinfo->measure_temp(0);
+ }
+
+ val = get_select_val(buff);
+
+ dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
+ if (val > SHARPSL_CHARGE_ON_TEMP)
+ return -1;
+
+ return 0;
+}
+
+static int sharpsl_check_battery_voltage(void)
+{
+ int val, i, buff[5];
+
+ /* disable charge, enable discharge */
+ sharpsl_pm.machinfo->charge(0);
+ sharpsl_pm.machinfo->discharge(1);
+ mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+
+ if (sharpsl_pm.machinfo->discharge1)
+ sharpsl_pm.machinfo->discharge1(1);
+
+ /* Check battery voltage */
+ for (i=0; i<5; i++) {
+ buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+ mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+ }
+
+ if (sharpsl_pm.machinfo->discharge1)
+ sharpsl_pm.machinfo->discharge1(0);
+
+ sharpsl_pm.machinfo->discharge(0);
+
+ val = get_select_val(buff);
+ dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
+
+ if (val < SHARPSL_CHARGE_ON_VOLT)
+ return -1;
+
+ return 0;
+}
+
+static int sharpsl_ac_check(void)
+{
+ int temp, i, buff[5];
+
+ for (i=0; i<5; i++) {
+ buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT);
+ mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
+ }
+
+ temp = get_select_val(buff);
+ dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
+
+ if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) {
+ dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ sharpsl_pm.flags |= SHARPSL_SUSPENDED;
+ flush_scheduled_work();
+
+ if (sharpsl_pm.charge_mode == CHRG_ON)
+ sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
+ else
+ sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+
+ return 0;
+}
+
+static int sharpsl_pm_resume(struct platform_device *pdev)
+{
+ /* Clear the reset source indicators as they break the bootloader upon reboot */
+ RCSR = 0x0f;
+ sharpsl_average_clear();
+ sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
+ sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
+
+ return 0;
+}
+
+static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+ dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
+
+ dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
+ /* not charging and AC-IN! */
+
+ if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) {
+ dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
+ sharpsl_pm.charge_mode = CHRG_OFF;
+ sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
+ sharpsl_off_charge_battery();
+ }
+
+ sharpsl_pm.machinfo->presuspend();
+
+ PEDR = 0xffffffff; /* clear it */
+
+ sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
+ if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
+ RTSR &= RTSR_ALE;
+ RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
+ dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
+ sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
+ } else if (alarm_enable) {
+ RTSR &= RTSR_ALE;
+ RTAR = alarm_time;
+ dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
+ } else {
+ dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
+ }
+
+ pxa_pm_enter(state);
+
+ sharpsl_pm.machinfo->postsuspend();
+
+ dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
+}
+
+static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
+{
+ if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
+ {
+ if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
+ dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
+ corgi_goto_sleep(alarm_time, alarm_enable, state);
+ return 1;
+ }
+ if(sharpsl_off_charge_battery()) {
+ dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
+ corgi_goto_sleep(alarm_time, alarm_enable, state);
+ return 1;
+ }
+ dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
+ }
+
+ if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) )
+ {
+ dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
+ corgi_goto_sleep(alarm_time, alarm_enable, state);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int corgi_pxa_pm_enter(suspend_state_t state)
+{
+ unsigned long alarm_time = RTAR;
+ unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
+
+ dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
+
+ corgi_goto_sleep(alarm_time, alarm_status, state);
+
+ while (corgi_enter_suspend(alarm_time,alarm_status,state))
+ {}
+
+ dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
+
+ return 0;
+}
+#endif
+
+
+/*
+ * Check for fatal battery errors
+ * Fatal returns -1
+ */
+static int sharpsl_fatal_check(void)
+{
+ int buff[5], temp, i, acin;
+
+ dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
+
+ /* Check AC-Adapter */
+ acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
+
+ if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+ sharpsl_pm.machinfo->charge(0);
+ udelay(100);
+ sharpsl_pm.machinfo->discharge(1); /* enable discharge */
+ mdelay(SHARPSL_WAIT_DISCHARGE_ON);
+ }
+
+ if (sharpsl_pm.machinfo->discharge1)
+ sharpsl_pm.machinfo->discharge1(1);
+
+ /* Check battery : check inserting battery ? */
+ for (i=0; i<5; i++) {
+ buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT);
+ mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
+ }
+
+ if (sharpsl_pm.machinfo->discharge1)
+ sharpsl_pm.machinfo->discharge1(0);
+
+ if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
+ udelay(100);
+ sharpsl_pm.machinfo->charge(1);
+ sharpsl_pm.machinfo->discharge(0);
+ }
+
+ temp = get_select_val(buff);
+ dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
+
+ if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) ||
+ (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT)))
+ return -1;
+ return 0;
+}
+
+static int sharpsl_off_charge_error(void)
+{
+ dev_err(sharpsl_pm.dev, "Offline Charger: Error occured.\n");
+ sharpsl_pm.machinfo->charge(0);
+ sharpsl_pm_led(SHARPSL_LED_ERROR);
+ sharpsl_pm.charge_mode = CHRG_ERROR;
+ return 1;
+}
+
+/*
+ * Charging Control while suspended
+ * Return 1 - go straight to sleep
+ * Return 0 - sleep or wakeup depending on other factors
+ */
+static int sharpsl_off_charge_battery(void)
+{
+ int time;
+
+ dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
+
+ if (sharpsl_pm.charge_mode == CHRG_OFF) {
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
+
+ /* AC Check */
+ if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
+ return sharpsl_off_charge_error();
+
+ /* Start Charging */
+ sharpsl_pm_led(SHARPSL_LED_ON);
+ sharpsl_pm.machinfo->charge(0);
+ mdelay(SHARPSL_CHARGE_WAIT_TIME);
+ sharpsl_pm.machinfo->charge(1);
+
+ sharpsl_pm.charge_mode = CHRG_ON;
+ sharpsl_pm.full_count = 0;
+
+ return 1;
+ } else if (sharpsl_pm.charge_mode != CHRG_ON) {
+ return 1;
+ }
+
+ if (sharpsl_pm.full_count == 0) {
+ int time;
+
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
+
+ if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
+ return sharpsl_off_charge_error();
+
+ sharpsl_pm.machinfo->charge(0);
+ mdelay(SHARPSL_CHARGE_WAIT_TIME);
+ sharpsl_pm.machinfo->charge(1);
+ sharpsl_pm.charge_mode = CHRG_ON;
+
+ mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+ time = RCNR;
+ while(1) {
+ /* Check if any wakeup event had occured */
+ if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+ return 0;
+ /* Check for timeout */
+ if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
+ return 1;
+ if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n");
+ sharpsl_pm.full_count++;
+ sharpsl_pm.machinfo->charge(0);
+ mdelay(SHARPSL_CHARGE_WAIT_TIME);
+ sharpsl_pm.machinfo->charge(1);
+ return 1;
+ }
+ }
+ }
+
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
+
+ mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
+
+ time = RCNR;
+ while(1) {
+ /* Check if any wakeup event had occured */
+ if (sharpsl_pm.machinfo->charger_wakeup() != 0)
+ return 0;
+ /* Check for timeout */
+ if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
+ if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
+ sharpsl_pm.full_count = 0;
+ }
+ sharpsl_pm.full_count++;
+ return 1;
+ }
+ if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) {
+ dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
+ sharpsl_pm_led(SHARPSL_LED_OFF);
+ sharpsl_pm.machinfo->charge(0);
+ sharpsl_pm.charge_mode = CHRG_DONE;
+ return 1;
+ }
+ }
+}
+
+
+static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
+}
+
+static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
+}
+
+static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
+static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
+
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+static void sharpsl_apm_get_power_status(struct apm_power_info *info)
+{
+ info->ac_line_status = sharpsl_pm.battstat.ac_status;
+
+ if (sharpsl_pm.charge_mode == CHRG_ON)
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ else
+ info->battery_status = sharpsl_pm.battstat.mainbat_status;
+
+ info->battery_flag = (1 << info->battery_status);
+ info->battery_life = sharpsl_pm.battstat.mainbat_percent;
+}
+
+static struct pm_ops sharpsl_pm_ops = {
+ .pm_disk_mode = PM_DISK_FIRMWARE,
+ .prepare = pxa_pm_prepare,
+ .enter = corgi_pxa_pm_enter,
+ .finish = pxa_pm_finish,
+};
+
+static int __init sharpsl_pm_probe(struct platform_device *pdev)
+{
+ if (!pdev->dev.platform_data)
+ return -EINVAL;
+
+ sharpsl_pm.dev = &pdev->dev;
+ sharpsl_pm.machinfo = pdev->dev.platform_data;
+ sharpsl_pm.charge_mode = CHRG_OFF;
+ sharpsl_pm.flags = 0;
+
+ init_timer(&sharpsl_pm.ac_timer);
+ sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
+
+ init_timer(&sharpsl_pm.chrg_full_timer);
+ sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
+
+ sharpsl_pm.machinfo->init();
+
+ device_create_file(&pdev->dev, &dev_attr_battery_percentage);
+ device_create_file(&pdev->dev, &dev_attr_battery_voltage);
+
+ apm_get_power_status = sharpsl_apm_get_power_status;
+
+ pm_set_ops(&sharpsl_pm_ops);
+
+ mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
+
+ return 0;
+}
+
+static int sharpsl_pm_remove(struct platform_device *pdev)
+{
+ pm_set_ops(NULL);
+
+ device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
+ device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
+
+ sharpsl_pm.machinfo->exit();
+
+ del_timer_sync(&sharpsl_pm.chrg_full_timer);
+ del_timer_sync(&sharpsl_pm.ac_timer);
+
+ return 0;
+}
+
+static struct platform_driver sharpsl_pm_driver = {
+ .probe = sharpsl_pm_probe,
+ .remove = sharpsl_pm_remove,
+ .suspend = sharpsl_pm_suspend,
+ .resume = sharpsl_pm_resume,
+ .driver = {
+ .name = "sharpsl-pm",
+ },
+};
+
+static int __devinit sharpsl_pm_init(void)
+{
+ return platform_driver_register(&sharpsl_pm_driver);
+}
+
+static void sharpsl_pm_exit(void)
+{
+ platform_driver_unregister(&sharpsl_pm_driver);
+}
+
+late_initcall(sharpsl_pm_init);
+module_exit(sharpsl_pm_exit);
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
new file mode 100644
index 000000000000..a45ed1687a59
--- /dev/null
+++ b/arch/arm/common/vic.c
@@ -0,0 +1,92 @@
+/*
+ * linux/arch/arm/common/vic.c
+ *
+ * Copyright (C) 1999 - 2003 ARM Limited
+ * Copyright (C) 2000 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 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/list.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/hardware/vic.h>
+
+static void __iomem *vic_base;
+
+static void vic_mask_irq(unsigned int irq)
+{
+ irq -= IRQ_VIC_START;
+ writel(1 << irq, vic_base + VIC_INT_ENABLE_CLEAR);
+}
+
+static void vic_unmask_irq(unsigned int irq)
+{
+ irq -= IRQ_VIC_START;
+ writel(1 << irq, vic_base + VIC_INT_ENABLE);
+}
+
+static struct irqchip vic_chip = {
+ .ack = vic_mask_irq,
+ .mask = vic_mask_irq,
+ .unmask = vic_unmask_irq,
+};
+
+void __init vic_init(void __iomem *base, u32 vic_sources)
+{
+ unsigned int i;
+
+ vic_base = base;
+
+ /* Disable all interrupts initially. */
+
+ writel(0, vic_base + VIC_INT_SELECT);
+ writel(0, vic_base + VIC_INT_ENABLE);
+ writel(~0, vic_base + VIC_INT_ENABLE_CLEAR);
+ writel(0, vic_base + VIC_IRQ_STATUS);
+ writel(0, vic_base + VIC_ITCR);
+ writel(~0, vic_base + VIC_INT_SOFT_CLEAR);
+
+ /*
+ * Make sure we clear all existing interrupts
+ */
+ writel(0, vic_base + VIC_VECT_ADDR);
+ for (i = 0; i < 19; i++) {
+ unsigned int value;
+
+ value = readl(vic_base + VIC_VECT_ADDR);
+ writel(value, vic_base + VIC_VECT_ADDR);
+ }
+
+ for (i = 0; i < 16; i++) {
+ void __iomem *reg = vic_base + VIC_VECT_CNTL0 + (i * 4);
+ writel(VIC_VECT_CNTL_ENABLE | i, reg);
+ }
+
+ writel(32, vic_base + VIC_DEF_VECT_ADDR);
+
+ for (i = 0; i < 32; i++) {
+ unsigned int irq = IRQ_VIC_START + i;
+
+ set_irq_chip(irq, &vic_chip);
+
+ if (vic_sources & (1 << i)) {
+ set_irq_handler(irq, do_level_IRQ);
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+ }
+ }
+}
diff --git a/arch/arm/configs/assabet_defconfig b/arch/arm/configs/assabet_defconfig
index ccbb4c0d58c4..089c9d598409 100644
--- a/arch/arm/configs/assabet_defconfig
+++ b/arch/arm/configs/assabet_defconfig
@@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
new file mode 100644
index 000000000000..5cdd13acf8ff
--- /dev/null
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -0,0 +1,1009 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15
+# Mon Jan 9 20:54:30 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+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_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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+CONFIG_ARCH_AT91RM9200DK=y
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+
+#
+# AT91RM9200 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT 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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# 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=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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x10000000
+CONFIG_MTD_PHYSMAP_LEN=0x200000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 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_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV 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_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_AT91_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=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_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP 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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_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
+
+#
+# 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_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_WBSD is not set
+CONFIG_MMC_AT91RM9200=y
+
+#
+# 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
+# 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
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
new file mode 100644
index 000000000000..20838ccf1da7
--- /dev/null
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -0,0 +1,998 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15
+# Mon Jan 9 20:57:31 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+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_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# 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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+CONFIG_MACH_AT91RM9200EK=y
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+
+#
+# AT91RM9200 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT 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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# 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=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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x10000000
+CONFIG_MTD_PHYSMAP_LEN=0x800000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 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_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 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 is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV 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_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_AT91_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=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_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP 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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# 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=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_S1D13XXX=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_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
+
+#
+# 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_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_WBSD is not set
+CONFIG_MMC_AT91RM9200=y
+
+#
+# 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
+# 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
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 5d92af975d87..cfe6bd8e81cd 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -66,7 +66,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig
index 35e3a99bcbb6..6886001b5366 100644
--- a/arch/arm/configs/bast_defconfig
+++ b/arch/arm/configs/bast_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/cerfcube_defconfig b/arch/arm/configs/cerfcube_defconfig
index d8fe0f40408f..f81a60005cd3 100644
--- a/arch/arm/configs/cerfcube_defconfig
+++ b/arch/arm/configs/cerfcube_defconfig
@@ -65,7 +65,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig
index 908758371405..af9ae5389131 100644
--- a/arch/arm/configs/clps7500_defconfig
+++ b/arch/arm/configs/clps7500_defconfig
@@ -57,7 +57,6 @@ CONFIG_ARCH_CLPS7500=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index 40dfe07a8bce..15468a0cf70e 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -71,7 +71,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 06229026f78b..3c3461e83398 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -87,7 +87,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
new file mode 100644
index 000000000000..885a3184830a
--- /dev/null
+++ b/arch/arm/configs/csb337_defconfig
@@ -0,0 +1,1136 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15
+# Mon Jan 9 21:51:31 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+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_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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+CONFIG_MACH_CSB337=y
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+
+#
+# AT91RM9200 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT 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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# 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=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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+CONFIG_MTD_CSB337=y
+
+#
+# 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_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_AT91_DATAFLASH is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE 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 is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=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_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=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_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP 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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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 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=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=y
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+CONFIG_USB_SERIAL_MCT_U232=y
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_WBSD is not set
+CONFIG_MMC_AT91RM9200=y
+
+#
+# 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
+# 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
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
new file mode 100644
index 000000000000..95a96a5462a0
--- /dev/null
+++ b/arch/arm/configs/csb637_defconfig
@@ -0,0 +1,1116 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15
+# Mon Jan 9 21:52:00 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+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_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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+CONFIG_MACH_CSB637=y
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+
+#
+# AT91RM9200 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT 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_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,38400 initrd=0x20410000,3145728 root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# 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=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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+CONFIG_MTD_CSB637=y
+
+#
+# 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_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_AT91_DATAFLASH is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_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_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE 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 is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=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_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_RTC=y
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=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_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP 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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# 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_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_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 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=y
+CONFIG_USB_SERIAL_CONSOLE=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=y
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+CONFIG_USB_SERIAL_KEYSPAN=y
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+CONFIG_USB_SERIAL_MCT_U232=y
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# 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
+# 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
+# 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_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig
index 6f61929b97a8..afcfff6140f2 100644
--- a/arch/arm/configs/ebsa110_defconfig
+++ b/arch/arm/configs/ebsa110_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
CONFIG_ARCH_EBSA110=y
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/edb7211_defconfig b/arch/arm/configs/edb7211_defconfig
index 78b08ed4d5f4..6ba7355ff85b 100644
--- a/arch/arm/configs/edb7211_defconfig
+++ b/arch/arm/configs/edb7211_defconfig
@@ -57,7 +57,6 @@ CONFIG_BASE_SMALL=0
CONFIG_ARCH_CLPS711X=y
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index fd7c0042bcca..9592e3925c79 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig
index 96342afa9c5f..3c73b707c2f3 100644
--- a/arch/arm/configs/ep80219_defconfig
+++ b/arch/arm/configs/ep80219_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
CONFIG_ARCH_IOP3XX=y
@@ -523,6 +522,7 @@ CONFIG_E100=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
index 9737c4850721..2a612d23120b 100644
--- a/arch/arm/configs/footbridge_defconfig
+++ b/arch/arm/configs/footbridge_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
CONFIG_ARCH_FOOTBRIDGE=y
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/fortunet_defconfig b/arch/arm/configs/fortunet_defconfig
index b6f688d850dc..65dc73a88c43 100644
--- a/arch/arm/configs/fortunet_defconfig
+++ b/arch/arm/configs/fortunet_defconfig
@@ -57,7 +57,6 @@ CONFIG_BASE_SMALL=0
CONFIG_ARCH_CLPS711X=y
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index b9de07de80fe..7a0da0b7facb 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/h7201_defconfig b/arch/arm/configs/h7201_defconfig
index 39c13a354541..116920aecef7 100644
--- a/arch/arm/configs/h7201_defconfig
+++ b/arch/arm/configs/h7201_defconfig
@@ -60,7 +60,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/h7202_defconfig b/arch/arm/configs/h7202_defconfig
index fbf5c244c696..9d62ed16bf57 100644
--- a/arch/arm/configs/h7202_defconfig
+++ b/arch/arm/configs/h7202_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig
index fb41a36a5a68..a45b57582b86 100644
--- a/arch/arm/configs/hackkit_defconfig
+++ b/arch/arm/configs/hackkit_defconfig
@@ -66,7 +66,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index 27ee76825254..d1ba7fdde818 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -65,7 +65,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
CONFIG_ARCH_INTEGRATOR=y
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig
index e71443b97390..32467160a6df 100644
--- a/arch/arm/configs/iq31244_defconfig
+++ b/arch/arm/configs/iq31244_defconfig
@@ -65,7 +65,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
CONFIG_ARCH_IOP3XX=y
@@ -494,6 +493,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
index ab5ad23b27da..b000da753c41 100644
--- a/arch/arm/configs/iq80321_defconfig
+++ b/arch/arm/configs/iq80321_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
CONFIG_ARCH_IOP3XX=y
@@ -416,6 +415,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig
index bb536133ef87..46c79e1efe07 100644
--- a/arch/arm/configs/iq80331_defconfig
+++ b/arch/arm/configs/iq80331_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
CONFIG_ARCH_IOP3XX=y
@@ -497,6 +496,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig
index 305f01f3a729..11959b705d82 100644
--- a/arch/arm/configs/iq80332_defconfig
+++ b/arch/arm/configs/iq80332_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
CONFIG_ARCH_IOP3XX=y
@@ -497,6 +496,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index e6a4d2656fe5..d9d6bb86a6fa 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 5572cf95d5f8..2dc9d499c7d7 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 0fddbde85835..4248123815e9 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index 89b9aa06aa91..ea8f4b478fa3 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -86,7 +86,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index f74c926beb42..4975b914f923 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc1-git5
-# Tue Sep 20 17:26:28 2005
+# Linux kernel version: 2.6.15
+# Tue Jan 3 03:20:40 2006
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -33,6 +33,7 @@ CONFIG_SYSCTL=y
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
@@ -42,7 +43,6 @@ CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
@@ -62,13 +62,29 @@ CONFIG_MODVERSIONS=y
CONFIG_KMOD=y
#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# System Type
#
# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
@@ -83,6 +99,7 @@ CONFIG_ARCH_IXP4XX=y
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_AAEC2000 is not set
@@ -102,6 +119,7 @@ CONFIG_MACH_IXDPG425=y
CONFIG_MACH_IXDP465=y
CONFIG_ARCH_IXCDP1100=y
CONFIG_ARCH_PRPMC1100=y
+CONFIG_MACH_NAS100D=y
CONFIG_ARCH_IXDP4XX=y
CONFIG_CPU_IXP46X=y
# CONFIG_MACH_GTWX5715 is not set
@@ -155,6 +173,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_ALIGNMENT_TRAP=y
#
@@ -173,6 +192,7 @@ CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs"
# At least one emulation must be selected
#
CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
# CONFIG_FPE_FASTFPE is not set
#
@@ -187,6 +207,8 @@ CONFIG_BINFMT_ELF=y
# Power management options
#
CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
CONFIG_APM=y
#
@@ -271,6 +293,10 @@ CONFIG_IP_VS_SH=m
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
# CONFIG_NETFILTER_NETLINK is not set
#
@@ -286,6 +312,7 @@ CONFIG_IP_NF_IRC=m
# CONFIG_IP_NF_NETBIOS_NS is not set
# CONFIG_IP_NF_TFTP is not set
# CONFIG_IP_NF_AMANDA is not set
+# CONFIG_IP_NF_PPTP is not set
CONFIG_IP_NF_QUEUE=m
CONFIG_IP_NF_IPTABLES=m
CONFIG_IP_NF_MATCH_LIMIT=m
@@ -319,6 +346,7 @@ CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
CONFIG_IP_NF_TARGET_TCPMSS=m
+# CONFIG_IP_NF_TARGET_NFQUEUE is not set
CONFIG_IP_NF_NAT=m
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -380,10 +408,18 @@ CONFIG_ECONET=m
CONFIG_ECONET_AUNUDP=y
CONFIG_ECONET_NATIVE=y
CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CLK_JIFFIES=y
# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
# CONFIG_NET_SCH_HFSC is not set
@@ -397,8 +433,10 @@ CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
# CONFIG_NET_SCH_NETEM is not set
CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
+
+#
+# Classification
+#
CONFIG_NET_CLS=y
# CONFIG_NET_CLS_BASIC is not set
CONFIG_NET_CLS_TCINDEX=m
@@ -407,13 +445,14 @@ CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_PERF is not set
-# CONFIG_NET_CLS_IND is not set
# CONFIG_CLS_U32_MARK is not set
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
#
# Network testing
@@ -437,6 +476,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_DEBUG_DRIVER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
@@ -458,6 +502,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
#
# RAM/ROM/Flash chip drivers
@@ -492,7 +537,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
CONFIG_MTD_IXP4XX=y
-# CONFIG_MTD_EDB7312 is not set
# CONFIG_MTD_PCI is not set
# CONFIG_MTD_PLATRAM is not set
@@ -523,6 +567,11 @@ CONFIG_MTD_NAND_IDS=m
# CONFIG_MTD_NAND_NANDSIM is not set
#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
# Parallel port support
#
# CONFIG_PARPORT is not set
@@ -548,14 +597,6 @@ CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
#
@@ -668,6 +709,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
@@ -739,6 +781,7 @@ CONFIG_NET_RADIO=y
#
# Wireless 802.11b ISA/PCI cards support
#
+# CONFIG_AIRO is not set
CONFIG_HERMES=y
# CONFIG_PLX_HERMES is not set
# CONFIG_TMD_HERMES is not set
@@ -782,6 +825,7 @@ CONFIG_WAN_ROUTER_DRIVERS=y
#
# ATM drivers
#
+# CONFIG_ATM_DUMMY is not set
CONFIG_ATM_TCP=m
# CONFIG_ATM_LANAI is not set
# CONFIG_ATM_ENI is not set
@@ -902,6 +946,7 @@ CONFIG_IXP4XX_WATCHDOG=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
# I2C support
@@ -954,6 +999,7 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -1036,6 +1082,10 @@ CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB is not set
#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -1110,6 +1160,7 @@ CONFIG_RAMFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
@@ -1190,7 +1241,9 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_USER is not set
# CONFIG_DEBUG_WAITQ is not set
CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/configs/jornada720_defconfig b/arch/arm/configs/jornada720_defconfig
index b88aeba82bc0..ad1048db96fb 100644
--- a/arch/arm/configs/jornada720_defconfig
+++ b/arch/arm/configs/jornada720_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/lart_defconfig b/arch/arm/configs/lart_defconfig
index 7033829ed145..c3a932844160 100644
--- a/arch/arm/configs/lart_defconfig
+++ b/arch/arm/configs/lart_defconfig
@@ -62,7 +62,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig
index d64706d3ff35..67eaa26c2647 100644
--- a/arch/arm/configs/lpd7a400_defconfig
+++ b/arch/arm/configs/lpd7a400_defconfig
@@ -60,7 +60,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig
index 87cbedfb303f..208d591ebfce 100644
--- a/arch/arm/configs/lpd7a404_defconfig
+++ b/arch/arm/configs/lpd7a404_defconfig
@@ -60,7 +60,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index 4bc8717c6f57..81daadcbe0ba 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/lusl7200_defconfig b/arch/arm/configs/lusl7200_defconfig
index 3ca64cabc92c..42f6a77bc3c0 100644
--- a/arch/arm/configs/lusl7200_defconfig
+++ b/arch/arm/configs/lusl7200_defconfig
@@ -62,7 +62,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/mainstone_defconfig b/arch/arm/configs/mainstone_defconfig
index 153d68594beb..b112bd75bda2 100644
--- a/arch/arm/configs/mainstone_defconfig
+++ b/arch/arm/configs/mainstone_defconfig
@@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/mx1ads_defconfig b/arch/arm/configs/mx1ads_defconfig
index 6517d167acf0..d16f6cd6e039 100644
--- a/arch/arm/configs/mx1ads_defconfig
+++ b/arch/arm/configs/mx1ads_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index 7fb1f7c7bf43..3d35255c64ed 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/netwinder_defconfig b/arch/arm/configs/netwinder_defconfig
index 6e81acf94c2f..2cae1ead9f9b 100644
--- a/arch/arm/configs/netwinder_defconfig
+++ b/arch/arm/configs/netwinder_defconfig
@@ -58,7 +58,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
CONFIG_ARCH_FOOTBRIDGE=y
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index 529f0f72e1e9..ee3ecbd9002d 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/pleb_defconfig b/arch/arm/configs/pleb_defconfig
index 10fec890578d..24e8bdd4cb91 100644
--- a/arch/arm/configs/pleb_defconfig
+++ b/arch/arm/configs/pleb_defconfig
@@ -63,7 +63,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
index 21c327883d8c..b71d31a4bb56 100644
--- a/arch/arm/configs/pxa255-idp_defconfig
+++ b/arch/arm/configs/pxa255-idp_defconfig
@@ -63,7 +63,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/realview_defconfig b/arch/arm/configs/realview_defconfig
index 0485b2f1cc20..3f1ec4e304f7 100644
--- a/arch/arm/configs/realview_defconfig
+++ b/arch/arm/configs/realview_defconfig
@@ -65,7 +65,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig
index 19184c1010ad..b498afdc03b6 100644
--- a/arch/arm/configs/rpc_defconfig
+++ b/arch/arm/configs/rpc_defconfig
@@ -66,7 +66,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3f97590c91f2..33f31080a98c 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -85,7 +85,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/shannon_defconfig b/arch/arm/configs/shannon_defconfig
index e3facc4fe792..d052c8f80515 100644
--- a/arch/arm/configs/shannon_defconfig
+++ b/arch/arm/configs/shannon_defconfig
@@ -62,7 +62,6 @@ CONFIG_OBSOLETE_MODPARM=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/shark_defconfig b/arch/arm/configs/shark_defconfig
index 271823f0d708..c48d17062262 100644
--- a/arch/arm/configs/shark_defconfig
+++ b/arch/arm/configs/shark_defconfig
@@ -66,7 +66,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/simpad_defconfig b/arch/arm/configs/simpad_defconfig
index 5373eeb7d578..2e5a616cc98d 100644
--- a/arch/arm/configs/simpad_defconfig
+++ b/arch/arm/configs/simpad_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/smdk2410_defconfig b/arch/arm/configs/smdk2410_defconfig
index 2c60865fda19..4d123d33c7df 100644
--- a/arch/arm/configs/smdk2410_defconfig
+++ b/arch/arm/configs/smdk2410_defconfig
@@ -58,7 +58,6 @@ CONFIG_BASE_SMALL=0
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 9895539533d6..d1ace3abfd8a 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -87,7 +87,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index d72f2c754268..2687a225aa6a 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -64,7 +64,6 @@ CONFIG_KMOD=y
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_CAMELOT is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_INTEGRATOR is not set
# CONFIG_ARCH_IOP3XX is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index c11169b5ed9a..2ce0e3a27a45 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -2,15 +2,16 @@
# Makefile for the linux kernel.
#
-AFLAGS_head.o := -DKERNEL_RAM_ADDR=$(TEXTADDR)
+AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
# Object file lists.
-obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \
+obj-y := compat.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o
obj-$(CONFIG_APM) += apm.o
+obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o
obj-$(CONFIG_FOOTBRIDGE) += isa.o
obj-$(CONFIG_FIQ) += fiq.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
obj-$(CONFIG_IWMMXT) += iwmmxt.o
AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
index a2843be05557..766b6c05c6db 100644
--- a/arch/arm/kernel/apm.c
+++ b/arch/arm/kernel/apm.c
@@ -18,9 +18,9 @@
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
#include <linux/apm_bios.h>
+#include <linux/capability.h>
#include <linux/sched.h>
#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -81,6 +81,7 @@ struct apm_user {
*/
static int suspends_pending;
static int apm_disabled;
+static int arm_apm_active;
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
@@ -477,9 +478,9 @@ static int kapmd(void *arg)
apm_event_t event;
wait_event_interruptible(kapmd_wait,
- !queue_empty(&kapmd_queue) || !pm_active);
+ !queue_empty(&kapmd_queue) || !arm_apm_active);
- if (!pm_active)
+ if (!arm_apm_active)
break;
spin_lock_irq(&kapmd_queue_lock);
@@ -522,16 +523,11 @@ static int __init apm_init(void)
return -ENODEV;
}
- if (PM_IS_ACTIVE()) {
- printk(KERN_NOTICE "apm: overridden by ACPI.\n");
- return -EINVAL;
- }
-
- pm_active = 1;
+ arm_apm_active = 1;
ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
if (ret < 0) {
- pm_active = 0;
+ arm_apm_active = 0;
return ret;
}
@@ -543,7 +539,7 @@ static int __init apm_init(void)
if (ret != 0) {
remove_proc_entry("apm", NULL);
- pm_active = 0;
+ arm_apm_active = 0;
wake_up(&kapmd_wait);
wait_for_completion(&kapmd_exit);
}
@@ -556,7 +552,7 @@ static void __exit apm_exit(void)
misc_deregister(&apm_device);
remove_proc_entry("apm", NULL);
- pm_active = 0;
+ arm_apm_active = 0;
wake_up(&kapmd_wait);
wait_for_completion(&kapmd_exit);
}
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 9997098009a9..1574941ebfe1 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -35,6 +35,16 @@ extern void __udivsi3(void);
extern void __umodsi3(void);
extern void __do_div64(void);
+extern void __aeabi_idiv(void);
+extern void __aeabi_idivmod(void);
+extern void __aeabi_lasr(void);
+extern void __aeabi_llsl(void);
+extern void __aeabi_llsr(void);
+extern void __aeabi_lmul(void);
+extern void __aeabi_uidiv(void);
+extern void __aeabi_uidivmod(void);
+extern void __aeabi_ulcmp(void);
+
extern void fpundefinstr(void);
extern void fp_enter(void);
@@ -141,6 +151,18 @@ EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(__umodsi3);
EXPORT_SYMBOL(__do_div64);
+#ifdef CONFIG_AEABI
+EXPORT_SYMBOL(__aeabi_idiv);
+EXPORT_SYMBOL(__aeabi_idivmod);
+EXPORT_SYMBOL(__aeabi_lasr);
+EXPORT_SYMBOL(__aeabi_llsl);
+EXPORT_SYMBOL(__aeabi_llsr);
+EXPORT_SYMBOL(__aeabi_lmul);
+EXPORT_SYMBOL(__aeabi_uidiv);
+EXPORT_SYMBOL(__aeabi_uidivmod);
+EXPORT_SYMBOL(__aeabi_ulcmp);
+#endif
+
/* bitops */
EXPORT_SYMBOL(_set_bit_le);
EXPORT_SYMBOL(_test_and_set_bit_le);
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 04d3082a7b94..0abbce8c70bc 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -23,20 +23,15 @@
#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
#endif
/*
- * GCC 2.95.1, 2.95.2: ignores register clobber list in asm().
* GCC 3.0, 3.1: general bad code generation.
* GCC 3.2.0: incorrect function argument offset calculation.
* GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
* (http://gcc.gnu.org/PR8896) and incorrect structure
* initialisation in fs/jffs2/erase.c
*/
-#if __GNUC__ < 2 || \
- (__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \
- (__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \
- __GNUC_PATCHLEVEL__ < 3) || \
- (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
#error Your compiler is too buggy; it is known to miscompile kernels.
-#error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.3
+#error Known good compilers: 3.3
#endif
/* Use marker if you need to separate the values later */
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 55076a75e5bf..75e6f9a94713 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -13,7 +13,7 @@
#define NR_syscalls 328
#else
-__syscall_start:
+100:
/* 0 */ .long sys_restart_syscall
.long sys_exit
.long sys_fork_wrapper
@@ -27,7 +27,7 @@ __syscall_start:
/* 10 */ .long sys_unlink
.long sys_execve_wrapper
.long sys_chdir
- .long sys_time /* used by libc4 */
+ .long OBSOLETE(sys_time) /* used by libc4 */
.long sys_mknod
/* 15 */ .long sys_chmod
.long sys_lchown16
@@ -36,15 +36,15 @@ __syscall_start:
.long sys_lseek
/* 20 */ .long sys_getpid
.long sys_mount
- .long sys_oldumount /* used by libc4 */
+ .long OBSOLETE(sys_oldumount) /* used by libc4 */
.long sys_setuid16
.long sys_getuid16
-/* 25 */ .long sys_stime
+/* 25 */ .long OBSOLETE(sys_stime)
.long sys_ptrace
- .long sys_alarm /* used by libc4 */
+ .long OBSOLETE(sys_alarm) /* used by libc4 */
.long sys_ni_syscall /* was sys_fstat */
.long sys_pause
-/* 30 */ .long sys_utime /* used by libc4 */
+/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */
.long sys_ni_syscall /* was sys_stty */
.long sys_ni_syscall /* was sys_getty */
.long sys_access
@@ -90,21 +90,21 @@ __syscall_start:
.long sys_sigpending
.long sys_sethostname
/* 75 */ .long sys_setrlimit
- .long sys_old_getrlimit /* used by libc4 */
+ .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */
.long sys_getrusage
.long sys_gettimeofday
.long sys_settimeofday
/* 80 */ .long sys_getgroups16
.long sys_setgroups16
- .long old_select /* used by libc4 */
+ .long OBSOLETE(old_select) /* used by libc4 */
.long sys_symlink
.long sys_ni_syscall /* was sys_lstat */
/* 85 */ .long sys_readlink
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir /* used by libc4 */
-/* 90 */ .long old_mmap /* used by libc4 */
+ .long OBSOLETE(old_readdir) /* used by libc4 */
+/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */
.long sys_munmap
.long sys_truncate
.long sys_ftruncate
@@ -116,7 +116,7 @@ __syscall_start:
.long sys_statfs
/* 100 */ .long sys_fstatfs
.long sys_ni_syscall
- .long sys_socketcall
+ .long OBSOLETE(sys_socketcall)
.long sys_syslog
.long sys_setitimer
/* 105 */ .long sys_getitimer
@@ -127,11 +127,11 @@ __syscall_start:
/* 110 */ .long sys_ni_syscall /* was sys_iopl */
.long sys_vhangup
.long sys_ni_syscall
- .long sys_syscall /* call a syscall */
+ .long OBSOLETE(sys_syscall) /* call a syscall */
.long sys_wait4
/* 115 */ .long sys_swapoff
.long sys_sysinfo
- .long sys_ipc
+ .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))
.long sys_fsync
.long sys_sigreturn_wrapper
/* 120 */ .long sys_clone_wrapper
@@ -194,8 +194,8 @@ __syscall_start:
.long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo
.long sys_rt_sigsuspend_wrapper
-/* 180 */ .long sys_pread64
- .long sys_pwrite64
+/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64)
+ .long ABI(sys_pwrite64, sys_oabi_pwrite64)
.long sys_chown16
.long sys_getcwd
.long sys_capget
@@ -207,11 +207,11 @@ __syscall_start:
/* 190 */ .long sys_vfork_wrapper
.long sys_getrlimit
.long sys_mmap2
- .long sys_truncate64
- .long sys_ftruncate64
-/* 195 */ .long sys_stat64
- .long sys_lstat64
- .long sys_fstat64
+ .long ABI(sys_truncate64, sys_oabi_truncate64)
+ .long ABI(sys_ftruncate64, sys_oabi_ftruncate64)
+/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64)
+ .long ABI(sys_lstat64, sys_oabi_lstat64)
+ .long ABI(sys_fstat64, sys_oabi_fstat64)
.long sys_lchown
.long sys_getuid
/* 200 */ .long sys_getgid
@@ -235,11 +235,11 @@ __syscall_start:
.long sys_pivot_root
.long sys_mincore
/* 220 */ .long sys_madvise
- .long sys_fcntl64
+ .long ABI(sys_fcntl64, sys_oabi_fcntl64)
.long sys_ni_syscall /* TUX */
.long sys_ni_syscall
.long sys_gettid
-/* 225 */ .long sys_readahead
+/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead)
.long sys_setxattr
.long sys_lsetxattr
.long sys_fsetxattr
@@ -265,8 +265,8 @@ __syscall_start:
.long sys_exit_group
.long sys_lookup_dcookie
/* 250 */ .long sys_epoll_create
- .long sys_epoll_ctl
- .long sys_epoll_wait
+ .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)
+ .long ABI(sys_epoll_wait, sys_oabi_epoll_wait)
.long sys_remap_file_pages
.long sys_ni_syscall /* sys_set_thread_area */
/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */
@@ -280,8 +280,8 @@ __syscall_start:
.long sys_clock_gettime
.long sys_clock_getres
/* 265 */ .long sys_clock_nanosleep
- .long sys_statfs64
- .long sys_fstatfs64
+ .long sys_statfs64_wrapper
+ .long sys_fstatfs64_wrapper
.long sys_tgkill
.long sys_utimes
/* 270 */ .long sys_arm_fadvise64_64
@@ -312,7 +312,7 @@ __syscall_start:
/* 295 */ .long sys_getsockopt
.long sys_sendmsg
.long sys_recvmsg
- .long sys_semop
+ .long ABI(sys_semop, sys_oabi_semop)
.long sys_semget
/* 300 */ .long sys_semctl
.long sys_msgsnd
@@ -326,7 +326,7 @@ __syscall_start:
.long sys_add_key
/* 310 */ .long sys_request_key
.long sys_keyctl
- .long sys_semtimedop
+ .long ABI(sys_semtimedop, sys_oabi_semtimedop)
/* vserver */ .long sys_ni_syscall
.long sys_ioprio_set
/* 315 */ .long sys_ioprio_get
@@ -336,9 +336,8 @@ __syscall_start:
.long sys_mbind
/* 320 */ .long sys_get_mempolicy
.long sys_set_mempolicy
-__syscall_end:
- .rept NR_syscalls - (__syscall_end - __syscall_start) / 4
+ .rept NR_syscalls - (. - 100b) / 4
.long sys_ni_syscall
.endr
#endif
diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
index e9a36304ec3e..03532769a97f 100644
--- a/arch/arm/kernel/dma-isa.c
+++ b/arch/arm/kernel/dma-isa.c
@@ -18,7 +18,7 @@
*/
#include <linux/ioport.h>
#include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <asm/dma.h>
#include <asm/io.h>
@@ -65,37 +65,41 @@ static void isa_enable_dma(dmach_t channel, dma_t *dma)
{
if (dma->invalid) {
unsigned long address, length;
- unsigned int mode, direction;
+ unsigned int mode;
+ enum dma_data_direction direction;
mode = channel & 3;
switch (dma->dma_mode & DMA_MODE_MASK) {
case DMA_MODE_READ:
mode |= ISA_DMA_MODE_READ;
- direction = PCI_DMA_FROMDEVICE;
+ direction = DMA_FROM_DEVICE;
break;
case DMA_MODE_WRITE:
mode |= ISA_DMA_MODE_WRITE;
- direction = PCI_DMA_TODEVICE;
+ direction = DMA_TO_DEVICE;
break;
case DMA_MODE_CASCADE:
mode |= ISA_DMA_MODE_CASCADE;
- direction = PCI_DMA_BIDIRECTIONAL;
+ direction = DMA_BIDIRECTIONAL;
break;
default:
- direction = PCI_DMA_NONE;
+ direction = DMA_NONE;
break;
}
- if (!dma->using_sg) {
+ if (!dma->sg) {
/*
* Cope with ISA-style drivers which expect cache
* coherence.
*/
- dma->buf.dma_address = pci_map_single(NULL,
- dma->buf.__address, dma->buf.length,
+ dma->sg = &dma->buf;
+ dma->sgcount = 1;
+ dma->buf.length = dma->count;
+ dma->buf.dma_address = dma_map_single(NULL,
+ dma->addr, dma->count,
direction);
}
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index 2b7883884234..5a0f4bc5da95 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -12,8 +12,6 @@
* DMA facilities.
*/
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mman.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
@@ -23,8 +21,7 @@
#include <asm/mach/dma.h>
DEFINE_SPINLOCK(dma_spin_lock);
-
-#if MAX_DMA_CHANNELS > 0
+EXPORT_SYMBOL(dma_spin_lock);
static dma_t dma_chan[MAX_DMA_CHANNELS];
@@ -81,6 +78,7 @@ bad_dma:
busy:
return -EBUSY;
}
+EXPORT_SYMBOL(request_dma);
/*
* Free DMA channel
@@ -112,6 +110,7 @@ void free_dma(dmach_t channel)
bad_dma:
printk(KERN_ERR "dma: trying to free DMA%d\n", channel);
}
+EXPORT_SYMBOL(free_dma);
/* Set DMA Scatter-Gather list
*/
@@ -125,15 +124,15 @@ void set_dma_sg (dmach_t channel, struct scatterlist *sg, int nr_sg)
dma->sg = sg;
dma->sgcount = nr_sg;
- dma->using_sg = 1;
dma->invalid = 1;
}
+EXPORT_SYMBOL(set_dma_sg);
/* Set DMA address
*
* Copy address to the structure, and set the invalid bit
*/
-void set_dma_addr (dmach_t channel, unsigned long physaddr)
+void __set_dma_addr (dmach_t channel, void *addr)
{
dma_t *dma = dma_chan + channel;
@@ -141,12 +140,11 @@ void set_dma_addr (dmach_t channel, unsigned long physaddr)
printk(KERN_ERR "dma%d: altering DMA address while "
"DMA active\n", channel);
- dma->sg = &dma->buf;
- dma->sgcount = 1;
- dma->buf.__address = bus_to_virt(physaddr);
- dma->using_sg = 0;
+ dma->sg = NULL;
+ dma->addr = addr;
dma->invalid = 1;
}
+EXPORT_SYMBOL(__set_dma_addr);
/* Set DMA byte count
*
@@ -160,12 +158,11 @@ void set_dma_count (dmach_t channel, unsigned long count)
printk(KERN_ERR "dma%d: altering DMA count while "
"DMA active\n", channel);
- dma->sg = &dma->buf;
- dma->sgcount = 1;
- dma->buf.length = count;
- dma->using_sg = 0;
+ dma->sg = NULL;
+ dma->count = count;
dma->invalid = 1;
}
+EXPORT_SYMBOL(set_dma_count);
/* Set DMA direction mode
*/
@@ -180,6 +177,7 @@ void set_dma_mode (dmach_t channel, dmamode_t mode)
dma->dma_mode = mode;
dma->invalid = 1;
}
+EXPORT_SYMBOL(set_dma_mode);
/* Enable DMA channel
*/
@@ -200,6 +198,7 @@ free_dma:
printk(KERN_ERR "dma%d: trying to enable free DMA\n", channel);
BUG();
}
+EXPORT_SYMBOL(enable_dma);
/* Disable DMA channel
*/
@@ -220,6 +219,7 @@ free_dma:
printk(KERN_ERR "dma%d: trying to disable free DMA\n", channel);
BUG();
}
+EXPORT_SYMBOL(disable_dma);
/*
* Is the specified DMA channel active?
@@ -233,6 +233,7 @@ void set_dma_page(dmach_t channel, char pagenr)
{
printk(KERN_ERR "dma%d: trying to set_dma_page\n", channel);
}
+EXPORT_SYMBOL(set_dma_page);
void set_dma_speed(dmach_t channel, int cycle_ns)
{
@@ -243,6 +244,7 @@ void set_dma_speed(dmach_t channel, int cycle_ns)
ret = dma->d_ops->setspeed(channel, dma, cycle_ns);
dma->speed = ret;
}
+EXPORT_SYMBOL(set_dma_speed);
int get_dma_residue(dmach_t channel)
{
@@ -254,49 +256,12 @@ int get_dma_residue(dmach_t channel)
return ret;
}
+EXPORT_SYMBOL(get_dma_residue);
-void __init init_dma(void)
+static int __init init_dma(void)
{
arch_dma_init(dma_chan);
-}
-
-#else
-
-int request_dma(dmach_t channel, const char *device_id)
-{
- return -EINVAL;
-}
-
-int get_dma_residue(dmach_t channel)
-{
return 0;
}
-#define GLOBAL_ALIAS(_a,_b) asm (".set " #_a "," #_b "; .globl " #_a)
-GLOBAL_ALIAS(disable_dma, get_dma_residue);
-GLOBAL_ALIAS(enable_dma, get_dma_residue);
-GLOBAL_ALIAS(free_dma, get_dma_residue);
-GLOBAL_ALIAS(get_dma_list, get_dma_residue);
-GLOBAL_ALIAS(set_dma_mode, get_dma_residue);
-GLOBAL_ALIAS(set_dma_page, get_dma_residue);
-GLOBAL_ALIAS(set_dma_count, get_dma_residue);
-GLOBAL_ALIAS(set_dma_addr, get_dma_residue);
-GLOBAL_ALIAS(set_dma_sg, get_dma_residue);
-GLOBAL_ALIAS(set_dma_speed, get_dma_residue);
-GLOBAL_ALIAS(init_dma, get_dma_residue);
-
-#endif
-
-EXPORT_SYMBOL(request_dma);
-EXPORT_SYMBOL(free_dma);
-EXPORT_SYMBOL(enable_dma);
-EXPORT_SYMBOL(disable_dma);
-EXPORT_SYMBOL(set_dma_addr);
-EXPORT_SYMBOL(set_dma_count);
-EXPORT_SYMBOL(set_dma_mode);
-EXPORT_SYMBOL(set_dma_page);
-EXPORT_SYMBOL(get_dma_residue);
-EXPORT_SYMBOL(set_dma_sg);
-EXPORT_SYMBOL(set_dma_speed);
-
-EXPORT_SYMBOL(dma_spin_lock);
+core_initcall(init_dma);
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index dceb826bd216..74ea29c3205e 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -40,6 +40,7 @@
#include <linux/proc_fs.h>
#include <linux/device.h>
#include <linux/init.h>
+#include <linux/mutex.h>
#include <asm/dma.h>
#include <asm/ecard.h>
@@ -206,7 +207,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
static DECLARE_WAIT_QUEUE_HEAD(ecard_wait);
static struct ecard_request *ecard_req;
-static DECLARE_MUTEX(ecard_sem);
+static DEFINE_MUTEX(ecard_mutex);
/*
* Set up the expansion card daemon's page tables.
@@ -299,7 +300,7 @@ static void ecard_call(struct ecard_request *req)
req->complete = &completion;
- down(&ecard_sem);
+ mutex_lock(&ecard_mutex);
ecard_req = req;
wake_up(&ecard_wait);
@@ -307,7 +308,7 @@ static void ecard_call(struct ecard_request *req)
* Now wait for kecardd to run.
*/
wait_for_completion(&completion);
- up(&ecard_sem);
+ mutex_unlock(&ecard_mutex);
}
/* ======================= Mid-level card control ===================== */
@@ -1146,9 +1147,11 @@ static void ecard_drv_shutdown(struct device *dev)
struct ecard_driver *drv = ECARD_DRV(dev->driver);
struct ecard_request req;
- if (drv->shutdown)
- drv->shutdown(ec);
- ecard_release(ec);
+ if (dev->driver) {
+ if (drv->shutdown)
+ drv->shutdown(ec);
+ ecard_release(ec);
+ }
/*
* If this card has a loader, call the reset handler.
@@ -1163,9 +1166,6 @@ static void ecard_drv_shutdown(struct device *dev)
int ecard_register_driver(struct ecard_driver *drv)
{
drv->drv.bus = &ecard_bus_type;
- drv->drv.probe = ecard_drv_probe;
- drv->drv.remove = ecard_drv_remove;
- drv->drv.shutdown = ecard_drv_shutdown;
return driver_register(&drv->drv);
}
@@ -1194,6 +1194,9 @@ struct bus_type ecard_bus_type = {
.name = "ecard",
.dev_attrs = ecard_dev_attrs,
.match = ecard_match,
+ .probe = ecard_drv_probe,
+ .remove = ecard_drv_remove,
+ .shutdown = ecard_drv_shutdown,
};
static int ecard_bus_init(void)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2a8d27e18fa7..d401d908c463 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -3,6 +3,7 @@
*
* Copyright (C) 1996,1997,1998 Russell King.
* ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk)
+ * nommu support by Hyok S. Choi (hyok.choi@samsung.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
@@ -18,8 +19,6 @@
#include <asm/memory.h>
#include <asm/glue.h>
#include <asm/vfpmacros.h>
-#include <asm/hardware.h> /* should be moved into entry-macro.S */
-#include <asm/arch/irqs.h> /* should be moved into entry-macro.S */
#include <asm/arch/entry-macro.S>
#include "entry-header.S"
@@ -106,14 +105,24 @@ common_invalid:
/*
* SVC mode handlers
*/
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+#define SPFIX(code...) code
+#else
+#define SPFIX(code...)
+#endif
+
.macro svc_entry
sub sp, sp, #S_FRAME_SIZE
+ SPFIX( tst sp, #4 )
+ SPFIX( bicne sp, sp, #4 )
stmib sp, {r1 - r12}
ldmia r0, {r1 - r3}
add r5, sp, #S_SP @ here for interlock avoidance
mov r4, #-1 @ "" "" "" ""
add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
+ SPFIX( addne r0, r0, #4 )
str r1, [sp] @ save the "real" r0 copied
@ from the exception stack
@@ -304,7 +313,14 @@ __pabt_svc:
/*
* User mode handlers
+ *
+ * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE
*/
+
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
+#error "sizeof(struct pt_regs) must be a multiple of 8"
+#endif
+
.macro usr_entry
sub sp, sp, #S_FRAME_SIZE
stmib sp, {r1 - r12}
@@ -540,7 +556,11 @@ ENTRY(__switch_to)
add ip, r1, #TI_CPU_SAVE
ldr r3, [r2, #TI_TP_VALUE]
stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
+#ifndef CONFIG_MMU
+ add r2, r2, #TI_CPU_DOMAIN
+#else
ldr r6, [r2, #TI_CPU_DOMAIN]!
+#endif
#if __LINUX_ARM_ARCH__ >= 6
#ifdef CONFIG_CPU_MPCORE
clrex
@@ -558,7 +578,9 @@ ENTRY(__switch_to)
mov r4, #0xffff0fff
str r3, [r4, #-15] @ TLS val at 0xffff0ff0
#endif
+#ifdef CONFIG_MMU
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
+#endif
#ifdef CONFIG_VFP
@ Always disable VFP so we can lazily save/restore the old
@ state. This occurs in the context of the previous thread.
@@ -713,8 +735,11 @@ __kuser_cmpxchg: @ 0xffff0fc0
* The kernel itself must perform the operation.
* A special ghost syscall is used for that (see traps.c).
*/
+ stmfd sp!, {r7, lr}
+ mov r7, #0xff00 @ 0xfff0 into r7 for EABI
+ orr r7, r7, #0xf0
swi #0x9ffff0
- mov pc, lr
+ ldmfd sp!, {r7, pc}
#elif __LINUX_ARM_ARCH__ < 6
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index e2b42997ad33..2b92ce85f97f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -98,20 +98,14 @@ ENTRY(ret_from_fork)
run on an ARM7 and we can save a couple of instructions.
--pb */
#ifdef CONFIG_CPU_ARM710
- .macro arm710_bug_check, instr, temp
- and \temp, \instr, #0x0f000000 @ check for SWI
- teq \temp, #0x0f000000
- bne .Larm700bug
- .endm
-
-.Larm700bug:
+#define A710(code...) code
+.Larm710bug:
ldmia sp, {r0 - lr}^ @ Get calling r0 - lr
mov r0, r0
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4
#else
- .macro arm710_bug_check, instr, temp
- .endm
+#define A710(code...)
#endif
.align 5
@@ -129,14 +123,50 @@ ENTRY(vector_swi)
/*
* Get the system call number.
*/
+
+#if defined(CONFIG_OABI_COMPAT)
+
+ /*
+ * If we have CONFIG_OABI_COMPAT then we need to look at the swi
+ * value to determine if it is an EABI or an old ABI call.
+ */
#ifdef CONFIG_ARM_THUMB
+ tst r8, #PSR_T_BIT
+ movne r10, #0 @ no thumb OABI emulation
+ ldreq r10, [lr, #-4] @ get SWI instruction
+#else
+ ldr r10, [lr, #-4] @ get SWI instruction
+ A710( and ip, r10, #0x0f000000 @ check for SWI )
+ A710( teq ip, #0x0f000000 )
+ A710( bne .Larm710bug )
+#endif
+
+#elif defined(CONFIG_AEABI)
+
+ /*
+ * Pure EABI user space always put syscall number into scno (r7).
+ */
+ A710( ldr ip, [lr, #-4] @ get SWI instruction )
+ A710( and ip, ip, #0x0f000000 @ check for SWI )
+ A710( teq ip, #0x0f000000 )
+ A710( bne .Larm710bug )
+
+#elif defined(CONFIG_ARM_THUMB)
+
+ /* Legacy ABI only, possibly thumb mode. */
tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs
addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in
ldreq scno, [lr, #-4]
+
#else
+
+ /* Legacy ABI only. */
ldr scno, [lr, #-4] @ get SWI instruction
+ A710( and ip, scno, #0x0f000000 @ check for SWI )
+ A710( teq ip, #0x0f000000 )
+ A710( bne .Larm710bug )
+
#endif
- arm710_bug_check scno, ip
#ifdef CONFIG_ALIGNMENT_TRAP
ldr ip, __cr_alignment
@@ -145,18 +175,31 @@ ENTRY(vector_swi)
#endif
enable_irq
- stmdb sp!, {r4, r5} @ push fifth and sixth args
-
get_thread_info tsk
+ adr tbl, sys_call_table @ load syscall table pointer
ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
+
+#if defined(CONFIG_OABI_COMPAT)
+ /*
+ * If the swi argument is zero, this is an EABI call and we do nothing.
+ *
+ * If this is an old ABI call, get the syscall number into scno and
+ * get the old ABI syscall table address.
+ */
+ bics r10, r10, #0xff000000
+ eorne scno, r10, #__NR_OABI_SYSCALL_BASE
+ ldrne tbl, =sys_oabi_call_table
+#elif !defined(CONFIG_AEABI)
bic scno, scno, #0xff000000 @ mask off SWI op-code
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
- adr tbl, sys_call_table @ load syscall table pointer
+#endif
+
+ stmdb sp!, {r4, r5} @ push fifth and sixth args
tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
bne __sys_trace
- adr lr, ret_fast_syscall @ return address
cmp scno, #NR_syscalls @ check upper syscall limit
+ adr lr, ret_fast_syscall @ return address
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
add r1, sp, #S_OFF
@@ -171,11 +214,13 @@ ENTRY(vector_swi)
* context switches, and waiting for our parent to respond.
*/
__sys_trace:
+ mov r2, scno
add r1, sp, #S_OFF
mov r0, #0 @ trace entry [IP = 0]
bl syscall_trace
adr lr, __sys_trace_return @ return address
+ mov scno, r0 @ syscall number (possibly new)
add r1, sp, #S_R0 + S_OFF @ pointer to regs
cmp scno, #NR_syscalls @ check upper syscall limit
ldmccia r1, {r0 - r3} @ have to reload r0 - r3
@@ -184,6 +229,7 @@ __sys_trace:
__sys_trace_return:
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
+ mov r2, scno
mov r1, sp
mov r0, #1 @ trace exit [IP = 1]
bl syscall_trace
@@ -195,10 +241,24 @@ __sys_trace_return:
__cr_alignment:
.word cr_alignment
#endif
+ .ltorg
+
+/*
+ * This is the syscall table declaration for native ABI syscalls.
+ * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
+ */
+#define ABI(native, compat) native
+#ifdef CONFIG_AEABI
+#define OBSOLETE(syscall) sys_ni_syscall
+#else
+#define OBSOLETE(syscall) syscall
+#endif
.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"
+#undef ABI
+#undef OBSOLETE
/*============================================================================
* Special system call wrappers
@@ -207,7 +267,7 @@ ENTRY(sys_call_table)
@ r8 = syscall table
.type sys_syscall, #function
sys_syscall:
- eor scno, r0, #__NR_SYSCALL_BASE
+ eor scno, r0, #__NR_OABI_SYSCALL_BASE
cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
cmpne scno, #NR_syscalls @ check range
stmloia sp, {r5, r6} @ shuffle args
@@ -255,6 +315,16 @@ sys_sigaltstack_wrapper:
ldr r2, [sp, #S_OFF + S_SP]
b do_sigaltstack
+sys_statfs64_wrapper:
+ teq r1, #88
+ moveq r1, #84
+ b sys_statfs64
+
+sys_fstatfs64_wrapper:
+ teq r1, #88
+ moveq r1, #84
+ b sys_fstatfs64
+
/*
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
* offset, we return EINVAL.
@@ -271,3 +341,49 @@ sys_mmap2:
str r5, [sp, #4]
b do_mmap2
#endif
+
+#ifdef CONFIG_OABI_COMPAT
+
+/*
+ * These are syscalls with argument register differences
+ */
+
+sys_oabi_pread64:
+ stmia sp, {r3, r4}
+ b sys_pread64
+
+sys_oabi_pwrite64:
+ stmia sp, {r3, r4}
+ b sys_pwrite64
+
+sys_oabi_truncate64:
+ mov r3, r2
+ mov r2, r1
+ b sys_truncate64
+
+sys_oabi_ftruncate64:
+ mov r3, r2
+ mov r2, r1
+ b sys_ftruncate64
+
+sys_oabi_readahead:
+ str r3, [sp]
+ mov r3, r2
+ mov r2, r1
+ b sys_readahead
+
+/*
+ * Let's declare a second syscall table for old ABI binaries
+ * using the compatibility syscall entries.
+ */
+#define ABI(native, compat) compat
+#define OBSOLETE(syscall) syscall
+
+ .type sys_oabi_call_table, #object
+ENTRY(sys_oabi_call_table)
+#include "calls.S"
+#undef ABI
+#undef OBSOLETE
+
+#endif
+
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 648cfff93138..55c99cdab7d6 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -19,6 +19,7 @@
@
@ Most of the stack format comes from struct pt_regs, but with
@ the addition of 8 bytes for storing syscall args 5 and 6.
+@ This _must_ remain a multiple of 8 for EABI.
@
#define S_OFF 8
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index 9299dfc25698..1ec3f7faa259 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -101,7 +101,7 @@ void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
ldmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
mov r0, r0\n\
- ldmea fp, {fp, sp, pc}"
+ ldmfd sp, {fp, sp, pc}"
: "=&r" (tmp)
: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
}
@@ -119,7 +119,7 @@ void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
stmia %1, {r8 - r14}\n\
msr cpsr_c, %0 @ return to SVC mode\n\
mov r0, r0\n\
- ldmea fp, {fp, sp, pc}"
+ ldmfd sp, {fp, sp, pc}"
: "=&r" (tmp)
: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
}
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index d7d69fd7039f..1aca1775b28f 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -33,6 +33,8 @@
#define MACHINFO_PGOFFIO 12
#define MACHINFO_NAME 16
+#define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET)
+
/*
* swapper_pg_dir is the virtual address of the initial page table.
* We place the page tables 16K below KERNEL_RAM_ADDR. Therefore, we must
@@ -249,12 +251,11 @@ __turn_mmu_on:
* r10 = procinfo
*
* Returns:
- * r0, r3, r5, r6, r7 corrupted
+ * r0, r3, r6, r7 corrupted
* r4 = physical page table address
*/
.type __create_page_tables, %function
__create_page_tables:
- ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram
pgtbl r4 @ page table address
/*
@@ -301,7 +302,7 @@ __create_page_tables:
* Then map first 1MB of ram in case it contains our boot params.
*/
add r0, r4, #PAGE_OFFSET >> 18
- orr r6, r5, r7
+ orr r6, r7, #PHYS_OFFSET
str r6, [r0]
#ifdef CONFIG_XIP_KERNEL
@@ -309,7 +310,7 @@ __create_page_tables:
* Map some ram to cover our .data and .bss areas.
* Mapping 3MB should be plenty.
*/
- sub r3, r4, r5
+ sub r3, r4, #PHYS_OFFSET
mov r3, r3, lsr #20
add r0, r0, r3, lsl #2
add r6, r6, r3, lsl #20
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index d7099dbbb879..1d50d2b98f55 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -684,8 +684,12 @@ int setup_irq(unsigned int irq, struct irqaction *new)
spin_lock_irqsave(&irq_controller_lock, flags);
p = &desc->action;
if ((old = *p) != NULL) {
- /* Can't share interrupts unless both agree to */
- if (!(old->flags & new->flags & SA_SHIRQ)) {
+ /*
+ * Can't share interrupts unless both agree to and are
+ * the same type.
+ */
+ if (!(old->flags & new->flags & SA_SHIRQ) ||
+ (~old->flags & new->flags) & SA_TRIGGER_MASK) {
spin_unlock_irqrestore(&irq_controller_lock, flags);
return -EBUSY;
}
@@ -705,6 +709,13 @@ int setup_irq(unsigned int irq, struct irqaction *new)
desc->running = 0;
desc->pending = 0;
desc->disable_depth = 1;
+
+ if (new->flags & SA_TRIGGER_MASK &&
+ desc->chip->set_type) {
+ unsigned int type = new->flags & SA_TRIGGER_MASK;
+ desc->chip->set_type(irq, type);
+ }
+
if (!desc->noautoenable) {
desc->disable_depth = 0;
desc->chip->unmask(irq);
@@ -1027,7 +1038,6 @@ void __init init_irq_proc(void)
void __init init_IRQ(void)
{
struct irqdesc *desc;
- extern void init_dma(void);
int irq;
#ifdef CONFIG_SMP
@@ -1041,7 +1051,6 @@ void __init init_IRQ(void)
}
init_arch_irq();
- init_dma();
}
static int __init noirqdebug_setup(char *str)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 30494aab829a..4b4e4cf79c80 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,10 +28,9 @@
#include <linux/init.h>
#include <linux/cpu.h>
-#include <asm/system.h>
-#include <asm/io.h>
#include <asm/leds.h>
#include <asm/processor.h>
+#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/mach/time.h>
@@ -343,10 +342,10 @@ void flush_thread(void)
void release_thread(struct task_struct *dead_task)
{
#if defined(CONFIG_VFP)
- vfp_release_thread(&dead_task->thread_info->vfpstate);
+ vfp_release_thread(&task_thread_info(dead_task)->vfpstate);
#endif
#if defined(CONFIG_IWMMXT)
- iwmmxt_task_release(dead_task->thread_info);
+ iwmmxt_task_release(task_thread_info(dead_task));
#endif
}
@@ -356,10 +355,9 @@ int
copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *thread = p->thread_info;
- struct pt_regs *childregs;
+ struct thread_info *thread = task_thread_info(p);
+ struct pt_regs *childregs = task_pt_regs(p);
- childregs = (void *)thread + THREAD_START_SP - sizeof(*regs);
*childregs = *regs;
childregs->ARM_r0 = 0;
childregs->ARM_sp = stack_start;
@@ -461,8 +459,8 @@ unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_start = (unsigned long)(p->thread_info + 1);
- stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE;
+ stack_start = (unsigned long)end_of_stack(p);
+ stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
fp = thread_saved_fp(p);
do {
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 2b84f78d7b0f..7b6256bb590e 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -55,23 +55,6 @@
#endif
/*
- * Get the address of the live pt_regs for the specified task.
- * These are saved onto the top kernel stack when the process
- * is not running.
- *
- * Note: if a user thread is execve'd from kernel space, the
- * kernel stack will not be empty on entry to the kernel, so
- * ptracing these tasks will fail.
- */
-static inline struct pt_regs *
-get_user_regs(struct task_struct *task)
-{
- return (struct pt_regs *)
- ((unsigned long)task->thread_info + THREAD_SIZE -
- 8 - sizeof(struct pt_regs));
-}
-
-/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the THREAD.
* this routine assumes that all the privileged stacks are in our
@@ -79,7 +62,7 @@ get_user_regs(struct task_struct *task)
*/
static inline long get_user_reg(struct task_struct *task, int offset)
{
- return get_user_regs(task)->uregs[offset];
+ return task_pt_regs(task)->uregs[offset];
}
/*
@@ -91,7 +74,7 @@ static inline long get_user_reg(struct task_struct *task, int offset)
static inline int
put_user_reg(struct task_struct *task, int offset, long data)
{
- struct pt_regs newregs, *regs = get_user_regs(task);
+ struct pt_regs newregs, *regs = task_pt_regs(task);
int ret = -EINVAL;
newregs = *regs;
@@ -421,7 +404,7 @@ void ptrace_set_bpt(struct task_struct *child)
u32 insn;
int res;
- regs = get_user_regs(child);
+ regs = task_pt_regs(child);
pc = instruction_pointer(regs);
if (thumb_mode(regs)) {
@@ -572,7 +555,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
*/
static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
{
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}
@@ -587,7 +570,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
ret = -EFAULT;
if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
ret = -EINVAL;
if (valid_user_regs(&newregs)) {
@@ -604,7 +587,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
*/
static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp)
{
- return copy_to_user(ufp, &tsk->thread_info->fpstate,
+ return copy_to_user(ufp, &task_thread_info(tsk)->fpstate,
sizeof(struct user_fp)) ? -EFAULT : 0;
}
@@ -613,7 +596,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void __user *ufp)
*/
static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
{
- struct thread_info *thread = tsk->thread_info;
+ struct thread_info *thread = task_thread_info(tsk);
thread->used_cp[1] = thread->used_cp[2] = 1;
return copy_from_user(&thread->fpstate, ufp,
sizeof(struct user_fp)) ? -EFAULT : 0;
@@ -626,7 +609,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
*/
static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
{
- struct thread_info *thread = tsk->thread_info;
+ struct thread_info *thread = task_thread_info(tsk);
void *ptr = &thread->fpstate;
if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
@@ -643,7 +626,7 @@ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
*/
static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
{
- struct thread_info *thread = tsk->thread_info;
+ struct thread_info *thread = task_thread_info(tsk);
void *ptr = &thread->fpstate;
if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
@@ -779,10 +762,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
case PTRACE_GET_THREAD_AREA:
- ret = put_user(child->thread_info->tp_value,
+ ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);
break;
+ case PTRACE_SET_SYSCALL:
+ ret = 0;
+ child->ptrace_message = data;
+ break;
+
default:
ret = ptrace_request(child, request, addr, data);
break;
@@ -791,14 +779,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret;
}
-asmlinkage void syscall_trace(int why, struct pt_regs *regs)
+asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
{
unsigned long ip;
if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return;
+ return scno;
if (!(current->ptrace & PT_PTRACED))
- return;
+ return scno;
/*
* Save IP. IP is used to denote syscall entry/exit:
@@ -807,6 +795,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
ip = regs->ARM_ip;
regs->ARM_ip = why;
+ current->ptrace_message = scno;
+
/* 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)
@@ -821,4 +811,6 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
current->exit_code = 0;
}
regs->ARM_ip = ip;
+
+ return current->ptrace_message;
}
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 4c31f2923055..981fe5c6ccbe 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -177,41 +177,42 @@ int __down_trylock(struct semaphore * sem)
* ip contains the semaphore pointer on entry. Save the C-clobbered
* registers (r0 to r3 and lr), but not ip, as we use it as a return
* value in some cases..
+ * To remain AAPCS compliant (64-bit stack align) we save r4 as well.
*/
asm(" .section .sched.text,\"ax\",%progbits \n\
.align 5 \n\
.globl __down_failed \n\
__down_failed: \n\
- stmfd sp!, {r0 - r3, lr} \n\
+ stmfd sp!, {r0 - r4, lr} \n\
mov r0, ip \n\
bl __down \n\
- ldmfd sp!, {r0 - r3, pc} \n\
+ ldmfd sp!, {r0 - r4, pc} \n\
\n\
.align 5 \n\
.globl __down_interruptible_failed \n\
__down_interruptible_failed: \n\
- stmfd sp!, {r0 - r3, lr} \n\
+ stmfd sp!, {r0 - r4, lr} \n\
mov r0, ip \n\
bl __down_interruptible \n\
mov ip, r0 \n\
- ldmfd sp!, {r0 - r3, pc} \n\
+ ldmfd sp!, {r0 - r4, pc} \n\
\n\
.align 5 \n\
.globl __down_trylock_failed \n\
__down_trylock_failed: \n\
- stmfd sp!, {r0 - r3, lr} \n\
+ stmfd sp!, {r0 - r4, lr} \n\
mov r0, ip \n\
bl __down_trylock \n\
mov ip, r0 \n\
- ldmfd sp!, {r0 - r3, pc} \n\
+ ldmfd sp!, {r0 - r4, pc} \n\
\n\
.align 5 \n\
.globl __up_wakeup \n\
__up_wakeup: \n\
- stmfd sp!, {r0 - r3, lr} \n\
+ stmfd sp!, {r0 - r4, lr} \n\
mov r0, ip \n\
bl __up \n\
- ldmfd sp!, {r0 - r3, pc} \n\
+ ldmfd sp!, {r0 - r4, pc} \n\
");
EXPORT_SYMBOL(__down_failed);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 85774165e9fd..c45d10d07bde 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -26,8 +26,6 @@
#include <asm/cpu.h>
#include <asm/elf.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
#include <asm/procinfo.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -207,7 +205,7 @@ static const char *proc_arch[] = {
"5TE",
"5TEJ",
"6TEJ",
- "?(10)",
+ "7",
"?(11)",
"?(12)",
"?(13)",
@@ -260,14 +258,17 @@ int cpu_architecture(void)
{
int cpu_arch;
- if ((processor_id & 0x0000f000) == 0) {
+ if ((processor_id & 0x0008f000) == 0) {
cpu_arch = CPU_ARCH_UNKNOWN;
- } else if ((processor_id & 0x0000f000) == 0x00007000) {
+ } else if ((processor_id & 0x0008f000) == 0x00007000) {
cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
- } else {
+ } else if ((processor_id & 0x00080000) == 0x00000000) {
cpu_arch = (processor_id >> 16) & 7;
if (cpu_arch)
cpu_arch += CPU_ARCH_ARMv3;
+ } else {
+ /* the revised CPUID */
+ cpu_arch = ((processor_id >> 12) & 0xf) - 0xb + CPU_ARCH_ARMv6;
}
return cpu_arch;
@@ -865,11 +866,11 @@ static int c_show(struct seq_file *m, void *v)
seq_printf(m, "\nCPU implementer\t: 0x%02x\n", processor_id >> 24);
seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]);
- if ((processor_id & 0x0000f000) == 0x00000000) {
+ if ((processor_id & 0x0008f000) == 0x00000000) {
/* pre-ARM7 */
seq_printf(m, "CPU part\t\t: %07x\n", processor_id >> 4);
} else {
- if ((processor_id & 0x0000f000) == 0x00007000) {
+ if ((processor_id & 0x0008f000) == 0x00007000) {
/* ARM7 */
seq_printf(m, "CPU variant\t: 0x%02x\n",
(processor_id >> 16) & 127);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 765922bcf9e7..a0cd0a90a10d 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -30,15 +30,21 @@
#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn))
/*
+ * With EABI, the syscall number has to be loaded into r7.
+ */
+#define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE))
+#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
+
+/*
* For Thumb syscalls, we pass the syscall number via r7. We therefore
* need two 16-bit instructions.
*/
#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
-const unsigned long sigreturn_codes[4] = {
- SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
- SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
+const unsigned long sigreturn_codes[7] = {
+ MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
+ MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
};
static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
@@ -189,7 +195,7 @@ struct aux_sigframe {
struct sigframe {
struct sigcontext sc;
unsigned long extramask[_NSIG_WORDS-1];
- unsigned long retcode;
+ unsigned long retcode[2];
struct aux_sigframe aux __attribute__((aligned(8)));
};
@@ -198,7 +204,7 @@ struct rt_sigframe {
void __user *puc;
struct siginfo info;
struct ucontext uc;
- unsigned long retcode;
+ unsigned long retcode[2];
struct aux_sigframe aux __attribute__((aligned(8)));
};
@@ -436,12 +442,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
if (ka->sa.sa_flags & SA_RESTORER) {
retcode = (unsigned long)ka->sa.sa_restorer;
} else {
- unsigned int idx = thumb;
+ unsigned int idx = thumb << 1;
if (ka->sa.sa_flags & SA_SIGINFO)
- idx += 2;
+ idx += 3;
- if (__put_user(sigreturn_codes[idx], rc))
+ if (__put_user(sigreturn_codes[idx], rc) ||
+ __put_user(sigreturn_codes[idx+1], rc+1))
return 1;
if (cpsr & MODE32_BIT) {
@@ -456,7 +463,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
* the return code written onto the stack.
*/
flush_icache_range((unsigned long)rc,
- (unsigned long)(rc + 1));
+ (unsigned long)(rc + 2));
retcode = ((unsigned long)rc) + thumb;
}
@@ -488,7 +495,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
}
if (err == 0)
- err = setup_return(regs, ka, &frame->retcode, frame, usig);
+ err = setup_return(regs, ka, frame->retcode, frame, usig);
return err;
}
@@ -522,7 +529,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err == 0)
- err = setup_return(regs, ka, &frame->retcode, frame, usig);
+ err = setup_return(regs, ka, frame->retcode, frame, usig);
if (err == 0) {
/*
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 91d26faca62b..9991049c522d 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -9,4 +9,4 @@
*/
#define KERN_SIGRETURN_CODE 0xffff0500
-extern const unsigned long sigreturn_codes[4];
+extern const unsigned long sigreturn_codes[7];
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 373c0959bc2f..7338948bd7d3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -114,7 +114,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_START_SP;
+ secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
secondary_data.pgdir = virt_to_phys(pgd);
wmb();
@@ -245,7 +245,7 @@ void __cpuexit cpu_die(void)
__asm__("mov sp, %0\n"
" b secondary_start_kernel"
:
- : "r" ((void *)current->thread_info + THREAD_SIZE - 8));
+ : "r" (task_stack_page(current) + THREAD_SIZE - 8));
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index ea569ba482b1..a491de2d9024 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -147,6 +147,7 @@ asmlinkage int old_select(struct sel_arg_struct __user *arg)
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
+#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
@@ -226,6 +227,7 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
return -ENOSYS;
}
}
+#endif
/* Fork a new task - this creates a new program thread.
* This is called indirectly via a small wrapper
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
new file mode 100644
index 000000000000..eafa8e5284af
--- /dev/null
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -0,0 +1,339 @@
+/*
+ * arch/arm/kernel/sys_oabi-compat.c
+ *
+ * Compatibility wrappers for syscalls that are used from
+ * old ABI user space binaries with an EABI kernel.
+ *
+ * Author: Nicolas Pitre
+ * Created: Oct 7, 2005
+ * Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The legacy ABI and the new ARM EABI have different rules making some
+ * syscalls incompatible especially with structure arguments.
+ * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of
+ * simply word aligned. EABI also pads structures to the size of the largest
+ * member it contains instead of the invariant 32-bit.
+ *
+ * The following syscalls are affected:
+ *
+ * sys_stat64:
+ * sys_lstat64:
+ * sys_fstat64:
+ *
+ * struct stat64 has different sizes and some members are shifted
+ * Compatibility wrappers are needed for them and provided below.
+ *
+ * sys_fcntl64:
+ *
+ * struct flock64 has different sizes and some members are shifted
+ * A compatibility wrapper is needed and provided below.
+ *
+ * sys_statfs64:
+ * sys_fstatfs64:
+ *
+ * struct statfs64 has extra padding with EABI growing its size from
+ * 84 to 88. This struct is now __attribute__((packed,aligned(4)))
+ * with a small assembly wrapper to force the sz argument to 84 if it is 88
+ * to avoid copying the extra padding over user space unexpecting it.
+ *
+ * sys_newuname:
+ *
+ * struct new_utsname has no padding with EABI. No problem there.
+ *
+ * sys_epoll_ctl:
+ * sys_epoll_wait:
+ *
+ * struct epoll_event has its second member shifted also affecting the
+ * structure size. Compatibility wrappers are needed and provided below.
+ *
+ * sys_ipc:
+ * sys_semop:
+ * sys_semtimedop:
+ *
+ * struct sembuf loses its padding with EABI. Since arrays of them are
+ * used they have to be copyed to remove the padding. Compatibility wrappers
+ * provided below.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/eventpoll.h>
+#include <linux/sem.h>
+#include <asm/ipc.h>
+#include <asm/uaccess.h>
+
+struct oldabi_stat64 {
+ unsigned long long st_dev;
+ unsigned int __pad1;
+ unsigned long __st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned long st_uid;
+ unsigned long st_gid;
+
+ unsigned long long st_rdev;
+ unsigned int __pad2;
+
+ long long st_size;
+ unsigned long st_blksize;
+ unsigned long long st_blocks;
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+
+ unsigned long long st_ino;
+} __attribute__ ((packed,aligned(4)));
+
+static long cp_oldabi_stat64(struct kstat *stat,
+ struct oldabi_stat64 __user *statbuf)
+{
+ struct oldabi_stat64 tmp;
+
+ tmp.st_dev = huge_encode_dev(stat->dev);
+ tmp.__pad1 = 0;
+ tmp.__st_ino = stat->ino;
+ tmp.st_mode = stat->mode;
+ tmp.st_nlink = stat->nlink;
+ tmp.st_uid = stat->uid;
+ tmp.st_gid = stat->gid;
+ tmp.st_rdev = huge_encode_dev(stat->rdev);
+ tmp.st_size = stat->size;
+ tmp.st_blocks = stat->blocks;
+ tmp.__pad2 = 0;
+ tmp.st_blksize = stat->blksize;
+ tmp.st_atime = stat->atime.tv_sec;
+ tmp.st_atime_nsec = stat->atime.tv_nsec;
+ tmp.st_mtime = stat->mtime.tv_sec;
+ tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+ tmp.st_ctime = stat->ctime.tv_sec;
+ tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+ tmp.st_ino = stat->ino;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage long sys_oabi_stat64(char __user * filename,
+ struct oldabi_stat64 __user * statbuf)
+{
+ struct kstat stat;
+ int error = vfs_stat(filename, &stat);
+ if (!error)
+ error = cp_oldabi_stat64(&stat, statbuf);
+ return error;
+}
+
+asmlinkage long sys_oabi_lstat64(char __user * filename,
+ struct oldabi_stat64 __user * statbuf)
+{
+ struct kstat stat;
+ int error = vfs_lstat(filename, &stat);
+ if (!error)
+ error = cp_oldabi_stat64(&stat, statbuf);
+ return error;
+}
+
+asmlinkage long sys_oabi_fstat64(unsigned long fd,
+ struct oldabi_stat64 __user * statbuf)
+{
+ struct kstat stat;
+ int error = vfs_fstat(fd, &stat);
+ if (!error)
+ error = cp_oldabi_stat64(&stat, statbuf);
+ return error;
+}
+
+struct oabi_flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+} __attribute__ ((packed,aligned(4)));
+
+asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ struct oabi_flock64 user;
+ struct flock64 kernel;
+ mm_segment_t fs = USER_DS; /* initialized to kill a warning */
+ unsigned long local_arg = arg;
+ int ret;
+
+ switch (cmd) {
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
+ sizeof(user)))
+ return -EFAULT;
+ kernel.l_type = user.l_type;
+ kernel.l_whence = user.l_whence;
+ kernel.l_start = user.l_start;
+ kernel.l_len = user.l_len;
+ kernel.l_pid = user.l_pid;
+ local_arg = (unsigned long)&kernel;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ }
+
+ ret = sys_fcntl64(fd, cmd, local_arg);
+
+ switch (cmd) {
+ case F_GETLK64:
+ if (!ret) {
+ user.l_type = kernel.l_type;
+ user.l_whence = kernel.l_whence;
+ user.l_start = kernel.l_start;
+ user.l_len = kernel.l_len;
+ user.l_pid = kernel.l_pid;
+ if (copy_to_user((struct oabi_flock64 __user *)arg,
+ &user, sizeof(user)))
+ ret = -EFAULT;
+ }
+ case F_SETLK64:
+ case F_SETLKW64:
+ set_fs(fs);
+ }
+
+ return ret;
+}
+
+struct oabi_epoll_event {
+ __u32 events;
+ __u64 data;
+} __attribute__ ((packed,aligned(4)));
+
+asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
+ struct oabi_epoll_event __user *event)
+{
+ struct oabi_epoll_event user;
+ struct epoll_event kernel;
+ mm_segment_t fs;
+ long ret;
+
+ if (op == EPOLL_CTL_DEL)
+ return sys_epoll_ctl(epfd, op, fd, NULL);
+ if (copy_from_user(&user, event, sizeof(user)))
+ return -EFAULT;
+ kernel.events = user.events;
+ kernel.data = user.data;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_epoll_ctl(epfd, op, fd, &kernel);
+ set_fs(fs);
+ return ret;
+}
+
+asmlinkage long sys_oabi_epoll_wait(int epfd,
+ struct oabi_epoll_event __user *events,
+ int maxevents, int timeout)
+{
+ struct epoll_event *kbuf;
+ mm_segment_t fs;
+ long ret, err, i;
+
+ if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event)))
+ return -EINVAL;
+ kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
+ set_fs(fs);
+ err = 0;
+ for (i = 0; i < ret; i++) {
+ __put_user_error(kbuf[i].events, &events->events, err);
+ __put_user_error(kbuf[i].data, &events->data, err);
+ events++;
+ }
+ kfree(kbuf);
+ return err ? -EFAULT : ret;
+}
+
+struct oabi_sembuf {
+ unsigned short sem_num;
+ short sem_op;
+ short sem_flg;
+ unsigned short __pad;
+};
+
+asmlinkage long sys_oabi_semtimedop(int semid,
+ struct oabi_sembuf __user *tsops,
+ unsigned nsops,
+ const struct timespec __user *timeout)
+{
+ struct sembuf *sops;
+ struct timespec local_timeout;
+ long err;
+ int i;
+
+ if (nsops < 1)
+ return -EINVAL;
+ sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
+ if (!sops)
+ return -ENOMEM;
+ err = 0;
+ for (i = 0; i < nsops; i++) {
+ __get_user_error(sops[i].sem_num, &tsops->sem_num, err);
+ __get_user_error(sops[i].sem_op, &tsops->sem_op, err);
+ __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err);
+ tsops++;
+ }
+ if (timeout) {
+ /* copy this as well before changing domain protection */
+ err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout));
+ timeout = &local_timeout;
+ }
+ if (err) {
+ err = -EFAULT;
+ } else {
+ mm_segment_t fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_semtimedop(semid, sops, nsops, timeout);
+ set_fs(fs);
+ }
+ kfree(sops);
+ return err;
+}
+
+asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops,
+ unsigned nsops)
+{
+ return sys_oabi_semtimedop(semid, tsops, nsops, NULL);
+}
+
+extern asmlinkage int sys_ipc(uint call, int first, int second, int third,
+ void __user *ptr, long fifth);
+
+asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
+ void __user *ptr, long fifth)
+{
+ switch (call & 0xffff) {
+ case SEMOP:
+ return sys_oabi_semtimedop(first,
+ (struct oabi_sembuf __user *)ptr,
+ second, NULL);
+ case SEMTIMEDOP:
+ return sys_oabi_semtimedop(first,
+ (struct oabi_sembuf __user *)ptr,
+ second,
+ (const struct timespec __user *)fifth);
+ default:
+ return sys_ipc(call, first, second, third, ptr, fifth);
+ }
+}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index fc4729106a32..d7d932c02866 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -29,9 +29,6 @@
#include <linux/sysdev.h>
#include <linux/timer.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/leds.h>
#include <asm/thread_info.h>
#include <asm/mach/time.h>
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 45e9ea6cd2a5..10235b01582e 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -23,7 +23,6 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
-#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -165,7 +164,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
} else if (verify_stack(fp)) {
printk("invalid frame pointer 0x%08x", fp);
ok = 0;
- } else if (fp < (unsigned long)(tsk->thread_info + 1))
+ } else if (fp < (unsigned long)end_of_stack(tsk))
printk("frame pointer underflow");
printk("\n");
@@ -211,7 +210,7 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
if (!user_mode(regs) || in_interrupt()) {
dump_mem("Stack: ", regs->ARM_sp,
- THREAD_SIZE + (unsigned long)tsk->thread_info);
+ THREAD_SIZE + (unsigned long)task_stack_page(tsk));
dump_backtrace(regs, tsk);
dump_instr(regs);
}
@@ -405,7 +404,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
struct thread_info *thread = current_thread_info();
siginfo_t info;
- if ((no >> 16) != 0x9f)
+ if ((no >> 16) != (__ARM_NR_BASE>> 16))
return bad_syscall(no, regs);
switch (no & 0xffff) {
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 9a47770114d4..2b254e88595c 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -17,15 +17,13 @@ jiffies = jiffies_64;
jiffies = jiffies_64 + 4;
#endif
+SECTIONS
+{
#ifdef CONFIG_XIP_KERNEL
-#define TEXTADDR XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+ . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
#else
-#define TEXTADDR KERNEL_RAM_ADDR
+ . = PAGE_OFFSET + TEXT_OFFSET;
#endif
-
-SECTIONS
-{
- . = TEXTADDR;
.init : { /* Init code and data */
_stext = .;
_sinittext = .;
@@ -104,7 +102,7 @@ SECTIONS
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
- . = KERNEL_RAM_ADDR;
+ . = PAGE_OFFSET + TEXT_OFFSET;
#else
. = ALIGN(THREAD_SIZE);
__data_loc = .;
diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S
index 561e20717b30..55e57a1c2e6d 100644
--- a/arch/arm/lib/ashldi3.S
+++ b/arch/arm/lib/ashldi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
#endif
ENTRY(__ashldi3)
+ENTRY(__aeabi_llsl)
subs r3, r2, #32
rsb ip, r2, #32
diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S
index 86fb2a90c301..0b31398f89b2 100644
--- a/arch/arm/lib/ashrdi3.S
+++ b/arch/arm/lib/ashrdi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
#endif
ENTRY(__ashrdi3)
+ENTRY(__aeabi_lasr)
subs r3, r2, #32
rsb ip, r2, #32
diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S
index 990ee63b2465..21effe0dbf97 100644
--- a/arch/arm/lib/csumpartialcopy.S
+++ b/arch/arm/lib/csumpartialcopy.S
@@ -18,11 +18,13 @@
*/
.macro save_regs
+ mov ip, sp
stmfd sp!, {r1, r4 - r8, fp, ip, lr, pc}
+ sub fp, ip, #4
.endm
- .macro load_regs,flags
- LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc})
+ .macro load_regs
+ ldmfd sp, {r1, r4 - r8, fp, sp, pc}
.endm
.macro load1b, reg1
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
index 4a4609c19095..c50e8f5285d1 100644
--- a/arch/arm/lib/csumpartialcopygeneric.S
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -23,7 +23,7 @@ len .req r2
sum .req r3
.Lzero: mov r0, sum
- load_regs ea
+ load_regs
/*
* Align an unaligned destination pointer. We know that
@@ -87,9 +87,7 @@ sum .req r3
b .Ldone
FN_ENTRY
- mov ip, sp
save_regs
- sub fp, ip, #4
cmp len, #8 @ Ensure that we have at least
blo .Lless8 @ 8 bytes to copy.
@@ -163,7 +161,7 @@ FN_ENTRY
ldr sum, [sp, #0] @ dst
tst sum, #1
movne r0, r0, ror #8
- load_regs ea
+ load_regs
.Lsrc_not_aligned:
adc sum, sum, #0 @ include C from dst alignment
diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S
index 333bca292de9..c3b93e22ea25 100644
--- a/arch/arm/lib/csumpartialcopyuser.S
+++ b/arch/arm/lib/csumpartialcopyuser.S
@@ -18,11 +18,13 @@
.text
.macro save_regs
+ mov ip, sp
stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
+ sub fp, ip, #4
.endm
- .macro load_regs,flags
- ldm\flags fp, {r1, r2, r4-r8, fp, sp, pc}
+ .macro load_regs
+ ldmfd sp, {r1, r2, r4-r8, fp, sp, pc}
.endm
.macro load1b, reg1
@@ -100,5 +102,5 @@
6002: teq r2, r1
strneb r0, [r1], #1
bne 6002b
- load_regs ea
+ load_regs
.previous
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 59026029d017..4e492f4b3f0e 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -206,6 +206,7 @@ Boston, MA 02111-1307, USA. */
ENTRY(__udivsi3)
+ENTRY(__aeabi_uidiv)
subs r2, r1, #1
moveq pc, lr
@@ -246,6 +247,7 @@ ENTRY(__umodsi3)
ENTRY(__divsi3)
+ENTRY(__aeabi_idiv)
cmp r1, #0
eor ip, r0, r1 @ save the sign of the result.
@@ -303,12 +305,33 @@ ENTRY(__modsi3)
rsbmi r0, r0, #0
mov pc, lr
+#ifdef CONFIG_AEABI
+
+ENTRY(__aeabi_uidivmod)
+
+ stmfd sp!, {r0, r1, ip, lr}
+ bl __aeabi_uidiv
+ ldmfd sp!, {r1, r2, ip, lr}
+ mul r3, r0, r2
+ sub r1, r1, r3
+ mov pc, lr
+
+ENTRY(__aeabi_idivmod)
+
+ stmfd sp!, {r0, r1, ip, lr}
+ bl __aeabi_idiv
+ ldmfd sp!, {r1, r2, ip, lr}
+ mul r3, r0, r2
+ sub r1, r1, r3
+ mov pc, lr
+
+#endif
Ldiv0:
- str lr, [sp, #-4]!
+ str lr, [sp, #-8]!
bl __div0
mov r0, #0 @ About as wrong as it could be.
- ldr pc, [sp], #4
+ ldr pc, [sp], #8
diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S
index 46c2ed19ec95..a86dbdd59cc4 100644
--- a/arch/arm/lib/lshrdi3.S
+++ b/arch/arm/lib/lshrdi3.S
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
#endif
ENTRY(__lshrdi3)
+ENTRY(__aeabi_llsr)
subs r3, r2, #32
rsb ip, r2, #32
diff --git a/arch/arm/lib/muldi3.S b/arch/arm/lib/muldi3.S
index c7fbdf005319..72d594184b8a 100644
--- a/arch/arm/lib/muldi3.S
+++ b/arch/arm/lib/muldi3.S
@@ -25,6 +25,7 @@
#endif
ENTRY(__muldi3)
+ENTRY(__aeabi_lmul)
mul xh, yl, xh
mla xh, xl, yh, xh
diff --git a/arch/arm/lib/ucmpdi2.S b/arch/arm/lib/ucmpdi2.S
index 112630f93e5d..d847a62834cb 100644
--- a/arch/arm/lib/ucmpdi2.S
+++ b/arch/arm/lib/ucmpdi2.S
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
#include <linux/linkage.h>
#ifdef __ARMEB__
@@ -33,3 +34,16 @@ ENTRY(__ucmpdi2)
movhi r0, #2
mov pc, lr
+#ifdef CONFIG_AEABI
+
+ENTRY(__aeabi_ulcmp)
+
+ cmp xh, yh
+ cmpeq xl, yl
+ movlo r0, #-1
+ moveq r0, #0
+ movhi r0, #1
+ mov pc, lr
+
+#endif
+
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index f5ef69702296..dc5fa8e5ebef 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -90,7 +90,6 @@ static void __init aaed2000_map_io(void)
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
/* Maintainer: Nicolas Bellido Y Ortega */
- .phys_ram = 0xf0000000,
.phys_io = PIO_BASE,
.io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc,
.map_io = aaed2000_map_io,
diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
index 0340ddc4824e..74aa7a39bb68 100644
--- a/arch/arm/mach-aaec2000/clock.c
+++ b/arch/arm/mach-aaec2000/clock.c
@@ -15,27 +15,28 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
-#include <asm/hardware/clock.h>
#include "clock.h"
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -58,17 +59,6 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL(clk_disable);
-int clk_use(struct clk *clk)
-{
- return 0;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_unuse);
-
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
@@ -89,18 +79,18 @@ EXPORT_SYMBOL(clk_set_rate);
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index 4e706d9ad368..dce4815cf53c 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -20,11 +20,11 @@
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
+#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
index daefc0ea14a1..b6029a95f19c 100644
--- a/arch/arm/mach-aaec2000/core.h
+++ b/arch/arm/mach-aaec2000/core.h
@@ -9,7 +9,7 @@
*
*/
-#include <asm/hardware/amba_clcd.h>
+#include <linux/amba/clcd.h>
struct sys_timer;
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig
new file mode 100644
index 000000000000..4b7218fc3eb1
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/Kconfig
@@ -0,0 +1,54 @@
+if ARCH_AT91RM9200
+
+menu "AT91RM9200 Implementations"
+
+comment "AT91RM9200 Board Type"
+
+config ARCH_AT91RM9200DK
+ bool "Atmel AT91RM9200-DK Development board"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Atmel's AT91RM9200-DK Development board
+
+config MACH_AT91RM9200EK
+ bool "Atmel AT91RM9200-EK Evaluation Kit"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Atmel's AT91RM9200-EK Evaluation Kit
+
+config MACH_CSB337
+ bool "Cogent CSB337 board"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Cogent's CSB337 board
+
+config MACH_CSB637
+ bool "Cogent CSB637 board"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Cogent's CSB637 board
+
+config MACH_CARMEVA
+ bool "Conitec's ARM&EVA"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using Conitec's AT91RM9200-MCU-Module
+
+config MACH_KB9200
+ bool "KwikByte's KB920x"
+ depends on ARCH_AT91RM9200
+ help
+ Select this if you are using KwikByte's KB920x board
+
+
+comment "AT91RM9200 Feature Selections"
+
+config AT91_PROGRAMMABLE_CLOCKS
+ bool "Programmable Clocks"
+ help
+ Select this if you need to program one or more of the PCK0..PCK3
+ programmable clock outputs.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
new file mode 100644
index 000000000000..75e6ee318ded
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := clock.o irq.o time.o gpio.o common.o devices.o
+obj-m :=
+obj-n :=
+obj- :=
+
+# Board-specific support
+obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o
+obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o
+obj-$(CONFIG_MACH_CSB337) += board-csb337.o
+obj-$(CONFIG_MACH_CSB637) += board-csb637.o
+#obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o
+#obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
+
+# LEDs support
+#led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
+#led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
+#led-$(CONFIG_MACH_CSB337) += leds.o
+#led-$(CONFIG_MACH_CSB637) += leds.o
+#led-$(CONFIG_MACH_KB9200) += leds.o
+obj-$(CONFIG_LEDS) += $(led-y)
+
+# VGA support
+#obj-$(CONFIG_FB_S1D13XXX) += ics1523.o
diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91rm9200/Makefile.boot
new file mode 100644
index 000000000000..e667dcc7cd34
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/Makefile.boot
@@ -0,0 +1,9 @@
+# Note: the following conditions must always be true:
+# ZRELADDR == virt_to_phys(TEXTADDR)
+# PARAMS_PHYS must be within 4MB of ZRELADDR
+# INITRD_PHYS must be in RAM
+
+ zreladdr-y := 0x20008000
+params_phys-y := 0x20000100
+initrd_phys-y := 0x20410000
+
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
new file mode 100644
index 000000000000..54022e58d50d
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -0,0 +1,142 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-csb337.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+
+#include "generic.h"
+
+static void __init csb337_init_irq(void)
+{
+ /* Initialize AIC controller */
+ at91rm9200_init_irq(NULL);
+
+ /* Set up the GPIO interrupts */
+ at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+#define CSB337_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+#define CSB337_SERIAL_CONSOLE 0 /* ttyS0 */
+
+static void __init csb337_map_io(void)
+{
+ int serial[AT91_NR_UART] = CSB337_UART_MAP;
+ int i;
+
+ at91rm9200_map_io();
+
+ /* Initialize clocks: 3.6864 MHz crystal */
+ at91_clock_init(3686400);
+
+#ifdef CONFIG_SERIAL_AT91
+ at91_console_port = CSB337_SERIAL_CONSOLE;
+ memcpy(at91_serial_map, serial, sizeof(serial));
+
+ /* Register UARTs */
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (serial[i] >= 0)
+ at91_register_uart(i, serial[i]);
+ }
+#endif
+}
+
+static struct at91_eth_data __initdata csb337_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC2,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata csb337_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata csb337_udc_data = {
+ // this has no VBUS sensing pin
+ .pullup_pin = AT91_PIN_PA24,
+};
+
+static struct at91_cf_data __initdata csb337_cf_data = {
+ /*
+ * connector P4 on the CSB 337 mates to
+ * connector P8 on the CSB 300CF
+ */
+
+ /* CSB337 specific */
+ .det_pin = AT91_PIN_PC3,
+
+ /* CSB300CF specific */
+ .irq_pin = AT91_PIN_PA19,
+ .vcc_pin = AT91_PIN_PD0,
+ .rst_pin = AT91_PIN_PD2,
+};
+
+static struct at91_mmc_data __initdata csb337_mmc_data = {
+ .det_pin = AT91_PIN_PD5,
+ .is_b = 0,
+ .wire4 = 1,
+ .wp_pin = AT91_PIN_PD6,
+};
+
+static void __init csb337_board_init(void)
+{
+ /* Ethernet */
+ at91_add_device_eth(&csb337_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&csb337_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&csb337_udc_data);
+ /* Compact Flash */
+ at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */
+ at91_add_device_cf(&csb337_cf_data);
+ /* MMC */
+ at91_add_device_mmc(&csb337_mmc_data);
+}
+
+MACHINE_START(CSB337, "Cogent CSB337")
+ /* Maintainer: Bill Gatliff */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = csb337_map_io,
+ .init_irq = csb337_init_irq,
+ .init_machine = csb337_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
new file mode 100644
index 000000000000..8195f9d919ea
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -0,0 +1,115 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-csb637.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+
+#include "generic.h"
+
+static void __init csb637_init_irq(void)
+{
+ /* Initialize AIC controller */
+ at91rm9200_init_irq(NULL);
+
+ /* Set up the GPIO interrupts */
+ at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+#define CSB637_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+#define CSB637_SERIAL_CONSOLE 0 /* ttyS0 */
+
+static void __init csb637_map_io(void)
+{
+ int serial[AT91_NR_UART] = CSB637_UART_MAP;
+ int i;
+
+ at91rm9200_map_io();
+
+ /* Initialize clocks: 3.6864 MHz crystal */
+ at91_clock_init(3686400);
+
+#ifdef CONFIG_SERIAL_AT91
+ at91_console_port = CSB637_SERIAL_CONSOLE;
+ memcpy(at91_serial_map, serial, sizeof(serial));
+
+ /* Register UARTs */
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (serial[i] >= 0)
+ at91_register_uart(i, serial[i]);
+ }
+#endif
+}
+
+static struct at91_eth_data __initdata csb637_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC0,
+ .is_rmii = 0,
+};
+
+static struct at91_usbh_data __initdata csb637_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata csb637_udc_data = {
+ .vbus_pin = AT91_PIN_PB28,
+ .pullup_pin = AT91_PIN_PB1,
+};
+
+static void __init csb637_board_init(void)
+{
+ /* Ethernet */
+ at91_add_device_eth(&csb637_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&csb637_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&csb637_udc_data);
+}
+
+MACHINE_START(CSB637, "Cogent CSB637")
+ /* Maintainer: Bill Gatliff */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = csb637_map_io,
+ .init_irq = csb637_init_irq,
+ .init_machine = csb637_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
new file mode 100644
index 000000000000..8a783368366e
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -0,0 +1,137 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-dk.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * Epson S1D framebuffer glue code is:
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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 <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+
+#include "generic.h"
+
+static void __init dk_init_irq(void)
+{
+ /* Initialize AIC controller */
+ at91rm9200_init_irq(NULL);
+
+ /* Set up the GPIO interrupts */
+ at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+#define DK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+#define DK_SERIAL_CONSOLE 0 /* ttyS0 */
+
+static void __init dk_map_io(void)
+{
+ int serial[AT91_NR_UART] = DK_UART_MAP;
+ int i;
+
+ at91rm9200_map_io();
+
+ /* Initialize clocks: 18.432 MHz crystal */
+ at91_clock_init(18432000);
+
+#ifdef CONFIG_SERIAL_AT91
+ at91_console_port = DK_SERIAL_CONSOLE;
+ memcpy(at91_serial_map, serial, sizeof(serial));
+
+ /* Register UARTs */
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (at91_serial_map[i] >= 0)
+ at91_register_uart(i, at91_serial_map[i]);
+ }
+#endif
+}
+
+static struct at91_eth_data __initdata dk_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata dk_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata dk_udc_data = {
+ .vbus_pin = AT91_PIN_PD4,
+ .pullup_pin = AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata dk_cf_data = {
+ .det_pin = AT91_PIN_PB0,
+ .rst_pin = AT91_PIN_PC5,
+ // .irq_pin = ... not connected
+ // .vcc_pin = ... always powered
+};
+
+static struct at91_mmc_data __initdata dk_mmc_data = {
+ .is_b = 0,
+ .wire4 = 1,
+};
+
+static void __init dk_board_init(void)
+{
+ /* Ethernet */
+ at91_add_device_eth(&dk_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&dk_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&dk_udc_data);
+ /* Compact Flash */
+ at91_add_device_cf(&dk_cf_data);
+ /* MMC */
+ at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_add_device_mmc(&dk_mmc_data);
+ /* VGA */
+// dk_add_device_video();
+}
+
+MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
+ /* Maintainer: SAN People/Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = dk_map_io,
+ .init_irq = dk_init_irq,
+ .init_machine = dk_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
new file mode 100644
index 000000000000..fd0752eba897
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-ek.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * Epson S1D framebuffer glue code is:
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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 <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+
+#include "generic.h"
+
+static void __init ek_init_irq(void)
+{
+ /* Initialize AIC controller */
+ at91rm9200_init_irq(NULL);
+
+ /* Set up the GPIO interrupts */
+ at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ * 0 .. 3 = USART0 .. USART3
+ * 4 = DBGU
+ */
+#define EK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
+#define EK_SERIAL_CONSOLE 0 /* ttyS0 */
+
+static void __init ek_map_io(void)
+{
+ int serial[AT91_NR_UART] = EK_UART_MAP;
+ int i;
+
+ at91rm9200_map_io();
+
+ /* Initialize clocks: 18.432 MHz crystal */
+ at91_clock_init(18432000);
+
+#ifdef CONFIG_SERIAL_AT91
+ at91_console_port = EK_SERIAL_CONSOLE;
+ memcpy(at91_serial_map, serial, sizeof(serial));
+
+ /* Register UARTs */
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (serial[i] >= 0)
+ at91_register_uart(i, serial[i]);
+ }
+#endif
+}
+
+static struct at91_eth_data __initdata ek_eth_data = {
+ .phy_irq_pin = AT91_PIN_PC4,
+ .is_rmii = 1,
+};
+
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PD4,
+ .pullup_pin = AT91_PIN_PD5,
+};
+
+static struct at91_mmc_data __initdata ek_mmc_data = {
+ .det_pin = AT91_PIN_PB27,
+ .is_b = 0,
+ .wire4 = 1,
+ .wp_pin = AT91_PIN_PA17,
+};
+
+static void __init ek_board_init(void)
+{
+ /* Ethernet */
+ at91_add_device_eth(&ek_eth_data);
+ /* USB Host */
+ at91_add_device_usbh(&ek_usbh_data);
+ /* USB Device */
+ at91_add_device_udc(&ek_udc_data);
+ /* MMC */
+ at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). default: MMC */
+ at91_add_device_mmc(&ek_mmc_data);
+ /* VGA */
+// ek_add_device_video();
+}
+
+MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
+ /* Maintainer: SAN People/Atmel */
+ .phys_io = AT91_BASE_SYS,
+ .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+ .boot_params = AT91_SDRAM_BASE + 0x100,
+ .timer = &at91rm9200_timer,
+ .map_io = ek_map_io,
+ .init_irq = ek_init_irq,
+ .init_machine = ek_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
new file mode 100644
index 000000000000..ec8195a2a3cc
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -0,0 +1,620 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/clock.c
+ *
+ * Copyright (C) 2005 David Brownell
+ * Copyright (C) 2005 Ivan Kokshaysky
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/board.h> /* for master clock global */
+
+#include "generic.h"
+
+#undef DEBUG
+
+/*
+ * There's a lot more which can be done with clocks, including cpufreq
+ * integration, slow clock mode support (for system suspend), letting
+ * PLLB be used at other rates (on boards that don't need USB), etc.
+ */
+
+struct clk {
+ const char *name;
+ unsigned long rate_hz;
+ struct clk *parent;
+ u32 pmc_mask;
+ void (*mode)(struct clk *, int);
+ unsigned id:2; /* PCK0..3, or 32k/main/a/b */
+ unsigned primary:1;
+ unsigned pll:1;
+ unsigned programmable:1;
+ u16 users;
+};
+
+static spinlock_t clk_lock;
+static u32 at91_pllb_usb_init;
+
+/*
+ * Four primary clock sources: two crystal oscillators (32K, main), and
+ * two PLLs. PLLA usually runs the master clock; and PLLB must run at
+ * 48 MHz (unless no USB function clocks are needed). The main clock and
+ * both PLLs are turned off to run in "slow clock mode" (system suspend).
+ */
+static struct clk clk32k = {
+ .name = "clk32k",
+ .rate_hz = AT91_SLOW_CLOCK,
+ .users = 1, /* always on */
+ .id = 0,
+ .primary = 1,
+};
+static struct clk main_clk = {
+ .name = "main",
+ .pmc_mask = 1 << 0, /* in PMC_SR */
+ .users = 1,
+ .id = 1,
+ .primary = 1,
+};
+static struct clk plla = {
+ .name = "plla",
+ .parent = &main_clk,
+ .pmc_mask = 1 << 1, /* in PMC_SR */
+ .id = 2,
+ .primary = 1,
+ .pll = 1,
+};
+
+static void pllb_mode(struct clk *clk, int is_on)
+{
+ u32 value;
+
+ if (is_on) {
+ is_on = AT91_PMC_LOCKB;
+ value = at91_pllb_usb_init;
+ } else
+ value = 0;
+
+ at91_sys_write(AT91_CKGR_PLLBR, value);
+
+ do {
+ cpu_relax();
+ } while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
+}
+
+static struct clk pllb = {
+ .name = "pllb",
+ .parent = &main_clk,
+ .pmc_mask = 1 << 2, /* in PMC_SR */
+ .mode = pllb_mode,
+ .id = 3,
+ .primary = 1,
+ .pll = 1,
+};
+
+static void pmc_sys_mode(struct clk *clk, int is_on)
+{
+ if (is_on)
+ at91_sys_write(AT91_PMC_SCER, clk->pmc_mask);
+ else
+ at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+}
+
+/* USB function clocks (PLLB must be 48 MHz) */
+static struct clk udpck = {
+ .name = "udpck",
+ .parent = &pllb,
+ .pmc_mask = AT91_PMC_UDP,
+ .mode = pmc_sys_mode,
+};
+static struct clk uhpck = {
+ .name = "uhpck",
+ .parent = &pllb,
+ .pmc_mask = AT91_PMC_UHP,
+ .mode = pmc_sys_mode,
+};
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+/*
+ * The four programmable clocks can be parented by any primary clock.
+ * You must configure pin multiplexing to bring these signals out.
+ */
+static struct clk pck0 = {
+ .name = "pck0",
+ .pmc_mask = AT91_PMC_PCK0,
+ .mode = pmc_sys_mode,
+ .programmable = 1,
+ .id = 0,
+};
+static struct clk pck1 = {
+ .name = "pck1",
+ .pmc_mask = AT91_PMC_PCK1,
+ .mode = pmc_sys_mode,
+ .programmable = 1,
+ .id = 1,
+};
+static struct clk pck2 = {
+ .name = "pck2",
+ .pmc_mask = AT91_PMC_PCK2,
+ .mode = pmc_sys_mode,
+ .programmable = 1,
+ .id = 2,
+};
+static struct clk pck3 = {
+ .name = "pck3",
+ .pmc_mask = AT91_PMC_PCK3,
+ .mode = pmc_sys_mode,
+ .programmable = 1,
+ .id = 3,
+};
+#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+
+/*
+ * The master clock is divided from the CPU clock (by 1-4). It's used for
+ * memory, interfaces to on-chip peripherals, the AIC, and sometimes more
+ * (e.g baud rate generation). It's sourced from one of the primary clocks.
+ */
+static struct clk mck = {
+ .name = "mck",
+ .pmc_mask = 1 << 3, /* in PMC_SR */
+ .users = 1, /* (must be) always on */
+};
+
+static void pmc_periph_mode(struct clk *clk, int is_on)
+{
+ if (is_on)
+ at91_sys_write(AT91_PMC_PCER, clk->pmc_mask);
+ else
+ at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
+}
+
+static struct clk udc_clk = {
+ .name = "udc_clk",
+ .parent = &mck,
+ .pmc_mask = 1 << AT91_ID_UDP,
+ .mode = pmc_periph_mode,
+};
+static struct clk ohci_clk = {
+ .name = "ohci_clk",
+ .parent = &mck,
+ .pmc_mask = 1 << AT91_ID_UHP,
+ .mode = pmc_periph_mode,
+};
+
+static struct clk *const clock_list[] = {
+ /* four primary clocks -- MUST BE FIRST! */
+ &clk32k,
+ &main_clk,
+ &plla,
+ &pllb,
+
+ /* PLLB children (USB) */
+ &udpck,
+ &uhpck,
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+ /* programmable clocks */
+ &pck0,
+ &pck1,
+ &pck2,
+ &pck3,
+#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+ /* MCK and peripherals */
+ &mck,
+ // usart0..usart3
+ // mmc
+ &udc_clk,
+ // i2c
+ // spi
+ // ssc0..ssc2
+ // tc0..tc5
+ &ohci_clk,
+ // ether
+};
+
+
+/* clocks are all static for now; no refcounting necessary */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
+ if (strcmp(id, clock_list[i]->name) == 0)
+ return clock_list[i];
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+static void __clk_enable(struct clk *clk)
+{
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->users++ == 0 && clk->mode)
+ clk->mode(clk, 1);
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+ BUG_ON(clk->users == 0);
+ if (--clk->users == 0 && clk->mode)
+ clk->mode(clk, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long rate;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ for (;;) {
+ rate = clk->rate_hz;
+ if (rate || !clk->parent)
+ break;
+ clk = clk->parent;
+ }
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+
+/*
+ * For now, only the programmable clocks support reparenting (MCK could
+ * do this too, with care) or rate changing (the PLLs could do this too,
+ * ditto MCK but that's more for cpufreq). Drivers may reparent to get
+ * a better rate match; we don't.
+ */
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ unsigned prescale;
+ unsigned long actual;
+
+ if (!clk->programmable)
+ return -EINVAL;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ actual = clk->parent->rate_hz;
+ for (prescale = 0; prescale < 7; prescale++) {
+ if (actual && actual <= rate)
+ break;
+ actual >>= 1;
+ }
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long flags;
+ unsigned prescale;
+ unsigned long actual;
+
+ if (!clk->programmable)
+ return -EINVAL;
+ if (clk->users)
+ return -EBUSY;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ actual = clk->parent->rate_hz;
+ for (prescale = 0; prescale < 7; prescale++) {
+ if (actual && actual <= rate) {
+ u32 pckr;
+
+ pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+ pckr &= 0x03;
+ pckr |= prescale << 2;
+ at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
+ clk->rate_hz = actual;
+ break;
+ }
+ actual >>= 1;
+ }
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return (prescale < 7) ? actual : -ENOENT;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+ return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ unsigned long flags;
+
+ if (clk->users)
+ return -EBUSY;
+ if (!parent->primary || !clk->programmable)
+ return -EINVAL;
+ spin_lock_irqsave(&clk_lock, flags);
+
+ clk->rate_hz = parent->rate_hz;
+ clk->parent = parent;
+ at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id);
+
+ spin_unlock_irqrestore(&clk_lock, flags);
+ return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+/*------------------------------------------------------------------------*/
+
+#ifdef CONFIG_DEBUG_FS
+
+static int at91_clk_show(struct seq_file *s, void *unused)
+{
+ u32 scsr, pcsr, sr;
+ unsigned i;
+
+ seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
+ seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
+
+ seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
+ seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
+ seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
+ seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
+
+ seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+ for (i = 0; i < 4; i++)
+ seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
+ seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
+
+ seq_printf(s, "\n");
+
+ for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
+ char *state;
+ struct clk *clk = clock_list[i];
+
+ if (clk->mode == pmc_sys_mode)
+ state = (scsr & clk->pmc_mask) ? "on" : "off";
+ else if (clk->mode == pmc_periph_mode)
+ state = (pcsr & clk->pmc_mask) ? "on" : "off";
+ else if (clk->pmc_mask)
+ state = (sr & clk->pmc_mask) ? "on" : "off";
+ else if (clk == &clk32k || clk == &main_clk)
+ state = "on";
+ else
+ state = "";
+
+ seq_printf(s, "%-10s users=%d %-3s %9ld Hz %s\n",
+ clk->name, clk->users, state, clk_get_rate(clk),
+ clk->parent ? clk->parent->name : "");
+ }
+ return 0;
+}
+
+static int at91_clk_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, at91_clk_show, NULL);
+}
+
+static struct file_operations at91_clk_operations = {
+ .open = at91_clk_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init at91_clk_debugfs_init(void)
+{
+ /* /sys/kernel/debug/at91_clk */
+ (void) debugfs_create_file("at91_clk", S_IFREG | S_IRUGO, NULL, NULL, &at91_clk_operations);
+
+ return 0;
+}
+postcore_initcall(at91_clk_debugfs_init);
+
+#endif
+
+/*------------------------------------------------------------------------*/
+
+static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg)
+{
+ unsigned mul, div;
+
+ div = reg & 0xff;
+ mul = (reg >> 16) & 0x7ff;
+ if (div && mul) {
+ freq /= div;
+ freq *= mul + 1;
+ } else
+ freq = 0;
+ if (pll == &pllb && (reg & (1 << 28)))
+ freq /= 2;
+ return freq;
+}
+
+static unsigned __init at91_pll_calc(unsigned main_freq, unsigned out_freq)
+{
+ unsigned i, div = 0, mul = 0, diff = 1 << 30;
+ unsigned ret = (out_freq > 155000000) ? 0xbe00 : 0x3e00;
+
+ /* PLL output max 240 MHz (or 180 MHz per errata) */
+ if (out_freq > 240000000)
+ goto fail;
+
+ for (i = 1; i < 256; i++) {
+ int diff1;
+ unsigned input, mul1;
+
+ /*
+ * PLL input between 1MHz and 32MHz per spec, but lower
+ * frequences seem necessary in some cases so allow 100K.
+ */
+ input = main_freq / i;
+ if (input < 100000)
+ continue;
+ if (input > 32000000)
+ continue;
+
+ mul1 = out_freq / input;
+ if (mul1 > 2048)
+ continue;
+ if (mul1 < 2)
+ goto fail;
+
+ diff1 = out_freq - input * mul1;
+ if (diff1 < 0)
+ diff1 = -diff1;
+ if (diff > diff1) {
+ diff = diff1;
+ div = i;
+ mul = mul1;
+ if (diff == 0)
+ break;
+ }
+ }
+ if (i == 256 && diff > (out_freq >> 5))
+ goto fail;
+ return ret | ((mul - 1) << 16) | div;
+fail:
+ return 0;
+}
+
+int __init at91_clock_init(unsigned long main_clock)
+{
+ unsigned tmp, freq, mckr;
+
+ spin_lock_init(&clk_lock);
+
+ /*
+ * When the bootloader initialized the main oscillator correctly,
+ * there's no problem using the cycle counter. But if it didn't,
+ * or when using oscillator bypass mode, we must be told the speed
+ * of the main clock.
+ */
+ if (!main_clock) {
+ do {
+ tmp = at91_sys_read(AT91_CKGR_MCFR);
+ } while (!(tmp & 0x10000));
+ main_clock = (tmp & 0xffff) * (AT91_SLOW_CLOCK / 16);
+ }
+ main_clk.rate_hz = main_clock;
+
+ /* report if PLLA is more than mildly overclocked */
+ plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
+ if (plla.rate_hz > 209000000)
+ pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
+
+ /*
+ * USB clock init: choose 48 MHz PLLB value, turn all clocks off,
+ * disable 48MHz clock during usb peripheral suspend.
+ *
+ * REVISIT: assumes MCK doesn't derive from PLLB!
+ */
+ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | 0x10000000;
+ pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
+ at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP));
+ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP);
+ at91_sys_write(AT91_CKGR_PLLBR, 0);
+ at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP);
+
+ /*
+ * MCK and CPU derive from one of those primary clocks.
+ * For now, assume this parentage won't change.
+ */
+ mckr = at91_sys_read(AT91_PMC_MCKR);
+ mck.parent = clock_list[mckr & AT91_PMC_CSS];
+ mck.parent->users++;
+ freq = mck.parent->rate_hz;
+ freq /= (1 << ((mckr >> 2) & 3)); /* prescale */
+ mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */
+
+ printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
+ freq / 1000000, (unsigned) mck.rate_hz / 1000000,
+ (unsigned) main_clock / 1000000,
+ ((unsigned) main_clock % 1000000) / 1000);
+
+ /* FIXME get rid of master_clock global */
+ at91_master_clock = mck.rate_hz;
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+ /* establish PCK0..PCK3 parentage */
+ for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
+ struct clk *clk = clock_list[tmp], *parent;
+ u32 pckr;
+
+ if (!clk->programmable)
+ continue;
+
+ pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+ parent = clock_list[pckr & 3];
+ clk->parent = parent;
+ clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+ }
+#else
+ /* disable unused clocks */
+ at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
+#endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+
+ /* FIXME several unused clocks may still be active... provide
+ * a CONFIG option to turn off all unused clocks at some point
+ * before driver init starts.
+ */
+
+ return 0;
+}
diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c
new file mode 100644
index 000000000000..3848fd2d5596
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/common.c
@@ -0,0 +1,115 @@
+/*
+ * arch/arm/mach-at91rm9200/common.c
+ *
+ * Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/arch/hardware.h>
+
+static struct map_desc at91rm9200_io_desc[] __initdata = {
+ {
+ .virtual = AT91_VA_BASE_SYS,
+ .pfn = __phys_to_pfn(AT91_BASE_SYS),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_SPI,
+ .pfn = __phys_to_pfn(AT91_BASE_SPI),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_SSC2,
+ .pfn = __phys_to_pfn(AT91_BASE_SSC2),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_SSC1,
+ .pfn = __phys_to_pfn(AT91_BASE_SSC1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_SSC0,
+ .pfn = __phys_to_pfn(AT91_BASE_SSC0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_US3,
+ .pfn = __phys_to_pfn(AT91_BASE_US3),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_US2,
+ .pfn = __phys_to_pfn(AT91_BASE_US2),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_US1,
+ .pfn = __phys_to_pfn(AT91_BASE_US1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_US0,
+ .pfn = __phys_to_pfn(AT91_BASE_US0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_EMAC,
+ .pfn = __phys_to_pfn(AT91_BASE_EMAC),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_TWI,
+ .pfn = __phys_to_pfn(AT91_BASE_TWI),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_MCI,
+ .pfn = __phys_to_pfn(AT91_BASE_MCI),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_UDP,
+ .pfn = __phys_to_pfn(AT91_BASE_UDP),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_TCB1,
+ .pfn = __phys_to_pfn(AT91_BASE_TCB1),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
+ .virtual = AT91_VA_BASE_TCB0,
+ .pfn = __phys_to_pfn(AT91_BASE_TCB0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init at91rm9200_map_io(void)
+{
+ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
+}
+
+
+unsigned long at91_master_clock;
+
+EXPORT_SYMBOL(at91_master_clock);
+
+
+int at91_serial_map[AT91_NR_UART];
+int at91_console_port;
+
+EXPORT_SYMBOL(at91_serial_map);
+EXPORT_SYMBOL(at91_console_port);
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
new file mode 100644
index 000000000000..8df3e5245651
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -0,0 +1,291 @@
+/*
+ * arch/arm/mach-at91rm9200/devices.c
+ *
+ * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ * 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 <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <linux/config.h>
+#include <linux/platform_device.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/pio.h>
+
+
+/* --------------------------------------------------------------------
+ * USB Host
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static u64 ohci_dmamask = 0xffffffffUL;
+static struct at91_usbh_data usbh_data;
+
+static struct resource at91rm9200_usbh_resource[] = {
+ [0] = {
+ .start = AT91_UHP_BASE,
+ .end = AT91_UHP_BASE + SZ_1M -1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = AT91_ID_UHP,
+ .end = AT91_ID_UHP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device at91rm9200_usbh_device = {
+ .name = "at91rm9200-ohci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbh_data,
+ },
+ .resource = at91rm9200_usbh_resource,
+ .num_resources = ARRAY_SIZE(at91rm9200_usbh_resource),
+};
+
+void __init at91_add_device_usbh(struct at91_usbh_data *data)
+{
+ if (!data)
+ return;
+
+ usbh_data = *data;
+ platform_device_register(&at91rm9200_usbh_device);
+}
+#else
+void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_AT91
+static struct at91_udc_data udc_data;
+
+static struct resource at91_udc_resources[] = {
+ {
+ .start = AT91_BASE_UDP,
+ .end = AT91_BASE_UDP + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91rm9200_udc_device = {
+ .name = "at91_udc",
+ .id = -1,
+ .dev = {
+ .platform_data = &udc_data,
+ },
+ .resource = at91_udc_resources,
+ .num_resources = ARRAY_SIZE(at91_udc_resources),
+};
+
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->vbus_pin) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+ if (data->pullup_pin)
+ at91_set_gpio_output(data->pullup_pin, 0);
+
+ udc_data = *data;
+ platform_device_register(&at91rm9200_udc_device);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Ethernet
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE)
+static u64 eth_dmamask = 0xffffffffUL;
+static struct at91_eth_data eth_data;
+
+static struct platform_device at91rm9200_eth_device = {
+ .name = "at91_ether",
+ .id = -1,
+ .dev = {
+ .dma_mask = &eth_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &eth_data,
+ },
+ .num_resources = 0,
+};
+
+void __init at91_add_device_eth(struct at91_eth_data *data)
+{
+ if (!data)
+ return;
+
+ if (data->phy_irq_pin) {
+ at91_set_gpio_input(data->phy_irq_pin, 0);
+ at91_set_deglitch(data->phy_irq_pin, 1);
+ }
+
+ /* Pins used for MII and RMII */
+ at91_set_A_periph(AT91_PIN_PA16, 0); /* EMDIO */
+ at91_set_A_periph(AT91_PIN_PA15, 0); /* EMDC */
+ at91_set_A_periph(AT91_PIN_PA14, 0); /* ERXER */
+ at91_set_A_periph(AT91_PIN_PA13, 0); /* ERX1 */
+ at91_set_A_periph(AT91_PIN_PA12, 0); /* ERX0 */
+ at91_set_A_periph(AT91_PIN_PA11, 0); /* ECRS_ECRSDV */
+ at91_set_A_periph(AT91_PIN_PA10, 0); /* ETX1 */
+ at91_set_A_periph(AT91_PIN_PA9, 0); /* ETX0 */
+ at91_set_A_periph(AT91_PIN_PA8, 0); /* ETXEN */
+ at91_set_A_periph(AT91_PIN_PA7, 0); /* ETXCK_EREFCK */
+
+ if (!data->is_rmii) {
+ at91_set_B_periph(AT91_PIN_PB19, 0); /* ERXCK */
+ at91_set_B_periph(AT91_PIN_PB18, 0); /* ECOL */
+ at91_set_B_periph(AT91_PIN_PB17, 0); /* ERXDV */
+ at91_set_B_periph(AT91_PIN_PB16, 0); /* ERX3 */
+ at91_set_B_periph(AT91_PIN_PB15, 0); /* ERX2 */
+ at91_set_B_periph(AT91_PIN_PB14, 0); /* ETXER */
+ at91_set_B_periph(AT91_PIN_PB13, 0); /* ETX3 */
+ at91_set_B_periph(AT91_PIN_PB12, 0); /* ETX2 */
+ }
+
+ eth_data = *data;
+ platform_device_register(&at91rm9200_eth_device);
+}
+#else
+void __init at91_add_device_eth(struct at91_eth_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * Compact Flash / PCMCIA
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
+static struct at91_cf_data cf_data;
+
+static struct platform_device at91rm9200_cf_device = {
+ .name = "at91_cf",
+ .id = -1,
+ .dev = {
+ .platform_data = &cf_data,
+ },
+ .num_resources = 0,
+};
+
+void __init at91_add_device_cf(struct at91_cf_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->irq_pin) {
+ at91_set_gpio_input(data->irq_pin, 1);
+ at91_set_deglitch(data->irq_pin, 1);
+ }
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+
+ /* outputs, initially off */
+ if (data->vcc_pin)
+ at91_set_gpio_output(data->vcc_pin, 0);
+ at91_set_gpio_output(data->rst_pin, 0);
+
+ cf_data = *data;
+ platform_device_register(&at91rm9200_cf_device);
+}
+#else
+void __init at91_add_device_cf(struct at91_cf_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ * MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE)
+static u64 mmc_dmamask = 0xffffffffUL;
+static struct at91_mmc_data mmc_data;
+
+static struct resource at91_mmc_resources[] = {
+ {
+ .start = AT91_BASE_MCI,
+ .end = AT91_BASE_MCI + SZ_16K - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device at91rm9200_mmc_device = {
+ .name = "at91rm9200_mci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &mmc_dmamask,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &mmc_data,
+ },
+ .resource = at91_mmc_resources,
+ .num_resources = ARRAY_SIZE(at91_mmc_resources),
+};
+
+void __init at91_add_device_mmc(struct at91_mmc_data *data)
+{
+ if (!data)
+ return;
+
+ /* input/irq */
+ if (data->det_pin) {
+ at91_set_gpio_input(data->det_pin, 1);
+ at91_set_deglitch(data->det_pin, 1);
+ }
+ if (data->wp_pin)
+ at91_set_gpio_input(data->wp_pin, 1);
+
+ /* CLK */
+ at91_set_A_periph(AT91_PIN_PA27, 0);
+
+ if (data->is_b) {
+ /* CMD */
+ at91_set_B_periph(AT91_PIN_PA8, 0);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_B_periph(AT91_PIN_PA9, 0);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PA10, 0);
+ at91_set_B_periph(AT91_PIN_PA11, 0);
+ at91_set_B_periph(AT91_PIN_PA12, 0);
+ }
+ } else {
+ /* CMD */
+ at91_set_A_periph(AT91_PIN_PA28, 0);
+
+ /* DAT0, maybe DAT1..DAT3 */
+ at91_set_A_periph(AT91_PIN_PA29, 0);
+ if (data->wire4) {
+ at91_set_B_periph(AT91_PIN_PB3, 0);
+ at91_set_B_periph(AT91_PIN_PB4, 0);
+ at91_set_B_periph(AT91_PIN_PB5, 0);
+ }
+ }
+
+ mmc_data = *data;
+ platform_device_register(&at91rm9200_mmc_device);
+}
+#else
+void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
+#endif
+
+/* -------------------------------------------------------------------- */
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
new file mode 100644
index 000000000000..9bd541eba0a0
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/generic.h
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/generic.h
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+void at91_gpio_irq_setup(unsigned banks);
+
+struct sys_timer;
+extern struct sys_timer at91rm9200_timer;
+
+extern void __init at91rm9200_map_io(void);
+
+extern int __init at91_clock_init(unsigned long main_clock);
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
new file mode 100644
index 000000000000..2fd2ef583e4d
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -0,0 +1,302 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/gpio.c
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+static const u32 pio_controller_offset[4] = {
+ AT91_PIOA,
+ AT91_PIOB,
+ AT91_PIOC,
+ AT91_PIOD,
+};
+
+static inline void __iomem *pin_to_controller(unsigned pin)
+{
+ void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
+
+ pin -= PIN_BASE;
+ pin /= 32;
+ if (likely(pin < BGA_GPIO_BANKS))
+ return sys_base + pio_controller_offset[pin];
+
+ return NULL;
+}
+
+static inline unsigned pin_to_mask(unsigned pin)
+{
+ pin -= PIN_BASE;
+ return 1 << (pin % 32);
+}
+
+
+/*--------------------------------------------------------------------------*/
+
+/* Not all hardware capabilities are exposed through these calls; they
+ * only encapsulate the most common features and modes. (So if you
+ * want to change signals in groups, do it directly.)
+ *
+ * Bootloaders will usually handle some of the pin multiplexing setup.
+ * The intent is certainly that by the time Linux is fully booted, all
+ * pins should have been fully initialized. These setup calls should
+ * only be used by board setup routines, or possibly in driver probe().
+ *
+ * For bootloaders doing all that setup, these calls could be inlined
+ * as NOPs so Linux won't duplicate any setup code
+ */
+
+
+/*
+ * mux the pin to the "A" internal peripheral role.
+ */
+int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_ASR);
+ __raw_writel(mask, pio + PIO_PDR);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_A_periph);
+
+
+/*
+ * mux the pin to the "B" internal peripheral role.
+ */
+int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_BSR);
+ __raw_writel(mask, pio + PIO_PDR);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_B_periph);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and
+ * configure it for an input.
+ */
+int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
+ __raw_writel(mask, pio + PIO_ODR);
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_input);
+
+
+/*
+ * mux the pin to the gpio controller (instead of "A" or "B" peripheral),
+ * and configure it for an output.
+ */
+int __init_or_module at91_set_gpio_output(unsigned pin, int value)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+
+ __raw_writel(mask, pio + PIO_IDR);
+ __raw_writel(mask, pio + PIO_PUDR);
+ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+ __raw_writel(mask, pio + PIO_OER);
+ __raw_writel(mask, pio + PIO_PER);
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_output);
+
+
+/*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+ */
+int __init_or_module at91_set_deglitch(unsigned pin, int is_on)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+ __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_deglitch);
+
+/*--------------------------------------------------------------------------*/
+
+
+/*
+ * assuming the pin is muxed as a gpio output, set its value.
+ */
+int at91_set_gpio_value(unsigned pin, int value)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (!pio)
+ return -EINVAL;
+ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
+ return 0;
+}
+EXPORT_SYMBOL(at91_set_gpio_value);
+
+
+/*
+ * read the pin's value (works even if it's not muxed as a gpio).
+ */
+int at91_get_gpio_value(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+ u32 pdsr;
+
+ if (!pio)
+ return -EINVAL;
+ pdsr = __raw_readl(pio + PIO_PDSR);
+ return (pdsr & mask) != 0;
+}
+EXPORT_SYMBOL(at91_get_gpio_value);
+
+/*--------------------------------------------------------------------------*/
+
+
+/* Several AIC controller irqs are dispatched through this GPIO handler.
+ * To use any AT91_PIN_* as an externally triggered IRQ, first call
+ * at91_set_gpio_input() then maybe enable its glitch filter.
+ * Then just request_irq() with the pin ID; it works like any ARM IRQ
+ * handler, though it always triggers on rising and falling edges.
+ *
+ * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after
+ * configuring them with at91_set_a_periph() or at91_set_b_periph().
+ * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
+ */
+
+static void gpio_irq_mask(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (pio)
+ __raw_writel(mask, pio + PIO_IDR);
+}
+
+static void gpio_irq_unmask(unsigned pin)
+{
+ void __iomem *pio = pin_to_controller(pin);
+ unsigned mask = pin_to_mask(pin);
+
+ if (pio)
+ __raw_writel(mask, pio + PIO_IER);
+}
+
+static int gpio_irq_type(unsigned pin, unsigned type)
+{
+ return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
+}
+
+static struct irqchip gpio_irqchip = {
+ .mask = gpio_irq_mask,
+ .unmask = gpio_irq_unmask,
+ .set_type = gpio_irq_type,
+};
+
+static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)
+{
+ unsigned pin;
+ struct irqdesc *gpio;
+ void __iomem *pio;
+ u32 isr;
+
+ pio = (void __force __iomem *) desc->chipdata;
+
+ /* temporarily mask (level sensitive) parent IRQ */
+ desc->chip->ack(irq);
+ for (;;) {
+ isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
+ if (!isr)
+ break;
+
+ pin = (unsigned) desc->data;
+ gpio = &irq_desc[pin];
+
+ while (isr) {
+ if (isr & 1)
+ gpio->handle(pin, gpio, regs);
+ pin++;
+ gpio++;
+ isr >>= 1;
+ }
+ }
+ desc->chip->unmask(irq);
+ /* now it may re-trigger */
+}
+
+/* call this from board-specific init_irq */
+void __init at91_gpio_irq_setup(unsigned banks)
+{
+ unsigned pioc, pin, id;
+
+ if (banks > 4)
+ banks = 4;
+ for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA;
+ pioc < banks;
+ pioc++, id++) {
+ void __iomem *controller;
+ unsigned i;
+
+ controller = (void __iomem *) AT91_VA_BASE_SYS + pio_controller_offset[pioc];
+ __raw_writel(~0, controller + PIO_IDR);
+
+ set_irq_data(id, (void *) pin);
+ set_irq_chipdata(id, (void __force *) controller);
+
+ for (i = 0; i < 32; i++, pin++) {
+ set_irq_chip(pin, &gpio_irqchip);
+ set_irq_handler(pin, do_simple_IRQ);
+ set_irq_flags(pin, IRQF_VALID);
+ }
+
+ set_irq_chained_handler(id, gpio_irq_handler);
+
+ /* enable the PIO peripheral clock */
+ at91_sys_write(AT91_PMC_PCER, 1 << id);
+ }
+ pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks);
+}
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
new file mode 100644
index 000000000000..cb62bc83a1dd
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -0,0 +1,170 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/irq.c
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+
+#include "generic.h"
+
+/*
+ * The default interrupt priority levels (0 = lowest, 7 = highest).
+ */
+static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = {
+ 7, /* Advanced Interrupt Controller */
+ 7, /* System Peripheral */
+ 0, /* Parallel IO Controller A */
+ 0, /* Parallel IO Controller B */
+ 0, /* Parallel IO Controller C */
+ 0, /* Parallel IO Controller D */
+ 6, /* USART 0 */
+ 6, /* USART 1 */
+ 6, /* USART 2 */
+ 6, /* USART 3 */
+ 0, /* Multimedia Card Interface */
+ 4, /* USB Device Port */
+ 0, /* Two-Wire Interface */
+ 6, /* Serial Peripheral Interface */
+ 5, /* Serial Synchronous Controller */
+ 5, /* Serial Synchronous Controller */
+ 5, /* Serial Synchronous Controller */
+ 0, /* Timer Counter 0 */
+ 0, /* Timer Counter 1 */
+ 0, /* Timer Counter 2 */
+ 0, /* Timer Counter 3 */
+ 0, /* Timer Counter 4 */
+ 0, /* Timer Counter 5 */
+ 3, /* USB Host port */
+ 3, /* Ethernet MAC */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0, /* Advanced Interrupt Controller */
+ 0 /* Advanced Interrupt Controller */
+};
+
+
+static void at91rm9200_mask_irq(unsigned int irq)
+{
+ /* Disable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+}
+
+static void at91rm9200_unmask_irq(unsigned int irq)
+{
+ /* Enable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IECR, 1 << irq);
+}
+
+static int at91rm9200_irq_type(unsigned irq, unsigned type)
+{
+ unsigned int smr, srctype;
+
+ /* change triggering only for FIQ and external IRQ0..IRQ6 */
+ if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ))
+ return -EINVAL;
+
+ switch (type) {
+ case IRQT_HIGH:
+ srctype = AT91_AIC_SRCTYPE_HIGH;
+ break;
+ case IRQT_RISING:
+ srctype = AT91_AIC_SRCTYPE_RISING;
+ break;
+ case IRQT_LOW:
+ srctype = AT91_AIC_SRCTYPE_LOW;
+ break;
+ case IRQT_FALLING:
+ srctype = AT91_AIC_SRCTYPE_FALLING;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ smr = at91_sys_read(AT91_AIC_SMR(irq)) & ~AT91_AIC_SRCTYPE;
+ at91_sys_write(AT91_AIC_SMR(irq), smr | srctype);
+ return 0;
+}
+
+static struct irqchip at91rm9200_irq_chip = {
+ .ack = at91rm9200_mask_irq,
+ .mask = at91rm9200_mask_irq,
+ .unmask = at91rm9200_unmask_irq,
+ .set_type = at91rm9200_irq_type,
+};
+
+/*
+ * Initialize the AIC interrupt controller.
+ */
+void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS])
+{
+ unsigned int i;
+
+ /* No priority list specified for this board -> use defaults */
+ if (priority == NULL)
+ priority = at91rm9200_default_irq_priority;
+
+ /*
+ * The IVR is used by macro get_irqnr_and_base to read and verify.
+ * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
+ */
+ for (i = 0; i < NR_AIC_IRQS; i++) {
+ /* Put irq number in Source Vector Register: */
+ at91_sys_write(AT91_AIC_SVR(i), i);
+ /* Store the Source Mode Register as defined in table above */
+ at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
+
+ set_irq_chip(i, &at91rm9200_irq_chip);
+ set_irq_handler(i, do_level_IRQ);
+ set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+
+ /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
+ if (i < 8)
+ at91_sys_write(AT91_AIC_EOICR, 0);
+ }
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
+ * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
+ */
+ at91_sys_write(AT91_AIC_SPU, NR_AIC_IRQS);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ at91_sys_write(AT91_AIC_DCR, 0);
+
+ /* Disable and clear all interrupts initially */
+ at91_sys_write(AT91_AIC_IDCR, 0xFFFFFFFF);
+ at91_sys_write(AT91_AIC_ICCR, 0xFFFFFFFF);
+}
diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c
new file mode 100644
index 000000000000..1b6dd2deeb22
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/time.c
@@ -0,0 +1,127 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/time.c
+ *
+ * Copyright (C) 2003 SAN People
+ * Copyright (C) 2003 ATMEL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/time.h>
+
+/*
+ * The ST_CRTR is updated asynchronously to the master clock. It is therefore
+ * necessary to read it twice (with the same value) to ensure accuracy.
+ */
+static inline unsigned long read_CRTR(void) {
+ unsigned long x1, x2;
+
+ do {
+ x1 = at91_sys_read(AT91_ST_CRTR);
+ x2 = at91_sys_read(AT91_ST_CRTR);
+ } while (x1 != x2);
+
+ return x1;
+}
+
+/*
+ * Returns number of microseconds since last timer interrupt. Note that interrupts
+ * will have been disabled by do_gettimeofday()
+ * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
+ * 'tick' is usecs per jiffy (linux/timex.h).
+ */
+static unsigned long at91rm9200_gettimeoffset(void)
+{
+ unsigned long elapsed;
+
+ elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV;
+
+ return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*
+ * IRQ handler for the timer.
+ */
+static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long rtar;
+
+ if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */
+ write_seqlock(&xtime_lock);
+
+ do {
+ timer_tick(regs);
+ rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV;
+ at91_sys_write(AT91_ST_RTAR, rtar);
+ } while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH);
+
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+ }
+ else
+ return IRQ_NONE; /* not handled */
+}
+
+static struct irqaction at91rm9200_timer_irq = {
+ .name = "at91_tick",
+ .flags = SA_SHIRQ | SA_INTERRUPT,
+ .handler = at91rm9200_timer_interrupt
+};
+
+/*
+ * Set up timer interrupt.
+ */
+void __init at91rm9200_timer_init(void)
+{
+ /* Disable all timer interrupts */
+ at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
+ (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */
+
+ /*
+ * Make IRQs happen for the system timer.
+ */
+ setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+
+ /* Set initial alarm to 0 */
+ at91_sys_write(AT91_ST_RTAR, 0);
+
+ /* Real time counter incremented every 30.51758 microseconds */
+ at91_sys_write(AT91_ST_RTMR, 1);
+
+ /* Set Period Interval timer */
+ at91_sys_write(AT91_ST_PIMR, LATCH);
+
+ /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
+ tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
+
+ /* Enable Period Interval Timer interrupt */
+ at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
+struct sys_timer at91rm9200_timer = {
+ .init = at91rm9200_timer_init,
+ .offset = at91rm9200_gettimeoffset,
+};
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 43b9423d1440..c13ca6c56baa 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -64,7 +64,6 @@ void __init autcpu12_map_io(void)
MACHINE_START(AUTCPU12, "autronix autcpu12")
/* Maintainer: Thomas Gleixner */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0020000,
diff --git a/arch/arm/mach-clps711x/cdb89712.c b/arch/arm/mach-clps711x/cdb89712.c
index cba7be5a06c3..831df007f6c7 100644
--- a/arch/arm/mach-clps711x/cdb89712.c
+++ b/arch/arm/mach-clps711x/cdb89712.c
@@ -55,7 +55,6 @@ static void __init cdb89712_map_io(void)
MACHINE_START(CDB89712, "Cirrus-CDB89712")
/* Maintainer: Ray Lehtiniemi */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 35d51a759b59..e2b2c5ac8a83 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -56,7 +56,6 @@ static void __init ceiva_map_io(void)
MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
/* Maintainer: Rob Scott */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/clep7312.c b/arch/arm/mach-clps711x/clep7312.c
index c83f3fd68fcd..09fb57e45213 100644
--- a/arch/arm/mach-clps711x/clep7312.c
+++ b/arch/arm/mach-clps711x/clep7312.c
@@ -38,7 +38,6 @@ fixup_clep7312(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CLEP7212, "Cirrus Logic 7212/7312")
/* Maintainer: Nobody */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps711x/dma.c b/arch/arm/mach-clps711x/dma.c
deleted file mode 100644
index af5a4de38eac..000000000000
--- a/arch/arm/mach-clps711x/dma.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * linux/arch/arm/mach-clps711x/dma.c
- *
- * Copyright (C) 2000 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 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 <asm/dma.h>
-#include <asm/mach/dma.h>
-
-void __init arch_dma_init(dma_t *dma)
-{
-}
diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c
index 255c98b63e15..dc81cc68595d 100644
--- a/arch/arm/mach-clps711x/edb7211-arch.c
+++ b/arch/arm/mach-clps711x/edb7211-arch.c
@@ -52,7 +52,6 @@ fixup_edb7211(struct machine_desc *desc, struct tag *tags,
MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)")
/* Maintainer: Jon McClintock */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index 3d88da0c287b..ff26a85aa4ba 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -78,7 +78,6 @@ fortunet_fixup(struct machine_desc *desc, struct tag *tags,
MACHINE_START(FORTUNET, "ARM-FortuNet")
/* Maintainer: FortuNet Inc. */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x00000000,
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index a1acb945fb51..9ba45f4d5a7e 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -90,7 +90,6 @@ static void __init p720t_map_io(void)
MACHINE_START(P720T, "ARM-Prospector720T")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xff000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index d869af0023f8..5b12cab0e691 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -384,7 +384,6 @@ static void __init clps7500_init(void)
MACHINE_START(CLPS7500, "CL-PS7500")
/* Maintainer: Philip Blundell */
- .phys_ram = 0x10000000,
.phys_io = 0x03000000,
.io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.map_io = clps7500_map_io,
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index ed4614983adb..6d620d8268cc 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -284,7 +284,6 @@ arch_initcall(ebsa110_init);
MACHINE_START(EBSA110, "EBSA110")
/* Maintainer: Russell King */
- .phys_ram = 0x00000000,
.phys_io = 0xe0000000,
.io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x00000400,
diff --git a/arch/arm/mach-epxa10db/Kconfig b/arch/arm/mach-epxa10db/Kconfig
deleted file mode 100644
index 55d896dd4950..000000000000
--- a/arch/arm/mach-epxa10db/Kconfig
+++ /dev/null
@@ -1,23 +0,0 @@
-if ARCH_CAMELOT
-
-menu "Epxa10db"
-
-comment "PLD hotswap support"
-
-config PLD
- bool
- default y
-
-config PLD_HOTSWAP
- bool "Support for PLD device hotplugging (experimental)"
- depends on EXPERIMENTAL
- help
- This enables support for the dynamic loading and configuration of
- compatible drivers when the contents of the PLD are changed. This
- is still experimental and requires configuration tools which are
- not yet generally available. Say N here. You must enable the kernel
- module loader for this feature to work.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-epxa10db/Makefile b/arch/arm/mach-epxa10db/Makefile
deleted file mode 100644
index 24fbd7d3a3c1..000000000000
--- a/arch/arm/mach-epxa10db/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y := arch.o irq.o mm.o time.o
-obj-m :=
-obj-n :=
-obj- :=
-
diff --git a/arch/arm/mach-epxa10db/Makefile.boot b/arch/arm/mach-epxa10db/Makefile.boot
deleted file mode 100644
index 28bec7d3fc88..000000000000
--- a/arch/arm/mach-epxa10db/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
- zreladdr-y := 0x00008000
-
diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c
deleted file mode 100644
index 44c56571d183..000000000000
--- a/arch/arm/mach-epxa10db/arch.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * linux/arch/arm/mach-epxa10db/arch.c
- *
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#include <asm/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-
-static struct plat_serial8250_port serial_platform_data[] = {
- {
- .iobase = 0x3f8,
- .irq = IRQ_UARTINT0,
-#error FIXME
- .uartclk = 0,
- .regshift = 0,
- .iotype = UPIO_PORT,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- },
- {
- .iobase = 0x2f8,
- .irq = IRQ_UARTINT1,
-#error FIXME
- .uartclk = 0,
- .regshift = 0,
- .iotype = UPIO_PORT,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
- },
- { },
-};
-
-static struct platform_device serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = serial_platform_data,
- },
-};
-
-extern void epxa10db_map_io(void);
-extern void epxa10db_init_irq(void);
-extern struct sys_timer epxa10db_timer;
-
-MACHINE_START(CAMELOT, "Altera Epxa10db")
- /* Maintainer: Altera Corporation */
- .phys_ram = 0x00000000,
- .phys_io = 0x7fffc000,
- .io_pg_offst = ((0xffffc000) >> 18) & 0xfffc,
- .map_io = epxa10db_map_io,
- .init_irq = epxa10db_init_irq,
- .timer = &epxa10db_timer,
-MACHINE_END
-
diff --git a/arch/arm/mach-epxa10db/irq.c b/arch/arm/mach-epxa10db/irq.c
deleted file mode 100644
index 9bf927e13309..000000000000
--- a/arch/arm/mach-epxa10db/irq.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * linux/arch/arm/mach-epxa10db/irq.c
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/stddef.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/arch/platform.h>
-#include <asm/arch/int_ctrl00.h>
-
-
-static void epxa_mask_irq(unsigned int irq)
-{
- writel(1 << irq, INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE)));
-}
-
-static void epxa_unmask_irq(unsigned int irq)
-{
- writel(1 << irq, INT_MS(IO_ADDRESS(EXC_INT_CTRL00_BASE)));
-}
-
-
-static struct irqchip epxa_irq_chip = {
- .ack = epxa_mask_irq,
- .mask = epxa_mask_irq,
- .unmask = epxa_unmask_irq,
-};
-
-static struct resource irq_resource = {
- .name = "irq_handler",
- .start = IO_ADDRESS(EXC_INT_CTRL00_BASE),
- .end = IO_ADDRESS(INT_PRIORITY_FC(EXC_INT_CTRL00_BASE))+4,
-};
-
-void __init epxa10db_init_irq(void)
-{
- unsigned int i;
-
- request_resource(&iomem_resource, &irq_resource);
-
- /*
- * This bit sets up the interrupt controller using
- * the 6 PLD interrupts mode (the default) each
- * irqs is assigned a priority which is the same
- * as its interrupt number. This scheme is used because
- * its easy, but you may want to change it depending
- * on the contents of your PLD
- */
-
- writel(3,INT_MODE(IO_ADDRESS(EXC_INT_CTRL00_BASE)));
- for (i = 0; i < NR_IRQS; i++){
- writel(i+1, INT_PRIORITY_P0(IO_ADDRESS(EXC_INT_CTRL00_BASE)) + (4*i));
- set_irq_chip(i,&epxa_irq_chip);
- set_irq_handler(i,do_level_IRQ);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
- }
-
- /* Disable all interrupts */
- writel(-1,INT_MC(IO_ADDRESS(EXC_INT_CTRL00_BASE)));
-
-}
diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c
deleted file mode 100644
index cfd0d2182d44..000000000000
--- a/arch/arm/mach-epxa10db/mm.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * linux/arch/arm/mach-epxa10db/mm.c
- *
- * MM routines for Altera'a Epxa10db board
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-#include <asm/page.h>
-
-#include <asm/mach/map.h>
-
-/* Page table mapping for I/O region */
-
-static struct map_desc epxa10db_io_desc[] __initdata = {
- {
- .virtual = IO_ADDRESS(EXC_REGISTERS_BASE),
- .pfn = __phys_to_pfn(EXC_REGISTERS_BASE),
- .length = SZ_16K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(EXC_PLD_BLOCK0_BASE),
- .pfn = __phys_to_pfn(EXC_PLD_BLOCK0_BASE),
- .length = SZ_16K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(EXC_PLD_BLOCK1_BASE),
- .pfn =__phys_to_pfn(EXC_PLD_BLOCK1_BASE),
- .length = SZ_16K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(EXC_PLD_BLOCK2_BASE),
- .physical = __phys_to_pfn(EXC_PLD_BLOCK2_BASE),
- .length = SZ_16K,
- .type = MT_DEVICE
- }, {
- .virtual = IO_ADDRESS(EXC_PLD_BLOCK3_BASE),
- .pfn = __phys_to_pfn(EXC_PLD_BLOCK3_BASE),
- .length = SZ_16K,
- .type = MT_DEVICE
- }, {
- .virtual = FLASH_VADDR(EXC_EBI_BLOCK0_BASE),
- .pfn = __phys_to_pfn(EXC_EBI_BLOCK0_BASE),
- .length = SZ_16M,
- .type = MT_DEVICE
- }
-};
-
-void __init epxa10db_map_io(void)
-{
- iotable_init(epxa10db_io_desc, ARRAY_SIZE(epxa10db_io_desc));
-}
diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c
deleted file mode 100644
index 4b1084dde8dd..000000000000
--- a/arch/arm/mach-epxa10db/time.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * linux/arch/arm/mach-epxa10db/time.c
- *
- * Copyright (C) 2000 Deep Blue Solutions
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-
-#include <asm/hardware.h>
-#include <asm/system.h>
-#include <asm/leds.h>
-
-#include <asm/mach/time.h>
-
-#define TIMER00_TYPE (volatile unsigned int*)
-#include <asm/arch/timer00.h>
-
-static int epxa10db_set_rtc(void)
-{
- return 1;
-}
-
-static int epxa10db_rtc_init(void)
-{
- set_rtc = epxa10db_set_rtc;
-
- return 0;
-}
-
-__initcall(epxa10db_rtc_init);
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-epxa10db_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- write_seqlock(&xtime_lock);
-
- // ...clear the interrupt
- *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))|=TIMER0_CR_CI_MSK;
-
- timer_tick(regs);
- write_sequnlock(&xtime_lock);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction epxa10db_timer_irq = {
- .name = "Excalibur Timer Tick",
- .flags = SA_INTERRUPT | SA_TIMER,
- .handler = epxa10db_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-static void __init epxa10db_timer_init(void)
-{
- /* Start the timer */
- *TIMER0_LIMIT(IO_ADDRESS(EXC_TIMER00_BASE))=(unsigned int)(EXC_AHB2_CLK_FREQUENCY/200);
- *TIMER0_PRESCALE(IO_ADDRESS(EXC_TIMER00_BASE))=1;
- *TIMER0_CR(IO_ADDRESS(EXC_TIMER00_BASE))=TIMER0_CR_IE_MSK | TIMER0_CR_S_MSK;
-
- setup_irq(IRQ_TIMER0, &epxa10db_timer_irq);
-}
-
-struct sys_timer epxa10db_timer = {
- .init = epxa10db_timer_init,
-};
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 49b898af0032..5b64d5c5b967 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -85,7 +85,6 @@ fixup_cats(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CATS, "Chalice-CATS")
/* Maintainer: Philip Blundell */
- .phys_ram = 0x00000000,
.phys_io = DC21285_ARMCSR_BASE,
.io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/co285.c b/arch/arm/mach-footbridge/co285.c
index 548a79081688..4545576ad8d9 100644
--- a/arch/arm/mach-footbridge/co285.c
+++ b/arch/arm/mach-footbridge/co285.c
@@ -29,7 +29,6 @@ fixup_coebsa285(struct machine_desc *desc, struct tag *tags,
MACHINE_START(CO285, "co-EBSA285")
/* Maintainer: Mark van Doesburg */
- .phys_ram = 0x00000000,
.phys_io = DC21285_ARMCSR_BASE,
.io_pg_offst = ((0x7cf00000) >> 18) & 0xfffc,
.fixup = fixup_coebsa285,
diff --git a/arch/arm/mach-footbridge/dma.c b/arch/arm/mach-footbridge/dma.c
index a6b1396b0951..7a54578b51af 100644
--- a/arch/arm/mach-footbridge/dma.c
+++ b/arch/arm/mach-footbridge/dma.c
@@ -15,6 +15,7 @@
#include <asm/dma.h>
#include <asm/io.h>
+#include <asm/scatterlist.h>
#include <asm/mach/dma.h>
#include <asm/hardware/dec21285.h>
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 1c37605268d5..b1d3bf20a41e 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -14,7 +14,6 @@
MACHINE_START(EBSA285, "EBSA285")
/* Maintainer: Russell King */
- .phys_ram = 0x00000000,
.phys_io = DC21285_ARMCSR_BASE,
.io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index 775f85fc8513..229bf0585e40 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -601,6 +601,7 @@ EXPORT_SYMBOL(gpio_lock);
EXPORT_SYMBOL(gpio_modify_op);
EXPORT_SYMBOL(gpio_modify_io);
EXPORT_SYMBOL(cpld_modify);
+EXPORT_SYMBOL(gpio_read);
/*
* Initialise any other hardware after we've got the PCI bus
@@ -648,7 +649,6 @@ fixup_netwinder(struct machine_desc *desc, struct tag *tags,
MACHINE_START(NETWINDER, "Rebel-NetWinder")
/* Maintainer: Russell King/Rebel.com */
- .phys_ram = 0x00000000,
.phys_io = DC21285_ARMCSR_BASE,
.io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index 0146b8bb59da..c4f843fc099d 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -14,7 +14,6 @@
MACHINE_START(PERSONAL_SERVER, "Compaq-PersonalServer")
/* Maintainer: Jamey Hicks / George France */
- .phys_ram = 0x00000000,
.phys_io = DC21285_ARMCSR_BASE,
.io_pg_offst = ((0xfe000000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index fa59e9e2a5c8..193f968edac3 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -31,7 +31,6 @@
MACHINE_START(H7201, "Hynix GMS30C7201")
/* Maintainer: Robert Schwebel, Pengutronix */
- .phys_ram = 0x40000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0xc0001000,
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index d75c8221d2a5..36266896979c 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -72,7 +72,6 @@ static void __init init_eval_h7202(void)
MACHINE_START(H7202, "Hynix HMS30C7202")
/* Maintainer: Robert Schwebel, Pengutronix */
- .phys_ram = 0x40000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf0000000) >> 18) & 0xfffc,
.boot_params = 0x40000100,
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index 708e1b3faa14..dc31e3fd6c57 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -29,27 +29,27 @@
#include "generic.h"
#include <asm/serial.h>
-static struct resource mx1ads_resources[] = {
+static struct resource cs89x0_resources[] = {
[0] = {
- .start = IMX_CS4_VIRT,
- .end = IMX_CS4_VIRT + 16,
+ .start = IMX_CS4_PHYS + 0x300,
+ .end = IMX_CS4_PHYS + 0x300 + 16,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 13,
- .end = 13,
+ .start = IRQ_GPIOC(17),
+ .end = IRQ_GPIOC(17),
.flags = IORESOURCE_IRQ,
},
};
-static struct platform_device mx1ads_device = {
- .name = "mx1ads",
- .num_resources = ARRAY_SIZE(mx1ads_resources),
- .resource = mx1ads_resources,
+static struct platform_device cs89x0_device = {
+ .name = "cirrus-cs89x0",
+ .num_resources = ARRAY_SIZE(cs89x0_resources),
+ .resource = cs89x0_resources,
};
static struct platform_device *devices[] __initdata = {
- &mx1ads_device,
+ &cs89x0_device,
};
static void __init
@@ -61,50 +61,14 @@ mx1ads_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
}
-static struct map_desc mx1ads_io_desc[] __initdata = {
- {
- .virtual = IMX_CS0_VIRT,
- .pfn = __phys_to_pfn(IMX_CS0_PHYS),
- .length = IMX_CS0_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IMX_CS1_VIRT,
- .pfn = __phys_to_pfn(IMX_CS1_PHYS),
- .length = IMX_CS1_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IMX_CS2_VIRT,
- .pfn = __phys_to_pfn(IMX_CS2_PHYS),
- .length = IMX_CS2_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IMX_CS3_VIRT,
- .pfn = __phys_to_pfn(IMX_CS3_PHYS),
- .length = IMX_CS3_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IMX_CS4_VIRT,
- .pfn = __phys_to_pfn(IMX_CS4_PHYS),
- .length = IMX_CS4_SIZE,
- .type = MT_DEVICE
- }, {
- .virtual = IMX_CS5_VIRT,
- .pfn = __phys_to_pfn(IMX_CS5_PHYS),
- .length = IMX_CS5_SIZE,
- .type = MT_DEVICE
- }
-};
-
static void __init
mx1ads_map_io(void)
{
imx_map_io();
- iotable_init(mx1ads_io_desc, ARRAY_SIZE(mx1ads_io_desc));
}
MACHINE_START(MX1ADS, "Motorola MX1ADS")
/* Maintainer: Sascha Hauer, Pengutronix */
- .phys_ram = 0x08000000,
.phys_io = 0x00200000,
.io_pg_offst = ((0xe0200000) >> 18) & 0xfffc,
.boot_params = 0x08000100,
diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
index 73c360685cad..95a1e263f7fa 100644
--- a/arch/arm/mach-integrator/clock.c
+++ b/arch/arm/mach-integrator/clock.c
@@ -14,28 +14,29 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
-#include <asm/hardware/clock.h>
#include <asm/hardware/icst525.h>
#include "clock.h"
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -58,17 +59,6 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL(clk_disable);
-int clk_use(struct clk *clk)
-{
- return 0;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_unuse);
-
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
@@ -118,18 +108,18 @@ static struct clk uart_clk = {
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index dacbf504dae2..20071a2767cc 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -15,11 +15,11 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/smp.h>
+#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/hardware/amba.h>
#include <asm/hardware/arm_timer.h>
#include <asm/arch/cm.h>
#include <asm/system.h>
diff --git a/arch/arm/mach-integrator/dma.c b/arch/arm/mach-integrator/dma.c
deleted file mode 100644
index aae6f23cd72b..000000000000
--- a/arch/arm/mach-integrator/dma.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/mach-integrator/dma.c
- *
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 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 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/slab.h>
-#include <linux/mman.h>
-#include <linux/init.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-
-#include <asm/mach/dma.h>
-
-void __init arch_dma_init(dma_t *dma)
-{
-}
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index a4bafee77a06..a85d471c5bfa 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -18,11 +18,11 @@
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/mm.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
#include <asm/io.h>
#include <asm/hardware/icst525.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_clcd.h>
#include <asm/arch/lm.h>
#include <asm/arch/impd1.h>
#include <asm/sizes.h>
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 4c0f7c65facf..d8d3c2a5a97e 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -25,6 +25,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -32,8 +34,6 @@
#include <asm/setup.h>
#include <asm/param.h> /* HZ */
#include <asm/mach-types.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_kmi.h>
#include <asm/arch/lm.h>
@@ -347,7 +347,6 @@ static struct sys_timer ap_timer = {
MACHINE_START(INTEGRATOR, "ARM-Integrator")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0x00000000,
.phys_io = 0x16000000,
.io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 93f7ccb22c27..31820170f306 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -16,15 +16,15 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
+#include <linux/amba/clcd.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_kmi.h>
-#include <asm/hardware/amba_clcd.h>
#include <asm/hardware/icst525.h>
#include <asm/arch/cm.h>
@@ -578,7 +578,6 @@ static struct sys_timer cp_timer = {
MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0x00000000,
.phys_io = 0x16000000,
.io_pg_offst = ((0xf1600000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-integrator/lm.c b/arch/arm/mach-integrator/lm.c
index 5b41e3a724e1..622cdc4212dd 100644
--- a/arch/arm/mach-integrator/lm.c
+++ b/arch/arm/mach-integrator/lm.c
@@ -22,20 +22,6 @@ static int lm_match(struct device *dev, struct device_driver *drv)
return 1;
}
-static struct bus_type lm_bustype = {
- .name = "logicmodule",
- .match = lm_match,
-// .suspend = lm_suspend,
-// .resume = lm_resume,
-};
-
-static int __init lm_init(void)
-{
- return bus_register(&lm_bustype);
-}
-
-postcore_initcall(lm_init);
-
static int lm_bus_probe(struct device *dev)
{
struct lm_device *lmdev = to_lm_device(dev);
@@ -49,16 +35,30 @@ static int lm_bus_remove(struct device *dev)
struct lm_device *lmdev = to_lm_device(dev);
struct lm_driver *lmdrv = to_lm_driver(dev->driver);
- lmdrv->remove(lmdev);
+ if (lmdrv->remove)
+ lmdrv->remove(lmdev);
return 0;
}
+static struct bus_type lm_bustype = {
+ .name = "logicmodule",
+ .match = lm_match,
+ .probe = lm_bus_probe,
+ .remove = lm_bus_remove,
+// .suspend = lm_bus_suspend,
+// .resume = lm_bus_resume,
+};
+
+static int __init lm_init(void)
+{
+ return bus_register(&lm_bustype);
+}
+
+postcore_initcall(lm_init);
+
int lm_driver_register(struct lm_driver *drv)
{
drv->drv.bus = &lm_bustype;
- drv->drv.probe = lm_bus_probe;
- drv->drv.remove = lm_bus_remove;
-
return driver_register(&drv->drv);
}
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
index 1a844ca139e0..3c22c16b38bf 100644
--- a/arch/arm/mach-integrator/time.c
+++ b/arch/arm/mach-integrator/time.c
@@ -14,8 +14,8 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/amba/bus.h>
-#include <asm/hardware/amba.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -96,7 +96,8 @@ static struct rtc_ops rtc_ops = {
.set_alarm = rtc_set_alarm,
};
-static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
writel(0, rtc_base + RTC_EOI);
return IRQ_HANDLED;
@@ -124,7 +125,7 @@ static int rtc_probe(struct amba_device *dev, void *id)
xtime.tv_sec = __raw_readl(rtc_base + RTC_DR);
- ret = request_irq(dev->irq[0], rtc_interrupt, SA_INTERRUPT,
+ ret = request_irq(dev->irq[0], arm_rtc_interrupt, SA_INTERRUPT,
"rtc-pl030", dev);
if (ret)
goto map_out;
diff --git a/arch/arm/mach-iop3xx/iop321-setup.c b/arch/arm/mach-iop3xx/iop321-setup.c
index 80770233b8d4..e4f4c52d93d4 100644
--- a/arch/arm/mach-iop3xx/iop321-setup.c
+++ b/arch/arm/mach-iop3xx/iop321-setup.c
@@ -151,7 +151,6 @@ extern void iop321_init_time(void);
#if defined(CONFIG_ARCH_IQ80321)
MACHINE_START(IQ80321, "Intel IQ80321")
/* Maintainer: Intel Corporation */
- .phys_ram = PHYS_OFFSET,
.phys_io = IQ80321_UART,
.io_pg_offst = ((IQ80321_UART) >> 18) & 0xfffc,
.map_io = iq80321_map_io,
@@ -163,7 +162,6 @@ MACHINE_END
#elif defined(CONFIG_ARCH_IQ31244)
MACHINE_START(IQ31244, "Intel IQ31244")
/* Maintainer: Intel Corp. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IQ31244_UART,
.io_pg_offst = ((IQ31244_UART) >> 18) & 0xfffc,
.map_io = iq31244_map_io,
diff --git a/arch/arm/mach-iop3xx/iop331-setup.c b/arch/arm/mach-iop3xx/iop331-setup.c
index 53f60614498b..63585485123e 100644
--- a/arch/arm/mach-iop3xx/iop331-setup.c
+++ b/arch/arm/mach-iop3xx/iop331-setup.c
@@ -18,7 +18,7 @@
#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/tty.h>
-#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
#include <asm/io.h>
#include <asm/pgtable.h>
@@ -50,32 +50,74 @@ static struct map_desc iop331_std_desc[] __initdata = {
}
};
-static struct uart_port iop331_serial_ports[] = {
- {
- .membase = (char*)(IOP331_UART0_VIRT),
- .mapbase = (IOP331_UART0_PHYS),
- .irq = IRQ_IOP331_UART0,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IOP331_UART_XTAL,
- .line = 0,
- .type = PORT_XSCALE,
- .fifosize = 32
- } , {
- .membase = (char*)(IOP331_UART1_VIRT),
- .mapbase = (IOP331_UART1_PHYS),
- .irq = IRQ_IOP331_UART1,
- .flags = UPF_SKIP_TEST,
- .iotype = UPIO_MEM,
- .regshift = 2,
- .uartclk = IOP331_UART_XTAL,
- .line = 1,
- .type = PORT_XSCALE,
- .fifosize = 32
+static struct resource iop33x_uart0_resources[] = {
+ [0] = {
+ .start = IOP331_UART0_PHYS,
+ .end = IOP331_UART0_PHYS + 0x3f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IOP331_UART0,
+ .end = IRQ_IOP331_UART0,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource iop33x_uart1_resources[] = {
+ [0] = {
+ .start = IOP331_UART1_PHYS,
+ .end = IOP331_UART1_PHYS + 0x3f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IOP331_UART1,
+ .end = IRQ_IOP331_UART1,
+ .flags = IORESOURCE_IRQ
}
};
+static struct plat_serial8250_port iop33x_uart0_data[] = {
+ {
+ .membase = (char*)(IOP331_UART0_VIRT),
+ .mapbase = (IOP331_UART0_PHYS),
+ .irq = IRQ_IOP331_UART0,
+ .uartclk = IOP331_UART_XTAL,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_SKIP_TEST,
+ },
+ { },
+};
+
+static struct plat_serial8250_port iop33x_uart1_data[] = {
+ {
+ .membase = (char*)(IOP331_UART1_VIRT),
+ .mapbase = (IOP331_UART1_PHYS),
+ .irq = IRQ_IOP331_UART1,
+ .uartclk = IOP331_UART_XTAL,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_SKIP_TEST,
+ },
+ { },
+};
+
+static struct platform_device iop33x_uart0 = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = iop33x_uart0_data,
+ .num_resources = 2,
+ .resource = iop33x_uart0_resources,
+};
+
+static struct platform_device iop33x_uart1 = {
+ .name = "serial8250",
+ .id = 1,
+ .dev.platform_data = iop33x_uart1_data,
+ .num_resources = 2,
+ .resource = iop33x_uart1_resources,
+};
+
static struct resource iop33x_i2c_0_resources[] = {
[0] = {
.start = 0xfffff680,
@@ -117,6 +159,8 @@ static struct platform_device iop33x_i2c_1_controller = {
};
static struct platform_device *iop33x_devices[] __initdata = {
+ &iop33x_uart0,
+ &iop33x_uart1,
&iop33x_i2c_0_controller,
&iop33x_i2c_1_controller
};
@@ -133,8 +177,6 @@ void __init iop33x_init(void)
void __init iop331_map_io(void)
{
iotable_init(iop331_std_desc, ARRAY_SIZE(iop331_std_desc));
- early_serial_setup(&iop331_serial_ports[0]);
- early_serial_setup(&iop331_serial_ports[1]);
}
#ifdef CONFIG_ARCH_IOP331
@@ -153,7 +195,6 @@ extern void iq80332_map_io(void);
#if defined(CONFIG_ARCH_IQ80331)
MACHINE_START(IQ80331, "Intel IQ80331")
/* Maintainer: Intel Corp. */
- .phys_ram = PHYS_OFFSET,
.phys_io = 0xfefff000,
.io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
.map_io = iq80331_map_io,
@@ -166,7 +207,6 @@ MACHINE_END
#elif defined(CONFIG_MACH_IQ80332)
MACHINE_START(IQ80332, "Intel IQ80332")
/* Maintainer: Intel Corp. */
- .phys_ram = PHYS_OFFSET,
.phys_io = 0xfefff000,
.io_pg_offst = ((0xfffff000) >> 18) & 0xfffc, // virtual, physical
.map_io = iq80332_map_io,
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 6851abaf5524..cfd5bef3190b 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -106,6 +106,16 @@ static struct map_desc ixp2000_io_desc[] __initdata = {
.length = IXP2000_MSF_SIZE,
.type = MT_IXP2000_DEVICE,
}, {
+ .virtual = IXP2000_SCRATCH_RING_VIRT_BASE,
+ .pfn = __phys_to_pfn(IXP2000_SCRATCH_RING_PHYS_BASE),
+ .length = IXP2000_SCRATCH_RING_SIZE,
+ .type = MT_IXP2000_DEVICE,
+ }, {
+ .virtual = IXP2000_SRAM0_VIRT_BASE,
+ .pfn = __phys_to_pfn(IXP2000_SRAM0_PHYS_BASE),
+ .length = IXP2000_SRAM0_SIZE,
+ .type = MT_IXP2000_DEVICE,
+ }, {
.virtual = IXP2000_PCI_IO_VIRT_BASE,
.pfn = __phys_to_pfn(IXP2000_PCI_IO_PHYS_BASE),
.length = IXP2000_PCI_IO_SIZE,
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 61f6006241bd..9e5a13bb39d0 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -254,7 +254,6 @@ static void __init enp2611_init_machine(void)
MACHINE_START(ENP2611, "Radisys ENP-2611 PCI network processor board")
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
- .phys_ram = 0x00000000,
.phys_io = IXP2000_UART_PHYS_BASE,
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2400.c b/arch/arm/mach-ixp2000/ixdp2400.c
index fd280a93637e..7c782403042a 100644
--- a/arch/arm/mach-ixp2000/ixdp2400.c
+++ b/arch/arm/mach-ixp2000/ixdp2400.c
@@ -169,7 +169,6 @@ void ixdp2400_init_irq(void)
MACHINE_START(IXDP2400, "Intel IXDP2400 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = 0x00000000,
.phys_io = IXP2000_UART_PHYS_BASE,
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index f9073aa28615..076e3f8acc96 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -285,7 +285,6 @@ void ixdp2800_init_irq(void)
MACHINE_START(IXDP2800, "Intel IXDP2800 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = 0x00000000,
.phys_io = IXP2000_UART_PHYS_BASE,
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
index e6a882f35da2..10f06606d460 100644
--- a/arch/arm/mach-ixp2000/ixdp2x01.c
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c
@@ -376,7 +376,6 @@ static void __init ixdp2x01_init_machine(void)
#ifdef CONFIG_ARCH_IXDP2401
MACHINE_START(IXDP2401, "Intel IXDP2401 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = 0x00000000,
.phys_io = IXP2000_UART_PHYS_BASE,
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
@@ -390,7 +389,6 @@ MACHINE_END
#ifdef CONFIG_ARCH_IXDP2801
MACHINE_START(IXDP2801, "Intel IXDP2801 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = 0x00000000,
.phys_io = IXP2000_UART_PHYS_BASE,
.io_pg_offst = ((IXP2000_UART_VIRT_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 385285851cb5..daadc78e271b 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -71,6 +71,14 @@ config ARCH_PRPMC1100
PrPCM1100 Processor Mezanine Module. For more information on
this platform, see <file:Documentation/arm/IXP4xx>.
+config MACH_NAS100D
+ bool
+ prompt "NAS100D"
+ help
+ Say 'Y' here if you want your kernel to support Iomega's
+ NAS 100d device. For more information on this platform,
+ see http://www.nslu2-linux.org/wiki/NAS100d/HomePage
+
#
# Avila and IXDP share the same source for now. Will change in future
#
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 7a15629c18d0..0471044fa179 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o gtwx5715-setup.o
obj-$(CONFIG_MACH_NSLU2) += nslu2-pci.o nslu2-setup.o nslu2-power.o
+obj-$(CONFIG_MACH_NAS100D) += nas100d-pci.o nas100d-setup.o nas100d-power.o
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 9795da270e3a..6e3462ed5306 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -341,6 +341,29 @@ int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
}
+/*
+ * Only first 64MB of memory can be accessed via PCI.
+ * We use GFP_DMA to allocate safe buffers to do map/unmap.
+ * This is really ugly and we need a better way of specifying
+ * DMA-capable regions of memory.
+ */
+void __init ixp4xx_adjust_zones(int node, unsigned long *zone_size,
+ unsigned long *zhole_size)
+{
+ unsigned int sz = SZ_64M >> PAGE_SHIFT;
+
+ /*
+ * Only adjust if > 64M on current system
+ */
+ if (node || (zone_size[0] <= sz))
+ return;
+
+ zone_size[1] = zone_size[0] - sz;
+ zone_size[0] = sz;
+ zhole_size[1] = zhole_size[0];
+ zhole_size[0] = 0;
+}
+
void __init ixp4xx_pci_preinit(void)
{
unsigned long processor_id;
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index f3c687cf0071..4bdc9d4526cd 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -142,6 +142,8 @@ static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
*int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
(line * IXP4XX_GPIO_STYLE_SIZE));
+ *IXP4XX_GPIO_GPISR = (1 << line);
+
/* Set the new style */
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
@@ -169,7 +171,7 @@ static void ixp4xx_irq_ack(unsigned int irq)
int line = (irq < 32) ? irq2gpio[irq] : -1;
if (line >= 0)
- gpio_line_isr_clear(line);
+ *IXP4XX_GPIO_GPISR = (1 << line);
}
/*
@@ -330,11 +332,28 @@ static struct platform_device *ixp46x_devices[] __initdata = {
&ixp46x_i2c_controller
};
+unsigned long ixp4xx_exp_bus_size;
+EXPORT_SYMBOL(ixp4xx_exp_bus_size);
+
void __init ixp4xx_sys_init(void)
{
+ ixp4xx_exp_bus_size = SZ_16M;
+
if (cpu_is_ixp46x()) {
+ int region;
+
platform_add_devices(ixp46x_devices,
ARRAY_SIZE(ixp46x_devices));
+
+ for (region = 0; region < 7; region++) {
+ if((*(IXP4XX_EXP_REG(0x4 * region)) & 0x200)) {
+ ixp4xx_exp_bus_size = SZ_32M;
+ break;
+ }
+ }
}
+
+ printk("IXP4xx: Using %luMiB expansion bus window size\n",
+ ixp4xx_exp_bus_size >> 20);
}
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index 60de8a94cff5..e6b7fcd923fa 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -33,9 +33,6 @@ void __init coyote_pci_preinit(void)
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);
-
ixp4xx_pci_preinit();
}
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 050c92768913..13f8a7ac3ba9 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -14,6 +14,7 @@
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_8250.h>
+#include <linux/slab.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -30,8 +31,6 @@ static struct flash_platform_data coyote_flash_data = {
};
static struct resource coyote_flash_resource = {
- .start = COYOTE_FLASH_BASE,
- .end = COYOTE_FLASH_BASE + COYOTE_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
@@ -81,6 +80,11 @@ static struct platform_device *coyote_devices[] __initdata = {
static void __init coyote_init(void)
{
+ ixp4xx_sys_init();
+
+ coyote_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ coyote_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
@@ -91,15 +95,12 @@ static void __init coyote_init(void)
coyote_uart_data[0].irq = IRQ_IXP4XX_UART1;
}
-
- ixp4xx_sys_init();
platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
}
#ifdef CONFIG_ARCH_ADI_COYOTE
MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
@@ -117,7 +118,6 @@ MACHINE_END
#ifdef CONFIG_MACH_IXDPG425
MACHINE_START(IXDPG425, "Intel IXDPG425")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 29a6d02fa851..654e2eed81fb 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -27,6 +27,7 @@
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_8250.h>
+#include <linux/slab.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -106,11 +107,9 @@ static struct flash_platform_data gtwx5715_flash_data = {
.width = 2,
};
-static struct resource gtwx5715_flash_resource = {
- .start = GTWX5715_FLASH_BASE,
- .end = GTWX5715_FLASH_BASE + GTWX5715_FLASH_SIZE - 1,
+static struct gtw5715_flash_resource = {
.flags = IORESOURCE_MEM,
-};
+}
static struct platform_device gtwx5715_flash = {
.name = "IXP4XX-Flash",
@@ -129,13 +128,20 @@ static struct platform_device *gtwx5715_devices[] __initdata = {
static void __init gtwx5715_init(void)
{
+ ixp4xx_sys_init();
+
+ if (!flash_resource)
+ printk(KERN_ERR "Could not allocate flash resource\n");
+
+ gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
+
platform_add_devices(gtwx5715_devices, ARRAY_SIZE(gtwx5715_devices));
}
MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
/* Maintainer: George Joseph */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_UART2_BASE_PHYS,
.io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index f9a1d3e7d692..da415d5d7f37 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -32,11 +32,6 @@ void __init ixdp425_pci_preinit(void)
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);
- gpio_line_isr_clear(IXDP425_PCI_INTC_PIN);
- gpio_line_isr_clear(IXDP425_PCI_INTD_PIN);
-
ixp4xx_pci_preinit();
}
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 3a22d84e1047..da72383ee301 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -14,6 +14,7 @@
#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial_8250.h>
+#include <linux/slab.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -30,8 +31,6 @@ static struct flash_platform_data ixdp425_flash_data = {
};
static struct resource ixdp425_flash_resource = {
- .start = IXDP425_FLASH_BASE,
- .end = IXDP425_FLASH_BASE + IXDP425_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
@@ -108,17 +107,13 @@ static struct platform_device *ixdp425_devices[] __initdata = {
&ixdp425_uart
};
-
static void __init ixdp425_init(void)
{
ixp4xx_sys_init();
- /*
- * IXP465 has 32MB window
- */
- if (machine_is_ixdp465()) {
- ixdp425_flash_resource.end += IXDP425_FLASH_SIZE;
- }
+ ixdp425_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ ixdp425_flash_resource.end =
+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices));
}
@@ -126,7 +121,6 @@ static void __init ixdp425_init(void)
#ifdef CONFIG_ARCH_IXDP425
MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
@@ -140,7 +134,6 @@ MACHINE_END
#ifdef CONFIG_MACH_IXDP465
MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
@@ -154,7 +147,6 @@ MACHINE_END
#ifdef CONFIG_ARCH_PRPMC1100
MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
@@ -174,7 +166,6 @@ MACHINE_END
#ifdef CONFIG_ARCH_AVILA
MACHINE_START(AVILA, "Gateworks Avila Network Platform")
/* Maintainer: Deepak Saxena <dsaxena@plexity.net> */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
.map_io = ixp4xx_map_io,
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index fe5e7660de1d..526fb6175bc3 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -32,9 +32,6 @@ void __init ixdpg425_pci_preinit(void)
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);
-
ixp4xx_pci_preinit();
}
diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c
new file mode 100644
index 000000000000..26b7c001ff64
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/nas100d-pci.c
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/mach-ixp4xx/nas100d-pci.c
+ *
+ * NAS 100d board-level PCI initialization
+ *
+ * based on ixdp425-pci.c:
+ * Copyright (C) 2002 Intel Corporation.
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Maintainer: http://www.nslu2-linux.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/config.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+void __init nas100d_pci_preinit(void)
+{
+ set_irq_type(IRQ_NAS100D_PCI_INTA, IRQT_LOW);
+ set_irq_type(IRQ_NAS100D_PCI_INTB, IRQT_LOW);
+ set_irq_type(IRQ_NAS100D_PCI_INTC, IRQT_LOW);
+ set_irq_type(IRQ_NAS100D_PCI_INTD, IRQT_LOW);
+ set_irq_type(IRQ_NAS100D_PCI_INTE, IRQT_LOW);
+
+ ixp4xx_pci_preinit();
+}
+
+static int __init nas100d_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ static int pci_irq_table[NAS100D_PCI_MAX_DEV][NAS100D_PCI_IRQ_LINES] =
+ {
+ { IRQ_NAS100D_PCI_INTA, -1, -1 },
+ { IRQ_NAS100D_PCI_INTB, -1, -1 },
+ { IRQ_NAS100D_PCI_INTC, IRQ_NAS100D_PCI_INTD, IRQ_NAS100D_PCI_INTE },
+ };
+
+ int irq = -1;
+
+ if (slot >= 1 && slot <= NAS100D_PCI_MAX_DEV &&
+ pin >= 1 && pin <= NAS100D_PCI_IRQ_LINES)
+ irq = pci_irq_table[slot-1][pin-1];
+
+ return irq;
+}
+
+struct hw_pci __initdata nas100d_pci = {
+ .nr_controllers = 1,
+ .preinit = nas100d_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = nas100d_map_irq,
+};
+
+int __init nas100d_pci_init(void)
+{
+ if (machine_is_nas100d())
+ pci_common_init(&nas100d_pci);
+
+ return 0;
+}
+
+subsys_initcall(nas100d_pci_init);
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
new file mode 100644
index 000000000000..2bec69bfa715
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/nas100d-power.c
@@ -0,0 +1,67 @@
+/*
+ * arch/arm/mach-ixp4xx/nas100d-power.c
+ *
+ * NAS 100d Power/Reset driver
+ *
+ * Copyright (C) 2005 Tower Technologies
+ *
+ * based on nas100d-io.c
+ * Copyright (C) 2004 Karen Spearel
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.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/reboot.h>
+#include <linux/interrupt.h>
+
+#include <asm/mach-types.h>
+
+extern void ctrl_alt_del(void);
+
+static irqreturn_t nas100d_reset_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* Signal init to do the ctrlaltdel action, this will bypass init if
+ * it hasn't started and do a kernel_restart.
+ */
+ ctrl_alt_del();
+
+ return IRQ_HANDLED;
+}
+
+static int __init nas100d_power_init(void)
+{
+ if (!(machine_is_nas100d()))
+ return 0;
+
+ set_irq_type(NAS100D_RB_IRQ, IRQT_LOW);
+
+ if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler,
+ SA_INTERRUPT, "NAS100D reset button", NULL) < 0) {
+
+ printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+ NAS100D_RB_IRQ);
+
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void __exit nas100d_power_exit(void)
+{
+ free_irq(NAS100D_RB_IRQ, NULL);
+}
+
+module_init(nas100d_power_init);
+module_exit(nas100d_power_exit);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("NAS100D Power/Reset driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
new file mode 100644
index 000000000000..856d56f3b2ae
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -0,0 +1,134 @@
+/*
+ * arch/arm/mach-ixp4xx/nas100d-setup.c
+ *
+ * NAS 100d board-setup
+ *
+ * based ixdp425-setup.c:
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Author: Rod Whitby <rod@whitby.id.au>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data nas100d_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+};
+
+static struct resource nas100d_flash_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device nas100d_flash = {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev.platform_data = &nas100d_flash_data,
+ .num_resources = 1,
+ .resource = &nas100d_flash_resource,
+};
+
+static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
+ .sda_pin = NAS100D_SDA_PIN,
+ .scl_pin = NAS100D_SCL_PIN,
+};
+
+static struct platform_device nas100d_i2c_controller = {
+ .name = "IXP4XX-I2C",
+ .id = 0,
+ .dev.platform_data = &nas100d_i2c_gpio_pins,
+ .num_resources = 0,
+};
+
+static struct resource nas100d_uart_resources[] = {
+ {
+ .start = IXP4XX_UART1_BASE_PHYS,
+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct plat_serial8250_port nas100d_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART1_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART1,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ { }
+};
+
+static struct platform_device nas100d_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = nas100d_uart_data,
+ .num_resources = 2,
+ .resource = nas100d_uart_resources,
+};
+
+static struct platform_device *nas100d_devices[] __initdata = {
+ &nas100d_i2c_controller,
+ &nas100d_flash,
+ &nas100d_uart,
+};
+
+static void nas100d_power_off(void)
+{
+ /* This causes the box to drop the power and go dead. */
+
+ /* enable the pwr cntl gpio */
+ gpio_line_config(NAS100D_PO_GPIO, IXP4XX_GPIO_OUT);
+
+ /* do the deed */
+ gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH);
+}
+
+static void __init nas100d_init(void)
+{
+ ixp4xx_sys_init();
+
+ nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ nas100d_flash_resource.end =
+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+
+ pm_power_off = nas100d_power_off;
+
+ platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
+}
+
+MACHINE_START(NAS100D, "Iomega NAS 100d")
+ /* Maintainer: www.nslu2-linux.org */
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
+ .boot_params = 0x00000100,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .init_machine = nas100d_init,
+MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
index a575f2e0b2c8..ece860444d5b 100644
--- a/arch/arm/mach-ixp4xx/nslu2-pci.c
+++ b/arch/arm/mach-ixp4xx/nslu2-pci.c
@@ -28,14 +28,6 @@ void __init nslu2_pci_preinit(void)
set_irq_type(IRQ_NSLU2_PCI_INTB, IRQT_LOW);
set_irq_type(IRQ_NSLU2_PCI_INTC, IRQT_LOW);
- gpio_line_isr_clear(NSLU2_PCI_INTA_PIN);
- gpio_line_isr_clear(NSLU2_PCI_INTB_PIN);
- gpio_line_isr_clear(NSLU2_PCI_INTC_PIN);
-
- /* INTD is not configured as GPIO is used
- * for the power input button.
- */
-
ixp4xx_pci_preinit();
}
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
index 18fbc8c0fb30..b0ad9e901f6e 100644
--- a/arch/arm/mach-ixp4xx/nslu2-power.c
+++ b/arch/arm/mach-ixp4xx/nslu2-power.c
@@ -54,9 +54,6 @@ static int __init nslu2_power_init(void)
set_irq_type(NSLU2_RB_IRQ, IRQT_LOW);
set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH);
- gpio_line_isr_clear(NSLU2_RB_GPIO);
- gpio_line_isr_clear(NSLU2_PB_GPIO);
-
if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler,
SA_INTERRUPT, "NSLU2 reset button", NULL) < 0) {
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 289e94cb65c2..da9340a53434 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -123,7 +123,6 @@ static void __init nslu2_init(void)
MACHINE_START(NSLU2, "Linksys NSLU2")
/* Maintainer: www.nslu2-linux.org */
- .phys_ram = PHYS_OFFSET,
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xFFFC,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c
index 03ed742ae2be..ac626436e96f 100644
--- a/arch/arm/mach-l7200/core.c
+++ b/arch/arm/mach-l7200/core.c
@@ -91,7 +91,6 @@ static void __init l7200_map_io(void)
MACHINE_START(L7200, "LinkUp Systems L7200")
/* Maintainer: Steve Hill / Scott McConnell */
- .phys_ram = 0xf0000000,
.phys_io = 0x80040000,
.io_pg_offst = ((0xd0000000) >> 18) & 0xfffc,
.map_io = l7200_map_io,
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 19f2fa2244c4..2cccc27c62e4 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -112,7 +112,6 @@ void __init lh7a40x_init_board_irq (void)
MACHINE_START (KEV7A400, "Sharp KEV7a400")
/* Maintainer: Marc Singer */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 4eb962fdb3a8..12e23277c5ea 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -317,7 +317,6 @@ lpd7a400_map_io(void)
MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
/* Maintainer: Marc Singer */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
@@ -333,7 +332,6 @@ MACHINE_END
MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
/* Maintainer: Marc Singer */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((io_p2v (0x80000000))>>18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 4b292e93fbe2..bdc20b51b076 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -109,7 +109,6 @@ static void __init omap_generic_map_io(void)
MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
/* Maintainer: Tony Lindgren <tony@atomide.com> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index a07e2c9307fa..9533c36a92df 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -199,7 +199,6 @@ static void __init h2_map_io(void)
MACHINE_START(OMAP_H2, "TI-H2")
/* Maintainer: Imre Deak <imre.deak@nokia.com> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 668e278433c2..d665efc1c344 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -215,7 +215,6 @@ static void __init h3_map_io(void)
MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
/* Maintainer: Texas Instruments, Inc. */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index 95f1ff36cdcb..652f37c7f906 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -303,7 +303,6 @@ static void __init innovator_map_io(void)
MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
/* Maintainer: MontaVista Software, Inc. */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c
index 0448fa7de8a4..58f783930d45 100644
--- a/arch/arm/mach-omap1/board-netstar.c
+++ b/arch/arm/mach-omap1/board-netstar.c
@@ -149,7 +149,6 @@ postcore_initcall(netstar_late_init);
MACHINE_START(NETSTAR, "NetStar OMAP5910")
/* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index e990e1bc1669..e5d126e8f276 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -274,7 +274,6 @@ static void __init osk_map_io(void)
MACHINE_START(OMAP_OSK, "TI-OSK")
/* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 540b20d78cca..67fada207622 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -19,6 +19,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/notifier.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
@@ -30,7 +31,6 @@
#include <asm/arch/usb.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
-#include <asm/hardware/clock.h>
static void __init omap_generic_init_irq(void)
{
@@ -76,7 +76,6 @@ static void __init omap_generic_map_io(void)
}
MACHINE_START(OMAP_PALMTE, "OMAP310 based Palm Tungsten E")
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index bd900b7ab33c..88708a0c52a2 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -184,7 +184,7 @@ static void __init omap_perseus2_map_io(void)
omap_writel(0x00000088, OMAP730_FLASH_ACFG_0);
/*
- * Ethernet support trough the debug board
+ * Ethernet support through the debug board
* CS1 timings setup
*/
omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1);
@@ -199,7 +199,6 @@ static void __init omap_perseus2_map_io(void)
MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
/* Maintainer: Kevin Hilman <kjh@hilman.org> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 6f9a6220e78a..959b4b847c87 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -281,7 +281,6 @@ EXPORT_SYMBOL(voiceblue_wdt_ping);
MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
/* Maintainer: Ladislav Michl <michl@2n.cz> */
- .phys_ram = 0x10000000,
.phys_io = 0xfff00000,
.io_pg_offst = ((0xfef00000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index 4277eee44ed5..75110ba10424 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -16,9 +16,9 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/usb.h>
#include <asm/arch/clock.h>
@@ -50,10 +50,10 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk)
{
int retval;
- retval = omap1_clk_use(&api_ck.clk);
+ retval = omap1_clk_enable(&api_ck.clk);
if (!retval) {
- retval = omap1_clk_enable(clk);
- omap1_clk_unuse(&api_ck.clk);
+ retval = omap1_clk_enable_generic(clk);
+ omap1_clk_disable(&api_ck.clk);
}
return retval;
@@ -61,9 +61,9 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk)
static void omap1_clk_disable_dsp_domain(struct clk *clk)
{
- if (omap1_clk_use(&api_ck.clk) == 0) {
- omap1_clk_disable(clk);
- omap1_clk_unuse(&api_ck.clk);
+ if (omap1_clk_enable(&api_ck.clk) == 0) {
+ omap1_clk_disable_generic(clk);
+ omap1_clk_disable(&api_ck.clk);
}
}
@@ -72,7 +72,7 @@ static int omap1_clk_enable_uart_functional(struct clk *clk)
int ret;
struct uart_clk *uclk;
- ret = omap1_clk_enable(clk);
+ ret = omap1_clk_enable_generic(clk);
if (ret == 0) {
/* Set smart idle acknowledgement mode */
uclk = (struct uart_clk *)clk;
@@ -91,7 +91,7 @@ static void omap1_clk_disable_uart_functional(struct clk *clk)
uclk = (struct uart_clk *)clk;
omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr);
- omap1_clk_disable(clk);
+ omap1_clk_disable_generic(clk);
}
static void omap1_clk_allow_idle(struct clk *clk)
@@ -230,9 +230,9 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk)
* Note that DSP_CKCTL virt addr = phys addr, so
* we must use __raw_readw() instead of omap_readw().
*/
- omap1_clk_use(&api_ck.clk);
+ omap1_clk_enable(&api_ck.clk);
dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset));
- omap1_clk_unuse(&api_ck.clk);
+ omap1_clk_disable(&api_ck.clk);
if (unlikely(clk->rate == clk->parent->rate / dsor))
return; /* No change, quick exit */
@@ -412,12 +412,12 @@ static void omap1_init_ext_clk(struct clk * clk)
clk-> rate = 96000000 / dsor;
}
-static int omap1_clk_use(struct clk *clk)
+static int omap1_clk_enable(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (likely(clk->parent)) {
- ret = omap1_clk_use(clk->parent);
+ ret = omap1_clk_enable(clk->parent);
if (unlikely(ret != 0)) {
clk->usecount--;
@@ -432,7 +432,7 @@ static int omap1_clk_use(struct clk *clk)
ret = clk->enable(clk);
if (unlikely(ret != 0) && clk->parent) {
- omap1_clk_unuse(clk->parent);
+ omap1_clk_disable(clk->parent);
clk->usecount--;
}
}
@@ -440,12 +440,12 @@ static int omap1_clk_use(struct clk *clk)
return ret;
}
-static void omap1_clk_unuse(struct clk *clk)
+static void omap1_clk_disable(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
clk->disable(clk);
if (likely(clk->parent)) {
- omap1_clk_unuse(clk->parent);
+ omap1_clk_disable(clk->parent);
if (clk->flags & CLOCK_NO_IDLE_PARENT)
if (!cpu_is_omap24xx())
omap1_clk_allow_idle(clk->parent);
@@ -453,7 +453,7 @@ static void omap1_clk_unuse(struct clk *clk)
}
}
-static int omap1_clk_enable(struct clk *clk)
+static int omap1_clk_enable_generic(struct clk *clk)
{
__u16 regval16;
__u32 regval32;
@@ -492,7 +492,7 @@ static int omap1_clk_enable(struct clk *clk)
return 0;
}
-static void omap1_clk_disable(struct clk *clk)
+static void omap1_clk_disable_generic(struct clk *clk)
{
__u16 regval16;
__u32 regval32;
@@ -654,8 +654,8 @@ late_initcall(omap1_late_clk_reset);
#endif
static struct clk_functions omap1_clk_functions = {
- .clk_use = omap1_clk_use,
- .clk_unuse = omap1_clk_unuse,
+ .clk_enable = omap1_clk_enable,
+ .clk_disable = omap1_clk_disable,
.clk_round_rate = omap1_clk_round_rate,
.clk_set_rate = omap1_clk_set_rate,
};
@@ -780,9 +780,9 @@ int __init omap1_clk_init(void)
* Only enable those clocks we will need, let the drivers
* enable other clocks as necessary
*/
- clk_use(&armper_ck.clk);
- clk_use(&armxor_ck.clk);
- clk_use(&armtim_ck.clk); /* This should be done by timer code */
+ clk_enable(&armper_ck.clk);
+ clk_enable(&armxor_ck.clk);
+ clk_enable(&armtim_ck.clk); /* This should be done by timer code */
if (cpu_is_omap1510())
clk_enable(&arm_gpio_ck);
diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h
index f3bdfb50e01a..4f18d1b94449 100644
--- a/arch/arm/mach-omap1/clock.h
+++ b/arch/arm/mach-omap1/clock.h
@@ -13,8 +13,8 @@
#ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H
#define __ARCH_ARM_MACH_OMAP1_CLOCK_H
-static int omap1_clk_enable(struct clk * clk);
-static void omap1_clk_disable(struct clk * clk);
+static int omap1_clk_enable_generic(struct clk * clk);
+static void omap1_clk_disable_generic(struct clk * clk);
static void omap1_ckctl_recalc(struct clk * clk);
static void omap1_watchdog_recalc(struct clk * clk);
static void omap1_ckctl_recalc_dsp_domain(struct clk * clk);
@@ -30,8 +30,8 @@ static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate);
static void omap1_init_ext_clk(struct clk * clk);
static int omap1_select_table_rate(struct clk * clk, unsigned long rate);
static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate);
-static int omap1_clk_use(struct clk *clk);
-static void omap1_clk_unuse(struct clk *clk);
+static int omap1_clk_enable(struct clk *clk);
+static void omap1_clk_disable(struct clk *clk);
struct mpu_rate {
unsigned long rate;
@@ -152,8 +152,8 @@ static struct clk ck_ref = {
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
ALWAYS_ENABLED,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk ck_dpll1 = {
@@ -161,8 +161,8 @@ static struct clk ck_dpll1 = {
.parent = &ck_ref,
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
RATE_PROPAGATES | ALWAYS_ENABLED,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct arm_idlect1_clk ck_dpll1out = {
@@ -173,8 +173,8 @@ static struct arm_idlect1_clk ck_dpll1out = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_CKOUT_ARM,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 12,
};
@@ -186,8 +186,8 @@ static struct clk arm_ck = {
RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED,
.rate_offset = CKCTL_ARMDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct arm_idlect1_clk armper_ck = {
@@ -200,8 +200,8 @@ static struct arm_idlect1_clk armper_ck = {
.enable_bit = EN_PERCK,
.rate_offset = CKCTL_PERDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 2,
};
@@ -213,8 +213,8 @@ static struct clk arm_gpio_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_GPIOCK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct arm_idlect1_clk armxor_ck = {
@@ -226,8 +226,8 @@ static struct arm_idlect1_clk armxor_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_XORPCK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 1,
};
@@ -241,8 +241,8 @@ static struct arm_idlect1_clk armtim_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_TIMCK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 9,
};
@@ -256,8 +256,8 @@ static struct arm_idlect1_clk armwdt_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_WDTCK,
.recalc = &omap1_watchdog_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 0,
};
@@ -272,8 +272,8 @@ static struct clk arminth_ck16xx = {
*
* 1510 version is in TC clocks.
*/
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk dsp_ck = {
@@ -285,8 +285,8 @@ static struct clk dsp_ck = {
.enable_bit = EN_DSPCK,
.rate_offset = CKCTL_DSPDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk dspmmu_ck = {
@@ -296,8 +296,8 @@ static struct clk dspmmu_ck = {
RATE_CKCTL | ALWAYS_ENABLED,
.rate_offset = CKCTL_DSPMMUDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk dspper_ck = {
@@ -349,8 +349,8 @@ static struct arm_idlect1_clk tc_ck = {
CLOCK_IDLE_CONTROL,
.rate_offset = CKCTL_TCDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 6,
};
@@ -364,8 +364,8 @@ static struct clk arminth_ck1510 = {
*
* 16xx version is in MPU clocks.
*/
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk tipb_ck = {
@@ -374,8 +374,8 @@ static struct clk tipb_ck = {
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk l3_ocpi_ck = {
@@ -386,8 +386,8 @@ static struct clk l3_ocpi_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT3,
.enable_bit = EN_OCPI_CK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk tc1_ck = {
@@ -397,8 +397,8 @@ static struct clk tc1_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT3,
.enable_bit = EN_TC1_CK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk tc2_ck = {
@@ -408,8 +408,8 @@ static struct clk tc2_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT3,
.enable_bit = EN_TC2_CK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk dma_ck = {
@@ -419,8 +419,8 @@ static struct clk dma_ck = {
.flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX |
ALWAYS_ENABLED,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk dma_lcdfree_ck = {
@@ -428,8 +428,8 @@ static struct clk dma_lcdfree_ck = {
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct arm_idlect1_clk api_ck = {
@@ -441,8 +441,8 @@ static struct arm_idlect1_clk api_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_APICK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 8,
};
@@ -455,8 +455,8 @@ static struct arm_idlect1_clk lb_ck = {
.enable_reg = (void __iomem *)ARM_IDLECT2,
.enable_bit = EN_LBCK,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 4,
};
@@ -466,8 +466,8 @@ static struct clk rhea1_ck = {
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk rhea2_ck = {
@@ -475,8 +475,8 @@ static struct clk rhea2_ck = {
.parent = &tc_ck.clk,
.flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED,
.recalc = &followparent_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk lcd_ck_16xx = {
@@ -487,8 +487,8 @@ static struct clk lcd_ck_16xx = {
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct arm_idlect1_clk lcd_ck_1510 = {
@@ -501,8 +501,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = {
.enable_bit = EN_LCDCK,
.rate_offset = CKCTL_LCDDIV_OFFSET,
.recalc = &omap1_ckctl_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
},
.idlect_shift = 3,
};
@@ -518,8 +518,8 @@ static struct clk uart1_1510 = {
.enable_bit = 29, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct uart_clk uart1_16xx = {
@@ -550,8 +550,8 @@ static struct clk uart2_ck = {
.enable_bit = 30, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk uart3_1510 = {
@@ -565,8 +565,8 @@ static struct clk uart3_1510 = {
.enable_bit = 31, /* Chooses between 12MHz and 48MHz */
.set_rate = &omap1_set_uart_rate,
.recalc = &omap1_uart_recalc,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct uart_clk uart3_16xx = {
@@ -593,8 +593,8 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)ULPD_CLOCK_CTRL,
.enable_bit = USB_MCLK_EN_BIT,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk usb_hhc_ck1510 = {
@@ -605,8 +605,8 @@ static struct clk usb_hhc_ck1510 = {
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = USB_HOST_HHC_UHOST_EN,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk usb_hhc_ck16xx = {
@@ -618,8 +618,8 @@ static struct clk usb_hhc_ck16xx = {
RATE_FIXED | ENABLE_REG_32BIT,
.enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */,
.enable_bit = 8 /* UHOST_EN */,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk usb_dc_ck = {
@@ -629,8 +629,8 @@ static struct clk usb_dc_ck = {
.flags = CLOCK_IN_OMAP16XX | RATE_FIXED,
.enable_reg = (void __iomem *)SOFT_REQ_REG,
.enable_bit = 4,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk mclk_1510 = {
@@ -638,8 +638,8 @@ static struct clk mclk_1510 = {
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk mclk_16xx = {
@@ -651,8 +651,8 @@ static struct clk mclk_16xx = {
.set_rate = &omap1_set_ext_clk_rate,
.round_rate = &omap1_round_ext_clk_rate,
.init = &omap1_init_ext_clk,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk bclk_1510 = {
@@ -660,8 +660,8 @@ static struct clk bclk_1510 = {
/* Direct from ULPD, no parent. May be enabled by ext hardware. */
.rate = 12000000,
.flags = CLOCK_IN_OMAP1510 | RATE_FIXED,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk bclk_16xx = {
@@ -673,8 +673,8 @@ static struct clk bclk_16xx = {
.set_rate = &omap1_set_ext_clk_rate,
.round_rate = &omap1_round_ext_clk_rate,
.init = &omap1_init_ext_clk,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk mmc1_ck = {
@@ -686,8 +686,8 @@ static struct clk mmc1_ck = {
RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 23,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk mmc2_ck = {
@@ -699,8 +699,8 @@ static struct clk mmc2_ck = {
RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT,
.enable_reg = (void __iomem *)MOD_CONF_CTRL_0,
.enable_bit = 20,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk virtual_ck_mpu = {
@@ -711,8 +711,8 @@ static struct clk virtual_ck_mpu = {
.recalc = &followparent_recalc,
.set_rate = &omap1_select_table_rate,
.round_rate = &omap1_round_to_table_rate,
- .enable = &omap1_clk_enable,
- .disable = &omap1_clk_disable,
+ .enable = &omap1_clk_enable_generic,
+ .disable = &omap1_clk_disable_generic,
};
static struct clk * onchip_clks[] = {
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 6810cfb84462..e924e0c6a4ce 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -17,10 +17,10 @@
#include <linux/tty.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/mach-types.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/board.h>
#include <asm/arch/mux.h>
@@ -146,7 +146,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart1_ck))
printk("Could not get uart1_ck\n");
else {
- clk_use(uart1_ck);
+ clk_enable(uart1_ck);
if (cpu_is_omap1510())
clk_set_rate(uart1_ck, 12000000);
}
@@ -166,7 +166,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart2_ck))
printk("Could not get uart2_ck\n");
else {
- clk_use(uart2_ck);
+ clk_enable(uart2_ck);
if (cpu_is_omap1510())
clk_set_rate(uart2_ck, 12000000);
else
@@ -188,7 +188,7 @@ void __init omap_serial_init(void)
if (IS_ERR(uart3_ck))
printk("Could not get uart3_ck\n");
else {
- clk_use(uart3_ck);
+ clk_enable(uart3_ck);
if (cpu_is_omap1510())
clk_set_rate(uart3_ck, 12000000);
}
@@ -252,9 +252,8 @@ static void __init omap_serial_set_port_wakeup(int 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);
+ SA_TRIGGER_RISING, "serial wakeup", NULL);
if (ret) {
omap_free_gpio(gpio_nr);
printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n",
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index c602e7a3d93e..b937123e5c65 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -69,7 +69,6 @@ static void __init omap_generic_map_io(void)
MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .phys_ram = 0x80000000,
.phys_io = 0x48000000,
.io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index f2554469a76a..c3c35d40378a 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -186,7 +186,6 @@ static void __init omap_h4_map_io(void)
MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
- .phys_ram = 0x80000000,
.phys_io = 0x48000000,
.io_pg_offst = ((0xd8000000) >> 18) & 0xfffc,
.boot_params = 0x80000100,
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 85818d9f2635..180f675c9064 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -22,10 +22,10 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
#include <asm/arch/prcm.h>
@@ -111,7 +111,7 @@ static void omap2_clk_fixed_enable(struct clk *clk)
/* Enables clock without considering parent dependencies or use count
* REVISIT: Maybe change this to use clk->enable like on omap1?
*/
-static int omap2_clk_enable(struct clk * clk)
+static int _omap2_clk_enable(struct clk * clk)
{
u32 regval32;
@@ -150,7 +150,7 @@ static void omap2_clk_fixed_disable(struct clk *clk)
}
/* Disables clock without considering parent dependencies or use count */
-static void omap2_clk_disable(struct clk *clk)
+static void _omap2_clk_disable(struct clk *clk)
{
u32 regval32;
@@ -167,23 +167,23 @@ static void omap2_clk_disable(struct clk *clk)
__raw_writel(regval32, clk->enable_reg);
}
-static int omap2_clk_use(struct clk *clk)
+static int omap2_clk_enable(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (likely((u32)clk->parent))
- ret = omap2_clk_use(clk->parent);
+ ret = omap2_clk_enable(clk->parent);
if (unlikely(ret != 0)) {
clk->usecount--;
return ret;
}
- ret = omap2_clk_enable(clk);
+ ret = _omap2_clk_enable(clk);
if (unlikely(ret != 0) && clk->parent) {
- omap2_clk_unuse(clk->parent);
+ omap2_clk_disable(clk->parent);
clk->usecount--;
}
}
@@ -191,12 +191,12 @@ static int omap2_clk_use(struct clk *clk)
return ret;
}
-static void omap2_clk_unuse(struct clk *clk)
+static void omap2_clk_disable(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
- omap2_clk_disable(clk);
+ _omap2_clk_disable(clk);
if (likely((u32)clk->parent))
- omap2_clk_unuse(clk->parent);
+ omap2_clk_disable(clk->parent);
}
}
@@ -873,7 +873,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
reg = (void __iomem *)src_sel;
if (clk->usecount > 0)
- omap2_clk_disable(clk);
+ _omap2_clk_disable(clk);
/* Set new source value (previous dividers if any in effect) */
reg_val = __raw_readl(reg) & ~(field_mask << src_off);
@@ -884,7 +884,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
__raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL);
if (clk->usecount > 0)
- omap2_clk_enable(clk);
+ _omap2_clk_enable(clk);
clk->parent = new_parent;
@@ -999,8 +999,6 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
static struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
- .clk_use = omap2_clk_use,
- .clk_unuse = omap2_clk_unuse,
.clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
@@ -1045,7 +1043,7 @@ static void __init omap2_disable_unused_clocks(void)
continue;
printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name);
- omap2_clk_disable(ck);
+ _omap2_clk_disable(ck);
}
}
late_initcall(omap2_disable_unused_clocks);
@@ -1120,10 +1118,10 @@ int __init omap2_clk_init(void)
* Only enable those clocks we will need, let the drivers
* enable other clocks as necessary
*/
- clk_use(&sync_32k_ick);
- clk_use(&omapctrl_ick);
+ clk_enable(&sync_32k_ick);
+ clk_enable(&omapctrl_ick);
if (cpu_is_omap2430())
- clk_use(&sdrc_ick);
+ clk_enable(&sdrc_ick);
return 0;
}
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 4aeab5591bd3..6cab20b1d3c1 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -24,7 +24,7 @@ static void omap2_propagate_rate(struct clk * clk);
static void omap2_mpu_recalc(struct clk * clk);
static int omap2_select_table_rate(struct clk * clk, unsigned long rate);
static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate);
-static void omap2_clk_unuse(struct clk *clk);
+static void omap2_clk_disable(struct clk *clk);
static void omap2_sys_clk_recalc(struct clk * clk);
static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val);
static u32 omap2_clksel_get_divisor(struct clk *clk);
@@ -859,7 +859,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */
static struct clk usb_l4_ick = { /* FS-USB interface clock */
.name = "usb_l4_ick",
- .parent = &core_ck,
+ .parent = &core_l3_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP |
CONFIG_PARTICIPANT,
@@ -1045,7 +1045,7 @@ static struct clk gpt1_ick = {
.name = "gpt1_ick",
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
- .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit4 */
+ .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit0 */
.enable_bit = 0,
.recalc = &omap2_followparent_recalc,
};
@@ -1055,7 +1055,7 @@ static struct clk gpt1_fck = {
.parent = &func_32k_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
CM_WKUP_SEL1,
- .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP,
+ .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, /* Bit0 */
.enable_bit = 0,
.src_offset = 0,
.recalc = &omap2_followparent_recalc,
@@ -1065,7 +1065,7 @@ static struct clk gpt2_ick = {
.name = "gpt2_ick",
.parent = &l4_ck,
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
- .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit4 */
+ .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */
.enable_bit = 0,
.recalc = &omap2_followparent_recalc,
};
@@ -1839,7 +1839,7 @@ static struct clk usb_fck = {
static struct clk usbhs_ick = {
.name = "usbhs_ick",
- .parent = &l4_ck,
+ .parent = &core_l3_ck,
.flags = CLOCK_IN_OMAP243X,
.enable_reg = (void __iomem *)&CM_ICLKEN2_CORE,
.enable_bit = 6,
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index f4df04fe1dd8..24dd374224af 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -16,9 +16,9 @@
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
+#include <linux/clk.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/common.h>
#include <asm/arch/board.h>
@@ -119,14 +119,14 @@ void __init omap_serial_init()
if (IS_ERR(uart1_ick))
printk("Could not get uart1_ick\n");
else {
- clk_use(uart1_ick);
+ clk_enable(uart1_ick);
}
uart1_fck = clk_get(NULL, "uart1_fck");
if (IS_ERR(uart1_fck))
printk("Could not get uart1_fck\n");
else {
- clk_use(uart1_fck);
+ clk_enable(uart1_fck);
}
break;
case 1:
@@ -134,14 +134,14 @@ void __init omap_serial_init()
if (IS_ERR(uart2_ick))
printk("Could not get uart2_ick\n");
else {
- clk_use(uart2_ick);
+ clk_enable(uart2_ick);
}
uart2_fck = clk_get(NULL, "uart2_fck");
if (IS_ERR(uart2_fck))
printk("Could not get uart2_fck\n");
else {
- clk_use(uart2_fck);
+ clk_enable(uart2_fck);
}
break;
case 2:
@@ -149,14 +149,14 @@ void __init omap_serial_init()
if (IS_ERR(uart3_ick))
printk("Could not get uart3_ick\n");
else {
- clk_use(uart3_ick);
+ clk_enable(uart3_ick);
}
uart3_fck = clk_get(NULL, "uart3_fck");
if (IS_ERR(uart3_fck))
printk("Could not get uart3_fck\n");
else {
- clk_use(uart3_fck);
+ clk_enable(uart3_fck);
}
break;
}
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 9ec11443200f..1d2f5ac2f69b 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -21,10 +21,11 @@
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/clk.h>
+
#include <asm/mach/time.h>
#include <asm/delay.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#define OMAP2_GP_TIMER1_BASE 0x48028000
#define OMAP2_GP_TIMER2_BASE 0x4802a000
@@ -103,7 +104,7 @@ static void __init omap2_gp_timer_init(void)
if (IS_ERR(sys_ck))
printk(KERN_ERR "Could not get sys_ck\n");
else {
- clk_use(sys_ck);
+ clk_enable(sys_ck);
tick_period = clk_get_rate(sys_ck) / 100;
clk_put(sys_ck);
}
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 2a58499c0968..c1d77f5b3823 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -112,12 +112,14 @@ config IWMMXT
config PXA_SHARP_C7xx
bool
select PXA_SSP
+ select SHARPSL_PM
help
Enable support for all Sharp C7xx models
config PXA_SHARP_Cxx00
bool
select PXA_SSP
+ select SHARPSL_PM
help
Enable common support for Sharp Cxx00 models
diff --git a/arch/arm/mach-pxa/akita-ioexp.c b/arch/arm/mach-pxa/akita-ioexp.c
index f6d73cc01f78..1b398742ab56 100644
--- a/arch/arm/mach-pxa/akita-ioexp.c
+++ b/arch/arm/mach-pxa/akita-ioexp.c
@@ -124,17 +124,16 @@ static int max7310_detach_client(struct i2c_client *client)
}
static struct i2c_driver max7310_i2c_driver = {
- .owner = THIS_MODULE,
- .name = "akita-max7310",
+ .driver = {
+ .name = "akita-max7310",
+ },
.id = I2C_DRIVERID_AKITAIOEXP,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = max7310_attach_adapter,
.detach_client = max7310_detach_client,
};
static struct i2c_client max7310_template = {
name: "akita-max7310",
- flags: I2C_CLIENT_ALLOW_USE,
driver: &max7310_i2c_driver,
};
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 100fb31b5156..7ffd2de8f2f3 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -213,15 +213,14 @@ static int corgi_mci_init(struct device *dev, irqreturn_t (*corgi_detect_int)(in
corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250);
- err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, SA_INTERRUPT,
- "MMC card detect", data);
+ err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "MMC card detect", data);
if (err) {
printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
return -1;
}
- set_irq_type(CORGI_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
-
return 0;
}
@@ -343,7 +342,6 @@ static void __init fixup_corgi(struct machine_desc *desc,
#ifdef CONFIG_MACH_CORGI
MACHINE_START(CORGI, "SHARP Corgi")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
@@ -356,7 +354,6 @@ MACHINE_END
#ifdef CONFIG_MACH_SHEPHERD
MACHINE_START(SHEPHERD, "SHARP Shepherd")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
@@ -369,7 +366,6 @@ MACHINE_END
#ifdef CONFIG_MACH_HUSKY
MACHINE_START(HUSKY, "SHARP Husky")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 599be14754f9..7a1ab73e9e10 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -33,19 +33,7 @@ static void corgi_charger_init(void)
pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN);
-}
-
-static void corgi_charge_led(int val)
-{
- if (val == SHARPSL_LED_ERROR) {
- dev_dbg(sharpsl_pm.dev, "Charge LED Error\n");
- } else if (val == SHARPSL_LED_ON) {
- dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
- GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
- } else {
- dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
- GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
- }
+ sharpsl_pm_pxa_init();
}
static void corgi_measure_temp(int on)
@@ -138,15 +126,15 @@ static int corgi_should_wakeup(unsigned int resume_on_alarm)
dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR);
if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) {
- if (STATUS_AC_IN()) {
+ if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
/* charge on */
dev_dbg(sharpsl_pm.dev, "ac insert\n");
sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
} else {
/* charge off */
dev_dbg(sharpsl_pm.dev, "ac remove\n");
- CHARGE_LED_OFF();
- CHARGE_OFF();
+ sharpsl_pm_led(SHARPSL_LED_OFF);
+ sharpsl_pm.machinfo->charge(0);
sharpsl_pm.charge_mode = CHRG_OFF;
}
}
@@ -172,23 +160,39 @@ static unsigned long corgi_charger_wakeup(void)
return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) );
}
-static int corgi_acin_status(void)
+unsigned long corgipm_read_devdata(int type)
{
- return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0);
+ switch(type) {
+ case SHARPSL_STATUS_ACIN:
+ return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0);
+ case SHARPSL_STATUS_LOCK:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock);
+ case SHARPSL_STATUS_CHRGFULL:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull);
+ case SHARPSL_STATUS_FATAL:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal);
+ case SHARPSL_ACIN_VOLT:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_ACIN_VOLT);
+ case SHARPSL_BATT_TEMP:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_TEMP);
+ case SHARPSL_BATT_VOLT:
+ default:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_VOLT);
+ }
}
static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
.init = corgi_charger_init,
+ .exit = sharpsl_pm_pxa_remove,
.gpio_batlock = CORGI_GPIO_BAT_COVER,
.gpio_acin = CORGI_GPIO_AC_IN,
.gpio_batfull = CORGI_GPIO_CHRG_FULL,
- .status_acin = corgi_acin_status,
.discharge = corgi_discharge,
.charge = corgi_charge,
- .chargeled = corgi_charge_led,
.measure_temp = corgi_measure_temp,
.presuspend = corgi_presuspend,
.postsuspend = corgi_postsuspend,
+ .read_devdata = corgipm_read_devdata,
.charger_wakeup = corgi_charger_wakeup,
.should_wakeup = corgi_should_wakeup,
.bat_levels = 40,
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 7de159e2ab42..347b9dea24c6 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -183,7 +183,6 @@ static void __init idp_map_io(void)
MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
/* Maintainer: Vibren Technologies */
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = idp_map_io,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index b464bc88ff93..3e26d7ce5bb2 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -437,7 +437,6 @@ static void __init lubbock_map_io(void)
MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
/* Maintainer: MontaVista Software Inc. */
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = lubbock_map_io,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 07892f4012d8..d5bda60209ec 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -43,6 +43,7 @@
#include <asm/arch/pxafb.h>
#include <asm/arch/mmc.h>
#include <asm/arch/irda.h>
+#include <asm/arch/ohci.h>
#include "generic.h"
@@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = {
&mst_flash_device[1],
};
+static int mainstone_ohci_init(struct device *dev)
+{
+ /* setup Port1 GPIO pin. */
+ pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
+ pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
+
+ /* Set the Power Control Polarity Low and Power Sense
+ Polarity Low to active low. */
+ UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
+ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ return 0;
+}
+
+static struct pxaohci_platform_data mainstone_ohci_platform_data = {
+ .port_mode = PMM_PERPORT_MODE,
+ .init = mainstone_ohci_init,
+};
+
static void __init mainstone_init(void)
{
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
@@ -407,6 +427,12 @@ static void __init mainstone_init(void)
printk(KERN_NOTICE "Mainstone configured to boot from %s\n",
mst_flash_data[0].name);
+ /* system bus arbiter setting
+ * - Core_Park
+ * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4
+ */
+ ARB_CNTRL = ARB_CORE_PARK | 0x234;
+
/*
* On Mainstone, we route AC97_SYSCLK via GPIO45 to
* the audio daughter card
@@ -424,6 +450,7 @@ static void __init mainstone_init(void)
pxa_set_mci_info(&mainstone_mci_platform_data);
pxa_set_ficp_info(&mainstone_ficp_platform_data);
+ pxa_set_ohci_info(&mainstone_ohci_platform_data);
}
@@ -462,7 +489,6 @@ static void __init mainstone_map_io(void)
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
/* Maintainer: MontaVista Software Inc. */
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.map_io = mainstone_map_io,
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index eef3de26ad37..911e6ff5a9bd 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -146,15 +146,14 @@ static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(
poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
- err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT,
- "MMC card detect", data);
+ err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "MMC card detect", data);
if (err) {
printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
return -1;
}
- set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE);
-
return 0;
}
@@ -312,7 +311,6 @@ static void __init fixup_poodle(struct machine_desc *desc,
}
MACHINE_START(POODLE, "SHARP Poodle")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_poodle,
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index c722a9a91fcc..b41b1efaa2cf 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -21,6 +21,7 @@
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/ohci.h>
#include "generic.h"
@@ -194,6 +195,11 @@ static struct platform_device ohci_device = {
.resource = pxa27x_ohci_resources,
};
+void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
+{
+ ohci_device.dev.platform_data = info;
+}
+
static struct platform_device *devices[] __initdata = {
&ohci_device,
};
diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
index b0c40a1d6671..da4769caaf72 100644
--- a/arch/arm/mach-pxa/sharpsl.h
+++ b/arch/arm/mach-pxa/sharpsl.h
@@ -1,7 +1,17 @@
/*
- * SharpSL SSP Driver
+ * 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
+ * published by the Free Software Foundation.
+ *
*/
+#include <asm/hardware/sharpsl_pm.h>
+
+/*
+ * SharpSL SSP Driver
+ */
struct corgissp_machinfo {
int port;
int cs_lcdcon;
@@ -14,18 +24,18 @@ struct corgissp_machinfo {
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);
@@ -33,89 +43,22 @@ void spitz_put_hsync(void);
void corgi_wait_hsync(void);
void spitz_wait_hsync(void);
+
/*
* SharpSL Battery/PM Driver
*/
-struct sharpsl_charger_machinfo {
- void (*init)(void);
- int gpio_acin;
- int gpio_batfull;
- int gpio_batlock;
- int gpio_fatal;
- int (*status_acin)(void);
- void (*discharge)(int);
- void (*discharge1)(int);
- void (*charge)(int);
- void (*chargeled)(int);
- void (*measure_temp)(int);
- void (*presuspend)(void);
- void (*postsuspend)(void);
- unsigned long (*charger_wakeup)(void);
- int (*should_wakeup)(unsigned int resume_on_alarm);
- int bat_levels;
- struct battery_thresh *bat_levels_noac;
- struct battery_thresh *bat_levels_acin;
- int status_high_acin;
- int status_low_acin;
- int status_high_noac;
- int status_low_noac;
-};
-
-struct battery_thresh {
- int voltage;
- int percentage;
-};
-
-struct battery_stat {
- int ac_status; /* APM AC Present/Not Present */
- int mainbat_status; /* APM Main Battery Status */
- int mainbat_percent; /* Main Battery Percentage Charge */
- int mainbat_voltage; /* Main Battery Voltage */
-};
-
-struct sharpsl_pm_status {
- struct device *dev;
- struct timer_list ac_timer;
- struct timer_list chrg_full_timer;
-
- int charge_mode;
-#define CHRG_ERROR (-1)
-#define CHRG_OFF (0)
-#define CHRG_ON (1)
-#define CHRG_DONE (2)
-
- unsigned int flags;
-#define SHARPSL_SUSPENDED (1 << 0) /* Device is Suspended */
-#define SHARPSL_ALARM_ACTIVE (1 << 1) /* Alarm is for charging event (not user) */
-#define SHARPSL_BL_LIMIT (1 << 2) /* Backlight Intensity Limited */
-#define SHARPSL_APM_QUEUED (1 << 3) /* APM Event Queued */
-#define SHARPSL_DO_OFFLINE_CHRG (1 << 4) /* Trigger the offline charger */
+#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x))
- int full_count;
- unsigned long charge_start_time;
- struct sharpsl_charger_machinfo *machinfo;
- struct battery_stat battstat;
-};
+/* MAX1111 Channel Definitions */
+#define MAX1111_BATT_VOLT 4u
+#define MAX1111_BATT_TEMP 2u
+#define MAX1111_ACIN_VOLT 6u
-extern struct sharpsl_pm_status sharpsl_pm;
extern struct battery_thresh spitz_battery_levels_acin[];
extern struct battery_thresh spitz_battery_levels_noac[];
+void sharpsl_pm_pxa_init(void);
+void sharpsl_pm_pxa_remove(void);
+int sharpsl_pm_pxa_read_max1111(int channel);
-#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x))
-
-#define SHARPSL_LED_ERROR 2
-#define SHARPSL_LED_ON 1
-#define SHARPSL_LED_OFF 0
-#define CHARGE_ON() sharpsl_pm.machinfo->charge(1)
-#define CHARGE_OFF() sharpsl_pm.machinfo->charge(0)
-#define CHARGE_LED_ON() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ON)
-#define CHARGE_LED_OFF() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_OFF)
-#define CHARGE_LED_ERR() sharpsl_pm.machinfo->chargeled(SHARPSL_LED_ERROR)
-#define DISCHARGE_ON() sharpsl_pm.machinfo->discharge(1)
-#define DISCHARGE_OFF() sharpsl_pm.machinfo->discharge(0)
-#define STATUS_AC_IN() sharpsl_pm.machinfo->status_acin()
-#define STATUS_BATT_LOCKED() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock)
-#define STATUS_CHRG_FULL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull)
-#define STATUS_FATAL() READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal)
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index c10be00fb526..6d402b262d8a 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -15,48 +15,20 @@
#undef DEBUG
#include <linux/module.h>
-#include <linux/timer.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/apm_bios.h>
-#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
-#include <asm/hardware/scoop.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/apm.h>
-
#include <asm/arch/pm.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/sharpsl.h>
#include "sharpsl.h"
-/*
- * Constants
- */
-#define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */
-#define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */
-#define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */
-#define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */
-#define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */
-#define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */
-#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */
-#define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */
-#define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */
-#define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */
-
-#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */
-#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */
-#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */
-#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */
-#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */
-#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */
-
struct battery_thresh spitz_battery_levels_acin[] = {
{ 213, 100},
{ 212, 98},
@@ -151,763 +123,17 @@ struct battery_thresh spitz_battery_levels_noac[] = {
#define MAXCTRL_SEL_SH 4
#define MAXCTRL_STR 1u << 7
-/* MAX1111 Channel Definitions */
-#define BATT_AD 4u
-#define BATT_THM 2u
-#define JK_VAD 6u
-
-
-/*
- * Prototypes
- */
-static int sharpsl_read_main_battery(void);
-static int sharpsl_off_charge_battery(void);
-static int sharpsl_check_battery_temp(void);
-static int sharpsl_check_battery_voltage(void);
-static int sharpsl_ac_check(void);
-static int sharpsl_fatal_check(void);
-static int sharpsl_average_value(int ad);
-static void sharpsl_average_clear(void);
-static void sharpsl_charge_toggle(void *private_);
-static void sharpsl_battery_thread(void *private_);
-
-
-/*
- * Variables
- */
-struct sharpsl_pm_status sharpsl_pm;
-DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL);
-DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL);
-
-
-static int get_percentage(int voltage)
-{
- int i = sharpsl_pm.machinfo->bat_levels - 1;
- struct battery_thresh *thresh;
-
- if (sharpsl_pm.charge_mode == CHRG_ON)
- thresh=sharpsl_pm.machinfo->bat_levels_acin;
- else
- thresh=sharpsl_pm.machinfo->bat_levels_noac;
-
- while (i > 0 && (voltage > thresh[i].voltage))
- i--;
-
- return thresh[i].percentage;
-}
-
-static int get_apm_status(int voltage)
-{
- int low_thresh, high_thresh;
-
- if (sharpsl_pm.charge_mode == CHRG_ON) {
- high_thresh = sharpsl_pm.machinfo->status_high_acin;
- low_thresh = sharpsl_pm.machinfo->status_low_acin;
- } else {
- high_thresh = sharpsl_pm.machinfo->status_high_noac;
- low_thresh = sharpsl_pm.machinfo->status_low_noac;
- }
-
- if (voltage >= high_thresh)
- return APM_BATTERY_STATUS_HIGH;
- if (voltage >= low_thresh)
- return APM_BATTERY_STATUS_LOW;
- return APM_BATTERY_STATUS_CRITICAL;
-}
-
-void sharpsl_battery_kick(void)
-{
- schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
-}
-EXPORT_SYMBOL(sharpsl_battery_kick);
-
-
-static void sharpsl_battery_thread(void *private_)
-{
- int voltage, percent, apm_status, i = 0;
-
- if (!sharpsl_pm.machinfo)
- return;
-
- sharpsl_pm.battstat.ac_status = (STATUS_AC_IN() ? APM_AC_ONLINE : APM_AC_OFFLINE);
-
- /* Corgi cannot confirm when battery fully charged so periodically kick! */
- if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON)
- && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL))
- schedule_work(&toggle_charger);
-
- while(1) {
- voltage = sharpsl_read_main_battery();
- if (voltage > 0) break;
- if (i++ > 5) {
- voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage;
- dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n");
- break;
- }
- }
-
- voltage = sharpsl_average_value(voltage);
- apm_status = get_apm_status(voltage);
- percent = get_percentage(voltage);
-
- /* At low battery voltages, the voltage has a tendency to start
- creeping back up so we try to avoid this here */
- if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) || percent <= sharpsl_pm.battstat.mainbat_percent) {
- sharpsl_pm.battstat.mainbat_voltage = voltage;
- sharpsl_pm.battstat.mainbat_status = apm_status;
- sharpsl_pm.battstat.mainbat_percent = percent;
- }
-
- dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %d\n", voltage,
- sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies);
-
- /* If battery is low. limit backlight intensity to save power. */
- if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
- && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
- (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
- if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
- corgibl_limit_intensity(1);
- sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
- }
- } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
- corgibl_limit_intensity(0);
- sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
- }
-
- /* Suspend if critical battery level */
- if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE)
- && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL)
- && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) {
- sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
- dev_err(sharpsl_pm.dev, "Fatal Off\n");
- apm_queue_event(APM_CRITICAL_SUSPEND);
- }
-
- schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME);
-}
-
-static void sharpsl_charge_on(void)
-{
- dev_dbg(sharpsl_pm.dev, "Turning Charger On\n");
-
- sharpsl_pm.full_count = 0;
- sharpsl_pm.charge_mode = CHRG_ON;
- schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250));
- schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500));
-}
-
-static void sharpsl_charge_off(void)
-{
- dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n");
-
- CHARGE_OFF();
- CHARGE_LED_OFF();
- sharpsl_pm.charge_mode = CHRG_OFF;
-
- schedule_work(&sharpsl_bat);
-}
-
-static void sharpsl_charge_error(void)
-{
- CHARGE_LED_ERR();
- CHARGE_OFF();
- sharpsl_pm.charge_mode = CHRG_ERROR;
-}
-
-static void sharpsl_charge_toggle(void *private_)
-{
- dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies);
-
- if (STATUS_AC_IN() == 0) {
- sharpsl_charge_off();
- return;
- } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) {
- sharpsl_charge_error();
- return;
- }
-
- CHARGE_LED_ON();
- CHARGE_OFF();
- mdelay(SHARPSL_CHARGE_WAIT_TIME);
- CHARGE_ON();
-
- sharpsl_pm.charge_start_time = jiffies;
-}
-
-static void sharpsl_ac_timer(unsigned long data)
-{
- int acin = STATUS_AC_IN();
-
- dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin);
-
- sharpsl_average_clear();
- if (acin && (sharpsl_pm.charge_mode != CHRG_ON))
- sharpsl_charge_on();
- else if (sharpsl_pm.charge_mode == CHRG_ON)
- sharpsl_charge_off();
-
- schedule_work(&sharpsl_bat);
-}
-
-
-static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp)
-{
- /* Delay the event slightly to debounce */
- /* Must be a smaller delay than the chrg_full_isr below */
- mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
- return IRQ_HANDLED;
-}
-
-static void sharpsl_chrg_full_timer(unsigned long data)
-{
- dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies);
-
- sharpsl_pm.full_count++;
-
- if (STATUS_AC_IN() == 0) {
- dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n");
- if (sharpsl_pm.charge_mode == CHRG_ON)
- sharpsl_charge_off();
- } else if (sharpsl_pm.full_count < 2) {
- dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n");
- schedule_work(&toggle_charger);
- } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) {
- dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n");
- schedule_work(&toggle_charger);
- } else {
- sharpsl_charge_off();
- sharpsl_pm.charge_mode = CHRG_DONE;
- dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n");
- }
-}
-
-/* Charging Finished Interrupt (Not present on Corgi) */
-/* Can trigger at the same time as an AC staus change so
- delay until after that has been processed */
-static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp)
-{
- if (sharpsl_pm.flags & SHARPSL_SUSPENDED)
- return IRQ_HANDLED;
-
- /* delay until after any ac interrupt */
- mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500));
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp)
-{
- int is_fatal = 0;
-
- if (STATUS_BATT_LOCKED() == 0) {
- dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n");
- is_fatal = 1;
- }
-
- if (sharpsl_pm.machinfo->gpio_fatal && (STATUS_FATAL() == 0)) {
- dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n");
- is_fatal = 1;
- }
-
- if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) {
- sharpsl_pm.flags |= SHARPSL_APM_QUEUED;
- apm_queue_event(APM_CRITICAL_SUSPEND);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * Maintain an average of the last 10 readings
- */
-#define SHARPSL_CNV_VALUE_NUM 10
-static int sharpsl_ad_index;
-
-static void sharpsl_average_clear(void)
-{
- sharpsl_ad_index = 0;
-}
-
-static int sharpsl_average_value(int ad)
-{
- int i, ad_val = 0;
- static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1];
-
- if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) {
- sharpsl_ad_index = 0;
- return ad;
- }
-
- sharpsl_ad[sharpsl_ad_index] = ad;
- sharpsl_ad_index++;
- if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) {
- for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++)
- sharpsl_ad[i] = sharpsl_ad[i+1];
- sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1;
- }
- for (i=0; i < sharpsl_ad_index; i++)
- ad_val += sharpsl_ad[i];
-
- return (ad_val / sharpsl_ad_index);
-}
-
-
/*
* Read MAX1111 ADC
*/
-static int read_max1111(int channel)
+int sharpsl_pm_pxa_read_max1111(int channel)
{
return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
| MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
}
-static int sharpsl_read_main_battery(void)
-{
- return read_max1111(BATT_AD);
-}
-
-static int sharpsl_read_temp(void)
+void sharpsl_pm_pxa_init(void)
{
- int temp;
-
- sharpsl_pm.machinfo->measure_temp(1);
-
- mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
- temp = read_max1111(BATT_THM);
-
- sharpsl_pm.machinfo->measure_temp(0);
-
- return temp;
-}
-
-static int sharpsl_read_acin(void)
-{
- return read_max1111(JK_VAD);
-}
-
-/*
- * Take an array of 5 integers, remove the maximum and minimum values
- * and return the average.
- */
-static int get_select_val(int *val)
-{
- int i, j, k, temp, sum = 0;
-
- /* Find MAX val */
- temp = val[0];
- j=0;
- for (i=1; i<5; i++) {
- if (temp < val[i]) {
- temp = val[i];
- j = i;
- }
- }
-
- /* Find MIN val */
- temp = val[4];
- k=4;
- for (i=3; i>=0; i--) {
- if (temp > val[i]) {
- temp = val[i];
- k = i;
- }
- }
-
- for (i=0; i<5; i++)
- if (i != j && i != k )
- sum += val[i];
-
- dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]);
-
- return (sum/3);
-}
-
-static int sharpsl_check_battery_temp(void)
-{
- int val, i, buff[5];
-
- /* Check battery temperature */
- for (i=0; i<5; i++) {
- mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP);
- buff[i] = sharpsl_read_temp();
- }
-
- val = get_select_val(buff);
-
- dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
- if (val > SHARPSL_CHARGE_ON_TEMP)
- return -1;
-
- return 0;
-}
-
-static int sharpsl_check_battery_voltage(void)
-{
- int val, i, buff[5];
-
- /* disable charge, enable discharge */
- CHARGE_OFF();
- DISCHARGE_ON();
- mdelay(SHARPSL_WAIT_DISCHARGE_ON);
-
- if (sharpsl_pm.machinfo->discharge1)
- sharpsl_pm.machinfo->discharge1(1);
-
- /* Check battery voltage */
- for (i=0; i<5; i++) {
- buff[i] = sharpsl_read_main_battery();
- mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
- }
-
- if (sharpsl_pm.machinfo->discharge1)
- sharpsl_pm.machinfo->discharge1(0);
-
- DISCHARGE_OFF();
-
- val = get_select_val(buff);
- dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
-
- if (val < SHARPSL_CHARGE_ON_VOLT)
- return -1;
-
- return 0;
-}
-
-static int sharpsl_ac_check(void)
-{
- int temp, i, buff[5];
-
- for (i=0; i<5; i++) {
- buff[i] = sharpsl_read_acin();
- mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN);
- }
-
- temp = get_select_val(buff);
- dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
-
- if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) {
- dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
- return -1;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
-{
- sharpsl_pm.flags |= SHARPSL_SUSPENDED;
- flush_scheduled_work();
-
- if (sharpsl_pm.charge_mode == CHRG_ON)
- sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
- else
- sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
-
- return 0;
-}
-
-static int sharpsl_pm_resume(struct platform_device *pdev)
-{
- /* Clear the reset source indicators as they break the bootloader upon reboot */
- RCSR = 0x0f;
- sharpsl_average_clear();
- sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED;
- sharpsl_pm.flags &= ~SHARPSL_SUSPENDED;
-
- return 0;
-}
-
-static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
- dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR);
-
- dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG);
- /* not charging and AC-IN! */
-
- if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (STATUS_AC_IN() != 0)) {
- dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n");
- sharpsl_pm.charge_mode = CHRG_OFF;
- sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG;
- sharpsl_off_charge_battery();
- }
-
- sharpsl_pm.machinfo->presuspend();
-
- PEDR = 0xffffffff; /* clear it */
-
- sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE;
- if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) {
- RTSR &= RTSR_ALE;
- RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND;
- dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR);
- sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE;
- } else if (alarm_enable) {
- RTSR &= RTSR_ALE;
- RTAR = alarm_time;
- dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR);
- } else {
- dev_dbg(sharpsl_pm.dev, "No alarms set.\n");
- }
-
- pxa_pm_enter(state);
-
- sharpsl_pm.machinfo->postsuspend();
-
- dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR);
-}
-
-static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state)
-{
- if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) )
- {
- if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) {
- dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n");
- corgi_goto_sleep(alarm_time, alarm_enable, state);
- return 1;
- }
- if(sharpsl_off_charge_battery()) {
- dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n");
- corgi_goto_sleep(alarm_time, alarm_enable, state);
- return 1;
- }
- dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n");
- }
-
- if ((STATUS_BATT_LOCKED() == 0) || (sharpsl_fatal_check() < 0) )
- {
- dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n");
- corgi_goto_sleep(alarm_time, alarm_enable, state);
- return 1;
- }
-
- return 0;
-}
-
-static int corgi_pxa_pm_enter(suspend_state_t state)
-{
- unsigned long alarm_time = RTAR;
- unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0);
-
- dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n");
-
- corgi_goto_sleep(alarm_time, alarm_status, state);
-
- while (corgi_enter_suspend(alarm_time,alarm_status,state))
- {}
-
- dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n");
-
- return 0;
-}
-#endif
-
-
-/*
- * Check for fatal battery errors
- * Fatal returns -1
- */
-static int sharpsl_fatal_check(void)
-{
- int buff[5], temp, i, acin;
-
- dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n");
-
- /* Check AC-Adapter */
- acin = STATUS_AC_IN();
-
- if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
- CHARGE_OFF();
- udelay(100);
- DISCHARGE_ON(); /* enable discharge */
- mdelay(SHARPSL_WAIT_DISCHARGE_ON);
- }
-
- if (sharpsl_pm.machinfo->discharge1)
- sharpsl_pm.machinfo->discharge1(1);
-
- /* Check battery : check inserting battery ? */
- for (i=0; i<5; i++) {
- buff[i] = sharpsl_read_main_battery();
- mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT);
- }
-
- if (sharpsl_pm.machinfo->discharge1)
- sharpsl_pm.machinfo->discharge1(0);
-
- if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) {
- udelay(100);
- CHARGE_ON();
- DISCHARGE_OFF();
- }
-
- temp = get_select_val(buff);
- dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_read_main_battery());
-
- if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) ||
- (!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT)))
- return -1;
- return 0;
-}
-
-static int sharpsl_off_charge_error(void)
-{
- dev_err(sharpsl_pm.dev, "Offline Charger: Error occured.\n");
- CHARGE_OFF();
- CHARGE_LED_ERR();
- sharpsl_pm.charge_mode = CHRG_ERROR;
- return 1;
-}
-
-/*
- * Charging Control while suspended
- * Return 1 - go straight to sleep
- * Return 0 - sleep or wakeup depending on other factors
- */
-static int sharpsl_off_charge_battery(void)
-{
- int time;
-
- dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode);
-
- if (sharpsl_pm.charge_mode == CHRG_OFF) {
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n");
-
- /* AC Check */
- if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0))
- return sharpsl_off_charge_error();
-
- /* Start Charging */
- CHARGE_LED_ON();
- CHARGE_OFF();
- mdelay(SHARPSL_CHARGE_WAIT_TIME);
- CHARGE_ON();
-
- sharpsl_pm.charge_mode = CHRG_ON;
- sharpsl_pm.full_count = 0;
-
- return 1;
- } else if (sharpsl_pm.charge_mode != CHRG_ON) {
- return 1;
- }
-
- if (sharpsl_pm.full_count == 0) {
- int time;
-
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n");
-
- if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0))
- return sharpsl_off_charge_error();
-
- CHARGE_OFF();
- mdelay(SHARPSL_CHARGE_WAIT_TIME);
- CHARGE_ON();
- sharpsl_pm.charge_mode = CHRG_ON;
-
- mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
- time = RCNR;
- while(1) {
- /* Check if any wakeup event had occured */
- if (sharpsl_pm.machinfo->charger_wakeup() != 0)
- return 0;
- /* Check for timeout */
- if ((RCNR - time) > SHARPSL_WAIT_CO_TIME)
- return 1;
- if (STATUS_CHRG_FULL()) {
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occured. Retrying to check\n");
- sharpsl_pm.full_count++;
- CHARGE_OFF();
- mdelay(SHARPSL_CHARGE_WAIT_TIME);
- CHARGE_ON();
- return 1;
- }
- }
- }
-
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n");
-
- mdelay(SHARPSL_CHARGE_CO_CHECK_TIME);
-
- time = RCNR;
- while(1) {
- /* Check if any wakeup event had occured */
- if (sharpsl_pm.machinfo->charger_wakeup() != 0)
- return 0;
- /* Check for timeout */
- if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) {
- if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) {
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n");
- sharpsl_pm.full_count = 0;
- }
- sharpsl_pm.full_count++;
- return 1;
- }
- if (STATUS_CHRG_FULL()) {
- dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n");
- CHARGE_LED_OFF();
- CHARGE_OFF();
- sharpsl_pm.charge_mode = CHRG_DONE;
- return 1;
- }
- }
-}
-
-
-static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent);
-}
-
-static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage);
-}
-
-static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL);
-static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL);
-
-extern void (*apm_get_power_status)(struct apm_power_info *);
-
-static void sharpsl_apm_get_power_status(struct apm_power_info *info)
-{
- info->ac_line_status = sharpsl_pm.battstat.ac_status;
-
- if (sharpsl_pm.charge_mode == CHRG_ON)
- info->battery_status = APM_BATTERY_STATUS_CHARGING;
- else
- info->battery_status = sharpsl_pm.battstat.mainbat_status;
-
- info->battery_flag = (1 << info->battery_status);
- info->battery_life = sharpsl_pm.battstat.mainbat_percent;
-}
-
-static struct pm_ops sharpsl_pm_ops = {
- .pm_disk_mode = PM_DISK_FIRMWARE,
- .prepare = pxa_pm_prepare,
- .enter = corgi_pxa_pm_enter,
- .finish = pxa_pm_finish,
-};
-
-static int __init sharpsl_pm_probe(struct platform_device *pdev)
-{
- if (!pdev->dev.platform_data)
- return -EINVAL;
-
- sharpsl_pm.dev = &pdev->dev;
- sharpsl_pm.machinfo = pdev->dev.platform_data;
- sharpsl_pm.charge_mode = CHRG_OFF;
- sharpsl_pm.flags = 0;
-
- sharpsl_pm.machinfo->init();
-
- init_timer(&sharpsl_pm.ac_timer);
- sharpsl_pm.ac_timer.function = sharpsl_ac_timer;
-
- init_timer(&sharpsl_pm.chrg_full_timer);
- sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer;
-
pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN);
pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN);
pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN);
@@ -938,26 +164,10 @@ static int __init sharpsl_pm_probe(struct platform_device *pdev)
}
else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQT_RISING);
}
-
- device_create_file(&pdev->dev, &dev_attr_battery_percentage);
- device_create_file(&pdev->dev, &dev_attr_battery_voltage);
-
- apm_get_power_status = sharpsl_apm_get_power_status;
-
- pm_set_ops(&sharpsl_pm_ops);
-
- mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250));
-
- return 0;
}
-static int sharpsl_pm_remove(struct platform_device *pdev)
+void sharpsl_pm_pxa_remove(void)
{
- pm_set_ops(NULL);
-
- device_remove_file(&pdev->dev, &dev_attr_battery_percentage);
- device_remove_file(&pdev->dev, &dev_attr_battery_voltage);
-
free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
@@ -966,32 +176,4 @@ static int sharpsl_pm_remove(struct platform_device *pdev)
if (!machine_is_corgi())
free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
-
- del_timer_sync(&sharpsl_pm.chrg_full_timer);
- del_timer_sync(&sharpsl_pm.ac_timer);
-
- return 0;
}
-
-static struct platform_driver sharpsl_pm_driver = {
- .probe = sharpsl_pm_probe,
- .remove = sharpsl_pm_remove,
- .suspend = sharpsl_pm_suspend,
- .resume = sharpsl_pm_resume,
- .driver = {
- .name = "sharpsl-pm",
- },
-};
-
-static int __devinit sharpsl_pm_init(void)
-{
- return platform_driver_register(&sharpsl_pm_driver);
-}
-
-static void sharpsl_pm_exit(void)
-{
- platform_driver_unregister(&sharpsl_pm_driver);
-}
-
-late_initcall(sharpsl_pm_init);
-module_exit(sharpsl_pm_exit);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 2df1b56615b1..c094d99ebf56 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -36,6 +36,7 @@
#include <asm/arch/irq.h>
#include <asm/arch/irda.h>
#include <asm/arch/mmc.h>
+#include <asm/arch/ohci.h>
#include <asm/arch/udc.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/akita.h>
@@ -126,10 +127,12 @@ static void spitz_card_pwr_ctrl(int device, unsigned short new_cpr)
cpr &= ~0x0002;
if (device == SPITZ_PWR_SD)
cpr &= ~0x0004;
- write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr);
if (!(cpr & 0x0002) && !(cpr & 0x0004)) {
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, 0x0000);
mdelay(1);
reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_CF_POWER);
+ } else {
+ write_scoop_reg(&spitzscoop_device.dev, SCOOP_CPR, cpr | new_cpr);
}
}
}
@@ -293,15 +296,14 @@ static int spitz_mci_init(struct device *dev, irqreturn_t (*spitz_detect_int)(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);
+ err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "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;
}
@@ -335,6 +337,35 @@ static struct pxamci_platform_data spitz_mci_platform_data = {
/*
+ * USB Host (OHCI)
+ */
+static int spitz_ohci_init(struct device *dev)
+{
+ /* Only Port 2 is connected */
+ pxa_gpio_mode(SPITZ_GPIO_USB_CONNECT | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_USB_HOST | GPIO_OUT);
+ pxa_gpio_mode(SPITZ_GPIO_USB_DEVICE | GPIO_IN);
+
+ /* Setup USB Port 2 Output Control Register */
+ UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
+
+ GPSR(SPITZ_GPIO_USB_HOST) = GPIO_bit(SPITZ_GPIO_USB_HOST);
+
+ UHCHR = (UHCHR) &
+ ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+
+ UHCRHDA |= UHCRHDA_NOCP;
+
+ return 0;
+}
+
+static struct pxaohci_platform_data spitz_ohci_platform_data = {
+ .port_mode = PMM_NPS_MODE,
+ .init = spitz_ohci_init,
+};
+
+
+/*
* Irda
*/
static void spitz_irda_transceiver_mode(struct device *dev, int mode)
@@ -411,6 +442,7 @@ static void __init common_init(void)
platform_add_devices(devices, ARRAY_SIZE(devices));
pxa_set_mci_info(&spitz_mci_platform_data);
+ pxa_set_ohci_info(&spitz_ohci_platform_data);
pxa_set_ficp_info(&spitz_ficp_platform_data);
set_pxa_fb_parent(&spitzssp_device.dev);
set_pxa_fb_info(&spitz_pxafb_info);
@@ -465,7 +497,6 @@ static void __init fixup_spitz(struct machine_desc *desc,
#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,
@@ -478,7 +509,6 @@ MACHINE_END
#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,
@@ -491,7 +521,6 @@ MACHINE_END
#ifdef CONFIG_MACH_AKITA
MACHINE_START(AKITA, "SHARP Akita")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_spitz,
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 3ce7486daa51..5e5bdc898482 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -33,19 +33,7 @@ static void spitz_charger_init(void)
{
pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN);
pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
-}
-
-static void spitz_charge_led(int val)
-{
- if (val == SHARPSL_LED_ERROR) {
- dev_dbg(sharpsl_pm.dev, "Charge LED Error\n");
- } else if (val == SHARPSL_LED_ON) {
- dev_dbg(sharpsl_pm.dev, "Charge LED On\n");
- set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
- } else {
- dev_dbg(sharpsl_pm.dev, "Charge LED Off\n");
- reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
- }
+ sharpsl_pm_pxa_init();
}
static void spitz_measure_temp(int on)
@@ -92,7 +80,7 @@ static void spitz_discharge1(int on)
static void spitz_presuspend(void)
{
- spitz_last_ac_status = STATUS_AC_IN();
+ spitz_last_ac_status = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
/* GPIO Sleep Register */
PGSR0 = 0x00144018;
@@ -138,7 +126,7 @@ static void spitz_postsuspend(void)
static int spitz_should_wakeup(unsigned int resume_on_alarm)
{
int is_resume = 0;
- int acin = STATUS_AC_IN();
+ int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN);
if (spitz_last_ac_status != acin) {
if (acin) {
@@ -148,8 +136,8 @@ static int spitz_should_wakeup(unsigned int resume_on_alarm)
} else {
/* charge off */
dev_dbg(sharpsl_pm.dev, "AC Removed\n");
- CHARGE_LED_OFF();
- CHARGE_OFF();
+ sharpsl_pm_led(SHARPSL_LED_OFF);
+ sharpsl_pm.machinfo->charge(0);
sharpsl_pm.charge_mode = CHRG_OFF;
}
spitz_last_ac_status = acin;
@@ -175,25 +163,41 @@ static unsigned long spitz_charger_wakeup(void)
return (~GPLR0 & GPIO_bit(SPITZ_GPIO_KEY_INT)) | (GPLR0 & GPIO_bit(SPITZ_GPIO_SYNC));
}
-static int spitz_acin_status(void)
+unsigned long spitzpm_read_devdata(int type)
{
- return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0);
+ switch(type) {
+ case SHARPSL_STATUS_ACIN:
+ return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0);
+ case SHARPSL_STATUS_LOCK:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock);
+ case SHARPSL_STATUS_CHRGFULL:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull);
+ case SHARPSL_STATUS_FATAL:
+ return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal);
+ case SHARPSL_ACIN_VOLT:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_ACIN_VOLT);
+ case SHARPSL_BATT_TEMP:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_TEMP);
+ case SHARPSL_BATT_VOLT:
+ default:
+ return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_VOLT);
+ }
}
struct sharpsl_charger_machinfo spitz_pm_machinfo = {
.init = spitz_charger_init,
+ .exit = sharpsl_pm_pxa_remove,
.gpio_batlock = SPITZ_GPIO_BAT_COVER,
.gpio_acin = SPITZ_GPIO_AC_IN,
.gpio_batfull = SPITZ_GPIO_CHRG_FULL,
.gpio_fatal = SPITZ_GPIO_FATAL_BAT,
- .status_acin = spitz_acin_status,
.discharge = spitz_discharge,
.discharge1 = spitz_discharge1,
.charge = spitz_charge,
- .chargeled = spitz_charge_led,
.measure_temp = spitz_measure_temp,
.presuspend = spitz_presuspend,
.postsuspend = spitz_postsuspend,
+ .read_devdata = spitzpm_read_devdata,
.charger_wakeup = spitz_charger_wakeup,
.should_wakeup = spitz_should_wakeup,
.bat_levels = 40,
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index a68b30eff4d2..93096befd017 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -31,6 +31,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
@@ -59,7 +60,7 @@ static const struct ssp_info_ ssp_info[PXA_SSP_PORTS] = {
#endif
};
-static DECLARE_MUTEX(sem);
+static DEFINE_MUTEX(mutex);
static int use_count[PXA_SSP_PORTS] = {0, 0, 0};
static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -239,16 +240,16 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
if (port > PXA_SSP_PORTS || port == 0)
return -ENODEV;
- down(&sem);
+ mutex_lock(&mutex);
if (use_count[port - 1]) {
- up(&sem);
+ mutex_unlock(&mutex);
return -EBUSY;
}
use_count[port - 1]++;
if (!request_mem_region(__PREG(SSCR0_P(port)), 0x2c, "SSP")) {
use_count[port - 1]--;
- up(&sem);
+ mutex_unlock(&mutex);
return -EBUSY;
}
dev->port = port;
@@ -265,13 +266,13 @@ int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags)
/* turn on SSP port clock */
pxa_set_cken(ssp_info[port-1].clock, 1);
- up(&sem);
+ mutex_unlock(&mutex);
return 0;
out_region:
release_mem_region(__PREG(SSCR0_P(port)), 0x2c);
use_count[port - 1]--;
- up(&sem);
+ mutex_unlock(&mutex);
return ret;
}
@@ -282,7 +283,7 @@ out_region:
*/
void ssp_exit(struct ssp_dev *dev)
{
- down(&sem);
+ mutex_lock(&mutex);
SSCR0_P(dev->port) &= ~SSCR0_SSE;
if (dev->port > PXA_SSP_PORTS || dev->port == 0) {
@@ -295,7 +296,7 @@ void ssp_exit(struct ssp_dev *dev)
free_irq(dev->irq, dev);
release_mem_region(__PREG(SSCR0_P(dev->port)), 0x2c);
use_count[dev->port - 1]--;
- up(&sem);
+ mutex_unlock(&mutex);
}
EXPORT_SYMBOL(ssp_write_word);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index e4f92efc616e..d168286ed470 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -295,7 +295,6 @@ static void __init fixup_tosa(struct machine_desc *desc,
}
MACHINE_START(TOSA, "SHARP Tosa")
- .phys_ram = 0xa0000000,
.phys_io = 0x40000000,
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_tosa,
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 129976866d47..17f5f4439fe7 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -3,7 +3,6 @@ menu "RealView platform type"
config MACH_REALVIEW_EB
bool "Support RealView/EB platform"
- default n
select ARM_GIC
help
Include support for the ARM(R) RealView Emulation Baseboard platform.
diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c
index 002635c97bb6..21325a4da9da 100644
--- a/arch/arm/mach-realview/clock.c
+++ b/arch/arm/mach-realview/clock.c
@@ -13,28 +13,29 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
-#include <asm/hardware/clock.h>
#include <asm/hardware/icst307.h>
#include "clock.h"
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -57,17 +58,6 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL(clk_disable);
-int clk_use(struct clk *clk)
-{
- return 0;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_unuse);
-
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
@@ -120,18 +110,18 @@ static struct clk mmci_clk = {
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index af6580f1ceb8..4a222f59f2cf 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -24,14 +24,14 @@
#include <linux/dma-mapping.h>
#include <linux/sysdev.h>
#include <linux/interrupt.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/leds.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_clcd.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/icst307.h>
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index c06e6041df41..93e86d9f439c 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -22,7 +22,8 @@
#ifndef __ASM_ARCH_REALVIEW_H
#define __ASM_ARCH_REALVIEW_H
-#include <asm/hardware/amba.h>
+#include <linux/amba/bus.h>
+
#include <asm/leds.h>
#include <asm/io.h>
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index c9d7c596b200..caf6b8bb6c95 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/smp.h>
+#include <linux/jiffies.h>
#include <asm/mach/time.h>
#include <asm/hardware/arm_twd.h>
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 7dc32503fdf2..d4a586e38d5b 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -30,7 +31,6 @@
#include <asm/leds.h>
#include <asm/mach-types.h>
#include <asm/hardware/gic.h>
-#include <asm/hardware/amba.h>
#include <asm/hardware/icst307.h>
#include <asm/mach/arch.h>
@@ -166,7 +166,6 @@ static void __init realview_eb_init(void)
MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0x00000000,
.phys_io = REALVIEW_UART0_BASE,
.io_pg_offst = (IO_ADDRESS(REALVIEW_UART0_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index bc0747439fb3..bd86ffba8810 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -13,7 +13,7 @@
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/pci.h>
+#include <linux/dma-mapping.h>
#include <asm/page.h>
#include <asm/dma.h>
@@ -148,11 +148,14 @@ static void iomd_enable_dma(dmach_t channel, dma_t *dma)
* Cope with ISA-style drivers which expect cache
* coherence.
*/
- if (!dma->using_sg) {
- dma->buf.dma_address = pci_map_single(NULL,
- dma->buf.__address, dma->buf.length,
+ if (!dma->sg) {
+ dma->sg = &dma->buf;
+ dma->sgcount = 1;
+ dma->buf.length = dma->count;
+ dma->buf.dma_address = dma_map_single(NULL,
+ dma->addr, dma->count,
dma->dma_mode == DMA_MODE_READ ?
- PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+ DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
iomd_writeb(DMA_CR_C, dma_base + CR);
@@ -239,7 +242,7 @@ static void floppy_enable_dma(dmach_t channel, dma_t *dma)
unsigned int fiqhandler_length;
struct pt_regs regs;
- if (dma->using_sg)
+ if (dma->sg)
BUG();
if (dma->dma_mode == DMA_MODE_READ) {
@@ -252,8 +255,8 @@ static void floppy_enable_dma(dmach_t channel, dma_t *dma)
fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
}
- regs.ARM_r9 = dma->buf.length;
- regs.ARM_r10 = (unsigned long)dma->buf.__address;
+ regs.ARM_r9 = dma->count;
+ regs.ARM_r10 = (unsigned long)dma->addr;
regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE;
if (claim_fiq(&fh)) {
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 5c4ac1c008a6..208a2b5dba1b 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -177,7 +177,6 @@ extern struct sys_timer ioc_timer;
MACHINE_START(RISCPC, "Acorn-RiscPC")
/* Maintainer: Russell King */
- .phys_ram = 0x10000000,
.phys_io = 0x03000000,
.io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x10000100,
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 82e8253b1fa0..af2f3d52b61b 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -34,16 +34,16 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
-
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/hardware.h>
#include <asm/atomic.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-clock.h>
#include "clock.h"
@@ -52,7 +52,7 @@
/* clock information */
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
/* old functions */
@@ -103,7 +103,7 @@ struct clk *clk_get(struct device *dev, const char *id)
else
idno = to_platform_device(dev)->id;
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, list) {
if (p->id == idno &&
@@ -127,7 +127,7 @@ struct clk *clk_get(struct device *dev, const char *id)
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -151,18 +151,6 @@ void clk_disable(struct clk *clk)
}
-int clk_use(struct clk *clk)
-{
- atomic_inc(&clk->used);
- return 0;
-}
-
-
-void clk_unuse(struct clk *clk)
-{
- atomic_dec(&clk->used);
-}
-
unsigned long clk_get_rate(struct clk *clk)
{
if (IS_ERR(clk))
@@ -196,8 +184,6 @@ EXPORT_SYMBOL(clk_get);
EXPORT_SYMBOL(clk_put);
EXPORT_SYMBOL(clk_enable);
EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_use);
-EXPORT_SYMBOL(clk_unuse);
EXPORT_SYMBOL(clk_get_rate);
EXPORT_SYMBOL(clk_round_rate);
EXPORT_SYMBOL(clk_set_rate);
@@ -268,100 +254,101 @@ struct clk s3c24xx_uclk = {
/* clock definitions */
static struct clk init_clocks[] = {
- { .name = "nand",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_NAND
- },
- { .name = "lcd",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_LCDC
- },
- { .name = "usb-host",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_USBH
- },
- { .name = "usb-device",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_USBD
- },
- { .name = "timers",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_PWMT
- },
- { .name = "sdi",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_SDI
- },
- { .name = "uart",
- .id = 0,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART0
- },
- { .name = "uart",
- .id = 1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART1
- },
- { .name = "uart",
- .id = 2,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_UART2
- },
- { .name = "gpio",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_GPIO
- },
- { .name = "rtc",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_RTC
- },
- { .name = "adc",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_ADC
- },
- { .name = "i2c",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_IIC
- },
- { .name = "iis",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_IIS
- },
- { .name = "spi",
- .id = -1,
- .parent = &clk_p,
- .enable = s3c24xx_clkcon_enable,
- .ctrlbit = S3C2410_CLKCON_SPI
- },
- { .name = "watchdog",
- .id = -1,
- .parent = &clk_p,
- .ctrlbit = 0
+ {
+ .name = "nand",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_NAND,
+ }, {
+ .name = "lcd",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_LCDC,
+ }, {
+ .name = "usb-host",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_USBH,
+ }, {
+ .name = "usb-device",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_USBD,
+ }, {
+ .name = "timers",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_PWMT,
+ }, {
+ .name = "sdi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_SDI,
+ }, {
+ .name = "uart",
+ .id = 0,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART0,
+ }, {
+ .name = "uart",
+ .id = 1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART1,
+ }, {
+ .name = "uart",
+ .id = 2,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_UART2,
+ }, {
+ .name = "gpio",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_GPIO,
+ }, {
+ .name = "rtc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_RTC,
+ }, {
+ .name = "adc",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_ADC,
+ }, {
+ .name = "i2c",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_IIC,
+ }, {
+ .name = "iis",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_IIS,
+ }, {
+ .name = "spi",
+ .id = -1,
+ .parent = &clk_p,
+ .enable = s3c24xx_clkcon_enable,
+ .ctrlbit = S3C2410_CLKCON_SPI,
+ }, {
+ .name = "watchdog",
+ .id = -1,
+ .parent = &clk_p,
+ .ctrlbit = 0,
}
};
@@ -370,16 +357,15 @@ static struct clk init_clocks[] = {
int s3c24xx_register_clock(struct clk *clk)
{
clk->owner = THIS_MODULE;
- atomic_set(&clk->used, 0);
if (clk->enable == NULL)
clk->enable = clk_null_enable;
/* add to the list of available clocks */
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->list, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
@@ -406,16 +392,15 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
clk_p.rate = pclk;
clk_f.rate = fclk;
- /* it looks like just setting the register here is not good
- * enough, and causes the odd hang at initial boot time, so
- * do all of them indivdually.
- *
- * I think disabling the LCD clock if the LCD is active is
- * very dangerous, and therefore the bootloader should be
- * careful to not enable the LCD clock if it is not needed.
+ /* We must be careful disabling the clocks we are not intending to
+ * be using at boot time, as subsytems such as the LCD which do
+ * their own DMA requests to the bus can cause the system to lockup
+ * if they where in the middle of requesting bus access.
*
- * and of course, this looks neater
- */
+ * Disabling the LCD clock if the LCD is active is very dangerous,
+ * and therefore the bootloader should be careful to not enable
+ * the LCD clock if it is not needed.
+ */
s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 7953b6f397b9..177d5c8decf7 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -16,7 +16,6 @@ struct clk {
struct clk *parent;
const char *name;
int id;
- atomic_t used;
unsigned long rate;
unsigned long ctrlbit;
int (*enable)(struct clk *, int enable);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 0f81fc0c2f7f..3e327b8e46be 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -294,7 +294,6 @@ static void __init anubis_map_io(void)
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,
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 4d962717fdf7..995bb8add331 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -527,7 +527,6 @@ static void __init bast_init(void)
MACHINE_START(BAST, "Simtec-BAST")
/* 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,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 0aa8760598f7..1c316f14ed94 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -171,7 +171,6 @@ static void __init h1940_init(void)
MACHINE_START(H1940, "IPAQ-H1940")
/* Maintainer: Ben Dooks <ben@fluff.org> */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 378d640ab00b..116ac3169966 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -128,7 +128,6 @@ MACHINE_START(N30, "Acer-N30")
/* 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,
.boot_params = S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
index 42b0eeff2e0f..07d09509a626 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -148,7 +148,6 @@ static void __init nexcoder_map_io(void)
MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index a2eb9ed48fcd..b39daedf93ca 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -116,7 +116,6 @@ static void __init otom11_map_io(void)
MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
/* Maintainer: Guillaume GOURAT <guillaume.gourat@nexvision.tv> */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index f8d86d1e16b6..0260ed5ab946 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -205,7 +205,6 @@ static void __init rx3715_init_machine(void)
MACHINE_START(RX3715, "IPAQ-RX3715")
/* Maintainer: Ben Dooks <ben@fluff.org> */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 2c91965ee1c8..1e76e1fdfcea 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -115,7 +115,6 @@ static void __init smdk2410_init_irq(void)
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 4e31118533e6..f4315721c3b8 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -216,7 +216,6 @@ static void __init smdk2440_machine_init(void)
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks <ben@fluff.org> */
- .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,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index ae7e099bf6c8..785fc9cdcf7c 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -395,7 +395,6 @@ static void __init vr1000_map_io(void)
MACHINE_START(VR1000, "Thorcom-VR1000")
/* 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,
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index c67e0979aec3..b557a2be8a01 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -29,16 +29,15 @@
#include <linux/err.h>
#include <linux/device.h>
#include <linux/sysdev.h>
-
#include <linux/interrupt.h>
#include <linux/ioport.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/atomic.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-clock.h>
#include "clock.h"
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index 4d63e7133b48..b7fe6d9453fb 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
+#include <linux/clk.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -36,7 +37,6 @@
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-serial.h>
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 8a00e3c3cd08..10a2976aefdd 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/system.h>
#include <asm/leds.h>
@@ -35,7 +36,6 @@
#include <asm/arch/regs-timer.h>
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
-#include <asm/hardware/clock.h>
#include "clock.h"
#include "cpu.h"
@@ -191,7 +191,6 @@ static void s3c2410_timer_setup (void)
if (IS_ERR(clk))
panic("failed to get clock for system timer");
- clk_use(clk);
clk_enable(clk);
pclk = clk_get_rate(clk);
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 5098b50158a3..495f8c6ffcb6 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -84,13 +84,13 @@ static void usb_simtec_enableoc(struct s3c2410_hcd_info *info, int on)
int ret;
if (on) {
- ret = request_irq(IRQ_USBOC, usb_simtec_ocirq, SA_INTERRUPT,
+ ret = request_irq(IRQ_USBOC, usb_simtec_ocirq,
+ SA_INTERRUPT | SA_TRIGGER_RISING |
+ SA_TRIGGER_FALLING,
"USB Over-current", info);
if (ret != 0) {
printk(KERN_ERR "failed to request usb oc irq\n");
}
-
- set_irq_type(IRQ_USBOC, IRQT_BOTHEDGE);
} else {
free_irq(IRQ_USBOC, info);
}
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index a66ac61233a2..a599bb0d4ab8 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -447,7 +447,6 @@ static void __init assabet_map_io(void)
MACHINE_START(ASSABET, "Intel-Assabet")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index edccd5eb06be..f60b7a66dfa0 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -297,7 +297,6 @@ static void __init badge4_map_io(void)
}
MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 508593722bc7..8269a9ef9afe 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -135,7 +135,6 @@ static void __init cerf_init(void)
MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
/* Maintainer: support@intrinsyc.com */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = cerf_map_io,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 522abc036d3a..6888816a1935 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -191,7 +191,6 @@ static void __init collie_map_io(void)
}
MACHINE_START(COLLIE, "Sharp-Collie")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = collie_map_io,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index e8352b7f74b0..b04d92271020 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -392,7 +392,6 @@ static void __init h3100_map_io(void)
}
MACHINE_START(H3100, "Compaq iPAQ H3100")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
@@ -510,7 +509,6 @@ static void __init h3600_map_io(void)
}
MACHINE_START(H3600, "Compaq iPAQ H3600")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
@@ -897,7 +895,6 @@ static void __init h3800_map_io(void)
}
MACHINE_START(H3800, "Compaq iPAQ H3800")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index c922e043c424..046b213efd5b 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -195,7 +195,6 @@ static void __init hackkit_init(void)
*/
MACHINE_START(HACKKIT, "HackKit Cpu Board")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 2f671cc3cb99..17f5a43acdb7 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -173,7 +173,6 @@ static void __init jornada720_mach_init(void)
MACHINE_START(JORNADA720, "HP Jornada 720")
/* Maintainer: Michael Gernoth <michael@gernoth.net> */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index 8c9e3dd52942..07d3a696ae7f 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -60,7 +60,6 @@ static void __init lart_map_io(void)
}
MACHINE_START(LART, "LART")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 58c18f9e9b7b..0709ebab531c 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -146,7 +146,6 @@ static void __init pleb_map_io(void)
}
MACHINE_START(PLEB, "PLEB")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.map_io = pleb_map_io,
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 59c7964cfe11..786c8534231f 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -135,29 +135,11 @@ unsigned long sleep_phys_sp(void *sp)
}
/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int sa11x0_pm_prepare(suspend_state_t state)
-{
- return 0;
-}
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int sa11x0_pm_finish(suspend_state_t state)
-{
- return 0;
-}
-
-/*
* Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
*/
static struct pm_ops sa11x0_pm_ops = {
.pm_disk_mode = PM_DISK_FIRMWARE,
- .prepare = sa11x0_pm_prepare,
.enter = sa11x0_pm_enter,
- .finish = sa11x0_pm_finish,
};
static int __init sa11x0_pm_init(void)
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 7482288278d9..5aafe0b56992 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -83,7 +83,6 @@ static void __init shannon_map_io(void)
}
MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 439ddc9b06d6..d2c23b2c34d1 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -229,7 +229,6 @@ arch_initcall(simpad_init);
MACHINE_START(SIMPAD, "Simpad")
/* Maintainer: Holger Freyther */
- .phys_ram = 0xc0000000,
.phys_io = 0x80000000,
.io_pg_offst = ((0xf8000000) >> 18) & 0xfffc,
.boot_params = 0xc0000100,
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 2d428b6dbb58..877600e212dd 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -111,7 +111,6 @@ static struct sys_timer shark_timer = {
MACHINE_START(SHARK, "Shark")
/* Maintainer: Alexander Schulz */
- .phys_ram = 0x08000000,
.phys_io = 0x40000000,
.io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x08003000,
diff --git a/arch/arm/mach-versatile/Kconfig b/arch/arm/mach-versatile/Kconfig
index 8d787f4c78e6..95096afd5271 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -9,7 +9,6 @@ config ARCH_VERSATILE_PB
config MACH_VERSATILE_AB
bool "Support Versatile/AB platform"
- default n
help
Include support for the ARM(R) Versatile/AP platform.
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
index b96a2ea15d41..9858c96560e2 100644
--- a/arch/arm/mach-versatile/clock.c
+++ b/arch/arm/mach-versatile/clock.c
@@ -14,28 +14,29 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/semaphore.h>
-#include <asm/hardware/clock.h>
#include <asm/hardware/icst307.h>
#include "clock.h"
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -58,17 +59,6 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL(clk_disable);
-int clk_use(struct clk *clk)
-{
- return 0;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_unuse);
-
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
@@ -121,18 +111,18 @@ static struct clk mmci_clk = {
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index a1ca46630dda..9ebbe808b41d 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -25,16 +25,17 @@
#include <linux/platform_device.h>
#include <linux/sysdev.h>
#include <linux/interrupt.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
#include <asm/system.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/leds.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_clcd.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/icst307.h>
+#include <asm/hardware/vic.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
@@ -56,24 +57,6 @@
#define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE)
#define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE)
-static void vic_mask_irq(unsigned int irq)
-{
- irq -= IRQ_VIC_START;
- writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
-}
-
-static void vic_unmask_irq(unsigned int irq)
-{
- irq -= IRQ_VIC_START;
- writel(1 << irq, VA_VIC_BASE + VIC_IRQ_ENABLE);
-}
-
-static struct irqchip vic_chip = {
- .ack = vic_mask_irq,
- .mask = vic_mask_irq,
- .unmask = vic_unmask_irq,
-};
-
static void sic_mask_irq(unsigned int irq)
{
irq -= IRQ_SIC_START;
@@ -127,43 +110,12 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
void __init versatile_init_irq(void)
{
- unsigned int i, value;
-
- /* Disable all interrupts initially. */
+ unsigned int i;
- writel(0, VA_VIC_BASE + VIC_INT_SELECT);
- writel(0, VA_VIC_BASE + VIC_IRQ_ENABLE);
- writel(~0, VA_VIC_BASE + VIC_IRQ_ENABLE_CLEAR);
- writel(0, VA_VIC_BASE + VIC_IRQ_STATUS);
- writel(0, VA_VIC_BASE + VIC_ITCR);
- writel(~0, VA_VIC_BASE + VIC_IRQ_SOFT_CLEAR);
-
- /*
- * Make sure we clear all existing interrupts
- */
- writel(0, VA_VIC_BASE + VIC_VECT_ADDR);
- for (i = 0; i < 19; i++) {
- value = readl(VA_VIC_BASE + VIC_VECT_ADDR);
- writel(value, VA_VIC_BASE + VIC_VECT_ADDR);
- }
-
- for (i = 0; i < 16; i++) {
- value = readl(VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
- writel(value | VICVectCntl_Enable | i, VA_VIC_BASE + VIC_VECT_CNTL0 + (i * 4));
- }
-
- writel(32, VA_VIC_BASE + VIC_DEF_VECT_ADDR);
-
- for (i = IRQ_VIC_START; i <= IRQ_VIC_END; i++) {
- if (i != IRQ_VICSOURCE31) {
- set_irq_chip(i, &vic_chip);
- set_irq_handler(i, do_level_IRQ);
- set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
- }
- }
+ vic_init(VA_VIC_BASE, ~(1 << 31));
set_irq_handler(IRQ_VICSOURCE31, sic_handle_irq);
- vic_unmask_irq(IRQ_VICSOURCE31);
+ enable_irq(IRQ_VICSOURCE31);
/* Do second interrupt controller */
writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
@@ -877,7 +829,7 @@ static unsigned long versatile_gettimeoffset(void)
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
do {
ticks1 = ticks2;
- status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
+ status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
} while (ticks2 > ticks1);
diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h
index 588c20669d5d..afcaa858eb1f 100644
--- a/arch/arm/mach-versatile/core.h
+++ b/arch/arm/mach-versatile/core.h
@@ -22,7 +22,7 @@
#ifndef __ASM_ARCH_VERSATILE_H
#define __ASM_ARCH_VERSATILE_H
-#include <asm/hardware/amba.h>
+#include <linux/amba/bus.h>
extern void __init versatile_init(void);
extern void __init versatile_init_irq(void);
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index 8b0b3bef24ae..1eb596782078 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -23,12 +23,12 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
-#include <asm/hardware/amba.h>
#include <asm/mach/arch.h>
@@ -36,7 +36,6 @@
MACHINE_START(VERSATILE_AB, "ARM-Versatile AB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0x00000000,
.phys_io = 0x101f1000,
.io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 7c3078c38916..f17ab4fb548a 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -23,12 +23,12 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
-#include <asm/hardware/amba.h>
#include <asm/mach/arch.h>
#include <asm/mach/mmc.h>
@@ -100,7 +100,6 @@ arch_initcall(versatile_pb_init);
MACHINE_START(VERSATILE_PB, "ARM-Versatile PB")
/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_ram = 0x00000000,
.phys_io = 0x101f1000,
.io_pg_offst = ((0xf11f1000) >> 18) & 0xfffc,
.boot_params = 0x00000100,
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index e84fdde6edf8..3b79d0e23455 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,8 +62,8 @@ config CPU_ARM720T
# ARM920T
config CPU_ARM920T
bool "Support ARM920T processor" if !ARCH_S3C2410
- depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
- default y if ARCH_S3C2410
+ depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
+ default y if ARCH_S3C2410 || ARCH_AT91RM9200
select CPU_32v4
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
@@ -83,8 +83,8 @@ config CPU_ARM920T
# ARM922T
config CPU_ARM922T
bool "Support ARM922T processor" if ARCH_INTEGRATOR
- depends on ARCH_CAMELOT || ARCH_LH7A40X || ARCH_INTEGRATOR
- default y if ARCH_CAMELOT || ARCH_LH7A40X
+ depends on ARCH_LH7A40X || ARCH_INTEGRATOR
+ default y if ARCH_LH7A40X
select CPU_32v4
select CPU_ABRT_EV4T
select CPU_CACHE_V4WT
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index dbfe9e891f01..c2ee18d2075e 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -19,17 +19,26 @@
#include <linux/dma-mapping.h>
#include <asm/cacheflush.h>
-#include <asm/io.h>
#include <asm/tlbflush.h>
+#include <asm/sizes.h>
+
+/* Sanity check size */
+#if (CONSISTENT_DMA_SIZE % SZ_2M)
+#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
+#endif
-#define CONSISTENT_BASE (0xffc00000)
#define CONSISTENT_END (0xffe00000)
+#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
+
#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
+#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
+
/*
- * This is the page table (2MB) covering uncached, DMA consistent allocations
+ * These are the page tables (2MB each) covering uncached, DMA consistent allocations
*/
-static pte_t *consistent_pte;
+static pte_t *consistent_pte[NUM_CONSISTENT_PTES];
static DEFINE_SPINLOCK(consistent_lock);
/*
@@ -143,7 +152,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
unsigned long order;
u64 mask = ISA_DMA_THRESHOLD, limit;
- if (!consistent_pte) {
+ if (!consistent_pte[0]) {
printk(KERN_ERR "%s: not initialised\n", __func__);
dump_stack();
return NULL;
@@ -206,9 +215,12 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
c = vm_region_alloc(&consistent_head, size,
gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
if (c) {
- pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ pte_t *pte;
struct page *end = page + (1 << order);
+ int idx = CONSISTENT_PTE_INDEX(c->vm_start);
+ u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
+ pte = consistent_pte[idx] + off;
c->vm_pages = page;
/*
@@ -227,6 +239,11 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
set_pte(pte, mk_pte(page, prot));
page++;
pte++;
+ off++;
+ if (off >= PTRS_PER_PTE) {
+ off = 0;
+ pte = consistent_pte[++idx];
+ }
} while (size -= PAGE_SIZE);
/*
@@ -328,6 +345,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
struct vm_region *c;
unsigned long flags, addr;
pte_t *ptep;
+ int idx;
+ u32 off;
WARN_ON(irqs_disabled());
@@ -348,7 +367,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
size = c->vm_end - c->vm_start;
}
- ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ idx = CONSISTENT_PTE_INDEX(c->vm_start);
+ off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
+ ptep = consistent_pte[idx] + off;
addr = c->vm_start;
do {
pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
@@ -356,6 +377,11 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
ptep++;
addr += PAGE_SIZE;
+ off++;
+ if (off >= PTRS_PER_PTE) {
+ off = 0;
+ ptep = consistent_pte[++idx];
+ }
if (!pte_none(pte) && pte_present(pte)) {
pfn = pte_pfn(pte);
@@ -402,11 +428,12 @@ static int __init consistent_init(void)
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int ret = 0;
+ int ret = 0, i = 0;
+ u32 base = CONSISTENT_BASE;
do {
- pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
- pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+ pgd = pgd_offset(&init_mm, base);
+ pmd = pmd_alloc(&init_mm, pgd, base);
if (!pmd) {
printk(KERN_ERR "%s: no pmd tables\n", __func__);
ret = -ENOMEM;
@@ -414,15 +441,16 @@ static int __init consistent_init(void)
}
WARN_ON(!pmd_none(*pmd));
- pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
+ pte = pte_alloc_kernel(pmd, base);
if (!pte) {
printk(KERN_ERR "%s: no pte tables\n", __func__);
ret = -ENOMEM;
break;
}
- consistent_pte = pte;
- } while (0);
+ consistent_pte[i++] = pte;
+ base += (1 << PGDIR_SHIFT);
+ } while (base < CONSISTENT_END);
return ret;
}
diff --git a/arch/arm/mm/discontig.c b/arch/arm/mm/discontig.c
index 0d097bb1bc4d..1e5602189507 100644
--- a/arch/arm/mm/discontig.c
+++ b/arch/arm/mm/discontig.c
@@ -9,10 +9,8 @@
* 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/mm.h>
-#include <linux/init.h>
+#include <linux/mmzone.h>
#include <linux/bootmem.h>
#if MAX_NUMNODES != 4 && MAX_NUMNODES != 16
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 10901398e4a2..de3ce1eec2ec 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -86,11 +86,12 @@ remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
}
static int
-remap_area_pages(unsigned long start, unsigned long phys_addr,
+remap_area_pages(unsigned long start, unsigned long pfn,
unsigned long size, unsigned long flags)
{
unsigned long address = start;
unsigned long end = start + size;
+ unsigned long phys_addr = __pfn_to_phys(pfn);
int err = 0;
pgd_t * dir;
@@ -130,36 +131,44 @@ remap_area_pages(unsigned long start, unsigned long phys_addr,
* mapping. See include/asm-arm/proc-armv/pgtable.h for more information.
*/
void __iomem *
+__ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
+ unsigned long flags)
+{
+ unsigned long addr;
+ struct vm_struct * area;
+
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = (unsigned long)area->addr;
+ if (remap_area_pages(addr, pfn, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void __iomem *) (offset + (char *)addr);
+}
+EXPORT_SYMBOL(__ioremap_pfn);
+
+void __iomem *
__ioremap(unsigned long phys_addr, size_t size, unsigned long flags)
{
- void * addr;
- struct vm_struct * area;
- unsigned long offset, last_addr;
+ unsigned long last_addr;
+ unsigned long offset = phys_addr & ~PAGE_MASK;
+ unsigned long pfn = __phys_to_pfn(phys_addr);
- /* Don't allow wraparound or zero size */
+ /*
+ * Don't allow wraparound or zero size
+ */
last_addr = phys_addr + size - 1;
if (!size || last_addr < phys_addr)
return NULL;
/*
- * Mappings have to be page-aligned
+ * Page align the mapping size
*/
- offset = phys_addr & ~PAGE_MASK;
- phys_addr &= PAGE_MASK;
size = PAGE_ALIGN(last_addr + 1) - phys_addr;
- /*
- * Ok, go for it..
- */
- area = get_vm_area(size, VM_IOREMAP);
- if (!area)
- return NULL;
- addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
- vfree(addr);
- return NULL;
- }
- return (void __iomem *) (offset + (char *)addr);
+ return __ioremap_pfn(pfn, offset, size, flags);
}
EXPORT_SYMBOL(__ioremap);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 9e50127be635..d0245a31d4dd 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -19,7 +19,6 @@
#include <asm/pgalloc.h>
#include <asm/page.h>
-#include <asm/io.h>
#include <asm/setup.h>
#include <asm/tlbflush.h>
diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h
index da4c616b6c49..28cd79a451d3 100644
--- a/arch/arm/nwfpe/fpa11.h
+++ b/arch/arm/nwfpe/fpa11.h
@@ -62,7 +62,7 @@ typedef union tagFPREG {
#else
u32 padding[3];
#endif
-} FPREG;
+} __attribute__ ((packed,aligned(4))) FPREG;
/*
* FPA11 device model.
@@ -89,7 +89,7 @@ typedef struct tagFPA11 {
so we can use it to detect whether this
instance of the emulator needs to be
initialised. */
-} FPA11;
+} __attribute__ ((packed,aligned(4))) FPA11;
extern int8 SetRoundingMode(const unsigned int);
extern int8 SetRoundingPrecision(const unsigned int);
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 9693e9b4ffd1..0887bb2a2551 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -22,7 +22,6 @@ comment "OMAP Feature Selections"
config OMAP_RESET_CLOCKS
bool "Reset unused clocks during boot"
depends on ARCH_OMAP
- default n
help
Say Y if you want to reset unused clocks during boot.
This option saves power, but assumes all drivers are
@@ -44,7 +43,6 @@ config OMAP_MUX
config OMAP_MUX_DEBUG
bool "Multiplexing debug output"
depends on OMAP_MUX
- default n
help
Makes the multiplexing functions print out a lot of debug info.
This is useful if you want to find out the correct values of the
@@ -93,7 +91,6 @@ config OMAP_32K_TIMER_HZ
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.
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 7ce39b986e23..3c2bfc0efdaf 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -19,35 +19,36 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/semaphore.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/clock.h>
LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
DEFINE_SPINLOCK(clockfw_lock);
static struct clk_functions *arch_clock;
/*-------------------------------------------------------------------------
- * Standard clock functions defined in asm/hardware/clock.h
+ * Standard clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
struct clk * clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -59,12 +60,8 @@ int clk_enable(struct clk *clk)
int ret = 0;
spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->enable)
- ret = clk->enable(clk);
- else if (arch_clock->clk_enable)
+ if (arch_clock->clk_enable)
ret = arch_clock->clk_enable(clk);
- else
- printk(KERN_ERR "Could not enable clock %s\n", clk->name);
spin_unlock_irqrestore(&clockfw_lock, flags);
return ret;
@@ -76,41 +73,12 @@ void clk_disable(struct clk *clk)
unsigned long flags;
spin_lock_irqsave(&clockfw_lock, flags);
- if (clk->disable)
- clk->disable(clk);
- else if (arch_clock->clk_disable)
+ if (arch_clock->clk_disable)
arch_clock->clk_disable(clk);
- else
- printk(KERN_ERR "Could not disable clock %s\n", clk->name);
spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
-int clk_use(struct clk *clk)
-{
- unsigned long flags;
- int ret = 0;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- if (arch_clock->clk_use)
- ret = arch_clock->clk_use(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(clk_use);
-
-void clk_unuse(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- if (arch_clock->clk_unuse)
- arch_clock->clk_unuse(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_unuse);
-
int clk_get_usecount(struct clk *clk)
{
unsigned long flags;
@@ -145,7 +113,7 @@ void clk_put(struct clk *clk)
EXPORT_SYMBOL(clk_put);
/*-------------------------------------------------------------------------
- * Optional clock functions defined in asm/hardware/clock.h
+ * Optional clock functions defined in include/linux/clk.h
*-------------------------------------------------------------------------*/
long clk_round_rate(struct clk *clk, unsigned long rate)
@@ -249,11 +217,11 @@ void propagate_rate(struct clk * tclk)
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->init)
clk->init(clk);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
@@ -261,9 +229,9 @@ EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index ccdb452630cf..adffc5a859ee 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -18,12 +18,12 @@
#include <linux/tty.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/mach/map.h>
-#include <asm/hardware/clock.h>
#include <asm/io.h>
#include <asm/setup.h>
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index fd894bb00107..98edc9fdd6d1 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -19,13 +19,12 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/system.h>
-#include <asm/hardware/clock.h>
-
/* TODO: Add support for SDRAM timing changes */
int omap_verify_speed(struct cpufreq_policy *policy)
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index f5cc21ad0956..a4e5ac77f6df 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -64,7 +64,7 @@ static int dma_chan_count;
static spinlock_t dma_chan_lock;
static struct omap_dma_lch dma_chan[OMAP_LOGICAL_DMA_CH_COUNT];
-const static u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
+static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10,
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 76f721d85137..b4d5b9e4bfce 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -19,9 +19,9 @@
#include <linux/ptrace.h>
#include <linux/sysdev.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
-#include <asm/hardware/clock.h>
#include <asm/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
@@ -853,19 +853,19 @@ static int __init _omap_gpio_init(void)
if (IS_ERR(gpio_ick))
printk("Could not get arm_gpio_ck\n");
else
- clk_use(gpio_ick);
+ clk_enable(gpio_ick);
}
if (cpu_is_omap24xx()) {
gpio_ick = clk_get(NULL, "gpios_ick");
if (IS_ERR(gpio_ick))
printk("Could not get gpios_ick\n");
else
- clk_use(gpio_ick);
+ clk_enable(gpio_ick);
gpio_fck = clk_get(NULL, "gpios_fck");
if (IS_ERR(gpio_ick))
printk("Could not get gpios_fck\n");
else
- clk_use(gpio_fck);
+ clk_enable(gpio_fck);
}
#ifdef CONFIG_ARCH_OMAP15XX
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index ea9475c86656..1cd2cace7e1b 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -19,6 +19,7 @@
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/delay.h>
#include <asm/io.h>
@@ -30,8 +31,6 @@
#include <asm/arch/dsp_common.h>
#include <asm/arch/mcbsp.h>
-#include <asm/hardware/clock.h>
-
#ifdef CONFIG_MCBSP_DEBUG
#define DBG(x...) printk(x)
#else
@@ -191,11 +190,11 @@ static int omap_mcbsp_check(unsigned int id)
static void omap_mcbsp_dsp_request(void)
{
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
- clk_use(mcbsp_dsp_ck);
- clk_use(mcbsp_api_ck);
+ clk_enable(mcbsp_dsp_ck);
+ clk_enable(mcbsp_api_ck);
/* enable 12MHz clock to mcbsp 1 & 3 */
- clk_use(mcbsp_dspxor_ck);
+ clk_enable(mcbsp_dspxor_ck);
/*
* DSP external peripheral reset
@@ -209,9 +208,9 @@ static void omap_mcbsp_dsp_request(void)
static void omap_mcbsp_dsp_free(void)
{
if (cpu_is_omap1510() || cpu_is_omap16xx()) {
- clk_unuse(mcbsp_dspxor_ck);
- clk_unuse(mcbsp_dsp_ck);
- clk_unuse(mcbsp_api_ck);
+ clk_disable(mcbsp_dspxor_ck);
+ clk_disable(mcbsp_dsp_ck);
+ clk_disable(mcbsp_api_ck);
}
}
diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c
index b86148227480..5cc6775c789c 100644
--- a/arch/arm/plat-omap/ocpi.c
+++ b/arch/arm/plat-omap/ocpi.c
@@ -31,9 +31,9 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/err.h>
+#include <linux/clk.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/hardware.h>
#define OCPI_BASE 0xfffec320
@@ -88,7 +88,7 @@ static int __init omap_ocpi_init(void)
if (IS_ERR(ocpi_ck))
return PTR_ERR(ocpi_ck);
- clk_use(ocpi_ck);
+ clk_enable(ocpi_ck);
ocpi_enable();
printk("OMAP OCPI interconnect driver loaded\n");
@@ -102,7 +102,7 @@ static void __exit omap_ocpi_exit(void)
if (!cpu_is_omap16xx())
return;
- clk_unuse(ocpi_ck);
+ clk_disable(ocpi_ck);
clk_put(ocpi_ck);
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 465487470d0e..d0f9bb5e9023 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Fri Nov 25 14:43:04 2005
+# Last update: Mon Jan 9 12:56:42 2006
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -910,3 +910,31 @@ mbus MACH_MBUS MBUS 896
nadia2vb MACH_NADIA2VB NADIA2VB 897
r1000 MACH_R1000 R1000 898
hw90250 MACH_HW90250 HW90250 899
+omap_2430sdp MACH_OMAP_2430SDP OMAP_2430SDP 900
+davinci_evm MACH_DAVINCI_EVM DAVINCI_EVM 901
+omap_tornado MACH_OMAP_TORNADO OMAP_TORNADO 902
+olocreek MACH_OLOCREEK OLOCREEK 903
+palmz72 MACH_PALMZ72 PALMZ72 904
+nxdb500 MACH_NXDB500 NXDB500 905
+apf9328 MACH_APF9328 APF9328 906
+omap_wipoq MACH_OMAP_WIPOQ OMAP_WIPOQ 907
+omap_twip MACH_OMAP_TWIP OMAP_TWIP 908
+xscale_treo650 MACH_XSCALE_PALMTREO650 XSCALE_PALMTREO650 909
+acumen MACH_ACUMEN ACUMEN 910
+xp100 MACH_XP100 XP100 911
+fs2410 MACH_FS2410 FS2410 912
+pxa270_cerf MACH_PXA270_CERF PXA270_CERF 913
+sq2ftlpalm MACH_SQ2FTLPALM SQ2FTLPALM 914
+bsemserver MACH_BSEMSERVER BSEMSERVER 915
+netclient MACH_NETCLIENT NETCLIENT 916
+xscale_palmtt5 MACH_XSCALE_PALMTT5 XSCALE_PALMTT5 917
+xscale_palmtc MACH_OMAP_PALMTC OMAP_PALMTC 918
+omap_apollon MACH_OMAP_APOLLON OMAP_APOLLON 919
+argonlvevb MACH_ARGONLVEVB ARGONLVEVB 920
+rea_2d MACH_REA_2D REA_2D 921
+eti3e524 MACH_TI3E524 TI3E524 922
+ateb9200 MACH_ATEB9200 ATEB9200 923
+auckland MACH_AUCKLAND AUCKLAND 924
+ak3220m MACH_AK3320M AK3320M 925
+duramax MACH_DURAMAX DURAMAX 926
+n35 MACH_N35 N35 927
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 1f00b3d03a07..274e07019b46 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -34,10 +34,6 @@ config FORCE_MAX_ZONEORDER
int
default 9
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index 35514b398e2e..811a6376c624 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -35,7 +35,6 @@
#include <asm/checksum.h>
#include <asm/mach-types.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, struct user_fp_struct *);
extern void inswb(unsigned int port, void *to, int len);
extern void outswb(unsigned int port, const void *to, int len);
diff --git a/arch/arm26/kernel/asm-offsets.c b/arch/arm26/kernel/asm-offsets.c
index 4ccacaef94df..ac682d5fd039 100644
--- a/arch/arm26/kernel/asm-offsets.c
+++ b/arch/arm26/kernel/asm-offsets.c
@@ -25,13 +25,6 @@
#if defined(__APCS_32__) && defined(CONFIG_CPU_26)
#error Sorry, your compiler targets APCS-32 but this kernel requires APCS-26
#endif
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95)
-#error Sorry, your compiler is known to miscompile kernels. Only use gcc 2.95.3 and later.
-#endif
-#if __GNUC__ == 2 && __GNUC_MINOR__ == 95
-/* shame we can't detect the .1 or .2 releases */
-#warning GCC 2.95.2 and earlier miscompiles kernels.
-#endif
/* Use marker if you need to separate the values later */
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
index f3cc1036e5bc..0934e6fba606 100644
--- a/arch/arm26/kernel/irq.c
+++ b/arch/arm26/kernel/irq.c
@@ -141,7 +141,7 @@ int show_interrupts(struct seq_file *p, void *v)
if (i < NR_IRQS) {
action = irq_desc[i].action;
if (!action)
- continue;
+ goto out;
seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next) {
@@ -152,6 +152,7 @@ int show_interrupts(struct seq_file *p, void *v)
show_fiq_list(p, v);
seq_printf(p, "Err: %10lu\n", irq_err_count);
}
+out:
return 0;
}
diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c
index 15833a0057dd..386305659171 100644
--- a/arch/arm26/kernel/process.c
+++ b/arch/arm26/kernel/process.c
@@ -277,10 +277,9 @@ int
copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
unsigned long unused, struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *thread = p->thread_info;
- struct pt_regs *childregs;
+ struct thread_info *thread = task_thread_info(p);
+ struct pt_regs *childregs = task_pt_regs(p);
- childregs = __get_user_regs(thread);
*childregs = *regs;
childregs->ARM_r0 = 0;
childregs->ARM_sp = stack_start;
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 4e6b7356a722..282e24d79328 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -40,21 +40,6 @@
#define BREAKINST_ARM 0xef9f0001
/*
- * Get the address of the live pt_regs for the specified task.
- * These are saved onto the top kernel stack when the process
- * is not running.
- *
- * Note: if a user thread is execve'd from kernel space, the
- * kernel stack will not be empty on entry to the kernel, so
- * ptracing these tasks will fail.
- */
-static inline struct pt_regs *
-get_user_regs(struct task_struct *task)
-{
- return __get_user_regs(task->thread_info);
-}
-
-/*
* this routine will get a word off of the processes privileged stack.
* the offset is how far from the base addr as stored in the THREAD.
* this routine assumes that all the privileged stacks are in our
@@ -62,7 +47,7 @@ get_user_regs(struct task_struct *task)
*/
static inline long get_user_reg(struct task_struct *task, int offset)
{
- return get_user_regs(task)->uregs[offset];
+ return task_pt_regs(task)->uregs[offset];
}
/*
@@ -74,7 +59,7 @@ static inline long get_user_reg(struct task_struct *task, int offset)
static inline int
put_user_reg(struct task_struct *task, int offset, long data)
{
- struct pt_regs newregs, *regs = get_user_regs(task);
+ struct pt_regs newregs, *regs = task_pt_regs(task);
int ret = -EINVAL;
newregs = *regs;
@@ -377,7 +362,7 @@ void ptrace_set_bpt(struct task_struct *child)
u32 insn;
int res;
- regs = get_user_regs(child);
+ regs = task_pt_regs(child);
pc = instruction_pointer(regs);
res = read_instr(child, pc, &insn);
@@ -500,7 +485,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
*/
static int ptrace_getregs(struct task_struct *tsk, void *uregs)
{
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}
@@ -515,7 +500,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs)
ret = -EFAULT;
if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
ret = -EINVAL;
if (valid_user_regs(&newregs)) {
@@ -532,7 +517,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs)
*/
static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
{
- return copy_to_user(ufp, &tsk->thread_info->fpstate,
+ return copy_to_user(ufp, &task_thread_info(tsk)->fpstate,
sizeof(struct user_fp)) ? -EFAULT : 0;
}
@@ -542,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
{
set_stopped_child_used_math(tsk);
- return copy_from_user(&tsk->thread_info->fpstate, ufp,
+ return copy_from_user(&task_thread_info(tsk)->fpstate, ufp,
sizeof(struct user_fp)) ? -EFAULT : 0;
}
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index f64f59022392..5847ea5d7747 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -132,7 +132,7 @@ static void dump_instr(struct pt_regs *regs)
/*static*/ void __dump_stack(struct task_struct *tsk, unsigned long sp)
{
- dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info);
+ dump_mem("Stack: ", sp, 8192+(unsigned long)task_stack_page(tsk));
}
void dump_stack(void)
@@ -158,7 +158,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
} else if (verify_stack(fp)) {
printk("invalid frame pointer 0x%08x", fp);
ok = 0;
- } else if (fp < (unsigned long)(tsk->thread_info + 1))
+ } else if (fp < (unsigned long)end_of_stack(tsk))
printk("frame pointer underflow");
printk("\n");
@@ -168,7 +168,7 @@ void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
/* FIXME - this is probably wrong.. */
void show_stack(struct task_struct *task, unsigned long *sp) {
- dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info);
+ dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task_stack_page(task));
}
DEFINE_SPINLOCK(die_lock);
@@ -187,7 +187,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
printk("CPU: %d\n", smp_processor_id());
show_regs(regs);
printk("Process %s (pid: %d, stack limit = 0x%p)\n",
- current->comm, current->pid, tsk->thread_info + 1);
+ current->comm, current->pid, end_of_stack(tsk));
if (!user_mode(regs) || in_interrupt()) {
__dump_stack(tsk, (unsigned long)(regs + 1));
diff --git a/arch/arm26/nwfpe/fpmodule.c b/arch/arm26/nwfpe/fpmodule.c
index 528fa710aa34..5258c6096fb9 100644
--- a/arch/arm26/nwfpe/fpmodule.c
+++ b/arch/arm26/nwfpe/fpmodule.c
@@ -46,10 +46,9 @@ typedef struct task_struct* PTASK;
#ifdef MODULE
void fp_send_sig(unsigned long sig, PTASK p, int priv);
-#if LINUX_VERSION_CODE > 0x20115
+
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
MODULE_DESCRIPTION("NWFPE floating point emulator");
-#endif
#else
#define fp_send_sig send_sig
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index e5979d68e352..b83261949737 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -9,10 +9,6 @@ config MMU
bool
default y
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/cris/arch-v10/drivers/ds1302.c b/arch/cris/arch-v10/drivers/ds1302.c
index 10795f67f687..b100f26497c4 100644
--- a/arch/cris/arch-v10/drivers/ds1302.c
+++ b/arch/cris/arch-v10/drivers/ds1302.c
@@ -148,6 +148,7 @@
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/bcd.h>
+#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/system.h>
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index f2c55742e90c..af517c210383 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -28,6 +28,7 @@
#include <linux/ioctl.h>
#include <linux/delay.h>
#include <linux/bcd.h>
+#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/system.h>
diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c
index b72e6a91a639..34528da98817 100644
--- a/arch/cris/arch-v10/kernel/kgdb.c
+++ b/arch/cris/arch-v10/kernel/kgdb.c
@@ -569,12 +569,6 @@ gdb_cris_strtol (const char *s, char **endptr, int base)
return x;
}
-int
-double_this(int x)
-{
- return 2 * x;
-}
-
/********************************* Register image ****************************/
/* Copy the content of a register image into another. The size n is
the size of the register image. Due to struct assignment generation of
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 69e28b4057e8..0a675ce9e099 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -79,7 +79,7 @@ void hard_reset_now (void)
*/
unsigned long thread_saved_pc(struct task_struct *t)
{
- return (unsigned long)user_regs(t->thread_info)->irp;
+ return task_pt_regs(t)->irp;
}
static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)
@@ -128,7 +128,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
* remember that the task_struct doubles as the kernel stack for the task
*/
- childregs = user_regs(p->thread_info);
+ childregs = task_pt_regs(p);
*childregs = *regs; /* struct copy of pt_regs */
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index 6cbd34a27b90..f214f74f264e 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -37,7 +37,7 @@ inline long get_reg(struct task_struct *task, unsigned int regno)
if (regno == PT_USP)
return task->thread.usp;
else if (regno < PT_MAX)
- return ((unsigned long *)user_regs(task->thread_info))[regno];
+ return ((unsigned long *)task_pt_regs(task))[regno];
else
return 0;
}
@@ -51,7 +51,7 @@ inline int put_reg(struct task_struct *task, unsigned int regno,
if (regno == PT_USP)
task->thread.usp = data;
else if (regno < PT_MAX)
- ((unsigned long *)user_regs(task->thread_info))[regno] = data;
+ ((unsigned long *)task_pt_regs(task))[regno] = data;
else
return -1;
return 0;
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c
index 882be42114f7..843513102d3c 100644
--- a/arch/cris/arch-v32/kernel/process.c
+++ b/arch/cris/arch-v32/kernel/process.c
@@ -96,7 +96,7 @@ hard_reset_now(void)
*/
unsigned long thread_saved_pc(struct task_struct *t)
{
- return (unsigned long)user_regs(t->thread_info)->erp;
+ return task_pt_regs(t)->erp;
}
static void
@@ -148,7 +148,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
* fix it up. Note: the task_struct doubles as the kernel stack for the
* task.
*/
- childregs = user_regs(p->thread_info);
+ childregs = task_pt_regs(p);
*childregs = *regs; /* Struct copy of pt_regs. */
p->set_child_tid = p->clear_child_tid = NULL;
childregs->r10 = 0; /* Child returns 0 after a fork/clone. */
@@ -157,7 +157,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
* The TLS is in $mof beacuse it is the 5th argument to sys_clone.
*/
if (p->mm && (clone_flags & CLONE_SETTLS)) {
- p->thread_info->tls = regs->mof;
+ task_thread_info(p)->tls = regs->mof;
}
/* Put the switch stack right below the pt_regs. */
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 5528b83a622b..82cf2e3624a4 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -46,7 +46,7 @@ long get_reg(struct task_struct *task, unsigned int regno)
unsigned long ret;
if (regno <= PT_EDA)
- ret = ((unsigned long *)user_regs(task->thread_info))[regno];
+ ret = ((unsigned long *)task_pt_regs(task))[regno];
else if (regno == PT_USP)
ret = task->thread.usp;
else if (regno == PT_PPC)
@@ -65,13 +65,13 @@ long get_reg(struct task_struct *task, unsigned int regno)
int put_reg(struct task_struct *task, unsigned int regno, unsigned long data)
{
if (regno <= PT_EDA)
- ((unsigned long *)user_regs(task->thread_info))[regno] = data;
+ ((unsigned long *)task_pt_regs(task))[regno] = data;
else if (regno == PT_USP)
task->thread.usp = data;
else if (regno == PT_PPC) {
/* Write pseudo-PC to ERP only if changed. */
if (data != get_pseudo_pc(task))
- ((unsigned long *)user_regs(task->thread_info))[PT_ERP] = data;
+ task_pt_regs(task)->erp = data;
} else if (regno <= PT_MAX)
return put_debugreg(task->pid, regno, data);
else
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 13867f4fad16..da40d19a151e 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -113,10 +113,10 @@ smp_boot_one_cpu(int cpuid)
if (IS_ERR(idle))
panic("SMP: fork failed for CPU:%d", cpuid);
- idle->thread_info->cpu = cpuid;
+ task_thread_info(idle)->cpu = cpuid;
/* Information to the CPU that is about to boot */
- smp_init_current_idle_thread = idle->thread_info;
+ smp_init_current_idle_thread = task_thread_info(idle);
cpu_now_booting = cpuid;
/* Wait for CPU to come online */
diff --git a/arch/cris/arch-v32/mm/tlb.c b/arch/cris/arch-v32/mm/tlb.c
index b08a28bb58ab..9d75d7692303 100644
--- a/arch/cris/arch-v32/mm/tlb.c
+++ b/arch/cris/arch-v32/mm/tlb.c
@@ -198,9 +198,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
per_cpu(current_pgd, cpu) = next->pgd;
/* Switch context in the MMU. */
- if (tsk && tsk->thread_info)
+ if (tsk && task_thread_info(tsk))
{
- SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | tsk->thread_info->tls);
+ SPEC_REG_WR(SPEC_REG_PID, next->context.page_id | task_thread_info(tsk)->tls);
}
else
{
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 85833d704ebb..de39725da920 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -21,7 +21,6 @@
#include <asm/pgtable.h>
#include <asm/fasttimer.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern unsigned long get_cmos_time(void);
extern void __Udiv(void);
extern void __Umod(void);
@@ -33,7 +32,6 @@ extern void __lshrdi3(void);
extern void iounmap(volatile void * __iomem);
/* Platform dependent support */
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(loops_per_usec);
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 7c80afb10460..4ab3e87115b6 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -257,34 +257,6 @@ void flush_thread(void)
{
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-#if 0
- int i;
-
- /* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
- for (i = 0; i < 8; i++)
- dump->u_debugreg[i] = current->debugreg[i];
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->regs = *regs;
-
- dump->u_fpvalid = dump_fpu (regs, &dump->i387);
-#endif
-}
-
/* Fill in the fpu structure for a core dump. */
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
{
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index ec85c0d6c6da..60a617aff8ba 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -6,10 +6,6 @@ config FRV
bool
default y
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -274,6 +270,11 @@ config GPREL_DATA_NONE
endchoice
+config FRV_ONCPU_SERIAL
+ bool "Use on-CPU serial ports"
+ select SERIAL_8250
+ default y
+
config PCI
bool "Use PCI"
depends on MB93090_MB00
@@ -305,23 +306,7 @@ config RESERVE_DMA_COHERENT
source "drivers/pci/Kconfig"
-config PCMCIA
- tristate "Use PCMCIA"
- help
- Say Y here if you want to attach PCMCIA- or PC-cards to your FR-V
- board. These are credit-card size devices such as network cards,
- modems or hard drives often used with laptops computers. There are
- actually two varieties of these cards: the older 16 bit PCMCIA cards
- and the newer 32 bit CardBus cards. If you want to use CardBus
- cards, you need to say Y here and also to "CardBus support" below.
-
- To use your PC-cards, you will need supporting software from David
- Hinds pcmcia-cs package (see the file <file:Documentation/Changes>
- for location). Please also read the PCMCIA-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as modules, choose M here: the
- modules will be called pcmcia_core and ds.
+source "drivers/pcmcia/Kconfig"
#config MATH_EMULATION
# bool "Math emulation support (EXPERIMENTAL)"
diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug
index 0034b654995d..211f01bc4caa 100644
--- a/arch/frv/Kconfig.debug
+++ b/arch/frv/Kconfig.debug
@@ -2,32 +2,10 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
-config EARLY_PRINTK
- bool "Early printk"
- depends on EMBEDDED && DEBUG_KERNEL
- default n
- help
- Write kernel log output directly into the VGA buffer or to a serial
- port.
-
- This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized. For normal operation
- it is not recommended because it looks ugly and doesn't cooperate
- with klogd/syslogd or the X server. You should normally N here,
- unless you want to debug such a crash.
-
config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
depends on DEBUG_KERNEL
-config DEBUG_PAGEALLOC
- bool "Page alloc debugging"
- depends on DEBUG_KERNEL
- help
- Unmap pages from the kernel linear mapping after free_pages().
- This results in a large slowdown, but helps to find certain types
- of memory corruptions.
-
config GDBSTUB
bool "Remote GDB kernel debugging"
depends on DEBUG_KERNEL
diff --git a/arch/frv/Makefile b/arch/frv/Makefile
index 54046d2386f5..90c0fb8d9dc3 100644
--- a/arch/frv/Makefile
+++ b/arch/frv/Makefile
@@ -109,10 +109,10 @@ bootstrap:
$(Q)$(MAKEBOOT) bootstrap
archmrproper:
- $(Q)$(MAKE) -C arch/frv/boot mrproper
+ $(Q)$(MAKE) $(build)=arch/frv/boot mrproper
archclean:
- $(Q)$(MAKE) -C arch/frv/boot clean
+ $(Q)$(MAKE) $(build)=arch/frv/boot clean
archdep: scripts/mkdep symlinks
- $(Q)$(MAKE) -C arch/frv/boot dep
+ $(Q)$(MAKE) $(build)=arch/frv/boot dep
diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile
index d75e0d771366..5dfc93fd945a 100644
--- a/arch/frv/boot/Makefile
+++ b/arch/frv/boot/Makefile
@@ -57,10 +57,10 @@ initrd:
# installation
#
install: $(CONFIGURE) Image
- sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
+ sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)"
zinstall: $(CONFIGURE) zImage
- sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+ sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
#
# miscellany
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index 981c2c7dec0d..5a827b349b5e 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -20,3 +20,5 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
obj-$(CONFIG_PM) += pm.o cmode.o
obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
obj-$(CONFIG_SYSCTL) += sysctl.o
+obj-$(CONFIG_FUTEX) += futex.o
+obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index ad10ea595459..5f6548388b74 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1076,7 +1076,7 @@ __entry_work_notifysig:
LEDS 0x6410
ori.p gr4,#0,gr8
call do_notify_resume
- bra __entry_return_direct
+ bra __entry_resume_userspace
# perform syscall entry tracing
__syscall_trace_entry:
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 1a76d5247190..0f1c6cbc4f50 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -16,17 +16,16 @@
#include <asm/semaphore.h>
#include <asm/checksum.h>
#include <asm/hardirq.h>
-#include <asm/current.h>
+#include <asm/cacheflush.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern long __memcpy_user(void *dst, const void *src, size_t count);
+extern long __memset_user(void *dst, const void *src, size_t count);
/* platform dependent support */
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
@@ -50,7 +49,11 @@ EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
EXPORT_SYMBOL(__page_offset);
EXPORT_SYMBOL(__memcpy_user);
-EXPORT_SYMBOL(flush_dcache_page);
+EXPORT_SYMBOL(__memset_user);
+EXPORT_SYMBOL(frv_dcache_writeback);
+EXPORT_SYMBOL(frv_cache_invalidate);
+EXPORT_SYMBOL(frv_icache_invalidate);
+EXPORT_SYMBOL(frv_cache_wback_inv);
#ifndef CONFIG_MMU
EXPORT_SYMBOL(memory_start);
@@ -72,6 +75,9 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__outsl_ns);
+EXPORT_SYMBOL(__insl_ns);
+
EXPORT_SYMBOL(get_wchan);
#ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
@@ -80,14 +86,13 @@ EXPORT_SYMBOL(atomic_test_and_OR_mask);
EXPORT_SYMBOL(atomic_test_and_XOR_mask);
EXPORT_SYMBOL(atomic_add_return);
EXPORT_SYMBOL(atomic_sub_return);
-EXPORT_SYMBOL(__xchg_8);
-EXPORT_SYMBOL(__xchg_16);
EXPORT_SYMBOL(__xchg_32);
-EXPORT_SYMBOL(__cmpxchg_8);
-EXPORT_SYMBOL(__cmpxchg_16);
EXPORT_SYMBOL(__cmpxchg_32);
#endif
+EXPORT_SYMBOL(__debug_bug_printk);
+EXPORT_SYMBOL(__delay_loops_MHz);
+
/*
* libgcc functions - functions that are used internally by the
* compiler... (prototypes are not correct though, but that
@@ -101,6 +106,8 @@ extern void __divdi3(void);
extern void __lshrdi3(void);
extern void __moddi3(void);
extern void __muldi3(void);
+extern void __mulll(void);
+extern void __umulll(void);
extern void __negdi2(void);
extern void __ucmpdi2(void);
extern void __udivdi3(void);
@@ -116,8 +123,10 @@ EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__lshrdi3);
//EXPORT_SYMBOL(__moddi3);
EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulll);
+EXPORT_SYMBOL(__umulll);
EXPORT_SYMBOL(__negdi2);
-//EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__ucmpdi2);
//EXPORT_SYMBOL(__udivdi3);
//EXPORT_SYMBOL(__udivmoddi4);
//EXPORT_SYMBOL(__umoddi3);
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
new file mode 100644
index 000000000000..eae874a970c6
--- /dev/null
+++ b/arch/frv/kernel/futex.c
@@ -0,0 +1,242 @@
+/* futex.c: futex operations
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/futex.h>
+#include <asm/futex.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+
+/*
+ * the various futex operations; MMU fault checking is ignored under no-MMU
+ * conditions
+ */
+static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+{
+ int oldval, ret;
+
+ asm("0: \n"
+ " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
+ " ckeq icc3,cc7 \n"
+ "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
+ " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
+ "2: cst.p %3,%M0 ,cc3,#1 \n"
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
+ " beq icc3,#0,0b \n"
+ " setlos 0,%2 \n"
+ "3: \n"
+ ".subsection 2 \n"
+ "4: setlos %5,%2 \n"
+ " bra 3b \n"
+ ".previous \n"
+ ".section __ex_table,\"a\" \n"
+ " .balign 8 \n"
+ " .long 1b,4b \n"
+ " .long 2b,4b \n"
+ ".previous"
+ : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
+ : "3"(oparg), "i"(-EFAULT)
+ : "memory", "cc7", "cc3", "icc3"
+ );
+
+ *_oldval = oldval;
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+{
+ int oldval, ret;
+
+ asm("0: \n"
+ " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
+ " ckeq icc3,cc7 \n"
+ "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
+ " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
+ " add %1,%3,%3 \n"
+ "2: cst.p %3,%M0 ,cc3,#1 \n"
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
+ " beq icc3,#0,0b \n"
+ " setlos 0,%2 \n"
+ "3: \n"
+ ".subsection 2 \n"
+ "4: setlos %5,%2 \n"
+ " bra 3b \n"
+ ".previous \n"
+ ".section __ex_table,\"a\" \n"
+ " .balign 8 \n"
+ " .long 1b,4b \n"
+ " .long 2b,4b \n"
+ ".previous"
+ : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
+ : "3"(oparg), "i"(-EFAULT)
+ : "memory", "cc7", "cc3", "icc3"
+ );
+
+ *_oldval = oldval;
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+{
+ int oldval, ret;
+
+ asm("0: \n"
+ " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
+ " ckeq icc3,cc7 \n"
+ "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
+ " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
+ " or %1,%3,%3 \n"
+ "2: cst.p %3,%M0 ,cc3,#1 \n"
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
+ " beq icc3,#0,0b \n"
+ " setlos 0,%2 \n"
+ "3: \n"
+ ".subsection 2 \n"
+ "4: setlos %5,%2 \n"
+ " bra 3b \n"
+ ".previous \n"
+ ".section __ex_table,\"a\" \n"
+ " .balign 8 \n"
+ " .long 1b,4b \n"
+ " .long 2b,4b \n"
+ ".previous"
+ : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
+ : "3"(oparg), "i"(-EFAULT)
+ : "memory", "cc7", "cc3", "icc3"
+ );
+
+ *_oldval = oldval;
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+{
+ int oldval, ret;
+
+ asm("0: \n"
+ " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
+ " ckeq icc3,cc7 \n"
+ "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
+ " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
+ " and %1,%3,%3 \n"
+ "2: cst.p %3,%M0 ,cc3,#1 \n"
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
+ " beq icc3,#0,0b \n"
+ " setlos 0,%2 \n"
+ "3: \n"
+ ".subsection 2 \n"
+ "4: setlos %5,%2 \n"
+ " bra 3b \n"
+ ".previous \n"
+ ".section __ex_table,\"a\" \n"
+ " .balign 8 \n"
+ " .long 1b,4b \n"
+ " .long 2b,4b \n"
+ ".previous"
+ : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
+ : "3"(oparg), "i"(-EFAULT)
+ : "memory", "cc7", "cc3", "icc3"
+ );
+
+ *_oldval = oldval;
+ return ret;
+}
+
+static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+{
+ int oldval, ret;
+
+ asm("0: \n"
+ " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
+ " ckeq icc3,cc7 \n"
+ "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
+ " orcr cc7,cc7,cc3 \n" /* set CC3 to true */
+ " xor %1,%3,%3 \n"
+ "2: cst.p %3,%M0 ,cc3,#1 \n"
+ " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
+ " beq icc3,#0,0b \n"
+ " setlos 0,%2 \n"
+ "3: \n"
+ ".subsection 2 \n"
+ "4: setlos %5,%2 \n"
+ " bra 3b \n"
+ ".previous \n"
+ ".section __ex_table,\"a\" \n"
+ " .balign 8 \n"
+ " .long 1b,4b \n"
+ " .long 2b,4b \n"
+ ".previous"
+ : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
+ : "3"(oparg), "i"(-EFAULT)
+ : "memory", "cc7", "cc3", "icc3"
+ );
+
+ *_oldval = oldval;
+ return ret;
+}
+
+/*****************************************************************************/
+/*
+ * do the futex operations
+ */
+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:
+ ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ADD:
+ ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_OR:
+ ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ANDN:
+ ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_XOR:
+ ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ 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; break;
+ }
+ }
+
+ return ret;
+
+} /* end futex_atomic_op_inuser() */
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 8c524cdd2717..59580c59c62c 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -32,6 +32,7 @@
#include <linux/irq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <asm/atomic.h>
#include <asm/io.h>
@@ -178,6 +179,8 @@ void disable_irq_nosync(unsigned int irq)
spin_unlock_irqrestore(&level->lock, flags);
}
+EXPORT_SYMBOL(disable_irq_nosync);
+
/**
* disable_irq - disable an irq and wait for completion
* @irq: Interrupt to disable
@@ -204,6 +207,8 @@ void disable_irq(unsigned int irq)
#endif
}
+EXPORT_SYMBOL(disable_irq);
+
/**
* enable_irq - enable handling of an irq
* @irq: Interrupt to enable
@@ -268,6 +273,8 @@ void enable_irq(unsigned int irq)
spin_unlock_irqrestore(&level->lock, flags);
}
+EXPORT_SYMBOL(enable_irq);
+
/*****************************************************************************/
/*
* handles all normal device IRQ's
@@ -425,6 +432,8 @@ int request_irq(unsigned int irq,
return retval;
}
+EXPORT_SYMBOL(request_irq);
+
/**
* free_irq - free an interrupt
* @irq: Interrupt line to free
@@ -496,6 +505,8 @@ void free_irq(unsigned int irq, void *dev_id)
}
}
+EXPORT_SYMBOL(free_irq);
+
/*
* IRQ autodetection code..
*
@@ -519,6 +530,8 @@ unsigned long probe_irq_on(void)
return 0;
}
+EXPORT_SYMBOL(probe_irq_on);
+
/*
* Return a mask of triggered interrupts (this
* can handle only legacy ISA interrupts).
@@ -542,6 +555,8 @@ unsigned int probe_irq_mask(unsigned long xmask)
return 0;
}
+EXPORT_SYMBOL(probe_irq_mask);
+
/*
* Return the one interrupt that triggered (this can
* handle any interrupt source).
@@ -571,6 +586,8 @@ int probe_irq_off(unsigned long xmask)
return -1;
}
+EXPORT_SYMBOL(probe_irq_off);
+
/* this was setup_x86_irq but it seems pretty generic */
int setup_irq(unsigned int irq, struct irqaction *new)
{
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c
new file mode 100644
index 000000000000..850d168f69fc
--- /dev/null
+++ b/arch/frv/kernel/module.c
@@ -0,0 +1,80 @@
+/* module.c: FRV specific module loading bits
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ * - Derived from arch/i386/kernel/module.c, Copyright (C) 2001 Rusty Russell.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+
+ return vmalloc_exec(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+ /* FIXME: If module_region == mod->init_region, trim exception
+ table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
+ return -ENOEXEC;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *me)
+{
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name);
+ return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 712c3c24c954..f0b8fff3e733 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_legacy.h>
#include <linux/sched.h>
@@ -27,6 +28,7 @@
#include "local.h"
void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
extern void frv_change_cmode(int);
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 54a452136f00..0fff8a61ef2a 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -204,7 +204,7 @@ int copy_thread(int nr, unsigned long clone_flags,
regs0 = __kernel_frame0_ptr;
childregs0 = (struct pt_regs *)
- ((unsigned long) p->thread_info + THREAD_SIZE - USER_CONTEXT_SIZE);
+ (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE);
childregs = childregs0;
/* set up the userspace frame (the only place that the USP is stored) */
@@ -220,7 +220,7 @@ int copy_thread(int nr, unsigned long clone_flags,
*childregs = *regs;
childregs->sp = (unsigned long) childregs0;
childregs->next_frame = childregs0;
- childregs->gr15 = (unsigned long) p->thread_info;
+ childregs->gr15 = (unsigned long) task_thread_info(p);
childregs->gr29 = (unsigned long) p;
}
@@ -244,28 +244,6 @@ int copy_thread(int nr, unsigned long clone_flags,
} /* end copy_thread() */
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs *regs, struct user *dump)
-{
-#if 0
- /* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = user_stack(regs) & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->regs = *(struct user_context *) regs;
-#endif
-}
-
-/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(char *name, char **argv, char **envp)
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 767ebb55bd83..5908deae9607 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -787,6 +787,7 @@ void __init setup_arch(char **cmdline_p)
#endif
/* register those serial ports that are available */
+#ifdef CONFIG_FRV_ONCPU_SERIAL
#ifndef CONFIG_GDBSTUB_UART0
__reg(UART0_BASE + UART_IER * 8) = 0;
early_serial_setup(&__frv_uart0);
@@ -795,6 +796,7 @@ void __init setup_arch(char **cmdline_p)
__reg(UART1_BASE + UART_IER * 8) = 0;
early_serial_setup(&__frv_uart1);
#endif
+#endif
#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
/* we need to initialize the Flashrom device here since we might
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d4ccc0728dfe..679c1d5cc958 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -35,74 +35,22 @@ struct fdpic_func_descriptor {
unsigned long GOT;
};
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- __frame->gr8 = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(__frame, &saveset))
- /* return the signal number as the return value of this function
- * - this is an utterly evil hack. syscalls should not invoke do_signal()
- * as entry.S sets regs->gr8 to the return value of the system call
- * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
- * and call waitpid() if SIGCHLD needed discarding
- * - this only works on the i386 because it passes arguments to the signal
- * handler on the stack, and the return value in EAX is effectively
- * discarded
- */
- return __frame->gr8;
- }
-}
-
-asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- __frame->gr8 = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(__frame, &saveset))
- /* return the signal number as the return value of this function
- * - this is an utterly evil hack. syscalls should not invoke do_signal()
- * as entry.S sets regs->gr8 to the return value of the system call
- * - we can't just use sigpending() as we'd have to discard SIG_IGN signals
- * and call waitpid() if SIGCHLD needed discarding
- * - this only works on the i386 because it passes arguments to the signal
- * handler on the stack, and the return value in EAX is effectively
- * discarded
- */
- return __frame->gr8;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage int sys_sigaction(int sig,
@@ -276,13 +224,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
* Determine which stack to use..
*/
static inline void __user *get_sigframe(struct k_sigaction *ka,
- struct pt_regs *regs,
size_t frame_size)
{
unsigned long sp;
/* Default to using normal stack */
- sp = regs->sp;
+ sp = __frame->sp;
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
@@ -291,18 +238,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
}
return (void __user *) ((sp - frame_size) & ~7UL);
+
} /* end get_sigframe() */
/*****************************************************************************/
/*
*
*/
-static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
{
struct sigframe __user *frame;
int rsig;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -346,47 +294,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p
}
/* set up registers for signal handler */
- regs->sp = (unsigned long) frame;
- regs->lr = (unsigned long) &frame->retcode;
- regs->gr8 = sig;
+ __frame->sp = (unsigned long) frame;
+ __frame->lr = (unsigned long) &frame->retcode;
+ __frame->gr8 = sig;
if (get_personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor *) ka->sa.sa_handler;
- __get_user(regs->pc, &funcptr->text);
- __get_user(regs->gr15, &funcptr->GOT);
+ __get_user(__frame->pc, &funcptr->text);
+ __get_user(__frame->gr15, &funcptr->GOT);
} else {
- regs->pc = (unsigned long) ka->sa.sa_handler;
- regs->gr15 = 0;
+ __frame->pc = (unsigned long) ka->sa.sa_handler;
+ __frame->gr15 = 0;
}
set_fs(USER_DS);
+ /* the tracer may want to single-step inside the handler */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
#if DEBUG_SIG
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
- sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
+ sig, current->comm, current->pid, frame, __frame->pc,
+ frame->pretcode);
#endif
- return;
+ return 0;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
-
force_sig(SIGSEGV, current);
+ return -EFAULT;
+
} /* end setup_frame() */
/*****************************************************************************/
/*
*
*/
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set)
{
struct rt_sigframe __user *frame;
int rsig;
- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -409,7 +361,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user(0, &frame->uc.uc_flags) ||
__put_user(0, &frame->uc.uc_link) ||
__put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
- __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
+ __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
__put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
goto give_sigsegv;
@@ -440,34 +392,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
}
/* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
- regs->lr = (unsigned long) &frame->retcode;
- regs->gr8 = sig;
- regs->gr9 = (unsigned long) &frame->info;
+ __frame->sp = (unsigned long) frame;
+ __frame->lr = (unsigned long) &frame->retcode;
+ __frame->gr8 = sig;
+ __frame->gr9 = (unsigned long) &frame->info;
if (get_personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor *funcptr =
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
- __get_user(regs->pc, &funcptr->text);
- __get_user(regs->gr15, &funcptr->GOT);
+ __get_user(__frame->pc, &funcptr->text);
+ __get_user(__frame->gr15, &funcptr->GOT);
} else {
- regs->pc = (unsigned long) ka->sa.sa_handler;
- regs->gr15 = 0;
+ __frame->pc = (unsigned long) ka->sa.sa_handler;
+ __frame->gr15 = 0;
}
set_fs(USER_DS);
+ /* the tracer may want to single-step inside the handler */
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
+
#if DEBUG_SIG
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
- sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
+ sig, current->comm, current->pid, frame, __frame->pc,
+ frame->pretcode);
#endif
- return;
+ return 0;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
+ return -EFAULT;
} /* end setup_rt_frame() */
@@ -475,43 +431,51 @@ give_sigsegv:
/*
* OK, we're invoking a handler
*/
-static void handle_signal(unsigned long sig, siginfo_t *info,
- struct k_sigaction *ka, sigset_t *oldset,
- struct pt_regs *regs)
+static int handle_signal(unsigned long sig, siginfo_t *info,
+ struct k_sigaction *ka, sigset_t *oldset)
{
+ int ret;
+
/* Are we from a system call? */
- if (in_syscall(regs)) {
+ if (in_syscall(__frame)) {
/* If so, check system call restarting.. */
- switch (regs->gr8) {
+ switch (__frame->gr8) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
- regs->gr8 = -EINTR;
+ __frame->gr8 = -EINTR;
break;
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
- regs->gr8 = -EINTR;
+ __frame->gr8 = -EINTR;
break;
}
+
/* fallthrough */
case -ERESTARTNOINTR:
- regs->gr8 = regs->orig_gr8;
- regs->pc -= 4;
+ __frame->gr8 = __frame->orig_gr8;
+ __frame->pc -= 4;
}
}
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset);
else
- setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(sig, ka, oldset);
+
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+
+ return ret;
- 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);
} /* end handle_signal() */
/*****************************************************************************/
@@ -520,10 +484,11 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(void)
{
struct k_sigaction ka;
siginfo_t info;
+ sigset_t *oldset;
int signr;
/*
@@ -532,45 +497,63 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* kernel mode. Just return without doing anything
* if so.
*/
- if (!user_mode(regs))
- return 1;
+ if (!user_mode(__frame))
+ return;
if (try_to_freeze())
goto no_signal;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
if (signr > 0) {
- handle_signal(signr, &info, &ka, oldset, regs);
- return 1;
+ if (handle_signal(signr, &info, &ka, oldset) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
}
- no_signal:
+no_signal:
/* Did we come from a system call? */
- if (regs->syscallno >= 0) {
+ if (__frame->syscallno >= 0) {
/* Restart the system call - no handlers present */
- if (regs->gr8 == -ERESTARTNOHAND ||
- regs->gr8 == -ERESTARTSYS ||
- regs->gr8 == -ERESTARTNOINTR) {
- regs->gr8 = regs->orig_gr8;
- regs->pc -= 4;
- }
+ switch (__frame->gr8) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ __frame->gr8 = __frame->orig_gr8;
+ __frame->pc -= 4;
+ break;
- if (regs->gr8 == -ERESTART_RESTARTBLOCK){
- regs->gr8 = __NR_restart_syscall;
- regs->pc -= 4;
+ case -ERESTART_RESTARTBLOCK:
+ __frame->gr8 = __NR_restart_syscall;
+ __frame->pc -= 4;
+ break;
}
}
- return 0;
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
+
} /* end do_signal() */
/*****************************************************************************/
/*
* notification of userspace execution resumption
- * - triggered by current->work.notify_resume
+ * - triggered by the TIF_WORK_MASK flags
*/
asmlinkage void do_notify_resume(__u32 thread_info_flags)
{
@@ -579,7 +562,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
clear_thread_flag(TIF_SINGLESTEP);
/* deal with pending signal delivery */
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(__frame, NULL);
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal();
} /* end do_notify_resume() */
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 2e9741227b73..24cf85f89e40 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -189,6 +189,8 @@ void do_gettimeofday(struct timeval *tv)
tv->tv_usec = usec;
}
+EXPORT_SYMBOL(do_gettimeofday);
+
int do_settimeofday(struct timespec *tv)
{
time_t wtm_sec, sec = tv->tv_sec;
@@ -218,6 +220,7 @@ int do_settimeofday(struct timespec *tv)
clock_was_set();
return 0;
}
+
EXPORT_SYMBOL(do_settimeofday);
/*
diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c
index 89073cae4b5d..9eb84b2e6abc 100644
--- a/arch/frv/kernel/traps.c
+++ b/arch/frv/kernel/traps.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/linkage.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/setup.h>
#include <asm/fpu.h>
@@ -250,6 +251,8 @@ void dump_stack(void)
show_stack(NULL, NULL);
}
+EXPORT_SYMBOL(dump_stack);
+
void show_stack(struct task_struct *task, unsigned long *sp)
{
}
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c
index f3fd58a5bc4a..9b751c0f0e84 100644
--- a/arch/frv/kernel/uaccess.c
+++ b/arch/frv/kernel/uaccess.c
@@ -10,6 +10,7 @@
*/
#include <linux/mm.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
/*****************************************************************************/
@@ -58,8 +59,11 @@ long strncpy_from_user(char *dst, const char *src, long count)
memset(p, 0, count); /* clear remainder of buffer [security] */
return err;
+
} /* end strncpy_from_user() */
+EXPORT_SYMBOL(strncpy_from_user);
+
/*****************************************************************************/
/*
* Return the size of a string (including the ending 0)
@@ -92,4 +96,7 @@ long strnlen_user(const char *src, long count)
}
return p - src + 1; /* return length including NUL */
+
} /* end strnlen_user() */
+
+EXPORT_SYMBOL(strnlen_user);
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index fceafd2cc202..f474534ba78a 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -112,6 +112,7 @@ SECTIONS
#endif
)
SCHED_TEXT
+ LOCK_TEXT
*(.fixup)
*(.gnu.warning)
*(.exitcall.exit)
diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile
index 19be2626d5e6..08be305c9f44 100644
--- a/arch/frv/lib/Makefile
+++ b/arch/frv/lib/Makefile
@@ -3,6 +3,6 @@
#
lib-y := \
- __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o \
+ __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
checksum.o memcpy.o memset.o atomic-ops.o \
outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
diff --git a/arch/frv/lib/__ucmpdi2.S b/arch/frv/lib/__ucmpdi2.S
new file mode 100644
index 000000000000..d892f16ffaa9
--- /dev/null
+++ b/arch/frv/lib/__ucmpdi2.S
@@ -0,0 +1,45 @@
+/* __ucmpdi2.S: 64-bit unsigned compare
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+ .text
+ .p2align 4
+
+###############################################################################
+#
+# int __ucmpdi2(unsigned long long a [GR8:GR9],
+# unsigned long long b [GR10:GR11])
+#
+# - returns 0, 1, or 2 as a <, =, > b respectively.
+#
+###############################################################################
+ .globl __ucmpdi2
+ .type __ucmpdi2,@function
+__ucmpdi2:
+ or.p gr8,gr0,gr4
+ subcc gr8,gr10,gr0,icc0
+ setlos.p #0,gr8
+ bclr icc0,#2 ; a.msw < b.msw
+
+ setlos.p #2,gr8
+ bhilr icc0,#0 ; a.msw > b.msw
+
+ subcc.p gr9,gr11,gr0,icc1
+ setlos #0,gr8
+ setlos.p #2,gr9
+ setlos #1,gr7
+ cknc icc1,cc6
+ cor.p gr9,gr0,gr8, cc6,#1
+ cckls icc1,cc4, cc6,#1
+ andcr cc6,cc4,cc4
+ cor gr7,gr0,gr8, cc4,#1
+ bralr
+ .size __ucmpdi2, .-__ucmpdi2
diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S
index b03d510a89e4..545cd325ac57 100644
--- a/arch/frv/lib/atomic-ops.S
+++ b/arch/frv/lib/atomic-ops.S
@@ -129,48 +129,6 @@ atomic_sub_return:
###############################################################################
#
-# uint8_t __xchg_8(uint8_t i, uint8_t *v)
-#
-###############################################################################
- .globl __xchg_8
- .type __xchg_8,@function
-__xchg_8:
- or.p gr8,gr8,gr10
-0:
- orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
- ckeq icc3,cc7
- ldub.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
- orcr cc7,cc7,cc3 /* set CC3 to true */
- cstb.p gr10,@(gr9,gr0) ,cc3,#1
- corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
- beq icc3,#0,0b
- bralr
-
- .size __xchg_8, .-__xchg_8
-
-###############################################################################
-#
-# uint16_t __xchg_16(uint16_t i, uint16_t *v)
-#
-###############################################################################
- .globl __xchg_16
- .type __xchg_16,@function
-__xchg_16:
- or.p gr8,gr8,gr10
-0:
- orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
- ckeq icc3,cc7
- lduh.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
- orcr cc7,cc7,cc3 /* set CC3 to true */
- csth.p gr10,@(gr9,gr0) ,cc3,#1
- corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
- beq icc3,#0,0b
- bralr
-
- .size __xchg_16, .-__xchg_16
-
-###############################################################################
-#
# uint32_t __xchg_32(uint32_t i, uint32_t *v)
#
###############################################################################
@@ -192,56 +150,6 @@ __xchg_32:
###############################################################################
#
-# uint8_t __cmpxchg_8(uint8_t *v, uint8_t test, uint8_t new)
-#
-###############################################################################
- .globl __cmpxchg_8
- .type __cmpxchg_8,@function
-__cmpxchg_8:
- or.p gr8,gr8,gr11
-0:
- orcc gr0,gr0,gr0,icc3
- ckeq icc3,cc7
- ldub.p @(gr11,gr0),gr8
- orcr cc7,cc7,cc3
- sub gr8,gr9,gr7
- sllicc gr7,#24,gr0,icc0
- bne icc0,#0,1f
- cstb.p gr10,@(gr11,gr0) ,cc3,#1
- corcc gr29,gr29,gr0 ,cc3,#1
- beq icc3,#0,0b
-1:
- bralr
-
- .size __cmpxchg_8, .-__cmpxchg_8
-
-###############################################################################
-#
-# uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new)
-#
-###############################################################################
- .globl __cmpxchg_16
- .type __cmpxchg_16,@function
-__cmpxchg_16:
- or.p gr8,gr8,gr11
-0:
- orcc gr0,gr0,gr0,icc3
- ckeq icc3,cc7
- lduh.p @(gr11,gr0),gr8
- orcr cc7,cc7,cc3
- sub gr8,gr9,gr7
- sllicc gr7,#16,gr0,icc0
- bne icc0,#0,1f
- csth.p gr10,@(gr11,gr0) ,cc3,#1
- corcc gr29,gr29,gr0 ,cc3,#1
- beq icc3,#0,0b
-1:
- bralr
-
- .size __cmpxchg_16, .-__cmpxchg_16
-
-###############################################################################
-#
# uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new)
#
###############################################################################
diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c
index 7bf5bd6cac8a..20e7dfc474ef 100644
--- a/arch/frv/lib/checksum.c
+++ b/arch/frv/lib/checksum.c
@@ -33,6 +33,7 @@
#include <net/checksum.h>
#include <asm/checksum.h>
+#include <linux/module.h>
static inline unsigned short from32to16(unsigned long x)
{
@@ -115,34 +116,52 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
return result;
}
+EXPORT_SYMBOL(csum_partial);
+
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
unsigned short ip_compute_csum(const unsigned char * buff, int len)
{
- return ~do_csum(buff,len);
+ return ~do_csum(buff, len);
}
+EXPORT_SYMBOL(ip_compute_csum);
+
/*
* copy from fs while checksumming, otherwise like csum_partial
*/
-
unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
+csum_partial_copy_from_user(const char __user *src, char *dst,
+ int len, int sum, int *csum_err)
{
- if (csum_err) *csum_err = 0;
- memcpy(dst, src, len);
+ int rem;
+
+ if (csum_err)
+ *csum_err = 0;
+
+ rem = copy_from_user(dst, src, len);
+ if (rem != 0) {
+ if (csum_err)
+ *csum_err = -EFAULT;
+ memset(dst + len - rem, 0, rem);
+ len = rem;
+ }
+
return csum_partial(dst, len, sum);
}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
/*
* copy from ds while checksumming, otherwise like csum_partial
*/
-
unsigned int
csum_partial_copy(const char *src, char *dst, int len, int sum)
{
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
}
+
+EXPORT_SYMBOL(csum_partial_copy);
diff --git a/arch/frv/mb93090-mb00/Makefile b/arch/frv/mb93090-mb00/Makefile
index 3faf0f8cf9b5..76595e870733 100644
--- a/arch/frv/mb93090-mb00/Makefile
+++ b/arch/frv/mb93090-mb00/Makefile
@@ -3,7 +3,7 @@
#
ifeq "$(CONFIG_PCI)" "y"
-obj-y := pci-frv.o pci-irq.o pci-vdk.o
+obj-y := pci-frv.o pci-irq.o pci-vdk.o pci-iomap.o
ifeq "$(CONFIG_MMU)" "y"
obj-y += pci-dma.o
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c
index 2082a9647f4f..4985466b1a7c 100644
--- a/arch/frv/mb93090-mb00/pci-dma-nommu.c
+++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c
@@ -83,6 +83,8 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand
return NULL;
}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
{
struct dma_alloc_record *rec;
@@ -102,6 +104,8 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_
BUG();
}
+EXPORT_SYMBOL(dma_free_coherent);
+
/*
* Map a single buffer of the indicated size for DMA in streaming mode.
* The 32-bit bus address to use is returned.
@@ -120,6 +124,8 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
return virt_to_bus(ptr);
}
+EXPORT_SYMBOL(dma_map_single);
+
/*
* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
@@ -150,3 +156,5 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
return nents;
}
+
+EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 86fbdadc51b6..671ce1e8434f 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -28,11 +28,15 @@ void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_hand
return ret;
}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
{
consistent_free(vaddr);
}
+EXPORT_SYMBOL(dma_free_coherent);
+
/*
* Map a single buffer of the indicated size for DMA in streaming mode.
* The 32-bit bus address to use is returned.
@@ -51,6 +55,8 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
return virt_to_bus(ptr);
}
+EXPORT_SYMBOL(dma_map_single);
+
/*
* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
@@ -96,6 +102,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
return nents;
}
+EXPORT_SYMBOL(dma_map_sg);
+
dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction direction)
{
@@ -103,3 +111,5 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long off
flush_dcache_page(page);
return (dma_addr_t) page_to_phys(page) + offset;
}
+
+EXPORT_SYMBOL(dma_map_page);
diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
index 83e5489cf039..0a26bf6f1cd4 100644
--- a/arch/frv/mb93090-mb00/pci-frv.c
+++ b/arch/frv/mb93090-mb00/pci-frv.c
@@ -142,9 +142,7 @@ static void __init pcibios_allocate_resources(int pass)
u16 command;
struct resource *r, *pr;
- while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
- dev != NULL
- ) {
+ for_each_pci_dev(dev) {
pci_read_config_word(dev, PCI_COMMAND, &command);
for(idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
@@ -188,9 +186,7 @@ static void __init pcibios_assign_resources(void)
int idx;
struct resource *r;
- while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
- dev != NULL
- ) {
+ for_each_pci_dev(dev) {
int class = dev->class >> 8;
/* Don't touch classless devices and host bridges */
diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c
new file mode 100644
index 000000000000..068fa04bd527
--- /dev/null
+++ b/arch/frv/mb93090-mb00/pci-iomap.c
@@ -0,0 +1,29 @@
+/* pci-iomap.c: description
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+ return NULL;
+
+ if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM))
+ return (void __iomem *) start;
+
+ return NULL;
+}
+
+EXPORT_SYMBOL(pci_iomap);
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 24622d89b1ca..c4a1144c98b0 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -48,9 +48,7 @@ void __init pcibios_fixup_irqs(void)
struct pci_dev *dev = NULL;
uint8_t line, pin;
- while (dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev),
- dev != NULL
- ) {
+ for_each_pci_dev(dev) {
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin) {
dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
diff --git a/arch/frv/mm/cache-page.c b/arch/frv/mm/cache-page.c
index 683b5e344318..0261cbe153b5 100644
--- a/arch/frv/mm/cache-page.c
+++ b/arch/frv/mm/cache-page.c
@@ -11,6 +11,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/module.h>
#include <asm/pgalloc.h>
/*****************************************************************************/
@@ -38,6 +39,8 @@ void flush_dcache_page(struct page *page)
} /* end flush_dcache_page() */
+EXPORT_SYMBOL(flush_dcache_page);
+
/*****************************************************************************/
/*
* ICI takes a virtual address and the page may not currently have one
@@ -64,3 +67,5 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
}
} /* end flush_icache_user_range() */
+
+EXPORT_SYMBOL(flush_icache_user_range);
diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c
index 41be1128dc64..caacf030ac75 100644
--- a/arch/frv/mm/extable.c
+++ b/arch/frv/mm/extable.c
@@ -43,7 +43,7 @@ static inline unsigned long search_one_table(const struct exception_table_entry
*/
unsigned long search_exception_table(unsigned long pc)
{
- unsigned long ret = 0;
+ const struct exception_table_entry *extab;
/* determine if the fault lay during a memcpy_user or a memset_user */
if (__frame->lr == (unsigned long) &__memset_user_error_lr &&
@@ -55,9 +55,10 @@ unsigned long search_exception_table(unsigned long pc)
*/
return (unsigned long) &__memset_user_error_handler;
}
- else if (__frame->lr == (unsigned long) &__memcpy_user_error_lr &&
- (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end
- ) {
+
+ if (__frame->lr == (unsigned long) &__memcpy_user_error_lr &&
+ (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end
+ ) {
/* the fault occurred in a protected memset
* - we search for the return address (in LR) instead of the program counter
* - it was probably during a copy_to/from_user()
@@ -65,27 +66,10 @@ unsigned long search_exception_table(unsigned long pc)
return (unsigned long) &__memcpy_user_error_handler;
}
-#ifndef CONFIG_MODULES
- /* there is only the kernel to search. */
- ret = search_one_table(__start___ex_table, __stop___ex_table - 1, pc);
- return ret;
-
-#else
- /* the kernel is the last "module" -- no need to treat it special */
- unsigned long flags;
- struct module *mp;
+ extab = search_exception_tables(pc);
+ if (extab)
+ return extab->fixup;
- spin_lock_irqsave(&modlist_lock, flags);
-
- for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
- continue;
- ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, pc);
- if (ret)
- break;
- }
+ return 0;
- spin_unlock_irqrestore(&modlist_lock, flags);
- return ret;
-#endif
} /* end search_exception_table() */
diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c
index 7dc8fbf3af97..7f77db7fabc7 100644
--- a/arch/frv/mm/highmem.c
+++ b/arch/frv/mm/highmem.c
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/highmem.h>
+#include <linux/module.h>
void *kmap(struct page *page)
{
@@ -18,6 +19,8 @@ void *kmap(struct page *page)
return kmap_high(page);
}
+EXPORT_SYMBOL(kmap);
+
void kunmap(struct page *page)
{
if (in_interrupt())
@@ -27,7 +30,12 @@ void kunmap(struct page *page)
kunmap_high(page);
}
+EXPORT_SYMBOL(kunmap);
+
struct page *kmap_atomic_to_page(void *ptr)
{
return virt_to_page(ptr);
}
+
+
+EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 26698a49f153..80940d712acf 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -21,10 +21,6 @@ config FPU
bool
default n
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/h8300/kernel/gpio.c b/arch/h8300/kernel/gpio.c
index 795682b873e2..d195568ca8a2 100644
--- a/arch/h8300/kernel/gpio.c
+++ b/arch/h8300/kernel/gpio.c
@@ -122,7 +122,7 @@ int h8300_get_gpio_dir(int port_bit)
static char *port_status(int portno)
{
static char result[10];
- const static char io[2]={'I','O'};
+ static const char io[2]={'I','O'};
char *rp;
int c;
unsigned char used,ddr;
@@ -143,7 +143,7 @@ static int gpio_proc_read(char *buf, char **start, off_t offset,
int len, int *unused_i, void *unused_v)
{
int c,outlen;
- const static char port_name[]="123456789ABCDEFGH";
+ static const char port_name[]="123456789ABCDEFGH";
outlen = 0;
for (c = 0; c < MAX_PORT; c++) {
if (ddrs[c] == NULL)
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index 5a630233112f..5cc76efaf7aa 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -22,11 +22,8 @@
//asmlinkage long long __lshrdi3 (long long, int);
extern char h8300_debug_device[];
-extern void dump_thread(struct pt_regs *, struct user *);
-
/* platform dependent support */
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
@@ -103,10 +100,6 @@ EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(__umoddi3);
EXPORT_SYMBOL(__umodsi3);
-#ifdef MAGIC_ROM_PTR
-EXPORT_SYMBOL(is_in_rom);
-#endif
-
EXPORT_SYMBOL(h8300_reserved_gpio);
EXPORT_SYMBOL(h8300_free_gpio);
EXPORT_SYMBOL(h8300_set_gpio_dir);
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index fe21adf3e75e..ed79ae20e88d 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -195,7 +195,7 @@ int copy_thread(int nr, unsigned long clone_flags,
{
struct pt_regs * childregs;
- childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+ childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
*childregs = *regs;
childregs->retpc = (unsigned long) ret_from_fork;
@@ -208,34 +208,6 @@ int copy_thread(int nr, unsigned long clone_flags,
}
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-/* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk +
- (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
-
- dump->u_ar0 = (struct user_regs_struct *)(((int)(&dump->regs)) -((int)(dump)));
- dump->regs.er0 = regs->er0;
- dump->regs.er1 = regs->er1;
- dump->regs.er2 = regs->er2;
- dump->regs.er3 = regs->er3;
- dump->regs.er4 = regs->er4;
- dump->regs.er5 = regs->er5;
- dump->regs.er6 = regs->er6;
- dump->regs.orig_er0 = regs->orig_er0;
- dump->regs.ccr = regs->ccr;
- dump->regs.pc = regs->pc;
-}
-
-/*
* sys_execve() executes a new program.
*/
asmlinkage int sys_execve(char *name, char **argv, char **envp,int dummy,...)
diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c
index f4ddece3216f..81eace93f867 100644
--- a/arch/h8300/mm/memory.c
+++ b/arch/h8300/mm/memory.c
@@ -55,16 +55,3 @@ unsigned long kernel_map(unsigned long paddr, unsigned long size,
return paddr;
}
-#ifdef MAGIC_ROM_PTR
-
-int is_in_rom(unsigned long addr)
-{
- /* Anything not in operational RAM is returned as in rom! */
- if (addr < _ramstart || addr >= _ramend)
- return 1;
- else
- return 0;
-}
-
-#endif
-
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
index 6ac93c05a1ae..746b1ae672a1 100644
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -98,7 +98,7 @@ struct optable {
.type = jmp, \
}
-const static struct optable optable_0[] = {
+static const struct optable optable_0[] = {
OPTABLE(0x00,0xff, 1,none), /* 0x00 */
OPTABLE(0x01,0xff,-1,none), /* 0x01 */
OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
@@ -131,31 +131,31 @@ const static struct optable optable_0[] = {
OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
};
-const static struct optable optable_1[] = {
+static const struct optable optable_1[] = {
OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
};
-const static struct optable optable_2[] = {
+static const struct optable optable_2[] = {
OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
};
-const static struct optable optable_3[] = {
+static const struct optable optable_3[] = {
OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
};
-const static struct optable optable_4[] = {
+static const struct optable optable_4[] = {
OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
};
-const static struct optables_list {
+static const struct optables_list {
const struct optable *ptr;
int size;
} optables[] = {
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index 5441cdd12a39..f6ed663bdde0 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -52,7 +52,7 @@ struct irq_pins {
unsigned char bit_no;
};
/* ISTR = 0 */
-const static struct irq_pins irq_assign_table0[16]={
+static const struct irq_pins irq_assign_table0[16]={
{H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
{H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
{H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
@@ -63,7 +63,7 @@ const static struct irq_pins irq_assign_table0[16]={
{H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
};
/* ISTR = 1 */
-const static struct irq_pins irq_assign_table1[16]={
+static const struct irq_pins irq_assign_table1[16]={
{H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
{H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
{H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
diff --git a/arch/h8300/platform/h8s/ints_h8s.c b/arch/h8300/platform/h8s/ints_h8s.c
index f53de493e3e8..8268dfd12f1f 100644
--- a/arch/h8300/platform/h8s/ints_h8s.c
+++ b/arch/h8300/platform/h8s/ints_h8s.c
@@ -42,7 +42,7 @@ struct irq_pins {
unsigned char bit_no;
} __attribute__((aligned(1),packed));
/* ISTR = 0 */
-const static struct irq_pins irq_assign_table0[16]={
+static const struct irq_pins irq_assign_table0[16]={
{H8300_GPIO_P5,H8300_GPIO_B0},{H8300_GPIO_P5,H8300_GPIO_B1},
{H8300_GPIO_P5,H8300_GPIO_B2},{H8300_GPIO_P5,H8300_GPIO_B3},
{H8300_GPIO_P5,H8300_GPIO_B4},{H8300_GPIO_P5,H8300_GPIO_B5},
@@ -53,7 +53,7 @@ const static struct irq_pins irq_assign_table0[16]={
{H8300_GPIO_PF,H8300_GPIO_B1},{H8300_GPIO_PF,H8300_GPIO_B2},
};
/* ISTR = 1 */
-const static struct irq_pins irq_assign_table1[16]={
+static const struct irq_pins irq_assign_table1[16]={
{H8300_GPIO_P8,H8300_GPIO_B0},{H8300_GPIO_P8,H8300_GPIO_B1},
{H8300_GPIO_P8,H8300_GPIO_B2},{H8300_GPIO_P8,H8300_GPIO_B3},
{H8300_GPIO_P8,H8300_GPIO_B4},{H8300_GPIO_P8,H8300_GPIO_B5},
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 6004bb0795e0..cbde675bc95c 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -29,10 +29,6 @@ config MMU
config SBUS
bool
-config UID16
- bool
- default y
-
config GENERIC_ISA_DMA
bool
default y
@@ -45,8 +41,21 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config DMI
+ bool
+ default y
+
source "init/Kconfig"
+config DOUBLEFAULT
+ default y
+ bool "Enable doublefault exception handler" if EMBEDDED
+ help
+ This option allows trapping of rare doublefault exceptions that
+ would otherwise cause a system to silently reboot. Disabling this
+ option saves about 4k and might cause you much additional grey
+ hair.
+
menu "Processor type and features"
choice
@@ -464,7 +473,6 @@ 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"
@@ -493,6 +501,10 @@ config HAVE_ARCH_ALLOC_REMAP
depends on NUMA
default y
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+ depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC)
+
config ARCH_DISCONTIGMEM_ENABLE
def_bool y
depends on NUMA
@@ -503,7 +515,8 @@ config ARCH_DISCONTIGMEM_DEFAULT
config ARCH_SPARSEMEM_ENABLE
def_bool y
- depends on NUMA
+ depends on (NUMA || (X86_PC && EXPERIMENTAL))
+ select SPARSEMEM_STATIC
config ARCH_SELECT_MEMORY_MODEL
def_bool y
@@ -626,10 +639,6 @@ config REGPARM
and passes the first three arguments of a function call in registers.
This will probably break binary only modules.
- This feature is only enabled for gcc-3.0 and later - earlier compilers
- generate incorrect output with certain kernel constructs when
- -mregparm=3 is used.
-
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
@@ -649,17 +658,6 @@ config SECCOMP
source kernel/Kconfig.hz
-config PHYSICAL_START
- hex "Physical address where the kernel is loaded" if EMBEDDED
- default "0x100000"
- help
- This gives the physical address where the kernel is loaded.
- Primarily used in the case of kexec on panic where the
- fail safe kernel needs to run at a different address than
- the panic-ed kernel.
-
- Don't change this unless you know what you are doing.
-
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on EXPERIMENTAL
@@ -679,11 +677,40 @@ config KEXEC
config CRASH_DUMP
bool "kernel crash dumps (EXPERIMENTAL)"
- depends on EMBEDDED
depends on EXPERIMENTAL
depends on HIGHMEM
help
Generate crash dump after being started by kexec.
+
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+
+ default "0x1000000" if CRASH_DUMP
+ default "0x100000"
+ help
+ This gives the physical address where the kernel is loaded. Normally
+ for regular kernels this value is 0x100000 (1MB). But in the case
+ of kexec on panic the fail safe kernel needs to run at a different
+ address than the panic-ed kernel. This option is used to set the load
+ address for kernels used to capture crash dump on being kexec'ed
+ after panic. The default value for crash dump kernels is
+ 0x1000000 (16MB). This can also be set based on the "X" value as
+ specified in the "crashkernel=YM@XM" command line boot parameter
+ passed to the panic-ed kernel. Typically this parameter is set as
+ crashkernel=64M@16M. Please take a look at
+ Documentation/kdump/kdump.txt for more details about crash dumps.
+
+ Don't change this unless you know what you are doing.
+
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+ depends on SMP && HOTPLUG && EXPERIMENTAL
+ ---help---
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu.
+
+ Say N.
+
endmenu
@@ -699,7 +726,7 @@ depends on PM && !X86_VISWS
config APM
tristate "APM (Advanced Power Management) BIOS support"
- depends on PM && PM_LEGACY
+ depends on PM
---help---
APM is a BIOS specification for saving power using several different
techniques. This is mostly useful for battery powered laptops with
@@ -970,15 +997,6 @@ config SCx200
This support is also available as a module. If compiled as a
module, it will be called scx200.
-config HOTPLUG_CPU
- bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
- depends on SMP && HOTPLUG && EXPERIMENTAL
- ---help---
- Say Y here to experiment with turning CPUs off and on. CPUs
- can be controlled through /sys/devices/system/cpu.
-
- Say N.
-
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
@@ -1055,3 +1073,7 @@ config X86_TRAMPOLINE
bool
depends on X86_SMP || (X86_VOYAGER && SMP)
default y
+
+config KTIME_SCALAR
+ bool
+ default y
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index 53bbb3c008ee..79603b3471f9 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -39,6 +39,7 @@ config M386
- "Winchip-2" for IDT Winchip 2.
- "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
+ - "Geode GX/LX" For AMD Geode GX and LX processors.
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
- "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
@@ -171,6 +172,11 @@ config MGEODEGX1
help
Select this for a Geode GX1 (Cyrix MediaGX) chip.
+config MGEODE_LX
+ bool "Geode GX/LX"
+ help
+ Select this for AMD Geode GX and LX processors.
+
config MCYRIXIII
bool "CyrixIII/VIA-C3"
help
@@ -220,8 +226,8 @@ config X86_XADD
config X86_L1_CACHE_SHIFT
int
default "7" if MPENTIUM4 || X86_GENERIC
- default "4" if X86_ELAN || M486 || M386
- default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
+ default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
+ default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
default "6" if MK7 || MK8 || MPENTIUMM
config RWSEM_GENERIC_SPINLOCK
@@ -290,12 +296,12 @@ config X86_INTEL_USERCOPY
config X86_USE_PPRO_CHECKSUM
bool
- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX
default y
config X86_USE_3DNOW
bool
- depends on MCYRIXIII || MK7
+ depends on MCYRIXIII || MK7 || MGEODE_LX
default y
config X86_OOSTORE
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index c48b424dd640..bf32ecc9ad04 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -42,6 +42,16 @@ config DEBUG_PAGEALLOC
This results in a large slowdown, but helps to find certain types
of memory corruptions.
+config DEBUG_RODATA
+ bool "Write protect kernel read-only data structures"
+ depends on DEBUG_KERNEL
+ help
+ Mark the kernel read-only data as write-protected in the pagetables,
+ in order to catch accidental (and incorrect) writes to such const
+ data. This option may have a slight performance impact because a
+ portion of the kernel code won't be covered by a 2MB TLB anymore.
+ If in doubt, say "N".
+
config 4KSTACKS
bool "Use 4Kb for kernel stacks instead of 8Kb"
depends on DEBUG_KERNEL
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index d121ea18460f..36bef6543ac1 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -37,14 +37,11 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
# CPU-specific tuning. Anything which can be shared with UML should go here.
include $(srctree)/arch/i386/Makefile.cpu
-# -mregparm=3 works ok on gcc-3.0 and later
-#
-GCC_VERSION := $(call cc-version)
-cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+cflags-$(CONFIG_REGPARM) += -mregparm=3
-# Disable unit-at-a-time mode, it makes gcc use a lot more stack
-# due to the lack of sharing of stacklots.
-CFLAGS += $(call cc-option,-fno-unit-at-a-time)
+# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+# a lot more stack due to the lack of sharing of stacklots:
+CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
CFLAGS += $(cflags-y)
@@ -103,7 +100,7 @@ AFLAGS += $(mflags-y)
boot := arch/i386/boot
.PHONY: zImage bzImage compressed zlilo bzlilo \
- zdisk bzdisk fdimage fdimage144 fdimage288 install kernel_install
+ zdisk bzdisk fdimage fdimage144 fdimage288 install
all: bzImage
@@ -125,8 +122,7 @@ zdisk bzdisk: vmlinux
fdimage fdimage144 fdimage288: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
-install: vmlinux
-install kernel_install:
+install:
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
archclean:
diff --git a/arch/i386/Makefile.cpu b/arch/i386/Makefile.cpu
index 8e51456df23d..dcd936ef45db 100644
--- a/arch/i386/Makefile.cpu
+++ b/arch/i386/Makefile.cpu
@@ -1,7 +1,7 @@
# CPU tuning section - shared with UML.
# Must change only cflags-y (or [yn]), not CFLAGS! That makes a difference for UML.
-#-mtune exists since gcc 3.4, and some -mcpu flavors didn't exist in gcc 2.95.
+#-mtune exists since gcc 3.4
HAS_MTUNE := $(call cc-option-yn, -mtune=i386)
ifeq ($(HAS_MTUNE),y)
tune = $(call cc-option,-mtune=$(1),)
@@ -14,7 +14,7 @@ cflags-$(CONFIG_M386) += -march=i386
cflags-$(CONFIG_M486) += -march=i486
cflags-$(CONFIG_M586) += -march=i586
cflags-$(CONFIG_M586TSC) += -march=i586
-cflags-$(CONFIG_M586MMX) += $(call cc-option,-march=pentium-mmx,-march=i586)
+cflags-$(CONFIG_M586MMX) += -march=pentium-mmx
cflags-$(CONFIG_M686) += -march=i686
cflags-$(CONFIG_MPENTIUMII) += -march=i686 $(call tune,pentium2)
cflags-$(CONFIG_MPENTIUMIII) += -march=i686 $(call tune,pentium3)
@@ -23,8 +23,8 @@ cflags-$(CONFIG_MPENTIUM4) += -march=i686 $(call tune,pentium4)
cflags-$(CONFIG_MK6) += -march=k6
# Please note, that patches that add -march=athlon-xp and friends are pointless.
# They make zero difference whatsosever to performance at this time.
-cflags-$(CONFIG_MK7) += $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)
-cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4))
+cflags-$(CONFIG_MK7) += -march=athlon
+cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon)
cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586)
@@ -37,5 +37,5 @@ cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686)
cflags-$(CONFIG_X86_ELAN) += -march=i486
# Geode GX1 support
-cflags-$(CONFIG_MGEODEGX1) += $(call cc-option,-march=pentium-mmx,-march=i486)
+cflags-$(CONFIG_MGEODEGX1) += -march=pentium-mmx
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 1e71382d413a..f136752563b1 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -100,5 +100,5 @@ zlilo: $(BOOTIMAGE)
cp System.map $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-install: $(BOOTIMAGE)
- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
+install:
+ sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index 82a807f9f5e6..f19f3a7492a5 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -11,7 +11,7 @@
#include <linux/linkage.h>
#include <linux/vmalloc.h>
-#include <linux/tty.h>
+#include <linux/screen_info.h>
#include <asm/io.h>
#include <asm/page.h>
diff --git a/arch/i386/boot/install.sh b/arch/i386/boot/install.sh
index f17b40dfc0f4..5e44c736eea8 100644
--- a/arch/i386/boot/install.sh
+++ b/arch/i386/boot/install.sh
@@ -19,6 +19,20 @@
# $4 - default install path (blank if root directory)
#
+verify () {
+ if [ ! -f "$1" ]; then
+ echo "" 1>&2
+ echo " *** Missing file: $1" 1>&2
+ echo ' *** You need to run "make" before "make install".' 1>&2
+ echo "" 1>&2
+ exit 1
+ fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
# User may have a custom install script
if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 92f669470142..2ac40c8244c4 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -97,7 +97,6 @@
#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
@@ -234,10 +233,6 @@ mopar_gr:
movw 18(%di), %ax
movl %eax, %fs:(PARAM_LFB_SIZE)
-# store mode capabilities
- movl 10(%di), %eax
- movl %eax, %fs:(PARAM_CAPABILITIES)
-
# switching the DAC to 8-bit is for <= 8 bpp only
movw %fs:(PARAM_LFB_DEPTH), %ax
cmpw $8, %ax
diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S
index 7b73c67cb4e8..911b15377f2e 100644
--- a/arch/i386/crypto/aes-i586-asm.S
+++ b/arch/i386/crypto/aes-i586-asm.S
@@ -255,18 +255,17 @@ aes_enc_blk:
xor 8(%ebp),%r4
xor 12(%ebp),%r5
- sub $8,%esp // space for register saves on stack
- add $16,%ebp // increment to next round key
- sub $10,%r3
- je 4f // 10 rounds for 128-bit key
- add $32,%ebp
- sub $2,%r3
- je 3f // 12 rounds for 128-bit key
- add $32,%ebp
-
-2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 128-bit key
+ sub $8,%esp // space for register saves on stack
+ add $16,%ebp // increment to next round key
+ cmp $12,%r3
+ jb 4f // 10 rounds for 128-bit key
+ lea 32(%ebp),%ebp
+ je 3f // 12 rounds for 192-bit key
+ lea 32(%ebp),%ebp
+
+2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 256-bit key
fwd_rnd2( -48(%ebp) ,ft_tab)
-3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 128-bit key
+3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 192-bit key
fwd_rnd2( -16(%ebp) ,ft_tab)
4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key
fwd_rnd2( +16(%ebp) ,ft_tab)
@@ -334,18 +333,17 @@ aes_dec_blk:
xor 8(%ebp),%r4
xor 12(%ebp),%r5
- sub $8,%esp // space for register saves on stack
- sub $16,%ebp // increment to next round key
- sub $10,%r3
- je 4f // 10 rounds for 128-bit key
- sub $32,%ebp
- sub $2,%r3
- je 3f // 12 rounds for 128-bit key
- sub $32,%ebp
+ sub $8,%esp // space for register saves on stack
+ sub $16,%ebp // increment to next round key
+ cmp $12,%r3
+ jb 4f // 10 rounds for 128-bit key
+ lea -32(%ebp),%ebp
+ je 3f // 12 rounds for 192-bit key
+ lea -32(%ebp),%ebp
-2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 128-bit key
+2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 256-bit key
inv_rnd2( +48(%ebp), it_tab)
-3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 128-bit key
+3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 192-bit key
inv_rnd2( +16(%ebp), it_tab)
4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key
inv_rnd2( -16(%ebp), it_tab)
diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c
index 88ee85c3b43b..a50397b1d5c7 100644
--- a/arch/i386/crypto/aes.c
+++ b/arch/i386/crypto/aes.c
@@ -36,6 +36,8 @@
* Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
*
*/
+
+#include <asm/byteorder.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -59,7 +61,6 @@ struct aes_ctx {
};
#define WPOLY 0x011b
-#define u32_in(x) le32_to_cpup((const __le32 *)(x))
#define bytes2word(b0, b1, b2, b3) \
(((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
@@ -93,7 +94,6 @@ static u32 rcon_tab[RC_LENGTH];
u32 ft_tab[4][256];
u32 fl_tab[4][256];
-static u32 ls_tab[4][256];
static u32 im_tab[4][256];
u32 il_tab[4][256];
u32 it_tab[4][256];
@@ -144,15 +144,6 @@ static void gen_tabs(void)
fl_tab[2][i] = upr(w, 2);
fl_tab[3][i] = upr(w, 3);
- /*
- * table for key schedule if fl_tab above is
- * not of the required form
- */
- ls_tab[0][i] = w;
- ls_tab[1][i] = upr(w, 1);
- ls_tab[2][i] = upr(w, 2);
- ls_tab[3][i] = upr(w, 3);
-
b = fi(inv_affine((u8)i));
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
@@ -393,13 +384,14 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
int i;
u32 ss[8];
struct aes_ctx *ctx = ctx_arg;
+ const __le32 *key = (const __le32 *)in_key;
/* encryption schedule */
- ctx->ekey[0] = ss[0] = u32_in(in_key);
- ctx->ekey[1] = ss[1] = u32_in(in_key + 4);
- ctx->ekey[2] = ss[2] = u32_in(in_key + 8);
- ctx->ekey[3] = ss[3] = u32_in(in_key + 12);
+ ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]);
+ ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]);
+ ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]);
+ ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]);
switch(key_len) {
case 16:
@@ -410,8 +402,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
break;
case 24:
- ctx->ekey[4] = ss[4] = u32_in(in_key + 16);
- ctx->ekey[5] = ss[5] = u32_in(in_key + 20);
+ ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
+ ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
for (i = 0; i < 7; i++)
ke6(ctx->ekey, i);
kel6(ctx->ekey, 7);
@@ -419,10 +411,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
break;
case 32:
- ctx->ekey[4] = ss[4] = u32_in(in_key + 16);
- ctx->ekey[5] = ss[5] = u32_in(in_key + 20);
- ctx->ekey[6] = ss[6] = u32_in(in_key + 24);
- ctx->ekey[7] = ss[7] = u32_in(in_key + 28);
+ ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
+ ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
+ ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]);
+ ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]);
for (i = 0; i < 6; i++)
ke8(ctx->ekey, i);
kel8(ctx->ekey, 6);
@@ -436,10 +428,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
/* decryption schedule */
- ctx->dkey[0] = ss[0] = u32_in(in_key);
- ctx->dkey[1] = ss[1] = u32_in(in_key + 4);
- ctx->dkey[2] = ss[2] = u32_in(in_key + 8);
- ctx->dkey[3] = ss[3] = u32_in(in_key + 12);
+ ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]);
+ ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]);
+ ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]);
+ ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]);
switch (key_len) {
case 16:
@@ -450,8 +442,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
break;
case 24:
- ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16));
- ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20));
+ ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
+ ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
kdf6(ctx->dkey, 0);
for (i = 1; i < 7; i++)
kd6(ctx->dkey, i);
@@ -459,10 +451,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
break;
case 32:
- ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16));
- ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20));
- ctx->dkey[6] = ff(ss[6] = u32_in(in_key + 24));
- ctx->dkey[7] = ff(ss[7] = u32_in(in_key + 28));
+ ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
+ ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
+ ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6]));
+ ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7]));
kdf8(ctx->dkey, 0);
for (i = 1; i < 6; i++)
kd8(ctx->dkey, i);
@@ -484,6 +476,8 @@ static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src)
static struct crypto_alg aes_alg = {
.cra_name = "aes",
+ .cra_driver_name = "aes-i586",
+ .cra_priority = 200,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 6a431b926019..3cbe6e9cb9fc 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -644,6 +644,8 @@ CONFIG_8139TOO_PIO=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index f10de0f2c5e6..60c3f76dfca4 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -4,10 +4,10 @@
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 \
+obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
- doublefault.o quirks.o i8237.o
+ quirks.o i8237.o
obj-y += cpu/
obj-y += timers/
@@ -25,6 +25,7 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
obj-$(CONFIG_KPROBES) += kprobes.o
@@ -33,6 +34,8 @@ obj-y += sysenter.o vsyscall.o
obj-$(CONFIG_ACPI_SRAT) += srat.o
obj-$(CONFIG_HPET_TIMER) += time_hpet.o
obj-$(CONFIG_EFI) += efi.o efi_stub.o
+obj-$(CONFIG_DOUBLEFAULT) += doublefault.o
+obj-$(CONFIG_VM86) += vm86.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
EXTRA_AFLAGS := -traditional
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 447fa9e33ffb..2111529dea77 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -108,7 +108,7 @@ char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
if (!phys_addr || !size)
return NULL;
- if (phys_addr < (end_pfn_map << PAGE_SHIFT))
+ if (phys_addr+size <= (end_pfn_map << PAGE_SHIFT) + PAGE_SIZE)
return __va(phys_addr);
return NULL;
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 496a2c9909fe..acd3f1e34ca6 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -26,6 +26,7 @@
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/cpu.h>
+#include <linux/module.h>
#include <asm/atomic.h>
#include <asm/smp.h>
@@ -37,10 +38,17 @@
#include <asm/i8253.h>
#include <mach_apic.h>
+#include <mach_ipi.h>
#include "io_ports.h"
/*
+ * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
+ * IPIs in place of local APIC timers
+ */
+static cpumask_t timer_bcast_ipi;
+
+/*
* Knob to control our willingness to enable the local APIC.
*/
int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
@@ -92,10 +100,6 @@ void __init apic_intr_init(void)
/* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0;
-static DEFINE_PER_CPU(int, prof_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_counter) = 1;
-
static int enabled_via_apicbase;
void enable_NMI_through_LVT0 (void * dummy)
@@ -721,7 +725,7 @@ static int __init apic_set_verbosity(char *str)
apic_verbosity = APIC_VERBOSE;
else
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
- " use apic=verbose or apic=debug", str);
+ " use apic=verbose or apic=debug\n", str);
return 0;
}
@@ -935,11 +939,16 @@ void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
static void __setup_APIC_LVTT(unsigned int clocks)
{
unsigned int lvtt_value, tmp_value, ver;
+ int cpu = smp_processor_id();
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);
+
+ if (cpu_isset(cpu, timer_bcast_ipi))
+ lvtt_value |= APIC_LVT_MASKED;
+
apic_write_around(APIC_LVTT, lvtt_value);
/*
@@ -1072,7 +1081,7 @@ void __devinit setup_secondary_APIC_clock(void)
setup_APIC_timer(calibration_result);
}
-void __devinit disable_APIC_timer(void)
+void disable_APIC_timer(void)
{
if (using_apic_timer) {
unsigned long v;
@@ -1084,7 +1093,10 @@ void __devinit disable_APIC_timer(void)
void enable_APIC_timer(void)
{
- if (using_apic_timer) {
+ int cpu = smp_processor_id();
+
+ if (using_apic_timer &&
+ !cpu_isset(cpu, timer_bcast_ipi)) {
unsigned long v;
v = apic_read(APIC_LVTT);
@@ -1092,33 +1104,31 @@ void enable_APIC_timer(void)
}
}
-/*
- * the frequency of the profiling timer can be changed
- * by writing a multiplier value into /proc/profile.
- */
-int setup_profiling_timer(unsigned int multiplier)
+void switch_APIC_timer_to_ipi(void *cpumask)
{
- int i;
+ cpumask_t mask = *(cpumask_t *)cpumask;
+ int cpu = smp_processor_id();
- /*
- * Sanity check. [at least 500 APIC cycles should be
- * between APIC interrupts as a rule of thumb, to avoid
- * irqs flooding us]
- */
- if ( (!multiplier) || (calibration_result/multiplier < 500))
- return -EINVAL;
-
- /*
- * Set the new multiplier for each CPU. CPUs don't start using the
- * new values until the next timer interrupt in which they do process
- * accounting. At that time they also adjust their APIC timers
- * accordingly.
- */
- for (i = 0; i < NR_CPUS; ++i)
- per_cpu(prof_multiplier, i) = multiplier;
+ if (cpu_isset(cpu, mask) &&
+ !cpu_isset(cpu, timer_bcast_ipi)) {
+ disable_APIC_timer();
+ cpu_set(cpu, timer_bcast_ipi);
+ }
+}
+EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
- return 0;
+void switch_ipi_to_APIC_timer(void *cpumask)
+{
+ cpumask_t mask = *(cpumask_t *)cpumask;
+ int cpu = smp_processor_id();
+
+ if (cpu_isset(cpu, mask) &&
+ cpu_isset(cpu, timer_bcast_ipi)) {
+ cpu_clear(cpu, timer_bcast_ipi);
+ enable_APIC_timer();
+ }
}
+EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
#undef APIC_DIVISOR
@@ -1134,32 +1144,10 @@ int setup_profiling_timer(unsigned int multiplier)
inline void smp_local_timer_interrupt(struct pt_regs * regs)
{
- int cpu = smp_processor_id();
-
profile_tick(CPU_PROFILING, regs);
- if (--per_cpu(prof_counter, cpu) <= 0) {
- /*
- * The multiplier may have changed since the last time we got
- * to this point as a result of the user writing to
- * /proc/profile. In this case we need to adjust the APIC
- * timer accordingly.
- *
- * Interrupts are already masked off at this point.
- */
- per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu);
- if (per_cpu(prof_counter, cpu) !=
- per_cpu(prof_old_multiplier, cpu)) {
- __setup_APIC_LVTT(
- calibration_result/
- per_cpu(prof_counter, cpu));
- per_cpu(prof_old_multiplier, cpu) =
- per_cpu(prof_counter, cpu);
- }
-
#ifdef CONFIG_SMP
- update_process_times(user_mode_vm(regs));
+ update_process_times(user_mode_vm(regs));
#endif
- }
/*
* We take the 'long' return path, and there every subsystem
@@ -1206,6 +1194,43 @@ fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
irq_exit();
}
+#ifndef CONFIG_SMP
+static void up_apic_timer_interrupt_call(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ /*
+ * the NMI deadlock-detector uses this.
+ */
+ per_cpu(irq_stat, cpu).apic_timer_irqs++;
+
+ smp_local_timer_interrupt(regs);
+}
+#endif
+
+void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
+{
+ cpumask_t mask;
+
+ cpus_and(mask, cpu_online_map, timer_bcast_ipi);
+ if (!cpus_empty(mask)) {
+#ifdef CONFIG_SMP
+ send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+#else
+ /*
+ * We can directly call the apic timer interrupt handler
+ * in UP case. Minus all irq related functions
+ */
+ up_apic_timer_interrupt_call(regs);
+#endif
+ }
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return -EINVAL;
+}
+
/*
* This interrupt should _never_ happen with our APIC/SMP architecture
*/
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 1e60acbed3c1..05312a8abb8b 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -219,6 +219,7 @@
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/pm_legacy.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/smp.h>
@@ -303,17 +304,6 @@ extern int (*console_blank_hook)(int);
#include "apm.h"
/*
- * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is
- * supposed to provide limit information that it recognizes. Many machines
- * do this correctly, but many others do not restrict themselves to their
- * claimed limit. When this happens, they will cause a segmentation
- * violation in the kernel at boot time. Most BIOS's, however, will
- * respect a 64k limit, so we use that. If you want to be pedantic and
- * hold your BIOS to its claims, then undefine this.
- */
-#define APM_RELAX_SEGMENTS
-
-/*
* Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
* This patched by Chad Miller <cmiller@surfsouth.com>, original code by
* David Chen <chen@ctpa04.mit.edu>
@@ -1075,22 +1065,23 @@ static int apm_engage_power_management(u_short device, int enable)
static int apm_console_blank(int blank)
{
- int error;
- u_short state;
+ int error, i;
+ u_short state;
+ static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
- /* Blank the first display device */
- error = set_power_state(0x100, state);
- if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
- /* try to blank them all instead */
- error = set_power_state(0x1ff, state);
- if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
- /* try to blank device one instead */
- error = set_power_state(0x101, state);
+
+ for (i = 0; i < ARRAY_SIZE(dev); i++) {
+ error = set_power_state(dev[i], state);
+
+ if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
+ return 1;
+
+ if (error == APM_NOT_ENGAGED)
+ break;
}
- if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
- return 1;
- if (error == APM_NOT_ENGAGED) {
+
+ if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
static int tried;
int eng_error;
if (tried++ == 0) {
@@ -2233,8 +2224,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
static int __init apm_init(void)
{
struct proc_dir_entry *apm_proc;
+ struct desc_struct *gdt;
int ret;
- int i;
dmi_check_system(apm_dmi_table);
@@ -2301,7 +2292,9 @@ static int __init apm_init(void)
apm_info.disabled = 1;
return -ENODEV;
}
+#ifdef CONFIG_PM_LEGACY
pm_active = 1;
+#endif
/*
* Set up a segment that references the real mode segment 0x40
@@ -2312,45 +2305,30 @@ static int __init apm_init(void)
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
+ /*
+ * Set up the long jump entry point to the APM BIOS, which is called
+ * from inline assembly.
+ */
apm_bios_entry.offset = apm_info.bios.offset;
apm_bios_entry.segment = APM_CS;
- for (i = 0; i < NR_CPUS; i++) {
- struct desc_struct *gdt = get_cpu_gdt_table(i);
- set_base(gdt[APM_CS >> 3],
- __va((unsigned long)apm_info.bios.cseg << 4));
- set_base(gdt[APM_CS_16 >> 3],
- __va((unsigned long)apm_info.bios.cseg_16 << 4));
- set_base(gdt[APM_DS >> 3],
- __va((unsigned long)apm_info.bios.dseg << 4));
-#ifndef APM_RELAX_SEGMENTS
- if (apm_info.bios.version == 0x100) {
-#endif
- /* For ASUS motherboard, Award BIOS rev 110 (and others?) */
- _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
- /* For some unknown machine. */
- _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
- /* For the DEC Hinote Ultra CT475 (and others?) */
- _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
-#ifndef APM_RELAX_SEGMENTS
- } else {
- _set_limit((char *)&gdt[APM_CS >> 3],
- (apm_info.bios.cseg_len - 1) & 0xffff);
- _set_limit((char *)&gdt[APM_CS_16 >> 3],
- (apm_info.bios.cseg_16_len - 1) & 0xffff);
- _set_limit((char *)&gdt[APM_DS >> 3],
- (apm_info.bios.dseg_len - 1) & 0xffff);
- /* workaround for broken BIOSes */
- if (apm_info.bios.cseg_len <= apm_info.bios.offset)
- _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1);
- if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
- /* for the BIOS that assumes granularity = 1 */
- gdt[APM_DS >> 3].b |= 0x800000;
- printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
- }
- }
-#endif
- }
+ /*
+ * The APM 1.1 BIOS is supposed to provide limit information that it
+ * recognizes. Many machines do this correctly, but many others do
+ * not restrict themselves to their claimed limit. When this happens,
+ * they will cause a segmentation violation in the kernel at boot time.
+ * Most BIOS's, however, will respect a 64k limit, so we use that.
+ *
+ * Note we only set APM segments on CPU zero, since we pin the APM
+ * code to that CPU.
+ */
+ gdt = get_cpu_gdt_table(0);
+ set_base(gdt[APM_CS >> 3],
+ __va((unsigned long)apm_info.bios.cseg << 4));
+ set_base(gdt[APM_CS_16 >> 3],
+ __va((unsigned long)apm_info.bios.cseg_16 << 4));
+ set_base(gdt[APM_DS >> 3],
+ __va((unsigned long)apm_info.bios.dseg << 4));
apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
if (apm_proc)
@@ -2407,7 +2385,9 @@ static void __exit apm_exit(void)
exit_kapmd = 1;
while (kapmd_running)
schedule();
+#ifdef CONFIG_PM_LEGACY
pm_active = 0;
+#endif
}
module_init(apm_init);
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index e344ef88cfcd..333578a4e91a 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -161,8 +161,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
break;
}
- break;
+ if (c->x86_model == 10) {
+ /* AMD Geode LX is model 10 */
+ /* placeholder for any needed mods */
+ break;
+ }
+ break;
case 6: /* An Athlon/Duron */
/* Bit 15 of Athlon specific MSR 15, needs to be 0
@@ -211,6 +216,12 @@ static void __init init_amd(struct cpuinfo_x86 *c)
c->x86_max_cores = 1;
}
+ if (cpuid_eax(0x80000000) >= 0x80000007) {
+ c->x86_power = cpuid_edx(0x80000007);
+ if (c->x86_power & (1<<8))
+ set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
+ }
+
#ifdef CONFIG_X86_HT
/*
* On a AMD dual core setup the lower bits of the APIC id
@@ -228,6 +239,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
cpu, c->x86_max_cores, cpu_core_id[cpu]);
}
#endif
+
}
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/changelog b/arch/i386/kernel/cpu/changelog
deleted file mode 100644
index cef76b80a710..000000000000
--- a/arch/i386/kernel/cpu/changelog
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean
- * and Martin Mares, November 1997.
- *
- * Force Cyrix 6x86(MX) and M II processors to report MTRR capability
- * and Cyrix "coma bug" recognition by
- * Zoltán Böszörményi <zboszor@mail.externet.hu> February 1999.
- *
- * Force Centaur C6 processors to report MTRR capability.
- * Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
- *
- * Intel Mobile Pentium II detection fix. Sean Gilley, June 1999.
- *
- * IDT Winchip tweaks, misc clean ups.
- * Dave Jones <davej@suse.de>, August 1999
- *
- * Better detection of Centaur/IDT WinChip models.
- * Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999.
- *
- * Cleaned up cache-detection code
- * Dave Jones <davej@suse.de>, October 1999
- *
- * Added proper L2 cache detection for Coppermine
- * Dragan Stancevic <visitor@valinux.com>, October 1999
- *
- * Added the original array for capability flags but forgot to credit
- * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff
- * Jauder Ho <jauderho@carumba.com>, January 2000
- *
- * Detection for Celeron coppermine, identify_cpu() overhauled,
- * and a few other clean ups.
- * Dave Jones <davej@suse.de>, April 2000
- *
- * Pentium III FXSR, SSE support
- * General FPU state handling cleanups
- * Gareth Hughes <gareth@valinux.com>, May 2000
- *
- * Added proper Cascades CPU and L2 cache detection for Cascades
- * and 8-way type cache happy bunch from Intel:^)
- * Dragan Stancevic <visitor@valinux.com>, May 2000
- *
- * Forward port AMD Duron errata T13 from 2.2.17pre
- * Dave Jones <davej@suse.de>, August 2000
- *
- * Forward port lots of fixes/improvements from 2.2.18pre
- * Cyrix III, Pentium IV support.
- * Dave Jones <davej@suse.de>, October 2000
- *
- * Massive cleanup of CPU detection and bug handling;
- * Transmeta CPU detection,
- * H. Peter Anvin <hpa@zytor.com>, November 2000
- *
- * VIA C3 Support.
- * Dave Jones <davej@suse.de>, March 2001
- *
- * AMD Athlon/Duron/Thunderbird bluesmoke support.
- * Dave Jones <davej@suse.de>, April 2001.
- *
- * CacheSize bug workaround updates for AMD, Intel & VIA Cyrix.
- * Dave Jones <davej@suse.de>, September, October 2001.
- *
- */
-
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 31e344b26bae..15aee26ec2b6 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -18,9 +18,6 @@
#include "cpu.h"
-DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
-EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
-
DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
@@ -207,7 +204,10 @@ static int __devinit have_cpuid_p(void)
/* Do minimum CPU detection early.
Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
- The others are not touched to avoid unwanted side effects. */
+ The others are not touched to avoid unwanted side effects.
+
+ WARNING: this function is only called on the BP. Don't add code here
+ that is supposed to run on all CPUs. */
static void __init early_cpu_detect(void)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
@@ -239,12 +239,6 @@ static void __init early_cpu_detect(void)
if (cap0 & (1<<19))
c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
}
-
- early_intel_workaround(c);
-
-#ifdef CONFIG_X86_HT
- phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
-#endif
}
void __devinit generic_identify(struct cpuinfo_x86 * c)
@@ -292,6 +286,12 @@ void __devinit generic_identify(struct cpuinfo_x86 * c)
get_model_name(c); /* Default name */
}
}
+
+ early_intel_workaround(c);
+
+#ifdef CONFIG_X86_HT
+ phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
}
static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
@@ -599,11 +599,6 @@ void __devinit cpu_init(void)
load_idt(&idt_descr);
/*
- * Delete NT
- */
- __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
-
- /*
* Set up and load the per-CPU TSS and LDT
*/
atomic_inc(&init_mm.mm_count);
@@ -617,8 +612,10 @@ void __devinit cpu_init(void)
load_TR_desc();
load_LDT(&init_mm.context);
+#ifdef CONFIG_DOUBLEFAULT
/* Set up doublefault TSS pointer in the GDT */
__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
+#endif
/* Clear %fs and %gs. */
asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 871366b83b3f..7975e79d5fa4 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -40,8 +40,6 @@
#include <linux/acpi.h>
#include <acpi/processor.h>
-#include "speedstep-est-common.h"
-
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
@@ -367,6 +365,7 @@ acpi_cpufreq_cpu_init (
unsigned int cpu = policy->cpu;
struct cpufreq_acpi_io *data;
unsigned int result = 0;
+ struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
union acpi_object arg0 = {ACPI_TYPE_BUFFER};
u32 arg0_buf[3];
@@ -390,7 +389,7 @@ acpi_cpufreq_cpu_init (
if (result)
goto err_free;
- if (is_const_loops_cpu(cpu)) {
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 04a405345203..2b62dee35c6c 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -177,9 +177,10 @@ static unsigned int nforce2_fsb_read(int bootfsb)
*/
static int nforce2_set_fsb(unsigned int fsb)
{
- u32 pll, temp = 0;
+ u32 temp = 0;
unsigned int tfsb;
int diff;
+ int pll = 0;
if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 68a1fc87f4ca..e11a09207ec8 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -45,7 +45,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.50.4"
+#define VERSION "version 1.60.0"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -216,10 +216,10 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid)
do {
wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
- if (i++ > 100) {
- printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
- return 1;
- }
+ if (i++ > 100) {
+ printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
+ return 1;
+ }
} while (query_current_values_with_pending_wait(data));
if (savefid != data->currfid) {
@@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
/* Phase 2 - core frequency transition */
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
{
- u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid;
+ u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid;
if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
@@ -359,9 +359,11 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
: vcoreqfid - vcocurrfid;
while (vcofiddiff > 2) {
+ (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
+
if (reqfid > data->currfid) {
if (data->currfid > LO_FID_TABLE_TOP) {
- if (write_new_fid(data, data->currfid + 2)) {
+ if (write_new_fid(data, data->currfid + fid_interval)) {
return 1;
}
} else {
@@ -371,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
}
}
} else {
- if (write_new_fid(data, data->currfid - 2))
+ if (write_new_fid(data, data->currfid - fid_interval))
return 1;
}
@@ -464,7 +466,7 @@ static int check_supported_cpu(unsigned int cpu)
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
- printk(KERN_ERR "limiting to cpu %u failed\n", cpu);
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
goto out;
}
@@ -474,7 +476,7 @@ static int check_supported_cpu(unsigned int cpu)
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
- ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) {
+ ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
goto out;
}
@@ -517,22 +519,24 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
return -ENODEV;
}
- if ((pst[j].fid > MAX_FID)
- || (pst[j].fid & 1)
- || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
+ if (pst[j].fid > MAX_FID) {
+ printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j);
+ return -ENODEV;
+ }
+ if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
/* Only first fid is allowed to be in "low" range */
- printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
+ printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
return -EINVAL;
}
if (pst[j].fid < lastfid)
lastfid = pst[j].fid;
}
if (lastfid & 1) {
- printk(KERN_ERR PFX "lastfid invalid\n");
+ printk(KERN_ERR BFX "lastfid invalid\n");
return -EINVAL;
}
if (lastfid > LO_FID_TABLE_TOP)
- printk(KERN_INFO PFX "first fid not from lo freq table\n");
+ printk(KERN_INFO BFX "first fid not from lo freq table\n");
return 0;
}
@@ -631,7 +635,7 @@ static int find_psb_table(struct powernow_k8_data *data)
dprintk("table vers: 0x%x\n", psb->tableversion);
if (psb->tableversion != PSB_VERSION_1_4) {
- printk(KERN_INFO BFX "PSB table is not v1.4\n");
+ printk(KERN_ERR BFX "PSB table is not v1.4\n");
return -ENODEV;
}
@@ -689,7 +693,7 @@ static int find_psb_table(struct powernow_k8_data *data)
* BIOS and Kernel Developer's Guide, which is available on
* www.amd.com
*/
- printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
+ printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n");
return -ENODEV;
}
@@ -912,7 +916,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
goto err_out;
}
@@ -976,12 +980,15 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
}
/* per CPU init entry point to the driver */
-static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
+static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask = CPU_MASK_ALL;
int rc, i;
+ if (!cpu_online(pol->cpu))
+ return -ENODEV;
+
if (!check_supported_cpu(pol->cpu))
return -ENODEV;
@@ -1021,7 +1028,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
if (smp_processor_id() != pol->cpu) {
- printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
+ printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
goto err_out;
}
@@ -1134,7 +1141,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
};
/* driver entry point for init */
-static int __init powernowk8_init(void)
+static int __cpuinit powernowk8_init(void)
{
unsigned int i, supported_cpus = 0;
@@ -1162,10 +1169,9 @@ static void __exit powernowk8_exit(void)
cpufreq_unregister_driver(&cpufreq_amd64_driver);
}
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>");
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
MODULE_LICENSE("GPL");
late_initcall(powernowk8_init);
module_exit(powernowk8_exit);
-
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index b1e85bb36396..d0de37d58e9a 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -42,7 +42,7 @@ struct powernow_k8_data {
#define CPUID_XFAM 0x0ff00000 /* extended family */
#define CPUID_XFAM_K8 0
#define CPUID_XMOD 0x000f0000 /* extended model */
-#define CPUID_XMOD_REV_F 0x00040000
+#define CPUID_XMOD_REV_G 0x00060000
#define CPUID_USE_XFAM_XMOD 0x00000f00
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
@@ -86,13 +86,14 @@ struct powernow_k8_data {
* low fid table
* - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry
* in the low fid table
- * - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid
+ * - the parts can only step at <= 200 MHz intervals, odd fid values are
+ * supported in revision G and later revisions.
* - lowest frequency must be >= interprocessor hypertransport link speed
* (only applies to MP systems obviously)
*/
/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
-#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */
+#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */
#define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */
#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */
@@ -106,7 +107,7 @@ struct powernow_k8_data {
#define MIN_FREQ 800 /* Min and max freqs, per spec */
#define MAX_FREQ 5000
-#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */
+#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */
#define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */
#define VID_OFF 0x3f
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index edb9873e27e3..9a826cde4fd1 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -35,8 +35,6 @@
#include <asm/processor.h>
#include <asm/cpufeature.h>
-#include "speedstep-est-common.h"
-
#define PFX "speedstep-centrino: "
#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
@@ -493,12 +491,13 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
unsigned l, h;
int ret;
int i;
+ struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
/* Only Intel makes Enhanced Speedstep-capable CPUs */
if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
- if (is_const_loops_cpu(policy->cpu)) {
+ if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h b/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
deleted file mode 100644
index 5ce995c9d866..000000000000
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-est-common.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Routines common for drivers handling Enhanced Speedstep Technology
- * Copyright (C) 2004 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- *
- * Licensed under the terms of the GNU GPL License version 2 -- see
- * COPYING for details.
- */
-
-static inline int is_const_loops_cpu(unsigned int cpu)
-{
- struct cpuinfo_x86 *c = cpu_data + cpu;
-
- if (c->x86_vendor != X86_VENDOR_INTEL || !cpu_has(c, X86_FEATURE_EST))
- return 0;
-
- /*
- * on P-4s, the TSC runs with constant frequency independent of cpu freq
- * when we use EST
- */
- if (c->x86 == 0xf)
- return 1;
-
- return 0;
-}
-
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
index 5b7d18a06afa..b425cd3d1838 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -40,6 +40,7 @@ static struct pci_dev *speedstep_chipset_dev;
*/
static unsigned int speedstep_processor = 0;
+static u32 pmbase;
/*
* There are only two frequency states for each processor. Values
@@ -56,34 +57,47 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
/**
- * speedstep_set_state - set the SpeedStep state
- * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
+ * speedstep_find_register - read the PMBASE address
*
- * Tries to change the SpeedStep state.
+ * Returns: -ENODEV if no register could be found
*/
-static void speedstep_set_state (unsigned int state)
+static int speedstep_find_register (void)
{
- u32 pmbase;
- u8 pm2_blk;
- u8 value;
- unsigned long flags;
-
- if (!speedstep_chipset_dev || (state > 0x1))
- return;
+ if (!speedstep_chipset_dev)
+ return -ENODEV;
/* get PMBASE */
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
if (!(pmbase & 0x01)) {
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
- return;
+ return -ENODEV;
}
pmbase &= 0xFFFFFFFE;
if (!pmbase) {
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
- return;
+ return -ENODEV;
}
+ dprintk("pmbase is 0x%x\n", pmbase);
+ return 0;
+}
+
+/**
+ * speedstep_set_state - set the SpeedStep state
+ * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
+ *
+ * Tries to change the SpeedStep state.
+ */
+static void speedstep_set_state (unsigned int state)
+{
+ u8 pm2_blk;
+ u8 value;
+ unsigned long flags;
+
+ if (state > 0x1)
+ return;
+
/* Disable IRQs */
local_irq_save(flags);
@@ -315,10 +329,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, policy->cpus);
- /* detect low and high frequency */
+ /* detect low and high frequency and transition latency */
result = speedstep_get_freqs(speedstep_processor,
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+ &policy->cpuinfo.transition_latency,
&speedstep_set_state);
set_cpus_allowed(current, cpus_allowed);
if (result)
@@ -335,7 +350,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = speed;
result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
@@ -400,6 +414,9 @@ static int __init speedstep_init(void)
return -EINVAL;
}
+ if (speedstep_find_register())
+ return -ENODEV;
+
return cpufreq_register_driver(&speedstep_driver);
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index d368b3f5fce8..7c47005a1805 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor);
unsigned int speedstep_get_freqs(unsigned int processor,
unsigned int *low_speed,
unsigned int *high_speed,
+ unsigned int *transition_latency,
void (*set_state) (unsigned int state))
{
unsigned int prev_speed;
unsigned int ret = 0;
unsigned long flags;
+ struct timeval tv1, tv2;
if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
return -EINVAL;
@@ -337,7 +339,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
return -EIO;
dprintk("previous speed is %u\n", prev_speed);
-
+
local_irq_save(flags);
/* switch to low state */
@@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor,
dprintk("low speed is %u\n", *low_speed);
+ /* start latency measurement */
+ if (transition_latency)
+ do_gettimeofday(&tv1);
+
/* switch to high state */
set_state(SPEEDSTEP_HIGH);
+
+ /* end latency measurement */
+ if (transition_latency)
+ do_gettimeofday(&tv2);
+
*high_speed = speedstep_get_processor_frequency(processor);
if (!*high_speed) {
ret = -EIO;
@@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor,
if (*high_speed != prev_speed)
set_state(SPEEDSTEP_LOW);
+ if (transition_latency) {
+ *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
+ tv2.tv_usec - tv1.tv_usec;
+ dprintk("transition latency is %u uSec\n", *transition_latency);
+
+ /* convert uSec to nSec and add 20% for safety reasons */
+ *transition_latency *= 1200;
+
+ /* check if the latency measurement is too high or too low
+ * and set it to a safe value (500uSec) in that case
+ */
+ if (*transition_latency > 10000000 || *transition_latency < 50000) {
+ printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
+ "range (%u nSec), falling back to a safe one of %u nSec.\n",
+ *transition_latency, 500000);
+ *transition_latency = 500000;
+ }
+ }
+
out:
local_irq_restore(flags);
return (ret);
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
index 261a2c9b7f6b..6a727fd3a77e 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
@@ -44,4 +44,5 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
extern unsigned int speedstep_get_freqs(unsigned int processor,
unsigned int *low_speed,
unsigned int *high_speed,
+ unsigned int *transition_latency,
void (*set_state) (unsigned int state));
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 2718fb6f6aba..28cc5d524afc 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -269,6 +269,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
result = speedstep_get_freqs(speedstep_processor,
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
+ NULL,
&speedstep_set_state);
if (result) {
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index ff87cc22b323..75015975d038 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -343,6 +343,31 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
}
/*
+ * Handle National Semiconductor branded processors
+ */
+static void __devinit init_nsc(struct cpuinfo_x86 *c)
+{
+ /* There may be GX1 processors in the wild that are branded
+ * NSC and not Cyrix.
+ *
+ * This function only handles the GX processor, and kicks every
+ * thing else to the Cyrix init function above - that should
+ * cover any processors that might have been branded differently
+ * after NSC aquired Cyrix.
+ *
+ * If this breaks your GX1 horribly, please e-mail
+ * info-linux@ldcmail.amd.com to tell us.
+ */
+
+ /* Handle the GX (Formally known as the GX2) */
+
+ if (c->x86 == 5 && c->x86_model == 5)
+ display_cacheinfo(c);
+ else
+ init_cyrix(c);
+}
+
+/*
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
* by the fact that they preserve the flags across the division of 5/2.
* PII and PPro exhibit this behavior too, but they have cpuid available.
@@ -422,7 +447,7 @@ int __init cyrix_init_cpu(void)
static struct cpu_dev nsc_cpu_dev __initdata = {
.c_vendor = "NSC",
.c_ident = { "Geode by NSC" },
- .c_init = init_cyrix,
+ .c_init = init_nsc,
.c_identify = generic_identify,
};
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 5e2da704f0fa..8c0120186b9f 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -183,10 +183,13 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
}
#endif
- if (c->x86 == 15)
+ if (c->x86 == 15)
set_bit(X86_FEATURE_P4, c->x86_capability);
if (c->x86 == 6)
set_bit(X86_FEATURE_P3, c->x86_capability);
+ if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ (c->x86 == 0x6 && c->x86_model >= 0x0e))
+ set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability);
}
diff --git a/arch/i386/kernel/cpu/mtrr/changelog b/arch/i386/kernel/cpu/mtrr/changelog
deleted file mode 100644
index af1368535955..000000000000
--- a/arch/i386/kernel/cpu/mtrr/changelog
+++ /dev/null
@@ -1,229 +0,0 @@
- ChangeLog
-
- Prehistory Martin Tischhäuser <martin@ikcbarka.fzk.de>
- Initial register-setting code (from proform-1.0).
- 19971216 Richard Gooch <rgooch@atnf.csiro.au>
- Original version for /proc/mtrr interface, SMP-safe.
- v1.0
- 19971217 Richard Gooch <rgooch@atnf.csiro.au>
- Bug fix for ioctls()'s.
- Added sample code in Documentation/mtrr.txt
- v1.1
- 19971218 Richard Gooch <rgooch@atnf.csiro.au>
- Disallow overlapping regions.
- 19971219 Jens Maurer <jmaurer@menuett.rhein-main.de>
- Register-setting fixups.
- v1.2
- 19971222 Richard Gooch <rgooch@atnf.csiro.au>
- Fixups for kernel 2.1.75.
- v1.3
- 19971229 David Wragg <dpw@doc.ic.ac.uk>
- Register-setting fixups and conformity with Intel conventions.
- 19971229 Richard Gooch <rgooch@atnf.csiro.au>
- Cosmetic changes and wrote this ChangeLog ;-)
- 19980106 Richard Gooch <rgooch@atnf.csiro.au>
- Fixups for kernel 2.1.78.
- v1.4
- 19980119 David Wragg <dpw@doc.ic.ac.uk>
- Included passive-release enable code (elsewhere in PCI setup).
- v1.5
- 19980131 Richard Gooch <rgooch@atnf.csiro.au>
- Replaced global kernel lock with private spinlock.
- v1.6
- 19980201 Richard Gooch <rgooch@atnf.csiro.au>
- Added wait for other CPUs to complete changes.
- v1.7
- 19980202 Richard Gooch <rgooch@atnf.csiro.au>
- Bug fix in definition of <set_mtrr> for UP.
- v1.8
- 19980319 Richard Gooch <rgooch@atnf.csiro.au>
- Fixups for kernel 2.1.90.
- 19980323 Richard Gooch <rgooch@atnf.csiro.au>
- Move SMP BIOS fixup before secondary CPUs call <calibrate_delay>
- v1.9
- 19980325 Richard Gooch <rgooch@atnf.csiro.au>
- Fixed test for overlapping regions: confused by adjacent regions
- 19980326 Richard Gooch <rgooch@atnf.csiro.au>
- Added wbinvd in <set_mtrr_prepare>.
- 19980401 Richard Gooch <rgooch@atnf.csiro.au>
- Bug fix for non-SMP compilation.
- 19980418 David Wragg <dpw@doc.ic.ac.uk>
- Fixed-MTRR synchronisation for SMP and use atomic operations
- instead of spinlocks.
- 19980418 Richard Gooch <rgooch@atnf.csiro.au>
- Differentiate different MTRR register classes for BIOS fixup.
- v1.10
- 19980419 David Wragg <dpw@doc.ic.ac.uk>
- Bug fix in variable MTRR synchronisation.
- v1.11
- 19980419 Richard Gooch <rgooch@atnf.csiro.au>
- Fixups for kernel 2.1.97.
- v1.12
- 19980421 Richard Gooch <rgooch@atnf.csiro.au>
- Safer synchronisation across CPUs when changing MTRRs.
- v1.13
- 19980423 Richard Gooch <rgooch@atnf.csiro.au>
- Bugfix for SMP systems without MTRR support.
- v1.14
- 19980427 Richard Gooch <rgooch@atnf.csiro.au>
- Trap calls to <mtrr_add> and <mtrr_del> on non-MTRR machines.
- v1.15
- 19980427 Richard Gooch <rgooch@atnf.csiro.au>
- Use atomic bitops for setting SMP change mask.
- v1.16
- 19980428 Richard Gooch <rgooch@atnf.csiro.au>
- Removed spurious diagnostic message.
- v1.17
- 19980429 Richard Gooch <rgooch@atnf.csiro.au>
- Moved register-setting macros into this file.
- Moved setup code from init/main.c to i386-specific areas.
- v1.18
- 19980502 Richard Gooch <rgooch@atnf.csiro.au>
- Moved MTRR detection outside conditionals in <mtrr_init>.
- v1.19
- 19980502 Richard Gooch <rgooch@atnf.csiro.au>
- Documentation improvement: mention Pentium II and AGP.
- v1.20
- 19980521 Richard Gooch <rgooch@atnf.csiro.au>
- Only manipulate interrupt enable flag on local CPU.
- Allow enclosed uncachable regions.
- v1.21
- 19980611 Richard Gooch <rgooch@atnf.csiro.au>
- Always define <main_lock>.
- v1.22
- 19980901 Richard Gooch <rgooch@atnf.csiro.au>
- Removed module support in order to tidy up code.
- Added sanity check for <mtrr_add>/<mtrr_del> before <mtrr_init>.
- Created addition queue for prior to SMP commence.
- v1.23
- 19980902 Richard Gooch <rgooch@atnf.csiro.au>
- Ported patch to kernel 2.1.120-pre3.
- v1.24
- 19980910 Richard Gooch <rgooch@atnf.csiro.au>
- Removed sanity checks and addition queue: Linus prefers an OOPS.
- v1.25
- 19981001 Richard Gooch <rgooch@atnf.csiro.au>
- Fixed harmless compiler warning in include/asm-i386/mtrr.h
- Fixed version numbering and history for v1.23 -> v1.24.
- v1.26
- 19990118 Richard Gooch <rgooch@atnf.csiro.au>
- Added devfs support.
- v1.27
- 19990123 Richard Gooch <rgooch@atnf.csiro.au>
- Changed locking to spin with reschedule.
- Made use of new <smp_call_function>.
- v1.28
- 19990201 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Extended the driver to be able to use Cyrix style ARRs.
- 19990204 Richard Gooch <rgooch@atnf.csiro.au>
- Restructured Cyrix support.
- v1.29
- 19990204 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Refined ARR support: enable MAPEN in set_mtrr_prepare()
- and disable MAPEN in set_mtrr_done().
- 19990205 Richard Gooch <rgooch@atnf.csiro.au>
- Minor cleanups.
- v1.30
- 19990208 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Protect plain 6x86s (and other processors without the
- Page Global Enable feature) against accessing CR4 in
- set_mtrr_prepare() and set_mtrr_done().
- 19990210 Richard Gooch <rgooch@atnf.csiro.au>
- Turned <set_mtrr_up> and <get_mtrr> into function pointers.
- v1.31
- 19990212 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Major rewrite of cyrix_arr_init(): do not touch ARRs,
- leave them as the BIOS have set them up.
- Enable usage of all 8 ARRs.
- Avoid multiplications by 3 everywhere and other
- code clean ups/speed ups.
- 19990213 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Set up other Cyrix processors identical to the boot cpu.
- Since Cyrix don't support Intel APIC, this is l'art pour l'art.
- Weigh ARRs by size:
- If size <= 32M is given, set up ARR# we were given.
- If size > 32M is given, set up ARR7 only if it is free,
- fail otherwise.
- 19990214 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Also check for size >= 256K if we are to set up ARR7,
- mtrr_add() returns the value it gets from set_mtrr()
- 19990218 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Remove Cyrix "coma bug" workaround from here.
- Moved to linux/arch/i386/kernel/setup.c and
- linux/include/asm-i386/bugs.h
- 19990228 Richard Gooch <rgooch@atnf.csiro.au>
- Added MTRRIOC_KILL_ENTRY ioctl(2)
- Trap for counter underflow in <mtrr_file_del>.
- Trap for 4 MiB aligned regions for PPro, stepping <= 7.
- 19990301 Richard Gooch <rgooch@atnf.csiro.au>
- Created <get_free_region> hook.
- 19990305 Richard Gooch <rgooch@atnf.csiro.au>
- Temporarily disable AMD support now MTRR capability flag is set.
- v1.32
- 19990308 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Adjust my changes (19990212-19990218) to Richard Gooch's
- latest changes. (19990228-19990305)
- v1.33
- 19990309 Richard Gooch <rgooch@atnf.csiro.au>
- Fixed typo in <printk> message.
- 19990310 Richard Gooch <rgooch@atnf.csiro.au>
- Support K6-II/III based on Alan Cox's <alan@redhat.com> patches.
- v1.34
- 19990511 Bart Hartgers <bart@etpmod.phys.tue.nl>
- Support Centaur C6 MCR's.
- 19990512 Richard Gooch <rgooch@atnf.csiro.au>
- Minor cleanups.
- v1.35
- 19990707 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Check whether ARR3 is protected in cyrix_get_free_region()
- and mtrr_del(). The code won't attempt to delete or change it
- from now on if the BIOS protected ARR3. It silently skips ARR3
- in cyrix_get_free_region() or returns with an error code from
- mtrr_del().
- 19990711 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
- if ARR3 isn't protected. This is needed because if SMM is active
- and ARR3 isn't protected then deleting and setting ARR3 again
- may lock up the processor. With SMM entirely disabled, it does
- not happen.
- 19990812 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Rearrange switch() statements so the driver accomodates to
- the fact that the AMD Athlon handles its MTRRs the same way
- as Intel does.
- 19990814 Zoltán Böszörményi <zboszor@mail.externet.hu>
- Double check for Intel in mtrr_add()'s big switch() because
- that revision check is only valid for Intel CPUs.
- 19990819 Alan Cox <alan@redhat.com>
- Tested Zoltan's changes on a pre production Athlon - 100%
- success.
- 19991008 Manfred Spraul <manfreds@colorfullife.com>
- replaced spin_lock_reschedule() with a normal semaphore.
- v1.36
- 20000221 Richard Gooch <rgooch@atnf.csiro.au>
- Compile fix if procfs and devfs not enabled.
- Formatting changes.
- v1.37
- 20001109 H. Peter Anvin <hpa@zytor.com>
- Use the new centralized CPU feature detects.
-
- v1.38
- 20010309 Dave Jones <davej@suse.de>
- Add support for Cyrix III.
-
- v1.39
- 20010312 Dave Jones <davej@suse.de>
- Ugh, I broke AMD support.
- Reworked fix by Troels Walsted Hansen <troels@thule.no>
-
- v1.40
- 20010327 Dave Jones <davej@suse.de>
- Adapted Cyrix III support to include VIA C3.
-
- v2.0
- 20020306 Patrick Mochel <mochel@osdl.org>
- Split mtrr.c -> mtrr/*.c
- Converted to Linux Kernel Coding Style
- Fixed several minor nits in form
- Moved some SMP-only functions out, so they can be used
- for power management in the future.
- TODO: Fix user interface cruft.
diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c
index cf39e205d33c..5ac051bb9d55 100644
--- a/arch/i386/kernel/cpu/mtrr/if.c
+++ b/arch/i386/kernel/cpu/mtrr/if.c
@@ -1,5 +1,6 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/seq_file.h>
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index e7921315ae9d..89a85af33d28 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -3,6 +3,7 @@
#include <linux/string.h>
#include <asm/semaphore.h>
#include <linux/seq_file.h>
+#include <linux/cpufreq.h>
/*
* Get CPU information for use by the procfs.
@@ -28,7 +29,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
- NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
+ NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
/* Transmeta-defined */
"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -39,7 +40,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Other (Linux-defined) */
"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "constant_tsc", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -56,11 +57,21 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* AMD-defined (#2) */
- "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
+ "lahf_lm", "cmp_legacy", "svm", NULL, "cr8legacy", NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
+ static char *x86_power_flags[] = {
+ "ts", /* temperature sensor */
+ "fid", /* frequency id control */
+ "vid", /* voltage id control */
+ "ttp", /* thermal trip */
+ "tm",
+ "stc",
+ NULL,
+ /* nothing */ /* constant_tsc - moved to flags */
+ };
struct cpuinfo_x86 *c = v;
int i, n = c - cpu_data;
int fpu_exception;
@@ -86,8 +97,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: unknown\n");
if ( cpu_has(c, X86_FEATURE_TSC) ) {
+ unsigned int freq = cpufreq_quick_get(n);
+ if (!freq)
+ freq = cpu_khz;
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
- cpu_khz / 1000, (cpu_khz % 1000));
+ freq / 1000, (freq % 1000));
}
/* Cache size */
@@ -127,6 +141,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
x86_cap_flags[i] != NULL )
seq_printf(m, " %s", x86_cap_flags[i]);
+ for (i = 0; i < 32; i++)
+ if (c->x86_power & (1 << i)) {
+ if (i < ARRAY_SIZE(x86_power_flags) &&
+ x86_power_flags[i])
+ seq_printf(m, "%s%s",
+ x86_power_flags[i][0]?" ":"",
+ x86_power_flags[i]);
+ else
+ seq_printf(m, " [%d]", i);
+ }
+
seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
c->loops_per_jiffy/(500000/HZ),
(c->loops_per_jiffy/(5000/HZ)) % 100);
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 13bae799e626..006141d1c12a 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -117,14 +117,13 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
{
char __user *tmp = buf;
u32 data[4];
- size_t rv;
u32 reg = *ppos;
int cpu = iminor(file->f_dentry->d_inode);
if (count % 16)
return -EINVAL; /* Invalid chunk size */
- for (rv = 0; count; count -= 16) {
+ for (; count; count -= 16) {
do_cpuid(cpu, reg, data);
if (copy_to_user(tmp, &data, 16))
return -EFAULT;
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 0248e084017c..d49dbe8dc96b 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -25,7 +25,6 @@
#include <mach_ipi.h>
-note_buf_t crash_notes[NR_CPUS];
/* This keeps a track of which one is crashing cpu. */
static int crashing_cpu;
@@ -72,7 +71,9 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
* squirrelled away. ELF notes happen to provide
* all of that that no need to invent something new.
*/
- buf = &crash_notes[cpu][0];
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
memset(&prstatus, 0, sizeof(prstatus));
prstatus.pr_pid = current->pid;
elf_core_copy_regs(&prstatus.pr_reg, regs);
@@ -81,51 +82,12 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
final_note(buf);
}
-static void crash_get_current_regs(struct pt_regs *regs)
-{
- __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
- __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
- __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
- __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
- __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
- __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
- __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
- __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
- __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
- __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
- __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
- __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
- __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
-
- regs->eip = (unsigned long)current_text_addr();
-}
-
-/* CPU does not save ss and esp on stack if execution is already
- * running in kernel mode at the time of NMI occurrence. This code
- * fixes it.
- */
-static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
-{
- memcpy(newregs, oldregs, sizeof(*newregs));
- newregs->esp = (unsigned long)&(oldregs->esp);
- __asm__ __volatile__("xorl %eax, %eax;");
- __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss));
-}
-
-/* We may have saved_regs from where the error came from
- * or it is NULL if via a direct panic().
- */
-static void crash_save_self(struct pt_regs *saved_regs)
+static void crash_save_self(struct pt_regs *regs)
{
- struct pt_regs regs;
int cpu;
cpu = smp_processor_id();
- if (saved_regs)
- crash_setup_regs(&regs, saved_regs);
- else
- crash_get_current_regs(&regs);
- crash_save_this_cpu(&regs, cpu);
+ crash_save_this_cpu(regs, cpu);
}
#ifdef CONFIG_SMP
@@ -144,7 +106,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
local_irq_disable();
if (!user_mode(regs)) {
- crash_setup_regs(&fixed_regs, regs);
+ crash_fixup_ss_esp(&fixed_regs, regs);
regs = &fixed_regs;
}
crash_save_this_cpu(regs, cpu);
diff --git a/arch/i386/kernel/crash_dump.c b/arch/i386/kernel/crash_dump.c
new file mode 100644
index 000000000000..3f532df488bc
--- /dev/null
+++ b/arch/i386/kernel/crash_dump.c
@@ -0,0 +1,74 @@
+/*
+ * kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ * Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
+
+#include <asm/uaccess.h>
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ * space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ * otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ void *vaddr;
+
+ if (!csize)
+ return 0;
+
+ vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+
+ if (!userbuf) {
+ memcpy(buf, (vaddr + offset), csize);
+ kunmap_atomic(vaddr, KM_PTE0);
+ } else {
+ if (!kdump_buf_page) {
+ printk(KERN_WARNING "Kdump: Kdump buffer page not"
+ " allocated\n");
+ return -EFAULT;
+ }
+ copy_page(kdump_buf_page, vaddr);
+ kunmap_atomic(vaddr, KM_PTE0);
+ if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+ return -EFAULT;
+ }
+
+ return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+ int ret = 0;
+
+ kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!kdump_buf_page) {
+ printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer"
+ " page\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+arch_initcall(kdump_buf_page_init);
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 58516e2ac172..6a93d75db431 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -4,7 +4,7 @@
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/bootmem.h>
-
+#include <linux/slab.h>
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
@@ -19,7 +19,7 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
}
if (*bp != 0) {
- str = alloc_bootmem(strlen(bp) + 1);
+ str = dmi_alloc(strlen(bp) + 1);
if (str != NULL)
strcpy(str, bp);
else
@@ -40,7 +40,7 @@ static int __init dmi_table(u32 base, int len, int num,
u8 *buf, *data;
int i = 0;
- buf = bt_ioremap(base, len);
+ buf = dmi_ioremap(base, len);
if (buf == NULL)
return -1;
@@ -65,7 +65,7 @@ static int __init dmi_table(u32 base, int len, int num,
data += 2;
i++;
}
- bt_iounmap(buf, len);
+ dmi_iounmap(buf, len);
return 0;
}
@@ -112,7 +112,7 @@ static void __init dmi_save_devices(struct dmi_header *dm)
if ((*d & 0x80) == 0)
continue;
- dev = alloc_bootmem(sizeof(*dev));
+ dev = dmi_alloc(sizeof(*dev));
if (!dev) {
printk(KERN_ERR "dmi_save_devices: out of memory.\n");
break;
@@ -131,7 +131,7 @@ static void __init dmi_save_ipmi_device(struct dmi_header *dm)
struct dmi_device *dev;
void * data;
- data = alloc_bootmem(dm->length);
+ data = dmi_alloc(dm->length);
if (data == NULL) {
printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
return;
@@ -139,7 +139,7 @@ static void __init dmi_save_ipmi_device(struct dmi_header *dm)
memcpy(data, dm, dm->length);
- dev = alloc_bootmem(sizeof(*dev));
+ dev = dmi_alloc(sizeof(*dev));
if (!dev) {
printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
return;
@@ -221,7 +221,7 @@ void __init dmi_scan_machine(void)
}
}
-out: printk(KERN_INFO "DMI not present.\n");
+out: printk(KERN_INFO "DMI not present or invalid.\n");
}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index e50b93155249..4d704724b2f5 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -323,6 +323,7 @@ work_notifysig: # deal with pending signals and
ALIGN
work_notifysig_v86:
+#ifdef CONFIG_VM86
pushl %ecx # save ti_flags for do_notify_resume
call save_v86_state # %eax contains pt_regs pointer
popl %ecx
@@ -330,6 +331,7 @@ work_notifysig_v86:
xorl %edx, %edx
call do_notify_resume
jmp resume_userspace
+#endif
# perform syscall exit tracing
ALIGN
@@ -657,6 +659,7 @@ ENTRY(spurious_interrupt_bug)
pushl $do_spurious_interrupt_bug
jmp error_code
+.section .rodata,"a"
#include "syscall_table.S"
syscall_table_size=(.-sys_call_table)
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index e437fb367498..5884469f6bfe 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -504,19 +504,24 @@ ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* 0x80 TSS descriptor */
.quad 0x0000000000000000 /* 0x88 LDT descriptor */
- /* Segments used for calling PnP BIOS */
- .quad 0x00c09a0000000000 /* 0x90 32-bit code */
- .quad 0x00809a0000000000 /* 0x98 16-bit code */
- .quad 0x0080920000000000 /* 0xa0 16-bit data */
- .quad 0x0080920000000000 /* 0xa8 16-bit data */
- .quad 0x0080920000000000 /* 0xb0 16-bit data */
+ /*
+ * Segments used for calling PnP BIOS have byte granularity.
+ * They code segments and data segments have fixed 64k limits,
+ * the transfer segment sizes are set at run time.
+ */
+ .quad 0x00409a000000ffff /* 0x90 32-bit code */
+ .quad 0x00009a000000ffff /* 0x98 16-bit code */
+ .quad 0x000092000000ffff /* 0xa0 16-bit data */
+ .quad 0x0000920000000000 /* 0xa8 16-bit data */
+ .quad 0x0000920000000000 /* 0xb0 16-bit data */
+
/*
* The APM segments have byte granularity and their bases
- * and limits are set at run time.
+ * are set at run time. All have 64k limits.
*/
- .quad 0x00409a0000000000 /* 0xb8 APM CS code */
- .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
- .quad 0x0040920000000000 /* 0xc8 APM DS data */
+ .quad 0x00409a000000ffff /* 0xb8 APM CS code */
+ .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
+ .quad 0x004092000000ffff /* 0xc8 APM DS data */
.quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
.quad 0x0000000000000000 /* 0xd8 - unused */
@@ -525,3 +530,5 @@ ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* 0xf0 - unused */
.quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
+ /* Be sure this is zeroed to avoid false validations in Xen */
+ .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 180f070d03cb..3999bec50c33 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -3,8 +3,7 @@
#include <asm/checksum.h>
#include <asm/desc.h>
-/* This is definitely a GPL-only symbol */
-EXPORT_SYMBOL_GPL(cpu_gdt_table);
+EXPORT_SYMBOL_GPL(cpu_gdt_descr);
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
index 9caa8e8db80c..cff95d10a4d8 100644
--- a/arch/i386/kernel/init_task.c
+++ b/arch/i386/kernel/init_task.c
@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task);
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
* no more per-task TSS's.
*/
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 22c8675c79f4..f2dd218d88cb 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -1649,7 +1649,7 @@ static void __init enable_IO_APIC(void)
for(apic = 0; apic < nr_ioapics; apic++) {
int pin;
/* See if any of the pins is in ExtINT mode */
- for(pin = 0; pin < nr_ioapic_registers[i]; pin++) {
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
struct IO_APIC_route_entry entry;
spin_lock_irqsave(&ioapic_lock, flags);
*(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
@@ -1722,8 +1722,8 @@ void disable_IO_APIC(void)
entry.dest_mode = 0; /* Physical */
entry.delivery_mode = dest_ExtINT; /* ExtInt */
entry.vector = 0;
- entry.dest.physical.physical_dest = 0;
-
+ entry.dest.physical.physical_dest =
+ GET_APIC_ID(apic_read(APIC_ID));
/*
* Add it to the IO-APIC irq-routing table:
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index b59a34dbe262..79026f026b85 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h>
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 1a201a932865..f3a9c78c4a24 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -19,7 +19,7 @@
#include <linux/cpu.h>
#include <linux/delay.h>
-DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;
+DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp;
EXPORT_PER_CPU_SYMBOL(irq_stat);
#ifndef CONFIG_X86_LOCAL_APIC
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 19edcd526ba4..6483eeb1a4e8 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -58,13 +58,9 @@ static inline int is_IF_modifier(kprobe_opcode_t opcode)
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
- return 0;
-}
-
-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;
+ return 0;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -81,10 +77,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
@@ -196,6 +188,19 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
+ if (regs->eflags & VM_MASK) {
+ /* We are in virtual-8086 mode. Return 0 */
+ goto no_kprobe;
+ }
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ regs->eip -= sizeof(kprobe_opcode_t);
+ ret = 1;
+ goto no_kprobe;
+ }
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 165f13158c60..d3fdf0057d82 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -70,6 +70,7 @@
*/
//#define DEBUG /* pr_debug */
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -165,7 +166,7 @@ static void collect_cpu_info (void *unused)
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */
- serialize_cpu();
+ sync_core();
/* 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",
@@ -379,7 +380,7 @@ static void do_update_one (void * unused)
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* see notes above for revision 1.07. Apparent chip bug */
- serialize_cpu();
+ sync_core();
/* 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 1ca5269b1e86..91a64016956e 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -38,6 +38,12 @@
int smp_found_config;
unsigned int __initdata maxcpus = NR_CPUS;
+#ifdef CONFIG_HOTPLUG_CPU
+#define CPU_HOTPLUG_ENABLED (1)
+#else
+#define CPU_HOTPLUG_ENABLED (0)
+#endif
+
/*
* Various Linux-internal data structures created from the
* MP-table.
@@ -219,14 +225,18 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
cpu_set(num_processors, cpu_possible_map);
num_processors++;
- if ((num_processors > 8) &&
- ((APIC_XAPIC(ver) &&
- (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) ||
- (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)))
- def_to_bigsmp = 1;
- else
- def_to_bigsmp = 0;
-
+ if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_INTEL:
+ if (!APIC_XAPIC(ver)) {
+ def_to_bigsmp = 0;
+ break;
+ }
+ /* If P4 and above fall through */
+ case X86_VENDOR_AMD:
+ def_to_bigsmp = 1;
+ }
+ }
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 44470fea4309..1d0a55e68760 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -172,7 +172,6 @@ static ssize_t msr_read(struct file *file, char __user * buf,
{
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;
@@ -180,7 +179,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
if (count % 8)
return -EINVAL; /* Invalid chunk size */
- for (rv = 0; count; count -= 8) {
+ for (; count; count -= 8) {
err = do_rdmsr(cpu, reg, &data[0], &data[1]);
if (err)
return err;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 2333aead0563..2185377fdde1 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -48,6 +48,7 @@
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/desc.h>
+#include <asm/vm86.h>
#ifdef CONFIG_MATH_EMULATION
#include <asm/math_emu.h>
#endif
@@ -308,9 +309,7 @@ void show_regs(struct pt_regs * regs)
cr0 = read_cr0();
cr2 = read_cr2();
cr3 = read_cr3();
- if (current_cpu_data.x86 > 4) {
- cr4 = read_cr4();
- }
+ cr4 = read_cr4_safe();
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
show_trace(NULL, &regs->esp);
}
@@ -404,17 +403,7 @@ void flush_thread(void)
void release_thread(struct task_struct *dead_task)
{
- if (dead_task->mm) {
- // temporary debugging check
- if (dead_task->mm->context.size) {
- printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
- dead_task->comm,
- dead_task->mm->context.ldt,
- dead_task->mm->context.size);
- BUG();
- }
- }
-
+ BUG_ON(dead_task->mm);
release_vm86_irqs(dead_task);
}
@@ -435,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
struct task_struct *tsk;
int err;
- childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
- /*
- * The below -8 is to reserve 8 bytes on top of the ring0 stack.
- * This is necessary to guarantee that the entire "struct pt_regs"
- * is accessable even if the CPU haven't stored the SS/ESP registers
- * on the stack (interrupt gate does not save these registers
- * when switching to the same priv ring).
- * Therefore beware: accessing the xss/esp fields of the
- * "struct pt_regs" is possible, but they may contain the
- * completely wrong values.
- */
- childregs = (struct pt_regs *) ((unsigned long) childregs - 8);
+ childregs = task_pt_regs(p);
*childregs = *regs;
childregs->eax = 0;
childregs->esp = esp;
@@ -551,12 +529,7 @@ EXPORT_SYMBOL(dump_thread);
*/
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{
- struct pt_regs ptregs;
-
- ptregs = *(struct pt_regs *)
- ((unsigned long)tsk->thread_info +
- /* see comments in copy_thread() about -8 */
- THREAD_SIZE - sizeof(ptregs) - 8);
+ struct pt_regs ptregs = *task_pt_regs(tsk);
ptregs.xcs &= 0xffff;
ptregs.xds &= 0xffff;
ptregs.xes &= 0xffff;
@@ -612,8 +585,8 @@ static inline void disable_tsc(struct task_struct *prev_p,
* 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;
+ prev = task_thread_info(prev_p);
+ next = task_thread_info(next_p);
if (has_secure_computing(prev) || has_secure_computing(next)) {
/* slow path here */
@@ -798,7 +771,7 @@ unsigned long get_wchan(struct task_struct *p)
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)p->thread_info;
+ stack_page = (unsigned long)task_stack_page(p);
esp = p->thread.esp;
if (!stack_page || esp < stack_page || esp > top_esp+stack_page)
return 0;
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 5ffbb4b7ad05..5c1fb6aada5b 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -32,9 +32,12 @@
* in exit.c or in signal.c.
*/
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x00044dd5
+/*
+ * Determines which flags the user has access to [1 = access, 0 = no access].
+ * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
+ * Also masks reserved bits (31-22, 15, 5, 3, 1).
+ */
+#define FLAG_MASK 0x00054dd5
/* set's the trap flag. */
#define TRAP_FLAG 0x100
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index aaf89cb2bc51..87ccdac84928 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -25,8 +25,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
/* enable access to config space*/
pci_read_config_byte(dev, 0xf4, &config);
- config |= 0x2;
- pci_write_config_byte(dev, 0xf4, config);
+ pci_write_config_byte(dev, 0xf4, config|0x2);
/* read xTPR register */
raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
@@ -42,9 +41,9 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
#endif
}
- config &= ~0x2;
- /* disable access to config space*/
- pci_write_config_byte(dev, 0xf4, config);
+ /* put back the original value for config space*/
+ if (!(config & 0x2))
+ pci_write_config_byte(dev, 0xf4, config);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 2afe0f8d555a..d207242976d3 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -12,6 +12,7 @@
#include <linux/efi.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
+#include <linux/pm.h>
#include <asm/uaccess.h>
#include <asm/apic.h>
#include <asm/desc.h>
@@ -111,12 +112,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
},
},
- { /* Handle problems with rebooting on HP nc6120 */
+ { /* Handle problems with rebooting on HP laptops */
.callback = set_bios_reboot,
- .ident = "HP Compaq nc6120",
+ .ident = "HP Compaq Laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
},
},
{ }
@@ -355,10 +356,10 @@ void machine_halt(void)
void machine_power_off(void)
{
- machine_shutdown();
-
- if (pm_power_off)
+ if (pm_power_off) {
+ machine_shutdown();
pm_power_off();
+ }
}
diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
index 9c968ae67c43..321f5fd26e75 100644
--- a/arch/i386/kernel/scx200.c
+++ b/arch/i386/kernel/scx200.c
@@ -143,7 +143,7 @@ static int __init scx200_init(void)
{
printk(KERN_INFO NAME ": NatSemi SCx200 Driver\n");
- return pci_module_init(&scx200_pci_driver);
+ return pci_register_driver(&scx200_pci_driver);
}
static void __exit scx200_cleanup(void)
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index fdfcb0cba9b4..51e513b4f72d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -45,6 +45,7 @@
#include <linux/nodemask.h>
#include <linux/kexec.h>
#include <linux/crash_dump.h>
+#include <linux/dmi.h>
#include <video/edid.h>
@@ -146,7 +147,6 @@ EXPORT_SYMBOL(ist_info);
struct e820map e820;
extern void early_cpu_init(void);
-extern void dmi_scan_machine(void);
extern void generic_apic_probe(char *);
extern int root_mountflags;
@@ -898,7 +898,7 @@ static void __init parse_cmdline_early (char ** cmdline_p)
}
}
#endif
-#ifdef CONFIG_CRASH_DUMP
+#ifdef CONFIG_PROC_VMCORE
/* elfcorehdr= specifies the location of elf core header
* stored by the crashed kernel.
*/
@@ -954,6 +954,12 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
return 0;
}
+static int __init
+efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
+{
+ memory_present(0, start, end);
+ return 0;
+}
/*
* Find the highest page frame number we have available
@@ -965,6 +971,7 @@ void __init find_max_pfn(void)
max_pfn = 0;
if (efi_enabled) {
efi_memmap_walk(efi_find_max_pfn, &max_pfn);
+ efi_memmap_walk(efi_memory_present_wrapper, NULL);
return;
}
@@ -979,6 +986,7 @@ void __init find_max_pfn(void)
continue;
if (end > max_pfn)
max_pfn = end;
+ memory_present(0, start, end);
}
}
@@ -1576,7 +1584,7 @@ void __init setup_arch(char **cmdline_p)
if (s) {
extern void setup_early_printk(char *);
- setup_early_printk(s);
+ setup_early_printk(strchr(s, '=') + 1);
printk("early console enabled\n");
}
}
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index adcd069db91e..963616d364ec 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -37,51 +37,17 @@
asmlinkage int
sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- struct pt_regs * regs = (struct pt_regs *) &history0;
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs->eax = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(struct pt_regs regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (regs.ecx != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs.eax = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&regs, &saveset))
- return -EINTR;
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
asmlinkage int
@@ -433,11 +399,11 @@ static int setup_frame(int sig, struct k_sigaction *ka,
current->comm, current->pid, frame, regs->eip, frame->pretcode);
#endif
- return 1;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
- return 0;
+ return -EFAULT;
}
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -527,11 +493,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->eip, frame->pretcode);
#endif
- return 1;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
- return 0;
+ return -EFAULT;
}
/*
@@ -581,7 +547,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
ret = setup_frame(sig, ka, oldset, regs);
- if (ret) {
+ if (ret == 0) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -598,11 +564,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
-int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void fastcall do_signal(struct pt_regs *regs)
{
siginfo_t info;
int signr;
struct k_sigaction ka;
+ sigset_t *oldset;
/*
* We want the common case to go fast, which
@@ -613,12 +580,14 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
* CS suffices.
*/
if (!user_mode(regs))
- return 1;
+ return;
if (try_to_freeze())
goto no_signal;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -628,38 +597,55 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
* have been cleared if the watchpoint triggered
* inside the kernel.
*/
- if (unlikely(current->thread.debugreg[7])) {
+ if (unlikely(current->thread.debugreg[7]))
set_debugreg(current->thread.debugreg[7], 7);
- }
/* Whee! Actually deliver the signal. */
- return handle_signal(signr, &info, &ka, oldset, regs);
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
}
- no_signal:
+no_signal:
/* Did we come from a system call? */
if (regs->orig_eax >= 0) {
/* Restart the system call - no handlers present */
- if (regs->eax == -ERESTARTNOHAND ||
- regs->eax == -ERESTARTSYS ||
- regs->eax == -ERESTARTNOINTR) {
+ switch (regs->eax) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
regs->eax = regs->orig_eax;
regs->eip -= 2;
- }
- if (regs->eax == -ERESTART_RESTARTBLOCK){
+ break;
+
+ case -ERESTART_RESTARTBLOCK:
regs->eax = __NR_restart_syscall;
regs->eip -= 2;
+ break;
}
}
- return 0;
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
}
/*
* notification of userspace execution resumption
- * - triggered by current->work.notify_resume
+ * - triggered by the TIF_WORK_MASK flags
*/
__attribute__((regparm(3)))
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
+void do_notify_resume(struct pt_regs *regs, void *_unused,
__u32 thread_info_flags)
{
/* Pending single-step? */
@@ -667,9 +653,10 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset,
regs->eflags |= TF_MASK;
clear_thread_flag(TIF_SINGLESTEP);
}
+
/* deal with pending signal delivery */
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(regs,oldset);
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+ do_signal(regs);
clear_thread_flag(TIF_IRET);
}
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 9ed449af8e9f..255adb498268 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu)
/* initialize thread_struct. we really want to avoid destroy
* idle tread
*/
- idle->thread.esp = (unsigned long)(((struct pt_regs *)
- (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1);
+ idle->thread.esp = (unsigned long)task_pt_regs(idle);
init_idle(idle, cpu);
return idle;
}
@@ -903,6 +902,12 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
unsigned long start_eip;
unsigned short nmi_high = 0, nmi_low = 0;
+ if (!cpu_gdt_descr[cpu].address &&
+ !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
+ printk("Failed to allocate GDT for CPU %d\n", cpu);
+ return 1;
+ }
+
++cpucount;
/*
@@ -1090,6 +1095,7 @@ static void smp_tune_scheduling (void)
cachesize = 16; /* Pentiums, 2x8kB cache */
bandwidth = 100;
}
+ max_cache_size = cachesize * 1024;
}
}
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 9b21a31d4f4e..1b665928336b 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -1,4 +1,3 @@
-.data
ENTRY(sys_call_table)
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
.long sys_exit
@@ -294,3 +293,19 @@ ENTRY(sys_call_table)
.long sys_inotify_init
.long sys_inotify_add_watch
.long sys_inotify_rm_watch
+ .long sys_migrate_pages
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_futimesat
+ .long sys_newfstatat /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_pselect6
+ .long sys_ppoll
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 41c5b2dc6200..a14d594bfbeb 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -302,6 +302,12 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer_interrupt(irq, regs);
write_sequnlock(&xtime_lock);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (using_apic_timer)
+ smp_send_timer_broadcast_ipi(regs);
+#endif
+
return IRQ_HANDLED;
}
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 9caeaa315cd7..a529f0cdce17 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -259,8 +259,6 @@ __setup("hpet=", hpet_setup);
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
-extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
#define DEFAULT_RTC_INT_FREQ 64
#define RTC_NUM_INTS 1
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index d395e3b42485..47675bbbb316 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -330,7 +330,9 @@ int recalibrate_cpu_khz(void)
unsigned int cpu_khz_old = cpu_khz;
if (cpu_has_tsc) {
+ local_irq_disable();
init_cpu_khz();
+ local_irq_enable();
cpu_data[0].loops_per_jiffy =
cpufreq_scale(cpu_data[0].loops_per_jiffy,
cpu_khz_old,
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index f0dffa03fbba..0aaebf3e1cfa 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -112,33 +112,38 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
p < (void *)tinfo + THREAD_SIZE - 3;
}
+static void print_addr_and_symbol(unsigned long addr, char *log_lvl)
+{
+ printk(log_lvl);
+ printk(" [<%08lx>] ", addr);
+ print_symbol("%s", addr);
+ printk("\n");
+}
+
static inline unsigned long print_context_stack(struct thread_info *tinfo,
- unsigned long *stack, unsigned long ebp)
+ unsigned long *stack, unsigned long ebp,
+ char *log_lvl)
{
unsigned long addr;
#ifdef CONFIG_FRAME_POINTER
while (valid_stack_ptr(tinfo, (void *)ebp)) {
addr = *(unsigned long *)(ebp + 4);
- printk(" [<%08lx>] ", addr);
- print_symbol("%s", addr);
- printk("\n");
+ print_addr_and_symbol(addr, log_lvl);
ebp = *(unsigned long *)ebp;
}
#else
while (valid_stack_ptr(tinfo, stack)) {
addr = *stack++;
- if (__kernel_text_address(addr)) {
- printk(" [<%08lx>]", addr);
- print_symbol(" %s", addr);
- printk("\n");
- }
+ if (__kernel_text_address(addr))
+ print_addr_and_symbol(addr, log_lvl);
}
#endif
return ebp;
}
-void show_trace(struct task_struct *task, unsigned long * stack)
+static void show_trace_log_lvl(struct task_struct *task,
+ unsigned long *stack, char *log_lvl)
{
unsigned long ebp;
@@ -157,15 +162,21 @@ void show_trace(struct task_struct *task, unsigned long * stack)
struct thread_info *context;
context = (struct thread_info *)
((unsigned long)stack & (~(THREAD_SIZE - 1)));
- ebp = print_context_stack(context, stack, ebp);
+ ebp = print_context_stack(context, stack, ebp, log_lvl);
stack = (unsigned long*)context->previous_esp;
if (!stack)
break;
- printk(" =======================\n");
+ printk(KERN_EMERG " =======================\n");
}
}
-void show_stack(struct task_struct *task, unsigned long *esp)
+void show_trace(struct task_struct *task, unsigned long * stack)
+{
+ show_trace_log_lvl(task, stack, "");
+}
+
+static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
+ char *log_lvl)
{
unsigned long *stack;
int i;
@@ -178,15 +189,26 @@ void show_stack(struct task_struct *task, unsigned long *esp)
}
stack = esp;
+ printk(log_lvl);
for(i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(stack))
break;
- if (i && ((i % 8) == 0))
- printk("\n ");
+ if (i && ((i % 8) == 0)) {
+ printk("\n");
+ printk(log_lvl);
+ printk(" ");
+ }
printk("%08lx ", *stack++);
}
- printk("\nCall Trace:\n");
- show_trace(task, esp);
+ printk("\n");
+ printk(log_lvl);
+ printk("Call Trace:\n");
+ show_trace_log_lvl(task, esp, log_lvl);
+}
+
+void show_stack(struct task_struct *task, unsigned long *esp)
+{
+ show_stack_log_lvl(task, esp, "");
}
/*
@@ -216,18 +238,18 @@ void show_registers(struct pt_regs *regs)
ss = regs->xss & 0xffff;
}
print_modules();
- printk("CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\nEFLAGS: %08lx"
- " (%s) \n",
+ printk(KERN_EMERG "CPU: %d\nEIP: %04x:[<%08lx>] %s VLI\n"
+ "EFLAGS: %08lx (%s) \n",
smp_processor_id(), 0xffff & regs->xcs, regs->eip,
print_tainted(), regs->eflags, system_utsname.release);
- print_symbol("EIP is at %s\n", regs->eip);
- printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
+ print_symbol(KERN_EMERG "EIP is at %s\n", regs->eip);
+ printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
- printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
+ printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
regs->esi, regs->edi, regs->ebp, esp);
- printk("ds: %04x es: %04x ss: %04x\n",
+ printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n",
regs->xds & 0xffff, regs->xes & 0xffff, ss);
- printk("Process %s (pid: %d, threadinfo=%p task=%p)",
+ printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)",
current->comm, current->pid, current_thread_info(), current);
/*
* When in-kernel, we also print out the stack and code at the
@@ -236,10 +258,10 @@ void show_registers(struct pt_regs *regs)
if (in_kernel) {
u8 __user *eip;
- printk("\nStack: ");
- show_stack(NULL, (unsigned long*)esp);
+ printk("\n" KERN_EMERG "Stack: ");
+ show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG);
- printk("Code: ");
+ printk(KERN_EMERG "Code: ");
eip = (u8 __user *)regs->eip - 43;
for (i = 0; i < 64; i++, eip++) {
@@ -280,15 +302,15 @@ static void handle_BUG(struct pt_regs *regs)
(unsigned long)file < PAGE_OFFSET || __get_user(c, file))
file = "<bad filename>";
- printk("------------[ cut here ]------------\n");
- printk(KERN_ALERT "kernel BUG at %s:%d!\n", file, line);
+ printk(KERN_EMERG "------------[ cut here ]------------\n");
+ printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
no_bug:
return;
/* Here we know it was a BUG but file-n-line is unavailable */
bug:
- printk("Kernel BUG\n");
+ printk(KERN_EMERG "Kernel BUG\n");
}
/* This is gone through when something in the kernel
@@ -306,28 +328,35 @@ void die(const char * str, struct pt_regs * regs, long err)
.lock_owner_depth = 0
};
static int die_counter;
+ unsigned long flags;
if (die.lock_owner != raw_smp_processor_id()) {
console_verbose();
- spin_lock_irq(&die.lock);
+ spin_lock_irqsave(&die.lock, flags);
die.lock_owner = smp_processor_id();
die.lock_owner_depth = 0;
bust_spinlocks(1);
}
+ else
+ local_save_flags(flags);
if (++die.lock_owner_depth < 3) {
int nl = 0;
handle_BUG(regs);
- printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+ printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
- printk("PREEMPT ");
+ printk(KERN_EMERG "PREEMPT ");
nl = 1;
#endif
#ifdef CONFIG_SMP
+ if (!nl)
+ printk(KERN_EMERG);
printk("SMP ");
nl = 1;
#endif
#ifdef CONFIG_DEBUG_PAGEALLOC
+ if (!nl)
+ printk(KERN_EMERG);
printk("DEBUG_PAGEALLOC");
nl = 1;
#endif
@@ -336,11 +365,11 @@ void die(const char * str, struct pt_regs * regs, long err)
notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
show_registers(regs);
} else
- printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+ printk(KERN_EMERG "Recursive die() failure, output suppressed\n");
bust_spinlocks(0);
die.lock_owner = -1;
- spin_unlock_irq(&die.lock);
+ spin_unlock_irqrestore(&die.lock, flags);
if (kexec_should_crash(current))
crash_kexec(regs);
@@ -452,7 +481,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
#endif
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
@@ -524,8 +553,10 @@ gp_in_kernel:
static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
{
- printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
- printk("You probably have a hardware problem with your RAM chips\n");
+ printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
+ "to continue\n");
+ printk(KERN_EMERG "You probably have a hardware problem with your RAM "
+ "chips\n");
/* Clear and disable the memory parity error line. */
clear_mem_error(reason);
@@ -535,7 +566,7 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs)
{
unsigned long i;
- printk("NMI: IOCK error (debug interrupt?)\n");
+ printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
show_registers(regs);
/* Re-enable the IOCK line, wait for a few seconds */
@@ -577,11 +608,11 @@ void die_nmi (struct pt_regs *regs, const char *msg)
* to get a message out.
*/
bust_spinlocks(1);
- printk(msg);
+ printk(KERN_EMERG "%s", msg);
printk(" on CPU%d, eip %08lx, registers:\n",
smp_processor_id(), regs->eip);
show_registers(regs);
- printk("console shuts up ...\n");
+ printk(KERN_EMERG "console shuts up ...\n");
console_silent();
spin_unlock(&nmi_print_lock);
bust_spinlocks(0);
@@ -987,8 +1018,8 @@ asmlinkage void math_state_restore(struct pt_regs regs)
asmlinkage void math_emulate(long arg)
{
- printk("math-emulation not enabled and no coprocessor found.\n");
- printk("killing %s.\n",current->comm);
+ printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n");
+ printk(KERN_EMERG "killing %s.\n",current->comm);
force_sig(SIGFPE,current);
schedule();
}
@@ -1075,9 +1106,9 @@ void __init trap_init(void)
set_trap_gate(0,&divide_error);
set_intr_gate(1,&debug);
set_intr_gate(2,&nmi);
- set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
+ set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
set_system_gate(4,&overflow);
- set_system_gate(5,&bounds);
+ set_trap_gate(5,&bounds);
set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available);
set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
@@ -1095,6 +1126,28 @@ void __init trap_init(void)
#endif
set_trap_gate(19,&simd_coprocessor_error);
+ if (cpu_has_fxsr) {
+ /*
+ * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
+ * Generates a compile-time "error: zero width for bit-field" if
+ * the alignment is wrong.
+ */
+ struct fxsrAlignAssert {
+ int _:!(offsetof(struct task_struct,
+ thread.i387.fxsave) & 15);
+ };
+
+ printk(KERN_INFO "Enabling fast FPU save and restore... ");
+ set_in_cr4(X86_CR4_OSFXSR);
+ printk("done.\n");
+ }
+ if (cpu_has_xmm) {
+ printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
+ "support... ");
+ set_in_cr4(X86_CR4_OSXMMEXCPT);
+ printk("done.\n");
+ }
+
set_system_gate(SYSCALL_VECTOR,&system_call);
/*
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index fc1993564f98..f51c894a7da5 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -4,7 +4,7 @@
* Copyright (C) 1994 Linus Torvalds
*
* 29 dec 2001 - Fixed oopses caused by unchecked access to the vm86
- * stack - Manfred Spraul <manfreds@colorfullife.com>
+ * stack - Manfred Spraul <manfred@colorfullife.com>
*
* 22 mar 2002 - Manfred detected the stackfaults, but didn't handle
* them correctly. Now the emulation will be in a
@@ -30,6 +30,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
@@ -310,7 +311,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
"movl %1,%%ebp\n\t"
"jmp resume_userspace"
: /* no outputs */
- :"r" (&info->regs), "r" (tsk->thread_info) : "ax");
+ :"r" (&info->regs), "r" (task_thread_info(tsk)) : "ax");
/* we never return here */
}
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 06e26f006238..2700f01994ba 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
pkmap_page_table = pte;
}
-static void __devinit free_new_highpage(struct page *page)
+static void __meminit free_new_highpage(struct page *page)
{
set_page_count(page, 1);
__free_page(page);
@@ -735,6 +735,30 @@ void free_initmem(void)
printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10);
}
+#ifdef CONFIG_DEBUG_RODATA
+
+extern char __start_rodata, __end_rodata;
+void mark_rodata_ro(void)
+{
+ unsigned long addr = (unsigned long)&__start_rodata;
+
+ for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE)
+ change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
+
+ printk ("Write protecting the kernel read-only data: %luk\n",
+ (unsigned long)(&__end_rodata - &__start_rodata) >> 10);
+
+ /*
+ * change_page_attr() requires a global_flush_tlb() call after it.
+ * We do this after the printk so that if something went wrong in the
+ * change, the printk gets out at least to give a better debug hint
+ * of who is the culprit.
+ */
+ global_flush_tlb();
+}
+#endif
+
+
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index f600fc244f02..d0cadb33b54c 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -13,6 +13,7 @@
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>
+#include <asm/sections.h>
static DEFINE_SPINLOCK(cpa_lock);
static struct list_head df_list = LIST_HEAD_INIT(df_list);
@@ -36,7 +37,8 @@ pte_t *lookup_address(unsigned long address)
return pte_offset_kernel(pmd, address);
}
-static struct page *split_large_page(unsigned long address, pgprot_t prot)
+static struct page *split_large_page(unsigned long address, pgprot_t prot,
+ pgprot_t ref_prot)
{
int i;
unsigned long addr;
@@ -54,7 +56,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot)
pbase = (pte_t *)page_address(base);
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
- addr == address ? prot : PAGE_KERNEL));
+ addr == address ? prot : ref_prot));
}
return base;
}
@@ -98,11 +100,18 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
*/
static inline void revert_page(struct page *kpte_page, unsigned long address)
{
- pte_t *linear = (pte_t *)
+ pgprot_t ref_prot;
+ pte_t *linear;
+
+ ref_prot =
+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
+ ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
+
+ linear = (pte_t *)
pmd_offset(pud_offset(pgd_offset_k(address), address), address);
set_pmd_pte(linear, address,
pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT,
- PAGE_KERNEL_LARGE));
+ ref_prot));
}
static int
@@ -123,10 +132,16 @@ __change_page_attr(struct page *page, pgprot_t prot)
if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
set_pte_atomic(kpte, mk_pte(page, prot));
} else {
- struct page *split = split_large_page(address, prot);
+ pgprot_t ref_prot;
+ struct page *split;
+
+ ref_prot =
+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
+ ? PAGE_KERNEL_EXEC : PAGE_KERNEL;
+ split = split_large_page(address, prot, ref_prot);
if (!split)
return -ENOMEM;
- set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
+ set_pmd_pte(kpte,address,mk_pte(split, ref_prot));
kpte_page = split;
}
get_page(kpte_page);
@@ -207,6 +222,10 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
{
if (PageHighMem(page))
return;
+ if (!enable)
+ mutex_debug_check_no_locks_freed(page_address(page),
+ numpages * PAGE_SIZE);
+
/* the return value is ignored - the calls cannot fail,
* large pages are disabled at boot time.
*/
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
index 4c4522b43be5..b33aea845f58 100644
--- a/arch/i386/pci/acpi.c
+++ b/arch/i386/pci/acpi.c
@@ -53,7 +53,7 @@ static int __init pci_acpi_init(void)
* don't use pci_enable_device().
*/
printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+ for_each_pci_dev(dev)
acpi_pci_irq_enable(dev);
} else
printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n");
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index eeb1b1f2d548..83c3645ccc43 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -413,6 +413,13 @@ static struct dmi_system_id __devinitdata toshiba_ohci1394_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
},
},
+ {
+ .ident = "Toshiba A40 based laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"),
+ },
+ },
{ }
};
@@ -442,3 +449,19 @@ static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
pci_post_fixup_toshiba_ohci1394);
+
+
+/*
+ * Prevent the BIOS trapping accesses to the Cyrix CS5530A video device
+ * configuration space.
+ */
+static void __devinit pci_early_fixup_cyrix_5530(struct pci_dev *dev)
+{
+ u8 r;
+ /* clear 'F4 Video Configuration Trap' bit */
+ pci_read_config_byte(dev, 0x42, &r);
+ r &= 0xfd;
+ pci_write_config_byte(dev, 0x42, r);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
+ pci_early_fixup_cyrix_5530);
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 19e6f4871d1e..e715aa930036 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -78,7 +78,7 @@ static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
for (i=0; i < rt->size; i++)
sum += addr[i];
if (!sum) {
- DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
+ DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
return rt;
}
return NULL;
@@ -128,7 +128,7 @@ static void __init pirq_peer_trick(void)
#ifdef DEBUG
{
int j;
- DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
+ DBG(KERN_DEBUG "%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
for(j=0; j<4; j++)
DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
DBG("\n");
@@ -160,10 +160,10 @@ void eisa_set_level_irq(unsigned int irq)
return;
eisa_irq_mask |= (1 << irq);
- printk("PCI: setting IRQ %u as level-triggered\n", irq);
+ printk(KERN_DEBUG "PCI: setting IRQ %u as level-triggered\n", irq);
val = inb(port);
if (!(val & mask)) {
- DBG(" -> edge");
+ DBG(KERN_DEBUG " -> edge");
outb(val | mask, port);
}
}
@@ -677,11 +677,11 @@ static __init int ali_router_probe(struct irq_router *r, struct pci_dev *router,
{
case PCI_DEVICE_ID_AL_M1533:
case PCI_DEVICE_ID_AL_M1563:
- printk("PCI: Using ALI IRQ Router\n");
- r->name = "ALI";
- r->get = pirq_ali_get;
- r->set = pirq_ali_set;
- return 1;
+ printk(KERN_DEBUG "PCI: Using ALI IRQ Router\n");
+ r->name = "ALI";
+ r->get = pirq_ali_get;
+ r->set = pirq_ali_set;
+ return 1;
}
return 0;
}
@@ -749,12 +749,13 @@ static void __init pirq_find_router(struct irq_router *r)
r->get = NULL;
r->set = NULL;
- DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
+ DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n",
rt->rtr_vendor, rt->rtr_device);
pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
if (!pirq_router_dev) {
- DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
+ DBG(KERN_DEBUG "PCI: Interrupt router not found at "
+ "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
return;
}
@@ -799,7 +800,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
/* Find IRQ pin */
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (!pin) {
- DBG(" -> no interrupt pin\n");
+ DBG(KERN_DEBUG " -> no interrupt pin\n");
return 0;
}
pin = pin - 1;
@@ -809,16 +810,16 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
if (!pirq_table)
return 0;
- DBG("IRQ for %s[%c]", pci_name(dev), 'A' + pin);
+ DBG(KERN_DEBUG "IRQ for %s[%c]", pci_name(dev), 'A' + pin);
info = pirq_get_info(dev);
if (!info) {
- DBG(" -> not found in routing table\n");
+ DBG(" -> not found in routing table\n" KERN_DEBUG);
return 0;
}
pirq = info->irq[pin].link;
mask = info->irq[pin].bitmap;
if (!pirq) {
- DBG(" -> not routed\n");
+ DBG(" -> not routed\n" KERN_DEBUG);
return 0;
}
DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
@@ -846,9 +847,12 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
* reported by the device if possible.
*/
newirq = dev->irq;
- if (!((1 << newirq) & mask)) {
+ if (newirq && !((1 << newirq) & mask)) {
if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
- else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, pci_name(dev));
+ else printk("\n" KERN_WARNING
+ "PCI: IRQ %i for device %s doesn't match PIRQ mask "
+ "- try pci=usepirqmask\n" KERN_DEBUG, newirq,
+ pci_name(dev));
}
if (!newirq && assign) {
for (i = 0; i < 16; i++) {
@@ -923,14 +927,14 @@ static void __init pcibios_fixup_irqs(void)
struct pci_dev *dev = NULL;
u8 pin;
- DBG("PCI: IRQ fixup\n");
+ DBG(KERN_DEBUG "PCI: IRQ fixup\n");
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
/*
* If the BIOS has set an out of range IRQ number, just ignore it.
* Also keep track of which IRQ's are already in use.
*/
if (dev->irq >= 16) {
- DBG("%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
+ DBG(KERN_DEBUG "%s: ignoring bogus IRQ %d\n", pci_name(dev), dev->irq);
dev->irq = 0;
}
/* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
@@ -1039,7 +1043,7 @@ static struct dmi_system_id __initdata pciirq_dmi_table[] = {
static int __init pcibios_irq_init(void)
{
- DBG("PCI: IRQ init\n");
+ DBG(KERN_DEBUG "PCI: IRQ init\n");
if (pcibios_enable_irq || raw_pci_ops == NULL)
return 0;
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 67932ad53082..f722e1a25948 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -25,7 +25,6 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
-falign-functions=32 -frename-registers -fno-optimize-sibling-calls
CFLAGS_KERNEL := -mconstant-gp
-GCC_VERSION := $(call cc-version)
GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
@@ -37,11 +36,7 @@ $(error Sorry, you need a newer version of the assember, one that is built from
ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
endif
-ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),)
-$(error Sorry, your compiler is too old. GCC v2.96 is known to generate bad code.)
-endif
-
-ifeq ($(GCC_VERSION),0304)
+ifeq ($(call cc-version),0304)
cflags-$(CONFIG_ITANIUM) += -mtune=merced
cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley
endif
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 80f8663bc6d9..991c07b57c24 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -557,6 +557,7 @@ CONFIG_E100=m
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -701,6 +702,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_SGI_L1_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_SGI_IOC4=y
+CONFIG_SERIAL_SGI_IOC3=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -1046,6 +1048,7 @@ CONFIG_INFINIBAND_IPOIB=m
# SN Devices
#
CONFIG_SGI_IOC4=y
+CONFIG_SGI_IOC3=y
#
# File systems
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index ff8bb3770c9d..3cb503b659e6 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -659,6 +659,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_SGI_L1_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_SGI_IOC4=y
+CONFIG_SERIAL_SGI_IOC3=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -899,6 +900,7 @@ CONFIG_INFINIBAND_SRP=m
# SN Devices
#
CONFIG_SGI_IOC4=y
+CONFIG_SGI_IOC3=y
#
# File systems
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index b1e8f09e9fd5..6859119bc9dd 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -565,6 +565,7 @@ CONFIG_E100=m
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 0856ca67dd50..53899dc8eb53 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -548,6 +548,7 @@ CONFIG_E100=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 275a26c6e5aa..dcbc78a4cfa4 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -565,6 +565,7 @@ CONFIG_E100=m
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 19ee635eeb70..626cdc83668b 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -26,6 +26,7 @@
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/serial.h>
@@ -107,7 +108,6 @@ static struct async_struct *IRQ_ports[NR_IRQS];
static struct console *console;
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
extern struct console *console_drivers; /* from kernel/printk.c */
@@ -166,15 +166,9 @@ static void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
}
}
seen_esc = 0;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
- *tty->flip.char_buf_ptr = ch;
-
- *tty->flip.flag_buf_ptr = 0;
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
+ break;
}
tty_flip_buffer_push(tty);
}
diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile
index 2ed90da81166..61cb60affd95 100644
--- a/arch/ia64/ia32/Makefile
+++ b/arch/ia64/ia32/Makefile
@@ -2,11 +2,9 @@
# Makefile for the ia32 kernel emulation subsystem.
#
-obj-y := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o \
+obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o
-CFLAGS_ia32_ioctl.o += -Ifs/
-
# Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and
# restore_ia32_fpstate_live() can be sure the live register contain user-level state.
CFLAGS_ia32_signal.o += -mfixed-range=f16-f31
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index b73b8b6b10c1..a47f63b204fb 100644
--- a/arch/ia64/ia32/elfcore32.h
+++ b/arch/ia64/ia32/elfcore32.h
@@ -95,8 +95,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs,
static inline int elf_core_copy_task_regs(struct task_struct *t,
elf_gregset_t* elfregs)
{
- struct pt_regs *pp = ia64_task_regs(t);
- ELF_CORE_COPY_REGS((*elfregs), pp);
+ ELF_CORE_COPY_REGS((*elfregs), task_pt_regs(t));
return 1;
}
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 494fad6bf376..95fe04400f6b 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -469,7 +469,7 @@ ia32_syscall_table:
data8 sys32_epoll_wait
data8 sys_remap_file_pages
data8 sys_set_tid_address
- data8 sys32_timer_create
+ data8 compat_sys_timer_create
data8 compat_sys_timer_settime /* 260 */
data8 compat_sys_timer_gettime
data8 sys_timer_getoverrun
diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
deleted file mode 100644
index 88739394f6df..000000000000
--- a/arch/ia64/ia32/ia32_ioctl.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * IA32 Architecture-specific ioctl shim code
- *
- * Copyright (C) 2000 VA Linux Co
- * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
- * Copyright (C) 2001-2003 Hewlett-Packard Co
- * David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/signal.h> /* argh, msdos_fs.h isn't self-contained... */
-#include <linux/syscalls.h>
-#include "ia32priv.h"
-
-#define INCLUDES
-#include "compat_ioctl.c"
-
-#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
-
-#define DO_IOCTL(fd, cmd, arg) ({ \
- int _ret; \
- mm_segment_t _old_fs = get_fs(); \
- \
- set_fs(KERNEL_DS); \
- _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \
- set_fs(_old_fs); \
- _ret; \
-})
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
- struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
- };
-
-IOCTL_TABLE_START
-#define DECLARES
-#include "compat_ioctl.c"
-#include <linux/compat_ioctl.h>
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index aa891c9bc9b6..5856510210fa 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -255,7 +255,7 @@ save_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
*/
fp_tos = (fsr>>11)&0x7;
fr8_st_map = (8-fp_tos)&0x7;
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
ia64f2ia32f(fpregp, &ptp->f8);
copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
@@ -389,7 +389,7 @@ restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
fr8_st_map = (8-fp_tos)&0x7;
fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
ia32f2ia64f(&ptp->f8, fpregp);
copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
index 4f630043b3ae..c187743965a0 100644
--- a/arch/ia64/ia32/ia32_support.c
+++ b/arch/ia64/ia32/ia32_support.c
@@ -58,7 +58,7 @@ load_desc (u16 selector)
void
ia32_load_segment_descriptors (struct task_struct *task)
{
- struct pt_regs *regs = ia64_task_regs(task);
+ struct pt_regs *regs = task_pt_regs(task);
/* Setup the segment descriptors */
regs->r24 = load_desc(regs->r16 >> 16); /* ESD */
@@ -113,7 +113,7 @@ void
ia32_load_state (struct task_struct *t)
{
unsigned long eflag, fsr, fcr, fir, fdr, tssd;
- struct pt_regs *regs = ia64_task_regs(t);
+ struct pt_regs *regs = task_pt_regs(t);
eflag = t->thread.eflag;
fsr = t->thread.fsr;
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index dc282710421a..3945d378bd7e 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -48,6 +48,7 @@
#include <linux/ptrace.h>
#include <linux/stat.h>
#include <linux/ipc.h>
+#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/vfs.h>
#include <linux/mman.h>
@@ -1481,7 +1482,7 @@ getreg (struct task_struct *child, int regno)
{
struct pt_regs *child_regs;
- child_regs = ia64_task_regs(child);
+ child_regs = task_pt_regs(child);
switch (regno / sizeof(int)) {
case PT_EBX: return child_regs->r11;
case PT_ECX: return child_regs->r9;
@@ -1509,7 +1510,7 @@ putreg (struct task_struct *child, int regno, unsigned int value)
{
struct pt_regs *child_regs;
- child_regs = ia64_task_regs(child);
+ child_regs = task_pt_regs(child);
switch (regno / sizeof(int)) {
case PT_EBX: child_regs->r11 = value; break;
case PT_ECX: child_regs->r9 = value; break;
@@ -1625,7 +1626,7 @@ save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user
* Stack frames start with 16-bytes of temp space
*/
swp = (struct switch_stack *)(tsk->thread.ksp + 16);
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
tos = (tsk->thread.fsr >> 11) & 7;
for (i = 0; i < 8; i++)
put_fpreg(i, &save->st_space[i], ptp, swp, tos);
@@ -1658,7 +1659,7 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __us
* Stack frames start with 16-bytes of temp space
*/
swp = (struct switch_stack *)(tsk->thread.ksp + 16);
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
tos = (tsk->thread.fsr >> 11) & 7;
for (i = 0; i < 8; i++)
get_fpreg(i, &save->st_space[i], ptp, swp, tos);
@@ -1689,7 +1690,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user
* Stack frames start with 16-bytes of temp space
*/
swp = (struct switch_stack *)(tsk->thread.ksp + 16);
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
tos = (tsk->thread.fsr >> 11) & 7;
for (i = 0; i < 8; i++)
put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
@@ -1733,7 +1734,7 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __u
* Stack frames start with 16-bytes of temp space
*/
swp = (struct switch_stack *)(tsk->thread.ksp + 16);
- ptp = ia64_task_regs(tsk);
+ ptp = task_pt_regs(tsk);
tos = (tsk->thread.fsr >> 11) & 7;
for (i = 0; i < 8; i++)
get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
@@ -1761,21 +1762,15 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data)
lock_kernel();
if (request == PTRACE_TRACEME) {
- ret = sys_ptrace(request, pid, addr, data);
+ ret = ptrace_traceme();
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)
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
goto out;
- ret = -EPERM;
- if (pid == 1) /* no messing around with init! */
- goto out_tsk;
+ }
if (request == PTRACE_ATTACH) {
ret = sys_ptrace(request, pid, addr, data);
@@ -2559,34 +2554,6 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
return 0;
}
-asmlinkage long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
-{
- struct sigevent se;
- mm_segment_t oldfs;
- timer_t t;
- long err;
-
- if (se32 == NULL)
- return sys_timer_create(clock, NULL, timer_id);
-
- if (get_compat_sigevent(&se, se32))
- return -EFAULT;
-
- if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
- return -EFAULT;
-
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t);
- set_fs(oldfs);
-
- if (!err)
- err = __put_user (t, timer_id);
-
- return err;
-}
-
long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
__u32 len_low, __u32 len_high, int advice)
{
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index a3aa45cbcfa0..c485a3b32ba8 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -247,6 +247,32 @@ typedef struct kern_memdesc {
static kern_memdesc_t *kern_memmap;
+#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT)
+
+static inline u64
+kmd_end(kern_memdesc_t *kmd)
+{
+ return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT));
+}
+
+static inline u64
+efi_md_end(efi_memory_desc_t *md)
+{
+ return (md->phys_addr + efi_md_size(md));
+}
+
+static inline int
+efi_wb(efi_memory_desc_t *md)
+{
+ return (md->attribute & EFI_MEMORY_WB);
+}
+
+static inline int
+efi_uc(efi_memory_desc_t *md)
+{
+ return (md->attribute & EFI_MEMORY_UC);
+}
+
static void
walk (efi_freemem_callback_t callback, void *arg, u64 attr)
{
@@ -595,8 +621,8 @@ efi_get_iobase (void)
return 0;
}
-u32
-efi_mem_type (unsigned long phys_addr)
+static efi_memory_desc_t *
+efi_memory_descriptor (unsigned long phys_addr)
{
void *efi_map_start, *efi_map_end, *p;
efi_memory_desc_t *md;
@@ -610,13 +636,13 @@ efi_mem_type (unsigned long phys_addr)
md = p;
if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
- return md->type;
+ return md;
}
return 0;
}
-u64
-efi_mem_attributes (unsigned long phys_addr)
+static int
+efi_memmap_has_mmio (void)
{
void *efi_map_start, *efi_map_end, *p;
efi_memory_desc_t *md;
@@ -629,36 +655,98 @@ efi_mem_attributes (unsigned long phys_addr)
for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
md = p;
- if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
- return md->attribute;
+ if (md->type == EFI_MEMORY_MAPPED_IO)
+ return 1;
}
return 0;
}
+
+u32
+efi_mem_type (unsigned long phys_addr)
+{
+ efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
+
+ if (md)
+ return md->type;
+ return 0;
+}
+
+u64
+efi_mem_attributes (unsigned long phys_addr)
+{
+ efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
+
+ if (md)
+ return md->attribute;
+ return 0;
+}
EXPORT_SYMBOL(efi_mem_attributes);
+/*
+ * Determines whether the memory at phys_addr supports the desired
+ * attribute (WB, UC, etc). If this returns 1, the caller can safely
+ * access *size bytes at phys_addr with the specified attribute.
+ */
+static int
+efi_mem_attribute_range (unsigned long phys_addr, unsigned long *size, u64 attr)
+{
+ efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
+ unsigned long md_end;
+
+ if (!md || (md->attribute & attr) != attr)
+ return 0;
+
+ do {
+ md_end = efi_md_end(md);
+ if (phys_addr + *size <= md_end)
+ return 1;
+
+ md = efi_memory_descriptor(md_end);
+ if (!md || (md->attribute & attr) != attr) {
+ *size = md_end - phys_addr;
+ return 1;
+ }
+ } while (md);
+ return 0;
+}
+
+/*
+ * For /dev/mem, we only allow read & write system calls to access
+ * write-back memory, because read & write don't allow the user to
+ * control access size.
+ */
int
valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t *md;
- u64 efi_desc_size;
+ return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
+}
- efi_map_start = __va(ia64_boot_param->efi_memmap);
- efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
- efi_desc_size = ia64_boot_param->efi_memdesc_size;
+/*
+ * We allow mmap of anything in the EFI memory map that supports
+ * either write-back or uncacheable access. For uncacheable regions,
+ * the supported access sizes are system-dependent, and the user is
+ * responsible for using the correct size.
+ *
+ * Note that this doesn't currently allow access to hot-added memory,
+ * because that doesn't appear in the boot-time EFI memory map.
+ */
+int
+valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+{
+ if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
+ return 1;
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- md = p;
+ if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
+ return 1;
- if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) {
- if (!(md->attribute & EFI_MEMORY_WB))
- return 0;
+ /*
+ * Some firmware doesn't report MMIO regions in the EFI memory map.
+ * The Intel BigSur (a.k.a. HP i2000) has this problem. In this
+ * case, we can't use the EFI memory map to validate mmap requests.
+ */
+ if (!efi_memmap_has_mmio())
+ return 1;
- if (*size > md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr)
- *size = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - phys_addr;
- return 1;
- }
- }
return 0;
}
@@ -707,32 +795,6 @@ efi_uart_console_only(void)
return 0;
}
-#define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT)
-
-static inline u64
-kmd_end(kern_memdesc_t *kmd)
-{
- return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT));
-}
-
-static inline u64
-efi_md_end(efi_memory_desc_t *md)
-{
- return (md->phys_addr + efi_md_size(md));
-}
-
-static inline int
-efi_wb(efi_memory_desc_t *md)
-{
- return (md->attribute & EFI_MEMORY_WB);
-}
-
-static inline int
-efi_uc(efi_memory_desc_t *md)
-{
- return (md->attribute & EFI_MEMORY_UC);
-}
-
/*
* Look for the first granule aligned memory descriptor memory
* that is big enough to hold EFI memory map. Make sure this
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0741b066b98f..7a6ffd613789 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1600,5 +1600,6 @@ sys_call_table:
data8 sys_inotify_init
data8 sys_inotify_add_watch
data8 sys_inotify_rm_watch
+ data8 sys_migrate_pages // 1280
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 2ddbac6f4999..ce423910ca97 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -903,5 +903,6 @@ fsyscall_table:
data8 0
data8 0
data8 0
+ data8 0 // 1280
.org fsyscall_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index bfe65b2e8621..fbc7ea35dd57 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -1060,7 +1060,7 @@ SET_REG(b5);
* the clobber lists for spin_lock() in include/asm-ia64/spinlock.h.
*/
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4)
.prologue
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index 5db9d3bcbbcb..e72de580ebbf 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -103,7 +103,7 @@ EXPORT_SYMBOL(unw_init_running);
#ifdef ASM_SUPPORTED
# ifdef CONFIG_SMP
-# if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+# if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
/*
* This is not a normal routine and we don't want a function descriptor for it, so we use
* a fake declaration here.
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index 2323377e3695..5cd6226f44f2 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -60,3 +60,30 @@ END(jprobe_break)
GLOBAL_ENTRY(jprobe_inst_return)
br.call.sptk.many b0=jprobe_break
END(jprobe_inst_return)
+
+GLOBAL_ENTRY(invalidate_stacked_regs)
+ movl r16=invalidate_restore_cfm
+ ;;
+ mov b6=r16
+ ;;
+ br.ret.sptk.many b6
+ ;;
+invalidate_restore_cfm:
+ mov r16=ar.rsc
+ ;;
+ mov ar.rsc=r0
+ ;;
+ loadrs
+ ;;
+ mov ar.rsc=r16
+ ;;
+ br.cond.sptk.many rp
+END(invalidate_stacked_regs)
+
+GLOBAL_ENTRY(flush_register_stack)
+ // flush dirty regs to backing store (must be first in insn group)
+ flushrs
+ ;;
+ br.ret.sptk.many rp
+END(flush_register_stack)
+
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 89a70400c4f6..50ae8c7d453d 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -467,10 +467,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
}
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
/*
* We are resuming execution after a single step fault, so the pt_regs
* structure reflects the register state after we executed the instruction
@@ -642,6 +638,13 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
}
+ } else if (!is_ia64_break_inst(regs)) {
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ ret = 1;
+ goto no_kprobe;
} else {
/* Not our break */
goto no_kprobe;
@@ -763,11 +766,56 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
return ret;
}
+struct param_bsp_cfm {
+ unsigned long ip;
+ unsigned long *bsp;
+ unsigned long cfm;
+};
+
+static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg)
+{
+ unsigned long ip;
+ struct param_bsp_cfm *lp = arg;
+
+ do {
+ unw_get_ip(info, &ip);
+ if (ip == 0)
+ break;
+ if (ip == lp->ip) {
+ unw_get_bsp(info, (unsigned long*)&lp->bsp);
+ unw_get_cfm(info, (unsigned long*)&lp->cfm);
+ return;
+ }
+ } while (unw_unwind(info) >= 0);
+ lp->bsp = 0;
+ lp->cfm = 0;
+ return;
+}
+
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;
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct param_bsp_cfm pa;
+ int bytes;
+
+ /*
+ * Callee owns the argument space and could overwrite it, eg
+ * tail call optimization. So to be absolutely safe
+ * we save the argument space before transfering the control
+ * to instrumented jprobe function which runs in
+ * the process context
+ */
+ pa.ip = regs->cr_iip;
+ unw_init_running(ia64_get_bsp_cfm, &pa);
+ bytes = (char *)ia64_rse_skip_regs(pa.bsp, pa.cfm & 0x3f)
+ - (char *)pa.bsp;
+ memcpy( kcb->jprobes_saved_stacked_regs,
+ pa.bsp,
+ bytes );
+ kcb->bsp = pa.bsp;
+ kcb->cfm = pa.cfm;
/* save architectural state */
kcb->jprobe_saved_regs = *regs;
@@ -789,8 +837,20 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ int bytes;
+ /* restoring architectural state */
*regs = kcb->jprobe_saved_regs;
+
+ /* restoring the original argument space */
+ flush_register_stack();
+ bytes = (char *)ia64_rse_skip_regs(kcb->bsp, kcb->cfm & 0x3f)
+ - (char *)kcb->bsp;
+ memcpy( kcb->bsp,
+ kcb->jprobes_saved_stacked_regs,
+ bytes );
+ invalidate_stacked_regs();
+
preempt_enable_no_resched();
return 1;
}
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 355af15287c7..ee7eec9ee576 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -766,7 +766,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
l = strlen(previous_current->comm);
snprintf(comm, sizeof(comm), "%s %*s %d",
current->comm, l, previous_current->comm,
- previous_current->thread_info->cpu);
+ task_thread_info(previous_current)->cpu);
}
memcpy(current->comm, comm, sizeof(current->comm));
@@ -1423,7 +1423,7 @@ format_mca_init_stack(void *mca_data, unsigned long offset,
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 = task_thread_info(p);
ti->flags = _TIF_MCA_INIT;
ti->preempt_count = 1;
ti->task = p;
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index db32fc1d3935..403a80a58c13 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -847,7 +847,7 @@ ia64_state_restore:
;;
mov cr.iim=temp3
mov cr.iha=temp4
- dep r22=0,r22,62,2 // pal_min_state, physical, uncached
+ dep r22=0,r22,62,1 // pal_min_state, physical, uncached
mov IA64_KR(CURRENT)=r21
ld8 r8=[temp1] // os_status
ld8 r10=[temp2] // context
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 410d4804fa6e..2ea4b39efffa 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/capability.h>
#include <linux/rcupdate.h>
#include <asm/errno.h>
@@ -627,9 +628,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count,
#include "perfmon_itanium.h"
#include "perfmon_mckinley.h"
+#include "perfmon_montecito.h"
#include "perfmon_generic.h"
static pmu_config_t *pmu_confs[]={
+ &pmu_conf_mont,
&pmu_conf_mck,
&pmu_conf_ita,
&pmu_conf_gen, /* must be last */
@@ -1709,7 +1712,7 @@ static void
pfm_syswide_force_stop(void *info)
{
pfm_context_t *ctx = (pfm_context_t *)info;
- struct pt_regs *regs = ia64_task_regs(current);
+ struct pt_regs *regs = task_pt_regs(current);
struct task_struct *owner;
unsigned long flags;
int ret;
@@ -1814,7 +1817,7 @@ pfm_flush(struct file *filp)
is_system = ctx->ctx_fl_system;
task = PFM_CTX_TASK(ctx);
- regs = ia64_task_regs(task);
+ regs = task_pt_regs(task);
DPRINT(("ctx_state=%d is_current=%d\n",
state,
@@ -1944,7 +1947,7 @@ pfm_close(struct inode *inode, struct file *filp)
is_system = ctx->ctx_fl_system;
task = PFM_CTX_TASK(ctx);
- regs = ia64_task_regs(task);
+ regs = task_pt_regs(task);
DPRINT(("ctx_state=%d is_current=%d\n",
state,
@@ -4051,7 +4054,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
*/
ia64_psr(regs)->up = 0;
} else {
- tregs = ia64_task_regs(task);
+ tregs = task_pt_regs(task);
/*
* stop monitoring at the user level
@@ -4133,7 +4136,7 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
ia64_psr(regs)->up = 1;
} else {
- tregs = ia64_task_regs(ctx->ctx_task);
+ tregs = task_pt_regs(ctx->ctx_task);
/*
* start monitoring at the kernel level the next
@@ -4403,7 +4406,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
/*
* when not current, task MUST be stopped, so this is safe
*/
- regs = ia64_task_regs(task);
+ regs = task_pt_regs(task);
/* force a full reload */
ctx->ctx_last_activation = PFM_INVALID_ACTIVATION;
@@ -4529,7 +4532,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
/*
* per-task mode
*/
- tregs = task == current ? regs : ia64_task_regs(task);
+ tregs = task == current ? regs : task_pt_regs(task);
if (task == current) {
/*
@@ -4592,7 +4595,7 @@ pfm_exit_thread(struct task_struct *task)
{
pfm_context_t *ctx;
unsigned long flags;
- struct pt_regs *regs = ia64_task_regs(task);
+ struct pt_regs *regs = task_pt_regs(task);
int ret, state;
int free_ok = 0;
@@ -4925,7 +4928,7 @@ restart_args:
if (unlikely(ret)) goto abort_locked;
skip_fd:
- ret = (*func)(ctx, args_k, count, ia64_task_regs(current));
+ ret = (*func)(ctx, args_k, count, task_pt_regs(current));
call_made = 1;
@@ -5049,7 +5052,7 @@ pfm_handle_work(void)
pfm_clear_task_notify();
- regs = ia64_task_regs(current);
+ regs = task_pt_regs(current);
/*
* extract reason for being here and clear
@@ -5793,7 +5796,7 @@ pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_c
* on every CPU, so we can rely on the pid to identify the idle task.
*/
if ((info & PFM_CPUINFO_EXCL_IDLE) == 0 || task->pid) {
- regs = ia64_task_regs(task);
+ regs = task_pt_regs(task);
ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0;
return;
}
@@ -5876,7 +5879,7 @@ pfm_save_regs(struct task_struct *task)
flags = pfm_protect_ctx_ctxsw(ctx);
if (ctx->ctx_state == PFM_CTX_ZOMBIE) {
- struct pt_regs *regs = ia64_task_regs(task);
+ struct pt_regs *regs = task_pt_regs(task);
pfm_clear_psr_up();
@@ -6076,7 +6079,7 @@ pfm_load_regs (struct task_struct *task)
BUG_ON(psr & IA64_PSR_I);
if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) {
- struct pt_regs *regs = ia64_task_regs(task);
+ struct pt_regs *regs = task_pt_regs(task);
BUG_ON(ctx->ctx_smpl_hdr);
@@ -6445,7 +6448,7 @@ pfm_alt_save_pmu_state(void *data)
{
struct pt_regs *regs;
- regs = ia64_task_regs(current);
+ regs = task_pt_regs(current);
DPRINT(("called\n"));
@@ -6471,7 +6474,7 @@ pfm_alt_restore_pmu_state(void *data)
{
struct pt_regs *regs;
- regs = ia64_task_regs(current);
+ regs = task_pt_regs(current);
DPRINT(("called\n"));
@@ -6753,7 +6756,7 @@ dump_pmu_state(const char *from)
local_irq_save(flags);
this_cpu = smp_processor_id();
- regs = ia64_task_regs(current);
+ regs = task_pt_regs(current);
info = PFM_CPUINFO_GET();
dcr = ia64_getreg(_IA64_REG_CR_DCR);
diff --git a/arch/ia64/kernel/perfmon_montecito.h b/arch/ia64/kernel/perfmon_montecito.h
new file mode 100644
index 000000000000..cd06ac6a686c
--- /dev/null
+++ b/arch/ia64/kernel/perfmon_montecito.h
@@ -0,0 +1,269 @@
+/*
+ * This file contains the Montecito PMU register description tables
+ * and pmc checker used by perfmon.c.
+ *
+ * Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
+ * Contributed by Stephane Eranian <eranian@hpl.hp.com>
+ */
+static int pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
+
+#define RDEP_MONT_ETB (RDEP(38)|RDEP(39)|RDEP(48)|RDEP(49)|RDEP(50)|RDEP(51)|RDEP(52)|RDEP(53)|RDEP(54)|\
+ RDEP(55)|RDEP(56)|RDEP(57)|RDEP(58)|RDEP(59)|RDEP(60)|RDEP(61)|RDEP(62)|RDEP(63))
+#define RDEP_MONT_DEAR (RDEP(32)|RDEP(33)|RDEP(36))
+#define RDEP_MONT_IEAR (RDEP(34)|RDEP(35))
+
+static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={
+/* pmc0 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc4 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(4),0, 0, 0}, {0,0, 0, 0}},
+/* pmc5 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(5),0, 0, 0}, {0,0, 0, 0}},
+/* pmc6 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(6),0, 0, 0}, {0,0, 0, 0}},
+/* pmc7 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(7),0, 0, 0}, {0,0, 0, 0}},
+/* pmc8 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(8),0, 0, 0}, {0,0, 0, 0}},
+/* pmc9 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(9),0, 0, 0}, {0,0, 0, 0}},
+/* pmc10 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(10),0, 0, 0}, {0,0, 0, 0}},
+/* pmc11 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(11),0, 0, 0}, {0,0, 0, 0}},
+/* pmc12 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(12),0, 0, 0}, {0,0, 0, 0}},
+/* pmc13 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(13),0, 0, 0}, {0,0, 0, 0}},
+/* pmc14 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(14),0, 0, 0}, {0,0, 0, 0}},
+/* pmc15 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(15),0, 0, 0}, {0,0, 0, 0}},
+/* pmc16 */ { PFM_REG_NOTIMPL, },
+/* pmc17 */ { PFM_REG_NOTIMPL, },
+/* pmc18 */ { PFM_REG_NOTIMPL, },
+/* pmc19 */ { PFM_REG_NOTIMPL, },
+/* pmc20 */ { PFM_REG_NOTIMPL, },
+/* pmc21 */ { PFM_REG_NOTIMPL, },
+/* pmc22 */ { PFM_REG_NOTIMPL, },
+/* pmc23 */ { PFM_REG_NOTIMPL, },
+/* pmc24 */ { PFM_REG_NOTIMPL, },
+/* pmc25 */ { PFM_REG_NOTIMPL, },
+/* pmc26 */ { PFM_REG_NOTIMPL, },
+/* pmc27 */ { PFM_REG_NOTIMPL, },
+/* pmc28 */ { PFM_REG_NOTIMPL, },
+/* pmc29 */ { PFM_REG_NOTIMPL, },
+/* pmc30 */ { PFM_REG_NOTIMPL, },
+/* pmc31 */ { PFM_REG_NOTIMPL, },
+/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}},
+/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
+/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}},
+/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}},
+/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}},
+ { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+static pfm_reg_desc_t pfm_mont_pmd_desc[PMU_MAX_PMDS]={
+/* pmd0 */ { PFM_REG_NOTIMPL, },
+/* pmd1 */ { PFM_REG_NOTIMPL, },
+/* pmd2 */ { PFM_REG_NOTIMPL, },
+/* pmd3 */ { PFM_REG_NOTIMPL, },
+/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(4),0, 0, 0}},
+/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(5),0, 0, 0}},
+/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(6),0, 0, 0}},
+/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(7),0, 0, 0}},
+/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(8),0, 0, 0}},
+/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(9),0, 0, 0}},
+/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(10),0, 0, 0}},
+/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(11),0, 0, 0}},
+/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(12),0, 0, 0}},
+/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(13),0, 0, 0}},
+/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(14),0, 0, 0}},
+/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(15),0, 0, 0}},
+/* pmd16 */ { PFM_REG_NOTIMPL, },
+/* pmd17 */ { PFM_REG_NOTIMPL, },
+/* pmd18 */ { PFM_REG_NOTIMPL, },
+/* pmd19 */ { PFM_REG_NOTIMPL, },
+/* pmd20 */ { PFM_REG_NOTIMPL, },
+/* pmd21 */ { PFM_REG_NOTIMPL, },
+/* pmd22 */ { PFM_REG_NOTIMPL, },
+/* pmd23 */ { PFM_REG_NOTIMPL, },
+/* pmd24 */ { PFM_REG_NOTIMPL, },
+/* pmd25 */ { PFM_REG_NOTIMPL, },
+/* pmd26 */ { PFM_REG_NOTIMPL, },
+/* pmd27 */ { PFM_REG_NOTIMPL, },
+/* pmd28 */ { PFM_REG_NOTIMPL, },
+/* pmd29 */ { PFM_REG_NOTIMPL, },
+/* pmd30 */ { PFM_REG_NOTIMPL, },
+/* pmd31 */ { PFM_REG_NOTIMPL, },
+/* pmd32 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(33)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}},
+/* pmd33 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}},
+/* pmd34 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(35),0, 0, 0}, {RDEP(37),0, 0, 0}},
+/* pmd35 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(34),0, 0, 0}, {RDEP(37),0, 0, 0}},
+/* pmd36 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(33),0, 0, 0}, {RDEP(40),0, 0, 0}},
+/* pmd37 */ { PFM_REG_NOTIMPL, },
+/* pmd38 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd39 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd40 */ { PFM_REG_NOTIMPL, },
+/* pmd41 */ { PFM_REG_NOTIMPL, },
+/* pmd42 */ { PFM_REG_NOTIMPL, },
+/* pmd43 */ { PFM_REG_NOTIMPL, },
+/* pmd44 */ { PFM_REG_NOTIMPL, },
+/* pmd45 */ { PFM_REG_NOTIMPL, },
+/* pmd46 */ { PFM_REG_NOTIMPL, },
+/* pmd47 */ { PFM_REG_NOTIMPL, },
+/* pmd48 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd49 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd50 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd51 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd52 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd53 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd54 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd55 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd56 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd57 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd58 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd59 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd60 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd61 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd62 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+/* pmd63 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}},
+ { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+/*
+ * PMC reserved fields must have their power-up values preserved
+ */
+static int
+pfm_mont_reserved(unsigned int cnum, unsigned long *val, struct pt_regs *regs)
+{
+ unsigned long tmp1, tmp2, ival = *val;
+
+ /* remove reserved areas from user value */
+ tmp1 = ival & PMC_RSVD_MASK(cnum);
+
+ /* get reserved fields values */
+ tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum);
+
+ *val = tmp1 | tmp2;
+
+ DPRINT(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n",
+ cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val));
+ return 0;
+}
+
+/*
+ * task can be NULL if the context is unloaded
+ */
+static int
+pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
+{
+ int ret = 0;
+ unsigned long val32 = 0, val38 = 0, val41 = 0;
+ unsigned long tmpval;
+ int check_case1 = 0;
+ int is_loaded;
+
+ /* first preserve the reserved fields */
+ pfm_mont_reserved(cnum, val, regs);
+
+ tmpval = *val;
+
+ /* sanity check */
+ if (ctx == NULL) return -EINVAL;
+
+ is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
+
+ /*
+ * we must clear the debug registers if pmc41 has a value which enable
+ * memory pipeline event constraints. In this case we need to clear the
+ * the debug registers if they have not yet been accessed. This is required
+ * to avoid picking stale state.
+ * PMC41 is "active" if:
+ * one of the pmc41.cfg_dtagXX field is different from 0x3
+ * AND
+ * at the corresponding pmc41.en_dbrpXX is set.
+ * AND
+ * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used)
+ */
+ DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded));
+
+ if (cnum == 41 && is_loaded
+ && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
+
+ DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval));
+
+ /* don't mix debug with perfmon */
+ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+ /*
+ * a count of 0 will mark the debug registers if:
+ * AND
+ */
+ ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs);
+ if (ret) return ret;
+ }
+ /*
+ * we must clear the (instruction) debug registers if:
+ * pmc38.ig_ibrpX is 0 (enabled)
+ * AND
+ * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used)
+ */
+ if (cnum == 38 && is_loaded && ((tmpval & 0x492UL) != 0x492UL) && ctx->ctx_fl_using_dbreg == 0) {
+
+ DPRINT(("pmc38=0x%lx has active pmc38 settings, clearing ibr\n", tmpval));
+
+ /* don't mix debug with perfmon */
+ if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+ /*
+ * a count of 0 will mark the debug registers as in use and also
+ * ensure that they are properly cleared.
+ */
+ ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs);
+ if (ret) return ret;
+
+ }
+ switch(cnum) {
+ case 32: val32 = *val;
+ val38 = ctx->ctx_pmcs[38];
+ val41 = ctx->ctx_pmcs[41];
+ check_case1 = 1;
+ break;
+ case 38: val38 = *val;
+ val32 = ctx->ctx_pmcs[32];
+ val41 = ctx->ctx_pmcs[41];
+ check_case1 = 1;
+ break;
+ case 41: val41 = *val;
+ val32 = ctx->ctx_pmcs[32];
+ val38 = ctx->ctx_pmcs[38];
+ check_case1 = 1;
+ break;
+ }
+ /* check illegal configuration which can produce inconsistencies in tagging
+ * i-side events in L1D and L2 caches
+ */
+ if (check_case1) {
+ ret = (((val41 >> 45) & 0xf) == 0 && ((val32>>57) & 0x1) == 0)
+ && ((((val38>>1) & 0x3) == 0x2 || ((val38>>1) & 0x3) == 0)
+ || (((val38>>4) & 0x3) == 0x2 || ((val38>>4) & 0x3) == 0));
+ if (ret) {
+ DPRINT(("invalid config pmc38=0x%lx pmc41=0x%lx pmc32=0x%lx\n", val38, val41, val32));
+ return -EINVAL;
+ }
+ }
+ *val = tmpval;
+ return 0;
+}
+
+/*
+ * impl_pmcs, impl_pmds are computed at runtime to minimize errors!
+ */
+static pmu_config_t pmu_conf_mont={
+ .pmu_name = "Montecito",
+ .pmu_family = 0x20,
+ .flags = PFM_PMU_IRQ_RESEND,
+ .ovfl_val = (1UL << 47) - 1,
+ .pmd_desc = pfm_mont_pmd_desc,
+ .pmc_desc = pfm_mont_pmc_desc,
+ .num_ibrs = 8,
+ .num_dbrs = 8,
+ .use_rr_dbregs = 1 /* debug register are use for range retrictions */
+};
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index e9904c74d2ba..309d59658e5f 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -328,7 +328,7 @@ ia64_save_extra (struct task_struct *task)
#endif
#ifdef CONFIG_IA32_SUPPORT
- if (IS_IA32_PROCESS(ia64_task_regs(task)))
+ if (IS_IA32_PROCESS(task_pt_regs(task)))
ia32_save_state(task);
#endif
}
@@ -353,7 +353,7 @@ ia64_load_extra (struct task_struct *task)
#endif
#ifdef CONFIG_IA32_SUPPORT
- if (IS_IA32_PROCESS(ia64_task_regs(task)))
+ if (IS_IA32_PROCESS(task_pt_regs(task)))
ia32_load_state(task);
#endif
}
@@ -488,7 +488,7 @@ copy_thread (int nr, unsigned long clone_flags,
* If we're cloning an IA32 task then save the IA32 extra
* state from the current task to the new task
*/
- if (IS_IA32_PROCESS(ia64_task_regs(current))) {
+ if (IS_IA32_PROCESS(task_pt_regs(current))) {
ia32_save_state(p);
if (clone_flags & CLONE_SETTLS)
retval = ia32_clone_tls(p, child_ptregs);
@@ -701,7 +701,7 @@ int
kernel_thread_helper (int (*fn)(void *), void *arg)
{
#ifdef CONFIG_IA32_SUPPORT
- if (IS_IA32_PROCESS(ia64_task_regs(current))) {
+ if (IS_IA32_PROCESS(task_pt_regs(current))) {
/* A kernel thread is always a 64-bit process. */
current->thread.map_base = DEFAULT_MAP_BASE;
current->thread.task_size = DEFAULT_TASK_SIZE;
@@ -722,7 +722,7 @@ flush_thread (void)
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
ia64_drop_fpu(current);
#ifdef CONFIG_IA32_SUPPORT
- if (IS_IA32_PROCESS(ia64_task_regs(current))) {
+ if (IS_IA32_PROCESS(task_pt_regs(current))) {
ia32_drop_partial_page_list(current);
current->thread.task_size = IA32_PAGE_OFFSET;
set_fs(USER_DS);
@@ -755,7 +755,7 @@ exit_thread (void)
if (current->thread.flags & IA64_THREAD_DBG_VALID)
pfm_release_debug_registers(current);
#endif
- if (IS_IA32_PROCESS(ia64_task_regs(current)))
+ if (IS_IA32_PROCESS(task_pt_regs(current)))
ia32_drop_partial_page_list(current);
}
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 4b19d0410632..eaed14aac6aa 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -254,7 +254,7 @@ get_rnat (struct task_struct *task, struct switch_stack *sw,
long num_regs, nbits;
struct pt_regs *pt;
- pt = ia64_task_regs(task);
+ pt = task_pt_regs(task);
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
@@ -314,7 +314,7 @@ put_rnat (struct task_struct *task, struct switch_stack *sw,
struct pt_regs *pt;
unsigned long cfm, *urbs_kargs;
- pt = ia64_task_regs(task);
+ pt = task_pt_regs(task);
kbsp = (unsigned long *) sw->ar_bspstore;
ubspstore = (unsigned long *) pt->ar_bspstore;
@@ -407,7 +407,7 @@ ia64_peek (struct task_struct *child, struct switch_stack *child_stack,
urbs_end = (long *) user_rbs_end;
laddr = (unsigned long *) addr;
- child_regs = ia64_task_regs(child);
+ child_regs = task_pt_regs(child);
bspstore = (unsigned long *) child_regs->ar_bspstore;
krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
if (on_kernel_rbs(addr, (unsigned long) bspstore,
@@ -467,7 +467,7 @@ ia64_poke (struct task_struct *child, struct switch_stack *child_stack,
struct pt_regs *child_regs;
laddr = (unsigned long *) addr;
- child_regs = ia64_task_regs(child);
+ child_regs = task_pt_regs(child);
bspstore = (unsigned long *) child_regs->ar_bspstore;
krbs = (unsigned long *) child + IA64_RBS_OFFSET/8;
if (on_kernel_rbs(addr, (unsigned long) bspstore,
@@ -567,7 +567,7 @@ thread_matches (struct task_struct *thread, unsigned long addr)
*/
return 0;
- thread_regs = ia64_task_regs(thread);
+ thread_regs = task_pt_regs(thread);
thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL);
if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end))
return 0;
@@ -627,7 +627,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
inline void
ia64_flush_fph (struct task_struct *task)
{
- struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+ struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
/*
* Prevent migrating this task while
@@ -653,7 +653,7 @@ ia64_flush_fph (struct task_struct *task)
void
ia64_sync_fph (struct task_struct *task)
{
- struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+ struct ia64_psr *psr = ia64_psr(task_pt_regs(task));
ia64_flush_fph(task);
if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) {
@@ -794,7 +794,7 @@ access_uarea (struct task_struct *child, unsigned long addr,
+ offsetof(struct pt_regs, reg)))
- pt = ia64_task_regs(child);
+ pt = task_pt_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
if ((addr & 0x7) != 0) {
@@ -1120,7 +1120,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
if (!access_ok(VERIFY_WRITE, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- pt = ia64_task_regs(child);
+ pt = task_pt_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
unw_init_from_blocked_task(&info, child);
if (unw_unwind_to_user(&info) < 0) {
@@ -1265,7 +1265,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
if (!access_ok(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)))
return -EIO;
- pt = ia64_task_regs(child);
+ pt = task_pt_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
unw_init_from_blocked_task(&info, child);
if (unw_unwind_to_user(&info) < 0) {
@@ -1403,7 +1403,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
void
ptrace_disable (struct task_struct *child)
{
- struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child));
+ struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
/* make sure the single step/taken-branch trap bits are not set: */
child_psr->ss = 0;
@@ -1422,14 +1422,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- current->ptrace |= PT_PTRACED;
- ret = 0;
+ ret = ptrace_traceme();
goto out;
}
@@ -1463,7 +1456,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
if (ret < 0)
goto out_tsk;
- pt = ia64_task_regs(child);
+ pt = task_pt_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);
switch (request) {
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 1461dc660b43..9d5a823479a3 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -3,7 +3,7 @@
*
* Creates entries in /proc/sal for various system features.
*
- * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2003, 2006 Silicon Graphics, Inc. All rights reserved.
* Copyright (c) 2003 Hewlett-Packard Co
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*
@@ -27,8 +27,17 @@
* 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.
+ *
+ * Jan 5 2006 kaos@sgi.com
+ * Handle hotplug cpus coming online.
+ * Handle hotplug cpus going offline while they still have outstanding records.
+ * Use the cpu_* macros consistently.
+ * Replace the counting semaphore with a mutex and a test if the cpumask is non-empty.
+ * Modify the locking to make the test for "work to do" an atomic operation.
*/
+#include <linux/capability.h>
+#include <linux/cpu.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
@@ -131,8 +140,8 @@ enum salinfo_state {
};
struct salinfo_data {
- volatile cpumask_t cpu_event; /* which cpus have outstanding events */
- struct semaphore sem; /* count of cpus with outstanding events (bits set in cpu_event) */
+ cpumask_t cpu_event; /* which cpus have outstanding events */
+ struct semaphore mutex;
u8 *log_buffer;
u64 log_size;
u8 *oemdata; /* decoded oem data */
@@ -173,6 +182,21 @@ struct salinfo_platform_oemdata_parms {
int ret;
};
+/* Kick the mutex that tells user space that there is work to do. Instead of
+ * trying to track the state of the mutex across multiple cpus, in user
+ * context, interrupt context, non-maskable interrupt context and hotplug cpu,
+ * it is far easier just to grab the mutex if it is free then release it.
+ *
+ * This routine must be called with data_saved_lock held, to make the down/up
+ * operation atomic.
+ */
+static void
+salinfo_work_to_do(struct salinfo_data *data)
+{
+ down_trylock(&data->mutex);
+ up(&data->mutex);
+}
+
static void
salinfo_platform_oemdata_cpu(void *context)
{
@@ -211,9 +235,9 @@ 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);
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;
@@ -231,13 +255,11 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
data_saved->size = size;
data_saved->buffer = buffer;
}
- if (irqsafe)
- spin_unlock_irqrestore(&data_saved_lock, flags);
}
-
- if (!test_and_set_bit(smp_processor_id(), &data->cpu_event)) {
- if (irqsafe)
- up(&data->sem);
+ cpu_set(smp_processor_id(), data->cpu_event);
+ if (irqsafe) {
+ salinfo_work_to_do(data);
+ spin_unlock_irqrestore(&data_saved_lock, flags);
}
}
@@ -248,20 +270,17 @@ static struct timer_list salinfo_timer;
static void
salinfo_timeout_check(struct salinfo_data *data)
{
- int i;
+ unsigned long flags;
if (!data->open)
return;
- 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".
- */
- up(&data->sem);
- }
+ if (!cpus_empty(data->cpu_event)) {
+ spin_lock_irqsave(&data_saved_lock, flags);
+ salinfo_work_to_do(data);
+ spin_unlock_irqrestore(&data_saved_lock, flags);
}
}
-static void
+static void
salinfo_timeout (unsigned long arg)
{
salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
@@ -289,16 +308,20 @@ salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t
int i, n, cpu = -1;
retry:
- if (down_trylock(&data->sem)) {
+ if (cpus_empty(data->cpu_event) && down_trylock(&data->mutex)) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
- if (down_interruptible(&data->sem))
+ if (down_interruptible(&data->mutex))
return -EINTR;
}
n = data->cpu_check;
for (i = 0; i < NR_CPUS; i++) {
- if (test_bit(n, &data->cpu_event) && cpu_online(n)) {
+ if (cpu_isset(n, data->cpu_event)) {
+ if (!cpu_online(n)) {
+ cpu_clear(n, data->cpu_event);
+ continue;
+ }
cpu = n;
break;
}
@@ -309,9 +332,6 @@ retry:
if (cpu == -1)
goto retry;
- /* events are sticky until the user says "clear" */
- up(&data->sem);
-
/* for next read, start checking at next CPU */
data->cpu_check = cpu;
if (++data->cpu_check == NR_CPUS)
@@ -380,10 +400,8 @@ salinfo_log_release(struct inode *inode, struct file *file)
static void
call_on_cpu(int cpu, void (*fn)(void *), void *arg)
{
- cpumask_t save_cpus_allowed, new_cpus_allowed;
- memcpy(&save_cpus_allowed, &current->cpus_allowed, sizeof(save_cpus_allowed));
- memset(&new_cpus_allowed, 0, sizeof(new_cpus_allowed));
- set_bit(cpu, &new_cpus_allowed);
+ cpumask_t save_cpus_allowed = current->cpus_allowed;
+ cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu);
set_cpus_allowed(current, new_cpus_allowed);
(*fn)(arg);
set_cpus_allowed(current, save_cpus_allowed);
@@ -432,10 +450,10 @@ retry:
if (!data->saved_num)
call_on_cpu(cpu, salinfo_log_read_cpu, data);
if (!data->log_size) {
- data->state = STATE_NO_DATA;
- clear_bit(cpu, &data->cpu_event);
+ data->state = STATE_NO_DATA;
+ cpu_clear(cpu, data->cpu_event);
} else {
- data->state = STATE_LOG_RECORD;
+ data->state = STATE_LOG_RECORD;
}
}
@@ -472,27 +490,31 @@ static int
salinfo_log_clear(struct salinfo_data *data, int cpu)
{
sal_log_record_header_t *rh;
+ unsigned long flags;
+ spin_lock_irqsave(&data_saved_lock, flags);
data->state = STATE_NO_DATA;
- if (!test_bit(cpu, &data->cpu_event))
+ if (!cpu_isset(cpu, data->cpu_event)) {
+ spin_unlock_irqrestore(&data_saved_lock, flags);
return 0;
- down(&data->sem);
- clear_bit(cpu, &data->cpu_event);
+ }
+ cpu_clear(cpu, data->cpu_event);
if (data->saved_num) {
- unsigned long flags;
- spin_lock_irqsave(&data_saved_lock, flags);
- shift1_data_saved(data, data->saved_num - 1 );
+ shift1_data_saved(data, data->saved_num - 1);
data->saved_num = 0;
- spin_unlock_irqrestore(&data_saved_lock, flags);
}
+ spin_unlock_irqrestore(&data_saved_lock, flags);
rh = (sal_log_record_header_t *)(data->log_buffer);
/* Corrected errors have already been cleared from SAL */
if (rh->severity != sal_log_severity_corrected)
call_on_cpu(cpu, salinfo_log_clear_cpu, data);
/* clearing a record may make a new record visible */
salinfo_log_new_read(cpu, data);
- if (data->state == STATE_LOG_RECORD &&
- !test_and_set_bit(cpu, &data->cpu_event))
- up(&data->sem);
+ if (data->state == STATE_LOG_RECORD) {
+ spin_lock_irqsave(&data_saved_lock, flags);
+ cpu_set(cpu, data->cpu_event);
+ salinfo_work_to_do(data);
+ spin_unlock_irqrestore(&data_saved_lock, flags);
+ }
return 0;
}
@@ -549,6 +571,53 @@ static struct file_operations salinfo_data_fops = {
.write = salinfo_log_write,
};
+#ifdef CONFIG_HOTPLUG_CPU
+static int __devinit
+salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+{
+ unsigned int i, cpu = (unsigned long)hcpu;
+ unsigned long flags;
+ struct salinfo_data *data;
+ switch (action) {
+ case CPU_ONLINE:
+ spin_lock_irqsave(&data_saved_lock, flags);
+ for (i = 0, data = salinfo_data;
+ i < ARRAY_SIZE(salinfo_data);
+ ++i, ++data) {
+ cpu_set(cpu, data->cpu_event);
+ salinfo_work_to_do(data);
+ }
+ spin_unlock_irqrestore(&data_saved_lock, flags);
+ break;
+ case CPU_DEAD:
+ spin_lock_irqsave(&data_saved_lock, flags);
+ for (i = 0, data = salinfo_data;
+ i < ARRAY_SIZE(salinfo_data);
+ ++i, ++data) {
+ struct salinfo_data_saved *data_saved;
+ int j;
+ for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;
+ j >= 0;
+ --j, --data_saved) {
+ if (data_saved->buffer && data_saved->cpu == cpu) {
+ shift1_data_saved(data, j);
+ }
+ }
+ cpu_clear(cpu, data->cpu_event);
+ }
+ spin_unlock_irqrestore(&data_saved_lock, flags);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block salinfo_cpu_notifier =
+{
+ .notifier_call = salinfo_cpu_callback,
+ .priority = 0,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
static int __init
salinfo_init(void)
{
@@ -556,7 +625,7 @@ salinfo_init(void)
struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
struct proc_dir_entry *dir, *entry;
struct salinfo_data *data;
- int i, j, online;
+ int i, j;
salinfo_dir = proc_mkdir("sal", NULL);
if (!salinfo_dir)
@@ -571,7 +640,7 @@ salinfo_init(void)
for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
data = salinfo_data + i;
data->type = i;
- sema_init(&data->sem, 0);
+ init_MUTEX(&data->mutex);
dir = proc_mkdir(salinfo_log_name[i], salinfo_dir);
if (!dir)
continue;
@@ -591,12 +660,8 @@ salinfo_init(void)
*sdir++ = entry;
/* we missed any events before now */
- online = 0;
- for_each_online_cpu(j) {
- set_bit(j, &data->cpu_event);
- ++online;
- }
- sema_init(&data->sem, online);
+ for_each_online_cpu(j)
+ cpu_set(j, data->cpu_event);
*sdir++ = dir;
}
@@ -608,6 +673,10 @@ salinfo_init(void)
salinfo_timer.function = &salinfo_timeout;
add_timer(&salinfo_timer);
+#ifdef CONFIG_HOTPLUG_CPU
+ register_cpu_notifier(&salinfo_cpu_notifier);
+#endif
+
return 0;
}
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 5add0bcf87a7..c0766575a3a2 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -43,6 +43,7 @@
#include <linux/initrd.h>
#include <linux/platform.h>
#include <linux/pm.h>
+#include <linux/cpufreq.h>
#include <asm/ia32.h>
#include <asm/machvec.h>
@@ -59,6 +60,7 @@
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/unistd.h>
+#include <asm/system.h>
#if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
# error "struct cpuinfo_ia64 too big!"
@@ -517,6 +519,7 @@ show_cpuinfo (struct seq_file *m, void *v)
char family[32], features[128], *cp, sep;
struct cpuinfo_ia64 *c = v;
unsigned long mask;
+ unsigned long proc_freq;
int i;
mask = c->features;
@@ -549,6 +552,10 @@ show_cpuinfo (struct seq_file *m, void *v)
sprintf(cp, " 0x%lx", mask);
}
+ proc_freq = cpufreq_quick_get(cpunum);
+ if (!proc_freq)
+ proc_freq = c->proc_freq / 1000;
+
seq_printf(m,
"processor : %d\n"
"vendor : %s\n"
@@ -565,7 +572,7 @@ show_cpuinfo (struct seq_file *m, void *v)
"BogoMIPS : %lu.%02lu\n",
cpunum, c->vendor, family, c->model, c->revision, c->archrev,
features, c->ppn, c->number,
- c->proc_freq / 1000000, c->proc_freq % 1000000,
+ proc_freq / 1000, proc_freq % 1000,
c->itc_freq / 1000000, c->itc_freq % 1000000,
lpj*HZ/500000, (lpj*HZ/5000) % 100);
#ifdef CONFIG_SMP
@@ -689,6 +696,7 @@ static void
get_max_cacheline_size (void)
{
unsigned long line_size, max = 1;
+ unsigned int cache_size = 0;
u64 l, levels, unique_caches;
pal_cache_config_info_t cci;
s64 status;
@@ -718,6 +726,8 @@ get_max_cacheline_size (void)
line_size = 1 << cci.pcci_line_size;
if (line_size > max)
max = line_size;
+ if (cache_size < cci.pcci_cache_size)
+ cache_size = cci.pcci_cache_size;
if (!cci.pcci_unified) {
status = ia64_pal_cache_config_info(l,
/* cache_type (instruction)= */ 1,
@@ -734,6 +744,9 @@ get_max_cacheline_size (void)
ia64_i_cache_stride_shift = cci.pcci_stride;
}
out:
+#ifdef CONFIG_SMP
+ max_cache_size = max(max_cache_size, cache_size);
+#endif
if (max > ia64_max_cacheline_size)
ia64_max_cacheline_size = max;
}
@@ -788,7 +801,7 @@ cpu_init (void)
#endif
/* Clear the stack memory reserved for pt_regs: */
- memset(ia64_task_regs(current), 0, sizeof(struct pt_regs));
+ memset(task_pt_regs(current), 0, sizeof(struct pt_regs));
ia64_set_kr(IA64_KR_FPU_OWNER, 0);
@@ -864,6 +877,15 @@ cpu_init (void)
pm_idle = default_idle;
}
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ */
+void sched_cacheflush(void)
+{
+ ia64_sal_cache_flush(3);
+}
+
void
check_bugs (void)
{
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 58ce07efc56e..463f6bb44d07 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -655,11 +655,11 @@ set_sigdelayed(pid_t pid, int signo, int code, void __user *addr)
if (!t)
return;
- t->thread_info->sigdelayed.signo = signo;
- t->thread_info->sigdelayed.code = code;
- t->thread_info->sigdelayed.addr = addr;
- t->thread_info->sigdelayed.start_time = start_time;
- t->thread_info->sigdelayed.pid = pid;
+ task_thread_info(t)->sigdelayed.signo = signo;
+ task_thread_info(t)->sigdelayed.code = code;
+ task_thread_info(t)->sigdelayed.addr = addr;
+ task_thread_info(t)->sigdelayed.start_time = start_time;
+ task_thread_info(t)->sigdelayed.pid = pid;
wmb();
set_tsk_thread_flag(t, TIF_SIGDELAYED);
}
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index f2dbcd1db0d4..c7b943f10199 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -151,7 +151,7 @@ out:
asmlinkage long
sys_pipe (void)
{
- struct pt_regs *regs = ia64_task_regs(current);
+ struct pt_regs *regs = task_pt_regs(current);
int fd[2];
int retval;
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index d3e0ecb56d62..55391901b013 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -530,12 +530,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
if (fsys_mode(current, &regs)) {
extern char __kernel_syscall_via_break[];
/*
- * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
- * need special handling; Debug trap is not supposed to happen.
+ * Got a trap in fsys-mode: Taken Branch Trap
+ * and Single Step trap need special handling;
+ * Debug trap is ignored (we disable it here
+ * and re-enable it in the lower-privilege trap).
*/
if (unlikely(vector == 29)) {
- die("Got debug trap in fsys-mode---not supposed to happen!",
- &regs, 0);
+ set_thread_flag(TIF_DB_DISABLED);
+ ia64_psr(&regs)->db = 0;
+ ia64_psr(&regs)->lp = 1;
return;
}
/* re-do the system call via break 0x100000: */
@@ -589,10 +592,19 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case 34:
if (isr & 0x2) {
/* Lower-Privilege Transfer Trap */
+
+ /* If we disabled debug traps during an fsyscall,
+ * re-enable them here.
+ */
+ if (test_thread_flag(TIF_DB_DISABLED)) {
+ clear_thread_flag(TIF_DB_DISABLED);
+ ia64_psr(&regs)->db = 1;
+ }
+
/*
- * Just clear PSR.lp and then return immediately: all the
- * interesting work (e.g., signal delivery is done in the kernel
- * exit path).
+ * Just clear PSR.lp and then return immediately:
+ * all the interesting work (e.g., signal delivery)
+ * is done in the kernel exit path.
*/
ia64_psr(&regs)->lp = 0;
return;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index e3215ba64ffd..b38b6d213c15 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -635,3 +635,39 @@ mem_init (void)
ia32_mem_init();
#endif
}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void online_page(struct page *page)
+{
+ ClearPageReserved(page);
+ set_page_count(page, 1);
+ __free_page(page);
+ totalram_pages++;
+ num_physpages++;
+}
+
+int add_memory(u64 start, u64 size)
+{
+ pg_data_t *pgdat;
+ struct zone *zone;
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ int ret;
+
+ pgdat = NODE_DATA(0);
+
+ zone = pgdat->node_zones + ZONE_NORMAL;
+ ret = __add_pages(zone, start_pfn, nr_pages);
+
+ if (ret)
+ printk("%s: Problem encountered in __add_pages() as ret=%d\n",
+ __FUNCTION__, ret);
+
+ return ret;
+}
+
+int remove_memory(u64 start, u64 size)
+{
+ return -EINVAL;
+}
+#endif
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 41105d454423..6a4eec9113e8 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -90,7 +90,7 @@ ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start,
{
static DEFINE_SPINLOCK(ptcg_lock);
- if (mm != current->active_mm) {
+ if (mm != current->active_mm || !current->mm) {
flush_tlb_all();
return;
}
diff --git a/arch/ia64/oprofile/backtrace.c b/arch/ia64/oprofile/backtrace.c
index b7dabbfb0d61..adb01566bd57 100644
--- a/arch/ia64/oprofile/backtrace.c
+++ b/arch/ia64/oprofile/backtrace.c
@@ -32,7 +32,7 @@ typedef struct
u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */
} ia64_backtrace_t;
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
/*
* Returns non-zero if the PC is in the spinlock contention out-of-line code
* with non-standard calling sequence (on older compilers).
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 20d76fae24e8..d27ecdcb6fca 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -454,14 +454,13 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
return 0;
}
-static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+static void __devinit
+pcibios_fixup_resources(struct pci_dev *dev, int start, int limit)
{
struct pci_bus_region region;
int i;
- int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \
- PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
- for (i = 0; i < limit; i++) {
+ for (i = start; i < limit; i++) {
if (!dev->resource[i].flags)
continue;
region.start = dev->resource[i].start;
@@ -472,6 +471,16 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
}
}
+static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+{
+ pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
+}
+
+static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
+{
+ pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES);
+}
+
/*
* Called after each bus is probed, but before its children are examined.
*/
@@ -482,7 +491,7 @@ pcibios_fixup_bus (struct pci_bus *b)
if (b->self) {
pci_read_bridge_bases(b);
- pcibios_fixup_device_resources(b->self);
+ pcibios_fixup_bridge_resources(b->self);
}
list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev);
@@ -700,7 +709,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
*/
int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
{
- int ret = 0;
+ int ret = size;
switch (size) {
case 1:
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
index 71c2b271b4c6..7c88e9a58516 100644
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ b/arch/ia64/sn/include/xtalk/hubdev.h
@@ -26,29 +26,37 @@
#define IIO_NUM_ITTES 7
#define HUB_NUM_BIG_WINDOW (IIO_NUM_ITTES - 1)
-struct sn_flush_device_list {
+/* This struct is shared between the PROM and the kernel.
+ * Changes to this struct will require corresponding changes to the kernel.
+ */
+struct sn_flush_device_common {
int sfdl_bus;
int sfdl_slot;
int sfdl_pin;
- struct bar_list {
+ struct common_bar_list {
unsigned long start;
unsigned long end;
} sfdl_bar_list[6];
unsigned long sfdl_force_int_addr;
unsigned long sfdl_flush_value;
volatile unsigned long *sfdl_flush_addr;
- uint32_t sfdl_persistent_busnum;
- uint32_t sfdl_persistent_segment;
+ u32 sfdl_persistent_busnum;
+ u32 sfdl_persistent_segment;
struct pcibus_info *sfdl_pcibus_info;
+};
+
+/* This struct is kernel only and is not used by the PROM */
+struct sn_flush_device_kernel {
spinlock_t sfdl_flush_lock;
+ struct sn_flush_device_common *common;
};
/*
- * **widget_p - Used as an array[wid_num][device] of sn_flush_device_list.
+ * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel.
*/
struct sn_flush_nasid_entry {
- struct sn_flush_device_list **widget_p; /* Used as a array of wid_num */
- uint64_t iio_itte[8];
+ struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num
+ u64 iio_itte[8];
};
struct hubdev_info {
@@ -62,8 +70,8 @@ struct hubdev_info {
void *hdi_nodepda;
void *hdi_node_vertex;
- uint32_t max_segment_number;
- uint32_t max_pcibus_number;
+ u32 max_segment_number;
+ u32 max_pcibus_number;
};
extern void hubdev_init_node(nodepda_t *, cnodeid_t);
diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h
index ec56b3432f17..90f37a4133d0 100644
--- a/arch/ia64/sn/include/xtalk/xbow.h
+++ b/arch/ia64/sn/include/xtalk/xbow.h
@@ -3,7 +3,8 @@
* 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-2006 Silicon Graphics, Inc. All Rights
+ * Reserved.
*/
#ifndef _ASM_IA64_SN_XTALK_XBOW_H
#define _ASM_IA64_SN_XTALK_XBOW_H
@@ -21,94 +22,94 @@
/* Register set for each xbow link */
typedef volatile struct xb_linkregs_s {
-/*
+/*
* we access these through synergy unswizzled space, so the address
* gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
* That's why we put the register first and filler second.
*/
- uint32_t link_ibf;
- uint32_t filler0; /* filler for proper alignment */
- uint32_t link_control;
- uint32_t filler1;
- uint32_t link_status;
- uint32_t filler2;
- uint32_t link_arb_upper;
- uint32_t filler3;
- uint32_t link_arb_lower;
- uint32_t filler4;
- uint32_t link_status_clr;
- uint32_t filler5;
- uint32_t link_reset;
- uint32_t filler6;
- uint32_t link_aux_status;
- uint32_t filler7;
+ u32 link_ibf;
+ u32 filler0; /* filler for proper alignment */
+ u32 link_control;
+ u32 filler1;
+ u32 link_status;
+ u32 filler2;
+ u32 link_arb_upper;
+ u32 filler3;
+ u32 link_arb_lower;
+ u32 filler4;
+ u32 link_status_clr;
+ u32 filler5;
+ u32 link_reset;
+ u32 filler6;
+ u32 link_aux_status;
+ u32 filler7;
} xb_linkregs_t;
typedef volatile struct xbow_s {
- /* standard widget configuration 0x000000-0x000057 */
- struct widget_cfg xb_widget; /* 0x000000 */
-
- /* helper fieldnames for accessing bridge widget */
-
-#define xb_wid_id xb_widget.w_id
-#define xb_wid_stat xb_widget.w_status
-#define xb_wid_err_upper xb_widget.w_err_upper_addr
-#define xb_wid_err_lower xb_widget.w_err_lower_addr
-#define xb_wid_control xb_widget.w_control
-#define xb_wid_req_timeout xb_widget.w_req_timeout
-#define xb_wid_int_upper xb_widget.w_intdest_upper_addr
-#define xb_wid_int_lower xb_widget.w_intdest_lower_addr
-#define xb_wid_err_cmdword xb_widget.w_err_cmd_word
-#define xb_wid_llp xb_widget.w_llp_cfg
-#define xb_wid_stat_clr xb_widget.w_tflush
-
-/*
+ /* standard widget configuration 0x000000-0x000057 */
+ struct widget_cfg xb_widget; /* 0x000000 */
+
+ /* helper fieldnames for accessing bridge widget */
+
+#define xb_wid_id xb_widget.w_id
+#define xb_wid_stat xb_widget.w_status
+#define xb_wid_err_upper xb_widget.w_err_upper_addr
+#define xb_wid_err_lower xb_widget.w_err_lower_addr
+#define xb_wid_control xb_widget.w_control
+#define xb_wid_req_timeout xb_widget.w_req_timeout
+#define xb_wid_int_upper xb_widget.w_intdest_upper_addr
+#define xb_wid_int_lower xb_widget.w_intdest_lower_addr
+#define xb_wid_err_cmdword xb_widget.w_err_cmd_word
+#define xb_wid_llp xb_widget.w_llp_cfg
+#define xb_wid_stat_clr xb_widget.w_tflush
+
+/*
* we access these through synergy unswizzled space, so the address
* gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.)
* That's why we put the register first and filler second.
*/
- /* xbow-specific widget configuration 0x000058-0x0000FF */
- uint32_t xb_wid_arb_reload; /* 0x00005C */
- uint32_t _pad_000058;
- uint32_t xb_perf_ctr_a; /* 0x000064 */
- uint32_t _pad_000060;
- uint32_t xb_perf_ctr_b; /* 0x00006c */
- uint32_t _pad_000068;
- uint32_t xb_nic; /* 0x000074 */
- uint32_t _pad_000070;
-
- /* Xbridge only */
- uint32_t xb_w0_rst_fnc; /* 0x00007C */
- uint32_t _pad_000078;
- uint32_t xb_l8_rst_fnc; /* 0x000084 */
- uint32_t _pad_000080;
- uint32_t xb_l9_rst_fnc; /* 0x00008c */
- uint32_t _pad_000088;
- uint32_t xb_la_rst_fnc; /* 0x000094 */
- uint32_t _pad_000090;
- uint32_t xb_lb_rst_fnc; /* 0x00009c */
- uint32_t _pad_000098;
- uint32_t xb_lc_rst_fnc; /* 0x0000a4 */
- uint32_t _pad_0000a0;
- uint32_t xb_ld_rst_fnc; /* 0x0000ac */
- uint32_t _pad_0000a8;
- uint32_t xb_le_rst_fnc; /* 0x0000b4 */
- uint32_t _pad_0000b0;
- uint32_t xb_lf_rst_fnc; /* 0x0000bc */
- uint32_t _pad_0000b8;
- uint32_t xb_lock; /* 0x0000c4 */
- uint32_t _pad_0000c0;
- uint32_t xb_lock_clr; /* 0x0000cc */
- uint32_t _pad_0000c8;
- /* end of Xbridge only */
- uint32_t _pad_0000d0[12];
-
- /* Link Specific Registers, port 8..15 0x000100-0x000300 */
- xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS];
-#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)]
-
+ /* xbow-specific widget configuration 0x000058-0x0000FF */
+ u32 xb_wid_arb_reload; /* 0x00005C */
+ u32 _pad_000058;
+ u32 xb_perf_ctr_a; /* 0x000064 */
+ u32 _pad_000060;
+ u32 xb_perf_ctr_b; /* 0x00006c */
+ u32 _pad_000068;
+ u32 xb_nic; /* 0x000074 */
+ u32 _pad_000070;
+
+ /* Xbridge only */
+ u32 xb_w0_rst_fnc; /* 0x00007C */
+ u32 _pad_000078;
+ u32 xb_l8_rst_fnc; /* 0x000084 */
+ u32 _pad_000080;
+ u32 xb_l9_rst_fnc; /* 0x00008c */
+ u32 _pad_000088;
+ u32 xb_la_rst_fnc; /* 0x000094 */
+ u32 _pad_000090;
+ u32 xb_lb_rst_fnc; /* 0x00009c */
+ u32 _pad_000098;
+ u32 xb_lc_rst_fnc; /* 0x0000a4 */
+ u32 _pad_0000a0;
+ u32 xb_ld_rst_fnc; /* 0x0000ac */
+ u32 _pad_0000a8;
+ u32 xb_le_rst_fnc; /* 0x0000b4 */
+ u32 _pad_0000b0;
+ u32 xb_lf_rst_fnc; /* 0x0000bc */
+ u32 _pad_0000b8;
+ u32 xb_lock; /* 0x0000c4 */
+ u32 _pad_0000c0;
+ u32 xb_lock_clr; /* 0x0000cc */
+ u32 _pad_0000c8;
+ /* end of Xbridge only */
+ u32 _pad_0000d0[12];
+
+ /* Link Specific Registers, port 8..15 0x000100-0x000300 */
+ xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS];
} xbow_t;
+#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)]
+
#define XB_FLAGS_EXISTS 0x1 /* device exists */
#define XB_FLAGS_MASTER 0x2
#define XB_FLAGS_SLAVE 0x0
@@ -160,7 +161,7 @@ typedef volatile struct xbow_s {
/* End of Xbridge only */
/* used only in ide, but defined here within the reserved portion */
-/* of the widget0 address space (before 0xf4) */
+/* of the widget0 address space (before 0xf4) */
#define XBOW_WID_UNDEF 0xe4
/* xbow link register set base, legal value for x is 0x8..0xf */
@@ -179,29 +180,37 @@ typedef volatile struct xbow_s {
/* link_control(x) */
#define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */
- /* reserved: 0x40000000 */
+/* reserved: 0x40000000 */
#define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */
-#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */
-#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */
-#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */
-#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */
-#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */
-#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */
-#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */
- /* reserved: 0x0000fe00 */
+#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer
+ level */
+#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8
+ bit mode */
+#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP
+ packet */
+#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit
+ mask */
+#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit
+ shift */
+#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination
+ */
+#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input
+ buffer */
+/* reserved: 0x0000fe00 */
#define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */
#define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */
#define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */
#define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */
#define XB_CTRL_RCV_IE 0x00000010 /* receive */
#define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */
- /* reserved: 0x00000004 */
-#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */
+/* reserved: 0x00000004 */
+#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request
+ timeout */
#define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */
/* link_status(x) */
#define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE
- /* reserved: 0x7ff80000 */
+/* reserved: 0x7ff80000 */
#define XB_STAT_MULTI_ERR 0x00040000 /* multi error */
#define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE
#define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE
@@ -211,7 +220,7 @@ typedef volatile struct xbow_s {
#define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE
#define XB_STAT_RCV_ERR XB_CTRL_RCV_IE
#define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE
- /* reserved: 0x00000004 */
+/* reserved: 0x00000004 */
#define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE
#define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE
@@ -222,7 +231,7 @@ typedef volatile struct xbow_s {
#define XB_AUX_LINKFAIL_RST_BAD 0x00000040
#define XB_AUX_STAT_PRESENT 0x00000020
#define XB_AUX_STAT_PORT_WIDTH 0x00000010
- /* reserved: 0x0000000f */
+/* reserved: 0x0000000f */
/*
* link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper
@@ -238,7 +247,8 @@ typedef volatile struct xbow_s {
/* XBOW_WID_STAT */
#define XB_WID_STAT_LINK_INTR_SHFT (24)
#define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT)
-#define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT))
+#define XB_WID_STAT_LINK_INTR(x) \
+ (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT))
#define XB_WID_STAT_WIDGET0_INTR 0x00800000
#define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */
#define XB_WID_STAT_REG_ACC_ERR 0x00000020
@@ -264,7 +274,7 @@ typedef volatile struct xbow_s {
#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */
#define XBOW_WIDGET_MFGR_NUM 0x0
#define XXBOW_WIDGET_MFGR_NUM 0x0
-#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */
+#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */
#define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */
#define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */
@@ -279,13 +289,13 @@ typedef volatile struct xbow_s {
#define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */
#define IS_XBRIDGE_XBOW(wid) \
- (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \
- XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
+ (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \
+ XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
#define IS_PIC_XBOW(wid) \
- (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \
- XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
+ (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \
+ XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM)
#define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv)
-#endif /* _ASM_IA64_SN_XTALK_XBOW_H */
+#endif /* _ASM_IA64_SN_XTALK_XBOW_H */
diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h
index c5f4bc5cc033..2800eda0fd68 100644
--- a/arch/ia64/sn/include/xtalk/xwidgetdev.h
+++ b/arch/ia64/sn/include/xtalk/xwidgetdev.h
@@ -25,28 +25,28 @@
/* widget configuration registers */
struct widget_cfg{
- uint32_t w_id; /* 0x04 */
- uint32_t w_pad_0; /* 0x00 */
- uint32_t w_status; /* 0x0c */
- uint32_t w_pad_1; /* 0x08 */
- uint32_t w_err_upper_addr; /* 0x14 */
- uint32_t w_pad_2; /* 0x10 */
- uint32_t w_err_lower_addr; /* 0x1c */
- uint32_t w_pad_3; /* 0x18 */
- uint32_t w_control; /* 0x24 */
- uint32_t w_pad_4; /* 0x20 */
- uint32_t w_req_timeout; /* 0x2c */
- uint32_t w_pad_5; /* 0x28 */
- uint32_t w_intdest_upper_addr; /* 0x34 */
- uint32_t w_pad_6; /* 0x30 */
- uint32_t w_intdest_lower_addr; /* 0x3c */
- uint32_t w_pad_7; /* 0x38 */
- uint32_t w_err_cmd_word; /* 0x44 */
- uint32_t w_pad_8; /* 0x40 */
- uint32_t w_llp_cfg; /* 0x4c */
- uint32_t w_pad_9; /* 0x48 */
- uint32_t w_tflush; /* 0x54 */
- uint32_t w_pad_10; /* 0x50 */
+ u32 w_id; /* 0x04 */
+ u32 w_pad_0; /* 0x00 */
+ u32 w_status; /* 0x0c */
+ u32 w_pad_1; /* 0x08 */
+ u32 w_err_upper_addr; /* 0x14 */
+ u32 w_pad_2; /* 0x10 */
+ u32 w_err_lower_addr; /* 0x1c */
+ u32 w_pad_3; /* 0x18 */
+ u32 w_control; /* 0x24 */
+ u32 w_pad_4; /* 0x20 */
+ u32 w_req_timeout; /* 0x2c */
+ u32 w_pad_5; /* 0x28 */
+ u32 w_intdest_upper_addr; /* 0x34 */
+ u32 w_pad_6; /* 0x30 */
+ u32 w_intdest_lower_addr; /* 0x3c */
+ u32 w_pad_7; /* 0x38 */
+ u32 w_err_cmd_word; /* 0x44 */
+ u32 w_pad_8; /* 0x40 */
+ u32 w_llp_cfg; /* 0x4c */
+ u32 w_pad_9; /* 0x48 */
+ u32 w_tflush; /* 0x54 */
+ u32 w_pad_10; /* 0x50 */
};
/*
@@ -63,7 +63,7 @@ struct xwidget_info{
struct xwidget_hwid xwi_hwid; /* Widget Identification */
char xwi_masterxid; /* Hub's Widget Port Number */
void *xwi_hubinfo; /* Hub's provider private info */
- uint64_t *xwi_hub_provider; /* prom provider functions */
+ u64 *xwi_hub_provider; /* prom provider functions */
void *xwi_vertex;
};
diff --git a/arch/ia64/sn/kernel/bte_error.c b/arch/ia64/sn/kernel/bte_error.c
index fcbc748ae433..f1ec1370b3e3 100644
--- a/arch/ia64/sn/kernel/bte_error.c
+++ b/arch/ia64/sn/kernel/bte_error.c
@@ -33,7 +33,7 @@ void bte_error_handler(unsigned long);
* Wait until all BTE related CRBs are completed
* and then reset the interfaces.
*/
-void shub1_bte_error_handler(unsigned long _nodepda)
+int shub1_bte_error_handler(unsigned long _nodepda)
{
struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
@@ -53,7 +53,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
(err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
smp_processor_id()));
- return;
+ return 1;
}
/* Determine information about our hub */
@@ -81,7 +81,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
mod_timer(recovery_timer, HZ * 5);
BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
smp_processor_id()));
- return;
+ return 1;
}
if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
@@ -99,7 +99,7 @@ void shub1_bte_error_handler(unsigned long _nodepda)
BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
err_nodepda, smp_processor_id(),
i));
- return;
+ return 1;
}
}
}
@@ -124,6 +124,42 @@ void shub1_bte_error_handler(unsigned long _nodepda)
REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
del_timer(recovery_timer);
+ return 0;
+}
+
+/*
+ * Wait until all BTE related CRBs are completed
+ * and then reset the interfaces.
+ */
+int shub2_bte_error_handler(unsigned long _nodepda)
+{
+ struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
+ struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
+ struct bteinfo_s *bte;
+ nasid_t nasid;
+ u64 status;
+ int i;
+
+ nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
+
+ /*
+ * Verify that all the BTEs are complete
+ */
+ for (i = 0; i < BTES_PER_NODE; i++) {
+ bte = &err_nodepda->bte_if[i];
+ status = BTE_LNSTAT_LOAD(bte);
+ if ((status & IBLS_ERROR) || !(status & IBLS_BUSY))
+ continue;
+ mod_timer(recovery_timer, HZ * 5);
+ BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
+ smp_processor_id()));
+ return 1;
+ }
+ if (ia64_sn_bte_recovery(nasid))
+ panic("bte_error_handler(): Fatal BTE Error");
+
+ del_timer(recovery_timer);
+ return 0;
}
/*
@@ -135,7 +171,6 @@ void bte_error_handler(unsigned long _nodepda)
struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
int i;
- nasid_t nasid;
unsigned long irq_flags;
volatile u64 *notify;
bte_result_t bh_error;
@@ -160,12 +195,15 @@ void bte_error_handler(unsigned long _nodepda)
}
if (is_shub1()) {
- shub1_bte_error_handler(_nodepda);
+ if (shub1_bte_error_handler(_nodepda)) {
+ spin_unlock_irqrestore(recovery_lock, irq_flags);
+ return;
+ }
} else {
- nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
-
- if (ia64_sn_bte_recovery(nasid))
- panic("bte_error_handler(): Fatal BTE Error");
+ if (shub2_bte_error_handler(_nodepda)) {
+ spin_unlock_irqrestore(recovery_lock, irq_flags);
+ return;
+ }
}
for (i = 0; i < BTES_PER_NODE; i++) {
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 5c5eb01c50f0..56ab6bae00ee 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -32,13 +32,14 @@ static irqreturn_t hub_eint_handler(int irq, void *arg, struct pt_regs *ep)
ret_stuff.v0 = 0;
hubdev_info = (struct hubdev_info *)arg;
nasid = hubdev_info->hdi_nasid;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
+
+ if (is_shub1()) {
+ SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
(u64) nasid, 0, 0, 0, 0, 0, 0);
- if ((int)ret_stuff.v0)
- panic("hubii_eint_handler(): Fatal TIO Error");
+ if ((int)ret_stuff.v0)
+ panic("hubii_eint_handler(): Fatal TIO Error");
- if (is_shub1()) {
if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
(void)hubiio_crb_error_handler(hubdev_info);
} else
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 318087e35b66..233d55115d33 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -76,11 +76,12 @@ static struct sn_pcibus_provider sn_pci_default_provider = {
};
/*
- * Retrieve the DMA Flush List given nasid. This list is needed
- * to implement the WAR - Flush DMA data on PIO Reads.
+ * Retrieve the DMA Flush List given nasid, widget, and device.
+ * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
*/
-static inline uint64_t
-sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address)
+static inline u64
+sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
+ u64 address)
{
struct ia64_sal_retval ret_stuff;
@@ -88,17 +89,17 @@ sal_get_widget_dmaflush_list(u64 nasid, u64 widget_num, u64 address)
ret_stuff.v0 = 0;
SAL_CALL_NOLOCK(ret_stuff,
- (u64) SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
- (u64) nasid, (u64) widget_num, (u64) address, 0, 0, 0,
- 0);
- return ret_stuff.v0;
+ (u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
+ (u64) nasid, (u64) widget_num,
+ (u64) device_num, (u64) address, 0, 0, 0);
+ return ret_stuff.status;
}
/*
* Retrieve the hub device info structure for the given nasid.
*/
-static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address)
+static inline u64 sal_get_hubdev_info(u64 handle, u64 address)
{
struct ia64_sal_retval ret_stuff;
@@ -114,7 +115,7 @@ static inline uint64_t sal_get_hubdev_info(u64 handle, u64 address)
/*
* Retrieve the pci bus information given the bus number.
*/
-static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
+static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
{
struct ia64_sal_retval ret_stuff;
@@ -130,9 +131,9 @@ static inline uint64_t sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
/*
* Retrieve the pci device information given the bus and device|function number.
*/
-static inline uint64_t
-sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
- u64 sn_irq_info)
+static inline u64
+sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
+ u64 sn_irq_info)
{
struct ia64_sal_retval ret_stuff;
ret_stuff.status = 0;
@@ -140,7 +141,7 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
SAL_CALL_NOLOCK(ret_stuff,
(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
- (u64) segment, (u64) bus_number, (u64) devfn,
+ (u64) segment, (u64) bus_number, (u64) devfn,
(u64) pci_dev,
sn_irq_info, 0, 0);
return ret_stuff.v0;
@@ -170,12 +171,12 @@ sn_pcidev_info_get(struct pci_dev *dev)
*/
static void sn_fixup_ionodes(void)
{
-
- struct sn_flush_device_list *sn_flush_device_list;
+ struct sn_flush_device_kernel *sn_flush_device_kernel;
+ struct sn_flush_device_kernel *dev_entry;
struct hubdev_info *hubdev;
- uint64_t status;
- uint64_t nasid;
- int i, widget;
+ u64 status;
+ u64 nasid;
+ int i, widget, device;
/*
* Get SGI Specific HUB chipset information.
@@ -186,7 +187,7 @@ static void sn_fixup_ionodes(void)
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));
+ status = sal_get_hubdev_info(nasid, (u64) __pa(hubdev));
if (status)
continue;
@@ -213,38 +214,49 @@ static void sn_fixup_ionodes(void)
hubdev->hdi_flush_nasid_list.widget_p =
kmalloc((HUB_WIDGET_ID_MAX + 1) *
- sizeof(struct sn_flush_device_list *), GFP_KERNEL);
-
+ sizeof(struct sn_flush_device_kernel *),
+ GFP_KERNEL);
memset(hubdev->hdi_flush_nasid_list.widget_p, 0x0,
(HUB_WIDGET_ID_MAX + 1) *
- sizeof(struct sn_flush_device_list *));
+ sizeof(struct sn_flush_device_kernel *));
for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
- sn_flush_device_list = kmalloc(DEV_PER_WIDGET *
- sizeof(struct
- sn_flush_device_list),
- GFP_KERNEL);
- memset(sn_flush_device_list, 0x0,
+ sn_flush_device_kernel = kmalloc(DEV_PER_WIDGET *
+ sizeof(struct
+ sn_flush_device_kernel),
+ GFP_KERNEL);
+ if (!sn_flush_device_kernel)
+ BUG();
+ memset(sn_flush_device_kernel, 0x0,
DEV_PER_WIDGET *
- sizeof(struct sn_flush_device_list));
-
- status =
- sal_get_widget_dmaflush_list(nasid, widget,
- (uint64_t)
- __pa
- (sn_flush_device_list));
- if (status) {
- kfree(sn_flush_device_list);
- continue;
+ sizeof(struct sn_flush_device_kernel));
+
+ dev_entry = sn_flush_device_kernel;
+ for (device = 0; device < DEV_PER_WIDGET;
+ device++,dev_entry++) {
+ dev_entry->common = kmalloc(sizeof(struct
+ sn_flush_device_common),
+ GFP_KERNEL);
+ if (!dev_entry->common)
+ BUG();
+ memset(dev_entry->common, 0x0, sizeof(struct
+ sn_flush_device_common));
+
+ status = sal_get_device_dmaflush_list(nasid,
+ widget,
+ device,
+ (u64)(dev_entry->common));
+ if (status)
+ BUG();
+
+ spin_lock_init(&dev_entry->sfdl_flush_lock);
}
- spin_lock_init(&sn_flush_device_list->sfdl_flush_lock);
- hubdev->hdi_flush_nasid_list.widget_p[widget] =
- sn_flush_device_list;
- }
-
+ if (sn_flush_device_kernel)
+ hubdev->hdi_flush_nasid_list.widget_p[widget] =
+ sn_flush_device_kernel;
+ }
}
-
}
/*
@@ -256,7 +268,7 @@ static void sn_fixup_ionodes(void)
*/
static void
sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
- int64_t * pci_addrs)
+ s64 * pci_addrs)
{
struct pci_controller *controller = PCI_CONTROLLER(dev->bus);
unsigned int i;
@@ -316,7 +328,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
struct pci_bus *host_pci_bus;
struct pci_dev *host_pci_dev;
struct pcidev_info *pcidev_info;
- int64_t pci_addrs[PCI_ROM_RESOURCE + 1];
+ s64 pci_addrs[PCI_ROM_RESOURCE + 1];
struct sn_irq_info *sn_irq_info;
unsigned long size;
unsigned int bus_no, devfn;
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 01d18b7b5bb3..ec37084bdc17 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -28,7 +28,7 @@ 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 */
-static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget,
+static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
u64 sn_irq_info,
int req_irq, nasid_t req_nasid,
int req_slice)
@@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
sn_irq_lh[irq], list) {
- uint64_t bridge;
+ u64 bridge;
int local_widget, status;
nasid_t local_nasid;
struct sn_irq_info *new_irq_info;
@@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
break;
memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
- bridge = (uint64_t) new_irq_info->irq_bridge;
+ bridge = (u64) new_irq_info->irq_bridge;
if (!bridge) {
kfree(new_irq_info);
break; /* irq is not a device interrupt */
@@ -349,10 +349,10 @@ static void force_interrupt(int irq)
*/
static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
{
- uint64_t regval;
+ u64 regval;
int irr_reg_num;
int irr_bit;
- uint64_t irr_reg;
+ u64 irr_reg;
struct pcidev_info *pcidev_info;
struct pcibus_info *pcibus_info;
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 0d8592a745a7..d263d3e8fbb9 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <asm/system.h>
@@ -65,7 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
}
-static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
+static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -76,12 +77,6 @@ static void tiocx_bus_release(struct device *dev)
kfree(to_cx_dev(dev));
}
-struct bus_type tiocx_bus_type = {
- .name = "tiocx",
- .match = tiocx_match,
- .hotplug = tiocx_hotplug,
-};
-
/**
* cx_device_match - Find cx_device in the id table.
* @ids: id table from driver
@@ -148,6 +143,14 @@ static int cx_driver_remove(struct device *dev)
return 0;
}
+struct bus_type tiocx_bus_type = {
+ .name = "tiocx",
+ .match = tiocx_match,
+ .uevent = tiocx_uevent,
+ .probe = cx_device_probe,
+ .remove = cx_driver_remove,
+};
+
/**
* cx_driver_register - Register the driver.
* @cx_driver: driver table (cx_drv struct) from driver
@@ -161,8 +164,6 @@ int cx_driver_register(struct cx_drv *cx_driver)
{
cx_driver->driver.name = cx_driver->name;
cx_driver->driver.bus = &tiocx_bus_type;
- cx_driver->driver.probe = cx_device_probe;
- cx_driver->driver.remove = cx_driver_remove;
return driver_register(&cx_driver->driver);
}
@@ -244,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev)
cx_dev->bt);
}
-static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget,
+static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget,
u64 sn_irq_info,
int req_irq, nasid_t req_nasid,
int req_slice)
@@ -301,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq,
void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
{
- uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge;
+ u64 bridge = (u64) sn_irq_info->irq_bridge;
nasid_t nasid = NASID_GET(bridge);
int widget;
@@ -312,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info)
}
}
-uint64_t tiocx_dma_addr(uint64_t addr)
+u64 tiocx_dma_addr(u64 addr)
{
return PHYS_TO_TIODMA(addr);
}
-uint64_t tiocx_swin_base(int nasid)
+u64 tiocx_swin_base(int nasid)
{
return TIO_SWIN_BASE(nasid, TIOCX_CORELET);
}
@@ -334,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base);
static void tio_conveyor_set(nasid_t nasid, int enable_flag)
{
- uint64_t ice_frz;
- uint64_t disable_cb = (1ull << 61);
+ u64 ice_frz;
+ u64 disable_cb = (1ull << 61);
if (!(nasid & 1))
return;
@@ -387,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt)
static int bitstream_loaded(nasid_t nasid)
{
- uint64_t cx_credits;
+ u64 cx_credits;
cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3);
cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK;
@@ -403,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev)
nasid_t nasid = cx_dev->cx_id.nasid;
if (bitstream_loaded(nasid)) {
- uint64_t cx_id;
+ u64 cx_id;
int rv;
rv = ia64_sn_sysctl_tio_clock_reset(nasid);
if (rv) {
printk(KERN_ALERT "CX port JTAG reset failed.\n");
} else {
- cx_id = *(volatile uint64_t *)
+ cx_id = *(volatile u64 *)
(TIO_SWIN_BASE(nasid, TIOCX_CORELET) +
WIDGET_ID);
part_num = XWIDGET_PART_NUM(cx_id);
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index abf4fc2a87bb..0c0a68902409 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <asm/sn/bte.h>
#include <asm/sn/sn_sal.h>
-#include "xpc.h"
+#include <asm/sn/xpc.h>
/*
@@ -779,6 +779,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
/* both sides are disconnected now */
+ if (ch->flags & XPC_C_CONNECTCALLOUT) {
+ spin_unlock_irqrestore(&ch->lock, *irq_flags);
+ xpc_disconnect_callout(ch, xpcDisconnected);
+ spin_lock_irqsave(&ch->lock, *irq_flags);
+ }
+
/* it's now safe to free the channel's message queues */
xpc_free_msgqueues(ch);
@@ -1645,7 +1651,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
void
-xpc_disconnecting_callout(struct xpc_channel *ch)
+xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason)
{
/*
* Let the channel's registerer know that the channel is being
@@ -1654,15 +1660,13 @@ xpc_disconnecting_callout(struct xpc_channel *ch)
*/
if (ch->func != NULL) {
- dev_dbg(xpc_chan, "ch->func() called, reason=xpcDisconnecting,"
- " partid=%d, channel=%d\n", ch->partid, ch->number);
+ dev_dbg(xpc_chan, "ch->func() called, reason=%d, partid=%d, "
+ "channel=%d\n", reason, ch->partid, ch->number);
- ch->func(xpcDisconnecting, ch->partid, ch->number, NULL,
- ch->key);
+ ch->func(reason, ch->partid, ch->number, NULL, ch->key);
- dev_dbg(xpc_chan, "ch->func() returned, reason="
- "xpcDisconnecting, partid=%d, channel=%d\n",
- ch->partid, ch->number);
+ dev_dbg(xpc_chan, "ch->func() returned, reason=%d, partid=%d, "
+ "channel=%d\n", reason, ch->partid, ch->number);
}
}
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index b617236524c6..8930586e0eb4 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -59,7 +59,7 @@
#include <asm/sn/sn_sal.h>
#include <asm/kdebug.h>
#include <asm/uaccess.h>
-#include "xpc.h"
+#include <asm/sn/xpc.h>
/* define two XPC debug device structures to be used with dev_dbg() et al */
@@ -82,6 +82,9 @@ struct device *xpc_part = &xpc_part_dbg_subname;
struct device *xpc_chan = &xpc_chan_dbg_subname;
+static int xpc_kdebug_ignore;
+
+
/* systune related variables for /proc/sys directories */
static int xpc_hb_interval = XPC_HB_DEFAULT_INTERVAL;
@@ -162,6 +165,8 @@ static ctl_table xpc_sys_dir[] = {
};
static struct ctl_table_header *xpc_sysctl;
+/* non-zero if any remote partition disengage request was timed out */
+int xpc_disengage_request_timedout;
/* #of IRQs received */
static atomic_t xpc_act_IRQ_rcvd;
@@ -773,7 +778,7 @@ xpc_daemonize_kthread(void *args)
ch->flags |= XPC_C_DISCONNECTCALLOUT;
spin_unlock_irqrestore(&ch->lock, irq_flags);
- xpc_disconnecting_callout(ch);
+ xpc_disconnect_callout(ch, xpcDisconnecting);
} else {
spin_unlock_irqrestore(&ch->lock, irq_flags);
}
@@ -921,9 +926,9 @@ static void
xpc_do_exit(enum xpc_retval reason)
{
partid_t partid;
- int active_part_count;
+ int active_part_count, printed_waiting_msg = 0;
struct xpc_partition *part;
- unsigned long printmsg_time;
+ unsigned long printmsg_time, disengage_request_timeout = 0;
/* a 'rmmod XPC' and a 'reboot' cannot both end up here together */
@@ -953,7 +958,8 @@ xpc_do_exit(enum xpc_retval reason)
/* wait for all partitions to become inactive */
- printmsg_time = jiffies;
+ printmsg_time = jiffies + (XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+ xpc_disengage_request_timedout = 0;
do {
active_part_count = 0;
@@ -969,20 +975,39 @@ xpc_do_exit(enum xpc_retval reason)
active_part_count++;
XPC_DEACTIVATE_PARTITION(part, reason);
- }
- if (active_part_count == 0) {
- break;
+ if (part->disengage_request_timeout >
+ disengage_request_timeout) {
+ disengage_request_timeout =
+ part->disengage_request_timeout;
+ }
}
- if (jiffies >= printmsg_time) {
- dev_info(xpc_part, "waiting for partitions to "
- "deactivate/disengage, active count=%d, remote "
- "engaged=0x%lx\n", active_part_count,
- xpc_partition_engaged(1UL << partid));
-
- printmsg_time = jiffies +
+ if (xpc_partition_engaged(-1UL)) {
+ if (time_after(jiffies, printmsg_time)) {
+ dev_info(xpc_part, "waiting for remote "
+ "partitions to disengage, timeout in "
+ "%ld seconds\n",
+ (disengage_request_timeout - jiffies)
+ / HZ);
+ printmsg_time = jiffies +
(XPC_DISENGAGE_PRINTMSG_INTERVAL * HZ);
+ printed_waiting_msg = 1;
+ }
+
+ } else if (active_part_count > 0) {
+ if (printed_waiting_msg) {
+ dev_info(xpc_part, "waiting for local partition"
+ " to disengage\n");
+ printed_waiting_msg = 0;
+ }
+
+ } else {
+ if (!xpc_disengage_request_timedout) {
+ dev_info(xpc_part, "all partitions have "
+ "disengaged\n");
+ }
+ break;
}
/* sleep for a 1/3 of a second or so */
@@ -1000,11 +1025,13 @@ xpc_do_exit(enum xpc_retval reason)
del_timer_sync(&xpc_hb_timer);
DBUG_ON(xpc_vars->heartbeating_to_mask != 0);
- /* take ourselves off of the reboot_notifier_list */
- (void) unregister_reboot_notifier(&xpc_reboot_notifier);
+ if (reason == xpcUnloading) {
+ /* take ourselves off of the reboot_notifier_list */
+ (void) unregister_reboot_notifier(&xpc_reboot_notifier);
- /* take ourselves off of the die_notifier list */
- (void) unregister_die_notifier(&xpc_die_notifier);
+ /* take ourselves off of the die_notifier list */
+ (void) unregister_die_notifier(&xpc_die_notifier);
+ }
/* close down protections for IPI operations */
xpc_restrict_IPI_ops();
@@ -1020,7 +1047,35 @@ xpc_do_exit(enum xpc_retval reason)
/*
- * Called when the system is about to be either restarted or halted.
+ * This function is called when the system is being rebooted.
+ */
+static int
+xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
+{
+ enum xpc_retval reason;
+
+
+ switch (event) {
+ case SYS_RESTART:
+ reason = xpcSystemReboot;
+ break;
+ case SYS_HALT:
+ reason = xpcSystemHalt;
+ break;
+ case SYS_POWER_OFF:
+ reason = xpcSystemPoweroff;
+ break;
+ default:
+ reason = xpcSystemGoingDown;
+ }
+
+ xpc_do_exit(reason);
+ return NOTIFY_DONE;
+}
+
+
+/*
+ * Notify other partitions to disengage from all references to our memory.
*/
static void
xpc_die_disengage(void)
@@ -1028,7 +1083,7 @@ xpc_die_disengage(void)
struct xpc_partition *part;
partid_t partid;
unsigned long engaged;
- long time, print_time, disengage_request_timeout;
+ long time, printmsg_time, disengage_request_timeout;
/* keep xpc_hb_checker thread from doing anything (just in case) */
@@ -1055,57 +1110,53 @@ xpc_die_disengage(void)
}
}
- print_time = rtc_time();
- disengage_request_timeout = print_time +
+ time = rtc_time();
+ printmsg_time = time +
+ (XPC_DISENGAGE_PRINTMSG_INTERVAL * sn_rtc_cycles_per_second);
+ disengage_request_timeout = time +
(xpc_disengage_request_timelimit * sn_rtc_cycles_per_second);
/* wait for all other partitions to disengage from us */
- while ((engaged = xpc_partition_engaged(-1UL)) &&
- (time = rtc_time()) < disengage_request_timeout) {
+ while (1) {
+ engaged = xpc_partition_engaged(-1UL);
+ if (!engaged) {
+ dev_info(xpc_part, "all partitions have disengaged\n");
+ break;
+ }
- if (time >= print_time) {
+ time = rtc_time();
+ if (time >= disengage_request_timeout) {
+ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) {
+ if (engaged & (1UL << partid)) {
+ dev_info(xpc_part, "disengage from "
+ "remote partition %d timed "
+ "out\n", partid);
+ }
+ }
+ break;
+ }
+
+ if (time >= printmsg_time) {
dev_info(xpc_part, "waiting for remote partitions to "
- "disengage, engaged=0x%lx\n", engaged);
- print_time = time + (XPC_DISENGAGE_PRINTMSG_INTERVAL *
+ "disengage, timeout in %ld seconds\n",
+ (disengage_request_timeout - time) /
+ sn_rtc_cycles_per_second);
+ printmsg_time = time +
+ (XPC_DISENGAGE_PRINTMSG_INTERVAL *
sn_rtc_cycles_per_second);
}
}
- dev_info(xpc_part, "finished waiting for remote partitions to "
- "disengage, engaged=0x%lx\n", engaged);
-}
-
-
-/*
- * This function is called when the system is being rebooted.
- */
-static int
-xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused)
-{
- enum xpc_retval reason;
-
-
- switch (event) {
- case SYS_RESTART:
- reason = xpcSystemReboot;
- break;
- case SYS_HALT:
- reason = xpcSystemHalt;
- break;
- case SYS_POWER_OFF:
- reason = xpcSystemPoweroff;
- break;
- default:
- reason = xpcSystemGoingDown;
- }
-
- xpc_do_exit(reason);
- return NOTIFY_DONE;
}
/*
- * This function is called when the system is being rebooted.
+ * This function is called when the system is being restarted or halted due
+ * to some sort of system failure. If this is the case we need to notify the
+ * other partitions to disengage from all references to our memory.
+ * This function can also be called when our heartbeater could be offlined
+ * for a time. In this case we need to notify other partitions to not worry
+ * about the lack of a heartbeat.
*/
static int
xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
@@ -1115,11 +1166,25 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused)
case DIE_MACHINE_HALT:
xpc_die_disengage();
break;
+
+ case DIE_KDEBUG_ENTER:
+ /* Should lack of heartbeat be ignored by other partitions? */
+ if (!xpc_kdebug_ignore) {
+ break;
+ }
+ /* fall through */
case DIE_MCA_MONARCH_ENTER:
case DIE_INIT_MONARCH_ENTER:
xpc_vars->heartbeat++;
xpc_vars->heartbeat_offline = 1;
break;
+
+ case DIE_KDEBUG_LEAVE:
+ /* Is lack of heartbeat being ignored by other partitions? */
+ if (!xpc_kdebug_ignore) {
+ break;
+ }
+ /* fall through */
case DIE_MCA_MONARCH_LEAVE:
case DIE_INIT_MONARCH_LEAVE:
xpc_vars->heartbeat++;
@@ -1344,3 +1409,7 @@ module_param(xpc_disengage_request_timelimit, int, 0);
MODULE_PARM_DESC(xpc_disengage_request_timelimit, "Number of seconds to wait "
"for disengage request to complete.");
+module_param(xpc_kdebug_ignore, int, 0);
+MODULE_PARM_DESC(xpc_kdebug_ignore, "Should lack of heartbeat be ignored by "
+ "other partitions when dropping into kdebug.");
+
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index cdd6431853a1..88a730e6cfdb 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -28,7 +28,7 @@
#include <asm/sn/sn_sal.h>
#include <asm/sn/nodepda.h>
#include <asm/sn/addrs.h>
-#include "xpc.h"
+#include <asm/sn/xpc.h>
/* XPC is exiting flag */
@@ -771,7 +771,8 @@ xpc_identify_act_IRQ_req(int nasid)
}
}
- if (!xpc_partition_disengaged(part)) {
+ if (part->disengage_request_timeout > 0 &&
+ !xpc_partition_disengaged(part)) {
/* still waiting on other side to disengage from us */
return;
}
@@ -873,6 +874,9 @@ xpc_partition_disengaged(struct xpc_partition *part)
* request in a timely fashion, so assume it's dead.
*/
+ dev_info(xpc_part, "disengage from remote partition %d "
+ "timed out\n", partid);
+ xpc_disengage_request_timedout = 1;
xpc_clear_partition_engaged(1UL << partid);
disengaged = 1;
}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
index d1647b863e61..aa3fa5152a32 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c
@@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */
* mark_ate: Mark the ate as either free or inuse.
*/
static void mark_ate(struct ate_resource *ate_resource, int start, int number,
- uint64_t value)
+ u64 value)
{
- uint64_t *ate = ate_resource->ate;
+ u64 *ate = ate_resource->ate;
int index;
int length = 0;
@@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start,
int count)
{
- uint64_t *ate = ate_resource->ate;
+ u64 *ate = ate_resource->ate;
int index;
int start_free;
@@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource,
int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
{
int status = 0;
- uint64_t flag;
+ u64 flag;
flag = pcibr_lock(pcibus_info);
status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count);
@@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count)
* Setup an Address Translation Entry as specified. Use either the Bridge
* internal maps or the external map RAM, as appropriate.
*/
-static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info,
+static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info,
int ate_index)
{
if (ate_index < pcibus_info->pbi_int_ate_size) {
@@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info,
*/
void inline
ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
- volatile uint64_t ate)
+ volatile u64 ate)
{
while (count-- > 0) {
if (ate_index < pcibus_info->pbi_int_ate_size) {
@@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count,
void pcibr_ate_free(struct pcibus_info *pcibus_info, int index)
{
- volatile uint64_t ate;
+ volatile u64 ate;
int count;
- uint64_t flags;
+ u64 flags;
if (pcibr_invalidate_ate) {
/* For debugging purposes, clear the valid bit in the ATE */
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index 34093476e965..54ce5b7ceed2 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -41,21 +41,21 @@ extern int sn_ioif_inited;
static dma_addr_t
pcibr_dmamap_ate32(struct pcidev_info *info,
- uint64_t paddr, size_t req_size, uint64_t flags)
+ u64 paddr, size_t req_size, u64 flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
pdi_pcibus_info;
- uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info->
+ u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info->
pdi_linux_pcidev->devfn)) - 1;
int ate_count;
int ate_index;
- uint64_t ate_flags = flags | PCI32_ATE_V;
- uint64_t ate;
- uint64_t pci_addr;
- uint64_t xio_addr;
- uint64_t offset;
+ u64 ate_flags = flags | PCI32_ATE_V;
+ u64 ate;
+ u64 pci_addr;
+ u64 xio_addr;
+ u64 offset;
/* PIC in PCI-X mode does not supports 32bit PageMap mode */
if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) {
@@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info,
}
static dma_addr_t
-pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
- uint64_t dma_attributes)
+pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
+ u64 dma_attributes)
{
struct pcibus_info *pcibus_info = (struct pcibus_info *)
((info->pdi_host_pcidev_info)->pdi_pcibus_info);
- uint64_t pci_addr;
+ u64 pci_addr;
/* Translate to Crosstalk View of Physical Address */
pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
@@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
/* Handle Bridge Chipset differences */
if (IS_PIC_SOFT(pcibus_info)) {
pci_addr |=
- ((uint64_t) pcibus_info->
+ ((u64) pcibus_info->
pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
} else
pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
@@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr,
static dma_addr_t
pcibr_dmatrans_direct32(struct pcidev_info * info,
- uint64_t paddr, size_t req_size, uint64_t flags)
+ u64 paddr, size_t req_size, u64 flags)
{
struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
pdi_pcibus_info;
- uint64_t xio_addr;
+ u64 xio_addr;
- uint64_t xio_base;
- uint64_t offset;
- uint64_t endoff;
+ u64 xio_base;
+ u64 offset;
+ u64 endoff;
if (IS_PCIX(pcibus_info)) {
return 0;
@@ -209,16 +209,18 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction)
* unlike the PIC Device(x) Write Request Buffer Flush register.
*/
-void sn_dma_flush(uint64_t addr)
+void sn_dma_flush(u64 addr)
{
nasid_t nasid;
int is_tio;
int wid_num;
int i, j;
- uint64_t flags;
- uint64_t itte;
+ u64 flags;
+ u64 itte;
struct hubdev_info *hubinfo;
- volatile struct sn_flush_device_list *p;
+ volatile struct sn_flush_device_kernel *p;
+ volatile struct sn_flush_device_common *common;
+
struct sn_flush_nasid_entry *flush_nasid_list;
if (!sn_ioif_inited)
@@ -268,17 +270,17 @@ void sn_dma_flush(uint64_t addr)
p = &flush_nasid_list->widget_p[wid_num][0];
/* find a matching BAR */
- for (i = 0; i < DEV_PER_WIDGET; i++) {
+ for (i = 0; i < DEV_PER_WIDGET; i++,p++) {
+ common = p->common;
for (j = 0; j < PCI_ROM_RESOURCE; j++) {
- if (p->sfdl_bar_list[j].start == 0)
+ if (common->sfdl_bar_list[j].start == 0)
break;
- if (addr >= p->sfdl_bar_list[j].start
- && addr <= p->sfdl_bar_list[j].end)
+ if (addr >= common->sfdl_bar_list[j].start
+ && addr <= common->sfdl_bar_list[j].end)
break;
}
- if (j < PCI_ROM_RESOURCE && p->sfdl_bar_list[j].start != 0)
+ if (j < PCI_ROM_RESOURCE && common->sfdl_bar_list[j].start != 0)
break;
- p++;
}
/* if no matching BAR, return without doing anything. */
@@ -297,31 +299,31 @@ void sn_dma_flush(uint64_t addr)
* 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);
+ u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
+ u32 revnum = XWIDGET_PART_REV_NUM(tio_id);
/* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */
if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) {
return;
} else {
- pcireg_wrb_flush_get(p->sfdl_pcibus_info,
- (p->sfdl_slot - 1));
+ pcireg_wrb_flush_get(common->sfdl_pcibus_info,
+ (common->sfdl_slot - 1));
}
} else {
- spin_lock_irqsave(&((struct sn_flush_device_list *)p)->
- sfdl_flush_lock, flags);
-
- *p->sfdl_flush_addr = 0;
+ spin_lock_irqsave((spinlock_t *)&p->sfdl_flush_lock,
+ flags);
+ *common->sfdl_flush_addr = 0;
/* force an interrupt. */
- *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1;
+ *(volatile u32 *)(common->sfdl_force_int_addr) = 1;
/* wait for the interrupt to come back. */
- while (*(p->sfdl_flush_addr) != 0x10f)
+ while (*(common->sfdl_flush_addr) != 0x10f)
cpu_relax();
/* okay, everything is synched up. */
- spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags);
+ spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock,
+ flags);
}
return;
}
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 1f500c81002c..77a1262751d3 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -23,7 +23,7 @@ int
sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
{
struct ia64_sal_retval ret_stuff;
- uint64_t busnum;
+ u64 busnum;
ret_stuff.status = 0;
ret_stuff.v0 = 0;
@@ -40,7 +40,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
void *resp)
{
struct ia64_sal_retval ret_stuff;
- uint64_t busnum;
+ u64 busnum;
ret_stuff.status = 0;
ret_stuff.v0 = 0;
@@ -56,7 +56,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
{
struct ia64_sal_retval ret_stuff;
- uint64_t busnum;
+ u64 busnum;
int segment;
ret_stuff.status = 0;
ret_stuff.v0 = 0;
@@ -92,7 +92,8 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
cnodeid_t near_cnode;
struct hubdev_info *hubdev_info;
struct pcibus_info *soft;
- struct sn_flush_device_list *sn_flush_device_list;
+ struct sn_flush_device_kernel *sn_flush_device_kernel;
+ struct sn_flush_device_common *common;
if (! IS_PCI_BRIDGE_ASIC(prom_bussoft->bs_asic_type)) {
return NULL;
@@ -137,20 +138,19 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
if (hubdev_info->hdi_flush_nasid_list.widget_p) {
- sn_flush_device_list = hubdev_info->hdi_flush_nasid_list.
+ sn_flush_device_kernel = hubdev_info->hdi_flush_nasid_list.
widget_p[(int)soft->pbi_buscommon.bs_xid];
- if (sn_flush_device_list) {
+ if (sn_flush_device_kernel) {
for (j = 0; j < DEV_PER_WIDGET;
- j++, sn_flush_device_list++) {
- if (sn_flush_device_list->sfdl_slot == -1)
+ j++, sn_flush_device_kernel++) {
+ common = sn_flush_device_kernel->common;
+ if (common->sfdl_slot == -1)
continue;
- if ((sn_flush_device_list->
- sfdl_persistent_segment ==
+ if ((common->sfdl_persistent_segment ==
soft->pbi_buscommon.bs_persist_segment) &&
- (sn_flush_device_list->
- sfdl_persistent_busnum ==
+ (common->sfdl_persistent_busnum ==
soft->pbi_buscommon.bs_persist_busnum))
- sn_flush_device_list->sfdl_pcibus_info =
+ common->sfdl_pcibus_info =
soft;
}
}
@@ -159,9 +159,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
/* Setup the PMU ATE map */
soft->pbi_int_ate_resource.lowest_free_index = 0;
soft->pbi_int_ate_resource.ate =
- kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL);
+ kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL);
memset(soft->pbi_int_ate_resource.ate, 0,
- (soft->pbi_int_ate_size * sizeof(uint64_t)));
+ (soft->pbi_int_ate_size * sizeof(u64)));
if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
/* TIO PCI Bridge: find nearest node with CPUs */
@@ -203,7 +203,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
struct pcidev_info *pcidev_info;
struct pcibus_info *pcibus_info;
int bit = sn_irq_info->irq_int_bit;
- uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr;
+ u64 xtalk_addr = sn_irq_info->irq_xtalkaddr;
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
if (pcidev_info) {
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
index 79fdb91d7259..8b8bbd51d433 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c
@@ -23,7 +23,7 @@ union br_ptr {
/*
* Control Register Access -- Read/Write 0000_0020
*/
-void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
+void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -43,7 +43,7 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
}
}
-void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
+void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
/*
* PCI/PCIX Target Flush Register Access -- Read Only 0000_0050
*/
-uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
+u64 pcireg_tflush_get(struct pcibus_info *pcibus_info)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- uint64_t ret = 0;
+ u64 ret = 0;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info)
/*
* Interrupt Status Register Access -- Read Only 0000_0100
*/
-uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
+u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- uint64_t ret = 0;
+ u64 ret = 0;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -121,7 +121,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info)
/*
* Interrupt Enable Register Access -- Read/Write 0000_0108
*/
-void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
+void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -141,7 +141,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits)
}
}
-void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
+void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -165,7 +165,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits)
* Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168
*/
void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n,
- uint64_t addr)
+ u64 addr)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n)
/*
* Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258
*/
-uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
+u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- uint64_t ret = 0;
+ u64 ret = 0;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
@@ -242,7 +242,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device)
}
void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
- uint64_t val)
+ u64 val)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
@@ -262,10 +262,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index,
}
}
-uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
+u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index)
{
union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base;
- uint64_t __iomem *ret = NULL;
+ u64 __iomem *ret = NULL;
if (pcibus_info) {
switch (pcibus_info->pbi_bridge_type) {
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 27aa1842dacc..7571a4025529 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -16,7 +16,7 @@
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioca_provider.h>
-uint32_t tioca_gart_found;
+u32 tioca_gart_found;
EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */
LIST_HEAD(tioca_list);
@@ -34,8 +34,8 @@ static int tioca_gart_init(struct tioca_kernel *);
static int
tioca_gart_init(struct tioca_kernel *tioca_kern)
{
- uint64_t ap_reg;
- uint64_t offset;
+ u64 ap_reg;
+ u64 offset;
struct page *tmp;
struct tioca_common *tioca_common;
struct tioca __iomem *ca_base;
@@ -214,7 +214,7 @@ void
tioca_fastwrite_enable(struct tioca_kernel *tioca_kern)
{
int cap_ptr;
- uint32_t reg;
+ u32 reg;
struct tioca __iomem *tioca_base;
struct pci_dev *pdev;
struct tioca_common *common;
@@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */
* We will always use 0x1
* 55:55 - Swap bytes Currently unused
*/
-static uint64_t
+static u64
tioca_dma_d64(unsigned long paddr)
{
dma_addr_t bus_addr;
@@ -318,15 +318,15 @@ tioca_dma_d64(unsigned long paddr)
* and so a given CA can only directly target nodes in the range
* xxx - xxx+255.
*/
-static uint64_t
-tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
+static u64
+tioca_dma_d48(struct pci_dev *pdev, u64 paddr)
{
struct tioca_common *tioca_common;
struct tioca __iomem *ca_base;
- uint64_t ct_addr;
+ u64 ct_addr;
dma_addr_t bus_addr;
- uint32_t node_upper;
- uint64_t agp_dma_extn;
+ u32 node_upper;
+ u64 agp_dma_extn;
struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev);
tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info;
@@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr)
* dma_addr_t is guarenteed to be contiguous in CA bus space.
*/
static dma_addr_t
-tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size)
+tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size)
{
int i, ps, ps_shift, entry, entries, mapsize, last_entry;
- uint64_t xio_addr, end_xio_addr;
+ u64 xio_addr, end_xio_addr;
struct tioca_common *tioca_common;
struct tioca_kernel *tioca_kern;
dma_addr_t bus_addr = 0;
@@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
* The mapping mode used is based on the devices dma_mask. As a last resort
* use the GART mapped mode.
*/
-static uint64_t
-tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
+static u64
+tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
{
- uint64_t mapaddr;
+ u64 mapaddr;
/*
* If card is 64 or 48 bit addresable, use a direct mapping. 32
@@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
{
struct tioca_common *soft = arg;
struct ia64_sal_retval ret_stuff;
- uint64_t segment;
- uint64_t busnum;
+ u64 segment;
+ u64 busnum;
ret_stuff.status = 0;
ret_stuff.v0 = 0;
@@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
INIT_LIST_HEAD(&tioca_kern->ca_dmamaps);
tioca_kern->ca_closest_node =
nasid_to_cnodeid(tioca_common->ca_closest_nasid);
- tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
+ tioca_common->ca_kernel_private = (u64) tioca_kern;
bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
tioca_common->ca_common.bs_persist_busnum);
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index dda196c9e324..e52831ed93eb 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -81,10 +81,10 @@
* 61 - 0 since this is not an MSI transaction
* 60:54 - reserved, MBZ
*/
-static uint64_t
+static u64
tioce_dma_d64(unsigned long ct_addr)
{
- uint64_t bus_addr;
+ u64 bus_addr;
bus_addr = ct_addr | (1UL << 63);
@@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
* length, and if enough resources exist, fill in the ATE's and construct a
* tioce_dmamap struct to track the mapping.
*/
-static uint64_t
+static u64
tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
- uint64_t ct_addr, int len)
+ u64 ct_addr, int len)
{
int i;
int j;
@@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
int entries;
int nates;
int pagesize;
- uint64_t *ate_shadow;
- uint64_t *ate_reg;
- uint64_t addr;
+ u64 *ate_shadow;
+ u64 *ate_reg;
+ u64 addr;
struct tioce *ce_mmr;
- uint64_t bus_base;
+ u64 bus_base;
struct tioce_dmamap *map;
ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
@@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
addr = ct_addr;
for (j = 0; j < nates; j++) {
- uint64_t ate;
+ u64 ate;
ate = ATE_MAKE(addr, pagesize);
ate_shadow[i + j] = ate;
@@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
*
* 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)
+static u64
+tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
{
int dma_ok;
int port;
struct tioce *ce_mmr;
struct tioce_kernel *ce_kern;
- uint64_t ct_upper;
- uint64_t ct_lower;
+ u64 ct_upper;
+ u64 ct_lower;
dma_addr_t bus_addr;
ct_upper = ct_addr & ~0x3fffffffUL;
@@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
- uint64_t tmp;
+ u64 tmp;
ce_kern->ce_port[port].dirmap_shadow = ct_upper;
writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]);
@@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
* 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)
+static u64
+tioce_dma_barrier(u64 bus_addr, int on)
{
- uint64_t barrier_bit;
+ u64 barrier_bit;
/* barrier not supported in M40/M40S mode */
if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr))
@@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
list_for_each_entry(map, &ce_kern->ce_dmamap_list,
ce_dmamap_list) {
- uint64_t last;
+ u64 last;
last = map->pci_start + map->nbytes - 1;
if (bus_addr >= map->pci_start && bus_addr <= last)
@@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
* 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,
+static u64
+tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
int barrier)
{
unsigned long flags;
- uint64_t ct_addr;
- uint64_t mapaddr = 0;
+ u64 ct_addr;
+ u64 mapaddr = 0;
struct tioce_kernel *ce_kern;
struct tioce_dmamap *map;
int port;
- uint64_t dma_mask;
+ u64 dma_mask;
dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask;
@@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
* address bits than this device can support.
*/
list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) {
- uint64_t last;
+ u64 last;
last = map->ct_start + map->nbytes - 1;
if (ct_addr >= map->ct_start &&
@@ -501,8 +501,8 @@ dma_map_done:
* 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)
+static u64
+tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
{
return tioce_do_dma_map(pdev, paddr, byte_count, 0);
}
@@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
*
* 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)
+ */ static u64
+tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
{
return tioce_do_dma_map(pdev, paddr, byte_count, 1);
}
@@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
tioce_kern_init(struct tioce_common *tioce_common)
{
int i;
- uint32_t tmp;
+ u32 tmp;
struct tioce *tioce_mmr;
struct tioce_kernel *tioce_kern;
@@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common)
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;
+ tioce_common->ce_kernel_private = (u64) tioce_kern;
/*
* Determine the secondary bus number of the port2 logical PPB.
@@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common)
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;
+ tioce_kern->ce_port1_secondary = (u8) tmp;
/*
* Set PMU pagesize to the largest size available, and zero out
@@ -615,7 +615,7 @@ 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;
+ u64 force_int_val;
if (!sn_irq_info->irq_bridge)
return;
@@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
struct tioce_common *ce_common;
struct tioce *ce_mmr;
int bit;
- uint64_t vector;
+ u64 vector;
pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
if (!pcidev_info)
@@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
bit = sn_irq_info->irq_int_bit;
__sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
- vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
+ vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT;
vector |= sn_irq_info->irq_xtalkaddr;
writeq(vector, &ce_mmr->ce_adm_int_dest[bit]);
__sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit));
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 4d100f3886e1..a3dcc3fab4b7 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -12,10 +12,6 @@ config M32R
config SBUS
bool
-config UID16
- bool
- default n
-
config GENERIC_ISA_DMA
bool
default y
@@ -81,6 +77,12 @@ config PLAT_MAPPI2
config PLAT_MAPPI3
bool "Mappi-III(M3A-2170)"
+config PLAT_M32104UT
+ bool "M32104UT"
+ help
+ The M3T-M32104UT is an reference board based on uT-Engine
+ specification. This board has a M32104 chip.
+
endchoice
choice
@@ -93,6 +95,10 @@ config CHIP_M32700
config CHIP_M32102
bool "M32102"
+config CHIP_M32104
+ bool "M32104"
+ depends on PLAT_M32104UT
+
config CHIP_VDEC2
bool "VDEC2"
@@ -115,7 +121,7 @@ config TLB_ENTRIES
config ISA_M32R
bool
- depends on CHIP_M32102
+ depends on CHIP_M32102 || CHIP_M32104
default y
config ISA_M32R2
@@ -140,6 +146,7 @@ config BUS_CLOCK
default "50000000" if PLAT_MAPPI3
default "50000000" if PLAT_M32700UT
default "50000000" if PLAT_OPSPUT
+ default "54000000" if PLAT_M32104UT
default "33333333" if PLAT_OAKS32R
default "20000000" if PLAT_MAPPI2
@@ -157,6 +164,7 @@ config MEMORY_START
default "08000000" if PLAT_USRV
default "08000000" if PLAT_M32700UT
default "08000000" if PLAT_OPSPUT
+ default "04000000" if PLAT_M32104UT
default "01000000" if PLAT_OAKS32R
config MEMORY_SIZE
@@ -166,6 +174,7 @@ config MEMORY_SIZE
default "02000000" if PLAT_USRV
default "01000000" if PLAT_M32700UT
default "01000000" if PLAT_OPSPUT
+ default "01000000" if PLAT_M32104UT
default "00800000" if PLAT_OAKS32R
config NOHIGHMEM
@@ -174,21 +183,22 @@ config NOHIGHMEM
config ARCH_DISCONTIGMEM_ENABLE
bool "Internal RAM Support"
- depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
+ depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104
default y
source "mm/Kconfig"
config IRAM_START
hex "Internal memory start address (hex)"
- default "00f00000"
- depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+ default "00f00000" if !CHIP_M32104
+ default "00700000" if CHIP_M32104
+ depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM
config IRAM_SIZE
hex "Internal memory size (hex)"
- depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
+ depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM
default "00080000" if CHIP_M32700
- default "00010000" if CHIP_M32102 || CHIP_OPSP
+ default "00010000" if CHIP_M32102 || CHIP_OPSP || CHIP_M32104
default "00008000" if CHIP_VDEC2
#
diff --git a/arch/m32r/boot/compressed/head.S b/arch/m32r/boot/compressed/head.S
index 07cfd6ad1ae4..234d8b1e0ac1 100644
--- a/arch/m32r/boot/compressed/head.S
+++ b/arch/m32r/boot/compressed/head.S
@@ -143,6 +143,11 @@ startup:
ldi r0, -2
ldi r1, 0x0100 ; invalidate
stb r1, @r0
+#elif defined(CONFIG_CHIP_M32104)
+ /* Cache flush */
+ ldi r0, -2
+ ldi r1, 0x0700 ; invalidate i-cache, copy back d-cache
+ sth r1, @r0
#else
#error "put your cache flush function, please"
#endif
diff --git a/arch/m32r/boot/setup.S b/arch/m32r/boot/setup.S
index 5d256434b4ad..398542507d84 100644
--- a/arch/m32r/boot/setup.S
+++ b/arch/m32r/boot/setup.S
@@ -1,11 +1,10 @@
/*
* linux/arch/m32r/boot/setup.S -- A setup code.
*
- * Copyright (C) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
- * and Hitoshi Yamamoto
+ * Copyright (C) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Hayato Fujiwara
*
*/
-/* $Id$ */
#include <linux/linkage.h>
#include <asm/segment.h>
@@ -80,6 +79,20 @@ ENTRY(boot)
ldi r1, #0x101 ; cache on (with invalidation)
; ldi r1, #0x00 ; cache off
st r1, @r0
+#elif defined(CONFIG_CHIP_M32104)
+ ldi r0, #-96 ; DNCR0
+ seth r1, #0x0060 ; from 0x00600000
+ or3 r1, r1, #0x0005 ; size 2MB
+ st r1, @r0
+ seth r1, #0x0100 ; from 0x01000000
+ or3 r1, r1, #0x0003 ; size 16MB
+ st r1, @+r0
+ seth r1, #0x0200 ; from 0x02000000
+ or3 r1, r1, #0x0002 ; size 32MB
+ st r1, @+r0
+ ldi r0, #-4 ;LDIMM (r0, M32R_MCCR)
+ ldi r1, #0x703 ; cache on (with invalidation)
+ st r1, @r0
#else
#error unknown chip configuration
#endif
@@ -115,10 +128,15 @@ mmu_on:
st r1, @(MATM_offset,r0) ; Set MATM (T bit ON)
ld r0, @(MATM_offset,r0) ; Check
#else
+#if defined(CONFIG_CHIP_M32700)
seth r0,#high(M32R_MCDCAR)
or3 r0,r0,#low(M32R_MCDCAR)
ld24 r1,#0x8080
st r1,@r0
+#elif defined(CONFIG_CHIP_M32104)
+ LDIMM (r2, eit_vector) ; set EVB(cr5)
+ mvtc r2, cr5
+#endif
#endif /* CONFIG_MMU */
jmp r13
nop
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
index 6c6b6c376638..5a2fa886906f 100644
--- a/arch/m32r/kernel/Makefile
+++ b/arch/m32r/kernel/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o
obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o
+obj-$(CONFIG_PLAT_M32104UT) += setup_m32104ut.o io_m32104ut.o
EXTRA_AFLAGS := -traditional
diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S
index 396c94218cc2..3871b65f0c82 100644
--- a/arch/m32r/kernel/entry.S
+++ b/arch/m32r/kernel/entry.S
@@ -315,7 +315,7 @@ ENTRY(ei_handler)
mv r1, sp ; arg1(regs)
#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
- || defined(CONFIG_CHIP_OPSP)
+ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
; GET_ICU_STATUS;
seth r0, #shigh(M32R_ICU_ISTS_ADDR)
@@ -541,7 +541,20 @@ check_int2:
bra check_end
.fillinsn
check_end:
-#endif /* CONFIG_PLAT_OPSPUT */
+#elif defined(CONFIG_PLAT_M32104UT)
+ add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
+ bnez r2, check_end
+ ; read ICU status register of PLD
+ seth r0, #high(PLD_ICUISTS)
+ or3 r0, r0, #low(PLD_ICUISTS)
+ lduh r0, @r0
+ slli r0, #21
+ srli r0, #27 ; ISN
+ addi r0, #(M32104UT_PLD_IRQ_BASE)
+ bra check_end
+ .fillinsn
+check_end:
+#endif /* CONFIG_PLAT_M32104UT */
bl do_IRQ
#endif /* CONFIG_SMP */
ld r14, @sp+
@@ -651,8 +664,6 @@ ENTRY(rie_handler)
/* void rie_handler(int error_code) */
SWITCH_TO_KERNEL_STACK
SAVE_ALL
- mvfc r0, bpc
- ld r1, @r0
ldi r1, #0x20 ; error_code
mv r0, sp ; pt_regs
bl do_rie_handler
diff --git a/arch/m32r/kernel/io_m32104ut.c b/arch/m32r/kernel/io_m32104ut.c
new file mode 100644
index 000000000000..d26adab9586c
--- /dev/null
+++ b/arch/m32r/kernel/io_m32104ut.c
@@ -0,0 +1,298 @@
+/*
+ * linux/arch/m32r/kernel/io_m32104ut.c
+ *
+ * Typical I/O routines for M32104UT board.
+ *
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Mamoru Sakugawa,
+ * Naoto Sugai, Hayato Fujiwara
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port) _port2addr(port)
+
+static inline void *_port2addr(unsigned long port)
+{
+ return (void *)(port | NONCACHE_OFFSET);
+}
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static inline void *__port2addr_ata(unsigned long port)
+{
+ static int dummy_reg;
+
+ switch (port) {
+ case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
+ case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
+ case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
+ case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
+ case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
+ case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
+ case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
+ case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
+ case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
+ default: return (void *)&dummy_reg;
+ }
+}
+#endif
+
+/*
+ * M32104T-LAN is located in the extended bus space
+ * from 0x01000000 to 0x01ffffff on physical address.
+ * The base address of LAN controller(LAN91C111) is 0x300.
+ */
+#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
+#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
+static inline void *_port2addr_ne(unsigned long port)
+{
+ return (void *)(port + NONCACHE_OFFSET + 0x01000000);
+}
+
+static inline void delay(void)
+{
+ __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+#define PORT2ADDR_NE(port) _port2addr_ne(port)
+
+static inline unsigned char _ne_inb(void *portp)
+{
+ return *(volatile unsigned char *)portp;
+}
+
+static inline unsigned short _ne_inw(void *portp)
+{
+ return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static inline void _ne_insb(void *portp, void *addr, unsigned long count)
+{
+ unsigned char *buf = (unsigned char *)addr;
+
+ while (count--)
+ *buf++ = _ne_inb(portp);
+}
+
+static inline void _ne_outb(unsigned char b, void *portp)
+{
+ *(volatile unsigned char *)portp = b;
+}
+
+static inline void _ne_outw(unsigned short w, void *portp)
+{
+ *(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ return _ne_inb(PORT2ADDR_NE(port));
+
+ return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ return _ne_inw(PORT2ADDR_NE(port));
+
+ return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+ return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+ unsigned char v = _inb(port);
+ delay();
+ return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+ unsigned short v = _inw(port);
+ delay();
+ return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+ unsigned long v = _inl(port);
+ delay();
+ return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_outb(b, PORT2ADDR_NE(port));
+ else
+ *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_outw(w, PORT2ADDR_NE(port));
+ else
+ *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+ *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+ _outb(b, port);
+ delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+ _outw(w, port);
+ delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+ _outl(l, port);
+ delay();
+}
+
+void _insb(unsigned int port, void *addr, unsigned long count)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_insb(PORT2ADDR_NE(port), addr, count);
+ else {
+ unsigned char *buf = addr;
+ unsigned char *portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned char *)portp;
+ }
+}
+
+void _insw(unsigned int port, void *addr, unsigned long count)
+{
+ unsigned short *buf = addr;
+ unsigned short *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ /*
+ * This portion is only used by smc91111.c to read data
+ * from the DATA_REG. Do not swap the data.
+ */
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
+ count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+#endif
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+ }
+}
+
+void _insl(unsigned int port, void *addr, unsigned long count)
+{
+ unsigned long *buf = addr;
+ unsigned long *portp;
+
+ portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void *addr, unsigned long count)
+{
+ const unsigned char *buf = addr;
+ unsigned char *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ _ne_outb(*buf++, portp);
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned char *)portp = *buf++;
+ }
+}
+
+void _outsw(unsigned int port, const void *addr, unsigned long count)
+{
+ const unsigned short *buf = addr;
+ unsigned short *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ /*
+ * This portion is only used by smc91111.c to write data
+ * into the DATA_REG. Do not swap the data.
+ */
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
+ count, 1);
+#endif
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+ }
+}
+
+void _outsl(unsigned int port, const void *addr, unsigned long count)
+{
+ const unsigned long *buf = addr;
+ unsigned char *portp;
+
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
index eda9f963c1eb..939932d6cc00 100644
--- a/arch/m32r/kernel/io_m32700ut.c
+++ b/arch/m32r/kernel/io_m32700ut.c
@@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port + NONCACHE_OFFSET);
+ return (void *)(port | NONCACHE_OFFSET);
}
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
@@ -45,15 +45,15 @@ static inline void *__port2addr_ata(unsigned long port)
static int dummy_reg;
switch (port) {
- case 0x1f0: return (void *)0xac002000;
- case 0x1f1: return (void *)0xac012800;
- case 0x1f2: return (void *)0xac012002;
- case 0x1f3: return (void *)0xac012802;
- case 0x1f4: return (void *)0xac012004;
- case 0x1f5: return (void *)0xac012804;
- case 0x1f6: return (void *)0xac012006;
- case 0x1f7: return (void *)0xac012806;
- case 0x3f6: return (void *)0xac01200e;
+ case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
+ case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
+ case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
+ case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
+ case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
+ case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
+ case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
+ case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
+ case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
default: return (void *)&dummy_reg;
}
}
@@ -64,8 +64,8 @@ static inline void *__port2addr_ata(unsigned long port)
* from 0x10000000 to 0x13ffffff on physical address.
* The base address of LAN controller(LAN91C111) is 0x300.
*/
-#define LAN_IOSTART 0xa0000300
-#define LAN_IOEND 0xa0000320
+#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
+#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
static inline void *_port2addr_ne(unsigned long port)
{
return (void *)(port + 0x10000000);
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
index 3c3da042fbd1..a662b537c5ba 100644
--- a/arch/m32r/kernel/io_mappi.c
+++ b/arch/m32r/kernel/io_mappi.c
@@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port | (NONCACHE_OFFSET));
+ return (void *)(port | NONCACHE_OFFSET);
}
static inline void *_port2addr_ne(unsigned long port)
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
index df3c729cb3e0..e72d725606af 100644
--- a/arch/m32r/kernel/io_mappi2.c
+++ b/arch/m32r/kernel/io_mappi2.c
@@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port | (NONCACHE_OFFSET));
+ return (void *)(port | NONCACHE_OFFSET);
}
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
@@ -42,22 +42,22 @@ static inline void *__port2addr_ata(unsigned long port)
static int dummy_reg;
switch (port) {
- case 0x1f0: return (void *)0xac002000;
- case 0x1f1: return (void *)0xac012800;
- case 0x1f2: return (void *)0xac012002;
- case 0x1f3: return (void *)0xac012802;
- case 0x1f4: return (void *)0xac012004;
- case 0x1f5: return (void *)0xac012804;
- case 0x1f6: return (void *)0xac012006;
- case 0x1f7: return (void *)0xac012806;
- case 0x3f6: return (void *)0xac01200e;
+ case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
+ case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
+ case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
+ case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
+ case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
+ case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
+ case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
+ case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
+ case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
default: return (void *)&dummy_reg;
}
}
#endif
-#define LAN_IOSTART 0xa0000300
-#define LAN_IOEND 0xa0000320
+#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
+#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
#ifdef CONFIG_CHIP_OPSP
static inline void *_port2addr_ne(unsigned long port)
{
diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c
index f80321a58764..ed6da930bc64 100644
--- a/arch/m32r/kernel/io_mappi3.c
+++ b/arch/m32r/kernel/io_mappi3.c
@@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port + NONCACHE_OFFSET);
+ return (void *)(port | NONCACHE_OFFSET);
}
#if defined(CONFIG_IDE)
@@ -43,33 +43,42 @@ static inline void *__port2addr_ata(unsigned long port)
switch (port) {
/* IDE0 CF */
- case 0x1f0: return (void *)0xb4002000;
- case 0x1f1: return (void *)0xb4012800;
- case 0x1f2: return (void *)0xb4012002;
- case 0x1f3: return (void *)0xb4012802;
- case 0x1f4: return (void *)0xb4012004;
- case 0x1f5: return (void *)0xb4012804;
- case 0x1f6: return (void *)0xb4012006;
- case 0x1f7: return (void *)0xb4012806;
- case 0x3f6: return (void *)0xb401200e;
+ case 0x1f0: return (void *)(0x14002000 | NONCACHE_OFFSET);
+ case 0x1f1: return (void *)(0x14012800 | NONCACHE_OFFSET);
+ case 0x1f2: return (void *)(0x14012002 | NONCACHE_OFFSET);
+ case 0x1f3: return (void *)(0x14012802 | NONCACHE_OFFSET);
+ case 0x1f4: return (void *)(0x14012004 | NONCACHE_OFFSET);
+ case 0x1f5: return (void *)(0x14012804 | NONCACHE_OFFSET);
+ case 0x1f6: return (void *)(0x14012006 | NONCACHE_OFFSET);
+ case 0x1f7: return (void *)(0x14012806 | NONCACHE_OFFSET);
+ case 0x3f6: return (void *)(0x1401200e | NONCACHE_OFFSET);
/* IDE1 IDE */
- case 0x170: return (void *)0xb4810000; /* Data 16bit */
- case 0x171: return (void *)0xb4810002; /* Features / Error */
- case 0x172: return (void *)0xb4810004; /* Sector count */
- case 0x173: return (void *)0xb4810006; /* Sector number */
- case 0x174: return (void *)0xb4810008; /* Cylinder low */
- case 0x175: return (void *)0xb481000a; /* Cylinder high */
- case 0x176: return (void *)0xb481000c; /* Device head */
- case 0x177: return (void *)0xb481000e; /* Command */
- case 0x376: return (void *)0xb480800c; /* Device control / Alt status */
+ case 0x170: /* Data 16bit */
+ return (void *)(0x14810000 | NONCACHE_OFFSET);
+ case 0x171: /* Features / Error */
+ return (void *)(0x14810002 | NONCACHE_OFFSET);
+ case 0x172: /* Sector count */
+ return (void *)(0x14810004 | NONCACHE_OFFSET);
+ case 0x173: /* Sector number */
+ return (void *)(0x14810006 | NONCACHE_OFFSET);
+ case 0x174: /* Cylinder low */
+ return (void *)(0x14810008 | NONCACHE_OFFSET);
+ case 0x175: /* Cylinder high */
+ return (void *)(0x1481000a | NONCACHE_OFFSET);
+ case 0x176: /* Device head */
+ return (void *)(0x1481000c | NONCACHE_OFFSET);
+ case 0x177: /* Command */
+ return (void *)(0x1481000e | NONCACHE_OFFSET);
+ case 0x376: /* Device control / Alt status */
+ return (void *)(0x1480800c | NONCACHE_OFFSET);
default: return (void *)&dummy_reg;
}
}
#endif
-#define LAN_IOSTART 0xa0000300
-#define LAN_IOEND 0xa0000320
+#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
+#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
static inline void *_port2addr_ne(unsigned long port)
{
return (void *)(port + 0x10000000);
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
index 8be323931e4a..910dd131c227 100644
--- a/arch/m32r/kernel/io_oaks32r.c
+++ b/arch/m32r/kernel/io_oaks32r.c
@@ -16,7 +16,7 @@
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port | (NONCACHE_OFFSET));
+ return (void *)(port | NONCACHE_OFFSET);
}
static inline void *_port2addr_ne(unsigned long port)
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
index 4793bd18e115..bec69297db3c 100644
--- a/arch/m32r/kernel/io_opsput.c
+++ b/arch/m32r/kernel/io_opsput.c
@@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
static inline void *_port2addr(unsigned long port)
{
- return (void *)(port | (NONCACHE_OFFSET));
+ return (void *)(port | NONCACHE_OFFSET);
}
/*
@@ -44,8 +44,8 @@ static inline void *_port2addr(unsigned long port)
* from 0x10000000 to 0x13ffffff on physical address.
* The base address of LAN controller(LAN91C111) is 0x300.
*/
-#define LAN_IOSTART 0xa0000300
-#define LAN_IOEND 0xa0000320
+#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
+#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
static inline void *_port2addr_ne(unsigned long port)
{
return (void *)(port + 0x10000000);
diff --git a/arch/m32r/kernel/m32r_ksyms.c b/arch/m32r/kernel/m32r_ksyms.c
index e5ec134d81d9..dbc8a392105f 100644
--- a/arch/m32r/kernel/m32r_ksyms.c
+++ b/arch/m32r/kernel/m32r_ksyms.c
@@ -18,8 +18,6 @@
#include <asm/irq.h>
#include <asm/tlbflush.h>
-extern void dump_thread(struct pt_regs *, struct user *);
-
#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
extern struct drive_info_struct drive_info;
EXPORT_SYMBOL(drive_info);
@@ -27,7 +25,6 @@ EXPORT_SYMBOL(drive_info);
/* platform dependent support */
EXPORT_SYMBOL(boot_cpu_data);
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index cc4b571e5db7..5dfc7ea45cf7 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -50,6 +50,10 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void) = NULL;
+EXPORT_SYMBOL(pm_idle);
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
void disable_hlt(void)
{
@@ -238,13 +242,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
int copy_thread(int nr, unsigned long clone_flags, unsigned long spu,
unsigned long unused, struct task_struct *tsk, struct pt_regs *regs)
{
- struct pt_regs *childregs;
- unsigned long sp = (unsigned long)tsk->thread_info + THREAD_SIZE;
+ struct pt_regs *childregs = task_pt_regs(tsk);
extern void ret_from_fork(void);
/* Copy registers */
- sp -= sizeof (struct pt_regs);
- childregs = (struct pt_regs *)sp;
*childregs = *regs;
childregs->spu = spu;
@@ -257,14 +258,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long spu,
}
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- /* M32R_FIXME */
-}
-
-/*
* Capture the user space registers if the task is not running (in user space)
*/
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 078d2a0e71c2..340a3bf59b88 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -35,23 +35,6 @@
#include <asm/mmu_context.h>
/*
- * Get the address of the live pt_regs for the specified task.
- * These are saved onto the top kernel stack when the process
- * is not running.
- *
- * Note: if a user thread is execve'd from kernel space, the
- * kernel stack will not be empty on entry to the kernel, so
- * ptracing these tasks will fail.
- */
-static inline struct pt_regs *
-get_user_regs(struct task_struct *task)
-{
- return (struct pt_regs *)
- ((unsigned long)task->thread_info + THREAD_SIZE
- - sizeof(struct pt_regs));
-}
-
-/*
* This routine will get a word off of the process kernel stack.
*/
static inline unsigned long int
@@ -59,7 +42,7 @@ get_stack_long(struct task_struct *task, int offset)
{
unsigned long *stack;
- stack = (unsigned long *)get_user_regs(task);
+ stack = (unsigned long *)task_pt_regs(task);
return stack[offset];
}
@@ -72,7 +55,7 @@ put_stack_long(struct task_struct *task, int offset, unsigned long data)
{
unsigned long *stack;
- stack = (unsigned long *)get_user_regs(task);
+ stack = (unsigned long *)task_pt_regs(task);
stack[offset] = data;
return 0;
@@ -208,7 +191,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
*/
static int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
{
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}
@@ -223,7 +206,7 @@ static int ptrace_setregs(struct task_struct *tsk, void __user *uregs)
ret = -EFAULT;
if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
- struct pt_regs *regs = get_user_regs(tsk);
+ struct pt_regs *regs = task_pt_regs(tsk);
*regs = newregs;
ret = 0;
}
@@ -762,28 +745,16 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
int ret;
lock_kernel();
- ret = -EPERM;
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
+ ret = ptrace_traceme();
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)
- goto out;
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
goto out;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index f722ec8eb021..c2e4dccf0112 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -320,6 +320,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#elif defined(CONFIG_CHIP_MP)
seq_printf(m, "cpu family\t: M32R-MP\n"
"cache size\t: I-xxKB/D-xxKB\n");
+#elif defined(CONFIG_CHIP_M32104)
+ seq_printf(m,"cpu family\t: M32104\n"
+ "cache size\t: I-8KB/D-8KB\n");
#else
seq_printf(m, "cpu family\t: Unknown\n");
#endif
@@ -340,6 +343,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "Machine\t\t: uServer\n");
#elif defined(CONFIG_PLAT_OAKS32R)
seq_printf(m, "Machine\t\t: OAKS32R\n");
+#elif defined(CONFIG_PLAT_M32104UT)
+ seq_printf(m, "Machine\t\t: M3T-M32104UT uT Engine board\n");
#else
seq_printf(m, "Machine\t\t: Unknown\n");
#endif
@@ -389,7 +394,7 @@ unsigned long cpu_initialized __initdata = 0;
*/
#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
- || defined(CONFIG_CHIP_OPSP)
+ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
void __init cpu_init (void)
{
int cpu_id = smp_processor_id();
diff --git a/arch/m32r/kernel/setup_m32104ut.c b/arch/m32r/kernel/setup_m32104ut.c
new file mode 100644
index 000000000000..6328e1357a80
--- /dev/null
+++ b/arch/m32r/kernel/setup_m32104ut.c
@@ -0,0 +1,156 @@
+/*
+ * linux/arch/m32r/kernel/setup_m32104ut.c
+ *
+ * Setup routines for M32104UT Board
+ *
+ * Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Mamoru Sakugawa,
+ * Naoto Sugai, Hayato Fujiwara
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_m32104ut_irq(unsigned int irq)
+{
+ unsigned long port, data;
+
+ port = irq2port(irq);
+ data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+ outl(data, port);
+}
+
+static void enable_m32104ut_irq(unsigned int irq)
+{
+ unsigned long port, data;
+
+ port = irq2port(irq);
+ data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+ outl(data, port);
+}
+
+static void mask_and_ack_m32104ut(unsigned int irq)
+{
+ disable_m32104ut_irq(irq);
+}
+
+static void end_m32104ut_irq(unsigned int irq)
+{
+ enable_m32104ut_irq(irq);
+}
+
+static unsigned int startup_m32104ut_irq(unsigned int irq)
+{
+ enable_m32104ut_irq(irq);
+ return (0);
+}
+
+static void shutdown_m32104ut_irq(unsigned int irq)
+{
+ unsigned long port;
+
+ port = irq2port(irq);
+ outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type m32104ut_irq_type =
+{
+ .typename = "M32104UT-IRQ",
+ .startup = startup_m32104ut_irq,
+ .shutdown = shutdown_m32104ut_irq,
+ .enable = enable_m32104ut_irq,
+ .disable = disable_m32104ut_irq,
+ .ack = mask_and_ack_m32104ut,
+ .end = end_m32104ut_irq
+};
+
+void __init init_IRQ(void)
+{
+ static int once = 0;
+
+ if (once)
+ return;
+ else
+ once++;
+
+#if defined(CONFIG_SMC91X)
+ /* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/
+ irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_INT0].handler = &m32104ut_irq_type;
+ irq_desc[M32R_IRQ_INT0].action = 0;
+ irq_desc[M32R_IRQ_INT0].depth = 1;
+ icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */
+ disable_m32104ut_irq(M32R_IRQ_INT0);
+#endif /* CONFIG_SMC91X */
+
+ /* MFT2 : system timer */
+ irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_MFT2].handler = &m32104ut_irq_type;
+ irq_desc[M32R_IRQ_MFT2].action = 0;
+ irq_desc[M32R_IRQ_MFT2].depth = 1;
+ icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+ disable_m32104ut_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+ /* SIO0_R : uart receive data */
+ irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO0_R].handler = &m32104ut_irq_type;
+ irq_desc[M32R_IRQ_SIO0_R].action = 0;
+ irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+ icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN;
+ disable_m32104ut_irq(M32R_IRQ_SIO0_R);
+
+ /* SIO0_S : uart send data */
+ irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO0_S].handler = &m32104ut_irq_type;
+ irq_desc[M32R_IRQ_SIO0_S].action = 0;
+ irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+ icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN;
+ disable_m32104ut_irq(M32R_IRQ_SIO0_S);
+#endif /* CONFIG_SERIAL_M32R_SIO */
+}
+
+#if defined(CONFIG_SMC91X)
+
+#define LAN_IOSTART 0x300
+#define LAN_IOEND 0x320
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = (LAN_IOSTART),
+ .end = (LAN_IOEND),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = M32R_IRQ_INT0,
+ .end = M32R_IRQ_INT0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+#endif
+
+static int __init platform_init(void)
+{
+#if defined(CONFIG_SMC91X)
+ platform_device_register(&smc91x_device);
+#endif
+ return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
index cb76916b014d..fad1fc99bb27 100644
--- a/arch/m32r/kernel/setup_m32700ut.c
+++ b/arch/m32r/kernel/setup_m32700ut.c
@@ -26,15 +26,7 @@
*/
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
-#else
icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
-#endif /* CONFIG_SMP */
-
static void disable_m32700ut_irq(unsigned int irq)
{
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
index 501d798cf050..00f253209cb3 100644
--- a/arch/m32r/kernel/setup_mappi.c
+++ b/arch/m32r/kernel/setup_mappi.c
@@ -19,12 +19,6 @@
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-#endif /* CONFIG_SMP */
-
icu_data_t icu_data[NR_IRQS];
static void disable_mappi_irq(unsigned int irq)
diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
index 7f2db5bfd626..eebc9d8b4e72 100644
--- a/arch/m32r/kernel/setup_mappi2.c
+++ b/arch/m32r/kernel/setup_mappi2.c
@@ -19,12 +19,6 @@
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-#endif /* CONFIG_SMP */
-
icu_data_t icu_data[NR_IRQS];
static void disable_mappi2_irq(unsigned int irq)
diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c
index f6ecdf7f555c..d2ff021e2d3d 100644
--- a/arch/m32r/kernel/setup_mappi3.c
+++ b/arch/m32r/kernel/setup_mappi3.c
@@ -19,12 +19,6 @@
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-#endif /* CONFIG_SMP */
-
icu_data_t icu_data[NR_IRQS];
static void disable_mappi3_irq(unsigned int irq)
diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
index 45add5b76f19..0e9e63538c0f 100644
--- a/arch/m32r/kernel/setup_oaks32r.c
+++ b/arch/m32r/kernel/setup_oaks32r.c
@@ -18,12 +18,6 @@
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-#endif /* CONFIG_SMP */
-
icu_data_t icu_data[NR_IRQS];
static void disable_oaks32r_irq(unsigned int irq)
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
index 1fbb140854e7..548e8fc7949b 100644
--- a/arch/m32r/kernel/setup_opsput.c
+++ b/arch/m32r/kernel/setup_opsput.c
@@ -27,15 +27,7 @@
*/
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#ifndef CONFIG_SMP
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
-#else
icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ];
-#endif /* CONFIG_SMP */
-
static void disable_opsput_irq(unsigned int irq)
{
diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
index 634741bf9d35..64be659a23e7 100644
--- a/arch/m32r/kernel/setup_usrv.c
+++ b/arch/m32r/kernel/setup_usrv.c
@@ -18,12 +18,6 @@
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
-#if !defined(CONFIG_SMP)
-typedef struct {
- unsigned long icucr; /* ICU Control Register */
-} icu_data_t;
-#endif /* CONFIG_SMP */
-
icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
static void disable_mappi_irq(unsigned int irq)
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index b90c54169fa5..d7ec16e7fb25 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -286,7 +286,7 @@ static void __init do_boot_cpu(int phys_id)
/* So we see what's up */
printk("Booting processor %d/%d\n", phys_id, cpu_id);
stack_start.spi = (void *)idle->thread.sp;
- idle->thread_info->cpu = cpu_id;
+ task_thread_info(idle)->cpu = cpu_id;
/*
* Send Startup IPI
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 2ebce2063fea..b8e68b542302 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -57,7 +57,7 @@ static unsigned long do_gettimeoffset(void)
#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
- || defined(CONFIG_CHIP_OPSP)
+ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
#ifndef CONFIG_SMP
unsigned long count;
@@ -268,7 +268,7 @@ void __init time_init(void)
#if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
- || defined(CONFIG_CHIP_OPSP)
+ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
/* M32102 MFT setup */
setup_irq(M32R_IRQ_MFT2, &irq0);
diff --git a/arch/arm/configs/epxa10db_defconfig b/arch/m32r/m32104ut/defconfig.m32104ut
index 9fb8b58c4954..454de336803a 100644
--- a/arch/arm/configs/epxa10db_defconfig
+++ b/arch/m32r/m32104ut/defconfig.m32104ut
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:46:51 2005
+# Linux kernel version: 2.6.14
+# Wed Nov 9 16:04:51 2005
#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
+CONFIG_M32R=y
+# CONFIG_UID16 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
#
# Code maturity level options
@@ -16,147 +15,174 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
+CONFIG_LOCALVERSION_AUTO=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_HOTPLUG=y
+# CONFIG_KOBJECT_UEVENT is not set
# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=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_TINY_SHMEM is not set
+CONFIG_TINY_SHMEM=y
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_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
-
-#
-# System Type
-#
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-CONFIG_ARCH_CAMELOT=y
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# Epxa10db
-#
-
-#
-# PLD hotswap support
-#
-CONFIG_PLD=y
-# CONFIG_PLD_HOTSWAP is not set
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
+CONFIG_PLAT_M32104UT=y
+# CONFIG_CHIP_M32700 is not set
+# CONFIG_CHIP_M32102 is not set
+CONFIG_CHIP_M32104=y
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_ISA_M32R=y
+CONFIG_BUS_CLOCK=54000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=04000000
+CONFIG_MEMORY_SIZE=01000000
+CONFIG_NOHIGHMEM=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
#
-# Processor Type
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-CONFIG_CPU_32=y
-CONFIG_CPU_ARM922T=y
-CONFIG_CPU_32v4=y
-CONFIG_CPU_ABRT_EV4T=y
-CONFIG_CPU_CACHE_V4WT=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_COPY_V4WB=y
-CONFIG_CPU_TLB_V4WBI=y
+# CONFIG_ISA is not set
#
-# Processor Features
+# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_ARM_THUMB is not set
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
#
-# Bus support
+# PC-card bridges
#
#
-# PCCARD (PCMCIA/CardBus) support
+# PCI Hotplug Support
#
-# CONFIG_PCCARD is not set
#
-# Kernel Features
+# Executable file formats
#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
#
-# Boot options
+# Networking
#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=32M console=ttyUA0,115200 initrd=0x00200000,8M root=/dev/ram0 rw"
-# CONFIG_XIP_KERNEL is not set
+CONFIG_NET=y
#
-# Floating point emulation
+# 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=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_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
#
-# At least one emulation must be selected
+# DCCP Configuration (EXPERIMENTAL)
#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
+# CONFIG_IP_DCCP is not set
#
-# Userspace binary formats
+# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR 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
#
-# Power management options
+# Network testing
#
-# CONFIG_PM is not set
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -167,7 +193,13 @@ CONFIG_BINFMT_ELF=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
@@ -186,30 +218,34 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD 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_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CDROM_PKTCDVD is not set
#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_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
+
+#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -220,6 +256,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -230,81 +267,26 @@ CONFIG_IOSCHED_CFQ=y
#
#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
+# Network device support
#
-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 is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# 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_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
-# CONFIG_NET_ETHERNET is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_NE2000 is not set
#
# Ethernet (1000 Mbit)
@@ -324,20 +306,20 @@ CONFIG_NETDEVICES=y
# CONFIG_NET_RADIO is not set
#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
# Wan interfaces
#
# CONFIG_WAN is not set
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
-CONFIG_PPP_DEFLATE=y
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE 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
@@ -345,46 +327,25 @@ CONFIG_PPP_DEFLATE=y
# CONFIG_ISDN is not set
#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
+# Telephony Support
#
-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_PHONE is not set
#
-# Input Device Drivers
+# Input device support
#
-# 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
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -395,10 +356,10 @@ CONFIG_HW_CONSOLE=y
#
# Non-8250 serial port support
#
-CONFIG_SERIAL_UART00=y
-CONFIG_SERIAL_UART00_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -411,8 +372,13 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=y
# CONFIG_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -420,13 +386,16 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
-# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -434,10 +403,25 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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
@@ -453,12 +437,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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
@@ -466,9 +444,8 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
-CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB is not set
#
# USB Gadget Support
@@ -481,25 +458,38 @@ CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_MMC is not set
#
+# InfiniBand support
+#
+
+#
+# SN Devices
+#
+
+#
# 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_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -510,8 +500,11 @@ CONFIG_AUTOFS4_FS=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=932
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -519,11 +512,10 @@ CONFIG_AUTOFS4_FS=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -535,7 +527,7 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -545,14 +537,25 @@ CONFIG_RAMFS=y
#
# Network File Systems
#
-# CONFIG_NFS_FS is not set
+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_SMB_FS=y
-# CONFIG_SMB_NLS_DEFAULT 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
@@ -565,7 +568,7 @@ CONFIG_MSDOS_PARTITION=y
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
@@ -582,7 +585,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
+CONFIG_NLS_CODEPAGE_932=y
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
@@ -602,7 +605,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=y
#
# Profiling support
@@ -613,11 +616,21 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
#
# Security options
@@ -637,8 +650,8 @@ CONFIG_FRAME_POINTER=y
#
# Library routines
#
-CONFIG_CRC_CCITT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/m32r/mm/cache.c b/arch/m32r/mm/cache.c
index 31b0789c1992..9f54dd937013 100644
--- a/arch/m32r/mm/cache.c
+++ b/arch/m32r/mm/cache.c
@@ -1,7 +1,7 @@
/*
* linux/arch/m32r/mm/cache.c
*
- * Copyright (C) 2002 Hirokazu Takata
+ * Copyright (C) 2002-2005 Hirokazu Takata, Hayato Fujiwara
*/
#include <linux/config.h>
@@ -9,7 +9,8 @@
#undef MCCR
-#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP)
+#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) \
+ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP)
/* Cache Control Register */
#define MCCR ((volatile unsigned long*)0xfffffffc)
#define MCCR_CC (1UL << 7) /* Cache mode modify bit */
@@ -26,7 +27,17 @@
#define MCCR ((volatile unsigned char*)0xfffffffe)
#define MCCR_IIV (1UL << 0) /* I-cache invalidate */
#define MCCR_ICACHE_INV MCCR_IIV
-#endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */
+#elif defined(CONFIG_CHIP_M32104)
+#define MCCR ((volatile unsigned short*)0xfffffffe)
+#define MCCR_IIV (1UL << 8) /* I-cache invalidate */
+#define MCCR_DIV (1UL << 9) /* D-cache invalidate */
+#define MCCR_DCB (1UL << 10) /* D-cache copy back */
+#define MCCR_ICM (1UL << 0) /* I-cache mode [0:off,1:on] */
+#define MCCR_DCM (1UL << 1) /* D-cache mode [0:off,1:on] */
+#define MCCR_ICACHE_INV MCCR_IIV
+#define MCCR_DCACHE_CB MCCR_DCB
+#define MCCR_DCACHE_CBINV (MCCR_DIV|MCCR_DCB)
+#endif
#ifndef MCCR
#error Unknown cache type.
@@ -37,29 +48,42 @@
void _flush_cache_all(void)
{
#if defined(CONFIG_CHIP_M32102)
+ unsigned char mccr;
*MCCR = MCCR_ICACHE_INV;
+#elif defined(CONFIG_CHIP_M32104)
+ unsigned short mccr;
+
+ /* Copyback and invalidate D-cache */
+ /* Invalidate I-cache */
+ *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CBINV);
#else
unsigned long mccr;
/* Copyback and invalidate D-cache */
/* Invalidate I-cache */
*MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CBINV;
- while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
#endif
+ while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
}
/* Copy back D-cache and invalidate I-cache all */
void _flush_cache_copyback_all(void)
{
#if defined(CONFIG_CHIP_M32102)
+ unsigned char mccr;
*MCCR = MCCR_ICACHE_INV;
+#elif defined(CONFIG_CHIP_M32104)
+ unsigned short mccr;
+
+ /* Copyback and invalidate D-cache */
+ /* Invalidate I-cache */
+ *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CB);
#else
unsigned long mccr;
/* Copyback D-cache */
/* Invalidate I-cache */
*MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CB;
- while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
-
#endif
+ while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */
}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 1dd5d18b2201..96b919828053 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -10,10 +10,6 @@ config MMU
bool
default y
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index d9edf2d1a492..b0aa61bf8700 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -126,9 +126,9 @@ void __init amiga_init_IRQ(void)
gayle.inten = GAYLE_IRQ_IDE;
/* turn off all interrupts and enable the master interrupt bit */
- custom.intena = 0x7fff;
- custom.intreq = 0x7fff;
- custom.intena = IF_SETCLR | IF_INTEN;
+ amiga_custom.intena = 0x7fff;
+ amiga_custom.intreq = 0x7fff;
+ amiga_custom.intena = IF_SETCLR | IF_INTEN;
cia_init_IRQ(&ciaa_base);
cia_init_IRQ(&ciab_base);
@@ -245,7 +245,7 @@ int amiga_request_irq(unsigned int irq,
/* enable the interrupt */
if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
- custom.intena = IF_SETCLR | amiga_intena_vals[irq];
+ amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
return error;
}
@@ -274,7 +274,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id)
amiga_delete_irq(&ami_irq_list[irq], dev_id);
/* if server list empty, disable the interrupt */
if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
- custom.intena = amiga_intena_vals[irq];
+ amiga_custom.intena = amiga_intena_vals[irq];
} else {
if (ami_irq_list[irq]->dev_id != dev_id)
printk("%s: removing probably wrong IRQ %d from %s\n",
@@ -283,7 +283,7 @@ void amiga_free_irq(unsigned int irq, void *dev_id)
ami_irq_list[irq]->flags = 0;
ami_irq_list[irq]->dev_id = NULL;
ami_irq_list[irq]->devname = NULL;
- custom.intena = amiga_intena_vals[irq];
+ amiga_custom.intena = amiga_intena_vals[irq];
}
}
@@ -327,7 +327,7 @@ void amiga_enable_irq(unsigned int irq)
}
/* enable the interrupt */
- custom.intena = IF_SETCLR | amiga_intena_vals[irq];
+ amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
}
void amiga_disable_irq(unsigned int irq)
@@ -358,7 +358,7 @@ void amiga_disable_irq(unsigned int irq)
}
/* disable the interrupt */
- custom.intena = amiga_intena_vals[irq];
+ amiga_custom.intena = amiga_intena_vals[irq];
}
inline void amiga_do_irq(int irq, struct pt_regs *fp)
@@ -373,7 +373,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
kstat_cpu(0).irqs[SYS_IRQS + irq]++;
- custom.intreq = amiga_intena_vals[irq];
+ amiga_custom.intreq = amiga_intena_vals[irq];
for (node = ami_irq_list[irq]; node; node = node->next)
node->handler(irq, node->dev_id, fp);
@@ -385,23 +385,23 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if serial transmit buffer empty, interrupt */
if (ints & IF_TBE) {
- custom.intreq = IF_TBE;
+ amiga_custom.intreq = IF_TBE;
amiga_do_irq(IRQ_AMIGA_TBE, fp);
}
/* if floppy disk transfer complete, interrupt */
if (ints & IF_DSKBLK) {
- custom.intreq = IF_DSKBLK;
+ amiga_custom.intreq = IF_DSKBLK;
amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
}
/* if software interrupt set, interrupt */
if (ints & IF_SOFT) {
- custom.intreq = IF_SOFT;
+ amiga_custom.intreq = IF_SOFT;
amiga_do_irq(IRQ_AMIGA_SOFT, fp);
}
return IRQ_HANDLED;
@@ -409,17 +409,17 @@ static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp)
static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if a blitter interrupt */
if (ints & IF_BLIT) {
- custom.intreq = IF_BLIT;
+ amiga_custom.intreq = IF_BLIT;
amiga_do_irq(IRQ_AMIGA_BLIT, fp);
}
/* if a copper interrupt */
if (ints & IF_COPER) {
- custom.intreq = IF_COPER;
+ amiga_custom.intreq = IF_COPER;
amiga_do_irq(IRQ_AMIGA_COPPER, fp);
}
@@ -431,29 +431,29 @@ static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp)
static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if audio 0 interrupt */
if (ints & IF_AUD0) {
- custom.intreq = IF_AUD0;
+ amiga_custom.intreq = IF_AUD0;
amiga_do_irq(IRQ_AMIGA_AUD0, fp);
}
/* if audio 1 interrupt */
if (ints & IF_AUD1) {
- custom.intreq = IF_AUD1;
+ amiga_custom.intreq = IF_AUD1;
amiga_do_irq(IRQ_AMIGA_AUD1, fp);
}
/* if audio 2 interrupt */
if (ints & IF_AUD2) {
- custom.intreq = IF_AUD2;
+ amiga_custom.intreq = IF_AUD2;
amiga_do_irq(IRQ_AMIGA_AUD2, fp);
}
/* if audio 3 interrupt */
if (ints & IF_AUD3) {
- custom.intreq = IF_AUD3;
+ amiga_custom.intreq = IF_AUD3;
amiga_do_irq(IRQ_AMIGA_AUD3, fp);
}
return IRQ_HANDLED;
@@ -461,7 +461,7 @@ static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp)
static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if serial receive buffer full interrupt */
if (ints & IF_RBF) {
@@ -471,7 +471,7 @@ static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp)
/* if a disk sync interrupt */
if (ints & IF_DSKSYN) {
- custom.intreq = IF_DSKSYN;
+ amiga_custom.intreq = IF_DSKSYN;
amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
}
return IRQ_HANDLED;
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index bd5d134e9f12..ae94db5d93b2 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -24,6 +24,8 @@ static const signed char sine_data[] = {
};
#define DATA_SIZE (sizeof(sine_data)/sizeof(sine_data[0]))
+#define custom amiga_custom
+
/*
* The minimum period for audio may be modified by the frame buffer
* device since it depends on htotal (for OCS/ECS/AGA)
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 7d55682615e3..9476eb9440f5 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -60,7 +60,7 @@ unsigned char cia_set_irq(struct ciabase *base, unsigned char mask)
else
base->icr_data &= ~mask;
if (base->icr_data & base->icr_mask)
- custom.intreq = IF_SETCLR | base->int_mask;
+ amiga_custom.intreq = IF_SETCLR | base->int_mask;
return old & base->icr_mask;
}
@@ -89,7 +89,7 @@ unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
}
}
if (base->icr_data & base->icr_mask)
- custom.intreq = IF_SETCLR | base->int_mask;
+ amiga_custom.intreq = IF_SETCLR | base->int_mask;
return old;
}
@@ -133,7 +133,7 @@ static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
mach_irq = base->cia_irq;
irq = SYS_IRQS + mach_irq;
ints = cia_set_irq(base, CIA_ICR_ALL);
- custom.intreq = base->int_mask;
+ amiga_custom.intreq = base->int_mask;
for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
if (ints & 1) {
kstat_cpu(0).irqs[irq]++;
@@ -162,7 +162,7 @@ void __init cia_init_IRQ(struct ciabase *base)
/* install CIA handler */
request_irq(base->handler_irq, cia_handler, 0, base->name, base);
- custom.intena = IF_SETCLR | base->int_mask;
+ amiga_custom.intena = IF_SETCLR | base->int_mask;
}
int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 4775e18a78f0..12e3706fe02c 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -105,9 +105,6 @@ static int a2000_hwclk (int, struct rtc_time *);
static int amiga_set_clock_mmss (unsigned long);
static unsigned int amiga_get_ss (void);
extern void amiga_mksound( unsigned int count, unsigned int ticks );
-#ifdef CONFIG_AMIGA_FLOPPY
-extern void amiga_floppy_setup(char *, int *);
-#endif
static void amiga_reset (void);
extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
@@ -290,7 +287,7 @@ static void __init amiga_identify(void)
case CS_OCS:
case CS_ECS:
case CS_AGA:
- switch (custom.deniseid & 0xf) {
+ switch (amiga_custom.deniseid & 0xf) {
case 0x0c:
AMIGAHW_SET(DENISE_HR);
break;
@@ -303,7 +300,7 @@ static void __init amiga_identify(void)
AMIGAHW_SET(DENISE);
break;
}
- switch ((custom.vposr>>8) & 0x7f) {
+ switch ((amiga_custom.vposr>>8) & 0x7f) {
case 0x00:
AMIGAHW_SET(AGNUS_PAL);
break;
@@ -427,13 +424,7 @@ void __init config_amiga(void)
mach_set_clock_mmss = amiga_set_clock_mmss;
mach_get_ss = amiga_get_ss;
-#ifdef CONFIG_AMIGA_FLOPPY
- mach_floppy_setup = amiga_floppy_setup;
-#endif
mach_reset = amiga_reset;
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
mach_beep = amiga_mksound;
#endif
@@ -447,9 +438,9 @@ void __init config_amiga(void)
amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
/* clear all DMA bits */
- custom.dmacon = DMAF_ALL;
+ amiga_custom.dmacon = DMAF_ALL;
/* ensure that the DMA master bit is set */
- custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+ amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
/* don't use Z2 RAM as system memory on Z3 capable machines */
if (AMIGAHW_PRESENT(ZORRO3)) {
@@ -830,8 +821,8 @@ static void amiga_savekmsg_init(void)
static void amiga_serial_putc(char c)
{
- custom.serdat = (unsigned char)c | 0x100;
- while (!(custom.serdatr & 0x2000))
+ amiga_custom.serdat = (unsigned char)c | 0x100;
+ while (!(amiga_custom.serdatr & 0x2000))
;
}
@@ -855,11 +846,11 @@ int amiga_serial_console_wait_key(struct console *co)
{
int ch;
- while (!(custom.intreqr & IF_RBF))
+ while (!(amiga_custom.intreqr & IF_RBF))
barrier();
- ch = custom.serdatr & 0xff;
+ ch = amiga_custom.serdatr & 0xff;
/* clear the interrupt, so that another character can be read */
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
return ch;
}
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 264929471253..d401962d9b25 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -176,9 +176,6 @@ void config_apollo(void) {
mach_set_clock_mmss = dn_dummy_set_clock_mmss; /* */
mach_process_int = dn_process_int;
mach_reset = dn_dummy_reset; /* */
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
#ifdef CONFIG_HEARTBEAT
mach_heartbeat = dn_heartbeat;
#endif
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 9261d2deeaf5..1012b08e5522 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -52,9 +52,6 @@ int atari_rtc_year_offset;
/* local function prototypes */
static void atari_reset( void );
-#ifdef CONFIG_ATARI_FLOPPY
-extern void atari_floppy_setup(char *, int *);
-#endif
static void atari_get_model(char *model);
static int atari_get_hardware_list(char *buffer);
@@ -244,12 +241,6 @@ void __init config_atari(void)
mach_get_irq_list = show_atari_interrupts;
mach_gettimeoffset = atari_gettimeoffset;
mach_reset = atari_reset;
-#ifdef CONFIG_ATARI_FLOPPY
- mach_floppy_setup = atari_floppy_setup;
-#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
mach_max_dma_address = 0xffffff;
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
mach_beep = atari_mksound;
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index eb63ca6ed94c..703cbc6dc9cc 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -11,6 +11,7 @@
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
@@ -46,6 +47,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned char msr;
unsigned long flags;
struct rtc_time wtime;
+ void __user *argp = (void __user *)arg;
switch (cmd) {
case RTC_RD_TIME: /* Read the time/date from RTC */
@@ -68,7 +70,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec));
rtc->msr = msr;
local_irq_restore(flags);
- return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
+ return copy_to_user(argp, &wtime, sizeof wtime) ?
-EFAULT : 0;
}
case RTC_SET_TIME: /* Set the RTC */
@@ -80,8 +82,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
- sizeof(struct rtc_time)))
+ if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time)))
return -EFAULT;
yrs = rtc_tm.tm_year;
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index a0b854f3f94a..6d129eef370f 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -261,9 +261,6 @@ void __init config_hp300(void)
#ifdef CONFIG_HEARTBEAT
mach_heartbeat = hp300_pulse;
#endif
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
mach_max_dma_address = 0xffffffff;
if (hp300_model >= HP_330 && hp300_model <= HP_433S && hp300_model != HP_350) {
diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c
index c787c5ba9513..246a8820c223 100644
--- a/arch/m68k/kernel/asm-offsets.c
+++ b/arch/m68k/kernel/asm-offsets.c
@@ -92,7 +92,7 @@ int main(void)
DEFINE(TRAP_TRACE, TRAP_TRACE);
/* offsets into the custom struct */
- DEFINE(CUSTOMBASE, &custom);
+ DEFINE(CUSTOMBASE, &amiga_custom);
DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index d4336d846df1..70002c146eed 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -273,8 +273,10 @@
* Macintosh console support
*/
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE
#define CONSOLE
#define CONSOLE_PENGUIN
+#endif
/*
* Macintosh serial debug support; outputs boot info to the printer
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 73e2f5e168dd..3d7f2000b714 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -23,8 +23,6 @@ asmlinkage long long __lshrdi3 (long long, int);
asmlinkage long long __muldi3 (long long, long long);
extern char m68k_debug_device[];
-extern void dump_thread(struct pt_regs *, struct user *);
-
/* platform dependent support */
EXPORT_SYMBOL(m68k_machtype);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 13d109328a42..3f9cb55d0356 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -238,10 +238,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
{
struct pt_regs * childregs;
struct switch_stack * childstack, *stack;
- unsigned long stack_offset, *retp;
+ unsigned long *retp;
- stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
- childregs = (struct pt_regs *) ((unsigned long) (p->thread_info) + stack_offset);
+ childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
*childregs = *regs;
childregs->d0 = 0;
@@ -386,7 +385,7 @@ unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)(p->thread_info);
+ stack_page = (unsigned long)task_stack_page(p);
fp = ((struct switch_stack *)p->thread.ksp)->a6;
do {
if (fp < stack_page+sizeof(struct thread_info) ||
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index d6ca99242e5a..750d5b3c971f 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -84,9 +84,6 @@ void (*mach_reset)( void );
void (*mach_halt)( void );
void (*mach_power_off)( void );
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
-void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-#endif
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int);
EXPORT_SYMBOL(mach_heartbeat);
@@ -100,6 +97,8 @@ void (*mach_beep)(unsigned int, unsigned int);
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
int isa_type;
int isa_sex;
+EXPORT_SYMBOL(isa_type);
+EXPORT_SYMBOL(isa_sex);
#endif
extern int amiga_parse_bootinfo(const struct bi_record *);
@@ -280,6 +279,10 @@ void __init setup_arch(char **cmdline_p)
}
}
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
switch (m68k_machtype) {
#ifdef CONFIG_AMIGA
case MACH_AMIGA:
@@ -521,16 +524,6 @@ int get_hardware_list(char *buffer)
return(len);
}
-
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
-void __init floppy_setup(char *str, int *ints)
-{
- if (mach_floppy_setup)
- mach_floppy_setup (str, ints);
-}
-
-#endif
-
void check_bugs(void)
{
#ifndef CONFIG_M68KFPU_EMU
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 9c636a4c238d..866917bfa028 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -96,7 +96,7 @@ asmlinkage int do_sigsuspend(struct pt_regs *regs)
asmlinkage int
do_rt_sigsuspend(struct pt_regs *regs)
{
- sigset_t *unewset = (sigset_t *)regs->d1;
+ sigset_t __user *unewset = (sigset_t __user *)regs->d1;
size_t sigsetsize = (size_t)regs->d2;
sigset_t saveset, newset;
@@ -122,8 +122,8 @@ do_rt_sigsuspend(struct pt_regs *regs)
}
asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+ struct old_sigaction __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
@@ -154,7 +154,7 @@ sys_sigaction(int sig, const struct old_sigaction *act,
}
asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
{
return do_sigaltstack(uss, uoss, rdusp());
}
@@ -169,10 +169,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
struct sigframe
{
- char *pretcode;
+ char __user *pretcode;
int sig;
int code;
- struct sigcontext *psc;
+ struct sigcontext __user *psc;
char retcode[8];
unsigned long extramask[_NSIG_WORDS-1];
struct sigcontext sc;
@@ -180,10 +180,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;
char retcode[8];
struct siginfo info;
struct ucontext uc;
@@ -248,7 +248,7 @@ out:
#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
-static inline int rt_restore_fpu_state(struct ucontext *uc)
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
{
unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = CPU_IS_060 ? 8 : 0;
@@ -267,7 +267,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
return 0;
}
- if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
+ if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
goto out;
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
if (!CPU_IS_060)
@@ -306,7 +306,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
"m" (*fpregs.f_fpcntl));
}
if (context_size &&
- __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
+ __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
context_size))
goto out;
__asm__ volatile (".chip 68k/68881\n\t"
@@ -319,7 +319,7 @@ out:
}
static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
int *pd0)
{
int fsize, formatvec;
@@ -404,10 +404,10 @@ badframe:
static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
- struct ucontext *uc, int *pd0)
+ struct ucontext __user *uc, int *pd0)
{
int fsize, temp;
- greg_t *gregs = uc->uc_mcontext.gregs;
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
unsigned long usp;
int err;
@@ -506,7 +506,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp();
- struct sigframe *frame = (struct sigframe *)(usp - 4);
+ struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set;
int d0;
@@ -536,7 +536,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp();
- struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
+ struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
sigset_t set;
int d0;
@@ -596,7 +596,7 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
}
}
-static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
{
unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = CPU_IS_060 ? 8 : 0;
@@ -617,7 +617,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
".chip 68k"
: : "m" (*fpstate) : "memory");
- err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
+ err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
fpregset_t fpregs;
if (!CPU_IS_060)
@@ -642,7 +642,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
sizeof(fpregs));
}
if (context_size)
- err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
+ err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
context_size);
return err;
}
@@ -662,10 +662,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
save_fpu_state(sc, regs);
}
-static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
+static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
{
struct switch_stack *sw = (struct switch_stack *)regs - 1;
- greg_t *gregs = uc->uc_mcontext.gregs;
+ greg_t __user *gregs = uc->uc_mcontext.gregs;
int err = 0;
err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
@@ -753,7 +753,7 @@ static inline void push_cache (unsigned long vaddr)
}
}
-static inline void *
+static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
unsigned long usp;
@@ -766,13 +766,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
if (!on_sig_stack(usp))
usp = current->sas_ss_sp + current->sas_ss_size;
}
- return (void *)((usp - frame_size) & -8UL);
+ return (void __user *)((usp - frame_size) & -8UL);
}
static void setup_frame (int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
- struct sigframe *frame;
+ struct sigframe __user *frame;
int fsize = frame_extra_sizes[regs->format];
struct sigcontext context;
int err = 0;
@@ -813,7 +813,7 @@ static void setup_frame (int sig, struct k_sigaction *ka,
err |= __put_user(frame->retcode, &frame->pretcode);
/* moveq #,d0; trap #0 */
err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
- (long *)(frame->retcode));
+ (long __user *)(frame->retcode));
if (err)
goto give_sigsegv;
@@ -849,7 +849,7 @@ give_sigsegv:
static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
- struct rt_sigframe *frame;
+ struct rt_sigframe __user *frame;
int fsize = frame_extra_sizes[regs->format];
int err = 0;
@@ -880,8 +880,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __put_user((void *)current->sas_ss_sp,
+ err |= __put_user(NULL, &frame->uc.uc_link);
+ err |= __put_user((void __user *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(rdusp()),
&frame->uc.uc_stack.ss_flags);
@@ -893,8 +893,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(frame->retcode, &frame->pretcode);
/* moveq #,d0; notb d0; trap #0 */
err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
- (long *)(frame->retcode + 0));
- err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
+ (long __user *)(frame->retcode + 0));
+ err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
if (err)
goto give_sigsegv;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 2ed7b783f654..143c552d38f3 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -6,6 +6,7 @@
* platform.
*/
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -31,7 +32,7 @@
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
-asmlinkage int sys_pipe(unsigned long * fildes)
+asmlinkage int sys_pipe(unsigned long __user * fildes)
{
int fd[2];
int error;
@@ -93,7 +94,7 @@ struct mmap_arg_struct {
unsigned long offset;
};
-asmlinkage int old_mmap(struct mmap_arg_struct *arg)
+asmlinkage int old_mmap(struct mmap_arg_struct __user *arg)
{
struct mmap_arg_struct a;
int error = -EFAULT;
@@ -159,11 +160,11 @@ out:
struct sel_arg_struct {
unsigned long n;
- fd_set *inp, *outp, *exp;
- struct timeval *tvp;
+ fd_set __user *inp, *outp, *exp;
+ struct timeval __user *tvp;
};
-asmlinkage int old_select(struct sel_arg_struct *arg)
+asmlinkage int old_select(struct sel_arg_struct __user *arg)
{
struct sel_arg_struct a;
@@ -179,7 +180,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
* This is really horribly ugly.
*/
asmlinkage int sys_ipc (uint call, int first, int second,
- int third, void *ptr, long fifth)
+ int third, void __user *ptr, long fifth)
{
int version, ret;
@@ -189,14 +190,14 @@ asmlinkage int sys_ipc (uint call, int first, int second,
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ return sys_semop (first, ptr, second);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
union semun fourth;
if (!ptr)
return -EINVAL;
- if (get_user(fourth.__pad, (void **) ptr))
+ if (get_user(fourth.__pad, (void __user *__user *) ptr))
return -EFAULT;
return sys_semctl (first, second, third, fourth);
}
@@ -206,31 +207,26 @@ asmlinkage int sys_ipc (uint call, int first, int second,
if (call <= MSGCTL)
switch (call) {
case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
- second, third);
+ return sys_msgsnd (first, ptr, second, third);
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
if (!ptr)
return -EINVAL;
- if (copy_from_user (&tmp,
- (struct ipc_kludge *)ptr,
- sizeof (tmp)))
+ if (copy_from_user (&tmp, ptr, sizeof (tmp)))
return -EFAULT;
return sys_msgrcv (first, tmp.msgp, second,
tmp.msgtyp, third);
}
default:
- return sys_msgrcv (first,
- (struct msgbuf *) ptr,
+ return sys_msgrcv (first, ptr,
second, fifth, third);
}
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
- return sys_msgctl (first, second,
- (struct msqid_ds *) ptr);
+ return sys_msgctl (first, second, ptr);
default:
return -ENOSYS;
}
@@ -240,20 +236,18 @@ asmlinkage int sys_ipc (uint call, int first, int second,
switch (version) {
default: {
ulong raddr;
- ret = do_shmat (first, (char *) ptr,
- second, &raddr);
+ ret = do_shmat (first, ptr, second, &raddr);
if (ret)
return ret;
- return put_user (raddr, (ulong *) third);
+ return put_user (raddr, (ulong __user *) third);
}
}
case SHMDT:
- return sys_shmdt ((char *)ptr);
+ return sys_shmdt (ptr);
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
- return sys_shmctl (first, second,
- (struct shmid_ds *) ptr);
+ return sys_shmctl (first, second, ptr);
default:
return -ENOSYS;
}
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index deb36e8b04a2..cdf58fbb3e73 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -169,25 +169,25 @@ void __init trap_init (void)
if (CPU_IS_060 && !FPU_IS_EMU) {
/* set up IFPSP entry points */
- asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
- asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
- asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
- asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
- asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
- asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
- asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
- asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
- asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
-
- vectors[VEC_FPNAN] = snan_vec;
- vectors[VEC_FPOE] = operr_vec;
- vectors[VEC_FPOVER] = ovfl_vec;
- vectors[VEC_FPUNDER] = unfl_vec;
- vectors[VEC_FPDIVZ] = dz_vec;
- vectors[VEC_FPIR] = inex_vec;
- vectors[VEC_LINE11] = fline_vec;
- vectors[VEC_FPUNSUP] = unsupp_vec;
- vectors[VEC_UNIMPEA] = effadd_vec;
+ asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
+ asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
+ asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
+ asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
+ asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
+ asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
+ asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
+ asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
+ asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
+
+ vectors[VEC_FPNAN] = snan_vec6;
+ vectors[VEC_FPOE] = operr_vec6;
+ vectors[VEC_FPOVER] = ovfl_vec6;
+ vectors[VEC_FPUNDER] = unfl_vec6;
+ vectors[VEC_FPDIVZ] = dz_vec6;
+ vectors[VEC_FPIR] = inex_vec6;
+ vectors[VEC_LINE11] = fline_vec6;
+ vectors[VEC_FPUNSUP] = unsupp_vec6;
+ vectors[VEC_UNIMPEA] = effadd_vec6;
}
/* if running on an amiga, make the NMI interrupt do nothing */
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index e58654f3f8dd..69d1d3d30c78 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -13,6 +13,7 @@ SECTIONS
.text : {
*(.text)
SCHED_TEXT
+ LOCK_TEXT
*(.fixup)
*(.gnu.warning)
} :text = 0x4e75
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index cc37e8d3c1e2..65cc39c24185 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -14,6 +14,7 @@ SECTIONS
*(.head)
*(.text)
SCHED_TEXT
+ LOCK_TEXT
*(.fixup)
*(.gnu.warning)
} :text = 0x4e75
@@ -66,7 +67,7 @@ __init_begin = .;
__initramfs_end = .;
. = ALIGN(8192);
__init_end = .;
- .init.task : { *(init_task) }
+ .data.init.task : { *(.data.init_task) }
.bss : { *(.bss) } /* BSS */
diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c
index 4a5c5445c610..cb13c6e3ccae 100644
--- a/arch/m68k/lib/checksum.c
+++ b/arch/m68k/lib/checksum.c
@@ -134,7 +134,7 @@ EXPORT_SYMBOL(csum_partial);
*/
unsigned int
-csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
+csum_partial_copy_from_user(const unsigned char __user *src, unsigned char *dst,
int len, int sum, int *csum_err)
{
/*
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index cd19cbb213e8..14f8d3f4e195 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -212,9 +212,6 @@ void __init config_mac(void)
mach_reset = mac_reset;
mach_halt = mac_poweroff;
mach_power_off = mac_poweroff;
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
mach_max_dma_address = 0xffffffff;
#if 0
mach_debug_init = mac_debug_init;
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index d889ba80ccdc..9179a3798407 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -293,8 +293,8 @@ void __init iop_init(void)
}
for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
- iop_send_queue[IOP_NUM_SCC][i] = 0;
- iop_send_queue[IOP_NUM_ISM][i] = 0;
+ iop_send_queue[IOP_NUM_SCC][i] = NULL;
+ iop_send_queue[IOP_NUM_ISM][i] = NULL;
iop_listeners[IOP_NUM_SCC][i].devname = NULL;
iop_listeners[IOP_NUM_SCC][i].handler = NULL;
iop_listeners[IOP_NUM_ISM][i].devname = NULL;
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index 5b80d7cd954a..bbb0c3b95e9c 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -39,72 +39,163 @@
extern struct mac_booter_data mac_bi_data;
static void (*rom_reset)(void);
-#ifdef CONFIG_ADB
-/*
- * Return the current time as the number of seconds since January 1, 1904.
- */
-
-static long adb_read_time(void)
+#ifdef CONFIG_ADB_CUDA
+static long cuda_read_time(void)
{
- volatile struct adb_request req;
+ struct adb_request req;
long time;
- adb_request((struct adb_request *) &req, NULL,
- ADBREQ_RAW|ADBREQ_SYNC,
- 2, CUDA_PACKET, CUDA_GET_TIME);
+ if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+ return 0;
+ while (!req.complete)
+ cuda_poll();
time = (req.reply[3] << 24) | (req.reply[4] << 16)
| (req.reply[5] << 8) | req.reply[6];
return time - RTC_OFFSET;
}
-/*
- * Set the current system time
- */
+static void cuda_write_time(long data)
+{
+ struct adb_request req;
+ data += RTC_OFFSET;
+ if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+ (data >> 24) & 0xFF, (data >> 16) & 0xFF,
+ (data >> 8) & 0xFF, data & 0xFF) < 0)
+ return;
+ while (!req.complete)
+ cuda_poll();
+}
-static void adb_write_time(long data)
+static __u8 cuda_read_pram(int offset)
{
- volatile struct adb_request req;
+ struct adb_request req;
+ if (cuda_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF) < 0)
+ return 0;
+ while (!req.complete)
+ cuda_poll();
+ return req.reply[3];
+}
- data += RTC_OFFSET;
+static void cuda_write_pram(int offset, __u8 data)
+{
+ struct adb_request req;
+ if (cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
+ return;
+ while (!req.complete)
+ cuda_poll();
+}
+#else
+#define cuda_read_time() 0
+#define cuda_write_time(n)
+#define cuda_read_pram NULL
+#define cuda_write_pram NULL
+#endif
+
+#ifdef CONFIG_ADB_PMU68K
+static long pmu_read_time(void)
+{
+ struct adb_request req;
+ long time;
+
+ if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+ return 0;
+ while (!req.complete)
+ pmu_poll();
- adb_request((struct adb_request *) &req, NULL,
- ADBREQ_RAW|ADBREQ_SYNC,
- 6, CUDA_PACKET, CUDA_SET_TIME,
+ time = (req.reply[0] << 24) | (req.reply[1] << 16)
+ | (req.reply[2] << 8) | req.reply[3];
+ return time - RTC_OFFSET;
+}
+
+static void pmu_write_time(long data)
+{
+ struct adb_request req;
+ data += RTC_OFFSET;
+ if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
(data >> 24) & 0xFF, (data >> 16) & 0xFF,
- (data >> 8) & 0xFF, data & 0xFF);
+ (data >> 8) & 0xFF, data & 0xFF) < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
}
-/*
- * Get a byte from the NVRAM
- */
+static __u8 pmu_read_pram(int offset)
+{
+ struct adb_request req;
+ if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF) < 0)
+ return 0;
+ while (!req.complete)
+ pmu_poll();
+ return req.reply[3];
+}
-static __u8 adb_read_pram(int offset)
+static void pmu_write_pram(int offset, __u8 data)
{
- volatile struct adb_request req;
+ struct adb_request req;
+ if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF, data) < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
+}
+#else
+#define pmu_read_time() 0
+#define pmu_write_time(n)
+#define pmu_read_pram NULL
+#define pmu_write_pram NULL
+#endif
- adb_request((struct adb_request *) &req, NULL,
- ADBREQ_RAW|ADBREQ_SYNC,
- 4, CUDA_PACKET, CUDA_GET_PRAM,
- (offset >> 8) & 0xFF, offset & 0xFF);
- return req.reply[3];
+#ifdef CONFIG_ADB_MACIISI
+extern int maciisi_request(struct adb_request *req,
+ void (*done)(struct adb_request *), int nbytes, ...);
+
+static long maciisi_read_time(void)
+{
+ struct adb_request req;
+ long time;
+
+ if (maciisi_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME))
+ return 0;
+
+ time = (req.reply[3] << 24) | (req.reply[4] << 16)
+ | (req.reply[5] << 8) | req.reply[6];
+ return time - RTC_OFFSET;
}
-/*
- * Write a byte to the NVRAM
- */
+static void maciisi_write_time(long data)
+{
+ struct adb_request req;
+ data += RTC_OFFSET;
+ maciisi_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+ (data >> 24) & 0xFF, (data >> 16) & 0xFF,
+ (data >> 8) & 0xFF, data & 0xFF);
+}
-static void adb_write_pram(int offset, __u8 data)
+static __u8 maciisi_read_pram(int offset)
{
- volatile struct adb_request req;
+ struct adb_request req;
+ if (maciisi_request(&req, NULL, 4, CUDA_PACKET, CUDA_GET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF))
+ return 0;
+ return req.reply[3];
+}
- adb_request((struct adb_request *) &req, NULL,
- ADBREQ_RAW|ADBREQ_SYNC,
- 5, CUDA_PACKET, CUDA_SET_PRAM,
- (offset >> 8) & 0xFF, offset & 0xFF,
- data);
+static void maciisi_write_pram(int offset, __u8 data)
+{
+ struct adb_request req;
+ maciisi_request(&req, NULL, 5, CUDA_PACKET, CUDA_SET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF, data);
}
-#endif /* CONFIG_ADB */
+#else
+#define maciisi_read_time() 0
+#define maciisi_write_time(n)
+#define maciisi_read_pram NULL
+#define maciisi_write_pram NULL
+#endif
/*
* VIA PRAM/RTC access routines
@@ -305,42 +396,55 @@ static void oss_shutdown(void)
static void cuda_restart(void)
{
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
+ struct adb_request req;
+ if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM) < 0)
+ return;
+ while (!req.complete)
+ cuda_poll();
}
static void cuda_shutdown(void)
{
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 2, CUDA_PACKET, CUDA_POWERDOWN);
+ struct adb_request req;
+ if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN) < 0)
+ return;
+ while (!req.complete)
+ cuda_poll();
}
#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_ADB_PMU68K
void pmu_restart(void)
{
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 3, PMU_PACKET, PMU_SET_INTR_MASK,
- PMU_INT_ADB|PMU_INT_TICK);
-
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 2, PMU_PACKET, PMU_RESET);
+ struct adb_request req;
+ if (pmu_request(&req, NULL,
+ 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
+ if (pmu_request(&req, NULL, 1, PMU_RESET) < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
}
void pmu_shutdown(void)
{
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 3, PMU_PACKET, PMU_SET_INTR_MASK,
- PMU_INT_ADB|PMU_INT_TICK);
-
- adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
- 6, PMU_PACKET, PMU_SHUTDOWN,
- 'M', 'A', 'T', 'T');
+ struct adb_request req;
+ if (pmu_request(&req, NULL,
+ 2, PMU_SET_INTR_MASK, PMU_INT_ADB|PMU_INT_TICK) < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
+ if (pmu_request(&req, NULL, 5, PMU_SHUTDOWN, 'M', 'A', 'T', 'T') < 0)
+ return;
+ while (!req.complete)
+ pmu_poll();
}
-#endif /* CONFIG_ADB_PMU */
+#endif
/*
*-------------------------------------------------------------------
@@ -351,21 +455,22 @@ void pmu_shutdown(void)
void mac_pram_read(int offset, __u8 *buffer, int len)
{
- __u8 (*func)(int) = NULL;
+ __u8 (*func)(int);
int i;
- if (macintosh_config->adb_type == MAC_ADB_IISI ||
- macintosh_config->adb_type == MAC_ADB_PB1 ||
- macintosh_config->adb_type == MAC_ADB_PB2 ||
- macintosh_config->adb_type == MAC_ADB_CUDA) {
-#ifdef CONFIG_ADB
- func = adb_read_pram;
-#else
- return;
-#endif
- } else {
+ switch(macintosh_config->adb_type) {
+ case MAC_ADB_IISI:
+ func = maciisi_read_pram; break;
+ case MAC_ADB_PB1:
+ case MAC_ADB_PB2:
+ func = pmu_read_pram; break;
+ case MAC_ADB_CUDA:
+ func = cuda_read_pram; break;
+ default:
func = via_read_pram;
}
+ if (!func)
+ return;
for (i = 0 ; i < len ; i++) {
buffer[i] = (*func)(offset++);
}
@@ -373,21 +478,22 @@ void mac_pram_read(int offset, __u8 *buffer, int len)
void mac_pram_write(int offset, __u8 *buffer, int len)
{
- void (*func)(int, __u8) = NULL;
+ void (*func)(int, __u8);
int i;
- if (macintosh_config->adb_type == MAC_ADB_IISI ||
- macintosh_config->adb_type == MAC_ADB_PB1 ||
- macintosh_config->adb_type == MAC_ADB_PB2 ||
- macintosh_config->adb_type == MAC_ADB_CUDA) {
-#ifdef CONFIG_ADB
- func = adb_write_pram;
-#else
- return;
-#endif
- } else {
+ switch(macintosh_config->adb_type) {
+ case MAC_ADB_IISI:
+ func = maciisi_write_pram; break;
+ case MAC_ADB_PB1:
+ case MAC_ADB_PB2:
+ func = pmu_write_pram; break;
+ case MAC_ADB_CUDA:
+ func = cuda_write_pram; break;
+ default:
func = via_write_pram;
}
+ if (!func)
+ return;
for (i = 0 ; i < len ; i++) {
(*func)(offset++, buffer[i]);
}
@@ -408,7 +514,7 @@ void mac_poweroff(void)
} else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
cuda_shutdown();
#endif
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_ADB_PMU68K
} else if (macintosh_config->adb_type == MAC_ADB_PB1
|| macintosh_config->adb_type == MAC_ADB_PB2) {
pmu_shutdown();
@@ -448,7 +554,7 @@ void mac_reset(void)
} else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
cuda_restart();
#endif
-#ifdef CONFIG_ADB_PMU
+#ifdef CONFIG_ADB_PMU68K
} else if (macintosh_config->adb_type == MAC_ADB_PB1
|| macintosh_config->adb_type == MAC_ADB_PB2) {
pmu_restart();
@@ -466,12 +572,13 @@ void mac_reset(void)
/* make a 1-to-1 mapping, using the transparent tran. reg. */
unsigned long virt = (unsigned long) mac_reset;
unsigned long phys = virt_to_phys(mac_reset);
+ unsigned long addr = (phys&0xFF000000)|0x8777;
unsigned long offset = phys-virt;
local_irq_disable(); /* lets not screw this up, ok? */
__asm__ __volatile__(".chip 68030\n\t"
"pmove %0,%/tt0\n\t"
".chip 68k"
- : : "m" ((phys&0xFF000000)|0x8777));
+ : : "m" (addr));
/* Now jump to physical address so we can disable MMU */
__asm__ __volatile__(
".chip 68030\n\t"
@@ -588,20 +695,22 @@ int mac_hwclk(int op, struct rtc_time *t)
unsigned long now;
if (!op) { /* read */
- if (macintosh_config->adb_type == MAC_ADB_II) {
+ switch (macintosh_config->adb_type) {
+ case MAC_ADB_II:
+ case MAC_ADB_IOP:
now = via_read_time();
- } else
-#ifdef CONFIG_ADB
- if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_PB1) ||
- (macintosh_config->adb_type == MAC_ADB_PB2) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- now = adb_read_time();
- } else
-#endif
- if (macintosh_config->adb_type == MAC_ADB_IOP) {
- now = via_read_time();
- } else {
+ break;
+ case MAC_ADB_IISI:
+ now = maciisi_read_time();
+ break;
+ case MAC_ADB_PB1:
+ case MAC_ADB_PB2:
+ now = pmu_read_time();
+ break;
+ case MAC_ADB_CUDA:
+ now = cuda_read_time();
+ break;
+ default:
now = 0;
}
@@ -619,15 +728,20 @@ int mac_hwclk(int op, struct rtc_time *t)
now = mktime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
- if (macintosh_config->adb_type == MAC_ADB_II) {
- via_write_time(now);
- } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_PB1) ||
- (macintosh_config->adb_type == MAC_ADB_PB2) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- adb_write_time(now);
- } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ switch (macintosh_config->adb_type) {
+ case MAC_ADB_II:
+ case MAC_ADB_IOP:
via_write_time(now);
+ break;
+ case MAC_ADB_CUDA:
+ cuda_write_time(now);
+ break;
+ case MAC_ADB_PB1:
+ case MAC_ADB_PB2:
+ pmu_write_time(now);
+ break;
+ case MAC_ADB_IISI:
+ maciisi_write_time(now);
}
#endif
}
diff --git a/arch/m68k/math-emu/multi_arith.h b/arch/m68k/math-emu/multi_arith.h
index 02251e5afd89..4ad0ca918e2e 100644
--- a/arch/m68k/math-emu/multi_arith.h
+++ b/arch/m68k/math-emu/multi_arith.h
@@ -366,7 +366,7 @@ static inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1,
#define fp_mul64(desth, destl, src1, src2) ({ \
asm ("mulu.l %2,%1:%0" : "=d" (destl), "=d" (desth) \
- : "g" (src1), "0" (src2)); \
+ : "dm" (src1), "0" (src2)); \
})
#define fp_div64(quot, rem, srch, srcl, div) \
asm ("divu.l %2,%1:%0" : "=d" (quot), "=d" (rem) \
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index fe2383e36b06..85ad19a0ac79 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -102,7 +102,7 @@ static inline void free_io_area(void *addr)
*/
/* Rewritten by Andreas Schwab to remove all races. */
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
{
struct vm_struct *area;
unsigned long virtaddr, retaddr;
@@ -121,7 +121,7 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
if (MACH_IS_AMIGA) {
if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
&& (cacheflag == IOMAP_NOCACHE_SER))
- return (void *)physaddr;
+ return (void __iomem *)physaddr;
}
#endif
@@ -218,21 +218,21 @@ void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
#endif
flush_tlb_all();
- return (void *)retaddr;
+ return (void __iomem *)retaddr;
}
/*
* Unmap a ioremap()ed region again
*/
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
{
#ifdef CONFIG_AMIGA
if ((!MACH_IS_AMIGA) ||
(((unsigned long)addr < 0x40000000) ||
((unsigned long)addr > 0x60000000)))
- free_io_area(addr);
+ free_io_area((__force void *)addr);
#else
- free_io_area(addr);
+ free_io_area((__force void *)addr);
#endif
}
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 7977eae50af2..a69fe3048edc 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -11,6 +11,7 @@
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/poll.h>
@@ -44,6 +45,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
unsigned long flags;
struct rtc_time wtime;
+ void __user *argp = (void __user *)arg;
switch (cmd) {
case RTC_RD_TIME: /* Read the time/date from RTC */
@@ -63,7 +65,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
rtc->ctrl = 0;
local_irq_restore(flags);
- return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
+ return copy_to_user(argp, &wtime, sizeof wtime) ?
-EFAULT : 0;
}
case RTC_SET_TIME: /* Set the RTC */
@@ -75,8 +77,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
- sizeof(struct rtc_time)))
+ if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time)))
return -EFAULT;
yrs = rtc_tm.tm_year;
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 02b626bae4ae..5e0f9b04d45e 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -36,8 +36,6 @@
#include <asm/machdep.h>
#include <asm/q40_master.h>
-extern void floppy_setup(char *str, int *ints);
-
extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
extern void q40_init_IRQ (void);
@@ -194,9 +192,6 @@ void __init config_q40(void)
mach_heartbeat = q40_heartbeat;
#endif
mach_halt = q40_halt;
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
/* disable a few things that SMSQ might have left enabled */
q40_disable_irqs();
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 77d05bcc3221..f1ca0dfbaa67 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -160,9 +160,6 @@ void __init config_sun3(void)
mach_hwclk = sun3_hwclk;
mach_halt = sun3_halt;
mach_get_hardware_list = sun3_get_hardware_list;
-#if defined(CONFIG_DUMMY_CONSOLE)
- conswitchp = &dummy_con;
-#endif
memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
// PROM seems to want the last couple of physical pages. --m
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 0ef547f5494d..0920f5d33606 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -71,10 +71,6 @@ void __init config_sun3x(void)
mach_get_model = sun3_get_model;
mach_get_hardware_list = sun3x_get_hardware_list;
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
sun3_intreg = (unsigned char *)SUN3X_INTREG;
/* only the serial console is known to work anyway... */
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index b96498120fe9..e2a6e8648960 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -17,10 +17,6 @@ config FPU
bool
default n
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index b6b5c14e55fd..6f880cbff1c8 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -99,7 +99,6 @@ cflags-$(CONFIG_M68360) := -m68332
AFLAGS += $(cflags-y)
CFLAGS += $(cflags-y)
-CFLAGS += -O1 -g
CFLAGS += -D__linux__
CFLAGS += -DUTS_SYSNAME=\"uClinux\"
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index e93a5ad56496..eddb8d3e130a 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -18,7 +18,6 @@
#include <asm/checksum.h>
#include <asm/current.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
/* platform dependent support */
@@ -26,7 +25,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
@@ -38,8 +36,6 @@ EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(ip_fast_csum);
-EXPORT_SYMBOL(mach_enable_irq);
-EXPORT_SYMBOL(mach_disable_irq);
EXPORT_SYMBOL(kernel_thread);
/* Networking helper routines. */
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 82e7ec888806..99bf43824795 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -198,10 +198,9 @@ int copy_thread(int nr, unsigned long clone_flags,
{
struct pt_regs * childregs;
struct switch_stack * childstack, *stack;
- unsigned long stack_offset, *retp;
+ unsigned long *retp;
- stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
- childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset);
+ childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
*childregs = *regs;
childregs->d0 = 0;
@@ -276,52 +275,6 @@ int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
}
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- struct switch_stack *sw;
-
- /* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk +
- (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
- sw = ((struct switch_stack *)regs) - 1;
- dump->regs.d1 = regs->d1;
- dump->regs.d2 = regs->d2;
- dump->regs.d3 = regs->d3;
- dump->regs.d4 = regs->d4;
- dump->regs.d5 = regs->d5;
- dump->regs.d6 = sw->d6;
- dump->regs.d7 = sw->d7;
- dump->regs.a0 = regs->a0;
- dump->regs.a1 = regs->a1;
- dump->regs.a2 = regs->a2;
- dump->regs.a3 = sw->a3;
- dump->regs.a4 = sw->a4;
- dump->regs.a5 = sw->a5;
- dump->regs.a6 = sw->a6;
- dump->regs.d0 = regs->d0;
- dump->regs.orig_d0 = regs->orig_d0;
- dump->regs.stkadj = regs->stkadj;
- dump->regs.sr = regs->sr;
- dump->regs.pc = regs->pc;
- dump->regs.fmtvec = (regs->format << 12) | regs->vector;
- /* dump floating point stuff */
- dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
-}
-
-/*
* Generic dumping code. Used for panic and debug.
*/
void dump(struct pt_regs *fp)
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 262ab8c72e5f..382ca5797b97 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -101,7 +101,7 @@ void ptrace_disable(struct task_struct *child)
put_reg(child, PT_SR, tmp);
}
-long arch_ptrace(truct task_struct *child, long request, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
int ret;
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index abb80fa2b940..93120b9bfff1 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -65,8 +65,6 @@ void (*mach_kbd_leds) (unsigned int) = NULL;
/* machine dependent irq functions */
void (*mach_init_IRQ) (void) = NULL;
irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-void (*mach_enable_irq) (unsigned int) = NULL;
-void (*mach_disable_irq) (unsigned int) = NULL;
int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL;
void (*mach_trap_init) (void);
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 43a2726c0d0a..e1b3aa39e270 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -285,6 +285,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
regs->d1 = context.sc_d1;
regs->a0 = context.sc_a0;
regs->a1 = context.sc_a1;
+ ((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
regs->pc = context.sc_pc;
regs->orig_d0 = -1; /* disable syscall checks */
@@ -498,6 +499,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
sc->sc_d1 = regs->d1;
sc->sc_a0 = regs->a0;
sc->sc_a1 = regs->a1;
+ sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
sc->sc_sr = regs->sr;
sc->sc_pc = regs->pc;
sc->sc_formatvec = regs->format << 12 | regs->vector;
@@ -597,6 +599,9 @@ static void setup_frame (int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */
wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler;
+ ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+ regs->format = 0x4; /*set format byte to make stack appear modulo 4
+ which it will be when doing the rte */
adjust_stack:
/* Prepare to skip over the extra stuff in the exception frame. */
@@ -664,6 +669,9 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */
wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler;
+ ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+ regs->format = 0x4; /*set format byte to make stack appear modulo 4
+ which it will be when doing the rte */
adjust_stack:
/* Prepare to skip over the extra stuff in the exception frame. */
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 0eab92ca4b97..ac9de2661c0b 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -129,7 +129,7 @@
*/
#if defined(CONFIG_M5208EVB)
#define RAM_START 0x40020000
-#define RAM_LENGTH 0x01e00000
+#define RAM_LENGTH 0x01fe0000
#endif
/*
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b50be449d3f5..c3e852e9953e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1471,7 +1471,7 @@ 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_R1 || CPU_MIPS64_R1) && 32BIT
+ 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"
@@ -1492,14 +1492,6 @@ config CPU_HAS_LLSC
for better performance, N if you don't know. You must say Y here
for multiprocessor machines.
-config CPU_HAS_LLDSCD
- bool "lld/scd Instructions available" if CPU_ADVANCED
- default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32_R1
- help
- Say Y here if your CPU has the lld and scd instructions, the 64-bit
- equivalents of ll and sc. Say Y here for better performance, N if
- you don't know. You must say Y here for multiprocessor machines.
-
config CPU_HAS_WB
bool "Writeback Buffer available" if CPU_ADVANCED
default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index e14ba5e01a36..2a9f2ef27b29 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -93,7 +93,6 @@ endif
#
cflags-y += -I $(TOPDIR)/include/asm/gcc
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
-cflags-y += $(call cc-option, -finline-limit=100000)
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
MODFLAGS += -mlong-calls
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 069f9d14983e..6fd353779813 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -130,7 +130,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_SIBYTE_DMA_PAGEOPS is not set
# CONFIG_MIPS_MT is not set
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 216f4023a81b..1d3ee18ea8bb 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -115,7 +115,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
index bea00a9e9269..a81e2de6947f 100644
--- a/arch/mips/configs/ddb5476_defconfig
+++ b/arch/mips/configs/ddb5476_defconfig
@@ -116,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 61f7171ca7ed..f1c27c2fb033 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -116,7 +116,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index 14e3815f11e6..aa24d85ea94d 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -118,7 +118,6 @@ CONFIG_PAGE_SIZE_4KB=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index 510819581d8a..eeed0e5ad260 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -121,7 +121,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 67979e3e606e..e56351abf87a 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -123,7 +123,6 @@ CONFIG_IP22_CPU_SCACHE=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 03af44d1d846..e17d3adff021 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -119,7 +119,6 @@ CONFIG_PAGE_SIZE_4KB=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index cba2a49cceb1..967e7acd8e1f 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -121,7 +121,6 @@ CONFIG_R5000_CPU_SCACHE=y
CONFIG_RM7000_CPU_SCACHE=y
# CONFIG_MIPS_MT is not set
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index e7ee1679af90..b5fa9639db6f 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -117,7 +117,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index 138c8a60a4dc..71386938d47f 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -114,7 +114,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 6238e0d6a430..14fb46886708 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -124,7 +124,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index a7ad99b12fe5..6c5df76d48d9 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -121,7 +121,6 @@ CONFIG_R5000_CPU_SCACHE=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index d1c44216f1c1..da0677a03c1d 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc2
-# Thu Nov 24 01:06:35 2005
+# Linux kernel version: 2.6.15-rc5
+# Fri Dec 23 02:21:03 2005
#
CONFIG_MIPS=y
@@ -87,8 +87,8 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
#
# CPU selection
#
-CONFIG_CPU_MIPS32_R1=y
-# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
@@ -112,7 +112,7 @@ CONFIG_SYS_HAS_CPU_MIPS64_R1=y
CONFIG_SYS_HAS_CPU_NEVADA=y
CONFIG_SYS_HAS_CPU_RM7000=y
CONFIG_CPU_MIPS32=y
-CONFIG_CPU_MIPSR1=y
+CONFIG_CPU_MIPSR2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 9081ea5a9dbd..7ad8718c1b69 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -122,7 +122,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index 570fc4d18166..e8d6bb3551a2 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -118,7 +118,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 6634ab24715c..f3787b68bdd1 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -123,7 +123,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index 4c396e1e2f0a..b6126ad4d06d 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -121,7 +121,6 @@ CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index d9a0d2fdba4f..4c650e708133 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -116,7 +116,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-# CONFIG_CPU_HAS_LLDSCD is not set
# CONFIG_CPU_HAS_WB is not set
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 1cc145023584..9aaa43024aec 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -124,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_MIPS_MT is not set
CONFIG_CPU_ADVANCED=y
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_WB=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 30975b305ae5..abf61095931e 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -124,7 +124,6 @@ CONFIG_PAGE_SIZE_4KB=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 63f1be18e9bf..52048c906079 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -133,7 +133,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# CONFIG_MIPS_MT is not set
CONFIG_SB1_PASS_1_WORKAROUNDS=y
CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_LLDSCD=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index d51d5d16297c..468c2e443d71 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -118,7 +118,6 @@ CONFIG_CPU_HAS_PREFETCH=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 2a1b844da43f..4f125e9e8e0b 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -123,7 +123,6 @@ CONFIG_IP22_CPU_SCACHE=y
# 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_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 72f2126ad19d..f36c4f20ee8a 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -50,7 +50,7 @@ obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.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_COMPAT) += linux32.o signal32.o
obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o
@@ -60,6 +60,5 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_64BIT) += cpu-bugs64.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
-CFLAGS_ioctl32.o += -Ifs/
EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 5e1b08b00a33..fac48ad27b34 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -435,6 +435,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
}
}
+static char unknown_isa[] __initdata = KERN_ERR \
+ "Unsupported ISA type, c0.config0: %d.";
+
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
{
unsigned int config0;
@@ -447,16 +450,37 @@ static inline unsigned int decode_config0(struct cpuinfo_mips *c)
isa = (config0 & MIPS_CONF_AT) >> 13;
switch (isa) {
case 0:
- c->isa_level = MIPS_CPU_ISA_M32;
+ switch ((config0 >> 10) & 7) {
+ case 0:
+ c->isa_level = MIPS_CPU_ISA_M32R1;
+ break;
+ case 1:
+ c->isa_level = MIPS_CPU_ISA_M32R2;
+ break;
+ default:
+ goto unknown;
+ }
break;
case 2:
- c->isa_level = MIPS_CPU_ISA_M64;
+ switch ((config0 >> 10) & 7) {
+ case 0:
+ c->isa_level = MIPS_CPU_ISA_M64R1;
+ break;
+ case 1:
+ c->isa_level = MIPS_CPU_ISA_M64R2;
+ break;
+ default:
+ goto unknown;
+ }
break;
default:
- panic("Unsupported ISA type, cp0.config0.at: %d.", isa);
+ goto unknown;
}
return config0 & MIPS_CONF_M;
+
+unknown:
+ panic(unknown_isa, config0);
}
static inline unsigned int decode_config1(struct cpuinfo_mips *c)
@@ -568,7 +592,6 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c)
break;
case PRID_IMP_34K:
c->cputype = CPU_34K;
- c->isa_level = MIPS_CPU_ISA_M32;
break;
}
}
@@ -647,7 +670,7 @@ static inline void cpu_probe_philips(struct cpuinfo_mips *c)
switch (c->processor_id & 0xff00) {
case PRID_IMP_PR4450:
c->cputype = CPU_PR4450;
- c->isa_level = MIPS_CPU_ISA_M32;
+ c->isa_level = MIPS_CPU_ISA_M32R1;
break;
default:
panic("Unknown Philips Core!"); /* REVISIT: die? */
@@ -690,8 +713,10 @@ __init void cpu_probe(void)
if (c->options & MIPS_CPU_FPU) {
c->fpu_id = cpu_get_fpu_id();
- if (c->isa_level == MIPS_CPU_ISA_M32 ||
- c->isa_level == MIPS_CPU_ISA_M64) {
+ if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
+ c->isa_level == MIPS_CPU_ISA_M32R2 ||
+ c->isa_level == MIPS_CPU_ISA_M64R1 ||
+ c->isa_level == MIPS_CPU_ISA_M64R2) {
if (c->fpu_id & MIPS_FPIR_3D)
c->ases |= MIPS_ASE_MIPS3D;
}
diff --git a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c
deleted file mode 100644
index 9ea1fc748864..000000000000
--- a/arch/mips/kernel/ioctl32.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Written by Ulf Carlsson (ulfc@engr.sgi.com)
- * Copyright (C) 2000, 2004 Ralf Baechle
- * Copyright (C) 2002, 2003 Maciej W. Rozycki
- */
-#define INCLUDES
-#include "compat_ioctl.c"
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/compat.h>
-#include <linux/ioctl32.h>
-#include <linux/syscalls.h>
-
-#ifdef CONFIG_SIBYTE_TBPROF
-#include <asm/sibyte/trace_prof.h>
-#endif
-
-#define A(__x) ((unsigned long)(__x))
-
-long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
- struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
- };
-
-IOCTL_TABLE_START
-
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-/*HANDLE_IOCTL(RTC_IRQP_READ, w_long)
-COMPATIBLE_IOCTL(RTC_IRQP_SET)
-HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
-COMPATIBLE_IOCTL(RTC_EPOCH_SET)
-*/
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 330cf84d21fe..60353f5acc48 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -420,7 +420,7 @@ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf,
goto out;
pos = merge_64(a4, a5);
ret = rw_verify_area(READ, file, &pos, count);
- if (ret)
+ if (ret < 0)
goto out;
ret = -EINVAL;
if (!file->f_op || !(read = file->f_op->read))
@@ -455,7 +455,7 @@ asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf,
goto out;
pos = merge_64(a4, a5);
ret = rw_verify_area(WRITE, file, &pos, count);
- if (ret)
+ if (ret < 0)
goto out;
ret = -EINVAL;
if (!file->f_op || !(write = file->f_op->write))
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index dd725779d91f..fa98f10d0132 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -140,12 +140,12 @@ void flush_thread(void)
int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
unsigned long unused, struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *ti = p->thread_info;
+ struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs;
long childksp;
p->set_child_tid = p->clear_child_tid = NULL;
- childksp = (unsigned long)ti + THREAD_SIZE - 32;
+ childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
preempt_disable();
@@ -205,7 +205,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
return 1;
}
-void dump_regs(elf_greg_t *gp, struct pt_regs *regs)
+void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
{
int i;
@@ -229,9 +229,7 @@ void dump_regs(elf_greg_t *gp, struct pt_regs *regs)
int dump_task_regs (struct task_struct *tsk, elf_gregset_t *regs)
{
- struct thread_info *ti = tsk->thread_info;
- long ksp = (unsigned long)ti + THREAD_SIZE - 32;
- dump_regs(&(*regs)[0], (struct pt_regs *) ksp - 1);
+ elf_dump_regs(*regs, task_pt_regs(tsk));
return 1;
}
@@ -409,7 +407,7 @@ unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = (unsigned long)p->thread_info;
+ stack_page = (unsigned long)task_stack_page(p);
if (!stack_page || !mips_frame_info_initialized)
return 0;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 510da5fda567..f838b36cc765 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -64,8 +64,7 @@ int ptrace_getregs (struct task_struct *child, __s64 __user *data)
if (!access_ok(VERIFY_WRITE, data, 38 * 8))
return -EIO;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
for (i = 0; i < 32; i++)
__put_user (regs->regs[i], data + i);
@@ -92,8 +91,7 @@ int ptrace_setregs (struct task_struct *child, __s64 __user *data)
if (!access_ok(VERIFY_READ, data, 38 * 8))
return -EIO;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
for (i = 0; i < 32; i++)
__get_user (regs->regs[i], data + i);
@@ -198,8 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
struct pt_regs *regs;
unsigned long tmp = 0;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
ret = 0; /* Default return value. */
switch (addr) {
@@ -280,12 +277,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO;
goto out;
}
- if (child->thread.dsp.used_dsp) {
- dregs = __get_dsp_regs(child);
- tmp = (unsigned long) (dregs[addr - DSP_BASE]);
- } else {
- tmp = -1; /* DSP registers yet used */
- }
+ dregs = __get_dsp_regs(child);
+ tmp = (unsigned long) (dregs[addr - DSP_BASE]);
break;
}
case DSP_CONTROL:
@@ -318,8 +311,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_POKEUSR: {
struct pt_regs *regs;
ret = 0;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
switch (addr) {
case 0 ... 31:
@@ -446,7 +438,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_GET_THREAD_AREA:
- ret = put_user(child->thread_info->tp_value,
+ ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);
break;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 9a9b04972132..0c82b25d8c6d 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -57,30 +57,16 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
(unsigned long) data);
#endif
lock_kernel();
- ret = -EPERM;
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- if ((ret = security_ptrace(current->parent, current)))
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
+ ret = ptrace_traceme();
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)
- goto out;
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ goto out;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
@@ -140,8 +126,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
struct pt_regs *regs;
unsigned int tmp;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
ret = 0; /* Default return value. */
switch (addr) {
@@ -215,12 +200,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
ret = -EIO;
goto out_tsk;
}
- if (child->thread.dsp.used_dsp) {
- dspreg_t *dregs = __get_dsp_regs(child);
- tmp = (unsigned long) (dregs[addr - DSP_BASE]);
- } else {
- tmp = -1; /* DSP registers yet used */
- }
+ dspreg_t *dregs = __get_dsp_regs(child);
+ tmp = (unsigned long) (dregs[addr - DSP_BASE]);
break;
case DSP_CONTROL:
if (!cpu_has_dsp) {
@@ -277,8 +258,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
case PTRACE_POKEUSR: {
struct pt_regs *regs;
ret = 0;
- regs = (struct pt_regs *) ((unsigned long) child->thread_info +
- THREAD_SIZE - 32 - sizeof(struct pt_regs));
+ regs = task_pt_regs(child);
switch (addr) {
case 0 ... 31:
@@ -395,7 +375,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
break;
case PTRACE_GET_THREAD_AREA:
- ret = put_user(child->thread_info->tp_value,
+ ret = put_user(task_thread_info(child)->tp_value,
(unsigned int __user *) (unsigned long) data);
break;
@@ -409,7 +389,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
break;
case PTRACE_GET_THREAD_AREA_3264:
- ret = put_user(child->thread_info->tp_value,
+ ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) (unsigned long) data);
break;
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index ae2ba67b7ef6..5e37df3111ad 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -12,6 +12,9 @@
#include <linux/reboot.h>
#include <asm/reboot.h>
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
/*
* Urgs ... Too many MIPS machines to handle this in a generic way.
* So handle all using function pointers to machine specific
@@ -33,6 +36,9 @@ void machine_halt(void)
void machine_power_off(void)
{
+ if (pm_power_off)
+ pm_power_off();
+
_machine_power_off();
}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index c856dbc52abb..98b185bbc947 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -588,7 +588,7 @@ static inline int setup_sigcontext32(struct pt_regs *regs,
err |= __put_user(regs->hi, &sc->sc_mdhi);
err |= __put_user(regs->lo, &sc->sc_mdlo);
if (cpu_has_dsp) {
- err |= __put_user(rddsp(DSP_MASK), &sc->sc_hi1);
+ err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
err |= __put_user(mfhi1(), &sc->sc_hi1);
err |= __put_user(mflo1(), &sc->sc_lo1);
err |= __put_user(mfhi2(), &sc->sc_hi2);
diff --git a/arch/mips/kernel/smp_mt.c b/arch/mips/kernel/smp_mt.c
index d429544ba4bc..794a1c3de2a4 100644
--- a/arch/mips/kernel/smp_mt.c
+++ b/arch/mips/kernel/smp_mt.c
@@ -287,6 +287,7 @@ void prom_prepare_cpus(unsigned int max_cpus)
*/
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
+ struct thread_info *gp = task_thread_info(idle);
dvpe();
set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -307,11 +308,9 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
write_tc_gpr_sp( __KSTK_TOS(idle));
/* global pointer */
- write_tc_gpr_gp((unsigned long)idle->thread_info);
+ write_tc_gpr_gp((unsigned long)gp);
- flush_icache_range((unsigned long)idle->thread_info,
- (unsigned long)idle->thread_info +
- sizeof(struct thread_info));
+ flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1));
/* finally out of configuration and into chaos */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index ee98eeb65e85..332358430ff5 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -9,6 +9,7 @@
*/
#include <linux/config.h>
#include <linux/a.out.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/mm.h>
@@ -262,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
void sys_set_thread_area(unsigned long addr)
{
- struct thread_info *ti = current->thread_info;
+ struct thread_info *ti = task_thread_info(current);
ti->tp_value = addr;
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 52924f8ce23c..0fc3730a294f 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/binfmts.h>
+#include <linux/capability.h>
#include <linux/highuid.h>
#include <linux/pagemap.h>
#include <linux/mm.h>
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 787ed541d442..7050b4ffffcd 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+int null_perf_irq(struct pt_regs *regs)
+{
+ return 0;
+}
+
+int (*perf_irq)(struct pt_regs *regs) = null_perf_irq;
+
+EXPORT_SYMBOL(null_perf_irq);
+EXPORT_SYMBOL(perf_irq);
+
asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
{
+ int r2 = cpu_has_mips_r2;
+
irq_enter();
kstat_this_cpu.irqs[irq]++;
+ /*
+ * Suckage alert:
+ * Before R2 of the architecture there was no way to see if a
+ * performance counter interrupt was pending, so we have to run the
+ * performance counter interrupt handler anyway.
+ */
+ if (!r2 || (read_c0_cause() & (1 << 26)))
+ if (perf_irq(regs))
+ goto out;
+
/* we keep interrupt disabled all the time */
- timer_interrupt(irq, NULL, regs);
+ if (!r2 || (read_c0_cause() & (1 << 30)))
+ timer_interrupt(irq, NULL, regs);
+out:
irq_exit();
}
@@ -628,9 +652,9 @@ void __init time_init(void)
mips_hpt_init = c0_hpt_init;
}
- if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) ||
- (current_cpu_data.isa_level == MIPS_CPU_ISA_I) ||
- (current_cpu_data.isa_level == MIPS_CPU_ISA_II))
+ if (cpu_has_mips32r1 || cpu_has_mips32r2 ||
+ (current_cpu_data.isa_level == MIPS_CPU_ISA_I) ||
+ (current_cpu_data.isa_level == MIPS_CPU_ISA_II))
/*
* We need to calibrate the counter but we don't have
* 64-bit division.
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 7058893d5ad2..59a187956de0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -519,7 +519,7 @@ static inline int simulate_llsc(struct pt_regs *regs)
*/
static inline int simulate_rdhwr(struct pt_regs *regs)
{
- struct thread_info *ti = current->thread_info;
+ struct thread_info *ti = task_thread_info(current);
unsigned int opcode;
if (unlikely(get_insn_opcode(regs, &opcode)))
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 06be405be399..ae83b755cf4a 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -99,9 +99,9 @@ struct vpe {
/* elfloader stuff */
void *load_addr;
- u32 len;
+ unsigned long len;
char *pbuffer;
- u32 plen;
+ unsigned long plen;
unsigned long __start;
@@ -253,11 +253,11 @@ void dump_mtregs(void)
}
/* Find some VPE program space */
-static void *alloc_progmem(u32 len)
+static void *alloc_progmem(unsigned long len)
{
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
/* this means you must tell linux to use less memory than you physically have */
- return (void *)((max_pfn * PAGE_SIZE) + KSEG0);
+ return pfn_to_kaddr(max_pfn);
#else
// simple grab some mem for now
return kmalloc(len, GFP_KERNEL);
@@ -1171,7 +1171,8 @@ static int __init vpe_module_init(void)
return -ENODEV;
}
- if ((major = register_chrdev(0, module_name, &vpe_fops) < 0)) {
+ major = register_chrdev(0, module_name, &vpe_fops);
+ if (major < 0) {
printk("VPE loader: unable to register character device\n");
return major;
}
diff --git a/arch/mips/lib/iomap.c b/arch/mips/lib/iomap.c
index b5d5fa833762..7e2ced715cfb 100644
--- a/arch/mips/lib/iomap.c
+++ b/arch/mips/lib/iomap.c
@@ -3,7 +3,7 @@
*
* This code is based on lib/iomap.c, by Linus Torvalds.
*
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
index 0065deaee24b..a1962eb460f8 100644
--- a/arch/mips/math-emu/dp_fint.c
+++ b/arch/mips/math-emu/dp_fint.c
@@ -33,8 +33,6 @@ ieee754dp ieee754dp_fint(int x)
CLEARCX;
- xc = ( 0 ? xc : xc );
-
if (x == 0)
return ieee754dp_zero(0);
if (x == 1 || x == -1)
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
index cb105b1dd860..eae90a866aa1 100644
--- a/arch/mips/math-emu/dp_flong.c
+++ b/arch/mips/math-emu/dp_flong.c
@@ -33,8 +33,6 @@ ieee754dp ieee754dp_flong(s64 x)
CLEARCX;
- xc = ( 0 ? xc : xc );
-
if (x == 0)
return ieee754dp_zero(0);
if (x == 1 || x == -1)
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
index 42d9ed4b9a94..7aac13afb09a 100644
--- a/arch/mips/math-emu/sp_fint.c
+++ b/arch/mips/math-emu/sp_fint.c
@@ -33,8 +33,6 @@ ieee754sp ieee754sp_fint(int x)
CLEARCX;
- xc = ( 0 ? xc : xc );
-
if (x == 0)
return ieee754sp_zero(0);
if (x == 1 || x == -1)
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
index 1e26795ccecb..3d6c1d11c178 100644
--- a/arch/mips/math-emu/sp_flong.c
+++ b/arch/mips/math-emu/sp_flong.c
@@ -33,8 +33,6 @@ ieee754sp ieee754sp_flong(s64 x)
CLEARCX;
- xc = ( 0 ? xc : xc );
-
if (x == 0)
return ieee754sp_zero(0);
if (x == 1 || x == -1)
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 72a12d931cba..93f3bf2c2b22 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -75,20 +75,31 @@ static void mips_timer_dispatch (struct pt_regs *regs)
do_IRQ (mips_cpu_timer_irq, regs);
}
+extern int null_perf_irq(struct pt_regs *regs);
+
+extern int (*perf_irq)(struct pt_regs *regs);
+
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef CONFIG_SMP
+ int r2 = cpu_has_mips_r2;
int cpu = smp_processor_id();
if (cpu == 0) {
/*
- * CPU 0 handles the global timer interrupt job and process accounting
- * resets count/compare registers to trigger next timer int.
+ * CPU 0 handles the global timer interrupt job and process
+ * accounting resets count/compare registers to trigger next
+ * timer int.
*/
- (void) timer_interrupt(irq, dev_id, regs);
+ if (!r2 || (read_c0_cause() & (1 << 26)))
+ if (perf_irq(regs))
+ goto out;
+
+ /* we keep interrupt disabled all the time */
+ if (!r2 || (read_c0_cause() & (1 << 30)))
+ timer_interrupt(irq, NULL, regs);
+
scroll_display_message();
- }
- else {
+ } else {
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
/*
@@ -103,16 +114,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
local_timer_interrupt (irq, dev_id, regs);
}
+out:
return IRQ_HANDLED;
-#else
- irqreturn_t r;
-
- r = timer_interrupt(irq, dev_id, regs);
-
- scroll_display_message();
-
- return r;
-#endif
}
/*
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 38223b44d962..422b55fab07a 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1183,8 +1183,8 @@ static void __init setup_scache(void)
if (!sc_present)
return;
- if ((c->isa_level == MIPS_CPU_ISA_M32 ||
- c->isa_level == MIPS_CPU_ISA_M64) &&
+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index dd2cc42f1b6d..53f9889b30ed 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -75,7 +75,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
int res;
switch (current_cpu_data.cputype) {
+ case CPU_5KC:
+ case CPU_20KC:
case CPU_24K:
+ case CPU_25KF:
lmodel = &op_model_mipsxx;
break;
diff --git a/arch/mips/oprofile/op_impl.h b/arch/mips/oprofile/op_impl.h
index f0121557047d..5cfce7d87a4d 100644
--- a/arch/mips/oprofile/op_impl.h
+++ b/arch/mips/oprofile/op_impl.h
@@ -12,8 +12,8 @@
struct pt_regs;
-extern void null_perf_irq(struct pt_regs *regs);
-extern void (*perf_irq)(struct pt_regs *regs);
+extern int null_perf_irq(struct pt_regs *regs);
+extern int (*perf_irq)(struct pt_regs *regs);
/* Per-counter configuration as set via oprofilefs. */
struct op_counter_config {
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index d36b64dfcb2f..1d1eee407faf 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args)
}
}
-static void mipsxx_perfcount_handler(struct pt_regs *regs)
+static int mipsxx_perfcount_handler(struct pt_regs *regs)
{
unsigned int counters = op_model_mipsxx.num_counters;
unsigned int control;
unsigned int counter;
+ int handled = 0;
switch (counters) {
#define HANDLE_COUNTER(n) \
@@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs)
(counter & M_COUNTER_OVERFLOW)) { \
oprofile_add_sample(regs, n); \
write_c0_perfcntr ## n(reg.counter[n]); \
+ handled = 1; \
}
HANDLE_COUNTER(3)
HANDLE_COUNTER(2)
HANDLE_COUNTER(1)
HANDLE_COUNTER(0)
}
+
+ return handled;
}
#define M_CONFIG1_PC (1 << 4)
@@ -176,17 +180,31 @@ static int __init mipsxx_init(void)
int counters;
counters = n_counters();
- if (counters == 0)
+ if (counters == 0) {
+ printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
return -ENODEV;
+ }
reset_counters(counters);
op_model_mipsxx.num_counters = counters;
switch (current_cpu_data.cputype) {
+ case CPU_20KC:
+ op_model_mipsxx.cpu_type = "mips/20K";
+ break;
+
case CPU_24K:
op_model_mipsxx.cpu_type = "mips/24K";
break;
+ case CPU_25KF:
+ op_model_mipsxx.cpu_type = "mips/25K";
+ break;
+
+ case CPU_5KC:
+ op_model_mipsxx.cpu_type = "mips/5K";
+ break;
+
default:
printk(KERN_ERR "Profiling unsupported for this CPU\n");
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index f2fc82c1c7c5..1e530751936c 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -1,7 +1,7 @@
/*
* fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups.
*
- * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 4975846da75a..b67ddaa47122 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -1,7 +1,7 @@
/*
* fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups.
*
- * Copyright (C) 2002,2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002,2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index bc55b06e1904..734f2b71e164 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -2,7 +2,7 @@
* fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
*
* Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
- * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index b5d42b12de10..c9e7cb4361a1 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -1,7 +1,7 @@
/*
* fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
*
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index 8436d7f1fdb2..fbe6bcb28199 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -1,7 +1,7 @@
/*
* fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c
index 430429b22ae1..900c6b32576c 100644
--- a/arch/mips/pci/ops-vr41xx.c
+++ b/arch/mips/pci/ops-vr41xx.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2003 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
index 91df4da7ddb9..9885fa403603 100644
--- a/arch/mips/pci/pci-vr41xx.c
+++ b/arch/mips/pci/pci-vr41xx.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2003 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify
diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h
index e087ec55641d..8a35e32b8376 100644
--- a/arch/mips/pci/pci-vr41xx.h
+++ b/arch/mips/pci/pci-vr41xx.h
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 0527170d6adb..f17f575f58f0 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -93,8 +93,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus)
*/
void prom_boot_secondary(int cpu, struct task_struct *idle)
{
- unsigned long gp = (unsigned long) idle->thread_info;
- unsigned long sp = gp + THREAD_SIZE - 32;
+ unsigned long gp = (unsigned long) task_thread_info(idle);
+ unsigned long sp = __KSTK_TOP(idle);
secondary_sp = sp;
secondary_gp = gp;
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index 07631a97670b..ce907eda221b 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/signal.h> /* for SIGBUS */
+#include <linux/sched.h> /* schow_regs(), force_sig() */
#include <asm/module.h>
#include <asm/sn/addrs.h>
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index 3a8291b7d26d..dbef3f6b5650 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -168,8 +168,8 @@ void __init prom_prepare_cpus(unsigned int max_cpus)
*/
void __init prom_boot_secondary(int cpu, struct task_struct *idle)
{
- unsigned long gp = (unsigned long) idle->thread_info;
- unsigned long sp = gp + THREAD_SIZE - 32;
+ unsigned long gp = (unsigned long)task_thread_info(idle);
+ unsigned long sp = __KSTK_TOS(idle);
LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu),
(launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
index e8485124b8fc..4477af3d8074 100644
--- a/arch/mips/sibyte/cfe/smp.c
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -60,7 +60,7 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
__KSTK_TOS(idle),
- (unsigned long)idle->thread_info, 0);
+ (unsigned long)task_thread_info(idle), 0);
if (retval != 0)
printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
}
diff --git a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
index d29201acc4f3..814900915c28 100644
--- a/arch/mips/vr41xx/casio-e55/setup.c
+++ b/arch/mips/vr41xx/casio-e55/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
*
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
index cdfa4273a1c5..de0c1b35f11c 100644
--- a/arch/mips/vr41xx/common/bcu.c
+++ b/arch/mips/vr41xx/common/bcu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
* - New creation, NEC VR4122 and VR4131 are supported.
* - Added support for NEC VR4111 and VR4121.
*
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* - Added support for NEC VR4133.
*/
#include <linux/kernel.h>
diff --git a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
index d758e432961b..657c5133c933 100644
--- a/arch/mips/vr41xx/common/cmu.c
+++ b/arch/mips/vr41xx/common/cmu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copuright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copuright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
* - New creation, NEC VR4122 and VR4131 are supported.
* - Added support for NEC VR4111 and VR4121.
*
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* - Added support for NEC VR4133.
*/
#include <linux/init.h>
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 0b73c5ab3c0c..07ae19cf0c29 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
* - New creation, NEC VR4122 and VR4131 are supported.
* - Added support for NEC VR4111 and VR4121.
*
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* - Coped with INTASSIGN of NEC VR4133.
*/
#include <linux/errno.h>
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index 578f6496ffd4..707bd0933eed 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -1,7 +1,7 @@
/*
* init.c, Common initialization routines for NEC VR4100 series.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
index 272c13aee4fd..2b6043f16d09 100644
--- a/arch/mips/vr41xx/common/int-handler.S
+++ b/arch/mips/vr41xx/common/int-handler.S
@@ -35,7 +35,7 @@
* MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
* - New creation, NEC VR4100 series are supported.
*
- * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* - Coped with INTASSIGN of NEC VR4133.
*/
#include <asm/asm.h>
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 43b214d39438..61aa264275ff 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -1,7 +1,7 @@
/*
* Interrupt handing routines for NEC VR4100 series.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index 53166f3598b2..02bf4f7d06ba 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -1,7 +1,7 @@
/*
* pmu.c, Power Management Unit routines for NEC VR4100 series.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/vr41xx/common/type.c b/arch/mips/vr41xx/common/type.c
index bcb5f71b5026..e0c1ac5e988e 100644
--- a/arch/mips/vr41xx/common/type.c
+++ b/arch/mips/vr41xx/common/type.c
@@ -1,7 +1,7 @@
/*
* type.c, System type for NEC VR4100 series.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
index 462a9af30eef..3e31f8193d21 100644
--- a/arch/mips/vr41xx/common/vrc4173.c
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2003 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify
@@ -561,7 +561,7 @@ static int __devinit vrc4173_init(void)
{
int err;
- err = pci_module_init(&vrc4173_driver);
+ err = pci_register_driver(&vrc4173_driver);
if (err < 0)
return err;
diff --git a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
index e4b34ad6ea61..50fe8af4c52c 100644
--- a/arch/mips/vr41xx/ibm-workpad/setup.c
+++ b/arch/mips/vr41xx/ibm-workpad/setup.c
@@ -1,7 +1,7 @@
/*
* setup.c, Setup for the IBM WorkPad z50.
*
- * Copyright (C) 2002-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 874a283edb95..e77a06e9621e 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -19,9 +19,6 @@ config MMU
config STACK_GROWSUP
def_bool y
-config UID16
- bool
-
config RWSEM_GENERIC_SPINLOCK
def_bool y
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index 955ef5084f3e..959ad3c4e372 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -602,6 +602,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
CONFIG_E1000=m
CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index 9d86b6b1ebd1..0b1c8c1fa8a3 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -626,6 +626,7 @@ CONFIG_ACENIC=m
# CONFIG_DL2K is not set
CONFIG_E1000=m
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index a64fd48fbfb5..29b4d61898f2 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/capability.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/namei.h>
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index 171f9c239f60..27827bc3717e 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -6,7 +6,6 @@ extra-y := init_task.o head.o vmlinux.lds
AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
-CFLAGS_ioctl32.o := -Ifs/
obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
@@ -19,6 +18,6 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
+obj-$(CONFIG_64BIT) += binfmt_elf32.o sys_parisc32.o signal32.o
# only supported for PCX-W/U in 64-bit mode at the moment
obj-$(CONFIG_64BIT) += perf.o perf_asm.o
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index a065349aee37..d8a4ca021aac 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -29,9 +29,9 @@
#include <asm/processor.h>
#include <asm/sections.h>
-int split_tlb;
-int dcache_stride;
-int icache_stride;
+int split_tlb __read_mostly;
+int dcache_stride __read_mostly;
+int icache_stride __read_mostly;
EXPORT_SYMBOL(dcache_stride);
@@ -45,29 +45,29 @@ DEFINE_SPINLOCK(pa_tlb_lock);
EXPORT_SYMBOL(pa_tlb_lock);
#endif
-struct pdc_cache_info cache_info;
+struct pdc_cache_info cache_info __read_mostly;
#ifndef CONFIG_PA20
-static struct pdc_btlb_info btlb_info;
+static struct pdc_btlb_info btlb_info __read_mostly;
#endif
#ifdef CONFIG_SMP
void
flush_data_cache(void)
{
- on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
+ on_each_cpu(flush_data_cache_local, NULL, 1, 1);
}
void
flush_instruction_cache(void)
{
- on_each_cpu((void (*)(void *))flush_instruction_cache_local, NULL, 1, 1);
+ on_each_cpu(flush_instruction_cache_local, NULL, 1, 1);
}
#endif
void
flush_cache_all_local(void)
{
- flush_instruction_cache_local();
- flush_data_cache_local();
+ flush_instruction_cache_local(NULL);
+ flush_data_cache_local(NULL);
}
EXPORT_SYMBOL(flush_cache_all_local);
@@ -332,7 +332,7 @@ void clear_user_page_asm(void *page, unsigned long vaddr)
}
#define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
-int parisc_cache_flush_threshold = FLUSH_THRESHOLD;
+int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD;
void parisc_setup_cache_timing(void)
{
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index d016d672ec2b..2d804e2d16d1 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -39,7 +39,7 @@
#include <asm/parisc-device.h>
/* See comments in include/asm-parisc/pci.h */
-struct hppa_dma_ops *hppa_dma_ops;
+struct hppa_dma_ops *hppa_dma_ops __read_mostly;
EXPORT_SYMBOL(hppa_dma_ops);
static struct device root = {
@@ -173,8 +173,6 @@ int register_parisc_driver(struct parisc_driver *driver)
WARN_ON(driver->drv.probe != NULL);
WARN_ON(driver->drv.remove != NULL);
- driver->drv.probe = parisc_driver_probe;
- driver->drv.remove = parisc_driver_remove;
driver->drv.name = driver->name;
return driver_register(&driver->drv);
@@ -515,8 +513,13 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
(iodc_data[5] << 8) | iodc_data[6];
dev->hpa.name = parisc_pathname(dev);
dev->hpa.start = hpa;
- if (hpa == 0xf4000000 || hpa == 0xf6000000 ||
- hpa == 0xf8000000 || hpa == 0xfa000000) {
+ /* This is awkward. The STI spec says that gfx devices may occupy
+ * 32MB or 64MB. Unfortunately, we don't know how to tell whether
+ * it's the former or the latter. Assumptions either way can hurt us.
+ */
+ if (hpa == 0xf4000000 || hpa == 0xf8000000) {
+ dev->hpa.end = hpa + 0x03ffffff;
+ } else if (hpa == 0xf6000000 || hpa == 0xfa000000) {
dev->hpa.end = hpa + 0x01ffffff;
} else {
dev->hpa.end = hpa + 0xfff;
@@ -570,6 +573,8 @@ struct bus_type parisc_bus_type = {
.name = "parisc",
.match = parisc_generic_match,
.dev_attrs = parisc_device_attrs,
+ .probe = parisc_driver_probe,
+ .remove = parisc_driver_remove,
};
/**
@@ -834,7 +839,7 @@ static void print_parisc_device(struct parisc_device *dev)
if (dev->num_addrs) {
int k;
- printk(", additional addresses: ");
+ printk(", additional addresses: ");
for (k = 0; k < dev->num_addrs; k++)
printk("0x%lx ", dev->addr[k]);
}
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 553f8fe03224..2dc06b8e1817 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -80,7 +80,7 @@ static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
/* Firmware needs to be initially set to narrow to determine the
* actual firmware width. */
-int parisc_narrow_firmware = 1;
+int parisc_narrow_firmware __read_mostly = 1;
#endif
/* On most currently-supported platforms, IODC I/O calls are 32-bit calls
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 2071b5bba15c..3058bffd8a2c 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -551,6 +551,7 @@ static struct hp_hardware hp_hardware_list[] __initdata = {
{HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"},
{HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"},
{HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"},
+ {HPHW_BRIDGE, 0x05D, 0x0000A, 0x00, "SummitHawk Dino PCI Bridge"},
{HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"},
{HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"},
{HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"},
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
index 8f563871e83c..4e847ba53180 100644
--- a/arch/parisc/kernel/inventory.c
+++ b/arch/parisc/kernel/inventory.c
@@ -38,7 +38,7 @@
*/
#undef DEBUG_PAT
-int pdc_type = PDC_TYPE_ILLEGAL;
+int pdc_type __read_mostly = PDC_TYPE_ILLEGAL;
void __init setup_pdc(void)
{
@@ -120,8 +120,8 @@ set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start,
* pdc info is bad in this case).
*/
- if ( ((start & (PAGE_SIZE - 1)) != 0)
- || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) {
+ if (unlikely( ((start & (PAGE_SIZE - 1)) != 0)
+ || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) )) {
panic("Memory range doesn't align with page size!\n");
}
diff --git a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
deleted file mode 100644
index 4eada1bb27f0..000000000000
--- a/arch/parisc/kernel/ioctl32.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#include <linux/syscalls.h>
-
-#define INCLUDES
-#include "compat_ioctl.c"
-
-#include <asm/perf.h>
-#include <asm/ioctls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
-
-#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END };
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-
-#define DECLARES
-#include "compat_ioctl.c"
-
-/* And these ioctls need translation */
-HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
-HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
-
-#if defined(CONFIG_GEN_RTC)
-COMPATIBLE_IOCTL(RTC_AIE_ON)
-COMPATIBLE_IOCTL(RTC_AIE_OFF)
-COMPATIBLE_IOCTL(RTC_UIE_ON)
-COMPATIBLE_IOCTL(RTC_UIE_OFF)
-COMPATIBLE_IOCTL(RTC_PIE_ON)
-COMPATIBLE_IOCTL(RTC_PIE_OFF)
-COMPATIBLE_IOCTL(RTC_WIE_ON)
-COMPATIBLE_IOCTL(RTC_WIE_OFF)
-COMPATIBLE_IOCTL(RTC_ALM_SET) /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_ALM_READ) /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_RD_TIME) /* struct rtc_time only has ints */
-COMPATIBLE_IOCTL(RTC_SET_TIME) /* struct rtc_time only has ints */
-HANDLE_IOCTL(RTC_IRQP_READ, w_long)
-COMPATIBLE_IOCTL(RTC_IRQP_SET)
-HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
-COMPATIBLE_IOCTL(RTC_EPOCH_SET)
-#endif
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index f94a02ef3d95..a6caf1073085 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -33,10 +33,10 @@
#include <asm/uaccess.h>
#include <asm/tlbflush.h> /* for purge_tlb_*() macros */
-static struct proc_dir_entry * proc_gsc_root = NULL;
+static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
-static unsigned long pcxl_used_bytes = 0;
-static unsigned long pcxl_used_pages = 0;
+static unsigned long pcxl_used_bytes __read_mostly = 0;
+static unsigned long pcxl_used_pages __read_mostly = 0;
extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */
static spinlock_t pcxl_res_lock;
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
index 52004ae28d20..2a01fe1bdc98 100644
--- a/arch/parisc/kernel/pdc_chassis.c
+++ b/arch/parisc/kernel/pdc_chassis.c
@@ -30,6 +30,7 @@
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
+#include <linux/cache.h>
#include <asm/pdc_chassis.h>
#include <asm/processor.h>
@@ -38,8 +39,8 @@
#ifdef CONFIG_PDC_CHASSIS
-static int pdc_chassis_old = 0;
-static unsigned int pdc_chassis_enabled = 1;
+static int pdc_chassis_old __read_mostly = 0;
+static unsigned int pdc_chassis_enabled __read_mostly = 1;
/**
@@ -132,7 +133,7 @@ void __init parisc_pdc_chassis_init(void)
{
#ifdef CONFIG_PDC_CHASSIS
int handle = 0;
- if (pdc_chassis_enabled) {
+ if (likely(pdc_chassis_enabled)) {
DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
/* Let see if we have something to handle... */
@@ -142,7 +143,7 @@ void __init parisc_pdc_chassis_init(void)
printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
handle = 1;
}
- else if (pdc_chassis_old) {
+ else if (unlikely(pdc_chassis_old)) {
printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
handle = 1;
}
@@ -178,7 +179,7 @@ int pdc_chassis_send_status(int message)
/* Maybe we should do that in an other way ? */
int retval = 0;
#ifdef CONFIG_PDC_CHASSIS
- if (pdc_chassis_enabled) {
+ if (likely(pdc_chassis_enabled)) {
DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
@@ -214,7 +215,7 @@ int pdc_chassis_send_status(int message)
}
} else retval = -1;
#else
- if (pdc_chassis_old) {
+ if (unlikely(pdc_chassis_old)) {
switch (message) {
case PDC_CHASSIS_DIRECT_BSTART:
case PDC_CHASSIS_DIRECT_BCOMPLETE:
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f6fec62b6a2f..11d406cd0b3e 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -42,6 +42,7 @@
* on every box.
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/miscdevice.h>
@@ -66,10 +67,10 @@ struct rdr_tbl_ent {
uint8_t write_control;
};
-static int perf_processor_interface = UNKNOWN_INTF;
-static int perf_enabled = 0;
+static int perf_processor_interface __read_mostly = UNKNOWN_INTF;
+static int perf_enabled __read_mostly = 0;
static spinlock_t perf_lock;
-struct parisc_device *cpu_device = NULL;
+struct parisc_device *cpu_device __read_mostly = NULL;
/* RDRs to write for PCX-W */
static int perf_rdrs_W[] =
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index fee4f1f09adc..5da41677e70b 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -54,7 +54,7 @@
#include <asm/uaccess.h>
#include <asm/unwind.h>
-static int hlt_counter;
+static int hlt_counter __read_mostly;
/*
* Power off function, if any
@@ -295,7 +295,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * pregs)
{
struct pt_regs * cregs = &(p->thread.regs);
- struct thread_info *ti = p->thread_info;
+ void *stack = task_stack_page(p);
/* We have to use void * instead of a function pointer, because
* function pointers aren't a pointer to the function on 64-bit.
@@ -322,7 +322,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
*/
if (usp == 1) {
/* kernel thread */
- cregs->ksp = (((unsigned long)(ti)) + THREAD_SZ_ALGN);
+ cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;
/* Must exit via ret_from_kernel_thread in order
* to call schedule_tail()
*/
@@ -344,7 +344,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
*/
/* Use same stack depth as parent */
- cregs->ksp = ((unsigned long)(ti))
+ cregs->ksp = (unsigned long)stack
+ (pregs->gr[21] & (THREAD_SIZE - 1));
cregs->gr[30] = usp;
if (p->personality == PER_HPUX) {
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 4f5bbcf1f5a4..6df9f62cecb5 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -44,10 +44,10 @@
#include <asm/irq.h> /* for struct irq_region */
#include <asm/parisc-device.h>
-struct system_cpuinfo_parisc boot_cpu_data;
+struct system_cpuinfo_parisc boot_cpu_data __read_mostly;
EXPORT_SYMBOL(boot_cpu_data);
-struct cpuinfo_parisc cpu_data[NR_CPUS];
+struct cpuinfo_parisc cpu_data[NR_CPUS] __read_mostly;
/*
** PARISC CPU driver - claim "device" and initialize CPU data structures.
@@ -378,12 +378,12 @@ show_cpuinfo (struct seq_file *m, void *v)
return 0;
}
-static struct parisc_device_id processor_tbl[] = {
+static struct parisc_device_id processor_tbl[] __read_mostly = {
{ HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
{ 0, }
};
-static struct parisc_driver cpu_driver = {
+static struct parisc_driver cpu_driver __read_mostly = {
.name = "CPU",
.id_table = processor_tbl,
.probe = processor_probe
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 73e9c34b0948..4a36ec3f6ac1 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -46,15 +46,15 @@
#include <asm/io.h>
#include <asm/setup.h>
-char command_line[COMMAND_LINE_SIZE];
+char command_line[COMMAND_LINE_SIZE] __read_mostly;
/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
-struct proc_dir_entry * proc_runway_root = NULL;
-struct proc_dir_entry * proc_gsc_root = NULL;
-struct proc_dir_entry * proc_mckinley_root = NULL;
+struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
+struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
+struct proc_dir_entry * proc_mckinley_root __read_mostly = NULL;
#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
-int parisc_bus_is_phys = 1; /* Assume no IOMMU is present */
+int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */
EXPORT_SYMBOL(parisc_bus_is_phys);
#endif
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index ce89da0f654d..25564b7ca6bb 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -39,7 +39,7 @@
#include <asm/atomic.h>
#include <asm/current.h>
#include <asm/delay.h>
-#include <asm/pgalloc.h> /* for flush_tlb_all() proto/macro */
+#include <asm/tlbflush.h>
#include <asm/io.h>
#include <asm/irq.h> /* for CPU_IRQ_REGION and friends */
@@ -58,9 +58,9 @@ DEFINE_SPINLOCK(smp_lock);
volatile struct task_struct *smp_init_current_idle_task;
-static volatile int cpu_now_booting = 0; /* track which CPU is booting */
+static volatile int cpu_now_booting __read_mostly = 0; /* track which CPU is booting */
-static int parisc_max_cpus = 1;
+static int parisc_max_cpus __read_mostly = 1;
/* online cpus are ones that we've managed to bring up completely
* possible cpus are all valid cpu
@@ -71,8 +71,8 @@ static int parisc_max_cpus = 1;
* empty in the beginning.
*/
-cpumask_t cpu_online_map = CPU_MASK_NONE; /* Bitmap of online CPUs */
-cpumask_t cpu_possible_map = CPU_MASK_ALL; /* Bitmap of Present CPUs */
+cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; /* Bitmap of online CPUs */
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; /* Bitmap of Present CPUs */
EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
@@ -406,12 +406,10 @@ EXPORT_SYMBOL(smp_call_function);
* as we want to ensure all TLB's flushed before proceeding.
*/
-extern void flush_tlb_all_local(void);
-
void
smp_flush_tlb_all(void)
{
- on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+ on_each_cpu(flush_tlb_all_local, NULL, 1, 1);
}
@@ -487,7 +485,7 @@ void __init smp_callin(void)
#endif
flush_cache_all_local(); /* start with known state */
- flush_tlb_all_local();
+ flush_tlb_all_local(NULL);
local_irq_enable(); /* Interrupts have been off until now */
@@ -519,7 +517,7 @@ int __init smp_boot_one_cpu(int cpuid)
if (IS_ERR(idle))
panic("SMP: fork failed for CPU:%d", cpuid);
- idle->thread_info->cpu = cpuid;
+ task_thread_info(idle)->cpu = cpuid;
/* Let _start know what logical CPU we're booting
** (offset into init_tasks[],cpu_data[])
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index cded25680787..594930bc4bcf 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -36,8 +36,8 @@
/* xtime and wall_jiffies keep wall-clock time */
extern unsigned long wall_jiffies;
-static long clocktick; /* timer cycles per tick */
-static long halftick;
+static long clocktick __read_mostly; /* timer cycles per tick */
+static long halftick __read_mostly;
#ifdef CONFIG_SMP
extern void smp_do_timer(struct pt_regs *regs);
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
index ac2a40681414..3ba040050e4c 100644
--- a/arch/parisc/kernel/topology.c
+++ b/arch/parisc/kernel/topology.c
@@ -20,8 +20,9 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/cpu.h>
+#include <linux/cache.h>
-static struct cpu cpu_devices[NR_CPUS];
+static struct cpu cpu_devices[NR_CPUS] __read_mostly;
static int __init topology_init(void)
{
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index eaae8a021f9f..de0a1b21cb40 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -122,7 +122,7 @@
#define ERR_NOTHANDLED -1
#define ERR_PAGEFAULT -2
-int unaligned_enabled = 1;
+int unaligned_enabled __read_mostly = 1;
void die_if_kernel (char *str, struct pt_regs *regs, long err);
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index db141108412e..cc1c1afc3187 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -35,7 +35,7 @@ static spinlock_t unwind_lock;
* we can call unwind_init as early in the bootup process as
* possible (before the slab allocator is initialized)
*/
-static struct unwind_table kernel_unwind_table;
+static struct unwind_table kernel_unwind_table __read_mostly;
static LIST_HEAD(unwind_tables);
static inline const struct unwind_table_entry *
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index e5fac3e08c7a..6d6436a6b624 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -68,7 +68,7 @@ SECTIONS
RODATA
/* writeable */
- . = ALIGN(4096); /* Make sure this is paged aligned so
+ . = ALIGN(4096); /* Make sure this is page aligned so
that we can properly leave these
as writable */
data_start = .;
@@ -105,6 +105,10 @@ SECTIONS
. = ALIGN(16);
.data.lock_aligned : { *(.data.lock_aligned) }
+ /* rarely changed data like cpu maps */
+ . = ALIGN(16);
+ .data.read_mostly : { *(.data.read_mostly) }
+
_edata = .; /* End of data section */
. = ALIGN(16384); /* init_task */
@@ -194,14 +198,7 @@ SECTIONS
#endif
}
- /* 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
.note 0 : { *(.note) }
}
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 29b998e430e6..720287d46e55 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -36,9 +36,9 @@ extern char _end; /* end of BSS, defined by linker */
extern char __init_begin, __init_end;
#ifdef CONFIG_DISCONTIGMEM
-struct node_map_data node_data[MAX_NUMNODES];
-bootmem_data_t bmem_data[MAX_NUMNODES];
-unsigned char pfnnid_map[PFNNID_MAP_MAX];
+struct node_map_data node_data[MAX_NUMNODES] __read_mostly;
+bootmem_data_t bmem_data[MAX_NUMNODES] __read_mostly;
+unsigned char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
#endif
static struct resource data_resource = {
@@ -58,14 +58,14 @@ static struct resource pdcdata_resource = {
.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
};
-static struct resource sysram_resources[MAX_PHYSMEM_RANGES];
+static struct resource sysram_resources[MAX_PHYSMEM_RANGES] __read_mostly;
/* The following array is initialized from the firmware specific
* information retrieved in kernel/inventory.c.
*/
-physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES];
-int npmem_ranges;
+physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES] __read_mostly;
+int npmem_ranges __read_mostly;
#ifdef __LP64__
#define MAX_MEM (~0UL)
@@ -73,7 +73,7 @@ int npmem_ranges;
#define MAX_MEM (3584U*1024U*1024U)
#endif /* !__LP64__ */
-static unsigned long mem_limit = MAX_MEM;
+static unsigned long mem_limit __read_mostly = MAX_MEM;
static void __init mem_limit_func(void)
{
@@ -300,6 +300,13 @@ static void __init setup_bootmem(void)
max_pfn = start_pfn + npages;
}
+ /* IOMMU is always used to access "high mem" on those boxes
+ * that can support enough mem that a PCI device couldn't
+ * directly DMA to any physical addresses.
+ * ISA DMA support will need to revisit this.
+ */
+ max_low_pfn = max_pfn;
+
if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) {
printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n");
BUG();
@@ -431,11 +438,11 @@ void free_initmem(void)
#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
& ~(VM_MAP_OFFSET-1)))
-void *vmalloc_start;
+void *vmalloc_start __read_mostly;
EXPORT_SYMBOL(vmalloc_start);
#ifdef CONFIG_PA11
-unsigned long pcxl_dma_start;
+unsigned long pcxl_dma_start __read_mostly;
#endif
void __init mem_init(void)
@@ -475,7 +482,7 @@ int do_check_pgt_cache(int low, int high)
return 0;
}
-unsigned long *empty_zero_page;
+unsigned long *empty_zero_page __read_mostly;
void show_mem(void)
{
@@ -998,7 +1005,7 @@ void flush_tlb_all(void)
void flush_tlb_all(void)
{
spin_lock(&sid_lock);
- flush_tlb_all_local();
+ flush_tlb_all_local(NULL);
recycle_sids();
spin_unlock(&sid_lock);
}
diff --git a/arch/parisc/mm/ioremap.c b/arch/parisc/mm/ioremap.c
index 5c7a1b3b9326..edd9a9559cba 100644
--- a/arch/parisc/mm/ioremap.c
+++ b/arch/parisc/mm/ioremap.c
@@ -1,12 +1,9 @@
/*
* arch/parisc/mm/ioremap.c
*
- * Re-map IO memory to kernel address space so that we can access it.
- * This is needed for high PCI addresses that aren't mapped in the
- * 640k-1MB IO memory area on PC's
- *
* (C) Copyright 1995 1996 Linus Torvalds
* (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ * (C) Copyright 2005 Kyle McMartin <kyle@parisc-linux.org>
*/
#include <linux/vmalloc.h>
@@ -14,81 +11,107 @@
#include <linux/module.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
-static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+static inline void
+remap_area_pte(pte_t *pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
{
- unsigned long end;
+ unsigned long end, pfn;
+ pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+ _PAGE_ACCESSED | flags);
address &= ~PMD_MASK;
+
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
- if (address >= end)
- BUG();
+
+ BUG_ON(address >= end);
+
+ pfn = phys_addr >> PAGE_SHIFT;
do {
- if (!pte_none(*pte)) {
- printk(KERN_ERR "remap_area_pte: page already exists\n");
- BUG();
- }
- set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
- _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
+ BUG_ON(!pte_none(*pte));
+
+ set_pte(pte, pfn_pte(pfn, pgprot));
+
address += PAGE_SIZE;
- phys_addr += PAGE_SIZE;
+ pfn++;
pte++;
} while (address && (address < end));
}
-static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long phys_addr, unsigned long flags)
+static inline int
+remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
{
unsigned long end;
address &= ~PGDIR_MASK;
+
end = address + size;
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
+
+ BUG_ON(address >= end);
+
phys_addr -= address;
- if (address >= end)
- BUG();
do {
- pte_t * pte = pte_alloc_kernel(pmd, address);
+ pte_t *pte = pte_alloc_kernel(pmd, address);
if (!pte)
return -ENOMEM;
- remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+
+ remap_area_pte(pte, address, end - address,
+ address + phys_addr, flags);
+
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
} while (address && (address < end));
+
return 0;
}
-#if (USE_HPPA_IOREMAP)
-static int remap_area_pages(unsigned long address, unsigned long phys_addr,
- unsigned long size, unsigned long flags)
+#if USE_HPPA_IOREMAP
+static int
+remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
{
- int error;
- pgd_t * dir;
+ pgd_t *dir;
+ int error = 0;
unsigned long end = address + size;
+ BUG_ON(address >= end);
+
phys_addr -= address;
- dir = pgd_offset(&init_mm, address);
+ dir = pgd_offset_k(address);
+
flush_cache_all();
- if (address >= end)
- BUG();
+
do {
+ pud_t *pud;
pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
+
error = -ENOMEM;
+ pud = pud_alloc(&init_mm, dir, address);
+ if (!pud)
+ break;
+
+ pmd = pmd_alloc(&init_mm, pud, address);
if (!pmd)
break;
+
if (remap_area_pmd(pmd, address, end - address,
- phys_addr + address, flags))
+ phys_addr + address, flags))
break;
+
error = 0;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
} while (address && (address < end));
+
flush_tlb_all();
+
return error;
}
#endif /* USE_HPPA_IOREMAP */
@@ -123,8 +146,7 @@ EXPORT_SYMBOL(__raw_bad_addr);
/*
* Remap an arbitrary physical address space into the kernel virtual
- * address space. Needed when the kernel wants to access high addresses
- * directly.
+ * address space.
*
* NOTE! We need to allow non-page-aligned mappings too: we will obviously
* have to convert them into an offset in a page-aligned mapping, but the
@@ -148,8 +170,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
#endif
#else
- void * addr;
- struct vm_struct * area;
+ void *addr;
+ struct vm_struct *area;
unsigned long offset, last_addr;
/* Don't allow wraparound or zero size */
@@ -167,9 +189,11 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
t_addr = __va(phys_addr);
t_end = t_addr + (size - 1);
- for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+ for (page = virt_to_page(t_addr);
+ page <= virt_to_page(t_end); page++) {
if(!PageReserved(page))
return NULL;
+ }
}
/*
@@ -185,11 +209,13 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
area = get_vm_area(size, VM_IOREMAP);
if (!area)
return NULL;
+
addr = area->addr;
if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
vfree(addr);
return NULL;
}
+
return (void __iomem *) (offset + (char *)addr);
#endif
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index db93dbc0e21a..df338c5cc910 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -26,9 +26,6 @@ config MMU
bool
default y
-config UID16
- bool
-
config GENERIC_HARDIRQS
bool
default y
@@ -50,7 +47,7 @@ config PPC
config EARLY_PRINTK
bool
- default y if PPC64
+ default y
config COMPAT
bool
@@ -74,15 +71,28 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config PPC_OF
+ def_bool y
+
+config PPC_UDBG_16550
+ bool
+ default n
+
+config GENERIC_TBSYNC
+ bool
+ default y if PPC32 && SMP
+ default n
+
menu "Processor support"
choice
prompt "Processor Type"
depends on PPC32
default 6xx
-config 6xx
+config CLASSIC32
bool "6xx/7xx/74xx"
select PPC_FPU
+ select 6xx
help
There are four families of PowerPC chips supported. The more common
types (601, 603, 604, 740, 750, 7400), the Motorola embedded
@@ -96,12 +106,20 @@ config 6xx
config PPC_52xx
bool "Freescale 52xx"
+ select 6xx
+ select PPC_FPU
config PPC_82xx
bool "Freescale 82xx"
+ select 6xx
+ select PPC_FPU
config PPC_83xx
bool "Freescale 83xx"
+ select 6xx
+ select FSL_SOC
+ select 83xx
+ select PPC_FPU
config 40x
bool "AMCC 40x"
@@ -137,6 +155,13 @@ config POWER4
depends on PPC64
def_bool y
+config 6xx
+ bool
+
+# this is temp to handle compat with arch=ppc
+config 83xx
+ bool
+
config PPC_FPU
bool
default y if PPC64
@@ -169,7 +194,7 @@ config PHYS_64BIT
config ALTIVEC
bool "AltiVec Support"
- depends on 6xx || POWER4
+ depends on CLASSIC32 || POWER4
---help---
This option enables kernel support for the Altivec extensions to the
PowerPC processor. The kernel currently supports saving and restoring
@@ -242,7 +267,7 @@ endmenu
source "init/Kconfig"
menu "Platform support"
- depends on PPC64 || 6xx
+ depends on PPC64 || CLASSIC32
choice
prompt "Machine type"
@@ -278,6 +303,7 @@ config PPC_PSERIES
select PPC_I8259
select PPC_RTAS
select RTAS_ERROR_LOGGING
+ select PPC_UDBG_16550
default y
config PPC_CHRP
@@ -287,6 +313,7 @@ config PPC_CHRP
select PPC_INDIRECT_PCI
select PPC_RTAS
select PPC_MPC106
+ select PPC_UDBG_16550
default y
config PPC_PMAC
@@ -300,6 +327,7 @@ config PPC_PMAC64
bool
depends on PPC_PMAC && POWER4
select U3_DART
+ select MPIC_BROKEN_U3
select GENERIC_TBSYNC
default y
@@ -308,6 +336,7 @@ config PPC_PREP
depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
select PPC_I8259
select PPC_INDIRECT_PCI
+ select PPC_UDBG_16550
default y
config PPC_MAPLE
@@ -316,6 +345,7 @@ config PPC_MAPLE
select U3_DART
select MPIC_BROKEN_U3
select GENERIC_TBSYNC
+ select PPC_UDBG_16550
default n
help
This option enables support for the Maple 970FX Evaluation Board.
@@ -326,11 +356,7 @@ config PPC_CELL
depends on PPC_MULTIPLATFORM && PPC64
select PPC_RTAS
select MMIO_NVRAM
-
-config PPC_OF
- bool
- depends on PPC_MULTIPLATFORM # for now
- default y
+ select PPC_UDBG_16550
config XICS
depends on PPC_PSERIES
@@ -384,13 +410,14 @@ config IBMVIO
bool
default y
-config PPC_MPC106
- bool
- default n
+config IBMEBUS
+ depends on PPC_PSERIES
+ bool "Support for GX bus based adapters"
+ help
+ Bus device driver for GX bus based adapters.
-config GENERIC_TBSYNC
+config PPC_MPC106
bool
- default y if CONFIG_PPC32 && CONFIG_SMP
default n
source "drivers/cpufreq/Kconfig"
@@ -473,8 +500,10 @@ endmenu
source arch/powerpc/platforms/embedded6xx/Kconfig
source arch/powerpc/platforms/4xx/Kconfig
+source arch/powerpc/platforms/83xx/Kconfig
source arch/powerpc/platforms/85xx/Kconfig
source arch/powerpc/platforms/8xx/Kconfig
+source arch/powerpc/platforms/cell/Kconfig
menu "Kernel options"
@@ -544,6 +573,16 @@ config KEXEC
support. As of this writing the exact hardware interface is
strongly in flux, so no good recommendation can be made.
+config CRASH_DUMP
+ bool "kernel crash dumps (EXPERIMENTAL)"
+ depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL
+ help
+ Build a kernel suitable for use as a kdump capture kernel.
+ The kernel will be linked at a different address than normal, and
+ so can only be used for Kdump.
+
+ Don't change this unless you know what you are doing.
+
config EMBEDDEDBOOT
bool
depends on 8xx || 8260
@@ -578,11 +617,12 @@ config ARCH_SELECT_MEMORY_MODEL
depends on PPC64
config ARCH_FLATMEM_ENABLE
- def_bool y
- depends on PPC64 && !NUMA
+ def_bool y
+ depends on (PPC64 && !NUMA) || PPC32
config ARCH_SPARSEMEM_ENABLE
def_bool y
+ depends on PPC64
config ARCH_SPARSEMEM_DEFAULT
def_bool y
@@ -694,7 +734,7 @@ config PPC_I8259
config PPC_INDIRECT_PCI
bool
depends on PCI
- default y if 40x || 44x || 85xx || 83xx
+ default y if 40x || 44x || 85xx
default n
config EISA
@@ -703,13 +743,16 @@ config EISA
config SBUS
bool
+config FSL_SOC
+ bool
+
# Yes MCA RS/6000s exist but Linux-PPC does not currently support any
config MCA
bool
config PCI
- bool "PCI support" if 40x || CPM2 || 83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
- default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx
+ bool "PCI support" if 40x || CPM2 || PPC_83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
+ default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !85xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
default PCI_QSPAN if !4xx && !CPM2 && 8xx
help
@@ -722,11 +765,6 @@ 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/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 30a30bf559ea..9254806f7032 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -115,4 +115,46 @@ config PPC_OCP
depends on IBM_OCP || XILINX_OCP
default y
+choice
+ prompt "Early debugging (dangerous)"
+ bool
+ optional
+ help
+ Enable early debugging. Careful, if you enable debugging for the
+ wrong type of machine your kernel _will not boot_.
+
+config PPC_EARLY_DEBUG_LPAR
+ bool "LPAR HV Console"
+ depends on PPC_PSERIES
+ help
+ Select this to enable early debugging for a machine with a HVC
+ console on vterm 0.
+
+config PPC_EARLY_DEBUG_G5
+ bool "Apple G5"
+ depends on PPC_PMAC64
+ help
+ Select this to enable early debugging for Apple G5 machines.
+
+config PPC_EARLY_DEBUG_RTAS
+ bool "RTAS Panel"
+ depends on PPC_RTAS
+ help
+ Select this to enable early debugging via the RTAS panel.
+
+config PPC_EARLY_DEBUG_MAPLE
+ bool "Maple real mode"
+ depends on PPC_MAPLE
+ help
+ Select this to enable early debugging for Maple.
+
+config PPC_EARLY_DEBUG_ISERIES
+ bool "iSeries HV Console"
+ depends on PPC_ISERIES
+ help
+ Select this to enable early debugging for legacy iSeries. You need
+ to hit "Ctrl-x Ctrl-x" to see the messages on the console.
+
+endchoice
+
endmenu
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index a13eb575f834..44dd82b791d1 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -76,8 +76,7 @@ LINUXINCLUDE += $(LINUXINCLUDE-y)
CHECKFLAGS += -m$(SZ) -D__powerpc__ -D__powerpc$(SZ)__
ifeq ($(CONFIG_PPC64),y)
-GCC_VERSION := $(call cc-version)
-GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi)
+GCC_BROKEN_VEC := $(shell if [ $(call cc-version) -lt 0400 ] ; then echo "y"; fi)
ifeq ($(CONFIG_POWER4_ONLY),y)
ifeq ($(CONFIG_ALTIVEC),y)
@@ -140,18 +139,15 @@ drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/
drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
-defaultimage-$(CONFIG_PPC32) := zImage
+# Default to zImage, override when needed
+defaultimage-y := zImage
defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
-defaultimage-$(CONFIG_PPC_PSERIES) := zImage
KBUILD_IMAGE := $(defaultimage-y)
all: $(KBUILD_IMAGE)
CPPFLAGS_vmlinux.lds := -Upowerpc
-# All the instructions talk about "make bzImage".
-bzImage: zImage
-
-BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
+BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage
.PHONY: $(BOOT_TARGETS)
@@ -189,10 +185,9 @@ TOUT := .tmp_gas_check
# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
# instructions.
# gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION := $(call cc-version)
checkbin:
- @if test "$(GCC_VERSION)" = "0304" ; then \
+ @if test "$(call cc-version)" = "0304" ; then \
if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
echo 'correctly with gcc-3.4 and your version of binutils.'; \
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
new file mode 100644
index 000000000000..45c9ad23526e
--- /dev/null
+++ b/arch/powerpc/boot/.gitignore
@@ -0,0 +1,20 @@
+addnote
+infblock.c
+infblock.h
+infcodes.c
+infcodes.h
+inffast.c
+inffast.h
+inflate.c
+inftrees.c
+inftrees.h
+infutil.c
+infutil.h
+kernel-vmlinux.strip.c
+kernel-vmlinux.strip.gz
+uImage
+zImage
+zImage.vmode
+zconf.h
+zlib.h
+zutil.h
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 9770f587af73..840ae595a617 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -25,8 +25,9 @@ HOSTCC := gcc
BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
$(shell $(CROSS32CC) -print-file-name=include) -fPIC
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
-BOOTLFLAGS := -T $(srctree)/$(src)/zImage.lds
OBJCOPYFLAGS := contents,alloc,load,readonly,data
+OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
+OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
@@ -35,7 +36,7 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
-src-boot := string.S prom.c main.c div64.S crt0.S
+src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
src-boot += $(zlib)
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
@@ -70,7 +71,7 @@ quiet_cmd_bootas = BOOTAS $@
cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
quiet_cmd_bootld = BOOTLD $@
- cmd_bootld = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(2)
+ cmd_bootld = $(CROSS32LD) -T $(srctree)/$(src)/$(3) -o $@ $(2)
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
$(call if_changed_dep,bootcc)
@@ -87,12 +88,14 @@ obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
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.vmode zImage.initrd.vmode zImage zImage.initrd \
- $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
- $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
- $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
- vmlinux.initrd
+hostprogs-y := addnote addRamDisk hack-coff
+
+targets += zImage.vmode zImage.initrd.vmode zImage zImage.initrd \
+ zImage.coff zImage.initrd.coff miboot.image miboot.initrd.image \
+ $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
+ $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
+ $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
+ vmlinux.initrd dummy.o
extra-y := initrd.o
quiet_cmd_ramdisk = RAMDISK $@
@@ -114,6 +117,14 @@ quiet_cmd_addsection = ADDSEC $@
quiet_cmd_addnote = ADDNOTE $@
cmd_addnote = $(obj)/addnote $@
+quiet_cmd_gen-miboot = GEN $@
+ cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_MIB_ARGS) \
+ --add-section=$1=$(word 2, $^) $< $@
+
+quiet_cmd_gencoff = COFF $@
+ cmd_gencoff = $(OBJCOPY) $(OBJCOPY_COFF_ARGS) $@ && \
+ $(obj)/hack-coff $@
+
$(call gz-sec, $(required)): $(obj)/kernel-%.gz: %
$(call if_changed,gzip)
@@ -127,23 +138,78 @@ $(call obj-sec, $(required) $(initrd)): $(obj)/kernel-%.o: $(obj)/kernel-%.c
$(call if_changed_dep,bootcc)
$(call cmd,addsection)
-$(obj)/zImage.vmode: obj-boot += $(call obj-sec, $(required))
+$(obj)/zImage.vmode $(obj)/zImage.coff: obj-boot += $(call obj-sec, $(required))
$(obj)/zImage.vmode: $(call obj-sec, $(required)) $(obj-boot) $(srctree)/$(src)/zImage.lds
- $(call cmd,bootld,$(obj-boot))
+ $(call cmd,bootld,$(obj-boot),zImage.lds)
-$(obj)/zImage.initrd.vmode: obj-boot += $(call obj-sec, $(required) $(initrd))
+$(obj)/zImage.initrd.vmode $(obj)/zImage.initrd.coff: obj-boot += $(call obj-sec, $(required) $(initrd))
$(obj)/zImage.initrd.vmode: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(srctree)/$(src)/zImage.lds
- $(call cmd,bootld,$(obj-boot))
+ $(call cmd,bootld,$(obj-boot),zImage.lds)
-$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote
+# For 32-bit powermacs, build the COFF and miboot images
+# as well as the ELF images.
+coffimage-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.coff
+coffrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/zImage.initrd.coff
+mibootimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.image
+mibrdimg-$(CONFIG_PPC_PMAC)-$(CONFIG_PPC32) := $(obj)/miboot.initrd.image
+
+$(obj)/zImage: $(obj)/zImage.vmode $(obj)/addnote $(coffimage-y-y) \
+ $(mibootimg-y-y)
@cp -f $< $@
$(call if_changed,addnote)
-$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote
+$(obj)/zImage.initrd: $(obj)/zImage.initrd.vmode $(obj)/addnote \
+ $(coffrdimg-y-y) $(mibrdimg-y-y)
@cp -f $< $@
$(call if_changed,addnote)
+$(obj)/zImage.coff: $(call obj-sec, $(required)) $(obj-boot) \
+ $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
+ $(call cmd,bootld,$(obj-boot),zImage.coff.lds)
+ $(call cmd,gencoff)
+
+$(obj)/zImage.initrd.coff: $(call obj-sec, $(required) $(initrd)) $(obj-boot) \
+ $(srctree)/$(src)/zImage.coff.lds $(obj)/hack-coff
+ $(call cmd,bootld,$(obj-boot),zImage.coff.lds)
+ $(call cmd,gencoff)
+
+$(obj)/miboot.image: $(obj)/dummy.o $(obj)/vmlinux.gz
+ $(call cmd,gen-miboot,image)
+
+$(obj)/miboot.initrd.image: $(obj)/miboot.image $(images)/ramdisk.image.gz
+ $(call cmd,gen-miboot,initrd)
+
+#-----------------------------------------------------------
+# build u-boot images
+#-----------------------------------------------------------
+quiet_cmd_mygzip = GZIP $@
+cmd_mygzip = gzip -f -9 < $< > $@.$$$$ && mv $@.$$$$ $@
+
+quiet_cmd_objbin = OBJCOPY $@
+ cmd_objbin = $(OBJCOPY) -O binary $< $@
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A ppc -O linux -T kernel \
+ -C gzip -a 00000000 -e 00000000 -n 'Linux-$(KERNELRELEASE)' \
+ -d $< $@
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+targets += uImage
+extra-y += vmlinux.bin vmlinux.gz
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objbin)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,mygzip)
+
+$(obj)/uImage: $(obj)/vmlinux.gz
+ $(Q)rm -f $@
+ $(call cmd,uimage)
+ @echo -n ' Image: $@ '
+ @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
+
install: $(CONFIGURE) $(BOOTIMAGE)
sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
-clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
+clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index d2f2ace56cd3..e0192c26037b 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -12,17 +12,23 @@
#include "ppc_asm.h"
.text
+ /* a procedure descriptor used when booting this as a COFF file */
+_zimage_start_opd:
+ .long _zimage_start, 0, 0, 0
+
.globl _zimage_start
_zimage_start:
+ /* Work out the offset between the address we were linked at
+ and the address where we're running. */
bl 1f
-
-1:
- mflr r0
+1: mflr r0
lis r9,1b@ha
addi r9,r9,1b@l
subf. r0,r9,r0
- beq 3f
+ beq 3f /* if running at same address as linked */
+ /* The .got2 section contains a list of addresses, so add
+ the address offset onto each entry. */
lis r9,__got2_start@ha
addi r9,r9,__got2_start@l
lis r8,__got2_end@ha
@@ -32,15 +38,14 @@ _zimage_start:
srwi. r8,r8,2
mtctr r8
add r9,r0,r9
-2:
- lwz r8,0(r9)
+2: lwz r8,0(r9)
add r8,r8,r0
stw r8,0(r9)
addi r9,r9,4
bdnz 2b
-3:
- lis r9,_start@h
+ /* Do a cache flush for our text, in case OF didn't */
+3: lis r9,_start@h
add r9,r0,r9
lis r8,_etext@ha
addi r8,r8,_etext@l
diff --git a/arch/powerpc/boot/dummy.c b/arch/powerpc/boot/dummy.c
new file mode 100644
index 000000000000..31dbf45bf99c
--- /dev/null
+++ b/arch/powerpc/boot/dummy.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c
new file mode 100644
index 000000000000..5e5a6573a1ef
--- /dev/null
+++ b/arch/powerpc/boot/hack-coff.c
@@ -0,0 +1,84 @@
+/*
+ * hack-coff.c - hack the header of an xcoff file to fill in
+ * a few fields needed by the Open Firmware xcoff loader on
+ * Power Macs but not initialized by objcopy.
+ *
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include "rs6000.h"
+
+#define AOUT_MAGIC 0x010b
+
+#define get_16be(x) ((((unsigned char *)(x))[0] << 8) \
+ + ((unsigned char *)(x))[1])
+#define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \
+ ((unsigned char *)(x))[1] = (v) & 0xff)
+#define get_32be(x) ((((unsigned char *)(x))[0] << 24) \
+ + (((unsigned char *)(x))[1] << 16) \
+ + (((unsigned char *)(x))[2] << 8) \
+ + ((unsigned char *)(x))[3])
+
+int
+main(int ac, char **av)
+{
+ int fd;
+ int i, nsect;
+ int aoutsz;
+ struct external_filehdr fhdr;
+ AOUTHDR aout;
+ struct external_scnhdr shdr;
+
+ if (ac != 2) {
+ fprintf(stderr, "Usage: hack-coff coff-file\n");
+ exit(1);
+ }
+ if ((fd = open(av[1], 2)) == -1) {
+ perror(av[2]);
+ exit(1);
+ }
+ if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr))
+ goto readerr;
+ i = get_16be(fhdr.f_magic);
+ if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) {
+ fprintf(stderr, "%s: not an xcoff file\n", av[1]);
+ exit(1);
+ }
+ aoutsz = get_16be(fhdr.f_opthdr);
+ if (read(fd, &aout, aoutsz) != aoutsz)
+ goto readerr;
+ nsect = get_16be(fhdr.f_nscns);
+ for (i = 0; i < nsect; ++i) {
+ if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr))
+ goto readerr;
+ if (strcmp(shdr.s_name, ".text") == 0) {
+ put_16be(aout.o_snentry, i+1);
+ put_16be(aout.o_sntext, i+1);
+ } else if (strcmp(shdr.s_name, ".data") == 0) {
+ put_16be(aout.o_sndata, i+1);
+ } else if (strcmp(shdr.s_name, ".bss") == 0) {
+ put_16be(aout.o_snbss, i+1);
+ }
+ }
+ put_16be(aout.magic, AOUT_MAGIC);
+ if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1
+ || write(fd, &aout, aoutsz) != aoutsz) {
+ fprintf(stderr, "%s: write error\n", av[1]);
+ exit(1);
+ }
+ close(fd);
+ exit(0);
+
+readerr:
+ fprintf(stderr, "%s: read error or file too short\n", av[1]);
+ exit(1);
+}
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 64ec93116fa6..55ec59867250 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -21,8 +21,8 @@ extern void flush_cache(void *, unsigned long);
/* Value picked to match that used by yaboot */
-#define PROG_START 0x01400000
-#define RAM_END (512<<20) // Fixme: use OF */
+#define PROG_START 0x01400000 /* only used on 64-bit systems */
+#define RAM_END (512<<20) /* Fixme: use OF */
#define ONE_MB 0x100000
extern char _start[];
@@ -160,6 +160,17 @@ static int is_elf64(void *hdr)
elfoffset = (unsigned long)elf64ph->p_offset;
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
+
+#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
+
return 1;
}
@@ -206,12 +217,18 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
exit();
if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
exit();
- stderr = stdout;
- if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
- exit();
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
+ /*
+ * 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);
+
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -228,25 +245,6 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
exit();
}
- /*
- * 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
-
/* We need to claim the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
index 4bea2f4dcb06..fa0057736f6b 100644
--- a/arch/powerpc/boot/prom.c
+++ b/arch/powerpc/boot/prom.c
@@ -13,487 +13,153 @@
#include "prom.h"
int (*prom)(void *);
+phandle chosen_handle;
+ihandle stdout;
-void *chosen_handle;
-
-void *stdin;
-void *stdout;
-void *stderr;
-
-
-int
-write(void *handle, void *ptr, int nb)
-{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- void *ihandle;
- void *addr;
- int len;
- int actual;
- } args;
-
- args.service = "write";
- args.nargs = 3;
- args.nret = 1;
- args.ihandle = handle;
- args.addr = ptr;
- args.len = nb;
- args.actual = -1;
- (*prom)(&args);
- return args.actual;
-}
-
-int
-read(void *handle, void *ptr, int nb)
+int call_prom(const char *service, int nargs, int nret, ...)
{
+ int i;
struct prom_args {
- char *service;
+ const char *service;
int nargs;
int nret;
- void *ihandle;
- void *addr;
- int len;
- int actual;
- } args;
-
- args.service = "read";
- args.nargs = 3;
- args.nret = 1;
- args.ihandle = handle;
- args.addr = ptr;
- args.len = nb;
- args.actual = -1;
- (*prom)(&args);
- return args.actual;
-}
-
-void
-exit()
-{
- struct prom_args {
- char *service;
- } args;
-
- for (;;) {
- args.service = "exit";
- (*prom)(&args);
- }
-}
-
-void
-pause(void)
-{
- struct prom_args {
- char *service;
+ unsigned int args[12];
} args;
+ va_list list;
- args.service = "enter";
- (*prom)(&args);
-}
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
-void *
-finddevice(const char *name)
-{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- const char *devspec;
- void *phandle;
- } args;
+ va_start(list, nret);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
- args.service = "finddevice";
- args.nargs = 1;
- args.nret = 1;
- args.devspec = name;
- args.phandle = (void *) -1;
- (*prom)(&args);
- return args.phandle;
-}
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
-void *
-claim(unsigned long virt, unsigned long size, unsigned long align)
-{
- struct prom_args {
- char *service;
- int nargs;
- int nret;
- unsigned int virt;
- unsigned int size;
- unsigned int align;
- void *ret;
- } args;
+ if (prom(&args) < 0)
+ return -1;
- args.service = "claim";
- args.nargs = 3;
- args.nret = 1;
- args.virt = virt;
- args.size = size;
- args.align = align;
- (*prom)(&args);
- return args.ret;
+ return (nret > 0)? args.args[nargs]: 0;
}
-int
-getprop(void *phandle, const char *name, void *buf, int buflen)
+int call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...)
{
+ int i;
struct prom_args {
- char *service;
+ const char *service;
int nargs;
int nret;
- void *phandle;
- const char *name;
- void *buf;
- int buflen;
- int size;
+ unsigned int args[12];
} args;
+ va_list list;
- args.service = "getprop";
- args.nargs = 4;
- args.nret = 1;
- args.phandle = phandle;
- args.name = name;
- args.buf = buf;
- args.buflen = buflen;
- args.size = -1;
- (*prom)(&args);
- return args.size;
-}
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
-int
-putc(int c, void *f)
-{
- char ch = c;
+ va_start(list, rets);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
- if (c == '\n')
- putc('\r', f);
- return write(f, &ch, 1) == 1? c: -1;
-}
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
-int
-putchar(int c)
-{
- return putc(c, stdout);
-}
+ if (prom(&args) < 0)
+ return -1;
-int
-fputs(char *str, void *f)
-{
- int n = strlen(str);
+ if (rets != (void *) 0)
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = args.args[nargs+i];
- return write(f, str, n) == n? 0: -1;
+ return (nret > 0)? args.args[nargs]: 0;
}
-size_t strnlen(const char * s, size_t count)
+int write(void *handle, void *ptr, int nb)
{
- const char *sc;
-
- for (sc = s; count-- && *sc != '\0'; ++sc)
- /* nothing */;
- return sc - s;
+ return call_prom("write", 3, 1, handle, ptr, nb);
}
-extern unsigned int __div64_32(unsigned long long *dividend,
- unsigned int divisor);
-
-/* The unnecessary pointer compare is there
- * to check for type safety (n must be 64bit)
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
*/
-# 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 need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
-static int skip_atoi(const char **s)
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
{
- int i, c;
-
- for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
- i = i*10 + c - '0';
- return i;
+ for (; *s2; ++s2)
+ if (*s1++ != *s2)
+ return 0;
+ return 1;
}
-#define ZEROPAD 1 /* pad with zero */
-#define SIGN 2 /* unsigned/signed long */
-#define PLUS 4 /* show plus */
-#define SPACE 8 /* space if plus */
-#define LEFT 16 /* left justified */
-#define SPECIAL 32 /* 0x */
-#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-
-static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+static int check_of_version(void)
{
- char c,sign,tmp[66];
- const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
- int i;
+ phandle oprom, chosen;
+ char version[64];
- if (type & LARGE)
- digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- if (type & LEFT)
- type &= ~ZEROPAD;
- if (base < 2 || base > 36)
+ oprom = finddevice("/openprom");
+ if (oprom == (phandle) -1)
return 0;
- c = (type & ZEROPAD) ? '0' : ' ';
- sign = 0;
- if (type & SIGN) {
- if ((signed long long)num < 0) {
- sign = '-';
- num = - (signed long long)num;
- size--;
- } else if (type & PLUS) {
- sign = '+';
- size--;
- } else if (type & SPACE) {
- sign = ' ';
- size--;
+ if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return 0;
+ version[sizeof(version)-1] = 0;
+ printf("OF version = '%s'\r\n", version);
+ if (!string_match(version, "Open Firmware, 1.")
+ && !string_match(version, "FirmWorks,3."))
+ return 0;
+ chosen = finddevice("/chosen");
+ if (chosen == (phandle) -1) {
+ chosen = finddevice("/chosen@0");
+ if (chosen == (phandle) -1) {
+ printf("no chosen\n");
+ return 0;
}
}
- if (type & SPECIAL) {
- if (base == 16)
- size -= 2;
- else if (base == 8)
- size--;
- }
- i = 0;
- if (num == 0)
- tmp[i++]='0';
- else while (num != 0) {
- tmp[i++] = digits[do_div(num, base)];
+ if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+ printf("no mmu\n");
+ return 0;
}
- if (i > precision)
- precision = i;
- size -= precision;
- if (!(type&(ZEROPAD+LEFT)))
- while(size-->0)
- *str++ = ' ';
- if (sign)
- *str++ = sign;
- if (type & SPECIAL) {
- if (base==8)
- *str++ = '0';
- else if (base==16) {
- *str++ = '0';
- *str++ = digits[33];
+ memory = (ihandle) call_prom("open", 1, 1, "/memory");
+ if (memory == (ihandle) -1) {
+ memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+ if (memory == (ihandle) -1) {
+ printf("no memory node\n");
+ return 0;
}
}
- if (!(type & LEFT))
- while (size-- > 0)
- *str++ = c;
- while (i < precision--)
- *str++ = '0';
- while (i-- > 0)
- *str++ = tmp[i];
- while (size-- > 0)
- *str++ = ' ';
- return str;
+ printf("old OF detected\r\n");
+ return 1;
}
-int vsprintf(char *buf, const char *fmt, va_list args)
+void *claim(unsigned long virt, unsigned long size, unsigned long align)
{
- int len;
- unsigned long long num;
- int i, base;
- char * str;
- const char *s;
-
- int flags; /* flags to number() */
-
- int field_width; /* width of output field */
- int precision; /* min. # of digits for integers; max
- number of chars for from string */
- int qualifier; /* 'h', 'l', or 'L' for integer fields */
- /* 'z' support added 23/7/1999 S.H. */
- /* 'z' changed to 'Z' --davidm 1/25/99 */
+ int ret;
+ unsigned int result;
+ if (need_map < 0)
+ need_map = check_of_version();
+ if (align || !need_map)
+ return (void *) call_prom("claim", 3, 1, virt, size, align);
- for (str=buf ; *fmt ; ++fmt) {
- if (*fmt != '%') {
- *str++ = *fmt;
- continue;
- }
-
- /* process flags */
- flags = 0;
- repeat:
- ++fmt; /* this also skips first '%' */
- switch (*fmt) {
- case '-': flags |= LEFT; goto repeat;
- case '+': flags |= PLUS; goto repeat;
- case ' ': flags |= SPACE; goto repeat;
- case '#': flags |= SPECIAL; goto repeat;
- case '0': flags |= ZEROPAD; goto repeat;
- }
-
- /* get field width */
- field_width = -1;
- if ('0' <= *fmt && *fmt <= '9')
- field_width = skip_atoi(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- field_width = va_arg(args, int);
- if (field_width < 0) {
- field_width = -field_width;
- flags |= LEFT;
- }
- }
-
- /* get the precision */
- precision = -1;
- if (*fmt == '.') {
- ++fmt;
- if ('0' <= *fmt && *fmt <= '9')
- precision = skip_atoi(&fmt);
- else if (*fmt == '*') {
- ++fmt;
- /* it's the next argument */
- precision = va_arg(args, int);
- }
- if (precision < 0)
- precision = 0;
- }
-
- /* get the conversion qualifier */
- qualifier = -1;
- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
- qualifier = *fmt;
- ++fmt;
- }
-
- /* default base */
- base = 10;
-
- switch (*fmt) {
- case 'c':
- if (!(flags & LEFT))
- while (--field_width > 0)
- *str++ = ' ';
- *str++ = (unsigned char) va_arg(args, int);
- while (--field_width > 0)
- *str++ = ' ';
- continue;
-
- case 's':
- s = va_arg(args, char *);
- if (!s)
- s = "<NULL>";
-
- len = strnlen(s, precision);
-
- if (!(flags & LEFT))
- while (len < field_width--)
- *str++ = ' ';
- for (i = 0; i < len; ++i)
- *str++ = *s++;
- while (len < field_width--)
- *str++ = ' ';
- continue;
-
- case 'p':
- if (field_width == -1) {
- field_width = 2*sizeof(void *);
- flags |= ZEROPAD;
- }
- str = number(str,
- (unsigned long) va_arg(args, void *), 16,
- field_width, precision, flags);
- continue;
-
-
- case 'n':
- if (qualifier == 'l') {
- long * ip = va_arg(args, long *);
- *ip = (str - buf);
- } else if (qualifier == 'Z') {
- size_t * ip = va_arg(args, size_t *);
- *ip = (str - buf);
- } else {
- int * ip = va_arg(args, int *);
- *ip = (str - buf);
- }
- continue;
-
- case '%':
- *str++ = '%';
- continue;
-
- /* integer number formats - set up the flags and "break" */
- case 'o':
- base = 8;
- break;
-
- case 'X':
- flags |= LARGE;
- case 'x':
- base = 16;
- break;
-
- case 'd':
- case 'i':
- flags |= SIGN;
- case 'u':
- break;
-
- default:
- *str++ = '%';
- if (*fmt)
- *str++ = *fmt;
- else
- --fmt;
- continue;
- }
- if (qualifier == 'l') {
- num = va_arg(args, unsigned long);
- if (flags & SIGN)
- num = (signed long) num;
- } else if (qualifier == 'Z') {
- num = va_arg(args, size_t);
- } else if (qualifier == 'h') {
- num = (unsigned short) va_arg(args, int);
- if (flags & SIGN)
- num = (signed short) num;
- } else {
- num = va_arg(args, unsigned int);
- if (flags & SIGN)
- num = (signed int) num;
- }
- str = number(str, num, base, field_width, precision, flags);
- }
- *str = '\0';
- return str-buf;
-}
-
-int sprintf(char * buf, const char *fmt, ...)
-{
- va_list args;
- int i;
-
- va_start(args, fmt);
- i=vsprintf(buf,fmt,args);
- va_end(args);
- return i;
-}
-
-static char sprint_buf[1024];
-
-int
-printf(const char *fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vsprintf(sprint_buf, fmt, args);
- va_end(args);
- write(stdout, sprint_buf, n);
- return n;
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
+ align, size, virt);
+ if (ret != 0 || result == -1)
+ return (void *) -1;
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+ align, size, virt);
+ /* 0x12 == coherent + read/write */
+ ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+ 0x12, size, virt, virt);
+ return (void *) virt;
}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 96ab5aec740c..3e2ddd4a5a81 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -1,18 +1,34 @@
#ifndef _PPC_BOOT_PROM_H_
#define _PPC_BOOT_PROM_H_
+typedef void *phandle;
+typedef void *ihandle;
+
extern int (*prom) (void *);
-extern void *chosen_handle;
+extern phandle chosen_handle;
+extern ihandle stdout;
-extern void *stdin;
-extern void *stdout;
-extern void *stderr;
+int call_prom(const char *service, int nargs, int nret, ...);
+int call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...);
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);
+extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
+
+static inline void exit(void)
+{
+ call_prom("exit", 0, 0);
+}
+
+static inline phandle finddevice(const char *name)
+{
+ return (phandle) call_prom("finddevice", 1, 1, name);
+}
+
+static inline int getprop(void *phandle, const char *name,
+ void *buf, int buflen)
+{
+ return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
+}
+
#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h
new file mode 100644
index 000000000000..433f45084e41
--- /dev/null
+++ b/arch/powerpc/boot/rs6000.h
@@ -0,0 +1,243 @@
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+ and John Gilmore of Cygnus Support. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+ /* IBM RS/6000 */
+#define U802WRMAGIC 0730 /* writeable text segments **chh** */
+#define U802ROMAGIC 0735 /* readonly sharable text segments */
+#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
+
+#define BADMAG(x) \
+ ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+ (x).f_magic != U802TOCMAGIC)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ 20
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
+ unsigned char dsize[4]; /* initialized data " " */
+ unsigned char bsize[4]; /* uninitialized data " " */
+ unsigned char entry[4]; /* entry pt. */
+ unsigned char text_start[4]; /* base of text used for this file */
+ unsigned char data_start[4]; /* base of data used for this file */
+ unsigned char o_toc[4]; /* address of TOC */
+ unsigned char o_snentry[2]; /* section number of entry point */
+ unsigned char o_sntext[2]; /* section number of .text section */
+ unsigned char o_sndata[2]; /* section number of .data section */
+ unsigned char o_sntoc[2]; /* section number of TOC */
+ unsigned char o_snloader[2]; /* section number of .loader section */
+ unsigned char o_snbss[2]; /* section number of .bss section */
+ unsigned char o_algntext[2]; /* .text alignment */
+ unsigned char o_algndata[2]; /* .data alignment */
+ unsigned char o_modtype[2]; /* module type (??) */
+ unsigned char o_cputype[2]; /* cpu type */
+ unsigned char o_maxstack[4]; /* max stack size (??) */
+ unsigned char o_maxdata[4]; /* max data size (??) */
+ unsigned char o_resv2[12]; /* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ 72
+#define SMALL_AOUTSZ (28)
+#define AOUTHDRSZ 72
+
+#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */
+#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */
+#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _PAD ".pad"
+#define _LOADER ".loader"
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ 40
+
+/* XCOFF uses a special .loader section with type STYP_LOADER. */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG. */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+ another section header with STYP_OVRFLO set. */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ struct {
+ unsigned char x_scnlen[4];
+ unsigned char x_parmhash[4];
+ unsigned char x_snhash[2];
+ unsigned char x_smtyp[1];
+ unsigned char x_smclas[1];
+ unsigned char x_stab[4];
+ unsigned char x_snstab[2];
+ } x_csect;
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+#define DBXMASK 0x80 /* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_size[1];
+ char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
new file mode 100644
index 000000000000..b5aa522f8b77
--- /dev/null
+++ b/arch/powerpc/boot/stdio.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "string.h"
+#include "stdio.h"
+#include "prom.h"
+
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+
+extern unsigned int __div64_32(unsigned long long *dividend,
+ unsigned int divisor);
+
+/* 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, c;
+
+ for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
+ i = i*10 + c - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if ((signed long long)num < 0) {
+ sign = '-';
+ num = - (signed long long)num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0) {
+ tmp[i++] = digits[do_div(num, base)];
+ }
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+ /* 'z' support added 23/7/1999 S.H. */
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if ('0' <= *fmt && *fmt <= '9')
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if ('0' <= *fmt && *fmt <= '9')
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else if (qualifier == 'Z') {
+ size_t * ip = va_arg(args, size_t *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l') {
+ num = va_arg(args, unsigned long);
+ if (flags & SIGN)
+ num = (signed long) num;
+ } else if (qualifier == 'Z') {
+ num = va_arg(args, size_t);
+ } else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (signed short) num;
+ } else {
+ num = va_arg(args, unsigned int);
+ if (flags & SIGN)
+ num = (signed int) num;
+ }
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+static char sprint_buf[1024];
+
+int
+printf(const char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vsprintf(sprint_buf, fmt, args);
+ va_end(args);
+ write(stdout, sprint_buf, n);
+ return n;
+}
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index 24bd3a8dee94..eb9e16c87aef 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -7,10 +7,4 @@ 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/powerpc/boot/string.S b/arch/powerpc/boot/string.S
index b1eeaed7db17..ac3d43b6a324 100644
--- a/arch/powerpc/boot/string.S
+++ b/arch/powerpc/boot/string.S
@@ -107,10 +107,12 @@ memcpy:
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
addi r6,r3,-4
addi r4,r4,-4
- beq 2f /* if less than 8 bytes to do */
+ beq 3f /* if less than 8 bytes to do */
andi. r0,r6,3 /* get dest word aligned */
mtctr r7
bne 5f
+ andi. r0,r4,3 /* check src word aligned too */
+ bne 3f
1: lwz r7,4(r4)
lwzu r8,8(r4)
stw r7,4(r6)
@@ -132,6 +134,11 @@ memcpy:
bdnz 4b
blr
5: subfic r0,r0,4
+ cmpw cr1,r0,r5
+ add r7,r0,r4
+ andi. r7,r7,3 /* will source be word-aligned too? */
+ ble cr1,3b
+ bne 3b /* do byte-by-byte if not */
mtctr r0
6: lbz r7,4(r4)
addi r4,r4,1
@@ -149,10 +156,12 @@ backwards_memcpy:
rlwinm. r7,r5,32-3,3,31 /* r7 = r5 >> 3 */
add r6,r3,r5
add r4,r4,r5
- beq 2f
+ beq 3f
andi. r0,r6,3
mtctr r7
bne 5f
+ andi. r0,r4,3
+ bne 3f
1: lwz r7,-4(r4)
lwzu r8,-8(r4)
stw r7,-4(r6)
@@ -171,7 +180,12 @@ backwards_memcpy:
stbu r0,-1(r6)
bdnz 4b
blr
-5: mtctr r0
+5: cmpw cr1,r0,r5
+ subf r7,r0,r4
+ andi. r7,r7,3
+ ble cr1,3b
+ bne 3b
+ mtctr r0
6: lbzu r7,-1(r4)
stbu r7,-1(r6)
bdnz 6b
diff --git a/arch/powerpc/boot/zImage.coff.lds b/arch/powerpc/boot/zImage.coff.lds
new file mode 100644
index 000000000000..6016251a1a2c
--- /dev/null
+++ b/arch/powerpc/boot/zImage.coff.lds
@@ -0,0 +1,46 @@
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_start)
+SECTIONS
+{
+ . = (5*1024*1024);
+ _start = .;
+ .text :
+ {
+ *(.text)
+ *(.fixup)
+ }
+ _etext = .;
+ . = ALIGN(4096);
+ .data :
+ {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ __got2_start = .;
+ *(.got2)
+ __got2_end = .;
+
+ _vmlinux_start = .;
+ *(.kernel:vmlinux.strip)
+ _vmlinux_end = .;
+
+ _initrd_start = .;
+ *(.kernel:initrd)
+ _initrd_end = .;
+ }
+
+ . = ALIGN(4096);
+ _edata = .;
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss)
+ *(.bss)
+ }
+ _end = . ;
+
+ /DISCARD/ :
+ {
+ *(.comment)
+ }
+}
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index b657f7e44762..063b84f2cbea 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -533,6 +533,7 @@ CONFIG_MII=y
# CONFIG_DL2K is not set
CONFIG_E1000=m
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 3c22ccb18519..d6fed3f56580 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -675,6 +675,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index 751a622fb7a7..c775027947f9 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -567,6 +567,7 @@ CONFIG_ACENIC=m
# CONFIG_DL2K is not set
CONFIG_E1000=m
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 07b6d3d23360..68194c03f6d1 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -454,6 +454,7 @@ CONFIG_AMD8111_ETH=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig
new file mode 100644
index 000000000000..3bff761965c2
--- /dev/null
+++ b/arch/powerpc/configs/mpc834x_sys_defconfig
@@ -0,0 +1,911 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-g461d4edf-dirty
+# Fri Jan 13 11:01:47 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+CONFIG_PPC_83xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+# CONFIG_E500 is not set
+CONFIG_6xx=y
+CONFIG_83xx=y
+CONFIG_PPC_FPU=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+
+#
+# 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_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_PPC_GEN550=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x=y
+
+#
+# Kernel options
+#
+# 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_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI 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
+
+#
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_GIANFAR=y
+# CONFIG_GFAR_NAPI 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT 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_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_83xx_WDT=y
+
+#
+# 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# 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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# SEC2.x Options
+#
+CONFIG_MPC8349E_SEC2x=y
+
+#
+# SEC2.x Test Options
+#
+CONFIG_MPC8349E_SEC2xTEST=y
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
new file mode 100644
index 000000000000..2ace57d1e333
--- /dev/null
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -0,0 +1,1744 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15
+# Sat Jan 14 16:26:08 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_GENERIC_TBSYNC is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+# CONFIG_E500 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+# CONFIG_PPC_CHRP is not set
+CONFIG_PPC_PMAC=y
+CONFIG_MPIC=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_PMAC=y
+CONFIG_PPC601_SYNC_FIX=y
+# CONFIG_TAU is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Kernel options
+#
+# 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_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_KEXEC is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+CONFIG_PM_DEBUG=y
+CONFIG_SOFTWARE_SUSPEND=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PPC_I8259 is not set
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=m
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI 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
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+CONFIG_IP_NF_MATCH_DCCP=m
+# CONFIG_IP_NF_MATCH_COMMENT is not set
+# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+# CONFIG_IP_NF_TARGET_NFQUEUE is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_NAT_PPTP=m
+# CONFIG_IP_NF_MANGLE is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+# CONFIG_IP_DCCP_UNLOAD_HACK 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
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_NSC_FIR is not set
+# CONFIG_WINBOND_FIR is not set
+# CONFIG_TOSHIBA_FIR is not set
+# CONFIG_SMC_IRCC_FIR is not set
+# CONFIG_ALI_FIR is not set
+# CONFIG_VLSI_FIR is not set
+# CONFIG_VIA_FIR is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+# CONFIG_BT_HCIUSB_SCO is not set
+# CONFIG_BT_HCIUART is not set
+CONFIG_BT_HCIBCM203X=m
+# CONFIG_BT_HCIBPA10X is not set
+CONFIG_BT_HCIBFUSB=m
+# CONFIG_BT_HCIDTL1 is not set
+# CONFIG_BT_HCIBT3C is not set
+# CONFIG_BT_HCIBLUECARD is not set
+# CONFIG_BT_HCIBTUART is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_UB=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X 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=y
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_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=y
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MESH_RESET_DELAY_MS=4000
+CONFIG_SCSI_MAC53C94=y
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID5=m
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+CONFIG_ADB=y
+CONFIG_ADB_CUDA=y
+CONFIG_ADB_PMU=y
+CONFIG_PMAC_APM_EMU=m
+CONFIG_PMAC_MEDIABAY=y
+CONFIG_PMAC_BACKLIGHT=y
+CONFIG_INPUT_ADBHID=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_WINDTUNNEL=m
+CONFIG_THERM_ADT746X=m
+# CONFIG_WINDFARM is not set
+# CONFIG_ANSLCD is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN 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_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
+CONFIG_BMAC=y
+# CONFIG_HAPPYMEAL is not set
+CONFIG_SUNGEM=y
+# CONFIG_CASSINI 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_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_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 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=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_AIRO is not set
+CONFIG_HERMES=m
+CONFIG_APPLE_AIRPORT=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_PCMCIA_HERMES is not set
+# CONFIG_PCMCIA_SPECTRUM is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=y
+CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+# CONFIG_SERIAL_8250_CS is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+CONFIG_SERIAL_PMACZILOG=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
+CONFIG_DRM=m
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_POWERMAC=y
+# CONFIG_I2C_MPC is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# 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=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_VALKYRIE=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_NVIDIA=y
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_RIVA is not set
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_FB_MATROX_G is not set
+# CONFIG_FB_MATROX_I2C is not set
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+# CONFIG_FB_ATY_GENERIC_LCD is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_3DFX_ACCEL is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+CONFIG_DMASOUND_PMAC=m
+CONFIG_DMASOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# ALSA PowerMac devices
+#
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_POWERMAC_AUTO_DRC=y
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_USX2Y is not set
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# 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_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+CONFIG_USB_APPLETOUCH=y
+
+#
+# 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=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS 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=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_LOCKD=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+
+#
+# Instrumentation Support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# CONFIG_BDI_SWITCH is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 509399eab6f5..6f6c6bed1aa5 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -724,6 +724,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
@@ -861,7 +862,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_ICOM=m
-CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -878,7 +879,7 @@ CONFIG_HVCS=m
#
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
+CONFIG_GEN_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index a50ce0fa9243..aa9893a1f6e8 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -671,6 +671,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 9ed551b6c172..c287980b7e65 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -4,7 +4,6 @@
ifeq ($(CONFIG_PPC64),y)
EXTRA_CFLAGS += -mno-minimal-toc
-CFLAGS_ioctl32.o += -Ifs/
endif
ifeq ($(CONFIG_PPC32),y)
CFLAGS_prom_init.o += -fPIC
@@ -12,16 +11,17 @@ CFLAGS_btext.o += -fPIC
endif
obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
- irq.o align.o signal_32.o pmc.o vdso.o
+ irq.o align.o signal_32.o pmc.o vdso.o \
+ init_task.o process.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
signal_64.o ptrace32.o systbl.o \
- paca.o ioctl32.o cpu_setup_power4.o \
- firmware.o sysfs.o udbg.o idle_64.o
+ paca.o cpu_setup_power4.o \
+ firmware.o sysfs.o idle_64.o
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_POWER4) += idle_power4.o
-obj-$(CONFIG_PPC_OF) += of_device.o
+obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64) := rtas_pci.o
@@ -30,12 +30,10 @@ obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_LPARCFG) += lparcfg.o
obj-$(CONFIG_IBMVIO) += vio.o
+obj-$(CONFIG_IBMEBUS) += ibmebus.o
obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
-obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
-obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
-udbgscc-$(CONFIG_PPC64) := udbg_scc.o
-obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
ifeq ($(CONFIG_PPC_MERGE),y)
@@ -47,26 +45,26 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds
-obj-y += process.o init_task.o time.o \
- prom.o traps.o setup-common.o
+obj-y += time.o prom.o traps.o setup-common.o udbg.o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o
obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
-obj-$(CONFIG_PPC_OF) += prom_init.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
obj-$(CONFIG_MODULES) += ppc_ksyms.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_6xx) += idle_6xx.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_KPROBES) += kprobes.o
-
+obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o
module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y)
pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \
pci_direct_iommu.o iomap.o
-obj-$(CONFIG_PCI) += $(pci64-y)
-
-kexec64-$(CONFIG_PPC64) += machine_kexec_64.o
-obj-$(CONFIG_KEXEC) += $(kexec64-y)
+pci32-$(CONFIG_PPC32) := pci_32.o
+obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
+kexec-$(CONFIG_PPC64) := machine_kexec_64.o crash.o
+kexec-$(CONFIG_PPC32) := machine_kexec_32.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o $(kexec-y)
ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 91538d2445bf..840aad43a98b 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -92,9 +92,9 @@ int main(void)
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
- DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
-#ifdef CONFIG_PPC32
+ DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_PPC32
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
#endif /* CONFIG_PPC32 */
@@ -131,13 +131,11 @@ int main(void)
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));
DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
- DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi));
DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp));
- DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca));
+ DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr));
DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id));
DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index bdfba92b2b38..6223d39177cb 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -31,15 +31,18 @@ static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb);
static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb);
-static int g_loc_X;
-static int g_loc_Y;
-static int g_max_loc_X;
-static int g_max_loc_Y;
+#define __force_data __attribute__((__section__(".data")))
-static int dispDeviceRowBytes;
-static int dispDeviceDepth;
-static int dispDeviceRect[4];
-static unsigned char *dispDeviceBase, *logicalDisplayBase;
+static int g_loc_X __force_data;
+static int g_loc_Y __force_data;
+static int g_max_loc_X __force_data;
+static int g_max_loc_Y __force_data;
+
+static int dispDeviceRowBytes __force_data;
+static int dispDeviceDepth __force_data;
+static int dispDeviceRect[4] __force_data;
+static unsigned char *dispDeviceBase __force_data;
+static unsigned char *logicalDisplayBase __force_data;
unsigned long disp_BAT[2] __initdata = {0, 0};
@@ -47,7 +50,7 @@ unsigned long disp_BAT[2] __initdata = {0, 0};
static unsigned char vga_font[cmapsz];
-int boot_text_mapped;
+int boot_text_mapped __force_data = 0;
int force_printk_to_btext = 0;
#ifdef CONFIG_PPC32
@@ -57,7 +60,7 @@ int force_printk_to_btext = 0;
*
* The display is mapped to virtual address 0xD0000000, rather
* than 1:1, because some some CHRP machines put the frame buffer
- * in the region starting at 0xC0000000 (KERNELBASE).
+ * in the region starting at 0xC0000000 (PAGE_OFFSET).
* This mapping is temporary and will disappear as soon as the
* setup done by MMU_Init() is applied.
*
@@ -66,10 +69,9 @@ int force_printk_to_btext = 0;
* is really badly aligned, but I didn't encounter this case
* yet.
*/
-void __init
-btext_prepare_BAT(void)
+void __init btext_prepare_BAT(void)
{
- unsigned long vaddr = KERNELBASE + 0x10000000;
+ unsigned long vaddr = PAGE_OFFSET + 0x10000000;
unsigned long addr;
unsigned long lowbits;
@@ -95,12 +97,13 @@ btext_prepare_BAT(void)
}
#endif
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
+
+/* This function can be used to enable the early boot text when doing
+ * OF booting or within bootx init. It must be followed by a btext_unmap()
+ * call before the logical address becomes unuseable
*/
-void __init
-btext_setup_display(int width, int height, int depth, int pitch,
- unsigned long address)
+void __init btext_setup_display(int width, int height, int depth, int pitch,
+ unsigned long address)
{
g_loc_X = 0;
g_loc_Y = 0;
@@ -116,6 +119,11 @@ btext_setup_display(int width, int height, int depth, int pitch,
boot_text_mapped = 1;
}
+void __init btext_unmap(void)
+{
+ boot_text_mapped = 0;
+}
+
/* Here's a small text engine to use during early boot
* or for debugging purposes
*
@@ -127,7 +135,7 @@ btext_setup_display(int width, int height, int depth, int pitch,
* changes.
*/
-void map_boot_text(void)
+static void map_boot_text(void)
{
unsigned long base, offset, size;
unsigned char *vbase;
@@ -175,8 +183,9 @@ int btext_initialize(struct device_node *np)
if (prop)
address = *prop;
- /* FIXME: Add support for PCI reg properties */
-
+ /* FIXME: Add support for PCI reg properties. Right now, only
+ * reliable on macs
+ */
if (address == 0)
return -EINVAL;
@@ -184,7 +193,6 @@ int btext_initialize(struct device_node *np)
g_loc_Y = 0;
g_max_loc_X = width / 8;
g_max_loc_Y = height / 16;
- logicalDisplayBase = (unsigned char *)address;
dispDeviceBase = (unsigned char *)address;
dispDeviceRowBytes = pitch;
dispDeviceDepth = depth;
@@ -197,14 +205,12 @@ int btext_initialize(struct device_node *np)
return 0;
}
-void __init init_boot_display(void)
+int __init btext_find_display(int allow_nonstdout)
{
char *name;
struct device_node *np = NULL;
int rc = -ENODEV;
- printk("trying to initialize btext ...\n");
-
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
if (name != NULL) {
np = of_find_node_by_path(name);
@@ -218,8 +224,8 @@ void __init init_boot_display(void)
}
if (np)
rc = btext_initialize(np);
- if (rc == 0)
- return;
+ if (rc == 0 || !allow_nonstdout)
+ return rc;
for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
if (get_property(np, "linux,opened", NULL)) {
@@ -228,8 +234,9 @@ void __init init_boot_display(void)
printk("result: %d\n", rc);
}
if (rc == 0)
- return;
+ break;
}
+ return rc;
}
/* Calc the base address of a given point (x,y) */
@@ -277,44 +284,83 @@ EXPORT_SYMBOL(btext_update_display);
void btext_clearscreen(void)
{
- unsigned long *base = (unsigned long *)calc_base(0, 0);
+ unsigned int *base = (unsigned int *)calc_base(0, 0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
- (dispDeviceDepth >> 3)) >> 3;
+ (dispDeviceDepth >> 3)) >> 2;
int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
{
- unsigned long *ptr = base;
+ unsigned int *ptr = base;
for(j=width; j; --j)
*(ptr++) = 0;
- base += (dispDeviceRowBytes >> 3);
+ base += (dispDeviceRowBytes >> 2);
}
}
+void btext_flushscreen(void)
+{
+ unsigned int *base = (unsigned int *)calc_base(0, 0);
+ unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
+ (dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i < (dispDeviceRect[3] - dispDeviceRect[1]); i++)
+ {
+ unsigned int *ptr = base;
+ for(j = width; j > 0; j -= 8) {
+ __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
+ ptr += 8;
+ }
+ base += (dispDeviceRowBytes >> 2);
+ }
+ __asm__ __volatile__ ("sync" ::: "memory");
+}
+
+void btext_flushline(void)
+{
+ unsigned int *base = (unsigned int *)calc_base(0, g_loc_Y << 4);
+ unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
+ (dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i < 16; i++)
+ {
+ unsigned int *ptr = base;
+ for(j = width; j > 0; j -= 8) {
+ __asm__ __volatile__ ("dcbst 0,%0" :: "r" (ptr));
+ ptr += 8;
+ }
+ base += (dispDeviceRowBytes >> 2);
+ }
+ __asm__ __volatile__ ("sync" ::: "memory");
+}
+
+
#ifndef NO_SCROLL
static void scrollscreen(void)
{
- unsigned long *src = (unsigned long *)calc_base(0,16);
- unsigned long *dst = (unsigned long *)calc_base(0,0);
+ unsigned int *src = (unsigned int *)calc_base(0,16);
+ unsigned int *dst = (unsigned int *)calc_base(0,0);
unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) *
- (dispDeviceDepth >> 3)) >> 3;
+ (dispDeviceDepth >> 3)) >> 2;
int i,j;
for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
{
- unsigned long *src_ptr = src;
- unsigned long *dst_ptr = dst;
+ unsigned int *src_ptr = src;
+ unsigned int *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = *(src_ptr++);
- src += (dispDeviceRowBytes >> 3);
- dst += (dispDeviceRowBytes >> 3);
+ src += (dispDeviceRowBytes >> 2);
+ dst += (dispDeviceRowBytes >> 2);
}
for (i=0; i<16; i++)
{
- unsigned long *dst_ptr = dst;
+ unsigned int *dst_ptr = dst;
for(j=width; j; --j)
*(dst_ptr++) = 0;
- dst += (dispDeviceRowBytes >> 3);
+ dst += (dispDeviceRowBytes >> 2);
}
}
#endif /* ndef NO_SCROLL */
@@ -377,6 +423,14 @@ void btext_drawstring(const char *c)
btext_drawchar(*c++);
}
+void btext_drawtext(const char *c, unsigned int len)
+{
+ if (!boot_text_mapped)
+ return;
+ while (len--)
+ btext_drawchar(*c++);
+}
+
void btext_drawhex(unsigned long v)
{
char *hex_table = "0123456789abcdef";
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index cca942fe6115..b61d86e7ceb6 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -130,7 +130,7 @@ _GLOBAL(__save_cpu_setup)
mfcr r7
/* Get storage ptr */
- LOADADDR(r5,cpu_state_storage)
+ LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
@@ -164,7 +164,7 @@ _GLOBAL(__restore_cpu_setup)
/* Get storage ptr (FIXME when using anton reloc as we
* are running with translation disabled here
*/
- LOADADDR(r5,cpu_state_storage)
+ LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
/* We only deal with 970 for now */
mfspr r0,SPRN_PVR
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 1d85cedbbb7b..10696456a4c6 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -55,7 +55,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
#define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4)
#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5)
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS)
-
+#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
+ PPC_FEATURE_BOOKE)
/* We only set the spe features if the kernel was compiled with
* spe support
@@ -78,10 +79,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power3",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "power3",
},
{ /* Power3+ */
.pvr_mask = 0xffff0000,
@@ -93,10 +93,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power3",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "power3",
},
{ /* Northstar */
.pvr_mask = 0xffff0000,
@@ -108,10 +107,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "rs64",
},
{ /* Pulsar */
.pvr_mask = 0xffff0000,
@@ -123,10 +121,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "rs64",
},
{ /* I-star */
.pvr_mask = 0xffff0000,
@@ -138,10 +135,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "rs64",
},
{ /* S-star */
.pvr_mask = 0xffff0000,
@@ -153,10 +149,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power3,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/rs64",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_RS64,
+ .platform = "rs64",
},
{ /* Power4 */
.pvr_mask = 0xffff0000,
@@ -168,10 +163,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power4,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power4",
- .oprofile_model = &op_model_rs64,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power4",
},
{ /* Power4+ */
.pvr_mask = 0xffff0000,
@@ -183,10 +177,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_power4,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power4",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power4",
},
{ /* PPC970 */
.pvr_mask = 0xffff0000,
@@ -199,10 +192,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "ppc970",
},
#endif /* CONFIG_PPC64 */
#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
@@ -221,10 +213,9 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 8,
.cpu_setup = __setup_cpu_ppc970,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "ppc970",
},
#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
#ifdef CONFIG_PPC64
@@ -238,10 +229,9 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.cpu_setup = __setup_cpu_ppc970,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/970",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "ppc970",
},
{ /* Power5 GR */
.pvr_mask = 0xffff0000,
@@ -253,27 +243,25 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
-#ifdef CONFIG_OPROFILE
.oprofile_cpu_type = "ppc64/power5",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power5",
},
{ /* Power5 GS */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003b0000,
- .cpu_name = "POWER5 (gs)",
+ .cpu_name = "POWER5+ (gs)",
.cpu_features = CPU_FTRS_POWER5,
.cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128,
.dcache_bsize = 128,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
-#ifdef CONFIG_OPROFILE
- .oprofile_cpu_type = "ppc64/power5",
- .oprofile_model = &op_model_power4,
-#endif
+ .oprofile_cpu_type = "ppc64/power5+",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power5+",
},
- { /* BE DD1.x */
+ { /* Cell Broadband Engine */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00700000,
.cpu_name = "Cell Broadband Engine",
@@ -283,6 +271,7 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 128,
.dcache_bsize = 128,
.cpu_setup = __setup_cpu_be,
+ .platform = "ppc-cell-be",
},
{ /* default match */
.pvr_mask = 0x00000000,
@@ -294,6 +283,7 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 128,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_power4,
+ .platform = "power4",
}
#endif /* CONFIG_PPC64 */
#ifdef CONFIG_PPC32
@@ -307,6 +297,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc601",
},
{ /* 603 */
.pvr_mask = 0xffff0000,
@@ -316,7 +307,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* 603e */
.pvr_mask = 0xffff0000,
@@ -326,7 +318,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* 603ev */
.pvr_mask = 0xffff0000,
@@ -336,7 +329,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* 604 */
.pvr_mask = 0xffff0000,
@@ -347,7 +341,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 2,
- .cpu_setup = __setup_cpu_604
+ .cpu_setup = __setup_cpu_604,
+ .platform = "ppc604",
},
{ /* 604e */
.pvr_mask = 0xfffff000,
@@ -358,7 +353,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_604
+ .cpu_setup = __setup_cpu_604,
+ .platform = "ppc604",
},
{ /* 604r */
.pvr_mask = 0xffff0000,
@@ -369,7 +365,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_604
+ .cpu_setup = __setup_cpu_604,
+ .platform = "ppc604",
},
{ /* 604ev */
.pvr_mask = 0xffff0000,
@@ -380,7 +377,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_604
+ .cpu_setup = __setup_cpu_604,
+ .platform = "ppc604",
},
{ /* 740/750 (0x4202, don't support TAU ?) */
.pvr_mask = 0xffffffff,
@@ -391,7 +389,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750,
+ .platform = "ppc750",
},
{ /* 750CX (80100 and 8010x?) */
.pvr_mask = 0xfffffff0,
@@ -402,7 +401,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750cx
+ .cpu_setup = __setup_cpu_750cx,
+ .platform = "ppc750",
},
{ /* 750CX (82201 and 82202) */
.pvr_mask = 0xfffffff0,
@@ -413,7 +413,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750cx
+ .cpu_setup = __setup_cpu_750cx,
+ .platform = "ppc750",
},
{ /* 750CXe (82214) */
.pvr_mask = 0xfffffff0,
@@ -424,7 +425,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750cx
+ .cpu_setup = __setup_cpu_750cx,
+ .platform = "ppc750",
},
{ /* 750CXe "Gekko" (83214) */
.pvr_mask = 0xffffffff,
@@ -435,7 +437,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750cx
+ .cpu_setup = __setup_cpu_750cx,
+ .platform = "ppc750",
},
{ /* 745/755 */
.pvr_mask = 0xfffff000,
@@ -446,7 +449,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750,
+ .platform = "ppc750",
},
{ /* 750FX rev 1.x */
.pvr_mask = 0xffffff00,
@@ -457,7 +461,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750,
+ .platform = "ppc750",
},
{ /* 750FX rev 2.0 must disable HID0[DPM] */
.pvr_mask = 0xffffffff,
@@ -468,7 +473,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750,
+ .platform = "ppc750",
},
{ /* 750FX (All revs except 2.0) */
.pvr_mask = 0xffff0000,
@@ -479,7 +485,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750fx
+ .cpu_setup = __setup_cpu_750fx,
+ .platform = "ppc750",
},
{ /* 750GX */
.pvr_mask = 0xffff0000,
@@ -490,7 +497,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750fx
+ .cpu_setup = __setup_cpu_750fx,
+ .platform = "ppc750",
},
{ /* 740/750 (L2CR bit need fixup for 740) */
.pvr_mask = 0xffff0000,
@@ -501,7 +509,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_750
+ .cpu_setup = __setup_cpu_750,
+ .platform = "ppc750",
},
{ /* 7400 rev 1.1 ? (no TAU) */
.pvr_mask = 0xffffffff,
@@ -512,7 +521,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_7400
+ .cpu_setup = __setup_cpu_7400,
+ .platform = "ppc7400",
},
{ /* 7400 */
.pvr_mask = 0xffff0000,
@@ -523,7 +533,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_7400
+ .cpu_setup = __setup_cpu_7400,
+ .platform = "ppc7400",
},
{ /* 7410 */
.pvr_mask = 0xffff0000,
@@ -534,7 +545,8 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
- .cpu_setup = __setup_cpu_7410
+ .cpu_setup = __setup_cpu_7410,
+ .platform = "ppc7400",
},
{ /* 7450 2.0 - no doze/nap */
.pvr_mask = 0xffffffff,
@@ -545,7 +557,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7450 2.1 */
.pvr_mask = 0xffffffff,
@@ -556,7 +571,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7450 2.3 and newer */
.pvr_mask = 0xffff0000,
@@ -567,7 +585,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7455 rev 1.x */
.pvr_mask = 0xffffff00,
@@ -578,7 +599,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7455 rev 2.0 */
.pvr_mask = 0xffffffff,
@@ -589,7 +613,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7455 others */
.pvr_mask = 0xffff0000,
@@ -600,7 +627,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.0 */
.pvr_mask = 0xffffffff,
@@ -611,7 +641,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.1 */
.pvr_mask = 0xffffffff,
@@ -622,7 +655,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.2 and later */
.pvr_mask = 0xffff0000,
@@ -633,7 +669,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7447A */
.pvr_mask = 0xffff0000,
@@ -644,7 +683,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 7448 */
.pvr_mask = 0xffff0000,
@@ -655,7 +697,10 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
- .cpu_setup = __setup_cpu_745x
+ .cpu_setup = __setup_cpu_745x,
+ .oprofile_cpu_type = "ppc/7450",
+ .oprofile_type = PPC_OPROFILE_G4,
+ .platform = "ppc7450",
},
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
.pvr_mask = 0x7fff0000,
@@ -665,7 +710,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* All G2_LE (603e core, plus some) have the same pvr */
.pvr_mask = 0x7fff0000,
@@ -675,7 +721,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* e300 (a 603e core, plus some) on 83xx */
.pvr_mask = 0x7fff0000,
@@ -685,7 +732,8 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
- .cpu_setup = __setup_cpu_603
+ .cpu_setup = __setup_cpu_603,
+ .platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
.pvr_mask = 0x00000000,
@@ -695,6 +743,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc603",
},
#endif /* CLASSIC_PPC */
#ifdef CONFIG_8xx
@@ -708,6 +757,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .platform = "ppc823",
},
#endif /* CONFIG_8xx */
#ifdef CONFIG_40x
@@ -719,6 +769,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .platform = "ppc403",
},
{ /* 403GCX */
.pvr_mask = 0xffffff00,
@@ -729,6 +780,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .platform = "ppc403",
},
{ /* 403G ?? */
.pvr_mask = 0xffff0000,
@@ -738,6 +790,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .platform = "ppc403",
},
{ /* 405GP */
.pvr_mask = 0xffff0000,
@@ -748,6 +801,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* STB 03xxx */
.pvr_mask = 0xffff0000,
@@ -758,6 +812,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* STB 04xxx */
.pvr_mask = 0xffff0000,
@@ -768,6 +823,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* NP405L */
.pvr_mask = 0xffff0000,
@@ -778,6 +834,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* NP4GS3 */
.pvr_mask = 0xffff0000,
@@ -788,6 +845,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* NP405H */
.pvr_mask = 0xffff0000,
@@ -798,6 +856,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* 405GPr */
.pvr_mask = 0xffff0000,
@@ -808,6 +867,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* STBx25xx */
.pvr_mask = 0xffff0000,
@@ -818,6 +878,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* 405LP */
.pvr_mask = 0xffff0000,
@@ -827,6 +888,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* Xilinx Virtex-II Pro */
.pvr_mask = 0xffff0000,
@@ -837,6 +899,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
{ /* 405EP */
.pvr_mask = 0xffff0000,
@@ -847,6 +910,7 @@ struct cpu_spec cpu_specs[] = {
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc405",
},
#endif /* CONFIG_40x */
@@ -856,81 +920,90 @@ struct cpu_spec cpu_specs[] = {
.pvr_value = 0x40000850,
.cpu_name = "440EP Rev. A",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = COMMON_USER, /* 440EP has an FPU */
+ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{
.pvr_mask = 0xf0000fff,
.pvr_value = 0x400008d3,
.cpu_name = "440EP Rev. B",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = COMMON_USER, /* 440EP has an FPU */
+ .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440GP Rev. B */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x40000440,
.cpu_name = "440GP Rev. B",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440gp",
},
{ /* 440GP Rev. C */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x40000481,
.cpu_name = "440GP Rev. C",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440gp",
},
{ /* 440GX Rev. A */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x50000850,
.cpu_name = "440GX Rev. A",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440GX Rev. B */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x50000851,
.cpu_name = "440GX Rev. B",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440GX Rev. C */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x50000892,
.cpu_name = "440GX Rev. C",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440GX Rev. F */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x50000894,
.cpu_name = "440GX Rev. F",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440SP Rev. A */
.pvr_mask = 0xff000fff,
.pvr_value = 0x53000891,
.cpu_name = "440SP Rev. A",
.cpu_features = CPU_FTRS_44X,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
{ /* 440SPe Rev. A */
.pvr_mask = 0xff000fff,
@@ -938,9 +1011,10 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "440SPe Rev. A",
.cpu_features = CPU_FTR_SPLIT_ID_CACHE |
CPU_FTR_USE_TB,
- .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "ppc440",
},
#endif /* CONFIG_44x */
#ifdef CONFIG_FSL_BOOKE
@@ -950,10 +1024,11 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "e200z5",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E200,
- .cpu_user_features = PPC_FEATURE_32 |
- PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_HAS_EFP_SINGLE |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
+ .platform = "ppc5554",
},
{ /* e200z6 */
.pvr_mask = 0xfff00000,
@@ -961,11 +1036,12 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "e200z6",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E200,
- .cpu_user_features = PPC_FEATURE_32 |
- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
+ .platform = "ppc5554",
},
{ /* e500 */
.pvr_mask = 0xffff0000,
@@ -973,12 +1049,15 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "e500",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E500,
- .cpu_user_features = PPC_FEATURE_32 |
- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_SPE_COMP |
PPC_FEATURE_HAS_EFP_SINGLE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e500",
+ .oprofile_type = PPC_OPROFILE_BOOKE,
+ .platform = "ppc8540",
},
{ /* e500v2 */
.pvr_mask = 0xffff0000,
@@ -986,12 +1065,16 @@ struct cpu_spec cpu_specs[] = {
.cpu_name = "e500v2",
/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
.cpu_features = CPU_FTRS_E500_2,
- .cpu_user_features = PPC_FEATURE_32 |
- PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
- PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_SPE_COMP |
+ PPC_FEATURE_HAS_EFP_SINGLE |
+ PPC_FEATURE_HAS_EFP_DOUBLE,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 4,
+ .oprofile_cpu_type = "ppc/e500",
+ .oprofile_type = PPC_OPROFILE_BOOKE,
+ .platform = "ppc8548",
},
#endif
#if !CLASSIC_PPC
@@ -1003,6 +1086,7 @@ struct cpu_spec cpu_specs[] = {
.cpu_user_features = PPC_FEATURE_32,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .platform = "powerpc",
}
#endif /* !CLASSIC_PPC */
#endif /* CONFIG_PPC32 */
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
new file mode 100644
index 000000000000..8c21d378f5d2
--- /dev/null
+++ b/arch/powerpc/kernel/crash.c
@@ -0,0 +1,197 @@
+/*
+ * Architecture specific (PPC64) functions for kexec based crash dumps.
+ *
+ * Copyright (C) 2005, IBM Corp.
+ *
+ * Created by: Haren Myneni
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <linux/delay.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/kdump.h>
+#include <asm/lmb.h>
+#include <asm/firmware.h>
+#include <asm/smp.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* This keeps a track of which one is crashing cpu. */
+int crashing_cpu = -1;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, &note, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, &note, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+void crash_ipi_callback(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ if (cpu == crashing_cpu)
+ return;
+
+ if (!cpu_online(cpu))
+ return;
+
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(1, 1);
+
+ local_irq_disable();
+
+ crash_save_this_cpu(regs, cpu);
+ atomic_dec(&waiting_for_crash_ipi);
+ kexec_smp_wait();
+ /* NOTREACHED */
+}
+
+static void crash_kexec_prepare_cpus(void)
+{
+ unsigned int msecs;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+
+ crash_send_ipi(crash_ipi_callback);
+ smp_wmb();
+
+ /*
+ * FIXME: Until we will have the way to stop other CPUSs reliabally,
+ * the crash CPU will send an IPI and wait for other CPUs to
+ * respond. If not, proceed the kexec boot even though we failed to
+ * capture other CPU states.
+ */
+ msecs = 1000000;
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
+ barrier();
+ mdelay(1);
+ }
+
+ /* Would it be better to replace the trap vector here? */
+
+ /*
+ * FIXME: In case if we do not get all CPUs, one possibility: ask the
+ * user to do soft reset such that we get all.
+ * IPI handler is already set by the panic cpu initially. Therefore,
+ * all cpus could invoke this handler from die() and the panic CPU
+ * will call machine_kexec() directly from this handler to do
+ * kexec boot.
+ */
+ if (atomic_read(&waiting_for_crash_ipi))
+ printk(KERN_ALERT "done waiting: %d cpus not responding\n",
+ atomic_read(&waiting_for_crash_ipi));
+ /* Leave the IPI callback set */
+}
+#else
+static void crash_kexec_prepare_cpus(void)
+{
+ /*
+ * move the secondarys to us so that we can copy
+ * the new kernel 0-0x100 safely
+ *
+ * do this if kexec in setup.c ?
+ */
+ smp_release_cpus();
+}
+
+#endif
+
+void default_machine_crash_shutdown(struct pt_regs *regs)
+{
+ /*
+ * This function is only called after the system
+ * has paniced or is otherwise in a critical state.
+ * The minimum amount of code to allow a kexec'd kernel
+ * to run successfully needs to happen here.
+ *
+ * In practice this means stopping other cpus in
+ * an SMP system.
+ * The kernel is broken so disable interrupts.
+ */
+ local_irq_disable();
+
+ if (ppc_md.kexec_cpu_down)
+ ppc_md.kexec_cpu_down(1, 0);
+
+ /*
+ * Make a note of crashing cpu. Will be used in machine_kexec
+ * such that another IPI will not be sent.
+ */
+ crashing_cpu = smp_processor_id();
+ crash_kexec_prepare_cpus();
+ crash_save_this_cpu(regs, crashing_cpu);
+}
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
new file mode 100644
index 000000000000..211d72653ea6
--- /dev/null
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -0,0 +1,111 @@
+/*
+ * Routines for doing kexec-based kdump.
+ *
+ * Copyright (C) 2005, IBM Corp.
+ *
+ * Created by: Michael Ellerman
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#undef DEBUG
+
+#include <linux/crash_dump.h>
+#include <linux/bootmem.h>
+#include <asm/kdump.h>
+#include <asm/lmb.h>
+#include <asm/firmware.h>
+#include <asm/uaccess.h>
+
+#ifdef DEBUG
+#include <asm/udbg.h>
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static void __init create_trampoline(unsigned long addr)
+{
+ /* The maximum range of a single instruction branch, is the current
+ * instruction's address + (32 MB - 4) bytes. For the trampoline we
+ * need to branch to current address + 32 MB. So we insert a nop at
+ * the trampoline address, then the next instruction (+ 4 bytes)
+ * does a branch to (32 MB - 4). The net effect is that when we
+ * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
+ * two instructions it doesn't require any registers.
+ */
+ create_instruction(addr, 0x60000000); /* nop */
+ create_branch(addr + 4, addr + PHYSICAL_START, 0);
+}
+
+void __init kdump_setup(void)
+{
+ unsigned long i;
+
+ DBG(" -> kdump_setup()\n");
+
+ for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
+ create_trampoline(i);
+ }
+
+ create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
+ create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
+
+ DBG(" <- kdump_setup()\n");
+}
+
+#ifdef CONFIG_PROC_VMCORE
+static int __init parse_elfcorehdr(char *p)
+{
+ if (p)
+ elfcorehdr_addr = memparse(p, &p);
+
+ return 0;
+}
+__setup("elfcorehdr=", parse_elfcorehdr);
+#endif
+
+static int __init parse_savemaxmem(char *p)
+{
+ if (p)
+ saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
+
+ return 0;
+}
+__setup("savemaxmem=", parse_savemaxmem);
+
+/*
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ * space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ * otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ void *vaddr;
+
+ if (!csize)
+ return 0;
+
+ vaddr = __ioremap(pfn << PAGE_SHIFT, PAGE_SIZE, 0);
+
+ if (userbuf) {
+ if (copy_to_user((char __user *)buf, (vaddr + offset), csize)) {
+ iounmap(vaddr);
+ return -EFAULT;
+ }
+ } else
+ memcpy(buf, (vaddr + offset), csize);
+
+ iounmap(vaddr);
+ return csize;
+}
diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
index 7c3419656ccc..36aaa7663f02 100644
--- a/arch/powerpc/kernel/dma_64.c
+++ b/arch/powerpc/kernel/dma_64.c
@@ -10,6 +10,7 @@
/* Include the busses we support */
#include <linux/pci.h>
#include <asm/vio.h>
+#include <asm/ibmebus.h>
#include <asm/scatterlist.h>
#include <asm/bug.h>
@@ -23,6 +24,10 @@ static struct dma_mapping_ops *get_dma_ops(struct device *dev)
if (dev->bus == &vio_bus_type)
return &vio_dma_ops;
#endif
+#ifdef CONFIG_IBMEBUS
+ if (dev->bus == &ibmebus_bus_type)
+ return &ibmebus_dma_ops;
+#endif
return NULL;
}
@@ -47,6 +52,10 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
if (dev->bus == &vio_bus_type)
return -EIO;
#endif /* CONFIG_IBMVIO */
+#ifdef CONFIG_IBMEBUS
+ if (dev->bus == &ibmebus_bus_type)
+ return -EIO;
+#endif
BUG();
return 0;
}
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 2e99ae41723c..f20a67261ec7 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall)
bl do_show_syscall
#endif /* SHOW_SYSCALLS */
rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- li r11,0
- stb r11,TI_SC_NOERR(r10)
lwz r11,TI_FLAGS(r10)
andi. r11,r11,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
@@ -222,25 +220,21 @@ ret_from_syscall:
bl do_show_syscall_exit
#endif
mr r6,r3
- li r11,-_LAST_ERRNO
- cmplw 0,r3,r11
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- blt+ 30f
- lbz r11,TI_SC_NOERR(r12)
- cmpwi r11,0
- bne 30f
- neg r3,r3
- lwz r10,_CCR(r1) /* Set SO bit in CR */
- oris r10,r10,0x1000
- stw r10,_CCR(r1)
-
/* disable interrupts so current_thread_info()->flags can't change */
-30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10)
lwz r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ li r8,-_LAST_ERRNO
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
bne- syscall_exit_work
+ cmplw 0,r3,r8
+ blt+ syscall_exit_cont
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
/* If the process has its own DBCR0 value, load it up. The single
@@ -292,46 +286,113 @@ syscall_dotrace:
b syscall_dotrace_cont
syscall_exit_work:
- stw r6,RESULT(r1) /* Save result */
+ andi. r0,r9,_TIF_RESTOREALL
+ bne- 2f
+ cmplw 0,r3,r8
+ blt+ 1f
+ andi. r0,r9,_TIF_NOERROR
+ bne- 1f
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
+
+1: stw r6,RESULT(r1) /* Save result */
stw r3,GPR3(r1) /* Update return value */
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq 5f
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10) /* re-enable interrupts */
+2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+ beq 4f
+
+ /* Clear per-syscall TIF flags if any are set, but _leave_
+ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
+ yet. */
+
+ li r11,_TIF_PERSYSCALL_MASK
+ addi r12,r12,TI_FLAGS
+3: lwarx r8,0,r12
+ andc r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+ dcbt 0,r12
+#endif
+ stwcx. r8,0,r12
+ bne- 3b
+ subi r12,r12,TI_FLAGS
+
+4: /* Anything which requires enabling interrupts? */
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
+ beq 7f
+
+ /* Save NVGPRS if they're not saved already */
lwz r4,_TRAP(r1)
andi. r4,r4,1
- beq 4f
+ beq 5f
SAVE_NVGPRS(r1)
li r4,0xc00
stw r4,_TRAP(r1)
-4:
+
+ /* Re-enable interrupts */
+5: ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10)
+
+ andi. r0,r9,_TIF_SAVE_NVGPRS
+ bne save_user_nvgprs
+
+save_user_nvgprs_cont:
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+ beq 7f
+
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_leave
REST_NVGPRS(r1)
-2:
- lwz r3,GPR3(r1)
+
+6: lwz r3,GPR3(r1)
LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10) /* disable interrupts again */
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
-5:
+7:
andi. r0,r9,_TIF_NEED_RESCHED
- bne 1f
+ bne 8f
lwz r5,_MSR(r1)
andi. r5,r5,MSR_PR
- beq syscall_exit_cont
- andi. r0,r9,_TIF_SIGPENDING
- beq syscall_exit_cont
+ beq ret_from_except
+ andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
+ beq ret_from_except
b do_user_signal
-1:
+8:
ori r10,r10,MSR_EE
SYNC
MTMSRD(r10) /* re-enable interrupts */
bl schedule
- b 2b
+ b 6b
+
+save_user_nvgprs:
+ lwz r8,TI_SIGFRAME(r12)
+
+.macro savewords start, end
+ 1: stw \start,4*(\start)(r8)
+ .section __ex_table,"a"
+ .align 2
+ .long 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savewords "(\start+1)",\end
+ .endif
+.endm
+ savewords 14,31
+ b save_user_nvgprs_cont
+
+
+save_user_nvgprs_fault:
+ li r3,11 /* SIGSEGV */
+ lwz r4,TI_TASK(r12)
+ bl force_sigsegv
+ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
+ lwz r9,TI_FLAGS(r12)
+ b save_user_nvgprs_cont
+
#ifdef SHOW_SYSCALLS
do_show_syscall:
#ifdef SHOW_SYSCALLS_TASK
@@ -401,28 +462,10 @@ show_syscalls_task:
#endif /* SHOW_SYSCALLS */
/*
- * The sigsuspend and rt_sigsuspend system calls can call do_signal
- * and thus put the process into the stopped state where we might
- * want to examine its user state with ptrace. Therefore we need
- * to save all the nonvolatile registers (r13 - r31) before calling
- * the C code.
+ * The fork/clone functions need to copy the full register set into
+ * the child process. Therefore we need to save all the nonvolatile
+ * registers (r13 - r31) before calling the C code.
*/
- .globl ppc_sigsuspend
-ppc_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,_TRAP(r1) /* register set saved */
- b sys_sigsuspend
-
- .globl ppc_rt_sigsuspend
-ppc_rt_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30
- stw r0,_TRAP(r1)
- b sys_rt_sigsuspend
-
.globl ppc_fork
ppc_fork:
SAVE_NVGPRS(r1)
@@ -447,14 +490,6 @@ ppc_clone:
stw r0,_TRAP(r1) /* register set saved */
b sys_clone
- .globl ppc_swapcontext
-ppc_swapcontext:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,_TRAP(r1) /* register set saved */
- b sys_swapcontext
-
/*
* Top-level page fault handling.
* This is in assembler because if do_page_fault tells us that
@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
.long ret_from_except
#endif
- .globl sigreturn_exit
-sigreturn_exit:
- subi r1,r3,STACK_FRAME_OVERHEAD
- rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- lwz r9,TI_FLAGS(r12)
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq+ ret_from_except_full
- bl do_syscall_trace_leave
- /* fall through */
-
.globl ret_from_except_full
ret_from_except_full:
REST_NVGPRS(r1)
@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
/* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK)
bne do_work
restore_user:
@@ -892,7 +917,7 @@ recheck:
lwz r9,TI_FLAGS(r9)
andi. r0,r9,_TIF_NEED_RESCHED
bne- do_resched
- andi. r0,r9,_TIF_SIGPENDING
+ andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
beq restore_user
do_user_signal: /* r10 contains MSR_KERNEL here */
ori r10,r10,MSR_EE
@@ -963,7 +988,7 @@ _GLOBAL(enter_rtas)
stwu r1,-INT_FRAME_SIZE(r1)
mflr r0
stw r0,INT_FRAME_SIZE+4(r1)
- LOADADDR(r4, rtas)
+ LOAD_REG_ADDR(r4, rtas)
lis r6,1f@ha /* physical return address for rtas */
addi r6,r6,1f@l
tophys(r6,r6)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index bce33a38399f..388f861b8ed1 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -113,9 +113,7 @@ system_call_common:
addi r9,r1,STACK_FRAME_OVERHEAD
#endif
clrrdi r11,r1,THREAD_SHIFT
- li r12,0
ld r10,TI_FLAGS(r11)
- stb r12,TI_SC_NOERR(r11)
andi. r11,r10,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
syscall_dotrace_cont:
@@ -144,24 +142,12 @@ system_call: /* label this so stack traces look sane */
bctrl /* Call handler */
syscall_exit:
+ std r3,RESULT(r1)
#ifdef SHOW_SYSCALLS
- std r3,GPR3(r1)
bl .do_show_syscall_exit
- ld r3,GPR3(r1)
+ ld r3,RESULT(r1)
#endif
- std r3,RESULT(r1)
- ld r5,_CCR(r1)
- li r10,-_LAST_ERRNO
- cmpld r3,r10
clrrdi r12,r1,THREAD_SHIFT
- bge- syscall_error
-syscall_error_cont:
-
- /* check for syscall tracing or audit */
- ld r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
- bne- syscall_exit_trace
-syscall_exit_trace_cont:
/* disable interrupts so current_thread_info()->flags can't change,
and so that we don't get interrupted after loading SRR0/1. */
@@ -173,8 +159,13 @@ syscall_exit_trace_cont:
rotldi r10,r10,16
mtmsrd r10,1
ld r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ li r11,-_LAST_ERRNO
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK)
bne- syscall_exit_work
+ cmpld r3,r11
+ ld r5,_CCR(r1)
+ bge- syscall_error
+syscall_error_cont:
ld r7,_NIP(r1)
stdcx. r0,0,r1 /* to clear the reservation */
andi. r6,r8,MSR_PR
@@ -193,21 +184,12 @@ syscall_exit_trace_cont:
rfid
b . /* prevent speculative execution */
-syscall_enosys:
- li r3,-ENOSYS
- std r3,RESULT(r1)
- clrrdi r12,r1,THREAD_SHIFT
- ld r5,_CCR(r1)
-
-syscall_error:
- lbz r11,TI_SC_NOERR(r12)
- cmpwi 0,r11,0
- bne- syscall_error_cont
- neg r3,r3
+syscall_error:
oris r5,r5,0x1000 /* Set SO bit in CR */
+ neg r3,r3
std r5,_CCR(r1)
b syscall_error_cont
-
+
/* Traced system call support */
syscall_dotrace:
bl .save_nvgprs
@@ -225,21 +207,69 @@ syscall_dotrace:
ld r10,TI_FLAGS(r10)
b syscall_dotrace_cont
-syscall_exit_trace:
- std r3,GPR3(r1)
- bl .save_nvgprs
+syscall_enosys:
+ li r3,-ENOSYS
+ b syscall_exit
+
+syscall_exit_work:
+ /* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
+ If TIF_NOERROR is set, just save r3 as it is. */
+
+ andi. r0,r9,_TIF_RESTOREALL
+ bne- 2f
+ cmpld r3,r11 /* r10 is -LAST_ERRNO */
+ blt+ 1f
+ andi. r0,r9,_TIF_NOERROR
+ bne- 1f
+ ld r5,_CCR(r1)
+ neg r3,r3
+ oris r5,r5,0x1000 /* Set SO bit in CR */
+ std r5,_CCR(r1)
+1: std r3,GPR3(r1)
+2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+ beq 4f
+
+ /* Clear per-syscall TIF flags if any are set, but _leave_
+ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
+ yet. */
+
+ li r11,_TIF_PERSYSCALL_MASK
+ addi r12,r12,TI_FLAGS
+3: ldarx r10,0,r12
+ andc r10,r10,r11
+ stdcx. r10,0,r12
+ bne- 3b
+ subi r12,r12,TI_FLAGS
+
+4: bl .save_nvgprs
+ /* Anything else left to do? */
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
+ beq .ret_from_except_lite
+
+ /* Re-enable interrupts */
+ mfmsr r10
+ ori r10,r10,MSR_EE
+ mtmsrd r10,1
+
+ andi. r0,r9,_TIF_SAVE_NVGPRS
+ bne save_user_nvgprs
+
+ /* If tracing, re-enable interrupts and do it */
+save_user_nvgprs_cont:
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+ beq 5f
+
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_syscall_trace_leave
REST_NVGPRS(r1)
- ld r3,GPR3(r1)
- ld r5,_CCR(r1)
clrrdi r12,r1,THREAD_SHIFT
- b syscall_exit_trace_cont
-/* Stuff to do on exit from a system call. */
-syscall_exit_work:
- std r3,GPR3(r1)
- std r5,_CCR(r1)
+ /* Disable interrupts again and handle other work if any */
+5: mfmsr r10
+ rldicl r10,r10,48,1
+ rotldi r10,r10,16
+ mtmsrd r10,1
+
b .ret_from_except_lite
/* Save non-volatile GPRs, if not already saved. */
@@ -252,6 +282,52 @@ _GLOBAL(save_nvgprs)
std r0,_TRAP(r1)
blr
+
+save_user_nvgprs:
+ ld r10,TI_SIGFRAME(r12)
+ andi. r0,r9,_TIF_32BIT
+ beq- save_user_nvgprs_64
+
+ /* 32-bit save to userspace */
+
+.macro savewords start, end
+ 1: stw \start,4*(\start)(r10)
+ .section __ex_table,"a"
+ .align 3
+ .llong 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savewords "(\start+1)",\end
+ .endif
+.endm
+ savewords 14,31
+ b save_user_nvgprs_cont
+
+save_user_nvgprs_64:
+ /* 64-bit save to userspace */
+
+.macro savelongs start, end
+ 1: std \start,8*(\start)(r10)
+ .section __ex_table,"a"
+ .align 3
+ .llong 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savelongs "(\start+1)",\end
+ .endif
+.endm
+ savelongs 14,31
+ b save_user_nvgprs_cont
+
+save_user_nvgprs_fault:
+ li r3,11 /* SIGSEGV */
+ ld r4,TI_TASK(r12)
+ bl .force_sigsegv
+
+ clrrdi r12,r1,THREAD_SHIFT
+ ld r9,TI_FLAGS(r12)
+ b save_user_nvgprs_cont
+
/*
* The sigsuspend and rt_sigsuspend system calls can call do_signal
* and thus put the process into the stopped state where we might
@@ -260,35 +336,6 @@ _GLOBAL(save_nvgprs)
* the C code. Similarly, fork, vfork and clone need the full
* register state on the stack so that it can be copied to the child.
*/
-_GLOBAL(ppc32_sigsuspend)
- bl .save_nvgprs
- bl .compat_sys_sigsuspend
- b 70f
-
-_GLOBAL(ppc64_rt_sigsuspend)
- bl .save_nvgprs
- bl .sys_rt_sigsuspend
- b 70f
-
-_GLOBAL(ppc32_rt_sigsuspend)
- bl .save_nvgprs
- bl .compat_sys_rt_sigsuspend
-70: cmpdi 0,r3,0
- /* If it returned an error, we need to return via syscall_exit to set
- the SO bit in cr0 and potentially stop for ptrace. */
- bne syscall_exit
- /* If sigsuspend() returns zero, we are going into a signal handler. We
- may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
-#ifdef CONFIG_AUDITSYSCALL
- ld r3,PACACURRENT(r13)
- ld r4,AUDITCONTEXT(r3)
- cmpdi 0,r4,0
- beq .ret_from_except /* No audit_context: Leave immediately. */
- li r4, 2 /* AUDITSC_FAILURE */
- li r5,-4 /* It's always -EINTR */
- bl .audit_syscall_exit
-#endif
- b .ret_from_except
_GLOBAL(ppc_fork)
bl .save_nvgprs
@@ -305,37 +352,6 @@ _GLOBAL(ppc_clone)
bl .sys_clone
b syscall_exit
-_GLOBAL(ppc32_swapcontext)
- bl .save_nvgprs
- bl .compat_sys_swapcontext
- b 80f
-
-_GLOBAL(ppc64_swapcontext)
- bl .save_nvgprs
- bl .sys_swapcontext
- b 80f
-
-_GLOBAL(ppc32_sigreturn)
- bl .compat_sys_sigreturn
- b 80f
-
-_GLOBAL(ppc32_rt_sigreturn)
- bl .compat_sys_rt_sigreturn
- b 80f
-
-_GLOBAL(ppc64_rt_sigreturn)
- bl .sys_rt_sigreturn
-
-80: cmpdi 0,r3,0
- blt syscall_exit
- clrrdi r4,r1,THREAD_SHIFT
- ld r4,TI_FLAGS(r4)
- andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
- beq+ 81f
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl .do_syscall_trace_leave
-81: b .ret_from_except
-
_GLOBAL(ret_from_fork)
bl .schedule_tail
REST_NVGPRS(r1)
@@ -495,7 +511,8 @@ restore:
cmpdi 0,r5,0
beq 4f
/* Check for pending interrupts (iSeries) */
- ld r3,PACALPPACA+LPPACAANYINT(r13)
+ ld r3,PACALPPACAPTR(r13)
+ ld r3,LPPACAANYINT(r3)
cmpdi r3,0
beq+ 4f /* skip do_IRQ if no interrupts */
@@ -673,9 +690,8 @@ _GLOBAL(enter_rtas)
std r6,PACASAVEDMSR(r13)
/* Setup our real return addr */
- SET_REG_TO_LABEL(r4,.rtas_return_loc)
- SET_REG_TO_CONST(r9,KERNELBASE)
- sub r4,r4,r9
+ LOAD_REG_ADDR(r4,.rtas_return_loc)
+ clrldi r4,r4,2 /* convert to realmode address */
mtlr r4
li r0,0
@@ -690,7 +706,7 @@ _GLOBAL(enter_rtas)
sync /* disable interrupts so SRR0/1 */
mtmsrd r0 /* don't get trashed */
- SET_REG_TO_LABEL(r4,rtas)
+ LOAD_REG_ADDR(r4, rtas)
ld r5,RTASENTRY(r4) /* get the rtas->entry value */
ld r4,RTASBASE(r4) /* get the rtas->base value */
@@ -702,8 +718,7 @@ _GLOBAL(enter_rtas)
_STATIC(rtas_return_loc)
/* relocation is off at this point */
mfspr r4,SPRN_SPRG3 /* Get PACA */
- SET_REG_TO_CONST(r5, KERNELBASE)
- sub r4,r4,r5 /* RELOC the PACA base pointer */
+ clrldi r4,r4,2 /* convert to realmode address */
mfmsr r6
li r0,MSR_RI
@@ -712,7 +727,7 @@ _STATIC(rtas_return_loc)
mtmsrd r6
ld r1,PACAR1(r4) /* Restore our SP */
- LOADADDR(r3,.rtas_restore_regs)
+ LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs)
ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
mtspr SPRN_SRR0,r3
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index b780b42c95fc..e4362dfa37fb 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -39,9 +39,9 @@ _GLOBAL(load_up_fpu)
* to another. Instead we call giveup_fpu in switch_to.
*/
#ifndef CONFIG_SMP
- LOADBASE(r3, last_task_used_math)
+ LOAD_REG_ADDRBASE(r3, last_task_used_math)
toreal(r3)
- PPC_LL r4,OFF(last_task_used_math)(r3)
+ PPC_LL r4,ADDROFF(last_task_used_math)(r3)
PPC_LCMPI 0,r4,0
beq 1f
toreal(r4)
@@ -77,7 +77,7 @@ _GLOBAL(load_up_fpu)
#ifndef CONFIG_SMP
subi r4,r5,THREAD
fromreal(r4)
- PPC_STL r4,OFF(last_task_used_math)(r3)
+ PPC_STL r4,ADDROFF(last_task_used_math)(r3)
#endif /* CONFIG_SMP */
/* restore registers and return */
/* we haven't used ctr or xer or lr */
@@ -113,8 +113,8 @@ _GLOBAL(giveup_fpu)
1:
#ifndef CONFIG_SMP
li r5,0
- LOADBASE(r4,last_task_used_math)
- PPC_STL r5,OFF(last_task_used_math)(r4)
+ LOAD_REG_ADDRBASE(r4,last_task_used_math)
+ PPC_STL r5,ADDROFF(last_task_used_math)(r4)
#endif /* CONFIG_SMP */
blr
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index ccdf94731e30..03b25f9359f8 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -120,10 +120,25 @@ __start:
* because OF may have I/O devices mapped into that area
* (particularly on CHRP).
*/
+#ifdef CONFIG_PPC_MULTIPLATFORM
cmpwi 0,r5,0
beq 1f
bl prom_init
trap
+#endif
+
+/*
+ * Check for BootX signature when supporting PowerMac and branch to
+ * appropriate trampoline if it's present
+ */
+#ifdef CONFIG_PPC_PMAC
+1: lis r31,0x426f
+ ori r31,r31,0x6f58
+ cmpw 0,r3,r31
+ bne 1f
+ bl bootx_init
+ trap
+#endif /* CONFIG_PPC_PMAC */
1: mr r31,r3 /* save parameters */
mr r30,r4
@@ -153,6 +168,9 @@ __after_mmu_off:
bl flush_tlbs
bl initial_bats
+#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+ bl setup_disp_bat
+#endif
/*
* Call setup_cpu for CPU 0 and initialize 6xx Idle
@@ -450,16 +468,11 @@ SystemCall:
* by executing an altivec instruction.
*/
. = 0xf00
- b Trap_0f
+ b PerformanceMonitor
. = 0xf20
b AltiVecUnavailable
-Trap_0f:
- EXCEPTION_PROLOG
- addi r3,r1,STACK_FRAME_OVERHEAD
- EXC_XFER_EE(0xf00, unknown_exception)
-
/*
* Handle TLB miss for instruction on 603/603e.
* Note: we get an alternate set of r0 - r3 to use automatically.
@@ -703,6 +716,11 @@ AltiVecUnavailable:
#endif /* CONFIG_ALTIVEC */
EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception)
+PerformanceMonitor:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_STD(0xf00, performance_monitor_exception)
+
#ifdef CONFIG_ALTIVEC
/* Note that the AltiVec support is closely modeled after the FP
* support. Changes to one are likely to be applicable to the
@@ -1306,6 +1324,32 @@ initial_bats:
blr
+#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT)
+setup_disp_bat:
+ /*
+ * setup the display bat prepared for us in prom.c
+ */
+ mflr r8
+ bl reloc_offset
+ mtlr r8
+ addis r8,r3,disp_BAT@ha
+ addi r8,r8,disp_BAT@l
+ cmpwi cr0,r8,0
+ beqlr
+ lwz r11,0(r8)
+ lwz r8,4(r8)
+ mfspr r9,SPRN_PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpwi 0,r9,1
+ beq 1f
+ mtspr SPRN_DBAT3L,r8
+ mtspr SPRN_DBAT3U,r11
+ blr
+1: mtspr SPRN_IBAT3L,r8
+ mtspr SPRN_IBAT3U,r11
+ blr
+#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */
+
#ifdef CONFIG_8260
/* Jump into the system reset for the rom.
* We first disable the MMU, and then jump to the ROM reset address.
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 8a8bf79ef044..308268466342 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -154,11 +154,15 @@ _GLOBAL(__secondary_hold)
bne 100b
#ifdef CONFIG_HMT
- b .hmt_init
+ SET_REG_IMMEDIATE(r4, .hmt_init)
+ mtctr r4
+ bctr
#else
#ifdef CONFIG_SMP
+ LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
+ mtctr r4
mr r3,r24
- b .pSeries_secondary_smp_init
+ bctr
#else
BUG_OPCODE
#endif
@@ -200,6 +204,21 @@ exception_marker:
#define EX_R3 64
#define EX_LR 72
+/*
+ * We're short on space and time in the exception prolog, so we can't
+ * use the normal SET_REG_IMMEDIATE macro. Normally we just need the
+ * low halfword of the address, but for Kdump we need the whole low
+ * word.
+ */
+#ifdef CONFIG_CRASH_DUMP
+#define LOAD_HANDLER(reg, label) \
+ oris reg,reg,(label)@h; /* virt addr of handler ... */ \
+ ori reg,reg,(label)@l; /* .. and the rest */
+#else
+#define LOAD_HANDLER(reg, label) \
+ ori reg,reg,(label)@l; /* virt addr of handler ... */
+#endif
+
#define EXCEPTION_PROLOG_PSERIES(area, label) \
mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
std r9,area+EX_R9(r13); /* save r9 - r12 */ \
@@ -212,7 +231,7 @@ exception_marker:
clrrdi r12,r13,32; /* get high part of &label */ \
mfmsr r10; \
mfspr r11,SPRN_SRR0; /* save SRR0 */ \
- ori r12,r12,(label)@l; /* virt addr of handler */ \
+ LOAD_HANDLER(r12,label) \
ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
mtspr SPRN_SRR0,r12; \
mfspr r12,SPRN_SRR1; /* and SRR1 */ \
@@ -236,8 +255,9 @@ exception_marker:
#define EXCEPTION_PROLOG_ISERIES_2 \
mfmsr r10; \
- ld r11,PACALPPACA+LPPACASRR0(r13); \
- ld r12,PACALPPACA+LPPACASRR1(r13); \
+ ld r12,PACALPPACAPTR(r13); \
+ ld r11,LPPACASRR0(r12); \
+ ld r12,LPPACASRR1(r12); \
ori r10,r10,MSR_RI; \
mtmsrd r10,1
@@ -553,6 +573,7 @@ slb_miss_user_pseries:
* Vectors for the FWNMI option. Share common code.
*/
.globl system_reset_fwnmi
+ .align 7
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
@@ -560,6 +581,7 @@ system_reset_fwnmi:
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
+ .align 7
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
@@ -614,7 +636,8 @@ data_access_slb_iSeries:
std r12,PACA_EXSLB+EX_R12(r13)
mfspr r10,SPRN_SPRG1
std r10,PACA_EXSLB+EX_R13(r13)
- ld r12,PACALPPACA+LPPACASRR1(r13);
+ ld r12,PACALPPACAPTR(r13)
+ ld r12,LPPACASRR1(r12)
b .slb_miss_realmode
STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN)
@@ -624,7 +647,8 @@ instruction_access_slb_iSeries:
mtspr SPRN_SPRG1,r13 /* save r13 */
mfspr r13,SPRN_SPRG3 /* get paca address into r13 */
std r3,PACA_EXSLB+EX_R3(r13)
- ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
+ ld r3,PACALPPACAPTR(r13)
+ ld r3,LPPACASRR0(r3) /* get SRR0 value */
std r9,PACA_EXSLB+EX_R9(r13)
mfcr r9
#ifdef __DISABLED__
@@ -636,7 +660,8 @@ instruction_access_slb_iSeries:
std r12,PACA_EXSLB+EX_R12(r13)
mfspr r10,SPRN_SPRG1
std r10,PACA_EXSLB+EX_R13(r13)
- ld r12,PACALPPACA+LPPACASRR1(r13);
+ ld r12,PACALPPACAPTR(r13)
+ ld r12,LPPACASRR1(r12)
b .slb_miss_realmode
#ifdef __DISABLED__
@@ -693,7 +718,7 @@ system_reset_iSeries:
lbz r23,PACAPROCSTART(r13) /* Test if this processor
* should start */
sync
- LOADADDR(r3,current_set)
+ LOAD_REG_IMMEDIATE(r3,current_set)
sldi r28,r24,3 /* get current_set[cpu#] */
ldx r3,r3,r28
addi r1,r3,THREAD_SIZE
@@ -725,16 +750,19 @@ iSeries_secondary_smp_loop:
.globl decrementer_iSeries_masked
decrementer_iSeries_masked:
li r11,1
- stb r11,PACALPPACA+LPPACADECRINT(r13)
- lwz r12,PACADEFAULTDECR(r13)
+ ld r12,PACALPPACAPTR(r13)
+ stb r11,LPPACADECRINT(r12)
+ LOAD_REG_ADDRBASE(r12,tb_ticks_per_jiffy)
+ lwz r12,ADDROFF(tb_ticks_per_jiffy)(r12)
mtspr SPRN_DEC,r12
/* fall through */
.globl hardware_interrupt_iSeries_masked
hardware_interrupt_iSeries_masked:
mtcrf 0x80,r9 /* Restore regs */
- ld r11,PACALPPACA+LPPACASRR0(r13)
- ld r12,PACALPPACA+LPPACASRR1(r13)
+ ld r12,PACALPPACAPTR(r13)
+ ld r11,LPPACASRR0(r12)
+ ld r12,LPPACASRR1(r12)
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r12
ld r9,PACA_EXGEN+EX_R9(r13)
@@ -973,7 +1001,8 @@ _GLOBAL(slb_miss_realmode)
ld r3,PACA_EXSLB+EX_R3(r13)
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
#ifdef CONFIG_PPC_ISERIES
- ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */
+ ld r11,PACALPPACAPTR(r13)
+ ld r11,LPPACASRR0(r11) /* get SRR0 value */
#endif /* CONFIG_PPC_ISERIES */
mtlr r10
@@ -1345,7 +1374,7 @@ _GLOBAL(do_stab_bolted)
* fixed address (the linker can't compute (u64)&initial_stab >>
* PAGE_SHIFT).
*/
- . = STAB0_PHYS_ADDR /* 0x6000 */
+ . = STAB0_OFFSET /* 0x6000 */
.globl initial_stab
initial_stab:
.space 4096
@@ -1391,7 +1420,7 @@ _GLOBAL(pSeries_secondary_smp_init)
* physical cpu id in r24, we need to search the pacas to find
* which logical id maps to our physical one.
*/
- LOADADDR(r13, paca) /* Get base vaddr of paca array */
+ LOAD_REG_IMMEDIATE(r13, paca) /* Get base vaddr of paca array */
li r5,0 /* logical cpu id */
1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */
cmpw r6,r24 /* Compare to our id */
@@ -1425,8 +1454,8 @@ _GLOBAL(pSeries_secondary_smp_init)
#ifdef CONFIG_PPC_ISERIES
_STATIC(__start_initialization_iSeries)
/* Clear out the BSS */
- LOADADDR(r11,__bss_stop)
- LOADADDR(r8,__bss_start)
+ LOAD_REG_IMMEDIATE(r11,__bss_stop)
+ LOAD_REG_IMMEDIATE(r8,__bss_start)
sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */
@@ -1437,17 +1466,17 @@ _STATIC(__start_initialization_iSeries)
3: stdu r0,8(r8)
bdnz 3b
4:
- LOADADDR(r1,init_thread_union)
+ LOAD_REG_IMMEDIATE(r1,init_thread_union)
addi r1,r1,THREAD_SIZE
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
- LOADADDR(r3,cpu_specs)
- LOADADDR(r4,cur_cpu_spec)
+ LOAD_REG_IMMEDIATE(r3,cpu_specs)
+ LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
li r5,0
bl .identify_cpu
- LOADADDR(r2,__toc_start)
+ LOAD_REG_IMMEDIATE(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
@@ -1485,11 +1514,13 @@ _STATIC(__mmu_off)
*
*/
_GLOBAL(__start_initialization_multiplatform)
+#ifdef CONFIG_PPC_MULTIPLATFORM
/*
* Are we booted from a PROM Of-type client-interface ?
*/
cmpldi cr0,r5,0
bne .__boot_from_prom /* yes -> prom */
+#endif
/* Save parameters */
mr r31,r3
@@ -1505,11 +1536,12 @@ _GLOBAL(__start_initialization_multiplatform)
li r24,0
/* Switch off MMU if not already */
- LOADADDR(r4, .__after_prom_start - KERNELBASE)
+ LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r30
bl .__mmu_off
b .__after_prom_start
+#ifdef CONFIG_PPC_MULTIPLATFORM
_STATIC(__boot_from_prom)
/* Save parameters */
mr r31,r3
@@ -1524,7 +1556,7 @@ _STATIC(__boot_from_prom)
/* put a relocation offset into r3 */
bl .reloc_offset
- LOADADDR(r2,__toc_start)
+ LOAD_REG_IMMEDIATE(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
@@ -1542,6 +1574,7 @@ _STATIC(__boot_from_prom)
bl .prom_init
/* We never return */
trap
+#endif
/*
* At this point, r3 contains the physical address we are running at,
@@ -1550,7 +1583,7 @@ _STATIC(__boot_from_prom)
_STATIC(__after_prom_start)
/*
- * We need to run with __start at physical address 0.
+ * We need to run with __start at physical address PHYSICAL_START.
* This will leave some code in the first 256B of
* real memory, which are reserved for software use.
* The remainder of the first page is loaded with the fixed
@@ -1563,9 +1596,9 @@ _STATIC(__after_prom_start)
*/
bl .reloc_offset
mr r26,r3
- SET_REG_TO_CONST(r27,KERNELBASE)
+ LOAD_REG_IMMEDIATE(r27, KERNELBASE)
- li r3,0 /* target addr */
+ LOAD_REG_IMMEDIATE(r3, PHYSICAL_START) /* target addr */
// XXX FIXME: Use phys returned by OF (r30)
add r4,r27,r26 /* source addr */
@@ -1573,7 +1606,7 @@ _STATIC(__after_prom_start)
/* i.e. where we are running */
/* the source addr */
- LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */
+ LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
sub r5,r5,r27
li r6,0x100 /* Start offset, the first 0x100 */
@@ -1583,11 +1616,11 @@ _STATIC(__after_prom_start)
/* this includes the code being */
/* executed here. */
- LOADADDR(r0, 4f) /* Jump to the copy of this code */
+ LOAD_REG_IMMEDIATE(r0, 4f) /* Jump to the copy of this code */
mtctr r0 /* that we just made/relocated */
bctr
-4: LOADADDR(r5,klimit)
+4: LOAD_REG_IMMEDIATE(r5,klimit)
add r5,r5,r26
ld r5,0(r5) /* get the value of klimit */
sub r5,r5,r27
@@ -1669,7 +1702,7 @@ _GLOBAL(pmac_secondary_start)
mtmsrd r3 /* RI on */
/* Set up a paca value for this processor. */
- LOADADDR(r4, paca) /* Get base vaddr of paca array */
+ LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r4 /* for this processor. */
mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */
@@ -1706,7 +1739,7 @@ _GLOBAL(__secondary_start)
bl .early_setup_secondary
/* Initialize the kernel stack. Just a repeat for iSeries. */
- LOADADDR(r3,current_set)
+ LOAD_REG_ADDR(r3, current_set)
sldi r28,r24,3 /* get current_set[cpu#] */
ldx r1,r3,r28
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
@@ -1717,8 +1750,8 @@ _GLOBAL(__secondary_start)
mtlr r7
/* enable MMU and jump to start_secondary */
- LOADADDR(r3,.start_secondary_prolog)
- SET_REG_TO_CONST(r4, MSR_KERNEL)
+ LOAD_REG_ADDR(r3, .start_secondary_prolog)
+ LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
#ifdef DO_SOFT_DISABLE
ori r4,r4,MSR_EE
#endif
@@ -1767,8 +1800,8 @@ _STATIC(start_here_multiplatform)
* be detached from the kernel completely. Besides, we need
* to clear it now for kexec-style entry.
*/
- LOADADDR(r11,__bss_stop)
- LOADADDR(r8,__bss_start)
+ LOAD_REG_IMMEDIATE(r11,__bss_stop)
+ LOAD_REG_IMMEDIATE(r8,__bss_start)
sub r11,r11,r8 /* bss size */
addi r11,r11,7 /* round up to an even double word */
rldicl. r11,r11,61,3 /* shift right by 3 */
@@ -1806,7 +1839,7 @@ _STATIC(start_here_multiplatform)
/* up the htab. This is done because we have relocated the */
/* kernel but are still running in real mode. */
- LOADADDR(r3,init_thread_union)
+ LOAD_REG_IMMEDIATE(r3,init_thread_union)
add r3,r3,r26
/* set up a stack pointer (physical address) */
@@ -1815,14 +1848,14 @@ _STATIC(start_here_multiplatform)
stdu r0,-STACK_FRAME_OVERHEAD(r1)
/* set up the TOC (physical address) */
- LOADADDR(r2,__toc_start)
+ LOAD_REG_IMMEDIATE(r2,__toc_start)
addi r2,r2,0x4000
addi r2,r2,0x4000
add r2,r2,r26
- LOADADDR(r3,cpu_specs)
+ LOAD_REG_IMMEDIATE(r3, cpu_specs)
add r3,r3,r26
- LOADADDR(r4,cur_cpu_spec)
+ LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
add r4,r4,r26
mr r5,r26
bl .identify_cpu
@@ -1838,15 +1871,15 @@ _STATIC(start_here_multiplatform)
* nowhere it can be initialized differently before we reach this
* code
*/
- LOADADDR(r27, boot_cpuid)
+ LOAD_REG_IMMEDIATE(r27, boot_cpuid)
add r27,r27,r26
lwz r27,0(r27)
- LOADADDR(r24, paca) /* Get base vaddr of paca array */
+ LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */
add r13,r13,r26 /* convert to physical addr */
- mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */
+ mtspr SPRN_SPRG3,r13
/* Do very early kernel initializations, including initial hash table,
* stab and slb setup before we turn on relocation. */
@@ -1855,8 +1888,8 @@ _STATIC(start_here_multiplatform)
mr r3,r31
bl .early_setup
- LOADADDR(r3,.start_here_common)
- SET_REG_TO_CONST(r4, MSR_KERNEL)
+ LOAD_REG_IMMEDIATE(r3, .start_here_common)
+ LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
mtspr SPRN_SRR0,r3
mtspr SPRN_SRR1,r4
rfid
@@ -1870,7 +1903,7 @@ _STATIC(start_here_common)
/* The following code sets up the SP and TOC now that we are */
/* running with translation enabled. */
- LOADADDR(r3,init_thread_union)
+ LOAD_REG_IMMEDIATE(r3,init_thread_union)
/* set up the stack */
addi r1,r3,THREAD_SIZE
@@ -1883,16 +1916,16 @@ _STATIC(start_here_common)
li r3,0
bl .do_cpu_ftr_fixups
- LOADADDR(r26, boot_cpuid)
+ LOAD_REG_IMMEDIATE(r26, boot_cpuid)
lwz r26,0(r26)
- LOADADDR(r24, paca) /* Get base vaddr of paca array */
+ LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */
mtspr SPRN_SPRG3,r13
/* ptr to current */
- LOADADDR(r4,init_task)
+ LOAD_REG_IMMEDIATE(r4, init_task)
std r4,PACACURRENT(r13)
/* Load the TOC */
@@ -1915,7 +1948,7 @@ _STATIC(start_here_common)
_GLOBAL(hmt_init)
#ifdef CONFIG_HMT
- LOADADDR(r5, hmt_thread_data)
+ LOAD_REG_IMMEDIATE(r5, hmt_thread_data)
mfspr r7,SPRN_PVR
srwi r7,r7,16
cmpwi r7,0x34 /* Pulsar */
@@ -1936,7 +1969,7 @@ _GLOBAL(hmt_init)
b 101f
__hmt_secondary_hold:
- LOADADDR(r5, hmt_thread_data)
+ LOAD_REG_IMMEDIATE(r5, hmt_thread_data)
clrldi r5,r5,4
li r7,0
mfspr r6,SPRN_PIR
@@ -1964,7 +1997,7 @@ __hmt_secondary_hold:
#ifdef CONFIG_HMT
_GLOBAL(hmt_start_secondary)
- LOADADDR(r4,__hmt_secondary_hold)
+ LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold)
clrldi r4,r4,4
mtspr SPRN_NIADORM, r4
mfspr r4, SPRN_MSRDORM
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
new file mode 100644
index 000000000000..e47d40ac6f39
--- /dev/null
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -0,0 +1,396 @@
+/*
+ * IBM PowerPC IBM eBus Infrastructure Support.
+ *
+ * Copyright (c) 2005 IBM Corporation
+ * Heiko J Schick <schickhj@de.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ * BSD.
+ *
+ * OpenIB BSD License
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kobject.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <asm/ibmebus.h>
+#include <asm/abs_addr.h>
+
+static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */
+ .name = ibmebus_bus_device.ofdev.dev.bus_id,
+ .ofdev.dev.bus_id = "ibmebus",
+ .ofdev.dev.bus = &ibmebus_bus_type,
+};
+
+static void *ibmebus_alloc_coherent(struct device *dev,
+ size_t size,
+ dma_addr_t *dma_handle,
+ gfp_t flag)
+{
+ void *mem;
+
+ mem = kmalloc(size, flag);
+ *dma_handle = (dma_addr_t)mem;
+
+ return mem;
+}
+
+static void ibmebus_free_coherent(struct device *dev,
+ size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ kfree(vaddr);
+}
+
+static dma_addr_t ibmebus_map_single(struct device *dev,
+ void *ptr,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ return (dma_addr_t)(ptr);
+}
+
+static void ibmebus_unmap_single(struct device *dev,
+ dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ return;
+}
+
+static int ibmebus_map_sg(struct device *dev,
+ struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ for (i = 0; i < nents; i++) {
+ sg[i].dma_address = (dma_addr_t)page_address(sg[i].page)
+ + sg[i].offset;
+ sg[i].dma_length = sg[i].length;
+ }
+
+ return nents;
+}
+
+static void ibmebus_unmap_sg(struct device *dev,
+ struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+{
+ return;
+}
+
+static int ibmebus_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+struct dma_mapping_ops ibmebus_dma_ops = {
+ .alloc_coherent = ibmebus_alloc_coherent,
+ .free_coherent = ibmebus_free_coherent,
+ .map_single = ibmebus_map_single,
+ .unmap_single = ibmebus_unmap_single,
+ .map_sg = ibmebus_map_sg,
+ .unmap_sg = ibmebus_unmap_sg,
+ .dma_supported = ibmebus_dma_supported,
+};
+
+static int ibmebus_bus_probe(struct device *dev)
+{
+ struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
+ struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
+ const struct of_device_id *id;
+ int error = -ENODEV;
+
+ if (!ibmebusdrv->probe)
+ return error;
+
+ id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev);
+ if (id) {
+ error = ibmebusdrv->probe(ibmebusdev, id);
+ }
+
+ return error;
+}
+
+static int ibmebus_bus_remove(struct device *dev)
+{
+ struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev);
+ struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver);
+
+ if (ibmebusdrv->remove) {
+ return ibmebusdrv->remove(ibmebusdev);
+ }
+
+ return 0;
+}
+
+static void __devinit ibmebus_dev_release(struct device *dev)
+{
+ of_node_put(to_ibmebus_dev(dev)->ofdev.node);
+ kfree(to_ibmebus_dev(dev));
+}
+
+static ssize_t ibmebusdev_show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name);
+}
+static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name,
+ NULL);
+
+static struct ibmebus_dev* __devinit ibmebus_register_device_common(
+ struct ibmebus_dev *dev, char *name)
+{
+ int err = 0;
+
+ dev->name = name;
+ dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev;
+ dev->ofdev.dev.bus = &ibmebus_bus_type;
+ dev->ofdev.dev.release = ibmebus_dev_release;
+
+ /* An ibmebusdev is based on a of_device. We have to change the
+ * bus type to use our own DMA mapping operations.
+ */
+ if ((err = of_device_register(&dev->ofdev)) != 0) {
+ printk(KERN_ERR "%s: failed to register device (%d).\n",
+ __FUNCTION__, err);
+ return NULL;
+ }
+
+ device_create_file(&dev->ofdev.dev, &dev_attr_name);
+
+ return dev;
+}
+
+static struct ibmebus_dev* __devinit ibmebus_register_device_node(
+ struct device_node *dn)
+{
+ struct ibmebus_dev *dev;
+ char *loc_code;
+ int length;
+
+ loc_code = (char *)get_property(dn, "ibm,loc-code", NULL);
+ if (!loc_code) {
+ printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
+ __FUNCTION__, dn->name ? dn->name : "<unknown>");
+ return NULL;
+ }
+
+ if (strlen(loc_code) == 0) {
+ printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n",
+ __FUNCTION__);
+ return NULL;
+ }
+
+ dev = kmalloc(sizeof(struct ibmebus_dev), GFP_KERNEL);
+ if (!dev) {
+ return NULL;
+ }
+ memset(dev, 0, sizeof(struct ibmebus_dev));
+
+ dev->ofdev.node = of_node_get(dn);
+
+ length = strlen(loc_code);
+ memcpy(dev->ofdev.dev.bus_id, loc_code
+ + (length - min(length, BUS_ID_SIZE - 1)),
+ min(length, BUS_ID_SIZE - 1));
+
+ /* Register with generic device framework. */
+ if (ibmebus_register_device_common(dev, dn->name) == NULL) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+
+static void ibmebus_probe_of_nodes(char* name)
+{
+ struct device_node *dn = NULL;
+
+ while ((dn = of_find_node_by_name(dn, name))) {
+ if (ibmebus_register_device_node(dn) == NULL) {
+ of_node_put(dn);
+
+ return;
+ }
+ }
+
+ of_node_put(dn);
+
+ return;
+}
+
+static void ibmebus_add_devices_by_id(struct of_device_id *idt)
+{
+ while (strlen(idt->name) > 0) {
+ ibmebus_probe_of_nodes(idt->name);
+ idt++;
+ }
+
+ return;
+}
+
+static int ibmebus_match_helper(struct device *dev, void *data)
+{
+ if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0)
+ return 1;
+
+ return 0;
+}
+
+static int ibmebus_unregister_device(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_name);
+ of_device_unregister(to_of_device(dev));
+
+ return 0;
+}
+
+static void ibmebus_remove_devices_by_id(struct of_device_id *idt)
+{
+ struct device *dev;
+
+ while (strlen(idt->name) > 0) {
+ while ((dev = bus_find_device(&ibmebus_bus_type, NULL,
+ (void*)idt->name,
+ ibmebus_match_helper))) {
+ ibmebus_unregister_device(dev);
+ }
+ idt++;
+
+ }
+
+ return;
+}
+
+int ibmebus_register_driver(struct ibmebus_driver *drv)
+{
+ int err = 0;
+
+ drv->driver.name = drv->name;
+ drv->driver.bus = &ibmebus_bus_type;
+ drv->driver.probe = ibmebus_bus_probe;
+ drv->driver.remove = ibmebus_bus_remove;
+
+ if ((err = driver_register(&drv->driver) != 0))
+ return err;
+
+ ibmebus_add_devices_by_id(drv->id_table);
+
+ return 0;
+}
+EXPORT_SYMBOL(ibmebus_register_driver);
+
+void ibmebus_unregister_driver(struct ibmebus_driver *drv)
+{
+ driver_unregister(&drv->driver);
+ ibmebus_remove_devices_by_id(drv->id_table);
+}
+EXPORT_SYMBOL(ibmebus_unregister_driver);
+
+int ibmebus_request_irq(struct ibmebus_dev *dev,
+ u32 ist,
+ irqreturn_t (*handler)(int, void*, struct pt_regs *),
+ unsigned long irq_flags, const char * devname,
+ void *dev_id)
+{
+ unsigned int irq = virt_irq_create_mapping(ist);
+
+ if (irq == NO_IRQ)
+ return -EINVAL;
+
+ irq = irq_offset_up(irq);
+
+ return request_irq(irq, handler,
+ irq_flags, devname, dev_id);
+}
+EXPORT_SYMBOL(ibmebus_request_irq);
+
+void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id)
+{
+ unsigned int irq = virt_irq_create_mapping(ist);
+
+ irq = irq_offset_up(irq);
+ free_irq(irq, dev_id);
+
+ return;
+}
+EXPORT_SYMBOL(ibmebus_free_irq);
+
+static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
+{
+ const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev);
+ struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv);
+ const struct of_device_id *ids = ebus_drv->id_table;
+ const struct of_device_id *found_id;
+
+ if (!ids)
+ return 0;
+
+ found_id = of_match_device(ids, &ebus_dev->ofdev);
+ if (found_id)
+ return 1;
+
+ return 0;
+}
+
+struct bus_type ibmebus_bus_type = {
+ .name = "ibmebus",
+ .match = ibmebus_bus_match,
+};
+EXPORT_SYMBOL(ibmebus_bus_type);
+
+static int __init ibmebus_bus_init(void)
+{
+ int err;
+
+ printk(KERN_INFO "IBM eBus Device Driver\n");
+
+ err = bus_register(&ibmebus_bus_type);
+ if (err) {
+ printk(KERN_ERR ":%s: failed to register IBM eBus.\n",
+ __FUNCTION__);
+ return err;
+ }
+
+ err = device_register(&ibmebus_bus_device.ofdev.dev);
+ if (err) {
+ printk(KERN_WARNING "%s: device_register returned %i\n",
+ __FUNCTION__, err);
+ bus_unregister(&ibmebus_bus_type);
+
+ return err;
+ }
+
+ return 0;
+}
+__initcall(ibmebus_bus_init);
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 1494e2f177f7..c16b4afab582 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -38,14 +38,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
/* We must dynamically check for the NAP feature as it
* can be cleared by CPU init after the fixups are done
*/
- LOADBASE(r3,cur_cpu_spec)
- ld r4,OFF(cur_cpu_spec)(r3)
+ LOAD_REG_ADDRBASE(r3,cur_cpu_spec)
+ ld r4,ADDROFF(cur_cpu_spec)(r3)
ld r4,CPU_SPEC_FEATURES(r4)
andi. r0,r4,CPU_FTR_CAN_NAP
beqlr
/* Now check if user or arch enabled NAP mode */
- LOADBASE(r3,powersave_nap)
- lwz r4,OFF(powersave_nap)(r3)
+ LOAD_REG_ADDRBASE(r3,powersave_nap)
+ lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
diff --git a/arch/powerpc/kernel/ioctl32.c b/arch/powerpc/kernel/ioctl32.c
deleted file mode 100644
index 0fa3d27fef01..000000000000
--- a/arch/powerpc/kernel/ioctl32.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Based on sparc64 ioctl32.c by:
- *
- * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- *
- * ppc64 changes:
- *
- * Copyright (C) 2000 Ken Aaker (kdaaker@rchland.vnet.ibm.com)
- * Copyright (C) 2001 Anton Blanchard (antonb@au.ibm.com)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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 INCLUDES
-#include "compat_ioctl.c"
-#include <linux/syscalls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
-
-#define IOCTL_TABLE_START \
- struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
- };
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5a71ed9612fe..d1fffce86df9 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -31,7 +31,6 @@
* to reduce code space and undefined function references.
*/
-#include <linux/errno.h>
#include <linux/module.h>
#include <linux/threads.h>
#include <linux/kernel_stat.h>
@@ -44,18 +43,12 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/irq.h>
-#include <linux/proc_fs.h>
-#include <linux/random.h>
#include <linux/seq_file.h>
#include <linux/cpumask.h>
#include <linux/profile.h>
#include <linux/bitops.h>
-#ifdef CONFIG_PPC64
-#include <linux/kallsyms.h>
-#endif
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -66,8 +59,7 @@
#include <asm/prom.h>
#include <asm/ptrace.h>
#include <asm/machdep.h>
-#ifdef CONFIG_PPC64
-#include <asm/iseries/it_lp_queue.h>
+#ifdef CONFIG_PPC_ISERIES
#include <asm/paca.h>
#endif
@@ -78,10 +70,6 @@ EXPORT_SYMBOL(__irq_offset_value);
static int ppc_spurious_interrupts;
-#if defined(CONFIG_PPC_ISERIES) && defined(CONFIG_SMP)
-extern void iSeries_smp_message_recv(struct pt_regs *);
-#endif
-
#ifdef CONFIG_PPC32
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
@@ -195,49 +183,6 @@ void fixup_irqs(cpumask_t map)
}
#endif
-#ifdef CONFIG_PPC_ISERIES
-void do_IRQ(struct pt_regs *regs)
-{
- struct paca_struct *lpaca;
-
- irq_enter();
-
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
- /* Debugging check for stack overflow: is there less than 2KB free? */
- {
- long sp;
-
- sp = __get_SP() & (THREAD_SIZE-1);
-
- if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
- printk("do_IRQ: stack overflow: %ld\n",
- sp - sizeof(struct thread_info));
- dump_stack();
- }
- }
-#endif
-
- lpaca = get_paca();
-#ifdef CONFIG_SMP
- if (lpaca->lppaca.int_dword.fields.ipi_cnt) {
- lpaca->lppaca.int_dword.fields.ipi_cnt = 0;
- iSeries_smp_message_recv(regs);
- }
-#endif /* CONFIG_SMP */
- if (hvlpevent_is_pending())
- process_hvlpevents(regs);
-
- irq_exit();
-
- if (lpaca->lppaca.int_dword.fields.decr_int) {
- lpaca->lppaca.int_dword.fields.decr_int = 0;
- /* Signal a fake decrementer interrupt */
- timer_interrupt(regs);
- }
-}
-
-#else /* CONFIG_PPC_ISERIES */
-
void do_IRQ(struct pt_regs *regs)
{
int irq;
@@ -286,16 +231,20 @@ void do_IRQ(struct pt_regs *regs)
} else
#endif
__do_IRQ(irq, regs);
- } else
-#ifdef CONFIG_PPC32
- if (irq != -2)
-#endif
- /* That's not SMP safe ... but who cares ? */
- ppc_spurious_interrupts++;
+ } else if (irq != -2)
+ /* That's not SMP safe ... but who cares ? */
+ ppc_spurious_interrupts++;
+
irq_exit();
-}
-#endif /* CONFIG_PPC_ISERIES */
+#ifdef CONFIG_PPC_ISERIES
+ if (get_lppaca()->int_dword.fields.decr_int) {
+ get_lppaca()->int_dword.fields.decr_int = 0;
+ /* Signal a fake decrementer interrupt */
+ timer_interrupt(regs);
+ }
+#endif
+}
void __init init_IRQ(void)
{
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 5368f9c2e6bf..cfab48566db1 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -35,7 +35,6 @@
#include <asm/kdebug.h>
#include <asm/sstep.h>
-static DECLARE_MUTEX(kprobe_mutex);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -54,19 +53,17 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
/* insn must be on a special executable page on ppc64 */
if (!ret) {
- down(&kprobe_mutex);
p->ainsn.insn = get_insn_slot();
- up(&kprobe_mutex);
if (!p->ainsn.insn)
ret = -ENOMEM;
}
- return ret;
-}
-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;
+ if (!ret) {
+ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
+ }
+
+ return ret;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -182,6 +179,18 @@ static inline int kprobe_handler(struct pt_regs *regs)
kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /* If trap variant, then it belongs not to us */
+ kprobe_opcode_t cur_insn = *addr;
+ if (is_trap(cur_insn))
+ goto no_kprobe;
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ ret = 1;
+ goto no_kprobe;
+ }
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
new file mode 100644
index 000000000000..f970ace208d3
--- /dev/null
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -0,0 +1,557 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_core.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/prom.h>
+#include <asm/serial.h>
+#include <asm/udbg.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+#define MAX_LEGACY_SERIAL_PORTS 8
+
+static struct plat_serial8250_port
+legacy_serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
+static struct legacy_serial_info {
+ struct device_node *np;
+ unsigned int speed;
+ unsigned int clock;
+ phys_addr_t taddr;
+} legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS];
+static unsigned int legacy_serial_count;
+static int legacy_serial_console = -1;
+
+static int __init add_legacy_port(struct device_node *np, int want_index,
+ int iotype, phys_addr_t base,
+ phys_addr_t taddr, unsigned long irq,
+ unsigned int flags)
+{
+ u32 *clk, *spd, clock = BASE_BAUD * 16;
+ int index;
+
+ /* get clock freq. if present */
+ clk = (u32 *)get_property(np, "clock-frequency", NULL);
+ if (clk && *clk)
+ clock = *clk;
+
+ /* get default speed if present */
+ spd = (u32 *)get_property(np, "current-speed", NULL);
+
+ /* If we have a location index, then try to use it */
+ if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
+ index = want_index;
+ else
+ index = legacy_serial_count;
+
+ /* if our index is still out of range, that mean that
+ * array is full, we could scan for a free slot but that
+ * make little sense to bother, just skip the port
+ */
+ if (index >= MAX_LEGACY_SERIAL_PORTS)
+ return -1;
+ if (index >= legacy_serial_count)
+ legacy_serial_count = index + 1;
+
+ /* Check if there is a port who already claimed our slot */
+ if (legacy_serial_infos[index].np != 0) {
+ /* if we still have some room, move it, else override */
+ if (legacy_serial_count < MAX_LEGACY_SERIAL_PORTS) {
+ printk(KERN_INFO "Moved legacy port %d -> %d\n",
+ index, legacy_serial_count);
+ legacy_serial_ports[legacy_serial_count] =
+ legacy_serial_ports[index];
+ legacy_serial_infos[legacy_serial_count] =
+ legacy_serial_infos[index];
+ legacy_serial_count++;
+ } else {
+ printk(KERN_INFO "Replacing legacy port %d\n", index);
+ }
+ }
+
+ /* Now fill the entry */
+ memset(&legacy_serial_ports[index], 0,
+ sizeof(struct plat_serial8250_port));
+ if (iotype == UPIO_PORT)
+ legacy_serial_ports[index].iobase = base;
+ else
+ legacy_serial_ports[index].mapbase = base;
+ legacy_serial_ports[index].iotype = iotype;
+ legacy_serial_ports[index].uartclk = clock;
+ legacy_serial_ports[index].irq = irq;
+ legacy_serial_ports[index].flags = flags;
+ legacy_serial_infos[index].taddr = taddr;
+ legacy_serial_infos[index].np = of_node_get(np);
+ legacy_serial_infos[index].clock = clock;
+ legacy_serial_infos[index].speed = spd ? *spd : 0;
+
+ printk(KERN_INFO "Found legacy serial port %d for %s\n",
+ index, np->full_name);
+ printk(KERN_INFO " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n",
+ (iotype == UPIO_PORT) ? "port" : "mem",
+ (unsigned long long)base, (unsigned long long)taddr, irq,
+ legacy_serial_ports[index].uartclk,
+ legacy_serial_infos[index].speed);
+
+ return index;
+}
+
+static int __init add_legacy_soc_port(struct device_node *np,
+ struct device_node *soc_dev)
+{
+ phys_addr_t addr;
+ u32 *addrp;
+ unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+
+ /* We only support ports that have a clock frequency properly
+ * encoded in the device-tree.
+ */
+ if (get_property(np, "clock-frequency", NULL) == NULL)
+ return -1;
+
+ /* Get the address */
+ addrp = of_get_address(soc_dev, 0, NULL, NULL);
+ if (addrp == NULL)
+ return -1;
+
+ addr = of_translate_address(soc_dev, addrp);
+
+ /* Add port, irq will be dealt with later. We passed a translated
+ * IO port value. It will be fixed up later along with the irq
+ */
+ return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags);
+}
+
+#ifdef CONFIG_ISA
+static int __init add_legacy_isa_port(struct device_node *np,
+ struct device_node *isa_brg)
+{
+ u32 *reg;
+ char *typep;
+ int index = -1;
+ phys_addr_t taddr;
+
+ /* Get the ISA port number */
+ reg = (u32 *)get_property(np, "reg", NULL);
+ if (reg == NULL)
+ return -1;
+
+ /* Verify it's an IO port, we don't support anything else */
+ if (!(reg[0] & 0x00000001))
+ return -1;
+
+ /* Now look for an "ibm,aix-loc" property that gives us ordering
+ * if any...
+ */
+ typep = (char *)get_property(np, "ibm,aix-loc", NULL);
+
+ /* If we have a location index, then use it */
+ if (typep && *typep == 'S')
+ index = simple_strtol(typep+1, NULL, 0) - 1;
+
+ /* Translate ISA address */
+ taddr = of_translate_address(np, reg);
+
+ /* Add port, irq will be dealt with later */
+ return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF);
+
+}
+#endif
+
+#ifdef CONFIG_PCI
+static int __init add_legacy_pci_port(struct device_node *np,
+ struct device_node *pci_dev)
+{
+ phys_addr_t addr, base;
+ u32 *addrp;
+ unsigned int flags;
+ int iotype, index = -1, lindex = 0;
+
+ /* We only support ports that have a clock frequency properly
+ * encoded in the device-tree (that is have an fcode). Anything
+ * else can't be used that early and will be normally probed by
+ * the generic 8250_pci driver later on. The reason is that 8250
+ * compatible UARTs on PCI need all sort of quirks (port offsets
+ * etc...) that this code doesn't know about
+ */
+ if (get_property(np, "clock-frequency", NULL) == NULL)
+ return -1;
+
+ /* Get the PCI address. Assume BAR 0 */
+ addrp = of_get_pci_address(pci_dev, 0, NULL, &flags);
+ if (addrp == NULL)
+ return -1;
+
+ /* We only support BAR 0 for now */
+ iotype = (flags & IORESOURCE_MEM) ? UPIO_MEM : UPIO_PORT;
+ addr = of_translate_address(pci_dev, addrp);
+
+ /* Set the IO base to the same as the translated address for MMIO,
+ * or to the domain local IO base for PIO (it will be fixed up later)
+ */
+ if (iotype == UPIO_MEM)
+ base = addr;
+ else
+ base = addrp[2];
+
+ /* Try to guess an index... If we have subdevices of the pci dev,
+ * we get to their "reg" property
+ */
+ if (np != pci_dev) {
+ u32 *reg = (u32 *)get_property(np, "reg", NULL);
+ if (reg && (*reg < 4))
+ index = lindex = *reg;
+ }
+
+ /* Local index means it's the Nth port in the PCI chip. Unfortunately
+ * the offset to add here is device specific. We know about those
+ * EXAR ports and we default to the most common case. If your UART
+ * doesn't work for these settings, you'll have to add your own special
+ * cases here
+ */
+ if (device_is_compatible(pci_dev, "pci13a8,152") ||
+ device_is_compatible(pci_dev, "pci13a8,154") ||
+ device_is_compatible(pci_dev, "pci13a8,158")) {
+ addr += 0x200 * lindex;
+ base += 0x200 * lindex;
+ } else {
+ addr += 8 * lindex;
+ base += 8 * lindex;
+ }
+
+ /* Add port, irq will be dealt with later. We passed a translated
+ * IO port value. It will be fixed up later along with the irq
+ */
+ return add_legacy_port(np, index, iotype, base, addr, NO_IRQ, UPF_BOOT_AUTOCONF);
+}
+#endif
+
+/*
+ * This is called very early, as part of setup_system() or eventually
+ * setup_arch(), basically before anything else in this file. This function
+ * will try to build a list of all the available 8250-compatible serial ports
+ * in the machine using the Open Firmware device-tree. It currently only deals
+ * with ISA and PCI busses but could be extended. It allows a very early boot
+ * console to be initialized, that list is also used later to provide 8250 with
+ * the machine non-PCI ports and to properly pick the default console port
+ */
+void __init find_legacy_serial_ports(void)
+{
+ struct device_node *np, *stdout = NULL;
+ char *path;
+ int index;
+
+ DBG(" -> find_legacy_serial_port()\n");
+
+ /* Now find out if one of these is out firmware console */
+ path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+ if (path != NULL) {
+ stdout = of_find_node_by_path(path);
+ if (stdout)
+ DBG("stdout is %s\n", stdout->full_name);
+ } else {
+ DBG(" no linux,stdout-path !\n");
+ }
+
+ /* First fill our array with SOC ports */
+ for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) {
+ struct device_node *soc = of_get_parent(np);
+ if (soc && !strcmp(soc->type, "soc")) {
+ index = add_legacy_soc_port(np, np);
+ if (index >= 0 && np == stdout)
+ legacy_serial_console = index;
+ }
+ of_node_put(soc);
+ }
+
+#ifdef CONFIG_ISA
+ /* First fill our array with ISA ports */
+ for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
+ struct device_node *isa = of_get_parent(np);
+ if (isa && !strcmp(isa->name, "isa")) {
+ index = add_legacy_isa_port(np, isa);
+ if (index >= 0 && np == stdout)
+ legacy_serial_console = index;
+ }
+ of_node_put(isa);
+ }
+#endif
+
+#ifdef CONFIG_PCI
+ /* Next, try to locate PCI ports */
+ for (np = NULL; (np = of_find_all_nodes(np));) {
+ struct device_node *pci, *parent = of_get_parent(np);
+ if (parent && !strcmp(parent->name, "isa")) {
+ of_node_put(parent);
+ continue;
+ }
+ if (strcmp(np->name, "serial") && strcmp(np->type, "serial")) {
+ of_node_put(parent);
+ continue;
+ }
+ /* Check for known pciclass, and also check wether we have
+ * a device with child nodes for ports or not
+ */
+ if (device_is_compatible(np, "pciclass,0700") ||
+ device_is_compatible(np, "pciclass,070002"))
+ pci = np;
+ else if (device_is_compatible(parent, "pciclass,0700") ||
+ device_is_compatible(parent, "pciclass,070002"))
+ pci = parent;
+ else {
+ of_node_put(parent);
+ continue;
+ }
+ index = add_legacy_pci_port(np, pci);
+ if (index >= 0 && np == stdout)
+ legacy_serial_console = index;
+ of_node_put(parent);
+ }
+#endif
+
+ DBG("legacy_serial_console = %d\n", legacy_serial_console);
+
+ /* udbg is 64 bits only for now, that will change soon though ... */
+ while (legacy_serial_console >= 0) {
+ struct legacy_serial_info *info =
+ &legacy_serial_infos[legacy_serial_console];
+ void __iomem *addr;
+
+ if (info->taddr == 0)
+ break;
+ addr = ioremap(info->taddr, 0x1000);
+ if (addr == NULL)
+ break;
+ if (info->speed == 0)
+ info->speed = udbg_probe_uart_speed(addr, info->clock);
+ DBG("default console speed = %d\n", info->speed);
+ udbg_init_uart(addr, info->speed, info->clock);
+ break;
+ }
+
+ DBG(" <- find_legacy_serial_port()\n");
+}
+
+static struct platform_device serial_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = legacy_serial_ports,
+ },
+};
+
+static void __init fixup_port_irq(int index,
+ struct device_node *np,
+ struct plat_serial8250_port *port)
+{
+ DBG("fixup_port_irq(%d)\n", index);
+
+ /* Check for interrupts in that node */
+ if (np->n_intrs > 0) {
+ port->irq = np->intrs[0].line;
+ DBG(" port %d (%s), irq=%d\n",
+ index, np->full_name, port->irq);
+ return;
+ }
+
+ /* Check for interrupts in the parent */
+ np = of_get_parent(np);
+ if (np == NULL)
+ return;
+
+ if (np->n_intrs > 0) {
+ port->irq = np->intrs[0].line;
+ DBG(" port %d (%s), irq=%d\n",
+ index, np->full_name, port->irq);
+ }
+ of_node_put(np);
+}
+
+static void __init fixup_port_pio(int index,
+ struct device_node *np,
+ struct plat_serial8250_port *port)
+{
+#ifdef CONFIG_PCI
+ struct pci_controller *hose;
+
+ DBG("fixup_port_pio(%d)\n", index);
+
+ hose = pci_find_hose_for_OF_device(np);
+ if (hose) {
+ unsigned long offset = (unsigned long)hose->io_base_virt -
+#ifdef CONFIG_PPC64
+ pci_io_base;
+#else
+ isa_io_base;
+#endif
+ DBG("port %d, IO %lx -> %lx\n",
+ index, port->iobase, port->iobase + offset);
+ port->iobase += offset;
+ }
+#endif
+}
+
+static void __init fixup_port_mmio(int index,
+ struct device_node *np,
+ struct plat_serial8250_port *port)
+{
+ DBG("fixup_port_mmio(%d)\n", index);
+
+ port->membase = ioremap(port->mapbase, 0x100);
+}
+
+/*
+ * This is called as an arch initcall, hopefully before the PCI bus is
+ * probed and/or the 8250 driver loaded since we need to register our
+ * platform devices before 8250 PCI ones are detected as some of them
+ * must properly "override" the platform ones.
+ *
+ * This function fixes up the interrupt value for platform ports as it
+ * couldn't be done earlier before interrupt maps have been parsed. It
+ * also "corrects" the IO address for PIO ports for the same reason,
+ * since earlier, the PHBs virtual IO space wasn't assigned yet. It then
+ * registers all those platform ports for use by the 8250 driver when it
+ * finally loads.
+ */
+static int __init serial_dev_init(void)
+{
+ int i;
+
+ if (legacy_serial_count == 0)
+ return -ENODEV;
+
+ /*
+ * Before we register the platfrom serial devices, we need
+ * to fixup their interrutps and their IO ports.
+ */
+ DBG("Fixing serial ports interrupts and IO ports ...\n");
+
+ for (i = 0; i < legacy_serial_count; i++) {
+ struct plat_serial8250_port *port = &legacy_serial_ports[i];
+ struct device_node *np = legacy_serial_infos[i].np;
+
+ if (port->irq == NO_IRQ)
+ fixup_port_irq(i, np, port);
+ if (port->iotype == UPIO_PORT)
+ fixup_port_pio(i, np, port);
+ if (port->iotype == UPIO_MEM)
+ fixup_port_mmio(i, np, port);
+ }
+
+ DBG("Registering platform serial ports\n");
+
+ return platform_device_register(&serial_device);
+}
+arch_initcall(serial_dev_init);
+
+
+/*
+ * This is called very early, as part of console_init() (typically just after
+ * time_init()). This function is respondible for trying to find a good
+ * default console on serial ports. It tries to match the open firmware
+ * default output with one of the available serial console drivers, either
+ * one of the platform serial ports that have been probed earlier by
+ * find_legacy_serial_ports() or some more platform specific ones.
+ */
+static int __init check_legacy_serial_console(void)
+{
+ struct device_node *prom_stdout = NULL;
+ int speed = 0, offset = 0;
+ char *name;
+ u32 *spd;
+
+ DBG(" -> check_legacy_serial_console()\n");
+
+ /* The user has requested a console so this is already set up. */
+ if (strstr(saved_command_line, "console=")) {
+ DBG(" console was specified !\n");
+ return -EBUSY;
+ }
+
+ if (!of_chosen) {
+ DBG(" of_chosen is NULL !\n");
+ return -ENODEV;
+ }
+
+ if (legacy_serial_console < 0) {
+ DBG(" legacy_serial_console not found !\n");
+ return -ENODEV;
+ }
+ /* We are getting a weird phandle from OF ... */
+ /* ... So use the full path instead */
+ name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+ if (name == NULL) {
+ DBG(" no linux,stdout-path !\n");
+ return -ENODEV;
+ }
+ prom_stdout = of_find_node_by_path(name);
+ if (!prom_stdout) {
+ DBG(" can't find stdout package %s !\n", name);
+ return -ENODEV;
+ }
+ DBG("stdout is %s\n", prom_stdout->full_name);
+
+ name = (char *)get_property(prom_stdout, "name", NULL);
+ if (!name) {
+ DBG(" stdout package has no name !\n");
+ goto not_found;
+ }
+ spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
+ if (spd)
+ speed = *spd;
+
+ if (0)
+ ;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ else if (strcmp(name, "serial") == 0) {
+ int i;
+ /* Look for it in probed array */
+ for (i = 0; i < legacy_serial_count; i++) {
+ if (prom_stdout != legacy_serial_infos[i].np)
+ continue;
+ offset = i;
+ speed = legacy_serial_infos[i].speed;
+ break;
+ }
+ if (i >= legacy_serial_count)
+ goto not_found;
+ }
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
+ else if (strcmp(name, "ch-a") == 0)
+ offset = 0;
+ else if (strcmp(name, "ch-b") == 0)
+ offset = 1;
+#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
+ else
+ goto not_found;
+ of_node_put(prom_stdout);
+
+ DBG("Found serial console at ttyS%d\n", offset);
+
+ if (speed) {
+ static char __initdata opt[16];
+ sprintf(opt, "%d", speed);
+ return add_preferred_console("ttyS", offset, opt);
+ } else
+ return add_preferred_console("ttyS", offset, NULL);
+
+ not_found:
+ DBG("No preferred console found !\n");
+ of_node_put(prom_stdout);
+ return -ENODEV;
+}
+console_initcall(check_legacy_serial_console);
+
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 9dda16ccde78..1ae96a8ed7e2 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -55,15 +55,13 @@ static unsigned long get_purr(void)
{
unsigned long sum_purr = 0;
int cpu;
- struct paca_struct *lpaca;
for_each_cpu(cpu) {
- lpaca = paca + cpu;
- sum_purr += lpaca->lppaca.emulated_time_base;
+ sum_purr += lppaca[cpu].emulated_time_base;
#ifdef PURR_DEBUG
printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
- cpu, lpaca->lppaca.emulated_time_base);
+ cpu, lppaca[cpu].emulated_time_base);
#endif
}
return sum_purr;
@@ -79,12 +77,11 @@ static int lparcfg_data(struct seq_file *m, void *v)
unsigned long pool_id, lp_index;
int shared, entitled_capacity, max_entitled_capacity;
int processors, max_processors;
- struct paca_struct *lpaca = get_paca();
unsigned long purr = get_purr();
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
- shared = (int)(lpaca->lppaca_ptr->shared_proc);
+ shared = (int)(get_lppaca()->shared_proc);
seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
e2a(xItExtVpdPanel.mfgID[2]),
e2a(xItExtVpdPanel.mfgID[3]),
@@ -402,7 +399,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
(h_resource >> 0 * 8) & 0xffff);
/* pool related entries are apropriate for shared configs */
- if (paca[0].lppaca.shared_proc) {
+ if (lppaca[0].shared_proc) {
h_pic(&pool_idle_time, &pool_procs);
@@ -451,7 +448,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
seq_printf(m, "partition_potential_processors=%d\n",
partition_potential_processors);
- seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.shared_proc);
+ seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc);
return 0;
}
diff --git a/arch/powerpc/kernel/lparmap.c b/arch/powerpc/kernel/lparmap.c
index 5a05a797485f..584d1e3c013d 100644
--- a/arch/powerpc/kernel/lparmap.c
+++ b/arch/powerpc/kernel/lparmap.c
@@ -7,7 +7,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <asm/mmu.h>
-#include <asm/page.h>
+#include <asm/pgtable.h>
#include <asm/iseries/lpar_map.h>
const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
@@ -16,16 +16,16 @@ const struct LparMap __attribute__((__section__(".text"))) xLparMap = {
.xSegmentTableOffs = STAB0_PAGE,
.xEsids = {
- { .xKernelEsid = GET_ESID(KERNELBASE),
- .xKernelVsid = KERNEL_VSID(KERNELBASE), },
- { .xKernelEsid = GET_ESID(VMALLOCBASE),
- .xKernelVsid = KERNEL_VSID(VMALLOCBASE), },
+ { .xKernelEsid = GET_ESID(PAGE_OFFSET),
+ .xKernelVsid = KERNEL_VSID(PAGE_OFFSET), },
+ { .xKernelEsid = GET_ESID(VMALLOC_START),
+ .xKernelVsid = KERNEL_VSID(VMALLOC_START), },
},
.xRanges = {
{ .xPages = HvPagesToMap,
.xOffset = 0,
- .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - HW_PAGE_SHIFT),
+ .xVPN = KERNEL_VSID(PAGE_OFFSET) << (SID_SHIFT - HW_PAGE_SHIFT),
},
},
};
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
new file mode 100644
index 000000000000..a81ca1b841ec
--- /dev/null
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -0,0 +1,61 @@
+/*
+ * Code to handle transition of Linux booting another kernel.
+ *
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * Copyright (C) 2005 IBM Corporation.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kexec.h>
+#include <linux/reboot.h>
+#include <linux/threads.h>
+#include <asm/machdep.h>
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ if (ppc_md.machine_crash_shutdown)
+ ppc_md.machine_crash_shutdown(regs);
+}
+
+/*
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ if (ppc_md.machine_kexec_prepare)
+ return ppc_md.machine_kexec_prepare(image);
+ /*
+ * Fail if platform doesn't provide its own machine_kexec_prepare
+ * implementation.
+ */
+ return -ENOSYS;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+ if (ppc_md.machine_kexec_cleanup)
+ ppc_md.machine_kexec_cleanup(image);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ if (ppc_md.machine_kexec)
+ ppc_md.machine_kexec(image);
+ else {
+ /*
+ * Fall back to normal restart if platform doesn't provide
+ * its own kexec function, and user insist to kexec...
+ */
+ machine_restart(NULL);
+ }
+ for(;;);
+}
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
new file mode 100644
index 000000000000..443606134dff
--- /dev/null
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -0,0 +1,65 @@
+/*
+ * PPC32 code to handle Linux booting another kernel.
+ *
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * Copyright (C) 2005 IBM Corporation.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/kexec.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/cacheflush.h>
+#include <asm/hw_irq.h>
+#include <asm/io.h>
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address) ATTRIB_NORET;
+
+/*
+ * This is a generic machine_kexec function suitable at least for
+ * non-OpenFirmware embedded platforms.
+ * It merely copies the image relocation code to the control page and
+ * jumps to it.
+ * A platform specific function may just call this one.
+ */
+void default_machine_kexec(struct kimage *image)
+{
+ const extern unsigned char relocate_new_kernel[];
+ const extern unsigned int relocate_new_kernel_size;
+ unsigned long page_list;
+ unsigned long reboot_code_buffer, reboot_code_buffer_phys;
+ relocate_new_kernel_t rnk;
+
+ /* Interrupts aren't acceptable while we reboot */
+ local_irq_disable();
+
+ page_list = image->head;
+
+ /* we need both effective and real address here */
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
+ reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
+
+ /* copy our kernel relocation code to the control code page */
+ memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ flush_icache_range(reboot_code_buffer,
+ reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+ printk(KERN_INFO "Bye!\n");
+
+ /* now call it */
+ rnk = (relocate_new_kernel_t) reboot_code_buffer;
+ (*rnk)(page_list, reboot_code_buffer_phys, image->start);
+}
+
+int default_machine_kexec_prepare(struct kimage *image)
+{
+ return 0;
+}
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 97c51e452be7..d6431440c54f 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -1,5 +1,5 @@
/*
- * machine_kexec.c - handle transition of Linux booting another kernel
+ * PPC64 code to handle Linux booting another kernel.
*
* Copyright (C) 2004-2005, IBM Corp.
*
@@ -28,21 +28,7 @@
#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */
-/* Have this around till we move it into crash specific file */
-note_buf_t crash_notes[NR_CPUS];
-
-/* Dummy for now. Not sure if we need to have a crash shutdown in here
- * and if what it will achieve. Letting it be now to compile the code
- * in generic kexec environment
- */
-void machine_crash_shutdown(struct pt_regs *regs)
-{
- /* do nothing right now */
- /* smp_relase_cpus() if we want smp on panic kernel */
- /* cpu_irq_down to isolate us until we are ready */
-}
-
-int machine_kexec_prepare(struct kimage *image)
+int default_machine_kexec_prepare(struct kimage *image)
{
int i;
unsigned long begin, end; /* limits of segment */
@@ -111,11 +97,6 @@ int machine_kexec_prepare(struct kimage *image)
return 0;
}
-void machine_kexec_cleanup(struct kimage *image)
-{
- /* we do nothing in prepare that needs to be undone */
-}
-
#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
static void copy_segments(unsigned long ind)
@@ -172,9 +153,8 @@ void kexec_copy_flush(struct kimage *image)
* including ones that were in place on the original copy
*/
for (i = 0; i < nr_segments; i++)
- flush_icache_range(ranges[i].mem + KERNELBASE,
- ranges[i].mem + KERNELBASE +
- ranges[i].memsz);
+ flush_icache_range((unsigned long)__va(ranges[i].mem),
+ (unsigned long)__va(ranges[i].mem + ranges[i].memsz));
}
#ifdef CONFIG_SMP
@@ -283,13 +263,20 @@ extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
void (*clear_all)(void)) ATTRIB_NORET;
/* too late to fail here */
-void machine_kexec(struct kimage *image)
+void default_machine_kexec(struct kimage *image)
{
-
/* prepare control code if any */
- /* shutdown other cpus into our wait loop and quiesce interrupts */
- kexec_prepare_cpus();
+ /*
+ * If the kexec boot is the normal one, need to shutdown other cpus
+ * into our wait loop and quiesce interrupts.
+ * Otherwise, in the case of crashed mode (crashing_cpu >= 0),
+ * stopping other CPUs and collecting their pt_regs is done before
+ * using debugger IPI.
+ */
+
+ if (crashing_cpu == -1)
+ kexec_prepare_cpus();
/* switch to a staticly allocated stack. Based on irq stack code.
* XXX: the task struct will likely be invalid once we do the copy!
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 624a983a9676..be982023409e 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -5,6 +5,10 @@
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
*
+ * kexec bits:
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -24,6 +28,8 @@
#include <asm/ppc_asm.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
+#include <asm/processor.h>
+#include <asm/kexec.h>
.text
@@ -62,7 +68,7 @@ _GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
- LOADADDR(r4,1b)
+ LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
@@ -74,7 +80,7 @@ _GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
- LOADADDR(r4,1b)
+ LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
@@ -1006,3 +1012,110 @@ _GLOBAL(execve)
*/
_GLOBAL(__main)
blr
+
+#ifdef CONFIG_KEXEC
+ /*
+ * Must be relocatable PIC code callable as a C function.
+ */
+ .globl relocate_new_kernel
+relocate_new_kernel:
+ /* r3 = page_list */
+ /* r4 = reboot_code_buffer */
+ /* r5 = start_address */
+
+ li r0, 0
+
+ /*
+ * Set Machine Status Register to a known status,
+ * switch the MMU off and jump to 1: in a single step.
+ */
+
+ mr r8, r0
+ ori r8, r8, MSR_RI|MSR_ME
+ mtspr SPRN_SRR1, r8
+ addi r8, r4, 1f - relocate_new_kernel
+ mtspr SPRN_SRR0, r8
+ sync
+ rfi
+
+1:
+ /* from this point address translation is turned off */
+ /* and interrupts are disabled */
+
+ /* set a new stack at the bottom of our page... */
+ /* (not really needed now) */
+ addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
+ stw r0, 0(r1)
+
+ /* Do the copies */
+ li r6, 0 /* checksum */
+ mr r0, r3
+ b 1f
+
+0: /* top, read another word for the indirection page */
+ lwzu r0, 4(r3)
+
+1:
+ /* is it a destination page? (r8) */
+ rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
+ beq 2f
+
+ rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
+ b 0b
+
+2: /* is it an indirection page? (r3) */
+ rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
+ beq 2f
+
+ rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
+ subi r3, r3, 4
+ b 0b
+
+2: /* are we done? */
+ rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
+ beq 2f
+ b 3f
+
+2: /* is it a source page? (r9) */
+ rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
+ beq 0b
+
+ rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
+
+ li r7, PAGE_SIZE / 4
+ mtctr r7
+ subi r9, r9, 4
+ subi r8, r8, 4
+9:
+ lwzu r0, 4(r9) /* do the copy */
+ xor r6, r6, r0
+ stwu r0, 4(r8)
+ dcbst 0, r8
+ sync
+ icbi 0, r8
+ bdnz 9b
+
+ addi r9, r9, 4
+ addi r8, r8, 4
+ b 0b
+
+3:
+
+ /* To be certain of avoiding problems with self-modifying code
+ * execute a serializing instruction here.
+ */
+ isync
+ sync
+
+ /* jump to the entry point, usually the setup routine */
+ mtlr r5
+ blrl
+
+1: b 1b
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
+#endif
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index ae48a002f81a..2778cce058e2 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -39,7 +39,7 @@ _GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
- LOADADDR(r4,1b)
+ LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
@@ -51,7 +51,7 @@ _GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
- LOADADDR(r4,1b)
+ LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
@@ -498,15 +498,15 @@ _GLOBAL(identify_cpu)
*/
_GLOBAL(do_cpu_ftr_fixups)
/* Get CPU 0 features */
- LOADADDR(r6,cur_cpu_spec)
+ LOAD_REG_IMMEDIATE(r6,cur_cpu_spec)
sub r6,r6,r3
ld r4,0(r6)
sub r4,r4,r3
ld r4,CPU_SPEC_FEATURES(r4)
/* Get the fixup table */
- LOADADDR(r6,__start___ftr_fixup)
+ LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup)
sub r6,r6,r3
- LOADADDR(r7,__stop___ftr_fixup)
+ LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup)
sub r7,r7,r3
/* Do the fixup */
1: cmpld r6,r7
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index c0fcd29918ce..fd7db8d542db 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -80,80 +80,74 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
static ssize_t dev_nvram_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- ssize_t len;
- char *tmp_buffer;
- int size;
+ ssize_t ret;
+ char *tmp = NULL;
+ ssize_t size;
- if (ppc_md.nvram_size == NULL)
- return -ENODEV;
+ ret = -ENODEV;
+ if (!ppc_md.nvram_size)
+ goto out;
+
+ ret = 0;
size = ppc_md.nvram_size();
+ if (*ppos >= size || size < 0)
+ goto out;
- if (!access_ok(VERIFY_WRITE, buf, count))
- return -EFAULT;
- if (*ppos >= size)
- return 0;
- if (count > size)
- count = size;
+ count = min_t(size_t, count, size - *ppos);
+ count = min(count, PAGE_SIZE);
- tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
- if (!tmp_buffer) {
- printk(KERN_ERR "dev_read_nvram: kmalloc failed\n");
- return -ENOMEM;
- }
+ ret = -ENOMEM;
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp)
+ goto out;
- len = ppc_md.nvram_read(tmp_buffer, count, ppos);
- if ((long)len <= 0) {
- kfree(tmp_buffer);
- return len;
- }
+ ret = ppc_md.nvram_read(tmp, count, ppos);
+ if (ret <= 0)
+ goto out;
- if (copy_to_user(buf, tmp_buffer, len)) {
- kfree(tmp_buffer);
- return -EFAULT;
- }
+ if (copy_to_user(buf, tmp, ret))
+ ret = -EFAULT;
- kfree(tmp_buffer);
- return len;
+out:
+ kfree(tmp);
+ return ret;
}
static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
- ssize_t len;
- char * tmp_buffer;
- int size;
+ ssize_t ret;
+ char *tmp = NULL;
+ ssize_t size;
- if (ppc_md.nvram_size == NULL)
- return -ENODEV;
+ ret = -ENODEV;
+ if (!ppc_md.nvram_size)
+ goto out;
+
+ ret = 0;
size = ppc_md.nvram_size();
+ if (*ppos >= size || size < 0)
+ goto out;
- if (!access_ok(VERIFY_READ, buf, count))
- return -EFAULT;
- if (*ppos >= size)
- return 0;
- if (count > size)
- count = size;
+ count = min_t(size_t, count, size - *ppos);
+ count = min(count, PAGE_SIZE);
- tmp_buffer = (char *) kmalloc(count, GFP_KERNEL);
- if (!tmp_buffer) {
- printk(KERN_ERR "dev_nvram_write: kmalloc failed\n");
- return -ENOMEM;
- }
-
- if (copy_from_user(tmp_buffer, buf, count)) {
- kfree(tmp_buffer);
- return -EFAULT;
- }
+ ret = -ENOMEM;
+ tmp = kmalloc(count, GFP_KERNEL);
+ if (!tmp)
+ goto out;
- len = ppc_md.nvram_write(tmp_buffer, count, ppos);
- if ((long)len <= 0) {
- kfree(tmp_buffer);
- return len;
- }
+ ret = -EFAULT;
+ if (copy_from_user(tmp, buf, count))
+ goto out;
+
+ ret = ppc_md.nvram_write(tmp, count, ppos);
+
+out:
+ kfree(tmp);
+ return ret;
- kfree(tmp_buffer);
- return len;
}
static int dev_nvram_ioctl(struct inode *inode, struct file *file,
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 7065e40e2f42..22d83d4d1af5 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -132,6 +132,8 @@ static int of_device_resume(struct device * dev)
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
+ .probe = of_device_probe,
+ .remove = of_device_remove,
.suspend = of_device_suspend,
.resume = of_device_resume,
};
@@ -150,8 +152,6 @@ int of_register_driver(struct of_platform_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &of_platform_bus_type;
- drv->driver.probe = of_device_probe;
- drv->driver.remove = of_device_remove;
/* register with core */
count = driver_register(&drv->driver);
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index a7b68f911eb1..5d1b708086bd 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -17,6 +17,7 @@
#include <asm/page.h>
#include <asm/lppaca.h>
#include <asm/iseries/it_lp_queue.h>
+#include <asm/iseries/it_lp_reg_save.h>
#include <asm/paca.h>
@@ -24,10 +25,31 @@
* field correctly */
extern unsigned long __toc_start;
+/*
+ * iSeries structure which the hypervisor knows about - this structure
+ * should not cross a page boundary. The vpa_init/register_vpa call
+ * is now known to fail if the lppaca structure crosses a page
+ * boundary. The lppaca is also used on POWER5 pSeries boxes. The
+ * lppaca is 640 bytes long, and cannot readily change since the
+ * hypervisor knows its layout, so a 1kB alignment will suffice to
+ * ensure that it doesn't cross a page boundary.
+ */
+struct lppaca lppaca[] = {
+ [0 ... (NR_CPUS-1)] = {
+ .desc = 0xd397d781, /* "LpPa" */
+ .size = sizeof(struct lppaca),
+ .dyn_proc_status = 2,
+ .decr_val = 0x00ff0000,
+ .fpregs_in_use = 1,
+ .end_of_quantum = 0xfffffffffffffffful,
+ .slb_count = 64,
+ .vmxregs_in_use = 0,
+ },
+};
+
/* The Paca is an array with one entry per processor. Each contains an
* lppaca, which contains the information shared between the
- * hypervisor and Linux. Each also contains an ItLpRegSave area which
- * is used by the hypervisor to save registers.
+ * hypervisor and Linux.
* On systems with hardware multi-threading, there are two threads
* per processor. The Paca array must contain an entry for each thread.
* The VPD Areas will give a max logical processors = 2 * max physical
@@ -35,33 +57,18 @@ extern unsigned long __toc_start;
* processor (not thread).
*/
#define PACA_INIT_COMMON(number, start, asrr, asrv) \
+ .lppaca_ptr = &lppaca[number], \
.lock_token = 0x8000, \
.paca_index = (number), /* Paca Index */ \
- .default_decr = 0x00ff0000, /* Initial Decr */ \
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
.stab_real = (asrr), /* Real pointer to segment table */ \
.stab_addr = (asrv), /* Virt pointer to segment table */ \
.cpu_start = (start), /* Processor start */ \
- .hw_cpu_id = 0xffff, \
- .lppaca = { \
- .desc = 0xd397d781, /* "LpPa" */ \
- .size = sizeof(struct lppaca), \
- .dyn_proc_status = 2, \
- .decr_val = 0x00ff0000, \
- .fpregs_in_use = 1, \
- .end_of_quantum = 0xfffffffffffffffful, \
- .slb_count = 64, \
- .vmxregs_in_use = 0, \
- }, \
+ .hw_cpu_id = 0xffff,
#ifdef CONFIG_PPC_ISERIES
#define PACA_INIT_ISERIES(number) \
- .lppaca_ptr = &paca[number].lppaca, \
- .reg_save_ptr = &paca[number].reg_save, \
- .reg_save = { \
- .xDesc = 0xd397d9e2, /* "LpRS" */ \
- .xSize = sizeof(struct ItLpRegSave) \
- }
+ .reg_save_ptr = &iseries_reg_save[number],
#define PACA_INIT(number) \
{ \
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
new file mode 100644
index 000000000000..704c846b2b0f
--- /dev/null
+++ b/arch/powerpc/kernel/pci_32.c
@@ -0,0 +1,1897 @@
+/*
+ * Common pmac/prep/chrp pci routines. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+int pcibios_assign_bus_offset = 1;
+
+void pcibios_make_OF_bus_map(void);
+
+static int pci_relocate_bridge_resource(struct pci_bus *bus, int i);
+static int probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict);
+static void update_bridge_base(struct pci_bus *bus, int i);
+static void pcibios_fixup_resources(struct pci_dev* dev);
+static void fixup_broken_pcnet32(struct pci_dev* dev);
+static int reparent_resources(struct resource *parent, struct resource *res);
+static void fixup_cpc710_pci64(struct pci_dev* dev);
+#ifdef CONFIG_PPC_OF
+static u8* pci_to_OF_bus_map;
+#endif
+
+/* By default, we don't re-assign bus numbers. We do this only on
+ * some pmacs
+ */
+int pci_assign_all_buses;
+
+struct pci_controller* hose_head;
+struct pci_controller** hose_tail = &hose_head;
+
+static int pci_bus_count;
+
+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);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
+
+static void
+fixup_cpc710_pci64(struct pci_dev* dev)
+{
+ /* Hide the PCI64 BARs from the kernel as their content doesn't
+ * fit well in the resource management
+ */
+ dev->resource[0].start = dev->resource[0].end = 0;
+ dev->resource[0].flags = 0;
+ dev->resource[1].start = dev->resource[1].end = 0;
+ dev->resource[1].flags = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
+
+static void
+pcibios_fixup_resources(struct pci_dev *dev)
+{
+ struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
+ int i;
+ unsigned long offset;
+
+ if (!hose) {
+ printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
+ return;
+ }
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = dev->resource + i;
+ if (!res->flags)
+ continue;
+ if (res->end == 0xffffffff) {
+ DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+ pci_name(dev), i, res->start, res->end);
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ continue;
+ }
+ offset = 0;
+ if (res->flags & IORESOURCE_MEM) {
+ offset = hose->pci_mem_offset;
+ } else if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long) hose->io_base_virt
+ - isa_io_base;
+ }
+ if (offset != 0) {
+ res->start += offset;
+ res->end += offset;
+#ifdef DEBUG
+ printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+ i, res->flags, pci_name(dev),
+ res->start - offset, res->start);
+#endif
+ }
+ }
+
+ /* Call machine specific resource fixup */
+ if (ppc_md.pcibios_fixup_resources)
+ ppc_md.pcibios_fixup_resources(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
+
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ unsigned long offset = 0;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (hose && res->flags & IORESOURCE_IO)
+ offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ else if (hose && res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+ region->start = res->start - offset;
+ region->end = res->end - offset;
+}
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+
+void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
+ struct pci_bus_region *region)
+{
+ unsigned long offset = 0;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (hose && res->flags & IORESOURCE_IO)
+ offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ else if (hose && res->flags & IORESOURCE_MEM)
+ offset = hose->pci_mem_offset;
+ res->start = region->start + offset;
+ res->end = region->end + offset;
+}
+EXPORT_SYMBOL(pcibios_bus_to_resource);
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+ unsigned long align)
+{
+ struct pci_dev *dev = data;
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (size > 0x100) {
+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+ " (%ld bytes)\n", pci_name(dev),
+ dev->resource - res, size);
+ }
+
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+/*
+ * Handle resources of PCI devices. If the world were perfect, we could
+ * just allocate all the resource regions and do nothing more. It isn't.
+ * On the other hand, we cannot just re-allocate all devices, as it would
+ * require us to know lots of host bridge internals. So we attempt to
+ * keep as much of the original configuration as possible, but tweak it
+ * when it's found to be wrong.
+ *
+ * Known BIOS problems we have to work around:
+ * - I/O or memory regions not configured
+ * - regions configured, but not enabled in the command register
+ * - bogus I/O addresses above 64K used
+ * - expansion ROMs left enabled (this may sound harmless, but given
+ * the fact the PCI specs explicitly allow address decoders to be
+ * shared between expansion ROMs and other resource regions, it's
+ * at least dangerous)
+ *
+ * Our solution:
+ * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
+ * This gives us fixed barriers on where we can allocate.
+ * (2) Allocate resources for all enabled devices. If there is
+ * a collision, just mark the resource as unallocated. Also
+ * disable expansion ROMs during this step.
+ * (3) Try to allocate resources for disabled devices. If the
+ * resources were assigned correctly, everything goes well,
+ * if they weren't, they won't disturb allocation of other
+ * resources.
+ * (4) Assign new addresses to resources which were either
+ * not configured at all or misconfigured. If explicitly
+ * requested by the user, configure expansion ROM address
+ * as well.
+ */
+
+static void __init
+pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+ struct pci_bus *bus;
+ int i;
+ struct resource *res, *pr;
+
+ /* Depth-First Search on bus tree */
+ list_for_each_entry(bus, bus_list, node) {
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL || !res->flags
+ || res->start > res->end)
+ continue;
+ if (bus->parent == NULL)
+ pr = (res->flags & IORESOURCE_IO)?
+ &ioport_resource: &iomem_resource;
+ else {
+ pr = pci_find_parent_resource(bus->self, res);
+ if (pr == res) {
+ /* this happens when the generic PCI
+ * code (wrongly) decides that this
+ * bridge is transparent -- paulus
+ */
+ continue;
+ }
+ }
+
+ DBG("PCI: bridge rsrc %lx..%lx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
+ if (pr) {
+ if (request_resource(pr, res) == 0)
+ continue;
+ /*
+ * Must be a conflict with an existing entry.
+ * Move that entry (or entries) under the
+ * bridge resource and try again.
+ */
+ if (reparent_resources(pr, res) == 0)
+ continue;
+ }
+ printk(KERN_ERR "PCI: Cannot allocate resource region "
+ "%d of PCI bridge %d\n", i, bus->number);
+ if (pci_relocate_bridge_resource(bus, i))
+ bus->resource[i] = NULL;
+ }
+ pcibios_allocate_bus_resources(&bus->children);
+ }
+}
+
+/*
+ * Reparent resource children of pr that conflict with res
+ * under res, and make res replace those children.
+ */
+static int __init
+reparent_resources(struct resource *parent, struct resource *res)
+{
+ struct resource *p, **pp;
+ struct resource **firstpp = NULL;
+
+ for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+ if (p->end < res->start)
+ continue;
+ if (res->end < p->start)
+ break;
+ if (p->start < res->start || p->end > res->end)
+ return -1; /* not completely contained */
+ if (firstpp == NULL)
+ firstpp = pp;
+ }
+ if (firstpp == NULL)
+ return -1; /* didn't find any conflicting entries? */
+ res->parent = parent;
+ res->child = *firstpp;
+ res->sibling = *pp;
+ *firstpp = res;
+ *pp = NULL;
+ for (p = res->child; p != NULL; p = p->sibling) {
+ p->parent = res;
+ DBG(KERN_INFO "PCI: reparented %s [%lx..%lx] under %s\n",
+ p->name, p->start, p->end, res->name);
+ }
+ return 0;
+}
+
+/*
+ * A bridge has been allocated a range which is outside the range
+ * of its parent bridge, so it needs to be moved.
+ */
+static int __init
+pci_relocate_bridge_resource(struct pci_bus *bus, int i)
+{
+ struct resource *res, *pr, *conflict;
+ unsigned long try, size;
+ int j;
+ struct pci_bus *parent = bus->parent;
+
+ if (parent == NULL) {
+ /* shouldn't ever happen */
+ printk(KERN_ERR "PCI: can't move host bridge resource\n");
+ return -1;
+ }
+ res = bus->resource[i];
+ if (res == NULL)
+ return -1;
+ pr = NULL;
+ for (j = 0; j < 4; j++) {
+ struct resource *r = parent->resource[j];
+ if (!r)
+ continue;
+ if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
+ continue;
+ if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) {
+ pr = r;
+ break;
+ }
+ if (res->flags & IORESOURCE_PREFETCH)
+ pr = r;
+ }
+ if (pr == NULL)
+ return -1;
+ size = res->end - res->start;
+ if (pr->start > pr->end || size > pr->end - pr->start)
+ return -1;
+ try = pr->end;
+ for (;;) {
+ res->start = try - size;
+ res->end = try;
+ if (probe_resource(bus->parent, pr, res, &conflict) == 0)
+ break;
+ if (conflict->start <= pr->start + size)
+ return -1;
+ try = conflict->start - 1;
+ }
+ if (request_resource(pr, res)) {
+ DBG(KERN_ERR "PCI: huh? couldn't move to %lx..%lx\n",
+ res->start, res->end);
+ return -1; /* "can't happen" */
+ }
+ update_bridge_base(bus, i);
+ printk(KERN_INFO "PCI: bridge %d resource %d moved to %lx..%lx\n",
+ bus->number, i, res->start, res->end);
+ return 0;
+}
+
+static int __init
+probe_resource(struct pci_bus *parent, struct resource *pr,
+ struct resource *res, struct resource **conflict)
+{
+ struct pci_bus *bus;
+ struct pci_dev *dev;
+ struct resource *r;
+ int i;
+
+ for (r = pr->child; r != NULL; r = r->sibling) {
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ list_for_each_entry(bus, &parent->children, node) {
+ for (i = 0; i < 4; ++i) {
+ if ((r = bus->resource[i]) == NULL)
+ continue;
+ if (!r->flags || r->start > r->end || r == res)
+ continue;
+ if (pci_find_parent_resource(bus->self, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ list_for_each_entry(dev, &parent->devices, bus_list) {
+ for (i = 0; i < 6; ++i) {
+ r = &dev->resource[i];
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue;
+ if (pci_find_parent_resource(dev, r) != pr)
+ continue;
+ if (r->end >= res->start && res->end >= r->start) {
+ *conflict = r;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static void __init
+update_bridge_base(struct pci_bus *bus, int i)
+{
+ struct resource *res = bus->resource[i];
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base, mem_limit;
+ u16 cmd;
+ unsigned long start, end, off;
+ struct pci_dev *dev = bus->self;
+ struct pci_controller *hose = dev->sysdata;
+
+ if (!hose) {
+ printk("update_bridge_base: no hose?\n");
+ return;
+ }
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND,
+ cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+ if (res->flags & IORESOURCE_IO) {
+ off = (unsigned long) hose->io_base_virt - isa_io_base;
+ start = res->start - off;
+ end = res->end - off;
+ io_base_lo = (start >> 8) & PCI_IO_RANGE_MASK;
+ io_limit_lo = (end >> 8) & PCI_IO_RANGE_MASK;
+ if (end > 0xffff) {
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ start >> 16);
+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+ end >> 16);
+ io_base_lo |= PCI_IO_RANGE_TYPE_32;
+ } else
+ io_base_lo |= PCI_IO_RANGE_TYPE_16;
+ pci_write_config_byte(dev, PCI_IO_BASE, io_base_lo);
+ pci_write_config_byte(dev, PCI_IO_LIMIT, io_limit_lo);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == IORESOURCE_MEM) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_MEMORY_RANGE_MASK;
+ pci_write_config_word(dev, PCI_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_MEMORY_LIMIT, mem_limit);
+
+ } else if ((res->flags & (IORESOURCE_MEM | IORESOURCE_PREFETCH))
+ == (IORESOURCE_MEM | IORESOURCE_PREFETCH)) {
+ off = hose->pci_mem_offset;
+ mem_base = ((res->start - off) >> 16) & PCI_PREF_RANGE_MASK;
+ mem_limit = ((res->end - off) >> 16) & PCI_PREF_RANGE_MASK;
+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE, mem_base);
+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT, mem_limit);
+
+ } else {
+ DBG(KERN_ERR "PCI: ugh, bridge %s res %d has flags=%lx\n",
+ pci_name(dev), i, res->flags);
+ }
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
+
+static inline void alloc_resource(struct pci_dev *dev, int idx)
+{
+ struct resource *pr, *r = &dev->resource[idx];
+
+ DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+ pci_name(dev), idx, r->start, r->end, r->flags);
+ pr = pci_find_parent_resource(dev, r);
+ if (!pr || request_resource(pr, r) < 0) {
+ printk(KERN_ERR "PCI: Cannot allocate resource region %d"
+ " of device %s\n", idx, pci_name(dev));
+ if (pr)
+ DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",
+ pr, pr->start, pr->end, pr->flags);
+ /* We'll assign a new address later */
+ r->flags |= IORESOURCE_UNSET;
+ r->end -= r->start;
+ r->start = 0;
+ }
+}
+
+static void __init
+pcibios_allocate_resources(int pass)
+{
+ struct pci_dev *dev = NULL;
+ int idx, disabled;
+ u16 command;
+ struct resource *r;
+
+ for_each_pci_dev(dev) {
+ pci_read_config_word(dev, PCI_COMMAND, &command);
+ for (idx = 0; idx < 6; idx++) {
+ r = &dev->resource[idx];
+ if (r->parent) /* Already allocated */
+ continue;
+ if (!r->flags || (r->flags & IORESOURCE_UNSET))
+ continue; /* Not assigned at all */
+ if (r->flags & IORESOURCE_IO)
+ disabled = !(command & PCI_COMMAND_IO);
+ else
+ disabled = !(command & PCI_COMMAND_MEMORY);
+ if (pass == disabled)
+ alloc_resource(dev, idx);
+ }
+ if (pass)
+ continue;
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ if (r->flags & IORESOURCE_ROM_ENABLE) {
+ /* Turn the ROM off, leave the resource region, but keep it unregistered. */
+ u32 reg;
+ DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+ r->flags &= ~IORESOURCE_ROM_ENABLE;
+ pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ reg & ~PCI_ROM_ADDRESS_ENABLE);
+ }
+ }
+}
+
+static void __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];
+
+ /*
+ * We shall assign a new address to this resource,
+ * either because the BIOS (sic) forgot to do so
+ * or because we have decided the old address was
+ * unusable for some reason.
+ */
+ if ((r->flags & IORESOURCE_UNSET) && r->end &&
+ (!ppc_md.pcibios_enable_device_hook ||
+ !ppc_md.pcibios_enable_device_hook(dev, 1))) {
+ r->flags &= ~IORESOURCE_UNSET;
+ pci_assign_resource(dev, idx);
+ }
+ }
+
+#if 0 /* don't assign ROMs */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ r->end -= r->start;
+ r->start = 0;
+ if (r->end)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+#endif
+ }
+}
+
+
+int
+pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1<<idx)))
+ continue;
+
+ r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_UNSET) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+static int next_controller_index;
+
+struct pci_controller * __init
+pcibios_alloc_controller(void)
+{
+ struct pci_controller *hose;
+
+ hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose));
+ memset(hose, 0, sizeof(struct pci_controller));
+
+ *hose_tail = hose;
+ hose_tail = &hose->next;
+
+ hose->index = next_controller_index++;
+
+ return hose;
+}
+
+#ifdef CONFIG_PPC_OF
+/*
+ * Functions below are used on OpenFirmware machines.
+ */
+static void
+make_one_node_map(struct device_node* node, u8 pci_bus)
+{
+ int *bus_range;
+ int len;
+
+ if (pci_bus >= pci_bus_count)
+ return;
+ bus_range = (int *) get_property(node, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s, "
+ "assuming it starts at 0\n", node->full_name);
+ pci_to_OF_bus_map[pci_bus] = 0;
+ } else
+ pci_to_OF_bus_map[pci_bus] = bus_range[0];
+
+ for (node=node->child; node != 0;node = node->sibling) {
+ struct pci_dev* dev;
+ unsigned int *class_code, *reg;
+
+ class_code = (unsigned int *) get_property(node, "class-code", NULL);
+ if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+ continue;
+ reg = (unsigned int *)get_property(node, "reg", NULL);
+ if (!reg)
+ continue;
+ dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
+ if (!dev || !dev->subordinate)
+ continue;
+ make_one_node_map(node, dev->subordinate->number);
+ }
+}
+
+void
+pcibios_make_OF_bus_map(void)
+{
+ int i;
+ struct pci_controller* hose;
+ u8* of_prop_map;
+
+ pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
+ if (!pci_to_OF_bus_map) {
+ printk(KERN_ERR "Can't allocate OF bus map !\n");
+ return;
+ }
+
+ /* We fill the bus map with invalid values, that helps
+ * debugging.
+ */
+ for (i=0; i<pci_bus_count; i++)
+ pci_to_OF_bus_map[i] = 0xff;
+
+ /* For each hose, we begin searching bridges */
+ for(hose=hose_head; hose; hose=hose->next) {
+ struct device_node* node;
+ node = (struct device_node *)hose->arch_data;
+ if (!node)
+ continue;
+ make_one_node_map(node, hose->first_busno);
+ }
+ of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
+ if (of_prop_map)
+ memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
+#ifdef DEBUG
+ printk("PCI->OF bus map:\n");
+ for (i=0; i<pci_bus_count; i++) {
+ if (pci_to_OF_bus_map[i] == 0xff)
+ continue;
+ printk("%d -> %d\n", i, pci_to_OF_bus_map[i]);
+ }
+#endif
+}
+
+typedef int (*pci_OF_scan_iterator)(struct device_node* node, void* data);
+
+static struct device_node*
+scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void* data)
+{
+ struct device_node* sub_node;
+
+ for (; node != 0;node = node->sibling) {
+ unsigned int *class_code;
+
+ if (filter(node, data))
+ return node;
+
+ /* For PCI<->PCI bridges or CardBus bridges, we go down
+ * Note: some OFs create a parent node "multifunc-device" as
+ * a fake root for all functions of a multi-function device,
+ * we go down them as well.
+ */
+ class_code = (unsigned int *) get_property(node, "class-code", NULL);
+ if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
+ strcmp(node->name, "multifunc-device"))
+ continue;
+ sub_node = scan_OF_pci_childs(node->child, filter, data);
+ if (sub_node)
+ return sub_node;
+ }
+ return NULL;
+}
+
+static int
+scan_OF_pci_childs_iterator(struct device_node* node, void* data)
+{
+ unsigned int *reg;
+ u8* fdata = (u8*)data;
+
+ reg = (unsigned int *) get_property(node, "reg", NULL);
+ if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
+ && ((reg[0] >> 16) & 0xff) == fdata[0])
+ return 1;
+ return 0;
+}
+
+static struct device_node*
+scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
+{
+ u8 filter_data[2] = {bus, dev_fn};
+
+ return scan_OF_pci_childs(node, scan_OF_pci_childs_iterator, filter_data);
+}
+
+/*
+ * Scans the OF tree for a device node matching a PCI device
+ */
+struct device_node *
+pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
+{
+ struct pci_controller *hose;
+ struct device_node *node;
+ int busnr;
+
+ if (!have_of)
+ return NULL;
+
+ /* Lookup the hose */
+ busnr = bus->number;
+ hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return NULL;
+
+ /* Check it has an OF node associated */
+ node = (struct device_node *) hose->arch_data;
+ if (!node)
+ return NULL;
+
+ /* Fixup bus number according to what OF think it is. */
+#ifdef CONFIG_PPC_PMAC
+ /* The G5 need a special case here. Basically, we don't remap all
+ * busses on it so we don't create the pci-OF-map. However, we do
+ * remap the AGP bus and so have to deal with it. A future better
+ * fix has to be done by making the remapping per-host and always
+ * filling the pci_to_OF map. --BenH
+ */
+ if (_machine == _MACH_Pmac && busnr >= 0xf0)
+ busnr -= 0xf0;
+ else
+#endif
+ if (pci_to_OF_bus_map)
+ busnr = pci_to_OF_bus_map[busnr];
+ if (busnr == 0xff)
+ return NULL;
+
+ /* Now, lookup childs of the hose */
+ return scan_OF_childs_for_device(node->child, busnr, devfn);
+}
+EXPORT_SYMBOL(pci_busdev_to_OF_node);
+
+struct device_node*
+pci_device_to_OF_node(struct pci_dev *dev)
+{
+ return pci_busdev_to_OF_node(dev->bus, dev->devfn);
+}
+EXPORT_SYMBOL(pci_device_to_OF_node);
+
+/* This routine is meant to be used early during boot, when the
+ * PCI bus numbers have not yet been assigned, and you need to
+ * issue PCI config cycles to an OF device.
+ * It could also be used to "fix" RTAS config cycles if you want
+ * to set pci_assign_all_buses to 1 and still use RTAS for PCI
+ * config cycles.
+ */
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+ if (!have_of)
+ return NULL;
+ while(node) {
+ struct pci_controller* hose;
+ for (hose=hose_head;hose;hose=hose->next)
+ if (hose->arch_data == node)
+ return hose;
+ node=node->parent;
+ }
+ return NULL;
+}
+
+static int
+find_OF_pci_device_filter(struct device_node* node, void* data)
+{
+ return ((void *)node == data);
+}
+
+/*
+ * Returns the PCI device matching a given OF node
+ */
+int
+pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
+{
+ unsigned int *reg;
+ struct pci_controller* hose;
+ struct pci_dev* dev = NULL;
+
+ if (!have_of)
+ return -ENODEV;
+ /* Make sure it's really a PCI device */
+ hose = pci_find_hose_for_OF_device(node);
+ if (!hose || !hose->arch_data)
+ return -ENODEV;
+ if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
+ find_OF_pci_device_filter, (void *)node))
+ return -ENODEV;
+ reg = (unsigned int *) get_property(node, "reg", NULL);
+ if (!reg)
+ return -ENODEV;
+ *bus = (reg[0] >> 16) & 0xff;
+ *devfn = ((reg[0] >> 8) & 0xff);
+
+ /* Ok, here we need some tweak. If we have already renumbered
+ * all busses, we can't rely on the OF bus number any more.
+ * the pci_to_OF_bus_map is not enough as several PCI busses
+ * may match the same OF bus number.
+ */
+ if (!pci_to_OF_bus_map)
+ return 0;
+
+ for_each_pci_dev(dev)
+ if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
+ dev->devfn == *devfn) {
+ *bus = dev->bus->number;
+ pci_dev_put(dev);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL(pci_device_from_OF_node);
+
+void __init
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+ struct device_node *dev, int primary)
+{
+ static unsigned int static_lc_ranges[256] __initdata;
+ unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
+ unsigned int size;
+ int rlen = 0, orig_rlen;
+ int memno = 0;
+ struct resource *res;
+ int np, na = prom_n_addr_cells(dev);
+ np = na + 5;
+
+ /* First we try to merge ranges to fix a problem with some pmacs
+ * that can have more than 3 ranges, fortunately using contiguous
+ * addresses -- BenH
+ */
+ dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+ if (!dt_ranges)
+ return;
+ /* Sanity check, though hopefully that never happens */
+ if (rlen > sizeof(static_lc_ranges)) {
+ printk(KERN_WARNING "OF ranges property too large !\n");
+ rlen = sizeof(static_lc_ranges);
+ }
+ lc_ranges = static_lc_ranges;
+ memcpy(lc_ranges, dt_ranges, rlen);
+ orig_rlen = rlen;
+
+ /* Let's work on a copy of the "ranges" property instead of damaging
+ * the device-tree image in memory
+ */
+ ranges = lc_ranges;
+ prev = NULL;
+ while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+ if (prev) {
+ if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
+ (prev[2] + prev[na+4]) == ranges[2] &&
+ (prev[na+2] + prev[na+4]) == ranges[na+2]) {
+ prev[na+4] += ranges[na+4];
+ ranges[0] = 0;
+ ranges += np;
+ continue;
+ }
+ }
+ prev = ranges;
+ ranges += np;
+ }
+
+ /*
+ * The ranges property is laid out as an array of elements,
+ * each of which comprises:
+ * cells 0 - 2: a PCI address
+ * cells 3 or 3+4: a CPU physical address
+ * (size depending on dev->n_addr_cells)
+ * cells 4+5 or 5+6: the size of the range
+ */
+ ranges = lc_ranges;
+ rlen = orig_rlen;
+ while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
+ res = NULL;
+ size = ranges[na+4];
+ switch ((ranges[0] >> 24) & 0x3) {
+ case 1: /* I/O space */
+ if (ranges[2] != 0)
+ break;
+ hose->io_base_phys = ranges[na+2];
+ /* limit I/O space to 16MB */
+ if (size > 0x01000000)
+ size = 0x01000000;
+ hose->io_base_virt = ioremap(ranges[na+2], size);
+ if (primary)
+ isa_io_base = (unsigned long) hose->io_base_virt;
+ res = &hose->io_resource;
+ res->flags = IORESOURCE_IO;
+ res->start = ranges[2];
+ DBG("PCI: IO 0x%lx -> 0x%lx\n",
+ res->start, res->start + size - 1);
+ break;
+ case 2: /* memory space */
+ memno = 0;
+ if (ranges[1] == 0 && ranges[2] == 0
+ && ranges[na+4] <= (16 << 20)) {
+ /* 1st 16MB, i.e. ISA memory area */
+ if (primary)
+ isa_mem_base = ranges[na+2];
+ memno = 1;
+ }
+ while (memno < 3 && hose->mem_resources[memno].flags)
+ ++memno;
+ if (memno == 0)
+ hose->pci_mem_offset = ranges[na+2] - ranges[2];
+ if (memno < 3) {
+ res = &hose->mem_resources[memno];
+ res->flags = IORESOURCE_MEM;
+ if(ranges[0] & 0x40000000)
+ res->flags |= IORESOURCE_PREFETCH;
+ res->start = ranges[na+2];
+ DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
+ res->start, res->start + size - 1);
+ }
+ break;
+ }
+ if (res != NULL) {
+ res->name = dev->full_name;
+ res->end = res->start + size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+ }
+ ranges += np;
+ }
+}
+
+/* We create the "pci-OF-bus-map" property now so it appears in the
+ * /proc device tree
+ */
+void __init
+pci_create_OF_bus_map(void)
+{
+ struct property* of_prop;
+
+ of_prop = (struct property*) alloc_bootmem(sizeof(struct property) + 256);
+ if (of_prop && find_path_device("/")) {
+ memset(of_prop, -1, sizeof(struct property) + 256);
+ of_prop->name = "pci-OF-bus-map";
+ of_prop->length = 256;
+ of_prop->value = (unsigned char *)&of_prop[1];
+ prom_add_property(find_path_device("/"), of_prop);
+ }
+}
+
+static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev;
+ struct device_node *np;
+
+ pdev = to_pci_dev (dev);
+ np = pci_device_to_OF_node(pdev);
+ if (np == NULL || np->full_name == NULL)
+ return 0;
+ return sprintf(buf, "%s", np->full_name);
+}
+static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
+
+#else /* CONFIG_PPC_OF */
+void pcibios_make_OF_bus_map(void)
+{
+}
+#endif /* CONFIG_PPC_OF */
+
+/* Add sysfs properties */
+void pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PPC_OF
+ device_create_file(&pdev->dev, &dev_attr_devspec);
+#endif /* CONFIG_PPC_OF */
+}
+
+
+#ifdef CONFIG_PPC_PMAC
+/*
+ * This set of routines checks for PCI<->PCI bridges that have closed
+ * IO resources and have child devices. It tries to re-open an IO
+ * window on them.
+ *
+ * This is a _temporary_ fix to workaround a problem with Apple's OF
+ * closing IO windows on P2P bridges when the OF drivers of cards
+ * below this bridge don't claim any IO range (typically ATI or
+ * Adaptec).
+ *
+ * A more complete fix would be to use drivers/pci/setup-bus.c, which
+ * involves a working pcibios_fixup_pbus_ranges(), some more care about
+ * ordering when creating the host bus resources, and maybe a few more
+ * minor tweaks
+ */
+
+/* Initialize bridges with base/limit values we have collected */
+static void __init
+do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
+{
+ struct pci_dev *bridge = bus->self;
+ struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
+ u32 l;
+ u16 w;
+ struct resource res;
+
+ if (bus->resource[0] == NULL)
+ return;
+ res = *(bus->resource[0]);
+
+ DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
+ res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
+ res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
+ DBG(" IO window: %08lx-%08lx\n", res.start, res.end);
+
+ /* Set up the top and bottom of the PCI I/O segment for this bus. */
+ pci_read_config_dword(bridge, PCI_IO_BASE, &l);
+ l &= 0xffff000f;
+ l |= (res.start >> 8) & 0x00f0;
+ l |= res.end & 0xf000;
+ pci_write_config_dword(bridge, PCI_IO_BASE, l);
+
+ if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ l = (res.start >> 16) | (res.end & 0xffff0000);
+ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
+ }
+
+ pci_read_config_word(bridge, PCI_COMMAND, &w);
+ w |= PCI_COMMAND_IO;
+ pci_write_config_word(bridge, PCI_COMMAND, w);
+
+#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
+ if (enable_vga) {
+ pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
+ w |= PCI_BRIDGE_CTL_VGA;
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
+ }
+#endif
+}
+
+/* This function is pretty basic and actually quite broken for the
+ * general case, it's enough for us right now though. It's supposed
+ * to tell us if we need to open an IO range at all or not and what
+ * size.
+ */
+static int __init
+check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
+{
+ struct pci_dev *dev;
+ int i;
+ int rc = 0;
+
+#define push_end(res, size) do { unsigned long __sz = (size) ; \
+ res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
+ } while (0)
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ u16 class = dev->class >> 8;
+
+ if (class == PCI_CLASS_DISPLAY_VGA ||
+ class == PCI_CLASS_NOT_DEFINED_VGA)
+ *found_vga = 1;
+ if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
+ rc |= check_for_io_childs(dev->subordinate, res, found_vga);
+ if (class == PCI_CLASS_BRIDGE_CARDBUS)
+ push_end(res, 0xfff);
+
+ for (i=0; i<PCI_NUM_RESOURCES; i++) {
+ struct resource *r;
+ unsigned long r_size;
+
+ if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
+ && i >= PCI_BRIDGE_RESOURCES)
+ continue;
+ r = &dev->resource[i];
+ r_size = r->end - r->start;
+ if (r_size < 0xfff)
+ r_size = 0xfff;
+ if (r->flags & IORESOURCE_IO && (r_size) != 0) {
+ rc = 1;
+ push_end(res, r_size);
+ }
+ }
+ }
+
+ return rc;
+}
+
+/* Here we scan all P2P bridges of a given level that have a closed
+ * IO window. Note that the test for the presence of a VGA card should
+ * be improved to take into account already configured P2P bridges,
+ * currently, we don't see them and might end up configuring 2 bridges
+ * with VGA pass through enabled
+ */
+static void __init
+do_fixup_p2p_level(struct pci_bus *bus)
+{
+ struct pci_bus *b;
+ int i, parent_io;
+ int has_vga = 0;
+
+ for (parent_io=0; parent_io<4; parent_io++)
+ if (bus->resource[parent_io]
+ && bus->resource[parent_io]->flags & IORESOURCE_IO)
+ break;
+ if (parent_io >= 4)
+ return;
+
+ list_for_each_entry(b, &bus->children, node) {
+ struct pci_dev *d = b->self;
+ struct pci_controller* hose = (struct pci_controller *)d->sysdata;
+ struct resource *res = b->resource[0];
+ struct resource tmp_res;
+ unsigned long max;
+ int found_vga = 0;
+
+ memset(&tmp_res, 0, sizeof(tmp_res));
+ tmp_res.start = bus->resource[parent_io]->start;
+
+ /* We don't let low addresses go through that closed P2P bridge, well,
+ * that may not be necessary but I feel safer that way
+ */
+ if (tmp_res.start == 0)
+ tmp_res.start = 0x1000;
+
+ if (!list_empty(&b->devices) && res && res->flags == 0 &&
+ res != bus->resource[parent_io] &&
+ (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+ check_for_io_childs(b, &tmp_res, &found_vga)) {
+ u8 io_base_lo;
+
+ printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
+
+ if (found_vga) {
+ if (has_vga) {
+ printk(KERN_WARNING "Skipping VGA, already active"
+ " on bus segment\n");
+ found_vga = 0;
+ } else
+ has_vga = 1;
+ }
+ pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
+
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
+ max = ((unsigned long) hose->io_base_virt
+ - isa_io_base) + 0xffffffff;
+ else
+ max = ((unsigned long) hose->io_base_virt
+ - isa_io_base) + 0xffff;
+
+ *res = tmp_res;
+ res->flags = IORESOURCE_IO;
+ res->name = b->name;
+
+ /* Find a resource in the parent where we can allocate */
+ for (i = 0 ; i < 4; i++) {
+ struct resource *r = bus->resource[i];
+ if (!r)
+ continue;
+ if ((r->flags & IORESOURCE_IO) == 0)
+ continue;
+ DBG("Trying to allocate from %08lx, size %08lx from parent"
+ " res %d: %08lx -> %08lx\n",
+ res->start, res->end, i, r->start, r->end);
+
+ if (allocate_resource(r, res, res->end + 1, res->start, max,
+ res->end + 1, NULL, NULL) < 0) {
+ DBG("Failed !\n");
+ continue;
+ }
+ do_update_p2p_io_resource(b, found_vga);
+ break;
+ }
+ }
+ do_fixup_p2p_level(b);
+ }
+}
+
+static void
+pcibios_fixup_p2p_bridges(void)
+{
+ struct pci_bus *b;
+
+ list_for_each_entry(b, &pci_root_buses, node)
+ do_fixup_p2p_level(b);
+}
+
+#endif /* CONFIG_PPC_PMAC */
+
+static int __init
+pcibios_init(void)
+{
+ struct pci_controller *hose;
+ struct pci_bus *bus;
+ int next_busno;
+
+ printk(KERN_INFO "PCI: Probing PCI hardware\n");
+
+ /* Scan all of the recorded PCI controllers. */
+ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+ if (pci_assign_all_buses)
+ hose->first_busno = next_busno;
+ hose->last_busno = 0xff;
+ bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
+ hose->last_busno = bus->subordinate;
+ if (pci_assign_all_buses || next_busno <= hose->last_busno)
+ next_busno = hose->last_busno + pcibios_assign_bus_offset;
+ }
+ pci_bus_count = next_busno;
+
+ /* OpenFirmware based machines need a map of OF bus
+ * numbers vs. kernel bus numbers since we may have to
+ * remap them.
+ */
+ if (pci_assign_all_buses && have_of)
+ pcibios_make_OF_bus_map();
+
+ /* Do machine dependent PCI interrupt routing */
+ if (ppc_md.pci_swizzle && ppc_md.pci_map_irq)
+ pci_fixup_irqs(ppc_md.pci_swizzle, ppc_md.pci_map_irq);
+
+ /* Call machine dependent fixup */
+ if (ppc_md.pcibios_fixup)
+ ppc_md.pcibios_fixup();
+
+ /* Allocate and assign resources */
+ pcibios_allocate_bus_resources(&pci_root_buses);
+ pcibios_allocate_resources(0);
+ pcibios_allocate_resources(1);
+#ifdef CONFIG_PPC_PMAC
+ pcibios_fixup_p2p_bridges();
+#endif /* CONFIG_PPC_PMAC */
+ pcibios_assign_resources();
+
+ /* Call machine dependent post-init code */
+ if (ppc_md.pcibios_after_init)
+ ppc_md.pcibios_after_init();
+
+ return 0;
+}
+
+subsys_initcall(pcibios_init);
+
+unsigned char __init
+common_swizzle(struct pci_dev *dev, unsigned char *pinp)
+{
+ struct pci_controller *hose = dev->sysdata;
+
+ if (dev->bus->number != hose->first_busno) {
+ u8 pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
+
+ /* The slot is the idsel of the last bridge. */
+ }
+ return PCI_SLOT(dev->devfn);
+}
+
+unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
+ unsigned long start, unsigned long size)
+{
+ return start;
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+ unsigned long io_offset;
+ struct resource *res;
+ int i;
+
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ if (bus->parent == NULL) {
+ /* This is a host bridge - fill in its resources */
+ hose->bus = bus;
+
+ bus->resource[0] = res = &hose->io_resource;
+ if (!res->flags) {
+ if (io_offset)
+ printk(KERN_ERR "I/O resource not set for host"
+ " bridge %d\n", hose->index);
+ res->start = 0;
+ res->end = IO_SPACE_LIMIT;
+ res->flags = IORESOURCE_IO;
+ }
+ res->start += io_offset;
+ res->end += io_offset;
+
+ for (i = 0; i < 3; ++i) {
+ res = &hose->mem_resources[i];
+ if (!res->flags) {
+ if (i > 0)
+ continue;
+ printk(KERN_ERR "Memory resource not set for "
+ "host bridge %d\n", hose->index);
+ res->start = hose->pci_mem_offset;
+ res->end = ~0U;
+ res->flags = IORESOURCE_MEM;
+ }
+ bus->resource[i+1] = res;
+ }
+ } else {
+ /* This is a subordinate bridge */
+ pci_read_bridge_bases(bus);
+
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL)
+ continue;
+ if (!res->flags)
+ continue;
+ if (io_offset && (res->flags & IORESOURCE_IO)) {
+ res->start += io_offset;
+ res->end += io_offset;
+ } else if (hose->pci_mem_offset
+ && (res->flags & IORESOURCE_MEM)) {
+ res->start += hose->pci_mem_offset;
+ res->end += hose->pci_mem_offset;
+ }
+ }
+ }
+
+ if (ppc_md.pcibios_fixup_bus)
+ ppc_md.pcibios_fixup_bus(bus);
+}
+
+char __init *pcibios_setup(char *str)
+{
+ return str;
+}
+
+/* the next one is stolen from the alpha port... */
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+ /* XXX FIXME - update OF device tree node interrupt property */
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ if (ppc_md.pcibios_enable_device_hook)
+ if (ppc_md.pcibios_enable_device_hook(dev, 0))
+ return -EINVAL;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (r->flags & IORESOURCE_UNSET) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ pci_name(dev), old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+struct pci_controller*
+pci_bus_to_hose(int bus)
+{
+ struct pci_controller* hose = hose_head;
+
+ for (; hose; hose = hose->next)
+ if (bus >= hose->first_busno && bus <= hose->last_busno)
+ return hose;
+ return NULL;
+}
+
+void __iomem *
+pci_bus_io_base(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return NULL;
+ return hose->io_base_virt;
+}
+
+unsigned long
+pci_bus_io_base_phys(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return 0;
+ return hose->io_base_phys;
+}
+
+unsigned long
+pci_bus_mem_base_phys(unsigned int bus)
+{
+ struct pci_controller *hose;
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return 0;
+ return hose->pci_mem_offset;
+}
+
+unsigned long
+pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
+{
+ /* Hack alert again ! See comments in chrp_pci.c
+ */
+ struct pci_controller* hose =
+ (struct pci_controller *)pdev->sysdata;
+ if (hose && res->flags & IORESOURCE_MEM)
+ return res->start - hose->pci_mem_offset;
+ /* We may want to do something with IOs here... */
+ return res->start;
+}
+
+
+static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
+ unsigned long *offset,
+ enum pci_mmap_state mmap_state)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ unsigned long io_offset = 0;
+ int i, res_bit;
+
+ if (hose == 0)
+ return NULL; /* should never happen */
+
+ /* If memory, add on the PCI bridge address offset */
+ if (mmap_state == pci_mmap_mem) {
+ *offset += hose->pci_mem_offset;
+ res_bit = IORESOURCE_MEM;
+ } else {
+ io_offset = hose->io_base_virt - ___IO_BASE;
+ *offset += io_offset;
+ res_bit = IORESOURCE_IO;
+ }
+
+ /*
+ * Check that the offset requested corresponds to one of the
+ * resources of the device.
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &dev->resource[i];
+ int flags = rp->flags;
+
+ /* treat ROM as memory (should be already) */
+ if (i == PCI_ROM_RESOURCE)
+ flags |= IORESOURCE_MEM;
+
+ /* Active and same type? */
+ if ((flags & res_bit) == 0)
+ continue;
+
+ /* In the range of this resource? */
+ if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end)
+ continue;
+
+ /* found it! construct the final physical address */
+ if (mmap_state == pci_mmap_io)
+ *offset += hose->io_base_phys - io_offset;
+ return rp;
+ }
+
+ return NULL;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,
+ pgprot_t protection,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ unsigned long prot = pgprot_val(protection);
+
+ /* Write combine is always 0 on non-memory space mappings. On
+ * memory space, if the user didn't pass 1, we check for a
+ * "prefetchable" resource. This is a bit hackish, but we use
+ * this to workaround the inability of /sysfs to provide a write
+ * combine bit
+ */
+ if (mmap_state != pci_mmap_mem)
+ write_combine = 0;
+ else if (write_combine == 0) {
+ if (rp->flags & IORESOURCE_PREFETCH)
+ write_combine = 1;
+ }
+
+ /* XXX would be nice to have a way to ask for write-through */
+ prot |= _PAGE_NO_CACHE;
+ if (write_combine)
+ prot &= ~_PAGE_GUARDED;
+ else
+ prot |= _PAGE_GUARDED;
+
+ printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+ prot);
+
+ return __pgprot(prot);
+}
+
+/*
+ * This one is used by /dev/mem and fbdev who have no clue about the
+ * PCI device, it tries to find the PCI device first and calls the
+ * above routine
+ */
+pgprot_t pci_phys_mem_access_prot(struct file *file,
+ unsigned long pfn,
+ unsigned long size,
+ pgprot_t protection)
+{
+ struct pci_dev *pdev = NULL;
+ struct resource *found = NULL;
+ unsigned long prot = pgprot_val(protection);
+ unsigned long offset = pfn << PAGE_SHIFT;
+ int i;
+
+ if (page_is_ram(pfn))
+ return prot;
+
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+ for_each_pci_dev(pdev) {
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &pdev->resource[i];
+ int flags = rp->flags;
+
+ /* Active and same type? */
+ if ((flags & IORESOURCE_MEM) == 0)
+ continue;
+ /* In the range of this resource? */
+ if (offset < (rp->start & PAGE_MASK) ||
+ offset > rp->end)
+ continue;
+ found = rp;
+ break;
+ }
+ if (found)
+ break;
+ }
+ if (found) {
+ if (found->flags & IORESOURCE_PREFETCH)
+ prot &= ~_PAGE_GUARDED;
+ pci_dev_put(pdev);
+ }
+
+ DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);
+
+ return __pgprot(prot);
+}
+
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture. The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ struct resource *rp;
+ int ret;
+
+ rp = __pci_mmap_make_offset(dev, &offset, mmap_state);
+ if (rp == NULL)
+ return -EINVAL;
+
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
+ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+ vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
+ vma->vm_page_prot,
+ mmap_state, write_combine);
+
+ ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+ return ret;
+}
+
+/* Obsolete functions. Should be removed once the symbios driver
+ * is fixed
+ */
+unsigned long
+phys_to_bus(unsigned long pa)
+{
+ struct pci_controller *hose;
+ int i;
+
+ for (hose = hose_head; hose; hose = hose->next) {
+ for (i = 0; i < 3; ++i) {
+ if (pa >= hose->mem_resources[i].start
+ && pa <= hose->mem_resources[i].end) {
+ /*
+ * XXX the hose->pci_mem_offset really
+ * only applies to mem_resources[0].
+ * We need a way to store an offset for
+ * the others. -- paulus
+ */
+ if (i == 0)
+ pa -= hose->pci_mem_offset;
+ return pa;
+ }
+ }
+ }
+ /* hmmm, didn't find it */
+ return 0;
+}
+
+unsigned long
+pci_phys_to_bus(unsigned long pa, int busnr)
+{
+ struct pci_controller* hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return pa;
+ return pa - hose->pci_mem_offset;
+}
+
+unsigned long
+pci_bus_to_phys(unsigned int ba, int busnr)
+{
+ struct pci_controller* hose = pci_bus_to_hose(busnr);
+ if (!hose)
+ return ba;
+ return ba + hose->pci_mem_offset;
+}
+
+/* Provide information on locations of various I/O regions in physical
+ * memory. Do this on a per-card basis so that we choose the right
+ * root bridge.
+ * Note that the returned IO or memory base is a physical address
+ */
+
+long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
+{
+ struct pci_controller* hose;
+ long result = -EOPNOTSUPP;
+
+ /* 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 (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
+ if (bus == 0)
+ bus = 0xf0;
+#endif /* CONFIG_PPC_PMAC */
+
+ hose = pci_bus_to_hose(bus);
+ if (!hose)
+ return -ENODEV;
+
+ 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 (long)isa_mem_base;
+ }
+
+ return result;
+}
+
+void pci_resource_to_user(const struct pci_dev *dev, int bar,
+ const struct resource *rsrc,
+ u64 *start, u64 *end)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+ unsigned long offset = 0;
+
+ if (hose == NULL)
+ return;
+
+ if (rsrc->flags & IORESOURCE_IO)
+ offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
+
+ *start = rsrc->start + offset;
+ *end = rsrc->end + offset;
+}
+
+void __init
+pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
+ int flags, char *name)
+{
+ res->start = start;
+ res->end = end;
+ res->flags = flags;
+ res->name = name;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len)
+ return NULL;
+ if (max && len > max)
+ len = max;
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM)
+ /* Not checking IORESOURCE_CACHEABLE because PPC does
+ * not currently distinguish between ioremap and
+ * ioremap_nocache.
+ */
+ return ioremap(start, len);
+ /* What? */
+ return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ /* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ struct pci_controller* hose = hose_head;
+
+ for (; hose; hose = hose->next) {
+ unsigned int size = hose->io_resource.end -
+ hose->io_resource.start + 1;
+ if (address >= hose->io_base_phys &&
+ address < (hose->io_base_phys + size)) {
+ unsigned long base =
+ (unsigned long)hose->io_base_virt - _IO_BASE;
+ return base + (address - hose->io_base_phys);
+ }
+ }
+ return (unsigned int)-1;
+}
+EXPORT_SYMBOL(pci_address_to_pio);
+
+/*
+ * Null PCI config access functions, for the case when we can't
+ * find a hose.
+ */
+#define NULL_PCI_OP(rw, size, type) \
+static int \
+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
+{ \
+ return PCIBIOS_DEVICE_NOT_FOUND; \
+}
+
+static int
+null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int
+null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static struct pci_ops null_pci_ops =
+{
+ null_read_config,
+ null_write_config
+};
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_bus *
+fake_pci_bus(struct pci_controller *hose, int busnr)
+{
+ static struct pci_bus bus;
+
+ if (hose == 0) {
+ hose = pci_bus_to_hose(busnr);
+ if (hose == 0)
+ printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
+ }
+ bus.number = busnr;
+ bus.sysdata = hose;
+ bus.ops = hose? hose->ops: &null_pci_ops;
+ return &bus;
+}
+
+#define EARLY_PCI_OP(rw, size, type) \
+int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
+ int devfn, int offset, type value) \
+{ \
+ return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \
+ devfn, offset, value); \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 8b6008ab217d..c367520bc1c3 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -34,7 +34,7 @@
#ifdef DEBUG
#include <asm/udbg.h>
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG(fmt...) printk(fmt)
#else
#define DBG(fmt...)
#endif
@@ -53,6 +53,7 @@ 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);
+static void phbs_remap_io(void);
#endif
/* pci_io_base -- the base address from which io bars are offsets.
@@ -251,7 +252,8 @@ void pcibios_free_controller(struct pci_controller *phb)
kfree(phb);
}
-static void __init pcibios_claim_one_bus(struct pci_bus *b)
+#ifndef CONFIG_PPC_ISERIES
+void __devinit pcibios_claim_one_bus(struct pci_bus *b)
{
struct pci_dev *dev;
struct pci_bus *child_bus;
@@ -271,8 +273,10 @@ static void __init pcibios_claim_one_bus(struct pci_bus *b)
list_for_each_entry(child_bus, &b->children, node)
pcibios_claim_one_bus(child_bus);
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+#endif
-#ifndef CONFIG_PPC_ISERIES
static void __init pcibios_claim_of_setup(void)
{
struct pci_bus *b;
@@ -323,6 +327,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
if (!addrs)
return;
+ DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
for (; proplen >= 20; proplen -= 20, addrs += 5) {
flags = pci_parse_of_flags(addrs[0]);
if (!flags)
@@ -332,6 +337,9 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
if (!size)
continue;
i = addrs[0] & 0xff;
+ DBG(" base: %llx, size: %llx, i: %x\n",
+ (unsigned long long)base, (unsigned long long)size, i);
+
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) {
@@ -362,6 +370,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
if (type == NULL)
type = "";
+ DBG(" create device, devfn: %x, type: %s\n", devfn, type);
+
memset(dev, 0, sizeof(struct pci_dev));
dev->bus = bus;
dev->sysdata = node;
@@ -375,12 +385,14 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
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);*/
+ dev->cfg_size = 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);
+ DBG(" class: 0x%x\n", dev->class);
+
dev->current_state = 4; /* unknown power state */
if (!strcmp(type, "pci")) {
@@ -402,6 +414,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
pci_parse_of_addrs(node, dev);
+ DBG(" adding to system ...\n");
+
pci_device_add(dev, bus);
/* XXX pci_scan_msi_device(dev); */
@@ -418,15 +432,21 @@ void __devinit of_scan_bus(struct device_node *node,
int reglen, devfn;
struct pci_dev *dev;
+ DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
+
while ((child = of_get_next_child(node, child)) != NULL) {
+ DBG(" * %s\n", child->full_name);
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;
+ DBG("dev header type: %x\n", dev->hdr_type);
+
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
of_scan_pci_bridge(child, dev);
@@ -446,16 +466,18 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
unsigned int flags;
u64 size;
+ DBG("of_scan_pci_bridge(%s)\n", node->full_name);
+
/* 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",
+ printk(KERN_DEBUG "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",
+ printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
node->full_name);
return;
}
@@ -509,10 +531,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
}
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
+ DBG(" bus name: %s\n", bus->name);
mode = PCI_PROBE_NORMAL;
if (ppc_md.pci_probe_mode)
mode = ppc_md.pci_probe_mode(bus);
+ DBG(" probe mode: %d\n", mode);
+
if (mode == PCI_PROBE_DEVTREE)
of_scan_bus(node, bus);
else if (mode == PCI_PROBE_NORMAL)
@@ -528,6 +553,8 @@ void __devinit scan_phb(struct pci_controller *hose)
int i, mode;
struct resource *res;
+ DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+
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",
@@ -552,8 +579,9 @@ void __devinit scan_phb(struct pci_controller *hose)
mode = PCI_PROBE_NORMAL;
#ifdef CONFIG_PPC_MULTIPLATFORM
- if (ppc_md.pci_probe_mode)
+ if (node && ppc_md.pci_probe_mode)
mode = ppc_md.pci_probe_mode(bus);
+ DBG(" probe mode: %d\n", mode);
if (mode == PCI_PROBE_DEVTREE) {
bus->subordinate = hose->last_busno;
of_scan_bus(node, bus);
@@ -842,8 +870,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
* Returns a negative error code on failure, zero on success.
*/
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state,
- int write_combine)
+ enum pci_mmap_state mmap_state, int write_combine)
{
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
struct resource *rp;
@@ -896,6 +923,25 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
unsigned long phb_io_base_phys,
void __iomem * phb_io_base_virt)
{
+ /* Remove these asap */
+
+ struct pci_address {
+ u32 a_hi;
+ u32 a_mid;
+ u32 a_lo;
+ };
+
+ struct isa_address {
+ u32 a_hi;
+ u32 a_lo;
+ };
+
+ struct isa_range {
+ struct isa_address isa_addr;
+ struct pci_address pci_addr;
+ unsigned int size;
+ };
+
struct isa_range *range;
unsigned long pci_addr;
unsigned int isa_addr;
@@ -1173,7 +1219,7 @@ int remap_bus_range(struct pci_bus *bus)
}
EXPORT_SYMBOL(remap_bus_range);
-void phbs_remap_io(void)
+static void phbs_remap_io(void)
{
struct pci_controller *hose, *tmp;
@@ -1223,6 +1269,7 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
}
EXPORT_SYMBOL(pcibios_fixup_device_resources);
+
static void __devinit do_bus_setup(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -1306,8 +1353,38 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
*end = rsrc->end + offset;
}
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
+{
+ if (!have_of)
+ return NULL;
+ while(node) {
+ struct pci_controller *hose, *tmp;
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ if (hose->arch_data == node)
+ return hose;
+ node = node->parent;
+ }
+ return NULL;
+}
+
#endif /* CONFIG_PPC_MULTIPLATFORM */
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ struct pci_controller *hose, *tmp;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+ if (address >= hose->io_base_phys &&
+ address < (hose->io_base_phys + hose->pci_io_size)) {
+ unsigned long base =
+ (unsigned long)hose->io_base_virt - pci_io_base;
+ return base + (address - hose->io_base_phys);
+ }
+ }
+ return (unsigned int)-1;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
#define IOBASE_BRIDGE_NUMBER 0
#define IOBASE_MEMORY 1
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c
index 2d333cc84082..e6fb194fe537 100644
--- a/arch/powerpc/kernel/pmc.c
+++ b/arch/powerpc/kernel/pmc.c
@@ -43,8 +43,13 @@ static void dummy_perf(struct pt_regs *regs)
mtspr(SPRN_MMCR0, mmcr0);
}
#else
+/* Ensure exceptions are disabled */
static void dummy_perf(struct pt_regs *regs)
{
+ unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+ mmcr0 &= ~(MMCR0_PMXE);
+ mtspr(SPRN_MMCR0, mmcr0);
}
#endif
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 94db25708456..d9a459c144d8 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -76,11 +76,6 @@ EXPORT_SYMBOL(single_step_exception);
EXPORT_SYMBOL(sys_sigreturn);
#endif
-#if defined(CONFIG_PPC_PREP)
-EXPORT_SYMBOL(_prep_type);
-EXPORT_SYMBOL(ucSystemType);
-#endif
-
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strcat);
@@ -235,8 +230,7 @@ EXPORT_SYMBOL(__down_interruptible);
EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
- defined(CONFIG_83xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_40x)
EXPORT_SYMBOL(__res);
#endif
@@ -249,7 +243,6 @@ EXPORT_SYMBOL(set_context);
extern long mol_trampoline;
EXPORT_SYMBOL(mol_trampoline); /* For MOL */
EXPORT_SYMBOL(flush_hash_pages); /* For MOL */
-EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
#ifdef CONFIG_SMP
extern int mmu_hash_lock;
EXPORT_SYMBOL(mmu_hash_lock); /* For MOL */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 105d5609ff57..57703994a063 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -201,13 +201,13 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
}
#endif /* CONFIG_SPE */
+#ifndef CONFIG_SMP
/*
* If we are doing lazy switching of CPU state (FP, altivec or SPE),
* and the current task has some state, discard it.
*/
-static inline void discard_lazy_cpu_state(void)
+void discard_lazy_cpu_state(void)
{
-#ifndef CONFIG_SMP
preempt_disable();
if (last_task_used_math == current)
last_task_used_math = NULL;
@@ -220,9 +220,10 @@ static inline void discard_lazy_cpu_state(void)
last_task_used_spe = NULL;
#endif
preempt_enable();
-#endif /* CONFIG_SMP */
}
+#endif /* CONFIG_SMP */
+#ifdef CONFIG_PPC_MERGE /* XXX for now */
int set_dabr(unsigned long dabr)
{
if (ppc_md.set_dabr)
@@ -231,6 +232,7 @@ int set_dabr(unsigned long dabr)
mtspr(SPRN_DABR, dabr);
return 0;
}
+#endif
#ifdef CONFIG_PPC64
DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
@@ -424,7 +426,7 @@ void show_regs(struct pt_regs * regs)
if (trap == 0x300 || trap == 0x600)
printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
printk("TASK = %p[%d] '%s' THREAD: %p",
- current, current->pid, current->comm, current->thread_info);
+ current, current->pid, current->comm, task_thread_info(current));
#ifdef CONFIG_SMP
printk(" CPU: %d", smp_processor_id());
@@ -503,7 +505,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
{
struct pt_regs *childregs, *kregs;
extern void ret_from_fork(void);
- unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
+ unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
CHECK_FULL_REGS(regs);
/* Copy registers */
@@ -516,7 +518,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
#ifdef CONFIG_PPC32
childregs->gpr[2] = (unsigned long) p;
#else
- clear_ti_thread_flag(p->thread_info, TIF_32BIT);
+ clear_tsk_thread_flag(p, TIF_32BIT);
#endif
p->thread.regs = NULL; /* no user register state */
} else {
@@ -588,10 +590,8 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
* set. Do it now.
*/
if (!current->thread.regs) {
- unsigned long childregs = (unsigned long)current->thread_info +
- THREAD_SIZE;
- childregs -= sizeof(struct pt_regs);
- current->thread.regs = (struct pt_regs *)childregs;
+ struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE;
+ current->thread.regs = regs - 1;
}
memset(regs->gpr, 0, sizeof(regs->gpr));
@@ -767,7 +767,7 @@ out:
static int validate_sp(unsigned long sp, struct task_struct *p,
unsigned long nbytes)
{
- unsigned long stack_page = (unsigned long)p->thread_info;
+ unsigned long stack_page = (unsigned long)task_stack_page(p);
if (sp >= stack_page + sizeof(struct thread_struct)
&& sp <= stack_page + THREAD_SIZE - nbytes)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 3bf968e74095..d50c8df0183e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -29,6 +29,7 @@
#include <linux/initrd.h>
#include <linux/bitops.h>
#include <linux/module.h>
+#include <linux/kexec.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -37,6 +38,7 @@
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/kdump.h>
#include <asm/smp.h>
#include <asm/system.h>
#include <asm/mmu.h>
@@ -55,21 +57,6 @@
#define DBG(fmt...)
#endif
-struct pci_reg_property {
- struct pci_address addr;
- u32 size_hi;
- u32 size_lo;
-};
-
-struct isa_reg_property {
- u32 space;
- u32 address;
- u32 size;
-};
-
-
-typedef int interpret_func(struct device_node *, unsigned long *,
- int, int, int);
static int __initdata dt_root_addr_cells;
static int __initdata dt_root_size_cells;
@@ -311,6 +298,16 @@ static int __devinit finish_node_interrupts(struct device_node *np,
int i, j, n, sense;
unsigned int *irq, virq;
struct device_node *ic;
+ int trace = 0;
+
+ //#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0)
+#define TRACE(fmt...)
+
+ if (!strcmp(np->name, "smu-doorbell"))
+ trace = 1;
+
+ TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n",
+ num_interrupt_controllers);
if (num_interrupt_controllers == 0) {
/*
@@ -345,11 +342,12 @@ static int __devinit finish_node_interrupts(struct device_node *np,
}
ints = (unsigned int *) get_property(np, "interrupts", &intlen);
+ TRACE("ints=%p, intlen=%d\n", ints, intlen);
if (ints == NULL)
return 0;
intrcells = prom_n_intr_cells(np);
intlen /= intrcells * sizeof(unsigned int);
-
+ TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen);
np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start);
if (!np->intrs)
return -ENOMEM;
@@ -360,6 +358,7 @@ static int __devinit finish_node_interrupts(struct device_node *np,
intrcount = 0;
for (i = 0; i < intlen; ++i, ints += intrcells) {
n = map_interrupt(&irq, &ic, np, ints, intrcells);
+ TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n);
if (n <= 0)
continue;
@@ -370,6 +369,7 @@ static int __devinit finish_node_interrupts(struct device_node *np,
np->intrs[intrcount].sense = map_isa_senses[sense];
} else {
virq = virt_irq_create_mapping(irq[0]);
+ TRACE("virq=%d\n", virq);
#ifdef CONFIG_PPC64
if (virq == NO_IRQ) {
printk(KERN_CRIT "Could not allocate interrupt"
@@ -379,6 +379,12 @@ static int __devinit finish_node_interrupts(struct device_node *np,
#endif
np->intrs[intrcount].line = irq_offset_up(virq);
sense = (n > 1)? (irq[1] & 3): 1;
+
+ /* Apple uses bits in there in a different way, let's
+ * only keep the real sense bit on macs
+ */
+ if (_machine == PLATFORM_POWERMAC)
+ sense &= 0x1;
np->intrs[intrcount].sense = map_mpic_senses[sense];
}
@@ -388,12 +394,13 @@ static int __devinit finish_node_interrupts(struct device_node *np,
char *name = get_property(ic->parent, "name", NULL);
if (name && !strcmp(name, "u3"))
np->intrs[intrcount].line += 128;
- else if (!(name && !strcmp(name, "mac-io")))
+ else if (!(name && (!strcmp(name, "mac-io") ||
+ !strcmp(name, "u4"))))
/* ignore other cascaded controllers, such as
the k2-sata-root */
break;
}
-#endif
+#endif /* CONFIG_PPC64 */
if (n > 2) {
printk("hmmm, got %d intr cells for %s:", n,
np->full_name);
@@ -408,234 +415,19 @@ static int __devinit finish_node_interrupts(struct device_node *np,
return 0;
}
-static int __devinit interpret_pci_props(struct device_node *np,
- unsigned long *mem_start,
- int naddrc, int nsizec,
- int measure_only)
-{
- struct address_range *adr;
- struct pci_reg_property *pci_addrs;
- int i, l, n_addrs;
-
- pci_addrs = (struct pci_reg_property *)
- get_property(np, "assigned-addresses", &l);
- if (!pci_addrs)
- return 0;
-
- n_addrs = l / sizeof(*pci_addrs);
-
- adr = prom_alloc(n_addrs * sizeof(*adr), mem_start);
- if (!adr)
- return -ENOMEM;
-
- if (measure_only)
- return 0;
-
- np->addrs = adr;
- np->n_addrs = n_addrs;
-
- for (i = 0; i < n_addrs; i++) {
- adr[i].space = pci_addrs[i].addr.a_hi;
- adr[i].address = pci_addrs[i].addr.a_lo |
- ((u64)pci_addrs[i].addr.a_mid << 32);
- adr[i].size = pci_addrs[i].size_lo;
- }
-
- return 0;
-}
-
-static int __init interpret_dbdma_props(struct device_node *np,
- unsigned long *mem_start,
- int naddrc, int nsizec,
- int measure_only)
-{
- struct reg_property32 *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l;
- struct device_node *db;
-
- base_address = 0;
- if (!measure_only) {
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
- }
-
- rp = (struct reg_property32 *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property32)) {
- i = 0;
- adr = (struct address_range *) (*mem_start);
- while ((l -= sizeof(struct reg_property32)) >= 0) {
- if (!measure_only) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- }
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- (*mem_start) += i * sizeof(struct address_range);
- }
-
- return 0;
-}
-
-static int __init interpret_macio_props(struct device_node *np,
- unsigned long *mem_start,
- int naddrc, int nsizec,
- int measure_only)
-{
- struct reg_property32 *rp;
- struct address_range *adr;
- unsigned long base_address;
- int i, l;
- struct device_node *db;
-
- base_address = 0;
- if (!measure_only) {
- for (db = np->parent; db != NULL; db = db->parent) {
- if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
- base_address = db->addrs[0].address;
- break;
- }
- }
- }
-
- rp = (struct reg_property32 *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct reg_property32)) {
- i = 0;
- adr = (struct address_range *) (*mem_start);
- while ((l -= sizeof(struct reg_property32)) >= 0) {
- if (!measure_only) {
- adr[i].space = 2;
- adr[i].address = rp[i].address + base_address;
- adr[i].size = rp[i].size;
- }
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- (*mem_start) += i * sizeof(struct address_range);
- }
-
- return 0;
-}
-
-static int __init interpret_isa_props(struct device_node *np,
- unsigned long *mem_start,
- int naddrc, int nsizec,
- int measure_only)
-{
- struct isa_reg_property *rp;
- struct address_range *adr;
- int i, l;
-
- rp = (struct isa_reg_property *) get_property(np, "reg", &l);
- if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
- i = 0;
- adr = (struct address_range *) (*mem_start);
- while ((l -= sizeof(struct isa_reg_property)) >= 0) {
- if (!measure_only) {
- adr[i].space = rp[i].space;
- adr[i].address = rp[i].address;
- adr[i].size = rp[i].size;
- }
- ++i;
- }
- np->addrs = adr;
- np->n_addrs = i;
- (*mem_start) += i * sizeof(struct address_range);
- }
-
- return 0;
-}
-
-static int __init interpret_root_props(struct device_node *np,
- unsigned long *mem_start,
- int naddrc, int nsizec,
- int measure_only)
-{
- struct address_range *adr;
- int i, l;
- unsigned int *rp;
- int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
-
- rp = (unsigned int *) get_property(np, "reg", &l);
- if (rp != 0 && l >= rpsize) {
- i = 0;
- adr = (struct address_range *) (*mem_start);
- while ((l -= rpsize) >= 0) {
- if (!measure_only) {
- adr[i].space = 0;
- adr[i].address = rp[naddrc - 1];
- adr[i].size = rp[naddrc + nsizec - 1];
- }
- ++i;
- rp += naddrc + nsizec;
- }
- np->addrs = adr;
- np->n_addrs = i;
- (*mem_start) += i * sizeof(struct address_range);
- }
-
- return 0;
-}
-
static int __devinit finish_node(struct device_node *np,
unsigned long *mem_start,
- interpret_func *ifunc,
- int naddrc, int nsizec,
int measure_only)
{
struct device_node *child;
- int *ip, rc = 0;
-
- /* get the device addresses and interrupts */
- if (ifunc != NULL)
- rc = ifunc(np, mem_start, naddrc, nsizec, measure_only);
- if (rc)
- goto out;
+ int rc = 0;
rc = finish_node_interrupts(np, mem_start, measure_only);
if (rc)
goto out;
- /* Look for #address-cells and #size-cells properties. */
- ip = (int *) get_property(np, "#address-cells", NULL);
- if (ip != NULL)
- naddrc = *ip;
- ip = (int *) get_property(np, "#size-cells", NULL);
- if (ip != NULL)
- nsizec = *ip;
-
- if (!strcmp(np->name, "device-tree") || np->parent == NULL)
- ifunc = interpret_root_props;
- else if (np->type == 0)
- ifunc = NULL;
- else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
- ifunc = interpret_pci_props;
- else if (!strcmp(np->type, "dbdma"))
- ifunc = interpret_dbdma_props;
- else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props)
- ifunc = interpret_macio_props;
- else if (!strcmp(np->type, "isa"))
- ifunc = interpret_isa_props;
- else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
- ifunc = interpret_root_props;
- else if (!((ifunc == interpret_dbdma_props
- || ifunc == interpret_macio_props)
- && (!strcmp(np->type, "escc")
- || !strcmp(np->type, "media-bay"))))
- ifunc = NULL;
-
for (child = np->child; child != NULL; child = child->sibling) {
- rc = finish_node(child, mem_start, ifunc,
- naddrc, nsizec, measure_only);
+ rc = finish_node(child, mem_start, measure_only);
if (rc)
goto out;
}
@@ -697,10 +489,10 @@ void __init finish_device_tree(void)
* reason and then remove those additional 16 bytes
*/
size = 16;
- finish_node(allnodes, &size, NULL, 0, 0, 1);
+ finish_node(allnodes, &size, 1);
size -= 16;
end = start = (unsigned long) __va(lmb_alloc(size, 128));
- finish_node(allnodes, &end, NULL, 0, 0, 0);
+ finish_node(allnodes, &end, 0);
BUG_ON(end != start + size);
DBG(" <- finish_device_tree\n");
@@ -1180,7 +972,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
#endif
#ifdef CONFIG_PPC_RTAS
- /* To help early debugging via the front panel, we retreive a minimal
+ /* To help early debugging via the front panel, we retrieve a minimal
* set of RTAS infos now if available
*/
{
@@ -1197,6 +989,16 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
}
#endif /* CONFIG_PPC_RTAS */
+#ifdef CONFIG_KEXEC
+ lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
+ if (lprop)
+ crashk_res.start = *lprop;
+
+ lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL);
+ if (lprop)
+ crashk_res.end = crashk_res.start + *lprop - 1;
+#endif
+
/* break now */
return 1;
}
@@ -1263,7 +1065,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
} else if (strcmp(type, "memory") != 0)
return 0;
- reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
+ reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ if (reg == NULL)
+ reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
@@ -1296,17 +1100,37 @@ static int __init early_init_dt_scan_memory(unsigned long node,
static void __init early_reserve_mem(void)
{
- unsigned long base, size;
- unsigned long *reserve_map;
+ u64 base, size;
+ u64 *reserve_map;
- reserve_map = (unsigned long *)(((unsigned long)initial_boot_params) +
+ reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
initial_boot_params->off_mem_rsvmap);
+#ifdef CONFIG_PPC32
+ /*
+ * Handle the case where we might be booting from an old kexec
+ * image that setup the mem_rsvmap as pairs of 32-bit values
+ */
+ if (*reserve_map > 0xffffffffull) {
+ u32 base_32, size_32;
+ u32 *reserve_map_32 = (u32 *)reserve_map;
+
+ while (1) {
+ base_32 = *(reserve_map_32++);
+ size_32 = *(reserve_map_32++);
+ if (size_32 == 0)
+ break;
+ DBG("reserving: %lx -> %lx\n", base_32, size_32);
+ lmb_reserve(base_32, size_32);
+ }
+ return;
+ }
+#endif
while (1) {
base = *(reserve_map++);
size = *(reserve_map++);
if (size == 0)
break;
- DBG("reserving: %lx -> %lx\n", base, size);
+ DBG("reserving: %llx -> %llx\n", base, size);
lmb_reserve(base, size);
}
@@ -1335,11 +1159,14 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
lmb_enforce_memory_limit(memory_limit);
lmb_analyze();
- lmb_reserve(0, __pa(klimit));
DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
+ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
+#ifdef CONFIG_CRASH_DUMP
+ lmb_reserve(0, KDUMP_RESERVE_LIMIT);
+#endif
early_reserve_mem();
DBG("Scanning CPUs ...\n");
@@ -1800,9 +1627,13 @@ static void of_node_release(struct kref *kref)
kfree(prop->value);
kfree(prop);
prop = next;
+
+ if (!prop) {
+ prop = node->deadprops;
+ node->deadprops = NULL;
+ }
}
kfree(node->intrs);
- kfree(node->addrs);
kfree(node->full_name);
kfree(node->data);
kfree(node);
@@ -1884,9 +1715,7 @@ void of_detach_node(const struct device_node *np)
* This should probably be split up into smaller chunks.
*/
-static int of_finish_dynamic_node(struct device_node *node,
- unsigned long *unused1, int unused2,
- int unused3, int unused4)
+static int of_finish_dynamic_node(struct device_node *node)
{
struct device_node *parent = of_get_parent(node);
int err = 0;
@@ -1907,7 +1736,8 @@ static int of_finish_dynamic_node(struct device_node *node,
return -ENODEV;
/* fix up new node's linux_phandle field */
- if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL)))
+ if ((ibm_phandle = (unsigned int *)get_property(node,
+ "ibm,phandle", NULL)))
node->linux_phandle = *ibm_phandle;
out:
@@ -1922,7 +1752,9 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
switch (action) {
case PSERIES_RECONFIG_ADD:
- err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0);
+ err = of_finish_dynamic_node(node);
+ if (!err)
+ finish_node(node, NULL, 0);
if (err < 0) {
printk(KERN_ERR "finish_node returned %d\n", err);
err = NOTIFY_BAD;
@@ -1947,22 +1779,32 @@ static int __init prom_reconfig_setup(void)
__initcall(prom_reconfig_setup);
#endif
-/*
- * Find a property with a given name for a given node
- * and return the value.
- */
-unsigned char *get_property(struct device_node *np, const char *name,
- int *lenp)
+struct property *of_find_property(struct device_node *np, const char *name,
+ int *lenp)
{
struct property *pp;
+ read_lock(&devtree_lock);
for (pp = np->properties; pp != 0; pp = pp->next)
if (strcmp(pp->name, name) == 0) {
if (lenp != 0)
*lenp = pp->length;
- return pp->value;
+ break;
}
- return NULL;
+ read_unlock(&devtree_lock);
+
+ return pp;
+}
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+unsigned char *get_property(struct device_node *np, const char *name,
+ int *lenp)
+{
+ struct property *pp = of_find_property(np,name,lenp);
+ return pp ? pp->value : NULL;
}
EXPORT_SYMBOL(get_property);
@@ -1996,175 +1838,82 @@ int prom_add_property(struct device_node* np, struct property* prop)
return 0;
}
-/* I quickly hacked that one, check against spec ! */
-static inline unsigned long
-bus_space_to_resource_flags(unsigned int bus_space)
+/*
+ * Remove a property from a node. Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property. Instead we just move the property
+ * to the "dead properties" list, so it won't be found any more.
+ */
+int prom_remove_property(struct device_node *np, struct property *prop)
{
- u8 space = (bus_space >> 24) & 0xf;
- if (space == 0)
- space = 0x02;
- if (space == 0x02)
- return IORESOURCE_MEM;
- else if (space == 0x01)
- return IORESOURCE_IO;
- else {
- printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
- bus_space);
- return 0;
- }
-}
+ struct property **next;
+ int found = 0;
-#ifdef CONFIG_PCI
-static struct resource *find_parent_pci_resource(struct pci_dev* pdev,
- struct address_range *range)
-{
- unsigned long mask;
- int i;
-
- /* Check this one */
- mask = bus_space_to_resource_flags(range->space);
- for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
- if ((pdev->resource[i].flags & mask) == mask &&
- pdev->resource[i].start <= range->address &&
- pdev->resource[i].end > range->address) {
- if ((range->address + range->size - 1) > pdev->resource[i].end) {
- /* Add better message */
- printk(KERN_WARNING "PCI/OF resource overlap !\n");
- return NULL;
- }
- break;
- }
+ write_lock(&devtree_lock);
+ next = &np->properties;
+ while (*next) {
+ if (*next == prop) {
+ /* found the node */
+ *next = prop->next;
+ prop->next = np->deadprops;
+ np->deadprops = prop;
+ found = 1;
+ break;
+ }
+ next = &(*next)->next;
}
- if (i == DEVICE_COUNT_RESOURCE)
- return NULL;
- return &pdev->resource[i];
+ write_unlock(&devtree_lock);
+
+ if (!found)
+ return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+ /* try to remove the proc node as well */
+ if (np->pde)
+ proc_device_tree_remove_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+ return 0;
}
/*
- * Request an OF device resource. Currently handles child of PCI devices,
- * or other nodes attached to the root node. Ultimately, put some
- * link to resources in the OF node.
+ * Update a property in a node. Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property. Instead we just move the property
+ * to the "dead properties" list, and add the new property to the
+ * property list
*/
-struct resource *request_OF_resource(struct device_node* node, int index,
- const char* name_postfix)
+int prom_update_property(struct device_node *np,
+ struct property *newprop,
+ struct property *oldprop)
{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
- int nlen, plen;
-
- if (index >= node->n_addrs)
- goto fail;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- goto fail;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while (nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
- node->name);
- goto fail;
- }
-
- res = __request_region(parent, node->addrs[index].address,
- node->addrs[index].size, NULL);
- if (!res)
- goto fail;
- nlen = strlen(node->name);
- plen = name_postfix ? strlen(name_postfix) : 0;
- res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
- if (res->name) {
- strcpy((char *)res->name, node->name);
- if (plen)
- strcpy((char *)res->name+nlen, name_postfix);
- }
- return res;
-fail:
- return NULL;
-}
-EXPORT_SYMBOL(request_OF_resource);
+ struct property **next;
+ int found = 0;
-int release_OF_resource(struct device_node *node, int index)
-{
- struct pci_dev* pcidev;
- u8 pci_bus, pci_devfn;
- unsigned long iomask, start, end;
- struct device_node* nd;
- struct resource* parent;
- struct resource *res = NULL;
-
- if (index >= node->n_addrs)
- return -EINVAL;
-
- /* Sanity check on bus space */
- iomask = bus_space_to_resource_flags(node->addrs[index].space);
- if (iomask & IORESOURCE_MEM)
- parent = &iomem_resource;
- else if (iomask & IORESOURCE_IO)
- parent = &ioport_resource;
- else
- return -EINVAL;
-
- /* Find a PCI parent if any */
- nd = node;
- pcidev = NULL;
- while(nd) {
- if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
- pcidev = pci_find_slot(pci_bus, pci_devfn);
- if (pcidev) break;
- nd = nd->parent;
- }
- if (pcidev)
- parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
- if (!parent) {
- printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
- node->name);
- return -ENODEV;
+ write_lock(&devtree_lock);
+ next = &np->properties;
+ while (*next) {
+ if (*next == oldprop) {
+ /* found the node */
+ newprop->next = oldprop->next;
+ *next = newprop;
+ oldprop->next = np->deadprops;
+ np->deadprops = oldprop;
+ found = 1;
+ break;
+ }
+ next = &(*next)->next;
}
+ write_unlock(&devtree_lock);
- /* Find us in the parent and its childs */
- res = parent->child;
- start = node->addrs[index].address;
- end = start + node->addrs[index].size - 1;
- while (res) {
- if (res->start == start && res->end == end &&
- (res->flags & IORESOURCE_BUSY))
- break;
- if (res->start <= start && res->end >= end)
- res = res->child;
- else
- res = res->sibling;
- }
- if (!res)
+ if (!found)
return -ENODEV;
- if (res->name) {
- kfree(res->name);
- res->name = NULL;
- }
- release_resource(res);
- kfree(res);
+#ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+ if (np->pde)
+ proc_device_tree_update_prop(np->pde, newprop, oldprop);
+#endif /* CONFIG_PROC_DEVICETREE */
return 0;
}
-EXPORT_SYMBOL(release_OF_resource);
-#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index bcdc209dca85..7881ec96ef11 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -137,8 +137,8 @@ struct prom_t {
};
struct mem_map_entry {
- unsigned long base;
- unsigned long size;
+ u64 base;
+ u64 size;
};
typedef u32 cell_t;
@@ -192,6 +192,11 @@ static unsigned long __initdata alloc_bottom;
static unsigned long __initdata rmo_top;
static unsigned long __initdata ram_top;
+#ifdef CONFIG_KEXEC
+static unsigned long __initdata prom_crashk_base;
+static unsigned long __initdata prom_crashk_size;
+#endif
+
static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
static int __initdata mem_reserve_cnt;
@@ -553,7 +558,8 @@ unsigned long prom_memparse(const char *ptr, const char **retptr)
static void __init early_cmdline_parse(void)
{
struct prom_t *_prom = &RELOC(prom);
- char *opt, *p;
+ const char *opt;
+ char *p;
int l = 0;
RELOC(prom_cmd_line[0]) = 0;
@@ -590,6 +596,35 @@ static void __init early_cmdline_parse(void)
RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
#endif
}
+
+#ifdef CONFIG_KEXEC
+ /*
+ * crashkernel=size@addr specifies the location to reserve for
+ * crash kernel.
+ */
+ opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
+ if (opt) {
+ opt += 12;
+ RELOC(prom_crashk_size) =
+ prom_memparse(opt, (const char **)&opt);
+
+ if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
+ RELOC(prom_crashk_size)) {
+ prom_printf("Warning: crashkernel size is not "
+ "aligned to 16MB\n");
+ }
+
+ /*
+ * At present, the crash kernel always run at 32MB.
+ * Just ignore whatever user passed.
+ */
+ RELOC(prom_crashk_base) = 0x2000000;
+ if (*opt == '@') {
+ prom_printf("Warning: PPC64 kdump kernel always runs "
+ "at 32 MB\n");
+ }
+ }
+#endif
}
#ifdef CONFIG_PPC_PSERIES
@@ -863,9 +898,9 @@ static unsigned long __init prom_next_cell(int s, cell_t **cellp)
* If problems seem to show up, it would be a good start to track
* them down.
*/
-static void reserve_mem(unsigned long base, unsigned long size)
+static void reserve_mem(u64 base, u64 size)
{
- unsigned long top = base + size;
+ u64 top = base + size;
unsigned long cnt = RELOC(mem_reserve_cnt);
if (size == 0)
@@ -1011,6 +1046,12 @@ static void __init prom_init_mem(void)
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
prom_printf(" ram_top : %x\n", RELOC(ram_top));
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base)) {
+ prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base));
+ prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size));
+ }
+#endif
}
@@ -1500,6 +1541,8 @@ static int __init prom_find_machine_type(void)
#ifdef CONFIG_PPC64
if (strstr(p, RELOC("Momentum,Maple")))
return PLATFORM_MAPLE;
+ if (strstr(p, RELOC("IBM,CPB")))
+ return PLATFORM_CELL;
#endif
i += sl + 1;
}
@@ -1994,7 +2037,7 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
if (r3 && r4 && r4 != 0xdeadbeef) {
unsigned long val;
- RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+ RELOC(prom_initrd_start) = is_kernel_addr(r3) ? __pa(r3) : r3;
RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
val = RELOC(prom_initrd_start);
@@ -2094,6 +2137,10 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
*/
prom_init_mem();
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base))
+ reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
+#endif
/*
* Determine which cpu is actually running right _now_
*/
@@ -2150,6 +2197,16 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
}
#endif
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base)) {
+ prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
+ PTRRELOC(&prom_crashk_base),
+ sizeof(RELOC(prom_crashk_base)));
+ prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
+ PTRRELOC(&prom_crashk_size),
+ sizeof(RELOC(prom_crashk_size)));
+ }
+#endif
/*
* Fixup any known bugs in the device-tree
*/
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
new file mode 100644
index 000000000000..a8099c806150
--- /dev/null
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -0,0 +1,548 @@
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/pci_regs.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+#ifdef CONFIG_PPC64
+#define PRu64 "%lx"
+#else
+#define PRu64 "%llx"
+#endif
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS 4
+#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
+ (ns) > 0)
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, u32 *addr, int na)
+{
+ printk("%s", s);
+ while(na--)
+ printk(" %08x", *(addr++));
+ printk("\n");
+}
+#else
+static void of_dump_addr(const char *s, u32 *addr, int na) { }
+#endif
+
+/* Read a big address */
+static inline u64 of_read_addr(u32 *cell, int size)
+{
+ u64 r = 0;
+ while (size--)
+ r = (r << 32) | *(cell++);
+ return r;
+}
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+ const char *name;
+ const char *addresses;
+ int (*match)(struct device_node *parent);
+ void (*count_cells)(struct device_node *child,
+ int *addrc, int *sizec);
+ u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna);
+ int (*translate)(u32 *addr, u64 offset, int na);
+ unsigned int (*get_flags)(u32 *addr);
+};
+
+
+/*
+ * Default translator (generic bus)
+ */
+
+static void of_bus_default_count_cells(struct device_node *dev,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = prom_n_addr_cells(dev);
+ if (sizec)
+ *sizec = prom_n_size_cells(dev);
+}
+
+static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ cp = of_read_addr(range, na);
+ s = of_read_addr(range + na + pna, ns);
+ da = of_read_addr(addr, na);
+
+ DBG("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
+ cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+ u64 a = of_read_addr(addr, na);
+ memset(addr, 0, na * 4);
+ a += offset;
+ if (na > 1)
+ addr[na - 2] = a >> 32;
+ addr[na - 1] = a & 0xffffffffu;
+
+ return 0;
+}
+
+static unsigned int of_bus_default_get_flags(u32 *addr)
+{
+ return IORESOURCE_MEM;
+}
+
+
+/*
+ * PCI bus specific translator
+ */
+
+static int of_bus_pci_match(struct device_node *np)
+{
+ /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
+ return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
+}
+
+static void of_bus_pci_count_cells(struct device_node *np,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = 3;
+ if (sizec)
+ *sizec = 2;
+}
+
+static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x03000000)
+ return OF_BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = of_read_addr(range + 1, na - 1);
+ s = of_read_addr(range + na + pna, ns);
+ da = of_read_addr(addr + 1, na - 1);
+
+ DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
+{
+ return of_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static unsigned int of_bus_pci_get_flags(u32 *addr)
+{
+ unsigned int flags = 0;
+ u32 w = addr[0];
+
+ switch((w >> 24) & 0x03) {
+ case 0x01:
+ flags |= IORESOURCE_IO;
+ case 0x02: /* 32 bits */
+ case 0x03: /* 64 bits */
+ flags |= IORESOURCE_MEM;
+ }
+ if (w & 0x40000000)
+ flags |= IORESOURCE_PREFETCH;
+ return flags;
+}
+
+/*
+ * ISA bus specific translator
+ */
+
+static int of_bus_isa_match(struct device_node *np)
+{
+ return !strcmp(np->name, "isa");
+}
+
+static void of_bus_isa_count_cells(struct device_node *child,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = 2;
+ if (sizec)
+ *sizec = 1;
+}
+
+static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x00000001)
+ return OF_BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = of_read_addr(range + 1, na - 1);
+ s = of_read_addr(range + na + pna, ns);
+ da = of_read_addr(addr + 1, na - 1);
+
+ DBG("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
+{
+ return of_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static unsigned int of_bus_isa_get_flags(u32 *addr)
+{
+ unsigned int flags = 0;
+ u32 w = addr[0];
+
+ if (w & 1)
+ flags |= IORESOURCE_IO;
+ else
+ flags |= IORESOURCE_MEM;
+ return flags;
+}
+
+
+/*
+ * Array of bus specific translators
+ */
+
+static struct of_bus of_busses[] = {
+ /* PCI */
+ {
+ .name = "pci",
+ .addresses = "assigned-addresses",
+ .match = of_bus_pci_match,
+ .count_cells = of_bus_pci_count_cells,
+ .map = of_bus_pci_map,
+ .translate = of_bus_pci_translate,
+ .get_flags = of_bus_pci_get_flags,
+ },
+ /* ISA */
+ {
+ .name = "isa",
+ .addresses = "reg",
+ .match = of_bus_isa_match,
+ .count_cells = of_bus_isa_count_cells,
+ .map = of_bus_isa_map,
+ .translate = of_bus_isa_translate,
+ .get_flags = of_bus_isa_get_flags,
+ },
+ /* Default */
+ {
+ .name = "default",
+ .addresses = "reg",
+ .match = NULL,
+ .count_cells = of_bus_default_count_cells,
+ .map = of_bus_default_map,
+ .translate = of_bus_default_translate,
+ .get_flags = of_bus_default_get_flags,
+ },
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
+ if (!of_busses[i].match || of_busses[i].match(np))
+ return &of_busses[i];
+ BUG();
+ return NULL;
+}
+
+static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+ struct of_bus *pbus, u32 *addr,
+ int na, int ns, int pna)
+{
+ u32 *ranges;
+ unsigned int rlen;
+ int rone;
+ u64 offset = OF_BAD_ADDR;
+
+ /* Normally, an absence of a "ranges" property means we are
+ * crossing a non-translatable boundary, and thus the addresses
+ * below the current not cannot be converted to CPU physical ones.
+ * Unfortunately, while this is very clear in the spec, it's not
+ * what Apple understood, and they do have things like /uni-n or
+ * /ht nodes with no "ranges" property and a lot of perfectly
+ * useable mapped devices below them. Thus we treat the absence of
+ * "ranges" as equivalent to an empty "ranges" property which means
+ * a 1:1 translation at that level. It's up to the caller not to try
+ * to translate addresses that aren't supposed to be translated in
+ * the first place. --BenH.
+ */
+ ranges = (u32 *)get_property(parent, "ranges", &rlen);
+ if (ranges == NULL || rlen == 0) {
+ offset = of_read_addr(addr, na);
+ memset(addr, 0, pna * 4);
+ DBG("OF: no ranges, 1:1 translation\n");
+ goto finish;
+ }
+
+ DBG("OF: walking ranges...\n");
+
+ /* Now walk through the ranges */
+ rlen /= 4;
+ rone = na + pna + ns;
+ for (; rlen >= rone; rlen -= rone, ranges += rone) {
+ offset = bus->map(addr, ranges, na, ns, pna);
+ if (offset != OF_BAD_ADDR)
+ break;
+ }
+ if (offset == OF_BAD_ADDR) {
+ DBG("OF: not found !\n");
+ return 1;
+ }
+ memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+ of_dump_addr("OF: parent translation for:", addr, pna);
+ DBG("OF: with offset: "PRu64"\n", offset);
+
+ /* Translate it into parent bus space */
+ return pbus->translate(addr, offset, pna);
+}
+
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+u64 of_translate_address(struct device_node *dev, u32 *in_addr)
+{
+ struct device_node *parent = NULL;
+ struct of_bus *bus, *pbus;
+ u32 addr[OF_MAX_ADDR_CELLS];
+ int na, ns, pna, pns;
+ u64 result = OF_BAD_ADDR;
+
+ DBG("OF: ** translation for device %s **\n", dev->full_name);
+
+ /* Increase refcount at current level */
+ of_node_get(dev);
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ goto bail;
+ bus = of_match_bus(parent);
+
+ /* Cound address cells & copy address locally */
+ bus->count_cells(dev, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+ dev->full_name);
+ goto bail;
+ }
+ memcpy(addr, in_addr, na * 4);
+
+ DBG("OF: bus is %s (na=%d, ns=%d) on %s\n",
+ bus->name, na, ns, parent->full_name);
+ of_dump_addr("OF: translating address:", addr, na);
+
+ /* Translate */
+ for (;;) {
+ /* Switch to parent bus */
+ of_node_put(dev);
+ dev = parent;
+ parent = of_get_parent(dev);
+
+ /* If root, we have finished */
+ if (parent == NULL) {
+ DBG("OF: reached root node\n");
+ result = of_read_addr(addr, na);
+ break;
+ }
+
+ /* Get new parent bus and counts */
+ pbus = of_match_bus(parent);
+ pbus->count_cells(dev, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+ dev->full_name);
+ break;
+ }
+
+ DBG("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+ pbus->name, pna, pns, parent->full_name);
+
+ /* Apply bus translation */
+ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+ break;
+
+ /* Complete the move up one level */
+ na = pna;
+ ns = pns;
+ bus = pbus;
+
+ of_dump_addr("OF: one level translation:", addr, na);
+ }
+ bail:
+ of_node_put(parent);
+ of_node_put(dev);
+
+ return result;
+}
+EXPORT_SYMBOL(of_translate_address);
+
+u32 *of_get_address(struct device_node *dev, int index, u64 *size,
+ unsigned int *flags)
+{
+ u32 *prop;
+ unsigned int psize;
+ struct device_node *parent;
+ struct of_bus *bus;
+ int onesize, i, na, ns;
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ return NULL;
+ bus = of_match_bus(parent);
+ bus->count_cells(dev, &na, &ns);
+ of_node_put(parent);
+ if (!OF_CHECK_COUNTS(na, ns))
+ return NULL;
+
+ /* Get "reg" or "assigned-addresses" property */
+ prop = (u32 *)get_property(dev, bus->addresses, &psize);
+ if (prop == NULL)
+ return NULL;
+ psize /= 4;
+
+ onesize = na + ns;
+ for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+ if (i == index) {
+ if (size)
+ *size = of_read_addr(prop + na, ns);
+ if (flags)
+ *flags = bus->get_flags(prop);
+ return prop;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_address);
+
+u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
+ unsigned int *flags)
+{
+ u32 *prop;
+ unsigned int psize;
+ struct device_node *parent;
+ struct of_bus *bus;
+ int onesize, i, na, ns;
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ return NULL;
+ bus = of_match_bus(parent);
+ if (strcmp(bus->name, "pci"))
+ return NULL;
+ bus->count_cells(dev, &na, &ns);
+ of_node_put(parent);
+ if (!OF_CHECK_COUNTS(na, ns))
+ return NULL;
+
+ /* Get "reg" or "assigned-addresses" property */
+ prop = (u32 *)get_property(dev, bus->addresses, &psize);
+ if (prop == NULL)
+ return NULL;
+ psize /= 4;
+
+ onesize = na + ns;
+ for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+ if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
+ if (size)
+ *size = of_read_addr(prop + na, ns);
+ if (flags)
+ *flags = bus->get_flags(prop);
+ return prop;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_pci_address);
+
+static int __of_address_to_resource(struct device_node *dev, u32 *addrp,
+ u64 size, unsigned int flags,
+ struct resource *r)
+{
+ u64 taddr;
+
+ if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+ return -EINVAL;
+ taddr = of_translate_address(dev, addrp);
+ if (taddr == OF_BAD_ADDR)
+ return -EINVAL;
+ memset(r, 0, sizeof(struct resource));
+ if (flags & IORESOURCE_IO) {
+ unsigned long port;
+ port = pci_address_to_pio(taddr);
+ if (port == (unsigned long)-1)
+ return -EINVAL;
+ r->start = port;
+ r->end = port + size - 1;
+ } else {
+ r->start = taddr;
+ r->end = taddr + size - 1;
+ }
+ r->flags = flags;
+ r->name = dev->name;
+ return 0;
+}
+
+int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r)
+{
+ u32 *addrp;
+ u64 size;
+ unsigned int flags;
+
+ addrp = of_get_address(dev, index, &size, &flags);
+ if (addrp == NULL)
+ return -EINVAL;
+ return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_address_to_resource);
+
+int of_pci_address_to_resource(struct device_node *dev, int bar,
+ struct resource *r)
+{
+ u32 *addrp;
+ u64 size;
+ unsigned int flags;
+
+ addrp = of_get_pci_address(dev, bar, &size, &flags);
+ if (addrp == NULL)
+ return -EINVAL;
+ return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h
index b1babb729673..5ccbdbe0d5c9 100644
--- a/arch/powerpc/kernel/ptrace-common.h
+++ b/arch/powerpc/kernel/ptrace-common.h
@@ -62,7 +62,7 @@ static inline void set_single_step(struct task_struct *task)
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
- set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
+ set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
static inline void clear_single_step(struct task_struct *task)
@@ -70,7 +70,7 @@ static inline void clear_single_step(struct task_struct *task)
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
- clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
+ clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
#ifdef CONFIG_ALTIVEC
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index 61762640b877..826ee3d056de 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -45,33 +45,19 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
unsigned long data)
{
struct task_struct *child;
- int ret = -EPERM;
+ int ret;
lock_kernel();
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
+ ret = ptrace_traceme();
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)
- goto out;
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ goto out;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4283fa33f784..7fe4a5c944c9 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -17,6 +17,7 @@
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <asm/prom.h>
@@ -29,11 +30,17 @@
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/lmb.h>
+#include <asm/udbg.h>
struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
};
+struct rtas_suspend_me_data {
+ long waiting;
+ struct rtas_args *args;
+};
+
EXPORT_SYMBOL(rtas);
DEFINE_SPINLOCK(rtas_data_buf_lock);
@@ -52,7 +59,7 @@ EXPORT_SYMBOL(rtas_flash_term_hook);
* are designed only for very early low-level debugging, which
* is why the token is hard-coded to 10.
*/
-void call_rtas_display_status(unsigned char c)
+static void call_rtas_display_status(char c)
{
struct rtas_args *args = &rtas.args;
unsigned long s;
@@ -65,14 +72,14 @@ void call_rtas_display_status(unsigned char c)
args->nargs = 1;
args->nret = 1;
args->rets = (rtas_arg_t *)&(args->args[1]);
- args->args[0] = (int)c;
+ args->args[0] = (unsigned char)c;
enter_rtas(__pa(args));
spin_unlock_irqrestore(&rtas.lock, s);
}
-void call_rtas_display_status_delay(unsigned char c)
+static void call_rtas_display_status_delay(char c)
{
static int pending_newline = 0; /* did last write end with unprinted newline? */
static int width = 16;
@@ -96,6 +103,11 @@ void call_rtas_display_status_delay(unsigned char c)
}
}
+void __init udbg_init_rtas(void)
+{
+ udbg_putc = call_rtas_display_status_delay;
+}
+
void rtas_progress(char *s, unsigned short hex)
{
struct device_node *root;
@@ -549,6 +561,80 @@ void rtas_os_term(char *str)
} while (status == RTAS_BUSY);
}
+static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
+#ifdef CONFIG_PPC_PSERIES
+static void rtas_percpu_suspend_me(void *info)
+{
+ long rc;
+ long flags;
+ struct rtas_suspend_me_data *data =
+ (struct rtas_suspend_me_data *)info;
+
+ /*
+ * We use "waiting" to indicate our state. As long
+ * as it is >0, we are still trying to all join up.
+ * If it goes to 0, we have successfully joined up and
+ * one thread got H_Continue. If any error happens,
+ * we set it to <0.
+ */
+ local_irq_save(flags);
+ do {
+ rc = plpar_hcall_norets(H_JOIN);
+ smp_rmb();
+ } while (rc == H_Success && data->waiting > 0);
+ if (rc == H_Success)
+ goto out;
+
+ if (rc == H_Continue) {
+ data->waiting = 0;
+ rtas_call(ibm_suspend_me_token, 0, 1,
+ data->args->args);
+ } else {
+ data->waiting = -EBUSY;
+ printk(KERN_ERR "Error on H_Join hypervisor call\n");
+ }
+
+out:
+ /* before we restore interrupts, make sure we don't
+ * generate a spurious soft lockup errors
+ */
+ touch_softlockup_watchdog();
+ local_irq_restore(flags);
+ return;
+}
+
+static int rtas_ibm_suspend_me(struct rtas_args *args)
+{
+ int i;
+
+ struct rtas_suspend_me_data data;
+
+ data.waiting = 1;
+ data.args = args;
+
+ /* Call function on all CPUs. One of us will make the
+ * rtas call
+ */
+ if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
+ data.waiting = -EINVAL;
+
+ if (data.waiting != 0)
+ printk(KERN_ERR "Error doing global join\n");
+
+ /* Prod each CPU. This won't hurt, and will wake
+ * anyone we successfully put to sleep with H_Join
+ */
+ for_each_cpu(i)
+ plpar_hcall_norets(H_PROD, i);
+
+ return data.waiting;
+}
+#else /* CONFIG_PPC_PSERIES */
+static int rtas_ibm_suspend_me(struct rtas_args *args)
+{
+ return -ENOSYS;
+}
+#endif
asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
{
@@ -556,6 +642,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
unsigned long flags;
char *buff_copy, *errbuf = NULL;
int nargs;
+ int rc;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -574,6 +661,17 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
nargs * sizeof(rtas_arg_t)) != 0)
return -EFAULT;
+ if (args.token == RTAS_UNKNOWN_SERVICE)
+ return -EINVAL;
+
+ /* Need to handle ibm,suspend_me call specially */
+ if (args.token == ibm_suspend_me_token) {
+ rc = rtas_ibm_suspend_me(&args);
+ if (rc)
+ return rc;
+ goto copy_return;
+ }
+
buff_copy = get_errorlog_buffer();
spin_lock_irqsave(&rtas.lock, flags);
@@ -597,6 +695,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
kfree(buff_copy);
}
+ copy_return:
/* Copy out args. */
if (copy_to_user(uargs->args + nargs,
args.args + nargs,
@@ -632,7 +731,7 @@ void rtas_stop_self(void)
}
/*
- * Call early during boot, before mem init or bootmem, to retreive the RTAS
+ * Call early during boot, before mem init or bootmem, to retrieve the RTAS
* informations from the device-tree and allocate the RMO buffer for userland
* accesses.
*/
@@ -668,8 +767,10 @@ void __init rtas_initialize(void)
* the stop-self token if any
*/
#ifdef CONFIG_PPC64
- if (_machine == PLATFORM_PSERIES_LPAR)
+ if (_machine == PLATFORM_PSERIES_LPAR) {
rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
+ ibm_suspend_me_token = rtas_token("ibm,suspend-me");
+ }
#endif
rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 60dec2401c26..5579f6559912 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -72,7 +72,7 @@ static int of_device_available(struct device_node * dn)
return 0;
}
-static int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
+int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
{
int returnval = -1;
unsigned long buid, addr;
@@ -188,39 +188,19 @@ int is_python(struct device_node *dev)
return 0;
}
-static int get_phb_reg_prop(struct device_node *dev,
- unsigned int addr_size_words,
- struct reg_property64 *reg)
+static void python_countermeasures(struct device_node *dev)
{
- unsigned int *ui_ptr = NULL, len;
-
- /* Found a PHB, now figure out where his registers are mapped. */
- ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
- if (ui_ptr == NULL)
- return 1;
-
- if (addr_size_words == 1) {
- reg->address = ((struct reg_property32 *)ui_ptr)->address;
- reg->size = ((struct reg_property32 *)ui_ptr)->size;
- } else {
- *reg = *((struct reg_property64 *)ui_ptr);
- }
-
- return 0;
-}
-
-static void python_countermeasures(struct device_node *dev,
- unsigned int addr_size_words)
-{
- struct reg_property64 reg_struct;
+ struct resource registers;
void __iomem *chip_regs;
volatile u32 val;
- if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
+ if (of_address_to_resource(dev, 0, &registers)) {
+ printk(KERN_ERR "Can't get address for Python workarounds !\n");
return;
+ }
/* Python's register file is 1 MB in size. */
- chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
+ chip_regs = ioremap(registers.start & ~(0xfffffUL), 0x100000);
/*
* Firmware doesn't always clear this bit which is critical
@@ -301,11 +281,10 @@ static int phb_set_bus_ranges(struct device_node *dev,
}
static int __devinit setup_phb(struct device_node *dev,
- struct pci_controller *phb,
- unsigned int addr_size_words)
+ struct pci_controller *phb)
{
if (is_python(dev))
- python_countermeasures(dev, addr_size_words);
+ python_countermeasures(dev);
if (phb_set_bus_ranges(dev, phb))
return 1;
@@ -320,8 +299,8 @@ unsigned long __init find_and_init_phbs(void)
{
struct device_node *node;
struct pci_controller *phb;
- unsigned int root_size_cells = 0;
unsigned int index;
+ unsigned int root_size_cells = 0;
unsigned int *opprop = NULL;
struct device_node *root = of_find_node_by_path("/");
@@ -343,10 +322,11 @@ unsigned long __init find_and_init_phbs(void)
phb = pcibios_alloc_controller(node);
if (!phb)
continue;
- setup_phb(node, phb, root_size_cells);
+ setup_phb(node, phb);
pci_process_bridge_OF_ranges(phb, node, 0);
pci_setup_phb_io(phb, index == 0);
#ifdef CONFIG_PPC_PSERIES
+ /* XXX This code need serious fixing ... --BenH */
if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
int addr = root_size_cells * (index + 2) - 1;
mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
@@ -381,22 +361,17 @@ unsigned long __init find_and_init_phbs(void)
struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
{
- struct device_node *root = of_find_node_by_path("/");
- unsigned int root_size_cells = 0;
struct pci_controller *phb;
int primary;
- root_size_cells = prom_n_size_cells(root);
-
primary = list_empty(&hose_list);
phb = pcibios_alloc_controller(dn);
if (!phb)
return NULL;
- setup_phb(dn, phb, root_size_cells);
+ setup_phb(dn, phb);
pci_process_bridge_OF_ranges(phb, dn, primary);
pci_setup_phb_io_dynamic(phb, primary);
- of_node_put(root);
pci_devs_phb_init_dynamic(phb);
scan_phb(phb);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index bd3eb4292b53..be12041c0fc5 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -93,14 +93,15 @@ EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
/* also used by kexec */
void machine_shutdown(void)
{
- if (ppc_md.nvram_sync)
- ppc_md.nvram_sync();
+ if (ppc_md.machine_shutdown)
+ ppc_md.machine_shutdown();
}
void machine_restart(char *cmd)
{
machine_shutdown();
- ppc_md.restart(cmd);
+ if (ppc_md.restart)
+ ppc_md.restart(cmd);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
@@ -112,7 +113,8 @@ void machine_restart(char *cmd)
void machine_power_off(void)
{
machine_shutdown();
- ppc_md.power_off();
+ if (ppc_md.power_off)
+ ppc_md.power_off();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
@@ -129,7 +131,8 @@ EXPORT_SYMBOL_GPL(pm_power_off);
void machine_halt(void)
{
machine_shutdown();
- ppc_md.halt();
+ if (ppc_md.halt)
+ ppc_md.halt();
#ifdef CONFIG_SMP
smp_send_stop();
#endif
@@ -294,129 +297,6 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static int __init set_preferred_console(void)
-{
- struct device_node *prom_stdout = NULL;
- char *name;
- u32 *spd;
- int offset = 0;
-
- DBG(" -> set_preferred_console()\n");
-
- /* The user has requested a console so this is already set up. */
- if (strstr(saved_command_line, "console=")) {
- DBG(" console was specified !\n");
- return -EBUSY;
- }
-
- if (!of_chosen) {
- DBG(" of_chosen is NULL !\n");
- return -ENODEV;
- }
- /* We are getting a weird phandle from OF ... */
- /* ... So use the full path instead */
- name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
- if (name == NULL) {
- DBG(" no linux,stdout-path !\n");
- return -ENODEV;
- }
- prom_stdout = of_find_node_by_path(name);
- if (!prom_stdout) {
- DBG(" can't find stdout package %s !\n", name);
- return -ENODEV;
- }
- DBG("stdout is %s\n", prom_stdout->full_name);
-
- name = (char *)get_property(prom_stdout, "name", NULL);
- if (!name) {
- DBG(" stdout package has no name !\n");
- goto not_found;
- }
- spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
-
- if (0)
- ;
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- else if (strcmp(name, "serial") == 0) {
- int i;
- u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);
- if (i > 8) {
- switch (reg[1]) {
- case 0x3f8:
- offset = 0;
- break;
- case 0x2f8:
- offset = 1;
- break;
- case 0x898:
- offset = 2;
- break;
- case 0x890:
- offset = 3;
- break;
- default:
- /* We dont recognise the serial port */
- goto not_found;
- }
- }
- }
-#endif /* CONFIG_SERIAL_8250_CONSOLE */
-#ifdef CONFIG_PPC_PSERIES
- else if (strcmp(name, "vty") == 0) {
- u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
- char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
-
- if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
- /* Host Virtual Serial Interface */
- switch (reg[0]) {
- case 0x30000000:
- offset = 0;
- break;
- case 0x30000001:
- offset = 1;
- break;
- default:
- goto not_found;
- }
- of_node_put(prom_stdout);
- DBG("Found hvsi console at offset %d\n", offset);
- return add_preferred_console("hvsi", offset, NULL);
- } else {
- /* pSeries LPAR virtual console */
- of_node_put(prom_stdout);
- DBG("Found hvc console\n");
- return add_preferred_console("hvc", 0, NULL);
- }
- }
-#endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE
- else if (strcmp(name, "ch-a") == 0)
- offset = 0;
- else if (strcmp(name, "ch-b") == 0)
- offset = 1;
-#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */
- else
- goto not_found;
- of_node_put(prom_stdout);
-
- DBG("Found serial console at ttyS%d\n", offset);
-
- if (spd) {
- static char __initdata opt[16];
- sprintf(opt, "%d", *spd);
- return add_preferred_console("ttyS", offset, opt);
- } else
- return add_preferred_console("ttyS", offset, NULL);
-
- not_found:
- DBG("No preferred console found !\n");
- of_node_put(prom_stdout);
- return -ENODEV;
-}
-console_initcall(set_preferred_console);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
void __init check_for_initrd(void)
{
#ifdef CONFIG_BLK_DEV_INITRD
@@ -442,7 +322,7 @@ void __init check_for_initrd(void)
/* If we were passed an initrd, set the ROOT_DEV properly if the values
* look sensible. If not, clear initrd reference.
*/
- if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+ if (is_kernel_addr(initrd_start) && is_kernel_addr(initrd_end) &&
initrd_end > initrd_start)
ROOT_DEV = Root_RAM0;
else
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index e5694335bf10..db72a92943bf 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -39,6 +39,8 @@
#include <asm/nvram.h>
#include <asm/xmon.h>
#include <asm/time.h>
+#include <asm/serial.h>
+#include <asm/udbg.h>
#include "setup.h"
@@ -172,12 +174,23 @@ void __init platform_init(void)
*/
void __init machine_init(unsigned long dt_ptr, unsigned long phys)
{
+ /* If btext is enabled, we might have a BAT setup for early display,
+ * thus we do enable some very basic udbg output
+ */
+#ifdef CONFIG_BOOTX_TEXT
+ udbg_putc = btext_drawchar;
+#endif
+
+ /* Do some early initialization based on the flat device tree */
early_init_devtree(__va(dt_ptr));
+ /* Check default command line */
#ifdef CONFIG_CMDLINE
- strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
+ if (cmd_line[0] == 0)
+ strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
#endif /* CONFIG_CMDLINE */
+ /* Base init based on machine type */
platform_init();
#ifdef CONFIG_6xx
@@ -282,25 +295,20 @@ void __init setup_arch(char **cmdline_p)
unflatten_device_tree();
check_for_initrd();
- finish_device_tree();
- smp_setup_cpu_maps();
+ if (ppc_md.init_early)
+ ppc_md.init_early();
-#ifdef CONFIG_BOOTX_TEXT
- init_boot_display();
-#endif
+ find_legacy_serial_ports();
+ finish_device_tree();
-#ifdef CONFIG_PPC_PMAC
- /* This could be called "early setup arch", it must be done
- * now because xmon need it
- */
- if (_machine == _MACH_Pmac)
- pmac_feature_init(); /* New cool way */
-#endif
+ smp_setup_cpu_maps();
#ifdef CONFIG_XMON_DEFAULT
xmon_init(1);
#endif
+ /* Register early console */
+ register_early_udbg_console();
#if defined(CONFIG_KGDB)
if (ppc_md.kgdb_map_scc)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e3fb78397dc6..e29b275e09e0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -33,7 +33,9 @@
#include <linux/unistd.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/bootmem.h>
#include <asm/io.h>
+#include <asm/kdump.h>
#include <asm/prom.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
@@ -69,33 +71,6 @@
#define DBG(fmt...)
#endif
-/*
- * Here are some early debugging facilities. You can enable one
- * but your kernel will not boot on anything else if you do so
- */
-
-/* This one is for use on LPAR machines that support an HVC console
- * on vterm 0
- */
-extern void udbg_init_debug_lpar(void);
-/* This one is for use on Apple G5 machines
- */
-extern void udbg_init_pmac_realmode(void);
-/* That's RTAS panel debug */
-extern void call_rtas_display_status_delay(unsigned char c);
-/* Here's maple real mode debug */
-extern void udbg_init_maple_realmode(void);
-
-#define EARLY_DEBUG_INIT() do {} while(0)
-
-#if 0
-#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
-#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
-#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
-#define EARLY_DEBUG_INIT() \
- do { udbg_putc = call_rtas_display_status_delay; } while(0)
-#endif
-
int have_of = 1;
int boot_cpuid = 0;
int boot_cpuid_phys = 0;
@@ -236,11 +211,8 @@ void __init early_setup(unsigned long dt_ptr)
struct paca_struct *lpaca = get_paca();
static struct machdep_calls **mach;
- /*
- * Enable early debugging if any specified (see top of
- * this file)
- */
- EARLY_DEBUG_INIT();
+ /* Enable early debugging if any specified (see udbg.h) */
+ udbg_early_init();
DBG(" -> early_setup()\n");
@@ -268,6 +240,10 @@ void __init early_setup(unsigned long dt_ptr)
}
ppc_md = **mach;
+#ifdef CONFIG_CRASH_DUMP
+ kdump_setup();
+#endif
+
DBG("Found, Initializing memory management...\n");
/*
@@ -317,6 +293,7 @@ void early_setup_secondary(void)
void smp_release_cpus(void)
{
extern unsigned long __secondary_hold_spinloop;
+ unsigned long *ptr;
DBG(" -> smp_release_cpus()\n");
@@ -327,7 +304,9 @@ void smp_release_cpus(void)
* This is useless but harmless on iSeries, secondaries are already
* waiting on their paca spinloops. */
- __secondary_hold_spinloop = 1;
+ ptr = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
+ - PHYSICAL_START);
+ *ptr = 1;
mb();
DBG(" <- smp_release_cpus()\n");
@@ -430,7 +409,7 @@ void __init setup_system(void)
/*
* Fill the ppc64_caches & systemcfg structures with informations
- * retreived from the device-tree. Need to be called before
+ * retrieved from the device-tree. Need to be called before
* finish_device_tree() since the later requires some of the
* informations filled up here to properly parse the interrupt
* tree.
@@ -459,16 +438,19 @@ void __init setup_system(void)
*/
ppc_md.init_early();
+ /*
+ * We can discover serial ports now since the above did setup the
+ * hash table management for us, thus ioremap works. We do that early
+ * so that further code can be debugged
+ */
+ find_legacy_serial_ports();
+
/*
* "Finish" the device-tree, that is do the actual parsing of
* some of the properties like the interrupt map
*/
finish_device_tree();
-#ifdef CONFIG_BOOTX_TEXT
- init_boot_display();
-#endif
-
/*
* Initialize xmon
*/
@@ -507,6 +489,9 @@ void __init setup_system(void)
ppc64_caches.iline_size);
printk("htab_address = 0x%p\n", htab_address);
printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
+#if PHYSICAL_START > 0
+ printk("physical_start = 0x%x\n", PHYSICAL_START);
+#endif
printk("-----------------------------------------------------\n");
mm_init_ppc64();
@@ -657,187 +642,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk("[terminate]%04x %s\n", src, msg);
}
-#ifndef CONFIG_PPC_ISERIES
-/*
- * This function can be used by platforms to "find" legacy serial ports.
- * It works for "serial" nodes under an "isa" node, and will try to
- * respect the "ibm,aix-loc" property if any. It works with up to 8
- * ports.
- */
-
-#define MAX_LEGACY_SERIAL_PORTS 8
-static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
-static unsigned int old_serial_count;
-
-void __init generic_find_legacy_serial_ports(u64 *physport,
- unsigned int *default_speed)
-{
- struct device_node *np;
- u32 *sizeprop;
-
- struct isa_reg_property {
- u32 space;
- u32 address;
- u32 size;
- };
- struct pci_reg_property {
- struct pci_address addr;
- u32 size_hi;
- u32 size_lo;
- };
-
- DBG(" -> generic_find_legacy_serial_port()\n");
-
- *physport = 0;
- if (default_speed)
- *default_speed = 0;
-
- np = of_find_node_by_path("/");
- if (!np)
- return;
-
- /* First fill our array */
- for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {
- struct device_node *isa, *pci;
- struct isa_reg_property *reg;
- unsigned long phys_size, addr_size, io_base;
- u32 *rangesp;
- u32 *interrupts, *clk, *spd;
- char *typep;
- int index, rlen, rentsize;
-
- /* Ok, first check if it's under an "isa" parent */
- isa = of_get_parent(np);
- if (!isa || strcmp(isa->name, "isa")) {
- DBG("%s: no isa parent found\n", np->full_name);
- continue;
- }
-
- /* Now look for an "ibm,aix-loc" property that gives us ordering
- * if any...
- */
- typep = (char *)get_property(np, "ibm,aix-loc", NULL);
-
- /* Get the ISA port number */
- reg = (struct isa_reg_property *)get_property(np, "reg", NULL);
- if (reg == NULL)
- goto next_port;
- /* We assume the interrupt number isn't translated ... */
- interrupts = (u32 *)get_property(np, "interrupts", NULL);
- /* get clock freq. if present */
- clk = (u32 *)get_property(np, "clock-frequency", NULL);
- /* get default speed if present */
- spd = (u32 *)get_property(np, "current-speed", NULL);
- /* Default to locate at end of array */
- index = old_serial_count; /* end of the array by default */
-
- /* If we have a location index, then use it */
- if (typep && *typep == 'S') {
- index = simple_strtol(typep+1, NULL, 0) - 1;
- /* if index is out of range, use end of array instead */
- if (index >= MAX_LEGACY_SERIAL_PORTS)
- index = old_serial_count;
- /* if our index is still out of range, that mean that
- * array is full, we could scan for a free slot but that
- * make little sense to bother, just skip the port
- */
- if (index >= MAX_LEGACY_SERIAL_PORTS)
- goto next_port;
- if (index >= old_serial_count)
- old_serial_count = index + 1;
- /* Check if there is a port who already claimed our slot */
- if (serial_ports[index].iobase != 0) {
- /* if we still have some room, move it, else override */
- if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) {
- DBG("Moved legacy port %d -> %d\n", index,
- old_serial_count);
- serial_ports[old_serial_count++] =
- serial_ports[index];
- } else {
- DBG("Replacing legacy port %d\n", index);
- }
- }
- }
- if (index >= MAX_LEGACY_SERIAL_PORTS)
- goto next_port;
- if (index >= old_serial_count)
- old_serial_count = index + 1;
-
- /* Now fill the entry */
- memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port));
- serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16;
- serial_ports[index].iobase = reg->address;
- serial_ports[index].irq = interrupts ? interrupts[0] : 0;
- serial_ports[index].flags = ASYNC_BOOT_AUTOCONF;
-
- DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n",
- index,
- serial_ports[index].iobase,
- serial_ports[index].irq,
- serial_ports[index].uartclk);
-
- /* Get phys address of IO reg for port 1 */
- if (index != 0)
- goto next_port;
-
- pci = of_get_parent(isa);
- if (!pci) {
- DBG("%s: no pci parent found\n", np->full_name);
- goto next_port;
- }
-
- rangesp = (u32 *)get_property(pci, "ranges", &rlen);
- if (rangesp == NULL) {
- of_node_put(pci);
- goto next_port;
- }
- rlen /= 4;
-
- /* we need the #size-cells of the PCI bridge node itself */
- phys_size = 1;
- sizeprop = (u32 *)get_property(pci, "#size-cells", NULL);
- if (sizeprop != NULL)
- phys_size = *sizeprop;
- /* we need the parent #addr-cells */
- addr_size = prom_n_addr_cells(pci);
- rentsize = 3 + addr_size + phys_size;
- io_base = 0;
- for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) {
- if (((rangesp[0] >> 24) & 0x3) != 1)
- continue; /* not IO space */
- io_base = rangesp[3];
- if (addr_size == 2)
- io_base = (io_base << 32) | rangesp[4];
- }
- if (io_base != 0) {
- *physport = io_base + reg->address;
- if (default_speed && spd)
- *default_speed = *spd;
- }
- of_node_put(pci);
- next_port:
- of_node_put(isa);
- }
-
- DBG(" <- generic_find_legacy_serial_port()\n");
-}
-
-static struct platform_device serial_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_PLATFORM,
- .dev = {
- .platform_data = serial_ports,
- },
-};
-
-static int __init serial_dev_init(void)
-{
- return platform_device_register(&serial_device);
-}
-arch_initcall(serial_dev_init);
-
-#endif /* CONFIG_PPC_ISERIES */
-
int check_legacy_ioport(unsigned long base_port)
{
if (ppc_md.check_legacy_ioport == NULL)
@@ -851,3 +655,28 @@ void cpu_die(void)
if (ppc_md.cpu_die)
ppc_md.cpu_die();
}
+
+#ifdef CONFIG_SMP
+void __init setup_per_cpu_areas(void)
+{
+ int i;
+ unsigned long size;
+ char *ptr;
+
+ /* Copy section for each CPU (we discard the original) */
+ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
+#ifdef CONFIG_MODULES
+ if (size < PERCPU_ENOUGH_ROOM)
+ size = PERCPU_ENOUGH_ROOM;
+#endif
+
+ for_each_cpu(i) {
+ ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
+ if (!ptr)
+ panic("Cannot allocate cpu data for CPU %d\n", i);
+
+ paca[i].data_offset = ptr - __per_cpu_start;
+ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+ }
+}
+#endif
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 5a2eba60dd39..3747ab0dac3f 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -76,7 +76,6 @@
* registers from *regs. This is what we need
* to do when a signal has been delivered.
*/
-#define sigreturn_exit(regs) return 0
#define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32))
#undef __SIGNAL_FRAMESIZE
@@ -156,9 +155,17 @@ static inline int save_general_regs(struct pt_regs *regs,
elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
int i;
- for (i = 0; i <= PT_RESULT; i ++)
+ if (!FULL_REGS(regs)) {
+ set_thread_flag(TIF_SAVE_NVGPRS);
+ current_thread_info()->nvgprs_frame = frame->mc_gregs;
+ }
+
+ for (i = 0; i <= PT_RESULT; i ++) {
+ if (i == 14 && !FULL_REGS(regs))
+ i = 32;
if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i]))
return -EFAULT;
+ }
return 0;
}
@@ -179,8 +186,6 @@ static inline int restore_general_regs(struct pt_regs *regs,
#else /* CONFIG_PPC64 */
-extern void sigreturn_exit(struct pt_regs *);
-
#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set)
@@ -214,6 +219,15 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka,
static inline int save_general_regs(struct pt_regs *regs,
struct mcontext __user *frame)
{
+ if (!FULL_REGS(regs)) {
+ /* Zero out the unsaved GPRs to avoid information
+ leak, and set TIF_SAVE_NVGPRS to ensure that the
+ registers do actually get saved later. */
+ memset(&regs->gpr[14], 0, 18 * sizeof(unsigned long));
+ current_thread_info()->nvgprs_frame = &frame->mc_gregs;
+ set_thread_flag(TIF_SAVE_NVGPRS);
+ }
+
return __copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE);
}
@@ -238,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs);
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
-long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
- struct pt_regs *regs)
+long sys_sigsuspend(old_sigset_t mask)
{
sigset_t saveset;
@@ -250,51 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- regs->ccr |= 0x10000000;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&saveset, regs))
- sigreturn_exit(regs);
- }
-}
-
-long sys_rt_sigsuspend(
-#ifdef CONFIG_PPC64
- compat_sigset_t __user *unewset,
-#else
- sigset_t __user *unewset,
-#endif
- size_t sigsetsize, int p3, int p4,
- int p6, int p7, struct pt_regs *regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (get_sigset_t(&newset, unewset))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- regs->ccr |= 0x10000000;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&saveset, regs))
- sigreturn_exit(regs);
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
#ifdef CONFIG_PPC32
@@ -391,9 +363,6 @@ struct rt_sigframe {
static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
int sigret)
{
-#ifdef CONFIG_PPC32
- CHECK_FULL_REGS(regs);
-#endif
/* Make sure floating point registers are stored in regs */
flush_fp_to_thread(current);
@@ -482,6 +451,15 @@ static long restore_user_regs(struct pt_regs *regs,
if (err)
return 1;
+ /*
+ * Do this before updating the thread state in
+ * current->thread.fpr/vr/evr. That way, if we get preempted
+ * and another task grabs the FPU/Altivec/SPE, it won't be
+ * tempted to save the current CPU state into the thread_struct
+ * and corrupt what we are writing there.
+ */
+ discard_lazy_cpu_state();
+
/* force the process to reload the FP registers from
current->thread when it next does FP instructions */
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
@@ -523,18 +501,6 @@ static long restore_user_regs(struct pt_regs *regs,
return 1;
#endif /* CONFIG_SPE */
-#ifndef CONFIG_SMP
- preempt_disable();
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- if (last_task_used_altivec == current)
- last_task_used_altivec = NULL;
-#ifdef CONFIG_SPE
- if (last_task_used_spe == current)
- last_task_used_spe = NULL;
-#endif
- preempt_enable();
-#endif
return 0;
}
@@ -828,12 +794,6 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->trap = 0;
-#ifdef CONFIG_PPC64
- regs->result = 0;
-
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-#endif
return 1;
badframe:
@@ -911,8 +871,8 @@ long sys_swapcontext(struct ucontext __user *old_ctx,
*/
if (do_setcontext(new_ctx, regs, 0))
do_exit(SIGSEGV);
- sigreturn_exit(regs);
- /* doesn't actually return back to here */
+
+ set_thread_flag(TIF_RESTOREALL);
return 0;
}
@@ -945,12 +905,11 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
* nobody does any...
*/
compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
- return (int)regs->result;
#else
do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
- sigreturn_exit(regs); /* doesn't return here */
- return 0;
#endif
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
bad:
force_sig(SIGSEGV, current);
@@ -1041,9 +1000,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
*/
do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
- sigreturn_exit(regs);
- /* doesn't actually return back to here */
-
+ set_thread_flag(TIF_RESTOREALL);
out:
return 0;
}
@@ -1107,12 +1064,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->trap = 0;
-#ifdef CONFIG_PPC64
- regs->result = 0;
-
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-#endif
return 1;
@@ -1160,12 +1111,8 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|| restore_user_regs(regs, sr, 1))
goto badframe;
-#ifdef CONFIG_PPC64
- return (int)regs->result;
-#else
- sigreturn_exit(regs); /* doesn't return */
+ set_thread_flag(TIF_RESTOREALL);
return 0;
-#endif
badframe:
force_sig(SIGSEGV, current);
@@ -1181,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
siginfo_t info;
struct k_sigaction ka;
- unsigned int frame, newsp;
+ unsigned int newsp;
int signr, ret;
#ifdef CONFIG_PPC32
@@ -1192,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
}
#endif
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else if (!oldset)
oldset = &current->blocked;
- newsp = frame = 0;
-
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
#ifdef CONFIG_PPC32
no_signal:
@@ -1226,8 +1173,14 @@ no_signal:
}
}
- if (signr == 0)
+ if (signr == 0) {
+ /* No signal to deliver -- put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
return 0; /* no signals delivered */
+ }
if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
&& !on_sig_stack(regs->gpr[1]))
@@ -1260,6 +1213,10 @@ no_signal:
sigaddset(&current->blocked, signr);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
+ /* A signal was successfully delivered; the saved sigmask is in
+ its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return ret;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 1decf2785530..b3193116e686 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -67,40 +67,6 @@ struct rt_sigframe {
char abigap[288];
} __attribute__ ((aligned (16)));
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
- int p6, int p7, struct pt_regs *regs)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- regs->result = -EINTR;
- regs->gpr[3] = EINTR;
- regs->ccr |= 0x10000000;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(&saveset, regs))
- return 0;
- }
-}
-
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs *regs)
@@ -152,6 +118,14 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
err |= __put_user(0, &sc->v_regs);
#endif /* CONFIG_ALTIVEC */
err |= __put_user(&sc->gp_regs, &sc->regs);
+ if (!FULL_REGS(regs)) {
+ /* Zero out the unsaved GPRs to avoid information
+ leak, and set TIF_SAVE_NVGPRS to ensure that the
+ registers do actually get saved later. */
+ memset(&regs->gpr[14], 0, 18 * sizeof(unsigned long));
+ set_thread_flag(TIF_SAVE_NVGPRS);
+ current_thread_info()->nvgprs_frame = &sc->gp_regs;
+ }
err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
err |= __put_user(signr, &sc->signal);
@@ -197,10 +171,20 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
if (!sig)
regs->gpr[13] = save_r13;
- err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
if (set != NULL)
err |= __get_user(set->sig[0], &sc->oldmask);
+ /*
+ * Do this before updating the thread state in
+ * current->thread.fpr/vr. That way, if we get preempted
+ * and another task grabs the FPU/Altivec, it won't be
+ * tempted to save the current CPU state into the thread_struct
+ * and corrupt what we are writing there.
+ */
+ discard_lazy_cpu_state();
+
+ err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
+
#ifdef CONFIG_ALTIVEC
err |= __get_user(v_regs, &sc->v_regs);
err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
@@ -219,14 +203,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
current->thread.vrsave = 0;
#endif /* CONFIG_ALTIVEC */
-#ifndef CONFIG_SMP
- preempt_disable();
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- if (last_task_used_altivec == current)
- last_task_used_altivec = NULL;
- preempt_enable();
-#endif
/* Force reload of FP/VEC */
regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
@@ -340,6 +316,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
do_exit(SIGSEGV);
/* This returns like rt_sigreturn */
+ set_thread_flag(TIF_RESTOREALL);
return 0;
}
@@ -372,7 +349,8 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
*/
do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]);
- return regs->result;
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
badframe:
#if DEBUG_SIG
@@ -454,9 +432,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
if (err)
goto badframe;
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-
return 1;
badframe:
@@ -502,6 +477,8 @@ static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
* we only get here if there is a handler, we dont restart.
*/
regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
break;
case -ERESTARTSYS:
/* ERESTARTSYS means to restart the syscall if there is no
@@ -509,6 +486,8 @@ static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
*/
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
break;
}
/* fallthrough */
@@ -541,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (test_thread_flag(TIF_32BIT))
return do_signal32(oldset, regs);
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
+ int ret;
+
/* Whee! Actually deliver the signal. */
if (TRAP(regs) == 0x0C00)
syscall_restart(regs, &ka);
@@ -558,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (current->thread.dabr)
set_dabr(current->thread.dabr);
- return handle_signal(signr, &ka, &info, oldset, regs);
+ ret = handle_signal(signr, &ka, &info, oldset, regs);
+
+ /* If a signal was successfully delivered, the saved sigmask is in
+ its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
+ if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+ return ret;
}
if (TRAP(regs) == 0x0C00) { /* System Call! */
@@ -574,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
regs->result = 0;
}
}
+ /* No signal to deliver -- put the saved sigmask back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
return 0;
}
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 30374d2f88e5..c8458c531b25 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -31,6 +31,7 @@
#include <linux/sysdev.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
+#include <linux/topology.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
@@ -75,6 +76,8 @@ void smp_call_function_interrupt(void);
int smt_enabled_at_boot = 1;
+static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
+
#ifdef CONFIG_MPIC
int __init smp_mpic_probe(void)
{
@@ -123,11 +126,16 @@ void smp_message_recv(int msg, struct pt_regs *regs)
/* XXX Do we have to do this? */
set_need_resched();
break;
-#ifdef CONFIG_DEBUGGER
case PPC_MSG_DEBUGGER_BREAK:
+ if (crash_ipi_function_ptr) {
+ crash_ipi_function_ptr(regs);
+ break;
+ }
+#ifdef CONFIG_DEBUGGER
debugger_ipi(regs);
break;
-#endif
+#endif /* CONFIG_DEBUGGER */
+ /* FALLTHROUGH */
default:
printk("SMP %d: smp_message_recv(): unknown msg %d\n",
smp_processor_id(), msg);
@@ -147,6 +155,17 @@ void smp_send_debugger_break(int cpu)
}
#endif
+#ifdef CONFIG_KEXEC
+void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
+{
+ crash_ipi_function_ptr = crash_ipi_callback;
+ if (crash_ipi_callback) {
+ mb();
+ smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
+ }
+}
+#endif
+
static void stop_this_cpu(void *dummy)
{
local_irq_disable();
@@ -319,8 +338,8 @@ static void __init smp_create_idle(unsigned int cpu)
#ifdef CONFIG_PPC64
paca[cpu].__current = p;
#endif
- current_set[cpu] = p->thread_info;
- p->thread_info->cpu = cpu;
+ current_set[cpu] = task_thread_info(p);
+ task_thread_info(p)->cpu = cpu;
}
void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -356,7 +375,7 @@ void __devinit smp_prepare_boot_cpu(void)
#ifdef CONFIG_PPC64
paca[boot_cpuid].__current = current;
#endif
- current_set[boot_cpuid] = current->thread_info;
+ current_set[boot_cpuid] = task_thread_info(current);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -452,10 +471,6 @@ int __devinit __cpu_up(unsigned int cpu)
if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
return -EINVAL;
-#ifdef CONFIG_PPC64
- paca[cpu].default_decr = tb_ticks_per_jiffy;
-#endif
-
/* Make sure callin-map entry is 0 (can be leftover a CPU
* hotplug
*/
@@ -554,6 +569,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
smp_ops->setup_cpu(boot_cpuid);
set_cpus_allowed(current, old_mask);
+
+ dump_numa_cpu_topology();
}
#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 9c921d1c4084..475249dc2350 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -552,30 +552,6 @@ asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec
return ret;
}
-asmlinkage int compat_sys_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_read((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- compat_ptr(ubuf));
-}
-
-asmlinkage int compat_sys_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_write((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- compat_ptr(ubuf));
-}
-
-asmlinkage int compat_sys_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
-{
- return sys_pciconfig_iobase(which, in_bus, in_devfn);
-}
-
-
/* Note: it is necessary to treat mode 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)
@@ -956,38 +932,6 @@ long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
advice);
}
-long ppc32_timer_create(clockid_t clock,
- struct compat_sigevent __user *ev32,
- timer_t __user *timer_id)
-{
- sigevent_t event;
- timer_t t;
- long err;
- mm_segment_t savefs;
-
- if (ev32 == NULL)
- return sys_timer_create(clock, NULL, timer_id);
-
- if (get_compat_sigevent(&event, ev32))
- return -EFAULT;
-
- if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
- return -EFAULT;
-
- savefs = get_fs();
- set_fs(KERNEL_DS);
- /* The __user pointer casts are valid due to the set_fs() */
- err = sys_timer_create(clock,
- (sigevent_t __user *) &event,
- (timer_t __user *) &t);
- set_fs(savefs);
-
- if (err == 0)
- err = __put_user(t, timer_id);
-
- return err;
-}
-
asmlinkage long compat_sys_add_key(const char __user *_type,
const char __user *_description,
const void __user *_payload,
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c
index 91b93d917b64..ad895c99813b 100644
--- a/arch/powerpc/kernel/syscalls.c
+++ b/arch/powerpc/kernel/syscalls.c
@@ -43,9 +43,6 @@
#include <asm/time.h>
#include <asm/unistd.h>
-extern unsigned long wall_jiffies;
-
-
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
@@ -311,31 +308,6 @@ int sys_olduname(struct oldold_utsname __user *name)
return error? -EFAULT: 0;
}
-#ifdef CONFIG_PPC64
-time_t sys64_time(time_t __user * tloc)
-{
- time_t secs;
- time_t usecs;
-
- long tb_delta = tb_ticks_since(tb_last_stamp);
- tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy;
-
- secs = xtime.tv_sec;
- usecs = (xtime.tv_nsec/1000) + tb_delta / tb_ticks_per_usec;
- while (usecs >= USEC_PER_SEC) {
- ++secs;
- usecs -= USEC_PER_SEC;
- }
-
- if (tloc) {
- if (put_user(secs,tloc))
- secs = -EFAULT;
- }
-
- return secs;
-}
-#endif
-
long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low,
u32 len_high, u32 len_low)
{
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 65eaea91b499..007b15ee36d2 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -54,7 +54,7 @@ SYSCALL(link)
SYSCALL(unlink)
COMPAT_SYS(execve)
SYSCALL(chdir)
-SYSX(sys64_time,compat_sys_time,sys_time)
+COMPAT_SYS(time)
SYSCALL(mknod)
SYSCALL(chmod)
SYSCALL(lchown)
@@ -113,7 +113,7 @@ SYSCALL(sgetmask)
COMPAT_SYS(ssetmask)
SYSCALL(setreuid)
SYSCALL(setregid)
-SYSX(sys_ni_syscall,ppc32_sigsuspend,ppc_sigsuspend)
+SYS32ONLY(sigsuspend)
COMPAT_SYS(sigpending)
COMPAT_SYS(sethostname)
COMPAT_SYS(setrlimit)
@@ -160,7 +160,7 @@ SYSCALL(swapoff)
COMPAT_SYS(sysinfo)
COMPAT_SYS(ipc)
SYSCALL(fsync)
-SYSX(sys_ni_syscall,ppc32_sigreturn,sys_sigreturn)
+SYS32ONLY(sigreturn)
PPC_SYS(clone)
COMPAT_SYS(setdomainname)
PPC_SYS(newuname)
@@ -213,13 +213,13 @@ COMPAT_SYS(nfsservctl)
SYSCALL(setresgid)
SYSCALL(getresgid)
COMPAT_SYS(prctl)
-SYSX(ppc64_rt_sigreturn,ppc32_rt_sigreturn,sys_rt_sigreturn)
+COMPAT_SYS(rt_sigreturn)
COMPAT_SYS(rt_sigaction)
COMPAT_SYS(rt_sigprocmask)
COMPAT_SYS(rt_sigpending)
COMPAT_SYS(rt_sigtimedwait)
COMPAT_SYS(rt_sigqueueinfo)
-SYSX(ppc64_rt_sigsuspend,ppc32_rt_sigsuspend,ppc_rt_sigsuspend)
+COMPAT_SYS(rt_sigsuspend)
COMPAT_SYS(pread64)
COMPAT_SYS(pwrite64)
SYSCALL(chown)
@@ -239,9 +239,9 @@ SYS32ONLY(ftruncate64)
SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
-COMPAT_SYS(pciconfig_read)
-COMPAT_SYS(pciconfig_write)
-COMPAT_SYS(pciconfig_iobase)
+SYSCALL(pciconfig_read)
+SYSCALL(pciconfig_write)
+SYSCALL(pciconfig_iobase)
SYSCALL(ni_syscall)
SYSCALL(getdents64)
SYSCALL(pivot_root)
@@ -281,7 +281,7 @@ SYSCALL(epoll_create)
SYSCALL(epoll_ctl)
SYSCALL(epoll_wait)
SYSCALL(remap_file_pages)
-SYSX(sys_timer_create,ppc32_timer_create,sys_timer_create)
+SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create)
COMPAT_SYS(timer_settime)
COMPAT_SYS(timer_gettime)
SYSCALL(timer_getoverrun)
@@ -290,7 +290,7 @@ COMPAT_SYS(clock_settime)
COMPAT_SYS(clock_gettime)
COMPAT_SYS(clock_getres)
COMPAT_SYS(clock_nanosleep)
-SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
+COMPAT_SYS(swapcontext)
COMPAT_SYS(tgkill)
COMPAT_SYS(utimes)
COMPAT_SYS(statfs64)
@@ -319,3 +319,7 @@ COMPAT_SYS(ioprio_get)
SYSCALL(inotify_init)
SYSCALL(inotify_add_watch)
SYSCALL(inotify_rm_watch)
+SYSCALL(spu_run)
+SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index de8479769bb7..c4a294d657b9 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -431,7 +431,7 @@ void timer_interrupt(struct pt_regs * regs)
profile_tick(CPU_PROFILING, regs);
#ifdef CONFIG_PPC_ISERIES
- get_paca()->lppaca.int_dword.fields.decr_int = 0;
+ get_lppaca()->int_dword.fields.decr_int = 0;
#endif
while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu)))
@@ -699,10 +699,6 @@ void __init time_init(void)
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res);
tb_to_xs = res.result_low;
-#ifdef CONFIG_PPC64
- get_paca()->default_decr = tb_ticks_per_jiffy;
-#endif
-
/*
* Compute scale factor for sched_clock.
* The calibrate_decr() function has set tb_ticks_per_sec,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 1511454c4690..7509aa6474f2 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -31,6 +31,7 @@
#include <linux/prctl.h>
#include <linux/delay.h>
#include <linux/kprobes.h>
+#include <linux/kexec.h>
#include <asm/kdebug.h>
#include <asm/pgtable.h>
@@ -95,7 +96,7 @@ static DEFINE_SPINLOCK(die_lock);
int die(const char *str, struct pt_regs *regs, long err)
{
- static int die_counter;
+ static int die_counter, crash_dump_start = 0;
int nl = 0;
if (debugger(regs))
@@ -156,7 +157,21 @@ int die(const char *str, struct pt_regs *regs, long err)
print_modules();
show_regs(regs);
bust_spinlocks(0);
+
+ if (!crash_dump_start && kexec_should_crash(current)) {
+ crash_dump_start = 1;
+ spin_unlock_irq(&die_lock);
+ crash_kexec(regs);
+ /* NOTREACHED */
+ }
spin_unlock_irq(&die_lock);
+ if (crash_dump_start)
+ /*
+ * Only for soft-reset: Other CPUs will be responded to an IPI
+ * sent by first kexec CPU.
+ */
+ for(;;)
+ ;
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -215,8 +230,10 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
void system_reset_exception(struct pt_regs *regs)
{
/* See if any machine dependent calls */
- if (ppc_md.system_reset_exception)
- ppc_md.system_reset_exception(regs);
+ if (ppc_md.system_reset_exception) {
+ if (ppc_md.system_reset_exception(regs))
+ return;
+ }
die("System Reset", regs, SIGABRT);
@@ -886,12 +903,10 @@ void altivec_unavailable_exception(struct pt_regs *regs)
die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
}
-#if defined(CONFIG_PPC64) || defined(CONFIG_E500)
void performance_monitor_exception(struct pt_regs *regs)
{
perf_irq(regs);
}
-#endif
#ifdef CONFIG_8xx
void SoftwareEmulation(struct pt_regs *regs)
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 0d878e72fc44..3774e80094f5 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -15,11 +15,36 @@
#include <linux/sched.h>
#include <linux/console.h>
#include <asm/processor.h>
+#include <asm/udbg.h>
-void (*udbg_putc)(unsigned char c);
-unsigned char (*udbg_getc)(void);
+void (*udbg_putc)(char c);
+int (*udbg_getc)(void);
int (*udbg_getc_poll)(void);
+/*
+ * Early debugging facilities. You can enable _one_ of these via .config,
+ * if you do so your kernel _will not boot_ on anything else. Be careful.
+ */
+void __init udbg_early_init(void)
+{
+#if defined(CONFIG_PPC_EARLY_DEBUG_LPAR)
+ /* For LPAR machines that have an HVC console on vterm 0 */
+ udbg_init_debug_lpar();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
+ /* For use on Apple G5 machines */
+ udbg_init_pmac_realmode();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS)
+ /* RTAS panel debug */
+ udbg_init_rtas();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
+ /* Maple real mode debug */
+ udbg_init_maple_realmode();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
+ /* For iSeries - hit Ctrl-x Ctrl-x to see the output */
+ udbg_init_iseries();
+#endif
+}
+
/* udbg library, used by xmon et al */
void udbg_puts(const char *s)
{
@@ -57,8 +82,8 @@ int udbg_write(const char *s, int n)
int udbg_read(char *buf, int buflen)
{
- char c, *p = buf;
- int i;
+ char *p = buf;
+ int i, c;
if (!udbg_getc)
return 0;
@@ -66,8 +91,11 @@ int udbg_read(char *buf, int buflen)
for (i = 0; i < buflen; ++i) {
do {
c = udbg_getc();
+ if (c == -1 && i == 0)
+ return -1;
+
} while (c == 0x11 || c == 0x13);
- if (c == 0)
+ if (c == 0 || c == -1)
break;
*p++ = c;
}
@@ -78,7 +106,7 @@ int udbg_read(char *buf, int buflen)
#define UDBG_BUFSIZE 256
void udbg_printf(const char *fmt, ...)
{
- unsigned char buf[UDBG_BUFSIZE];
+ char buf[UDBG_BUFSIZE];
va_list args;
va_start(args, fmt);
@@ -87,6 +115,12 @@ void udbg_printf(const char *fmt, ...)
va_end(args);
}
+void __init udbg_progress(char *s, unsigned short hex)
+{
+ udbg_puts(s);
+ udbg_puts("\n");
+}
+
/*
* Early boot console based on udbg
*/
@@ -99,7 +133,7 @@ static void udbg_console_write(struct console *con, const char *s,
static struct console udbg_console = {
.name = "udbg",
.write = udbg_console_write,
- .flags = CON_PRINTBUFFER,
+ .flags = CON_PRINTBUFFER | CON_ENABLED,
.index = -1,
};
@@ -107,15 +141,19 @@ static int early_console_initialized;
void __init disable_early_printk(void)
{
+#if 1
if (!early_console_initialized)
return;
unregister_console(&udbg_console);
early_console_initialized = 0;
+#endif
}
/* called by setup_system */
void register_early_udbg_console(void)
{
+ if (early_console_initialized)
+ return;
early_console_initialized = 1;
register_console(&udbg_console);
}
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 9313574ab935..2da65a9c93f6 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -43,9 +43,11 @@ struct NS16550 {
#define LSR_TEMT 0x40 /* Xmitter empty */
#define LSR_ERR 0x80 /* Error */
+#define LCR_DLAB 0x80
+
static volatile struct NS16550 __iomem *udbg_comport;
-static void udbg_550_putc(unsigned char c)
+static void udbg_550_putc(char c)
{
if (udbg_comport) {
while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
@@ -67,39 +69,80 @@ static int udbg_550_getc_poll(void)
return -1;
}
-static unsigned char udbg_550_getc(void)
+static int 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;
+ return -1;
}
-void udbg_init_uart(void __iomem *comport, unsigned int speed)
+void udbg_init_uart(void __iomem *comport, unsigned int speed,
+ unsigned int clock)
{
- u16 dll = speed ? (115200 / speed) : 12;
+ unsigned int dll, base_bauds = clock / 16;
+
+ if (speed == 0)
+ speed = 9600;
+ dll = base_bauds / speed;
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 */
+ out_8(&udbg_comport->lcr, LCR_DLAB);
+ out_8(&udbg_comport->dll, dll & 0xff);
+ out_8(&udbg_comport->dlm, dll >> 8);
+ /* 8 data, 1 stop, no parity */
+ out_8(&udbg_comport->lcr, 0x03);
+ /* RTS/DTR */
+ out_8(&udbg_comport->mcr, 0x03);
+ /* Clear & enable FIFOs */
+ out_8(&udbg_comport->fcr ,0x07);
udbg_putc = udbg_550_putc;
udbg_getc = udbg_550_getc;
udbg_getc_poll = udbg_550_getc_poll;
}
}
+unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
+{
+ unsigned int dll, dlm, divisor, prescaler, speed;
+ u8 old_lcr;
+ volatile struct NS16550 __iomem *port = comport;
+
+ old_lcr = in_8(&port->lcr);
+
+ /* select divisor latch registers. */
+ out_8(&port->lcr, LCR_DLAB);
+
+ /* now, read the divisor */
+ dll = in_8(&port->dll);
+ dlm = in_8(&port->dlm);
+ divisor = dlm << 8 | dll;
+
+ /* check prescaling */
+ if (in_8(&port->mcr) & 0x80)
+ prescaler = 4;
+ else
+ prescaler = 1;
+
+ /* restore the LCR */
+ out_8(&port->lcr, old_lcr);
+
+ /* calculate speed */
+ speed = (clock / prescaler) / (divisor * 16);
+
+ /* sanity check */
+ if (speed < 0 || speed > (clock / 16))
+ speed = 9600;
+
+ return speed;
+}
+
#ifdef CONFIG_PPC_MAPLE
void udbg_maple_real_putc(unsigned char c)
{
@@ -112,7 +155,7 @@ void udbg_maple_real_putc(unsigned char c)
}
}
-void udbg_init_maple_realmode(void)
+void __init udbg_init_maple_realmode(void)
{
udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
diff --git a/arch/powerpc/kernel/vdso32/.gitignore b/arch/powerpc/kernel/vdso32/.gitignore
new file mode 100644
index 000000000000..e45fba9d0ced
--- /dev/null
+++ b/arch/powerpc/kernel/vdso32/.gitignore
@@ -0,0 +1 @@
+vdso32.lds
diff --git a/arch/powerpc/kernel/vdso64/.gitignore b/arch/powerpc/kernel/vdso64/.gitignore
new file mode 100644
index 000000000000..3fd18cf9fec2
--- /dev/null
+++ b/arch/powerpc/kernel/vdso64/.gitignore
@@ -0,0 +1 @@
+vdso64.lds
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 71a6addf9f7f..13c655ba2841 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -76,7 +76,7 @@ static void vio_bus_shutdown(struct device *dev)
struct vio_dev *viodev = to_vio_dev(dev);
struct vio_driver *viodrv = to_vio_driver(dev->driver);
- if (viodrv->shutdown)
+ if (dev->driver && viodrv->shutdown)
viodrv->shutdown(viodev);
}
@@ -91,9 +91,6 @@ int vio_register_driver(struct vio_driver *viodrv)
/* fill in 'struct driver' fields */
viodrv->driver.bus = &vio_bus_type;
- viodrv->driver.probe = vio_bus_probe;
- viodrv->driver.remove = vio_bus_remove;
- viodrv->driver.shutdown = vio_bus_shutdown;
return driver_register(&viodrv->driver);
}
@@ -293,6 +290,9 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
struct bus_type vio_bus_type = {
.name = "vio",
- .hotplug = vio_hotplug,
+ .uevent = vio_hotplug,
.match = vio_bus_match,
+ .probe = vio_bus_probe,
+ .remove = vio_bus_remove,
+ .shutdown = vio_bus_shutdown,
};
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c
index 35bd03c41dd1..8362fa272ca5 100644
--- a/arch/powerpc/lib/locks.c
+++ b/arch/powerpc/lib/locks.c
@@ -28,15 +28,13 @@
void __spin_yield(raw_spinlock_t *lock)
{
unsigned int lock_value, holder_cpu, yield_count;
- struct paca_struct *holder_paca;
lock_value = lock->slock;
if (lock_value == 0)
return;
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
- holder_paca = &paca[holder_cpu];
- yield_count = holder_paca->lppaca.yield_count;
+ yield_count = lppaca[holder_cpu].yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
@@ -60,15 +58,13 @@ void __rw_yield(raw_rwlock_t *rw)
{
int lock_value;
unsigned int holder_cpu, yield_count;
- struct paca_struct *holder_paca;
lock_value = rw->lock;
if (lock_value >= 0)
return; /* no write lock at present */
holder_cpu = lock_value & 0xffff;
BUG_ON(holder_cpu >= NR_CPUS);
- holder_paca = &paca[holder_cpu];
- yield_count = holder_paca->lppaca.yield_count;
+ yield_count = lppaca[holder_cpu].yield_count;
if ((yield_count & 1) == 0)
return; /* virtual cpu is currently running */
rmb();
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 93d4fbfdb724..a4815d316722 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -81,7 +81,8 @@ static int store_updates_sp(struct pt_regs *regs)
}
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-static void do_dabr(struct pt_regs *regs, unsigned long error_code)
+static void do_dabr(struct pt_regs *regs, unsigned long address,
+ unsigned long error_code)
{
siginfo_t info;
@@ -99,7 +100,7 @@ static void do_dabr(struct pt_regs *regs, unsigned long error_code)
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_HWBKPT;
- info.si_addr = (void __user *)regs->nip;
+ info.si_addr = (void __user *)address;
force_sig_info(SIGTRAP, &info, current);
}
#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
@@ -159,7 +160,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
if (error_code & DSISR_DABRMATCH) {
/* DABR match */
- do_dabr(regs, error_code);
+ do_dabr(regs, address, error_code);
return 0;
}
#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index a606504678bd..149351a84b94 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -368,7 +368,7 @@ static unsigned long __init htab_get_table_size(void)
unsigned long mem_size, rnd_mem_size, pteg_count;
/* If hash size isn't already provided by the platform, we try to
- * retreive it from the device-tree. If it's not there neither, we
+ * retrieve it from the device-tree. If it's not there neither, we
* calculate it now based on the total RAM size
*/
if (ppc64_pft_size == 0)
@@ -456,7 +456,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].base + KERNELBASE;
+ base = (unsigned long)__va(lmb.memory.region[i].base);
size = lmb.memory.region[i].size;
DBG("creating mapping for region: %lx : %lx\n", base, size);
@@ -498,8 +498,8 @@ void __init htab_initialize(void)
* for either 4K or 16MB pages.
*/
if (tce_alloc_start) {
- tce_alloc_start += KERNELBASE;
- tce_alloc_end += KERNELBASE;
+ tce_alloc_start = (unsigned long)__va(tce_alloc_start);
+ tce_alloc_end = (unsigned long)__va(tce_alloc_end);
if (base + size >= tce_alloc_start)
tce_alloc_start = base + size + 1;
@@ -644,6 +644,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
DBG_LOW(" -> rc=%d\n", rc);
return rc;
}
+EXPORT_SYMBOL_GPL(hash_page);
void hash_preload(struct mm_struct *mm, unsigned long ea,
unsigned long access, unsigned long trap)
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 54131b877da3..b51bb28c054b 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -549,6 +549,17 @@ fail:
return addr;
}
+static int htlb_check_hinted_area(unsigned long addr, unsigned long len)
+{
+ struct vm_area_struct *vma;
+
+ vma = find_vma(current->mm, addr);
+ if (!vma || ((addr + len) <= vma->vm_start))
+ return 0;
+
+ return -ENOMEM;
+}
+
static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
{
unsigned long addr = 0;
@@ -618,15 +629,28 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
if (!cpu_has_feature(CPU_FTR_16M_PAGE))
return -EINVAL;
+ /* Paranoia, caller should have dealt with this */
+ BUG_ON((addr + len) < addr);
+
if (test_thread_flag(TIF_32BIT)) {
+ /* Paranoia, caller should have dealt with this */
+ BUG_ON((addr + len) > 0x100000000UL);
+
curareas = current->mm->context.low_htlb_areas;
- /* First see if we can do the mapping in the existing
- * low areas */
+ /* First see if we can use the hint address */
+ if (addr && (htlb_check_hinted_area(addr, len) == 0)) {
+ areamask = LOW_ESID_MASK(addr, len);
+ if (open_low_hpage_areas(current->mm, areamask) == 0)
+ return addr;
+ }
+
+ /* Next see if we can map in the existing low areas */
addr = htlb_get_low_area(len, curareas);
if (addr != -ENOMEM)
return addr;
+ /* Finally go looking for areas to open */
lastshift = 0;
for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
! lastshift; areamask >>=1) {
@@ -641,12 +665,22 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
} else {
curareas = current->mm->context.high_htlb_areas;
- /* First see if we can do the mapping in the existing
- * high areas */
+ /* First see if we can use the hint address */
+ /* We discourage 64-bit processes from doing hugepage
+ * mappings below 4GB (must use MAP_FIXED) */
+ if ((addr >= 0x100000000UL)
+ && (htlb_check_hinted_area(addr, len) == 0)) {
+ areamask = HTLB_AREA_MASK(addr, len);
+ if (open_high_hpage_areas(current->mm, areamask) == 0)
+ return addr;
+ }
+
+ /* Next see if we can map in the existing high areas */
addr = htlb_get_high_area(len, curareas);
if (addr != -ENOMEM)
return addr;
+ /* Finally go looking for areas to open */
lastshift = 0;
for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
! lastshift; areamask >>=1) {
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c
index f9587bcc6a48..8b0c132bc163 100644
--- a/arch/powerpc/mm/imalloc.c
+++ b/arch/powerpc/mm/imalloc.c
@@ -107,6 +107,7 @@ static int im_region_status(unsigned long v_addr, unsigned long size,
if (v_addr < (unsigned long) tmp->addr + tmp->size)
break;
+ *vm = NULL;
if (tmp) {
if (im_region_overlaps(v_addr, size, tmp))
return IM_REGION_OVERLAP;
@@ -127,7 +128,6 @@ static int im_region_status(unsigned long v_addr, unsigned long size,
}
}
- *vm = NULL;
return IM_REGION_UNUSED;
}
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 7d4b8b5f0606..7d0d75c11848 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -188,6 +188,11 @@ void __init MMU_init(void)
if (ppc_md.progress)
ppc_md.progress("MMU:exit", 0x211);
+
+ /* From now on, btext is no longer BAT mapped if it was at all */
+#ifdef CONFIG_BOOTX_TEXT
+ btext_unmap();
+#endif
}
/* This is only called until mem_init is done. */
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index ed6ed2e30dac..15aac0d78dfa 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -114,19 +114,18 @@ void online_page(struct page *page)
num_physpages++;
}
-/*
- * This works only for the non-NUMA case. Later, we'll need a lookup
- * to convert from real physical addresses to nid, that doesn't use
- * pfn_to_nid().
- */
int __devinit add_memory(u64 start, u64 size)
{
- struct pglist_data *pgdata = NODE_DATA(0);
+ struct pglist_data *pgdata;
struct zone *zone;
+ int nid;
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- start += KERNELBASE;
+ nid = hot_add_scn_to_nid(start);
+ pgdata = NODE_DATA(nid);
+
+ start = __va(start);
create_section_mapping(start, start + size);
/* this should work for most non-highmem platforms */
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index ba7a3055a9fc..2863a912bcd0 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(node_data);
static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
static int min_common_depth;
+static int n_mem_addr_cells, n_mem_size_cells;
/*
* We need somewhere to store start/end/node for each region until we have
@@ -254,32 +255,20 @@ static int __init find_min_common_depth(void)
return depth;
}
-static int __init get_mem_addr_cells(void)
+static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells)
{
struct device_node *memory = NULL;
- int rc;
memory = of_find_node_by_type(memory, "memory");
if (!memory)
- return 0; /* it won't matter */
+ panic("numa.c: No memory nodes found!");
- rc = prom_n_addr_cells(memory);
- return rc;
+ *n_addr_cells = prom_n_addr_cells(memory);
+ *n_size_cells = prom_n_size_cells(memory);
+ of_node_put(memory);
}
-static int __init get_mem_size_cells(void)
-{
- struct device_node *memory = NULL;
- int rc;
-
- memory = of_find_node_by_type(memory, "memory");
- if (!memory)
- return 0; /* it won't matter */
- rc = prom_n_size_cells(memory);
- return rc;
-}
-
-static unsigned long __init read_n_cells(int n, unsigned int **buf)
+static unsigned long __devinit read_n_cells(int n, unsigned int **buf)
{
unsigned long result = 0;
@@ -386,7 +375,6 @@ static int __init parse_numa_properties(void)
{
struct device_node *cpu = NULL;
struct device_node *memory = NULL;
- int addr_cells, size_cells;
int max_domain;
unsigned long i;
@@ -425,8 +413,7 @@ static int __init parse_numa_properties(void)
}
}
- addr_cells = get_mem_addr_cells();
- size_cells = get_mem_size_cells();
+ get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
memory = NULL;
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
unsigned long start;
@@ -436,15 +423,21 @@ static int __init parse_numa_properties(void)
unsigned int *memcell_buf;
unsigned int len;
- memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+ memcell_buf = (unsigned int *)get_property(memory,
+ "linux,usable-memory", &len);
+ if (!memcell_buf || len <= 0)
+ memcell_buf =
+ (unsigned int *)get_property(memory, "reg",
+ &len);
if (!memcell_buf || len <= 0)
continue;
- ranges = memory->n_addrs;
+ /* ranges in cell */
+ ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
new_range:
/* these are order-sensitive, and modify the buffer pointer */
- start = read_n_cells(addr_cells, &memcell_buf);
- size = read_n_cells(size_cells, &memcell_buf);
+ start = read_n_cells(n_mem_addr_cells, &memcell_buf);
+ size = read_n_cells(n_mem_size_cells, &memcell_buf);
numa_domain = of_node_numa_domain(memory);
@@ -497,7 +490,41 @@ static void __init setup_nonnuma(void)
node_set_online(0);
}
-static void __init dump_numa_topology(void)
+void __init dump_numa_cpu_topology(void)
+{
+ unsigned int node;
+ unsigned int cpu, count;
+
+ if (min_common_depth == -1 || !numa_enabled)
+ return;
+
+ for_each_online_node(node) {
+ printk(KERN_INFO "Node %d CPUs:", node);
+
+ count = 0;
+ /*
+ * If we used a CPU iterator here we would miss printing
+ * the holes in the cpumap.
+ */
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+ if (count == 0)
+ printk(" %u", cpu);
+ ++count;
+ } else {
+ if (count > 1)
+ printk("-%u", cpu - 1);
+ count = 0;
+ }
+ }
+
+ if (count > 1)
+ printk("-%u", NR_CPUS - 1);
+ printk("\n");
+ }
+}
+
+static void __init dump_numa_memory_topology(void)
{
unsigned int node;
unsigned int count;
@@ -529,7 +556,6 @@ static void __init dump_numa_topology(void)
printk("-0x%lx", i);
printk("\n");
}
- return;
}
/*
@@ -591,7 +617,7 @@ void __init do_init_bootmem(void)
if (parse_numa_properties())
setup_nonnuma();
else
- dump_numa_topology();
+ dump_numa_memory_topology();
register_cpu_notifier(&ppc64_numa_nb);
@@ -730,3 +756,60 @@ static int __init early_numa(char *p)
return 0;
}
early_param("numa", early_numa);
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * Find the node associated with a hot added memory section. Section
+ * corresponds to a SPARSEMEM section, not an LMB. It is assumed that
+ * sections are fully contained within a single LMB.
+ */
+int hot_add_scn_to_nid(unsigned long scn_addr)
+{
+ struct device_node *memory = NULL;
+ nodemask_t nodes;
+ int numa_domain = 0;
+
+ if (!numa_enabled || (min_common_depth < 0))
+ return numa_domain;
+
+ while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
+ unsigned long start, size;
+ int ranges;
+ unsigned int *memcell_buf;
+ unsigned int len;
+
+ memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
+ if (!memcell_buf || len <= 0)
+ continue;
+
+ /* ranges in cell */
+ ranges = (len >> 2) / (n_mem_addr_cells + n_mem_size_cells);
+ha_new_range:
+ start = read_n_cells(n_mem_addr_cells, &memcell_buf);
+ size = read_n_cells(n_mem_size_cells, &memcell_buf);
+ numa_domain = of_node_numa_domain(memory);
+
+ /* Domains not present at boot default to 0 */
+ if (!node_online(numa_domain))
+ numa_domain = any_online_node(NODE_MASK_ALL);
+
+ if ((scn_addr >= start) && (scn_addr < (start + size))) {
+ of_node_put(memory);
+ goto got_numa_domain;
+ }
+
+ if (--ranges) /* process all ranges in cell */
+ goto ha_new_range;
+ }
+ BUG(); /* section address should be found above */
+
+ /* Temporary code to ensure that returned node is not empty */
+got_numa_domain:
+ nodes_setall(nodes);
+ while (NODE_DATA(numa_domain)->node_spanned_pages == 0) {
+ node_clear(numa_domain, nodes);
+ numa_domain = any_online_node(nodes);
+ }
+ return numa_domain;
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 2ffca63602c5..7b278d83739e 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -174,7 +174,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
pa = addr & PAGE_MASK;
size = PAGE_ALIGN(addr + size) - pa;
- if (size == 0)
+ if ((size == 0) || (pa == 0))
return NULL;
if (mem_init_done) {
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 60e852f2f8e5..ffc8ed4de62d 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -75,7 +75,7 @@ static void slb_flush_and_rebolt(void)
vflags = SLB_VSID_KERNEL | virtual_llp;
ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
- if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
+ if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET)
ksp_esid_data &= ~SLB_ESID_V;
/* We need to do this all in asm, so we're sure we don't touch
@@ -87,8 +87,8 @@ static void slb_flush_and_rebolt(void)
/* Slot 2 - kernel stack */
"slbmte %2,%3\n"
"isync"
- :: "r"(mk_vsid_data(VMALLOCBASE, vflags)),
- "r"(mk_esid_data(VMALLOCBASE, 1)),
+ :: "r"(mk_vsid_data(VMALLOC_START, vflags)),
+ "r"(mk_esid_data(VMALLOC_START, 1)),
"r"(mk_vsid_data(ksp_esid_data, lflags)),
"r"(ksp_esid_data)
: "memory");
@@ -134,14 +134,14 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
else
unmapped_base = TASK_UNMAPPED_BASE_USER64;
- if (pc >= KERNELBASE)
+ if (is_kernel_addr(pc))
return;
slb_allocate(pc);
if (GET_ESID(pc) == GET_ESID(stack))
return;
- if (stack >= KERNELBASE)
+ if (is_kernel_addr(stack))
return;
slb_allocate(stack);
@@ -149,7 +149,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
|| (GET_ESID(stack) == GET_ESID(unmapped_base)))
return;
- if (unmapped_base >= KERNELBASE)
+ if (is_kernel_addr(unmapped_base))
return;
slb_allocate(unmapped_base);
}
@@ -213,10 +213,10 @@ void slb_initialize(void)
asm volatile("isync":::"memory");
asm volatile("slbmte %0,%0"::"r" (0) : "memory");
asm volatile("isync; slbia; isync":::"memory");
- create_slbe(KERNELBASE, lflags, 0);
+ create_slbe(PAGE_OFFSET, lflags, 0);
/* VMALLOC space has 4K pages always for now */
- create_slbe(VMALLOCBASE, vflags, 1);
+ create_slbe(VMALLOC_START, vflags, 1);
/* We don't bolt the stack for the time being - we're in boot,
* so the stack is in the bolted segment. By the time it goes
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 950ffc5848c7..d1acee38f163 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -37,9 +37,9 @@ _GLOBAL(slb_allocate_realmode)
srdi r9,r3,60 /* get region */
srdi r10,r3,28 /* get esid */
- cmpldi cr7,r9,0xc /* cmp KERNELBASE for later use */
+ cmpldi cr7,r9,0xc /* cmp PAGE_OFFSET for later use */
- /* r3 = address, r10 = esid, cr7 = <>KERNELBASE */
+ /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */
blt cr7,0f /* user or kernel? */
/* kernel address: proto-VSID = ESID */
@@ -166,7 +166,7 @@ _GLOBAL(slb_allocate_user)
/*
* Finish loading of an SLB entry and return
*
- * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <>KERNELBASE
+ * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
*/
slb_finish_load:
ASM_VSID_SCRAMBLE(r10,r9)
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 51e7951414e5..82e4951826bc 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -40,7 +40,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
unsigned long entry, group, old_esid, castout_entry, i;
unsigned int global_entry;
struct stab_entry *ste, *castout_ste;
- unsigned long kernel_segment = (esid << SID_SHIFT) >= KERNELBASE;
+ unsigned long kernel_segment = (esid << SID_SHIFT) >= PAGE_OFFSET;
vsid_data = vsid << STE_VSID_SHIFT;
esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V;
@@ -83,7 +83,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
}
/* Dont cast out the first kernel segment */
- if ((castout_ste->esid_data & ESID_MASK) != KERNELBASE)
+ if ((castout_ste->esid_data & ESID_MASK) != PAGE_OFFSET)
break;
castout_entry = (castout_entry + 1) & 0xf;
@@ -122,7 +122,7 @@ static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
unsigned long offset;
/* Kernel or user address? */
- if (ea >= KERNELBASE) {
+ if (is_kernel_addr(ea)) {
vsid = get_kernel_vsid(ea);
} else {
if ((ea >= TASK_SIZE_USER64) || (! mm))
@@ -133,7 +133,7 @@ static int __ste_allocate(unsigned long ea, struct mm_struct *mm)
stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid);
- if (ea < KERNELBASE) {
+ if (!is_kernel_addr(ea)) {
offset = __get_cpu_var(stab_cache_ptr);
if (offset < NR_STAB_CACHE_ENTRIES)
__get_cpu_var(stab_cache[offset++]) = stab_entry;
@@ -190,7 +190,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm)
entry++, ste++) {
unsigned long ea;
ea = ste->esid_data & ESID_MASK;
- if (ea < KERNELBASE) {
+ if (!is_kernel_addr(ea)) {
ste->esid_data = 0;
}
}
@@ -251,7 +251,7 @@ void stabs_alloc(void)
panic("Unable to allocate segment table for CPU %d.\n",
cpu);
- newstab += KERNELBASE;
+ newstab = (unsigned long)__va(newstab);
memset((void *)newstab, 0, HW_PAGE_SIZE);
@@ -270,11 +270,11 @@ void stabs_alloc(void)
*/
void stab_initialize(unsigned long stab)
{
- unsigned long vsid = get_kernel_vsid(KERNELBASE);
+ unsigned long vsid = get_kernel_vsid(PAGE_OFFSET);
unsigned long stabreal;
asm volatile("isync; slbia; isync":::"memory");
- make_ste(stab, GET_ESID(KERNELBASE), vsid);
+ make_ste(stab, GET_ESID(PAGE_OFFSET), vsid);
/* Order update */
asm volatile("sync":::"memory");
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index 859d29a0cac5..bb3afb6e6317 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -168,7 +168,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
batch->mm = mm;
batch->psize = psize;
}
- if (addr < KERNELBASE) {
+ if (!is_kernel_addr(addr)) {
vsid = get_vsid(mm->context.id, addr);
WARN_ON(vsid == 0);
} else
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 0782d0cca89c..554cd7c75321 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -9,3 +9,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofile-y := $(DRIVER_OBJS) common.o
oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o
oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o
+oprofile-$(CONFIG_PPC32) += op_model_7450.o
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index af2c05d20ba5..cc2535be3a73 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -14,9 +14,6 @@
*/
#include <linux/oprofile.h>
-#ifndef __powerpc64__
-#include <linux/slab.h>
-#endif /* ! __powerpc64__ */
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/errno.h>
@@ -31,10 +28,6 @@ static struct op_powerpc_model *model;
static struct op_counter_config ctr[OP_MAX_COUNTER];
static struct op_system_config sys;
-#ifndef __powerpc64__
-static char *cpu_type;
-#endif /* ! __powerpc64__ */
-
static void op_handle_interrupt(struct pt_regs *regs)
{
model->handle_interrupt(regs, ctr);
@@ -53,14 +46,7 @@ static int op_powerpc_setup(void)
model->reg_setup(ctr, &sys, model->num_counters);
/* Configure the registers on all cpus. */
-#ifdef __powerpc64__
on_each_cpu(model->cpu_setup, NULL, 0, 1);
-#else /* __powerpc64__ */
-#if 0
- /* FIXME: Make multi-cpu work */
- on_each_cpu(model->reg_setup, NULL, 0, 1);
-#endif
-#endif /* __powerpc64__ */
return 0;
}
@@ -95,7 +81,7 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
{
int i;
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
/*
* There is one mmcr0, mmcr1 and mmcra for setting the events for
* all of the counters.
@@ -103,7 +89,7 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
-#endif /* __powerpc64__ */
+#endif
for (i = 0; i < model->num_counters; ++i) {
struct dentry *dir;
@@ -115,65 +101,68 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
-#ifdef __powerpc64__
+
/*
- * We dont support per counter user/kernel selection, but
- * we leave the entries because userspace expects them
+ * Classic PowerPC doesn't support per-counter
+ * control like this, but the options are
+ * expected, so they remain. For Freescale
+ * Book-E style performance monitors, we do
+ * support them.
*/
-#endif /* __powerpc64__ */
oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
-#ifndef __powerpc64__
- /* FIXME: Not sure if this is used */
-#endif /* ! __powerpc64__ */
oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
}
oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
oprofilefs_create_ulong(sb, root, "backtrace_spinlocks",
&sys.backtrace_spinlocks);
-#endif /* __powerpc64__ */
+#endif
/* Default to tracing both kernel and user */
sys.enable_kernel = 1;
sys.enable_user = 1;
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
/* Turn on backtracing through spinlocks by default */
sys.backtrace_spinlocks = 1;
-#endif /* __powerpc64__ */
+#endif
return 0;
}
int __init oprofile_arch_init(struct oprofile_operations *ops)
{
-#ifndef __powerpc64__
-#ifdef CONFIG_FSL_BOOKE
- model = &op_model_fsl_booke;
+ if (!cur_cpu_spec->oprofile_cpu_type)
+ return -ENODEV;
+
+ switch (cur_cpu_spec->oprofile_type) {
+#ifdef CONFIG_PPC64
+ case PPC_OPROFILE_RS64:
+ model = &op_model_rs64;
+ break;
+ case PPC_OPROFILE_POWER4:
+ model = &op_model_power4;
+ break;
#else
- return -ENODEV;
+ case PPC_OPROFILE_G4:
+ model = &op_model_7450;
+ break;
#endif
+#ifdef CONFIG_FSL_BOOKE
+ case PPC_OPROFILE_BOOKE:
+ model = &op_model_fsl_booke;
+ break;
+#endif
+ default:
+ return -ENODEV;
+ }
- cpu_type = kmalloc(32, GFP_KERNEL);
- if (NULL == cpu_type)
- return -ENOMEM;
-
- sprintf(cpu_type, "ppc/%s", cur_cpu_spec->cpu_name);
-
- model->num_counters = cur_cpu_spec->num_pmcs;
-
- ops->cpu_type = cpu_type;
-#else /* __powerpc64__ */
- 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;
-#endif /* __powerpc64__ */
ops->create_files = op_powerpc_create_files;
ops->setup = op_powerpc_setup;
ops->shutdown = op_powerpc_shutdown;
@@ -188,8 +177,4 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
void oprofile_arch_exit(void)
{
-#ifndef __powerpc64__
- kfree(cpu_type);
- cpu_type = NULL;
-#endif /* ! __powerpc64__ */
}
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c
new file mode 100644
index 000000000000..32abfdbb0eb1
--- /dev/null
+++ b/arch/powerpc/oprofile/op_model_7450.c
@@ -0,0 +1,206 @@
+/*
+ * oprofile/op_model_7450.c
+ *
+ * Freescale 745x/744x oprofile support, based on fsl_booke support
+ * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, Inc
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/cputable.h>
+#include <asm/page.h>
+#include <asm/pmc.h>
+#include <asm/oprofile_impl.h>
+
+static unsigned long reset_value[OP_MAX_COUNTER];
+
+static int oprofile_running;
+static u32 mmcr0_val, mmcr1_val, mmcr2_val;
+
+#define MMCR0_PMC1_SHIFT 6
+#define MMCR0_PMC2_SHIFT 0
+#define MMCR1_PMC3_SHIFT 27
+#define MMCR1_PMC4_SHIFT 22
+#define MMCR1_PMC5_SHIFT 17
+#define MMCR1_PMC6_SHIFT 11
+
+#define mmcr0_event1(event) \
+ ((event << MMCR0_PMC1_SHIFT) & MMCR0_PMC1SEL)
+#define mmcr0_event2(event) \
+ ((event << MMCR0_PMC2_SHIFT) & MMCR0_PMC2SEL)
+
+#define mmcr1_event3(event) \
+ ((event << MMCR1_PMC3_SHIFT) & MMCR1_PMC3SEL)
+#define mmcr1_event4(event) \
+ ((event << MMCR1_PMC4_SHIFT) & MMCR1_PMC4SEL)
+#define mmcr1_event5(event) \
+ ((event << MMCR1_PMC5_SHIFT) & MMCR1_PMC5SEL)
+#define mmcr1_event6(event) \
+ ((event << MMCR1_PMC6_SHIFT) & MMCR1_PMC6SEL)
+
+#define MMCR0_INIT (MMCR0_FC | MMCR0_FCS | MMCR0_FCP | MMCR0_FCM1 | MMCR0_FCM0)
+
+/* Unfreezes the counters on this CPU, enables the interrupt,
+ * enables the counters to trigger the interrupt, and sets the
+ * counters to only count when the mark bit is not set.
+ */
+static void pmc_start_ctrs(void)
+{
+ u32 mmcr0 = mfspr(SPRN_MMCR0);
+
+ mmcr0 &= ~(MMCR0_FC | MMCR0_FCM0);
+ mmcr0 |= (MMCR0_FCECE | MMCR0_PMC1CE | MMCR0_PMCnCE | MMCR0_PMXE);
+
+ mtspr(SPRN_MMCR0, mmcr0);
+}
+
+/* Disables the counters on this CPU, and freezes them */
+static void pmc_stop_ctrs(void)
+{
+ u32 mmcr0 = mfspr(SPRN_MMCR0);
+
+ mmcr0 |= MMCR0_FC;
+ mmcr0 &= ~(MMCR0_FCECE | MMCR0_PMC1CE | MMCR0_PMCnCE | MMCR0_PMXE);
+
+ mtspr(SPRN_MMCR0, mmcr0);
+}
+
+/* Configures the counters on this CPU based on the global
+ * settings */
+static void fsl7450_cpu_setup(void *unused)
+{
+ /* freeze all counters */
+ pmc_stop_ctrs();
+
+ mtspr(SPRN_MMCR0, mmcr0_val);
+ mtspr(SPRN_MMCR1, mmcr1_val);
+ mtspr(SPRN_MMCR2, mmcr2_val);
+}
+
+#define NUM_CTRS 6
+
+/* Configures the global settings for the countes on all CPUs. */
+static void fsl7450_reg_setup(struct op_counter_config *ctr,
+ struct op_system_config *sys,
+ int num_ctrs)
+{
+ int i;
+
+ /* Our counters count up, and "count" refers to
+ * how much before the next interrupt, and we interrupt
+ * on overflow. So we calculate the starting value
+ * which will give us "count" until overflow.
+ * Then we set the events on the enabled counters */
+ for (i = 0; i < NUM_CTRS; ++i)
+ reset_value[i] = 0x80000000UL - ctr[i].count;
+
+ /* Set events for Counters 1 & 2 */
+ mmcr0_val = MMCR0_INIT | mmcr0_event1(ctr[0].event)
+ | mmcr0_event2(ctr[1].event);
+
+ /* Setup user/kernel bits */
+ if (sys->enable_kernel)
+ mmcr0_val &= ~(MMCR0_FCS);
+
+ if (sys->enable_user)
+ mmcr0_val &= ~(MMCR0_FCP);
+
+ /* Set events for Counters 3-6 */
+ mmcr1_val = mmcr1_event3(ctr[2].event)
+ | mmcr1_event4(ctr[3].event)
+ | mmcr1_event5(ctr[4].event)
+ | mmcr1_event6(ctr[5].event);
+
+ mmcr2_val = 0;
+}
+
+/* Sets the counters on this CPU to the chosen values, and starts them */
+static void fsl7450_start(struct op_counter_config *ctr)
+{
+ int i;
+
+ mtmsr(mfmsr() | MSR_PMM);
+
+ for (i = 0; i < NUM_CTRS; ++i) {
+ if (ctr[i].enabled)
+ ctr_write(i, reset_value[i]);
+ else
+ ctr_write(i, 0);
+ }
+
+ /* Clear the freeze bit, and enable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs();
+
+ oprofile_running = 1;
+}
+
+/* Stop the counters on this CPU */
+static void fsl7450_stop(void)
+{
+ /* freeze counters */
+ pmc_stop_ctrs();
+
+ oprofile_running = 0;
+
+ mb();
+}
+
+
+/* Handle the interrupt on this CPU, and log a sample for each
+ * event that triggered the interrupt */
+static void fsl7450_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+{
+ unsigned long pc;
+ int is_kernel;
+ int val;
+ int i;
+
+ /* set the PMM bit (see comment below) */
+ mtmsr(mfmsr() | MSR_PMM);
+
+ pc = mfspr(SPRN_SIAR);
+ is_kernel = (pc >= KERNELBASE);
+
+ for (i = 0; i < NUM_CTRS; ++i) {
+ val = ctr_read(i);
+ if (val < 0) {
+ if (oprofile_running && ctr[i].enabled) {
+ oprofile_add_pc(pc, is_kernel, i);
+ ctr_write(i, reset_value[i]);
+ } else {
+ ctr_write(i, 0);
+ }
+ }
+ }
+
+ /* The freeze bit was set by the interrupt. */
+ /* Clear the freeze bit, and reenable the interrupt.
+ * The counters won't actually start until the rfi clears
+ * the PMM bit */
+ pmc_start_ctrs();
+}
+
+struct op_powerpc_model op_model_7450= {
+ .reg_setup = fsl7450_reg_setup,
+ .cpu_setup = fsl7450_cpu_setup,
+ .start = fsl7450_start,
+ .stop = fsl7450_stop,
+ .handle_interrupt = fsl7450_handle_interrupt,
+};
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index a3401b46f3ba..659a021da0c7 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -252,7 +252,7 @@ static unsigned long get_pc(struct pt_regs *regs)
return (unsigned long)__va(pc);
/* Not sure where we were */
- if (pc < KERNELBASE)
+ if (!is_kernel_addr(pc))
/* function descriptor madness */
return *((unsigned long *)kernel_unknown_bucket);
@@ -264,7 +264,7 @@ static int get_kernel(unsigned long pc)
int is_kernel;
if (!mmcra_has_sihv) {
- is_kernel = (pc >= KERNELBASE);
+ is_kernel = is_kernel_addr(pc);
} else {
unsigned long mmcra = mfspr(SPRN_MMCRA);
is_kernel = ((mmcra & MMCRA_SIPR) == 0);
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c
index e010b85996e8..5c909ee609fe 100644
--- a/arch/powerpc/oprofile/op_model_rs64.c
+++ b/arch/powerpc/oprofile/op_model_rs64.c
@@ -178,7 +178,6 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
int val;
int i;
unsigned long pc = mfspr(SPRN_SIAR);
- int is_kernel = (pc >= KERNELBASE);
/* set the PMM bit (see comment below) */
mtmsrd(mfmsr() | MSR_PMM);
@@ -187,7 +186,7 @@ static void rs64_handle_interrupt(struct pt_regs *regs,
val = ctr_read(i);
if (val < 0) {
if (ctr[i].enabled) {
- oprofile_add_pc(pc, is_kernel, i);
+ oprofile_add_pc(pc, is_kernel_addr(pc), i);
ctr_write(i, reset_value[i]);
} else {
ctr_write(i, 0);
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
new file mode 100644
index 000000000000..7675e675dce1
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -0,0 +1,27 @@
+menu "Platform support"
+ depends on PPC_83xx
+
+choice
+ prompt "Machine Type"
+ default MPC834x_SYS
+
+config MPC834x_SYS
+ bool "Freescale MPC834x SYS"
+ select DEFAULT_UIMAGE
+ 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.
+
+endchoice
+
+config MPC834x
+ bool
+ select PPC_UDBG_16550
+ select PPC_INDIRECT_PCI
+ default y if MPC834x_SYS
+
+endmenu
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
new file mode 100644
index 000000000000..9d8b28ef3343
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o pci.o
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
new file mode 100644
index 000000000000..2098dd05a773
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -0,0 +1,243 @@
+/*
+ * arch/powerpc/platforms/83xx/mpc834x_sys.c
+ *
+ * MPC834x SYS board specific routines
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/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/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc83xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+#ifdef CONFIG_PCI
+extern int mpc83xx_pci2_busno;
+
+static 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 */
+ {0, 0, 0, 0},
+ {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */
+ {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */
+ {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */
+ {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */
+ {0, 0, 0, 0}, /* idsel 0x19 */
+ {0, 0, 0, 0}, /* idsel 0x20 */
+ };
+
+ const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static int
+mpc83xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (mpc83xx_pci2_busno)
+ if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc834x_sys_setup_arch(void)
+{
+ struct device_node *np;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc834x_sys_setup_arch()", 0);
+
+ np = of_find_node_by_type(NULL, "cpu");
+ if (np != 0) {
+ unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL);
+ if (fp != 0)
+ loops_per_jiffy = *fp / HZ;
+ else
+ loops_per_jiffy = 50000000 / HZ;
+ of_node_put(np);
+ }
+
+#ifdef CONFIG_PCI
+ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+ add_bridge(np);
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = mpc83xx_map_irq;
+ ppc_md.pci_exclude_device = mpc83xx_exclude_device;
+#endif
+
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+}
+
+void __init
+mpc834x_sys_init_IRQ(void)
+{
+ u8 senses[8] = {
+ 0, /* EXT 0 */
+ 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(get_immrbase() + 0x00700, 0, 0, senses, 8);
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ ipic_set_default_priority();
+}
+
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init
+mpc834x_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = ds1374_get_rtc_time;
+ ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time)();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+late_initcall(mpc834x_rtc_hookup);
+#endif
+
+static void
+mpc83xx_restart(char *cmd)
+{
+#define RST_OFFSET 0x00000900
+#define RST_PROT_REG 0x00000018
+#define RST_CTRL_REG 0x0000001c
+ __be32 __iomem *reg;
+
+ // map reset register space
+ reg = ioremap(get_immrbase() + 0x900, 0xff);
+
+ local_irq_disable();
+
+ /* enable software reset "RSTE" */
+ out_be32(reg + (RST_PROT_REG >> 2), 0x52535445);
+
+ /* set software hard reset */
+ out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445);
+ for(;;);
+}
+
+static long __init
+mpc83xx_time_init(void)
+{
+#define SPCR_OFFSET 0x00000110
+#define SPCR_TBEN 0x00400000
+ __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4);
+ __be32 tmp;
+
+ tmp = in_be32(spcr);
+ out_be32(spcr, tmp|SPCR_TBEN);
+
+ iounmap(spcr);
+
+ return 0;
+}
+void __init
+platform_init(void)
+{
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = mpc834x_sys_setup_arch;
+
+ ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
+ ppc_md.get_irq = ipic_get_irq;
+
+ ppc_md.restart = mpc83xx_restart;
+
+ ppc_md.time_init = mpc83xx_time_init;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = generic_calibrate_decr;
+
+ ppc_md.progress = udbg_progress;
+
+ if (ppc_md.progress)
+ ppc_md.progress("mpc834x_sys_init(): exit", 0);
+
+ return;
+}
+
+
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h
new file mode 100644
index 000000000000..e4ca39f6a862
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h
@@ -0,0 +1,23 @@
+/*
+ * arch/powerppc/platforms/83xx/mpc834x_sys.h
+ *
+ * MPC834X SYS common board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.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.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_SYS_H__
+#define __MACH_MPC83XX_SYS_H__
+
+#define PIRQA MPC83xx_IRQ_EXT4
+#define PIRQB MPC83xx_IRQ_EXT5
+#define PIRQC MPC83xx_IRQ_EXT6
+#define PIRQD MPC83xx_IRQ_EXT7
+
+#endif /* __MACH_MPC83XX_SYS_H__ */
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
new file mode 100644
index 000000000000..ce9e66abef24
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -0,0 +1,14 @@
+#ifndef __MPC83XX_H__
+#define __MPC83XX_H__
+
+#include <linux/init.h>
+#include <linux/device.h>
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc83xx_* files. Mostly for use by mpc83xx_setup
+ */
+
+extern int add_bridge(struct device_node *dev);
+
+#endif /* __MPC83XX_H__ */
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
new file mode 100644
index 000000000000..469cdacc5bd4
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -0,0 +1,99 @@
+/*
+ * FSL SoC setup code
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact 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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+int mpc83xx_pci2_busno;
+
+#ifdef CONFIG_PCI
+int __init add_bridge(struct device_node *dev)
+{
+ int len;
+ struct pci_controller *hose;
+ struct resource rsrc;
+ int *bus_range;
+ int primary = 1, has_address = 0;
+ phys_addr_t immr = get_immrbase();
+
+ DBG("Adding PCI host bridge %s\n", dev->full_name);
+
+ /* Fetch host bridge registers address */
+ has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+ /* Get bus range if any */
+ 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 = pcibios_alloc_controller();
+ if (!hose)
+ return -ENOMEM;
+ hose->arch_data = dev;
+ hose->set_cfg_type = 1;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar
+ * the other at 0x8600, we consider the 0x8500 the primary controller
+ */
+ /* PCI 1 */
+ if ((rsrc.start & 0xfffff) == 0x8500) {
+ setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304);
+ }
+ /* PCI 2*/
+ if ((rsrc.start & 0xfffff) == 0x8600) {
+ setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384);
+ primary = 0;
+ hose->bus_offset = hose->first_busno;
+ mpc83xx_pci2_busno = hose->first_busno;
+ }
+
+ printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. "
+ "Firmware bus number: %d->%d\n",
+ rsrc.start, hose->first_busno, hose->last_busno);
+
+ DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+ hose, hose->cfg_addr, hose->cfg_data);
+
+ /* Interpret the "ranges" property */
+ /* This also maps the I/O region and sets isa_io/mem_base */
+ pci_process_bridge_OF_ranges(hose, dev, primary);
+
+ return 0;
+}
+
+#endif
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 8836b3a00668..04073fd987ec 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -7,6 +7,7 @@ endif
endif
obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_4xx) += 4xx/
+obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_85xx) += 85xx/
obj-$(CONFIG_PPC_PSERIES) += pseries/
obj-$(CONFIG_PPC_ISERIES) += iseries/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
new file mode 100644
index 000000000000..3157071e241c
--- /dev/null
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -0,0 +1,13 @@
+menu "Cell Broadband Engine options"
+ depends on PPC_CELL
+
+config SPU_FS
+ tristate "SPU file system"
+ default m
+ depends on PPC_CELL
+ help
+ The SPU file system is used to access Synergistic Processing
+ Units on machines implementing the Broadband Processor
+ Architecture.
+
+endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 55e094b96bc0..16031b565be4 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -1,2 +1,10 @@
obj-y += interrupt.o iommu.o setup.o spider-pic.o
+obj-y += pervasive.o
+
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_SPU_FS) += spufs/ spu-base.o
+
+spu-base-y += spu_base.o spu_priv1.o
+
+builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o
+obj-y += $(builtin-spufs-m)
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 7fbe78a9327d..63aa52acf441 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/module.h>
#include <linux/percpu.h>
#include <linux/types.h>
@@ -55,6 +56,7 @@ struct iic_regs {
struct iic {
struct iic_regs __iomem *regs;
+ u8 target_id;
};
static DEFINE_PER_CPU(struct iic, iic);
@@ -172,12 +174,11 @@ int iic_get_irq(struct pt_regs *regs)
return irq;
}
-static struct iic_regs __iomem *find_iic(int cpu)
+static int setup_iic(int cpu, struct iic *iic)
{
struct device_node *np;
int nodeid = cpu / 2;
unsigned long regs;
- struct iic_regs __iomem *iic_regs;
for (np = of_find_node_by_type(NULL, "cpu");
np;
@@ -188,20 +189,23 @@ static struct iic_regs __iomem *find_iic(int cpu)
if (!np) {
printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
- iic_regs = NULL;
- } else {
- regs = *(long *)get_property(np, "iic", NULL);
-
- /* hack until we have decided on the devtree info */
- regs += 0x400;
- if (cpu & 1)
- regs += 0x20;
-
- printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
- iic_regs = __ioremap(regs, sizeof(struct iic_regs),
- _PAGE_NO_CACHE);
+ iic->regs = NULL;
+ iic->target_id = 0xff;
+ return -ENODEV;
}
- return iic_regs;
+
+ regs = *(long *)get_property(np, "iic", NULL);
+
+ /* hack until we have decided on the devtree info */
+ regs += 0x400;
+ if (cpu & 1)
+ regs += 0x20;
+
+ printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
+ iic->regs = __ioremap(regs, sizeof(struct iic_regs),
+ _PAGE_NO_CACHE);
+ iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
+ return 0;
}
#ifdef CONFIG_SMP
@@ -227,6 +231,12 @@ void iic_cause_IPI(int cpu, int mesg)
out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
}
+u8 iic_get_target_id(int cpu)
+{
+ return per_cpu(iic, cpu).target_id;
+}
+EXPORT_SYMBOL_GPL(iic_get_target_id);
+
static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
smp_message_recv(iic_irq_to_ipi(irq), regs);
@@ -276,7 +286,7 @@ void iic_init_IRQ(void)
irq_offset = 0;
for_each_cpu(cpu) {
iic = &per_cpu(iic, cpu);
- iic->regs = find_iic(cpu);
+ setup_iic(cpu, iic);
if (iic->regs)
out_be64(&iic->regs->prio, 0xff);
}
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h
index 37d58e6fd0c6..a14bd38791c0 100644
--- a/arch/powerpc/platforms/cell/interrupt.h
+++ b/arch/powerpc/platforms/cell/interrupt.h
@@ -54,6 +54,7 @@ extern void iic_setup_cpu(void);
extern void iic_local_enable(void);
extern void iic_local_disable(void);
+extern u8 iic_get_target_id(int cpu);
extern void spider_init_IRQ(void);
extern int spider_get_irq(unsigned long int_pending);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 74f999b4ac9e..46e7cb9c3e64 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -29,6 +29,8 @@
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
#include <asm/sections.h>
#include <asm/iommu.h>
@@ -40,6 +42,7 @@
#include <asm/abs_addr.h>
#include <asm/system.h>
#include <asm/ppc-pci.h>
+#include <asm/udbg.h>
#include "iommu.h"
@@ -220,8 +223,6 @@ set_iopt_cache(void __iomem *base, unsigned long index,
{
unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
- pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",
- index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);
out_be64(p, val);
out_be64(&tags[index], tag);
@@ -248,67 +249,176 @@ set_iocmd_config(void __iomem *base)
out_be64(p, conf | IOCMD_CONF_TE);
}
-/* FIXME: get these from the device tree */
-#define ioc_base 0x20000511000ull
-#define ioc_mmio_base 0x20000510000ull
-#define ioid 0x48a
-#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */
-#define io_page_size 0x1000000
-
-static unsigned long map_iopt_entry(unsigned long address)
+static void enable_mapping(void __iomem *base, void __iomem *mmio_base)
{
- switch (address >> 20) {
- case 0x600:
- address = 0x24020000000ull; /* spider i/o */
- break;
- default:
- address += iopt_phys_offset;
- break;
- }
-
- return get_iopt_entry(address, ioid, IOPT_PROT_RW);
+ set_iocmd_config(base);
+ set_iost_origin(mmio_base);
}
-static void iommu_bus_setup_null(struct pci_bus *b) { }
static void iommu_dev_setup_null(struct pci_dev *d) { }
+static void iommu_bus_setup_null(struct pci_bus *b) { }
+
+struct cell_iommu {
+ unsigned long base;
+ unsigned long mmio_base;
+ void __iomem *mapped_base;
+ void __iomem *mapped_mmio_base;
+};
+
+static struct cell_iommu cell_iommus[NR_CPUS];
/* initialize the iommu to support a simple linear mapping
* for each DMA window used by any device. For now, we
* happen to know that there is only one DMA window in use,
* starting at iopt_phys_offset. */
-static void cell_map_iommu(void)
+static void cell_do_map_iommu(struct cell_iommu *iommu,
+ unsigned int ioid,
+ unsigned long map_start,
+ unsigned long map_size)
{
- unsigned long address;
- void __iomem *base;
+ unsigned long io_address, real_address;
+ void __iomem *ioc_base, *ioc_mmio_base;
ioste ioste;
unsigned long index;
- base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);
- pr_debug("%lx mapped to %p\n", ioc_base, base);
- set_iocmd_config(base);
- iounmap(base);
+ /* we pretend the io page table was at a very high address */
+ const unsigned long fake_iopt = 0x10000000000ul;
+ const unsigned long io_page_size = 0x1000000; /* use 16M pages */
+ const unsigned long io_segment_size = 0x10000000; /* 256M */
+
+ ioc_base = iommu->mapped_base;
+ ioc_mmio_base = iommu->mapped_mmio_base;
+
+ for (real_address = 0, io_address = 0;
+ io_address <= map_start + map_size;
+ real_address += io_page_size, io_address += io_page_size) {
+ ioste = get_iost_entry(fake_iopt, io_address, io_page_size);
+ if ((real_address % io_segment_size) == 0) /* segment start */
+ set_iost_cache(ioc_mmio_base,
+ io_address >> 28, ioste);
+ index = get_ioc_hash_1way(ioste, io_address);
+ pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
+ io_address, index, ioste.val);
+ set_iopt_cache(ioc_mmio_base,
+ get_ioc_hash_1way(ioste, io_address),
+ get_ioc_tag(ioste, io_address),
+ get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW));
+ }
+}
- base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);
- pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);
+static void iommu_devnode_setup(struct device_node *d)
+{
+ unsigned int *ioid;
+ unsigned long *dma_window, map_start, map_size, token;
+ struct cell_iommu *iommu;
- set_iost_origin(base);
+ ioid = (unsigned int *)get_property(d, "ioid", NULL);
+ if (!ioid)
+ pr_debug("No ioid entry found !\n");
- for (address = 0; address < 0x100000000ul; address += io_page_size) {
- ioste = get_iost_entry(0x10000000000ul, address, io_page_size);
- if ((address & 0xfffffff) == 0) /* segment start */
- set_iost_cache(base, address >> 28, ioste);
- index = get_ioc_hash_1way(ioste, address);
- pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
- address, index, ioste.val);
- set_iopt_cache(base,
- get_ioc_hash_1way(ioste, address),
- get_ioc_tag(ioste, address),
- map_iopt_entry(address));
- }
- iounmap(base);
+ dma_window = (unsigned long *)get_property(d, "ibm,dma-window", NULL);
+ if (!dma_window)
+ pr_debug("No ibm,dma-window entry found !\n");
+
+ map_start = dma_window[1];
+ map_size = dma_window[2];
+ token = dma_window[0] >> 32;
+
+ iommu = &cell_iommus[token];
+
+ cell_do_map_iommu(iommu, *ioid, map_start, map_size);
+}
+
+static void iommu_bus_setup(struct pci_bus *b)
+{
+ struct device_node *d = (struct device_node *)b->sysdata;
+ iommu_devnode_setup(d);
+}
+
+
+static int cell_map_iommu_hardcoded(int num_nodes)
+{
+ struct cell_iommu *iommu = NULL;
+
+ pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__);
+
+ /* node 0 */
+ iommu = &cell_iommus[0];
+ iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE);
+
+ enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
+
+ cell_do_map_iommu(iommu, 0x048a,
+ 0x20000000ul,0x20000000ul);
+
+ if (num_nodes < 2)
+ return 0;
+
+ /* node 1 */
+ iommu = &cell_iommus[1];
+ iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE);
+
+ enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base);
+
+ cell_do_map_iommu(iommu, 0x048a,
+ 0x20000000,0x20000000ul);
+
+ return 0;
}
+static int cell_map_iommu(void)
+{
+ unsigned int num_nodes = 0, *node_id;
+ unsigned long *base, *mmio_base;
+ struct device_node *dn;
+ struct cell_iommu *iommu = NULL;
+
+ /* determine number of nodes (=iommus) */
+ pr_debug("%s(%d): determining number of nodes...", __FUNCTION__, __LINE__);
+ for(dn = of_find_node_by_type(NULL, "cpu");
+ dn;
+ dn = of_find_node_by_type(dn, "cpu")) {
+ node_id = (unsigned int *)get_property(dn, "node-id", NULL);
+
+ if (num_nodes < *node_id)
+ num_nodes = *node_id;
+ }
+
+ num_nodes++;
+ pr_debug("%i found.\n", num_nodes);
+
+ /* map the iommu registers for each node */
+ pr_debug("%s(%d): Looping through nodes\n", __FUNCTION__, __LINE__);
+ for(dn = of_find_node_by_type(NULL, "cpu");
+ dn;
+ dn = of_find_node_by_type(dn, "cpu")) {
+
+ node_id = (unsigned int *)get_property(dn, "node-id", NULL);
+ base = (unsigned long *)get_property(dn, "ioc-cache", NULL);
+ mmio_base = (unsigned long *)get_property(dn, "ioc-translation", NULL);
+
+ if (!base || !mmio_base || !node_id)
+ return cell_map_iommu_hardcoded(num_nodes);
+
+ iommu = &cell_iommus[*node_id];
+ iommu->base = *base;
+ iommu->mmio_base = *mmio_base;
+
+ iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE);
+ iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE);
+
+ enable_mapping(iommu->mapped_base,
+ iommu->mapped_mmio_base);
+
+ /* everything else will be done in iommu_bus_setup */
+ }
+
+ return 1;
+}
+
static void *cell_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
@@ -365,11 +475,28 @@ static int cell_dma_supported(struct device *dev, u64 mask)
void cell_init_iommu(void)
{
- cell_map_iommu();
-
- /* Direct I/O, IOMMU off */
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+ int setup_bus = 0;
+
+ if (of_find_node_by_path("/mambo")) {
+ pr_info("Not using iommu on systemsim\n");
+ } else {
+
+ if (!(of_chosen &&
+ get_property(of_chosen, "linux,iommu-off", NULL)))
+ setup_bus = cell_map_iommu();
+
+ if (setup_bus) {
+ pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__);
+ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+ ppc_md.iommu_bus_setup = iommu_bus_setup;
+ } else {
+ pr_debug("%s: IOMMU mapping activated, "
+ "no device action necessary\n", __FUNCTION__);
+ /* Direct I/O, IOMMU off */
+ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+ ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+ }
+ }
pci_dma_ops.alloc_coherent = cell_alloc_coherent;
pci_dma_ops.free_coherent = cell_free_coherent;
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
new file mode 100644
index 000000000000..e0e051c675dd
--- /dev/null
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -0,0 +1,229 @@
+/*
+ * CBE Pervasive Monitor and Debug
+ *
+ * (C) Copyright IBM Corporation 2005
+ *
+ * Authors: Maximino Aguilar (maguilar@us.ibm.com)
+ * Michael N. Day (mnday@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, 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.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+#include <linux/kallsyms.h>
+
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/pgtable.h>
+#include <asm/reg.h>
+
+#include "pervasive.h"
+
+static DEFINE_SPINLOCK(cbe_pervasive_lock);
+struct cbe_pervasive {
+ struct pmd_regs __iomem *regs;
+ unsigned int thread;
+};
+
+/* can't use per_cpu from setup_arch */
+static struct cbe_pervasive cbe_pervasive[NR_CPUS];
+
+static void __init cbe_enable_pause_zero(void)
+{
+ unsigned long thread_switch_control;
+ unsigned long temp_register;
+ struct cbe_pervasive *p;
+ int thread;
+
+ spin_lock_irq(&cbe_pervasive_lock);
+ p = &cbe_pervasive[smp_processor_id()];
+
+ if (!cbe_pervasive->regs)
+ goto out;
+
+ pr_debug("Power Management: CPU %d\n", smp_processor_id());
+
+ /* Enable Pause(0) control bit */
+ temp_register = in_be64(&p->regs->pm_control);
+
+ out_be64(&p->regs->pm_control,
+ temp_register|PMD_PAUSE_ZERO_CONTROL);
+
+ /* Enable DEC and EE interrupt request */
+ thread_switch_control = mfspr(SPRN_TSC_CELL);
+ thread_switch_control |= TSC_CELL_EE_ENABLE | TSC_CELL_EE_BOOST;
+
+ switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) {
+ case CTRL_CT0:
+ thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
+ thread = 0;
+ break;
+ case CTRL_CT1:
+ thread_switch_control |= TSC_CELL_DEC_ENABLE_1;
+ thread = 1;
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown configuration\n",
+ __FUNCTION__);
+ thread = -1;
+ break;
+ }
+
+ if (p->thread != thread)
+ printk(KERN_WARNING "%s: device tree inconsistant, "
+ "cpu %i: %d/%d\n", __FUNCTION__,
+ smp_processor_id(),
+ p->thread, thread);
+
+ mtspr(SPRN_TSC_CELL, thread_switch_control);
+
+out:
+ spin_unlock_irq(&cbe_pervasive_lock);
+}
+
+static void cbe_idle(void)
+{
+ unsigned long ctrl;
+
+ cbe_enable_pause_zero();
+
+ while (1) {
+ if (!need_resched()) {
+ local_irq_disable();
+ while (!need_resched()) {
+ /* go into low thread priority */
+ HMT_low();
+
+ /*
+ * atomically disable thread execution
+ * and runlatch.
+ * External and Decrementer exceptions
+ * are still handled when the thread
+ * is disabled but now enter in
+ * cbe_system_reset_exception()
+ */
+ ctrl = mfspr(SPRN_CTRLF);
+ ctrl &= ~(CTRL_RUNLATCH | CTRL_TE);
+ mtspr(SPRN_CTRLT, ctrl);
+ }
+ /* restore thread prio */
+ HMT_medium();
+ local_irq_enable();
+ }
+
+ /*
+ * turn runlatch on again before scheduling the
+ * process we just woke up
+ */
+ ppc64_runlatch_on();
+
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
+
+static int cbe_system_reset_exception(struct pt_regs *regs)
+{
+ switch (regs->msr & SRR1_WAKEMASK) {
+ case SRR1_WAKEEE:
+ do_IRQ(regs);
+ break;
+ case SRR1_WAKEDEC:
+ timer_interrupt(regs);
+ break;
+ case SRR1_WAKEMT:
+ /* no action required */
+ break;
+ default:
+ /* do system reset */
+ return 0;
+ }
+ /* everything handled */
+ return 1;
+}
+
+static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p)
+{
+ struct device_node *node;
+ unsigned int *int_servers;
+ char *addr;
+ unsigned long real_address;
+ unsigned int size;
+
+ struct pmd_regs __iomem *pmd_mmio_area;
+ int hardid, thread;
+ int proplen;
+
+ pmd_mmio_area = NULL;
+ hardid = get_hard_smp_processor_id(cpu);
+ for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) {
+ int_servers = (void *) get_property(node,
+ "ibm,ppc-interrupt-server#s", &proplen);
+ if (!int_servers) {
+ printk(KERN_WARNING "%s misses "
+ "ibm,ppc-interrupt-server#s property",
+ node->full_name);
+ continue;
+ }
+ for (thread = 0; thread < proplen / sizeof (int); thread++) {
+ if (hardid == int_servers[thread]) {
+ addr = get_property(node, "pervasive", NULL);
+ goto found;
+ }
+ }
+ }
+
+ printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu);
+ return -EINVAL;
+
+found:
+ real_address = *(unsigned long*) addr;
+ addr += sizeof (unsigned long);
+ size = *(unsigned int*) addr;
+
+ pr_debug("pervasive area for CPU %d at %lx, size %x\n",
+ cpu, real_address, size);
+ p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE);
+ p->thread = thread;
+ return 0;
+}
+
+void __init cell_pervasive_init(void)
+{
+ struct cbe_pervasive *p;
+ int cpu;
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
+ return;
+
+ for_each_cpu(cpu) {
+ p = &cbe_pervasive[cpu];
+ ret = cbe_find_pmd_mmio(cpu, p);
+ if (ret)
+ return;
+ }
+
+ ppc_md.idle_loop = cbe_idle;
+ ppc_md.system_reset_exception = cbe_system_reset_exception;
+}
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
new file mode 100644
index 000000000000..da1fb85ca3e8
--- /dev/null
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -0,0 +1,62 @@
+/*
+ * Cell Pervasive Monitor and Debug interface and HW structures
+ *
+ * (C) Copyright IBM Corporation 2005
+ *
+ * Authors: Maximino Aguilar (maguilar@us.ibm.com)
+ * David J. Erb (djerb@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, 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 PERVASIVE_H
+#define PERVASIVE_H
+
+struct pmd_regs {
+ u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */
+
+ /* Thermal Sensor Registers */
+ u64 ts_ctsr1; /* 0x0800 */
+ u64 ts_ctsr2; /* 0x0808 */
+ u64 ts_mtsr1; /* 0x0810 */
+ u64 ts_mtsr2; /* 0x0818 */
+ u64 ts_itr1; /* 0x0820 */
+ u64 ts_itr2; /* 0x0828 */
+ u64 ts_gitr; /* 0x0830 */
+ u64 ts_isr; /* 0x0838 */
+ u64 ts_imr; /* 0x0840 */
+ u64 tm_cr1; /* 0x0848 */
+ u64 tm_cr2; /* 0x0850 */
+ u64 tm_simr; /* 0x0858 */
+ u64 tm_tpr; /* 0x0860 */
+ u64 tm_str1; /* 0x0868 */
+ u64 tm_str2; /* 0x0870 */
+ u64 tm_tsr; /* 0x0878 */
+
+ /* Power Management */
+ u64 pm_control; /* 0x0880 */
+#define PMD_PAUSE_ZERO_CONTROL 0x10000
+ u64 pm_status; /* 0x0888 */
+
+ /* Time Base Register */
+ u64 tbr; /* 0x0890 */
+
+ u8 pad_0x0898_0x1000 [0x1000 - 0x0898]; /* 0x0898 */
+};
+
+void __init cell_pervasive_init(void);
+
+#endif
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 9a495634d0c2..b33a4443f5a9 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -33,6 +33,7 @@
#include <asm/mmu.h>
#include <asm/processor.h>
#include <asm/io.h>
+#include <asm/kexec.h>
#include <asm/pgtable.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -48,6 +49,7 @@
#include "interrupt.h"
#include "iommu.h"
+#include "pervasive.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -55,7 +57,7 @@
#define DBG(fmt...)
#endif
-void cell_show_cpuinfo(struct seq_file *m)
+static void cell_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
const char *model = "";
@@ -67,6 +69,77 @@ void cell_show_cpuinfo(struct seq_file *m)
of_node_put(root);
}
+#ifdef CONFIG_SPARSEMEM
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+#ifdef CONFIG_NUMA
+ struct device_node *cpu;
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+#else
+ id = NULL;
+#endif
+ return id ? *id : 0;
+}
+
+static void __init cell_spuprop_present(struct device_node *spe,
+ const char *prop, int early)
+{
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *p;
+ int proplen;
+
+ unsigned long start_pfn, end_pfn, pfn;
+ int node_id;
+
+ p = (void*)get_property(spe, prop, &proplen);
+ WARN_ON(proplen != sizeof (*p));
+
+ node_id = find_spu_node_id(spe);
+
+ start_pfn = p->address >> PAGE_SHIFT;
+ end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ /* We need to call memory_present *before* the call to sparse_init,
+ but we can initialize the page structs only *after* that call.
+ Thus, we're being called twice. */
+ if (early)
+ memory_present(node_id, start_pfn, end_pfn);
+ else {
+ /* As the pages backing SPU LS and I/O are outside the range
+ of regular memory, their page structs were not initialized
+ by free_area_init. Do it here instead. */
+ for (pfn = start_pfn; pfn < end_pfn; pfn++) {
+ struct page *page = pfn_to_page(pfn);
+ set_page_links(page, ZONE_DMA, node_id, pfn);
+ set_page_count(page, 1);
+ reset_page_mapcount(page);
+ SetPageReserved(page);
+ INIT_LIST_HEAD(&page->lru);
+ }
+ }
+}
+
+static void __init cell_spumem_init(int early)
+{
+ struct device_node *node;
+ for (node = of_find_node_by_type(NULL, "spe");
+ node; node = of_find_node_by_type(node, "spe")) {
+ cell_spuprop_present(node, "local-store", early);
+ cell_spuprop_present(node, "problem", early);
+ cell_spuprop_present(node, "priv1", early);
+ cell_spuprop_present(node, "priv2", early);
+ }
+}
+#else
+static void __init cell_spumem_init(int early)
+{
+}
+#endif
+
static void cell_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
@@ -93,11 +166,14 @@ static void __init cell_setup_arch(void)
init_pci_config_tokens();
find_and_init_phbs();
spider_init_IRQ();
+ cell_pervasive_init();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
mmio_nvram_init();
+
+ cell_spumem_init(0);
}
/*
@@ -113,6 +189,8 @@ static void __init cell_init_early(void)
ppc64_interrupt_controller = IC_CELL_PIC;
+ cell_spumem_init(1);
+
DBG(" <- cell_init_early()\n");
}
@@ -125,6 +203,15 @@ static int __init cell_probe(int platform)
return 1;
}
+/*
+ * Cell has no legacy IO; anything calling this function has to
+ * fail or bad things will happen
+ */
+static int cell_check_legacy_ioport(unsigned int baseport)
+{
+ return -ENODEV;
+}
+
struct machdep_calls __initdata cell_md = {
.probe = cell_probe,
.setup_arch = cell_setup_arch,
@@ -137,5 +224,11 @@ struct machdep_calls __initdata cell_md = {
.get_rtc_time = rtas_get_rtc_time,
.set_rtc_time = rtas_set_rtc_time,
.calibrate_decr = generic_calibrate_decr,
+ .check_legacy_ioport = cell_check_legacy_ioport,
.progress = cell_progress,
+#ifdef CONFIG_KEXEC
+ .machine_kexec = default_machine_kexec,
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
};
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index de96eadf419d..bdf6c5fe58c0 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -86,7 +86,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
pcpu = get_hard_smp_processor_id(lcpu);
/* Fixup atomic count: it exited inside IRQ handler. */
- paca[lcpu].__current->thread_info->preempt_count = 0;
+ task_thread_info(paca[lcpu].__current)->preempt_count = 0;
/*
* If the RTAS start-cpu token does not exist then presume the
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
new file mode 100644
index 000000000000..d75ae03df686
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -0,0 +1,711 @@
+/*
+ * Low-level SPU handling
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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.
+ */
+
+#undef DEBUG
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/semaphore.h>
+#include <asm/spu.h>
+#include <asm/mmu_context.h>
+
+#include "interrupt.h"
+
+static int __spu_trap_invalid_dma(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ force_sig(SIGBUS, /* info, */ current);
+ return 0;
+}
+
+static int __spu_trap_dma_align(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ force_sig(SIGBUS, /* info, */ current);
+ return 0;
+}
+
+static int __spu_trap_error(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ force_sig(SIGILL, /* info, */ current);
+ return 0;
+}
+
+static void spu_restart_dma(struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags))
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND);
+}
+
+static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ struct mm_struct *mm = spu->mm;
+ u64 esid, vsid;
+
+ pr_debug("%s\n", __FUNCTION__);
+
+ if (test_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags)) {
+ /* SLBs are pre-loaded for context switch, so
+ * we should never get here!
+ */
+ printk("%s: invalid access during switch!\n", __func__);
+ return 1;
+ }
+ if (!mm || (REGION_ID(ea) != USER_REGION_ID)) {
+ /* Future: support kernel segments so that drivers
+ * can use SPUs.
+ */
+ pr_debug("invalid region access at %016lx\n", ea);
+ return 1;
+ }
+
+ esid = (ea & ESID_MASK) | SLB_ESID_V;
+ vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER;
+ if (in_hugepage_area(mm->context, ea))
+ vsid |= SLB_VSID_L;
+
+ out_be64(&priv2->slb_index_W, spu->slb_replace);
+ out_be64(&priv2->slb_vsid_RW, vsid);
+ out_be64(&priv2->slb_esid_RW, esid);
+
+ spu->slb_replace++;
+ if (spu->slb_replace >= 8)
+ spu->slb_replace = 0;
+
+ spu_restart_dma(spu);
+
+ return 0;
+}
+
+extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
+static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
+{
+ pr_debug("%s\n", __FUNCTION__);
+
+ /* Handle kernel space hash faults immediately.
+ User hash faults need to be deferred to process context. */
+ if ((dsisr & MFC_DSISR_PTE_NOT_FOUND)
+ && REGION_ID(ea) != USER_REGION_ID
+ && hash_page(ea, _PAGE_PRESENT, 0x300) == 0) {
+ spu_restart_dma(spu);
+ return 0;
+ }
+
+ if (test_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags)) {
+ printk("%s: invalid access during switch!\n", __func__);
+ return 1;
+ }
+
+ spu->dar = ea;
+ spu->dsisr = dsisr;
+ mb();
+ if (spu->stop_callback)
+ spu->stop_callback(spu);
+ return 0;
+}
+
+static int __spu_trap_mailbox(struct spu *spu)
+{
+ if (spu->ibox_callback)
+ spu->ibox_callback(spu);
+
+ /* atomically disable SPU mailbox interrupts */
+ spin_lock(&spu->register_lock);
+ spu_int_mask_and(spu, 2, ~0x1);
+ spin_unlock(&spu->register_lock);
+ return 0;
+}
+
+static int __spu_trap_stop(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ spu->stop_code = in_be32(&spu->problem->spu_status_R);
+ if (spu->stop_callback)
+ spu->stop_callback(spu);
+ return 0;
+}
+
+static int __spu_trap_halt(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ spu->stop_code = in_be32(&spu->problem->spu_status_R);
+ if (spu->stop_callback)
+ spu->stop_callback(spu);
+ return 0;
+}
+
+static int __spu_trap_tag_group(struct spu *spu)
+{
+ pr_debug("%s\n", __FUNCTION__);
+ /* wake_up(&spu->dma_wq); */
+ return 0;
+}
+
+static int __spu_trap_spubox(struct spu *spu)
+{
+ if (spu->wbox_callback)
+ spu->wbox_callback(spu);
+
+ /* atomically disable SPU mailbox interrupts */
+ spin_lock(&spu->register_lock);
+ spu_int_mask_and(spu, 2, ~0x10);
+ spin_unlock(&spu->register_lock);
+ return 0;
+}
+
+static irqreturn_t
+spu_irq_class_0(int irq, void *data, struct pt_regs *regs)
+{
+ struct spu *spu;
+
+ spu = data;
+ spu->class_0_pending = 1;
+ if (spu->stop_callback)
+ spu->stop_callback(spu);
+
+ return IRQ_HANDLED;
+}
+
+int
+spu_irq_class_0_bottom(struct spu *spu)
+{
+ unsigned long stat, mask;
+
+ spu->class_0_pending = 0;
+
+ mask = spu_int_mask_get(spu, 0);
+ stat = spu_int_stat_get(spu, 0);
+
+ stat &= mask;
+
+ if (stat & 1) /* invalid MFC DMA */
+ __spu_trap_invalid_dma(spu);
+
+ if (stat & 2) /* invalid DMA alignment */
+ __spu_trap_dma_align(spu);
+
+ if (stat & 4) /* error on SPU */
+ __spu_trap_error(spu);
+
+ spu_int_stat_clear(spu, 0, stat);
+
+ return (stat & 0x7) ? -EIO : 0;
+}
+EXPORT_SYMBOL_GPL(spu_irq_class_0_bottom);
+
+static irqreturn_t
+spu_irq_class_1(int irq, void *data, struct pt_regs *regs)
+{
+ struct spu *spu;
+ unsigned long stat, mask, dar, dsisr;
+
+ spu = data;
+
+ /* atomically read & clear class1 status. */
+ spin_lock(&spu->register_lock);
+ mask = spu_int_mask_get(spu, 1);
+ stat = spu_int_stat_get(spu, 1) & mask;
+ dar = spu_mfc_dar_get(spu);
+ dsisr = spu_mfc_dsisr_get(spu);
+ if (stat & 2) /* mapping fault */
+ spu_mfc_dsisr_set(spu, 0ul);
+ spu_int_stat_clear(spu, 1, stat);
+ spin_unlock(&spu->register_lock);
+
+ if (stat & 1) /* segment fault */
+ __spu_trap_data_seg(spu, dar);
+
+ if (stat & 2) { /* mapping fault */
+ __spu_trap_data_map(spu, dar, dsisr);
+ }
+
+ if (stat & 4) /* ls compare & suspend on get */
+ ;
+
+ if (stat & 8) /* ls compare & suspend on put */
+ ;
+
+ return stat ? IRQ_HANDLED : IRQ_NONE;
+}
+EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom);
+
+static irqreturn_t
+spu_irq_class_2(int irq, void *data, struct pt_regs *regs)
+{
+ struct spu *spu;
+ unsigned long stat;
+ unsigned long mask;
+
+ spu = data;
+ stat = spu_int_stat_get(spu, 2);
+ mask = spu_int_mask_get(spu, 2);
+
+ pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
+
+ stat &= mask;
+
+ if (stat & 1) /* PPC core mailbox */
+ __spu_trap_mailbox(spu);
+
+ if (stat & 2) /* SPU stop-and-signal */
+ __spu_trap_stop(spu);
+
+ if (stat & 4) /* SPU halted */
+ __spu_trap_halt(spu);
+
+ if (stat & 8) /* DMA tag group complete */
+ __spu_trap_tag_group(spu);
+
+ if (stat & 0x10) /* SPU mailbox threshold */
+ __spu_trap_spubox(spu);
+
+ spu_int_stat_clear(spu, 2, stat);
+ return stat ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int
+spu_request_irqs(struct spu *spu)
+{
+ int ret;
+ int irq_base;
+
+ irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET;
+
+ snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
+ ret = request_irq(irq_base + spu->isrc,
+ spu_irq_class_0, 0, spu->irq_c0, spu);
+ if (ret)
+ goto out;
+
+ snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
+ ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
+ spu_irq_class_1, 0, spu->irq_c1, spu);
+ if (ret)
+ goto out1;
+
+ snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
+ ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
+ spu_irq_class_2, 0, spu->irq_c2, spu);
+ if (ret)
+ goto out2;
+ goto out;
+
+out2:
+ free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu);
+out1:
+ free_irq(irq_base + spu->isrc, spu);
+out:
+ return ret;
+}
+
+static void
+spu_free_irqs(struct spu *spu)
+{
+ int irq_base;
+
+ irq_base = IIC_NODE_STRIDE * spu->node + IIC_SPE_OFFSET;
+
+ free_irq(irq_base + spu->isrc, spu);
+ free_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc, spu);
+ free_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc, spu);
+}
+
+static LIST_HEAD(spu_list);
+static DECLARE_MUTEX(spu_mutex);
+
+static void spu_init_channels(struct spu *spu)
+{
+ static const struct {
+ unsigned channel;
+ unsigned count;
+ } zero_list[] = {
+ { 0x00, 1, }, { 0x01, 1, }, { 0x03, 1, }, { 0x04, 1, },
+ { 0x18, 1, }, { 0x19, 1, }, { 0x1b, 1, }, { 0x1d, 1, },
+ }, count_list[] = {
+ { 0x00, 0, }, { 0x03, 0, }, { 0x04, 0, }, { 0x15, 16, },
+ { 0x17, 1, }, { 0x18, 0, }, { 0x19, 0, }, { 0x1b, 0, },
+ { 0x1c, 1, }, { 0x1d, 0, }, { 0x1e, 1, },
+ };
+ struct spu_priv2 __iomem *priv2;
+ int i;
+
+ priv2 = spu->priv2;
+
+ /* initialize all channel data to zero */
+ for (i = 0; i < ARRAY_SIZE(zero_list); i++) {
+ int count;
+
+ out_be64(&priv2->spu_chnlcntptr_RW, zero_list[i].channel);
+ for (count = 0; count < zero_list[i].count; count++)
+ out_be64(&priv2->spu_chnldata_RW, 0);
+ }
+
+ /* initialize channel counts to meaningful values */
+ for (i = 0; i < ARRAY_SIZE(count_list); i++) {
+ out_be64(&priv2->spu_chnlcntptr_RW, count_list[i].channel);
+ out_be64(&priv2->spu_chnlcnt_RW, count_list[i].count);
+ }
+}
+
+struct spu *spu_alloc(void)
+{
+ struct spu *spu;
+
+ down(&spu_mutex);
+ if (!list_empty(&spu_list)) {
+ spu = list_entry(spu_list.next, struct spu, list);
+ list_del_init(&spu->list);
+ pr_debug("Got SPU %x %d\n", spu->isrc, spu->number);
+ } else {
+ pr_debug("No SPU left\n");
+ spu = NULL;
+ }
+ up(&spu_mutex);
+
+ if (spu)
+ spu_init_channels(spu);
+
+ return spu;
+}
+EXPORT_SYMBOL_GPL(spu_alloc);
+
+void spu_free(struct spu *spu)
+{
+ down(&spu_mutex);
+ list_add_tail(&spu->list, &spu_list);
+ up(&spu_mutex);
+}
+EXPORT_SYMBOL_GPL(spu_free);
+
+static int spu_handle_mm_fault(struct spu *spu)
+{
+ struct mm_struct *mm = spu->mm;
+ struct vm_area_struct *vma;
+ u64 ea, dsisr, is_write;
+ int ret;
+
+ ea = spu->dar;
+ dsisr = spu->dsisr;
+#if 0
+ if (!IS_VALID_EA(ea)) {
+ return -EFAULT;
+ }
+#endif /* XXX */
+ if (mm == NULL) {
+ return -EFAULT;
+ }
+ if (mm->pgd == NULL) {
+ return -EFAULT;
+ }
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, ea);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= ea)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+#if 0
+ if (expand_stack(vma, ea))
+ goto bad_area;
+#endif /* XXX */
+good_area:
+ is_write = dsisr & MFC_DSISR_ACCESS_PUT;
+ if (is_write) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+ if (dsisr & MFC_DSISR_ACCESS_DENIED)
+ goto bad_area;
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+ ret = 0;
+ switch (handle_mm_fault(mm, vma, ea, is_write)) {
+ case VM_FAULT_MINOR:
+ current->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ current->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ ret = -EFAULT;
+ goto bad_area;
+ case VM_FAULT_OOM:
+ ret = -ENOMEM;
+ goto bad_area;
+ default:
+ BUG();
+ }
+ up_read(&mm->mmap_sem);
+ return ret;
+
+bad_area:
+ up_read(&mm->mmap_sem);
+ return -EFAULT;
+}
+
+int spu_irq_class_1_bottom(struct spu *spu)
+{
+ u64 ea, dsisr, access, error = 0UL;
+ int ret = 0;
+
+ ea = spu->dar;
+ dsisr = spu->dsisr;
+ if (dsisr & MFC_DSISR_PTE_NOT_FOUND) {
+ access = (_PAGE_PRESENT | _PAGE_USER);
+ access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ if (hash_page(ea, access, 0x300) != 0)
+ error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ }
+ if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) ||
+ (dsisr & MFC_DSISR_ACCESS_DENIED)) {
+ if ((ret = spu_handle_mm_fault(spu)) != 0)
+ error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ else
+ error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ }
+ spu->dar = 0UL;
+ spu->dsisr = 0UL;
+ if (!error) {
+ spu_restart_dma(spu);
+ } else {
+ __spu_trap_invalid_dma(spu);
+ }
+ return ret;
+}
+
+void spu_irq_setaffinity(struct spu *spu, int cpu)
+{
+ u64 target = iic_get_target_id(cpu);
+ u64 route = target << 48 | target << 32 | target << 16;
+ spu_int_route_set(spu, route);
+}
+EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
+
+static void __iomem * __init map_spe_prop(struct device_node *n,
+ const char *name)
+{
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *prop;
+
+ void *p;
+ int proplen;
+
+ p = get_property(n, name, &proplen);
+ if (proplen != sizeof (struct address_prop))
+ return NULL;
+
+ prop = p;
+
+ return ioremap(prop->address, prop->len);
+}
+
+static void spu_unmap(struct spu *spu)
+{
+ iounmap(spu->priv2);
+ iounmap(spu->priv1);
+ iounmap(spu->problem);
+ iounmap((u8 __iomem *)spu->local_store);
+}
+
+static int __init spu_map_device(struct spu *spu, struct device_node *spe)
+{
+ char *prop;
+ int ret;
+
+ ret = -ENODEV;
+ prop = get_property(spe, "isrc", NULL);
+ if (!prop)
+ goto out;
+ spu->isrc = *(unsigned int *)prop;
+
+ spu->name = get_property(spe, "name", NULL);
+ if (!spu->name)
+ goto out;
+
+ prop = get_property(spe, "local-store", NULL);
+ if (!prop)
+ goto out;
+ spu->local_store_phys = *(unsigned long *)prop;
+
+ /* we use local store as ram, not io memory */
+ spu->local_store = (void __force *)map_spe_prop(spe, "local-store");
+ if (!spu->local_store)
+ goto out;
+
+ spu->problem= map_spe_prop(spe, "problem");
+ if (!spu->problem)
+ goto out_unmap;
+
+ spu->priv1= map_spe_prop(spe, "priv1");
+ /* priv1 is not available on a hypervisor */
+
+ spu->priv2= map_spe_prop(spe, "priv2");
+ if (!spu->priv2)
+ goto out_unmap;
+ ret = 0;
+ goto out;
+
+out_unmap:
+ spu_unmap(spu);
+out:
+ return ret;
+}
+
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+ struct device_node *cpu;
+
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+
+ return id ? *id : 0;
+}
+
+static int __init create_spu(struct device_node *spe)
+{
+ struct spu *spu;
+ int ret;
+ static int number;
+
+ ret = -ENOMEM;
+ spu = kmalloc(sizeof (*spu), GFP_KERNEL);
+ if (!spu)
+ goto out;
+
+ ret = spu_map_device(spu, spe);
+ if (ret)
+ goto out_free;
+
+ spu->node = find_spu_node_id(spe);
+ spu->stop_code = 0;
+ spu->slb_replace = 0;
+ spu->mm = NULL;
+ spu->ctx = NULL;
+ spu->rq = NULL;
+ spu->pid = 0;
+ spu->class_0_pending = 0;
+ spu->flags = 0UL;
+ spu->dar = 0UL;
+ spu->dsisr = 0UL;
+ spin_lock_init(&spu->register_lock);
+
+ spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
+ spu_mfc_sr1_set(spu, 0x33);
+
+ spu->ibox_callback = NULL;
+ spu->wbox_callback = NULL;
+ spu->stop_callback = NULL;
+
+ down(&spu_mutex);
+ spu->number = number++;
+ ret = spu_request_irqs(spu);
+ if (ret)
+ goto out_unmap;
+
+ list_add(&spu->list, &spu_list);
+ up(&spu_mutex);
+
+ pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
+ spu->name, spu->isrc, spu->local_store,
+ spu->problem, spu->priv1, spu->priv2, spu->number);
+ goto out;
+
+out_unmap:
+ up(&spu_mutex);
+ spu_unmap(spu);
+out_free:
+ kfree(spu);
+out:
+ return ret;
+}
+
+static void destroy_spu(struct spu *spu)
+{
+ list_del_init(&spu->list);
+
+ spu_free_irqs(spu);
+ spu_unmap(spu);
+ kfree(spu);
+}
+
+static void cleanup_spu_base(void)
+{
+ struct spu *spu, *tmp;
+ down(&spu_mutex);
+ list_for_each_entry_safe(spu, tmp, &spu_list, list)
+ destroy_spu(spu);
+ up(&spu_mutex);
+}
+module_exit(cleanup_spu_base);
+
+static int __init init_spu_base(void)
+{
+ struct device_node *node;
+ int ret;
+
+ ret = -ENODEV;
+ for (node = of_find_node_by_type(NULL, "spe");
+ node; node = of_find_node_by_type(node, "spe")) {
+ ret = create_spu(node);
+ if (ret) {
+ printk(KERN_WARNING "%s: Error initializing %s\n",
+ __FUNCTION__, node->name);
+ cleanup_spu_base();
+ break;
+ }
+ }
+ /* in some old firmware versions, the spe is called 'spc', so we
+ look for that as well */
+ for (node = of_find_node_by_type(NULL, "spc");
+ node; node = of_find_node_by_type(node, "spc")) {
+ ret = create_spu(node);
+ if (ret) {
+ printk(KERN_WARNING "%s: Error initializing %s\n",
+ __FUNCTION__, node->name);
+ cleanup_spu_base();
+ break;
+ }
+ }
+ return ret;
+}
+module_init(init_spu_base);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c
new file mode 100644
index 000000000000..b2656421c7b5
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_priv1.c
@@ -0,0 +1,133 @@
+/*
+ * access to SPU privileged registers
+ */
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+
+void spu_int_mask_and(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+
+ old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+ out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_and);
+
+void spu_int_mask_or(struct spu *spu, int class, u64 mask)
+{
+ u64 old_mask;
+
+ old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+ out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_or);
+
+void spu_int_mask_set(struct spu *spu, int class, u64 mask)
+{
+ out_be64(&spu->priv1->int_mask_RW[class], mask);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_set);
+
+u64 spu_int_mask_get(struct spu *spu, int class)
+{
+ return in_be64(&spu->priv1->int_mask_RW[class]);
+}
+EXPORT_SYMBOL_GPL(spu_int_mask_get);
+
+void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+ out_be64(&spu->priv1->int_stat_RW[class], stat);
+}
+EXPORT_SYMBOL_GPL(spu_int_stat_clear);
+
+u64 spu_int_stat_get(struct spu *spu, int class)
+{
+ return in_be64(&spu->priv1->int_stat_RW[class]);
+}
+EXPORT_SYMBOL_GPL(spu_int_stat_get);
+
+void spu_int_route_set(struct spu *spu, u64 route)
+{
+ out_be64(&spu->priv1->int_route_RW, route);
+}
+EXPORT_SYMBOL_GPL(spu_int_route_set);
+
+u64 spu_mfc_dar_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_dar_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
+
+u64 spu_mfc_dsisr_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_dsisr_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
+
+void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+ out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
+
+void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
+{
+ out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
+
+void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+ out_be64(&spu->priv1->mfc_sr1_RW, sr1);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
+
+u64 spu_mfc_sr1_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_sr1_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
+
+void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+ out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
+
+u64 spu_mfc_tclass_id_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->mfc_tclass_id_RW);
+}
+EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
+
+void spu_tlb_invalidate(struct spu *spu)
+{
+ out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
+}
+EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
+
+void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+ out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
+
+u64 spu_resource_allocation_groupID_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->resource_allocation_groupID_RW);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
+
+void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+ out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
+
+u64 spu_resource_allocation_enable_get(struct spu *spu)
+{
+ return in_be64(&spu->priv1->resource_allocation_enable_RW);
+}
+EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
new file mode 100644
index 000000000000..261b507a901a
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -0,0 +1,88 @@
+/*
+ * SPU file system -- system call stubs
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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/file.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+
+#include <asm/spu.h>
+
+struct spufs_calls spufs_calls = {
+ .owner = NULL,
+};
+
+/* These stub syscalls are needed to have the actual implementation
+ * within a loadable module. When spufs is built into the kernel,
+ * this file is not used and the syscalls directly enter the fs code */
+
+asmlinkage long sys_spu_create(const char __user *name,
+ unsigned int flags, mode_t mode)
+{
+ long ret;
+ struct module *owner = spufs_calls.owner;
+
+ ret = -ENOSYS;
+ if (owner && try_module_get(owner)) {
+ ret = spufs_calls.create_thread(name, flags, mode);
+ module_put(owner);
+ }
+ return ret;
+}
+
+asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
+{
+ long ret;
+ struct file *filp;
+ int fput_needed;
+ struct module *owner = spufs_calls.owner;
+
+ ret = -ENOSYS;
+ if (owner && try_module_get(owner)) {
+ ret = -EBADF;
+ filp = fget_light(fd, &fput_needed);
+ if (filp) {
+ ret = spufs_calls.spu_run(filp, unpc, ustatus);
+ fput_light(filp, fput_needed);
+ }
+ module_put(owner);
+ }
+ return ret;
+}
+
+int register_spu_syscalls(struct spufs_calls *calls)
+{
+ if (spufs_calls.owner)
+ return -EBUSY;
+
+ spufs_calls.create_thread = calls->create_thread;
+ spufs_calls.spu_run = calls->spu_run;
+ smp_mb();
+ spufs_calls.owner = calls->owner;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(register_spu_syscalls);
+
+void unregister_spu_syscalls(struct spufs_calls *calls)
+{
+ BUG_ON(spufs_calls.owner != calls->owner);
+ spufs_calls.owner = NULL;
+}
+EXPORT_SYMBOL_GPL(unregister_spu_syscalls);
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
new file mode 100644
index 000000000000..a7cddf40e3d9
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -0,0 +1,54 @@
+obj-$(CONFIG_SPU_FS) += spufs.o
+spufs-y += inode.o file.o context.o switch.o syscalls.o
+spufs-y += sched.o backing_ops.o hw_ops.o run.o
+
+# Rules to build switch.o with the help of SPU tool chain
+SPU_CROSS := spu-
+SPU_CC := $(SPU_CROSS)gcc
+SPU_AS := $(SPU_CROSS)gcc
+SPU_LD := $(SPU_CROSS)ld
+SPU_OBJCOPY := $(SPU_CROSS)objcopy
+SPU_CFLAGS := -O2 -Wall -I$(srctree)/include -I$(objtree)/include2
+SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2
+SPU_LDFLAGS := -N -Ttext=0x0
+
+$(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
+
+# Compile SPU files
+ cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $<
+quiet_cmd_spu_cc = SPU_CC $@
+$(obj)/spu_%.o: $(src)/spu_%.c
+ $(call if_changed,spu_cc)
+
+# Assemble SPU files
+ cmd_spu_as = $(SPU_AS) $(SPU_AFLAGS) -o $@ $<
+quiet_cmd_spu_as = SPU_AS $@
+$(obj)/spu_%.o: $(src)/spu_%.S
+ $(call if_changed,spu_as)
+
+# Link SPU Executables
+ cmd_spu_ld = $(SPU_LD) $(SPU_LDFLAGS) -o $@ $^
+quiet_cmd_spu_ld = SPU_LD $@
+$(obj)/spu_%: $(obj)/spu_%_crt0.o $(obj)/spu_%.o
+ $(call if_changed,spu_ld)
+
+# Copy into binary format
+ cmd_spu_objcopy = $(SPU_OBJCOPY) -O binary $< $@
+quiet_cmd_spu_objcopy = OBJCOPY $@
+$(obj)/spu_%.bin: $(src)/spu_%
+ $(call if_changed,spu_objcopy)
+
+# create C code from ELF executable
+cmd_hexdump = ( \
+ echo "/*" ; \
+ echo " * $*_dump.h: Copyright (C) 2005 IBM." ; \
+ echo " * Hex-dump auto generated from $*.c." ; \
+ echo " * Do not edit!" ; \
+ echo " */" ; \
+ echo "static unsigned int $*_code[] __page_aligned = {" ; \
+ hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \
+ echo "};" ; \
+ ) > $@
+quiet_cmd_hexdump = HEXDUMP $@
+$(obj)/%_dump.h: $(obj)/%.bin
+ $(call if_changed,hexdump)
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c
new file mode 100644
index 000000000000..a5c489a53c61
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -0,0 +1,308 @@
+/* backing_ops.c - query/set operations on saved SPU context.
+ *
+ * Copyright (C) IBM 2005
+ * Author: Mark Nutter <mnutter@us.ibm.com>
+ *
+ * These register operations allow SPUFS to operate on saved
+ * SPU contexts rather than hardware.
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/poll.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include <asm/mmu_context.h>
+#include "spufs.h"
+
+/*
+ * Reads/writes to various problem and priv2 registers require
+ * state changes, i.e. generate SPU events, modify channel
+ * counts, etc.
+ */
+
+static void gen_spu_event(struct spu_context *ctx, u32 event)
+{
+ u64 ch0_cnt;
+ u64 ch0_data;
+ u64 ch1_data;
+
+ ch0_cnt = ctx->csa.spu_chnlcnt_RW[0];
+ ch0_data = ctx->csa.spu_chnldata_RW[0];
+ ch1_data = ctx->csa.spu_chnldata_RW[1];
+ ctx->csa.spu_chnldata_RW[0] |= event;
+ if ((ch0_cnt == 0) && !(ch0_data & event) && (ch1_data & event)) {
+ ctx->csa.spu_chnlcnt_RW[0] = 1;
+ }
+}
+
+static int spu_backing_mbox_read(struct spu_context *ctx, u32 * data)
+{
+ u32 mbox_stat;
+ int ret = 0;
+
+ spin_lock(&ctx->csa.register_lock);
+ mbox_stat = ctx->csa.prob.mb_stat_R;
+ if (mbox_stat & 0x0000ff) {
+ /* Read the first available word.
+ * Implementation note: the depth
+ * of pu_mb_R is currently 1.
+ */
+ *data = ctx->csa.prob.pu_mb_R;
+ ctx->csa.prob.mb_stat_R &= ~(0x0000ff);
+ ctx->csa.spu_chnlcnt_RW[28] = 1;
+ gen_spu_event(ctx, MFC_PU_MAILBOX_AVAILABLE_EVENT);
+ ret = 4;
+ }
+ spin_unlock(&ctx->csa.register_lock);
+ return ret;
+}
+
+static u32 spu_backing_mbox_stat_read(struct spu_context *ctx)
+{
+ return ctx->csa.prob.mb_stat_R;
+}
+
+static unsigned int spu_backing_mbox_stat_poll(struct spu_context *ctx,
+ unsigned int events)
+{
+ int ret;
+ u32 stat;
+
+ ret = 0;
+ spin_lock_irq(&ctx->csa.register_lock);
+ stat = ctx->csa.prob.mb_stat_R;
+
+ /* if the requested event is there, return the poll
+ mask, otherwise enable the interrupt to get notified,
+ but first mark any pending interrupts as done so
+ we don't get woken up unnecessarily */
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (stat & 0xff0000)
+ ret |= POLLIN | POLLRDNORM;
+ else {
+ ctx->csa.priv1.int_stat_class0_RW &= ~0x1;
+ ctx->csa.priv1.int_mask_class2_RW |= 0x1;
+ }
+ }
+ if (events & (POLLOUT | POLLWRNORM)) {
+ if (stat & 0x00ff00)
+ ret = POLLOUT | POLLWRNORM;
+ else {
+ ctx->csa.priv1.int_stat_class0_RW &= ~0x10;
+ ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+ }
+ }
+ spin_unlock_irq(&ctx->csa.register_lock);
+ return ret;
+}
+
+static int spu_backing_ibox_read(struct spu_context *ctx, u32 * data)
+{
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ if (ctx->csa.prob.mb_stat_R & 0xff0000) {
+ /* Read the first available word.
+ * Implementation note: the depth
+ * of puint_mb_R is currently 1.
+ */
+ *data = ctx->csa.priv2.puint_mb_R;
+ ctx->csa.prob.mb_stat_R &= ~(0xff0000);
+ ctx->csa.spu_chnlcnt_RW[30] = 1;
+ gen_spu_event(ctx, MFC_PU_INT_MAILBOX_AVAILABLE_EVENT);
+ ret = 4;
+ } else {
+ /* make sure we get woken up by the interrupt */
+ ctx->csa.priv1.int_mask_class2_RW |= 0x1UL;
+ ret = 0;
+ }
+ spin_unlock(&ctx->csa.register_lock);
+ return ret;
+}
+
+static int spu_backing_wbox_write(struct spu_context *ctx, u32 data)
+{
+ int ret;
+
+ spin_lock(&ctx->csa.register_lock);
+ if ((ctx->csa.prob.mb_stat_R) & 0x00ff00) {
+ int slot = ctx->csa.spu_chnlcnt_RW[29];
+ int avail = (ctx->csa.prob.mb_stat_R & 0x00ff00) >> 8;
+
+ /* We have space to write wbox_data.
+ * Implementation note: the depth
+ * of spu_mb_W is currently 4.
+ */
+ BUG_ON(avail != (4 - slot));
+ ctx->csa.spu_mailbox_data[slot] = data;
+ ctx->csa.spu_chnlcnt_RW[29] = ++slot;
+ ctx->csa.prob.mb_stat_R = (((4 - slot) & 0xff) << 8);
+ gen_spu_event(ctx, MFC_SPU_MAILBOX_WRITTEN_EVENT);
+ ret = 4;
+ } else {
+ /* make sure we get woken up by the interrupt when space
+ becomes available */
+ ctx->csa.priv1.int_mask_class2_RW |= 0x10;
+ ret = 0;
+ }
+ spin_unlock(&ctx->csa.register_lock);
+ return ret;
+}
+
+static u32 spu_backing_signal1_read(struct spu_context *ctx)
+{
+ return ctx->csa.spu_chnldata_RW[3];
+}
+
+static void spu_backing_signal1_write(struct spu_context *ctx, u32 data)
+{
+ spin_lock(&ctx->csa.register_lock);
+ if (ctx->csa.priv2.spu_cfg_RW & 0x1)
+ ctx->csa.spu_chnldata_RW[3] |= data;
+ else
+ ctx->csa.spu_chnldata_RW[3] = data;
+ ctx->csa.spu_chnlcnt_RW[3] = 1;
+ gen_spu_event(ctx, MFC_SIGNAL_1_EVENT);
+ spin_unlock(&ctx->csa.register_lock);
+}
+
+static u32 spu_backing_signal2_read(struct spu_context *ctx)
+{
+ return ctx->csa.spu_chnldata_RW[4];
+}
+
+static void spu_backing_signal2_write(struct spu_context *ctx, u32 data)
+{
+ spin_lock(&ctx->csa.register_lock);
+ if (ctx->csa.priv2.spu_cfg_RW & 0x2)
+ ctx->csa.spu_chnldata_RW[4] |= data;
+ else
+ ctx->csa.spu_chnldata_RW[4] = data;
+ ctx->csa.spu_chnlcnt_RW[4] = 1;
+ gen_spu_event(ctx, MFC_SIGNAL_2_EVENT);
+ spin_unlock(&ctx->csa.register_lock);
+}
+
+static void spu_backing_signal1_type_set(struct spu_context *ctx, u64 val)
+{
+ u64 tmp;
+
+ spin_lock(&ctx->csa.register_lock);
+ tmp = ctx->csa.priv2.spu_cfg_RW;
+ if (val)
+ tmp |= 1;
+ else
+ tmp &= ~1;
+ ctx->csa.priv2.spu_cfg_RW = tmp;
+ spin_unlock(&ctx->csa.register_lock);
+}
+
+static u64 spu_backing_signal1_type_get(struct spu_context *ctx)
+{
+ return ((ctx->csa.priv2.spu_cfg_RW & 1) != 0);
+}
+
+static void spu_backing_signal2_type_set(struct spu_context *ctx, u64 val)
+{
+ u64 tmp;
+
+ spin_lock(&ctx->csa.register_lock);
+ tmp = ctx->csa.priv2.spu_cfg_RW;
+ if (val)
+ tmp |= 2;
+ else
+ tmp &= ~2;
+ ctx->csa.priv2.spu_cfg_RW = tmp;
+ spin_unlock(&ctx->csa.register_lock);
+}
+
+static u64 spu_backing_signal2_type_get(struct spu_context *ctx)
+{
+ return ((ctx->csa.priv2.spu_cfg_RW & 2) != 0);
+}
+
+static u32 spu_backing_npc_read(struct spu_context *ctx)
+{
+ return ctx->csa.prob.spu_npc_RW;
+}
+
+static void spu_backing_npc_write(struct spu_context *ctx, u32 val)
+{
+ ctx->csa.prob.spu_npc_RW = val;
+}
+
+static u32 spu_backing_status_read(struct spu_context *ctx)
+{
+ return ctx->csa.prob.spu_status_R;
+}
+
+static char *spu_backing_get_ls(struct spu_context *ctx)
+{
+ return ctx->csa.lscsa->ls;
+}
+
+static void spu_backing_runcntl_write(struct spu_context *ctx, u32 val)
+{
+ spin_lock(&ctx->csa.register_lock);
+ ctx->csa.prob.spu_runcntl_RW = val;
+ if (val & SPU_RUNCNTL_RUNNABLE) {
+ ctx->csa.prob.spu_status_R |= SPU_STATUS_RUNNING;
+ } else {
+ ctx->csa.prob.spu_status_R &= ~SPU_STATUS_RUNNING;
+ }
+ spin_unlock(&ctx->csa.register_lock);
+}
+
+static void spu_backing_runcntl_stop(struct spu_context *ctx)
+{
+ spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
+}
+
+struct spu_context_ops spu_backing_ops = {
+ .mbox_read = spu_backing_mbox_read,
+ .mbox_stat_read = spu_backing_mbox_stat_read,
+ .mbox_stat_poll = spu_backing_mbox_stat_poll,
+ .ibox_read = spu_backing_ibox_read,
+ .wbox_write = spu_backing_wbox_write,
+ .signal1_read = spu_backing_signal1_read,
+ .signal1_write = spu_backing_signal1_write,
+ .signal2_read = spu_backing_signal2_read,
+ .signal2_write = spu_backing_signal2_write,
+ .signal1_type_set = spu_backing_signal1_type_set,
+ .signal1_type_get = spu_backing_signal1_type_get,
+ .signal2_type_set = spu_backing_signal2_type_set,
+ .signal2_type_get = spu_backing_signal2_type_get,
+ .npc_read = spu_backing_npc_read,
+ .npc_write = spu_backing_npc_write,
+ .status_read = spu_backing_status_read,
+ .get_ls = spu_backing_get_ls,
+ .runcntl_write = spu_backing_runcntl_write,
+ .runcntl_stop = spu_backing_runcntl_stop,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
new file mode 100644
index 000000000000..336f238102fd
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -0,0 +1,167 @@
+/*
+ * SPU file system -- SPU context management
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include "spufs.h"
+
+struct spu_context *alloc_spu_context(struct address_space *local_store)
+{
+ struct spu_context *ctx;
+ ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
+ if (!ctx)
+ goto out;
+ /* Binding to physical processor deferred
+ * until spu_activate().
+ */
+ spu_init_csa(&ctx->csa);
+ if (!ctx->csa.lscsa) {
+ goto out_free;
+ }
+ spin_lock_init(&ctx->mmio_lock);
+ kref_init(&ctx->kref);
+ init_rwsem(&ctx->state_sema);
+ init_MUTEX(&ctx->run_sema);
+ init_waitqueue_head(&ctx->ibox_wq);
+ init_waitqueue_head(&ctx->wbox_wq);
+ init_waitqueue_head(&ctx->stop_wq);
+ ctx->ibox_fasync = NULL;
+ ctx->wbox_fasync = NULL;
+ ctx->state = SPU_STATE_SAVED;
+ ctx->local_store = local_store;
+ ctx->spu = NULL;
+ ctx->ops = &spu_backing_ops;
+ ctx->owner = get_task_mm(current);
+ goto out;
+out_free:
+ kfree(ctx);
+ ctx = NULL;
+out:
+ return ctx;
+}
+
+void destroy_spu_context(struct kref *kref)
+{
+ struct spu_context *ctx;
+ ctx = container_of(kref, struct spu_context, kref);
+ down_write(&ctx->state_sema);
+ spu_deactivate(ctx);
+ ctx->ibox_fasync = NULL;
+ ctx->wbox_fasync = NULL;
+ up_write(&ctx->state_sema);
+ spu_fini_csa(&ctx->csa);
+ kfree(ctx);
+}
+
+struct spu_context * get_spu_context(struct spu_context *ctx)
+{
+ kref_get(&ctx->kref);
+ return ctx;
+}
+
+int put_spu_context(struct spu_context *ctx)
+{
+ return kref_put(&ctx->kref, &destroy_spu_context);
+}
+
+/* give up the mm reference when the context is about to be destroyed */
+void spu_forget(struct spu_context *ctx)
+{
+ struct mm_struct *mm;
+ spu_acquire_saved(ctx);
+ mm = ctx->owner;
+ ctx->owner = NULL;
+ mmput(mm);
+ spu_release(ctx);
+}
+
+void spu_acquire(struct spu_context *ctx)
+{
+ down_read(&ctx->state_sema);
+}
+
+void spu_release(struct spu_context *ctx)
+{
+ up_read(&ctx->state_sema);
+}
+
+void spu_unmap_mappings(struct spu_context *ctx)
+{
+ unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
+}
+
+int spu_acquire_runnable(struct spu_context *ctx)
+{
+ int ret = 0;
+
+ down_read(&ctx->state_sema);
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ ctx->spu->prio = current->prio;
+ return 0;
+ }
+ up_read(&ctx->state_sema);
+
+ down_write(&ctx->state_sema);
+ /* ctx is about to be freed, can't acquire any more */
+ if (!ctx->owner) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ctx->state == SPU_STATE_SAVED) {
+ ret = spu_activate(ctx, 0);
+ if (ret)
+ goto out;
+ ctx->state = SPU_STATE_RUNNABLE;
+ }
+
+ downgrade_write(&ctx->state_sema);
+ /* On success, we return holding the lock */
+
+ return ret;
+out:
+ /* Release here, to simplify calling code. */
+ up_write(&ctx->state_sema);
+
+ return ret;
+}
+
+void spu_acquire_saved(struct spu_context *ctx)
+{
+ down_read(&ctx->state_sema);
+
+ if (ctx->state == SPU_STATE_SAVED)
+ return;
+
+ up_read(&ctx->state_sema);
+ down_write(&ctx->state_sema);
+
+ if (ctx->state == SPU_STATE_RUNNABLE) {
+ spu_deactivate(ctx);
+ ctx->state = SPU_STATE_SAVED;
+ }
+
+ downgrade_write(&ctx->state_sema);
+}
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
new file mode 100644
index 000000000000..dfa649c9b956
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -0,0 +1,794 @@
+/*
+ * SPU file system -- file contents
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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/fs.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/ptrace.h>
+
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/spu.h>
+#include <asm/uaccess.h>
+
+#include "spufs.h"
+
+
+static int
+spufs_mem_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ file->private_data = i->i_ctx;
+ file->f_mapping = i->i_ctx->local_store;
+ return 0;
+}
+
+static ssize_t
+spufs_mem_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ char *local_store;
+ int ret;
+
+ spu_acquire(ctx);
+
+ local_store = ctx->ops->get_ls(ctx);
+ ret = simple_read_from_buffer(buffer, size, pos, local_store, LS_SIZE);
+
+ spu_release(ctx);
+ return ret;
+}
+
+static ssize_t
+spufs_mem_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ char *local_store;
+ int ret;
+
+ size = min_t(ssize_t, LS_SIZE - *pos, size);
+ if (size <= 0)
+ return -EFBIG;
+ *pos += size;
+
+ spu_acquire(ctx);
+
+ local_store = ctx->ops->get_ls(ctx);
+ ret = copy_from_user(local_store + *pos - size,
+ buffer, size) ? -EFAULT : size;
+
+ spu_release(ctx);
+ return ret;
+}
+
+#ifdef CONFIG_SPARSEMEM
+static struct page *
+spufs_mem_mmap_nopage(struct vm_area_struct *vma,
+ unsigned long address, int *type)
+{
+ struct page *page = NOPAGE_SIGBUS;
+
+ struct spu_context *ctx = vma->vm_file->private_data;
+ unsigned long offset = address - vma->vm_start;
+ offset += vma->vm_pgoff << PAGE_SHIFT;
+
+ spu_acquire(ctx);
+
+ if (ctx->state == SPU_STATE_SAVED)
+ page = vmalloc_to_page(ctx->csa.lscsa->ls + offset);
+ else
+ page = pfn_to_page((ctx->spu->local_store_phys + offset)
+ >> PAGE_SHIFT);
+
+ spu_release(ctx);
+
+ if (type)
+ *type = VM_FAULT_MINOR;
+
+ page_cache_get(page);
+ return page;
+}
+
+static struct vm_operations_struct spufs_mem_mmap_vmops = {
+ .nopage = spufs_mem_mmap_nopage,
+};
+
+static int
+spufs_mem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (!(vma->vm_flags & VM_SHARED))
+ return -EINVAL;
+
+ /* FIXME: */
+ vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+ | _PAGE_NO_CACHE);
+
+ vma->vm_ops = &spufs_mem_mmap_vmops;
+ return 0;
+}
+#endif
+
+static struct file_operations spufs_mem_fops = {
+ .open = spufs_mem_open,
+ .read = spufs_mem_read,
+ .write = spufs_mem_write,
+ .llseek = generic_file_llseek,
+#ifdef CONFIG_SPARSEMEM
+ .mmap = spufs_mem_mmap,
+#endif
+};
+
+static int
+spufs_regs_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ file->private_data = i->i_ctx;
+ return 0;
+}
+
+static ssize_t
+spufs_regs_read(struct file *file, char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ int ret;
+
+ spu_acquire_saved(ctx);
+
+ ret = simple_read_from_buffer(buffer, size, pos,
+ lscsa->gprs, sizeof lscsa->gprs);
+
+ spu_release(ctx);
+ return ret;
+}
+
+static ssize_t
+spufs_regs_write(struct file *file, const char __user *buffer,
+ size_t size, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ int ret;
+
+ size = min_t(ssize_t, sizeof lscsa->gprs - *pos, size);
+ if (size <= 0)
+ return -EFBIG;
+ *pos += size;
+
+ spu_acquire_saved(ctx);
+
+ ret = copy_from_user(lscsa->gprs + *pos - size,
+ buffer, size) ? -EFAULT : size;
+
+ spu_release(ctx);
+ return ret;
+}
+
+static struct file_operations spufs_regs_fops = {
+ .open = spufs_regs_open,
+ .read = spufs_regs_read,
+ .write = spufs_regs_write,
+ .llseek = generic_file_llseek,
+};
+
+static ssize_t
+spufs_fpcr_read(struct file *file, char __user * buffer,
+ size_t size, loff_t * pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ int ret;
+
+ spu_acquire_saved(ctx);
+
+ ret = simple_read_from_buffer(buffer, size, pos,
+ &lscsa->fpcr, sizeof(lscsa->fpcr));
+
+ spu_release(ctx);
+ return ret;
+}
+
+static ssize_t
+spufs_fpcr_write(struct file *file, const char __user * buffer,
+ size_t size, loff_t * pos)
+{
+ struct spu_context *ctx = file->private_data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ int ret;
+
+ size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
+ if (size <= 0)
+ return -EFBIG;
+ *pos += size;
+
+ spu_acquire_saved(ctx);
+
+ ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
+ buffer, size) ? -EFAULT : size;
+
+ spu_release(ctx);
+ return ret;
+}
+
+static struct file_operations spufs_fpcr_fops = {
+ .open = spufs_regs_open,
+ .read = spufs_fpcr_read,
+ .write = spufs_fpcr_write,
+ .llseek = generic_file_llseek,
+};
+
+/* generic open function for all pipe-like files */
+static int spufs_pipe_open(struct inode *inode, struct file *file)
+{
+ struct spufs_inode_info *i = SPUFS_I(inode);
+ file->private_data = i->i_ctx;
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 mbox_data;
+ int ret;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+ ret = ctx->ops->mbox_read(ctx, &mbox_data);
+ spu_release(ctx);
+
+ if (!ret)
+ return -EAGAIN;
+
+ if (copy_to_user(buf, &mbox_data, sizeof mbox_data))
+ return -EFAULT;
+
+ return 4;
+}
+
+static struct file_operations spufs_mbox_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_mbox_read,
+};
+
+static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 mbox_stat;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+
+ mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
+
+ spu_release(ctx);
+
+ if (copy_to_user(buf, &mbox_stat, sizeof mbox_stat))
+ return -EFAULT;
+
+ return 4;
+}
+
+static struct file_operations spufs_mbox_stat_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_mbox_stat_read,
+};
+
+/* low-level ibox access function */
+size_t spu_ibox_read(struct spu_context *ctx, u32 *data)
+{
+ return ctx->ops->ibox_read(ctx, data);
+}
+
+static int spufs_ibox_fasync(int fd, struct file *file, int on)
+{
+ struct spu_context *ctx = file->private_data;
+
+ return fasync_helper(fd, file, on, &ctx->ibox_fasync);
+}
+
+/* interrupt-level ibox callback function. */
+void spufs_ibox_callback(struct spu *spu)
+{
+ struct spu_context *ctx = spu->ctx;
+
+ wake_up_all(&ctx->ibox_wq);
+ kill_fasync(&ctx->ibox_fasync, SIGIO, POLLIN);
+}
+
+static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 ibox_data;
+ ssize_t ret;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+
+ ret = 0;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!spu_ibox_read(ctx, &ibox_data))
+ ret = -EAGAIN;
+ } else {
+ ret = spufs_wait(ctx->ibox_wq, spu_ibox_read(ctx, &ibox_data));
+ }
+
+ spu_release(ctx);
+
+ if (ret)
+ return ret;
+
+ ret = 4;
+ if (copy_to_user(buf, &ibox_data, sizeof ibox_data))
+ ret = -EFAULT;
+
+ return ret;
+}
+
+static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
+{
+ struct spu_context *ctx = file->private_data;
+ unsigned int mask;
+
+ poll_wait(file, &ctx->ibox_wq, wait);
+
+ spu_acquire(ctx);
+ mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
+ spu_release(ctx);
+
+ return mask;
+}
+
+static struct file_operations spufs_ibox_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_ibox_read,
+ .poll = spufs_ibox_poll,
+ .fasync = spufs_ibox_fasync,
+};
+
+static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 ibox_stat;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+ ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
+ spu_release(ctx);
+
+ if (copy_to_user(buf, &ibox_stat, sizeof ibox_stat))
+ return -EFAULT;
+
+ return 4;
+}
+
+static struct file_operations spufs_ibox_stat_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_ibox_stat_read,
+};
+
+/* low-level mailbox write */
+size_t spu_wbox_write(struct spu_context *ctx, u32 data)
+{
+ return ctx->ops->wbox_write(ctx, data);
+}
+
+static int spufs_wbox_fasync(int fd, struct file *file, int on)
+{
+ struct spu_context *ctx = file->private_data;
+ int ret;
+
+ ret = fasync_helper(fd, file, on, &ctx->wbox_fasync);
+
+ return ret;
+}
+
+/* interrupt-level wbox callback function. */
+void spufs_wbox_callback(struct spu *spu)
+{
+ struct spu_context *ctx = spu->ctx;
+
+ wake_up_all(&ctx->wbox_wq);
+ kill_fasync(&ctx->wbox_fasync, SIGIO, POLLOUT);
+}
+
+static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 wbox_data;
+ int ret;
+
+ if (len < 4)
+ return -EINVAL;
+
+ if (copy_from_user(&wbox_data, buf, sizeof wbox_data))
+ return -EFAULT;
+
+ spu_acquire(ctx);
+
+ ret = 0;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!spu_wbox_write(ctx, wbox_data))
+ ret = -EAGAIN;
+ } else {
+ ret = spufs_wait(ctx->wbox_wq, spu_wbox_write(ctx, wbox_data));
+ }
+
+ spu_release(ctx);
+
+ return ret ? ret : sizeof wbox_data;
+}
+
+static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
+{
+ struct spu_context *ctx = file->private_data;
+ unsigned int mask;
+
+ poll_wait(file, &ctx->wbox_wq, wait);
+
+ spu_acquire(ctx);
+ mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
+ spu_release(ctx);
+
+ return mask;
+}
+
+static struct file_operations spufs_wbox_fops = {
+ .open = spufs_pipe_open,
+ .write = spufs_wbox_write,
+ .poll = spufs_wbox_poll,
+ .fasync = spufs_wbox_fasync,
+};
+
+static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 wbox_stat;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+ wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
+ spu_release(ctx);
+
+ if (copy_to_user(buf, &wbox_stat, sizeof wbox_stat))
+ return -EFAULT;
+
+ return 4;
+}
+
+static struct file_operations spufs_wbox_stat_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_wbox_stat_read,
+};
+
+static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx = file->private_data;
+ u32 data;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+ data = ctx->ops->signal1_read(ctx);
+ spu_release(ctx);
+
+ if (copy_to_user(buf, &data, 4))
+ return -EFAULT;
+
+ return 4;
+}
+
+static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx;
+ u32 data;
+
+ ctx = file->private_data;
+
+ if (len < 4)
+ return -EINVAL;
+
+ if (copy_from_user(&data, buf, 4))
+ return -EFAULT;
+
+ spu_acquire(ctx);
+ ctx->ops->signal1_write(ctx, data);
+ spu_release(ctx);
+
+ return 4;
+}
+
+static struct file_operations spufs_signal1_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_signal1_read,
+ .write = spufs_signal1_write,
+};
+
+static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx;
+ u32 data;
+
+ ctx = file->private_data;
+
+ if (len < 4)
+ return -EINVAL;
+
+ spu_acquire(ctx);
+ data = ctx->ops->signal2_read(ctx);
+ spu_release(ctx);
+
+ if (copy_to_user(buf, &data, 4))
+ return -EFAULT;
+
+ return 4;
+}
+
+static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *pos)
+{
+ struct spu_context *ctx;
+ u32 data;
+
+ ctx = file->private_data;
+
+ if (len < 4)
+ return -EINVAL;
+
+ if (copy_from_user(&data, buf, 4))
+ return -EFAULT;
+
+ spu_acquire(ctx);
+ ctx->ops->signal2_write(ctx, data);
+ spu_release(ctx);
+
+ return 4;
+}
+
+static struct file_operations spufs_signal2_fops = {
+ .open = spufs_pipe_open,
+ .read = spufs_signal2_read,
+ .write = spufs_signal2_write,
+};
+
+static void spufs_signal1_type_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+
+ spu_acquire(ctx);
+ ctx->ops->signal1_type_set(ctx, val);
+ spu_release(ctx);
+}
+
+static u64 spufs_signal1_type_get(void *data)
+{
+ struct spu_context *ctx = data;
+ u64 ret;
+
+ spu_acquire(ctx);
+ ret = ctx->ops->signal1_type_get(ctx);
+ spu_release(ctx);
+
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
+ spufs_signal1_type_set, "%llu");
+
+static void spufs_signal2_type_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+
+ spu_acquire(ctx);
+ ctx->ops->signal2_type_set(ctx, val);
+ spu_release(ctx);
+}
+
+static u64 spufs_signal2_type_get(void *data)
+{
+ struct spu_context *ctx = data;
+ u64 ret;
+
+ spu_acquire(ctx);
+ ret = ctx->ops->signal2_type_get(ctx);
+ spu_release(ctx);
+
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
+ spufs_signal2_type_set, "%llu");
+
+static void spufs_npc_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ spu_acquire(ctx);
+ ctx->ops->npc_write(ctx, val);
+ spu_release(ctx);
+}
+
+static u64 spufs_npc_get(void *data)
+{
+ struct spu_context *ctx = data;
+ u64 ret;
+ spu_acquire(ctx);
+ ret = ctx->ops->npc_read(ctx);
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set, "%llx\n")
+
+static void spufs_decr_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ spu_acquire_saved(ctx);
+ lscsa->decr.slot[0] = (u32) val;
+ spu_release(ctx);
+}
+
+static u64 spufs_decr_get(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ u64 ret;
+ spu_acquire_saved(ctx);
+ ret = lscsa->decr.slot[0];
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
+ "%llx\n")
+
+static void spufs_decr_status_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ spu_acquire_saved(ctx);
+ lscsa->decr_status.slot[0] = (u32) val;
+ spu_release(ctx);
+}
+
+static u64 spufs_decr_status_get(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ u64 ret;
+ spu_acquire_saved(ctx);
+ ret = lscsa->decr_status.slot[0];
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
+ spufs_decr_status_set, "%llx\n")
+
+static void spufs_spu_tag_mask_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ spu_acquire_saved(ctx);
+ lscsa->tag_mask.slot[0] = (u32) val;
+ spu_release(ctx);
+}
+
+static u64 spufs_spu_tag_mask_get(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ u64 ret;
+ spu_acquire_saved(ctx);
+ ret = lscsa->tag_mask.slot[0];
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_spu_tag_mask_ops, spufs_spu_tag_mask_get,
+ spufs_spu_tag_mask_set, "%llx\n")
+
+static void spufs_event_mask_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ spu_acquire_saved(ctx);
+ lscsa->event_mask.slot[0] = (u32) val;
+ spu_release(ctx);
+}
+
+static u64 spufs_event_mask_get(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ u64 ret;
+ spu_acquire_saved(ctx);
+ ret = lscsa->event_mask.slot[0];
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
+ spufs_event_mask_set, "%llx\n")
+
+static void spufs_srr0_set(void *data, u64 val)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ spu_acquire_saved(ctx);
+ lscsa->srr0.slot[0] = (u32) val;
+ spu_release(ctx);
+}
+
+static u64 spufs_srr0_get(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu_lscsa *lscsa = ctx->csa.lscsa;
+ u64 ret;
+ spu_acquire_saved(ctx);
+ ret = lscsa->srr0.slot[0];
+ spu_release(ctx);
+ return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
+ "%llx\n")
+
+struct tree_descr spufs_dir_contents[] = {
+ { "mem", &spufs_mem_fops, 0666, },
+ { "regs", &spufs_regs_fops, 0666, },
+ { "mbox", &spufs_mbox_fops, 0444, },
+ { "ibox", &spufs_ibox_fops, 0444, },
+ { "wbox", &spufs_wbox_fops, 0222, },
+ { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
+ { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
+ { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
+ { "signal1", &spufs_signal1_fops, 0666, },
+ { "signal2", &spufs_signal2_fops, 0666, },
+ { "signal1_type", &spufs_signal1_type, 0666, },
+ { "signal2_type", &spufs_signal2_type, 0666, },
+ { "npc", &spufs_npc_ops, 0666, },
+ { "fpcr", &spufs_fpcr_fops, 0666, },
+ { "decr", &spufs_decr_ops, 0666, },
+ { "decr_status", &spufs_decr_status_ops, 0666, },
+ { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
+ { "event_mask", &spufs_event_mask_ops, 0666, },
+ { "srr0", &spufs_srr0_ops, 0666, },
+ {},
+};
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
new file mode 100644
index 000000000000..5445719bff79
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -0,0 +1,255 @@
+/* hw_ops.c - query/set operations on active SPU context.
+ *
+ * Copyright (C) IBM 2005
+ * Author: Mark Nutter <mnutter@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, 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/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include <asm/mmu_context.h>
+#include "spufs.h"
+
+static int spu_hw_mbox_read(struct spu_context *ctx, u32 * data)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 mbox_stat;
+ int ret = 0;
+
+ spin_lock_irq(&spu->register_lock);
+ mbox_stat = in_be32(&prob->mb_stat_R);
+ if (mbox_stat & 0x0000ff) {
+ *data = in_be32(&prob->pu_mb_R);
+ ret = 4;
+ }
+ spin_unlock_irq(&spu->register_lock);
+ return ret;
+}
+
+static u32 spu_hw_mbox_stat_read(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->mb_stat_R);
+}
+
+static unsigned int spu_hw_mbox_stat_poll(struct spu_context *ctx,
+ unsigned int events)
+{
+ struct spu *spu = ctx->spu;
+ int ret = 0;
+ u32 stat;
+
+ spin_lock_irq(&spu->register_lock);
+ stat = in_be32(&spu->problem->mb_stat_R);
+
+ /* if the requested event is there, return the poll
+ mask, otherwise enable the interrupt to get notified,
+ but first mark any pending interrupts as done so
+ we don't get woken up unnecessarily */
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ if (stat & 0xff0000)
+ ret |= POLLIN | POLLRDNORM;
+ else {
+ spu_int_stat_clear(spu, 2, 0x1);
+ spu_int_mask_or(spu, 2, 0x1);
+ }
+ }
+ if (events & (POLLOUT | POLLWRNORM)) {
+ if (stat & 0x00ff00)
+ ret = POLLOUT | POLLWRNORM;
+ else {
+ spu_int_stat_clear(spu, 2, 0x10);
+ spu_int_mask_or(spu, 2, 0x10);
+ }
+ }
+ spin_unlock_irq(&spu->register_lock);
+ return ret;
+}
+
+static int spu_hw_ibox_read(struct spu_context *ctx, u32 * data)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_problem __iomem *prob = spu->problem;
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int ret;
+
+ spin_lock_irq(&spu->register_lock);
+ if (in_be32(&prob->mb_stat_R) & 0xff0000) {
+ /* read the first available word */
+ *data = in_be64(&priv2->puint_mb_R);
+ ret = 4;
+ } else {
+ /* make sure we get woken up by the interrupt */
+ spu_int_mask_or(spu, 2, 0x1);
+ ret = 0;
+ }
+ spin_unlock_irq(&spu->register_lock);
+ return ret;
+}
+
+static int spu_hw_wbox_write(struct spu_context *ctx, u32 data)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_problem __iomem *prob = spu->problem;
+ int ret;
+
+ spin_lock_irq(&spu->register_lock);
+ if (in_be32(&prob->mb_stat_R) & 0x00ff00) {
+ /* we have space to write wbox_data to */
+ out_be32(&prob->spu_mb_W, data);
+ ret = 4;
+ } else {
+ /* make sure we get woken up by the interrupt when space
+ becomes available */
+ spu_int_mask_or(spu, 2, 0x10);
+ ret = 0;
+ }
+ spin_unlock_irq(&spu->register_lock);
+ return ret;
+}
+
+static u32 spu_hw_signal1_read(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->signal_notify1);
+}
+
+static void spu_hw_signal1_write(struct spu_context *ctx, u32 data)
+{
+ out_be32(&ctx->spu->problem->signal_notify1, data);
+}
+
+static u32 spu_hw_signal2_read(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->signal_notify1);
+}
+
+static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
+{
+ out_be32(&ctx->spu->problem->signal_notify2, data);
+}
+
+static void spu_hw_signal1_type_set(struct spu_context *ctx, u64 val)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 tmp;
+
+ spin_lock_irq(&spu->register_lock);
+ tmp = in_be64(&priv2->spu_cfg_RW);
+ if (val)
+ tmp |= 1;
+ else
+ tmp &= ~1;
+ out_be64(&priv2->spu_cfg_RW, tmp);
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static u64 spu_hw_signal1_type_get(struct spu_context *ctx)
+{
+ return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 1) != 0);
+}
+
+static void spu_hw_signal2_type_set(struct spu_context *ctx, u64 val)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 tmp;
+
+ spin_lock_irq(&spu->register_lock);
+ tmp = in_be64(&priv2->spu_cfg_RW);
+ if (val)
+ tmp |= 2;
+ else
+ tmp &= ~2;
+ out_be64(&priv2->spu_cfg_RW, tmp);
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static u64 spu_hw_signal2_type_get(struct spu_context *ctx)
+{
+ return ((in_be64(&ctx->spu->priv2->spu_cfg_RW) & 2) != 0);
+}
+
+static u32 spu_hw_npc_read(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->spu_npc_RW);
+}
+
+static void spu_hw_npc_write(struct spu_context *ctx, u32 val)
+{
+ out_be32(&ctx->spu->problem->spu_npc_RW, val);
+}
+
+static u32 spu_hw_status_read(struct spu_context *ctx)
+{
+ return in_be32(&ctx->spu->problem->spu_status_R);
+}
+
+static char *spu_hw_get_ls(struct spu_context *ctx)
+{
+ return ctx->spu->local_store;
+}
+
+static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
+{
+ eieio();
+ out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
+}
+
+static void spu_hw_runcntl_stop(struct spu_context *ctx)
+{
+ spin_lock_irq(&ctx->spu->register_lock);
+ out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
+ cpu_relax();
+ spin_unlock_irq(&ctx->spu->register_lock);
+}
+
+struct spu_context_ops spu_hw_ops = {
+ .mbox_read = spu_hw_mbox_read,
+ .mbox_stat_read = spu_hw_mbox_stat_read,
+ .mbox_stat_poll = spu_hw_mbox_stat_poll,
+ .ibox_read = spu_hw_ibox_read,
+ .wbox_write = spu_hw_wbox_write,
+ .signal1_read = spu_hw_signal1_read,
+ .signal1_write = spu_hw_signal1_write,
+ .signal2_read = spu_hw_signal2_read,
+ .signal2_write = spu_hw_signal2_write,
+ .signal1_type_set = spu_hw_signal1_type_set,
+ .signal1_type_get = spu_hw_signal1_type_get,
+ .signal2_type_set = spu_hw_signal2_type_set,
+ .signal2_type_get = spu_hw_signal2_type_get,
+ .npc_read = spu_hw_npc_read,
+ .npc_write = spu_hw_npc_write,
+ .status_read = spu_hw_status_read,
+ .get_ls = spu_hw_get_ls,
+ .runcntl_write = spu_hw_runcntl_write,
+ .runcntl_stop = spu_hw_runcntl_stop,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
new file mode 100644
index 000000000000..b3962c3a0348
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -0,0 +1,486 @@
+/*
+ * SPU file system
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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/file.h>
+#include <linux/fs.h>
+#include <linux/backing-dev.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/spu.h>
+#include <asm/uaccess.h>
+
+#include "spufs.h"
+
+static kmem_cache_t *spufs_inode_cache;
+
+static struct inode *
+spufs_alloc_inode(struct super_block *sb)
+{
+ struct spufs_inode_info *ei;
+
+ ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL);
+ if (!ei)
+ return NULL;
+ return &ei->vfs_inode;
+}
+
+static void
+spufs_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
+}
+
+static void
+spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct spufs_inode_info *ei = p;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ inode_init_once(&ei->vfs_inode);
+ }
+}
+
+static struct inode *
+spufs_new_inode(struct super_block *sb, int mode)
+{
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (!inode)
+ goto out;
+
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+out:
+ return inode;
+}
+
+static int
+spufs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if ((attr->ia_valid & ATTR_SIZE) &&
+ (attr->ia_size != inode->i_size))
+ return -EINVAL;
+ return inode_setattr(inode, attr);
+}
+
+
+static int
+spufs_new_file(struct super_block *sb, struct dentry *dentry,
+ struct file_operations *fops, int mode,
+ struct spu_context *ctx)
+{
+ static struct inode_operations spufs_file_iops = {
+ .setattr = spufs_setattr,
+ };
+ struct inode *inode;
+ int ret;
+
+ ret = -ENOSPC;
+ inode = spufs_new_inode(sb, S_IFREG | mode);
+ if (!inode)
+ goto out;
+
+ ret = 0;
+ inode->i_op = &spufs_file_iops;
+ inode->i_fop = fops;
+ inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
+ d_add(dentry, inode);
+out:
+ return ret;
+}
+
+static void
+spufs_delete_inode(struct inode *inode)
+{
+ if (SPUFS_I(inode)->i_ctx)
+ put_spu_context(SPUFS_I(inode)->i_ctx);
+ clear_inode(inode);
+}
+
+static void spufs_prune_dir(struct dentry *dir)
+{
+ struct dentry *dentry, *tmp;
+ mutex_lock(&dir->d_inode->i_mutex);
+ list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+ spin_lock(&dcache_lock);
+ spin_lock(&dentry->d_lock);
+ if (!(d_unhashed(dentry)) && dentry->d_inode) {
+ dget_locked(dentry);
+ __d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
+ simple_unlink(dir->d_inode, dentry);
+ spin_unlock(&dcache_lock);
+ dput(dentry);
+ } else {
+ spin_unlock(&dentry->d_lock);
+ spin_unlock(&dcache_lock);
+ }
+ }
+ shrink_dcache_parent(dir);
+ mutex_unlock(&dir->d_inode->i_mutex);
+}
+
+static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
+{
+ struct spu_context *ctx;
+
+ /* remove all entries */
+ mutex_lock(&root->i_mutex);
+ spufs_prune_dir(dir_dentry);
+ mutex_unlock(&root->i_mutex);
+
+ /* We have to give up the mm_struct */
+ ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
+ spu_forget(ctx);
+
+ /* XXX Do we need to hold i_mutex here ? */
+ return simple_rmdir(root, dir_dentry);
+}
+
+static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
+ int mode, struct spu_context *ctx)
+{
+ struct dentry *dentry;
+ int ret;
+
+ while (files->name && files->name[0]) {
+ ret = -ENOMEM;
+ dentry = d_alloc_name(dir, files->name);
+ if (!dentry)
+ goto out;
+ ret = spufs_new_file(dir->d_sb, dentry, files->ops,
+ files->mode & mode, ctx);
+ if (ret)
+ goto out;
+ files++;
+ }
+ return 0;
+out:
+ spufs_prune_dir(dir);
+ return ret;
+}
+
+static int spufs_dir_close(struct inode *inode, struct file *file)
+{
+ struct inode *dir;
+ struct dentry *dentry;
+ int ret;
+
+ dentry = file->f_dentry;
+ dir = dentry->d_parent->d_inode;
+
+ ret = spufs_rmdir(dir, dentry);
+ WARN_ON(ret);
+
+ return dcache_dir_close(inode, file);
+}
+
+struct inode_operations spufs_dir_inode_operations = {
+ .lookup = simple_lookup,
+};
+
+struct file_operations spufs_context_fops = {
+ .open = dcache_dir_open,
+ .release = spufs_dir_close,
+ .llseek = dcache_dir_lseek,
+ .read = generic_read_dir,
+ .readdir = dcache_readdir,
+ .fsync = simple_sync_file,
+};
+
+static int
+spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int ret;
+ struct inode *inode;
+ struct spu_context *ctx;
+
+ ret = -ENOSPC;
+ inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
+ if (!inode)
+ goto out;
+
+ if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ inode->i_mode &= S_ISGID;
+ }
+ ctx = alloc_spu_context(inode->i_mapping);
+ SPUFS_I(inode)->i_ctx = ctx;
+ if (!ctx)
+ goto out_iput;
+
+ inode->i_op = &spufs_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
+ if (ret)
+ goto out_free_ctx;
+
+ d_instantiate(dentry, inode);
+ dget(dentry);
+ dir->i_nlink++;
+ dentry->d_inode->i_nlink++;
+ goto out;
+
+out_free_ctx:
+ put_spu_context(ctx);
+out_iput:
+ iput(inode);
+out:
+ return ret;
+}
+
+static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
+{
+ int ret;
+ struct file *filp;
+
+ ret = get_unused_fd();
+ if (ret < 0) {
+ dput(dentry);
+ mntput(mnt);
+ goto out;
+ }
+
+ filp = dentry_open(dentry, mnt, O_RDONLY);
+ if (IS_ERR(filp)) {
+ put_unused_fd(ret);
+ ret = PTR_ERR(filp);
+ goto out;
+ }
+
+ filp->f_op = &spufs_context_fops;
+ fd_install(ret, filp);
+out:
+ return ret;
+}
+
+static struct file_system_type spufs_type;
+
+long spufs_create_thread(struct nameidata *nd,
+ unsigned int flags, mode_t mode)
+{
+ struct dentry *dentry;
+ int ret;
+
+ /* need to be at the root of spufs */
+ ret = -EINVAL;
+ if (nd->dentry->d_sb->s_type != &spufs_type ||
+ nd->dentry != nd->dentry->d_sb->s_root)
+ goto out;
+
+ dentry = lookup_create(nd, 1);
+ ret = PTR_ERR(dentry);
+ if (IS_ERR(dentry))
+ goto out_dir;
+
+ ret = -EEXIST;
+ if (dentry->d_inode)
+ goto out_dput;
+
+ mode &= ~current->fs->umask;
+ ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO);
+ if (ret)
+ goto out_dput;
+
+ /*
+ * get references for dget and mntget, will be released
+ * in error path of *_open().
+ */
+ ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
+ if (ret < 0)
+ spufs_rmdir(nd->dentry->d_inode, dentry);
+
+out_dput:
+ dput(dentry);
+out_dir:
+ mutex_unlock(&nd->dentry->d_inode->i_mutex);
+out:
+ return ret;
+}
+
+/* File system initialization */
+enum {
+ Opt_uid, Opt_gid, Opt_err,
+};
+
+static match_table_t spufs_tokens = {
+ { Opt_uid, "uid=%d" },
+ { Opt_gid, "gid=%d" },
+ { Opt_err, NULL },
+};
+
+static int
+spufs_parse_options(char *options, struct inode *root)
+{
+ char *p;
+ substring_t args[MAX_OPT_ARGS];
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token, option;
+
+ if (!*p)
+ continue;
+
+ token = match_token(p, spufs_tokens, args);
+ switch (token) {
+ case Opt_uid:
+ if (match_int(&args[0], &option))
+ return 0;
+ root->i_uid = option;
+ break;
+ case Opt_gid:
+ if (match_int(&args[0], &option))
+ return 0;
+ root->i_gid = option;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+spufs_create_root(struct super_block *sb, void *data)
+{
+ struct inode *inode;
+ int ret;
+
+ ret = -ENOMEM;
+ inode = spufs_new_inode(sb, S_IFDIR | 0775);
+ if (!inode)
+ goto out;
+
+ inode->i_op = &spufs_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+ SPUFS_I(inode)->i_ctx = NULL;
+
+ ret = -EINVAL;
+ if (!spufs_parse_options(data, inode))
+ goto out_iput;
+
+ ret = -ENOMEM;
+ sb->s_root = d_alloc_root(inode);
+ if (!sb->s_root)
+ goto out_iput;
+
+ return 0;
+out_iput:
+ iput(inode);
+out:
+ return ret;
+}
+
+static int
+spufs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ static struct super_operations s_ops = {
+ .alloc_inode = spufs_alloc_inode,
+ .destroy_inode = spufs_destroy_inode,
+ .statfs = simple_statfs,
+ .delete_inode = spufs_delete_inode,
+ .drop_inode = generic_delete_inode,
+ };
+
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = SPUFS_MAGIC;
+ sb->s_op = &s_ops;
+
+ return spufs_create_root(sb, data);
+}
+
+static struct super_block *
+spufs_get_sb(struct file_system_type *fstype, int flags,
+ const char *name, void *data)
+{
+ return get_sb_single(fstype, flags, data, spufs_fill_super);
+}
+
+static struct file_system_type spufs_type = {
+ .owner = THIS_MODULE,
+ .name = "spufs",
+ .get_sb = spufs_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+static int spufs_init(void)
+{
+ int ret;
+ ret = -ENOMEM;
+ spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
+ sizeof(struct spufs_inode_info), 0,
+ SLAB_HWCACHE_ALIGN, spufs_init_once, NULL);
+
+ if (!spufs_inode_cache)
+ goto out;
+ if (spu_sched_init() != 0) {
+ kmem_cache_destroy(spufs_inode_cache);
+ goto out;
+ }
+ ret = register_filesystem(&spufs_type);
+ if (ret)
+ goto out_cache;
+ ret = register_spu_syscalls(&spufs_calls);
+ if (ret)
+ goto out_fs;
+ return 0;
+out_fs:
+ unregister_filesystem(&spufs_type);
+out_cache:
+ kmem_cache_destroy(spufs_inode_cache);
+out:
+ return ret;
+}
+module_init(spufs_init);
+
+static void spufs_exit(void)
+{
+ spu_sched_exit();
+ unregister_spu_syscalls(&spufs_calls);
+ unregister_filesystem(&spufs_type);
+ kmem_cache_destroy(spufs_inode_cache);
+}
+module_exit(spufs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
+
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c
new file mode 100644
index 000000000000..18ea8866c61a
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -0,0 +1,131 @@
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+
+#include <asm/spu.h>
+
+#include "spufs.h"
+
+/* interrupt-level stop callback function. */
+void spufs_stop_callback(struct spu *spu)
+{
+ struct spu_context *ctx = spu->ctx;
+
+ wake_up_all(&ctx->stop_wq);
+}
+
+static inline int spu_stopped(struct spu_context *ctx, u32 * stat)
+{
+ struct spu *spu;
+ u64 pte_fault;
+
+ *stat = ctx->ops->status_read(ctx);
+ if (ctx->state != SPU_STATE_RUNNABLE)
+ return 1;
+ spu = ctx->spu;
+ pte_fault = spu->dsisr &
+ (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED);
+ return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0;
+}
+
+static inline int spu_run_init(struct spu_context *ctx, u32 * npc,
+ u32 * status)
+{
+ int ret;
+
+ if ((ret = spu_acquire_runnable(ctx)) != 0)
+ return ret;
+ ctx->ops->npc_write(ctx, *npc);
+ ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
+ return 0;
+}
+
+static inline int spu_run_fini(struct spu_context *ctx, u32 * npc,
+ u32 * status)
+{
+ int ret = 0;
+
+ *status = ctx->ops->status_read(ctx);
+ *npc = ctx->ops->npc_read(ctx);
+ spu_release(ctx);
+
+ if (signal_pending(current))
+ ret = -ERESTARTSYS;
+ if (unlikely(current->ptrace & PT_PTRACED)) {
+ if ((*status & SPU_STATUS_STOPPED_BY_STOP)
+ && (*status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) {
+ force_sig(SIGTRAP, current);
+ ret = -ERESTARTSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc,
+ u32 *status)
+{
+ int ret;
+
+ if ((ret = spu_run_fini(ctx, npc, status)) != 0)
+ return ret;
+ if (*status & (SPU_STATUS_STOPPED_BY_STOP |
+ SPU_STATUS_STOPPED_BY_HALT)) {
+ return *status;
+ }
+ if ((ret = spu_run_init(ctx, npc, status)) != 0)
+ return ret;
+ return 0;
+}
+
+static inline int spu_process_events(struct spu_context *ctx)
+{
+ struct spu *spu = ctx->spu;
+ u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED;
+ int ret = 0;
+
+ if (spu->dsisr & pte_fault)
+ ret = spu_irq_class_1_bottom(spu);
+ if (spu->class_0_pending)
+ ret = spu_irq_class_0_bottom(spu);
+ if (!ret && signal_pending(current))
+ ret = -ERESTARTSYS;
+ return ret;
+}
+
+long spufs_run_spu(struct file *file, struct spu_context *ctx,
+ u32 * npc, u32 * status)
+{
+ int ret;
+
+ if (down_interruptible(&ctx->run_sema))
+ return -ERESTARTSYS;
+
+ ret = spu_run_init(ctx, npc, status);
+ if (ret)
+ goto out;
+
+ do {
+ ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status));
+ if (unlikely(ret))
+ break;
+ if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) {
+ ret = spu_reacquire_runnable(ctx, npc, status);
+ if (ret)
+ goto out;
+ continue;
+ }
+ ret = spu_process_events(ctx);
+
+ } while (!ret && !(*status & (SPU_STATUS_STOPPED_BY_STOP |
+ SPU_STATUS_STOPPED_BY_HALT)));
+
+ ctx->ops->runcntl_stop(ctx);
+ ret = spu_run_fini(ctx, npc, status);
+ if (!ret)
+ ret = *status;
+ spu_yield(ctx);
+
+out:
+ up(&ctx->run_sema);
+ return ret;
+}
+
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
new file mode 100644
index 000000000000..963182fbd1aa
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -0,0 +1,461 @@
+/* sched.c - SPU scheduler.
+ *
+ * Copyright (C) IBM 2005
+ * Author: Mark Nutter <mnutter@us.ibm.com>
+ *
+ * SPU scheduler, based on Linux thread priority. For now use
+ * a simple "cooperative" yield model with no preemption. SPU
+ * scheduling will eventually be preemptive: When a thread with
+ * a higher static priority gets ready to run, then an active SPU
+ * context will be preempted and returned to the waitq.
+ *
+ * This program is free software; you can redistribute 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.
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/completion.h>
+#include <linux/vmalloc.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include "spufs.h"
+
+#define SPU_MIN_TIMESLICE (100 * HZ / 1000)
+
+#define SPU_BITMAP_SIZE (((MAX_PRIO+BITS_PER_LONG)/BITS_PER_LONG)+1)
+struct spu_prio_array {
+ atomic_t nr_blocked;
+ unsigned long bitmap[SPU_BITMAP_SIZE];
+ wait_queue_head_t waitq[MAX_PRIO];
+};
+
+/* spu_runqueue - This is the main runqueue data structure for SPUs. */
+struct spu_runqueue {
+ struct semaphore sem;
+ unsigned long nr_active;
+ unsigned long nr_idle;
+ unsigned long nr_switches;
+ struct list_head active_list;
+ struct list_head idle_list;
+ struct spu_prio_array prio;
+};
+
+static struct spu_runqueue *spu_runqueues = NULL;
+
+static inline struct spu_runqueue *spu_rq(void)
+{
+ /* Future: make this a per-NODE array,
+ * and use cpu_to_node(smp_processor_id())
+ */
+ return spu_runqueues;
+}
+
+static inline struct spu *del_idle(struct spu_runqueue *rq)
+{
+ struct spu *spu;
+
+ BUG_ON(rq->nr_idle <= 0);
+ BUG_ON(list_empty(&rq->idle_list));
+ /* Future: Move SPU out of low-power SRI state. */
+ spu = list_entry(rq->idle_list.next, struct spu, sched_list);
+ list_del_init(&spu->sched_list);
+ rq->nr_idle--;
+ return spu;
+}
+
+static inline void del_active(struct spu_runqueue *rq, struct spu *spu)
+{
+ BUG_ON(rq->nr_active <= 0);
+ BUG_ON(list_empty(&rq->active_list));
+ list_del_init(&spu->sched_list);
+ rq->nr_active--;
+}
+
+static inline void add_idle(struct spu_runqueue *rq, struct spu *spu)
+{
+ /* Future: Put SPU into low-power SRI state. */
+ list_add_tail(&spu->sched_list, &rq->idle_list);
+ rq->nr_idle++;
+}
+
+static inline void add_active(struct spu_runqueue *rq, struct spu *spu)
+{
+ rq->nr_active++;
+ rq->nr_switches++;
+ list_add_tail(&spu->sched_list, &rq->active_list);
+}
+
+static void prio_wakeup(struct spu_runqueue *rq)
+{
+ if (atomic_read(&rq->prio.nr_blocked) && rq->nr_idle) {
+ int best = sched_find_first_bit(rq->prio.bitmap);
+ if (best < MAX_PRIO) {
+ wait_queue_head_t *wq = &rq->prio.waitq[best];
+ wake_up_interruptible_nr(wq, 1);
+ }
+ }
+}
+
+static void prio_wait(struct spu_runqueue *rq, struct spu_context *ctx,
+ u64 flags)
+{
+ int prio = current->prio;
+ wait_queue_head_t *wq = &rq->prio.waitq[prio];
+ DEFINE_WAIT(wait);
+
+ __set_bit(prio, rq->prio.bitmap);
+ atomic_inc(&rq->prio.nr_blocked);
+ prepare_to_wait_exclusive(wq, &wait, TASK_INTERRUPTIBLE);
+ if (!signal_pending(current)) {
+ up(&rq->sem);
+ up_write(&ctx->state_sema);
+ pr_debug("%s: pid=%d prio=%d\n", __FUNCTION__,
+ current->pid, current->prio);
+ schedule();
+ down_write(&ctx->state_sema);
+ down(&rq->sem);
+ }
+ finish_wait(wq, &wait);
+ atomic_dec(&rq->prio.nr_blocked);
+ if (!waitqueue_active(wq))
+ __clear_bit(prio, rq->prio.bitmap);
+}
+
+static inline int is_best_prio(struct spu_runqueue *rq)
+{
+ int best_prio;
+
+ best_prio = sched_find_first_bit(rq->prio.bitmap);
+ return (current->prio < best_prio) ? 1 : 0;
+}
+
+static inline void mm_needs_global_tlbie(struct mm_struct *mm)
+{
+ /* Global TLBIE broadcast required with SPEs. */
+#if (NR_CPUS > 1)
+ __cpus_setall(&mm->cpu_vm_mask, NR_CPUS);
+#else
+ __cpus_setall(&mm->cpu_vm_mask, NR_CPUS+1); /* is this ok? */
+#endif
+}
+
+static inline void bind_context(struct spu *spu, struct spu_context *ctx)
+{
+ pr_debug("%s: pid=%d SPU=%d\n", __FUNCTION__, current->pid,
+ spu->number);
+ spu->ctx = ctx;
+ spu->flags = 0;
+ ctx->flags = 0;
+ ctx->spu = spu;
+ ctx->ops = &spu_hw_ops;
+ spu->pid = current->pid;
+ spu->prio = current->prio;
+ spu->mm = ctx->owner;
+ mm_needs_global_tlbie(spu->mm);
+ spu->ibox_callback = spufs_ibox_callback;
+ spu->wbox_callback = spufs_wbox_callback;
+ spu->stop_callback = spufs_stop_callback;
+ mb();
+ spu_unmap_mappings(ctx);
+ spu_restore(&ctx->csa, spu);
+ spu->timestamp = jiffies;
+}
+
+static inline void unbind_context(struct spu *spu, struct spu_context *ctx)
+{
+ pr_debug("%s: unbind pid=%d SPU=%d\n", __FUNCTION__,
+ spu->pid, spu->number);
+ spu_unmap_mappings(ctx);
+ spu_save(&ctx->csa, spu);
+ spu->timestamp = jiffies;
+ ctx->state = SPU_STATE_SAVED;
+ spu->ibox_callback = NULL;
+ spu->wbox_callback = NULL;
+ spu->stop_callback = NULL;
+ spu->mm = NULL;
+ spu->pid = 0;
+ spu->prio = MAX_PRIO;
+ ctx->ops = &spu_backing_ops;
+ ctx->spu = NULL;
+ ctx->flags = 0;
+ spu->flags = 0;
+ spu->ctx = NULL;
+}
+
+static void spu_reaper(void *data)
+{
+ struct spu_context *ctx = data;
+ struct spu *spu;
+
+ down_write(&ctx->state_sema);
+ spu = ctx->spu;
+ if (spu && test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
+ if (atomic_read(&spu->rq->prio.nr_blocked)) {
+ pr_debug("%s: spu=%d\n", __func__, spu->number);
+ ctx->ops->runcntl_stop(ctx);
+ spu_deactivate(ctx);
+ wake_up_all(&ctx->stop_wq);
+ } else {
+ clear_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
+ }
+ }
+ up_write(&ctx->state_sema);
+ put_spu_context(ctx);
+}
+
+static void schedule_spu_reaper(struct spu_runqueue *rq, struct spu *spu)
+{
+ struct spu_context *ctx = get_spu_context(spu->ctx);
+ unsigned long now = jiffies;
+ unsigned long expire = spu->timestamp + SPU_MIN_TIMESLICE;
+
+ set_bit(SPU_CONTEXT_PREEMPT, &ctx->flags);
+ INIT_WORK(&ctx->reap_work, spu_reaper, ctx);
+ if (time_after(now, expire))
+ schedule_work(&ctx->reap_work);
+ else
+ schedule_delayed_work(&ctx->reap_work, expire - now);
+}
+
+static void check_preempt_active(struct spu_runqueue *rq)
+{
+ struct list_head *p;
+ struct spu *worst = NULL;
+
+ list_for_each(p, &rq->active_list) {
+ struct spu *spu = list_entry(p, struct spu, sched_list);
+ struct spu_context *ctx = spu->ctx;
+ if (!test_bit(SPU_CONTEXT_PREEMPT, &ctx->flags)) {
+ if (!worst || (spu->prio > worst->prio)) {
+ worst = spu;
+ }
+ }
+ }
+ if (worst && (current->prio < worst->prio))
+ schedule_spu_reaper(rq, worst);
+}
+
+static struct spu *get_idle_spu(struct spu_context *ctx, u64 flags)
+{
+ struct spu_runqueue *rq;
+ struct spu *spu = NULL;
+
+ rq = spu_rq();
+ down(&rq->sem);
+ for (;;) {
+ if (rq->nr_idle > 0) {
+ if (is_best_prio(rq)) {
+ /* Fall through. */
+ spu = del_idle(rq);
+ break;
+ } else {
+ prio_wakeup(rq);
+ up(&rq->sem);
+ yield();
+ if (signal_pending(current)) {
+ return NULL;
+ }
+ rq = spu_rq();
+ down(&rq->sem);
+ continue;
+ }
+ } else {
+ check_preempt_active(rq);
+ prio_wait(rq, ctx, flags);
+ if (signal_pending(current)) {
+ prio_wakeup(rq);
+ spu = NULL;
+ break;
+ }
+ continue;
+ }
+ }
+ up(&rq->sem);
+ return spu;
+}
+
+static void put_idle_spu(struct spu *spu)
+{
+ struct spu_runqueue *rq = spu->rq;
+
+ down(&rq->sem);
+ add_idle(rq, spu);
+ prio_wakeup(rq);
+ up(&rq->sem);
+}
+
+static int get_active_spu(struct spu *spu)
+{
+ struct spu_runqueue *rq = spu->rq;
+ struct list_head *p;
+ struct spu *tmp;
+ int rc = 0;
+
+ down(&rq->sem);
+ list_for_each(p, &rq->active_list) {
+ tmp = list_entry(p, struct spu, sched_list);
+ if (tmp == spu) {
+ del_active(rq, spu);
+ rc = 1;
+ break;
+ }
+ }
+ up(&rq->sem);
+ return rc;
+}
+
+static void put_active_spu(struct spu *spu)
+{
+ struct spu_runqueue *rq = spu->rq;
+
+ down(&rq->sem);
+ add_active(rq, spu);
+ up(&rq->sem);
+}
+
+/* Lock order:
+ * spu_activate() & spu_deactivate() require the
+ * caller to have down_write(&ctx->state_sema).
+ *
+ * The rq->sem is breifly held (inside or outside a
+ * given ctx lock) for list management, but is never
+ * held during save/restore.
+ */
+
+int spu_activate(struct spu_context *ctx, u64 flags)
+{
+ struct spu *spu;
+
+ if (ctx->spu)
+ return 0;
+ spu = get_idle_spu(ctx, flags);
+ if (!spu)
+ return (signal_pending(current)) ? -ERESTARTSYS : -EAGAIN;
+ bind_context(spu, ctx);
+ /*
+ * We're likely to wait for interrupts on the same
+ * CPU that we are now on, so send them here.
+ */
+ spu_irq_setaffinity(spu, raw_smp_processor_id());
+ put_active_spu(spu);
+ return 0;
+}
+
+void spu_deactivate(struct spu_context *ctx)
+{
+ struct spu *spu;
+ int needs_idle;
+
+ spu = ctx->spu;
+ if (!spu)
+ return;
+ needs_idle = get_active_spu(spu);
+ unbind_context(spu, ctx);
+ if (needs_idle)
+ put_idle_spu(spu);
+}
+
+void spu_yield(struct spu_context *ctx)
+{
+ struct spu *spu;
+ int need_yield = 0;
+
+ down_write(&ctx->state_sema);
+ spu = ctx->spu;
+ if (spu && (sched_find_first_bit(spu->rq->prio.bitmap) < MAX_PRIO)) {
+ pr_debug("%s: yielding SPU %d\n", __FUNCTION__, spu->number);
+ spu_deactivate(ctx);
+ ctx->state = SPU_STATE_SAVED;
+ need_yield = 1;
+ } else if (spu) {
+ spu->prio = MAX_PRIO;
+ }
+ up_write(&ctx->state_sema);
+ if (unlikely(need_yield))
+ yield();
+}
+
+int __init spu_sched_init(void)
+{
+ struct spu_runqueue *rq;
+ struct spu *spu;
+ int i;
+
+ rq = spu_runqueues = kmalloc(sizeof(struct spu_runqueue), GFP_KERNEL);
+ if (!rq) {
+ printk(KERN_WARNING "%s: Unable to allocate runqueues.\n",
+ __FUNCTION__);
+ return 1;
+ }
+ memset(rq, 0, sizeof(struct spu_runqueue));
+ init_MUTEX(&rq->sem);
+ INIT_LIST_HEAD(&rq->active_list);
+ INIT_LIST_HEAD(&rq->idle_list);
+ rq->nr_active = 0;
+ rq->nr_idle = 0;
+ rq->nr_switches = 0;
+ atomic_set(&rq->prio.nr_blocked, 0);
+ for (i = 0; i < MAX_PRIO; i++) {
+ init_waitqueue_head(&rq->prio.waitq[i]);
+ __clear_bit(i, rq->prio.bitmap);
+ }
+ __set_bit(MAX_PRIO, rq->prio.bitmap);
+ for (;;) {
+ spu = spu_alloc();
+ if (!spu)
+ break;
+ pr_debug("%s: adding SPU[%d]\n", __FUNCTION__, spu->number);
+ add_idle(rq, spu);
+ spu->rq = rq;
+ spu->timestamp = jiffies;
+ }
+ if (!rq->nr_idle) {
+ printk(KERN_WARNING "%s: No available SPUs.\n", __FUNCTION__);
+ kfree(rq);
+ return 1;
+ }
+ return 0;
+}
+
+void __exit spu_sched_exit(void)
+{
+ struct spu_runqueue *rq = spu_rq();
+ struct spu *spu;
+
+ if (!rq) {
+ printk(KERN_WARNING "%s: no runqueues!\n", __FUNCTION__);
+ return;
+ }
+ while (rq->nr_idle > 0) {
+ spu = del_idle(rq);
+ if (!spu)
+ break;
+ spu_free(spu);
+ }
+ kfree(rq);
+}
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore.c b/arch/powerpc/platforms/cell/spufs/spu_restore.c
new file mode 100644
index 000000000000..0bf723dcd677
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore.c
@@ -0,0 +1,336 @@
+/*
+ * spu_restore.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * SPU-side context restore sequence outlined in
+ * Synergistic Processor Element Book IV
+ *
+ * Author: Mark Nutter <mnutter@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, 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 LS_SIZE
+#define LS_SIZE 0x40000 /* 256K (in bytes) */
+#endif
+
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+#include <spu_intrinsics.h>
+#include <asm/spu_csa.h>
+#include "spu_utils.h"
+
+#define BR_INSTR 0x327fff80 /* br -4 */
+#define NOP_INSTR 0x40200000 /* nop */
+#define HEQ_INSTR 0x7b000000 /* heq $0, $0 */
+#define STOP_INSTR 0x00000000 /* stop 0x0 */
+#define ILLEGAL_INSTR 0x00800000 /* illegal instr */
+#define RESTORE_COMPLETE 0x00003ffc /* stop 0x3ffc */
+
+static inline void fetch_regs_from_mem(addr64 lscsa_ea)
+{
+ unsigned int ls = (unsigned int)&regs_spill[0];
+ unsigned int size = sizeof(regs_spill);
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0x40; /* GET */
+
+ spu_writech(MFC_LSA, ls);
+ spu_writech(MFC_EAH, lscsa_ea.ui[0]);
+ spu_writech(MFC_EAL, lscsa_ea.ui[1]);
+ spu_writech(MFC_Size, size);
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void restore_upper_240kb(addr64 lscsa_ea)
+{
+ unsigned int ls = 16384;
+ unsigned int list = (unsigned int)&dma_list[0];
+ unsigned int size = sizeof(dma_list);
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0x44; /* GETL */
+
+ /* Restore, Step 4:
+ * Enqueue the GETL command (tag 0) to the MFC SPU command
+ * queue to transfer the upper 240 kb of LS from CSA.
+ */
+ spu_writech(MFC_LSA, ls);
+ spu_writech(MFC_EAH, lscsa_ea.ui[0]);
+ spu_writech(MFC_EAL, list);
+ spu_writech(MFC_Size, size);
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void restore_decr(void)
+{
+ unsigned int offset;
+ unsigned int decr_running;
+ unsigned int decr;
+
+ /* Restore, Step 6:
+ * If the LSCSA "decrementer running" flag is set
+ * then write the SPU_WrDec channel with the
+ * decrementer value from LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(decr_status);
+ decr_running = regs_spill[offset].slot[0];
+ if (decr_running) {
+ offset = LSCSA_QW_OFFSET(decr);
+ decr = regs_spill[offset].slot[0];
+ spu_writech(SPU_WrDec, decr);
+ }
+}
+
+static inline void write_ppu_mb(void)
+{
+ unsigned int offset;
+ unsigned int data;
+
+ /* Restore, Step 11:
+ * Write the MFC_WrOut_MB channel with the PPU_MB
+ * data from LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(ppu_mb);
+ data = regs_spill[offset].slot[0];
+ spu_writech(SPU_WrOutMbox, data);
+}
+
+static inline void write_ppuint_mb(void)
+{
+ unsigned int offset;
+ unsigned int data;
+
+ /* Restore, Step 12:
+ * Write the MFC_WrInt_MB channel with the PPUINT_MB
+ * data from LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(ppuint_mb);
+ data = regs_spill[offset].slot[0];
+ spu_writech(SPU_WrOutIntrMbox, data);
+}
+
+static inline void restore_fpcr(void)
+{
+ unsigned int offset;
+ vector unsigned int fpcr;
+
+ /* Restore, Step 13:
+ * Restore the floating-point status and control
+ * register from the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(fpcr);
+ fpcr = regs_spill[offset].v;
+ spu_mtfpscr(fpcr);
+}
+
+static inline void restore_srr0(void)
+{
+ unsigned int offset;
+ unsigned int srr0;
+
+ /* Restore, Step 14:
+ * Restore the SPU SRR0 data from the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(srr0);
+ srr0 = regs_spill[offset].slot[0];
+ spu_writech(SPU_WrSRR0, srr0);
+}
+
+static inline void restore_event_mask(void)
+{
+ unsigned int offset;
+ unsigned int event_mask;
+
+ /* Restore, Step 15:
+ * Restore the SPU_RdEventMsk data from the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(event_mask);
+ event_mask = regs_spill[offset].slot[0];
+ spu_writech(SPU_WrEventMask, event_mask);
+}
+
+static inline void restore_tag_mask(void)
+{
+ unsigned int offset;
+ unsigned int tag_mask;
+
+ /* Restore, Step 16:
+ * Restore the SPU_RdTagMsk data from the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(tag_mask);
+ tag_mask = regs_spill[offset].slot[0];
+ spu_writech(MFC_WrTagMask, tag_mask);
+}
+
+static inline void restore_complete(void)
+{
+ extern void exit_fini(void);
+ unsigned int *exit_instrs = (unsigned int *)exit_fini;
+ unsigned int offset;
+ unsigned int stopped_status;
+ unsigned int stopped_code;
+
+ /* Restore, Step 18:
+ * Issue a stop-and-signal instruction with
+ * "good context restore" signal value.
+ *
+ * Restore, Step 19:
+ * There may be additional instructions placed
+ * here by the PPE Sequence for SPU Context
+ * Restore in order to restore the correct
+ * "stopped state".
+ *
+ * This step is handled here by analyzing the
+ * LSCSA.stopped_status and then modifying the
+ * exit() function to behave appropriately.
+ */
+
+ offset = LSCSA_QW_OFFSET(stopped_status);
+ stopped_status = regs_spill[offset].slot[0];
+ stopped_code = regs_spill[offset].slot[1];
+
+ switch (stopped_status) {
+ case SPU_STOPPED_STATUS_P_I:
+ /* SPU_Status[P,I]=1. Add illegal instruction
+ * followed by stop-and-signal instruction after
+ * end of restore code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = ILLEGAL_INSTR;
+ exit_instrs[2] = STOP_INSTR | stopped_code;
+ break;
+ case SPU_STOPPED_STATUS_P_H:
+ /* SPU_Status[P,H]=1. Add 'heq $0, $0' followed
+ * by stop-and-signal instruction after end of
+ * restore code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = HEQ_INSTR;
+ exit_instrs[2] = STOP_INSTR | stopped_code;
+ break;
+ case SPU_STOPPED_STATUS_S_P:
+ /* SPU_Status[S,P]=1. Add nop instruction
+ * followed by 'br -4' after end of restore
+ * code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = STOP_INSTR | stopped_code;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ case SPU_STOPPED_STATUS_S_I:
+ /* SPU_Status[S,I]=1. Add illegal instruction
+ * followed by 'br -4' after end of restore code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = ILLEGAL_INSTR;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ case SPU_STOPPED_STATUS_I:
+ /* SPU_Status[I]=1. Add illegal instruction followed
+ * by infinite loop after end of restore sequence.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = ILLEGAL_INSTR;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ case SPU_STOPPED_STATUS_S:
+ /* SPU_Status[S]=1. Add two 'nop' instructions. */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = NOP_INSTR;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ case SPU_STOPPED_STATUS_H:
+ /* SPU_Status[H]=1. Add 'heq $0, $0' instruction
+ * after end of restore code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = HEQ_INSTR;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ case SPU_STOPPED_STATUS_P:
+ /* SPU_Status[P]=1. Add stop-and-signal instruction
+ * after end of restore code.
+ */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = STOP_INSTR | stopped_code;
+ break;
+ case SPU_STOPPED_STATUS_R:
+ /* SPU_Status[I,S,H,P,R]=0. Add infinite loop. */
+ exit_instrs[0] = RESTORE_COMPLETE;
+ exit_instrs[1] = NOP_INSTR;
+ exit_instrs[2] = NOP_INSTR;
+ exit_instrs[3] = BR_INSTR;
+ break;
+ default:
+ /* SPU_Status[R]=1. No additonal instructions. */
+ break;
+ }
+ spu_sync();
+}
+
+/**
+ * main - entry point for SPU-side context restore.
+ *
+ * This code deviates from the documented sequence in the
+ * following aspects:
+ *
+ * 1. The EA for LSCSA is passed from PPE in the
+ * signal notification channels.
+ * 2. The register spill area is pulled by SPU
+ * into LS, rather than pushed by PPE.
+ * 3. All 128 registers are restored by exit().
+ * 4. The exit() function is modified at run
+ * time in order to properly restore the
+ * SPU_Status register.
+ */
+int main()
+{
+ addr64 lscsa_ea;
+
+ lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);
+ lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);
+ fetch_regs_from_mem(lscsa_ea);
+
+ set_event_mask(); /* Step 1. */
+ set_tag_mask(); /* Step 2. */
+ build_dma_list(lscsa_ea); /* Step 3. */
+ restore_upper_240kb(lscsa_ea); /* Step 4. */
+ /* Step 5: done by 'exit'. */
+ restore_decr(); /* Step 6. */
+ enqueue_putllc(lscsa_ea); /* Step 7. */
+ set_tag_update(); /* Step 8. */
+ read_tag_status(); /* Step 9. */
+ read_llar_status(); /* Step 10. */
+ write_ppu_mb(); /* Step 11. */
+ write_ppuint_mb(); /* Step 12. */
+ restore_fpcr(); /* Step 13. */
+ restore_srr0(); /* Step 14. */
+ restore_event_mask(); /* Step 15. */
+ restore_tag_mask(); /* Step 16. */
+ /* Step 17. done by 'exit'. */
+ restore_complete(); /* Step 18. */
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_crt0.S b/arch/powerpc/platforms/cell/spufs/spu_restore_crt0.S
new file mode 100644
index 000000000000..2905949debe1
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore_crt0.S
@@ -0,0 +1,116 @@
+/*
+ * crt0_r.S: Entry function for SPU-side context restore.
+ *
+ * Copyright (C) 2005 IBM
+ *
+ * Entry and exit function for SPU-side of the context restore
+ * sequence. Sets up an initial stack frame, then branches to
+ * 'main'. On return, restores all 128 registers from the LSCSA
+ * and exits.
+ *
+ *
+ * This program is free software; you can redistribute 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 <asm/spu_csa.h>
+
+.data
+.align 7
+.globl regs_spill
+regs_spill:
+.space SIZEOF_SPU_SPILL_REGS, 0x0
+
+.text
+.global _start
+_start:
+ /* Initialize the stack pointer to point to 16368
+ * (16kb-16). The back chain pointer is initialized
+ * to NULL.
+ */
+ il $0, 0
+ il $SP, 16368
+ stqd $0, 0($SP)
+
+ /* Allocate a minimum stack frame for the called main.
+ * This is needed so that main has a place to save the
+ * link register when it calls another function.
+ */
+ stqd $SP, -160($SP)
+ ai $SP, $SP, -160
+
+ /* Call the program's main function. */
+ brsl $0, main
+
+.global exit
+.global _exit
+exit:
+_exit:
+ /* SPU Context Restore, Step 5: Restore the remaining 112 GPRs. */
+ ila $3, regs_spill + 256
+restore_regs:
+ lqr $4, restore_reg_insts
+restore_reg_loop:
+ ai $4, $4, 4
+ .balignl 16, 0x40200000
+restore_reg_insts: /* must be quad-word aligned. */
+ lqd $16, 0($3)
+ lqd $17, 16($3)
+ lqd $18, 32($3)
+ lqd $19, 48($3)
+ andi $5, $4, 0x7F
+ stqr $4, restore_reg_insts
+ ai $3, $3, 64
+ brnz $5, restore_reg_loop
+
+ /* SPU Context Restore Step 17: Restore the first 16 GPRs. */
+ lqa $0, regs_spill + 0
+ lqa $1, regs_spill + 16
+ lqa $2, regs_spill + 32
+ lqa $3, regs_spill + 48
+ lqa $4, regs_spill + 64
+ lqa $5, regs_spill + 80
+ lqa $6, regs_spill + 96
+ lqa $7, regs_spill + 112
+ lqa $8, regs_spill + 128
+ lqa $9, regs_spill + 144
+ lqa $10, regs_spill + 160
+ lqa $11, regs_spill + 176
+ lqa $12, regs_spill + 192
+ lqa $13, regs_spill + 208
+ lqa $14, regs_spill + 224
+ lqa $15, regs_spill + 240
+
+ /* Under normal circumstances, the 'exit' function
+ * terminates with 'stop SPU_RESTORE_COMPLETE',
+ * indicating that the SPU-side restore code has
+ * completed.
+ *
+ * However it is possible that instructions immediately
+ * following the 'stop 0x3ffc' have been modified at run
+ * time so as to recreate the exact SPU_Status settings
+ * from the application, e.g. illegal instruciton, halt,
+ * etc.
+ */
+.global exit_fini
+.global _exit_fini
+exit_fini:
+_exit_fini:
+ stop SPU_RESTORE_COMPLETE
+ stop 0
+ stop 0
+ stop 0
+
+ /* Pad the size of this crt0.o to be multiple of 16 bytes. */
+.balignl 16, 0x0
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
new file mode 100644
index 000000000000..1b2355ff7036
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
@@ -0,0 +1,231 @@
+/*
+ * spu_restore_dump.h: Copyright (C) 2005 IBM.
+ * Hex-dump auto generated from spu_restore.c.
+ * Do not edit!
+ */
+static unsigned int spu_restore_code[] __page_aligned = {
+0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
+0x1cd80081, 0x33001180, 0x42030003, 0x33800284,
+0x1c010204, 0x40200000, 0x40200000, 0x40200000,
+0x34000190, 0x34004191, 0x34008192, 0x3400c193,
+0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85,
+0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603,
+0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07,
+0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b,
+0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f,
+0x00003ffc, 0x00000000, 0x00000000, 0x00000000,
+0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204,
+0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202,
+0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682,
+0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f,
+0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204,
+0x04000203, 0x21a00903, 0x40848002, 0x21a00982,
+0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82,
+0x21a00083, 0x40800082, 0x21a00b02, 0x10002818,
+0x40a80002, 0x32800007, 0x4207000c, 0x18008208,
+0x40a0000b, 0x4080020a, 0x40800709, 0x00200000,
+0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000,
+0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185,
+0xb0408584, 0x28830382, 0x1c020387, 0x38828182,
+0xb0408405, 0x1802c408, 0x28828182, 0x217ff886,
+0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102,
+0x04000106, 0x21a00886, 0x04000603, 0x21a00903,
+0x40803c02, 0x21a00982, 0x40800003, 0x04000184,
+0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005,
+0x34208702, 0x21002282, 0x21a00804, 0x21a00886,
+0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102,
+0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04,
+0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83,
+0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02,
+0x34210283, 0x21a00f03, 0x34200284, 0x77400200,
+0x3421c282, 0x21a00702, 0x34218283, 0x21a00083,
+0x34214282, 0x21a00b02, 0x4200480c, 0x00200000,
+0x1c010286, 0x34220284, 0x34220302, 0x0f608203,
+0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000,
+0x18008185, 0x38808183, 0x3b814182, 0x21004e84,
+0x4020007f, 0x35000100, 0x000004e0, 0x000002a0,
+0x000002e8, 0x00000428, 0x00000360, 0x000002e8,
+0x000004a0, 0x00000468, 0x000003c8, 0x00000360,
+0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085,
+0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f,
+0x4020007f, 0x20801203, 0x38810602, 0xb0408586,
+0x28810602, 0x32004180, 0x34204702, 0x21a00382,
+0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203,
+0x40800204, 0x3ec40087, 0x40800405, 0x00200000,
+0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
+0xb060c107, 0x20801203, 0x41004003, 0x38810602,
+0x4020007f, 0xb0408188, 0x4020007f, 0x28810602,
+0x41201002, 0x38814603, 0x10009c09, 0xb060c109,
+0x4020007f, 0x28814603, 0x41193f83, 0x38818602,
+0x60ffc003, 0xb040818a, 0x28818602, 0x32003080,
+0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
+0x41201008, 0x10009c14, 0x40800405, 0x3ac10609,
+0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b,
+0x20801203, 0x38810602, 0xb0408409, 0x28810602,
+0x38814603, 0xb060c40a, 0x4020007f, 0x28814603,
+0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b,
+0x28818602, 0x32002380, 0x409ffe02, 0x30801204,
+0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607,
+0x3ac18608, 0xb0810103, 0x41004002, 0x20801204,
+0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107,
+0x4020007f, 0x4020007f, 0x28814603, 0x38818602,
+0x4020007f, 0x4020007f, 0xb0408588, 0x28818602,
+0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e,
+0x40800204, 0x30801203, 0x40800405, 0x3ec40087,
+0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
+0xb060c107, 0x20801203, 0x413d8003, 0x38810602,
+0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c,
+0x40800205, 0x30801204, 0x40800406, 0x3ec40083,
+0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002,
+0x20801204, 0x38814603, 0x4020007f, 0x327feb80,
+0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
+0x40800405, 0x1000650a, 0x40800606, 0x3ac10608,
+0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203,
+0x38810602, 0xb0408588, 0x4020007f, 0x327fc980,
+0x00400000, 0x40800003, 0x4020007f, 0x35000000,
+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, 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, 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, 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,
+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, 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, 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, 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,
+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, 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, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save.c b/arch/powerpc/platforms/cell/spufs/spu_save.c
new file mode 100644
index 000000000000..196033b8a579
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_save.c
@@ -0,0 +1,195 @@
+/*
+ * spu_save.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * SPU-side context save sequence outlined in
+ * Synergistic Processor Element Book IV
+ *
+ * Author: Mark Nutter <mnutter@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, 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 LS_SIZE
+#define LS_SIZE 0x40000 /* 256K (in bytes) */
+#endif
+
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+#include <spu_intrinsics.h>
+#include <asm/spu_csa.h>
+#include "spu_utils.h"
+
+static inline void save_event_mask(void)
+{
+ unsigned int offset;
+
+ /* Save, Step 2:
+ * Read the SPU_RdEventMsk channel and save to the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(event_mask);
+ regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask);
+}
+
+static inline void save_tag_mask(void)
+{
+ unsigned int offset;
+
+ /* Save, Step 3:
+ * Read the SPU_RdTagMsk channel and save to the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(tag_mask);
+ regs_spill[offset].slot[0] = spu_readch(MFC_RdTagMask);
+}
+
+static inline void save_upper_240kb(addr64 lscsa_ea)
+{
+ unsigned int ls = 16384;
+ unsigned int list = (unsigned int)&dma_list[0];
+ unsigned int size = sizeof(dma_list);
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0x24; /* PUTL */
+
+ /* Save, Step 7:
+ * Enqueue the PUTL command (tag 0) to the MFC SPU command
+ * queue to transfer the remaining 240 kb of LS to CSA.
+ */
+ spu_writech(MFC_LSA, ls);
+ spu_writech(MFC_EAH, lscsa_ea.ui[0]);
+ spu_writech(MFC_EAL, list);
+ spu_writech(MFC_Size, size);
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void save_fpcr(void)
+{
+ // vector unsigned int fpcr;
+ unsigned int offset;
+
+ /* Save, Step 9:
+ * Issue the floating-point status and control register
+ * read instruction, and save to the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(fpcr);
+ regs_spill[offset].v = spu_mffpscr();
+}
+
+static inline void save_decr(void)
+{
+ unsigned int offset;
+
+ /* Save, Step 10:
+ * Read and save the SPU_RdDec channel data to
+ * the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(decr);
+ regs_spill[offset].slot[0] = spu_readch(SPU_RdDec);
+}
+
+static inline void save_srr0(void)
+{
+ unsigned int offset;
+
+ /* Save, Step 11:
+ * Read and save the SPU_WSRR0 channel data to
+ * the LSCSA.
+ */
+ offset = LSCSA_QW_OFFSET(srr0);
+ regs_spill[offset].slot[0] = spu_readch(SPU_RdSRR0);
+}
+
+static inline void spill_regs_to_mem(addr64 lscsa_ea)
+{
+ unsigned int ls = (unsigned int)&regs_spill[0];
+ unsigned int size = sizeof(regs_spill);
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0x20; /* PUT */
+
+ /* Save, Step 13:
+ * Enqueue a PUT command (tag 0) to send the LSCSA
+ * to the CSA.
+ */
+ spu_writech(MFC_LSA, ls);
+ spu_writech(MFC_EAH, lscsa_ea.ui[0]);
+ spu_writech(MFC_EAL, lscsa_ea.ui[1]);
+ spu_writech(MFC_Size, size);
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void enqueue_sync(addr64 lscsa_ea)
+{
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0xCC;
+
+ /* Save, Step 14:
+ * Enqueue an MFC_SYNC command (tag 0).
+ */
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void save_complete(void)
+{
+ /* Save, Step 18:
+ * Issue a stop-and-signal instruction indicating
+ * "save complete". Note: This function will not
+ * return!!
+ */
+ spu_stop(SPU_SAVE_COMPLETE);
+}
+
+/**
+ * main - entry point for SPU-side context save.
+ *
+ * This code deviates from the documented sequence as follows:
+ *
+ * 1. The EA for LSCSA is passed from PPE in the
+ * signal notification channels.
+ * 2. All 128 registers are saved by crt0.o.
+ */
+int main()
+{
+ addr64 lscsa_ea;
+
+ lscsa_ea.ui[0] = spu_readch(SPU_RdSigNotify1);
+ lscsa_ea.ui[1] = spu_readch(SPU_RdSigNotify2);
+
+ /* Step 1: done by exit(). */
+ save_event_mask(); /* Step 2. */
+ save_tag_mask(); /* Step 3. */
+ set_event_mask(); /* Step 4. */
+ set_tag_mask(); /* Step 5. */
+ build_dma_list(lscsa_ea); /* Step 6. */
+ save_upper_240kb(lscsa_ea); /* Step 7. */
+ /* Step 8: done by exit(). */
+ save_fpcr(); /* Step 9. */
+ save_decr(); /* Step 10. */
+ save_srr0(); /* Step 11. */
+ enqueue_putllc(lscsa_ea); /* Step 12. */
+ spill_regs_to_mem(lscsa_ea); /* Step 13. */
+ enqueue_sync(lscsa_ea); /* Step 14. */
+ set_tag_update(); /* Step 15. */
+ read_tag_status(); /* Step 16. */
+ read_llar_status(); /* Step 17. */
+ save_complete(); /* Step 18. */
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_crt0.S b/arch/powerpc/platforms/cell/spufs/spu_save_crt0.S
new file mode 100644
index 000000000000..6659d6a66faa
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_save_crt0.S
@@ -0,0 +1,102 @@
+/*
+ * crt0_s.S: Entry function for SPU-side context save.
+ *
+ * Copyright (C) 2005 IBM
+ *
+ * Entry function for SPU-side of the context save sequence.
+ * Saves all 128 GPRs, sets up an initial stack frame, then
+ * branches to 'main'.
+ *
+ *
+ * This program is free software; you can redistribute 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 <asm/spu_csa.h>
+
+.data
+.align 7
+.globl regs_spill
+regs_spill:
+.space SIZEOF_SPU_SPILL_REGS, 0x0
+
+.text
+.global _start
+_start:
+ /* SPU Context Save Step 1: Save the first 16 GPRs. */
+ stqa $0, regs_spill + 0
+ stqa $1, regs_spill + 16
+ stqa $2, regs_spill + 32
+ stqa $3, regs_spill + 48
+ stqa $4, regs_spill + 64
+ stqa $5, regs_spill + 80
+ stqa $6, regs_spill + 96
+ stqa $7, regs_spill + 112
+ stqa $8, regs_spill + 128
+ stqa $9, regs_spill + 144
+ stqa $10, regs_spill + 160
+ stqa $11, regs_spill + 176
+ stqa $12, regs_spill + 192
+ stqa $13, regs_spill + 208
+ stqa $14, regs_spill + 224
+ stqa $15, regs_spill + 240
+
+ /* SPU Context Save, Step 8: Save the remaining 112 GPRs. */
+ ila $3, regs_spill + 256
+save_regs:
+ lqr $4, save_reg_insts
+save_reg_loop:
+ ai $4, $4, 4
+ .balignl 16, 0x40200000
+save_reg_insts: /* must be quad-word aligned. */
+ stqd $16, 0($3)
+ stqd $17, 16($3)
+ stqd $18, 32($3)
+ stqd $19, 48($3)
+ andi $5, $4, 0x7F
+ stqr $4, save_reg_insts
+ ai $3, $3, 64
+ brnz $5, save_reg_loop
+
+ /* Initialize the stack pointer to point to 16368
+ * (16kb-16). The back chain pointer is initialized
+ * to NULL.
+ */
+ il $0, 0
+ il $SP, 16368
+ stqd $0, 0($SP)
+
+ /* Allocate a minimum stack frame for the called main.
+ * This is needed so that main has a place to save the
+ * link register when it calls another function.
+ */
+ stqd $SP, -160($SP)
+ ai $SP, $SP, -160
+
+ /* Call the program's main function. */
+ brsl $0, main
+
+ /* In this case main should not return; if it does
+ * there has been an error in the sequence. Execute
+ * stop-and-signal with code=0.
+ */
+.global exit
+.global _exit
+exit:
+_exit:
+ stop 0x0
+
+ /* Pad the size of this crt0.o to be multiple of 16 bytes. */
+.balignl 16, 0x0
+
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
new file mode 100644
index 000000000000..39e54003f1df
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
@@ -0,0 +1,191 @@
+/*
+ * spu_save_dump.h: Copyright (C) 2005 IBM.
+ * Hex-dump auto generated from spu_save.c.
+ * Do not edit!
+ */
+static unsigned int spu_save_code[] __page_aligned = {
+0x20805000, 0x20805201, 0x20805402, 0x20805603,
+0x20805804, 0x20805a05, 0x20805c06, 0x20805e07,
+0x20806008, 0x20806209, 0x2080640a, 0x2080660b,
+0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f,
+0x4201c003, 0x33800184, 0x1c010204, 0x40200000,
+0x24000190, 0x24004191, 0x24008192, 0x2400c193,
+0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85,
+0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
+0x1cd80081, 0x33000180, 0x00000000, 0x00000000,
+0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204,
+0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583,
+0x34218682, 0x3ed80684, 0xb0408184, 0x24218682,
+0x01a00603, 0x00200000, 0x34214682, 0x3ed40684,
+0xb0408184, 0x40800003, 0x24214682, 0x21a00083,
+0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e,
+0x40a80002, 0x32800008, 0x4205c00c, 0x00200000,
+0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709,
+0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183,
+0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404,
+0x1cffc489, 0x00200000, 0x18008403, 0x38830402,
+0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402,
+0x1c020408, 0x38828182, 0xb0408385, 0x1802c387,
+0x28828182, 0x217ff886, 0x04000582, 0x32800007,
+0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285,
+0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903,
+0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06,
+0x40801202, 0x21a00a82, 0x73000003, 0x24200683,
+0x01a00404, 0x00200000, 0x34204682, 0x3ec40683,
+0xb0408203, 0x24204682, 0x01a00783, 0x00200000,
+0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682,
+0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204,
+0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002,
+0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82,
+0x04000683, 0x21a00803, 0x21a00885, 0x21a00904,
+0x40848002, 0x21a00982, 0x21a00a06, 0x40801002,
+0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000,
+0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83,
+0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003,
+0x4020007f, 0x35000000, 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, 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,
+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, 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, 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, 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,
+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, 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, 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, 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,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/spu_utils.h b/arch/powerpc/platforms/cell/spufs/spu_utils.h
new file mode 100644
index 000000000000..58359feb6c95
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spu_utils.h
@@ -0,0 +1,160 @@
+/*
+ * utils.h: Utilities for SPU-side of the context switch operation.
+ *
+ * (C) Copyright IBM 2005
+ *
+ * This program is free software; you can redistribute 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 _SPU_CONTEXT_UTILS_H_
+#define _SPU_CONTEXT_UTILS_H_
+
+/*
+ * 64-bit safe EA.
+ */
+typedef union {
+ unsigned long long ull;
+ unsigned int ui[2];
+} addr64;
+
+/*
+ * 128-bit register template.
+ */
+typedef union {
+ unsigned int slot[4];
+ vector unsigned int v;
+} spu_reg128v;
+
+/*
+ * DMA list structure.
+ */
+struct dma_list_elem {
+ unsigned int size;
+ unsigned int ea_low;
+};
+
+/*
+ * Declare storage for 8-byte aligned DMA list.
+ */
+struct dma_list_elem dma_list[15] __attribute__ ((aligned(8)));
+
+/*
+ * External definition for storage
+ * declared in crt0.
+ */
+extern spu_reg128v regs_spill[NR_SPU_SPILL_REGS];
+
+/*
+ * Compute LSCSA byte offset for a given field.
+ */
+static struct spu_lscsa *dummy = (struct spu_lscsa *)0;
+#define LSCSA_BYTE_OFFSET(_field) \
+ ((char *)(&(dummy->_field)) - (char *)(&(dummy->gprs[0].slot[0])))
+#define LSCSA_QW_OFFSET(_field) (LSCSA_BYTE_OFFSET(_field) >> 4)
+
+static inline void set_event_mask(void)
+{
+ unsigned int event_mask = 0;
+
+ /* Save, Step 4:
+ * Restore, Step 1:
+ * Set the SPU_RdEventMsk channel to zero to mask
+ * all events.
+ */
+ spu_writech(SPU_WrEventMask, event_mask);
+}
+
+static inline void set_tag_mask(void)
+{
+ unsigned int tag_mask = 1;
+
+ /* Save, Step 5:
+ * Restore, Step 2:
+ * Set the SPU_WrTagMsk channel to '01' to unmask
+ * only tag group 0.
+ */
+ spu_writech(MFC_WrTagMask, tag_mask);
+}
+
+static inline void build_dma_list(addr64 lscsa_ea)
+{
+ unsigned int ea_low;
+ int i;
+
+ /* Save, Step 6:
+ * Restore, Step 3:
+ * Update the effective address for the CSA in the
+ * pre-canned DMA-list in local storage.
+ */
+ ea_low = lscsa_ea.ui[1];
+ ea_low += LSCSA_BYTE_OFFSET(ls[16384]);
+
+ for (i = 0; i < 15; i++, ea_low += 16384) {
+ dma_list[i].size = 16384;
+ dma_list[i].ea_low = ea_low;
+ }
+}
+
+static inline void enqueue_putllc(addr64 lscsa_ea)
+{
+ unsigned int ls = 0;
+ unsigned int size = 128;
+ unsigned int tag_id = 0;
+ unsigned int cmd = 0xB4; /* PUTLLC */
+
+ /* Save, Step 12:
+ * Restore, Step 7:
+ * Send a PUTLLC (tag 0) command to the MFC using
+ * an effective address in the CSA in order to
+ * remove any possible lock-line reservation.
+ */
+ spu_writech(MFC_LSA, ls);
+ spu_writech(MFC_EAH, lscsa_ea.ui[0]);
+ spu_writech(MFC_EAL, lscsa_ea.ui[1]);
+ spu_writech(MFC_Size, size);
+ spu_writech(MFC_TagID, tag_id);
+ spu_writech(MFC_Cmd, cmd);
+}
+
+static inline void set_tag_update(void)
+{
+ unsigned int update_any = 1;
+
+ /* Save, Step 15:
+ * Restore, Step 8:
+ * Write the MFC_TagUpdate channel with '01'.
+ */
+ spu_writech(MFC_WrTagUpdate, update_any);
+}
+
+static inline void read_tag_status(void)
+{
+ /* Save, Step 16:
+ * Restore, Step 9:
+ * Read the MFC_TagStat channel data.
+ */
+ spu_readch(MFC_RdTagStat);
+}
+
+static inline void read_llar_status(void)
+{
+ /* Save, Step 17:
+ * Restore, Step 10:
+ * Read the MFC_AtomicStat channel data.
+ */
+ spu_readch(MFC_RdAtomicStat);
+}
+
+#endif /* _SPU_CONTEXT_UTILS_H_ */
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
new file mode 100644
index 000000000000..db2601f0abd5
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -0,0 +1,163 @@
+/*
+ * SPU file system
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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 SPUFS_H
+#define SPUFS_H
+
+#include <linux/kref.h>
+#include <linux/rwsem.h>
+#include <linux/spinlock.h>
+#include <linux/fs.h>
+
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+
+/* The magic number for our file system */
+enum {
+ SPUFS_MAGIC = 0x23c9b64e,
+};
+
+struct spu_context_ops;
+
+#define SPU_CONTEXT_PREEMPT 0UL
+
+struct spu_context {
+ struct spu *spu; /* pointer to a physical SPU */
+ struct spu_state csa; /* SPU context save area. */
+ spinlock_t mmio_lock; /* protects mmio access */
+ struct address_space *local_store;/* local store backing store */
+
+ enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
+ struct rw_semaphore state_sema;
+ struct semaphore run_sema;
+
+ struct mm_struct *owner;
+
+ struct kref kref;
+ wait_queue_head_t ibox_wq;
+ wait_queue_head_t wbox_wq;
+ wait_queue_head_t stop_wq;
+ struct fasync_struct *ibox_fasync;
+ struct fasync_struct *wbox_fasync;
+ struct spu_context_ops *ops;
+ struct work_struct reap_work;
+ u64 flags;
+};
+
+/* SPU context query/set operations. */
+struct spu_context_ops {
+ int (*mbox_read) (struct spu_context * ctx, u32 * data);
+ u32(*mbox_stat_read) (struct spu_context * ctx);
+ unsigned int (*mbox_stat_poll)(struct spu_context *ctx,
+ unsigned int events);
+ int (*ibox_read) (struct spu_context * ctx, u32 * data);
+ int (*wbox_write) (struct spu_context * ctx, u32 data);
+ u32(*signal1_read) (struct spu_context * ctx);
+ void (*signal1_write) (struct spu_context * ctx, u32 data);
+ u32(*signal2_read) (struct spu_context * ctx);
+ void (*signal2_write) (struct spu_context * ctx, u32 data);
+ void (*signal1_type_set) (struct spu_context * ctx, u64 val);
+ u64(*signal1_type_get) (struct spu_context * ctx);
+ void (*signal2_type_set) (struct spu_context * ctx, u64 val);
+ u64(*signal2_type_get) (struct spu_context * ctx);
+ u32(*npc_read) (struct spu_context * ctx);
+ void (*npc_write) (struct spu_context * ctx, u32 data);
+ u32(*status_read) (struct spu_context * ctx);
+ char*(*get_ls) (struct spu_context * ctx);
+ void (*runcntl_write) (struct spu_context * ctx, u32 data);
+ void (*runcntl_stop) (struct spu_context * ctx);
+};
+
+extern struct spu_context_ops spu_hw_ops;
+extern struct spu_context_ops spu_backing_ops;
+
+struct spufs_inode_info {
+ struct spu_context *i_ctx;
+ struct inode vfs_inode;
+};
+#define SPUFS_I(inode) \
+ container_of(inode, struct spufs_inode_info, vfs_inode)
+
+extern struct tree_descr spufs_dir_contents[];
+
+/* system call implementation */
+long spufs_run_spu(struct file *file,
+ struct spu_context *ctx, u32 *npc, u32 *status);
+long spufs_create_thread(struct nameidata *nd,
+ unsigned int flags, mode_t mode);
+extern struct file_operations spufs_context_fops;
+
+/* context management */
+struct spu_context * alloc_spu_context(struct address_space *local_store);
+void destroy_spu_context(struct kref *kref);
+struct spu_context * get_spu_context(struct spu_context *ctx);
+int put_spu_context(struct spu_context *ctx);
+void spu_unmap_mappings(struct spu_context *ctx);
+
+void spu_forget(struct spu_context *ctx);
+void spu_acquire(struct spu_context *ctx);
+void spu_release(struct spu_context *ctx);
+int spu_acquire_runnable(struct spu_context *ctx);
+void spu_acquire_saved(struct spu_context *ctx);
+
+int spu_activate(struct spu_context *ctx, u64 flags);
+void spu_deactivate(struct spu_context *ctx);
+void spu_yield(struct spu_context *ctx);
+int __init spu_sched_init(void);
+void __exit spu_sched_exit(void);
+
+/*
+ * spufs_wait
+ * Same as wait_event_interruptible(), except that here
+ * we need to call spu_release(ctx) before sleeping, and
+ * then spu_acquire(ctx) when awoken.
+ */
+
+#define spufs_wait(wq, condition) \
+({ \
+ int __ret = 0; \
+ DEFINE_WAIT(__wait); \
+ for (;;) { \
+ prepare_to_wait(&(wq), &__wait, TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ spu_release(ctx); \
+ schedule(); \
+ spu_acquire(ctx); \
+ continue; \
+ } \
+ __ret = -ERESTARTSYS; \
+ break; \
+ } \
+ finish_wait(&(wq), &__wait); \
+ __ret; \
+})
+
+size_t spu_wbox_write(struct spu_context *ctx, u32 data);
+size_t spu_ibox_read(struct spu_context *ctx, u32 *data);
+
+/* irq callback funcs. */
+void spufs_ibox_callback(struct spu *spu);
+void spufs_wbox_callback(struct spu *spu);
+void spufs_stop_callback(struct spu *spu);
+
+#endif
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
new file mode 100644
index 000000000000..212db28531fa
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -0,0 +1,2204 @@
+/*
+ * spu_switch.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author: Mark Nutter <mnutter@us.ibm.com>
+ *
+ * Host-side part of SPU context switch sequence outlined in
+ * Synergistic Processor Element, Book IV.
+ *
+ * A fully premptive switch of an SPE is very expensive in terms
+ * of time and system resources. SPE Book IV indicates that SPE
+ * allocation should follow a "serially reusable device" model,
+ * in which the SPE is assigned a task until it completes. When
+ * this is not possible, this sequence may be used to premptively
+ * save, and then later (optionally) restore the context of a
+ * program executing on an SPE.
+ *
+ *
+ * This program is free software; you can redistribute 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/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_csa.h>
+#include <asm/mmu_context.h>
+
+#include "spu_save_dump.h"
+#include "spu_restore_dump.h"
+
+#if 0
+#define POLL_WHILE_TRUE(_c) { \
+ do { \
+ } while (_c); \
+ }
+#else
+#define RELAX_SPIN_COUNT 1000
+#define POLL_WHILE_TRUE(_c) { \
+ do { \
+ int _i; \
+ for (_i=0; _i<RELAX_SPIN_COUNT && (_c); _i++) { \
+ cpu_relax(); \
+ } \
+ if (unlikely(_c)) yield(); \
+ else break; \
+ } while (_c); \
+ }
+#endif /* debug */
+
+#define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c))
+
+static inline void acquire_spu_lock(struct spu *spu)
+{
+ /* Save, Step 1:
+ * Restore, Step 1:
+ * Acquire SPU-specific mutual exclusion lock.
+ * TBD.
+ */
+}
+
+static inline void release_spu_lock(struct spu *spu)
+{
+ /* Restore, Step 76:
+ * Release SPU-specific mutual exclusion lock.
+ * TBD.
+ */
+}
+
+static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 isolate_state;
+
+ /* Save, Step 2:
+ * Save, Step 6:
+ * If SPU_Status[E,L,IS] any field is '1', this
+ * SPU is in isolate state and cannot be context
+ * saved at this time.
+ */
+ isolate_state = SPU_STATUS_ISOLATED_STATE |
+ SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS;
+ return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0;
+}
+
+static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 3:
+ * Restore, Step 2:
+ * Save INT_Mask_class0 in CSA.
+ * Write INT_MASK_class0 with value of 0.
+ * Save INT_Mask_class1 in CSA.
+ * Write INT_MASK_class1 with value of 0.
+ * Save INT_Mask_class2 in CSA.
+ * Write INT_MASK_class2 with value of 0.
+ */
+ spin_lock_irq(&spu->register_lock);
+ if (csa) {
+ csa->priv1.int_mask_class0_RW = spu_int_mask_get(spu, 0);
+ csa->priv1.int_mask_class1_RW = spu_int_mask_get(spu, 1);
+ csa->priv1.int_mask_class2_RW = spu_int_mask_get(spu, 2);
+ }
+ spu_int_mask_set(spu, 0, 0ul);
+ spu_int_mask_set(spu, 1, 0ul);
+ spu_int_mask_set(spu, 2, 0ul);
+ eieio();
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static inline void set_watchdog_timer(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 4:
+ * Restore, Step 25.
+ * Set a software watchdog timer, which specifies the
+ * maximum allowable time for a context save sequence.
+ *
+ * For present, this implementation will not set a global
+ * watchdog timer, as virtualization & variable system load
+ * may cause unpredictable execution times.
+ */
+}
+
+static inline void inhibit_user_access(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 5:
+ * Restore, Step 3:
+ * Inhibit user-space access (if provided) to this
+ * SPU by unmapping the virtual pages assigned to
+ * the SPU memory-mapped I/O (MMIO) for problem
+ * state. TBD.
+ */
+}
+
+static inline void set_switch_pending(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 7:
+ * Restore, Step 5:
+ * Set a software context switch pending flag.
+ */
+ set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);
+ mb();
+}
+
+static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 8:
+ * Suspend DMA and save MFC_CNTL.
+ */
+ switch (in_be64(&priv2->mfc_control_RW) &
+ MFC_CNTL_SUSPEND_DMA_STATUS_MASK) {
+ case MFC_CNTL_SUSPEND_IN_PROGRESS:
+ POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+ MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
+ MFC_CNTL_SUSPEND_COMPLETE);
+ /* fall through */
+ case MFC_CNTL_SUSPEND_COMPLETE:
+ if (csa) {
+ csa->priv2.mfc_control_RW =
+ in_be64(&priv2->mfc_control_RW) |
+ MFC_CNTL_SUSPEND_DMA_QUEUE;
+ }
+ break;
+ case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION:
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE);
+ POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &
+ MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==
+ MFC_CNTL_SUSPEND_COMPLETE);
+ if (csa) {
+ csa->priv2.mfc_control_RW =
+ in_be64(&priv2->mfc_control_RW) &
+ ~MFC_CNTL_SUSPEND_DMA_QUEUE;
+ }
+ break;
+ }
+}
+
+static inline void save_spu_runcntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 9:
+ * Save SPU_Runcntl in the CSA. This value contains
+ * the "Application Desired State".
+ */
+ csa->prob.spu_runcntl_RW = in_be32(&prob->spu_runcntl_RW);
+}
+
+static inline void save_mfc_sr1(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 10:
+ * Save MFC_SR1 in the CSA.
+ */
+ csa->priv1.mfc_sr1_RW = spu_mfc_sr1_get(spu);
+}
+
+static inline void save_spu_status(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 11:
+ * Read SPU_Status[R], and save to CSA.
+ */
+ if ((in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) == 0) {
+ csa->prob.spu_status_R = in_be32(&prob->spu_status_R);
+ } else {
+ u32 stopped;
+
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ stopped =
+ SPU_STATUS_INVALID_INSTR | SPU_STATUS_SINGLE_STEP |
+ SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
+ if ((in_be32(&prob->spu_status_R) & stopped) == 0)
+ csa->prob.spu_status_R = SPU_STATUS_RUNNING;
+ else
+ csa->prob.spu_status_R = in_be32(&prob->spu_status_R);
+ }
+}
+
+static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 12:
+ * Read MFC_CNTL[Ds]. Update saved copy of
+ * CSA.MFC_CNTL[Ds].
+ */
+ if (in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DECREMENTER_RUNNING) {
+ csa->priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING;
+ csa->suspend_time = get_cycles();
+ out_be64(&priv2->spu_chnlcntptr_RW, 7ULL);
+ eieio();
+ csa->spu_chnldata_RW[7] = in_be64(&priv2->spu_chnldata_RW);
+ eieio();
+ } else {
+ csa->priv2.mfc_control_RW &= ~MFC_CNTL_DECREMENTER_RUNNING;
+ }
+}
+
+static inline void halt_mfc_decr(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 13:
+ * Write MFC_CNTL[Dh] set to a '1' to halt
+ * the decrementer.
+ */
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_DECREMENTER_HALTED);
+ eieio();
+}
+
+static inline void save_timebase(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 14:
+ * Read PPE Timebase High and Timebase low registers
+ * and save in CSA. TBD.
+ */
+ csa->suspend_time = get_cycles();
+}
+
+static inline void remove_other_spu_access(struct spu_state *csa,
+ struct spu *spu)
+{
+ /* Save, Step 15:
+ * Remove other SPU access to this SPU by unmapping
+ * this SPU's pages from their address space. TBD.
+ */
+}
+
+static inline void do_mfc_mssync(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 16:
+ * Restore, Step 11.
+ * Write SPU_MSSync register. Poll SPU_MSSync[P]
+ * for a value of 0.
+ */
+ out_be64(&prob->spc_mssync_RW, 1UL);
+ POLL_WHILE_TRUE(in_be64(&prob->spc_mssync_RW) & MS_SYNC_PENDING);
+}
+
+static inline void issue_mfc_tlbie(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 17:
+ * Restore, Step 12.
+ * Restore, Step 48.
+ * Write TLB_Invalidate_Entry[IS,VPN,L,Lp]=0 register.
+ * Then issue a PPE sync instruction.
+ */
+ spu_tlb_invalidate(spu);
+ mb();
+}
+
+static inline void handle_pending_interrupts(struct spu_state *csa,
+ struct spu *spu)
+{
+ /* Save, Step 18:
+ * Handle any pending interrupts from this SPU
+ * here. This is OS or hypervisor specific. One
+ * option is to re-enable interrupts to handle any
+ * pending interrupts, with the interrupt handlers
+ * recognizing the software Context Switch Pending
+ * flag, to ensure the SPU execution or MFC command
+ * queue is not restarted. TBD.
+ */
+}
+
+static inline void save_mfc_queues(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Save, Step 19:
+ * If MFC_Cntl[Se]=0 then save
+ * MFC command queues.
+ */
+ if ((in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DMA_QUEUES_EMPTY) == 0) {
+ for (i = 0; i < 8; i++) {
+ csa->priv2.puq[i].mfc_cq_data0_RW =
+ in_be64(&priv2->puq[i].mfc_cq_data0_RW);
+ csa->priv2.puq[i].mfc_cq_data1_RW =
+ in_be64(&priv2->puq[i].mfc_cq_data1_RW);
+ csa->priv2.puq[i].mfc_cq_data2_RW =
+ in_be64(&priv2->puq[i].mfc_cq_data2_RW);
+ csa->priv2.puq[i].mfc_cq_data3_RW =
+ in_be64(&priv2->puq[i].mfc_cq_data3_RW);
+ }
+ for (i = 0; i < 16; i++) {
+ csa->priv2.spuq[i].mfc_cq_data0_RW =
+ in_be64(&priv2->spuq[i].mfc_cq_data0_RW);
+ csa->priv2.spuq[i].mfc_cq_data1_RW =
+ in_be64(&priv2->spuq[i].mfc_cq_data1_RW);
+ csa->priv2.spuq[i].mfc_cq_data2_RW =
+ in_be64(&priv2->spuq[i].mfc_cq_data2_RW);
+ csa->priv2.spuq[i].mfc_cq_data3_RW =
+ in_be64(&priv2->spuq[i].mfc_cq_data3_RW);
+ }
+ }
+}
+
+static inline void save_ppu_querymask(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 20:
+ * Save the PPU_QueryMask register
+ * in the CSA.
+ */
+ csa->prob.dma_querymask_RW = in_be32(&prob->dma_querymask_RW);
+}
+
+static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 21:
+ * Save the PPU_QueryType register
+ * in the CSA.
+ */
+ csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW);
+}
+
+static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 22:
+ * Save the MFC_CSR_TSQ register
+ * in the LSCSA.
+ */
+ csa->priv2.spu_tag_status_query_RW =
+ in_be64(&priv2->spu_tag_status_query_RW);
+}
+
+static inline void save_mfc_csr_cmd(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 23:
+ * Save the MFC_CSR_CMD1 and MFC_CSR_CMD2
+ * registers in the CSA.
+ */
+ csa->priv2.spu_cmd_buf1_RW = in_be64(&priv2->spu_cmd_buf1_RW);
+ csa->priv2.spu_cmd_buf2_RW = in_be64(&priv2->spu_cmd_buf2_RW);
+}
+
+static inline void save_mfc_csr_ato(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 24:
+ * Save the MFC_CSR_ATO register in
+ * the CSA.
+ */
+ csa->priv2.spu_atomic_status_RW = in_be64(&priv2->spu_atomic_status_RW);
+}
+
+static inline void save_mfc_tclass_id(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 25:
+ * Save the MFC_TCLASS_ID register in
+ * the CSA.
+ */
+ csa->priv1.mfc_tclass_id_RW = spu_mfc_tclass_id_get(spu);
+}
+
+static inline void set_mfc_tclass_id(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 26:
+ * Restore, Step 23.
+ * Write the MFC_TCLASS_ID register with
+ * the value 0x10000000.
+ */
+ spu_mfc_tclass_id_set(spu, 0x10000000);
+ eieio();
+}
+
+static inline void purge_mfc_queue(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 27:
+ * Restore, Step 14.
+ * Write MFC_CNTL[Pc]=1 (purge queue).
+ */
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_PURGE_DMA_REQUEST);
+ eieio();
+}
+
+static inline void wait_purge_complete(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 28:
+ * Poll MFC_CNTL[Ps] until value '11' is read
+ * (purge complete).
+ */
+ POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
+ MFC_CNTL_PURGE_DMA_COMPLETE);
+}
+
+static inline void save_mfc_slbs(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Save, Step 29:
+ * If MFC_SR1[R]='1', save SLBs in CSA.
+ */
+ if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK) {
+ csa->priv2.slb_index_W = in_be64(&priv2->slb_index_W);
+ for (i = 0; i < 8; i++) {
+ out_be64(&priv2->slb_index_W, i);
+ eieio();
+ csa->slb_esid_RW[i] = in_be64(&priv2->slb_esid_RW);
+ csa->slb_vsid_RW[i] = in_be64(&priv2->slb_vsid_RW);
+ eieio();
+ }
+ }
+}
+
+static inline void setup_mfc_sr1(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 30:
+ * Restore, Step 18:
+ * Write MFC_SR1 with MFC_SR1[D=0,S=1] and
+ * MFC_SR1[TL,R,Pr,T] set correctly for the
+ * OS specific environment.
+ *
+ * Implementation note: The SPU-side code
+ * for save/restore is privileged, so the
+ * MFC_SR1[Pr] bit is not set.
+ *
+ */
+ spu_mfc_sr1_set(spu, (MFC_STATE1_MASTER_RUN_CONTROL_MASK |
+ MFC_STATE1_RELOCATE_MASK |
+ MFC_STATE1_BUS_TLBIE_MASK));
+}
+
+static inline void save_spu_npc(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 31:
+ * Save SPU_NPC in the CSA.
+ */
+ csa->prob.spu_npc_RW = in_be32(&prob->spu_npc_RW);
+}
+
+static inline void save_spu_privcntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 32:
+ * Save SPU_PrivCntl in the CSA.
+ */
+ csa->priv2.spu_privcntl_RW = in_be64(&priv2->spu_privcntl_RW);
+}
+
+static inline void reset_spu_privcntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 33:
+ * Restore, Step 16:
+ * Write SPU_PrivCntl[S,Le,A] fields reset to 0.
+ */
+ out_be64(&priv2->spu_privcntl_RW, 0UL);
+ eieio();
+}
+
+static inline void save_spu_lslr(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 34:
+ * Save SPU_LSLR in the CSA.
+ */
+ csa->priv2.spu_lslr_RW = in_be64(&priv2->spu_lslr_RW);
+}
+
+static inline void reset_spu_lslr(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 35:
+ * Restore, Step 17.
+ * Reset SPU_LSLR.
+ */
+ out_be64(&priv2->spu_lslr_RW, LS_ADDR_MASK);
+ eieio();
+}
+
+static inline void save_spu_cfg(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 36:
+ * Save SPU_Cfg in the CSA.
+ */
+ csa->priv2.spu_cfg_RW = in_be64(&priv2->spu_cfg_RW);
+}
+
+static inline void save_pm_trace(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 37:
+ * Save PM_Trace_Tag_Wait_Mask in the CSA.
+ * Not performed by this implementation.
+ */
+}
+
+static inline void save_mfc_rag(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 38:
+ * Save RA_GROUP_ID register and the
+ * RA_ENABLE reigster in the CSA.
+ */
+ csa->priv1.resource_allocation_groupID_RW =
+ spu_resource_allocation_groupID_get(spu);
+ csa->priv1.resource_allocation_enable_RW =
+ spu_resource_allocation_enable_get(spu);
+}
+
+static inline void save_ppu_mb_stat(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 39:
+ * Save MB_Stat register in the CSA.
+ */
+ csa->prob.mb_stat_R = in_be32(&prob->mb_stat_R);
+}
+
+static inline void save_ppu_mb(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 40:
+ * Save the PPU_MB register in the CSA.
+ */
+ csa->prob.pu_mb_R = in_be32(&prob->pu_mb_R);
+}
+
+static inline void save_ppuint_mb(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 41:
+ * Save the PPUINT_MB register in the CSA.
+ */
+ csa->priv2.puint_mb_R = in_be64(&priv2->puint_mb_R);
+}
+
+static inline void save_ch_part1(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ int i;
+
+ /* Save, Step 42:
+ * Save the following CH: [0,1,3,4,24,25,27]
+ */
+ for (i = 0; i < 7; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ csa->spu_chnldata_RW[idx] = in_be64(&priv2->spu_chnldata_RW);
+ csa->spu_chnlcnt_RW[idx] = in_be64(&priv2->spu_chnlcnt_RW);
+ out_be64(&priv2->spu_chnldata_RW, 0UL);
+ out_be64(&priv2->spu_chnlcnt_RW, 0UL);
+ eieio();
+ }
+}
+
+static inline void save_spu_mb(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Save, Step 43:
+ * Save SPU Read Mailbox Channel.
+ */
+ out_be64(&priv2->spu_chnlcntptr_RW, 29UL);
+ eieio();
+ csa->spu_chnlcnt_RW[29] = in_be64(&priv2->spu_chnlcnt_RW);
+ for (i = 0; i < 4; i++) {
+ csa->spu_mailbox_data[i] = in_be64(&priv2->spu_chnldata_RW);
+ }
+ out_be64(&priv2->spu_chnlcnt_RW, 0UL);
+ eieio();
+}
+
+static inline void save_mfc_cmd(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 44:
+ * Save MFC_CMD Channel.
+ */
+ out_be64(&priv2->spu_chnlcntptr_RW, 21UL);
+ eieio();
+ csa->spu_chnlcnt_RW[21] = in_be64(&priv2->spu_chnlcnt_RW);
+ eieio();
+}
+
+static inline void reset_ch(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 ch_indices[4] = { 21UL, 23UL, 28UL, 30UL };
+ u64 ch_counts[4] = { 16UL, 1UL, 1UL, 1UL };
+ u64 idx;
+ int i;
+
+ /* Save, Step 45:
+ * Reset the following CH: [21, 23, 28, 30]
+ */
+ for (i = 0; i < 4; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ out_be64(&priv2->spu_chnlcnt_RW, ch_counts[i]);
+ eieio();
+ }
+}
+
+static inline void resume_mfc_queue(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 46:
+ * Restore, Step 25.
+ * Write MFC_CNTL[Sc]=0 (resume queue processing).
+ */
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
+}
+
+static inline void invalidate_slbs(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Save, Step 45:
+ * Restore, Step 19:
+ * If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All.
+ */
+ if (spu_mfc_sr1_get(spu) & MFC_STATE1_RELOCATE_MASK) {
+ out_be64(&priv2->slb_invalidate_all_W, 0UL);
+ eieio();
+ }
+}
+
+static inline void get_kernel_slb(u64 ea, u64 slb[2])
+{
+ slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
+ slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
+
+ /* Large pages are used for kernel text/data, but not vmalloc. */
+ if (cpu_has_feature(CPU_FTR_16M_PAGE)
+ && REGION_ID(ea) == KERNEL_REGION_ID)
+ slb[0] |= SLB_VSID_L;
+}
+
+static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ out_be64(&priv2->slb_index_W, slbe);
+ eieio();
+ out_be64(&priv2->slb_vsid_RW, slb[0]);
+ out_be64(&priv2->slb_esid_RW, slb[1]);
+ eieio();
+}
+
+static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
+{
+ u64 code_slb[2];
+ u64 lscsa_slb[2];
+
+ /* Save, Step 47:
+ * Restore, Step 30.
+ * If MFC_SR1[R]=1, write 0 to SLB_Invalidate_All
+ * register, then initialize SLB_VSID and SLB_ESID
+ * to provide access to SPU context save code and
+ * LSCSA.
+ *
+ * This implementation places both the context
+ * switch code and LSCSA in kernel address space.
+ *
+ * Further this implementation assumes that the
+ * MFC_SR1[R]=1 (in other words, assume that
+ * translation is desired by OS environment).
+ */
+ invalidate_slbs(csa, spu);
+ get_kernel_slb((unsigned long)&spu_save_code[0], code_slb);
+ get_kernel_slb((unsigned long)csa->lscsa, lscsa_slb);
+ load_mfc_slb(spu, code_slb, 0);
+ if ((lscsa_slb[0] != code_slb[0]) || (lscsa_slb[1] != code_slb[1]))
+ load_mfc_slb(spu, lscsa_slb, 1);
+}
+
+static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
+{
+ /* Save, Step 48:
+ * Restore, Step 23.
+ * Change the software context switch pending flag
+ * to context switch active.
+ */
+ set_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags);
+ clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);
+ mb();
+}
+
+static inline void enable_interrupts(struct spu_state *csa, struct spu *spu)
+{
+ unsigned long class1_mask = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
+ CLASS1_ENABLE_STORAGE_FAULT_INTR;
+
+ /* Save, Step 49:
+ * Restore, Step 22:
+ * Reset and then enable interrupts, as
+ * needed by OS.
+ *
+ * This implementation enables only class1
+ * (translation) interrupts.
+ */
+ spin_lock_irq(&spu->register_lock);
+ spu_int_stat_clear(spu, 0, ~0ul);
+ spu_int_stat_clear(spu, 1, ~0ul);
+ spu_int_stat_clear(spu, 2, ~0ul);
+ spu_int_mask_set(spu, 0, 0ul);
+ spu_int_mask_set(spu, 1, class1_mask);
+ spu_int_mask_set(spu, 2, 0ul);
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static inline int send_mfc_dma(struct spu *spu, unsigned long ea,
+ unsigned int ls_offset, unsigned int size,
+ unsigned int tag, unsigned int rclass,
+ unsigned int cmd)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ union mfc_tag_size_class_cmd command;
+ unsigned int transfer_size;
+ volatile unsigned int status = 0x0;
+
+ while (size > 0) {
+ transfer_size =
+ (size > MFC_MAX_DMA_SIZE) ? MFC_MAX_DMA_SIZE : size;
+ command.u.mfc_size = transfer_size;
+ command.u.mfc_tag = tag;
+ command.u.mfc_rclassid = rclass;
+ command.u.mfc_cmd = cmd;
+ do {
+ out_be32(&prob->mfc_lsa_W, ls_offset);
+ out_be64(&prob->mfc_ea_W, ea);
+ out_be64(&prob->mfc_union_W.all64, command.all64);
+ status =
+ in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32);
+ if (unlikely(status & 0x2)) {
+ cpu_relax();
+ }
+ } while (status & 0x3);
+ size -= transfer_size;
+ ea += transfer_size;
+ ls_offset += transfer_size;
+ }
+ return 0;
+}
+
+static inline void save_ls_16kb(struct spu_state *csa, struct spu *spu)
+{
+ unsigned long addr = (unsigned long)&csa->lscsa->ls[0];
+ unsigned int ls_offset = 0x0;
+ unsigned int size = 16384;
+ unsigned int tag = 0;
+ unsigned int rclass = 0;
+ unsigned int cmd = MFC_PUT_CMD;
+
+ /* Save, Step 50:
+ * Issue a DMA command to copy the first 16K bytes
+ * of local storage to the CSA.
+ */
+ send_mfc_dma(spu, addr, ls_offset, size, tag, rclass, cmd);
+}
+
+static inline void set_spu_npc(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 51:
+ * Restore, Step 31.
+ * Write SPU_NPC[IE]=0 and SPU_NPC[LSA] to entry
+ * point address of context save code in local
+ * storage.
+ *
+ * This implementation uses SPU-side save/restore
+ * programs with entry points at LSA of 0.
+ */
+ out_be32(&prob->spu_npc_RW, 0);
+ eieio();
+}
+
+static inline void set_signot1(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ union {
+ u64 ull;
+ u32 ui[2];
+ } addr64;
+
+ /* Save, Step 52:
+ * Restore, Step 32:
+ * Write SPU_Sig_Notify_1 register with upper 32-bits
+ * of the CSA.LSCSA effective address.
+ */
+ addr64.ull = (u64) csa->lscsa;
+ out_be32(&prob->signal_notify1, addr64.ui[0]);
+ eieio();
+}
+
+static inline void set_signot2(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ union {
+ u64 ull;
+ u32 ui[2];
+ } addr64;
+
+ /* Save, Step 53:
+ * Restore, Step 33:
+ * Write SPU_Sig_Notify_2 register with lower 32-bits
+ * of the CSA.LSCSA effective address.
+ */
+ addr64.ull = (u64) csa->lscsa;
+ out_be32(&prob->signal_notify2, addr64.ui[1]);
+ eieio();
+}
+
+static inline void send_save_code(struct spu_state *csa, struct spu *spu)
+{
+ unsigned long addr = (unsigned long)&spu_save_code[0];
+ unsigned int ls_offset = 0x0;
+ unsigned int size = sizeof(spu_save_code);
+ unsigned int tag = 0;
+ unsigned int rclass = 0;
+ unsigned int cmd = MFC_GETFS_CMD;
+
+ /* Save, Step 54:
+ * Issue a DMA command to copy context save code
+ * to local storage and start SPU.
+ */
+ send_mfc_dma(spu, addr, ls_offset, size, tag, rclass, cmd);
+}
+
+static inline void set_ppu_querymask(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Save, Step 55:
+ * Restore, Step 38.
+ * Write PPU_QueryMask=1 (enable Tag Group 0)
+ * and issue eieio instruction.
+ */
+ out_be32(&prob->dma_querymask_RW, MFC_TAGID_TO_TAGMASK(0));
+ eieio();
+}
+
+static inline void wait_tag_complete(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 mask = MFC_TAGID_TO_TAGMASK(0);
+ unsigned long flags;
+
+ /* Save, Step 56:
+ * Restore, Step 39.
+ * Restore, Step 39.
+ * Restore, Step 46.
+ * Poll PPU_TagStatus[gn] until 01 (Tag group 0 complete)
+ * or write PPU_QueryType[TS]=01 and wait for Tag Group
+ * Complete Interrupt. Write INT_Stat_Class0 or
+ * INT_Stat_Class2 with value of 'handled'.
+ */
+ POLL_WHILE_FALSE(in_be32(&prob->dma_tagstatus_R) & mask);
+
+ local_irq_save(flags);
+ spu_int_stat_clear(spu, 0, ~(0ul));
+ spu_int_stat_clear(spu, 2, ~(0ul));
+ local_irq_restore(flags);
+}
+
+static inline void wait_spu_stopped(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ unsigned long flags;
+
+ /* Save, Step 57:
+ * Restore, Step 40.
+ * Poll until SPU_Status[R]=0 or wait for SPU Class 0
+ * or SPU Class 2 interrupt. Write INT_Stat_class0
+ * or INT_Stat_class2 with value of handled.
+ */
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING);
+
+ local_irq_save(flags);
+ spu_int_stat_clear(spu, 0, ~(0ul));
+ spu_int_stat_clear(spu, 2, ~(0ul));
+ local_irq_restore(flags);
+}
+
+static inline int check_save_status(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 complete;
+
+ /* Save, Step 54:
+ * If SPU_Status[P]=1 and SPU_Status[SC] = "success",
+ * context save succeeded, otherwise context save
+ * failed.
+ */
+ complete = ((SPU_SAVE_COMPLETE << SPU_STOP_STATUS_SHIFT) |
+ SPU_STATUS_STOPPED_BY_STOP);
+ return (in_be32(&prob->spu_status_R) != complete) ? 1 : 0;
+}
+
+static inline void terminate_spu_app(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 4:
+ * If required, notify the "using application" that
+ * the SPU task has been terminated. TBD.
+ */
+}
+
+static inline void suspend_mfc(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 7:
+ * Restore, Step 47.
+ * Write MFC_Cntl[Dh,Sc]='1','1' to suspend
+ * the queue and halt the decrementer.
+ */
+ out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE |
+ MFC_CNTL_DECREMENTER_HALTED);
+ eieio();
+}
+
+static inline void wait_suspend_mfc_complete(struct spu_state *csa,
+ struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 8:
+ * Restore, Step 47.
+ * Poll MFC_CNTL[Ss] until 11 is returned.
+ */
+ POLL_WHILE_FALSE(in_be64(&priv2->mfc_control_RW) &
+ MFC_CNTL_SUSPEND_COMPLETE);
+}
+
+static inline int suspend_spe(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 9:
+ * If SPU_Status[R]=1, stop SPU execution
+ * and wait for stop to complete.
+ *
+ * Returns 1 if SPU_Status[R]=1 on entry.
+ * 0 otherwise
+ */
+ if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) {
+ if (in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_EXIT_STAUTUS) {
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+ if ((in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_LOAD_STAUTUS)
+ || (in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_STATE)) {
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ out_be32(&prob->spu_runcntl_RW, 0x2);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+ if (in_be32(&prob->spu_status_R) &
+ SPU_STATUS_WAITING_FOR_CHANNEL) {
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static inline void clear_spu_status(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 10:
+ * If SPU_Status[R]=0 and SPU_Status[E,L,IS]=1,
+ * release SPU from isolate state.
+ */
+ if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) {
+ if (in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_EXIT_STAUTUS) {
+ spu_mfc_sr1_set(spu,
+ MFC_STATE1_MASTER_RUN_CONTROL_MASK);
+ eieio();
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_RUNNABLE);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+ if ((in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_LOAD_STAUTUS)
+ || (in_be32(&prob->spu_status_R) &
+ SPU_STATUS_ISOLATED_STATE)) {
+ spu_mfc_sr1_set(spu,
+ MFC_STATE1_MASTER_RUN_CONTROL_MASK);
+ eieio();
+ out_be32(&prob->spu_runcntl_RW, 0x2);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+ }
+}
+
+static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ u64 idx;
+ int i;
+
+ /* Restore, Step 20:
+ * Reset the following CH: [0,1,3,4,24,25,27]
+ */
+ for (i = 0; i < 7; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ out_be64(&priv2->spu_chnldata_RW, 0UL);
+ out_be64(&priv2->spu_chnlcnt_RW, 0UL);
+ eieio();
+ }
+}
+
+static inline void reset_ch_part2(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 ch_indices[5] = { 21UL, 23UL, 28UL, 29UL, 30UL };
+ u64 ch_counts[5] = { 16UL, 1UL, 1UL, 0UL, 1UL };
+ u64 idx;
+ int i;
+
+ /* Restore, Step 21:
+ * Reset the following CH: [21, 23, 28, 29, 30]
+ */
+ for (i = 0; i < 5; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ out_be64(&priv2->spu_chnlcnt_RW, ch_counts[i]);
+ eieio();
+ }
+}
+
+static inline void setup_spu_status_part1(struct spu_state *csa,
+ struct spu *spu)
+{
+ u32 status_P = SPU_STATUS_STOPPED_BY_STOP;
+ u32 status_I = SPU_STATUS_INVALID_INSTR;
+ u32 status_H = SPU_STATUS_STOPPED_BY_HALT;
+ u32 status_S = SPU_STATUS_SINGLE_STEP;
+ u32 status_S_I = SPU_STATUS_SINGLE_STEP | SPU_STATUS_INVALID_INSTR;
+ u32 status_S_P = SPU_STATUS_SINGLE_STEP | SPU_STATUS_STOPPED_BY_STOP;
+ u32 status_P_H = SPU_STATUS_STOPPED_BY_HALT |SPU_STATUS_STOPPED_BY_STOP;
+ u32 status_P_I = SPU_STATUS_STOPPED_BY_STOP |SPU_STATUS_INVALID_INSTR;
+ u32 status_code;
+
+ /* Restore, Step 27:
+ * If the CSA.SPU_Status[I,S,H,P]=1 then add the correct
+ * instruction sequence to the end of the SPU based restore
+ * code (after the "context restored" stop and signal) to
+ * restore the correct SPU status.
+ *
+ * NOTE: Rather than modifying the SPU executable, we
+ * instead add a new 'stopped_status' field to the
+ * LSCSA. The SPU-side restore reads this field and
+ * takes the appropriate action when exiting.
+ */
+
+ status_code =
+ (csa->prob.spu_status_R >> SPU_STOP_STATUS_SHIFT) & 0xFFFF;
+ if ((csa->prob.spu_status_R & status_P_I) == status_P_I) {
+
+ /* SPU_Status[P,I]=1 - Illegal Instruction followed
+ * by Stop and Signal instruction, followed by 'br -4'.
+ *
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_P_I;
+ csa->lscsa->stopped_status.slot[1] = status_code;
+
+ } else if ((csa->prob.spu_status_R & status_P_H) == status_P_H) {
+
+ /* SPU_Status[P,H]=1 - Halt Conditional, followed
+ * by Stop and Signal instruction, followed by
+ * 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_P_H;
+ csa->lscsa->stopped_status.slot[1] = status_code;
+
+ } else if ((csa->prob.spu_status_R & status_S_P) == status_S_P) {
+
+ /* SPU_Status[S,P]=1 - Stop and Signal instruction
+ * followed by 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_S_P;
+ csa->lscsa->stopped_status.slot[1] = status_code;
+
+ } else if ((csa->prob.spu_status_R & status_S_I) == status_S_I) {
+
+ /* SPU_Status[S,I]=1 - Illegal instruction followed
+ * by 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_S_I;
+ csa->lscsa->stopped_status.slot[1] = status_code;
+
+ } else if ((csa->prob.spu_status_R & status_P) == status_P) {
+
+ /* SPU_Status[P]=1 - Stop and Signal instruction
+ * followed by 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_P;
+ csa->lscsa->stopped_status.slot[1] = status_code;
+
+ } else if ((csa->prob.spu_status_R & status_H) == status_H) {
+
+ /* SPU_Status[H]=1 - Halt Conditional, followed
+ * by 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_H;
+
+ } else if ((csa->prob.spu_status_R & status_S) == status_S) {
+
+ /* SPU_Status[S]=1 - Two nop instructions.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_S;
+
+ } else if ((csa->prob.spu_status_R & status_I) == status_I) {
+
+ /* SPU_Status[I]=1 - Illegal instruction followed
+ * by 'br -4'.
+ */
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_I;
+
+ }
+}
+
+static inline void setup_spu_status_part2(struct spu_state *csa,
+ struct spu *spu)
+{
+ u32 mask;
+
+ /* Restore, Step 28:
+ * If the CSA.SPU_Status[I,S,H,P,R]=0 then
+ * add a 'br *' instruction to the end of
+ * the SPU based restore code.
+ *
+ * NOTE: Rather than modifying the SPU executable, we
+ * instead add a new 'stopped_status' field to the
+ * LSCSA. The SPU-side restore reads this field and
+ * takes the appropriate action when exiting.
+ */
+ mask = SPU_STATUS_INVALID_INSTR |
+ SPU_STATUS_SINGLE_STEP |
+ SPU_STATUS_STOPPED_BY_HALT |
+ SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_RUNNING;
+ if (!(csa->prob.spu_status_R & mask)) {
+ csa->lscsa->stopped_status.slot[0] = SPU_STOPPED_STATUS_R;
+ }
+}
+
+static inline void restore_mfc_rag(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 29:
+ * Restore RA_GROUP_ID register and the
+ * RA_ENABLE reigster from the CSA.
+ */
+ spu_resource_allocation_groupID_set(spu,
+ csa->priv1.resource_allocation_groupID_RW);
+ spu_resource_allocation_enable_set(spu,
+ csa->priv1.resource_allocation_enable_RW);
+}
+
+static inline void send_restore_code(struct spu_state *csa, struct spu *spu)
+{
+ unsigned long addr = (unsigned long)&spu_restore_code[0];
+ unsigned int ls_offset = 0x0;
+ unsigned int size = sizeof(spu_restore_code);
+ unsigned int tag = 0;
+ unsigned int rclass = 0;
+ unsigned int cmd = MFC_GETFS_CMD;
+
+ /* Restore, Step 37:
+ * Issue MFC DMA command to copy context
+ * restore code to local storage.
+ */
+ send_mfc_dma(spu, addr, ls_offset, size, tag, rclass, cmd);
+}
+
+static inline void setup_decr(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 34:
+ * If CSA.MFC_CNTL[Ds]=1 (decrementer was
+ * running) then adjust decrementer, set
+ * decrementer running status in LSCSA,
+ * and set decrementer "wrapped" status
+ * in LSCSA.
+ */
+ if (csa->priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING) {
+ cycles_t resume_time = get_cycles();
+ cycles_t delta_time = resume_time - csa->suspend_time;
+
+ csa->lscsa->decr.slot[0] = delta_time;
+ }
+}
+
+static inline void setup_ppu_mb(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 35:
+ * Copy the CSA.PU_MB data into the LSCSA.
+ */
+ csa->lscsa->ppu_mb.slot[0] = csa->prob.pu_mb_R;
+}
+
+static inline void setup_ppuint_mb(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 36:
+ * Copy the CSA.PUINT_MB data into the LSCSA.
+ */
+ csa->lscsa->ppuint_mb.slot[0] = csa->priv2.puint_mb_R;
+}
+
+static inline int check_restore_status(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 complete;
+
+ /* Restore, Step 40:
+ * If SPU_Status[P]=1 and SPU_Status[SC] = "success",
+ * context restore succeeded, otherwise context restore
+ * failed.
+ */
+ complete = ((SPU_RESTORE_COMPLETE << SPU_STOP_STATUS_SHIFT) |
+ SPU_STATUS_STOPPED_BY_STOP);
+ return (in_be32(&prob->spu_status_R) != complete) ? 1 : 0;
+}
+
+static inline void restore_spu_privcntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 41:
+ * Restore SPU_PrivCntl from the CSA.
+ */
+ out_be64(&priv2->spu_privcntl_RW, csa->priv2.spu_privcntl_RW);
+ eieio();
+}
+
+static inline void restore_status_part1(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 mask;
+
+ /* Restore, Step 42:
+ * If any CSA.SPU_Status[I,S,H,P]=1, then
+ * restore the error or single step state.
+ */
+ mask = SPU_STATUS_INVALID_INSTR |
+ SPU_STATUS_SINGLE_STEP |
+ SPU_STATUS_STOPPED_BY_HALT | SPU_STATUS_STOPPED_BY_STOP;
+ if (csa->prob.spu_status_R & mask) {
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_RUNNABLE);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+}
+
+static inline void restore_status_part2(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 mask;
+
+ /* Restore, Step 43:
+ * If all CSA.SPU_Status[I,S,H,P,R]=0 then write
+ * SPU_RunCntl[R0R1]='01', wait for SPU_Status[R]=1,
+ * then write '00' to SPU_RunCntl[R0R1] and wait
+ * for SPU_Status[R]=0.
+ */
+ mask = SPU_STATUS_INVALID_INSTR |
+ SPU_STATUS_SINGLE_STEP |
+ SPU_STATUS_STOPPED_BY_HALT |
+ SPU_STATUS_STOPPED_BY_STOP | SPU_STATUS_RUNNING;
+ if (!(csa->prob.spu_status_R & mask)) {
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_RUNNABLE);
+ eieio();
+ POLL_WHILE_FALSE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ eieio();
+ POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) &
+ SPU_STATUS_RUNNING);
+ }
+}
+
+static inline void restore_ls_16kb(struct spu_state *csa, struct spu *spu)
+{
+ unsigned long addr = (unsigned long)&csa->lscsa->ls[0];
+ unsigned int ls_offset = 0x0;
+ unsigned int size = 16384;
+ unsigned int tag = 0;
+ unsigned int rclass = 0;
+ unsigned int cmd = MFC_GET_CMD;
+
+ /* Restore, Step 44:
+ * Issue a DMA command to restore the first
+ * 16kb of local storage from CSA.
+ */
+ send_mfc_dma(spu, addr, ls_offset, size, tag, rclass, cmd);
+}
+
+static inline void clear_interrupts(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 49:
+ * Write INT_MASK_class0 with value of 0.
+ * Write INT_MASK_class1 with value of 0.
+ * Write INT_MASK_class2 with value of 0.
+ * Write INT_STAT_class0 with value of -1.
+ * Write INT_STAT_class1 with value of -1.
+ * Write INT_STAT_class2 with value of -1.
+ */
+ spin_lock_irq(&spu->register_lock);
+ spu_int_mask_set(spu, 0, 0ul);
+ spu_int_mask_set(spu, 1, 0ul);
+ spu_int_mask_set(spu, 2, 0ul);
+ spu_int_stat_clear(spu, 0, ~0ul);
+ spu_int_stat_clear(spu, 1, ~0ul);
+ spu_int_stat_clear(spu, 2, ~0ul);
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static inline void restore_mfc_queues(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Restore, Step 50:
+ * If MFC_Cntl[Se]!=0 then restore
+ * MFC command queues.
+ */
+ if ((csa->priv2.mfc_control_RW & MFC_CNTL_DMA_QUEUES_EMPTY_MASK) == 0) {
+ for (i = 0; i < 8; i++) {
+ out_be64(&priv2->puq[i].mfc_cq_data0_RW,
+ csa->priv2.puq[i].mfc_cq_data0_RW);
+ out_be64(&priv2->puq[i].mfc_cq_data1_RW,
+ csa->priv2.puq[i].mfc_cq_data1_RW);
+ out_be64(&priv2->puq[i].mfc_cq_data2_RW,
+ csa->priv2.puq[i].mfc_cq_data2_RW);
+ out_be64(&priv2->puq[i].mfc_cq_data3_RW,
+ csa->priv2.puq[i].mfc_cq_data3_RW);
+ }
+ for (i = 0; i < 16; i++) {
+ out_be64(&priv2->spuq[i].mfc_cq_data0_RW,
+ csa->priv2.spuq[i].mfc_cq_data0_RW);
+ out_be64(&priv2->spuq[i].mfc_cq_data1_RW,
+ csa->priv2.spuq[i].mfc_cq_data1_RW);
+ out_be64(&priv2->spuq[i].mfc_cq_data2_RW,
+ csa->priv2.spuq[i].mfc_cq_data2_RW);
+ out_be64(&priv2->spuq[i].mfc_cq_data3_RW,
+ csa->priv2.spuq[i].mfc_cq_data3_RW);
+ }
+ }
+ eieio();
+}
+
+static inline void restore_ppu_querymask(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 51:
+ * Restore the PPU_QueryMask register from CSA.
+ */
+ out_be32(&prob->dma_querymask_RW, csa->prob.dma_querymask_RW);
+ eieio();
+}
+
+static inline void restore_ppu_querytype(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 52:
+ * Restore the PPU_QueryType register from CSA.
+ */
+ out_be32(&prob->dma_querytype_RW, csa->prob.dma_querytype_RW);
+ eieio();
+}
+
+static inline void restore_mfc_csr_tsq(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 53:
+ * Restore the MFC_CSR_TSQ register from CSA.
+ */
+ out_be64(&priv2->spu_tag_status_query_RW,
+ csa->priv2.spu_tag_status_query_RW);
+ eieio();
+}
+
+static inline void restore_mfc_csr_cmd(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 54:
+ * Restore the MFC_CSR_CMD1 and MFC_CSR_CMD2
+ * registers from CSA.
+ */
+ out_be64(&priv2->spu_cmd_buf1_RW, csa->priv2.spu_cmd_buf1_RW);
+ out_be64(&priv2->spu_cmd_buf2_RW, csa->priv2.spu_cmd_buf2_RW);
+ eieio();
+}
+
+static inline void restore_mfc_csr_ato(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 55:
+ * Restore the MFC_CSR_ATO register from CSA.
+ */
+ out_be64(&priv2->spu_atomic_status_RW, csa->priv2.spu_atomic_status_RW);
+}
+
+static inline void restore_mfc_tclass_id(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 56:
+ * Restore the MFC_TCLASS_ID register from CSA.
+ */
+ spu_mfc_tclass_id_set(spu, csa->priv1.mfc_tclass_id_RW);
+ eieio();
+}
+
+static inline void set_llr_event(struct spu_state *csa, struct spu *spu)
+{
+ u64 ch0_cnt, ch0_data;
+ u64 ch1_data;
+
+ /* Restore, Step 57:
+ * Set the Lock Line Reservation Lost Event by:
+ * 1. OR CSA.SPU_Event_Status with bit 21 (Lr) set to 1.
+ * 2. If CSA.SPU_Channel_0_Count=0 and
+ * CSA.SPU_Wr_Event_Mask[Lr]=1 and
+ * CSA.SPU_Event_Status[Lr]=0 then set
+ * CSA.SPU_Event_Status_Count=1.
+ */
+ ch0_cnt = csa->spu_chnlcnt_RW[0];
+ ch0_data = csa->spu_chnldata_RW[0];
+ ch1_data = csa->spu_chnldata_RW[1];
+ csa->spu_chnldata_RW[0] |= MFC_LLR_LOST_EVENT;
+ if ((ch0_cnt == 0) && !(ch0_data & MFC_LLR_LOST_EVENT) &&
+ (ch1_data & MFC_LLR_LOST_EVENT)) {
+ csa->spu_chnlcnt_RW[0] = 1;
+ }
+}
+
+static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 58:
+ * If the status of the CSA software decrementer
+ * "wrapped" flag is set, OR in a '1' to
+ * CSA.SPU_Event_Status[Tm].
+ */
+ if (csa->lscsa->decr_status.slot[0] == 1) {
+ csa->spu_chnldata_RW[0] |= 0x20;
+ }
+ if ((csa->lscsa->decr_status.slot[0] == 1) &&
+ (csa->spu_chnlcnt_RW[0] == 0 &&
+ ((csa->spu_chnldata_RW[2] & 0x20) == 0x0) &&
+ ((csa->spu_chnldata_RW[0] & 0x20) != 0x1))) {
+ csa->spu_chnlcnt_RW[0] = 1;
+ }
+}
+
+static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+ int i;
+
+ /* Restore, Step 59:
+ * Restore the following CH: [0,1,3,4,24,25,27]
+ */
+ for (i = 0; i < 7; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[idx]);
+ out_be64(&priv2->spu_chnlcnt_RW, csa->spu_chnlcnt_RW[idx]);
+ eieio();
+ }
+}
+
+static inline void restore_ch_part2(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 ch_indices[3] = { 9UL, 21UL, 23UL };
+ u64 ch_counts[3] = { 1UL, 16UL, 1UL };
+ u64 idx;
+ int i;
+
+ /* Restore, Step 60:
+ * Restore the following CH: [9,21,23].
+ */
+ ch_counts[0] = 1UL;
+ ch_counts[1] = csa->spu_chnlcnt_RW[21];
+ ch_counts[2] = 1UL;
+ for (i = 0; i < 3; i++) {
+ idx = ch_indices[i];
+ out_be64(&priv2->spu_chnlcntptr_RW, idx);
+ eieio();
+ out_be64(&priv2->spu_chnlcnt_RW, ch_counts[i]);
+ eieio();
+ }
+}
+
+static inline void restore_spu_lslr(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 61:
+ * Restore the SPU_LSLR register from CSA.
+ */
+ out_be64(&priv2->spu_lslr_RW, csa->priv2.spu_lslr_RW);
+ eieio();
+}
+
+static inline void restore_spu_cfg(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 62:
+ * Restore the SPU_Cfg register from CSA.
+ */
+ out_be64(&priv2->spu_cfg_RW, csa->priv2.spu_cfg_RW);
+ eieio();
+}
+
+static inline void restore_pm_trace(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 63:
+ * Restore PM_Trace_Tag_Wait_Mask from CSA.
+ * Not performed by this implementation.
+ */
+}
+
+static inline void restore_spu_npc(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 64:
+ * Restore SPU_NPC from CSA.
+ */
+ out_be32(&prob->spu_npc_RW, csa->prob.spu_npc_RW);
+ eieio();
+}
+
+static inline void restore_spu_mb(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Restore, Step 65:
+ * Restore MFC_RdSPU_MB from CSA.
+ */
+ out_be64(&priv2->spu_chnlcntptr_RW, 29UL);
+ eieio();
+ out_be64(&priv2->spu_chnlcnt_RW, csa->spu_chnlcnt_RW[29]);
+ for (i = 0; i < 4; i++) {
+ out_be64(&priv2->spu_chnldata_RW, csa->spu_mailbox_data[i]);
+ }
+ eieio();
+}
+
+static inline void check_ppu_mb_stat(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+ u32 dummy = 0;
+
+ /* Restore, Step 66:
+ * If CSA.MB_Stat[P]=0 (mailbox empty) then
+ * read from the PPU_MB register.
+ */
+ if ((csa->prob.mb_stat_R & 0xFF) == 0) {
+ dummy = in_be32(&prob->pu_mb_R);
+ eieio();
+ }
+}
+
+static inline void check_ppuint_mb_stat(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ u64 dummy = 0UL;
+
+ /* Restore, Step 66:
+ * If CSA.MB_Stat[I]=0 (mailbox empty) then
+ * read from the PPUINT_MB register.
+ */
+ if ((csa->prob.mb_stat_R & 0xFF0000) == 0) {
+ dummy = in_be64(&priv2->puint_mb_R);
+ eieio();
+ spu_int_stat_clear(spu, 2, CLASS2_ENABLE_MAILBOX_INTR);
+ eieio();
+ }
+}
+
+static inline void restore_mfc_slbs(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+ int i;
+
+ /* Restore, Step 68:
+ * If MFC_SR1[R]='1', restore SLBs from CSA.
+ */
+ if (csa->priv1.mfc_sr1_RW & MFC_STATE1_RELOCATE_MASK) {
+ for (i = 0; i < 8; i++) {
+ out_be64(&priv2->slb_index_W, i);
+ eieio();
+ out_be64(&priv2->slb_esid_RW, csa->slb_esid_RW[i]);
+ out_be64(&priv2->slb_vsid_RW, csa->slb_vsid_RW[i]);
+ eieio();
+ }
+ out_be64(&priv2->slb_index_W, csa->priv2.slb_index_W);
+ eieio();
+ }
+}
+
+static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 69:
+ * Restore the MFC_SR1 register from CSA.
+ */
+ spu_mfc_sr1_set(spu, csa->priv1.mfc_sr1_RW);
+ eieio();
+}
+
+static inline void restore_other_spu_access(struct spu_state *csa,
+ struct spu *spu)
+{
+ /* Restore, Step 70:
+ * Restore other SPU mappings to this SPU. TBD.
+ */
+}
+
+static inline void restore_spu_runcntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_problem __iomem *prob = spu->problem;
+
+ /* Restore, Step 71:
+ * If CSA.SPU_Status[R]=1 then write
+ * SPU_RunCntl[R0R1]='01'.
+ */
+ if (csa->prob.spu_status_R & SPU_STATUS_RUNNING) {
+ out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_RUNNABLE);
+ eieio();
+ }
+}
+
+static inline void restore_mfc_cntl(struct spu_state *csa, struct spu *spu)
+{
+ struct spu_priv2 __iomem *priv2 = spu->priv2;
+
+ /* Restore, Step 72:
+ * Restore the MFC_CNTL register for the CSA.
+ */
+ out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW);
+ eieio();
+}
+
+static inline void enable_user_access(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 73:
+ * Enable user-space access (if provided) to this
+ * SPU by mapping the virtual pages assigned to
+ * the SPU memory-mapped I/O (MMIO) for problem
+ * state. TBD.
+ */
+}
+
+static inline void reset_switch_active(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 74:
+ * Reset the "context switch active" flag.
+ */
+ clear_bit(SPU_CONTEXT_SWITCH_ACTIVE, &spu->flags);
+ mb();
+}
+
+static inline void reenable_interrupts(struct spu_state *csa, struct spu *spu)
+{
+ /* Restore, Step 75:
+ * Re-enable SPU interrupts.
+ */
+ spin_lock_irq(&spu->register_lock);
+ spu_int_mask_set(spu, 0, csa->priv1.int_mask_class0_RW);
+ spu_int_mask_set(spu, 1, csa->priv1.int_mask_class1_RW);
+ spu_int_mask_set(spu, 2, csa->priv1.int_mask_class2_RW);
+ spin_unlock_irq(&spu->register_lock);
+}
+
+static int quiece_spu(struct spu_state *prev, struct spu *spu)
+{
+ /*
+ * Combined steps 2-18 of SPU context save sequence, which
+ * quiesce the SPU state (disable SPU execution, MFC command
+ * queues, decrementer, SPU interrupts, etc.).
+ *
+ * Returns 0 on success.
+ * 2 if failed step 2.
+ * 6 if failed step 6.
+ */
+
+ if (check_spu_isolate(prev, spu)) { /* Step 2. */
+ return 2;
+ }
+ disable_interrupts(prev, spu); /* Step 3. */
+ set_watchdog_timer(prev, spu); /* Step 4. */
+ inhibit_user_access(prev, spu); /* Step 5. */
+ if (check_spu_isolate(prev, spu)) { /* Step 6. */
+ return 6;
+ }
+ set_switch_pending(prev, spu); /* Step 7. */
+ save_mfc_cntl(prev, spu); /* Step 8. */
+ save_spu_runcntl(prev, spu); /* Step 9. */
+ save_mfc_sr1(prev, spu); /* Step 10. */
+ save_spu_status(prev, spu); /* Step 11. */
+ save_mfc_decr(prev, spu); /* Step 12. */
+ halt_mfc_decr(prev, spu); /* Step 13. */
+ save_timebase(prev, spu); /* Step 14. */
+ remove_other_spu_access(prev, spu); /* Step 15. */
+ do_mfc_mssync(prev, spu); /* Step 16. */
+ issue_mfc_tlbie(prev, spu); /* Step 17. */
+ handle_pending_interrupts(prev, spu); /* Step 18. */
+
+ return 0;
+}
+
+static void save_csa(struct spu_state *prev, struct spu *spu)
+{
+ /*
+ * Combine steps 19-44 of SPU context save sequence, which
+ * save regions of the privileged & problem state areas.
+ */
+
+ save_mfc_queues(prev, spu); /* Step 19. */
+ save_ppu_querymask(prev, spu); /* Step 20. */
+ save_ppu_querytype(prev, spu); /* Step 21. */
+ save_mfc_csr_tsq(prev, spu); /* Step 22. */
+ save_mfc_csr_cmd(prev, spu); /* Step 23. */
+ save_mfc_csr_ato(prev, spu); /* Step 24. */
+ save_mfc_tclass_id(prev, spu); /* Step 25. */
+ set_mfc_tclass_id(prev, spu); /* Step 26. */
+ purge_mfc_queue(prev, spu); /* Step 27. */
+ wait_purge_complete(prev, spu); /* Step 28. */
+ save_mfc_slbs(prev, spu); /* Step 29. */
+ setup_mfc_sr1(prev, spu); /* Step 30. */
+ save_spu_npc(prev, spu); /* Step 31. */
+ save_spu_privcntl(prev, spu); /* Step 32. */
+ reset_spu_privcntl(prev, spu); /* Step 33. */
+ save_spu_lslr(prev, spu); /* Step 34. */
+ reset_spu_lslr(prev, spu); /* Step 35. */
+ save_spu_cfg(prev, spu); /* Step 36. */
+ save_pm_trace(prev, spu); /* Step 37. */
+ save_mfc_rag(prev, spu); /* Step 38. */
+ save_ppu_mb_stat(prev, spu); /* Step 39. */
+ save_ppu_mb(prev, spu); /* Step 40. */
+ save_ppuint_mb(prev, spu); /* Step 41. */
+ save_ch_part1(prev, spu); /* Step 42. */
+ save_spu_mb(prev, spu); /* Step 43. */
+ save_mfc_cmd(prev, spu); /* Step 44. */
+ reset_ch(prev, spu); /* Step 45. */
+}
+
+static void save_lscsa(struct spu_state *prev, struct spu *spu)
+{
+ /*
+ * Perform steps 46-57 of SPU context save sequence,
+ * which save regions of the local store and register
+ * file.
+ */
+
+ resume_mfc_queue(prev, spu); /* Step 46. */
+ setup_mfc_slbs(prev, spu); /* Step 47. */
+ set_switch_active(prev, spu); /* Step 48. */
+ enable_interrupts(prev, spu); /* Step 49. */
+ save_ls_16kb(prev, spu); /* Step 50. */
+ set_spu_npc(prev, spu); /* Step 51. */
+ set_signot1(prev, spu); /* Step 52. */
+ set_signot2(prev, spu); /* Step 53. */
+ send_save_code(prev, spu); /* Step 54. */
+ set_ppu_querymask(prev, spu); /* Step 55. */
+ wait_tag_complete(prev, spu); /* Step 56. */
+ wait_spu_stopped(prev, spu); /* Step 57. */
+}
+
+static void harvest(struct spu_state *prev, struct spu *spu)
+{
+ /*
+ * Perform steps 2-25 of SPU context restore sequence,
+ * which resets an SPU either after a failed save, or
+ * when using SPU for first time.
+ */
+
+ disable_interrupts(prev, spu); /* Step 2. */
+ inhibit_user_access(prev, spu); /* Step 3. */
+ terminate_spu_app(prev, spu); /* Step 4. */
+ set_switch_pending(prev, spu); /* Step 5. */
+ remove_other_spu_access(prev, spu); /* Step 6. */
+ suspend_mfc(prev, spu); /* Step 7. */
+ wait_suspend_mfc_complete(prev, spu); /* Step 8. */
+ if (!suspend_spe(prev, spu)) /* Step 9. */
+ clear_spu_status(prev, spu); /* Step 10. */
+ do_mfc_mssync(prev, spu); /* Step 11. */
+ issue_mfc_tlbie(prev, spu); /* Step 12. */
+ handle_pending_interrupts(prev, spu); /* Step 13. */
+ purge_mfc_queue(prev, spu); /* Step 14. */
+ wait_purge_complete(prev, spu); /* Step 15. */
+ reset_spu_privcntl(prev, spu); /* Step 16. */
+ reset_spu_lslr(prev, spu); /* Step 17. */
+ setup_mfc_sr1(prev, spu); /* Step 18. */
+ invalidate_slbs(prev, spu); /* Step 19. */
+ reset_ch_part1(prev, spu); /* Step 20. */
+ reset_ch_part2(prev, spu); /* Step 21. */
+ enable_interrupts(prev, spu); /* Step 22. */
+ set_switch_active(prev, spu); /* Step 23. */
+ set_mfc_tclass_id(prev, spu); /* Step 24. */
+ resume_mfc_queue(prev, spu); /* Step 25. */
+}
+
+static void restore_lscsa(struct spu_state *next, struct spu *spu)
+{
+ /*
+ * Perform steps 26-40 of SPU context restore sequence,
+ * which restores regions of the local store and register
+ * file.
+ */
+
+ set_watchdog_timer(next, spu); /* Step 26. */
+ setup_spu_status_part1(next, spu); /* Step 27. */
+ setup_spu_status_part2(next, spu); /* Step 28. */
+ restore_mfc_rag(next, spu); /* Step 29. */
+ setup_mfc_slbs(next, spu); /* Step 30. */
+ set_spu_npc(next, spu); /* Step 31. */
+ set_signot1(next, spu); /* Step 32. */
+ set_signot2(next, spu); /* Step 33. */
+ setup_decr(next, spu); /* Step 34. */
+ setup_ppu_mb(next, spu); /* Step 35. */
+ setup_ppuint_mb(next, spu); /* Step 36. */
+ send_restore_code(next, spu); /* Step 37. */
+ set_ppu_querymask(next, spu); /* Step 38. */
+ wait_tag_complete(next, spu); /* Step 39. */
+ wait_spu_stopped(next, spu); /* Step 40. */
+}
+
+static void restore_csa(struct spu_state *next, struct spu *spu)
+{
+ /*
+ * Combine steps 41-76 of SPU context restore sequence, which
+ * restore regions of the privileged & problem state areas.
+ */
+
+ restore_spu_privcntl(next, spu); /* Step 41. */
+ restore_status_part1(next, spu); /* Step 42. */
+ restore_status_part2(next, spu); /* Step 43. */
+ restore_ls_16kb(next, spu); /* Step 44. */
+ wait_tag_complete(next, spu); /* Step 45. */
+ suspend_mfc(next, spu); /* Step 46. */
+ wait_suspend_mfc_complete(next, spu); /* Step 47. */
+ issue_mfc_tlbie(next, spu); /* Step 48. */
+ clear_interrupts(next, spu); /* Step 49. */
+ restore_mfc_queues(next, spu); /* Step 50. */
+ restore_ppu_querymask(next, spu); /* Step 51. */
+ restore_ppu_querytype(next, spu); /* Step 52. */
+ restore_mfc_csr_tsq(next, spu); /* Step 53. */
+ restore_mfc_csr_cmd(next, spu); /* Step 54. */
+ restore_mfc_csr_ato(next, spu); /* Step 55. */
+ restore_mfc_tclass_id(next, spu); /* Step 56. */
+ set_llr_event(next, spu); /* Step 57. */
+ restore_decr_wrapped(next, spu); /* Step 58. */
+ restore_ch_part1(next, spu); /* Step 59. */
+ restore_ch_part2(next, spu); /* Step 60. */
+ restore_spu_lslr(next, spu); /* Step 61. */
+ restore_spu_cfg(next, spu); /* Step 62. */
+ restore_pm_trace(next, spu); /* Step 63. */
+ restore_spu_npc(next, spu); /* Step 64. */
+ restore_spu_mb(next, spu); /* Step 65. */
+ check_ppu_mb_stat(next, spu); /* Step 66. */
+ check_ppuint_mb_stat(next, spu); /* Step 67. */
+ restore_mfc_slbs(next, spu); /* Step 68. */
+ restore_mfc_sr1(next, spu); /* Step 69. */
+ restore_other_spu_access(next, spu); /* Step 70. */
+ restore_spu_runcntl(next, spu); /* Step 71. */
+ restore_mfc_cntl(next, spu); /* Step 72. */
+ enable_user_access(next, spu); /* Step 73. */
+ reset_switch_active(next, spu); /* Step 74. */
+ reenable_interrupts(next, spu); /* Step 75. */
+}
+
+static int __do_spu_save(struct spu_state *prev, struct spu *spu)
+{
+ int rc;
+
+ /*
+ * SPU context save can be broken into three phases:
+ *
+ * (a) quiesce [steps 2-16].
+ * (b) save of CSA, performed by PPE [steps 17-42]
+ * (c) save of LSCSA, mostly performed by SPU [steps 43-52].
+ *
+ * Returns 0 on success.
+ * 2,6 if failed to quiece SPU
+ * 53 if SPU-side of save failed.
+ */
+
+ rc = quiece_spu(prev, spu); /* Steps 2-16. */
+ switch (rc) {
+ default:
+ case 2:
+ case 6:
+ harvest(prev, spu);
+ return rc;
+ break;
+ case 0:
+ break;
+ }
+ save_csa(prev, spu); /* Steps 17-43. */
+ save_lscsa(prev, spu); /* Steps 44-53. */
+ return check_save_status(prev, spu); /* Step 54. */
+}
+
+static int __do_spu_restore(struct spu_state *next, struct spu *spu)
+{
+ int rc;
+
+ /*
+ * SPU context restore can be broken into three phases:
+ *
+ * (a) harvest (or reset) SPU [steps 2-24].
+ * (b) restore LSCSA [steps 25-40], mostly performed by SPU.
+ * (c) restore CSA [steps 41-76], performed by PPE.
+ *
+ * The 'harvest' step is not performed here, but rather
+ * as needed below.
+ */
+
+ restore_lscsa(next, spu); /* Steps 24-39. */
+ rc = check_restore_status(next, spu); /* Step 40. */
+ switch (rc) {
+ default:
+ /* Failed. Return now. */
+ return rc;
+ break;
+ case 0:
+ /* Fall through to next step. */
+ break;
+ }
+ restore_csa(next, spu);
+
+ return 0;
+}
+
+/**
+ * spu_save - SPU context save, with locking.
+ * @prev: pointer to SPU context save area, to be saved.
+ * @spu: pointer to SPU iomem structure.
+ *
+ * Acquire locks, perform the save operation then return.
+ */
+int spu_save(struct spu_state *prev, struct spu *spu)
+{
+ int rc;
+
+ acquire_spu_lock(spu); /* Step 1. */
+ rc = __do_spu_save(prev, spu); /* Steps 2-53. */
+ release_spu_lock(spu);
+ if (rc) {
+ panic("%s failed on SPU[%d], rc=%d.\n",
+ __func__, spu->number, rc);
+ }
+ return rc;
+}
+
+/**
+ * spu_restore - SPU context restore, with harvest and locking.
+ * @new: pointer to SPU context save area, to be restored.
+ * @spu: pointer to SPU iomem structure.
+ *
+ * Perform harvest + restore, as we may not be coming
+ * from a previous succesful save operation, and the
+ * hardware state is unknown.
+ */
+int spu_restore(struct spu_state *new, struct spu *spu)
+{
+ int rc;
+
+ acquire_spu_lock(spu);
+ harvest(NULL, spu);
+ spu->stop_code = 0;
+ spu->dar = 0;
+ spu->dsisr = 0;
+ spu->slb_replace = 0;
+ spu->class_0_pending = 0;
+ rc = __do_spu_restore(new, spu);
+ release_spu_lock(spu);
+ if (rc) {
+ panic("%s failed on SPU[%d] rc=%d.\n",
+ __func__, spu->number, rc);
+ }
+ return rc;
+}
+
+/**
+ * spu_harvest - SPU harvest (reset) operation
+ * @spu: pointer to SPU iomem structure.
+ *
+ * Perform SPU harvest (reset) operation.
+ */
+void spu_harvest(struct spu *spu)
+{
+ acquire_spu_lock(spu);
+ harvest(NULL, spu);
+ release_spu_lock(spu);
+}
+
+static void init_prob(struct spu_state *csa)
+{
+ csa->spu_chnlcnt_RW[9] = 1;
+ csa->spu_chnlcnt_RW[21] = 16;
+ csa->spu_chnlcnt_RW[23] = 1;
+ csa->spu_chnlcnt_RW[28] = 1;
+ csa->spu_chnlcnt_RW[30] = 1;
+ csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP;
+}
+
+static void init_priv1(struct spu_state *csa)
+{
+ /* Enable decode, relocate, tlbie response, master runcntl. */
+ csa->priv1.mfc_sr1_RW = MFC_STATE1_LOCAL_STORAGE_DECODE_MASK |
+ MFC_STATE1_MASTER_RUN_CONTROL_MASK |
+ MFC_STATE1_PROBLEM_STATE_MASK |
+ MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK;
+
+ /* Set storage description. */
+ csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1);
+
+ /* Enable OS-specific set of interrupts. */
+ csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR |
+ CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR |
+ CLASS0_ENABLE_SPU_ERROR_INTR;
+ csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR |
+ CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR |
+ CLASS2_ENABLE_SPU_HALT_INTR;
+}
+
+static void init_priv2(struct spu_state *csa)
+{
+ csa->priv2.spu_lslr_RW = LS_ADDR_MASK;
+ csa->priv2.mfc_control_RW = MFC_CNTL_RESUME_DMA_QUEUE |
+ MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION |
+ MFC_CNTL_DMA_QUEUES_EMPTY_MASK;
+}
+
+/**
+ * spu_alloc_csa - allocate and initialize an SPU context save area.
+ *
+ * Allocate and initialize the contents of an SPU context save area.
+ * This includes enabling address translation, interrupt masks, etc.,
+ * as appropriate for the given OS environment.
+ *
+ * Note that storage for the 'lscsa' is allocated separately,
+ * as it is by far the largest of the context save regions,
+ * and may need to be pinned or otherwise specially aligned.
+ */
+void spu_init_csa(struct spu_state *csa)
+{
+ struct spu_lscsa *lscsa;
+ unsigned char *p;
+
+ if (!csa)
+ return;
+ memset(csa, 0, sizeof(struct spu_state));
+
+ lscsa = vmalloc(sizeof(struct spu_lscsa));
+ if (!lscsa)
+ return;
+
+ memset(lscsa, 0, sizeof(struct spu_lscsa));
+ csa->lscsa = lscsa;
+ csa->register_lock = SPIN_LOCK_UNLOCKED;
+
+ /* Set LS pages reserved to allow for user-space mapping. */
+ for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+ SetPageReserved(vmalloc_to_page(p));
+
+ init_prob(csa);
+ init_priv1(csa);
+ init_priv2(csa);
+}
+
+void spu_fini_csa(struct spu_state *csa)
+{
+ /* Clear reserved bit before vfree. */
+ unsigned char *p;
+ for (p = csa->lscsa->ls; p < csa->lscsa->ls + LS_SIZE; p += PAGE_SIZE)
+ ClearPageReserved(vmalloc_to_page(p));
+
+ vfree(csa->lscsa);
+}
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
new file mode 100644
index 000000000000..e6565a949ddc
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -0,0 +1,103 @@
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+
+#include <asm/uaccess.h>
+
+#include "spufs.h"
+
+/**
+ * sys_spu_run - run code loaded into an SPU
+ *
+ * @unpc: next program counter for the SPU
+ * @ustatus: status of the SPU
+ *
+ * This system call transfers the control of execution of a
+ * user space thread to an SPU. It will return when the
+ * SPU has finished executing or when it hits an error
+ * condition and it will be interrupted if a signal needs
+ * to be delivered to a handler in user space.
+ *
+ * The next program counter is set to the passed value
+ * before the SPU starts fetching code and the user space
+ * pointer gets updated with the new value when returning
+ * from kernel space.
+ *
+ * The status value returned from spu_run reflects the
+ * value of the spu_status register after the SPU has stopped.
+ *
+ */
+static long do_spu_run(struct file *filp,
+ __u32 __user *unpc,
+ __u32 __user *ustatus)
+{
+ long ret;
+ struct spufs_inode_info *i;
+ u32 npc, status;
+
+ ret = -EFAULT;
+ if (get_user(npc, unpc) || get_user(status, ustatus))
+ goto out;
+
+ /* check if this file was created by spu_create */
+ ret = -EINVAL;
+ if (filp->f_op != &spufs_context_fops)
+ goto out;
+
+ i = SPUFS_I(filp->f_dentry->d_inode);
+ ret = spufs_run_spu(filp, i->i_ctx, &npc, &status);
+
+ if (put_user(npc, unpc) || put_user(status, ustatus))
+ ret = -EFAULT;
+out:
+ return ret;
+}
+
+#ifndef MODULE
+asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
+{
+ int fput_needed;
+ struct file *filp;
+ long ret;
+
+ ret = -EBADF;
+ filp = fget_light(fd, &fput_needed);
+ if (filp) {
+ ret = do_spu_run(filp, unpc, ustatus);
+ fput_light(filp, fput_needed);
+ }
+
+ return ret;
+}
+#endif
+
+asmlinkage long sys_spu_create(const char __user *pathname,
+ unsigned int flags, mode_t mode)
+{
+ char *tmp;
+ int ret;
+
+ tmp = getname(pathname);
+ ret = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+ struct nameidata nd;
+
+ ret = path_lookup(tmp, LOOKUP_PARENT|
+ LOOKUP_OPEN|LOOKUP_CREATE, &nd);
+ if (!ret) {
+ ret = spufs_create_thread(&nd, flags, mode);
+ path_release(&nd);
+ }
+ putname(tmp);
+ }
+
+ return ret;
+}
+
+struct spufs_calls spufs_calls = {
+ .create_thread = sys_spu_create,
+ .spu_run = do_spu_run,
+ .owner = THIS_MODULE,
+};
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c
index 82c429d487f3..00c52f27ef4f 100644
--- a/arch/powerpc/platforms/chrp/pci.c
+++ b/arch/powerpc/platforms/chrp/pci.c
@@ -135,12 +135,13 @@ int __init
hydra_init(void)
{
struct device_node *np;
+ struct resource r;
np = find_devices("mac-io");
- if (np == NULL || np->n_addrs == 0)
+ if (np == NULL || of_address_to_resource(np, 0, &r))
return 0;
- Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
- printk("Hydra Mac I/O at %lx\n", np->addrs[0].address);
+ Hydra = ioremap(r.start, r.end-r.start);
+ printk("Hydra Mac I/O at %lx\n", r.start);
printk("Hydra Feature_Control was %x",
in_le32(&Hydra->Feature_Control));
out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
@@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev)
{
u32 __iomem *reg;
u32 val;
- unsigned long addr = dev->addrs[0].address;
+ struct resource r;
- setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010);
+ if (of_address_to_resource(dev, 0, &r)) {
+ printk(KERN_ERR "No address for Python PCI controller\n");
+ return;
+ }
/* Clear the magic go-slow bit */
- reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40);
+ reg = ioremap(r.start + 0xf6000, 0x40);
+ BUG_ON(!reg);
val = in_be32(&reg[12]);
if (val & PRG_CL_RESET_VALID) {
out_be32(&reg[12], val & ~PRG_CL_RESET_VALID);
in_be32(&reg[12]);
}
iounmap(reg);
+
+ setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010);
}
/* Marvell Discovery II based Pegasos 2 */
@@ -218,7 +225,7 @@ chrp_find_bridges(void)
char *model, *machine;
int is_longtrail = 0, is_mot = 0, is_pegasos = 0;
struct device_node *root = find_path_device("/");
-
+ struct resource r;
/*
* The PCI host bridge nodes on some machines don't have
* properties to adequately identify them, so we have to
@@ -238,7 +245,7 @@ chrp_find_bridges(void)
continue;
++index;
/* The GG2 bridge on the LongTrail doesn't have an address */
- if (dev->n_addrs < 1 && !is_longtrail) {
+ if (of_address_to_resource(dev, 0, &r) && !is_longtrail) {
printk(KERN_WARNING "Can't use %s: no address\n",
dev->full_name);
continue;
@@ -255,8 +262,8 @@ chrp_find_bridges(void)
printk(KERN_INFO "PCI buses %d..%d",
bus_range[0], bus_range[1]);
printk(" controlled by %s", dev->type);
- if (dev->n_addrs > 0)
- printk(" at %lx", dev->addrs[0].address);
+ if (!is_longtrail)
+ printk(" at %lx", r.start);
printk("\n");
hose = pcibios_alloc_controller();
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index dda5f2c72c25..2dc87aa5962f 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -49,7 +49,6 @@
#include <asm/hydra.h>
#include <asm/sections.h>
#include <asm/time.h>
-#include <asm/btext.h>
#include <asm/i8259.h>
#include <asm/mpic.h>
#include <asm/rtas.h>
@@ -58,7 +57,6 @@
#include "chrp.h"
void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
int _chrp_type;
EXPORT_SYMBOL(_chrp_type);
@@ -264,11 +262,6 @@ void __init chrp_setup_arch(void)
ppc_md.set_rtc_time = rtas_set_rtc_time;
}
-#ifdef CONFIG_BOOTX_TEXT
- if (ppc_md.progress == NULL && boot_text_mapped)
- ppc_md.progress = btext_progress;
-#endif
-
#ifdef CONFIG_BLK_DEV_INITRD
/* this is fine for chrp */
initrd_below_start_ok = 1;
@@ -359,9 +352,10 @@ static void __init chrp_find_openpic(void)
opaddr = opprop[na-1]; /* assume 32-bit */
oplen /= na * sizeof(unsigned int);
} else {
- if (np->n_addrs == 0)
+ struct resource r;
+ if (of_address_to_resource(np, 0, &r))
return;
- opaddr = np->addrs[0].address;
+ opaddr = r.start;
oplen = 0;
}
@@ -384,7 +378,7 @@ static void __init chrp_find_openpic(void)
*/
if (oplen < len) {
printk(KERN_ERR "Insufficient addresses for distributed"
- " OpenPIC (%d < %d)\n", np->n_addrs, len);
+ " OpenPIC (%d < %d)\n", oplen, len);
len = oplen;
}
@@ -522,12 +516,3 @@ void __init chrp_init(void)
smp_ops = &chrp_smp_ops;
#endif /* CONFIG_SMP */
}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
- btext_drawstring(s);
- btext_drawstring("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c
index 737ee5d9f0aa..36a0f97bb7b1 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -21,6 +21,7 @@
#include <linux/mc146818rtc.h>
#include <linux/init.h>
#include <linux/bcd.h>
+#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/nvram.h>
@@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA;
long __init chrp_time_init(void)
{
struct device_node *rtcs;
+ struct resource r;
int base;
rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
if (rtcs == NULL)
rtcs = find_compatible_devices("rtc", "ds1385-rtc");
- if (rtcs == NULL || rtcs->addrs == NULL)
+ if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r))
return 0;
- base = rtcs->addrs[0].address;
+
+ base = r.start;
nvram_as1 = 0;
nvram_as0 = base;
nvram_data = base + 1;
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 81250090f98d..4fdbc9ae876b 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -144,16 +144,6 @@ config LITE5200
much but it's only been tested on this board version. I think this
board is also known as IceCube.
-config MPC834x_SYS
- bool "Freescale 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
@@ -192,14 +182,6 @@ config 8272
The MPC8272 CPM has a different internal dpram setup than other CPM2
devices
-config 83xx
- bool
- default y if MPC834x_SYS
-
-config MPC834x
- bool
- default y if MPC834x_SYS
-
config CPM2
bool
depends on 8260 || MPC8560 || MPC8555
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 127b465308be..ce8c0b943fa0 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,8 +1,8 @@
EXTRA_CFLAGS += -mno-minimal-toc
obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
- hvcall.o proc.o htab.o iommu.o misc.o
-obj-$(CONFIG_PCI) += pci.o irq.o vpdinfo.o
+ hvcall.o proc.o htab.o iommu.o misc.o irq.o
+obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_VIOPATH) += viopath.o
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 2b54eeb2c899..bea0b703f409 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -34,6 +34,8 @@
#include <asm/pci-bridge.h>
#include <asm/iseries/hv_call_xm.h>
+#include "iommu.h"
+
extern struct list_head iSeries_Global_Device_List;
diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h
new file mode 100644
index 000000000000..cb5658fbe657
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/iommu.h
@@ -0,0 +1,35 @@
+#ifndef _PLATFORMS_ISERIES_IOMMU_H
+#define _PLATFORMS_ISERIES_IOMMU_H
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ */
+
+struct device_node;
+struct iommu_table;
+
+/* Creates table for an individual device node */
+extern void iommu_devnode_init_iSeries(struct device_node *dn);
+
+/* Get table parameters from HV */
+extern void iommu_table_getparms_iSeries(unsigned long busno,
+ unsigned char slotno, unsigned char virtbus,
+ struct iommu_table *tbl);
+
+#endif /* _PLATFORMS_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index a58daa153686..be3fbfc24e6c 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -35,161 +35,131 @@
#include <linux/irq.h>
#include <linux/spinlock.h>
+#include <asm/paca.h>
#include <asm/iseries/hv_types.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_lp_queue.h>
#include "irq.h"
#include "call_pci.h"
-static long Pci_Interrupt_Count;
-static long Pci_Event_Count;
-
-enum XmPciLpEvent_Subtype {
- XmPciLpEvent_BusCreated = 0, // PHB has been created
- XmPciLpEvent_BusError = 1, // PHB has failed
- XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
- XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
- XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
- XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
- XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
- XmPciLpEvent_BridgeError = 21, // Bridge Error
- XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
-};
+#if defined(CONFIG_SMP)
+extern void iSeries_smp_message_recv(struct pt_regs *);
+#endif
-struct XmPciLpEvent_BusInterrupt {
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
-};
+#ifdef CONFIG_PCI
-struct XmPciLpEvent_NodeInterrupt {
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
- HvAgentId deviceId;
+enum pci_event_type {
+ pe_bus_created = 0, /* PHB has been created */
+ pe_bus_error = 1, /* PHB has failed */
+ pe_bus_failed = 2, /* Msg to Secondary, Primary failed bus */
+ pe_node_failed = 4, /* Multi-adapter bridge has failed */
+ pe_node_recovered = 5, /* Multi-adapter bridge has recovered */
+ pe_bus_recovered = 12, /* PHB has been recovered */
+ pe_unquiese_bus = 18, /* Secondary bus unqiescing */
+ pe_bridge_error = 21, /* Bridge Error */
+ pe_slot_interrupt = 22 /* Slot interrupt */
};
-struct XmPciLpEvent {
- struct HvLpEvent hvLpEvent;
-
+struct pci_event {
+ struct HvLpEvent event;
union {
- u64 alignData; // Align on an 8-byte boundary
-
+ u64 __align; /* Align on an 8-byte boundary */
struct {
u32 fisr;
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
- HvAgentId deviceId;
- } slotInterrupt;
-
- struct XmPciLpEvent_BusInterrupt busFailed;
- struct XmPciLpEvent_BusInterrupt busRecovered;
- struct XmPciLpEvent_BusInterrupt busCreated;
-
- struct XmPciLpEvent_NodeInterrupt nodeFailed;
- struct XmPciLpEvent_NodeInterrupt nodeRecovered;
-
- } eventData;
-
+ HvBusNumber bus_number;
+ HvSubBusNumber sub_bus_number;
+ HvAgentId dev_id;
+ } slot;
+ struct {
+ HvBusNumber bus_number;
+ HvSubBusNumber sub_bus_number;
+ } bus;
+ struct {
+ HvBusNumber bus_number;
+ HvSubBusNumber sub_bus_number;
+ HvAgentId dev_id;
+ } node;
+ } data;
};
-static void intReceived(struct XmPciLpEvent *eventParm,
- struct pt_regs *regsParm)
+static DEFINE_SPINLOCK(pending_irqs_lock);
+static int num_pending_irqs;
+static int pending_irqs[NR_IRQS];
+
+static void int_received(struct pci_event *event, struct pt_regs *regs)
{
int irq;
-#ifdef CONFIG_IRQSTACKS
- struct thread_info *curtp, *irqtp;
-#endif
- ++Pci_Interrupt_Count;
-
- switch (eventParm->hvLpEvent.xSubtype) {
- case XmPciLpEvent_SlotInterrupt:
- irq = eventParm->hvLpEvent.xCorrelationToken;
- /* Dispatch the interrupt handlers for this irq */
-#ifdef CONFIG_IRQSTACKS
- /* Switch to the irq stack to handle this */
- curtp = current_thread_info();
- irqtp = hardirq_ctx[smp_processor_id()];
- if (curtp != irqtp) {
- irqtp->task = curtp->task;
- irqtp->flags = 0;
- call___do_IRQ(irq, regsParm, irqtp);
- irqtp->task = NULL;
- if (irqtp->flags)
- set_bits(irqtp->flags, &curtp->flags);
- } else
-#endif
- __do_IRQ(irq, regsParm);
- HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
- eventParm->eventData.slotInterrupt.subBusNumber,
- eventParm->eventData.slotInterrupt.deviceId);
+ switch (event->event.xSubtype) {
+ case pe_slot_interrupt:
+ irq = event->event.xCorrelationToken;
+ if (irq < NR_IRQS) {
+ spin_lock(&pending_irqs_lock);
+ pending_irqs[irq]++;
+ num_pending_irqs++;
+ spin_unlock(&pending_irqs_lock);
+ } else {
+ printk(KERN_WARNING "int_received: bad irq number %d\n",
+ irq);
+ HvCallPci_eoi(event->data.slot.bus_number,
+ event->data.slot.sub_bus_number,
+ event->data.slot.dev_id);
+ }
break;
/* Ignore error recovery events for now */
- case XmPciLpEvent_BusCreated:
- printk(KERN_INFO "intReceived: system bus %d created\n",
- eventParm->eventData.busCreated.busNumber);
+ case pe_bus_created:
+ printk(KERN_INFO "int_received: system bus %d created\n",
+ event->data.bus.bus_number);
break;
- case XmPciLpEvent_BusError:
- case XmPciLpEvent_BusFailed:
- printk(KERN_INFO "intReceived: system bus %d failed\n",
- eventParm->eventData.busFailed.busNumber);
+ case pe_bus_error:
+ case pe_bus_failed:
+ printk(KERN_INFO "int_received: system bus %d failed\n",
+ event->data.bus.bus_number);
break;
- case XmPciLpEvent_BusRecovered:
- case XmPciLpEvent_UnQuiesceBus:
- printk(KERN_INFO "intReceived: system bus %d recovered\n",
- eventParm->eventData.busRecovered.busNumber);
+ case pe_bus_recovered:
+ case pe_unquiese_bus:
+ printk(KERN_INFO "int_received: system bus %d recovered\n",
+ event->data.bus.bus_number);
break;
- case XmPciLpEvent_NodeFailed:
- case XmPciLpEvent_BridgeError:
+ case pe_node_failed:
+ case pe_bridge_error:
printk(KERN_INFO
- "intReceived: multi-adapter bridge %d/%d/%d failed\n",
- eventParm->eventData.nodeFailed.busNumber,
- eventParm->eventData.nodeFailed.subBusNumber,
- eventParm->eventData.nodeFailed.deviceId);
+ "int_received: multi-adapter bridge %d/%d/%d failed\n",
+ event->data.node.bus_number,
+ event->data.node.sub_bus_number,
+ event->data.node.dev_id);
break;
- case XmPciLpEvent_NodeRecovered:
+ case pe_node_recovered:
printk(KERN_INFO
- "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
- eventParm->eventData.nodeRecovered.busNumber,
- eventParm->eventData.nodeRecovered.subBusNumber,
- eventParm->eventData.nodeRecovered.deviceId);
+ "int_received: multi-adapter bridge %d/%d/%d recovered\n",
+ event->data.node.bus_number,
+ event->data.node.sub_bus_number,
+ event->data.node.dev_id);
break;
default:
printk(KERN_ERR
- "intReceived: unrecognized event subtype 0x%x\n",
- eventParm->hvLpEvent.xSubtype);
+ "int_received: unrecognized event subtype 0x%x\n",
+ event->event.xSubtype);
break;
}
}
-static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
- struct pt_regs *regsParm)
+static void pci_event_handler(struct HvLpEvent *event, struct pt_regs *regs)
{
-#ifdef CONFIG_PCI
- ++Pci_Event_Count;
-
- if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
- switch (eventParm->xFlags.xFunction) {
- case HvLpEvent_Function_Int:
- intReceived((struct XmPciLpEvent *)eventParm, regsParm);
- break;
- case HvLpEvent_Function_Ack:
+ if (event && (event->xType == HvLpEvent_Type_PciIo)) {
+ if (hvlpevent_is_int(event))
+ int_received((struct pci_event *)event, regs);
+ else
printk(KERN_ERR
- "XmPciLpEvent_handler: unexpected ack received\n");
- break;
- default:
- printk(KERN_ERR
- "XmPciLpEvent_handler: unexpected event function %d\n",
- (int)eventParm->xFlags.xFunction);
- break;
- }
- } else if (eventParm)
+ "pci_event_handler: unexpected ack received\n");
+ } else if (event)
printk(KERN_ERR
- "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
- (int)eventParm->xType);
+ "pci_event_handler: Unrecognized PCI event type 0x%x\n",
+ (int)event->xType);
else
- printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
-#endif
+ printk(KERN_ERR "pci_event_handler: NULL event received\n");
}
/*
@@ -199,20 +169,21 @@ static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
void __init iSeries_init_IRQ(void)
{
/* Register PCI event handler and open an event path */
- int xRc;
-
- xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
- &XmPciLpEvent_handler);
- if (xRc == 0) {
- xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
- if (xRc != 0)
- printk(KERN_ERR "iSeries_init_IRQ: open event path "
- "failed with rc 0x%x\n", xRc);
+ int ret;
+
+ ret = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+ &pci_event_handler);
+ if (ret == 0) {
+ ret = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+ if (ret != 0)
+ printk(KERN_ERR "iseries_init_IRQ: open event path "
+ "failed with rc 0x%x\n", ret);
} else
- printk(KERN_ERR "iSeries_init_IRQ: register handler "
- "failed with rc 0x%x\n", xRc);
+ printk(KERN_ERR "iseries_init_IRQ: register handler "
+ "failed with rc 0x%x\n", ret);
}
+#define REAL_IRQ_TO_SUBBUS(irq) (((irq) >> 14) & 0xff)
#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
@@ -221,40 +192,40 @@ void __init iSeries_init_IRQ(void)
* This will be called by device drivers (via enable_IRQ)
* to enable INTA in the bridge interrupt status register.
*/
-static void iSeries_enable_IRQ(unsigned int irq)
+static void iseries_enable_IRQ(unsigned int irq)
{
- u32 bus, deviceId, function, mask;
- const u32 subBus = 0;
+ u32 bus, dev_id, function, mask;
+ const u32 sub_bus = 0;
unsigned int rirq = virt_irq_to_real_map[irq];
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+ dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
/* Unmask secondary INTA */
mask = 0x80000000;
- HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+ HvCallPci_unmaskInterrupts(bus, sub_bus, dev_id, mask);
}
-/* This is called by iSeries_activate_IRQs */
-static unsigned int iSeries_startup_IRQ(unsigned int irq)
+/* This is called by iseries_activate_IRQs */
+static unsigned int iseries_startup_IRQ(unsigned int irq)
{
- u32 bus, deviceId, function, mask;
- const u32 subBus = 0;
+ u32 bus, dev_id, function, mask;
+ const u32 sub_bus = 0;
unsigned int rirq = virt_irq_to_real_map[irq];
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+ dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
/* Link the IRQ number to the bridge */
- HvCallXm_connectBusUnit(bus, subBus, deviceId, irq);
+ HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq);
/* Unmask bridge interrupts in the FISR */
mask = 0x01010000 << function;
- HvCallPci_unmaskFisr(bus, subBus, deviceId, mask);
- iSeries_enable_IRQ(irq);
+ HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
+ iseries_enable_IRQ(irq);
return 0;
}
@@ -279,78 +250,117 @@ void __init iSeries_activate_IRQs()
}
/* this is not called anywhere currently */
-static void iSeries_shutdown_IRQ(unsigned int irq)
+static void iseries_shutdown_IRQ(unsigned int irq)
{
- u32 bus, deviceId, function, mask;
- const u32 subBus = 0;
+ u32 bus, dev_id, function, mask;
+ const u32 sub_bus = 0;
unsigned int rirq = virt_irq_to_real_map[irq];
/* irq should be locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+ dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
/* Invalidate the IRQ number in the bridge */
- HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
+ HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0);
/* Mask bridge interrupts in the FISR */
mask = 0x01010000 << function;
- HvCallPci_maskFisr(bus, subBus, deviceId, mask);
+ HvCallPci_maskFisr(bus, sub_bus, dev_id, mask);
}
/*
* This will be called by device drivers (via disable_IRQ)
* to disable INTA in the bridge interrupt status register.
*/
-static void iSeries_disable_IRQ(unsigned int irq)
+static void iseries_disable_IRQ(unsigned int irq)
{
- u32 bus, deviceId, function, mask;
- const u32 subBus = 0;
+ u32 bus, dev_id, function, mask;
+ const u32 sub_bus = 0;
unsigned int rirq = virt_irq_to_real_map[irq];
/* The IRQ has already been locked by the caller */
bus = REAL_IRQ_TO_BUS(rirq);
function = REAL_IRQ_TO_FUNC(rirq);
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+ dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
/* Mask secondary INTA */
mask = 0x80000000;
- HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
+ HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
}
-/*
- * This does nothing because there is not enough information
- * provided to do the EOI HvCall. This is done by XmPciLpEvent.c
- */
-static void iSeries_end_IRQ(unsigned int irq)
+static void iseries_end_IRQ(unsigned int irq)
{
+ unsigned int rirq = virt_irq_to_real_map[irq];
+
+ HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
+ (REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
}
static hw_irq_controller iSeries_IRQ_handler = {
.typename = "iSeries irq controller",
- .startup = iSeries_startup_IRQ,
- .shutdown = iSeries_shutdown_IRQ,
- .enable = iSeries_enable_IRQ,
- .disable = iSeries_disable_IRQ,
- .end = iSeries_end_IRQ
+ .startup = iseries_startup_IRQ,
+ .shutdown = iseries_shutdown_IRQ,
+ .enable = iseries_enable_IRQ,
+ .disable = iseries_disable_IRQ,
+ .end = iseries_end_IRQ
};
/*
* This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
* It calculates the irq value for the slot.
- * Note that subBusNumber is always 0 (at the moment at least).
+ * Note that sub_bus is always 0 (at the moment at least).
*/
-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
- HvSubBusNumber subBusNumber, HvAgentId deviceId)
+int __init iSeries_allocate_IRQ(HvBusNumber bus,
+ HvSubBusNumber sub_bus, HvAgentId dev_id)
{
int virtirq;
unsigned int realirq;
- u8 idsel = (deviceId >> 4);
- u8 function = deviceId & 7;
+ u8 idsel = (dev_id >> 4);
+ u8 function = dev_id & 7;
- realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
+ realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
+ + function;
virtirq = virt_irq_create_mapping(realirq);
irq_desc[virtirq].handler = &iSeries_IRQ_handler;
return virtirq;
}
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Get the next pending IRQ.
+ */
+int iSeries_get_irq(struct pt_regs *regs)
+{
+ /* -2 means ignore this interrupt */
+ int irq = -2;
+
+#ifdef CONFIG_SMP
+ if (get_lppaca()->int_dword.fields.ipi_cnt) {
+ get_lppaca()->int_dword.fields.ipi_cnt = 0;
+ iSeries_smp_message_recv(regs);
+ }
+#endif /* CONFIG_SMP */
+ if (hvlpevent_is_pending())
+ process_hvlpevents(regs);
+
+#ifdef CONFIG_PCI
+ if (num_pending_irqs) {
+ spin_lock(&pending_irqs_lock);
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ if (pending_irqs[irq]) {
+ pending_irqs[irq]--;
+ num_pending_irqs--;
+ break;
+ }
+ }
+ spin_unlock(&pending_irqs_lock);
+ if (irq >= NR_IRQS)
+ irq = -2;
+ }
+#endif
+
+ return irq;
+}
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index 5f643f16ecc0..b9c801ba5a47 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -4,5 +4,6 @@
extern void iSeries_init_IRQ(void);
extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
extern void iSeries_activate_IRQs(void);
+extern int iSeries_get_irq(struct pt_regs *);
#endif /* _ISERIES_IRQ_H */
diff --git a/arch/powerpc/platforms/iseries/lpardata.c b/arch/powerpc/platforms/iseries/lpardata.c
index bb8c91537f35..438e2dba63b5 100644
--- a/arch/powerpc/platforms/iseries/lpardata.c
+++ b/arch/powerpc/platforms/iseries/lpardata.c
@@ -93,10 +93,7 @@ struct ItLpNaca itLpNaca = {
.xPirEnvironMode = 0, /* Piranha stuff */
.xPirConsoleMode = 0,
.xPirDasdMode = 0,
- .xLparInstalled = 0,
- .xSysPartitioned = 0,
- .xHwSyncedTBs = 0,
- .xIntProcUtilHmt = 0,
+ .flags = 0,
.xSpVpdFormat = 0,
.xIntProcRatio = 0,
.xPlicVrmIndex = 0, /* VRM index of PLIC */
@@ -225,3 +222,10 @@ struct ItVpdAreas itVpdAreas = {
0,0
}
};
+
+struct ItLpRegSave iseries_reg_save[] = {
+ [0 ... (NR_CPUS-1)] = {
+ .xDesc = 0xd397d9e2, /* "LpRS" */
+ .xSize = sizeof(struct ItLpRegSave),
+ },
+};
diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
index e9fb98bf895f..0b885300d1d1 100644
--- a/arch/powerpc/platforms/iseries/lpevents.c
+++ b/arch/powerpc/platforms/iseries/lpevents.c
@@ -53,7 +53,7 @@ static struct HvLpEvent * get_next_hvlpevent(void)
struct HvLpEvent * event;
event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
- if (event->xFlags.xValid) {
+ if (hvlpevent_is_valid(event)) {
/* rmb() needed only for weakly consistent machines (regatta) */
rmb();
/* Set pointer to next potential event */
@@ -84,7 +84,7 @@ int hvlpevent_is_pending(void)
next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
- return next_event->xFlags.xValid |
+ return hvlpevent_is_valid(next_event) ||
hvlpevent_queue.xPlicOverflowIntPending;
}
@@ -101,18 +101,18 @@ static void hvlpevent_clear_valid(struct HvLpEvent * event)
switch (extra) {
case 3:
tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
- tmp->xFlags.xValid = 0;
+ hvlpevent_invalidate(tmp);
case 2:
tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
- tmp->xFlags.xValid = 0;
+ hvlpevent_invalidate(tmp);
case 1:
tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
- tmp->xFlags.xValid = 0;
+ hvlpevent_invalidate(tmp);
}
mb();
- event->xFlags.xValid = 0;
+ hvlpevent_invalidate(event);
}
void process_hvlpevents(struct pt_regs *regs)
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index 49e7e4b85847..a41d8b78c0cd 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -251,10 +251,7 @@ static struct pending_event *new_pending_event(void)
}
memset(ev, 0, sizeof(struct pending_event));
hev = &ev->event.hp_lp_event;
- hev->xFlags.xValid = 1;
- hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
- hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
- hev->xFlags.xFunction = HvLpEvent_Function_Int;
+ hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | HV_LP_EVENT_INT;
hev->xType = HvLpEvent_Type_MachineFac;
hev->xSourceLp = HvLpConfig_getLpIndex();
hev->xTargetLp = primary_lp;
@@ -518,17 +515,10 @@ static void handle_ack(struct io_mf_lp_event *event)
static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
{
if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
- switch(event->xFlags.xFunction) {
- case HvLpEvent_Function_Ack:
+ if (hvlpevent_is_ack(event))
handle_ack((struct io_mf_lp_event *)event);
- break;
- case HvLpEvent_Function_Int:
+ else
handle_int((struct io_mf_lp_event *)event);
- break;
- default:
- printk(KERN_ERR "mf.c: non ack/int event received\n");
- break;
- }
} else
printk(KERN_ERR "mf.c: alien event received\n");
}
diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S
index dfe7aa1ba098..7641fc7e550a 100644
--- a/arch/powerpc/platforms/iseries/misc.S
+++ b/arch/powerpc/platforms/iseries/misc.S
@@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore)
/* Check pending interrupts */
/* A decrementer, IPI or PMC interrupt may have occurred
* while we were in the hypervisor (which enables) */
- ld r4,PACALPPACA+LPPACAANYINT(r13)
+ ld r4,PACALPPACAPTR(r13)
+ ld r4,LPPACAANYINT(r4)
cmpdi r4,0
beqlr
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index dafc518fbb83..a19833b880e4 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -43,6 +43,7 @@
#include "irq.h"
#include "pci.h"
#include "call_pci.h"
+#include "iommu.h"
extern unsigned long io_page_mask;
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index da26639190db..3f8790146b00 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -52,6 +52,7 @@
#include <asm/iseries/mf.h>
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
+#include <asm/udbg.h>
#include "naca.h"
#include "setup.h"
@@ -62,10 +63,8 @@
#include "call_sm.h"
#include "call_hpt.h"
-extern void hvlog(char *fmt, ...);
-
#ifdef DEBUG
-#define DBG(fmt...) hvlog(fmt)
+#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif
@@ -474,14 +473,6 @@ static unsigned long __init build_iSeries_Memory_Map(void)
printk("HPT absolute addr = %016lx, size = %dK\n",
chunk_to_addr(hptFirstChunk), hptSizeChunks * 256);
- ppc64_pft_size = __ilog2(hptSizePages * HW_PAGE_SIZE);
-
- /*
- * The actual hashed page table is in the hypervisor,
- * we have no direct access
- */
- htab_address = NULL;
-
/*
* Determine if absolute memory has any
* holes so that we can interpret the
@@ -547,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void)
*/
static void __init iSeries_setup_arch(void)
{
- if (get_paca()->lppaca.shared_proc) {
+ if (get_lppaca()->shared_proc) {
ppc_md.idle_loop = iseries_shared_idle;
printk(KERN_INFO "Using shared processor idle loop\n");
} else {
@@ -571,16 +562,6 @@ static void iSeries_show_cpuinfo(struct seq_file *m)
/*
* Document me.
- * and Implement me.
- */
-static int iSeries_get_irq(struct pt_regs *regs)
-{
- /* -2 means ignore this interrupt */
- return -2;
-}
-
-/*
- * Document me.
*/
static void iSeries_restart(char *cmd)
{
@@ -666,7 +647,7 @@ static void yield_shared_processor(void)
* The decrementer stops during the yield. Force a fake decrementer
* here and let the timer_interrupt code sort out the actual time.
*/
- get_paca()->lppaca.int_dword.fields.decr_int = 1;
+ get_lppaca()->int_dword.fields.decr_int = 1;
process_iSeries_events();
}
@@ -871,6 +852,11 @@ void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
dt_prop(dt, name, (char *)data, sizeof(u64) * n);
}
+void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
+{
+ dt_prop(dt, name, (char *)data, sizeof(u32) * n);
+}
+
void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
{
dt_prop(dt, name, NULL, 0);
@@ -882,6 +868,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
unsigned char *p;
unsigned int i, index;
struct IoHriProcessorVpd *d;
+ u32 pft_size[2];
/* yuck */
snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
@@ -892,8 +879,11 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_prop_u32(dt, "#address-cells", 1);
dt_prop_u32(dt, "#size-cells", 0);
+ pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */
+ pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
for (i = 0; i < NR_CPUS; i++) {
- if (paca[i].lppaca.dyn_proc_status >= 2)
+ if (lppaca[i].dyn_proc_status >= 2)
continue;
snprintf(p, 32 - (p - buf), "@%d", i);
@@ -901,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_prop_str(dt, "device_type", "cpu");
- index = paca[i].lppaca.dyn_hv_phys_proc_index;
+ index = lppaca[i].dyn_hv_phys_proc_index;
d = &xIoHriProcessorVpd[index];
dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
@@ -918,6 +908,8 @@ void dt_cpus(struct iseries_flat_dt *dt)
dt_prop_u32(dt, "reg", i);
+ dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
dt_end_node(dt);
}
@@ -994,3 +986,16 @@ static int __init early_parsemem(char *p)
return 0;
}
early_param("mem", early_parsemem);
+
+static void hvputc(char c)
+{
+ if (c == '\n')
+ hvputc('\r');
+
+ HvCall_writeLogBuffer(&c, 1);
+}
+
+void __init udbg_init_iseries(void)
+{
+ udbg_putc = hvputc;
+}
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c
index fcb094ec6aec..6f9d407a709f 100644
--- a/arch/powerpc/platforms/iseries/smp.c
+++ b/arch/powerpc/platforms/iseries/smp.c
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr)
BUG_ON((nr < 0) || (nr >= NR_CPUS));
/* Verify that our partition has a processor nr */
- if (paca[nr].lppaca.dyn_proc_status >= 2)
+ if (lppaca[nr].dyn_proc_status >= 2)
return;
/* The processor is currently spinning, waiting
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 384360ee06ec..ad36ab0639f0 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -22,6 +22,8 @@
#include <asm/iseries/hv_lp_config.h>
#include <asm/iseries/hv_call_xm.h>
+#include "iommu.h"
+
struct device *iSeries_vio_dev = &vio_bus_device.dev;
EXPORT_SYMBOL(iSeries_vio_dev);
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 842672695598..622a30149b48 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -270,7 +270,7 @@ static void handleMonitorEvent(struct HvLpEvent *event)
* First see if this is just a normal monitor message from the
* other partition
*/
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
remoteLp = event->xSourceLp;
if (!viopathStatus[remoteLp].isActive)
sendMonMsg(remoteLp);
@@ -331,13 +331,12 @@ static void handleConfig(struct HvLpEvent *event)
{
if (!event)
return;
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
printk(VIOPATH_KERN_WARN
"unexpected config request from partition %d",
event->xSourceLp);
- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
@@ -377,7 +376,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK)
>> VIOMAJOR_SUBTYPE_SHIFT;
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
remoteLp = event->xSourceLp;
/*
* The isActive is checked because if the hosting partition
@@ -436,8 +435,7 @@ static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs)
"unexpected virtual io event subtype %d from partition %d\n",
event->xSubtype, remoteLp);
/* No handler. Ack if necessary */
- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+ if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index f40451da037c..7d4099a34f92 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -316,7 +316,6 @@ static int __init add_bridge(struct device_node *dev)
char* disp_name;
int *bus_range;
int primary = 1;
- struct property *of_prop;
DBG("Adding PCI host bridge %s\n", dev->full_name);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 7ece8983a105..ec5c1e10c407 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -51,6 +51,7 @@
#include <asm/pgtable.h>
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/kexec.h>
#include <asm/pci-bridge.h>
#include <asm/iommu.h>
#include <asm/machdep.h>
@@ -70,41 +71,60 @@
#define DBG(fmt...)
#endif
-extern void generic_find_legacy_serial_ports(u64 *physport,
- unsigned int *default_speed);
+static unsigned long maple_find_nvram_base(void)
+{
+ struct device_node *rtcs;
+ unsigned long result = 0;
+
+ /* find NVRAM device */
+ rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111");
+ if (rtcs) {
+ struct resource r;
+ if (of_address_to_resource(rtcs, 0, &r)) {
+ printk(KERN_EMERG "Maple: Unable to translate NVRAM"
+ " address\n");
+ goto bail;
+ }
+ if (!(r.flags & IORESOURCE_IO)) {
+ printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n");
+ goto bail;
+ }
+ result = r.start;
+ } else
+ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+ bail:
+ of_node_put(rtcs);
+ return result;
+}
static void maple_restart(char *cmd)
{
unsigned int maple_nvram_base;
unsigned int maple_nvram_offset;
unsigned int maple_nvram_command;
- struct device_node *rtcs;
+ struct device_node *sp;
- /* find NVRAM device */
- rtcs = find_compatible_devices("nvram", "AMD8111");
- if (rtcs && rtcs->addrs) {
- maple_nvram_base = rtcs->addrs[0].address;
- } else {
- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
- printk(KERN_EMERG "Maple: Manual Restart Required\n");
- return;
- }
+ maple_nvram_base = maple_find_nvram_base();
+ if (maple_nvram_base == 0)
+ goto fail;
/* find service processor device */
- rtcs = find_devices("service-processor");
- if (!rtcs) {
+ sp = of_find_node_by_name(NULL, "service-processor");
+ if (!sp) {
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
- printk(KERN_EMERG "Maple: Manual Restart Required\n");
- return;
+ goto fail;
}
- maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+ maple_nvram_offset = *(unsigned int*) get_property(sp,
"restart-addr", NULL);
- maple_nvram_command = *(unsigned int*) get_property(rtcs,
+ maple_nvram_command = *(unsigned int*) get_property(sp,
"restart-value", NULL);
+ of_node_put(sp);
/* send command */
outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
for (;;) ;
+ fail:
+ printk(KERN_EMERG "Maple: Manual Restart Required\n");
}
static void maple_power_off(void)
@@ -112,33 +132,29 @@ static void maple_power_off(void)
unsigned int maple_nvram_base;
unsigned int maple_nvram_offset;
unsigned int maple_nvram_command;
- struct device_node *rtcs;
+ struct device_node *sp;
- /* find NVRAM device */
- rtcs = find_compatible_devices("nvram", "AMD8111");
- if (rtcs && rtcs->addrs) {
- maple_nvram_base = rtcs->addrs[0].address;
- } else {
- printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
- return;
- }
+ maple_nvram_base = maple_find_nvram_base();
+ if (maple_nvram_base == 0)
+ goto fail;
/* find service processor device */
- rtcs = find_devices("service-processor");
- if (!rtcs) {
+ sp = of_find_node_by_name(NULL, "service-processor");
+ if (!sp) {
printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
- printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
- return;
+ goto fail;
}
- maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+ maple_nvram_offset = *(unsigned int*) get_property(sp,
"power-off-addr", NULL);
- maple_nvram_command = *(unsigned int*) get_property(rtcs,
+ maple_nvram_command = *(unsigned int*) get_property(sp,
"power-off-value", NULL);
+ of_node_put(sp);
/* send command */
outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
for (;;) ;
+ fail:
+ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
}
static void maple_halt(void)
@@ -181,9 +197,6 @@ void __init maple_setup_arch(void)
*/
static void __init maple_init_early(void)
{
- unsigned int default_speed;
- u64 physport;
-
DBG(" -> maple_init_early\n");
/* Initialize hash table, from now on, we can take hash faults
@@ -191,24 +204,10 @@ static void __init maple_init_early(void)
*/
hpte_init_native();
- /* Find the serial port */
- generic_find_legacy_serial_ports(&physport, &default_speed);
-
- DBG("phys port addr: %lx\n", (long)physport);
-
- if (physport) {
- void *comport;
- /* Map the uart for udbg. */
- comport = (void *)ioremap(physport, 16);
- udbg_init_uart(comport, default_speed);
-
- DBG("Hello World !\n");
- }
-
/* Setup interrupt mapping options */
ppc64_interrupt_controller = IC_OPEN_PIC;
- iommu_init_early_u3();
+ iommu_init_early_dart();
DBG(" <- maple_init_early\n");
}
@@ -270,7 +269,7 @@ static int __init maple_probe(int platform)
* occupies having to be broken up so the DART itself is not
* part of the cacheable linar mapping
*/
- alloc_u3_dart_table();
+ alloc_dart_table();
return 1;
}
@@ -292,4 +291,9 @@ struct machdep_calls __initdata maple_md = {
.calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
.idle_loop = native_idle,
+#ifdef CONFIG_KEXEC
+ .machine_kexec = default_machine_kexec,
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
+#endif
};
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c
index 15846cc938ac..50bc4eb85353 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -168,11 +168,24 @@ unsigned long __init maple_get_boot_time(void)
struct rtc_time tm;
struct device_node *rtcs;
- rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
- if (rtcs && rtcs->addrs) {
- maple_rtc_addr = rtcs->addrs[0].address;
- printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr);
- } else {
+ rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00");
+ if (rtcs) {
+ struct resource r;
+ if (of_address_to_resource(rtcs, 0, &r)) {
+ printk(KERN_EMERG "Maple: Unable to translate RTC"
+ " address\n");
+ goto bail;
+ }
+ if (!(r.flags & IORESOURCE_IO)) {
+ printk(KERN_EMERG "Maple: RTC address isn't PIO!\n");
+ goto bail;
+ }
+ maple_rtc_addr = r.start;
+ printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n",
+ maple_rtc_addr);
+ }
+ bail:
+ if (maple_rtc_addr == 0) {
maple_rtc_addr = RTC_PORT(0); /* legacy address */
printk(KERN_INFO "Maple: No device node for RTC, assuming "
"legacy address (0x%x)\n", maple_rtc_addr);
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
index c9df44fcf571..78093d7f97af 100644
--- a/arch/powerpc/platforms/powermac/Makefile
+++ b/arch/powerpc/platforms/powermac/Makefile
@@ -1,9 +1,14 @@
+CFLAGS_bootx_init.o += -fPIC
+
obj-y += pic.o setup.o time.o feature.o pci.o \
- sleep.o low_i2c.o cache.o
+ sleep.o low_i2c.o cache.o pfunc_core.o \
+ pfunc_base.o
obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o
obj-$(CONFIG_NVRAM) += nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64) += nvram.o
+obj-$(CONFIG_PPC32) += bootx_init.o
obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_PPC_MERGE) += udbg_scc.o udbg_adb.o
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
new file mode 100644
index 000000000000..fa8b4d7b5ded
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -0,0 +1,547 @@
+/*
+ * Early boot support code for BootX bootloader
+ *
+ * Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/bootx.h>
+#include <asm/bootinfo.h>
+#include <asm/btext.h>
+#include <asm/io.h>
+
+#undef DEBUG
+#define SET_BOOT_BAT
+
+#ifdef DEBUG
+#define DBG(fmt...) do { bootx_printf(fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
+extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
+
+static unsigned long __initdata bootx_dt_strbase;
+static unsigned long __initdata bootx_dt_strend;
+static unsigned long __initdata bootx_node_chosen;
+static boot_infos_t * __initdata bootx_info;
+static char __initdata bootx_disp_path[256];
+
+/* Is boot-info compatible ? */
+#define BOOT_INFO_IS_COMPATIBLE(bi) \
+ ((bi)->compatible_version <= BOOT_INFO_VERSION)
+#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
+#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
+
+#ifdef CONFIG_BOOTX_TEXT
+static void __init bootx_printf(const char *format, ...)
+{
+ const char *p, *q, *s;
+ va_list args;
+ unsigned long v;
+
+ va_start(args, format);
+ for (p = format; *p != 0; p = q) {
+ for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
+ ;
+ if (q > p)
+ btext_drawtext(p, q - p);
+ if (*q == 0)
+ break;
+ if (*q == '\n') {
+ ++q;
+ btext_flushline();
+ btext_drawstring("\r\n");
+ btext_flushline();
+ continue;
+ }
+ ++q;
+ if (*q == 0)
+ break;
+ switch (*q) {
+ case 's':
+ ++q;
+ s = va_arg(args, const char *);
+ if (s == NULL)
+ s = "<NULL>";
+ btext_drawstring(s);
+ break;
+ case 'x':
+ ++q;
+ v = va_arg(args, unsigned long);
+ btext_drawhex(v);
+ break;
+ }
+ }
+}
+#else /* CONFIG_BOOTX_TEXT */
+static void __init bootx_printf(const char *format, ...) {}
+#endif /* CONFIG_BOOTX_TEXT */
+
+static void * __init bootx_early_getprop(unsigned long base,
+ unsigned long node,
+ char *prop)
+{
+ struct bootx_dt_node *np = (struct bootx_dt_node *)(base + node);
+ u32 *ppp = &np->properties;
+
+ while(*ppp) {
+ struct bootx_dt_prop *pp =
+ (struct bootx_dt_prop *)(base + *ppp);
+
+ if (strcmp((char *)((unsigned long)pp->name + base),
+ prop) == 0) {
+ return (void *)((unsigned long)pp->value + base);
+ }
+ ppp = &pp->next;
+ }
+ return NULL;
+}
+
+#define dt_push_token(token, mem) \
+ do { \
+ *(mem) = _ALIGN_UP(*(mem),4); \
+ *((u32 *)*(mem)) = token; \
+ *(mem) += 4; \
+ } while(0)
+
+static unsigned long __init bootx_dt_find_string(char *str)
+{
+ char *s, *os;
+
+ s = os = (char *)bootx_dt_strbase;
+ s += 4;
+ while (s < (char *)bootx_dt_strend) {
+ if (strcmp(s, str) == 0)
+ return s - os;
+ s += strlen(s) + 1;
+ }
+ return 0;
+}
+
+static void __init bootx_dt_add_prop(char *name, void *data, int size,
+ unsigned long *mem_end)
+{
+ unsigned long soff = bootx_dt_find_string(name);
+ if (data == NULL)
+ size = 0;
+ if (soff == 0) {
+ bootx_printf("WARNING: Can't find string index for <%s>\n",
+ name);
+ return;
+ }
+ if (size > 0x20000) {
+ bootx_printf("WARNING: ignoring large property ");
+ bootx_printf("%s length 0x%x\n", name, size);
+ return;
+ }
+ dt_push_token(OF_DT_PROP, mem_end);
+ dt_push_token(size, mem_end);
+ dt_push_token(soff, mem_end);
+
+ /* push property content */
+ if (size && data) {
+ memcpy((void *)*mem_end, data, size);
+ *mem_end = _ALIGN_UP(*mem_end + size, 4);
+ }
+}
+
+static void __init bootx_add_chosen_props(unsigned long base,
+ unsigned long *mem_end)
+{
+ u32 val = _MACH_Pmac;
+
+ bootx_dt_add_prop("linux,platform", &val, 4, mem_end);
+
+ if (bootx_info->kernelParamsOffset) {
+ char *args = (char *)((unsigned long)bootx_info) +
+ bootx_info->kernelParamsOffset;
+ bootx_dt_add_prop("bootargs", args, strlen(args) + 1, mem_end);
+ }
+ if (bootx_info->ramDisk) {
+ val = ((unsigned long)bootx_info) + bootx_info->ramDisk;
+ bootx_dt_add_prop("linux,initrd-start", &val, 4, mem_end);
+ val += bootx_info->ramDiskSize;
+ bootx_dt_add_prop("linux,initrd-end", &val, 4, mem_end);
+ }
+ if (strlen(bootx_disp_path))
+ bootx_dt_add_prop("linux,stdout-path", bootx_disp_path,
+ strlen(bootx_disp_path) + 1, mem_end);
+}
+
+static void __init bootx_add_display_props(unsigned long base,
+ unsigned long *mem_end)
+{
+ bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
+ bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+}
+
+static void __init bootx_dt_add_string(char *s, unsigned long *mem_end)
+{
+ unsigned int l = strlen(s) + 1;
+ memcpy((void *)*mem_end, s, l);
+ bootx_dt_strend = *mem_end = *mem_end + l;
+}
+
+static void __init bootx_scan_dt_build_strings(unsigned long base,
+ unsigned long node,
+ unsigned long *mem_end)
+{
+ struct bootx_dt_node *np = (struct bootx_dt_node *)(base + node);
+ u32 *cpp, *ppp = &np->properties;
+ unsigned long soff;
+ char *namep;
+
+ /* Keep refs to known nodes */
+ namep = np->full_name ? (char *)(base + np->full_name) : NULL;
+ if (namep == NULL) {
+ bootx_printf("Node without a full name !\n");
+ namep = "";
+ }
+ DBG("* strings: %s\n", namep);
+
+ if (!strcmp(namep, "/chosen")) {
+ DBG(" detected /chosen ! adding properties names !\n");
+ bootx_dt_add_string("linux,platform", mem_end);
+ bootx_dt_add_string("linux,stdout-path", mem_end);
+ bootx_dt_add_string("linux,initrd-start", mem_end);
+ bootx_dt_add_string("linux,initrd-end", mem_end);
+ bootx_dt_add_string("bootargs", mem_end);
+ bootx_node_chosen = node;
+ }
+ if (node == bootx_info->dispDeviceRegEntryOffset) {
+ DBG(" detected display ! adding properties names !\n");
+ bootx_dt_add_string("linux,boot-display", mem_end);
+ bootx_dt_add_string("linux,opened", mem_end);
+ strncpy(bootx_disp_path, namep, 255);
+ }
+
+ /* get and store all property names */
+ while (*ppp) {
+ struct bootx_dt_prop *pp =
+ (struct bootx_dt_prop *)(base + *ppp);
+
+ namep = pp->name ? (char *)(base + pp->name) : NULL;
+ if (namep == NULL || strcmp(namep, "name") == 0)
+ goto next;
+ /* get/create string entry */
+ soff = bootx_dt_find_string(namep);
+ if (soff == 0)
+ bootx_dt_add_string(namep, mem_end);
+ next:
+ ppp = &pp->next;
+ }
+
+ /* do all our children */
+ cpp = &np->child;
+ while(*cpp) {
+ np = (struct bootx_dt_node *)(base + *cpp);
+ bootx_scan_dt_build_strings(base, *cpp, mem_end);
+ cpp = &np->sibling;
+ }
+}
+
+static void __init bootx_scan_dt_build_struct(unsigned long base,
+ unsigned long node,
+ unsigned long *mem_end)
+{
+ struct bootx_dt_node *np = (struct bootx_dt_node *)(base + node);
+ u32 *cpp, *ppp = &np->properties;
+ char *namep, *p, *ep, *lp;
+ int l;
+
+ dt_push_token(OF_DT_BEGIN_NODE, mem_end);
+
+ /* get the node's full name */
+ namep = np->full_name ? (char *)(base + np->full_name) : NULL;
+ if (namep == NULL)
+ namep = "";
+ l = strlen(namep);
+
+ DBG("* struct: %s\n", namep);
+
+ /* Fixup an Apple bug where they have bogus \0 chars in the
+ * middle of the path in some properties, and extract
+ * the unit name (everything after the last '/').
+ */
+ memcpy((void *)*mem_end, namep, l + 1);
+ namep = (char *)*mem_end;
+ for (lp = p = namep, ep = namep + l; p < ep; p++) {
+ if (*p == '/')
+ lp = namep;
+ else if (*p != 0)
+ *lp++ = *p;
+ }
+ *lp = 0;
+ *mem_end = _ALIGN_UP((unsigned long)lp + 1, 4);
+
+ /* get and store all properties */
+ while (*ppp) {
+ struct bootx_dt_prop *pp =
+ (struct bootx_dt_prop *)(base + *ppp);
+
+ namep = pp->name ? (char *)(base + pp->name) : NULL;
+ /* Skip "name" */
+ if (namep == NULL || !strcmp(namep, "name"))
+ goto next;
+ /* Skip "bootargs" in /chosen too as we replace it */
+ if (node == bootx_node_chosen && !strcmp(namep, "bootargs"))
+ goto next;
+
+ /* push property head */
+ bootx_dt_add_prop(namep,
+ pp->value ? (void *)(base + pp->value): NULL,
+ pp->length, mem_end);
+ next:
+ ppp = &pp->next;
+ }
+
+ if (node == bootx_node_chosen)
+ bootx_add_chosen_props(base, mem_end);
+ if (node == bootx_info->dispDeviceRegEntryOffset)
+ bootx_add_display_props(base, mem_end);
+
+ /* do all our children */
+ cpp = &np->child;
+ while(*cpp) {
+ np = (struct bootx_dt_node *)(base + *cpp);
+ bootx_scan_dt_build_struct(base, *cpp, mem_end);
+ cpp = &np->sibling;
+ }
+
+ dt_push_token(OF_DT_END_NODE, mem_end);
+}
+
+static unsigned long __init bootx_flatten_dt(unsigned long start)
+{
+ boot_infos_t *bi = bootx_info;
+ unsigned long mem_start, mem_end;
+ struct boot_param_header *hdr;
+ unsigned long base;
+ u64 *rsvmap;
+
+ /* Start using memory after the big blob passed by BootX, get
+ * some space for the header
+ */
+ mem_start = mem_end = _ALIGN_UP(((unsigned long)bi) + start, 4);
+ DBG("Boot params header at: %x\n", mem_start);
+ hdr = (struct boot_param_header *)mem_start;
+ mem_end += sizeof(struct boot_param_header);
+ rsvmap = (u64 *)(_ALIGN_UP(mem_end, 8));
+ hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - mem_start;
+ mem_end = ((unsigned long)rsvmap) + 8 * sizeof(u64);
+
+ /* Get base of tree */
+ base = ((unsigned long)bi) + bi->deviceTreeOffset;
+
+ /* Build string array */
+ DBG("Building string array at: %x\n", mem_end);
+ DBG("Device Tree Base=%x\n", base);
+ bootx_dt_strbase = mem_end;
+ mem_end += 4;
+ bootx_dt_strend = mem_end;
+ bootx_scan_dt_build_strings(base, 4, &mem_end);
+ hdr->off_dt_strings = bootx_dt_strbase - mem_start;
+ hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase;
+
+ /* Build structure */
+ mem_end = _ALIGN(mem_end, 16);
+ DBG("Building device tree structure at: %x\n", mem_end);
+ hdr->off_dt_struct = mem_end - mem_start;
+ bootx_scan_dt_build_struct(base, 4, &mem_end);
+ dt_push_token(OF_DT_END, &mem_end);
+
+ /* Finish header */
+ hdr->boot_cpuid_phys = 0;
+ hdr->magic = OF_DT_HEADER;
+ hdr->totalsize = mem_end - mem_start;
+ hdr->version = OF_DT_VERSION;
+ /* 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
+ * fail since it's too late.
+ */
+ mem_end = _ALIGN(mem_end, PAGE_SIZE);
+ DBG("End of boot params: %x\n", mem_end);
+ rsvmap[0] = mem_start;
+ rsvmap[1] = mem_end;
+ rsvmap[2] = 0;
+ rsvmap[3] = 0;
+
+ return (unsigned long)hdr;
+}
+
+
+#ifdef CONFIG_BOOTX_TEXT
+static void __init btext_welcome(boot_infos_t *bi)
+{
+ unsigned long flags;
+ unsigned long pvr;
+
+ bootx_printf("Welcome to Linux, kernel " UTS_RELEASE "\n");
+ bootx_printf("\nlinked at : 0x%x", KERNELBASE);
+ bootx_printf("\nframe buffer at : 0x%x", bi->dispDeviceBase);
+ bootx_printf(" (phys), 0x%x", bi->logicalDisplayBase);
+ bootx_printf(" (log)");
+ bootx_printf("\nklimit : 0x%x",(unsigned long)klimit);
+ bootx_printf("\nboot_info at : 0x%x", bi);
+ __asm__ __volatile__ ("mfmsr %0" : "=r" (flags));
+ bootx_printf("\nMSR : 0x%x", flags);
+ __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
+ bootx_printf("\nPVR : 0x%x", pvr);
+ pvr >>= 16;
+ if (pvr > 1) {
+ __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
+ bootx_printf("\nHID0 : 0x%x", flags);
+ }
+ if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
+ __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
+ bootx_printf("\nICTC : 0x%x", flags);
+ }
+#ifdef DEBUG
+ bootx_printf("\n\n");
+ bootx_printf("bi->deviceTreeOffset : 0x%x\n",
+ bi->deviceTreeOffset);
+ bootx_printf("bi->deviceTreeSize : 0x%x\n",
+ bi->deviceTreeSize);
+#endif
+ bootx_printf("\n\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+void __init bootx_init(unsigned long r3, unsigned long r4)
+{
+ boot_infos_t *bi = (boot_infos_t *) r4;
+ unsigned long hdr;
+ unsigned long space;
+ unsigned long ptr, x;
+ char *model;
+ unsigned long offset = reloc_offset();
+
+ reloc_got2(offset);
+
+ bootx_info = bi;
+
+ /* We haven't cleared any bss at this point, make sure
+ * what we need is initialized
+ */
+ bootx_dt_strbase = bootx_dt_strend = 0;
+ bootx_node_chosen = 0;
+ bootx_disp_path[0] = 0;
+
+ if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
+ bi->logicalDisplayBase = bi->dispDeviceBase;
+
+#ifdef CONFIG_BOOTX_TEXT
+ btext_setup_display(bi->dispDeviceRect[2] - bi->dispDeviceRect[0],
+ bi->dispDeviceRect[3] - bi->dispDeviceRect[1],
+ bi->dispDeviceDepth, bi->dispDeviceRowBytes,
+ (unsigned long)bi->logicalDisplayBase);
+ btext_clearscreen();
+ btext_flushscreen();
+#endif /* CONFIG_BOOTX_TEXT */
+
+ /*
+ * Test if boot-info is compatible. Done only in config
+ * CONFIG_BOOTX_TEXT since there is nothing much we can do
+ * with an incompatible version, except display a message
+ * and eventually hang the processor...
+ *
+ * I'll try to keep enough of boot-info compatible in the
+ * future to always allow display of this message;
+ */
+ if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
+ bootx_printf(" !!! WARNING - Incompatible version"
+ " of BootX !!!\n\n\n");
+ for (;;)
+ ;
+ }
+ if (bi->architecture != BOOT_ARCH_PCI) {
+ bootx_printf(" !!! WARNING - Usupported machine"
+ " architecture !\n");
+ for (;;)
+ ;
+ }
+
+#ifdef CONFIG_BOOTX_TEXT
+ btext_welcome(bi);
+#endif
+ /* New BootX enters kernel with MMU off, i/os are not allowed
+ * here. This hack will have been done by the boostrap anyway.
+ */
+ if (bi->version < 4) {
+ /*
+ * XXX If this is an iMac, turn off the USB controller.
+ */
+ model = (char *) bootx_early_getprop(r4 + bi->deviceTreeOffset,
+ 4, "model");
+ if (model
+ && (strcmp(model, "iMac,1") == 0
+ || strcmp(model, "PowerMac1,1") == 0)) {
+ bootx_printf("iMac,1 detected, shutting down USB \n");
+ out_le32((unsigned *)0x80880008, 1); /* XXX */
+ }
+ }
+
+ /* Get a pointer that points above the device tree, args, ramdisk,
+ * etc... to use for generating the flattened tree
+ */
+ if (bi->version < 5) {
+ space = bi->deviceTreeOffset + bi->deviceTreeSize;
+ if (bi->ramDisk)
+ space = bi->ramDisk + bi->ramDiskSize;
+ } else
+ space = bi->totalParamsSize;
+
+ bootx_printf("Total space used by parameters & ramdisk: %x \n", space);
+
+ /* New BootX will have flushed all TLBs and enters kernel with
+ * MMU switched OFF, so this should not be useful anymore.
+ */
+ if (bi->version < 4) {
+ bootx_printf("Touching pages...\n");
+
+ /*
+ * Touch each page to make sure the PTEs for them
+ * are in the hash table - the aim is to try to avoid
+ * getting DSI exceptions while copying the kernel image.
+ */
+ for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
+ ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
+ x = *(volatile unsigned long *)ptr;
+ }
+
+ /* Ok, now we need to generate a flattened device-tree to pass
+ * to the kernel
+ */
+ bootx_printf("Preparing boot params...\n");
+
+ hdr = bootx_flatten_dt(space);
+
+#ifdef CONFIG_BOOTX_TEXT
+#ifdef SET_BOOT_BAT
+ bootx_printf("Preparing BAT...\n");
+ btext_prepare_BAT();
+#else
+ btext_unmap();
+#endif
+#endif
+
+ reloc_got2(-offset);
+
+ __start(hdr, KERNELBASE + offset, 0);
+}
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 39150342c6f1..a415e8d2f7af 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -28,6 +28,7 @@
#include <asm/cputable.h>
#include <asm/time.h>
#include <asm/smu.h>
+#include <asm/pmac_pfunc.h>
#undef DEBUG
@@ -79,12 +80,16 @@ static struct freq_attr* g5_cpu_freqs_attr[] = {
};
/* Power mode data is an array of the 32 bits PCR values to use for
- * the various frequencies, retreived from the device-tree
+ * the various frequencies, retrieved from the device-tree
*/
static u32 *g5_pmode_data;
static int g5_pmode_max;
static int g5_pmode_cur;
+static void (*g5_switch_volt)(int speed_mode);
+static int (*g5_switch_freq)(int speed_mode);
+static int (*g5_query_freq)(void);
+
static DECLARE_MUTEX(g5_switch_mutex);
@@ -92,9 +97,11 @@ static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */
static int g5_fvt_count; /* number of op. points */
static int g5_fvt_cur; /* current op. point */
-/* ----------------- real hardware interface */
+/*
+ * SMU based voltage switching for Neo2 platforms
+ */
-static void g5_switch_volt(int speed_mode)
+static void g5_smu_switch_volt(int speed_mode)
{
struct smu_simple_cmd cmd;
@@ -105,26 +112,57 @@ static void g5_switch_volt(int speed_mode)
wait_for_completion(&comp);
}
-static int g5_switch_freq(int speed_mode)
+/*
+ * Platform function based voltage/vdnap switching for Neo2
+ */
+
+static struct pmf_function *pfunc_set_vdnap0;
+static struct pmf_function *pfunc_vdnap0_complete;
+
+static void g5_vdnap_switch_volt(int speed_mode)
{
- struct cpufreq_freqs freqs;
- int to;
+ struct pmf_args args;
+ u32 slew, done = 0;
+ unsigned long timeout;
- if (g5_pmode_cur == speed_mode)
- return 0;
+ slew = (speed_mode == CPUFREQ_LOW) ? 1 : 0;
+ args.count = 1;
+ args.u[0].p = &slew;
- down(&g5_switch_mutex);
+ pmf_call_one(pfunc_set_vdnap0, &args);
- freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
- freqs.new = g5_cpu_freqs[speed_mode].frequency;
- freqs.cpu = 0;
+ /* It's an irq GPIO so we should be able to just block here,
+ * I'll do that later after I've properly tested the IRQ code for
+ * platform functions
+ */
+ timeout = jiffies + HZ/10;
+ while(!time_after(jiffies, timeout)) {
+ args.count = 1;
+ args.u[0].p = &done;
+ pmf_call_one(pfunc_vdnap0_complete, &args);
+ if (done)
+ break;
+ msleep(1);
+ }
+ if (done == 0)
+ printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
+}
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+/*
+ * SCOM based frequency switching for 970FX rev3
+ */
+static int g5_scom_switch_freq(int speed_mode)
+{
+ unsigned long flags;
+ int to;
/* If frequency is going up, first ramp up the voltage */
if (speed_mode < g5_pmode_cur)
g5_switch_volt(speed_mode);
+ local_irq_save(flags);
+
/* Clear PCR high */
scom970_write(SCOM_PCR, 0);
/* Clear PCR low */
@@ -147,6 +185,8 @@ static int g5_switch_freq(int speed_mode)
udelay(100);
}
+ local_irq_restore(flags);
+
/* If frequency is going down, last ramp the voltage */
if (speed_mode > g5_pmode_cur)
g5_switch_volt(speed_mode);
@@ -154,14 +194,10 @@ static int g5_switch_freq(int speed_mode)
g5_pmode_cur = speed_mode;
ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul;
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- up(&g5_switch_mutex);
-
return 0;
}
-static int g5_query_freq(void)
+static int g5_scom_query_freq(void)
{
unsigned long psr = scom970_read(SCOM_PSR);
int i;
@@ -173,7 +209,104 @@ static int g5_query_freq(void)
return i;
}
-/* ----------------- cpufreq bookkeeping */
+/*
+ * Platform function based voltage switching for PowerMac7,2 & 7,3
+ */
+
+static struct pmf_function *pfunc_cpu0_volt_high;
+static struct pmf_function *pfunc_cpu0_volt_low;
+static struct pmf_function *pfunc_cpu1_volt_high;
+static struct pmf_function *pfunc_cpu1_volt_low;
+
+static void g5_pfunc_switch_volt(int speed_mode)
+{
+ if (speed_mode == CPUFREQ_HIGH) {
+ if (pfunc_cpu0_volt_high)
+ pmf_call_one(pfunc_cpu0_volt_high, NULL);
+ if (pfunc_cpu1_volt_high)
+ pmf_call_one(pfunc_cpu1_volt_high, NULL);
+ } else {
+ if (pfunc_cpu0_volt_low)
+ pmf_call_one(pfunc_cpu0_volt_low, NULL);
+ if (pfunc_cpu1_volt_low)
+ pmf_call_one(pfunc_cpu1_volt_low, NULL);
+ }
+ msleep(10); /* should be faster , to fix */
+}
+
+/*
+ * Platform function based frequency switching for PowerMac7,2 & 7,3
+ */
+
+static struct pmf_function *pfunc_cpu_setfreq_high;
+static struct pmf_function *pfunc_cpu_setfreq_low;
+static struct pmf_function *pfunc_cpu_getfreq;
+static struct pmf_function *pfunc_slewing_done;;
+
+static int g5_pfunc_switch_freq(int speed_mode)
+{
+ struct pmf_args args;
+ u32 done = 0;
+ unsigned long timeout;
+
+ /* If frequency is going up, first ramp up the voltage */
+ if (speed_mode < g5_pmode_cur)
+ g5_switch_volt(speed_mode);
+
+ /* Do it */
+ if (speed_mode == CPUFREQ_HIGH)
+ pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+ else
+ pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+ /* It's an irq GPIO so we should be able to just block here,
+ * I'll do that later after I've properly tested the IRQ code for
+ * platform functions
+ */
+ timeout = jiffies + HZ/10;
+ while(!time_after(jiffies, timeout)) {
+ args.count = 1;
+ args.u[0].p = &done;
+ pmf_call_one(pfunc_slewing_done, &args);
+ if (done)
+ break;
+ msleep(1);
+ }
+ if (done == 0)
+ printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
+
+ /* If frequency is going down, last ramp the voltage */
+ if (speed_mode > g5_pmode_cur)
+ g5_switch_volt(speed_mode);
+
+ g5_pmode_cur = speed_mode;
+ ppc_proc_freq = g5_cpu_freqs[speed_mode].frequency * 1000ul;
+
+ return 0;
+}
+
+static int g5_pfunc_query_freq(void)
+{
+ struct pmf_args args;
+ u32 val = 0;
+
+ args.count = 1;
+ args.u[0].p = &val;
+ pmf_call_one(pfunc_cpu_getfreq, &args);
+ return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
+}
+
+/*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+/*
+ * Common interface to the cpufreq core
+ */
static int g5_cpufreq_verify(struct cpufreq_policy *policy)
{
@@ -183,13 +316,30 @@ static int g5_cpufreq_verify(struct cpufreq_policy *policy)
static int g5_cpufreq_target(struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int relation)
{
- unsigned int newstate = 0;
+ unsigned int newstate = 0;
+ struct cpufreq_freqs freqs;
+ int rc;
if (cpufreq_frequency_table_target(policy, g5_cpu_freqs,
target_freq, relation, &newstate))
return -EINVAL;
- return g5_switch_freq(newstate);
+ if (g5_pmode_cur == newstate)
+ return 0;
+
+ down(&g5_switch_mutex);
+
+ freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency;
+ freqs.new = g5_cpu_freqs[newstate].frequency;
+ freqs.cpu = 0;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ rc = g5_switch_freq(newstate);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ up(&g5_switch_mutex);
+
+ return rc;
}
static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
@@ -205,6 +355,7 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
+ policy->cpus = cpu_possible_map;
cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
return cpufreq_frequency_table_cpuinfo(policy,
@@ -224,19 +375,39 @@ static struct cpufreq_driver g5_cpufreq_driver = {
};
-static int __init g5_cpufreq_init(void)
+static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
{
struct device_node *cpunode;
unsigned int psize, ssize;
- struct smu_sdbp_header *shdr;
unsigned long max_freq;
- u32 *valp;
+ char *freq_method, *volt_method;
+ u32 *valp, pvr_hi;
+ int use_volts_vdnap = 0;
+ int use_volts_smu = 0;
int rc = -ENODEV;
- /* Look for CPU and SMU nodes */
- cpunode = of_find_node_by_type(NULL, "cpu");
- if (!cpunode) {
- DBG("No CPU node !\n");
+ /* Check supported platforms */
+ if (machine_is_compatible("PowerMac8,1") ||
+ machine_is_compatible("PowerMac8,2") ||
+ machine_is_compatible("PowerMac9,1"))
+ use_volts_smu = 1;
+ else if (machine_is_compatible("PowerMac11,2"))
+ use_volts_vdnap = 1;
+ else
+ return -ENODEV;
+
+ /* Get first CPU node */
+ for (cpunode = NULL;
+ (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
+ u32 *reg =
+ (u32 *)get_property(cpunode, "reg", NULL);
+ if (reg == NULL || (*reg) != 0)
+ continue;
+ if (!strcmp(cpunode->type, "cpu"))
+ break;
+ }
+ if (cpunode == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
return -ENODEV;
}
@@ -246,8 +417,9 @@ static int __init g5_cpufreq_init(void)
DBG("No cpu-version property !\n");
goto bail_noprops;
}
- if (((*valp) >> 16) != 0x3c) {
- DBG("Wrong CPU version: %08x\n", *valp);
+ pvr_hi = (*valp) >> 16;
+ if (pvr_hi != 0x3c && pvr_hi != 0x44) {
+ printk(KERN_ERR "cpufreq: Unsupported CPU version\n");
goto bail_noprops;
}
@@ -259,18 +431,50 @@ static int __init g5_cpufreq_init(void)
}
g5_pmode_max = psize / sizeof(u32) - 1;
- /* Look for the FVT table */
- shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
- if (!shdr)
- goto bail_noprops;
- g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1];
- ssize = (shdr->len * sizeof(u32)) - sizeof(struct smu_sdbp_header);
- g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt);
- g5_fvt_cur = 0;
-
- /* Sanity checking */
- if (g5_fvt_count < 1 || g5_pmode_max < 1)
- goto bail_noprops;
+ if (use_volts_smu) {
+ struct smu_sdbp_header *shdr;
+
+ /* Look for the FVT table */
+ shdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
+ if (!shdr)
+ goto bail_noprops;
+ g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1];
+ ssize = (shdr->len * sizeof(u32)) -
+ sizeof(struct smu_sdbp_header);
+ g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt);
+ g5_fvt_cur = 0;
+
+ /* Sanity checking */
+ if (g5_fvt_count < 1 || g5_pmode_max < 1)
+ goto bail_noprops;
+
+ g5_switch_volt = g5_smu_switch_volt;
+ volt_method = "SMU";
+ } else if (use_volts_vdnap) {
+ struct device_node *root;
+
+ root = of_find_node_by_path("/");
+ if (root == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find root of "
+ "device tree\n");
+ goto bail_noprops;
+ }
+ pfunc_set_vdnap0 = pmf_find_function(root, "set-vdnap0");
+ pfunc_vdnap0_complete =
+ pmf_find_function(root, "slewing-done");
+ if (pfunc_set_vdnap0 == NULL ||
+ pfunc_vdnap0_complete == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find required "
+ "platform function\n");
+ goto bail_noprops;
+ }
+
+ g5_switch_volt = g5_vdnap_switch_volt;
+ volt_method = "GPIO";
+ } else {
+ g5_switch_volt = g5_dummy_switch_volt;
+ volt_method = "none";
+ }
/*
* From what I see, clock-frequency is always the maximal frequency.
@@ -286,19 +490,23 @@ static int __init g5_cpufreq_init(void)
g5_cpu_freqs[0].frequency = max_freq;
g5_cpu_freqs[1].frequency = max_freq/2;
- /* Check current frequency */
- g5_pmode_cur = g5_query_freq();
- if (g5_pmode_cur > 1)
- /* We don't support anything but 1:1 and 1:2, fixup ... */
- g5_pmode_cur = 1;
+ /* Set callbacks */
+ g5_switch_freq = g5_scom_switch_freq;
+ g5_query_freq = g5_scom_query_freq;
+ freq_method = "SCOM";
/* Force apply current frequency to make sure everything is in
* sync (voltage is right for example). Firmware may leave us with
* a strange setting ...
*/
- g5_switch_freq(g5_pmode_cur);
+ g5_switch_volt(CPUFREQ_HIGH);
+ msleep(10);
+ g5_pmode_cur = -1;
+ g5_switch_freq(g5_query_freq());
printk(KERN_INFO "Registering G5 CPU frequency driver\n");
+ printk(KERN_INFO "Frequency method: %s, Voltage method: %s\n",
+ freq_method, volt_method);
printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
g5_cpu_freqs[1].frequency/1000,
g5_cpu_freqs[0].frequency/1000,
@@ -317,6 +525,200 @@ static int __init g5_cpufreq_init(void)
return rc;
}
+static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
+{
+ struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
+ u8 *eeprom = NULL;
+ u32 *valp;
+ u64 max_freq, min_freq, ih, il;
+ int has_volt = 1, rc = 0;
+
+ /* Get first CPU node */
+ for (cpunode = NULL;
+ (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
+ if (!strcmp(cpunode->type, "cpu"))
+ break;
+ }
+ if (cpunode == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find any CPU node\n");
+ return -ENODEV;
+ }
+
+ /* Lookup the cpuid eeprom node */
+ cpuid = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/cpuid@a0");
+ if (cpuid != NULL)
+ eeprom = (u8 *)get_property(cpuid, "cpuid", NULL);
+ if (eeprom == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
+ /* Lookup the i2c hwclock */
+ for (hwclock = NULL;
+ (hwclock = of_find_node_by_name(hwclock, "i2c-hwclock")) != NULL;){
+ char *loc = get_property(hwclock, "hwctrl-location", NULL);
+ if (loc == NULL)
+ continue;
+ if (strcmp(loc, "CPU CLOCK"))
+ continue;
+ if (!get_property(hwclock, "platform-get-frequency", NULL))
+ continue;
+ break;
+ }
+ if (hwclock == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find i2c clock chip !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
+ DBG("cpufreq: i2c clock chip found: %s\n", hwclock->full_name);
+
+ /* Now get all the platform functions */
+ pfunc_cpu_getfreq =
+ pmf_find_function(hwclock, "get-frequency");
+ pfunc_cpu_setfreq_high =
+ pmf_find_function(hwclock, "set-frequency-high");
+ pfunc_cpu_setfreq_low =
+ pmf_find_function(hwclock, "set-frequency-low");
+ pfunc_slewing_done =
+ pmf_find_function(hwclock, "slewing-done");
+ pfunc_cpu0_volt_high =
+ pmf_find_function(hwclock, "set-voltage-high-0");
+ pfunc_cpu0_volt_low =
+ pmf_find_function(hwclock, "set-voltage-low-0");
+ pfunc_cpu1_volt_high =
+ pmf_find_function(hwclock, "set-voltage-high-1");
+ pfunc_cpu1_volt_low =
+ pmf_find_function(hwclock, "set-voltage-low-1");
+
+ /* Check we have minimum requirements */
+ if (pfunc_cpu_getfreq == NULL || pfunc_cpu_setfreq_high == NULL ||
+ pfunc_cpu_setfreq_low == NULL || pfunc_slewing_done == NULL) {
+ printk(KERN_ERR "cpufreq: Can't find platform functions !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
+ /* Check that we have complete sets */
+ if (pfunc_cpu0_volt_high == NULL || pfunc_cpu0_volt_low == NULL) {
+ pmf_put_function(pfunc_cpu0_volt_high);
+ pmf_put_function(pfunc_cpu0_volt_low);
+ pfunc_cpu0_volt_high = pfunc_cpu0_volt_low = NULL;
+ has_volt = 0;
+ }
+ if (!has_volt ||
+ pfunc_cpu1_volt_high == NULL || pfunc_cpu1_volt_low == NULL) {
+ pmf_put_function(pfunc_cpu1_volt_high);
+ pmf_put_function(pfunc_cpu1_volt_low);
+ pfunc_cpu1_volt_high = pfunc_cpu1_volt_low = NULL;
+ }
+
+ /* Note: The device tree also contains a "platform-set-values"
+ * function for which I haven't quite figured out the usage. It
+ * might have to be called on init and/or wakeup, I'm not too sure
+ * but things seem to work fine without it so far ...
+ */
+
+ /* Get max frequency from device-tree */
+ valp = (u32 *)get_property(cpunode, "clock-frequency", NULL);
+ if (!valp) {
+ printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+
+ max_freq = (*valp)/1000;
+
+ /* Now calculate reduced frequency by using the cpuid input freq
+ * ratio. This requires 64 bits math unless we are willing to lose
+ * some precision
+ */
+ ih = *((u32 *)(eeprom + 0x10));
+ il = *((u32 *)(eeprom + 0x20));
+ min_freq = 0;
+ if (ih != 0 && il != 0)
+ min_freq = (max_freq * il) / ih;
+
+ /* Sanity check */
+ if (min_freq >= max_freq || min_freq < 1000) {
+ printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
+ rc = -ENODEV;
+ goto bail;
+ }
+ g5_cpu_freqs[0].frequency = max_freq;
+ g5_cpu_freqs[1].frequency = min_freq;
+
+ /* Set callbacks */
+ g5_switch_volt = g5_pfunc_switch_volt;
+ g5_switch_freq = g5_pfunc_switch_freq;
+ g5_query_freq = g5_pfunc_query_freq;
+
+ /* Force apply current frequency to make sure everything is in
+ * sync (voltage is right for example). Firmware may leave us with
+ * a strange setting ...
+ */
+ g5_switch_volt(CPUFREQ_HIGH);
+ msleep(10);
+ g5_pmode_cur = -1;
+ g5_switch_freq(g5_query_freq());
+
+ printk(KERN_INFO "Registering G5 CPU frequency driver\n");
+ printk(KERN_INFO "Frequency method: i2c/pfunc, "
+ "Voltage method: %s\n", has_volt ? "i2c/pfunc" : "none");
+ printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+ g5_cpu_freqs[1].frequency/1000,
+ g5_cpu_freqs[0].frequency/1000,
+ g5_cpu_freqs[g5_pmode_cur].frequency/1000);
+
+ rc = cpufreq_register_driver(&g5_cpufreq_driver);
+ bail:
+ if (rc != 0) {
+ pmf_put_function(pfunc_cpu_getfreq);
+ pmf_put_function(pfunc_cpu_setfreq_high);
+ pmf_put_function(pfunc_cpu_setfreq_low);
+ pmf_put_function(pfunc_slewing_done);
+ pmf_put_function(pfunc_cpu0_volt_high);
+ pmf_put_function(pfunc_cpu0_volt_low);
+ pmf_put_function(pfunc_cpu1_volt_high);
+ pmf_put_function(pfunc_cpu1_volt_low);
+ }
+ of_node_put(hwclock);
+ of_node_put(cpuid);
+ of_node_put(cpunode);
+
+ return rc;
+}
+
+static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
+{
+ /* NYI */
+ return 0;
+}
+
+static int __init g5_cpufreq_init(void)
+{
+ struct device_node *cpus;
+ int rc;
+
+ cpus = of_find_node_by_path("/cpus");
+ if (cpus == NULL) {
+ DBG("No /cpus node !\n");
+ return -ENODEV;
+ }
+
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3"))
+ rc = g5_pm72_cpufreq_init(cpus);
+ else if (machine_is_compatible("RackMac3,1"))
+ rc = g5_rm31_cpufreq_init(cpus);
+ else
+ rc = g5_neo2_cpufreq_init(cpus);
+
+ of_node_put(cpus);
+ return rc;
+}
+
module_init(g5_cpufreq_init);
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index f6e22da2a5da..558dd0692092 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -58,12 +58,11 @@ extern int powersave_lowspeed;
extern int powersave_nap;
extern struct device_node *k2_skiplist[2];
-
/*
* We use a single global lock to protect accesses. Each driver has
* to take care of its own locking
*/
-static DEFINE_SPINLOCK(feature_lock);
+DEFINE_SPINLOCK(feature_lock);
#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
@@ -101,26 +100,17 @@ static const char *macio_names[] =
"Keylargo",
"Pangea",
"Intrepid",
- "K2"
+ "K2",
+ "Shasta",
};
+struct device_node *uninorth_node;
+u32 __iomem *uninorth_base;
-/*
- * Uninorth reg. access. Note that Uni-N regs are big endian
- */
-
-#define UN_REG(r) (uninorth_base + ((r) >> 2))
-#define UN_IN(r) (in_be32(UN_REG(r)))
-#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
-
-static struct device_node *uninorth_node;
-static u32 __iomem *uninorth_base;
static u32 uninorth_rev;
-static int uninorth_u3;
-static void __iomem *u3_ht;
+static int uninorth_maj;
+static void __iomem *u3_ht_base;
/*
* For each motherboard family, we have a table of functions pointers
@@ -1399,8 +1389,15 @@ static long g5_fw_enable(struct device_node *node, long param, long value)
static long g5_mpic_enable(struct device_node *node, long param, long value)
{
unsigned long flags;
+ struct device_node *parent = of_get_parent(node);
+ int is_u3;
- if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+ if (parent == NULL)
+ return 0;
+ is_u3 = strcmp(parent->name, "u3") == 0 ||
+ strcmp(parent->name, "u4") == 0;
+ of_node_put(parent);
+ if (!is_u3)
return 0;
LOCK(flags);
@@ -1445,20 +1442,53 @@ static long g5_i2s_enable(struct device_node *node, long param, long value)
/* Very crude implementation for now */
struct macio_chip *macio = &macio_chips[0];
unsigned long flags;
-
- if (value == 0)
- return 0; /* don't disable yet */
+ int cell;
+ u32 fcrs[3][3] = {
+ { 0,
+ K2_FCR1_I2S0_CELL_ENABLE |
+ K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE,
+ KL3_I2S0_CLK18_ENABLE
+ },
+ { KL0_SCC_A_INTF_ENABLE,
+ K2_FCR1_I2S1_CELL_ENABLE |
+ K2_FCR1_I2S1_CLK_ENABLE_BIT | K2_FCR1_I2S1_ENABLE,
+ KL3_I2S1_CLK18_ENABLE
+ },
+ { KL0_SCC_B_INTF_ENABLE,
+ SH_FCR1_I2S2_CELL_ENABLE |
+ SH_FCR1_I2S2_CLK_ENABLE_BIT | SH_FCR1_I2S2_ENABLE,
+ SH_FCR3_I2S2_CLK18_ENABLE
+ },
+ };
+
+ if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
+ return -ENODEV;
+ if (strncmp(node->name, "i2s-", 4))
+ return -ENODEV;
+ cell = node->name[4] - 'a';
+ switch(cell) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (macio->type == macio_shasta)
+ break;
+ default:
+ return -ENODEV;
+ }
LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE |
- KL3_I2S0_CLK18_ENABLE);
- udelay(10);
- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE |
- K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE);
+ if (value) {
+ MACIO_BIC(KEYLARGO_FCR0, fcrs[cell][0]);
+ MACIO_BIS(KEYLARGO_FCR1, fcrs[cell][1]);
+ MACIO_BIS(KEYLARGO_FCR3, fcrs[cell][2]);
+ } else {
+ MACIO_BIC(KEYLARGO_FCR3, fcrs[cell][2]);
+ MACIO_BIC(KEYLARGO_FCR1, fcrs[cell][1]);
+ MACIO_BIS(KEYLARGO_FCR0, fcrs[cell][0]);
+ }
udelay(10);
- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET);
UNLOCK(flags);
- udelay(10);
return 0;
}
@@ -1473,7 +1503,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
struct device_node *np;
macio = &macio_chips[0];
- if (macio->type != macio_keylargo2)
+ if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
return -ENODEV;
np = find_path_device("/cpus");
@@ -1512,14 +1542,17 @@ static long g5_reset_cpu(struct device_node *node, long param, long value)
*/
void g5_phy_disable_cpu1(void)
{
- UN_OUT(U3_API_PHY_CONFIG_1, 0);
+ if (uninorth_maj == 3)
+ UN_OUT(U3_API_PHY_CONFIG_1, 0);
}
#endif /* CONFIG_POWER4 */
#ifndef CONFIG_POWER4
-static void
-keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
+
+#ifdef CONFIG_PM
+
+static void keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
{
u32 temp;
@@ -1572,8 +1605,7 @@ keylargo_shutdown(struct macio_chip *macio, int sleep_mode)
(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
-static void
-pangea_shutdown(struct macio_chip *macio, int sleep_mode)
+static void pangea_shutdown(struct macio_chip *macio, int sleep_mode)
{
u32 temp;
@@ -1606,8 +1638,7 @@ pangea_shutdown(struct macio_chip *macio, int sleep_mode)
(void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
}
-static void
-intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
+static void intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
{
u32 temp;
@@ -1635,124 +1666,6 @@ intrepid_shutdown(struct macio_chip *macio, int sleep_mode)
}
-void pmac_tweak_clock_spreading(int enable)
-{
- struct macio_chip *macio = &macio_chips[0];
-
- /* Hack for doing clock spreading on some machines PowerBooks and
- * iBooks. This implements the "platform-do-clockspreading" OF
- * property as decoded manually on various models. For safety, we also
- * check the product ID in the device-tree in cases we'll whack the i2c
- * chip to make reasonably sure we won't set wrong values in there
- *
- * Of course, ultimately, we have to implement a real parser for
- * the platform-do-* stuff...
- */
-
- if (macio->type == macio_intrepid) {
- struct device_node *clock =
- of_find_node_by_path("/uni-n@f8000000/hw-clock");
- if (clock && get_property(clock, "platform-do-clockspreading",
- NULL)) {
- printk(KERN_INFO "%sabling clock spreading on Intrepid"
- " ASIC\n", enable ? "En" : "Dis");
- if (enable)
- UN_OUT(UNI_N_CLOCK_SPREADING, 2);
- else
- UN_OUT(UNI_N_CLOCK_SPREADING, 0);
- mdelay(40);
- }
- of_node_put(clock);
- }
-
- while (machine_is_compatible("PowerBook5,2") ||
- machine_is_compatible("PowerBook5,3") ||
- machine_is_compatible("PowerBook6,2") ||
- machine_is_compatible("PowerBook6,3")) {
- struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
- struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
- u8 buffer[9];
- u32 *productID;
- int i, rc, changed = 0;
-
- if (dt == NULL)
- break;
- productID = (u32 *)get_property(dt, "pid#", NULL);
- if (productID == NULL)
- break;
- while(ui2c) {
- struct device_node *p = of_get_parent(ui2c);
- if (p && !strcmp(p->name, "uni-n"))
- break;
- ui2c = of_find_node_by_type(ui2c, "i2c");
- }
- if (ui2c == NULL)
- break;
- DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
- rc = pmac_low_i2c_open(ui2c, 1);
- if (rc != 0)
- break;
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
- DBG("read result: %d,", rc);
- if (rc != 0) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- for (i=0; i<9; i++)
- DBG(" %02x", buffer[i]);
- DBG("\n");
-
- switch(*productID) {
- case 0x1182: /* AlBook 12" rev 2 */
- case 0x1183: /* iBook G4 12" */
- buffer[0] = (buffer[0] & 0x8f) | 0x70;
- buffer[2] = (buffer[2] & 0x7f) | 0x00;
- buffer[5] = (buffer[5] & 0x80) | 0x31;
- buffer[6] = (buffer[6] & 0x40) | 0xb0;
- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
- buffer[8] = (buffer[8] & 0x00) | 0x30;
- changed = 1;
- break;
- case 0x3142: /* AlBook 15" (ATI M10) */
- case 0x3143: /* AlBook 17" (ATI M10) */
- buffer[0] = (buffer[0] & 0xaf) | 0x50;
- buffer[2] = (buffer[2] & 0x7f) | 0x00;
- buffer[5] = (buffer[5] & 0x80) | 0x31;
- buffer[6] = (buffer[6] & 0x40) | 0xb0;
- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
- buffer[8] = (buffer[8] & 0x00) | 0x30;
- changed = 1;
- break;
- default:
- DBG("i2c-hwclock: Machine model not handled\n");
- break;
- }
- if (!changed) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n",
- enable ? "En" : "Dis");
-
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
- DBG("write result: %d,", rc);
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
- DBG("read result: %d,", rc);
- if (rc != 0) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- for (i=0; i<9; i++)
- DBG(" %02x", buffer[i]);
- pmac_low_i2c_close(ui2c);
- break;
- }
-}
-
-
static int
core99_sleep(void)
{
@@ -1909,6 +1822,8 @@ core99_wake_up(void)
return 0;
}
+#endif /* CONFIG_PM */
+
static long
core99_sleep_state(struct device_node *node, long param, long value)
{
@@ -1930,10 +1845,13 @@ core99_sleep_state(struct device_node *node, long param, long value)
if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
return -EPERM;
+#ifdef CONFIG_PM
if (value == 1)
return core99_sleep();
else if (value == 0)
return core99_wake_up();
+
+#endif /* CONFIG_PM */
return 0;
}
@@ -2057,7 +1975,9 @@ static struct feature_table_entry core99_features[] = {
{ PMAC_FTR_USB_ENABLE, core99_usb_enable },
{ PMAC_FTR_1394_ENABLE, core99_firewire_enable },
{ PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
+#ifdef CONFIG_PM
{ PMAC_FTR_SLEEP_STATE, core99_sleep_state },
+#endif
#ifdef CONFIG_SMP
{ PMAC_FTR_RESET_CPU, core99_reset_cpu },
#endif /* CONFIG_SMP */
@@ -2427,6 +2347,14 @@ static struct pmac_mb_def pmac_mb_defs[] = {
PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
0,
},
+ { "PowerMac11,2", "PowerMac G5 Dual Core",
+ PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
+ 0,
+ },
+ { "PowerMac12,1", "iMac G5 (iSight)",
+ PMAC_TYPE_POWERMAC_G5_U3L, g5_features,
+ 0,
+ },
{ "RackMac3,1", "XServe G5",
PMAC_TYPE_XSERVE_G5, g5_features,
0,
@@ -2539,6 +2467,11 @@ static int __init probe_motherboard(void)
pmac_mb.model_name = "Unknown K2-based";
pmac_mb.features = g5_features;
break;
+ case macio_shasta:
+ pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA;
+ pmac_mb.model_name = "Unknown Shasta-based";
+ pmac_mb.features = g5_features;
+ break;
#endif /* CONFIG_POWER4 */
default:
return -ENODEV;
@@ -2607,6 +2540,8 @@ found:
*/
static void __init probe_uninorth(void)
{
+ u32 *addrp;
+ phys_addr_t address;
unsigned long actrl;
/* Locate core99 Uni-N */
@@ -2614,22 +2549,31 @@ static void __init probe_uninorth(void)
/* Locate G5 u3 */
if (uninorth_node == NULL) {
uninorth_node = of_find_node_by_name(NULL, "u3");
- uninorth_u3 = 1;
- }
- if (uninorth_node && uninorth_node->n_addrs > 0) {
- unsigned long address = uninorth_node->addrs[0].address;
- uninorth_base = ioremap(address, 0x40000);
- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
- if (uninorth_u3)
- u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
- } else
- uninorth_node = NULL;
-
- if (!uninorth_node)
+ uninorth_maj = 3;
+ }
+ /* Locate G5 u4 */
+ if (uninorth_node == NULL) {
+ uninorth_node = of_find_node_by_name(NULL, "u4");
+ uninorth_maj = 4;
+ }
+ if (uninorth_node == NULL)
return;
- printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
- uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
+ addrp = (u32 *)get_property(uninorth_node, "reg", NULL);
+ if (addrp == NULL)
+ return;
+ address = of_translate_address(uninorth_node, addrp);
+ if (address == 0)
+ return;
+ uninorth_base = ioremap(address, 0x40000);
+ uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+ if (uninorth_maj == 3 || uninorth_maj == 4)
+ u3_ht_base = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
+
+ printk(KERN_INFO "Found %s memory controller & host bridge"
+ " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" :
+ uninorth_maj == 4 ? "U4" : "UniNorth",
+ (unsigned int)address, uninorth_rev);
printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
/* Set the arbitrer QAck delay according to what Apple does
@@ -2637,7 +2581,8 @@ static void __init probe_uninorth(void)
if (uninorth_rev < 0x11) {
actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
- UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+ UNI_N_ARB_CTRL_QACK_DELAY) <<
+ UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
UN_OUT(UNI_N_ARB_CTRL, actrl);
}
@@ -2645,7 +2590,8 @@ static void __init probe_uninorth(void)
* revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
* memory timeout
*/
- if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+ if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) ||
+ uninorth_rev == 0xc0)
UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
}
@@ -2653,18 +2599,17 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
{
struct device_node* node;
int i;
- volatile u32 __iomem * base;
- u32* revp;
+ volatile u32 __iomem *base;
+ u32 *addrp, *revp;
+ phys_addr_t addr;
+ u64 size;
- node = find_devices(name);
- if (!node || !node->n_addrs)
- return;
- if (compat)
- do {
- if (device_is_compatible(node, compat))
- break;
- node = node->next;
- } while (node);
+ for (node = NULL; (node = of_find_node_by_name(node, name)) != NULL;) {
+ if (!compat)
+ break;
+ if (device_is_compatible(node, compat))
+ break;
+ }
if (!node)
return;
for(i=0; i<MAX_MACIO_CHIPS; i++) {
@@ -2673,22 +2618,38 @@ static void __init probe_one_macio(const char *name, const char *compat, int typ
if (macio_chips[i].of_node == node)
return;
}
+
if (i >= MAX_MACIO_CHIPS) {
printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
return;
}
- base = ioremap(node->addrs[0].address, node->addrs[0].size);
+ addrp = of_get_pci_address(node, 0, &size, NULL);
+ if (addrp == NULL) {
+ printk(KERN_ERR "pmac_feature: %s: can't find base !\n",
+ node->full_name);
+ return;
+ }
+ addr = of_translate_address(node, addrp);
+ if (addr == 0) {
+ printk(KERN_ERR "pmac_feature: %s, can't translate base !\n",
+ node->full_name);
+ return;
+ }
+ base = ioremap(addr, (unsigned long)size);
if (!base) {
- printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+ printk(KERN_ERR "pmac_feature: %s, can't map mac-io chip !\n",
+ node->full_name);
return;
}
- if (type == macio_keylargo) {
+ if (type == macio_keylargo || type == macio_keylargo2) {
u32 *did = (u32 *)get_property(node, "device-id", NULL);
if (*did == 0x00000025)
type = macio_pangea;
if (*did == 0x0000003e)
type = macio_intrepid;
+ if (*did == 0x0000004f)
+ type = macio_shasta;
}
macio_chips[i].of_node = node;
macio_chips[i].type = type;
@@ -2787,7 +2748,8 @@ set_initial_features(void)
}
#ifdef CONFIG_POWER4
- if (macio_chips[0].type == macio_keylargo2) {
+ if (macio_chips[0].type == macio_keylargo2 ||
+ macio_chips[0].type == macio_shasta) {
#ifndef CONFIG_SMP
/* On SMP machines running UP, we have the second CPU eating
* bus cycles. We need to take it off the bus. This is done
@@ -2896,12 +2858,6 @@ set_initial_features(void)
MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
}
- /* Some machine models need the clock chip to be properly setup for
- * clock spreading now. This should be a platform function but we
- * don't do these at the moment
- */
- pmac_tweak_clock_spreading(1);
-
#endif /* CONFIG_POWER4 */
/* On all machines, switch modem & serial ports off */
@@ -2929,9 +2885,6 @@ pmac_feature_init(void)
return;
}
- /* Setup low-level i2c stuffs */
- pmac_init_low_i2c();
-
/* Probe machine type */
if (probe_motherboard())
printk(KERN_WARNING "Unknown PowerMac !\n");
@@ -2942,26 +2895,6 @@ pmac_feature_init(void)
set_initial_features();
}
-int __init pmac_feature_late_init(void)
-{
-#if 0
- struct device_node *np;
-
- /* Request some resources late */
- if (uninorth_node)
- request_OF_resource(uninorth_node, 0, NULL);
- np = find_devices("hammerhead");
- if (np)
- request_OF_resource(np, 0, NULL);
- np = find_devices("interrupt-controller");
- if (np)
- request_OF_resource(np, 0, NULL);
-#endif
- return 0;
-}
-
-device_initcall(pmac_feature_late_init);
-
#if 0
static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
{
@@ -2984,9 +2917,9 @@ void __init pmac_check_ht_link(void)
u8 px_bus, px_devfn;
struct pci_controller *px_hose;
- (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
- ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
- ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
+ (void)in_be32(u3_ht_base + U3_HT_LINK_COMMAND);
+ ucfg = cfg = in_be32(u3_ht_base + U3_HT_LINK_CONFIG);
+ ufreq = freq = in_be32(u3_ht_base + U3_HT_LINK_FREQ);
dump_HT_speeds("U3 HyperTransport", cfg, freq);
pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index f3f39e8e337a..535c802b369f 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1,22 +1,34 @@
/*
- * arch/ppc/platforms/pmac_low_i2c.c
+ * arch/powerpc/platforms/powermac/low_i2c.c
*
- * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
+ * Copyright (C) 2003-2005 Ben. Herrenschmidt (benh@kernel.crashing.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 file contains some low-level i2c access routines that
- * need to be used by various bits of the PowerMac platform code
- * at times where the real asynchronous & interrupt driven driver
- * cannot be used. The API borrows some semantics from the darwin
- * driver in order to ease the implementation of the platform
- * properties parser
+ * The linux i2c layer isn't completely suitable for our needs for various
+ * reasons ranging from too late initialisation to semantics not perfectly
+ * matching some requirements of the apple platform functions etc...
+ *
+ * This file thus provides a simple low level unified i2c interface for
+ * powermac that covers the various types of i2c busses used in Apple machines.
+ * For now, keywest, PMU and SMU, though we could add Cuda, or other bit
+ * banging busses found on older chipstes in earlier machines if we ever need
+ * one of them.
+ *
+ * The drivers in this file are synchronous/blocking. In addition, the
+ * keywest one is fairly slow due to the use of msleep instead of interrupts
+ * as the interrupt is currently used by i2c-keywest. In the long run, we
+ * might want to get rid of those high-level interfaces to linux i2c layer
+ * either completely (converting all drivers) or replacing them all with a
+ * single stub driver on top of this one. Once done, the interrupt will be
+ * available for our use.
*/
#undef DEBUG
+#undef DEBUG_LOW
#include <linux/config.h>
#include <linux/types.h>
@@ -25,66 +37,91 @@
#include <linux/module.h>
#include <linux/adb.h>
#include <linux/pmu.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/timer.h>
#include <asm/keylargo.h>
#include <asm/uninorth.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/machdep.h>
+#include <asm/smu.h>
+#include <asm/pmac_pfunc.h>
#include <asm/pmac_low_i2c.h>
-#define MAX_LOW_I2C_HOST 4
-
#ifdef DEBUG
#define DBG(x...) do {\
- printk(KERN_DEBUG "KW:" x); \
+ printk(KERN_DEBUG "low_i2c:" x); \
} while(0)
#else
#define DBG(x...)
#endif
-struct low_i2c_host;
-
-typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
+#ifdef DEBUG_LOW
+#define DBG_LOW(x...) do {\
+ printk(KERN_DEBUG "low_i2c:" x); \
+ } while(0)
+#else
+#define DBG_LOW(x...)
+#endif
-struct low_i2c_host
-{
- struct device_node *np; /* OF device node */
- struct semaphore mutex; /* Access mutex for use by i2c-keywest */
- low_i2c_func_t func; /* Access function */
- unsigned int is_open : 1; /* Poor man's access control */
- int mode; /* Current mode */
- int channel; /* Current channel */
- int num_channels; /* Number of channels */
- void __iomem *base; /* For keywest-i2c, base address */
- int bsteps; /* And register stepping */
- int speed; /* And speed */
-};
-static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
+static int pmac_i2c_force_poll = 1;
-/* No locking is necessary on allocation, we are running way before
- * anything can race with us
+/*
+ * A bus structure. Each bus in the system has such a structure associated.
*/
-static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
+struct pmac_i2c_bus
{
- int i;
+ struct list_head link;
+ struct device_node *controller;
+ struct device_node *busnode;
+ int type;
+ int flags;
+ struct i2c_adapter *adapter;
+ void *hostdata;
+ int channel; /* some hosts have multiple */
+ int mode; /* current mode */
+ struct semaphore sem;
+ int opened;
+ int polled; /* open mode */
+ struct platform_device *platform_dev;
+
+ /* ops */
+ int (*open)(struct pmac_i2c_bus *bus);
+ void (*close)(struct pmac_i2c_bus *bus);
+ int (*xfer)(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len);
+};
- for (i = 0; i < MAX_LOW_I2C_HOST; i++)
- if (low_i2c_hosts[i].np == np)
- return &low_i2c_hosts[i];
- return NULL;
-}
+static LIST_HEAD(pmac_i2c_busses);
/*
- *
- * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
- *
+ * Keywest implementation
*/
-/*
- * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
- * should be moved somewhere in include/asm-ppc/
- */
+struct pmac_i2c_host_kw
+{
+ struct semaphore mutex; /* Access mutex for use by
+ * i2c-keywest */
+ void __iomem *base; /* register base address */
+ int bsteps; /* register stepping */
+ int speed; /* speed */
+ int irq;
+ u8 *data;
+ unsigned len;
+ int state;
+ int rw;
+ int polled;
+ int result;
+ struct completion complete;
+ spinlock_t lock;
+ struct timer_list timeout_timer;
+};
+
/* Register indices */
typedef enum {
reg_mode = 0,
@@ -97,6 +134,8 @@ typedef enum {
reg_data
} reg_t;
+/* The Tumbler audio equalizer can be really slow sometimes */
+#define KW_POLL_TIMEOUT (2*HZ)
/* Mode register */
#define KW_I2C_MODE_100KHZ 0x00
@@ -140,8 +179,9 @@ enum {
};
#define WRONG_STATE(name) do {\
- printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
- name, __kw_state_names[state], isr); \
+ printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s " \
+ "(isr: %02x)\n", \
+ name, __kw_state_names[host->state], isr); \
} while(0)
static const char *__kw_state_names[] = {
@@ -153,120 +193,137 @@ static const char *__kw_state_names[] = {
"state_dead"
};
-static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
+static inline u8 __kw_read_reg(struct pmac_i2c_host_kw *host, reg_t reg)
{
return readb(host->base + (((unsigned int)reg) << host->bsteps));
}
-static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
+static inline void __kw_write_reg(struct pmac_i2c_host_kw *host,
+ reg_t reg, u8 val)
{
writeb(val, host->base + (((unsigned)reg) << host->bsteps));
(void)__kw_read_reg(host, reg_subaddr);
}
-#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
-#define kw_read_reg(reg) __kw_read_reg(host, reg)
-
+#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
+#define kw_read_reg(reg) __kw_read_reg(host, reg)
-/* Don't schedule, the g5 fan controller is too
- * timing sensitive
- */
-static u8 kw_wait_interrupt(struct low_i2c_host* host)
+static u8 kw_i2c_wait_interrupt(struct pmac_i2c_host_kw *host)
{
int i, j;
u8 isr;
- for (i = 0; i < 100000; i++) {
+ for (i = 0; i < 1000; i++) {
isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
if (isr != 0)
return isr;
/* This code is used with the timebase frozen, we cannot rely
- * on udelay ! For now, just use a bogus loop
+ * on udelay nor schedule when in polled mode !
+ * For now, just use a bogus loop....
*/
- for (j = 1; j < 10000; j++)
- mb();
+ if (host->polled) {
+ for (j = 1; j < 100000; j++)
+ mb();
+ } else
+ msleep(1);
}
return isr;
}
-static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
+static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 isr)
{
u8 ack;
- DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr);
+ DBG_LOW("kw_handle_interrupt(%s, isr: %x)\n",
+ __kw_state_names[host->state], isr);
+
+ if (host->state == state_idle) {
+ printk(KERN_WARNING "low_i2c: Keywest got an out of state"
+ " interrupt, ignoring\n");
+ kw_write_reg(reg_isr, isr);
+ return;
+ }
if (isr == 0) {
- if (state != state_stop) {
- DBG("KW: Timeout !\n");
- *rc = -EIO;
+ if (host->state != state_stop) {
+ DBG_LOW("KW: Timeout !\n");
+ host->result = -EIO;
goto stop;
}
- if (state == state_stop) {
+ if (host->state == state_stop) {
ack = kw_read_reg(reg_status);
- if (!(ack & KW_I2C_STAT_BUSY)) {
- state = state_idle;
- kw_write_reg(reg_ier, 0x00);
- }
+ if (ack & KW_I2C_STAT_BUSY)
+ kw_write_reg(reg_status, 0);
+ host->state = state_idle;
+ kw_write_reg(reg_ier, 0x00);
+ if (!host->polled)
+ complete(&host->complete);
}
- return state;
+ return;
}
if (isr & KW_I2C_IRQ_ADDR) {
ack = kw_read_reg(reg_status);
- if (state != state_addr) {
+ if (host->state != state_addr) {
kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
WRONG_STATE("KW_I2C_IRQ_ADDR");
- *rc = -EIO;
+ host->result = -EIO;
goto stop;
}
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- *rc = -ENODEV;
- DBG("KW: NAK on address\n");
- return state_stop;
+ if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
+ host->result = -ENODEV;
+ DBG_LOW("KW: NAK on address\n");
+ host->state = state_stop;
+ return;
} else {
- if (rw) {
- state = state_read;
- if (*len > 1)
- kw_write_reg(reg_control, KW_I2C_CTL_AAK);
+ if (host->len == 0) {
+ kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
+ goto stop;
+ }
+ if (host->rw) {
+ host->state = state_read;
+ if (host->len > 1)
+ kw_write_reg(reg_control,
+ KW_I2C_CTL_AAK);
} else {
- state = state_write;
- kw_write_reg(reg_data, **data);
- (*data)++; (*len)--;
+ host->state = state_write;
+ kw_write_reg(reg_data, *(host->data++));
+ host->len--;
}
}
kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
}
if (isr & KW_I2C_IRQ_DATA) {
- if (state == state_read) {
- **data = kw_read_reg(reg_data);
- (*data)++; (*len)--;
+ if (host->state == state_read) {
+ *(host->data++) = kw_read_reg(reg_data);
+ host->len--;
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
- if ((*len) == 0)
- state = state_stop;
- else if ((*len) == 1)
+ if (host->len == 0)
+ host->state = state_stop;
+ else if (host->len == 1)
kw_write_reg(reg_control, 0);
- } else if (state == state_write) {
+ } else if (host->state == state_write) {
ack = kw_read_reg(reg_status);
if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- DBG("KW: nack on data write\n");
- *rc = -EIO;
+ DBG_LOW("KW: nack on data write\n");
+ host->result = -EIO;
goto stop;
- } else if (*len) {
- kw_write_reg(reg_data, **data);
- (*data)++; (*len)--;
+ } else if (host->len) {
+ kw_write_reg(reg_data, *(host->data++));
+ host->len--;
} else {
kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- state = state_stop;
- *rc = 0;
+ host->state = state_stop;
+ host->result = 0;
}
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
} else {
kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
WRONG_STATE("KW_I2C_IRQ_DATA");
- if (state != state_stop) {
- *rc = -EIO;
+ if (host->state != state_stop) {
+ host->result = -EIO;
goto stop;
}
}
@@ -274,98 +331,194 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int
if (isr & KW_I2C_IRQ_STOP) {
kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
- if (state != state_stop) {
+ if (host->state != state_stop) {
WRONG_STATE("KW_I2C_IRQ_STOP");
- *rc = -EIO;
+ host->result = -EIO;
}
- return state_idle;
+ host->state = state_idle;
+ if (!host->polled)
+ complete(&host->complete);
}
if (isr & KW_I2C_IRQ_START)
kw_write_reg(reg_isr, KW_I2C_IRQ_START);
- return state;
-
+ return;
stop:
kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- return state_stop;
+ host->state = state_stop;
+ return;
}
-static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
+/* Interrupt handler */
+static irqreturn_t kw_i2c_irq(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct pmac_i2c_host_kw *host = dev_id;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ del_timer(&host->timeout_timer);
+ kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
+ if (host->state != state_idle) {
+ host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
+ add_timer(&host->timeout_timer);
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ return IRQ_HANDLED;
+}
+
+static void kw_i2c_timeout(unsigned long data)
+{
+ struct pmac_i2c_host_kw *host = (struct pmac_i2c_host_kw *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+ kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
+ if (host->state != state_idle) {
+ host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
+ add_timer(&host->timeout_timer);
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static int kw_i2c_open(struct pmac_i2c_bus *bus)
+{
+ struct pmac_i2c_host_kw *host = bus->hostdata;
+ down(&host->mutex);
+ return 0;
+}
+
+static void kw_i2c_close(struct pmac_i2c_bus *bus)
+{
+ struct pmac_i2c_host_kw *host = bus->hostdata;
+ up(&host->mutex);
+}
+
+static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len)
+{
+ struct pmac_i2c_host_kw *host = bus->hostdata;
u8 mode_reg = host->speed;
- int state = state_addr;
- int rc = 0;
+ int use_irq = host->irq != NO_IRQ && !bus->polled;
/* Setup mode & subaddress if any */
- switch(host->mode) {
- case pmac_low_i2c_mode_dumb:
- printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
+ switch(bus->mode) {
+ case pmac_i2c_mode_dumb:
return -EINVAL;
- case pmac_low_i2c_mode_std:
+ case pmac_i2c_mode_std:
mode_reg |= KW_I2C_MODE_STANDARD;
+ if (subsize != 0)
+ return -EINVAL;
break;
- case pmac_low_i2c_mode_stdsub:
+ case pmac_i2c_mode_stdsub:
mode_reg |= KW_I2C_MODE_STANDARDSUB;
+ if (subsize != 1)
+ return -EINVAL;
break;
- case pmac_low_i2c_mode_combined:
+ case pmac_i2c_mode_combined:
mode_reg |= KW_I2C_MODE_COMBINED;
+ if (subsize != 1)
+ return -EINVAL;
break;
}
/* Setup channel & clear pending irqs */
kw_write_reg(reg_isr, kw_read_reg(reg_isr));
- kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
+ kw_write_reg(reg_mode, mode_reg | (bus->channel << 4));
kw_write_reg(reg_status, 0);
- /* Set up address and r/w bit */
- kw_write_reg(reg_addr, addr);
+ /* Set up address and r/w bit, strip possible stale bus number from
+ * address top bits
+ */
+ kw_write_reg(reg_addr, addrdir & 0xff);
/* Set up the sub address */
if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
|| (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
kw_write_reg(reg_subaddr, subaddr);
- /* Start sending address & disable interrupt*/
- kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
+ /* Prepare for async operations */
+ host->data = data;
+ host->len = len;
+ host->state = state_addr;
+ host->result = 0;
+ host->rw = (addrdir & 1);
+ host->polled = bus->polled;
+
+ /* Enable interrupt if not using polled mode and interrupt is
+ * available
+ */
+ if (use_irq) {
+ /* Clear completion */
+ INIT_COMPLETION(host->complete);
+ /* Ack stale interrupts */
+ kw_write_reg(reg_isr, kw_read_reg(reg_isr));
+ /* Arm timeout */
+ host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
+ add_timer(&host->timeout_timer);
+ /* Enable emission */
+ kw_write_reg(reg_ier, KW_I2C_IRQ_MASK);
+ }
+
+ /* Start sending address */
kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
- /* State machine, to turn into an interrupt handler */
- while(state != state_idle) {
- u8 isr = kw_wait_interrupt(host);
- state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
+ /* Wait for completion */
+ if (use_irq)
+ wait_for_completion(&host->complete);
+ else {
+ while(host->state != state_idle) {
+ unsigned long flags;
+
+ u8 isr = kw_i2c_wait_interrupt(host);
+ spin_lock_irqsave(&host->lock, flags);
+ kw_i2c_handle_interrupt(host, isr);
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
}
- return rc;
+ /* Disable emission */
+ kw_write_reg(reg_ier, 0);
+
+ return host->result;
}
-static void keywest_low_i2c_add(struct device_node *np)
+static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
{
- struct low_i2c_host *host = find_low_i2c_host(NULL);
- u32 *psteps, *prate, steps, aoffset = 0;
- struct device_node *parent;
+ struct pmac_i2c_host_kw *host;
+ u32 *psteps, *prate, *addrp, steps;
+ host = kzalloc(sizeof(struct pmac_i2c_host_kw), GFP_KERNEL);
if (host == NULL) {
printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
np->full_name);
- return;
+ return NULL;
}
- memset(host, 0, sizeof(*host));
+ /* Apple is kind enough to provide a valid AAPL,address property
+ * on all i2c keywest nodes so far ... we would have to fallback
+ * to macio parsing if that wasn't the case
+ */
+ addrp = (u32 *)get_property(np, "AAPL,address", NULL);
+ if (addrp == NULL) {
+ printk(KERN_ERR "low_i2c: Can't find address for %s\n",
+ np->full_name);
+ kfree(host);
+ return NULL;
+ }
init_MUTEX(&host->mutex);
- host->np = of_node_get(np);
+ init_completion(&host->complete);
+ spin_lock_init(&host->lock);
+ init_timer(&host->timeout_timer);
+ host->timeout_timer.function = kw_i2c_timeout;
+ host->timeout_timer.data = (unsigned long)host;
+
psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
steps = psteps ? (*psteps) : 0x10;
for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
steps >>= 1;
- parent = of_get_parent(np);
- host->num_channels = 1;
- if (parent && parent->name[0] == 'u') {
- host->num_channels = 2;
- aoffset = 3;
- }
/* Select interface rate */
- host->speed = KW_I2C_MODE_100KHZ;
+ host->speed = KW_I2C_MODE_25KHZ;
prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
if (prate) switch(*prate) {
case 100:
@@ -378,146 +531,981 @@ static void keywest_low_i2c_add(struct device_node *np)
host->speed = KW_I2C_MODE_25KHZ;
break;
}
+ if (np->n_intrs > 0)
+ host->irq = np->intrs[0].line;
+ else
+ host->irq = NO_IRQ;
+
+ host->base = ioremap((*addrp), 0x1000);
+ if (host->base == NULL) {
+ printk(KERN_ERR "low_i2c: Can't map registers for %s\n",
+ np->full_name);
+ kfree(host);
+ return NULL;
+ }
+
+ /* Make sure IRA is disabled */
+ kw_write_reg(reg_ier, 0);
+
+ /* Request chip interrupt */
+ if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host))
+ host->irq = NO_IRQ;
+
+ printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
+ *addrp, host->irq, np->full_name);
- host->mode = pmac_low_i2c_mode_std;
- host->base = ioremap(np->addrs[0].address + aoffset,
- np->addrs[0].size);
- host->func = keywest_low_i2c_func;
+ return host;
}
+
+static void __init kw_i2c_add(struct pmac_i2c_host_kw *host,
+ struct device_node *controller,
+ struct device_node *busnode,
+ int channel)
+{
+ struct pmac_i2c_bus *bus;
+
+ bus = kzalloc(sizeof(struct pmac_i2c_bus), GFP_KERNEL);
+ if (bus == NULL)
+ return;
+
+ bus->controller = of_node_get(controller);
+ bus->busnode = of_node_get(busnode);
+ bus->type = pmac_i2c_bus_keywest;
+ bus->hostdata = host;
+ bus->channel = channel;
+ bus->mode = pmac_i2c_mode_std;
+ bus->open = kw_i2c_open;
+ bus->close = kw_i2c_close;
+ bus->xfer = kw_i2c_xfer;
+ init_MUTEX(&bus->sem);
+ if (controller == busnode)
+ bus->flags = pmac_i2c_multibus;
+ list_add(&bus->link, &pmac_i2c_busses);
+
+ printk(KERN_INFO " channel %d bus %s\n", channel,
+ (controller == busnode) ? "<multibus>" : busnode->full_name);
+}
+
+static void __init kw_i2c_probe(void)
+{
+ struct device_node *np, *child, *parent;
+
+ /* Probe keywest-i2c busses */
+ for (np = NULL;
+ (np = of_find_compatible_node(np, "i2c","keywest-i2c")) != NULL;){
+ struct pmac_i2c_host_kw *host;
+ int multibus, chans, i;
+
+ /* Found one, init a host structure */
+ host = kw_i2c_host_init(np);
+ if (host == NULL)
+ continue;
+
+ /* Now check if we have a multibus setup (old style) or if we
+ * have proper bus nodes. Note that the "new" way (proper bus
+ * nodes) might cause us to not create some busses that are
+ * kept hidden in the device-tree. In the future, we might
+ * want to work around that by creating busses without a node
+ * but not for now
+ */
+ child = of_get_next_child(np, NULL);
+ multibus = !child || strcmp(child->name, "i2c-bus");
+ of_node_put(child);
+
+ /* For a multibus setup, we get the bus count based on the
+ * parent type
+ */
+ if (multibus) {
+ parent = of_get_parent(np);
+ if (parent == NULL)
+ continue;
+ chans = parent->name[0] == 'u' ? 2 : 1;
+ for (i = 0; i < chans; i++)
+ kw_i2c_add(host, np, np, i);
+ } else {
+ for (child = NULL;
+ (child = of_get_next_child(np, child)) != NULL;) {
+ u32 *reg =
+ (u32 *)get_property(child, "reg", NULL);
+ if (reg == NULL)
+ continue;
+ kw_i2c_add(host, np, child, *reg);
+ }
+ }
+ }
+}
+
+
/*
*
* PMU implementation
*
*/
-
#ifdef CONFIG_ADB_PMU
-static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
+/*
+ * i2c command block to the PMU
+ */
+struct pmu_i2c_hdr {
+ u8 bus;
+ u8 mode;
+ u8 bus2;
+ u8 address;
+ u8 sub_addr;
+ u8 comb_addr;
+ u8 count;
+ u8 data[];
+};
+
+static void pmu_i2c_complete(struct adb_request *req)
{
- // TODO
- return -ENODEV;
+ complete(req->arg);
}
-static void pmu_low_i2c_add(struct device_node *np)
+static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len)
{
- struct low_i2c_host *host = find_low_i2c_host(NULL);
+ struct adb_request *req = bus->hostdata;
+ struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req->data[1];
+ struct completion comp;
+ int read = addrdir & 1;
+ int retry;
+ int rc = 0;
- if (host == NULL) {
- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
- np->full_name);
- return;
+ /* For now, limit ourselves to 16 bytes transfers */
+ if (len > 16)
+ return -EINVAL;
+
+ init_completion(&comp);
+
+ for (retry = 0; retry < 16; retry++) {
+ memset(req, 0, sizeof(struct adb_request));
+ hdr->bus = bus->channel;
+ hdr->count = len;
+
+ switch(bus->mode) {
+ case pmac_i2c_mode_std:
+ if (subsize != 0)
+ return -EINVAL;
+ hdr->address = addrdir;
+ hdr->mode = PMU_I2C_MODE_SIMPLE;
+ break;
+ case pmac_i2c_mode_stdsub:
+ case pmac_i2c_mode_combined:
+ if (subsize != 1)
+ return -EINVAL;
+ hdr->address = addrdir & 0xfe;
+ hdr->comb_addr = addrdir;
+ hdr->sub_addr = subaddr;
+ if (bus->mode == pmac_i2c_mode_stdsub)
+ hdr->mode = PMU_I2C_MODE_STDSUB;
+ else
+ hdr->mode = PMU_I2C_MODE_COMBINED;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ INIT_COMPLETION(comp);
+ req->data[0] = PMU_I2C_CMD;
+ req->reply[0] = 0xff;
+ req->nbytes = sizeof(struct pmu_i2c_hdr) + 1;
+ req->done = pmu_i2c_complete;
+ req->arg = &comp;
+ if (!read && len) {
+ memcpy(hdr->data, data, len);
+ req->nbytes += len;
+ }
+ rc = pmu_queue_request(req);
+ if (rc)
+ return rc;
+ wait_for_completion(&comp);
+ if (req->reply[0] == PMU_I2C_STATUS_OK)
+ break;
+ msleep(15);
}
- memset(host, 0, sizeof(*host));
+ if (req->reply[0] != PMU_I2C_STATUS_OK)
+ return -EIO;
- init_MUTEX(&host->mutex);
- host->np = of_node_get(np);
- host->num_channels = 3;
- host->mode = pmac_low_i2c_mode_std;
- host->func = pmu_low_i2c_func;
+ for (retry = 0; retry < 16; retry++) {
+ memset(req, 0, sizeof(struct adb_request));
+
+ /* I know that looks like a lot, slow as hell, but darwin
+ * does it so let's be on the safe side for now
+ */
+ msleep(15);
+
+ hdr->bus = PMU_I2C_BUS_STATUS;
+
+ INIT_COMPLETION(comp);
+ req->data[0] = PMU_I2C_CMD;
+ req->reply[0] = 0xff;
+ req->nbytes = 2;
+ req->done = pmu_i2c_complete;
+ req->arg = &comp;
+ rc = pmu_queue_request(req);
+ if (rc)
+ return rc;
+ wait_for_completion(&comp);
+
+ if (req->reply[0] == PMU_I2C_STATUS_OK && !read)
+ return 0;
+ if (req->reply[0] == PMU_I2C_STATUS_DATAREAD && read) {
+ int rlen = req->reply_len - 1;
+
+ if (rlen != len) {
+ printk(KERN_WARNING "low_i2c: PMU returned %d"
+ " bytes, expected %d !\n", rlen, len);
+ return -EIO;
+ }
+ if (len)
+ memcpy(data, &req->reply[1], len);
+ return 0;
+ }
+ }
+ return -EIO;
+}
+
+static void __init pmu_i2c_probe(void)
+{
+ struct pmac_i2c_bus *bus;
+ struct device_node *busnode;
+ int channel, sz;
+
+ if (!pmu_present())
+ return;
+
+ /* There might or might not be a "pmu-i2c" node, we use that
+ * or via-pmu itself, whatever we find. I haven't seen a machine
+ * with separate bus nodes, so we assume a multibus setup
+ */
+ busnode = of_find_node_by_name(NULL, "pmu-i2c");
+ if (busnode == NULL)
+ busnode = of_find_node_by_name(NULL, "via-pmu");
+ if (busnode == NULL)
+ return;
+
+ printk(KERN_INFO "PMU i2c %s\n", busnode->full_name);
+
+ /*
+ * We add bus 1 and 2 only for now, bus 0 is "special"
+ */
+ for (channel = 1; channel <= 2; channel++) {
+ sz = sizeof(struct pmac_i2c_bus) + sizeof(struct adb_request);
+ bus = kzalloc(sz, GFP_KERNEL);
+ if (bus == NULL)
+ return;
+
+ bus->controller = busnode;
+ bus->busnode = busnode;
+ bus->type = pmac_i2c_bus_pmu;
+ bus->channel = channel;
+ bus->mode = pmac_i2c_mode_std;
+ bus->hostdata = bus + 1;
+ bus->xfer = pmu_i2c_xfer;
+ init_MUTEX(&bus->sem);
+ bus->flags = pmac_i2c_multibus;
+ list_add(&bus->link, &pmac_i2c_busses);
+
+ printk(KERN_INFO " channel %d bus <multibus>\n", channel);
+ }
}
#endif /* CONFIG_ADB_PMU */
-void __init pmac_init_low_i2c(void)
+
+/*
+ *
+ * SMU implementation
+ *
+ */
+
+#ifdef CONFIG_PMAC_SMU
+
+static void smu_i2c_complete(struct smu_i2c_cmd *cmd, void *misc)
{
- struct device_node *np;
+ complete(misc);
+}
- /* Probe keywest-i2c busses */
- np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
- while(np) {
- keywest_low_i2c_add(np);
- np = of_find_compatible_node(np, "i2c", "keywest-i2c");
+static int smu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len)
+{
+ struct smu_i2c_cmd *cmd = bus->hostdata;
+ struct completion comp;
+ int read = addrdir & 1;
+ int rc = 0;
+
+ if ((read && len > SMU_I2C_READ_MAX) ||
+ ((!read) && len > SMU_I2C_WRITE_MAX))
+ return -EINVAL;
+
+ memset(cmd, 0, sizeof(struct smu_i2c_cmd));
+ cmd->info.bus = bus->channel;
+ cmd->info.devaddr = addrdir;
+ cmd->info.datalen = len;
+
+ switch(bus->mode) {
+ case pmac_i2c_mode_std:
+ if (subsize != 0)
+ return -EINVAL;
+ cmd->info.type = SMU_I2C_TRANSFER_SIMPLE;
+ break;
+ case pmac_i2c_mode_stdsub:
+ case pmac_i2c_mode_combined:
+ if (subsize > 3 || subsize < 1)
+ return -EINVAL;
+ cmd->info.sublen = subsize;
+ /* that's big-endian only but heh ! */
+ memcpy(&cmd->info.subaddr, ((char *)&subaddr) + (4 - subsize),
+ subsize);
+ if (bus->mode == pmac_i2c_mode_stdsub)
+ cmd->info.type = SMU_I2C_TRANSFER_STDSUB;
+ else
+ cmd->info.type = SMU_I2C_TRANSFER_COMBINED;
+ break;
+ default:
+ return -EINVAL;
}
+ if (!read && len)
+ memcpy(cmd->info.data, data, len);
+
+ init_completion(&comp);
+ cmd->done = smu_i2c_complete;
+ cmd->misc = &comp;
+ rc = smu_queue_i2c(cmd);
+ if (rc < 0)
+ return rc;
+ wait_for_completion(&comp);
+ rc = cmd->status;
+
+ if (read && len)
+ memcpy(data, cmd->info.data, len);
+ return rc < 0 ? rc : 0;
+}
+
+static void __init smu_i2c_probe(void)
+{
+ struct device_node *controller, *busnode;
+ struct pmac_i2c_bus *bus;
+ u32 *reg;
+ int sz;
+
+ if (!smu_present())
+ return;
+
+ controller = of_find_node_by_name(NULL, "smu-i2c-control");
+ if (controller == NULL)
+ controller = of_find_node_by_name(NULL, "smu");
+ if (controller == NULL)
+ return;
+
+ printk(KERN_INFO "SMU i2c %s\n", controller->full_name);
+
+ /* Look for childs, note that they might not be of the right
+ * type as older device trees mix i2c busses and other thigns
+ * at the same level
+ */
+ for (busnode = NULL;
+ (busnode = of_get_next_child(controller, busnode)) != NULL;) {
+ if (strcmp(busnode->type, "i2c") &&
+ strcmp(busnode->type, "i2c-bus"))
+ continue;
+ reg = (u32 *)get_property(busnode, "reg", NULL);
+ if (reg == NULL)
+ continue;
+
+ sz = sizeof(struct pmac_i2c_bus) + sizeof(struct smu_i2c_cmd);
+ bus = kzalloc(sz, GFP_KERNEL);
+ if (bus == NULL)
+ return;
+
+ bus->controller = controller;
+ bus->busnode = of_node_get(busnode);
+ bus->type = pmac_i2c_bus_smu;
+ bus->channel = *reg;
+ bus->mode = pmac_i2c_mode_std;
+ bus->hostdata = bus + 1;
+ bus->xfer = smu_i2c_xfer;
+ init_MUTEX(&bus->sem);
+ bus->flags = 0;
+ list_add(&bus->link, &pmac_i2c_busses);
+
+ printk(KERN_INFO " channel %x bus %s\n",
+ bus->channel, busnode->full_name);
+ }
+}
+
+#endif /* CONFIG_PMAC_SMU */
+
+/*
+ *
+ * Core code
+ *
+ */
-#ifdef CONFIG_ADB_PMU
- /* Probe PMU busses */
- np = of_find_node_by_name(NULL, "via-pmu");
- if (np)
- pmu_low_i2c_add(np);
-#endif /* CONFIG_ADB_PMU */
- /* TODO: Add CUDA support as well */
+struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node)
+{
+ struct device_node *p = of_node_get(node);
+ struct device_node *prev = NULL;
+ struct pmac_i2c_bus *bus;
+
+ while(p) {
+ list_for_each_entry(bus, &pmac_i2c_busses, link) {
+ if (p == bus->busnode) {
+ if (prev && bus->flags & pmac_i2c_multibus) {
+ u32 *reg;
+ reg = (u32 *)get_property(prev, "reg",
+ NULL);
+ if (!reg)
+ continue;
+ if (((*reg) >> 8) != bus->channel)
+ continue;
+ }
+ of_node_put(p);
+ of_node_put(prev);
+ return bus;
+ }
+ }
+ of_node_put(prev);
+ prev = p;
+ p = of_get_parent(p);
+ }
+ return NULL;
}
+EXPORT_SYMBOL_GPL(pmac_i2c_find_bus);
+
+u8 pmac_i2c_get_dev_addr(struct device_node *device)
+{
+ u32 *reg = (u32 *)get_property(device, "reg", NULL);
+
+ if (reg == NULL)
+ return 0;
+
+ return (*reg) & 0xff;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_dev_addr);
+
+struct device_node *pmac_i2c_get_controller(struct pmac_i2c_bus *bus)
+{
+ return bus->controller;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_controller);
+
+struct device_node *pmac_i2c_get_bus_node(struct pmac_i2c_bus *bus)
+{
+ return bus->busnode;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_bus_node);
+
+int pmac_i2c_get_type(struct pmac_i2c_bus *bus)
+{
+ return bus->type;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_type);
+
+int pmac_i2c_get_flags(struct pmac_i2c_bus *bus)
+{
+ return bus->flags;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_flags);
+
+int pmac_i2c_get_channel(struct pmac_i2c_bus *bus)
+{
+ return bus->channel;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_channel);
+
+
+void pmac_i2c_attach_adapter(struct pmac_i2c_bus *bus,
+ struct i2c_adapter *adapter)
+{
+ WARN_ON(bus->adapter != NULL);
+ bus->adapter = adapter;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_attach_adapter);
+
+void pmac_i2c_detach_adapter(struct pmac_i2c_bus *bus,
+ struct i2c_adapter *adapter)
+{
+ WARN_ON(bus->adapter != adapter);
+ bus->adapter = NULL;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_detach_adapter);
+
+struct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus)
+{
+ return bus->adapter;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_get_adapter);
+
+struct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter)
+{
+ struct pmac_i2c_bus *bus;
+
+ list_for_each_entry(bus, &pmac_i2c_busses, link)
+ if (bus->adapter == adapter)
+ return bus;
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_adapter_to_bus);
+
+extern int pmac_i2c_match_adapter(struct device_node *dev,
+ struct i2c_adapter *adapter)
+{
+ struct pmac_i2c_bus *bus = pmac_i2c_find_bus(dev);
+
+ if (bus == NULL)
+ return 0;
+ return (bus->adapter == adapter);
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_match_adapter);
int pmac_low_i2c_lock(struct device_node *np)
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ struct pmac_i2c_bus *bus, *found = NULL;
- if (!host)
+ list_for_each_entry(bus, &pmac_i2c_busses, link) {
+ if (np == bus->controller) {
+ found = bus;
+ break;
+ }
+ }
+ if (!found)
return -ENODEV;
- down(&host->mutex);
- return 0;
+ return pmac_i2c_open(bus, 0);
}
-EXPORT_SYMBOL(pmac_low_i2c_lock);
+EXPORT_SYMBOL_GPL(pmac_low_i2c_lock);
int pmac_low_i2c_unlock(struct device_node *np)
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ struct pmac_i2c_bus *bus, *found = NULL;
- if (!host)
+ list_for_each_entry(bus, &pmac_i2c_busses, link) {
+ if (np == bus->controller) {
+ found = bus;
+ break;
+ }
+ }
+ if (!found)
return -ENODEV;
- up(&host->mutex);
+ pmac_i2c_close(bus);
return 0;
}
-EXPORT_SYMBOL(pmac_low_i2c_unlock);
+EXPORT_SYMBOL_GPL(pmac_low_i2c_unlock);
-int pmac_low_i2c_open(struct device_node *np, int channel)
+int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled)
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ int rc;
+
+ down(&bus->sem);
+ bus->polled = polled || pmac_i2c_force_poll;
+ bus->opened = 1;
+ bus->mode = pmac_i2c_mode_std;
+ if (bus->open && (rc = bus->open(bus)) != 0) {
+ bus->opened = 0;
+ up(&bus->sem);
+ return rc;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_open);
- if (!host)
- return -ENODEV;
+void pmac_i2c_close(struct pmac_i2c_bus *bus)
+{
+ WARN_ON(!bus->opened);
+ if (bus->close)
+ bus->close(bus);
+ bus->opened = 0;
+ up(&bus->sem);
+}
+EXPORT_SYMBOL_GPL(pmac_i2c_close);
- if (channel >= host->num_channels)
+int pmac_i2c_setmode(struct pmac_i2c_bus *bus, int mode)
+{
+ WARN_ON(!bus->opened);
+
+ /* Report me if you see the error below as there might be a new
+ * "combined4" mode that I need to implement for the SMU bus
+ */
+ if (mode < pmac_i2c_mode_dumb || mode > pmac_i2c_mode_combined) {
+ printk(KERN_ERR "low_i2c: Invalid mode %d requested on"
+ " bus %s !\n", mode, bus->busnode->full_name);
return -EINVAL;
-
- down(&host->mutex);
- host->is_open = 1;
- host->channel = channel;
+ }
+ bus->mode = mode;
return 0;
}
-EXPORT_SYMBOL(pmac_low_i2c_open);
+EXPORT_SYMBOL_GPL(pmac_i2c_setmode);
-int pmac_low_i2c_close(struct device_node *np)
+int pmac_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len)
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ int rc;
- if (!host)
- return -ENODEV;
+ WARN_ON(!bus->opened);
- host->is_open = 0;
- up(&host->mutex);
+ DBG("xfer() chan=%d, addrdir=0x%x, mode=%d, subsize=%d, subaddr=0x%x,"
+ " %d bytes, bus %s\n", bus->channel, addrdir, bus->mode, subsize,
+ subaddr, len, bus->busnode->full_name);
- return 0;
+ rc = bus->xfer(bus, addrdir, subsize, subaddr, data, len);
+
+#ifdef DEBUG
+ if (rc)
+ DBG("xfer error %d\n", rc);
+#endif
+ return rc;
}
-EXPORT_SYMBOL(pmac_low_i2c_close);
+EXPORT_SYMBOL_GPL(pmac_i2c_xfer);
+
+/* some quirks for platform function decoding */
+enum {
+ pmac_i2c_quirk_invmask = 0x00000001u,
+};
-int pmac_low_i2c_setmode(struct device_node *np, int mode)
+static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
+ int quirks))
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ struct pmac_i2c_bus *bus;
+ struct device_node *np;
+ static struct whitelist_ent {
+ char *name;
+ char *compatible;
+ int quirks;
+ } whitelist[] = {
+ /* XXX Study device-tree's & apple drivers are get the quirks
+ * right !
+ */
+ { "i2c-hwclock", NULL, pmac_i2c_quirk_invmask },
+ { "i2c-cpu-voltage", NULL, 0},
+ { "temp-monitor", NULL, 0 },
+ { "supply-monitor", NULL, 0 },
+ { NULL, NULL, 0 },
+ };
+
+ /* Only some devices need to have platform functions instanciated
+ * here. For now, we have a table. Others, like 9554 i2c GPIOs used
+ * on Xserve, if we ever do a driver for them, will use their own
+ * platform function instance
+ */
+ list_for_each_entry(bus, &pmac_i2c_busses, link) {
+ for (np = NULL;
+ (np = of_get_next_child(bus->busnode, np)) != NULL;) {
+ struct whitelist_ent *p;
+ /* If multibus, check if device is on that bus */
+ if (bus->flags & pmac_i2c_multibus)
+ if (bus != pmac_i2c_find_bus(np))
+ continue;
+ for (p = whitelist; p->name != NULL; p++) {
+ if (strcmp(np->name, p->name))
+ continue;
+ if (p->compatible &&
+ !device_is_compatible(np, p->compatible))
+ continue;
+ callback(np, p->quirks);
+ break;
+ }
+ }
+ }
+}
- if (!host)
- return -ENODEV;
- WARN_ON(!host->is_open);
- host->mode = mode;
+#define MAX_I2C_DATA 64
+
+struct pmac_i2c_pf_inst
+{
+ struct pmac_i2c_bus *bus;
+ u8 addr;
+ u8 buffer[MAX_I2C_DATA];
+ u8 scratch[MAX_I2C_DATA];
+ int bytes;
+ int quirks;
+};
+
+static void* pmac_i2c_do_begin(struct pmf_function *func, struct pmf_args *args)
+{
+ struct pmac_i2c_pf_inst *inst;
+ struct pmac_i2c_bus *bus;
+
+ bus = pmac_i2c_find_bus(func->node);
+ if (bus == NULL) {
+ printk(KERN_ERR "low_i2c: Can't find bus for %s (pfunc)\n",
+ func->node->full_name);
+ return NULL;
+ }
+ if (pmac_i2c_open(bus, 0)) {
+ printk(KERN_ERR "low_i2c: Can't open i2c bus for %s (pfunc)\n",
+ func->node->full_name);
+ return NULL;
+ }
+
+ /* XXX might need GFP_ATOMIC when called during the suspend process,
+ * but then, there are already lots of issues with suspending when
+ * near OOM that need to be resolved, the allocator itself should
+ * probably make GFP_NOIO implicit during suspend
+ */
+ inst = kzalloc(sizeof(struct pmac_i2c_pf_inst), GFP_KERNEL);
+ if (inst == NULL) {
+ pmac_i2c_close(bus);
+ return NULL;
+ }
+ inst->bus = bus;
+ inst->addr = pmac_i2c_get_dev_addr(func->node);
+ inst->quirks = (int)(long)func->driver_data;
+ return inst;
+}
+
+static void pmac_i2c_do_end(struct pmf_function *func, void *instdata)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ if (inst == NULL)
+ return;
+ pmac_i2c_close(inst->bus);
+ if (inst)
+ kfree(inst);
+}
+
+static int pmac_i2c_do_read(PMF_STD_ARGS, u32 len)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ inst->bytes = len;
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_read, 0, 0,
+ inst->buffer, len);
+}
+
+static int pmac_i2c_do_write(PMF_STD_ARGS, u32 len, const u8 *data)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 0, 0,
+ (u8 *)data, len);
+}
+
+/* This function is used to do the masking & OR'ing for the "rmw" type
+ * callbacks. Ze should apply the mask and OR in the values in the
+ * buffer before writing back. The problem is that it seems that
+ * various darwin drivers implement the mask/or differently, thus
+ * we need to check the quirks first
+ */
+static void pmac_i2c_do_apply_rmw(struct pmac_i2c_pf_inst *inst,
+ u32 len, const u8 *mask, const u8 *val)
+{
+ int i;
+
+ if (inst->quirks & pmac_i2c_quirk_invmask) {
+ for (i = 0; i < len; i ++)
+ inst->scratch[i] = (inst->buffer[i] & mask[i]) | val[i];
+ } else {
+ for (i = 0; i < len; i ++)
+ inst->scratch[i] = (inst->buffer[i] & ~mask[i])
+ | (val[i] & mask[i]);
+ }
+}
+
+static int pmac_i2c_do_rmw(PMF_STD_ARGS, u32 masklen, u32 valuelen,
+ u32 totallen, const u8 *maskdata,
+ const u8 *valuedata)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ if (masklen > inst->bytes || valuelen > inst->bytes ||
+ totallen > inst->bytes || valuelen > masklen)
+ return -EINVAL;
+
+ pmac_i2c_do_apply_rmw(inst, masklen, maskdata, valuedata);
+
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 0, 0,
+ inst->scratch, totallen);
+}
+
+static int pmac_i2c_do_read_sub(PMF_STD_ARGS, u8 subaddr, u32 len)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ inst->bytes = len;
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_read, 1, subaddr,
+ inst->buffer, len);
+}
+
+static int pmac_i2c_do_write_sub(PMF_STD_ARGS, u8 subaddr, u32 len,
+ const u8 *data)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 1,
+ subaddr, (u8 *)data, len);
+}
+static int pmac_i2c_do_set_mode(PMF_STD_ARGS, int mode)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ return pmac_i2c_setmode(inst->bus, mode);
+}
+
+static int pmac_i2c_do_rmw_sub(PMF_STD_ARGS, u8 subaddr, u32 masklen,
+ u32 valuelen, u32 totallen, const u8 *maskdata,
+ const u8 *valuedata)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+
+ if (masklen > inst->bytes || valuelen > inst->bytes ||
+ totallen > inst->bytes || valuelen > masklen)
+ return -EINVAL;
+
+ pmac_i2c_do_apply_rmw(inst, masklen, maskdata, valuedata);
+
+ return pmac_i2c_xfer(inst->bus, inst->addr | pmac_i2c_write, 1,
+ subaddr, inst->scratch, totallen);
+}
+
+static int pmac_i2c_do_mask_and_comp(PMF_STD_ARGS, u32 len,
+ const u8 *maskdata,
+ const u8 *valuedata)
+{
+ struct pmac_i2c_pf_inst *inst = instdata;
+ int i, match;
+
+ /* Get return value pointer, it's assumed to be a u32 */
+ if (!args || !args->count || !args->u[0].p)
+ return -EINVAL;
+
+ /* Check buffer */
+ if (len > inst->bytes)
+ return -EINVAL;
+
+ for (i = 0, match = 1; match && i < len; i ++)
+ if ((inst->buffer[i] & maskdata[i]) != valuedata[i])
+ match = 0;
+ *args->u[0].p = match;
return 0;
}
-EXPORT_SYMBOL(pmac_low_i2c_setmode);
-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
+static int pmac_i2c_do_delay(PMF_STD_ARGS, u32 duration)
{
- struct low_i2c_host *host = find_low_i2c_host(np);
+ msleep((duration + 999) / 1000);
+ return 0;
+}
- if (!host)
- return -ENODEV;
- WARN_ON(!host->is_open);
- return host->func(host, addrdir, subaddr, data, len);
+static struct pmf_handlers pmac_i2c_pfunc_handlers = {
+ .begin = pmac_i2c_do_begin,
+ .end = pmac_i2c_do_end,
+ .read_i2c = pmac_i2c_do_read,
+ .write_i2c = pmac_i2c_do_write,
+ .rmw_i2c = pmac_i2c_do_rmw,
+ .read_i2c_sub = pmac_i2c_do_read_sub,
+ .write_i2c_sub = pmac_i2c_do_write_sub,
+ .rmw_i2c_sub = pmac_i2c_do_rmw_sub,
+ .set_i2c_mode = pmac_i2c_do_set_mode,
+ .mask_and_compare = pmac_i2c_do_mask_and_comp,
+ .delay = pmac_i2c_do_delay,
+};
+
+static void __init pmac_i2c_dev_create(struct device_node *np, int quirks)
+{
+ DBG("dev_create(%s)\n", np->full_name);
+
+ pmf_register_driver(np, &pmac_i2c_pfunc_handlers,
+ (void *)(long)quirks);
+}
+
+static void __init pmac_i2c_dev_init(struct device_node *np, int quirks)
+{
+ DBG("dev_create(%s)\n", np->full_name);
+
+ pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_INIT, NULL);
+}
+
+static void pmac_i2c_dev_suspend(struct device_node *np, int quirks)
+{
+ DBG("dev_suspend(%s)\n", np->full_name);
+ pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_SLEEP, NULL);
+}
+
+static void pmac_i2c_dev_resume(struct device_node *np, int quirks)
+{
+ DBG("dev_resume(%s)\n", np->full_name);
+ pmf_do_functions(np, NULL, 0, PMF_FLAGS_ON_WAKE, NULL);
+}
+
+void pmac_pfunc_i2c_suspend(void)
+{
+ pmac_i2c_devscan(pmac_i2c_dev_suspend);
+}
+
+void pmac_pfunc_i2c_resume(void)
+{
+ pmac_i2c_devscan(pmac_i2c_dev_resume);
+}
+
+/*
+ * Initialize us: probe all i2c busses on the machine, instantiate
+ * busses and platform functions as needed.
+ */
+/* This is non-static as it might be called early by smp code */
+int __init pmac_i2c_init(void)
+{
+ static int i2c_inited;
+
+ if (i2c_inited)
+ return 0;
+ i2c_inited = 1;
+
+ /* Probe keywest-i2c busses */
+ kw_i2c_probe();
+
+#ifdef CONFIG_ADB_PMU
+ /* Probe PMU i2c busses */
+ pmu_i2c_probe();
+#endif
+
+#ifdef CONFIG_PMAC_SMU
+ /* Probe SMU i2c busses */
+ smu_i2c_probe();
+#endif
+
+ /* Now add plaform functions for some known devices */
+ pmac_i2c_devscan(pmac_i2c_dev_create);
+
+ return 0;
}
-EXPORT_SYMBOL(pmac_low_i2c_xfer);
+arch_initcall(pmac_i2c_init);
+
+/* Since pmac_i2c_init can be called too early for the platform device
+ * registration, we need to do it at a later time. In our case, subsys
+ * happens to fit well, though I agree it's a bit of a hack...
+ */
+static int __init pmac_i2c_create_platform_devices(void)
+{
+ struct pmac_i2c_bus *bus;
+ int i = 0;
+
+ /* In the case where we are initialized from smp_init(), we must
+ * not use the timer (and thus the irq). It's safe from now on
+ * though
+ */
+ pmac_i2c_force_poll = 0;
+
+ /* Create platform devices */
+ list_for_each_entry(bus, &pmac_i2c_busses, link) {
+ bus->platform_dev =
+ platform_device_alloc("i2c-powermac", i++);
+ if (bus->platform_dev == NULL)
+ return -ENOMEM;
+ bus->platform_dev->dev.platform_data = bus;
+ platform_device_add(bus->platform_dev);
+ }
+
+ /* Now call platform "init" functions */
+ pmac_i2c_devscan(pmac_i2c_dev_init);
+ return 0;
+}
+subsys_initcall(pmac_i2c_create_platform_devices);
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c
index 4042e2f06ee0..3ebd045a3350 100644
--- a/arch/powerpc/platforms/powermac/nvram.c
+++ b/arch/powerpc/platforms/powermac/nvram.c
@@ -514,7 +514,7 @@ static void core99_nvram_sync(void)
#endif
}
-static int __init core99_nvram_setup(struct device_node *dp)
+static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
{
int i;
u32 gen_bank0, gen_bank1;
@@ -528,7 +528,7 @@ static int __init core99_nvram_setup(struct device_node *dp)
printk(KERN_ERR "nvram: can't allocate ram image\n");
return -ENOMEM;
}
- nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+ nvram_data = ioremap(addr, NVRAM_SIZE*2);
nvram_naddrs = 1; /* Make sure we get the correct case */
DBG("nvram: Checking bank 0...\n");
@@ -549,6 +549,7 @@ static int __init core99_nvram_setup(struct device_node *dp)
ppc_md.nvram_write = core99_nvram_write;
ppc_md.nvram_size = core99_nvram_size;
ppc_md.nvram_sync = core99_nvram_sync;
+ ppc_md.machine_shutdown = core99_nvram_sync;
/*
* Maybe we could be smarter here though making an exclusive list
* of known flash chips is a bit nasty as older OF didn't provide us
@@ -569,34 +570,48 @@ static int __init core99_nvram_setup(struct device_node *dp)
int __init pmac_nvram_init(void)
{
struct device_node *dp;
+ struct resource r1, r2;
+ unsigned int s1 = 0, s2 = 0;
int err = 0;
nvram_naddrs = 0;
- dp = find_devices("nvram");
+ dp = of_find_node_by_name(NULL, "nvram");
if (dp == NULL) {
printk(KERN_ERR "Can't find NVRAM device\n");
return -ENODEV;
}
- nvram_naddrs = dp->n_addrs;
+
+ /* Try to obtain an address */
+ if (of_address_to_resource(dp, 0, &r1) == 0) {
+ nvram_naddrs = 1;
+ s1 = (r1.end - r1.start) + 1;
+ if (of_address_to_resource(dp, 1, &r2) == 0) {
+ nvram_naddrs = 2;
+ s2 = (r2.end - r2.start) + 1;
+ }
+ }
+
is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99)
- err = core99_nvram_setup(dp);
+ if (is_core_99) {
+ err = core99_nvram_setup(dp, r1.start);
+ goto bail;
+ }
+
#ifdef CONFIG_PPC32
- else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
- dp->addrs[0].size);
+ if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+ nvram_data = ioremap(r1.start, s1);
nvram_mult = 1;
ppc_md.nvram_read_val = direct_nvram_read_byte;
ppc_md.nvram_write_val = direct_nvram_write_byte;
} else if (nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
+ nvram_data = ioremap(r1.start, s1);
+ nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE;
ppc_md.nvram_read_val = direct_nvram_read_byte;
ppc_md.nvram_write_val = direct_nvram_write_byte;
} else if (nvram_naddrs == 2) {
- nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
+ nvram_addr = ioremap(r1.start, s1);
+ nvram_data = ioremap(r2.start, s2);
ppc_md.nvram_read_val = indirect_nvram_read_byte;
ppc_md.nvram_write_val = indirect_nvram_write_byte;
} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
@@ -605,13 +620,15 @@ int __init pmac_nvram_init(void)
ppc_md.nvram_read_val = pmu_nvram_read_byte;
ppc_md.nvram_write_val = pmu_nvram_write_byte;
#endif /* CONFIG_ADB_PMU */
- }
-#endif
- else {
+ } else {
printk(KERN_ERR "Incompatible type of NVRAM\n");
- return -ENXIO;
+ err = -ENXIO;
}
- lookup_partitions();
+#endif /* CONFIG_PPC32 */
+bail:
+ of_node_put(dp);
+ if (err == 0)
+ lookup_partitions();
return err;
}
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 443be526cde7..f671ed253901 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1,7 +1,7 @@
/*
* Support for PCI bridges found on Power Macintoshes.
*
- * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org)
+ * Copyright (C) 2003-2005 Benjamin Herrenschmuidt (benh@kernel.crashing.org)
* Copyright (C) 1997 Paul Mackerras (paulus@samba.org)
*
* This program is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@
#include <asm/pmac_feature.h>
#include <asm/grackle.h>
#ifdef CONFIG_PPC64
-#include <asm/iommu.h>
+//#include <asm/iommu.h>
#include <asm/ppc-pci.h>
#endif
@@ -44,6 +44,7 @@ static int add_bridge(struct device_node *dev);
static int has_uninorth;
#ifdef CONFIG_PPC64
static struct pci_controller *u3_agp;
+static struct pci_controller *u4_pcie;
static struct pci_controller *u3_ht;
#endif /* CONFIG_PPC64 */
@@ -97,11 +98,8 @@ static void __init fixup_bus_range(struct device_node *bridge)
/* Lookup the "bus-range" property for the hose */
bus_range = (int *) get_property(bridge, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- bridge->full_name);
+ if (bus_range == NULL || len < 2 * sizeof(int))
return;
- }
bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
}
@@ -128,14 +126,14 @@ static void __init fixup_bus_range(struct device_node *bridge)
*/
#define MACRISC_CFA0(devfn, off) \
- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
- | (((unsigned long)(off)) & 0xFCUL))
+ ((1 << (unsigned int)PCI_SLOT(dev_fn)) \
+ | (((unsigned int)PCI_FUNC(dev_fn)) << 8) \
+ | (((unsigned int)(off)) & 0xFCUL))
#define MACRISC_CFA1(bus, devfn, off) \
- ((((unsigned long)(bus)) << 16) \
- |(((unsigned long)(devfn)) << 8) \
- |(((unsigned long)(off)) & 0xFCUL) \
+ ((((unsigned int)(bus)) << 16) \
+ |(((unsigned int)(devfn)) << 8) \
+ |(((unsigned int)(off)) & 0xFCUL) \
|1UL)
static unsigned long macrisc_cfg_access(struct pci_controller* hose,
@@ -168,7 +166,8 @@ static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn,
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
-
+ if (offset >= 0x100)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -199,7 +198,8 @@ static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn,
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
-
+ if (offset >= 0x100)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -234,12 +234,13 @@ static struct pci_ops macrisc_pci_ops =
/*
* Verify that a specific (bus, dev_fn) exists on chaos
*/
-static int
-chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
+static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
{
struct device_node *np;
u32 *vendor, *device;
+ if (offset >= 0x100)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
np = pci_busdev_to_OF_node(bus, devfn);
if (np == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -285,15 +286,13 @@ static struct pci_ops chaos_pci_ops =
};
static void __init setup_chaos(struct pci_controller *hose,
- struct reg_property *addr)
+ struct resource *addr)
{
/* assume a `chaos' bridge */
hose->ops = &chaos_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+ hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000);
}
-#else
-#define setup_chaos(hose, addr)
#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
@@ -326,7 +325,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->data && PCI_DN(dn)->devfn == devfn)
+ if (PCI_DN(dn) && PCI_DN(dn)->devfn == devfn)
break;
if (dn == NULL)
return -1;
@@ -343,10 +342,10 @@ static int u3_ht_skip_device(struct pci_controller *hose,
}
#define U3_HT_CFA0(devfn, off) \
- ((((unsigned long)devfn) << 8) | offset)
+ ((((unsigned int)devfn) << 8) | offset)
#define U3_HT_CFA1(bus, devfn, off) \
(U3_HT_CFA0(devfn, off) \
- + (((unsigned long)bus) << 16) \
+ + (((unsigned int)bus) << 16) \
+ 0x01000000UL)
static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
@@ -356,9 +355,11 @@ static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
/* For now, we don't self probe U3 HT bridge */
if (PCI_SLOT(devfn) == 0)
return 0;
- return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset);
+ return ((unsigned long)hose->cfg_data) +
+ U3_HT_CFA0(devfn, offset);
} else
- return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset);
+ return ((unsigned long)hose->cfg_data) +
+ U3_HT_CFA1(bus, devfn, offset);
}
static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -370,7 +371,8 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
-
+ if (offset >= 0x100)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -419,7 +421,8 @@ static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn,
hose = pci_bus_to_host(bus);
if (hose == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
-
+ if (offset >= 0x100)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
@@ -459,6 +462,112 @@ static struct pci_ops u3_ht_pci_ops =
u3_ht_read_config,
u3_ht_write_config
};
+
+#define U4_PCIE_CFA0(devfn, off) \
+ ((1 << ((unsigned int)PCI_SLOT(dev_fn))) \
+ | (((unsigned int)PCI_FUNC(dev_fn)) << 8) \
+ | ((((unsigned int)(off)) >> 8) << 28) \
+ | (((unsigned int)(off)) & 0xfcU))
+
+#define U4_PCIE_CFA1(bus, devfn, off) \
+ ((((unsigned int)(bus)) << 16) \
+ |(((unsigned int)(devfn)) << 8) \
+ | ((((unsigned int)(off)) >> 8) << 28) \
+ |(((unsigned int)(off)) & 0xfcU) \
+ |1UL)
+
+static unsigned long u4_pcie_cfg_access(struct pci_controller* hose,
+ u8 bus, u8 dev_fn, int offset)
+{
+ unsigned int caddr;
+
+ if (bus == hose->first_busno) {
+ caddr = U4_PCIE_CFA0(dev_fn, offset);
+ } else
+ caddr = U4_PCIE_CFA1(bus, dev_fn, offset);
+
+ /* Uninorth will return garbage if we don't read back the value ! */
+ do {
+ out_le32(hose->cfg_addr, caddr);
+ } while (in_le32(hose->cfg_addr) != caddr);
+
+ offset &= 0x03;
+ return ((unsigned long)hose->cfg_data) + offset;
+}
+
+static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose;
+ unsigned long addr;
+
+ hose = pci_bus_to_host(bus);
+ if (hose == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (offset >= 0x1000)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ *val = in_8((u8 *)addr);
+ break;
+ case 2:
+ *val = in_le16((u16 *)addr);
+ break;
+ default:
+ *val = in_le32((u32 *)addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose;
+ unsigned long addr;
+
+ hose = pci_bus_to_host(bus);
+ if (hose == NULL)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (offset >= 0x1000)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+ if (!addr)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ out_8((u8 *)addr, val);
+ (void) in_8((u8 *)addr);
+ break;
+ case 2:
+ out_le16((u16 *)addr, val);
+ (void) in_le16((u16 *)addr);
+ break;
+ default:
+ out_le32((u32 *)addr, val);
+ (void) in_le32((u32 *)addr);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u4_pcie_pci_ops =
+{
+ u4_pcie_read_config,
+ u4_pcie_write_config
+};
+
#endif /* CONFIG_PPC64 */
#ifdef CONFIG_PPC32
@@ -532,7 +641,8 @@ static void __init init_p2pbridge(void)
}
if (early_read_config_word(hose, bus, devfn,
PCI_BRIDGE_CONTROL, &val) < 0) {
- printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
+ printk(KERN_ERR "init_p2pbridge: couldn't read bridge"
+ " control\n");
return;
}
val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
@@ -576,36 +686,38 @@ static void __init fixup_nec_usb2(void)
continue;
early_read_config_dword(hose, bus, devfn, 0xe4, &data);
if (data & 1UL) {
- printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");
+ printk("Found NEC PD720100A USB2 chip with disabled"
+ " EHCI, fixing up...\n");
data &= ~1UL;
early_write_config_dword(hose, bus, devfn, 0xe4, data);
- early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,
+ early_write_config_byte(hose, bus,
+ devfn | 2, PCI_INTERRUPT_LINE,
nec->intrs[0].line);
}
}
}
static void __init setup_bandit(struct pci_controller *hose,
- struct reg_property *addr)
+ struct resource *addr)
{
hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+ hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000);
init_bandit(hose);
}
static int __init setup_uninorth(struct pci_controller *hose,
- struct reg_property *addr)
+ struct resource *addr)
{
pci_assign_all_buses = 1;
has_uninorth = 1;
hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+ hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(addr->start + 0xc00000, 0x1000);
/* We "know" that the bridge at f2000000 has the PCI slots. */
- return addr->address == 0xf2000000;
+ return addr->start == 0xf2000000;
}
-#endif
+#endif /* CONFIG_PPC32 */
#ifdef CONFIG_PPC64
static void __init setup_u3_agp(struct pci_controller* hose)
@@ -625,15 +737,36 @@ static void __init setup_u3_agp(struct pci_controller* hose)
hose->ops = &macrisc_pci_ops;
hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
-
u3_agp = hose;
}
+static void __init setup_u4_pcie(struct pci_controller* hose)
+{
+ /* We currently only implement the "non-atomic" config space, to
+ * be optimised later.
+ */
+ hose->ops = &u4_pcie_pci_ops;
+ hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+ hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+ /* The bus contains a bridge from root -> device, we need to
+ * make it visible on bus 0 so that we pick the right type
+ * of config cycles. If we didn't, we would have to force all
+ * config cycles to be type 1. So we override the "bus-range"
+ * property here
+ */
+ hose->first_busno = 0x00;
+ hose->last_busno = 0xff;
+ u4_pcie = hose;
+}
+
static void __init setup_u3_ht(struct pci_controller* hose)
{
struct device_node *np = (struct device_node *)hose->arch_data;
+ struct pci_controller *other = NULL;
int i, cur;
+
hose->ops = &u3_ht_pci_ops;
/* We hard code the address because of the different size of
@@ -667,11 +800,20 @@ static void __init setup_u3_ht(struct pci_controller* hose)
u3_ht = hose;
- if (u3_agp == NULL) {
- DBG("U3 has no AGP, using full resource range\n");
+ if (u3_agp != NULL)
+ other = u3_agp;
+ else if (u4_pcie != NULL)
+ other = u4_pcie;
+
+ if (other == NULL) {
+ DBG("U3/4 has no AGP/PCIE, using full resource range\n");
return;
}
+ /* Fixup bus range vs. PCIE */
+ if (u4_pcie)
+ hose->last_busno = u4_pcie->first_busno - 1;
+
/* We "remove" the AGP resources from the resources allocated to HT,
* that is we create "holes". However, that code does assumptions
* that so far happen to be true (cross fingers...), typically that
@@ -679,7 +821,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
*/
cur = 0;
for (i=0; i<3; i++) {
- struct resource *res = &u3_agp->mem_resources[i];
+ struct resource *res = &other->mem_resources[i];
if (res->flags != IORESOURCE_MEM)
continue;
/* We don't care about "fine" resources */
@@ -722,7 +864,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
hose->mem_resources[cur-1].end = res->start - 1;
}
}
-#endif
+#endif /* CONFIG_PPC64 */
/*
* We assume that if we have a G3 powermac, we have one bridge called
@@ -733,24 +875,17 @@ static int __init add_bridge(struct device_node *dev)
{
int len;
struct pci_controller *hose;
-#ifdef CONFIG_PPC32
- struct reg_property *addr;
-#endif
+ struct resource rsrc;
char *disp_name;
int *bus_range;
- int primary = 1;
+ int primary = 1, has_address = 0;
DBG("Adding PCI host bridge %s\n", dev->full_name);
-#ifdef CONFIG_PPC32
- /* XXX fix this */
- addr = (struct reg_property *) get_property(dev, "reg", &len);
- if (addr == NULL || len < sizeof(*addr)) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- return -ENODEV;
- }
-#endif
+ /* Fetch host bridge registers address */
+ has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+ /* Get bus range if any */
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"
@@ -770,6 +905,8 @@ static int __init add_bridge(struct device_node *dev)
hose->last_busno = bus_range ? bus_range[1] : 0xff;
disp_name = NULL;
+
+ /* 64 bits only bridges */
#ifdef CONFIG_PPC64
if (device_is_compatible(dev, "u3-agp")) {
setup_u3_agp(hose);
@@ -779,28 +916,37 @@ static int __init add_bridge(struct device_node *dev)
setup_u3_ht(hose);
disp_name = "U3-HT";
primary = 1;
+ } else if (device_is_compatible(dev, "u4-pcie")) {
+ setup_u4_pcie(hose);
+ disp_name = "U4-PCIE";
+ primary = 0;
}
- printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n",
- disp_name, hose->first_busno, hose->last_busno);
-#else
+ printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number:"
+ " %d->%d\n", disp_name, hose->first_busno, hose->last_busno);
+#endif /* CONFIG_PPC64 */
+
+ /* 32 bits only bridges */
+#ifdef CONFIG_PPC32
if (device_is_compatible(dev, "uni-north")) {
- primary = setup_uninorth(hose, addr);
+ primary = setup_uninorth(hose, &rsrc);
disp_name = "UniNorth";
} else if (strcmp(dev->name, "pci") == 0) {
/* XXX assume this is a mpc106 (grackle) */
setup_grackle(hose);
disp_name = "Grackle (MPC106)";
} else if (strcmp(dev->name, "bandit") == 0) {
- setup_bandit(hose, addr);
+ setup_bandit(hose, &rsrc);
disp_name = "Bandit";
} else if (strcmp(dev->name, "chaos") == 0) {
- setup_chaos(hose, addr);
+ setup_chaos(hose, &rsrc);
disp_name = "Chaos";
primary = 0;
}
- printk(KERN_INFO "Found %s PCI host bridge at 0x%08lx. Firmware bus number: %d->%d\n",
- disp_name, addr->address, hose->first_busno, hose->last_busno);
-#endif
+ printk(KERN_INFO "Found %s PCI host bridge at 0x%08lx. "
+ "Firmware bus number: %d->%d\n",
+ disp_name, rsrc.start, hose->first_busno, hose->last_busno);
+#endif /* CONFIG_PPC32 */
+
DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
hose, hose->cfg_addr, hose->cfg_data);
@@ -814,8 +960,7 @@ static int __init add_bridge(struct device_node *dev)
return 0;
}
-static void __init
-pcibios_fixup_OF_interrupts(void)
+static void __init pcibios_fixup_OF_interrupts(void)
{
struct pci_dev* dev = NULL;
@@ -835,8 +980,7 @@ pcibios_fixup_OF_interrupts(void)
}
}
-void __init
-pmac_pcibios_fixup(void)
+void __init pmac_pcibios_fixup(void)
{
/* Fixup interrupts according to OF tree */
pcibios_fixup_OF_interrupts();
@@ -899,6 +1043,8 @@ void __init pmac_pci_init(void)
pci_setup_phb_io(u3_ht, 1);
if (u3_agp)
pci_setup_phb_io(u3_agp, 0);
+ if (u4_pcie)
+ pci_setup_phb_io(u4_pcie, 0);
/*
* On ppc64, fixup the IO resources on our host bridges as
@@ -911,7 +1057,8 @@ void __init pmac_pci_init(void)
/* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
* assume there is no P2P bridge on the AGP bus, which should be a
- * safe assumptions hopefully.
+ * safe assumptions for now. We should do something better in the
+ * future though
*/
if (u3_agp) {
struct device_node *np = u3_agp->arch_data;
@@ -919,7 +1066,6 @@ void __init pmac_pci_init(void)
for (np = np->child; np; np = np->sibling)
PCI_DN(np)->busno = 0xf0;
}
-
/* pmac_check_ht_link(); */
/* Tell pci.c to not use the common resource allocation mechanism */
@@ -1126,7 +1272,8 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
good:
pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
if ((progif & 5) != 5) {
- printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
+ printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n",
+ pci_name(dev));
(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
(progif & 5) != 5)
@@ -1152,7 +1299,8 @@ static void fixup_k2_sata(struct pci_dev* dev)
for (i = 0; i < 6; i++) {
dev->resource[i].start = dev->resource[i].end = 0;
dev->resource[i].flags = 0;
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i,
+ 0);
}
} else {
pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -1161,7 +1309,8 @@ static void fixup_k2_sata(struct pci_dev* dev)
for (i = 0; i < 5; i++) {
dev->resource[i].start = dev->resource[i].end = 0;
dev->resource[i].flags = 0;
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i,
+ 0);
}
}
}
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
new file mode 100644
index 000000000000..4ffd2a9832a0
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -0,0 +1,405 @@
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+
+#define DBG(fmt...) printk(fmt)
+
+static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs)
+{
+ pmf_do_irq(data);
+
+ return IRQ_HANDLED;
+}
+
+static int macio_do_gpio_irq_enable(struct pmf_function *func)
+{
+ if (func->node->n_intrs < 1)
+ return -EINVAL;
+
+ return request_irq(func->node->intrs[0].line, macio_gpio_irq, 0,
+ func->node->name, func);
+}
+
+static int macio_do_gpio_irq_disable(struct pmf_function *func)
+{
+ if (func->node->n_intrs < 1)
+ return -EINVAL;
+
+ free_irq(func->node->intrs[0].line, func);
+ return 0;
+}
+
+static int macio_do_gpio_write(PMF_STD_ARGS, u8 value, u8 mask)
+{
+ u8 __iomem *addr = (u8 __iomem *)func->driver_data;
+ unsigned long flags;
+ u8 tmp;
+
+ /* Check polarity */
+ if (args && args->count && !args->u[0].v)
+ value = ~value;
+
+ /* Toggle the GPIO */
+ spin_lock_irqsave(&feature_lock, flags);
+ tmp = readb(addr);
+ tmp = (tmp & ~mask) | (value & mask);
+ DBG("Do write 0x%02x to GPIO %s (%p)\n",
+ tmp, func->node->full_name, addr);
+ writeb(tmp, addr);
+ spin_unlock_irqrestore(&feature_lock, flags);
+
+ return 0;
+}
+
+static int macio_do_gpio_read(PMF_STD_ARGS, u8 mask, int rshift, u8 xor)
+{
+ u8 __iomem *addr = (u8 __iomem *)func->driver_data;
+ u32 value;
+
+ /* Check if we have room for reply */
+ if (args == NULL || args->count == 0 || args->u[0].p == NULL)
+ return -EINVAL;
+
+ value = readb(addr);
+ *args->u[0].p = ((value & mask) >> rshift) ^ xor;
+
+ return 0;
+}
+
+static int macio_do_delay(PMF_STD_ARGS, u32 duration)
+{
+ /* assume we can sleep ! */
+ msleep((duration + 999) / 1000);
+ return 0;
+}
+
+static struct pmf_handlers macio_gpio_handlers = {
+ .irq_enable = macio_do_gpio_irq_enable,
+ .irq_disable = macio_do_gpio_irq_disable,
+ .write_gpio = macio_do_gpio_write,
+ .read_gpio = macio_do_gpio_read,
+ .delay = macio_do_delay,
+};
+
+static void macio_gpio_init_one(struct macio_chip *macio)
+{
+ struct device_node *gparent, *gp;
+
+ /*
+ * Find the "gpio" parent node
+ */
+
+ for (gparent = NULL;
+ (gparent = of_get_next_child(macio->of_node, gparent)) != NULL;)
+ if (strcmp(gparent->name, "gpio") == 0)
+ break;
+ if (gparent == NULL)
+ return;
+
+ DBG("Installing GPIO functions for macio %s\n",
+ macio->of_node->full_name);
+
+ /*
+ * Ok, got one, we dont need anything special to track them down, so
+ * we just create them all
+ */
+ for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;) {
+ u32 *reg = (u32 *)get_property(gp, "reg", NULL);
+ unsigned long offset;
+ if (reg == NULL)
+ continue;
+ offset = *reg;
+ /* Deal with old style device-tree. We can safely hard code the
+ * offset for now too even if it's a bit gross ...
+ */
+ if (offset < 0x50)
+ offset += 0x50;
+ offset += (unsigned long)macio->base;
+ pmf_register_driver(gp, &macio_gpio_handlers, (void *)offset);
+ }
+
+ DBG("Calling initial GPIO functions for macio %s\n",
+ macio->of_node->full_name);
+
+ /* And now we run all the init ones */
+ for (gp = NULL; (gp = of_get_next_child(gparent, gp)) != NULL;)
+ pmf_do_functions(gp, NULL, 0, PMF_FLAGS_ON_INIT, NULL);
+
+ /* Note: We do not at this point implement the "at sleep" or "at wake"
+ * functions. I yet to find any for GPIOs anyway
+ */
+}
+
+static int macio_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)
+{
+ struct macio_chip *macio = func->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&feature_lock, flags);
+ MACIO_OUT32(offset, (MACIO_IN32(offset) & ~mask) | (value & mask));
+ spin_unlock_irqrestore(&feature_lock, flags);
+ return 0;
+}
+
+static int macio_do_read_reg32(PMF_STD_ARGS, u32 offset)
+{
+ struct macio_chip *macio = func->driver_data;
+
+ /* Check if we have room for reply */
+ if (args == NULL || args->count == 0 || args->u[0].p == NULL)
+ return -EINVAL;
+
+ *args->u[0].p = MACIO_IN32(offset);
+ return 0;
+}
+
+static int macio_do_write_reg8(PMF_STD_ARGS, u32 offset, u8 value, u8 mask)
+{
+ struct macio_chip *macio = func->driver_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&feature_lock, flags);
+ MACIO_OUT8(offset, (MACIO_IN8(offset) & ~mask) | (value & mask));
+ spin_unlock_irqrestore(&feature_lock, flags);
+ return 0;
+}
+
+static int macio_do_read_reg8(PMF_STD_ARGS, u32 offset)
+{
+ struct macio_chip *macio = func->driver_data;
+
+ /* Check if we have room for reply */
+ if (args == NULL || args->count == 0 || args->u[0].p == NULL)
+ return -EINVAL;
+
+ *((u8 *)(args->u[0].p)) = MACIO_IN8(offset);
+ return 0;
+}
+
+static int macio_do_read_reg32_msrx(PMF_STD_ARGS, u32 offset, u32 mask,
+ u32 shift, u32 xor)
+{
+ struct macio_chip *macio = func->driver_data;
+
+ /* Check if we have room for reply */
+ if (args == NULL || args->count == 0 || args->u[0].p == NULL)
+ return -EINVAL;
+
+ *args->u[0].p = ((MACIO_IN32(offset) & mask) >> shift) ^ xor;
+ return 0;
+}
+
+static int macio_do_read_reg8_msrx(PMF_STD_ARGS, u32 offset, u32 mask,
+ u32 shift, u32 xor)
+{
+ struct macio_chip *macio = func->driver_data;
+
+ /* Check if we have room for reply */
+ if (args == NULL || args->count == 0 || args->u[0].p == NULL)
+ return -EINVAL;
+
+ *((u8 *)(args->u[0].p)) = ((MACIO_IN8(offset) & mask) >> shift) ^ xor;
+ return 0;
+}
+
+static int macio_do_write_reg32_slm(PMF_STD_ARGS, u32 offset, u32 shift,
+ u32 mask)
+{
+ struct macio_chip *macio = func->driver_data;
+ unsigned long flags;
+ u32 tmp, val;
+
+ /* Check args */
+ if (args == NULL || args->count == 0)
+ return -EINVAL;
+
+ spin_lock_irqsave(&feature_lock, flags);
+ tmp = MACIO_IN32(offset);
+ val = args->u[0].v << shift;
+ tmp = (tmp & ~mask) | (val & mask);
+ MACIO_OUT32(offset, tmp);
+ spin_unlock_irqrestore(&feature_lock, flags);
+ return 0;
+}
+
+static int macio_do_write_reg8_slm(PMF_STD_ARGS, u32 offset, u32 shift,
+ u32 mask)
+{
+ struct macio_chip *macio = func->driver_data;
+ unsigned long flags;
+ u32 tmp, val;
+
+ /* Check args */
+ if (args == NULL || args->count == 0)
+ return -EINVAL;
+
+ spin_lock_irqsave(&feature_lock, flags);
+ tmp = MACIO_IN8(offset);
+ val = args->u[0].v << shift;
+ tmp = (tmp & ~mask) | (val & mask);
+ MACIO_OUT8(offset, tmp);
+ spin_unlock_irqrestore(&feature_lock, flags);
+ return 0;
+}
+
+static struct pmf_handlers macio_mmio_handlers = {
+ .write_reg32 = macio_do_write_reg32,
+ .read_reg32 = macio_do_read_reg32,
+ .write_reg8 = macio_do_write_reg8,
+ .read_reg32 = macio_do_read_reg8,
+ .read_reg32_msrx = macio_do_read_reg32_msrx,
+ .read_reg8_msrx = macio_do_read_reg8_msrx,
+ .write_reg32_slm = macio_do_write_reg32_slm,
+ .write_reg8_slm = macio_do_write_reg8_slm,
+ .delay = macio_do_delay,
+};
+
+static void macio_mmio_init_one(struct macio_chip *macio)
+{
+ DBG("Installing MMIO functions for macio %s\n",
+ macio->of_node->full_name);
+
+ pmf_register_driver(macio->of_node, &macio_mmio_handlers, macio);
+}
+
+static struct device_node *unin_hwclock;
+
+static int unin_do_write_reg32(PMF_STD_ARGS, u32 offset, u32 value, u32 mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&feature_lock, flags);
+ /* This is fairly bogus in darwin, but it should work for our needs
+ * implemeted that way:
+ */
+ UN_OUT(offset, (UN_IN(offset) & ~mask) | (value & mask));
+ spin_unlock_irqrestore(&feature_lock, flags);
+ return 0;
+}
+
+
+static struct pmf_handlers unin_mmio_handlers = {
+ .write_reg32 = unin_do_write_reg32,
+ .delay = macio_do_delay,
+};
+
+static void uninorth_install_pfunc(void)
+{
+ struct device_node *np;
+
+ DBG("Installing functions for UniN %s\n",
+ uninorth_node->full_name);
+
+ /*
+ * Install handlers for the bridge itself
+ */
+ pmf_register_driver(uninorth_node, &unin_mmio_handlers, NULL);
+ pmf_do_functions(uninorth_node, NULL, 0, PMF_FLAGS_ON_INIT, NULL);
+
+
+ /*
+ * Install handlers for the hwclock child if any
+ */
+ for (np = NULL; (np = of_get_next_child(uninorth_node, np)) != NULL;)
+ if (strcmp(np->name, "hw-clock") == 0) {
+ unin_hwclock = np;
+ break;
+ }
+ if (unin_hwclock) {
+ DBG("Installing functions for UniN clock %s\n",
+ unin_hwclock->full_name);
+ pmf_register_driver(unin_hwclock, &unin_mmio_handlers, NULL);
+ pmf_do_functions(unin_hwclock, NULL, 0, PMF_FLAGS_ON_INIT,
+ NULL);
+ }
+}
+
+/* We export this as the SMP code might init us early */
+int __init pmac_pfunc_base_install(void)
+{
+ static int pfbase_inited;
+ int i;
+
+ if (pfbase_inited)
+ return 0;
+ pfbase_inited = 1;
+
+
+ DBG("Installing base platform functions...\n");
+
+ /*
+ * Locate mac-io chips and install handlers
+ */
+ for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {
+ if (macio_chips[i].of_node) {
+ macio_mmio_init_one(&macio_chips[i]);
+ macio_gpio_init_one(&macio_chips[i]);
+ }
+ }
+
+ /*
+ * Install handlers for northbridge and direct mapped hwclock
+ * if any. We do not implement the config space access callback
+ * which is only ever used for functions that we do not call in
+ * the current driver (enabling/disabling cells in U2, mostly used
+ * to restore the PCI settings, we do that differently)
+ */
+ if (uninorth_node && uninorth_base)
+ uninorth_install_pfunc();
+
+ DBG("All base functions installed\n");
+
+ return 0;
+}
+
+arch_initcall(pmac_pfunc_base_install);
+
+#ifdef CONFIG_PM
+
+/* Those can be called by pmac_feature. Ultimately, I should use a sysdev
+ * or a device, but for now, that's good enough until I sort out some
+ * ordering issues. Also, we do not bother with GPIOs, as so far I yet have
+ * to see a case where a GPIO function has the on-suspend or on-resume bit
+ */
+void pmac_pfunc_base_suspend(void)
+{
+ int i;
+
+ for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {
+ if (macio_chips[i].of_node)
+ pmf_do_functions(macio_chips[i].of_node, NULL, 0,
+ PMF_FLAGS_ON_SLEEP, NULL);
+ }
+ if (uninorth_node)
+ pmf_do_functions(uninorth_node, NULL, 0,
+ PMF_FLAGS_ON_SLEEP, NULL);
+ if (unin_hwclock)
+ pmf_do_functions(unin_hwclock, NULL, 0,
+ PMF_FLAGS_ON_SLEEP, NULL);
+}
+
+void pmac_pfunc_base_resume(void)
+{
+ int i;
+
+ if (unin_hwclock)
+ pmf_do_functions(unin_hwclock, NULL, 0,
+ PMF_FLAGS_ON_WAKE, NULL);
+ if (uninorth_node)
+ pmf_do_functions(uninorth_node, NULL, 0,
+ PMF_FLAGS_ON_WAKE, NULL);
+ for (i = 0 ; i < MAX_MACIO_CHIPS; i++) {
+ if (macio_chips[i].of_node)
+ pmf_do_functions(macio_chips[i].of_node, NULL, 0,
+ PMF_FLAGS_ON_WAKE, NULL);
+ }
+}
+
+#endif /* CONFIG_PM */
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
new file mode 100644
index 000000000000..c32c623001dc
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -0,0 +1,989 @@
+/*
+ *
+ * FIXME: Properly make this race free with refcounting etc...
+ *
+ * FIXME: LOCKING !!!
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+
+#include <asm/semaphore.h>
+#include <asm/prom.h>
+#include <asm/pmac_pfunc.h>
+
+/* Debug */
+#define LOG_PARSE(fmt...)
+#define LOG_ERROR(fmt...) printk(fmt)
+#define LOG_BLOB(t,b,c)
+#define DBG(fmt...) printk(fmt)
+
+/* Command numbers */
+#define PMF_CMD_LIST 0
+#define PMF_CMD_WRITE_GPIO 1
+#define PMF_CMD_READ_GPIO 2
+#define PMF_CMD_WRITE_REG32 3
+#define PMF_CMD_READ_REG32 4
+#define PMF_CMD_WRITE_REG16 5
+#define PMF_CMD_READ_REG16 6
+#define PMF_CMD_WRITE_REG8 7
+#define PMF_CMD_READ_REG8 8
+#define PMF_CMD_DELAY 9
+#define PMF_CMD_WAIT_REG32 10
+#define PMF_CMD_WAIT_REG16 11
+#define PMF_CMD_WAIT_REG8 12
+#define PMF_CMD_READ_I2C 13
+#define PMF_CMD_WRITE_I2C 14
+#define PMF_CMD_RMW_I2C 15
+#define PMF_CMD_GEN_I2C 16
+#define PMF_CMD_SHIFT_BYTES_RIGHT 17
+#define PMF_CMD_SHIFT_BYTES_LEFT 18
+#define PMF_CMD_READ_CFG 19
+#define PMF_CMD_WRITE_CFG 20
+#define PMF_CMD_RMW_CFG 21
+#define PMF_CMD_READ_I2C_SUBADDR 22
+#define PMF_CMD_WRITE_I2C_SUBADDR 23
+#define PMF_CMD_SET_I2C_MODE 24
+#define PMF_CMD_RMW_I2C_SUBADDR 25
+#define PMF_CMD_READ_REG32_MASK_SHR_XOR 26
+#define PMF_CMD_READ_REG16_MASK_SHR_XOR 27
+#define PMF_CMD_READ_REG8_MASK_SHR_XOR 28
+#define PMF_CMD_WRITE_REG32_SHL_MASK 29
+#define PMF_CMD_WRITE_REG16_SHL_MASK 30
+#define PMF_CMD_WRITE_REG8_SHL_MASK 31
+#define PMF_CMD_MASK_AND_COMPARE 32
+#define PMF_CMD_COUNT 33
+
+/* This structure holds the state of the parser while walking through
+ * a function definition
+ */
+struct pmf_cmd {
+ const void *cmdptr;
+ const void *cmdend;
+ struct pmf_function *func;
+ void *instdata;
+ struct pmf_args *args;
+ int error;
+};
+
+#if 0
+/* Debug output */
+static void print_blob(const char *title, const void *blob, int bytes)
+{
+ printk("%s", title);
+ while(bytes--) {
+ printk("%02x ", *((u8 *)blob));
+ blob += 1;
+ }
+ printk("\n");
+}
+#endif
+
+/*
+ * Parser helpers
+ */
+
+static u32 pmf_next32(struct pmf_cmd *cmd)
+{
+ u32 value;
+ if ((cmd->cmdend - cmd->cmdptr) < 4) {
+ cmd->error = 1;
+ return 0;
+ }
+ value = *((u32 *)cmd->cmdptr);
+ cmd->cmdptr += 4;
+ return value;
+}
+
+static const void* pmf_next_blob(struct pmf_cmd *cmd, int count)
+{
+ const void *value;
+ if ((cmd->cmdend - cmd->cmdptr) < count) {
+ cmd->error = 1;
+ return NULL;
+ }
+ value = cmd->cmdptr;
+ cmd->cmdptr += count;
+ return value;
+}
+
+/*
+ * Individual command parsers
+ */
+
+#define PMF_PARSE_CALL(name, cmd, handlers, p...) \
+ do { \
+ if (cmd->error) \
+ return -ENXIO; \
+ if (handlers == NULL) \
+ return 0; \
+ if (handlers->name) \
+ return handlers->name(cmd->func, cmd->instdata, \
+ cmd->args, p); \
+ return -1; \
+ } while(0) \
+
+
+static int pmf_parser_write_gpio(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u8 value = (u8)pmf_next32(cmd);
+ u8 mask = (u8)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_gpio(value: %02x, mask: %02x)\n", value, mask);
+
+ PMF_PARSE_CALL(write_gpio, cmd, h, value, mask);
+}
+
+static int pmf_parser_read_gpio(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u8 mask = (u8)pmf_next32(cmd);
+ int rshift = (int)pmf_next32(cmd);
+ u8 xor = (u8)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_gpio(mask: %02x, rshift: %d, xor: %02x)\n",
+ mask, rshift, xor);
+
+ PMF_PARSE_CALL(read_gpio, cmd, h, mask, rshift, xor);
+}
+
+static int pmf_parser_write_reg32(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 value = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg32(offset: %08x, value: %08x, mask: %08x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(write_reg32, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_read_reg32(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg32(offset: %08x)\n", offset);
+
+ PMF_PARSE_CALL(read_reg32, cmd, h, offset);
+}
+
+
+static int pmf_parser_write_reg16(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u16 value = (u16)pmf_next32(cmd);
+ u16 mask = (u16)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg16(offset: %08x, value: %04x, mask: %04x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(write_reg16, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_read_reg16(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg16(offset: %08x)\n", offset);
+
+ PMF_PARSE_CALL(read_reg16, cmd, h, offset);
+}
+
+
+static int pmf_parser_write_reg8(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u8 value = (u16)pmf_next32(cmd);
+ u8 mask = (u16)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg8(offset: %08x, value: %02x, mask: %02x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(write_reg8, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_read_reg8(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg8(offset: %08x)\n", offset);
+
+ PMF_PARSE_CALL(read_reg8, cmd, h, offset);
+}
+
+static int pmf_parser_delay(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 duration = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: delay(duration: %d us)\n", duration);
+
+ PMF_PARSE_CALL(delay, cmd, h, duration);
+}
+
+static int pmf_parser_wait_reg32(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 value = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: wait_reg32(offset: %08x, comp_value: %08x,mask: %08x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(wait_reg32, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_wait_reg16(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u16 value = (u16)pmf_next32(cmd);
+ u16 mask = (u16)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: wait_reg16(offset: %08x, comp_value: %04x,mask: %04x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(wait_reg16, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_wait_reg8(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u8 value = (u8)pmf_next32(cmd);
+ u8 mask = (u8)pmf_next32(cmd);
+
+ LOG_PARSE("pmf: wait_reg8(offset: %08x, comp_value: %02x,mask: %02x)\n",
+ offset, value, mask);
+
+ PMF_PARSE_CALL(wait_reg8, cmd, h, offset, value, mask);
+}
+
+static int pmf_parser_read_i2c(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 bytes = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_i2c(bytes: %ud)\n", bytes);
+
+ PMF_PARSE_CALL(read_i2c, cmd, h, bytes);
+}
+
+static int pmf_parser_write_i2c(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 bytes = pmf_next32(cmd);
+ const void *blob = pmf_next_blob(cmd, bytes);
+
+ LOG_PARSE("pmf: write_i2c(bytes: %ud) ...\n", bytes);
+ LOG_BLOB("pmf: data: \n", blob, bytes);
+
+ PMF_PARSE_CALL(write_i2c, cmd, h, bytes, blob);
+}
+
+
+static int pmf_parser_rmw_i2c(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 maskbytes = pmf_next32(cmd);
+ u32 valuesbytes = pmf_next32(cmd);
+ u32 totalbytes = pmf_next32(cmd);
+ const void *maskblob = pmf_next_blob(cmd, maskbytes);
+ const void *valuesblob = pmf_next_blob(cmd, valuesbytes);
+
+ LOG_PARSE("pmf: rmw_i2c(maskbytes: %ud, valuebytes: %ud, "
+ "totalbytes: %d) ...\n",
+ maskbytes, valuesbytes, totalbytes);
+ LOG_BLOB("pmf: mask data: \n", maskblob, maskbytes);
+ LOG_BLOB("pmf: values data: \n", valuesblob, valuesbytes);
+
+ PMF_PARSE_CALL(rmw_i2c, cmd, h, maskbytes, valuesbytes, totalbytes,
+ maskblob, valuesblob);
+}
+
+static int pmf_parser_read_cfg(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 bytes = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_cfg(offset: %x, bytes: %ud)\n", offset, bytes);
+
+ PMF_PARSE_CALL(read_cfg, cmd, h, offset, bytes);
+}
+
+
+static int pmf_parser_write_cfg(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 bytes = pmf_next32(cmd);
+ const void *blob = pmf_next_blob(cmd, bytes);
+
+ LOG_PARSE("pmf: write_cfg(offset: %x, bytes: %ud)\n", offset, bytes);
+ LOG_BLOB("pmf: data: \n", blob, bytes);
+
+ PMF_PARSE_CALL(write_cfg, cmd, h, offset, bytes, blob);
+}
+
+static int pmf_parser_rmw_cfg(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 maskbytes = pmf_next32(cmd);
+ u32 valuesbytes = pmf_next32(cmd);
+ u32 totalbytes = pmf_next32(cmd);
+ const void *maskblob = pmf_next_blob(cmd, maskbytes);
+ const void *valuesblob = pmf_next_blob(cmd, valuesbytes);
+
+ LOG_PARSE("pmf: rmw_cfg(maskbytes: %ud, valuebytes: %ud,"
+ " totalbytes: %d) ...\n",
+ maskbytes, valuesbytes, totalbytes);
+ LOG_BLOB("pmf: mask data: \n", maskblob, maskbytes);
+ LOG_BLOB("pmf: values data: \n", valuesblob, valuesbytes);
+
+ PMF_PARSE_CALL(rmw_cfg, cmd, h, offset, maskbytes, valuesbytes,
+ totalbytes, maskblob, valuesblob);
+}
+
+
+static int pmf_parser_read_i2c_sub(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u8 subaddr = (u8)pmf_next32(cmd);
+ u32 bytes = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_i2c_sub(subaddr: %x, bytes: %ud)\n",
+ subaddr, bytes);
+
+ PMF_PARSE_CALL(read_i2c_sub, cmd, h, subaddr, bytes);
+}
+
+static int pmf_parser_write_i2c_sub(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u8 subaddr = (u8)pmf_next32(cmd);
+ u32 bytes = pmf_next32(cmd);
+ const void *blob = pmf_next_blob(cmd, bytes);
+
+ LOG_PARSE("pmf: write_i2c_sub(subaddr: %x, bytes: %ud) ...\n",
+ subaddr, bytes);
+ LOG_BLOB("pmf: data: \n", blob, bytes);
+
+ PMF_PARSE_CALL(write_i2c_sub, cmd, h, subaddr, bytes, blob);
+}
+
+static int pmf_parser_set_i2c_mode(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u32 mode = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: set_i2c_mode(mode: %d)\n", mode);
+
+ PMF_PARSE_CALL(set_i2c_mode, cmd, h, mode);
+}
+
+
+static int pmf_parser_rmw_i2c_sub(struct pmf_cmd *cmd, struct pmf_handlers *h)
+{
+ u8 subaddr = (u8)pmf_next32(cmd);
+ u32 maskbytes = pmf_next32(cmd);
+ u32 valuesbytes = pmf_next32(cmd);
+ u32 totalbytes = pmf_next32(cmd);
+ const void *maskblob = pmf_next_blob(cmd, maskbytes);
+ const void *valuesblob = pmf_next_blob(cmd, valuesbytes);
+
+ LOG_PARSE("pmf: rmw_i2c_sub(subaddr: %x, maskbytes: %ud, valuebytes: %ud"
+ ", totalbytes: %d) ...\n",
+ subaddr, maskbytes, valuesbytes, totalbytes);
+ LOG_BLOB("pmf: mask data: \n", maskblob, maskbytes);
+ LOG_BLOB("pmf: values data: \n", valuesblob, valuesbytes);
+
+ PMF_PARSE_CALL(rmw_i2c_sub, cmd, h, subaddr, maskbytes, valuesbytes,
+ totalbytes, maskblob, valuesblob);
+}
+
+static int pmf_parser_read_reg32_msrx(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 xor = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg32_msrx(offset: %x, mask: %x, shift: %x,"
+ " xor: %x\n", offset, mask, shift, xor);
+
+ PMF_PARSE_CALL(read_reg32_msrx, cmd, h, offset, mask, shift, xor);
+}
+
+static int pmf_parser_read_reg16_msrx(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 xor = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg16_msrx(offset: %x, mask: %x, shift: %x,"
+ " xor: %x\n", offset, mask, shift, xor);
+
+ PMF_PARSE_CALL(read_reg16_msrx, cmd, h, offset, mask, shift, xor);
+}
+static int pmf_parser_read_reg8_msrx(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 xor = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: read_reg8_msrx(offset: %x, mask: %x, shift: %x,"
+ " xor: %x\n", offset, mask, shift, xor);
+
+ PMF_PARSE_CALL(read_reg8_msrx, cmd, h, offset, mask, shift, xor);
+}
+
+static int pmf_parser_write_reg32_slm(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg32_slm(offset: %x, shift: %x, mask: %x\n",
+ offset, shift, mask);
+
+ PMF_PARSE_CALL(write_reg32_slm, cmd, h, offset, shift, mask);
+}
+
+static int pmf_parser_write_reg16_slm(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg16_slm(offset: %x, shift: %x, mask: %x\n",
+ offset, shift, mask);
+
+ PMF_PARSE_CALL(write_reg16_slm, cmd, h, offset, shift, mask);
+}
+
+static int pmf_parser_write_reg8_slm(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 offset = pmf_next32(cmd);
+ u32 shift = pmf_next32(cmd);
+ u32 mask = pmf_next32(cmd);
+
+ LOG_PARSE("pmf: write_reg8_slm(offset: %x, shift: %x, mask: %x\n",
+ offset, shift, mask);
+
+ PMF_PARSE_CALL(write_reg8_slm, cmd, h, offset, shift, mask);
+}
+
+static int pmf_parser_mask_and_compare(struct pmf_cmd *cmd,
+ struct pmf_handlers *h)
+{
+ u32 bytes = pmf_next32(cmd);
+ const void *maskblob = pmf_next_blob(cmd, bytes);
+ const void *valuesblob = pmf_next_blob(cmd, bytes);
+
+ LOG_PARSE("pmf: mask_and_compare(length: %ud ...\n", bytes);
+ LOG_BLOB("pmf: mask data: \n", maskblob, bytes);
+ LOG_BLOB("pmf: values data: \n", valuesblob, bytes);
+
+ PMF_PARSE_CALL(mask_and_compare, cmd, h,
+ bytes, maskblob, valuesblob);
+}
+
+
+typedef int (*pmf_cmd_parser_t)(struct pmf_cmd *cmd, struct pmf_handlers *h);
+
+static pmf_cmd_parser_t pmf_parsers[PMF_CMD_COUNT] =
+{
+ NULL,
+ pmf_parser_write_gpio,
+ pmf_parser_read_gpio,
+ pmf_parser_write_reg32,
+ pmf_parser_read_reg32,
+ pmf_parser_write_reg16,
+ pmf_parser_read_reg16,
+ pmf_parser_write_reg8,
+ pmf_parser_read_reg8,
+ pmf_parser_delay,
+ pmf_parser_wait_reg32,
+ pmf_parser_wait_reg16,
+ pmf_parser_wait_reg8,
+ pmf_parser_read_i2c,
+ pmf_parser_write_i2c,
+ pmf_parser_rmw_i2c,
+ NULL, /* Bogus command */
+ NULL, /* Shift bytes right: NYI */
+ NULL, /* Shift bytes left: NYI */
+ pmf_parser_read_cfg,
+ pmf_parser_write_cfg,
+ pmf_parser_rmw_cfg,
+ pmf_parser_read_i2c_sub,
+ pmf_parser_write_i2c_sub,
+ pmf_parser_set_i2c_mode,
+ pmf_parser_rmw_i2c_sub,
+ pmf_parser_read_reg32_msrx,
+ pmf_parser_read_reg16_msrx,
+ pmf_parser_read_reg8_msrx,
+ pmf_parser_write_reg32_slm,
+ pmf_parser_write_reg16_slm,
+ pmf_parser_write_reg8_slm,
+ pmf_parser_mask_and_compare,
+};
+
+struct pmf_device {
+ struct list_head link;
+ struct device_node *node;
+ struct pmf_handlers *handlers;
+ struct list_head functions;
+ struct kref ref;
+};
+
+static LIST_HEAD(pmf_devices);
+static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+
+static void pmf_release_device(struct kref *kref)
+{
+ struct pmf_device *dev = container_of(kref, struct pmf_device, ref);
+ kfree(dev);
+}
+
+static inline void pmf_put_device(struct pmf_device *dev)
+{
+ kref_put(&dev->ref, pmf_release_device);
+}
+
+static inline struct pmf_device *pmf_get_device(struct pmf_device *dev)
+{
+ kref_get(&dev->ref);
+ return dev;
+}
+
+static inline struct pmf_device *pmf_find_device(struct device_node *np)
+{
+ struct pmf_device *dev;
+
+ list_for_each_entry(dev, &pmf_devices, link) {
+ if (dev->node == np)
+ return pmf_get_device(dev);
+ }
+ return NULL;
+}
+
+static int pmf_parse_one(struct pmf_function *func,
+ struct pmf_handlers *handlers,
+ void *instdata, struct pmf_args *args)
+{
+ struct pmf_cmd cmd;
+ u32 ccode;
+ int count, rc;
+
+ cmd.cmdptr = func->data;
+ cmd.cmdend = func->data + func->length;
+ cmd.func = func;
+ cmd.instdata = instdata;
+ cmd.args = args;
+ cmd.error = 0;
+
+ LOG_PARSE("pmf: func %s, %d bytes, %s...\n",
+ func->name, func->length,
+ handlers ? "executing" : "parsing");
+
+ /* One subcommand to parse for now */
+ count = 1;
+
+ while(count-- && cmd.cmdptr < cmd.cmdend) {
+ /* Get opcode */
+ ccode = pmf_next32(&cmd);
+ /* Check if we are hitting a command list, fetch new count */
+ if (ccode == 0) {
+ count = pmf_next32(&cmd) - 1;
+ ccode = pmf_next32(&cmd);
+ }
+ if (cmd.error) {
+ LOG_ERROR("pmf: parse error, not enough data\n");
+ return -ENXIO;
+ }
+ if (ccode >= PMF_CMD_COUNT) {
+ LOG_ERROR("pmf: command code %d unknown !\n", ccode);
+ return -ENXIO;
+ }
+ if (pmf_parsers[ccode] == NULL) {
+ LOG_ERROR("pmf: no parser for command %d !\n", ccode);
+ return -ENXIO;
+ }
+ rc = pmf_parsers[ccode](&cmd, handlers);
+ if (rc != 0) {
+ LOG_ERROR("pmf: parser for command %d returned"
+ " error %d\n", ccode, rc);
+ return rc;
+ }
+ }
+
+ /* We are doing an initial parse pass, we need to adjust the size */
+ if (handlers == NULL)
+ func->length = cmd.cmdptr - func->data;
+
+ return 0;
+}
+
+static int pmf_add_function_prop(struct pmf_device *dev, void *driverdata,
+ const char *name, u32 *data,
+ unsigned int length)
+{
+ int count = 0;
+ struct pmf_function *func = NULL;
+
+ DBG("pmf: Adding functions for platform-do-%s\n", name);
+
+ while (length >= 12) {
+ /* Allocate a structure */
+ func = kzalloc(sizeof(struct pmf_function), GFP_KERNEL);
+ if (func == NULL)
+ goto bail;
+ kref_init(&func->ref);
+ INIT_LIST_HEAD(&func->irq_clients);
+ func->node = dev->node;
+ func->driver_data = driverdata;
+ func->name = name;
+ func->phandle = data[0];
+ func->flags = data[1];
+ data += 2;
+ length -= 8;
+ func->data = data;
+ func->length = length;
+ func->dev = dev;
+ DBG("pmf: idx %d: flags=%08x, phandle=%08x "
+ " %d bytes remaining, parsing...\n",
+ count+1, func->flags, func->phandle, length);
+ if (pmf_parse_one(func, NULL, NULL, NULL)) {
+ kfree(func);
+ goto bail;
+ }
+ length -= func->length;
+ data = (u32 *)(((u8 *)data) + func->length);
+ list_add(&func->link, &dev->functions);
+ pmf_get_device(dev);
+ count++;
+ }
+ bail:
+ DBG("pmf: Added %d functions\n", count);
+
+ return count;
+}
+
+static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
+{
+ struct property *pp;
+#define PP_PREFIX "platform-do-"
+ const int plen = strlen(PP_PREFIX);
+ int count = 0;
+
+ for (pp = dev->node->properties; pp != 0; pp = pp->next) {
+ char *name;
+ if (strncmp(pp->name, PP_PREFIX, plen) != 0)
+ continue;
+ name = pp->name + plen;
+ if (strlen(name) && pp->length >= 12)
+ count += pmf_add_function_prop(dev, driverdata, name,
+ (u32 *)pp->value,
+ pp->length);
+ }
+ return count;
+}
+
+
+int pmf_register_driver(struct device_node *np,
+ struct pmf_handlers *handlers,
+ void *driverdata)
+{
+ struct pmf_device *dev;
+ unsigned long flags;
+ int rc = 0;
+
+ if (handlers == NULL)
+ return -EINVAL;
+
+ DBG("pmf: registering driver for node %s\n", np->full_name);
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ dev = pmf_find_device(np);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ if (dev != NULL) {
+ DBG("pmf: already there !\n");
+ pmf_put_device(dev);
+ return -EBUSY;
+ }
+
+ dev = kzalloc(sizeof(struct pmf_device), GFP_KERNEL);
+ if (dev == NULL) {
+ DBG("pmf: no memory !\n");
+ return -ENOMEM;
+ }
+ kref_init(&dev->ref);
+ dev->node = of_node_get(np);
+ dev->handlers = handlers;
+ INIT_LIST_HEAD(&dev->functions);
+
+ rc = pmf_add_functions(dev, driverdata);
+ if (rc == 0) {
+ DBG("pmf: no functions, disposing.. \n");
+ of_node_put(np);
+ kfree(dev);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ list_add(&dev->link, &pmf_devices);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pmf_register_driver);
+
+struct pmf_function *pmf_get_function(struct pmf_function *func)
+{
+ if (!try_module_get(func->dev->handlers->owner))
+ return NULL;
+ kref_get(&func->ref);
+ return func;
+}
+EXPORT_SYMBOL_GPL(pmf_get_function);
+
+static void pmf_release_function(struct kref *kref)
+{
+ struct pmf_function *func =
+ container_of(kref, struct pmf_function, ref);
+ pmf_put_device(func->dev);
+ kfree(func);
+}
+
+static inline void __pmf_put_function(struct pmf_function *func)
+{
+ kref_put(&func->ref, pmf_release_function);
+}
+
+void pmf_put_function(struct pmf_function *func)
+{
+ if (func == NULL)
+ return;
+ module_put(func->dev->handlers->owner);
+ __pmf_put_function(func);
+}
+EXPORT_SYMBOL_GPL(pmf_put_function);
+
+void pmf_unregister_driver(struct device_node *np)
+{
+ struct pmf_device *dev;
+ unsigned long flags;
+
+ DBG("pmf: unregistering driver for node %s\n", np->full_name);
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ dev = pmf_find_device(np);
+ if (dev == NULL) {
+ DBG("pmf: not such driver !\n");
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ return;
+ }
+ list_del(&dev->link);
+
+ while(!list_empty(&dev->functions)) {
+ struct pmf_function *func =
+ list_entry(dev->functions.next, typeof(*func), link);
+ list_del(&func->link);
+ __pmf_put_function(func);
+ }
+
+ pmf_put_device(dev);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pmf_unregister_driver);
+
+struct pmf_function *__pmf_find_function(struct device_node *target,
+ const char *name, u32 flags)
+{
+ struct device_node *actor = of_node_get(target);
+ struct pmf_device *dev;
+ struct pmf_function *func, *result = NULL;
+ char fname[64];
+ u32 *prop, ph;
+
+ /*
+ * Look for a "platform-*" function reference. If we can't find
+ * one, then we fallback to a direct call attempt
+ */
+ snprintf(fname, 63, "platform-%s", name);
+ prop = (u32 *)get_property(target, fname, NULL);
+ if (prop == NULL)
+ goto find_it;
+ ph = *prop;
+ if (ph == 0)
+ goto find_it;
+
+ /*
+ * Ok, now try to find the actor. If we can't find it, we fail,
+ * there is no point in falling back there
+ */
+ of_node_put(actor);
+ actor = of_find_node_by_phandle(ph);
+ if (actor == NULL)
+ return NULL;
+ find_it:
+ dev = pmf_find_device(actor);
+ if (dev == NULL)
+ return NULL;
+
+ list_for_each_entry(func, &dev->functions, link) {
+ if (name && strcmp(name, func->name))
+ continue;
+ if (func->phandle && target->node != func->phandle)
+ continue;
+ if ((func->flags & flags) == 0)
+ continue;
+ result = func;
+ break;
+ }
+ of_node_put(actor);
+ pmf_put_device(dev);
+ return result;
+}
+
+
+int pmf_register_irq_client(struct device_node *target,
+ const char *name,
+ struct pmf_irq_client *client)
+{
+ struct pmf_function *func;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ func = __pmf_find_function(target, name, PMF_FLAGS_INT_GEN);
+ if (func == NULL) {
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ return -ENODEV;
+ }
+ list_add(&client->link, &func->irq_clients);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pmf_register_irq_client);
+
+void pmf_unregister_irq_client(struct device_node *np,
+ const char *name,
+ struct pmf_irq_client *client)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ list_del(&client->link);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pmf_unregister_irq_client);
+
+
+void pmf_do_irq(struct pmf_function *func)
+{
+ unsigned long flags;
+ struct pmf_irq_client *client;
+
+ /* For now, using a spinlock over the whole function. Can be made
+ * to drop the lock using 2 lists if necessary
+ */
+ spin_lock_irqsave(&pmf_lock, flags);
+ list_for_each_entry(client, &func->irq_clients, link) {
+ if (!try_module_get(client->owner))
+ continue;
+ client->handler(client->data);
+ module_put(client->owner);
+ }
+ spin_unlock_irqrestore(&pmf_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pmf_do_irq);
+
+
+int pmf_call_one(struct pmf_function *func, struct pmf_args *args)
+{
+ struct pmf_device *dev = func->dev;
+ void *instdata = NULL;
+ int rc = 0;
+
+ DBG(" ** pmf_call_one(%s/%s) **\n", dev->node->full_name, func->name);
+
+ if (dev->handlers->begin)
+ instdata = dev->handlers->begin(func, args);
+ rc = pmf_parse_one(func, dev->handlers, instdata, args);
+ if (dev->handlers->end)
+ dev->handlers->end(func, instdata);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pmf_call_one);
+
+int pmf_do_functions(struct device_node *np, const char *name,
+ u32 phandle, u32 fflags, struct pmf_args *args)
+{
+ struct pmf_device *dev;
+ struct pmf_function *func, *tmp;
+ unsigned long flags;
+ int rc = -ENODEV;
+
+ spin_lock_irqsave(&pmf_lock, flags);
+
+ dev = pmf_find_device(np);
+ if (dev == NULL) {
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ return -ENODEV;
+ }
+ list_for_each_entry_safe(func, tmp, &dev->functions, link) {
+ if (name && strcmp(name, func->name))
+ continue;
+ if (phandle && func->phandle && phandle != func->phandle)
+ continue;
+ if ((func->flags & fflags) == 0)
+ continue;
+ if (pmf_get_function(func) == NULL)
+ continue;
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ rc = pmf_call_one(func, args);
+ pmf_put_function(func);
+ spin_lock_irqsave(&pmf_lock, flags);
+ }
+ pmf_put_device(dev);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pmf_do_functions);
+
+
+struct pmf_function *pmf_find_function(struct device_node *target,
+ const char *name)
+{
+ struct pmf_function *func;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pmf_lock, flags);
+ func = __pmf_find_function(target, name, PMF_FLAGS_ON_DEMAND);
+ if (func)
+ func = pmf_get_function(func);
+ spin_unlock_irqrestore(&pmf_lock, flags);
+ return func;
+}
+EXPORT_SYMBOL_GPL(pmf_find_function);
+
+int pmf_call_function(struct device_node *target, const char *name,
+ struct pmf_args *args)
+{
+ struct pmf_function *func = pmf_find_function(target, name);
+ int rc;
+
+ if (func == NULL)
+ return -ENODEV;
+
+ rc = pmf_call_one(func, args);
+ pmf_put_function(func);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pmf_call_function);
+
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 90040c49494d..18bf3011d1e3 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -5,8 +5,8 @@
* in a separate file
*
* Copyright (C) 1997 Paul Mackerras (paulus@samba.org)
- *
- * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ * Copyright (C) 2005 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ * IBM, Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -54,12 +54,7 @@ struct pmac_irq_hw {
};
/* Default addresses */
-static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
- (struct pmac_irq_hw *) 0xf3000020,
- (struct pmac_irq_hw *) 0xf3000010,
- (struct pmac_irq_hw *) 0xf4000020,
- (struct pmac_irq_hw *) 0xf4000010,
-};
+static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];
#define GC_LEVEL_MASK 0x3ff00000
#define OHARE_LEVEL_MASK 0x1ff00000
@@ -82,8 +77,7 @@ static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
* since it can lose interrupts (see pmac_set_irq_mask).
* -- Cort
*/
-void
-__set_lost(unsigned long irq_nr, int nokick)
+void __set_lost(unsigned long irq_nr, int nokick)
{
if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
atomic_inc(&ppc_n_lost_interrupts);
@@ -92,8 +86,7 @@ __set_lost(unsigned long irq_nr, int nokick)
}
}
-static void
-pmac_mask_and_ack_irq(unsigned int irq_nr)
+static void pmac_mask_and_ack_irq(unsigned int irq_nr)
{
unsigned long bit = 1UL << (irq_nr & 0x1f);
int i = irq_nr >> 5;
@@ -224,8 +217,7 @@ static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
-int
-pmac_get_irq(struct pt_regs *regs)
+static int pmac_get_irq(struct pt_regs *regs)
{
int irq;
unsigned long bits = 0;
@@ -256,34 +248,40 @@ pmac_get_irq(struct pt_regs *regs)
/* This routine will fix some missing interrupt values in the device tree
* on the gatwick mac-io controller used by some PowerBooks
+ *
+ * Walking of OF nodes could use a bit more fixing up here, but it's not
+ * very important as this is all boot time code on static portions of the
+ * device-tree.
+ *
+ * However, the modifications done to "intrs" will have to be removed and
+ * replaced with proper updates of the "interrupts" properties or
+ * AAPL,interrupts, yet to be decided, once the dynamic parsing is there.
*/
-static void __init
-pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+static void __init pmac_fix_gatwick_interrupts(struct device_node *gw,
+ int irq_base)
{
struct device_node *node;
int count;
memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
- node = gw->child;
count = 0;
- while(node)
- {
+ for (node = NULL; (node = of_get_next_child(gw, node)) != NULL;) {
/* Fix SCC */
- if (strcasecmp(node->name, "escc") == 0)
- if (node->child) {
- if (node->child->n_intrs < 3) {
- node->child->intrs = &gatwick_int_pool[count];
- count += 3;
- }
- node->child->n_intrs = 3;
- node->child->intrs[0].line = 15+irq_base;
- node->child->intrs[1].line = 4+irq_base;
- node->child->intrs[2].line = 5+irq_base;
- printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
- node->child->intrs[0].line,
- node->child->intrs[1].line,
- node->child->intrs[2].line);
+ if ((strcasecmp(node->name, "escc") == 0) && node->child) {
+ if (node->child->n_intrs < 3) {
+ node->child->intrs = &gatwick_int_pool[count];
+ count += 3;
}
+ node->child->n_intrs = 3;
+ node->child->intrs[0].line = 15+irq_base;
+ node->child->intrs[1].line = 4+irq_base;
+ node->child->intrs[2].line = 5+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on gatwick"
+ " (%d,%d,%d)\n",
+ node->child->intrs[0].line,
+ node->child->intrs[1].line,
+ node->child->intrs[2].line);
+ }
/* Fix media-bay & left SWIM */
if (strcasecmp(node->name, "media-bay") == 0) {
struct device_node* ya_node;
@@ -292,12 +290,11 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
node->intrs = &gatwick_int_pool[count++];
node->n_intrs = 1;
node->intrs[0].line = 29+irq_base;
- printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
- node->intrs[0].line);
+ printk(KERN_INFO "irq: fixed media-bay on gatwick"
+ " (%d)\n", node->intrs[0].line);
ya_node = node->child;
- while(ya_node)
- {
+ while(ya_node) {
if (strcasecmp(ya_node->name, "floppy") == 0) {
if (ya_node->n_intrs < 2) {
ya_node->intrs = &gatwick_int_pool[count];
@@ -323,7 +320,6 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
ya_node = ya_node->sibling;
}
}
- node = node->sibling;
}
if (count > 10) {
printk("WARNING !! Gatwick interrupt pool overflow\n");
@@ -338,45 +334,41 @@ pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
* controller. If we find this second ohare, set it up and fix the
* interrupt value in the device tree for the ethernet chip.
*/
-static int __init enable_second_ohare(void)
+static void __init enable_second_ohare(struct device_node *np)
{
unsigned char bus, devfn;
unsigned short cmd;
- unsigned long addr;
- struct device_node *irqctrler = find_devices("pci106b,7");
struct device_node *ether;
- if (irqctrler == NULL || irqctrler->n_addrs <= 0)
- return -1;
- addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
- pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
- max_irqs = 64;
- if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
- struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
- if (!hose)
- printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
- else {
- early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- cmd &= ~PCI_COMMAND_IO;
- early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
+ /* This code doesn't strictly belong here, it could be part of
+ * either the PCI initialisation or the feature code. It's kept
+ * here for historical reasons.
+ */
+ if (pci_device_from_OF_node(np, &bus, &devfn) == 0) {
+ struct pci_controller* hose =
+ pci_find_hose_for_OF_device(np);
+ if (!hose) {
+ printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+ return;
}
+ early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+ cmd &= ~PCI_COMMAND_IO;
+ early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
}
/* Fix interrupt for the modem/ethernet combo controller. The number
- in the device tree (27) is bogus (correct for the ethernet-only
- board but not the combo ethernet/modem board).
- The real interrupt is 28 on the second controller -> 28+32 = 60.
- */
- ether = find_devices("pci1011,14");
+ * in the device tree (27) is bogus (correct for the ethernet-only
+ * board but not the combo ethernet/modem board).
+ * The real interrupt is 28 on the second controller -> 28+32 = 60.
+ */
+ ether = of_find_node_by_name(NULL, "pci1011,14");
if (ether && ether->n_intrs > 0) {
ether->intrs[0].line = 60;
printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
ether->intrs[0].line);
}
-
- /* Return the interrupt number of the cascade */
- return irqctrler->intrs[0].line;
+ of_node_put(ether);
}
#ifdef CONFIG_XMON
@@ -394,189 +386,251 @@ static struct irqaction gatwick_cascade_action = {
.mask = CPU_MASK_NONE,
.name = "cascade",
};
-#endif /* CONFIG_PPC32 */
-static int pmac_u3_cascade(struct pt_regs *regs, void *data)
+static void __init pmac_pic_probe_oldstyle(void)
{
- return mpic_get_one_irq((struct mpic *)data, regs);
-}
-
-void __init pmac_pic_init(void)
-{
- struct device_node *irqctrler = NULL;
- struct device_node *irqctrler2 = NULL;
- struct device_node *np;
-#ifdef CONFIG_PPC32
int i;
- unsigned long addr;
int irq_cascade = -1;
-#endif
- struct mpic *mpic1, *mpic2;
+ struct device_node *master = NULL;
+ struct device_node *slave = NULL;
+ u8 __iomem *addr;
+ struct resource r;
- /* We first try to detect Apple's new Core99 chipset, since mac-io
- * is quite different on those machines and contains an IBM MPIC2.
- */
- np = find_type_devices("open-pic");
- while (np) {
- if (np->parent && !strcmp(np->parent->name, "u3"))
- irqctrler2 = np;
- else
- irqctrler = np;
- np = np->next;
- }
- if (irqctrler != NULL && irqctrler->n_addrs > 0) {
- unsigned char senses[128];
-
- printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
- (unsigned int)irqctrler->addrs[0].address);
- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);
-
- prom_get_irq_senses(senses, 0, 128);
- mpic1 = mpic_alloc(irqctrler->addrs[0].address,
- MPIC_PRIMARY | MPIC_WANTS_RESET,
- 0, 0, 128, 252, senses, 128, " OpenPIC ");
- BUG_ON(mpic1 == NULL);
- mpic_init(mpic1);
-
- if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
- irqctrler2->n_addrs > 0) {
- printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
- (u32)irqctrler2->addrs[0].address,
- irqctrler2->intrs[0].line);
-
- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
- prom_get_irq_senses(senses, 128, 128 + 124);
-
- /* We don't need to set MPIC_BROKEN_U3 here since we don't have
- * hypertransport interrupts routed to it
- */
- mpic2 = mpic_alloc(irqctrler2->addrs[0].address,
- MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
- 0, 128, 124, 0, senses, 124,
- " U3-MPIC ");
- BUG_ON(mpic2 == NULL);
- mpic_init(mpic2);
- mpic_setup_cascade(irqctrler2->intrs[0].line,
- pmac_u3_cascade, mpic2);
- }
-#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
- {
- struct device_node* pswitch;
- int nmi_irq;
-
- pswitch = find_devices("programmer-switch");
- if (pswitch && pswitch->n_intrs) {
- nmi_irq = pswitch->intrs[0].line;
- mpic_irq_set_priority(nmi_irq, 9);
- setup_irq(nmi_irq, &xmon_action);
- }
- }
-#endif /* CONFIG_XMON */
- return;
- }
- irqctrler = NULL;
+ /* Set our get_irq function */
+ ppc_md.get_irq = pmac_get_irq;
-#ifdef CONFIG_PPC32
- /* Get the level/edge settings, assume if it's not
- * a Grand Central nor an OHare, then it's an Heathrow
- * (or Paddington).
+ /*
+ * Find the interrupt controller type & node
*/
- ppc_md.get_irq = pmac_get_irq;
- if (find_devices("gc"))
+
+ if ((master = of_find_node_by_name(NULL, "gc")) != NULL) {
+ max_irqs = max_real_irqs = 32;
level_mask[0] = GC_LEVEL_MASK;
- else if (find_devices("ohare")) {
+ } else if ((master = of_find_node_by_name(NULL, "ohare")) != NULL) {
+ max_irqs = max_real_irqs = 32;
level_mask[0] = OHARE_LEVEL_MASK;
+
/* We might have a second cascaded ohare */
- level_mask[1] = OHARE_LEVEL_MASK;
- } else {
+ slave = of_find_node_by_name(NULL, "pci106b,7");
+ if (slave) {
+ max_irqs = 64;
+ level_mask[1] = OHARE_LEVEL_MASK;
+ enable_second_ohare(slave);
+ }
+ } else if ((master = of_find_node_by_name(NULL, "mac-io")) != NULL) {
+ max_irqs = max_real_irqs = 64;
level_mask[0] = HEATHROW_LEVEL_MASK;
level_mask[1] = 0;
+
/* We might have a second cascaded heathrow */
- level_mask[2] = HEATHROW_LEVEL_MASK;
- level_mask[3] = 0;
- }
+ slave = of_find_node_by_name(master, "mac-io");
+
+ /* Check ordering of master & slave */
+ if (device_is_compatible(master, "gatwick")) {
+ struct device_node *tmp;
+ BUG_ON(slave == NULL);
+ tmp = master;
+ master = slave;
+ slave = tmp;
+ }
- /*
- * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
- * 1998 G3 Series PowerBooks have 128,
- * other powermacs have 32.
- * The combo ethernet/modem card for the Powerstar powerbooks
- * (2400/3400/3500, ohare based) has a second ohare chip
- * effectively making a total of 64.
- */
- max_irqs = max_real_irqs = 32;
- irqctrler = find_devices("mac-io");
- if (irqctrler)
- {
- max_real_irqs = 64;
- if (irqctrler->next)
+ /* We found a slave */
+ if (slave) {
max_irqs = 128;
- else
- max_irqs = 64;
+ level_mask[2] = HEATHROW_LEVEL_MASK;
+ level_mask[3] = 0;
+ pmac_fix_gatwick_interrupts(slave, max_real_irqs);
+ }
}
+ BUG_ON(master == NULL);
+
+ /* Set the handler for the main PIC */
for ( i = 0; i < max_real_irqs ; i++ )
irq_desc[i].handler = &pmac_pic;
- /* get addresses of first controller */
- if (irqctrler) {
- if (irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 0; i < 2; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (2 - i) * 0x10);
- }
+ /* Get addresses of first controller if we have a node for it */
+ BUG_ON(of_address_to_resource(master, 0, &r));
- /* get addresses of second controller */
- irqctrler = irqctrler->next;
- if (irqctrler && irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 2; i < 4; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (4 - i) * 0x10);
- irq_cascade = irqctrler->intrs[0].line;
- if (device_is_compatible(irqctrler, "gatwick"))
- pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
- }
- } else {
- /* older powermacs have a GC (grand central) or ohare at
- f3000000, with interrupt control registers at f3000020. */
- addr = (unsigned long) ioremap(0xf3000000, 0x40);
- pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
+ /* Map interrupts of primary controller */
+ addr = (u8 __iomem *) ioremap(r.start, 0x40);
+ i = 0;
+ pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
+ (addr + 0x20);
+ if (max_real_irqs > 32)
+ pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
+ (addr + 0x10);
+ of_node_put(master);
+
+ printk(KERN_INFO "irq: Found primary Apple PIC %s for %d irqs\n",
+ master->full_name, max_real_irqs);
+
+ /* Map interrupts of cascaded controller */
+ if (slave && !of_address_to_resource(slave, 0, &r)) {
+ addr = (u8 __iomem *)ioremap(r.start, 0x40);
+ pmac_irq_hw[i++] = (volatile struct pmac_irq_hw __iomem *)
+ (addr + 0x20);
+ if (max_irqs > 64)
+ pmac_irq_hw[i++] =
+ (volatile struct pmac_irq_hw __iomem *)
+ (addr + 0x10);
+ irq_cascade = slave->intrs[0].line;
+
+ printk(KERN_INFO "irq: Found slave Apple PIC %s for %d irqs"
+ " cascade: %d\n", slave->full_name,
+ max_irqs - max_real_irqs, irq_cascade);
}
-
- /* PowerBooks 3400 and 3500 can have a second controller in a second
- ohare chip, on the combo ethernet/modem card */
- if (machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500"))
- irq_cascade = enable_second_ohare();
+ of_node_put(slave);
/* disable all interrupts in all controllers */
for (i = 0; i * 32 < max_irqs; ++i)
out_le32(&pmac_irq_hw[i]->enable, 0);
+
/* mark level interrupts */
for (i = 0; i < max_irqs; i++)
if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
irq_desc[i].status = IRQ_LEVEL;
- /* get interrupt line of secondary interrupt controller */
- if (irq_cascade >= 0) {
- printk(KERN_INFO "irq: secondary controller on irq %d\n",
- (int)irq_cascade);
+ /* Setup handlers for secondary controller and hook cascade irq*/
+ if (slave) {
for ( i = max_real_irqs ; i < max_irqs ; i++ )
irq_desc[i].handler = &gatwick_pic;
setup_irq(irq_cascade, &gatwick_cascade_action);
}
- printk("System has %d possible interrupts\n", max_irqs);
- if (max_irqs != max_real_irqs)
- printk(KERN_DEBUG "%d interrupts on main controller\n",
- max_real_irqs);
-
+ printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
#ifdef CONFIG_XMON
setup_irq(20, &xmon_action);
-#endif /* CONFIG_XMON */
-#endif /* CONFIG_PPC32 */
+#endif
+}
+#endif /* CONFIG_PPC32 */
+
+static int pmac_u3_cascade(struct pt_regs *regs, void *data)
+{
+ return mpic_get_one_irq((struct mpic *)data, regs);
+}
+
+static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
+{
+#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
+ struct device_node* pswitch;
+ int nmi_irq;
+
+ pswitch = of_find_node_by_name(NULL, "programmer-switch");
+ if (pswitch && pswitch->n_intrs) {
+ nmi_irq = pswitch->intrs[0].line;
+ mpic_irq_set_priority(nmi_irq, 9);
+ setup_irq(nmi_irq, &xmon_action);
+ }
+ of_node_put(pswitch);
+#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
+}
+
+static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
+ int master)
+{
+ unsigned char senses[128];
+ int offset = master ? 0 : 128;
+ int count = master ? 128 : 124;
+ const char *name = master ? " MPIC 1 " : " MPIC 2 ";
+ struct resource r;
+ struct mpic *mpic;
+ unsigned int flags = master ? MPIC_PRIMARY : 0;
+ int rc;
+
+ rc = of_address_to_resource(np, 0, &r);
+ if (rc)
+ return NULL;
+
+ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
+
+ prom_get_irq_senses(senses, offset, offset + count);
+
+ flags |= MPIC_WANTS_RESET;
+ if (get_property(np, "big-endian", NULL))
+ flags |= MPIC_BIG_ENDIAN;
+
+ /* Primary Big Endian means HT interrupts. This is quite dodgy
+ * but works until I find a better way
+ */
+ if (master && (flags & MPIC_BIG_ENDIAN))
+ flags |= MPIC_BROKEN_U3;
+
+ mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0,
+ senses, count, name);
+ if (mpic == NULL)
+ return NULL;
+
+ mpic_init(mpic);
+
+ return mpic;
+ }
+
+static int __init pmac_pic_probe_mpic(void)
+{
+ struct mpic *mpic1, *mpic2;
+ struct device_node *np, *master = NULL, *slave = NULL;
+
+ /* We can have up to 2 MPICs cascaded */
+ for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
+ != NULL;) {
+ if (master == NULL &&
+ get_property(np, "interrupts", NULL) == NULL)
+ master = of_node_get(np);
+ else if (slave == NULL)
+ slave = of_node_get(np);
+ if (master && slave)
+ break;
+ }
+
+ /* Check for bogus setups */
+ if (master == NULL && slave != NULL) {
+ master = slave;
+ slave = NULL;
+ }
+
+ /* Not found, default to good old pmac pic */
+ if (master == NULL)
+ return -ENODEV;
+
+ /* Set master handler */
+ ppc_md.get_irq = mpic_get_irq;
+
+ /* Setup master */
+ mpic1 = pmac_setup_one_mpic(master, 1);
+ BUG_ON(mpic1 == NULL);
+
+ /* Install NMI if any */
+ pmac_pic_setup_mpic_nmi(mpic1);
+
+ of_node_put(master);
+
+ /* No slave, let's go out */
+ if (slave == NULL || slave->n_intrs < 1)
+ return 0;
+
+ mpic2 = pmac_setup_one_mpic(slave, 0);
+ if (mpic2 == NULL) {
+ printk(KERN_ERR "Failed to setup slave MPIC\n");
+ of_node_put(slave);
+ return 0;
+ }
+ mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2);
+
+ of_node_put(slave);
+ return 0;
+}
+
+
+void __init pmac_pic_init(void)
+{
+ /* We first try to detect Apple's new Core99 chipset, since mac-io
+ * is quite different on those machines and contains an IBM MPIC2.
+ */
+ if (pmac_pic_probe_mpic() == 0)
+ return;
+
+#ifdef CONFIG_PPC32
+ pmac_pic_probe_oldstyle();
+#endif
}
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index 2ad25e13423e..21c7b0f8f329 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -42,10 +42,6 @@ extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
unsigned long data_port, unsigned long ctrl_port, int *irq);
extern int pmac_nvram_init(void);
-
-extern struct hw_interrupt_type pmac_pic;
-
-void pmac_pic_init(void);
-int pmac_get_irq(struct pt_regs *regs);
+extern void pmac_pic_init(void);
#endif /* __PMAC_H__ */
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 7acb0546671f..89c4c3636161 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -60,6 +60,7 @@
#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/io.h>
+#include <asm/kexec.h>
#include <asm/pci-bridge.h>
#include <asm/ohare.h>
#include <asm/mediabay.h>
@@ -74,8 +75,8 @@
#include <asm/iommu.h>
#include <asm/smu.h>
#include <asm/pmc.h>
-#include <asm/mpic.h>
#include <asm/lmb.h>
+#include <asm/udbg.h>
#include "pmac.h"
@@ -277,7 +278,7 @@ static void __init l2cr_init(void)
}
#endif
-void __init pmac_setup_arch(void)
+static void __init pmac_setup_arch(void)
{
struct device_node *cpu, *ic;
int *fp;
@@ -321,16 +322,6 @@ void __init pmac_setup_arch(void)
l2cr_init();
#endif /* CONFIG_PPC32 */
-#ifdef CONFIG_PPC64
- /* Probe motherboard chipset */
- /* this is done earlier in setup_arch for 32-bit */
- pmac_feature_init();
-
- /* We can NAP */
- powersave_nap = 1;
- printk(KERN_INFO "Using native/NAP idle loop\n");
-#endif
-
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
#endif
@@ -354,7 +345,7 @@ void __init pmac_setup_arch(void)
#ifdef CONFIG_SMP
/* Check for Core99 */
- if (find_devices("uni-n") || find_devices("u3"))
+ if (find_devices("uni-n") || find_devices("u3") || find_devices("u4"))
smp_ops = &core99_smp_ops;
#ifdef CONFIG_PPC32
else
@@ -621,35 +612,31 @@ static void __init pmac_init_early(void)
* and call ioremap
*/
hpte_init_native();
+#endif
- /* Init SCC */
- if (strstr(cmd_line, "sccdbg")) {
- sccdbg = 1;
- udbg_init_scc(NULL);
+ /* Enable early btext debug if requested */
+ if (strstr(cmd_line, "btextdbg")) {
+ udbg_adb_init_early();
+ register_early_udbg_console();
}
- /* Setup interrupt mapping options */
- ppc64_interrupt_controller = IC_OPEN_PIC;
+ /* Probe motherboard chipset */
+ pmac_feature_init();
- iommu_init_early_u3();
-#endif
-}
+ /* We can NAP */
+ powersave_nap = 1;
+ printk(KERN_INFO "Using native/NAP idle loop\n");
+
+ /* Initialize debug stuff */
+ udbg_scc_init(!!strstr(cmd_line, "sccdbg"));
+ udbg_adb_init(!!strstr(cmd_line, "btextdbg"));
-static void __init pmac_progress(char *s, unsigned short hex)
-{
#ifdef CONFIG_PPC64
- if (sccdbg) {
- udbg_puts(s);
- udbg_puts("\n");
- return;
- }
+ /* Setup interrupt mapping options */
+ ppc64_interrupt_controller = IC_OPEN_PIC;
+
+ iommu_init_early_dart();
#endif
-#ifdef CONFIG_BOOTX_TEXT
- if (boot_text_mapped) {
- btext_drawstring(s);
- btext_drawchar('\n');
- }
-#endif /* CONFIG_BOOTX_TEXT */
}
/*
@@ -663,35 +650,14 @@ static int pmac_check_legacy_ioport(unsigned int baseport)
static int __init pmac_declare_of_platform_devices(void)
{
- struct device_node *np, *npp;
-
- np = find_devices("uni-n");
- if (np) {
- for (np = np->child; np != NULL; np = np->sibling)
- if (strncmp(np->name, "i2c", 3) == 0) {
- of_platform_device_create(np, "uni-n-i2c",
- NULL);
- break;
- }
- }
- np = find_devices("valkyrie");
+ struct device_node *np;
+
+ np = of_find_node_by_name(NULL, "valkyrie");
if (np)
of_platform_device_create(np, "valkyrie", NULL);
- np = find_devices("platinum");
+ np = of_find_node_by_name(NULL, "platinum");
if (np)
of_platform_device_create(np, "platinum", NULL);
-
- npp = of_find_node_by_name(NULL, "u3");
- if (npp) {
- for (np = NULL; (np = of_get_next_child(npp, np)) != NULL;) {
- if (strncmp(np->name, "i2c", 3) == 0) {
- of_platform_device_create(np, "u3-i2c", NULL);
- of_node_put(np);
- break;
- }
- }
- of_node_put(npp);
- }
np = of_find_node_by_type(NULL, "smu");
if (np) {
of_platform_device_create(np, "smu", NULL);
@@ -718,7 +684,7 @@ static int __init pmac_probe(int platform)
* occupies having to be broken up so the DART itself is not
* part of the cacheable linar mapping
*/
- alloc_u3_dart_table();
+ alloc_dart_table();
#endif
#ifdef CONFIG_PMAC_SMU
@@ -734,15 +700,17 @@ static int __init pmac_probe(int platform)
}
#ifdef CONFIG_PPC64
-static int pmac_probe_mode(struct pci_bus *bus)
+/* Move that to pci.c */
+static int pmac_pci_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"))
+ * since the device for the AGP bridge isn't in the tree.
+ */
+ if (bus->self == NULL && (device_is_compatible(node, "u3-agp") ||
+ device_is_compatible(node, "u4-pcie")))
return PCI_PROBE_NORMAL;
-
return PCI_PROBE_DEVTREE;
}
#endif
@@ -756,7 +724,7 @@ struct machdep_calls __initdata pmac_md = {
.init_early = pmac_init_early,
.show_cpuinfo = pmac_show_cpuinfo,
.init_IRQ = pmac_pic_init,
- .get_irq = mpic_get_irq, /* changed later */
+ .get_irq = NULL, /* changed later */
.pcibios_fixup = pmac_pcibios_fixup,
.restart = pmac_restart,
.power_off = pmac_power_off,
@@ -768,12 +736,17 @@ struct machdep_calls __initdata pmac_md = {
.calibrate_decr = pmac_calibrate_decr,
.feature_call = pmac_do_feature_call,
.check_legacy_ioport = pmac_check_legacy_ioport,
- .progress = pmac_progress,
+ .progress = udbg_progress,
#ifdef CONFIG_PPC64
- .pci_probe_mode = pmac_probe_mode,
+ .pci_probe_mode = pmac_pci_probe_mode,
.idle_loop = native_idle,
.enable_pmcs = power4_enable_pmcs,
+#ifdef CONFIG_KEXEC
+ .machine_kexec = default_machine_kexec,
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
#endif
+#endif /* CONFIG_PPC64 */
#ifdef CONFIG_PPC32
.pcibios_enable_device_hook = pmac_pci_enable_device_hook,
.pcibios_after_init = pmac_pcibios_after_init,
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index fb2a7c798e82..0df2cdcd805c 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -52,8 +52,9 @@
#include <asm/cacheflush.h>
#include <asm/keylargo.h>
#include <asm/pmac_low_i2c.h>
+#include <asm/pmac_pfunc.h>
-#undef DEBUG
+#define DEBUG
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -62,6 +63,7 @@
#endif
extern void __secondary_start_pmac_0(void);
+extern int pmac_pfunc_base_install(void);
#ifdef CONFIG_PPC32
@@ -361,7 +363,6 @@ static void __init psurge_dual_sync_tb(int cpu_nr)
set_dec(tb_ticks_per_jiffy);
/* XXX fixme */
set_tb(0, 0);
- last_jiffy_stamp(cpu_nr) = 0;
if (cpu_nr > 0) {
mb();
@@ -429,15 +430,62 @@ struct smp_ops_t psurge_smp_ops = {
};
#endif /* CONFIG_PPC32 - actually powersurge support */
+/*
+ * Core 99 and later support
+ */
+
+static void (*pmac_tb_freeze)(int freeze);
+static unsigned long timebase;
+static int tb_req;
+
+static void smp_core99_give_timebase(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ while(!tb_req)
+ barrier();
+ tb_req = 0;
+ (*pmac_tb_freeze)(1);
+ mb();
+ timebase = get_tb();
+ mb();
+ while (timebase)
+ barrier();
+ mb();
+ (*pmac_tb_freeze)(0);
+ mb();
+
+ local_irq_restore(flags);
+}
+
+
+static void __devinit smp_core99_take_timebase(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ tb_req = 1;
+ mb();
+ while (!timebase)
+ barrier();
+ mb();
+ set_tb(timebase >> 32, timebase & 0xffffffff);
+ timebase = 0;
+ mb();
+ set_dec(tb_ticks_per_jiffy/2);
+
+ local_irq_restore(flags);
+}
+
#ifdef CONFIG_PPC64
/*
* G5s enable/disable the timebase via an i2c-connected clock chip.
*/
-static struct device_node *pmac_tb_clock_chip_host;
+static struct pmac_i2c_bus *pmac_tb_clock_chip_host;
static u8 pmac_tb_pulsar_addr;
-static void (*pmac_tb_freeze)(int freeze);
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase;
static void smp_core99_cypress_tb_freeze(int freeze)
{
@@ -447,19 +495,20 @@ static void smp_core99_cypress_tb_freeze(int freeze)
/* Strangely, the device-tree says address is 0xd2, but darwin
* accesses 0xd0 ...
*/
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd0 | pmac_low_i2c_read,
- 0x81, &data, 1);
+ pmac_i2c_setmode(pmac_tb_clock_chip_host,
+ pmac_i2c_mode_combined);
+ rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
+ 0xd0 | pmac_i2c_read,
+ 1, 0x81, &data, 1);
if (rc != 0)
goto bail;
data = (data & 0xf3) | (freeze ? 0x00 : 0x0c);
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd0 | pmac_low_i2c_write,
- 0x81, &data, 1);
+ pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub);
+ rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
+ 0xd0 | pmac_i2c_write,
+ 1, 0x81, &data, 1);
bail:
if (rc != 0) {
@@ -475,19 +524,20 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
u8 data;
int rc;
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- pmac_tb_pulsar_addr | pmac_low_i2c_read,
- 0x2e, &data, 1);
+ pmac_i2c_setmode(pmac_tb_clock_chip_host,
+ pmac_i2c_mode_combined);
+ rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
+ pmac_tb_pulsar_addr | pmac_i2c_read,
+ 1, 0x2e, &data, 1);
if (rc != 0)
goto bail;
data = (data & 0x88) | (freeze ? 0x11 : 0x22);
- pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- pmac_tb_pulsar_addr | pmac_low_i2c_write,
- 0x2e, &data, 1);
+ pmac_i2c_setmode(pmac_tb_clock_chip_host, pmac_i2c_mode_stdsub);
+ rc = pmac_i2c_xfer(pmac_tb_clock_chip_host,
+ pmac_tb_pulsar_addr | pmac_i2c_write,
+ 1, 0x2e, &data, 1);
bail:
if (rc != 0) {
printk(KERN_ERR "Pulsar Timebase %s rc: %d\n",
@@ -496,54 +546,14 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
}
}
-
-static void smp_core99_give_timebase(void)
-{
- /* Open i2c bus for synchronous access */
- if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
- panic("Can't open i2c for TB sync !\n");
-
- spin_lock(&timebase_lock);
- (*pmac_tb_freeze)(1);
- mb();
- timebase = get_tb();
- spin_unlock(&timebase_lock);
-
- while (timebase)
- barrier();
-
- spin_lock(&timebase_lock);
- (*pmac_tb_freeze)(0);
- spin_unlock(&timebase_lock);
-
- /* Close i2c bus */
- pmac_low_i2c_close(pmac_tb_clock_chip_host);
-}
-
-
-static void __devinit smp_core99_take_timebase(void)
-{
- while (!timebase)
- barrier();
- spin_lock(&timebase_lock);
- set_tb(timebase >> 32, timebase & 0xffffffff);
- timebase = 0;
- spin_unlock(&timebase_lock);
-}
-
-static void __init smp_core99_setup(int ncpus)
+static void __init smp_core99_setup_i2c_hwsync(int ncpus)
{
struct device_node *cc = NULL;
struct device_node *p;
+ const char *name = NULL;
u32 *reg;
int ok;
- /* HW sync only on these platforms */
- if (!machine_is_compatible("PowerMac7,2") &&
- !machine_is_compatible("PowerMac7,3") &&
- !machine_is_compatible("RackMac3,1"))
- return;
-
/* Look for the clock chip */
while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
p = of_get_parent(cc);
@@ -552,124 +562,86 @@ static void __init smp_core99_setup(int ncpus)
if (!ok)
continue;
+ pmac_tb_clock_chip_host = pmac_i2c_find_bus(cc);
+ if (pmac_tb_clock_chip_host == NULL)
+ continue;
reg = (u32 *)get_property(cc, "reg", NULL);
if (reg == NULL)
continue;
-
switch (*reg) {
case 0xd2:
- if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
+ if (device_is_compatible(cc,"pulsar-legacy-slewing")) {
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
pmac_tb_pulsar_addr = 0xd2;
- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+ name = "Pulsar";
} else if (device_is_compatible(cc, "cy28508")) {
pmac_tb_freeze = smp_core99_cypress_tb_freeze;
- printk(KERN_INFO "Timebase clock is Cypress chip\n");
+ name = "Cypress";
}
break;
case 0xd4:
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
pmac_tb_pulsar_addr = 0xd4;
- printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+ name = "Pulsar";
break;
}
- if (pmac_tb_freeze != NULL) {
- pmac_tb_clock_chip_host = of_get_parent(cc);
- of_node_put(cc);
+ if (pmac_tb_freeze != NULL)
break;
- }
}
- if (pmac_tb_freeze == NULL) {
- smp_ops->give_timebase = smp_generic_give_timebase;
- smp_ops->take_timebase = smp_generic_take_timebase;
+ if (pmac_tb_freeze != NULL) {
+ /* Open i2c bus for synchronous access */
+ if (pmac_i2c_open(pmac_tb_clock_chip_host, 1)) {
+ printk(KERN_ERR "Failed top open i2c bus for clock"
+ " sync, fallback to software sync !\n");
+ goto no_i2c_sync;
+ }
+ printk(KERN_INFO "Processor timebase sync using %s i2c clock\n",
+ name);
+ return;
}
+ no_i2c_sync:
+ pmac_tb_freeze = NULL;
+ pmac_tb_clock_chip_host = NULL;
}
-/* nothing to do here, caches are already set up by service processor */
-static inline void __devinit core99_init_caches(int cpu)
+
+
+/*
+ * Newer G5s uses a platform function
+ */
+
+static void smp_core99_pfunc_tb_freeze(int freeze)
{
+ struct device_node *cpus;
+ struct pmf_args args;
+
+ cpus = of_find_node_by_path("/cpus");
+ BUG_ON(cpus == NULL);
+ args.count = 1;
+ args.u[0].v = !freeze;
+ pmf_call_function(cpus, "cpu-timebase", &args);
+ of_node_put(cpus);
}
#else /* CONFIG_PPC64 */
/*
- * SMP G4 powermacs use a GPIO to enable/disable the timebase.
+ * SMP G4 use a GPIO to enable/disable the timebase.
*/
static unsigned int core99_tb_gpio; /* Timebase freeze GPIO */
-static unsigned int pri_tb_hi, pri_tb_lo;
-static unsigned int pri_tb_stamp;
-
-/* not __init, called in sleep/wakeup code */
-void smp_core99_give_timebase(void)
+static void smp_core99_gpio_tb_freeze(int freeze)
{
- unsigned long flags;
- unsigned int t;
-
- /* wait for the secondary to be in take_timebase */
- for (t = 100000; t > 0 && !sec_tb_reset; --t)
- udelay(10);
- if (!sec_tb_reset) {
- printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
- return;
- }
-
- /* freeze the timebase and read it */
- /* disable interrupts so the timebase is disabled for the
- shortest possible time */
- local_irq_save(flags);
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+ if (freeze)
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+ else
+ pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
- mb();
- pri_tb_hi = get_tbu();
- pri_tb_lo = get_tbl();
- pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
- mb();
-
- /* tell the secondary we're ready */
- sec_tb_reset = 2;
- mb();
-
- /* wait for the secondary to have taken it */
- /* note: can't use udelay here, since it needs the timebase running */
- for (t = 10000000; t > 0 && sec_tb_reset; --t)
- barrier();
- if (sec_tb_reset)
- /* XXX BUG_ON here? */
- printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
-
- /* Now, restart the timebase by leaving the GPIO to an open collector */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
- pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
- local_irq_restore(flags);
}
-/* not __init, called in sleep/wakeup code */
-void smp_core99_take_timebase(void)
-{
- unsigned long flags;
-
- /* tell the primary we're here */
- sec_tb_reset = 1;
- mb();
-
- /* wait for the primary to set pri_tb_hi/lo */
- while (sec_tb_reset < 2)
- mb();
-
- /* set our stuff the same as the primary */
- local_irq_save(flags);
- set_dec(1);
- set_tb(pri_tb_hi, pri_tb_lo);
- last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
- mb();
- /* tell the primary we're done */
- sec_tb_reset = 0;
- mb();
- local_irq_restore(flags);
-}
+#endif /* !CONFIG_PPC64 */
/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
volatile static long int core99_l2_cache;
@@ -677,6 +649,7 @@ volatile static long int core99_l3_cache;
static void __devinit core99_init_caches(int cpu)
{
+#ifndef CONFIG_PPC64
if (!cpu_has_feature(CPU_FTR_L2CR))
return;
@@ -702,30 +675,76 @@ static void __devinit core99_init_caches(int cpu)
_set_L3CR(core99_l3_cache);
printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
}
+#endif /* !CONFIG_PPC64 */
}
static void __init smp_core99_setup(int ncpus)
{
- struct device_node *cpu;
- u32 *tbprop = NULL;
- int i;
+#ifdef CONFIG_PPC64
+
+ /* i2c based HW sync on some G5s */
+ if (machine_is_compatible("PowerMac7,2") ||
+ machine_is_compatible("PowerMac7,3") ||
+ machine_is_compatible("RackMac3,1"))
+ smp_core99_setup_i2c_hwsync(ncpus);
- core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
- cpu = of_find_node_by_type(NULL, "cpu");
- if (cpu != NULL) {
- tbprop = (u32 *)get_property(cpu, "timebase-enable", NULL);
- if (tbprop)
- core99_tb_gpio = *tbprop;
- of_node_put(cpu);
+ /* pfunc based HW sync on recent G5s */
+ if (pmac_tb_freeze == NULL) {
+ struct device_node *cpus =
+ of_find_node_by_path("/cpus");
+ if (cpus &&
+ get_property(cpus, "platform-cpu-timebase", NULL)) {
+ pmac_tb_freeze = smp_core99_pfunc_tb_freeze;
+ printk(KERN_INFO "Processor timebase sync using"
+ " platform function\n");
+ }
}
- /* XXX should get this from reg properties */
- for (i = 1; i < ncpus; ++i)
- smp_hw_index[i] = i;
- powersave_nap = 0;
-}
+#else /* CONFIG_PPC64 */
+
+ /* GPIO based HW sync on ppc32 Core99 */
+ if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) {
+ struct device_node *cpu;
+ u32 *tbprop = NULL;
+
+ core99_tb_gpio = KL_GPIO_TB_ENABLE; /* default value */
+ cpu = of_find_node_by_type(NULL, "cpu");
+ if (cpu != NULL) {
+ tbprop = (u32 *)get_property(cpu, "timebase-enable",
+ NULL);
+ if (tbprop)
+ core99_tb_gpio = *tbprop;
+ of_node_put(cpu);
+ }
+ pmac_tb_freeze = smp_core99_gpio_tb_freeze;
+ printk(KERN_INFO "Processor timebase sync using"
+ " GPIO 0x%02x\n", core99_tb_gpio);
+ }
+
+#endif /* CONFIG_PPC64 */
+
+ /* No timebase sync, fallback to software */
+ if (pmac_tb_freeze == NULL) {
+ smp_ops->give_timebase = smp_generic_give_timebase;
+ smp_ops->take_timebase = smp_generic_take_timebase;
+ printk(KERN_INFO "Processor timebase sync using software\n");
+ }
+
+#ifndef CONFIG_PPC64
+ {
+ int i;
+
+ /* XXX should get this from reg properties */
+ for (i = 1; i < ncpus; ++i)
+ smp_hw_index[i] = i;
+ }
#endif
+ /* 32 bits SMP can't NAP */
+ if (!machine_is_compatible("MacRISC4"))
+ powersave_nap = 0;
+}
+
static int __init smp_core99_probe(void)
{
struct device_node *cpus;
@@ -743,8 +762,19 @@ static int __init smp_core99_probe(void)
if (ncpus <= 1)
return 1;
+ /* We need to perform some early initialisations before we can start
+ * setting up SMP as we are running before initcalls
+ */
+ pmac_pfunc_base_install();
+ pmac_i2c_init();
+
+ /* Setup various bits like timebase sync method, ability to nap, ... */
smp_core99_setup(ncpus);
+
+ /* Install IPIs */
mpic_request_ipis();
+
+ /* Collect l2cr and l3cr values from CPU 0 */
core99_init_caches(0);
return ncpus;
@@ -753,14 +783,15 @@ static int __init smp_core99_probe(void)
static void __devinit smp_core99_kick_cpu(int nr)
{
unsigned int save_vector;
- unsigned long new_vector;
- unsigned long flags;
+ unsigned long target, flags;
volatile unsigned int *vector
= ((volatile unsigned int *)(KERNELBASE+0x100));
if (nr < 0 || nr > 3)
return;
- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+
+ if (ppc_md.progress)
+ ppc_md.progress("smp_core99_kick_cpu", 0x346);
local_irq_save(flags);
local_irq_disable();
@@ -768,14 +799,11 @@ static void __devinit smp_core99_kick_cpu(int nr)
/* Save reset vector */
save_vector = *vector;
- /* Setup fake reset vector that does
+ /* Setup fake reset vector that does
* b __secondary_start_pmac_0 + nr*8 - KERNELBASE
*/
- new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;
- *vector = 0x48000002 + new_vector - KERNELBASE;
-
- /* flush data cache and inval instruction cache */
- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+ target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
+ create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
/* Put some life in our friend */
pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
@@ -805,17 +833,25 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
mpic_setup_this_cpu();
if (cpu_nr == 0) {
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
extern void g5_phy_disable_cpu1(void);
+ /* Close i2c bus if it was used for tb sync */
+ if (pmac_tb_clock_chip_host) {
+ pmac_i2c_close(pmac_tb_clock_chip_host);
+ pmac_tb_clock_chip_host = NULL;
+ }
+
/* If we didn't start the second CPU, we must take
* it off the bus
*/
if (machine_is_compatible("MacRISC4") &&
num_online_cpus() < 2)
g5_phy_disable_cpu1();
-#endif /* CONFIG_POWER4 */
- if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+#endif /* CONFIG_PPC64 */
+
+ if (ppc_md.progress)
+ ppc_md.progress("core99_setup_cpu 0 done", 0x349);
}
}
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index feb0a94e7819..5d9afa1fa02d 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -258,15 +258,20 @@ int __init via_calibrate_decr(void)
volatile unsigned char __iomem *via;
int count = VIA_TIMER_FREQ_6 / 100;
unsigned int dstart, dend;
+ struct resource rsrc;
- vias = find_devices("via-cuda");
+ vias = of_find_node_by_name(NULL, "via-cuda");
if (vias == 0)
- vias = find_devices("via-pmu");
+ vias = of_find_node_by_name(NULL, "via-pmu");
if (vias == 0)
- vias = find_devices("via");
- if (vias == 0 || vias->n_addrs == 0)
+ vias = of_find_node_by_name(NULL, "via");
+ if (vias == 0 || of_address_to_resource(vias, 0, &rsrc))
return 0;
- via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
+ via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ if (via == NULL) {
+ printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
+ return 0;
+ }
/* set timer 1 for continuous interrupts */
out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c
new file mode 100644
index 000000000000..06c8265c2baf
--- /dev/null
+++ b/arch/powerpc/platforms/powermac/udbg_adb.c
@@ -0,0 +1,221 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <linux/ptrace.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <linux/cuda.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/xmon.h>
+#include <asm/prom.h>
+#include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/errno.h>
+#include <asm/pmac_feature.h>
+#include <asm/processor.h>
+#include <asm/delay.h>
+#include <asm/btext.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+/*
+ * This implementation is "special", it can "patch" the current
+ * udbg implementation and work on top of it. It must thus be
+ * initialized last
+ */
+
+static void (*udbg_adb_old_putc)(char c);
+static int (*udbg_adb_old_getc)(void);
+static int (*udbg_adb_old_getc_poll)(void);
+
+static enum {
+ input_adb_none,
+ input_adb_pmu,
+ input_adb_cuda,
+} input_type = input_adb_none;
+
+int xmon_wants_key, xmon_adb_keycode;
+
+static inline void udbg_adb_poll(void)
+{
+#ifdef CONFIG_ADB_PMU
+ if (input_type == input_adb_pmu)
+ pmu_poll_adb();
+#endif /* CONFIG_ADB_PMU */
+#ifdef CONFIG_ADB_CUDA
+ if (input_type == input_adb_cuda)
+ cuda_poll();
+#endif /* CONFIG_ADB_CUDA */
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+
+static int udbg_adb_use_btext;
+static int xmon_adb_shiftstate;
+
+static unsigned char xmon_keytab[128] =
+ "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
+ "yt123465=97-80]o" /* 0x10 - 0x1f */
+ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
+ "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
+ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
+ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
+
+static unsigned char xmon_shift_keytab[128] =
+ "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
+ "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
+ "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
+ "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
+ "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
+ "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
+
+static int udbg_adb_local_getc(void)
+{
+ int k, t, on;
+
+ xmon_wants_key = 1;
+ for (;;) {
+ xmon_adb_keycode = -1;
+ t = 0;
+ on = 0;
+ k = -1;
+ do {
+ if (--t < 0) {
+ on = 1 - on;
+ btext_drawchar(on? 0xdb: 0x20);
+ btext_drawchar('\b');
+ t = 200000;
+ }
+ udbg_adb_poll();
+ if (udbg_adb_old_getc_poll)
+ k = udbg_adb_old_getc_poll();
+ } while (k == -1 && xmon_adb_keycode == -1);
+ if (on)
+ btext_drawstring(" \b");
+ if (k != -1)
+ return k;
+ k = xmon_adb_keycode;
+
+ /* test for shift keys */
+ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
+ xmon_adb_shiftstate = (k & 0x80) == 0;
+ continue;
+ }
+ if (k >= 0x80)
+ continue; /* ignore up transitions */
+ k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
+ if (k != 0)
+ break;
+ }
+ xmon_wants_key = 0;
+ return k;
+}
+#endif /* CONFIG_BOOTX_TEXT */
+
+static int udbg_adb_getc(void)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ if (udbg_adb_use_btext && input_type != input_adb_none)
+ return udbg_adb_local_getc();
+#endif
+ if (udbg_adb_old_getc)
+ return udbg_adb_old_getc();
+ return -1;
+}
+
+/* getc_poll() is not really used, unless you have the xmon-over modem
+ * hack that doesn't quite concern us here, thus we just poll the low level
+ * ADB driver to prevent it from timing out and call back the original poll
+ * routine.
+ */
+static int udbg_adb_getc_poll(void)
+{
+ udbg_adb_poll();
+
+ if (udbg_adb_old_getc_poll)
+ return udbg_adb_old_getc_poll();
+ return -1;
+}
+
+static void udbg_adb_putc(char c)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ if (udbg_adb_use_btext)
+ btext_drawchar(c);
+#endif
+ if (udbg_adb_old_putc)
+ return udbg_adb_old_putc(c);
+}
+
+void udbg_adb_init_early(void)
+{
+#ifdef CONFIG_BOOTX_TEXT
+ if (btext_find_display(1) == 0) {
+ udbg_adb_use_btext = 1;
+ udbg_putc = udbg_adb_putc;
+ }
+#endif
+}
+
+int udbg_adb_init(int force_btext)
+{
+ struct device_node *np;
+
+ /* Capture existing callbacks */
+ udbg_adb_old_putc = udbg_putc;
+ udbg_adb_old_getc = udbg_getc;
+ udbg_adb_old_getc_poll = udbg_getc_poll;
+
+ /* Check if our early init was already called */
+ if (udbg_adb_old_putc == udbg_adb_putc)
+ udbg_adb_old_putc = NULL;
+#ifdef CONFIG_BOOTX_TEXT
+ if (udbg_adb_old_putc == btext_drawchar)
+ udbg_adb_old_putc = NULL;
+#endif
+
+ /* Set ours as output */
+ udbg_putc = udbg_adb_putc;
+ udbg_getc = udbg_adb_getc;
+ udbg_getc_poll = udbg_adb_getc_poll;
+
+#ifdef CONFIG_BOOTX_TEXT
+ /* Check if we should use btext output */
+ if (btext_find_display(force_btext) == 0)
+ udbg_adb_use_btext = 1;
+#endif
+
+ /* See if there is a keyboard in the device tree with a parent
+ * of type "adb". If not, we return a failure, but we keep the
+ * bext output set for now
+ */
+ for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) {
+ struct device_node *parent = of_get_parent(np);
+ int found = (parent && strcmp(parent->type, "adb") == 0);
+ of_node_put(parent);
+ if (found)
+ break;
+ }
+ if (np == NULL)
+ return -ENODEV;
+ of_node_put(np);
+
+#ifdef CONFIG_ADB_PMU
+ if (find_via_pmu())
+ input_type = input_adb_pmu;
+#endif
+#ifdef CONFIG_ADB_CUDA
+ if (find_via_cuda())
+ input_type = input_adb_cuda;
+#endif
+
+ /* Same as above: nothing found, keep btext set for output */
+ if (input_type == input_adb_none)
+ return -ENODEV;
+
+ return 0;
+}
diff --git a/arch/powerpc/kernel/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
index 820c53551507..c4352a8db644 100644
--- a/arch/powerpc/kernel/udbg_scc.c
+++ b/arch/powerpc/platforms/powermac/udbg_scc.c
@@ -25,7 +25,7 @@ extern void real_writeb(u8 data, volatile u8 __iomem *addr);
static volatile u8 __iomem *sccc;
static volatile u8 __iomem *sccd;
-static void udbg_scc_putc(unsigned char c)
+static void udbg_scc_putc(char c)
{
if (sccc) {
while ((in_8(sccc) & SCC_TXRDY) == 0)
@@ -47,14 +47,14 @@ static int udbg_scc_getc_poll(void)
return -1;
}
-static unsigned char udbg_scc_getc(void)
+static int udbg_scc_getc(void)
{
if (sccc) {
while ((in_8(sccc) & SCC_RXRDY) == 0)
;
return in_8(sccd);
}
- return 0;
+ return -1;
}
static unsigned char scc_inittab[] = {
@@ -67,38 +67,59 @@ static unsigned char scc_inittab[] = {
3, 0xc1, /* rx enable, 8 bits */
};
-void udbg_init_scc(struct device_node *np)
+void udbg_scc_init(int force_scc)
{
u32 *reg;
unsigned long addr;
+ struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
+ struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
+ char *path;
int i, x;
- if (np == NULL)
- np = of_find_node_by_name(NULL, "escc");
- if (np == NULL || np->parent == NULL)
- return;
+ escc = of_find_node_by_name(NULL, "escc");
+ if (escc == NULL)
+ goto bail;
+ macio = of_get_parent(escc);
+ if (macio == NULL)
+ goto bail;
+ path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+ if (path != NULL)
+ stdout = of_find_node_by_path(path);
+ for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
+ if (ch == stdout)
+ ch_def = of_node_get(ch);
+ if (strcmp(ch->name, "ch-a") == 0)
+ ch_a = of_node_get(ch);
+ }
+ if (ch_def == NULL && !force_scc)
+ goto bail;
+
+ ch = ch_def ? ch_def : ch_a;
- udbg_printf("found SCC...\n");
/* Get address within mac-io ASIC */
- reg = (u32 *)get_property(np, "reg", NULL);
+ reg = (u32 *)get_property(escc, "reg", NULL);
if (reg == NULL)
- return;
+ goto bail;
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);
+ reg = (u32 *)get_property(macio, "assigned-addresses", NULL);
if (reg == NULL)
- return;
+ goto bail;
addr += reg[2];
- udbg_printf("final addr: %lx\n", addr);
+
+ /* Lock the serial port */
+ pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
+ PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
+
/* Setup for 57600 8N1 */
- addr += 0x20;
+ if (ch == ch_a)
+ 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)
@@ -113,9 +134,17 @@ void udbg_init_scc(struct device_node *np)
udbg_getc_poll = udbg_scc_getc_poll;
udbg_puts("Hello World !\n");
+
+ bail:
+ of_node_put(macio);
+ of_node_put(escc);
+ of_node_put(stdout);
+ of_node_put(ch_def);
+ of_node_put(ch_a);
}
-static void udbg_real_scc_putc(unsigned char c)
+#ifdef CONFIG_PPC64
+static void udbg_real_scc_putc(char c)
{
while ((real_readb(sccc) & SCC_TXRDY) == 0)
;
@@ -124,7 +153,7 @@ static void udbg_real_scc_putc(unsigned char c)
udbg_real_scc_putc('\r');
}
-void udbg_init_pmac_realmode(void)
+void __init udbg_init_pmac_realmode(void)
{
sccc = (volatile u8 __iomem *)0x80013020ul;
sccd = (volatile u8 __iomem *)0x80013030ul;
@@ -133,3 +162,4 @@ void udbg_init_pmac_realmode(void)
udbg_getc = NULL;
udbg_getc_poll = NULL;
}
+#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 06d5ef501218..61616d144072 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,10 +1,10 @@
obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \
- setup.o iommu.o ras.o rtasd.o
+ setup.o iommu.o ras.o rtasd.o pci_dlpar.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_IBMVIO) += vio.o
obj-$(CONFIG_XICS) += xics.o
obj-$(CONFIG_SCANLOG) += scanlog.o
-obj-$(CONFIG_EEH) += eeh.o eeh_event.o
+obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o
obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_HVCS) += hvcserver.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index c8d2a40dc5b4..83578313ee7e 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -76,15 +76,14 @@
*/
#define EEH_MAX_FAILS 100000
-/* Misc forward declaraions */
-static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn);
-
/* RTAS tokens */
static int ibm_set_eeh_option;
static int ibm_set_slot_reset;
static int ibm_read_slot_reset_state;
static int ibm_read_slot_reset_state2;
static int ibm_slot_error_detail;
+static int ibm_get_config_addr_info;
+static int ibm_configure_bridge;
int eeh_subsystem_enabled;
EXPORT_SYMBOL(eeh_subsystem_enabled);
@@ -98,308 +97,23 @@ static DEFINE_SPINLOCK(slot_errbuf_lock);
static int eeh_error_buf_size;
/* System monitoring statistics */
-static DEFINE_PER_CPU(unsigned long, no_device);
-static DEFINE_PER_CPU(unsigned long, no_dn);
-static DEFINE_PER_CPU(unsigned long, no_cfg_addr);
-static DEFINE_PER_CPU(unsigned long, ignored_check);
-static DEFINE_PER_CPU(unsigned long, total_mmio_ffs);
-static DEFINE_PER_CPU(unsigned long, false_positives);
-static DEFINE_PER_CPU(unsigned long, ignored_failures);
-static DEFINE_PER_CPU(unsigned long, slot_resets);
-
-/**
- * The pci address cache subsystem. This subsystem places
- * PCI device address resources into a red-black tree, sorted
- * according to the address range, so that given only an i/o
- * address, the corresponding PCI device can be **quickly**
- * found. It is safe to perform an address lookup in an interrupt
- * context; this ability is an important feature.
- *
- * Currently, the only customer of this code is the EEH subsystem;
- * thus, this code has been somewhat tailored to suit EEH better.
- * In particular, the cache does *not* hold the addresses of devices
- * for which EEH is not enabled.
- *
- * (Implementation Note: The RB tree seems to be better/faster
- * than any hash algo I could think of for this problem, even
- * with the penalty of slow pointer chases for d-cache misses).
- */
-struct pci_io_addr_range
-{
- struct rb_node rb_node;
- unsigned long addr_lo;
- unsigned long addr_hi;
- struct pci_dev *pcidev;
- unsigned int flags;
-};
-
-static struct pci_io_addr_cache
-{
- struct rb_root rb_root;
- spinlock_t piar_lock;
-} pci_io_addr_cache_root;
-
-static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
-{
- struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
-
- while (n) {
- struct pci_io_addr_range *piar;
- piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-
- if (addr < piar->addr_lo) {
- n = n->rb_left;
- } else {
- if (addr > piar->addr_hi) {
- n = n->rb_right;
- } else {
- pci_dev_get(piar->pcidev);
- return piar->pcidev;
- }
- }
- }
-
- return NULL;
-}
-
-/**
- * pci_get_device_by_addr - Get device, given only address
- * @addr: mmio (PIO) phys address or i/o port number
- *
- * Given an mmio phys address, or a port number, find a pci device
- * that implements this address. Be sure to pci_dev_put the device
- * when finished. I/O port numbers are assumed to be offset
- * from zero (that is, they do *not* have pci_io_addr added in).
- * It is safe to call this function within an interrupt.
- */
-static struct pci_dev *pci_get_device_by_addr(unsigned long addr)
-{
- struct pci_dev *dev;
- unsigned long flags;
-
- spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
- dev = __pci_get_device_by_addr(addr);
- spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
- return dev;
-}
-
-#ifdef DEBUG
-/*
- * Handy-dandy debug print routine, does nothing more
- * than print out the contents of our addr cache.
- */
-static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
-{
- struct rb_node *n;
- int cnt = 0;
-
- n = rb_first(&cache->rb_root);
- 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\n",
- (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
- piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
- cnt++;
- n = rb_next(n);
- }
-}
-#endif
-
-/* Insert address range into the rb tree. */
-static struct pci_io_addr_range *
-pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
- unsigned long ahi, unsigned int flags)
-{
- struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
- struct rb_node *parent = NULL;
- struct pci_io_addr_range *piar;
-
- /* Walk tree, find a place to insert into tree */
- while (*p) {
- parent = *p;
- piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
- if (ahi < piar->addr_lo) {
- p = &parent->rb_left;
- } else if (alo > piar->addr_hi) {
- p = &parent->rb_right;
- } else {
- if (dev != piar->pcidev ||
- alo != piar->addr_lo || ahi != piar->addr_hi) {
- printk(KERN_WARNING "PIAR: overlapping address range\n");
- }
- return piar;
- }
- }
- piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
- if (!piar)
- return NULL;
-
- piar->addr_lo = alo;
- piar->addr_hi = ahi;
- piar->pcidev = dev;
- piar->flags = flags;
-
-#ifdef DEBUG
- printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
- alo, ahi, pci_name (dev));
-#endif
+static unsigned long no_device;
+static unsigned long no_dn;
+static unsigned long no_cfg_addr;
+static unsigned long ignored_check;
+static unsigned long total_mmio_ffs;
+static unsigned long false_positives;
+static unsigned long ignored_failures;
+static unsigned long slot_resets;
- rb_link_node(&piar->rb_node, parent, p);
- rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
-
- return piar;
-}
-
-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\n", pci_name(dev));
- return;
- }
-
- /* Skip any devices for which EEH is not enabled. */
- pdn = PCI_DN(dn);
- 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), pdn->node->full_name);
-#endif
- return;
- }
-
- /* The cache holds a reference to the device... */
- pci_dev_get(dev);
-
- /* Walk resources on this device, poke them into the tree */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- unsigned long start = pci_resource_start(dev,i);
- unsigned long end = pci_resource_end(dev,i);
- unsigned int flags = pci_resource_flags(dev,i);
-
- /* We are interested only bus addresses, not dma or other stuff */
- if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
- continue;
- if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
- continue;
- pci_addr_cache_insert(dev, start, end, flags);
- inserted = 1;
- }
-
- /* If there was nothing to add, the cache has no reference... */
- if (!inserted)
- pci_dev_put(dev);
-}
-
-/**
- * pci_addr_cache_insert_device - Add a device to the address cache
- * @dev: PCI device whose I/O addresses we are interested in.
- *
- * In order to support the fast lookup of devices based on addresses,
- * we maintain a cache of devices that can be quickly searched.
- * This routine adds a device to that cache.
- */
-static void pci_addr_cache_insert_device(struct pci_dev *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
- __pci_addr_cache_insert_device(dev);
- spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-}
-
-static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
-{
- struct rb_node *n;
- int removed = 0;
-
-restart:
- n = rb_first(&pci_io_addr_cache_root.rb_root);
- while (n) {
- struct pci_io_addr_range *piar;
- piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-
- if (piar->pcidev == dev) {
- rb_erase(n, &pci_io_addr_cache_root.rb_root);
- removed = 1;
- kfree(piar);
- goto restart;
- }
- n = rb_next(n);
- }
-
- /* The cache no longer holds its reference to this device... */
- if (removed)
- pci_dev_put(dev);
-}
-
-/**
- * pci_addr_cache_remove_device - remove pci device from addr cache
- * @dev: device to remove
- *
- * Remove a device from the addr-cache tree.
- * This is potentially expensive, since it will walk
- * the tree multiple times (once per resource).
- * But so what; device removal doesn't need to be that fast.
- */
-static void pci_addr_cache_remove_device(struct pci_dev *dev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
- __pci_addr_cache_remove_device(dev);
- spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-}
-
-/**
- * pci_addr_cache_build - Build a cache of I/O addresses
- *
- * Build a cache of pci i/o addresses. This cache will be used to
- * find the pci device that corresponds to a given address.
- * This routine scans all pci busses to build the cache.
- * Must be run late in boot process, after the pci controllers
- * have been scaned for devices (after all device resources are known).
- */
-void __init pci_addr_cache_build(void)
-{
- struct device_node *dn;
- struct pci_dev *dev = NULL;
-
- if (!eeh_subsystem_enabled)
- return;
-
- spin_lock_init(&pci_io_addr_cache_root.piar_lock);
-
- while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- /* Ignore PCI bridges ( XXX why ??) */
- if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
- continue;
- }
- pci_addr_cache_insert_device(dev);
-
- /* Save the BAR's; firmware doesn't restore these after EEH reset */
- dn = pci_device_to_OF_node(dev);
- eeh_save_bars(dev, PCI_DN(dn));
- }
-
-#ifdef DEBUG
- /* Verify tree built up above, echo back the list of addrs. */
- pci_addr_cache_print(&pci_io_addr_cache_root);
-#endif
-}
+#define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE)
/* --------------------------------------------------------------- */
-/* Above lies the PCI Address Cache. Below lies the EEH event infrastructure */
+/* Below lies the EEH event infrastructure */
void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
{
+ int config_addr;
unsigned long flags;
int rc;
@@ -407,8 +121,13 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
spin_lock_irqsave(&slot_errbuf_lock, flags);
memset(slot_errbuf, 0, eeh_error_buf_size);
+ /* Use PE configuration address, if present */
+ config_addr = pdn->eeh_config_addr;
+ if (pdn->eeh_pe_config_addr)
+ config_addr = pdn->eeh_pe_config_addr;
+
rc = rtas_call(ibm_slot_error_detail,
- 8, 1, NULL, pdn->eeh_config_addr,
+ 8, 1, NULL, config_addr,
BUID_HI(pdn->phb->buid),
BUID_LO(pdn->phb->buid), NULL, 0,
virt_to_phys(slot_errbuf),
@@ -428,6 +147,7 @@ void eeh_slot_error_detail (struct pci_dn *pdn, int severity)
static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
{
int token, outputs;
+ int config_addr;
if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
token = ibm_read_slot_reset_state2;
@@ -438,7 +158,12 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
outputs = 3;
}
- return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+ /* Use PE configuration address, if present */
+ config_addr = pdn->eeh_config_addr;
+ if (pdn->eeh_pe_config_addr)
+ config_addr = pdn->eeh_pe_config_addr;
+
+ return rtas_call(token, 3, outputs, rets, config_addr,
BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
}
@@ -462,7 +187,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
/**
* Return the "partitionable endpoint" (pe) under which this device lies
*/
-static struct device_node * find_device_pe(struct device_node *dn)
+struct device_node * find_device_pe(struct device_node *dn)
{
while ((dn->parent) && PCI_DN(dn->parent) &&
(PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
@@ -483,8 +208,14 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
{
while (dn) {
if (PCI_DN(dn)) {
+ /* Mark the pci device driver too */
+ struct pci_dev *dev = PCI_DN(dn)->pcidev;
+
PCI_DN(dn)->eeh_mode |= mode_flag;
+ if (dev && dev->driver)
+ dev->error_state = pci_channel_io_frozen;
+
if (dn->child)
__eeh_mark_slot (dn->child, mode_flag);
}
@@ -495,6 +226,11 @@ static void __eeh_mark_slot (struct device_node *dn, int mode_flag)
void eeh_mark_slot (struct device_node *dn, int mode_flag)
{
dn = find_device_pe (dn);
+
+ /* Back up one, since config addrs might be shared */
+ if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ dn = dn->parent;
+
PCI_DN(dn)->eeh_mode |= mode_flag;
__eeh_mark_slot (dn->child, mode_flag);
}
@@ -516,7 +252,13 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag)
{
unsigned long flags;
spin_lock_irqsave(&confirm_error_lock, flags);
+
dn = find_device_pe (dn);
+
+ /* Back up one, since config addrs might be shared */
+ if (PCI_DN(dn) && PCI_DN(dn)->eeh_pe_config_addr)
+ dn = dn->parent;
+
PCI_DN(dn)->eeh_mode &= ~mode_flag;
PCI_DN(dn)->eeh_check_count = 0;
__eeh_clear_slot (dn->child, mode_flag);
@@ -544,15 +286,16 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
int rets[3];
unsigned long flags;
struct pci_dn *pdn;
+ enum pci_channel_state state;
int rc = 0;
- __get_cpu_var(total_mmio_ffs)++;
+ total_mmio_ffs++;
if (!eeh_subsystem_enabled)
return 0;
if (!dn) {
- __get_cpu_var(no_dn)++;
+ no_dn++;
return 0;
}
pdn = PCI_DN(dn);
@@ -560,7 +303,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
/* Access to IO BARs might get this far and still not want checking. */
if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
pdn->eeh_mode & EEH_MODE_NOCHECK) {
- __get_cpu_var(ignored_check)++;
+ ignored_check++;
#ifdef DEBUG
printk ("EEH:ignored check (%x) for %s %s\n",
pdn->eeh_mode, pci_name (dev), dn->full_name);
@@ -568,8 +311,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
return 0;
}
- if (!pdn->eeh_config_addr) {
- __get_cpu_var(no_cfg_addr)++;
+ if (!pdn->eeh_config_addr && !pdn->eeh_pe_config_addr) {
+ no_cfg_addr++;
return 0;
}
@@ -611,7 +354,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
if (ret != 0) {
printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n",
ret, dn->full_name);
- __get_cpu_var(false_positives)++;
+ false_positives++;
rc = 0;
goto dn_unlock;
}
@@ -620,14 +363,14 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
if (rets[1] != 1) {
printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n",
ret, dn->full_name);
- __get_cpu_var(false_positives)++;
+ false_positives++;
rc = 0;
goto dn_unlock;
}
/* If not the kind of error we know about, punt. */
if (rets[0] != 2 && rets[0] != 4 && rets[0] != 5) {
- __get_cpu_var(false_positives)++;
+ false_positives++;
rc = 0;
goto dn_unlock;
}
@@ -635,12 +378,12 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
/* Note that config-io to empty slots may fail;
* we recognize empty because they don't have children. */
if ((rets[0] == 5) && (dn->child == NULL)) {
- __get_cpu_var(false_positives)++;
+ false_positives++;
rc = 0;
goto dn_unlock;
}
- __get_cpu_var(slot_resets)++;
+ slot_resets++;
/* Avoid repeated reports of this failure, including problems
* with other functions on this device, and functions under
@@ -648,8 +391,13 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
eeh_mark_slot (dn, EEH_MODE_ISOLATED);
spin_unlock_irqrestore(&confirm_error_lock, flags);
- eeh_send_failure_event (dn, dev, rets[0], rets[2]);
-
+ state = pci_channel_io_normal;
+ if ((rets[0] == 2) || (rets[0] == 4))
+ state = pci_channel_io_frozen;
+ if (rets[0] == 5)
+ state = pci_channel_io_perm_failure;
+ eeh_send_failure_event (dn, dev, state, rets[2]);
+
/* Most EEH events are due to device driver bugs. Having
* a stack trace will help the device-driver authors figure
* out what happened. So print that out. */
@@ -685,7 +433,7 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon
addr = eeh_token_to_phys((unsigned long __force) token);
dev = pci_get_device_by_addr(addr);
if (!dev) {
- __get_cpu_var(no_device)++;
+ no_device++;
return val;
}
@@ -716,11 +464,16 @@ eeh_slot_availability(struct pci_dn *pdn)
if (rc) return rc;
if (rets[1] == 0) return -1; /* EEH is not supported */
- if (rets[0] == 0) return 0; /* Oll Korrect */
+ if (rets[0] == 0) return 0; /* Oll Korrect */
if (rets[0] == 5) {
if (rets[2] == 0) return -1; /* permanently unavailable */
return rets[2]; /* number of millisecs to wait */
}
+ if (rets[0] == 1)
+ return 250;
+
+ printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n",
+ rc, rets[0], rets[1], rets[2]);
return -1;
}
@@ -737,6 +490,7 @@ eeh_slot_availability(struct pci_dn *pdn)
static void
rtas_pci_slot_reset(struct pci_dn *pdn, int state)
{
+ int config_addr;
int rc;
BUG_ON (pdn==NULL);
@@ -747,8 +501,13 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
return;
}
+ /* Use PE configuration address, if present */
+ config_addr = pdn->eeh_config_addr;
+ if (pdn->eeh_pe_config_addr)
+ config_addr = pdn->eeh_pe_config_addr;
+
rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
- pdn->eeh_config_addr,
+ config_addr,
BUID_HI(pdn->phb->buid),
BUID_LO(pdn->phb->buid),
state);
@@ -761,9 +520,11 @@ rtas_pci_slot_reset(struct pci_dn *pdn, int state)
/** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
* dn -- device node to be reset.
+ *
+ * Return 0 if success, else a non-zero value.
*/
-void
+int
rtas_set_slot_reset(struct pci_dn *pdn)
{
int i, rc;
@@ -793,10 +554,21 @@ rtas_set_slot_reset(struct pci_dn *pdn)
* ready to be used; if not, wait for recovery. */
for (i=0; i<10; i++) {
rc = eeh_slot_availability (pdn);
- if (rc <= 0) break;
+ if (rc < 0)
+ printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", rc, pdn->node->full_name);
+ if (rc == 0)
+ return 0;
+ if (rc < 0)
+ return -1;
msleep (rc+100);
}
+
+ rc = eeh_slot_availability (pdn);
+ if (rc)
+ printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name);
+
+ return rc;
}
/* ------------------------------------------------------- */
@@ -851,7 +623,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
if (!pdn)
return;
- if (! pdn->eeh_is_bridge)
+ if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code))
__restore_bars (pdn);
dn = pdn->node->child;
@@ -869,30 +641,30 @@ void eeh_restore_bars(struct pci_dn *pdn)
* PCI devices are added individuallly; but, for the restore,
* an entire slot is reset at a time.
*/
-static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn)
+static void eeh_save_bars(struct pci_dn *pdn)
{
int i;
- if (!pdev || !pdn )
+ if (!pdn )
return;
for (i = 0; i < 16; i++)
- pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]);
-
- if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- pdn->eeh_is_bridge = 1;
+ rtas_read_config(pdn, i * 4, 4, &pdn->config_space[i]);
}
void
rtas_configure_bridge(struct pci_dn *pdn)
{
- int token = rtas_token ("ibm,configure-bridge");
+ int config_addr;
int rc;
- if (token == RTAS_UNKNOWN_SERVICE)
- return;
- rc = rtas_call(token,3,1, NULL,
- pdn->eeh_config_addr,
+ /* Use PE configuration address, if present */
+ config_addr = pdn->eeh_config_addr;
+ if (pdn->eeh_pe_config_addr)
+ config_addr = pdn->eeh_pe_config_addr;
+
+ rc = rtas_call(ibm_configure_bridge,3,1, NULL,
+ config_addr,
BUID_HI(pdn->phb->buid),
BUID_LO(pdn->phb->buid));
if (rc) {
@@ -927,6 +699,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
int enable;
struct pci_dn *pdn = PCI_DN(dn);
+ pdn->class_code = 0;
pdn->eeh_mode = 0;
pdn->eeh_check_count = 0;
pdn->eeh_freeze_count = 0;
@@ -943,6 +716,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
pdn->eeh_mode |= EEH_MODE_NOCHECK;
return NULL;
}
+ pdn->class_code = *class_code;
/*
* Now decide if we are going to "Disable" EEH checking
@@ -953,8 +727,10 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
* But there are a few cases like display devices that make sense.
*/
enable = 1; /* i.e. we will do checking */
+#if 0
if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
enable = 0;
+#endif
if (!enable)
pdn->eeh_mode |= EEH_MODE_NOCHECK;
@@ -973,8 +749,22 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
eeh_subsystem_enabled = 1;
pdn->eeh_mode |= EEH_MODE_SUPPORTED;
pdn->eeh_config_addr = regs[0];
+
+ /* If the newer, better, ibm,get-config-addr-info is supported,
+ * then use that instead. */
+ pdn->eeh_pe_config_addr = 0;
+ if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
+ unsigned int rets[2];
+ ret = rtas_call (ibm_get_config_addr_info, 4, 2, rets,
+ pdn->eeh_config_addr,
+ info->buid_hi, info->buid_lo,
+ 0);
+ if (ret == 0)
+ pdn->eeh_pe_config_addr = rets[0];
+ }
#ifdef DEBUG
- printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name);
+ printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n",
+ dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr);
#endif
} else {
@@ -993,6 +783,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
dn->full_name);
}
+ eeh_save_bars(pdn);
return NULL;
}
@@ -1026,6 +817,8 @@ void __init eeh_init(void)
ibm_read_slot_reset_state2 = rtas_token("ibm,read-slot-reset-state2");
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
ibm_slot_error_detail = rtas_token("ibm,slot-error-detail");
+ ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info");
+ ibm_configure_bridge = rtas_token ("ibm,configure-bridge");
if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE)
return;
@@ -1080,12 +873,10 @@ void eeh_add_device_early(struct device_node *dn)
if (!dn || !PCI_DN(dn))
return;
phb = PCI_DN(dn)->phb;
- if (NULL == phb || 0 == phb->buid) {
- printk(KERN_WARNING "EEH: Expected buid but found none for %s\n",
- dn->full_name);
- dump_stack();
+
+ /* USB Bus children of PCI devices will not have BUID's */
+ if (NULL == phb || 0 == phb->buid)
return;
- }
info.buid_hi = BUID_HI(phb->buid);
info.buid_lo = BUID_LO(phb->buid);
@@ -1093,6 +884,15 @@ void eeh_add_device_early(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(eeh_add_device_early);
+void eeh_add_device_tree_early(struct device_node *dn)
+{
+ struct device_node *sib;
+ for (sib = dn->child; sib; sib = sib->sibling)
+ eeh_add_device_tree_early(sib);
+ eeh_add_device_early(dn);
+}
+EXPORT_SYMBOL_GPL(eeh_add_device_tree_early);
+
/**
* eeh_add_device_late - perform EEH initialization for the indicated pci device
* @dev: pci device for which to set up EEH
@@ -1118,7 +918,6 @@ void eeh_add_device_late(struct pci_dev *dev)
pdn->pcidev = dev;
pci_addr_cache_insert_device (dev);
- eeh_save_bars(dev, pdn);
}
EXPORT_SYMBOL_GPL(eeh_add_device_late);
@@ -1147,27 +946,28 @@ void eeh_remove_device(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(eeh_remove_device);
-static int proc_eeh_show(struct seq_file *m, void *v)
-{
- unsigned int cpu;
- unsigned long ffs = 0, positives = 0, failures = 0;
- unsigned long resets = 0;
- unsigned long no_dev = 0, no_dn = 0, no_cfg = 0, no_check = 0;
-
- for_each_cpu(cpu) {
- ffs += per_cpu(total_mmio_ffs, cpu);
- positives += per_cpu(false_positives, cpu);
- failures += per_cpu(ignored_failures, cpu);
- resets += per_cpu(slot_resets, cpu);
- no_dev += per_cpu(no_device, cpu);
- no_dn += per_cpu(no_dn, cpu);
- no_cfg += per_cpu(no_cfg_addr, cpu);
- no_check += per_cpu(ignored_check, cpu);
+void eeh_remove_bus_device(struct pci_dev *dev)
+{
+ eeh_remove_device(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *bus = dev->subordinate;
+ struct list_head *ln;
+ if (!bus)
+ return;
+ for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+ struct pci_dev *pdev = pci_dev_b(ln);
+ if (pdev)
+ eeh_remove_bus_device(pdev);
+ }
}
+}
+EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
+static int proc_eeh_show(struct seq_file *m, void *v)
+{
if (0 == eeh_subsystem_enabled) {
seq_printf(m, "EEH Subsystem is globally disabled\n");
- seq_printf(m, "eeh_total_mmio_ffs=%ld\n", ffs);
+ seq_printf(m, "eeh_total_mmio_ffs=%ld\n", total_mmio_ffs);
} else {
seq_printf(m, "EEH Subsystem is enabled\n");
seq_printf(m,
@@ -1179,8 +979,10 @@ static int proc_eeh_show(struct seq_file *m, void *v)
"eeh_false_positives=%ld\n"
"eeh_ignored_failures=%ld\n"
"eeh_slot_resets=%ld\n",
- no_dev, no_dn, no_cfg, no_check,
- ffs, positives, failures, resets);
+ no_device, no_dn, no_cfg_addr,
+ ignored_check, total_mmio_ffs,
+ false_positives, ignored_failures,
+ slot_resets);
}
return 0;
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
new file mode 100644
index 000000000000..d4a402c5866c
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -0,0 +1,316 @@
+/*
+ * eeh_cache.c
+ * PCI address cache; allows the lookup of PCI devices based on I/O address
+ *
+ * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/list.h>
+#include <linux/pci.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+#undef DEBUG
+
+/**
+ * The pci address cache subsystem. This subsystem places
+ * PCI device address resources into a red-black tree, sorted
+ * according to the address range, so that given only an i/o
+ * address, the corresponding PCI device can be **quickly**
+ * found. It is safe to perform an address lookup in an interrupt
+ * context; this ability is an important feature.
+ *
+ * Currently, the only customer of this code is the EEH subsystem;
+ * thus, this code has been somewhat tailored to suit EEH better.
+ * In particular, the cache does *not* hold the addresses of devices
+ * for which EEH is not enabled.
+ *
+ * (Implementation Note: The RB tree seems to be better/faster
+ * than any hash algo I could think of for this problem, even
+ * with the penalty of slow pointer chases for d-cache misses).
+ */
+struct pci_io_addr_range
+{
+ struct rb_node rb_node;
+ unsigned long addr_lo;
+ unsigned long addr_hi;
+ struct pci_dev *pcidev;
+ unsigned int flags;
+};
+
+static struct pci_io_addr_cache
+{
+ struct rb_root rb_root;
+ spinlock_t piar_lock;
+} pci_io_addr_cache_root;
+
+static inline struct pci_dev *__pci_get_device_by_addr(unsigned long addr)
+{
+ struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
+
+ while (n) {
+ struct pci_io_addr_range *piar;
+ piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+ if (addr < piar->addr_lo) {
+ n = n->rb_left;
+ } else {
+ if (addr > piar->addr_hi) {
+ n = n->rb_right;
+ } else {
+ pci_dev_get(piar->pcidev);
+ return piar->pcidev;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * pci_get_device_by_addr - Get device, given only address
+ * @addr: mmio (PIO) phys address or i/o port number
+ *
+ * Given an mmio phys address, or a port number, find a pci device
+ * that implements this address. Be sure to pci_dev_put the device
+ * when finished. I/O port numbers are assumed to be offset
+ * from zero (that is, they do *not* have pci_io_addr added in).
+ * It is safe to call this function within an interrupt.
+ */
+struct pci_dev *pci_get_device_by_addr(unsigned long addr)
+{
+ struct pci_dev *dev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ dev = __pci_get_device_by_addr(addr);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+ return dev;
+}
+
+#ifdef DEBUG
+/*
+ * Handy-dandy debug print routine, does nothing more
+ * than print out the contents of our addr cache.
+ */
+static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
+{
+ struct rb_node *n;
+ int cnt = 0;
+
+ n = rb_first(&cache->rb_root);
+ 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\n",
+ (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
+ piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
+ cnt++;
+ n = rb_next(n);
+ }
+}
+#endif
+
+/* Insert address range into the rb tree. */
+static struct pci_io_addr_range *
+pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+ unsigned long ahi, unsigned int flags)
+{
+ struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
+ struct rb_node *parent = NULL;
+ struct pci_io_addr_range *piar;
+
+ /* Walk tree, find a place to insert into tree */
+ while (*p) {
+ parent = *p;
+ piar = rb_entry(parent, struct pci_io_addr_range, rb_node);
+ if (ahi < piar->addr_lo) {
+ p = &parent->rb_left;
+ } else if (alo > piar->addr_hi) {
+ p = &parent->rb_right;
+ } else {
+ if (dev != piar->pcidev ||
+ alo != piar->addr_lo || ahi != piar->addr_hi) {
+ printk(KERN_WARNING "PIAR: overlapping address range\n");
+ }
+ return piar;
+ }
+ }
+ piar = (struct pci_io_addr_range *)kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+ if (!piar)
+ return NULL;
+
+ piar->addr_lo = alo;
+ piar->addr_hi = ahi;
+ piar->pcidev = dev;
+ piar->flags = flags;
+
+#ifdef DEBUG
+ printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
+ alo, ahi, pci_name (dev));
+#endif
+
+ rb_link_node(&piar->rb_node, parent, p);
+ rb_insert_color(&piar->rb_node, &pci_io_addr_cache_root.rb_root);
+
+ return piar;
+}
+
+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\n", pci_name(dev));
+ return;
+ }
+
+ /* Skip any devices for which EEH is not enabled. */
+ pdn = PCI_DN(dn);
+ 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), pdn->node->full_name);
+#endif
+ return;
+ }
+
+ /* The cache holds a reference to the device... */
+ pci_dev_get(dev);
+
+ /* Walk resources on this device, poke them into the tree */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ unsigned long start = pci_resource_start(dev,i);
+ unsigned long end = pci_resource_end(dev,i);
+ unsigned int flags = pci_resource_flags(dev,i);
+
+ /* We are interested only bus addresses, not dma or other stuff */
+ if (0 == (flags & (IORESOURCE_IO | IORESOURCE_MEM)))
+ continue;
+ if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
+ continue;
+ pci_addr_cache_insert(dev, start, end, flags);
+ inserted = 1;
+ }
+
+ /* If there was nothing to add, the cache has no reference... */
+ if (!inserted)
+ pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_insert_device - Add a device to the address cache
+ * @dev: PCI device whose I/O addresses we are interested in.
+ *
+ * In order to support the fast lookup of devices based on addresses,
+ * we maintain a cache of devices that can be quickly searched.
+ * This routine adds a device to that cache.
+ */
+void pci_addr_cache_insert_device(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ __pci_addr_cache_insert_device(dev);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+ struct rb_node *n;
+ int removed = 0;
+
+restart:
+ n = rb_first(&pci_io_addr_cache_root.rb_root);
+ while (n) {
+ struct pci_io_addr_range *piar;
+ piar = rb_entry(n, struct pci_io_addr_range, rb_node);
+
+ if (piar->pcidev == dev) {
+ rb_erase(n, &pci_io_addr_cache_root.rb_root);
+ removed = 1;
+ kfree(piar);
+ goto restart;
+ }
+ n = rb_next(n);
+ }
+
+ /* The cache no longer holds its reference to this device... */
+ if (removed)
+ pci_dev_put(dev);
+}
+
+/**
+ * pci_addr_cache_remove_device - remove pci device from addr cache
+ * @dev: device to remove
+ *
+ * Remove a device from the addr-cache tree.
+ * This is potentially expensive, since it will walk
+ * the tree multiple times (once per resource).
+ * But so what; device removal doesn't need to be that fast.
+ */
+void pci_addr_cache_remove_device(struct pci_dev *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
+ __pci_addr_cache_remove_device(dev);
+ spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
+}
+
+/**
+ * pci_addr_cache_build - Build a cache of I/O addresses
+ *
+ * Build a cache of pci i/o addresses. This cache will be used to
+ * find the pci device that corresponds to a given address.
+ * This routine scans all pci busses to build the cache.
+ * Must be run late in boot process, after the pci controllers
+ * have been scaned for devices (after all device resources are known).
+ */
+void __init pci_addr_cache_build(void)
+{
+ struct device_node *dn;
+ struct pci_dev *dev = NULL;
+
+ spin_lock_init(&pci_io_addr_cache_root.piar_lock);
+
+ while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ /* Ignore PCI bridges */
+ if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+ continue;
+
+ pci_addr_cache_insert_device(dev);
+
+ dn = pci_device_to_OF_node(dev);
+ pci_dev_get (dev); /* matching put is in eeh_remove_device() */
+ PCI_DN(dn)->pcidev = dev;
+ }
+
+#ifdef DEBUG
+ /* Verify tree built up above, echo back the list of addrs. */
+ pci_addr_cache_print(&pci_io_addr_cache_root);
+#endif
+}
+
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
new file mode 100644
index 000000000000..6373372932ba
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -0,0 +1,376 @@
+/*
+ * PCI Error Recovery Driver for RPA-compliant PPC64 platform.
+ * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org>
+ *
+ * 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 <linas@us.ibm.com>
+ *
+ */
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/pci.h>
+#include <asm/eeh.h>
+#include <asm/eeh_event.h>
+#include <asm/ppc-pci.h>
+#include <asm/pci-bridge.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+
+
+static inline const char * pcid_name (struct pci_dev *pdev)
+{
+ if (pdev->dev.driver)
+ return pdev->dev.driver->name;
+ return "";
+}
+
+#ifdef DEBUG
+static void print_device_node_tree (struct pci_dn *pdn, int dent)
+{
+ int i;
+ if (!pdn) return;
+ for (i=0;i<dent; i++)
+ printk(" ");
+ printk("dn=%s mode=%x \tcfg_addr=%x pe_addr=%x \tfull=%s\n",
+ pdn->node->name, pdn->eeh_mode, pdn->eeh_config_addr,
+ pdn->eeh_pe_config_addr, pdn->node->full_name);
+ dent += 3;
+ struct device_node *pc = pdn->node->child;
+ while (pc) {
+ print_device_node_tree(PCI_DN(pc), dent);
+ pc = pc->sibling;
+ }
+}
+#endif
+
+/**
+ * irq_in_use - return true if this irq is being used
+ */
+static int irq_in_use(unsigned int irq)
+{
+ int rc = 0;
+ unsigned long flags;
+ struct irq_desc *desc = irq_desc + irq;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ if (desc->action)
+ rc = 1;
+ spin_unlock_irqrestore(&desc->lock, flags);
+ return rc;
+}
+
+/* ------------------------------------------------------- */
+/** eeh_report_error - report an EEH error to each device,
+ * collect up and merge the device responses.
+ */
+
+static void eeh_report_error(struct pci_dev *dev, void *userdata)
+{
+ enum pci_ers_result rc, *res = userdata;
+ struct pci_driver *driver = dev->driver;
+
+ dev->error_state = pci_channel_io_frozen;
+
+ if (!driver)
+ return;
+
+ if (irq_in_use (dev->irq)) {
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+ disable_irq_nosync(dev->irq);
+ }
+ if (!driver->err_handler)
+ return;
+ if (!driver->err_handler->error_detected)
+ return;
+
+ rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);
+ if (*res == PCI_ERS_RESULT_NONE) *res = rc;
+ if (*res == PCI_ERS_RESULT_NEED_RESET) return;
+ if (*res == PCI_ERS_RESULT_DISCONNECT &&
+ rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
+}
+
+/** eeh_report_reset -- tell this device that the pci slot
+ * has been reset.
+ */
+
+static void eeh_report_reset(struct pci_dev *dev, void *userdata)
+{
+ struct pci_driver *driver = dev->driver;
+ struct device_node *dn = pci_device_to_OF_node(dev);
+
+ if (!driver)
+ return;
+
+ if ((PCI_DN(dn)->eeh_mode) & EEH_MODE_IRQ_DISABLED) {
+ PCI_DN(dn)->eeh_mode &= ~EEH_MODE_IRQ_DISABLED;
+ enable_irq(dev->irq);
+ }
+ if (!driver->err_handler)
+ return;
+ if (!driver->err_handler->slot_reset)
+ return;
+
+ driver->err_handler->slot_reset(dev);
+}
+
+static void eeh_report_resume(struct pci_dev *dev, void *userdata)
+{
+ struct pci_driver *driver = dev->driver;
+
+ dev->error_state = pci_channel_io_normal;
+
+ if (!driver)
+ return;
+ if (!driver->err_handler)
+ return;
+ if (!driver->err_handler->resume)
+ return;
+
+ driver->err_handler->resume(dev);
+}
+
+static void eeh_report_failure(struct pci_dev *dev, void *userdata)
+{
+ struct pci_driver *driver = dev->driver;
+
+ dev->error_state = pci_channel_io_perm_failure;
+
+ if (!driver)
+ return;
+
+ if (irq_in_use (dev->irq)) {
+ struct device_node *dn = pci_device_to_OF_node(dev);
+ PCI_DN(dn)->eeh_mode |= EEH_MODE_IRQ_DISABLED;
+ disable_irq_nosync(dev->irq);
+ }
+ if (!driver->err_handler)
+ return;
+ if (!driver->err_handler->error_detected)
+ return;
+ driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
+}
+
+/* ------------------------------------------------------- */
+/**
+ * handle_eeh_events -- reset a PCI device after hard lockup.
+ *
+ * pSeries systems will isolate a PCI slot if the PCI-Host
+ * bridge detects address or data parity errors, DMA's
+ * occuring to wild addresses (which usually happen due to
+ * bugs in device drivers or in PCI adapter firmware).
+ * Slot isolations also occur if #SERR, #PERR or other misc
+ * PCI-related errors are detected.
+ *
+ * Recovery process consists of unplugging the device driver
+ * (which generated hotplug events to userspace), then issuing
+ * a PCI #RST to the device, then reconfiguring the PCI config
+ * space for all bridges & devices under this slot, and then
+ * finally restarting the device drivers (which cause a second
+ * set of hotplug events to go out to userspace).
+ */
+
+/**
+ * eeh_reset_device() -- perform actual reset of a pci slot
+ * Args: bus: pointer to the pci bus structure corresponding
+ * to the isolated slot. A non-null value will
+ * cause all devices under the bus to be removed
+ * and then re-added.
+ * pe_dn: pointer to a "Partionable Endpoint" device node.
+ * This is the top-level structure on which pci
+ * bus resets can be performed.
+ */
+
+static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
+{
+ int rc;
+ if (bus)
+ pcibios_remove_pci_devices(bus);
+
+ /* Reset the pci controller. (Asserts RST#; resets config space).
+ * Reconfigure bridges and devices. Don't try to bring the system
+ * up if the reset failed for some reason. */
+ rc = rtas_set_slot_reset(pe_dn);
+ if (rc)
+ return rc;
+
+ /* New-style config addrs might be shared across multiple devices,
+ * Walk over all functions on this device */
+ if (pe_dn->eeh_pe_config_addr) {
+ struct device_node *pe = pe_dn->node;
+ pe = pe->parent->child;
+ while (pe) {
+ struct pci_dn *ppe = PCI_DN(pe);
+ if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) {
+ rtas_configure_bridge(ppe);
+ eeh_restore_bars(ppe);
+ }
+ pe = pe->sibling;
+ }
+ } else {
+ rtas_configure_bridge(pe_dn);
+ eeh_restore_bars(pe_dn);
+ }
+
+ /* Give the system 5 seconds to finish running the user-space
+ * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,
+ * this is a hack, but if we don't do this, and try to bring
+ * the device up before the scripts have taken it down,
+ * potentially weird things happen.
+ */
+ if (bus) {
+ ssleep (5);
+ pcibios_add_pci_devices(bus);
+ }
+
+ return 0;
+}
+
+/* The longest amount of time to wait for a pci device
+ * to come back on line, in seconds.
+ */
+#define MAX_WAIT_FOR_RECOVERY 15
+
+void handle_eeh_events (struct eeh_event *event)
+{
+ struct device_node *frozen_dn;
+ struct pci_dn *frozen_pdn;
+ struct pci_bus *frozen_bus;
+ int rc = 0;
+ enum pci_ers_result result = PCI_ERS_RESULT_NONE;
+
+ frozen_dn = find_device_pe(event->dn);
+ frozen_bus = pcibios_find_pci_bus(frozen_dn);
+
+ if (!frozen_dn) {
+ printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
+ pci_name(event->dev));
+ return;
+ }
+
+ /* There are two different styles for coming up with the PE.
+ * In the old style, it was the highest EEH-capable device
+ * which was always an EADS pci bridge. In the new style,
+ * there might not be any EADS bridges, and even when there are,
+ * the firmware marks them as "EEH incapable". So another
+ * two-step is needed to find the pci bus.. */
+ if (!frozen_bus)
+ frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);
+
+ if (!frozen_bus) {
+ printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
+ frozen_dn->full_name);
+ return;
+ }
+
+#if 0
+ /* We may get "permanent failure" messages on empty slots.
+ * These are false alarms. Empty slots have no child dn. */
+ if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL))
+ return;
+#endif
+
+ frozen_pdn = PCI_DN(frozen_dn);
+ frozen_pdn->eeh_freeze_count++;
+
+ if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES)
+ goto hard_fail;
+
+ /* If the reset state is a '5' and the time to reset is 0 (infinity)
+ * or is more then 15 seconds, then mark this as a permanent failure.
+ */
+ if ((event->state == pci_channel_io_perm_failure) &&
+ ((event->time_unavail <= 0) ||
+ (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000)))
+ goto hard_fail;
+
+ eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
+ printk(KERN_WARNING
+ "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
+ frozen_pdn->eeh_freeze_count,
+ pci_name (frozen_pdn->pcidev),
+ pcid_name(frozen_pdn->pcidev));
+
+ /* Walk the various device drivers attached to this slot through
+ * a reset sequence, giving each an opportunity to do what it needs
+ * to accomplish the reset. Each child gets a report of the
+ * status ... if any child can't handle the reset, then the entire
+ * slot is dlpar removed and added.
+ */
+ pci_walk_bus(frozen_bus, eeh_report_error, &result);
+
+ /* If all device drivers were EEH-unaware, then shut
+ * down all of the device drivers, and hope they
+ * go down willingly, without panicing the system.
+ */
+ if (result == PCI_ERS_RESULT_NONE) {
+ rc = eeh_reset_device(frozen_pdn, frozen_bus);
+ if (rc)
+ goto hard_fail;
+ }
+
+ /* If any device called out for a reset, then reset the slot */
+ if (result == PCI_ERS_RESULT_NEED_RESET) {
+ rc = eeh_reset_device(frozen_pdn, NULL);
+ if (rc)
+ goto hard_fail;
+ pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+ }
+
+ /* If all devices reported they can proceed, the re-enable PIO */
+ if (result == PCI_ERS_RESULT_CAN_RECOVER) {
+ /* XXX Not supported; we brute-force reset the device */
+ rc = eeh_reset_device(frozen_pdn, NULL);
+ if (rc)
+ goto hard_fail;
+ pci_walk_bus(frozen_bus, eeh_report_reset, 0);
+ }
+
+ /* Tell all device drivers that they can resume operations */
+ pci_walk_bus(frozen_bus, eeh_report_resume, 0);
+
+ return;
+
+hard_fail:
+ /*
+ * About 90% of all real-life EEH failures in the field
+ * are due to poorly seated PCI cards. Only 10% or so are
+ * due to actual, failed cards.
+ */
+ printk(KERN_ERR
+ "EEH: PCI device %s - %s has failed %d times \n"
+ "and has been permanently disabled. Please try reseating\n"
+ "this device or replacing it.\n",
+ pci_name (frozen_pdn->pcidev),
+ pcid_name(frozen_pdn->pcidev),
+ frozen_pdn->eeh_freeze_count);
+
+ eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
+
+ /* Notify all devices that they're about to go down. */
+ pci_walk_bus(frozen_bus, eeh_report_failure, 0);
+
+ /* Shut down the device drivers for good. */
+ pcibios_remove_pci_devices(frozen_bus);
+}
+
+/* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 92497333c2b6..9a9961f27480 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/eeh_event.h>
+#include <asm/ppc-pci.h>
/** Overview:
* EEH error states may be detected within exception handlers;
@@ -37,31 +38,6 @@ static void eeh_thread_launcher(void *);
DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
/**
- * eeh_panic - call panic() for an eeh event that cannot be handled.
- * The philosophy of this routine is that it is better to panic and
- * halt the OS than it is to risk possible data corruption by
- * oblivious device drivers that don't know better.
- *
- * @dev pci device that had an eeh event
- * @reset_state current reset state of the device slot
- */
-static void eeh_panic(struct pci_dev *dev, int reset_state)
-{
- /*
- * Since the panic_on_oops sysctl is used to halt the system
- * in light of potential corruption, we can use it here.
- */
- if (panic_on_oops) {
- panic("EEH: MMIO failure (%d) on device:%s\n", reset_state,
- pci_name(dev));
- }
- else {
- printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n",
- reset_state, pci_name(dev));
- }
-}
-
-/**
* eeh_event_handler - dispatch EEH events. The detection of a frozen
* slot can occur inside an interrupt, where it can be hard to do
* anything about it. The goal of this routine is to pull these
@@ -82,10 +58,16 @@ static int eeh_event_handler(void * dummy)
spin_lock_irqsave(&eeh_eventlist_lock, flags);
event = NULL;
+
+ /* Unqueue the event, get ready to process. */
if (!list_empty(&eeh_eventlist)) {
event = list_entry(eeh_eventlist.next, struct eeh_event, list);
list_del(&event->list);
}
+
+ if (event)
+ eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+
spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
if (event == NULL)
break;
@@ -93,8 +75,11 @@ static int eeh_event_handler(void * dummy)
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
pci_name(event->dev));
- eeh_panic (event->dev, event->state);
+ handle_eeh_events(event);
+
+ eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
+ pci_dev_put(event->dev);
kfree(event);
}
@@ -122,7 +107,7 @@ static void eeh_thread_launcher(void *dummy)
*/
int eeh_send_failure_event (struct device_node *dn,
struct pci_dev *dev,
- int state,
+ enum pci_channel_state state,
int time_unavail)
{
unsigned long flags;
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c
index 4d584172055a..22bfb5c89db9 100644
--- a/arch/powerpc/platforms/pseries/hvcserver.c
+++ b/arch/powerpc/platforms/pseries/hvcserver.c
@@ -40,7 +40,7 @@ MODULE_VERSION(HVCS_ARCH_VERSION);
* functions aren't performance sensitive, so this conversion isn't an
* issue.
*/
-int hvcs_convert(long to_convert)
+static int hvcs_convert(long to_convert)
{
switch (to_convert) {
case H_Success:
@@ -91,7 +91,7 @@ int hvcs_free_partner_info(struct list_head *head)
EXPORT_SYMBOL(hvcs_free_partner_info);
/* Helper function for hvcs_get_partner_info */
-int hvcs_next_partner(uint32_t unit_address,
+static int hvcs_next_partner(uint32_t unit_address,
unsigned long last_p_partition_ID,
unsigned long last_p_unit_address, unsigned long *pi_buff)
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 2043659ea7b1..48cfbfc43f99 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -51,8 +51,6 @@
#define DBG(fmt...)
-extern int is_python(struct device_node *);
-
static void tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction)
@@ -436,7 +434,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
return;
}
- ppci = pdn->data;
+ ppci = PCI_DN(pdn);
if (!ppci->iommu_table) {
/* Bussubno hasn't been copied yet.
* Do it now because iommu_table_setparms_lpar needs it.
@@ -483,10 +481,10 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
* an already allocated iommu table is found and use that.
*/
- while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
+ while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL)
dn = dn->parent;
- if (dn && dn->data) {
+ if (dn && PCI_DN(dn)) {
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, pci_name(dev));
@@ -497,7 +495,7 @@ 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;
+ struct pci_dn *pci = PCI_DN(np);
switch (action) {
case PSERIES_RECONFIG_REMOVE:
@@ -533,7 +531,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
*/
dn = pci_device_to_OF_node(dev);
- for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+ for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
pdn = pdn->parent) {
dma_window = (unsigned int *)
get_property(pdn, "ibm,dma-window", NULL);
@@ -552,7 +550,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
DBG("Found DMA window, allocating table\n");
}
- pci = pdn->data;
+ pci = PCI_DN(pdn);
if (!pci->iommu_table) {
/* iommu_table_setparms_lpar needs bussubno. */
pci->bussubno = pci->phb->bus->number;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index cf1bc11b3346..8952528d31ac 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -24,6 +24,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
+#include <linux/console.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/page.h>
@@ -60,7 +61,7 @@ extern void pSeries_find_serial_port(void);
int vtermno; /* virtual terminal# for udbg */
#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-static void udbg_hvsi_putc(unsigned char c)
+static void udbg_hvsi_putc(char c)
{
/* packet's seqno isn't used anyways */
uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
@@ -111,7 +112,7 @@ static int udbg_hvsi_getc_poll(void)
return ch;
}
-static unsigned char udbg_hvsi_getc(void)
+static int udbg_hvsi_getc(void)
{
int ch;
for (;;) {
@@ -127,7 +128,7 @@ static unsigned char udbg_hvsi_getc(void)
}
}
-static void udbg_putcLP(unsigned char c)
+static void udbg_putcLP(char c)
{
char buf[16];
unsigned long rc;
@@ -172,7 +173,7 @@ static int udbg_getc_pollLP(void)
return ch;
}
-static unsigned char udbg_getcLP(void)
+static int udbg_getcLP(void)
{
int ch;
for (;;) {
@@ -191,7 +192,7 @@ static unsigned char udbg_getcLP(void)
/* call this from early_init() for a working debug console on
* vterm capable LPAR machines
*/
-void udbg_init_debug_lpar(void)
+void __init udbg_init_debug_lpar(void)
{
vtermno = 0;
udbg_putc = udbg_putcLP;
@@ -200,73 +201,64 @@ void udbg_init_debug_lpar(void)
}
/* returns 0 if couldn't find or use /chosen/stdout as console */
-int find_udbg_vterm(void)
+void __init find_udbg_vterm(void)
{
struct device_node *stdout_node;
u32 *termno;
char *name;
- int found = 0;
+ int add_console;
/* find the boot console from /chosen/stdout */
if (!of_chosen)
- return 0;
+ return;
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
if (name == NULL)
- return 0;
+ return;
stdout_node = of_find_node_by_path(name);
if (!stdout_node)
- return 0;
-
- /* now we have the stdout node; figure out what type of device it is. */
+ return;
name = (char *)get_property(stdout_node, "name", NULL);
if (!name) {
printk(KERN_WARNING "stdout node missing 'name' property!\n");
goto out;
}
+ /* The user has requested a console so this is already set up. */
+ add_console = !strstr(cmd_line, "console=");
- if (strncmp(name, "vty", 3) == 0) {
- if (device_is_compatible(stdout_node, "hvterm1")) {
- termno = (u32 *)get_property(stdout_node, "reg", NULL);
- if (termno) {
- vtermno = termno[0];
- 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];
- udbg_putc = udbg_hvsi_putc;
- udbg_getc = udbg_hvsi_getc;
- udbg_getc_poll = udbg_hvsi_getc_poll;
- found = 1;
- }
- }
- } else if (strncmp(name, "serial", 6)) {
- /* XXX fix ISA serial console */
- printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
- "can't print udbg messages\n",
- stdout_node->full_name);
- } else {
- printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
- stdout_node->full_name);
+ /* Check if it's a virtual terminal */
+ if (strncmp(name, "vty", 3) != 0)
+ goto out;
+ termno = (u32 *)get_property(stdout_node, "reg", NULL);
+ if (termno == NULL)
+ goto out;
+ vtermno = termno[0];
+
+ if (device_is_compatible(stdout_node, "hvterm1")) {
+ udbg_putc = udbg_putcLP;
+ udbg_getc = udbg_getcLP;
+ udbg_getc_poll = udbg_getc_pollLP;
+ if (add_console)
+ add_preferred_console("hvc", termno[0] & 0xff, NULL);
+ } else if (device_is_compatible(stdout_node, "hvterm-protocol")) {
+ vtermno = termno[0];
+ udbg_putc = udbg_hvsi_putc;
+ udbg_getc = udbg_hvsi_getc;
+ udbg_getc_poll = udbg_hvsi_getc_poll;
+ if (add_console)
+ add_preferred_console("hvsi", termno[0] & 0xff, NULL);
}
-
out:
of_node_put(stdout_node);
- return found;
}
void vpa_init(int cpu)
{
int hwcpu = get_hard_smp_processor_id(cpu);
- unsigned long vpa = __pa(&paca[cpu].lppaca);
+ unsigned long vpa = __pa(&lppaca[cpu]);
long ret;
if (cpu_has_feature(CPU_FTR_ALTIVEC))
- paca[cpu].lppaca.vmxregs_in_use = 1;
+ lppaca[cpu].vmxregs_in_use = 1;
ret = register_vpa(hwcpu, vpa);
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
new file mode 100644
index 000000000000..21934784f936
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -0,0 +1,174 @@
+/*
+ * PCI Dynamic LPAR, PCI Hot Plug and PCI EEH recovery code
+ * for RPA-compliant PPC64 platform.
+ * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com>
+ * Copyright (C) 2005 International Business Machines
+ *
+ * Updates, 2005, John Rose <johnrose@austin.ibm.com>
+ * Updates, 2005, Linas Vepstas <linas@austin.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.
+ */
+
+#include <linux/pci.h>
+#include <asm/pci-bridge.h>
+
+static struct pci_bus *
+find_bus_among_children(struct pci_bus *bus,
+ struct device_node *dn)
+{
+ 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;
+
+ list_for_each(tmp, &bus->children) {
+ child = find_bus_among_children(pci_bus_b(tmp), dn);
+ if (child)
+ break;
+ };
+ return child;
+}
+
+struct pci_bus *
+pcibios_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);
+}
+
+/**
+ * pcibios_remove_pci_devices - remove all devices under this bus
+ *
+ * Remove all of the PCI devices under this bus both from the
+ * linux pci device tree, and from the powerpc EEH address cache.
+ */
+void
+pcibios_remove_pci_devices(struct pci_bus *bus)
+{
+ struct pci_dev *dev, *tmp;
+
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+ eeh_remove_bus_device(dev);
+ pci_remove_bus_device(dev);
+ }
+}
+
+/* Must be called before pci_bus_add_devices */
+void
+pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ /*
+ * Skip already-present devices (which are on the
+ * global device list.)
+ */
+ if (list_empty(&dev->global_list)) {
+ int i;
+
+ /* Need to setup IOMMU tables */
+ ppc_md.iommu_dev_setup(dev);
+
+ if(fix_bus)
+ pcibios_fixup_device_resources(dev, bus);
+ pci_read_irq_line(dev);
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if (r->parent || !r->start || !r->flags)
+ continue;
+ pci_claim_resource(dev, i);
+ }
+ }
+ }
+}
+
+static int
+pcibios_pci_config_bridge(struct pci_dev *dev)
+{
+ u8 sec_busno;
+ struct pci_bus *child_bus;
+ struct pci_dev *child_dev;
+
+ /* Get busno of downstream bus */
+ pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
+
+ /* Add to children of PCI bridge dev->bus */
+ child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
+ if (!child_bus) {
+ printk (KERN_ERR "%s: could not add second bus\n", __FUNCTION__);
+ return -EIO;
+ }
+ sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
+
+ pci_scan_child_bus(child_bus);
+
+ list_for_each_entry(child_dev, &child_bus->devices, bus_list) {
+ eeh_add_device_late(child_dev);
+ }
+
+ /* Fixup new pci devices without touching bus struct */
+ pcibios_fixup_new_pci_devices(child_bus, 0);
+
+ /* Make the discovered devices available */
+ pci_bus_add_devices(child_bus);
+ return 0;
+}
+
+/**
+ * pcibios_add_pci_devices - adds new pci devices to bus
+ *
+ * This routine will find and fixup new pci devices under
+ * the indicated bus. This routine presumes that there
+ * might already be some devices under this bridge, so
+ * it carefully tries to add only new devices. (And that
+ * is how this routine differs from other, similar pcibios
+ * routines.)
+ */
+void
+pcibios_add_pci_devices(struct pci_bus * bus)
+{
+ int slotno, num;
+ struct pci_dev *dev;
+ struct device_node *dn = pci_bus_to_OF_node(bus);
+
+ eeh_add_device_tree_early(dn);
+
+ /* pci_scan_slot should find all children */
+ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+ num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+ if (num) {
+ pcibios_fixup_new_pci_devices(bus, 1);
+ pci_bus_add_devices(bus);
+ }
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late (dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ pcibios_pci_config_bridge(dev);
+ }
+}
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index fbd214d68b07..b046bcf7443d 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -49,14 +49,14 @@
#include <asm/machdep.h>
#include <asm/rtas.h>
#include <asm/udbg.h>
+#include <asm/firmware.h>
+
+#include "ras.h"
static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
static DEFINE_SPINLOCK(ras_log_buf_lock);
-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;
+char mce_data_buf[RTAS_ERROR_LOG_MAX];
static int ras_get_sensor_state_token;
static int ras_check_exception_token;
@@ -280,7 +280,7 @@ static void fwnmi_release_errinfo(void)
printk("FWNMI: nmi-interlock failed: %d\n", ret);
}
-void pSeries_system_reset_exception(struct pt_regs *regs)
+int pSeries_system_reset_exception(struct pt_regs *regs)
{
if (fwnmi_active) {
struct rtas_error_log *errhdr = fwnmi_get_errinfo(regs);
@@ -289,6 +289,7 @@ void pSeries_system_reset_exception(struct pt_regs *regs)
}
fwnmi_release_errinfo();
}
+ return 0; /* need to perform reset */
}
/*
diff --git a/arch/powerpc/platforms/pseries/ras.h b/arch/powerpc/platforms/pseries/ras.h
new file mode 100644
index 000000000000..0e66b0da55e2
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/ras.h
@@ -0,0 +1,9 @@
+#ifndef _PSERIES_RAS_H
+#define _PSERIES_RAS_H
+
+struct pt_regs;
+
+extern int pSeries_system_reset_exception(struct pt_regs *regs);
+extern int pSeries_machine_check_exception(struct pt_regs *regs);
+
+#endif /* _PSERIES_RAS_H */
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index d8864164dbe8..86cfa6ecdcf3 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -350,6 +350,100 @@ static int do_remove_node(char *buf)
return rv;
}
+static char *parse_node(char *buf, size_t bufsize, struct device_node **npp)
+{
+ char *handle_str;
+ phandle handle;
+ *npp = NULL;
+
+ handle_str = buf;
+
+ buf = strchr(buf, ' ');
+ if (!buf)
+ return NULL;
+ *buf = '\0';
+ buf++;
+
+ handle = simple_strtoul(handle_str, NULL, 10);
+
+ *npp = of_find_node_by_phandle(handle);
+ return buf;
+}
+
+static int do_add_property(char *buf, size_t bufsize)
+{
+ struct property *prop = NULL;
+ struct device_node *np;
+ unsigned char *value;
+ char *name, *end;
+ int length;
+ end = buf + bufsize;
+ buf = parse_node(buf, bufsize, &np);
+
+ if (!np)
+ return -ENODEV;
+
+ if (parse_next_property(buf, end, &name, &length, &value) == NULL)
+ return -EINVAL;
+
+ prop = new_property(name, length, value, NULL);
+ if (!prop)
+ return -ENOMEM;
+
+ prom_add_property(np, prop);
+
+ return 0;
+}
+
+static int do_remove_property(char *buf, size_t bufsize)
+{
+ struct device_node *np;
+ char *tmp;
+ struct property *prop;
+ buf = parse_node(buf, bufsize, &np);
+
+ if (!np)
+ return -ENODEV;
+
+ tmp = strchr(buf,' ');
+ if (tmp)
+ *tmp = '\0';
+
+ if (strlen(buf) == 0)
+ return -EINVAL;
+
+ prop = of_find_property(np, buf, NULL);
+
+ return prom_remove_property(np, prop);
+}
+
+static int do_update_property(char *buf, size_t bufsize)
+{
+ struct device_node *np;
+ unsigned char *value;
+ char *name, *end;
+ int length;
+ struct property *newprop, *oldprop;
+ buf = parse_node(buf, bufsize, &np);
+ end = buf + bufsize;
+
+ if (!np)
+ return -ENODEV;
+
+ if (parse_next_property(buf, end, &name, &length, &value) == NULL)
+ return -EINVAL;
+
+ newprop = new_property(name, length, value, NULL);
+ if (!newprop)
+ return -ENOMEM;
+
+ oldprop = of_find_property(np, name,NULL);
+ if (!oldprop)
+ return -ENODEV;
+
+ return prom_update_property(np, newprop, oldprop);
+}
+
/**
* ofdt_write - perform operations on the Open Firmware device tree
*
@@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun
rv = do_add_node(tmp, count - (tmp - kbuf));
else if (!strcmp(kbuf, "remove_node"))
rv = do_remove_node(tmp);
+ else if (!strcmp(kbuf, "add_property"))
+ rv = do_add_property(tmp, count - (tmp - kbuf));
+ else if (!strcmp(kbuf, "remove_property"))
+ rv = do_remove_property(tmp, count - (tmp - kbuf));
+ else if (!strcmp(kbuf, "update_property"))
+ rv = do_update_property(tmp, count - (tmp - kbuf));
else
rv = -EINVAL;
out:
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 2edc947f7c44..50643496eb63 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -192,7 +192,7 @@ struct file_operations scanlog_fops = {
.release = scanlog_release,
};
-int __init scanlog_init(void)
+static int __init scanlog_init(void)
{
struct proc_dir_entry *ent;
@@ -222,7 +222,7 @@ int __init scanlog_init(void)
return 0;
}
-void __exit scanlog_cleanup(void)
+static void __exit scanlog_cleanup(void)
{
if (proc_ppc64_scan_log_dump) {
kfree(proc_ppc64_scan_log_dump->data);
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 4a465f067ede..da6cebaf72cd 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -56,6 +56,7 @@
#include <asm/dma.h>
#include <asm/machdep.h>
#include <asm/irq.h>
+#include <asm/kexec.h>
#include <asm/time.h>
#include <asm/nvram.h>
#include "xics.h"
@@ -68,6 +69,7 @@
#include <asm/smp.h>
#include "plpar_wrappers.h"
+#include "ras.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -76,22 +78,15 @@
#endif
extern void find_udbg_vterm(void);
-extern void system_reset_fwnmi(void); /* from head.S */
-extern void machine_check_fwnmi(void); /* from head.S */
-extern void generic_find_legacy_serial_ports(u64 *physport,
- unsigned int *default_speed);
int fwnmi_active; /* TRUE if an FWNMI handler is present */
-extern void pSeries_system_reset_exception(struct pt_regs *regs);
-extern int pSeries_machine_check_exception(struct pt_regs *regs);
-
static void pseries_shared_idle(void);
static void pseries_dedicated_idle(void);
struct mpic *pSeries_mpic;
-void pSeries_show_cpuinfo(struct seq_file *m)
+static void pSeries_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
const char *model = "";
@@ -105,18 +100,22 @@ void pSeries_show_cpuinfo(struct seq_file *m)
/* Initialize firmware assisted non-maskable interrupts if
* the firmware supports this feature.
- *
*/
static void __init fwnmi_init(void)
{
- int ret;
+ unsigned long system_reset_addr, machine_check_addr;
+
int ibm_nmi_register = rtas_token("ibm,nmi-register");
if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
return;
- ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
- __pa((unsigned long)system_reset_fwnmi),
- __pa((unsigned long)machine_check_fwnmi));
- if (ret == 0)
+
+ /* If the kernel's not linked at zero we point the firmware at low
+ * addresses anyway, and use a trampoline to get to the real code. */
+ system_reset_addr = __pa(system_reset_fwnmi) - PHYSICAL_START;
+ machine_check_addr = __pa(machine_check_fwnmi) - PHYSICAL_START;
+
+ if (0 == rtas_call(ibm_nmi_register, 2, 1, NULL, system_reset_addr,
+ machine_check_addr))
fwnmi_active = 1;
}
@@ -191,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void)
/* instruct hypervisor to maintain PMCs */
if (firmware_has_feature(FW_FEATURE_SPLPAR))
- get_paca()->lppaca.pmcregs_in_use = 1;
+ get_lppaca()->pmcregs_in_use = 1;
}
static void __init pSeries_setup_arch(void)
@@ -235,7 +234,7 @@ static void __init pSeries_setup_arch(void)
/* Choose an idle loop */
if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
vpa_init(boot_cpuid);
- if (get_paca()->lppaca.shared_proc) {
+ if (get_lppaca()->shared_proc) {
printk(KERN_INFO "Using shared processor idle loop\n");
ppc_md.idle_loop = pseries_shared_idle;
} else {
@@ -323,15 +322,18 @@ static void __init pSeries_discover_pic(void)
ppc64_interrupt_controller = IC_INVALID;
for (np = NULL; (np = of_find_node_by_name(np, "interrupt-controller"));) {
typep = (char *)get_property(np, "compatible", NULL);
- if (strstr(typep, "open-pic"))
+ if (strstr(typep, "open-pic")) {
ppc64_interrupt_controller = IC_OPEN_PIC;
- else if (strstr(typep, "ppc-xicp"))
+ break;
+ } else if (strstr(typep, "ppc-xicp")) {
ppc64_interrupt_controller = IC_PPC_XIC;
- else
- printk("pSeries_discover_pic: failed to recognize"
- " interrupt-controller\n");
- break;
+ break;
+ }
}
+ if (ppc64_interrupt_controller == IC_INVALID)
+ printk("pSeries_discover_pic: failed to recognize"
+ " interrupt-controller\n");
+
}
static void pSeries_mach_cpu_die(void)
@@ -365,10 +367,7 @@ static int pseries_set_xdabr(unsigned long dabr)
*/
static void __init pSeries_init_early(void)
{
- void *comport;
int iommu_off = 0;
- unsigned int default_speed;
- u64 physport;
DBG(" -> pSeries_init_early()\n");
@@ -382,17 +381,8 @@ static void __init pSeries_init_early(void)
get_property(of_chosen, "linux,iommu-off", NULL));
}
- generic_find_legacy_serial_ports(&physport, &default_speed);
-
if (platform_is_lpar())
find_udbg_vterm();
- else if (physport) {
- /* Map the uart for udbg. */
- comport = (void *)ioremap(physport, 16);
- udbg_init_uart(comport, default_speed);
-
- DBG("Hello World !\n");
- }
if (firmware_has_feature(FW_FEATURE_DABR))
ppc_md.set_dabr = pseries_set_dabr;
@@ -454,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay);
static inline void dedicated_idle_sleep(unsigned int cpu)
{
- struct paca_struct *ppaca = &paca[cpu ^ 1];
+ struct lppaca *plppaca = &lppaca[cpu ^ 1];
/* Only sleep if the other thread is not idle */
- if (!(ppaca->lppaca.idle)) {
+ if (!(plppaca->idle)) {
local_irq_disable();
/*
@@ -490,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu)
static void pseries_dedicated_idle(void)
{
- struct paca_struct *lpaca = get_paca();
unsigned int cpu = smp_processor_id();
unsigned long start_snooze;
unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
@@ -501,7 +490,7 @@ static void pseries_dedicated_idle(void)
* Indicate to the HV that we are idle. Now would be
* a good time to find other work to dispatch.
*/
- lpaca->lppaca.idle = 1;
+ get_lppaca()->idle = 1;
if (!need_resched()) {
start_snooze = get_tb() +
@@ -528,7 +517,7 @@ static void pseries_dedicated_idle(void)
HMT_medium();
}
- lpaca->lppaca.idle = 0;
+ get_lppaca()->idle = 0;
ppc64_runlatch_on();
preempt_enable_no_resched();
@@ -542,7 +531,6 @@ static void pseries_dedicated_idle(void)
static void pseries_shared_idle(void)
{
- struct paca_struct *lpaca = get_paca();
unsigned int cpu = smp_processor_id();
while (1) {
@@ -550,7 +538,7 @@ static void pseries_shared_idle(void)
* Indicate to the HV that we are idle. Now would be
* a good time to find other work to dispatch.
*/
- lpaca->lppaca.idle = 1;
+ get_lppaca()->idle = 1;
while (!need_resched() && !cpu_is_offline(cpu)) {
local_irq_disable();
@@ -574,7 +562,7 @@ static void pseries_shared_idle(void)
HMT_medium();
}
- lpaca->lppaca.idle = 0;
+ get_lppaca()->idle = 0;
ppc64_runlatch_on();
preempt_enable_no_resched();
@@ -598,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
{
/* Don't risk a hypervisor call if we're crashing */
if (!crash_shutdown) {
- unsigned long vpa = __pa(&get_paca()->lppaca);
+ unsigned long vpa = __pa(get_lppaca());
if (unregister_vpa(hard_smp_processor_id(), vpa)) {
printk("VPA deregistration of cpu %u (hw_cpu_id %d) "
@@ -638,5 +626,8 @@ struct machdep_calls __initdata pSeries_md = {
.machine_check_exception = pSeries_machine_check_exception,
#ifdef CONFIG_KEXEC
.kexec_cpu_down = pseries_kexec_cpu_down,
+ .machine_kexec = default_machine_kexec,
+ .machine_kexec_prepare = default_machine_kexec_prepare,
+ .machine_crash_shutdown = default_machine_crash_shutdown,
#endif
};
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 25181c594d73..8e6b1ed1396e 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -93,7 +93,7 @@ static int query_cpu_stopped(unsigned int pcpu)
return cpu_status;
}
-int pSeries_cpu_disable(void)
+static int pSeries_cpu_disable(void)
{
int cpu = smp_processor_id();
@@ -109,7 +109,7 @@ int pSeries_cpu_disable(void)
return 0;
}
-void pSeries_cpu_die(unsigned int cpu)
+static void pSeries_cpu_die(unsigned int cpu)
{
int tries;
int cpu_status;
@@ -282,7 +282,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
pcpu = get_hard_smp_processor_id(lcpu);
/* Fixup atomic count: it exited inside IRQ handler. */
- paca[lcpu].__current->thread_info->preempt_count = 0;
+ task_thread_info(paca[lcpu].__current)->preempt_count = 0;
/*
* If the RTAS start-cpu token does not exist then presume the
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 0377decc0719..fd823c7c9ac8 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -381,7 +381,7 @@ int xics_get_irq(struct pt_regs *regs)
#ifdef CONFIG_SMP
-irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
{
int cpu = smp_processor_id();
@@ -407,7 +407,7 @@ irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
smp_message_recv(PPC_MSG_MIGRATE_TASK, regs);
}
#endif
-#ifdef CONFIG_DEBUGGER
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK,
&xics_ipi_message[cpu].value)) {
mb();
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 6b7efcfc352a..4c2b356774ea 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -4,5 +4,7 @@ obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_MPC106) += grackle.o
obj-$(CONFIG_BOOKE) += dcr.o
obj-$(CONFIG_40x) += dcr.o
-obj-$(CONFIG_U3_DART) += u3_iommu.o
+obj-$(CONFIG_U3_DART) += dart_iommu.o
obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
+obj-$(CONFIG_PPC_83xx) += ipic.o
+obj-$(CONFIG_FSL_SOC) += fsl_soc.o
diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h
index 33ed9ed7fc1e..c2d05763ccbe 100644
--- a/arch/powerpc/sysdev/dart.h
+++ b/arch/powerpc/sysdev/dart.h
@@ -20,29 +20,44 @@
#define _POWERPC_SYSDEV_DART_H
-/* physical base of DART registers */
-#define DART_BASE 0xf8033000UL
-
/* Offset from base to control register */
-#define DARTCNTL 0
+#define DART_CNTL 0
+
/* Offset from base to exception register */
-#define DARTEXCP 0x10
+#define DART_EXCP_U3 0x10
/* Offset from base to TLB tag registers */
-#define DARTTAG 0x1000
+#define DART_TAGS_U3 0x1000
+/* U4 registers */
+#define DART_BASE_U4 0x10
+#define DART_SIZE_U4 0x20
+#define DART_EXCP_U4 0x30
+#define DART_TAGS_U4 0x1000
/* Control Register fields */
-/* base address of table (pfn) */
-#define DARTCNTL_BASE_MASK 0xfffff
-#define DARTCNTL_BASE_SHIFT 12
+/* U3 registers */
+#define DART_CNTL_U3_BASE_MASK 0xfffff
+#define DART_CNTL_U3_BASE_SHIFT 12
+#define DART_CNTL_U3_FLUSHTLB 0x400
+#define DART_CNTL_U3_ENABLE 0x200
+#define DART_CNTL_U3_SIZE_MASK 0x1ff
+#define DART_CNTL_U3_SIZE_SHIFT 0
+
+/* U4 registers */
+#define DART_BASE_U4_BASE_MASK 0xffffff
+#define DART_BASE_U4_BASE_SHIFT 0
+#define DART_CNTL_U4_FLUSHTLB 0x20000000
+#define DART_CNTL_U4_ENABLE 0x80000000
+#define DART_SIZE_U4_SIZE_MASK 0x1fff
+#define DART_SIZE_U4_SIZE_SHIFT 0
+
+#define DART_REG(r) (dart + ((r) >> 2))
+#define DART_IN(r) (in_be32(DART_REG(r)))
+#define DART_OUT(r,v) (out_be32(DART_REG(r), (v)))
-#define DARTCNTL_FLUSHTLB 0x400
-#define DARTCNTL_ENABLE 0x200
/* size of table in pages */
-#define DARTCNTL_SIZE_MASK 0x1ff
-#define DARTCNTL_SIZE_SHIFT 0
/* DART table fields */
diff --git a/arch/powerpc/sysdev/u3_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 5c1a26a6d00c..977de9db8754 100644
--- a/arch/powerpc/sysdev/u3_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -1,25 +1,27 @@
/*
- * arch/powerpc/sysdev/u3_iommu.c
+ * arch/powerpc/sysdev/dart_iommu.c
*
* Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>,
+ * IBM Corporation
*
* Based on pSeries_iommu.c:
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
* Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
*
- * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
+ * Dynamic DMA mapping support, Apple U3, U4 & IBM CPC925 "DART" iommu.
+ *
*
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the 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
@@ -57,21 +59,22 @@ static unsigned long dart_tablesize;
static u32 *dart_vbase;
/* Mapped base address for the dart */
-static unsigned int *dart;
+static unsigned int *__iomem dart;
/* Dummy val that entries are set to when unused */
static unsigned int dart_emptyval;
-static struct iommu_table iommu_table_u3;
-static int iommu_table_u3_inited;
+static struct iommu_table iommu_table_dart;
+static int iommu_table_dart_inited;
static int dart_dirty;
+static int dart_is_u4;
#define DBG(...)
static inline void dart_tlb_invalidate_all(void)
{
unsigned long l = 0;
- unsigned int reg;
+ unsigned int reg, inv_bit;
unsigned long limit;
DBG("dart: flush\n");
@@ -81,29 +84,28 @@ static inline void dart_tlb_invalidate_all(void)
*
* Gotcha: Sometimes, the DART won't detect that the bit gets
* set. If so, clear it and set it again.
- */
+ */
limit = 0;
+ inv_bit = dart_is_u4 ? DART_CNTL_U4_FLUSHTLB : DART_CNTL_U3_FLUSHTLB;
retry:
- reg = in_be32((unsigned int *)dart+DARTCNTL);
- reg |= DARTCNTL_FLUSHTLB;
- out_be32((unsigned int *)dart+DARTCNTL, reg);
-
l = 0;
- while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
- l < (1L<<limit)) {
+ reg = DART_IN(DART_CNTL);
+ reg |= inv_bit;
+ DART_OUT(DART_CNTL, reg);
+
+ while ((DART_IN(DART_CNTL) & inv_bit) && l < (1L << limit))
l++;
- }
- if (l == (1L<<limit)) {
+ if (l == (1L << limit)) {
if (limit < 4) {
limit++;
- reg = in_be32((unsigned int *)dart+DARTCNTL);
- reg &= ~DARTCNTL_FLUSHTLB;
- out_be32((unsigned int *)dart+DARTCNTL, reg);
+ reg = DART_IN(DART_CNTL);
+ reg &= ~inv_bit;
+ DART_OUT(DART_CNTL, reg);
goto retry;
} else
- panic("U3-DART: TLB did not flush after waiting a long "
+ panic("DART: TLB did not flush after waiting a long "
"time. Buggy U3 ?");
}
}
@@ -115,7 +117,7 @@ static void dart_flush(struct iommu_table *tbl)
dart_dirty = 0;
}
-static void dart_build(struct iommu_table *tbl, long index,
+static void dart_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction)
{
@@ -128,7 +130,7 @@ static void dart_build(struct iommu_table *tbl, long index,
npages <<= DART_PAGE_FACTOR;
dp = ((unsigned int*)tbl->it_base) + index;
-
+
/* On U3, all memory is contigous, so we can move this
* out of the loop.
*/
@@ -137,7 +139,6 @@ static void dart_build(struct iommu_table *tbl, long index,
*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
- rpn++;
uaddr += DART_PAGE_SIZE;
}
@@ -148,7 +149,7 @@ static void dart_build(struct iommu_table *tbl, long index,
static void dart_free(struct iommu_table *tbl, long index, long npages)
{
unsigned int *dp;
-
+
/* We don't worry about flushing the TLB cache. The only drawback of
* not doing it is that we won't catch buggy device drivers doing
* bad DMAs, but then no 32-bit architecture ever does either.
@@ -160,7 +161,7 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
npages <<= DART_PAGE_FACTOR;
dp = ((unsigned int *)tbl->it_base) + index;
-
+
while (npages--)
*(dp++) = dart_emptyval;
}
@@ -168,20 +169,25 @@ static void dart_free(struct iommu_table *tbl, long index, long npages)
static int dart_init(struct device_node *dart_node)
{
- unsigned int regword;
unsigned int i;
- unsigned long tmp;
+ unsigned long tmp, base, size;
+ struct resource r;
if (dart_tablebase == 0 || dart_tablesize == 0) {
- printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
+ printk(KERN_INFO "DART: table not allocated, using "
+ "direct DMA\n");
return -ENODEV;
}
+ if (of_address_to_resource(dart_node, 0, &r))
+ panic("DART: can't get register base ! ");
+
/* Make sure nothing from the DART range remains in the CPU cache
* from a previous mapping that existed before the kernel took
* over
*/
- flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
+ flush_dcache_phys_range(dart_tablebase,
+ dart_tablebase + dart_tablesize);
/* Allocate a spare page to map all invalid DART pages. We need to do
* that to work around what looks like a problem with the HT bridge
@@ -189,21 +195,16 @@ static int dart_init(struct device_node *dart_node)
*/
tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
if (!tmp)
- panic("U3-DART: Cannot allocate spare page!");
- dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK);
+ panic("DART: Cannot allocate spare page!");
+ dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) &
+ DARTMAP_RPNMASK);
- /* Map in DART registers. FIXME: Use device node to get base address */
- dart = ioremap(DART_BASE, 0x7000);
+ /* Map in DART registers */
+ dart = ioremap(r.start, r.end - r.start + 1);
if (dart == NULL)
- panic("U3-DART: Cannot map registers!");
+ panic("DART: Cannot map registers!");
- /* Set initial control register contents: table base,
- * table size and enable bit
- */
- regword = DARTCNTL_ENABLE |
- ((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
- (((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
- << DARTCNTL_SIZE_SHIFT);
+ /* Map in DART table */
dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
/* Fill initial table */
@@ -211,36 +212,50 @@ static int dart_init(struct device_node *dart_node)
dart_vbase[i] = dart_emptyval;
/* Initialize DART with table base and enable it. */
- out_be32((unsigned int *)dart, regword);
+ base = dart_tablebase >> DART_PAGE_SHIFT;
+ size = dart_tablesize >> DART_PAGE_SHIFT;
+ if (dart_is_u4) {
+ size &= DART_SIZE_U4_SIZE_MASK;
+ DART_OUT(DART_BASE_U4, base);
+ DART_OUT(DART_SIZE_U4, size);
+ DART_OUT(DART_CNTL, DART_CNTL_U4_ENABLE);
+ } else {
+ size &= DART_CNTL_U3_SIZE_MASK;
+ DART_OUT(DART_CNTL,
+ DART_CNTL_U3_ENABLE |
+ (base << DART_CNTL_U3_BASE_SHIFT) |
+ (size << DART_CNTL_U3_SIZE_SHIFT));
+ }
/* Invalidate DART to get rid of possible stale TLBs */
dart_tlb_invalidate_all();
- printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
+ printk(KERN_INFO "DART IOMMU initialized for %s type chipset\n",
+ dart_is_u4 ? "U4" : "U3");
return 0;
}
-static void iommu_table_u3_setup(void)
+static void iommu_table_dart_setup(void)
{
- iommu_table_u3.it_busno = 0;
- iommu_table_u3.it_offset = 0;
+ iommu_table_dart.it_busno = 0;
+ iommu_table_dart.it_offset = 0;
/* it_size is in number of entries */
- iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
+ iommu_table_dart.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
/* Initialize the common IOMMU code */
- iommu_table_u3.it_base = (unsigned long)dart_vbase;
- iommu_table_u3.it_index = 0;
- iommu_table_u3.it_blocksize = 1;
- iommu_init_table(&iommu_table_u3);
+ iommu_table_dart.it_base = (unsigned long)dart_vbase;
+ iommu_table_dart.it_index = 0;
+ iommu_table_dart.it_blocksize = 1;
+ iommu_init_table(&iommu_table_dart);
/* Reserve the last page of the DART to avoid possible prefetch
* past the DART mapped area
*/
- set_bit(iommu_table_u3.it_size - 1, iommu_table_u3.it_map);
+ set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
}
-static void iommu_dev_setup_u3(struct pci_dev *dev)
+static void iommu_dev_setup_dart(struct pci_dev *dev)
{
struct device_node *dn;
@@ -254,35 +269,39 @@ static void iommu_dev_setup_u3(struct pci_dev *dev)
dn = pci_device_to_OF_node(dev);
if (dn)
- PCI_DN(dn)->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_dart;
}
-static void iommu_bus_setup_u3(struct pci_bus *bus)
+static void iommu_bus_setup_dart(struct pci_bus *bus)
{
struct device_node *dn;
- if (!iommu_table_u3_inited) {
- iommu_table_u3_inited = 1;
- iommu_table_u3_setup();
+ if (!iommu_table_dart_inited) {
+ iommu_table_dart_inited = 1;
+ iommu_table_dart_setup();
}
dn = pci_bus_to_OF_node(bus);
if (dn)
- PCI_DN(dn)->iommu_table = &iommu_table_u3;
+ PCI_DN(dn)->iommu_table = &iommu_table_dart;
}
static void iommu_dev_setup_null(struct pci_dev *dev) { }
static void iommu_bus_setup_null(struct pci_bus *bus) { }
-void iommu_init_early_u3(void)
+void iommu_init_early_dart(void)
{
struct device_node *dn;
/* Find the DART in the device-tree */
dn = of_find_compatible_node(NULL, "dart", "u3-dart");
- if (dn == NULL)
- return;
+ if (dn == NULL) {
+ dn = of_find_compatible_node(NULL, "dart", "u4-dart");
+ if (dn == NULL)
+ goto bail;
+ dart_is_u4 = 1;
+ }
/* Setup low level TCE operations for the core IOMMU code */
ppc_md.tce_build = dart_build;
@@ -290,24 +309,27 @@ void iommu_init_early_u3(void)
ppc_md.tce_flush = dart_flush;
/* Initialize the DART HW */
- if (dart_init(dn)) {
- /* If init failed, use direct iommu and null setup functions */
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
-
- /* Setup pci_dma ops */
- pci_direct_iommu_init();
- } else {
- ppc_md.iommu_dev_setup = iommu_dev_setup_u3;
- ppc_md.iommu_bus_setup = iommu_bus_setup_u3;
+ if (dart_init(dn) == 0) {
+ ppc_md.iommu_dev_setup = iommu_dev_setup_dart;
+ ppc_md.iommu_bus_setup = iommu_bus_setup_dart;
/* Setup pci_dma ops */
pci_iommu_init();
+
+ return;
}
+
+ bail:
+ /* If init failed, use direct iommu and null setup functions */
+ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+ ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+
+ /* Setup pci_dma ops */
+ pci_direct_iommu_init();
}
-void __init alloc_u3_dart_table(void)
+void __init alloc_dart_table(void)
{
/* Only reserve DART space if machine has more than 2GB of RAM
* or if requested with iommu=on on cmdline.
@@ -323,5 +345,5 @@ void __init alloc_u3_dart_table(void)
dart_tablebase = (unsigned long)
abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
- printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
+ printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
new file mode 100644
index 000000000000..064c9de47732
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -0,0 +1,317 @@
+/*
+ * FSL SoC setup code
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact 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; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <sysdev/fsl_soc.h>
+#include <mm/mmu_decl.h>
+
+static phys_addr_t immrbase = -1;
+
+phys_addr_t get_immrbase(void)
+{
+ struct device_node *soc;
+
+ if (immrbase != -1)
+ return immrbase;
+
+ soc = of_find_node_by_type(NULL, "soc");
+ if (soc != 0) {
+ unsigned int size;
+ void *prop = get_property(soc, "reg", &size);
+ immrbase = of_translate_address(soc, prop);
+ of_node_put(soc);
+ };
+
+ return immrbase;
+}
+EXPORT_SYMBOL(get_immrbase);
+
+static const char * gfar_tx_intr = "tx";
+static const char * gfar_rx_intr = "rx";
+static const char * gfar_err_intr = "error";
+
+static int __init gfar_of_init(void)
+{
+ struct device_node *np;
+ unsigned int i;
+ struct platform_device *mdio_dev, *gfar_dev;
+ struct resource res;
+ int ret;
+
+ for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) {
+ int k;
+ struct device_node *child = NULL;
+ struct gianfar_mdio_data mdio_data;
+
+ memset(&res, 0, sizeof(res));
+ memset(&mdio_data, 0, sizeof(mdio_data));
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ goto mdio_err;
+
+ mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1);
+ if (IS_ERR(mdio_dev)) {
+ ret = PTR_ERR(mdio_dev);
+ goto mdio_err;
+ }
+
+ for (k = 0; k < 32; k++)
+ mdio_data.irq[k] = -1;
+
+ while ((child = of_get_next_child(np, child)) != NULL) {
+ if (child->n_intrs) {
+ u32 *id = (u32 *) get_property(child, "reg", NULL);
+ mdio_data.irq[*id] = child->intrs[0].line;
+ }
+ }
+
+ ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data));
+ if (ret)
+ goto mdio_unreg;
+ }
+
+ for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) {
+ struct resource r[4];
+ struct device_node *phy, *mdio;
+ struct gianfar_platform_data gfar_data;
+ unsigned int *id;
+ char *model;
+ void *mac_addr;
+ phandle *ph;
+
+ memset(r, 0, sizeof(r));
+ memset(&gfar_data, 0, sizeof(gfar_data));
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto gfar_err;
+
+ r[1].start = np->intrs[0].line;
+ r[1].end = np->intrs[0].line;
+ r[1].flags = IORESOURCE_IRQ;
+
+ model = get_property(np, "model", NULL);
+
+ /* If we aren't the FEC we have multiple interrupts */
+ if (model && strcasecmp(model, "FEC")) {
+ r[1].name = gfar_tx_intr;
+
+ r[2].name = gfar_rx_intr;
+ r[2].start = np->intrs[1].line;
+ r[2].end = np->intrs[1].line;
+ r[2].flags = IORESOURCE_IRQ;
+
+ r[3].name = gfar_err_intr;
+ r[3].start = np->intrs[2].line;
+ r[3].end = np->intrs[2].line;
+ r[3].flags = IORESOURCE_IRQ;
+ }
+
+ gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1);
+
+ if (IS_ERR(gfar_dev)) {
+ ret = PTR_ERR(gfar_dev);
+ goto gfar_err;
+ }
+
+ mac_addr = get_property(np, "address", NULL);
+ memcpy(gfar_data.mac_addr, mac_addr, 6);
+
+ if (model && !strcasecmp(model, "TSEC"))
+ gfar_data.device_flags =
+ FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE |
+ FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR;
+ if (model && !strcasecmp(model, "eTSEC"))
+ gfar_data.device_flags =
+ FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE |
+ FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM |
+ FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
+
+ ph = (phandle *) get_property(np, "phy-handle", NULL);
+ phy = of_find_node_by_phandle(*ph);
+
+ if (phy == NULL) {
+ ret = -ENODEV;
+ goto gfar_unreg;
+ }
+
+ mdio = of_get_parent(phy);
+
+ id = (u32 *) get_property(phy, "reg", NULL);
+ ret = of_address_to_resource(mdio, 0, &res);
+ if (ret) {
+ of_node_put(phy);
+ of_node_put(mdio);
+ goto gfar_unreg;
+ }
+
+ gfar_data.phy_id = *id;
+ gfar_data.bus_id = res.start;
+
+ of_node_put(phy);
+ of_node_put(mdio);
+
+ ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data));
+ if (ret)
+ goto gfar_unreg;
+ }
+
+ return 0;
+
+mdio_unreg:
+ platform_device_unregister(mdio_dev);
+mdio_err:
+ return ret;
+
+gfar_unreg:
+ platform_device_unregister(gfar_dev);
+gfar_err:
+ return ret;
+}
+arch_initcall(gfar_of_init);
+
+static int __init fsl_i2c_of_init(void)
+{
+ struct device_node *np;
+ unsigned int i;
+ struct platform_device *i2c_dev;
+ int ret;
+
+ for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) {
+ struct resource r[2];
+ struct fsl_i2c_platform_data i2c_data;
+ unsigned char * flags = NULL;
+
+ memset(&r, 0, sizeof(r));
+ memset(&i2c_data, 0, sizeof(i2c_data));
+
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ goto i2c_err;
+
+ r[1].start = np->intrs[0].line;
+ r[1].end = np->intrs[0].line;
+ r[1].flags = IORESOURCE_IRQ;
+
+ i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
+ if (IS_ERR(i2c_dev)) {
+ ret = PTR_ERR(i2c_dev);
+ goto i2c_err;
+ }
+
+ i2c_data.device_flags = 0;
+ flags = get_property(np, "dfsrr", NULL);
+ if (flags)
+ i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
+
+ flags = get_property(np, "fsl5200-clocking", NULL);
+ if (flags)
+ i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
+
+ ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data));
+ if (ret)
+ goto i2c_unreg;
+ }
+
+ return 0;
+
+i2c_unreg:
+ platform_device_unregister(i2c_dev);
+i2c_err:
+ return ret;
+}
+arch_initcall(fsl_i2c_of_init);
+
+#ifdef CONFIG_PPC_83xx
+static int __init mpc83xx_wdt_init(void)
+{
+ struct resource r;
+ struct device_node *soc, *np;
+ struct platform_device *dev;
+ unsigned int *freq;
+ int ret;
+
+ np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
+
+ if (!np) {
+ ret = -ENODEV;
+ goto mpc83xx_wdt_nodev;
+ }
+
+ soc = of_find_node_by_type(NULL, "soc");
+
+ if (!soc) {
+ ret = -ENODEV;
+ goto mpc83xx_wdt_nosoc;
+ }
+
+ freq = (unsigned int *)get_property(soc, "bus-frequency", NULL);
+ if (!freq) {
+ ret = -ENODEV;
+ goto mpc83xx_wdt_err;
+ }
+
+ memset(&r, 0, sizeof(r));
+
+ ret = of_address_to_resource(np, 0, &r);
+ if (ret)
+ goto mpc83xx_wdt_err;
+
+ dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
+ if (IS_ERR(dev)) {
+ ret = PTR_ERR(dev);
+ goto mpc83xx_wdt_err;
+ }
+
+ ret = platform_device_add_data(dev, freq, sizeof(int));
+ if (ret)
+ goto mpc83xx_wdt_unreg;
+
+ of_node_put(soc);
+ of_node_put(np);
+
+ return 0;
+
+mpc83xx_wdt_unreg:
+ platform_device_unregister(dev);
+mpc83xx_wdt_err:
+ of_node_put(soc);
+mpc83xx_wdt_nosoc:
+ of_node_put(np);
+mpc83xx_wdt_nodev:
+ return ret;
+}
+arch_initcall(mpc83xx_wdt_init);
+#endif
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
new file mode 100644
index 000000000000..c433d3f39edd
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -0,0 +1,8 @@
+#ifndef __PPC_FSL_SOC_H
+#define __PPC_FSL_SOC_H
+#ifdef __KERNEL__
+
+extern phys_addr_t get_immrbase(void);
+
+#endif
+#endif
diff --git a/arch/ppc/syslib/ipic.c b/arch/powerpc/sysdev/ipic.c
index 8f01e0f1d847..8f01e0f1d847 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
diff --git a/arch/ppc/syslib/ipic.h b/arch/powerpc/sysdev/ipic.h
index a7ce7da8785c..a7ce7da8785c 100644
--- a/arch/ppc/syslib/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 58d1cc2023c8..4f26304d0263 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -13,6 +13,9 @@
*/
#undef DEBUG
+#undef DEBUG_IPI
+#undef DEBUG_IRQ
+#undef DEBUG_LOW
#include <linux/config.h>
#include <linux/types.h>
@@ -45,7 +48,11 @@ static struct mpic *mpic_primary;
static DEFINE_SPINLOCK(mpic_lock);
#ifdef CONFIG_PPC32 /* XXX for now */
-#define distribute_irqs CONFIG_IRQ_ALL_CPUS
+#ifdef CONFIG_IRQ_ALL_CPUS
+#define distribute_irqs (1)
+#else
+#define distribute_irqs (0)
+#endif
#endif
/*
@@ -164,70 +171,129 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic)
/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
* to force the edge setting on the MPIC and do the ack workaround.
*/
-static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
{
- if (source_no >= 128 || !mpic->fixups)
+ if (source >= 128 || !mpic->fixups)
return 0;
- return mpic->fixups[source_no].base != NULL;
+ return mpic->fixups[source].base != NULL;
}
-static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
+
+static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
{
- struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
- u32 tmp;
+ struct mpic_irq_fixup *fixup = &mpic->fixups[source];
- spin_lock(&mpic->fixup_lock);
- writeb(0x11 + 2 * fixup->irq, fixup->base);
- tmp = readl(fixup->base + 2);
- writel(tmp | 0x80000000ul, fixup->base + 2);
- /* config writes shouldn't be posted but let's be safe ... */
- (void)readl(fixup->base + 2);
- spin_unlock(&mpic->fixup_lock);
+ if (fixup->applebase) {
+ unsigned int soff = (fixup->index >> 3) & ~3;
+ unsigned int mask = 1U << (fixup->index & 0x1f);
+ writel(mask, fixup->applebase + soff);
+ } else {
+ spin_lock(&mpic->fixup_lock);
+ writeb(0x11 + 2 * fixup->index, fixup->base + 2);
+ writel(fixup->data, fixup->base + 4);
+ spin_unlock(&mpic->fixup_lock);
+ }
}
+static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
+ unsigned int irqflags)
+{
+ struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+ unsigned long flags;
+ u32 tmp;
-static void __init mpic_amd8111_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+ if (fixup->base == NULL)
+ return;
+
+ DBG("startup_ht_interrupt(%u, %u) index: %d\n",
+ source, irqflags, fixup->index);
+ spin_lock_irqsave(&mpic->fixup_lock, flags);
+ /* Enable and configure */
+ writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+ tmp = readl(fixup->base + 4);
+ tmp &= ~(0x23U);
+ if (irqflags & IRQ_LEVEL)
+ tmp |= 0x22;
+ writel(tmp, fixup->base + 4);
+ spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
+ unsigned int irqflags)
{
- int i, irq;
+ struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+ unsigned long flags;
u32 tmp;
- printk(KERN_INFO "mpic: - Workarounds on AMD 8111 @ %p\n", devbase);
+ if (fixup->base == NULL)
+ return;
- for (i=0; i < 24; i++) {
- writeb(0x10 + 2*i, devbase + 0xf2);
- tmp = readl(devbase + 0xf4);
- if ((tmp & 0x1) || !(tmp & 0x20))
- continue;
- irq = (tmp >> 16) & 0xff;
- mpic->fixups[irq].irq = i;
- mpic->fixups[irq].base = devbase + 0xf2;
- }
+ DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
+
+ /* Disable */
+ spin_lock_irqsave(&mpic->fixup_lock, flags);
+ writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+ tmp = readl(fixup->base + 4);
+ tmp &= ~1U;
+ writel(tmp, fixup->base + 4);
+ spin_unlock_irqrestore(&mpic->fixup_lock, flags);
}
-
-static void __init mpic_amd8131_read_irq(struct mpic *mpic, u8 __iomem *devbase)
+
+static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
+ unsigned int devfn, u32 vdid)
{
- int i, irq;
+ int i, irq, n;
+ u8 __iomem *base;
u32 tmp;
+ u8 pos;
+
+ for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+ pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+ u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+ if (id == PCI_CAP_ID_HT_IRQCONF) {
+ id = readb(devbase + pos + 3);
+ if (id == 0x80)
+ break;
+ }
+ }
+ if (pos == 0)
+ return;
- printk(KERN_INFO "mpic: - Workarounds on AMD 8131 @ %p\n", devbase);
+ base = devbase + pos;
+ writeb(0x01, base + 2);
+ n = (readl(base + 4) >> 16) & 0xff;
- for (i=0; i < 4; i++) {
- writeb(0x10 + 2*i, devbase + 0xba);
- tmp = readl(devbase + 0xbc);
- if ((tmp & 0x1) || !(tmp & 0x20))
- continue;
+ printk(KERN_INFO "mpic: - HT:%02x.%x [0x%02x] vendor %04x device %04x"
+ " has %d irqs\n",
+ devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
+
+ for (i = 0; i <= n; i++) {
+ writeb(0x10 + 2 * i, base + 2);
+ tmp = readl(base + 4);
irq = (tmp >> 16) & 0xff;
- mpic->fixups[irq].irq = i;
- mpic->fixups[irq].base = devbase + 0xba;
+ DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
+ /* mask it , will be unmasked later */
+ tmp |= 0x1;
+ writel(tmp, base + 4);
+ mpic->fixups[irq].index = i;
+ mpic->fixups[irq].base = base;
+ /* Apple HT PIC has a non-standard way of doing EOIs */
+ if ((vdid & 0xffff) == 0x106b)
+ mpic->fixups[irq].applebase = devbase + 0x60;
+ else
+ mpic->fixups[irq].applebase = NULL;
+ writeb(0x11 + 2 * i, base + 2);
+ mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
}
}
-static void __init mpic_scan_ioapics(struct mpic *mpic)
+
+static void __init mpic_scan_ht_pics(struct mpic *mpic)
{
unsigned int devfn;
u8 __iomem *cfgspace;
- printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
+ printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
/* Allocate fixups array */
mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
@@ -237,21 +303,20 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
/* Init spinlock */
spin_lock_init(&mpic->fixup_lock);
- /* Map u3 config space. We assume all IO-APICs are on the primary bus
- * and slot will never be above "0xf" so we only need to map 32k
+ /* Map U3 config space. We assume all IO-APICs are on the primary bus
+ * so we only need to map 64kB.
*/
- cfgspace = (unsigned char __iomem *)ioremap(0xf2000000, 0x8000);
+ cfgspace = ioremap(0xf2000000, 0x10000);
BUG_ON(cfgspace == NULL);
- /* Now we scan all slots. We do a very quick scan, we read the header type,
- * vendor ID and device ID only, that's plenty enough
+ /* Now we scan all slots. We do a very quick scan, we read the header
+ * type, vendor ID and device ID only, that's plenty enough
*/
- for (devfn = 0; devfn < PCI_DEVFN(0x10,0); devfn ++) {
+ for (devfn = 0; devfn < 0x100; devfn++) {
u8 __iomem *devbase = cfgspace + (devfn << 8);
u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
u32 l = readl(devbase + PCI_VENDOR_ID);
- u16 vendor_id, device_id;
- int multifunc = 0;
+ u16 s;
DBG("devfn %x, l: %x\n", devfn, l);
@@ -259,22 +324,16 @@ static void __init mpic_scan_ioapics(struct mpic *mpic)
if (l == 0xffffffff || l == 0x00000000 ||
l == 0x0000ffff || l == 0xffff0000)
goto next;
+ /* Check if is supports capability lists */
+ s = readw(devbase + PCI_STATUS);
+ if (!(s & PCI_STATUS_CAP_LIST))
+ goto next;
+
+ mpic_scan_ht_pic(mpic, devbase, devfn, l);
- /* Check if it's a multifunction device (only really used
- * to function 0 though
- */
- multifunc = !!(hdr_type & 0x80);
- vendor_id = l & 0xffff;
- device_id = (l >> 16) & 0xffff;
-
- /* If a known device, go to fixup setup code */
- if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7460)
- mpic_amd8111_read_irq(mpic, devbase);
- if (vendor_id == PCI_VENDOR_ID_AMD && device_id == 0x7450)
- mpic_amd8131_read_irq(mpic, devbase);
next:
/* next device, if function 0 */
- if ((PCI_FUNC(devfn) == 0) && !multifunc)
+ if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
devfn += 7;
}
}
@@ -371,6 +430,31 @@ static void mpic_enable_irq(unsigned int irq)
break;
}
} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+ if (mpic->flags & MPIC_BROKEN_U3) {
+ unsigned int src = irq - mpic->irq_offset;
+ if (mpic_is_ht_interrupt(mpic, src) &&
+ (irq_desc[irq].status & IRQ_LEVEL))
+ mpic_ht_end_irq(mpic, src);
+ }
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+}
+
+static unsigned int mpic_startup_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+ struct mpic *mpic = mpic_from_irq(irq);
+ unsigned int src = irq - mpic->irq_offset;
+
+ if (mpic_is_ht_interrupt(mpic, src))
+ mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+ mpic_enable_irq(irq);
+
+ return 0;
}
static void mpic_disable_irq(unsigned int irq)
@@ -394,12 +478,27 @@ static void mpic_disable_irq(unsigned int irq)
} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
}
+static void mpic_shutdown_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+ struct mpic *mpic = mpic_from_irq(irq);
+ unsigned int src = irq - mpic->irq_offset;
+
+ if (mpic_is_ht_interrupt(mpic, src))
+ mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+ mpic_disable_irq(irq);
+}
+
static void mpic_end_irq(unsigned int irq)
{
struct mpic *mpic = mpic_from_irq(irq);
+#ifdef DEBUG_IRQ
DBG("%s: end_irq: %d\n", mpic->name, irq);
-
+#endif
/* We always EOI on end_irq() even for edge interrupts since that
* should only lower the priority, the MPIC should have properly
* latched another edge interrupt coming in anyway
@@ -408,8 +507,9 @@ static void mpic_end_irq(unsigned int irq)
#ifdef CONFIG_MPIC_BROKEN_U3
if (mpic->flags & MPIC_BROKEN_U3) {
unsigned int src = irq - mpic->irq_offset;
- if (mpic_is_ht_interrupt(mpic, src))
- mpic_apic_end_irq(mpic, src);
+ if (mpic_is_ht_interrupt(mpic, src) &&
+ (irq_desc[irq].status & IRQ_LEVEL))
+ mpic_ht_end_irq(mpic, src);
}
#endif /* CONFIG_MPIC_BROKEN_U3 */
@@ -490,6 +590,8 @@ struct mpic * __init mpic_alloc(unsigned long phys_addr,
mpic->name = name;
mpic->hc_irq.typename = name;
+ mpic->hc_irq.startup = mpic_startup_irq;
+ mpic->hc_irq.shutdown = mpic_shutdown_irq;
mpic->hc_irq.enable = mpic_enable_irq;
mpic->hc_irq.disable = mpic_disable_irq;
mpic->hc_irq.end = mpic_end_irq;
@@ -658,10 +760,10 @@ void __init mpic_init(struct mpic *mpic)
mpic->irq_count = mpic->num_sources;
#ifdef CONFIG_MPIC_BROKEN_U3
- /* Do the ioapic fixups on U3 broken mpic */
+ /* Do the HT PIC fixups on U3 broken mpic */
DBG("MPIC flags: %x\n", mpic->flags);
if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
- mpic_scan_ioapics(mpic);
+ mpic_scan_ht_pics(mpic);
#endif /* CONFIG_MPIC_BROKEN_U3 */
for (i = 0; i < mpic->num_sources; i++) {
@@ -848,7 +950,9 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
BUG_ON(mpic == NULL);
+#ifdef DEBUG_IPI
DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+#endif
mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
@@ -859,19 +963,28 @@ int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs)
u32 irq;
irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+#ifdef DEBUG_LOW
DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
-
+#endif
if (mpic->cascade && irq == mpic->cascade_vec) {
+#ifdef DEBUG_LOW
DBG("%s: cascading ...\n", mpic->name);
+#endif
irq = mpic->cascade(regs, mpic->cascade_data);
mpic_eoi(mpic);
return irq;
}
if (unlikely(irq == MPIC_VEC_SPURRIOUS))
return -1;
- if (irq < MPIC_VEC_IPI_0)
+ if (irq < MPIC_VEC_IPI_0) {
+#ifdef DEBUG_IRQ
+ DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
+#endif
return irq + mpic->irq_offset;
+ }
+#ifdef DEBUG_IPI
DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+#endif
return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
}
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index b20312e5ed27..109d874ecfbe 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -3,9 +3,5 @@
ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-
-obj-$(CONFIG_8xx) += start_8xx.o
-obj-$(CONFIG_6xx) += start_32.o
-obj-$(CONFIG_4xx) += start_32.o
-obj-$(CONFIG_PPC64) += start_64.o
-obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o nonstdio.o
+obj-y += xmon.o ppc-dis.o ppc-opc.o setjmp.o start.o \
+ nonstdio.o
diff --git a/arch/powerpc/xmon/start_64.c b/arch/powerpc/xmon/start.c
index 712552c4f242..712552c4f242 100644
--- a/arch/powerpc/xmon/start_64.c
+++ b/arch/powerpc/xmon/start.c
diff --git a/arch/powerpc/xmon/start_32.c b/arch/powerpc/xmon/start_32.c
deleted file mode 100644
index c2464df4217e..000000000000
--- a/arch/powerpc/xmon/start_32.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <linux/config.h>
-#include <linux/string.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/cuda.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/bitops.h>
-#include <asm/xmon.h>
-#include <asm/prom.h>
-#include <asm/bootx.h>
-#include <asm/machdep.h>
-#include <asm/errno.h>
-#include <asm/pmac_feature.h>
-#include <asm/processor.h>
-#include <asm/delay.h>
-#include <asm/btext.h>
-#include <asm/time.h>
-#include "nonstdio.h"
-
-static volatile unsigned char __iomem *sccc, *sccd;
-unsigned int TXRDY, RXRDY, DLAB;
-
-static int use_serial;
-static int use_screen;
-static int via_modem;
-static int xmon_use_sccb;
-static struct device_node *channel_node;
-
-void buf_access(void)
-{
- if (DLAB)
- sccd[3] &= ~DLAB; /* reset DLAB */
-}
-
-extern int adb_init(void);
-
-#ifdef CONFIG_PPC_CHRP
-/*
- * This looks in the "ranges" property for the primary PCI host bridge
- * to find the physical address of the start of PCI/ISA I/O space.
- * It is basically a cut-down version of pci_process_bridge_OF_ranges.
- */
-static unsigned long chrp_find_phys_io_base(void)
-{
- struct device_node *node;
- unsigned int *ranges;
- unsigned long base = CHRP_ISA_IO_BASE;
- int rlen = 0;
- int np;
-
- node = find_devices("isa");
- if (node != NULL) {
- node = node->parent;
- if (node == NULL || node->type == NULL
- || strcmp(node->type, "pci") != 0)
- node = NULL;
- }
- if (node == NULL)
- node = find_devices("pci");
- if (node == NULL)
- return base;
-
- ranges = (unsigned int *) get_property(node, "ranges", &rlen);
- np = prom_n_addr_cells(node) + 5;
- while ((rlen -= np * sizeof(unsigned int)) >= 0) {
- if ((ranges[0] >> 24) == 1 && ranges[2] == 0) {
- /* I/O space starting at 0, grab the phys base */
- base = ranges[np - 3];
- break;
- }
- ranges += np;
- }
- return base;
-}
-#endif /* CONFIG_PPC_CHRP */
-
-void xmon_map_scc(void)
-{
-#ifdef CONFIG_PPC_MULTIPLATFORM
- volatile unsigned char __iomem *base;
-
- if (_machine == _MACH_Pmac) {
- struct device_node *np;
- unsigned long addr;
-#ifdef CONFIG_BOOTX_TEXT
- if (!use_screen && !use_serial
- && !machine_is_compatible("iMac")) {
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- for (np = find_devices("keyboard"); np; np = np->next)
- if (np->parent && np->parent->type
- && strcmp(np->parent->type, "adb") == 0)
- break;
-
- /* needs to be hacked if xmon_printk is to be used
- from within find_via_pmu() */
-#ifdef CONFIG_ADB_PMU
- if (np != NULL && boot_text_mapped && find_via_pmu())
- use_screen = 1;
-#endif
-#ifdef CONFIG_ADB_CUDA
- if (np != NULL && boot_text_mapped && find_via_cuda())
- use_screen = 1;
-#endif
- }
- if (!use_screen && (np = find_devices("escc")) != NULL) {
- /*
- * look for the device node for the serial port
- * we're using and see if it says it has a modem
- */
- char *name = xmon_use_sccb? "ch-b": "ch-a";
- char *slots;
- int l;
-
- np = np->child;
- while (np != NULL && strcmp(np->name, name) != 0)
- np = np->sibling;
- if (np != NULL) {
- /* XXX should parse this properly */
- channel_node = np;
- slots = get_property(np, "slot-names", &l);
- if (slots != NULL && l >= 10
- && strcmp(slots+4, "Modem") == 0)
- via_modem = 1;
- }
- }
- btext_drawstring("xmon uses ");
- if (use_screen)
- btext_drawstring("screen and keyboard\n");
- else {
- if (via_modem)
- btext_drawstring("modem on ");
- btext_drawstring(xmon_use_sccb? "printer": "modem");
- btext_drawstring(" port\n");
- }
-
-#endif /* CONFIG_BOOTX_TEXT */
-
-#ifdef CHRP_ESCC
- addr = 0xc1013020;
-#else
- addr = 0xf3013020;
-#endif
- TXRDY = 4;
- RXRDY = 1;
-
- np = find_devices("mac-io");
- if (np && np->n_addrs)
- addr = np->addrs[0].address + 0x13020;
- base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
- sccc = base + (addr & ~PAGE_MASK);
- sccd = sccc + 0x10;
-
- } else {
- base = (volatile unsigned char *) isa_io_base;
-
-#ifdef CONFIG_PPC_CHRP
- if (_machine == _MACH_chrp)
- base = (volatile unsigned char __iomem *)
- ioremap(chrp_find_phys_io_base(), 0x1000);
-#endif
-
- sccc = base + 0x3fd;
- sccd = base + 0x3f8;
- if (xmon_use_sccb) {
- sccc -= 0x100;
- sccd -= 0x100;
- }
- TXRDY = 0x20;
- RXRDY = 1;
- DLAB = 0x80;
- }
-#elif defined(CONFIG_GEMINI)
- /* should already be mapped by the kernel boot */
- sccc = (volatile unsigned char __iomem *) 0xffeffb0d;
- sccd = (volatile unsigned char __iomem *) 0xffeffb08;
- TXRDY = 0x20;
- RXRDY = 1;
- DLAB = 0x80;
-#elif defined(CONFIG_405GP)
- sccc = (volatile unsigned char __iomem *)0xef600305;
- sccd = (volatile unsigned char __iomem *)0xef600300;
- TXRDY = 0x20;
- RXRDY = 1;
- DLAB = 0x80;
-#endif /* platform */
-}
-
-static int scc_initialized = 0;
-
-void xmon_init_scc(void);
-extern void cuda_poll(void);
-
-static inline void do_poll_adb(void)
-{
-#ifdef CONFIG_ADB_PMU
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll_adb();
-#endif /* CONFIG_ADB_PMU */
-#ifdef CONFIG_ADB_CUDA
- if (sys_ctrler == SYS_CTRLER_CUDA)
- cuda_poll();
-#endif /* CONFIG_ADB_CUDA */
-}
-
-int xmon_write(void *ptr, int nb)
-{
- char *p = ptr;
- int i, c, ct;
-
-#ifdef CONFIG_SMP
- static unsigned long xmon_write_lock;
- int lock_wait = 1000000;
- int locked;
-
- while ((locked = test_and_set_bit(0, &xmon_write_lock)) != 0)
- if (--lock_wait == 0)
- break;
-#endif
-
-#ifdef CONFIG_BOOTX_TEXT
- if (use_screen) {
- /* write it on the screen */
- for (i = 0; i < nb; ++i)
- btext_drawchar(*p++);
- goto out;
- }
-#endif
- if (!scc_initialized)
- xmon_init_scc();
- ct = 0;
- for (i = 0; i < nb; ++i) {
- while ((*sccc & TXRDY) == 0)
- do_poll_adb();
- c = p[i];
- if (c == '\n' && !ct) {
- c = '\r';
- ct = 1;
- --i;
- } else {
- ct = 0;
- }
- buf_access();
- *sccd = c;
- eieio();
- }
-
- out:
-#ifdef CONFIG_SMP
- if (!locked)
- clear_bit(0, &xmon_write_lock);
-#endif
- return nb;
-}
-
-int xmon_wants_key;
-int xmon_adb_keycode;
-
-#ifdef CONFIG_BOOTX_TEXT
-static int xmon_adb_shiftstate;
-
-static unsigned char xmon_keytab[128] =
- "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
- "yt123465=97-80]o" /* 0x10 - 0x1f */
- "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
- "\t `\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
- "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
- "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
-
-static unsigned char xmon_shift_keytab[128] =
- "ASDFHGZXCV\000BQWER" /* 0x00 - 0x0f */
- "YT!@#$^%+(&_*)}O" /* 0x10 - 0x1f */
- "U{IP\rLJ\"K:|<?NM>" /* 0x20 - 0x2f */
- "\t ~\177\0\033\0\0\0\0\0\0\0\0\0\0" /* 0x30 - 0x3f */
- "\0.\0*\0+\0\0\0\0\0/\r\0-\0" /* 0x40 - 0x4f */
- "\0\0000123456789\0\0\0"; /* 0x50 - 0x5f */
-
-static int xmon_get_adb_key(void)
-{
- int k, t, on;
-
- xmon_wants_key = 1;
- for (;;) {
- xmon_adb_keycode = -1;
- t = 0;
- on = 0;
- do {
- if (--t < 0) {
- on = 1 - on;
- btext_drawchar(on? 0xdb: 0x20);
- btext_drawchar('\b');
- t = 200000;
- }
- do_poll_adb();
- } while (xmon_adb_keycode == -1);
- k = xmon_adb_keycode;
- if (on)
- btext_drawstring(" \b");
-
- /* test for shift keys */
- if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) {
- xmon_adb_shiftstate = (k & 0x80) == 0;
- continue;
- }
- if (k >= 0x80)
- continue; /* ignore up transitions */
- k = (xmon_adb_shiftstate? xmon_shift_keytab: xmon_keytab)[k];
- if (k != 0)
- break;
- }
- xmon_wants_key = 0;
- return k;
-}
-#endif /* CONFIG_BOOTX_TEXT */
-
-int xmon_readchar(void)
-{
-#ifdef CONFIG_BOOTX_TEXT
- if (use_screen)
- return xmon_get_adb_key();
-#endif
- if (!scc_initialized)
- xmon_init_scc();
- while ((*sccc & RXRDY) == 0)
- do_poll_adb();
- buf_access();
- return *sccd;
-}
-
-int xmon_read_poll(void)
-{
- if ((*sccc & RXRDY) == 0) {
- do_poll_adb();
- return -1;
- }
- buf_access();
- return *sccd;
-}
-
-static unsigned char scc_inittab[] = {
- 13, 0, /* set baud rate divisor */
- 12, 1,
- 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 xmon_init_scc(void)
-{
- if ( _machine == _MACH_chrp )
- {
- sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */
- sccd[0] = 12; eieio(); /* DLL = 9600 baud */
- sccd[1] = 0; eieio();
- sccd[2] = 0; eieio(); /* FCR = 0 */
- sccd[3] = 3; eieio(); /* LCR = 8N1 */
- sccd[1] = 0; eieio(); /* IER = 0 */
- }
- else if ( _machine == _MACH_Pmac )
- {
- int i, x;
- unsigned long timeout;
-
- if (channel_node != 0)
- pmac_call_feature(
- PMAC_FTR_SCC_ENABLE,
- channel_node,
- PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
- printk(KERN_INFO "Serial port locked ON by debugger !\n");
- if (via_modem && channel_node != 0) {
- unsigned int t0;
-
- pmac_call_feature(
- PMAC_FTR_MODEM_ENABLE,
- channel_node, 0, 1);
- printk(KERN_INFO "Modem powered up by debugger !\n");
- t0 = get_tbl();
- timeout = 3 * tb_ticks_per_sec;
- if (timeout == 0)
- /* assume 25MHz if tb_ticks_per_sec not set */
- timeout = 75000000;
- while (get_tbl() - t0 < timeout)
- eieio();
- }
- /* use the B channel if requested */
- if (xmon_use_sccb) {
- sccc = (volatile unsigned char *)
- ((unsigned long)sccc & ~0x20);
- sccd = sccc + 0x10;
- }
- for (i = 20000; i != 0; --i) {
- x = *sccc; eieio();
- }
- *sccc = 9; eieio(); /* reset A or B side */
- *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
- for (i = 0; i < sizeof(scc_inittab); ++i) {
- *sccc = scc_inittab[i];
- eieio();
- }
- }
- scc_initialized = 1;
- if (via_modem) {
- for (;;) {
- xmon_write("ATE1V1\r", 7);
- if (xmon_expect("OK", 5)) {
- xmon_write("ATA\r", 4);
- if (xmon_expect("CONNECT", 40))
- break;
- }
- xmon_write("+++", 3);
- xmon_expect("OK", 3);
- }
- }
-}
-
-void xmon_enter(void)
-{
-#ifdef CONFIG_ADB_PMU
- if (_machine == _MACH_Pmac) {
- pmu_suspend();
- }
-#endif
-}
-
-void xmon_leave(void)
-{
-#ifdef CONFIG_ADB_PMU
- if (_machine == _MACH_Pmac) {
- pmu_resume();
- }
-#endif
-}
diff --git a/arch/powerpc/xmon/start_8xx.c b/arch/powerpc/xmon/start_8xx.c
deleted file mode 100644
index 4c17b0486ad5..000000000000
--- a/arch/powerpc/xmon/start_8xx.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- * Copyright (C) 2000 Dan Malek.
- * Quick hack of Paul's code to make XMON work on 8xx processors. Lots
- * of assumptions, like the SMC1 is used, it has been initialized by the
- * loader at some point, and we can just stuff and suck bytes.
- * We rely upon the 8xx uart driver to support us, as the interface
- * changes between boot up and operational phases of the kernel.
- */
-#include <linux/string.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <linux/kernel.h>
-#include <asm/8xx_immap.h>
-#include <asm/mpc8xx.h>
-#include <asm/commproc.h>
-#include "nonstdio.h"
-
-extern int xmon_8xx_write(char *str, int nb);
-extern int xmon_8xx_read_poll(void);
-extern int xmon_8xx_read_char(void);
-
-void xmon_map_scc(void)
-{
- cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
-}
-
-void xmon_init_scc(void);
-
-int xmon_write(void *ptr, int nb)
-{
- return(xmon_8xx_write(ptr, nb));
-}
-
-int xmon_readchar(void)
-{
- return xmon_8xx_read_char();
-}
-
-int xmon_read_poll(void)
-{
- return(xmon_8xx_read_poll());
-}
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index c45a6ad5f3b7..7d02fa2a8990 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -311,7 +311,7 @@ static void release_output_lock(void)
}
#endif
-int xmon_core(struct pt_regs *regs, int fromipi)
+static int xmon_core(struct pt_regs *regs, int fromipi)
{
int cmd = 0;
unsigned long msr;
@@ -450,7 +450,6 @@ int xmon_core(struct pt_regs *regs, int fromipi)
leave:
cpu_clear(cpu, cpus_in_xmon);
xmon_fault_jmp[cpu] = NULL;
-
#else
/* UP is simple... */
if (in_xmon) {
@@ -529,7 +528,7 @@ xmon_irq(int irq, void *d, struct pt_regs *regs)
return IRQ_HANDLED;
}
-int xmon_bpt(struct pt_regs *regs)
+static int xmon_bpt(struct pt_regs *regs)
{
struct bpt *bp;
unsigned long offset;
@@ -555,7 +554,7 @@ int xmon_bpt(struct pt_regs *regs)
return 1;
}
-int xmon_sstep(struct pt_regs *regs)
+static int xmon_sstep(struct pt_regs *regs)
{
if (user_mode(regs))
return 0;
@@ -563,7 +562,7 @@ int xmon_sstep(struct pt_regs *regs)
return 1;
}
-int xmon_dabr_match(struct pt_regs *regs)
+static int xmon_dabr_match(struct pt_regs *regs)
{
if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
return 0;
@@ -573,7 +572,7 @@ int xmon_dabr_match(struct pt_regs *regs)
return 1;
}
-int xmon_iabr_match(struct pt_regs *regs)
+static int xmon_iabr_match(struct pt_regs *regs)
{
if ((regs->msr & (MSR_IR|MSR_PR|MSR_SF)) != (MSR_IR|MSR_SF))
return 0;
@@ -583,7 +582,7 @@ int xmon_iabr_match(struct pt_regs *regs)
return 1;
}
-int xmon_ipi(struct pt_regs *regs)
+static int xmon_ipi(struct pt_regs *regs)
{
#ifdef CONFIG_SMP
if (in_xmon && !cpu_isset(smp_processor_id(), cpus_in_xmon))
@@ -592,7 +591,7 @@ int xmon_ipi(struct pt_regs *regs)
return 0;
}
-int xmon_fault_handler(struct pt_regs *regs)
+static int xmon_fault_handler(struct pt_regs *regs)
{
struct bpt *bp;
unsigned long offset;
@@ -805,7 +804,10 @@ cmds(struct pt_regs *excp)
break;
case 'x':
case 'X':
+ return cmd;
case EOF:
+ printf(" <no input ...>\n");
+ mdelay(2000);
return cmd;
case '?':
printf(help_string);
@@ -1011,7 +1013,7 @@ static long check_bp_loc(unsigned long addr)
unsigned int instr;
addr &= ~3;
- if (addr < KERNELBASE) {
+ if (!is_kernel_addr(addr)) {
printf("Breakpoints may only be placed at kernel addresses\n");
return 0;
}
@@ -1062,7 +1064,7 @@ bpt_cmds(void)
dabr.address = 0;
dabr.enabled = 0;
if (scanhex(&dabr.address)) {
- if (dabr.address < KERNELBASE) {
+ if (!is_kernel_addr(dabr.address)) {
printf(badaddr);
break;
}
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
index 84d96b857e4a..8ace2a1f3b48 100644
--- a/arch/ppc/4xx_io/serial_sicc.c
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -47,6 +47,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/capability.h>
#include <linux/circ_buf.h>
#include <linux/serial.h>
#include <linux/console.h>
@@ -214,7 +215,6 @@ static struct tty_driver *siccnormal_driver;
* memory if large numbers of serial ports are open.
*/
static u_char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index cc3f64c084c5..11899f06bf06 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -8,9 +8,6 @@ config MMU
bool
default y
-config UID16
- bool
-
config GENERIC_HARDIRQS
bool
default y
@@ -61,11 +58,11 @@ config 6xx
help
There are four types of PowerPC chips supported. The more common
types (601, 603, 604, 740, 750, 7400), the Motorola embedded
- versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded
- versions (403 and 405) and the high end 64 bit Power processors
- (POWER 3, POWER4, and IBM 970 also known as G5)
+ versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM
+ embedded versions (403 and 405) and the POWER3 processor.
+ (For support for more recent 64-bit processors, set ARCH=powerpc.)
Unless you are building a kernel for one of the embedded processor
- systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
+ systems or a POWER3-based IBM RS/6000, choose 6xx.
Note that the kernel runs in 32-bit mode even on 64-bit chips.
Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
specific support for that chipset is asked later on.
@@ -80,10 +77,6 @@ config POWER3
select PPC_FPU
bool "POWER3"
-config POWER4
- select PPC_FPU
- bool "POWER4 and 970 (G5)"
-
config 8xx
bool "8xx"
@@ -126,7 +119,7 @@ config PHYS_64BIT
config ALTIVEC
bool "AltiVec Support"
- depends on 6xx || POWER4
+ depends on 6xx
depends on !8260 && !83xx
---help---
This option enables kernel support for the Altivec extensions to the
@@ -238,18 +231,9 @@ config KEXEC
source "drivers/cpufreq/Kconfig"
-config CPU_FREQ_PMAC
- bool "Support for Apple PowerBooks"
- depends on CPU_FREQ && ADB_PMU
- select CPU_FREQ_TABLE
- help
- This adds support for frequency switching on Apple PowerBooks,
- this currently includes some models of iBook & Titanium
- PowerBook.
-
config PPC601_SYNC_FIX
bool "Workarounds for PPC601 bugs"
- depends on 6xx && (PPC_PREP || PPC_PMAC)
+ depends on 6xx && PPC_PREP
help
Some versions of the PPC601 (the first PowerPC chip) have bugs which
mean that extra synchronization instructions are required near
@@ -261,26 +245,17 @@ 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
config PPC64BRIDGE
bool
- depends on POWER3 || POWER4
+ depends on POWER3
default y
config PPC_STD_MMU
bool
- depends on 6xx || POWER3 || POWER4
+ depends on 6xx || POWER3
default y
config NOT_COHERENT_CACHE
@@ -508,7 +483,7 @@ endchoice
choice
prompt "Machine Type"
- depends on 6xx || POWER3 || POWER4
+ depends on 6xx || POWER3
default PPC_MULTIPLATFORM
---help---
Linux currently supports several different kinds of PowerPC-based
@@ -519,11 +494,15 @@ choice
Platform) machines (including all of the recent IBM RS/6000 and
pSeries machines), and several embedded PowerPC systems containing
4xx, 6xx, 7xx, 8xx, 74xx, and 82xx processors. Currently, the
- default option is to build a kernel which works on the first three.
+ default option is to build a kernel which works on PReP and CHRP.
+
+ Note that support for Apple machines is now only available with
+ ARCH=powerpc, and has been removed from this menu. If you wish
+ to build a kernel for an Apple machine, exit this configuration
+ process and re-run it with ARCH=powerpc.
- Select CHRP/PowerMac/PReP if configuring for an IBM RS/6000 or
- pSeries machine, a Power Macintosh (including iMacs, iBooks and
- Powerbooks), or a PReP machine.
+ Select CHRP/PReP if configuring for an IBM RS/6000 or
+ pSeries machine, or a PReP machine.
Select Gemini if configuring for a Synergy Microsystems' Gemini
series Single Board Computer. More information is available at:
@@ -533,7 +512,7 @@ choice
available at: <http://linux-apus.sourceforge.net/>.
config PPC_MULTIPLATFORM
- bool "CHRP/PowerMac/PReP"
+ bool "CHRP/PReP"
config APUS
bool "Amiga-APUS"
@@ -746,6 +725,10 @@ config MPC834x
bool
default y if MPC834x_SYS
+config PPC_83xx
+ bool
+ default y if 83xx
+
config CPM1
bool
depends on 8xx
@@ -767,25 +750,14 @@ config CPM2
on it (826x, 827x, 8560).
config PPC_CHRP
- bool
+ bool "Support for CHRP (Common Hardware Reference Platform) machines"
depends on PPC_MULTIPLATFORM
select PPC_I8259
select PPC_INDIRECT_PCI
default y
-config PPC_PMAC
- bool
- depends on PPC_MULTIPLATFORM
- select PPC_INDIRECT_PCI
- default y
-
-config PPC_PMAC64
- bool
- depends on PPC_PMAC && POWER4
- default y
-
config PPC_PREP
- bool
+ bool "Support for PReP (PowerPC Reference Platform) machines"
depends on PPC_MULTIPLATFORM
select PPC_I8259
select PPC_INDIRECT_PCI
@@ -793,7 +765,7 @@ config PPC_PREP
config PPC_OF
bool
- depends on PPC_PMAC || PPC_CHRP
+ depends on PPC_CHRP
default y
config PPC_GEN550
@@ -1165,7 +1137,7 @@ config ISA
config GENERIC_ISA_DMA
bool
- depends on POWER3 || POWER4 || 6xx && !CPM2
+ depends on POWER3 || 6xx && !CPM2
default y
config PPC_I8259
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index e719a4933af1..98e940beeb3b 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -128,10 +128,9 @@ TOUT := .tmp_gas_check
# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
# instructions.
# gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION := $(call cc-version)
checkbin:
- @if test "$(GCC_VERSION)" = "0304" ; then \
+ @if test "$(call cc-version)" = "0304" ; then \
if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
echo 'correctly with gcc-3.4 and your version of binutils.'; \
diff --git a/arch/ppc/amiga/amiints.c b/arch/ppc/amiga/amiints.c
index 91195e2ce38d..5f35cf3986f7 100644
--- a/arch/ppc/amiga/amiints.c
+++ b/arch/ppc/amiga/amiints.c
@@ -96,8 +96,8 @@ void amiga_init_IRQ(void)
gayle.inten = GAYLE_IRQ_IDE;
/* turn off all interrupts... */
- custom.intena = 0x7fff;
- custom.intreq = 0x7fff;
+ amiga_custom.intena = 0x7fff;
+ amiga_custom.intreq = 0x7fff;
#ifdef CONFIG_APUS
/* Clear any inter-CPU interrupt requests. Circumvents bug in
@@ -110,7 +110,7 @@ void amiga_init_IRQ(void)
APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK);
#endif
/* ... and enable the master interrupt bit */
- custom.intena = IF_SETCLR | IF_INTEN;
+ amiga_custom.intena = IF_SETCLR | IF_INTEN;
cia_init_IRQ(&ciaa_base);
cia_init_IRQ(&ciab_base);
@@ -151,7 +151,7 @@ void amiga_enable_irq(unsigned int irq)
}
/* enable the interrupt */
- custom.intena = IF_SETCLR | ami_intena_vals[irq];
+ amiga_custom.intena = IF_SETCLR | ami_intena_vals[irq];
}
void amiga_disable_irq(unsigned int irq)
@@ -177,7 +177,7 @@ void amiga_disable_irq(unsigned int irq)
}
/* disable the interrupt */
- custom.intena = ami_intena_vals[irq];
+ amiga_custom.intena = ami_intena_vals[irq];
}
inline void amiga_do_irq(int irq, struct pt_regs *fp)
@@ -196,7 +196,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
kstat_cpu(0).irqs[irq]++;
- custom.intreq = ami_intena_vals[irq];
+ amiga_custom.intreq = ami_intena_vals[irq];
for (action = desc->action; action; action = action->next)
action->handler(irq, action->dev_id, fp);
@@ -208,40 +208,40 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp)
static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if serial transmit buffer empty, interrupt */
if (ints & IF_TBE) {
- custom.intreq = IF_TBE;
+ amiga_custom.intreq = IF_TBE;
amiga_do_irq(IRQ_AMIGA_TBE, fp);
}
/* if floppy disk transfer complete, interrupt */
if (ints & IF_DSKBLK) {
- custom.intreq = IF_DSKBLK;
+ amiga_custom.intreq = IF_DSKBLK;
amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
}
/* if software interrupt set, interrupt */
if (ints & IF_SOFT) {
- custom.intreq = IF_SOFT;
+ amiga_custom.intreq = IF_SOFT;
amiga_do_irq(IRQ_AMIGA_SOFT, fp);
}
}
static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if a blitter interrupt */
if (ints & IF_BLIT) {
- custom.intreq = IF_BLIT;
+ amiga_custom.intreq = IF_BLIT;
amiga_do_irq(IRQ_AMIGA_BLIT, fp);
}
/* if a copper interrupt */
if (ints & IF_COPER) {
- custom.intreq = IF_COPER;
+ amiga_custom.intreq = IF_COPER;
amiga_do_irq(IRQ_AMIGA_COPPER, fp);
}
@@ -252,36 +252,36 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if audio 0 interrupt */
if (ints & IF_AUD0) {
- custom.intreq = IF_AUD0;
+ amiga_custom.intreq = IF_AUD0;
amiga_do_irq(IRQ_AMIGA_AUD0, fp);
}
/* if audio 1 interrupt */
if (ints & IF_AUD1) {
- custom.intreq = IF_AUD1;
+ amiga_custom.intreq = IF_AUD1;
amiga_do_irq(IRQ_AMIGA_AUD1, fp);
}
/* if audio 2 interrupt */
if (ints & IF_AUD2) {
- custom.intreq = IF_AUD2;
+ amiga_custom.intreq = IF_AUD2;
amiga_do_irq(IRQ_AMIGA_AUD2, fp);
}
/* if audio 3 interrupt */
if (ints & IF_AUD3) {
- custom.intreq = IF_AUD3;
+ amiga_custom.intreq = IF_AUD3;
amiga_do_irq(IRQ_AMIGA_AUD3, fp);
}
}
static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
{
- unsigned short ints = custom.intreqr & custom.intenar;
+ unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
/* if serial receive buffer full interrupt */
if (ints & IF_RBF) {
@@ -291,7 +291,7 @@ static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
/* if a disk sync interrupt */
if (ints & IF_DSKSYN) {
- custom.intreq = IF_DSKSYN;
+ amiga_custom.intreq = IF_DSKSYN;
amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
}
}
diff --git a/arch/ppc/amiga/cia.c b/arch/ppc/amiga/cia.c
index ad961465b6cb..4431c58f611a 100644
--- a/arch/ppc/amiga/cia.c
+++ b/arch/ppc/amiga/cia.c
@@ -66,7 +66,7 @@ static unsigned char cia_set_irq_private(struct ciabase *base,
else
base->icr_data &= ~mask;
if (base->icr_data & base->icr_mask)
- custom.intreq = IF_SETCLR | base->int_mask;
+ amiga_custom.intreq = IF_SETCLR | base->int_mask;
return old & base->icr_mask;
}
@@ -114,7 +114,7 @@ static unsigned char cia_able_irq_private(struct ciabase *base,
base->icr_mask &= CIA_ICR_ALL;
if (base->icr_data & base->icr_mask)
- custom.intreq = IF_SETCLR | base->int_mask;
+ amiga_custom.intreq = IF_SETCLR | base->int_mask;
return old;
}
@@ -145,7 +145,7 @@ static void cia_handler(int irq, void *dev_id, struct pt_regs *fp)
irq = base->cia_irq;
desc = irq_desc + irq;
ints = cia_set_irq_private(base, CIA_ICR_ALL);
- custom.intreq = base->int_mask;
+ amiga_custom.intreq = base->int_mask;
for (i = 0; i < CIA_IRQS; i++, irq++) {
if (ints & 1) {
kstat_cpu(0).irqs[irq]++;
@@ -174,5 +174,5 @@ void __init cia_init_IRQ(struct ciabase *base)
action->name = base->name;
setup_irq(base->handler_irq, &amiga_sys_irqaction[base->handler_irq-IRQ_AMIGA_AUTO]);
- custom.intena = IF_SETCLR | base->int_mask;
+ amiga_custom.intena = IF_SETCLR | base->int_mask;
}
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index af881d7454dd..60e2da1c92c0 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -90,9 +90,6 @@ static void a3000_gettod (int *, int *, int *, int *, int *, int *);
static void a2000_gettod (int *, int *, int *, int *, int *, int *);
static int amiga_hwclk (int, struct hwclk_time *);
static int amiga_set_clock_mmss (unsigned long);
-#ifdef CONFIG_AMIGA_FLOPPY
-extern void amiga_floppy_setup(char *, int *);
-#endif
static void amiga_reset (void);
extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
@@ -281,7 +278,7 @@ static void __init amiga_identify(void)
case CS_OCS:
case CS_ECS:
case CS_AGA:
- switch (custom.deniseid & 0xf) {
+ switch (amiga_custom.deniseid & 0xf) {
case 0x0c:
AMIGAHW_SET(DENISE_HR);
break;
@@ -294,7 +291,7 @@ static void __init amiga_identify(void)
AMIGAHW_SET(DENISE);
break;
}
- switch ((custom.vposr>>8) & 0x7f) {
+ switch ((amiga_custom.vposr>>8) & 0x7f) {
case 0x00:
AMIGAHW_SET(AGNUS_PAL);
break;
@@ -419,9 +416,6 @@ void __init config_amiga(void)
mach_hwclk = amiga_hwclk;
mach_set_clock_mmss = amiga_set_clock_mmss;
-#ifdef CONFIG_AMIGA_FLOPPY
- mach_floppy_setup = amiga_floppy_setup;
-#endif
mach_reset = amiga_reset;
#ifdef CONFIG_HEARTBEAT
mach_heartbeat = amiga_heartbeat;
@@ -432,9 +426,9 @@ void __init config_amiga(void)
amiga_colorclock = 5*amiga_eclock; /* 3.5 MHz */
/* clear all DMA bits */
- custom.dmacon = DMAF_ALL;
+ amiga_custom.dmacon = DMAF_ALL;
/* ensure that the DMA master bit is set */
- custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+ amiga_custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
/* request all RAM */
for (i = 0; i < m68k_num_memory; i++) {
@@ -753,9 +747,9 @@ static void amiga_savekmsg_init(void)
static void amiga_serial_putc(char c)
{
- custom.serdat = (unsigned char)c | 0x100;
+ amiga_custom.serdat = (unsigned char)c | 0x100;
mb();
- while (!(custom.serdatr & 0x2000))
+ while (!(amiga_custom.serdatr & 0x2000))
;
}
@@ -785,11 +779,11 @@ int amiga_serial_console_wait_key(struct console *co)
{
int ch;
- while (!(custom.intreqr & IF_RBF))
+ while (!(amiga_custom.intreqr & IF_RBF))
barrier();
- ch = custom.serdatr & 0xff;
+ ch = amiga_custom.serdatr & 0xff;
/* clear the interrupt, so that another character can be read */
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
return ch;
}
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 995f89bb049c..efd8ce515d5f 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -18,7 +18,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd
bootdir-y := simple
bootdir-$(CONFIG_PPC_OF) += openfirmware
subdir-y := lib common images
-subdir-$(CONFIG_PPC_OF) += of1275
+subdir-$(CONFIG_PPC_MULTIPLATFORM) += of1275
# for cleaning
subdir- += simple openfirmware
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
index c96c9f80521e..368ec035e6cd 100644
--- a/arch/ppc/boot/common/util.S
+++ b/arch/ppc/boot/common/util.S
@@ -234,7 +234,8 @@ udelay:
* First, flush the data cache in case it was enabled and may be
* holding instructions for copy back.
*/
-_GLOBAL(flush_instruction_cache)
+ .globl flush_instruction_cache
+flush_instruction_cache:
mflr r6
bl flush_data_cache
@@ -279,7 +280,8 @@ _GLOBAL(flush_instruction_cache)
* Flush data cache
* Do this by just reading lots of stuff into the cache.
*/
-_GLOBAL(flush_data_cache)
+ .globl flush_data_cache
+flush_data_cache:
lis r3,cache_flush_buffer@h
ori r3,r3,cache_flush_buffer@l
li r4,NUM_CACHE_LINES
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index 532e7ef1edb6..58415d5718e3 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -26,7 +26,7 @@ quiet_cmd_uimage = UIMAGE $@
targets += uImage
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
- $(call if_changed,uimage)
+ $(call cmd,uimage)
@echo -n ' Image: $@ '
@if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
index 83a6433459ce..2a411ec2e650 100644
--- a/arch/ppc/boot/openfirmware/Makefile
+++ b/arch/ppc/boot/openfirmware/Makefile
@@ -21,26 +21,16 @@ bootlib := $(boot)/lib
of1275 := $(boot)/of1275
images := $(boot)/images
-OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
-COFF_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00500000 \
- -Bstatic
CHRP_LD_ARGS := -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x00800000
-NEWWORLD_LD_ARGS:= -T $(srctree)/$(boot)/ld.script -e _start -Ttext 0x01000000
COMMONOBJS := start.o misc.o common.o
-COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o
CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o
-NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o
-targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o
-COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS))
+targets := $(CHRPOBJS) dummy.o
CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS))
-NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS))
LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a
-HACKCOFF := $(utils)/hack-coff
-
ifdef CONFIG_SMP
END := .smp
endif
@@ -72,56 +62,11 @@ targets += image.initrd.o
$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE
$(call if_changed,genimage-initrd)
-# Create the note section for New-World PowerMacs.
-quiet_cmd_mknote = MKNOTE $@
- cmd_mknote = $(utils)/mknote > $@
-targets += note
-$(obj)/note: $(utils)/mknote FORCE
- $(call if_changed,mknote)
-
-$(obj)/coffcrt0.o: EXTRA_AFLAGS := -DXCOFF
-targets += coffcrt0.o crt0.o
-$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE
+targets += crt0.o
+$(obj)/crt0.o: $(common)/crt0.S FORCE
$(call if_changed_dep,as_o_S)
-quiet_cmd_gencoffb = COFF $@
- cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(COFFOBJS) $< $(LIBS) && \
- $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
-targets += coffboot
-$(obj)/coffboot: $(obj)/image.o $(COFFOBJS) $(LIBS) $(srctree)/$(boot)/ld.script FORCE
- $(call if_changed,gencoffb)
-targets += coffboot.initrd
-$(obj)/coffboot.initrd: $(obj)/image.initrd.o $(COFFOBJS) $(LIBS) \
- $(srctree)/$(boot)/ld.script FORCE
- $(call if_changed,gencoffb)
-
-
-quiet_cmd_gen-coff = COFF $@
- cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \
- $(HACKCOFF) $@ && \
- ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac
-
-$(images)/vmlinux.coff: $(obj)/coffboot
- $(call cmd,gen-coff)
-
-$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd
- $(call cmd,gen-coff)
-
-quiet_cmd_gen-elf-pmac = ELF $@
- cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \
- $(NEWWORLDOBJS) $(LIBS) $< && \
- $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \
- -R .comment $(del-ramdisk-sec)
-
-$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) \
- $(obj)/note $(srctree)/$(boot)/ld.script
- $(call cmd,gen-elf-pmac)
-$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \
- $(LIBS) $(obj)/note \
- $(srctree)/$(boot)/ld.script
- $(call cmd,gen-elf-pmac)
-
quiet_cmd_gen-chrp = CHRP $@
cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $(CHRPOBJS) $< $(LIBS) && \
$(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec)
@@ -139,46 +84,23 @@ $(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \
%-rs6k: %
$(call cmd,addnote)
-quiet_cmd_gen-miboot = GEN $@
- cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \
- --add-section=$1=$(word 2, $^) $< $@
-$(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz
- $(call cmd,gen-miboot,image)
-
-$(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz
- $(call cmd,gen-miboot,initrd)
-
# The targets used on the make command-line
.PHONY: zImage zImage.initrd
-zImage: $(images)/vmlinux.coff \
- $(images)/vmlinux.elf-pmac \
- $(images)/zImage.chrp \
- $(images)/zImage.chrp-rs6k \
- $(images)/miboot.image
+zImage: $(images)/zImage.chrp \
+ $(images)/zImage.chrp-rs6k
@echo ' kernel: $@ is ready ($<)'
-zImage.initrd: $(images)/vmlinux.initrd.coff \
- $(images)/vmlinux.initrd.elf-pmac \
- $(images)/zImage.initrd.chrp \
- $(images)/zImage.initrd.chrp-rs6k \
- $(images)/miboot.initrd.image
+zImage.initrd: $(images)/zImage.initrd.chrp \
+ $(images)/zImage.initrd.chrp-rs6k
@echo ' kernel: $@ is ready ($<)'
TFTPIMAGE := /tftpboot/zImage
.PHONY: znetboot znetboot.initrd
-znetboot: $(images)/vmlinux.coff \
- $(images)/vmlinux.elf-pmac \
- $(images)/zImage.chrp
- cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END)
- cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+znetboot: $(images)/zImage.chrp
cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END)
@echo ' kernel: $@ is ready ($<)'
-znetboot.initrd:$(images)/vmlinux.initrd.coff \
- $(images)/vmlinux.initrd.elf-pmac \
- $(images)/zImage.initrd.chrp
- cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END)
- cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf
+znetboot.initrd:$(images)/zImage.initrd.chrp
cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END)
@echo ' kernel: $@ is ready ($<)'
diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c
deleted file mode 100644
index 2da8855e2be0..000000000000
--- a/arch/ppc/boot/openfirmware/coffmain.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/string.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-
-#include "nonstdio.h"
-#include "of1275.h"
-
-/* Passed from the linker */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin[], __ramdisk_end;
-extern char _start, _end;
-
-extern char image_data[], initrd_data[];
-extern int initrd_len, image_len;
-extern unsigned int heap_max;
-extern void flush_cache(void *start, unsigned int len);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned int progend);
-extern void setup_bats(unsigned long start);
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-
-#define SCRATCH_SIZE (128 << 10)
-
-static char heap[SCRATCH_SIZE];
-
-static unsigned long ram_start = 0;
-static unsigned long ram_end = 0x1000000;
-
-static unsigned long prog_start = 0x800000;
-static unsigned long prog_size = 0x700000;
-
-typedef void (*kernel_start_t)(int, int, void *);
-
-void boot(int a1, int a2, void *prom)
-{
- unsigned sa, len;
- void *dst;
- unsigned char *im;
- unsigned initrd_start, initrd_size;
-
- printf("coffboot starting: loaded at 0x%p\n", &_start);
- setup_bats(ram_start);
-
- initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
- if (initrd_size) {
- initrd_start = (ram_end - initrd_size) & ~0xFFF;
- a1 = initrd_start;
- a2 = initrd_size;
- claim(initrd_start, ram_end - initrd_start, 0);
- printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
- initrd_start, (char *)(&__ramdisk_begin), initrd_size);
- memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
- prog_size = initrd_start - prog_start;
- } else
- a2 = 0xdeadbeef;
-
- im = (char *)(&__image_begin);
- len = (char *)(&__image_end) - (char *)(&__image_begin);
- /* claim 4MB starting at PROG_START */
- claim(prog_start, prog_size, 0);
- map(prog_start, prog_start, prog_size);
- dst = (void *) prog_start;
- if (im[0] == 0x1f && im[1] == 0x8b) {
- /* set up scratch space */
- begin_avail = avail_high = avail_ram = heap;
- end_avail = heap + sizeof(heap);
- printf("heap at 0x%p\n", avail_ram);
- printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
- gunzip(dst, prog_size, im, &len);
- printf("done %u bytes\n", len);
- printf("%u bytes of heap consumed, max in use %u\n",
- avail_high - begin_avail, heap_max);
- } else {
- memmove(dst, im, len);
- }
-
- flush_cache(dst, len);
- make_bi_recs(((unsigned long) dst + len), "coffboot", _MACH_Pmac,
- (prog_start + prog_size));
-
- sa = (unsigned long)prog_start;
- printf("start address = 0x%x\n", sa);
-
- (*(kernel_start_t)sa)(a1, a2, prom);
-
- printf("returned?\n");
-
- pause();
-}
diff --git a/arch/ppc/boot/openfirmware/newworldmain.c b/arch/ppc/boot/openfirmware/newworldmain.c
deleted file mode 100644
index fa8a8f9313f9..000000000000
--- a/arch/ppc/boot/openfirmware/newworldmain.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/string.h>
-#include "nonstdio.h"
-#include "of1275.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-
-/* Passed from the linker */
-extern char __image_begin, __image_end;
-extern char __ramdisk_begin[], __ramdisk_end;
-extern char _start, _end;
-
-extern unsigned int heap_max;
-extern void flush_cache(void *start, unsigned int len);
-extern void gunzip(void *, int, unsigned char *, int *);
-extern void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
- unsigned int progend);
-
-char *avail_ram;
-char *begin_avail, *end_avail;
-char *avail_high;
-
-
-#define RAM_END (16 << 20)
-
-#define PROG_START 0x00010000
-#define PROG_SIZE 0x007f0000
-
-#define SCRATCH_SIZE (128 << 10)
-
-typedef void (*kernel_start_t)(int, int, void *);
-
-void boot(int a1, int a2, void *prom)
-{
- unsigned sa, len;
- void *dst;
- unsigned char *im;
- unsigned initrd_start, initrd_size;
-
- printf("chrpboot starting: loaded at 0x%p\n", &_start);
-
- initrd_size = (char *)(&__ramdisk_end) - (char *)(&__ramdisk_begin);
- if (initrd_size) {
- initrd_start = (RAM_END - initrd_size) & ~0xFFF;
- a1 = initrd_start;
- a2 = initrd_size;
- claim(initrd_start, RAM_END - initrd_start, 0);
- printf("initial ramdisk moving 0x%x <- 0x%p (%x bytes)\n\r",
- initrd_start, (char *)(&__ramdisk_begin), initrd_size);
- memcpy((char *)initrd_start, (char *)(&__ramdisk_begin), initrd_size);
- } else
- a2 = 0xdeadbeef;
-
- im = (char *)(&__image_begin);
- len = (char *)(&__image_end) - (char *)(&__image_begin);
- /* claim 3MB starting at PROG_START */
- claim(PROG_START, PROG_SIZE, 0);
- dst = (void *) PROG_START;
- if (im[0] == 0x1f && im[1] == 0x8b) {
- /* claim some memory for scratch space */
- avail_ram = (char *) claim(0, SCRATCH_SIZE, 0x10);
- begin_avail = avail_high = avail_ram;
- end_avail = avail_ram + SCRATCH_SIZE;
- printf("heap at 0x%p\n", avail_ram);
- printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
- gunzip(dst, PROG_SIZE, im, &len);
- printf("done %u bytes\n", len);
- printf("%u bytes of heap consumed, max in use %u\n",
- avail_high - begin_avail, heap_max);
- release(begin_avail, SCRATCH_SIZE);
- } else {
- memmove(dst, im, len);
- }
-
- flush_cache(dst, len);
- make_bi_recs(((unsigned long) dst + len), "chrpboot", _MACH_Pmac,
- (PROG_START + PROG_SIZE));
-
- sa = (unsigned long)PROG_START;
- printf("start address = 0x%x\n", sa);
-
- (*(kernel_start_t)sa)(a1, a2, prom);
-
- printf("returned?\n");
-
- pause();
-}
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index f3e9c534aa82..9533f8de238f 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -190,6 +190,8 @@ boot-$(CONFIG_REDWOOD_5) += embed_config.o
boot-$(CONFIG_REDWOOD_6) += embed_config.o
boot-$(CONFIG_8xx) += embed_config.o
boot-$(CONFIG_8260) += embed_config.o
+boot-$(CONFIG_EP405) += embed_config.o
+boot-$(CONFIG_XILINX_ML300) += embed_config.o
boot-$(CONFIG_BSEIP) += iic.o
boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o
boot-$(CONFIG_MV64X60) += misc-mv64x60.o
diff --git a/arch/ppc/configs/TQM8540_defconfig b/arch/ppc/configs/TQM8540_defconfig
new file mode 100644
index 000000000000..99bf3b7a2762
--- /dev/null
+++ b/arch/ppc/configs/TQM8540_defconfig
@@ -0,0 +1,973 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc2
+# Fri Nov 25 17:26:50 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=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 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
+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 is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_E500=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_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_GEN550=y
+CONFIG_85xx=y
+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 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+CONFIG_TQM8540=y
+# CONFIG_TQM8541 is not set
+# CONFIG_TQM8555 is not set
+# CONFIG_TQM8560 is not set
+CONFIG_MPC8540=y
+
+#
+# Platform options
+#
+# 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_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_RAPIDIO 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
+
+#
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=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=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# 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 is not set
+CONFIG_MTD_TQM85xx=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_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
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X 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 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 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_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT 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_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# 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_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# 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
+# 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=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_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=y
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# 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_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/TQM8541_defconfig b/arch/ppc/configs/TQM8541_defconfig
new file mode 100644
index 000000000000..0ff56695d349
--- /dev/null
+++ b/arch/ppc/configs/TQM8541_defconfig
@@ -0,0 +1,986 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc2
+# Wed Nov 30 13:36:28 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=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 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
+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 is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_E500=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_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_GEN550=y
+CONFIG_85xx=y
+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 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+CONFIG_TQM8541=y
+# CONFIG_TQM8555 is not set
+# CONFIG_TQM8560 is not set
+CONFIG_MPC8555=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD 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_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD 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
+
+#
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=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=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# 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 is not set
+CONFIG_MTD_TQM85xx=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_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
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X 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 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_FS_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT 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_SERIAL_CPM is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_MPC8260 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_MAX6900 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8563 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_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# 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
+# 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=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_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=y
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# 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_KGDB_CONSOLE is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/TQM8555_defconfig b/arch/ppc/configs/TQM8555_defconfig
new file mode 100644
index 000000000000..730b3db2e47a
--- /dev/null
+++ b/arch/ppc/configs/TQM8555_defconfig
@@ -0,0 +1,983 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc2
+# Thu Nov 24 17:10:52 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=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 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
+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 is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_E500=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_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_GEN550=y
+CONFIG_85xx=y
+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 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+# CONFIG_TQM8541 is not set
+CONFIG_TQM8555=y
+# CONFIG_TQM8560 is not set
+CONFIG_MPC8555=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD 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_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD 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
+
+#
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=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=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# 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 is not set
+CONFIG_MTD_TQM85xx=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_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
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X 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 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_FS_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT 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_SERIAL_CPM is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# 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_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# 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
+# 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=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_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=y
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# 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_KGDB_CONSOLE is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/TQM8560_defconfig b/arch/ppc/configs/TQM8560_defconfig
new file mode 100644
index 000000000000..1d902072825e
--- /dev/null
+++ b/arch/ppc/configs/TQM8560_defconfig
@@ -0,0 +1,992 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-rc2
+# Wed Nov 30 16:47:53 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=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 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
+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 is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_E500=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_WANT_EARLY_SERIAL is not set
+CONFIG_85xx=y
+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 is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+# CONFIG_TQM8540 is not set
+# CONFIG_TQM8541 is not set
+# CONFIG_TQM8555 is not set
+CONFIG_TQM8560=y
+CONFIG_MPC8560=y
+
+#
+# Platform options
+#
+CONFIG_CPM2=y
+# CONFIG_PC_KEYBOARD 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_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_LEGACY_PROC is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_RAPIDIO 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
+
+#
+# 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_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=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=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# 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 is not set
+CONFIG_MTD_TQM85xx=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_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
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X 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 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# 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
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# 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 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_FS_ENET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT 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_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+CONFIG_SERIAL_CPM_SCC1=y
+# 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 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
+
+#
+# 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_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_MPC8260 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_MAX6900 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8563 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_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# 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
+# 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=y
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_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=y
+
+#
+# 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
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+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'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_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_RELAYFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+# CONFIG_SCC_ENET is not set
+# CONFIG_FEC_ENET is not set
+
+#
+# CPM2 Options
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+# 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_KGDB_CONSOLE is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig
index 0ba4e70d50b6..41fd3938fa5c 100644
--- a/arch/ppc/configs/bamboo_defconfig
+++ b/arch/ppc/configs/bamboo_defconfig
@@ -499,6 +499,7 @@ CONFIG_NATSEMI=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig
index 0f3bb9af9c22..7311fe6b42de 100644
--- a/arch/ppc/configs/katana_defconfig
+++ b/arch/ppc/configs/katana_defconfig
@@ -488,6 +488,7 @@ CONFIG_E100=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
index 673dc64ebcb1..b96a6d6dad0e 100644
--- a/arch/ppc/configs/mpc834x_sys_defconfig
+++ b/arch/ppc/configs/mpc834x_sys_defconfig
@@ -402,6 +402,7 @@ CONFIG_E100=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
index 93da595a4738..a1ef929bca59 100644
--- a/arch/ppc/configs/power3_defconfig
+++ b/arch/ppc/configs/power3_defconfig
@@ -442,6 +442,7 @@ CONFIG_E100=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 0bb23fce4293..e399bbb969a4 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -9,16 +9,13 @@ extra-$(CONFIG_44x) := head_44x.o
extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
extra-$(CONFIG_8xx) := head_8xx.o
extra-$(CONFIG_6xx) += idle_6xx.o
-extra-$(CONFIG_POWER4) += idle_power4.o
extra-y += vmlinux.lds
obj-y := entry.o traps.o idle.o time.o misc.o \
- process.o \
setup.o \
ppc_htab.o
obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
-obj-$(CONFIG_POWER4) += cpu_setup_power4.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
obj-$(CONFIG_PCI) += pci.o
@@ -43,11 +40,9 @@ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
-obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_TAU) += temp.o
ifndef CONFIG_E200
obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
endif
-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
endif
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index fe0e767fb94e..7964bf660e92 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -131,7 +131,7 @@ main(void)
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
- DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
+ DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index f044edbb454f..a48b950722a1 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall)
bl do_show_syscall
#endif /* SHOW_SYSCALLS */
rlwinm r10,r1,0,0,18 /* current_thread_info() */
- li r11,0
- stb r11,TI_SC_NOERR(r10)
lwz r11,TI_FLAGS(r10)
andi. r11,r11,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
@@ -222,25 +220,21 @@ ret_from_syscall:
bl do_show_syscall_exit
#endif
mr r6,r3
- li r11,-_LAST_ERRNO
- cmplw 0,r3,r11
rlwinm r12,r1,0,0,18 /* current_thread_info() */
- blt+ 30f
- lbz r11,TI_SC_NOERR(r12)
- cmpwi r11,0
- bne 30f
- neg r3,r3
- lwz r10,_CCR(r1) /* Set SO bit in CR */
- oris r10,r10,0x1000
- stw r10,_CCR(r1)
-
/* disable interrupts so current_thread_info()->flags can't change */
-30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10)
lwz r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ li r8,-_LAST_ERRNO
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne- syscall_exit_work
+ cmplw 0,r3,r8
+ blt+ syscall_exit_cont
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
/* If the process has its own DBCR0 value, load it up. The single
@@ -292,46 +286,113 @@ syscall_dotrace:
b syscall_dotrace_cont
syscall_exit_work:
- stw r6,RESULT(r1) /* Save result */
+ andi. r0,r9,_TIF_RESTOREALL
+ bne- 2f
+ cmplw 0,r3,r8
+ blt+ 1f
+ andi. r0,r9,_TIF_NOERROR
+ bne- 1f
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
+
+1: stw r6,RESULT(r1) /* Save result */
stw r3,GPR3(r1) /* Update return value */
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq 5f
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10) /* re-enable interrupts */
+2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+ beq 4f
+
+ /* Clear per-syscall TIF flags if any are set, but _leave_
+ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
+ yet. */
+
+ li r11,_TIF_PERSYSCALL_MASK
+ addi r12,r12,TI_FLAGS
+3: lwarx r8,0,r12
+ andc r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+ dcbt 0,r12
+#endif
+ stwcx. r8,0,r12
+ bne- 3b
+ subi r12,r12,TI_FLAGS
+
+4: /* Anything which requires enabling interrupts? */
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
+ beq 7f
+
+ /* Save NVGPRS if they're not saved already */
lwz r4,TRAP(r1)
andi. r4,r4,1
- beq 4f
+ beq 5f
SAVE_NVGPRS(r1)
li r4,0xc00
stw r4,TRAP(r1)
-4:
+
+ /* Re-enable interrupts */
+5: ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10)
+
+ andi. r0,r9,_TIF_SAVE_NVGPRS
+ bne save_user_nvgprs
+
+save_user_nvgprs_cont:
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+ beq 7f
+
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_leave
REST_NVGPRS(r1)
-2:
- lwz r3,GPR3(r1)
+
+6: lwz r3,GPR3(r1)
LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10) /* disable interrupts again */
rlwinm r12,r1,0,0,18 /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
-5:
+7:
andi. r0,r9,_TIF_NEED_RESCHED
- bne 1f
+ bne 8f
lwz r5,_MSR(r1)
andi. r5,r5,MSR_PR
- beq syscall_exit_cont
+ beq ret_from_except
andi. r0,r9,_TIF_SIGPENDING
- beq syscall_exit_cont
+ beq ret_from_except
b do_user_signal
-1:
+8:
ori r10,r10,MSR_EE
SYNC
MTMSRD(r10) /* re-enable interrupts */
bl schedule
- b 2b
+ b 6b
+
+save_user_nvgprs:
+ lwz r8,TI_SIGFRAME(r12)
+
+.macro savewords start, end
+ 1: stw \start,4*(\start)(r8)
+ .section __ex_table,"a"
+ .align 2
+ .long 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savewords "(\start+1)",\end
+ .endif
+.endm
+ savewords 14,31
+ b save_user_nvgprs_cont
+
+
+save_user_nvgprs_fault:
+ li r3,11 /* SIGSEGV */
+ lwz r4,TI_TASK(r12)
+ bl force_sigsegv
+ rlwinm r12,r1,0,0,18 /* current_thread_info() */
+ lwz r9,TI_FLAGS(r12)
+ b save_user_nvgprs_cont
+
#ifdef SHOW_SYSCALLS
do_show_syscall:
#ifdef SHOW_SYSCALLS_TASK
@@ -401,28 +462,10 @@ show_syscalls_task:
#endif /* SHOW_SYSCALLS */
/*
- * The sigsuspend and rt_sigsuspend system calls can call do_signal
- * and thus put the process into the stopped state where we might
- * want to examine its user state with ptrace. Therefore we need
- * to save all the nonvolatile registers (r13 - r31) before calling
- * the C code.
+ * The fork/clone functions need to copy the full register set into
+ * the child process. Therefore we need to save all the nonvolatile
+ * registers (r13 - r31) before calling the C code.
*/
- .globl ppc_sigsuspend
-ppc_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_sigsuspend
-
- .globl ppc_rt_sigsuspend
-ppc_rt_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30
- stw r0,TRAP(r1)
- b sys_rt_sigsuspend
-
.globl ppc_fork
ppc_fork:
SAVE_NVGPRS(r1)
@@ -447,14 +490,6 @@ ppc_clone:
stw r0,TRAP(r1) /* register set saved */
b sys_clone
- .globl ppc_swapcontext
-ppc_swapcontext:
- SAVE_NVGPRS(r1)
- lwz r0,TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,TRAP(r1) /* register set saved */
- b sys_swapcontext
-
/*
* Top-level page fault handling.
* This is in assembler because if do_page_fault tells us that
@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
.long ret_from_except
#endif
- .globl sigreturn_exit
-sigreturn_exit:
- subi r1,r3,STACK_FRAME_OVERHEAD
- rlwinm r12,r1,0,0,18 /* current_thread_info() */
- lwz r9,TI_FLAGS(r12)
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq+ ret_from_except_full
- bl do_syscall_trace_leave
- /* fall through */
-
.globl ret_from_except_full
ret_from_except_full:
REST_NVGPRS(r1)
@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
/* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,18
lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne do_work
restore_user:
diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S
index de0978742221..3e6ca7f5843f 100644
--- a/arch/ppc/kernel/head_8xx.S
+++ b/arch/ppc/kernel/head_8xx.S
@@ -375,6 +375,8 @@ DataStoreTLBMiss:
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
rlwimi r10, r11, 0, 2, 19
+ stw r12, 16(r0)
+ b LoadLargeDTLB
3:
lwz r11, 0(r10) /* Get the level 1 entry */
rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
@@ -430,6 +432,81 @@ DataStoreTLBMiss:
InstructionTLBError:
b InstructionAccess
+LoadLargeDTLB:
+ li r12, 0
+ lwz r11, 0(r10) /* Get the level 1 entry */
+ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */
+ beq 3f /* If zero, don't try to find a pte */
+
+ /* We have a pte table, so load fetch the pte from the table.
+ */
+ ori r11, r11, 1 /* Set valid bit in physical L2 page */
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11 /* Load pte table base address */
+ mfspr r10, SPRN_MD_TWC /* ....and get the pte address */
+ lwz r10, 0(r10) /* Get the pte */
+
+ /* Insert the Guarded flag into the TWC from the Linux PTE.
+ * It is bit 27 of both the Linux PTE and the TWC (at least
+ * I got that right :-). It will be better when we can put
+ * this into the Linux pgd/pmd and load it in the operation
+ * above.
+ */
+ rlwimi r11, r10, 0, 27, 27
+
+ rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */
+ mfspr r3, SPRN_MD_EPN
+ rlwinm r3, r3, 0, 0, 9 /* extract virtual address */
+ tophys(r3, r3)
+ cmpw r3, r12 /* only use 8M page if it is a direct
+ kernel mapping */
+ bne 1f
+ ori r11, r11, MD_PS8MEG
+ li r12, 1
+ b 2f
+1:
+ li r12, 0 /* can't use 8MB TLB, so zero r12. */
+2:
+ DO_8xx_CPU6(0x3b80, r3)
+ mtspr SPRN_MD_TWC, r11
+
+ /* The Linux PTE won't go exactly into the MMU TLB.
+ * Software indicator bits 21, 22 and 28 must be clear.
+ * Software indicator bits 24, 25, 26, and 27 must be
+ * set. All other Linux PTE bits control the behavior
+ * of the MMU.
+ */
+3: li r11, 0x00f0
+ rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */
+ cmpwi r12, 1
+ bne 4f
+ ori r10, r10, 0x8
+
+ mfspr r12, SPRN_MD_EPN
+ lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
+ ori r3, r3, 0x0fff
+ and r12, r3, r12
+ DO_8xx_CPU6(0x3780, r3)
+ mtspr SPRN_MD_EPN, r12
+
+ lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */
+ ori r3, r3, 0x0fff
+ and r10, r3, r10
+4:
+ DO_8xx_CPU6(0x3d80, r3)
+ mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
+
+ mfspr r10, SPRN_M_TW /* Restore registers */
+ lwz r11, 0(r0)
+ mtcr r11
+ lwz r11, 4(r0)
+
+ lwz r12, 16(r0)
+#ifdef CONFIG_8xx_CPU6
+ lwz r3, 8(r0)
+#endif
+ rfi
+
/* This is the data TLB error on the MPC8xx. This could be due to
* many reasons, including a dirty update to a pte. We can catch that
* one here, but anything else is an error. First, we track down the
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 821a75e45602..1be3ca5bae40 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -37,7 +37,6 @@
void default_idle(void)
{
void (*powersave)(void);
- int cpu = smp_processor_id();
powersave = ppc_md.power_save;
@@ -47,7 +46,8 @@ void default_idle(void)
#ifdef CONFIG_SMP
else {
set_thread_flag(TIF_POLLING_NRFLAG);
- while (!need_resched() && !cpu_is_offline(cpu))
+ while (!need_resched() &&
+ !cpu_is_offline(smp_processor_id()))
barrier();
clear_thread_flag(TIF_POLLING_NRFLAG);
}
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
index a882b0dbe8de..84d65a87191e 100644
--- a/arch/ppc/kernel/machine_kexec.c
+++ b/arch/ppc/kernel/machine_kexec.c
@@ -28,12 +28,6 @@ typedef NORET_TYPE void (*relocate_new_kernel_t)(
const extern unsigned char relocate_new_kernel[];
const extern unsigned int relocate_new_kernel_size;
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-note_buf_t crash_notes[NR_CPUS];
-
void machine_shutdown(void)
{
if (ppc_md.machine_shutdown)
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 5e61124581d0..c3427eed8345 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -204,78 +204,6 @@ _GLOBAL(call_setup_cpu)
mtctr r5
bctr
-#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx)
-
-/* This gets called by via-pmu.c to switch the PLL selection
- * on 750fx CPU. This function should really be moved to some
- * other place (as most of the cpufreq code in via-pmu
- */
-_GLOBAL(low_choose_750fx_pll)
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* If switching to PLL1, disable HID0:BTIC */
- cmplwi cr0,r3,0
- beq 1f
- mfspr r5,SPRN_HID0
- rlwinm r5,r5,0,27,25
- sync
- mtspr SPRN_HID0,r5
- isync
- sync
-
-1:
- /* Calc new HID1 value */
- mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */
- rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */
- rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */
- or r4,r4,r5
- mtspr SPRN_HID1,r4
-
- /* Store new HID1 image */
- rlwinm r6,r1,0,0,18
- lwz r6,TI_CPU(r6)
- slwi r6,r6,2
- addis r6,r6,nap_save_hid1@ha
- stw r4,nap_save_hid1@l(r6)
-
- /* If switching to PLL0, enable HID0:BTIC */
- cmplwi cr0,r3,0
- bne 1f
- mfspr r5,SPRN_HID0
- ori r5,r5,HID0_BTIC
- sync
- mtspr SPRN_HID0,r5
- isync
- sync
-
-1:
- /* Return */
- mtmsr r7
- blr
-
-_GLOBAL(low_choose_7447a_dfs)
- /* Clear MSR:EE */
- mfmsr r7
- rlwinm r0,r7,0,17,15
- mtmsr r0
-
- /* Calc new HID1 value */
- mfspr r4,SPRN_HID1
- insrwi r4,r3,1,9 /* insert parameter into bit 9 */
- sync
- mtspr SPRN_HID1,r4
- sync
- isync
-
- /* Return */
- mtmsr r7
- blr
-
-#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */
-
/*
* complement mask on the msr then "or" some values on.
* _nmask_and_or_msr(nmask, value_to_or)
@@ -1197,7 +1125,7 @@ _GLOBAL(sys_call_table)
.long sys_ssetmask
.long sys_setreuid /* 70 */
.long sys_setregid
- .long ppc_sigsuspend
+ .long sys_sigsuspend
.long sys_sigpending
.long sys_sethostname
.long sys_setrlimit /* 75 */
@@ -1303,7 +1231,7 @@ _GLOBAL(sys_call_table)
.long sys_rt_sigpending /* 175 */
.long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo
- .long ppc_rt_sigsuspend
+ .long sys_rt_sigsuspend
.long sys_pread64
.long sys_pwrite64 /* 180 */
.long sys_chown
@@ -1374,7 +1302,7 @@ _GLOBAL(sys_call_table)
.long sys_clock_gettime
.long sys_clock_getres
.long sys_clock_nanosleep
- .long ppc_swapcontext
+ .long sys_swapcontext
.long sys_tgkill /* 250 */
.long sys_utimes
.long sys_statfs64
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index f7fae5f153b2..04d04c5bfdd0 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * Common pmac/prep/chrp pci routines. -- Cort
+ * Common prep/chrp pci routines. -- Cort
*/
#include <linux/config.h>
@@ -50,8 +50,7 @@ static void fixup_cpc710_pci64(struct pci_dev* dev);
static u8* pci_to_OF_bus_map;
#endif
-/* By default, we don't re-assign bus numbers. We do this only on
- * some pmacs
+/* By default, we don't re-assign bus numbers.
*/
int pci_assign_all_buses;
@@ -503,7 +502,7 @@ pcibios_allocate_resources(int pass)
u16 command;
struct resource *r;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ for_each_pci_dev(dev) {
pci_read_config_word(dev, PCI_COMMAND, &command);
for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
@@ -540,7 +539,7 @@ pcibios_assign_resources(void)
int idx;
struct resource *r;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+ for_each_pci_dev(dev) {
int class = dev->class >> 8;
/* Don't touch classless devices and host bridges */
@@ -780,17 +779,6 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
return NULL;
/* Fixup bus number according to what OF think it is. */
-#ifdef CONFIG_PPC_PMAC
- /* The G5 need a special case here. Basically, we don't remap all
- * busses on it so we don't create the pci-OF-map. However, we do
- * remap the AGP bus and so have to deal with it. A future better
- * fix has to be done by making the remapping per-host and always
- * filling the pci_to_OF map. --BenH
- */
- if (_machine == _MACH_Pmac && busnr >= 0xf0)
- busnr -= 0xf0;
- else
-#endif
if (pci_to_OF_bus_map)
busnr = pci_to_OF_bus_map[busnr];
if (busnr == 0xff)
@@ -815,8 +803,7 @@ EXPORT_SYMBOL(pci_device_to_OF_node);
* to set pci_assign_all_buses to 1 and still use RTAS for PCI
* config cycles.
*/
-struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node* node)
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
{
if (!have_of)
return NULL;
@@ -868,14 +855,15 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
*/
if (!pci_to_OF_bus_map)
return 0;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if (pci_to_OF_bus_map[dev->bus->number] != *bus)
- continue;
- if (dev->devfn != *devfn)
- continue;
- *bus = dev->bus->number;
- return 0;
- }
+
+ for_each_pci_dev(dev)
+ if (pci_to_OF_bus_map[dev->bus->number] == *bus &&
+ dev->devfn == *devfn) {
+ *bus = dev->bus->number;
+ pci_dev_put(dev);
+ return 0;
+ }
+
return -ENODEV;
}
EXPORT_SYMBOL(pci_device_from_OF_node);
@@ -942,7 +930,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
res = NULL;
size = ranges[na+4];
- switch (ranges[0] >> 24) {
+ switch ((ranges[0] >> 24) & 0x3) {
case 1: /* I/O space */
if (ranges[2] != 0)
break;
@@ -956,6 +944,8 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
res = &hose->io_resource;
res->flags = IORESOURCE_IO;
res->start = ranges[2];
+ DBG("PCI: IO 0x%lx -> 0x%lx\n",
+ res->start, res->start + size - 1);
break;
case 2: /* memory space */
memno = 0;
@@ -973,7 +963,11 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
if (memno < 3) {
res = &hose->mem_resources[memno];
res->flags = IORESOURCE_MEM;
+ if(ranges[0] & 0x40000000)
+ res->flags |= IORESOURCE_PREFETCH;
res->start = ranges[na+2];
+ DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
+ res->start, res->start + size - 1);
}
break;
}
@@ -1034,216 +1028,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev)
}
-#ifdef CONFIG_PPC_PMAC
-/*
- * This set of routines checks for PCI<->PCI bridges that have closed
- * IO resources and have child devices. It tries to re-open an IO
- * window on them.
- *
- * This is a _temporary_ fix to workaround a problem with Apple's OF
- * closing IO windows on P2P bridges when the OF drivers of cards
- * below this bridge don't claim any IO range (typically ATI or
- * Adaptec).
- *
- * A more complete fix would be to use drivers/pci/setup-bus.c, which
- * involves a working pcibios_fixup_pbus_ranges(), some more care about
- * ordering when creating the host bus resources, and maybe a few more
- * minor tweaks
- */
-
-/* Initialize bridges with base/limit values we have collected */
-static void __init
-do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga)
-{
- struct pci_dev *bridge = bus->self;
- struct pci_controller* hose = (struct pci_controller *)bridge->sysdata;
- u32 l;
- u16 w;
- struct resource res;
-
- if (bus->resource[0] == NULL)
- return;
- res = *(bus->resource[0]);
-
- DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
- res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
- res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
- DBG(" IO window: %08lx-%08lx\n", res.start, res.end);
-
- /* Set up the top and bottom of the PCI I/O segment for this bus. */
- pci_read_config_dword(bridge, PCI_IO_BASE, &l);
- l &= 0xffff000f;
- l |= (res.start >> 8) & 0x00f0;
- l |= res.end & 0xf000;
- pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
- if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
- l = (res.start >> 16) | (res.end & 0xffff0000);
- pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l);
- }
-
- pci_read_config_word(bridge, PCI_COMMAND, &w);
- w |= PCI_COMMAND_IO;
- pci_write_config_word(bridge, PCI_COMMAND, w);
-
-#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */
- if (enable_vga) {
- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w);
- w |= PCI_BRIDGE_CTL_VGA;
- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w);
- }
-#endif
-}
-
-/* This function is pretty basic and actually quite broken for the
- * general case, it's enough for us right now though. It's supposed
- * to tell us if we need to open an IO range at all or not and what
- * size.
- */
-static int __init
-check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga)
-{
- struct pci_dev *dev;
- int i;
- int rc = 0;
-
-#define push_end(res, size) do { unsigned long __sz = (size) ; \
- res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
- } while (0)
-
- list_for_each_entry(dev, &bus->devices, bus_list) {
- u16 class = dev->class >> 8;
-
- if (class == PCI_CLASS_DISPLAY_VGA ||
- class == PCI_CLASS_NOT_DEFINED_VGA)
- *found_vga = 1;
- if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate)
- rc |= check_for_io_childs(dev->subordinate, res, found_vga);
- if (class == PCI_CLASS_BRIDGE_CARDBUS)
- push_end(res, 0xfff);
-
- for (i=0; i<PCI_NUM_RESOURCES; i++) {
- struct resource *r;
- unsigned long r_size;
-
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI
- && i >= PCI_BRIDGE_RESOURCES)
- continue;
- r = &dev->resource[i];
- r_size = r->end - r->start;
- if (r_size < 0xfff)
- r_size = 0xfff;
- if (r->flags & IORESOURCE_IO && (r_size) != 0) {
- rc = 1;
- push_end(res, r_size);
- }
- }
- }
-
- return rc;
-}
-
-/* Here we scan all P2P bridges of a given level that have a closed
- * IO window. Note that the test for the presence of a VGA card should
- * be improved to take into account already configured P2P bridges,
- * currently, we don't see them and might end up configuring 2 bridges
- * with VGA pass through enabled
- */
-static void __init
-do_fixup_p2p_level(struct pci_bus *bus)
-{
- struct pci_bus *b;
- int i, parent_io;
- int has_vga = 0;
-
- for (parent_io=0; parent_io<4; parent_io++)
- if (bus->resource[parent_io]
- && bus->resource[parent_io]->flags & IORESOURCE_IO)
- break;
- if (parent_io >= 4)
- return;
-
- list_for_each_entry(b, &bus->children, node) {
- struct pci_dev *d = b->self;
- struct pci_controller* hose = (struct pci_controller *)d->sysdata;
- struct resource *res = b->resource[0];
- struct resource tmp_res;
- unsigned long max;
- int found_vga = 0;
-
- memset(&tmp_res, 0, sizeof(tmp_res));
- tmp_res.start = bus->resource[parent_io]->start;
-
- /* We don't let low addresses go through that closed P2P bridge, well,
- * that may not be necessary but I feel safer that way
- */
- if (tmp_res.start == 0)
- tmp_res.start = 0x1000;
-
- if (!list_empty(&b->devices) && res && res->flags == 0 &&
- res != bus->resource[parent_io] &&
- (d->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
- check_for_io_childs(b, &tmp_res, &found_vga)) {
- u8 io_base_lo;
-
- printk(KERN_INFO "Fixing up IO bus %s\n", b->name);
-
- if (found_vga) {
- if (has_vga) {
- printk(KERN_WARNING "Skipping VGA, already active"
- " on bus segment\n");
- found_vga = 0;
- } else
- has_vga = 1;
- }
- pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo);
-
- if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32)
- max = ((unsigned long) hose->io_base_virt
- - isa_io_base) + 0xffffffff;
- else
- max = ((unsigned long) hose->io_base_virt
- - isa_io_base) + 0xffff;
-
- *res = tmp_res;
- res->flags = IORESOURCE_IO;
- res->name = b->name;
-
- /* Find a resource in the parent where we can allocate */
- for (i = 0 ; i < 4; i++) {
- struct resource *r = bus->resource[i];
- if (!r)
- continue;
- if ((r->flags & IORESOURCE_IO) == 0)
- continue;
- DBG("Trying to allocate from %08lx, size %08lx from parent"
- " res %d: %08lx -> %08lx\n",
- res->start, res->end, i, r->start, r->end);
-
- if (allocate_resource(r, res, res->end + 1, res->start, max,
- res->end + 1, NULL, NULL) < 0) {
- DBG("Failed !\n");
- continue;
- }
- do_update_p2p_io_resource(b, found_vga);
- break;
- }
- }
- do_fixup_p2p_level(b);
- }
-}
-
-static void
-pcibios_fixup_p2p_bridges(void)
-{
- struct pci_bus *b;
-
- list_for_each_entry(b, &pci_root_buses, node)
- do_fixup_p2p_level(b);
-}
-
-#endif /* CONFIG_PPC_PMAC */
-
static int __init
pcibios_init(void)
{
@@ -1284,9 +1068,6 @@ pcibios_init(void)
pcibios_allocate_bus_resources(&pci_root_buses);
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
-#ifdef CONFIG_PPC_PMAC
- pcibios_fixup_p2p_bridges();
-#endif /* CONFIG_PPC_PMAC */
pcibios_assign_resources();
/* Call machine dependent post-init code */
@@ -1716,17 +1497,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
struct pci_controller* hose;
long result = -EOPNOTSUPP;
- /* 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 (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))
- if (bus == 0)
- bus = 0xf0;
-#endif /* CONFIG_PPC_PMAC */
-
hose = pci_bus_to_hose(bus);
if (!hose)
return -ENODEV;
@@ -1806,6 +1576,23 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
EXPORT_SYMBOL(pci_iomap);
EXPORT_SYMBOL(pci_iounmap);
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ struct pci_controller* hose = hose_head;
+
+ for (; hose; hose = hose->next) {
+ unsigned int size = hose->io_resource.end -
+ hose->io_resource.start + 1;
+ if (address >= hose->io_base_phys &&
+ address < (hose->io_base_phys + size)) {
+ unsigned long base =
+ (unsigned long)hose->io_base_virt - _IO_BASE;
+ return base + (address - hose->io_base_phys);
+ }
+ }
+ return (unsigned int)-1;
+}
+EXPORT_SYMBOL(pci_address_to_pio);
/*
* Null PCI config access functions, for the case when we can't
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index ca810025993f..2f5c7650274f 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -16,6 +16,7 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/sysctl.h>
+#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/threads.h>
#include <linux/smp_lock.h>
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index bb6a5c6a64be..3a6e4bcb3c53 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -34,7 +34,6 @@
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
-#include <asm/pmac_feature.h>
#include <asm/dma.h>
#include <asm/machdep.h>
#include <asm/hw_irq.h>
@@ -58,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs);
extern void alignment_exception(struct pt_regs *regs);
extern void program_check_exception(struct pt_regs *regs);
extern void single_step_exception(struct pt_regs *regs);
-extern int pmac_newworld;
extern int sys_sigreturn(struct pt_regs *regs);
long long __ashrdi3(long long, int);
@@ -82,10 +80,6 @@ EXPORT_SYMBOL(ppc_n_lost_interrupts);
EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
EXPORT_SYMBOL(DMA_MODE_READ);
EXPORT_SYMBOL(DMA_MODE_WRITE);
-#if defined(CONFIG_PPC_PREP)
-EXPORT_SYMBOL(_prep_type);
-EXPORT_SYMBOL(ucSystemType);
-#endif
#if !defined(__INLINE_BITOPS)
EXPORT_SYMBOL(set_bit);
@@ -217,10 +211,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
EXPORT_SYMBOL(cuda_request);
EXPORT_SYMBOL(cuda_poll);
#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_PPC_PMAC
-EXPORT_SYMBOL(sys_ctrler);
-EXPORT_SYMBOL(pmac_newworld);
-#endif
#ifdef CONFIG_PPC_OF
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
@@ -245,9 +235,6 @@ EXPORT_SYMBOL(of_node_put);
#if defined(CONFIG_BOOTX_TEXT)
EXPORT_SYMBOL(btext_update_display);
#endif
-#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC)
-EXPORT_SYMBOL(note_scsi_host);
-#endif
#ifdef CONFIG_VT
EXPORT_SYMBOL(kd_mksound);
#endif
@@ -274,7 +261,6 @@ EXPORT_SYMBOL(__delay);
EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(tb_ticks_per_jiffy);
-EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
#ifdef CONFIG_XMON
EXPORT_SYMBOL(xmon);
@@ -311,7 +297,6 @@ EXPORT_SYMBOL(__res);
EXPORT_SYMBOL(next_mmu_context);
EXPORT_SYMBOL(set_context);
-EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */
EXPORT_SYMBOL(disarm_decr);
#ifdef CONFIG_PPC_STD_MMU
extern long mol_trampoline;
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
deleted file mode 100644
index 25cbdc8d2941..000000000000
--- a/arch/ppc/kernel/process.c
+++ /dev/null
@@ -1,851 +0,0 @@
-/*
- * arch/ppc/kernel/process.c
- *
- * Derived from "arch/i386/kernel/process.c"
- * Copyright (C) 1995 Linus Torvalds
- *
- * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and
- * Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/elf.h>
-#include <linux/init.h>
-#include <linux/prctl.h>
-#include <linux/init_task.h>
-#include <linux/module.h>
-#include <linux/kallsyms.h>
-#include <linux/mqueue.h>
-#include <linux/hardirq.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/mmu.h>
-#include <asm/prom.h>
-
-extern unsigned long _get_SP(void);
-
-struct task_struct *last_task_used_math = NULL;
-struct task_struct *last_task_used_altivec = NULL;
-struct task_struct *last_task_used_spe = NULL;
-
-static struct fs_struct init_fs = INIT_FS;
-static struct files_struct init_files = INIT_FILES;
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-struct mm_struct init_mm = INIT_MM(init_mm);
-EXPORT_SYMBOL(init_mm);
-
-/* this is 8kB-aligned so we can get to the thread_info struct
- at the base of it from the stack pointer with 1 integer instruction. */
-union thread_union init_thread_union
- __attribute__((__section__(".data.init_task"))) =
-{ INIT_THREAD_INFO(init_task) };
-
-/* initial task structure */
-struct task_struct init_task = INIT_TASK(init_task);
-EXPORT_SYMBOL(init_task);
-
-/* only used to get secondary processor up */
-struct task_struct *current_set[NR_CPUS] = {&init_task, };
-
-#undef SHOW_TASK_SWITCHES
-#undef CHECK_STACK
-
-#if defined(CHECK_STACK)
-unsigned long
-kernel_stack_top(struct task_struct *tsk)
-{
- return ((unsigned long)tsk) + sizeof(union task_union);
-}
-
-unsigned long
-task_top(struct task_struct *tsk)
-{
- return ((unsigned long)tsk) + sizeof(struct thread_info);
-}
-
-/* check to make sure the kernel stack is healthy */
-int check_stack(struct task_struct *tsk)
-{
- unsigned long stack_top = kernel_stack_top(tsk);
- unsigned long tsk_top = task_top(tsk);
- int ret = 0;
-
-#if 0
- /* check thread magic */
- if ( tsk->thread.magic != THREAD_MAGIC )
- {
- ret |= 1;
- printk("thread.magic bad: %08x\n", tsk->thread.magic);
- }
-#endif
-
- if ( !tsk )
- printk("check_stack(): tsk bad tsk %p\n",tsk);
-
- /* check if stored ksp is bad */
- if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) )
- {
- printk("stack out of bounds: %s/%d\n"
- " tsk_top %08lx ksp %08lx stack_top %08lx\n",
- tsk->comm,tsk->pid,
- tsk_top, tsk->thread.ksp, stack_top);
- ret |= 2;
- }
-
- /* check if stack ptr RIGHT NOW is bad */
- if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) )
- {
- printk("current stack ptr out of bounds: %s/%d\n"
- " tsk_top %08lx sp %08lx stack_top %08lx\n",
- current->comm,current->pid,
- tsk_top, _get_SP(), stack_top);
- ret |= 4;
- }
-
-#if 0
- /* check amount of free stack */
- for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ )
- {
- if ( !i )
- printk("check_stack(): i = %p\n", i);
- if ( *i != 0 )
- {
- /* only notify if it's less than 900 bytes */
- if ( (i - (unsigned long *)task_top(tsk)) < 900 )
- printk("%d bytes free on stack\n",
- i - task_top(tsk));
- break;
- }
- }
-#endif
-
- if (ret)
- {
- panic("bad kernel stack");
- }
- return(ret);
-}
-#endif /* defined(CHECK_STACK) */
-
-/*
- * Make sure the floating-point register state in the
- * the thread_struct is up to date for task tsk.
- */
-void flush_fp_to_thread(struct task_struct *tsk)
-{
- if (tsk->thread.regs) {
- /*
- * We need to disable preemption here because if we didn't,
- * another process could get scheduled after the regs->msr
- * test but before we have finished saving the FP registers
- * to the thread_struct. That process could take over the
- * FPU, and then when we get scheduled again we would store
- * bogus values for the remaining FP registers.
- */
- preempt_disable();
- if (tsk->thread.regs->msr & MSR_FP) {
-#ifdef CONFIG_SMP
- /*
- * This should only ever be called for current or
- * for a stopped child process. Since we save away
- * the FP register state on context switch on SMP,
- * there is something wrong if a stopped child appears
- * to still have its FP state in the CPU registers.
- */
- BUG_ON(tsk != current);
-#endif
- giveup_fpu(current);
- }
- preempt_enable();
- }
-}
-
-void enable_kernel_fp(void)
-{
- WARN_ON(preemptible());
-
-#ifdef CONFIG_SMP
- if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
- giveup_fpu(current);
- else
- giveup_fpu(NULL); /* just enables FP for kernel */
-#else
- giveup_fpu(last_task_used_math);
-#endif /* CONFIG_SMP */
-}
-EXPORT_SYMBOL(enable_kernel_fp);
-
-int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
-{
- preempt_disable();
- if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP))
- giveup_fpu(tsk);
- preempt_enable();
- memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs));
- return 1;
-}
-
-#ifdef CONFIG_ALTIVEC
-void enable_kernel_altivec(void)
-{
- WARN_ON(preemptible());
-
-#ifdef CONFIG_SMP
- if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
- giveup_altivec(current);
- else
- giveup_altivec(NULL); /* just enable AltiVec for kernel - force */
-#else
- giveup_altivec(last_task_used_altivec);
-#endif /* __SMP __ */
-}
-EXPORT_SYMBOL(enable_kernel_altivec);
-
-/*
- * Make sure the VMX/Altivec register state in the
- * the thread_struct is up to date for task tsk.
- */
-void flush_altivec_to_thread(struct task_struct *tsk)
-{
- if (tsk->thread.regs) {
- preempt_disable();
- if (tsk->thread.regs->msr & MSR_VEC) {
-#ifdef CONFIG_SMP
- BUG_ON(tsk != current);
-#endif
- giveup_altivec(current);
- }
- preempt_enable();
- }
-}
-
-int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
-{
- if (regs->msr & MSR_VEC)
- giveup_altivec(current);
- memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
- return 1;
-}
-#endif /* CONFIG_ALTIVEC */
-
-#ifdef CONFIG_SPE
-void
-enable_kernel_spe(void)
-{
- WARN_ON(preemptible());
-
-#ifdef CONFIG_SMP
- if (current->thread.regs && (current->thread.regs->msr & MSR_SPE))
- giveup_spe(current);
- else
- giveup_spe(NULL); /* just enable SPE for kernel - force */
-#else
- giveup_spe(last_task_used_spe);
-#endif /* __SMP __ */
-}
-EXPORT_SYMBOL(enable_kernel_spe);
-
-void flush_spe_to_thread(struct task_struct *tsk)
-{
- if (tsk->thread.regs) {
- preempt_disable();
- if (tsk->thread.regs->msr & MSR_SPE) {
-#ifdef CONFIG_SMP
- BUG_ON(tsk != current);
-#endif
- giveup_spe(current);
- }
- preempt_enable();
- }
-}
-
-int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
-{
- if (regs->msr & MSR_SPE)
- giveup_spe(current);
- /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
- memcpy(evrregs, &current->thread.evr[0], sizeof(u32) * 35);
- return 1;
-}
-#endif /* CONFIG_SPE */
-
-struct task_struct *__switch_to(struct task_struct *prev,
- struct task_struct *new)
-{
- struct thread_struct *new_thread, *old_thread;
- unsigned long s;
- struct task_struct *last;
-
- local_irq_save(s);
-#ifdef CHECK_STACK
- check_stack(prev);
- check_stack(new);
-#endif
-
-#ifdef CONFIG_SMP
- /* avoid complexity of lazy save/restore of fpu
- * by just saving it every time we switch out if
- * this task used the fpu during the last quantum.
- *
- * If it tries to use the fpu again, it'll trap and
- * reload its fp regs. So we don't have to do a restore
- * every switch, just a save.
- * -- Cort
- */
- if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
- giveup_fpu(prev);
-#ifdef CONFIG_ALTIVEC
- /*
- * If the previous thread used altivec in the last quantum
- * (thus changing altivec regs) then save them.
- * We used to check the VRSAVE register but not all apps
- * set it, so we don't rely on it now (and in fact we need
- * to save & restore VSCR even if VRSAVE == 0). -- paulus
- *
- * On SMP we always save/restore altivec regs just to avoid the
- * complexity of changing processors.
- * -- Cort
- */
- if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)))
- giveup_altivec(prev);
-#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SPE
- /*
- * If the previous thread used spe in the last quantum
- * (thus changing spe regs) then save them.
- *
- * On SMP we always save/restore spe regs just to avoid the
- * complexity of changing processors.
- */
- if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE)))
- giveup_spe(prev);
-#endif /* CONFIG_SPE */
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_ALTIVEC
- /* Avoid the trap. On smp this this never happens since
- * we don't set last_task_used_altivec -- Cort
- */
- if (new->thread.regs && last_task_used_altivec == new)
- new->thread.regs->msr |= MSR_VEC;
-#endif
-#ifdef CONFIG_SPE
- /* Avoid the trap. On smp this this never happens since
- * we don't set last_task_used_spe
- */
- if (new->thread.regs && last_task_used_spe == new)
- new->thread.regs->msr |= MSR_SPE;
-#endif /* CONFIG_SPE */
- new_thread = &new->thread;
- old_thread = &current->thread;
- last = _switch(old_thread, new_thread);
- local_irq_restore(s);
- return last;
-}
-
-void show_regs(struct pt_regs * regs)
-{
- int i, trap;
-
- printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n",
- regs->nip, regs->link, regs->gpr[1], regs, regs->trap,
- print_tainted());
- printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
- regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
- regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
- regs->msr&MSR_IR ? 1 : 0,
- regs->msr&MSR_DR ? 1 : 0);
- trap = TRAP(regs);
- if (trap == 0x300 || trap == 0x600)
- printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr);
- printk("TASK = %p[%d] '%s' THREAD: %p\n",
- current, current->pid, current->comm, current->thread_info);
- printk("Last syscall: %ld ", current->thread.last_syscall);
-
-#ifdef CONFIG_SMP
- printk(" CPU: %d", smp_processor_id());
-#endif /* CONFIG_SMP */
-
- for (i = 0; i < 32; i++) {
- long r;
- if ((i % 8) == 0)
- printk("\n" KERN_INFO "GPR%02d: ", i);
- if (__get_user(r, &regs->gpr[i]))
- break;
- printk("%08lX ", r);
- if (i == 12 && !FULL_REGS(regs))
- break;
- }
- printk("\n");
-#ifdef CONFIG_KALLSYMS
- /*
- * Lookup NIP late so we have the best change of getting the
- * above info out without failing
- */
- printk("NIP [%08lx] ", regs->nip);
- print_symbol("%s\n", regs->nip);
- printk("LR [%08lx] ", regs->link);
- print_symbol("%s\n", regs->link);
-#endif
- show_stack(current, (unsigned long *) regs->gpr[1]);
-}
-
-void exit_thread(void)
-{
- preempt_disable();
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- if (last_task_used_altivec == current)
- last_task_used_altivec = NULL;
-#ifdef CONFIG_SPE
- if (last_task_used_spe == current)
- last_task_used_spe = NULL;
-#endif
- preempt_enable();
-}
-
-void flush_thread(void)
-{
- preempt_disable();
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- if (last_task_used_altivec == current)
- last_task_used_altivec = NULL;
-#ifdef CONFIG_SPE
- if (last_task_used_spe == current)
- last_task_used_spe = NULL;
-#endif
- preempt_enable();
-}
-
-void
-release_thread(struct task_struct *t)
-{
-}
-
-/*
- * This gets called before we allocate a new thread and copy
- * the current task into it.
- */
-void prepare_to_copy(struct task_struct *tsk)
-{
- struct pt_regs *regs = tsk->thread.regs;
-
- if (regs == NULL)
- return;
- preempt_disable();
- if (regs->msr & MSR_FP)
- giveup_fpu(current);
-#ifdef CONFIG_ALTIVEC
- if (regs->msr & MSR_VEC)
- giveup_altivec(current);
-#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SPE
- if (regs->msr & MSR_SPE)
- giveup_spe(current);
-#endif /* CONFIG_SPE */
- preempt_enable();
-}
-
-/*
- * Copy a thread..
- */
-int
-copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
- unsigned long unused,
- struct task_struct *p, struct pt_regs *regs)
-{
- struct pt_regs *childregs, *kregs;
- extern void ret_from_fork(void);
- unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE;
- unsigned long childframe;
-
- CHECK_FULL_REGS(regs);
- /* Copy registers */
- sp -= sizeof(struct pt_regs);
- childregs = (struct pt_regs *) sp;
- *childregs = *regs;
- if ((childregs->msr & MSR_PR) == 0) {
- /* for kernel thread, set `current' and stackptr in new task */
- childregs->gpr[1] = sp + sizeof(struct pt_regs);
- childregs->gpr[2] = (unsigned long) p;
- p->thread.regs = NULL; /* no user register state */
- } else {
- childregs->gpr[1] = usp;
- p->thread.regs = childregs;
- if (clone_flags & CLONE_SETTLS)
- childregs->gpr[2] = childregs->gpr[6];
- }
- childregs->gpr[3] = 0; /* Result from fork() */
- sp -= STACK_FRAME_OVERHEAD;
- childframe = sp;
-
- /*
- * The way this works is that at some point in the future
- * some task will call _switch to switch to the new task.
- * That will pop off the stack frame created below and start
- * the new task running at ret_from_fork. The new task will
- * do some house keeping and then return from the fork or clone
- * system call, using the stack frame created above.
- */
- sp -= sizeof(struct pt_regs);
- kregs = (struct pt_regs *) sp;
- sp -= STACK_FRAME_OVERHEAD;
- p->thread.ksp = sp;
- kregs->nip = (unsigned long)ret_from_fork;
-
- p->thread.last_syscall = -1;
-
- return 0;
-}
-
-/*
- * Set up a thread for executing a new program
- */
-void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
-{
- set_fs(USER_DS);
- memset(regs->gpr, 0, sizeof(regs->gpr));
- regs->ctr = 0;
- regs->link = 0;
- regs->xer = 0;
- regs->ccr = 0;
- regs->mq = 0;
- regs->nip = nip;
- regs->gpr[1] = sp;
- regs->msr = MSR_USER;
- preempt_disable();
- if (last_task_used_math == current)
- last_task_used_math = NULL;
- if (last_task_used_altivec == current)
- last_task_used_altivec = NULL;
-#ifdef CONFIG_SPE
- if (last_task_used_spe == current)
- last_task_used_spe = NULL;
-#endif
- preempt_enable();
- memset(current->thread.fpr, 0, sizeof(current->thread.fpr));
- current->thread.fpscr.val = 0;
-#ifdef CONFIG_ALTIVEC
- memset(current->thread.vr, 0, sizeof(current->thread.vr));
- memset(&current->thread.vscr, 0, sizeof(current->thread.vscr));
- current->thread.vrsave = 0;
- current->thread.used_vr = 0;
-#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SPE
- memset(current->thread.evr, 0, sizeof(current->thread.evr));
- current->thread.acc = 0;
- current->thread.spefscr = 0;
- current->thread.used_spe = 0;
-#endif /* CONFIG_SPE */
-}
-
-#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \
- | PR_FP_EXC_RES | PR_FP_EXC_INV)
-
-int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
-{
- struct pt_regs *regs = tsk->thread.regs;
-
- /* This is a bit hairy. If we are an SPE enabled processor
- * (have embedded fp) we store the IEEE exception enable flags in
- * fpexc_mode. fpexc_mode is also used for setting FP exception
- * mode (asyn, precise, disabled) for 'Classic' FP. */
- if (val & PR_FP_EXC_SW_ENABLE) {
-#ifdef CONFIG_SPE
- tsk->thread.fpexc_mode = val &
- (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT);
-#else
- return -EINVAL;
-#endif
- } else {
- /* on a CONFIG_SPE this does not hurt us. The bits that
- * __pack_fe01 use do not overlap with bits used for
- * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits
- * on CONFIG_SPE implementations are reserved so writing to
- * them does not change anything */
- if (val > PR_FP_EXC_PRECISE)
- return -EINVAL;
- tsk->thread.fpexc_mode = __pack_fe01(val);
- if (regs != NULL && (regs->msr & MSR_FP) != 0)
- regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1))
- | tsk->thread.fpexc_mode;
- }
- return 0;
-}
-
-int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
-{
- unsigned int val;
-
- if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
-#ifdef CONFIG_SPE
- val = tsk->thread.fpexc_mode;
-#else
- return -EINVAL;
-#endif
- else
- val = __unpack_fe01(tsk->thread.fpexc_mode);
- return put_user(val, (unsigned int __user *) adr);
-}
-
-int sys_clone(unsigned long clone_flags, unsigned long usp,
- int __user *parent_tidp, void __user *child_threadptr,
- int __user *child_tidp, int p6,
- struct pt_regs *regs)
-{
- CHECK_FULL_REGS(regs);
- if (usp == 0)
- usp = regs->gpr[1]; /* stack pointer for child */
- return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
-}
-
-int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs)
-{
- CHECK_FULL_REGS(regs);
- return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);
-}
-
-int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
- unsigned long p4, unsigned long p5, unsigned long p6,
- struct pt_regs *regs)
-{
- CHECK_FULL_REGS(regs);
- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],
- regs, 0, NULL, NULL);
-}
-
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs *regs)
-{
- int error;
- char * filename;
-
- filename = getname((char __user *) a0);
- error = PTR_ERR(filename);
- if (IS_ERR(filename))
- goto out;
- preempt_disable();
- if (regs->msr & MSR_FP)
- giveup_fpu(current);
-#ifdef CONFIG_ALTIVEC
- if (regs->msr & MSR_VEC)
- giveup_altivec(current);
-#endif /* CONFIG_ALTIVEC */
-#ifdef CONFIG_SPE
- if (regs->msr & MSR_SPE)
- giveup_spe(current);
-#endif /* CONFIG_SPE */
- preempt_enable();
- error = do_execve(filename, (char __user *__user *) a1,
- (char __user *__user *) a2, regs);
- if (error == 0) {
- task_lock(current);
- current->ptrace &= ~PT_DTRACE;
- task_unlock(current);
- }
- putname(filename);
-out:
- return error;
-}
-
-void dump_stack(void)
-{
- show_stack(current, NULL);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
-void show_stack(struct task_struct *tsk, unsigned long *stack)
-{
- unsigned long sp, stack_top, prev_sp, ret;
- int count = 0;
- unsigned long next_exc = 0;
- struct pt_regs *regs;
- extern char ret_from_except, ret_from_except_full, ret_from_syscall;
-
- sp = (unsigned long) stack;
- if (tsk == NULL)
- tsk = current;
- if (sp == 0) {
- if (tsk == current)
- asm("mr %0,1" : "=r" (sp));
- else
- sp = tsk->thread.ksp;
- }
-
- prev_sp = (unsigned long) (tsk->thread_info + 1);
- stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE;
- while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) {
- if (count == 0) {
- printk("Call trace:");
-#ifdef CONFIG_KALLSYMS
- printk("\n");
-#endif
- } else {
- if (next_exc) {
- ret = next_exc;
- next_exc = 0;
- } else
- ret = *(unsigned long *)(sp + 4);
- printk(" [%08lx] ", ret);
-#ifdef CONFIG_KALLSYMS
- print_symbol("%s", ret);
- printk("\n");
-#endif
- if (ret == (unsigned long) &ret_from_except
- || ret == (unsigned long) &ret_from_except_full
- || ret == (unsigned long) &ret_from_syscall) {
- /* sp + 16 points to an exception frame */
- regs = (struct pt_regs *) (sp + 16);
- if (sp + 16 + sizeof(*regs) <= stack_top)
- next_exc = regs->nip;
- }
- }
- ++count;
- sp = *(unsigned long *)sp;
- }
-#ifndef CONFIG_KALLSYMS
- if (count > 0)
- printk("\n");
-#endif
-}
-
-#if 0
-/*
- * Low level print for debugging - Cort
- */
-int __init ll_printk(const char *fmt, ...)
-{
- va_list args;
- char buf[256];
- int i;
-
- va_start(args, fmt);
- i=vsprintf(buf,fmt,args);
- ll_puts(buf);
- va_end(args);
- return i;
-}
-
-int lines = 24, cols = 80;
-int orig_x = 0, orig_y = 0;
-
-void puthex(unsigned long val)
-{
- unsigned char buf[10];
- int i;
- for (i = 7; i >= 0; i--)
- {
- buf[i] = "0123456789ABCDEF"[val & 0x0F];
- val >>= 4;
- }
- buf[8] = '\0';
- prom_print(buf);
-}
-
-void __init ll_puts(const char *s)
-{
- int x,y;
- char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
- char c;
- extern int mem_init_done;
-
- if ( mem_init_done ) /* assume this means we can printk */
- {
- printk(s);
- return;
- }
-
-#if 0
- if ( have_of )
- {
- prom_print(s);
- return;
- }
-#endif
-
- /*
- * can't ll_puts on chrp without openfirmware yet.
- * vidmem just needs to be setup for it.
- * -- Cort
- */
- if ( _machine != _MACH_prep )
- return;
- x = orig_x;
- y = orig_y;
-
- while ( ( c = *s++ ) != '\0' ) {
- if ( c == '\n' ) {
- x = 0;
- if ( ++y >= lines ) {
- /*scroll();*/
- /*y--;*/
- y = 0;
- }
- } else {
- vidmem [ ( x + cols * y ) * 2 ] = c;
- if ( ++x >= cols ) {
- x = 0;
- if ( ++y >= lines ) {
- /*scroll();*/
- /*y--;*/
- y = 0;
- }
- }
- }
- }
-
- orig_x = x;
- orig_y = y;
-}
-#endif
-
-unsigned long get_wchan(struct task_struct *p)
-{
- unsigned long ip, sp;
- unsigned long stack_page = (unsigned long) p->thread_info;
- int count = 0;
- if (!p || p == current || p->state == TASK_RUNNING)
- return 0;
- sp = p->thread.ksp;
- do {
- sp = *(unsigned long *)sp;
- if (sp < stack_page || sp >= stack_page + 8188)
- return 0;
- if (count > 0) {
- ip = *(unsigned long *)(sp + 4);
- if (!in_sched_functions(ip))
- return ip;
- }
- } while (count++ < 16);
- return 0;
-}
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 0eb0b7085e6a..c08ab432e958 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,5 +1,5 @@
/*
- * Common prep/pmac/chrp boot and setup code.
+ * Common prep/chrp boot and setup code.
*/
#include <linux/config.h>
@@ -35,7 +35,6 @@
#include <asm/machdep.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/pmac_feature.h>
#include <asm/sections.h>
#include <asm/nvram.h>
#include <asm/xmon.h>
@@ -55,7 +54,6 @@
extern void platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
-extern void bootx_init(unsigned long r4, unsigned long phys);
extern void identify_cpu(unsigned long offset, unsigned long cpu);
extern void do_cpu_ftr_fixups(unsigned long offset);
extern void reloc_got2(unsigned long offset);
@@ -80,8 +78,6 @@ EXPORT_SYMBOL(_machine);
extern void prep_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
-extern void pmac_init(unsigned long r3, unsigned long r4,
- unsigned long r5, unsigned long r6, unsigned long r7);
extern void chrp_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7);
@@ -324,20 +320,15 @@ early_init(int r3, int r4, int r5)
identify_cpu(offset, 0);
do_cpu_ftr_fixups(offset);
-#if defined(CONFIG_PPC_MULTIPLATFORM)
+#if defined(CONFIG_PPC_OF)
reloc_got2(offset);
- /* If we came here from BootX, clear the screen,
- * set up some pointers and return. */
- if ((r3 == 0x426f6f58) && (r5 == 0))
- bootx_init(r4, phys);
-
/*
* don't do anything on prep
* for now, don't use bootinfo because it breaks yaboot 0.5
* and assume that if we didn't find a magic number, we have OF
*/
- else if (*(unsigned long *)(0) != 0xdeadc0de)
+ if (*(unsigned long *)(0) != 0xdeadc0de)
phys = prom_init(r3, r4, (prom_entry)r5);
reloc_got2(-offset);
@@ -424,6 +415,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
#endif
+#ifdef CONFIG_PPC_OF
have_of = 1;
/* prom_init has already been called from __start */
@@ -495,19 +487,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif /* CONFIG_ADB */
switch (_machine) {
-#ifdef CONFIG_PPC_PMAC
- case _MACH_Pmac:
- pmac_init(r3, r4, r5, r6, r7);
- break;
-#endif
#ifdef CONFIG_PPC_CHRP
case _MACH_chrp:
chrp_init(r3, r4, r5, r6, r7);
break;
#endif
}
+#endif /* CONFIG_PPC_OF */
}
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+#ifdef CONFIG_PPC_OF
#ifdef CONFIG_SERIAL_CORE_CONSOLE
extern char *of_stdout_device;
@@ -564,7 +554,7 @@ static int __init set_preferred_console(void)
}
console_initcall(set_preferred_console);
#endif /* CONFIG_SERIAL_CORE_CONSOLE */
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_PPC_OF */
struct bi_record *find_bootinfo(void)
{
@@ -744,13 +734,8 @@ void __init setup_arch(char **cmdline_p)
/* so udelay does something sensible, assume <= 1000 bogomips */
loops_per_jiffy = 500000000 / HZ;
-#ifdef CONFIG_PPC_MULTIPLATFORM
- /* This could be called "early setup arch", it must be done
- * now because xmon need it
- */
- if (_machine == _MACH_Pmac)
- pmac_feature_init(); /* New cool way */
-#endif
+ if (ppc_md.init_early)
+ ppc_md.init_early();
#ifdef CONFIG_XMON
xmon_init(1);
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index becbfa397556..e55cdda6149a 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -318,7 +318,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
p = fork_idle(cpu);
if (IS_ERR(p))
panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
- p->thread_info->cpu = cpu;
+ task_thread_info(p)->cpu = cpu;
idle_tasks[cpu] = p;
}
}
@@ -369,7 +369,7 @@ int __cpu_up(unsigned int cpu)
char buf[32];
int c;
- secondary_ti = idle_tasks[cpu]->thread_info;
+ secondary_ti = task_thread_info(idle_tasks[cpu]);
mb();
/*
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 9dbc4d28fa28..6d0a1838d94c 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -38,9 +38,6 @@
#include <asm/io.h>
#include <asm/reg.h>
#include <asm/xmon.h>
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
#include <asm/pmc.h>
#ifdef CONFIG_XMON
@@ -85,12 +82,6 @@ int die(const char * str, struct pt_regs * fp, long err)
int nl = 0;
console_verbose();
spin_lock_irq(&die_lock);
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (_machine == _MACH_Pmac) {
- set_backlight_enable(1);
- set_backlight_level(BACKLIGHT_MAX);
- }
-#endif
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
@@ -159,7 +150,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
*/
static inline int check_io_access(struct pt_regs *regs)
{
-#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx
+#if defined CONFIG_8xx
unsigned long msr = regs->msr;
const struct exception_table_entry *entry;
unsigned int *nip = (unsigned int *)regs->nip;
@@ -196,7 +187,7 @@ static inline int check_io_access(struct pt_regs *regs)
return 1;
}
}
-#endif /* CONFIG_PPC_PMAC */
+#endif /* CONFIG_8xx */
return 0;
}
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 45f0782059f1..134db5c04203 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -67,10 +67,6 @@ unsigned long ppc_memoffset = PAGE_OFFSET;
int mem_init_done;
int init_bootmem_done;
int boot_mapsize;
-#ifdef CONFIG_PPC_PMAC
-unsigned long agp_special_page;
-EXPORT_SYMBOL(agp_special_page);
-#endif
extern char _end[];
extern char etext[], _stext[];
@@ -424,10 +420,6 @@ void __init mem_init(void)
addr += PAGE_SIZE)
SetPageReserved(virt_to_page(addr));
#endif
-#ifdef CONFIG_PPC_PMAC
- if (agp_special_page)
- SetPageReserved(virt_to_page(agp_special_page));
-#endif
for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
addr += PAGE_SIZE) {
if (!PageReserved(virt_to_page(addr)))
@@ -463,11 +455,6 @@ void __init mem_init(void)
initpages<< (PAGE_SHIFT-10),
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
-#ifdef CONFIG_PPC_PMAC
- if (agp_special_page)
- printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
-#endif
-
mem_init_done = 1;
}
@@ -512,22 +499,6 @@ set_phys_avail(unsigned long total_memory)
if (rtas_data)
mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
#endif
-#ifdef CONFIG_PPC_PMAC
- /* Because of some uninorth weirdness, we need a page of
- * memory as high as possible (it must be outside of the
- * bus address seen as the AGP aperture). It will be used
- * by the r128 DRM driver
- *
- * FIXME: We need to make sure that page doesn't overlap any of the\
- * above. This could be done by improving mem_pieces_find to be able
- * to do a backward search from the end of the list.
- */
- if (_machine == _MACH_Pmac && find_devices("uni-north-agp")) {
- agp_special_page = (total_memory - PAGE_SIZE);
- mem_pieces_remove(&phys_avail, agp_special_page, PAGE_SIZE, 0);
- agp_special_page = (unsigned long)__va(agp_special_page);
- }
-#endif /* CONFIG_PPC_PMAC */
}
/* Mark some memory as reserved by removing it from phys_avail. */
diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c
index 956f45e4ef97..d24c09ee7b18 100644
--- a/arch/ppc/platforms/4xx/ibm440gx.c
+++ b/arch/ppc/platforms/4xx/ibm440gx.c
@@ -58,7 +58,6 @@ static struct ocp_func_emac_data ibm440gx_emac2_def = {
.wol_irq = 65, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = 0, /* TAH device index */
- .jumbo = 1, /* Jumbo frames supported */
};
static struct ocp_func_emac_data ibm440gx_emac3_def = {
@@ -72,7 +71,6 @@ static struct ocp_func_emac_data ibm440gx_emac3_def = {
.wol_irq = 67, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = 1, /* TAH device index */
- .jumbo = 1, /* Jumbo frames supported */
};
OCP_SYSFS_EMAC_DATA()
diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c
index feb17e41ef69..71a0117d3597 100644
--- a/arch/ppc/platforms/4xx/ibm440sp.c
+++ b/arch/ppc/platforms/4xx/ibm440sp.c
@@ -31,7 +31,6 @@ static struct ocp_func_emac_data ibm440sp_emac0_def = {
.wol_irq = 61, /* WOL interrupt number */
.mdio_idx = -1, /* No shared MDIO */
.tah_idx = -1, /* No TAH */
- .jumbo = 1, /* Jumbo frames supported */
};
OCP_SYSFS_EMAC_DATA()
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index 04bdc39bf47b..012e1e652c03 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -51,9 +51,6 @@
#include <syslib/ppc83xx_setup.h>
-static const char *GFAR_PHY_0 = "phy0:0";
-static const char *GFAR_PHY_1 = "phy0:1";
-
#ifndef CONFIG_PCI
unsigned long isa_io_base = 0;
unsigned long isa_mem_base = 0;
@@ -129,20 +126,21 @@ mpc834x_sys_setup_arch(void)
mdata->irq[1] = MPC83xx_IRQ_EXT2;
mdata->irq[2] = -1;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 0;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_1;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
index c5bc2821d991..7ddd331a7145 100644
--- a/arch/ppc/platforms/85xx/Kconfig
+++ b/arch/ppc/platforms/85xx/Kconfig
@@ -39,7 +39,7 @@ config MPC8560_ADS
config SBC8560
bool "WindRiver PowerQUICC III SBC8560"
help
- This option enables support for the WindRiver PowerQUICC III
+ This option enables support for the WindRiver PowerQUICC III
SBC8560 board.
config STX_GP3
@@ -48,6 +48,26 @@ config STX_GP3
This option enables support for the Silicon Turnkey Express GP3
board.
+config TQM8540
+ bool "TQ Components TQM8540"
+ help
+ This option enablese support for the TQ Components TQM8540 board.
+
+config TQM8541
+ bool "TQ Components TQM8541"
+ help
+ This option enablese support for the TQ Components TQM8541 board.
+
+config TQM8555
+ bool "TQ Components TQM8555"
+ help
+ This option enablese support for the TQ Components TQM8555 board.
+
+config TQM8560
+ bool "TQ Components TQM8560"
+ help
+ This option enablese support for the TQ Components TQM8560 board.
+
endchoice
# It's often necessary to know the specific 85xx processor type.
@@ -55,7 +75,7 @@ endchoice
# don't need to ask more redundant questions.
config MPC8540
bool
- depends on MPC8540_ADS
+ depends on MPC8540_ADS || TQM8540
default y
config MPC8548
@@ -65,12 +85,12 @@ config MPC8548
config MPC8555
bool
- depends on MPC8555_CDS
+ depends on MPC8555_CDS || TQM8541 || TQM8555
default y
config MPC8560
bool
- depends on SBC8560 || MPC8560_ADS || STX_GP3
+ depends on SBC8560 || MPC8560_ADS || STX_GP3 || TQM8560
default y
config 85xx_PCI2
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
index efdf813108f2..6c4753c144d3 100644
--- a/arch/ppc/platforms/85xx/Makefile
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -7,3 +7,7 @@ obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o
obj-$(CONFIG_SBC8560) += sbc85xx.o sbc8560.o
obj-$(CONFIG_STX_GP3) += stx_gp3.o
+obj-$(CONFIG_TQM8540) += tqm85xx.o
+obj-$(CONFIG_TQM8541) += tqm85xx.o
+obj-$(CONFIG_TQM8555) += tqm85xx.o
+obj-$(CONFIG_TQM8560) += tqm85xx.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index c5cde97c6ef0..2eceb1e6f4eb 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -52,10 +52,6 @@
#include <syslib/ppc85xx_setup.h>
-static const char *GFAR_PHY_0 = "phy0:0";
-static const char *GFAR_PHY_1 = "phy0:1";
-static const char *GFAR_PHY_3 = "phy0:3";
-
/* ************************************************************************
*
* Setup the architecture
@@ -102,27 +98,29 @@ mpc8540ads_setup_arch(void)
mdata->irq[2] = -1;
mdata->irq[3] = MPC85xx_IRQ_EXT5;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 0;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_1;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
if (pdata) {
pdata->board_flags = 0;
- pdata->bus_id = GFAR_PHY_3;
+ pdata->bus_id = 0;
+ pdata->phy_id = 3;
memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 8e39a5517092..442c7ff195d3 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -56,10 +56,6 @@
#include <syslib/ppc85xx_setup.h>
-static const char *GFAR_PHY_0 = "phy0:0";
-static const char *GFAR_PHY_1 = "phy0:1";
-static const char *GFAR_PHY_3 = "phy0:3";
-
/* ************************************************************************
*
* Setup the architecture
@@ -99,20 +95,21 @@ mpc8560ads_setup_arch(void)
mdata->irq[2] = -1;
mdata->irq[3] = MPC85xx_IRQ_EXT5;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 0;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_1;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 5e8cc5ec6ab5..b332ebae6bd3 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -351,10 +351,10 @@ mpc85xx_cds_fixup_via(struct pci_controller *hose)
void __init
mpc85xx_cds_pcibios_fixup(void)
{
- struct pci_dev *dev = NULL;
+ struct pci_dev *dev;
u_char c;
- if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
/*
* U-Boot does not set the enable bits
@@ -371,30 +371,30 @@ mpc85xx_cds_pcibios_fixup(void)
*/
dev->irq = 14;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ pci_dev_put(dev);
}
/*
* Force legacy USB interrupt routing
*/
- if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
dev->irq = 10;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+ pci_dev_put(dev);
}
- if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_82C586_2, dev))) {
dev->irq = 11;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+ pci_dev_put(dev);
}
}
#endif /* CONFIG_PCI */
TODC_ALLOC();
-static const char *GFAR_PHY_0 = "phy0:0";
-static const char *GFAR_PHY_1 = "phy0:1";
-
/* ************************************************************************
*
* Setup the architecture
@@ -458,34 +458,37 @@ mpc85xx_cds_setup_arch(void)
mdata->irq[2] = -1;
mdata->irq[3] = -1;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 0;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_1;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 0;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_1;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 45a5b81b4ed1..e777ba824aa9 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -91,9 +91,6 @@ sbc8560_early_serial_map(void)
}
#endif
-static const char *GFAR_PHY_25 = "phy0:25";
-static const char *GFAR_PHY_26 = "phy0:26";
-
/* ************************************************************************
*
* Setup the architecture
@@ -136,20 +133,21 @@ sbc8560_setup_arch(void)
mdata->irq[25] = MPC85xx_IRQ_EXT6;
mdata->irq[26] = MPC85xx_IRQ_EXT7;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_25;
+ pdata->bus_id = 0;
+ pdata->phy_id = 25;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
if (pdata) {
pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->bus_id = GFAR_PHY_26;
+ pdata->bus_id = 0;
+ pdata->phy_id = 26;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 15ce9d070634..061bb7cf2d9a 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -93,9 +93,6 @@ static u8 gp3_openpic_initsenses[] __initdata = {
0x0, /* External 11: */
};
-static const char *GFAR_PHY_2 = "phy0:2";
-static const char *GFAR_PHY_4 = "phy0:4";
-
/*
* Setup the architecture
*/
@@ -130,20 +127,21 @@ gp3_setup_arch(void)
mdata->irq[2] = MPC85xx_IRQ_EXT5;
mdata->irq[4] = MPC85xx_IRQ_EXT5;
mdata->irq[31] = -1;
- mdata->paddr += binfo->bi_immr_base;
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
if (pdata) {
/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
- pdata->bus_id = GFAR_PHY_2;
+ pdata->bus_id = 0;
+ pdata->phy_id = 2;
memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
}
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
if (pdata) {
/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
- pdata->bus_id = GFAR_PHY_4;
+ pdata->bus_id = 0;
+ pdata->phy_id = 4;
memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
}
diff --git a/arch/ppc/platforms/85xx/tqm85xx.c b/arch/ppc/platforms/85xx/tqm85xx.c
new file mode 100644
index 000000000000..b436f4d0a3fa
--- /dev/null
+++ b/arch/ppc/platforms/85xx/tqm85xx.c
@@ -0,0 +1,415 @@
+/*
+ * arch/ppc/platforms/85xx/tqm85xx.c
+ *
+ * TQM85xx (40/41/55/60) board specific routines
+ *
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * Kumar Gala <galak@kernel.crashing.org>
+ * Copyright 2004 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#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/console.h>
+#include <linux/delay.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/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <asm/immap_85xx.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <asm/cpm2.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc85xx_setup.h>
+#include <syslib/cpm2_pic.h>
+#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_rio.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+
+extern unsigned long total_memory; /* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+static u_char tqm85xx_openpic_initsenses[] __initdata = {
+ MPC85XX_INTERNAL_IRQ_SENSES,
+ 0x0, /* External 0: */
+ 0x0, /* External 1: */
+#if defined(CONFIG_PCI)
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI INTA */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI INTB */
+#else
+ 0x0, /* External 2: */
+ 0x0, /* External 3: */
+#endif
+ 0x0, /* External 4: */
+ 0x0, /* External 5: */
+ 0x0, /* External 6: */
+ 0x0, /* External 7: */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 8: PHY */
+ 0x0, /* External 9: */
+ 0x0, /* External 10: */
+ 0x0, /* External 11: */
+};
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+tqm85xx_setup_arch(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+ struct gianfar_platform_data *pdata;
+ struct gianfar_mdio_data *mdata;
+
+#ifdef CONFIG_MPC8560
+ cpm2_reset();
+#endif
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ if (ppc_md.progress)
+ ppc_md.progress("tqm85xx_setup_arch()", 0);
+
+ /* Set loops_per_jiffy to a half-way reasonable value,
+ for use until calibrate_delay gets called. */
+ loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+ /* setup PCI host bridges */
+ mpc85xx_setup_hose();
+#endif
+
+#ifndef CONFIG_MPC8560
+#if defined(CONFIG_SERIAL_8250)
+ mpc85xx_early_serial_map();
+#endif
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ /* Invalidate the entry we stole earlier the serial ports
+ * should be properly mapped */
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
+#endif
+#endif /* CONFIG_MPC8560 */
+
+ /* setup the board related info for the MDIO bus */
+ mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
+
+ mdata->irq[0] = MPC85xx_IRQ_EXT8;
+ mdata->irq[1] = MPC85xx_IRQ_EXT8;
+ mdata->irq[2] = -1;
+ mdata->irq[3] = MPC85xx_IRQ_EXT8;
+ mdata->irq[31] = -1;
+
+ /* setup the board related information for the enet controllers */
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->bus_id = 0;
+ pdata->phy_id = 2;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->bus_id = 0;
+ pdata->phy_id = 1;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+#ifdef CONFIG_MPC8540
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+ if (pdata) {
+ pdata->board_flags = 0;
+ pdata->bus_id = 0;
+ pdata->phy_id = 3;
+ memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+ }
+#endif
+
+#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_HDA1;
+#endif
+}
+
+#ifdef CONFIG_MPC8560
+static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
+{
+ while ((irq = cpm2_get_irq(regs)) >= 0)
+ __do_IRQ(irq, regs);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction cpm2_irqaction = {
+ .handler = cpm2_cascade,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "cpm2_cascade",
+};
+#endif /* CONFIG_MPC8560 */
+
+void __init
+tqm85xx_init_IRQ(void)
+{
+ bd_t *binfo = (bd_t *) __res;
+
+ /* Determine the Physical Address of the OpenPIC regs */
+ phys_addr_t OpenPIC_PAddr =
+ binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+ OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+ OpenPIC_InitSenses = tqm85xx_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof (tqm85xx_openpic_initsenses);
+
+ /* Skip reserved space and internal sources */
+ openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+
+ /* Map PIC IRQs 0-11 */
+ openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
+
+ /* we let openpic interrupts starting from an offset, to
+ * leave space for cascading interrupts underneath.
+ */
+ openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+
+#ifdef CONFIG_MPC8560
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
+
+ setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
+#endif /* CONFIG_MPC8560 */
+
+ return;
+}
+
+int tqm85xx_show_cpuinfo(struct seq_file *m)
+{
+ uint pvid, svid, phid1;
+ uint memsize = total_memory;
+ bd_t *binfo = (bd_t *) __res;
+ unsigned int freq;
+
+ /* get the core frequency */
+ freq = binfo->bi_intfreq;
+
+ pvid = mfspr(SPRN_PVR);
+ svid = mfspr(SPRN_SVR);
+
+ seq_printf(m, "Vendor\t\t: TQ Components\n");
+ seq_printf(m, "Machine\t\t: TQM%s\n", cur_ppc_sys_spec->ppc_sys_name);
+ seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
+ seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+ seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+ /* Display cpu Pll setting */
+ phid1 = mfspr(SPRN_HID1);
+ seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+ /* Display the amount of memory */
+ seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+
+ return 0;
+}
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_DS1337)
+extern ulong ds1337_get_rtc_time(void);
+extern int ds1337_set_rtc_time(unsigned long nowtime);
+
+static int __init
+tqm85xx_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.set_rtc_time = ds1337_set_rtc_time;
+ ppc_md.get_rtc_time = ds1337_get_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time)();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+late_initcall(tqm85xx_rtc_hookup);
+#endif
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+int mpc85xx_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, 0, 0},
+ };
+
+ const long min_idsel = 0x1c, max_idsel = 0x1c, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+int mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+ if (bus == 0 && PCI_SLOT(devfn) == 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ else
+ return PCIBIOS_SUCCESSFUL;
+}
+
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_RAPIDIO
+void platform_rio_init(void)
+{
+ /* 512MB RIO LAW at 0xc0000000 */
+ mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
+
+/* ************************************************************************ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ /* parse_bootinfo must always be called first */
+ 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_SERIAL_TEXT_DEBUG) && !defined(CONFIG_MPC8560)
+ {
+ bd_t *binfo = (bd_t *) __res;
+ struct uart_port p;
+
+ /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
+ settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
+ binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(0, &p);
+
+ memset(&p, 0, sizeof (p));
+ p.iotype = SERIAL_IO_MEM;
+ p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET;
+ p.uartclk = binfo->bi_busfreq;
+
+ gen550_init(1, &p);
+ }
+#endif
+
+#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));
+ }
+
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
+ /* setup the PowerPC module struct */
+ ppc_md.setup_arch = tqm85xx_setup_arch;
+ ppc_md.show_cpuinfo = tqm85xx_show_cpuinfo;
+
+ ppc_md.init_IRQ = tqm85xx_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = mpc85xx_restart;
+ ppc_md.power_off = mpc85xx_power_off;
+ ppc_md.halt = mpc85xx_halt;
+
+ ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = NULL;
+ ppc_md.get_rtc_time = NULL;
+ ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+#ifndef CONFIG_MPC8560
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+ ppc_md.progress = gen550_progress;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+ ppc_md.early_serial_map = mpc85xx_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
+#endif /* CONFIG_MPC8560 */
+
+ if (ppc_md.progress)
+ ppc_md.progress("tqm85xx_init(): exit", 0);
+
+ return;
+}
diff --git a/arch/ppc/platforms/85xx/tqm85xx.h b/arch/ppc/platforms/85xx/tqm85xx.h
new file mode 100644
index 000000000000..3775eb363fde
--- /dev/null
+++ b/arch/ppc/platforms/85xx/tqm85xx.h
@@ -0,0 +1,56 @@
+/*
+ * arch/ppc/platforms/85xx/tqm85xx.h
+ *
+ * TQM85xx (40/41/55/60) board definitions
+ *
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.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.
+ *
+ */
+
+#ifndef __MACH_TQM85XX_H
+#define __MACH_TQM85XX_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+#define BOARD_CCSRBAR ((uint)0xe0000000)
+#define CCSRBAR_SIZE ((uint)1024*1024)
+
+#define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET)
+
+#define PCI_CFG_ADDR_OFFSET (0x8000)
+#define PCI_CFG_DATA_OFFSET (0x8004)
+
+/* PCI interrupt controller */
+#define PIRQA MPC85xx_IRQ_EXT2
+#define PIRQB MPC85xx_IRQ_EXT3
+
+#define MPC85XX_PCI1_LOWER_IO 0x00000000
+#define MPC85XX_PCI1_UPPER_IO 0x00ffffff
+
+#define MPC85XX_PCI1_LOWER_MEM 0x80000000
+#define MPC85XX_PCI1_UPPER_MEM 0x9fffffff
+
+#define MPC85XX_PCI1_IO_BASE 0xe2000000
+#define MPC85XX_PCI1_MEM_OFFSET 0x00000000
+
+#define MPC85XX_PCI1_IO_SIZE 0x01000000
+
+#define BASE_BAUD 115200
+
+extern void mpc85xx_setup_hose(void) __init;
+extern void mpc85xx_restart(char *cmd);
+extern void mpc85xx_power_off(void);
+extern void mpc85xx_halt(void);
+extern void mpc85xx_init_IRQ(void) __init;
+extern unsigned long mpc85xx_find_end_of_memory(void) __init;
+extern void mpc85xx_calibrate_decr(void) __init;
+
+#endif /* __MACH_TQM85XX_H */
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 7c5cdabf6f3c..51430e294b32 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -3,26 +3,18 @@
#
# Extra CFLAGS so we don't have to do relative includes
-CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm
+CFLAGS_chrp_setup.o += -Iarch/$(ARCH)/mm
obj-$(CONFIG_APUS) += apus_setup.o
ifeq ($(CONFIG_APUS),y)
obj-$(CONFIG_PCI) += apus_pci.o
endif
-obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \
- pmac_feature.o pmac_pci.o pmac_sleep.o \
- pmac_low_i2c.o pmac_cache.o
obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \
chrp_pegasos_eth.o
ifeq ($(CONFIG_PPC_CHRP),y)
obj-$(CONFIG_NVRAM) += chrp_nvram.o
endif
obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o
-ifeq ($(CONFIG_PPC_PMAC),y)
-obj-$(CONFIG_NVRAM) += pmac_nvram.o
-obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o
-endif
-obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o
obj-$(CONFIG_PREP_RESIDUAL) += residual.o
obj-$(CONFIG_PQ2ADS) += pq2ads.o
obj-$(CONFIG_TQM8260) += tqm8260_setup.o
@@ -47,6 +39,5 @@ obj-$(CONFIG_LITE5200) += lite5200.o
obj-$(CONFIG_EV64360) += ev64360.o
ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
obj-$(CONFIG_PPC_CHRP) += chrp_smp.o
endif
diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c
index 2f74fde98ebc..c42c50073da5 100644
--- a/arch/ppc/platforms/apus_setup.c
+++ b/arch/ppc/platforms/apus_setup.c
@@ -55,9 +55,6 @@ int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
int (*mach_set_clock_mmss) (unsigned long) = NULL;
void (*mach_reset)( void );
long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY)
-void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-#endif
#ifdef CONFIG_HEARTBEAT
void (*mach_heartbeat) (int) = NULL;
extern void apus_heartbeat (void);
@@ -76,7 +73,6 @@ struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
struct mem_info ramdisk;
-extern void amiga_floppy_setup(char *, int *);
extern void config_amiga(void);
static int __60nsram = 0;
@@ -305,16 +301,6 @@ void kbd_reset_setup(char *str, int *ints)
{
}
-/*********************************************************** FLOPPY */
-#if defined(CONFIG_AMIGA_FLOPPY)
-__init
-void floppy_setup(char *str, int *ints)
-{
- if (mach_floppy_setup)
- mach_floppy_setup (str, ints);
-}
-#endif
-
/*********************************************************** MEMORY */
#define KMAP_MAX 32
unsigned long kmap_chunks[KMAP_MAX*3];
@@ -574,9 +560,9 @@ static __inline__ void ser_RTSon(void)
int __debug_ser_out( unsigned char c )
{
- custom.serdat = c | 0x100;
+ amiga_custom.serdat = c | 0x100;
mb();
- while (!(custom.serdatr & 0x2000))
+ while (!(amiga_custom.serdatr & 0x2000))
barrier();
return 1;
}
@@ -586,11 +572,11 @@ unsigned char __debug_ser_in( void )
unsigned char c;
/* XXX: is that ok?? derived from amiga_ser.c... */
- while( !(custom.intreqr & IF_RBF) )
+ while( !(amiga_custom.intreqr & IF_RBF) )
barrier();
- c = custom.serdatr;
+ c = amiga_custom.serdatr;
/* clear the interrupt, so that another character can be read */
- custom.intreq = IF_RBF;
+ amiga_custom.intreq = IF_RBF;
return c;
}
@@ -601,10 +587,10 @@ int __debug_serinit( void )
local_irq_save(flags);
/* turn off Rx and Tx interrupts */
- custom.intena = IF_RBF | IF_TBE;
+ amiga_custom.intena = IF_RBF | IF_TBE;
/* clear any pending interrupt */
- custom.intreq = IF_RBF | IF_TBE;
+ amiga_custom.intreq = IF_RBF | IF_TBE;
local_irq_restore(flags);
@@ -617,7 +603,7 @@ int __debug_serinit( void )
#ifdef CONFIG_KGDB
/* turn Rx interrupts on for GDB */
- custom.intena = IF_SETCLR | IF_RBF;
+ amiga_custom.intena = IF_SETCLR | IF_RBF;
ser_RTSon();
#endif
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
index bd047aac01b1..c7fe6182bb77 100644
--- a/arch/ppc/platforms/chrp_pci.c
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -275,7 +275,7 @@ chrp_find_bridges(void)
setup_python(hose, dev);
} else if (is_mot
|| strncmp(model, "Motorola, Grackle", 17) == 0) {
- setup_grackle(hose);
+ setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
} else if (is_longtrail) {
void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
hose->ops = &gg2_pci_ops;
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
index f1b70ab3c6fd..48996b787378 100644
--- a/arch/ppc/platforms/chrp_setup.c
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -53,6 +53,7 @@
#include <asm/i8259.h>
#include <asm/open_pic.h>
#include <asm/xmon.h>
+#include "mem_pieces.h"
unsigned long chrp_get_rtc_time(void);
int chrp_set_rtc_time(unsigned long nowtime);
@@ -65,7 +66,6 @@ void rtas_display_progress(char *, unsigned short);
void rtas_indicator_progress(char *, unsigned short);
void btext_progress(char *, unsigned short);
-extern unsigned long pmac_find_end_of_memory(void);
extern int of_show_percpuinfo(struct seq_file *, int);
int _chrp_type;
@@ -404,7 +404,6 @@ static struct irqaction xmon_irqaction = {
void __init chrp_init_IRQ(void)
{
struct device_node *np;
- int i;
unsigned long chrp_int_ack = 0;
unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
#if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
@@ -468,6 +467,75 @@ chrp_init2(void)
ppc_md.progress(" Have fun! ", 0x7777);
}
+static struct device_node *memory_node;
+
+static int __init get_mem_prop(char *name, struct mem_pieces *mp)
+{
+ struct reg_property *rp;
+ int i, s;
+ unsigned int *ip;
+ int nac = prom_n_addr_cells(memory_node);
+ int nsc = prom_n_size_cells(memory_node);
+
+ ip = (unsigned int *) get_property(memory_node, name, &s);
+ if (ip == NULL) {
+ printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+ name);
+ return 0;
+ }
+ s /= (nsc + nac) * 4;
+ rp = mp->regions;
+ for (i = 0; i < s; ++i, ip += nac+nsc) {
+ if (nac >= 2 && ip[nac-2] != 0)
+ continue;
+ rp->address = ip[nac-1];
+ if (nsc >= 2 && ip[nac+nsc-2] != 0)
+ rp->size = ~0U;
+ else
+ rp->size = ip[nac+nsc-1];
+ ++rp;
+ }
+ mp->n_regions = rp - mp->regions;
+
+ /* Make sure the pieces are sorted. */
+ mem_pieces_sort(mp);
+ mem_pieces_coalesce(mp);
+ return 1;
+}
+
+static unsigned long __init chrp_find_end_of_memory(void)
+{
+ unsigned long a, total;
+ struct mem_pieces phys_mem;
+
+ /*
+ * Find out where physical memory is, and check that it
+ * starts at 0 and is contiguous. It seems that RAM is
+ * always physically contiguous on Power Macintoshes.
+ *
+ * Supporting discontiguous physical memory isn't hard,
+ * it just makes the virtual <-> physical mapping functions
+ * more complicated (or else you end up wasting space
+ * in mem_map).
+ */
+ memory_node = find_devices("memory");
+ if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
+ || phys_mem.n_regions == 0)
+ panic("No RAM??");
+ a = phys_mem.regions[0].address;
+ if (a != 0)
+ panic("RAM doesn't start at physical address 0");
+ total = phys_mem.regions[0].size;
+
+ if (phys_mem.n_regions > 1) {
+ printk("RAM starting at 0x%x is not contiguous\n",
+ phys_mem.regions[1].address);
+ printk("Using RAM from 0 to 0x%lx\n", total-1);
+ }
+
+ return total;
+}
+
void __init
chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
@@ -526,7 +594,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.get_rtc_time = chrp_get_rtc_time;
ppc_md.calibrate_decr = chrp_calibrate_decr;
- ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+ ppc_md.find_end_of_memory = chrp_find_end_of_memory;
if (rtas_data) {
struct device_node *rtas;
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c
index 29d074c305f0..57753a55b580 100644
--- a/arch/ppc/platforms/chrp_time.c
+++ b/arch/ppc/platforms/chrp_time.c
@@ -163,13 +163,75 @@ unsigned long chrp_get_rtc_time(void)
return mktime(year, mon, day, hour, min, sec);
}
+/*
+ * Calibrate the decrementer frequency with the VIA timer 1.
+ */
+#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
+
+/* VIA registers */
+#define RS 0x200 /* skip between registers */
+#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
+#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
+#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
+#define ACR (11*RS) /* Auxiliary control register */
+#define IFR (13*RS) /* Interrupt flag register */
+
+/* Bits in ACR */
+#define T1MODE 0xc0 /* Timer 1 mode */
+#define T1MODE_CONT 0x40 /* continuous interrupts */
+
+/* Bits in IFR and IER */
+#define T1_INT 0x40 /* Timer 1 interrupt */
+
+static int __init chrp_via_calibrate_decr(void)
+{
+ struct device_node *vias;
+ volatile unsigned char __iomem *via;
+ int count = VIA_TIMER_FREQ_6 / 100;
+ unsigned int dstart, dend;
+
+ vias = find_devices("via-cuda");
+ if (vias == 0)
+ vias = find_devices("via");
+ if (vias == 0 || vias->n_addrs == 0)
+ return 0;
+ via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
+
+ /* set timer 1 for continuous interrupts */
+ out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
+ /* set the counter to a small value */
+ out_8(&via[T1CH], 2);
+ /* set the latch to `count' */
+ out_8(&via[T1LL], count);
+ out_8(&via[T1LH], count >> 8);
+ /* wait until it hits 0 */
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dstart = get_dec();
+ /* clear the interrupt & wait until it hits 0 again */
+ in_8(&via[T1CL]);
+ while ((in_8(&via[IFR]) & T1_INT) == 0)
+ ;
+ dend = get_dec();
+
+ tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
+ tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
+
+ printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+ tb_ticks_per_jiffy, dstart - dend);
+
+ iounmap(via);
+
+ return 1;
+}
void __init chrp_calibrate_decr(void)
{
struct device_node *cpu;
unsigned int freq, *fp;
- if (via_calibrate_decr())
+ if (chrp_via_calibrate_decr())
return;
/*
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index d44cc991179f..7ed52dc340c9 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -196,8 +196,10 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
mpc52xx_set_bat();
/* No ISA bus by default */
+#ifdef CONFIG_PCI
isa_io_base = 0;
isa_mem_base = 0;
+#endif
/* Powersave */
/* This is provided as an example on how to do it. But you
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
deleted file mode 100644
index a58db438c162..000000000000
--- a/arch/ppc/platforms/mpc5200.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/ppc/platforms/mpc5200.c
- *
- * OCP Definitions for the boards based on MPC5200 processor. Contains
- * definitions for every common peripherals. (Mostly all but PSCs)
- *
- * Maintainer : Sylvain Munaut <tnt@246tNt.com>
- *
- * Copyright 2004 Sylvain Munaut <tnt@246tNt.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 <asm/ocp.h>
-#include <asm/mpc52xx.h>
-
-
-static struct ocp_fs_i2c_data mpc5200_i2c_def = {
- .flags = FS_I2C_CLOCK_5200,
-};
-
-
-/* Here is the core_ocp struct.
- * With all the devices common to all board. Even if port multiplexing is
- * not setup for them (if the user don't want them, just don't select the
- * config option). The potentially conflicting devices (like PSCs) goes in
- * board specific file.
- */
-struct ocp_def core_ocp[] = {
- {
- .vendor = OCP_VENDOR_FREESCALE,
- .function = OCP_FUNC_IIC,
- .index = 0,
- .paddr = MPC52xx_I2C1,
- .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */
- .pm = OCP_CPM_NA,
- .additions = &mpc5200_i2c_def,
- },
- {
- .vendor = OCP_VENDOR_FREESCALE,
- .function = OCP_FUNC_IIC,
- .index = 1,
- .paddr = MPC52xx_I2C2,
- .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */
- .pm = OCP_CPM_NA,
- .additions = &mpc5200_i2c_def,
- },
- { /* Terminating entry */
- .vendor = OCP_VENDOR_INVALID
- }
-};
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
deleted file mode 100644
index 8be2f7d071f0..000000000000
--- a/arch/ppc/platforms/pmac_backlight.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- * Contains support for the backlight.
- *
- * Copyright (C) 2000 Benjamin Herrenschmidt
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/reboot.h>
-#include <linux/nvram.h>
-#include <linux/console.h>
-#include <asm/sections.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <asm/backlight.h>
-
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-static struct backlight_controller *backlighter;
-static void* backlighter_data;
-static int backlight_autosave;
-static int backlight_level = BACKLIGHT_MAX;
-static int backlight_enabled = 1;
-static int backlight_req_level = -1;
-static int backlight_req_enable = -1;
-
-static void backlight_callback(void *);
-static DECLARE_WORK(backlight_work, backlight_callback, NULL);
-
-void register_backlight_controller(struct backlight_controller *ctrler,
- void *data, char *type)
-{
- struct device_node* bk_node;
- char *prop;
- int valid = 0;
-
- /* There's already a matching controller, bail out */
- if (backlighter != NULL)
- return;
-
- bk_node = find_devices("backlight");
-
-#ifdef CONFIG_ADB_PMU
- /* Special case for the old PowerBook since I can't test on it */
- backlight_autosave = machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500");
- if ((backlight_autosave
- || machine_is_compatible("AAPL,PowerBook1998")
- || machine_is_compatible("PowerBook1,1"))
- && !strcmp(type, "pmu"))
- valid = 1;
-#endif
- if (bk_node) {
- prop = get_property(bk_node, "backlight-control", NULL);
- if (prop && !strncmp(prop, type, strlen(type)))
- valid = 1;
- }
- if (!valid)
- return;
- backlighter = ctrler;
- backlighter_data = data;
-
- if (bk_node && !backlight_autosave)
- prop = get_property(bk_node, "bklt", NULL);
- else
- prop = NULL;
- if (prop) {
- backlight_level = ((*prop)+1) >> 1;
- if (backlight_level > BACKLIGHT_MAX)
- backlight_level = BACKLIGHT_MAX;
- }
-
-#ifdef CONFIG_ADB_PMU
- if (backlight_autosave) {
- struct adb_request req;
- pmu_request(&req, NULL, 2, 0xd9, 0);
- while (!req.complete)
- pmu_poll();
- backlight_level = req.reply[0] >> 4;
- }
-#endif
- acquire_console_sem();
- if (!backlighter->set_enable(1, backlight_level, data))
- backlight_enabled = 1;
- release_console_sem();
-
- printk(KERN_INFO "Registered \"%s\" backlight controller,"
- "level: %d/15\n", type, backlight_level);
-}
-EXPORT_SYMBOL(register_backlight_controller);
-
-void unregister_backlight_controller(struct backlight_controller
- *ctrler, void *data)
-{
- /* We keep the current backlight level (for now) */
- if (ctrler == backlighter && data == backlighter_data)
- backlighter = NULL;
-}
-EXPORT_SYMBOL(unregister_backlight_controller);
-
-static int __set_backlight_enable(int enable)
-{
- int rc;
-
- if (!backlighter)
- return -ENODEV;
- acquire_console_sem();
- rc = backlighter->set_enable(enable, backlight_level,
- backlighter_data);
- if (!rc)
- backlight_enabled = enable;
- release_console_sem();
- return rc;
-}
-int set_backlight_enable(int enable)
-{
- if (!backlighter)
- return -ENODEV;
- backlight_req_enable = enable;
- schedule_work(&backlight_work);
- return 0;
-}
-
-EXPORT_SYMBOL(set_backlight_enable);
-
-int get_backlight_enable(void)
-{
- if (!backlighter)
- return -ENODEV;
- return backlight_enabled;
-}
-EXPORT_SYMBOL(get_backlight_enable);
-
-static int __set_backlight_level(int level)
-{
- int rc = 0;
-
- if (!backlighter)
- return -ENODEV;
- if (level < BACKLIGHT_MIN)
- level = BACKLIGHT_OFF;
- if (level > BACKLIGHT_MAX)
- level = BACKLIGHT_MAX;
- acquire_console_sem();
- if (backlight_enabled)
- rc = backlighter->set_level(level, backlighter_data);
- if (!rc)
- backlight_level = level;
- release_console_sem();
- if (!rc && !backlight_autosave) {
- level <<=1;
- if (level & 0x10)
- level |= 0x01;
- // -- todo: save to property "bklt"
- }
- return rc;
-}
-int set_backlight_level(int level)
-{
- if (!backlighter)
- return -ENODEV;
- backlight_req_level = level;
- schedule_work(&backlight_work);
- return 0;
-}
-
-EXPORT_SYMBOL(set_backlight_level);
-
-int get_backlight_level(void)
-{
- if (!backlighter)
- return -ENODEV;
- return backlight_level;
-}
-EXPORT_SYMBOL(get_backlight_level);
-
-static void backlight_callback(void *dummy)
-{
- int level, enable;
-
- do {
- level = backlight_req_level;
- enable = backlight_req_enable;
- mb();
-
- if (level >= 0)
- __set_backlight_level(level);
- if (enable >= 0)
- __set_backlight_enable(enable);
- } while(cmpxchg(&backlight_req_level, level, -1) != level ||
- cmpxchg(&backlight_req_enable, enable, -1) != enable);
-}
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S
deleted file mode 100644
index fb977de6b704..000000000000
--- a/arch/ppc/platforms/pmac_cache.S
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * This file contains low-level cache management functions
- * used for sleep and CPU speed changes on Apple machines.
- * (In fact the only thing that is Apple-specific is that we assume
- * that we can read from ROM at physical address 0xfff00000.)
- *
- * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and
- * Benjamin Herrenschmidt (benh@kernel.crashing.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/cputable.h>
-
-/*
- * Flush and disable all data caches (dL1, L2, L3). This is used
- * when going to sleep, when doing a PMU based cpufreq transition,
- * or when "offlining" a CPU on SMP machines. This code is over
- * paranoid, but I've had enough issues with various CPU revs and
- * bugs that I decided it was worth beeing over cautious
- */
-
-_GLOBAL(flush_disable_caches)
-#ifndef CONFIG_6xx
- blr
-#else
-BEGIN_FTR_SECTION
- b flush_disable_745x
-END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
-BEGIN_FTR_SECTION
- b flush_disable_75x
-END_FTR_SECTION_IFSET(CPU_FTR_L2CR)
- b __flush_disable_L1
-
-/* This is the code for G3 and 74[01]0 */
-flush_disable_75x:
- mflr r10
-
- /* Turn off EE and DR in MSR */
- mfmsr r11
- rlwinm r0,r11,0,~MSR_EE
- rlwinm r0,r0,0,~MSR_DR
- sync
- mtmsr r0
- isync
-
- /* Stop DST streams */
-BEGIN_FTR_SECTION
- DSSALL
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-
- /* Stop DPM */
- mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */
- rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */
- sync
- mtspr SPRN_HID0,r4 /* Disable DPM */
- sync
-
- /* Disp-flush L1. We have a weird problem here that I never
- * totally figured out. On 750FX, using the ROM for the flush
- * results in a non-working flush. We use that workaround for
- * now until I finally understand what's going on. --BenH
- */
-
- /* ROM base by default */
- lis r4,0xfff0
- mfpvr r3
- srwi r3,r3,16
- cmplwi cr0,r3,0x7000
- bne+ 1f
- /* RAM base on 750FX */
- li r4,0
-1: li r4,0x4000
- mtctr r4
-1: lwz r0,0(r4)
- addi r4,r4,32
- bdnz 1b
- sync
- isync
-
- /* Disable / invalidate / enable L1 data */
- mfspr r3,SPRN_HID0
- rlwinm r3,r3,0,~(HID0_DCE | HID0_ICE)
- mtspr SPRN_HID0,r3
- sync
- isync
- ori r3,r3,(HID0_DCE|HID0_DCI|HID0_ICE|HID0_ICFI)
- sync
- isync
- mtspr SPRN_HID0,r3
- xori r3,r3,(HID0_DCI|HID0_ICFI)
- mtspr SPRN_HID0,r3
- sync
-
- /* Get the current enable bit of the L2CR into r4 */
- mfspr r5,SPRN_L2CR
- /* Set to data-only (pre-745x bit) */
- oris r3,r5,L2CR_L2DO@h
- b 2f
- /* When disabling L2, code must be in L1 */
- .balign 32
-1: mtspr SPRN_L2CR,r3
-3: sync
- isync
- b 1f
-2: b 3f
-3: sync
- isync
- b 1b
-1: /* disp-flush L2. The interesting thing here is that the L2 can be
- * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory
- * but that is probbaly fine. We disp-flush over 4Mb to be safe
- */
- lis r4,2
- mtctr r4
- lis r4,0xfff0
-1: lwz r0,0(r4)
- addi r4,r4,32
- bdnz 1b
- sync
- isync
- lis r4,2
- mtctr r4
- lis r4,0xfff0
-1: dcbf 0,r4
- addi r4,r4,32
- bdnz 1b
- sync
- isync
-
- /* now disable L2 */
- rlwinm r5,r5,0,~L2CR_L2E
- b 2f
- /* When disabling L2, code must be in L1 */
- .balign 32
-1: mtspr SPRN_L2CR,r5
-3: sync
- isync
- b 1f
-2: b 3f
-3: sync
- isync
- b 1b
-1: sync
- isync
- /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */
- oris r4,r5,L2CR_L2I@h
- mtspr SPRN_L2CR,r4
- sync
- isync
-
- /* Wait for the invalidation to complete */
-1: mfspr r3,SPRN_L2CR
- rlwinm. r0,r3,0,31,31
- bne 1b
-
- /* Clear L2I */
- xoris r4,r4,L2CR_L2I@h
- sync
- mtspr SPRN_L2CR,r4
- sync
-
- /* now disable the L1 data cache */
- mfspr r0,SPRN_HID0
- rlwinm r0,r0,0,~(HID0_DCE|HID0_ICE)
- mtspr SPRN_HID0,r0
- sync
- isync
-
- /* Restore HID0[DPM] to whatever it was before */
- sync
- mfspr r0,SPRN_HID0
- rlwimi r0,r8,0,11,11 /* Turn back HID0[DPM] */
- mtspr SPRN_HID0,r0
- sync
-
- /* restore DR and EE */
- sync
- mtmsr r11
- isync
-
- mtlr r10
- blr
-
-/* This code is for 745x processors */
-flush_disable_745x:
- /* Turn off EE and DR in MSR */
- mfmsr r11
- rlwinm r0,r11,0,~MSR_EE
- rlwinm r0,r0,0,~MSR_DR
- sync
- mtmsr r0
- isync
-
- /* Stop prefetch streams */
- DSSALL
- sync
-
- /* Disable L2 prefetching */
- mfspr r0,SPRN_MSSCR0
- rlwinm r0,r0,0,0,29
- mtspr SPRN_MSSCR0,r0
- sync
- isync
- lis r4,0
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
- dcbf 0,r4
-
- /* Due to a bug with the HW flush on some CPU revs, we occasionally
- * experience data corruption. I'm adding a displacement flush along
- * with a dcbf loop over a few Mb to "help". The problem isn't totally
- * fixed by this in theory, but at least, in practice, I couldn't reproduce
- * it even with a big hammer...
- */
-
- lis r4,0x0002
- mtctr r4
- li r4,0
-1:
- lwz r0,0(r4)
- addi r4,r4,32 /* Go to start of next cache line */
- bdnz 1b
- isync
-
- /* Now, flush the first 4MB of memory */
- lis r4,0x0002
- mtctr r4
- li r4,0
- sync
-1:
- dcbf 0,r4
- addi r4,r4,32 /* Go to start of next cache line */
- bdnz 1b
-
- /* Flush and disable the L1 data cache */
- mfspr r6,SPRN_LDSTCR
- lis r3,0xfff0 /* read from ROM for displacement flush */
- li r4,0xfe /* start with only way 0 unlocked */
- li r5,128 /* 128 lines in each way */
-1: mtctr r5
- rlwimi r6,r4,0,24,31
- mtspr SPRN_LDSTCR,r6
- sync
- isync
-2: lwz r0,0(r3) /* touch each cache line */
- addi r3,r3,32
- bdnz 2b
- rlwinm r4,r4,1,24,30 /* move on to the next way */
- ori r4,r4,1
- cmpwi r4,0xff /* all done? */
- bne 1b
- /* now unlock the L1 data cache */
- li r4,0
- rlwimi r6,r4,0,24,31
- sync
- mtspr SPRN_LDSTCR,r6
- sync
- isync
-
- /* Flush the L2 cache using the hardware assist */
- mfspr r3,SPRN_L2CR
- cmpwi r3,0 /* check if it is enabled first */
- bge 4f
- oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h
- b 2f
- /* When disabling/locking L2, code must be in L1 */
- .balign 32
-1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */
-3: sync
- isync
- b 1f
-2: b 3f
-3: sync
- isync
- b 1b
-1: sync
- isync
- ori r0,r3,L2CR_L2HWF_745x
- sync
- mtspr SPRN_L2CR,r0 /* set the hardware flush bit */
-3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */
- andi. r0,r0,L2CR_L2HWF_745x
- bne 3b
- sync
- rlwinm r3,r3,0,~L2CR_L2E
- b 2f
- /* When disabling L2, code must be in L1 */
- .balign 32
-1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */
-3: sync
- isync
- b 1f
-2: b 3f
-3: sync
- isync
- b 1b
-1: sync
- isync
- oris r4,r3,L2CR_L2I@h
- mtspr SPRN_L2CR,r4
- sync
- isync
-1: mfspr r4,SPRN_L2CR
- andis. r0,r4,L2CR_L2I@h
- bne 1b
- sync
-
-BEGIN_FTR_SECTION
- /* Flush the L3 cache using the hardware assist */
-4: mfspr r3,SPRN_L3CR
- cmpwi r3,0 /* check if it is enabled */
- bge 6f
- oris r0,r3,L3CR_L3IO@h
- ori r0,r0,L3CR_L3DO
- sync
- mtspr SPRN_L3CR,r0 /* lock the L3 cache */
- sync
- isync
- ori r0,r0,L3CR_L3HWF
- sync
- mtspr SPRN_L3CR,r0 /* set the hardware flush bit */
-5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */
- andi. r0,r0,L3CR_L3HWF
- bne 5b
- rlwinm r3,r3,0,~L3CR_L3E
- sync
- mtspr SPRN_L3CR,r3 /* disable the L3 cache */
- sync
- ori r4,r3,L3CR_L3I
- mtspr SPRN_L3CR,r4
-1: mfspr r4,SPRN_L3CR
- andi. r0,r4,L3CR_L3I
- bne 1b
- sync
-END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
-
-6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */
- rlwinm r0,r0,0,~HID0_DCE
- mtspr SPRN_HID0,r0
- sync
- isync
- mtmsr r11 /* restore DR and EE */
- isync
- blr
-#endif /* CONFIG_6xx */
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
deleted file mode 100644
index fba7e4d7c0bf..000000000000
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * arch/ppc/platforms/pmac_cpufreq.c
- *
- * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * Copyright (C) 2004 John Steele Scott <toojays@toojays.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.
- *
- * TODO: Need a big cleanup here. Basically, we need to have different
- * cpufreq_driver structures for the different type of HW instead of the
- * current mess. We also need to better deal with the detection of the
- * type of machine.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-#include <linux/init.h>
-#include <linux/sysdev.h>
-#include <linux/i2c.h>
-#include <linux/hardirq.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/pmac_feature.h>
-#include <asm/mmu_context.h>
-#include <asm/sections.h>
-#include <asm/cputable.h>
-#include <asm/time.h>
-#include <asm/system.h>
-#include <asm/open_pic.h>
-#include <asm/keylargo.h>
-
-/* WARNING !!! This will cause calibrate_delay() to be called,
- * but this is an __init function ! So you MUST go edit
- * init/main.c to make it non-init before enabling DEBUG_FREQ
- */
-#undef DEBUG_FREQ
-
-/*
- * There is a problem with the core cpufreq code on SMP kernels,
- * it won't recalculate the Bogomips properly
- */
-#ifdef CONFIG_SMP
-#warning "WARNING, CPUFREQ not recommended on SMP kernels"
-#endif
-
-extern void low_choose_7447a_dfs(int dfs);
-extern void low_choose_750fx_pll(int pll);
-extern void low_sleep_handler(void);
-
-/*
- * Currently, PowerMac cpufreq supports only high & low frequencies
- * that are set by the firmware
- */
-static unsigned int low_freq;
-static unsigned int hi_freq;
-static unsigned int cur_freq;
-static unsigned int sleep_freq;
-
-/*
- * Different models uses different mecanisms to switch the frequency
- */
-static int (*set_speed_proc)(int low_speed);
-static unsigned int (*get_speed_proc)(void);
-
-/*
- * Some definitions used by the various speedprocs
- */
-static u32 voltage_gpio;
-static u32 frequency_gpio;
-static u32 slew_done_gpio;
-static int no_schedule;
-static int has_cpu_l2lve;
-static int is_pmu_based;
-
-/* There are only two frequency states for each processor. Values
- * are in kHz for the time being.
- */
-#define CPUFREQ_HIGH 0
-#define CPUFREQ_LOW 1
-
-static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
- {CPUFREQ_HIGH, 0},
- {CPUFREQ_LOW, 0},
- {0, CPUFREQ_TABLE_END},
-};
-
-static struct freq_attr* pmac_cpu_freqs_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static inline void local_delay(unsigned long ms)
-{
- if (no_schedule)
- mdelay(ms);
- else
- msleep(ms);
-}
-
-static inline void wakeup_decrementer(void)
-{
- set_dec(tb_ticks_per_jiffy);
- /* No currently-supported powerbook has a 601,
- * so use get_tbl, not native
- */
- last_jiffy_stamp(0) = tb_last_stamp = get_tbl();
-}
-
-#ifdef DEBUG_FREQ
-static inline void debug_calc_bogomips(void)
-{
- /* This will cause a recalc of bogomips and display the
- * result. We backup/restore the value to avoid affecting the
- * core cpufreq framework's own calculation.
- */
- extern void calibrate_delay(void);
-
- unsigned long save_lpj = loops_per_jiffy;
- calibrate_delay();
- loops_per_jiffy = save_lpj;
-}
-#endif /* DEBUG_FREQ */
-
-/* Switch CPU speed under 750FX CPU control
- */
-static int cpu_750fx_cpu_speed(int low_speed)
-{
- u32 hid2;
-
- if (low_speed == 0) {
- /* ramping up, set voltage first */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
- /* Make sure we sleep for at least 1ms */
- local_delay(10);
-
- /* tweak L2 for high voltage */
- if (has_cpu_l2lve) {
- hid2 = mfspr(SPRN_HID2);
- hid2 &= ~0x2000;
- mtspr(SPRN_HID2, hid2);
- }
- }
-#ifdef CONFIG_6xx
- low_choose_750fx_pll(low_speed);
-#endif
- if (low_speed == 1) {
- /* tweak L2 for low voltage */
- if (has_cpu_l2lve) {
- hid2 = mfspr(SPRN_HID2);
- hid2 |= 0x2000;
- mtspr(SPRN_HID2, hid2);
- }
-
- /* ramping down, set voltage last */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
- local_delay(10);
- }
-
- return 0;
-}
-
-static unsigned int cpu_750fx_get_cpu_speed(void)
-{
- if (mfspr(SPRN_HID1) & HID1_PS)
- return low_freq;
- else
- return hi_freq;
-}
-
-/* Switch CPU speed using DFS */
-static int dfs_set_cpu_speed(int low_speed)
-{
- if (low_speed == 0) {
- /* ramping up, set voltage first */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
- /* Make sure we sleep for at least 1ms */
- local_delay(1);
- }
-
- /* set frequency */
-#ifdef CONFIG_6xx
- low_choose_7447a_dfs(low_speed);
-#endif
- udelay(100);
-
- if (low_speed == 1) {
- /* ramping down, set voltage last */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
- local_delay(1);
- }
-
- return 0;
-}
-
-static unsigned int dfs_get_cpu_speed(void)
-{
- if (mfspr(SPRN_HID1) & HID1_DFS)
- return low_freq;
- else
- return hi_freq;
-}
-
-
-/* Switch CPU speed using slewing GPIOs
- */
-static int gpios_set_cpu_speed(int low_speed)
-{
- int gpio, timeout = 0;
-
- /* If ramping up, set voltage first */
- if (low_speed == 0) {
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05);
- /* Delay is way too big but it's ok, we schedule */
- local_delay(10);
- }
-
- /* Set frequency */
- gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
- if (low_speed == ((gpio & 0x01) == 0))
- goto skip;
-
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio,
- low_speed ? 0x04 : 0x05);
- udelay(200);
- do {
- if (++timeout > 100)
- break;
- local_delay(1);
- gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0);
- } while((gpio & 0x02) == 0);
- skip:
- /* If ramping down, set voltage last */
- if (low_speed == 1) {
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04);
- /* Delay is way too big but it's ok, we schedule */
- local_delay(10);
- }
-
-#ifdef DEBUG_FREQ
- debug_calc_bogomips();
-#endif
-
- return 0;
-}
-
-/* Switch CPU speed under PMU control
- */
-static int pmu_set_cpu_speed(int low_speed)
-{
- struct adb_request req;
- unsigned long save_l2cr;
- unsigned long save_l3cr;
- unsigned int pic_prio;
- unsigned long flags;
-
- preempt_disable();
-
-#ifdef DEBUG_FREQ
- printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
-#endif
- pmu_suspend();
-
- /* Disable all interrupt sources on openpic */
- pic_prio = openpic_get_priority();
- openpic_set_priority(0xf);
-
- /* Make sure the decrementer won't interrupt us */
- asm volatile("mtdec %0" : : "r" (0x7fffffff));
- /* Make sure any pending DEC interrupt occuring while we did
- * the above didn't re-enable the DEC */
- mb();
- asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
- /* We can now disable MSR_EE */
- local_irq_save(flags);
-
- /* Giveup the FPU & vec */
- enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
- if (cpu_has_feature(CPU_FTR_ALTIVEC))
- enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
- /* Save & disable L2 and L3 caches */
- save_l3cr = _get_L3CR(); /* (returns -1 if not available) */
- save_l2cr = _get_L2CR(); /* (returns -1 if not available) */
-
- /* Send the new speed command. My assumption is that this command
- * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep
- */
- pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed);
- while (!req.complete)
- pmu_poll();
-
- /* Prepare the northbridge for the speed transition */
- pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1);
-
- /* Call low level code to backup CPU state and recover from
- * hardware reset
- */
- low_sleep_handler();
-
- /* Restore the northbridge */
- pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0);
-
- /* Restore L2 cache */
- if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0)
- _set_L2CR(save_l2cr);
- /* Restore L3 cache */
- if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0)
- _set_L3CR(save_l3cr);
-
- /* Restore userland MMU context */
- set_context(current->active_mm->context, current->active_mm->pgd);
-
-#ifdef DEBUG_FREQ
- printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
-#endif
-
- /* Restore low level PMU operations */
- pmu_unlock();
-
- /* Restore decrementer */
- wakeup_decrementer();
-
- /* Restore interrupts */
- openpic_set_priority(pic_prio);
-
- /* Let interrupts flow again ... */
- local_irq_restore(flags);
-
-#ifdef DEBUG_FREQ
- debug_calc_bogomips();
-#endif
-
- pmu_resume();
-
- preempt_enable();
-
- return 0;
-}
-
-static int do_set_cpu_speed(int speed_mode, int notify)
-{
- struct cpufreq_freqs freqs;
- unsigned long l3cr;
- static unsigned long prev_l3cr;
-
- freqs.old = cur_freq;
- freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
- freqs.cpu = smp_processor_id();
-
- if (freqs.old == freqs.new)
- return 0;
-
- if (notify)
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if (speed_mode == CPUFREQ_LOW &&
- cpu_has_feature(CPU_FTR_L3CR)) {
- l3cr = _get_L3CR();
- if (l3cr & L3CR_L3E) {
- prev_l3cr = l3cr;
- _set_L3CR(0);
- }
- }
- set_speed_proc(speed_mode == CPUFREQ_LOW);
- if (speed_mode == CPUFREQ_HIGH &&
- cpu_has_feature(CPU_FTR_L3CR)) {
- l3cr = _get_L3CR();
- if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
- _set_L3CR(prev_l3cr);
- }
- if (notify)
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
-
- return 0;
-}
-
-static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
-{
- return cur_freq;
-}
-
-static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
-}
-
-static int pmac_cpufreq_target( struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- unsigned int newstate = 0;
-
- if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs,
- target_freq, relation, &newstate))
- return -EINVAL;
-
- return do_set_cpu_speed(newstate, 1);
-}
-
-unsigned int pmac_get_one_cpufreq(int i)
-{
- /* Supports only one CPU for now */
- return (i == 0) ? cur_freq : 0;
-}
-
-static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- if (policy->cpu != 0)
- return -ENODEV;
-
- policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- policy->cur = cur_freq;
-
- cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
- return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
-}
-
-static u32 read_gpio(struct device_node *np)
-{
- u32 *reg = (u32 *)get_property(np, "reg", NULL);
- u32 offset;
-
- if (reg == NULL)
- return 0;
- /* That works for all keylargos but shall be fixed properly
- * some day... The problem is that it seems we can't rely
- * on the "reg" property of the GPIO nodes, they are either
- * relative to the base of KeyLargo or to the base of the
- * GPIO space, and the device-tree doesn't help.
- */
- offset = *reg;
- if (offset < KEYLARGO_GPIO_LEVELS0)
- offset += KEYLARGO_GPIO_LEVELS0;
- return offset;
-}
-
-static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
-{
- /* Ok, this could be made a bit smarter, but let's be robust for now. We
- * always force a speed change to high speed before sleep, to make sure
- * we have appropriate voltage and/or bus speed for the wakeup process,
- * and to make sure our loops_per_jiffies are "good enough", that is will
- * not cause too short delays if we sleep in low speed and wake in high
- * speed..
- */
- no_schedule = 1;
- sleep_freq = cur_freq;
- if (cur_freq == low_freq && !is_pmu_based)
- do_set_cpu_speed(CPUFREQ_HIGH, 0);
- return 0;
-}
-
-static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
-{
- /* If we resume, first check if we have a get() function */
- if (get_speed_proc)
- cur_freq = get_speed_proc();
- else
- cur_freq = 0;
-
- /* We don't, hrm... we don't really know our speed here, best
- * is that we force a switch to whatever it was, which is
- * probably high speed due to our suspend() routine
- */
- do_set_cpu_speed(sleep_freq == low_freq ?
- CPUFREQ_LOW : CPUFREQ_HIGH, 0);
-
- no_schedule = 0;
- return 0;
-}
-
-static struct cpufreq_driver pmac_cpufreq_driver = {
- .verify = pmac_cpufreq_verify,
- .target = pmac_cpufreq_target,
- .get = pmac_cpufreq_get_speed,
- .init = pmac_cpufreq_cpu_init,
- .suspend = pmac_cpufreq_suspend,
- .resume = pmac_cpufreq_resume,
- .flags = CPUFREQ_PM_NO_WARN,
- .attr = pmac_cpu_freqs_attr,
- .name = "powermac",
- .owner = THIS_MODULE,
-};
-
-
-static int pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
-{
- struct device_node *volt_gpio_np = of_find_node_by_name(NULL,
- "voltage-gpio");
- struct device_node *freq_gpio_np = of_find_node_by_name(NULL,
- "frequency-gpio");
- struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL,
- "slewing-done");
- u32 *value;
-
- /*
- * Check to see if it's GPIO driven or PMU only
- *
- * The way we extract the GPIO address is slightly hackish, but it
- * works well enough for now. We need to abstract the whole GPIO
- * stuff sooner or later anyway
- */
-
- if (volt_gpio_np)
- voltage_gpio = read_gpio(volt_gpio_np);
- if (freq_gpio_np)
- frequency_gpio = read_gpio(freq_gpio_np);
- if (slew_done_gpio_np)
- slew_done_gpio = read_gpio(slew_done_gpio_np);
-
- /* If we use the frequency GPIOs, calculate the min/max speeds based
- * on the bus frequencies
- */
- if (frequency_gpio && slew_done_gpio) {
- int lenp, rc;
- u32 *freqs, *ratio;
-
- freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp);
- lenp /= sizeof(u32);
- if (freqs == NULL || lenp != 2) {
- printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
- return 1;
- }
- ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL);
- if (ratio == NULL) {
- printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
- return 1;
- }
-
- /* Get the min/max bus frequencies */
- low_freq = min(freqs[0], freqs[1]);
- hi_freq = max(freqs[0], freqs[1]);
-
- /* Grrrr.. It _seems_ that the device-tree is lying on the low bus
- * frequency, it claims it to be around 84Mhz on some models while
- * it appears to be approx. 101Mhz on all. Let's hack around here...
- * fortunately, we don't need to be too precise
- */
- if (low_freq < 98000000)
- low_freq = 101000000;
-
- /* Convert those to CPU core clocks */
- low_freq = (low_freq * (*ratio)) / 2000;
- hi_freq = (hi_freq * (*ratio)) / 2000;
-
- /* Now we get the frequencies, we read the GPIO to see what is out current
- * speed
- */
- rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0);
- cur_freq = (rc & 0x01) ? hi_freq : low_freq;
-
- set_speed_proc = gpios_set_cpu_speed;
- return 1;
- }
-
- /* If we use the PMU, look for the min & max frequencies in the
- * device-tree
- */
- value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL);
- if (!value)
- return 1;
- low_freq = (*value) / 1000;
- /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree
- * here */
- if (low_freq < 100000)
- low_freq *= 10;
-
- value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL);
- if (!value)
- return 1;
- hi_freq = (*value) / 1000;
- set_speed_proc = pmu_set_cpu_speed;
- is_pmu_based = 1;
-
- return 0;
-}
-
-static int pmac_cpufreq_init_7447A(struct device_node *cpunode)
-{
- struct device_node *volt_gpio_np;
-
- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
- return 1;
-
- volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
- if (volt_gpio_np)
- voltage_gpio = read_gpio(volt_gpio_np);
- if (!voltage_gpio){
- printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
- return 1;
- }
-
- /* OF only reports the high frequency */
- hi_freq = cur_freq;
- low_freq = cur_freq/2;
-
- /* Read actual frequency from CPU */
- cur_freq = dfs_get_cpu_speed();
- set_speed_proc = dfs_set_cpu_speed;
- get_speed_proc = dfs_get_cpu_speed;
-
- return 0;
-}
-
-static int pmac_cpufreq_init_750FX(struct device_node *cpunode)
-{
- struct device_node *volt_gpio_np;
- u32 pvr, *value;
-
- if (get_property(cpunode, "dynamic-power-step", NULL) == NULL)
- return 1;
-
- hi_freq = cur_freq;
- value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL);
- if (!value)
- return 1;
- low_freq = (*value) / 1000;
-
- volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select");
- if (volt_gpio_np)
- voltage_gpio = read_gpio(volt_gpio_np);
-
- pvr = mfspr(SPRN_PVR);
- has_cpu_l2lve = !((pvr & 0xf00) == 0x100);
-
- set_speed_proc = cpu_750fx_cpu_speed;
- get_speed_proc = cpu_750fx_get_cpu_speed;
- cur_freq = cpu_750fx_get_cpu_speed();
-
- return 0;
-}
-
-/* Currently, we support the following machines:
- *
- * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz)
- * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
- * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
- * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
- * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
- * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
- * - Recent MacRISC3 laptops
- * - All new machines with 7447A CPUs
- */
-static int __init pmac_cpufreq_setup(void)
-{
- struct device_node *cpunode;
- u32 *value;
-
- if (strstr(cmd_line, "nocpufreq"))
- return 0;
-
- /* Assume only one CPU */
- cpunode = find_type_devices("cpu");
- if (!cpunode)
- goto out;
-
- /* Get current cpu clock freq */
- value = (u32 *)get_property(cpunode, "clock-frequency", NULL);
- if (!value)
- goto out;
- cur_freq = (*value) / 1000;
-
- /* Check for 7447A based MacRISC3 */
- if (machine_is_compatible("MacRISC3") &&
- get_property(cpunode, "dynamic-power-step", NULL) &&
- PVR_VER(mfspr(SPRN_PVR)) == 0x8003) {
- pmac_cpufreq_init_7447A(cpunode);
- /* Check for other MacRISC3 machines */
- } else if (machine_is_compatible("PowerBook3,4") ||
- machine_is_compatible("PowerBook3,5") ||
- machine_is_compatible("MacRISC3")) {
- pmac_cpufreq_init_MacRISC3(cpunode);
- /* Else check for iBook2 500/600 */
- } else if (machine_is_compatible("PowerBook4,1")) {
- hi_freq = cur_freq;
- low_freq = 400000;
- set_speed_proc = pmu_set_cpu_speed;
- is_pmu_based = 1;
- }
- /* Else check for TiPb 550 */
- else if (machine_is_compatible("PowerBook3,3") && cur_freq == 550000) {
- hi_freq = cur_freq;
- low_freq = 500000;
- set_speed_proc = pmu_set_cpu_speed;
- is_pmu_based = 1;
- }
- /* Else check for TiPb 400 & 500 */
- else if (machine_is_compatible("PowerBook3,2")) {
- /* We only know about the 400 MHz and the 500Mhz model
- * they both have 300 MHz as low frequency
- */
- if (cur_freq < 350000 || cur_freq > 550000)
- goto out;
- hi_freq = cur_freq;
- low_freq = 300000;
- set_speed_proc = pmu_set_cpu_speed;
- is_pmu_based = 1;
- }
- /* Else check for 750FX */
- else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
- pmac_cpufreq_init_750FX(cpunode);
-out:
- if (set_speed_proc == NULL)
- return -ENODEV;
-
- pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq;
- pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
-
- printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
- printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
- low_freq/1000, hi_freq/1000, cur_freq/1000);
-
- return cpufreq_register_driver(&pmac_cpufreq_driver);
-}
-
-module_init(pmac_cpufreq_setup);
-
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
deleted file mode 100644
index 6b7b3a150631..000000000000
--- a/arch/ppc/platforms/pmac_feature.c
+++ /dev/null
@@ -1,3023 +0,0 @@
-/*
- * arch/ppc/platforms/pmac_feature.c
- *
- * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
- * Ben. Herrenschmidt (benh@kernel.crashing.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.
- *
- * TODO:
- *
- * - Replace mdelay with some schedule loop if possible
- * - Shorten some obfuscated delays on some routines (like modem
- * power)
- * - Refcount some clocks (see darwin)
- * - Split split split...
- *
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <asm/sections.h>
-#include <asm/errno.h>
-#include <asm/ohare.h>
-#include <asm/heathrow.h>
-#include <asm/keylargo.h>
-#include <asm/uninorth.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/dbdma.h>
-#include <asm/pci-bridge.h>
-#include <asm/pmac_low_i2c.h>
-
-#undef DEBUG_FEATURE
-
-#ifdef DEBUG_FEATURE
-#define DBG(fmt,...) printk(KERN_DEBUG fmt)
-#else
-#define DBG(fmt,...)
-#endif
-
-#ifdef CONFIG_6xx
-extern int powersave_lowspeed;
-#endif
-
-extern int powersave_nap;
-extern struct device_node *k2_skiplist[2];
-
-
-/*
- * We use a single global lock to protect accesses. Each driver has
- * to take care of its own locking
- */
-static DEFINE_SPINLOCK(feature_lock);
-
-#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags);
-#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags);
-
-
-/*
- * Instance of some macio stuffs
- */
-struct macio_chip macio_chips[MAX_MACIO_CHIPS];
-
-struct macio_chip* macio_find(struct device_node* child, int type)
-{
- while(child) {
- int i;
-
- for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
- if (child == macio_chips[i].of_node &&
- (!type || macio_chips[i].type == type))
- return &macio_chips[i];
- child = child->parent;
- }
- return NULL;
-}
-EXPORT_SYMBOL_GPL(macio_find);
-
-static const char* macio_names[] =
-{
- "Unknown",
- "Grand Central",
- "OHare",
- "OHareII",
- "Heathrow",
- "Gatwick",
- "Paddington",
- "Keylargo",
- "Pangea",
- "Intrepid",
- "K2"
-};
-
-
-
-/*
- * Uninorth reg. access. Note that Uni-N regs are big endian
- */
-
-#define UN_REG(r) (uninorth_base + ((r) >> 2))
-#define UN_IN(r) (in_be32(UN_REG(r)))
-#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
-
-static struct device_node* uninorth_node;
-static u32 __iomem * uninorth_base;
-static u32 uninorth_rev;
-static int uninorth_u3;
-static void __iomem *u3_ht;
-
-/*
- * For each motherboard family, we have a table of functions pointers
- * that handle the various features.
- */
-
-typedef long (*feature_call)(struct device_node* node, long param, long value);
-
-struct feature_table_entry {
- unsigned int selector;
- feature_call function;
-};
-
-struct pmac_mb_def
-{
- const char* model_string;
- const char* model_name;
- int model_id;
- struct feature_table_entry* features;
- unsigned long board_flags;
-};
-static struct pmac_mb_def pmac_mb;
-
-/*
- * Here are the chip specific feature functions
- */
-
-static inline int
-simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
-{
- struct macio_chip* macio;
- unsigned long flags;
-
- macio = macio_find(node, type);
- if (!macio)
- return -ENODEV;
- LOCK(flags);
- if (value)
- MACIO_BIS(reg, mask);
- else
- MACIO_BIC(reg, mask);
- (void)MACIO_IN32(reg);
- UNLOCK(flags);
-
- return 0;
-}
-
-#ifndef CONFIG_POWER4
-
-static long
-ohare_htw_scc_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long chan_mask;
- unsigned long fcr;
- unsigned long flags;
- int htw, trans;
- unsigned long rmask;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- if (!strcmp(node->name, "ch-a"))
- chan_mask = MACIO_FLAG_SCCA_ON;
- else if (!strcmp(node->name, "ch-b"))
- chan_mask = MACIO_FLAG_SCCB_ON;
- else
- return -ENODEV;
-
- htw = (macio->type == macio_heathrow || macio->type == macio_paddington
- || macio->type == macio_gatwick);
- /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
- trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
- pmac_mb.model_id != PMAC_TYPE_YIKES);
- if (value) {
-#ifdef CONFIG_ADB_PMU
- if ((param & 0xfff) == PMAC_SCC_IRDA)
- pmu_enable_irled(1);
-#endif /* CONFIG_ADB_PMU */
- LOCK(flags);
- fcr = MACIO_IN32(OHARE_FCR);
- /* Check if scc cell need enabling */
- if (!(fcr & OH_SCC_ENABLE)) {
- fcr |= OH_SCC_ENABLE;
- if (htw) {
- /* Side effect: this will also power up the
- * modem, but it's too messy to figure out on which
- * ports this controls the tranceiver and on which
- * it controls the modem
- */
- if (trans)
- fcr &= ~HRW_SCC_TRANS_EN_N;
- MACIO_OUT32(OHARE_FCR, fcr);
- fcr |= (rmask = HRW_RESET_SCC);
- MACIO_OUT32(OHARE_FCR, fcr);
- } else {
- fcr |= (rmask = OH_SCC_RESET);
- MACIO_OUT32(OHARE_FCR, fcr);
- }
- UNLOCK(flags);
- (void)MACIO_IN32(OHARE_FCR);
- mdelay(15);
- LOCK(flags);
- fcr &= ~rmask;
- MACIO_OUT32(OHARE_FCR, fcr);
- }
- if (chan_mask & MACIO_FLAG_SCCA_ON)
- fcr |= OH_SCCA_IO;
- if (chan_mask & MACIO_FLAG_SCCB_ON)
- fcr |= OH_SCCB_IO;
- MACIO_OUT32(OHARE_FCR, fcr);
- macio->flags |= chan_mask;
- UNLOCK(flags);
- if (param & PMAC_SCC_FLAG_XMON)
- macio->flags |= MACIO_FLAG_SCC_LOCKED;
- } else {
- if (macio->flags & MACIO_FLAG_SCC_LOCKED)
- return -EPERM;
- LOCK(flags);
- fcr = MACIO_IN32(OHARE_FCR);
- if (chan_mask & MACIO_FLAG_SCCA_ON)
- fcr &= ~OH_SCCA_IO;
- if (chan_mask & MACIO_FLAG_SCCB_ON)
- fcr &= ~OH_SCCB_IO;
- MACIO_OUT32(OHARE_FCR, fcr);
- if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
- fcr &= ~OH_SCC_ENABLE;
- if (htw && trans)
- fcr |= HRW_SCC_TRANS_EN_N;
- MACIO_OUT32(OHARE_FCR, fcr);
- }
- macio->flags &= ~(chan_mask);
- UNLOCK(flags);
- mdelay(10);
-#ifdef CONFIG_ADB_PMU
- if ((param & 0xfff) == PMAC_SCC_IRDA)
- pmu_enable_irled(0);
-#endif /* CONFIG_ADB_PMU */
- }
- return 0;
-}
-
-static long
-ohare_floppy_enable(struct device_node* node, long param, long value)
-{
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_FLOPPY_ENABLE, value);
-}
-
-static long
-ohare_mesh_enable(struct device_node* node, long param, long value)
-{
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_MESH_ENABLE, value);
-}
-
-static long
-ohare_ide_enable(struct device_node* node, long param, long value)
-{
- switch(param) {
- case 0:
- /* For some reason, setting the bit in set_initial_features()
- * doesn't stick. I'm still investigating... --BenH.
- */
- if (value)
- simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_IOBUS_ENABLE, 1);
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_IDE0_ENABLE, value);
- case 1:
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_BAY_IDE_ENABLE, value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-ohare_ide_reset(struct device_node* node, long param, long value)
-{
- switch(param) {
- case 0:
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_IDE0_RESET_N, !value);
- case 1:
- return simple_feature_tweak(node, macio_ohare,
- OHARE_FCR, OH_IDE1_RESET_N, !value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-ohare_sleep_state(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio = &macio_chips[0];
-
- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
- return -EPERM;
- if (value == 1) {
- MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
- } else if (value == 0) {
- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
- }
-
- return 0;
-}
-
-static long
-heathrow_modem_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- u8 gpio;
- unsigned long flags;
-
- macio = macio_find(node, macio_unknown);
- if (!macio)
- return -ENODEV;
- gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
- if (!value) {
- LOCK(flags);
- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
- UNLOCK(flags);
- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- mdelay(250);
- }
- if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
- pmac_mb.model_id != PMAC_TYPE_YIKES) {
- LOCK(flags);
- if (value)
- MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
- else
- MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
- UNLOCK(flags);
- (void)MACIO_IN32(HEATHROW_FCR);
- mdelay(250);
- }
- if (value) {
- LOCK(flags);
- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
- (void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250);
- }
- return 0;
-}
-
-static long
-heathrow_floppy_enable(struct device_node* node, long param, long value)
-{
- return simple_feature_tweak(node, macio_unknown,
- HEATHROW_FCR,
- HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
- value);
-}
-
-static long
-heathrow_mesh_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
-
- macio = macio_find(node, macio_unknown);
- if (!macio)
- return -ENODEV;
- LOCK(flags);
- /* Set clear mesh cell enable */
- if (value)
- MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
- else
- MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
- (void)MACIO_IN32(HEATHROW_FCR);
- udelay(10);
- /* Set/Clear termination power */
- if (value)
- MACIO_BIC(HEATHROW_MBCR, 0x04000000);
- else
- MACIO_BIS(HEATHROW_MBCR, 0x04000000);
- (void)MACIO_IN32(HEATHROW_MBCR);
- udelay(10);
- UNLOCK(flags);
-
- return 0;
-}
-
-static long
-heathrow_ide_enable(struct device_node* node, long param, long value)
-{
- switch(param) {
- case 0:
- return simple_feature_tweak(node, macio_unknown,
- HEATHROW_FCR, HRW_IDE0_ENABLE, value);
- case 1:
- return simple_feature_tweak(node, macio_unknown,
- HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-heathrow_ide_reset(struct device_node* node, long param, long value)
-{
- switch(param) {
- case 0:
- return simple_feature_tweak(node, macio_unknown,
- HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
- case 1:
- return simple_feature_tweak(node, macio_unknown,
- HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-heathrow_bmac_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- if (value) {
- LOCK(flags);
- MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
- MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
- UNLOCK(flags);
- (void)MACIO_IN32(HEATHROW_FCR);
- mdelay(10);
- LOCK(flags);
- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
- UNLOCK(flags);
- (void)MACIO_IN32(HEATHROW_FCR);
- mdelay(10);
- } else {
- LOCK(flags);
- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
- UNLOCK(flags);
- }
- return 0;
-}
-
-static long
-heathrow_sound_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
-
- /* B&W G3 and Yikes don't support that properly (the
- * sound appear to never come back after beeing shut down).
- */
- if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
- pmac_mb.model_id == PMAC_TYPE_YIKES)
- return 0;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- if (value) {
- LOCK(flags);
- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
- UNLOCK(flags);
- (void)MACIO_IN32(HEATHROW_FCR);
- } else {
- LOCK(flags);
- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
- UNLOCK(flags);
- }
- return 0;
-}
-
-static u32 save_fcr[6];
-static u32 save_mbcr;
-static u32 save_gpio_levels[2];
-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
-static u32 save_unin_clock_ctl;
-static struct dbdma_regs save_dbdma[13];
-static struct dbdma_regs save_alt_dbdma[13];
-
-static void
-dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
-{
- int i;
-
- /* Save state & config of DBDMA channels */
- for (i=0; i<13; i++) {
- volatile struct dbdma_regs __iomem * chan = (void __iomem *)
- (macio->base + ((0x8000+i*0x100)>>2));
- save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
- save[i].cmdptr = in_le32(&chan->cmdptr);
- save[i].intr_sel = in_le32(&chan->intr_sel);
- save[i].br_sel = in_le32(&chan->br_sel);
- save[i].wait_sel = in_le32(&chan->wait_sel);
- }
-}
-
-static void
-dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
-{
- int i;
-
- /* Save state & config of DBDMA channels */
- for (i=0; i<13; i++) {
- volatile struct dbdma_regs __iomem * chan = (void __iomem *)
- (macio->base + ((0x8000+i*0x100)>>2));
- out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
- while (in_le32(&chan->status) & ACTIVE)
- mb();
- out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
- out_le32(&chan->cmdptr, save[i].cmdptr);
- out_le32(&chan->intr_sel, save[i].intr_sel);
- out_le32(&chan->br_sel, save[i].br_sel);
- out_le32(&chan->wait_sel, save[i].wait_sel);
- }
-}
-
-static void
-heathrow_sleep(struct macio_chip* macio, int secondary)
-{
- if (secondary) {
- dbdma_save(macio, save_alt_dbdma);
- save_fcr[2] = MACIO_IN32(0x38);
- save_fcr[3] = MACIO_IN32(0x3c);
- } else {
- dbdma_save(macio, save_dbdma);
- save_fcr[0] = MACIO_IN32(0x38);
- save_fcr[1] = MACIO_IN32(0x3c);
- save_mbcr = MACIO_IN32(0x34);
- /* Make sure sound is shut down */
- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
- /* This seems to be necessary as well or the fan
- * keeps coming up and battery drains fast */
- MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
- MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N);
- /* Make sure eth is down even if module or sleep
- * won't work properly */
- MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
- }
- /* Make sure modem is shut down */
- MACIO_OUT8(HRW_GPIO_MODEM_RESET,
- MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
- MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
- MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
-
- /* Let things settle */
- (void)MACIO_IN32(HEATHROW_FCR);
-}
-
-static void
-heathrow_wakeup(struct macio_chip* macio, int secondary)
-{
- if (secondary) {
- MACIO_OUT32(0x38, save_fcr[2]);
- (void)MACIO_IN32(0x38);
- mdelay(1);
- MACIO_OUT32(0x3c, save_fcr[3]);
- (void)MACIO_IN32(0x38);
- mdelay(10);
- dbdma_restore(macio, save_alt_dbdma);
- } else {
- MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
- (void)MACIO_IN32(0x38);
- mdelay(1);
- MACIO_OUT32(0x3c, save_fcr[1]);
- (void)MACIO_IN32(0x38);
- mdelay(1);
- MACIO_OUT32(0x34, save_mbcr);
- (void)MACIO_IN32(0x38);
- mdelay(10);
- dbdma_restore(macio, save_dbdma);
- }
-}
-
-static long
-heathrow_sleep_state(struct device_node* node, long param, long value)
-{
- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
- return -EPERM;
- if (value == 1) {
- if (macio_chips[1].type == macio_gatwick)
- heathrow_sleep(&macio_chips[0], 1);
- heathrow_sleep(&macio_chips[0], 0);
- } else if (value == 0) {
- heathrow_wakeup(&macio_chips[0], 0);
- if (macio_chips[1].type == macio_gatwick)
- heathrow_wakeup(&macio_chips[0], 1);
- }
- return 0;
-}
-
-static long
-core99_scc_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
- unsigned long chan_mask;
- u32 fcr;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- if (!strcmp(node->name, "ch-a"))
- chan_mask = MACIO_FLAG_SCCA_ON;
- else if (!strcmp(node->name, "ch-b"))
- chan_mask = MACIO_FLAG_SCCB_ON;
- else
- return -ENODEV;
-
- if (value) {
- int need_reset_scc = 0;
- int need_reset_irda = 0;
-
- LOCK(flags);
- fcr = MACIO_IN32(KEYLARGO_FCR0);
- /* Check if scc cell need enabling */
- if (!(fcr & KL0_SCC_CELL_ENABLE)) {
- fcr |= KL0_SCC_CELL_ENABLE;
- need_reset_scc = 1;
- }
- if (chan_mask & MACIO_FLAG_SCCA_ON) {
- fcr |= KL0_SCCA_ENABLE;
- /* Don't enable line drivers for I2S modem */
- if ((param & 0xfff) == PMAC_SCC_I2S1)
- fcr &= ~KL0_SCC_A_INTF_ENABLE;
- else
- fcr |= KL0_SCC_A_INTF_ENABLE;
- }
- if (chan_mask & MACIO_FLAG_SCCB_ON) {
- fcr |= KL0_SCCB_ENABLE;
- /* Perform irda specific inits */
- if ((param & 0xfff) == PMAC_SCC_IRDA) {
- fcr &= ~KL0_SCC_B_INTF_ENABLE;
- fcr |= KL0_IRDA_ENABLE;
- fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
- fcr |= KL0_IRDA_SOURCE1_SEL;
- fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
- fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
- need_reset_irda = 1;
- } else
- fcr |= KL0_SCC_B_INTF_ENABLE;
- }
- MACIO_OUT32(KEYLARGO_FCR0, fcr);
- macio->flags |= chan_mask;
- if (need_reset_scc) {
- MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- UNLOCK(flags);
- mdelay(15);
- LOCK(flags);
- MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
- }
- if (need_reset_irda) {
- MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- UNLOCK(flags);
- mdelay(15);
- LOCK(flags);
- MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
- }
- UNLOCK(flags);
- if (param & PMAC_SCC_FLAG_XMON)
- macio->flags |= MACIO_FLAG_SCC_LOCKED;
- } else {
- if (macio->flags & MACIO_FLAG_SCC_LOCKED)
- return -EPERM;
- LOCK(flags);
- fcr = MACIO_IN32(KEYLARGO_FCR0);
- if (chan_mask & MACIO_FLAG_SCCA_ON)
- fcr &= ~KL0_SCCA_ENABLE;
- if (chan_mask & MACIO_FLAG_SCCB_ON) {
- fcr &= ~KL0_SCCB_ENABLE;
- /* Perform irda specific clears */
- if ((param & 0xfff) == PMAC_SCC_IRDA) {
- fcr &= ~KL0_IRDA_ENABLE;
- fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
- fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
- fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
- }
- }
- MACIO_OUT32(KEYLARGO_FCR0, fcr);
- if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
- fcr &= ~KL0_SCC_CELL_ENABLE;
- MACIO_OUT32(KEYLARGO_FCR0, fcr);
- }
- macio->flags &= ~(chan_mask);
- UNLOCK(flags);
- mdelay(10);
- }
- return 0;
-}
-
-static long
-core99_modem_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- u8 gpio;
- unsigned long flags;
-
- /* Hack for internal USB modem */
- if (node == NULL) {
- if (macio_chips[0].type != macio_keylargo)
- return -ENODEV;
- node = macio_chips[0].of_node;
- }
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
- gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
- gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
-
- if (!value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- UNLOCK(flags);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- mdelay(250);
- }
- LOCK(flags);
- if (value) {
- MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- UNLOCK(flags);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- mdelay(250);
- } else {
- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- UNLOCK(flags);
- }
- if (value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250);
- }
- return 0;
-}
-
-static long
-pangea_modem_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- u8 gpio;
- unsigned long flags;
-
- /* Hack for internal USB modem */
- if (node == NULL) {
- if (macio_chips[0].type != macio_pangea &&
- macio_chips[0].type != macio_intrepid)
- return -ENODEV;
- node = macio_chips[0].of_node;
- }
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
- gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
- gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
- gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
-
- if (!value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- UNLOCK(flags);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- mdelay(250);
- }
- LOCK(flags);
- if (value) {
- MACIO_OUT8(KL_GPIO_MODEM_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE);
- UNLOCK(flags);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- mdelay(250);
- } else {
- MACIO_OUT8(KL_GPIO_MODEM_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
- UNLOCK(flags);
- }
- if (value) {
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250); LOCK(flags);
- MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
- (void)MACIO_IN8(KL_GPIO_MODEM_RESET);
- UNLOCK(flags); mdelay(250);
- }
- return 0;
-}
-
-static long
-core99_ata100_enable(struct device_node* node, long value)
-{
- unsigned long flags;
- struct pci_dev *pdev = NULL;
- u8 pbus, pid;
-
- if (uninorth_rev < 0x24)
- return -ENODEV;
-
- LOCK(flags);
- if (value)
- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
- else
- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- UNLOCK(flags);
- udelay(20);
-
- if (value) {
- if (pci_device_from_OF_node(node, &pbus, &pid) == 0)
- pdev = pci_find_slot(pbus, pid);
- if (pdev == NULL)
- return 0;
- pci_enable_device(pdev);
- pci_set_master(pdev);
- }
- return 0;
-}
-
-static long
-core99_ide_enable(struct device_node* node, long param, long value)
-{
- /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2
- * based ata-100
- */
- switch(param) {
- case 0:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
- case 1:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
- case 2:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
- case 3:
- return core99_ata100_enable(node, value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-core99_ide_reset(struct device_node* node, long param, long value)
-{
- switch(param) {
- case 0:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
- case 1:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
- case 2:
- return simple_feature_tweak(node, macio_unknown,
- KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
- default:
- return -ENODEV;
- }
-}
-
-static long
-core99_gmac_enable(struct device_node* node, long param, long value)
-{
- unsigned long flags;
-
- LOCK(flags);
- if (value)
- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
- else
- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- UNLOCK(flags);
- udelay(20);
-
- return 0;
-}
-
-static long
-core99_gmac_phy_reset(struct device_node* node, long param, long value)
-{
- unsigned long flags;
- struct macio_chip* macio;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
-
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
- UNLOCK(flags);
- mdelay(10);
- LOCK(flags);
- MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */
- KEYLARGO_GPIO_OUTOUT_DATA);
- UNLOCK(flags);
- mdelay(10);
-
- return 0;
-}
-
-static long
-core99_sound_chip_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
-
- /* Do a better probe code, screamer G4 desktops &
- * iMacs can do that too, add a recalibrate in
- * the driver as well
- */
- if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
- pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
- LOCK(flags);
- if (value)
- MACIO_OUT8(KL_GPIO_SOUND_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE |
- KEYLARGO_GPIO_OUTOUT_DATA);
- else
- MACIO_OUT8(KL_GPIO_SOUND_POWER,
- KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)MACIO_IN8(KL_GPIO_SOUND_POWER);
- UNLOCK(flags);
- }
- return 0;
-}
-
-static long
-core99_airport_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
- int state;
-
- macio = macio_find(node, 0);
- if (!macio)
- return -ENODEV;
-
- /* Hint: we allow passing of macio itself for the sake of the
- * sleep code
- */
- if (node != macio->of_node &&
- (!node->parent || node->parent != macio->of_node))
- return -ENODEV;
- state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
- if (value == state)
- return 0;
- if (value) {
- /* This code is a reproduction of OF enable-cardslot
- * and init-wireless methods, slightly hacked until
- * I got it working.
- */
- LOCK(flags);
- MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
- UNLOCK(flags);
- mdelay(10);
- LOCK(flags);
- MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
- UNLOCK(flags);
-
- mdelay(10);
-
- LOCK(flags);
- MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- udelay(10);
- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
- udelay(10);
- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
- udelay(10);
- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
- (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
- udelay(10);
- MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
- udelay(10);
- MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
- (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
- UNLOCK(flags);
- udelay(10);
- MACIO_OUT32(0x1c000, 0);
- mdelay(1);
- MACIO_OUT8(0x1a3e0, 0x41);
- (void)MACIO_IN8(0x1a3e0);
- udelay(10);
- LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- UNLOCK(flags);
- mdelay(100);
-
- macio->flags |= MACIO_FLAG_AIRPORT_ON;
- } else {
- LOCK(flags);
- MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
- (void)MACIO_IN32(KEYLARGO_FCR2);
- MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
- MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
- MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
- MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
- MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
- (void)MACIO_IN8(KL_GPIO_AIRPORT_4);
- UNLOCK(flags);
-
- macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
- }
- return 0;
-}
-
-#ifdef CONFIG_SMP
-static long
-core99_reset_cpu(struct device_node* node, long param, long value)
-{
- unsigned int reset_io = 0;
- unsigned long flags;
- struct macio_chip* macio;
- struct device_node* np;
- const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0,
- KL_GPIO_RESET_CPU1,
- KL_GPIO_RESET_CPU2,
- KL_GPIO_RESET_CPU3 };
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo)
- return -ENODEV;
-
- np = find_path_device("/cpus");
- if (np == NULL)
- return -ENODEV;
- for (np = np->child; np != NULL; np = np->sibling) {
- u32* num = (u32 *)get_property(np, "reg", NULL);
- u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
- if (num == NULL || rst == NULL)
- continue;
- if (param == *num) {
- reset_io = *rst;
- break;
- }
- }
- if (np == NULL || reset_io == 0)
- reset_io = dflt_reset_lines[param];
-
- LOCK(flags);
- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)MACIO_IN8(reset_io);
- udelay(1);
- MACIO_OUT8(reset_io, 0);
- (void)MACIO_IN8(reset_io);
- UNLOCK(flags);
-
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-static long
-core99_usb_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio;
- unsigned long flags;
- char* prop;
- int number;
- u32 reg;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
-
- prop = (char *)get_property(node, "AAPL,clock-id", NULL);
- if (!prop)
- return -ENODEV;
- if (strncmp(prop, "usb0u048", 8) == 0)
- number = 0;
- else if (strncmp(prop, "usb1u148", 8) == 0)
- number = 2;
- else if (strncmp(prop, "usb2u248", 8) == 0)
- number = 4;
- else
- return -ENODEV;
-
- /* Sorry for the brute-force locking, but this is only used during
- * sleep and the timing seem to be critical
- */
- LOCK(flags);
- if (value) {
- /* Turn ON */
- if (number == 0) {
- MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
- (void)MACIO_IN32(KEYLARGO_FCR0);
- UNLOCK(flags);
- mdelay(1);
- LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
- } else if (number == 2) {
- MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
- UNLOCK(flags);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- mdelay(1);
- LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
- } else if (number == 4) {
- MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
- UNLOCK(flags);
- (void)MACIO_IN32(KEYLARGO_FCR1);
- mdelay(1);
- LOCK(flags);
- MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE);
- }
- if (number < 4) {
- reg = MACIO_IN32(KEYLARGO_FCR4);
- reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
- KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
- reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
- KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
- MACIO_OUT32(KEYLARGO_FCR4, reg);
- (void)MACIO_IN32(KEYLARGO_FCR4);
- udelay(10);
- } else {
- reg = MACIO_IN32(KEYLARGO_FCR3);
- reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
- KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0));
- reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
- KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1));
- MACIO_OUT32(KEYLARGO_FCR3, reg);
- (void)MACIO_IN32(KEYLARGO_FCR3);
- udelay(10);
- }
- if (macio->type == macio_intrepid) {
- /* wait for clock stopped bits to clear */
- u32 test0 = 0, test1 = 0;
- u32 status0, status1;
- int timeout = 1000;
-
- UNLOCK(flags);
- switch (number) {
- case 0:
- test0 = UNI_N_CLOCK_STOPPED_USB0;
- test1 = UNI_N_CLOCK_STOPPED_USB0PCI;
- break;
- case 2:
- test0 = UNI_N_CLOCK_STOPPED_USB1;
- test1 = UNI_N_CLOCK_STOPPED_USB1PCI;
- break;
- case 4:
- test0 = UNI_N_CLOCK_STOPPED_USB2;
- test1 = UNI_N_CLOCK_STOPPED_USB2PCI;
- break;
- }
- do {
- if (--timeout <= 0) {
- printk(KERN_ERR "core99_usb_enable: "
- "Timeout waiting for clocks\n");
- break;
- }
- mdelay(1);
- status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0);
- status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1);
- } while ((status0 & test0) | (status1 & test1));
- LOCK(flags);
- }
- } else {
- /* Turn OFF */
- if (number < 4) {
- reg = MACIO_IN32(KEYLARGO_FCR4);
- reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
- KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
- reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
- KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
- MACIO_OUT32(KEYLARGO_FCR4, reg);
- (void)MACIO_IN32(KEYLARGO_FCR4);
- udelay(1);
- } else {
- reg = MACIO_IN32(KEYLARGO_FCR3);
- reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) |
- KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0);
- reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) |
- KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1);
- MACIO_OUT32(KEYLARGO_FCR3, reg);
- (void)MACIO_IN32(KEYLARGO_FCR3);
- udelay(1);
- }
- if (number == 0) {
- if (macio->type != macio_intrepid)
- MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- udelay(1);
- MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
- (void)MACIO_IN32(KEYLARGO_FCR0);
- } else if (number == 2) {
- if (macio->type != macio_intrepid)
- MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- udelay(1);
- MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
- (void)MACIO_IN32(KEYLARGO_FCR0);
- } else if (number == 4) {
- udelay(1);
- MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1));
- (void)MACIO_IN32(KEYLARGO_FCR1);
- }
- udelay(1);
- }
- UNLOCK(flags);
-
- return 0;
-}
-
-static long
-core99_firewire_enable(struct device_node* node, long param, long value)
-{
- unsigned long flags;
- struct macio_chip* macio;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
- if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
- return -ENODEV;
-
- LOCK(flags);
- if (value) {
- UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- } else {
- UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
- (void)UN_IN(UNI_N_CLOCK_CNTL);
- }
- UNLOCK(flags);
- mdelay(1);
-
- return 0;
-}
-
-static long
-core99_firewire_cable_power(struct device_node* node, long param, long value)
-{
- unsigned long flags;
- struct macio_chip* macio;
-
- /* Trick: we allow NULL node */
- if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
- return -ENODEV;
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
- if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
- return -ENODEV;
-
- LOCK(flags);
- if (value) {
- MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
- MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
- udelay(10);
- } else {
- MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
- MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
- }
- UNLOCK(flags);
- mdelay(1);
-
- return 0;
-}
-
-static long
-intrepid_aack_delay_enable(struct device_node* node, long param, long value)
-{
- unsigned long flags;
-
- if (uninorth_rev < 0xd2)
- return -ENODEV;
-
- LOCK(flags);
- if (param)
- UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
- else
- UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE);
- UNLOCK(flags);
-
- return 0;
-}
-
-
-#endif /* CONFIG_POWER4 */
-
-static long
-core99_read_gpio(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio = &macio_chips[0];
-
- return MACIO_IN8(param);
-}
-
-
-static long
-core99_write_gpio(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio = &macio_chips[0];
-
- MACIO_OUT8(param, (u8)(value & 0xff));
- return 0;
-}
-
-#ifdef CONFIG_POWER4
-
-static long
-g5_gmac_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio = &macio_chips[0];
- unsigned long flags;
- u8 pbus, pid;
-
- LOCK(flags);
- if (value) {
- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
- mb();
- k2_skiplist[0] = NULL;
- } else {
- k2_skiplist[0] = node;
- mb();
- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE);
- }
-
- UNLOCK(flags);
- mdelay(1);
-
- return 0;
-}
-
-static long
-g5_fw_enable(struct device_node* node, long param, long value)
-{
- struct macio_chip* macio = &macio_chips[0];
- unsigned long flags;
-
- LOCK(flags);
- if (value) {
- MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
- mb();
- k2_skiplist[1] = NULL;
- } else {
- k2_skiplist[1] = node;
- mb();
- MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE);
- }
-
- UNLOCK(flags);
- mdelay(1);
-
- return 0;
-}
-
-static long
-g5_mpic_enable(struct device_node* node, long param, long value)
-{
- unsigned long flags;
-
- if (node->parent == NULL || strcmp(node->parent->name, "u3"))
- return 0;
-
- LOCK(flags);
- UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE);
- UNLOCK(flags);
-
- return 0;
-}
-
-#ifdef CONFIG_SMP
-static long
-g5_reset_cpu(struct device_node* node, long param, long value)
-{
- unsigned int reset_io = 0;
- unsigned long flags;
- struct macio_chip* macio;
- struct device_node* np;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo2)
- return -ENODEV;
-
- np = find_path_device("/cpus");
- if (np == NULL)
- return -ENODEV;
- for (np = np->child; np != NULL; np = np->sibling) {
- u32* num = (u32 *)get_property(np, "reg", NULL);
- u32* rst = (u32 *)get_property(np, "soft-reset", NULL);
- if (num == NULL || rst == NULL)
- continue;
- if (param == *num) {
- reset_io = *rst;
- break;
- }
- }
- if (np == NULL || reset_io == 0)
- return -ENODEV;
-
- LOCK(flags);
- MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
- (void)MACIO_IN8(reset_io);
- udelay(1);
- MACIO_OUT8(reset_io, 0);
- (void)MACIO_IN8(reset_io);
- UNLOCK(flags);
-
- return 0;
-}
-#endif /* CONFIG_SMP */
-
-/*
- * This can be called from pmac_smp so isn't static
- *
- * This takes the second CPU off the bus on dual CPU machines
- * running UP
- */
-void g5_phy_disable_cpu1(void)
-{
- UN_OUT(U3_API_PHY_CONFIG_1, 0);
-}
-
-#endif /* CONFIG_POWER4 */
-
-#ifndef CONFIG_POWER4
-
-static void
-keylargo_shutdown(struct macio_chip* macio, int sleep_mode)
-{
- u32 temp;
-
- if (sleep_mode) {
- mdelay(1);
- MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
- (void)MACIO_IN32(KEYLARGO_FCR0);
- mdelay(1);
- }
-
- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
- KL0_SCC_CELL_ENABLE |
- KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
- KL0_IRDA_CLK19_ENABLE);
-
- MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
- MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE);
-
- MACIO_BIC(KEYLARGO_FCR1,
- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
- KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
- KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
- KL1_UIDE_ENABLE);
-
- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
-
- temp = MACIO_IN32(KEYLARGO_FCR3);
- if (macio->rev >= 2) {
- temp |= KL3_SHUTDOWN_PLL2X;
- if (sleep_mode)
- temp |= KL3_SHUTDOWN_PLL_TOTAL;
- }
-
- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
- KL3_SHUTDOWN_PLLKW35;
- if (sleep_mode)
- temp |= KL3_SHUTDOWN_PLLKW12;
- temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
- | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
- if (sleep_mode)
- temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
- MACIO_OUT32(KEYLARGO_FCR3, temp);
-
- /* Flush posted writes & wait a bit */
- (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
-}
-
-static void
-pangea_shutdown(struct macio_chip* macio, int sleep_mode)
-{
- u32 temp;
-
- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
- KL0_SCC_CELL_ENABLE |
- KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
-
- MACIO_BIC(KEYLARGO_FCR1,
- KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
- KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
- KL1_UIDE_ENABLE);
- if (pmac_mb.board_flags & PMAC_MB_MOBILE)
- MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
-
- MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
-
- temp = MACIO_IN32(KEYLARGO_FCR3);
- temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
- KL3_SHUTDOWN_PLLKW35;
- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE
- | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE);
- if (sleep_mode)
- temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE);
- MACIO_OUT32(KEYLARGO_FCR3, temp);
-
- /* Flush posted writes & wait a bit */
- (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1);
-}
-
-static void
-intrepid_shutdown(struct macio_chip* macio, int sleep_mode)
-{
- u32 temp;
-
- MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
- KL0_SCC_CELL_ENABLE);
-
- MACIO_BIC(KEYLARGO_FCR1,
- /*KL1_USB2_CELL_ENABLE |*/
- KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
- KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
- KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE);
- if (pmac_mb.board_flags & PMAC_MB_MOBILE)
- MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N);
-
- temp = MACIO_IN32(KEYLARGO_FCR3);
- temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE |
- KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE);
- if (sleep_mode)
- temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE);
- MACIO_OUT32(KEYLARGO_FCR3, temp);
-
- /* Flush posted writes & wait a bit */
- (void)MACIO_IN32(KEYLARGO_FCR0);
- mdelay(10);
-}
-
-
-void pmac_tweak_clock_spreading(int enable)
-{
- struct macio_chip* macio = &macio_chips[0];
-
- /* Hack for doing clock spreading on some machines PowerBooks and
- * iBooks. This implements the "platform-do-clockspreading" OF
- * property as decoded manually on various models. For safety, we also
- * check the product ID in the device-tree in cases we'll whack the i2c
- * chip to make reasonably sure we won't set wrong values in there
- *
- * Of course, ultimately, we have to implement a real parser for
- * the platform-do-* stuff...
- */
-
- if (macio->type == macio_intrepid) {
- struct device_node *clock =
- of_find_node_by_path("/uni-n@f8000000/hw-clock");
- if (clock && get_property(clock, "platform-do-clockspreading",
- NULL)) {
- printk(KERN_INFO "%sabling clock spreading on Intrepid"
- " ASIC\n", enable ? "En" : "Dis");
- if (enable)
- UN_OUT(UNI_N_CLOCK_SPREADING, 2);
- else
- UN_OUT(UNI_N_CLOCK_SPREADING, 0);
- mdelay(40);
- }
- of_node_put(clock);
- }
-
- while (machine_is_compatible("PowerBook5,2") ||
- machine_is_compatible("PowerBook5,3") ||
- machine_is_compatible("PowerBook6,2") ||
- machine_is_compatible("PowerBook6,3")) {
- struct device_node *ui2c = of_find_node_by_type(NULL, "i2c");
- struct device_node *dt = of_find_node_by_name(NULL, "device-tree");
- u8 buffer[9];
- u32 *productID;
- int i, rc, changed = 0;
-
- if (dt == NULL)
- break;
- productID = (u32 *)get_property(dt, "pid#", NULL);
- if (productID == NULL)
- break;
- while(ui2c) {
- struct device_node *p = of_get_parent(ui2c);
- if (p && !strcmp(p->name, "uni-n"))
- break;
- ui2c = of_find_node_by_type(ui2c, "i2c");
- }
- if (ui2c == NULL)
- break;
- DBG("Trying to bump clock speed for PID: %08x...\n", *productID);
- rc = pmac_low_i2c_open(ui2c, 1);
- if (rc != 0)
- break;
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
- DBG("read result: %d,", rc);
- if (rc != 0) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- for (i=0; i<9; i++)
- DBG(" %02x", buffer[i]);
- DBG("\n");
-
- switch(*productID) {
- case 0x1182: /* AlBook 12" rev 2 */
- case 0x1183: /* iBook G4 12" */
- buffer[0] = (buffer[0] & 0x8f) | 0x70;
- buffer[2] = (buffer[2] & 0x7f) | 0x00;
- buffer[5] = (buffer[5] & 0x80) | 0x31;
- buffer[6] = (buffer[6] & 0x40) | 0xb0;
- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xc0 : 0xba);
- buffer[8] = (buffer[8] & 0x00) | 0x30;
- changed = 1;
- break;
- case 0x3142: /* AlBook 15" (ATI M10) */
- case 0x3143: /* AlBook 17" (ATI M10) */
- buffer[0] = (buffer[0] & 0xaf) | 0x50;
- buffer[2] = (buffer[2] & 0x7f) | 0x00;
- buffer[5] = (buffer[5] & 0x80) | 0x31;
- buffer[6] = (buffer[6] & 0x40) | 0xb0;
- buffer[7] = (buffer[7] & 0x00) | (enable ? 0xd0 : 0xc0);
- buffer[8] = (buffer[8] & 0x00) | 0x30;
- changed = 1;
- break;
- default:
- DBG("i2c-hwclock: Machine model not handled\n");
- break;
- }
- if (!changed) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- printk(KERN_INFO "%sabling clock spreading on i2c clock chip\n",
- enable ? "En" : "Dis");
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9);
- DBG("write result: %d,", rc);
- pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined);
- rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9);
- DBG("read result: %d,", rc);
- if (rc != 0) {
- pmac_low_i2c_close(ui2c);
- break;
- }
- for (i=0; i<9; i++)
- DBG(" %02x", buffer[i]);
- pmac_low_i2c_close(ui2c);
- break;
- }
-}
-
-
-static int
-core99_sleep(void)
-{
- struct macio_chip* macio;
- int i;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
-
- /* We power off the wireless slot in case it was not done
- * by the driver. We don't power it on automatically however
- */
- if (macio->flags & MACIO_FLAG_AIRPORT_ON)
- core99_airport_enable(macio->of_node, 0, 0);
-
- /* We power off the FW cable. Should be done by the driver... */
- if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
- core99_firewire_enable(NULL, 0, 0);
- core99_firewire_cable_power(NULL, 0, 0);
- }
-
- /* We make sure int. modem is off (in case driver lost it) */
- if (macio->type == macio_keylargo)
- core99_modem_enable(macio->of_node, 0, 0);
- else
- pangea_modem_enable(macio->of_node, 0, 0);
-
- /* We make sure the sound is off as well */
- core99_sound_chip_enable(macio->of_node, 0, 0);
-
- /*
- * Save various bits of KeyLargo
- */
-
- /* Save the state of the various GPIOs */
- save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
- save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
- save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
- for (i=0; i<KEYLARGO_GPIO_CNT; i++)
- save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
-
- /* Save the FCRs */
- if (macio->type == macio_keylargo)
- save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
- save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
- save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
- save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
- save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
- save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
- if (macio->type == macio_pangea || macio->type == macio_intrepid)
- save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5);
-
- /* Save state & config of DBDMA channels */
- dbdma_save(macio, save_dbdma);
-
- /*
- * Turn off as much as we can
- */
- if (macio->type == macio_pangea)
- pangea_shutdown(macio, 1);
- else if (macio->type == macio_intrepid)
- intrepid_shutdown(macio, 1);
- else if (macio->type == macio_keylargo)
- keylargo_shutdown(macio, 1);
-
- /*
- * Put the host bridge to sleep
- */
-
- save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
- /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it
- * enabled !
- */
- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
- ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
- udelay(100);
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
- mdelay(10);
-
- /*
- * FIXME: A bit of black magic with OpenPIC (don't ask me why)
- */
- if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
- MACIO_BIS(0x506e0, 0x00400000);
- MACIO_BIS(0x506e0, 0x80000000);
- }
- return 0;
-}
-
-static int
-core99_wake_up(void)
-{
- struct macio_chip* macio;
- int i;
-
- macio = &macio_chips[0];
- if (macio->type != macio_keylargo && macio->type != macio_pangea &&
- macio->type != macio_intrepid)
- return -ENODEV;
-
- /*
- * Wakeup the host bridge
- */
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
- udelay(10);
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
- udelay(10);
-
- /*
- * Restore KeyLargo
- */
-
- if (macio->type == macio_keylargo) {
- MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
- (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
- }
- MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
- (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
- MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
- (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
- MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
- (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
- MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
- (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
- MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
- (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
- if (macio->type == macio_pangea || macio->type == macio_intrepid) {
- MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]);
- (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10);
- }
-
- dbdma_restore(macio, save_dbdma);
-
- MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
- MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
- for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
- MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
- for (i=0; i<KEYLARGO_GPIO_CNT; i++)
- MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
-
- /* FIXME more black magic with OpenPIC ... */
- if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
- MACIO_BIC(0x506e0, 0x00400000);
- MACIO_BIC(0x506e0, 0x80000000);
- }
-
- UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
- udelay(100);
-
- return 0;
-}
-
-static long
-core99_sleep_state(struct device_node* node, long param, long value)
-{
- /* Param == 1 means to enter the "fake sleep" mode that is
- * used for CPU speed switch
- */
- if (param == 1) {
- if (value == 1) {
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2);
- } else {
- UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
- udelay(10);
- UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
- udelay(10);
- }
- return 0;
- }
- if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
- return -EPERM;
-
- if (value == 1)
- return core99_sleep();
- else if (value == 0)
- return core99_wake_up();
- return 0;
-}
-
-#endif /* CONFIG_POWER4 */
-
-static long
-generic_dev_can_wake(struct device_node* node, long param, long value)
-{
- /* Todo: eventually check we are really dealing with on-board
- * video device ...
- */
-
- if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP)
- pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP;
- return 0;
-}
-
-static long
-generic_get_mb_info(struct device_node* node, long param, long value)
-{
- switch(param) {
- case PMAC_MB_INFO_MODEL:
- return pmac_mb.model_id;
- case PMAC_MB_INFO_FLAGS:
- return pmac_mb.board_flags;
- case PMAC_MB_INFO_NAME:
- /* hack hack hack... but should work */
- *((const char **)value) = pmac_mb.model_name;
- return 0;
- }
- return -EINVAL;
-}
-
-
-/*
- * Table definitions
- */
-
-/* Used on any machine
- */
-static struct feature_table_entry any_features[] = {
- { PMAC_FTR_GET_MB_INFO, generic_get_mb_info },
- { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake },
- { 0, NULL }
-};
-
-#ifndef CONFIG_POWER4
-
-/* OHare based motherboards. Currently, we only use these on the
- * 2400,3400 and 3500 series powerbooks. Some older desktops seem
- * to have issues with turning on/off those asic cells
- */
-static struct feature_table_entry ohare_features[] = {
- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
- { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable },
- { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable },
- { PMAC_FTR_IDE_ENABLE, ohare_ide_enable},
- { PMAC_FTR_IDE_RESET, ohare_ide_reset},
- { PMAC_FTR_SLEEP_STATE, ohare_sleep_state },
- { 0, NULL }
-};
-
-/* Heathrow desktop machines (Beige G3).
- * Separated as some features couldn't be properly tested
- * and the serial port control bits appear to confuse it.
- */
-static struct feature_table_entry heathrow_desktop_features[] = {
- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
- { 0, NULL }
-};
-
-/* Heathrow based laptop, that is the Wallstreet and mainstreet
- * powerbooks.
- */
-static struct feature_table_entry heathrow_laptop_features[] = {
- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
- { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
- { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
- { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
- { 0, NULL }
-};
-
-/* Paddington based machines
- * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
- */
-static struct feature_table_entry paddington_features[] = {
- { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable },
- { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable },
- { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable },
- { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable },
- { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable },
- { PMAC_FTR_IDE_RESET, heathrow_ide_reset },
- { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable },
- { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable },
- { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state },
- { 0, NULL }
-};
-
-/* Core99 & MacRISC 2 machines (all machines released since the
- * iBook (included), that is all AGP machines, except pangea
- * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
- * used on iBook2 & iMac "flow power".
- */
-static struct feature_table_entry core99_features[] = {
- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
- { PMAC_FTR_MODEM_ENABLE, core99_modem_enable },
- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
- { PMAC_FTR_IDE_RESET, core99_ide_reset },
- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
- { PMAC_FTR_USB_ENABLE, core99_usb_enable },
- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
-#ifdef CONFIG_SMP
- { PMAC_FTR_RESET_CPU, core99_reset_cpu },
-#endif /* CONFIG_SMP */
- { PMAC_FTR_READ_GPIO, core99_read_gpio },
- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
- { 0, NULL }
-};
-
-/* RackMac
- */
-static struct feature_table_entry rackmac_features[] = {
- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
- { PMAC_FTR_IDE_RESET, core99_ide_reset },
- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
- { PMAC_FTR_USB_ENABLE, core99_usb_enable },
- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
-#ifdef CONFIG_SMP
- { PMAC_FTR_RESET_CPU, core99_reset_cpu },
-#endif /* CONFIG_SMP */
- { PMAC_FTR_READ_GPIO, core99_read_gpio },
- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
- { 0, NULL }
-};
-
-/* Pangea features
- */
-static struct feature_table_entry pangea_features[] = {
- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
- { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
- { PMAC_FTR_IDE_RESET, core99_ide_reset },
- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
- { PMAC_FTR_USB_ENABLE, core99_usb_enable },
- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
- { PMAC_FTR_READ_GPIO, core99_read_gpio },
- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
- { 0, NULL }
-};
-
-/* Intrepid features
- */
-static struct feature_table_entry intrepid_features[] = {
- { PMAC_FTR_SCC_ENABLE, core99_scc_enable },
- { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable },
- { PMAC_FTR_IDE_ENABLE, core99_ide_enable },
- { PMAC_FTR_IDE_RESET, core99_ide_reset },
- { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable },
- { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset },
- { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable },
- { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable },
- { PMAC_FTR_USB_ENABLE, core99_usb_enable },
- { PMAC_FTR_1394_ENABLE, core99_firewire_enable },
- { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power },
- { PMAC_FTR_SLEEP_STATE, core99_sleep_state },
- { PMAC_FTR_READ_GPIO, core99_read_gpio },
- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
- { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable },
- { 0, NULL }
-};
-
-#else /* CONFIG_POWER4 */
-
-/* G5 features
- */
-static struct feature_table_entry g5_features[] = {
- { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable },
- { PMAC_FTR_1394_ENABLE, g5_fw_enable },
- { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable },
-#ifdef CONFIG_SMP
- { PMAC_FTR_RESET_CPU, g5_reset_cpu },
-#endif /* CONFIG_SMP */
- { PMAC_FTR_READ_GPIO, core99_read_gpio },
- { PMAC_FTR_WRITE_GPIO, core99_write_gpio },
- { 0, NULL }
-};
-
-#endif /* CONFIG_POWER4 */
-
-static struct pmac_mb_def pmac_mb_defs[] = {
-#ifndef CONFIG_POWER4
- /*
- * Desktops
- */
-
- { "AAPL,8500", "PowerMac 8500/8600",
- PMAC_TYPE_PSURGE, NULL,
- 0
- },
- { "AAPL,9500", "PowerMac 9500/9600",
- PMAC_TYPE_PSURGE, NULL,
- 0
- },
- { "AAPL,7200", "PowerMac 7200",
- PMAC_TYPE_PSURGE, NULL,
- 0
- },
- { "AAPL,7300", "PowerMac 7200/7300",
- PMAC_TYPE_PSURGE, NULL,
- 0
- },
- { "AAPL,7500", "PowerMac 7500",
- PMAC_TYPE_PSURGE, NULL,
- 0
- },
- { "AAPL,ShinerESB", "Apple Network Server",
- PMAC_TYPE_ANS, NULL,
- 0
- },
- { "AAPL,e407", "Alchemy",
- PMAC_TYPE_ALCHEMY, NULL,
- 0
- },
- { "AAPL,e411", "Gazelle",
- PMAC_TYPE_GAZELLE, NULL,
- 0
- },
- { "AAPL,Gossamer", "PowerMac G3 (Gossamer)",
- PMAC_TYPE_GOSSAMER, heathrow_desktop_features,
- 0
- },
- { "AAPL,PowerMac G3", "PowerMac G3 (Silk)",
- PMAC_TYPE_SILK, heathrow_desktop_features,
- 0
- },
- { "PowerMac1,1", "Blue&White G3",
- PMAC_TYPE_YOSEMITE, paddington_features,
- 0
- },
- { "PowerMac1,2", "PowerMac G4 PCI Graphics",
- PMAC_TYPE_YIKES, paddington_features,
- 0
- },
- { "PowerMac2,1", "iMac FireWire",
- PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
- },
- { "PowerMac2,2", "iMac FireWire",
- PMAC_TYPE_FW_IMAC, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
- },
- { "PowerMac3,1", "PowerMac G4 AGP Graphics",
- PMAC_TYPE_SAWTOOTH, core99_features,
- PMAC_MB_OLD_CORE99
- },
- { "PowerMac3,2", "PowerMac G4 AGP Graphics",
- PMAC_TYPE_SAWTOOTH, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
- },
- { "PowerMac3,3", "PowerMac G4 AGP Graphics",
- PMAC_TYPE_SAWTOOTH, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
- },
- { "PowerMac3,4", "PowerMac G4 Silver",
- PMAC_TYPE_QUICKSILVER, core99_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerMac3,5", "PowerMac G4 Silver",
- PMAC_TYPE_QUICKSILVER, core99_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerMac3,6", "PowerMac G4 Windtunnel",
- PMAC_TYPE_WINDTUNNEL, core99_features,
- PMAC_MB_MAY_SLEEP,
- },
- { "PowerMac4,1", "iMac \"Flower Power\"",
- PMAC_TYPE_PANGEA_IMAC, pangea_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerMac4,2", "Flat panel iMac",
- PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features,
- PMAC_MB_CAN_SLEEP
- },
- { "PowerMac4,4", "eMac",
- PMAC_TYPE_EMAC, core99_features,
- PMAC_MB_MAY_SLEEP
- },
- { "PowerMac5,1", "PowerMac G4 Cube",
- PMAC_TYPE_CUBE, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99
- },
- { "PowerMac6,1", "Flat panel iMac",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP,
- },
- { "PowerMac6,3", "Flat panel iMac",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP,
- },
- { "PowerMac6,4", "eMac",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP,
- },
- { "PowerMac10,1", "Mac mini",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER,
- },
- { "iMac,1", "iMac (first generation)",
- PMAC_TYPE_ORIG_IMAC, paddington_features,
- 0
- },
-
- /*
- * Xserve's
- */
-
- { "RackMac1,1", "XServe",
- PMAC_TYPE_RACKMAC, rackmac_features,
- 0,
- },
- { "RackMac1,2", "XServe rev. 2",
- PMAC_TYPE_RACKMAC, rackmac_features,
- 0,
- },
-
- /*
- * Laptops
- */
-
- { "AAPL,3400/2400", "PowerBook 3400",
- PMAC_TYPE_HOOPER, ohare_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
- },
- { "AAPL,3500", "PowerBook 3500",
- PMAC_TYPE_KANGA, ohare_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
- },
- { "AAPL,PowerBook1998", "PowerBook Wallstreet",
- PMAC_TYPE_WALLSTREET, heathrow_laptop_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
- },
- { "PowerBook1,1", "PowerBook 101 (Lombard)",
- PMAC_TYPE_101_PBOOK, paddington_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE
- },
- { "PowerBook2,1", "iBook (first generation)",
- PMAC_TYPE_ORIG_IBOOK, core99_features,
- PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
- },
- { "PowerBook2,2", "iBook FireWire",
- PMAC_TYPE_FW_IBOOK, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
- PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
- },
- { "PowerBook3,1", "PowerBook Pismo",
- PMAC_TYPE_PISMO, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER |
- PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE
- },
- { "PowerBook3,2", "PowerBook Titanium",
- PMAC_TYPE_TITANIUM, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook3,3", "PowerBook Titanium II",
- PMAC_TYPE_TITANIUM2, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook3,4", "PowerBook Titanium III",
- PMAC_TYPE_TITANIUM3, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook3,5", "PowerBook Titanium IV",
- PMAC_TYPE_TITANIUM4, core99_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook4,1", "iBook 2",
- PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook4,2", "iBook 2",
- PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook4,3", "iBook 2 rev. 2",
- PMAC_TYPE_IBOOK2, pangea_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE
- },
- { "PowerBook5,1", "PowerBook G4 17\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,2", "PowerBook G4 15\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,3", "PowerBook G4 17\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,4", "PowerBook G4 15\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,5", "PowerBook G4 17\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,6", "PowerBook G4 15\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,7", "PowerBook G4 17\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,8", "PowerBook G4 15\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook5,9", "PowerBook G4 17\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,1", "PowerBook G4 12\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,2", "PowerBook G4",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,3", "iBook G4",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,4", "PowerBook G4 12\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,5", "iBook G4",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,7", "iBook G4",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
- { "PowerBook6,8", "PowerBook G4 12\"",
- PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features,
- PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE,
- },
-#else /* CONFIG_POWER4 */
- { "PowerMac7,2", "PowerMac G5",
- PMAC_TYPE_POWERMAC_G5, g5_features,
- 0,
- },
-#endif /* CONFIG_POWER4 */
-};
-
-/*
- * The toplevel feature_call callback
- */
-long
-pmac_do_feature_call(unsigned int selector, ...)
-{
- struct device_node* node;
- long param, value;
- int i;
- feature_call func = NULL;
- va_list args;
-
- if (pmac_mb.features)
- for (i=0; pmac_mb.features[i].function; i++)
- if (pmac_mb.features[i].selector == selector) {
- func = pmac_mb.features[i].function;
- break;
- }
- if (!func)
- for (i=0; any_features[i].function; i++)
- if (any_features[i].selector == selector) {
- func = any_features[i].function;
- break;
- }
- if (!func)
- return -ENODEV;
-
- va_start(args, selector);
- node = (struct device_node*)va_arg(args, void*);
- param = va_arg(args, long);
- value = va_arg(args, long);
- va_end(args);
-
- return func(node, param, value);
-}
-
-static int __init
-probe_motherboard(void)
-{
- int i;
- struct macio_chip* macio = &macio_chips[0];
- const char* model = NULL;
- struct device_node *dt;
-
- /* Lookup known motherboard type in device-tree. First try an
- * exact match on the "model" property, then try a "compatible"
- * match is none is found.
- */
- dt = find_devices("device-tree");
- if (dt != NULL)
- model = (const char *) get_property(dt, "model", NULL);
- for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
- if (strcmp(model, pmac_mb_defs[i].model_string) == 0) {
- pmac_mb = pmac_mb_defs[i];
- goto found;
- }
- }
- for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
- if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
- pmac_mb = pmac_mb_defs[i];
- goto found;
- }
- }
-
- /* Fallback to selection depending on mac-io chip type */
- switch(macio->type) {
-#ifndef CONFIG_POWER4
- case macio_grand_central:
- pmac_mb.model_id = PMAC_TYPE_PSURGE;
- pmac_mb.model_name = "Unknown PowerSurge";
- break;
- case macio_ohare:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
- pmac_mb.model_name = "Unknown OHare-based";
- break;
- case macio_heathrow:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
- pmac_mb.model_name = "Unknown Heathrow-based";
- pmac_mb.features = heathrow_desktop_features;
- break;
- case macio_paddington:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
- pmac_mb.model_name = "Unknown Paddington-based";
- pmac_mb.features = paddington_features;
- break;
- case macio_keylargo:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
- pmac_mb.model_name = "Unknown Keylargo-based";
- pmac_mb.features = core99_features;
- break;
- case macio_pangea:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
- pmac_mb.model_name = "Unknown Pangea-based";
- pmac_mb.features = pangea_features;
- break;
- case macio_intrepid:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID;
- pmac_mb.model_name = "Unknown Intrepid-based";
- pmac_mb.features = intrepid_features;
- break;
-#else /* CONFIG_POWER4 */
- case macio_keylargo2:
- pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2;
- pmac_mb.model_name = "Unknown G5";
- pmac_mb.features = g5_features;
- break;
-#endif /* CONFIG_POWER4 */
- default:
- return -ENODEV;
- }
-found:
-#ifndef CONFIG_POWER4
- /* Fixup Hooper vs. Comet */
- if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
- u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4);
- if (!mach_id_ptr)
- return -ENODEV;
- /* Here, I used to disable the media-bay on comet. It
- * appears this is wrong, the floppy connector is actually
- * a kind of media-bay and works with the current driver.
- */
- if (__raw_readl(mach_id_ptr) & 0x20000000UL)
- pmac_mb.model_id = PMAC_TYPE_COMET;
- iounmap(mach_id_ptr);
- }
-#endif /* CONFIG_POWER4 */
-
-#ifdef CONFIG_6xx
- /* Set default value of powersave_nap on machines that support it.
- * It appears that uninorth rev 3 has a problem with it, we don't
- * enable it on those. In theory, the flush-on-lock property is
- * supposed to be set when not supported, but I'm not very confident
- * that all Apple OF revs did it properly, I do it the paranoid way.
- */
- while (uninorth_base && uninorth_rev > 3) {
- struct device_node* np = find_path_device("/cpus");
- if (!np || !np->child) {
- printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
- break;
- }
- np = np->child;
- /* Nap mode not supported on SMP */
- if (np->sibling)
- break;
- /* Nap mode not supported if flush-on-lock property is present */
- if (get_property(np, "flush-on-lock", NULL))
- break;
- powersave_nap = 1;
- printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
- break;
- }
-
- /* On CPUs that support it (750FX), lowspeed by default during
- * NAP mode
- */
- powersave_lowspeed = 1;
-#endif /* CONFIG_6xx */
-#ifdef CONFIG_POWER4
- powersave_nap = 1;
-#endif
- /* Check for "mobile" machine */
- if (model && (strncmp(model, "PowerBook", 9) == 0
- || strncmp(model, "iBook", 5) == 0))
- pmac_mb.board_flags |= PMAC_MB_MOBILE;
-
-
- printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
- return 0;
-}
-
-/* Initialize the Core99 UniNorth host bridge and memory controller
- */
-static void __init
-probe_uninorth(void)
-{
- unsigned long actrl;
-
- /* Locate core99 Uni-N */
- uninorth_node = of_find_node_by_name(NULL, "uni-n");
- /* Locate G5 u3 */
- if (uninorth_node == NULL) {
- uninorth_node = of_find_node_by_name(NULL, "u3");
- uninorth_u3 = 1;
- }
- if (uninorth_node && uninorth_node->n_addrs > 0) {
- unsigned long address = uninorth_node->addrs[0].address;
- uninorth_base = ioremap(address, 0x40000);
- uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
- if (uninorth_u3)
- u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
- } else
- uninorth_node = NULL;
-
- if (!uninorth_node)
- return;
-
- printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n",
- uninorth_u3 ? "U3" : "UniNorth", uninorth_rev);
- printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
-
- /* Set the arbitrer QAck delay according to what Apple does
- */
- if (uninorth_rev < 0x11) {
- actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
- actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
- UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
- UN_OUT(UNI_N_ARB_CTRL, actrl);
- }
-
- /* Some more magic as done by them in recent MacOS X on UniNorth
- * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
- * memory timeout
- */
- if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
- UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
-}
-
-static void __init
-probe_one_macio(const char* name, const char* compat, int type)
-{
- struct device_node* node;
- int i;
- volatile u32 __iomem * base;
- u32* revp;
-
- node = find_devices(name);
- if (!node || !node->n_addrs)
- return;
- if (compat)
- do {
- if (device_is_compatible(node, compat))
- break;
- node = node->next;
- } while (node);
- if (!node)
- return;
- for(i=0; i<MAX_MACIO_CHIPS; i++) {
- if (!macio_chips[i].of_node)
- break;
- if (macio_chips[i].of_node == node)
- return;
- }
- if (i >= MAX_MACIO_CHIPS) {
- printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
- printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
- return;
- }
- base = ioremap(node->addrs[0].address, node->addrs[0].size);
- if (!base) {
- printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
- return;
- }
- if (type == macio_keylargo) {
- u32* did = (u32 *)get_property(node, "device-id", NULL);
- if (*did == 0x00000025)
- type = macio_pangea;
- if (*did == 0x0000003e)
- type = macio_intrepid;
- }
- macio_chips[i].of_node = node;
- macio_chips[i].type = type;
- macio_chips[i].base = base;
- macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
- macio_chips[i].name = macio_names[type];
- revp = (u32 *)get_property(node, "revision-id", NULL);
- if (revp)
- macio_chips[i].rev = *revp;
- printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
- macio_names[type], macio_chips[i].rev, macio_chips[i].base);
-}
-
-static int __init
-probe_macios(void)
-{
- /* Warning, ordering is important */
- probe_one_macio("gc", NULL, macio_grand_central);
- probe_one_macio("ohare", NULL, macio_ohare);
- probe_one_macio("pci106b,7", NULL, macio_ohareII);
- probe_one_macio("mac-io", "keylargo", macio_keylargo);
- probe_one_macio("mac-io", "paddington", macio_paddington);
- probe_one_macio("mac-io", "gatwick", macio_gatwick);
- probe_one_macio("mac-io", "heathrow", macio_heathrow);
- probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2);
-
- /* Make sure the "main" macio chip appear first */
- if (macio_chips[0].type == macio_gatwick
- && macio_chips[1].type == macio_heathrow) {
- struct macio_chip temp = macio_chips[0];
- macio_chips[0] = macio_chips[1];
- macio_chips[1] = temp;
- }
- if (macio_chips[0].type == macio_ohareII
- && macio_chips[1].type == macio_ohare) {
- struct macio_chip temp = macio_chips[0];
- macio_chips[0] = macio_chips[1];
- macio_chips[1] = temp;
- }
- macio_chips[0].lbus.index = 0;
- macio_chips[1].lbus.index = 1;
-
- return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
-}
-
-static void __init
-initial_serial_shutdown(struct device_node* np)
-{
- int len;
- struct slot_names_prop {
- int count;
- char name[1];
- } *slots;
- char *conn;
- int port_type = PMAC_SCC_ASYNC;
- int modem = 0;
-
- slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
- conn = get_property(np, "AAPL,connector", &len);
- if (conn && (strcmp(conn, "infrared") == 0))
- port_type = PMAC_SCC_IRDA;
- else if (device_is_compatible(np, "cobalt"))
- modem = 1;
- else if (slots && slots->count > 0) {
- if (strcmp(slots->name, "IrDA") == 0)
- port_type = PMAC_SCC_IRDA;
- else if (strcmp(slots->name, "Modem") == 0)
- modem = 1;
- }
- if (modem)
- pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
- pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
-}
-
-static void __init
-set_initial_features(void)
-{
- struct device_node* np;
-
- /* That hack appears to be necessary for some StarMax motherboards
- * but I'm not too sure it was audited for side-effects on other
- * ohare based machines...
- * Since I still have difficulties figuring the right way to
- * differenciate them all and since that hack was there for a long
- * time, I'll keep it around
- */
- if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
- struct macio_chip* macio = &macio_chips[0];
- MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
- } else if (macio_chips[0].type == macio_ohare) {
- struct macio_chip* macio = &macio_chips[0];
- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
- } else if (macio_chips[1].type == macio_ohare) {
- struct macio_chip* macio = &macio_chips[1];
- MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
- }
-
-#ifdef CONFIG_POWER4
- if (macio_chips[0].type == macio_keylargo2) {
-#ifndef CONFIG_SMP
- /* On SMP machines running UP, we have the second CPU eating
- * bus cycles. We need to take it off the bus. This is done
- * from pmac_smp for SMP kernels running on one CPU
- */
- np = of_find_node_by_type(NULL, "cpu");
- if (np != NULL)
- np = of_find_node_by_type(np, "cpu");
- if (np != NULL) {
- g5_phy_disable_cpu1();
- of_node_put(np);
- }
-#endif /* CONFIG_SMP */
- /* Enable GMAC for now for PCI probing. It will be disabled
- * later on after PCI probe
- */
- np = of_find_node_by_name(NULL, "ethernet");
- while(np) {
- if (device_is_compatible(np, "K2-GMAC"))
- g5_gmac_enable(np, 0, 1);
- np = of_find_node_by_name(np, "ethernet");
- }
-
- /* Enable FW before PCI probe. Will be disabled later on
- * Note: We should have a batter way to check that we are
- * dealing with uninorth internal cell and not a PCI cell
- * on the external PCI. The code below works though.
- */
- np = of_find_node_by_name(NULL, "firewire");
- while(np) {
- if (device_is_compatible(np, "pci106b,5811")) {
- macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
- g5_fw_enable(np, 0, 1);
- }
- np = of_find_node_by_name(np, "firewire");
- }
- }
-#else /* CONFIG_POWER4 */
-
- if (macio_chips[0].type == macio_keylargo ||
- macio_chips[0].type == macio_pangea ||
- macio_chips[0].type == macio_intrepid) {
- /* Enable GMAC for now for PCI probing. It will be disabled
- * later on after PCI probe
- */
- np = of_find_node_by_name(NULL, "ethernet");
- while(np) {
- if (np->parent
- && device_is_compatible(np->parent, "uni-north")
- && device_is_compatible(np, "gmac"))
- core99_gmac_enable(np, 0, 1);
- np = of_find_node_by_name(np, "ethernet");
- }
-
- /* Enable FW before PCI probe. Will be disabled later on
- * Note: We should have a batter way to check that we are
- * dealing with uninorth internal cell and not a PCI cell
- * on the external PCI. The code below works though.
- */
- np = of_find_node_by_name(NULL, "firewire");
- while(np) {
- if (np->parent
- && device_is_compatible(np->parent, "uni-north")
- && (device_is_compatible(np, "pci106b,18") ||
- device_is_compatible(np, "pci106b,30") ||
- device_is_compatible(np, "pci11c1,5811"))) {
- macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
- core99_firewire_enable(np, 0, 1);
- }
- np = of_find_node_by_name(np, "firewire");
- }
-
- /* Enable ATA-100 before PCI probe. */
- np = of_find_node_by_name(NULL, "ata-6");
- while(np) {
- if (np->parent
- && device_is_compatible(np->parent, "uni-north")
- && device_is_compatible(np, "kauai-ata")) {
- core99_ata100_enable(np, 1);
- }
- np = of_find_node_by_name(np, "ata-6");
- }
-
- /* Switch airport off */
- np = find_devices("radio");
- while(np) {
- if (np && np->parent == macio_chips[0].of_node) {
- macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
- core99_airport_enable(np, 0, 0);
- }
- np = np->next;
- }
- }
-
- /* On all machines that support sound PM, switch sound off */
- if (macio_chips[0].of_node)
- pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
- macio_chips[0].of_node, 0, 0);
-
- /* While on some desktop G3s, we turn it back on */
- if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
- && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
- pmac_mb.model_id == PMAC_TYPE_SILK)) {
- struct macio_chip* macio = &macio_chips[0];
- MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
- MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
- }
-
- /* Some machine models need the clock chip to be properly setup for
- * clock spreading now. This should be a platform function but we
- * don't do these at the moment
- */
- pmac_tweak_clock_spreading(1);
-
-#endif /* CONFIG_POWER4 */
-
- /* On all machines, switch modem & serial ports off */
- np = find_devices("ch-a");
- while(np) {
- initial_serial_shutdown(np);
- np = np->next;
- }
- np = find_devices("ch-b");
- while(np) {
- initial_serial_shutdown(np);
- np = np->next;
- }
-}
-
-void __init
-pmac_feature_init(void)
-{
- /* Detect the UniNorth memory controller */
- probe_uninorth();
-
- /* Probe mac-io controllers */
- if (probe_macios()) {
- printk(KERN_WARNING "No mac-io chip found\n");
- return;
- }
-
- /* Setup low-level i2c stuffs */
- pmac_init_low_i2c();
-
- /* Probe machine type */
- if (probe_motherboard())
- printk(KERN_WARNING "Unknown PowerMac !\n");
-
- /* Set some initial features (turn off some chips that will
- * be later turned on)
- */
- set_initial_features();
-}
-
-int __init
-pmac_feature_late_init(void)
-{
- struct device_node* np;
-
- /* Request some resources late */
- if (uninorth_node)
- request_OF_resource(uninorth_node, 0, NULL);
- np = find_devices("hammerhead");
- if (np)
- request_OF_resource(np, 0, NULL);
- np = find_devices("interrupt-controller");
- if (np)
- request_OF_resource(np, 0, NULL);
- return 0;
-}
-
-device_initcall(pmac_feature_late_init);
-
-#ifdef CONFIG_POWER4
-
-static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
-{
- int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
- int bits[8] = { 8,16,0,32,2,4,0,0 };
- int freq = (frq >> 8) & 0xf;
-
- if (freqs[freq] == 0)
- printk("%s: Unknown HT link frequency %x\n", name, freq);
- else
- printk("%s: %d MHz on main link, (%d in / %d out) bits width\n",
- name, freqs[freq],
- bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
-}
-
-void __init pmac_check_ht_link(void)
-{
- u32 ufreq, freq, ucfg, cfg;
- struct device_node *pcix_node;
- u8 px_bus, px_devfn;
- struct pci_controller *px_hose;
-
- (void)in_be32(u3_ht + U3_HT_LINK_COMMAND);
- ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG);
- ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ);
- dump_HT_speeds("U3 HyperTransport", cfg, freq);
-
- pcix_node = of_find_compatible_node(NULL, "pci", "pci-x");
- if (pcix_node == NULL) {
- printk("No PCI-X bridge found\n");
- return;
- }
- if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) {
- printk("PCI-X bridge found but not matched to pci\n");
- return;
- }
- px_hose = pci_find_hose_for_OF_device(pcix_node);
- if (px_hose == NULL) {
- printk("PCI-X bridge found but not matched to host\n");
- return;
- }
- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
- early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
- dump_HT_speeds("PCI-X HT Uplink", cfg, freq);
- early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg);
- early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq);
- dump_HT_speeds("PCI-X HT Downlink", cfg, freq);
-}
-
-#endif /* CONFIG_POWER4 */
-
-/*
- * Early video resume hook
- */
-
-static void (*pmac_early_vresume_proc)(void *data);
-static void *pmac_early_vresume_data;
-
-void pmac_set_early_video_resume(void (*proc)(void *data), void *data)
-{
- if (_machine != _MACH_Pmac)
- return;
- preempt_disable();
- pmac_early_vresume_proc = proc;
- pmac_early_vresume_data = data;
- preempt_enable();
-}
-EXPORT_SYMBOL(pmac_set_early_video_resume);
-
-void pmac_call_early_video_resume(void)
-{
- if (pmac_early_vresume_proc)
- pmac_early_vresume_proc(pmac_early_vresume_data);
-}
-
-/*
- * AGP related suspend/resume code
- */
-
-static struct pci_dev *pmac_agp_bridge;
-static int (*pmac_agp_suspend)(struct pci_dev *bridge);
-static int (*pmac_agp_resume)(struct pci_dev *bridge);
-
-void pmac_register_agp_pm(struct pci_dev *bridge,
- int (*suspend)(struct pci_dev *bridge),
- int (*resume)(struct pci_dev *bridge))
-{
- if (suspend || resume) {
- pmac_agp_bridge = bridge;
- pmac_agp_suspend = suspend;
- pmac_agp_resume = resume;
- return;
- }
- if (bridge != pmac_agp_bridge)
- return;
- pmac_agp_suspend = pmac_agp_resume = NULL;
- return;
-}
-EXPORT_SYMBOL(pmac_register_agp_pm);
-
-void pmac_suspend_agp_for_card(struct pci_dev *dev)
-{
- if (pmac_agp_bridge == NULL || pmac_agp_suspend == NULL)
- return;
- if (pmac_agp_bridge->bus != dev->bus)
- return;
- pmac_agp_suspend(pmac_agp_bridge);
-}
-EXPORT_SYMBOL(pmac_suspend_agp_for_card);
-
-void pmac_resume_agp_for_card(struct pci_dev *dev)
-{
- if (pmac_agp_bridge == NULL || pmac_agp_resume == NULL)
- return;
- if (pmac_agp_bridge->bus != dev->bus)
- return;
- pmac_agp_resume(pmac_agp_bridge);
-}
-EXPORT_SYMBOL(pmac_resume_agp_for_card);
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c
deleted file mode 100644
index 08583fce1692..000000000000
--- a/arch/ppc/platforms/pmac_low_i2c.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * arch/ppc/platforms/pmac_low_i2c.c
- *
- * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.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 file contains some low-level i2c access routines that
- * need to be used by various bits of the PowerMac platform code
- * at times where the real asynchronous & interrupt driven driver
- * cannot be used. The API borrows some semantics from the darwin
- * driver in order to ease the implementation of the platform
- * properties parser
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <asm/keylargo.h>
-#include <asm/uninorth.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_low_i2c.h>
-
-#define MAX_LOW_I2C_HOST 4
-
-#if 1
-#define DBG(x...) do {\
- printk(KERN_DEBUG "KW:" x); \
- } while(0)
-#else
-#define DBGG(x...)
-#endif
-
-struct low_i2c_host;
-
-typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len);
-
-struct low_i2c_host
-{
- struct device_node *np; /* OF device node */
- struct semaphore mutex; /* Access mutex for use by i2c-keywest */
- low_i2c_func_t func; /* Access function */
- int is_open : 1; /* Poor man's access control */
- int mode; /* Current mode */
- int channel; /* Current channel */
- int num_channels; /* Number of channels */
- void __iomem * base; /* For keywest-i2c, base address */
- int bsteps; /* And register stepping */
- int speed; /* And speed */
-};
-
-static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST];
-
-/* No locking is necessary on allocation, we are running way before
- * anything can race with us
- */
-static struct low_i2c_host *find_low_i2c_host(struct device_node *np)
-{
- int i;
-
- for (i = 0; i < MAX_LOW_I2C_HOST; i++)
- if (low_i2c_hosts[i].np == np)
- return &low_i2c_hosts[i];
- return NULL;
-}
-
-/*
- *
- * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
- *
- */
-
-/*
- * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
- * should be moved somewhere in include/asm-ppc/
- */
-/* Register indices */
-typedef enum {
- reg_mode = 0,
- reg_control,
- reg_status,
- reg_isr,
- reg_ier,
- reg_addr,
- reg_subaddr,
- reg_data
-} reg_t;
-
-
-/* Mode register */
-#define KW_I2C_MODE_100KHZ 0x00
-#define KW_I2C_MODE_50KHZ 0x01
-#define KW_I2C_MODE_25KHZ 0x02
-#define KW_I2C_MODE_DUMB 0x00
-#define KW_I2C_MODE_STANDARD 0x04
-#define KW_I2C_MODE_STANDARDSUB 0x08
-#define KW_I2C_MODE_COMBINED 0x0C
-#define KW_I2C_MODE_MODE_MASK 0x0C
-#define KW_I2C_MODE_CHAN_MASK 0xF0
-
-/* Control register */
-#define KW_I2C_CTL_AAK 0x01
-#define KW_I2C_CTL_XADDR 0x02
-#define KW_I2C_CTL_STOP 0x04
-#define KW_I2C_CTL_START 0x08
-
-/* Status register */
-#define KW_I2C_STAT_BUSY 0x01
-#define KW_I2C_STAT_LAST_AAK 0x02
-#define KW_I2C_STAT_LAST_RW 0x04
-#define KW_I2C_STAT_SDA 0x08
-#define KW_I2C_STAT_SCL 0x10
-
-/* IER & ISR registers */
-#define KW_I2C_IRQ_DATA 0x01
-#define KW_I2C_IRQ_ADDR 0x02
-#define KW_I2C_IRQ_STOP 0x04
-#define KW_I2C_IRQ_START 0x08
-#define KW_I2C_IRQ_MASK 0x0F
-
-/* State machine states */
-enum {
- state_idle,
- state_addr,
- state_read,
- state_write,
- state_stop,
- state_dead
-};
-
-#define WRONG_STATE(name) do {\
- printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
- name, __kw_state_names[state], isr); \
- } while(0)
-
-static const char *__kw_state_names[] = {
- "state_idle",
- "state_addr",
- "state_read",
- "state_write",
- "state_stop",
- "state_dead"
-};
-
-static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
-{
- return in_8(host->base + (((unsigned)reg) << host->bsteps));
-}
-
-static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
-{
- out_8(host->base + (((unsigned)reg) << host->bsteps), val);
- (void)__kw_read_reg(host, reg_subaddr);
-}
-
-#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
-#define kw_read_reg(reg) __kw_read_reg(host, reg)
-
-
-/* Don't schedule, the g5 fan controller is too
- * timing sensitive
- */
-static u8 kw_wait_interrupt(struct low_i2c_host* host)
-{
- int i;
- u8 isr;
-
- for (i = 0; i < 200000; i++) {
- isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
- if (isr != 0)
- return isr;
- udelay(1);
- }
- return isr;
-}
-
-static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr)
-{
- u8 ack;
-
- if (isr == 0) {
- if (state != state_stop) {
- DBG("KW: Timeout !\n");
- *rc = -EIO;
- goto stop;
- }
- if (state == state_stop) {
- ack = kw_read_reg(reg_status);
- if (!(ack & KW_I2C_STAT_BUSY)) {
- state = state_idle;
- kw_write_reg(reg_ier, 0x00);
- }
- }
- return state;
- }
-
- if (isr & KW_I2C_IRQ_ADDR) {
- ack = kw_read_reg(reg_status);
- if (state != state_addr) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- WRONG_STATE("KW_I2C_IRQ_ADDR");
- *rc = -EIO;
- goto stop;
- }
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- *rc = -ENODEV;
- DBG("KW: NAK on address\n");
- return state_stop;
- } else {
- if (rw) {
- state = state_read;
- if (*len > 1)
- kw_write_reg(reg_control, KW_I2C_CTL_AAK);
- } else {
- state = state_write;
- kw_write_reg(reg_data, **data);
- (*data)++; (*len)--;
- }
- }
- kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- }
-
- if (isr & KW_I2C_IRQ_DATA) {
- if (state == state_read) {
- **data = kw_read_reg(reg_data);
- (*data)++; (*len)--;
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
- if ((*len) == 0)
- state = state_stop;
- else if ((*len) == 1)
- kw_write_reg(reg_control, 0);
- } else if (state == state_write) {
- ack = kw_read_reg(reg_status);
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- DBG("KW: nack on data write\n");
- *rc = -EIO;
- goto stop;
- } else if (*len) {
- kw_write_reg(reg_data, **data);
- (*data)++; (*len)--;
- } else {
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- state = state_stop;
- *rc = 0;
- }
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
- } else {
- kw_write_reg(reg_isr, KW_I2C_IRQ_DATA);
- WRONG_STATE("KW_I2C_IRQ_DATA");
- if (state != state_stop) {
- *rc = -EIO;
- goto stop;
- }
- }
- }
-
- if (isr & KW_I2C_IRQ_STOP) {
- kw_write_reg(reg_isr, KW_I2C_IRQ_STOP);
- if (state != state_stop) {
- WRONG_STATE("KW_I2C_IRQ_STOP");
- *rc = -EIO;
- }
- return state_idle;
- }
-
- if (isr & KW_I2C_IRQ_START)
- kw_write_reg(reg_isr, KW_I2C_IRQ_START);
-
- return state;
-
- stop:
- kw_write_reg(reg_control, KW_I2C_CTL_STOP);
- return state_stop;
-}
-
-static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len)
-{
- u8 mode_reg = host->speed;
- int state = state_addr;
- int rc = 0;
-
- /* Setup mode & subaddress if any */
- switch(host->mode) {
- case pmac_low_i2c_mode_dumb:
- printk(KERN_ERR "low_i2c: Dumb mode not supported !\n");
- return -EINVAL;
- case pmac_low_i2c_mode_std:
- mode_reg |= KW_I2C_MODE_STANDARD;
- break;
- case pmac_low_i2c_mode_stdsub:
- mode_reg |= KW_I2C_MODE_STANDARDSUB;
- kw_write_reg(reg_subaddr, subaddr);
- break;
- case pmac_low_i2c_mode_combined:
- mode_reg |= KW_I2C_MODE_COMBINED;
- kw_write_reg(reg_subaddr, subaddr);
- break;
- }
-
- /* Setup channel & clear pending irqs */
- kw_write_reg(reg_isr, kw_read_reg(reg_isr));
- kw_write_reg(reg_mode, mode_reg | (host->channel << 4));
- kw_write_reg(reg_status, 0);
-
- /* Set up address and r/w bit */
- kw_write_reg(reg_addr, addr);
-
- /* Start sending address & disable interrupt*/
- kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
- kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
-
- /* State machine, to turn into an interrupt handler */
- while(state != state_idle) {
- u8 isr = kw_wait_interrupt(host);
- state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr);
- }
-
- return rc;
-}
-
-static void keywest_low_i2c_add(struct device_node *np)
-{
- struct low_i2c_host *host = find_low_i2c_host(NULL);
- unsigned long *psteps, *prate, steps, aoffset = 0;
- struct device_node *parent;
-
- if (host == NULL) {
- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
- np->full_name);
- return;
- }
- memset(host, 0, sizeof(*host));
-
- init_MUTEX(&host->mutex);
- host->np = of_node_get(np);
- psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);
- steps = psteps ? (*psteps) : 0x10;
- for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
- steps >>= 1;
- parent = of_get_parent(np);
- host->num_channels = 1;
- if (parent && parent->name[0] == 'u') {
- host->num_channels = 2;
- aoffset = 3;
- }
- /* Select interface rate */
- host->speed = KW_I2C_MODE_100KHZ;
- prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);
- if (prate) switch(*prate) {
- case 100:
- host->speed = KW_I2C_MODE_100KHZ;
- break;
- case 50:
- host->speed = KW_I2C_MODE_50KHZ;
- break;
- case 25:
- host->speed = KW_I2C_MODE_25KHZ;
- break;
- }
- host->mode = pmac_low_i2c_mode_std;
- host->base = ioremap(np->addrs[0].address + aoffset,
- np->addrs[0].size);
- host->func = keywest_low_i2c_func;
-}
-
-/*
- *
- * PMU implementation
- *
- */
-
-
-#ifdef CONFIG_ADB_PMU
-
-static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len)
-{
- // TODO
- return -ENODEV;
-}
-
-static void pmu_low_i2c_add(struct device_node *np)
-{
- struct low_i2c_host *host = find_low_i2c_host(NULL);
-
- if (host == NULL) {
- printk(KERN_ERR "low_i2c: Can't allocate host for %s\n",
- np->full_name);
- return;
- }
- memset(host, 0, sizeof(*host));
-
- init_MUTEX(&host->mutex);
- host->np = of_node_get(np);
- host->num_channels = 3;
- host->mode = pmac_low_i2c_mode_std;
- host->func = pmu_low_i2c_func;
-}
-
-#endif /* CONFIG_ADB_PMU */
-
-void __init pmac_init_low_i2c(void)
-{
- struct device_node *np;
-
- /* Probe keywest-i2c busses */
- np = of_find_compatible_node(NULL, "i2c", "keywest-i2c");
- while(np) {
- keywest_low_i2c_add(np);
- np = of_find_compatible_node(np, "i2c", "keywest-i2c");
- }
-
-#ifdef CONFIG_ADB_PMU
- /* Probe PMU busses */
- np = of_find_node_by_name(NULL, "via-pmu");
- if (np)
- pmu_low_i2c_add(np);
-#endif /* CONFIG_ADB_PMU */
-
- /* TODO: Add CUDA support as well */
-}
-
-int pmac_low_i2c_lock(struct device_node *np)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
- down(&host->mutex);
- return 0;
-}
-EXPORT_SYMBOL(pmac_low_i2c_lock);
-
-int pmac_low_i2c_unlock(struct device_node *np)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
- up(&host->mutex);
- return 0;
-}
-EXPORT_SYMBOL(pmac_low_i2c_unlock);
-
-
-int pmac_low_i2c_open(struct device_node *np, int channel)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
-
- if (channel >= host->num_channels)
- return -EINVAL;
-
- down(&host->mutex);
- host->is_open = 1;
- host->channel = channel;
-
- return 0;
-}
-EXPORT_SYMBOL(pmac_low_i2c_open);
-
-int pmac_low_i2c_close(struct device_node *np)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
-
- host->is_open = 0;
- up(&host->mutex);
-
- return 0;
-}
-EXPORT_SYMBOL(pmac_low_i2c_close);
-
-int pmac_low_i2c_setmode(struct device_node *np, int mode)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
- WARN_ON(!host->is_open);
- host->mode = mode;
-
- return 0;
-}
-EXPORT_SYMBOL(pmac_low_i2c_setmode);
-
-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len)
-{
- struct low_i2c_host *host = find_low_i2c_host(np);
-
- if (!host)
- return -ENODEV;
- WARN_ON(!host->is_open);
-
- return host->func(host, addrdir, subaddr, data, len);
-}
-EXPORT_SYMBOL(pmac_low_i2c_xfer);
-
diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c
deleted file mode 100644
index 8c9b008c7226..000000000000
--- a/arch/ppc/platforms/pmac_nvram.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * arch/ppc/platforms/pmac_nvram.c
- *
- * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.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.
- *
- * Todo: - add support for the OF persistent properties
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/nvram.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <linux/bootmem.h>
-#include <linux/completion.h>
-#include <linux/spinlock.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-
-#define DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
-
-#define CORE99_SIGNATURE 0x5a
-#define CORE99_ADLER_START 0x14
-
-/* On Core99, nvram is either a sharp, a micron or an AMD flash */
-#define SM_FLASH_STATUS_DONE 0x80
-#define SM_FLASH_STATUS_ERR 0x38
-#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0
-#define SM_FLASH_CMD_ERASE_SETUP 0x20
-#define SM_FLASH_CMD_RESET 0xff
-#define SM_FLASH_CMD_WRITE_SETUP 0x40
-#define SM_FLASH_CMD_CLEAR_STATUS 0x50
-#define SM_FLASH_CMD_READ_STATUS 0x70
-
-/* CHRP NVRAM header */
-struct chrp_header {
- u8 signature;
- u8 cksum;
- u16 len;
- char name[12];
- u8 data[0];
-};
-
-struct core99_header {
- struct chrp_header hdr;
- u32 adler;
- u32 generation;
- u32 reserved[2];
-};
-
-/*
- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
- */
-static int nvram_naddrs;
-static volatile unsigned char *nvram_addr;
-static volatile unsigned char *nvram_data;
-static int nvram_mult, is_core_99;
-static int core99_bank = 0;
-static int nvram_partitions[3];
-static DEFINE_SPINLOCK(nv_lock);
-
-extern int pmac_newworld;
-extern int system_running;
-
-static int (*core99_write_bank)(int bank, u8* datas);
-static int (*core99_erase_bank)(int bank);
-
-static char *nvram_image;
-
-
-static unsigned char core99_nvram_read_byte(int addr)
-{
- if (nvram_image == NULL)
- return 0xff;
- return nvram_image[addr];
-}
-
-static void core99_nvram_write_byte(int addr, unsigned char val)
-{
- if (nvram_image == NULL)
- return;
- nvram_image[addr] = val;
-}
-
-
-static unsigned char direct_nvram_read_byte(int addr)
-{
- return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
-}
-
-static void direct_nvram_write_byte(int addr, unsigned char val)
-{
- out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
-}
-
-
-static unsigned char indirect_nvram_read_byte(int addr)
-{
- unsigned char val;
- unsigned long flags;
-
- spin_lock_irqsave(&nv_lock, flags);
- out_8(nvram_addr, addr >> 5);
- val = in_8(&nvram_data[(addr & 0x1f) << 4]);
- spin_unlock_irqrestore(&nv_lock, flags);
-
- return val;
-}
-
-static void indirect_nvram_write_byte(int addr, unsigned char val)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&nv_lock, flags);
- out_8(nvram_addr, addr >> 5);
- out_8(&nvram_data[(addr & 0x1f) << 4], val);
- spin_unlock_irqrestore(&nv_lock, flags);
-}
-
-
-#ifdef CONFIG_ADB_PMU
-
-static void pmu_nvram_complete(struct adb_request *req)
-{
- if (req->arg)
- complete((struct completion *)req->arg);
-}
-
-static unsigned char pmu_nvram_read_byte(int addr)
-{
- struct adb_request req;
- DECLARE_COMPLETION(req_complete);
-
- req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
- if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
- (addr >> 8) & 0xff, addr & 0xff))
- return 0xff;
- if (system_state == SYSTEM_RUNNING)
- wait_for_completion(&req_complete);
- while (!req.complete)
- pmu_poll();
- return req.reply[0];
-}
-
-static void pmu_nvram_write_byte(int addr, unsigned char val)
-{
- struct adb_request req;
- DECLARE_COMPLETION(req_complete);
-
- req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
- if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
- (addr >> 8) & 0xff, addr & 0xff, val))
- return;
- if (system_state == SYSTEM_RUNNING)
- wait_for_completion(&req_complete);
- while (!req.complete)
- pmu_poll();
-}
-
-#endif /* CONFIG_ADB_PMU */
-
-
-static u8 chrp_checksum(struct chrp_header* hdr)
-{
- u8 *ptr;
- u16 sum = hdr->signature;
- for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
- sum += *ptr;
- while (sum > 0xFF)
- sum = (sum & 0xFF) + (sum>>8);
- return sum;
-}
-
-static u32 core99_calc_adler(u8 *buffer)
-{
- int cnt;
- u32 low, high;
-
- buffer += CORE99_ADLER_START;
- low = 1;
- high = 0;
- for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
- if ((cnt % 5000) == 0) {
- high %= 65521UL;
- high %= 65521UL;
- }
- low += buffer[cnt];
- high += low;
- }
- low %= 65521UL;
- high %= 65521UL;
-
- return (high << 16) | low;
-}
-
-static u32 core99_check(u8* datas)
-{
- struct core99_header* hdr99 = (struct core99_header*)datas;
-
- if (hdr99->hdr.signature != CORE99_SIGNATURE) {
- DBG("Invalid signature\n");
- return 0;
- }
- if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
- DBG("Invalid checksum\n");
- return 0;
- }
- if (hdr99->adler != core99_calc_adler(datas)) {
- DBG("Invalid adler\n");
- return 0;
- }
- return hdr99->generation;
-}
-
-static int sm_erase_bank(int bank)
-{
- int stat, i;
- unsigned long timeout;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
-
- out_8(base, SM_FLASH_CMD_ERASE_SETUP);
- out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
- timeout = 0;
- do {
- if (++timeout > 1000000) {
- printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n");
- break;
- }
- out_8(base, SM_FLASH_CMD_READ_STATUS);
- stat = in_8(base);
- } while (!(stat & SM_FLASH_STATUS_DONE));
-
- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
- out_8(base, SM_FLASH_CMD_RESET);
-
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != 0xff) {
- printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static int sm_write_bank(int bank, u8* datas)
-{
- int i, stat = 0;
- unsigned long timeout;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
-
- for (i=0; i<NVRAM_SIZE; i++) {
- out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
- udelay(1);
- out_8(base+i, datas[i]);
- timeout = 0;
- do {
- if (++timeout > 1000000) {
- printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
- break;
- }
- out_8(base, SM_FLASH_CMD_READ_STATUS);
- stat = in_8(base);
- } while (!(stat & SM_FLASH_STATUS_DONE));
- if (!(stat & SM_FLASH_STATUS_DONE))
- break;
- }
- out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
- out_8(base, SM_FLASH_CMD_RESET);
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != datas[i]) {
- printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static int amd_erase_bank(int bank)
-{
- int i, stat = 0;
- unsigned long timeout;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- DBG("nvram: AMD Erasing bank %d...\n", bank);
-
- /* Unlock 1 */
- out_8(base+0x555, 0xaa);
- udelay(1);
- /* Unlock 2 */
- out_8(base+0x2aa, 0x55);
- udelay(1);
-
- /* Sector-Erase */
- out_8(base+0x555, 0x80);
- udelay(1);
- out_8(base+0x555, 0xaa);
- udelay(1);
- out_8(base+0x2aa, 0x55);
- udelay(1);
- out_8(base, 0x30);
- udelay(1);
-
- timeout = 0;
- do {
- if (++timeout > 1000000) {
- printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
- break;
- }
- stat = in_8(base) ^ in_8(base);
- } while (stat != 0);
-
- /* Reset */
- out_8(base, 0xf0);
- udelay(1);
-
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != 0xff) {
- printk(KERN_ERR "nvram: AMD flash erase failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static int amd_write_bank(int bank, u8* datas)
-{
- int i, stat = 0;
- unsigned long timeout;
-
- u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-
- DBG("nvram: AMD Writing bank %d...\n", bank);
-
- for (i=0; i<NVRAM_SIZE; i++) {
- /* Unlock 1 */
- out_8(base+0x555, 0xaa);
- udelay(1);
- /* Unlock 2 */
- out_8(base+0x2aa, 0x55);
- udelay(1);
-
- /* Write single word */
- out_8(base+0x555, 0xa0);
- udelay(1);
- out_8(base+i, datas[i]);
-
- timeout = 0;
- do {
- if (++timeout > 1000000) {
- printk(KERN_ERR "nvram: AMD flash write timeout !\n");
- break;
- }
- stat = in_8(base) ^ in_8(base);
- } while (stat != 0);
- if (stat != 0)
- break;
- }
-
- /* Reset */
- out_8(base, 0xf0);
- udelay(1);
-
- for (i=0; i<NVRAM_SIZE; i++)
- if (base[i] != datas[i]) {
- printk(KERN_ERR "nvram: AMD flash write failed !\n");
- return -ENXIO;
- }
- return 0;
-}
-
-static void __init lookup_partitions(void)
-{
- u8 buffer[17];
- int i, offset;
- struct chrp_header* hdr;
-
- if (pmac_newworld) {
- nvram_partitions[pmac_nvram_OF] = -1;
- nvram_partitions[pmac_nvram_XPRAM] = -1;
- nvram_partitions[pmac_nvram_NR] = -1;
- hdr = (struct chrp_header *)buffer;
-
- offset = 0;
- buffer[16] = 0;
- do {
- for (i=0;i<16;i++)
- buffer[i] = nvram_read_byte(offset+i);
- if (!strcmp(hdr->name, "common"))
- nvram_partitions[pmac_nvram_OF] = offset + 0x10;
- if (!strcmp(hdr->name, "APL,MacOS75")) {
- nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
- nvram_partitions[pmac_nvram_NR] = offset + 0x110;
- }
- offset += (hdr->len * 0x10);
- } while(offset < NVRAM_SIZE);
- } else {
- nvram_partitions[pmac_nvram_OF] = 0x1800;
- nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
- nvram_partitions[pmac_nvram_NR] = 0x1400;
- }
- DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
- DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
- DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
-}
-
-static void core99_nvram_sync(void)
-{
- struct core99_header* hdr99;
- unsigned long flags;
-
- if (!is_core_99 || !nvram_data || !nvram_image)
- return;
-
- spin_lock_irqsave(&nv_lock, flags);
- if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
- NVRAM_SIZE))
- goto bail;
-
- DBG("Updating nvram...\n");
-
- hdr99 = (struct core99_header*)nvram_image;
- hdr99->generation++;
- hdr99->hdr.signature = CORE99_SIGNATURE;
- hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
- hdr99->adler = core99_calc_adler(nvram_image);
- core99_bank = core99_bank ? 0 : 1;
- if (core99_erase_bank)
- if (core99_erase_bank(core99_bank)) {
- printk("nvram: Error erasing bank %d\n", core99_bank);
- goto bail;
- }
- if (core99_write_bank)
- if (core99_write_bank(core99_bank, nvram_image))
- printk("nvram: Error writing bank %d\n", core99_bank);
- bail:
- spin_unlock_irqrestore(&nv_lock, flags);
-
-#ifdef DEBUG
- mdelay(2000);
-#endif
-}
-
-void __init pmac_nvram_init(void)
-{
- struct device_node *dp;
-
- nvram_naddrs = 0;
-
- dp = find_devices("nvram");
- if (dp == NULL) {
- printk(KERN_ERR "Can't find NVRAM device\n");
- return;
- }
- nvram_naddrs = dp->n_addrs;
- is_core_99 = device_is_compatible(dp, "nvram,flash");
- if (is_core_99) {
- int i;
- u32 gen_bank0, gen_bank1;
-
- if (nvram_naddrs < 1) {
- printk(KERN_ERR "nvram: no address\n");
- return;
- }
- nvram_image = alloc_bootmem(NVRAM_SIZE);
- if (nvram_image == NULL) {
- printk(KERN_ERR "nvram: can't allocate ram image\n");
- return;
- }
- nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
- nvram_naddrs = 1; /* Make sure we get the correct case */
-
- DBG("nvram: Checking bank 0...\n");
-
- gen_bank0 = core99_check((u8 *)nvram_data);
- gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
- core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
-
- DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
- DBG("nvram: Active bank is: %d\n", core99_bank);
-
- for (i=0; i<NVRAM_SIZE; i++)
- nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
-
- ppc_md.nvram_read_val = core99_nvram_read_byte;
- ppc_md.nvram_write_val = core99_nvram_write_byte;
- ppc_md.nvram_sync = core99_nvram_sync;
- /*
- * Maybe we could be smarter here though making an exclusive list
- * of known flash chips is a bit nasty as older OF didn't provide us
- * with a useful "compatible" entry. A solution would be to really
- * identify the chip using flash id commands and base ourselves on
- * a list of known chips IDs
- */
- if (device_is_compatible(dp, "amd-0137")) {
- core99_erase_bank = amd_erase_bank;
- core99_write_bank = amd_write_bank;
- } else {
- core99_erase_bank = sm_erase_bank;
- core99_write_bank = sm_write_bank;
- }
- } else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
- dp->addrs[0].size);
- nvram_mult = 1;
- ppc_md.nvram_read_val = direct_nvram_read_byte;
- ppc_md.nvram_write_val = direct_nvram_write_byte;
- } else if (nvram_naddrs == 1) {
- nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
- ppc_md.nvram_read_val = direct_nvram_read_byte;
- ppc_md.nvram_write_val = direct_nvram_write_byte;
- } else if (nvram_naddrs == 2) {
- nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
- nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
- ppc_md.nvram_read_val = indirect_nvram_read_byte;
- ppc_md.nvram_write_val = indirect_nvram_write_byte;
- } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
-#ifdef CONFIG_ADB_PMU
- nvram_naddrs = -1;
- ppc_md.nvram_read_val = pmu_nvram_read_byte;
- ppc_md.nvram_write_val = pmu_nvram_write_byte;
-#endif /* CONFIG_ADB_PMU */
- } else {
- printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
- nvram_naddrs);
- }
- lookup_partitions();
-}
-
-int pmac_get_partition(int partition)
-{
- return nvram_partitions[partition];
-}
-
-u8 pmac_xpram_read(int xpaddr)
-{
- int offset = nvram_partitions[pmac_nvram_XPRAM];
-
- if (offset < 0)
- return 0xff;
-
- return ppc_md.nvram_read_val(xpaddr + offset);
-}
-
-void pmac_xpram_write(int xpaddr, u8 data)
-{
- int offset = nvram_partitions[pmac_nvram_XPRAM];
-
- if (offset < 0)
- return;
-
- ppc_md.nvram_write_val(xpaddr + offset, data);
-}
-
-EXPORT_SYMBOL(pmac_get_partition);
-EXPORT_SYMBOL(pmac_xpram_read);
-EXPORT_SYMBOL(pmac_xpram_write);
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
deleted file mode 100644
index 786295b6ddd0..000000000000
--- a/arch/ppc/platforms/pmac_pci.c
+++ /dev/null
@@ -1,1124 +0,0 @@
-/*
- * Support for PCI bridges found on Power Macintoshes.
- * At present the "bandit" and "chaos" bridges are supported.
- * Fortunately you access configuration space in the same
- * way with either bridge.
- *
- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#ifdef CONFIG_XMON
-extern void xmon_printf(const char *fmt, ...);
-#define DBG(x...) xmon_printf(x)
-#else
-#define DBG(x...) printk(x)
-#endif
-#else
-#define DBG(x...)
-#endif
-
-static int add_bridge(struct device_node *dev);
-extern void pmac_check_ht_link(void);
-
-/* XXX Could be per-controller, but I don't think we risk anything by
- * assuming we won't have both UniNorth and Bandit */
-static int has_uninorth;
-#ifdef CONFIG_POWER4
-static struct pci_controller *u3_agp;
-#endif /* CONFIG_POWER4 */
-
-extern u8 pci_cache_line_size;
-extern int pcibios_assign_bus_offset;
-
-struct device_node *k2_skiplist[2];
-
-/*
- * Magic constants for enabling cache coherency in the bandit/PSX bridge.
- */
-#define BANDIT_DEVID_2 8
-#define BANDIT_REVID 3
-
-#define BANDIT_DEVNUM 11
-#define BANDIT_MAGIC 0x50
-#define BANDIT_COHERENT 0x40
-
-static int __init
-fixup_one_level_bus_range(struct device_node *node, int higher)
-{
- for (; node != 0;node = node->sibling) {
- int * bus_range;
- unsigned int *class_code;
- int len;
-
- /* For PCI<->PCI bridges or CardBus bridges, we go down */
- class_code = (unsigned int *) get_property(node, "class-code", NULL);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
- continue;
- bus_range = (int *) get_property(node, "bus-range", &len);
- if (bus_range != NULL && len > 2 * sizeof(int)) {
- if (bus_range[1] > higher)
- higher = bus_range[1];
- }
- higher = fixup_one_level_bus_range(node->child, higher);
- }
- return higher;
-}
-
-/* This routine fixes the "bus-range" property of all bridges in the
- * system since they tend to have their "last" member wrong on macs
- *
- * Note that the bus numbers manipulated here are OF bus numbers, they
- * are not Linux bus numbers.
- */
-static void __init
-fixup_bus_range(struct device_node *bridge)
-{
- int * bus_range;
- int len;
-
- /* Lookup the "bus-range" property for the hose */
- bus_range = (int *) get_property(bridge, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s\n",
- bridge->full_name);
- return;
- }
- bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
-}
-
-/*
- * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers.
- *
- * The "Bandit" version is present in all early PCI PowerMacs,
- * and up to the first ones using Grackle. Some machines may
- * have 2 bandit controllers (2 PCI busses).
- *
- * "Chaos" is used in some "Bandit"-type machines as a bridge
- * for the separate display bus. It is accessed the same
- * way as bandit, but cannot be probed for devices. It therefore
- * has its own config access functions.
- *
- * The "UniNorth" version is present in all Core99 machines
- * (iBook, G4, new IMacs, and all the recent Apple machines).
- * It contains 3 controllers in one ASIC.
- *
- * The U3 is the bridge used on G5 machines. It contains an
- * AGP bus which is dealt with the old UniNorth access routines
- * and a HyperTransport bus which uses its own set of access
- * functions.
- */
-
-#define MACRISC_CFA0(devfn, off) \
- ((1 << (unsigned long)PCI_SLOT(dev_fn)) \
- | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
- | (((unsigned long)(off)) & 0xFCUL))
-
-#define MACRISC_CFA1(bus, devfn, off) \
- ((((unsigned long)(bus)) << 16) \
- |(((unsigned long)(devfn)) << 8) \
- |(((unsigned long)(off)) & 0xFCUL) \
- |1UL)
-
-static void volatile __iomem *
-macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
-{
- unsigned int caddr;
-
- if (bus == hose->first_busno) {
- if (dev_fn < (11 << 3))
- return NULL;
- caddr = MACRISC_CFA0(dev_fn, offset);
- } else
- caddr = MACRISC_CFA1(bus, dev_fn, offset);
-
- /* Uninorth will return garbage if we don't read back the value ! */
- do {
- out_le32(hose->cfg_addr, caddr);
- } while (in_le32(hose->cfg_addr) != caddr);
-
- offset &= has_uninorth ? 0x07 : 0x03;
- return hose->cfg_data + offset;
-}
-
-static int
-macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- void volatile __iomem *addr;
-
- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_le16(addr);
- break;
- default:
- *val = in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- void volatile __iomem *addr;
-
- addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- out_8(addr, val);
- (void) in_8(addr);
- break;
- case 2:
- out_le16(addr, val);
- (void) in_le16(addr);
- break;
- default:
- out_le32(addr, val);
- (void) in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops macrisc_pci_ops =
-{
- macrisc_read_config,
- macrisc_write_config
-};
-
-/*
- * Verifiy that a specific (bus, dev_fn) exists on chaos
- */
-static int
-chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
-{
- struct device_node *np;
- u32 *vendor, *device;
-
- np = pci_busdev_to_OF_node(bus, devfn);
- if (np == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- vendor = (u32 *)get_property(np, "vendor-id", NULL);
- device = (u32 *)get_property(np, "device-id", NULL);
- if (vendor == NULL || device == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10)
- && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- int result = chaos_validate_dev(bus, devfn, offset);
- if (result == PCIBIOS_BAD_REGISTER_NUMBER)
- *val = ~0U;
- if (result != PCIBIOS_SUCCESSFUL)
- return result;
- return macrisc_read_config(bus, devfn, offset, len, val);
-}
-
-static int
-chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- int result = chaos_validate_dev(bus, devfn, offset);
- if (result != PCIBIOS_SUCCESSFUL)
- return result;
- return macrisc_write_config(bus, devfn, offset, len, val);
-}
-
-static struct pci_ops chaos_pci_ops =
-{
- chaos_read_config,
- chaos_write_config
-};
-
-#ifdef CONFIG_POWER4
-
-/*
- * These versions of U3 HyperTransport config space access ops do not
- * implement self-view of the HT host yet
- */
-
-#define U3_HT_CFA0(devfn, off) \
- ((((unsigned long)devfn) << 8) | offset)
-#define U3_HT_CFA1(bus, devfn, off) \
- (U3_HT_CFA0(devfn, off) \
- + (((unsigned long)bus) << 16) \
- + 0x01000000UL)
-
-static void volatile __iomem *
-u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset)
-{
- if (bus == hose->first_busno) {
- /* For now, we don't self probe U3 HT bridge */
- if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 ||
- PCI_SLOT(devfn) < 1)
- return 0;
- return hose->cfg_data + U3_HT_CFA0(devfn, offset);
- } else
- return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset);
-}
-
-static int
-u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- void volatile __iomem *addr;
- int i;
-
- struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
- if (np == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- /*
- * When a device in K2 is powered down, we die on config
- * cycle accesses. Fix that here.
- */
- for (i=0; i<2; i++)
- if (k2_skiplist[i] == np) {
- switch (len) {
- case 1:
- *val = 0xff; break;
- case 2:
- *val = 0xffff; break;
- default:
- *val = 0xfffffffful; break;
- }
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- *val = in_8(addr);
- break;
- case 2:
- *val = in_le16(addr);
- break;
- default:
- *val = in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- void volatile __iomem *addr;
- int i;
-
- struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
- if (np == NULL)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * When a device in K2 is powered down, we die on config
- * cycle accesses. Fix that here.
- */
- for (i=0; i<2; i++)
- if (k2_skiplist[i] == np)
- return PCIBIOS_SUCCESSFUL;
-
- addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
- if (!addr)
- return PCIBIOS_DEVICE_NOT_FOUND;
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- switch (len) {
- case 1:
- out_8(addr, val);
- (void) in_8(addr);
- break;
- case 2:
- out_le16(addr, val);
- (void) in_le16(addr);
- break;
- default:
- out_le32(addr, val);
- (void) in_le32(addr);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops u3_ht_pci_ops =
-{
- u3_ht_read_config,
- u3_ht_write_config
-};
-
-#endif /* CONFIG_POWER4 */
-
-/*
- * For a bandit bridge, turn on cache coherency if necessary.
- * N.B. we could clean this up using the hose ops directly.
- */
-static void __init
-init_bandit(struct pci_controller *bp)
-{
- unsigned int vendev, magic;
- int rev;
-
- /* read the word at offset 0 in config space for device 11 */
- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
- udelay(2);
- vendev = in_le32(bp->cfg_data);
- if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) +
- PCI_VENDOR_ID_APPLE) {
- /* read the revision id */
- out_le32(bp->cfg_addr,
- (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
- udelay(2);
- rev = in_8(bp->cfg_data);
- if (rev != BANDIT_REVID)
- printk(KERN_WARNING
- "Unknown revision %d for bandit\n", rev);
- } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
- printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
- return;
- }
-
- /* read the word at offset 0x50 */
- out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
- udelay(2);
- magic = in_le32(bp->cfg_data);
- if ((magic & BANDIT_COHERENT) != 0)
- return;
- magic |= BANDIT_COHERENT;
- udelay(2);
- out_le32(bp->cfg_data, magic);
- printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
-}
-
-
-/*
- * Tweak the PCI-PCI bridge chip on the blue & white G3s.
- */
-static void __init
-init_p2pbridge(void)
-{
- struct device_node *p2pbridge;
- struct pci_controller* hose;
- u8 bus, devfn;
- u16 val;
-
- /* XXX it would be better here to identify the specific
- PCI-PCI bridge chip we have. */
- if ((p2pbridge = find_devices("pci-bridge")) == 0
- || p2pbridge->parent == NULL
- || strcmp(p2pbridge->parent->name, "pci") != 0)
- return;
- if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
- DBG("Can't find PCI infos for PCI<->PCI bridge\n");
- return;
- }
- /* Warning: At this point, we have not yet renumbered all busses.
- * So we must use OF walking to find out hose
- */
- hose = pci_find_hose_for_OF_device(p2pbridge);
- if (!hose) {
- DBG("Can't find hose for PCI<->PCI bridge\n");
- return;
- }
- if (early_read_config_word(hose, bus, devfn,
- PCI_BRIDGE_CONTROL, &val) < 0) {
- printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
- return;
- }
- val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
- early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
-}
-
-/*
- * Some Apple desktop machines have a NEC PD720100A USB2 controller
- * on the motherboard. Open Firmware, on these, will disable the
- * EHCI part of it so it behaves like a pair of OHCI's. This fixup
- * code re-enables it ;)
- */
-static void __init
-fixup_nec_usb2(void)
-{
- struct device_node *nec;
-
- for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) {
- struct pci_controller *hose;
- u32 data, *prop;
- u8 bus, devfn;
-
- prop = (u32 *)get_property(nec, "vendor-id", NULL);
- if (prop == NULL)
- continue;
- if (0x1033 != *prop)
- continue;
- prop = (u32 *)get_property(nec, "device-id", NULL);
- if (prop == NULL)
- continue;
- if (0x0035 != *prop)
- continue;
- prop = (u32 *)get_property(nec, "reg", NULL);
- if (prop == NULL)
- continue;
- devfn = (prop[0] >> 8) & 0xff;
- bus = (prop[0] >> 16) & 0xff;
- if (PCI_FUNC(devfn) != 0)
- continue;
- hose = pci_find_hose_for_OF_device(nec);
- if (!hose)
- continue;
- early_read_config_dword(hose, bus, devfn, 0xe4, &data);
- if (data & 1UL) {
- printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n");
- data &= ~1UL;
- early_write_config_dword(hose, bus, devfn, 0xe4, data);
- early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE,
- nec->intrs[0].line);
- }
- }
-}
-
-void __init
-pmac_find_bridges(void)
-{
- struct device_node *np, *root;
- struct device_node *ht = NULL;
-
- root = of_find_node_by_path("/");
- if (root == NULL) {
- printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n");
- return;
- }
- for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) {
- if (np->name == NULL)
- continue;
- if (strcmp(np->name, "bandit") == 0
- || strcmp(np->name, "chaos") == 0
- || strcmp(np->name, "pci") == 0) {
- if (add_bridge(np) == 0)
- of_node_get(np);
- }
- if (strcmp(np->name, "ht") == 0) {
- of_node_get(np);
- ht = np;
- }
- }
- of_node_put(root);
-
- /* Probe HT last as it relies on the agp resources to be already
- * setup
- */
- if (ht && add_bridge(ht) != 0)
- of_node_put(ht);
-
- init_p2pbridge();
- fixup_nec_usb2();
-
- /* We are still having some issues with the Xserve G4, enabling
- * some offset between bus number and domains for now when we
- * assign all busses should help for now
- */
- if (pci_assign_all_buses)
- pcibios_assign_bus_offset = 0x10;
-
-#ifdef CONFIG_POWER4
- /* There is something wrong with DMA on U3/HT. I haven't figured out
- * the details yet, but if I set the cache line size to 128 bytes like
- * it should, I'm getting memory corruption caused by devices like
- * sungem (even without the MWI bit set, but maybe sungem doesn't
- * care). Right now, it appears that setting up a 64 bytes line size
- * works properly, 64 bytes beeing the max transfer size of HT, I
- * suppose this is related the way HT/PCI are hooked together. I still
- * need to dive into more specs though to be really sure of what's
- * going on. --BenH.
- *
- * Ok, apparently, it's just that HT can't do more than 64 bytes
- * transactions. MWI seem to be meaningless there as well, it may
- * be worth nop'ing out pci_set_mwi too though I haven't done that
- * yet.
- *
- * Note that it's a bit different for whatever is in the AGP slot.
- * For now, I don't care, but this can become a real issue, we
- * should probably hook pci_set_mwi anyway to make sure it sets
- * the real cache line size in there.
- */
- if (machine_is_compatible("MacRISC4"))
- pci_cache_line_size = 16; /* 64 bytes */
-
- pmac_check_ht_link();
-#endif /* CONFIG_POWER4 */
-}
-
-#define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
- | (((o) & ~3) << 24))
-
-#define GRACKLE_PICR1_STG 0x00000040
-#define GRACKLE_PICR1_LOOPSNOOP 0x00000010
-
-/* N.B. this is called before bridges is initialized, so we can't
- use grackle_pcibios_{read,write}_config_dword. */
-static inline void grackle_set_stg(struct pci_controller* bp, int enable)
-{
- unsigned int val;
-
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- val = in_le32(bp->cfg_data);
- val = enable? (val | GRACKLE_PICR1_STG) :
- (val & ~GRACKLE_PICR1_STG);
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- out_le32(bp->cfg_data, val);
- (void)in_le32(bp->cfg_data);
-}
-
-static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
-{
- unsigned int val;
-
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- val = in_le32(bp->cfg_data);
- val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
- (val & ~GRACKLE_PICR1_LOOPSNOOP);
- out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
- out_le32(bp->cfg_data, val);
- (void)in_le32(bp->cfg_data);
-}
-
-static int __init
-setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
-{
- pci_assign_all_buses = 1;
- has_uninorth = 1;
- hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
- /* We "know" that the bridge at f2000000 has the PCI slots. */
- return addr->address == 0xf2000000;
-}
-
-static void __init
-setup_bandit(struct pci_controller* hose, struct reg_property* addr)
-{
- hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
- init_bandit(hose);
-}
-
-static void __init
-setup_chaos(struct pci_controller* hose, struct reg_property* addr)
-{
- /* assume a `chaos' bridge */
- hose->ops = &chaos_pci_ops;
- hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
- hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
-}
-
-#ifdef CONFIG_POWER4
-
-static void __init
-setup_u3_agp(struct pci_controller* hose, struct reg_property* addr)
-{
- /* On G5, we move AGP up to high bus number so we don't need
- * to reassign bus numbers for HT. If we ever have P2P bridges
- * on AGP, we'll have to move pci_assign_all_buses to the
- * pci_controller structure so we enable it for AGP and not for
- * HT childs.
- * We hard code the address because of the different size of
- * the reg address cell, we shall fix that by killing struct
- * reg_property and using some accessor functions instead
- */
- hose->first_busno = 0xf0;
- hose->last_busno = 0xff;
- has_uninorth = 1;
- hose->ops = &macrisc_pci_ops;
- hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
- hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
-
- u3_agp = hose;
-}
-
-static void __init
-setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)
-{
- struct device_node *np = (struct device_node *)hose->arch_data;
- int i, cur;
-
- hose->ops = &u3_ht_pci_ops;
-
- /* We hard code the address because of the different size of
- * the reg address cell, we shall fix that by killing struct
- * reg_property and using some accessor functions instead
- */
- hose->cfg_data = ioremap(0xf2000000, 0x02000000);
-
- /*
- * /ht node doesn't expose a "ranges" property, so we "remove" regions that
- * have been allocated to AGP. So far, this version of the code doesn't assign
- * any of the 0xfxxxxxxx "fine" memory regions to /ht.
- * We need to fix that sooner or later by either parsing all child "ranges"
- * properties or figuring out the U3 address space decoding logic and
- * then read its configuration register (if any).
- */
- hose->io_base_phys = 0xf4000000;
- hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
- isa_io_base = (unsigned long) hose->io_base_virt;
- hose->io_resource.name = np->full_name;
- hose->io_resource.start = 0;
- hose->io_resource.end = 0x003fffff;
- hose->io_resource.flags = IORESOURCE_IO;
- hose->pci_mem_offset = 0;
- hose->first_busno = 0;
- hose->last_busno = 0xef;
- hose->mem_resources[0].name = np->full_name;
- hose->mem_resources[0].start = 0x80000000;
- hose->mem_resources[0].end = 0xefffffff;
- hose->mem_resources[0].flags = IORESOURCE_MEM;
-
- if (u3_agp == NULL) {
- DBG("U3 has no AGP, using full resource range\n");
- return;
- }
-
- /* We "remove" the AGP resources from the resources allocated to HT, that
- * is we create "holes". However, that code does assumptions that so far
- * happen to be true (cross fingers...), typically that resources in the
- * AGP node are properly ordered
- */
- cur = 0;
- for (i=0; i<3; i++) {
- struct resource *res = &u3_agp->mem_resources[i];
- if (res->flags != IORESOURCE_MEM)
- continue;
- /* We don't care about "fine" resources */
- if (res->start >= 0xf0000000)
- continue;
- /* Check if it's just a matter of "shrinking" us in one direction */
- if (hose->mem_resources[cur].start == res->start) {
- DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
- cur, hose->mem_resources[cur].start, res->end + 1);
- hose->mem_resources[cur].start = res->end + 1;
- continue;
- }
- if (hose->mem_resources[cur].end == res->end) {
- DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
- cur, hose->mem_resources[cur].end, res->start - 1);
- hose->mem_resources[cur].end = res->start - 1;
- continue;
- }
- /* No, it's not the case, we need a hole */
- if (cur == 2) {
- /* not enough resources to make a hole, we drop part of the range */
- printk(KERN_WARNING "Running out of resources for /ht host !\n");
- hose->mem_resources[cur].end = res->start - 1;
- continue;
- }
- cur++;
- 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;
- hose->mem_resources[cur].start = res->end + 1;
- hose->mem_resources[cur].end = hose->mem_resources[cur-1].end;
- hose->mem_resources[cur-1].end = res->start - 1;
- }
-}
-
-#endif /* CONFIG_POWER4 */
-
-void __init
-setup_grackle(struct pci_controller *hose)
-{
- setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
- if (machine_is_compatible("AAPL,PowerBook1998"))
- grackle_set_loop_snoop(hose, 1);
-#if 0 /* Disabled for now, HW problems ??? */
- grackle_set_stg(hose, 1);
-#endif
-}
-
-/*
- * We assume that if we have a G3 powermac, we have one bridge called
- * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
- * if we have one or more bandit or chaos bridges, we don't have a MPC106.
- */
-static int __init
-add_bridge(struct device_node *dev)
-{
- int len;
- struct pci_controller *hose;
- struct reg_property *addr;
- char* disp_name;
- int *bus_range;
- int primary = 1;
-
- DBG("Adding PCI host bridge %s\n", dev->full_name);
-
- addr = (struct reg_property *) get_property(dev, "reg", &len);
- if (addr == NULL || len < sizeof(*addr)) {
- printk(KERN_WARNING "Can't use %s: no address\n",
- dev->full_name);
- return -ENODEV;
- }
- 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 = pcibios_alloc_controller();
- if (!hose)
- return -ENOMEM;
- hose->arch_data = dev;
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- disp_name = NULL;
-#ifdef CONFIG_POWER4
- if (device_is_compatible(dev, "u3-agp")) {
- setup_u3_agp(hose, addr);
- disp_name = "U3-AGP";
- primary = 0;
- } else if (device_is_compatible(dev, "u3-ht")) {
- setup_u3_ht(hose, addr);
- disp_name = "U3-HT";
- primary = 1;
- } else
-#endif /* CONFIG_POWER4 */
- if (device_is_compatible(dev, "uni-north")) {
- primary = setup_uninorth(hose, addr);
- disp_name = "UniNorth";
- } else if (strcmp(dev->name, "pci") == 0) {
- /* XXX assume this is a mpc106 (grackle) */
- setup_grackle(hose);
- disp_name = "Grackle (MPC106)";
- } else if (strcmp(dev->name, "bandit") == 0) {
- setup_bandit(hose, addr);
- disp_name = "Bandit";
- } else if (strcmp(dev->name, "chaos") == 0) {
- setup_chaos(hose, addr);
- disp_name = "Chaos";
- primary = 0;
- }
- printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
- disp_name, addr->address, hose->first_busno, hose->last_busno);
- DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
- hose, hose->cfg_addr, hose->cfg_data);
-
- /* Interpret the "ranges" property */
- /* This also maps the I/O region and sets isa_io/mem_base */
- pci_process_bridge_OF_ranges(hose, dev, primary);
-
- /* Fixup "bus-range" OF property */
- fixup_bus_range(dev);
-
- return 0;
-}
-
-static void __init
-pcibios_fixup_OF_interrupts(void)
-{
- struct pci_dev* dev = NULL;
-
- /*
- * Open Firmware often doesn't initialize the
- * PCI_INTERRUPT_LINE config register properly, so we
- * should find the device node and apply the interrupt
- * obtained from the OF device-tree
- */
- for_each_pci_dev(dev) {
- struct device_node *node;
- node = pci_device_to_OF_node(dev);
- /* this is the node, see if it has interrupts */
- if (node && node->n_intrs > 0)
- dev->irq = node->intrs[0].line;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-}
-
-void __init
-pmac_pcibios_fixup(void)
-{
- /* Fixup interrupts according to OF tree */
- pcibios_fixup_OF_interrupts();
-}
-
-int
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
-{
- struct device_node* node;
- int updatecfg = 0;
- int uninorth_child;
-
- node = pci_device_to_OF_node(dev);
-
- /* We don't want to enable USB controllers absent from the OF tree
- * (iBook second controller)
- */
- if (dev->vendor == PCI_VENDOR_ID_APPLE
- && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10))
- && !node) {
- printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n",
- pci_name(dev));
- return -EINVAL;
- }
-
- if (!node)
- return 0;
-
- uninorth_child = node->parent &&
- device_is_compatible(node->parent, "uni-north");
-
- /* Firewire & GMAC were disabled after PCI probe, the driver is
- * claiming them, we must re-enable them now.
- */
- if (uninorth_child && !strcmp(node->name, "firewire") &&
- (device_is_compatible(node, "pci106b,18") ||
- device_is_compatible(node, "pci106b,30") ||
- device_is_compatible(node, "pci11c1,5811"))) {
- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
- pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
- updatecfg = 1;
- }
- if (uninorth_child && !strcmp(node->name, "ethernet") &&
- device_is_compatible(node, "gmac")) {
- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
- updatecfg = 1;
- }
-
- if (updatecfg) {
- u16 cmd;
-
- /*
- * Make sure PCI is correctly configured
- *
- * We use old pci_bios versions of the function since, by
- * default, gmac is not powered up, and so will be absent
- * from the kernel initial PCI lookup.
- *
- * Should be replaced by 2.4 new PCI mechanisms and really
- * register the device.
- */
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
- pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size);
- }
-
- return 0;
-}
-
-/* We power down some devices after they have been probed. They'll
- * be powered back on later on
- */
-void __init
-pmac_pcibios_after_init(void)
-{
- struct device_node* nd;
-
-#ifdef CONFIG_BLK_DEV_IDE
- struct pci_dev *dev = NULL;
-
- /* OF fails to initialize IDE controllers on macs
- * (and maybe other machines)
- *
- * Ideally, this should be moved to the IDE layer, but we need
- * to check specifically with Andre Hedrick how to do it cleanly
- * since the common IDE code seem to care about the fact that the
- * BIOS may have disabled a controller.
- *
- * -- BenH
- */
- for_each_pci_dev(dev) {
- if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
- pci_enable_device(dev);
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
- nd = find_devices("firewire");
- while (nd) {
- if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
- device_is_compatible(nd, "pci106b,30") ||
- device_is_compatible(nd, "pci11c1,5811"))
- && device_is_compatible(nd->parent, "uni-north")) {
- pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
- pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
- }
- nd = nd->next;
- }
- nd = find_devices("ethernet");
- while (nd) {
- if (nd->parent && device_is_compatible(nd, "gmac")
- && device_is_compatible(nd->parent, "uni-north"))
- pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
- nd = nd->next;
- }
-}
-
-void pmac_pci_fixup_cardbus(struct pci_dev* dev)
-{
- if (_machine != _MACH_Pmac)
- return;
- /*
- * Fix the interrupt routing on the various cardbus bridges
- * used on powerbooks
- */
- if (dev->vendor != PCI_VENDOR_ID_TI)
- return;
- if (dev->device == PCI_DEVICE_ID_TI_1130 ||
- dev->device == PCI_DEVICE_ID_TI_1131) {
- u8 val;
- /* Enable PCI interrupt */
- if (pci_read_config_byte(dev, 0x91, &val) == 0)
- pci_write_config_byte(dev, 0x91, val | 0x30);
- /* Disable ISA interrupt mode */
- if (pci_read_config_byte(dev, 0x92, &val) == 0)
- pci_write_config_byte(dev, 0x92, val & ~0x06);
- }
- if (dev->device == PCI_DEVICE_ID_TI_1210 ||
- dev->device == PCI_DEVICE_ID_TI_1211 ||
- dev->device == PCI_DEVICE_ID_TI_1410 ||
- dev->device == PCI_DEVICE_ID_TI_1510) {
- u8 val;
- /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA
- signal out the MFUNC0 pin */
- if (pci_read_config_byte(dev, 0x8c, &val) == 0)
- pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2);
- /* Disable ISA interrupt mode */
- if (pci_read_config_byte(dev, 0x92, &val) == 0)
- pci_write_config_byte(dev, 0x92, val & ~0x06);
- }
-}
-
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
-
-void pmac_pci_fixup_pciata(struct pci_dev* dev)
-{
- u8 progif = 0;
-
- /*
- * On PowerMacs, we try to switch any PCI ATA controller to
- * fully native mode
- */
- if (_machine != _MACH_Pmac)
- return;
- /* Some controllers don't have the class IDE */
- if (dev->vendor == PCI_VENDOR_ID_PROMISE)
- switch(dev->device) {
- case PCI_DEVICE_ID_PROMISE_20246:
- case PCI_DEVICE_ID_PROMISE_20262:
- case PCI_DEVICE_ID_PROMISE_20263:
- case PCI_DEVICE_ID_PROMISE_20265:
- case PCI_DEVICE_ID_PROMISE_20267:
- case PCI_DEVICE_ID_PROMISE_20268:
- case PCI_DEVICE_ID_PROMISE_20269:
- case PCI_DEVICE_ID_PROMISE_20270:
- case PCI_DEVICE_ID_PROMISE_20271:
- case PCI_DEVICE_ID_PROMISE_20275:
- case PCI_DEVICE_ID_PROMISE_20276:
- case PCI_DEVICE_ID_PROMISE_20277:
- goto good;
- }
- /* Others, check PCI class */
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- good:
- pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
- if ((progif & 5) != 5) {
- printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
- (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
- if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
- (progif & 5) != 5)
- printk(KERN_ERR "Rewrite of PROGIF failed !\n");
- }
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
-
-
-/*
- * Disable second function on K2-SATA, it's broken
- * and disable IO BARs on first one
- */
-void pmac_pci_fixup_k2_sata(struct pci_dev* dev)
-{
- int i;
- u16 cmd;
-
- if (PCI_FUNC(dev->devfn) > 0) {
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- for (i = 0; i < 6; i++) {
- dev->resource[i].start = dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
- }
- } else {
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd &= ~PCI_COMMAND_IO;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- for (i = 0; i < 5; i++) {
- dev->resource[i].start = dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
- }
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c
deleted file mode 100644
index 4742bf609357..000000000000
--- a/arch/ppc/platforms/pmac_pic.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * Support for the interrupt controllers found on Power Macintosh,
- * currently Apple's "Grand Central" interrupt controller in all
- * it's incarnations. OpenPIC support used on newer machines is
- * in a separate file
- *
- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/xmon.h>
-#include <asm/pmac_feature.h>
-#include <asm/machdep.h>
-
-#include "pmac_pic.h"
-
-/*
- * XXX this should be in xmon.h, but putting it there means xmon.h
- * has to include <linux/interrupt.h> (to get irqreturn_t), which
- * causes all sorts of problems. -- paulus
- */
-extern irqreturn_t xmon_irq(int, void *, struct pt_regs *);
-
-struct pmac_irq_hw {
- unsigned int event;
- unsigned int enable;
- unsigned int ack;
- unsigned int level;
-};
-
-/* Default addresses */
-static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
- (struct pmac_irq_hw *) 0xf3000020,
- (struct pmac_irq_hw *) 0xf3000010,
- (struct pmac_irq_hw *) 0xf4000020,
- (struct pmac_irq_hw *) 0xf4000010,
-};
-
-#define GC_LEVEL_MASK 0x3ff00000
-#define OHARE_LEVEL_MASK 0x1ff00000
-#define HEATHROW_LEVEL_MASK 0x1ff00000
-
-static int max_irqs;
-static int max_real_irqs;
-static u32 level_mask[4];
-
-static DEFINE_SPINLOCK(pmac_pic_lock);
-
-
-#define GATWICK_IRQ_POOL_SIZE 10
-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
-
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-
-/*
- * Mark an irq as "lost". This is only used on the pmac
- * since it can lose interrupts (see pmac_set_irq_mask).
- * -- Cort
- */
-void
-__set_lost(unsigned long irq_nr, int nokick)
-{
- if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
- atomic_inc(&ppc_n_lost_interrupts);
- if (!nokick)
- set_dec(1);
- }
-}
-
-static void
-pmac_mask_and_ack_irq(unsigned int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
- unsigned long flags;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- clear_bit(irq_nr, ppc_cached_irq_mask);
- if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
- atomic_dec(&ppc_n_lost_interrupts);
- spin_lock_irqsave(&pmac_pic_lock, flags);
- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
- out_le32(&pmac_irq_hw[i]->ack, bit);
- do {
- /* make sure ack gets to controller before we enable
- interrupts */
- mb();
- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
- != (ppc_cached_irq_mask[i] & bit));
- spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-static void pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
- unsigned long flags;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- spin_lock_irqsave(&pmac_pic_lock, flags);
- /* enable unmasked interrupts */
- out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
-
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
- != (ppc_cached_irq_mask[i] & bit));
-
- /*
- * Unfortunately, setting the bit in the enable register
- * when the device interrupt is already on *doesn't* set
- * the bit in the flag register or request another interrupt.
- */
- if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
- __set_lost((ulong)irq_nr, nokicklost);
- spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-/* When an irq gets requested for the first client, if it's an
- * edge interrupt, we clear any previous one on the controller
- */
-static unsigned int pmac_startup_irq(unsigned int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
-
- if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0)
- out_le32(&pmac_irq_hw[i]->ack, bit);
- set_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr, 0);
-
- return 0;
-}
-
-static void pmac_mask_irq(unsigned int irq_nr)
-{
- clear_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr, 0);
- mb();
-}
-
-static void pmac_unmask_irq(unsigned int irq_nr)
-{
- set_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr, 0);
-}
-
-static void pmac_end_irq(unsigned int irq_nr)
-{
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
- && irq_desc[irq_nr].action) {
- set_bit(irq_nr, ppc_cached_irq_mask);
- pmac_set_irq_mask(irq_nr, 1);
- }
-}
-
-
-struct hw_interrupt_type pmac_pic = {
- .typename = " PMAC-PIC ",
- .startup = pmac_startup_irq,
- .enable = pmac_unmask_irq,
- .disable = pmac_mask_irq,
- .ack = pmac_mask_and_ack_irq,
- .end = pmac_end_irq,
-};
-
-struct hw_interrupt_type gatwick_pic = {
- .typename = " GATWICK ",
- .startup = pmac_startup_irq,
- .enable = pmac_unmask_irq,
- .disable = pmac_mask_irq,
- .ack = pmac_mask_and_ack_irq,
- .end = pmac_end_irq,
-};
-
-static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- int irq, bits;
-
- for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
- int i = irq >> 5;
- bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
- /* We must read level interrupts from the level register */
- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
- bits &= ppc_cached_irq_mask[i];
- if (bits == 0)
- continue;
- irq += __ilog2(bits);
- __do_IRQ(irq, regs);
- return IRQ_HANDLED;
- }
- printk("gatwick irq not from gatwick pic\n");
- return IRQ_NONE;
-}
-
-int
-pmac_get_irq(struct pt_regs *regs)
-{
- int irq;
- unsigned long bits = 0;
-
-#ifdef CONFIG_SMP
- void psurge_smp_message_recv(struct pt_regs *);
-
- /* IPI's are a hack on the powersurge -- Cort */
- if ( smp_processor_id() != 0 ) {
- psurge_smp_message_recv(regs);
- return -2; /* ignore, already handled */
- }
-#endif /* CONFIG_SMP */
- for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
- int i = irq >> 5;
- bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
- /* We must read level interrupts from the level register */
- bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
- bits &= ppc_cached_irq_mask[i];
- if (bits == 0)
- continue;
- irq += __ilog2(bits);
- break;
- }
-
- return irq;
-}
-
-/* This routine will fix some missing interrupt values in the device tree
- * on the gatwick mac-io controller used by some PowerBooks
- */
-static void __init
-pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
-{
- struct device_node *node;
- int count;
-
- memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
- node = gw->child;
- count = 0;
- while(node)
- {
- /* Fix SCC */
- if (strcasecmp(node->name, "escc") == 0)
- if (node->child) {
- if (node->child->n_intrs < 3) {
- node->child->intrs = &gatwick_int_pool[count];
- count += 3;
- }
- node->child->n_intrs = 3;
- node->child->intrs[0].line = 15+irq_base;
- node->child->intrs[1].line = 4+irq_base;
- node->child->intrs[2].line = 5+irq_base;
- printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
- node->child->intrs[0].line,
- node->child->intrs[1].line,
- node->child->intrs[2].line);
- }
- /* Fix media-bay & left SWIM */
- if (strcasecmp(node->name, "media-bay") == 0) {
- struct device_node* ya_node;
-
- if (node->n_intrs == 0)
- node->intrs = &gatwick_int_pool[count++];
- node->n_intrs = 1;
- node->intrs[0].line = 29+irq_base;
- printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
- node->intrs[0].line);
-
- ya_node = node->child;
- while(ya_node)
- {
- if (strcasecmp(ya_node->name, "floppy") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 19+irq_base;
- ya_node->intrs[1].line = 1+irq_base;
- printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- if (strcasecmp(ya_node->name, "ata4") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 14+irq_base;
- ya_node->intrs[1].line = 3+irq_base;
- printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- ya_node = ya_node->sibling;
- }
- }
- node = node->sibling;
- }
- if (count > 10) {
- printk("WARNING !! Gatwick interrupt pool overflow\n");
- printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
- printk(" requested = %d\n", count);
- }
-}
-
-/*
- * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
- * card which includes an ohare chip that acts as a second interrupt
- * controller. If we find this second ohare, set it up and fix the
- * interrupt value in the device tree for the ethernet chip.
- */
-static int __init enable_second_ohare(void)
-{
- unsigned char bus, devfn;
- unsigned short cmd;
- unsigned long addr;
- struct device_node *irqctrler = find_devices("pci106b,7");
- struct device_node *ether;
-
- if (irqctrler == NULL || irqctrler->n_addrs <= 0)
- return -1;
- addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
- pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
- max_irqs = 64;
- if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
- struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
- if (!hose)
- printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
- else {
- early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
- cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- cmd &= ~PCI_COMMAND_IO;
- early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
- }
- }
-
- /* Fix interrupt for the modem/ethernet combo controller. The number
- in the device tree (27) is bogus (correct for the ethernet-only
- board but not the combo ethernet/modem board).
- The real interrupt is 28 on the second controller -> 28+32 = 60.
- */
- ether = find_devices("pci1011,14");
- if (ether && ether->n_intrs > 0) {
- ether->intrs[0].line = 60;
- printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
- ether->intrs[0].line);
- }
-
- /* Return the interrupt number of the cascade */
- return irqctrler->intrs[0].line;
-}
-
-#ifdef CONFIG_POWER4
-static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- int irq;
-
- irq = openpic2_get_irq(regs);
- if (irq != -1)
- __do_IRQ(irq, regs);
- return IRQ_HANDLED;
-}
-
-static struct irqaction k2u3_cascade_action = {
- .handler = k2u3_action,
- .flags = 0,
- .mask = CPU_MASK_NONE,
- .name = "U3->K2 Cascade",
-};
-#endif /* CONFIG_POWER4 */
-
-#ifdef CONFIG_XMON
-static struct irqaction xmon_action = {
- .handler = xmon_irq,
- .flags = 0,
- .mask = CPU_MASK_NONE,
- .name = "NMI - XMON"
-};
-#endif
-
-static struct irqaction gatwick_cascade_action = {
- .handler = gatwick_action,
- .flags = SA_INTERRUPT,
- .mask = CPU_MASK_NONE,
- .name = "cascade",
-};
-
-void __init pmac_pic_init(void)
-{
- int i;
- struct device_node *irqctrler = NULL;
- struct device_node *irqctrler2 = NULL;
- struct device_node *np;
- unsigned long addr;
- int irq_cascade = -1;
-
- /* We first try to detect Apple's new Core99 chipset, since mac-io
- * is quite different on those machines and contains an IBM MPIC2.
- */
- np = find_type_devices("open-pic");
- while(np) {
- if (np->parent && !strcmp(np->parent->name, "u3"))
- irqctrler2 = np;
- else
- irqctrler = np;
- np = np->next;
- }
- if (irqctrler != NULL)
- {
- if (irqctrler->n_addrs > 0)
- {
- unsigned char senses[128];
-
- printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n",
- irqctrler->addrs[0].address);
-
- prom_get_irq_senses(senses, 0, 128);
- OpenPIC_InitSenses = senses;
- OpenPIC_NumInitSenses = 128;
- ppc_md.get_irq = openpic_get_irq;
- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0);
- OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
- irqctrler->addrs[0].size);
- openpic_init(0);
-
-#ifdef CONFIG_POWER4
- if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 &&
- irqctrler2->n_addrs > 0) {
- printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n",
- irqctrler2->addrs[0].address,
- irqctrler2->intrs[0].line);
- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0);
- OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address,
- irqctrler2->addrs[0].size);
- prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET,
- PMAC_OPENPIC2_OFFSET+128);
- OpenPIC_InitSenses = senses;
- OpenPIC_NumInitSenses = 128;
- openpic2_init(PMAC_OPENPIC2_OFFSET);
-
- if (setup_irq(irqctrler2->intrs[0].line,
- &k2u3_cascade_action))
- printk("Unable to get OpenPIC IRQ for cascade\n");
- }
-#endif /* CONFIG_POWER4 */
-
-#ifdef CONFIG_XMON
- {
- struct device_node* pswitch;
- int nmi_irq;
-
- pswitch = find_devices("programmer-switch");
- if (pswitch && pswitch->n_intrs) {
- nmi_irq = pswitch->intrs[0].line;
- openpic_init_nmi_irq(nmi_irq);
- setup_irq(nmi_irq, &xmon_action);
- }
- }
-#endif /* CONFIG_XMON */
- return;
- }
- irqctrler = NULL;
- }
-
- /* Get the level/edge settings, assume if it's not
- * a Grand Central nor an OHare, then it's an Heathrow
- * (or Paddington).
- */
- if (find_devices("gc"))
- level_mask[0] = GC_LEVEL_MASK;
- else if (find_devices("ohare")) {
- level_mask[0] = OHARE_LEVEL_MASK;
- /* We might have a second cascaded ohare */
- level_mask[1] = OHARE_LEVEL_MASK;
- } else {
- level_mask[0] = HEATHROW_LEVEL_MASK;
- level_mask[1] = 0;
- /* We might have a second cascaded heathrow */
- level_mask[2] = HEATHROW_LEVEL_MASK;
- level_mask[3] = 0;
- }
-
- /*
- * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
- * 1998 G3 Series PowerBooks have 128,
- * other powermacs have 32.
- * The combo ethernet/modem card for the Powerstar powerbooks
- * (2400/3400/3500, ohare based) has a second ohare chip
- * effectively making a total of 64.
- */
- max_irqs = max_real_irqs = 32;
- irqctrler = find_devices("mac-io");
- if (irqctrler)
- {
- max_real_irqs = 64;
- if (irqctrler->next)
- max_irqs = 128;
- else
- max_irqs = 64;
- }
- for ( i = 0; i < max_real_irqs ; i++ )
- irq_desc[i].handler = &pmac_pic;
-
- /* get addresses of first controller */
- if (irqctrler) {
- if (irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 0; i < 2; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (2 - i) * 0x10);
- }
-
- /* get addresses of second controller */
- irqctrler = irqctrler->next;
- if (irqctrler && irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 2; i < 4; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (4 - i) * 0x10);
- irq_cascade = irqctrler->intrs[0].line;
- if (device_is_compatible(irqctrler, "gatwick"))
- pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
- }
- } else {
- /* older powermacs have a GC (grand central) or ohare at
- f3000000, with interrupt control registers at f3000020. */
- addr = (unsigned long) ioremap(0xf3000000, 0x40);
- pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
- }
-
- /* PowerBooks 3400 and 3500 can have a second controller in a second
- ohare chip, on the combo ethernet/modem card */
- if (machine_is_compatible("AAPL,3400/2400")
- || machine_is_compatible("AAPL,3500"))
- irq_cascade = enable_second_ohare();
-
- /* disable all interrupts in all controllers */
- for (i = 0; i * 32 < max_irqs; ++i)
- out_le32(&pmac_irq_hw[i]->enable, 0);
- /* mark level interrupts */
- for (i = 0; i < max_irqs; i++)
- if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
- irq_desc[i].status = IRQ_LEVEL;
-
- /* get interrupt line of secondary interrupt controller */
- if (irq_cascade >= 0) {
- printk(KERN_INFO "irq: secondary controller on irq %d\n",
- (int)irq_cascade);
- for ( i = max_real_irqs ; i < max_irqs ; i++ )
- irq_desc[i].handler = &gatwick_pic;
- setup_irq(irq_cascade, &gatwick_cascade_action);
- }
- printk("System has %d possible interrupts\n", max_irqs);
- if (max_irqs != max_real_irqs)
- printk(KERN_DEBUG "%d interrupts on main controller\n",
- max_real_irqs);
-
-#ifdef CONFIG_XMON
- setup_irq(20, &xmon_action);
-#endif /* CONFIG_XMON */
-}
-
-#ifdef CONFIG_PM
-/*
- * These procedures are used in implementing sleep on the powerbooks.
- * sleep_save_intrs() saves the states of all interrupt enables
- * and disables all interrupts except for the nominated one.
- * sleep_restore_intrs() restores the states of all interrupt enables.
- */
-unsigned long sleep_save_mask[2];
-
-/* This used to be passed by the PMU driver but that link got
- * broken with the new driver model. We use this tweak for now...
- */
-static int pmacpic_find_viaint(void)
-{
- int viaint = -1;
-
-#ifdef CONFIG_ADB_PMU
- struct device_node *np;
-
- if (pmu_get_model() != PMU_OHARE_BASED)
- goto not_found;
- np = of_find_node_by_name(NULL, "via-pmu");
- if (np == NULL)
- goto not_found;
- viaint = np->intrs[0].line;
-#endif /* CONFIG_ADB_PMU */
-
-not_found:
- return viaint;
-}
-
-static int pmacpic_suspend(struct sys_device *sysdev, pm_message_t state)
-{
- int viaint = pmacpic_find_viaint();
-
- sleep_save_mask[0] = ppc_cached_irq_mask[0];
- sleep_save_mask[1] = ppc_cached_irq_mask[1];
- ppc_cached_irq_mask[0] = 0;
- ppc_cached_irq_mask[1] = 0;
- if (viaint > 0)
- set_bit(viaint, ppc_cached_irq_mask);
- out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
- if (max_real_irqs > 32)
- out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
- (void)in_le32(&pmac_irq_hw[0]->event);
- /* make sure mask gets to controller before we return to caller */
- mb();
- (void)in_le32(&pmac_irq_hw[0]->enable);
-
- return 0;
-}
-
-static int pmacpic_resume(struct sys_device *sysdev)
-{
- int i;
-
- out_le32(&pmac_irq_hw[0]->enable, 0);
- if (max_real_irqs > 32)
- out_le32(&pmac_irq_hw[1]->enable, 0);
- mb();
- for (i = 0; i < max_real_irqs; ++i)
- if (test_bit(i, sleep_save_mask))
- pmac_unmask_irq(i);
-
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
-static struct sysdev_class pmacpic_sysclass = {
- set_kset_name("pmac_pic"),
-};
-
-static struct sys_device device_pmacpic = {
- .id = 0,
- .cls = &pmacpic_sysclass,
-};
-
-static struct sysdev_driver driver_pmacpic = {
-#ifdef CONFIG_PM
- .suspend = &pmacpic_suspend,
- .resume = &pmacpic_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init init_pmacpic_sysfs(void)
-{
- if (max_irqs == 0)
- return -ENODEV;
-
- printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
- sysdev_class_register(&pmacpic_sysclass);
- sysdev_register(&device_pmacpic);
- sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic);
- return 0;
-}
-
-subsys_initcall(init_pmacpic_sysfs);
-
diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h
deleted file mode 100644
index 664103dfeef9..000000000000
--- a/arch/ppc/platforms/pmac_pic.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __PPC_PLATFORMS_PMAC_PIC_H
-#define __PPC_PLATFORMS_PMAC_PIC_H
-
-#include <linux/irq.h>
-
-extern struct hw_interrupt_type pmac_pic;
-
-void pmac_pic_init(void);
-int pmac_get_irq(struct pt_regs *regs);
-
-#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
deleted file mode 100644
index 55d2beffe560..000000000000
--- a/arch/ppc/platforms/pmac_setup.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * arch/ppc/platforms/setup.c
- *
- * PowerPC version
- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- * Adapted for Power Macintosh by Paul Mackerras
- * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * Derived from "arch/alpha/kernel/setup.c"
- * Copyright (C) 1995 Linus Torvalds
- *
- * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.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.
- *
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/vt_kern.h>
-#include <linux/console.h>
-#include <linux/ide.h>
-#include <linux/pci.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/bitops.h>
-#include <linux/suspend.h>
-
-#include <asm/reg.h>
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/ohare.h>
-#include <asm/mediabay.h>
-#include <asm/machdep.h>
-#include <asm/dma.h>
-#include <asm/bootx.h>
-#include <asm/cputable.h>
-#include <asm/btext.h>
-#include <asm/pmac_feature.h>
-#include <asm/time.h>
-#include <asm/of_device.h>
-#include <asm/mmu_context.h>
-
-#include "pmac_pic.h"
-#include "mem_pieces.h"
-
-#undef SHOW_GATWICK_IRQS
-
-extern long pmac_time_init(void);
-extern unsigned long pmac_get_rtc_time(void);
-extern int pmac_set_rtc_time(unsigned long nowtime);
-extern void pmac_read_rtc_time(void);
-extern void pmac_calibrate_decr(void);
-extern void pmac_pcibios_fixup(void);
-extern void pmac_find_bridges(void);
-extern unsigned long pmac_ide_get_base(int index);
-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
- unsigned long data_port, unsigned long ctrl_port, int *irq);
-
-extern void pmac_nvram_update(void);
-extern unsigned char pmac_nvram_read_byte(int addr);
-extern void pmac_nvram_write_byte(int addr, unsigned char val);
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
-extern void pmac_pcibios_after_init(void);
-extern int of_show_percpuinfo(struct seq_file *m, int i);
-
-struct device_node *memory_node;
-
-unsigned char drive_info;
-
-int ppc_override_l2cr = 0;
-int ppc_override_l2cr_value;
-int has_l2cache = 0;
-
-static int current_root_goodness = -1;
-
-extern int pmac_newworld;
-
-#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */
-
-extern void zs_kgdb_hook(int tty_num);
-static void ohare_init(void);
-#ifdef CONFIG_BOOTX_TEXT
-static void pmac_progress(char *s, unsigned short hex);
-#endif
-
-sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t psurge_smp_ops;
-extern struct smp_ops_t core99_smp_ops;
-#endif /* CONFIG_SMP */
-
-static int
-pmac_show_cpuinfo(struct seq_file *m)
-{
- struct device_node *np;
- char *pp;
- int plen;
- int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
- NULL, PMAC_MB_INFO_MODEL, 0);
- unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
- NULL, PMAC_MB_INFO_FLAGS, 0);
- char* mbname;
-
- if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
- mbname = "Unknown";
-
- /* find motherboard type */
- seq_printf(m, "machine\t\t: ");
- np = find_devices("device-tree");
- if (np != NULL) {
- pp = (char *) get_property(np, "model", NULL);
- if (pp != NULL)
- seq_printf(m, "%s\n", pp);
- else
- seq_printf(m, "PowerMac\n");
- pp = (char *) get_property(np, "compatible", &plen);
- if (pp != NULL) {
- seq_printf(m, "motherboard\t:");
- while (plen > 0) {
- int l = strlen(pp) + 1;
- seq_printf(m, " %s", pp);
- plen -= l;
- pp += l;
- }
- seq_printf(m, "\n");
- }
- } else
- seq_printf(m, "PowerMac\n");
-
- /* print parsed model */
- seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
- seq_printf(m, "pmac flags\t: %08x\n", mbflags);
-
- /* find l2 cache info */
- np = find_devices("l2-cache");
- if (np == 0)
- np = find_type_devices("cache");
- if (np != 0) {
- unsigned int *ic = (unsigned int *)
- get_property(np, "i-cache-size", NULL);
- unsigned int *dc = (unsigned int *)
- get_property(np, "d-cache-size", NULL);
- seq_printf(m, "L2 cache\t:");
- has_l2cache = 1;
- if (get_property(np, "cache-unified", NULL) != 0 && dc) {
- seq_printf(m, " %dK unified", *dc / 1024);
- } else {
- if (ic)
- seq_printf(m, " %dK instruction", *ic / 1024);
- if (dc)
- seq_printf(m, "%s %dK data",
- (ic? " +": ""), *dc / 1024);
- }
- pp = get_property(np, "ram-type", NULL);
- if (pp)
- seq_printf(m, " %s", pp);
- seq_printf(m, "\n");
- }
-
- /* find ram info */
- np = find_devices("memory");
- if (np != 0) {
- int n;
- struct reg_property *reg = (struct reg_property *)
- get_property(np, "reg", &n);
-
- if (reg != 0) {
- unsigned long total = 0;
-
- for (n /= sizeof(struct reg_property); n > 0; --n)
- total += (reg++)->size;
- seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
- }
- }
-
- /* Checks "l2cr-value" property in the registry */
- np = find_devices("cpus");
- if (np == 0)
- np = find_type_devices("cpu");
- if (np != 0) {
- unsigned int *l2cr = (unsigned int *)
- get_property(np, "l2cr-value", NULL);
- if (l2cr != 0) {
- seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
- }
- }
-
- /* Indicate newworld/oldworld */
- seq_printf(m, "pmac-generation\t: %s\n",
- pmac_newworld ? "NewWorld" : "OldWorld");
-
-
- return 0;
-}
-
-static int
-pmac_show_percpuinfo(struct seq_file *m, int i)
-{
-#ifdef CONFIG_CPU_FREQ_PMAC
- extern unsigned int pmac_get_one_cpufreq(int i);
- unsigned int freq = pmac_get_one_cpufreq(i);
- if (freq != 0) {
- seq_printf(m, "clock\t\t: %dMHz\n", freq/1000);
- return 0;
- }
-#endif /* CONFIG_CPU_FREQ_PMAC */
- return of_show_percpuinfo(m, i);
-}
-
-static volatile u32 *sysctrl_regs;
-
-void __init
-pmac_setup_arch(void)
-{
- struct device_node *cpu;
- int *fp;
- unsigned long pvr;
-
- pvr = PVR_VER(mfspr(SPRN_PVR));
-
- /* Set loops_per_jiffy to a half-way reasonable value,
- for use until calibrate_delay gets called. */
- cpu = find_type_devices("cpu");
- if (cpu != 0) {
- fp = (int *) get_property(cpu, "clock-frequency", NULL);
- if (fp != 0) {
- if (pvr == 4 || pvr >= 8)
- /* 604, G3, G4 etc. */
- loops_per_jiffy = *fp / HZ;
- else
- /* 601, 603, etc. */
- loops_per_jiffy = *fp / (2*HZ);
- } else
- loops_per_jiffy = 50000000 / HZ;
- }
-
- /* this area has the CPU identification register
- and some registers used by smp boards */
- sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
- ohare_init();
-
- /* Lookup PCI hosts */
- pmac_find_bridges();
-
- /* Checks "l2cr-value" property in the registry */
- if (cpu_has_feature(CPU_FTR_L2CR)) {
- struct device_node *np = find_devices("cpus");
- if (np == 0)
- np = find_type_devices("cpu");
- if (np != 0) {
- unsigned int *l2cr = (unsigned int *)
- get_property(np, "l2cr-value", NULL);
- if (l2cr != 0) {
- ppc_override_l2cr = 1;
- ppc_override_l2cr_value = *l2cr;
- _set_L2CR(0);
- _set_L2CR(ppc_override_l2cr_value);
- }
- }
- }
-
- if (ppc_override_l2cr)
- printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
- ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
- ? "enabled" : "disabled");
-
-#ifdef CONFIG_KGDB
- zs_kgdb_hook(0);
-#endif
-
-#ifdef CONFIG_ADB_CUDA
- find_via_cuda();
-#else
- if (find_devices("via-cuda")) {
- printk("WARNING ! Your machine is Cuda based but your kernel\n");
- printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n");
- }
-#endif
-#ifdef CONFIG_ADB_PMU
- find_via_pmu();
-#else
- if (find_devices("via-pmu")) {
- printk("WARNING ! Your machine is PMU based but your kernel\n");
- printk(" wasn't compiled with CONFIG_ADB_PMU option !\n");
- }
-#endif
-#ifdef CONFIG_NVRAM
- pmac_nvram_init();
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = DEFAULT_ROOT_DEVICE;
-
-#ifdef CONFIG_SMP
- /* Check for Core99 */
- if (find_devices("uni-n") || find_devices("u3"))
- smp_ops = &core99_smp_ops;
- else
- smp_ops = &psurge_smp_ops;
-#endif /* CONFIG_SMP */
-
- pci_create_OF_bus_map();
-}
-
-static void __init ohare_init(void)
-{
- /*
- * Turn on the L2 cache.
- * We assume that we have a PSX memory controller iff
- * we have an ohare I/O controller.
- */
- if (find_devices("ohare") != NULL) {
- if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
- if (sysctrl_regs[4] & 0x10)
- sysctrl_regs[4] |= 0x04000020;
- else
- sysctrl_regs[4] |= 0x04000000;
- if(has_l2cache)
- printk(KERN_INFO "Level 2 cache enabled\n");
- }
- }
-}
-
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern dev_t boot_dev;
-
-#ifdef CONFIG_SCSI
-void __init
-note_scsi_host(struct device_node *node, void *host)
-{
- int l;
- char *p;
-
- l = strlen(node->full_name);
- if (bootpath != NULL && bootdevice != NULL
- && strncmp(node->full_name, bootdevice, l) == 0
- && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
- boot_host = host;
- /*
- * There's a bug in OF 1.0.5. (Why am I not surprised.)
- * If you pass a path like scsi/sd@1:0 to canon, it returns
- * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
- * That is, the scsi target number doesn't get preserved.
- * So we pick the target number out of bootpath and use that.
- */
- p = strstr(bootpath, "/sd@");
- if (p != NULL) {
- p += 4;
- boot_target = simple_strtoul(p, NULL, 10);
- p = strchr(p, ':');
- if (p != NULL)
- boot_part = simple_strtoul(p + 1, NULL, 10);
- }
- }
-}
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init
-find_ide_boot(void)
-{
- char *p;
- int n;
- dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
- if (bootdevice == NULL)
- return 0;
- p = strrchr(bootdevice, '/');
- if (p == NULL)
- return 0;
- n = p - bootdevice;
-
- return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-static void __init
-find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
- boot_dev = find_ide_boot();
-#endif
-}
-
-static int initializing = 1;
-/* TODO: Merge the suspend-to-ram with the common code !!!
- * currently, this is a stub implementation for suspend-to-disk
- * only
- */
-
-#ifdef CONFIG_SOFTWARE_SUSPEND
-
-static int pmac_pm_prepare(suspend_state_t state)
-{
- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
- return 0;
-}
-
-static int pmac_pm_enter(suspend_state_t state)
-{
- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
- /* Giveup the lazy FPU & vec so we don't have to back them
- * up from the low level code
- */
- enable_kernel_fp();
-
-#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
- enable_kernel_altivec();
-#endif /* CONFIG_ALTIVEC */
-
- return 0;
-}
-
-static int pmac_pm_finish(suspend_state_t state)
-{
- printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
-
- /* Restore userland MMU context */
- set_context(current->active_mm->context, current->active_mm->pgd);
-
- return 0;
-}
-
-static struct pm_ops pmac_pm_ops = {
- .pm_disk_mode = PM_DISK_SHUTDOWN,
- .prepare = pmac_pm_prepare,
- .enter = pmac_pm_enter,
- .finish = pmac_pm_finish,
-};
-
-#endif /* CONFIG_SOFTWARE_SUSPEND */
-
-static int pmac_late_init(void)
-{
- initializing = 0;
-#ifdef CONFIG_SOFTWARE_SUSPEND
- pm_set_ops(&pmac_pm_ops);
-#endif /* CONFIG_SOFTWARE_SUSPEND */
- return 0;
-}
-
-late_initcall(pmac_late_init);
-
-/* can't be __init - can be called whenever a disk is first accessed */
-void
-note_bootable_part(dev_t dev, int part, int goodness)
-{
- static int found_boot = 0;
- char *p;
-
- if (!initializing)
- return;
- if ((goodness <= current_root_goodness) &&
- ROOT_DEV != DEFAULT_ROOT_DEVICE)
- return;
- p = strstr(saved_command_line, "root=");
- if (p != NULL && (p == saved_command_line || p[-1] == ' '))
- return;
-
- if (!found_boot) {
- find_boot_device();
- found_boot = 1;
- }
- if (!boot_dev || dev == boot_dev) {
- ROOT_DEV = dev + part;
- boot_dev = 0;
- current_root_goodness = goodness;
- }
-}
-
-static void
-pmac_restart(char *cmd)
-{
-#ifdef CONFIG_ADB_CUDA
- struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_RESET_SYSTEM);
- for (;;)
- cuda_poll();
- break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- pmu_restart();
- break;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
-}
-
-static void
-pmac_power_off(void)
-{
-#ifdef CONFIG_ADB_CUDA
- struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_POWERDOWN);
- for (;;)
- cuda_poll();
- break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- pmu_shutdown();
- break;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
-}
-
-static void
-pmac_halt(void)
-{
- pmac_power_off();
-}
-
-/*
- * Read in a property describing some pieces of memory.
- */
-
-static int __init
-get_mem_prop(char *name, struct mem_pieces *mp)
-{
- struct reg_property *rp;
- int i, s;
- unsigned int *ip;
- int nac = prom_n_addr_cells(memory_node);
- int nsc = prom_n_size_cells(memory_node);
-
- ip = (unsigned int *) get_property(memory_node, name, &s);
- if (ip == NULL) {
- printk(KERN_ERR "error: couldn't get %s property on /memory\n",
- name);
- return 0;
- }
- s /= (nsc + nac) * 4;
- rp = mp->regions;
- for (i = 0; i < s; ++i, ip += nac+nsc) {
- if (nac >= 2 && ip[nac-2] != 0)
- continue;
- rp->address = ip[nac-1];
- if (nsc >= 2 && ip[nac+nsc-2] != 0)
- rp->size = ~0U;
- else
- rp->size = ip[nac+nsc-1];
- ++rp;
- }
- mp->n_regions = rp - mp->regions;
-
- /* Make sure the pieces are sorted. */
- mem_pieces_sort(mp);
- mem_pieces_coalesce(mp);
- return 1;
-}
-
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long __init
-pmac_find_end_of_memory(void)
-{
- unsigned long a, total;
- struct mem_pieces phys_mem;
-
- /*
- * Find out where physical memory is, and check that it
- * starts at 0 and is contiguous. It seems that RAM is
- * always physically contiguous on Power Macintoshes.
- *
- * Supporting discontiguous physical memory isn't hard,
- * it just makes the virtual <-> physical mapping functions
- * more complicated (or else you end up wasting space
- * in mem_map).
- */
- memory_node = find_devices("memory");
- if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
- || phys_mem.n_regions == 0)
- panic("No RAM??");
- a = phys_mem.regions[0].address;
- if (a != 0)
- panic("RAM doesn't start at physical address 0");
- total = phys_mem.regions[0].size;
-
- if (phys_mem.n_regions > 1) {
- printk("RAM starting at 0x%x is not contiguous\n",
- phys_mem.regions[1].address);
- printk("Using RAM from 0 to 0x%lx\n", total-1);
- }
-
- return total;
-}
-
-void __init
-pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- /* isa_io_base gets set in pmac_find_bridges */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-
- ppc_md.setup_arch = pmac_setup_arch;
- ppc_md.show_cpuinfo = pmac_show_cpuinfo;
- ppc_md.show_percpuinfo = pmac_show_percpuinfo;
- ppc_md.init_IRQ = pmac_pic_init;
- ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */
-
- ppc_md.pcibios_fixup = pmac_pcibios_fixup;
- ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
- ppc_md.pcibios_after_init = pmac_pcibios_after_init;
- ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
- ppc_md.restart = pmac_restart;
- ppc_md.power_off = pmac_power_off;
- ppc_md.halt = pmac_halt;
-
- ppc_md.time_init = pmac_time_init;
- ppc_md.set_rtc_time = pmac_set_rtc_time;
- ppc_md.get_rtc_time = pmac_get_rtc_time;
- ppc_md.calibrate_decr = pmac_calibrate_decr;
-
- ppc_md.find_end_of_memory = pmac_find_end_of_memory;
-
- ppc_md.feature_call = pmac_do_feature_call;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
- ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
- ppc_ide_md.default_io_base = pmac_ide_get_base;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
-#ifdef CONFIG_BOOTX_TEXT
- ppc_md.progress = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
- if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-static void __init
-pmac_progress(char *s, unsigned short hex)
-{
- if (boot_text_mapped) {
- btext_drawstring(s);
- btext_drawchar('\n');
- }
-}
-#endif /* CONFIG_BOOTX_TEXT */
-
-static int __init
-pmac_declare_of_platform_devices(void)
-{
- struct device_node *np;
-
- np = find_devices("uni-n");
- if (np) {
- for (np = np->child; np != NULL; np = np->sibling)
- if (strncmp(np->name, "i2c", 3) == 0) {
- of_platform_device_create(np, "uni-n-i2c",
- NULL);
- break;
- }
- }
- np = find_devices("u3");
- if (np) {
- for (np = np->child; np != NULL; np = np->sibling)
- if (strncmp(np->name, "i2c", 3) == 0) {
- of_platform_device_create(np, "u3-i2c",
- NULL);
- break;
- }
- }
-
- np = find_devices("valkyrie");
- if (np)
- of_platform_device_create(np, "valkyrie", NULL);
- np = find_devices("platinum");
- if (np)
- of_platform_device_create(np, "platinum", NULL);
-
- return 0;
-}
-
-device_initcall(pmac_declare_of_platform_devices);
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S
deleted file mode 100644
index 22b113d19b24..000000000000
--- a/arch/ppc/platforms/pmac_sleep.S
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * This file contains sleep low-level functions for PowerBook G3.
- * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
- * and Paul Mackerras (paulus@samba.org).
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/ppc_asm.h>
-#include <asm/cputable.h>
-#include <asm/cache.h>
-#include <asm/thread_info.h>
-#include <asm/asm-offsets.h>
-
-#define MAGIC 0x4c617273 /* 'Lars' */
-
-/*
- * Structure for storing CPU registers on the stack.
- */
-#define SL_SP 0
-#define SL_PC 4
-#define SL_MSR 8
-#define SL_SDR1 0xc
-#define SL_SPRG0 0x10 /* 4 sprg's */
-#define SL_DBAT0 0x20
-#define SL_IBAT0 0x28
-#define SL_DBAT1 0x30
-#define SL_IBAT1 0x38
-#define SL_DBAT2 0x40
-#define SL_IBAT2 0x48
-#define SL_DBAT3 0x50
-#define SL_IBAT3 0x58
-#define SL_TB 0x60
-#define SL_R2 0x68
-#define SL_CR 0x6c
-#define SL_R12 0x70 /* r12 to r31 */
-#define SL_SIZE (SL_R12 + 80)
-
- .section .text
- .align 5
-
-#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC)
-
-/* This gets called by via-pmu.c late during the sleep process.
- * The PMU was already send the sleep command and will shut us down
- * soon. We need to save all that is needed and setup the wakeup
- * vector that will be called by the ROM on wakeup
- */
-_GLOBAL(low_sleep_handler)
-#ifndef CONFIG_6xx
- blr
-#else
- mflr r0
- stw r0,4(r1)
- stwu r1,-SL_SIZE(r1)
- mfcr r0
- stw r0,SL_CR(r1)
- stw r2,SL_R2(r1)
- stmw r12,SL_R12(r1)
-
- /* Save MSR & SDR1 */
- mfmsr r4
- stw r4,SL_MSR(r1)
- mfsdr1 r4
- stw r4,SL_SDR1(r1)
-
- /* Get a stable timebase and save it */
-1: mftbu r4
- stw r4,SL_TB(r1)
- mftb r5
- stw r5,SL_TB+4(r1)
- mftbu r3
- cmpw r3,r4
- bne 1b
-
- /* Save SPRGs */
- mfsprg r4,0
- stw r4,SL_SPRG0(r1)
- mfsprg r4,1
- stw r4,SL_SPRG0+4(r1)
- mfsprg r4,2
- stw r4,SL_SPRG0+8(r1)
- mfsprg r4,3
- stw r4,SL_SPRG0+12(r1)
-
- /* Save BATs */
- mfdbatu r4,0
- stw r4,SL_DBAT0(r1)
- mfdbatl r4,0
- stw r4,SL_DBAT0+4(r1)
- mfdbatu r4,1
- stw r4,SL_DBAT1(r1)
- mfdbatl r4,1
- stw r4,SL_DBAT1+4(r1)
- mfdbatu r4,2
- stw r4,SL_DBAT2(r1)
- mfdbatl r4,2
- stw r4,SL_DBAT2+4(r1)
- mfdbatu r4,3
- stw r4,SL_DBAT3(r1)
- mfdbatl r4,3
- stw r4,SL_DBAT3+4(r1)
- mfibatu r4,0
- stw r4,SL_IBAT0(r1)
- mfibatl r4,0
- stw r4,SL_IBAT0+4(r1)
- mfibatu r4,1
- stw r4,SL_IBAT1(r1)
- mfibatl r4,1
- stw r4,SL_IBAT1+4(r1)
- mfibatu r4,2
- stw r4,SL_IBAT2(r1)
- mfibatl r4,2
- stw r4,SL_IBAT2+4(r1)
- mfibatu r4,3
- stw r4,SL_IBAT3(r1)
- mfibatl r4,3
- stw r4,SL_IBAT3+4(r1)
-
- /* Backup various CPU config stuffs */
- bl __save_cpu_setup
-
- /* The ROM can wake us up via 2 different vectors:
- * - On wallstreet & lombard, we must write a magic
- * value 'Lars' at address 4 and a pointer to a
- * memory location containing the PC to resume from
- * at address 0.
- * - On Core99, we must store the wakeup vector at
- * address 0x80 and eventually it's parameters
- * at address 0x84. I've have some trouble with those
- * parameters however and I no longer use them.
- */
- lis r5,grackle_wake_up@ha
- addi r5,r5,grackle_wake_up@l
- tophys(r5,r5)
- stw r5,SL_PC(r1)
- lis r4,KERNELBASE@h
- tophys(r5,r1)
- addi r5,r5,SL_PC
- lis r6,MAGIC@ha
- addi r6,r6,MAGIC@l
- stw r5,0(r4)
- stw r6,4(r4)
- /* Setup stuffs at 0x80-0x84 for Core99 */
- lis r3,core99_wake_up@ha
- addi r3,r3,core99_wake_up@l
- tophys(r3,r3)
- stw r3,0x80(r4)
- stw r5,0x84(r4)
- /* Store a pointer to our backup storage into
- * a kernel global
- */
- lis r3,sleep_storage@ha
- 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
-
- /* Turn off data relocation. */
- mfmsr r3 /* Save MSR in r7 */
- rlwinm r3,r3,0,28,26 /* Turn off DR bit */
- sync
- mtmsr r3
- isync
-
-BEGIN_FTR_SECTION
- /* Flush any pending L2 data prefetches to work around HW bug */
- sync
- lis r3,0xfff0
- lwz r0,0(r3) /* perform cache-inhibited load to ROM */
- sync /* (caches are disabled at this point) */
-END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
-
-/*
- * Set the HID0 and MSR for sleep.
- */
- mfspr r2,SPRN_HID0
- rlwinm r2,r2,0,10,7 /* clear doze, nap */
- oris r2,r2,HID0_SLEEP@h
- sync
- isync
- mtspr SPRN_HID0,r2
- sync
-
-/* This loop puts us back to sleep in case we have a spurrious
- * wakeup so that the host bridge properly stays asleep. The
- * CPU will be turned off, either after a known time (about 1
- * second) on wallstreet & lombard, or as soon as the CPU enters
- * SLEEP mode on core99
- */
- mfmsr r2
- oris r2,r2,MSR_POW@h
-1: sync
- mtmsr r2
- isync
- b 1b
-
-/*
- * Here is the resume code.
- */
-
-
-/*
- * Core99 machines resume here
- * r4 has the physical address of SL_PC(sp) (unused)
- */
-_GLOBAL(core99_wake_up)
- /* Make sure HID0 no longer contains any sleep bit and that data cache
- * is disabled
- */
- mfspr r3,SPRN_HID0
- rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */
- rlwinm 3,r3,0,18,15 /* clear DCE, ICE */
- mtspr SPRN_HID0,r3
- sync
- isync
-
- /* sanitize MSR */
- mfmsr r3
- ori r3,r3,MSR_EE|MSR_IP
- xori r3,r3,MSR_EE|MSR_IP
- sync
- isync
- mtmsr r3
- sync
- isync
-
- /* Recover sleep storage */
- lis r3,sleep_storage@ha
- addi r3,r3,sleep_storage@l
- tophys(r3,r3)
- lwz r1,0(r3)
-
- /* Pass thru to older resume code ... */
-/*
- * Here is the resume code for older machines.
- * r1 has the physical address of SL_PC(sp).
- */
-
-grackle_wake_up:
-
- /* Restore the kernel's segment registers before
- * we do any r1 memory access as we are not sure they
- * are in a sane state above the first 256Mb region
- */
- li r0,16 /* load up segment register values */
- mtctr r0 /* for context 0 */
- lis r3,0x2000 /* Ku = 1, VSID = 0 */
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,0x111 /* increment VSID */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
- sync
- isync
-
- subi r1,r1,SL_PC
-
- /* Restore various CPU config stuffs */
- bl __restore_cpu_setup
-
- /* Make sure all FPRs have been initialized */
- bl reloc_offset
- bl __init_fpu_registers
-
- /* Invalidate & enable L1 cache, we don't care about
- * whatever the ROM may have tried to write to memory
- */
- bl __inval_enable_L1
-
- /* Restore the BATs, and SDR1. Then we can turn on the MMU. */
- lwz r4,SL_SDR1(r1)
- mtsdr1 r4
- lwz r4,SL_SPRG0(r1)
- mtsprg 0,r4
- lwz r4,SL_SPRG0+4(r1)
- mtsprg 1,r4
- lwz r4,SL_SPRG0+8(r1)
- mtsprg 2,r4
- lwz r4,SL_SPRG0+12(r1)
- mtsprg 3,r4
-
- lwz r4,SL_DBAT0(r1)
- mtdbatu 0,r4
- lwz r4,SL_DBAT0+4(r1)
- mtdbatl 0,r4
- lwz r4,SL_DBAT1(r1)
- mtdbatu 1,r4
- lwz r4,SL_DBAT1+4(r1)
- mtdbatl 1,r4
- lwz r4,SL_DBAT2(r1)
- mtdbatu 2,r4
- lwz r4,SL_DBAT2+4(r1)
- mtdbatl 2,r4
- lwz r4,SL_DBAT3(r1)
- mtdbatu 3,r4
- lwz r4,SL_DBAT3+4(r1)
- mtdbatl 3,r4
- lwz r4,SL_IBAT0(r1)
- mtibatu 0,r4
- lwz r4,SL_IBAT0+4(r1)
- mtibatl 0,r4
- lwz r4,SL_IBAT1(r1)
- mtibatu 1,r4
- lwz r4,SL_IBAT1+4(r1)
- mtibatl 1,r4
- lwz r4,SL_IBAT2(r1)
- mtibatu 2,r4
- lwz r4,SL_IBAT2+4(r1)
- mtibatl 2,r4
- lwz r4,SL_IBAT3(r1)
- mtibatu 3,r4
- lwz r4,SL_IBAT3+4(r1)
- mtibatl 3,r4
-
-BEGIN_FTR_SECTION
- li r4,0
- mtspr SPRN_DBAT4U,r4
- mtspr SPRN_DBAT4L,r4
- mtspr SPRN_DBAT5U,r4
- mtspr SPRN_DBAT5L,r4
- mtspr SPRN_DBAT6U,r4
- mtspr SPRN_DBAT6L,r4
- mtspr SPRN_DBAT7U,r4
- mtspr SPRN_DBAT7L,r4
- mtspr SPRN_IBAT4U,r4
- mtspr SPRN_IBAT4L,r4
- mtspr SPRN_IBAT5U,r4
- mtspr SPRN_IBAT5L,r4
- mtspr SPRN_IBAT6U,r4
- mtspr SPRN_IBAT6L,r4
- mtspr SPRN_IBAT7U,r4
- mtspr SPRN_IBAT7L,r4
-END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
-
- /* Flush all TLBs */
- lis r4,0x1000
-1: addic. r4,r4,-0x1000
- tlbie r4
- blt 1b
- sync
-
- /* restore the MSR and turn on the MMU */
- lwz r3,SL_MSR(r1)
- bl turn_on_mmu
-
- /* get back the stack pointer */
- tovirt(r1,r1)
-
- /* Restore TB */
- li r3,0
- mttbl r3
- lwz r3,SL_TB(r1)
- lwz r4,SL_TB+4(r1)
- mttbu r3
- mttbl r4
-
- /* Restore the callee-saved registers and return */
- lwz r0,SL_CR(r1)
- mtcr r0
- lwz r2,SL_R2(r1)
- lmw r12,SL_R12(r1)
- addi r1,r1,SL_SIZE
- lwz r0,4(r1)
- mtlr r0
- blr
-
-turn_on_mmu:
- mflr r4
- tovirt(r4,r4)
- mtsrr0 r4
- mtsrr1 r3
- sync
- isync
- rfi
-
-#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
-
- .section .data
- .balign L1_CACHE_BYTES
-sleep_storage:
- .long 0
- .balign L1_CACHE_BYTES, 0
-
-#endif /* CONFIG_6xx */
- .section .text
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
deleted file mode 100644
index 26ff26238f03..000000000000
--- a/arch/ppc/platforms/pmac_smp.c
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * SMP support for power macintosh.
- *
- * We support both the old "powersurge" SMP architecture
- * and the current Core99 (G4 PowerMac) machines.
- *
- * Note that we don't support the very first rev. of
- * Apple/DayStar 2 CPUs board, the one with the funky
- * watchdog. Hopefully, none of these should be there except
- * maybe internally to Apple. I should probably still add some
- * code to detect this card though and disable SMP. --BenH.
- *
- * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
- * and Ben Herrenschmidt <benh@kernel.crashing.org>.
- *
- * Support for DayStar quad CPU cards
- * Copyright (C) XLR8, Inc. 1994-2000
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/hardirq.h>
-#include <linux/cpu.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/cacheflush.h>
-#include <asm/keylargo.h>
-
-/*
- * Powersurge (old powermac SMP) support.
- */
-
-extern void __secondary_start_pmac_0(void);
-
-/* Addresses for powersurge registers */
-#define HAMMERHEAD_BASE 0xf8000000
-#define HHEAD_CONFIG 0x90
-#define HHEAD_SEC_INTR 0xc0
-
-/* register for interrupting the primary processor on the powersurge */
-/* N.B. this is actually the ethernet ROM! */
-#define PSURGE_PRI_INTR 0xf3019000
-
-/* register for storing the start address for the secondary processor */
-/* N.B. this is the PCI config space address register for the 1st bridge */
-#define PSURGE_START 0xf2800000
-
-/* Daystar/XLR8 4-CPU card */
-#define PSURGE_QUAD_REG_ADDR 0xf8800000
-
-#define PSURGE_QUAD_IRQ_SET 0
-#define PSURGE_QUAD_IRQ_CLR 1
-#define PSURGE_QUAD_IRQ_PRIMARY 2
-#define PSURGE_QUAD_CKSTOP_CTL 3
-#define PSURGE_QUAD_PRIMARY_ARB 4
-#define PSURGE_QUAD_BOARD_ID 6
-#define PSURGE_QUAD_WHICH_CPU 7
-#define PSURGE_QUAD_CKSTOP_RDBK 8
-#define PSURGE_QUAD_RESET_CTL 11
-
-#define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v)))
-#define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f)
-#define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
-#define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
-
-/* virtual addresses for the above */
-static volatile u8 __iomem *hhead_base;
-static volatile u8 __iomem *quad_base;
-static volatile u32 __iomem *psurge_pri_intr;
-static volatile u8 __iomem *psurge_sec_intr;
-static volatile u32 __iomem *psurge_start;
-
-/* values for psurge_type */
-#define PSURGE_NONE -1
-#define PSURGE_DUAL 0
-#define PSURGE_QUAD_OKEE 1
-#define PSURGE_QUAD_COTTON 2
-#define PSURGE_QUAD_ICEGRASS 3
-
-/* what sort of powersurge board we have */
-static int psurge_type = PSURGE_NONE;
-
-/* L2 and L3 cache settings to pass from CPU0 to CPU1 */
-volatile static long int core99_l2_cache;
-volatile static long int core99_l3_cache;
-
-/* Timebase freeze GPIO */
-static unsigned int core99_tb_gpio;
-
-/* Sync flag for HW tb sync */
-static volatile int sec_tb_reset = 0;
-static unsigned int pri_tb_hi, pri_tb_lo;
-static unsigned int pri_tb_stamp;
-
-static void __devinit core99_init_caches(int cpu)
-{
- if (!cpu_has_feature(CPU_FTR_L2CR))
- return;
-
- if (cpu == 0) {
- core99_l2_cache = _get_L2CR();
- printk("CPU0: L2CR is %lx\n", core99_l2_cache);
- } else {
- printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
- _set_L2CR(0);
- _set_L2CR(core99_l2_cache);
- printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
- }
-
- if (!cpu_has_feature(CPU_FTR_L3CR))
- return;
-
- if (cpu == 0){
- core99_l3_cache = _get_L3CR();
- printk("CPU0: L3CR is %lx\n", core99_l3_cache);
- } else {
- printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
- _set_L3CR(0);
- _set_L3CR(core99_l3_cache);
- printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
- }
-}
-
-/*
- * Set and clear IPIs for powersurge.
- */
-static inline void psurge_set_ipi(int cpu)
-{
- if (psurge_type == PSURGE_NONE)
- return;
- if (cpu == 0)
- in_be32(psurge_pri_intr);
- else if (psurge_type == PSURGE_DUAL)
- out_8(psurge_sec_intr, 0);
- else
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
-}
-
-static inline void psurge_clr_ipi(int cpu)
-{
- if (cpu > 0) {
- switch(psurge_type) {
- case PSURGE_DUAL:
- out_8(psurge_sec_intr, ~0);
- case PSURGE_NONE:
- break;
- default:
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
- }
- }
-}
-
-/*
- * On powersurge (old SMP powermac architecture) we don't have
- * separate IPIs for separate messages like openpic does. Instead
- * we have a bitmap for each processor, where a 1 bit means that
- * the corresponding message is pending for that processor.
- * Ideally each cpu's entry would be in a different cache line.
- * -- paulus.
- */
-static unsigned long psurge_smp_message[NR_CPUS];
-
-void psurge_smp_message_recv(struct pt_regs *regs)
-{
- int cpu = smp_processor_id();
- int msg;
-
- /* clear interrupt */
- psurge_clr_ipi(cpu);
-
- if (num_online_cpus() < 2)
- return;
-
- /* make sure there is a message there */
- for (msg = 0; msg < 4; msg++)
- if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
- smp_message_recv(msg, regs);
-}
-
-irqreturn_t psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
-{
- psurge_smp_message_recv(regs);
- return IRQ_HANDLED;
-}
-
-static void smp_psurge_message_pass(int target, int msg)
-{
- int i;
-
- if (num_online_cpus() < 2)
- return;
-
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i))
- continue;
- if (target == MSG_ALL
- || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
- || target == i) {
- set_bit(msg, &psurge_smp_message[i]);
- psurge_set_ipi(i);
- }
- }
-}
-
-/*
- * Determine a quad card presence. We read the board ID register, we
- * force the data bus to change to something else, and we read it again.
- * It it's stable, then the register probably exist (ugh !)
- */
-static int __init psurge_quad_probe(void)
-{
- int type;
- unsigned int i;
-
- type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
- if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
- || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
- return PSURGE_DUAL;
-
- /* looks OK, try a slightly more rigorous test */
- /* bogus is not necessarily cacheline-aligned,
- though I don't suppose that really matters. -- paulus */
- for (i = 0; i < 100; i++) {
- volatile u32 bogus[8];
- bogus[(0+i)%8] = 0x00000000;
- bogus[(1+i)%8] = 0x55555555;
- bogus[(2+i)%8] = 0xFFFFFFFF;
- bogus[(3+i)%8] = 0xAAAAAAAA;
- bogus[(4+i)%8] = 0x33333333;
- bogus[(5+i)%8] = 0xCCCCCCCC;
- bogus[(6+i)%8] = 0xCCCCCCCC;
- bogus[(7+i)%8] = 0x33333333;
- wmb();
- asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
- mb();
- if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
- return PSURGE_DUAL;
- }
- return type;
-}
-
-static void __init psurge_quad_init(void)
-{
- int procbits;
-
- if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
- procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
- if (psurge_type == PSURGE_QUAD_ICEGRASS)
- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
- else
- PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
- mdelay(33);
- out_8(psurge_sec_intr, ~0);
- PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
- PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
- if (psurge_type != PSURGE_QUAD_ICEGRASS)
- PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
- PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
- mdelay(33);
- PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
- mdelay(33);
- PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
- mdelay(33);
-}
-
-static int __init smp_psurge_probe(void)
-{
- int i, ncpus;
-
- /* We don't do SMP on the PPC601 -- paulus */
- if (PVR_VER(mfspr(SPRN_PVR)) == 1)
- return 1;
-
- /*
- * The powersurge cpu board can be used in the generation
- * of powermacs that have a socket for an upgradeable cpu card,
- * including the 7500, 8500, 9500, 9600.
- * The device tree doesn't tell you if you have 2 cpus because
- * OF doesn't know anything about the 2nd processor.
- * Instead we look for magic bits in magic registers,
- * in the hammerhead memory controller in the case of the
- * dual-cpu powersurge board. -- paulus.
- */
- if (find_devices("hammerhead") == NULL)
- return 1;
-
- hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
- quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
- psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
-
- psurge_type = psurge_quad_probe();
- if (psurge_type != PSURGE_DUAL) {
- psurge_quad_init();
- /* All released cards using this HW design have 4 CPUs */
- ncpus = 4;
- } else {
- iounmap(quad_base);
- if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
- /* not a dual-cpu card */
- iounmap(hhead_base);
- psurge_type = PSURGE_NONE;
- return 1;
- }
- ncpus = 2;
- }
-
- psurge_start = ioremap(PSURGE_START, 4);
- psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
-
- /* this is not actually strictly necessary -- paulus. */
- for (i = 1; i < ncpus; ++i)
- smp_hw_index[i] = i;
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
-
- return ncpus;
-}
-
-static void __init smp_psurge_kick_cpu(int nr)
-{
- unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
- unsigned long a;
-
- /* may need to flush here if secondary bats aren't setup */
- for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
- asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
- asm volatile("sync");
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
-
- out_be32(psurge_start, start);
- mb();
-
- psurge_set_ipi(nr);
- udelay(10);
- psurge_clr_ipi(nr);
-
- if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
-}
-
-/*
- * With the dual-cpu powersurge board, the decrementers and timebases
- * of both cpus are frozen after the secondary cpu is started up,
- * until we give the secondary cpu another interrupt. This routine
- * uses this to get the timebases synchronized.
- * -- paulus.
- */
-static void __init psurge_dual_sync_tb(int cpu_nr)
-{
- int t;
-
- set_dec(tb_ticks_per_jiffy);
- set_tb(0, 0);
- last_jiffy_stamp(cpu_nr) = 0;
-
- if (cpu_nr > 0) {
- mb();
- sec_tb_reset = 1;
- return;
- }
-
- /* wait for the secondary to have reset its TB before proceeding */
- for (t = 10000000; t > 0 && !sec_tb_reset; --t)
- ;
-
- /* now interrupt the secondary, starting both TBs */
- psurge_set_ipi(1);
-
- smp_tb_synchronized = 1;
-}
-
-static struct irqaction psurge_irqaction = {
- .handler = psurge_primary_intr,
- .flags = SA_INTERRUPT,
- .mask = CPU_MASK_NONE,
- .name = "primary IPI",
-};
-
-static void __init smp_psurge_setup_cpu(int cpu_nr)
-{
-
- if (cpu_nr == 0) {
- /* If we failed to start the second CPU, we should still
- * send it an IPI to start the timebase & DEC or we might
- * have them stuck.
- */
- if (num_online_cpus() < 2) {
- if (psurge_type == PSURGE_DUAL)
- psurge_set_ipi(1);
- return;
- }
- /* reset the entry point so if we get another intr we won't
- * try to startup again */
- out_be32(psurge_start, 0x100);
- if (setup_irq(30, &psurge_irqaction))
- printk(KERN_ERR "Couldn't get primary IPI interrupt");
- }
-
- if (psurge_type == PSURGE_DUAL)
- psurge_dual_sync_tb(cpu_nr);
-}
-
-void __init smp_psurge_take_timebase(void)
-{
- /* Dummy implementation */
-}
-
-void __init smp_psurge_give_timebase(void)
-{
- /* Dummy implementation */
-}
-
-static int __init smp_core99_probe(void)
-{
-#ifdef CONFIG_6xx
- extern int powersave_nap;
-#endif
- struct device_node *cpus, *firstcpu;
- int i, ncpus = 0, boot_cpu = -1;
- u32 *tbprop = NULL;
-
- if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
- cpus = firstcpu = find_type_devices("cpu");
- while(cpus != NULL) {
- u32 *regprop = (u32 *)get_property(cpus, "reg", NULL);
- char *stateprop = (char *)get_property(cpus, "state", NULL);
- if (regprop != NULL && stateprop != NULL &&
- !strncmp(stateprop, "running", 7))
- boot_cpu = *regprop;
- ++ncpus;
- cpus = cpus->next;
- }
- if (boot_cpu == -1)
- printk(KERN_WARNING "Couldn't detect boot CPU !\n");
- if (boot_cpu != 0)
- printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu);
-
- if (machine_is_compatible("MacRISC4")) {
- extern struct smp_ops_t core99_smp_ops;
-
- core99_smp_ops.take_timebase = smp_generic_take_timebase;
- core99_smp_ops.give_timebase = smp_generic_give_timebase;
- } else {
- if (firstcpu != NULL)
- tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL);
- if (tbprop)
- core99_tb_gpio = *tbprop;
- else
- core99_tb_gpio = KL_GPIO_TB_ENABLE;
- }
-
- if (ncpus > 1) {
- openpic_request_IPIs();
- for (i = 1; i < ncpus; ++i)
- smp_hw_index[i] = i;
-#ifdef CONFIG_6xx
- powersave_nap = 0;
-#endif
- core99_init_caches(0);
- }
-
- return ncpus;
-}
-
-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 < 0 || nr > 3)
- return;
- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
-
- local_irq_save(flags);
- local_irq_disable();
-
- /* Save reset vector */
- save_vector = *vector;
-
- /* Setup fake reset vector that does
- * b __secondary_start_pmac_0 + nr*8 - KERNELBASE
- */
- new_vector = (unsigned long) __secondary_start_pmac_0 + nr * 8;
- *vector = 0x48000002 + new_vector - KERNELBASE;
-
- /* flush data cache and inval instruction cache */
- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-
- /* Put some life in our friend */
- pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
-
- /* FIXME: We wait a bit for the CPU to take the exception, I should
- * instead wait for the entry code to set something for me. Well,
- * ideally, all that crap will be done in prom.c and the CPU left
- * in a RAM-based wait loop like CHRP.
- */
- mdelay(1);
-
- /* Restore our exception vector */
- *vector = save_vector;
- flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-
- local_irq_restore(flags);
- if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
-}
-
-static void __devinit smp_core99_setup_cpu(int cpu_nr)
-{
- /* Setup L2/L3 */
- if (cpu_nr != 0)
- core99_init_caches(cpu_nr);
-
- /* Setup openpic */
- do_openpic_setup_cpu();
-
- if (cpu_nr == 0) {
-#ifdef CONFIG_POWER4
- extern void g5_phy_disable_cpu1(void);
-
- /* If we didn't start the second CPU, we must take
- * it off the bus
- */
- if (machine_is_compatible("MacRISC4") &&
- num_online_cpus() < 2)
- g5_phy_disable_cpu1();
-#endif /* CONFIG_POWER4 */
- if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
- }
-}
-
-/* not __init, called in sleep/wakeup code */
-void smp_core99_take_timebase(void)
-{
- unsigned long flags;
-
- /* tell the primary we're here */
- sec_tb_reset = 1;
- mb();
-
- /* wait for the primary to set pri_tb_hi/lo */
- while (sec_tb_reset < 2)
- mb();
-
- /* set our stuff the same as the primary */
- local_irq_save(flags);
- set_dec(1);
- set_tb(pri_tb_hi, pri_tb_lo);
- last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
- mb();
-
- /* tell the primary we're done */
- sec_tb_reset = 0;
- mb();
- local_irq_restore(flags);
-}
-
-/* not __init, called in sleep/wakeup code */
-void smp_core99_give_timebase(void)
-{
- unsigned long flags;
- unsigned int t;
-
- /* wait for the secondary to be in take_timebase */
- for (t = 100000; t > 0 && !sec_tb_reset; --t)
- udelay(10);
- if (!sec_tb_reset) {
- printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
- return;
- }
-
- /* freeze the timebase and read it */
- /* disable interrupts so the timebase is disabled for the
- shortest possible time */
- local_irq_save(flags);
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
- pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
- mb();
- pri_tb_hi = get_tbu();
- pri_tb_lo = get_tbl();
- pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
- mb();
-
- /* tell the secondary we're ready */
- sec_tb_reset = 2;
- mb();
-
- /* wait for the secondary to have taken it */
- for (t = 100000; t > 0 && sec_tb_reset; --t)
- udelay(10);
- if (sec_tb_reset)
- printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
- else
- smp_tb_synchronized = 1;
-
- /* Now, restart the timebase by leaving the GPIO to an open collector */
- pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
- pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
- local_irq_restore(flags);
-}
-
-
-/* PowerSurge-style Macs */
-struct smp_ops_t psurge_smp_ops = {
- .message_pass = smp_psurge_message_pass,
- .probe = smp_psurge_probe,
- .kick_cpu = smp_psurge_kick_cpu,
- .setup_cpu = smp_psurge_setup_cpu,
- .give_timebase = smp_psurge_give_timebase,
- .take_timebase = smp_psurge_take_timebase,
-};
-
-/* Core99 Macs (dual G4s) */
-struct smp_ops_t core99_smp_ops = {
- .message_pass = smp_openpic_message_pass,
- .probe = smp_core99_probe,
- .kick_cpu = smp_core99_kick_cpu,
- .setup_cpu = smp_core99_setup_cpu,
- .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/pmac_time.c b/arch/ppc/platforms/pmac_time.c
deleted file mode 100644
index edb9fcc64790..000000000000
--- a/arch/ppc/platforms/pmac_time.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Support for periodic interrupts (100 per second) and for getting
- * the current time from the RTC on Power Macintoshes.
- *
- * We use the decrementer register for our periodic interrupts.
- *
- * Paul Mackerras August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <linux/hardirq.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/nvram.h>
-
-/* Apparently the RTC stores seconds since 1 Jan 1904 */
-#define RTC_OFFSET 2082844800
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS 0x200 /* skip between registers */
-#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
-#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
-#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
-#define ACR (11*RS) /* Auxiliary control register */
-#define IFR (13*RS) /* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE 0xc0 /* Timer 1 mode */
-#define T1MODE_CONT 0x40 /* continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT 0x40 /* Timer 1 interrupt */
-
-extern struct timezone sys_tz;
-
-long __init
-pmac_time_init(void)
-{
-#ifdef CONFIG_NVRAM
- s32 delta = 0;
- int dst;
-
- delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
- delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
- delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
- if (delta & 0x00800000UL)
- delta |= 0xFF000000UL;
- dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
- printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
- dst ? "on" : "off");
- return delta;
-#else
- return 0;
-#endif
-}
-
-unsigned long
-pmac_get_rtc_time(void)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
- struct adb_request req;
- unsigned long now;
-#endif
-
- /* Get the time from the RTC */
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
- return 0;
- while (!req.complete)
- cuda_poll();
- if (req.reply_len != 7)
- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
- req.reply_len);
- now = (req.reply[3] << 24) + (req.reply[4] << 16)
- + (req.reply[5] << 8) + req.reply[6];
- return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
- return 0;
- while (!req.complete)
- pmu_poll();
- if (req.reply_len != 4)
- printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
- req.reply_len);
- now = (req.reply[0] << 24) + (req.reply[1] << 16)
- + (req.reply[2] << 8) + req.reply[3];
- return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_PMU */
- default: ;
- }
- return 0;
-}
-
-int
-pmac_set_rtc_time(unsigned long nowtime)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
- struct adb_request req;
-#endif
-
- nowtime += RTC_OFFSET;
-
- switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
- case SYS_CTRLER_CUDA:
- if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
- return 0;
- while (!req.complete)
- cuda_poll();
- if ((req.reply_len != 3) && (req.reply_len != 7))
- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
- req.reply_len);
- return 1;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
- case SYS_CTRLER_PMU:
- if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
- nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
- return 0;
- while (!req.complete)
- pmu_poll();
- if (req.reply_len != 0)
- printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
- req.reply_len);
- return 1;
-#endif /* CONFIG_ADB_PMU */
- default:
- return 0;
- }
-}
-
-/*
- * Calibrate the decrementer register using VIA timer 1.
- * This is used both on powermacs and CHRP machines.
- */
-int __init
-via_calibrate_decr(void)
-{
- struct device_node *vias;
- volatile unsigned char __iomem *via;
- int count = VIA_TIMER_FREQ_6 / 100;
- unsigned int dstart, dend;
-
- vias = find_devices("via-cuda");
- if (vias == 0)
- vias = find_devices("via-pmu");
- if (vias == 0)
- vias = find_devices("via");
- if (vias == 0 || vias->n_addrs == 0)
- return 0;
- via = ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
- /* set timer 1 for continuous interrupts */
- out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
- /* set the counter to a small value */
- out_8(&via[T1CH], 2);
- /* set the latch to `count' */
- out_8(&via[T1LL], count);
- out_8(&via[T1LH], count >> 8);
- /* wait until it hits 0 */
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dstart = get_dec();
- /* clear the interrupt & wait until it hits 0 again */
- in_8(&via[T1CL]);
- while ((in_8(&via[IFR]) & T1_INT) == 0)
- ;
- dend = get_dec();
-
- tb_ticks_per_jiffy = (dstart - dend) / ((6 * HZ)/100);
- tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
- printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
- tb_ticks_per_jiffy, dstart - dend);
-
- iounmap(via);
-
- return 1;
-}
-
-#ifdef CONFIG_PM
-/*
- * Reset the time after a sleep.
- */
-static int
-time_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- static unsigned long time_diff;
- unsigned long flags;
- unsigned long seq;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- do {
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
- time_diff = xtime.tv_sec - pmac_get_rtc_time();
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
- break;
- case PBOOK_WAKE:
- write_seqlock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = pmac_get_rtc_time() + time_diff;
- xtime.tv_nsec = 0;
- last_rtc_update = xtime.tv_sec;
- write_sequnlock_irqrestore(&xtime_lock, flags);
- break;
- }
- return PBOOK_SLEEP_OK;
-}
-
-static struct pmu_sleep_notifier time_sleep_notifier = {
- time_sleep_notify, SLEEP_LEVEL_MISC,
-};
-#endif /* CONFIG_PM */
-
-/*
- * Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
- */
-void __init
-pmac_calibrate_decr(void)
-{
- struct device_node *cpu;
- unsigned int freq, *fp;
-
-#ifdef CONFIG_PM
- pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PM */
-
- /* We assume MacRISC2 machines have correct device-tree
- * calibration. That's better since the VIA itself seems
- * to be slightly off. --BenH
- */
- if (!machine_is_compatible("MacRISC2") &&
- !machine_is_compatible("MacRISC3") &&
- !machine_is_compatible("MacRISC4"))
- if (via_calibrate_decr())
- return;
-
- /* Special case: QuickSilver G4s seem to have a badly calibrated
- * timebase-frequency in OF, VIA is much better on these. We should
- * probably implement calibration based on the KL timer on these
- * machines anyway... -BenH
- */
- if (machine_is_compatible("PowerMac3,5"))
- if (via_calibrate_decr())
- return;
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- cpu = find_type_devices("cpu");
- if (cpu == 0)
- panic("can't find cpu node in time_init");
- fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
- if (fp == 0)
- panic("can't get cpu timebase frequency");
- freq = *fp;
- printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- freq/1000000, freq%1000000);
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 4415748071dc..d06535802003 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -72,7 +72,6 @@
TODC_ALLOC();
-unsigned char ucSystemType;
unsigned char ucBoardRev;
unsigned char ucBoardRevMaj, ucBoardRevMin;
@@ -954,7 +953,6 @@ prep_calibrate_decr(void)
static void __init
prep_init_IRQ(void)
{
- int i;
unsigned int pci_viddid, pci_did;
if (OpenPIC_Addr != NULL) {
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 5b7f2b80e56e..159dcd92a6d1 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -39,8 +39,6 @@ obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
-obj-$(CONFIG_PPC_PMAC) += open_pic.o
-obj-$(CONFIG_POWER4) += open_pic2.o
obj-$(CONFIG_PPC_CHRP) += open_pic.o
obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
@@ -96,7 +94,7 @@ ifeq ($(CONFIG_85xx),y)
obj-$(CONFIG_PCI) += pci_auto.o
endif
obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
-obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \
+obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \
mpc83xx_sys.o mpc83xx_devices.o
ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += pci_auto.o
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 1cc3abe6fa43..688616de3cde 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -135,6 +135,16 @@ static struct irqaction tbint_irqaction = {
.name = "tbint",
};
+/* per-board overridable init_internal_rtc() function. */
+void __init __attribute__ ((weak))
+init_internal_rtc(void)
+{
+ /* Disable the RTC one second and alarm interrupts. */
+ out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
+ /* Enable the RTC */
+ out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
+}
+
/* The decrementer counts at the system (internal) clock frequency divided by
* sixteen, or external oscillator divided by four. We force the processor
* to use system clock divided by sixteen.
@@ -183,10 +193,7 @@ void __init m8xx_calibrate_decr(void)
out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck, KAPWR_KEY);
out_be32(&((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbk, KAPWR_KEY);
- /* Disable the RTC one second and alarm interrupts. */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) & ~(RTCSC_SIE | RTCSC_ALE));
- /* Enable the RTC */
- out_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc, in_be16(&((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc) | (RTCSC_RTF | RTCSC_RTE));
+ init_internal_rtc();
/* Enabling the decrementer also enables the timebase interrupts
* (or from the other point of view, to get decrementer interrupts
diff --git a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c
index a21632d37e5a..df6c9557b86a 100644
--- a/arch/ppc/syslib/m8xx_wdt.c
+++ b/arch/ppc/syslib/m8xx_wdt.c
@@ -19,6 +19,7 @@
#include <syslib/m8xx_wdt.h>
static int wdt_timeout;
+int m8xx_has_internal_rtc = 0;
static irqreturn_t m8xx_wdt_interrupt(int, void *, struct pt_regs *);
static struct irqaction m8xx_wdt_irqaction = {
@@ -45,35 +46,15 @@ static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void __init m8xx_wdt_handler_install(bd_t * binfo)
+#define SYPCR_SWP 0x1
+#define SYPCR_SWE 0x4
+
+
+void __init m8xx_wdt_install_irq(volatile immap_t *imap, bd_t *binfo)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
u32 pitc;
- u32 sypcr;
u32 pitrtclk;
- sypcr = in_be32(&imap->im_siu_conf.sc_sypcr);
-
- if (!(sypcr & 0x04)) {
- printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
- sypcr);
- return;
- }
-
- m8xx_wdt_reset();
-
- printk(KERN_NOTICE
- "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
- (sypcr >> 16), sypcr & 0x01);
-
- wdt_timeout = (sypcr >> 16) & 0xFFFF;
-
- if (!wdt_timeout)
- wdt_timeout = 0xFFFF;
-
- if (sypcr & 0x01)
- wdt_timeout *= 2048;
-
/*
* Fire trigger if half of the wdt ticked down
*/
@@ -98,6 +79,67 @@ void __init m8xx_wdt_handler_install(bd_t * binfo)
printk(KERN_NOTICE
"m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc);
+}
+
+static void m8xx_wdt_timer_func(unsigned long data);
+
+static struct timer_list m8xx_wdt_timer =
+ TIMER_INITIALIZER(m8xx_wdt_timer_func, 0, 0);
+
+void m8xx_wdt_stop_timer(void)
+{
+ del_timer(&m8xx_wdt_timer);
+}
+
+void m8xx_wdt_install_timer(void)
+{
+ m8xx_wdt_timer.expires = jiffies + (HZ/2);
+ add_timer(&m8xx_wdt_timer);
+}
+
+static void m8xx_wdt_timer_func(unsigned long data)
+{
+ m8xx_wdt_reset();
+ m8xx_wdt_install_timer();
+}
+
+void __init m8xx_wdt_handler_install(bd_t * binfo)
+{
+ volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ u32 sypcr;
+
+ sypcr = in_be32(&imap->im_siu_conf.sc_sypcr);
+
+ if (!(sypcr & SYPCR_SWE)) {
+ printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n",
+ sypcr);
+ return;
+ }
+
+ m8xx_wdt_reset();
+
+ printk(KERN_NOTICE
+ "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n",
+ (sypcr >> 16), sypcr & SYPCR_SWP);
+
+ wdt_timeout = (sypcr >> 16) & 0xFFFF;
+
+ if (!wdt_timeout)
+ wdt_timeout = 0xFFFF;
+
+ if (sypcr & SYPCR_SWP)
+ wdt_timeout *= 2048;
+
+ m8xx_has_internal_rtc = in_be16(&imap->im_sit.sit_rtcsc) & RTCSC_RTE;
+
+ /* if the internal RTC is off use a kernel timer */
+ if (!m8xx_has_internal_rtc) {
+ if (wdt_timeout < (binfo->bi_intfreq/HZ))
+ printk(KERN_ERR "m8xx_wdt: timeout too short for ktimer!\n");
+ m8xx_wdt_install_timer();
+ } else
+ m8xx_wdt_install_irq(imap, binfo);
+
wdt_timeout /= binfo->bi_intfreq;
}
diff --git a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h
index 0d81a9f8155f..e75835f0012b 100644
--- a/arch/ppc/syslib/m8xx_wdt.h
+++ b/arch/ppc/syslib/m8xx_wdt.h
@@ -9,8 +9,12 @@
#ifndef _PPC_SYSLIB_M8XX_WDT_H
#define _PPC_SYSLIB_M8XX_WDT_H
+extern int m8xx_has_internal_rtc;
+
extern void m8xx_wdt_handler_install(bd_t * binfo);
extern int m8xx_wdt_get_timeout(void);
extern void m8xx_wdt_reset(void);
+extern void m8xx_wdt_install_timer(void);
+extern void m8xx_wdt_stop_timer(void);
#endif /* _PPC_SYSLIB_M8XX_WDT_H */
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 4ac19080eb85..313c96ec7eb1 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -24,6 +24,12 @@
#include <asm/machdep.h>
+/* This macro is defined to activate the workaround for the bug
+ 435 of the MPC5200 (L25R). With it activated, we don't do any
+ 32 bits configuration access during type-1 cycles */
+#define MPC5200_BUG_435_WORKAROUND
+
+
static int
mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int len, u32 *val)
@@ -40,17 +46,39 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
((bus->number - hose->bus_offset) << 16) |
(devfn << 8) |
(offset & 0xfc));
+ mb();
+
+#ifdef MPC5200_BUG_435_WORKAROUND
+ if (bus->number != hose->bus_offset) {
+ switch (len) {
+ case 1:
+ value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
+ break;
+ case 2:
+ value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
+ break;
+
+ default:
+ value = in_le16((u16 __iomem *)hose->cfg_data) |
+ (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+ break;
+ }
+ }
+ else
+#endif
+ {
+ value = in_le32(hose->cfg_data);
- value = in_le32(hose->cfg_data);
-
- if (len != 4) {
- value >>= ((offset & 0x3) << 3);
- value &= 0xffffffff >> (32 - (len << 3));
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
}
*val = value;
out_be32(hose->cfg_addr, 0);
+ mb();
return PCIBIOS_SUCCESSFUL;
}
@@ -71,21 +99,48 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
((bus->number - hose->bus_offset) << 16) |
(devfn << 8) |
(offset & 0xfc));
+ mb();
+
+#ifdef MPC5200_BUG_435_WORKAROUND
+ if (bus->number != hose->bus_offset) {
+ switch (len) {
+ case 1:
+ out_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3), val);
+ break;
+ case 2:
+ out_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1), val);
+ break;
+
+ default:
+ out_le16((u16 __iomem *)hose->cfg_data,
+ (u16)val);
+ out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+ (u16)(val>>16));
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
- if (len != 4) {
- value = in_le32(hose->cfg_data);
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
- offset = (offset & 0x3) << 3;
- mask = (0xffffffff >> (32 - (len << 3)));
- mask <<= offset;
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
- value &= ~mask;
- val = value | ((val << offset) & mask);
+ out_le32(hose->cfg_data, val);
}
-
- out_le32(hose->cfg_data, val);
+ mb();
out_be32(hose->cfg_addr, 0);
+ mb();
return PCIBIOS_SUCCESSFUL;
}
@@ -99,9 +154,12 @@ static struct pci_ops mpc52xx_pci_ops = {
static void __init
mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
{
+ u32 tmp;
/* Setup control regs */
- /* Nothing to do afaik */
+ tmp = in_be32(&pci_regs->scr);
+ tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ out_be32(&pci_regs->scr, tmp);
/* Setup windows */
out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
@@ -142,16 +200,15 @@ mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
/* Not necessary and can be a bad thing if for example the bootloader
is displaying a splash screen or ... Just left here for
documentation purpose if anyone need it */
-#if 0
- u32 tmp;
tmp = in_be32(&pci_regs->gscr);
+#if 0
out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
udelay(50);
- out_be32(&pci_regs->gscr, tmp);
#endif
+ out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
}
-static void __init
+static void
mpc52xx_pci_fixup_resources(struct pci_dev *dev)
{
int i;
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index bb2374585a7b..a4a4b02227df 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -84,9 +84,11 @@ mpc52xx_set_bat(void)
void __init
mpc52xx_map_io(void)
{
- /* Here we only map the MBAR */
+ /* Here we map the MBAR and the whole upper zone. MBAR is only
+ 64k but we can't map only 64k with BATs. Map the whole
+ 0xf0000000 range is ok and helps eventual lpb devices placed there */
io_block_mapping(
- MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO);
+ MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _PAGE_IO);
}
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 847df4409982..f9b95de70e23 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -28,7 +28,6 @@
*/
struct gianfar_mdio_data mpc83xx_mdio_pdata = {
- .paddr = 0x24520,
};
static struct gianfar_platform_data mpc83xx_tsec1_pdata = {
@@ -226,7 +225,14 @@ struct platform_device ppc_sys_platform_devices[] = {
.name = "fsl-gianfar_mdio",
.id = 0,
.dev.platform_data = &mpc83xx_mdio_pdata,
- .num_resources = 0,
+ .num_resources = 1,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x24520,
+ .end = 0x2453f,
+ .flags = IORESOURCE_MEM,
+ },
+ },
},
};
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 69949d255658..00e9b6ff2f6e 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -26,7 +26,6 @@
* what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
*/
struct gianfar_mdio_data mpc85xx_mdio_pdata = {
- .paddr = MPC85xx_MIIM_OFFSET,
};
static struct gianfar_platform_data mpc85xx_tsec1_pdata = {
@@ -720,7 +719,14 @@ struct platform_device ppc_sys_platform_devices[] = {
.name = "fsl-gianfar_mdio",
.id = 0,
.dev.platform_data = &mpc85xx_mdio_pdata,
- .num_resources = 0,
+ .num_resources = 1,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x24520,
+ .end = 0x2453f,
+ .flags = IORESOURCE_MEM,
+ },
+ },
},
};
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index 9ccce438bd7a..ab34b1d6072f 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -189,6 +189,8 @@ ocp_device_resume(struct device *dev)
struct bus_type ocp_bus_type = {
.name = "ocp",
.match = ocp_device_match,
+ .probe = ocp_driver_probe,
+ .remove = ocp_driver_remove,
.suspend = ocp_device_suspend,
.resume = ocp_device_resume,
};
@@ -210,8 +212,6 @@ ocp_register_driver(struct ocp_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &ocp_bus_type;
- drv->driver.probe = ocp_device_probe;
- drv->driver.remove = ocp_device_remove;
/* register with core */
return driver_register(&drv->driver);
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
index af4deace49e0..482f837fd373 100644
--- a/arch/ppc/syslib/prom.c
+++ b/arch/ppc/syslib/prom.c
@@ -70,8 +70,6 @@ int use_of_interrupt_tree;
struct device_node *dflt_interrupt_controller;
int num_interrupt_controllers;
-int pmac_newworld;
-
extern unsigned int rtas_entry; /* physical pointer */
extern struct device_node *allnodes;
@@ -123,22 +121,13 @@ finish_device_tree(void)
unsigned long mem = (unsigned long) klimit;
struct device_node *np;
- /* All newworld pmac machines and CHRPs now use the interrupt tree */
+ /* All CHRPs now use the interrupt tree */
for (np = allnodes; np != NULL; np = np->allnext) {
if (get_property(np, "interrupt-parent", NULL)) {
use_of_interrupt_tree = 1;
break;
}
}
- if (_machine == _MACH_Pmac && use_of_interrupt_tree)
- pmac_newworld = 1;
-
-#ifdef CONFIG_BOOTX_TEXT
- if (boot_infos && pmac_newworld) {
- prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
- prom_print(" You should use an Open Firmware bootloader\n");
- }
-#endif /* CONFIG_BOOTX_TEXT */
if (use_of_interrupt_tree) {
/*
@@ -434,16 +423,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start)
* those machines, we want to offset interrupts from the
* second openpic by 128 -- BenH
*/
- if (_machine != _MACH_Pmac && num_interrupt_controllers > 1
+ if (num_interrupt_controllers > 1
&& ic != NULL
&& get_property(ic, "interrupt-parent", NULL) == NULL)
offset = 16;
- else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1
- && ic != NULL && ic->parent != NULL) {
- char *name = get_property(ic->parent, "name", NULL);
- if (name && !strcmp(name, "u3"))
- offset = 128;
- }
np->intrs[i].line = irq[0] + offset;
if (n > 1)
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index c80177f8ec04..4344cbe9b5c5 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -18,7 +18,6 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/errno.h>
-#include <asm/pmac_feature.h>
#include <asm/processor.h>
#include <asm/delay.h>
#include <asm/btext.h>
@@ -27,11 +26,9 @@ static volatile unsigned char *sccc, *sccd;
unsigned int TXRDY, RXRDY, DLAB;
static int xmon_expect(const char *str, unsigned int timeout);
-static int use_serial;
static int use_screen;
static int via_modem;
static int xmon_use_sccb;
-static struct device_node *channel_node;
#define TB_SPEED 25000000
@@ -112,96 +109,21 @@ xmon_map_scc(void)
#ifdef CONFIG_PPC_MULTIPLATFORM
volatile unsigned char *base;
- if (_machine == _MACH_Pmac) {
- struct device_node *np;
- unsigned long addr;
-#ifdef CONFIG_BOOTX_TEXT
- if (!use_screen && !use_serial
- && !machine_is_compatible("iMac")) {
- /* see if there is a keyboard in the device tree
- with a parent of type "adb" */
- for (np = find_devices("keyboard"); np; np = np->next)
- if (np->parent && np->parent->type
- && strcmp(np->parent->type, "adb") == 0)
- break;
-
- /* needs to be hacked if xmon_printk is to be used
- from within find_via_pmu() */
-#ifdef CONFIG_ADB_PMU
- if (np != NULL && boot_text_mapped && find_via_pmu())
- use_screen = 1;
-#endif
-#ifdef CONFIG_ADB_CUDA
- if (np != NULL && boot_text_mapped && find_via_cuda())
- use_screen = 1;
-#endif
- }
- if (!use_screen && (np = find_devices("escc")) != NULL) {
- /*
- * look for the device node for the serial port
- * we're using and see if it says it has a modem
- */
- char *name = xmon_use_sccb? "ch-b": "ch-a";
- char *slots;
- int l;
-
- np = np->child;
- while (np != NULL && strcmp(np->name, name) != 0)
- np = np->sibling;
- if (np != NULL) {
- /* XXX should parse this properly */
- channel_node = np;
- slots = get_property(np, "slot-names", &l);
- if (slots != NULL && l >= 10
- && strcmp(slots+4, "Modem") == 0)
- via_modem = 1;
- }
- }
- btext_drawstring("xmon uses ");
- if (use_screen)
- btext_drawstring("screen and keyboard\n");
- else {
- if (via_modem)
- btext_drawstring("modem on ");
- btext_drawstring(xmon_use_sccb? "printer": "modem");
- btext_drawstring(" port\n");
- }
-
-#endif /* CONFIG_BOOTX_TEXT */
-
-#ifdef CHRP_ESCC
- addr = 0xc1013020;
-#else
- addr = 0xf3013020;
-#endif
- TXRDY = 4;
- RXRDY = 1;
-
- np = find_devices("mac-io");
- if (np && np->n_addrs)
- addr = np->addrs[0].address + 0x13020;
- base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
- sccc = base + (addr & ~PAGE_MASK);
- sccd = sccc + 0x10;
-
- }
#ifdef CONFIG_PPC_CHRP
- else {
- base = (volatile unsigned char *) isa_io_base;
- if (_machine == _MACH_chrp)
- base = (volatile unsigned char *)
- ioremap(chrp_find_phys_io_base(), 0x1000);
-
- sccc = base + 0x3fd;
- sccd = base + 0x3f8;
- if (xmon_use_sccb) {
- sccc -= 0x100;
- sccd -= 0x100;
- }
- TXRDY = 0x20;
- RXRDY = 1;
- DLAB = 0x80;
+ base = (volatile unsigned char *) isa_io_base;
+ if (_machine == _MACH_chrp)
+ base = (volatile unsigned char *)
+ ioremap(chrp_find_phys_io_base(), 0x1000);
+
+ sccc = base + 0x3fd;
+ sccd = base + 0x3f8;
+ if (xmon_use_sccb) {
+ sccc -= 0x100;
+ sccd -= 0x100;
}
+ TXRDY = 0x20;
+ RXRDY = 1;
+ DLAB = 0x80;
#endif /* CONFIG_PPC_CHRP */
#elif defined(CONFIG_GEMINI)
/* should already be mapped by the kernel boot */
@@ -385,16 +307,6 @@ xmon_read_poll(void)
return *sccd;
}
-static unsigned char scc_inittab[] = {
- 13, 0, /* set baud rate divisor */
- 12, 1,
- 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
xmon_init_scc(void)
{
@@ -407,43 +319,6 @@ xmon_init_scc(void)
sccd[3] = 3; eieio(); /* LCR = 8N1 */
sccd[1] = 0; eieio(); /* IER = 0 */
}
- else if ( _machine == _MACH_Pmac )
- {
- int i, x;
-
- if (channel_node != 0)
- pmac_call_feature(
- PMAC_FTR_SCC_ENABLE,
- channel_node,
- PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
- printk(KERN_INFO "Serial port locked ON by debugger !\n");
- if (via_modem && channel_node != 0) {
- unsigned int t0;
-
- pmac_call_feature(
- PMAC_FTR_MODEM_ENABLE,
- channel_node, 0, 1);
- printk(KERN_INFO "Modem powered up by debugger !\n");
- t0 = readtb();
- while (readtb() - t0 < 3*TB_SPEED)
- eieio();
- }
- /* use the B channel if requested */
- if (xmon_use_sccb) {
- sccc = (volatile unsigned char *)
- ((unsigned long)sccc & ~0x20);
- sccd = sccc + 0x10;
- }
- for (i = 20000; i != 0; --i) {
- x = *sccc; eieio();
- }
- *sccc = 9; eieio(); /* reset A or B side */
- *sccc = ((unsigned long)sccc & 0x20)? 0x80: 0x40; eieio();
- for (i = 0; i < sizeof(scc_inittab); ++i) {
- *sccc = scc_inittab[i];
- eieio();
- }
- }
scc_initialized = 1;
if (via_modem) {
for (;;) {
@@ -632,19 +507,9 @@ xmon_fgets(char *str, int nb, void *f)
void
xmon_enter(void)
{
-#ifdef CONFIG_ADB_PMU
- if (_machine == _MACH_Pmac) {
- pmu_suspend();
- }
-#endif
}
void
xmon_leave(void)
{
-#ifdef CONFIG_ADB_PMU
- if (_machine == _MACH_Pmac) {
- pmu_resume();
- }
-#endif
}
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index 2b483b4f1602..bdaf6597b4c2 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -16,9 +16,6 @@
#include <asm/bootx.h>
#include <asm/machdep.h>
#include <asm/xmon.h>
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
#include "nonstdio.h"
#include "privinst.h"
@@ -99,7 +96,7 @@ static void remove_bpts(void);
static void insert_bpts(void);
static struct bpt *at_breakpoint(unsigned pc);
static void bpt_cmds(void);
-static void cacheflush(void);
+void cacheflush(void);
#ifdef CONFIG_SMP
static void cpu_cmd(void);
#endif /* CONFIG_SMP */
@@ -260,16 +257,6 @@ int xmon(struct pt_regs *excp)
*/
#endif /* CONFIG_SMP */
remove_bpts();
-#ifdef CONFIG_PMAC_BACKLIGHT
- if( setjmp(bus_error_jmp) == 0 ) {
- debugger_fault_handler = handle_fault;
- sync();
- set_backlight_enable(1);
- set_backlight_level(BACKLIGHT_MAX);
- sync();
- }
- debugger_fault_handler = NULL;
-#endif /* CONFIG_PMAC_BACKLIGHT */
cmd = cmds(excp);
if (cmd == 's') {
xmon_trace[smp_processor_id()] = SSTEP;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 477ac2758bd5..b66602ad7b33 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -23,35 +23,22 @@ config GENERIC_BUST_SPINLOCK
mainmenu "Linux Kernel Configuration"
-config ARCH_S390
+config S390
bool
default y
-config UID16
- bool
- default y
- depends on ARCH_S390X = 'n'
-
source "init/Kconfig"
menu "Base setup"
comment "Processor type and features"
-config ARCH_S390X
+config 64BIT
bool "64 bit kernel"
help
Select this option if you have a 64 bit IBM zSeries machine
and want to use the 64 bit addressing mode.
-config 64BIT
- def_bool ARCH_S390X
-
-config ARCH_S390_31
- bool
- depends on ARCH_S390X = 'n'
- default y
-
config SMP
bool "Symmetric multi-processing support"
---help---
@@ -101,20 +88,15 @@ config MATHEMU
on older S/390 machines. Say Y unless you know your machine doesn't
need this.
-config S390_SUPPORT
+config COMPAT
bool "Kernel support for 31 bit emulation"
- depends on ARCH_S390X
+ depends on 64BIT
help
Select this option if you want to enable your system kernel to
handle system-calls from ELF binaries for 31 bit ESA. This option
(and some other stuff like libraries and such) is needed for
executing 31 bit applications. It is safe to say "Y".
-config COMPAT
- bool
- depends on S390_SUPPORT
- default y
-
config SYSVIPC_COMPAT
bool
depends on COMPAT && SYSVIPC
@@ -122,7 +104,7 @@ config SYSVIPC_COMPAT
config BINFMT_ELF32
tristate "Kernel support for 31 bit ELF binaries"
- depends on S390_SUPPORT
+ depends on COMPAT
help
This allows you to run 32-bit Linux/ELF binaries on your zSeries
in 64 bit mode. Everybody wants this; say Y.
@@ -135,7 +117,7 @@ choice
config MARCH_G5
bool "S/390 model G5 and G6"
- depends on ARCH_S390_31
+ depends on !64BIT
help
Select this to build a 31 bit kernel that works
on all S/390 and zSeries machines.
@@ -240,8 +222,8 @@ config MACHCHK_WARNING
config QDIO
tristate "QDIO support"
---help---
- This driver provides the Queued Direct I/O base support for the
- IBM S/390 (G5 and G6) and eServer zSeries (z800, z890, z900 and z990).
+ This driver provides the Queued Direct I/O base support for
+ IBM mainframes.
For details please refer to the documentation provided by IBM at
<http://www10.software.ibm.com/developerworks/opensource/linux390>
@@ -263,7 +245,8 @@ config QDIO_DEBUG
bool "Extended debugging information"
depends on QDIO
help
- Say Y here to get extended debugging output in /proc/s390dbf/qdio...
+ Say Y here to get extended debugging output in
+ /sys/kernel/debug/s390dbf/qdio...
Warning: this option reduces the performance of the QDIO module.
If unsure, say N.
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 73a09a6ee6c8..6c6b197898d0 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -13,16 +13,14 @@
# Copyright (C) 1994 by Linus Torvalds
#
-ifdef CONFIG_ARCH_S390_31
+ifndef CONFIG_64BIT
LDFLAGS := -m elf_s390
CFLAGS += -m31
AFLAGS += -m31
UTS_MACHINE := s390
STACK_SIZE := 8192
CHECKFLAGS += -D__s390__
-endif
-
-ifdef CONFIG_ARCH_S390X
+else
LDFLAGS := -m elf64_s390
MODFLAGS += -fpic -D__PIC__
CFLAGS += -m64
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index dee6ab54984d..d06a8d71c71d 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -40,7 +40,7 @@
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
for 1 microsecond */
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */
#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */
@@ -54,13 +54,13 @@
#define APPLDATA_GEN_EVENT_RECORD 0x82
#define APPLDATA_START_CONFIG_REC 0x83
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/*
* Parameter list for DIAGNOSE X'DC'
*/
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
struct appldata_parameter_list {
u16 diag; /* The DIAGNOSE code X'00DC' */
u8 function; /* The function code for the DIAGNOSE */
@@ -82,7 +82,7 @@ struct appldata_parameter_list {
u64 product_id_addr;
u64 buffer_addr;
};
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/*
* /proc entries (sysctl)
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index e0a476bf4fd6..99ddd3bf2fba 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -141,19 +141,19 @@ static void appldata_get_os_data(void *data)
j = 0;
for_each_online_cpu(i) {
os_data->os_cpu[j].per_cpu_user =
- kstat_cpu(i).cpustat.user;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.user);
os_data->os_cpu[j].per_cpu_nice =
- kstat_cpu(i).cpustat.nice;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.nice);
os_data->os_cpu[j].per_cpu_system =
- kstat_cpu(i).cpustat.system;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.system);
os_data->os_cpu[j].per_cpu_idle =
- kstat_cpu(i).cpustat.idle;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.idle);
os_data->os_cpu[j].per_cpu_irq =
- kstat_cpu(i).cpustat.irq;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.irq);
os_data->os_cpu[j].per_cpu_softirq =
- kstat_cpu(i).cpustat.softirq;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.softirq);
os_data->os_cpu[j].per_cpu_iowait =
- kstat_cpu(i).cpustat.iowait;
+ cputime_to_jiffies(kstat_cpu(i).cpustat.iowait);
j++;
}
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 96a05e6b51e0..bfe2541dc5cf 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -2,7 +2,9 @@
# Cryptographic API
#
-obj-$(CONFIG_CRYPTO_SHA1_Z990) += sha1_z990.o
-obj-$(CONFIG_CRYPTO_DES_Z990) += des_z990.o des_check_key.o
+obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o
+obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
+obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
+obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
-obj-$(CONFIG_CRYPTO_TEST) += crypt_z990_query.o
+obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
new file mode 100644
index 000000000000..c5ca2dc5d428
--- /dev/null
+++ b/arch/s390/crypto/aes_s390.c
@@ -0,0 +1,276 @@
+/*
+ * Cryptographic API.
+ *
+ * s390 implementation of the AES Cipher Algorithm.
+ *
+ * s390 Version:
+ * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ * Author(s): Jan Glauber (jang@de.ibm.com)
+ *
+ * Derived from "crypto/aes.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/module.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+#include "crypt_s390.h"
+
+#define AES_MIN_KEY_SIZE 16
+#define AES_MAX_KEY_SIZE 32
+
+/* data block size for all key lengths */
+#define AES_BLOCK_SIZE 16
+
+int has_aes_128 = 0;
+int has_aes_192 = 0;
+int has_aes_256 = 0;
+
+struct s390_aes_ctx {
+ u8 iv[AES_BLOCK_SIZE];
+ u8 key[AES_MAX_KEY_SIZE];
+ int key_len;
+};
+
+static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len,
+ u32 *flags)
+{
+ struct s390_aes_ctx *sctx = ctx;
+
+ switch (key_len) {
+ case 16:
+ if (!has_aes_128)
+ goto fail;
+ break;
+ case 24:
+ if (!has_aes_192)
+ goto fail;
+
+ break;
+ case 32:
+ if (!has_aes_256)
+ goto fail;
+ break;
+ default:
+ /* invalid key length */
+ goto fail;
+ break;
+ }
+
+ sctx->key_len = key_len;
+ memcpy(sctx->key, in_key, key_len);
+ return 0;
+fail:
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+}
+
+static void aes_encrypt(void *ctx, u8 *out, const u8 *in)
+{
+ const struct s390_aes_ctx *sctx = ctx;
+
+ switch (sctx->key_len) {
+ case 16:
+ crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ case 24:
+ crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ case 32:
+ crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ }
+}
+
+static void aes_decrypt(void *ctx, u8 *out, const u8 *in)
+{
+ const struct s390_aes_ctx *sctx = ctx;
+
+ switch (sctx->key_len) {
+ case 16:
+ crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ case 24:
+ crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ case 32:
+ crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
+ AES_BLOCK_SIZE);
+ break;
+ }
+}
+
+static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(AES_BLOCK_SIZE - 1);
+
+ switch (sctx->key_len) {
+ case 16:
+ ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 24:
+ ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 32:
+ ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ }
+ return nbytes;
+}
+
+static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(AES_BLOCK_SIZE - 1);
+
+ switch (sctx->key_len) {
+ case 16:
+ ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 24:
+ ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 32:
+ ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ }
+ return nbytes;
+}
+
+static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(AES_BLOCK_SIZE - 1);
+
+ memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
+ switch (sctx->key_len) {
+ case 16:
+ ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 24:
+ ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 32:
+ ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ }
+ memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
+
+ return nbytes;
+}
+
+static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(AES_BLOCK_SIZE - 1);
+
+ memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
+ switch (sctx->key_len) {
+ case 16:
+ ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 24:
+ ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ case 32:
+ ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+ break;
+ }
+ return nbytes;
+}
+
+
+static struct crypto_alg aes_alg = {
+ .cra_name = "aes",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct s390_aes_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt,
+ .cia_encrypt_ecb = aes_encrypt_ecb,
+ .cia_decrypt_ecb = aes_decrypt_ecb,
+ .cia_encrypt_cbc = aes_encrypt_cbc,
+ .cia_decrypt_cbc = aes_decrypt_cbc,
+ }
+ }
+};
+
+static int __init aes_init(void)
+{
+ int ret;
+
+ if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
+ has_aes_128 = 1;
+ if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
+ has_aes_192 = 1;
+ if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
+ has_aes_256 = 1;
+
+ if (!has_aes_128 && !has_aes_192 && !has_aes_256)
+ return -ENOSYS;
+
+ ret = crypto_register_alg(&aes_alg);
+ if (ret != 0)
+ printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
+ return ret;
+}
+
+static void __exit aes_fini(void)
+{
+ crypto_unregister_alg(&aes_alg);
+}
+
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_ALIAS("aes");
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
+MODULE_LICENSE("GPL");
+
diff --git a/arch/s390/crypto/crypt_z990.h b/arch/s390/crypto/crypt_s390.h
index 4df660b99e5a..d1c259a7fe33 100644
--- a/arch/s390/crypto/crypt_z990.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -1,7 +1,7 @@
/*
* Cryptographic API.
*
- * Support for z990 cryptographic instructions.
+ * Support for s390 cryptographic instructions.
*
* Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
* Author(s): Thomas Spatzier (tspat@de.ibm.com)
@@ -12,84 +12,108 @@
* any later version.
*
*/
-#ifndef _CRYPTO_ARCH_S390_CRYPT_Z990_H
-#define _CRYPTO_ARCH_S390_CRYPT_Z990_H
+#ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H
+#define _CRYPTO_ARCH_S390_CRYPT_S390_H
#include <asm/errno.h>
-#define CRYPT_Z990_OP_MASK 0xFF00
-#define CRYPT_Z990_FUNC_MASK 0x00FF
+#define CRYPT_S390_OP_MASK 0xFF00
+#define CRYPT_S390_FUNC_MASK 0x00FF
-
-/*z990 cryptographic operations*/
-enum crypt_z990_operations {
- CRYPT_Z990_KM = 0x0100,
- CRYPT_Z990_KMC = 0x0200,
- CRYPT_Z990_KIMD = 0x0300,
- CRYPT_Z990_KLMD = 0x0400,
- CRYPT_Z990_KMAC = 0x0500
+/* s930 cryptographic operations */
+enum crypt_s390_operations {
+ CRYPT_S390_KM = 0x0100,
+ CRYPT_S390_KMC = 0x0200,
+ CRYPT_S390_KIMD = 0x0300,
+ CRYPT_S390_KLMD = 0x0400,
+ CRYPT_S390_KMAC = 0x0500
};
-/*function codes for KM (CIPHER MESSAGE) instruction*/
-enum crypt_z990_km_func {
- KM_QUERY = CRYPT_Z990_KM | 0,
- KM_DEA_ENCRYPT = CRYPT_Z990_KM | 1,
- KM_DEA_DECRYPT = CRYPT_Z990_KM | 1 | 0x80, //modifier bit->decipher
- KM_TDEA_128_ENCRYPT = CRYPT_Z990_KM | 2,
- KM_TDEA_128_DECRYPT = CRYPT_Z990_KM | 2 | 0x80,
- KM_TDEA_192_ENCRYPT = CRYPT_Z990_KM | 3,
- KM_TDEA_192_DECRYPT = CRYPT_Z990_KM | 3 | 0x80,
+/* function codes for KM (CIPHER MESSAGE) instruction
+ * 0x80 is the decipher modifier bit
+ */
+enum crypt_s390_km_func {
+ KM_QUERY = CRYPT_S390_KM | 0x0,
+ KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1,
+ KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80,
+ KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2,
+ KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80,
+ KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3,
+ KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80,
+ KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12,
+ KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80,
+ KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13,
+ KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80,
+ KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14,
+ KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80,
};
-/*function codes for KMC (CIPHER MESSAGE WITH CHAINING) instruction*/
-enum crypt_z990_kmc_func {
- KMC_QUERY = CRYPT_Z990_KMC | 0,
- KMC_DEA_ENCRYPT = CRYPT_Z990_KMC | 1,
- KMC_DEA_DECRYPT = CRYPT_Z990_KMC | 1 | 0x80, //modifier bit->decipher
- KMC_TDEA_128_ENCRYPT = CRYPT_Z990_KMC | 2,
- KMC_TDEA_128_DECRYPT = CRYPT_Z990_KMC | 2 | 0x80,
- KMC_TDEA_192_ENCRYPT = CRYPT_Z990_KMC | 3,
- KMC_TDEA_192_DECRYPT = CRYPT_Z990_KMC | 3 | 0x80,
+/* function codes for KMC (CIPHER MESSAGE WITH CHAINING)
+ * instruction
+ */
+enum crypt_s390_kmc_func {
+ KMC_QUERY = CRYPT_S390_KMC | 0x0,
+ KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1,
+ KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80,
+ KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2,
+ KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80,
+ KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3,
+ KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80,
+ KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12,
+ KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80,
+ KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13,
+ KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80,
+ KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14,
+ KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80,
};
-/*function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) instruction*/
-enum crypt_z990_kimd_func {
- KIMD_QUERY = CRYPT_Z990_KIMD | 0,
- KIMD_SHA_1 = CRYPT_Z990_KIMD | 1,
+/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+ * instruction
+ */
+enum crypt_s390_kimd_func {
+ KIMD_QUERY = CRYPT_S390_KIMD | 0,
+ KIMD_SHA_1 = CRYPT_S390_KIMD | 1,
+ KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
};
-/*function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) instruction*/
-enum crypt_z990_klmd_func {
- KLMD_QUERY = CRYPT_Z990_KLMD | 0,
- KLMD_SHA_1 = CRYPT_Z990_KLMD | 1,
+/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
+ * instruction
+ */
+enum crypt_s390_klmd_func {
+ KLMD_QUERY = CRYPT_S390_KLMD | 0,
+ KLMD_SHA_1 = CRYPT_S390_KLMD | 1,
+ KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
};
-/*function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) instruction*/
-enum crypt_z990_kmac_func {
- KMAC_QUERY = CRYPT_Z990_KMAC | 0,
- KMAC_DEA = CRYPT_Z990_KMAC | 1,
- KMAC_TDEA_128 = CRYPT_Z990_KMAC | 2,
- KMAC_TDEA_192 = CRYPT_Z990_KMAC | 3
+/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction
+ */
+enum crypt_s390_kmac_func {
+ KMAC_QUERY = CRYPT_S390_KMAC | 0,
+ KMAC_DEA = CRYPT_S390_KMAC | 1,
+ KMAC_TDEA_128 = CRYPT_S390_KMAC | 2,
+ KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
};
-/*status word for z990 crypto instructions' QUERY functions*/
-struct crypt_z990_query_status {
+/* status word for s390 crypto instructions' QUERY functions */
+struct crypt_s390_query_status {
u64 high;
u64 low;
};
/*
- * Standard fixup and ex_table sections for crypt_z990 inline functions.
- * label 0: the z990 crypto operation
- * label 1: just after 1 to catch illegal operation exception on non-z990
+ * Standard fixup and ex_table sections for crypt_s390 inline functions.
+ * label 0: the s390 crypto operation
+ * label 1: just after 1 to catch illegal operation exception
+ * (unsupported model)
* label 6: the return point after fixup
* label 7: set error value if exception _in_ crypto operation
* label 8: set error value if illegal operation exception
* [ret] is the variable to receive the error code
* [ERR] is the error code value
*/
-#ifndef __s390x__
-#define __crypt_z990_fixup \
+#ifndef CONFIG_64BIT
+#define __crypt_s390_fixup \
".section .fixup,\"ax\" \n" \
"7: lhi %0,%h[e1] \n" \
" bras 1,9f \n" \
@@ -105,8 +129,8 @@ struct crypt_z990_query_status {
" .long 0b,7b \n" \
" .long 1b,8b \n" \
".previous"
-#else /* __s390x__ */
-#define __crypt_z990_fixup \
+#else /* CONFIG_64BIT */
+#define __crypt_s390_fixup \
".section .fixup,\"ax\" \n" \
"7: lhi %0,%h[e1] \n" \
" jg 6b \n" \
@@ -118,25 +142,25 @@ struct crypt_z990_query_status {
" .quad 0b,7b \n" \
" .quad 1b,8b \n" \
".previous"
-#endif /* __s390x__ */
+#endif /* CONFIG_64BIT */
/*
- * Standard code for setting the result of z990 crypto instructions.
+ * Standard code for setting the result of s390 crypto instructions.
* %0: the register which will receive the result
* [result]: the register containing the result (e.g. second operand length
* to compute number of processed bytes].
*/
-#ifndef __s390x__
-#define __crypt_z990_set_result \
+#ifndef CONFIG_64BIT
+#define __crypt_s390_set_result \
" lr %0,%[result] \n"
-#else /* __s390x__ */
-#define __crypt_z990_set_result \
+#else /* CONFIG_64BIT */
+#define __crypt_s390_set_result \
" lgr %0,%[result] \n"
#endif
/*
- * Executes the KM (CIPHER MESSAGE) operation of the z990 CPU.
- * @param func: the function code passed to KM; see crypt_z990_km_func
+ * Executes the KM (CIPHER MESSAGE) operation of the CPU.
+ * @param func: the function code passed to KM; see crypt_s390_km_func
* @param param: address of parameter block; see POP for details on each func
* @param dest: address of destination memory area
* @param src: address of source memory area
@@ -145,9 +169,9 @@ struct crypt_z990_query_status {
* for encryption/decryption funcs
*/
static inline int
-crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len)
+crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len)
{
- register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
register u8* __dest asm("4") = dest;
register const u8* __src asm("2") = src;
@@ -156,26 +180,26 @@ crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len)
ret = 0;
__asm__ __volatile__ (
- "0: .insn rre,0xB92E0000,%1,%2 \n" //KM opcode
- "1: brc 1,0b \n" //handle partial completion
- __crypt_z990_set_result
+ "0: .insn rre,0xB92E0000,%1,%2 \n" /* KM opcode */
+ "1: brc 1,0b \n" /* handle partial completion */
+ __crypt_s390_set_result
"6: \n"
- __crypt_z990_fixup
+ __crypt_s390_fixup
: "+d" (ret), "+a" (__dest), "+a" (__src),
[result] "+d" (__src_len)
: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
"a" (__param)
: "cc", "memory"
);
- if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
ret = src_len - ret;
}
return ret;
}
/*
- * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the z990 CPU.
- * @param func: the function code passed to KM; see crypt_z990_kmc_func
+ * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU.
+ * @param func: the function code passed to KM; see crypt_s390_kmc_func
* @param param: address of parameter block; see POP for details on each func
* @param dest: address of destination memory area
* @param src: address of source memory area
@@ -184,9 +208,9 @@ crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len)
* for encryption/decryption funcs
*/
static inline int
-crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
+crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
{
- register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
register u8* __dest asm("4") = dest;
register const u8* __src asm("2") = src;
@@ -195,18 +219,18 @@ crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
ret = 0;
__asm__ __volatile__ (
- "0: .insn rre,0xB92F0000,%1,%2 \n" //KMC opcode
- "1: brc 1,0b \n" //handle partial completion
- __crypt_z990_set_result
+ "0: .insn rre,0xB92F0000,%1,%2 \n" /* KMC opcode */
+ "1: brc 1,0b \n" /* handle partial completion */
+ __crypt_s390_set_result
"6: \n"
- __crypt_z990_fixup
+ __crypt_s390_fixup
: "+d" (ret), "+a" (__dest), "+a" (__src),
[result] "+d" (__src_len)
: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
"a" (__param)
: "cc", "memory"
);
- if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
ret = src_len - ret;
}
return ret;
@@ -214,8 +238,8 @@ crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
/*
* Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
- * of the z990 CPU.
- * @param func: the function code passed to KM; see crypt_z990_kimd_func
+ * of the CPU.
+ * @param func: the function code passed to KM; see crypt_s390_kimd_func
* @param param: address of parameter block; see POP for details on each func
* @param src: address of source memory area
* @param src_len: length of src operand in bytes
@@ -223,9 +247,9 @@ crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
* for digest funcs
*/
static inline int
-crypt_z990_kimd(long func, void* param, const u8* src, long src_len)
+crypt_s390_kimd(long func, void* param, const u8* src, long src_len)
{
- register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
register const u8* __src asm("2") = src;
register long __src_len asm("3") = src_len;
@@ -233,25 +257,25 @@ crypt_z990_kimd(long func, void* param, const u8* src, long src_len)
ret = 0;
__asm__ __volatile__ (
- "0: .insn rre,0xB93E0000,%1,%1 \n" //KIMD opcode
- "1: brc 1,0b \n" /*handle partical completion of kimd*/
- __crypt_z990_set_result
+ "0: .insn rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */
+ "1: brc 1,0b \n" /* handle partical completion */
+ __crypt_s390_set_result
"6: \n"
- __crypt_z990_fixup
+ __crypt_s390_fixup
: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
"a" (__param)
: "cc", "memory"
);
- if (ret >= 0 && (func & CRYPT_Z990_FUNC_MASK)){
+ if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){
ret = src_len - ret;
}
return ret;
}
/*
- * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the z990 CPU.
- * @param func: the function code passed to KM; see crypt_z990_klmd_func
+ * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU.
+ * @param func: the function code passed to KM; see crypt_s390_klmd_func
* @param param: address of parameter block; see POP for details on each func
* @param src: address of source memory area
* @param src_len: length of src operand in bytes
@@ -259,9 +283,9 @@ crypt_z990_kimd(long func, void* param, const u8* src, long src_len)
* for digest funcs
*/
static inline int
-crypt_z990_klmd(long func, void* param, const u8* src, long src_len)
+crypt_s390_klmd(long func, void* param, const u8* src, long src_len)
{
- register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
register const u8* __src asm("2") = src;
register long __src_len asm("3") = src_len;
@@ -269,17 +293,17 @@ crypt_z990_klmd(long func, void* param, const u8* src, long src_len)
ret = 0;
__asm__ __volatile__ (
- "0: .insn rre,0xB93F0000,%1,%1 \n" //KLMD opcode
- "1: brc 1,0b \n" /*handle partical completion of klmd*/
- __crypt_z990_set_result
+ "0: .insn rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */
+ "1: brc 1,0b \n" /* handle partical completion */
+ __crypt_s390_set_result
"6: \n"
- __crypt_z990_fixup
+ __crypt_s390_fixup
: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
"a" (__param)
: "cc", "memory"
);
- if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
ret = src_len - ret;
}
return ret;
@@ -287,8 +311,8 @@ crypt_z990_klmd(long func, void* param, const u8* src, long src_len)
/*
* Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
- * of the z990 CPU.
- * @param func: the function code passed to KM; see crypt_z990_klmd_func
+ * of the CPU.
+ * @param func: the function code passed to KM; see crypt_s390_klmd_func
* @param param: address of parameter block; see POP for details on each func
* @param src: address of source memory area
* @param src_len: length of src operand in bytes
@@ -296,9 +320,9 @@ crypt_z990_klmd(long func, void* param, const u8* src, long src_len)
* for digest funcs
*/
static inline int
-crypt_z990_kmac(long func, void* param, const u8* src, long src_len)
+crypt_s390_kmac(long func, void* param, const u8* src, long src_len)
{
- register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK;
+ register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
register void* __param asm("1") = param;
register const u8* __src asm("2") = src;
register long __src_len asm("3") = src_len;
@@ -306,58 +330,58 @@ crypt_z990_kmac(long func, void* param, const u8* src, long src_len)
ret = 0;
__asm__ __volatile__ (
- "0: .insn rre,0xB91E0000,%5,%5 \n" //KMAC opcode
- "1: brc 1,0b \n" /*handle partical completion of klmd*/
- __crypt_z990_set_result
+ "0: .insn rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */
+ "1: brc 1,0b \n" /* handle partical completion */
+ __crypt_s390_set_result
"6: \n"
- __crypt_z990_fixup
+ __crypt_s390_fixup
: "+d" (ret), "+a" (__src), [result] "+d" (__src_len)
: [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func),
"a" (__param)
: "cc", "memory"
);
- if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){
+ if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){
ret = src_len - ret;
}
return ret;
}
/**
- * Tests if a specific z990 crypto function is implemented on the machine.
+ * Tests if a specific crypto function is implemented on the machine.
* @param func: the function code of the specific function; 0 if op in general
* @return 1 if func available; 0 if func or op in general not available
*/
static inline int
-crypt_z990_func_available(int func)
+crypt_s390_func_available(int func)
{
int ret;
- struct crypt_z990_query_status status = {
+ struct crypt_s390_query_status status = {
.high = 0,
.low = 0
};
- switch (func & CRYPT_Z990_OP_MASK){
- case CRYPT_Z990_KM:
- ret = crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0);
+ switch (func & CRYPT_S390_OP_MASK){
+ case CRYPT_S390_KM:
+ ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
break;
- case CRYPT_Z990_KMC:
- ret = crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+ case CRYPT_S390_KMC:
+ ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
break;
- case CRYPT_Z990_KIMD:
- ret = crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0);
+ case CRYPT_S390_KIMD:
+ ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
break;
- case CRYPT_Z990_KLMD:
- ret = crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0);
+ case CRYPT_S390_KLMD:
+ ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
break;
- case CRYPT_Z990_KMAC:
- ret = crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0);
+ case CRYPT_S390_KMAC:
+ ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
break;
default:
ret = 0;
return ret;
}
if (ret >= 0){
- func &= CRYPT_Z990_FUNC_MASK;
+ func &= CRYPT_S390_FUNC_MASK;
func &= 0x7f; //mask modifier bit
if (func < 64){
ret = (status.high >> (64 - func - 1)) & 0x1;
@@ -370,5 +394,4 @@ crypt_z990_func_available(int func)
return ret;
}
-
-#endif // _CRYPTO_ARCH_S390_CRYPT_Z990_H
+#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H
diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c
new file mode 100644
index 000000000000..def02bdc44a4
--- /dev/null
+++ b/arch/s390/crypto/crypt_s390_query.c
@@ -0,0 +1,129 @@
+/*
+ * Cryptographic API.
+ *
+ * Support for s390 cryptographic instructions.
+ * Testing module for querying processor crypto capabilities.
+ *
+ * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@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 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/errno.h>
+#include "crypt_s390.h"
+
+static void query_available_functions(void)
+{
+ printk(KERN_INFO "#####################\n");
+
+ /* query available KM functions */
+ printk(KERN_INFO "KM_QUERY: %d\n",
+ crypt_s390_func_available(KM_QUERY));
+ printk(KERN_INFO "KM_DEA: %d\n",
+ crypt_s390_func_available(KM_DEA_ENCRYPT));
+ printk(KERN_INFO "KM_TDEA_128: %d\n",
+ crypt_s390_func_available(KM_TDEA_128_ENCRYPT));
+ printk(KERN_INFO "KM_TDEA_192: %d\n",
+ crypt_s390_func_available(KM_TDEA_192_ENCRYPT));
+ printk(KERN_INFO "KM_AES_128: %d\n",
+ crypt_s390_func_available(KM_AES_128_ENCRYPT));
+ printk(KERN_INFO "KM_AES_192: %d\n",
+ crypt_s390_func_available(KM_AES_192_ENCRYPT));
+ printk(KERN_INFO "KM_AES_256: %d\n",
+ crypt_s390_func_available(KM_AES_256_ENCRYPT));
+
+ /* query available KMC functions */
+ printk(KERN_INFO "KMC_QUERY: %d\n",
+ crypt_s390_func_available(KMC_QUERY));
+ printk(KERN_INFO "KMC_DEA: %d\n",
+ crypt_s390_func_available(KMC_DEA_ENCRYPT));
+ printk(KERN_INFO "KMC_TDEA_128: %d\n",
+ crypt_s390_func_available(KMC_TDEA_128_ENCRYPT));
+ printk(KERN_INFO "KMC_TDEA_192: %d\n",
+ crypt_s390_func_available(KMC_TDEA_192_ENCRYPT));
+ printk(KERN_INFO "KMC_AES_128: %d\n",
+ crypt_s390_func_available(KMC_AES_128_ENCRYPT));
+ printk(KERN_INFO "KMC_AES_192: %d\n",
+ crypt_s390_func_available(KMC_AES_192_ENCRYPT));
+ printk(KERN_INFO "KMC_AES_256: %d\n",
+ crypt_s390_func_available(KMC_AES_256_ENCRYPT));
+
+ /* query available KIMD fucntions */
+ printk(KERN_INFO "KIMD_QUERY: %d\n",
+ crypt_s390_func_available(KIMD_QUERY));
+ printk(KERN_INFO "KIMD_SHA_1: %d\n",
+ crypt_s390_func_available(KIMD_SHA_1));
+ printk(KERN_INFO "KIMD_SHA_256: %d\n",
+ crypt_s390_func_available(KIMD_SHA_256));
+
+ /* query available KLMD functions */
+ printk(KERN_INFO "KLMD_QUERY: %d\n",
+ crypt_s390_func_available(KLMD_QUERY));
+ printk(KERN_INFO "KLMD_SHA_1: %d\n",
+ crypt_s390_func_available(KLMD_SHA_1));
+ printk(KERN_INFO "KLMD_SHA_256: %d\n",
+ crypt_s390_func_available(KLMD_SHA_256));
+
+ /* query available KMAC functions */
+ printk(KERN_INFO "KMAC_QUERY: %d\n",
+ crypt_s390_func_available(KMAC_QUERY));
+ printk(KERN_INFO "KMAC_DEA: %d\n",
+ crypt_s390_func_available(KMAC_DEA));
+ printk(KERN_INFO "KMAC_TDEA_128: %d\n",
+ crypt_s390_func_available(KMAC_TDEA_128));
+ printk(KERN_INFO "KMAC_TDEA_192: %d\n",
+ crypt_s390_func_available(KMAC_TDEA_192));
+}
+
+static int init(void)
+{
+ struct crypt_s390_query_status status = {
+ .high = 0,
+ .low = 0
+ };
+
+ printk(KERN_INFO "crypt_s390: querying available crypto functions\n");
+ crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
+ printk(KERN_INFO "KM:\t%016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+ printk(KERN_INFO "KMC:\t%016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KIMD:\t%016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KLMD:\t%016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+ status.high = status.low = 0;
+ crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
+ printk(KERN_INFO "KMAC:\t%016llx %016llx\n",
+ (unsigned long long) status.high,
+ (unsigned long long) status.low);
+
+ query_available_functions();
+ return -ECANCELED;
+}
+
+static void __exit cleanup(void)
+{
+}
+
+module_init(init);
+module_exit(cleanup);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/s390/crypto/crypt_z990_query.c b/arch/s390/crypto/crypt_z990_query.c
deleted file mode 100644
index 7133983d1384..000000000000
--- a/arch/s390/crypto/crypt_z990_query.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Support for z990 cryptographic instructions.
- * Testing module for querying processor crypto capabilities.
- *
- * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@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 of the License, or (at your option)
- * any later version.
- *
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/errno.h>
-#include "crypt_z990.h"
-
-static void
-query_available_functions(void)
-{
- printk(KERN_INFO "#####################\n");
- //query available KM functions
- printk(KERN_INFO "KM_QUERY: %d\n",
- crypt_z990_func_available(KM_QUERY));
- printk(KERN_INFO "KM_DEA: %d\n",
- crypt_z990_func_available(KM_DEA_ENCRYPT));
- printk(KERN_INFO "KM_TDEA_128: %d\n",
- crypt_z990_func_available(KM_TDEA_128_ENCRYPT));
- printk(KERN_INFO "KM_TDEA_192: %d\n",
- crypt_z990_func_available(KM_TDEA_192_ENCRYPT));
- //query available KMC functions
- printk(KERN_INFO "KMC_QUERY: %d\n",
- crypt_z990_func_available(KMC_QUERY));
- printk(KERN_INFO "KMC_DEA: %d\n",
- crypt_z990_func_available(KMC_DEA_ENCRYPT));
- printk(KERN_INFO "KMC_TDEA_128: %d\n",
- crypt_z990_func_available(KMC_TDEA_128_ENCRYPT));
- printk(KERN_INFO "KMC_TDEA_192: %d\n",
- crypt_z990_func_available(KMC_TDEA_192_ENCRYPT));
- //query available KIMD fucntions
- printk(KERN_INFO "KIMD_QUERY: %d\n",
- crypt_z990_func_available(KIMD_QUERY));
- printk(KERN_INFO "KIMD_SHA_1: %d\n",
- crypt_z990_func_available(KIMD_SHA_1));
- //query available KLMD functions
- printk(KERN_INFO "KLMD_QUERY: %d\n",
- crypt_z990_func_available(KLMD_QUERY));
- printk(KERN_INFO "KLMD_SHA_1: %d\n",
- crypt_z990_func_available(KLMD_SHA_1));
- //query available KMAC functions
- printk(KERN_INFO "KMAC_QUERY: %d\n",
- crypt_z990_func_available(KMAC_QUERY));
- printk(KERN_INFO "KMAC_DEA: %d\n",
- crypt_z990_func_available(KMAC_DEA));
- printk(KERN_INFO "KMAC_TDEA_128: %d\n",
- crypt_z990_func_available(KMAC_TDEA_128));
- printk(KERN_INFO "KMAC_TDEA_192: %d\n",
- crypt_z990_func_available(KMAC_TDEA_192));
-}
-
-static int
-init(void)
-{
- struct crypt_z990_query_status status = {
- .high = 0,
- .low = 0
- };
-
- printk(KERN_INFO "crypt_z990: querying available crypto functions\n");
- crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0);
- printk(KERN_INFO "KM: %016llx %016llx\n",
- (unsigned long long) status.high,
- (unsigned long long) status.low);
- status.high = status.low = 0;
- crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0);
- printk(KERN_INFO "KMC: %016llx %016llx\n",
- (unsigned long long) status.high,
- (unsigned long long) status.low);
- status.high = status.low = 0;
- crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0);
- printk(KERN_INFO "KIMD: %016llx %016llx\n",
- (unsigned long long) status.high,
- (unsigned long long) status.low);
- status.high = status.low = 0;
- crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0);
- printk(KERN_INFO "KLMD: %016llx %016llx\n",
- (unsigned long long) status.high,
- (unsigned long long) status.low);
- status.high = status.low = 0;
- crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0);
- printk(KERN_INFO "KMAC: %016llx %016llx\n",
- (unsigned long long) status.high,
- (unsigned long long) status.low);
-
- query_available_functions();
- return -1;
-}
-
-static void __exit
-cleanup(void)
-{
-}
-
-module_init(init);
-module_exit(cleanup);
-
-MODULE_LICENSE("GPL");
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
new file mode 100644
index 000000000000..e3c37aa0a199
--- /dev/null
+++ b/arch/s390/crypto/des_s390.c
@@ -0,0 +1,466 @@
+/*
+ * Cryptographic API.
+ *
+ * s390 implementation of the DES Cipher Algorithm.
+ *
+ * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Thomas Spatzier (tspat@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 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#include "crypt_s390.h"
+#include "crypto_des.h"
+
+#define DES_BLOCK_SIZE 8
+#define DES_KEY_SIZE 8
+
+#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE)
+#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE
+
+#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE)
+#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE
+
+struct crypt_s390_des_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES_KEY_SIZE];
+};
+
+struct crypt_s390_des3_128_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES3_128_KEY_SIZE];
+};
+
+struct crypt_s390_des3_192_ctx {
+ u8 iv[DES_BLOCK_SIZE];
+ u8 key[DES3_192_KEY_SIZE];
+};
+
+static int des_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ struct crypt_s390_des_ctx *dctx = ctx;
+ int ret;
+
+ /* test if key is valid (not a weak key) */
+ ret = crypto_des_check_key(key, keylen, flags);
+ if (ret == 0)
+ memcpy(dctx->key, key, keylen);
+ return ret;
+}
+
+static void des_encrypt(void *ctx, u8 *out, const u8 *in)
+{
+ struct crypt_s390_des_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
+}
+
+static void des_decrypt(void *ctx, u8 *out, const u8 *in)
+{
+ struct crypt_s390_des_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
+}
+
+static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES_BLOCK_SIZE - 1);
+
+ memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE);
+ return nbytes;
+}
+
+static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
+ const u8 *in, unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES_BLOCK_SIZE - 1);
+
+ memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static struct crypto_alg des_alg = {
+ .cra_name = "des",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES_KEY_SIZE,
+ .cia_max_keysize = DES_KEY_SIZE,
+ .cia_setkey = des_setkey,
+ .cia_encrypt = des_encrypt,
+ .cia_decrypt = des_decrypt,
+ .cia_encrypt_ecb = des_encrypt_ecb,
+ .cia_decrypt_ecb = des_decrypt_ecb,
+ .cia_encrypt_cbc = des_encrypt_cbc,
+ .cia_decrypt_cbc = des_decrypt_cbc,
+ }
+ }
+};
+
+/*
+ * RFC2451:
+ *
+ * For DES-EDE3, there is no known need to reject weak or
+ * complementation keys. Any weakness is obviated by the use of
+ * multiple keys.
+ *
+ * However, if the two independent 64-bit keys are equal,
+ * then the DES3 operation is simply the same as DES.
+ * Implementers MUST reject keys that exhibit this property.
+ *
+ */
+static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ int i, ret;
+ struct crypt_s390_des3_128_ctx *dctx = ctx;
+ const u8* temp_key = key;
+
+ if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
+ return -EINVAL;
+ }
+ for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) {
+ ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
+ if (ret < 0)
+ return ret;
+ }
+ memcpy(dctx->key, key, keylen);
+ return 0;
+}
+
+static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_s390_des3_128_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src,
+ DES3_128_BLOCK_SIZE);
+}
+
+static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_s390_des3_128_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src,
+ DES3_128_BLOCK_SIZE);
+}
+
+static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
+
+ memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE);
+ return nbytes;
+}
+
+static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_128_BLOCK_SIZE - 1);
+
+ memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static struct crypto_alg des3_128_alg = {
+ .cra_name = "des3_ede128",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_128_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_128_KEY_SIZE,
+ .cia_max_keysize = DES3_128_KEY_SIZE,
+ .cia_setkey = des3_128_setkey,
+ .cia_encrypt = des3_128_encrypt,
+ .cia_decrypt = des3_128_decrypt,
+ .cia_encrypt_ecb = des3_128_encrypt_ecb,
+ .cia_decrypt_ecb = des3_128_decrypt_ecb,
+ .cia_encrypt_cbc = des3_128_encrypt_cbc,
+ .cia_decrypt_cbc = des3_128_decrypt_cbc,
+ }
+ }
+};
+
+/*
+ * RFC2451:
+ *
+ * For DES-EDE3, there is no known need to reject weak or
+ * complementation keys. Any weakness is obviated by the use of
+ * multiple keys.
+ *
+ * However, if the first two or last two independent 64-bit keys are
+ * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
+ * same as DES. Implementers MUST reject keys that exhibit this
+ * property.
+ *
+ */
+static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen,
+ u32 *flags)
+{
+ int i, ret;
+ struct crypt_s390_des3_192_ctx *dctx = ctx;
+ const u8* temp_key = key;
+
+ if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
+ memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
+ DES_KEY_SIZE))) {
+
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
+ return -EINVAL;
+ }
+ for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
+ ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
+ if (ret < 0)
+ return ret;
+ }
+ memcpy(dctx->key, key, keylen);
+ return 0;
+}
+
+static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_s390_des3_192_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
+ DES3_192_BLOCK_SIZE);
+}
+
+static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
+{
+ struct crypt_s390_des3_192_ctx *dctx = ctx;
+
+ crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
+ DES3_192_BLOCK_SIZE);
+}
+
+static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
+ ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
+
+ memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE);
+ return nbytes;
+}
+
+static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc,
+ u8 *out, const u8 *in,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm);
+ int ret;
+
+ /* only use complete blocks */
+ nbytes &= ~(DES3_192_BLOCK_SIZE - 1);
+
+ memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE);
+ ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes);
+ BUG_ON((ret < 0) || (ret != nbytes));
+
+ return nbytes;
+}
+
+static struct crypto_alg des3_192_alg = {
+ .cra_name = "des3_ede",
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES3_192_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES3_192_KEY_SIZE,
+ .cia_max_keysize = DES3_192_KEY_SIZE,
+ .cia_setkey = des3_192_setkey,
+ .cia_encrypt = des3_192_encrypt,
+ .cia_decrypt = des3_192_decrypt,
+ .cia_encrypt_ecb = des3_192_encrypt_ecb,
+ .cia_decrypt_ecb = des3_192_decrypt_ecb,
+ .cia_encrypt_cbc = des3_192_encrypt_cbc,
+ .cia_decrypt_cbc = des3_192_decrypt_cbc,
+ }
+ }
+};
+
+static int init(void)
+{
+ int ret = 0;
+
+ if (!crypt_s390_func_available(KM_DEA_ENCRYPT) ||
+ !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) ||
+ !crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
+ return -ENOSYS;
+
+ ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1;
+ ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2;
+ ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4;
+ if (ret) {
+ crypto_unregister_alg(&des3_192_alg);
+ crypto_unregister_alg(&des3_128_alg);
+ crypto_unregister_alg(&des_alg);
+ return -EEXIST;
+ }
+ return 0;
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&des3_192_alg);
+ crypto_unregister_alg(&des3_128_alg);
+ crypto_unregister_alg(&des_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_ALIAS("des");
+MODULE_ALIAS("des3_ede");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
diff --git a/arch/s390/crypto/des_z990.c b/arch/s390/crypto/des_z990.c
deleted file mode 100644
index 813cf37b1177..000000000000
--- a/arch/s390/crypto/des_z990.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Cryptographic API.
- *
- * z990 implementation of the DES Cipher Algorithm.
- *
- * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@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 of the License, or
- * (at your option) any later version.
- *
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <asm/scatterlist.h>
-#include <linux/crypto.h>
-#include "crypt_z990.h"
-#include "crypto_des.h"
-
-#define DES_BLOCK_SIZE 8
-#define DES_KEY_SIZE 8
-
-#define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE)
-#define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE
-
-#define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE)
-#define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE
-
-struct crypt_z990_des_ctx {
- u8 iv[DES_BLOCK_SIZE];
- u8 key[DES_KEY_SIZE];
-};
-
-struct crypt_z990_des3_128_ctx {
- u8 iv[DES_BLOCK_SIZE];
- u8 key[DES3_128_KEY_SIZE];
-};
-
-struct crypt_z990_des3_192_ctx {
- u8 iv[DES_BLOCK_SIZE];
- u8 key[DES3_192_KEY_SIZE];
-};
-
-static int
-des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
-{
- struct crypt_z990_des_ctx *dctx;
- int ret;
-
- dctx = ctx;
- //test if key is valid (not a weak key)
- ret = crypto_des_check_key(key, keylen, flags);
- if (ret == 0){
- memcpy(dctx->key, key, keylen);
- }
- return ret;
-}
-
-
-static void
-des_encrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE);
-}
-
-static void
-des_decrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE);
-}
-
-static struct crypto_alg des_alg = {
- .cra_name = "des",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = DES_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypt_z990_des_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
- .cra_u = { .cipher = {
- .cia_min_keysize = DES_KEY_SIZE,
- .cia_max_keysize = DES_KEY_SIZE,
- .cia_setkey = des_setkey,
- .cia_encrypt = des_encrypt,
- .cia_decrypt = des_decrypt } }
-};
-
-/*
- * RFC2451:
- *
- * For DES-EDE3, there is no known need to reject weak or
- * complementation keys. Any weakness is obviated by the use of
- * multiple keys.
- *
- * However, if the two independent 64-bit keys are equal,
- * then the DES3 operation is simply the same as DES.
- * Implementers MUST reject keys that exhibit this property.
- *
- */
-static int
-des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
-{
- int i, ret;
- struct crypt_z990_des3_128_ctx *dctx;
- const u8* temp_key = key;
-
- dctx = ctx;
- if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
-
- *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
- return -EINVAL;
- }
- for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) {
- ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
- if (ret < 0)
- return ret;
- }
- memcpy(dctx->key, key, keylen);
- return 0;
-}
-
-static void
-des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des3_128_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src,
- DES3_128_BLOCK_SIZE);
-}
-
-static void
-des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des3_128_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src,
- DES3_128_BLOCK_SIZE);
-}
-
-static struct crypto_alg des3_128_alg = {
- .cra_name = "des3_ede128",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = DES3_128_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypt_z990_des3_128_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list),
- .cra_u = { .cipher = {
- .cia_min_keysize = DES3_128_KEY_SIZE,
- .cia_max_keysize = DES3_128_KEY_SIZE,
- .cia_setkey = des3_128_setkey,
- .cia_encrypt = des3_128_encrypt,
- .cia_decrypt = des3_128_decrypt } }
-};
-
-/*
- * RFC2451:
- *
- * For DES-EDE3, there is no known need to reject weak or
- * complementation keys. Any weakness is obviated by the use of
- * multiple keys.
- *
- * However, if the first two or last two independent 64-bit keys are
- * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
- * same as DES. Implementers MUST reject keys that exhibit this
- * property.
- *
- */
-static int
-des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
-{
- int i, ret;
- struct crypt_z990_des3_192_ctx *dctx;
- const u8* temp_key;
-
- dctx = ctx;
- temp_key = key;
- if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
- memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
- DES_KEY_SIZE))) {
-
- *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED;
- return -EINVAL;
- }
- for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) {
- ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags);
- if (ret < 0){
- return ret;
- }
- }
- memcpy(dctx->key, key, keylen);
- return 0;
-}
-
-static void
-des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des3_192_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
- DES3_192_BLOCK_SIZE);
-}
-
-static void
-des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
-{
- struct crypt_z990_des3_192_ctx *dctx;
-
- dctx = ctx;
- crypt_z990_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
- DES3_192_BLOCK_SIZE);
-}
-
-static struct crypto_alg des3_192_alg = {
- .cra_name = "des3_ede",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
- .cra_blocksize = DES3_192_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypt_z990_des3_192_ctx),
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list),
- .cra_u = { .cipher = {
- .cia_min_keysize = DES3_192_KEY_SIZE,
- .cia_max_keysize = DES3_192_KEY_SIZE,
- .cia_setkey = des3_192_setkey,
- .cia_encrypt = des3_192_encrypt,
- .cia_decrypt = des3_192_decrypt } }
-};
-
-
-
-static int
-init(void)
-{
- int ret;
-
- if (!crypt_z990_func_available(KM_DEA_ENCRYPT) ||
- !crypt_z990_func_available(KM_TDEA_128_ENCRYPT) ||
- !crypt_z990_func_available(KM_TDEA_192_ENCRYPT)){
- return -ENOSYS;
- }
-
- ret = 0;
- ret |= (crypto_register_alg(&des_alg) == 0)? 0:1;
- ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2;
- ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4;
- if (ret){
- crypto_unregister_alg(&des3_192_alg);
- crypto_unregister_alg(&des3_128_alg);
- crypto_unregister_alg(&des_alg);
- return -EEXIST;
- }
-
- printk(KERN_INFO "crypt_z990: des_z990 loaded.\n");
- return 0;
-}
-
-static void __exit
-fini(void)
-{
- crypto_unregister_alg(&des3_192_alg);
- crypto_unregister_alg(&des3_128_alg);
- crypto_unregister_alg(&des_alg);
-}
-
-module_init(init);
-module_exit(fini);
-
-MODULE_ALIAS("des");
-MODULE_ALIAS("des3_ede");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
diff --git a/arch/s390/crypto/sha1_z990.c b/arch/s390/crypto/sha1_s390.c
index 298174ddf5b1..98c896b86dcd 100644
--- a/arch/s390/crypto/sha1_z990.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -1,7 +1,7 @@
/*
* Cryptographic API.
*
- * z990 implementation of the SHA1 Secure Hash Algorithm.
+ * s390 implementation of the SHA1 Secure Hash Algorithm.
*
* Derived from cryptoapi implementation, adapted for in-place
* scatterlist interface. Originally based on the public domain
@@ -28,22 +28,22 @@
#include <linux/crypto.h>
#include <asm/scatterlist.h>
#include <asm/byteorder.h>
-#include "crypt_z990.h"
+#include "crypt_s390.h"
#define SHA1_DIGEST_SIZE 20
#define SHA1_BLOCK_SIZE 64
-struct crypt_z990_sha1_ctx {
- u64 count;
- u32 state[5];
+struct crypt_s390_sha1_ctx {
+ u64 count;
+ u32 state[5];
u32 buf_len;
- u8 buffer[2 * SHA1_BLOCK_SIZE];
+ u8 buffer[2 * SHA1_BLOCK_SIZE];
};
static void
sha1_init(void *ctx)
{
- static const struct crypt_z990_sha1_ctx initstate = {
+ static const struct crypt_s390_sha1_ctx initstate = {
.state = {
0x67452301,
0xEFCDAB89,
@@ -58,7 +58,7 @@ sha1_init(void *ctx)
static void
sha1_update(void *ctx, const u8 *data, unsigned int len)
{
- struct crypt_z990_sha1_ctx *sctx;
+ struct crypt_s390_sha1_ctx *sctx;
long imd_len;
sctx = ctx;
@@ -69,7 +69,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len)
//complete full block and hash
memcpy(sctx->buffer + sctx->buf_len, data,
SHA1_BLOCK_SIZE - sctx->buf_len);
- crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
+ crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
SHA1_BLOCK_SIZE);
data += SHA1_BLOCK_SIZE - sctx->buf_len;
len -= SHA1_BLOCK_SIZE - sctx->buf_len;
@@ -79,7 +79,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len)
//rest of data contains full blocks?
imd_len = len & ~0x3ful;
if (imd_len){
- crypt_z990_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
+ crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
data += imd_len;
len -= imd_len;
}
@@ -92,7 +92,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len)
static void
-pad_message(struct crypt_z990_sha1_ctx* sctx)
+pad_message(struct crypt_s390_sha1_ctx* sctx)
{
int index;
@@ -113,11 +113,11 @@ pad_message(struct crypt_z990_sha1_ctx* sctx)
static void
sha1_final(void* ctx, u8 *out)
{
- struct crypt_z990_sha1_ctx *sctx = ctx;
+ struct crypt_s390_sha1_ctx *sctx = ctx;
//must perform manual padding
pad_message(sctx);
- crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
+ crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
//copy digest to out
memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
/* Wipe context */
@@ -128,7 +128,7 @@ static struct crypto_alg alg = {
.cra_name = "sha1",
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA1_BLOCK_SIZE,
- .cra_ctxsize = sizeof(struct crypt_z990_sha1_ctx),
+ .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx),
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = {
@@ -143,10 +143,10 @@ init(void)
{
int ret = -ENOSYS;
- if (crypt_z990_func_available(KIMD_SHA_1)){
+ if (crypt_s390_func_available(KIMD_SHA_1)){
ret = crypto_register_alg(&alg);
if (ret == 0){
- printk(KERN_INFO "crypt_z990: sha1_z990 loaded.\n");
+ printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n");
}
}
return ret;
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
new file mode 100644
index 000000000000..1ec5e92b3454
--- /dev/null
+++ b/arch/s390/crypto/sha256_s390.c
@@ -0,0 +1,166 @@
+/*
+ * Cryptographic API.
+ *
+ * s390 implementation of the SHA256 Secure Hash Algorithm.
+ *
+ * s390 Version:
+ * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ * Author(s): Jan Glauber (jang@de.ibm.com)
+ *
+ * Derived from "crypto/sha256.c"
+ * and "arch/s390/crypto/sha1_s390.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/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#include "crypt_s390.h"
+
+#define SHA256_DIGEST_SIZE 32
+#define SHA256_BLOCK_SIZE 64
+
+struct s390_sha256_ctx {
+ u64 count;
+ u32 state[8];
+ u8 buf[2 * SHA256_BLOCK_SIZE];
+};
+
+static void sha256_init(void *ctx)
+{
+ struct s390_sha256_ctx *sctx = ctx;
+
+ sctx->state[0] = 0x6a09e667;
+ sctx->state[1] = 0xbb67ae85;
+ sctx->state[2] = 0x3c6ef372;
+ sctx->state[3] = 0xa54ff53a;
+ sctx->state[4] = 0x510e527f;
+ sctx->state[5] = 0x9b05688c;
+ sctx->state[6] = 0x1f83d9ab;
+ sctx->state[7] = 0x5be0cd19;
+ sctx->count = 0;
+ memset(sctx->buf, 0, sizeof(sctx->buf));
+}
+
+static void sha256_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct s390_sha256_ctx *sctx = ctx;
+ unsigned int index;
+ int ret;
+
+ /* how much is already in the buffer? */
+ index = sctx->count / 8 & 0x3f;
+
+ /* update message bit length */
+ sctx->count += len * 8;
+
+ if ((index + len) < SHA256_BLOCK_SIZE)
+ goto store;
+
+ /* process one stored block */
+ if (index) {
+ memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index);
+ ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
+ SHA256_BLOCK_SIZE);
+ BUG_ON(ret != SHA256_BLOCK_SIZE);
+ data += SHA256_BLOCK_SIZE - index;
+ len -= SHA256_BLOCK_SIZE - index;
+ }
+
+ /* process as many blocks as possible */
+ if (len >= SHA256_BLOCK_SIZE) {
+ ret = crypt_s390_kimd(KIMD_SHA_256, sctx->state, data,
+ len & ~(SHA256_BLOCK_SIZE - 1));
+ BUG_ON(ret != (len & ~(SHA256_BLOCK_SIZE - 1)));
+ data += ret;
+ len -= ret;
+ }
+
+store:
+ /* anything left? */
+ if (len)
+ memcpy(sctx->buf + index , data, len);
+}
+
+static void pad_message(struct s390_sha256_ctx* sctx)
+{
+ int index, end;
+
+ index = sctx->count / 8 & 0x3f;
+ end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE;
+
+ /* start pad with 1 */
+ sctx->buf[index] = 0x80;
+
+ /* pad with zeros */
+ index++;
+ memset(sctx->buf + index, 0x00, end - index - 8);
+
+ /* append message length */
+ memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count);
+
+ sctx->count = end * 8;
+}
+
+/* Add padding and return the message digest */
+static void sha256_final(void* ctx, u8 *out)
+{
+ struct s390_sha256_ctx *sctx = ctx;
+
+ /* must perform manual padding */
+ pad_message(sctx);
+
+ crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf,
+ sctx->count / 8);
+
+ /* copy digest to out */
+ memcpy(out, sctx->state, SHA256_DIGEST_SIZE);
+
+ /* wipe context */
+ memset(sctx, 0, sizeof *sctx);
+}
+
+static struct crypto_alg alg = {
+ .cra_name = "sha256",
+ .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct s390_sha256_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(alg.cra_list),
+ .cra_u = { .digest = {
+ .dia_digestsize = SHA256_DIGEST_SIZE,
+ .dia_init = sha256_init,
+ .dia_update = sha256_update,
+ .dia_final = sha256_final } }
+};
+
+static int init(void)
+{
+ int ret;
+
+ if (!crypt_s390_func_available(KIMD_SHA_256))
+ return -ENOSYS;
+
+ ret = crypto_register_alg(&alg);
+ if (ret != 0)
+ printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded.");
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ crypto_unregister_alg(&alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_ALIAS("sha256");
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 45d44c6bb39d..7d23edc6facb 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,12 +1,12 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-rc1
-# Wed Sep 14 16:46:19 2005
+# Linux kernel version: 2.6.15-rc2
+# Mon Nov 21 13:51:30 2005
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_S390=y
+CONFIG_S390=y
CONFIG_UID16=y
#
@@ -65,15 +65,31 @@ CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# Base setup
#
#
# Processor type and features
#
-# CONFIG_ARCH_S390X is not set
# CONFIG_64BIT is not set
-CONFIG_ARCH_S390_31=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
@@ -97,6 +113,7 @@ CONFIG_FLATMEM_MANUAL=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
#
# I/O subsystem configuration
@@ -188,10 +205,18 @@ CONFIG_IPV6=y
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_CLK_JIFFIES=y
# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
CONFIG_NET_SCH_CBQ=m
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
@@ -204,8 +229,10 @@ CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_SCH_INGRESS is not set
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
+
+#
+# Classification
+#
CONFIG_NET_CLS=y
# CONFIG_NET_CLS_BASIC is not set
CONFIG_NET_CLS_TCINDEX=m
@@ -214,18 +241,18 @@ CONFIG_NET_CLS_ROUTE=y
CONFIG_NET_CLS_FW=m
CONFIG_NET_CLS_U32=m
# CONFIG_CLS_U32_PERF is not set
-# CONFIG_NET_CLS_IND is not set
CONFIG_NET_CLS_RSVP=m
CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=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
@@ -276,6 +303,7 @@ CONFIG_SCSI_FC_ATTRS=y
#
# SCSI low-level drivers
#
+# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_ZFCP=y
@@ -292,7 +320,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
# CONFIG_CDROM_PKTCDVD is not set
#
@@ -305,15 +332,8 @@ CONFIG_DASD_PROFILE=y
CONFIG_DASD_ECKD=y
CONFIG_DASD_FBA=y
CONFIG_DASD_DIAG=y
+CONFIG_DASD_EER=m
# CONFIG_DASD_CMB is not set
-
-#
-# 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
#
@@ -378,7 +398,6 @@ CONFIG_S390_TAPE_34XX=m
# CONFIG_VMLOGRDR is not set
# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
-# CONFIG_DCSS_SHM is not set
#
# Cryptographic devices
@@ -593,6 +612,8 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_RCU_TORTURE_TEST is not set
#
# Security options
@@ -609,17 +630,19 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA1_Z990 is not set
+# CONFIG_CRYPTO_SHA1_S390 is not set
# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA256_S390 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_DES_Z990 is not set
+# CONFIG_CRYPTO_DES_S390 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_AES_S390 is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
# CONFIG_CRYPTO_TEA is not set
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 7434c32bc631..9269b5788fac 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -8,31 +8,25 @@ obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
+obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
+obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+
extra-y += head.o init_task.o vmlinux.lds
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_S390_SUPPORT) += compat_linux.o compat_signal.o \
- compat_ioctl.o compat_wrapper.o \
- compat_exec_domain.o
+obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \
+ compat_wrapper.o compat_exec_domain.o
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
-obj-$(CONFIG_ARCH_S390_31) += entry.o reipl.o
-obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o
-
obj-$(CONFIG_VIRT_TIMER) += vtime.o
# Kexec part
S390_KEXEC_OBJS := machine_kexec.o crash.o
-ifeq ($(CONFIG_ARCH_S390X),y)
-S390_KEXEC_OBJS += relocate_kernel64.o
-else
-S390_KEXEC_OBJS += relocate_kernel.o
-endif
+S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o)
obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS)
-
#
# This is just to get the dependencies...
#
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index 03ba5893f17b..1f451c2cb071 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -112,7 +112,7 @@ static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs)
static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs)
{
- struct pt_regs *ptregs = __KSTK_PTREGS(tsk);
+ struct pt_regs *ptregs = task_pt_regs(tsk);
int i;
memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
deleted file mode 100644
index 6504c4e69986..000000000000
--- a/arch/s390/kernel/compat_ioctl.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * S390 version
- * Copyright (C) 2000-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Gerhard Tonn (ton@de.ibm.com)
- * Arnd Bergmann (arndb@de.ibm.com)
- *
- * Original implementation from 32-bit Sparc compat code which is
- * Copyright (C) 2000 Silicon Graphics, Inc.
- * Written by Ulf Carlsson (ulfc@engr.sgi.com)
- */
-
-#include "compat_linux.h"
-#define INCLUDES
-#define CODE
-#include "../../../fs/compat_ioctl.c"
-#include <asm/dasd.h>
-#include <asm/cmb.h>
-#include <asm/tape390.h>
-#include <asm/ccwdev.h>
-#include "../../../drivers/s390/char/raw3270.h"
-
-static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *f)
-{
- return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
-}
-
-static int do_ioctl32_ulong(unsigned int fd, unsigned int cmd,
- unsigned long arg, struct file *f)
-{
- return sys_ioctl(fd, cmd, arg);
-}
-
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_pointer)
-#define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_ulong)
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL },
-
-struct ioctl_trans ioctl_start[] = {
-/* architecture independent ioctls */
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "../../../fs/compat_ioctl.c"
-
-/* s390 only ioctls */
-COMPATIBLE_IOCTL(DASDAPIVER)
-COMPATIBLE_IOCTL(BIODASDDISABLE)
-COMPATIBLE_IOCTL(BIODASDENABLE)
-COMPATIBLE_IOCTL(BIODASDRSRV)
-COMPATIBLE_IOCTL(BIODASDRLSE)
-COMPATIBLE_IOCTL(BIODASDSLCK)
-COMPATIBLE_IOCTL(BIODASDINFO)
-COMPATIBLE_IOCTL(BIODASDINFO2)
-COMPATIBLE_IOCTL(BIODASDFMT)
-COMPATIBLE_IOCTL(BIODASDPRRST)
-COMPATIBLE_IOCTL(BIODASDQUIESCE)
-COMPATIBLE_IOCTL(BIODASDRESUME)
-COMPATIBLE_IOCTL(BIODASDPRRD)
-COMPATIBLE_IOCTL(BIODASDPSRD)
-COMPATIBLE_IOCTL(BIODASDGATTR)
-COMPATIBLE_IOCTL(BIODASDSATTR)
-COMPATIBLE_IOCTL(BIODASDCMFENABLE)
-COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
-COMPATIBLE_IOCTL(BIODASDREADALLCMB)
-
-COMPATIBLE_IOCTL(TUBICMD)
-COMPATIBLE_IOCTL(TUBOCMD)
-COMPATIBLE_IOCTL(TUBGETI)
-COMPATIBLE_IOCTL(TUBGETO)
-COMPATIBLE_IOCTL(TUBSETMOD)
-COMPATIBLE_IOCTL(TUBGETMOD)
-
-COMPATIBLE_IOCTL(TAPE390_DISPLAY)
-
-/* s390 doesn't need handlers here */
-COMPATIBLE_IOCTL(TIOCGSERIAL)
-COMPATIBLE_IOCTL(TIOCSSERIAL)
-};
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index ed877d0f27e6..bf9a7a361b34 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -55,6 +55,7 @@
#include <linux/syscalls.h>
#include <linux/sysctl.h>
#include <linux/binfmts.h>
+#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/vfs.h>
#include <linux/ptrace.h>
@@ -279,7 +280,7 @@ asmlinkage long sys32_getegid16(void)
static inline long get_tv32(struct timeval *o, struct compat_timeval *i)
{
- return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
+ return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
(__get_user(o->tv_sec, &i->tv_sec) ||
__get_user(o->tv_usec, &i->tv_usec)));
}
@@ -1014,38 +1015,6 @@ asmlinkage long sys32_clone(struct pt_regs regs)
}
/*
- * Wrapper function for sys_timer_create.
- */
-extern asmlinkage long
-sys_timer_create(clockid_t, struct sigevent *, timer_t *);
-
-asmlinkage long
-sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32,
- timer_t *timer_id)
-{
- struct sigevent se;
- timer_t ktimer_id;
- mm_segment_t old_fs;
- long ret;
-
- if (se32 == NULL)
- return sys_timer_create(which_clock, NULL, timer_id);
-
- if (get_compat_sigevent(&se, se32))
- return -EFAULT;
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_timer_create(which_clock, &se, &ktimer_id);
- set_fs(old_fs);
-
- if (!ret)
- ret = put_user (ktimer_id, timer_id);
-
- return ret;
-}
-
-/*
* 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
* These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
* because the 31 bit values differ from the 64 bit values.
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 4ff6808456ea..fa2b3bc22f20 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -467,8 +467,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
if (err)
goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
set_fs (KERNEL_DS);
do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
set_fs (old_fs);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 23fe94e58688..cfde1905d07d 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1289,7 +1289,7 @@ sys32_timer_create_wrapper:
lgfr %r2,%r2 # timer_t (int)
llgtr %r3,%r3 # struct compat_sigevent *
llgtr %r4,%r4 # timer_t *
- jg sys32_timer_create
+ jg compat_sys_timer_create
.globl sys32_timer_settime_wrapper
sys32_timer_settime_wrapper:
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index d47fecb42cc5..4ef44e536b2c 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -39,7 +39,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
if (response != NULL && rlen > 0) {
memset(response, 0, rlen);
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile ( "lra 2,0(%2)\n"
"lr 4,%3\n"
"o 4,%6\n"
@@ -55,7 +55,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
: "a" (cpcmd_buf), "d" (cmdlen),
"a" (response), "d" (rlen), "m" (mask)
: "cc", "2", "3", "4", "5" );
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile ( "lrag 2,0(%2)\n"
"lgr 4,%3\n"
"o 4,%6\n"
@@ -73,11 +73,11 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
: "a" (cpcmd_buf), "d" (cmdlen),
"a" (response), "d" (rlen), "m" (mask)
: "cc", "2", "3", "4", "5" );
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
EBCASC(response, rlen);
} else {
return_len = 0;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile ( "lra 2,0(%1)\n"
"lr 3,%2\n"
"diag 2,3,0x8\n"
@@ -85,7 +85,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
: "=d" (return_code)
: "a" (cpcmd_buf), "d" (cmdlen)
: "2", "3" );
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile ( "lrag 2,0(%1)\n"
"lgr 3,%2\n"
"sam31\n"
@@ -95,7 +95,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
: "=d" (return_code)
: "a" (cpcmd_buf), "d" (cmdlen)
: "2", "3" );
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
}
spin_unlock_irqrestore(&cpcmd_lock, flags);
if (response_code != NULL)
@@ -105,7 +105,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
EXPORT_SYMBOL(__cpcmd);
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
char *lowbuf;
@@ -129,4 +129,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
}
EXPORT_SYMBOL(cpcmd);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
index 7bd169c58b0c..926cceeae0fa 100644
--- a/arch/s390/kernel/crash.c
+++ b/arch/s390/kernel/crash.c
@@ -10,8 +10,6 @@
#include <linux/threads.h>
#include <linux/kexec.h>
-note_buf_t crash_notes[NR_CPUS];
-
void machine_crash_shutdown(struct pt_regs *regs)
{
}
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 4eb71ffcf484..369ab4413ec7 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -213,7 +213,7 @@ sysc_nr_ok:
mvc SP_ARGS(8,%r15),SP_R7(%r15)
sysc_do_restart:
larl %r10,sys_call_table
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
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
@@ -361,7 +361,7 @@ sys_clone_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs
jg sys_clone # branch to sys_clone
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_clone_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs
jg sys32_clone # branch to sys32_clone
@@ -383,7 +383,7 @@ sys_execve_glue:
bnz 0(%r12) # it did fail -> store result in gpr2
b 6(%r12) # SKIP STG 2,SP_R2(15) in
# system_call/sysc_tracesys
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_execve_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs
lgr %r12,%r14 # save return address
@@ -398,7 +398,7 @@ sys_sigreturn_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys_sigreturn # branch to sys_sigreturn
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_sigreturn_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys32_sigreturn # branch to sys32_sigreturn
@@ -408,7 +408,7 @@ sys_rt_sigreturn_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys_rt_sigreturn # branch to sys_sigreturn
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_rt_sigreturn_glue:
la %r2,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys32_rt_sigreturn # branch to sys32_sigreturn
@@ -429,7 +429,7 @@ sys_sigsuspend_glue:
la %r14,6(%r14) # skip store of return value
jg sys_sigsuspend # branch to sys_sigsuspend
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_sigsuspend_glue:
llgfr %r4,%r4 # unsigned long
lgr %r5,%r4 # move mask back
@@ -449,7 +449,7 @@ sys_rt_sigsuspend_glue:
la %r14,6(%r14) # skip store of return value
jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_rt_sigsuspend_glue:
llgfr %r3,%r3 # size_t
lgr %r4,%r3 # move sigsetsize parameter
@@ -464,7 +464,7 @@ sys_sigaltstack_glue:
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys_sigaltstack # branch to sys_sigreturn
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
sys32_sigaltstack_glue:
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys32_sigaltstack_wrapper # branch to sys_sigreturn
@@ -1009,7 +1009,7 @@ sys_call_table:
#include "syscalls.S"
#undef SYSCALL
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
#define SYSCALL(esa,esame,emu) .long emu
.globl sys_call_table_emu
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index d31a97c89f68..ea88d066bf04 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -30,7 +30,7 @@
#include <asm/thread_info.h>
#include <asm/page.h>
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
#define ARCH_OFFSET 4
#else
#define ARCH_OFFSET 0
@@ -539,7 +539,7 @@ ipl_devno:
.word 0
.endm
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
#include "head64.S"
#else
#include "head31.S"
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 5aa71b05b8ae..f0ed5c642c74 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -85,7 +85,7 @@ kexec_halt_all_cpus(void *kernel_image)
pfault_fini();
#endif
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter stopped state */
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 607d506689c8..c271cdab58e2 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -37,11 +37,11 @@
#define DEBUGP(fmt , ...)
#endif
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
#define PLT_ENTRY_SIZE 12
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define PLT_ENTRY_SIZE 20
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
void *module_alloc(unsigned long size)
{
@@ -294,17 +294,17 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
unsigned int *ip;
ip = me->module_core + me->arch.plt_offset +
info->plt_offset;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
ip[1] = 0x100607f1;
ip[2] = val;
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */
ip[1] = 0x100a0004;
ip[2] = 0x07f10000;
ip[3] = (unsigned int) (val >> 32);
ip[4] = (unsigned int) val;
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
info->plt_initialized = 1;
}
if (r_type == R_390_PLTOFF16 ||
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 78b64fe5e7c2..008c74526fd3 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -58,10 +58,18 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
*/
unsigned long thread_saved_pc(struct task_struct *tsk)
{
- struct stack_frame *sf;
+ struct stack_frame *sf, *low, *high;
- sf = (struct stack_frame *) tsk->thread.ksp;
- sf = (struct stack_frame *) sf->back_chain;
+ if (!tsk || !task_stack_page(tsk))
+ return 0;
+ low = task_stack_page(tsk);
+ high = (struct stack_frame *) task_pt_regs(tsk);
+ sf = (struct stack_frame *) (tsk->thread.ksp & PSW_ADDR_INSN);
+ if (sf <= low || sf > high)
+ return 0;
+ sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN);
+ if (sf <= low || sf > high)
+ return 0;
return sf->gprs[8];
}
@@ -153,7 +161,7 @@ void show_regs(struct pt_regs *regs)
{
struct task_struct *tsk = current;
- printk("CPU: %d %s\n", tsk->thread_info->cpu, print_tainted());
+ printk("CPU: %d %s\n", task_thread_info(tsk)->cpu, print_tainted());
printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
current->comm, current->pid, (void *) tsk,
(void *) tsk->thread.ksp);
@@ -217,8 +225,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
struct pt_regs childregs;
} *frame;
- frame = ((struct fake_frame *)
- (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+ frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
p->thread.ksp = (unsigned long) frame;
/* Store access registers to kernel stack of new process. */
frame->childregs = *regs;
@@ -235,7 +242,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
/* Save access registers to new thread structure. */
save_access_regs(&p->thread.acrs[0]);
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
/*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the child.
@@ -247,7 +254,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS)
p->thread.acrs[0] = regs->gprs[6];
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
/* Save the fpu registers to new thread structure. */
save_fp_regs(&p->thread.fp_regs);
p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
@@ -260,7 +267,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
p->thread.acrs[1] = (unsigned int) regs->gprs[6];
}
}
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/* start new process with ar4 pointing to the correct address space */
p->thread.mm_segment = get_fs();
/* Don't copy debug registers */
@@ -339,51 +346,29 @@ out:
*/
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
/*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the dump.
*/
save_fp_regs(&current->thread.fp_regs);
memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
save_fp_regs(fpregs);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return 1;
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
-
-/* changed the size calculations - should hopefully work better. lbt */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = regs->gprs[15] & ~(PAGE_SIZE - 1);
- dump->u_tsize = current->mm->end_code >> PAGE_SHIFT;
- dump->u_dsize = (current->mm->brk + PAGE_SIZE - 1) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = (TASK_SIZE - dump->start_stack) >> PAGE_SHIFT;
- memcpy(&dump->regs, regs, sizeof(s390_regs));
- dump_fpu (regs, &dump->regs.fp_regs);
- dump->regs.per_info = current->thread.per_info;
-}
-
unsigned long get_wchan(struct task_struct *p)
{
struct stack_frame *sf, *low, *high;
unsigned long return_address;
int count;
- if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info)
+ if (!p || p == current || p->state == TASK_RUNNING || !task_stack_page(p))
return 0;
- low = (struct stack_frame *) p->thread_info;
- high = (struct stack_frame *)
- ((unsigned long) p->thread_info + THREAD_SIZE) - 1;
+ low = task_stack_page(p);
+ high = (struct stack_frame *) task_pt_regs(p);
sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN);
if (sf <= low || sf > high)
return 0;
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 06afa3103ace..37dfe33dab73 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -42,7 +42,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
#include "compat_ptrace.h"
#endif
@@ -52,14 +52,14 @@ FixPerRegisters(struct task_struct *task)
struct pt_regs *regs;
per_struct *per_info;
- regs = __KSTK_PTREGS(task);
+ regs = task_pt_regs(task);
per_info = (per_struct *) &task->thread.per_info;
per_info->control_regs.bits.em_instruction_fetch =
per_info->single_step | per_info->instruction_fetch;
if (per_info->single_step) {
per_info->control_regs.bits.starting_addr = 0;
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT))
per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
else
@@ -112,7 +112,7 @@ ptrace_disable(struct task_struct *child)
clear_single_step(child);
}
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
# define __ADDR_MASK 3
#else
# define __ADDR_MASK 7
@@ -138,7 +138,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
* an alignment of 4. Programmers from hell...
*/
mask = __ADDR_MASK;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
if (addr >= (addr_t) &dummy->regs.acrs &&
addr < (addr_t) &dummy->regs.orig_gpr2)
mask = 3;
@@ -150,7 +150,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
/*
* psw and gprs are stored on the stack
*/
- tmp = *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr);
+ tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
if (addr == (addr_t) &dummy->regs.psw.mask)
/* Remove per bit from user psw. */
tmp &= ~PSW_MASK_PER;
@@ -160,7 +160,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
* access registers are stored in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.acrs;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
/*
* Very special case: old & broken 64 bit gdb reading
* from acrs[15]. Result is a 64 bit value. Read the
@@ -176,7 +176,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
/*
* orig_gpr2 is stored on the kernel stack
*/
- tmp = (addr_t) __KSTK_PTREGS(child)->orig_gpr2;
+ tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
/*
@@ -218,7 +218,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
* an alignment of 4. Programmers from hell indeed...
*/
mask = __ADDR_MASK;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
if (addr >= (addr_t) &dummy->regs.acrs &&
addr < (addr_t) &dummy->regs.orig_gpr2)
mask = 3;
@@ -231,26 +231,26 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
* psw and gprs are stored on the stack
*/
if (addr == (addr_t) &dummy->regs.psw.mask &&
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
#endif
data != PSW_MASK_MERGE(PSW_USER_BITS, data))
/* Invalid psw mask. */
return -EINVAL;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
if (addr == (addr_t) &dummy->regs.psw.addr)
/* I'd like to reject addresses without the
high order bit but older gdb's rely on it */
data |= PSW_ADDR_AMODE;
#endif
- *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr) = data;
+ *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
/*
* access registers are stored in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.acrs;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
/*
* Very special case: old & broken 64 bit gdb writing
* to acrs[15] with a 64 bit value. Ignore the lower
@@ -267,7 +267,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
/*
* orig_gpr2 is stored on the kernel stack
*/
- __KSTK_PTREGS(child)->orig_gpr2 = data;
+ task_pt_regs(child)->orig_gpr2 = data;
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
/*
@@ -357,7 +357,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
return ptrace_request(child, request, addr, data);
}
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
/*
* Now the fun part starts... a 31 bit program running in the
* 31 bit emulation tracing another program. PTRACE_PEEKTEXT,
@@ -393,15 +393,15 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
*/
if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Fake a 31 bit psw mask. */
- tmp = (__u32)(__KSTK_PTREGS(child)->psw.mask >> 32);
+ tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp);
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Fake a 31 bit psw address. */
- tmp = (__u32) __KSTK_PTREGS(child)->psw.addr |
+ tmp = (__u32) task_pt_regs(child)->psw.addr |
PSW32_ADDR_AMODE31;
} else {
/* gpr 0-15 */
- tmp = *(__u32 *)((addr_t) &__KSTK_PTREGS(child)->psw +
+ tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
addr*2 + 4);
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
@@ -415,7 +415,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
/*
* orig_gpr2 is stored on the kernel stack
*/
- tmp = *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4);
+ tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
/*
@@ -472,15 +472,15 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp))
/* Invalid psw mask. */
return -EINVAL;
- __KSTK_PTREGS(child)->psw.mask =
+ task_pt_regs(child)->psw.mask =
PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32);
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Build a 64 bit psw address from 31 bit address. */
- __KSTK_PTREGS(child)->psw.addr =
+ task_pt_regs(child)->psw.addr =
(__u64) tmp & PSW32_ADDR_INSN;
} else {
/* gpr 0-15 */
- *(__u32*)((addr_t) &__KSTK_PTREGS(child)->psw
+ *(__u32*)((addr_t) &task_pt_regs(child)->psw
+ addr*2 + 4) = tmp;
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
@@ -494,7 +494,7 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
/*
* orig_gpr2 is stored on the kernel stack
*/
- *(__u32*)((addr_t) &__KSTK_PTREGS(child)->orig_gpr2 + 4) = tmp;
+ *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
/*
@@ -629,7 +629,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
return peek_user(child, addr, data);
if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
return poke_user(child, addr, data);
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
if (request == PTRACE_PEEKUSR &&
addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
return peek_user_emu31(child, addr, data);
@@ -695,7 +695,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
/* Do requests that differ for 31/64 bit */
default:
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT))
return do_ptrace_emu31(child, request, addr, data);
#endif
@@ -712,35 +712,18 @@ sys_ptrace(long request, long pid, long addr, long data)
int ret;
lock_kernel();
-
if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- ret = -EPERM;
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- goto out;
+ ret = ptrace_traceme();
+ goto out;
}
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- 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)
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
goto out;
+ }
ret = do_ptrace(child, request, addr, data);
-
put_task_struct(child);
out:
unlock_kernel();
diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c
index 83cb42bc0b76..1f33951ba439 100644
--- a/arch/s390/kernel/reipl_diag.c
+++ b/arch/s390/kernel/reipl_diag.c
@@ -26,7 +26,7 @@ void reipl_diag(void)
" st %%r4,%0\n"
" st %%r5,%1\n"
".section __ex_table,\"a\"\n"
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
" .align 8\n"
" .quad 0b, 0b\n"
#else
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index bee654abb6d3..4176c77670c4 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -10,7 +10,6 @@
#include <linux/smp.h>
#include <linux/syscalls.h>
#include <linux/interrupt.h>
-#include <linux/ioctl32.h>
#include <asm/checksum.h>
#include <asm/cpcmd.h>
#include <asm/delay.h>
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 31e7b19348b7..de8784267473 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -268,7 +268,7 @@ static void do_machine_restart_nonsmp(char * __unused)
reipl_diag();
if (MACHINE_IS_VM)
- cpcmd ("IPL", NULL, 0);
+ cpcmd ("IPL", NULL, 0, NULL);
else
reipl (0x10000 | S390_lowcore.ipl_device);
}
@@ -276,14 +276,14 @@ static void do_machine_restart_nonsmp(char * __unused)
static void do_machine_halt_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
- cpcmd(vmhalt_cmd, NULL, 0);
+ cpcmd(vmhalt_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}
static void do_machine_power_off_nonsmp(void)
{
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
- cpcmd(vmpoff_cmd, NULL, 0);
+ cpcmd(vmpoff_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(), sigp_stop_and_store_status);
}
@@ -315,6 +315,11 @@ void machine_power_off(void)
_machine_power_off();
}
+/*
+ * Dummy power off function.
+ */
+void (*pm_power_off)(void) = machine_power_off;
+
static void __init
add_memory_hole(unsigned long start, unsigned long end)
{
@@ -427,7 +432,7 @@ setup_lowcore(void)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
lc->thread_info = (unsigned long) &init_thread_union;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) {
lc->extended_save_area_addr = (__u32)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
@@ -562,21 +567,21 @@ setup_arch(char **cmdline_p)
/*
* print what head.S has found out about the machine
*/
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
printk((MACHINE_IS_VM) ?
"We are running under VM (31 bit mode)\n" :
"We are running native (31 bit mode)\n");
printk((MACHINE_HAS_IEEE) ?
"This machine has an IEEE fpu\n" :
"This machine has no IEEE fpu\n");
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
printk((MACHINE_IS_VM) ?
"We are running under VM (64 bit mode)\n" :
"We are running native (64 bit mode)\n");
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
ROOT_DEV = Root_RAM0;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */
/*
* We need some free virtual space to be able to do vmalloc.
@@ -585,9 +590,9 @@ setup_arch(char **cmdline_p)
*/
if (memory_end > 1920*1024*1024)
memory_end = 1920*1024*1024;
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
memory_end = memory_size & ~0x200000UL; /* detected in head.s */
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) &_etext;
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 6e0110d71191..6ae4a77270b5 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -254,9 +254,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
if (restore_sigregs(regs, &frame->uc.uc_mcontext))
goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL,
+ regs->gprs[15]) == -EFAULT)
+ goto badframe;
return regs->gprs[2];
badframe:
@@ -501,7 +501,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (signr > 0) {
/* Whee! Actually deliver the signal. */
-#ifdef CONFIG_S390_SUPPORT
+#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT)) {
extern void handle_signal32(unsigned long sig,
struct k_sigaction *ka,
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 5856b3fda6bf..cbfcfd02a43a 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -263,7 +263,7 @@ static void do_machine_restart(void * __unused)
int cpu;
static atomic_t cpuid = ATOMIC_INIT(-1);
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter stopped state */
@@ -313,7 +313,7 @@ static void do_machine_halt(void * __unused)
{
static atomic_t cpuid = ATOMIC_INIT(-1);
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
smp_send_stop();
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
cpcmd(vmhalt_cmd, NULL, 0, NULL);
@@ -332,7 +332,7 @@ static void do_machine_power_off(void * __unused)
{
static atomic_t cpuid = ATOMIC_INIT(-1);
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) {
smp_send_stop();
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
cpcmd(vmpoff_cmd, NULL, 0, NULL);
@@ -402,7 +402,7 @@ static void smp_ext_bitcall_others(ec_bit_sig sig)
}
}
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
/*
* this function sends a 'purge tlb' signal to another CPU.
*/
@@ -416,7 +416,7 @@ void smp_ptlb_all(void)
on_each_cpu(smp_ptlb_callback, NULL, 0, 1);
}
EXPORT_SYMBOL(smp_ptlb_all);
-#endif /* ! CONFIG_ARCH_S390X */
+#endif /* ! CONFIG_64BIT */
/*
* this function sends a 'reschedule' IPI to another CPU.
@@ -657,7 +657,7 @@ __cpu_up(unsigned int cpu)
idle = current_set[cpu];
cpu_lowcore = lowcore_ptr[cpu];
cpu_lowcore->kernel_stack = (unsigned long)
- idle->thread_info + (THREAD_SIZE);
+ task_stack_page(idle) + (THREAD_SIZE);
sf = (struct stack_frame *) (cpu_lowcore->kernel_stack
- sizeof(struct pt_regs)
- sizeof(struct stack_frame));
@@ -783,7 +783,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
if (stack == 0ULL)
panic("smp_boot_cpus failed to allocate memory\n");
lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
-#ifndef __s390x__
+#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) {
lowcore_ptr[i]->extended_save_area_addr =
(__u32) __get_free_pages(GFP_KERNEL,0);
@@ -793,7 +793,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
#endif
}
-#ifndef __s390x__
+#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
ctl_set_bit(14, 29); /* enable extended save area */
#endif
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index efe6b83b53f7..6a63553493c5 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -26,9 +26,7 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
-#ifdef CONFIG_ARCH_S390X
#include <linux/personality.h>
-#endif /* CONFIG_ARCH_S390X */
#include <asm/uaccess.h>
#include <asm/ipc.h>
@@ -121,7 +119,7 @@ out:
return error;
}
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
struct sel_arg_struct {
unsigned long n;
fd_set *inp, *outp, *exp;
@@ -138,7 +136,7 @@ asmlinkage long old_select(struct sel_arg_struct __user *arg)
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
}
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
@@ -211,7 +209,7 @@ asmlinkage long sys_ipc(uint call, int first, unsigned long second,
return -EINVAL;
}
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
asmlinkage long s390x_newuname(struct new_utsname __user *name)
{
int ret = sys_newuname(name);
@@ -235,12 +233,12 @@ asmlinkage long s390x_personality(unsigned long personality)
return ret;
}
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/*
* Wrapper function for sys_fadvise64/fadvise64_64
*/
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asmlinkage long
s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index c36353e8c140..7c0fe152a111 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -214,7 +214,7 @@ void account_ticks(struct pt_regs *regs)
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- account_user_vtime(current);
+ account_tick_vtime(current);
#else
while (ticks--)
update_process_times(user_mode(regs));
@@ -282,7 +282,7 @@ static inline void start_hz_timer(void)
{
if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
return;
- account_ticks(__KSTK_PTREGS(current));
+ account_ticks(task_pt_regs(current));
cpu_clear(smp_processor_id(), nohz_cpu_mask);
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index c5bd36fae56b..5d21e9e6e7b4 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -67,13 +67,13 @@ extern pgm_check_handler_t do_monitor_call;
#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
#define FOURLONG "%08lx %08lx %08lx %08lx\n"
static int kstack_depth_to_print = 12;
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define FOURLONG "%016lx %016lx %016lx %016lx\n"
static int kstack_depth_to_print = 20;
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
/*
* For show_trace we have tree different stack to consider:
@@ -136,8 +136,8 @@ void show_trace(struct task_struct *task, unsigned long * stack)
sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
S390_lowcore.async_stack);
if (task)
- __show_trace(sp, (unsigned long) task->thread_info,
- (unsigned long) task->thread_info + THREAD_SIZE);
+ __show_trace(sp, (unsigned long) task_stack_page(task),
+ (unsigned long) task_stack_page(task) + THREAD_SIZE);
else
__show_trace(sp, S390_lowcore.thread_info,
S390_lowcore.thread_info + THREAD_SIZE);
@@ -240,7 +240,7 @@ char *task_show_regs(struct task_struct *task, char *buffer)
{
struct pt_regs *regs;
- regs = __KSTK_PTREGS(task);
+ regs = task_pt_regs(task);
buffer += sprintf(buffer, "task: %p, ksp: %p\n",
task, (void *)task->thread.ksp);
buffer += sprintf(buffer, "User PSW : %p %p\n",
@@ -702,12 +702,12 @@ void __init trap_init(void)
pgm_check_table[0x11] = &do_dat_exception;
pgm_check_table[0x12] = &translation_exception;
pgm_check_table[0x13] = &special_op_exception;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
pgm_check_table[0x38] = &do_dat_exception;
pgm_check_table[0x39] = &do_dat_exception;
pgm_check_table[0x3A] = &do_dat_exception;
pgm_check_table[0x3B] = &do_dat_exception;
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
pgm_check_table[0x15] = &operand_exception;
pgm_check_table[0x1C] = &space_switch_exception;
pgm_check_table[0x1D] = &hfp_sqrt_exception;
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 89fdb3808bc0..9289face3027 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -5,7 +5,7 @@
#include <asm-generic/vmlinux.lds.h>
#include <linux/config.h>
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
OUTPUT_ARCH(s390)
ENTRY(_start)
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 22a895ecb7a4..dfe6f0856617 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -32,7 +32,7 @@ DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
* Update process times based on virtual cpu times stored by entry.S
* to the lowcore fields user_timer, system_timer & steal_clock.
*/
-void account_user_vtime(struct task_struct *tsk)
+void account_tick_vtime(struct task_struct *tsk)
{
cputime_t cputime;
__u64 timer, clock;
@@ -76,6 +76,31 @@ void account_user_vtime(struct task_struct *tsk)
* Update process times based on virtual cpu times stored by entry.S
* to the lowcore fields user_timer, system_timer & steal_clock.
*/
+void account_vtime(struct task_struct *tsk)
+{
+ cputime_t cputime;
+ __u64 timer;
+
+ timer = S390_lowcore.last_update_timer;
+ asm volatile (" STPT %0" /* Store current cpu timer value */
+ : "=m" (S390_lowcore.last_update_timer) );
+ S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
+
+ cputime = S390_lowcore.user_timer >> 12;
+ S390_lowcore.user_timer -= cputime << 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_user_time(tsk, cputime);
+
+ cputime = S390_lowcore.system_timer >> 12;
+ S390_lowcore.system_timer -= cputime << 12;
+ S390_lowcore.steal_clock -= cputime << 12;
+ account_system_time(tsk, 0, cputime);
+}
+
+/*
+ * Update process times based on virtual cpu times stored by entry.S
+ * to the lowcore fields user_timer, system_timer & steal_clock.
+ */
void account_system_vtime(struct task_struct *tsk)
{
cputime_t cputime;
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index b701efa1f00e..f20b51ff1d86 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -5,5 +5,5 @@
EXTRA_AFLAGS := -traditional
lib-y += delay.o string.o
-lib-$(CONFIG_ARCH_S390_31) += uaccess.o spinlock.o
-lib-$(CONFIG_ARCH_S390X) += uaccess64.o spinlock.o
+lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
+lib-$(CONFIG_SMP) += spinlock.o \ No newline at end of file
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 2dc14e9c8327..60f80a4eed4e 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -13,7 +13,6 @@
#include <linux/init.h>
#include <asm/io.h>
-atomic_t spin_retry_counter;
int spin_retry = 1000;
/**
@@ -29,7 +28,7 @@ __setup("spin_retry=", spin_retry_setup);
static inline void
_diag44(void)
{
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
if (MACHINE_HAS_DIAG44)
#endif
asm volatile("diag 0,0,0x44");
@@ -45,7 +44,6 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
_diag44();
count = spin_retry;
}
- atomic_inc(&spin_retry_counter);
if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
return;
}
@@ -58,7 +56,6 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
int count = spin_retry;
while (count-- > 0) {
- atomic_inc(&spin_retry_counter);
if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
return 1;
}
@@ -77,7 +74,6 @@ _raw_read_lock_wait(raw_rwlock_t *rw)
_diag44();
count = spin_retry;
}
- atomic_inc(&spin_retry_counter);
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
return;
@@ -92,7 +88,6 @@ _raw_read_trylock_retry(raw_rwlock_t *rw)
int count = spin_retry;
while (count-- > 0) {
- atomic_inc(&spin_retry_counter);
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
return 1;
@@ -111,7 +106,6 @@ _raw_write_lock_wait(raw_rwlock_t *rw)
_diag44();
count = spin_retry;
}
- atomic_inc(&spin_retry_counter);
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return;
}
@@ -124,7 +118,6 @@ _raw_write_trylock_retry(raw_rwlock_t *rw)
int count = spin_retry;
while (count-- > 0) {
- atomic_inc(&spin_retry_counter);
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return 1;
}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 506a33b51e4f..a9566bcab682 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -143,7 +143,7 @@ dcss_diag (__u8 func, void *parameter,
rx = (unsigned long) parameter;
ry = (unsigned long) func;
__asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
" sam31\n" // switch to 31 bit
" diag %0,%1,0x64\n"
" sam64\n" // switch back to 64 bit
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fb2607c369ed..81ade401b073 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -31,17 +31,17 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
#define __FAIL_ADDR_MASK 0x7ffff000
#define __FIXUP_MASK 0x7fffffff
#define __SUBCODE_MASK 0x0200
#define __PF_RES_FIELD 0ULL
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define __FAIL_ADDR_MASK -4096L
#define __FIXUP_MASK ~0L
#define __SUBCODE_MASK 0x0600
#define __PF_RES_FIELD 0x8000000000000000ULL
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
#ifdef CONFIG_SYSCTL
extern int sysctl_userprocess_debug;
@@ -393,11 +393,11 @@ int pfault_init(void)
"2:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
" .long 0b,1b\n"
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
" .quad 0b,1b\n"
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
".previous"
: "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
__ctl_set_bit(0, 9);
@@ -417,11 +417,11 @@ void pfault_fini(void)
"0:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
" .long 0b,0b\n"
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
" .quad 0b,0b\n"
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
".previous"
: : "a" (&refbk), "m" (refbk) : "cc" );
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 6ec5cd981e74..df953383724d 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -44,7 +44,7 @@ void diag10(unsigned long addr)
{
if (addr >= 0x7ff00000)
return;
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
asm volatile (
" sam31\n"
" diag %0,%0,0x10\n"
@@ -106,7 +106,7 @@ extern unsigned long __initdata zholes_size[];
* paging_init() sets up the page tables
*/
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
void __init paging_init(void)
{
pgd_t * pg_dir;
@@ -175,7 +175,7 @@ void __init paging_init(void)
return;
}
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
void __init paging_init(void)
{
pgd_t * pg_dir;
@@ -256,7 +256,7 @@ void __init paging_init(void)
return;
}
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
void __init mem_init(void)
{
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index fb187e5a54b4..356257c171de 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -50,7 +50,7 @@ static inline unsigned long mmap_base(void)
static inline int mmap_is_legacy(void)
{
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
/*
* Force standard allocation for 64 bit programs.
*/
diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile
index ec349276258a..537b2d840e69 100644
--- a/arch/s390/oprofile/Makefile
+++ b/arch/s390/oprofile/Makefile
@@ -6,4 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) init.o
+oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
diff --git a/arch/s390/oprofile/backtrace.c b/arch/s390/oprofile/backtrace.c
new file mode 100644
index 000000000000..bc4b84a35cad
--- /dev/null
+++ b/arch/s390/oprofile/backtrace.c
@@ -0,0 +1,79 @@
+/**
+ * arch/s390/oprofile/backtrace.c
+ *
+ * S390 Version
+ * Copyright (C) 2005 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Author(s): Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+ */
+
+#include <linux/oprofile.h>
+
+#include <asm/processor.h> /* for struct stack_frame */
+
+static unsigned long
+__show_trace(unsigned int *depth, unsigned long sp,
+ unsigned long low, unsigned long high)
+{
+ struct stack_frame *sf;
+ struct pt_regs *regs;
+
+ while (*depth) {
+ sp = sp & PSW_ADDR_INSN;
+ if (sp < low || sp > high - sizeof(*sf))
+ return sp;
+ sf = (struct stack_frame *) sp;
+ (*depth)--;
+ oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
+
+ /* Follow the backchain. */
+ while (*depth) {
+ low = sp;
+ sp = sf->back_chain & PSW_ADDR_INSN;
+ if (!sp)
+ break;
+ if (sp <= low || sp > high - sizeof(*sf))
+ return sp;
+ sf = (struct stack_frame *) sp;
+ (*depth)--;
+ oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
+
+ }
+
+ if (*depth == 0)
+ break;
+
+ /* Zero backchain detected, check for interrupt frame. */
+ sp = (unsigned long) (sf + 1);
+ if (sp <= low || sp > high - sizeof(*regs))
+ return sp;
+ regs = (struct pt_regs *) sp;
+ (*depth)--;
+ oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN);
+ low = sp;
+ sp = regs->gprs[15];
+ }
+ return sp;
+}
+
+void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
+{
+ unsigned long head;
+ struct stack_frame* head_sf;
+
+ if (user_mode (regs))
+ return;
+
+ head = regs->gprs[15];
+ head_sf = (struct stack_frame*)head;
+
+ if (!head_sf->back_chain)
+ return;
+
+ head = head_sf->back_chain;
+
+ head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE,
+ S390_lowcore.async_stack);
+
+ __show_trace(&depth, head, S390_lowcore.thread_info,
+ S390_lowcore.thread_info + THREAD_SIZE);
+}
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index a65ead0e200a..7a995113b918 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -12,8 +12,12 @@
#include <linux/init.h>
#include <linux/errno.h>
+
+extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
+
int __init oprofile_arch_init(struct oprofile_operations* ops)
{
+ ops->backtrace = s390_backtrace;
return -ENODEV;
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 64f5ae0ff96d..01bc7d589afe 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,10 +14,6 @@ config SUPERH
gaming console. The SuperH port has a home page at
<http://www.linux-sh.org/>.
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
@@ -37,9 +33,11 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+config GENERIC_IOMAP
+ bool
+
config ARCH_MAY_HAVE_PC_FDC
bool
- default y
source "init/Kconfig"
@@ -57,24 +55,28 @@ config SH_SOLUTION_ENGINE
config SH_7751_SOLUTION_ENGINE
bool "SolutionEngine7751"
+ select CPU_SUBTYPE_SH7751
help
Select 7751 SolutionEngine if configuring for a Hitachi SH7751
evaluation board.
config SH_7300_SOLUTION_ENGINE
bool "SolutionEngine7300"
+ select CPU_SUBTYPE_SH7300
help
Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
evaluation board.
config SH_73180_SOLUTION_ENGINE
bool "SolutionEngine73180"
+ select CPU_SUBTYPE_SH73180
help
Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
evaluation board.
config SH_7751_SYSTEMH
bool "SystemH7751R"
+ select CPU_SUBTYPE_SH7751R
help
Select SystemH if you are configuring for a Renesas SystemH
7751R evaluation board.
@@ -85,27 +87,13 @@ config SH_STB1_HARP
config SH_STB1_OVERDRIVE
bool "STB1_Overdrive"
-config SH_HP620
- bool "HP620"
+config SH_HP6XX
+ bool "HP6XX"
help
- Select HP620 if configuring for a HP jornada HP620.
+ Select HP6XX if configuring for a HP jornada HP6xx.
More information (hardware only) at
<http://www.hp.com/jornada/>.
-config SH_HP680
- bool "HP680"
- help
- Select HP680 if configuring for a HP Jornada HP680.
- More information (hardware only) at
- <http://www.hp.com/jornada/products/680/>.
-
-config SH_HP690
- bool "HP690"
- help
- Select HP690 if configuring for a HP Jornada HP690.
- More information (hardware only)
- at <http://www.hp.com/jornada/products/680/>.
-
config SH_CQREEK
bool "CqREEK"
help
@@ -127,11 +115,13 @@ config SH_EC3104
config SH_SATURN
bool "Saturn"
+ select CPU_SUBTYPE_SH7604
help
Select Saturn if configuring for a SEGA Saturn.
config SH_DREAMCAST
bool "Dreamcast"
+ select CPU_SUBTYPE_SH7091
help
Select Dreamcast if configuring for a SEGA Dreamcast.
More information at
@@ -146,6 +136,7 @@ config SH_BIGSUR
config SH_SH2000
bool "SH2000"
+ select CPU_SUBTYPE_SH7709
help
SH-2000 is a single-board computer based around SH7709A chip
intended for embedded applications.
@@ -157,20 +148,22 @@ config SH_ADX
bool "ADX"
config SH_MPC1211
- bool "MPC1211"
+ bool "Interface MPC1211"
+ help
+ CTP/PCI-SH02 is a CPU module computer that is produced
+ by Interface Corporation.
+ More information at <http://www.interface.co.jp>
config SH_SH03
- bool "SH03"
+ bool "Interface CTP/PCI-SH03"
help
- CTP/PCI-SH03 is a CPU module computer that produced
+ CTP/PCI-SH03 is a CPU module computer that is produced
by Interface Corporation.
- It is compact and excellent in durability.
- It will play an active part in your factory or laboratory
- as a FA computer.
More information at <http://www.interface.co.jp>
config SH_SECUREEDGE5410
bool "SecureEdge5410"
+ select CPU_SUBTYPE_SH7751R
help
Select SecureEdge5410 if configuring for a SnapGear SH board.
This includes both the OEM SecureEdge products as well as the
@@ -178,25 +171,49 @@ config SH_SECUREEDGE5410
config SH_HS7751RVOIP
bool "HS7751RVOIP"
+ select CPU_SUBTYPE_SH7751R
help
Select HS7751RVOIP if configuring for a Renesas Technology
Sales VoIP board.
config SH_RTS7751R2D
bool "RTS7751R2D"
+ select CPU_SUBTYPE_SH7751R
help
Select RTS7751R2D if configuring for a Renesas Technology
Sales SH-Graphics board.
+config SH_R7780RP
+ bool "R7780RP-1"
+ select CPU_SUBTYPE_SH7780
+ help
+ Select R7780RP-1 if configuring for a Renesas Solutions
+ HIGHLANDER board.
+
config SH_EDOSK7705
bool "EDOSK7705"
+ select CPU_SUBTYPE_SH7705
config SH_SH4202_MICRODEV
bool "SH4-202 MicroDev"
+ select CPU_SUBTYPE_SH4_202
help
Select SH4-202 MicroDev if configuring for a SuperH MicroDev board
with an SH4-202 CPU.
+config SH_LANDISK
+ bool "LANDISK"
+ select CPU_SUBTYPE_SH7751R
+ help
+ I-O DATA DEVICE, INC. "LANDISK Series" support.
+
+config SH_TITAN
+ bool "TITAN"
+ select CPU_SUBTYPE_SH7751R
+ help
+ Select Titan if you are configuring for a Nimble Microsystems
+ NetEngine NP51R.
+
config SH_UNKNOWN
bool "BareCPU"
help
@@ -211,168 +228,27 @@ config SH_UNKNOWN
endchoice
-choice
- prompt "Processor family"
- default CPU_SH4
- help
- This option determines the CPU family to compile for. Supported
- targets are SH-2, SH-3, and SH-4. These options are independent of
- CPU functionality. As such, SH-DSP users will still want to select
- their respective processor family in addition to the DSP support
- option.
-
-config CPU_SH2
- bool "SH-2"
- select SH_WRITETHROUGH
-
-config CPU_SH3
- bool "SH-3"
-
-config CPU_SH4
- bool "SH-4"
-
-endchoice
-
-choice
- prompt "Processor subtype"
-
-config CPU_SUBTYPE_SH7604
- bool "SH7604"
- depends on CPU_SH2
- help
- Select SH7604 if you have SH7604
-
-config CPU_SUBTYPE_SH7300
- bool "SH7300"
- depends on CPU_SH3
-
-config CPU_SUBTYPE_SH7705
- bool "SH7705"
- depends on CPU_SH3
-
-config CPU_SUBTYPE_SH7707
- bool "SH7707"
- depends on CPU_SH3
- help
- Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
-
-config CPU_SUBTYPE_SH7708
- bool "SH7708"
- depends on CPU_SH3
- help
- Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
- if you have a 100 Mhz SH-3 HD6417708R CPU.
-
-config CPU_SUBTYPE_SH7709
- bool "SH7709"
- depends on CPU_SH3
- help
- Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
-
-config CPU_SUBTYPE_SH7750
- bool "SH7750"
- depends on CPU_SH4
- help
- Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
-
-config CPU_SUBTYPE_SH7751
- bool "SH7751/SH7751R"
- depends on CPU_SH4
- help
- Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
- or if you have a HD6417751R CPU.
-
-config CPU_SUBTYPE_SH7760
- bool "SH7760"
- depends on CPU_SH4
-
-config CPU_SUBTYPE_SH73180
- bool "SH73180"
- depends on CPU_SH4
-
-config CPU_SUBTYPE_ST40STB1
- bool "ST40STB1 / ST40RA"
- depends on CPU_SH4
- help
- Select ST40STB1 if you have a ST40RA CPU.
- This was previously called the ST40STB1, hence the option name.
-
-config CPU_SUBTYPE_ST40GX1
- bool "ST40GX1"
- depends on CPU_SH4
- help
- Select ST40GX1 if you have a ST40GX1 CPU.
-
-config CPU_SUBTYPE_SH4_202
- bool "SH4-202"
- depends on CPU_SH4
-
-endchoice
-
-config SH7705_CACHE_32KB
- bool "Enable 32KB cache size for SH7705"
- depends on CPU_SUBTYPE_SH7705
- default y
-
-config MMU
- bool "Support for memory management hardware"
- depends on !CPU_SH2
- default y
- help
- Early SH processors (such as the SH7604) lack an MMU. In order to
- boot on these systems, this option must not be set.
-
- On other systems (such as the SH-3 and 4) where an MMU exists,
- turning this off will boot the kernel on these machines with the
- MMU implicitly switched off.
-
-choice
- prompt "HugeTLB page size"
- depends on HUGETLB_PAGE && CPU_SH4 && MMU
- default HUGETLB_PAGE_SIZE_64K
-
-config HUGETLB_PAGE_SIZE_64K
- bool "64K"
-
-config HUGETLB_PAGE_SIZE_1MB
- bool "1MB"
-
-endchoice
-
-config CMDLINE_BOOL
- bool "Default bootloader kernel arguments"
-
-config CMDLINE
- string "Initial kernel command string"
- depends on CMDLINE_BOOL
- default "console=ttySC1,115200"
+source "arch/sh/mm/Kconfig"
-# Platform-specific memory start and size definitions
config MEMORY_START
- hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE
- default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV
- default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705)
+ hex "Physical memory start address"
+ default "0x08000000"
---help---
Computers built with Hitachi SuperH processors always
map the ROM starting at address zero. But the processor
does not specify the range that RAM takes.
The physical memory (RAM) start address will be automatically
- set to 08000000, unless you selected one of the following
- processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
- in which case the start address will be set to 0c000000.
+ set to 08000000. Other platforms, such as the Solution Engine
+ boards typically map RAM at 0C000000.
- Tweak this only when porting to a new machine which is not already
- known by the config system. Changing it from the known correct
+ Tweak this only when porting to a new machine which does not
+ already have a defconfig. Changing it from the known correct
value on any of the known systems will only lead to disaster.
config MEMORY_SIZE
- hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE
- default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000)
- default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705
- default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE)
- default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV)
- default "0x08000000" if SH_MPC1211 || SH_SH03
+ hex "Physical memory size"
+ default "0x00400000"
help
This sets the default memory size assumed by your SH kernel. It can
be overridden as normal by the 'mem=' argument on the kernel command
@@ -380,21 +256,6 @@ config MEMORY_SIZE
as 0x00400000 which was the default value before this became
configurable.
-config MEMORY_SET
- bool
- depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705)
- default y
- help
- This is an option about which you will never be asked a question.
- Therefore, I conclude that you do not exist - go away.
-
- There is a grue here.
-
-# If none of the above have set memory start/size, ask the user.
-config MEMORY_OVERRIDE
- bool "Override default load address and memory size"
-
-# XXX: break these out into the board-specific configs below
config CF_ENABLER
bool "Compact Flash Enabler support"
depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
@@ -438,10 +299,21 @@ config CF_BASE_ADDR
default "0xb8000000" if CF_AREA6
default "0xb4000000" if CF_AREA5
+menu "Processor features"
+
+config CPU_LITTLE_ENDIAN
+ bool "Little Endian"
+ help
+ Some SuperH machines can be configured for either little or big
+ endian byte order. These modes require different kernels. Say Y if
+ your machine is little endian, N if it's a big endian machine.
+
# The SH7750 RTC module is disabled in the Dreamcast
config SH_RTC
bool
- depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE
+ depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \
+ !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \
+ !SH_R7780RP
default y
help
Selecting this option will allow the Linux kernel to emulate
@@ -480,104 +352,131 @@ config SH_ADC
If unsure, say N.
-config SH_HP600
+config SH_STORE_QUEUES
+ bool "Support for Store Queues"
+ depends on CPU_SH4
+ help
+ Selecting this option will enable an in-kernel API for manipulating
+ the store queues integrated in the SH-4 processors.
+
+config CPU_HAS_INTEVT
bool
- depends on SH_HP620 || SH_HP680 || SH_HP690
- default y
-config CPU_SUBTYPE_ST40
- bool
- depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
- default y
+config CPU_HAS_PINT_IRQ
+ bool
-source "mm/Kconfig"
+config CPU_HAS_INTC2_IRQ
+ bool
-config ZERO_PAGE_OFFSET
- hex "Zero page offset"
- default "0x00001000" if !(SH_MPC1211 || SH_SH03)
- default "0x00004000" if SH_MPC1211 || SH_SH03
+config CPU_HAS_SR_RB
+ bool "CPU has SR.RB"
+ depends on CPU_SH3 || CPU_SH4
+ default y
help
- This sets the default offset of zero page.
+ This will enable the use of SR.RB register bank usage. Processors
+ that are lacking this bit must have another method in place for
+ accomplishing what is taken care of by the banked registers.
-# XXX: needs to lose subtype for system type
-config ST40_LMI_MEMORY
- bool "Memory on LMI"
- depends on CPU_SUBTYPE_ST40STB1
+ See <file:Documentation/sh/register-banks.txt> for further
+ information on SR.RB and register banking in the kernel in general.
-config MEMORY_START
- hex
- depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
- default "0x08000000"
+endmenu
-config MEMORY_SIZE
- hex
- depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
- default "0x00400000"
+menu "Timer support"
-config MEMORY_SET
- bool
- depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY
+config SH_TMU
+ bool "TMU timer support"
default y
-
-config BOOT_LINK_OFFSET
- hex "Link address offset for booting"
- default "0x00800000"
help
- This option allows you to set the link address offset of the zImage.
- This can be useful if you are on a board which has a small amount of
- memory.
+ This enables the use of the TMU as the system timer.
-config CPU_LITTLE_ENDIAN
- bool "Little Endian"
- help
- Some SuperH machines can be configured for either little or big
- endian byte order. These modes require different kernels. Say Y if
- your machine is little endian, N if it's a big endian machine.
+endmenu
-config PREEMPT
- bool "Preemptible Kernel (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
-config UBC_WAKEUP
- bool "Wakeup UBC on startup"
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+
+config SH_PCLK_FREQ_BOOL
+ bool "Set default pclk frequency"
+ default y if !SH_RTC
+ default n
+
+config SH_PCLK_FREQ
+ int "Peripheral clock frequency (in Hz)"
+ depends on SH_PCLK_FREQ_BOOL
+ default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
+ default "60000000" if CPU_SUBTYPE_SH7751
+ default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
+ default "27000000" if CPU_SUBTYPE_SH73180
+ default "66000000" if CPU_SUBTYPE_SH4_202
help
- Selecting this option will wakeup the User Break Controller (UBC) on
- startup. Although the UBC is left in an awake state when the processor
- comes up, some boot loaders misbehave by putting the UBC to sleep in a
- power saving state, which causes issues with things like ptrace().
+ This option is used to specify the peripheral clock frequency.
+ This is necessary for determining the reference clock value on
+ platforms lacking an RTC.
- If unsure, say N.
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
-config SH_WRITETHROUGH
- bool "Use write-through caching"
- default y if CPU_SH2
+config SH_CPU_FREQ
+ tristate "SuperH CPU Frequency driver"
+ depends on CPU_FREQ
+ select CPU_FREQ_TABLE
help
- Selecting this option will configure the caches in write-through
- mode, as opposed to the default write-back configuration.
+ This adds the cpufreq driver for SuperH. At present, only
+ the SH-4 is supported.
- Since there's sill some aliasing issues on SH-4, this option will
- unfortunately still require the majority of flushing functions to
- be implemented to deal with aliasing.
+ For details, take a look at <file:Documentation/cpu-freq>.
If unsure, say N.
-config SH_OCRAM
- bool "Operand Cache RAM (OCRAM) support"
+endmenu
+
+source "arch/sh/drivers/dma/Kconfig"
+
+source "arch/sh/cchips/Kconfig"
+
+config HEARTBEAT
+ bool "Heartbeat LED"
+ depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \
+ SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \
+ SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
+ SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
+ SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
help
- Selecting this option will automatically tear down the number of
- sets in the dcache by half, which in turn exposes a memory range.
+ Use the power-on LED on your machine as a load meter. The exact
+ behavior is platform-dependent, but normally the flash frequency is
+ a hyperbolic function of the 5-minute load average.
- The addresses for the OC RAM base will vary according to the
- processor version. Consult vendor documentation for specifics.
+endmenu
- If unsure, say N.
+config ISA_DMA_API
+ bool
+ depends on MPC1211
+ default y
-config SH_STORE_QUEUES
- bool "Support for Store Queues"
- depends on CPU_SH4
+menu "Kernel features"
+
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
help
- Selecting this option will enable an in-kernel API for manipulating
- the store queues integrated in the SH-4 processors.
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
+config PREEMPT
+ bool "Preemptible Kernel (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
config SMP
bool "Symmetric multi-processing support"
@@ -614,87 +513,58 @@ config NR_CPUS
This is purely to save memory - each supported CPU adds
approximately eight kilobytes to the kernel image.
-config HS7751RVOIP_CODEC
- bool "Support VoIP Codec section"
- depends on SH_HS7751RVOIP
- help
- Selecting this option will support CODEC section.
-
-config RTS7751R2D_REV11
- bool "RTS7751R2D Rev. 1.1 board support"
- depends on SH_RTS7751R2D
- help
- Selecting this option will support version rev. 1.1.
-
-config SH_PCLK_CALC
- bool
- default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180
+config CPU_HAS_SR_RB
+ bool "CPU has SR.RB"
+ depends on CPU_SH3 || CPU_SH4
default y
help
- This option will cause the PCLK value to be probed at run-time. It
- will display a notification if the probed value has greater than a
- 1% variance of the hardcoded CONFIG_SH_PCLK_FREQ.
+ This will enable the use of SR.RB register bank usage. Processors
+ that are lacking this bit must have another method in place for
+ accomplishing what is taken care of by the banked registers.
-config SH_PCLK_FREQ
- int "Peripheral clock frequency (in Hz)"
- default "50000000" if CPU_SUBTYPE_SH7750
- default "60000000" if CPU_SUBTYPE_SH7751
- default "33333333" if CPU_SUBTYPE_SH7300
- default "27000000" if CPU_SUBTYPE_SH73180
- default "66000000" if CPU_SUBTYPE_SH4_202
- default "1193182"
- help
- This option is used to specify the peripheral clock frequency. This
- option must be set for each processor in order for the kernel to
- function reliably. If no sane default exists, we use a default from
- the legacy i8254. Any discrepancies will be reported on boot time
- with an auto-probed frequency which should be considered the proper
- value for your hardware.
+ See <file:Documentation/sh/register-banks.txt> for further
+ information on SR.RB and register banking in the kernel in general.
-menu "CPU Frequency scaling"
+endmenu
-source "drivers/cpufreq/Kconfig"
+menu "Boot options"
-config SH_CPU_FREQ
- tristate "SuperH CPU Frequency driver"
- depends on CPU_FREQ
- select CPU_FREQ_TABLE
+config ZERO_PAGE_OFFSET
+ hex "Zero page offset"
+ default "0x00004000" if SH_MPC1211 || SH_SH03
+ default "0x00001000"
help
- This adds the cpufreq driver for SuperH. At present, only
- the SH-4 is supported.
-
- For details, take a look at <file:Documentation/cpu-freq>.
-
- If unsure, say N.
+ This sets the default offset of zero page.
-endmenu
+config BOOT_LINK_OFFSET
+ hex "Link address offset for booting"
+ default "0x00800000"
+ help
+ This option allows you to set the link address offset of the zImage.
+ This can be useful if you are on a board which has a small amount of
+ memory.
-source "arch/sh/drivers/dma/Kconfig"
+config UBC_WAKEUP
+ bool "Wakeup UBC on startup"
+ help
+ Selecting this option will wakeup the User Break Controller (UBC) on
+ startup. Although the UBC is left in an awake state when the processor
+ comes up, some boot loaders misbehave by putting the UBC to sleep in a
+ power saving state, which causes issues with things like ptrace().
-source "arch/sh/cchips/Kconfig"
+ If unsure, say N.
-config HEARTBEAT
- bool "Heartbeat LED"
- depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV
- help
- Use the power-on LED on your machine as a load meter. The exact
- behavior is platform-dependent, but normally the flash frequency is
- a hyperbolic function of the 5-minute load average.
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
-config RTC_9701JE
- tristate "EPSON RTC-9701JE support"
- depends on SH_RTS7751R2D
- help
- Selecting this option will support EPSON RTC-9701JE.
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttySC1,115200"
endmenu
-config ISA_DMA_API
- bool
- depends on MPC1211
- default y
-
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+menu "Bus options"
# Even on SuperH devices which don't have an ISA bus,
# this variable helps the PCMCIA modules handle
@@ -705,7 +575,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
# PCMCIA outright. -- PFM.
config ISA
bool
- default y if PCMCIA || SMC91X
+ default y if PCMCIA
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -739,10 +609,9 @@ config MCA
config SBUS
bool
-config MAPLE
- tristate "Maple Bus support"
- depends on SH_DREAMCAST
- default y
+config SUPERHYWAY
+ tristate "SuperHyway Bus support"
+ depends on CPU_SUBTYPE_SH4_202
source "arch/sh/drivers/pci/Kconfig"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index 3fab181da364..8fb31ab2c02c 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -17,7 +17,7 @@ config SH_STANDARD_BIOS
config EARLY_SCIF_CONSOLE
bool "Use early SCIF console"
- depends on CPU_SH4
+ depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS
config EARLY_PRINTK
bool "Early printk support"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 67192d6b00d8..08c9515c4806 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -17,10 +17,30 @@
cflags-y := -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml
+isa-y := any
+isa-$(CONFIG_CPU_SH2) := sh2
+isa-$(CONFIG_CPU_SH3) := sh3
+isa-$(CONFIG_CPU_SH4) := sh4
+isa-$(CONFIG_CPU_SH4A) := sh4a
+isa-$(CONFIG_CPU_SH2A) := sh2a
+
+isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp
+
+ifndef CONFIG_MMU
+isa-y := $(isa-y)-nommu
+endif
+
+ifndef CONFIG_SH_FPU
+isa-y := $(isa-y)-nofpu
+endif
+
+cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
+
cflags-$(CONFIG_CPU_SH2) += -m2
cflags-$(CONFIG_CPU_SH3) += -m3
cflags-$(CONFIG_CPU_SH4) += -m4 \
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
+cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_SH_DSP) += -Wa,-dsp
cflags-$(CONFIG_SH_KGDB) += -g
@@ -67,9 +87,7 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300
machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180
machdir-$(CONFIG_SH_STB1_HARP) := harp
machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive
-machdir-$(CONFIG_SH_HP620) := hp6xx/hp620
-machdir-$(CONFIG_SH_HP680) := hp6xx/hp680
-machdir-$(CONFIG_SH_HP690) := hp6xx/hp690
+machdir-$(CONFIG_SH_HP6XX) := hp6xx
machdir-$(CONFIG_SH_CQREEK) := cqreek
machdir-$(CONFIG_SH_DMIDA) := dmida
machdir-$(CONFIG_SH_EC3104) := ec3104
@@ -119,31 +137,39 @@ boot := arch/sh/boot
CPPFLAGS_vmlinux.lds := -traditional
+ifneq ($(KBUILD_SRC),)
+incdir-prefix := $(srctree)/include/asm-sh/
+else
+incdir-prefix :=
+endif
+
# Update machine arch and proc symlinks if something which affects
# them changed. We use .arch and .mach to indicate when they were
# updated last, otherwise make uses the target directory mtime.
include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
@echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
-ifneq ($(KBUILD_SRC),)
- $(Q)mkdir -p include/asm-sh
- $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu
-else
- $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu
-endif
+ $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
+ $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@touch $@
+# Most boards have their own mach directories. For the ones that
+# don't, just reference the parent directory so the semantics are
+# kept roughly the same.
+
include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
- @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)'
-ifneq ($(KBUILD_SRC),)
- $(Q)mkdir -p include/asm-sh
- $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach
-else
- $(Q)ln -fsn $(incdir-y) include/asm-sh/mach
-endif
+ @echo -n ' SYMLINK include/asm-sh/mach -> '
+ $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
+ $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
+ echo -e 'include/asm-sh/$(incdir-y)'; \
+ ln -fsn $(incdir-prefix)$(incdir-y) \
+ include/asm-sh/mach; \
+ else \
+ echo -e 'include/asm-sh'; \
+ ln -fsn $(incdir-prefix) include/asm-sh/mach; \
+ fi
@touch $@
-
archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
.PHONY: maketools FORCE
diff --git a/arch/sh/boards/hp6xx/Makefile b/arch/sh/boards/hp6xx/Makefile
new file mode 100644
index 000000000000..927fe0aa5dfa
--- /dev/null
+++ b/arch/sh/boards/hp6xx/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HP6xx specific parts of the kernel
+#
+
+obj-y := mach.o setup.o
+
diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile
deleted file mode 100644
index 20691dbce347..000000000000
--- a/arch/sh/boards/hp6xx/hp620/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the HP620 specific parts of the kernel
-#
-
-obj-y := mach.o setup.o
-
diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c
deleted file mode 100644
index 0392d82b4a7b..000000000000
--- a/arch/sh/boards/hp6xx/hp620/mach.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/hp620/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the HP620
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
-#include <asm/irq.h>
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_hp620 __initmv = {
- .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
-
- .mv_inb = hd64461_inb,
- .mv_inw = hd64461_inw,
- .mv_inl = hd64461_inl,
- .mv_outb = hd64461_outb,
- .mv_outw = hd64461_outw,
- .mv_outl = hd64461_outl,
-
- .mv_inb_p = hd64461_inb_p,
- .mv_inw_p = hd64461_inw,
- .mv_inl_p = hd64461_inl,
- .mv_outb_p = hd64461_outb_p,
- .mv_outw_p = hd64461_outw,
- .mv_outl_p = hd64461_outl,
-
- .mv_insb = hd64461_insb,
- .mv_insw = hd64461_insw,
- .mv_insl = hd64461_insl,
- .mv_outsb = hd64461_outsb,
- .mv_outsw = hd64461_outsw,
- .mv_outsl = hd64461_outsl,
-
- .mv_irq_demux = hd64461_irq_demux,
-};
-ALIAS_MV(hp620)
diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c
deleted file mode 100644
index 045fc5da7274..000000000000
--- a/arch/sh/boards/hp6xx/hp620/setup.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/hp620/setup.c
- *
- * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See Linux/COPYING for more information.
- *
- * Setup code for an HP620.
- * Due to similiarity with hp680/hp690 same inits are done (for now)
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <asm/hd64461/hd64461.h>
-#include <asm/io.h>
-#include <asm/hp6xx/hp6xx.h>
-#include <asm/cpu/dac.h>
-
-const char *get_system_type(void)
-{
- return "HP620";
-}
-
-int __init platform_setup(void)
-{
- u16 v;
-
- v = inw(HD64461_STBCR);
- v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
- HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
- HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
- HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
- HD64461_STBCR_SAFECKE_IST;
- outw(v, HD64461_STBCR);
-
- v = inw(HD64461_GPADR);
- v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
- outw(v, HD64461_GPADR);
-
- sh_dac_disable(DAC_SPEAKER_VOLUME);
-
- return 0;
-}
-
diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile
deleted file mode 100644
index 0beef11d9b11..000000000000
--- a/arch/sh/boards/hp6xx/hp680/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the HP680 specific parts of the kernel
-#
-
-obj-y := mach.o setup.o
-
diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile
deleted file mode 100644
index fbbe95e75f83..000000000000
--- a/arch/sh/boards/hp6xx/hp690/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the HP690 specific parts of the kernel
-#
-
-obj-y := mach.o
-
diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c
deleted file mode 100644
index 2a4c68783cd6..000000000000
--- a/arch/sh/boards/hp6xx/hp690/mach.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * linux/arch/sh/boards/hp6xx/hp690/mach.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Machine vector for the HP690
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
-#include <asm/irq.h>
-
-struct sh_machine_vector mv_hp690 __initmv = {
- .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM,
-
- .mv_inb = hd64461_inb,
- .mv_inw = hd64461_inw,
- .mv_inl = hd64461_inl,
- .mv_outb = hd64461_outb,
- .mv_outw = hd64461_outw,
- .mv_outl = hd64461_outl,
-
- .mv_inb_p = hd64461_inb_p,
- .mv_inw_p = hd64461_inw,
- .mv_inl_p = hd64461_inl,
- .mv_outb_p = hd64461_outb_p,
- .mv_outw_p = hd64461_outw,
- .mv_outl_p = hd64461_outl,
-
- .mv_insb = hd64461_insb,
- .mv_insw = hd64461_insw,
- .mv_insl = hd64461_insl,
- .mv_outsb = hd64461_outsb,
- .mv_outsw = hd64461_outsw,
- .mv_outsl = hd64461_outsl,
-
- .mv_irq_demux = hd64461_irq_demux,
-};
-ALIAS_MV(hp690)
diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/mach.c
index d73486136045..08dbba910f74 100644
--- a/arch/sh/boards/hp6xx/hp680/mach.c
+++ b/arch/sh/boards/hp6xx/mach.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/sh/boards/hp6xx/hp680/mach.c
+ * linux/arch/sh/boards/hp6xx/mach.c
*
* Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
*
@@ -8,19 +8,12 @@
*
* Machine vector for the HP680
*/
-
-#include <linux/init.h>
-
#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
+#include <asm/hd64461.h>
#include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
-#include <asm/hp6xx/io.h>
#include <asm/irq.h>
-struct sh_machine_vector mv_hp680 __initmv = {
+struct sh_machine_vector mv_hp6xx __initmv = {
.mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
.mv_inb = hd64461_inb,
@@ -50,4 +43,4 @@ struct sh_machine_vector mv_hp680 __initmv = {
.mv_irq_demux = hd64461_irq_demux,
};
-ALIAS_MV(hp680)
+ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/setup.c
index 4170190f2644..6d94a8e2e67a 100644
--- a/arch/sh/boards/hp6xx/hp680/setup.c
+++ b/arch/sh/boards/hp6xx/setup.c
@@ -11,18 +11,19 @@
#include <linux/config.h>
#include <linux/init.h>
-#include <asm/hd64461/hd64461.h>
#include <asm/io.h>
+#include <asm/hd64461.h>
#include <asm/hp6xx/hp6xx.h>
#include <asm/cpu/dac.h>
const char *get_system_type(void)
{
- return "HP680";
+ return "HP6xx";
}
int __init platform_setup(void)
{
+ u8 v8;
u16 v;
v = inw(HD64461_STBCR);
v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
@@ -30,12 +31,25 @@ int __init platform_setup(void)
HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
HD64461_STBCR_SAFECKE_IST;
+#ifndef CONFIG_HD64461_ENABLER
+ v |= HD64461_STBCR_SPC1ST;
+#endif
outw(v, HD64461_STBCR);
v = inw(HD64461_GPADR);
v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
outw(v, HD64461_GPADR);
+ outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR);
+
+#ifndef CONFIG_HD64461_ENABLER
+ outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR);
+#endif
+
+ sh_dac_output(0, DAC_SPEAKER_VOLUME);
sh_dac_disable(DAC_SPEAKER_VOLUME);
+ v8 = ctrl_inb(DACR);
+ v8 &= ~DACR_DAE;
+ ctrl_outb(v8,DACR);
return 0;
}
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
index 1762b59e9279..245f03baf762 100644
--- a/arch/sh/boards/overdrive/Makefile
+++ b/arch/sh/boards/overdrive/Makefile
@@ -2,7 +2,7 @@
# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
#
-obj-y := mach.o setup.o io.o irq.o led.o time.o
+obj-y := mach.o setup.o io.o irq.o led.o
obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
index a36ce0284ed3..94f6165d33b8 100644
--- a/arch/sh/boards/overdrive/setup.c
+++ b/arch/sh/boards/overdrive/setup.c
@@ -17,8 +17,6 @@
#include <asm/overdrive/overdrive.h>
#include <asm/overdrive/fpga.h>
-extern void od_time_init(void);
-
const char *get_system_type(void)
{
return "SH7750 Overdrive";
@@ -31,11 +29,9 @@ int __init platform_setup(void)
{
#ifdef CONFIG_PCI
init_overdrive_fpga();
- galileo_init();
+ galileo_init();
#endif
- board_time_init = od_time_init;
-
/* Enable RS232 receive buffers */
writel(0x1e, OVERDRIVE_CTRL);
}
diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c
deleted file mode 100644
index 68533690e097..000000000000
--- a/arch/sh/boards/overdrive/time.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * arch/sh/boards/overdrive/time.c
- *
- * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
- * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * STMicroelectronics Overdrive Support.
- */
-
-void od_time_init(void)
-{
- struct frqcr_data {
- unsigned short frqcr;
- struct {
- unsigned char multiplier;
- unsigned char divisor;
- } factor[3];
- };
-
- static struct frqcr_data st40_frqcr_table[] = {
- { 0x000, {{1,1}, {1,1}, {1,2}}},
- { 0x002, {{1,1}, {1,1}, {1,4}}},
- { 0x004, {{1,1}, {1,1}, {1,8}}},
- { 0x008, {{1,1}, {1,2}, {1,2}}},
- { 0x00A, {{1,1}, {1,2}, {1,4}}},
- { 0x00C, {{1,1}, {1,2}, {1,8}}},
- { 0x011, {{1,1}, {2,3}, {1,6}}},
- { 0x013, {{1,1}, {2,3}, {1,3}}},
- { 0x01A, {{1,1}, {1,2}, {1,4}}},
- { 0x01C, {{1,1}, {1,2}, {1,8}}},
- { 0x023, {{1,1}, {2,3}, {1,3}}},
- { 0x02C, {{1,1}, {1,2}, {1,8}}},
- { 0x048, {{1,2}, {1,2}, {1,4}}},
- { 0x04A, {{1,2}, {1,2}, {1,6}}},
- { 0x04C, {{1,2}, {1,2}, {1,8}}},
- { 0x05A, {{1,2}, {1,3}, {1,6}}},
- { 0x05C, {{1,2}, {1,3}, {1,6}}},
- { 0x063, {{1,2}, {1,4}, {1,4}}},
- { 0x06C, {{1,2}, {1,4}, {1,8}}},
- { 0x091, {{1,3}, {1,3}, {1,6}}},
- { 0x093, {{1,3}, {1,3}, {1,6}}},
- { 0x0A3, {{1,3}, {1,6}, {1,6}}},
- { 0x0DA, {{1,4}, {1,4}, {1,8}}},
- { 0x0DC, {{1,4}, {1,4}, {1,8}}},
- { 0x0EC, {{1,4}, {1,8}, {1,8}}},
- { 0x123, {{1,4}, {1,4}, {1,8}}},
- { 0x16C, {{1,4}, {1,8}, {1,8}}},
- };
-
- struct memclk_data {
- unsigned char multiplier;
- unsigned char divisor;
- };
- static struct memclk_data st40_memclk_table[8] = {
- {1,1}, // 000
- {1,2}, // 001
- {1,3}, // 010
- {2,3}, // 011
- {1,4}, // 100
- {1,6}, // 101
- {1,8}, // 110
- {1,8} // 111
- };
-
- unsigned long pvr;
-
- /*
- * This should probably be moved into the SH3 probing code, and then
- * use the processor structure to determine which CPU we are running
- * on.
- */
- pvr = ctrl_inl(CCN_PVR);
- printk("PVR %08x\n", pvr);
-
- if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) {
- /*
- * Unfortunatly the STB1 FRQCR values are different from the
- * 7750 ones.
- */
- struct frqcr_data *d;
- int a;
- unsigned long memclkcr;
- struct memclk_data *e;
-
- for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
- d = &st40_frqcr_table[a];
- if (d->frqcr == (frqcr & 0x1ff))
- break;
- }
- if (a == ARRAY_SIZE(st40_frqcr_table)) {
- d = st40_frqcr_table;
- printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
- }
-
- memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
- e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
-
- printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
- d->factor[0].multiplier, d->factor[0].divisor,
- d->factor[1].multiplier, d->factor[1].divisor,
- e->multiplier, e->divisor,
- d->factor[2].multiplier, d->factor[2].divisor);
-
- current_cpu_data.master_clock = current_cpu_data.module_clock *
- d->factor[2].divisor /
- d->factor[2].multiplier;
- current_cpu_data.bus_clock = current_cpu_data.master_clock *
- d->factor[1].multiplier /
- d->factor[1].divisor;
- current_cpu_data.memory_clock = current_cpu_data.master_clock *
- e->multiplier / e->divisor;
- current_cpu_data.cpu_clock = current_cpu_data.master_clock *
- d->factor[0].multiplier /
- d->factor[0].divisor;
-}
-
diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp6xx_defconfig
index c85d3655b53c..b36f102cec81 100644
--- a/arch/sh/configs/hp680_defconfig
+++ b/arch/sh/configs/hp6xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-sh
-# Wed Mar 2 15:09:41 2005
+# Linux kernel version: 2.6.15-sh
+# Wed Jan 4 15:32:56 2006
#
CONFIG_SUPERH=y
CONFIG_UID16=y
@@ -17,31 +17,36 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
CONFIG_BROKEN=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 is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_HOTPLUG is not set
+CONFIG_HOTPLUG=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=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_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
@@ -49,6 +54,24 @@ CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_MODULES is not set
#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
# System type
#
# CONFIG_SH_SOLUTION_ENGINE is not set
@@ -58,9 +81,7 @@ CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_SH_7751_SYSTEMH is not set
# CONFIG_SH_STB1_HARP is not set
# CONFIG_SH_STB1_OVERDRIVE is not set
-# CONFIG_SH_HP620 is not set
-CONFIG_SH_HP680=y
-# CONFIG_SH_HP690 is not set
+CONFIG_SH_HP6XX=y
# CONFIG_SH_CQREEK is not set
# CONFIG_SH_DMIDA is not set
# CONFIG_SH_EC3104 is not set
@@ -77,43 +98,90 @@ CONFIG_SH_HP680=y
# CONFIG_SH_RTS7751R2D is not set
# CONFIG_SH_EDOSK7705 is not set
# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
# CONFIG_SH_UNKNOWN is not set
-# CONFIG_CPU_SH2 is not set
+
+#
+# Processor selection
+#
CONFIG_CPU_SH3=y
-# CONFIG_CPU_SH4 is not set
+
+#
+# SH-2 Processor Support
+#
# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
# CONFIG_CPU_SUBTYPE_SH7300 is not set
# CONFIG_CPU_SUBTYPE_SH7705 is not set
# CONFIG_CPU_SUBTYPE_SH7707 is not set
# CONFIG_CPU_SUBTYPE_SH7708 is not set
CONFIG_CPU_SUBTYPE_SH7709=y
+
+#
+# SH-4 Processor Support
+#
# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
# CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
-# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
CONFIG_MMU=y
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
CONFIG_MEMORY_START=0x0c000000
CONFIG_MEMORY_SIZE=0x00400000
-CONFIG_MEMORY_SET=y
-# CONFIG_MEMORY_OVERRIDE is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SH_RTC=y
# CONFIG_SH_DSP is not set
CONFIG_SH_ADC=y
-CONFIG_SH_HP600=y
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CPU_LITTLE_ENDIAN=y
-# CONFIG_PREEMPT is not set
-# CONFIG_UBC_WAKEUP is not set
-# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-# CONFIG_SMP is not set
-CONFIG_SH_PCLK_CALC=y
-CONFIG_SH_PCLK_FREQ=1193182
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=22110000
#
# CPU Frequency scaling
@@ -123,7 +191,10 @@ CONFIG_SH_PCLK_FREQ=1193182
#
# DMA support
#
-# CONFIG_SH_DMA is not set
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+# CONFIG_DMA_PAGE_OPS is not set
#
# Companion Chips
@@ -132,21 +203,47 @@ CONFIG_HD6446X_SERIES=y
CONFIG_HD64461=y
# CONFIG_HD64465 is not set
CONFIG_HD64461_IRQ=36
-# CONFIG_HD64461_ENABLER is not set
+CONFIG_HD64461_IOBASE=0xb0000000
+CONFIG_HD64461_ENABLER=y
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+# Boot options
#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
# CONFIG_PCI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
#
# PC-card bridges
#
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_HD64461_PCMCIA=y
+CONFIG_HD64461_PCMCIA_SOCKETS=1
+CONFIG_PCMCIA_PROBE=y
#
# PCI Hotplug Support
@@ -160,9 +257,9 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
#
-# SH initrd options
+# Networking
#
-# CONFIG_EMBEDDED_RAMDISK is not set
+# CONFIG_NET is not set
#
# Device Drivers
@@ -173,7 +270,11 @@ CONFIG_BINFMT_ELF=y
#
# CONFIG_STANDALONE is not set
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
#
# Memory Technology Devices (MTD)
@@ -188,30 +289,20 @@ CONFIG_PREVENT_FIRMWARE_BUILD=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_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
#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-
-#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -224,6 +315,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -235,6 +327,7 @@ CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDE_GENERIC=y
CONFIG_IDE_SH=y
# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
# CONFIG_BLK_DEV_IDEDMA is not set
# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
@@ -242,9 +335,15 @@ CONFIG_IDE_SH=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# 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
@@ -252,6 +351,7 @@ CONFIG_IDE_SH=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -263,9 +363,8 @@ CONFIG_IDE_SH=y
#
#
-# Networking support
+# Network device support
#
-# CONFIG_NET is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -296,17 +395,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=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -316,6 +404,15 @@ CONFIG_SERIO=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -353,10 +450,22 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
-# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -367,10 +476,21 @@ CONFIG_LEGACY_PTY_COUNT=256
# 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
@@ -383,27 +503,35 @@ CONFIG_LEGACY_PTY_COUNT=256
# Graphics support
#
CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_HIT=y
# CONFIG_FB_VIRTUAL is not set
#
# Console display driver support
#
-# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
CONFIG_FONTS=y
# CONFIG_FONT_8x8 is not set
# CONFIG_FONT_8x16 is not set
# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
CONFIG_FONT_PEARL_8x8=y
# CONFIG_FONT_ACORN_8x8 is not set
# CONFIG_FONT_MINI_4x6 is not set
# CONFIG_FONT_SUN8x16 is not set
# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
#
# Logo configuration
@@ -414,7 +542,22 @@ CONFIG_FONT_PEARL_8x8=y
#
# Sound
#
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_SH_DAC_AUDIO=y
+CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1
#
# USB support
@@ -423,7 +566,7 @@ CONFIG_FONT_PEARL_8x8=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
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
@@ -442,25 +585,29 @@ CONFIG_FONT_PEARL_8x8=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 is not set
# CONFIG_JBD is not set
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
# CONFIG_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
@@ -471,8 +618,11 @@ CONFIG_DNOTIFY=y
#
# DOS/FAT/NT Filesystems
#
+CONFIG_FAT_FS=y
# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
@@ -481,14 +631,11 @@ CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-# 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
@@ -516,7 +663,46 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-# CONFIG_NLS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
#
# Profiling support
@@ -526,7 +712,9 @@ CONFIG_MSDOS_PARTITION=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_FRAME_POINTER is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_KGDB is not set
@@ -550,5 +738,6 @@ 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
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 96e3036ec2bb..47c3e837599b 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -3,7 +3,7 @@
*
* SuperH-specific DMA management API
*
- * Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2003, 2004, 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -15,6 +15,7 @@
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include <linux/list.h>
+#include <linux/platform_device.h>
#include <asm/dma.h>
DEFINE_SPINLOCK(dma_spin_lock);
@@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list);
struct dma_info *get_dma_info(unsigned int chan)
{
- struct list_head *pos, *tmp;
+ struct dma_info *info;
unsigned int total = 0;
/*
* Look for each DMAC's range to determine who the owner of
* the channel is.
*/
- list_for_each_safe(pos, tmp, &registered_dmac_list) {
- struct dma_info *info = list_entry(pos, struct dma_info, list);
-
+ list_for_each_entry(info, &registered_dmac_list, list) {
total += info->nr_channels;
if (chan > total)
continue;
@@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan)
return NULL;
}
+static unsigned int get_nr_channels(void)
+{
+ struct dma_info *info;
+ unsigned int nr = 0;
+
+ if (unlikely(list_empty(&registered_dmac_list)))
+ return nr;
+
+ list_for_each_entry(info, &registered_dmac_list, list)
+ nr += info->nr_channels;
+
+ return nr;
+}
+
struct dma_channel *get_dma_channel(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
@@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from,
static int dma_read_proc(char *buf, char **start, off_t off,
int len, int *eof, void *data)
{
- struct list_head *pos, *tmp;
+ struct dma_info *info;
char *p = buf;
if (list_empty(&registered_dmac_list))
@@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off,
/*
* Iterate over each registered DMAC
*/
- list_for_each_safe(pos, tmp, &registered_dmac_list) {
- struct dma_info *info = list_entry(pos, struct dma_info, list);
+ list_for_each_entry(info, &registered_dmac_list, list) {
int i;
/*
@@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off,
#endif
-int __init register_dmac(struct dma_info *info)
+int register_dmac(struct dma_info *info)
{
- int i;
+ unsigned int total_channels, i;
INIT_LIST_HEAD(&info->list);
@@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info)
BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);
+ info->pdev = platform_device_register_simple((char *)info->name, -1,
+ NULL, 0);
+ if (IS_ERR(info->pdev))
+ return PTR_ERR(info->pdev);
+
/*
* Don't touch pre-configured channels
*/
@@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info)
memset(info->channels, 0, size);
}
+ total_channels = get_nr_channels();
for (i = 0; i < info->nr_channels; i++) {
struct dma_channel *chan = info->channels + i;
chan->chan = i;
+ chan->vchan = i + total_channels;
memcpy(chan->dev_id, "Unused", 7);
@@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info)
init_MUTEX(&chan->sem);
init_waitqueue_head(&chan->wait_queue);
-#ifdef CONFIG_SYSFS
- dma_create_sysfs_files(chan);
-#endif
+ dma_create_sysfs_files(chan, info);
}
list_add(&info->list, &registered_dmac_list);
@@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info)
return 0;
}
-void __exit unregister_dmac(struct dma_info *info)
+void unregister_dmac(struct dma_info *info)
{
+ unsigned int i;
+
+ for (i = 0; i < info->nr_channels; i++)
+ dma_remove_sysfs_files(info->channels + i, info);
+
if (!(info->flags & DMAC_CHANNELS_CONFIGURED))
kfree(info->channels);
list_del(&info->list);
+ platform_device_unregister(info->pdev);
}
static int __init dma_api_init(void)
diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c
index 231e3f6fb28f..5afab6f56ec3 100644
--- a/arch/sh/drivers/dma/dma-g2.c
+++ b/arch/sh/drivers/dma/dma-g2.c
@@ -140,7 +140,7 @@ static struct dma_ops g2_dma_ops = {
};
static struct dma_info g2_dma_info = {
- .name = "G2 DMA",
+ .name = "g2_dmac",
.nr_channels = 4,
.ops = &g2_dma_ops,
.flags = DMAC_CHANNELS_TEI_CAPABLE,
@@ -160,6 +160,7 @@ static int __init g2_dma_init(void)
static void __exit g2_dma_exit(void)
{
free_irq(HW_EVENT_G2_DMA, 0);
+ unregister_dmac(&g2_dma_info);
}
subsys_initcall(g2_dma_init);
diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c
index 1c9bc45b8bcb..05a74ffdb68d 100644
--- a/arch/sh/drivers/dma/dma-isa.c
+++ b/arch/sh/drivers/dma/dma-isa.c
@@ -25,14 +25,14 @@
* such, this code is meant for only the simplest of tasks (and shouldn't be
* used in any new drivers at all).
*
- * It should also be noted that various functions here are labelled as
- * being deprecated. This is due to the fact that the ops->xfer() method is
- * the preferred way of doing things (as well as just grabbing the spinlock
- * directly). As such, any users of this interface will be warned rather
- * loudly.
+ * NOTE: ops->xfer() is the preferred way of doing things. However, there
+ * are some users of the ISA DMA API that exist in common code that we
+ * don't necessarily want to go out of our way to break, so we still
+ * allow for some compatability at that level. Any new code is strongly
+ * advised to run far away from the ISA DMA API and use the SH DMA API
+ * directly.
*/
-
-unsigned long __deprecated claim_dma_lock(void)
+unsigned long claim_dma_lock(void)
{
unsigned long flags;
@@ -42,19 +42,19 @@ unsigned long __deprecated claim_dma_lock(void)
}
EXPORT_SYMBOL(claim_dma_lock);
-void __deprecated release_dma_lock(unsigned long flags)
+void release_dma_lock(unsigned long flags)
{
spin_unlock_irqrestore(&dma_spin_lock, flags);
}
EXPORT_SYMBOL(release_dma_lock);
-void __deprecated disable_dma(unsigned int chan)
+void disable_dma(unsigned int chan)
{
/* Nothing */
}
EXPORT_SYMBOL(disable_dma);
-void __deprecated enable_dma(unsigned int chan)
+void enable_dma(unsigned int chan)
{
struct dma_info *info = get_dma_info(chan);
struct dma_channel *channel = &info->channels[chan];
diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c
index 2e1d58f2d1b9..df604975ccc8 100644
--- a/arch/sh/drivers/dma/dma-pvr2.c
+++ b/arch/sh/drivers/dma/dma-pvr2.c
@@ -80,7 +80,7 @@ static struct dma_ops pvr2_dma_ops = {
};
static struct dma_info pvr2_dma_info = {
- .name = "PowerVR 2 DMA",
+ .name = "pvr2_dmac",
.nr_channels = 1,
.ops = &pvr2_dma_ops,
.flags = DMAC_CHANNELS_TEI_CAPABLE,
@@ -98,6 +98,7 @@ static void __exit pvr2_dma_exit(void)
{
free_dma(PVR2_CASCADE_CHAN);
free_irq(HW_EVENT_PVR2_DMA, 0);
+ unregister_dmac(&pvr2_dma_info);
}
subsys_initcall(pvr2_dma_init);
diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c
index 31dacd4444b2..cca26c4c9d1b 100644
--- a/arch/sh/drivers/dma/dma-sh.c
+++ b/arch/sh/drivers/dma/dma-sh.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2000 Takashi YOSHII
* Copyright (C) 2003, 2004 Paul Mundt
+ * Copyright (C) 2005 Andriy Skulysh
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -16,51 +17,28 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <asm/dreamcast/dma.h>
#include <asm/signal.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/io.h>
#include "dma-sh.h"
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
- XMIT_SZ_64BIT,
- XMIT_SZ_8BIT,
- XMIT_SZ_16BIT,
- XMIT_SZ_32BIT,
- XMIT_SZ_256BIT,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-static unsigned int ts_shift[] = {
- [XMIT_SZ_64BIT] = 3,
- [XMIT_SZ_8BIT] = 0,
- [XMIT_SZ_16BIT] = 1,
- [XMIT_SZ_32BIT] = 2,
- [XMIT_SZ_256BIT] = 5,
-};
-
static inline unsigned int get_dmte_irq(unsigned int chan)
{
- unsigned int irq;
+ unsigned int irq = 0;
/*
* Normally we could just do DMTE0_IRQ + chan outright, though in the
* case of the 7751R, the DMTE IRQs for channels > 4 start right above
* the SCIF
*/
-
if (chan < 4) {
irq = DMTE0_IRQ + chan;
} else {
+#ifdef DMTE4_IRQ
irq = DMTE4_IRQ + chan - 4;
+#endif
}
return irq;
@@ -78,9 +56,7 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan)
{
u32 chcr = ctrl_inl(CHCR[chan->chan]);
- chcr >>= 4;
-
- return ts_shift[chcr & 0x0007];
+ return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT];
}
/*
@@ -109,8 +85,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
static int sh_dmac_request_dma(struct dma_channel *chan)
{
+ char name[32];
+
+ snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
+ chan->chan);
+
return request_irq(get_dmte_irq(chan->chan), dma_tei,
- SA_INTERRUPT, "DMAC Transfer End", chan);
+ SA_INTERRUPT, name, chan);
}
static void sh_dmac_free_dma(struct dma_channel *chan)
@@ -118,10 +99,18 @@ static void sh_dmac_free_dma(struct dma_channel *chan)
free_irq(get_dmte_irq(chan->chan), chan);
}
-static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
+static void
+sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr)
{
if (!chcr)
- chcr = RS_DUAL;
+ chcr = RS_DUAL | CHCR_IE;
+
+ if (chcr & CHCR_IE) {
+ chcr &= ~CHCR_IE;
+ chan->flags |= DMA_TEI_CAPABLE;
+ } else {
+ chan->flags &= ~DMA_TEI_CAPABLE;
+ }
ctrl_outl(chcr, CHCR[chan->chan]);
@@ -130,22 +119,32 @@ static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long ch
static void sh_dmac_enable_dma(struct dma_channel *chan)
{
- int irq = get_dmte_irq(chan->chan);
+ int irq;
u32 chcr;
chcr = ctrl_inl(CHCR[chan->chan]);
- chcr |= CHCR_DE | CHCR_IE;
+ chcr |= CHCR_DE;
+
+ if (chan->flags & DMA_TEI_CAPABLE)
+ chcr |= CHCR_IE;
+
ctrl_outl(chcr, CHCR[chan->chan]);
- enable_irq(irq);
+ if (chan->flags & DMA_TEI_CAPABLE) {
+ irq = get_dmte_irq(chan->chan);
+ enable_irq(irq);
+ }
}
static void sh_dmac_disable_dma(struct dma_channel *chan)
{
- int irq = get_dmte_irq(chan->chan);
+ int irq;
u32 chcr;
- disable_irq(irq);
+ if (chan->flags & DMA_TEI_CAPABLE) {
+ irq = get_dmte_irq(chan->chan);
+ disable_irq(irq);
+ }
chcr = ctrl_inl(CHCR[chan->chan]);
chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE);
@@ -158,7 +157,7 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
* If we haven't pre-configured the channel with special flags, use
* the defaults.
*/
- if (!(chan->flags & DMA_CONFIGURED))
+ if (unlikely(!(chan->flags & DMA_CONFIGURED)))
sh_dmac_configure_channel(chan, 0);
sh_dmac_disable_dma(chan);
@@ -178,9 +177,11 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan)
* cascading to the PVR2 DMAC. In this case, we still need to write
* SAR and DAR, regardless of value, in order for cascading to work.
*/
- if (chan->sar || (mach_is_dreamcast() && chan->chan == 2))
+ if (chan->sar || (mach_is_dreamcast() &&
+ chan->chan == PVR2_CASCADE_CHAN))
ctrl_outl(chan->sar, SAR[chan->chan]);
- if (chan->dar || (mach_is_dreamcast() && chan->chan == 2))
+ if (chan->dar || (mach_is_dreamcast() &&
+ chan->chan == PVR2_CASCADE_CHAN))
ctrl_outl(chan->dar, DAR[chan->chan]);
ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]);
@@ -198,17 +199,38 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan)
return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan);
}
-#if defined(CONFIG_CPU_SH4)
-static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#define dmaor_read_reg() ctrl_inw(DMAOR)
+#define dmaor_write_reg(data) ctrl_outw(data, DMAOR)
+#else
+#define dmaor_read_reg() ctrl_inl(DMAOR)
+#define dmaor_write_reg(data) ctrl_outl(data, DMAOR)
+#endif
+
+static inline int dmaor_reset(void)
{
- unsigned long dmaor = ctrl_inl(DMAOR);
+ unsigned long dmaor = dmaor_read_reg();
+
+ /* Try to clear the error flags first, incase they are set */
+ dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
+ dmaor_write_reg(dmaor);
- printk("DMAE: DMAOR=%lx\n", dmaor);
+ dmaor |= DMAOR_INIT;
+ dmaor_write_reg(dmaor);
- ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR);
- ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR);
- ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR);
+ /* See if we got an error again */
+ if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) {
+ printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#if defined(CONFIG_CPU_SH4)
+static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs)
+{
+ dmaor_reset();
disable_irq(irq);
return IRQ_HANDLED;
@@ -224,8 +246,8 @@ static struct dma_ops sh_dmac_ops = {
};
static struct dma_info sh_dmac_info = {
- .name = "SuperH DMAC",
- .nr_channels = 4,
+ .name = "sh_dmac",
+ .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS,
.ops = &sh_dmac_ops,
.flags = DMAC_CHANNELS_TEI_CAPABLE,
};
@@ -248,7 +270,13 @@ static int __init sh_dmac_init(void)
make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
}
- ctrl_outl(0x8000 | DMAOR_DME, DMAOR);
+ /*
+ * Initialize DMAOR, and clean up any error flags that may have
+ * been set.
+ */
+ i = dmaor_reset();
+ if (i < 0)
+ return i;
return register_dmac(info);
}
@@ -258,10 +286,12 @@ static void __exit sh_dmac_exit(void)
#ifdef CONFIG_CPU_SH4
free_irq(DMAE_IRQ, 0);
#endif
+ unregister_dmac(&sh_dmac_info);
}
subsys_initcall(sh_dmac_init);
module_exit(sh_dmac_exit);
+MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh");
+MODULE_DESCRIPTION("SuperH On-Chip DMAC Support");
MODULE_LICENSE("GPL");
-
diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h
index dd9d547539a2..0f591fbc922d 100644
--- a/arch/sh/drivers/dma/dma-sh.h
+++ b/arch/sh/drivers/dma/dma-sh.h
@@ -11,6 +11,8 @@
#ifndef __DMA_SH_H
#define __DMA_SH_H
+#include <asm/cpu/dma.h>
+
/* Definitions for the SuperH DMAC */
#define REQ_L 0x00000000
#define REQ_E 0x00080000
@@ -26,27 +28,47 @@
#define SM_DEC 0x00002000
#define RS_IN 0x00000200
#define RS_OUT 0x00000300
-#define TM_BURST 0x0000080
-#define TS_8 0x00000010
-#define TS_16 0x00000020
-#define TS_32 0x00000030
-#define TS_64 0x00000000
#define TS_BLK 0x00000040
#define CHCR_DE 0x00000001
#define CHCR_TE 0x00000002
#define CHCR_IE 0x00000004
-/* Define the default configuration for dual address memory-memory transfer.
- * The 0x400 value represents auto-request, external->external.
- */
-#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
-
-#define DMAOR_COD 0x00000008
+/* DMAOR definitions */
#define DMAOR_AE 0x00000004
#define DMAOR_NMIF 0x00000002
#define DMAOR_DME 0x00000001
+/*
+ * Define the default configuration for dual address memory-memory transfer.
+ * The 0x400 value represents auto-request, external->external.
+ */
+#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32)
+
#define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS)
+/*
+ * Subtypes that have fewer channels than this simply need to change
+ * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number
+ * of channels should expand on this.
+ *
+ * For most subtypes we can easily figure these values out with some
+ * basic calculation, unfortunately on other subtypes these are more
+ * scattered, so we just leave it unrolled for simplicity.
+ */
+#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \
+ SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \
+ SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60})
+#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \
+ SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \
+ SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64})
+#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \
+ SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \
+ SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68})
+#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \
+ SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \
+ SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c})
+
+#define DMAOR (SH_DMAC_BASE + 0x40)
+
#endif /* __DMA_SH_H */
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index 6e3b58bd8795..70a5d82eb2f8 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -3,7 +3,7 @@
*
* sysfs interface for SH DMA API
*
- * Copyright (C) 2004 Paul Mundt
+ * Copyright (C) 2004, 2005 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -12,7 +12,9 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sysdev.h>
+#include <linux/platform_device.h>
#include <linux/module.h>
+#include <linux/err.h>
#include <linux/string.h>
#include <asm/dma.h>
@@ -77,7 +79,7 @@ static ssize_t dma_store_config(struct sys_device *dev,
unsigned long config;
config = simple_strtoul(buf, NULL, 0);
- dma_configure_channel(channel->chan, config);
+ dma_configure_channel(channel->vchan, config);
return count;
}
@@ -111,12 +113,13 @@ static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL);
dma_ro_attr(count, "0x%08x\n");
dma_ro_attr(flags, "0x%08lx\n");
-int __init dma_create_sysfs_files(struct dma_channel *chan)
+int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info)
{
struct sys_device *dev = &chan->dev;
+ char name[16];
int ret;
- dev->id = chan->chan;
+ dev->id = chan->vchan;
dev->cls = &dma_sysclass;
ret = sysdev_register(dev);
@@ -129,6 +132,24 @@ int __init dma_create_sysfs_files(struct dma_channel *chan)
sysdev_create_file(dev, &attr_flags);
sysdev_create_file(dev, &attr_config);
- return 0;
+ snprintf(name, sizeof(name), "dma%d", chan->chan);
+ return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name);
+}
+
+void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info)
+{
+ struct sys_device *dev = &chan->dev;
+ char name[16];
+
+ sysdev_remove_file(dev, &attr_dev_id);
+ sysdev_remove_file(dev, &attr_count);
+ sysdev_remove_file(dev, &attr_mode);
+ sysdev_remove_file(dev, &attr_flags);
+ sysdev_remove_file(dev, &attr_config);
+
+ snprintf(name, sizeof(name), "dma%d", chan->chan);
+ sysfs_remove_link(&info->pdev->dev.kobj, name);
+
+ sysdev_unregister(dev);
}
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 8b819698df14..7a86eeb22655 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -17,6 +17,4 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o
obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-
-USE_STANDARD_AS_RULE := true
-
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index cd43714df61a..5bfc33bec5d0 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -2,15 +2,12 @@
# Makefile for the Linux/SuperH CPU-specifc backends.
#
-obj-y := irq_ipr.o irq_imask.o init.o bus.o
+obj-y += irq/ init.o bus.o clock.o
obj-$(CONFIG_CPU_SH2) += sh2/
obj-$(CONFIG_CPU_SH3) += sh3/
obj-$(CONFIG_CPU_SH4) += sh4/
-obj-$(CONFIG_SH_RTC) += rtc.o
+obj-$(CONFIG_SH_RTC) += rtc.o
obj-$(CONFIG_UBC_WAKEUP) += ubc.o
-obj-$(CONFIG_SH_ADC) += adc.o
-
-USE_STANDARD_AS_RULE := true
-
+obj-$(CONFIG_SH_ADC) += adc.o
diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c
index d4fee2a79373..fc6c4bd40c65 100644
--- a/arch/sh/kernel/cpu/bus.c
+++ b/arch/sh/kernel/cpu/bus.c
@@ -53,21 +53,6 @@ static int sh_bus_resume(struct device *dev)
return 0;
}
-static struct device sh_bus_devices[SH_NR_BUSES] = {
- {
- .bus_id = SH_BUS_NAME_VIRT,
- },
-};
-
-struct bus_type sh_bus_types[SH_NR_BUSES] = {
- {
- .name = SH_BUS_NAME_VIRT,
- .match = sh_bus_match,
- .suspend = sh_bus_suspend,
- .resume = sh_bus_resume,
- },
-};
-
static int sh_device_probe(struct device *dev)
{
struct sh_dev *shdev = to_sh_dev(dev);
@@ -90,6 +75,23 @@ static int sh_device_remove(struct device *dev)
return 0;
}
+static struct device sh_bus_devices[SH_NR_BUSES] = {
+ {
+ .bus_id = SH_BUS_NAME_VIRT,
+ },
+};
+
+struct bus_type sh_bus_types[SH_NR_BUSES] = {
+ {
+ .name = SH_BUS_NAME_VIRT,
+ .match = sh_bus_match,
+ .probe = sh_bus_probe,
+ .remove = sh_bus_remove,
+ .suspend = sh_bus_suspend,
+ .resume = sh_bus_resume,
+ },
+};
+
int sh_device_register(struct sh_dev *dev)
{
if (!dev)
@@ -107,6 +109,8 @@ int sh_device_register(struct sh_dev *dev)
/* This is needed for USB OHCI to work */
if (dev->dma_mask)
dev->dev.dma_mask = dev->dma_mask;
+ if (dev->coherent_dma_mask)
+ dev->dev.coherent_dma_mask = dev->coherent_dma_mask;
snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u",
dev->name, dev->dev_id);
@@ -133,8 +137,6 @@ int sh_driver_register(struct sh_driver *drv)
return -EINVAL;
}
- drv->drv.probe = sh_device_probe;
- drv->drv.remove = sh_device_remove;
drv->drv.bus = &sh_bus_types[drv->bus_id];
return driver_register(&drv->drv);
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
new file mode 100644
index 000000000000..989e7fdd524d
--- /dev/null
+++ b/arch/sh/kernel/cpu/clock.c
@@ -0,0 +1,287 @@
+/*
+ * arch/sh/kernel/cpu/clock.c - SuperH clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This clock framework is derived from the OMAP version by:
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
+#include <asm/clock.h>
+#include <asm/timer.h>
+
+static LIST_HEAD(clock_list);
+static DEFINE_SPINLOCK(clock_lock);
+static DECLARE_MUTEX(clock_list_sem);
+
+/*
+ * Each subtype is expected to define the init routines for these clocks,
+ * as each subtype (or processor family) will have these clocks at the
+ * very least. These are all provided through the CPG, which even some of
+ * the more quirky parts (such as ST40, SH4-202, etc.) still have.
+ *
+ * The processor-specific code is expected to register any additional
+ * clock sources that are of interest.
+ */
+static struct clk master_clk = {
+ .name = "master_clk",
+ .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
+#ifdef CONFIG_SH_PCLK_FREQ_BOOL
+ .rate = CONFIG_SH_PCLK_FREQ,
+#endif
+};
+
+static struct clk module_clk = {
+ .name = "module_clk",
+ .parent = &master_clk,
+ .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
+};
+
+static struct clk bus_clk = {
+ .name = "bus_clk",
+ .parent = &master_clk,
+ .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
+};
+
+static struct clk cpu_clk = {
+ .name = "cpu_clk",
+ .parent = &master_clk,
+ .flags = CLK_ALWAYS_ENABLED,
+};
+
+/*
+ * The ordering of these clocks matters, do not change it.
+ */
+static struct clk *onchip_clocks[] = {
+ &master_clk,
+ &module_clk,
+ &bus_clk,
+ &cpu_clk,
+};
+
+static void propagate_rate(struct clk *clk)
+{
+ struct clk *clkp;
+
+ list_for_each_entry(clkp, &clock_list, node) {
+ if (likely(clkp->parent != clk))
+ continue;
+ if (likely(clkp->ops && clkp->ops->recalc))
+ clkp->ops->recalc(clkp);
+ }
+}
+
+int __clk_enable(struct clk *clk)
+{
+ /*
+ * See if this is the first time we're enabling the clock, some
+ * clocks that are always enabled still require "special"
+ * initialization. This is especially true if the clock mode
+ * changes and the clock needs to hunt for the proper set of
+ * divisors to use before it can effectively recalc.
+ */
+ if (unlikely(atomic_read(&clk->kref.refcount) == 1))
+ if (clk->ops && clk->ops->init)
+ clk->ops->init(clk);
+
+ if (clk->flags & CLK_ALWAYS_ENABLED)
+ return 0;
+
+ if (likely(clk->ops && clk->ops->enable))
+ clk->ops->enable(clk);
+
+ kref_get(&clk->kref);
+ return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ ret = __clk_enable(clk);
+ spin_unlock_irqrestore(&clock_lock, flags);
+
+ return ret;
+}
+
+static void clk_kref_release(struct kref *kref)
+{
+ /* Nothing to do */
+}
+
+void __clk_disable(struct clk *clk)
+{
+ if (clk->flags & CLK_ALWAYS_ENABLED)
+ return;
+
+ kref_put(&clk->kref, clk_kref_release);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clock_lock, flags);
+}
+
+int clk_register(struct clk *clk)
+{
+ down(&clock_list_sem);
+
+ list_add(&clk->node, &clock_list);
+ kref_init(&clk->kref);
+
+ up(&clock_list_sem);
+
+ return 0;
+}
+
+void clk_unregister(struct clk *clk)
+{
+ down(&clock_list_sem);
+ list_del(&clk->node);
+ up(&clock_list_sem);
+}
+
+inline unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int ret = -EOPNOTSUPP;
+
+ if (likely(clk->ops && clk->ops->set_rate)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ ret = clk->ops->set_rate(clk, rate);
+ spin_unlock_irqrestore(&clock_lock, flags);
+ }
+
+ if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+ propagate_rate(clk);
+
+ return ret;
+}
+
+void clk_recalc_rate(struct clk *clk)
+{
+ if (likely(clk->ops && clk->ops->recalc)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_lock, flags);
+ clk->ops->recalc(clk);
+ spin_unlock_irqrestore(&clock_lock, flags);
+ }
+
+ if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
+ propagate_rate(clk);
+}
+
+struct clk *clk_get(const char *id)
+{
+ struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+ down(&clock_list_sem);
+ list_for_each_entry(p, &clock_list, node) {
+ if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+ up(&clock_list_sem);
+
+ return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+ if (clk && !IS_ERR(clk))
+ module_put(clk->owner);
+}
+
+void __init __attribute__ ((weak))
+arch_init_clk_ops(struct clk_ops **ops, int type)
+{
+}
+
+int __init clk_init(void)
+{
+ int i, ret = 0;
+
+ if (unlikely(!master_clk.rate))
+ /*
+ * NOTE: This will break if the default divisor has been
+ * changed.
+ *
+ * No one should be changing the default on us however,
+ * expect that a sane value for CONFIG_SH_PCLK_FREQ will
+ * be defined in the event of a different divisor.
+ */
+ master_clk.rate = get_timer_frequency() * 4;
+
+ for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
+ struct clk *clk = onchip_clocks[i];
+
+ arch_init_clk_ops(&clk->ops, i);
+ ret |= clk_register(clk);
+ clk_enable(clk);
+ }
+
+ /* Kick the child clocks.. */
+ propagate_rate(&master_clk);
+ propagate_rate(&bus_clk);
+
+ return ret;
+}
+
+int show_clocks(struct seq_file *m)
+{
+ struct clk *clk;
+
+ list_for_each_entry_reverse(clk, &clock_list, node) {
+ unsigned long rate = clk_get_rate(clk);
+
+ /*
+ * Don't bother listing dummy clocks with no ancestry
+ * that only support enable and disable ops.
+ */
+ if (unlikely(!rate && !clk->parent))
+ continue;
+
+ seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name,
+ rate / 1000000, (rate % 1000000) / 10000);
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(clk_register);
+EXPORT_SYMBOL_GPL(clk_unregister);
+EXPORT_SYMBOL_GPL(clk_get);
+EXPORT_SYMBOL_GPL(clk_put);
+EXPORT_SYMBOL_GPL(clk_enable);
+EXPORT_SYMBOL_GPL(clk_disable);
+EXPORT_SYMBOL_GPL(__clk_enable);
+EXPORT_SYMBOL_GPL(__clk_disable);
+EXPORT_SYMBOL_GPL(clk_get_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_recalc_rate);
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
new file mode 100644
index 000000000000..e3cccea15e1d
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
+#
+obj-y += ipr.o imask.o
+
+obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
+obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq/imask.c
index a963d00a971e..baed9a550d39 100644
--- a/arch/sh/kernel/cpu/irq_imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -1,16 +1,12 @@
-/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
- *
- * linux/arch/sh/kernel/irq_imask.c
+/*
+ * arch/sh/kernel/cpu/irq/imask.c
*
* Copyright (C) 1999, 2000 Niibe Yutaka
*
* Simple interrupt handling using IMASK of SR register.
*
*/
-
/* NOTE: Will not work on level 15 */
-
-
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/kernel_stat.h>
@@ -19,13 +15,11 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/irq.h>
/* Bitmap of IRQ masked */
static unsigned long imask_mask = 0x7fff;
@@ -40,7 +34,7 @@ static void end_imask_irq(unsigned int irq);
#define IMASK_PRIORITY 15
static unsigned int startup_imask_irq(unsigned int irq)
-{
+{
/* Nothing to do */
return 0; /* never anything pending */
}
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
new file mode 100644
index 000000000000..06e8afab32e4
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -0,0 +1,284 @@
+/*
+ * Interrupt handling for INTC2-based IRQ.
+ *
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See linux/COPYING for more information.
+ *
+ * These are the "new Hitachi style" interrupts, as present on the
+ * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+struct intc2_data {
+ unsigned char msk_offset;
+ unsigned char msk_shift;
+
+ int (*clear_irq) (int);
+};
+
+static struct intc2_data intc2_data[NR_INTC2_IRQS];
+
+static void enable_intc2_irq(unsigned int irq);
+static void disable_intc2_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_intc2_irq disable_intc2_irq
+
+static void mask_and_ack_intc2(unsigned int);
+static void end_intc2_irq(unsigned int irq);
+
+static unsigned int startup_intc2_irq(unsigned int irq)
+{
+ enable_intc2_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type intc2_irq_type = {
+ .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)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ int msk_shift, msk_offset;
+
+ /* Sanity check */
+ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
+ return;
+
+ msk_shift = intc2_data[irq_offset].msk_shift;
+ msk_offset = intc2_data[irq_offset].msk_offset;
+
+ ctrl_outl(1 << msk_shift,
+ INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset);
+}
+
+static void enable_intc2_irq(unsigned int irq)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ int msk_shift, msk_offset;
+
+ /* Sanity check */
+ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
+ return;
+
+ msk_shift = intc2_data[irq_offset].msk_shift;
+ msk_offset = intc2_data[irq_offset].msk_offset;
+
+ ctrl_outl(1 << msk_shift,
+ INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset);
+}
+
+static void mask_and_ack_intc2(unsigned int irq)
+{
+ disable_intc2_irq(irq);
+}
+
+static void end_intc2_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_intc2_irq(irq);
+
+ if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq))
+ intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq);
+}
+
+/*
+ * Setup an INTC2 style interrupt.
+ * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
+ * allowing the use of the numbers straight out of the datasheet.
+ * For example:
+ * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
+ * would be: ^ ^ ^ ^
+ * | | | |
+ * make_intc2_irq(84, 0, 16, 0, 13);
+ */
+void make_intc2_irq(unsigned int irq,
+ unsigned int ipr_offset, unsigned int ipr_shift,
+ unsigned int msk_offset, unsigned int msk_shift,
+ unsigned int priority)
+{
+ int irq_offset = irq - INTC2_FIRST_IRQ;
+ unsigned int flags;
+ unsigned long ipr;
+
+ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS))
+ return;
+
+ disable_irq_nosync(irq);
+
+ /* Fill the data we need */
+ intc2_data[irq_offset].msk_offset = msk_offset;
+ intc2_data[irq_offset].msk_shift = msk_shift;
+ intc2_data[irq_offset].clear_irq = NULL;
+
+ /* Set the priority level */
+ local_irq_save(flags);
+
+ ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
+ ipr &= ~(0xf << ipr_shift);
+ ipr |= priority << ipr_shift;
+ ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset);
+
+ local_irq_restore(flags);
+
+ irq_desc[irq].handler = &intc2_irq_type;
+
+ disable_intc2_irq(irq);
+}
+
+static struct intc2_init {
+ unsigned short irq;
+ unsigned char ipr_offset, ipr_shift;
+ unsigned char msk_offset, msk_shift;
+ unsigned char priority;
+} intc2_init_data[] __initdata = {
+#if defined(CONFIG_CPU_SUBTYPE_ST40)
+ {64, 0, 0, 0, 0, 13}, /* PCI serr */
+ {65, 0, 4, 0, 1, 13}, /* PCI err */
+ {66, 0, 4, 0, 2, 13}, /* PCI ad */
+ {67, 0, 4, 0, 3, 13}, /* PCI pwd down */
+ {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */
+ {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */
+ {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */
+ {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */
+ {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */
+ {78, 0, 8, 0, 11, 13}, /* DMAC ERR */
+ {80, 0, 12, 0, 12, 13}, /* PIO0 */
+ {84, 0, 16, 0, 13, 13}, /* PIO1 */
+ {88, 0, 20, 0, 14, 13}, /* PIO2 */
+ {112, 4, 0, 4, 0, 13}, /* Mailbox */
+ #ifdef CONFIG_CPU_SUBTYPE_ST40GX1
+ {116, 4, 4, 4, 4, 13}, /* SSC0 */
+ {120, 4, 8, 4, 8, 13}, /* IR Blaster */
+ {124, 4, 12, 4, 12, 13}, /* USB host */
+ {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */
+ {132, 4, 20, 4, 20, 13}, /* UART0 */
+ {134, 4, 20, 4, 22, 13}, /* UART2 */
+ {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */
+ {140, 4, 28, 4, 28, 13}, /* EMPI */
+ {144, 8, 0, 8, 0, 13}, /* MAFE */
+ {148, 8, 4, 8, 4, 13}, /* PWM */
+ {152, 8, 8, 8, 8, 13}, /* SSC1 */
+ {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */
+ {160, 8, 16, 8, 16, 13}, /* USB target */
+ {164, 8, 20, 8, 20, 13}, /* UART1 */
+ {168, 8, 24, 8, 24, 13}, /* Teletext */
+ {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */
+ {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */
+ {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */
+#endif
+#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
+/*
+ * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
+ */
+ /* INTPRIO0 | INTMSK0 */
+ {48, 0, 28, 0, 31, 3}, /* IRQ 4 */
+ {49, 0, 24, 0, 30, 3}, /* IRQ 3 */
+ {50, 0, 20, 0, 29, 3}, /* IRQ 2 */
+ {51, 0, 16, 0, 28, 3}, /* IRQ 1 */
+ /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
+ /* INTPRIO4 | INTMSK0 */
+ {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */
+ {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */
+ {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */
+ {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */
+ {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */
+ {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */
+ {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */
+ {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */
+ /* INTPRIO8 | INTMSK0 */
+ {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */
+ {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */
+ {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */
+ {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */
+ {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */
+ {65, 8, 24, 0, 16, 3}, /* LCDC */
+ /* 66, 67 unused */
+ {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */
+ {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */
+ {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */
+ /* 71 unused */
+ {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */
+ {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */
+ {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */
+ {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */
+ {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */
+ {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */
+ {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */
+ {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */
+ /* | INTMSK4 */
+ {80, 8, 4, 4, 23, 3}, /* SIM_ERI */
+ {81, 8, 4, 4, 22, 3}, /* SIM_RXI */
+ {82, 8, 4, 4, 21, 3}, /* SIM_TXI */
+ {83, 8, 4, 4, 20, 3}, /* SIM_TEI */
+ {84, 8, 0, 4, 19, 3}, /* HSPII */
+ /* INTPRIOC | INTMSK4 */
+ /* 85-87 unused/reserved */
+ {88, 12, 20, 4, 18, 3}, /* MMCI0 */
+ {89, 12, 20, 4, 17, 3}, /* MMCI1 */
+ {90, 12, 20, 4, 16, 3}, /* MMCI2 */
+ {91, 12, 20, 4, 15, 3}, /* MMCI3 */
+ {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/
+ /* 93-107 reserved/undocumented */
+ {108,12, 4, 4, 1, 3}, /* ADC */
+ {109,12, 0, 4, 0, 3}, /* CMTI */
+ /* 110-111 reserved/unused */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+ { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
+#ifdef CONFIG_SH_RTC
+ { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+#endif
+ { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+ { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+ { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+ { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
+
+ { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+ { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+ { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+ { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY },
+
+ { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY },
+ { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
+ { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
+ { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
+ { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
+#endif
+};
+
+void __init init_IRQ_intc2(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) {
+ struct intc2_init *p = intc2_init_data + i;
+ make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
+ p-> msk_offset, p->msk_shift, p->priority);
+ }
+}
+
+/* Adds a termination callback to the interrupt */
+void intc2_add_clear_irq(int irq, int (*fn)(int))
+{
+ if (unlikely(irq < INTC2_FIRST_IRQ))
+ return;
+
+ intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
+}
+
diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 71f92096132b..fdbd718ae5c6 100644
--- a/arch/sh/kernel/cpu/irq_ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -1,6 +1,5 @@
-/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $
- *
- * linux/arch/sh/kernel/irq_ipr.c
+/*
+ * arch/sh/kernel/cpu/irq/ipr.c
*
* Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
* Copyright (C) 2000 Kazumoto Kojima
@@ -109,7 +108,8 @@ static void end_ipr_irq(unsigned int irq)
enable_ipr_irq(irq);
}
-void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
+void make_ipr_irq(unsigned int irq, unsigned int addr, int pos,
+ int priority, int maskpos)
{
disable_irq_nosync(irq);
ipr_data[irq].addr = addr;
@@ -120,126 +120,47 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority)
disable_ipr_irq(irq);
}
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7707) || \
- defined(CONFIG_CPU_SUBTYPE_SH7709)
-static unsigned char pint_map[256];
-static unsigned long portcr_mask = 0;
-
-static void enable_pint_irq(unsigned int irq);
-static void disable_pint_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_pint_irq disable_pint_irq
-
-static void mask_and_ack_pint(unsigned int);
-static void end_pint_irq(unsigned int irq);
-
-static unsigned int startup_pint_irq(unsigned int irq)
-{
- enable_pint_irq(irq);
- return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type pint_irq_type = {
- .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)
-{
- unsigned long val, flags;
-
- local_irq_save(flags);
- val = ctrl_inw(INTC_INTER);
- val &= ~(1 << (irq - PINT_IRQ_BASE));
- ctrl_outw(val, INTC_INTER); /* disable PINTn */
- portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
- local_irq_restore(flags);
-}
-
-static void enable_pint_irq(unsigned int irq)
-{
- unsigned long val, flags;
-
- local_irq_save(flags);
- val = ctrl_inw(INTC_INTER);
- val |= 1 << (irq - PINT_IRQ_BASE);
- ctrl_outw(val, INTC_INTER); /* enable PINTn */
- portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
- local_irq_restore(flags);
-}
-
-static void mask_and_ack_pint(unsigned int irq)
-{
- disable_pint_irq(irq);
-}
-
-static void end_pint_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_pint_irq(irq);
-}
-
-void make_pint_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].handler = &pint_irq_type;
- disable_pint_irq(irq);
-}
-#endif
-
void __init init_IRQ(void)
{
-#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \
- defined(CONFIG_CPU_SUBTYPE_SH7707) || \
- defined(CONFIG_CPU_SUBTYPE_SH7709)
- int i;
-#endif
-
- make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
- make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
+ make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0);
+ make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0);
#if defined(CONFIG_SH_RTC)
- make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+ make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0);
#endif
#ifdef SCI_ERI_IRQ
- make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
- make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
- make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
+ make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
+ make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
+ make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0);
#endif
#ifdef SCIF1_ERI_IRQ
- make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
- make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
- make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
- make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
+ make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
+ make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
+ make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
+ make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0);
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7300)
- make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
- make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
- make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
- make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+ make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0);
+ make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
+ make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0);
+ make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0);
#endif
#ifdef SCIF_ERI_IRQ
- make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
- make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
- make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
- make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
+ make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
+ make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
+ make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
+ make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0);
#endif
#ifdef IRDA_ERI_IRQ
- make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
- make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
- make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
- make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
+ make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
+ make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
+ make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
+ make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0);
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
@@ -254,86 +175,32 @@ void __init init_IRQ(void)
* You should set corresponding bits of PFC to "00"
* to enable these interrupts.
*/
- make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
- make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
- make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
- make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
- make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
- make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
- make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
- make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
- enable_ipr_irq(PINT0_IRQ);
- enable_ipr_irq(PINT8_IRQ);
+ make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0);
+ make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0);
+ make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0);
+ make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0);
+ make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0);
+ make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0);
+#endif
+#endif
- for(i = 0; i < 16; i++)
- make_pint_irq(PINT_IRQ_BASE + i);
- for(i = 0; i < 256; i++)
- {
- if(i & 1) pint_map[i] = 0;
- else if(i & 2) pint_map[i] = 1;
- else if(i & 4) pint_map[i] = 2;
- else if(i & 8) pint_map[i] = 3;
- else if(i & 0x10) pint_map[i] = 4;
- else if(i & 0x20) pint_map[i] = 5;
- else if(i & 0x40) pint_map[i] = 6;
- else if(i & 0x80) pint_map[i] = 7;
- }
-#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */
-#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/
+#ifdef CONFIG_CPU_HAS_PINT_IRQ
+ init_IRQ_pint();
+#endif
-#ifdef CONFIG_CPU_SUBTYPE_ST40
+#ifdef CONFIG_CPU_HAS_INTC2_IRQ
init_IRQ_intc2();
#endif
-
/* Perform the machine specific initialisation */
- if (sh_mv.mv_init_irq != NULL) {
+ if (sh_mv.mv_init_irq != NULL)
sh_mv.mv_init_irq();
- }
}
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
- defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+
+#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
int ipr_irq_demux(int irq)
{
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
- unsigned long creg, dreg, d, sav;
-
- if(irq == PINT0_IRQ)
- {
-#if defined(CONFIG_CPU_SUBTYPE_SH7707)
- creg = PORT_PACR;
- dreg = PORT_PADR;
-#else
- creg = PORT_PCCR;
- dreg = PORT_PCDR;
-#endif
- sav = ctrl_inw(creg);
- ctrl_outw(sav | portcr_mask, creg);
- d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff;
- ctrl_outw(sav, creg);
- if(d == 0) return irq;
- return PINT_IRQ_BASE + pint_map[d];
- }
- else if(irq == PINT8_IRQ)
- {
-#if defined(CONFIG_CPU_SUBTYPE_SH7707)
- creg = PORT_PBCR;
- dreg = PORT_PBDR;
-#else
- creg = PORT_PFCR;
- dreg = PORT_PFDR;
-#endif
- sav = ctrl_inw(creg);
- ctrl_outw(sav | (portcr_mask >> 16), creg);
- d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff;
- ctrl_outw(sav, creg);
- if(d == 0) return irq;
- return PINT_IRQ_BASE + 8 + pint_map[d];
- }
-#endif
return irq;
}
#endif
EXPORT_SYMBOL(make_ipr_irq);
-
diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c
new file mode 100644
index 000000000000..95d6024fe1ae
--- /dev/null
+++ b/arch/sh/kernel/cpu/irq/pint.c
@@ -0,0 +1,169 @@
+/*
+ * arch/sh/kernel/cpu/irq/pint.c - Interrupt handling for PINT-based IRQs.
+ *
+ * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+static unsigned char pint_map[256];
+static unsigned long portcr_mask;
+
+static void enable_pint_irq(unsigned int irq);
+static void disable_pint_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_pint_irq disable_pint_irq
+
+static void mask_and_ack_pint(unsigned int);
+static void end_pint_irq(unsigned int irq);
+
+static unsigned int startup_pint_irq(unsigned int irq)
+{
+ enable_pint_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type pint_irq_type = {
+ .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)
+{
+ unsigned long val, flags;
+
+ local_irq_save(flags);
+ val = ctrl_inw(INTC_INTER);
+ val &= ~(1 << (irq - PINT_IRQ_BASE));
+ ctrl_outw(val, INTC_INTER); /* disable PINTn */
+ portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
+ local_irq_restore(flags);
+}
+
+static void enable_pint_irq(unsigned int irq)
+{
+ unsigned long val, flags;
+
+ local_irq_save(flags);
+ val = ctrl_inw(INTC_INTER);
+ val |= 1 << (irq - PINT_IRQ_BASE);
+ ctrl_outw(val, INTC_INTER); /* enable PINTn */
+ portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_pint(unsigned int irq)
+{
+ disable_pint_irq(irq);
+}
+
+static void end_pint_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_pint_irq(irq);
+}
+
+void make_pint_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
+ irq_desc[irq].handler = &pint_irq_type;
+ disable_pint_irq(irq);
+}
+
+void __init init_IRQ_pint(void)
+{
+ int i;
+
+ make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY);
+ make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
+
+ enable_irq(PINT0_IRQ);
+ enable_irq(PINT8_IRQ);
+
+ for(i = 0; i < 16; i++)
+ make_pint_irq(PINT_IRQ_BASE + i);
+
+ for(i = 0; i < 256; i++) {
+ if (i & 1)
+ pint_map[i] = 0;
+ else if (i & 2)
+ pint_map[i] = 1;
+ else if (i & 4)
+ pint_map[i] = 2;
+ else if (i & 8)
+ pint_map[i] = 3;
+ else if (i & 0x10)
+ pint_map[i] = 4;
+ else if (i & 0x20)
+ pint_map[i] = 5;
+ else if (i & 0x40)
+ pint_map[i] = 6;
+ else if (i & 0x80)
+ pint_map[i] = 7;
+ }
+}
+
+int ipr_irq_demux(int irq)
+{
+ unsigned long creg, dreg, d, sav;
+
+ if (irq == PINT0_IRQ) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+ creg = PORT_PACR;
+ dreg = PORT_PADR;
+#else
+ creg = PORT_PCCR;
+ dreg = PORT_PCDR;
+#endif
+ sav = ctrl_inw(creg);
+ ctrl_outw(sav | portcr_mask, creg);
+ d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) &
+ ctrl_inw(INTC_INTER) & 0xff;
+ ctrl_outw(sav, creg);
+
+ if (d == 0)
+ return irq;
+
+ return PINT_IRQ_BASE + pint_map[d];
+ } else if (irq == PINT8_IRQ) {
+#if defined(CONFIG_CPU_SUBTYPE_SH7707)
+ creg = PORT_PBCR;
+ dreg = PORT_PBDR;
+#else
+ creg = PORT_PFCR;
+ dreg = PORT_PFDR;
+#endif
+ sav = ctrl_inw(creg);
+ ctrl_outw(sav | (portcr_mask >> 16), creg);
+ d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) &
+ (ctrl_inw(INTC_INTER) >> 8) & 0xff;
+ ctrl_outw(sav, creg);
+
+ if (d == 0)
+ return irq;
+
+ return PINT_IRQ_BASE + 8 + pint_map[d];
+ }
+
+ return irq;
+}
+
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index a64532e4dc63..b54dbb9a0c86 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -4,3 +4,10 @@
obj-y := ex.o probe.o
+clock-$(CONFIG_CPU_SH3) := clock-sh3.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o
+
+obj-y += $(clock-y)
+
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c
new file mode 100644
index 000000000000..c3c945958baf
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c
@@ -0,0 +1,89 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh3.c
+ *
+ * Generic SH-3 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * FRQCR parsing hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
+static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate *= pfc_divisors[idx];
+}
+
+static struct clk_ops sh3_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh3_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
+
+ clk->rate = clk->parent->rate / stc_multipliers[idx];
+}
+
+static struct clk_ops sh3_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
+
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh3_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh3_clk_ops[] = {
+ &sh3_master_clk_ops,
+ &sh3_module_clk_ops,
+ &sh3_bus_clk_ops,
+ &sh3_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh3_clk_ops))
+ *ops = sh3_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7300.c b/arch/sh/kernel/cpu/sh3/clock-sh7300.c
new file mode 100644
index 000000000000..e804174b9625
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7300.c
@@ -0,0 +1,78 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7300.c
+ *
+ * SH7300 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * FRQCR parsing hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007];
+}
+
+static struct clk_ops sh7300_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0007);
+ clk->rate = clk->parent->rate / md_table[idx];
+}
+
+static struct clk_ops sh7300_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8;
+ clk->rate = clk->parent->rate / md_table[idx];
+}
+
+static struct clk_ops sh7300_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4;
+ clk->rate = clk->parent->rate / md_table[idx];
+}
+
+static struct clk_ops sh7300_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7300_clk_ops[] = {
+ &sh7300_master_clk_ops,
+ &sh7300_module_clk_ops,
+ &sh7300_bus_clk_ops,
+ &sh7300_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7300_clk_ops))
+ *ops = sh7300_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
new file mode 100644
index 000000000000..dfdbf3277fd7
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
@@ -0,0 +1,84 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7705.c
+ *
+ * SH7705 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * FRQCR parsing hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+/*
+ * SH7705 uses the same divisors as the generic SH-3 case, it's just the
+ * FRQCR layout that is a bit different..
+ */
+static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
+static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003];
+}
+
+static struct clk_ops sh7705_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = ctrl_inw(FRQCR) & 0x0003;
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7705_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8;
+ clk->rate = clk->parent->rate / stc_multipliers[idx];
+}
+
+static struct clk_ops sh7705_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4;
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7705_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7705_clk_ops[] = {
+ &sh7705_master_clk_ops,
+ &sh7705_module_clk_ops,
+ &sh7705_bus_clk_ops,
+ &sh7705_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7705_clk_ops))
+ *ops = sh7705_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
new file mode 100644
index 000000000000..10461a745e5f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
@@ -0,0 +1,96 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7709.c
+ *
+ * SH7709 support for the clock framework
+ *
+ * Copyright (C) 2005 Andriy Skulysh
+ *
+ * Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
+static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
+static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+
+static void set_bus_parent(struct clk *clk)
+{
+ struct clk *bus_clk = clk_get("bus_clk");
+ clk->parent = bus_clk;
+ clk_put(bus_clk);
+}
+
+static void master_clk_init(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate *= pfc_divisors[idx];
+}
+
+static struct clk_ops sh7709_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7709_module_clk_ops = {
+#ifdef CLOCK_MODE_0_1_2_7
+ .init = set_bus_parent,
+#endif
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = (frqcr & 0x0080) ?
+ ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1;
+
+ clk->rate = clk->parent->rate * stc_multipliers[idx];
+}
+
+static struct clk_ops sh7709_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int frqcr = ctrl_inw(FRQCR);
+ int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
+
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7709_cpu_clk_ops = {
+ .init = set_bus_parent,
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7709_clk_ops[] = {
+ &sh7709_master_clk_ops,
+ &sh7709_module_clk_ops,
+ &sh7709_bus_clk_ops,
+ &sh7709_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7709_clk_ops))
+ *ops = sh7709_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index ead1071eac73..3d5cafc71ae3 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -5,6 +5,15 @@
obj-y := ex.o probe.o
obj-$(CONFIG_SH_FPU) += fpu.o
-obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SH4) := clock-sh4.o
+clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
+
+# Additional clocks by subtype
+clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
+
+obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
new file mode 100644
index 000000000000..bfdf5fe8d948
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -0,0 +1,179 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+ *
+ * Additional SH4-202 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+#define CPG2_FRQCR3 0xfe0a0018
+
+static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 };
+static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 };
+
+static void emi_clk_recalc(struct clk *clk)
+{
+ int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007;
+ clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+}
+
+static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
+{
+ int divisor = clk->parent->rate / rate;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++)
+ if (frqcr3_divisors[i] == divisor)
+ return frqcr3_values[i];
+
+ /* Safe fallback */
+ return 5;
+}
+
+static struct clk_ops sh4202_emi_clk_ops = {
+ .recalc = emi_clk_recalc,
+};
+
+static struct clk sh4202_emi_clk = {
+ .name = "emi_clk",
+ .flags = CLK_ALWAYS_ENABLED,
+ .ops = &sh4202_emi_clk_ops,
+};
+
+static void femi_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007;
+ clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+}
+
+static struct clk_ops sh4202_femi_clk_ops = {
+ .recalc = femi_clk_recalc,
+};
+
+static struct clk sh4202_femi_clk = {
+ .name = "femi_clk",
+ .flags = CLK_ALWAYS_ENABLED,
+ .ops = &sh4202_femi_clk_ops,
+};
+
+static void shoc_clk_init(struct clk *clk)
+{
+ int i;
+
+ /*
+ * For some reason, the shoc_clk seems to be set to some really
+ * insane value at boot (values outside of the allowable frequency
+ * range for instance). We deal with this by scaling it back down
+ * to something sensible just in case.
+ *
+ * Start scaling from the high end down until we find something
+ * that passes rate verification..
+ */
+ for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
+ int divisor = frqcr3_divisors[i];
+
+ if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
+ break;
+ }
+
+ WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */
+}
+
+static void shoc_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007;
+ clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+}
+
+static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
+{
+ struct clk *bclk = clk_get("bus_clk");
+ unsigned long bclk_rate = clk_get_rate(bclk);
+
+ clk_put(bclk);
+
+ if (rate > bclk_rate)
+ return 1;
+ if (rate > 66000000)
+ return 1;
+
+ return 0;
+}
+
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ unsigned long frqcr3;
+ unsigned int tmp;
+
+ /* Make sure we have something sensible to switch to */
+ if (shoc_clk_verify_rate(clk, rate) != 0)
+ return -EINVAL;
+
+ tmp = frqcr3_lookup(clk, rate);
+
+ frqcr3 = ctrl_inl(CPG2_FRQCR3);
+ frqcr3 &= ~(0x0007 << 6);
+ frqcr3 |= tmp << 6;
+ ctrl_outl(frqcr3, CPG2_FRQCR3);
+
+ clk->rate = clk->parent->rate / frqcr3_divisors[tmp];
+
+ return 0;
+}
+
+static struct clk_ops sh4202_shoc_clk_ops = {
+ .init = shoc_clk_init,
+ .recalc = shoc_clk_recalc,
+ .set_rate = shoc_clk_set_rate,
+};
+
+static struct clk sh4202_shoc_clk = {
+ .name = "shoc_clk",
+ .flags = CLK_ALWAYS_ENABLED,
+ .ops = &sh4202_shoc_clk_ops,
+};
+
+static struct clk *sh4202_onchip_clocks[] = {
+ &sh4202_emi_clk,
+ &sh4202_femi_clk,
+ &sh4202_shoc_clk,
+};
+
+static int __init sh4202_clk_init(void)
+{
+ struct clk *clk = clk_get("master_clk");
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
+ struct clk *clkp = sh4202_onchip_clocks[i];
+
+ clkp->parent = clk;
+ clk_register(clkp);
+ clk_enable(clkp);
+ }
+
+ /*
+ * Now that we have the rest of the clocks registered, we need to
+ * force the parent clock to propagate so that these clocks will
+ * automatically figure out their rate. We cheat by handing the
+ * parent clock its current rate and forcing child propagation.
+ */
+ clk_set_rate(clk, clk_get_rate(clk));
+
+ clk_put(clk);
+
+ return 0;
+}
+
+arch_initcall(sh4202_clk_init);
+
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c
new file mode 100644
index 000000000000..dca9f87a12d6
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c
@@ -0,0 +1,80 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh4.c
+ *
+ * Generic SH-4 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * FRQCR parsing hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
+#define bfc_divisors ifc_divisors /* Same */
+static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007];
+}
+
+static struct clk_ops sh4_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) & 0x0007);
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh4_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007;
+ clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh4_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007;
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh4_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh4_clk_ops[] = {
+ &sh4_master_clk_ops,
+ &sh4_module_clk_ops,
+ &sh4_bus_clk_ops,
+ &sh4_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh4_clk_ops))
+ *ops = sh4_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4/clock-sh73180.c
new file mode 100644
index 000000000000..2fa5cb2ae68d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/clock-sh73180.c
@@ -0,0 +1,81 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh73180.c
+ *
+ * SH73180 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * FRQCR parsing hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+/*
+ * SH73180 uses a common set of divisors, so this is quite simple..
+ */
+static int divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= divisors[ctrl_inl(FRQCR) & 0x0007];
+}
+
+static struct clk_ops sh73180_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) & 0x0007);
+ clk->rate = clk->parent->rate / divisors[idx];
+}
+
+static struct clk_ops sh73180_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) >> 12) & 0x0007;
+ clk->rate = clk->parent->rate / divisors[idx];
+}
+
+static struct clk_ops sh73180_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) >> 20) & 0x0007;
+ clk->rate = clk->parent->rate / divisors[idx];
+}
+
+static struct clk_ops sh73180_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh73180_clk_ops[] = {
+ &sh73180_master_clk_ops,
+ &sh73180_module_clk_ops,
+ &sh73180_bus_clk_ops,
+ &sh73180_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh73180_clk_ops))
+ *ops = sh73180_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4/clock-sh7770.c
new file mode 100644
index 000000000000..c8694bac6477
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/clock-sh7770.c
@@ -0,0 +1,73 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7770.c
+ *
+ * SH7770 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
+static int bfc_divisors[] = { 1, 1, 1, 1, 1, 8,12, 1 };
+static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f];
+}
+
+static struct clk_ops sh7770_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f);
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7770_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) & 0x000f);
+ clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh7770_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f);
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7770_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7770_clk_ops[] = {
+ &sh7770_master_clk_ops,
+ &sh7770_module_clk_ops,
+ &sh7770_bus_clk_ops,
+ &sh7770_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7770_clk_ops))
+ *ops = sh7770_clk_ops[idx];
+}
+
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c
new file mode 100644
index 000000000000..93ad367342c9
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c
@@ -0,0 +1,126 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7780.c
+ *
+ * SH7780 support for the clock framework
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int ifc_divisors[] = { 2, 4 };
+static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 };
+static int pfc_divisors[] = { 1, 24, 24, 1 };
+static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003];
+}
+
+static struct clk_ops sh7780_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+ int idx = (ctrl_inl(FRQCR) & 0x0003);
+ clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7780_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007);
+ clk->rate = clk->parent->rate / bfc_divisors[idx];
+}
+
+static struct clk_ops sh7780_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001);
+ clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7780_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7780_clk_ops[] = {
+ &sh7780_master_clk_ops,
+ &sh7780_module_clk_ops,
+ &sh7780_bus_clk_ops,
+ &sh7780_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+ if (idx < ARRAY_SIZE(sh7780_clk_ops))
+ *ops = sh7780_clk_ops[idx];
+}
+
+static void shyway_clk_recalc(struct clk *clk)
+{
+ int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007);
+ clk->rate = clk->parent->rate / cfc_divisors[idx];
+}
+
+static struct clk_ops sh7780_shyway_clk_ops = {
+ .recalc = shyway_clk_recalc,
+};
+
+static struct clk sh7780_shyway_clk = {
+ .name = "shyway_clk",
+ .flags = CLK_ALWAYS_ENABLED,
+ .ops = &sh7780_shyway_clk_ops,
+};
+
+/*
+ * Additional SH7780-specific on-chip clocks that aren't already part of the
+ * clock framework
+ */
+static struct clk *sh7780_onchip_clocks[] = {
+ &sh7780_shyway_clk,
+};
+
+static int __init sh7780_clk_init(void)
+{
+ struct clk *clk = clk_get("master_clk");
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
+ struct clk *clkp = sh7780_onchip_clocks[i];
+
+ clkp->parent = clk;
+ clk_register(clkp);
+ clk_enable(clkp);
+ }
+
+ /*
+ * Now that we have the rest of the clocks registered, we need to
+ * force the parent clock to propagate so that these clocks will
+ * automatically figure out their rate. We cheat by handing the
+ * parent clock its current rate and forcing child propagation.
+ */
+ clk_set_rate(clk, clk_get_rate(clk));
+
+ clk_put(clk);
+
+ return 0;
+}
+
+arch_initcall(sh7780_clk_init);
+
diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c
deleted file mode 100644
index f6b16ba01932..000000000000
--- a/arch/sh/kernel/cpu/sh4/irq_intc2.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * linux/arch/sh/kernel/irq_intc2.c
- *
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Interrupt handling for INTC2-based IRQ.
- *
- * These are the "new Hitachi style" interrupts, as present on the
- * Hitachi 7751 and the STM ST40 STB1.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/machvec.h>
-
-
-struct intc2_data {
- unsigned char msk_offset;
- unsigned char msk_shift;
-#ifdef CONFIG_CPU_SUBTYPE_ST40
- int (*clear_irq) (int);
-#endif
-};
-
-
-static struct intc2_data intc2_data[NR_INTC2_IRQS];
-
-static void enable_intc2_irq(unsigned int irq);
-static void disable_intc2_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_intc2_irq disable_intc2_irq
-
-static void mask_and_ack_intc2(unsigned int);
-static void end_intc2_irq(unsigned int irq);
-
-static unsigned int startup_intc2_irq(unsigned int irq)
-{
- enable_intc2_irq(irq);
- return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type intc2_irq_type = {
- .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)
-{
- int irq_offset = irq - INTC2_FIRST_IRQ;
- int msk_shift, msk_offset;
-
- // Sanity check
- if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
- return;
-
- msk_shift = intc2_data[irq_offset].msk_shift;
- msk_offset = intc2_data[irq_offset].msk_offset;
-
- ctrl_outl(1<<msk_shift,
- INTC2_BASE+INTC2_INTMSK_OFFSET+msk_offset);
-}
-
-static void enable_intc2_irq(unsigned int irq)
-{
- int irq_offset = irq - INTC2_FIRST_IRQ;
- int msk_shift, msk_offset;
-
- /* Sanity check */
- if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
- return;
-
- msk_shift = intc2_data[irq_offset].msk_shift;
- msk_offset = intc2_data[irq_offset].msk_offset;
-
- ctrl_outl(1<<msk_shift,
- INTC2_BASE+INTC2_INTMSKCLR_OFFSET+msk_offset);
-}
-
-static void mask_and_ack_intc2(unsigned int irq)
-{
- disable_intc2_irq(irq);
-}
-
-static void end_intc2_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_intc2_irq(irq);
-
-#ifdef CONFIG_CPU_SUBTYPE_ST40
- if (intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)
- intc2_data[irq - INTC2_FIRST_IRQ].clear_irq (irq);
-#endif
-}
-
-/*
- * Setup an INTC2 style interrupt.
- * NOTE: Unlike IPR interrupts, parameters are not shifted by this code,
- * allowing the use of the numbers straight out of the datasheet.
- * For example:
- * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
- * would be: ^ ^ ^ ^
- * | | | |
- * make_intc2_irq(84, 0, 16, 0, 13);
- */
-void make_intc2_irq(unsigned int irq,
- unsigned int ipr_offset, unsigned int ipr_shift,
- unsigned int msk_offset, unsigned int msk_shift,
- unsigned int priority)
-{
- int irq_offset = irq - INTC2_FIRST_IRQ;
- unsigned int flags;
- unsigned long ipr;
-
- if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS))
- return;
-
- disable_irq_nosync(irq);
-
- /* Fill the data we need */
- intc2_data[irq_offset].msk_offset = msk_offset;
- intc2_data[irq_offset].msk_shift = msk_shift;
-#ifdef CONFIG_CPU_SUBTYPE_ST40
- intc2_data[irq_offset].clear_irq = NULL;
-#endif
-
- /* Set the priority level */
- local_irq_save(flags);
-
- ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
- ipr&=~(0xf<<ipr_shift);
- ipr|=(priority)<<ipr_shift;
- ctrl_outl(ipr, INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset);
-
- local_irq_restore(flags);
-
- irq_desc[irq].handler=&intc2_irq_type;
-
- disable_intc2_irq(irq);
-}
-
-#ifdef CONFIG_CPU_SUBTYPE_ST40
-
-struct intc2_init {
- unsigned short irq;
- unsigned char ipr_offset, ipr_shift;
- unsigned char msk_offset, msk_shift;
-};
-
-static struct intc2_init intc2_init_data[] __initdata = {
- {64, 0, 0, 0, 0}, /* PCI serr */
- {65, 0, 4, 0, 1}, /* PCI err */
- {66, 0, 4, 0, 2}, /* PCI ad */
- {67, 0, 4, 0, 3}, /* PCI pwd down */
- {72, 0, 8, 0, 5}, /* DMAC INT0 */
- {73, 0, 8, 0, 6}, /* DMAC INT1 */
- {74, 0, 8, 0, 7}, /* DMAC INT2 */
- {75, 0, 8, 0, 8}, /* DMAC INT3 */
- {76, 0, 8, 0, 9}, /* DMAC INT4 */
- {78, 0, 8, 0, 11}, /* DMAC ERR */
- {80, 0, 12, 0, 12}, /* PIO0 */
- {84, 0, 16, 0, 13}, /* PIO1 */
- {88, 0, 20, 0, 14}, /* PIO2 */
- {112, 4, 0, 4, 0}, /* Mailbox */
-#ifdef CONFIG_CPU_SUBTYPE_ST40GX1
- {116, 4, 4, 4, 4}, /* SSC0 */
- {120, 4, 8, 4, 8}, /* IR Blaster */
- {124, 4, 12, 4, 12}, /* USB host */
- {128, 4, 16, 4, 16}, /* Video processor BLITTER */
- {132, 4, 20, 4, 20}, /* UART0 */
- {134, 4, 20, 4, 22}, /* UART2 */
- {136, 4, 24, 4, 24}, /* IO_PIO0 */
- {140, 4, 28, 4, 28}, /* EMPI */
- {144, 8, 0, 8, 0}, /* MAFE */
- {148, 8, 4, 8, 4}, /* PWM */
- {152, 8, 8, 8, 8}, /* SSC1 */
- {156, 8, 12, 8, 12}, /* IO_PIO1 */
- {160, 8, 16, 8, 16}, /* USB target */
- {164, 8, 20, 8, 20}, /* UART1 */
- {168, 8, 24, 8, 24}, /* Teletext */
- {172, 8, 28, 8, 28}, /* VideoSync VTG */
- {173, 8, 28, 8, 29}, /* VideoSync DVP0 */
- {174, 8, 28, 8, 30}, /* VideoSync DVP1 */
-#endif
-};
-
-void __init init_IRQ_intc2(void)
-{
- struct intc2_init *p;
-
- printk(KERN_ALERT "init_IRQ_intc2\n");
-
- for (p = intc2_init_data;
- p<intc2_init_data+ARRAY_SIZE(intc2_init_data);
- p++) {
- make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift,
- p-> msk_offset, p->msk_shift, 13);
- }
-}
-
-/* Adds a termination callback to the interrupt */
-void intc2_add_clear_irq(int irq, int (*fn)(int))
-{
- if (irq < INTC2_FIRST_IRQ)
- return;
-
- intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn;
-}
-
-#endif /* CONFIG_CPU_SUBTYPE_ST40 */
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c
index d9932f25993b..71c9fde2fd90 100644
--- a/arch/sh/kernel/io.c
+++ b/arch/sh/kernel/io.c
@@ -2,58 +2,73 @@
* linux/arch/sh/kernel/io.c
*
* Copyright (C) 2000 Stuart Menefy
+ * Copyright (C) 2005 Paul Mundt
*
* Provide real functions which expand to whatever the header file defined.
* Also definitions of machine independent IO functions.
+ *
+ * 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/io.h>
#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
/*
* Copy data from IO memory space to "real" memory space.
* This needs to be optimized.
*/
-void memcpy_fromio(void * to, unsigned long from, unsigned long count)
+void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count)
{
char *p = to;
while (count) {
count--;
- *p = readb(from);
+ *p = readb((void __iomem *)from);
p++;
from++;
}
}
-
+EXPORT_SYMBOL(memcpy_fromio);
+
/*
* Copy data from "real" memory space to IO memory space.
* This needs to be optimized.
*/
-void memcpy_toio(unsigned long to, const void * from, unsigned long count)
+void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count)
{
const char *p = from;
while (count) {
count--;
- writeb(*p, to);
+ writeb(*p, (void __iomem *)to);
p++;
to++;
}
}
-
+EXPORT_SYMBOL(memcpy_toio);
+
/*
* "memset" on IO memory space.
* This needs to be optimized.
*/
-void memset_io(unsigned long dst, int c, unsigned long count)
+void memset_io(volatile void __iomem *dst, int c, unsigned long count)
{
while (count) {
count--;
- writeb(c, dst);
+ writeb(c, (void __iomem *)dst);
dst++;
}
}
-
-EXPORT_SYMBOL(memcpy_fromio);
-EXPORT_SYMBOL(memcpy_toio);
EXPORT_SYMBOL(memset_io);
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ return sh_mv.mv_ioport_map(port, nr);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+ sh_mv.mv_ioport_unmap(addr);
+}
+EXPORT_SYMBOL(ioport_unmap);
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c
index a911b0149d1f..28ec7487de8c 100644
--- a/arch/sh/kernel/io_generic.c
+++ b/arch/sh/kernel/io_generic.c
@@ -3,6 +3,7 @@
* linux/arch/sh/kernel/io_generic.c
*
* Copyright (C) 2000 Niibe Yutaka
+ * Copyright (C) 2005 Paul Mundt
*
* Generic I/O routine. These can be used where a machine specific version
* is not required.
@@ -10,21 +11,20 @@
* 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 <asm/io.h>
#include <asm/machvec.h>
-#include <linux/module.h>
-#if defined(CONFIG_CPU_SH3)
+#ifdef CONFIG_CPU_SH3
+/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
+ * workaround. */
/* I'm not sure SH7709 has this kind of bug */
-#define SH3_PCMCIA_BUG_WORKAROUND 1
-#define DUMMY_READ_AREA6 0xba000000
+#define dummy_read() ctrl_inb(0xba000000)
+#else
+#define dummy_read()
#endif
-#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
-
unsigned long generic_io_base;
static inline void delay(void)
@@ -32,40 +32,40 @@ static inline void delay(void)
ctrl_inw(0xa0000000);
}
-unsigned char generic_inb(unsigned long port)
+u8 generic_inb(unsigned long port)
{
- return *(volatile unsigned char*)PORT2ADDR(port);
+ return ctrl_inb((unsigned long __force)ioport_map(port, 1));
}
-unsigned short generic_inw(unsigned long port)
+u16 generic_inw(unsigned long port)
{
- return *(volatile unsigned short*)PORT2ADDR(port);
+ return ctrl_inw((unsigned long __force)ioport_map(port, 2));
}
-unsigned int generic_inl(unsigned long port)
+u32 generic_inl(unsigned long port)
{
- return *(volatile unsigned long*)PORT2ADDR(port);
+ return ctrl_inl((unsigned long __force)ioport_map(port, 4));
}
-unsigned char generic_inb_p(unsigned long port)
+u8 generic_inb_p(unsigned long port)
{
- unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
+ unsigned long v = generic_inb(port);
delay();
return v;
}
-unsigned short generic_inw_p(unsigned long port)
+u16 generic_inw_p(unsigned long port)
{
- unsigned long v = *(volatile unsigned short*)PORT2ADDR(port);
+ unsigned long v = generic_inw(port);
delay();
return v;
}
-unsigned int generic_inl_p(unsigned long port)
+u32 generic_inl_p(unsigned long port)
{
- unsigned long v = *(volatile unsigned long*)PORT2ADDR(port);
+ unsigned long v = generic_inl(port);
delay();
return v;
@@ -77,75 +77,70 @@ unsigned int generic_inl_p(unsigned long port)
* convert the port address to real address once.
*/
-void generic_insb(unsigned long port, void *buffer, unsigned long count)
+void generic_insb(unsigned long port, void *dst, unsigned long count)
{
- volatile unsigned char *port_addr;
- unsigned char *buf=buffer;
-
- port_addr = (volatile unsigned char *)PORT2ADDR(port);
+ volatile u8 *port_addr;
+ u8 *buf = dst;
- while(count--)
- *buf++ = *port_addr;
+ port_addr = (volatile u8 *)ioport_map(port, 1);
+ while (count--)
+ *buf++ = *port_addr;
}
-void generic_insw(unsigned long port, void *buffer, unsigned long count)
+void generic_insw(unsigned long port, void *dst, unsigned long count)
{
- volatile unsigned short *port_addr;
- unsigned short *buf=buffer;
+ volatile u16 *port_addr;
+ u16 *buf = dst;
- port_addr = (volatile unsigned short *)PORT2ADDR(port);
+ port_addr = (volatile u16 *)ioport_map(port, 2);
+ while (count--)
+ *buf++ = *port_addr;
- while(count--)
- *buf++ = *port_addr;
-#ifdef SH3_PCMCIA_BUG_WORKAROUND
- ctrl_inb (DUMMY_READ_AREA6);
-#endif
+ dummy_read();
}
-void generic_insl(unsigned long port, void *buffer, unsigned long count)
+void generic_insl(unsigned long port, void *dst, unsigned long count)
{
- volatile unsigned long *port_addr;
- unsigned long *buf=buffer;
+ volatile u32 *port_addr;
+ u32 *buf = dst;
- port_addr = (volatile unsigned long *)PORT2ADDR(port);
+ port_addr = (volatile u32 *)ioport_map(port, 4);
+ while (count--)
+ *buf++ = *port_addr;
- while(count--)
- *buf++ = *port_addr;
-#ifdef SH3_PCMCIA_BUG_WORKAROUND
- ctrl_inb (DUMMY_READ_AREA6);
-#endif
+ dummy_read();
}
-void generic_outb(unsigned char b, unsigned long port)
+void generic_outb(u8 b, unsigned long port)
{
- *(volatile unsigned char*)PORT2ADDR(port) = b;
+ ctrl_outb(b, (unsigned long __force)ioport_map(port, 1));
}
-void generic_outw(unsigned short b, unsigned long port)
+void generic_outw(u16 b, unsigned long port)
{
- *(volatile unsigned short*)PORT2ADDR(port) = b;
+ ctrl_outw(b, (unsigned long __force)ioport_map(port, 2));
}
-void generic_outl(unsigned int b, unsigned long port)
+void generic_outl(u32 b, unsigned long port)
{
- *(volatile unsigned long*)PORT2ADDR(port) = b;
+ ctrl_outl(b, (unsigned long __force)ioport_map(port, 4));
}
-void generic_outb_p(unsigned char b, unsigned long port)
+void generic_outb_p(u8 b, unsigned long port)
{
- *(volatile unsigned char*)PORT2ADDR(port) = b;
+ generic_outb(b, port);
delay();
}
-void generic_outw_p(unsigned short b, unsigned long port)
+void generic_outw_p(u16 b, unsigned long port)
{
- *(volatile unsigned short*)PORT2ADDR(port) = b;
+ generic_outw(b, port);
delay();
}
-void generic_outl_p(unsigned int b, unsigned long port)
+void generic_outl_p(u32 b, unsigned long port)
{
- *(volatile unsigned long*)PORT2ADDR(port) = b;
+ generic_outl(b, port);
delay();
}
@@ -154,90 +149,77 @@ void generic_outl_p(unsigned int b, unsigned long port)
* address. However as the port address doesn't change we only need to
* convert the port address to real address once.
*/
-
-void generic_outsb(unsigned long port, const void *buffer, unsigned long count)
+void generic_outsb(unsigned long port, const void *src, unsigned long count)
{
- volatile unsigned char *port_addr;
- const unsigned char *buf=buffer;
+ volatile u8 *port_addr;
+ const u8 *buf = src;
- port_addr = (volatile unsigned char *)PORT2ADDR(port);
+ port_addr = (volatile u8 __force *)ioport_map(port, 1);
- while(count--)
- *port_addr = *buf++;
+ while (count--)
+ *port_addr = *buf++;
}
-void generic_outsw(unsigned long port, const void *buffer, unsigned long count)
+void generic_outsw(unsigned long port, const void *src, unsigned long count)
{
- volatile unsigned short *port_addr;
- const unsigned short *buf=buffer;
+ volatile u16 *port_addr;
+ const u16 *buf = src;
- port_addr = (volatile unsigned short *)PORT2ADDR(port);
+ port_addr = (volatile u16 __force *)ioport_map(port, 2);
- while(count--)
- *port_addr = *buf++;
+ while (count--)
+ *port_addr = *buf++;
-#ifdef SH3_PCMCIA_BUG_WORKAROUND
- ctrl_inb (DUMMY_READ_AREA6);
-#endif
+ dummy_read();
}
-void generic_outsl(unsigned long port, const void *buffer, unsigned long count)
+void generic_outsl(unsigned long port, const void *src, unsigned long count)
{
- volatile unsigned long *port_addr;
- const unsigned long *buf=buffer;
+ volatile u32 *port_addr;
+ const u32 *buf = src;
- port_addr = (volatile unsigned long *)PORT2ADDR(port);
+ port_addr = (volatile u32 __force *)ioport_map(port, 4);
+ while (count--)
+ *port_addr = *buf++;
- while(count--)
- *port_addr = *buf++;
-
-#ifdef SH3_PCMCIA_BUG_WORKAROUND
- ctrl_inb (DUMMY_READ_AREA6);
-#endif
-}
-
-unsigned char generic_readb(unsigned long addr)
-{
- return *(volatile unsigned char*)addr;
+ dummy_read();
}
-unsigned short generic_readw(unsigned long addr)
+u8 generic_readb(void __iomem *addr)
{
- return *(volatile unsigned short*)addr;
+ return ctrl_inb((unsigned long __force)addr);
}
-unsigned int generic_readl(unsigned long addr)
+u16 generic_readw(void __iomem *addr)
{
- return *(volatile unsigned long*)addr;
+ return ctrl_inw((unsigned long __force)addr);
}
-void generic_writeb(unsigned char b, unsigned long addr)
+u32 generic_readl(void __iomem *addr)
{
- *(volatile unsigned char*)addr = b;
+ return ctrl_inl((unsigned long __force)addr);
}
-void generic_writew(unsigned short b, unsigned long addr)
+void generic_writeb(u8 b, void __iomem *addr)
{
- *(volatile unsigned short*)addr = b;
+ ctrl_outb(b, (unsigned long __force)addr);
}
-void generic_writel(unsigned int b, unsigned long addr)
+void generic_writew(u16 b, void __iomem *addr)
{
- *(volatile unsigned long*)addr = b;
+ ctrl_outw(b, (unsigned long __force)addr);
}
-void * generic_ioremap(unsigned long offset, unsigned long size)
+void generic_writel(u32 b, void __iomem *addr)
{
- return (void *) P2SEGADDR(offset);
+ ctrl_outl(b, (unsigned long __force)addr);
}
-EXPORT_SYMBOL(generic_ioremap);
-void generic_iounmap(void *addr)
+void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
{
+ return (void __iomem *)(addr + generic_io_base);
}
-EXPORT_SYMBOL(generic_iounmap);
-unsigned long generic_isa_port2addr(unsigned long offset)
+void generic_ioport_unmap(void __iomem *addr)
{
- return offset + generic_io_base;
}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 54c171225b78..6883c00728cb 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -8,38 +8,13 @@
* SuperH version: Copyright (C) 1999 Niibe Yutaka
*/
-/*
- * IRQs are in fact implemented a bit like signal handlers for the kernel.
- * Naturally it's not a 1:1 relation, but there are similarities.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
+#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
+#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
-#include <linux/kallsyms.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/delay.h>
#include <asm/irq.h>
-#include <linux/irq.h>
-
+#include <asm/processor.h>
+#include <asm/cpu/mmu_context.h>
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
@@ -66,7 +41,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
}
- if (i < ACTUAL_NR_IRQS) {
+ if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
@@ -86,19 +61,32 @@ unlock:
}
#endif
+
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs regs)
-{
- int irq;
+{
+ int irq = r4;
irq_enter();
- asm volatile("stc r2_bank, %0\n\t"
- "shlr2 %0\n\t"
- "shlr2 %0\n\t"
- "shlr %0\n\t"
- "add #-16, %0\n\t"
- :"=z" (irq));
+
+#ifdef CONFIG_CPU_HAS_INTEVT
+ __asm__ __volatile__ (
+#ifdef CONFIG_CPU_HAS_SR_RB
+ "stc r2_bank, %0\n\t"
+#else
+ "mov.l @%1, %0\n\t"
+#endif
+ "shlr2 %0\n\t"
+ "shlr2 %0\n\t"
+ "shlr %0\n\t"
+ "add #-16, %0\n\t"
+ : "=z" (irq), "=r" (r4)
+ : "1" (INTEVT)
+ : "memory"
+ );
+#endif
+
irq = irq_demux(irq);
__do_IRQ(irq, &regs);
irq_exit();
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
new file mode 100644
index 000000000000..43546525f28f
--- /dev/null
+++ b/arch/sh/kernel/machine_kexec.c
@@ -0,0 +1,112 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ *
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ * LANDISK/sh4 supported by kogiidena
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned long vbr_reg) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+extern void *gdb_vbr_vector;
+
+/*
+ * Provide a dummy crash_notes definition while crash dump arrives to ppc.
+ * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
+ */
+void *crash_notes = NULL;
+
+void machine_shutdown(void)
+{
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
+/*
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+static void kexec_info(struct kimage *image)
+{
+ int i;
+ printk("kexec information\n");
+ for (i = 0; i < image->nr_segments; i++) {
+ printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n",
+ i,
+ (unsigned int)image->segment[i].mem,
+ (unsigned int)image->segment[i].mem + image->segment[i].memsz,
+ (unsigned int)image->segment[i].memsz);
+ }
+ printk(" start : 0x%08x\n\n", (unsigned int)image->start);
+}
+
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+
+ unsigned long page_list;
+ unsigned long reboot_code_buffer;
+ unsigned long vbr_reg;
+ relocate_new_kernel_t rnk;
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+ vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100;
+#else
+ vbr_reg = 0x80000000; // dummy
+#endif
+ /* Interrupts aren't acceptable while we reboot */
+ local_irq_disable();
+
+ page_list = image->head;
+
+ /* we need both effective and real address here */
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
+
+ /* copy our kernel relocation code to the control code page */
+ memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ kexec_info(image);
+ flush_cache_all();
+
+ /* now call it */
+ rnk = (relocate_new_kernel_t) reboot_code_buffer;
+ (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
+}
+
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index fd4f240b833d..a4dc2b532e10 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -71,6 +71,16 @@ void cpu_idle(void)
void machine_restart(char * __unused)
{
+
+#ifdef CONFIG_KEXEC
+ struct kimage *image;
+ image = xchg(&kexec_image, 0);
+ if (image) {
+ machine_shutdown();
+ machine_kexec(image);
+ }
+#endif
+
/* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
asm volatile("ldc %0, sr\n\t"
"mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
@@ -191,13 +201,8 @@ void flush_thread(void)
{
#if defined(CONFIG_SH_FPU)
struct task_struct *tsk = current;
- struct pt_regs *regs = (struct pt_regs *)
- ((unsigned long)tsk->thread_info
- + THREAD_SIZE - sizeof(struct pt_regs)
- - sizeof(unsigned long));
-
/* Forget lazy FPU state */
- clear_fpu(tsk, regs);
+ clear_fpu(tsk, task_pt_regs(tsk));
clear_used_math();
#endif
}
@@ -232,13 +237,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{
struct pt_regs ptregs;
- ptregs = *(struct pt_regs *)
- ((unsigned long)tsk->thread_info + THREAD_SIZE
- - sizeof(struct pt_regs)
-#ifdef CONFIG_SH_DSP
- - sizeof(struct pt_dspregs)
-#endif
- - sizeof(unsigned long));
+ ptregs = *task_pt_regs(tsk);
elf_core_copy_regs(regs, &ptregs);
return 1;
@@ -252,11 +251,7 @@ dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *fpu)
#if defined(CONFIG_SH_FPU)
fpvalid = !!tsk_used_math(tsk);
if (fpvalid) {
- struct pt_regs *regs = (struct pt_regs *)
- ((unsigned long)tsk->thread_info
- + THREAD_SIZE - sizeof(struct pt_regs)
- - sizeof(unsigned long));
- unlazy_fpu(tsk, regs);
+ unlazy_fpu(tsk, task_pt_regs(tsk));
memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
}
#endif
@@ -279,18 +274,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
copy_to_stopped_child_used_math(p);
#endif
- childregs = ((struct pt_regs *)
- (THREAD_SIZE + (unsigned long) p->thread_info)
-#ifdef CONFIG_SH_DSP
- - sizeof(struct pt_dspregs)
-#endif
- - sizeof(unsigned long)) - 1;
+ childregs = task_pt_regs(p);
*childregs = *regs;
if (user_mode(regs)) {
childregs->regs[15] = usp;
} else {
- childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE;
+ childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
}
if (clone_flags & CLONE_SETTLS) {
childregs->gbr = childregs->regs[0];
@@ -305,26 +295,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
return 0;
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- dump->magic = CMAGIC;
- dump->start_code = current->mm->start_code;
- dump->start_data = current->mm->start_data;
- dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
- dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
- dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
- dump->u_ssize = (current->mm->start_stack - dump->start_stack +
- PAGE_SIZE - 1) >> PAGE_SHIFT;
- /* Debug registers will come here. */
-
- dump->regs = *regs;
-
- dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
-}
-
/* Tracing by user break controller. */
static void
ubc_set_tracing(int asid, unsigned long pc)
@@ -353,11 +323,7 @@ ubc_set_tracing(int asid, unsigned long pc)
struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next)
{
#if defined(CONFIG_SH_FPU)
- struct pt_regs *regs = (struct pt_regs *)
- ((unsigned long)prev->thread_info
- + THREAD_SIZE - sizeof(struct pt_regs)
- - sizeof(unsigned long));
- unlazy_fpu(prev, regs);
+ unlazy_fpu(prev, task_pt_regs(prev));
#endif
#ifdef CONFIG_PREEMPT
@@ -366,13 +332,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
struct pt_regs *regs;
local_irq_save(flags);
- regs = (struct pt_regs *)
- ((unsigned long)prev->thread_info
- + THREAD_SIZE - sizeof(struct pt_regs)
-#ifdef CONFIG_SH_DSP
- - sizeof(struct pt_dspregs)
-#endif
- - sizeof(unsigned long));
+ regs = task_pt_regs(prev);
if (user_mode(regs) && regs->regs[15] >= 0xc0000000) {
int offset = (int)regs->regs[15];
@@ -392,7 +352,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
*/
asm volatile("ldc %0, r7_bank"
: /* no output */
- : "r" (next->thread_info));
+ : "r" (task_thread_info(next)));
#ifdef CONFIG_MMU
/* If no tasks are using the UBC, we're done */
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 1a8be06519ec..3887b4f6feb2 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -41,12 +41,7 @@ static inline int get_stack_long(struct task_struct *task, int offset)
{
unsigned char *stack;
- stack = (unsigned char *)
- task->thread_info + THREAD_SIZE - sizeof(struct pt_regs)
-#ifdef CONFIG_SH_DSP
- - sizeof(struct pt_dspregs)
-#endif
- - sizeof(unsigned long);
+ stack = (unsigned char *)task_pt_regs(task);
stack += offset;
return (*((int *)stack));
}
@@ -59,12 +54,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
{
unsigned char *stack;
- stack = (unsigned char *)
- task->thread_info + THREAD_SIZE - sizeof(struct pt_regs)
-#ifdef CONFIG_SH_DSP
- - sizeof(struct pt_dspregs)
-#endif
- - sizeof(unsigned long);
+ stack = (unsigned char *)task_pt_regs(task);
stack += offset;
*(unsigned long *) stack = data;
return 0;
diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..b0695cffec6e
--- /dev/null
+++ b/arch/sh/kernel/relocate_kernel.S
@@ -0,0 +1,102 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * 2005.9.17 kogiidena@eggplant.ddo.jp
+ *
+ * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+
+#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */
+
+
+ .globl relocate_new_kernel
+relocate_new_kernel:
+ /* r4 = indirection_page */
+ /* r5 = reboot_code_buffer */
+ /* r6 = start_address */
+ /* r7 = vbr_reg */
+
+ mov.l 10f,r8 /* 4096 */
+ mov.l 11f,r9 /* 0xa0000000 */
+
+ /* stack setting */
+ add r8,r5
+ mov r5,r15
+
+ bra 1f
+ mov r4,r0 /* cmd = indirection_page */
+0:
+ mov.l @r4+,r0 /* cmd = *ind++ */
+
+1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */
+ mov r0,r2
+ or r9,r2
+ mov #-16,r1
+ and r1,r2
+
+ /* if(cmd & IND_DESTINATION) dst = addr */
+ tst #1,r0
+ bt 2f
+ bra 0b
+ mov r2,r5
+
+2: /* else if(cmd & IND_INDIRECTION) ind = addr */
+ tst #2,r0
+ bt 3f
+ bra 0b
+ mov r2,r4
+
+3: /* else if(cmd & IND_DONE) goto 6 */
+ tst #4,r0
+ bt 4f
+ bra 6f
+ nop
+
+4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
+ tst #8,r0
+ bt 0b
+
+ mov r8,r3
+ shlr2 r3
+ shlr2 r3
+5:
+ dt r3
+ mov.l @r2+,r1 /* 16n+0 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+4 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+8 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+12 */
+ mov.l r1,@r5
+ add #4,r5
+ bf 5b
+
+ bra 0b
+ nop
+6:
+#ifdef CONFIG_SH_STANDARD_BIOS
+ ldc r7, vbr
+#endif
+ jmp @r6
+ nop
+
+ .align 2
+10:
+ .long PAGE_SIZE
+11:
+ .long 0xa0000000
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 6954fd62470a..1cf94a618be3 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -21,14 +21,12 @@
#include <asm/cacheflush.h>
#include <asm/checksum.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
extern struct hw_interrupt_type no_irq_type;
EXPORT_SYMBOL(sh_mv);
/* platform dependent support */
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(enable_irq);
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 59e49b18252c..62c7d1c0ad7b 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -103,7 +103,7 @@ int __cpu_up(unsigned int cpu)
if (IS_ERR(tsk))
panic("Failed forking idle task for cpu %d\n", cpu);
- tsk->thread_info->cpu = cpu;
+ task_thread_info(tsk)->cpu = cpu;
cpu_set(cpu, cpu_online_map);
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 671b876416bf..314a275c04e0 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
* Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
*
* Some code taken from i386 version.
@@ -11,50 +11,21 @@
*/
#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/init.h>
-#include <linux/smp.h>
#include <linux/profile.h>
-
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/machvec.h>
+#include <asm/clock.h>
#include <asm/rtc.h>
-#include <asm/freq.h>
-#include <asm/cpu/timer.h>
-#ifdef CONFIG_SH_KGDB
+#include <asm/timer.h>
#include <asm/kgdb.h>
-#endif
-
-#include <linux/timex.h>
-#include <linux/irq.h>
-
-#define TMU_TOCR_INIT 0x00
-#define TMU0_TCR_INIT 0x0020
-#define TMU_TSTR_INIT 1
-
-#define TMU0_TCR_CALIB 0x0000
-
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-#define CLOCKGEN_MEMCLKCR 0xbb040038
-#define MEMCLKCR_RATIO_MASK 0x7
-#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
extern unsigned long wall_jiffies;
-#define TICK_SIZE (tick_nsec / 1000)
-DEFINE_SPINLOCK(tmu0_lock);
+struct sys_timer *sys_timer;
+
+/* Move this somewhere more sensible.. */
+DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want
* these routines anywhere... */
@@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *);
int (*rtc_set_time)(const time_t);
#endif
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
-#endif
-#if defined(CONFIG_CPU_SH3)
-static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
-static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
-#define bfc_divisors stc_multipliers
-#define bfc_values stc_values
-static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
-static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 };
-static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
-static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
-#elif defined(CONFIG_CPU_SH4)
-#if defined(CONFIG_CPU_SUBTYPE_SH73180)
-static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
-static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
-#define bfc_divisors ifc_divisors /* Same */
-#define bfc_values ifc_values
-#define pfc_divisors ifc_divisors /* Same */
-#define pfc_values ifc_values
-#else
-static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
-static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 };
-#define bfc_divisors ifc_divisors /* Same */
-#define bfc_values ifc_values
-static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
-static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 };
-#endif
-#else
-#error "Unknown ifc/bfc/pfc/stc values for this processor"
-#endif
-
/*
* Scheduler clock - returns current time in nanosec units.
*/
-unsigned long long sched_clock(void)
+unsigned long long __attribute__ ((weak)) sched_clock(void)
{
return (unsigned long long)jiffies * (1000000000 / HZ);
}
-static unsigned long do_gettimeoffset(void)
-{
- int count;
- unsigned long flags;
-
- static int count_p = 0x7fffffff; /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- spin_lock_irqsave(&tmu0_lock, flags);
- /* timer count may underflow right here */
- count = ctrl_inl(TMU0_TCNT); /* read the latched count */
-
- jiffies_t = jiffies;
-
- /*
- * avoiding timer inconsistencies (they are rare, but they happen)...
- * there is one kind of problem that must be avoided here:
- * 1. the timer counter underflows
- */
-
- if( jiffies_t == jiffies_p ) {
- if( count > count_p ) {
- /* the nutcase */
-
- if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
- /*
- * We cannot detect lost timer interrupts ...
- * well, that's why we call them lost, don't we? :)
- * [hmm, on the Pentium and Alpha we can ... sort of]
- */
- count -= LATCH;
- } else {
- printk("do_slow_gettimeoffset(): hardware timer problem?\n");
- }
- }
- } else
- jiffies_p = jiffies_t;
-
- count_p = count;
- spin_unlock_irqrestore(&tmu0_lock, flags);
-
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
-
- return count;
-}
-
void do_gettimeofday(struct timeval *tv)
{
unsigned long seq;
@@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv)
do {
seq = read_seqbegin(&xtime_lock);
- usec = do_gettimeoffset();
+ usec = get_timer_offset();
lost = jiffies - wall_jiffies;
if (lost)
@@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- nsec -= 1000 * (do_gettimeoffset() +
+ nsec -= 1000 * (get_timer_offset() +
(jiffies - wall_jiffies) * (1000000 / HZ));
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
@@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday);
static long last_rtc_update;
/*
- * timer_interrupt() needs to keep up the real-time clock,
+ * handle_timer_tick() 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, struct pt_regs *regs)
+void handle_timer_tick(struct pt_regs *regs)
{
do_timer(regs);
#ifndef CONFIG_SMP
@@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
if (rtc_set_time(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ /* do it again in 60s */
+ last_rtc_update = xtime.tv_sec - 600;
}
}
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long timer_status;
-
- /* Clear UNF bit */
- timer_status = ctrl_inw(TMU0_TCR);
- timer_status &= ~0x100;
- ctrl_outw(timer_status, TMU0_TCR);
-
- /*
- * Here we are in the timer irq handler. We just have irqs locally
- * disabled but we don't know if the timer_bh is running on the other
- * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
- * the irq version of write_lock because as just said we have irq
- * locally disabled. -arca
- */
- write_seqlock(&xtime_lock);
- do_timer_interrupt(irq, regs);
- write_sequnlock(&xtime_lock);
-
- return IRQ_HANDLED;
-}
-
-/*
- * Hah! We'll see if this works (switching from usecs to nsecs).
- */
-static unsigned int __init get_timer_frequency(void)
-{
- u32 freq;
- struct timespec ts1, ts2;
- unsigned long diff_nsec;
- unsigned long factor;
-
- /* Setup the timer: We don't want to generate interrupts, just
- * have it count down at its natural rate.
- */
- ctrl_outb(0, TMU_TSTR);
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
- ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-#endif
- ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
- ctrl_outl(0xffffffff, TMU0_TCOR);
- ctrl_outl(0xffffffff, TMU0_TCNT);
-
- rtc_get_time(&ts2);
-
- do {
- rtc_get_time(&ts1);
- } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
- /* actually start the timer */
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
-
- do {
- rtc_get_time(&ts2);
- } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
-
- freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
- if (ts2.tv_nsec < ts1.tv_nsec) {
- ts2.tv_nsec += 1000000000;
- ts2.tv_sec--;
- }
-
- diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
-
- /* this should work well if the RTC has a precision of n Hz, where
- * n is an integer. I don't think we have to worry about the other
- * cases. */
- factor = (1000000000 + diff_nsec/2) / diff_nsec;
-
- if (factor * diff_nsec > 1100000000 ||
- factor * diff_nsec < 900000000)
- panic("weird RTC (diff_nsec %ld)", diff_nsec);
-
- return freq * factor;
-}
-
-void (*board_time_init)(void);
-void (*board_timer_setup)(struct irqaction *irq);
-
-static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ;
-
-static int __init sh_pclk_setup(char *str)
-{
- unsigned int freq;
-
- if (get_option(&str, &freq))
- sh_pclk_freq = freq;
-
- return 1;
-}
-__setup("sh_pclk=", sh_pclk_setup);
-
-static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
-
-void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc)
-{
- unsigned int frqcr = ctrl_inw(FRQCR);
-
-#if defined(CONFIG_CPU_SH3)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
- *ifc = md_table[((frqcr & 0x0070) >> 4)];
- *bfc = md_table[((frqcr & 0x0700) >> 8)];
- *pfc = md_table[frqcr & 0x0007];
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
- *bfc = stc_multipliers[(frqcr & 0x0300) >> 8];
- *ifc = ifc_divisors[(frqcr & 0x0030) >> 4];
- *pfc = pfc_divisors[frqcr & 0x0003];
-#else
- unsigned int tmp;
-
- tmp = (frqcr & 0x8000) >> 13;
- tmp |= (frqcr & 0x0030) >> 4;
- *bfc = stc_multipliers[tmp];
- tmp = (frqcr & 0x4000) >> 12;
- tmp |= (frqcr & 0x000c) >> 2;
- *ifc = ifc_divisors[tmp];
- tmp = (frqcr & 0x2000) >> 11;
- tmp |= frqcr & 0x0003;
- *pfc = pfc_divisors[tmp];
-#endif
-#elif defined(CONFIG_CPU_SH4)
-#if defined(CONFIG_CPU_SUBTYPE_SH73180)
- *ifc = ifc_divisors[(frqcr>> 20) & 0x0007];
- *bfc = bfc_divisors[(frqcr>> 12) & 0x0007];
- *pfc = pfc_divisors[frqcr & 0x0007];
-#else
- *ifc = ifc_divisors[(frqcr >> 6) & 0x0007];
- *bfc = bfc_divisors[(frqcr >> 3) & 0x0007];
- *pfc = pfc_divisors[frqcr & 0x0007];
-#endif
-#endif
-}
-
-/*
- * This bit of ugliness builds up accessor routines to get at both
- * the divisors and the physical values.
- */
-#define _FREQ_TABLE(x) \
- unsigned int get_##x##_divisor(unsigned int value) \
- { return x##_divisors[value]; } \
- \
- unsigned int get_##x##_value(unsigned int divisor) \
- { return x##_values[(divisor - 1)]; }
-
-_FREQ_TABLE(ifc);
-_FREQ_TABLE(bfc);
-_FREQ_TABLE(pfc);
-
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-
-/*
- * The ST40 divisors are totally different so we set the cpu data
- * clocks using a different algorithm
- *
- * I've just plugged this from the 2.4 code
- * - Alex Bennee <kernel-hacker@bennee.com>
- */
-#define CCN_PVR_CHIP_SHIFT 24
-#define CCN_PVR_CHIP_MASK 0xff
-#define CCN_PVR_CHIP_ST40STB1 0x4
-
-
-struct frqcr_data {
- unsigned short frqcr;
-
- struct {
- unsigned char multiplier;
- unsigned char divisor;
- } factor[3];
-};
-
-static struct frqcr_data st40_frqcr_table[] = {
- { 0x000, {{1,1}, {1,1}, {1,2}}},
- { 0x002, {{1,1}, {1,1}, {1,4}}},
- { 0x004, {{1,1}, {1,1}, {1,8}}},
- { 0x008, {{1,1}, {1,2}, {1,2}}},
- { 0x00A, {{1,1}, {1,2}, {1,4}}},
- { 0x00C, {{1,1}, {1,2}, {1,8}}},
- { 0x011, {{1,1}, {2,3}, {1,6}}},
- { 0x013, {{1,1}, {2,3}, {1,3}}},
- { 0x01A, {{1,1}, {1,2}, {1,4}}},
- { 0x01C, {{1,1}, {1,2}, {1,8}}},
- { 0x023, {{1,1}, {2,3}, {1,3}}},
- { 0x02C, {{1,1}, {1,2}, {1,8}}},
- { 0x048, {{1,2}, {1,2}, {1,4}}},
- { 0x04A, {{1,2}, {1,2}, {1,6}}},
- { 0x04C, {{1,2}, {1,2}, {1,8}}},
- { 0x05A, {{1,2}, {1,3}, {1,6}}},
- { 0x05C, {{1,2}, {1,3}, {1,6}}},
- { 0x063, {{1,2}, {1,4}, {1,4}}},
- { 0x06C, {{1,2}, {1,4}, {1,8}}},
- { 0x091, {{1,3}, {1,3}, {1,6}}},
- { 0x093, {{1,3}, {1,3}, {1,6}}},
- { 0x0A3, {{1,3}, {1,6}, {1,6}}},
- { 0x0DA, {{1,4}, {1,4}, {1,8}}},
- { 0x0DC, {{1,4}, {1,4}, {1,8}}},
- { 0x0EC, {{1,4}, {1,8}, {1,8}}},
- { 0x123, {{1,4}, {1,4}, {1,8}}},
- { 0x16C, {{1,4}, {1,8}, {1,8}}},
+static struct sysdev_class timer_sysclass = {
+ set_kset_name("timer"),
};
-struct memclk_data {
- unsigned char multiplier;
- unsigned char divisor;
-};
-
-static struct memclk_data st40_memclk_table[8] = {
- {1,1}, // 000
- {1,2}, // 001
- {1,3}, // 010
- {2,3}, // 011
- {1,4}, // 100
- {1,6}, // 101
- {1,8}, // 110
- {1,8} // 111
-};
-
-static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr)
+static int __init timer_init_sysfs(void)
{
- unsigned int cpu_clock, master_clock, bus_clock, memory_clock;
- struct frqcr_data *d;
- int a;
- unsigned long memclkcr;
- struct memclk_data *e;
+ int ret = sysdev_class_register(&timer_sysclass);
+ if (ret != 0)
+ return ret;
- for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) {
- d = &st40_frqcr_table[a];
-
- if (d->frqcr == (frqcr & 0x1ff))
- break;
- }
+ sys_timer->dev.cls = &timer_sysclass;
+ return sysdev_register(&sys_timer->dev);
+}
- if (a == ARRAY_SIZE(st40_frqcr_table)) {
- d = st40_frqcr_table;
+device_initcall(timer_init_sysfs);
- printk("ERROR: Unrecognised FRQCR value (0x%x), "
- "using default multipliers\n", frqcr);
- }
-
- memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
- e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
-
- printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d "
- "Mem: %d/%d Periph: %d/%d\n",
- d->factor[0].multiplier, d->factor[0].divisor,
- d->factor[1].multiplier, d->factor[1].divisor,
- e->multiplier, e->divisor,
- d->factor[2].multiplier, d->factor[2].divisor);
-
- master_clock = module_clock * d->factor[2].divisor
- / d->factor[2].multiplier;
- bus_clock = master_clock * d->factor[1].multiplier
- / d->factor[1].divisor;
- memory_clock = master_clock * e->multiplier
- / e->divisor;
- cpu_clock = master_clock * d->factor[0].multiplier
- / d->factor[0].divisor;
-
- current_cpu_data.cpu_clock = cpu_clock;
- current_cpu_data.master_clock = master_clock;
- current_cpu_data.bus_clock = bus_clock;
- current_cpu_data.memory_clock = memory_clock;
- current_cpu_data.module_clock = module_clock;
-}
-#endif
+void (*board_time_init)(void);
void __init time_init(void)
{
- unsigned int timer_freq = 0;
- unsigned int ifc, pfc, bfc;
- unsigned long interval;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
- unsigned long pvr;
- unsigned short frqcr;
-#endif
-
if (board_time_init)
board_time_init();
- /*
- * If we don't have an RTC (such as with the SH7300), don't attempt to
- * probe the timer frequency. Rely on an either hardcoded peripheral
- * clock value, or on the sh_pclk command line option. Note that we
- * still need to have CONFIG_SH_PCLK_FREQ set in order for things like
- * CLOCK_TICK_RATE to be sane.
- */
- current_cpu_data.module_clock = sh_pclk_freq;
-
-#ifdef CONFIG_SH_PCLK_CALC
- /* XXX: Switch this over to a more generic test. */
- {
- unsigned int freq;
-
- /*
- * If we've specified a peripheral clock frequency, and we have
- * an RTC, compare it against the autodetected value. Complain
- * if there's a mismatch.
- */
- timer_freq = get_timer_frequency();
- freq = timer_freq * 4;
-
- if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) {
- printk(KERN_NOTICE "Calculated peripheral clock value "
- "%d differs from sh_pclk value %d, fixing..\n",
- freq, sh_pclk_freq);
- current_cpu_data.module_clock = freq;
- }
- }
-#endif
-
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
- /* XXX: Update ST40 code to use board_time_init() */
- pvr = ctrl_inl(CCN_PVR);
- frqcr = ctrl_inw(FRQCR);
- printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr);
-
- if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1)
- st40_specific_time_init(current_cpu_data.module_clock, frqcr);
- else
-#endif
- get_current_frequency_divisors(&ifc, &bfc, &pfc);
+ clk_init();
if (rtc_get_time) {
rtc_get_time(&xtime);
@@ -594,51 +179,12 @@ void __init time_init(void)
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
- if (board_timer_setup) {
- board_timer_setup(&irq0);
- } else {
- setup_irq(TIMER_IRQ, &irq0);
- }
-
/*
- * for ST40 chips the current_cpu_data should already be set
- * so not having valid pfc/bfc/ifc shouldn't be a problem
+ * Find the timer to use as the system timer, it will be
+ * initialized for us.
*/
- if (!current_cpu_data.master_clock)
- current_cpu_data.master_clock = current_cpu_data.module_clock * pfc;
- if (!current_cpu_data.bus_clock)
- current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc;
- if (!current_cpu_data.cpu_clock)
- current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc;
-
- printk("CPU clock: %d.%02dMHz\n",
- (current_cpu_data.cpu_clock / 1000000),
- (current_cpu_data.cpu_clock % 1000000)/10000);
- printk("Bus clock: %d.%02dMHz\n",
- (current_cpu_data.bus_clock / 1000000),
- (current_cpu_data.bus_clock % 1000000)/10000);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
- printk("Memory clock: %d.%02dMHz\n",
- (current_cpu_data.memory_clock / 1000000),
- (current_cpu_data.memory_clock % 1000000)/10000);
-#endif
- printk("Module clock: %d.%02dMHz\n",
- (current_cpu_data.module_clock / 1000000),
- (current_cpu_data.module_clock % 1000000)/10000);
-
- interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ;
-
- printk("Interval = %ld\n", interval);
-
- /* Start TMU0 */
- ctrl_outb(0, TMU_TSTR);
-#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
- ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
-#endif
- ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
- ctrl_outl(interval, TMU0_TCOR);
- ctrl_outl(interval, TMU0_TCNT);
- ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+ sys_timer = get_sys_timer();
+ printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
#if defined(CONFIG_SH_KGDB)
/*
diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile
new file mode 100644
index 000000000000..151a6a304cec
--- /dev/null
+++ b/arch/sh/kernel/timers/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the various Linux/SuperH timers
+#
+
+obj-y := timer.o
+
+obj-$(CONFIG_SH_TMU) += timer-tmu.o
+
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
new file mode 100644
index 000000000000..96a64cb13106
--- /dev/null
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -0,0 +1,229 @@
+/*
+ * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * TMU handling code hacked out of arch/sh/kernel/time.c
+ *
+ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/seqlock.h>
+#include <asm/timer.h>
+#include <asm/rtc.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/clock.h>
+
+#define TMU_TOCR_INIT 0x00
+#define TMU0_TCR_INIT 0x0020
+#define TMU_TSTR_INIT 1
+
+#define TMU0_TCR_CALIB 0x0000
+
+static DEFINE_SPINLOCK(tmu0_lock);
+
+static unsigned long tmu_timer_get_offset(void)
+{
+ int count;
+ unsigned long flags;
+
+ static int count_p = 0x7fffffff; /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ spin_lock_irqsave(&tmu0_lock, flags);
+ /* timer count may underflow right here */
+ count = ctrl_inl(TMU0_TCNT); /* read the latched count */
+
+ jiffies_t = jiffies;
+
+ /*
+ * avoiding timer inconsistencies (they are rare, but they happen)...
+ * there is one kind of problem that must be avoided here:
+ * 1. the timer counter underflows
+ */
+
+ if (jiffies_t == jiffies_p) {
+ if (count > count_p) {
+ /* the nutcase */
+ if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
+ count -= LATCH;
+ } else {
+ printk("%s (): hardware timer problem?\n",
+ __FUNCTION__);
+ }
+ }
+ } else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+ spin_unlock_irqrestore(&tmu0_lock, flags);
+
+ count = ((LATCH-1) - count) * TICK_SIZE;
+ count = (count + LATCH/2) / LATCH;
+
+ return count;
+}
+
+static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ unsigned long timer_status;
+
+ /* Clear UNF bit */
+ timer_status = ctrl_inw(TMU0_TCR);
+ timer_status &= ~0x100;
+ ctrl_outw(timer_status, TMU0_TCR);
+
+ /*
+ * Here we are in the timer irq handler. We just have irqs locally
+ * disabled but we don't know if the timer_bh is running on the other
+ * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+ * the irq version of write_lock because as just said we have irq
+ * locally disabled. -arca
+ */
+ write_seqlock(&xtime_lock);
+ handle_timer_tick(regs);
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction tmu_irq = {
+ .name = "timer",
+ .handler = tmu_timer_interrupt,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+};
+
+/*
+ * Hah! We'll see if this works (switching from usecs to nsecs).
+ */
+static unsigned long tmu_timer_get_frequency(void)
+{
+ u32 freq;
+ struct timespec ts1, ts2;
+ unsigned long diff_nsec;
+ unsigned long factor;
+
+ /* Setup the timer: We don't want to generate interrupts, just
+ * have it count down at its natural rate.
+ */
+ ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
+ ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
+ ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
+ ctrl_outl(0xffffffff, TMU0_TCOR);
+ ctrl_outl(0xffffffff, TMU0_TCNT);
+
+ rtc_get_time(&ts2);
+
+ do {
+ rtc_get_time(&ts1);
+ } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
+
+ /* actually start the timer */
+ ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+
+ do {
+ rtc_get_time(&ts2);
+ } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
+
+ freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
+ if (ts2.tv_nsec < ts1.tv_nsec) {
+ ts2.tv_nsec += 1000000000;
+ ts2.tv_sec--;
+ }
+
+ diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
+
+ /* this should work well if the RTC has a precision of n Hz, where
+ * n is an integer. I don't think we have to worry about the other
+ * cases. */
+ factor = (1000000000 + diff_nsec/2) / diff_nsec;
+
+ if (factor * diff_nsec > 1100000000 ||
+ factor * diff_nsec < 900000000)
+ panic("weird RTC (diff_nsec %ld)", diff_nsec);
+
+ return freq * factor;
+}
+
+static void tmu_clk_init(struct clk *clk)
+{
+ u8 divisor = TMU0_TCR_INIT & 0x7;
+ ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
+ clk->rate = clk->parent->rate / (4 << (divisor << 1));
+}
+
+static void tmu_clk_recalc(struct clk *clk)
+{
+ u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
+ clk->rate = clk->parent->rate / (4 << (divisor << 1));
+}
+
+static struct clk_ops tmu_clk_ops = {
+ .init = tmu_clk_init,
+ .recalc = tmu_clk_recalc,
+};
+
+static struct clk tmu0_clk = {
+ .name = "tmu0_clk",
+ .ops = &tmu_clk_ops,
+};
+
+static int tmu_timer_init(void)
+{
+ unsigned long interval;
+
+ setup_irq(TIMER_IRQ, &tmu_irq);
+
+ tmu0_clk.parent = clk_get("module_clk");
+
+ /* Start TMU0 */
+ ctrl_outb(0, TMU_TSTR);
+#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
+ ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+#endif
+
+ clk_register(&tmu0_clk);
+ clk_enable(&tmu0_clk);
+
+ interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ;
+ printk(KERN_INFO "Interval = %ld\n", interval);
+
+ ctrl_outl(interval, TMU0_TCOR);
+ ctrl_outl(interval, TMU0_TCNT);
+
+ ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+
+ return 0;
+}
+
+struct sys_timer_ops tmu_timer_ops = {
+ .init = tmu_timer_init,
+ .get_frequency = tmu_timer_get_frequency,
+ .get_offset = tmu_timer_get_offset,
+};
+
+struct sys_timer tmu_timer = {
+ .name = "tmu",
+ .ops = &tmu_timer_ops,
+};
+
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
new file mode 100644
index 000000000000..dc1f631053a8
--- /dev/null
+++ b/arch/sh/kernel/timers/timer.c
@@ -0,0 +1,50 @@
+/*
+ * arch/sh/kernel/timers/timer.c - Common timer code
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <asm/timer.h>
+
+static struct sys_timer *sys_timers[] __initdata = {
+#ifdef CONFIG_SH_TMU
+ &tmu_timer,
+#endif
+ NULL,
+};
+
+static char timer_override[10] __initdata;
+static int __init timer_setup(char *str)
+{
+ if (str)
+ strlcpy(timer_override, str, sizeof(timer_override));
+ return 1;
+}
+__setup("timer=", timer_setup);
+
+struct sys_timer *get_sys_timer(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sys_timers); i++) {
+ struct sys_timer *t = sys_timers[i];
+
+ if (unlikely(!t))
+ break;
+ if (unlikely(timer_override[0]))
+ if ((strcmp(timer_override, t->name) != 0))
+ continue;
+ if (likely(t->ops->init() == 0))
+ return t;
+ }
+
+ return NULL;
+}
+
diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig
new file mode 100644
index 000000000000..fb586b1cf8bb
--- /dev/null
+++ b/arch/sh/mm/Kconfig
@@ -0,0 +1,233 @@
+menu "Processor selection"
+
+#
+# Processor families
+#
+config CPU_SH2
+ bool
+ select SH_WRITETHROUGH
+
+config CPU_SH3
+ bool
+ select CPU_HAS_INTEVT
+ select CPU_HAS_SR_RB
+
+config CPU_SH4
+ bool
+ select CPU_HAS_INTEVT
+ select CPU_HAS_SR_RB
+
+config CPU_SH4A
+ bool
+ select CPU_SH4
+ select CPU_HAS_INTC2_IRQ
+
+config CPU_SUBTYPE_ST40
+ bool
+ select CPU_SH4
+ select CPU_HAS_INTC2_IRQ
+
+#
+# Processor subtypes
+#
+
+comment "SH-2 Processor Support"
+
+config CPU_SUBTYPE_SH7604
+ bool "Support SH7604 processor"
+ select CPU_SH2
+
+comment "SH-3 Processor Support"
+
+config CPU_SUBTYPE_SH7300
+ bool "Support SH7300 processor"
+ select CPU_SH3
+
+config CPU_SUBTYPE_SH7705
+ bool "Support SH7705 processor"
+ select CPU_SH3
+ select CPU_HAS_PINT_IRQ
+
+config CPU_SUBTYPE_SH7707
+ bool "Support SH7707 processor"
+ select CPU_SH3
+ select CPU_HAS_PINT_IRQ
+ help
+ Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU.
+
+config CPU_SUBTYPE_SH7708
+ bool "Support SH7708 processor"
+ select CPU_SH3
+ help
+ Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or
+ if you have a 100 Mhz SH-3 HD6417708R CPU.
+
+config CPU_SUBTYPE_SH7709
+ bool "Support SH7709 processor"
+ select CPU_SH3
+ select CPU_HAS_PINT_IRQ
+ help
+ Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU.
+
+comment "SH-4 Processor Support"
+
+config CPU_SUBTYPE_SH7750
+ bool "Support SH7750 processor"
+ select CPU_SH4
+ help
+ Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
+
+config CPU_SUBTYPE_SH7091
+ bool "Support SH7091 processor"
+ select CPU_SH4
+ select CPU_SUBTYPE_SH7750
+ help
+ Select SH7091 if you have an SH-4 based Sega device (such as
+ the Dreamcast, Naomi, and Naomi 2).
+
+config CPU_SUBTYPE_SH7750R
+ bool "Support SH7750R processor"
+ select CPU_SH4
+ select CPU_SUBTYPE_SH7750
+
+config CPU_SUBTYPE_SH7750S
+ bool "Support SH7750S processor"
+ select CPU_SH4
+ select CPU_SUBTYPE_SH7750
+
+config CPU_SUBTYPE_SH7751
+ bool "Support SH7751 processor"
+ select CPU_SH4
+ help
+ Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU,
+ or if you have a HD6417751R CPU.
+
+config CPU_SUBTYPE_SH7751R
+ bool "Support SH7751R processor"
+ select CPU_SH4
+ select CPU_SUBTYPE_SH7751
+
+config CPU_SUBTYPE_SH7760
+ bool "Support SH7760 processor"
+ select CPU_SH4
+ select CPU_HAS_INTC2_IRQ
+
+config CPU_SUBTYPE_SH4_202
+ bool "Support SH4-202 processor"
+ select CPU_SH4
+
+comment "ST40 Processor Support"
+
+config CPU_SUBTYPE_ST40STB1
+ bool "Support ST40STB1/ST40RA processors"
+ select CPU_SUBTYPE_ST40
+ help
+ Select ST40STB1 if you have a ST40RA CPU.
+ This was previously called the ST40STB1, hence the option name.
+
+config CPU_SUBTYPE_ST40GX1
+ bool "Support ST40GX1 processor"
+ select CPU_SUBTYPE_ST40
+ help
+ Select ST40GX1 if you have a ST40GX1 CPU.
+
+comment "SH-4A Processor Support"
+
+config CPU_SUBTYPE_SH73180
+ bool "Support SH73180 processor"
+ select CPU_SH4A
+
+config CPU_SUBTYPE_SH7770
+ bool "Support SH7770 processor"
+ select CPU_SH4A
+
+config CPU_SUBTYPE_SH7780
+ bool "Support SH7780 processor"
+ select CPU_SH4A
+
+endmenu
+
+menu "Memory management options"
+
+config MMU
+ bool "Support for memory management hardware"
+ depends on !CPU_SH2
+ default y
+ help
+ Some SH processors (such as SH-2/SH-2A) lack an MMU. In order to
+ boot on these systems, this option must not be set.
+
+ On other systems (such as the SH-3 and 4) where an MMU exists,
+ turning this off will boot the kernel on these machines with the
+ MMU implicitly switched off.
+
+config 32BIT
+ bool "Support 32-bit physical addressing through PMB"
+ depends on CPU_SH4A
+ default y
+ help
+ If you say Y here, physical addressing will be extended to
+ 32-bits through the SH-4A PMB. If this is not set, legacy
+ 29-bit physical addressing will be used.
+
+choice
+ prompt "HugeTLB page size"
+ depends on HUGETLB_PAGE && CPU_SH4 && MMU
+ default HUGETLB_PAGE_SIZE_64K
+
+config HUGETLB_PAGE_SIZE_64K
+ bool "64K"
+
+config HUGETLB_PAGE_SIZE_1MB
+ bool "1MB"
+
+endchoice
+
+source "mm/Kconfig"
+
+endmenu
+
+menu "Cache configuration"
+
+config SH7705_CACHE_32KB
+ bool "Enable 32KB cache size for SH7705"
+ depends on CPU_SUBTYPE_SH7705
+ default y
+
+config SH_DIRECT_MAPPED
+ bool "Use direct-mapped caching"
+ default n
+ help
+ Selecting this option will configure the caches to be direct-mapped,
+ even if the cache supports a 2 or 4-way mode. This is useful primarily
+ for debugging on platforms with 2 and 4-way caches (SH7750R/SH7751R,
+ SH4-202, SH4-501, etc.)
+
+ Turn this option off for platforms that do not have a direct-mapped
+ cache, and you have no need to run the caches in such a configuration.
+
+config SH_WRITETHROUGH
+ bool "Use write-through caching"
+ default y if CPU_SH2
+ help
+ Selecting this option will configure the caches in write-through
+ mode, as opposed to the default write-back configuration.
+
+ Since there's sill some aliasing issues on SH-4, this option will
+ unfortunately still require the majority of flushing functions to
+ be implemented to deal with aliasing.
+
+ If unsure, say N.
+
+config SH_OCRAM
+ bool "Operand Cache RAM (OCRAM) support"
+ help
+ Selecting this option will automatically tear down the number of
+ sets in the dcache by half, which in turn exposes a memory range.
+
+ The addresses for the OC RAM base will vary according to the
+ processor version. Consult vendor documentation for specifics.
+
+ If unsure, say N.
+
+endmenu
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index e794e27a72f1..96fa4a999e2a 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -6,13 +6,19 @@
* 640k-1MB IO memory area on PC's
*
* (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2005, 2006 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
*/
-
#include <linux/vmalloc.h>
+#include <linux/module.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
+#include <asm/addrspace.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -80,9 +86,15 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
if (address >= end)
BUG();
do {
+ pud_t *pud;
pmd_t *pmd;
- pmd = pmd_alloc(&init_mm, dir, address);
+
error = -ENOMEM;
+
+ pud = pud_alloc(&init_mm, dir, address);
+ if (!pud)
+ break;
+ pmd = pmd_alloc(&init_mm, pud, address);
if (!pmd)
break;
if (remap_area_pmd(pmd, address, end - address,
@@ -97,10 +109,6 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
}
/*
- * Generic mapping function (not visible outside):
- */
-
-/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
* directly.
@@ -109,11 +117,11 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr,
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
-void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
+ unsigned long flags)
{
- void * addr;
struct vm_struct * area;
- unsigned long offset, last_addr;
+ unsigned long offset, last_addr, addr, orig_addr;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -124,7 +132,7 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla
* Don't remap the low PCI/ISA area, it's always mapped..
*/
if (phys_addr >= 0xA0000 && last_addr < 0x100000)
- return phys_to_virt(phys_addr);
+ return (void __iomem *)phys_to_virt(phys_addr);
/*
* Don't allow anybody to remap normal RAM that we're using..
@@ -146,16 +154,71 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla
if (!area)
return NULL;
area->phys_addr = phys_addr;
- addr = area->addr;
- if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
- vunmap(addr);
- return NULL;
+ orig_addr = addr = (unsigned long)area->addr;
+
+#ifdef CONFIG_32BIT
+ /*
+ * First try to remap through the PMB once a valid VMA has been
+ * established. Smaller allocations (or the rest of the size
+ * remaining after a PMB mapping due to the size not being
+ * perfectly aligned on a PMB size boundary) are then mapped
+ * through the UTLB using conventional page tables.
+ *
+ * PMB entries are all pre-faulted.
+ */
+ if (unlikely(size >= 0x1000000)) {
+ unsigned long mapped = pmb_remap(addr, phys_addr, size, flags);
+
+ if (likely(mapped)) {
+ addr += mapped;
+ phys_addr += mapped;
+ size -= mapped;
+ }
}
- return (void *) (offset + (char *)addr);
+#endif
+
+ if (likely(size))
+ if (remap_area_pages(addr, phys_addr, size, flags)) {
+ vunmap((void *)orig_addr);
+ return NULL;
+ }
+
+ return (void __iomem *)(offset + (char *)orig_addr);
}
+EXPORT_SYMBOL(__ioremap);
-void p3_iounmap(void *addr)
+void __iounmap(void __iomem *addr)
{
- if (addr > high_memory)
- vfree((void *)(PAGE_MASK & (unsigned long)addr));
+ unsigned long vaddr = (unsigned long __force)addr;
+ struct vm_struct *p;
+
+ if (PXSEG(vaddr) < P3SEG)
+ return;
+
+#ifdef CONFIG_32BIT
+ /*
+ * Purge any PMB entries that may have been established for this
+ * mapping, then proceed with conventional VMA teardown.
+ *
+ * XXX: Note that due to the way that remove_vm_area() does
+ * matching of the resultant VMA, we aren't able to fast-forward
+ * the address past the PMB space until the end of the VMA where
+ * the page tables reside. As such, unmap_vm_area() will be
+ * forced to linearly scan over the area until it finds the page
+ * tables where PTEs that need to be unmapped actually reside,
+ * which is far from optimal. Perhaps we need to use a separate
+ * VMA for the PMB mappings?
+ * -- PFM.
+ */
+ pmb_unmap(vaddr);
+#endif
+
+ p = remove_vm_area((void *)(vaddr & PAGE_MASK));
+ if (!p) {
+ printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr);
+ return;
+ }
+
+ kfree(p);
}
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types
index 0693fbd1f956..182fe9092577 100644
--- a/arch/sh/tools/mach-types
+++ b/arch/sh/tools/mach-types
@@ -10,10 +10,7 @@ SE SH_SOLUTION_ENGINE
7300SE SH_7300_SOLUTION_ENGINE
73180SE SH_73180_SOLUTION_ENGINE
7751SYSTEMH SH_7751_SYSTEMH
-HP600 SH_HP600
-HP620 SH_HP620
-HP680 SH_HP680
-HP690 SH_HP690
+HP6XX SH_HP6XX
HD64461 HD64461
HD64465 HD64465
SH2000 SH_SH2000
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index fb35b45dc130..07b172deb872 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -17,10 +17,6 @@ config MMU
bool
default y
-config UID16
- bool
- default y
-
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index b95d04141855..1da9c61d6823 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -744,7 +744,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
}
#endif
/* Copy from sh version */
- childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info )) - 1;
+ childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;
*childregs = *regs;
@@ -752,7 +752,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->regs[15] = usp;
p->thread.uregs = childregs;
} else {
- childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE;
+ childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
}
childregs->regs[9] = 0; /* Set return value for child */
@@ -775,26 +775,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
return 0;
}
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
- dump->magic = CMAGIC;
- dump->start_code = current->mm->start_code;
- dump->start_data = current->mm->start_data;
- dump->start_stack = regs->regs[15] & ~(PAGE_SIZE - 1);
- dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT;
- dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT;
- dump->u_ssize = (current->mm->start_stack - dump->start_stack +
- PAGE_SIZE - 1) >> PAGE_SHIFT;
- /* Debug registers will come here. */
-
- dump->regs = *regs;
-
- dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
-}
-
asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 0b5497d70bd3..472b450e61be 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -29,7 +29,6 @@
#include <asm/delay.h>
#include <asm/irq.h>
-extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
#if 0
@@ -41,7 +40,6 @@ EXPORT_SYMBOL(drive_info);
#endif
/* platform dependent support */
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(iounmap);
EXPORT_SYMBOL(enable_irq);
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 870fe5327e09..1195af37ee5a 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -417,7 +417,7 @@ static __init unsigned int get_cpu_hz(void)
/*
** Regardless the toolchain, force the compiler to use the
** arbitrary register r3 as a clock tick counter.
- ** NOTE: r3 must be in accordance with rtc_interrupt()
+ ** NOTE: r3 must be in accordance with sh64_rtc_interrupt()
*/
register unsigned long long __rtc_irq_flag __asm__ ("r3");
@@ -482,7 +482,8 @@ static __init unsigned int get_cpu_hz(void)
#endif
}
-static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
ctrl_outb(0, RCR1); /* Disable Carry Interrupts */
regs->regs[3] = 1; /* Using r3 */
@@ -491,7 +492,7 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
-static struct irqaction irq1 = { rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL};
+static struct irqaction irq1 = { sh64_rtc_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "rtc", NULL, NULL};
void __init time_init(void)
{
diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c
index 526fedae6db8..58087331b8a6 100644
--- a/arch/sh64/lib/dbg.c
+++ b/arch/sh64/lib/dbg.c
@@ -174,7 +174,7 @@ void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
struct ring_node *rr;
pid = current->pid;
- stack_bottom = (unsigned long) current->thread_info;
+ stack_bottom = (unsigned long) task_stack_page(current);
asm volatile("ori r15, 0, %0" : "=r" (sp));
rr = event_ring + event_ptr;
rr->evt = evt;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 56c34e7fd4ee..f944b58cdfe7 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -9,10 +9,6 @@ config MMU
bool
default y
-config UID16
- bool
- default y
-
config HIGHMEM
bool
default y
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index ea8647411462..fbb05a452e51 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -302,7 +302,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
int count = 0;
if (tsk != NULL)
- task_base = (unsigned long) tsk->thread_info;
+ task_base = (unsigned long) task_stack_page(tsk);
else
task_base = (unsigned long) current_thread_info();
@@ -337,7 +337,7 @@ EXPORT_SYMBOL(dump_stack);
*/
unsigned long thread_saved_pc(struct task_struct *tsk)
{
- return tsk->thread_info->kpc;
+ return task_thread_info(tsk)->kpc;
}
/*
@@ -392,7 +392,7 @@ void flush_thread(void)
/* We must fixup kregs as well. */
/* XXX This was not fixed for ti for a while, worked. Unused? */
current->thread.kregs = (struct pt_regs *)
- ((char *)current->thread_info + (THREAD_SIZE - TRACEREG_SZ));
+ (task_stack_page(current) + (THREAD_SIZE - TRACEREG_SZ));
}
}
@@ -459,7 +459,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *ti = p->thread_info;
+ struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs;
char *new_stack;
@@ -482,7 +482,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
* V V (stk.fr.) V (pt_regs) { (stk.fr.) }
* +----- - - - - - ------+===========+============={+==========}+
*/
- new_stack = (char*)ti + THREAD_SIZE;
+ new_stack = task_stack_page(p) + THREAD_SIZE;
if (regs->psr & PSR_PS)
new_stack -= STACKFRAME_SZ;
new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
@@ -724,7 +724,7 @@ unsigned long get_wchan(struct task_struct *task)
task->state == TASK_RUNNING)
goto out;
- fp = task->thread_info->ksp + bias;
+ fp = task_thread_info(task)->ksp + bias;
do {
/* Bogus frame pointer? */
if (fp < (task_base + sizeof(struct thread_info)) ||
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 475c4c13462c..1baf13ed5c3a 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -75,7 +75,7 @@ static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
struct task_struct *tsk, long __user *addr)
{
struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_info *t = tsk->thread_info;
+ struct thread_info *t = task_thread_info(tsk);
int v;
if(offset >= 1024)
@@ -170,7 +170,7 @@ static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
struct task_struct *tsk)
{
struct pt_regs *cregs = tsk->thread.kregs;
- struct thread_info *t = tsk->thread_info;
+ struct thread_info *t = task_thread_info(tsk);
unsigned long value = regs->u_regs[UREG_I3];
if(offset >= 1024)
@@ -286,40 +286,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
s, (int) request, (int) pid, addr, data, addr2);
}
#endif
- if (request == PTRACE_TRACEME) {
- int my_ret;
-
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED) {
- pt_error_return(regs, EPERM);
- goto out;
- }
- my_ret = security_ptrace(current->parent, current);
- if (my_ret) {
- pt_error_return(regs, -my_ret);
- goto out;
- }
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
+ if (request == PTRACE_TRACEME) {
+ ret = ptrace_traceme();
pt_succ_return(regs, 0);
goto out;
}
-#ifndef ALLOW_INIT_TRACING
- if (pid == 1) {
- /* Can't dork with init. */
- pt_error_return(regs, EPERM);
- goto out;
- }
-#endif
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child) {
- pt_error_return(regs, ESRCH);
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ pt_error_return(regs, -ret);
goto out;
}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 1c8fd0fd9305..0b0d492c953b 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -82,8 +82,6 @@ extern int __lshrdi3(int, int);
extern int __muldi3(int, int);
extern int __divdi3(int, int);
-extern void dump_thread(struct pt_regs *, struct user *);
-
/* Private functions with odd calling conventions. */
extern void ___atomic24_add(void);
extern void ___atomic24_sub(void);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index cc1fc898495c..40d426cce824 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -200,7 +200,7 @@ void __init smp4d_boot_cpus(void)
/* Cook up an idler for this guy. */
p = fork_idle(i);
cpucount++;
- current_set[i] = p->thread_info;
+ current_set[i] = task_thread_info(p);
for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
&& mid != i; no++) ;
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index f113422a3727..a21f27d10e55 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -173,7 +173,7 @@ void __init smp4m_boot_cpus(void)
/* Cook up an idler for this guy. */
p = fork_idle(i);
cpucount++;
- current_set[i] = p->thread_info;
+ current_set[i] = task_thread_info(p);
/* See trampoline.S for details... */
entry += ((i-1) * 3);
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index d07ae02101ad..288de276d9ff 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -30,6 +30,7 @@
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c
index 3f451ae66482..41d45c298fb2 100644
--- a/arch/sparc/kernel/traps.c
+++ b/arch/sparc/kernel/traps.c
@@ -291,7 +291,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
#ifndef CONFIG_SMP
if(!fpt) {
#else
- if(!(fpt->thread_info->flags & _TIF_USEDFPU)) {
+ if(!(task_thread_info(fpt)->flags & _TIF_USEDFPU)) {
#endif
fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
regs->psr &= ~PSR_EF;
@@ -334,7 +334,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
/* nope, better SIGFPE the offending process... */
#ifdef CONFIG_SMP
- fpt->thread_info->flags &= ~_TIF_USEDFPU;
+ task_thread_info(fpt)->flags &= ~_TIF_USEDFPU;
#endif
if(psr & PSR_PS) {
/* The first fsr store/load we tried trapped,
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 489bf68d5f05..77840c804786 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -295,8 +295,7 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus)
int ioptex;
int i;
- if (busa < iommu->start)
- BUG();
+ BUG_ON(busa < iommu->start);
ioptex = (busa - iommu->start) >> PAGE_SHIFT;
for (i = 0; i < npages; i++) {
iopte_val(iommu->page_table[ioptex + i]) = 0;
@@ -340,9 +339,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
iopte_t *first;
int ioptex;
- if ((va & ~PAGE_MASK) != 0) BUG();
- if ((addr & ~PAGE_MASK) != 0) BUG();
- if ((len & ~PAGE_MASK) != 0) BUG();
+ BUG_ON((va & ~PAGE_MASK) != 0);
+ BUG_ON((addr & ~PAGE_MASK) != 0);
+ BUG_ON((len & ~PAGE_MASK) != 0);
/* page color = physical address */
ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT,
@@ -405,8 +404,8 @@ static void iommu_unmap_dma_area(unsigned long busa, int len)
unsigned long end;
int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
- if ((busa & ~PAGE_MASK) != 0) BUG();
- if ((len & ~PAGE_MASK) != 0) BUG();
+ BUG_ON((busa & ~PAGE_MASK) != 0);
+ BUG_ON((len & ~PAGE_MASK) != 0);
iopte += ioptex;
end = busa + len;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index c4b7ad70cd7c..ab733be9af08 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -179,7 +179,7 @@ config HUGETLB_PAGE_SIZE_512K
bool "512K"
config HUGETLB_PAGE_SIZE_64K
- depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512K
+ depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB
bool "64K"
endchoice
@@ -309,11 +309,6 @@ config COMPAT
depends on SPARC32_COMPAT
default y
-config UID16
- bool
- depends on SPARC32_COMPAT
- default y
-
config BINFMT_ELF32
tristate "Kernel support for 32-bit ELF binaries"
depends on SPARC32_COMPAT
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 46a6ad60a8f5..9ceddad0fb49 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,46 +1,67 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Sun Mar 6 20:47:29 2005
+# Linux kernel version: 2.6.16-rc1
+# Wed Jan 18 13:41:02 2006
#
+CONFIG_SPARC=y
+CONFIG_SPARC64=y
CONFIG_64BIT=y
CONFIG_MMU=y
CONFIG_TIME_INTERPOLATION=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_SPARC64_PAGE_SIZE_8KB=y
+# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+# CONFIG_SPARC64_PAGE_SIZE_512KB is not set
+# CONFIG_SPARC64_PAGE_SIZE_4MB is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_LOCK_KERNEL=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=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -52,20 +73,32 @@ CONFIG_OBSOLETE_MODPARM=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_KMOD=y
-CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_SYSVIPC_COMPAT=y
#
# General machine setup
#
-CONFIG_BBC_I2C=m
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_SMP=y
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
-CONFIG_NR_CPUS=4
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=m
CONFIG_CPU_FREQ_STAT_DETAILS=y
@@ -75,15 +108,22 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_FREQ_GOV_ONDEMAND=m
-CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
CONFIG_US3_FREQ=m
CONFIG_US2E_FREQ=m
-CONFIG_SPARC64=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_GENERIC_ISA_DMA=y
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
@@ -91,130 +131,147 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_RTC=y
# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
CONFIG_SUN_OPENPROMFS=m
CONFIG_SPARC32_COMPAT=y
CONFIG_COMPAT=y
-CONFIG_UID16=y
CONFIG_BINFMT_ELF32=y
# CONFIG_BINFMT_AOUT32 is not set
+
+#
+# Executable file formats
+#
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
-CONFIG_SOLARIS_EMUL=m
+# CONFIG_SOLARIS_EMUL is not set
+# CONFIG_CMDLINE_BOOL is not set
#
-# Parallel port support
+# Networking
#
-CONFIG_PARPORT=m
-CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_SUNBPP is not set
-# CONFIG_PARPORT_OTHER is not set
-CONFIG_PARPORT_1284=y
-CONFIG_PRINTER=m
-CONFIG_ENVCTRL=m
-CONFIG_DISPLAY7SEG=m
-# CONFIG_CMDLINE_BOOL is not set
+CONFIG_NET=y
#
-# Generic Driver Options
+# Networking options
#
-CONFIG_STANDALONE=y
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FW_LOADER=m
-# CONFIG_DEBUG_DRIVER is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
#
-# Graphics support
+# TCP congestion control
#
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-# CONFIG_FB_CIRRUS is not set
-CONFIG_FB_PM2=y
-# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_BW2 is not set
-# CONFIG_FB_CG3 is not set
-CONFIG_FB_CG6=y
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-# CONFIG_FB_ATY_GENERIC_LCD is not set
-# CONFIG_FB_ATY_XL_INIT is not set
-CONFIG_FB_ATY_GX=y
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-CONFIG_FB_SBUS=y
-CONFIG_FB_FFB=y
-# CONFIG_FB_TCX is not set
-# CONFIG_FB_CG14 is not set
-# CONFIG_FB_P9100 is not set
-# CONFIG_FB_LEO is not set
-# CONFIG_FB_PCI is not set
-# CONFIG_FB_VIRTUAL is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETFILTER is not set
#
-# Console display driver support
+# DCCP Configuration (EXPERIMENTAL)
#
-# CONFIG_PROM_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-CONFIG_FONT_SUN8x16=y
-# CONFIG_FONT_SUN12x22 is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
#
-# Logo configuration
+# DCCP CCIDs Configuration (EXPERIMENTAL)
#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_LOGO_SUN_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_IP_DCCP_CCID3=m
+CONFIG_IP_DCCP_TFRC_LIB=m
#
-# Serial drivers
+# DCCP Kernel Hacking
#
+# CONFIG_IP_DCCP_DEBUG is not set
+# CONFIG_IP_DCCP_UNLOAD_HACK is not set
#
-# Non-8250 serial port support
+# SCTP Configuration (EXPERIMENTAL)
#
-CONFIG_SERIAL_SUNCORE=y
-CONFIG_SERIAL_SUNZILOG=y
-CONFIG_SERIAL_SUNZILOG_CONSOLE=y
-CONFIG_SERIAL_SUNSU=y
-CONFIG_SERIAL_SUNSU_CONSOLE=y
-CONFIG_SERIAL_SUNSAB=m
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+CONFIG_VLAN_8021Q=m
+# 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
#
-# Misc Linux/SPARC drivers
+# TIPC Configuration (EXPERIMENTAL)
#
-CONFIG_SUN_OPENPROMIO=m
-CONFIG_SUN_MOSTEK_RTC=y
-CONFIG_OBP_FLASH=m
-# CONFIG_SUN_BPP is not set
+# CONFIG_TIPC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
#
# Memory Technology Devices (MTD)
@@ -222,10 +279,18 @@ CONFIG_OBP_FLASH=m
# 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_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
@@ -234,22 +299,13 @@ CONFIG_OBP_FLASH=m
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_SX8=m
+# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_UB=m
# CONFIG_BLK_DEV_RAM is not set
CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
CONFIG_CDROM_PKTCDVD_WCACHE=y
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
CONFIG_ATA_OVER_ETH=m
#
@@ -265,7 +321,7 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDETAPE=m
+# 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
@@ -278,7 +334,7 @@ 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=m
+# 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=y
@@ -286,27 +342,25 @@ CONFIG_IDEDMA_ONLYDISK=y
# CONFIG_BLK_DEV_AEC62XX is not set
CONFIG_BLK_DEV_ALI15X3=y
# CONFIG_WDC_ALI15X3 is not set
-CONFIG_BLK_DEV_AMD74XX=m
-CONFIG_BLK_DEV_CMD64X=m
-CONFIG_BLK_DEV_TRIFLEX=m
-CONFIG_BLK_DEV_CY82C693=m
-CONFIG_BLK_DEV_CS5520=m
-CONFIG_BLK_DEV_CS5530=m
-CONFIG_BLK_DEV_HPT34X=m
-# CONFIG_HPT34X_AUTODMA is not set
-CONFIG_BLK_DEV_HPT366=m
-CONFIG_BLK_DEV_SC1200=m
-CONFIG_BLK_DEV_PIIX=m
-CONFIG_BLK_DEV_NS87415=m
-CONFIG_BLK_DEV_PDC202XX_OLD=m
-# CONFIG_PDC202XX_BURST is not set
-CONFIG_BLK_DEV_PDC202XX_NEW=m
-# CONFIG_PDC202XX_FORCE is not set
-CONFIG_BLK_DEV_SVWKS=m
-CONFIG_BLK_DEV_SIIMAGE=m
-CONFIG_BLK_DEV_SLC90E66=m
-CONFIG_BLK_DEV_TRM290=m
-CONFIG_BLK_DEV_VIA82CXXX=m
+# 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 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
@@ -316,6 +370,7 @@ CONFIG_IDEDMA_AUTO=y
#
# SCSI device support
#
+CONFIG_RAID_ATTRS=m
CONFIG_SCSI=y
CONFIG_SCSI_PROC_FS=y
@@ -323,11 +378,12 @@ CONFIG_SCSI_PROC_FS=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=m
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -340,89 +396,41 @@ CONFIG_SCSI_CONSTANTS=y
# SCSI Transport Attributes
#
CONFIG_SCSI_SPI_ATTRS=y
-CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=y
CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_ATTRS is not set
#
# SCSI low-level drivers
#
-CONFIG_BLK_DEV_3W_XXXX_RAID=m
-CONFIG_SCSI_3W_9XXX=m
-CONFIG_SCSI_ACARD=m
-CONFIG_SCSI_AACRAID=m
+CONFIG_ISCSI_TCP=m
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
-CONFIG_SCSI_AIC79XX=m
-CONFIG_AIC79XX_CMDS_PER_DEVICE=32
-CONFIG_AIC79XX_RESET_DELAY_MS=15000
-# CONFIG_AIC79XX_BUILD_FIRMWARE is not set
-# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
-# CONFIG_AIC79XX_DEBUG_ENABLE is not set
-CONFIG_AIC79XX_DEBUG_MASK=0
-# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC79XX is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
-CONFIG_SCSI_SATA=y
-CONFIG_SCSI_SATA_AHCI=m
-CONFIG_SCSI_SATA_SVW=m
-CONFIG_SCSI_ATA_PIIX=m
-CONFIG_SCSI_SATA_NV=m
-CONFIG_SCSI_SATA_PROMISE=m
-CONFIG_SCSI_SATA_QSTOR=m
-CONFIG_SCSI_SATA_SX4=m
-CONFIG_SCSI_SATA_SIL=m
-CONFIG_SCSI_SATA_SIS=m
-CONFIG_SCSI_SATA_ULI=m
-CONFIG_SCSI_SATA_VIA=m
-CONFIG_SCSI_SATA_VITESSE=m
-CONFIG_SCSI_DMX3191D=m
-CONFIG_SCSI_EATA_PIO=m
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
-CONFIG_SCSI_IPS=m
-CONFIG_SCSI_INITIO=m
-CONFIG_SCSI_INIA100=m
-CONFIG_SCSI_PPA=m
-CONFIG_SCSI_IMM=m
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR 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_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_ISP=m
-CONFIG_SCSI_QLOGIC_FC=y
-CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
+# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
-CONFIG_SCSI_QLOGICPTI=m
-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_DC395x=m
+# CONFIG_SCSI_QLOGICPTI is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
-CONFIG_SCSI_DEBUG=m
-CONFIG_SCSI_SUNESP=y
-
-#
-# Fibre Channel support
-#
-CONFIG_FC4=m
-
-#
-# FC4 drivers
-#
-CONFIG_FC4_SOC=m
-CONFIG_FC4_SOCAL=m
-
-#
-# FC4 targets
-#
-CONFIG_SCSI_PLUTO=m
-CONFIG_SCSI_FCAL=m
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SUNESP is not set
#
# Multi-device support (RAID and LVM)
@@ -442,427 +450,34 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
#
-CONFIG_FUSION=m
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_CTL=m
-CONFIG_FUSION_LAN=m
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
-CONFIG_IEEE1394=m
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-CONFIG_IEEE1394_OUI_DB=y
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-
-#
-# Device Drivers
-#
-CONFIG_IEEE1394_PCILYNX=m
-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
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-# CONFIG_IP_PNP is not set
-CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
-CONFIG_NET_IPGRE_BROADCAST=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_ARPD=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=y
-CONFIG_INET_ESP=y
-CONFIG_INET_IPCOMP=y
-CONFIG_INET_TUNNEL=y
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-CONFIG_IP_VS=m
-# CONFIG_IP_VS_DEBUG is not set
-CONFIG_IP_VS_TAB_BITS=12
-
-#
-# IPVS transport protocol load balancing support
-#
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-
-#
-# IPVS scheduler
-#
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-
-#
-# IPVS application helper
-#
-CONFIG_IP_VS_FTP=m
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-CONFIG_IP_NF_CT_ACCT=y
-CONFIG_IP_NF_CONNTRACK_MARK=y
-CONFIG_IP_NF_CT_PROTO_SCTP=m
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_PHYSDEV=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_CONNMARK=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_CONNMARK=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-CONFIG_IP6_NF_MATCH_LIMIT=m
-CONFIG_IP6_NF_MATCH_MAC=m
-CONFIG_IP6_NF_MATCH_RT=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_MULTIPORT=m
-CONFIG_IP6_NF_MATCH_OWNER=m
-CONFIG_IP6_NF_MATCH_MARK=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-CONFIG_IP6_NF_MATCH_AHESP=m
-CONFIG_IP6_NF_MATCH_LENGTH=m
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_PHYSDEV=m
-CONFIG_IP6_NF_FILTER=m
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_TARGET_MARK=m
-CONFIG_IP6_NF_RAW=m
-
-#
-# DECnet: Netfilter Configuration
-#
-CONFIG_DECNET_NF_GRABULATOR=m
-
-#
-# Bridge: Netfilter Configuration
-#
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_ATM_BR2684_IPFILTER=y
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
-CONFIG_DECNET_ROUTE_FWMARK=y
-CONFIG_LLC=m
-CONFIG_LLC2=m
-CONFIG_IPX=m
-# CONFIG_IPX_INTERN is not set
-CONFIG_ATALK=m
-# CONFIG_DEV_APPLETALK is not set
-CONFIG_X25=m
-CONFIG_LAPB=m
-CONFIG_NET_DIVERT=y
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
+# CONFIG_IEEE1394 is not set
#
-# QoS and/or fair queueing
+# I2O device support
#
-CONFIG_NET_SCHED=y
-# CONFIG_NET_SCH_CLK_JIFFIES is not set
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-CONFIG_NET_SCH_CLK_CPU=y
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=y
-CONFIG_NET_SCH_PRIO=m
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-CONFIG_NET_SCH_INGRESS=m
-CONFIG_NET_QOS=y
-CONFIG_NET_ESTIMATOR=y
-CONFIG_NET_CLS=y
-CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_CLS_U32_PERF=y
-CONFIG_NET_CLS_IND=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_STACK=32
-CONFIG_NET_EMATCH_CMP=m
-CONFIG_NET_EMATCH_NBYTE=m
-CONFIG_NET_EMATCH_U32=m
-CONFIG_NET_EMATCH_META=m
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=m
-CONFIG_NET_ACT_GACT=m
-CONFIG_GACT_PROB=y
-CONFIG_NET_ACT_MIRRED=m
-CONFIG_NET_ACT_IPT=m
-CONFIG_NET_ACT_PEDIT=m
+# CONFIG_I2O is not set
#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-CONFIG_NET_POLL_CONTROLLER=y
-CONFIG_HAMRADIO=y
-
-#
-# Packet Radio protocols
-#
-CONFIG_AX25=m
-CONFIG_AX25_DAMA_SLAVE=y
-CONFIG_NETROM=m
-CONFIG_ROSE=m
-
-#
-# AX.25 network device drivers
-#
-# CONFIG_BPQETHER is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_YAM is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRNET=m
-CONFIG_IRCOMM=m
-CONFIG_IRDA_ULTRA=y
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-# CONFIG_IRTTY_SIR is not set
-
-#
-# Dongle support
-#
-
-#
-# Old SIR device drivers
-#
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
-# CONFIG_USB_IRDA is not set
-CONFIG_SIGMATEL_FIR=m
-# CONFIG_VLSI_FIR is not set
-CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_CMTP=m
-CONFIG_BT_HIDP=m
-
+# Network device support
#
-# Bluetooth device drivers
-#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
-CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_BCSP_TXCRC=y
-CONFIG_BT_HCIBCM203X=m
-CONFIG_BT_HCIBPA10X=m
-CONFIG_BT_HCIBFUSB=m
-CONFIG_BT_HCIVHCI=m
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
#
# ARCnet devices
@@ -870,86 +485,74 @@ CONFIG_TUN=m
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
-CONFIG_SUNLANCE=y
-CONFIG_HAPPYMEAL=y
-CONFIG_SUNBMAC=m
-CONFIG_SUNQE=m
-CONFIG_SUNGEM=y
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+# CONFIG_NET_VENDOR_3COM is not set
#
# Tulip family network device support
#
-CONFIG_NET_TULIP=y
-CONFIG_DE2104X=m
-CONFIG_TULIP=m
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
-CONFIG_TULIP_NAPI=y
-CONFIG_TULIP_NAPI_HW_MITIGATION=y
-CONFIG_DE4X5=m
-CONFIG_WINBOND_840=m
-# CONFIG_DM9102 is not set
+# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
+# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
-CONFIG_ADAPTEC_STARFIRE=m
-CONFIG_ADAPTEC_STARFIRE_NAPI=y
-CONFIG_B44=m
-CONFIG_FORCEDETH=m
-CONFIG_DGRS=m
-CONFIG_EEPRO100=m
-CONFIG_E100=m
-CONFIG_FEALNX=m
-CONFIG_NATSEMI=m
-CONFIG_NE2K_PCI=m
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
# CONFIG_8139CP is not set
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_SIS900=m
-CONFIG_EPIC100=m
-CONFIG_SUNDANCE=m
-CONFIG_SUNDANCE_MMIO=y
-CONFIG_VIA_RHINE=m
-# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
#
# Ethernet (1000 Mbit)
#
-CONFIG_ACENIC=m
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_DL2K=m
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
CONFIG_E1000=m
CONFIG_E1000_NAPI=y
-CONFIG_MYRI_SBUS=m
-CONFIG_NS83820=m
-CONFIG_HAMACHI=m
-CONFIG_YELLOWFIN=m
-CONFIG_R8169=m
-CONFIG_R8169_NAPI=y
-CONFIG_R8169_VLAN=y
-CONFIG_SK98LIN=m
-CONFIG_VIA_VELOCITY=m
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=m
+CONFIG_BNX2=m
#
# Ethernet (10000 Mbit)
#
-CONFIG_IXGB=m
-CONFIG_IXGB_NAPI=y
-CONFIG_S2IO=m
-CONFIG_S2IO_NAPI=y
-CONFIG_2BUFF_MODE=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
@@ -959,140 +562,31 @@ CONFIG_2BUFF_MODE=y
#
# Wireless LAN (non-hamradio)
#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_TMD_HERMES=m
-CONFIG_PCI_HERMES=m
-CONFIG_ATMEL=m
-CONFIG_PCI_ATMEL=m
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-CONFIG_PRISM54=m
-CONFIG_NET_WIRELESS=y
+# CONFIG_NET_RADIO is not set
#
# Wan interfaces
#
# CONFIG_WAN is not set
-
-#
-# ATM drivers
-#
-CONFIG_ATM_TCP=m
-# CONFIG_ATM_LANAI is not set
-# CONFIG_ATM_ENI is not set
-# CONFIG_ATM_FIRESTREAM is not set
-# CONFIG_ATM_ZATM is not set
-# CONFIG_ATM_IDT77252 is not set
-# CONFIG_ATM_AMBASSADOR is not set
-# CONFIG_ATM_HORIZON is not set
-CONFIG_ATM_FORE200E_MAYBE=m
-CONFIG_ATM_FORE200E_PCA=y
-CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y
-CONFIG_ATM_FORE200E_SBA=y
-CONFIG_ATM_FORE200E_SBA_DEFAULT_FW=y
-CONFIG_ATM_FORE200E_USE_TASKLET=y
-CONFIG_ATM_FORE200E_TX_RETRY=16
-CONFIG_ATM_FORE200E_DEBUG=0
-CONFIG_ATM_FORE200E=m
-CONFIG_ATM_HE=m
-CONFIG_ATM_HE_USE_SUNI=y
-CONFIG_FDDI=y
-# CONFIG_DEFXX is not set
-CONFIG_SKFP=m
-CONFIG_HIPPI=y
-# CONFIG_ROADRUNNER is not set
-CONFIG_PLIP=m
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
-CONFIG_NET_FC=y
-CONFIG_SHAPER=m
-CONFIG_NETCONSOLE=m
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
#
# ISDN subsystem
#
-CONFIG_ISDN=m
-
-#
-# Old ISDN4Linux
-#
-# CONFIG_ISDN_I4L is not set
-
-#
-# CAPI subsystem
-#
-CONFIG_ISDN_CAPI=m
-# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set
-# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
-CONFIG_ISDN_CAPI_CAPI20=m
-
-#
-# CAPI hardware drivers
-#
-
-#
-# Active AVM cards
-#
-CONFIG_CAPI_AVM=y
-CONFIG_ISDN_DRV_AVMB1_B1PCI=m
-CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
-CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
-CONFIG_ISDN_DRV_AVMB1_T1PCI=m
-CONFIG_ISDN_DRV_AVMB1_C4=m
-
-#
-# Active Eicon DIVA Server cards
-#
-CONFIG_CAPI_EICON=y
-CONFIG_ISDN_DIVAS=m
-CONFIG_ISDN_DIVAS_BRIPCI=y
-CONFIG_ISDN_DIVAS_PRIPCI=y
-CONFIG_ISDN_DIVAS_DIVACAPI=m
-CONFIG_ISDN_DIVAS_USERIDI=m
-CONFIG_ISDN_DIVAS_MAINT=m
+# CONFIG_ISDN is not set
#
# Telephony Support
#
-CONFIG_PHONE=m
-CONFIG_PHONE_IXJ=m
-
-#
-# Unix98 PTY support
-#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# XFree86 DRI support
-#
-CONFIG_DRM=y
-CONFIG_DRM_TDFX=m
-# CONFIG_DRM_R128 is not set
+# CONFIG_PHONE is not set
#
# Input device support
@@ -1112,26 +606,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-CONFIG_GAMEPORT_CS461X=m
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_PCIPS2=m
-CONFIG_SERIO_LIBPS2=y
-CONFIG_SERIO_RAW=m
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -1143,7 +617,7 @@ CONFIG_KEYBOARD_LKKBD=m
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_SERIAL=y
-CONFIG_MOUSE_VSXXXAA=m
+# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
@@ -1151,406 +625,255 @@ CONFIG_INPUT_SPARCSPKR=y
# CONFIG_INPUT_UINPUT is not set
#
-# I2C support
-#
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
-
-#
-# I2C Hardware Bus support
-#
-CONFIG_I2C_ALI1535=m
-CONFIG_I2C_ALI1563=m
-CONFIG_I2C_ALI15X3=m
-CONFIG_I2C_AMD756=m
-# CONFIG_I2C_AMD756_S4882 is not set
-CONFIG_I2C_AMD8111=m
-CONFIG_I2C_I801=m
-CONFIG_I2C_I810=m
-CONFIG_I2C_ISA=m
-CONFIG_I2C_NFORCE2=m
-CONFIG_I2C_PARPORT=m
-CONFIG_I2C_PARPORT_LIGHT=m
-CONFIG_I2C_PIIX4=m
-CONFIG_I2C_PROSAVAGE=m
-CONFIG_I2C_SAVAGE4=m
-CONFIG_SCx200_ACB=m
-CONFIG_I2C_SIS5595=m
-CONFIG_I2C_SIS630=m
-CONFIG_I2C_SIS96X=m
-CONFIG_I2C_STUB=m
-CONFIG_I2C_VIA=m
-CONFIG_I2C_VIAPRO=m
-CONFIG_I2C_VOODOO3=m
-CONFIG_I2C_PCA_ISA=m
-
-#
-# Hardware Sensors Chip support
-#
-CONFIG_I2C_SENSOR=m
-CONFIG_SENSORS_ADM1021=m
-CONFIG_SENSORS_ADM1025=m
-CONFIG_SENSORS_ADM1026=m
-CONFIG_SENSORS_ADM1031=m
-CONFIG_SENSORS_ASB100=m
-CONFIG_SENSORS_DS1621=m
-CONFIG_SENSORS_FSCHER=m
-CONFIG_SENSORS_FSCPOS=m
-CONFIG_SENSORS_GL518SM=m
-CONFIG_SENSORS_GL520SM=m
-CONFIG_SENSORS_IT87=m
-CONFIG_SENSORS_LM63=m
-CONFIG_SENSORS_LM75=m
-CONFIG_SENSORS_LM77=m
-CONFIG_SENSORS_LM78=m
-CONFIG_SENSORS_LM80=m
-CONFIG_SENSORS_LM83=m
-CONFIG_SENSORS_LM85=m
-CONFIG_SENSORS_LM87=m
-CONFIG_SENSORS_LM90=m
-CONFIG_SENSORS_MAX1619=m
-CONFIG_SENSORS_PC87360=m
-CONFIG_SENSORS_SMSC47B397=m
-CONFIG_SENSORS_SIS5595=m
-CONFIG_SENSORS_SMSC47M1=m
-CONFIG_SENSORS_VIA686A=m
-CONFIG_SENSORS_W83781D=m
-CONFIG_SENSORS_W83L785TS=m
-CONFIG_SENSORS_W83627HF=m
-
-#
-# Other I2C Chip support
-#
-CONFIG_SENSORS_EEPROM=m
-CONFIG_SENSORS_PCF8574=m
-CONFIG_SENSORS_PCF8591=m
-CONFIG_SENSORS_RTC8564=m
-# 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
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-CONFIG_JFS_POSIX_ACL=y
-CONFIG_JFS_SECURITY=y
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_FS_POSIX_ACL=y
-
-#
-# XFS support
-#
-CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
-# CONFIG_XFS_RT is not set
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_MINIX_FS=m
-CONFIG_ROMFS_FS=m
-# CONFIG_QUOTA is not set
-CONFIG_QUOTACTL=y
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
+# Hardware I/O ports
#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
#
-# Pseudo filesystems
+# Character devices
#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
-CONFIG_TMPFS=y
-CONFIG_TMPFS_XATTR=y
-CONFIG_TMPFS_SECURITY=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
#
-# Miscellaneous filesystems
+# Serial drivers
#
-CONFIG_ADFS_FS=m
-# CONFIG_ADFS_FS_RW is not set
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-# CONFIG_BEFS_DEBUG is not set
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_CRAMFS=m
-CONFIG_VXFS_FS=m
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-CONFIG_UFS_FS_WRITE=y
#
-# Network File Systems
+# Non-8250 serial port support
#
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
-CONFIG_SUNRPC=m
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
-CONFIG_RPCSEC_GSS_SPKM3=m
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
-CONFIG_NCP_FS=m
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-CONFIG_CODA_FS=m
-# CONFIG_CODA_FS_OLD_API is not set
-CONFIG_AFS_FS=m
-CONFIG_RXRPC=m
+CONFIG_SERIAL_SUNCORE=y
+# CONFIG_SERIAL_SUNZILOG is not set
+CONFIG_SERIAL_SUNSU=y
+CONFIG_SERIAL_SUNSU_CONSOLE=y
+CONFIG_SERIAL_SUNSAB=m
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
#
-# Partition Types
+# IPMI
#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-CONFIG_SUN_PARTITION=y
+# CONFIG_IPMI_HANDLER is not set
#
-# Native Language Support
+# Watchdog Cards
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_CODEPAGE_737=m
-CONFIG_NLS_CODEPAGE_775=m
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-CONFIG_NLS_CODEPAGE_855=m
-CONFIG_NLS_CODEPAGE_857=m
-CONFIG_NLS_CODEPAGE_860=m
-CONFIG_NLS_CODEPAGE_861=m
-CONFIG_NLS_CODEPAGE_862=m
-CONFIG_NLS_CODEPAGE_863=m
-CONFIG_NLS_CODEPAGE_864=m
-CONFIG_NLS_CODEPAGE_865=m
-CONFIG_NLS_CODEPAGE_866=m
-CONFIG_NLS_CODEPAGE_869=m
-CONFIG_NLS_CODEPAGE_936=m
-CONFIG_NLS_CODEPAGE_950=m
-CONFIG_NLS_CODEPAGE_932=m
-CONFIG_NLS_CODEPAGE_949=m
-CONFIG_NLS_CODEPAGE_874=m
-CONFIG_NLS_ISO8859_8=m
-CONFIG_NLS_CODEPAGE_1250=m
-CONFIG_NLS_CODEPAGE_1251=m
-CONFIG_NLS_ASCII=m
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-CONFIG_NLS_ISO8859_5=m
-CONFIG_NLS_ISO8859_6=m
-CONFIG_NLS_ISO8859_7=m
-CONFIG_NLS_ISO8859_9=m
-CONFIG_NLS_ISO8859_13=m
-CONFIG_NLS_ISO8859_14=m
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_KOI8_R=m
-CONFIG_NLS_KOI8_U=m
-CONFIG_NLS_UTF8=m
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
#
-# Multimedia devices
+# Ftape, the floppy tape device driver
#
-CONFIG_VIDEO_DEV=y
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
#
-# Video For Linux
+# TPM devices
#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
#
-# Video Adapters
+# I2C support
#
-CONFIG_VIDEO_BT848=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_W9966=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_PP=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_SAA5246A=m
-CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-# CONFIG_VIDEO_SAA7134 is not set
-CONFIG_VIDEO_MXB=m
-CONFIG_VIDEO_DPC=m
-CONFIG_VIDEO_HEXIUM_ORION=m
-CONFIG_VIDEO_HEXIUM_GEMINI=m
-CONFIG_VIDEO_CX88=m
-CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
#
-# Radio Adapters
+# I2C Algorithms
#
-CONFIG_RADIO_GEMTEK_PCI=m
-CONFIG_RADIO_MAXIRADIO=m
-CONFIG_RADIO_MAESTRO=m
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
#
-# Digital Video Broadcasting Devices
+# I2C Hardware Bus support
#
-CONFIG_DVB=y
-CONFIG_DVB_CORE=m
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_RTC_X1205_I2C is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
-# Supported SAA7146 based PCI Adapters
+# SPI support
#
-CONFIG_DVB_AV7110=m
-# CONFIG_DVB_AV7110_OSD is not set
-CONFIG_DVB_BUDGET=m
-CONFIG_DVB_BUDGET_CI=m
-CONFIG_DVB_BUDGET_AV=m
-CONFIG_DVB_BUDGET_PATCH=m
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
#
-# Supported USB Adapters
+# Dallas's 1-wire bus
#
-# CONFIG_DVB_TTUSB_BUDGET is not set
-CONFIG_DVB_TTUSB_DEC=m
-CONFIG_DVB_DIBUSB=m
-# CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES is not set
-CONFIG_DVB_DIBCOM_DEBUG=y
-CONFIG_DVB_CINERGYT2=m
-# CONFIG_DVB_CINERGYT2_TUNING is not set
+# CONFIG_W1 is not set
#
-# Supported FlexCopII (B2C2) Adapters
+# Hardware Monitoring support
#
-CONFIG_DVB_B2C2_SKYSTAR=m
-CONFIG_DVB_B2C2_USB=m
+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
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Supported BT878 Adapters
+# Misc devices
#
-CONFIG_DVB_BT8XX=m
#
-# Supported DVB Frontends
+# Multimedia Capabilities Port drivers
#
#
-# Customise DVB Frontends
+# Multimedia devices
#
+# CONFIG_VIDEO_DEV is not set
#
-# DVB-S (satellite) frontends
+# Digital Video Broadcasting Devices
#
-CONFIG_DVB_STV0299=m
-CONFIG_DVB_CX24110=m
-CONFIG_DVB_TDA8083=m
-CONFIG_DVB_TDA80XX=m
-CONFIG_DVB_MT312=m
-CONFIG_DVB_VES1X93=m
+# CONFIG_DVB is not set
#
-# DVB-T (terrestrial) frontends
+# Graphics support
#
-CONFIG_DVB_SP8870=m
-CONFIG_DVB_SP887X=m
-CONFIG_DVB_CX22700=m
-CONFIG_DVB_CX22702=m
-CONFIG_DVB_L64781=m
-CONFIG_DVB_TDA1004X=m
-CONFIG_DVB_NXT6000=m
-CONFIG_DVB_MT352=m
-CONFIG_DVB_DIB3000MB=m
-CONFIG_DVB_DIB3000MC=m
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_SBUS is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PCI is not set
+# CONFIG_FB_VIRTUAL is not set
#
-# DVB-C (cable) frontends
+# Console display driver support
#
-CONFIG_DVB_ATMEL_AT76C651=m
-CONFIG_DVB_VES1820=m
-CONFIG_DVB_TDA10021=m
-CONFIG_DVB_STV0297=m
+# CONFIG_PROM_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_SUN8x16=y
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
#
-# ATSC (North American/Korean Terresterial DTV) frontends
+# Logo configuration
#
-CONFIG_DVB_NXT2002=m
-CONFIG_VIDEO_SAA7146=m
-CONFIG_VIDEO_SAA7146_VV=m
-CONFIG_VIDEO_VIDEOBUF=m
-CONFIG_VIDEO_TUNER=m
-CONFIG_VIDEO_BUF=m
-CONFIG_VIDEO_BTCX=m
-CONFIG_VIDEO_IR=m
-CONFIG_VIDEO_TVEEPROM=m
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_SUN_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -1563,7 +886,6 @@ CONFIG_SOUND=m
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
-CONFIG_SND_HWDEP=m
CONFIG_SND_RAWMIDI=m
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
@@ -1571,8 +893,9 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_BIT32_EMUL=m
# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
@@ -1580,59 +903,58 @@ CONFIG_SND_BIT32_EMUL=m
# Generic devices
#
CONFIG_SND_MPU401_UART=m
-CONFIG_SND_OPL3_LIB=m
-CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_AC97_BUS=m
CONFIG_SND_DUMMY=m
CONFIG_SND_VIRMIDI=m
-# CONFIG_SND_MTPAV is not set
+CONFIG_SND_MTPAV=m
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
#
# PCI devices
#
-CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_AD1889 is not set
CONFIG_SND_ALI5451=m
-CONFIG_SND_ATIIXP=m
-CONFIG_SND_ATIIXP_MODEM=m
-CONFIG_SND_AU8810=m
-CONFIG_SND_AU8820=m
-CONFIG_SND_AU8830=m
-CONFIG_SND_AZT3328=m
-CONFIG_SND_BT87X=m
-# CONFIG_SND_BT87X_OVERCLOCK is not set
-CONFIG_SND_CS46XX=m
-# CONFIG_SND_CS46XX_NEW_DSP is not set
-CONFIG_SND_CS4281=m
-CONFIG_SND_EMU10K1=m
-CONFIG_SND_EMU10K1X=m
-CONFIG_SND_CA0106=m
-CONFIG_SND_KORG1212=m
-CONFIG_SND_MIXART=m
-CONFIG_SND_NM256=m
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-CONFIG_SND_TRIDENT=m
-CONFIG_SND_YMFPCI=m
-CONFIG_SND_ALS4000=m
-CONFIG_SND_CMIPCI=m
-CONFIG_SND_ENS1370=m
-CONFIG_SND_ENS1371=m
-CONFIG_SND_ES1938=m
-CONFIG_SND_ES1968=m
-CONFIG_SND_MAESTRO3=m
-CONFIG_SND_FM801=m
-CONFIG_SND_FM801_TEA575X=m
-CONFIG_SND_ICE1712=m
-# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=m
-CONFIG_SND_INTEL8X0M=m
-CONFIG_SND_SONICVIBES=m
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
-CONFIG_SND_VIA82XX_MODEM=m
-CONFIG_SND_VX222=m
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
#
# USB devices
@@ -1642,12 +964,20 @@ CONFIG_SND_VX222=m
#
# ALSA Sparc devices
#
-CONFIG_SND_SUN_AMD7930=m
+# CONFIG_SND_SUN_AMD7930 is not set
CONFIG_SND_SUN_CS4231=m
+# CONFIG_SND_SUN_DBRI is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -1658,8 +988,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -1667,174 +995,108 @@ CONFIG_USB_ARCH_HAS_OHCI=y
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=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
-CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
#
-# CONFIG_USB_AUDIO is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
-# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
-# CONFIG_USB_MIDI is not set
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# 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_RW_DETECT=y
-# CONFIG_USB_STORAGE_DATAFAB is not set
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
-CONFIG_USB_STORAGE_HP8200e=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
CONFIG_USB_HIDDEV=y
# CONFIG_USB_AIPTEK is not set
-CONFIG_USB_WACOM=m
-CONFIG_USB_KBTAB=m
+# 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=m
-CONFIG_USB_EGALAX=m
+# 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=m
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
#
# USB Imaging devices
#
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
#
# USB Multimedia devices
#
# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-CONFIG_USB_SN9C102=m
-# CONFIG_USB_STV680 is not set
-CONFIG_USB_W9968CF=m
#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-
-#
-# USB Host-to-Host Cables
+# Video4Linux support is needed for USB Multimedia device support
#
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_GENESYS=y
-CONFIG_USB_NET1080=y
-CONFIG_USB_PL2301=y
-CONFIG_USB_KC2190=y
-
-#
-# Intelligent USB Devices/Gadgets
-#
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_ZAURUS=y
-CONFIG_USB_CDCETHER=y
#
# USB Network Adapters
#
-CONFIG_USB_AX8817X=y
+# 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 is not set
#
# USB port drivers
#
-CONFIG_USB_USS720=m
#
# USB Serial Converter support
#
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-# CONFIG_USB_SERIAL_VISOR is not set
-CONFIG_USB_SERIAL_IPAQ=m
-# CONFIG_USB_SERIAL_IR is not set
-CONFIG_USB_SERIAL_EDGEPORT=m
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-CONFIG_USB_SERIAL_GARMIN=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
-CONFIG_USB_SERIAL_KLSI=m
-# CONFIG_USB_SERIAL_KOBIL_SCT is not set
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_PL2303=m
-# CONFIG_USB_SERIAL_SAFE is not set
-CONFIG_USB_SERIAL_TI=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_EZUSB=y
+# CONFIG_USB_SERIAL is not set
#
# USB Miscellaneous drivers
#
-CONFIG_USB_EMI62=m
-CONFIG_USB_EMI26=m
-CONFIG_USB_AUERSWALD=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-CONFIG_USB_LED=m
-CONFIG_USB_CYTHERM=m
-CONFIG_USB_PHIDGETKIT=m
-CONFIG_USB_PHIDGETSERVO=m
-CONFIG_USB_IDMOUSE=m
-CONFIG_USB_TEST=m
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
#
-# USB ATM/DSL drivers
+# USB DSL modem support
#
-CONFIG_USB_ATM=m
-CONFIG_USB_SPEEDTOUCH=m
#
# USB Gadget Support
@@ -1842,64 +1104,202 @@ CONFIG_USB_SPEEDTOUCH=m
# CONFIG_USB_GADGET is not set
#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
# InfiniBand support
#
-CONFIG_INFINIBAND=m
-CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
-CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+# CONFIG_INFINIBAND is not set
#
-# Watchdog Cards
+# SN Devices
+#
+
+#
+# Misc Linux/SPARC drivers
+#
+CONFIG_SUN_OPENPROMIO=m
+CONFIG_SUN_MOSTEK_RTC=y
+# CONFIG_OBP_FLASH is not set
+# CONFIG_SUN_BPP is not set
+# CONFIG_BBC_I2C is not set
+# CONFIG_ENVCTRL is not set
+# CONFIG_DISPLAY7SEG is not set
+
+#
+# Fibre Channel support
+#
+# CONFIG_FC4 is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
#
-# Watchdog Device Drivers
+# DOS/FAT/NT Filesystems
#
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_WATCHDOG_CP1XXX=m
-CONFIG_WATCHDOG_RIO=m
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
#
-# PCI-based Watchdog Cards
+# Pseudo filesystems
#
-CONFIG_PCIPCWATCHDOG=m
-CONFIG_WDTPCI=m
-CONFIG_WDT_501_PCI=y
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
#
-# USB-based Watchdog Cards
+# Miscellaneous filesystems
#
-CONFIG_USBPCWATCHDOG=m
+# 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
#
-# Profiling support
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_SUN_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Instrumentation Support
#
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
#
# Kernel hacking
#
-CONFIG_DEBUG_KERNEL=y
+CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_DEBUG_STACK_USAGE is not set
-CONFIG_KPROBES=y
# CONFIG_DEBUG_DCFLUSH is not set
# CONFIG_STACK_DEBUG is not set
# CONFIG_DEBUG_BOOTMEM is not set
-CONFIG_HAVE_DEC_LOCK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
#
# Security options
@@ -1945,6 +1345,7 @@ CONFIG_CRYPTO_TEST=m
# Library routines
#
CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 6f00ab8b9d23..83d67eb18895 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y := process.o setup.o cpu.o idprom.o \
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
pci_psycho.o pci_sabre.o pci_schizo.o
obj-$(CONFIG_SMP) += smp.o trampoline.o
-obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o
+obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
obj-$(CONFIG_MODULES) += module.o
@@ -40,5 +40,3 @@ endif
head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \
etrap.S rtrap.S winfixup.S entry.S
-
-CFLAGS_ioctl32.o += -Ifs/
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index edf52d06b280..202a80c24b6f 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -36,8 +36,6 @@ static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout32_library(struct file*);
static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
-extern void dump_thread(struct pt_regs *, struct user *);
-
static struct linux_binfmt aout32_format = {
NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump,
PAGE_SIZE
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index 6ffbeb701940..7991e919d8ab 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -527,18 +527,12 @@ static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
{
struct pci_dev *pdev = start;
- do {
- pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev);
- if (pdev &&
- (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
- pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev)))
+ if (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
+ pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)
break;
- } while (pdev != NULL);
- if (pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
- *is_rio_p = 1;
- else
- *is_rio_p = 0;
+ *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS));
return pdev;
}
@@ -637,6 +631,7 @@ void __init ebus_init(void)
ebus->is_rio = is_rio;
++num_ebus;
}
+ pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */
#ifdef CONFIG_SUN_AUXIO
auxio_probe();
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 11a848402fb1..710002991888 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1657,13 +1657,10 @@ ret_sys_call:
/* Check if force_successful_syscall_return()
* was invoked.
*/
- ldub [%curptr + TI_SYS_NOERROR], %l0
- brz,pt %l0, 1f
- nop
- ba,pt %xcc, 80f
+ ldub [%curptr + TI_SYS_NOERROR], %l2
+ brnz,a,pn %l2, 80f
stb %g0, [%curptr + TI_SYS_NOERROR]
-1:
cmp %o0, -ERESTART_RESTARTBLOCK
bgeu,pn %xcc, 1f
andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
deleted file mode 100644
index 196b208665a2..000000000000
--- a/arch/sparc64/kernel/ioctl32.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id: ioctl32.c,v 1.136 2002/01/14 09:49:52 davem Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 2003 Pavel Machek (pavel@suse.cz)
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#define INCLUDES
-#include "compat_ioctl.c"
-#include <linux/syscalls.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl)
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL },
-#define IOCTL_TABLE_START \
- struct ioctl_trans ioctl_start[] = {
-#define IOCTL_TABLE_END \
- };
-
-IOCTL_TABLE_START
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-#if 0
-HANDLE_IOCTL(RTC32_IRQP_READ, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_IRQP_SET, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_EPOCH_READ, do_rtc_ioctl)
-HANDLE_IOCTL(RTC32_EPOCH_SET, do_rtc_ioctl)
-#endif
-/* take care of sizeof(sizeof()) breakage */
-IOCTL_TABLE_END
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index a97b0f0727ab..b9a9ce70e55c 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -43,14 +43,10 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
- return 0;
-}
-
-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;
+ return 0;
}
void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -65,10 +61,6 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
flushi(p->addr);
}
-void __kprobes arch_remove_kprobe(struct kprobe *p)
-{
-}
-
static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
kcb->prev_kprobe.kp = kprobe_running();
@@ -143,6 +135,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
prepare_singlestep(p, regs, kcb);
return 1;
} else {
+ if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ ret = 1;
+ goto no_kprobe;
+ }
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs))
goto ss_probe;
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 9e8362ea3104..30bcaf58e3ab 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -14,6 +14,7 @@
#include <linux/signal.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/pm.h>
#include <asm/system.h>
#include <asm/ebus.h>
@@ -70,6 +71,9 @@ void machine_power_off(void)
machine_halt();
}
+void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
+
#ifdef CONFIG_PCI
static int powerd(void *__unused)
{
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 02f9dec1d459..059b0d025224 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -164,6 +164,7 @@ void machine_restart(char * cmd)
panic("Reboot failed!");
}
+#ifdef CONFIG_COMPAT
static void show_regwindow32(struct pt_regs *regs)
{
struct reg_window32 __user *rw;
@@ -189,6 +190,9 @@ static void show_regwindow32(struct pt_regs *regs)
r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3],
r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]);
}
+#else
+#define show_regwindow32(regs) do { } while (0)
+#endif
static void show_regwindow(struct pt_regs *regs)
{
@@ -390,7 +394,7 @@ void show_regs32(struct pt_regs32 *regs)
unsigned long thread_saved_pc(struct task_struct *tsk)
{
- struct thread_info *ti = tsk->thread_info;
+ struct thread_info *ti = task_thread_info(tsk);
unsigned long ret = 0xdeadbeefUL;
if (ti && ti->ksp) {
@@ -616,11 +620,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long unused,
struct task_struct *p, struct pt_regs *regs)
{
- struct thread_info *t = p->thread_info;
+ struct thread_info *t = task_thread_info(p);
char *child_trap_frame;
/* Calculate offset to stack_frame & pt_regs */
- child_trap_frame = ((char *)t) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
+ child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ));
memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ));
t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |
@@ -845,9 +849,9 @@ unsigned long get_wchan(struct task_struct *task)
task->state == TASK_RUNNING)
goto out;
- thread_info_base = (unsigned long) task->thread_info;
+ thread_info_base = (unsigned long) task_stack_page(task);
bias = STACK_BIAS;
- fp = task->thread_info->ksp + bias;
+ fp = task_thread_info(task)->ksp + bias;
do {
/* Bogus frame pointer? */
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 774ecbb8a031..3f9746f856d2 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -198,39 +198,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
}
#endif
if (request == PTRACE_TRACEME) {
- int ret;
-
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED) {
- pt_error_return(regs, EPERM);
- goto out;
- }
- ret = security_ptrace(current->parent, current);
- if (ret) {
- pt_error_return(regs, -ret);
- goto out;
- }
-
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
+ ret = ptrace_traceme();
pt_succ_return(regs, 0);
goto out;
}
-#ifndef ALLOW_INIT_TRACING
- if (pid == 1) {
- /* Can't dork with init. */
- pt_error_return(regs, EPERM);
- goto out;
- }
-#endif
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child) {
- pt_error_return(regs, ESRCH);
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ pt_error_return(regs, -ret);
goto out;
}
@@ -320,7 +296,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_GETREGS: {
struct pt_regs32 __user *pregs =
(struct pt_regs32 __user *) addr;
- struct pt_regs *cregs = child->thread_info->kregs;
+ struct pt_regs *cregs = task_pt_regs(child);
int rval;
if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
@@ -344,11 +320,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_GETREGS64: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = child->thread_info->kregs;
+ struct pt_regs *cregs = task_pt_regs(child);
unsigned long tpc = cregs->tpc;
int rval;
- if ((child->thread_info->flags & _TIF_32BIT) != 0)
+ if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
tpc &= 0xffffffff;
if (__put_user(cregs->tstate, (&pregs->tstate)) ||
__put_user(tpc, (&pregs->tpc)) ||
@@ -372,7 +348,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_SETREGS: {
struct pt_regs32 __user *pregs =
(struct pt_regs32 __user *) addr;
- struct pt_regs *cregs = child->thread_info->kregs;
+ struct pt_regs *cregs = task_pt_regs(child);
unsigned int psr, pc, npc, y;
int i;
@@ -405,7 +381,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_SETREGS64: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
- struct pt_regs *cregs = child->thread_info->kregs;
+ struct pt_regs *cregs = task_pt_regs(child);
unsigned long tstate, tpc, tnpc, y;
int i;
@@ -419,7 +395,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
pt_error_return(regs, EFAULT);
goto out_tsk;
}
- if ((child->thread_info->flags & _TIF_32BIT) != 0) {
+ if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
tpc &= 0xffffffff;
tnpc &= 0xffffffff;
}
@@ -454,11 +430,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = child->thread_info->fpregs;
+ unsigned long *fpregs = task_thread_info(child)->fpregs;
if (copy_to_user(&fps->regs[0], fpregs,
(32 * sizeof(unsigned int))) ||
- __put_user(child->thread_info->xfsr[0], (&fps->fsr)) ||
+ __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
__put_user(0, (&fps->fpqd)) ||
__put_user(0, (&fps->flags)) ||
__put_user(0, (&fps->extra)) ||
@@ -476,11 +452,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
unsigned long fsr;
};
struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = child->thread_info->fpregs;
+ unsigned long *fpregs = task_thread_info(child)->fpregs;
if (copy_to_user(&fps->regs[0], fpregs,
(64 * sizeof(unsigned int))) ||
- __put_user(child->thread_info->xfsr[0], (&fps->fsr))) {
+ __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
pt_error_return(regs, EFAULT);
goto out_tsk;
}
@@ -501,7 +477,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = child->thread_info->fpregs;
+ unsigned long *fpregs = task_thread_info(child)->fpregs;
unsigned fsr;
if (copy_from_user(fpregs, &fps->regs[0],
@@ -510,11 +486,11 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
pt_error_return(regs, EFAULT);
goto out_tsk;
}
- child->thread_info->xfsr[0] &= 0xffffffff00000000UL;
- child->thread_info->xfsr[0] |= fsr;
- if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
- child->thread_info->gsr[0] = 0;
- child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
+ task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
+ task_thread_info(child)->xfsr[0] |= fsr;
+ if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
+ task_thread_info(child)->gsr[0] = 0;
+ task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
pt_succ_return(regs, 0);
goto out_tsk;
}
@@ -525,17 +501,17 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
unsigned long fsr;
};
struct fps __user *fps = (struct fps __user *) addr;
- unsigned long *fpregs = child->thread_info->fpregs;
+ unsigned long *fpregs = task_thread_info(child)->fpregs;
if (copy_from_user(fpregs, &fps->regs[0],
(64 * sizeof(unsigned int))) ||
- __get_user(child->thread_info->xfsr[0], (&fps->fsr))) {
+ __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) {
pt_error_return(regs, EFAULT);
goto out_tsk;
}
- if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
- child->thread_info->gsr[0] = 0;
- child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
+ if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
+ task_thread_info(child)->gsr[0] = 0;
+ task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
pt_succ_return(regs, 0);
goto out_tsk;
}
@@ -586,8 +562,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
#ifdef DEBUG_PTRACE
printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
child->pid, child->exit_code,
- child->thread_info->kregs->tpc,
- child->thread_info->kregs->tnpc);
+ task_pt_regs(child)->tpc,
+ task_pt_regs(child)->tnpc);
#endif
wake_up_process(child);
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 48180531562f..054461e6946d 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -520,7 +520,7 @@ void __init setup_arch(char **cmdline_p)
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
#endif
- init_task.thread_info->kregs = &fake_swapper_regs;
+ task_thread_info(&init_task)->kregs = &fake_swapper_regs;
#ifdef CONFIG_IP_PNP
if (!ic_set_manually) {
@@ -561,6 +561,8 @@ static int __init set_preferred_console(void)
serial_console = 1;
} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
serial_console = 2;
+ } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
+ serial_console = 3;
} else {
prom_printf("Inconsistent console: "
"input %d, output %d\n",
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 6efc03df51c3..1fb6323e65a4 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -335,7 +335,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
p = fork_idle(cpu);
callin_flag = 0;
- cpu_new_thread = p->thread_info;
+ cpu_new_thread = task_thread_info(p);
cpu_set(cpu, cpu_callout_map);
cpu_find_by_mid(cpu, &cpu_node);
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index fb7a5370dbfc..d177d7e5c9d3 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -94,7 +94,6 @@ extern void (*prom_palette)(int);
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);
extern unsigned long phys_base;
@@ -241,7 +240,6 @@ EXPORT_SYMBOL(io_remap_pfn_range);
EXPORT_SYMBOL(_sigpause_common);
EXPORT_SYMBOL(verify_compat_iovec);
-EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(pte_alloc_one_kernel);
#ifndef CONFIG_SMP
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 7f6239ed2521..9264ccbaaafa 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -11,6 +11,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/file.h>
@@ -820,7 +821,7 @@ asmlinkage long sys32_utimes(char __user *filename,
return -EFAULT;
}
- return do_utimes(filename, (tvs ? &ktvs[0] : NULL));
+ return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL));
}
/* These are here just in case some old sparc32 binary calls it. */
@@ -1002,7 +1003,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
asmlinkage long sparc32_open(const char __user *filename,
int flags, int mode)
{
- return do_sys_open(filename, flags, mode);
+ return do_sys_open(AT_FDCWD, filename, flags, mode);
}
extern unsigned long do_mremap(unsigned long addr,
@@ -1120,39 +1121,3 @@ long sys32_lookup_dcookie(unsigned long cookie_high,
return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
buf, len);
}
-
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
- struct sigevent __user *timer_event_spec,
- timer_t __user *created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32,
- timer_t __user *timer_id)
-{
- struct sigevent se;
- mm_segment_t oldfs;
- timer_t t;
- long err;
-
- if (se32 == NULL)
- return sys_timer_create(clock, NULL, timer_id);
-
- if (get_compat_sigevent(&se, se32))
- return -EFAULT;
-
- if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
- return -EFAULT;
-
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- err = sys_timer_create(clock,
- (struct sigevent __user *) &se,
- (timer_t __user *) &t);
- set_fs(oldfs);
-
- if (!err)
- err = __put_user (t, timer_id);
-
- return err;
-}
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index bfa4aa68312d..ae5b32f817f0 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/mman.h>
#include <linux/mm.h>
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 53eaf2345fe9..98d24bc00044 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -73,7 +73,7 @@ sys_call_table32:
/*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
.word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
- .word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
+ .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
@@ -98,7 +98,7 @@ sys_call_table:
.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
-/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_stat64, sys_getpagesize
+/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
.word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect
.word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 459c8fbe02b4..a22930d62adf 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -280,9 +280,9 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
* Since STICK is constantly updating, we have to access it carefully.
*
* The sequence we use to read is:
- * 1) read low
- * 2) read high
- * 3) read low again, if it rolled over increment high by 1
+ * 1) read high
+ * 2) read low
+ * 3) read high again, if it rolled re-read both low and high again.
*
* Writing STICK safely is also tricky:
* 1) write low to zero
@@ -295,18 +295,18 @@ static struct sparc64_tick_ops stick_operations __read_mostly = {
static unsigned long __hbird_read_stick(void)
{
unsigned long ret, tmp1, tmp2, tmp3;
- unsigned long addr = HBIRD_STICK_ADDR;
+ unsigned long addr = HBIRD_STICK_ADDR+8;
- __asm__ __volatile__("ldxa [%1] %5, %2\n\t"
- "add %1, 0x8, %1\n\t"
- "ldxa [%1] %5, %3\n\t"
+ __asm__ __volatile__("ldxa [%1] %5, %2\n"
+ "1:\n\t"
"sub %1, 0x8, %1\n\t"
+ "ldxa [%1] %5, %3\n\t"
+ "add %1, 0x8, %1\n\t"
"ldxa [%1] %5, %4\n\t"
"cmp %4, %2\n\t"
- "blu,a,pn %%xcc, 1f\n\t"
- " add %3, 1, %3\n"
- "1:\n\t"
- "sllx %3, 32, %3\n\t"
+ "bne,a,pn %%xcc, 1b\n\t"
+ " mov %4, %2\n\t"
+ "sllx %4, 32, %4\n\t"
"or %3, %4, %0\n\t"
: "=&r" (ret), "=&r" (addr),
"=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3)
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 5570e7bb22bb..8d44ae5a15e3 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1808,7 +1808,7 @@ static void user_instruction_dump (unsigned int __user *pc)
void show_stack(struct task_struct *tsk, unsigned long *_ksp)
{
unsigned long pc, fp, thread_base, ksp;
- struct thread_info *tp = tsk->thread_info;
+ void *tp = task_stack_page(tsk);
struct reg_window *rw;
int count = 0;
@@ -1862,7 +1862,7 @@ static inline int is_kernel_stack(struct task_struct *task,
return 0;
}
- thread_base = (unsigned long) task->thread_info;
+ thread_base = (unsigned long) task_stack_page(task);
thread_end = thread_base + sizeof(union thread_union);
if (rw_addr >= thread_base &&
rw_addr < thread_end &&
diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c
index eae5db8dda56..ac6d035dd150 100644
--- a/arch/sparc64/prom/console.c
+++ b/arch/sparc64/prom/console.c
@@ -99,8 +99,12 @@ prom_query_input_device(void)
if (!strncmp(propb, "keyboard", 8))
return PROMDEV_ITTYA;
+ if (!strncmp (propb, "rsc", 3))
+ return PROMDEV_IRSC;
+
if (strncmp (propb, "tty", 3) || !propb[3])
return PROMDEV_I_UNK;
+
switch (propb[3]) {
case 'a': return PROMDEV_ITTYA;
case 'b': return PROMDEV_ITTYB;
@@ -136,8 +140,12 @@ prom_query_output_device(void)
if (!strncmp(propb, "screen", 6))
return PROMDEV_OTTYA;
+ if (!strncmp (propb, "rsc", 3))
+ return PROMDEV_ORSC;
+
if (strncmp (propb, "tty", 3) || !propb[3])
return PROMDEV_O_UNK;
+
switch (propb[3]) {
case 'a': return PROMDEV_OTTYA;
case 'b': return PROMDEV_OTTYB;
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index d7c99fa89661..4885ca6cbc77 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/mm.h>
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 1eb21de9d1b5..5982fe2753e0 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -22,10 +22,6 @@ config SBUS
config PCI
bool
-config UID16
- bool
- default y
-
config GENERIC_CALIBRATE_DELAY
bool
default y
@@ -39,12 +35,12 @@ menu "UML-specific options"
config MODE_TT
bool "Tracing thread support"
- default y
+ default n
help
This option controls whether tracing thread support is compiled
- into UML. Normally, this should be set to Y. If you intend to
- use only skas mode (and the host has the skas patch applied to it),
- then it is OK to say N here.
+ into UML. This option is largely obsolete, given that skas0 provides
+ skas security and performance without needing to patch the host.
+ It is safe to say 'N' here.
config STATIC_LINK
bool "Force a static link"
@@ -83,7 +79,7 @@ config KERNEL_HALF_GIGS
of physical memory.
config MODE_SKAS
- bool "Separate Kernel Address Space support"
+ bool "Separate Kernel Address Space support" if MODE_TT
default y
help
This option controls whether skas (separate kernel address space)
@@ -147,6 +143,7 @@ config HOSTFS
config HPPFS
tristate "HoneyPot ProcFS (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
help
hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
entries to be overridden, removed, or fabricated from the host.
@@ -159,10 +156,6 @@ config HPPFS
You only need this if you are setting up a UML honeypot. Otherwise,
it is safe to say 'N' here.
- If you are actively using it, please report any problems, since it's
- getting fixed. In this moment, it is experimental on 2.6 (it works on
- 2.4).
-
config MCONSOLE
bool "Management console"
default y
@@ -247,8 +240,16 @@ config NEST_LEVEL
Only change this if you are running nested UMLs.
config HIGHMEM
- bool "Highmem support"
- depends on !64BIT
+ bool "Highmem support (EXPERIMENTAL)"
+ depends on !64BIT && EXPERIMENTAL
+ default n
+ help
+ This was used to allow UML to run with big amounts of memory.
+ Currently it is unstable, so if unsure say N.
+
+ To use big amounts of memory, it is recommended to disable TT mode (i.e.
+ CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
+ this should allow the guest to use up to 2.75G of memory.
config KERNEL_STACK_ORDER
int "Kernel stack size order"
@@ -273,17 +274,13 @@ endmenu
source "init/Kconfig"
-source "net/Kconfig"
-
-source "drivers/base/Kconfig"
+source "drivers/block/Kconfig"
source "arch/um/Kconfig.char"
-source "drivers/block/Kconfig"
+source "drivers/base/Kconfig"
-config NETDEVICES
- bool
- default NET
+source "net/Kconfig"
source "arch/um/Kconfig.net"
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index c71b39a677aa..ef79ed25aecd 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -22,13 +22,17 @@ config TOP_ADDR
default 0x80000000 if HOST_2G_2G
config 3_LEVEL_PGTABLES
- bool "Three-level pagetables"
+ bool "Three-level pagetables (EXPERIMENTAL)"
default n
+ depends on EXPERIMENTAL
help
Three-level pagetables will let UML have more than 4G of physical
memory. All the memory that can't be mapped directly will be treated
as high memory.
+ However, this it experimental on 32-bit architectures, so if unsure say
+ N (on x86-64 it's automatically enabled, instead, as it's safe there).
+
config STUB_CODE
hex
default 0xbfffe000
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 1b12feeba368..6430a6383853 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt
um-modes-$(CONFIG_MODE_SKAS) += skas
MODE_INCLUDE += $(foreach mode,$(um-modes-y),\
- -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include)
+ -I$(srctree)/$(ARCH_DIR)/include/$(mode))
MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\
$(srctree)/$(ARCH_DIR)/Makefile-$(mode))
@@ -67,7 +67,8 @@ USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
# in CFLAGS. Otherwise, it would cause ld to complain about the two different
# errnos.
-CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask
+CFLAGS += -Derrno=kernel_errno -Dsigprocmask=kernel_sigprocmask \
+ -Dmktime=kernel_mktime
CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
@@ -189,6 +190,12 @@ define filechk_umlconfig
sed 's/ CONFIG/ UML_CONFIG/'
endef
+$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
+ $(call filechk,umlconfig)
+
+$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
+ $(CC) $(USER_CFLAGS) -S -o $@ $<
+
define filechk_gen-asm-offsets
(set -e; \
echo "/*"; \
@@ -202,24 +209,13 @@ define filechk_gen-asm-offsets
echo ""; )
endef
-$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
- $(call filechk,umlconfig)
-
-$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
- $(CC) $(USER_CFLAGS) -S -o $@ $<
-
$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
$(call filechk,gen-asm-offsets)
CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
-$(ARCH_DIR)/kernel-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/kernel-offsets.c \
- archprepare
- $(CC) $(CFLAGS) $(NOSTDINC_FLAGS) $(CPPFLAGS) -S -o $@ $<
-
-$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/kernel-offsets.s
- $(call filechk,gen-asm-offsets)
-
-CLEAN_FILES += $(ARCH_DIR)/kernel-offsets.s
+$(ARCH_DIR)/include/kern_constants.h:
+ @echo ' SYMLINK $@'
+ $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 5b58fad45290..ab0d0b170816 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(NULL);
+ return NULL;
}
static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(-ENODEV);
+ return -ENODEV;
}
static void not_configged_close(int fd, void *data)
@@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(-EIO);
+ return -EIO;
}
static int not_configged_write(int fd, const char *buf, int len, void *data)
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(-EIO);
+ return -EIO;
}
static int not_configged_console_write(int fd, const char *buf, int len)
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(-EIO);
+ return -EIO;
}
static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
{
my_puts("Using a channel type which is configured out of "
"UML\n");
- return(-ENODEV);
+ return -ENODEV;
}
static void not_configged_free(void *data)
@@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
n = os_read_file(fd, c_out, sizeof(*c_out));
if(n == -EAGAIN)
- return(0);
+ return 0;
else if(n == 0)
- return(-EIO);
- return(n);
+ return -EIO;
+ return n;
}
/* XXX Trivial wrapper around os_write_file */
int generic_write(int fd, const char *buf, int n, void *unused)
{
- return(os_write_file(fd, buf, n));
+ return os_write_file(fd, buf, n);
}
int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
ret = os_window_size(fd, &rows, &cols);
if(ret < 0)
- return(ret);
+ return ret;
ret = ((*rows_out != rows) || (*cols_out != cols));
*rows_out = rows;
*cols_out = cols;
- return(ret);
+ return ret;
}
void generic_free(void *data)
@@ -186,25 +186,26 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
}
}
- if((tty->flip.flag_buf_ptr == NULL) ||
- (tty->flip.char_buf_ptr == NULL))
- return;
tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
-static int open_one_chan(struct chan *chan, int input, int output, int primary)
+static int open_one_chan(struct chan *chan)
{
int fd;
- if(chan->opened) return(0);
- if(chan->ops->open == NULL) fd = 0;
- else fd = (*chan->ops->open)(input, output, primary, chan->data,
- &chan->dev);
- if(fd < 0) return(fd);
+ if(chan->opened)
+ return 0;
+
+ if(chan->ops->open == NULL)
+ fd = 0;
+ else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
+ chan->data, &chan->dev);
+ if(fd < 0)
+ return fd;
chan->fd = fd;
chan->opened = 1;
- return(0);
+ return 0;
}
int open_chan(struct list_head *chans)
@@ -215,11 +216,11 @@ int open_chan(struct list_head *chans)
list_for_each(ele, chans){
chan = list_entry(ele, struct chan, list);
- ret = open_one_chan(chan, chan->input, chan->output,
- chan->primary);
- if(chan->primary) err = ret;
+ ret = open_one_chan(chan);
+ if(chan->primary)
+ err = ret;
}
- return(err);
+ return err;
}
void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -236,20 +237,65 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
}
}
-void enable_chan(struct list_head *chans, struct tty_struct *tty)
+void enable_chan(struct line *line)
{
struct list_head *ele;
struct chan *chan;
- list_for_each(ele, chans){
+ list_for_each(ele, &line->chan_list){
chan = list_entry(ele, struct chan, list);
- if(!chan->opened) continue;
+ if(open_one_chan(chan))
+ continue;
- line_setup_irq(chan->fd, chan->input, chan->output, tty);
+ if(chan->enabled)
+ continue;
+ line_setup_irq(chan->fd, chan->input, chan->output, line,
+ chan);
+ chan->enabled = 1;
}
}
-void close_chan(struct list_head *chans)
+static LIST_HEAD(irqs_to_free);
+
+void free_irqs(void)
+{
+ struct chan *chan;
+
+ while(!list_empty(&irqs_to_free)){
+ chan = list_entry(irqs_to_free.next, struct chan, free_list);
+ list_del(&chan->free_list);
+
+ if(chan->input)
+ free_irq(chan->line->driver->read_irq, chan);
+ if(chan->output)
+ free_irq(chan->line->driver->write_irq, chan);
+ chan->enabled = 0;
+ }
+}
+
+static void close_one_chan(struct chan *chan, int delay_free_irq)
+{
+ if(!chan->opened)
+ return;
+
+ if(delay_free_irq){
+ list_add(&chan->free_list, &irqs_to_free);
+ }
+ else {
+ if(chan->input)
+ free_irq(chan->line->driver->read_irq, chan);
+ if(chan->output)
+ free_irq(chan->line->driver->write_irq, chan);
+ chan->enabled = 0;
+ }
+ if(chan->ops->close != NULL)
+ (*chan->ops->close)(chan->fd, chan->data);
+
+ chan->opened = 0;
+ chan->fd = -1;
+}
+
+void close_chan(struct list_head *chans, int delay_free_irq)
{
struct chan *chan;
@@ -259,15 +305,37 @@ void close_chan(struct list_head *chans)
* so it must be the last closed.
*/
list_for_each_entry_reverse(chan, chans, list) {
- if(!chan->opened) continue;
- if(chan->ops->close != NULL)
- (*chan->ops->close)(chan->fd, chan->data);
- chan->opened = 0;
- chan->fd = -1;
+ close_one_chan(chan, delay_free_irq);
}
}
-int write_chan(struct list_head *chans, const char *buf, int len,
+void deactivate_chan(struct list_head *chans, int irq)
+{
+ struct list_head *ele;
+
+ struct chan *chan;
+ list_for_each(ele, chans) {
+ chan = list_entry(ele, struct chan, list);
+
+ if(chan->enabled && chan->input)
+ deactivate_fd(chan->fd, irq);
+ }
+}
+
+void reactivate_chan(struct list_head *chans, int irq)
+{
+ struct list_head *ele;
+ struct chan *chan;
+
+ list_for_each(ele, chans) {
+ chan = list_entry(ele, struct chan, list);
+
+ if(chan->enabled && chan->input)
+ reactivate_fd(chan->fd, irq);
+ }
+}
+
+int write_chan(struct list_head *chans, const char *buf, int len,
int write_irq)
{
struct list_head *ele;
@@ -285,7 +353,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
reactivate_fd(chan->fd, write_irq);
}
}
- return(ret);
+ return ret;
}
int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -301,19 +369,18 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
n = chan->ops->console_write(chan->fd, buf, len);
if(chan->primary) ret = n;
}
- return(ret);
+ return ret;
}
-int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts)
+int console_open_chan(struct line *line, struct console *co,
+ struct chan_opts *opts)
{
- if (!list_empty(&line->chan_list))
- return 0;
+ int err;
+
+ err = open_chan(&line->chan_list);
+ if(err)
+ return err;
- if (0 != parse_chan_pair(line->init_str, &line->chan_list,
- line->init_pri, co->index, opts))
- return -1;
- if (0 != open_chan(&line->chan_list))
- return -1;
printk("Console initialized on /dev/%s%d\n",co->name,co->index);
return 0;
}
@@ -327,32 +394,36 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
list_for_each(ele, chans){
chan = list_entry(ele, struct chan, list);
if(chan->primary){
- if(chan->ops->window_size == NULL) return(0);
- return(chan->ops->window_size(chan->fd, chan->data,
- rows_out, cols_out));
+ if(chan->ops->window_size == NULL)
+ return 0;
+ return chan->ops->window_size(chan->fd, chan->data,
+ rows_out, cols_out);
}
}
- return(0);
+ return 0;
}
-void free_one_chan(struct chan *chan)
+void free_one_chan(struct chan *chan, int delay_free_irq)
{
list_del(&chan->list);
+
+ close_one_chan(chan, delay_free_irq);
+
if(chan->ops->free != NULL)
(*chan->ops->free)(chan->data);
- free_irq_by_fd(chan->fd);
+
if(chan->primary && chan->output) ignore_sigio_fd(chan->fd);
kfree(chan);
}
-void free_chan(struct list_head *chans)
+void free_chan(struct list_head *chans, int delay_free_irq)
{
struct list_head *ele, *next;
struct chan *chan;
list_for_each_safe(ele, next, chans){
chan = list_entry(ele, struct chan, list);
- free_one_chan(chan);
+ free_one_chan(chan, delay_free_irq);
}
}
@@ -363,23 +434,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
if(chan == NULL){
CONFIG_CHUNK(str, size, n, "none", 1);
- return(n);
+ return n;
}
CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
if(chan->dev == NULL){
CONFIG_CHUNK(str, size, n, "", 1);
- return(n);
+ return n;
}
CONFIG_CHUNK(str, size, n, ":", 0);
CONFIG_CHUNK(str, size, n, chan->dev, 0);
- return(n);
+ return n;
}
-static int chan_pair_config_string(struct chan *in, struct chan *out,
+static int chan_pair_config_string(struct chan *in, struct chan *out,
char *str, int size, char **error_out)
{
int n;
@@ -390,7 +461,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
if(in == out){
CONFIG_CHUNK(str, size, n, "", 1);
- return(n);
+ return n;
}
CONFIG_CHUNK(str, size, n, ",", 1);
@@ -399,10 +470,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
size -= n;
CONFIG_CHUNK(str, size, n, "", 1);
- return(n);
+ return n;
}
-int chan_config_string(struct list_head *chans, char *str, int size,
+int chan_config_string(struct list_head *chans, char *str, int size,
char **error_out)
{
struct list_head *ele;
@@ -418,7 +489,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
out = chan;
}
- return(chan_pair_config_string(in, out, str, size, error_out));
+ return chan_pair_config_string(in, out, str, size, error_out);
}
struct chan_type {
@@ -462,7 +533,7 @@ struct chan_type chan_table[] = {
#endif
};
-static struct chan *parse_chan(char *str, int pri, int device,
+static struct chan *parse_chan(struct line *line, char *str, int device,
struct chan_opts *opts)
{
struct chan_type *entry;
@@ -484,36 +555,42 @@ static struct chan *parse_chan(char *str, int pri, int device,
if(ops == NULL){
my_printf("parse_chan couldn't parse \"%s\"\n",
str);
- return(NULL);
+ return NULL;
}
- if(ops->init == NULL) return(NULL);
+ if(ops->init == NULL)
+ return NULL;
data = (*ops->init)(str, device, opts);
- if(data == NULL) return(NULL);
+ if(data == NULL)
+ return NULL;
chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
- if(chan == NULL) return(NULL);
+ if(chan == NULL)
+ return NULL;
*chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
+ .free_list =
+ LIST_HEAD_INIT(chan->free_list),
+ .line = line,
.primary = 1,
.input = 0,
.output = 0,
.opened = 0,
+ .enabled = 0,
.fd = -1,
- .pri = pri,
.ops = ops,
.data = data });
- return(chan);
+ return chan;
}
-int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
+int parse_chan_pair(char *str, struct line *line, int device,
struct chan_opts *opts)
{
+ struct list_head *chans = &line->chan_list;
struct chan *new, *chan;
char *in, *out;
if(!list_empty(chans)){
chan = list_entry(chans->next, struct chan, list);
- if(chan->pri >= pri) return(0);
- free_chan(chans);
+ free_chan(chans, 0);
INIT_LIST_HEAD(chans);
}
@@ -522,24 +599,30 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
in = str;
*out = '\0';
out++;
- new = parse_chan(in, pri, device, opts);
- if(new == NULL) return(-1);
+ new = parse_chan(line, in, device, opts);
+ if(new == NULL)
+ return -1;
+
new->input = 1;
list_add(&new->list, chans);
- new = parse_chan(out, pri, device, opts);
- if(new == NULL) return(-1);
+ new = parse_chan(line, out, device, opts);
+ if(new == NULL)
+ return -1;
+
list_add(&new->list, chans);
new->output = 1;
}
else {
- new = parse_chan(str, pri, device, opts);
- if(new == NULL) return(-1);
+ new = parse_chan(line, str, device, opts);
+ if(new == NULL)
+ return -1;
+
list_add(&new->list, chans);
new->input = 1;
new->output = 1;
}
- return(0);
+ return 0;
}
int chan_out_fd(struct list_head *chans)
@@ -550,9 +633,9 @@ int chan_out_fd(struct list_head *chans)
list_for_each(ele, chans){
chan = list_entry(ele, struct chan, list);
if(chan->primary && chan->output)
- return(chan->fd);
+ return chan->fd;
}
- return(-1);
+ return -1;
}
void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -567,9 +650,8 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
chan = list_entry(ele, struct chan, list);
if(!chan->input || (chan->ops->read == NULL)) continue;
do {
- if((tty != NULL) &&
- (tty->flip.count >= TTY_FLIPBUF_SIZE)){
- schedule_work(task);
+ if (tty && !tty_buffer_request_room(tty, 1)) {
+ schedule_delayed_work(task, 1);
goto out;
}
err = chan->ops->read(chan->fd, &c, chan->data);
@@ -582,29 +664,12 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
if(chan->primary){
if(tty != NULL)
tty_hangup(tty);
- line_disable(tty, irq);
- close_chan(chans);
- free_chan(chans);
+ close_chan(chans, 1);
return;
}
- else {
- if(chan->ops->close != NULL)
- chan->ops->close(chan->fd, chan->data);
- free_one_chan(chan);
- }
+ else close_one_chan(chan, 1);
}
}
out:
if(tty) tty_flip_buffer_push(tty);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c
index 30d285b266af..507e3cbac9d3 100644
--- a/arch/um/drivers/daemon_kern.c
+++ b/arch/um/drivers/daemon_kern.c
@@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data)
dpri->fd = -1;
dpri->control = -1;
dpri->dev = dev;
+ /* We will free this pointer. If it contains crap we're burned. */
+ dpri->ctl_addr = NULL;
+ dpri->data_addr = NULL;
+ dpri->local_addr = NULL;
printk("daemon backend (uml_switch version %d) - %s:%s",
SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock);
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index 1bb085b2824d..c944265955e2 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -158,10 +158,16 @@ static void daemon_remove(void *data)
struct daemon_data *pri = data;
os_close_file(pri->fd);
+ pri->fd = -1;
os_close_file(pri->control);
+ pri->control = -1;
+
kfree(pri->data_addr);
+ pri->data_addr = NULL;
kfree(pri->ctl_addr);
+ pri->ctl_addr = NULL;
kfree(pri->local_addr);
+ pri->local_addr = NULL;
}
int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 3296e86a03a5..c41f75e4acb5 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -11,6 +11,7 @@
#include "user.h"
#include "user_util.h"
#include "chan_user.h"
+#include "os.h"
struct fd_chan {
int fd;
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index e0fdffa2d542..46ceb25a9959 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -23,8 +23,9 @@
static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
{
- struct tty_struct *tty = data;
- struct line *line = tty->driver_data;
+ struct chan *chan = data;
+ struct line *line = chan->line;
+ struct tty_struct *tty = line->tty;
if (line)
chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,11 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
static void line_timer_cb(void *arg)
{
- struct tty_struct *tty = arg;
- struct line *line = tty->driver_data;
+ struct line *line = arg;
- line_interrupt(line->driver->read_irq, arg, NULL);
+ if(!line->throttled)
+ chan_interrupt(&line->chan_list, &line->task, line->tty,
+ line->driver->read_irq);
}
/* Returns the free space inside the ring buffer of this line.
@@ -124,7 +126,8 @@ static int buffer_data(struct line *line, const char *buf, int len)
if (len < end){
memcpy(line->tail, buf, len);
line->tail += len;
- } else {
+ }
+ else {
/* The circular buffer is wrapping */
memcpy(line->tail, buf, end);
buf += end;
@@ -170,7 +173,7 @@ static int flush_buffer(struct line *line)
}
count = line->tail - line->head;
- n = write_chan(&line->chan_list, line->head, count,
+ n = write_chan(&line->chan_list, line->head, count,
line->driver->write_irq);
if(n < 0)
@@ -227,7 +230,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
if (err <= 0 && (err != -EAGAIN || !ret))
ret = err;
} else {
- n = write_chan(&line->chan_list, buf, len,
+ n = write_chan(&line->chan_list, buf, len,
line->driver->write_irq);
if (n < 0) {
ret = n;
@@ -338,11 +341,36 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
return ret;
}
+void line_throttle(struct tty_struct *tty)
+{
+ struct line *line = tty->driver_data;
+
+ deactivate_chan(&line->chan_list, line->driver->read_irq);
+ line->throttled = 1;
+}
+
+void line_unthrottle(struct tty_struct *tty)
+{
+ struct line *line = tty->driver_data;
+
+ line->throttled = 0;
+ chan_interrupt(&line->chan_list, &line->task, tty,
+ line->driver->read_irq);
+
+ /* Maybe there is enough stuff pending that calling the interrupt
+ * throttles us again. In this case, line->throttled will be 1
+ * again and we shouldn't turn the interrupt back on.
+ */
+ if(!line->throttled)
+ reactivate_chan(&line->chan_list, line->driver->read_irq);
+}
+
static irqreturn_t line_write_interrupt(int irq, void *data,
struct pt_regs *unused)
{
- struct tty_struct *tty = data;
- struct line *line = tty->driver_data;
+ struct chan *chan = data;
+ struct line *line = chan->line;
+ struct tty_struct *tty = line->tty;
int err;
/* Interrupts are enabled here because we registered the interrupt with
@@ -364,7 +392,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
(tty->ldisc.write_wakeup != NULL))
(tty->ldisc.write_wakeup)(tty);
-
+
/* BLOCKING mode
* In blocking mode, everything sleeps on tty->write_wait.
* Sleeping in the console driver would break non-blocking
@@ -376,53 +404,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
return IRQ_HANDLED;
}
-int line_setup_irq(int fd, int input, int output, struct tty_struct *tty)
+int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
{
- struct line *line = tty->driver_data;
struct line_driver *driver = line->driver;
int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
if (input)
err = um_request_irq(driver->read_irq, fd, IRQ_READ,
- line_interrupt, flags,
- driver->read_irq_name, tty);
+ line_interrupt, flags,
+ driver->read_irq_name, data);
if (err)
return err;
if (output)
err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
- line_write_interrupt, flags,
- driver->write_irq_name, tty);
+ line_write_interrupt, flags,
+ driver->write_irq_name, data);
line->have_irq = 1;
return err;
}
-void line_disable(struct tty_struct *tty, int current_irq)
-{
- struct line *line = tty->driver_data;
-
- if(!line->have_irq)
- return;
-
- if(line->driver->read_irq == current_irq)
- free_irq_later(line->driver->read_irq, tty);
- else {
- free_irq(line->driver->read_irq, tty);
- }
-
- if(line->driver->write_irq == current_irq)
- free_irq_later(line->driver->write_irq, tty);
- else {
- free_irq(line->driver->write_irq, tty);
- }
-
- line->have_irq = 0;
-}
-
-int line_open(struct line *lines, struct tty_struct *tty,
- struct chan_opts *opts)
+int line_open(struct line *lines, struct tty_struct *tty)
{
struct line *line;
- int err = 0;
+ int err = -ENODEV;
line = &lines[tty->index];
tty->driver_data = line;
@@ -430,31 +434,29 @@ int line_open(struct line *lines, struct tty_struct *tty,
/* The IRQ which takes this lock is not yet enabled and won't be run
* before the end, so we don't need to use spin_lock_irq.*/
spin_lock(&line->lock);
- if (tty->count == 1) {
- if (!line->valid) {
- err = -ENODEV;
- goto out;
- }
- if (list_empty(&line->chan_list)) {
- err = parse_chan_pair(line->init_str, &line->chan_list,
- line->init_pri, tty->index, opts);
- if(err) goto out;
- err = open_chan(&line->chan_list);
- if(err) goto out;
+
+ tty->driver_data = line;
+ line->tty = tty;
+ if(!line->valid)
+ goto out;
+
+ if(tty->count == 1){
+ /* Here the device is opened, if necessary, and interrupt
+ * is registered.
+ */
+ enable_chan(line);
+ INIT_WORK(&line->task, line_timer_cb, line);
+
+ if(!line->sigio){
+ chan_enable_winch(&line->chan_list, tty);
+ line->sigio = 1;
}
- /* Here the interrupt is registered.*/
- enable_chan(&line->chan_list, tty);
- INIT_WORK(&line->task, line_timer_cb, tty);
- }
- if(!line->sigio){
- chan_enable_winch(&line->chan_list, tty);
- line->sigio = 1;
+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+ &tty->winsize.ws_col);
}
- chan_window_size(&line->chan_list, &tty->winsize.ws_row,
- &tty->winsize.ws_col);
- line->count++;
+ err = 0;
out:
spin_unlock(&line->lock);
return err;
@@ -474,15 +476,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
/* We ignore the error anyway! */
flush_buffer(line);
- line->count--;
- if (tty->count == 1) {
- line_disable(tty, -1);
+ if(tty->count == 1){
+ line->tty = NULL;
tty->driver_data = NULL;
- }
- if((line->count == 0) && line->sigio){
- unregister_winch(tty);
- line->sigio = 0;
+ if(line->sigio){
+ unregister_winch(tty);
+ line->sigio = 0;
+ }
}
spin_unlock_irq(&line->lock);
@@ -493,17 +494,15 @@ void close_lines(struct line *lines, int nlines)
int i;
for(i = 0; i < nlines; i++)
- close_chan(&lines[i].chan_list);
+ close_chan(&lines[i].chan_list, 0);
}
/* Common setup code for both startup command line and mconsole initialization.
* @lines contains the the array (of size @num) to modify;
* @init is the setup string;
- * @all_allowed is a boolean saying if we can setup the whole @lines
- * at once. For instance, it will be usually true for startup init. (where we
- * can use con=xterm) and false for mconsole.*/
+ */
-int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed)
+int line_setup(struct line *lines, unsigned int num, char *init)
{
int i, n;
char *end;
@@ -512,10 +511,11 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
/* We said con=/ssl= instead of con#=, so we are configuring all
* consoles at once.*/
n = -1;
- } else {
+ }
+ else {
n = simple_strtoul(init, &end, 0);
if(*end != '='){
- printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
+ printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
init);
return 0;
}
@@ -527,8 +527,9 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
n, num - 1);
return 0;
- } else if (n >= 0){
- if (lines[n].count > 0) {
+ }
+ else if (n >= 0){
+ if (lines[n].tty != NULL) {
printk("line_setup - device %d is open\n", n);
return 0;
}
@@ -539,13 +540,10 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
else {
lines[n].init_str = init;
lines[n].valid = 1;
- }
+ }
}
- } else if(!all_allowed){
- printk("line_setup - can't configure all devices from "
- "mconsole\n");
- return 0;
- } else {
+ }
+ else {
for(i = 0; i < num; i++){
if(lines[i].init_pri <= INIT_ALL){
lines[i].init_pri = INIT_ALL;
@@ -557,18 +555,33 @@ int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed
}
}
}
- return 1;
+ return n == -1 ? num : n;
}
-int line_config(struct line *lines, unsigned int num, char *str)
+int line_config(struct line *lines, unsigned int num, char *str,
+ struct chan_opts *opts)
{
- char *new = uml_strdup(str);
+ struct line *line;
+ char *new;
+ int n;
+ if(*str == '='){
+ printk("line_config - can't configure all devices from "
+ "mconsole\n");
+ return 1;
+ }
+
+ new = kstrdup(str, GFP_KERNEL);
if(new == NULL){
- printk("line_config - uml_strdup failed\n");
- return -ENOMEM;
+ printk("line_config - kstrdup failed\n");
+ return 1;
}
- return !line_setup(lines, num, new, 0);
+ n = line_setup(lines, num, new);
+ if(n < 0)
+ return 1;
+
+ line = &lines[n];
+ return parse_chan_pair(line->init_str, line, n, opts);
}
int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -594,7 +607,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
spin_lock(&line->lock);
if(!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
- else if(line->count == 0)
+ else if(line->tty == NULL)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
spin_unlock(&line->lock);
@@ -619,14 +632,18 @@ int line_id(char **str, int *start_out, int *end_out)
int line_remove(struct line *lines, unsigned int num, int n)
{
+ int err;
char config[sizeof("conxxxx=none\0")];
sprintf(config, "%d=none", n);
- return !line_setup(lines, num, config, 0);
+ err = line_setup(lines, num, config);
+ if(err >= 0)
+ err = 0;
+ return err;
}
struct tty_driver *line_register_devfs(struct lines *set,
- struct line_driver *line_driver,
+ struct line_driver *line_driver,
struct tty_operations *ops, struct line *lines,
int nlines)
{
@@ -655,7 +672,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
}
for(i = 0; i < nlines; i++){
- if(!lines[i].valid)
+ if(!lines[i].valid)
tty_unregister_device(driver, i);
}
@@ -663,24 +680,28 @@ struct tty_driver *line_register_devfs(struct lines *set,
return driver;
}
-static spinlock_t winch_handler_lock;
-LIST_HEAD(winch_handlers);
+static DEFINE_SPINLOCK(winch_handler_lock);
+static LIST_HEAD(winch_handlers);
-void lines_init(struct line *lines, int nlines)
+void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
{
struct line *line;
int i;
- spin_lock_init(&winch_handler_lock);
for(i = 0; i < nlines; i++){
line = &lines[i];
INIT_LIST_HEAD(&line->chan_list);
- spin_lock_init(&line->lock);
- if(line->init_str != NULL){
- line->init_str = uml_strdup(line->init_str);
- if(line->init_str == NULL)
- printk("lines_init - uml_strdup returned "
- "NULL\n");
+
+ if(line->init_str == NULL)
+ continue;
+
+ line->init_str = kstrdup(line->init_str, GFP_KERNEL);
+ if(line->init_str == NULL)
+ printk("lines_init - kstrdup returned NULL\n");
+
+ if(parse_chan_pair(line->init_str, line, i, opts)){
+ printk("parse_chan_pair failed for device %d\n", i);
+ line->valid = 0;
}
}
}
@@ -717,8 +738,7 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
tty = winch->tty;
if (tty != NULL) {
line = tty->driver_data;
- chan_window_size(&line->chan_list,
- &tty->winsize.ws_row,
+ chan_window_size(&line->chan_list, &tty->winsize.ws_row,
&tty->winsize.ws_col);
kill_pg(tty->pgrp, SIGWINCH, 1);
}
@@ -749,60 +769,54 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
spin_unlock(&winch_handler_lock);
if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
+ SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
"winch", winch) < 0)
printk("register_winch_irq - failed to register IRQ\n");
}
+static void free_winch(struct winch *winch)
+{
+ list_del(&winch->list);
+
+ if(winch->pid != -1)
+ os_kill_process(winch->pid, 1);
+ if(winch->fd != -1)
+ os_close_file(winch->fd);
+
+ free_irq(WINCH_IRQ, winch);
+ kfree(winch);
+}
+
static void unregister_winch(struct tty_struct *tty)
{
struct list_head *ele;
- struct winch *winch, *found = NULL;
+ struct winch *winch;
spin_lock(&winch_handler_lock);
+
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
if(winch->tty == tty){
- found = winch;
- break;
+ free_winch(winch);
+ break;
}
}
- if(found == NULL)
- goto err;
-
- list_del(&winch->list);
- spin_unlock(&winch_handler_lock);
-
- if(winch->pid != -1)
- os_kill_process(winch->pid, 1);
-
- free_irq(WINCH_IRQ, winch);
- kfree(winch);
-
- return;
-err:
spin_unlock(&winch_handler_lock);
}
-/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
- * order... are we sure that nothing else is done on the list? */
static void winch_cleanup(void)
{
- struct list_head *ele;
+ struct list_head *ele, *next;
struct winch *winch;
- list_for_each(ele, &winch_handlers){
+ spin_lock(&winch_handler_lock);
+
+ list_for_each_safe(ele, next, &winch_handlers){
winch = list_entry(ele, struct winch, list);
- if(winch->fd != -1){
- /* Why is this different from the above free_irq(),
- * which deactivates SIGIO? This searches the FD
- * somewhere else and removes it from the list... */
- deactivate_fd(winch->fd, WINCH_IRQ);
- os_close_file(winch->fd);
- }
- if(winch->pid != -1)
- os_kill_process(winch->pid, 1);
+ free_winch(winch);
}
+
+ spin_unlock(&winch_handler_lock);
}
__uml_exitcall(winch_cleanup);
@@ -811,10 +825,10 @@ char *add_xterm_umid(char *base)
char *umid, *title;
int len;
- umid = get_umid(1);
- if(umid == NULL)
+ umid = get_umid();
+ if(*umid == '\0')
return base;
-
+
len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
title = kmalloc(len, GFP_KERNEL);
if(title == NULL){
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 12c95368124a..e3d576567172 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -20,6 +20,7 @@
#include "linux/namei.h"
#include "linux/proc_fs.h"
#include "linux/syscalls.h"
+#include "linux/console.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
#include "user_util.h"
@@ -34,7 +35,7 @@
#include "irq_kern.h"
#include "choose-mode.h"
-static int do_unlink_socket(struct notifier_block *notifier,
+static int do_unlink_socket(struct notifier_block *notifier,
unsigned long what, void *data)
{
return(mconsole_unlink_socket());
@@ -46,12 +47,12 @@ static struct notifier_block reboot_notifier = {
.priority = 0,
};
-/* Safe without explicit locking for now. Tasklets provide their own
+/* Safe without explicit locking for now. Tasklets provide their own
* locking, and the interrupt handler is safe because it can't interrupt
* itself and it can only happen on CPU 0.
*/
-LIST_HEAD(mc_requests);
+static LIST_HEAD(mc_requests);
static void mc_work_proc(void *unused)
{
@@ -60,7 +61,7 @@ static void mc_work_proc(void *unused)
while(!list_empty(&mc_requests)){
local_save_flags(flags);
- req = list_entry(mc_requests.next, struct mconsole_entry,
+ req = list_entry(mc_requests.next, struct mconsole_entry,
list);
list_del(&req->list);
local_irq_restore(flags);
@@ -69,7 +70,7 @@ static void mc_work_proc(void *unused)
}
}
-DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
+static DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
@@ -103,8 +104,8 @@ void mconsole_version(struct mc_request *req)
{
char version[256];
- sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
- system_utsname.nodename, system_utsname.release,
+ sprintf(version, "%s %s %s %s %s", system_utsname.sysname,
+ system_utsname.nodename, system_utsname.release,
system_utsname.version, system_utsname.machine);
mconsole_reply(req, version, 0, 0);
}
@@ -348,7 +349,7 @@ static struct mc_device *mconsole_find_dev(char *name)
#define CONFIG_BUF_SIZE 64
-static void mconsole_get_config(int (*get_config)(char *, char *, int,
+static void mconsole_get_config(int (*get_config)(char *, char *, int,
char **),
struct mc_request *req, char *name)
{
@@ -389,7 +390,6 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int,
out:
if(buf != default_buf)
kfree(buf);
-
}
void mconsole_config(struct mc_request *req)
@@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req)
void mconsole_remove(struct mc_request *req)
{
- struct mc_device *dev;
+ struct mc_device *dev;
char *ptr = req->request.data, *err_msg = "";
- char error[256];
+ char error[256];
int err, start, end, n;
ptr += strlen("remove");
@@ -433,37 +433,112 @@ void mconsole_remove(struct mc_request *req)
return;
}
- ptr = &ptr[strlen(dev->name)];
-
- err = 1;
- n = (*dev->id)(&ptr, &start, &end);
- if(n < 0){
- err_msg = "Couldn't parse device number";
- goto out;
- }
- else if((n < start) || (n > end)){
- sprintf(error, "Invalid device number - must be between "
- "%d and %d", start, end);
- err_msg = error;
- goto out;
- }
+ ptr = &ptr[strlen(dev->name)];
+
+ err = 1;
+ n = (*dev->id)(&ptr, &start, &end);
+ if(n < 0){
+ err_msg = "Couldn't parse device number";
+ goto out;
+ }
+ else if((n < start) || (n > end)){
+ sprintf(error, "Invalid device number - must be between "
+ "%d and %d", start, end);
+ err_msg = error;
+ goto out;
+ }
err = (*dev->remove)(n);
- switch(err){
- case -ENODEV:
- err_msg = "Device doesn't exist";
- break;
- case -EBUSY:
- err_msg = "Device is currently open";
- break;
- default:
- break;
- }
- out:
+ switch(err){
+ case -ENODEV:
+ err_msg = "Device doesn't exist";
+ break;
+ case -EBUSY:
+ err_msg = "Device is currently open";
+ break;
+ default:
+ break;
+ }
+out:
mconsole_reply(req, err_msg, err, 0);
}
+static DEFINE_SPINLOCK(console_lock);
+static LIST_HEAD(clients);
+static char console_buf[MCONSOLE_MAX_DATA];
+static int console_index = 0;
+
+static void console_write(struct console *console, const char *string,
+ unsigned len)
+{
+ struct list_head *ele;
+ int n;
+
+ if(list_empty(&clients))
+ return;
+
+ while(1){
+ n = min(len, ARRAY_SIZE(console_buf) - console_index);
+ strncpy(&console_buf[console_index], string, n);
+ console_index += n;
+ string += n;
+ len -= n;
+ if(len == 0)
+ return;
+
+ list_for_each(ele, &clients){
+ struct mconsole_entry *entry;
+
+ entry = list_entry(ele, struct mconsole_entry, list);
+ mconsole_reply_len(&entry->request, console_buf,
+ console_index, 0, 1);
+ }
+
+ console_index = 0;
+ }
+}
+
+static struct console mc_console = { .name = "mc",
+ .write = console_write,
+ .flags = CON_ENABLED,
+ .index = -1 };
+
+static int mc_add_console(void)
+{
+ register_console(&mc_console);
+ return 0;
+}
+
+late_initcall(mc_add_console);
+
+static void with_console(struct mc_request *req, void (*proc)(void *),
+ void *arg)
+{
+ struct mconsole_entry entry;
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&entry.list);
+ entry.request = *req;
+ list_add(&entry.list, &clients);
+ spin_lock_irqsave(&console_lock, flags);
+
+ (*proc)(arg);
+
+ mconsole_reply_len(req, console_buf, console_index, 0, 0);
+ console_index = 0;
+
+ spin_unlock_irqrestore(&console_lock, flags);
+ list_del(&entry.list);
+}
+
#ifdef CONFIG_MAGIC_SYSRQ
+static void sysrq_proc(void *arg)
+{
+ char *op = arg;
+
+ handle_sysrq(*op, &current->thread.regs, NULL);
+}
+
void mconsole_sysrq(struct mc_request *req)
{
char *ptr = req->request.data;
@@ -471,8 +546,13 @@ void mconsole_sysrq(struct mc_request *req)
ptr += strlen("sysrq");
while(isspace(*ptr)) ptr++;
- mconsole_reply(req, "", 0, 0);
- handle_sysrq(*ptr, &current->thread.regs, NULL);
+ /* With 'b', the system will shut down without a chance to reply,
+ * so in this case, we reply first.
+ */
+ if(*ptr == 'b')
+ mconsole_reply(req, "", 0, 0);
+
+ with_console(req, sysrq_proc, ptr);
}
#else
void mconsole_sysrq(struct mc_request *req)
@@ -481,6 +561,14 @@ void mconsole_sysrq(struct mc_request *req)
}
#endif
+static void stack_proc(void *arg)
+{
+ struct task_struct *from = current, *to = arg;
+
+ to->thread.saved_task = from;
+ switch_to(from, to, from);
+}
+
/* Mconsole stack trace
* Added by Allan Graves, Jeff Dike
* Dumps a stacks registers to the linux console.
@@ -488,37 +576,34 @@ void mconsole_sysrq(struct mc_request *req)
*/
void do_stack(struct mc_request *req)
{
- char *ptr = req->request.data;
- int pid_requested= -1;
- struct task_struct *from = NULL;
+ char *ptr = req->request.data;
+ int pid_requested= -1;
+ struct task_struct *from = NULL;
struct task_struct *to = NULL;
- /* Would be nice:
- * 1) Send showregs output to mconsole.
+ /* Would be nice:
+ * 1) Send showregs output to mconsole.
* 2) Add a way to stack dump all pids.
*/
- ptr += strlen("stack");
- while(isspace(*ptr)) ptr++;
-
- /* Should really check for multiple pids or reject bad args here */
- /* What do the arguments in mconsole_reply mean? */
- if(sscanf(ptr, "%d", &pid_requested) == 0){
- mconsole_reply(req, "Please specify a pid", 1, 0);
- return;
- }
+ ptr += strlen("stack");
+ while(isspace(*ptr)) ptr++;
- from = current;
- to = find_task_by_pid(pid_requested);
+ /* Should really check for multiple pids or reject bad args here */
+ /* What do the arguments in mconsole_reply mean? */
+ if(sscanf(ptr, "%d", &pid_requested) == 0){
+ mconsole_reply(req, "Please specify a pid", 1, 0);
+ return;
+ }
- if((to == NULL) || (pid_requested == 0)) {
- mconsole_reply(req, "Couldn't find that pid", 1, 0);
- return;
- }
- to->thread.saved_task = current;
+ from = current;
- switch_to(from, to, from);
- mconsole_reply(req, "Stack Dumped to console and message log", 0, 0);
+ to = find_task_by_pid(pid_requested);
+ if((to == NULL) || (pid_requested == 0)) {
+ mconsole_reply(req, "Couldn't find that pid", 1, 0);
+ return;
+ }
+ with_console(req, stack_proc, to);
}
void mconsole_stack(struct mc_request *req)
@@ -534,9 +619,9 @@ void mconsole_stack(struct mc_request *req)
/* Changed by mconsole_setup, which is __setup, and called before SMP is
* active.
*/
-static char *notify_socket = NULL;
+static char *notify_socket = NULL;
-int mconsole_init(void)
+static int mconsole_init(void)
{
/* long to avoid size mismatch warnings from gcc */
long sock;
@@ -563,16 +648,16 @@ int mconsole_init(void)
}
if(notify_socket != NULL){
- notify_socket = uml_strdup(notify_socket);
+ notify_socket = kstrdup(notify_socket, GFP_KERNEL);
if(notify_socket != NULL)
mconsole_notify(notify_socket, MCONSOLE_SOCKET,
- mconsole_socket_name,
+ mconsole_socket_name,
strlen(mconsole_socket_name) + 1);
else printk(KERN_ERR "mconsole_setup failed to strdup "
"string\n");
}
- printk("mconsole (version %d) initialized on %s\n",
+ printk("mconsole (version %d) initialized on %s\n",
MCONSOLE_VERSION, mconsole_socket_name);
return(0);
}
@@ -585,7 +670,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer,
char *buf;
buf = kmalloc(count + 1, GFP_KERNEL);
- if(buf == NULL)
+ if(buf == NULL)
return(-ENOMEM);
if(copy_from_user(buf, buffer, count)){
@@ -661,7 +746,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,
if(notify_socket == NULL) return(0);
- mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
+ mconsole_notify(notify_socket, MCONSOLE_PANIC, message,
strlen(message) + 1);
return(0);
}
@@ -686,14 +771,3 @@ char *mconsole_notify_socket(void)
}
EXPORT_SYMBOL(mconsole_notify_socket);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 310c1f823f26..4b109fe7fff8 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req)
return(1);
}
-int mconsole_reply(struct mc_request *req, char *str, int err, int more)
+int mconsole_reply_len(struct mc_request *req, const char *str, int total,
+ int err, int more)
{
struct mconsole_reply reply;
- int total, len, n;
+ int len, n;
- total = strlen(str);
do {
reply.err = err;
@@ -155,6 +155,12 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
return(0);
}
+int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
+{
+ return mconsole_reply_len(req, str, strlen(str), err, more);
+}
+
+
int mconsole_unlink_socket(void)
{
unlink(mconsole_socket_name);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 84c73a300acb..8ebb2241ad42 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -34,7 +34,7 @@
#define DRIVER_NAME "uml-netdev"
static DEFINE_SPINLOCK(opened_lock);
-LIST_HEAD(opened);
+static LIST_HEAD(opened);
static int uml_net_rx(struct net_device *dev)
{
@@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev)
return pkt_len;
}
+static void uml_dev_close(void* dev)
+{
+ dev_close( (struct net_device *) dev);
+}
+
irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
@@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_lock(&lp->lock);
while((err = uml_net_rx(dev)) > 0) ;
if(err < 0) {
+ DECLARE_WORK(close_work, uml_dev_close, dev);
printk(KERN_ERR
"Device '%s' read returned %d, shutting it down\n",
dev->name, err);
- dev_close(dev);
+ /* dev_close can't be called in interrupt context, and takes
+ * again lp->lock.
+ * And dev_close() can be safely called multiple times on the
+ * same device, since it tests for (dev->flags & IFF_UP). So
+ * there's no harm in delaying the device shutdown. */
+ schedule_work(&close_work);
goto out;
}
reactivate_fd(lp->fd, UM_ETH_IRQ);
- out:
+out:
spin_unlock(&lp->lock);
return(IRQ_HANDLED);
}
@@ -150,6 +161,7 @@ static int uml_net_close(struct net_device *dev)
if(lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
lp->fd = -1;
+ list_del(&lp->list);
spin_unlock(&lp->lock);
return 0;
@@ -266,7 +278,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
}
static DEFINE_SPINLOCK(devices_lock);
-static struct list_head devices = LIST_HEAD_INIT(devices);
+static LIST_HEAD(devices);
static struct platform_driver uml_net_driver = {
.driver = {
@@ -316,6 +328,11 @@ static int eth_configure(int n, void *init, char *mac,
return 1;
}
+ lp = dev->priv;
+ /* This points to the transport private data. It's still clear, but we
+ * must memset it to 0 *now*. Let's help the drivers. */
+ memset(lp, 0, size);
+
/* sysfs register */
if (!driver_registered) {
platform_driver_register(&uml_net_driver);
@@ -357,7 +374,6 @@ static int eth_configure(int n, void *init, char *mac,
free_netdev(dev);
return 1;
}
- lp = dev->priv;
/* lp.user is the first four bytes of the transport data, which
* has already been initialized. This structure assignment will
@@ -586,7 +602,7 @@ static int net_config(char *str)
err = eth_parse(str, &n, &str);
if(err) return(err);
- str = uml_strdup(str);
+ str = kstrdup(str, GFP_KERNEL);
if(str == NULL){
printk(KERN_ERR "net_config failed to strdup string\n");
return(-1);
@@ -715,6 +731,7 @@ static void close_devices(void)
list_for_each(ele, &opened){
lp = list_entry(ele, struct uml_net_private, list);
+ free_irq(lp->dev->irq, lp->dev);
if((lp->close != NULL) && (lp->fd >= 0))
(*lp->close)(lp->fd, &lp->user);
if(lp->remove != NULL) (*lp->remove)(&lp->user);
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 62e04ecfada8..a32ef55cb244 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -69,7 +69,7 @@ static struct line_driver driver = {
.name = "ssl",
.config = ssl_config,
.get_config = ssl_get_config,
- .id = line_id,
+ .id = line_id,
.remove = ssl_remove,
},
};
@@ -84,26 +84,23 @@ static struct lines lines = LINES_INIT(NR_PORTS);
static int ssl_config(char *str)
{
- return(line_config(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+ return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts);
}
static int ssl_get_config(char *dev, char *str, int size, char **error_out)
{
- return(line_get_config(dev, serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]),
- str, size, error_out));
+ return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str,
+ size, error_out);
}
static int ssl_remove(int n)
{
- return line_remove(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]), n);
+ return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n);
}
int ssl_open(struct tty_struct *tty, struct file *filp)
{
- return line_open(serial_lines, tty, &opts);
+ return line_open(serial_lines, tty);
}
#if 0
@@ -112,16 +109,6 @@ static void ssl_flush_buffer(struct tty_struct *tty)
return;
}
-static void ssl_throttle(struct tty_struct * tty)
-{
- printk(KERN_ERR "Someone should implement ssl_throttle\n");
-}
-
-static void ssl_unthrottle(struct tty_struct * tty)
-{
- printk(KERN_ERR "Someone should implement ssl_unthrottle\n");
-}
-
static void ssl_stop(struct tty_struct *tty)
{
printk(KERN_ERR "Someone should implement ssl_stop\n");
@@ -148,9 +135,9 @@ static struct tty_operations ssl_ops = {
.flush_chars = line_flush_chars,
.set_termios = line_set_termios,
.ioctl = line_ioctl,
+ .throttle = line_throttle,
+ .unthrottle = line_unthrottle,
#if 0
- .throttle = ssl_throttle,
- .unthrottle = ssl_unthrottle,
.stop = ssl_stop,
.start = ssl_start,
.hangup = ssl_hangup,
@@ -183,7 +170,7 @@ static int ssl_console_setup(struct console *co, char *options)
{
struct line *line = &serial_lines[co->index];
- return console_open_chan(line,co,&opts);
+ return console_open_chan(line, co, &opts);
}
static struct console ssl_cons = {
@@ -199,12 +186,13 @@ int ssl_init(void)
{
char *new_title;
- printk(KERN_INFO "Initializing software serial port version %d\n",
+ printk(KERN_INFO "Initializing software serial port version %d\n",
ssl_version);
ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops,
- serial_lines, ARRAY_SIZE(serial_lines));
+ serial_lines,
+ ARRAY_SIZE(serial_lines));
- lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]));
+ lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts);
new_title = add_xterm_umid(opts.xterm_title);
if (new_title != NULL)
@@ -212,7 +200,7 @@ int ssl_init(void)
ssl_init_done = 1;
register_console(&ssl_cons);
- return(0);
+ return 0;
}
late_initcall(ssl_init);
@@ -220,16 +208,13 @@ static void ssl_exit(void)
{
if (!ssl_init_done)
return;
- close_lines(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]));
+ close_lines(serial_lines, ARRAY_SIZE(serial_lines));
}
__uml_exitcall(ssl_exit);
static int ssl_chan_setup(char *str)
{
- return(line_setup(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]),
- str, 1));
+ return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str);
}
__setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 005aa6333b6e..61db8b2fc83f 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -75,7 +75,7 @@ static struct line_driver driver = {
.name = "con",
.config = con_config,
.get_config = con_get_config,
- .id = line_id,
+ .id = line_id,
.remove = con_remove,
},
};
@@ -86,28 +86,27 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS);
* individual elements are protected by individual semaphores.
*/
struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
- [ 1 ... MAX_TTYS - 1 ] =
+ [ 1 ... MAX_TTYS - 1 ] =
LINE_INIT(CONFIG_CON_CHAN, &driver) };
static int con_config(char *str)
{
- return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str));
+ return line_config(vts, ARRAY_SIZE(vts), str, &opts);
}
static int con_get_config(char *dev, char *str, int size, char **error_out)
{
- return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str,
- size, error_out));
+ return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out);
}
static int con_remove(int n)
{
- return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n);
+ return line_remove(vts, ARRAY_SIZE(vts), n);
}
static int con_open(struct tty_struct *tty, struct file *filp)
{
- return line_open(vts, tty, &opts);
+ return line_open(vts, tty);
}
static int con_init_done = 0;
@@ -117,16 +116,18 @@ static struct tty_operations console_ops = {
.close = line_close,
.write = line_write,
.put_char = line_put_char,
- .write_room = line_write_room,
+ .write_room = line_write_room,
.chars_in_buffer = line_chars_in_buffer,
.flush_buffer = line_flush_buffer,
.flush_chars = line_flush_chars,
.set_termios = line_set_termios,
.ioctl = line_ioctl,
+ .throttle = line_throttle,
+ .unthrottle = line_unthrottle,
};
static void uml_console_write(struct console *console, const char *string,
- unsigned len)
+ unsigned len)
{
struct line *line = &vts[console->index];
unsigned long flags;
@@ -146,7 +147,7 @@ static int uml_console_setup(struct console *co, char *options)
{
struct line *line = &vts[co->index];
- return console_open_chan(line,co,&opts);
+ return console_open_chan(line, co, &opts);
}
static struct console stdiocons = {
@@ -156,7 +157,7 @@ static struct console stdiocons = {
.setup = uml_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
- .data = &vts,
+ .data = &vts,
};
int stdio_init(void)
@@ -166,11 +167,11 @@ int stdio_init(void)
console_driver = line_register_devfs(&console_lines, &driver,
&console_ops, vts,
ARRAY_SIZE(vts));
- if (NULL == console_driver)
+ if (console_driver == NULL)
return -1;
printk(KERN_INFO "Initialized stdio console driver\n");
- lines_init(vts, sizeof(vts)/sizeof(vts[0]));
+ lines_init(vts, ARRAY_SIZE(vts), &opts);
new_title = add_xterm_umid(opts.xterm_title);
if(new_title != NULL)
@@ -178,7 +179,7 @@ int stdio_init(void)
con_init_done = 1;
register_console(&stdiocons);
- return(0);
+ return 0;
}
late_initcall(stdio_init);
@@ -186,13 +187,13 @@ static void console_exit(void)
{
if (!con_init_done)
return;
- close_lines(vts, sizeof(vts)/sizeof(vts[0]));
+ close_lines(vts, ARRAY_SIZE(vts));
}
__uml_exitcall(console_exit);
static int console_chan_setup(char *str)
{
- return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
+ return line_setup(vts, ARRAY_SIZE(vts), str);
}
__setup("con", console_chan_setup);
__channel_help(console_chan_setup, "con");
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93898917cbe5..101efd26d467 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -117,6 +117,7 @@ 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,
unsigned int cmd, unsigned long arg);
+static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
#define MAX_DEV (8)
@@ -125,6 +126,7 @@ static struct block_device_operations ubd_blops = {
.open = ubd_open,
.release = ubd_release,
.ioctl = ubd_ioctl,
+ .getgeo = ubd_getgeo,
};
/* Protected by the queue_lock */
@@ -706,7 +708,7 @@ static int ubd_config(char *str)
{
int n, err;
- str = uml_strdup(str);
+ str = kstrdup(str, GFP_KERNEL);
if(str == NULL){
printk(KERN_ERR "ubd_config failed to strdup string\n");
return(1);
@@ -1058,10 +1060,19 @@ static void do_ubd_request(request_queue_t *q)
}
}
+static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ubd *dev = bdev->bd_disk->private_data;
+
+ geo->heads = 128;
+ geo->sectors = 32;
+ geo->cylinders = dev->size / (128 * 32 * 512);
+ return 0;
+}
+
static int ubd_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
struct ubd *dev = inode->i_bdev->bd_disk->private_data;
struct hd_driveid ubd_id = {
.cyls = 0,
@@ -1070,16 +1081,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
};
switch (cmd) {
- struct hd_geometry g;
struct cdrom_volctrl volume;
- case HDIO_GETGEO:
- if(!loc) return(-EINVAL);
- g.heads = 128;
- g.sectors = 32;
- g.cylinders = dev->size / (128 * 32 * 512);
- g.start = get_start_sect(inode->i_bdev);
- return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
-
case HDIO_GET_IDENTITY:
ubd_id.cyls = dev->size / (128 * 32 * 512);
if(copy_to_user((char __user *) arg, (char *) &ubd_id,
@@ -1101,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
-static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
+static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow)
{
struct uml_stat buf1, buf2;
int err;
- if(from_cmdline == NULL) return(1);
- if(!strcmp(from_cmdline, from_cow)) return(1);
+ if(from_cmdline == NULL)
+ return 0;
+ if(!strcmp(from_cmdline, from_cow))
+ return 0;
err = os_stat_file(from_cmdline, &buf1);
if(err < 0){
printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
- return(1);
+ return 0;
}
err = os_stat_file(from_cow, &buf2);
if(err < 0){
printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
- return(1);
+ return 1;
}
if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
- return(1);
+ return 0;
printk("Backing file mismatch - \"%s\" requested,\n"
"\"%s\" specified in COW header of \"%s\"\n",
from_cmdline, from_cow, cow);
- return(0);
+ return 1;
}
static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
@@ -1187,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags,
unsigned long long size;
__u32 version, align;
char *backing_file;
- int fd, err, sectorsize, same, mode = 0644;
+ int fd, err, sectorsize, asked_switch, mode = 0644;
fd = os_open_file(file, *openflags, mode);
- if(fd < 0){
- if((fd == -ENOENT) && (create_cow_out != NULL))
+ if (fd < 0) {
+ if ((fd == -ENOENT) && (create_cow_out != NULL))
*create_cow_out = 1;
- if(!openflags->w ||
- ((fd != -EROFS) && (fd != -EACCES))) return(fd);
+ if (!openflags->w ||
+ ((fd != -EROFS) && (fd != -EACCES)))
+ return fd;
openflags->w = 0;
fd = os_open_file(file, *openflags, mode);
- if(fd < 0)
- return(fd);
+ if (fd < 0)
+ return fd;
}
err = os_lock_file(fd, openflags->w);
@@ -1207,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags,
goto out_close;
}
- if(backing_file_out == NULL) return(fd);
+ /* Succesful return case! */
+ if(backing_file_out == NULL)
+ return(fd);
err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
&size, &sectorsize, &align, bitmap_offset_out);
@@ -1216,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags,
"errno = %d\n", file, -err);
goto out_close;
}
- if(err) return(fd);
-
- if(backing_file_out == NULL) return(fd);
+ if(err)
+ return(fd);
- same = same_backing_files(*backing_file_out, backing_file, file);
+ asked_switch = path_requires_switch(*backing_file_out, backing_file, file);
- if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
+ /* Allow switching only if no mismatch. */
+ if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) {
printk("Switching backing file to '%s'\n", *backing_file_out);
err = write_cow_header(file, fd, *backing_file_out,
sectorsize, align, &size);
- if(err){
+ if (err) {
printk("Switch failed, errno = %d\n", -err);
- return(err);
+ goto out_close;
}
- }
- else {
+ } else {
*backing_file_out = backing_file;
err = backing_file_mismatch(*backing_file_out, size, mtime);
- if(err) goto out_close;
+ if (err)
+ goto out_close;
}
cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
bitmap_len_out, data_offset_out);
- return(fd);
+ return fd;
out_close:
os_close_file(fd);
- return(err);
+ return err;
}
int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
@@ -1387,15 +1394,6 @@ int io_thread(void *arg)
printk("io_thread - write failed, fd = %d, err = %d\n",
kernel_fd, -n);
}
-}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+ return 0;
+}
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index da9a6717e7a4..1bb5e9d94270 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -14,21 +14,23 @@
struct chan {
struct list_head list;
+ struct list_head free_list;
+ struct line *line;
char *dev;
unsigned int primary:1;
unsigned int input:1;
unsigned int output:1;
unsigned int opened:1;
+ unsigned int enabled:1;
int fd;
- enum chan_init_pri pri;
struct chan_ops *ops;
void *data;
};
extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
struct tty_struct *tty, int irq);
-extern int parse_chan_pair(char *str, struct list_head *chans, int pri,
- int device, struct chan_opts *opts);
+extern int parse_chan_pair(char *str, struct line *line, int device,
+ struct chan_opts *opts);
extern int open_chan(struct list_head *chans);
extern int write_chan(struct list_head *chans, const char *buf, int len,
int write_irq);
@@ -36,9 +38,11 @@ extern int console_write_chan(struct list_head *chans, const char *buf,
int len);
extern int console_open_chan(struct line *line, struct console *co,
struct chan_opts *opts);
-extern void close_chan(struct list_head *chans);
+extern void deactivate_chan(struct list_head *chans, int irq);
+extern void reactivate_chan(struct list_head *chans, int irq);
extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
-extern void enable_chan(struct list_head *chans, struct tty_struct *tty);
+extern void enable_chan(struct line *line);
+extern void close_chan(struct list_head *chans, int delay_free_irq);
extern int chan_window_size(struct list_head *chans,
unsigned short *rows_out,
unsigned short *cols_out);
@@ -47,14 +51,3 @@ extern int chan_config_string(struct list_head *chans, char *str, int size,
char **error_out);
#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/choose-mode.h b/arch/um/include/choose-mode.h
index f25fa83a5da6..b87b36a87d91 100644
--- a/arch/um/include/choose-mode.h
+++ b/arch/um/include/choose-mode.h
@@ -23,6 +23,9 @@ static inline void *__choose_mode(void *tt, void *skas) {
#elif defined(UML_CONFIG_MODE_TT)
#define CHOOSE_MODE(tt, skas) (tt)
+
+#else
+#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
#endif
#define CHOOSE_MODE_PROC(tt, skas, args...) \
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index f724b717213f..b61deb8b362a 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -18,19 +18,8 @@ extern int deactivate_all_fds(void);
extern void forward_interrupts(int pid);
extern void init_irq_signals(int on_sigstack);
extern void forward_ipi(int fd, int pid);
-extern void free_irq_later(int irq, void *dev_id);
extern int activate_ipi(int fd, int pid);
extern unsigned long irq_lock(void);
extern void irq_unlock(unsigned long flags);
-#endif
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 1e3170768b5c..7d223beccbc0 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -17,7 +17,7 @@ extern int errno;
extern int clone(int (*proc)(void *), void *sp, int flags, void *data);
extern int sleep(int);
-extern int printf(char *fmt, ...);
+extern int printf(const char *fmt, ...);
extern char *strerror(int errnum);
extern char *ptsname(int __fd);
extern int munmap(void *, int);
@@ -35,15 +35,6 @@ extern int read(unsigned int, char *, int);
extern int pipe(int *);
extern int sched_yield(void);
extern int ptrace(int op, int pid, long addr, long data);
+
#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/kern_util.h b/arch/um/include/kern_util.h
index e5fec5570199..c649108a9e9f 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -10,6 +10,19 @@
#include "sysdep/ptrace.h"
#include "sysdep/faultinfo.h"
+typedef void (*kern_hndl)(int, union uml_pt_regs *);
+
+struct kern_handlers {
+ kern_hndl relay_signal;
+ kern_hndl winch;
+ kern_hndl bus_handler;
+ kern_hndl page_fault;
+ kern_hndl sigio_handler;
+ kern_hndl timer_handler;
+};
+
+extern struct kern_handlers handlinfo_kern;
+
extern int ncpus;
extern char *linux_prog;
extern char *gdb_init;
@@ -51,8 +64,6 @@ extern void timer_handler(int sig, union uml_pt_regs *regs);
extern int set_signals(int enable);
extern void force_sigbus(void);
extern int pid_to_processor_id(int pid);
-extern void block_signals(void);
-extern void unblock_signals(void);
extern void deliver_signals(void *t);
extern int next_syscall_index(int max);
extern int next_trap_index(int max);
@@ -109,9 +120,13 @@ extern void machine_halt(void);
extern int is_syscall(unsigned long addr);
extern void arch_switch(void);
extern void free_irq(unsigned int, void *);
-extern int um_in_interrupt(void);
extern int cpu(void);
+/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
+extern int __cant_sleep(void);
+extern void segv_handler(int sig, union uml_pt_regs *regs);
+extern void sigio_handler(int sig, union uml_pt_regs *regs);
+
#endif
/*
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 5323d22a6ca7..6f4d680dc1d4 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -32,11 +32,13 @@ struct line_driver {
};
struct line {
+ struct tty_struct *tty;
char *init_str;
int init_pri;
struct list_head chan_list;
int valid;
int count;
+ int throttled;
/*This lock is actually, mostly, local to*/
spinlock_t lock;
@@ -58,14 +60,15 @@ struct line {
#define LINE_INIT(str, d) \
{ init_str : str, \
init_pri : INIT_STATIC, \
- chan_list : { }, \
valid : 1, \
+ throttled : 0, \
+ lock : SPIN_LOCK_UNLOCKED, \
buffer : NULL, \
head : NULL, \
tail : NULL, \
sigio : 0, \
- driver : d, \
- have_irq : 0 }
+ driver : d, \
+ have_irq : 0 }
struct lines {
int num;
@@ -74,11 +77,11 @@ struct lines {
#define LINES_INIT(n) { num : n }
extern void line_close(struct tty_struct *tty, struct file * filp);
-extern int line_open(struct line *lines, struct tty_struct *tty,
- struct chan_opts *opts);
-extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init,
- int all_allowed);
-extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len);
+extern int line_open(struct line *lines, struct tty_struct *tty);
+extern int line_setup(struct line *lines, unsigned int sizeof_lines,
+ char *init);
+extern int line_write(struct tty_struct *tty, const unsigned char *buf,
+ int len);
extern void line_put_char(struct tty_struct *tty, unsigned char ch);
extern void line_set_termios(struct tty_struct *tty, struct termios * old);
extern int line_chars_in_buffer(struct tty_struct *tty);
@@ -87,23 +90,27 @@ extern void line_flush_chars(struct tty_struct *tty);
extern int line_write_room(struct tty_struct *tty);
extern int line_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+extern void line_throttle(struct tty_struct *tty);
+extern void line_unthrottle(struct tty_struct *tty);
extern char *add_xterm_umid(char *base);
-extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty);
+extern int line_setup_irq(int fd, int input, int output, struct line *line,
+ void *data);
extern void line_close_chan(struct line *line);
-extern void line_disable(struct tty_struct *tty, int current_irq);
-extern struct tty_driver * line_register_devfs(struct lines *set,
- struct line_driver *line_driver,
+extern struct tty_driver * line_register_devfs(struct lines *set,
+ struct line_driver *line_driver,
struct tty_operations *driver,
struct line *lines,
int nlines);
-extern void lines_init(struct line *lines, int nlines);
+extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
extern void close_lines(struct line *lines, int nlines);
-extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_config(struct line *lines, unsigned int sizeof_lines,
+ char *str, struct chan_opts *opts);
extern int line_id(char **str, int *start_out, int *end_out);
extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
-extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
+extern int line_get_config(char *dev, struct line *lines,
+ unsigned int sizeof_lines, char *str,
int size, char **error_out);
#endif
diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h
new file mode 100644
index 000000000000..018b3819ab0b
--- /dev/null
+++ b/arch/um/include/longjmp.h
@@ -0,0 +1,19 @@
+#ifndef __UML_LONGJMP_H
+#define __UML_LONGJMP_H
+
+#include <setjmp.h>
+#include "os.h"
+
+#define UML_SIGLONGJMP(buf, val) do { \
+ longjmp(*buf, val); \
+} while(0)
+
+#define UML_SIGSETJMP(buf, enable) ({ \
+ int n; \
+ enable = get_signals(); \
+ n = setjmp(*buf); \
+ if(n != 0) \
+ set_signals(enable); \
+ n; })
+
+#endif
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index b1b512f47035..58f67d391105 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -32,7 +32,7 @@ struct mconsole_reply {
struct mconsole_notify {
u32 magic;
- u32 version;
+ u32 version;
enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG,
MCONSOLE_USER_NOTIFY } type;
u32 len;
@@ -66,7 +66,9 @@ struct mc_request
extern char mconsole_socket_name[];
extern int mconsole_unlink_socket(void);
-extern int mconsole_reply(struct mc_request *req, char *reply, int err,
+extern int mconsole_reply_len(struct mc_request *req, const char *reply,
+ int len, int err, int more);
+extern int mconsole_reply(struct mc_request *req, const char *str, int err,
int more);
extern void mconsole_version(struct mc_request *req);
@@ -84,7 +86,7 @@ extern void mconsole_proc(struct mc_request *req);
extern void mconsole_stack(struct mc_request *req);
extern int mconsole_get_request(int fd, struct mc_request *req);
-extern int mconsole_notify(char *sock_name, int type, const void *data,
+extern int mconsole_notify(char *sock_name, int type, const void *data,
int len);
extern char *mconsole_notify_socket(void);
extern void lock_notify(void);
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
index 2d88afd0cf16..e7539a8451ef 100644
--- a/arch/um/include/mode_kern.h
+++ b/arch/um/include/mode_kern.h
@@ -9,22 +9,11 @@
#include "linux/config.h"
#ifdef CONFIG_MODE_TT
-#include "mode_kern-tt.h"
+#include "mode_kern_tt.h"
#endif
#ifdef CONFIG_MODE_SKAS
-#include "mode_kern-skas.h"
+#include "mode_kern_skas.h"
#endif
#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/os.h b/arch/um/include/os.h
index 2cccfa5b8ab5..eb1710b81255 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -9,6 +9,9 @@
#include "uml-config.h"
#include "asm/types.h"
#include "../os/include/file.h"
+#include "sysdep/ptrace.h"
+#include "kern_util.h"
+#include "skas/mm_id.h"
#define OS_TYPE_FILE 1
#define OS_TYPE_DIR 2
@@ -188,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
extern 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 stop(void);
+extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern int protect_memory(unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern void forward_pending_sigio(int target);
@@ -213,15 +217,78 @@ extern int run_helper_thread(int (*proc)(void *), void *arg,
int stack_order);
extern int helper_wait(int pid);
-#endif
+/* umid.c */
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+extern int umid_file_name(char *name, char *buf, int len);
+extern int set_umid(char *name);
+extern char *get_umid(void);
+
+/* signal.c */
+extern void set_sigstack(void *sig_stack, int size);
+extern void remove_sigstack(void);
+extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern int change_sig(int signal, int on);
+extern void block_signals(void);
+extern void unblock_signals(void);
+extern int get_signals(void);
+extern int set_signals(int enable);
+extern void os_usr1_signal(int on);
+
+/* trap.c */
+extern void os_fill_handlinfo(struct kern_handlers h);
+extern void do_longjmp(void *p, int val);
+
+/* util.c */
+extern void stack_protections(unsigned long address);
+extern void task_protections(unsigned long address);
+extern int raw(int fd);
+extern void setup_machinename(char *machine_out);
+extern void setup_hostinfo(void);
+extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
+
+/* time.c */
+#define BILLION (1000 * 1000 * 1000)
+
+extern void switch_timers(int to_real);
+extern void idle_sleep(int secs);
+extern void enable_timer(void);
+extern void disable_timer(void);
+extern void user_time_init(void);
+extern void uml_idle_timer(void);
+extern unsigned long long os_nsecs(void);
+
+/* skas/mem.c */
+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);
+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, int done,
+ void **data);
+
+/* skas/process.c */
+extern int is_skas_winch(int pid, int fd, void *data);
+extern int start_userspace(unsigned long stub_stack);
+extern int copy_context_skas0(unsigned long stack, int pid);
+extern void userspace(union uml_pt_regs *regs);
+extern void map_stub_pages(int fd, unsigned long code,
+ unsigned long data, unsigned long stack);
+extern void new_thread(void *stack, void **switch_buf_ptr,
+ void **fork_buf_ptr, void (*handler)(int));
+extern void thread_wait(void *sw, void *fb);
+extern void switch_threads(void *me, void *next);
+extern int start_idle_thread(void *stack, void *switch_buf_ptr,
+ void **fork_buf_ptr);
+extern void initial_thread_cb_skas(void (*proc)(void *),
+ void *arg);
+extern void halt_skas(void);
+extern void reboot_skas(void);
+
+#endif
diff --git a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h
deleted file mode 100644
index b075e543d864..000000000000
--- a/arch/um/include/signal_user.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SIGNAL_USER_H__
-#define __SIGNAL_USER_H__
-
-extern int signal_stack_size;
-
-extern int change_sig(int signal, int on);
-extern void set_sigstack(void *stack, int size);
-extern void set_handler(int sig, void (*handler)(int), int flags, ...);
-extern int set_signals(int enable);
-extern int get_signals(void);
-
-#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/mm_id.h b/arch/um/include/skas/mm_id.h
index 48dd0989ddaa..48dd0989ddaa 100644
--- a/arch/um/kernel/skas/include/mm_id.h
+++ b/arch/um/include/skas/mm_id.h
diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h
new file mode 100644
index 000000000000..d8869a6ef1b4
--- /dev/null
+++ b/arch/um/include/skas/mmu-skas.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_MMU_H
+#define __SKAS_MMU_H
+
+#include "linux/config.h"
+#include "mm_id.h"
+#include "asm/ldt.h"
+
+struct mmu_context_skas {
+ struct mm_id id;
+ unsigned long last_page_table;
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ unsigned long last_pmd;
+#endif
+ uml_ldt_t ldt;
+};
+
+extern void switch_mm_skas(struct mm_id * mm_idp);
+
+#endif
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
new file mode 100644
index 000000000000..260065cfeef1
--- /dev/null
+++ b/arch/um/include/skas/mode-skas.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_SKAS_H__
+#define __MODE_SKAS_H__
+
+#include <sysdep/ptrace.h>
+
+extern unsigned long exec_regs[];
+extern unsigned long exec_fp_regs[];
+extern unsigned long exec_fpx_regs[];
+extern int have_fpx_regs;
+
+extern void sig_handler_common_skas(int sig, void *sc_ptr);
+extern void kill_off_processes_skas(void);
+
+#endif
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h
index c97a80dfe370..63c58739bde0 100644
--- a/arch/um/kernel/skas/include/mode_kern-skas.h
+++ b/arch/um/include/skas/mode_kern_skas.h
@@ -18,7 +18,6 @@ extern int copy_thread_skas(int nr, unsigned long clone_flags,
unsigned long sp, unsigned long stack_top,
struct task_struct *p, struct pt_regs *regs);
extern void release_thread_skas(struct task_struct *task);
-extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
extern void init_idle_skas(void);
extern void flush_tlb_kernel_range_skas(unsigned long start,
unsigned long end);
@@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task);
#define kmem_end_skas (host_task_size - 1024 * 1024)
#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/proc_mm.h b/arch/um/include/skas/proc_mm.h
index cce61a679052..902809209603 100644
--- a/arch/um/kernel/skas/include/proc_mm.h
+++ b/arch/um/include/skas/proc_mm.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -22,13 +22,13 @@ struct mm_mmap {
struct mm_munmap {
unsigned long addr;
- unsigned long len;
+ unsigned long len;
};
struct mm_mprotect {
unsigned long addr;
unsigned long len;
- unsigned int prot;
+ unsigned int prot;
};
struct proc_mm_op {
@@ -42,14 +42,3 @@ struct proc_mm_op {
};
#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/skas/skas.h b/arch/um/include/skas/skas.h
new file mode 100644
index 000000000000..86357282d681
--- /dev/null
+++ b/arch/um/include/skas/skas.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_H
+#define __SKAS_H
+
+#include "mm_id.h"
+#include "sysdep/ptrace.h"
+
+extern int userspace_pid[];
+extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
+extern int skas_needs_stub;
+
+extern int user_thread(unsigned long stack, int flags);
+extern void new_thread_proc(void *stack, void (*handler)(int sig));
+extern void new_thread_handler(int sig);
+extern void handle_syscall(union uml_pt_regs *regs);
+extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
+extern int new_mm(unsigned long stack);
+extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
+extern long execute_syscall_skas(void *r);
+extern unsigned long current_stub_stack(void);
+
+#endif
diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h
index f6ed92c3727d..f6ed92c3727d 100644
--- a/arch/um/kernel/skas/include/stub-data.h
+++ b/arch/um/include/skas/stub-data.h
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h
index 64516c556cdf..224a75f4c025 100644
--- a/arch/um/kernel/skas/include/uaccess-skas.h
+++ b/arch/um/include/skas/uaccess-skas.h
@@ -19,14 +19,3 @@ extern int clear_user_skas(void __user *mem, int len);
extern int strnlen_user_skas(const void __user *str, int len);
#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/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index 764ba4db4788..7d3d202d7fff 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -36,7 +36,7 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
int len, int sum)
{
memcpy(dst, src, len);
- return(csum_partial(dst, len, sum));
+ return csum_partial(dst, len, sum);
}
/*
@@ -104,7 +104,7 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
- return(sum);
+ return sum;
}
/*
diff --git a/arch/um/sys-i386/kernel-offsets.c b/arch/um/include/sysdep-i386/kernel-offsets.h
index 35db85057506..82f96c574144 100644
--- a/arch/um/sys-i386/kernel-offsets.c
+++ b/arch/um/include/sysdep-i386/kernel-offsets.h
@@ -1,12 +1,9 @@
-#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/sched.h>
-#include <linux/time.h>
#include <linux/elf.h>
-#include <asm/page.h>
#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define STR(x) #x
#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
diff --git a/arch/um/sys-x86_64/kernel-offsets.c b/arch/um/include/sysdep-x86_64/kernel-offsets.h
index bfcb104b846e..5ce93abd0b54 100644
--- a/arch/um/sys-x86_64/kernel-offsets.c
+++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
@@ -6,7 +6,7 @@
#include <asm/page.h>
#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define DEFINE_STR1(x) #x
#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : )
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
deleted file mode 100644
index 17d7ef2141f4..000000000000
--- a/arch/um/include/time_user.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TIME_USER_H__
-#define __TIME_USER_H__
-
-extern void timer(void);
-extern void switch_timers(int to_real);
-extern void idle_sleep(int secs);
-extern void enable_timer(void);
-extern void prepare_timer(void * ptr);
-extern void disable_timer(void);
-extern unsigned long time_lock(void);
-extern void time_unlock(unsigned long);
-extern void user_time_init(void);
-
-#endif
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h
index 738435461e13..9778fa838296 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/include/tt/debug.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and
* Lars Brinkhoff.
* Licensed under the GPL
diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h
new file mode 100644
index 000000000000..572a78b22587
--- /dev/null
+++ b/arch/um/include/tt/mmu-tt.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MMU_H
+#define __TT_MMU_H
+
+struct mmu_context_tt {
+};
+
+#endif
diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h
new file mode 100644
index 000000000000..2823cd56eea2
--- /dev/null
+++ b/arch/um/include/tt/mode-tt.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_TT_H__
+#define __MODE_TT_H__
+
+#include "sysdep/ptrace.h"
+
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
+extern int tracing_pid;
+
+extern int tracer(int (*init_proc)(void *), void *sp);
+extern void sig_handler_common_tt(int sig, void *sc);
+extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
+extern void reboot_tt(void);
+extern void halt_tt(void);
+extern int is_tracer_winch(int pid, int fd, void *data);
+extern void kill_off_processes_tt(void);
+
+#endif
diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h
new file mode 100644
index 000000000000..efa0012550d0
--- /dev/null
+++ b/arch/um/include/tt/mode_kern_tt.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MODE_KERN_H__
+#define __TT_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+
+extern void switch_to_tt(void *prev, void *next);
+extern void flush_thread_tt(void);
+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp);
+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct *p,
+ struct pt_regs *regs);
+extern void release_thread_tt(struct task_struct *task);
+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
+extern void init_idle_tt(void);
+extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_vm_tt(void);
+extern void __flush_tlb_one_tt(unsigned long addr);
+extern void flush_tlb_range_tt(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_mm_tt(struct mm_struct *mm);
+extern void force_flush_all_tt(void);
+extern long execute_syscall_tt(void *r);
+extern void before_mem_tt(unsigned long brk_start);
+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out);
+extern int start_uml_tt(void);
+extern int external_pid_tt(struct task_struct *task);
+extern int thread_pid_tt(struct task_struct *task);
+
+#define kmem_end_tt (host_task_size - ABOVE_KMEM)
+
+#endif
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h
index c667b67af405..808521980186 100644
--- a/arch/um/kernel/tt/include/tt.h
+++ b/arch/um/include/tt/tt.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r);
#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/tt/include/uaccess-tt.h b/arch/um/include/tt/uaccess-tt.h
index b9bfe9c481c4..b19645f32f24 100644
--- a/arch/um/kernel/tt/include/uaccess-tt.h
+++ b/arch/um/include/tt/uaccess-tt.h
@@ -46,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len);
extern int strnlen_user_tt(const void __user *str, int len);
#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/user.h b/arch/um/include/user.h
index 0f865ef46918..91b0ac4ad88c 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -18,6 +18,7 @@ extern int open_gdb_chan(void);
extern unsigned long strlcpy(char *, const char *, unsigned long);
extern unsigned long strlcat(char *, const char *, unsigned long);
extern void *um_vmalloc(int size);
+extern void *um_vmalloc_atomic(int size);
extern void vfree(void *ptr);
#endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index bb505e01d994..a6f1f176cf84 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -23,12 +23,7 @@ struct cpu_task {
extern struct cpu_task cpu_tasks[];
-struct signal_info {
- void (*handler)(int, union uml_pt_regs *);
- int is_irq;
-};
-
-extern struct signal_info sig_info[];
+extern void (*sig_info[])(int, union uml_pt_regs *);
extern unsigned long low_physmem;
extern unsigned long high_physmem;
@@ -49,10 +44,6 @@ extern unsigned long brk_start;
extern int pty_output_sigio;
extern int pty_close_sigio;
-extern void stop(void);
-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 linux_main(int argc, char **argv);
extern void set_cmdline(char *cmd);
@@ -60,12 +51,8 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
extern int get_pty(void);
extern void *um_kmalloc(int size);
extern int switcheroo(int fd, int prot, void *from, void *to, int size);
-extern void setup_machinename(char *machine_out);
-extern void setup_hostinfo(void);
extern void do_exec(int old_pid, int new_pid);
extern void tracer_panic(char *msg, ...);
-extern char *get_umid(int only_if_set);
-extern void do_longjmp(void *p, int val);
extern int detach(int pid, int sig);
extern int attach(int pid);
extern void kill_child_dead(int pid);
@@ -77,18 +64,6 @@ 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 arch_init_thread(void);
-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
extern int raw(int fd);
#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/Makefile b/arch/um/kernel/Makefile
index 3de9d21e36bf..693018ba80f1 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -9,9 +9,8 @@ clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
- signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
- time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
- umid.o user_util.o
+ signal_kern.o smp.o syscall_kern.o sysrq.o \
+ time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
@@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o
+USER_OBJS := $(user-objs-y) config.o tty_log.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c
index c13a64a288f6..91ea538e1612 100644
--- a/arch/um/kernel/asm-offsets.c
+++ b/arch/um/kernel/asm-offsets.c
@@ -1 +1 @@
-/* Dummy file to make kbuild happy - unused! */
+#include "sysdep/kernel-offsets.h"
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index efd222ffe20e..569fe8b9b053 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -17,7 +17,6 @@
#include "irq_user.h"
#include "tlb.h"
#include "os.h"
-#include "time_user.h"
#include "choose-mode.h"
#include "mode_kern.h"
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..0e32f5f4a887 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -15,7 +15,6 @@
#include "kern_util.h"
#include "user.h"
#include "process.h"
-#include "signal_user.h"
#include "sigio.h"
#include "irq_user.h"
#include "os.h"
@@ -29,7 +28,6 @@ struct irq_fd {
int pid;
int events;
int current_events;
- int freed;
};
static struct irq_fd *active_fds = NULL;
@@ -41,9 +39,11 @@ static int pollfds_size = 0;
extern int io_count, intr_count;
+extern void free_irqs(void);
+
void sigio_handler(int sig, union uml_pt_regs *regs)
{
- struct irq_fd *irq_fd, *next;
+ struct irq_fd *irq_fd;
int i, n;
if(smp_sigio_handler()) return;
@@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
irq_fd = irq_fd->next;
}
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){
- next = irq_fd->next;
+ for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
if(irq_fd->current_events != 0){
irq_fd->current_events = 0;
do_IRQ(irq_fd->irq, regs);
-
- /* This is here because the next irq may be
- * freed in the handler. If a console goes
- * away, both the read and write irqs will be
- * freed. After do_IRQ, ->next will point to
- * a good IRQ.
- * Irqs can't be freed inside their handlers,
- * so the next best thing is to have them
- * marked as needing freeing, so that they
- * can be freed here.
- */
- next = irq_fd->next;
- if(irq_fd->freed){
- free_irq(irq_fd->irq, irq_fd->id);
- }
}
}
}
+
+ free_irqs();
}
int activate_ipi(int fd, int pid)
@@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
.irq = irq,
.pid = pid,
.events = events,
- .current_events = 0,
- .freed = 0 } );
+ .current_events = 0 } );
/* Critical section - locked by a spinlock because this stuff can
* be changed from interrupt handlers. The stuff above is done
@@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
return(irq);
}
-void free_irq_later(int irq, void *dev_id)
-{
- struct irq_fd *irq_fd;
- unsigned long flags;
-
- flags = irq_lock();
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
- break;
- }
- if(irq_fd == NULL){
- printk("free_irq_later found no irq, irq = %d, "
- "dev_id = 0x%p\n", irq, dev_id);
- goto out;
- }
- irq_fd->freed = 1;
- out:
- irq_unlock(flags);
-}
-
void reactivate_fd(int fd, int irqnum)
{
struct irq_fd *irq;
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 34b54a3e2132..3113cab8675e 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -36,11 +36,9 @@
#include "kern_util.h"
#include "kern.h"
#include "signal_kern.h"
-#include "signal_user.h"
#include "init.h"
#include "irq_user.h"
#include "mem_user.h"
-#include "time_user.h"
#include "tlb.h"
#include "frame_kern.h"
#include "sigcontext.h"
@@ -108,7 +106,7 @@ void set_current(void *t)
{
struct task_struct *task = t;
- cpu_tasks[task->thread_info->cpu] = ((struct cpu_task)
+ cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
{ external_pid(task), task });
}
@@ -289,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt);
void *um_kmalloc(int size)
{
- return(kmalloc(size, GFP_KERNEL));
+ return kmalloc(size, GFP_KERNEL);
}
void *um_kmalloc_atomic(int size)
{
- return(kmalloc(size, GFP_ATOMIC));
+ return kmalloc(size, GFP_ATOMIC);
}
void *um_vmalloc(int size)
{
- return(vmalloc(size));
+ return vmalloc(size);
+}
+
+void *um_vmalloc_atomic(int size)
+{
+ return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
+}
+
+int __cant_sleep(void) {
+ return in_atomic() || irqs_disabled() || in_interrupt();
+ /* Is in_interrupt() really needed? */
}
unsigned long get_fault_addr(void)
@@ -324,10 +332,6 @@ int user_context(unsigned long sp)
return(stack != (unsigned long) current_thread);
}
-extern void remove_umid_dir(void);
-
-__uml_exitcall(remove_umid_dir);
-
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
void do_uml_exitcalls(void)
@@ -375,11 +379,6 @@ int smp_sigio_handler(void)
return(0);
}
-int um_in_interrupt(void)
-{
- return(in_interrupt());
-}
-
int cpu(void)
{
return(current_thread->cpu);
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index a637e885c583..6f1a3a288117 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -12,6 +12,8 @@
#include "mode.h"
#include "choose-mode.h"
+void (*pm_power_off)(void);
+
#ifdef CONFIG_SMP
static void kill_idlers(int me)
{
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 48b1f644b9a6..f7b18e157d35 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused)
"err = %d\n", -n);
}
}
+
+ return 0;
}
static int need_poll(int n)
@@ -335,70 +337,103 @@ int ignore_sigio_fd(int fd)
return(err);
}
-static int setup_initial_poll(int fd)
+static struct pollfd* setup_initial_poll(int fd)
{
struct pollfd *p;
- p = um_kmalloc_atomic(sizeof(struct pollfd));
- if(p == NULL){
+ p = um_kmalloc(sizeof(struct pollfd));
+ if (p == NULL) {
printk("setup_initial_poll : failed to allocate poll\n");
- return(-1);
+ return NULL;
}
*p = ((struct pollfd) { .fd = fd,
.events = POLLIN,
.revents = 0 });
- current_poll = ((struct pollfds) { .poll = p,
- .used = 1,
- .size = 1 });
- return(0);
+ return p;
}
void write_sigio_workaround(void)
{
unsigned long stack;
+ struct pollfd *p;
int err;
+ int l_write_sigio_fds[2];
+ int l_sigio_private[2];
+ int l_write_sigio_pid;
+ /* We call this *tons* of times - and most ones we must just fail. */
sigio_lock();
- if(write_sigio_pid != -1)
- goto out;
+ l_write_sigio_pid = write_sigio_pid;
+ sigio_unlock();
+
+ if (l_write_sigio_pid != -1)
+ return;
- err = os_pipe(write_sigio_fds, 1, 1);
+ err = os_pipe(l_write_sigio_fds, 1, 1);
if(err < 0){
printk("write_sigio_workaround - os_pipe 1 failed, "
"err = %d\n", -err);
- goto out;
+ return;
}
- err = os_pipe(sigio_private, 1, 1);
+ err = os_pipe(l_sigio_private, 1, 1);
if(err < 0){
- printk("write_sigio_workaround - os_pipe 2 failed, "
+ printk("write_sigio_workaround - os_pipe 1 failed, "
"err = %d\n", -err);
goto out_close1;
}
- if(setup_initial_poll(sigio_private[1]))
+
+ p = setup_initial_poll(l_sigio_private[1]);
+ if(!p)
goto out_close2;
- write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
+ sigio_lock();
+
+ /* Did we race? Don't try to optimize this, please, it's not so likely
+ * to happen, and no more than once at the boot. */
+ if(write_sigio_pid != -1)
+ goto out_unlock;
+
+ write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
CLONE_FILES | CLONE_VM, &stack, 0);
- if(write_sigio_pid < 0) goto out_close2;
+ if (write_sigio_pid < 0)
+ goto out_clear;
- if(write_sigio_irq(write_sigio_fds[0]))
+ if (write_sigio_irq(l_write_sigio_fds[0]))
goto out_kill;
- out:
+ /* Success, finally. */
+ memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
+ memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
+
+ current_poll = ((struct pollfds) { .poll = p,
+ .used = 1,
+ .size = 1 });
+
sigio_unlock();
return;
out_kill:
- os_kill_process(write_sigio_pid, 1);
+ l_write_sigio_pid = write_sigio_pid;
+ write_sigio_pid = -1;
+ sigio_unlock();
+ /* Going to call waitpid, avoid holding the lock. */
+ os_kill_process(l_write_sigio_pid, 1);
+ goto out_free;
+
+ out_clear:
write_sigio_pid = -1;
+ out_unlock:
+ sigio_unlock();
+ out_free:
+ kfree(p);
out_close2:
- os_close_file(sigio_private[0]);
- os_close_file(sigio_private[1]);
+ os_close_file(l_sigio_private[0]);
+ os_close_file(l_sigio_private[1]);
out_close1:
- os_close_file(write_sigio_fds[0]);
- os_close_file(write_sigio_fds[1]);
- sigio_unlock();
+ os_close_file(l_write_sigio_fds[0]);
+ os_close_file(l_write_sigio_fds[1]);
+ return;
}
int read_sigio_fd(int fd)
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 03618bd13d55..da17b7541e08 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -22,7 +22,6 @@
#include "asm/ucontext.h"
#include "kern_util.h"
#include "signal_kern.h"
-#include "signal_user.h"
#include "kern.h"
#include "frame_kern.h"
#include "sigcontext.h"
@@ -100,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
return err;
}
-static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
+static int kern_do_signal(struct pt_regs *regs)
{
struct k_sigaction ka_copy;
siginfo_t info;
+ sigset_t *oldset;
int sig, handled_sig = 0;
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
+ oldset = &current->blocked;
+
while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){
handled_sig = 1;
/* Whee! Actually deliver the signal. */
- if(!handle_signal(regs, sig, &ka_copy, &info, oldset))
+ if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
break;
+ }
}
/* Did we come from a system call? */
if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){
/* Restart the system call - no handlers present */
- if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND ||
- PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS ||
- PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){
+ switch(PT_REGS_SYSCALL_RET(regs)){
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
PT_REGS_RESTART_SYSCALL(regs);
- }
- else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
+ break;
+ case -ERESTART_RESTARTBLOCK:
PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
PT_REGS_RESTART_SYSCALL(regs);
+ break;
}
}
@@ -138,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset)
if(current->ptrace & PT_DTRACE)
current->thread.singlestep_syscall =
is_syscall(PT_REGS_IP(&current->thread.regs));
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+ }
return(handled_sig);
}
int do_signal(void)
{
- return(kern_do_signal(&current->thread.regs, &current->blocked));
+ return(kern_do_signal(&current->thread.regs));
}
/*
@@ -151,63 +172,20 @@ int do_signal(void)
*/
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if(kern_do_signal(&current->thread.regs, &saveset))
- return(-EINTR);
- }
-}
-
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
-{
- sigset_t saveset, newset;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
-
- PT_REGS_SYSCALL_RET(&current->thread.regs) = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (kern_do_signal(&current->thread.regs, &saveset))
- return(-EINTR);
- }
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
}
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
{
return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
}
-
-/*
- * 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/signal_user.c b/arch/um/kernel/signal_user.c
deleted file mode 100644
index 62f457835fb1..000000000000
--- a/arch/um/kernel/signal_user.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/mman.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "signal_user.h"
-#include "signal_kern.h"
-#include "sysdep/sigcontext.h"
-#include "sigcontext.h"
-
-void set_sigstack(void *sig_stack, int size)
-{
- stack_t stack = ((stack_t) { .ss_flags = 0,
- .ss_sp = (__ptr_t) sig_stack,
- .ss_size = size - sizeof(void *) });
-
- if(sigaltstack(&stack, NULL) != 0)
- panic("enabling signal stack failed, errno = %d\n", errno);
-}
-
-void set_handler(int sig, void (*handler)(int), int flags, ...)
-{
- struct sigaction action;
- va_list ap;
- int mask;
-
- va_start(ap, flags);
- action.sa_handler = handler;
- sigemptyset(&action.sa_mask);
- while((mask = va_arg(ap, int)) != -1){
- sigaddset(&action.sa_mask, mask);
- }
- va_end(ap);
- action.sa_flags = flags;
- action.sa_restorer = NULL;
- if(sigaction(sig, &action, NULL) < 0)
- panic("sigaction failed");
-}
-
-int change_sig(int signal, int on)
-{
- sigset_t sigset, old;
-
- sigemptyset(&sigset);
- sigaddset(&sigset, signal);
- sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
- return(!sigismember(&old, signal));
-}
-
-/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
- * disable profiling; it's safe because the profiling code does not interact
- * with the kernel code at all.*/
-
-static void change_signals(int type)
-{
- sigset_t mask;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGVTALRM);
- sigaddset(&mask, SIGALRM);
- sigaddset(&mask, SIGIO);
- if(sigprocmask(type, &mask, NULL) < 0)
- panic("Failed to change signal mask - errno = %d", errno);
-}
-
-void block_signals(void)
-{
- change_signals(SIG_BLOCK);
-}
-
-void unblock_signals(void)
-{
- change_signals(SIG_UNBLOCK);
-}
-
-/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
- * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
- * be able to profile all of UML, not just the non-critical sections. If
- * profiling is not thread-safe, then that is not my problem. We can disable
- * profiling when SMP is enabled in that case.
- */
-#define SIGIO_BIT 0
-#define SIGVTALRM_BIT 1
-
-static int enable_mask(sigset_t *mask)
-{
- int sigs;
-
- sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT;
- sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT;
- sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT;
- return(sigs);
-}
-
-int get_signals(void)
-{
- sigset_t mask;
-
- if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
- panic("Failed to get signal mask");
- return(enable_mask(&mask));
-}
-
-int set_signals(int enable)
-{
- sigset_t mask;
- int ret;
-
- sigemptyset(&mask);
- if(enable & (1 << SIGIO_BIT))
- sigaddset(&mask, SIGIO);
- if(enable & (1 << SIGVTALRM_BIT)){
- sigaddset(&mask, SIGVTALRM);
- sigaddset(&mask, SIGALRM);
- }
-
- /* This is safe - sigprocmask is guaranteed to copy locally the
- * value of new_set, do his work and then, at the end, write to
- * old_set.
- */
- if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
- panic("Failed to enable signals");
- ret = enable_mask(&mask);
- sigemptyset(&mask);
- if((enable & (1 << SIGIO_BIT)) == 0)
- sigaddset(&mask, SIGIO);
- if((enable & (1 << SIGVTALRM_BIT)) == 0){
- sigaddset(&mask, SIGVTALRM);
- sigaddset(&mask, SIGALRM);
- }
- if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
- panic("Failed to block signals");
-
- 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/skas/Makefile b/arch/um/kernel/skas/Makefile
index 8de471b59c1c..57181a920d48 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -1,12 +1,12 @@
-#
+#
# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
# Licensed under the GPL
#
-obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
- syscall.o tlb.o trap_user.o uaccess.o
+obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
+ syscall.o tlb.o uaccess.o
-USER_OBJS := process.o clone.o
+USER_OBJS := clone.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
deleted file mode 100644
index 44110c521e49..000000000000
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_MMU_H
-#define __SKAS_MMU_H
-
-#include "linux/config.h"
-#include "mm_id.h"
-#include "asm/ldt.h"
-
-struct mmu_context_skas {
- struct mm_id id;
- unsigned long last_page_table;
-#ifdef CONFIG_3_LEVEL_PGTABLES
- unsigned long last_pmd;
-#endif
- uml_ldt_t ldt;
-};
-
-extern void switch_mm_skas(struct mm_id * mm_idp);
-
-#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/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
deleted file mode 100644
index bcd26a6a3888..000000000000
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __MODE_SKAS_H__
-#define __MODE_SKAS_H__
-
-#include <sysdep/ptrace.h>
-
-extern unsigned long exec_regs[];
-extern unsigned long exec_fp_regs[];
-extern unsigned long exec_fpx_regs[];
-extern int have_fpx_regs;
-
-extern void sig_handler_common_skas(int sig, void *sc_ptr);
-extern void halt_skas(void);
-extern void reboot_skas(void);
-extern void kill_off_processes_skas(void);
-extern int is_skas_winch(int pid, int fd, void *data);
-
-#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/skas.h b/arch/um/kernel/skas/include/skas.h
deleted file mode 100644
index daa2f85b684c..000000000000
--- a/arch/um/kernel/skas/include/skas.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __SKAS_H
-#define __SKAS_H
-
-#include "mm_id.h"
-#include "sysdep/ptrace.h"
-
-extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
-extern int skas_needs_stub;
-
-extern void switch_threads(void *me, void *next);
-extern void thread_wait(void *sw, void *fb);
-extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
- void (*handler)(int));
-extern int start_idle_thread(void *stack, void *switch_buf_ptr,
- void **fork_buf_ptr);
-extern int user_thread(unsigned long stack, int flags);
-extern void userspace(union uml_pt_regs *regs);
-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, 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, int done,
- void **data);
-extern void user_signal(int sig, union uml_pt_regs *regs, int pid);
-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
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 677871f1b37c..c5c9885a8297 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
struct mmu_context_skas *from_mm = NULL;
struct mmu_context_skas *to_mm = &mm->context.skas;
unsigned long stack = 0;
- int from_fd, ret = -ENOMEM;
+ int ret = -ENOMEM;
if(skas_needs_stub){
stack = get_zeroed_page(GFP_KERNEL);
@@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
from_mm = &current->mm->context.skas;
if(proc_mm){
- if(from_mm)
- from_fd = from_mm->id.u.mm_fd;
- else from_fd = -1;
-
- ret = new_mm(from_fd, stack);
+ ret = new_mm(stack);
if(ret < 0){
printk("init_new_context_skas - new_mm failed, "
"errno = %d\n", ret);
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 599d679bd4fc..eea1c9c4bb0f 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -18,7 +18,6 @@
#include <asm/types.h>
#include "user.h"
#include "ptrace_user.h"
-#include "time_user.h"
#include "sysdep/ptrace.h"
#include "user_util.h"
#include "kern_util.h"
@@ -31,7 +30,6 @@
#include "proc_mm.h"
#include "skas_ptrace.h"
#include "chan_user.h"
-#include "signal_user.h"
#include "registers.h"
#include "mem.h"
#include "uml-config.h"
@@ -69,7 +67,7 @@ void wait_stub_done(int pid, int sig, char * fname)
if((n < 0) || !WIFSTOPPED(status) ||
(WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
- unsigned long regs[FRAME_SIZE];
+ unsigned long regs[HOST_FRAME_SIZE];
if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
printk("Failed to get registers from stub, "
"errno = %d\n", errno);
@@ -77,7 +75,7 @@ void wait_stub_done(int pid, int sig, char * fname)
int i;
printk("Stub registers -\n");
- for(i = 0; i < FRAME_SIZE; i++)
+ for(i = 0; i < HOST_FRAME_SIZE; i++)
printk("\t%d - %lx\n", i, regs[i]);
}
panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
@@ -514,16 +512,6 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
siglongjmp(**switch_buf, 1);
}
-void remove_sigstack(void)
-{
- stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
- .ss_sp = NULL,
- .ss_size = 0 });
-
- if(sigaltstack(&stack, NULL) != 0)
- panic("disabling signal stack failed, errno = %d\n", errno);
-}
-
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
sigjmp_buf here;
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 9c990253966c..3f70a2e12f06 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -13,15 +13,12 @@
#include "asm/uaccess.h"
#include "asm/atomic.h"
#include "kern_util.h"
-#include "time_user.h"
-#include "signal_user.h"
#include "skas.h"
#include "os.h"
#include "user_util.h"
#include "tlb.h"
#include "kern.h"
#include "mode.h"
-#include "proc_mm.h"
#include "registers.h"
void switch_to_skas(void *prev, void *next)
@@ -35,7 +32,7 @@ void switch_to_skas(void *prev, void *next)
if(current->pid == 0)
switch_timers(0);
- switch_threads(&from->thread.mode.skas.switch_buf,
+ switch_threads(&from->thread.mode.skas.switch_buf,
to->thread.mode.skas.switch_buf);
if(current->pid == 0)
@@ -51,8 +48,8 @@ void new_thread_handler(int sig)
fn = current->thread.request.u.thread.proc;
arg = current->thread.request.u.thread.arg;
- change_sig(SIGUSR1, 1);
- thread_wait(&current->thread.mode.skas.switch_buf,
+ os_usr1_signal(1);
+ thread_wait(&current->thread.mode.skas.switch_buf,
current->thread.mode.skas.fork_buf);
if(current->thread.prev_sched != NULL)
@@ -83,8 +80,8 @@ void release_thread_skas(struct task_struct *task)
void fork_handler(int sig)
{
- change_sig(SIGUSR1, 1);
- thread_wait(&current->thread.mode.skas.switch_buf,
+ os_usr1_signal(1);
+ thread_wait(&current->thread.mode.skas.switch_buf,
current->thread.mode.skas.fork_buf);
force_flush_all();
@@ -94,13 +91,13 @@ void fork_handler(int sig)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
- /* Handle any immediate reschedules or signals */
+/* Handle any immediate reschedules or signals */
interrupt_end();
userspace(&current->thread.regs.regs);
}
int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
- unsigned long stack_top, struct task_struct * p,
+ unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
void (*handler)(int);
@@ -119,32 +116,19 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
handler = new_thread_handler;
}
- new_thread(p->thread_info, &p->thread.mode.skas.switch_buf,
+ new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
&p->thread.mode.skas.fork_buf, handler);
return(0);
}
-extern void map_stub_pages(int fd, unsigned long code,
- unsigned long data, unsigned long stack);
-int new_mm(int from, unsigned long stack)
+int new_mm(unsigned long stack)
{
- struct proc_mm_op copy;
- int n, fd;
+ int fd;
fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
if(fd < 0)
return(fd);
- if(from != -1){
- copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
- .u =
- { .copy_segments = from } } );
- n = os_write_file(fd, &copy, sizeof(copy));
- if(n != sizeof(copy))
- printk("new_mm : /proc/mm copy_segments failed, "
- "err = %d\n", -n);
- }
-
if(skas_needs_stub)
map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
@@ -186,7 +170,7 @@ int start_uml_skas(void)
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
- return(start_idle_thread(init_task.thread_info,
+ return(start_idle_thread(task_stack_page(&init_task),
&init_task.thread.mode.skas.switch_buf,
&init_task.thread.mode.skas.fork_buf));
}
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index a5a47528dec7..5992c3257167 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -13,7 +13,7 @@
#include "asm/pgtable.h"
#include "asm/uaccess.h"
#include "kern_util.h"
-#include "user_util.h"
+#include "os.h"
extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out);
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 1429c131879d..1731d90e6850 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -25,12 +25,12 @@ int record_syscall_start(int syscall)
syscall_record[index].syscall = syscall;
syscall_record[index].pid = current_pid();
syscall_record[index].result = 0xdeadbeef;
- syscall_record[index].start = os_usecs();
+ syscall_record[index].start = os_nsecs();
return(index);
}
void record_syscall_end(int index, long result)
{
syscall_record[index].result = result;
- syscall_record[index].end = os_usecs();
+ syscall_record[index].end = os_nsecs();
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40b611e3d93..8fa2ae7f3026 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -14,9 +14,9 @@
#include "kern_util.h"
#include "user.h"
#include "process.h"
-#include "signal_user.h"
#include "time_user.h"
#include "kern_constants.h"
+#include "os.h"
/* XXX This really needs to be declared and initialized in a kernel file since
* it's in <linux/time.h>
@@ -99,7 +99,8 @@ void uml_idle_timer(void)
set_interval(ITIMER_REAL);
}
-extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+extern void ktime_get_ts(struct timespec *ts);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
void time_init(void)
{
@@ -114,8 +115,8 @@ void time_init(void)
wall_to_monotonic.tv_nsec = -now.tv_nsec;
}
-/* Declared in linux/time.h, which can't be included here */
-extern void clock_was_set(void);
+/* Defined in linux/ktimer.h, which can't be included here */
+#define clock_was_set() do { } while (0)
void do_gettimeofday(struct timeval *tv)
{
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 020ca79b8d33..3c7626cdba4b 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -13,12 +13,12 @@
#include "linux/interrupt.h"
#include "linux/init.h"
#include "linux/delay.h"
+#include "linux/hrtimer.h"
#include "asm/irq.h"
#include "asm/param.h"
#include "asm/current.h"
#include "kern_util.h"
#include "user_util.h"
-#include "time_user.h"
#include "mode.h"
#include "os.h"
@@ -39,7 +39,7 @@ unsigned long long sched_clock(void)
int timer_irq_inited = 0;
static int first_tick;
-static unsigned long long prev_usecs;
+static unsigned long long prev_nsecs;
#ifdef CONFIG_UML_REAL_TIME_CLOCK
static long long delta; /* Deviation per interval */
#endif
@@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs)
if(first_tick){
#ifdef CONFIG_UML_REAL_TIME_CLOCK
/* We've had 1 tick */
- unsigned long long usecs = os_usecs();
+ unsigned long long nsecs = os_nsecs();
- delta += usecs - prev_usecs;
- prev_usecs = usecs;
+ delta += nsecs - prev_nsecs;
+ prev_nsecs = nsecs;
/* Protect against the host clock being set backwards */
if(delta < 0)
delta = 0;
- ticks += (delta * HZ) / MILLION;
- delta -= (ticks * MILLION) / HZ;
+ ticks += (delta * HZ) / BILLION;
+ delta -= (ticks * BILLION) / HZ;
#else
ticks = 1;
#endif
}
else {
- prev_usecs = os_usecs();
+ prev_nsecs = os_nsecs();
first_tick = 1;
}
@@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs)
}
}
-void boot_timer_handler(int sig)
+void do_boot_timer_handler(struct sigcontext * sc)
{
struct pt_regs regs;
- CHOOSE_MODE((void)
- (UPT_SC(&regs.regs) = (struct sigcontext *) (&sig + 1)),
+ CHOOSE_MODE((void) (UPT_SC(&regs.regs) = sc),
(void) (regs.regs.skas.is_user = 0));
do_timer(&regs);
}
+static DEFINE_SPINLOCK(timer_spinlock);
+
+static unsigned long long local_offset = 0;
+
+static inline unsigned long long get_time(void)
+{
+ unsigned long long nsecs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&timer_spinlock, flags);
+ nsecs = os_nsecs();
+ nsecs += local_offset;
+ spin_unlock_irqrestore(&timer_spinlock, flags);
+
+ return nsecs;
+}
+
irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
{
+ unsigned long long nsecs;
unsigned long flags;
do_timer(regs);
+
write_seqlock_irqsave(&xtime_lock, flags);
- timer();
+ nsecs = get_time() + local_offset;
+ xtime.tv_sec = nsecs / NSEC_PER_SEC;
+ xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
write_sequnlock_irqrestore(&xtime_lock, flags);
+
return(IRQ_HANDLED);
}
long um_time(int __user *tloc)
{
- struct timeval now;
+ long ret = get_time() / NSEC_PER_SEC;
- do_gettimeofday(&now);
- if (tloc) {
- if (put_user(now.tv_sec, tloc))
- now.tv_sec = -EFAULT;
- }
- return now.tv_sec;
+ if((tloc != NULL) && put_user(ret, tloc))
+ return -EFAULT;
+
+ return ret;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long long nsecs = get_time();
+
+ tv->tv_sec = nsecs / NSEC_PER_SEC;
+ /* Careful about calculations here - this was originally done as
+ * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC
+ * which gave bogus (> 1000000) values. Dunno why, suspect gcc
+ * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion
+ * problem that I missed.
+ */
+ nsecs -= tv->tv_sec * NSEC_PER_SEC;
+ tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC;
+}
+
+static inline void set_time(unsigned long long nsecs)
+{
+ unsigned long long now;
+ unsigned long flags;
+
+ spin_lock_irqsave(&timer_spinlock, flags);
+ now = os_nsecs();
+ local_offset = nsecs - now;
+ spin_unlock_irqrestore(&timer_spinlock, flags);
+
+ clock_was_set();
}
long um_stime(int __user *tptr)
{
int value;
- struct timespec new;
if (get_user(value, tptr))
return -EFAULT;
- new.tv_sec = value;
- new.tv_nsec = 0;
- do_settimeofday(&new);
+
+ set_time((unsigned long long) value * NSEC_PER_SEC);
+
+ return 0;
+}
+
+int do_settimeofday(struct timespec *tv)
+{
+ set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec);
+
return 0;
}
@@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs)
{
local_irq_disable();
irq_enter();
- update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)),
- (regs)->skas.is_user));
+ update_process_times(CHOOSE_MODE(
+ (UPT_SC(regs) && user_context(UPT_SP(regs))),
+ (regs)->skas.is_user));
irq_exit();
local_irq_enable();
if(current_thread->cpu == 0)
timer_irq(regs);
}
-static DEFINE_SPINLOCK(timer_spinlock);
-
-unsigned long time_lock(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&timer_spinlock, flags);
- return(flags);
-}
-
-void time_unlock(unsigned long flags)
-{
- spin_unlock_irqrestore(&timer_spinlock, flags);
-}
-
int __init timer_init(void)
{
int err;
@@ -171,14 +210,3 @@ int __init timer_init(void)
}
__initcall(timer_init);
-
-/*
- * 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_kern.c b/arch/um/kernel/trap_kern.c
index 0d4c10a73607..d56046c2aba2 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -26,9 +26,13 @@
#include "mconsole_kern.h"
#include "mem.h"
#include "mem_kern.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/ptrace.h"
+#include "os.h"
#ifdef CONFIG_MODE_SKAS
#include "skas.h"
#endif
+#include "os.h"
/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
int handle_page_fault(unsigned long address, unsigned long ip,
@@ -125,6 +129,25 @@ out_of_memory:
goto out;
}
+void segv_handler(int sig, union uml_pt_regs *regs)
+{
+ struct faultinfo * fi = UPT_FAULTINFO(regs);
+
+ if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
+ bad_segv(*fi, UPT_IP(regs));
+ return;
+ }
+ segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
+}
+
+struct kern_handlers handlinfo_kern = {
+ .relay_signal = relay_signal,
+ .winch = winch,
+ .bus_handler = relay_signal,
+ .page_fault = segv_handler,
+ .sigio_handler = sigio_handler,
+ .timer_handler = timer_handler
+};
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
deleted file mode 100644
index e9ccd6b8d3c7..000000000000
--- a/arch/um/kernel/trap_user.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <asm/page.h>
-#include <asm/unistd.h>
-#include <asm/ptrace.h>
-#include "init.h"
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "sysdep/sigcontext.h"
-#include "irq_user.h"
-#include "signal_user.h"
-#include "time_user.h"
-#include "task.h"
-#include "mode.h"
-#include "choose-mode.h"
-#include "kern_util.h"
-#include "user_util.h"
-#include "os.h"
-
-void kill_child_dead(int pid)
-{
- kill(pid, SIGKILL);
- kill(pid, SIGCONT);
- do {
- int n;
- CATCH_EINTR(n = waitpid(pid, NULL, 0));
- if (n > 0)
- kill(pid, SIGCONT);
- else
- break;
- } while(1);
-}
-
-void segv_handler(int sig, union uml_pt_regs *regs)
-{
- struct faultinfo * fi = UPT_FAULTINFO(regs);
-
- if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){
- bad_segv(*fi, UPT_IP(regs));
- return;
- }
- segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
-}
-
-void usr2_handler(int sig, union uml_pt_regs *regs)
-{
- CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
-}
-
-struct signal_info sig_info[] = {
- [ SIGTRAP ] { .handler = relay_signal,
- .is_irq = 0 },
- [ SIGFPE ] { .handler = relay_signal,
- .is_irq = 0 },
- [ SIGILL ] { .handler = relay_signal,
- .is_irq = 0 },
- [ SIGWINCH ] { .handler = winch,
- .is_irq = 1 },
- [ SIGBUS ] { .handler = bus_handler,
- .is_irq = 0 },
- [ SIGSEGV] { .handler = segv_handler,
- .is_irq = 0 },
- [ SIGIO ] { .handler = sigio_handler,
- .is_irq = 1 },
- [ SIGVTALRM ] { .handler = timer_handler,
- .is_irq = 1 },
- [ SIGALRM ] { .handler = timer_handler,
- .is_irq = 1 },
- [ SIGUSR2 ] { .handler = usr2_handler,
- .is_irq = 0 },
-};
-
-void do_longjmp(void *b, int val)
-{
- sigjmp_buf *buf = b;
-
- siglongjmp(*buf, val);
-}
-
-/*
- * 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/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 065b504a653b..5c1e4cc1c049 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -13,8 +13,6 @@
#include "user_util.h"
#include "kern_util.h"
#include "irq_user.h"
-#include "time_user.h"
-#include "signal_user.h"
#include "mem_user.h"
#include "os.h"
#include "tlb.h"
@@ -40,7 +38,7 @@ void flush_thread_tt(void)
do_exit(SIGKILL);
}
- new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp);
+ new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
if(new_pid < 0){
printk(KERN_ERR
"flush_thread : new thread failed, errno = %d\n",
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 37e22d71a0d9..786e4edd86c5 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -20,6 +20,7 @@
#include "user_util.h"
#include "tt.h"
#include "sysdep/thread.h"
+#include "os.h"
extern int debugger_pid;
extern int debugger_fd;
diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h
deleted file mode 100644
index 0440510ab3fe..000000000000
--- a/arch/um/kernel/tt/include/mmu-tt.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __TT_MMU_H
-#define __TT_MMU_H
-
-struct mmu_context_tt {
-};
-
-#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/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index cfaa373a6e77..295c1ac817b3 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -13,13 +13,11 @@
#include "asm/ptrace.h"
#include "asm/tlbflush.h"
#include "irq_user.h"
-#include "signal_user.h"
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
#include "kern.h"
#include "sigcontext.h"
-#include "time_user.h"
#include "mem_user.h"
#include "tlb.h"
#include "mode.h"
@@ -37,7 +35,7 @@ void switch_to_tt(void *prev, void *next)
from = prev;
to = next;
- cpu = from->thread_info->cpu;
+ cpu = task_thread_info(from)->cpu;
if(cpu == 0)
forward_interrupts(to->thread.mode.tt.extern_pid);
#ifdef CONFIG_SMP
@@ -254,7 +252,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
clone_flags &= CLONE_VM;
p->thread.temp_stack = stack;
- new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp);
+ new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
if(new_pid < 0){
printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
-new_pid);
@@ -344,7 +342,7 @@ int do_proc_op(void *t, int proc_id)
pid = thread->request.u.exec.pid;
do_exec(thread->mode.tt.extern_pid, pid);
thread->mode.tt.extern_pid = pid;
- cpu_tasks[task->thread_info->cpu].pid = pid;
+ cpu_tasks[task_thread_info(task)->cpu].pid = pid;
break;
case OP_FORK:
attach_process(thread->request.u.fork.pid);
@@ -426,7 +424,7 @@ int start_uml_tt(void)
int pages;
pages = (1 << CONFIG_KERNEL_STACK_ORDER);
- sp = (void *) ((unsigned long) init_task.thread_info) +
+ sp = task_stack_page(&init_task) +
pages * PAGE_SIZE - sizeof(unsigned long);
return(tracer(start_kernel_proc, sp));
}
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 528a5fc8d887..03774427d468 100644
--- a/arch/um/kernel/tt/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
#include "kern_util.h"
#include "ptrace_user.h"
#include "tt.h"
+#include "os.h"
long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index a5f0e01e214e..99f178319d03 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -15,6 +15,7 @@ terms and conditions.
#include "ptrace_user.h"
#include "user_util.h"
#include "user.h"
+#include "os.h"
int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
long *arg5)
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index d11e7399d7a1..71daae24e48a 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -19,7 +19,6 @@
#include "sigcontext.h"
#include "sysdep/sigcontext.h"
#include "os.h"
-#include "signal_user.h"
#include "user_util.h"
#include "mem_user.h"
#include "process.h"
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index fc108615beaf..b5d9d64d91e4 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -8,18 +8,18 @@
#include <signal.h>
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
-#include "signal_user.h"
#include "user_util.h"
#include "kern_util.h"
#include "task.h"
#include "tt.h"
+#include "os.h"
void sig_handler_common_tt(int sig, void *sc_ptr)
{
struct sigcontext *sc = sc_ptr;
struct tt_regs save_regs, *r;
- struct signal_info *info;
- int save_errno = errno, is_user;
+ int save_errno = errno, is_user = 0;
+ void (*handler)(int, union uml_pt_regs *);
/* This is done because to allow SIGSEGV to be delivered inside a SEGV
* handler. This can happen in copy_user, and if SEGV is disabled,
@@ -35,15 +35,20 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
}
save_regs = *r;
- is_user = user_context(SC_SP(sc));
+ if (sc)
+ is_user = user_context(SC_SP(sc));
r->sc = sc;
if(sig != SIGUSR2)
r->syscall = -1;
- info = &sig_info[sig];
- if(!info->is_irq) unblock_signals();
+ handler = sig_info[sig];
+
+ /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
+ if (sig != SIGIO && sig != SIGWINCH &&
+ sig != SIGVTALRM && sig != SIGALRM)
+ unblock_signals();
- (*info->handler)(sig, (union uml_pt_regs *) r);
+ handler(sig, (union uml_pt_regs *) r);
if(is_user){
interrupt_end();
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 142a9493912b..e2d3ca445ef5 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -146,8 +146,8 @@ void set_cmdline(char *cmd)
if(CHOOSE_MODE(honeypot, 0)) return;
- umid = get_umid(1);
- if(umid != NULL){
+ umid = get_umid();
+ if(*umid != '\0'){
snprintf(argv1_begin,
(argv1_end - argv1_begin) * sizeof(*ptr),
"(%s) ", umid);
@@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add)
return(0);
}
-#else
-
-#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
-
#endif
#endif
#endif
@@ -363,6 +359,11 @@ int linux_main(int argc, char **argv)
uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
&host_task_size, &task_size);
+ /*
+ * Setting up handlers to 'sig_info' struct
+ */
+ os_fill_handlinfo(handlinfo_kern);
+
brk_start = (unsigned long) sbrk(0);
CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
/* Increase physical memory size for exec-shield users
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 0b21d59ba0cd..4eaee823bfd2 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -3,61 +3,30 @@
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include "user.h"
-#include "umid.h"
+#include "asm/errno.h"
#include "init.h"
#include "os.h"
-#include "user_util.h"
-#include "choose-mode.h"
+#include "kern.h"
+#include "linux/kernel.h"
-#define UMID_LEN 64
-#define UML_DIR "~/.uml/"
-
-/* Changed by set_umid and make_umid, which are run early in boot */
-static char umid[UMID_LEN] = { 0 };
-
-/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
-static char *uml_dir = UML_DIR;
-
-/* Changed by set_umid */
-static int umid_is_random = 1;
+/* Changed by set_umid_arg */
static int umid_inited = 0;
-/* Have we created the files? Should we remove them? */
-static int umid_owned = 0;
-static int make_umid(int (*printer)(const char *fmt, ...));
-
-static int __init set_umid(char *name, int is_random,
- int (*printer)(const char *fmt, ...))
+static int __init set_umid_arg(char *name, int *add)
{
- if(umid_inited){
- (*printer)("Unique machine name can't be set twice\n");
- return(-1);
- }
+ int err;
- if(strlen(name) > UMID_LEN - 1)
- (*printer)("Unique machine name is being truncated to %d "
- "characters\n", UMID_LEN);
- strlcpy(umid, name, sizeof(umid));
+ if(umid_inited)
+ return 0;
- umid_is_random = is_random;
- umid_inited = 1;
- return 0;
-}
-
-static int __init set_umid_arg(char *name, int *add)
-{
*add = 0;
- return(set_umid(name, 0, printf));
+ err = set_umid(name);
+ if(err == -EEXIST)
+ printf("umid '%s' already in use\n", name);
+ else if(!err)
+ umid_inited = 1;
+
+ return 0;
}
__uml_setup("umid=", set_umid_arg,
@@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg,
" is used for naming the pid file and management console socket.\n\n"
);
-int __init umid_file_name(char *name, char *buf, int len)
-{
- int n;
-
- if(!umid_inited && make_umid(printk)) return(-1);
-
- n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
- if(n > len){
- printk("umid_file_name : buffer too short\n");
- return(-1);
- }
-
- sprintf(buf, "%s%s/%s", uml_dir, umid, name);
- return(0);
-}
-
-extern int tracing_pid;
-
-static void __init create_pid_file(void)
-{
- char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
- char pid[sizeof("nnnnn\0")];
- int fd, n;
-
- if(umid_file_name("pid", file, sizeof(file)))
- return;
-
- fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
- 0644);
- if(fd < 0){
- printf("Open of machine pid file \"%s\" failed: %s\n",
- file, strerror(-fd));
- return;
- }
-
- sprintf(pid, "%d\n", os_getpid());
- n = os_write_file(fd, pid, strlen(pid));
- if(n != strlen(pid))
- printf("Write of pid file failed - err = %d\n", -n);
- os_close_file(fd);
-}
-
-static int actually_do_remove(char *dir)
-{
- DIR *directory;
- struct dirent *ent;
- int len;
- char file[256];
-
- directory = opendir(dir);
- if(directory == NULL){
- printk("actually_do_remove : couldn't open directory '%s', "
- "errno = %d\n", dir, errno);
- return(1);
- }
- while((ent = readdir(directory)) != NULL){
- if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
- continue;
- len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
- if(len > sizeof(file)){
- printk("Not deleting '%s' from '%s' - name too long\n",
- ent->d_name, dir);
- continue;
- }
- sprintf(file, "%s/%s", dir, ent->d_name);
- if(unlink(file) < 0){
- printk("actually_do_remove : couldn't remove '%s' "
- "from '%s', errno = %d\n", ent->d_name, dir,
- errno);
- return(1);
- }
- }
- if(rmdir(dir) < 0){
- printk("actually_do_remove : couldn't rmdir '%s', "
- "errno = %d\n", dir, errno);
- return(1);
- }
- return(0);
-}
-
-void remove_umid_dir(void)
-{
- char dir[strlen(uml_dir) + UMID_LEN + 1];
- if (!umid_owned)
- return;
-
- sprintf(dir, "%s%s", uml_dir, umid);
- actually_do_remove(dir);
-}
-
-char *get_umid(int only_if_set)
-{
- if(only_if_set && umid_is_random)
- return NULL;
- return umid;
-}
-
-static int not_dead_yet(char *dir)
-{
- char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
- char pid[sizeof("nnnnn\0")], *end;
- int dead, fd, p, n;
-
- sprintf(file, "%s/pid", dir);
- dead = 0;
- fd = os_open_file(file, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- if(fd != -ENOENT){
- printk("not_dead_yet : couldn't open pid file '%s', "
- "err = %d\n", file, -fd);
- return(1);
- }
- dead = 1;
- }
- if(fd > 0){
- n = os_read_file(fd, pid, sizeof(pid));
- if(n < 0){
- printk("not_dead_yet : couldn't read pid file '%s', "
- "err = %d\n", file, -n);
- return(1);
- }
- p = strtoul(pid, &end, 0);
- if(end == pid){
- printk("not_dead_yet : couldn't parse pid file '%s', "
- "errno = %d\n", file, errno);
- dead = 1;
- }
- if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
- (p == CHOOSE_MODE(tracing_pid, os_getpid())))
- dead = 1;
- }
- if(!dead)
- return(1);
- return(actually_do_remove(dir));
-}
-
-static int __init set_uml_dir(char *name, int *add)
-{
- if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
- uml_dir = malloc(strlen(name) + 2);
- if(uml_dir == NULL){
- printf("Failed to malloc uml_dir - error = %d\n",
- errno);
- uml_dir = name;
- /* Return 0 here because do_initcalls doesn't look at
- * the return value.
- */
- return(0);
- }
- sprintf(uml_dir, "%s/", name);
- }
- else uml_dir = name;
- return(0);
-}
-
-static int __init make_uml_dir(void)
-{
- char dir[MAXPATHLEN + 1] = { '\0' };
- int len;
-
- if(*uml_dir == '~'){
- char *home = getenv("HOME");
-
- if(home == NULL){
- printf("make_uml_dir : no value in environment for "
- "$HOME\n");
- exit(1);
- }
- strlcpy(dir, home, sizeof(dir));
- uml_dir++;
- }
- strlcat(dir, uml_dir, sizeof(dir));
- len = strlen(dir);
- if (len > 0 && dir[len - 1] != '/')
- strlcat(dir, "/", sizeof(dir));
-
- uml_dir = malloc(strlen(dir) + 1);
- if (uml_dir == NULL) {
- printf("make_uml_dir : malloc failed, errno = %d\n", errno);
- exit(1);
- }
- strcpy(uml_dir, dir);
-
- if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
- printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno));
- return(-1);
- }
- return 0;
-}
-
-static int __init make_umid(int (*printer)(const char *fmt, ...))
-{
- int fd, err;
- char tmp[strlen(uml_dir) + UMID_LEN + 1];
-
- strlcpy(tmp, uml_dir, sizeof(tmp));
-
- if(!umid_inited){
- strcat(tmp, "XXXXXX");
- fd = mkstemp(tmp);
- if(fd < 0){
- (*printer)("make_umid - mkstemp(%s) failed: %s\n",
- tmp,strerror(errno));
- return(1);
- }
-
- os_close_file(fd);
- /* There's a nice tiny little race between this unlink and
- * the mkdir below. It'd be nice if there were a mkstemp
- * for directories.
- */
- unlink(tmp);
- set_umid(&tmp[strlen(uml_dir)], 1, printer);
- }
-
- sprintf(tmp, "%s%s", uml_dir, umid);
-
- err = mkdir(tmp, 0777);
- if(err < 0){
- if(errno == EEXIST){
- if(not_dead_yet(tmp)){
- (*printer)("umid '%s' is in use\n", umid);
- umid_owned = 0;
- return(-1);
- }
- err = mkdir(tmp, 0777);
- }
- }
- if(err < 0){
- (*printer)("Failed to create %s - errno = %d\n", umid, errno);
- return(-1);
- }
-
- umid_owned = 1;
- return 0;
-}
-
-__uml_setup("uml_dir=", set_uml_dir,
-"uml_dir=<directory>\n"
-" The location to place the pid and umid files.\n\n"
-);
-
-static int __init make_umid_setup(void)
-{
- /* one function with the ordering we need ... */
- make_uml_dir();
- make_umid(printf);
- create_pid_file();
- return 0;
-}
-__uml_postsetup(make_umid_setup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index b83ac8e21c35..08a4e628b24c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,11 +4,13 @@
#
obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \
- sys-$(SUBARCH)/
+ start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \
+ util.o drivers/ sys-$(SUBARCH)/
+
+obj-$(CONFIG_MODE_SKAS) += skas/
USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
- start_up.o time.o tt.o tty.o uaccess.o
+ start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o
elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index ffa759addd3c..f897140cc4ae 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -16,12 +16,12 @@
#include "mode.h"
struct aio_thread_req {
- enum aio_type type;
- int io_fd;
- unsigned long long offset;
- char *buf;
- int len;
- struct aio_context *aio;
+ enum aio_type type;
+ int io_fd;
+ unsigned long long offset;
+ char *buf;
+ int len;
+ struct aio_context *aio;
};
static int aio_req_fd_r = -1;
@@ -38,18 +38,18 @@ static int aio_req_fd_w = -1;
static long io_setup(int n, aio_context_t *ctxp)
{
- return syscall(__NR_io_setup, n, 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);
+ 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)
+ struct io_event *events, struct timespec *timeout)
{
- return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
+ return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout);
}
#endif
@@ -66,243 +66,245 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr,
*/
static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf,
- int len, unsigned long long offset, struct aio_context *aio)
+ int len, unsigned long long offset, 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 = fd,
- .aio_buf = (unsigned long) buf,
- .aio_nbytes = len,
- .aio_offset = offset,
- .aio_reserved1 = 0,
- .aio_reserved2 = 0,
- .aio_reserved3 = 0 });
-
- switch(type){
- case AIO_READ:
- iocb.aio_lio_opcode = IOCB_CMD_PREAD;
- err = io_submit(ctx, 1, &iocbp);
- break;
- case AIO_WRITE:
- iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
- err = io_submit(ctx, 1, &iocbp);
- break;
- case AIO_MMAP:
- iocb.aio_lio_opcode = IOCB_CMD_PREAD;
- iocb.aio_buf = (unsigned long) &c;
- iocb.aio_nbytes = sizeof(c);
- err = io_submit(ctx, 1, &iocbp);
- break;
- default:
- printk("Bogus op in do_aio - %d\n", type);
- err = -EINVAL;
- break;
- }
-
- if(err > 0)
- err = 0;
+ struct iocb iocb, *iocbp = &iocb;
+ char c;
+ int err;
+
+ iocb = ((struct iocb) { .aio_data = (unsigned long) aio,
+ .aio_reqprio = 0,
+ .aio_fildes = fd,
+ .aio_buf = (unsigned long) buf,
+ .aio_nbytes = len,
+ .aio_offset = offset,
+ .aio_reserved1 = 0,
+ .aio_reserved2 = 0,
+ .aio_reserved3 = 0 });
+
+ switch(type){
+ case AIO_READ:
+ iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+ err = io_submit(ctx, 1, &iocbp);
+ break;
+ case AIO_WRITE:
+ iocb.aio_lio_opcode = IOCB_CMD_PWRITE;
+ err = io_submit(ctx, 1, &iocbp);
+ break;
+ case AIO_MMAP:
+ iocb.aio_lio_opcode = IOCB_CMD_PREAD;
+ iocb.aio_buf = (unsigned long) &c;
+ iocb.aio_nbytes = sizeof(c);
+ err = io_submit(ctx, 1, &iocbp);
+ break;
+ default:
+ printk("Bogus op in do_aio - %d\n", type);
+ err = -EINVAL;
+ break;
+ }
+
+ if(err > 0)
+ err = 0;
else
err = -errno;
- return err;
+ return err;
}
static aio_context_t ctx = 0;
static int aio_thread(void *arg)
{
- struct aio_thread_reply reply;
- struct io_event event;
- int err, n, reply_fd;
-
- 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 {
- reply = ((struct aio_thread_reply)
- { .data = (void *) (long) event.data,
- .err = event.res });
+ struct aio_thread_reply reply;
+ struct io_event event;
+ int err, n, reply_fd;
+
+ 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 {
+ reply = ((struct aio_thread_reply)
+ { .data = (void *) (long) event.data,
+ .err = event.res });
reply_fd = ((struct aio_context *) reply.data)->reply_fd;
err = os_write_file(reply_fd, &reply, sizeof(reply));
- if(err != sizeof(reply))
+ if(err != sizeof(reply))
printk("aio_thread - write failed, fd = %d, "
- "err = %d\n", aio_req_fd_r, -err);
- }
- }
- return 0;
+ "err = %d\n", aio_req_fd_r, -err);
+ }
+ }
+ return 0;
}
#endif
static int do_not_aio(struct aio_thread_req *req)
{
- char c;
- int err;
-
- switch(req->type){
- case AIO_READ:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_read_file(req->io_fd, req->buf, req->len);
- break;
- case AIO_WRITE:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_write_file(req->io_fd, req->buf, req->len);
- break;
- case AIO_MMAP:
- err = os_seek_file(req->io_fd, req->offset);
- if(err)
- goto out;
-
- err = os_read_file(req->io_fd, &c, sizeof(c));
- break;
- default:
- printk("do_not_aio - bad request type : %d\n", req->type);
- err = -EINVAL;
- break;
- }
-
- out:
- return err;
+ char c;
+ int err;
+
+ switch(req->type){
+ case AIO_READ:
+ err = os_seek_file(req->io_fd, req->offset);
+ if(err)
+ goto out;
+
+ err = os_read_file(req->io_fd, req->buf, req->len);
+ break;
+ case AIO_WRITE:
+ err = os_seek_file(req->io_fd, req->offset);
+ if(err)
+ goto out;
+
+ err = os_write_file(req->io_fd, req->buf, req->len);
+ break;
+ case AIO_MMAP:
+ err = os_seek_file(req->io_fd, req->offset);
+ if(err)
+ goto out;
+
+ err = os_read_file(req->io_fd, &c, sizeof(c));
+ break;
+ default:
+ printk("do_not_aio - bad request type : %d\n", req->type);
+ err = -EINVAL;
+ break;
+ }
+
+out:
+ return err;
}
static int not_aio_thread(void *arg)
{
- struct aio_thread_req req;
- struct aio_thread_reply reply;
- int err;
-
- signal(SIGWINCH, SIG_IGN);
- while(1){
- err = os_read_file(aio_req_fd_r, &req, sizeof(req));
- if(err != sizeof(req)){
- 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;
- }
- err = do_not_aio(&req);
- reply = ((struct aio_thread_reply) { .data = req.aio,
- .err = err });
- err = os_write_file(req.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);
- }
+ struct aio_thread_req req;
+ struct aio_thread_reply reply;
+ int err;
+
+ signal(SIGWINCH, SIG_IGN);
+ while(1){
+ err = os_read_file(aio_req_fd_r, &req, sizeof(req));
+ if(err != sizeof(req)){
+ 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;
+ }
+ err = do_not_aio(&req);
+ reply = ((struct aio_thread_reply) { .data = req.aio,
+ .err = err });
+ err = os_write_file(req.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);
+ }
+
+ return 0;
}
static int aio_pid = -1;
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:
+ 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");
- return 0;
+ return 0;
}
#ifdef HAVE_AIO_ABI
#define DEFAULT_24_AIO 0
static int init_aio_26(void)
{
- unsigned long stack;
- int err;
+ unsigned long stack;
+ int err;
- if(io_setup(256, &ctx)){
+ if(io_setup(256, &ctx)){
err = -errno;
- printk("aio_thread failed to initialize context, err = %d\n",
- errno);
- return err;
- }
+ printk("aio_thread failed to initialize context, err = %d\n",
+ errno);
+ return err;
+ }
- err = run_helper_thread(aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
- if(err < 0)
- return err;
+ err = run_helper_thread(aio_thread, NULL,
+ CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0);
+ if(err < 0)
+ return err;
- aio_pid = err;
+ aio_pid = err;
printk("Using 2.6 host AIO\n");
- return 0;
+ return 0;
}
static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
unsigned long long offset, struct aio_context *aio)
{
- struct aio_thread_reply reply;
- int err;
-
- err = do_aio(ctx, type, io_fd, buf, len, offset, 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;
+ struct aio_thread_reply reply;
+ int err;
+
+ err = do_aio(ctx, type, io_fd, buf, len, offset, 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;
}
#else
#define DEFAULT_24_AIO 1
static int init_aio_26(void)
{
- return -ENOSYS;
+ return -ENOSYS;
}
static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len,
unsigned long long offset, struct aio_context *aio)
{
- return -ENOSYS;
+ return -ENOSYS;
}
#endif
@@ -310,8 +312,8 @@ static int aio_24 = DEFAULT_24_AIO;
static int __init set_aio_24(char *name, int *add)
{
- aio_24 = 1;
- return 0;
+ aio_24 = 1;
+ return 0;
}
__uml_setup("aio=2.4", set_aio_24,
@@ -328,28 +330,27 @@ __uml_setup("aio=2.4", set_aio_24,
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;
+ 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
@@ -362,8 +363,8 @@ __initcall(init_aio);
static void exit_aio(void)
{
- if(aio_pid != -1)
- os_kill_process(aio_pid, 1);
+ if(aio_pid != -1)
+ os_kill_process(aio_pid, 1);
}
__uml_exitcall(exit_aio);
@@ -371,30 +372,30 @@ __uml_exitcall(exit_aio);
static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len,
unsigned long long offset, struct aio_context *aio)
{
- struct aio_thread_req req = { .type = type,
- .io_fd = io_fd,
- .offset = offset,
- .buf = buf,
- .len = len,
- .aio = aio,
- };
- int err;
-
- err = os_write_file(aio_req_fd_w, &req, sizeof(req));
- if(err == sizeof(req))
- err = 0;
-
- return err;
+ struct aio_thread_req req = { .type = type,
+ .io_fd = io_fd,
+ .offset = offset,
+ .buf = buf,
+ .len = len,
+ .aio = aio,
+ };
+ int err;
+
+ err = os_write_file(aio_req_fd_w, &req, sizeof(req));
+ if(err == sizeof(req))
+ err = 0;
+
+ return err;
}
int submit_aio(enum aio_type type, int io_fd, char *buf, int len,
- unsigned long long offset, int reply_fd,
- struct aio_context *aio)
+ unsigned long long offset, int reply_fd,
+ struct aio_context *aio)
{
- aio->reply_fd = reply_fd;
- if(aio_24)
- return submit_aio_24(type, io_fd, buf, len, offset, aio);
- else {
- return submit_aio_26(type, io_fd, buf, len, offset, aio);
- }
+ aio->reply_fd = reply_fd;
+ if(aio_24)
+ return submit_aio_24(type, io_fd, buf, len, offset, aio);
+ else {
+ return submit_aio_26(type, io_fd, buf, len, offset, aio);
+ }
}
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 36cc8475bcda..6490a4ff40ac 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
if((stack_out != NULL) && (*stack_out != 0))
stack = *stack_out;
- else stack = alloc_stack(0, um_in_interrupt());
+ else stack = alloc_stack(0, __cant_sleep());
if(stack == 0)
return(-ENOMEM);
@@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long stack, sp;
int pid, status, err;
- stack = alloc_stack(stack_order, um_in_interrupt());
+ stack = alloc_stack(stack_order, __cant_sleep());
if(stack == 0) return(-ENOMEM);
sp = stack + (page_size() << stack_order) - sizeof(void *);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 23da27d22569..2878e89a674f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -16,8 +16,6 @@
#include "user_util.h"
#include "kern_util.h"
#include "mem_user.h"
-#include "signal_user.h"
-#include "time_user.h"
#include "irq_user.h"
#include "user.h"
#include "init.h"
@@ -83,20 +81,8 @@ extern void scan_elf_aux( char **envp);
int main(int argc, char **argv, char **envp)
{
char **new_argv;
- sigset_t mask;
int ret, i, err;
- /* Enable all signals except SIGIO - in some environments, we can
- * enter with some signals blocked
- */
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGIO);
- if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
- perror("sigprocmask");
- exit(1);
- }
-
#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/os-Linux/process.c b/arch/um/os-Linux/process.c
index d9c52387c4a1..7f5e2dac2a35 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -15,10 +15,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"
+#include "longjmp.h"
#define ARBITRARY_ADDR -1
#define FAILURE_PID -1
@@ -206,24 +206,13 @@ void init_new_thread_signals(int 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);
+ sigjmp_buf buf;
+ int n, enable;
+
+ *jmp_ptr = &buf;
+ n = UML_SIGSETJMP(&buf, enable);
+ 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
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c7bfd5ee3925..f11b3124a0c8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -4,27 +4,74 @@
*/
#include <signal.h>
-#include "time_user.h"
-#include "mode.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/mman.h>
+#include "user_util.h"
+#include "user.h"
+#include "signal_kern.h"
+#include "sysdep/sigcontext.h"
#include "sysdep/signal.h"
+#include "sigcontext.h"
+#include "mode.h"
+#include "os.h"
+
+/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
+ * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
+ * be able to profile all of UML, not just the non-critical sections. If
+ * profiling is not thread-safe, then that is not my problem. We can disable
+ * profiling when SMP is enabled in that case.
+ */
+#define SIGIO_BIT 0
+#define SIGIO_MASK (1 << SIGIO_BIT)
+
+#define SIGVTALRM_BIT 1
+#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
+
+#define SIGALRM_BIT 2
+#define SIGALRM_MASK (1 << SIGALRM_BIT)
+
+static int signals_enabled = 1;
+static int pending = 0;
void sig_handler(ARCH_SIGHDLR_PARAM)
{
struct sigcontext *sc;
+ int enabled;
+
+ /* Must be the first thing that this handler does - x86_64 stores
+ * the sigcontext in %rdx, and we need to save it before it has a
+ * chance to get trashed.
+ */
ARCH_GET_SIGCONTEXT(sc, sig);
+
+ enabled = signals_enabled;
+ if(!enabled && (sig == SIGIO)){
+ pending |= SIGIO_MASK;
+ return;
+ }
+
+ block_signals();
+
CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
sig, sc);
+
+ set_signals(enabled);
}
extern int timer_irq_inited;
-void alarm_handler(ARCH_SIGHDLR_PARAM)
+static void real_alarm_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
-
- ARCH_GET_SIGCONTEXT(sc, sig);
- if(!timer_irq_inited) return;
+ if(!timer_irq_inited){
+ signals_enabled = 1;
+ return;
+ }
if(sig == SIGALRM)
switch_timers(0);
@@ -34,15 +81,180 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
if(sig == SIGALRM)
switch_timers(1);
+
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+void alarm_handler(ARCH_SIGHDLR_PARAM)
+{
+ struct sigcontext *sc;
+ int enabled;
+
+ ARCH_GET_SIGCONTEXT(sc, sig);
+
+ enabled = signals_enabled;
+ if(!signals_enabled){
+ if(sig == SIGVTALRM)
+ pending |= SIGVTALRM_MASK;
+ else pending |= SIGALRM_MASK;
+
+ return;
+ }
+
+ block_signals();
+
+ real_alarm_handler(sig, sc);
+ set_signals(enabled);
+}
+
+extern void do_boot_timer_handler(struct sigcontext * sc);
+
+void boot_timer_handler(ARCH_SIGHDLR_PARAM)
+{
+ struct sigcontext *sc;
+ int enabled;
+
+ ARCH_GET_SIGCONTEXT(sc, sig);
+
+ enabled = signals_enabled;
+ if(!enabled){
+ if(sig == SIGVTALRM)
+ pending |= SIGVTALRM_MASK;
+ else pending |= SIGALRM_MASK;
+ return;
+ }
+
+ block_signals();
+
+ do_boot_timer_handler(sc);
+ set_signals(enabled);
+}
+
+void set_sigstack(void *sig_stack, int size)
+{
+ stack_t stack = ((stack_t) { .ss_flags = 0,
+ .ss_sp = (__ptr_t) sig_stack,
+ .ss_size = size - sizeof(void *) });
+
+ if(sigaltstack(&stack, NULL) != 0)
+ panic("enabling signal stack failed, errno = %d\n", errno);
+}
+
+void remove_sigstack(void)
+{
+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
+ .ss_sp = NULL,
+ .ss_size = 0 });
+
+ if(sigaltstack(&stack, NULL) != 0)
+ panic("disabling signal stack failed, errno = %d\n", errno);
+}
+
+void set_handler(int sig, void (*handler)(int), int flags, ...)
+{
+ struct sigaction action;
+ va_list ap;
+ sigset_t sig_mask;
+ int mask;
+
+ va_start(ap, flags);
+ action.sa_handler = handler;
+ sigemptyset(&action.sa_mask);
+ while((mask = va_arg(ap, int)) != -1){
+ sigaddset(&action.sa_mask, mask);
+ }
+ va_end(ap);
+ action.sa_flags = flags;
+ action.sa_restorer = NULL;
+ if(sigaction(sig, &action, NULL) < 0)
+ panic("sigaction failed - errno = %d\n", errno);
+
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, sig);
+ if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
+ panic("sigprocmask failed - errno = %d\n", errno);
+}
+
+int change_sig(int signal, int on)
+{
+ sigset_t sigset, old;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, signal);
+ sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
+ return(!sigismember(&old, signal));
+}
+
+void block_signals(void)
+{
+ signals_enabled = 0;
+}
+
+void unblock_signals(void)
+{
+ int save_pending;
+
+ if(signals_enabled == 1)
+ return;
+
+ /* We loop because the IRQ handler returns with interrupts off. So,
+ * interrupts may have arrived and we need to re-enable them and
+ * recheck pending.
+ */
+ while(1){
+ /* Save and reset save_pending after enabling signals. This
+ * way, pending won't be changed while we're reading it.
+ */
+ signals_enabled = 1;
+
+ save_pending = pending;
+ if(save_pending == 0)
+ return;
+
+ pending = 0;
+
+ /* We have pending interrupts, so disable signals, as the
+ * handlers expect them off when they are called. They will
+ * be enabled again above.
+ */
+
+ signals_enabled = 0;
+
+ /* Deal with SIGIO first because the alarm handler might
+ * schedule, leaving the pending SIGIO stranded until we come
+ * back here.
+ */
+ if(save_pending & SIGIO_MASK)
+ CHOOSE_MODE_PROC(sig_handler_common_tt,
+ sig_handler_common_skas, SIGIO, NULL);
+
+ if(save_pending & SIGALRM_MASK)
+ real_alarm_handler(SIGALRM, NULL);
+
+ if(save_pending & SIGVTALRM_MASK)
+ real_alarm_handler(SIGVTALRM, NULL);
+ }
+}
+
+int get_signals(void)
+{
+ return signals_enabled;
+}
+
+int set_signals(int enable)
+{
+ int ret;
+ if(signals_enabled == enable)
+ return enable;
+
+ ret = signals_enabled;
+ if(enable)
+ unblock_signals();
+ else block_signals();
+
+ return ret;
+}
+
+void os_usr1_signal(int on)
+{
+ change_sig(SIGUSR1, on);
+}
diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
new file mode 100644
index 000000000000..5fd8d4dad66a
--- /dev/null
+++ b/arch/um/os-Linux/skas/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
+# Licensed under the GPL
+#
+
+obj-y := mem.o process.o trap.o
+
+USER_OBJS := mem.o process.o trap.o
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c
index 1d89640bd502..9890e9090f58 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname);
static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
unsigned long *stack)
{
- if(stack == NULL){
+ if(stack == NULL) {
stack = (unsigned long *) mm_idp->stack + 2;
*stack = 0;
}
@@ -45,13 +45,14 @@ 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)
+static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
{
unsigned long regs[MAX_REG_NR];
- unsigned long *data;
- unsigned long *syscall;
+ int n;
long ret, offset;
- int n, pid = mm_idp->u.pid;
+ unsigned long * data;
+ unsigned long * syscall;
+ int pid = mm_idp->u.pid;
if(proc_mm)
#warning Need to look up userspace_pid by cpu
@@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
multi_count++;
- get_safe_registers(regs);
- regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+ get_safe_registers(regs);
+ regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
((unsigned long) &batch_syscall_stub -
- (unsigned long) &__syscall_stub_start);
+ (unsigned long) &__syscall_stub_start);
+
n = ptrace_setregs(pid, regs);
if(n < 0)
panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n",
@@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
if (offset) {
data = (unsigned long *)(mm_idp->stack +
offset - UML_CONFIG_STUB_DATA);
+ printk("do_syscall_stub : ret = %d, offset = %d, "
+ "data = 0x%x\n", ret, offset, data);
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",
@@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr)
long run_syscall_stub(struct mm_id * mm_idp, int syscall,
unsigned long *args, long expected, void **addr,
- int done)
+ int done)
{
- unsigned long *stack = check_init_stack(mm_idp, *addr);
+ unsigned long *stack = check_init_stack(mm_idp, *addr);
if(done && *addr == NULL)
single_count++;
- *stack += sizeof(long);
+ *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++ = 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++;
+ *stack = 0;
+ multi_op_count++;
- if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
+ if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
PAGE_SIZE - 10 * sizeof(long))){
*addr = stack;
- return 0;
- }
+ return 0;
+ }
return do_syscall_stub(mm_idp, addr);
}
@@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp,
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 */
+ /* in case of error, don't overwrite data on stack */
if(ret)
return ret;
}
@@ -172,39 +176,39 @@ 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, ret;
-
- prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
- (x ? PROT_EXEC : 0);
-
- 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 =
- { .addr = virt,
- .len = len,
- .prot = prot,
- .flags = MAP_SHARED |
- MAP_FIXED,
- .fd = phys_fd,
- .offset= offset
- } } } );
+ int prot, ret;
+
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0);
+
+ 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 =
+ { .addr = virt,
+ .len = len,
+ .prot = prot,
+ .flags = MAP_SHARED |
+ MAP_FIXED,
+ .fd = phys_fd,
+ .offset= offset
+ } } } );
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 {
- unsigned long args[] = { virt, len, prot,
- MAP_SHARED | MAP_FIXED, phys_fd,
- MMAP_OFFSET(offset) };
+ }
+ else {
+ unsigned long args[] = { virt, len, prot,
+ MAP_SHARED | MAP_FIXED, phys_fd,
+ MMAP_OFFSET(offset) };
ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt,
data, done);
- }
+ }
return ret;
}
@@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len,
int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done,
void **data)
{
- 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 } } } );
+ 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 } } } );
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 {
- unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
- 0 };
+ }
+ else {
+ unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0,
+ 0 };
ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0,
data, done);
- if(ret < 0)
- printk("munmap stub failed, errno = %d\n", ret);
- }
+ }
- return ret;
+ return ret;
}
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, ret;
-
- prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
- (x ? PROT_EXEC : 0);
-
- if(proc_mm){
- int fd = mm_idp->u.mm_fd;
- protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
- .u =
- { .mprotect =
- { .addr =
- (unsigned long) addr,
- .len = len,
- .prot = prot } } } );
-
- ret = os_write_file(fd, &protect, sizeof(protect));
- if(ret != sizeof(protect))
- printk("protect failed, err = %d", -ret);
- else ret = 0;
- }
- else {
- unsigned long args[] = { addr, len, prot, 0, 0, 0 };
-
- ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
- data, done);
- }
-
- return ret;
+ struct proc_mm_op protect;
+ int prot, ret;
+
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0);
+ if(proc_mm){
+ int fd = mm_idp->u.mm_fd;
+
+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
+ .u =
+ { .mprotect =
+ { .addr =
+ (unsigned long) addr,
+ .len = len,
+ .prot = prot } } } );
+
+ ret = os_write_file(fd, &protect, sizeof(protect));
+ if(ret != sizeof(protect))
+ printk("protect failed, err = %d", -ret);
+ else ret = 0;
+ }
+ else {
+ unsigned long args[] = { addr, len, prot, 0, 0, 0 };
+
+ ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0,
+ data, done);
+ }
+
+ return ret;
}
void before_mem_skas(unsigned long unused)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
new file mode 100644
index 000000000000..120a21c5883f
--- /dev/null
+++ b/arch/um/os-Linux/skas/process.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sched.h>
+#include "ptrace_user.h"
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <sys/time.h>
+#include <asm/unistd.h>
+#include <asm/types.h>
+#include "user.h"
+#include "sysdep/ptrace.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "stub-data.h"
+#include "mm_id.h"
+#include "sysdep/sigcontext.h"
+#include "sysdep/stub.h"
+#include "os.h"
+#include "proc_mm.h"
+#include "skas_ptrace.h"
+#include "chan_user.h"
+#include "registers.h"
+#include "mem.h"
+#include "uml-config.h"
+#include "process.h"
+#include "longjmp.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+ if(pid != os_getpgrp())
+ return(0);
+
+ register_winch_irq(-1, fd, -1, data);
+ return(1);
+}
+
+void wait_stub_done(int pid, int sig, char * fname)
+{
+ int n, status, err;
+
+ do {
+ if ( sig != -1 ) {
+ err = ptrace(PTRACE_CONT, pid, 0, sig);
+ if(err)
+ panic("%s : continue failed, errno = %d\n",
+ fname, errno);
+ }
+ sig = 0;
+
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ } while((n >= 0) && WIFSTOPPED(status) &&
+ ((WSTOPSIG(status) == SIGVTALRM) ||
+ /* running UML inside a detached screen can cause
+ * SIGWINCHes
+ */
+ (WSTOPSIG(status) == SIGWINCH)));
+
+ if((n < 0) || !WIFSTOPPED(status) ||
+ (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
+ unsigned long regs[HOST_FRAME_SIZE];
+
+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ printk("Failed to get registers from stub, "
+ "errno = %d\n", errno);
+ else {
+ int i;
+
+ printk("Stub registers -\n");
+ for(i = 0; i < HOST_FRAME_SIZE; i++)
+ printk("\t%d - %lx\n", i, regs[i]);
+ }
+ panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
+ "pid = %d, n = %d, errno = %d, status = 0x%x\n",
+ fname, pid, n, errno, status);
+ }
+}
+
+extern unsigned long current_stub_stack(void);
+
+void get_skas_faultinfo(int pid, struct faultinfo * fi)
+{
+ int err;
+
+ if(ptrace_faultinfo){
+ err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
+ if(err)
+ panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+ "errno = %d\n", errno);
+
+ /* Special handling for i386, which has different structs */
+ if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+ memset((char *)fi + sizeof(struct ptrace_faultinfo), 0,
+ sizeof(struct faultinfo) -
+ sizeof(struct ptrace_faultinfo));
+ }
+ else {
+ wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo");
+
+ /* faultinfo is prepared by the stub-segv-handler at start of
+ * the stub stack page. We just have to copy it.
+ */
+ memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
+ }
+}
+
+static void handle_segv(int pid, union uml_pt_regs * regs)
+{
+ get_skas_faultinfo(pid, &regs->skas.faultinfo);
+ segv(regs->skas.faultinfo, 0, 1, NULL);
+}
+
+/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
+{
+ int err, status;
+
+ /* Mark this as a syscall */
+ UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
+
+ if (!local_using_sysemu)
+ {
+ err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+ __NR_getpid);
+ if(err < 0)
+ panic("handle_trap - nullifying syscall failed errno = %d\n",
+ errno);
+
+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+ if(err < 0)
+ panic("handle_trap - continuing to end of syscall failed, "
+ "errno = %d\n", errno);
+
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+ if((err < 0) || !WIFSTOPPED(status) ||
+ (WSTOPSIG(status) != SIGTRAP + 0x80))
+ panic("handle_trap - failed to wait at end of syscall, "
+ "errno = %d, status = %d\n", errno, status);
+ }
+
+ handle_syscall(regs);
+}
+
+extern int __syscall_stub_start;
+
+static int userspace_tramp(void *stack)
+{
+ void *addr;
+
+ ptrace(PTRACE_TRACEME, 0, 0, 0);
+
+ init_new_thread_signals(1);
+ enable_timer();
+
+ if(!proc_mm){
+ /* 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);
+ if(addr == MAP_FAILED){
+ printk("mapping mmap stub failed, errno = %d\n",
+ errno);
+ exit(1);
+ }
+
+ if(stack != NULL){
+ 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, "
+ "errno = %d\n", errno);
+ exit(1);
+ }
+ }
+ }
+ if(!ptrace_faultinfo && (stack != NULL)){
+ unsigned long v = UML_CONFIG_STUB_CODE +
+ (unsigned long) stub_segv_handler -
+ (unsigned long) &__syscall_stub_start;
+
+ set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
+ set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
+ SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
+ SIGUSR1, -1);
+ }
+
+ os_stop_process(os_getpid());
+ return(0);
+}
+
+/* Each element set once, and only accessed by a single processor anyway */
+#undef NR_CPUS
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+int start_userspace(unsigned long stub_stack)
+{
+ void *stack;
+ unsigned long sp;
+ int pid, status, n, flags;
+
+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if(stack == MAP_FAILED)
+ panic("start_userspace : mmap failed, errno = %d", errno);
+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+
+ flags = CLONE_FILES | SIGCHLD;
+ if(proc_mm) flags |= CLONE_VM;
+ pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
+ if(pid < 0)
+ panic("start_userspace : clone failed, errno = %d", errno);
+
+ do {
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ if(n < 0)
+ panic("start_userspace : wait failed, errno = %d",
+ errno);
+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
+
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+ panic("start_userspace : expected SIGSTOP, got status = %d",
+ status);
+
+ if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
+ panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
+ errno);
+
+ if(munmap(stack, PAGE_SIZE) < 0)
+ panic("start_userspace : munmap failed, errno = %d\n", errno);
+
+ return(pid);
+}
+
+void userspace(union uml_pt_regs *regs)
+{
+ int err, status, op, pid = userspace_pid[0];
+ int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
+
+ while(1){
+ restore_registers(pid, regs);
+
+ /* Now we set local_using_sysemu to be used for one loop */
+ local_using_sysemu = get_using_sysemu();
+
+ op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
+
+ err = ptrace(op, pid, 0, 0);
+ if(err)
+ panic("userspace - could not resume userspace process, "
+ "pid=%d, ptrace operation = %d, errno = %d\n",
+ op, errno);
+
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+ if(err < 0)
+ panic("userspace - waitpid failed, errno = %d\n",
+ errno);
+
+ regs->skas.is_user = 1;
+ save_registers(pid, regs);
+ UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
+
+ if(WIFSTOPPED(status)){
+ switch(WSTOPSIG(status)){
+ case SIGSEGV:
+ if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo)
+ user_signal(SIGSEGV, regs, pid);
+ else handle_segv(pid, regs);
+ break;
+ case SIGTRAP + 0x80:
+ handle_trap(pid, regs, local_using_sysemu);
+ break;
+ case SIGTRAP:
+ relay_signal(SIGTRAP, regs);
+ break;
+ case SIGIO:
+ case SIGVTALRM:
+ case SIGILL:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGWINCH:
+ user_signal(WSTOPSIG(status), regs, pid);
+ break;
+ default:
+ printk("userspace - child stopped with signal "
+ "%d\n", WSTOPSIG(status));
+ }
+ pid = userspace_pid[0];
+ interrupt_end();
+
+ /* Avoid -ERESTARTSYS handling in host */
+ if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
+ PT_SYSCALL_NR(regs->skas.regs) = -1;
+ }
+ }
+}
+#define INIT_JMP_NEW_THREAD 0
+#define INIT_JMP_REMOVE_SIGSTACK 1
+#define INIT_JMP_CALLBACK 2
+#define INIT_JMP_HALT 3
+#define INIT_JMP_REBOOT 4
+
+int copy_context_skas0(unsigned long new_stack, int pid)
+{
+ int err;
+ unsigned long regs[MAX_REG_NR];
+ unsigned long current_stack = current_stub_stack();
+ struct stub_data *data = (struct stub_data *) current_stack;
+ struct stub_data *child_data = (struct stub_data *) new_stack;
+ __u64 new_offset;
+ int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);
+
+ /* prepare offset and fd of child's stack as argument for parent's
+ * and child's mmap2 calls
+ */
+ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset),
+ .fd = new_fd,
+ .timer = ((struct itimerval)
+ { { 0, 1000000 / hz() },
+ { 0, 1000000 / hz() }})});
+ get_safe_registers(regs);
+
+ /* Set parent's instruction pointer to start of clone-stub */
+ regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
+ (unsigned long) stub_clone_handler -
+ (unsigned long) &__syscall_stub_start;
+ regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
+ sizeof(void *);
+#ifdef __SIGNAL_FRAMESIZE
+ regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
+#endif
+ err = ptrace_setregs(pid, regs);
+ if(err < 0)
+ panic("copy_context_skas0 : PTRACE_SETREGS failed, "
+ "pid = %d, errno = %d\n", pid, errno);
+
+ /* set a well known return code for detection of child write failure */
+ child_data->err = 12345678;
+
+ /* Wait, until parent has finished its work: read child's pid from
+ * parent's stack, and check, if bad result.
+ */
+ wait_stub_done(pid, 0, "copy_context_skas0");
+
+ pid = data->err;
+ if(pid < 0)
+ panic("copy_context_skas0 - stub-parent reports error %d\n",
+ pid);
+
+ /* Wait, until child has finished too: read child's result from
+ * child's stack and check it.
+ */
+ wait_stub_done(pid, -1, "copy_context_skas0");
+ if (child_data->err != UML_CONFIG_STUB_DATA)
+ panic("copy_context_skas0 - stub-child reports error %d\n",
+ child_data->err);
+
+ if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+ (void *)PTRACE_O_TRACESYSGOOD) < 0)
+ panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
+ "errno = %d\n", errno);
+
+ return pid;
+}
+
+/*
+ * This is used only, if stub pages are needed, while proc_mm is
+ * availabl. 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;
+ __u64 code_offset;
+ int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start),
+ &code_offset);
+
+ mmop = ((struct proc_mm_op) { .op = MM_MMAP,
+ .u =
+ { .mmap =
+ { .addr = code,
+ .len = PAGE_SIZE,
+ .prot = PROT_EXEC,
+ .flags = MAP_FIXED | MAP_PRIVATE,
+ .fd = code_fd,
+ .offset = 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))
+{
+ unsigned long flags;
+ sigjmp_buf switch_buf, fork_buf;
+ int enable;
+
+ *switch_buf_ptr = &switch_buf;
+ *fork_buf_ptr = &fork_buf;
+
+ /* Somewhat subtle - siglongjmp restores the signal mask before doing
+ * the longjmp. This means that when jumping from one stack to another
+ * when the target stack has interrupts enabled, an interrupt may occur
+ * on the source stack. This is bad when starting up a process because
+ * it's not supposed to get timer ticks until it has been scheduled.
+ * So, we disable interrupts around the sigsetjmp to ensure that
+ * they can't happen until we get back here where they are safe.
+ */
+ flags = get_signals();
+ block_signals();
+ if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+ new_thread_proc(stack, handler);
+
+ remove_sigstack();
+
+ set_signals(flags);
+}
+
+void thread_wait(void *sw, void *fb)
+{
+ sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+ int enable;
+
+ *switch_buf = &buf;
+ fork_buf = fb;
+ if(UML_SIGSETJMP(&buf, enable) == 0)
+ siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
+}
+
+void switch_threads(void *me, void *next)
+{
+ sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+ int enable;
+
+ *me_ptr = &my_buf;
+ if(UML_SIGSETJMP(&my_buf, enable) == 0)
+ UML_SIGLONGJMP(next_buf, 1);
+}
+
+static sigjmp_buf initial_jmpbuf;
+
+/* XXX Make these percpu */
+static void (*cb_proc)(void *arg);
+static void *cb_arg;
+static sigjmp_buf *cb_back;
+
+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+{
+ sigjmp_buf **switch_buf = switch_buf_ptr;
+ int n, enable;
+
+ set_handler(SIGWINCH, (__sighandler_t) sig_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
+ SIGVTALRM, -1);
+
+ *fork_buf_ptr = &initial_jmpbuf;
+ n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+ switch(n){
+ case INIT_JMP_NEW_THREAD:
+ new_thread_proc((void *) stack, new_thread_handler);
+ break;
+ case INIT_JMP_REMOVE_SIGSTACK:
+ remove_sigstack();
+ break;
+ case INIT_JMP_CALLBACK:
+ (*cb_proc)(cb_arg);
+ UML_SIGLONGJMP(cb_back, 1);
+ break;
+ case INIT_JMP_HALT:
+ kmalloc_ok = 0;
+ return(0);
+ case INIT_JMP_REBOOT:
+ kmalloc_ok = 0;
+ return(1);
+ default:
+ panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
+ }
+ UML_SIGLONGJMP(*switch_buf, 1);
+}
+
+void initial_thread_cb_skas(void (*proc)(void *), void *arg)
+{
+ sigjmp_buf here;
+ int enable;
+
+ cb_proc = proc;
+ cb_arg = arg;
+ cb_back = &here;
+
+ block_signals();
+ if(UML_SIGSETJMP(&here, enable) == 0)
+ UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+ unblock_signals();
+
+ cb_proc = NULL;
+ cb_arg = NULL;
+ cb_back = NULL;
+}
+
+void halt_skas(void)
+{
+ block_signals();
+ UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+}
+
+void reboot_skas(void)
+{
+ block_signals();
+ UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+}
+
+void switch_mm_skas(struct mm_id *mm_idp)
+{
+ int err;
+
+#warning need cpu pid in switch_mm_skas
+ if(proc_mm){
+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
+ mm_idp->u.mm_fd);
+ if(err)
+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "
+ "errno = %d\n", errno);
+ }
+ else userspace_pid[0] = mm_idp->u.pid;
+}
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/os-Linux/skas/trap.c
index 9950a6716fe5..9ad5fbec4593 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/os-Linux/skas/trap.c
@@ -1,11 +1,10 @@
-/*
+/*
* Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include <signal.h>
#include <errno.h>
-#include "signal_user.h"
#include "user_util.h"
#include "kern_util.h"
#include "task.h"
@@ -14,12 +13,13 @@
#include "ptrace_user.h"
#include "sysdep/ptrace.h"
#include "sysdep/ptrace_user.h"
+#include "os.h"
void sig_handler_common_skas(int sig, void *sc_ptr)
{
struct sigcontext *sc = sc_ptr;
struct skas_regs *r;
- struct signal_info *info;
+ void (*handler)(int, union uml_pt_regs *);
int save_errno = errno;
int save_user;
@@ -34,17 +34,22 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
r = &TASK_REGS(get_current())->skas;
save_user = r->is_user;
r->is_user = 0;
- if ( sig == SIGFPE || sig == SIGSEGV ||
- sig == SIGBUS || sig == SIGILL ||
- sig == SIGTRAP ) {
- GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
- }
+ if ( sig == SIGFPE || sig == SIGSEGV ||
+ sig == SIGBUS || sig == SIGILL ||
+ sig == SIGTRAP ) {
+ GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
+ }
change_sig(SIGUSR1, 1);
- info = &sig_info[sig];
- if(!info->is_irq) unblock_signals();
- (*info->handler)(sig, (union uml_pt_regs *) r);
+ handler = sig_info[sig];
+
+ /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
+ if (sig != SIGIO && sig != SIGWINCH &&
+ sig != SIGVTALRM && sig != SIGALRM)
+ unblock_signals();
+
+ handler(sig, (union uml_pt_regs *) r);
errno = save_errno;
r->is_user = save_user;
@@ -54,25 +59,15 @@ extern int ptrace_faultinfo;
void user_signal(int sig, union uml_pt_regs *regs, int pid)
{
- struct signal_info *info;
- int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
- (sig == SIGILL) || (sig == SIGTRAP));
+ void (*handler)(int, union uml_pt_regs *);
+ int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
+ (sig == SIGILL) || (sig == SIGTRAP));
if (segv)
get_skas_faultinfo(pid, &regs->skas.faultinfo);
- info = &sig_info[sig];
- (*info->handler)(sig, regs);
+
+ handler = sig_info[sig];
+ handler(sig, (union uml_pt_regs *) regs);
unblock_signals();
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 29a9e3f43763..6c5b17ed59e1 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -24,13 +24,11 @@
#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 "mem_user.h"
-#include "time_user.h"
#include "init.h"
#include "os.h"
#include "uml-config.h"
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index cf30a39bc484..6f7626775acb 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -1,21 +1,128 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "process.h"
+#include "kern_constants.h"
+#include "os.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
+
+static void set_interval(int timer_type)
+{
+ int usec = 1000000/hz();
+ struct itimerval interval = ((struct itimerval) { { 0, usec },
+ { 0, usec } });
+
+ if(setitimer(timer_type, &interval, NULL) == -1)
+ panic("setitimer failed - errno = %d\n", errno);
+}
+
+void enable_timer(void)
+{
+ set_interval(ITIMER_VIRTUAL);
+}
+
+void disable_timer(void)
+{
+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+ if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
+ (setitimer(ITIMER_REAL, &disable, NULL) < 0))
+ printk("disnable_timer - setitimer failed, errno = %d\n",
+ errno);
+ /* If there are signals already queued, after unblocking ignore them */
+ set_handler(SIGALRM, SIG_IGN, 0, -1);
+ set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+}
+
+void switch_timers(int to_real)
+{
+ struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+ struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
+ { 0, 1000000/hz() }});
+ int old, new;
+
+ if(to_real){
+ old = ITIMER_VIRTUAL;
+ new = ITIMER_REAL;
+ }
+ else {
+ old = ITIMER_REAL;
+ new = ITIMER_VIRTUAL;
+ }
+
+ if((setitimer(old, &disable, NULL) < 0) ||
+ (setitimer(new, &enable, NULL)))
+ printk("switch_timers - setitimer failed, errno = %d\n",
+ errno);
+}
-unsigned long long os_usecs(void)
+void uml_idle_timer(void)
+{
+ if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
+ panic("Couldn't unset SIGVTALRM handler");
+
+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+ SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+ set_interval(ITIMER_REAL);
+}
+
+extern void ktime_get_ts(struct timespec *ts);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
+
+void time_init(void)
+{
+ struct timespec now;
+
+ if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
+ panic("Couldn't set SIGVTALRM handler");
+ set_interval(ITIMER_VIRTUAL);
+
+ do_posix_clock_monotonic_gettime(&now);
+ wall_to_monotonic.tv_sec = -now.tv_sec;
+ wall_to_monotonic.tv_nsec = -now.tv_nsec;
+}
+
+unsigned long long os_nsecs(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
- return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
+ return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000);
}
-/*
- * 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:
- */
+void idle_sleep(int secs)
+{
+ struct timespec ts;
+
+ ts.tv_sec = secs;
+ ts.tv_nsec = 0;
+ nanosleep(&ts, NULL);
+}
+
+/* XXX This partly duplicates init_irq_signals */
+
+void user_time_init(void)
+{
+ set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+ SIGALRM, SIGUSR2, -1);
+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+ SIGVTALRM, SIGUSR2, -1);
+ set_interval(ITIMER_VIRTUAL);
+}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
new file mode 100644
index 000000000000..a9f6b26f9828
--- /dev/null
+++ b/arch/um/os-Linux/trap.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <setjmp.h>
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "mode.h"
+#include "longjmp.h"
+
+void usr2_handler(int sig, union uml_pt_regs *regs)
+{
+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
+}
+
+void (*sig_info[NSIG])(int, union uml_pt_regs *);
+
+void os_fill_handlinfo(struct kern_handlers h)
+{
+ sig_info[SIGTRAP] = h.relay_signal;
+ sig_info[SIGFPE] = h.relay_signal;
+ sig_info[SIGILL] = h.relay_signal;
+ sig_info[SIGWINCH] = h.winch;
+ sig_info[SIGBUS] = h.bus_handler;
+ sig_info[SIGSEGV] = h.page_fault;
+ sig_info[SIGIO] = h.sigio_handler;
+ sig_info[SIGVTALRM] = h.timer_handler;
+ sig_info[SIGALRM] = h.timer_handler;
+ sig_info[SIGUSR2] = usr2_handler;
+}
+
+void do_longjmp(void *b, int val)
+{
+ sigjmp_buf *buf = b;
+
+ UML_SIGLONGJMP(buf, val);
+}
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c
index a6db8877931a..919d19f11537 100644
--- a/arch/um/os-Linux/tt.c
+++ b/arch/um/os-Linux/tt.c
@@ -23,12 +23,10 @@
#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"
@@ -50,6 +48,68 @@ int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
return(0);
}
+void kill_child_dead(int pid)
+{
+ kill(pid, SIGKILL);
+ kill(pid, SIGCONT);
+ do {
+ int n;
+ CATCH_EINTR(n = waitpid(pid, NULL, 0));
+ if (n > 0)
+ kill(pid, SIGCONT);
+ else
+ break;
+ } while(1);
+}
+
+void stop(void)
+{
+ while(1) sleep(1000000);
+}
+
+int wait_for_stop(int pid, int sig, int cont_type, void *relay)
+{
+ sigset_t *relay_signals = relay;
+ int status, ret;
+
+ while(1){
+ CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
+ if((ret < 0) ||
+ !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
+ if(ret < 0){
+ printk("wait failed, errno = %d\n",
+ errno);
+ }
+ else if(WIFEXITED(status))
+ printk("process %d exited with status %d\n",
+ pid, WEXITSTATUS(status));
+ else if(WIFSIGNALED(status))
+ printk("process %d exited with signal %d\n",
+ pid, WTERMSIG(status));
+ else if((WSTOPSIG(status) == SIGVTALRM) ||
+ (WSTOPSIG(status) == SIGALRM) ||
+ (WSTOPSIG(status) == SIGIO) ||
+ (WSTOPSIG(status) == SIGPROF) ||
+ (WSTOPSIG(status) == SIGCHLD) ||
+ (WSTOPSIG(status) == SIGWINCH) ||
+ (WSTOPSIG(status) == SIGINT)){
+ ptrace(cont_type, pid, 0, WSTOPSIG(status));
+ continue;
+ }
+ else if((relay_signals != NULL) &&
+ sigismember(relay_signals, WSTOPSIG(status))){
+ ptrace(cont_type, pid, 0, WSTOPSIG(status));
+ continue;
+ }
+ else printk("process %d stopped with signal %d\n",
+ pid, WSTOPSIG(status));
+ panic("wait_for_stop failed to wait for %d to stop "
+ "with %d\n", pid, sig);
+ }
+ return(status);
+ }
+}
+
/*
*-------------------------
* only for tt mode (will be deleted in future...)
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d710158c3d..166fb66995df 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
#include <setjmp.h>
#include <string.h>
+#include "longjmp.h"
unsigned long __do_user_copy(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
int n), int *faulted_out)
{
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
+ int enable;
sigjmp_buf jbuf;
*fault_catcher = &jbuf;
- if(sigsetjmp(jbuf, 1) == 0){
+ if(UML_SIGSETJMP(&jbuf, enable) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
new file mode 100644
index 000000000000..ecf107ae5ac8
--- /dev/null
+++ b/arch/um/os-Linux/umid.c
@@ -0,0 +1,335 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <dirent.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include "init.h"
+#include "os.h"
+#include "user.h"
+#include "mode.h"
+
+#define UML_DIR "~/.uml/"
+
+#define UMID_LEN 64
+
+/* Changed by set_umid, which is run early in boot */
+char umid[UMID_LEN] = { 0 };
+
+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
+static char *uml_dir = UML_DIR;
+
+static int __init make_uml_dir(void)
+{
+ char dir[512] = { '\0' };
+ int len, err;
+
+ if(*uml_dir == '~'){
+ char *home = getenv("HOME");
+
+ err = -ENOENT;
+ if(home == NULL){
+ printk("make_uml_dir : no value in environment for "
+ "$HOME\n");
+ goto err;
+ }
+ strlcpy(dir, home, sizeof(dir));
+ uml_dir++;
+ }
+ strlcat(dir, uml_dir, sizeof(dir));
+ len = strlen(dir);
+ if (len > 0 && dir[len - 1] != '/')
+ strlcat(dir, "/", sizeof(dir));
+
+ err = -ENOMEM;
+ uml_dir = malloc(strlen(dir) + 1);
+ if (uml_dir == NULL) {
+ printf("make_uml_dir : malloc failed, errno = %d\n", errno);
+ goto err;
+ }
+ strcpy(uml_dir, dir);
+
+ if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
+ printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno));
+ err = -errno;
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ free(uml_dir);
+err:
+ uml_dir = NULL;
+ return err;
+}
+
+static int actually_do_remove(char *dir)
+{
+ DIR *directory;
+ struct dirent *ent;
+ int len;
+ char file[256];
+
+ directory = opendir(dir);
+ if(directory == NULL)
+ return -errno;
+
+ while((ent = readdir(directory)) != NULL){
+ if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
+ continue;
+ len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
+ if(len > sizeof(file))
+ return -E2BIG;
+
+ sprintf(file, "%s/%s", dir, ent->d_name);
+ if(unlink(file) < 0)
+ return -errno;
+ }
+ if(rmdir(dir) < 0)
+ return -errno;
+
+ return 0;
+}
+
+/* This says that there isn't already a user of the specified directory even if
+ * there are errors during the checking. This is because if these errors
+ * happen, the directory is unusable by the pre-existing UML, so we might as
+ * well take it over. This could happen either by
+ * the existing UML somehow corrupting its umid directory
+ * something other than UML sticking stuff in the directory
+ * this boot racing with a shutdown of the other UML
+ * In any of these cases, the directory isn't useful for anything else.
+ */
+
+static int not_dead_yet(char *dir)
+{
+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
+ char pid[sizeof("nnnnn\0")], *end;
+ int dead, fd, p, n, err;
+
+ n = snprintf(file, sizeof(file), "%s/pid", dir);
+ if(n >= sizeof(file)){
+ printk("not_dead_yet - pid filename too long\n");
+ err = -E2BIG;
+ goto out;
+ }
+
+ dead = 0;
+ fd = open(file, O_RDONLY);
+ if(fd < 0){
+ if(fd != -ENOENT){
+ printk("not_dead_yet : couldn't open pid file '%s', "
+ "err = %d\n", file, -fd);
+ }
+ goto out;
+ }
+
+ err = 0;
+ n = read(fd, pid, sizeof(pid));
+ if(n <= 0){
+ printk("not_dead_yet : couldn't read pid file '%s', "
+ "err = %d\n", file, -n);
+ goto out_close;
+ }
+
+ p = strtoul(pid, &end, 0);
+ if(end == pid){
+ printk("not_dead_yet : couldn't parse pid file '%s', "
+ "errno = %d\n", file, errno);
+ goto out_close;
+ }
+
+ if((kill(p, 0) == 0) || (errno != ESRCH))
+ return 1;
+
+ err = actually_do_remove(dir);
+ if(err)
+ printk("not_dead_yet - actually_do_remove failed with "
+ "err = %d\n", err);
+
+ return err;
+
+ out_close:
+ close(fd);
+ out:
+ return 0;
+}
+
+static void __init create_pid_file(void)
+{
+ char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
+ char pid[sizeof("nnnnn\0")];
+ int fd, n;
+
+ if(umid_file_name("pid", file, sizeof(file)))
+ return;
+
+ fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
+ if(fd < 0){
+ printk("Open of machine pid file \"%s\" failed: %s\n",
+ file, strerror(-fd));
+ return;
+ }
+
+ snprintf(pid, sizeof(pid), "%d\n", getpid());
+ n = write(fd, pid, strlen(pid));
+ if(n != strlen(pid))
+ printk("Write of pid file failed - err = %d\n", -n);
+
+ close(fd);
+}
+
+int __init set_umid(char *name)
+{
+ if(strlen(name) > UMID_LEN - 1)
+ return -E2BIG;
+
+ strlcpy(umid, name, sizeof(umid));
+
+ return 0;
+}
+
+static int umid_setup = 0;
+
+int __init make_umid(void)
+{
+ int fd, err;
+ char tmp[256];
+
+ if(umid_setup)
+ return 0;
+
+ make_uml_dir();
+
+ if(*umid == '\0'){
+ strlcpy(tmp, uml_dir, sizeof(tmp));
+ strlcat(tmp, "XXXXXX", sizeof(tmp));
+ fd = mkstemp(tmp);
+ if(fd < 0){
+ printk("make_umid - mkstemp(%s) failed: %s\n",
+ tmp, strerror(errno));
+ err = -errno;
+ goto err;
+ }
+
+ close(fd);
+
+ set_umid(&tmp[strlen(uml_dir)]);
+
+ /* There's a nice tiny little race between this unlink and
+ * the mkdir below. It'd be nice if there were a mkstemp
+ * for directories.
+ */
+ if(unlink(tmp)){
+ err = -errno;
+ goto err;
+ }
+ }
+
+ snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid);
+ err = mkdir(tmp, 0777);
+ if(err < 0){
+ err = -errno;
+ if(errno != EEXIST)
+ goto err;
+
+ if(not_dead_yet(tmp) < 0)
+ goto err;
+
+ err = mkdir(tmp, 0777);
+ }
+ if(err < 0){
+ printk("Failed to create '%s' - err = %d\n", umid, err);
+ goto err_rmdir;
+ }
+
+ umid_setup = 1;
+
+ create_pid_file();
+
+ return 0;
+
+ err_rmdir:
+ rmdir(tmp);
+ err:
+ return err;
+}
+
+static int __init make_umid_init(void)
+{
+ make_umid();
+
+ return 0;
+}
+
+__initcall(make_umid_init);
+
+int __init umid_file_name(char *name, char *buf, int len)
+{
+ int n, err;
+
+ err = make_umid();
+ if(err)
+ return err;
+
+ n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name);
+ if(n >= len){
+ printk("umid_file_name : buffer too short\n");
+ return -E2BIG;
+ }
+
+ return 0;
+}
+
+char *get_umid(void)
+{
+ return umid;
+}
+
+static int __init set_uml_dir(char *name, int *add)
+{
+ if(*name == '\0'){
+ printf("uml_dir can't be an empty string\n");
+ return 0;
+ }
+
+ if(name[strlen(name) - 1] == '/'){
+ uml_dir = name;
+ return 0;
+ }
+
+ uml_dir = malloc(strlen(name) + 2);
+ if(uml_dir == NULL){
+ printf("Failed to malloc uml_dir - error = %d\n", errno);
+
+ /* Return 0 here because do_initcalls doesn't look at
+ * the return value.
+ */
+ return 0;
+ }
+ sprintf(uml_dir, "%s/", name);
+
+ return 0;
+}
+
+__uml_setup("uml_dir=", set_uml_dir,
+"uml_dir=<directory>\n"
+" The location to place the pid and umid files.\n\n"
+);
+
+static void remove_umid_dir(void)
+{
+ char dir[strlen(uml_dir) + UMID_LEN + 1], err;
+
+ sprintf(dir, "%s%s", uml_dir, umid);
+ err = actually_do_remove(dir);
+ if(err)
+ printf("remove_umid_dir - actually_do_remove failed with "
+ "err = %d\n", err);
+}
+
+__uml_exitcall(remove_umid_dir);
diff --git a/arch/um/kernel/user_util.c b/arch/um/os-Linux/util.c
index 4c231161f257..e32065e2fdc8 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/os-Linux/util.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -29,17 +29,14 @@
#include "init.h"
#include "ptrace_user.h"
#include "uml-config.h"
-
-void stop(void)
-{
- while(1) sleep(1000000);
-}
+#include "os.h"
+#include "longjmp.h"
void stack_protections(unsigned long address)
{
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
- if(mprotect((void *) address, page_size(), prot) < 0)
+ if(mprotect((void *) address, page_size(), prot) < 0)
panic("protecting stack failed, errno = %d", errno);
}
@@ -59,49 +56,6 @@ void task_protections(unsigned long address)
panic("protecting stack failed, errno = %d", errno);
}
-int wait_for_stop(int pid, int sig, int cont_type, void *relay)
-{
- sigset_t *relay_signals = relay;
- int status, ret;
-
- while(1){
- CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
- if((ret < 0) ||
- !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
- if(ret < 0){
- printk("wait failed, errno = %d\n",
- errno);
- }
- else if(WIFEXITED(status))
- printk("process %d exited with status %d\n",
- pid, WEXITSTATUS(status));
- else if(WIFSIGNALED(status))
- printk("process %d exited with signal %d\n",
- pid, WTERMSIG(status));
- else if((WSTOPSIG(status) == SIGVTALRM) ||
- (WSTOPSIG(status) == SIGALRM) ||
- (WSTOPSIG(status) == SIGIO) ||
- (WSTOPSIG(status) == SIGPROF) ||
- (WSTOPSIG(status) == SIGCHLD) ||
- (WSTOPSIG(status) == SIGWINCH) ||
- (WSTOPSIG(status) == SIGINT)){
- ptrace(cont_type, pid, 0, WSTOPSIG(status));
- continue;
- }
- else if((relay_signals != NULL) &&
- sigismember(relay_signals, WSTOPSIG(status))){
- ptrace(cont_type, pid, 0, WSTOPSIG(status));
- continue;
- }
- else printk("process %d stopped with signal %d\n",
- pid, WSTOPSIG(status));
- panic("wait_for_stop failed to wait for %d to stop "
- "with %d\n", pid, sig);
- }
- return(status);
- }
-}
-
int raw(int fd)
{
struct termios tt;
@@ -113,7 +67,7 @@ int raw(int fd)
cfmakeraw(&tt);
- CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
+ CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
if(err < 0)
return -errno;
@@ -149,7 +103,7 @@ void setup_hostinfo(void)
int setjmp_wrapper(void (*proc)(void *, void *), ...)
{
- va_list args;
+ va_list args;
sigjmp_buf buf;
int n;
@@ -161,14 +115,3 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
va_end(args);
return(n);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 17746b4c08ff..0cdfd4481d5e 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -16,6 +16,8 @@
#include "choose-mode.h"
#include "kern.h"
#include "mode_kern.h"
+#include "proc_mm.h"
+#include "os.h"
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
@@ -456,13 +458,14 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
int i;
long page, err=0;
void *addr = NULL;
+ struct proc_mm_op copy;
- memset(&desc, 0, sizeof(desc));
if(!ptrace_ldt)
init_MUTEX(&new_mm->ldt.semaphore);
if(!from_mm){
+ memset(&desc, 0, sizeof(desc));
/*
* We have to initialize a clean ldt.
*/
@@ -494,8 +497,26 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
}
}
new_mm->ldt.entry_count = 0;
+
+ goto out;
}
- else if (!ptrace_ldt) {
+
+ if(proc_mm){
+ /* We have a valid from_mm, so we now have to copy the LDT of
+ * from_mm to new_mm, because using proc_mm an new mm with
+ * an empty/default LDT was created in new_mm()
+ */
+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
+ .u =
+ { .copy_segments =
+ from_mm->id.u.mm_fd } } );
+ i = os_write_file(new_mm->id.u.mm_fd, &copy, sizeof(copy));
+ if(i != sizeof(copy))
+ printk("new_mm : /proc/mm copy_segments failed, "
+ "err = %d\n", -i);
+ }
+
+ if(!ptrace_ldt) {
/* Our local LDT is used to supply the data for
* modify_ldt(READLDT), if PTRACE_LDT isn't available,
* i.e., we have to use the stub for modify_ldt, which
@@ -524,6 +545,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm,
up(&from_mm->ldt.semaphore);
}
+ out:
return err;
}
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 16bc19928b3c..7cd1a82dc8c2 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -10,7 +10,6 @@
#include "asm/uaccess.h"
#include "asm/unistd.h"
#include "frame_kern.h"
-#include "signal_user.h"
#include "sigcontext.h"
#include "registers.h"
#include "mode.h"
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 310865903234..04494638b963 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -10,9 +10,6 @@ mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration"
config MMU
bool
default n
-config UID16
- bool
- default n
config RWSEM_GENERIC_SPINLOCK
bool
default y
diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c
index 39cf247cdae4..eb909937958b 100644
--- a/arch/v850/kernel/process.c
+++ b/arch/v850/kernel/process.c
@@ -114,7 +114,7 @@ int copy_thread (int nr, unsigned long clone_flags,
struct task_struct *p, struct pt_regs *regs)
{
/* Start pushing stuff from the top of the child's kernel stack. */
- unsigned long orig_ksp = (unsigned long)p->thread_info + THREAD_SIZE;
+ unsigned long orig_ksp = task_tos(p);
unsigned long ksp = orig_ksp;
/* We push two `state save' stack fames (see entry.S) on the new
kernel stack:
@@ -164,30 +164,6 @@ int copy_thread (int nr, unsigned long clone_flags,
}
/*
- * fill in the user structure for a core dump..
- */
-void dump_thread (struct pt_regs *regs, struct user *dump)
-{
-#if 0 /* Later. XXX */
- dump->magic = CMAGIC;
- dump->start_code = 0;
- dump->start_stack = regs->gpr[GPR_SP];
- dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
- dump->u_dsize = ((unsigned long) (current->mm->brk +
- (PAGE_SIZE-1))) >> PAGE_SHIFT;
- dump->u_dsize -= dump->u_tsize;
- dump->u_ssize = 0;
-
- if (dump->start_stack < TASK_SIZE)
- dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
-
- dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
- dump->regs = *regs;
- dump->u_fpvalid = 0;
-#endif
-}
-
-/*
* sys_execve() executes a new program.
*/
int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs)
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index 18492d02aaf6..67e057509664 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -58,7 +58,7 @@ static v850_reg_t *reg_save_addr (unsigned reg_offs, struct task_struct *t)
regs = thread_saved_regs (t);
else
/* Register saved during kernel entry (or not available). */
- regs = task_regs (t);
+ regs = task_pt_regs (t);
return (v850_reg_t *)((char *)regs + reg_offs);
}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 0ca64900dd91..8ffc29c1c89d 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -21,8 +21,6 @@ extern void *trap_table;
EXPORT_SYMBOL (trap_table);
/* platform dependent support */
-extern void dump_thread (struct pt_regs *, struct user *);
-EXPORT_SYMBOL (dump_thread);
EXPORT_SYMBOL (kernel_thread);
EXPORT_SYMBOL (enable_irq);
EXPORT_SYMBOL (disable_irq);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 6ece645e4dbe..2f9deca31cc9 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -69,12 +69,34 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
+config DMI
+ bool
+ default y
+
source "init/Kconfig"
menu "Processor type and features"
choice
+ prompt "Subarchitecture Type"
+ default X86_PC
+
+config X86_PC
+ bool "PC-compatible"
+ help
+ Choose this option if your computer is a standard PC or compatible.
+
+config X86_VSMP
+ bool "Support for ScaleMP vSMP"
+ help
+ Support for ScaleMP vSMP systems. Say 'Y' here if this kernel is
+ supposed to run on these EM64T-based machines. Only choose this option
+ if you have one of these machines.
+
+endchoice
+
+choice
prompt "Processor family"
default MK8
@@ -283,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT
config ARCH_SPARSEMEM_ENABLE
def_bool y
- depends on NUMA
+ depends on (NUMA || EXPERIMENTAL)
+
+config ARCH_MEMORY_PROBE
+ def_bool y
+ depends on MEMORY_HOTPLUG
config ARCH_FLATMEM_ENABLE
def_bool y
@@ -293,6 +319,7 @@ source "mm/Kconfig"
config HAVE_ARCH_EARLY_PFN_TO_NID
def_bool y
+ depends on NUMA
config NR_CPUS
int "Maximum number of CPUs (2-256)"
@@ -328,7 +355,7 @@ config HPET_TIMER
<http://www.intel.com/hardwaredesign/hpetspec.htm>.
config X86_PM_TIMER
- bool "PM timer"
+ bool "PM timer" if EMBEDDED
depends on ACPI
default y
help
@@ -347,32 +374,24 @@ config HPET_EMULATE_RTC
depends on HPET_TIMER && RTC=y
config GART_IOMMU
- bool "IOMMU support"
+ bool "K8 GART IOMMU support"
default y
+ select SWIOTLB
depends on PCI
help
Support the IOMMU. Needed to run systems with more than 3GB of memory
properly with 32-bit PCI devices that do not support DAC (Double Address
Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter.
Normally the kernel will take the right choice by itself.
- This option includes a driver for the AMD Opteron/Athlon64 IOMMU
- and a software emulation used on some other systems.
+ This option includes a driver for the AMD Opteron/Athlon64 northbridge IOMMU
+ and a software emulation used on other systems.
If unsure, say Y.
# need this always enabled with GART_IOMMU for the VIA workaround
config SWIOTLB
- bool
- depends on GART_IOMMU
- default y
-
-config DUMMY_IOMMU
bool
- depends on !GART_IOMMU && !SWIOTLB
default y
- help
- Don't use IOMMU code. This will cause problems when you have more than 4GB
- of memory and any 32-bit devices. Don't turn on unless you know what you
- are doing.
+ depends on GART_IOMMU
config X86_MCE
bool "Machine check support" if EMBEDDED
@@ -399,17 +418,6 @@ config X86_MCE_AMD
Additional support for AMD specific MCE features such as
the DRAM Error Threshold.
-config PHYSICAL_START
- hex "Physical address where the kernel is loaded" if EMBEDDED
- default "0x100000"
- help
- This gives the physical address where the kernel is loaded.
- Primarily used in the case of kexec on panic where the
- fail safe kernel needs to run at a different address than
- the panic-ed kernel.
-
- Don't change this unless you know what you are doing.
-
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on EXPERIMENTAL
@@ -427,6 +435,31 @@ config KEXEC
support. As of this writing the exact hardware interface is
strongly in flux, so no good recommendation can be made.
+config CRASH_DUMP
+ bool "kernel crash dumps (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Generate crash dump after being started by kexec.
+
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
+ default "0x1000000" if CRASH_DUMP
+ default "0x100000"
+ help
+ This gives the physical address where the kernel is loaded. Normally
+ for regular kernels this value is 0x100000 (1MB). But in the case
+ of kexec on panic the fail safe kernel needs to run at a different
+ address than the panic-ed kernel. This option is used to set the load
+ address for kernels used to capture crash dump on being kexec'ed
+ after panic. The default value for crash dump kernels is
+ 0x1000000 (16MB). This can also be set based on the "X" value as
+ specified in the "crashkernel=YM@XM" command line boot parameter
+ passed to the panic-ed kernel. Typically this parameter is set as
+ crashkernel=64M@16M. Please take a look at
+ Documentation/kdump/kdump.txt for more details about crash dumps.
+
+ Don't change this unless you know what you are doing.
+
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
@@ -542,11 +575,6 @@ config SYSVIPC_COMPAT
depends on COMPAT && SYSVIPC
default y
-config UID16
- bool
- depends on IA32_EMULATION
- default y
-
endmenu
source "net/Kconfig"
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
index e2c6e64a85ec..fcb06a50fdd2 100644
--- a/arch/x86_64/Kconfig.debug
+++ b/arch/x86_64/Kconfig.debug
@@ -9,6 +9,16 @@ config INIT_DEBUG
Fill __init and __initdata at the end of boot. This helps debugging
illegal uses of __init and __initdata after initialization.
+config DEBUG_RODATA
+ bool "Write protect kernel read-only data structures"
+ depends on DEBUG_KERNEL
+ help
+ Mark the kernel read-only data as write-protected in the pagetables,
+ in order to catch accidental (and incorrect) writes to such const data.
+ This option may have a slight performance impact because a portion
+ of the kernel code won't be covered by a 2MB TLB anymore.
+ If in doubt, say "N".
+
config IOMMU_DEBUG
depends on GART_IOMMU && DEBUG_KERNEL
bool "Enable IOMMU debugging"
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index a9cd42e61828..d7fd46479c55 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -31,6 +31,7 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
CFLAGS += $(cflags-y)
+CFLAGS += -m64
CFLAGS += -mno-red-zone
CFLAGS += -mcmodel=kernel
CFLAGS += -pipe
@@ -38,8 +39,10 @@ CFLAGS += -pipe
# actually it makes the kernel smaller too.
CFLAGS += -fno-reorder-blocks
CFLAGS += -Wno-sign-compare
-ifneq ($(CONFIG_DEBUG_INFO),y)
+ifneq ($(CONFIG_UNWIND_INFO),y)
CFLAGS += -fno-asynchronous-unwind-tables
+endif
+ifneq ($(CONFIG_DEBUG_INFO),y)
# -fweb shrinks the kernel a bit, but the difference is very small
# it also messes up debugging, so don't use it for now.
#CFLAGS += $(call cc-option,-fweb)
@@ -50,6 +53,8 @@ CFLAGS += $(call cc-option,-funit-at-a-time)
# prevent gcc from generating any FP code by mistake
CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+AFLAGS += -m64
+
head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
libs-y += arch/x86_64/lib/
@@ -80,9 +85,12 @@ bzlilo: vmlinux
bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
-install fdimage fdimage144 fdimage288: vmlinux
+fdimage fdimage144 fdimage288: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+install:
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/x86_64/boot/.gitignore b/arch/x86_64/boot/.gitignore
new file mode 100644
index 000000000000..495f20c085de
--- /dev/null
+++ b/arch/x86_64/boot/.gitignore
@@ -0,0 +1,3 @@
+bootsect
+bzImage
+setup
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index 18c6e915d69b..29f8396ed151 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -98,5 +98,5 @@ zlilo: $(BOOTIMAGE)
cp System.map $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-install: $(BOOTIMAGE)
+install:
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index 0e10fd84c7cc..cf4b88c416dc 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -9,7 +9,7 @@
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
*/
-#include "miscsetup.h"
+#include <linux/screen_info.h>
#include <asm/io.h>
#include <asm/page.h>
diff --git a/arch/x86_64/boot/compressed/miscsetup.h b/arch/x86_64/boot/compressed/miscsetup.h
deleted file mode 100644
index bb1620531703..000000000000
--- a/arch/x86_64/boot/compressed/miscsetup.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#define NULL 0
-//typedef unsigned int size_t;
-
-
-struct screen_info {
- unsigned char orig_x; /* 0x00 */
- unsigned char orig_y; /* 0x01 */
- unsigned short dontuse1; /* 0x02 -- EXT_MEM_K sits here */
- unsigned short orig_video_page; /* 0x04 */
- unsigned char orig_video_mode; /* 0x06 */
- unsigned char orig_video_cols; /* 0x07 */
- unsigned short unused2; /* 0x08 */
- unsigned short orig_video_ega_bx; /* 0x0a */
- unsigned short unused3; /* 0x0c */
- unsigned char orig_video_lines; /* 0x0e */
- unsigned char orig_video_isVGA; /* 0x0f */
- unsigned short orig_video_points; /* 0x10 */
-
- /* VESA graphic mode -- linear frame buffer */
- unsigned short lfb_width; /* 0x12 */
- unsigned short lfb_height; /* 0x14 */
- unsigned short lfb_depth; /* 0x16 */
- unsigned long lfb_base; /* 0x18 */
- unsigned long lfb_size; /* 0x1c */
- unsigned short dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
- unsigned short lfb_linelength; /* 0x24 */
- unsigned char red_size; /* 0x26 */
- unsigned char red_pos; /* 0x27 */
- unsigned char green_size; /* 0x28 */
- unsigned char green_pos; /* 0x29 */
- unsigned char blue_size; /* 0x2a */
- unsigned char blue_pos; /* 0x2b */
- unsigned char rsvd_size; /* 0x2c */
- unsigned char rsvd_pos; /* 0x2d */
- unsigned short vesapm_seg; /* 0x2e */
- unsigned short vesapm_off; /* 0x30 */
- unsigned short pages; /* 0x32 */
- /* 0x34 -- 0x3f reserved for future expansion */
-};
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
index 198af15a7758..baaa2369bdb8 100644
--- a/arch/x86_64/boot/install.sh
+++ b/arch/x86_64/boot/install.sh
@@ -1,40 +1,2 @@
#!/bin/sh
-#
-# arch/x86_64/boot/install.sh
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1995 by Linus Torvalds
-#
-# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
-#
-# "make install" script for i386 architecture
-#
-# Arguments:
-# $1 - kernel version
-# $2 - kernel image file
-# $3 - kernel map file
-# $4 - default install path (blank if root directory)
-#
-
-# User may have a custom install script
-
-if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
-if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
-
-# Default install - same as make zlilo
-
-if [ -f $4/vmlinuz ]; then
- mv $4/vmlinuz $4/vmlinuz.old
-fi
-
-if [ -f $4/System.map ]; then
- mv $4/System.map $4/System.old
-fi
-
-cat $2 > $4/vmlinuz
-cp $3 $4/System.map
-
-if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+. $srctree/arch/i386/boot/install.sh
diff --git a/arch/x86_64/boot/tools/.gitignore b/arch/x86_64/boot/tools/.gitignore
new file mode 100644
index 000000000000..378eac25d311
--- /dev/null
+++ b/arch/x86_64/boot/tools/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c
index acfdaa28791e..fb1b961a2e2f 100644
--- a/arch/x86_64/crypto/aes.c
+++ b/arch/x86_64/crypto/aes.c
@@ -74,8 +74,6 @@ static inline u8 byte(const u32 x, const unsigned n)
return x >> (n << 3);
}
-#define u32_in(x) le32_to_cpu(*(const __le32 *)(x))
-
struct aes_ctx
{
u32 key_length;
@@ -234,6 +232,7 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len,
u32 *flags)
{
struct aes_ctx *ctx = ctx_arg;
+ const __le32 *key = (const __le32 *)in_key;
u32 i, j, t, u, v, w;
if (key_len != 16 && key_len != 24 && key_len != 32) {
@@ -243,10 +242,10 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len,
ctx->key_length = key_len;
- D_KEY[key_len + 24] = E_KEY[0] = u32_in(in_key);
- D_KEY[key_len + 25] = E_KEY[1] = u32_in(in_key + 4);
- D_KEY[key_len + 26] = E_KEY[2] = u32_in(in_key + 8);
- D_KEY[key_len + 27] = E_KEY[3] = u32_in(in_key + 12);
+ D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]);
+ D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]);
+ D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]);
+ D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]);
switch (key_len) {
case 16:
@@ -256,17 +255,17 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len,
break;
case 24:
- E_KEY[4] = u32_in(in_key + 16);
- t = E_KEY[5] = u32_in(in_key + 20);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ t = E_KEY[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
- E_KEY[4] = u32_in(in_key + 16);
- E_KEY[5] = u32_in(in_key + 20);
- E_KEY[6] = u32_in(in_key + 24);
- t = E_KEY[7] = u32_in(in_key + 28);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ E_KEY[5] = le32_to_cpu(key[5]);
+ E_KEY[6] = le32_to_cpu(key[6]);
+ t = E_KEY[7] = le32_to_cpu(key[7]);
for (i = 0; i < 7; ++i)
loop8(i);
break;
@@ -290,6 +289,8 @@ extern void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in);
static struct crypto_alg aes_alg = {
.cra_name = "aes",
+ .cra_driver_name = "aes-x86_64",
+ .cra_priority = 200,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 5d56542fb68f..09a3eb743315 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.14-git7
-# Sat Nov 5 15:55:50 2005
+# Linux kernel version: 2.6.15-git12
+# Mon Jan 16 13:09:08 2006
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -15,6 +15,7 @@ CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_DMI=y
#
# Code maturity level options
@@ -35,18 +36,21 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_VM86=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -55,8 +59,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -71,8 +77,28 @@ CONFIG_OBSOLETE_MODPARM=y
CONFIG_STOP_MACHINE=y
#
+# Block layer
+#
+CONFIG_LBD=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
# Processor type and features
#
+CONFIG_X86_PC=y
+# CONFIG_X86_VSMP is not set
# CONFIG_MK8 is not set
# CONFIG_MPSC is not set
CONFIG_GENERIC_CPU=y
@@ -89,14 +115,14 @@ CONFIG_X86_LOCAL_APIC=y
CONFIG_MTRR=y
CONFIG_SMP=y
CONFIG_SCHED_SMT=y
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
CONFIG_PREEMPT_BKL=y
CONFIG_NUMA=y
CONFIG_K8_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
-# CONFIG_NUMA_EMU is not set
+CONFIG_NUMA_EMU=y
CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
@@ -109,6 +135,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_NEED_MULTIPLE_NODES=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
CONFIG_NR_CPUS=32
CONFIG_HOTPLUG_CPU=y
@@ -120,8 +147,9 @@ CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
CONFIG_X86_MCE_INTEL=y
CONFIG_X86_MCE_AMD=y
-CONFIG_PHYSICAL_START=0x100000
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x100000
CONFIG_SECCOMP=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
@@ -136,6 +164,7 @@ CONFIG_GENERIC_PENDING_IRQ=y
# Power management options
#
CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_SOFTWARE_SUSPEND=y
CONFIG_PM_STD_PARTITION=""
@@ -152,7 +181,7 @@ CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
# CONFIG_ACPI_VIDEO is not set
-CONFIG_ACPI_HOTKEY=m
+# CONFIG_ACPI_HOTKEY is not set
CONFIG_ACPI_FAN=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_HOTPLUG_CPU=y
@@ -205,7 +234,7 @@ CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_UNORDERED_IO=y
-# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCIEPORTBUS=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_DEBUG is not set
@@ -229,7 +258,6 @@ CONFIG_IA32_EMULATION=y
CONFIG_IA32_AOUT=y
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
-CONFIG_UID16=y
#
# Networking
@@ -291,11 +319,19 @@ CONFIG_IPV6=y
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
@@ -315,7 +351,7 @@ CONFIG_IPV6=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
#
@@ -356,21 +392,7 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
-CONFIG_LBD=y
# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-CONFIG_DEFAULT_DEADLINE=y
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_ATA_OVER_ETH is not set
#
@@ -410,7 +432,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y
-# CONFIG_BLK_DEV_ATIIXP is not set
+CONFIG_BLK_DEV_ATIIXP=y
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set
@@ -458,20 +480,21 @@ CONFIG_BLK_DEV_SD=y
# 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_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
#
# SCSI Transport Attributes
#
CONFIG_SCSI_SPI_ATTRS=y
-# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_ISCSI_ATTRS is not set
# CONFIG_SCSI_SAS_ATTRS is not set
#
# SCSI low-level drivers
#
+# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -485,11 +508,13 @@ CONFIG_AIC79XX_RESET_DELAY_MS=4000
# CONFIG_AIC79XX_DEBUG_ENABLE is not set
CONFIG_AIC79XX_DEBUG_MASK=0
# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
-# CONFIG_MEGARAID_NEWGEN is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=y
+CONFIG_MEGARAID_MAILBOX=y
# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_MEGARAID_SAS is not set
+CONFIG_MEGARAID_SAS=y
CONFIG_SCSI_SATA=y
-# CONFIG_SCSI_SATA_AHCI is not set
+CONFIG_SCSI_SATA_AHCI=y
# CONFIG_SCSI_SATA_SVW is not set
CONFIG_SCSI_ATA_PIIX=y
# CONFIG_SCSI_SATA_MV is not set
@@ -498,7 +523,7 @@ CONFIG_SCSI_SATA_NV=y
# CONFIG_SCSI_SATA_QSTOR is not set
# CONFIG_SCSI_SATA_PROMISE is not set
# CONFIG_SCSI_SATA_SX4 is not set
-# CONFIG_SCSI_SATA_SIL is not set
+CONFIG_SCSI_SATA_SIL=y
# CONFIG_SCSI_SATA_SIL24 is not set
# CONFIG_SCSI_SATA_SIS is not set
# CONFIG_SCSI_SATA_ULI is not set
@@ -517,13 +542,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
# 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_QLA_FC is not set
# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
@@ -627,12 +646,14 @@ CONFIG_8139TOO=y
# CONFIG_DL2K is not set
CONFIG_E1000=y
# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
@@ -645,7 +666,6 @@ CONFIG_TIGON3=y
# CONFIG_IXGB is not set
CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
-# CONFIG_2BUFF_MODE is not set
#
# Token Ring devices
@@ -744,6 +764,7 @@ CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_ACPI is not set
CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -751,7 +772,6 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -790,6 +810,7 @@ CONFIG_SOFT_WATCHDOG=y
# CONFIG_W83877F_WDT is not set
# CONFIG_W83977F_WDT is not set
# CONFIG_MACHZ_WDT is not set
+# CONFIG_SBC_EPX_C3_WATCHDOG is not set
#
# PCI-based Watchdog Cards
@@ -817,10 +838,10 @@ CONFIG_AGP_INTEL=y
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
CONFIG_HPET_MMAP=y
-CONFIG_MAX_RAW_DEVS=256
# CONFIG_HANGCHECK_TIMER is not set
#
@@ -835,6 +856,12 @@ CONFIG_MAX_RAW_DEVS=256
# CONFIG_I2C is not set
#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
@@ -892,6 +919,7 @@ CONFIG_SOUND=y
# Open Sound System
#
CONFIG_SOUND_PRIME=y
+CONFIG_OBSOLETE_OSS_DRIVER=y
# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
@@ -968,13 +996,15 @@ 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
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
#
# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
# CONFIG_HID_FF is not set
# CONFIG_USB_HIDDEV is not set
# CONFIG_USB_AIPTEK is not set
@@ -988,6 +1018,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_YEALINK is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
# CONFIG_USB_KEYSPAN_REMOTE is not set
# CONFIG_USB_APPLETOUCH is not set
@@ -1097,6 +1128,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -1135,6 +1167,7 @@ CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
CONFIG_RELAYFS_FS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1232,21 +1265,23 @@ CONFIG_NLS_ISO8859_15=y
CONFIG_NLS_UTF8=y
#
-# Profiling support
+# Instrumentation Support
#
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1254,10 +1289,11 @@ CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
# CONFIG_FRAME_POINTER is not set
+# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_INIT_DEBUG=y
+# CONFIG_DEBUG_RODATA is not set
# CONFIG_IOMMU_DEBUG is not set
-CONFIG_KPROBES=y
#
# Security options
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index f76217d8f579..929e6b0771f8 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -2,9 +2,9 @@
# Makefile for the ia32 kernel emulation subsystem.
#
-obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
- ia32_signal.o tls32.o \
- ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o
+obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \
+ ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \
+ mmap32.o
sysv-$(CONFIG_SYSVIPC) := ipc32.o
obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
@@ -29,4 +29,3 @@ $(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
AFLAGS_vsyscall-sysenter.o = -m32
AFLAGS_vsyscall-syscall.o = -m32
-CFLAGS_ia32_ioctl.o += -Ifs/
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 2b760d0d9ce2..572b3b28772d 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -197,8 +197,7 @@ static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *re
static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs)
{
- struct pt_regs *pp = (struct pt_regs *)(t->thread.rsp0);
- --pp;
+ struct pt_regs *pp = task_pt_regs(t);
ELF_CORE_COPY_REGS((*elfregs), pp);
/* fix wrong segments */
(*elfregs)[7] = t->thread.ds;
@@ -217,7 +216,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
if (!tsk_used_math(tsk))
return 0;
if (!regs)
- regs = ((struct pt_regs *)tsk->thread.rsp0) - 1;
+ regs = task_pt_regs(tsk);
if (tsk == current)
unlazy_fpu(tsk);
set_fs(KERNEL_DS);
@@ -233,7 +232,7 @@ elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpr
static inline int
elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
{
- struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1;
+ struct pt_regs *regs = task_pt_regs(t);
if (!tsk_used_math(t))
return 0;
if (t == current)
@@ -294,8 +293,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int
} while(0)
-#define elf_map elf32_map
-
#include <linux/module.h>
MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries.");
@@ -391,21 +388,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top,
}
EXPORT_SYMBOL(ia32_setup_arg_pages);
-static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
-{
- unsigned long map_addr;
- struct task_struct *me = current;
-
- down_write(&me->mm->mmap_sem);
- map_addr = do_mmap(filep, ELF_PAGESTART(addr),
- eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot,
- type,
- eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
- up_write(&me->mm->mmap_sem);
- return(map_addr);
-}
-
#ifdef CONFIG_SYSCTL
/* Register vsyscall32 into the ABI table */
#include <linux/sysctl.h>
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
deleted file mode 100644
index e335bd0b637d..000000000000
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* $Id: ia32_ioctl.c,v 1.25 2002/10/11 07:17:06 ak Exp $
- * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
- *
- * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
- * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
- *
- * These routines maintain argument size conversion between 32bit and 64bit
- * ioctls.
- */
-
-#define INCLUDES
-#include <linux/syscalls.h>
-#include "compat_ioctl.c"
-#include <asm/ia32.h>
-
-#define CODE
-#include "compat_ioctl.c"
-
-#define RTC_IRQP_READ32 _IOR('p', 0x0b, unsigned int) /* Read IRQ rate */
-#define RTC_IRQP_SET32 _IOW('p', 0x0c, unsigned int) /* Set IRQ rate */
-#define RTC_EPOCH_READ32 _IOR('p', 0x0d, unsigned) /* Read epoch */
-#define RTC_EPOCH_SET32 _IOW('p', 0x0e, unsigned) /* Set epoch */
-
-static int rtc32_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
-{
- unsigned long val;
- mm_segment_t oldfs = get_fs();
- int ret;
-
- switch (cmd) {
- case RTC_IRQP_READ32:
- set_fs(KERNEL_DS);
- ret = sys_ioctl(fd, RTC_IRQP_READ, (unsigned long)&val);
- set_fs(oldfs);
- if (!ret)
- ret = put_user(val, (unsigned int __user *) arg);
- return ret;
-
- case RTC_IRQP_SET32:
- cmd = RTC_IRQP_SET;
- break;
-
- case RTC_EPOCH_READ32:
- set_fs(KERNEL_DS);
- ret = sys_ioctl(fd, RTC_EPOCH_READ, (unsigned long) &val);
- set_fs(oldfs);
- if (!ret)
- ret = put_user(val, (unsigned int __user *) arg);
- return ret;
-
- case RTC_EPOCH_SET32:
- cmd = RTC_EPOCH_SET;
- break;
- }
- return sys_ioctl(fd,cmd,arg);
-}
-
-
-#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler) },
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
-
-struct ioctl_trans ioctl_start[] = {
-#include <linux/compat_ioctl.h>
-#define DECLARES
-#include "compat_ioctl.c"
-
-/* And these ioctls need translation */
-/* realtime device */
-HANDLE_IOCTL(RTC_IRQP_READ, rtc32_ioctl)
-HANDLE_IOCTL(RTC_IRQP_READ32,rtc32_ioctl)
-HANDLE_IOCTL(RTC_IRQP_SET32, rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_READ32, rtc32_ioctl)
-HANDLE_IOCTL(RTC_EPOCH_SET32, rtc32_ioctl)
-/* take care of sizeof(sizeof()) breakage */
-};
-
-int ioctl_table_size = ARRAY_SIZE(ioctl_start);
-
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index 0903cc1faef2..e0a92439f634 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -353,7 +353,6 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
struct pt_regs *regs, unsigned int mask)
{
int tmp, err = 0;
- u32 eflags;
tmp = 0;
__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -378,10 +377,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
err |= __put_user(current->thread.trap_no, &sc->trapno);
err |= __put_user(current->thread.error_code, &sc->err);
err |= __put_user((u32)regs->rip, &sc->eip);
- eflags = regs->eflags;
- if (current->ptrace & PT_PTRACED)
- eflags &= ~TF_MASK;
- err |= __put_user((u32)eflags, &sc->eflags);
+ err |= __put_user((u32)regs->eflags, &sc->eflags);
err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
tmp = save_i387_ia32(current, fpstate, regs, 0);
@@ -505,13 +501,9 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
regs->ss = __USER32_DS;
set_fs(USER_DS);
- if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
- ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
- }
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -605,13 +597,9 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->ss = __USER32_DS;
set_fs(USER_DS);
- if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
- ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
- }
+ regs->eflags &= ~TF_MASK;
+ if (test_thread_flag(TIF_SINGLESTEP))
+ ptrace_notify(SIGTRAP);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index e0eb0c712fe9..f05c2a802489 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -35,6 +35,18 @@
movq %rax,R8(%rsp)
.endm
+ .macro CFI_STARTPROC32 simple
+ CFI_STARTPROC \simple
+ CFI_UNDEFINED r8
+ CFI_UNDEFINED r9
+ CFI_UNDEFINED r10
+ CFI_UNDEFINED r11
+ CFI_UNDEFINED r12
+ CFI_UNDEFINED r13
+ CFI_UNDEFINED r14
+ CFI_UNDEFINED r15
+ .endm
+
/*
* 32bit SYSENTER instruction entry.
*
@@ -55,7 +67,7 @@
* with the int 0x80 path.
*/
ENTRY(ia32_sysenter_target)
- CFI_STARTPROC simple
+ CFI_STARTPROC32 simple
CFI_DEF_CFA rsp,0
CFI_REGISTER rsp,rbp
swapgs
@@ -92,6 +104,7 @@ ENTRY(ia32_sysenter_target)
.quad 1b,ia32_badarg
.previous
GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
CFI_REMEMBER_STATE
jnz sysenter_tracesys
@@ -105,6 +118,7 @@ sysenter_do_call:
cli
testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10)
jnz int_ret_from_sys_call
+ andl $~TS_COMPAT,threadinfo_status(%r10)
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-R11(%rsp)
RESTORE_ARGS 1,24,1,1,1,1
@@ -161,7 +175,7 @@ sysenter_tracesys:
* with the int 0x80 path.
*/
ENTRY(ia32_cstar_target)
- CFI_STARTPROC simple
+ CFI_STARTPROC32 simple
CFI_DEF_CFA rsp,0
CFI_REGISTER rip,rcx
/*CFI_REGISTER rflags,r11*/
@@ -191,6 +205,7 @@ ENTRY(ia32_cstar_target)
.quad 1b,ia32_badarg
.previous
GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
CFI_REMEMBER_STATE
jnz cstar_tracesys
@@ -204,6 +219,7 @@ cstar_do_call:
cli
testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10)
jnz int_ret_from_sys_call
+ andl $~TS_COMPAT,threadinfo_status(%r10)
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
movl RIP-ARGOFFSET(%rsp),%ecx
CFI_REGISTER rip,rcx
@@ -276,6 +292,7 @@ ENTRY(ia32_syscall)
this could be a problem. */
SAVE_ARGS 0,0,1
GET_THREAD_INFO(%r10)
+ orl $TS_COMPAT,threadinfo_status(%r10)
testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
jnz ia32_tracesys
ia32_do_syscall:
@@ -318,7 +335,7 @@ quiet_ni_syscall:
jmp ia32_ptregs_common
.endm
- CFI_STARTPROC
+ CFI_STARTPROC32
PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
@@ -333,15 +350,26 @@ quiet_ni_syscall:
ENTRY(ia32_ptregs_common)
popq %r11
- CFI_ADJUST_CFA_OFFSET -8
- CFI_REGISTER rip, r11
+ CFI_ENDPROC
+ CFI_STARTPROC32 simple
+ CFI_DEF_CFA rsp,SS+8-ARGOFFSET
+ CFI_REL_OFFSET rax,RAX-ARGOFFSET
+ CFI_REL_OFFSET rcx,RCX-ARGOFFSET
+ CFI_REL_OFFSET rdx,RDX-ARGOFFSET
+ CFI_REL_OFFSET rsi,RSI-ARGOFFSET
+ CFI_REL_OFFSET rdi,RDI-ARGOFFSET
+ CFI_REL_OFFSET rip,RIP-ARGOFFSET
+/* CFI_REL_OFFSET cs,CS-ARGOFFSET*/
+/* CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/
+ CFI_REL_OFFSET rsp,RSP-ARGOFFSET
+/* CFI_REL_OFFSET ss,SS-ARGOFFSET*/
SAVE_REST
call *%rax
RESTORE_REST
jmp ia32_sysret /* misbalances the return cache */
CFI_ENDPROC
- .data
+ .section .rodata,"a"
.align 8
.globl ia32_sys_call_table
ia32_sys_call_table:
@@ -608,7 +636,7 @@ ia32_sys_call_table:
.quad sys_epoll_wait
.quad sys_remap_file_pages
.quad sys_set_tid_address
- .quad sys32_timer_create
+ .quad compat_sys_timer_create
.quad compat_sys_timer_settime /* 260 */
.quad compat_sys_timer_gettime
.quad sys_timer_getoverrun
@@ -643,6 +671,20 @@ ia32_sys_call_table:
.quad sys_inotify_init
.quad sys_inotify_add_watch
.quad sys_inotify_rm_watch
+ .quad sys_migrate_pages
+ .quad compat_sys_openat /* 295 */
+ .quad sys_mkdirat
+ .quad sys_mknodat
+ .quad sys_fchownat
+ .quad sys_futimesat
+ .quad compat_sys_newfstatat /* 300 */
+ .quad sys_unlinkat
+ .quad sys_renameat
+ .quad sys_linkat
+ .quad sys_symlinkat
+ .quad sys_readlinkat /* 305 */
+ .quad sys_fchmodat
+ .quad sys_faccessat
ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
.quad ni_syscall
diff --git a/arch/x86_64/ia32/mmap32.c b/arch/x86_64/ia32/mmap32.c
new file mode 100644
index 000000000000..079f4132575c
--- /dev/null
+++ b/arch/x86_64/ia32/mmap32.c
@@ -0,0 +1,78 @@
+/*
+ * linux/arch/x86_64/ia32/mm/mmap.c
+ *
+ * flexible mmap layout support
+ *
+ * Based on the i386 version which was
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * 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
+ *
+ *
+ * Started by Ingo Molnar <mingo@elte.hu>
+ */
+
+#include <linux/personality.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+
+/*
+ * Top of mmap area (just below the process stack).
+ *
+ * Leave an at least ~128 MB hole.
+ */
+#define MIN_GAP (128*1024*1024)
+#define MAX_GAP (TASK_SIZE/6*5)
+
+static inline unsigned long mmap_base(struct mm_struct *mm)
+{
+ unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+ unsigned long random_factor = 0;
+
+ if (current->flags & PF_RANDOMIZE)
+ random_factor = get_random_int() % (1024*1024);
+
+ if (gap < MIN_GAP)
+ gap = MIN_GAP;
+ else if (gap > MAX_GAP)
+ gap = MAX_GAP;
+
+ return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
+}
+
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void ia32_pick_mmap_layout(struct mm_struct *mm)
+{
+ /*
+ * Fall back to the standard layout if the personality
+ * bit is set, or if the expected stack growth is unlimited:
+ */
+ if (sysctl_legacy_va_layout ||
+ (current->personality & ADDR_COMPAT_LAYOUT) ||
+ current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
+ mm->mmap_base = TASK_UNMAPPED_BASE;
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+ } else {
+ mm->mmap_base = mmap_base(mm);
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+ mm->unmap_area = arch_unmap_area_topdown;
+ }
+}
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
index 2a925e2af390..23a4515a73b4 100644
--- a/arch/x86_64/ia32/ptrace32.c
+++ b/arch/x86_64/ia32/ptrace32.c
@@ -28,9 +28,12 @@
#include <asm/i387.h>
#include <asm/fpu32.h>
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x44dd5UL
+/*
+ * Determines which flags the user has access to [1 = access, 0 = no access].
+ * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
+ * Also masks reserved bits (31-22, 15, 5, 3, 1).
+ */
+#define FLAG_MASK 0x54dd5UL
#define R32(l,q) \
case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break
@@ -38,7 +41,7 @@
static int putreg32(struct task_struct *child, unsigned regno, u32 val)
{
int i;
- __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs));
+ __u64 *stack = (__u64 *)task_pt_regs(child);
switch (regno) {
case offsetof(struct user32, regs.fs):
@@ -134,7 +137,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
{
- __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs));
+ __u64 *stack = (__u64 *)task_pt_regs(child);
switch (regno) {
case offsetof(struct user32, regs.fs):
@@ -196,36 +199,6 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
#undef R32
-static struct task_struct *find_target(int request, int pid, int *err)
-{
- struct task_struct *child;
-
- *err = -EPERM;
- if (pid == 1)
- return NULL;
-
- *err = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (child) {
- *err = -EPERM;
- if (child->pid == 1)
- goto out;
- *err = ptrace_check_attach(child, request == PTRACE_KILL);
- if (*err < 0)
- goto out;
- return child;
- }
- out:
- if (child)
- put_task_struct(child);
- return NULL;
-
-}
-
asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
{
struct task_struct *child;
@@ -254,11 +227,18 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break;
}
- child = find_target(request, pid, &ret);
- if (!child)
- return ret;
+ if (request == PTRACE_TRACEME)
+ return ptrace_traceme();
+
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
- childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs));
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out;
+
+ childregs = task_pt_regs(child);
switch (request) {
case PTRACE_PEEKDATA:
@@ -373,6 +353,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break;
}
+ out:
put_task_struct(child);
return ret;
}
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 5389df610e78..54481af5344a 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -969,25 +969,6 @@ long sys32_kill(int pid, int sig)
return sys_kill(pid, sig);
}
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock,
- struct sigevent __user *timer_event_spec,
- timer_t __user * created_timer_id);
-
-long
-sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
-{
- struct sigevent __user *p = NULL;
- if (se32) {
- struct sigevent se;
- p = compat_alloc_user_space(sizeof(struct sigevent));
- if (get_compat_sigevent(&se, se32) ||
- copy_to_user(p, &se, sizeof(se)))
- return -EFAULT;
- }
- return sys_timer_create(clock, p, timer_id);
-}
-
long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
__u32 len_low, __u32 len_high, int advice)
{
diff --git a/arch/x86_64/ia32/vsyscall-sigreturn.S b/arch/x86_64/ia32/vsyscall-sigreturn.S
index 8b5a4b060bb5..d90321fe9bba 100644
--- a/arch/x86_64/ia32/vsyscall-sigreturn.S
+++ b/arch/x86_64/ia32/vsyscall-sigreturn.S
@@ -7,6 +7,7 @@
* by doing ".balign 32" must match in both versions of the page.
*/
+ .code32
.section .text.sigreturn,"ax"
.balign 32
.globl __kernel_sigreturn
diff --git a/arch/x86_64/ia32/vsyscall-syscall.S b/arch/x86_64/ia32/vsyscall-syscall.S
index b024965bb689..cf9ef678de3e 100644
--- a/arch/x86_64/ia32/vsyscall-syscall.S
+++ b/arch/x86_64/ia32/vsyscall-syscall.S
@@ -6,6 +6,7 @@
#include <asm/asm-offsets.h>
#include <asm/segment.h>
+ .code32
.text
.section .text.vsyscall,"ax"
.globl __kernel_vsyscall
diff --git a/arch/x86_64/ia32/vsyscall-sysenter.S b/arch/x86_64/ia32/vsyscall-sysenter.S
index 71f3de586b56..ae056e553d13 100644
--- a/arch/x86_64/ia32/vsyscall-sysenter.S
+++ b/arch/x86_64/ia32/vsyscall-sysenter.S
@@ -5,6 +5,7 @@
#include <asm/ia32_unistd.h>
#include <asm/asm-offsets.h>
+ .code32
.text
.section .text.vsyscall,"ax"
.globl __kernel_vsyscall
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index fe4cbd1c4b2f..72fe60c20d39 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -7,7 +7,8 @@ EXTRA_AFLAGS := -traditional
obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
x8664_ksyms.o i387.o syscall.o vsyscall.o \
- setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o
+ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
+ dmi_scan.o pci-dma.o pci-nommu.o
obj-$(CONFIG_X86_MCE) += mce.o
obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o
@@ -22,14 +23,16 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
genapic.o genapic_cluster.o genapic_flat.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_PM) += suspend.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
-obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o
+obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
+obj-$(CONFIG_X86_VSMP) += vsmp.o
obj-$(CONFIG_MODULES) += module.o
@@ -46,3 +49,5 @@ intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
+dmi_scan-y += ../../i386/kernel/dmi_scan.o
+
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index c7f4fdd20f05..e4e2b7d01f89 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -23,6 +23,7 @@
#include <asm/io.h>
#include <asm/proto.h>
#include <asm/pci-direct.h>
+#include <asm/dma.h>
int iommu_aperture;
int iommu_aperture_disabled __initdata = 0;
@@ -247,7 +248,7 @@ void __init iommu_hole_init(void)
/* Got the aperture from the AGP bridge */
} else if (swiotlb && !valid_agp) {
/* Do nothing */
- } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
+ } else if ((!no_iommu && end_pfn >= MAX_DMA32_PFN) ||
force_iommu ||
valid_agp ||
fallback_aper_force) {
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 18691ce4c759..5d3c5b07b8db 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -25,6 +25,7 @@
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
+#include <linux/module.h>
#include <asm/atomic.h>
#include <asm/smp.h>
@@ -33,36 +34,36 @@
#include <asm/pgalloc.h>
#include <asm/mach_apic.h>
#include <asm/nmi.h>
+#include <asm/idle.h>
int apic_verbosity;
int disable_apic_timer __initdata;
+/*
+ * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
+ * IPIs in place of local APIC timers
+ */
+static cpumask_t timer_interrupt_broadcast_ipi_mask;
+
/* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0;
-static DEFINE_PER_CPU(int, prof_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_counter) = 1;
-
static void apic_pm_activate(void);
void enable_NMI_through_LVT0 (void * dummy)
{
- unsigned int v, ver;
+ unsigned int v;
- ver = apic_read(APIC_LVR);
- ver = GET_APIC_VERSION(ver);
v = APIC_DM_NMI; /* unmask and set to NMI */
- apic_write_around(APIC_LVT0, v);
+ apic_write(APIC_LVT0, v);
}
int get_maxlvt(void)
{
- unsigned int v, ver, maxlvt;
+ unsigned int v, maxlvt;
v = apic_read(APIC_LVR);
- ver = GET_APIC_VERSION(v);
maxlvt = GET_APIC_MAXLVT(v);
return maxlvt;
}
@@ -80,33 +81,33 @@ void clear_local_APIC(void)
*/
if (maxlvt >= 3) {
v = ERROR_APIC_VECTOR; /* any non-zero vector will do */
- apic_write_around(APIC_LVTERR, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVTERR, v | APIC_LVT_MASKED);
}
/*
* Careful: we have to set masks only first to deassert
* any level-triggered sources.
*/
v = apic_read(APIC_LVTT);
- apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
v = apic_read(APIC_LVT0);
- apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
v = apic_read(APIC_LVT1);
- apic_write_around(APIC_LVT1, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVT1, v | APIC_LVT_MASKED);
if (maxlvt >= 4) {
v = apic_read(APIC_LVTPC);
- apic_write_around(APIC_LVTPC, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVTPC, v | APIC_LVT_MASKED);
}
/*
* Clean APIC state for other OSs:
*/
- apic_write_around(APIC_LVTT, APIC_LVT_MASKED);
- apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
- apic_write_around(APIC_LVT1, APIC_LVT_MASKED);
+ apic_write(APIC_LVTT, APIC_LVT_MASKED);
+ apic_write(APIC_LVT0, APIC_LVT_MASKED);
+ apic_write(APIC_LVT1, APIC_LVT_MASKED);
if (maxlvt >= 3)
- apic_write_around(APIC_LVTERR, APIC_LVT_MASKED);
+ apic_write(APIC_LVTERR, APIC_LVT_MASKED);
if (maxlvt >= 4)
- apic_write_around(APIC_LVTPC, APIC_LVT_MASKED);
+ apic_write(APIC_LVTPC, APIC_LVT_MASKED);
v = GET_APIC_VERSION(apic_read(APIC_LVR));
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
@@ -151,7 +152,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
value &= ~APIC_VECTOR_MASK;
value |= APIC_SPIV_APIC_ENABLED;
value |= 0xf;
- apic_write_around(APIC_SPIV, value);
+ apic_write(APIC_SPIV, value);
if (!virt_wire_setup) {
/* For LVT0 make it edge triggered, active high, external and enabled */
@@ -161,11 +162,11 @@ void disconnect_bsp_APIC(int virt_wire_setup)
APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
- apic_write_around(APIC_LVT0, value);
+ apic_write(APIC_LVT0, value);
}
else {
/* Disable LVT0 */
- apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+ apic_write(APIC_LVT0, APIC_LVT_MASKED);
}
/* For LVT1 make it edge triggered, active high, nmi and enabled */
@@ -176,7 +177,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
- apic_write_around(APIC_LVT1, value);
+ apic_write(APIC_LVT1, value);
}
}
@@ -192,7 +193,7 @@ void disable_local_APIC(void)
*/
value = apic_read(APIC_SPIV);
value &= ~APIC_SPIV_APIC_ENABLED;
- apic_write_around(APIC_SPIV, value);
+ apic_write(APIC_SPIV, value);
}
/*
@@ -269,7 +270,7 @@ void __init sync_Arb_IDs(void)
apic_wait_icr_idle();
apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
- apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
+ apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
| APIC_DM_INIT);
}
@@ -280,7 +281,7 @@ extern void __error_in_apic_c (void);
*/
void __init init_bsp_APIC(void)
{
- unsigned int value, ver;
+ unsigned int value;
/*
* Don't do the setup now if we have a SMP BIOS as the
@@ -290,7 +291,6 @@ void __init init_bsp_APIC(void)
return;
value = apic_read(APIC_LVR);
- ver = GET_APIC_VERSION(value);
/*
* Do not trust the local APIC being empty at bootup.
@@ -305,22 +305,21 @@ void __init init_bsp_APIC(void)
value |= APIC_SPIV_APIC_ENABLED;
value |= APIC_SPIV_FOCUS_DISABLED;
value |= SPURIOUS_APIC_VECTOR;
- apic_write_around(APIC_SPIV, value);
+ apic_write(APIC_SPIV, value);
/*
* Set up the virtual wire mode.
*/
- apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+ apic_write(APIC_LVT0, APIC_DM_EXTINT);
value = APIC_DM_NMI;
- apic_write_around(APIC_LVT1, value);
+ apic_write(APIC_LVT1, value);
}
void __cpuinit setup_local_APIC (void)
{
- unsigned int value, ver, maxlvt;
+ unsigned int value, maxlvt;
value = apic_read(APIC_LVR);
- ver = GET_APIC_VERSION(value);
if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
__error_in_apic_c();
@@ -345,7 +344,7 @@ void __cpuinit setup_local_APIC (void)
*/
value = apic_read(APIC_TASKPRI);
value &= ~APIC_TPRI_MASK;
- apic_write_around(APIC_TASKPRI, value);
+ apic_write(APIC_TASKPRI, value);
/*
* Now that we are all set up, enable the APIC
@@ -387,7 +386,7 @@ void __cpuinit setup_local_APIC (void)
* Set spurious IRQ vector
*/
value |= SPURIOUS_APIC_VECTOR;
- apic_write_around(APIC_SPIV, value);
+ apic_write(APIC_SPIV, value);
/*
* Set up LVT0, LVT1:
@@ -407,7 +406,7 @@ void __cpuinit setup_local_APIC (void)
value = APIC_DM_EXTINT | APIC_LVT_MASKED;
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id());
}
- apic_write_around(APIC_LVT0, value);
+ apic_write(APIC_LVT0, value);
/*
* only the BP should see the LINT1 NMI signal, obviously.
@@ -416,14 +415,14 @@ void __cpuinit setup_local_APIC (void)
value = APIC_DM_NMI;
else
value = APIC_DM_NMI | APIC_LVT_MASKED;
- apic_write_around(APIC_LVT1, value);
+ apic_write(APIC_LVT1, value);
{
unsigned oldvalue;
maxlvt = get_maxlvt();
oldvalue = apic_read(APIC_ESR);
value = ERROR_APIC_VECTOR; // enables sending errors
- apic_write_around(APIC_LVTERR, value);
+ apic_write(APIC_LVTERR, value);
/*
* spec says clear errors after enabling vector.
*/
@@ -500,13 +499,10 @@ static int lapic_resume(struct sys_device *dev)
if (!apic_pm_state.active)
return 0;
- /* XXX: Pavel needs this for S3 resume, but can't explain why */
- set_fixmap_nocache(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
-
local_irq_save(flags);
rdmsr(MSR_IA32_APICBASE, l, h);
l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
wrmsr(MSR_IA32_APICBASE, l, h);
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id);
@@ -660,20 +656,25 @@ void __init init_apic_mappings(void)
static void __setup_APIC_LVTT(unsigned int clocks)
{
unsigned int lvtt_value, tmp_value, ver;
+ int cpu = smp_processor_id();
ver = GET_APIC_VERSION(apic_read(APIC_LVR));
lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
- apic_write_around(APIC_LVTT, lvtt_value);
+
+ if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask))
+ lvtt_value |= APIC_LVT_MASKED;
+
+ apic_write(APIC_LVTT, lvtt_value);
/*
* Divide PICLK by 16
*/
tmp_value = apic_read(APIC_TDCR);
- apic_write_around(APIC_TDCR, (tmp_value
+ apic_write(APIC_TDCR, (tmp_value
& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
| APIC_TDR_DIV_16);
- apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
+ apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
}
static void setup_APIC_timer(unsigned int clocks)
@@ -682,12 +683,6 @@ static void setup_APIC_timer(unsigned int clocks)
local_irq_save(flags);
- /* For some reasons this doesn't work on Simics, so fake it for now */
- if (!strstr(boot_cpu_data.x86_model_id, "Screwdriver")) {
- __setup_APIC_LVTT(clocks);
- return;
- }
-
/* wait for irq slice */
if (vxtime.hpet_address) {
int trigger = hpet_readl(HPET_T0_CMP);
@@ -700,7 +695,7 @@ static void setup_APIC_timer(unsigned int clocks)
outb_p(0x00, 0x43);
c2 = inb_p(0x40);
c2 |= inb_p(0x40) << 8;
- do {
+ do {
c1 = c2;
outb_p(0x00, 0x43);
c2 = inb_p(0x40);
@@ -785,52 +780,68 @@ void __cpuinit setup_secondary_APIC_clock(void)
local_irq_enable();
}
-void __cpuinit disable_APIC_timer(void)
+void disable_APIC_timer(void)
{
if (using_apic_timer) {
unsigned long v;
v = apic_read(APIC_LVTT);
- apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
}
}
void enable_APIC_timer(void)
{
- if (using_apic_timer) {
+ int cpu = smp_processor_id();
+
+ if (using_apic_timer &&
+ !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
unsigned long v;
v = apic_read(APIC_LVTT);
- apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
+ apic_write(APIC_LVTT, v & ~APIC_LVT_MASKED);
}
}
-/*
- * the frequency of the profiling timer can be changed
- * by writing a multiplier value into /proc/profile.
- */
-int setup_profiling_timer(unsigned int multiplier)
+void switch_APIC_timer_to_ipi(void *cpumask)
{
- int i;
+ cpumask_t mask = *(cpumask_t *)cpumask;
+ int cpu = smp_processor_id();
- /*
- * Sanity check. [at least 500 APIC cycles should be
- * between APIC interrupts as a rule of thumb, to avoid
- * irqs flooding us]
- */
- if ( (!multiplier) || (calibration_result/multiplier < 500))
- return -EINVAL;
-
- /*
- * Set the new multiplier for each CPU. CPUs don't start using the
- * new values until the next timer interrupt in which they do process
- * accounting. At that time they also adjust their APIC timers
- * accordingly.
- */
- for (i = 0; i < NR_CPUS; ++i)
- per_cpu(prof_multiplier, i) = multiplier;
+ if (cpu_isset(cpu, mask) &&
+ !cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
+ disable_APIC_timer();
+ cpu_set(cpu, timer_interrupt_broadcast_ipi_mask);
+ }
+}
+EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
- return 0;
+void smp_send_timer_broadcast_ipi(void)
+{
+ cpumask_t mask;
+
+ cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask);
+ if (!cpus_empty(mask)) {
+ send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
+ }
+}
+
+void switch_ipi_to_APIC_timer(void *cpumask)
+{
+ cpumask_t mask = *(cpumask_t *)cpumask;
+ int cpu = smp_processor_id();
+
+ if (cpu_isset(cpu, mask) &&
+ cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) {
+ cpu_clear(cpu, timer_interrupt_broadcast_ipi_mask);
+ enable_APIC_timer();
+ }
+}
+EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+ return -EINVAL;
}
#ifdef CONFIG_X86_MCE_AMD
@@ -857,32 +868,10 @@ void setup_threshold_lvt(unsigned long lvt_off)
void smp_local_timer_interrupt(struct pt_regs *regs)
{
- int cpu = smp_processor_id();
-
profile_tick(CPU_PROFILING, regs);
- if (--per_cpu(prof_counter, cpu) <= 0) {
- /*
- * The multiplier may have changed since the last time we got
- * to this point as a result of the user writing to
- * /proc/profile. In this case we need to adjust the APIC
- * timer accordingly.
- *
- * Interrupts are already masked off at this point.
- */
- per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu);
- if (per_cpu(prof_counter, cpu) !=
- per_cpu(prof_old_multiplier, cpu)) {
- __setup_APIC_LVTT(calibration_result/
- per_cpu(prof_counter, cpu));
- per_cpu(prof_old_multiplier, cpu) =
- per_cpu(prof_counter, cpu);
- }
-
#ifdef CONFIG_SMP
- update_process_times(user_mode(regs));
+ update_process_times(user_mode(regs));
#endif
- }
-
/*
* We take the 'long' return path, and there every subsystem
* grabs the appropriate locks (kernel lock/ irq lock).
@@ -920,6 +909,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
* Besides, if we don't timer interrupts ignore the global
* interrupt lock, which is the WrongThing (tm) to do.
*/
+ exit_idle();
irq_enter();
smp_local_timer_interrupt(regs);
irq_exit();
@@ -979,6 +969,7 @@ __init int oem_force_hpet_timer(void)
asmlinkage void smp_spurious_interrupt(void)
{
unsigned int v;
+ exit_idle();
irq_enter();
/*
* Check if this really is a spurious interrupt and ACK it
@@ -1014,6 +1005,7 @@ asmlinkage void smp_error_interrupt(void)
{
unsigned int v, v1;
+ exit_idle();
irq_enter();
/* First tickle the hardware, only then report what went on. -- REW */
v = apic_read(APIC_ESR);
@@ -1060,7 +1052,7 @@ int __init APIC_init_uniprocessor (void)
connect_bsp_APIC();
phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
- apic_write_around(APIC_ID, boot_cpu_id);
+ apic_write(APIC_ID, SET_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 aaa6d3833517..38834bbbae11 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -33,6 +33,7 @@ int main(void)
ENTRY(flags);
ENTRY(addr_limit);
ENTRY(preempt_count);
+ ENTRY(status);
BLANK();
#undef ENTRY
#define ENTRY(entry) DEFINE(pda_ ## entry, offsetof(struct x8664_pda, entry))
@@ -42,6 +43,7 @@ int main(void)
ENTRY(irqcount);
ENTRY(cpunumber);
ENTRY(irqstackptr);
+ ENTRY(data_offset);
BLANK();
#undef ENTRY
#ifdef CONFIG_IA32_EMULATION
@@ -64,5 +66,7 @@ int main(void)
DEFINE(pbe_address, offsetof(struct pbe, address));
DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
DEFINE(pbe_next, offsetof(struct pbe, next));
+ BLANK();
+ DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
return 0;
}
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index 535e04466079..4e6c3b729e39 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -11,19 +11,156 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/smp.h>
+#include <linux/irq.h>
#include <linux/reboot.h>
#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
#include <asm/processor.h>
#include <asm/hardirq.h>
#include <asm/nmi.h>
#include <asm/hw_irq.h>
+#include <asm/mach_apic.h>
-note_buf_t crash_notes[NR_CPUS];
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type,
+ void *data, size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, &note, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, &note, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+
+ if (!buf)
+ return;
+
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+{
+ /*
+ * Don't do anything if this handler is invoked on crashing cpu.
+ * Otherwise, system will completely hang. Crashing cpu can get
+ * an NMI if system was initially booted with nmi_watchdog parameter.
+ */
+ if (cpu == crashing_cpu)
+ return 1;
+ local_irq_disable();
+
+ crash_save_this_cpu(regs, cpu);
+ disable_local_APIC();
+ atomic_dec(&waiting_for_crash_ipi);
+ /* Assume hlt works */
+ for(;;)
+ asm("hlt");
+
+ return 1;
+}
+
+static void smp_send_nmi_allbutself(void)
+{
+ send_IPI_allbutself(APIC_DM_NMI);
+}
+
+/*
+ * This code is a best effort heuristic to get the
+ * other cpus to stop executing. So races with
+ * cpu hotplug shouldn't matter.
+ */
+
+static void nmi_shootdown_cpus(void)
+{
+ unsigned long msecs;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+ set_nmi_callback(crash_nmi_callback);
+
+ /*
+ * Ensure the new callback function is set before sending
+ * out the NMI
+ */
+ wmb();
+
+ smp_send_nmi_allbutself();
+
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+ msecs--;
+ }
+ /* Leave the nmi callback set */
+ disable_local_APIC();
+}
+#else
+static void nmi_shootdown_cpus(void)
+{
+ /* There are no cpus to shootdown */
+}
+#endif
void machine_crash_shutdown(struct pt_regs *regs)
{
- /* This function is only called after the system
+ /*
+ * This function is only called after the system
* has paniced or is otherwise in a critical state.
* The minimum amount of code to allow a kexec'd kernel
* to run successfully needs to happen here.
@@ -31,4 +168,19 @@ void machine_crash_shutdown(struct pt_regs *regs)
* In practice this means shooting down the other cpus in
* an SMP system.
*/
+ /* The kernel is broken so disable interrupts */
+ local_irq_disable();
+
+ /* Make a note of crashing cpu. Will be used in NMI callback.*/
+ crashing_cpu = smp_processor_id();
+ nmi_shootdown_cpus();
+
+ if(cpu_has_apic)
+ disable_local_APIC();
+
+#if defined(CONFIG_X86_IO_APIC)
+ disable_IO_APIC();
+#endif
+
+ crash_save_self(regs);
}
diff --git a/kernel/crash_dump.c b/arch/x86_64/kernel/crash_dump.c
index 334c37f5218a..942deac4d43a 100644
--- a/kernel/crash_dump.c
+++ b/arch/x86_64/kernel/crash_dump.c
@@ -5,18 +5,11 @@
* Copyright (C) IBM Corporation, 2004. All rights reserved
*/
-#include <linux/smp_lock.h>
#include <linux/errno.h>
-#include <linux/proc_fs.h>
-#include <linux/bootmem.h>
-#include <linux/highmem.h>
#include <linux/crash_dump.h>
-#include <asm/io.h>
#include <asm/uaccess.h>
-
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+#include <asm/io.h>
/**
* copy_oldmem_page - copy one page from "oldmem"
@@ -32,30 +25,23 @@ unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
*/
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
- size_t csize, unsigned long offset, int userbuf)
+ size_t csize, unsigned long offset, int userbuf)
{
- void *page, *vaddr;
+ void *vaddr;
if (!csize)
return 0;
- page = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
- copy_page(page, vaddr);
- kunmap_atomic(vaddr, KM_PTE0);
+ vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
if (userbuf) {
- if (copy_to_user(buf, (page + offset), csize)) {
- kfree(page);
+ if (copy_to_user(buf, (vaddr + offset), csize)) {
+ iounmap(vaddr);
return -EFAULT;
}
- } else {
- memcpy(buf, (page + offset), csize);
- }
+ } else
+ memcpy(buf, (vaddr + offset), csize);
- kfree(page);
+ iounmap(vaddr);
return csize;
}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 17579a1a174b..293cd71a266a 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -559,6 +559,27 @@ void __init parse_memopt(char *p, char **from)
end_user_pfn >>= PAGE_SHIFT;
}
+void __init parse_memmapopt(char *p, char **from)
+{
+ unsigned long long start_at, mem_size;
+
+ mem_size = memparse(p, from);
+ p = *from;
+ if (*p == '@') {
+ start_at = memparse(p+1, from);
+ add_memory_region(start_at, mem_size, E820_RAM);
+ } else if (*p == '#') {
+ start_at = memparse(p+1, from);
+ add_memory_region(start_at, mem_size, E820_ACPI);
+ } else if (*p == '$') {
+ start_at = memparse(p+1, from);
+ add_memory_region(start_at, mem_size, E820_RESERVED);
+ } else {
+ end_user_pfn = (mem_size >> PAGE_SHIFT);
+ }
+ p = *from;
+}
+
unsigned long pci_mem_start = 0xaeedbabe;
/*
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 9cd968dd0f5a..6dffb498ccd7 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -216,7 +216,7 @@ void early_printk(const char *fmt, ...)
va_end(ap);
}
-static int keep_early;
+static int __initdata keep_early;
int __init setup_early_printk(char *opt)
{
@@ -226,8 +226,6 @@ int __init setup_early_printk(char *opt)
if (early_console_initialized)
return -1;
- opt = strchr(opt, '=') + 1;
-
strlcpy(buf,opt,sizeof(buf));
space = strchr(buf, ' ');
if (space)
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 9ff42041bb6b..dbdba56e8faa 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -41,6 +41,7 @@
#include <asm/unistd.h>
#include <asm/thread_info.h>
#include <asm/hw_irq.h>
+#include <asm/page.h>
.code64
@@ -313,6 +314,7 @@ int_with_check:
movl threadinfo_flags(%rcx),%edx
andl %edi,%edx
jnz int_careful
+ andl $~TS_COMPAT,threadinfo_status(%rcx)
jmp retint_swapgs
/* Either reschedule or signal or syscall exit tracking needed. */
@@ -673,7 +675,7 @@ ENTRY(spurious_interrupt)
/* error code is on the stack already */
/* handle NMI like exceptions that can happen everywhere */
- .macro paranoidentry sym
+ .macro paranoidentry sym, ist=0
SAVE_ALL
cld
movl $1,%ebx
@@ -683,10 +685,20 @@ ENTRY(spurious_interrupt)
js 1f
swapgs
xorl %ebx,%ebx
-1: movq %rsp,%rdi
+1:
+ .if \ist
+ movq %gs:pda_data_offset, %rbp
+ .endif
+ movq %rsp,%rdi
movq ORIG_RAX(%rsp),%rsi
movq $-1,ORIG_RAX(%rsp)
+ .if \ist
+ subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+ .endif
call \sym
+ .if \ist
+ addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp)
+ .endif
cli
.endm
@@ -754,7 +766,7 @@ error_exit:
jnz retint_careful
swapgs
RESTORE_ARGS 0,8,0
- iretq
+ jmp iret_label
CFI_ENDPROC
error_kernelspace:
@@ -904,7 +916,7 @@ KPROBE_ENTRY(debug)
INTR_FRAME
pushq $0
CFI_ADJUST_CFA_OFFSET 8
- paranoidentry do_debug
+ paranoidentry do_debug, DEBUG_STACK
jmp paranoid_exit
CFI_ENDPROC
.previous .text
@@ -959,7 +971,12 @@ paranoid_schedule:
CFI_ENDPROC
KPROBE_ENTRY(int3)
- zeroentry do_int3
+ INTR_FRAME
+ pushq $0
+ CFI_ADJUST_CFA_OFFSET 8
+ paranoidentry do_int3, DEBUG_STACK
+ jmp paranoid_exit
+ CFI_ENDPROC
.previous .text
ENTRY(overflow)
@@ -1021,23 +1038,18 @@ ENTRY(machine_check)
CFI_ENDPROC
#endif
-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
+ movq %rsp,%rdx
+ CFI_DEF_CFA_REGISTER rdx
incl %gs:pda_irqcount
cmove %rax,%rsp
+ pushq %rdx
+ /*todo CFI_DEF_CFA_EXPRESSION ...*/
call __do_softirq
- movq %r15,%rsp
+ popq %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_cluster.c b/arch/x86_64/kernel/genapic_cluster.c
index a472d62f899a..43fcf62fef0f 100644
--- a/arch/x86_64/kernel/genapic_cluster.c
+++ b/arch/x86_64/kernel/genapic_cluster.c
@@ -72,14 +72,11 @@ 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;
- int me = get_cpu(); /* Ensure we are not preempted when we clear */
- cpu_clear(me, mask);
+ cpu_clear(smp_processor_id(), 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 9da3edb799ea..1a2ab825be98 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -83,12 +83,11 @@ static void flat_send_IPI_allbutself(int vector)
__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);
+
+ cpu_clear(smp_processor_id(), allbutme);
if (!cpus_empty(allbutme))
flat_send_IPI_mask(allbutme, vector);
- put_cpu();
#endif
}
@@ -149,10 +148,9 @@ static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
static void physflat_send_IPI_allbutself(int vector)
{
cpumask_t allbutme = cpu_online_map;
- int me = get_cpu();
- cpu_clear(me, allbutme);
+
+ cpu_clear(smp_processor_id(), allbutme);
physflat_send_IPI_mask(allbutme, vector);
- put_cpu();
}
static void physflat_send_IPI_all(int vector)
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 15290968e49d..692c737feddb 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -241,104 +241,70 @@ ljumpvector:
ENTRY(stext)
ENTRY(_stext)
-.org 0x1000
-ENTRY(init_level4_pgt)
+ $page = 0
+#define NEXT_PAGE(name) \
+ $page = $page + 1; \
+ .org $page * 0x1000; \
+ phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \
+ENTRY(name)
+
+NEXT_PAGE(init_level4_pgt)
/* This gets initialized in x86_64_start_kernel */
.fill 512,8,0
-.org 0x2000
-ENTRY(level3_ident_pgt)
- .quad 0x0000000000004007 + __PHYSICAL_START
+NEXT_PAGE(level3_ident_pgt)
+ .quad phys_level2_ident_pgt | 0x007
.fill 511,8,0
-.org 0x3000
-ENTRY(level3_kernel_pgt)
+NEXT_PAGE(level3_kernel_pgt)
.fill 510,8,0
/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
- .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */
+ .quad phys_level2_kernel_pgt | 0x007
.fill 1,8,0
-.org 0x4000
-ENTRY(level2_ident_pgt)
+NEXT_PAGE(level2_ident_pgt)
/* 40MB for bootup. */
- .quad 0x0000000000000083
- .quad 0x0000000000200083
- .quad 0x0000000000400083
- .quad 0x0000000000600083
- .quad 0x0000000000800083
- .quad 0x0000000000A00083
- .quad 0x0000000000C00083
- .quad 0x0000000000E00083
- .quad 0x0000000001000083
- .quad 0x0000000001200083
- .quad 0x0000000001400083
- .quad 0x0000000001600083
- .quad 0x0000000001800083
- .quad 0x0000000001A00083
- .quad 0x0000000001C00083
- .quad 0x0000000001E00083
- .quad 0x0000000002000083
- .quad 0x0000000002200083
- .quad 0x0000000002400083
- .quad 0x0000000002600083
+ i = 0
+ .rept 20
+ .quad i << 21 | 0x083
+ i = i + 1
+ .endr
/* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */
.globl temp_boot_pmds
temp_boot_pmds:
.fill 492,8,0
-.org 0x5000
-ENTRY(level2_kernel_pgt)
+NEXT_PAGE(level2_kernel_pgt)
/* 40MB kernel mapping. The kernel code cannot be bigger than that.
When you change this change KERNEL_TEXT_SIZE in page.h too. */
/* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */
- .quad 0x0000000000000183
- .quad 0x0000000000200183
- .quad 0x0000000000400183
- .quad 0x0000000000600183
- .quad 0x0000000000800183
- .quad 0x0000000000A00183
- .quad 0x0000000000C00183
- .quad 0x0000000000E00183
- .quad 0x0000000001000183
- .quad 0x0000000001200183
- .quad 0x0000000001400183
- .quad 0x0000000001600183
- .quad 0x0000000001800183
- .quad 0x0000000001A00183
- .quad 0x0000000001C00183
- .quad 0x0000000001E00183
- .quad 0x0000000002000183
- .quad 0x0000000002200183
- .quad 0x0000000002400183
- .quad 0x0000000002600183
+ i = 0
+ .rept 20
+ .quad i << 21 | 0x183
+ i = i + 1
+ .endr
/* Module mapping starts here */
.fill 492,8,0
-.org 0x6000
-ENTRY(empty_zero_page)
+NEXT_PAGE(empty_zero_page)
-.org 0x7000
-ENTRY(empty_bad_page)
-
-.org 0x8000
-ENTRY(empty_bad_pte_table)
+NEXT_PAGE(level3_physmem_pgt)
+ .quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */
+ .fill 511,8,0
-.org 0x9000
-ENTRY(empty_bad_pmd_table)
+#undef NEXT_PAGE
-.org 0xa000
-ENTRY(level3_physmem_pgt)
- .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
+ .data
- .org 0xb000
#ifdef CONFIG_ACPI_SLEEP
+ .align PAGE_SIZE
ENTRY(wakeup_level4_pgt)
- .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
+ .quad phys_level3_ident_pgt | 0x007
.fill 255,8,0
- .quad 0x000000000000a007 + __PHYSICAL_START
+ .quad phys_level3_physmem_pgt | 0x007
.fill 254,8,0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
- .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
+ .quad phys_level3_kernel_pgt | 0x007
#endif
#ifndef CONFIG_HOTPLUG_CPU
@@ -352,12 +318,12 @@ ENTRY(wakeup_level4_pgt)
*/
.align PAGE_SIZE
ENTRY(boot_level4_pgt)
- .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
+ .quad phys_level3_ident_pgt | 0x007
.fill 255,8,0
- .quad 0x000000000000a007 + __PHYSICAL_START
+ .quad phys_level3_physmem_pgt | 0x007
.fill 254,8,0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
- .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
+ .quad phys_level3_kernel_pgt | 0x007
.data
@@ -379,14 +345,14 @@ gdt:
* Also sysret mandates a special GDT layout
*/
-.align L1_CACHE_BYTES
+.align PAGE_SIZE
/* The TLS descriptors are currently at a different place compared to i386.
Hopefully nobody expects them at a fixed place (Wine?) */
ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
- .quad 0x008f9a000000ffff /* __KERNEL_COMPAT32_CS */
+ .quad 0x0 /* unused */
.quad 0x00af9a000000ffff /* __KERNEL_CS */
.quad 0x00cf92000000ffff /* __KERNEL_DS */
.quad 0x00cffa000000ffff /* __USER32_CS */
@@ -396,15 +362,15 @@ ENTRY(cpu_gdt_table)
.quad 0,0 /* TSS */
.quad 0,0 /* LDT */
.quad 0,0,0 /* three TLS descriptors */
- .quad 0x00009a000000ffff /* __KERNEL16_CS - 16bit PM for S3 wakeup. */
- /* base must be patched for real base address. */
+ .quad 0 /* unused */
gdt_end:
/* asm/segment.h:GDT_ENTRIES must match this */
/* This should be a multiple of the cache line size */
- /* GDTs of other CPUs: */
- .fill (GDT_SIZE * NR_CPUS) - (gdt_end - cpu_gdt_table)
+ /* GDTs of other CPUs are now dynamically allocated */
+
+ /* zero the remaining page */
+ .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0
- .align L1_CACHE_BYTES
ENTRY(idt_table)
.rept 256
.quad 0
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index b675c5add01e..cea20a66c150 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -92,6 +92,9 @@ void __init x86_64_start_kernel(char * real_mode_data)
memcpy(init_level4_pgt, boot_level4_pgt, PTRS_PER_PGD*sizeof(pgd_t));
asm volatile("movq %0,%%cr3" :: "r" (__pa_symbol(&init_level4_pgt)));
+ for (i = 0; i < NR_CPUS; i++)
+ cpu_pda(i) = &boot_cpu_pda[i];
+
pda_init(0);
copy_bootdata(real_mode_data);
#ifdef CONFIG_SMP
@@ -99,7 +102,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
#endif
s = strstr(saved_command_line, "earlyprintk=");
if (s != NULL)
- setup_early_printk(s);
+ setup_early_printk(strchr(s, '=') + 1);
#ifdef CONFIG_NUMA
s = strstr(saved_command_line, "numa=");
if (s != NULL)
diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c
index d9b22b633e39..a5d7e16b928e 100644
--- a/arch/x86_64/kernel/i387.c
+++ b/arch/x86_64/kernel/i387.c
@@ -95,7 +95,7 @@ int save_i387(struct _fpstate __user *buf)
if (!used_math())
return 0;
clear_used_math(); /* trigger finit */
- if (tsk->thread_info->status & TS_USEDFPU) {
+ if (task_thread_info(tsk)->status & TS_USEDFPU) {
err = save_i387_checking((struct i387_fxsave_struct __user *)buf);
if (err) return err;
stts();
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 6e5101ad3d1a..5ecd34ab8c2b 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -133,7 +133,7 @@ static void end_8259A_irq (unsigned int irq)
{
if (irq > 256) {
char var;
- printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, current->thread_info);
+ printk("return %p stack %p ti %p\n", __builtin_return_address(0), &var, task_thread_info(current));
BUG();
}
@@ -549,10 +549,9 @@ void __init init_IRQ(void)
int vector = FIRST_EXTERNAL_VECTOR + i;
if (i >= NR_IRQS)
break;
- if (vector != IA32_SYSCALL_VECTOR && vector != KDB_VECTOR) {
+ if (vector != IA32_SYSCALL_VECTOR)
set_intr_gate(vector, interrupt[i]);
}
- }
#ifdef CONFIG_SMP
/*
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index e0ba5c1043fd..ce31d904d601 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 = INIT_TSS;
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_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 97154ab058b4..e8cf44ef8778 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -37,6 +37,7 @@
#include <asm/proto.h>
#include <asm/mach_apic.h>
#include <asm/acpi.h>
+#include <asm/dma.h>
#define __apicdebuginit __init
@@ -46,6 +47,9 @@ static int no_timer_check;
int disable_timer_pin_1 __initdata;
+/* Where if anywhere is the i8259 connect in external int mode */
+static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
+
static DEFINE_SPINLOCK(ioapic_lock);
/*
@@ -260,9 +264,6 @@ __setup("apic", enable_ioapic_setup);
void __init check_ioapic(void)
{
int num,slot,func;
- if (ioapic_force)
- return;
-
/* Poor man's PCI discovery */
for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) {
@@ -284,7 +285,7 @@ void __init check_ioapic(void)
switch (vendor) {
case PCI_VENDOR_ID_VIA:
#ifdef CONFIG_GART_IOMMU
- if ((end_pfn >= (0xffffffff>>PAGE_SHIFT) ||
+ if ((end_pfn > MAX_DMA32_PFN ||
force_iommu) &&
!iommu_aperture_allowed) {
printk(KERN_INFO
@@ -363,7 +364,7 @@ static int find_irq_entry(int apic, int pin, int type)
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
-static int find_isa_irq_pin(int irq, int type)
+static int __init find_isa_irq_pin(int irq, int type)
{
int i;
@@ -381,6 +382,31 @@ static int find_isa_irq_pin(int irq, int type)
return -1;
}
+static int __init find_isa_irq_apic(int irq, int type)
+{
+ int i;
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ int lbus = mp_irqs[i].mpc_srcbus;
+
+ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
+ mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+ (mp_irqs[i].mpc_irqtype == type) &&
+ (mp_irqs[i].mpc_srcbusirq == irq))
+ break;
+ }
+ if (i < mp_irq_entries) {
+ int apic;
+ for(apic = 0; apic < nr_ioapics; apic++) {
+ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic)
+ return apic;
+ }
+ }
+
+ return -1;
+}
+
/*
* Find a specific PCI IRQ entry.
* Not an __init, possibly needed by modules
@@ -874,7 +900,7 @@ static void __init setup_IO_APIC_irqs(void)
* Set up the 8259A-master output pin as broadcast to all
* CPUs.
*/
-static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
+static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -884,7 +910,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
disable_8259A_irq(0);
/* mask LVT0 */
- apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
/*
* We use logical delivery to get the timer IRQ
@@ -908,8 +934,8 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
* Add it to the IO-APIC irq-routing table:
*/
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);
enable_8259A_irq(0);
@@ -1188,7 +1214,8 @@ void __apicdebuginit print_PIC(void)
static void __init enable_IO_APIC(void)
{
union IO_APIC_reg_01 reg_01;
- int i;
+ int i8259_apic, i8259_pin;
+ int i, apic;
unsigned long flags;
for (i = 0; i < PIN_MAP_SIZE; i++) {
@@ -1202,11 +1229,48 @@ static void __init enable_IO_APIC(void)
/*
* The number of IO-APIC IRQ registers (== #pins):
*/
- for (i = 0; i < nr_ioapics; i++) {
+ for (apic = 0; apic < nr_ioapics; apic++) {
spin_lock_irqsave(&ioapic_lock, flags);
- reg_01.raw = io_apic_read(i, 1);
+ reg_01.raw = io_apic_read(apic, 1);
spin_unlock_irqrestore(&ioapic_lock, flags);
- nr_ioapic_registers[i] = reg_01.bits.entries+1;
+ nr_ioapic_registers[apic] = reg_01.bits.entries+1;
+ }
+ for(apic = 0; apic < nr_ioapics; apic++) {
+ int pin;
+ /* See if any of the pins is in ExtINT mode */
+ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
+ struct IO_APIC_route_entry entry;
+ spin_lock_irqsave(&ioapic_lock, flags);
+ *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
+ *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+
+ /* If the interrupt line is enabled and in ExtInt mode
+ * I have found the pin where the i8259 is connected.
+ */
+ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) {
+ ioapic_i8259.apic = apic;
+ ioapic_i8259.pin = pin;
+ goto found_i8259;
+ }
+ }
+ }
+ found_i8259:
+ /* Look to see what if the MP table has reported the ExtINT */
+ i8259_pin = find_isa_irq_pin(0, mp_ExtINT);
+ i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+ /* Trust the MP table if nothing is setup in the hardware */
+ if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
+ printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
+ ioapic_i8259.pin = i8259_pin;
+ ioapic_i8259.apic = i8259_apic;
+ }
+ /* Complain if the MP table and the hardware disagree */
+ if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) &&
+ (i8259_pin >= 0) && (ioapic_i8259.pin >= 0))
+ {
+ printk(KERN_WARNING "ExtINT in hardware and MP table differ\n");
}
/*
@@ -1220,7 +1284,6 @@ static void __init enable_IO_APIC(void)
*/
void disable_IO_APIC(void)
{
- int pin;
/*
* Clear the IO-APIC before rebooting:
*/
@@ -1231,8 +1294,7 @@ void disable_IO_APIC(void)
* Put that IOAPIC in virtual wire mode
* so legacy interrupts can be delivered.
*/
- pin = find_isa_irq_pin(0, mp_ExtINT);
- if (pin != -1) {
+ if (ioapic_i8259.pin != -1) {
struct IO_APIC_route_entry entry;
unsigned long flags;
@@ -1243,21 +1305,23 @@ void disable_IO_APIC(void)
entry.polarity = 0; /* High */
entry.delivery_status = 0;
entry.dest_mode = 0; /* Physical */
- entry.delivery_mode = 7; /* ExtInt */
+ entry.delivery_mode = dest_ExtINT; /* ExtInt */
entry.vector = 0;
- entry.dest.physical.physical_dest = 0;
-
+ entry.dest.physical.physical_dest =
+ GET_APIC_ID(apic_read(APIC_ID));
/*
* Add it to the IO-APIC irq-routing table:
*/
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
- io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+ io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
+ *(((int *)&entry)+1));
+ io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
+ *(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);
}
- disconnect_bsp_APIC(pin != -1);
+ disconnect_bsp_APIC(ioapic_i8259.pin != -1);
}
/*
@@ -1571,7 +1635,7 @@ static void enable_lapic_irq (unsigned int irq)
unsigned long v;
v = apic_read(APIC_LVT0);
- apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED);
+ apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
}
static void disable_lapic_irq (unsigned int irq)
@@ -1579,7 +1643,7 @@ static void disable_lapic_irq (unsigned int irq)
unsigned long v;
v = apic_read(APIC_LVT0);
- apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED);
+ apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
}
static void ack_lapic_irq (unsigned int irq)
@@ -1626,20 +1690,21 @@ static void setup_nmi (void)
*/
static inline void unlock_ExtINT_logic(void)
{
- int pin, i;
+ int apic, pin, i;
struct IO_APIC_route_entry entry0, entry1;
unsigned char save_control, save_freq_select;
unsigned long flags;
- pin = find_isa_irq_pin(8, mp_INT);
+ pin = find_isa_irq_pin(8, mp_INT);
+ apic = find_isa_irq_apic(8, mp_INT);
if (pin == -1)
return;
spin_lock_irqsave(&ioapic_lock, flags);
- *(((int *)&entry0) + 1) = io_apic_read(0, 0x11 + 2 * pin);
- *(((int *)&entry0) + 0) = io_apic_read(0, 0x10 + 2 * pin);
+ *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+ *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
spin_unlock_irqrestore(&ioapic_lock, flags);
- clear_IO_APIC_pin(0, pin);
+ clear_IO_APIC_pin(apic, pin);
memset(&entry1, 0, sizeof(entry1));
@@ -1652,8 +1717,8 @@ static inline void unlock_ExtINT_logic(void)
entry1.vector = 0;
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
- io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);
save_control = CMOS_READ(RTC_CONTROL);
@@ -1671,11 +1736,11 @@ static inline void unlock_ExtINT_logic(void)
CMOS_WRITE(save_control, RTC_CONTROL);
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- clear_IO_APIC_pin(0, pin);
+ clear_IO_APIC_pin(apic, pin);
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(0, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
- io_apic_write(0, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
spin_unlock_irqrestore(&ioapic_lock, flags);
}
@@ -1687,7 +1752,7 @@ static inline void unlock_ExtINT_logic(void)
*/
static inline void check_timer(void)
{
- int pin1, pin2;
+ int apic1, pin1, apic2, pin2;
int vector;
/*
@@ -1704,14 +1769,17 @@ static inline void check_timer(void)
* the 8259A which implies the virtual wire has to be
* disabled in the local APIC.
*/
- apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
+ apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1);
enable_8259A_irq(0);
- pin1 = find_isa_irq_pin(0, mp_INT);
- pin2 = find_isa_irq_pin(0, mp_ExtINT);
+ pin1 = find_isa_irq_pin(0, mp_INT);
+ apic1 = find_isa_irq_apic(0, mp_INT);
+ pin2 = ioapic_i8259.pin;
+ apic2 = ioapic_i8259.apic;
- apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+ apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
+ vector, apic1, pin1, apic2, pin2);
if (pin1 != -1) {
/*
@@ -1729,17 +1797,20 @@ static inline void check_timer(void)
clear_IO_APIC_pin(0, pin1);
return;
}
- clear_IO_APIC_pin(0, pin1);
- apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+ clear_IO_APIC_pin(apic1, pin1);
+ apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not "
+ "connected to IO-APIC\n");
}
- apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
+ apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) "
+ "through the 8259A ... ");
if (pin2 != -1) {
- apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2);
+ apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...",
+ apic2, pin2);
/*
* legacy devices should be connected to IO APIC #0
*/
- setup_ExtINT_IRQ0_pin(pin2, vector);
+ setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
if (timer_irq_works()) {
printk("works.\n");
nmi_watchdog_default();
@@ -1751,7 +1822,7 @@ static inline void check_timer(void)
/*
* Cleanup, just in case ...
*/
- clear_IO_APIC_pin(0, pin2);
+ clear_IO_APIC_pin(apic2, pin2);
}
printk(" failed.\n");
@@ -1764,21 +1835,21 @@ static inline void check_timer(void)
disable_8259A_irq(0);
irq_desc[0].handler = &lapic_irq_type;
- apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
+ apic_write(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
enable_8259A_irq(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, " works.\n");
return;
}
- apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+ apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
apic_printk(APIC_VERBOSE," failed.\n");
apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
init_8259A(0);
make_8259A_irq(0);
- apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+ apic_write(APIC_LVT0, APIC_DM_EXTINT);
unlock_ExtINT_logic();
diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
index cde0e868efe3..b81614970ecc 100644
--- a/arch/x86_64/kernel/ioport.c
+++ b/arch/x86_64/kernel/ioport.c
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/ioport.h>
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index d6a04a8320a3..30d2a1e545fe 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io_apic.h>
+#include <asm/idle.h>
atomic_t irq_err_count;
#ifdef CONFIG_X86_IO_APIC
@@ -69,13 +70,13 @@ skip:
seq_printf(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
- seq_printf(p, "%10u ", cpu_pda[j].__nmi_count);
+ seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
seq_putc(p, '\n');
#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
- seq_printf(p, "%10u ", cpu_pda[j].apic_timer_irqs);
+ seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -98,6 +99,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
/* high bits used in ret_from_ code */
unsigned irq = regs->orig_rax & 0xff;
+ exit_idle();
irq_enter();
__do_IRQ(irq, regs);
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index afe11f4fbd1d..8b866a8572cf 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -42,8 +42,8 @@
#include <asm/pgtable.h>
#include <asm/kdebug.h>
-static DECLARE_MUTEX(kprobe_mutex);
void jprobe_return_end(void);
+static void __kprobes arch_copy_kprobe(struct kprobe *p);
DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -69,12 +69,11 @@ static inline int is_IF_modifier(kprobe_opcode_t *insn)
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
/* insn: must be on special executable page on x86_64. */
- down(&kprobe_mutex);
p->ainsn.insn = get_insn_slot();
- up(&kprobe_mutex);
if (!p->ainsn.insn) {
return -ENOMEM;
}
+ arch_copy_kprobe(p);
return 0;
}
@@ -181,7 +180,7 @@ static inline s32 *is_riprel(u8 *insn)
return NULL;
}
-void __kprobes arch_copy_kprobe(struct kprobe *p)
+static void __kprobes arch_copy_kprobe(struct kprobe *p)
{
s32 *ripdisp;
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
@@ -335,6 +334,15 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
return 1;
}
} else {
+ if (*addr != BREAKPOINT_INSTRUCTION) {
+ /* The breakpoint instruction was removed by
+ * another cpu right after we hit, no further
+ * handling of this interrupt is appropriate
+ */
+ regs->rip = (unsigned long)addr;
+ ret = 1;
+ goto no_kprobe;
+ }
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 183dc6105429..13a2eada6c95 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -15,6 +15,7 @@
#include <linux/sysdev.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
+#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/percpu.h>
#include <linux/ctype.h>
@@ -23,9 +24,10 @@
#include <asm/mce.h>
#include <asm/kdebug.h>
#include <asm/uaccess.h>
+#include <asm/smp.h>
#define MISC_MCELOG_MINOR 227
-#define NR_BANKS 5
+#define NR_BANKS 6
static int mce_dont_init;
@@ -91,6 +93,7 @@ void mce_log(struct mce *mce)
static void print_mce(struct mce *m)
{
printk(KERN_EMERG "\n"
+ KERN_EMERG "HARDWARE ERROR\n"
KERN_EMERG
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
m->cpu, m->mcgstatus, m->bank, m->status);
@@ -109,6 +112,9 @@ static void print_mce(struct mce *m)
if (m->misc)
printk("MISC %Lx ", m->misc);
printk("\n");
+ printk(KERN_EMERG "This is not a software problem!\n");
+ printk(KERN_EMERG
+ "Run through mcelog --ascii to decode and contact your hardware vendor\n");
}
static void mce_panic(char *msg, struct mce *backup, unsigned long start)
@@ -168,12 +174,12 @@ void do_machine_check(struct pt_regs * regs, long error_code)
int panicm_found = 0;
if (regs)
- notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL);
+ notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL);
if (!banks)
return;
memset(&m, 0, sizeof(struct mce));
- m.cpu = hard_smp_processor_id();
+ m.cpu = safe_smp_processor_id();
rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
if (!(m.mcgstatus & MCG_STATUS_RIPV))
kill_it = 1;
@@ -573,6 +579,10 @@ ACCESSOR(bank1ctl,bank[1],mce_restart())
ACCESSOR(bank2ctl,bank[2],mce_restart())
ACCESSOR(bank3ctl,bank[3],mce_restart())
ACCESSOR(bank4ctl,bank[4],mce_restart())
+ACCESSOR(bank5ctl,bank[5],mce_restart())
+static struct sysdev_attribute * bank_attributes[NR_BANKS] = {
+ &attr_bank0ctl, &attr_bank1ctl, &attr_bank2ctl,
+ &attr_bank3ctl, &attr_bank4ctl, &attr_bank5ctl};
ACCESSOR(tolerant,tolerant,)
ACCESSOR(check_interval,check_interval,mce_restart())
@@ -580,6 +590,7 @@ ACCESSOR(check_interval,check_interval,mce_restart())
static __cpuinit int mce_create_device(unsigned int cpu)
{
int err;
+ int i;
if (!mce_available(&cpu_data[cpu]))
return -EIO;
@@ -589,11 +600,9 @@ static __cpuinit int mce_create_device(unsigned int cpu)
err = sysdev_register(&per_cpu(device_mce,cpu));
if (!err) {
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank0ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank1ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank2ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank3ctl);
- sysdev_create_file(&per_cpu(device_mce,cpu), &attr_bank4ctl);
+ for (i = 0; i < banks; i++)
+ sysdev_create_file(&per_cpu(device_mce,cpu),
+ bank_attributes[i]);
sysdev_create_file(&per_cpu(device_mce,cpu), &attr_tolerant);
sysdev_create_file(&per_cpu(device_mce,cpu), &attr_check_interval);
}
@@ -603,11 +612,11 @@ static __cpuinit int mce_create_device(unsigned int cpu)
#ifdef CONFIG_HOTPLUG_CPU
static __cpuinit void mce_remove_device(unsigned int cpu)
{
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank0ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank1ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank2ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank3ctl);
- sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_bank4ctl);
+ int i;
+
+ for (i = 0; i < banks; i++)
+ sysdev_remove_file(&per_cpu(device_mce,cpu),
+ bank_attributes[i]);
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant);
sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
sysdev_unregister(&per_cpu(device_mce,cpu));
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index 1f76175ace02..d3ad7d81266d 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -27,6 +27,7 @@
#include <asm/mce.h>
#include <asm/msr.h>
#include <asm/percpu.h>
+#include <asm/idle.h>
#define PFX "mce_threshold: "
#define VERSION "version 1.00.9"
@@ -140,6 +141,7 @@ asmlinkage void mce_threshold_interrupt(void)
struct mce m;
ack_APIC_irq();
+ exit_idle();
irq_enter();
memset(&m, 0, sizeof(m));
@@ -318,7 +320,7 @@ static struct kobj_type threshold_ktype = {
static __cpuinit int threshold_create_bank(unsigned int cpu, int bank)
{
int err = 0;
- struct threshold_bank *b = 0;
+ struct threshold_bank *b = NULL;
#ifdef CONFIG_SMP
if (cpu_core_id[cpu] && shared_bank[bank]) { /* symlink */
@@ -407,7 +409,7 @@ static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank)
if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) {
sprintf(name, "bank%i", bank);
sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name);
- per_cpu(threshold_banks, cpu)[bank] = 0;
+ per_cpu(threshold_banks, cpu)[bank] = NULL;
} else {
kobject_unregister(&b->kobj);
kfree(per_cpu(threshold_banks, cpu)[bank]);
diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c
index 0be0a7959814..8f533d2c40cb 100644
--- a/arch/x86_64/kernel/mce_intel.c
+++ b/arch/x86_64/kernel/mce_intel.c
@@ -10,6 +10,7 @@
#include <asm/msr.h>
#include <asm/mce.h>
#include <asm/hw_irq.h>
+#include <asm/idle.h>
static DEFINE_PER_CPU(unsigned long, next_check);
@@ -19,6 +20,7 @@ asmlinkage void smp_thermal_interrupt(void)
ack_APIC_irq();
+ exit_idle();
irq_enter();
if (time_before(jiffies, __get_cpu_var(next_check)))
goto done;
@@ -78,7 +80,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
h = THERMAL_APIC_VECTOR;
h |= (APIC_DM_FIXED | APIC_LVT_MASKED);
- apic_write_around(APIC_LVTTHMR, h);
+ apic_write(APIC_LVTTHMR, h);
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h);
@@ -87,7 +89,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
wrmsr(MSR_IA32_MISC_ENABLE, l | (1 << 3), h);
l = apic_read(APIC_LVTTHMR);
- apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+ apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
cpu, tm2 ? "TM2" : "TM1");
return;
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 39d445e16f22..5fae6f0cd994 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -151,23 +151,25 @@ int __init check_nmi_watchdog (void)
printk(KERN_INFO "testing NMI watchdog ... ");
+#ifdef CONFIG_SMP
if (nmi_watchdog == NMI_LOCAL_APIC)
smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
+#endif
for (cpu = 0; cpu < NR_CPUS; cpu++)
- counts[cpu] = cpu_pda[cpu].__nmi_count;
+ counts[cpu] = cpu_pda(cpu)->__nmi_count;
local_irq_enable();
mdelay((10*1000)/nmi_hz); // wait 10 ticks
for (cpu = 0; cpu < NR_CPUS; cpu++) {
if (!cpu_online(cpu))
continue;
- if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
+ if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) {
endflag = 1;
printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
cpu,
counts[cpu],
- cpu_pda[cpu].__nmi_count);
+ cpu_pda(cpu)->__nmi_count);
nmi_active = 0;
lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
nmi_perfctr_msr = 0;
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index cab471cf3edb..2f5d8328e2b9 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -8,53 +8,259 @@
#include <linux/pci.h>
#include <linux/module.h>
#include <asm/io.h>
+#include <asm/proto.h>
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA. This is the scatter-gather version of the
- * above pci_map_single interface. Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length. They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- * DMA address/length pairs than there are SG table elements.
- * (for example via virtual mapping capabilities)
- * The routine returns the number of addr/length pairs actually
- * used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
+int iommu_merge __read_mostly = 0;
+EXPORT_SYMBOL(iommu_merge);
+
+dma_addr_t bad_dma_address __read_mostly;
+EXPORT_SYMBOL(bad_dma_address);
+
+/* This tells the BIO block layer to assume merging. Default to off
+ because we cannot guarantee merging later. */
+int iommu_bio_merge __read_mostly = 0;
+EXPORT_SYMBOL(iommu_bio_merge);
+
+int iommu_sac_force __read_mostly = 0;
+EXPORT_SYMBOL(iommu_sac_force);
+
+int no_iommu __read_mostly;
+#ifdef CONFIG_IOMMU_DEBUG
+int panic_on_overflow __read_mostly = 1;
+int force_iommu __read_mostly = 1;
+#else
+int panic_on_overflow __read_mostly = 0;
+int force_iommu __read_mostly= 0;
+#endif
+
+/* Dummy device used for NULL arguments (normally ISA). Better would
+ be probably a smaller DMA mask, but this is bug-to-bug compatible
+ to i386. */
+struct device fallback_dev = {
+ .bus_id = "fallback device",
+ .coherent_dma_mask = 0xffffffff,
+ .dma_mask = &fallback_dev.coherent_dma_mask,
+};
+
+/* Allocate DMA memory on node near device */
+noinline static void *
+dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
+{
+ struct page *page;
+ int node;
+ 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;
+}
+
+/*
+ * Allocate memory for a coherent mapping.
*/
-int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction)
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp)
{
- int i;
-
- BUG_ON(direction == DMA_NONE);
- for (i = 0; i < nents; i++ ) {
- struct scatterlist *s = &sg[i];
- BUG_ON(!s->page);
- s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
- s->dma_length = s->length;
+ void *memory;
+ unsigned long dma_mask = 0;
+ u64 bus;
+
+ if (!dev)
+ dev = &fallback_dev;
+ dma_mask = dev->coherent_dma_mask;
+ if (dma_mask == 0)
+ dma_mask = 0xffffffff;
+
+ /* Kludge to make it bug-to-bug compatible with i386. i386
+ uses the normal dma_mask for alloc_coherent. */
+ dma_mask &= *dev->dma_mask;
+
+ /* Why <=? Even when the mask is smaller than 4GB it is often
+ larger than 16MB and in this case we have a chance of
+ finding fitting memory in the next higher zone first. If
+ not retry with true GFP_DMA. -AK */
+ if (dma_mask <= 0xffffffff)
+ gfp |= GFP_DMA32;
+
+ again:
+ memory = dma_alloc_pages(dev, gfp, get_order(size));
+ if (memory == NULL)
+ return NULL;
+
+ {
+ int high, mmu;
+ bus = virt_to_bus(memory);
+ high = (bus + size) >= dma_mask;
+ mmu = high;
+ if (force_iommu && !(gfp & GFP_DMA))
+ mmu = 1;
+ else if (high) {
+ free_pages((unsigned long)memory,
+ get_order(size));
+
+ /* Don't use the 16MB ZONE_DMA unless absolutely
+ needed. It's better to use remapping first. */
+ if (dma_mask < 0xffffffff && !(gfp & GFP_DMA)) {
+ gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+ goto again;
+ }
+
+ if (dma_ops->alloc_coherent)
+ return dma_ops->alloc_coherent(dev, size,
+ dma_handle, gfp);
+ return NULL;
+ }
+
+ memset(memory, 0, size);
+ if (!mmu) {
+ *dma_handle = virt_to_bus(memory);
+ return memory;
+ }
+ }
+
+ if (dma_ops->alloc_coherent) {
+ free_pages((unsigned long)memory, get_order(size));
+ gfp &= ~(GFP_DMA|GFP_DMA32);
+ return dma_ops->alloc_coherent(dev, size, dma_handle, gfp);
+ }
+
+ if (dma_ops->map_simple) {
+ *dma_handle = dma_ops->map_simple(dev, memory,
+ size,
+ PCI_DMA_BIDIRECTIONAL);
+ if (*dma_handle != bad_dma_address)
+ return memory;
}
- return nents;
-}
-EXPORT_SYMBOL(dma_map_sg);
+ if (panic_on_overflow)
+ panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n",size);
+ free_pages((unsigned long)memory, get_order(size));
+ return NULL;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
+/*
+ * Unmap coherent memory.
+ * The caller must ensure that the device has finished accessing the mapping.
*/
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, int dir)
+void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t bus)
+{
+ if (dma_ops->unmap_single)
+ dma_ops->unmap_single(dev, bus, size, 0);
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+int dma_supported(struct device *dev, u64 mask)
+{
+ if (dma_ops->dma_supported)
+ return dma_ops->dma_supported(dev, mask);
+
+ /* Copied from i386. Doesn't make much sense, because it will
+ only work for pci_alloc_coherent.
+ The caller just has to use GFP_DMA in this case. */
+ if (mask < 0x00ffffff)
+ return 0;
+
+ /* Tell the device to use SAC when IOMMU force is on. This
+ allows the driver to use cheaper accesses in some cases.
+
+ Problem with this is that if we overflow the IOMMU area and
+ return DAC as fallback address the device may not handle it
+ correctly.
+
+ As a special case some controllers have a 39bit address
+ mode that is as efficient as 32bit (aic79xx). Don't force
+ SAC for these. Assume all masks <= 40 bits are of this
+ type. Normally this doesn't make any difference, but gives
+ more gentle handling of IOMMU overflow. */
+ if (iommu_sac_force && (mask >= 0xffffffffffULL)) {
+ printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 mask)
{
- int i;
- for (i = 0; i < nents; i++) {
- struct scatterlist *s = &sg[i];
- BUG_ON(s->page == NULL);
- BUG_ON(s->dma_address == 0);
- dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
- }
+ if (!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+ *dev->dma_mask = mask;
+ return 0;
}
+EXPORT_SYMBOL(dma_set_mask);
+
+/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
+ [,forcesac][,fullflush][,nomerge][,biomerge]
+ size set size of iommu (in bytes)
+ noagp don't initialize the AGP driver and use full aperture.
+ off don't use the IOMMU
+ leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
+ memaper[=order] allocate an own aperture over RAM with size 32MB^order.
+ noforce don't force IOMMU usage. Default.
+ force Force IOMMU.
+ merge Do lazy merging. This may improve performance on some block devices.
+ Implies force (experimental)
+ biomerge Do merging at the BIO layer. This is more efficient than merge,
+ but should be only done with very big IOMMUs. Implies merge,force.
+ nomerge Don't do SG merging.
+ forcesac For SAC mode for masks <40bits (experimental)
+ fullflush Flush IOMMU on each allocation (default)
+ nofullflush Don't use IOMMU fullflush
+ allowed overwrite iommu off workarounds for specific chipsets.
+ soft Use software bounce buffering (default for Intel machines)
+ noaperture Don't touch the aperture for AGP.
+*/
+__init int iommu_setup(char *p)
+{
+ iommu_merge = 1;
-EXPORT_SYMBOL(dma_unmap_sg);
+ while (*p) {
+ if (!strncmp(p,"off",3))
+ no_iommu = 1;
+ /* gart_parse_options has more force support */
+ if (!strncmp(p,"force",5))
+ force_iommu = 1;
+ if (!strncmp(p,"noforce",7)) {
+ iommu_merge = 0;
+ force_iommu = 0;
+ }
+
+ if (!strncmp(p, "biomerge",8)) {
+ iommu_bio_merge = 4096;
+ iommu_merge = 1;
+ force_iommu = 1;
+ }
+ if (!strncmp(p, "panic",5))
+ panic_on_overflow = 1;
+ if (!strncmp(p, "nopanic",7))
+ panic_on_overflow = 0;
+ if (!strncmp(p, "merge",5)) {
+ iommu_merge = 1;
+ force_iommu = 1;
+ }
+ if (!strncmp(p, "nomerge",7))
+ iommu_merge = 0;
+ if (!strncmp(p, "forcesac",8))
+ iommu_sac_force = 1;
+
+#ifdef CONFIG_SWIOTLB
+ if (!strncmp(p, "soft",4))
+ swiotlb = 1;
+#endif
+
+#ifdef CONFIG_GART_IOMMU
+ gart_parse_options(p);
+#endif
+
+ p += strcspn(p, ",");
+ if (*p == ',')
+ ++p;
+ }
+ return 1;
+}
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 2e28e855ec3c..c37fc7726ba6 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -30,8 +30,8 @@
#include <asm/proto.h>
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
-
-dma_addr_t bad_dma_address;
+#include <asm/swiotlb.h>
+#include <asm/dma.h>
unsigned long iommu_bus_base; /* GART remapping area (physical) */
static unsigned long iommu_size; /* size of remapping area bytes */
@@ -39,18 +39,6 @@ static unsigned long iommu_pages; /* .. and in pages */
u32 *iommu_gatt_base; /* Remapping table */
-int no_iommu;
-static int no_agp;
-#ifdef CONFIG_IOMMU_DEBUG
-int panic_on_overflow = 1;
-int force_iommu = 1;
-#else
-int panic_on_overflow = 0;
-int force_iommu = 0;
-#endif
-int iommu_merge = 1;
-int iommu_sac_force = 0;
-
/* If this is disabled the IOMMU will use an optimized flushing strategy
of only flushing when an mapping is reused. With it true the GART is flushed
for every mapping. Problem is that doing the lazy flush seems to trigger
@@ -58,10 +46,6 @@ int iommu_sac_force = 0;
also seen with Qlogic at least). */
int iommu_fullflush = 1;
-/* This tells the BIO block layer to assume merging. Default to off
- because we cannot guarantee merging later. */
-int iommu_bio_merge = 0;
-
#define MAX_NB 8
/* Allocation bitmap for the remapping area */
@@ -102,16 +86,6 @@ AGPEXTERN __u32 *agp_gatt_table;
static unsigned long next_bit; /* protected by iommu_bitmap_lock */
static int need_flush; /* global flush state. set for each gart wrap */
-static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
- size_t size, int dir, int do_panic);
-
-/* Dummy device used for NULL arguments (normally ISA). Better would
- be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */
-static struct device fallback_dev = {
- .bus_id = "fallback device",
- .coherent_dma_mask = 0xffffffff,
- .dma_mask = &fallback_dev.coherent_dma_mask,
-};
static unsigned long alloc_iommu(int size)
{
@@ -185,114 +159,7 @@ static void flush_gart(struct device *dev)
spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
}
-/* Allocate DMA memory on node near device */
-noinline
-static void *dma_alloc_pages(struct device *dev, gfp_t gfp, unsigned order)
-{
- struct page *page;
- int node;
- 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;
-}
-
-/*
- * Allocate memory for a coherent mapping.
- */
-void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp)
-{
- void *memory;
- unsigned long dma_mask = 0;
- u64 bus;
- if (!dev)
- dev = &fallback_dev;
- dma_mask = dev->coherent_dma_mask;
- if (dma_mask == 0)
- dma_mask = 0xffffffff;
-
- /* Kludge to make it bug-to-bug compatible with i386. i386
- uses the normal dma_mask for alloc_coherent. */
- dma_mask &= *dev->dma_mask;
-
- /* Why <=? Even when the mask is smaller than 4GB it is often larger
- than 16MB and in this case we have a chance of finding fitting memory
- in the next higher zone first. If not retry with true GFP_DMA. -AK */
- if (dma_mask <= 0xffffffff)
- gfp |= GFP_DMA32;
-
- again:
- memory = dma_alloc_pages(dev, gfp, get_order(size));
- if (memory == NULL)
- return NULL;
-
- {
- int high, mmu;
- bus = virt_to_bus(memory);
- high = (bus + size) >= dma_mask;
- mmu = high;
- if (force_iommu && !(gfp & GFP_DMA))
- mmu = 1;
- if (no_iommu || dma_mask < 0xffffffffUL) {
- if (high) {
- free_pages((unsigned long)memory,
- get_order(size));
-
- if (swiotlb) {
- return
- swiotlb_alloc_coherent(dev, size,
- dma_handle,
- gfp);
- }
-
- if (!(gfp & GFP_DMA)) {
- gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
- goto again;
- }
- return NULL;
- }
- mmu = 0;
- }
- memset(memory, 0, size);
- if (!mmu) {
- *dma_handle = virt_to_bus(memory);
- return memory;
- }
- }
-
- *dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0);
- if (*dma_handle == bad_dma_address)
- goto error;
- flush_gart(dev);
- return memory;
-
-error:
- if (panic_on_overflow)
- panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size);
- free_pages((unsigned long)memory, get_order(size));
- return NULL;
-}
-
-/*
- * Unmap coherent memory.
- * The caller must ensure that the device has finished accessing the mapping.
- */
-void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t bus)
-{
- if (swiotlb) {
- swiotlb_free_coherent(dev, size, vaddr, bus);
- return;
- }
-
- dma_unmap_single(dev, bus, size, 0);
- free_pages((unsigned long)vaddr, get_order(size));
-}
#ifdef CONFIG_IOMMU_LEAK
@@ -326,7 +193,7 @@ void dump_leak(void)
#define CLEAR_LEAK(x)
#endif
-static void iommu_full(struct device *dev, size_t size, int dir, int do_panic)
+static void iommu_full(struct device *dev, size_t size, int dir)
{
/*
* Ran out of IOMMU space for this operation. This is very bad.
@@ -342,11 +209,11 @@ static void iommu_full(struct device *dev, size_t size, int dir, int do_panic)
"PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n",
size, dev->bus_id);
- if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) {
+ if (size > PAGE_SIZE*EMERGENCY_PAGES) {
if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
panic("PCI-DMA: Memory would be corrupted\n");
if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL)
- panic("PCI-DMA: Random memory would be DMAed\n");
+ panic(KERN_ERR "PCI-DMA: Random memory would be DMAed\n");
}
#ifdef CONFIG_IOMMU_LEAK
@@ -385,8 +252,8 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t
/* Map a single continuous physical area into the IOMMU.
* Caller needs to check if the iommu is needed and flush.
*/
-static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
- size_t size, int dir, int do_panic)
+static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
+ size_t size, int dir)
{
unsigned long npages = to_pages(phys_mem, size);
unsigned long iommu_page = alloc_iommu(npages);
@@ -396,7 +263,7 @@ static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
return phys_mem;
if (panic_on_overflow)
panic("dma_map_area overflow %lu bytes\n", size);
- iommu_full(dev, size, dir, do_panic);
+ iommu_full(dev, size, dir);
return bad_dma_address;
}
@@ -408,15 +275,21 @@ static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK);
}
+static dma_addr_t gart_map_simple(struct device *dev, char *buf,
+ size_t size, int dir)
+{
+ dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
+ flush_gart(dev);
+ return map;
+}
+
/* Map a single area into the IOMMU */
-dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir)
+dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, int dir)
{
unsigned long phys_mem, bus;
BUG_ON(dir == DMA_NONE);
- if (swiotlb)
- return swiotlb_map_single(dev,addr,size,dir);
if (!dev)
dev = &fallback_dev;
@@ -424,10 +297,24 @@ dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir)
if (!need_iommu(dev, phys_mem, size))
return phys_mem;
- bus = dma_map_area(dev, phys_mem, size, dir, 1);
- flush_gart(dev);
+ bus = gart_map_simple(dev, addr, size, dir);
return bus;
-}
+}
+
+/*
+ * Wrapper for pci_unmap_single working with scatterlists.
+ */
+void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
+{
+ int i;
+
+ for (i = 0; i < nents; i++) {
+ struct scatterlist *s = &sg[i];
+ if (!s->dma_length || !s->length)
+ break;
+ dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
+ }
+}
/* Fallback for dma_map_sg in case of overflow */
static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
@@ -443,10 +330,10 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
struct scatterlist *s = &sg[i];
unsigned long addr = page_to_phys(s->page) + s->offset;
if (nonforced_iommu(dev, addr, s->length)) {
- addr = dma_map_area(dev, addr, s->length, dir, 0);
+ addr = dma_map_area(dev, addr, s->length, dir);
if (addr == bad_dma_address) {
if (i > 0)
- dma_unmap_sg(dev, sg, i, dir);
+ gart_unmap_sg(dev, sg, i, dir);
nents = 0;
sg[0].dma_length = 0;
break;
@@ -515,7 +402,7 @@ static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
* DMA map all entries in a scatterlist.
* Merge chunks that have page aligned sizes into a continuous mapping.
*/
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
+int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
{
int i;
int out;
@@ -527,8 +414,6 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
if (nents == 0)
return 0;
- if (swiotlb)
- return swiotlb_map_sg(dev,sg,nents,dir);
if (!dev)
dev = &fallback_dev;
@@ -571,13 +456,13 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
error:
flush_gart(NULL);
- dma_unmap_sg(dev, sg, nents, dir);
+ gart_unmap_sg(dev, sg, nents, dir);
/* When it was forced try again unforced */
if (force_iommu)
return dma_map_sg_nonforce(dev, sg, nents, dir);
if (panic_on_overflow)
panic("dma_map_sg: overflow on %lu pages\n", pages);
- iommu_full(dev, pages << PAGE_SHIFT, dir, 0);
+ iommu_full(dev, pages << PAGE_SHIFT, dir);
for (i = 0; i < nents; i++)
sg[i].dma_address = bad_dma_address;
return 0;
@@ -586,18 +471,13 @@ error:
/*
* Free a DMA mapping.
*/
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
size_t size, int direction)
{
unsigned long iommu_page;
int npages;
int i;
- if (swiotlb) {
- swiotlb_unmap_single(dev,dma_addr,size,direction);
- return;
- }
-
if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE ||
dma_addr >= iommu_bus_base + iommu_size)
return;
@@ -610,68 +490,7 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
free_iommu(iommu_page, npages);
}
-/*
- * Wrapper for pci_unmap_single working with scatterlists.
- */
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
-{
- int i;
- if (swiotlb) {
- swiotlb_unmap_sg(dev,sg,nents,dir);
- return;
- }
- for (i = 0; i < nents; i++) {
- struct scatterlist *s = &sg[i];
- if (!s->dma_length || !s->length)
- break;
- dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
- }
-}
-
-int dma_supported(struct device *dev, u64 mask)
-{
- /* Copied from i386. Doesn't make much sense, because it will
- only work for pci_alloc_coherent.
- The caller just has to use GFP_DMA in this case. */
- if (mask < 0x00ffffff)
- return 0;
-
- /* Tell the device to use SAC when IOMMU force is on.
- This allows the driver to use cheaper accesses in some cases.
-
- Problem with this is that if we overflow the IOMMU area
- and return DAC as fallback address the device may not handle it correctly.
-
- As a special case some controllers have a 39bit address mode
- that is as efficient as 32bit (aic79xx). Don't force SAC for these.
- Assume all masks <= 40 bits are of this type. Normally this doesn't
- make any difference, but gives more gentle handling of IOMMU overflow. */
- if (iommu_sac_force && (mask >= 0xffffffffffULL)) {
- printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
- return 0;
- }
-
- return 1;
-}
-
-int dma_get_cache_alignment(void)
-{
- return boot_cpu_data.x86_clflush_size;
-}
-
-EXPORT_SYMBOL(dma_unmap_sg);
-EXPORT_SYMBOL(dma_map_sg);
-EXPORT_SYMBOL(dma_map_single);
-EXPORT_SYMBOL(dma_unmap_single);
-EXPORT_SYMBOL(dma_supported);
-EXPORT_SYMBOL(no_iommu);
-EXPORT_SYMBOL(force_iommu);
-EXPORT_SYMBOL(bad_dma_address);
-EXPORT_SYMBOL(iommu_bio_merge);
-EXPORT_SYMBOL(iommu_sac_force);
-EXPORT_SYMBOL(dma_get_cache_alignment);
-EXPORT_SYMBOL(dma_alloc_coherent);
-EXPORT_SYMBOL(dma_free_coherent);
+static int no_agp;
static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
{
@@ -772,12 +591,27 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
nommu:
/* Should not happen anymore */
printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n"
- KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction.");
+ KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction.\n");
return -1;
}
extern int agp_amd64_init(void);
+static struct dma_mapping_ops gart_dma_ops = {
+ .mapping_error = NULL,
+ .map_single = gart_map_single,
+ .map_simple = gart_map_simple,
+ .unmap_single = gart_unmap_single,
+ .sync_single_for_cpu = NULL,
+ .sync_single_for_device = NULL,
+ .sync_single_range_for_cpu = NULL,
+ .sync_single_range_for_device = NULL,
+ .sync_sg_for_cpu = NULL,
+ .sync_sg_for_device = NULL,
+ .map_sg = gart_map_sg,
+ .unmap_sg = gart_unmap_sg,
+};
+
static int __init pci_iommu_init(void)
{
struct agp_kern_info info;
@@ -799,16 +633,15 @@ static int __init pci_iommu_init(void)
if (swiotlb) {
no_iommu = 1;
- printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
return -1;
}
if (no_iommu ||
- (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) ||
+ (!force_iommu && end_pfn <= MAX_DMA32_PFN) ||
!iommu_aperture ||
(no_agp && init_k8_gatt(&info) < 0)) {
- printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
no_iommu = 1;
+ no_iommu_init();
return -1;
}
@@ -885,100 +718,50 @@ static int __init pci_iommu_init(void)
flush_gart(NULL);
+ printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
+ dma_ops = &gart_dma_ops;
+
return 0;
}
/* Must execute after PCI subsystem */
fs_initcall(pci_iommu_init);
-/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
- [,forcesac][,fullflush][,nomerge][,biomerge]
- size set size of iommu (in bytes)
- noagp don't initialize the AGP driver and use full aperture.
- off don't use the IOMMU
- leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
- memaper[=order] allocate an own aperture over RAM with size 32MB^order.
- noforce don't force IOMMU usage. Default.
- force Force IOMMU.
- merge Do lazy merging. This may improve performance on some block devices.
- Implies force (experimental)
- biomerge Do merging at the BIO layer. This is more efficient than merge,
- but should be only done with very big IOMMUs. Implies merge,force.
- nomerge Don't do SG merging.
- forcesac For SAC mode for masks <40bits (experimental)
- fullflush Flush IOMMU on each allocation (default)
- nofullflush Don't use IOMMU fullflush
- allowed overwrite iommu off workarounds for specific chipsets.
- soft Use software bounce buffering (default for Intel machines)
- noaperture Don't touch the aperture for AGP.
-*/
-__init int iommu_setup(char *p)
-{
- int arg;
-
- while (*p) {
- if (!strncmp(p,"noagp",5))
- no_agp = 1;
- if (!strncmp(p,"off",3))
- no_iommu = 1;
- if (!strncmp(p,"force",5)) {
- force_iommu = 1;
- iommu_aperture_allowed = 1;
- }
- if (!strncmp(p,"allowed",7))
- iommu_aperture_allowed = 1;
- if (!strncmp(p,"noforce",7)) {
- iommu_merge = 0;
- force_iommu = 0;
- }
- if (!strncmp(p, "memaper", 7)) {
- fallback_aper_force = 1;
- p += 7;
- if (*p == '=') {
- ++p;
- if (get_option(&p, &arg))
- fallback_aper_order = arg;
- }
- }
- if (!strncmp(p, "biomerge",8)) {
- iommu_bio_merge = 4096;
- iommu_merge = 1;
- force_iommu = 1;
- }
- if (!strncmp(p, "panic",5))
- panic_on_overflow = 1;
- if (!strncmp(p, "nopanic",7))
- panic_on_overflow = 0;
- if (!strncmp(p, "merge",5)) {
- iommu_merge = 1;
- force_iommu = 1;
- }
- if (!strncmp(p, "nomerge",7))
- iommu_merge = 0;
- if (!strncmp(p, "forcesac",8))
- iommu_sac_force = 1;
- if (!strncmp(p, "fullflush",8))
- iommu_fullflush = 1;
- if (!strncmp(p, "nofullflush",11))
- iommu_fullflush = 0;
- if (!strncmp(p, "soft",4))
- swiotlb = 1;
- if (!strncmp(p, "noaperture",10))
- fix_aperture = 0;
+void gart_parse_options(char *p)
+{
+ int arg;
+
#ifdef CONFIG_IOMMU_LEAK
- if (!strncmp(p,"leak",4)) {
- leak_trace = 1;
- p += 4;
- if (*p == '=') ++p;
- if (isdigit(*p) && get_option(&p, &arg))
- iommu_leak_pages = arg;
- } else
+ if (!strncmp(p,"leak",4)) {
+ leak_trace = 1;
+ p += 4;
+ if (*p == '=') ++p;
+ if (isdigit(*p) && get_option(&p, &arg))
+ iommu_leak_pages = arg;
+ }
#endif
- if (isdigit(*p) && get_option(&p, &arg))
- iommu_size = arg;
- p += strcspn(p, ",");
- if (*p == ',')
- ++p;
- }
- return 1;
-}
+ if (isdigit(*p) && get_option(&p, &arg))
+ iommu_size = arg;
+ if (!strncmp(p, "fullflush",8))
+ iommu_fullflush = 1;
+ if (!strncmp(p, "nofullflush",11))
+ iommu_fullflush = 0;
+ if (!strncmp(p,"noagp",5))
+ no_agp = 1;
+ if (!strncmp(p, "noaperture",10))
+ fix_aperture = 0;
+ /* duplicated from pci-dma.c */
+ if (!strncmp(p,"force",5))
+ iommu_aperture_allowed = 1;
+ if (!strncmp(p,"allowed",7))
+ iommu_aperture_allowed = 1;
+ if (!strncmp(p, "memaper", 7)) {
+ fallback_aper_force = 1;
+ p += 7;
+ if (*p == '=') {
+ ++p;
+ if (get_option(&p, &arg))
+ fallback_aper_order = arg;
+ }
+ }
+}
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 5a981dca87ff..e41564975195 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -6,89 +6,94 @@
#include <linux/string.h>
#include <asm/proto.h>
#include <asm/processor.h>
+#include <asm/dma.h>
-int iommu_merge = 0;
-EXPORT_SYMBOL(iommu_merge);
-
-dma_addr_t bad_dma_address;
-EXPORT_SYMBOL(bad_dma_address);
-
-int iommu_bio_merge = 0;
-EXPORT_SYMBOL(iommu_bio_merge);
-
-int iommu_sac_force = 0;
-EXPORT_SYMBOL(iommu_sac_force);
-
-/*
- * Dummy IO MMU functions
- */
-
-void *dma_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+static int
+check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
{
- void *ret;
- u64 mask;
- int order = get_order(size);
-
- if (hwdev)
- mask = hwdev->coherent_dma_mask & *hwdev->dma_mask;
- else
- mask = 0xffffffff;
- for (;;) {
- ret = (void *)__get_free_pages(gfp, order);
- if (ret == NULL)
- return NULL;
- *dma_handle = virt_to_bus(ret);
- if ((*dma_handle & ~mask) == 0)
- break;
- free_pages((unsigned long)ret, order);
- if (gfp & GFP_DMA)
- return NULL;
- gfp |= GFP_DMA;
+ if (hwdev && bus + size > *hwdev->dma_mask) {
+ printk(KERN_ERR
+ "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
+ name, (long long)bus, size, (long long)*hwdev->dma_mask);
+ return 0;
}
+ return 1;
+}
- memset(ret, 0, size);
- return ret;
+static dma_addr_t
+nommu_map_single(struct device *hwdev, void *ptr, size_t size,
+ int direction)
+{
+ dma_addr_t bus = virt_to_bus(ptr);
+ if (!check_addr("map_single", hwdev, bus, size))
+ return bad_dma_address;
+ return bus;
}
-EXPORT_SYMBOL(dma_alloc_coherent);
-void dma_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+ int direction)
{
- free_pages((unsigned long)vaddr, get_order(size));
}
-EXPORT_SYMBOL(dma_free_coherent);
-int dma_supported(struct device *hwdev, u64 mask)
+/* Map a set of buffers described by scatterlist in streaming
+ * mode for DMA. This is the scatter-gather version of the
+ * above pci_map_single interface. Here the scatter gather list
+ * elements are each tagged with the appropriate dma address
+ * and length. They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ * DMA address/length pairs than there are SG table elements.
+ * (for example via virtual mapping capabilities)
+ * The routine returns the number of addr/length pairs actually
+ * used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
+ */
+int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, int direction)
{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- * RED-PEN this won't work for pci_map_single. Caller has to
- * use GFP_DMA in the first place.
- */
- if (mask < 0x00ffffff)
- return 0;
+ int i;
- return 1;
-}
-EXPORT_SYMBOL(dma_supported);
+ BUG_ON(direction == DMA_NONE);
+ for (i = 0; i < nents; i++ ) {
+ struct scatterlist *s = &sg[i];
+ BUG_ON(!s->page);
+ s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
+ if (!check_addr("map_sg", hwdev, s->dma_address, s->length))
+ return 0;
+ s->dma_length = s->length;
+ }
+ return nents;
+}
-int dma_get_cache_alignment(void)
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+void nommu_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nents, int dir)
{
- return boot_cpu_data.x86_clflush_size;
}
-EXPORT_SYMBOL(dma_get_cache_alignment);
-static int __init check_ram(void)
-{
- if (end_pfn >= 0xffffffff>>PAGE_SHIFT) {
- printk(
- KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
- KERN_ERR "WARNING 32bit PCI may malfunction.\n");
- }
- return 0;
-}
-__initcall(check_ram);
+struct dma_mapping_ops nommu_dma_ops = {
+ .map_single = nommu_map_single,
+ .unmap_single = nommu_unmap_single,
+ .map_sg = nommu_map_sg,
+ .unmap_sg = nommu_unmap_sg,
+ .is_phys = 1,
+};
+void __init no_iommu_init(void)
+{
+ if (dma_ops)
+ return;
+ printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
+ dma_ops = &nommu_dma_ops;
+ if (end_pfn > MAX_DMA32_PFN) {
+ printk(KERN_ERR
+ "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
+ KERN_ERR "WARNING 32bit PCI may malfunction.\n"
+ KERN_ERR "You might want to enable CONFIG_GART_IOMMU\n");
+ }
+}
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
new file mode 100644
index 000000000000..3569a25ad7fb
--- /dev/null
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -0,0 +1,42 @@
+/* Glue code to lib/swiotlb.c */
+
+#include <linux/pci.h>
+#include <linux/cache.h>
+#include <linux/module.h>
+#include <asm/dma-mapping.h>
+#include <asm/proto.h>
+#include <asm/swiotlb.h>
+#include <asm/dma.h>
+
+int swiotlb __read_mostly;
+EXPORT_SYMBOL(swiotlb);
+
+struct dma_mapping_ops swiotlb_dma_ops = {
+ .mapping_error = swiotlb_dma_mapping_error,
+ .alloc_coherent = swiotlb_alloc_coherent,
+ .free_coherent = swiotlb_free_coherent,
+ .map_single = swiotlb_map_single,
+ .unmap_single = swiotlb_unmap_single,
+ .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+ .sync_single_for_device = swiotlb_sync_single_for_device,
+ .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
+ .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
+ .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+ .sync_sg_for_device = swiotlb_sync_sg_for_device,
+ .map_sg = swiotlb_map_sg,
+ .unmap_sg = swiotlb_unmap_sg,
+ .dma_supported = NULL,
+};
+
+void pci_swiotlb_init(void)
+{
+ /* don't initialize swiotlb if iommu=off (no_iommu=1) */
+ if (!iommu_aperture && !no_iommu &&
+ (end_pfn > MAX_DMA32_PFN || force_iommu))
+ swiotlb = 1;
+ if (swiotlb) {
+ swiotlb_init();
+ printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
+ dma_ops = &swiotlb_dma_ops;
+ }
+}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 7519fc520eb3..8ded407e4a94 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -36,6 +36,7 @@
#include <linux/utsname.h>
#include <linux/random.h>
#include <linux/kprobes.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -50,13 +51,12 @@
#include <asm/desc.h>
#include <asm/proto.h>
#include <asm/ia32.h>
+#include <asm/idle.h>
asmlinkage extern void ret_from_fork(void);
unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
-static atomic_t hlt_counter = ATOMIC_INIT(0);
-
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
@@ -66,19 +66,49 @@ EXPORT_SYMBOL(boot_option_idle_override);
void (*pm_idle)(void);
static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
-void disable_hlt(void)
+static struct notifier_block *idle_notifier;
+static DEFINE_SPINLOCK(idle_notifier_lock);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&idle_notifier_lock, flags);
+ notifier_chain_register(&idle_notifier, n);
+ spin_unlock_irqrestore(&idle_notifier_lock, flags);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
{
- atomic_inc(&hlt_counter);
+ unsigned long flags;
+ spin_lock_irqsave(&idle_notifier_lock, flags);
+ notifier_chain_unregister(&idle_notifier, n);
+ spin_unlock_irqrestore(&idle_notifier_lock, flags);
}
+EXPORT_SYMBOL(idle_notifier_unregister);
-EXPORT_SYMBOL(disable_hlt);
+enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
+static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
-void enable_hlt(void)
+void enter_idle(void)
{
- atomic_dec(&hlt_counter);
+ __get_cpu_var(idle_state) = CPU_IDLE;
+ notifier_call_chain(&idle_notifier, IDLE_START, NULL);
}
-EXPORT_SYMBOL(enable_hlt);
+static void __exit_idle(void)
+{
+ __get_cpu_var(idle_state) = CPU_NOT_IDLE;
+ notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+}
+
+/* Called from interrupts to signify idle end */
+void exit_idle(void)
+{
+ if (current->pid | read_pda(irqcount))
+ return;
+ __exit_idle();
+}
/*
* We use this if we don't have any better
@@ -88,21 +118,16 @@ void default_idle(void)
{
local_irq_enable();
- if (!atomic_read(&hlt_counter)) {
- clear_thread_flag(TIF_POLLING_NRFLAG);
- smp_mb__after_clear_bit();
- while (!need_resched()) {
- local_irq_disable();
- if (!need_resched())
- safe_halt();
- else
- local_irq_enable();
- }
- set_thread_flag(TIF_POLLING_NRFLAG);
- } else {
- while (!need_resched())
- cpu_relax();
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb__after_clear_bit();
+ while (!need_resched()) {
+ local_irq_disable();
+ if (!need_resched())
+ safe_halt();
+ else
+ local_irq_enable();
}
+ set_thread_flag(TIF_POLLING_NRFLAG);
}
/*
@@ -157,7 +182,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
DECLARE_PER_CPU(int, cpu_state);
#include <asm/nmi.h>
-/* We don't actually take CPU down, just spin without interrupts. */
+/* We halt the CPU with physical CPU hotplug */
static inline void play_dead(void)
{
idle_task_exit();
@@ -166,8 +191,9 @@ static inline void play_dead(void)
/* Ack it */
__get_cpu_var(cpu_state) = CPU_DEAD;
+ local_irq_disable();
while (1)
- safe_halt();
+ halt();
}
#else
static inline void play_dead(void)
@@ -200,7 +226,9 @@ void cpu_idle (void)
idle = default_idle;
if (cpu_is_offline(smp_processor_id()))
play_dead();
+ enter_idle();
idle();
+ __exit_idle();
}
preempt_enable_no_resched();
@@ -423,7 +451,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
struct task_struct *me = current;
childregs = ((struct pt_regs *)
- (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+ (THREAD_SIZE + task_stack_page(p))) - 1;
*childregs = *regs;
childregs->rax = 0;
@@ -435,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
p->thread.rsp0 = (unsigned long) (childregs+1);
p->thread.userrsp = me->thread.userrsp;
- set_ti_thread_flag(p->thread_info, TIF_FORK);
+ set_tsk_thread_flag(p, TIF_FORK);
p->thread.fs = me->thread.fs;
p->thread.gs = me->thread.gs;
@@ -562,7 +590,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
write_pda(oldrsp, next->userrsp);
write_pda(pcurrent, next_p);
write_pda(kernelstack,
- (unsigned long)next_p->thread_info + THREAD_SIZE - PDA_STACKOFFSET);
+ task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
/*
* Now maybe reload the debug registers
@@ -676,7 +704,7 @@ unsigned long get_wchan(struct task_struct *p)
if (!p || p == current || p->state==TASK_RUNNING)
return 0;
- stack = (unsigned long)p->thread_info;
+ stack = (unsigned long)task_stack_page(p);
if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE)
return 0;
fp = *(u64 *)(p->thread.rsp);
@@ -794,8 +822,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{
struct pt_regs *pp, ptregs;
- pp = (struct pt_regs *)(tsk->thread.rsp0);
- --pp;
+ pp = task_pt_regs(tsk);
ptregs = *pp;
ptregs.cs &= 0xffff;
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index a87b6cebe80f..53205622351c 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -36,9 +36,12 @@
* in exit.c or in signal.c.
*/
-/* determines which flags the user has access to. */
-/* 1 = access 0 = no access */
-#define FLAG_MASK 0x44dd5UL
+/*
+ * Determines which flags the user has access to [1 = access, 0 = no access].
+ * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
+ * Also masks reserved bits (63-22, 15, 5, 3, 1).
+ */
+#define FLAG_MASK 0x54dd5UL
/* set's the trap flag. */
#define TRAP_FLAG 0x100UL
@@ -64,12 +67,6 @@ static inline unsigned long get_stack_long(struct task_struct *task, int offset)
return (*((unsigned long *)stack));
}
-static inline struct pt_regs *get_child_regs(struct task_struct *task)
-{
- struct pt_regs *regs = (void *)task->thread.rsp0;
- return regs - 1;
-}
-
/*
* this routine will put a word on the processes privileged stack.
* the offset is how far from the base addr as stored in the TSS.
@@ -167,7 +164,7 @@ static int is_at_popf(struct task_struct *child, struct pt_regs *regs)
static void set_singlestep(struct task_struct *child)
{
- struct pt_regs *regs = get_child_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
/*
* Always set TIF_SINGLESTEP - this guarantees that
@@ -205,7 +202,7 @@ static void clear_singlestep(struct task_struct *child)
/* But touch TF only if it was set by us.. */
if (child->ptrace & PT_DTRACE) {
- struct pt_regs *regs = get_child_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
regs->eflags &= ~TRAP_FLAG;
child->ptrace &= ~PT_DTRACE;
}
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
index 75235ed2b31b..57117b8beb2b 100644
--- a/arch/x86_64/kernel/reboot.c
+++ b/arch/x86_64/kernel/reboot.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/string.h>
+#include <linux/pm.h>
#include <asm/io.h>
#include <asm/kdebug.h>
#include <asm/delay.h>
@@ -154,10 +155,11 @@ void machine_halt(void)
void machine_power_off(void)
{
- if (!reboot_force) {
- machine_shutdown();
- }
- if (pm_power_off)
+ if (pm_power_off) {
+ if (!reboot_force) {
+ machine_shutdown();
+ }
pm_power_off();
+ }
}
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 750e01dcbdf4..28895c03cb11 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -35,6 +35,7 @@
#include <asm/processor.h>
#include <linux/console.h>
#include <linux/seq_file.h>
+#include <linux/crash_dump.h>
#include <linux/root_dev.h>
#include <linux/pci.h>
#include <linux/acpi.h>
@@ -42,6 +43,9 @@
#include <linux/edd.h>
#include <linux/mmzone.h>
#include <linux/kexec.h>
+#include <linux/cpufreq.h>
+#include <linux/dmi.h>
+#include <linux/dma-mapping.h>
#include <asm/mtrr.h>
#include <asm/uaccess.h>
@@ -60,7 +64,9 @@
#include <asm/setup.h>
#include <asm/mach_apic.h>
#include <asm/numa.h>
+#include <asm/swiotlb.h>
#include <asm/sections.h>
+#include <asm/gart-mapping.h>
/*
* Machine setup..
@@ -85,11 +91,6 @@ int bootloader_type;
unsigned long saved_video_mode;
-#ifdef CONFIG_SWIOTLB
-int swiotlb;
-EXPORT_SYMBOL(swiotlb);
-#endif
-
/*
* Setup options
*/
@@ -274,10 +275,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
{
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
- saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+ int userdef = 0;
for (;;) {
if (c != ' ')
@@ -345,10 +343,14 @@ static __init void parse_cmdline_early (char ** cmdline_p)
!memcmp(from, "disableapic", 11))
disable_apic = 1;
- if (!memcmp(from, "noapic", 6))
+ /* Don't confuse with noapictimer */
+ if (!memcmp(from, "noapic", 6) &&
+ (from[6] == ' ' || from[6] == 0))
skip_ioapic_setup = 1;
- if (!memcmp(from, "apic", 4)) {
+ /* Make sure to not confuse with apic= */
+ if (!memcmp(from, "apic", 4) &&
+ (from[4] == ' ' || from[4] == 0)) {
skip_ioapic_setup = 0;
ioapic_force = 1;
}
@@ -356,16 +358,36 @@ static __init void parse_cmdline_early (char ** cmdline_p)
if (!memcmp(from, "mem=", 4))
parse_memopt(from+4, &from);
+ if (!memcmp(from, "memmap=", 7)) {
+ /* exactmap option is for used defined memory */
+ if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+ /* If we are doing a crash dump, we
+ * still need to know the real mem
+ * size before original memory map is
+ * reset.
+ */
+ saved_max_pfn = e820_end_of_ram();
+#endif
+ from += 8+7;
+ end_pfn_map = 0;
+ e820.nr_map = 0;
+ userdef = 1;
+ }
+ else {
+ parse_memmapopt(from+7, &from);
+ userdef = 1;
+ }
+ }
+
#ifdef CONFIG_NUMA
if (!memcmp(from, "numa=", 5))
numa_setup(from+5);
#endif
-#ifdef CONFIG_GART_IOMMU
if (!memcmp(from,"iommu=",6)) {
iommu_setup(from+6);
}
-#endif
if (!memcmp(from,"oops=panic", 10))
panic_on_oops = 1;
@@ -394,6 +416,14 @@ static __init void parse_cmdline_early (char ** cmdline_p)
}
#endif
+#ifdef CONFIG_PROC_VMCORE
+ /* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel. This option will be passed
+ * by kexec loader to the capture kernel.
+ */
+ else if(!memcmp(from, "elfcorehdr=", 11))
+ elfcorehdr_addr = memparse(from+11, &from);
+#endif
next_char:
c = *(from++);
if (!c)
@@ -402,6 +432,10 @@ static __init void parse_cmdline_early (char ** cmdline_p)
break;
*(to++) = c;
}
+ if (userdef) {
+ printk(KERN_INFO "user-defined physical RAM map:\n");
+ e820_print_map("user");
+ }
*to = '\0';
*cmdline_p = command_line;
}
@@ -442,6 +476,8 @@ static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
};
+extern char __vsyscall_0;
+
/* Replace instructions with better alternatives for this CPU type.
This runs before SMP is initialized to avoid SMP problems with
@@ -453,11 +489,17 @@ void apply_alternatives(void *start, void *end)
struct alt_instr *a;
int diff, i, k;
for (a = start; (void *)a < end; a++) {
+ u8 *instr;
+
if (!boot_cpu_has(a->cpuid))
continue;
BUG_ON(a->replacementlen > a->instrlen);
- __inline_memcpy(a->instr, a->replacement, a->replacementlen);
+ instr = a->instr;
+ /* vsyscall code is not mapped yet. resolve it manually. */
+ if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END)
+ instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+ __inline_memcpy(instr, a->replacement, a->replacementlen);
diff = a->instrlen - a->replacementlen;
/* Pad the rest with nops */
@@ -465,7 +507,7 @@ void apply_alternatives(void *start, void *end)
k = diff;
if (k > ASM_NOP_MAX)
k = ASM_NOP_MAX;
- __inline_memcpy(a->instr + i, k8_nops[k], k);
+ __inline_memcpy(instr + i, k8_nops[k], k);
}
}
}
@@ -669,6 +711,8 @@ void __init setup_arch(char **cmdline_p)
acpi_boot_init();
#endif
+ init_cpu_to_node();
+
#ifdef CONFIG_X86_LOCAL_APIC
/*
* get boot-time SMP configuration:
@@ -833,7 +877,6 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
static int __init init_amd(struct cpuinfo_x86 *c)
{
int r;
- int level;
#ifdef CONFIG_SMP
unsigned long value;
@@ -856,11 +899,6 @@ static int __init init_amd(struct cpuinfo_x86 *c)
3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
clear_bit(0*32+31, &c->x86_capability);
- /* C-stepping K8? */
- level = cpuid_eax(1);
- if ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
- set_bit(X86_FEATURE_K8_C, &c->x86_capability);
-
r = get_model_name(c);
if (!r) {
switch (c->x86) {
@@ -873,6 +911,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
}
display_cacheinfo(c);
+ /* c->x86_power is 8000_0007 edx. Bit 8 is constant TSC */
+ if (c->x86_power & (1<<8))
+ set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+
if (c->extended_cpuid_level >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
if (c->x86_max_cores & (c->x86_max_cores - 1))
@@ -991,8 +1033,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if (c->x86 == 15)
c->x86_cache_alignment = c->x86_clflush_size * 2;
- if (c->x86 >= 15)
+ if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
+ (c->x86 == 0x6 && c->x86_model >= 0x0e))
set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+ set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
c->x86_max_cores = intel_num_cpu_cores(c);
srat_detect_node();
@@ -1191,7 +1235,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
- NULL, "fxsr_opt", NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
+ NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
/* Transmeta-defined */
"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1219,7 +1263,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* AMD-defined (#2) */
- "lahf_lm", "cmp_legacy", NULL, NULL, NULL, NULL, NULL, NULL,
+ "lahf_lm", "cmp_legacy", "svm", NULL, "cr8_legacy", NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -1230,7 +1274,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"vid", /* voltage id control */
"ttp", /* thermal trip */
"tm",
- "stc"
+ "stc",
+ NULL,
+ /* nothing */ /* constant_tsc - moved to flags */
};
@@ -1256,8 +1302,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: unknown\n");
if (cpu_has(c,X86_FEATURE_TSC)) {
+ unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+ if (!freq)
+ freq = cpu_khz;
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
- cpu_khz / 1000, (cpu_khz % 1000));
+ freq / 1000, (freq % 1000));
}
/* Cache size */
@@ -1307,8 +1356,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
unsigned i;
for (i = 0; i < 32; i++)
if (c->x86_power & (1 << i)) {
- if (i < ARRAY_SIZE(x86_power_flags))
- seq_printf(m, " %s", x86_power_flags[i]);
+ if (i < ARRAY_SIZE(x86_power_flags) &&
+ x86_power_flags[i])
+ seq_printf(m, "%s%s",
+ x86_power_flags[i][0]?" ":"",
+ x86_power_flags[i]);
else
seq_printf(m, " [%d]", i);
}
@@ -1340,3 +1392,11 @@ struct seq_operations cpuinfo_op = {
.stop = c_stop,
.show = show_cpuinfo,
};
+
+static int __init run_dmi_scan(void)
+{
+ dmi_scan_machine();
+ return 0;
+}
+core_initcall(run_dmi_scan);
+
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 06dc354375c3..70f1bb808a20 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -30,14 +30,15 @@ char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
-struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned;
+struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
+struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
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 __read_mostly = ~0UL;
-static int do_not_nx __initdata = 0;
+static int do_not_nx __cpuinitdata = 0;
/* noexec=on|off
Control non executable mappings for 64bit processes.
@@ -110,18 +111,18 @@ void __init setup_per_cpu_areas(void)
}
if (!ptr)
panic("Cannot allocate cpu data for CPU %d\n", i);
- cpu_pda[i].data_offset = ptr - __per_cpu_start;
+ cpu_pda(i)->data_offset = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
}
}
void pda_init(int cpu)
{
- struct x8664_pda *pda = &cpu_pda[cpu];
+ struct x8664_pda *pda = cpu_pda(cpu);
/* Setup up data that may be needed in __get_free_pages early */
asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
- wrmsrl(MSR_GS_BASE, cpu_pda + cpu);
+ wrmsrl(MSR_GS_BASE, pda);
pda->cpunumber = cpu;
pda->irqcount = -1;
@@ -145,7 +146,7 @@ void pda_init(int cpu)
pda->irqstackptr += IRQSTACKSIZE-64;
}
-char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ]
+char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
__attribute__((section(".bss.page_aligned")));
/* May not be marked __init: used by software suspend */
@@ -213,23 +214,14 @@ void __cpuinit cpu_init (void)
* Initialize the per-CPU GDT with the boot GDT,
* and set up the GDT descriptor:
*/
- if (cpu) {
- memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
- }
+ if (cpu)
+ memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
cpu_gdt_descr[cpu].size = GDT_SIZE;
- cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
asm volatile("lgdt %0" :: "m" (cpu_gdt_descr[cpu]));
asm volatile("lidt %0" :: "m" (idt_descr));
- memcpy(me->thread.tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);
-
- /*
- * Delete NT
- */
-
- asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax");
-
+ memset(me->thread.tls_array, 0, GDT_ENTRY_TLS_ENTRIES * 8);
syscall_init();
wrmsrl(MSR_FS_BASE, 0);
@@ -243,13 +235,27 @@ void __cpuinit cpu_init (void)
*/
for (v = 0; v < N_EXCEPTION_STACKS; v++) {
if (cpu) {
- estacks = (char *)__get_free_pages(GFP_ATOMIC,
- EXCEPTION_STACK_ORDER);
+ static const unsigned int order[N_EXCEPTION_STACKS] = {
+ [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+ [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+ };
+
+ estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
if (!estacks)
panic("Cannot allocate exception stack %ld %d\n",
v, cpu);
}
- estacks += EXCEPTION_STKSZ;
+ switch (v + 1) {
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+ case DEBUG_STACK:
+ cpu_pda[cpu].debugstack = (unsigned long)estacks;
+ estacks += DEBUG_STKSZ;
+ break;
+#endif
+ default:
+ estacks += EXCEPTION_STKSZ;
+ break;
+ }
t->ist[v] = (unsigned long)estacks;
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index cfc3d9dccbd9..19ef012b1f17 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -27,6 +27,7 @@
#include <asm/mmu_context.h>
#include <asm/proto.h>
#include <asm/apicdef.h>
+#include <asm/idle.h>
/*
* Smarter SMP flushing macros.
@@ -280,11 +281,6 @@ void flush_tlb_all(void)
on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
}
-void smp_kdb_stop(void)
-{
- send_IPI_allbutself(KDB_VECTOR);
-}
-
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
@@ -512,6 +508,7 @@ asmlinkage void smp_call_function_interrupt(void)
/*
* At this point the info structure may be out of scope unless wait==1
*/
+ exit_idle();
irq_enter();
(*func)(info);
irq_exit();
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index ecbd7b83acc1..a28756ef7cef 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -335,7 +335,13 @@ static __cpuinit void sync_tsc(unsigned int master)
static void __cpuinit tsc_sync_wait(void)
{
- if (notscsync || !cpu_has_tsc)
+ /*
+ * When the CPU has synchronized TSCs assume the BIOS
+ * or the hardware already synced. Otherwise we could
+ * mess up a possible perfect synchronization with a
+ * not-quite-perfect algorithm.
+ */
+ if (notscsync || !cpu_has_tsc || !unsynchronized_tsc())
return;
sync_tsc(0);
}
@@ -646,6 +652,7 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
+ mb();
atomic_set(&init_deasserted, 1);
num_starts = 2;
@@ -659,7 +666,6 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
for (j = 1; j <= num_starts; j++) {
Dprintk("Sending STARTUP #%d.\n",j);
- apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
Dprintk("After apic_write.\n");
@@ -698,7 +704,6 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
* Due to the Pentium erratum 3AP.
*/
if (maxlvt > 3) {
- apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0);
}
accept_status = (apic_read(APIC_ESR) & 0xEF);
@@ -743,11 +748,35 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
};
DECLARE_WORK(work, do_fork_idle, &c_idle);
+ /* allocate memory for gdts of secondary cpus. Hotplug is considered */
+ if (!cpu_gdt_descr[cpu].address &&
+ !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
+ printk(KERN_ERR "Failed to allocate GDT for CPU %d\n", cpu);
+ return -1;
+ }
+
+ /* Allocate node local memory for AP pdas */
+ if (cpu_pda(cpu) == &boot_cpu_pda[cpu]) {
+ struct x8664_pda *newpda, *pda;
+ int node = cpu_to_node(cpu);
+ pda = cpu_pda(cpu);
+ newpda = kmalloc_node(sizeof (struct x8664_pda), GFP_ATOMIC,
+ node);
+ if (newpda) {
+ memcpy(newpda, pda, sizeof (struct x8664_pda));
+ cpu_pda(cpu) = newpda;
+ } else
+ printk(KERN_ERR
+ "Could not allocate node local PDA for CPU %d on node %d\n",
+ cpu, node);
+ }
+
+
c_idle.idle = get_idle_for_cpu(cpu);
if (c_idle.idle) {
c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *)
- (THREAD_SIZE + (unsigned long) c_idle.idle->thread_info)) - 1);
+ (THREAD_SIZE + task_stack_page(c_idle.idle))) - 1);
init_idle(c_idle.idle, cpu);
goto do_rest;
}
@@ -778,14 +807,14 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
do_rest:
- cpu_pda[cpu].pcurrent = c_idle.idle;
+ cpu_pda(cpu)->pcurrent = c_idle.idle;
start_rip = setup_trampoline();
init_rsp = c_idle.idle->thread.rsp;
per_cpu(init_tss,cpu).rsp0 = init_rsp;
initial_code = start_secondary;
- clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK);
+ clear_tsk_thread_flag(c_idle.idle, TIF_FORK);
printk(KERN_INFO "Booting processor %d/%d APIC 0x%x\n", cpu,
cpus_weight(cpu_present_map),
@@ -811,11 +840,8 @@ do_rest:
/*
* Be paranoid about clearing APIC errors.
*/
- if (APIC_INTEGRATED(apic_version[apicid])) {
- apic_read_around(APIC_SPIV);
- apic_write(APIC_ESR, 0);
- apic_read(APIC_ESR);
- }
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
/*
* Status is now clean
@@ -927,8 +953,8 @@ int additional_cpus __initdata = -1;
*
* Three ways to find out the number of additional hotplug CPUs:
* - If the BIOS specified disabled CPUs in ACPI/mptables use that.
- * - otherwise use half of the available CPUs or 2, whatever is more.
* - The user can overwrite it with additional_cpus=NUM
+ * - Otherwise don't reserve additional CPUs.
* We do this because additional CPUs waste a lot of memory.
* -AK
*/
@@ -938,13 +964,10 @@ __init void prefill_possible_map(void)
int possible;
if (additional_cpus == -1) {
- if (disabled_cpus > 0) {
+ if (disabled_cpus > 0)
additional_cpus = disabled_cpus;
- } else {
- additional_cpus = num_processors / 2;
- if (additional_cpus == 0)
- additional_cpus = 2;
- }
+ else
+ additional_cpus = 0;
}
possible = num_processors + additional_cpus;
if (possible > NR_CPUS)
@@ -996,7 +1019,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
/*
* If we couldn't find a local APIC, then get out of here now!
*/
- if (APIC_INTEGRATED(apic_version[boot_cpu_id]) && !cpu_has_apic) {
+ if (!cpu_has_apic) {
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
boot_cpu_id);
printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index fd2bef780882..ecbd34c1093d 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -120,7 +120,7 @@ void fix_processor_context(void)
set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
- cpu_gdt_table[cpu][GDT_ENTRY_TSS].type = 9;
+ cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9;
syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c
index e263685f864c..7c176b3edde0 100644
--- a/arch/x86_64/kernel/syscall.c
+++ b/arch/x86_64/kernel/syscall.c
@@ -19,7 +19,7 @@ typedef void (*sys_call_ptr_t)(void);
extern void sys_ni_syscall(void);
-sys_call_ptr_t sys_call_table[__NR_syscall_max+1] __cacheline_aligned = {
+const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
/* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
[0 ... __NR_syscall_max] = &sys_ni_syscall,
#include <asm-x86_64/unistd.h>
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 74102796e5c0..f8c47c688443 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -71,14 +71,6 @@ unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
struct timespec __xtime __section_xtime;
struct timezone __sys_tz __section_sys_tz;
-static inline void rdtscll_sync(unsigned long *tsc)
-{
-#ifdef CONFIG_SMP
- sync_core();
-#endif
- rdtscll(*tsc);
-}
-
/*
* do_gettimeoffset() returns microseconds since last timer interrupt was
* triggered by hardware. A memory read of HPET is slower than a register read
@@ -93,7 +85,7 @@ static inline unsigned int do_gettimeoffset_tsc(void)
{
unsigned long t;
unsigned long x;
- rdtscll_sync(&t);
+ t = get_cycles_sync();
if (t < vxtime.last_tsc) t = vxtime.last_tsc; /* hack */
x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32;
return x;
@@ -259,8 +251,8 @@ static void set_rtc_mmss(unsigned long nowtime)
#endif
{
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
CMOS_WRITE(real_seconds, RTC_SECONDS);
CMOS_WRITE(real_minutes, RTC_MINUTES);
}
@@ -297,25 +289,21 @@ unsigned long long monotonic_clock(void)
last_offset = vxtime.last;
base = monotonic_base;
this_offset = hpet_readl(HPET_COUNTER);
-
} while (read_seqretry(&xtime_lock, seq));
offset = (this_offset - last_offset);
offset *=(NSEC_PER_SEC/HZ)/hpet_tick;
return base + offset;
- }else{
+ } else {
do {
seq = read_seqbegin(&xtime_lock);
last_offset = vxtime.last_tsc;
base = monotonic_base;
} while (read_seqretry(&xtime_lock, seq));
- sync_core();
- rdtscll(this_offset);
+ this_offset = get_cycles_sync();
offset = (this_offset - last_offset)*1000/cpu_khz;
return base + offset;
}
-
-
}
EXPORT_SYMBOL(monotonic_clock);
@@ -391,7 +379,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
delay = LATCH - 1 - delay;
}
- rdtscll_sync(&tsc);
+ tsc = get_cycles_sync();
if (vxtime.mode == VXTIME_HPET) {
if (offset - vxtime.last > hpet_tick) {
@@ -471,6 +459,11 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_sequnlock(&xtime_lock);
+#ifdef CONFIG_X86_LOCAL_APIC
+ if (using_apic_timer)
+ smp_send_timer_broadcast_ipi();
+#endif
+
return IRQ_HANDLED;
}
@@ -509,10 +502,10 @@ unsigned long long sched_clock(void)
return cycles_2_ns(a);
}
-unsigned long get_cmos_time(void)
+static unsigned long get_cmos_time(void)
{
- unsigned int timeout, year, mon, day, hour, min, sec;
- unsigned char last, this;
+ unsigned int timeout = 1000000, year, mon, day, hour, min, sec;
+ unsigned char uip = 0, this = 0;
unsigned long flags;
/*
@@ -525,45 +518,41 @@ unsigned long get_cmos_time(void)
spin_lock_irqsave(&rtc_lock, flags);
- timeout = 1000000;
- last = this = 0;
-
- while (timeout && last && !this) {
- last = this;
+ while (timeout && (!uip || this)) {
+ uip |= this;
this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP;
timeout--;
}
-/*
- * Here we are safe to assume the registers won't change for a whole second, so
- * we just go ahead and read them.
- */
-
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
+ /*
+ * Here we are safe to assume the registers won't change for a whole
+ * second, so we just go ahead and read them.
+ */
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
spin_unlock_irqrestore(&rtc_lock, flags);
-/*
- * We know that x86-64 always uses BCD format, no need to check the config
- * register.
- */
+ /*
+ * We know that x86-64 always uses BCD format, no need to check the
+ * config register.
+ */
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
-/*
- * x86-64 systems only exists since 2002.
- * This will work up to Dec 31, 2100
- */
+ /*
+ * x86-64 systems only exists since 2002.
+ * This will work up to Dec 31, 2100
+ */
year += 2000;
return mktime(year, mon, day, hour, min, sec);
@@ -695,8 +684,7 @@ static unsigned int __init hpet_calibrate_tsc(void)
do {
local_irq_disable();
hpet_now = hpet_readl(HPET_COUNTER);
- sync_core();
- rdtscl(tsc_now);
+ tsc_now = get_cycles_sync();
local_irq_restore(flags);
} while ((tsc_now - tsc_start) < TICK_COUNT &&
(hpet_now - hpet_start) < TICK_COUNT);
@@ -726,11 +714,9 @@ static unsigned int __init pit_calibrate_tsc(void)
outb(0xb0, 0x43);
outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42);
- rdtscll(start);
- sync_core();
+ start = get_cycles_sync();
while ((inb(0x61) & 0x20) == 0);
- sync_core();
- rdtscll(end);
+ end = get_cycles_sync();
spin_unlock_irqrestore(&i8253_lock, flags);
@@ -744,7 +730,7 @@ static __init int late_hpet_init(void)
unsigned int ntimer;
if (!vxtime.hpet_address)
- return -1;
+ return -1;
memset(&hd, 0, sizeof (hd));
@@ -878,8 +864,6 @@ static struct irqaction irq0 = {
timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL
};
-extern void __init config_acpi_tables(void);
-
void __init time_init(void)
{
char *timename;
@@ -934,7 +918,7 @@ void __init time_init(void)
vxtime.mode = VXTIME_TSC;
vxtime.quot = (1000000L << 32) / vxtime_hz;
vxtime.tsc_quot = (1000L << 32) / cpu_khz;
- rdtscll_sync(&vxtime.last_tsc);
+ vxtime.last_tsc = get_cycles_sync();
setup_irq(0, &irq0);
set_cyc2ns_scale(cpu_khz);
@@ -948,7 +932,7 @@ void __init time_init(void)
* Make an educated guess if the TSC is trustworthy and synchronized
* over all CPUs.
*/
-static __init int unsynchronized_tsc(void)
+__init int unsynchronized_tsc(void)
{
#ifdef CONFIG_SMP
if (oem_force_hpet_timer())
@@ -959,7 +943,7 @@ static __init int unsynchronized_tsc(void)
return 0;
#endif
/* Assume multi socket systems are not synchronized */
- return num_online_cpus() > 1;
+ return num_present_cpus() > 1;
}
/*
@@ -999,6 +983,10 @@ __setup("report_lost_ticks", time_setup);
static long clock_cmos_diff;
static unsigned long sleep_start;
+/*
+ * sysfs support for the timer.
+ */
+
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
/*
@@ -1041,7 +1029,6 @@ static struct sysdev_class timer_sysclass = {
set_kset_name("timer"),
};
-
/* XXX this driverfs stuff should probably go elsewhere later -john */
static struct sys_device device_timer = {
.id = 0,
@@ -1075,8 +1062,6 @@ device_initcall(time_init_device);
*/
#include <linux/rtc.h>
-extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
#define DEFAULT_RTC_INT_FREQ 64
#define RTC_NUM_INTS 1
@@ -1285,8 +1270,6 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
#endif
-
-
static int __init nohpet_setup(char *s)
{
nohpet = 1;
@@ -1303,5 +1286,3 @@ static int __init notsc_setup(char *s)
}
__setup("notsc", notsc_setup);
-
-
diff --git a/arch/x86_64/kernel/trampoline.S b/arch/x86_64/kernel/trampoline.S
index 6d9c9a8e7d0e..23a03eb91fc7 100644
--- a/arch/x86_64/kernel/trampoline.S
+++ b/arch/x86_64/kernel/trampoline.S
@@ -42,8 +42,15 @@ r_base = .
movl $0xA5A5A5A5, trampoline_data - r_base
# write marker for master knows we're running
- lidt idt_48 - r_base # load idt with 0, 0
- lgdt gdt_48 - r_base # load gdt with whatever is appropriate
+ /*
+ * GDT tables in non default location kernel can be beyond 16MB and
+ * lgdt will not be able to load the address as in real mode default
+ * operand size is 16bit. Use lgdtl instead to force operand size
+ * to 32 bit.
+ */
+
+ lidtl idt_48 - r_base # load idt with 0, 0
+ lgdtl gdt_48 - r_base # load gdt with whatever is appropriate
xor %ax, %ax
inc %ax # protected mode (PE) bit
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index bf337f493189..8bb0aeda78b9 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -70,7 +70,6 @@ asmlinkage void reserved(void);
asmlinkage void alignment_check(void);
asmlinkage void machine_check(void);
asmlinkage void spurious_interrupt_bug(void);
-asmlinkage void call_debug(void);
struct notifier_block *die_chain;
static DEFINE_SPINLOCK(die_notifier_lock);
@@ -121,19 +120,31 @@ int printk_address(unsigned long address)
static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
unsigned *usedp, const char **idp)
{
- static const char ids[N_EXCEPTION_STACKS][8] = {
+ static char ids[][8] = {
[DEBUG_STACK - 1] = "#DB",
[NMI_STACK - 1] = "NMI",
[DOUBLEFAULT_STACK - 1] = "#DF",
[STACKFAULT_STACK - 1] = "#SS",
[MCE_STACK - 1] = "#MC",
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+ [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
+#endif
};
unsigned k;
for (k = 0; k < N_EXCEPTION_STACKS; k++) {
unsigned long end;
- end = per_cpu(init_tss, cpu).ist[k];
+ switch (k + 1) {
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+ case DEBUG_STACK:
+ end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
+ break;
+#endif
+ default:
+ end = per_cpu(init_tss, cpu).ist[k];
+ break;
+ }
if (stack >= end)
continue;
if (stack >= end - EXCEPTION_STKSZ) {
@@ -143,6 +154,22 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
*idp = ids[k];
return (unsigned long *)end;
}
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+ if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
+ unsigned j = N_EXCEPTION_STACKS - 1;
+
+ do {
+ ++j;
+ end -= EXCEPTION_STKSZ;
+ ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
+ } while (stack < end - EXCEPTION_STKSZ);
+ if (*usedp & (1U << j))
+ break;
+ *usedp |= 1U << j;
+ *idp = ids[j];
+ return (unsigned long *)end;
+ }
+#endif
}
return NULL;
}
@@ -156,9 +183,8 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
void show_trace(unsigned long *stack)
{
- unsigned long addr;
const unsigned cpu = safe_smp_processor_id();
- unsigned long *irqstack_end = (unsigned long *)cpu_pda[cpu].irqstackptr;
+ unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
int i;
unsigned used = 0;
@@ -166,8 +192,14 @@ void show_trace(unsigned long *stack)
#define HANDLE_STACK(cond) \
do while (cond) { \
- addr = *stack++; \
+ unsigned long addr = *stack++; \
if (kernel_text_address(addr)) { \
+ if (i > 50) { \
+ printk("\n "); \
+ i = 0; \
+ } \
+ else \
+ i += printk(" "); \
/* \
* If the address is either in the text segment of the \
* kernel, or in the region which contains vmalloc'ed \
@@ -177,25 +209,19 @@ void show_trace(unsigned long *stack)
* out the call path that was taken. \
*/ \
i += printk_address(addr); \
- if (i > 50) { \
- printk("\n "); \
- i = 0; \
- } \
- else \
- i += printk(" "); \
} \
} while (0)
- for(i = 0; ; ) {
+ for(i = 11; ; ) {
const char *id;
unsigned long *estack_end;
estack_end = in_exception_stack(cpu, (unsigned long)stack,
&used, &id);
if (estack_end) {
- i += printk(" <%s> ", id);
+ i += printk(" <%s>", id);
HANDLE_STACK (stack < estack_end);
- i += printk(" <EOE> ");
+ i += printk(" <EOE>");
stack = (unsigned long *) estack_end[-2];
continue;
}
@@ -205,11 +231,11 @@ void show_trace(unsigned long *stack)
(IRQSTACKSIZE - 64) / sizeof(*irqstack);
if (stack >= irqstack && stack < irqstack_end) {
- i += printk(" <IRQ> ");
+ i += printk(" <IRQ>");
HANDLE_STACK (stack < irqstack_end);
stack = (unsigned long *) (irqstack_end[-1]);
irqstack_end = NULL;
- i += printk(" <EOI> ");
+ i += printk(" <EOI>");
continue;
}
}
@@ -226,8 +252,8 @@ void show_stack(struct task_struct *tsk, unsigned long * rsp)
unsigned long *stack;
int i;
const int cpu = safe_smp_processor_id();
- unsigned long *irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr);
- unsigned long *irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE);
+ unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
+ unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
// debugging aid: "show_stack(NULL, NULL);" prints the
// back trace for this cpu.
@@ -275,14 +301,14 @@ void show_registers(struct pt_regs *regs)
int in_kernel = !user_mode(regs);
unsigned long rsp;
const int cpu = safe_smp_processor_id();
- struct task_struct *cur = cpu_pda[cpu].pcurrent;
+ struct task_struct *cur = cpu_pda(cpu)->pcurrent;
rsp = regs->rsp;
printk("CPU %d ", cpu);
__show_regs(regs);
printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
- cur->comm, cur->pid, cur->thread_info, cur);
+ cur->comm, cur->pid, task_thread_info(cur), cur);
/*
* When in-kernel, we also print out the stack and code at the
@@ -314,20 +340,26 @@ bad:
void handle_BUG(struct pt_regs *regs)
{
struct bug_frame f;
- char tmp;
+ long len;
+ const char *prefix = "";
if (user_mode(regs))
return;
- if (__copy_from_user(&f, (struct bug_frame *) regs->rip,
+ if (__copy_from_user(&f, (const void __user *) regs->rip,
sizeof(struct bug_frame)))
return;
if (f.filename >= 0 ||
f.ud2[0] != 0x0f || f.ud2[1] != 0x0b)
return;
- if (__get_user(tmp, (char *)(long)f.filename))
+ len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1;
+ if (len < 0 || len >= PATH_MAX)
f.filename = (int)(long)"unmapped filename";
+ else if (len > 50) {
+ f.filename += len - 50;
+ prefix = "...";
+ }
printk("----------- [cut here ] --------- [please bite here ] ---------\n");
- printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", (char *)(long)f.filename, f.line);
+ printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line);
}
#ifdef CONFIG_BUG
@@ -382,7 +414,7 @@ void __die(const char * str, struct pt_regs * regs, long err)
printk("DEBUG_PAGEALLOC");
#endif
printk("\n");
- notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+ notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
show_registers(regs);
/* Executive summary in case the oops scrolled away */
printk(KERN_ALERT "RIP ");
@@ -399,11 +431,6 @@ void die(const char * str, struct pt_regs * regs, long err)
oops_end(flags);
do_exit(SIGSEGV);
}
-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
-{
- if (!(regs->eflags & VM_MASK) && (regs->cs == __KERNEL_CS))
- die(str, regs, err);
-}
void die_nmi(char *str, struct pt_regs *regs)
{
@@ -426,19 +453,20 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
struct pt_regs * regs, long error_code,
siginfo_t *info)
{
+ struct task_struct *tsk = current;
+
conditional_sti(regs);
- if (user_mode(regs)) {
- struct task_struct *tsk = current;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = trapnr;
+ if (user_mode(regs)) {
if (exception_trace && unhandled_signal(tsk, signr))
printk(KERN_INFO
"%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
tsk->comm, tsk->pid, str,
regs->rip,regs->rsp,error_code);
- tsk->thread.error_code = error_code;
- tsk->thread.trap_no = trapnr;
if (info)
force_sig_info(signr, info, tsk);
else
@@ -485,7 +513,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->rip)
DO_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_ERROR( 5, SIGSEGV, "bounds", bounds)
-DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->rip)
+DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->rip)
DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
@@ -493,24 +521,41 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
DO_ERROR(18, SIGSEGV, "reserved", reserved)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
-DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
+
+asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
+{
+ static const char str[] = "double fault";
+ struct task_struct *tsk = current;
+
+ /* Return not checked because double check cannot be ignored */
+ notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV);
+
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 8;
+
+ /* This is always a kernel trap and never fixable (and thus must
+ never return). */
+ for (;;)
+ die(str, regs, error_code);
+}
asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
long error_code)
{
+ struct task_struct *tsk = current;
+
conditional_sti(regs);
- if (user_mode(regs)) {
- struct task_struct *tsk = current;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 13;
+ if (user_mode(regs)) {
if (exception_trace && unhandled_signal(tsk, SIGSEGV))
printk(KERN_INFO
"%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
tsk->comm, tsk->pid,
regs->rip,regs->rsp,error_code);
- tsk->thread.error_code = error_code;
- tsk->thread.trap_no = 13;
force_sig(SIGSEGV, tsk);
return;
}
@@ -573,7 +618,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
reason = get_nmi_reason();
if (!(reason & 0xc0)) {
- if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+ if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
== NOTIFY_STOP)
return;
#ifdef CONFIG_X86_LOCAL_APIC
@@ -589,7 +634,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
unknown_nmi_error(reason, regs);
return;
}
- if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+ if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
return;
/* AK: following checks seem to be broken on modern chipsets. FIXME */
@@ -600,6 +645,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
io_check_error(reason, regs);
}
+/* runs on IST stack. */
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) {
@@ -620,7 +666,7 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
;
/* Exception from user space */
else if (user_mode(eregs))
- regs = ((struct pt_regs *)current->thread.rsp0) - 1;
+ regs = task_pt_regs(current);
/* Exception from kernel and interrupts are enabled. Move to
kernel process stack. */
else if (eregs->eflags & X86_EFLAGS_IF)
@@ -684,11 +730,9 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs,
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
- if (!user_mode(regs))
- goto clear_dr7;
+ info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL;
+ force_sig_info(SIGTRAP, &info, tsk);
- info.si_addr = (void __user *)regs->rip;
- force_sig_info(SIGTRAP, &info, tsk);
clear_dr7:
set_debugreg(0UL, 7);
return;
@@ -698,7 +742,7 @@ clear_TF_reenable:
regs->eflags &= ~TF_MASK;
}
-static int kernel_math_error(struct pt_regs *regs, char *str)
+static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr)
{
const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->rip);
@@ -706,8 +750,9 @@ static int kernel_math_error(struct pt_regs *regs, char *str)
regs->rip = fixup->fixup;
return 1;
}
- notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE);
+ notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE);
/* Illegal floating point operation in the kernel */
+ current->thread.trap_no = trapnr;
die(str, regs, 0);
return 0;
}
@@ -726,7 +771,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
conditional_sti(regs);
if (!user_mode(regs) &&
- kernel_math_error(regs, "kernel x87 math error"))
+ kernel_math_error(regs, "kernel x87 math error", 16))
return;
/*
@@ -795,7 +840,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
conditional_sti(regs);
if (!user_mode(regs) &&
- kernel_math_error(regs, "kernel simd math error"))
+ kernel_math_error(regs, "kernel simd math error", 19))
return;
/*
@@ -867,12 +912,7 @@ asmlinkage void math_state_restore(void)
if (!used_math())
init_fpu(me);
restore_fpu_checking(&me->thread.i387.fxsave);
- me->thread_info->status |= TS_USEDFPU;
-}
-
-void do_call_debug(struct pt_regs *regs)
-{
- notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT);
+ task_thread_info(me)->status |= TS_USEDFPU;
}
void __init trap_init(void)
@@ -880,9 +920,9 @@ void __init trap_init(void)
set_intr_gate(0,&divide_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
- set_system_gate(3,&int3);
- set_system_gate(4,&overflow); /* int4-5 can be called from all */
- set_system_gate(5,&bounds);
+ set_system_gate_ist(3,&int3,DEBUG_STACK); /* int3 can be called from all */
+ set_system_gate(4,&overflow); /* int4 can be called from all */
+ set_intr_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
set_intr_gate(7,&device_not_available);
set_intr_gate_ist(8,&double_fault, DOUBLEFAULT_STACK);
@@ -904,8 +944,6 @@ void __init trap_init(void)
set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
#endif
- set_intr_gate(KDB_VECTOR, call_debug);
-
/*
* Should be a barrier for any external CPU state.
*/
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 58b19215b4b3..b0eed1faf740 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -8,6 +8,8 @@
#include <asm/page.h>
#include <linux/config.h>
+#undef i386 /* in case the preprocessor is a 32bit one */
+
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
@@ -189,7 +191,7 @@ SECTIONS
/* Sections to be discarded */
/DISCARD/ : {
*(.exitcall.exit)
-#ifndef CONFIG_DEBUG_INFO
+#ifndef CONFIG_UNWIND_INFO
*(.eh_frame)
#endif
}
diff --git a/arch/x86_64/kernel/vsmp.c b/arch/x86_64/kernel/vsmp.c
new file mode 100644
index 000000000000..92f70c74965f
--- /dev/null
+++ b/arch/x86_64/kernel/vsmp.c
@@ -0,0 +1,45 @@
+/*
+ * vSMPowered(tm) systems specific initialization
+ * Copyright (C) 2005 ScaleMP Inc.
+ *
+ * Use of this code is subject to the terms and conditions of the
+ * GNU general public license version 2. See "COPYING" or
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Ravikiran Thirumalai <kiran@scalemp.com>,
+ * Shai Fultheim <shai@scalemp.com>
+ */
+
+#include <linux/init.h>
+#include <linux/pci_ids.h>
+#include <linux/pci_regs.h>
+#include <asm/pci-direct.h>
+
+static int __init vsmp_init(void)
+{
+ void *address;
+ unsigned int cap, ctl;
+
+ /* Check if we are running on a ScaleMP vSMP box */
+ if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) ||
+ (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
+ return 0;
+
+ /* set vSMP magic bits to indicate vSMP capable kernel */
+ address = ioremap(read_pci_config(0, 0x1f, 0, PCI_BASE_ADDRESS_0), 8);
+ cap = readl(address);
+ ctl = readl(address + 4);
+ printk("vSMP CTL: capabilities:0x%08x control:0x%08x\n", cap, ctl);
+ if (cap & ctl & (1 << 4)) {
+ /* Turn on vSMP IRQ fastpath handling (see system.h) */
+ ctl &= ~(1 << 4);
+ writel(ctl, address + 4);
+ ctl = readl(address + 4);
+ printk("vSMP CTL: control set to:0x%08x\n", ctl);
+ }
+
+ iounmap(address);
+ return 0;
+}
+
+core_initcall(vsmp_init);
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 70a0bd16085f..9468fb20b0bc 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -35,14 +35,13 @@
#include <asm/io.h>
#define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
-#define force_inline __attribute__((always_inline)) inline
int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
#include <asm/unistd.h>
-static force_inline void timeval_normalize(struct timeval * tv)
+static __always_inline void timeval_normalize(struct timeval * tv)
{
time_t __sec;
@@ -53,7 +52,7 @@ static force_inline void timeval_normalize(struct timeval * tv)
}
}
-static force_inline void do_vgettimeofday(struct timeval * tv)
+static __always_inline void do_vgettimeofday(struct timeval * tv)
{
long sequence, t;
unsigned long sec, usec;
@@ -66,8 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
(__jiffies - __wall_jiffies) * (1000000 / HZ);
if (__vxtime.mode != VXTIME_HPET) {
- sync_core();
- rdtscll(t);
+ t = get_cycles_sync();
if (t < __vxtime.last_tsc)
t = __vxtime.last_tsc;
usec += ((t - __vxtime.last_tsc) *
@@ -84,12 +82,12 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
}
/* RED-PEN may want to readd seq locking, but then the variable should be write-once. */
-static force_inline void do_get_tz(struct timezone * tz)
+static __always_inline void do_get_tz(struct timezone * tz)
{
*tz = __sys_tz;
}
-static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
+static __always_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
{
int ret;
asm volatile("vsysc2: syscall"
@@ -98,7 +96,7 @@ static force_inline int gettimeofday(struct timeval *tv, struct timezone *tz)
return ret;
}
-static force_inline long time_syscall(long *t)
+static __always_inline long time_syscall(long *t)
{
long secs;
asm volatile("vsysc1: syscall"
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 4a54221e10bc..b614d54d2ae4 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -13,7 +13,6 @@
#include <linux/string.h>
#include <linux/syscalls.h>
#include <linux/tty.h>
-#include <linux/ioctl32.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
@@ -45,22 +44,15 @@ extern struct drive_info_struct drive_info;
EXPORT_SYMBOL(drive_info);
#endif
-extern unsigned long get_cmos_time(void);
-
/* platform dependent support */
EXPORT_SYMBOL(boot_cpu_data);
//EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(ioremap_nocache);
EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
-EXPORT_SYMBOL(probe_irq_mask);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(pm_idle);
EXPORT_SYMBOL(pm_power_off);
-EXPORT_SYMBOL(get_cmos_time);
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
@@ -84,9 +76,6 @@ EXPORT_SYMBOL(__put_user_2);
EXPORT_SYMBOL(__put_user_4);
EXPORT_SYMBOL(__put_user_8);
-EXPORT_SYMBOL(strpbrk);
-EXPORT_SYMBOL(strstr);
-
EXPORT_SYMBOL(strncpy_from_user);
EXPORT_SYMBOL(__strncpy_from_user);
EXPORT_SYMBOL(clear_user);
@@ -98,25 +87,18 @@ EXPORT_SYMBOL(copy_in_user);
EXPORT_SYMBOL(strnlen_user);
#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-#endif
-
-#ifdef CONFIG_PCI
EXPORT_SYMBOL(pci_mem_start);
#endif
EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(clear_page);
-EXPORT_SYMBOL(cpu_pda);
+EXPORT_SYMBOL(_cpu_pda);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(__write_lock_failed);
EXPORT_SYMBOL(__read_lock_failed);
-EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(smp_call_function);
EXPORT_SYMBOL(cpu_callout_map);
#endif
@@ -137,30 +119,17 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
#undef memcpy
#undef memset
#undef memmove
-#undef memchr
#undef strlen
-#undef strncmp
-#undef strncpy
-#undef strchr
extern void * memset(void *,int,__kernel_size_t);
extern size_t strlen(const char *);
extern void * memmove(void * dest,const void *src,size_t count);
-extern void *memchr(const void *s, int c, size_t n);
extern void * memcpy(void *,const void *,__kernel_size_t);
extern void * __memcpy(void *,const void *,__kernel_size_t);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(memscan);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(__memcpy);
diff --git a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S
index dfa358b05c89..79422b6559c3 100644
--- a/arch/x86_64/lib/copy_user.S
+++ b/arch/x86_64/lib/copy_user.S
@@ -4,12 +4,9 @@
* Functions to copy from and to user space.
*/
-#define FIX_ALIGNMENT 1
-
#include <asm/current.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
- #include <asm/cpufeature.h>
/* Standard copy_to_user with segment limit checking */
.globl copy_to_user
@@ -21,23 +18,7 @@ copy_to_user:
jc bad_to_user
cmpq threadinfo_addr_limit(%rax),%rcx
jae bad_to_user
-2:
- .byte 0xe9 /* 32bit jump */
- .long .Lcug-1f
-1:
-
- .section .altinstr_replacement,"ax"
-3: .byte 0xe9 /* replacement jmp with 8 bit immediate */
- .long copy_user_generic_c-1b /* offset */
- .previous
- .section .altinstructions,"a"
- .align 8
- .quad 2b
- .quad 3b
- .byte X86_FEATURE_K8_C
- .byte 5
- .byte 5
- .previous
+ jmp copy_user_generic
/* Standard copy_from_user with segment limit checking */
.globl copy_from_user
@@ -72,223 +53,44 @@ bad_to_user:
* rsi source
* rdx count
*
+ * Only 4GB of copy is supported. This shouldn't be a problem
+ * because the kernel normally only writes from/to page sized chunks
+ * even if user space passed a longer buffer.
+ * And more would be dangerous because both Intel and AMD have
+ * errata with rep movsq > 4GB. If someone feels the need to fix
+ * this please consider this.
+ *
* Output:
* eax uncopied bytes or 0 if successful.
*/
- .globl copy_user_generic
- .p2align 4
-copy_user_generic:
- .byte 0x66,0x66,0x90 /* 5 byte nop for replacement jump */
- .byte 0x66,0x90
-1:
- .section .altinstr_replacement,"ax"
-2: .byte 0xe9 /* near jump with 32bit immediate */
- .long copy_user_generic_c-1b /* offset */
- .previous
- .section .altinstructions,"a"
- .align 8
- .quad copy_user_generic
- .quad 2b
- .byte X86_FEATURE_K8_C
- .byte 5
- .byte 5
- .previous
-.Lcug:
- pushq %rbx
- xorl %eax,%eax /*zero for the exception handler */
-
-#ifdef FIX_ALIGNMENT
- /* check for bad alignment of destination */
- movl %edi,%ecx
- andl $7,%ecx
- jnz .Lbad_alignment
-.Lafter_bad_alignment:
-#endif
- movq %rdx,%rcx
-
- movl $64,%ebx
- shrq $6,%rdx
- decq %rdx
- js .Lhandle_tail
-
- .p2align 4
-.Lloop:
-.Ls1: movq (%rsi),%r11
-.Ls2: movq 1*8(%rsi),%r8
-.Ls3: movq 2*8(%rsi),%r9
-.Ls4: movq 3*8(%rsi),%r10
-.Ld1: movq %r11,(%rdi)
-.Ld2: movq %r8,1*8(%rdi)
-.Ld3: movq %r9,2*8(%rdi)
-.Ld4: movq %r10,3*8(%rdi)
-
-.Ls5: movq 4*8(%rsi),%r11
-.Ls6: movq 5*8(%rsi),%r8
-.Ls7: movq 6*8(%rsi),%r9
-.Ls8: movq 7*8(%rsi),%r10
-.Ld5: movq %r11,4*8(%rdi)
-.Ld6: movq %r8,5*8(%rdi)
-.Ld7: movq %r9,6*8(%rdi)
-.Ld8: movq %r10,7*8(%rdi)
-
- decq %rdx
-
- leaq 64(%rsi),%rsi
- leaq 64(%rdi),%rdi
-
- jns .Lloop
-
- .p2align 4
-.Lhandle_tail:
- movl %ecx,%edx
- andl $63,%ecx
- shrl $3,%ecx
- jz .Lhandle_7
- movl $8,%ebx
- .p2align 4
-.Lloop_8:
-.Ls9: movq (%rsi),%r8
-.Ld9: movq %r8,(%rdi)
- decl %ecx
- leaq 8(%rdi),%rdi
- leaq 8(%rsi),%rsi
- jnz .Lloop_8
-
-.Lhandle_7:
- movl %edx,%ecx
- andl $7,%ecx
- jz .Lende
- .p2align 4
-.Lloop_1:
-.Ls10: movb (%rsi),%bl
-.Ld10: movb %bl,(%rdi)
- incq %rdi
- incq %rsi
- decl %ecx
- jnz .Lloop_1
-
-.Lende:
- popq %rbx
- ret
-
-#ifdef FIX_ALIGNMENT
- /* align destination */
- .p2align 4
-.Lbad_alignment:
- movl $8,%r9d
- subl %ecx,%r9d
- movl %r9d,%ecx
- cmpq %r9,%rdx
- jz .Lhandle_7
- js .Lhandle_7
-.Lalign_1:
-.Ls11: movb (%rsi),%bl
-.Ld11: movb %bl,(%rdi)
- incq %rsi
- incq %rdi
- decl %ecx
- jnz .Lalign_1
- subq %r9,%rdx
- jmp .Lafter_bad_alignment
-#endif
-
- /* table sorted by exception address */
- .section __ex_table,"a"
- .align 8
- .quad .Ls1,.Ls1e
- .quad .Ls2,.Ls2e
- .quad .Ls3,.Ls3e
- .quad .Ls4,.Ls4e
- .quad .Ld1,.Ls1e
- .quad .Ld2,.Ls2e
- .quad .Ld3,.Ls3e
- .quad .Ld4,.Ls4e
- .quad .Ls5,.Ls5e
- .quad .Ls6,.Ls6e
- .quad .Ls7,.Ls7e
- .quad .Ls8,.Ls8e
- .quad .Ld5,.Ls5e
- .quad .Ld6,.Ls6e
- .quad .Ld7,.Ls7e
- .quad .Ld8,.Ls8e
- .quad .Ls9,.Le_quad
- .quad .Ld9,.Le_quad
- .quad .Ls10,.Le_byte
- .quad .Ld10,.Le_byte
-#ifdef FIX_ALIGNMENT
- .quad .Ls11,.Lzero_rest
- .quad .Ld11,.Lzero_rest
-#endif
- .quad .Le5,.Le_zero
- .previous
-
- /* compute 64-offset for main loop. 8 bytes accuracy with error on the
- pessimistic side. this is gross. it would be better to fix the
- interface. */
- /* eax: zero, ebx: 64 */
-.Ls1e: addl $8,%eax
-.Ls2e: addl $8,%eax
-.Ls3e: addl $8,%eax
-.Ls4e: addl $8,%eax
-.Ls5e: addl $8,%eax
-.Ls6e: addl $8,%eax
-.Ls7e: addl $8,%eax
-.Ls8e: addl $8,%eax
- addq %rbx,%rdi /* +64 */
- subq %rax,%rdi /* correct destination with computed offset */
-
- shlq $6,%rdx /* loop counter * 64 (stride length) */
- addq %rax,%rdx /* add offset to loopcnt */
- andl $63,%ecx /* remaining bytes */
- addq %rcx,%rdx /* add them */
- jmp .Lzero_rest
-
- /* exception on quad word loop in tail handling */
- /* ecx: loopcnt/8, %edx: length, rdi: correct */
-.Le_quad:
- shll $3,%ecx
- andl $7,%edx
- addl %ecx,%edx
- /* edx: bytes to zero, rdi: dest, eax:zero */
-.Lzero_rest:
- movq %rdx,%rcx
-.Le_byte:
- xorl %eax,%eax
-.Le5: rep
- stosb
- /* when there is another exception while zeroing the rest just return */
-.Le_zero:
- movq %rdx,%rax
- jmp .Lende
-
- /* C stepping K8 run faster using the string copy instructions.
- This is also a lot simpler. Use them when possible.
- Patch in jmps to this code instead of copying it fully
- to avoid unwanted aliasing in the exception tables. */
-
- /* rdi destination
- * rsi source
- * rdx count
- *
- * Output:
- * eax uncopied bytes or 0 if successfull.
- */
-copy_user_generic_c:
+ .globl copy_user_generic
+copy_user_generic:
movl %edx,%ecx
shrl $3,%ecx
andl $7,%edx
+ jz 5f
1: rep
movsq
movl %edx,%ecx
+ xor %eax,%eax
2: rep
movsb
-4: movl %ecx,%eax
ret
+ /* align here? */
+5: xorl %eax,%eax
+6: rep movsq
+ ret
+
+ .section .fixup,"ax"
3: lea (%rdx,%rcx,8),%rax
ret
-
+4: movl %ecx,%eax
+ ret
+ .previous
+
.section __ex_table,"a"
.quad 1b,3b
.quad 2b,4b
+ .quad 6b,4b
.previous
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index 841bd738a189..03c460cbdd1c 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -39,7 +39,7 @@ void __delay(unsigned long loops)
inline void __const_udelay(unsigned long xloops)
{
- __delay(((xloops * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
+ __delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32);
}
void __udelay(unsigned long usecs)
diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c
index db8abba1ad81..9bc2c295818e 100644
--- a/arch/x86_64/lib/usercopy.c
+++ b/arch/x86_64/lib/usercopy.c
@@ -109,14 +109,11 @@ unsigned long clear_user(void __user *to, unsigned long n)
* Return 0 on exception, a value greater than N if too long
*/
-long strnlen_user(const char __user *s, long n)
+long __strnlen_user(const char __user *s, long n)
{
long res = 0;
char c;
- if (!access_ok(VERIFY_READ, s, n))
- return 0;
-
while (1) {
if (res>n)
return n+1;
@@ -129,6 +126,13 @@ long strnlen_user(const char __user *s, long n)
}
}
+long strnlen_user(const char __user *s, long n)
+{
+ if (!access_ok(VERIFY_READ, s, n))
+ return 0;
+ return __strnlen_user(s, n);
+}
+
long strlen_user(const char __user *s)
{
long res = 0;
diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile
index 1d232a87f113..d25ac86fe27a 100644
--- a/arch/x86_64/mm/Makefile
+++ b/arch/x86_64/mm/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux x86_64-specific parts of the memory manager.
#
-obj-y := init.o fault.o ioremap.o extable.o pageattr.o
+obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_K8_NUMA) += k8topology.o
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 3a63707a698b..26eac194064b 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -35,6 +35,13 @@
#include <asm-generic/sections.h>
#include <asm/kdebug.h>
+/* Page fault error code bits */
+#define PF_PROT (1<<0) /* or no page found */
+#define PF_WRITE (1<<1)
+#define PF_USER (1<<2)
+#define PF_RSVD (1<<3)
+#define PF_INSTR (1<<4)
+
void bust_spinlocks(int yes)
{
int loglevel_save = console_loglevel;
@@ -68,7 +75,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
unsigned char *max_instr;
/* If it was a exec fault ignore */
- if (error_code & (1<<4))
+ if (error_code & PF_INSTR)
return 0;
instr = (unsigned char *)convert_rip_to_linear(current, regs);
@@ -222,17 +229,22 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
unsigned long error_code)
{
unsigned long flags = oops_begin();
+ struct task_struct *tsk;
printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
current->comm, address);
dump_pagetable(address);
+ tsk = current;
+ tsk->thread.cr2 = address;
+ tsk->thread.trap_no = 14;
+ tsk->thread.error_code = error_code;
__die("Bad pagetable", regs, error_code);
oops_end(flags);
do_exit(SIGKILL);
}
/*
- * Handle a fault on the vmalloc or module mapping area
+ * Handle a fault on the vmalloc area
*
* This assumes no large pages in there.
*/
@@ -278,7 +290,6 @@ static int vmalloc_fault(unsigned long address)
that. */
if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
BUG();
- __flush_tlb_all();
return 0;
}
@@ -289,12 +300,6 @@ int exception_trace = 1;
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
- *
- * error_code:
- * bit 0 == 0 means no page found, 1 means protection fault
- * bit 1 == 0 means read, 1 means write
- * bit 2 == 0 means kernel, 1 means user-mode
- * bit 3 == 1 means fault was an instruction fetch
*/
asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
unsigned long error_code)
@@ -337,12 +342,16 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
*
* This verifies that the fault happens in kernel space
* (error_code & 4) == 0, and that the fault was not a
- * protection error (error_code & 1) == 0.
+ * protection error (error_code & 9) == 0.
*/
if (unlikely(address >= TASK_SIZE64)) {
- if (!(error_code & 5) &&
- ((address >= VMALLOC_START && address < VMALLOC_END) ||
- (address >= MODULES_VADDR && address < MODULES_END))) {
+ /*
+ * Don't check for the module range here: its PML4
+ * is always initialized because it's shared with the main
+ * kernel text. Only vmalloc may need PML4 syncups.
+ */
+ if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
+ ((address >= VMALLOC_START && address < VMALLOC_END))) {
if (vmalloc_fault(address) < 0)
goto bad_area_nosemaphore;
return;
@@ -354,7 +363,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}
- if (unlikely(error_code & (1 << 3)))
+ if (unlikely(error_code & PF_RSVD))
pgtable_bad(address, regs, error_code);
/*
@@ -381,7 +390,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
* thus avoiding the deadlock.
*/
if (!down_read_trylock(&mm->mmap_sem)) {
- if ((error_code & 4) == 0 &&
+ if ((error_code & PF_USER) == 0 &&
!search_exception_tables(regs->rip))
goto bad_area_nosemaphore;
down_read(&mm->mmap_sem);
@@ -408,17 +417,17 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
good_area:
info.si_code = SEGV_ACCERR;
write = 0;
- switch (error_code & 3) {
+ switch (error_code & (PF_PROT|PF_WRITE)) {
default: /* 3: write, present */
/* fall through */
- case 2: /* write, not present */
+ case PF_WRITE: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
write++;
break;
- case 1: /* read, present */
+ case PF_PROT: /* read, present */
goto bad_area;
- case 0: /* read, not present */
+ case 0: /* read, not present */
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
@@ -453,7 +462,7 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
- if (error_code & 4) {
+ if (error_code & PF_USER) {
if (is_prefetch(regs, address, error_code))
return;
@@ -521,6 +530,9 @@ no_context:
printk_address(regs->rip);
printk("\n");
dump_pagetable(address);
+ tsk->thread.cr2 = address;
+ tsk->thread.trap_no = 14;
+ tsk->thread.error_code = error_code;
__die("Oops", regs, error_code);
/* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address);
@@ -546,7 +558,7 @@ do_sigbus:
up_read(&mm->mmap_sem);
/* Kernel mode? Handle exceptions or die */
- if (!(error_code & 4))
+ if (!(error_code & PF_USER))
goto no_context;
tsk->thread.cr2 = address;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index c016dfe84784..7af1742aa958 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -23,6 +23,9 @@
#include <linux/bootmem.h>
#include <linux/proc_fs.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/memory_hotplug.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -38,11 +41,16 @@
#include <asm/proto.h>
#include <asm/smp.h>
#include <asm/sections.h>
+#include <asm/dma-mapping.h>
+#include <asm/swiotlb.h>
#ifndef Dprintk
#define Dprintk(x...)
#endif
+struct dma_mapping_ops* dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
static unsigned long dma_reserve __initdata;
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -174,13 +182,19 @@ static struct temp_map {
{}
};
-static __init void *alloc_low_page(int *index, unsigned long *phys)
+static __meminit void *alloc_low_page(int *index, unsigned long *phys)
{
struct temp_map *ti;
int i;
unsigned long pfn = table_end++, paddr;
void *adr;
+ if (after_bootmem) {
+ adr = (void *)get_zeroed_page(GFP_ATOMIC);
+ *phys = __pa(adr);
+ return adr;
+ }
+
if (pfn >= end_pfn)
panic("alloc_low_page: ran out of memory");
for (i = 0; temp_mappings[i].allocated; i++) {
@@ -193,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys)
ti->allocated = 1;
__flush_tlb();
adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK);
+ memset(adr, 0, PAGE_SIZE);
*index = i;
*phys = pfn * PAGE_SIZE;
return adr;
}
-static __init void unmap_low_page(int i)
+static __meminit void unmap_low_page(int i)
{
- struct temp_map *ti = &temp_mappings[i];
+ struct temp_map *ti;
+
+ if (after_bootmem)
+ return;
+
+ ti = &temp_mappings[i];
set_pmd(ti->pmd, __pmd(0));
ti->allocated = 0;
}
-static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+static void __meminit
+phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
+{
+ int i;
+
+ for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
+ unsigned long entry;
+
+ if (address > end) {
+ for (; i < PTRS_PER_PMD; i++, pmd++)
+ set_pmd(pmd, __pmd(0));
+ break;
+ }
+ entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
+ entry &= __supported_pte_mask;
+ set_pmd(pmd, __pmd(entry));
+ }
+}
+
+static void __meminit
+phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
+{
+ pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
+
+ if (pmd_none(*pmd)) {
+ spin_lock(&init_mm.page_table_lock);
+ phys_pmd_init(pmd, address, end);
+ spin_unlock(&init_mm.page_table_lock);
+ __flush_tlb_all();
+ }
+}
+
+static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
{
- long i, j;
+ long i = pud_index(address);
- i = pud_index(address);
pud = pud + i;
+
+ if (after_bootmem && pud_val(*pud)) {
+ phys_pmd_update(pud, address, end);
+ return;
+ }
+
for (; i < PTRS_PER_PUD; pud++, i++) {
int map;
unsigned long paddr, pmd_phys;
pmd_t *pmd;
- paddr = address + i*PUD_SIZE;
- if (paddr >= end) {
- for (; i < PTRS_PER_PUD; i++, pud++)
- set_pud(pud, __pud(0));
+ paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
+ if (paddr >= end)
break;
- }
- if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
+ if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) {
set_pud(pud, __pud(0));
continue;
}
pmd = alloc_low_page(&map, &pmd_phys);
+ spin_lock(&init_mm.page_table_lock);
set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
- for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
- unsigned long pe;
-
- if (paddr >= end) {
- for (; j < PTRS_PER_PMD; j++, pmd++)
- set_pmd(pmd, __pmd(0));
- break;
- }
- pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr;
- pe &= __supported_pte_mask;
- set_pmd(pmd, __pmd(pe));
- }
+ phys_pmd_init(pmd, paddr, end);
+ spin_unlock(&init_mm.page_table_lock);
unmap_low_page(map);
}
__flush_tlb();
@@ -249,25 +294,32 @@ static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned lon
static void __init find_early_table_space(unsigned long end)
{
- unsigned long puds, pmds, tables;
+ unsigned long puds, pmds, tables, start;
puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
- table_start = find_e820_area(0x8000, __pa_symbol(&_text), tables);
+ /* RED-PEN putting page tables only on node 0 could
+ cause a hotspot and fill up ZONE_DMA. The page tables
+ need roughly 0.5KB per GB. */
+ start = 0x8000;
+ table_start = find_e820_area(start, end, tables);
if (table_start == -1UL)
panic("Cannot find space for the kernel page tables");
table_start >>= PAGE_SHIFT;
table_end = table_start;
+
+ early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
+ end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
}
/* Setup the direct mapping of the physical memory at PAGE_OFFSET.
This runs before bootmem is initialized and gets pages directly from the
physical memory. To access them they are temporarily mapped. */
-void __init init_memory_mapping(unsigned long start, unsigned long end)
+void __meminit init_memory_mapping(unsigned long start, unsigned long end)
{
unsigned long next;
@@ -279,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
* mapped. Unfortunately this is done currently before the nodes are
* discovered.
*/
- find_early_table_space(end);
+ if (!after_bootmem)
+ find_early_table_space(end);
start = (unsigned long)__va(start);
end = (unsigned long)__va(end);
@@ -287,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end)
for (; start < end; start = next) {
int map;
unsigned long pud_phys;
- pud_t *pud = alloc_low_page(&map, &pud_phys);
+ pgd_t *pgd = pgd_offset_k(start);
+ pud_t *pud;
+
+ if (after_bootmem)
+ pud = pud_offset_k(pgd, __PAGE_OFFSET);
+ else
+ pud = alloc_low_page(&map, &pud_phys);
+
next = start + PGDIR_SIZE;
if (next > end)
next = end;
phys_pud_init(pud, __pa(start), __pa(next));
- set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
+ if (!after_bootmem)
+ set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys));
unmap_low_page(map);
}
- asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
+ if (!after_bootmem)
+ asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features));
__flush_tlb_all();
- early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end,
- table_start<<PAGE_SHIFT,
- table_end<<PAGE_SHIFT);
}
void __cpuinit zap_low_mappings(int cpu)
@@ -375,6 +434,9 @@ size_zones(unsigned long *z, unsigned long *h,
void __init paging_init(void)
{
unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
+
+ memory_present(0, 0, end_pfn);
+ sparse_init();
size_zones(zones, holes, 0, end_pfn);
free_area_init_node(0, NODE_DATA(0), zones,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
@@ -415,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size)
__flush_tlb_all();
}
+/*
+ * Memory hotplug specific functions
+ * These are only for non-NUMA machines right now.
+ */
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+void online_page(struct page *page)
+{
+ ClearPageReserved(page);
+ set_page_count(page, 1);
+ __free_page(page);
+ totalram_pages++;
+ num_physpages++;
+}
+
+int add_memory(u64 start, u64 size)
+{
+ struct pglist_data *pgdat = NODE_DATA(0);
+ struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
+ unsigned long start_pfn = start >> PAGE_SHIFT;
+ unsigned long nr_pages = size >> PAGE_SHIFT;
+ int ret;
+
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ if (ret)
+ goto error;
+
+ init_memory_mapping(start, (start + size -1));
+
+ return ret;
+error:
+ printk("%s: Problem encountered in __add_pages!\n", __func__);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(add_memory);
+
+int remove_memory(u64 start, u64 size)
+{
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+
+#endif
+
static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
kcore_vsyscall;
@@ -423,12 +529,9 @@ void __init mem_init(void)
long codesize, reservedpages, datasize, initsize;
#ifdef CONFIG_SWIOTLB
- if (!iommu_aperture &&
- (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
- swiotlb = 1;
- if (swiotlb)
- swiotlb_init();
+ pci_swiotlb_init();
#endif
+ no_iommu_init();
/* How many end-of-memory variables you have, grandma! */
max_low_pfn = end_pfn;
@@ -498,10 +601,33 @@ void free_initmem(void)
printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10);
}
+#ifdef CONFIG_DEBUG_RODATA
+
+extern char __start_rodata, __end_rodata;
+void mark_rodata_ro(void)
+{
+ unsigned long addr = (unsigned long)&__start_rodata;
+
+ for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE)
+ change_page_attr_addr(addr, 1, PAGE_KERNEL_RO);
+
+ printk ("Write protecting the kernel read-only data: %luk\n",
+ (&__end_rodata - &__start_rodata) >> 10);
+
+ /*
+ * change_page_attr_addr() requires a global_flush_tlb() call after it.
+ * We do this after the printk so that if something went wrong in the
+ * change, the printk gets out at least to give a better debug hint
+ * of who is the culprit.
+ */
+ global_flush_tlb();
+}
+#endif
+
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
- if (start < (unsigned long)&_end)
+ if (start >= end)
return;
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
for (; start < end; start += PAGE_SIZE) {
diff --git a/arch/x86_64/mm/mmap.c b/arch/x86_64/mm/mmap.c
new file mode 100644
index 000000000000..43e9b99bdf25
--- /dev/null
+++ b/arch/x86_64/mm/mmap.c
@@ -0,0 +1,30 @@
+/* Copyright 2005 Andi Kleen, SuSE Labs.
+ * Licensed under GPL, v.2
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <asm/ia32.h>
+
+/* Notebook: move the mmap code from sys_x86_64.c over here. */
+
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+#ifdef CONFIG_IA32_EMULATION
+ if (current_thread_info()->flags & _TIF_IA32)
+ return ia32_pick_mmap_layout(mm);
+#endif
+ mm->mmap_base = TASK_UNMAPPED_BASE;
+ if (current->flags & PF_RANDOMIZE) {
+ /* Add 28bit randomness which is about 40bits of address space
+ because mmap base has to be page aligned.
+ or ~1/128 of the total user VM
+ (total user address space is 47bits) */
+ unsigned rnd = get_random_int() & 0xfffffff;
+ mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
+ }
+ mm->get_unmapped_area = arch_get_unmapped_area;
+ mm->unmap_area = arch_unmap_area;
+}
+
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 15b67d2760cb..6ef9f9a76235 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -46,8 +46,8 @@ int numa_off __initdata;
* 0 if memnodmap[] too small (of shift too small)
* -1 if node overlap or lost ram (shift too big)
*/
-static int __init populate_memnodemap(
- const struct node *nodes, int numnodes, int shift)
+static int __init
+populate_memnodemap(const struct node *nodes, int numnodes, int shift)
{
int i;
int res = -1;
@@ -81,7 +81,7 @@ int __init compute_hash_shift(struct node *nodes, int numnodes)
while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0)
shift++;
- printk(KERN_DEBUG "Using %d for the hash shift.\n",
+ printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
shift);
if (populate_memnodemap(nodes, numnodes, shift) != 1) {
@@ -110,7 +110,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
start = round_up(start, ZONE_ALIGN);
- printk("Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end);
+ printk(KERN_INFO "Bootmem setup node %d %016lx-%016lx\n", nodeid, start, end);
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
@@ -156,7 +156,7 @@ void __init setup_node_zones(int nodeid)
start_pfn = node_start_pfn(nodeid);
end_pfn = node_end_pfn(nodeid);
- Dprintk(KERN_INFO "setting up node %d %lx-%lx\n",
+ Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
nodeid, start_pfn, end_pfn);
size_zones(zones, holes, start_pfn, end_pfn);
@@ -200,7 +200,7 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
while ((x << 1) < sz)
x <<= 1;
if (x < sz/2)
- printk("Numa emulation unbalanced. Complain to maintainer\n");
+ printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n");
sz = x;
}
@@ -272,7 +272,7 @@ __cpuinit void numa_add_cpu(int cpu)
void __cpuinit numa_set_node(int cpu, int node)
{
- cpu_pda[cpu].nodenumber = node;
+ cpu_pda(cpu)->nodenumber = node;
cpu_to_node[cpu] = node;
}
@@ -330,8 +330,69 @@ __init int numa_setup(char *opt)
return 1;
}
+/*
+ * Setup early cpu_to_node.
+ *
+ * Populate cpu_to_node[] only if x86_cpu_to_apicid[],
+ * and apicid_to_node[] tables have valid entries for a CPU.
+ * This means we skip cpu_to_node[] initialisation for NUMA
+ * emulation and faking node case (when running a kernel compiled
+ * for NUMA on a non NUMA box), which is OK as cpu_to_node[]
+ * is already initialized in a round robin manner at numa_init_array,
+ * prior to this call, and this initialization is good enough
+ * for the fake NUMA cases.
+ */
+void __init init_cpu_to_node(void)
+{
+ int i;
+ for (i = 0; i < NR_CPUS; i++) {
+ u8 apicid = x86_cpu_to_apicid[i];
+ if (apicid == BAD_APICID)
+ continue;
+ if (apicid_to_node[apicid] == NUMA_NO_NODE)
+ continue;
+ cpu_to_node[i] = apicid_to_node[apicid];
+ }
+}
+
EXPORT_SYMBOL(cpu_to_node);
EXPORT_SYMBOL(node_to_cpumask);
EXPORT_SYMBOL(memnode_shift);
EXPORT_SYMBOL(memnodemap);
EXPORT_SYMBOL(node_data);
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * Functions to convert PFNs from/to per node page addresses.
+ * These are out of line because they are quite big.
+ * They could be all tuned by pre caching more state.
+ * Should do that.
+ */
+
+/* Requires pfn_valid(pfn) to be true */
+struct page *pfn_to_page(unsigned long pfn)
+{
+ int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT);
+ return (pfn - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map;
+}
+EXPORT_SYMBOL(pfn_to_page);
+
+unsigned long page_to_pfn(struct page *page)
+{
+ return (long)(((page) - page_zone(page)->zone_mem_map) +
+ page_zone(page)->zone_start_pfn);
+}
+EXPORT_SYMBOL(page_to_pfn);
+
+int pfn_valid(unsigned long pfn)
+{
+ unsigned nid;
+ if (pfn >= num_physpages)
+ return 0;
+ nid = pfn_to_nid(pfn);
+ if (nid == 0xff)
+ return 0;
+ return pfn >= node_start_pfn(nid) && (pfn) < node_end_pfn(nid);
+}
+EXPORT_SYMBOL(pfn_valid);
+#endif
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index b90e8fe9eeb0..35f1f1aab063 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -128,6 +128,7 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
pte_t *kpte;
struct page *kpte_page;
unsigned kpte_flags;
+ pgprot_t ref_prot2;
kpte = lookup_address(address);
if (!kpte) return 0;
kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
@@ -140,10 +141,14 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
* split_large_page will take the reference for this change_page_attr
* on the split page.
*/
- struct page *split = split_large_page(address, prot, ref_prot);
+
+ struct page *split;
+ ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE));
+
+ split = split_large_page(address, prot, ref_prot2);
if (!split)
return -ENOMEM;
- set_pte(kpte,mk_pte(split, ref_prot));
+ set_pte(kpte,mk_pte(split, ref_prot2));
kpte_page = split;
}
get_page(kpte_page);
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 33340bd1e328..8b7f85608fa8 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -17,21 +17,23 @@
#include <linux/topology.h>
#include <asm/proto.h>
#include <asm/numa.h>
+#include <asm/e820.h>
static struct acpi_table_slit *acpi_slit;
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 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];
+ return -1;
+ /* Extend 0xff to (int)-1 */
+ return (signed char)pxm2node[pxm];
}
static __init int setup_node(int pxm)
@@ -91,9 +93,36 @@ static __init inline int srat_disabled(void)
return numa_off || acpi_numa < 0;
}
+/*
+ * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
+ * up the NUMA heuristics which wants the local node to have a smaller
+ * distance than the others.
+ * Do some quick checks here and only use the SLIT if it passes.
+ */
+static __init int slit_valid(struct acpi_table_slit *slit)
+{
+ int i, j;
+ int d = slit->localities;
+ for (i = 0; i < d; i++) {
+ for (j = 0; j < d; j++) {
+ u8 val = slit->entry[d*i + j];
+ if (i == j) {
+ if (val != 10)
+ return 0;
+ } else if (val <= 10)
+ return 0;
+ }
+ }
+ return 1;
+}
+
/* Callback for SLIT parsing */
void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
{
+ if (!slit_valid(slit)) {
+ printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
+ return;
+ }
acpi_slit = slit;
}
@@ -168,12 +197,39 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
nd->start, nd->end);
}
+/* Sanity check to catch more bad SRATs (they are amazingly common).
+ Make sure the PXMs cover all memory. */
+static int nodes_cover_memory(void)
+{
+ int i;
+ unsigned long pxmram, e820ram;
+
+ pxmram = 0;
+ for_each_node_mask(i, nodes_parsed) {
+ unsigned long s = nodes[i].start >> PAGE_SHIFT;
+ unsigned long e = nodes[i].end >> PAGE_SHIFT;
+ pxmram += e - s;
+ pxmram -= e820_hole_size(s, e);
+ }
+
+ e820ram = end_pfn - e820_hole_size(0, end_pfn);
+ if (pxmram < e820ram) {
+ printk(KERN_ERR
+ "SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n",
+ (pxmram << PAGE_SHIFT) >> 20,
+ (e820ram << PAGE_SHIFT) >> 20);
+ return 0;
+ }
+ return 1;
+}
+
void __init acpi_numa_arch_fixup(void) {}
/* Use the information discovered above to actually set up the nodes. */
int __init acpi_scan_nodes(unsigned long start, unsigned long end)
{
int i;
+
if (acpi_numa <= 0)
return -1;
@@ -184,6 +240,11 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
node_clear(i, nodes_parsed);
}
+ if (!nodes_cover_memory()) {
+ bad_srat();
+ return -1;
+ }
+
memnode_shift = compute_hash_shift(nodes, nodes_weight(nodes_parsed));
if (memnode_shift < 0) {
printk(KERN_ERR
diff --git a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS
deleted file mode 100644
index 4f0c05abd408..000000000000
--- a/arch/x86_64/pci/Makefile-BUS
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Makefile for X86_64 specific PCI routines
-#
-# Reuse the i386 PCI subsystem
-#
-CFLAGS += -I arch/i386/pci
-
-obj-y := i386.o
-obj-$(CONFIG_PCI_DIRECT)+= direct.o
-obj-y += fixup.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
-
-direct-y += ../../i386/pci/direct.o
-acpi-y += ../../i386/pci/acpi.o
-legacy-y += ../../i386/pci/legacy.o
-irq-y += ../../i386/pci/irq.o
-common-y += ../../i386/pci/common.o
-fixup-y += ../../i386/pci/fixup.o
-i386-y += ../../i386/pci/i386.o
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 7e841aa2a4aa..7ee4a14ec3b1 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -18,10 +18,6 @@ config XTENSA
with reasonable minimum requirements. The Xtensa Linux project has
a home page at <http://xtensa.sourceforge.net/>.
-config UID16
- bool
- default n
-
config RWSEM_XCHGADD_ALGORITHM
bool
default y
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 6a44b54ae817..f1f596644bfc 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -145,7 +145,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
int user_mode = user_mode(regs);
/* Set up new TSS. */
- tos = (unsigned long)p->thread_info + THREAD_SIZE;
+ tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
if (user_mode)
childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
else
@@ -217,7 +217,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
unsigned long get_wchan(struct task_struct *p)
{
unsigned long sp, pc;
- unsigned long stack_page = (unsigned long) p->thread_info;
+ unsigned long stack_page = (unsigned long) task_stack_page(p);
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index ab5c4c65b5c4..4cc85285a70a 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -72,7 +72,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
struct pt_regs *regs;
unsigned long tmp;
- regs = xtensa_pt_regs(child);
+ regs = task_pt_regs(child);
tmp = 0; /* Default return value. */
switch(addr) {
@@ -149,7 +149,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_POKEUSR:
{
struct pt_regs *regs;
- regs = xtensa_pt_regs(child);
+ regs = task_pt_regs(child);
switch (addr) {
case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
@@ -240,7 +240,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* elf_gregset_t format. */
xtensa_gregset_t format;
- struct pt_regs *regs = xtensa_pt_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
do_copy_regs (&format, regs, child);
@@ -257,7 +257,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* values in the elf_gregset_t format. */
xtensa_gregset_t format;
- struct pt_regs *regs = xtensa_pt_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){
ret = -EFAULT;
@@ -281,7 +281,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* elf_fpregset_t format. */
elf_fpregset_t fpregs;
- struct pt_regs *regs = xtensa_pt_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
do_save_fpregs (&fpregs, regs, child);
@@ -299,7 +299,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* values in the elf_fpregset_t format.
*/
elf_fpregset_t fpregs;
- struct pt_regs *regs = xtensa_pt_regs(child);
+ struct pt_regs *regs = task_pt_regs(child);
ret = 0;
if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) {
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index cb6e38ed2b1d..937d81f62f43 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -201,7 +201,7 @@ again:
if ((signed long)(get_ccount() - next) > 0)
goto again;
- /* Allow platform to do something usefull (Wdog). */
+ /* Allow platform to do something useful (Wdog). */
platform_heartbeat();
diff --git a/block/Kconfig b/block/Kconfig
index eb48edb80c1d..377f6dd20e17 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -5,7 +5,7 @@
#for instance.
config LBD
bool "Support for Large Block Devices"
- depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML
+ depends on X86 || (MIPS && 32BIT) || PPC32 || (S390 && !64BIT) || 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/block/as-iosched.c b/block/as-iosched.c
index 43fa20495688..8da3cf66894c 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -182,6 +182,9 @@ struct as_rq {
static kmem_cache_t *arq_pool;
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
+static void as_antic_stop(struct as_data *ad);
+
/*
* IO Context helper functions
*/
@@ -370,7 +373,7 @@ static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir)
* existing request against the same sector), which can happen when using
* direct IO, then return the alias.
*/
-static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
{
struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node;
struct rb_node *parent = NULL;
@@ -397,6 +400,16 @@ static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
return NULL;
}
+static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+ struct as_rq *alias;
+
+ while ((unlikely(alias = __as_add_arq_rb(ad, arq)))) {
+ as_move_to_dispatch(ad, alias);
+ as_antic_stop(ad);
+ }
+}
+
static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
{
if (!ON_RB(&arq->rb_node)) {
@@ -1133,23 +1146,6 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
/*
* take it off the sort and fifo list, add to dispatch queue
*/
- while (!list_empty(&rq->queuelist)) {
- struct request *__rq = list_entry_rq(rq->queuelist.next);
- struct as_rq *__arq = RQ_DATA(__rq);
-
- list_del(&__rq->queuelist);
-
- elv_dispatch_add_tail(ad->q, __rq);
-
- if (__arq->io_context && __arq->io_context->aic)
- atomic_inc(&__arq->io_context->aic->nr_dispatched);
-
- WARN_ON(__arq->state != AS_RQ_QUEUED);
- __arq->state = AS_RQ_DISPATCHED;
-
- ad->nr_dispatched++;
- }
-
as_remove_queued_request(ad->q, rq);
WARN_ON(arq->state != AS_RQ_QUEUED);
@@ -1326,49 +1322,12 @@ fifo_expired:
}
/*
- * Add arq to a list behind alias
- */
-static inline void
-as_add_aliased_request(struct as_data *ad, struct as_rq *arq,
- struct as_rq *alias)
-{
- struct request *req = arq->request;
- struct list_head *insert = alias->request->queuelist.prev;
-
- /*
- * Transfer list of aliases
- */
- while (!list_empty(&req->queuelist)) {
- struct request *__rq = list_entry_rq(req->queuelist.next);
- struct as_rq *__arq = RQ_DATA(__rq);
-
- list_move_tail(&__rq->queuelist, &alias->request->queuelist);
-
- WARN_ON(__arq->state != AS_RQ_QUEUED);
- }
-
- /*
- * Another request with the same start sector on the rbtree.
- * Link this request to that sector. They are untangled in
- * as_move_to_dispatch
- */
- list_add(&arq->request->queuelist, insert);
-
- /*
- * Don't want to have to handle merges.
- */
- as_del_arq_hash(arq);
- arq->request->flags |= REQ_NOMERGE;
-}
-
-/*
* add arq to rbtree and fifo
*/
static void as_add_request(request_queue_t *q, struct request *rq)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(rq);
- struct as_rq *alias;
int data_dir;
arq->state = AS_RQ_NEW;
@@ -1387,33 +1346,17 @@ static void as_add_request(request_queue_t *q, struct request *rq)
atomic_inc(&arq->io_context->aic->nr_queued);
}
- alias = as_add_arq_rb(ad, arq);
- if (!alias) {
- /*
- * set expire time (only used for reads) and add to fifo list
- */
- arq->expires = jiffies + ad->fifo_expire[data_dir];
- list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+ as_add_arq_rb(ad, arq);
+ if (rq_mergeable(arq->request))
+ as_add_arq_hash(ad, arq);
- if (rq_mergeable(arq->request))
- as_add_arq_hash(ad, arq);
- as_update_arq(ad, arq); /* keep state machine up to date */
-
- } else {
- as_add_aliased_request(ad, arq, alias);
-
- /*
- * have we been anticipating this request?
- * or does it come from the same process as the one we are
- * anticipating for?
- */
- if (ad->antic_status == ANTIC_WAIT_REQ
- || ad->antic_status == ANTIC_WAIT_NEXT) {
- if (as_can_break_anticipation(ad, arq))
- as_antic_stop(ad);
- }
- }
+ /*
+ * set expire time (only used for reads) and add to fifo list
+ */
+ arq->expires = jiffies + ad->fifo_expire[data_dir];
+ list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+ as_update_arq(ad, arq); /* keep state machine up to date */
arq->state = AS_RQ_QUEUED;
}
@@ -1536,23 +1479,8 @@ static void as_merged_request(request_queue_t *q, struct request *req)
* if the merge was a front merge, we need to reposition request
*/
if (rq_rb_key(req) != arq->rb_key) {
- struct as_rq *alias, *next_arq = NULL;
-
- if (ad->next_arq[arq->is_sync] == arq)
- next_arq = as_find_next_arq(ad, arq);
-
- /*
- * Note! We should really be moving any old aliased requests
- * off this request and try to insert them into the rbtree. We
- * currently don't bother. Ditto the next function.
- */
as_del_arq_rb(ad, arq);
- if ((alias = as_add_arq_rb(ad, arq))) {
- list_del_init(&arq->fifo);
- as_add_aliased_request(ad, arq, alias);
- if (next_arq)
- ad->next_arq[arq->is_sync] = next_arq;
- }
+ as_add_arq_rb(ad, arq);
/*
* Note! At this stage of this and the next function, our next
* request may not be optimal - eg the request may have "grown"
@@ -1579,18 +1507,8 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
as_add_arq_hash(ad, arq);
if (rq_rb_key(req) != arq->rb_key) {
- struct as_rq *alias, *next_arq = NULL;
-
- if (ad->next_arq[arq->is_sync] == arq)
- next_arq = as_find_next_arq(ad, arq);
-
as_del_arq_rb(ad, arq);
- if ((alias = as_add_arq_rb(ad, arq))) {
- list_del_init(&arq->fifo);
- as_add_aliased_request(ad, arq, alias);
- if (next_arq)
- ad->next_arq[arq->is_sync] = next_arq;
- }
+ as_add_arq_rb(ad, arq);
}
/*
@@ -1610,18 +1528,6 @@ static void as_merged_requests(request_queue_t *q, struct request *req,
}
/*
- * Transfer list of aliases
- */
- while (!list_empty(&next->queuelist)) {
- struct request *__rq = list_entry_rq(next->queuelist.next);
- struct as_rq *__arq = RQ_DATA(__rq);
-
- list_move_tail(&__rq->queuelist, &req->queuelist);
-
- WARN_ON(__arq->state != AS_RQ_QUEUED);
- }
-
- /*
* kill knowledge of next, this one is a goner
*/
as_remove_queued_request(q, next);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ee0bb41694b0..74fae2daf87e 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -25,15 +25,15 @@
/*
* tunables
*/
-static int cfq_quantum = 4; /* max queue in one round of service */
-static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/
-static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
-static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */
-static int cfq_back_penalty = 2; /* penalty of a backwards seek */
+static const int cfq_quantum = 4; /* max queue in one round of service */
+static const int cfq_queued = 8; /* minimum rq allocate limit per-queue*/
+static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
+static const int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */
+static const int cfq_back_penalty = 2; /* penalty of a backwards seek */
-static int cfq_slice_sync = HZ / 10;
+static const int cfq_slice_sync = HZ / 10;
static int cfq_slice_async = HZ / 25;
-static int cfq_slice_async_rq = 2;
+static const int cfq_slice_async_rq = 2;
static int cfq_slice_idle = HZ / 100;
#define CFQ_IDLE_GRACE (HZ / 10)
@@ -45,7 +45,7 @@ static int cfq_slice_idle = HZ / 100;
/*
* disable queueing at the driver/hardware level
*/
-static int cfq_max_depth = 2;
+static const int cfq_max_depth = 2;
/*
* for the hash of cfqq inside the cfqd
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 9cbec09e8415..27e494b1bf97 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -19,10 +19,10 @@
/*
* See Documentation/block/deadline-iosched.txt
*/
-static int read_expire = HZ / 2; /* max time before a read is submitted. */
-static int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
-static int writes_starved = 2; /* max times reads can starve a write */
-static int fifo_batch = 16; /* # of sequential requests treated as one
+static const int read_expire = HZ / 2; /* max time before a read is submitted. */
+static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
+static const int writes_starved = 2; /* max times reads can starve a write */
+static const int fifo_batch = 16; /* # of sequential requests treated as one
by the above parameters. For throughput. */
static const int deadline_hash_shift = 5;
diff --git a/block/elevator.c b/block/elevator.c
index 6c3fc8a10bf2..c9f424d5399c 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -64,7 +64,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_rq_merge_ok);
-inline int elv_try_merge(struct request *__rq, struct bio *bio)
+static inline int elv_try_merge(struct request *__rq, struct bio *bio)
{
int ret = ELEVATOR_NO_MERGE;
@@ -80,7 +80,6 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio)
return ret;
}
-EXPORT_SYMBOL(elv_try_merge);
static struct elevator_type *elevator_find(const char *name)
{
@@ -150,13 +149,20 @@ static void elevator_setup_default(void)
if (!chosen_elevator[0])
strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
+ /*
+ * Be backwards-compatible with previous kernels, so users
+ * won't get the wrong elevator.
+ */
+ if (!strcmp(chosen_elevator, "as"))
+ strcpy(chosen_elevator, "anticipatory");
+
/*
- * If the given scheduler is not available, fall back to no-op.
+ * If the given scheduler is not available, fall back to the default
*/
if ((e = elevator_find(chosen_elevator)))
elevator_put(e);
else
- strcpy(chosen_elevator, "noop");
+ strcpy(chosen_elevator, CONFIG_DEFAULT_IOSCHED);
}
static int __init elevator_setup(char *str)
@@ -304,15 +310,7 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
rq->flags &= ~REQ_STARTED;
- /*
- * if this is the flush, requeue the original instead and drop the flush
- */
- if (rq->flags & REQ_BAR_FLUSH) {
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- rq = rq->end_io_data;
- }
-
- __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
+ __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE, 0);
}
static void elv_drain_elevator(request_queue_t *q)
@@ -332,8 +330,19 @@ static void elv_drain_elevator(request_queue_t *q)
void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
+ struct list_head *pos;
+ unsigned ordseq;
+
+ if (q->ordcolor)
+ rq->flags |= REQ_ORDERED_COLOR;
+
if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
/*
+ * toggle ordered color
+ */
+ q->ordcolor ^= 1;
+
+ /*
* barriers implicitly indicate back insertion
*/
if (where == ELEVATOR_INSERT_SORT)
@@ -393,6 +402,30 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
q->elevator->ops->elevator_add_req_fn(q, rq);
break;
+ case ELEVATOR_INSERT_REQUEUE:
+ /*
+ * If ordered flush isn't in progress, we do front
+ * insertion; otherwise, requests should be requeued
+ * in ordseq order.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
+
+ if (q->ordseq == 0) {
+ list_add(&rq->queuelist, &q->queue_head);
+ break;
+ }
+
+ ordseq = blk_ordered_req_seq(rq);
+
+ list_for_each(pos, &q->queue_head) {
+ struct request *pos_rq = list_entry_rq(pos);
+ if (ordseq <= blk_ordered_req_seq(pos_rq))
+ break;
+ }
+
+ list_add_tail(&rq->queuelist, pos);
+ break;
+
default:
printk(KERN_ERR "%s: bad insertion point %d\n",
__FUNCTION__, where);
@@ -422,25 +455,16 @@ static inline struct request *__elv_next_request(request_queue_t *q)
{
struct request *rq;
- if (unlikely(list_empty(&q->queue_head) &&
- !q->elevator->ops->elevator_dispatch_fn(q, 0)))
- return NULL;
-
- rq = list_entry_rq(q->queue_head.next);
-
- /*
- * if this is a barrier write and the device has to issue a
- * flush sequence to support it, check how far we are
- */
- if (blk_fs_request(rq) && blk_barrier_rq(rq)) {
- BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
+ while (1) {
+ while (!list_empty(&q->queue_head)) {
+ rq = list_entry_rq(q->queue_head.next);
+ if (blk_do_ordered(q, &rq))
+ return rq;
+ }
- if (q->ordered == QUEUE_ORDERED_FLUSH &&
- !blk_barrier_preflush(rq))
- rq = blk_start_pre_flush(q, rq);
+ if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
+ return NULL;
}
-
- return rq;
}
struct request *elv_next_request(request_queue_t *q)
@@ -498,7 +522,7 @@ struct request *elv_next_request(request_queue_t *q)
blkdev_dequeue_request(rq);
rq->flags |= REQ_QUIET;
end_that_request_chunk(rq, 0, nr_bytes);
- end_that_request_last(rq);
+ end_that_request_last(rq, 0);
} else {
printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__,
ret);
@@ -597,6 +621,20 @@ void elv_completed_request(request_queue_t *q, struct request *rq)
if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
e->ops->elevator_completed_req_fn(q, rq);
}
+
+ /*
+ * Check if the queue is waiting for fs requests to be
+ * drained for flush sequence.
+ */
+ if (unlikely(q->ordseq)) {
+ struct request *first_rq = list_entry_rq(q->queue_head.next);
+ if (q->in_flight == 0 &&
+ blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
+ blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) {
+ blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
+ q->request_fn(q);
+ }
+ }
}
int elv_register_queue(struct request_queue *q)
diff --git a/block/genhd.c b/block/genhd.c
index f04609d553b8..db57546a709d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -38,34 +38,100 @@ static inline int major_to_index(int major)
return major % MAX_PROBE_HASH;
}
-#ifdef CONFIG_PROC_FS
-/* get block device names in somewhat random order */
-int get_blkdev_list(char *p, int used)
+struct blkdev_info {
+ int index;
+ struct blk_major_name *bd;
+};
+
+/*
+ * iterate over a list of blkdev_info structures. allows
+ * the major_names array to be iterated over from outside this file
+ * must be called with the block_subsys_sem held
+ */
+void *get_next_blkdev(void *dev)
+{
+ struct blkdev_info *info;
+
+ if (dev == NULL) {
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ goto out;
+ info->index=0;
+ info->bd = major_names[info->index];
+ if (info->bd)
+ goto out;
+ } else {
+ info = dev;
+ }
+
+ while (info->index < ARRAY_SIZE(major_names)) {
+ if (info->bd)
+ info->bd = info->bd->next;
+ if (info->bd)
+ goto out;
+ /*
+ * No devices on this chain, move to the next
+ */
+ info->index++;
+ info->bd = (info->index < ARRAY_SIZE(major_names)) ?
+ major_names[info->index] : NULL;
+ if (info->bd)
+ goto out;
+ }
+
+out:
+ return info;
+}
+
+void *acquire_blkdev_list(void)
+{
+ down(&block_subsys_sem);
+ return get_next_blkdev(NULL);
+}
+
+void release_blkdev_list(void *dev)
+{
+ up(&block_subsys_sem);
+ kfree(dev);
+}
+
+
+/*
+ * Count the number of records in the blkdev_list.
+ * must be called with the block_subsys_sem held
+ */
+int count_blkdev_list(void)
{
struct blk_major_name *n;
- int i, len;
+ int i, count;
- len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n");
+ count = 0;
- down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
- for (n = major_names[i]; n; n = n->next) {
- /*
- * If the curent string plus the 5 extra characters
- * in the line would run us off the page, then we're done
- */
- if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
- goto page_full;
- len += sprintf(p+len, "%3d %s\n",
- n->major, n->name);
- }
+ for (n = major_names[i]; n; n = n->next)
+ count++;
}
-page_full:
- up(&block_subsys_sem);
- return len;
+ return count;
}
-#endif
+
+/*
+ * extract the major and name values from a blkdev_info struct
+ * passed in as a void to *dev. Must be called with
+ * block_subsys_sem held
+ */
+int get_blkdev_info(void *dev, int *major, char **name)
+{
+ struct blkdev_info *info = dev;
+
+ if (info->bd == NULL)
+ return 1;
+
+ *major = info->bd->major;
+ *name = info->bd->name;
+ return 0;
+}
+
int register_blkdev(unsigned int major, const char *name)
{
@@ -358,7 +424,7 @@ static struct sysfs_ops disk_sysfs_ops = {
static ssize_t disk_uevent_store(struct gendisk * disk,
const char *buf, size_t count)
{
- kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
return count;
}
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
@@ -455,14 +521,14 @@ static struct kobj_type ktype_block = {
extern struct kobj_type ktype_part;
-static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
return ((ktype == &ktype_block) || (ktype == &ktype_part));
}
-static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int block_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -474,40 +540,40 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
if (ktype == &ktype_block) {
disk = container_of(kobj, struct gendisk, kobj);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "MINOR=%u", disk->first_minor);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MINOR=%u", disk->first_minor);
} else if (ktype == &ktype_part) {
disk = container_of(kobj->parent, struct gendisk, kobj);
part = container_of(kobj, struct hd_struct, kobj);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "MINOR=%u",
- disk->first_minor + part->partno);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "MINOR=%u",
+ disk->first_minor + part->partno);
} else
return 0;
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
- "MAJOR=%u", disk->major);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MAJOR=%u", disk->major);
/* add physical device, backing this device */
physdev = disk->driverfs_dev;
if (physdev) {
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "PHYSDEVPATH=%s", path);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "PHYSDEVPATH=%s", path);
kfree(path);
if (physdev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s",
- physdev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s",
+ physdev->bus->name);
if (physdev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s",
- physdev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s",
+ physdev->driver->name);
}
/* terminate, set to next free slot, shrink available space */
@@ -520,13 +586,13 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
return 0;
}
-static struct kset_hotplug_ops block_hotplug_ops = {
- .filter = block_hotplug_filter,
- .hotplug = block_hotplug,
+static struct kset_uevent_ops block_uevent_ops = {
+ .filter = block_uevent_filter,
+ .uevent = block_uevent,
};
/* declare block_subsys. */
-static decl_subsys(block, &ktype_block, &block_hotplug_ops);
+static decl_subsys(block, &ktype_block, &block_uevent_ops);
/*
diff --git a/block/ioctl.c b/block/ioctl.c
index 6e278474f9a8..e1109491c234 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -1,6 +1,7 @@
-#include <linux/sched.h> /* for capable() */
+#include <linux/capability.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
+#include <linux/hdreg.h>
#include <linux/backing-dev.h>
#include <linux/buffer_head.h>
#include <linux/smp_lock.h>
@@ -245,6 +246,27 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
set_device_ro(bdev, n);
unlock_kernel();
return 0;
+ case HDIO_GETGEO: {
+ struct hd_geometry geo;
+
+ if (!arg)
+ return -EINVAL;
+ if (!disk->fops->getgeo)
+ return -ENOTTY;
+
+ /*
+ * We need to set the startsect first, the driver may
+ * want to override it.
+ */
+ geo.start = get_start_sect(bdev);
+ ret = disk->fops->getgeo(bdev, &geo);
+ if (ret)
+ return ret;
+ if (copy_to_user((struct hd_geometry __user *)arg, &geo,
+ sizeof(geo)))
+ return -EFAULT;
+ return 0;
+ }
}
lock_kernel();
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 99c9ca6d5992..8e27d0ab0d7c 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -26,7 +26,8 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/writeback.h>
-#include <linux/blkdev.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
/*
* for max sense size
@@ -36,6 +37,8 @@
static void blk_unplug_work(void *data);
static void blk_unplug_timeout(unsigned long data);
static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
+static void init_request_from_bio(struct request *req, struct bio *bio);
+static int __make_request(request_queue_t *q, struct bio *bio);
/*
* For the allocated request tables
@@ -60,13 +63,15 @@ static wait_queue_head_t congestion_wqh[2] = {
/*
* Controlling structure to kblockd
*/
-static struct workqueue_struct *kblockd_workqueue;
+static struct workqueue_struct *kblockd_workqueue;
unsigned long blk_max_low_pfn, blk_max_pfn;
EXPORT_SYMBOL(blk_max_low_pfn);
EXPORT_SYMBOL(blk_max_pfn);
+static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
+
/* Amount of time in which a process may batch requests */
#define BLK_BATCH_TIME (HZ/50UL)
@@ -205,6 +210,13 @@ void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn)
EXPORT_SYMBOL(blk_queue_merge_bvec);
+void blk_queue_softirq_done(request_queue_t *q, softirq_done_fn *fn)
+{
+ q->softirq_done_fn = fn;
+}
+
+EXPORT_SYMBOL(blk_queue_softirq_done);
+
/**
* blk_queue_make_request - define an alternate make_request function for a device
* @q: the request queue for the device to be affected
@@ -239,7 +251,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
- blk_queue_max_sectors(q, MAX_SECTORS);
+ blk_queue_max_sectors(q, SAFE_MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
blk_queue_dma_alignment(q, 511);
blk_queue_congestion_threshold(q);
@@ -268,6 +280,7 @@ EXPORT_SYMBOL(blk_queue_make_request);
static inline void rq_init(request_queue_t *q, struct request *rq)
{
INIT_LIST_HEAD(&rq->queuelist);
+ INIT_LIST_HEAD(&rq->donelist);
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
@@ -284,12 +297,13 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
rq->sense = NULL;
rq->end_io = NULL;
rq->end_io_data = NULL;
+ rq->completion_data = NULL;
}
/**
* blk_queue_ordered - does this queue support ordered writes
- * @q: the request queue
- * @flag: see below
+ * @q: the request queue
+ * @ordered: one of QUEUE_ORDERED_*
*
* Description:
* For journalled file systems, doing ordered writes on a commit
@@ -298,28 +312,30 @@ static inline void rq_init(request_queue_t *q, struct request *rq)
* feature should call this function and indicate so.
*
**/
-void blk_queue_ordered(request_queue_t *q, int flag)
-{
- switch (flag) {
- case QUEUE_ORDERED_NONE:
- if (q->flush_rq)
- kmem_cache_free(request_cachep, q->flush_rq);
- q->flush_rq = NULL;
- q->ordered = flag;
- break;
- case QUEUE_ORDERED_TAG:
- q->ordered = flag;
- break;
- case QUEUE_ORDERED_FLUSH:
- q->ordered = flag;
- if (!q->flush_rq)
- q->flush_rq = kmem_cache_alloc(request_cachep,
- GFP_KERNEL);
- break;
- default:
- printk("blk_queue_ordered: bad value %d\n", flag);
- break;
+int blk_queue_ordered(request_queue_t *q, unsigned ordered,
+ prepare_flush_fn *prepare_flush_fn)
+{
+ if (ordered & (QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH) &&
+ prepare_flush_fn == NULL) {
+ printk(KERN_ERR "blk_queue_ordered: prepare_flush_fn required\n");
+ return -EINVAL;
}
+
+ if (ordered != QUEUE_ORDERED_NONE &&
+ ordered != QUEUE_ORDERED_DRAIN &&
+ ordered != QUEUE_ORDERED_DRAIN_FLUSH &&
+ ordered != QUEUE_ORDERED_DRAIN_FUA &&
+ ordered != QUEUE_ORDERED_TAG &&
+ ordered != QUEUE_ORDERED_TAG_FLUSH &&
+ ordered != QUEUE_ORDERED_TAG_FUA) {
+ printk(KERN_ERR "blk_queue_ordered: bad value %d\n", ordered);
+ return -EINVAL;
+ }
+
+ q->next_ordered = ordered;
+ q->prepare_flush_fn = prepare_flush_fn;
+
+ return 0;
}
EXPORT_SYMBOL(blk_queue_ordered);
@@ -344,167 +360,265 @@ EXPORT_SYMBOL(blk_queue_issue_flush_fn);
/*
* Cache flushing for ordered writes handling
*/
-static void blk_pre_flush_end_io(struct request *flush_rq)
+inline unsigned blk_ordered_cur_seq(request_queue_t *q)
{
- struct request *rq = flush_rq->end_io_data;
- request_queue_t *q = rq->q;
-
- elv_completed_request(q, flush_rq);
-
- rq->flags |= REQ_BAR_PREFLUSH;
-
- if (!flush_rq->errors)
- elv_requeue_request(q, rq);
- else {
- q->end_flush_fn(q, flush_rq);
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- q->request_fn(q);
- }
+ if (!q->ordseq)
+ return 0;
+ return 1 << ffz(q->ordseq);
}
-static void blk_post_flush_end_io(struct request *flush_rq)
+unsigned blk_ordered_req_seq(struct request *rq)
{
- struct request *rq = flush_rq->end_io_data;
request_queue_t *q = rq->q;
- elv_completed_request(q, flush_rq);
+ BUG_ON(q->ordseq == 0);
- rq->flags |= REQ_BAR_POSTFLUSH;
+ if (rq == &q->pre_flush_rq)
+ return QUEUE_ORDSEQ_PREFLUSH;
+ if (rq == &q->bar_rq)
+ return QUEUE_ORDSEQ_BAR;
+ if (rq == &q->post_flush_rq)
+ return QUEUE_ORDSEQ_POSTFLUSH;
- q->end_flush_fn(q, flush_rq);
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- q->request_fn(q);
+ if ((rq->flags & REQ_ORDERED_COLOR) ==
+ (q->orig_bar_rq->flags & REQ_ORDERED_COLOR))
+ return QUEUE_ORDSEQ_DRAIN;
+ else
+ return QUEUE_ORDSEQ_DONE;
}
-struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
+void blk_ordered_complete_seq(request_queue_t *q, unsigned seq, int error)
{
- struct request *flush_rq = q->flush_rq;
-
- BUG_ON(!blk_barrier_rq(rq));
+ struct request *rq;
+ int uptodate;
- if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags))
- return NULL;
+ if (error && !q->orderr)
+ q->orderr = error;
- rq_init(q, flush_rq);
- flush_rq->elevator_private = NULL;
- flush_rq->flags = REQ_BAR_FLUSH;
- flush_rq->rq_disk = rq->rq_disk;
- flush_rq->rl = NULL;
+ BUG_ON(q->ordseq & seq);
+ q->ordseq |= seq;
- /*
- * prepare_flush returns 0 if no flush is needed, just mark both
- * pre and post flush as done in that case
- */
- if (!q->prepare_flush_fn(q, flush_rq)) {
- rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH;
- clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
- return rq;
- }
+ if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE)
+ return;
/*
- * some drivers dequeue requests right away, some only after io
- * completion. make sure the request is dequeued.
+ * Okay, sequence complete.
*/
- if (!list_empty(&rq->queuelist))
- blkdev_dequeue_request(rq);
+ rq = q->orig_bar_rq;
+ uptodate = q->orderr ? q->orderr : 1;
- flush_rq->end_io_data = rq;
- flush_rq->end_io = blk_pre_flush_end_io;
+ q->ordseq = 0;
- __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
- return flush_rq;
+ end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+ end_that_request_last(rq, uptodate);
}
-static void blk_start_post_flush(request_queue_t *q, struct request *rq)
+static void pre_flush_end_io(struct request *rq, int error)
{
- struct request *flush_rq = q->flush_rq;
+ elv_completed_request(rq->q, rq);
+ blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_PREFLUSH, error);
+}
- BUG_ON(!blk_barrier_rq(rq));
+static void bar_end_io(struct request *rq, int error)
+{
+ elv_completed_request(rq->q, rq);
+ blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_BAR, error);
+}
- rq_init(q, flush_rq);
- flush_rq->elevator_private = NULL;
- flush_rq->flags = REQ_BAR_FLUSH;
- flush_rq->rq_disk = rq->rq_disk;
- flush_rq->rl = NULL;
+static void post_flush_end_io(struct request *rq, int error)
+{
+ elv_completed_request(rq->q, rq);
+ blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_POSTFLUSH, error);
+}
- if (q->prepare_flush_fn(q, flush_rq)) {
- flush_rq->end_io_data = rq;
- flush_rq->end_io = blk_post_flush_end_io;
+static void queue_flush(request_queue_t *q, unsigned which)
+{
+ struct request *rq;
+ rq_end_io_fn *end_io;
- __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
- q->request_fn(q);
+ if (which == QUEUE_ORDERED_PREFLUSH) {
+ rq = &q->pre_flush_rq;
+ end_io = pre_flush_end_io;
+ } else {
+ rq = &q->post_flush_rq;
+ end_io = post_flush_end_io;
}
+
+ rq_init(q, rq);
+ rq->flags = REQ_HARDBARRIER;
+ rq->elevator_private = NULL;
+ rq->rq_disk = q->bar_rq.rq_disk;
+ rq->rl = NULL;
+ rq->end_io = end_io;
+ q->prepare_flush_fn(q, rq);
+
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
}
-static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq,
- int sectors)
+static inline struct request *start_ordered(request_queue_t *q,
+ struct request *rq)
{
- if (sectors > rq->nr_sectors)
- sectors = rq->nr_sectors;
+ q->bi_size = 0;
+ q->orderr = 0;
+ q->ordered = q->next_ordered;
+ q->ordseq |= QUEUE_ORDSEQ_STARTED;
+
+ /*
+ * Prep proxy barrier request.
+ */
+ blkdev_dequeue_request(rq);
+ q->orig_bar_rq = rq;
+ rq = &q->bar_rq;
+ rq_init(q, rq);
+ rq->flags = bio_data_dir(q->orig_bar_rq->bio);
+ rq->flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
+ rq->elevator_private = NULL;
+ rq->rl = NULL;
+ init_request_from_bio(rq, q->orig_bar_rq->bio);
+ rq->end_io = bar_end_io;
+
+ /*
+ * Queue ordered sequence. As we stack them at the head, we
+ * need to queue in reverse order. Note that we rely on that
+ * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs
+ * request gets inbetween ordered sequence.
+ */
+ if (q->ordered & QUEUE_ORDERED_POSTFLUSH)
+ queue_flush(q, QUEUE_ORDERED_POSTFLUSH);
+ else
+ q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH;
+
+ __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
- rq->nr_sectors -= sectors;
- return rq->nr_sectors;
+ if (q->ordered & QUEUE_ORDERED_PREFLUSH) {
+ queue_flush(q, QUEUE_ORDERED_PREFLUSH);
+ rq = &q->pre_flush_rq;
+ } else
+ q->ordseq |= QUEUE_ORDSEQ_PREFLUSH;
+
+ if ((q->ordered & QUEUE_ORDERED_TAG) || q->in_flight == 0)
+ q->ordseq |= QUEUE_ORDSEQ_DRAIN;
+ else
+ rq = NULL;
+
+ return rq;
}
-static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq,
- int sectors, int queue_locked)
+int blk_do_ordered(request_queue_t *q, struct request **rqp)
{
- if (q->ordered != QUEUE_ORDERED_FLUSH)
- return 0;
- if (!blk_fs_request(rq) || !blk_barrier_rq(rq))
- return 0;
- if (blk_barrier_postflush(rq))
- return 0;
+ struct request *rq = *rqp, *allowed_rq;
+ int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq);
- if (!blk_check_end_barrier(q, rq, sectors)) {
- unsigned long flags = 0;
+ if (!q->ordseq) {
+ if (!is_barrier)
+ return 1;
- if (!queue_locked)
- spin_lock_irqsave(q->queue_lock, flags);
+ if (q->next_ordered != QUEUE_ORDERED_NONE) {
+ *rqp = start_ordered(q, rq);
+ return 1;
+ } else {
+ /*
+ * This can happen when the queue switches to
+ * ORDERED_NONE while this request is on it.
+ */
+ blkdev_dequeue_request(rq);
+ end_that_request_first(rq, -EOPNOTSUPP,
+ rq->hard_nr_sectors);
+ end_that_request_last(rq, -EOPNOTSUPP);
+ *rqp = NULL;
+ return 0;
+ }
+ }
- blk_start_post_flush(q, rq);
+ if (q->ordered & QUEUE_ORDERED_TAG) {
+ if (is_barrier && rq != &q->bar_rq)
+ *rqp = NULL;
+ return 1;
+ }
- if (!queue_locked)
- spin_unlock_irqrestore(q->queue_lock, flags);
+ switch (blk_ordered_cur_seq(q)) {
+ case QUEUE_ORDSEQ_PREFLUSH:
+ allowed_rq = &q->pre_flush_rq;
+ break;
+ case QUEUE_ORDSEQ_BAR:
+ allowed_rq = &q->bar_rq;
+ break;
+ case QUEUE_ORDSEQ_POSTFLUSH:
+ allowed_rq = &q->post_flush_rq;
+ break;
+ default:
+ allowed_rq = NULL;
+ break;
}
+ if (rq != allowed_rq &&
+ (blk_fs_request(rq) || rq == &q->pre_flush_rq ||
+ rq == &q->post_flush_rq))
+ *rqp = NULL;
+
return 1;
}
-/**
- * blk_complete_barrier_rq - complete possible barrier request
- * @q: the request queue for the device
- * @rq: the request
- * @sectors: number of sectors to complete
- *
- * Description:
- * Used in driver end_io handling to determine whether to postpone
- * completion of a barrier request until a post flush has been done. This
- * is the unlocked variant, used if the caller doesn't already hold the
- * queue lock.
- **/
-int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors)
+static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
{
- return __blk_complete_barrier_rq(q, rq, sectors, 0);
+ request_queue_t *q = bio->bi_private;
+ struct bio_vec *bvec;
+ int i;
+
+ /*
+ * This is dry run, restore bio_sector and size. We'll finish
+ * this request again with the original bi_end_io after an
+ * error occurs or post flush is complete.
+ */
+ q->bi_size += bytes;
+
+ if (bio->bi_size)
+ return 1;
+
+ /* Rewind bvec's */
+ bio->bi_idx = 0;
+ bio_for_each_segment(bvec, bio, i) {
+ bvec->bv_len += bvec->bv_offset;
+ bvec->bv_offset = 0;
+ }
+
+ /* Reset bio */
+ set_bit(BIO_UPTODATE, &bio->bi_flags);
+ bio->bi_size = q->bi_size;
+ bio->bi_sector -= (q->bi_size >> 9);
+ q->bi_size = 0;
+
+ return 0;
}
-EXPORT_SYMBOL(blk_complete_barrier_rq);
-/**
- * blk_complete_barrier_rq_locked - complete possible barrier request
- * @q: the request queue for the device
- * @rq: the request
- * @sectors: number of sectors to complete
- *
- * Description:
- * See blk_complete_barrier_rq(). This variant must be used if the caller
- * holds the queue lock.
- **/
-int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq,
- int sectors)
+static inline int ordered_bio_endio(struct request *rq, struct bio *bio,
+ unsigned int nbytes, int error)
{
- return __blk_complete_barrier_rq(q, rq, sectors, 1);
+ request_queue_t *q = rq->q;
+ bio_end_io_t *endio;
+ void *private;
+
+ if (&q->bar_rq != rq)
+ return 0;
+
+ /*
+ * Okay, this is the barrier request in progress, dry finish it.
+ */
+ if (error && !q->orderr)
+ q->orderr = error;
+
+ endio = bio->bi_end_io;
+ private = bio->bi_private;
+ bio->bi_end_io = flush_dry_bio_endio;
+ bio->bi_private = q;
+
+ bio_endio(bio, nbytes, error);
+
+ bio->bi_end_io = endio;
+ bio->bi_private = private;
+
+ return 1;
}
-EXPORT_SYMBOL(blk_complete_barrier_rq_locked);
/**
* blk_queue_bounce_limit - set bounce buffer limit for queue
@@ -555,7 +669,12 @@ void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
}
- q->max_sectors = q->max_hw_sectors = max_sectors;
+ if (BLK_DEF_MAX_SECTORS > max_sectors)
+ q->max_hw_sectors = q->max_sectors = max_sectors;
+ else {
+ q->max_sectors = BLK_DEF_MAX_SECTORS;
+ q->max_hw_sectors = max_sectors;
+ }
}
EXPORT_SYMBOL(blk_queue_max_sectors);
@@ -657,8 +776,8 @@ EXPORT_SYMBOL(blk_queue_hardsect_size);
void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
{
/* zero is "infinity" */
- t->max_sectors = t->max_hw_sectors =
- min_not_zero(t->max_sectors,b->max_sectors);
+ t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
+ t->max_hw_sectors = min_not_zero(t->max_hw_sectors,b->max_hw_sectors);
t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
@@ -1034,12 +1153,13 @@ void blk_queue_invalidate_tags(request_queue_t *q)
EXPORT_SYMBOL(blk_queue_invalidate_tags);
-static char *rq_flags[] = {
+static const char * const rq_flags[] = {
"REQ_RW",
"REQ_FAILFAST",
"REQ_SORTED",
"REQ_SOFTBARRIER",
"REQ_HARDBARRIER",
+ "REQ_FUA",
"REQ_CMD",
"REQ_NOMERGE",
"REQ_STARTED",
@@ -1059,6 +1179,7 @@ static char *rq_flags[] = {
"REQ_PM_SUSPEND",
"REQ_PM_RESUME",
"REQ_PM_SHUTDOWN",
+ "REQ_ORDERED_COLOR",
};
void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -1293,9 +1414,15 @@ static inline int ll_new_hw_segment(request_queue_t *q,
static int ll_back_merge_fn(request_queue_t *q, struct request *req,
struct bio *bio)
{
+ unsigned short max_sectors;
int len;
- if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+ if (unlikely(blk_pc_request(req)))
+ max_sectors = q->max_hw_sectors;
+ else
+ max_sectors = q->max_sectors;
+
+ if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
@@ -1325,9 +1452,16 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
static int ll_front_merge_fn(request_queue_t *q, struct request *req,
struct bio *bio)
{
+ unsigned short max_sectors;
int len;
- if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+ if (unlikely(blk_pc_request(req)))
+ max_sectors = q->max_hw_sectors;
+ else
+ max_sectors = q->max_sectors;
+
+
+ if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
@@ -1623,8 +1757,6 @@ void blk_cleanup_queue(request_queue_t * q)
if (q->queue_tags)
__blk_queue_free_tags(q);
- blk_queue_ordered(q, QUEUE_ORDERED_NONE);
-
kmem_cache_free(requestq_cachep, q);
}
@@ -1649,8 +1781,6 @@ static int blk_init_free_list(request_queue_t *q)
return 0;
}
-static int __make_request(request_queue_t *, struct bio *);
-
request_queue_t *blk_alloc_queue(gfp_t gfp_mask)
{
return blk_alloc_queue_node(gfp_mask, -1);
@@ -1890,40 +2020,40 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
- struct io_context *ioc = current_io_context(GFP_ATOMIC);
- int priv;
-
- if (rl->count[rw]+1 >= q->nr_requests) {
- /*
- * The queue will fill after this allocation, so set it as
- * full, and mark this process as "batching". This process
- * will be allowed to complete a batch of requests, others
- * will be blocked.
- */
- if (!blk_queue_full(q, rw)) {
- ioc_set_batching(q, ioc);
- blk_set_queue_full(q, rw);
- }
- }
+ struct io_context *ioc = NULL;
+ int may_queue, priv;
- switch (elv_may_queue(q, rw, bio)) {
- case ELV_MQUEUE_NO:
- goto rq_starved;
- case ELV_MQUEUE_MAY:
- break;
- case ELV_MQUEUE_MUST:
- goto get_rq;
- }
+ may_queue = elv_may_queue(q, rw, bio);
+ if (may_queue == ELV_MQUEUE_NO)
+ goto rq_starved;
- if (blk_queue_full(q, rw) && !ioc_batching(q, ioc)) {
- /*
- * The queue is full and the allocating process is not a
- * "batcher", and not exempted by the IO scheduler
- */
- goto out;
+ if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) {
+ if (rl->count[rw]+1 >= q->nr_requests) {
+ ioc = current_io_context(GFP_ATOMIC);
+ /*
+ * The queue will fill after this allocation, so set
+ * it as full, and mark this process as "batching".
+ * This process will be allowed to complete a batch of
+ * requests, others will be blocked.
+ */
+ if (!blk_queue_full(q, rw)) {
+ ioc_set_batching(q, ioc);
+ blk_set_queue_full(q, rw);
+ } else {
+ if (may_queue != ELV_MQUEUE_MUST
+ && !ioc_batching(q, ioc)) {
+ /*
+ * The queue is full and the allocating
+ * process is not a "batcher", and not
+ * exempted by the IO scheduler
+ */
+ goto out;
+ }
+ }
+ }
+ set_queue_congested(q, rw);
}
-get_rq:
/*
* Only allow batching queuers to allocate up to 50% over the defined
* limit of requests, otherwise we could have thousands of requests
@@ -1934,8 +2064,6 @@ get_rq:
rl->count[rw]++;
rl->starved[rw] = 0;
- if (rl->count[rw] >= queue_congestion_on_threshold(q))
- set_queue_congested(q, rw);
priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
if (priv)
@@ -1944,7 +2072,7 @@ get_rq:
spin_unlock_irq(q->queue_lock);
rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
- if (!rq) {
+ if (unlikely(!rq)) {
/*
* Allocation failed presumably due to memory. Undo anything
* we might have messed up.
@@ -1969,6 +2097,12 @@ rq_starved:
goto out;
}
+ /*
+ * ioc may be NULL here, and ioc_batching will be false. That's
+ * OK, if the queue is under the request limit then requests need
+ * not count toward the nr_batch_requests limit. There will always
+ * be some limit enforced by BLK_BATCH_TIME.
+ */
if (ioc_batching(q, ioc))
ioc->nr_batch_requests--;
@@ -2144,7 +2278,7 @@ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf,
struct bio *bio;
int reading;
- if (len > (q->max_sectors << 9))
+ if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len || !ubuf)
return -EINVAL;
@@ -2259,7 +2393,7 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf,
{
struct bio *bio;
- if (len > (q->max_sectors << 9))
+ if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len || !kbuf)
return -EINVAL;
@@ -2295,7 +2429,7 @@ EXPORT_SYMBOL(blk_rq_map_kern);
*/
void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
struct request *rq, int at_head,
- void (*done)(struct request *))
+ rq_end_io_fn *done)
{
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
@@ -2306,6 +2440,8 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
generic_unplug_device(q);
}
+EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
+
/**
* blk_execute_rq - insert a request into queue for execution
* @q: queue to insert the request in
@@ -2444,7 +2580,7 @@ void disk_round_stats(struct gendisk *disk)
/*
* queue lock must be held
*/
-static void __blk_put_request(request_queue_t *q, struct request *req)
+void __blk_put_request(request_queue_t *q, struct request *req)
{
struct request_list *rl = req->rl;
@@ -2473,6 +2609,8 @@ static void __blk_put_request(request_queue_t *q, struct request *req)
}
}
+EXPORT_SYMBOL_GPL(__blk_put_request);
+
void blk_put_request(struct request *req)
{
unsigned long flags;
@@ -2495,7 +2633,7 @@ EXPORT_SYMBOL(blk_put_request);
* blk_end_sync_rq - executes a completion event on a request
* @rq: request to complete
*/
-void blk_end_sync_rq(struct request *rq)
+void blk_end_sync_rq(struct request *rq, int error)
{
struct completion *waiting = rq->waiting;
@@ -2609,29 +2747,35 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq)
return 0;
}
-/**
- * blk_attempt_remerge - attempt to remerge active head with next request
- * @q: The &request_queue_t belonging to the device
- * @rq: The head request (usually)
- *
- * Description:
- * For head-active devices, the queue can easily be unplugged so quickly
- * that proper merging is not done on the front request. This may hurt
- * performance greatly for some devices. The block layer cannot safely
- * do merging on that first request for these queues, but the driver can
- * call this function and make it happen any way. Only the driver knows
- * when it is safe to do so.
- **/
-void blk_attempt_remerge(request_queue_t *q, struct request *rq)
+static void init_request_from_bio(struct request *req, struct bio *bio)
{
- unsigned long flags;
+ req->flags |= REQ_CMD;
- spin_lock_irqsave(q->queue_lock, flags);
- attempt_back_merge(q, rq);
- spin_unlock_irqrestore(q->queue_lock, flags);
-}
+ /*
+ * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
+ */
+ if (bio_rw_ahead(bio) || bio_failfast(bio))
+ req->flags |= REQ_FAILFAST;
-EXPORT_SYMBOL(blk_attempt_remerge);
+ /*
+ * REQ_BARRIER implies no merging, but lets make it explicit
+ */
+ if (unlikely(bio_barrier(bio)))
+ req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
+
+ req->errors = 0;
+ req->hard_sector = req->sector = bio->bi_sector;
+ req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio);
+ req->current_nr_sectors = req->hard_cur_sectors = bio_cur_sectors(bio);
+ req->nr_phys_segments = bio_phys_segments(req->q, bio);
+ req->nr_hw_segments = bio_hw_segments(req->q, bio);
+ req->buffer = bio_data(bio); /* see ->buffer comment above */
+ req->waiting = NULL;
+ req->bio = req->biotail = bio;
+ req->ioprio = bio_prio(bio);
+ req->rq_disk = bio->bi_bdev->bd_disk;
+ req->start_time = jiffies;
+}
static int __make_request(request_queue_t *q, struct bio *bio)
{
@@ -2658,7 +2802,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
spin_lock_prefetch(q->queue_lock);
barrier = bio_barrier(bio);
- if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
+ if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) {
err = -EOPNOTSUPP;
goto end_io;
}
@@ -2728,33 +2872,7 @@ get_rq:
* We don't worry about that case for efficiency. It won't happen
* often, and the elevators are able to handle it.
*/
-
- req->flags |= REQ_CMD;
-
- /*
- * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
- */
- if (bio_rw_ahead(bio) || bio_failfast(bio))
- req->flags |= REQ_FAILFAST;
-
- /*
- * REQ_BARRIER implies no merging, but lets make it explicit
- */
- if (unlikely(barrier))
- req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
-
- req->errors = 0;
- req->hard_sector = req->sector = sector;
- req->hard_nr_sectors = req->nr_sectors = nr_sectors;
- req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors;
- req->nr_phys_segments = bio_phys_segments(q, bio);
- req->nr_hw_segments = bio_hw_segments(q, bio);
- req->buffer = bio_data(bio); /* see ->buffer comment above */
- req->waiting = NULL;
- req->bio = req->biotail = bio;
- req->ioprio = prio;
- req->rq_disk = bio->bi_bdev->bd_disk;
- req->start_time = jiffies;
+ init_request_from_bio(req, bio);
spin_lock_irq(q->queue_lock);
if (elv_queue_empty(q))
@@ -3045,7 +3163,8 @@ static int __end_that_request_first(struct request *req, int uptodate,
if (nr_bytes >= bio->bi_size) {
req->bio = bio->bi_next;
nbytes = bio->bi_size;
- bio_endio(bio, nbytes, error);
+ if (!ordered_bio_endio(req, bio, nbytes, error))
+ bio_endio(bio, nbytes, error);
next_idx = 0;
bio_nbytes = 0;
} else {
@@ -3100,7 +3219,8 @@ static int __end_that_request_first(struct request *req, int uptodate,
* if the request wasn't completed, update state
*/
if (bio_nbytes) {
- bio_endio(bio, bio_nbytes, error);
+ if (!ordered_bio_endio(req, bio, bio_nbytes, error))
+ bio_endio(bio, bio_nbytes, error);
bio->bi_idx += next_idx;
bio_iovec(bio)->bv_offset += nr_bytes;
bio_iovec(bio)->bv_len -= nr_bytes;
@@ -3155,11 +3275,100 @@ int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
EXPORT_SYMBOL(end_that_request_chunk);
/*
+ * splice the completion data to a local structure and hand off to
+ * process_completion_queue() to complete the requests
+ */
+static void blk_done_softirq(struct softirq_action *h)
+{
+ struct list_head *cpu_list;
+ LIST_HEAD(local_list);
+
+ local_irq_disable();
+ cpu_list = &__get_cpu_var(blk_cpu_done);
+ list_splice_init(cpu_list, &local_list);
+ local_irq_enable();
+
+ while (!list_empty(&local_list)) {
+ struct request *rq = list_entry(local_list.next, struct request, donelist);
+
+ list_del_init(&rq->donelist);
+ rq->q->softirq_done_fn(rq);
+ }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int blk_cpu_notify(struct notifier_block *self, unsigned long action,
+ void *hcpu)
+{
+ /*
+ * If a CPU goes away, splice its entries to the current CPU
+ * and trigger a run of the softirq
+ */
+ if (action == CPU_DEAD) {
+ int cpu = (unsigned long) hcpu;
+
+ local_irq_disable();
+ list_splice_init(&per_cpu(blk_cpu_done, cpu),
+ &__get_cpu_var(blk_cpu_done));
+ raise_softirq_irqoff(BLOCK_SOFTIRQ);
+ local_irq_enable();
+ }
+
+ return NOTIFY_OK;
+}
+
+
+static struct notifier_block __devinitdata blk_cpu_notifier = {
+ .notifier_call = blk_cpu_notify,
+};
+
+#endif /* CONFIG_HOTPLUG_CPU */
+
+/**
+ * blk_complete_request - end I/O on a request
+ * @req: the request being processed
+ *
+ * Description:
+ * Ends all I/O on a request. It does not handle partial completions,
+ * unless the driver actually implements this in its completionc callback
+ * through requeueing. Theh actual completion happens out-of-order,
+ * through a softirq handler. The user must have registered a completion
+ * callback through blk_queue_softirq_done().
+ **/
+
+void blk_complete_request(struct request *req)
+{
+ struct list_head *cpu_list;
+ unsigned long flags;
+
+ BUG_ON(!req->q->softirq_done_fn);
+
+ local_irq_save(flags);
+
+ cpu_list = &__get_cpu_var(blk_cpu_done);
+ list_add_tail(&req->donelist, cpu_list);
+ raise_softirq_irqoff(BLOCK_SOFTIRQ);
+
+ local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(blk_complete_request);
+
+/*
* queue lock must be held
*/
-void end_that_request_last(struct request *req)
+void end_that_request_last(struct request *req, int uptodate)
{
struct gendisk *disk = req->rq_disk;
+ int error;
+
+ /*
+ * extend uptodate bool to allow < 0 value to be direct io error
+ */
+ error = 0;
+ if (end_io_error(uptodate))
+ error = !uptodate ? -EIO : uptodate;
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
@@ -3174,7 +3383,7 @@ void end_that_request_last(struct request *req)
disk->in_flight--;
}
if (req->end_io)
- req->end_io(req);
+ req->end_io(req, error);
else
__blk_put_request(req->q, req);
}
@@ -3186,7 +3395,7 @@ void end_request(struct request *req, int uptodate)
if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) {
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
}
@@ -3224,6 +3433,8 @@ EXPORT_SYMBOL(kblockd_flush);
int __init blk_dev_init(void)
{
+ int i;
+
kblockd_workqueue = create_workqueue("kblockd");
if (!kblockd_workqueue)
panic("Failed to create kblockd\n");
@@ -3237,6 +3448,14 @@ int __init blk_dev_init(void)
iocontext_cachep = kmem_cache_create("blkdev_ioc",
sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL);
+ for (i = 0; i < NR_CPUS; i++)
+ INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
+
+ open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
+#ifdef CONFIG_HOTPLUG_CPU
+ register_cpu_notifier(&blk_cpu_notifier);
+#endif
+
blk_max_low_pfn = max_low_pfn;
blk_max_pfn = max_pfn;
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 6e7db2e79f42..cc72210687eb 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -21,6 +21,7 @@
#include <linux/string.h>
#include <linux/module.h>
#include <linux/blkdev.h>
+#include <linux/capability.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
#include <linux/slab.h>
@@ -46,7 +47,7 @@ EXPORT_SYMBOL(scsi_command_size);
static int sg_get_version(int __user *p)
{
- static int sg_version_num = 30527;
+ static const int sg_version_num = 30527;
return put_user(sg_version_num, p);
}
@@ -190,16 +191,21 @@ static int verify_command(struct file *file, unsigned char *cmd)
safe_for_write(GPCMD_SET_STREAMING),
};
unsigned char type = cmd_type[cmd[0]];
+ int has_write_perm = 0;
/* Anybody who can open the device can do a read-safe command */
if (type & CMD_READ_SAFE)
return 0;
+ /*
+ * file can be NULL from ioctl_by_bdev()...
+ */
+ if (file)
+ has_write_perm = file->f_mode & FMODE_WRITE;
+
/* Write-safe commands just require a writable open.. */
- if (type & CMD_WRITE_SAFE) {
- if (file->f_mode & FMODE_WRITE)
- return 0;
- }
+ if ((type & CMD_WRITE_SAFE) && has_write_perm)
+ return 0;
/* And root can do any command.. */
if (capable(CAP_SYS_RAWIO))
@@ -233,7 +239,7 @@ static int sg_io(struct file *file, request_queue_t *q,
if (verify_command(file, cmd))
return -EPERM;
- if (hdr->dxfer_len > (q->max_sectors << 9))
+ if (hdr->dxfer_len > (q->max_hw_sectors << 9))
return -EIO;
if (hdr->dxfer_len)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 89299f4ffe12..c442f2e7ce46 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -40,10 +40,11 @@ config CRYPTO_SHA1
help
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
-config CRYPTO_SHA1_Z990
- tristate "SHA1 digest algorithm for IBM zSeries z990"
- depends on CRYPTO && ARCH_S390
+config CRYPTO_SHA1_S390
+ tristate "SHA1 digest algorithm (s390)"
+ depends on CRYPTO && S390
help
+ This is the s390 hardware accelerated implementation of the
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
config CRYPTO_SHA256
@@ -55,6 +56,16 @@ config CRYPTO_SHA256
This version of SHA implements a 256 bit hash with 128 bits of
security against collision attacks.
+config CRYPTO_SHA256_S390
+ tristate "SHA256 digest algorithm (s390)"
+ depends on CRYPTO && S390
+ help
+ This is the s390 hardware accelerated implementation of the
+ SHA256 secure hash standard (DFIPS 180-2).
+
+ This version of SHA implements a 256 bit hash with 128 bits of
+ security against collision attacks.
+
config CRYPTO_SHA512
tristate "SHA384 and SHA512 digest algorithms"
depends on CRYPTO
@@ -98,9 +109,9 @@ config CRYPTO_DES
help
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
-config CRYPTO_DES_Z990
- tristate "DES and Triple DES cipher algorithms for IBM zSeries z990"
- depends on CRYPTO && ARCH_S390
+config CRYPTO_DES_S390
+ tristate "DES and Triple DES cipher algorithms (s390)"
+ depends on CRYPTO && S390
help
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
@@ -146,7 +157,7 @@ config CRYPTO_SERPENT
config CRYPTO_AES
tristate "AES cipher algorithms"
- depends on CRYPTO && !(X86 || UML_X86)
+ depends on CRYPTO
help
AES cipher algorithms (FIPS-197). AES uses the Rijndael
algorithm.
@@ -204,6 +215,26 @@ config CRYPTO_AES_X86_64
See <http://csrc.nist.gov/encryption/aes/> for more information.
+config CRYPTO_AES_S390
+ tristate "AES cipher algorithms (s390)"
+ depends on CRYPTO && S390
+ help
+ This is the s390 hardware accelerated implementation of the
+ AES cipher algorithms (FIPS-197). AES uses the Rijndael
+ algorithm.
+
+ Rijndael appears to be consistently a very good performer in
+ both hardware and software across a wide range of computing
+ environments regardless of its use in feedback or non-feedback
+ modes. Its key setup time is excellent, and its key agility is
+ good. Rijndael's very low memory requirements make it very well
+ suited for restricted-space environments, in which it also
+ demonstrates excellent performance. Rijndael's operations are
+ among the easiest to defend against power and timing attacks.
+
+ On s390 the System z9-109 currently only supports the key size
+ of 128 bit.
+
config CRYPTO_CAST5
tristate "CAST5 (CAST-128) cipher algorithm"
depends on CRYPTO
diff --git a/crypto/aes.c b/crypto/aes.c
index 5df92888ef5a..0a6a5c143686 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -73,9 +73,6 @@ byte(const u32 x, const unsigned n)
return x >> (n << 3);
}
-#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
-#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
-
struct aes_ctx {
int key_length;
u32 E[60];
@@ -256,6 +253,7 @@ static int
aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
{
struct aes_ctx *ctx = ctx_arg;
+ const __le32 *key = (const __le32 *)in_key;
u32 i, t, u, v, w;
if (key_len != 16 && key_len != 24 && key_len != 32) {
@@ -265,10 +263,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
ctx->key_length = key_len;
- E_KEY[0] = u32_in (in_key);
- E_KEY[1] = u32_in (in_key + 4);
- E_KEY[2] = u32_in (in_key + 8);
- E_KEY[3] = u32_in (in_key + 12);
+ E_KEY[0] = le32_to_cpu(key[0]);
+ E_KEY[1] = le32_to_cpu(key[1]);
+ E_KEY[2] = le32_to_cpu(key[2]);
+ E_KEY[3] = le32_to_cpu(key[3]);
switch (key_len) {
case 16:
@@ -278,17 +276,17 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
break;
case 24:
- E_KEY[4] = u32_in (in_key + 16);
- t = E_KEY[5] = u32_in (in_key + 20);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ t = E_KEY[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
- E_KEY[4] = u32_in (in_key + 16);
- E_KEY[5] = u32_in (in_key + 20);
- E_KEY[6] = u32_in (in_key + 24);
- t = E_KEY[7] = u32_in (in_key + 28);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ E_KEY[5] = le32_to_cpu(key[5]);
+ E_KEY[6] = le32_to_cpu(key[6]);
+ t = E_KEY[7] = le32_to_cpu(key[7]);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
@@ -324,13 +322,15 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
+ const __le32 *src = (const __le32 *)in;
+ __le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
const u32 *kp = E_KEY + 4;
- b0[0] = u32_in (in) ^ E_KEY[0];
- b0[1] = u32_in (in + 4) ^ E_KEY[1];
- b0[2] = u32_in (in + 8) ^ E_KEY[2];
- b0[3] = u32_in (in + 12) ^ E_KEY[3];
+ b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0];
+ b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1];
+ b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2];
+ b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3];
if (ctx->key_length > 24) {
f_nround (b1, b0, kp);
@@ -353,10 +353,10 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
f_nround (b1, b0, kp);
f_lround (b0, b1, kp);
- u32_out (out, b0[0]);
- u32_out (out + 4, b0[1]);
- u32_out (out + 8, b0[2]);
- u32_out (out + 12, b0[3]);
+ dst[0] = cpu_to_le32(b0[0]);
+ dst[1] = cpu_to_le32(b0[1]);
+ dst[2] = cpu_to_le32(b0[2]);
+ dst[3] = cpu_to_le32(b0[3]);
}
/* decrypt a block of text */
@@ -377,14 +377,16 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
{
const struct aes_ctx *ctx = ctx_arg;
+ const __le32 *src = (const __le32 *)in;
+ __le32 *dst = (__le32 *)out;
u32 b0[4], b1[4];
const int key_len = ctx->key_length;
const u32 *kp = D_KEY + key_len + 20;
- b0[0] = u32_in (in) ^ E_KEY[key_len + 24];
- b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25];
- b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26];
- b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27];
+ b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24];
+ b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25];
+ b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26];
+ b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27];
if (key_len > 24) {
i_nround (b1, b0, kp);
@@ -407,18 +409,21 @@ static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
i_nround (b1, b0, kp);
i_lround (b0, b1, kp);
- u32_out (out, b0[0]);
- u32_out (out + 4, b0[1]);
- u32_out (out + 8, b0[2]);
- u32_out (out + 12, b0[3]);
+ dst[0] = cpu_to_le32(b0[0]);
+ dst[1] = cpu_to_le32(b0[1]);
+ dst[2] = cpu_to_le32(b0[2]);
+ dst[3] = cpu_to_le32(b0[3]);
}
static struct crypto_alg aes_alg = {
.cra_name = "aes",
+ .cra_driver_name = "aes-generic",
+ .cra_priority = 100,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
.cra_u = {
diff --git a/crypto/anubis.c b/crypto/anubis.c
index 3925eb0133cb..2c796bdb91a6 100644
--- a/crypto/anubis.c
+++ b/crypto/anubis.c
@@ -32,8 +32,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define ANUBIS_MIN_KEY_SIZE 16
#define ANUBIS_MAX_KEY_SIZE 40
@@ -461,8 +463,8 @@ static const u32 rc[] = {
static int anubis_setkey(void *ctx_arg, const u8 *in_key,
unsigned int key_len, u32 *flags)
{
-
- int N, R, i, pos, r;
+ const __be32 *key = (const __be32 *)in_key;
+ int N, R, i, r;
u32 kappa[ANUBIS_MAX_N];
u32 inter[ANUBIS_MAX_N];
@@ -483,13 +485,8 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key,
ctx->R = R = 8 + N;
/* * map cipher key to initial key state (mu): */
- for (i = 0, pos = 0; i < N; i++, pos += 4) {
- kappa[i] =
- (in_key[pos ] << 24) ^
- (in_key[pos + 1] << 16) ^
- (in_key[pos + 2] << 8) ^
- (in_key[pos + 3] );
- }
+ for (i = 0; i < N; i++)
+ kappa[i] = be32_to_cpu(key[i]);
/*
* generate R + 1 round keys:
@@ -578,7 +575,9 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key,
static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4],
u8 *ciphertext, const u8 *plaintext, const int R)
{
- int i, pos, r;
+ const __be32 *src = (const __be32 *)plaintext;
+ __be32 *dst = (__be32 *)ciphertext;
+ int i, r;
u32 state[4];
u32 inter[4];
@@ -586,14 +585,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4],
* map plaintext block to cipher state (mu)
* and add initial round key (sigma[K^0]):
*/
- for (i = 0, pos = 0; i < 4; i++, pos += 4) {
- state[i] =
- (plaintext[pos ] << 24) ^
- (plaintext[pos + 1] << 16) ^
- (plaintext[pos + 2] << 8) ^
- (plaintext[pos + 3] ) ^
- roundKey[0][i];
- }
+ for (i = 0; i < 4; i++)
+ state[i] = be32_to_cpu(src[i]) ^ roundKey[0][i];
/*
* R - 1 full rounds:
@@ -663,13 +656,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4],
* map cipher state to ciphertext block (mu^{-1}):
*/
- for (i = 0, pos = 0; i < 4; i++, pos += 4) {
- u32 w = inter[i];
- ciphertext[pos ] = (u8)(w >> 24);
- ciphertext[pos + 1] = (u8)(w >> 16);
- ciphertext[pos + 2] = (u8)(w >> 8);
- ciphertext[pos + 3] = (u8)(w );
- }
+ for (i = 0; i < 4; i++)
+ dst[i] = cpu_to_be32(inter[i]);
}
static void anubis_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
@@ -689,6 +677,7 @@ static struct crypto_alg anubis_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = ANUBIS_BLOCK_SIZE,
.cra_ctxsize = sizeof (struct anubis_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(anubis_alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/api.c b/crypto/api.c
index 40ae42e9b6a6..e26156f71839 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
* and Nettle, by Niels Möller.
@@ -18,9 +19,11 @@
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/errno.h>
+#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/rwsem.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include "internal.h"
LIST_HEAD(crypto_alg_list);
@@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg)
static struct crypto_alg *crypto_alg_lookup(const char *name)
{
struct crypto_alg *q, *alg = NULL;
+ int best = -1;
if (!name)
return NULL;
@@ -46,11 +50,23 @@ static struct crypto_alg *crypto_alg_lookup(const char *name)
down_read(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (!(strcmp(q->cra_name, name))) {
- if (crypto_alg_get(q))
- alg = q;
+ int exact, fuzzy;
+
+ exact = !strcmp(q->cra_driver_name, name);
+ fuzzy = !strcmp(q->cra_name, name);
+ if (!exact && !(fuzzy && q->cra_priority > best))
+ continue;
+
+ if (unlikely(!crypto_alg_get(q)))
+ continue;
+
+ best = q->cra_priority;
+ if (alg)
+ crypto_alg_put(alg);
+ alg = q;
+
+ if (exact)
break;
- }
}
up_read(&crypto_alg_sem);
@@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
kfree(tfm);
}
+static inline int crypto_set_driver_name(struct crypto_alg *alg)
+{
+ static const char suffix[] = "-generic";
+ char *driver_name = (char *)alg->cra_driver_name;
+ int len;
+
+ if (*driver_name)
+ return 0;
+
+ len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+ if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
+ return -ENAMETOOLONG;
+
+ memcpy(driver_name + len, suffix, sizeof(suffix));
+ return 0;
+}
+
int crypto_register_alg(struct crypto_alg *alg)
{
- int ret = 0;
+ int ret;
struct crypto_alg *q;
if (alg->cra_alignmask & (alg->cra_alignmask + 1))
@@ -218,13 +251,20 @@ int crypto_register_alg(struct crypto_alg *alg)
if (alg->cra_alignmask & alg->cra_blocksize)
return -EINVAL;
- if (alg->cra_blocksize > PAGE_SIZE)
+ if (alg->cra_blocksize > PAGE_SIZE / 8)
+ return -EINVAL;
+
+ if (alg->cra_priority < 0)
return -EINVAL;
+ ret = crypto_set_driver_name(alg);
+ if (unlikely(ret))
+ return ret;
+
down_write(&crypto_alg_sem);
list_for_each_entry(q, &crypto_alg_list, cra_list) {
- if (!(strcmp(q->cra_name, alg->cra_name))) {
+ if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) {
ret = -EEXIST;
goto out;
}
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
index a8b29d54e7d8..7f710b201f20 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish.c
@@ -19,8 +19,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define BF_BLOCK_SIZE 8
#define BF_MIN_KEY_SIZE 4
@@ -451,6 +453,7 @@ static struct crypto_alg alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = BF_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct bf_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/cast5.c b/crypto/cast5.c
index bc42f42b4fe3..8834c8580c04 100644
--- a/crypto/cast5.c
+++ b/crypto/cast5.c
@@ -21,11 +21,13 @@
*/
+#include <asm/byteorder.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/types.h>
#define CAST5_BLOCK_SIZE 8
#define CAST5_MIN_KEY_SIZE 5
@@ -578,6 +580,8 @@ static const u32 sb8[256] = {
static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
{
struct cast5_ctx *c = (struct cast5_ctx *) ctx;
+ const __be32 *src = (const __be32 *)inbuf;
+ __be32 *dst = (__be32 *)outbuf;
u32 l, r, t;
u32 I; /* used by the Fx macros */
u32 *Km;
@@ -589,8 +593,8 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
/* (L0,R0) <-- (m1...m64). (Split the plaintext into left and
* right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
*/
- l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
- r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
+ l = be32_to_cpu(src[0]);
+ r = be32_to_cpu(src[1]);
/* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
* Li = Ri-1;
@@ -634,19 +638,15 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
/* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
* concatenate to form the ciphertext.) */
- outbuf[0] = (r >> 24) & 0xff;
- outbuf[1] = (r >> 16) & 0xff;
- outbuf[2] = (r >> 8) & 0xff;
- outbuf[3] = r & 0xff;
- outbuf[4] = (l >> 24) & 0xff;
- outbuf[5] = (l >> 16) & 0xff;
- outbuf[6] = (l >> 8) & 0xff;
- outbuf[7] = l & 0xff;
+ dst[0] = cpu_to_be32(r);
+ dst[1] = cpu_to_be32(l);
}
static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
{
struct cast5_ctx *c = (struct cast5_ctx *) ctx;
+ const __be32 *src = (const __be32 *)inbuf;
+ __be32 *dst = (__be32 *)outbuf;
u32 l, r, t;
u32 I;
u32 *Km;
@@ -655,8 +655,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
Km = c->Km;
Kr = c->Kr;
- l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
- r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
+ l = be32_to_cpu(src[0]);
+ r = be32_to_cpu(src[1]);
if (!(c->rr)) {
t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
@@ -690,14 +690,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
}
- outbuf[0] = (r >> 24) & 0xff;
- outbuf[1] = (r >> 16) & 0xff;
- outbuf[2] = (r >> 8) & 0xff;
- outbuf[3] = r & 0xff;
- outbuf[4] = (l >> 24) & 0xff;
- outbuf[5] = (l >> 16) & 0xff;
- outbuf[6] = (l >> 8) & 0xff;
- outbuf[7] = l & 0xff;
+ dst[0] = cpu_to_be32(r);
+ dst[1] = cpu_to_be32(l);
}
static void key_schedule(u32 * x, u32 * z, u32 * k)
@@ -782,7 +776,7 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags)
u32 x[4];
u32 z[4];
u32 k[16];
- u8 p_key[16];
+ __be32 p_key[4];
struct cast5_ctx *c = (struct cast5_ctx *) ctx;
if (key_len < 5 || key_len > 16) {
@@ -796,12 +790,10 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags)
memcpy(p_key, key, key_len);
- x[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3];
- x[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7];
- x[2] =
- p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11];
- x[3] =
- p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15];
+ x[0] = be32_to_cpu(p_key[0]);
+ x[1] = be32_to_cpu(p_key[1]);
+ x[2] = be32_to_cpu(p_key[2]);
+ x[3] = be32_to_cpu(p_key[3]);
key_schedule(x, z, k);
for (i = 0; i < 16; i++)
@@ -817,6 +809,7 @@ static struct crypto_alg alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = CAST5_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct cast5_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = {
diff --git a/crypto/cast6.c b/crypto/cast6.c
index 3eb081073423..9e28740ba775 100644
--- a/crypto/cast6.c
+++ b/crypto/cast6.c
@@ -18,11 +18,13 @@
*/
+#include <asm/byteorder.h>
#include <linux/init.h>
#include <linux/crypto.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/types.h>
#define CAST6_BLOCK_SIZE 16
#define CAST6_MIN_KEY_SIZE 16
@@ -384,7 +386,7 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags)
{
int i;
u32 key[8];
- u8 p_key[32]; /* padded key */
+ __be32 p_key[8]; /* padded key */
struct cast6_ctx *c = (struct cast6_ctx *) ctx;
if (key_len < 16 || key_len > 32 || key_len % 4 != 0) {
@@ -395,14 +397,14 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags)
memset (p_key, 0, 32);
memcpy (p_key, in_key, key_len);
- key[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; /* A */
- key[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; /* B */
- key[2] = p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; /* C */
- key[3] = p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; /* D */
- key[4] = p_key[16] << 24 | p_key[17] << 16 | p_key[18] << 8 | p_key[19]; /* E */
- key[5] = p_key[20] << 24 | p_key[21] << 16 | p_key[22] << 8 | p_key[23]; /* F */
- key[6] = p_key[24] << 24 | p_key[25] << 16 | p_key[26] << 8 | p_key[27]; /* G */
- key[7] = p_key[28] << 24 | p_key[29] << 16 | p_key[30] << 8 | p_key[31]; /* H */
+ key[0] = be32_to_cpu(p_key[0]); /* A */
+ key[1] = be32_to_cpu(p_key[1]); /* B */
+ key[2] = be32_to_cpu(p_key[2]); /* C */
+ key[3] = be32_to_cpu(p_key[3]); /* D */
+ key[4] = be32_to_cpu(p_key[4]); /* E */
+ key[5] = be32_to_cpu(p_key[5]); /* F */
+ key[6] = be32_to_cpu(p_key[6]); /* G */
+ key[7] = be32_to_cpu(p_key[7]); /* H */
@@ -444,14 +446,16 @@ static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) {
static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
struct cast6_ctx * c = (struct cast6_ctx *)ctx;
+ const __be32 *src = (const __be32 *)inbuf;
+ __be32 *dst = (__be32 *)outbuf;
u32 block[4];
u32 * Km;
u8 * Kr;
- block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
- block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
- block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11];
- block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15];
+ block[0] = be32_to_cpu(src[0]);
+ block[1] = be32_to_cpu(src[1]);
+ block[2] = be32_to_cpu(src[2]);
+ block[3] = be32_to_cpu(src[3]);
Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km);
Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km);
@@ -465,35 +469,25 @@ static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km);
Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km);
Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km);
-
- outbuf[0] = (block[0] >> 24) & 0xff;
- outbuf[1] = (block[0] >> 16) & 0xff;
- outbuf[2] = (block[0] >> 8) & 0xff;
- outbuf[3] = block[0] & 0xff;
- outbuf[4] = (block[1] >> 24) & 0xff;
- outbuf[5] = (block[1] >> 16) & 0xff;
- outbuf[6] = (block[1] >> 8) & 0xff;
- outbuf[7] = block[1] & 0xff;
- outbuf[8] = (block[2] >> 24) & 0xff;
- outbuf[9] = (block[2] >> 16) & 0xff;
- outbuf[10] = (block[2] >> 8) & 0xff;
- outbuf[11] = block[2] & 0xff;
- outbuf[12] = (block[3] >> 24) & 0xff;
- outbuf[13] = (block[3] >> 16) & 0xff;
- outbuf[14] = (block[3] >> 8) & 0xff;
- outbuf[15] = block[3] & 0xff;
+
+ dst[0] = cpu_to_be32(block[0]);
+ dst[1] = cpu_to_be32(block[1]);
+ dst[2] = cpu_to_be32(block[2]);
+ dst[3] = cpu_to_be32(block[3]);
}
static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
struct cast6_ctx * c = (struct cast6_ctx *)ctx;
+ const __be32 *src = (const __be32 *)inbuf;
+ __be32 *dst = (__be32 *)outbuf;
u32 block[4];
u32 * Km;
u8 * Kr;
- block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
- block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
- block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11];
- block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15];
+ block[0] = be32_to_cpu(src[0]);
+ block[1] = be32_to_cpu(src[1]);
+ block[2] = be32_to_cpu(src[2]);
+ block[3] = be32_to_cpu(src[3]);
Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km);
Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km);
@@ -508,22 +502,10 @@ static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km);
Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km);
- outbuf[0] = (block[0] >> 24) & 0xff;
- outbuf[1] = (block[0] >> 16) & 0xff;
- outbuf[2] = (block[0] >> 8) & 0xff;
- outbuf[3] = block[0] & 0xff;
- outbuf[4] = (block[1] >> 24) & 0xff;
- outbuf[5] = (block[1] >> 16) & 0xff;
- outbuf[6] = (block[1] >> 8) & 0xff;
- outbuf[7] = block[1] & 0xff;
- outbuf[8] = (block[2] >> 24) & 0xff;
- outbuf[9] = (block[2] >> 16) & 0xff;
- outbuf[10] = (block[2] >> 8) & 0xff;
- outbuf[11] = block[2] & 0xff;
- outbuf[12] = (block[3] >> 24) & 0xff;
- outbuf[13] = (block[3] >> 16) & 0xff;
- outbuf[14] = (block[3] >> 8) & 0xff;
- outbuf[15] = block[3] & 0xff;
+ dst[0] = cpu_to_be32(block[0]);
+ dst[1] = cpu_to_be32(block[1]);
+ dst[2] = cpu_to_be32(block[2]);
+ dst[3] = cpu_to_be32(block[3]);
}
static struct crypto_alg alg = {
@@ -531,6 +513,7 @@ static struct crypto_alg alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = CAST6_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct cast6_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = {
diff --git a/crypto/cipher.c b/crypto/cipher.c
index dfd4bcfc5975..65bcea0cd17c 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -212,9 +212,10 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
struct crypto_tfm *tfm = desc->tfm;
void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
int bsize = crypto_tfm_alg_blocksize(tfm);
+ unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
- u8 stack[src == dst ? bsize : 0];
- u8 *buf = stack;
+ u8 stack[src == dst ? bsize + alignmask : 0];
+ u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
u8 **dst_p = src == dst ? &buf : &dst;
void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index 256956cd9377..953362423a5c 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/crypto.h>
#include <linux/crc32c.h>
+#include <linux/types.h>
#include <asm/byteorder.h>
#define CHKSUM_BLOCK_SIZE 32
diff --git a/crypto/des.c b/crypto/des.c
index a3c863dddded..7bb548653dc6 100644
--- a/crypto/des.c
+++ b/crypto/des.c
@@ -12,11 +12,13 @@
*
*/
+#include <asm/byteorder.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define DES_KEY_SIZE 8
#define DES_EXPKEY_WORDS 32
@@ -947,6 +949,7 @@ static struct crypto_alg des_alg = {
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct des_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(des_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = DES_KEY_SIZE,
diff --git a/crypto/internal.h b/crypto/internal.h
index 37aa652ce5ce..959e602909a6 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -2,6 +2,7 @@
* Cryptographic API.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -16,10 +17,15 @@
#include <linux/highmem.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/list.h>
#include <linux/kernel.h>
+#include <linux/rwsem.h>
#include <linux/slab.h>
#include <asm/kmap_types.h>
+extern struct list_head crypto_alg_list;
+extern struct rw_semaphore crypto_alg_sem;
+
extern enum km_type crypto_km_types[];
static inline enum km_type crypto_kmap_type(int out)
diff --git a/crypto/khazad.c b/crypto/khazad.c
index 738cb0dd1e7c..807f2bf4ea24 100644
--- a/crypto/khazad.c
+++ b/crypto/khazad.c
@@ -22,8 +22,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define KHAZAD_KEY_SIZE 16
#define KHAZAD_BLOCK_SIZE 8
@@ -755,8 +757,8 @@ static const u64 c[KHAZAD_ROUNDS + 1] = {
static int khazad_setkey(void *ctx_arg, const u8 *in_key,
unsigned int key_len, u32 *flags)
{
-
struct khazad_ctx *ctx = ctx_arg;
+ const __be64 *key = (const __be64 *)in_key;
int r;
const u64 *S = T7;
u64 K2, K1;
@@ -767,22 +769,8 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key,
return -EINVAL;
}
- K2 = ((u64)in_key[ 0] << 56) ^
- ((u64)in_key[ 1] << 48) ^
- ((u64)in_key[ 2] << 40) ^
- ((u64)in_key[ 3] << 32) ^
- ((u64)in_key[ 4] << 24) ^
- ((u64)in_key[ 5] << 16) ^
- ((u64)in_key[ 6] << 8) ^
- ((u64)in_key[ 7] );
- K1 = ((u64)in_key[ 8] << 56) ^
- ((u64)in_key[ 9] << 48) ^
- ((u64)in_key[10] << 40) ^
- ((u64)in_key[11] << 32) ^
- ((u64)in_key[12] << 24) ^
- ((u64)in_key[13] << 16) ^
- ((u64)in_key[14] << 8) ^
- ((u64)in_key[15] );
+ K2 = be64_to_cpu(key[0]);
+ K1 = be64_to_cpu(key[1]);
/* setup the encrypt key */
for (r = 0; r <= KHAZAD_ROUNDS; r++) {
@@ -820,19 +808,12 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key,
static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1],
u8 *ciphertext, const u8 *plaintext)
{
-
+ const __be64 *src = (const __be64 *)plaintext;
+ __be64 *dst = (__be64 *)ciphertext;
int r;
u64 state;
- state = ((u64)plaintext[0] << 56) ^
- ((u64)plaintext[1] << 48) ^
- ((u64)plaintext[2] << 40) ^
- ((u64)plaintext[3] << 32) ^
- ((u64)plaintext[4] << 24) ^
- ((u64)plaintext[5] << 16) ^
- ((u64)plaintext[6] << 8) ^
- ((u64)plaintext[7] ) ^
- roundKey[0];
+ state = be64_to_cpu(*src) ^ roundKey[0];
for (r = 1; r < KHAZAD_ROUNDS; r++) {
state = T0[(int)(state >> 56) ] ^
@@ -856,15 +837,7 @@ static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1],
(T7[(int)(state ) & 0xff] & 0x00000000000000ffULL) ^
roundKey[KHAZAD_ROUNDS];
- ciphertext[0] = (u8)(state >> 56);
- ciphertext[1] = (u8)(state >> 48);
- ciphertext[2] = (u8)(state >> 40);
- ciphertext[3] = (u8)(state >> 32);
- ciphertext[4] = (u8)(state >> 24);
- ciphertext[5] = (u8)(state >> 16);
- ciphertext[6] = (u8)(state >> 8);
- ciphertext[7] = (u8)(state );
-
+ *dst = cpu_to_be64(state);
}
static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
@@ -884,6 +857,7 @@ static struct crypto_alg khazad_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = KHAZAD_BLOCK_SIZE,
.cra_ctxsize = sizeof (struct khazad_ctx),
+ .cra_alignmask = 7,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(khazad_alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/md4.c b/crypto/md4.c
index bef6a9e5ac9b..a2d6df5c0f8c 100644
--- a/crypto/md4.c
+++ b/crypto/md4.c
@@ -24,6 +24,7 @@
#include <linux/crypto.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <asm/byteorder.h>
#define MD4_DIGEST_SIZE 16
diff --git a/crypto/md5.c b/crypto/md5.c
index 1ed45f9c263e..7f041aef5da2 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#include <asm/byteorder.h>
#define MD5_DIGEST_SIZE 16
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index a470bcb3693e..4f6ab23e14ad 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -10,10 +10,12 @@
* published by the Free Software Foundation.
*/
+#include <asm/byteorder.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/crypto.h>
+#include <linux/types.h>
struct michael_mic_ctx {
@@ -43,21 +45,6 @@ do { \
} while (0)
-static inline u32 get_le32(const u8 *p)
-{
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-
-static inline void put_le32(u8 *p, u32 v)
-{
- p[0] = v;
- p[1] = v >> 8;
- p[2] = v >> 16;
- p[3] = v >> 24;
-}
-
-
static void michael_init(void *ctx)
{
struct michael_mic_ctx *mctx = ctx;
@@ -68,6 +55,7 @@ static void michael_init(void *ctx)
static void michael_update(void *ctx, const u8 *data, unsigned int len)
{
struct michael_mic_ctx *mctx = ctx;
+ const __le32 *src;
if (mctx->pending_len) {
int flen = 4 - mctx->pending_len;
@@ -81,21 +69,23 @@ static void michael_update(void *ctx, const u8 *data, unsigned int len)
if (mctx->pending_len < 4)
return;
- mctx->l ^= get_le32(mctx->pending);
+ src = (const __le32 *)mctx->pending;
+ mctx->l ^= le32_to_cpup(src);
michael_block(mctx->l, mctx->r);
mctx->pending_len = 0;
}
+ src = (const __le32 *)data;
+
while (len >= 4) {
- mctx->l ^= get_le32(data);
+ mctx->l ^= le32_to_cpup(src++);
michael_block(mctx->l, mctx->r);
- data += 4;
len -= 4;
}
if (len > 0) {
mctx->pending_len = len;
- memcpy(mctx->pending, data, len);
+ memcpy(mctx->pending, src, len);
}
}
@@ -104,6 +94,7 @@ static void michael_final(void *ctx, u8 *out)
{
struct michael_mic_ctx *mctx = ctx;
u8 *data = mctx->pending;
+ __le32 *dst = (__le32 *)out;
/* Last block and padding (0x5a, 4..7 x 0) */
switch (mctx->pending_len) {
@@ -125,8 +116,8 @@ static void michael_final(void *ctx, u8 *out)
/* l ^= 0; */
michael_block(mctx->l, mctx->r);
- put_le32(out, mctx->l);
- put_le32(out + 4, mctx->r);
+ dst[0] = cpu_to_le32(mctx->l);
+ dst[1] = cpu_to_le32(mctx->r);
}
@@ -134,13 +125,16 @@ static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
u32 *flags)
{
struct michael_mic_ctx *mctx = ctx;
+ const __le32 *data = (const __le32 *)key;
+
if (keylen != 8) {
if (flags)
*flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
- mctx->l = get_le32(key);
- mctx->r = get_le32(key + 4);
+
+ mctx->l = le32_to_cpu(data[0]);
+ mctx->r = le32_to_cpu(data[1]);
return 0;
}
diff --git a/crypto/proc.c b/crypto/proc.c
index 630ba91c08f1..c0a5dd7ce2cc 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -4,6 +4,7 @@
* Procfs information.
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -18,9 +19,6 @@
#include <linux/seq_file.h>
#include "internal.h"
-extern struct list_head crypto_alg_list;
-extern struct rw_semaphore crypto_alg_sem;
-
static void *c_start(struct seq_file *m, loff_t *pos)
{
struct list_head *v;
@@ -53,7 +51,9 @@ static int c_show(struct seq_file *m, void *p)
struct crypto_alg *alg = (struct crypto_alg *)p;
seq_printf(m, "name : %s\n", alg->cra_name);
+ seq_printf(m, "driver : %s\n", alg->cra_driver_name);
seq_printf(m, "module : %s\n", module_name(alg->cra_module));
+ seq_printf(m, "priority : %d\n", alg->cra_priority);
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_CIPHER:
diff --git a/crypto/serpent.c b/crypto/serpent.c
index 3cf2c5067eea..52ad1a492620 100644
--- a/crypto/serpent.c
+++ b/crypto/serpent.c
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <asm/byteorder.h>
#include <linux/crypto.h>
+#include <linux/types.h>
/* Key is padded to the maximum of 256 bits before round key generation.
* Any key length <= 256 bits (32 bytes) is allowed by the algorithm.
@@ -552,6 +553,7 @@ static struct crypto_alg tnepres_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = SERPENT_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct serpent_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(serpent_alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/sha1.c b/crypto/sha1.c
index 4016f3b8ce9b..21571ed35b7e 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/crypto.h>
#include <linux/cryptohash.h>
+#include <linux/types.h>
#include <asm/scatterlist.h>
#include <asm/byteorder.h>
@@ -48,23 +49,33 @@ static void sha1_init(void *ctx)
static void sha1_update(void *ctx, const u8 *data, unsigned int len)
{
struct sha1_ctx *sctx = ctx;
- unsigned int i, j;
- u32 temp[SHA_WORKSPACE_WORDS];
+ unsigned int partial, done;
+ const u8 *src;
- j = (sctx->count >> 3) & 0x3f;
- sctx->count += len << 3;
+ partial = sctx->count & 0x3f;
+ sctx->count += len;
+ done = 0;
+ src = data;
- if ((j + len) > 63) {
- memcpy(&sctx->buffer[j], data, (i = 64-j));
- sha_transform(sctx->state, sctx->buffer, temp);
- for ( ; i + 63 < len; i += 64) {
- sha_transform(sctx->state, &data[i], temp);
+ if ((partial + len) > 63) {
+ u32 temp[SHA_WORKSPACE_WORDS];
+
+ if (partial) {
+ done = -partial;
+ memcpy(sctx->buffer + partial, data, done + 64);
+ src = sctx->buffer;
}
- j = 0;
+
+ do {
+ sha_transform(sctx->state, src, temp);
+ done += 64;
+ src = data + done;
+ } while (done + 63 < len);
+
+ memset(temp, 0, sizeof(temp));
+ partial = 0;
}
- else i = 0;
- memset(temp, 0, sizeof(temp));
- memcpy(&sctx->buffer[j], &data[i], len - i);
+ memcpy(sctx->buffer + partial, src, len - done);
}
@@ -72,37 +83,24 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len)
static void sha1_final(void* ctx, u8 *out)
{
struct sha1_ctx *sctx = ctx;
- u32 i, j, index, padlen;
- u64 t;
- u8 bits[8] = { 0, };
+ __be32 *dst = (__be32 *)out;
+ u32 i, index, padlen;
+ __be64 bits;
static const u8 padding[64] = { 0x80, };
- t = sctx->count;
- bits[7] = 0xff & t; t>>=8;
- bits[6] = 0xff & t; t>>=8;
- bits[5] = 0xff & t; t>>=8;
- bits[4] = 0xff & t; t>>=8;
- bits[3] = 0xff & t; t>>=8;
- bits[2] = 0xff & t; t>>=8;
- bits[1] = 0xff & t; t>>=8;
- bits[0] = 0xff & t;
+ bits = cpu_to_be64(sctx->count << 3);
/* Pad out to 56 mod 64 */
- index = (sctx->count >> 3) & 0x3f;
+ index = sctx->count & 0x3f;
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
sha1_update(sctx, padding, padlen);
/* Append length */
- sha1_update(sctx, bits, sizeof bits);
+ sha1_update(sctx, (const u8 *)&bits, sizeof(bits));
/* Store state in digest */
- for (i = j = 0; i < 5; i++, j += 4) {
- u32 t2 = sctx->state[i];
- out[j+3] = t2 & 0xff; t2>>=8;
- out[j+2] = t2 & 0xff; t2>>=8;
- out[j+1] = t2 & 0xff; t2>>=8;
- out[j ] = t2 & 0xff;
- }
+ for (i = 0; i < 5; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
/* Wipe context */
memset(sctx, 0, sizeof *sctx);
diff --git a/crypto/sha256.c b/crypto/sha256.c
index c78da50a9b7a..9d5ef674d6a9 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#include <asm/scatterlist.h>
#include <asm/byteorder.h>
@@ -279,22 +280,15 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len)
static void sha256_final(void* ctx, u8 *out)
{
struct sha256_ctx *sctx = ctx;
- u8 bits[8];
- unsigned int index, pad_len, t;
- int i, j;
+ __be32 *dst = (__be32 *)out;
+ __be32 bits[2];
+ unsigned int index, pad_len;
+ int i;
static const u8 padding[64] = { 0x80, };
/* Save number of bits */
- t = sctx->count[0];
- bits[7] = t; t >>= 8;
- bits[6] = t; t >>= 8;
- bits[5] = t; t >>= 8;
- bits[4] = t;
- t = sctx->count[1];
- bits[3] = t; t >>= 8;
- bits[2] = t; t >>= 8;
- bits[1] = t; t >>= 8;
- bits[0] = t;
+ bits[1] = cpu_to_be32(sctx->count[0]);
+ bits[0] = cpu_to_be32(sctx->count[1]);
/* Pad out to 56 mod 64. */
index = (sctx->count[0] >> 3) & 0x3f;
@@ -302,16 +296,11 @@ static void sha256_final(void* ctx, u8 *out)
sha256_update(sctx, padding, pad_len);
/* Append length (before padding) */
- sha256_update(sctx, bits, 8);
+ sha256_update(sctx, (const u8 *)bits, sizeof(bits));
/* Store state in digest */
- for (i = j = 0; i < 8; i++, j += 4) {
- t = sctx->state[i];
- out[j+3] = t; t >>= 8;
- out[j+2] = t; t >>= 8;
- out[j+1] = t; t >>= 8;
- out[j ] = t;
- }
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be32(sctx->state[i]);
/* Zeroize sensitive information. */
memset(sctx, 0, sizeof(*sctx));
diff --git a/crypto/sha512.c b/crypto/sha512.c
index c663438322e9..3e6e9392310c 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#include <asm/scatterlist.h>
#include <asm/byteorder.h>
@@ -235,39 +236,17 @@ static void
sha512_final(void *ctx, u8 *hash)
{
struct sha512_ctx *sctx = ctx;
-
static u8 padding[128] = { 0x80, };
-
- u32 t;
- u64 t2;
- u8 bits[128];
+ __be64 *dst = (__be64 *)hash;
+ __be32 bits[4];
unsigned int index, pad_len;
- int i, j;
-
- index = pad_len = t = i = j = 0;
- t2 = 0;
+ int i;
/* Save number of bits */
- t = sctx->count[0];
- bits[15] = t; t>>=8;
- bits[14] = t; t>>=8;
- bits[13] = t; t>>=8;
- bits[12] = t;
- t = sctx->count[1];
- bits[11] = t; t>>=8;
- bits[10] = t; t>>=8;
- bits[9 ] = t; t>>=8;
- bits[8 ] = t;
- t = sctx->count[2];
- bits[7 ] = t; t>>=8;
- bits[6 ] = t; t>>=8;
- bits[5 ] = t; t>>=8;
- bits[4 ] = t;
- t = sctx->count[3];
- bits[3 ] = t; t>>=8;
- bits[2 ] = t; t>>=8;
- bits[1 ] = t; t>>=8;
- bits[0 ] = t;
+ bits[3] = cpu_to_be32(sctx->count[0]);
+ bits[2] = cpu_to_be32(sctx->count[1]);
+ bits[1] = cpu_to_be32(sctx->count[2]);
+ bits[0] = cpu_to_be32(sctx->count[3]);
/* Pad out to 112 mod 128. */
index = (sctx->count[0] >> 3) & 0x7f;
@@ -275,21 +254,12 @@ sha512_final(void *ctx, u8 *hash)
sha512_update(sctx, padding, pad_len);
/* Append length (before padding) */
- sha512_update(sctx, bits, 16);
+ sha512_update(sctx, (const u8 *)bits, sizeof(bits));
/* Store state in digest */
- for (i = j = 0; i < 8; i++, j += 8) {
- t2 = sctx->state[i];
- hash[j+7] = (char)t2 & 0xff; t2>>=8;
- hash[j+6] = (char)t2 & 0xff; t2>>=8;
- hash[j+5] = (char)t2 & 0xff; t2>>=8;
- hash[j+4] = (char)t2 & 0xff; t2>>=8;
- hash[j+3] = (char)t2 & 0xff; t2>>=8;
- hash[j+2] = (char)t2 & 0xff; t2>>=8;
- hash[j+1] = (char)t2 & 0xff; t2>>=8;
- hash[j ] = (char)t2 & 0xff;
- }
-
+ for (i = 0; i < 8; i++)
+ dst[i] = cpu_to_be64(sctx->state[i]);
+
/* Zeroize sensitive information. */
memset(sctx, 0, sizeof(struct sha512_ctx));
}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 53f4ee804bdb..49e344f00806 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -805,6 +805,8 @@ static void do_test(void)
//AES
test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
+ test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS);
+ test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS);
//CAST5
test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS);
@@ -910,6 +912,8 @@ static void do_test(void)
case 10:
test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
+ test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS);
+ test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS);
break;
case 11:
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 522ffd4b6f43..733d07ed75e9 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -1836,6 +1836,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
*/
#define AES_ENC_TEST_VECTORS 3
#define AES_DEC_TEST_VECTORS 3
+#define AES_CBC_ENC_TEST_VECTORS 2
+#define AES_CBC_DEC_TEST_VECTORS 2
static struct cipher_testvec aes_enc_tv_template[] = {
{ /* From FIPS-197 */
@@ -1911,6 +1913,68 @@ static struct cipher_testvec aes_dec_tv_template[] = {
},
};
+static struct cipher_testvec aes_cbc_enc_tv_template[] = {
+ { /* From RFC 3602 */
+ .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+ 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+ .klen = 16,
+ .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+ 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+ .input = { "Single block msg" },
+ .ilen = 16,
+ .result = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+ 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
+ .rlen = 16,
+ }, {
+ .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+ 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+ .klen = 16,
+ .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+ 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+ .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .ilen = 32,
+ .result = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+ 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+ 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+ 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
+ .rlen = 32,
+ },
+};
+
+static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ { /* From RFC 3602 */
+ .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b,
+ 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 },
+ .klen = 16,
+ .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30,
+ 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 },
+ .input = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8,
+ 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a },
+ .ilen = 16,
+ .result = { "Single block msg" },
+ .rlen = 16,
+ }, {
+ .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0,
+ 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a },
+ .klen = 16,
+ .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28,
+ 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 },
+ .input = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a,
+ 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+ 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+ 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
+ .ilen = 32,
+ .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ .rlen = 32,
+ },
+};
+
/* Cast5 test vectors from RFC 2144 */
#define CAST5_ENC_TEST_VECTORS 3
#define CAST5_DEC_TEST_VECTORS 3
diff --git a/crypto/tea.c b/crypto/tea.c
index 5924efdd3a16..a6a02b30e470 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -22,8 +22,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define TEA_KEY_SIZE 16
#define TEA_BLOCK_SIZE 8
@@ -35,9 +37,6 @@
#define XTEA_ROUNDS 32
#define XTEA_DELTA 0x9e3779b9
-#define u32_in(x) le32_to_cpu(*(const __le32 *)(x))
-#define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from))
-
struct tea_ctx {
u32 KEY[4];
};
@@ -49,8 +48,8 @@ struct xtea_ctx {
static int tea_setkey(void *ctx_arg, const u8 *in_key,
unsigned int key_len, u32 *flags)
{
-
struct tea_ctx *ctx = ctx_arg;
+ const __le32 *key = (const __le32 *)in_key;
if (key_len != 16)
{
@@ -58,10 +57,10 @@ static int tea_setkey(void *ctx_arg, const u8 *in_key,
return -EINVAL;
}
- ctx->KEY[0] = u32_in (in_key);
- ctx->KEY[1] = u32_in (in_key + 4);
- ctx->KEY[2] = u32_in (in_key + 8);
- ctx->KEY[3] = u32_in (in_key + 12);
+ ctx->KEY[0] = le32_to_cpu(key[0]);
+ ctx->KEY[1] = le32_to_cpu(key[1]);
+ ctx->KEY[2] = le32_to_cpu(key[2]);
+ ctx->KEY[3] = le32_to_cpu(key[3]);
return 0;
@@ -73,9 +72,11 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
u32 k0, k1, k2, k3;
struct tea_ctx *ctx = ctx_arg;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
k0 = ctx->KEY[0];
k1 = ctx->KEY[1];
@@ -90,19 +91,20 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(z);
}
static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
{
u32 y, z, n, sum;
u32 k0, k1, k2, k3;
-
struct tea_ctx *ctx = ctx_arg;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
k0 = ctx->KEY[0];
k1 = ctx->KEY[1];
@@ -119,16 +121,15 @@ static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
sum -= TEA_DELTA;
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
-
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(z);
}
static int xtea_setkey(void *ctx_arg, const u8 *in_key,
unsigned int key_len, u32 *flags)
{
-
struct xtea_ctx *ctx = ctx_arg;
+ const __le32 *key = (const __le32 *)in_key;
if (key_len != 16)
{
@@ -136,10 +137,10 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key,
return -EINVAL;
}
- ctx->KEY[0] = u32_in (in_key);
- ctx->KEY[1] = u32_in (in_key + 4);
- ctx->KEY[2] = u32_in (in_key + 8);
- ctx->KEY[3] = u32_in (in_key + 12);
+ ctx->KEY[0] = le32_to_cpu(key[0]);
+ ctx->KEY[1] = le32_to_cpu(key[1]);
+ ctx->KEY[2] = le32_to_cpu(key[2]);
+ ctx->KEY[3] = le32_to_cpu(key[3]);
return 0;
@@ -147,14 +148,15 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key,
static void xtea_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;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
while (sum != limit) {
y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]);
@@ -162,19 +164,19 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]);
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
-
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(z);
}
static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
{
-
u32 y, z, sum;
struct tea_ctx *ctx = ctx_arg;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
sum = XTEA_DELTA * XTEA_ROUNDS;
@@ -184,22 +186,22 @@ static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]);
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
-
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(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;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
while (sum != limit) {
y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3];
@@ -207,19 +209,19 @@ static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3];
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
-
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(z);
}
static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
{
-
u32 y, z, sum;
struct tea_ctx *ctx = ctx_arg;
+ const __le32 *in = (const __le32 *)src;
+ __le32 *out = (__le32 *)dst;
- y = u32_in (src);
- z = u32_in (src + 4);
+ y = le32_to_cpu(in[0]);
+ z = le32_to_cpu(in[1]);
sum = XTEA_DELTA * XTEA_ROUNDS;
@@ -229,9 +231,8 @@ static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
}
- u32_out (dst, y);
- u32_out (dst + 4, z);
-
+ out[0] = cpu_to_le32(y);
+ out[1] = cpu_to_le32(z);
}
static struct crypto_alg tea_alg = {
@@ -239,6 +240,7 @@ static struct crypto_alg tea_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = TEA_BLOCK_SIZE,
.cra_ctxsize = sizeof (struct tea_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(tea_alg.cra_list),
.cra_u = { .cipher = {
@@ -254,6 +256,7 @@ static struct crypto_alg xtea_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = XTEA_BLOCK_SIZE,
.cra_ctxsize = sizeof (struct xtea_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(xtea_alg.cra_list),
.cra_u = { .cipher = {
@@ -269,6 +272,7 @@ static struct crypto_alg xeta_alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = XTEA_BLOCK_SIZE,
.cra_ctxsize = sizeof (struct xtea_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(xtea_alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index f0a45cf716d0..2d8e44f6fbe9 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -24,8 +24,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define TGR192_DIGEST_SIZE 24
#define TGR160_DIGEST_SIZE 20
@@ -467,18 +469,10 @@ static void tgr192_transform(struct tgr192_ctx *tctx, const u8 * data)
u64 a, b, c, aa, bb, cc;
u64 x[8];
int i;
- const u8 *ptr = data;
-
- for (i = 0; i < 8; i++, ptr += 8) {
- x[i] = (((u64)ptr[7] ) << 56) ^
- (((u64)ptr[6] & 0xffL) << 48) ^
- (((u64)ptr[5] & 0xffL) << 40) ^
- (((u64)ptr[4] & 0xffL) << 32) ^
- (((u64)ptr[3] & 0xffL) << 24) ^
- (((u64)ptr[2] & 0xffL) << 16) ^
- (((u64)ptr[1] & 0xffL) << 8) ^
- (((u64)ptr[0] & 0xffL) );
- }
+ const __le64 *ptr = (const __le64 *)data;
+
+ for (i = 0; i < 8; i++)
+ x[i] = le64_to_cpu(ptr[i]);
/* save */
a = aa = tctx->a;
@@ -558,9 +552,10 @@ static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len)
static void tgr192_final(void *ctx, u8 * out)
{
struct tgr192_ctx *tctx = ctx;
+ __be64 *dst = (__be64 *)out;
+ __be64 *be64p;
+ __le32 *le32p;
u32 t, msb, lsb;
- u8 *p;
- int i, j;
tgr192_update(tctx, NULL, 0); /* flush */ ;
@@ -594,41 +589,16 @@ static void tgr192_final(void *ctx, u8 * out)
memset(tctx->hash, 0, 56); /* fill next block with zeroes */
}
/* append the 64 bit count */
- tctx->hash[56] = lsb;
- tctx->hash[57] = lsb >> 8;
- tctx->hash[58] = lsb >> 16;
- tctx->hash[59] = lsb >> 24;
- tctx->hash[60] = msb;
- tctx->hash[61] = msb >> 8;
- tctx->hash[62] = msb >> 16;
- tctx->hash[63] = msb >> 24;
+ le32p = (__le32 *)&tctx->hash[56];
+ le32p[0] = cpu_to_le32(lsb);
+ le32p[1] = cpu_to_le32(msb);
+
tgr192_transform(tctx, tctx->hash);
- p = tctx->hash;
- *p++ = tctx->a >> 56; *p++ = tctx->a >> 48; *p++ = tctx->a >> 40;
- *p++ = tctx->a >> 32; *p++ = tctx->a >> 24; *p++ = tctx->a >> 16;
- *p++ = tctx->a >> 8; *p++ = tctx->a;\
- *p++ = tctx->b >> 56; *p++ = tctx->b >> 48; *p++ = tctx->b >> 40;
- *p++ = tctx->b >> 32; *p++ = tctx->b >> 24; *p++ = tctx->b >> 16;
- *p++ = tctx->b >> 8; *p++ = tctx->b;
- *p++ = tctx->c >> 56; *p++ = tctx->c >> 48; *p++ = tctx->c >> 40;
- *p++ = tctx->c >> 32; *p++ = tctx->c >> 24; *p++ = tctx->c >> 16;
- *p++ = tctx->c >> 8; *p++ = tctx->c;
-
-
- /* unpack the hash */
- j = 7;
- for (i = 0; i < 8; i++) {
- out[j--] = (tctx->a >> 8 * i) & 0xff;
- }
- j = 15;
- for (i = 0; i < 8; i++) {
- out[j--] = (tctx->b >> 8 * i) & 0xff;
- }
- j = 23;
- for (i = 0; i < 8; i++) {
- out[j--] = (tctx->c >> 8 * i) & 0xff;
- }
+ be64p = (__be64 *)tctx->hash;
+ dst[0] = be64p[0] = cpu_to_be64(tctx->a);
+ dst[1] = be64p[1] = cpu_to_be64(tctx->b);
+ dst[2] = be64p[2] = cpu_to_be64(tctx->c);
}
static void tgr160_final(void *ctx, u8 * out)
diff --git a/crypto/twofish.c b/crypto/twofish.c
index 4efff8cf9958..a26d885486fb 100644
--- a/crypto/twofish.c
+++ b/crypto/twofish.c
@@ -37,6 +37,8 @@
* Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
* Third Edition.
*/
+
+#include <asm/byteorder.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -621,13 +623,11 @@ static const u8 calc_sb_tbl[512] = {
* whitening subkey number m. */
#define INPACK(n, x, m) \
- x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \
- ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m]
+ x = le32_to_cpu(src[n]) ^ ctx->w[m]
#define OUTUNPACK(n, x, m) \
x ^= ctx->w[m]; \
- out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \
- out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24
+ dst[n] = cpu_to_le32(x)
#define TF_MIN_KEY_SIZE 16
#define TF_MAX_KEY_SIZE 32
@@ -804,6 +804,8 @@ static int twofish_setkey(void *cx, const u8 *key,
static void twofish_encrypt(void *cx, u8 *out, const u8 *in)
{
struct twofish_ctx *ctx = cx;
+ const __le32 *src = (const __le32 *)in;
+ __le32 *dst = (__le32 *)out;
/* The four 32-bit chunks of the text. */
u32 a, b, c, d;
@@ -839,6 +841,8 @@ static void twofish_encrypt(void *cx, u8 *out, const u8 *in)
static void twofish_decrypt(void *cx, u8 *out, const u8 *in)
{
struct twofish_ctx *ctx = cx;
+ const __le32 *src = (const __le32 *)in;
+ __le32 *dst = (__le32 *)out;
/* The four 32-bit chunks of the text. */
u32 a, b, c, d;
@@ -875,6 +879,7 @@ static struct crypto_alg alg = {
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = TF_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct twofish_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .cipher = {
diff --git a/crypto/wp512.c b/crypto/wp512.c
index fd6e20e1f291..b226a126cfae 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -22,8 +22,10 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/types.h>
#define WP512_DIGEST_SIZE 64
#define WP384_DIGEST_SIZE 48
@@ -778,19 +780,10 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) {
u64 block[8]; /* mu(buffer) */
u64 state[8]; /* the cipher state */
u64 L[8];
- u8 *buffer = wctx->buffer;
+ const __be64 *buffer = (const __be64 *)wctx->buffer;
- for (i = 0; i < 8; i++, buffer += 8) {
- block[i] =
- (((u64)buffer[0] ) << 56) ^
- (((u64)buffer[1] & 0xffL) << 48) ^
- (((u64)buffer[2] & 0xffL) << 40) ^
- (((u64)buffer[3] & 0xffL) << 32) ^
- (((u64)buffer[4] & 0xffL) << 24) ^
- (((u64)buffer[5] & 0xffL) << 16) ^
- (((u64)buffer[6] & 0xffL) << 8) ^
- (((u64)buffer[7] & 0xffL) );
- }
+ for (i = 0; i < 8; i++)
+ block[i] = be64_to_cpu(buffer[i]);
state[0] = block[0] ^ (K[0] = wctx->hash[0]);
state[1] = block[1] ^ (K[1] = wctx->hash[1]);
@@ -1069,7 +1062,7 @@ static void wp512_final(void *ctx, u8 *out)
u8 *bitLength = wctx->bitLength;
int bufferBits = wctx->bufferBits;
int bufferPos = wctx->bufferPos;
- u8 *digest = out;
+ __be64 *digest = (__be64 *)out;
buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
bufferPos++;
@@ -1088,17 +1081,8 @@ static void wp512_final(void *ctx, u8 *out)
memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES],
bitLength, WP512_LENGTHBYTES);
wp512_process_buffer(wctx);
- for (i = 0; i < WP512_DIGEST_SIZE/8; i++) {
- digest[0] = (u8)(wctx->hash[i] >> 56);
- digest[1] = (u8)(wctx->hash[i] >> 48);
- digest[2] = (u8)(wctx->hash[i] >> 40);
- digest[3] = (u8)(wctx->hash[i] >> 32);
- digest[4] = (u8)(wctx->hash[i] >> 24);
- digest[5] = (u8)(wctx->hash[i] >> 16);
- digest[6] = (u8)(wctx->hash[i] >> 8);
- digest[7] = (u8)(wctx->hash[i] );
- digest += 8;
- }
+ for (i = 0; i < WP512_DIGEST_SIZE/8; i++)
+ digest[i] = cpu_to_be64(wctx->hash[i]);
wctx->bufferBits = bufferBits;
wctx->bufferPos = bufferPos;
}
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 48f446d3c671..bddf431bbb72 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -44,6 +44,8 @@ source "drivers/char/Kconfig"
source "drivers/i2c/Kconfig"
+source "drivers/spi/Kconfig"
+
source "drivers/w1/Kconfig"
source "drivers/hwmon/Kconfig"
@@ -66,4 +68,6 @@ source "drivers/infiniband/Kconfig"
source "drivers/sn/Kconfig"
+source "drivers/edac/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ea410b6b7644..619dd964c51c 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -13,6 +13,7 @@ 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/
+obj-$(CONFIG_ARM_AMBA) += amba/
# char/ comes before serial/ etc so that the VT console is the boot-time
# default.
@@ -40,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/
obj-$(CONFIG_IEEE1394) += ieee1394/
obj-y += cdrom/
obj-$(CONFIG_MTD) += mtd/
+obj-$(CONFIG_SPI) += spi/
obj-$(CONFIG_PCCARD) += pcmcia/
obj-$(CONFIG_DIO) += dio/
obj-$(CONFIG_SBUS) += sbus/
@@ -61,6 +63,7 @@ obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_ISDN) += isdn/
+obj-$(CONFIG_EDAC) += edac/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 4b65f74d66b1..ce074f6f3369 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock);
#define MAJOR_NR MFM_ACORN_MAJOR
#define QUEUE (mfm_queue)
#define CURRENT elv_next_request(mfm_queue)
-/*
- * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
- */
-#ifndef HDIO_GETGEO
-#define HDIO_GETGEO 0x301
-struct hd_geometry {
- unsigned char heads;
- unsigned char sectors;
- unsigned short cylinders;
- unsigned long start;
-};
-#endif
-
/*
* Configuration section
@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void)
* The 'front' end of the mfm driver follows...
*/
-static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
+static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct mfm_info *p = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry *geo = (struct hd_geometry *) arg;
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- if (!arg)
- return -EINVAL;
- if (put_user (p->heads, &geo->heads))
- return -EFAULT;
- if (put_user (p->sectors, &geo->sectors))
- return -EFAULT;
- if (put_user (p->cylinders, &geo->cylinders))
- return -EFAULT;
- if (put_user (get_start_sect(inode->i_bdev), &geo->start))
- return -EFAULT;
+ struct mfm_info *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->heads;
+ geo->sectors = p->sectors;
+ geo->cylinders = p->cylinders;
return 0;
}
@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
static struct block_device_operations mfm_fops =
{
.owner = THIS_MODULE,
- .ioctl = mfm_ioctl,
+ .getgeo = mfm_getgeo,
};
/*
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index c22bb9dca1ec..c26c08b36829 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -12,6 +12,7 @@
* On Acorn machines, the following i2c devices are on the bus:
* - PCF8583 real time clock & static RAM
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/time.h>
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index e26f007a1417..9b49f316ae92 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -257,9 +257,10 @@ pcf8583_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver pcf8583_driver = {
- .name = "PCF8583",
+ .driver = {
+ .name = "PCF8583",
+ },
.id = I2C_DRIVERID_PCF8583,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8583_probe,
.detach_client = pcf8583_detach,
.command = pcf8583_command
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index fce21c257523..6d61945260a8 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -168,7 +168,6 @@ config ACPI_NUMA
config ACPI_ASUS
tristate "ASUS/Medion Laptop Extras"
depends on X86
- 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 +208,6 @@ config ACPI_IBM
config ACPI_TOSHIBA
tristate "Toshiba Laptop Extras"
depends on X86
- default y
---help---
This driver adds support for access to certain system settings
on "legacy free" Toshiba laptops. These laptops can be recognized by
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 27ec12c1fab0..b69a8cad82b7 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -172,21 +172,21 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle);
if (!result)
- kobject_hotplug(&device->kobj,
- KOBJ_ONLINE);
+ kobject_uevent(&device->kobj,
+ KOBJ_ONLINE);
else
printk("Failed to add container\n");
}
} else {
if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
}
}
break;
case ACPI_NOTIFY_EJECT_REQUEST:
if (!acpi_bus_get_device(handle, &device) && device) {
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
}
break;
default:
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7e1a445955bc..3758b558d2b5 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -153,7 +153,7 @@ static int acpi_ec_polling_mode = EC_POLLING;
Transaction Management
-------------------------------------------------------------------------- */
-static inline u32 acpi_ec_read_status(union acpi_ec *ec)
+static u32 acpi_ec_read_status(union acpi_ec *ec)
{
u32 status = 0;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index e3cd0b16031a..20c9a37643c7 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -204,11 +204,13 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
return AE_OK;
}
+EXPORT_SYMBOL_GPL(acpi_os_map_memory);
void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
{
iounmap(virt);
}
+EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
#ifdef ACPI_FUTURE_USAGE
acpi_status
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 09567c2edcfb..e567c03b238e 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -361,8 +361,7 @@ acpi_pci_irq_derive(struct pci_dev *dev,
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);
+ bridge_pin = bridge->pin;
if (!bridge_pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
@@ -412,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
if (!dev)
return_VALUE(-EINVAL);
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
@@ -503,7 +502,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
if (!dev || !dev->bus)
return_VOID;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin)
return_VOID;
pin--;
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 0c561c571f29..1278aca96fe3 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -748,7 +748,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
return_VALUE(-ENODEV);
if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
- kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
+ kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
}
return_VALUE(0);
}
@@ -788,13 +788,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
}
if (pr->id >= 0 && (pr->id < NR_CPUS)) {
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
break;
}
result = acpi_processor_start(device);
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
- kobject_hotplug(&device->kobj, KOBJ_ONLINE);
+ kobject_uevent(&device->kobj, KOBJ_ONLINE);
} else {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Device [%s] failed to start\n",
@@ -818,7 +818,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
}
if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
- kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&device->kobj, KOBJ_OFFLINE);
break;
default:
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 807b0df308f1..cc049338e418 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -843,6 +843,15 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
unsigned int i;
unsigned int working = 0;
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ struct cpuinfo_x86 *c = cpu_data + pr->id;
+ cpumask_t mask = cpumask_of_cpu(pr->id);
+
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
+ }
+#endif
+
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) {
struct acpi_processor_cx *cx = &pr->power.states[i];
@@ -857,6 +866,12 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
case ACPI_STATE_C3:
acpi_processor_power_verify_c3(pr, cx);
+#ifdef ARCH_APICTIMER_STOPS_ON_C3
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
+ on_each_cpu(switch_APIC_timer_to_ipi,
+ &mask, 1, 1);
+ }
+#endif
break;
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 31218e1d2a18..3b26a7104363 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -78,7 +78,7 @@ static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release,
};
-static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+static int namespace_uevent(struct kset *kset, struct kobject *kobj,
char **envp, int num_envp, char *buffer,
int buffer_size)
{
@@ -89,8 +89,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
if (!dev->driver)
return 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "PHYSDEVDRIVER=%s", dev->driver->name))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "PHYSDEVDRIVER=%s", dev->driver->name))
return -ENOMEM;
envp[i] = NULL;
@@ -98,8 +98,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
return 0;
}
-static struct kset_hotplug_ops namespace_hotplug_ops = {
- .hotplug = &namespace_hotplug,
+static struct kset_uevent_ops namespace_uevent_ops = {
+ .uevent = &namespace_uevent,
};
static struct kset acpi_namespace_kset = {
@@ -108,7 +108,7 @@ static struct kset acpi_namespace_kset = {
},
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
- .hotplug_ops = &namespace_hotplug_ops,
+ .uevent_ops = &namespace_uevent_ops,
};
static void acpi_device_register(struct acpi_device *device,
@@ -347,7 +347,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
}
/* --------------------------------------------------------------------------
- ACPI hotplug sysfs device file support
+ ACPI sysfs device file support
-------------------------------------------------------------------------- */
static ssize_t acpi_eject_store(struct acpi_device *device,
const char *buf, size_t count);
@@ -475,8 +475,10 @@ static LIST_HEAD(acpi_bus_drivers);
static DECLARE_MUTEX(acpi_bus_drivers_lock);
/**
- * acpi_bus_match
- * --------------
+ * acpi_bus_match - match device IDs to driver's supported IDs
+ * @device: the device that we are trying to match to a driver
+ * @driver: driver whose device id table is being checked
+ *
* Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
* matches the specified driver's criteria.
*/
@@ -489,8 +491,10 @@ acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
}
/**
- * acpi_bus_driver_init
- * --------------------
+ * acpi_bus_driver_init - add a device to a driver
+ * @device: the device to add and initialize
+ * @driver: driver for the device
+ *
* Used to initialize a device via its device driver. Called whenever a
* driver is bound to a device. Invokes the driver's add() and start() ops.
*/
@@ -603,8 +607,9 @@ static int acpi_driver_detach(struct acpi_driver *drv)
}
/**
- * acpi_bus_register_driver
- * ------------------------
+ * acpi_bus_register_driver - register a driver with the ACPI bus
+ * @driver: driver being registered
+ *
* Registers a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and binds. Returns the
* number of devices that were claimed by the driver, or a negative
@@ -633,8 +638,9 @@ int acpi_bus_register_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_register_driver);
/**
- * acpi_bus_unregister_driver
- * --------------------------
+ * acpi_bus_unregister_driver - unregisters a driver with the APIC bus
+ * @driver: driver to unregister
+ *
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
*/
@@ -660,8 +666,9 @@ int acpi_bus_unregister_driver(struct acpi_driver *driver)
EXPORT_SYMBOL(acpi_bus_unregister_driver);
/**
- * acpi_bus_find_driver
- * --------------------
+ * acpi_bus_find_driver - check if there is a driver installed for the device
+ * @device: device that we are trying to find a supporting driver for
+ *
* Parses the list of registered drivers looking for a driver applicable for
* the specified device.
*/
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index a2bf25b05e1c..31d4f3ffc265 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -37,7 +37,7 @@
#define PREFIX "ACPI: "
-#define ACPI_MAX_TABLES 256
+#define ACPI_MAX_TABLES 128
static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
[ACPI_TABLE_UNKNOWN] = "????",
@@ -74,7 +74,7 @@ struct acpi_table_sdt {
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] __initdata;
void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr)
{
diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile
new file mode 100644
index 000000000000..40fe74097be2
--- /dev/null
+++ b/drivers/amba/Makefile
@@ -0,0 +1,2 @@
+obj-y += bus.o
+
diff --git a/arch/arm/common/amba.c b/drivers/amba/bus.c
index e1013112c354..889855d8d9f9 100644
--- a/arch/arm/common/amba.c
+++ b/drivers/amba/bus.c
@@ -12,10 +12,9 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/amba/bus.h>
#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/hardware/amba.h>
#include <asm/sizes.h>
#define to_amba_device(d) container_of(d, struct amba_device, dev)
@@ -45,7 +44,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
}
#ifdef CONFIG_HOTPLUG
-static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
+static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
{
struct amba_device *pcdev = to_amba_device(dev);
@@ -58,7 +57,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
return 0;
}
#else
-#define amba_hotplug NULL
+#define amba_uevent NULL
#endif
static int amba_suspend(struct device *dev, pm_message_t state)
@@ -88,7 +87,7 @@ static int amba_resume(struct device *dev)
static struct bus_type amba_bustype = {
.name = "amba",
.match = amba_match,
- .hotplug = amba_hotplug,
+ .uevent = amba_uevent,
.suspend = amba_suspend,
.resume = amba_resume,
};
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index c57e20dcb0f8..074abc81ec3d 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -2126,8 +2126,7 @@ static void process_rsq(ns_dev *card)
if (!ns_rsqe_valid(card->rsq.next))
return;
- while (ns_rsqe_valid(card->rsq.next))
- {
+ do {
dequeue_rx(card, card->rsq.next);
ns_rsqe_init(card->rsq.next);
previous = card->rsq.next;
@@ -2135,7 +2134,7 @@ static void process_rsq(ns_dev *card)
card->rsq.next = card->rsq.base;
else
card->rsq.next++;
- }
+ } while (ns_rsqe_valid(card->rsq.next));
writel((((u32) previous) - ((u32) card->rsq.base)),
card->membase + RSQH);
}
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 55959e4d1cb7..f484747f255e 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -669,11 +669,13 @@ printk("NONONONOO!!!!\n");
u32 *put;
int i;
- dsc = (u32 *) kmalloc(uPD98401_TXPD_SIZE*2+
- uPD98401_TXBD_SIZE*ATM_SKB(skb)->iovcnt,GFP_ATOMIC);
+ dsc = kmalloc(uPD98401_TXPD_SIZE * 2 +
+ uPD98401_TXBD_SIZE * ATM_SKB(skb)->iovcnt, GFP_ATOMIC);
if (!dsc) {
- if (vcc->pop) vcc->pop(vcc,skb);
- else dev_kfree_skb_irq(skb);
+ if (vcc->pop)
+ vcc->pop(vcc, skb);
+ else
+ dev_kfree_skb_irq(skb);
return -EAGAIN;
}
/* @@@ should check alignment */
@@ -683,7 +685,7 @@ printk("NONONONOO!!!!\n");
(ATM_SKB(skb)->atm_options & ATM_ATMOPT_CLP ?
uPD98401_CLPM_1 : uPD98401_CLPM_0));
dsc[1] = 0;
- dsc[2] = ATM_SKB(skb)->iovcnt*uPD98401_TXBD_SIZE;
+ dsc[2] = ATM_SKB(skb)->iovcnt * uPD98401_TXBD_SIZE;
dsc[3] = virt_to_bus(put);
for (i = 0; i < ATM_SKB(skb)->iovcnt; i++) {
*put++ = ((struct iovec *) skb->data)[i].iov_len;
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 934149c1512b..f0eff3dac58d 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -19,11 +19,11 @@ config PREVENT_FIRMWARE_BUILD
If unsure say Y here.
config FW_LOADER
- tristate "Hotplug firmware loading support"
+ tristate "Userspace firmware loading support"
select HOTPLUG
---help---
This option is provided for the case where no in-kernel-tree modules
- require hotplug firmware loading support, but a module built outside
+ require userspace firmware loading support, but a module built outside
the kernel tree does.
config DEBUG_DRIVER
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index fa601b085eba..29f6af554e71 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == drv) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_release_driver(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
err = count;
}
put_device(dev);
@@ -175,9 +179,13 @@ static ssize_t driver_bind(struct device_driver *drv,
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
if (dev && dev->driver == NULL) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
err = driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
}
put_device(dev);
put_bus(bus);
@@ -420,6 +428,26 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
}
}
+#ifdef CONFIG_HOTPLUG
+/*
+ * Thanks to drivers making their tables __devinit, we can't allow manual
+ * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
+ */
+static void add_bind_files(struct device_driver *drv)
+{
+ driver_create_file(drv, &driver_attr_unbind);
+ driver_create_file(drv, &driver_attr_bind);
+}
+
+static void remove_bind_files(struct device_driver *drv)
+{
+ driver_remove_file(drv, &driver_attr_bind);
+ driver_remove_file(drv, &driver_attr_unbind);
+}
+#else
+static inline void add_bind_files(struct device_driver *drv) {}
+static inline void remove_bind_files(struct device_driver *drv) {}
+#endif
/**
* bus_add_driver - Add a driver to the bus.
@@ -449,8 +477,7 @@ int bus_add_driver(struct device_driver * drv)
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
- driver_create_file(drv, &driver_attr_unbind);
- driver_create_file(drv, &driver_attr_bind);
+ add_bind_files(drv);
}
return error;
}
@@ -468,8 +495,7 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
- driver_remove_file(drv, &driver_attr_bind);
- driver_remove_file(drv, &driver_attr_unbind);
+ remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv);
klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -484,8 +510,13 @@ void bus_remove_driver(struct device_driver * drv)
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
- if (!dev->driver)
+ if (!dev->driver) {
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
device_attach(dev);
+ if (dev->parent)
+ up(&dev->parent->sem);
+ }
return 0;
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index db65fd0babe9..df7fdabd0730 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -178,7 +178,7 @@ static void class_device_create_release(struct class_device *class_dev)
}
/* needed to allow these devices to have parent class devices */
-static int class_device_create_hotplug(struct class_device *class_dev,
+static int class_device_create_uevent(struct class_device *class_dev,
char **envp, int num_envp,
char *buffer, int buffer_size)
{
@@ -331,7 +331,7 @@ static struct kobj_type ktype_class_device = {
.release = class_dev_release,
};
-static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -343,14 +343,14 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
{
struct class_device *class_dev = to_class_dev(kobj);
return class_dev->class->name;
}
-static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
@@ -365,29 +365,29 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
struct device *dev = class_dev->dev;
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
- add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "PHYSDEVPATH=%s", path);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "PHYSDEVPATH=%s", path);
kfree(path);
if (dev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
}
if (MAJOR(class_dev->devt)) {
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MAJOR=%u", MAJOR(class_dev->devt));
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MAJOR=%u", MAJOR(class_dev->devt));
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MINOR=%u", MINOR(class_dev->devt));
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MINOR=%u", MINOR(class_dev->devt));
}
/* terminate, set to next free slot, shrink available space */
@@ -397,30 +397,30 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
buffer = &buffer[length];
buffer_size -= length;
- if (class_dev->hotplug) {
+ if (class_dev->uevent) {
/* have the class device specific function add its stuff */
- retval = class_dev->hotplug(class_dev, envp, num_envp,
+ retval = class_dev->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
- pr_debug("class_dev->hotplug() returned %d\n", retval);
- } else if (class_dev->class->hotplug) {
+ pr_debug("class_dev->uevent() returned %d\n", retval);
+ } else if (class_dev->class->uevent) {
/* have the class specific function add its stuff */
- retval = class_dev->class->hotplug(class_dev, envp, num_envp,
+ retval = class_dev->class->uevent(class_dev, envp, num_envp,
buffer, buffer_size);
if (retval)
- pr_debug("class->hotplug() returned %d\n", retval);
+ pr_debug("class->uevent() returned %d\n", retval);
}
return retval;
}
-static struct kset_hotplug_ops class_hotplug_ops = {
- .filter = class_hotplug_filter,
- .name = class_hotplug_name,
- .hotplug = class_hotplug,
+static struct kset_uevent_ops class_uevent_ops = {
+ .filter = class_uevent_filter,
+ .name = class_uevent_name,
+ .uevent = class_uevent,
};
-static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
+static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
static int class_device_add_attrs(struct class_device * cd)
@@ -464,7 +464,7 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&class_dev->kobj, KOBJ_ADD);
return count;
}
@@ -559,7 +559,7 @@ int class_device_add(struct class_device *class_dev)
class_name);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&class_dev->kobj, KOBJ_ADD);
/* notify any interfaces this device is now here */
if (parent_class) {
@@ -632,7 +632,7 @@ struct class_device *class_device_create(struct class *cls,
class_dev->class = cls;
class_dev->parent = parent;
class_dev->release = class_device_create_release;
- class_dev->hotplug = class_device_create_hotplug;
+ class_dev->uevent = class_device_create_uevent;
va_start(args, fmt);
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
@@ -674,7 +674,7 @@ void class_device_del(struct class_device *class_dev)
class_device_remove_file(class_dev, class_dev->devt_attr);
class_device_remove_attrs(class_dev);
- kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
kobject_del(&class_dev->kobj);
class_device_put(parent_device);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8615b42b517a..6b355bd7816d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -90,7 +90,7 @@ static struct kobj_type ktype_device = {
};
-static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
+static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -102,14 +102,14 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
return dev->bus->name;
}
-static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct device *dev = to_dev(kobj);
@@ -119,15 +119,15 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
/* add bus name of physical device */
if (dev->bus)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVBUS=%s", dev->bus->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
/* add driver name of physical device */
if (dev->driver)
- add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVDRIVER=%s", dev->driver->name);
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
@@ -136,11 +136,11 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
buffer = &buffer[length];
buffer_size -= length;
- if (dev->bus && dev->bus->hotplug) {
+ if (dev->bus && dev->bus->uevent) {
/* have the bus specific function add its stuff */
- retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
+ retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
+ pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval);
}
}
@@ -148,24 +148,24 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
return retval;
}
-static struct kset_hotplug_ops device_hotplug_ops = {
- .filter = dev_hotplug_filter,
- .name = dev_hotplug_name,
- .hotplug = dev_hotplug,
+static struct kset_uevent_ops device_uevent_ops = {
+ .filter = dev_uevent_filter,
+ .name = dev_uevent_name,
+ .uevent = dev_uevent,
};
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
return count;
}
-/**
- * device_subsys - structure to be registered with kobject core.
+/*
+ * devices_subsys - structure to be registered with kobject core.
*/
-decl_subsys(devices, &ktype_device, &device_hotplug_ops);
+decl_subsys(devices, &ktype_device, &device_uevent_ops);
/**
@@ -274,7 +274,7 @@ int device_add(struct device *dev)
dev->uevent_attr.store = store_uevent;
device_create_file(dev, &dev->uevent_attr);
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
@@ -291,7 +291,7 @@ int device_add(struct device *dev)
BusError:
device_pm_remove(dev);
PMError:
- kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
if (parent)
@@ -374,7 +374,7 @@ void device_del(struct device * dev)
platform_notify_remove(dev);
bus_remove_device(dev);
device_pm_remove(dev);
- kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
+ kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
if (parent)
put_device(parent);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index a95844790f7b..07a7f97e1de9 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -41,14 +41,14 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
case '0':
ret = cpu_down(cpu->sysdev.id);
if (!ret)
- kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
+ kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
break;
case '1':
ret = smp_prepare_cpu(cpu->sysdev.id);
if (!ret)
ret = cpu_up(cpu->sysdev.id);
if (!ret)
- kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
+ kobject_uevent(&dev->kobj, KOBJ_ONLINE);
break;
default:
ret = -EINVAL;
@@ -83,6 +83,31 @@ static inline void register_cpu_control(struct cpu *cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
+#ifdef CONFIG_KEXEC
+#include <linux/kexec.h>
+
+static ssize_t show_crash_notes(struct sys_device *dev, char *buf)
+{
+ struct cpu *cpu = container_of(dev, struct cpu, sysdev);
+ ssize_t rc;
+ unsigned long long addr;
+ int cpunum;
+
+ cpunum = cpu->sysdev.id;
+
+ /*
+ * Might be reading other cpu's data based on which cpu read thread
+ * has been scheduled. But cpu data (memory) is allocated once during
+ * boot up and this data does not change there after. Hence this
+ * operation should be safe. No locking required.
+ */
+ addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+ rc = sprintf(buf, "%Lx\n", addr);
+ return rc;
+}
+static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+#endif
+
/*
* register_cpu - Setup a driverfs device for a CPU.
* @cpu - Callers can set the cpu->no_control field to 1, to indicate not to
@@ -108,6 +133,11 @@ int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
register_cpu_control(cpu);
if (!error)
cpu_sys_devices[num] = &cpu->sysdev;
+
+#ifdef CONFIG_KEXEC
+ if (!error)
+ error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes);
+#endif
return error;
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 3b419c9a1e7e..730a9ce0a14a 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
* This function returns 1 if a match is found, an error if one
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
*
- * This function must be called with @dev->sem held.
+ * This function must be called with @dev->sem held. When called
+ * for a USB interface, @dev->parent->sem must be held as well.
*/
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
@@ -77,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
pr_debug("%s: Matched Device %s with Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
dev->driver = drv;
- if (drv->probe) {
+ if (dev->bus->probe) {
+ ret = dev->bus->probe(dev);
+ if (ret) {
+ dev->driver = NULL;
+ goto ProbeFailed;
+ }
+ } else if (drv->probe) {
ret = drv->probe(dev);
if (ret) {
dev->driver = NULL;
@@ -123,6 +130,8 @@ static int __device_attach(struct device_driver * drv, void * data)
*
* Returns 1 if the device was bound to a driver;
* 0 if no matching device was found; error code otherwise.
+ *
+ * When called for a USB interface, @dev->parent->sem must be held.
*/
int device_attach(struct device * dev)
{
@@ -152,10 +161,14 @@ static int __driver_attach(struct device * dev, void * data)
* is an error.
*/
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
return 0;
}
@@ -181,6 +194,8 @@ void driver_attach(struct device_driver * drv)
* Manually detach device from driver.
*
* __device_release_driver() must be called with @dev->sem held.
+ * When called for a USB interface, @dev->parent->sem must be held
+ * as well.
*/
static void __device_release_driver(struct device * dev)
@@ -194,7 +209,9 @@ static void __device_release_driver(struct device * dev)
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
- if (drv->remove)
+ if (dev->bus->remove)
+ dev->bus->remove(dev);
+ else if (drv->remove)
drv->remove(dev);
dev->driver = NULL;
put_driver(drv);
@@ -233,10 +250,14 @@ void driver_detach(struct device_driver * drv)
get_device(dev);
spin_unlock(&drv->klist_devices.k_lock);
+ if (dev->parent) /* Needed for USB */
+ down(&dev->parent->sem);
down(&dev->sem);
if (dev->driver == drv)
__device_release_driver(dev);
up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
put_device(dev);
}
}
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 161f3a390d90..b400314e1c62 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n)
*/
int driver_register(struct device_driver * drv)
{
+ if ((drv->bus->probe && drv->probe) ||
+ (drv->bus->remove && drv->remove) ||
+ (drv->bus->shutdown && drv->shutdown)) {
+ printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
+ }
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 59dacb6552c0..e97e911ebf7a 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -7,6 +7,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -47,7 +48,7 @@ struct firmware_priv {
struct timer_list timeout;
};
-static inline void
+static void
fw_load_abort(struct firmware_priv *fw_priv)
{
set_bit(FW_STATUS_ABORT, &fw_priv->status);
@@ -85,17 +86,17 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_class_dev_release(struct class_device *class_dev);
-int firmware_class_hotplug(struct class_device *dev, char **envp,
+int firmware_class_uevent(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
static struct class firmware_class = {
.name = "firmware",
- .hotplug = firmware_class_hotplug,
+ .uevent = firmware_class_uevent,
.release = fw_class_dev_release,
};
int
-firmware_class_hotplug(struct class_device *class_dev, char **envp,
+firmware_class_uevent(struct class_device *class_dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
@@ -104,13 +105,12 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp,
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
return -ENODEV;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "FIRMWARE=%s", fw_priv->fw_id))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "FIRMWARE=%s", fw_priv->fw_id))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
- "TIMEOUT=%i", loading_timeout))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "TIMEOUT=%i", loading_timeout))
return -ENOMEM;
-
envp[i] = NULL;
return 0;
@@ -352,7 +352,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, int hotplug)
+ const char *fw_name, struct device *device, int uevent)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -384,7 +384,7 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
goto error_unreg;
}
- if (hotplug)
+ if (uevent)
set_bit(FW_STATUS_READY, &fw_priv->status);
else
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
@@ -399,7 +399,7 @@ out:
static int
_request_firmware(const struct firmware **firmware_p, const char *name,
- struct device *device, int hotplug)
+ struct device *device, int uevent)
{
struct class_device *class_dev;
struct firmware_priv *fw_priv;
@@ -418,19 +418,19 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
}
retval = fw_setup_class_device(firmware, &class_dev, name, device,
- hotplug);
+ uevent);
if (retval)
goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev);
- if (hotplug) {
+ if (uevent) {
if (loading_timeout > 0) {
fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
add_timer(&fw_priv->timeout);
}
- kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+ kobject_uevent(&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);
@@ -456,7 +456,7 @@ out:
}
/**
- * request_firmware: - request firmware to hotplug and wait for it
+ * request_firmware: - send firmware request and wait for it
* @firmware_p: pointer to firmware image
* @name: name of firmware file
* @device: device for which firmware is being loaded
@@ -466,7 +466,7 @@ out:
*
* Should be called from user context where sleeping is allowed.
*
- * @name will be used as $FIRMWARE in the hotplug environment and
+ * @name will be used as $FIRMWARE in the uevent environment and
* should be distinctive enough not to be confused with any other
* firmware image for this or any other device.
**/
@@ -474,8 +474,8 @@ 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);
+ int uevent = 1;
+ return _request_firmware(firmware_p, name, device, uevent);
}
/**
@@ -518,7 +518,7 @@ struct firmware_work {
struct device *device;
void *context;
void (*cont)(const struct firmware *fw, void *context);
- int hotplug;
+ int uevent;
};
static int
@@ -533,7 +533,7 @@ request_firmware_work_func(void *arg)
}
daemonize("%s/%s", "firmware", fw_work->name);
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
- fw_work->hotplug);
+ fw_work->uevent);
if (ret < 0)
fw_work->cont(NULL, fw_work->context);
else {
@@ -548,7 +548,7 @@ request_firmware_work_func(void *arg)
/**
* request_firmware_nowait: asynchronous version of request_firmware
* @module: module requesting the firmware
- * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ * @uevent: sends uevent to copy the firmware image if this flag
* is non-zero else the firmware copy must be done manually.
* @name: name of firmware file
* @device: device for which firmware is being loaded
@@ -562,7 +562,7 @@ request_firmware_work_func(void *arg)
**/
int
request_firmware_nowait(
- struct module *module, int hotplug,
+ struct module *module, int uevent,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
@@ -583,7 +583,7 @@ request_firmware_nowait(
.device = device,
.context = context,
.cont = cont,
- .hotplug = hotplug,
+ .uevent = uevent,
};
ret = kernel_thread(request_firmware_work_func, fw_work,
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index bc3ca6a656b2..d1a05224627e 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -13,8 +13,8 @@
#include <linux/sysdev.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h> /* capable() */
#include <linux/topology.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/memory.h>
#include <linux/kobject.h>
@@ -29,12 +29,12 @@ static struct sysdev_class memory_sysdev_class = {
set_kset_name(MEMORY_CLASS_NAME),
};
-static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
{
return MEMORY_CLASS_NAME;
}
-static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
+static int memory_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
int retval = 0;
@@ -42,19 +42,19 @@ static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
return retval;
}
-static struct kset_hotplug_ops memory_hotplug_ops = {
- .name = memory_hotplug_name,
- .hotplug = memory_hotplug,
+static struct kset_uevent_ops memory_uevent_ops = {
+ .name = memory_uevent_name,
+ .uevent = memory_uevent,
};
static struct notifier_block *memory_chain;
-static int register_memory_notifier(struct notifier_block *nb)
+int register_memory_notifier(struct notifier_block *nb)
{
return notifier_chain_register(&memory_chain, nb);
}
-static void unregister_memory_notifier(struct notifier_block *nb)
+void unregister_memory_notifier(struct notifier_block *nb)
{
notifier_chain_unregister(&memory_chain, nb);
}
@@ -62,8 +62,7 @@ static void unregister_memory_notifier(struct notifier_block *nb)
/*
* register_memory - Setup a sysfs device for a memory block
*/
-static int
-register_memory(struct memory_block *memory, struct mem_section *section,
+int register_memory(struct memory_block *memory, struct mem_section *section,
struct node *root)
{
int error;
@@ -431,7 +430,7 @@ int __init memory_dev_init(void)
unsigned int i;
int ret;
- memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
+ memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
ret = sysdev_class_register(&memory_sysdev_class);
/*
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 8827dafba945..461554a02517 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -25,6 +25,7 @@
struct device platform_bus = {
.bus_id = "platform",
};
+EXPORT_SYMBOL_GPL(platform_bus);
/**
* platform_get_resource - get a resource for a device
@@ -49,6 +50,7 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource);
/**
* platform_get_irq - get an IRQ for a device
@@ -61,6 +63,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
return r ? r->start : 0;
}
+EXPORT_SYMBOL_GPL(platform_get_irq);
/**
* platform_get_resource_byname - get a resource for a device by name
@@ -84,6 +87,7 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
}
return NULL;
}
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
/**
* platform_get_irq - get an IRQ for a device
@@ -96,6 +100,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name)
return r ? r->start : 0;
}
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
/**
* platform_add_devices - add a numbers of platform devices
@@ -117,6 +122,7 @@ int platform_add_devices(struct platform_device **devs, int num)
return ret;
}
+EXPORT_SYMBOL_GPL(platform_add_devices);
struct platform_object {
struct platform_device pdev;
@@ -168,7 +174,7 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
pa->pdev.dev.release = platform_device_release;
}
- return pa ? &pa->pdev : NULL;
+ return pa ? &pa->pdev : NULL;
}
EXPORT_SYMBOL_GPL(platform_device_alloc);
@@ -257,7 +263,7 @@ int platform_device_add(struct platform_device *pdev)
p = &ioport_resource;
}
- if (p && request_resource(p, r)) {
+ if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d\n",
pdev->dev.bus_id, i);
@@ -282,24 +288,13 @@ int platform_device_add(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(platform_device_add);
/**
- * platform_device_register - add a platform-level device
- * @pdev: platform device we're adding
- *
- */
-int platform_device_register(struct platform_device * pdev)
-{
- device_initialize(&pdev->dev);
- return platform_device_add(pdev);
-}
-
-/**
- * platform_device_unregister - remove a platform-level device
+ * platform_device_del - remove a platform-level device
* @pdev: platform device we're removing
*
* Note that this function will also release all memory- and port-based
* resources owned by the device (@dev->resource).
*/
-void platform_device_unregister(struct platform_device * pdev)
+void platform_device_del(struct platform_device *pdev)
{
int i;
@@ -310,9 +305,37 @@ void platform_device_unregister(struct platform_device * pdev)
release_resource(r);
}
- device_unregister(&pdev->dev);
+ device_del(&pdev->dev);
}
}
+EXPORT_SYMBOL_GPL(platform_device_del);
+
+/**
+ * platform_device_register - add a platform-level device
+ * @pdev: platform device we're adding
+ *
+ */
+int platform_device_register(struct platform_device * pdev)
+{
+ device_initialize(&pdev->dev);
+ return platform_device_add(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_register);
+
+/**
+ * platform_device_unregister - unregister a platform-level device
+ * @pdev: platform device we're unregistering
+ *
+ * Unregistration is done in 2 steps. Fisrt we release all resources
+ * and remove it from the subsystem, then we drop reference count by
+ * calling platform_device_put().
+ */
+void platform_device_unregister(struct platform_device * pdev)
+{
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+}
+EXPORT_SYMBOL_GPL(platform_device_unregister);
/**
* platform_device_register_simple
@@ -355,6 +378,7 @@ error:
platform_device_put(pdev);
return ERR_PTR(retval);
}
+EXPORT_SYMBOL_GPL(platform_device_register_simple);
static int platform_drv_probe(struct device *_dev)
{
@@ -476,6 +500,7 @@ struct bus_type platform_bus_type = {
.suspend = platform_suspend,
.resume = platform_resume,
};
+EXPORT_SYMBOL_GPL(platform_bus_type);
int __init platform_bus_init(void)
{
@@ -504,14 +529,3 @@ u64 dma_get_required_mask(struct device *dev)
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif
-
-EXPORT_SYMBOL_GPL(platform_bus);
-EXPORT_SYMBOL_GPL(platform_bus_type);
-EXPORT_SYMBOL_GPL(platform_add_devices);
-EXPORT_SYMBOL_GPL(platform_device_register);
-EXPORT_SYMBOL_GPL(platform_device_register_simple);
-EXPORT_SYMBOL_GPL(platform_device_unregister);
-EXPORT_SYMBOL_GPL(platform_get_irq);
-EXPORT_SYMBOL_GPL(platform_get_resource);
-EXPORT_SYMBOL_GPL(platform_get_irq_byname);
-EXPORT_SYMBOL_GPL(platform_get_resource_byname);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index adbc3148c039..96370ec1d673 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -62,8 +62,10 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
up(&dpm_sem);
return error;
}
+EXPORT_SYMBOL(dpm_runtime_suspend);
+#if 0
/**
* dpm_set_power_state - Update power_state field.
* @dev: Device.
@@ -80,3 +82,4 @@ void dpm_set_power_state(struct device * dev, pm_message_t state)
dev->power.power_state = state;
up(&dpm_sem);
}
+#endif /* 0 */
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index f50a08be424b..c2475f3134ea 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -35,12 +35,15 @@ extern int sysdev_shutdown(void);
*/
void device_shutdown(void)
{
- struct device * dev;
+ struct device * dev, *devn;
down_write(&devices_subsys.rwsem);
- list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
+ list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
kobj.entry) {
- if (dev->driver && dev->driver->shutdown) {
+ if (dev->bus && dev->bus->shutdown) {
+ dev_dbg(dev, "shutdown\n");
+ dev->bus->shutdown(dev);
+ } else if (dev->driver && dev->driver->shutdown) {
dev_dbg(dev, "shutdown\n");
dev->driver->shutdown(dev);
}
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 70eaa5c7ac08..6ede1f352c29 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
return 0;
}
-static int DAC960_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct gendisk *disk = bdev->bd_disk;
DAC960_Controller_T *p = disk->queue->queuedata;
int drive_nr = (long)disk->private_data;
- struct hd_geometry g;
- struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
-
- if (cmd != HDIO_GETGEO || !loc)
- return -EINVAL;
if (p->FirmwareType == DAC960_V1_Controller) {
- g.heads = p->V1.GeometryTranslationHeads;
- g.sectors = p->V1.GeometryTranslationSectors;
- g.cylinders = p->V1.LogicalDriveInformation[drive_nr].
- LogicalDriveSize / (g.heads * g.sectors);
+ geo->heads = p->V1.GeometryTranslationHeads;
+ geo->sectors = p->V1.GeometryTranslationSectors;
+ geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
+ LogicalDriveSize / (geo->heads * geo->sectors);
} else {
DAC960_V2_LogicalDeviceInfo_T *i =
p->V2.LogicalDeviceInformation[drive_nr];
switch (i->DriveGeometry) {
case DAC960_V2_Geometry_128_32:
- g.heads = 128;
- g.sectors = 32;
+ geo->heads = 128;
+ geo->sectors = 32;
break;
case DAC960_V2_Geometry_255_63:
- g.heads = 255;
- g.sectors = 63;
+ geo->heads = 255;
+ geo->sectors = 63;
break;
default:
DAC960_Error("Illegal Logical Device Geometry %d\n",
@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
- g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
+ geo->cylinders = i->ConfigurableDeviceSize /
+ (geo->heads * geo->sectors);
}
- g.start = get_start_sect(inode->i_bdev);
-
- return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ return 0;
}
static int DAC960_media_changed(struct gendisk *disk)
@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
static struct block_device_operations DAC960_BlockDeviceOperations = {
.owner = THIS_MODULE,
.open = DAC960_open,
- .ioctl = DAC960_ioctl,
+ .getgeo = DAC960_getgeo,
.media_changed = DAC960_media_changed,
.revalidate_disk = DAC960_revalidate_disk,
};
@@ -3471,7 +3464,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
- end_that_request_last(Request);
+ end_that_request_last(Request, UpToDate);
if (Command->Completion) {
complete(Command->Completion);
@@ -3767,7 +3760,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
if (SenseKey == DAC960_SenseKey_VendorSpecific &&
AdditionalSenseCode == 0x80 &&
AdditionalSenseCodeQualifier <
- sizeof(DAC960_EventMessages) / sizeof(char *))
+ ARRAY_SIZE(DAC960_EventMessages))
DAC960_Critical("Physical Device %d:%d %s\n", Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
@@ -7186,7 +7179,7 @@ static int DAC960_init_module(void)
{
int ret;
- ret = pci_module_init(&DAC960_pci_driver);
+ ret = pci_register_driver(&DAC960_pci_driver);
#ifdef DAC960_GAM_MINOR
if (!ret)
DAC960_gam_init();
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 7b1cd93892be..139cbba76180 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -117,7 +117,7 @@ config BLK_DEV_XD
config PARIDE
tristate "Parallel port IDE device support"
- depends on PARPORT
+ depends on PARPORT_PC
---help---
There are many external CD-ROM and disk devices that connect through
your computer's parallel port. Most of them are actually IDE devices
@@ -358,7 +358,8 @@ config BLK_DEV_UB
This driver supports certain USB attached storage devices
such as flash keys.
- Warning: Enabling this cripples the usb-storage driver.
+ If you enable this driver, it is recommended to avoid conflicts
+ with usb-storage by enabling USB_LIBUSUAL.
If unsure, say N.
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 5d2d649f7e8d..196c0ec9cd54 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void )
*
***********************************************************************/
+static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct acsi_info_struct *aip = bdev->bd_disk->private_data;
+
+ /*
+ * Just fake some geometry here, it's nonsense anyway
+ * To make it easy, use Adaptec's usual 64/32 mapping
+ */
+ geo->heads = 64;
+ geo->sectors = 32;
+ geo->cylinders = aip->size >> 11;
+ return 0;
+}
static int acsi_ioctl( struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg )
@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
struct gendisk *disk = inode->i_bdev->bd_disk;
struct acsi_info_struct *aip = disk->private_data;
switch (cmd) {
- case HDIO_GETGEO:
- /* HDIO_GETGEO is supported more for getting the partition's
- * start sector... */
- { struct hd_geometry *geo = (struct hd_geometry *)arg;
- /* just fake some geometry here, it's nonsense anyway; to make it
- * easy, use Adaptec's usual 64/32 mapping */
- put_user( 64, &geo->heads );
- put_user( 32, &geo->sectors );
- put_user( aip->size >> 11, &geo->cylinders );
- put_user(get_start_sect(inode->i_bdev), &geo->start);
- return 0;
- }
case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
put_user( aip->target | (aip->lun << 8),
@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = {
.open = acsi_open,
.release = acsi_release,
.ioctl = acsi_ioctl,
+ .getgeo = acsi_getgeo,
.media_changed = acsi_media_change,
.revalidate_disk= acsi_revalidate,
};
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 0acbfff8ad28..b6e290956214 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -131,7 +131,7 @@ static struct fd_drive_type drive_types[] = {
{ FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
{ FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
-static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
+static int num_dr_types = ARRAY_SIZE(drive_types);
static int amiga_read(int), dos_read(int);
static void amiga_write(int), dos_write(int);
@@ -194,6 +194,8 @@ static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
*/
#define MAX_ERRORS 12
+#define custom amiga_custom
+
/* Prevent "aliased" accesses. */
static int fd_ref[4] = { 0,0,0,0 };
static int fd_device[4] = { 0, 0, 0, 0 };
@@ -1424,25 +1426,24 @@ static void do_fd_request(request_queue_t * q)
redo_fd_request();
}
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ int drive = MINOR(bdev->bd_dev) & 3;
+
+ geo->heads = unit[drive].type->heads;
+ geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
+ geo->cylinders = unit[drive].type->tracks;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param)
{
int drive = iminor(inode) & 3;
static struct floppy_struct getprm;
+ void __user *argp = (void __user *)param;
switch(cmd){
- case HDIO_GETGEO:
- {
- struct hd_geometry loc;
- loc.heads = unit[drive].type->heads;
- loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
- loc.cylinders = unit[drive].type->tracks;
- loc.start = 0;
- if (copy_to_user((void *)param, (void *)&loc,
- sizeof(struct hd_geometry)))
- return -EFAULT;
- break;
- }
case FDFMTBEG:
get_fdc(drive);
if (fd_ref[drive] > 1) {
@@ -1486,9 +1487,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
getprm.head=unit[drive].type->heads;
getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult;
getprm.size=unit[drive].blocks;
- if (copy_to_user((void *)param,
- (void *)&getprm,
- sizeof(struct floppy_struct)))
+ if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct)))
return -EFAULT;
break;
case FDSETPRM:
@@ -1500,8 +1499,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
break;
#ifdef RAW_IOCTL
case IOCTL_RAW_TRACK:
- if (copy_to_user((void *)param, raw_buf,
- unit[drive].type->read_size))
+ if (copy_to_user(argp, raw_buf, unit[drive].type->read_size))
return -EFAULT;
else
return unit[drive].type->read_size;
@@ -1652,15 +1650,10 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
.media_changed = amiga_floppy_change,
};
-void __init amiga_floppy_setup (char *str, int *ints)
-{
- printk (KERN_INFO "amiflop: Setting default df0 to %x\n", ints[1]);
- fd_def_df0 = ints[1];
-}
-
static int __init fd_probe_drives(void)
{
int drive,drives,nomem;
@@ -1846,4 +1839,18 @@ void cleanup_module(void)
unregister_blkdev(FLOPPY_MAJOR, "fd");
}
#endif
+
+#else
+static int __init amiga_floppy_setup (char *str)
+{
+ int n;
+ if (!MACH_IS_AMIGA)
+ return 0;
+ if (!get_option(&str, &n))
+ return 0;
+ printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
+ fd_def_df0 = n;
+}
+
+__setup("floppy=", amiga_floppy_setup);
#endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 0e97fcb9f3a1..c05ee8bffd97 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
return 0;
}
-/* This ioctl implementation expects userland to have the device node
- * permissions set so that only priviledged users can open an aoe
- * block device directly.
- */
static int
-aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg)
+aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct aoedev *d;
-
- if (!arg)
- return -EINVAL;
+ struct aoedev *d = bdev->bd_disk->private_data;
- d = inode->i_bdev->bd_disk->private_data;
if ((d->flags & DEVFL_UP) == 0) {
printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
return -ENODEV;
}
- if (cmd == HDIO_GETGEO) {
- d->geo.start = get_start_sect(inode->i_bdev);
- if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo))
- return 0;
- return -EFAULT;
- }
- printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
- return -EINVAL;
+ geo->cylinders = d->geo.cylinders;
+ geo->heads = d->geo.heads;
+ geo->sectors = d->geo.sectors;
+ return 0;
}
static struct block_device_operations aoe_bdops = {
.open = aoeblk_open,
.release = aoeblk_release,
- .ioctl = aoeblk_ioctl,
+ .getgeo = aoeblk_getgeo,
.owner = THIS_MODULE,
};
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 22bda05fc693..f8ce235ccfc3 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -181,7 +181,7 @@ static struct {
{ 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */
};
-#define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype))
+#define NUM_DISK_MINORS ARRAY_SIZE(minor2disktype)
/*
* Maximum disk size (in kilobytes). This default is used whenever the
@@ -1361,7 +1361,7 @@ static int floppy_revalidate(struct gendisk *disk)
formats, for 'permanent user-defined' parameter:
restore default_params[] here if flagged valid! */
if (default_params[drive].blocks == 0)
- UDT = 0;
+ UDT = NULL;
else
UDT = &default_params[drive];
}
@@ -1495,6 +1495,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
struct floppy_struct getprm;
int settype;
struct floppy_struct setprm;
+ void __user *argp = (void __user *)param;
switch (cmd) {
case FDGETPRM:
@@ -1521,7 +1522,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
getprm.head = 2;
getprm.track = dtp->blocks/dtp->spt/2;
getprm.stretch = dtp->stretch;
- if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
+ if (copy_to_user(argp, &getprm, sizeof(getprm)))
return -EFAULT;
return 0;
}
@@ -1540,7 +1541,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
/* get the parameters from user space */
if (floppy->ref != 1 && floppy->ref != -1)
return -EBUSY;
- if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
+ if (copy_from_user(&setprm, argp, sizeof(setprm)))
return -EFAULT;
/*
* first of all: check for floppy change and revalidate,
@@ -1647,7 +1648,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
case FDFMTTRK:
if (floppy->ref != 1 && floppy->ref != -1)
return -EBUSY;
- if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
+ if (copy_from_user(&fmt_desc, argp, sizeof(fmt_desc)))
return -EFAULT;
return do_format(drive, type, &fmt_desc);
case FDCLRPRM:
@@ -1950,14 +1951,20 @@ Enomem:
return -ENOMEM;
}
-
-void __init atari_floppy_setup( char *str, int *ints )
+#ifndef MODULE
+static int __init atari_floppy_setup(char *str)
{
+ int ints[3 + FD_MAX_UNITS];
int i;
+
+ if (!MACH_IS_ATARI)
+ return 0;
+
+ str = get_options(str, 3 + FD_MAX_UNITS, ints);
if (ints[0] < 1) {
printk(KERN_ERR "ataflop_setup: no arguments!\n" );
- return;
+ return 0;
}
else if (ints[0] > 2+FD_MAX_UNITS) {
printk(KERN_ERR "ataflop_setup: too many arguments\n" );
@@ -1977,9 +1984,13 @@ void __init atari_floppy_setup( char *str, int *ints )
else
UserSteprate[i-3] = ints[i];
}
+ return 1;
}
-static void atari_floppy_exit(void)
+__setup("floppy=", atari_floppy_setup);
+#endif
+
+static void __exit atari_floppy_exit(void)
{
int i;
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c3441b3f086e..12d7b9bdfa93 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1,6 +1,6 @@
/*
* Disk Array driver for HP SA 5xxx and 6xxx Controllers
- * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,12 +47,12 @@
#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.8)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.10)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
" SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
@@ -103,7 +103,7 @@ static const struct pci_device_id cciss_pci_device_id[] = {
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
-#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
+#define NR_PRODUCTS ARRAY_SIZE(products)
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep);
static int cciss_release(struct inode *inode, struct file *filep);
static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
@@ -166,7 +167,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
-
+static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32);
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,
@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = {
.open = cciss_open,
.release = cciss_release,
.ioctl = cciss_ioctl,
+ .getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = cciss_compat_ioctl,
#endif
@@ -282,7 +284,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
h->product_name,
(unsigned long)h->board_id,
h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3],
- (unsigned int)h->intr,
+ (unsigned int)h->intr[SIMPLE_MODE_INT],
h->num_luns,
h->Qdepth, h->commands_outstanding,
h->maxQsinceinit, h->max_outstanding, h->maxSG);
@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
return err;
}
#endif
+
+static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ drive_info_struct *drv = get_drv(bdev->bd_disk);
+
+ if (!drv->cylinders)
+ return -ENXIO;
+
+ geo->heads = drv->heads;
+ geo->sectors = drv->sectors;
+ geo->cylinders = drv->cylinders;
+ return 0;
+}
+
/*
* ioctl
*/
@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
#endif /* CCISS_DEBUG */
switch(cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry driver_geo;
- if (drv->cylinders) {
- driver_geo.heads = drv->heads;
- driver_geo.sectors = drv->sectors;
- driver_geo.cylinders = drv->cylinders;
- } else
- return -ENXIO;
- driver_geo.start= get_start_sect(inode->i_bdev);
- if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry)))
- return -EFAULT;
- return(0);
- }
-
case CCISS_GETPCIINFO:
{
cciss_pci_info_struct pciinfo;
@@ -2177,16 +2178,48 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
start_io(h);
}
+
+static void cciss_softirq_done(struct request *rq)
+{
+ CommandList_struct *cmd = rq->completion_data;
+ ctlr_info_t *h = hba[cmd->ctlr];
+ u64bit temp64;
+ int i, ddir;
+
+ if (cmd->Request.Type.Direction == XFER_READ)
+ ddir = PCI_DMA_FROMDEVICE;
+ else
+ ddir = PCI_DMA_TODEVICE;
+
+ /* command did not need to be retried */
+ /* unmap the DMA mapping for all the scatter gather elements */
+ for(i=0; i<cmd->Header.SGList; i++) {
+ temp64.val32.lower = cmd->SG[i].Addr.lower;
+ temp64.val32.upper = cmd->SG[i].Addr.upper;
+ pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+ }
+
+ complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+ printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+ spin_lock_irq(&h->lock);
+ end_that_request_last(rq, rq->errors);
+ cmd_free(h, cmd,1);
+ spin_unlock_irq(&h->lock);
+}
+
/* checks the status of the job and calls complete buffers to mark all
- * buffers for the completed job.
+ * buffers for the completed job. Note that this function does not need
+ * to hold the hba/queue lock.
*/
static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
int timeout)
{
int status = 1;
- int i;
int retry_cmd = 0;
- u64bit temp64;
if (timeout)
status = 0;
@@ -2294,24 +2327,10 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
resend_cciss_cmd(h,cmd);
return;
}
- /* command did not need to be retried */
- /* unmap the DMA mapping for all the scatter gather elements */
- for(i=0; i<cmd->Header.SGList; i++) {
- temp64.val32.lower = cmd->SG[i].Addr.lower;
- temp64.val32.upper = cmd->SG[i].Addr.upper;
- pci_unmap_page(hba[cmd->ctlr]->pdev,
- temp64.val, cmd->SG[i].Len,
- (cmd->Request.Type.Direction == XFER_READ) ?
- PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
- }
- complete_buffers(cmd->rq->bio, status);
-#ifdef CCISS_DEBUG
- printk("Done with %p\n", cmd->rq);
-#endif /* CCISS_DEBUG */
-
- end_that_request_last(cmd->rq);
- cmd_free(h,cmd,1);
+ cmd->rq->completion_data = cmd;
+ cmd->rq->errors = status;
+ blk_complete_request(cmd->rq);
}
/*
@@ -2661,6 +2680,60 @@ static int find_PCI_BAR_index(struct pci_dev *pdev,
return -1;
}
+/* If MSI/MSI-X is supported by the kernel we will try to enable it on
+ * controllers that are capable. If not, we use IO-APIC mode.
+ */
+
+static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id)
+{
+#ifdef CONFIG_PCI_MSI
+ int err;
+ struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1},
+ {0,2}, {0,3}};
+
+ /* Some boards advertise MSI but don't really support it */
+ if ((board_id == 0x40700E11) ||
+ (board_id == 0x40800E11) ||
+ (board_id == 0x40820E11) ||
+ (board_id == 0x40830E11))
+ goto default_int_mode;
+
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+ err = pci_enable_msix(pdev, cciss_msix_entries, 4);
+ if (!err) {
+ c->intr[0] = cciss_msix_entries[0].vector;
+ c->intr[1] = cciss_msix_entries[1].vector;
+ c->intr[2] = cciss_msix_entries[2].vector;
+ c->intr[3] = cciss_msix_entries[3].vector;
+ c->msix_vector = 1;
+ return;
+ }
+ if (err > 0) {
+ printk(KERN_WARNING "cciss: only %d MSI-X vectors "
+ "available\n", err);
+ } else {
+ printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
+ err);
+ }
+ }
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+ if (!pci_enable_msi(pdev)) {
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ c->msi_vector = 1;
+ return;
+ } else {
+ printk(KERN_WARNING "cciss: MSI init failed\n");
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ return;
+ }
+ }
+#endif /* CONFIG_PCI_MSI */
+ /* if we get here we're going to use the default interrupt mode */
+default_int_mode:
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ return;
+}
+
static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
{
ushort subsystem_vendor_id, subsystem_device_id, command;
@@ -2721,7 +2794,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
printk("board_id = %x\n", board_id);
#endif /* CCISS_DEBUG */
- c->intr = pdev->irq;
+/* If the kernel supports MSI/MSI-X we will try to enable that functionality,
+ * else we use the IO-APIC interrupt assigned to us by system ROM.
+ */
+ cciss_interrupt_mode(c, pdev, board_id);
/*
* Memory base addr is first addr , the second points to the config
@@ -2775,7 +2851,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
c->board_id = board_id;
#ifdef CCISS_DEBUG
- print_cfg_table(c->cfgtable);
+ print_cfg_table(c->cfgtable);
#endif /* CCISS_DEBUG */
for(i=0; i<NR_PRODUCTS; i++) {
@@ -3060,7 +3136,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
* 8 controller support.
*/
if (i < MAX_CTLR_ORIG)
- hba[i]->major = MAJOR_NR + i;
+ hba[i]->major = COMPAQ_CISS_MAJOR + i;
rc = register_blkdev(hba[i]->major, hba[i]->devname);
if(rc == -EBUSY || rc == -EINVAL) {
printk(KERN_ERR
@@ -3075,11 +3151,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* make sure the board interrupts are off */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
- if( request_irq(hba[i]->intr, do_cciss_intr,
+ if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
hba[i]->devname, hba[i])) {
printk(KERN_ERR "cciss: Unable to get irq %d for %s\n",
- hba[i]->intr, hba[i]->devname);
+ hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
goto clean2;
}
hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
@@ -3141,15 +3217,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
drv->queue = q;
q->backing_dev_info.ra_pages = READ_AHEAD;
- blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+ blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
- /* This is a hardware imposed limit. */
- blk_queue_max_hw_segments(q, MAXSGENTRIES);
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(q, MAXSGENTRIES);
- /* This is a limit in the driver and could be eliminated. */
- blk_queue_max_phys_segments(q, MAXSGENTRIES);
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(q, MAXSGENTRIES);
- blk_queue_max_sectors(q, 512);
+ blk_queue_max_sectors(q, 512);
+
+ blk_queue_softirq_done(q, cciss_softirq_done);
q->queuedata = hba[i];
sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
@@ -3185,7 +3263,7 @@ clean4:
NR_CMDS * sizeof( ErrorInfo_struct),
hba[i]->errinfo_pool,
hba[i]->errinfo_pool_dhandle);
- free_irq(hba[i]->intr, hba[i]);
+ free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
clean2:
unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1:
@@ -3226,7 +3304,15 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
printk(KERN_WARNING "Error Flushing cache on controller %d\n",
i);
}
- free_irq(hba[i]->intr, hba[i]);
+ free_irq(hba[i]->intr[2], hba[i]);
+
+#ifdef CONFIG_PCI_MSI
+ if (hba[i]->msix_vector)
+ pci_disable_msix(hba[i]->pdev);
+ else if (hba[i]->msi_vector)
+ pci_disable_msi(hba[i]->pdev);
+#endif /* CONFIG_PCI_MSI */
+
pci_set_drvdata(pdev, NULL);
iounmap(hba[i]->vaddr);
cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
@@ -3274,7 +3360,7 @@ static int __init cciss_init(void)
printk(KERN_INFO DRIVER_NAME "\n");
/* Register for our PCI devices */
- return pci_module_init(&cciss_pci_driver);
+ return pci_register_driver(&cciss_pci_driver);
}
static void __exit cciss_cleanup(void)
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 3b0858c83897..b24fc0553ccf 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -13,8 +13,6 @@
#define IO_OK 0
#define IO_ERROR 1
-#define MAJOR_NR COMPAQ_CISS_MAJOR
-
struct ctlr_info;
typedef struct ctlr_info ctlr_info_t;
@@ -65,7 +63,6 @@ struct ctlr_info
unsigned long io_mem_addr;
unsigned long io_mem_length;
CfgTable_struct __iomem *cfgtable;
- unsigned int intr;
int interrupts_enabled;
int major;
int max_commands;
@@ -74,6 +71,13 @@ struct ctlr_info
int num_luns;
int highest_lun;
int usage_count; /* number of opens all all minor devices */
+# define DOORBELL_INT 0
+# define PERF_MODE_INT 1
+# define SIMPLE_MODE_INT 2
+# define MEMQ_MODE_INT 3
+ unsigned int intr[4];
+ unsigned int msix_vector;
+ unsigned int msi_vector;
// information about each logical volume
drive_info_struct drv[CISS_MAX_LUN];
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 2942d32280a5..9e35de05d5c5 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -714,7 +714,7 @@ cciss_scsi_detect(int ctlr)
((struct cciss_scsi_adapter_data_t *)
hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh;
sh->hostdata[0] = (unsigned long) hba[ctlr];
- sh->irq = hba[ctlr]->intr;
+ sh->irq = hba[ctlr]->intr[SIMPLE_MODE_INT];
sh->unique_id = sh->irq;
error = scsi_add_host(sh, &hba[ctlr]->pdev->dev);
if (error)
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index cf1822a6361c..862b9abac0ae 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -72,11 +72,11 @@ static ctlr_info_t *hba[MAX_CTLR];
static int eisa[8];
-#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
+#define NR_PRODUCTS ARRAY_SIZE(products)
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
- * access = Address of the struct of function pointers
+ * access = Address of the struct of function pointers
*/
static struct board_type products[] = {
{ 0x0040110E, "IDA", &smart1_access },
@@ -160,6 +160,7 @@ static int sendcmd(
static int ida_open(struct inode *inode, struct file *filep);
static int ida_release(struct inode *inode, struct file *filep);
static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io);
static void do_ida_request(request_queue_t *q);
@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = {
.open = ida_open,
.release = ida_release,
.ioctl = ida_ioctl,
+ .getgeo = ida_getgeo,
.revalidate_disk= ida_revalidate,
};
@@ -1036,7 +1038,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
complete_buffers(cmd->rq->bio, ok);
DBGPX(printk("Done with %p\n", cmd->rq););
- end_that_request_last(cmd->rq);
+ end_that_request_last(cmd->rq, ok ? 1 : -EIO);
}
/*
@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata)
h->misc_tflags = 0;
}
+static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ drv_info_t *drv = get_drv(bdev->bd_disk);
+
+ if (drv->cylinders) {
+ geo->heads = drv->heads;
+ geo->sectors = drv->sectors;
+ geo->cylinders = drv->cylinders;
+ } else {
+ geo->heads = 0xff;
+ geo->sectors = 0x3f;
+ geo->cylinders = drv->nr_blks / (0xff*0x3f);
+ }
+
+ return 0;
+}
+
/*
* ida_ioctl does some miscellaneous stuff like reporting drive geometry,
* setting readahead and submitting commands from userspace to the controller.
@@ -1133,27 +1152,10 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);
ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);
int error;
- int diskinfo[4];
- struct hd_geometry __user *geo = (struct hd_geometry __user *)arg;
ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg;
ida_ioctl_t *my_io;
switch(cmd) {
- case HDIO_GETGEO:
- if (drv->cylinders) {
- diskinfo[0] = drv->heads;
- diskinfo[1] = drv->sectors;
- diskinfo[2] = drv->cylinders;
- } else {
- diskinfo[0] = 0xff;
- diskinfo[1] = 0x3f;
- diskinfo[2] = drv->nr_blks / (0xff*0x3f);
- }
- put_user(diskinfo[0], &geo->heads);
- put_user(diskinfo[1], &geo->sectors);
- put_user(diskinfo[2], &geo->cylinders);
- put_user(get_start_sect(inode->i_bdev), &geo->start);
- return 0;
case IDAGETDRVINFO:
if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t)))
return -EFAULT;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index f7e765a1d313..d23b54332d7e 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -242,7 +242,6 @@ static int allowed_drive_mask = 0x33;
static int irqdma_allocated;
-#define LOCAL_END_REQUEST
#define DEVICE_NAME "floppy"
#include <linux/blkdev.h>
@@ -479,7 +478,6 @@ static struct floppy_struct floppy_type[32] = {
{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
};
-#define NUMBER(x) (sizeof(x) / sizeof(*(x)))
#define SECTSIZE (_FD_SECTSIZE(*floppy))
/* Auto-detection: Disk type used until the next media change occurs. */
@@ -2301,7 +2299,7 @@ static void floppy_end_request(struct request *req, int uptodate)
add_disk_randomness(req->rq_disk);
floppy_off((long)req->rq_disk->private_data);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
/* We're done with the request */
current_req = NULL;
@@ -3445,6 +3443,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
return 0;
}
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ int drive = (long)bdev->bd_disk->private_data;
+ int type = ITYPE(drive_state[drive].fd_device);
+ struct floppy_struct *g;
+ int ret;
+
+ ret = get_floppy_geometry(drive, type, &g);
+ if (ret)
+ return ret;
+
+ geo->heads = g->head;
+ geo->sectors = g->sect;
+ geo->cylinders = g->track;
+ return 0;
+}
+
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long param)
{
@@ -3474,23 +3489,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
cmd = FDEJECT;
}
- /* generic block device ioctls */
- switch (cmd) {
- /* the following have been inspired by the corresponding
- * code for other block devices. */
- struct floppy_struct *g;
- case HDIO_GETGEO:
- {
- struct hd_geometry loc;
- ECALL(get_floppy_geometry(drive, type, &g));
- loc.heads = g->head;
- loc.sectors = g->sect;
- loc.cylinders = g->track;
- loc.start = 0;
- return _COPYOUT(loc);
- }
- }
-
/* convert the old style command into a new style command */
if ((cmd & 0xff00) == 0x0200) {
ECALL(normalize_ioctl(&cmd, &size));
@@ -3645,7 +3643,7 @@ static void __init config_types(void)
const char *name = NULL;
static char temparea[32];
- if (type < NUMBER(default_drive_params)) {
+ if (type < ARRAY_SIZE(default_drive_params)) {
params = &default_drive_params[type].params;
if (type) {
name = default_drive_params[type].name;
@@ -3938,6 +3936,7 @@ static struct block_device_operations floppy_fops = {
.open = floppy_open,
.release = floppy_release,
.ioctl = fd_ioctl,
+ .getgeo = fd_getgeo,
.media_changed = check_floppy_change,
.revalidate_disk = floppy_revalidate,
};
@@ -3960,7 +3959,7 @@ static void __init register_devfs_entries(int drive)
{
int base_minor = (drive < 4) ? drive : (124 + drive);
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
int i = 0;
do {
int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
@@ -4218,7 +4217,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL;
- if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+ if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
return NULL;
*part = 0;
return get_disk(disks[drive]);
@@ -4570,7 +4569,7 @@ static void unregister_devfs_entries(int drive)
{
int i;
- if (UDP->cmos < NUMBER(default_drive_params)) {
+ if (UDP->cmos < ARRAY_SIZE(default_drive_params)) {
i = 0;
do {
devfs_remove("floppy/%d%s", drive,
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 96c664af8d06..5f6d1a5cce11 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -213,9 +213,9 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
struct address_space_operations *aops = mapping->a_ops;
pgoff_t index;
unsigned offset, bv_offs;
- int len, ret = 0;
+ int len, ret;
- down(&mapping->host->i_sem);
+ mutex_lock(&mapping->host->i_mutex);
index = pos >> PAGE_CACHE_SHIFT;
offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1);
bv_offs = bvec->bv_offset;
@@ -232,9 +232,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
page = grab_cache_page(mapping, index);
if (unlikely(!page))
goto fail;
- if (unlikely(aops->prepare_write(file, page, offset,
- offset + size)))
+ ret = aops->prepare_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
transfer_result = lo_do_transfer(lo, WRITE, page, offset,
bvec->bv_page, bv_offs, size, IV);
if (unlikely(transfer_result)) {
@@ -251,9 +257,15 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
kunmap_atomic(kaddr, KM_USER0);
}
flush_dcache_page(page);
- if (unlikely(aops->commit_write(file, page, offset,
- offset + size)))
+ ret = aops->commit_write(file, page, offset,
+ offset + size);
+ if (unlikely(ret)) {
+ if (ret == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
goto unlock;
+ }
if (unlikely(transfer_result))
goto unlock;
bv_offs += size;
@@ -264,8 +276,9 @@ static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
unlock_page(page);
page_cache_release(page);
}
+ ret = 0;
out:
- up(&mapping->host->i_sem);
+ mutex_unlock(&mapping->host->i_mutex);
return ret;
unlock:
unlock_page(page);
@@ -281,7 +294,7 @@ fail:
* This helper just factors out common code between do_lo_send_direct_write()
* and do_lo_send_write().
*/
-static inline int __do_lo_send_write(struct file *file,
+static int __do_lo_send_write(struct file *file,
u8 __user *buf, const int len, loff_t pos)
{
ssize_t bw;
@@ -514,12 +527,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
lo->lo_pending++;
loop_add_bio(lo, old_bio);
spin_unlock_irq(&lo->lo_lock);
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
return 0;
out:
if (lo->lo_pending == 0)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
@@ -580,23 +593,20 @@ static int loop_thread(void *data)
lo->lo_pending = 1;
/*
- * up sem, we are running
+ * complete it, we are running
*/
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
for (;;) {
int pending;
- /*
- * interruptible just to not contribute to load avg
- */
- if (down_interruptible(&lo->lo_bh_mutex))
+ if (wait_for_completion_interruptible(&lo->lo_bh_done))
continue;
spin_lock_irq(&lo->lo_lock);
/*
- * could be upped because of tear-down, not pending work
+ * could be completed because of tear-down, not pending work
*/
if (unlikely(!lo->lo_pending)) {
spin_unlock_irq(&lo->lo_lock);
@@ -619,7 +629,7 @@ static int loop_thread(void *data)
break;
}
- up(&lo->lo_sem);
+ complete(&lo->lo_done);
return 0;
}
@@ -830,7 +840,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
kernel_thread(loop_thread, lo, CLONE_KERNEL);
- down(&lo->lo_sem);
+ wait_for_completion(&lo->lo_done);
return 0;
out_putf:
@@ -896,10 +906,10 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_state = Lo_rundown;
lo->lo_pending--;
if (!lo->lo_pending)
- up(&lo->lo_bh_mutex);
+ complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- down(&lo->lo_sem);
+ wait_for_completion(&lo->lo_done);
lo->lo_backing_file = NULL;
@@ -1276,8 +1286,8 @@ static int __init loop_init(void)
if (!lo->lo_queue)
goto out_mem4;
init_MUTEX(&lo->lo_ctl_mutex);
- init_MUTEX_LOCKED(&lo->lo_sem);
- init_MUTEX_LOCKED(&lo->lo_bh_mutex);
+ init_completion(&lo->lo_done);
+ init_completion(&lo->lo_bh_done);
lo->lo_number = i;
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 9e268ddedfbd..6997d8e6bfb5 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -54,11 +54,15 @@
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
#include <net/sock.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
+#include <asm/system.h>
#include <asm/types.h>
#include <linux/nbd.h>
@@ -136,7 +140,7 @@ static void nbd_end_request(struct request *req)
spin_lock_irqsave(q->queue_lock, flags);
if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
spin_unlock_irqrestore(q->queue_lock, flags);
}
@@ -170,7 +174,6 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
- msg.msg_namelen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (send)
@@ -230,14 +233,6 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
request.len = htonl(size);
memcpy(request.handle, &req, sizeof(req));
- down(&lo->tx_lock);
-
- if (!sock || !lo->sock) {
- printk(KERN_ERR "%s: Attempted send on closed socket\n",
- lo->disk->disk_name);
- goto error_out;
- }
-
dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
lo->disk->disk_name, req,
nbdcmd_to_ascii(nbd_cmd(req)),
@@ -276,11 +271,9 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
}
}
}
- up(&lo->tx_lock);
return 0;
error_out:
- up(&lo->tx_lock);
return 1;
}
@@ -289,9 +282,14 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
struct request *req;
struct list_head *tmp;
struct request *xreq;
+ int err;
memcpy(&xreq, handle, sizeof(xreq));
+ err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq);
+ if (unlikely(err))
+ goto out;
+
spin_lock(&lo->queue_lock);
list_for_each(tmp, &lo->queue_head) {
req = list_entry(tmp, struct request, queuelist);
@@ -302,7 +300,11 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
return req;
}
spin_unlock(&lo->queue_lock);
- return NULL;
+
+ err = -ENOENT;
+
+out:
+ return ERR_PTR(err);
}
static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec)
@@ -331,7 +333,11 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
goto harderror;
}
req = nbd_find_request(lo, reply.handle);
- if (req == NULL) {
+ if (unlikely(IS_ERR(req))) {
+ result = PTR_ERR(req);
+ if (result != -ENOENT)
+ goto harderror;
+
printk(KERN_ERR "%s: Unexpected reply (%p)\n",
lo->disk->disk_name, reply.handle);
result = -EBADR;
@@ -395,19 +401,24 @@ static void nbd_clear_que(struct nbd_device *lo)
BUG_ON(lo->magic != LO_MAGIC);
- do {
- req = NULL;
- spin_lock(&lo->queue_lock);
- if (!list_empty(&lo->queue_head)) {
- req = list_entry(lo->queue_head.next, struct request, queuelist);
- list_del_init(&req->queuelist);
- }
- spin_unlock(&lo->queue_lock);
- if (req) {
- req->errors++;
- nbd_end_request(req);
- }
- } while (req);
+ /*
+ * Because we have set lo->sock to NULL under the tx_lock, all
+ * modifications to the list must have completed by now. For
+ * the same reason, the active_req must be NULL.
+ *
+ * As a consequence, we don't need to take the spin lock while
+ * purging the list here.
+ */
+ BUG_ON(lo->sock);
+ BUG_ON(lo->active_req);
+
+ while (!list_empty(&lo->queue_head)) {
+ req = list_entry(lo->queue_head.next, struct request,
+ queuelist);
+ list_del_init(&req->queuelist);
+ req->errors++;
+ nbd_end_request(req);
+ }
}
/*
@@ -435,11 +446,6 @@ static void do_nbd_request(request_queue_t * q)
BUG_ON(lo->magic != LO_MAGIC);
- if (!lo->file) {
- printk(KERN_ERR "%s: Request when not-ready\n",
- lo->disk->disk_name);
- goto error_out;
- }
nbd_cmd(req) = NBD_CMD_READ;
if (rq_data_dir(req) == WRITE) {
nbd_cmd(req) = NBD_CMD_WRITE;
@@ -453,32 +459,34 @@ static void do_nbd_request(request_queue_t * q)
req->errors = 0;
spin_unlock_irq(q->queue_lock);
- spin_lock(&lo->queue_lock);
-
- if (!lo->file) {
- spin_unlock(&lo->queue_lock);
- printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n",
- lo->disk->disk_name);
+ down(&lo->tx_lock);
+ if (unlikely(!lo->sock)) {
+ up(&lo->tx_lock);
+ printk(KERN_ERR "%s: Attempted send on closed socket\n",
+ lo->disk->disk_name);
req->errors++;
nbd_end_request(req);
spin_lock_irq(q->queue_lock);
continue;
}
- list_add(&req->queuelist, &lo->queue_head);
- spin_unlock(&lo->queue_lock);
+ lo->active_req = req;
if (nbd_send_req(lo, req) != 0) {
printk(KERN_ERR "%s: Request send failed\n",
lo->disk->disk_name);
- if (nbd_find_request(lo, (char *)&req) != NULL) {
- /* we still own req */
- req->errors++;
- nbd_end_request(req);
- } else /* we're racing with nbd_clear_que */
- printk(KERN_DEBUG "nbd: can't find req\n");
+ req->errors++;
+ nbd_end_request(req);
+ } else {
+ spin_lock(&lo->queue_lock);
+ list_add(&req->queuelist, &lo->queue_head);
+ spin_unlock(&lo->queue_lock);
}
+ lo->active_req = NULL;
+ up(&lo->tx_lock);
+ wake_up_all(&lo->active_wq);
+
spin_lock_irq(q->queue_lock);
continue;
@@ -529,17 +537,10 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
down(&lo->tx_lock);
lo->sock = NULL;
up(&lo->tx_lock);
- spin_lock(&lo->queue_lock);
file = lo->file;
lo->file = NULL;
- spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
- spin_lock(&lo->queue_lock);
- if (!list_empty(&lo->queue_head)) {
- printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n");
- error = -EBUSY;
- }
- spin_unlock(&lo->queue_lock);
+ BUG_ON(!list_empty(&lo->queue_head));
if (file)
fput(file);
return error;
@@ -598,24 +599,19 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
lo->sock = NULL;
}
up(&lo->tx_lock);
- spin_lock(&lo->queue_lock);
file = lo->file;
lo->file = NULL;
- spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name);
if (file)
fput(file);
return lo->harderror;
case NBD_CLEAR_QUE:
- down(&lo->tx_lock);
- if (lo->sock) {
- up(&lo->tx_lock);
- return 0; /* probably should be error, but that would
- * break "nbd-client -d", so just return 0 */
- }
- up(&lo->tx_lock);
- nbd_clear_que(lo);
+ /*
+ * This is for compatibility only. The queue is always cleared
+ * by NBD_DO_IT or NBD_CLEAR_SOCK.
+ */
+ BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
return 0;
case NBD_PRINT_DEBUG:
printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
@@ -688,6 +684,7 @@ static int __init nbd_init(void)
spin_lock_init(&nbd_dev[i].queue_lock);
INIT_LIST_HEAD(&nbd_dev[i].queue_head);
init_MUTEX(&nbd_dev[i].tx_lock);
+ init_waitqueue_head(&nbd_dev[i].active_wq);
nbd_dev[i].blksize = 1024;
nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */
disk->major = NBD_MAJOR;
diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig
index 17ff40561257..c0d2854dd097 100644
--- a/drivers/block/paride/Kconfig
+++ b/drivers/block/paride/Kconfig
@@ -4,11 +4,12 @@
# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
# PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option
# controls the choices given to the user ...
+# PARIDE only supports PC style parports. Tough for USB or other parports...
config PARIDE_PARPORT
tristate
depends on PARIDE!=n
- default m if PARPORT=m
- default y if PARPORT!=m
+ default m if PARPORT_PC=m
+ default y if PARPORT_PC!=m
comment "Parallel IDE high-level drivers"
depends on PARIDE
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index fa49d62626ba..62d2464c12f2 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file)
return 0;
}
+static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct pd_unit *disk = bdev->bd_disk->private_data;
+
+ if (disk->alt_geom) {
+ geo->heads = PD_LOG_HEADS;
+ geo->sectors = PD_LOG_SECTS;
+ geo->cylinders = disk->capacity / (geo->heads * geo->sectors);
+ } else {
+ geo->heads = disk->heads;
+ geo->sectors = disk->sectors;
+ geo->cylinders = disk->cylinders;
+ }
+
+ return 0;
+}
+
static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct pd_unit *disk = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
switch (cmd) {
case CDROMEJECT:
if (disk->access == 1)
pd_special_command(disk, pd_eject);
return 0;
- case HDIO_GETGEO:
- if (disk->alt_geom) {
- g.heads = PD_LOG_HEADS;
- g.sectors = PD_LOG_SECTS;
- g.cylinders = disk->capacity / (g.heads * g.sectors);
- } else {
- g.heads = disk->heads;
- g.sectors = disk->sectors;
- g.cylinders = disk->cylinders;
- }
- g.start = get_start_sect(inode->i_bdev);
- if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
- return -EFAULT;
- return 0;
default:
return -EINVAL;
}
@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = {
.open = pd_open,
.release = pd_release,
.ioctl = pd_ioctl,
+ .getgeo = pd_getgeo,
.media_changed = pd_check_media,
.revalidate_disk= pd_revalidate
};
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index e9746af29b9f..852b564e903a 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file);
static void do_pf_request(request_queue_t * q);
static int pf_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int pf_release(struct inode *inode, struct file *file);
@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = {
.open = pf_open,
.release = pf_release,
.ioctl = pf_ioctl,
+ .getgeo = pf_getgeo,
.media_changed = pf_check_media,
};
@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file)
return 0;
}
-static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *geo = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
- sector_t capacity;
-
- if (cmd == CDROMEJECT) {
- if (pf->access == 1) {
- pf_eject(pf);
- return 0;
- }
- return -EBUSY;
- }
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- capacity = get_capacity(pf->disk);
+ struct pf_unit *pf = bdev->bd_disk->private_data;
+ sector_t capacity = get_capacity(pf->disk);
+
if (capacity < PF_FD_MAX) {
- g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
- g.heads = PF_FD_HDS;
- g.sectors = PF_FD_SPT;
+ geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT);
+ geo->heads = PF_FD_HDS;
+ geo->sectors = PF_FD_SPT;
} else {
- g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
- g.heads = PF_HD_HDS;
- g.sectors = PF_HD_SPT;
+ geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT);
+ geo->heads = PF_HD_HDS;
+ geo->sectors = PF_HD_SPT;
}
- if (copy_to_user(geo, &g, sizeof(g)))
- return -EFAULT;
+
+ return 0;
+}
+
+static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct pf_unit *pf = inode->i_bdev->bd_disk->private_data;
+
+ if (cmd != CDROMEJECT)
+ return -EINVAL;
+
+ if (pf->access != 1)
+ return -EBUSY;
+ pf_eject(pf);
return 0;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index c0233efabeba..93affeeef7bd 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -247,7 +247,7 @@ static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node)
return rb_entry(n, struct pkt_rb_node, rb_node);
}
-static inline void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
+static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
{
rb_erase(&node->rb_node, &pd->bio_queue);
mempool_free(node, pd->rb_pool);
@@ -315,7 +315,7 @@ static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *nod
/*
* Add a bio to a single linked list defined by its head and tail pointers.
*/
-static inline void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
+static void pkt_add_list_last(struct bio *bio, struct bio **list_head, struct bio **list_tail)
{
bio->bi_next = NULL;
if (*list_tail) {
@@ -1955,9 +1955,12 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY)))
goto out;
+ if ((ret = bd_claim(pd->bdev, pd)))
+ goto out_putdev;
+
if ((ret = pkt_get_last_written(pd, &lba))) {
printk("pktcdvd: pkt_get_last_written failed\n");
- goto out_putdev;
+ goto out_unclaim;
}
set_capacity(pd->disk, lba << 2);
@@ -1967,7 +1970,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
q = bdev_get_queue(pd->bdev);
if (write) {
if ((ret = pkt_open_write(pd)))
- goto out_putdev;
+ goto out_unclaim;
/*
* Some CDRW drives can not handle writes larger than one packet,
* even if the size is a multiple of the packet size.
@@ -1982,13 +1985,15 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
}
if ((ret = pkt_set_segment_merging(pd, q)))
- goto out_putdev;
+ goto out_unclaim;
if (write)
printk("pktcdvd: %lukB available on disc\n", lba << 1);
return 0;
+out_unclaim:
+ bd_release(pd->bdev);
out_putdev:
blkdev_put(pd->bdev);
out:
@@ -2007,6 +2012,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
pkt_lock_door(pd, 0);
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
+ bd_release(pd->bdev);
blkdev_put(pd->bdev);
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 29d1518be72a..bea75f2cb211 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -43,6 +43,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/module.h>
+#include <linux/hdreg.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -81,8 +82,7 @@ static void (*current_int_handler) (u_int) = NULL;
static void ps2esdi_normal_interrupt_handler(u_int);
static void ps2esdi_initial_reset_int_handler(u_int);
static void ps2esdi_geometry_int_handler(u_int);
-static int ps2esdi_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg);
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
@@ -132,7 +132,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] =
static struct block_device_operations ps2esdi_fops =
{
.owner = THIS_MODULE,
- .ioctl = ps2esdi_ioctl,
+ .getgeo = ps2esdi_getgeo,
};
static struct gendisk *ps2esdi_gendisk[2];
@@ -1058,21 +1058,13 @@ static void dump_cmd_complete_status(u_int int_ret_code)
}
-static int ps2esdi_ioctl(struct inode *inode,
- struct file *file, u_int cmd, u_long arg)
+static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data;
- struct ps2esdi_geometry geom;
-
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- memset(&geom, 0, sizeof(geom));
- geom.heads = p->head;
- geom.sectors = p->sect;
- geom.cylinders = p->cyl;
- geom.start = get_start_sect(inode->i_bdev);
- if (copy_to_user((void __user *)arg, &geom, sizeof(geom)))
- return -EFAULT;
+ struct ps2esdi_i_struct *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->head;
+ geo->sectors = p->sect;
+ geo->cylinders = p->cyl;
return 0;
}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 68c60a5bcdab..ffd6abd6d5a0 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -154,7 +154,7 @@ static int ramdisk_commit_write(struct file *file, struct page *page,
/*
* ->writepage to the the blockdev's mapping has to redirty the page so that the
- * VM doesn't go and steal it. We return WRITEPAGE_ACTIVATE so that the VM
+ * VM doesn't go and steal it. We return AOP_WRITEPAGE_ACTIVATE so that the VM
* won't try to (pointlessly) write the page again for a while.
*
* Really, these pages should not be on the LRU at all.
@@ -165,7 +165,7 @@ static int ramdisk_writepage(struct page *page, struct writeback_control *wbc)
make_page_uptodate(page);
SetPageDirty(page);
if (wbc->for_reclaim)
- return WRITEPAGE_ACTIVATE;
+ return AOP_WRITEPAGE_ACTIVATE;
unlock_page(page);
return 0;
}
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index af7cb2bfd670..01f042f6f1c4 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -1083,23 +1083,33 @@ static int swim3_add_device(struct device_node *swim)
{
struct device_node *mediabay;
struct floppy_state *fs = &floppy_states[floppy_count];
+ struct resource res_reg, res_dma;
- if (swim->n_addrs < 2)
- {
- printk(KERN_INFO "swim3: expecting 2 addrs (n_addrs:%d, n_intrs:%d)\n",
- swim->n_addrs, swim->n_intrs);
+ if (of_address_to_resource(swim, 0, &res_reg) ||
+ of_address_to_resource(swim, 1, &res_dma)) {
+ printk(KERN_ERR "swim3: Can't get addresses\n");
return -EINVAL;
}
-
- if (swim->n_intrs < 2)
- {
- printk(KERN_INFO "swim3: expecting 2 intrs (n_addrs:%d, n_intrs:%d)\n",
- swim->n_addrs, swim->n_intrs);
+ if (request_mem_region(res_reg.start, res_reg.end - res_reg.start + 1,
+ " (reg)") == NULL) {
+ printk(KERN_ERR "swim3: Can't request register space\n");
+ return -EINVAL;
+ }
+ if (request_mem_region(res_dma.start, res_dma.end - res_dma.start + 1,
+ " (dma)") == NULL) {
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ printk(KERN_ERR "swim3: Can't request DMA space\n");
return -EINVAL;
}
- if (!request_OF_resource(swim, 0, NULL)) {
- printk(KERN_INFO "swim3: can't request IO resource !\n");
+ if (swim->n_intrs < 2) {
+ printk(KERN_INFO "swim3: expecting 2 intrs (n_intrs:%d)\n",
+ swim->n_intrs);
+ release_mem_region(res_reg.start,
+ res_reg.end - res_reg.start + 1);
+ release_mem_region(res_dma.start,
+ res_dma.end - res_dma.start + 1);
return -EINVAL;
}
@@ -1110,10 +1120,8 @@ static int swim3_add_device(struct device_node *swim)
memset(fs, 0, sizeof(*fs));
spin_lock_init(&fs->lock);
fs->state = idle;
- fs->swim3 = (struct swim3 __iomem *)
- ioremap(swim->addrs[0].address, 0x200);
- fs->dma = (struct dbdma_regs __iomem *)
- ioremap(swim->addrs[1].address, 0x200);
+ fs->swim3 = (struct swim3 __iomem *)ioremap(res_reg.start, 0x200);
+ fs->dma = (struct dbdma_regs __iomem *)ioremap(res_dma.start, 0x200);
fs->swim3_intr = swim->intrs[0].line;
fs->dma_intr = swim->intrs[1].line;
fs->cur_cyl = -1;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 1ded3b433459..2ae08b343b93 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -27,8 +27,8 @@
#include <linux/time.h>
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
+#include <linux/completion.h>
#include <asm/io.h>
-#include <asm/semaphore.h>
#include <asm/uaccess.h>
#if 0
@@ -303,7 +303,7 @@ struct carm_host {
struct work_struct fsm_task;
- struct semaphore probe_sem;
+ struct completion probe_comp;
};
struct carm_response {
@@ -407,8 +407,7 @@ struct carm_array_info {
static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static void carm_remove_one (struct pci_dev *pdev);
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg);
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static struct pci_device_id carm_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
static struct block_device_operations carm_bd_ops = {
.owner = THIS_MODULE,
- .ioctl = carm_bdev_ioctl,
+ .getgeo = carm_bdev_getgeo,
};
static unsigned int carm_host_id;
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg)
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- void __user *usermem = (void __user *) arg;
- struct carm_port *port = ino->i_bdev->bd_disk->private_data;
- struct hd_geometry geom;
+ struct carm_port *port = bdev->bd_disk->private_data;
- switch (cmd) {
- case HDIO_GETGEO:
- if (!usermem)
- return -EINVAL;
-
- geom.heads = (u8) port->dev_geom_head;
- geom.sectors = (u8) port->dev_geom_sect;
- geom.cylinders = port->dev_geom_cyl;
- geom.start = get_start_sect(ino->i_bdev);
-
- if (copy_to_user(usermem, &geom, sizeof(geom)))
- return -EFAULT;
- return 0;
-
- default:
- break;
- }
-
- return -EOPNOTSUPP;
+ geo->heads = (u8) port->dev_geom_head;
+ geo->sectors = (u8) port->dev_geom_sect;
+ geo->cylinders = port->dev_geom_cyl;
+ return 0;
}
static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
@@ -770,7 +751,7 @@ static inline void carm_end_request_queued(struct carm_host *host,
rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
assert(rc == 0);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
rc = carm_put_request(host, crq);
assert(rc == 0);
@@ -1365,7 +1346,7 @@ static void carm_fsm_task (void *_data)
}
case HST_PROBE_FINISHED:
- up(&host->probe_sem);
+ complete(&host->probe_comp);
break;
case HST_ERROR:
@@ -1641,7 +1622,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->flags = pci_dac ? FL_DAC : 0;
spin_lock_init(&host->lock);
INIT_WORK(&host->fsm_task, carm_fsm_task, host);
- init_MUTEX_LOCKED(&host->probe_sem);
+ init_completion(&host->probe_comp);
for (i = 0; i < ARRAY_SIZE(host->req); i++)
host->req[i].tag = i;
@@ -1710,8 +1691,8 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_free_irq;
- DPRINTK("waiting for probe_sem\n");
- down(&host->probe_sem);
+ DPRINTK("waiting for probe_comp\n");
+ wait_for_completion(&host->probe_comp);
printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
@@ -1774,7 +1755,7 @@ static void carm_remove_one (struct pci_dev *pdev)
static int __init carm_init(void)
{
- return pci_module_init(&carm_driver);
+ return pci_register_driver(&carm_driver);
}
static void __exit carm_exit(void)
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index bfb23d543ff7..a05fe5843e6c 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -9,7 +9,6 @@
*
* TODO (sorted by decreasing priority)
* -- Kill first_open (Al Viro fixed the block layer now)
- * -- Do resets with usb_device_reset (needs a thread context, use khubd)
* -- set readonly flag for CDs, set removable flag for CF readers
* -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
* -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
@@ -29,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/timer.h>
@@ -107,16 +107,6 @@
*/
/*
- * Definitions which have to be scattered once we understand the layout better.
- */
-
-/* Transport (despite PR in the name) */
-#define US_PR_BULK 0x50 /* bulk only */
-
-/* Protocol */
-#define US_SC_SCSI 0x06 /* Transparent */
-
-/*
* This many LUNs per USB device.
* Every one of them takes a host, see UB_MAX_HOSTS.
*/
@@ -125,7 +115,7 @@
/*
*/
-#define UB_MINORS_PER_MAJOR 8
+#define UB_PARTS_PER_LUN 8
#define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */
@@ -245,6 +235,13 @@ struct ub_scsi_cmd {
void *back;
};
+struct ub_request {
+ struct request *rq;
+ unsigned int current_try;
+ unsigned int nsg; /* sgv[nsg] */
+ struct scatterlist sgv[UB_MAX_REQ_SG];
+};
+
/*
*/
struct ub_capacity {
@@ -340,6 +337,8 @@ struct ub_lun {
int readonly;
int first_open; /* Kludge. See ub_bd_open. */
+ struct ub_request urq;
+
/* Use Ingo's mempool if or when we have more than one command. */
/*
* Currently we never need more than one command for the whole device.
@@ -360,6 +359,7 @@ struct ub_dev {
atomic_t poison; /* The USB device is disconnected */
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
+ int reset; /* Reset is running */
unsigned int tagcnt;
char name[12];
struct usb_device *dev;
@@ -387,6 +387,9 @@ struct ub_dev {
struct bulk_cs_wrap work_bcs;
struct usb_ctrlrequest work_cr;
+ struct work_struct reset_work;
+ wait_queue_head_t reset_wait;
+
int sg_stat[6];
struct ub_scsi_trace tr;
};
@@ -395,12 +398,14 @@ struct ub_dev {
*/
static void ub_cleanup(struct ub_dev *sc);
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_lun *lun,
- struct ub_scsi_cmd *cmd, struct request *rq);
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct ub_request *urq);
+static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct ub_request *urq);
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_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
static void ub_scsi_action(unsigned long _dev);
@@ -415,6 +420,8 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
+static void ub_reset_enter(struct ub_dev *sc);
+static void ub_reset_task(void *arg);
static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret);
@@ -422,13 +429,18 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
/*
*/
+#ifdef CONFIG_USB_LIBUSUAL
+
+#define ub_usb_ids storage_usb_ids
+#else
+
static struct usb_device_id ub_usb_ids[] = {
- // { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) }, /* SDDR-31 */
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
{ }
};
MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
/*
* Find me a way to identify "next free minor" for add_disk(),
@@ -522,6 +534,9 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&sc->lock, flags);
cnt += sprintf(page + cnt,
+ "poison %d reset %d\n",
+ atomic_read(&sc->poison), sc->reset);
+ cnt += sprintf(page + cnt,
"qlen %d qmax %d\n",
sc->cmd_queue.qlen, sc->cmd_queue.qmax);
cnt += sprintf(page + cnt,
@@ -770,7 +785,8 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
{
struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
- int rc;
+ struct ub_request *urq;
+ int n_elem;
if (atomic_read(&sc->poison) || lun->changed) {
blkdev_dequeue_request(rq);
@@ -778,65 +794,70 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
return 0;
}
+ if (lun->urq.rq != NULL)
+ return -1;
if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
blkdev_dequeue_request(rq);
+
+ urq = &lun->urq;
+ memset(urq, 0, sizeof(struct ub_request));
+ urq->rq = rq;
+
+ /*
+ * get scatterlist from block layer
+ */
+ n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
+ if (n_elem < 0) {
+ printk(KERN_INFO "%s: failed request map (%d)\n",
+ lun->name, n_elem); /* P3 */
+ goto drop;
+ }
+ if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
+ printk(KERN_WARNING "%s: request with %d segments\n",
+ lun->name, n_elem);
+ goto drop;
+ }
+ urq->nsg = n_elem;
+ sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
+
if (blk_pc_request(rq)) {
- rc = ub_cmd_build_packet(sc, lun, cmd, rq);
+ ub_cmd_build_packet(sc, lun, cmd, urq);
} else {
- rc = ub_cmd_build_block(sc, lun, cmd, rq);
- }
- if (rc != 0) {
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- return 0;
+ ub_cmd_build_block(sc, lun, cmd, urq);
}
cmd->state = UB_CMDST_INIT;
cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
- cmd->back = rq;
+ cmd->back = urq;
cmd->tag = sc->tagcnt++;
- if (ub_submit_scsi(sc, cmd) != 0) {
- ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
- return 0;
- }
+ if (ub_submit_scsi(sc, cmd) != 0)
+ goto drop;
return 0;
+
+drop:
+ ub_put_cmd(lun, cmd);
+ ub_end_rq(rq, 0);
+ return 0;
}
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
- struct ub_scsi_cmd *cmd, struct request *rq)
+static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct ub_request *urq)
{
- int ub_dir;
- int n_elem;
+ struct request *rq = urq->rq;
unsigned int block, nblks;
if (rq_data_dir(rq) == WRITE)
- ub_dir = UB_DIR_WRITE;
+ cmd->dir = UB_DIR_WRITE;
else
- ub_dir = UB_DIR_READ;
- cmd->dir = ub_dir;
+ 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; /* request with no s/g entries? */
- }
- 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 < 5 ? n_elem : 5]++;
+ cmd->nsg = urq->nsg;
+ memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
/*
* build the command
@@ -847,7 +868,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
block = rq->sector >> lun->capacity.bshift;
nblks = rq->nr_sectors >> lun->capacity.bshift;
- cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
+ cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
cmd->cdb[2] = block >> 24;
cmd->cdb[3] = block >> 16;
@@ -858,14 +879,12 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb_len = 10;
cmd->len = rq->nr_sectors * 512;
-
- return 0;
}
-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_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct ub_request *urq)
{
- int n_elem;
+ struct request *rq = urq->rq;
if (rq->data_len == 0) {
cmd->dir = UB_DIR_NONE;
@@ -874,40 +893,26 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
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;
- }
- 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 < 5 ? n_elem : 5]++;
+ cmd->nsg = urq->nsg;
+ memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
cmd->cdb_len = rq->cmd_len;
cmd->len = rq->data_len;
-
- return 0;
}
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 ub_request *urq = cmd->back;
+ struct request *rq;
int uptodate;
+ rq = urq->rq;
+
if (cmd->error == 0) {
uptodate = 1;
@@ -928,9 +933,16 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rq->errors = SAM_STAT_CHECK_CONDITION;
else
rq->errors = DID_ERROR << 16;
+ } else {
+ if (cmd->error == -EIO) {
+ if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
+ return;
+ }
}
}
+ urq->rq = NULL;
+
ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
blk_start_queue(lun->disk->queue);
@@ -938,11 +950,43 @@ 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)
{
- int rc;
+ end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+ end_that_request_last(rq, uptodate);
+}
+
+static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_request *urq, struct ub_scsi_cmd *cmd)
+{
+
+ if (atomic_read(&sc->poison))
+ return -ENXIO;
+
+ ub_reset_enter(sc);
- rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
- // assert(rc == 0);
- end_that_request_last(rq);
+ if (urq->current_try >= 3)
+ return -EIO;
+ urq->current_try++;
+ /* P3 */ printk("%s: dir %c len/act %d/%d "
+ "[sense %x %02x %02x] retry %d\n",
+ sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
+ cmd->key, cmd->asc, cmd->ascq, urq->current_try);
+
+ memset(cmd, 0, sizeof(struct ub_scsi_cmd));
+ ub_cmd_build_block(sc, lun, cmd, urq);
+
+ cmd->state = UB_CMDST_INIT;
+ cmd->lun = lun;
+ cmd->done = ub_rw_cmd_done;
+ cmd->back = urq;
+
+ cmd->tag = sc->tagcnt++;
+
+#if 0 /* Wasteful */
+ return ub_submit_scsi(sc, cmd);
+#else
+ ub_cmdq_add(sc, cmd);
+ return 0;
+#endif
}
/*
@@ -1075,7 +1119,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
struct ub_scsi_cmd *cmd;
int rc;
- while ((cmd = ub_cmdq_peek(sc)) != NULL) {
+ while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) {
if (cmd->state == UB_CMDST_DONE) {
ub_cmdq_pop(sc);
(*cmd->done)(sc, cmd);
@@ -1098,11 +1142,12 @@ 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 len;
int rc;
if (atomic_read(&sc->poison)) {
- /* A little too simplistic, I feel... */
- goto Bad_End;
+ ub_state_done(sc, cmd, -ENODEV);
+ return;
}
if (cmd->state == UB_CMDST_CLEAR) {
@@ -1110,7 +1155,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
/*
* STALL while clearning STALL.
* The control pipe clears itself - nothing to do.
- * XXX Might try to reset the device here and retry.
*/
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
@@ -1129,11 +1173,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else if (cmd->state == UB_CMDST_CLR2STS) {
if (urb->status == -EPIPE) {
- /*
- * STALL while clearning STALL.
- * The control pipe clears itself - nothing to do.
- * XXX Might try to reset the device here and retry.
- */
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
goto Bad_End;
@@ -1151,11 +1190,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else if (cmd->state == UB_CMDST_CLRRS) {
if (urb->status == -EPIPE) {
- /*
- * STALL while clearning STALL.
- * The control pipe clears itself - nothing to do.
- * XXX Might try to reset the device here and retry.
- */
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
goto Bad_End;
@@ -1172,7 +1206,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_state_stat_counted(sc, cmd);
} else if (cmd->state == UB_CMDST_CMD) {
- if (urb->status == -EPIPE) {
+ switch (urb->status) {
+ case 0:
+ break;
+ case -EOVERFLOW:
+ goto Bad_End;
+ case -EPIPE:
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
@@ -1182,17 +1221,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
*/
- goto Bad_End;
+ ub_state_done(sc, cmd, rc);
+ return;
}
cmd->state = UB_CMDST_CLEAR;
ub_cmdtr_state(sc, cmd);
return;
- }
- if (urb->status != 0) {
+ case -ESHUTDOWN: /* unplug */
+ case -EILSEQ: /* unplug timeout on uhci */
+ ub_state_done(sc, cmd, -ENODEV);
+ return;
+ default:
goto Bad_End;
}
if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
- /* XXX Must do reset here to unconfuse the device */
goto Bad_End;
}
@@ -1211,11 +1253,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_NOTICE "%s: "
"unable to submit clear (%d)\n",
sc->name, rc);
- /*
- * This is typically ENOMEM or some other such shit.
- * Retrying is pointless. Just do Bad End on it...
- */
- goto Bad_End;
+ ub_state_done(sc, cmd, rc);
+ return;
}
cmd->state = UB_CMDST_CLR2STS;
ub_cmdtr_state(sc, cmd);
@@ -1224,14 +1263,50 @@ 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... */
ub_state_stat(sc, cmd);
return;
}
- if (urb->status != 0)
- goto Bad_End;
+
+ if (cmd->dir == UB_DIR_WRITE) {
+ /*
+ * Do not continue writes in case of a failure.
+ * Doing so would cause sectors to be mixed up,
+ * which is worse than sectors lost.
+ *
+ * We must try to read the CSW, or many devices
+ * get confused.
+ */
+ len = urb->actual_length;
+ if (urb->status != 0 ||
+ len != cmd->sgv[cmd->current_sg].length) {
+ cmd->act_len += len;
+ ub_cmdtr_act_len(sc, cmd);
+
+ cmd->error = -EIO;
+ ub_state_stat(sc, cmd);
+ return;
+ }
+
+ } else {
+ /*
+ * If an error occurs on read, we record it, and
+ * continue to fetch data in order to avoid bubble.
+ *
+ * As a small shortcut, we stop if we detect that
+ * a CSW mixed into data.
+ */
+ if (urb->status != 0)
+ cmd->error = -EIO;
+
+ len = urb->actual_length;
+ if (urb->status != 0 ||
+ len != cmd->sgv[cmd->current_sg].length) {
+ if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN)
+ goto Bad_End;
+ }
+ }
cmd->act_len += urb->actual_length;
ub_cmdtr_act_len(sc, cmd);
@@ -1249,11 +1324,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_NOTICE "%s: "
"unable to submit clear (%d)\n",
sc->name, rc);
- /*
- * This is typically ENOMEM or some other such shit.
- * Retrying is pointless. Just do Bad End on it...
- */
- goto Bad_End;
+ ub_state_done(sc, cmd, rc);
+ return;
}
/*
@@ -1266,14 +1338,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_cmdtr_state(sc, cmd);
return;
}
- if (urb->status == -EOVERFLOW) {
- /*
- * XXX We are screwed here. Retrying is pointless,
- * because the pipelined data will not get in until
- * we read with a big enough buffer. We must reset XXX.
- */
- goto Bad_End;
- }
+
+ /* Catch everything, including -EOVERFLOW and other nasties. */
if (urb->status != 0)
goto Bad_End;
@@ -1319,15 +1385,15 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
- rc = le32_to_cpu(bcs->Residue);
- if (rc != cmd->len - cmd->act_len) {
+ len = le32_to_cpu(bcs->Residue);
+ if (len != cmd->len - cmd->act_len) {
/*
* It is all right to transfer less, the caller has
* to check. But it's not all right if the device
* counts disagree with our counts.
*/
/* P3 */ printk("%s: resid %d len %d act %d\n",
- sc->name, rc, cmd->len, cmd->act_len);
+ sc->name, len, cmd->len, cmd->act_len);
goto Bad_End;
}
@@ -1338,13 +1404,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_state_sense(sc, cmd);
return;
case US_BULK_STAT_PHASE:
- /* XXX We must reset the transport here */
/* P3 */ printk("%s: status PHASE\n", sc->name);
goto Bad_End;
default:
printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
sc->name, bcs->Status);
- goto Bad_End;
+ ub_state_done(sc, cmd, -EINVAL);
+ return;
}
/* Not zeroing error to preserve a babble indicator */
@@ -1364,7 +1430,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_WARNING "%s: "
"wrong command state %d\n",
sc->name, cmd->state);
- goto Bad_End;
+ ub_state_done(sc, cmd, -EINVAL);
+ return;
}
return;
@@ -1612,6 +1679,93 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
}
/*
+ * Reset management
+ */
+
+static void ub_reset_enter(struct ub_dev *sc)
+{
+
+ if (sc->reset) {
+ /* This happens often on multi-LUN devices. */
+ return;
+ }
+ sc->reset = 1;
+
+#if 0 /* Not needed because the disconnect waits for us. */
+ unsigned long flags;
+ spin_lock_irqsave(&ub_lock, flags);
+ sc->openc++;
+ spin_unlock_irqrestore(&ub_lock, flags);
+#endif
+
+#if 0 /* We let them stop themselves. */
+ struct list_head *p;
+ struct ub_lun *lun;
+ list_for_each(p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ blk_stop_queue(lun->disk->queue);
+ }
+#endif
+
+ schedule_work(&sc->reset_work);
+}
+
+static void ub_reset_task(void *arg)
+{
+ struct ub_dev *sc = arg;
+ unsigned long flags;
+ struct list_head *p;
+ struct ub_lun *lun;
+ int lkr, rc;
+
+ if (!sc->reset) {
+ printk(KERN_WARNING "%s: Running reset unrequested\n",
+ sc->name);
+ return;
+ }
+
+ if (atomic_read(&sc->poison)) {
+ printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
+ sc->name); /* P3 This floods. Remove soon. XXX */
+ } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
+ printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
+ sc->name); /* P3 This floods. Remove soon. XXX */
+ } else {
+ if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
+ printk(KERN_NOTICE
+ "%s: usb_lock_device_for_reset failed (%d)\n",
+ sc->name, lkr);
+ } else {
+ rc = usb_reset_device(sc->dev);
+ if (rc < 0) {
+ printk(KERN_NOTICE "%s: "
+ "usb_lock_device_for_reset failed (%d)\n",
+ sc->name, rc);
+ }
+
+ if (lkr)
+ usb_unlock_device(sc->dev);
+ }
+ }
+
+ /*
+ * In theory, no commands can be running while reset is active,
+ * so nobody can ask for another reset, and so we do not need any
+ * queues of resets or anything. We do need a spinlock though,
+ * to interact with block layer.
+ */
+ spin_lock_irqsave(&sc->lock, flags);
+ sc->reset = 0;
+ tasklet_schedule(&sc->tasklet);
+ list_for_each(p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ blk_start_queue(lun->disk->queue);
+ }
+ wake_up(&sc->reset_wait);
+ spin_unlock_irqrestore(&sc->lock, flags);
+}
+
+/*
* This is called from a process context.
*/
static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
@@ -2146,7 +2300,7 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
if (ep_in == NULL || ep_out == NULL) {
printk(KERN_NOTICE "%s: failed endpoint check\n",
sc->name);
- return -EIO;
+ return -ENODEV;
}
/* Calculate and store the pipe values */
@@ -2172,6 +2326,9 @@ static int ub_probe(struct usb_interface *intf,
int rc;
int i;
+ if (usb_usual_check_type(dev_id, USB_US_TYPE_UB))
+ return -ENXIO;
+
rc = -ENOMEM;
if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
goto err_core;
@@ -2181,6 +2338,8 @@ static int ub_probe(struct usb_interface *intf,
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
+ INIT_WORK(&sc->reset_work, ub_reset_task, sc);
+ init_waitqueue_head(&sc->reset_wait);
init_timer(&sc->work_timer);
sc->work_timer.data = (unsigned long) sc;
@@ -2201,7 +2360,8 @@ static int ub_probe(struct usb_interface *intf,
/* XXX Verify that we can handle the device (from descriptors) */
- ub_get_pipes(sc, sc->dev, intf);
+ if (ub_get_pipes(sc, sc->dev, intf) != 0)
+ goto err_dev_desc;
if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
goto err_diag;
@@ -2272,6 +2432,7 @@ static int ub_probe(struct usb_interface *intf,
/* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
err_diag:
+err_dev_desc:
usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
@@ -2309,14 +2470,14 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
ub_revalidate(sc, lun);
rc = -ENOMEM;
- if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
+ if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
goto err_diskalloc;
lun->disk = disk;
sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
disk->major = UB_MAJOR;
- disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
+ disk->first_minor = lun->id * UB_PARTS_PER_LUN;
disk->fops = &ub_bd_fops;
disk->private_data = lun;
disk->driverfs_dev = &sc->intf->dev;
@@ -2380,6 +2541,11 @@ static void ub_disconnect(struct usb_interface *intf)
atomic_set(&sc->poison, 1);
/*
+ * Wait for reset to end, if any.
+ */
+ wait_event(sc->reset_wait, !sc->reset);
+
+ /*
* Blow away queued commands.
*
* Actually, this never works, because before we get here
@@ -2392,7 +2558,7 @@ static void ub_disconnect(struct usb_interface *intf)
{
struct ub_scsi_cmd *cmd;
int cnt = 0;
- while ((cmd = ub_cmdq_pop(sc)) != NULL) {
+ while ((cmd = ub_cmdq_peek(sc)) != NULL) {
cmd->error = -ENOTCONN;
cmd->state = UB_CMDST_DONE;
ub_cmdtr_state(sc, cmd);
@@ -2461,7 +2627,6 @@ static void ub_disconnect(struct usb_interface *intf)
}
static struct usb_driver ub_driver = {
- .owner = THIS_MODULE,
.name = "ub",
.probe = ub_probe,
.disconnect = ub_disconnect,
@@ -2479,6 +2644,7 @@ static int __init ub_init(void)
if ((rc = usb_register(&ub_driver)) != 0)
goto err_register;
+ usb_usual_set_present(USB_US_TYPE_UB);
return 0;
err_register:
@@ -2494,6 +2660,7 @@ static void __exit ub_exit(void)
devfs_remove(DEVFS_NAME);
unregister_blkdev(UB_MAJOR, DRV_NAME);
+ usb_usual_clear_present(USB_US_TYPE_UB);
}
module_init(ub_init);
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 0f48301342da..a3614e6a68d0 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk)
set_capacity(disk, card->mm_size << 1);
return 0;
}
-/*
------------------------------------------------------------------------------------
--- mm_ioctl
------------------------------------------------------------------------------------
-*/
-static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
+
+static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- if (cmd == HDIO_GETGEO) {
- struct cardinfo *card = i->i_bdev->bd_disk->private_data;
- int size = card->mm_size * (1024 / MM_HARDSECT);
- struct hd_geometry geo;
- /*
- * get geometry: we have to fake one... trim the size to a
- * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
- * whatever cylinders.
- */
- geo.heads = 64;
- geo.sectors = 32;
- geo.start = get_start_sect(i->i_bdev);
- geo.cylinders = size / (geo.heads * geo.sectors);
-
- if (copy_to_user((void __user *) arg, &geo, sizeof(geo)))
- return -EFAULT;
- return 0;
- }
+ struct cardinfo *card = bdev->bd_disk->private_data;
+ int size = card->mm_size * (1024 / MM_HARDSECT);
- return -EINVAL;
+ /*
+ * get geometry: we have to fake one... trim the size to a
+ * multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
+ * whatever cylinders.
+ */
+ geo->heads = 64;
+ geo->sectors = 32;
+ geo->cylinders = size / (geo->heads * geo->sectors);
+ return 0;
}
+
/*
-----------------------------------------------------------------------------------
-- mm_check_change
@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk)
*/
static struct block_device_operations mm_fops = {
.owner = THIS_MODULE,
- .ioctl = mm_ioctl,
+ .getgeo = mm_getgeo,
.revalidate_disk= mm_revalidate,
.media_changed = mm_check_change,
};
@@ -1185,7 +1174,7 @@ static int __init mm_init(void)
printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n");
- retval = pci_module_init(&mm_pci_driver);
+ retval = pci_register_driver(&mm_pci_driver);
if (retval)
return -ENOMEM;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index 2d518aa2720a..f63e07bd9f9c 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil)
/* External ioctl entry point.
*/
-static int viodasd_ioctl(struct inode *ino, struct file *fil,
- unsigned int cmd, unsigned long arg)
+static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- unsigned char sectors;
- unsigned char heads;
- unsigned short cylinders;
- struct hd_geometry *geo;
- struct gendisk *gendisk;
- struct viodasd_device *d;
+ struct gendisk *disk = bdev->bd_disk;
+ struct viodasd_device *d = disk->private_data;
- switch (cmd) {
- case HDIO_GETGEO:
- geo = (struct hd_geometry *)arg;
- if (geo == NULL)
- return -EINVAL;
- if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo)))
- return -EFAULT;
- gendisk = ino->i_bdev->bd_disk;
- d = gendisk->private_data;
- sectors = d->sectors;
- if (sectors == 0)
- sectors = 32;
- heads = d->tracks;
- if (heads == 0)
- heads = 64;
- cylinders = d->cylinders;
- if (cylinders == 0)
- cylinders = get_capacity(gendisk) / (sectors * heads);
- if (__put_user(sectors, &geo->sectors) ||
- __put_user(heads, &geo->heads) ||
- __put_user(cylinders, &geo->cylinders) ||
- __put_user(get_start_sect(ino->i_bdev), &geo->start))
- return -EFAULT;
- return 0;
- }
+ geo->sectors = d->sectors ? d->sectors : 0;
+ geo->heads = d->tracks ? d->tracks : 64;
+ geo->cylinders = d->cylinders ? d->cylinders :
+ get_capacity(disk) / (geo->cylinders * geo->heads);
- return -EINVAL;
+ return 0;
}
/*
@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = {
.owner = THIS_MODULE,
.open = viodasd_open,
.release = viodasd_release,
- .ioctl = viodasd_ioctl,
+ .getgeo = viodasd_getgeo,
};
/*
@@ -305,7 +279,7 @@ static void viodasd_end_request(struct request *req, int uptodate,
if (end_that_request_first(req, uptodate, num_sectors))
return;
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
/*
@@ -319,6 +293,7 @@ static int send_request(struct request *req)
u16 viocmd;
HvLpEvent_Rc hvrc;
struct vioblocklpevent *bevent;
+ struct HvLpEvent *hev;
struct scatterlist sg[VIOMAXBLOCKDMA];
int sgindex;
int statindex;
@@ -373,22 +348,19 @@ static int send_request(struct request *req)
* token so we can match the response up later
*/
memset(bevent, 0, sizeof(struct vioblocklpevent));
- bevent->event.xFlags.xValid = 1;
- bevent->event.xFlags.xFunction = HvLpEvent_Function_Int;
- bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
- bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
- bevent->event.xType = HvLpEvent_Type_VirtualIo;
- bevent->event.xSubtype = viocmd;
- bevent->event.xSourceLp = HvLpConfig_getLpIndex();
- bevent->event.xTargetLp = viopath_hostLp;
- bevent->event.xSizeMinus1 =
+ hev = &bevent->event;
+ hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK |
+ HV_LP_EVENT_INT;
+ hev->xType = HvLpEvent_Type_VirtualIo;
+ hev->xSubtype = viocmd;
+ hev->xSourceLp = HvLpConfig_getLpIndex();
+ hev->xTargetLp = viopath_hostLp;
+ hev->xSizeMinus1 =
offsetof(struct vioblocklpevent, u.rw_data.dma_info) +
(sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1;
- bevent->event.xSourceInstanceId =
- viopath_sourceinst(viopath_hostLp);
- bevent->event.xTargetInstanceId =
- viopath_targetinst(viopath_hostLp);
- bevent->event.xCorrelationToken = (u64)req;
+ hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp);
+ hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp);
+ hev->xCorrelationToken = (u64)req;
bevent->version = VIOVERSION;
bevent->disk = DEVICE_NO(d);
bevent->u.rw_data.offset = start;
@@ -675,10 +647,10 @@ static void handle_block_event(struct HvLpEvent *event)
/* Notification that a partition went away! */
return;
/* First, we should NEVER get an int here...only acks */
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
printk(VIOD_KERN_WARNING
"Yikes! got an int in viodasd event handler!\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
@@ -721,7 +693,7 @@ static void handle_block_event(struct HvLpEvent *event)
default:
printk(VIOD_KERN_WARNING "invalid subtype!");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 68b6d7b154cf..cbce7c5e9445 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock);
static struct gendisk *xd_gendisk[2];
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo);
+
static struct block_device_operations xd_fops = {
.owner = THIS_MODULE,
.ioctl = xd_ioctl,
+ .getgeo = xd_getgeo,
};
static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
@@ -276,11 +279,11 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address)
return(1);
}
- for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) {
+ for (i = 0; i < ARRAY_SIZE(xd_bases); i++) {
void __iomem *p = ioremap(xd_bases[i], 0x2000);
if (!p)
continue;
- for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) {
+ for (j = 1; j < ARRAY_SIZE(xd_sigs); j++) {
const char *s = xd_sigs[j].string;
if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) {
*controller = j;
@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q)
}
}
+static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ XD_INFO *p = bdev->bd_disk->private_data;
+
+ geo->heads = p->heads;
+ geo->sectors = p->sectors;
+ geo->cylinders = p->cylinders;
+ return 0;
+}
+
/* xd_ioctl: handle device ioctl's */
static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
{
- XD_INFO *p = inode->i_bdev->bd_disk->private_data;
-
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry g;
- struct hd_geometry __user *geom= (void __user *)arg;
- g.heads = p->heads;
- g.sectors = p->sectors;
- g.cylinders = p->cylinders;
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
- }
case HDIO_SET_DMA:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (xdc_busy) return -EBUSY;
@@ -1017,7 +1018,7 @@ static void __init do_xd_setup (int *integers)
case 2: if ((integers[2] > 0) && (integers[2] < 16))
xd_irq = integers[2];
case 1: xd_override = 1;
- if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
+ if ((integers[1] >= 0) && (integers[1] < ARRAY_SIZE(xd_sigs)))
xd_type = integers[1];
case 0: break;
default:printk("xd: too many parameters for xd\n");
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 8e7fb3551775..3e7a067cc087 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -275,7 +275,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
}
static struct usb_driver bcm203x_driver = {
- .owner = THIS_MODULE,
.name = "bcm203x",
.probe = bcm203x_probe,
.disconnect = bcm203x_disconnect,
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 067e27893e4a..8947c8837dac 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -768,7 +768,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
}
static struct usb_driver bfusb_driver = {
- .owner = THIS_MODULE,
.name = "bfusb",
.probe = bfusb_probe,
.disconnect = bfusb_disconnect,
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index f36c563d72c4..9888bc151755 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -87,14 +87,8 @@ typedef struct bluecard_info_t {
static void bluecard_config(dev_link_t *link);
static void bluecard_release(dev_link_t *link);
-static int bluecard_event(event_t event, int priority, event_callback_args_t *args);
-static dev_info_t dev_info = "bluecard_cs";
-
-static dev_link_t *bluecard_attach(void);
-static void bluecard_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void bluecard_detach(struct pcmcia_device *p_dev);
/* Default baud rate: 57600, 115200, 230400 or 460800 */
@@ -862,17 +856,15 @@ static int bluecard_close(bluecard_info_t *info)
return 0;
}
-static dev_link_t *bluecard_attach(void)
+static int bluecard_attach(struct pcmcia_device *p_dev)
{
bluecard_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
link = &info->link;
link->priv = info;
@@ -889,50 +881,24 @@ static dev_link_t *bluecard_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- bluecard_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ bluecard_config(link);
+
+ return 0;
}
-static void bluecard_detach(dev_link_t *link)
+static void bluecard_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
bluecard_info_t *info = link->priv;
- dev_link_t **linkp;
- int ret;
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
-
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
bluecard_release(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
-
kfree(info);
}
@@ -1045,39 +1011,24 @@ static void bluecard_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
+static int bluecard_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
-static int bluecard_event(event_t event, int priority, event_callback_args_t *args)
+ return 0;
+}
+
+static int bluecard_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- bluecard_info_t *info = link->priv;
+ dev_link_t *link = dev_to_instance(dev);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- bluecard_close(info);
- bluecard_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bluecard_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
@@ -1095,10 +1046,11 @@ static struct pcmcia_driver bluecard_driver = {
.drv = {
.name = "bluecard_cs",
},
- .attach = bluecard_attach,
- .event = bluecard_event,
- .detach = bluecard_detach,
+ .probe = bluecard_attach,
+ .remove = bluecard_detach,
.id_table = bluecard_ids,
+ .suspend = bluecard_suspend,
+ .resume = bluecard_resume,
};
static int __init init_bluecard_cs(void)
@@ -1110,7 +1062,6 @@ static int __init init_bluecard_cs(void)
static void __exit exit_bluecard_cs(void)
{
pcmcia_unregister_driver(&bluecard_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_bluecard_cs);
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 394796315adc..9446960ac742 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -619,7 +619,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
}
static struct usb_driver bpa10x_driver = {
- .owner = THIS_MODULE,
.name = "bpa10x",
.probe = bpa10x_probe,
.disconnect = bpa10x_disconnect,
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index d2a0add19cc8..e522d19ad886 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -90,14 +90,8 @@ typedef struct bt3c_info_t {
static void bt3c_config(dev_link_t *link);
static void bt3c_release(dev_link_t *link);
-static int bt3c_event(event_t event, int priority, event_callback_args_t *args);
-static dev_info_t dev_info = "bt3c_cs";
-
-static dev_link_t *bt3c_attach(void);
-static void bt3c_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void bt3c_detach(struct pcmcia_device *p_dev);
/* Transmit states */
@@ -663,17 +657,15 @@ static int bt3c_close(bt3c_info_t *info)
return 0;
}
-static dev_link_t *bt3c_attach(void)
+static int bt3c_attach(struct pcmcia_device *p_dev)
{
bt3c_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
link = &info->link;
link->priv = info;
@@ -690,50 +682,24 @@ static dev_link_t *bt3c_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- bt3c_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ bt3c_config(link);
+
+ return 0;
}
-static void bt3c_detach(dev_link_t *link)
+static void bt3c_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
bt3c_info_t *info = link->priv;
- dev_link_t **linkp;
- int ret;
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
-
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
bt3c_release(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
-
kfree(info);
}
@@ -891,43 +857,29 @@ static void bt3c_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
+static int bt3c_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
-static int bt3c_event(event_t event, int priority, event_callback_args_t *args)
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int bt3c_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- bt3c_info_t *info = link->priv;
+ dev_link_t *link = dev_to_instance(dev);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- bt3c_close(info);
- bt3c_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- bt3c_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
+
static struct pcmcia_device_id bt3c_ids[] = {
PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
PCMCIA_DEVICE_NULL
@@ -939,10 +891,11 @@ static struct pcmcia_driver bt3c_driver = {
.drv = {
.name = "bt3c_cs",
},
- .attach = bt3c_attach,
- .event = bt3c_event,
- .detach = bt3c_detach,
+ .probe = bt3c_attach,
+ .remove = bt3c_detach,
.id_table = bt3c_ids,
+ .suspend = bt3c_suspend,
+ .resume = bt3c_resume,
};
static int __init init_bt3c_cs(void)
@@ -954,7 +907,6 @@ static int __init init_bt3c_cs(void)
static void __exit exit_bt3c_cs(void)
{
pcmcia_unregister_driver(&bt3c_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_bt3c_cs);
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 529a28a3209d..7b4bff4cfa2d 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -86,14 +86,8 @@ typedef struct btuart_info_t {
static void btuart_config(dev_link_t *link);
static void btuart_release(dev_link_t *link);
-static int btuart_event(event_t event, int priority, event_callback_args_t *args);
-static dev_info_t dev_info = "btuart_cs";
-
-static dev_link_t *btuart_attach(void);
-static void btuart_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void btuart_detach(struct pcmcia_device *p_dev);
/* Maximum baud rate */
@@ -582,17 +576,15 @@ static int btuart_close(btuart_info_t *info)
return 0;
}
-static dev_link_t *btuart_attach(void)
+static int btuart_attach(struct pcmcia_device *p_dev)
{
btuart_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
link = &info->link;
link->priv = info;
@@ -609,50 +601,24 @@ static dev_link_t *btuart_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- btuart_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ btuart_config(link);
+
+ return 0;
}
-static void btuart_detach(dev_link_t *link)
+static void btuart_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
btuart_info_t *info = link->priv;
- dev_link_t **linkp;
- int ret;
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
-
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
btuart_release(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
-
kfree(info);
}
@@ -811,43 +777,29 @@ static void btuart_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
+static int btuart_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
-static int btuart_event(event_t event, int priority, event_callback_args_t *args)
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int btuart_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- btuart_info_t *info = link->priv;
+ dev_link_t *link = dev_to_instance(dev);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- btuart_close(info);
- btuart_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- btuart_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
+
static struct pcmcia_device_id btuart_ids[] = {
/* don't use this driver. Use serial_cs + hci_uart instead */
PCMCIA_DEVICE_NULL
@@ -859,10 +811,11 @@ static struct pcmcia_driver btuart_driver = {
.drv = {
.name = "btuart_cs",
},
- .attach = btuart_attach,
- .event = btuart_event,
- .detach = btuart_detach,
+ .probe = btuart_attach,
+ .remove = btuart_detach,
.id_table = btuart_ids,
+ .suspend = btuart_suspend,
+ .resume = btuart_resume,
};
static int __init init_btuart_cs(void)
@@ -874,7 +827,6 @@ static int __init init_btuart_cs(void)
static void __exit exit_btuart_cs(void)
{
pcmcia_unregister_driver(&btuart_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_btuart_cs);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index dec5980a1cd6..0449bc45ae5e 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -89,14 +89,8 @@ typedef struct dtl1_info_t {
static void dtl1_config(dev_link_t *link);
static void dtl1_release(dev_link_t *link);
-static int dtl1_event(event_t event, int priority, event_callback_args_t *args);
-static dev_info_t dev_info = "dtl1_cs";
-
-static dev_link_t *dtl1_attach(void);
-static void dtl1_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
+static void dtl1_detach(struct pcmcia_device *p_dev);
/* Transmit states */
@@ -561,17 +555,15 @@ static int dtl1_close(dtl1_info_t *info)
return 0;
}
-static dev_link_t *dtl1_attach(void)
+static int dtl1_attach(struct pcmcia_device *p_dev)
{
dtl1_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
/* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
link = &info->link;
link->priv = info;
@@ -588,50 +580,24 @@ static dev_link_t *dtl1_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- dtl1_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ dtl1_config(link);
+
+ return 0;
}
-static void dtl1_detach(dev_link_t *link)
+static void dtl1_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
dtl1_info_t *info = link->priv;
- dev_link_t **linkp;
- int ret;
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
-
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
dtl1_release(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
-
kfree(info);
}
@@ -763,46 +729,33 @@ static void dtl1_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
+static int dtl1_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
-static int dtl1_event(event_t event, int priority, event_callback_args_t *args)
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int dtl1_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- dtl1_info_t *info = link->priv;
+ dev_link_t *link = dev_to_instance(dev);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- dtl1_close(info);
- dtl1_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- dtl1_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
+
static struct pcmcia_device_id dtl1_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
+ PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
@@ -812,10 +765,11 @@ static struct pcmcia_driver dtl1_driver = {
.drv = {
.name = "dtl1_cs",
},
- .attach = dtl1_attach,
- .event = dtl1_event,
- .detach = dtl1_detach,
+ .probe = dtl1_attach,
+ .remove = dtl1_detach,
.id_table = dtl1_ids,
+ .suspend = dtl1_suspend,
+ .resume = dtl1_resume,
};
static int __init init_dtl1_cs(void)
@@ -827,7 +781,6 @@ static int __init init_dtl1_cs(void)
static void __exit exit_dtl1_cs(void)
{
pcmcia_unregister_driver(&dtl1_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_dtl1_cs);
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 8fddfdfd0fbd..7bd4ef904115 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -494,7 +494,7 @@ static inline void bcsp_unslip_one_byte(struct bcsp_struct *bcsp, unsigned char
}
}
-static inline void bcsp_complete_rx_pkt(struct hci_uart *hu)
+static void bcsp_complete_rx_pkt(struct hci_uart *hu)
{
struct bcsp_struct *bcsp = hu->priv;
int pass_up;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 573ff6c1be5f..613673b12fa6 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -279,6 +279,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
tty->disc_data = hu;
hu->tty = tty;
+ tty->receive_room = 65536;
spin_lock_init(&hu->rx_lock);
@@ -348,20 +349,6 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
hci_uart_tx_wakeup(hu);
}
-/* hci_uart_tty_room()
- *
- * Callback function from tty driver. Return the amount of
- * space left in the receiver's buffer to decide if remote
- * transmitter is to be throttled.
- *
- * Arguments: tty pointer to associated tty instance data
- * Return Value: number of bytes left in receive buffer
- */
-static int hci_uart_tty_room (struct tty_struct *tty)
-{
- return 65536;
-}
-
/* hci_uart_tty_receive()
*
* Called by tty low level driver when receive data is
@@ -544,7 +531,6 @@ static int __init hci_uart_init(void)
hci_uart_ldisc.write = hci_uart_tty_write;
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
hci_uart_ldisc.poll = hci_uart_tty_poll;
- hci_uart_ldisc.receive_room = hci_uart_tty_room;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
hci_uart_ldisc.owner = THIS_MODULE;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 057cb2b6e6d1..92382e823285 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -1044,7 +1044,6 @@ static void hci_usb_disconnect(struct usb_interface *intf)
}
static struct usb_driver hci_usb_driver = {
- .owner = THIS_MODULE,
.name = "hci_usb",
.probe = hci_usb_probe,
.disconnect = hci_usb_disconnect,
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 153960348414..879bbc26ce96 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1131,7 +1131,7 @@ int open_for_data(struct cdrom_device_info * cdi)
This ensures that the drive gets unlocked after a mount fails. This
is a goto to avoid bloating the driver with redundant code. */
clean_up_and_return:
- cdinfo(CD_WARNING, "open failed.\n");
+ cdinfo(CD_OPEN, "open failed.\n");
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
cdo->lock_door(cdi, 0);
cdinfo(CD_OPEN, "door unlocked.\n");
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index ac96de15d833..378e88d20757 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -1402,7 +1402,7 @@ static void do_cdu31a_request(request_queue_t * q)
if (!end_that_request_first(req, 1, nblock)) {
spin_lock_irq(q->queue_lock);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
spin_unlock_irq(q->queue_lock);
}
continue;
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 01f035173328..ce127f7ec0f6 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -32,7 +32,7 @@ History:
18 mrt 1995: 0.24 Working background read-ahead. (still problems)
26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
Statistics implemented, though separate stats206.h.
- Accessible trough ioctl 0x1000 (just a number).
+ Accessible through ioctl 0x1000 (just a number).
Hard to choose between v1.2 development and 1.1.75.
Bottom-half doesn't work with 1.2...
0.25a: fixed... typo. Still problems...
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index b5191780ecca..193446e6a08a 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -542,10 +542,10 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
/* Notification that a partition went away! */
return;
/* First, we should NEVER get an int here...only acks */
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
printk(VIOCD_KERN_WARNING
"Yikes! got an int in viocd event handler!\n");
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
@@ -616,7 +616,7 @@ return_complete:
printk(VIOCD_KERN_WARNING
"message with invalid subtype %0x04X!\n",
event->xSubtype & VIOMINOR_SUBTYPE_MASK);
- if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) {
+ if (hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/char/.gitignore b/drivers/char/.gitignore
index 2b6b1d772ed7..73dfdcebfbba 100644
--- a/drivers/char/.gitignore
+++ b/drivers/char/.gitignore
@@ -1,3 +1,3 @@
consolemap_deftbl.c
defkeymap.c
-
+qtronixmap.c
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 84e68cdd451b..4135d8c5bcae 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
+ depends on SERIAL_NONSTANDARD
---help---
This driver supports the entire family of Intelliport II/Plus
controllers with the exception of the MicroChannel controllers and
@@ -153,7 +153,7 @@ config DIGIEPCA
config ESPSERIAL
tristate "Hayes ESP serial port support"
- depends on SERIAL_NONSTANDARD && ISA && BROKEN_ON_SMP && ISA_DMA_API
+ depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
@@ -166,7 +166,7 @@ config ESPSERIAL
config MOXA_INTELLIO
tristate "Moxa Intellio support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
Say Y here if you have a Moxa Intellio multiport serial card.
@@ -220,6 +220,14 @@ config SYNCLINKMP
The module will be called synclinkmp. If you want to do that, say M
here.
+config SYNCLINK_GT
+ tristate "SyncLink GT/AC support"
+ depends on SERIAL_NONSTANDARD
+ help
+ Support for SyncLink GT and SyncLink AC families of
+ synchronous and asynchronous serial adapters
+ manufactured by Microgate Systems, Ltd. (www.microgate.com)
+
config N_HDLC
tristate "HDLC line discipline support"
depends on SERIAL_NONSTANDARD
@@ -282,7 +290,7 @@ config SX
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP && !64BIT
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -687,7 +695,7 @@ config NVRAM
config RTC
tristate "Enhanced Real Time Clock Support"
- depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI)
+ depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV
---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
@@ -735,7 +743,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV
---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
@@ -873,16 +881,6 @@ config FTAPE
module. To compile this driver as a module, choose M here: the
module will be called ftape.
- Note that the Ftape-HOWTO is out of date (sorry) and documents the
- older version 2.08 of this software but still contains useful
- information. There is a web page with more recent documentation at
- <http://www.instmath.rwth-aachen.de/~heine/ftape/>. This page
- always contains the latest release of the ftape driver and useful
- information (backup software, ftape related patches and
- documentation, FAQ). Note that the file system interface has
- changed quite a bit compared to previous versions of ftape. Please
- read <file:Documentation/ftape.txt>.
-
source "drivers/char/ftape/Kconfig"
endmenu
@@ -928,6 +926,15 @@ config SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.
+config CS5535_GPIO
+ tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
+ depends on X86_32
+ help
+ Give userspace access to the GPIO pins on the AMD CS5535 and
+ CS5536 Geode companion devices.
+
+ If compiled as a module, it will be called cs5535_gpio.
+
config GPIO_VR41XX
tristate "NEC VR4100 series General-purpose I/O Unit support"
depends on CPU_VR41XX
@@ -985,7 +992,7 @@ config HPET_MMAP
config HANGCHECK_TIMER
tristate "Hangcheck timer"
- depends on X86 || IA64 || PPC64 || ARCH_S390
+ depends on X86 || IA64 || PPC64 || S390
help
The hangcheck-timer module detects when the system has gone
out to lunch past a certain margin. It can reboot the system
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 4aeae687e88a..503dd901d406 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_RISCOM8) += riscom8.o
obj-$(CONFIG_ISI) += isicom.o
obj-$(CONFIG_SYNCLINK) += synclink.o
obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o
+obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
obj-$(CONFIG_SX) += sx.o generic_serial.o
@@ -80,6 +81,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 3f8f7fa6b0ff..268f78d926d3 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/jiffies.h>
#include <linux/agp_backend.h>
#include "agp.h"
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a124f8c5d062..7ac365b5d9ec 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -99,6 +99,7 @@ static char *serial_version = "4.30";
#define _INLINE_ inline
#endif
+#define custom amiga_custom
static char *serial_name = "Amiga-builtin serial driver";
static struct tty_driver *serial_driver;
@@ -116,7 +117,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
static struct serial_state rs_table[1];
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
+#define NR_PORTS ARRAY_SIZE(rs_table)
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
@@ -128,7 +129,6 @@ static struct serial_state rs_table[1];
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
#include <asm/uaccess.h>
@@ -265,8 +265,9 @@ static _INLINE_ void receive_chars(struct async_struct *info)
int status;
int serdatr;
struct tty_struct *tty = info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
struct async_icount *icount;
+ int oe = 0;
icount = &info->state->icount;
@@ -282,15 +283,12 @@ static _INLINE_ void receive_chars(struct async_struct *info)
status |= UART_LSR_OE;
ch = serdatr & 0xff;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
- *tty->flip.char_buf_ptr = ch;
icount->rx++;
#ifdef SERIAL_DEBUG_INTR
printk("DR%02x:%02x...", ch, status);
#endif
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
/*
* We don't handle parity or frame errors - but I have left
@@ -319,7 +317,7 @@ static _INLINE_ void receive_chars(struct async_struct *info)
* should be ignored.
*/
if (status & info->ignore_status_mask)
- goto ignore_char;
+ goto out;
status &= info->read_status_mask;
@@ -327,33 +325,28 @@ static _INLINE_ void receive_chars(struct async_struct *info)
#ifdef SERIAL_DEBUG_INTR
printk("handling break....");
#endif
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
if (status & UART_LSR_OE) {
/*
* Overrun is special, since it's
* reported immediately, and doesn't
* affect the current character
*/
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ oe = 1;
}
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- ignore_char:
-
+ tty_insert_flip_char(tty, ch, flag);
+ if (oe == 1)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
tty_flip_buffer_push(tty);
+out:
+ return;
}
static _INLINE_ void transmit_chars(struct async_struct *info)
@@ -1095,7 +1088,7 @@ static void rs_unthrottle(struct tty_struct * tty)
*/
static int get_serial_info(struct async_struct * info,
- struct serial_struct * retinfo)
+ struct serial_struct __user * retinfo)
{
struct serial_struct tmp;
struct serial_state *state = info->state;
@@ -1119,7 +1112,7 @@ static int get_serial_info(struct async_struct * info,
}
static int set_serial_info(struct async_struct * info,
- struct serial_struct * new_info)
+ struct serial_struct __user * new_info)
{
struct serial_struct new_serial;
struct serial_state old_state, *state;
@@ -1200,7 +1193,7 @@ check_and_exit:
* transmit holding register is empty. This functionality
* allows an RS485 driver to be written in user space.
*/
-static int get_lsr_info(struct async_struct * info, unsigned int *value)
+static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
{
unsigned char status;
unsigned int result;
@@ -1291,6 +1284,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
struct async_struct * info = (struct async_struct *)tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct icount;
+ void __user *argp = (void __user *)arg;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
@@ -1305,19 +1299,17 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
switch (cmd) {
case TIOCGSERIAL:
- return get_serial_info(info,
- (struct serial_struct *) arg);
+ return get_serial_info(info, argp);
case TIOCSSERIAL:
- return set_serial_info(info,
- (struct serial_struct *) arg);
+ return set_serial_info(info, argp);
case TIOCSERCONFIG:
return 0;
case TIOCSERGETLSR: /* Get line status register */
- return get_lsr_info(info, (unsigned int *) arg);
+ return get_lsr_info(info, argp);
case TIOCSERGSTRUCT:
- if (copy_to_user((struct async_struct *) arg,
+ if (copy_to_user(argp,
info, sizeof(struct async_struct)))
return -EFAULT;
return 0;
@@ -1376,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
- if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+ if (copy_to_user(argp, &icount, sizeof(icount)))
return -EFAULT;
return 0;
case TIOCSERGWILD:
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
new file mode 100644
index 000000000000..5d72f50de1ac
--- /dev/null
+++ b/drivers/char/cs5535_gpio.c
@@ -0,0 +1,250 @@
+/*
+ * AMD CS5535/CS5536 GPIO driver.
+ * Allows a user space process to play with the GPIO pins.
+ *
+ * Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+
+#define NAME "cs5535_gpio"
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO Pin Driver");
+MODULE_LICENSE("GPL");
+
+static int major;
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static ulong mask;
+module_param(mask, ulong, 0);
+MODULE_PARM_DESC(mask, "GPIO channel mask");
+
+#define MSR_LBAR_GPIO 0x5140000C
+
+static u32 gpio_base;
+
+static struct pci_device_id divil_pci[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
+ { } /* NULL entry */
+};
+
+static struct cdev cs5535_gpio_cdev;
+
+/* reserve 32 entries even though some aren't usable */
+#define CS5535_GPIO_COUNT 32
+
+/* IO block size */
+#define CS5535_GPIO_SIZE 256
+
+struct gpio_regmap {
+ u32 rd_offset;
+ u32 wr_offset;
+ char on;
+ char off;
+};
+static struct gpio_regmap rm[] =
+{
+ { 0x30, 0x00, '1', '0' }, /* GPIOx_READ_BACK / GPIOx_OUT_VAL */
+ { 0x20, 0x20, 'I', 'i' }, /* GPIOx_IN_EN */
+ { 0x04, 0x04, 'O', 'o' }, /* GPIOx_OUT_EN */
+ { 0x08, 0x08, 't', 'T' }, /* GPIOx_OUT_OD_EN */
+ { 0x18, 0x18, 'P', 'p' }, /* GPIOx_OUT_PU_EN */
+ { 0x1c, 0x1c, 'D', 'd' }, /* GPIOx_OUT_PD_EN */
+};
+
+
+/**
+ * Gets the register offset for the GPIO bank.
+ * Low (0-15) starts at 0x00, high (16-31) starts at 0x80
+ */
+static inline u32 cs5535_lowhigh_base(int reg)
+{
+ return (reg & 0x10) << 3;
+}
+
+static ssize_t cs5535_gpio_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ u32 m = iminor(file->f_dentry->d_inode);
+ int i, j;
+ u32 base = gpio_base + cs5535_lowhigh_base(m);
+ u32 m0, m1;
+ char c;
+
+ /**
+ * Creates the mask for atomic bit programming.
+ * The high 16 bits and the low 16 bits are used to set the mask.
+ * For example, GPIO 15 maps to 31,15: 0,1 => On; 1,0=> Off
+ */
+ m1 = 1 << (m & 0x0F);
+ m0 = m1 << 16;
+
+ for (i = 0; i < len; ++i) {
+ if (get_user(c, data+i))
+ return -EFAULT;
+
+ for (j = 0; j < ARRAY_SIZE(rm); j++) {
+ if (c == rm[j].on) {
+ outl(m1, base + rm[j].wr_offset);
+ break;
+ } else if (c == rm[j].off) {
+ outl(m0, base + rm[j].wr_offset);
+ break;
+ }
+ }
+ }
+ *ppos = 0;
+ return len;
+}
+
+static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ u32 m = iminor(file->f_dentry->d_inode);
+ u32 base = gpio_base + cs5535_lowhigh_base(m);
+ int rd_bit = 1 << (m & 0x0f);
+ int i;
+ char ch;
+ ssize_t count = 0;
+
+ if (*ppos >= ARRAY_SIZE(rm))
+ return 0;
+
+ for (i = *ppos; (i < (*ppos + len)) && (i < ARRAY_SIZE(rm)); i++) {
+ ch = (inl(base + rm[i].rd_offset) & rd_bit) ?
+ rm[i].on : rm[i].off;
+
+ if (put_user(ch, buf+count))
+ return -EFAULT;
+
+ count++;
+ }
+
+ /* add a line-feed if there is room */
+ if ((i == ARRAY_SIZE(rm)) && (count < len)) {
+ put_user('\n', buf + count);
+ count++;
+ }
+
+ *ppos += count;
+ return count;
+}
+
+static int cs5535_gpio_open(struct inode *inode, struct file *file)
+{
+ u32 m = iminor(inode);
+
+ /* the mask says which pins are usable by this driver */
+ if ((mask & (1 << m)) == 0)
+ return -EINVAL;
+
+ return nonseekable_open(inode, file);
+}
+
+static struct file_operations cs5535_gpio_fops = {
+ .owner = THIS_MODULE,
+ .write = cs5535_gpio_write,
+ .read = cs5535_gpio_read,
+ .open = cs5535_gpio_open
+};
+
+static int __init cs5535_gpio_init(void)
+{
+ dev_t dev_id;
+ u32 low, hi;
+ int retval;
+
+ if (pci_dev_present(divil_pci) == 0) {
+ printk(KERN_WARNING NAME ": DIVIL not found\n");
+ return -ENODEV;
+ }
+
+ /* Grab the GPIO I/O range */
+ rdmsr(MSR_LBAR_GPIO, low, hi);
+
+ /* Check the mask and whether GPIO is enabled (sanity check) */
+ if (hi != 0x0000f001) {
+ printk(KERN_WARNING NAME ": GPIO not enabled\n");
+ return -ENODEV;
+ }
+
+ /* Mask off the IO base address */
+ gpio_base = low & 0x0000ff00;
+
+ /**
+ * Some GPIO pins
+ * 31-29,23 : reserved (always mask out)
+ * 28 : Power Button
+ * 26 : PME#
+ * 22-16 : LPC
+ * 14,15 : SMBus
+ * 9,8 : UART1
+ * 7 : PCI INTB
+ * 3,4 : UART2/DDC
+ * 2 : IDE_IRQ0
+ * 0 : PCI INTA
+ *
+ * If a mask was not specified, be conservative and only allow:
+ * 1,2,5,6,10-13,24,25,27
+ */
+ if (mask != 0)
+ mask &= 0x1f7fffff;
+ else
+ mask = 0x0b003c66;
+
+ if (request_region(gpio_base, CS5535_GPIO_SIZE, NAME) == 0) {
+ printk(KERN_ERR NAME ": can't allocate I/O for GPIO\n");
+ return -ENODEV;
+ }
+
+ if (major) {
+ dev_id = MKDEV(major, 0);
+ retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
+ NAME);
+ } else {
+ retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
+ NAME);
+ major = MAJOR(dev_id);
+ }
+
+ if (retval) {
+ release_region(gpio_base, CS5535_GPIO_SIZE);
+ return -1;
+ }
+
+ printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n",
+ gpio_base, mask, major);
+
+ cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
+ cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);
+
+ return 0;
+}
+
+static void __exit cs5535_gpio_cleanup(void)
+{
+ dev_t dev_id = MKDEV(major, 0);
+ unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
+ if (gpio_base != 0)
+ release_region(gpio_base, CS5535_GPIO_SIZE);
+}
+
+module_init(cs5535_gpio_init);
+module_exit(cs5535_gpio_cleanup);
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index c7f818cd7b02..39c61a71176e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -641,6 +641,7 @@ static char rcsid[] =
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <linux/string.h>
@@ -723,7 +724,7 @@ static unsigned int cy_isa_addresses[] = {
0xDE000,
0,0,0,0,0,0,0,0
};
-#define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
+#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
#ifdef MODULE
static long maddr[NR_CARDS] = { 0, };
@@ -1086,7 +1087,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int had_work;
int mdm_change;
int mdm_status;
-
+ int len;
if((cinfo = (struct cyclades_card *)dev_id) == 0){
#ifdef CY_DEBUG_INTERRUPTS
printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
@@ -1163,63 +1164,43 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
info->icount.rx++;
continue;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
+ if (tty_buffer_request_room(tty, 1)) {
if (data & info->read_status_mask){
if(data & CyBREAK){
- *tty->flip.flag_buf_ptr++ =
- TTY_BREAK;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_BREAK);
info->icount.rx++;
if (info->flags & ASYNC_SAK){
do_SAK(tty);
}
}else if(data & CyFRAME){
- *tty->flip.flag_buf_ptr++ =
- TTY_FRAME;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
info->icount.rx++;
info->idle_stats.frame_errs++;
}else if(data & CyPARITY){
- *tty->flip.flag_buf_ptr++ =
- TTY_PARITY;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
+ /* Pieces of seven... */
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_PARITY);
info->icount.rx++;
info->idle_stats.parity_errs++;
}else if(data & CyOVERRUN){
- *tty->flip.flag_buf_ptr++ =
- TTY_OVERRUN;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
info->icount.rx++;
/* If the flip buffer itself is
overflowing, we still lose
the next incoming character.
*/
- if(tty->flip.count
- < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ =
- TTY_NORMAL;
- *tty->flip.char_buf_ptr++ =
- cy_readb(base_addr+(CyRDSR<<index));
- info->icount.rx++;
- }
+ tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<<index)), TTY_FRAME);
+ info->icount.rx++;
info->idle_stats.overruns++;
/* These two conditions may imply */
/* a normal read should be done. */
/* }else if(data & CyTIMEOUT){ */
/* }else if(data & CySPECHAR){ */
- }else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
- info->icount.rx++;
+ }else {
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
+ info->icount.rx++;
}
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
info->icount.rx++;
}
}else{
@@ -1240,14 +1221,10 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
info->mon.char_max = char_count;
info->mon.char_last = char_count;
#endif
- while(char_count--){
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- break;
- }
- tty->flip.count++;
+ len = tty_buffer_request_room(tty, char_count);
+ while(len--){
data = cy_readb(base_addr+(CyRDSR<<index));
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
#ifdef CY_16Y_HACK
@@ -1256,7 +1233,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
info->idle_stats.recv_idle = jiffies;
}
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
/* end of service */
cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
@@ -1551,6 +1528,7 @@ cyz_handle_rx(struct cyclades_port *info,
struct cyclades_card *cinfo = &cy_card[info->card];
struct tty_struct *tty = info->tty;
volatile int char_count;
+ int len;
#ifdef BLOCKMOVE
int small_count;
#else
@@ -1606,18 +1584,11 @@ cyz_handle_rx(struct cyclades_port *info,
tty->flip.count += small_count;
}
#else
- while(char_count--){
- if (tty->flip.count >= N_TTY_BUF_SIZE - tty->read_cnt)
- break;
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
+ len = tty_buffer_request_room(tty, char_count);
+ while(len--){
data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
info->idle_stats.recv_bytes++;
info->icount.rx++;
}
@@ -1635,7 +1606,7 @@ cyz_handle_rx(struct cyclades_port *info,
}
#endif
info->idle_stats.recv_idle = jiffies;
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
/* Update rx_get */
cy_writel(&buf_ctrl->rx_get, new_rx_get);
@@ -1763,23 +1734,17 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
switch(cmd) {
case C_CM_PR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_PARITY);
info->icount.rx++;
special_count++;
break;
case C_CM_FR_ERROR:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_FRAME);
info->icount.rx++;
special_count++;
break;
case C_CM_RXBRK:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
info->icount.rx++;
special_count++;
break;
@@ -1844,7 +1809,7 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
if(delta_count)
cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
if(special_count)
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
}
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index e41060c76226..9d180c42816c 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
- drm_drv.o drm_fops.o drm_init.o drm_ioctl.o drm_irq.o \
+ drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \
drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
drm_sysfs.o
@@ -18,7 +18,7 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.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
+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 via_dmablit.o
ifeq ($(CONFIG_COMPAT),y)
drm-objs += drm_ioc32.o
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index efff0eec618c..5485382cadec 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -52,7 +52,7 @@
# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
-static unsigned long drm_ati_alloc_pcigart_table(void)
+static void *drm_ati_alloc_pcigart_table(void)
{
unsigned long address;
struct page *page;
@@ -72,27 +72,26 @@ static unsigned long drm_ati_alloc_pcigart_table(void)
}
DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address);
- return address;
+ return (void *)address;
}
-static void drm_ati_free_pcigart_table(unsigned long address)
+static void drm_ati_free_pcigart_table(void *address)
{
struct page *page;
int i;
DRM_DEBUG("%s\n", __FUNCTION__);
- page = virt_to_page(address);
+ page = virt_to_page((unsigned long)address);
for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) {
__put_page(page);
ClearPageReserved(page);
}
- free_pages(address, ATI_PCIGART_TABLE_ORDER);
+ free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER);
}
-int drm_ati_pcigart_cleanup(drm_device_t * dev,
- drm_ati_pcigart_info * gart_info)
+int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
unsigned long pages;
@@ -136,10 +135,10 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev,
EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
-int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
+int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info)
{
drm_sg_mem_t *entry = dev->sg;
- unsigned long address = 0;
+ void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base, bus_address = 0;
int i, j, ret = 0;
@@ -163,7 +162,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
goto done;
}
- bus_address = pci_map_single(dev->pdev, (void *)address,
+ bus_address = pci_map_single(dev->pdev, address,
ATI_PCIGART_TABLE_PAGES *
PAGE_SIZE, PCI_DMA_TODEVICE);
if (bus_address == 0) {
@@ -176,7 +175,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
address = gart_info->addr;
bus_address = gart_info->bus_addr;
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
- bus_address, address);
+ bus_address, (unsigned long)address);
}
pci_gart = (u32 *) address;
@@ -195,7 +194,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info)
if (entry->busaddr[i] == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_pcigart_cleanup(dev, gart_info);
- address = 0;
+ address = NULL;
bus_address = 0;
goto done;
}
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 64d6237fdd0b..9da0ddb892b5 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -90,8 +90,8 @@
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
-#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
-#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 3dc3c9d79ae4..54b561e69486 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -144,20 +144,6 @@
/** \name Backward compatibility section */
/*@{*/
-#ifndef MODULE_LICENSE
-#define MODULE_LICENSE(x)
-#endif
-
-#ifndef preempt_disable
-#define preempt_disable()
-#define preempt_enable()
-#endif
-
-#ifndef pte_offset_map
-#define pte_offset_map pte_offset
-#define pte_unmap(pte)
-#endif
-
#define DRM_RPR_ARG(vma) vma,
#define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT)
@@ -286,10 +272,13 @@ typedef int drm_ioctl_t(struct inode *inode, struct file *filp,
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
unsigned long arg);
+#define DRM_AUTH 0x1
+#define DRM_MASTER 0x2
+#define DRM_ROOT_ONLY 0x4
+
typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
- int auth_needed;
- int root_only;
+ int flags;
} drm_ioctl_desc_t;
typedef struct drm_devstate {
@@ -384,6 +373,7 @@ typedef struct drm_buf_entry {
/** File private data */
typedef struct drm_file {
int authenticated;
+ int master;
int minor;
pid_t pid;
uid_t uid;
@@ -532,8 +522,9 @@ typedef struct drm_vbl_sig {
typedef struct ati_pcigart_info {
int gart_table_location;
int is_pcie;
- unsigned long addr;
+ void *addr;
dma_addr_t bus_addr;
+ drm_local_map_t mapping;
} drm_ati_pcigart_info;
/**
@@ -544,16 +535,14 @@ typedef struct ati_pcigart_info {
struct drm_device;
struct drm_driver {
- int (*preinit) (struct drm_device *, unsigned long flags);
- void (*prerelease) (struct drm_device *, struct file * filp);
- void (*pretakedown) (struct drm_device *);
- int (*postcleanup) (struct drm_device *);
- int (*presetup) (struct drm_device *);
- int (*postsetup) (struct drm_device *);
+ int (*load) (struct drm_device *, unsigned long flags);
+ int (*firstopen) (struct drm_device *);
+ int (*open) (struct drm_device *, drm_file_t *);
+ void (*preclose) (struct drm_device *, struct file * filp);
+ void (*postclose) (struct drm_device *, drm_file_t *);
+ void (*lastclose) (struct drm_device *);
+ int (*unload) (struct drm_device *);
int (*dma_ioctl) (DRM_IOCTL_ARGS);
- int (*open_helper) (struct drm_device *, drm_file_t *);
- void (*free_filp_priv) (struct drm_device *, drm_file_t *);
- void (*release) (struct drm_device *, struct file * filp);
void (*dma_ready) (struct drm_device *);
int (*dma_quiescent) (struct drm_device *);
int (*context_ctor) (struct drm_device * dev, int context);
@@ -561,8 +550,9 @@ 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);
+ drm_lock_t *lock);
int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence);
+ int (*dri_library_name) (struct drm_device *dev, char *buf);
/**
* Called by \c drm_device_is_agp. Typically used to determine if a
@@ -579,16 +569,24 @@ struct drm_driver {
/* these have to be filled in */
- int (*postinit) (struct drm_device *, unsigned long flags);
- irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
+ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
void (*irq_preinstall) (struct drm_device * dev);
void (*irq_postinstall) (struct drm_device * dev);
void (*irq_uninstall) (struct drm_device * dev);
void (*reclaim_buffers) (struct drm_device * dev, struct file * filp);
+ void (*reclaim_buffers_locked) (struct drm_device *dev,
+ struct file *filp);
unsigned long (*get_map_ofs) (drm_map_t * map);
unsigned long (*get_reg_ofs) (struct drm_device * dev);
void (*set_version) (struct drm_device * dev, drm_set_version_t * sv);
- int (*version) (drm_version_t * version);
+
+ int major;
+ int minor;
+ int patchlevel;
+ char *name;
+ char *desc;
+ char *date;
+
u32 driver_features;
int dev_priv_size;
drm_ioctl_desc_t *ioctls;
@@ -752,19 +750,43 @@ static inline int drm_core_has_MTRR(struct drm_device *dev)
{
return drm_core_check_feature(dev, DRIVER_USE_MTRR);
}
+
+#define DRM_MTRR_WC MTRR_TYPE_WRCOMB
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ return mtrr_add(offset, size, flags, 1);
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+ unsigned long size, unsigned int flags)
+{
+ return mtrr_del(handle, offset, size);
+}
+
#else
#define drm_core_has_MTRR(dev) (0)
+
+#define DRM_MTRR_WC 0
+
+static inline int drm_mtrr_add(unsigned long offset, unsigned long size,
+ unsigned int flags)
+{
+ return 0;
+}
+
+static inline int drm_mtrr_del(int handle, unsigned long offset,
+ unsigned long size, unsigned int flags)
+{
+ return 0;
+}
#endif
/******************************************************************/
/** \name Internal function definitions */
/*@{*/
- /* Misc. support (drm_init.h) */
-extern int drm_flags;
-extern void drm_parse_options(char *s);
-extern int drm_cpu_valid(void);
-
/* Driver support (drm_drv.h) */
extern int drm_init(struct drm_driver *driver);
extern void drm_exit(struct drm_driver *driver);
@@ -772,12 +794,11 @@ extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern long drm_compat_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_takedown(drm_device_t * dev);
+extern int drm_lastclose(drm_device_t *dev);
/* Device support (drm_fops.h) */
extern int drm_open(struct inode *inode, struct file *filp);
extern int drm_stub_open(struct inode *inode, struct file *filp);
-extern int drm_flush(struct file *filp);
extern int drm_fasync(int fd, struct file *filp, int on);
extern int drm_release(struct inode *inode, struct file *filp);
@@ -819,6 +840,8 @@ extern int drm_getstats(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_setversion(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern int drm_noop(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg);
/* Context IOCTL support (drm_context.h) */
extern int drm_resctx(struct inode *inode, struct file *filp,
@@ -857,10 +880,6 @@ extern int drm_getmagic(struct inode *inode, struct file *filp,
extern int drm_authmagic(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
- /* Placeholder for ioctls past */
-extern int drm_noop(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
-
/* Locking IOCTL support (drm_lock.h) */
extern int drm_lock(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
@@ -873,6 +892,7 @@ extern int drm_lock_free(drm_device_t * dev,
/* Buffer management support (drm_bufs.h) */
extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request);
extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request);
+extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request);
extern int drm_addmap(drm_device_t * dev, unsigned int offset,
unsigned int size, drm_map_type_t type,
drm_map_flags_t flags, drm_local_map_t ** map_ptr);
@@ -908,8 +928,8 @@ extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp);
/* IRQ support (drm_irq.h) */
extern int drm_control(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_irq_uninstall(drm_device_t * dev);
extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS);
+extern int drm_irq_uninstall(drm_device_t * dev);
extern void drm_driver_irq_preinstall(drm_device_t * dev);
extern void drm_driver_irq_postinstall(drm_device_t * dev);
extern void drm_driver_irq_uninstall(drm_device_t * dev);
@@ -933,13 +953,17 @@ extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
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,
+extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_free(struct inode *inode, struct file *filp,
+extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request);
+extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_unbind(struct inode *inode, struct file *filp,
+extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
-extern int drm_agp_bind(struct inode *inode, struct file *filp,
+extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request);
+extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge,
size_t pages, u32 type);
@@ -991,10 +1015,8 @@ extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner,
char *name);
extern void drm_sysfs_destroy(struct drm_sysfs_class *cs);
extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
- dev_t dev,
- struct device *device,
- const char *fmt, ...);
-extern void drm_sysfs_device_remove(dev_t dev);
+ drm_head_t *head);
+extern void drm_sysfs_device_remove(struct class_device *class_dev);
/* Inline replacements for DRM_IOREMAP macros */
static __inline__ void drm_core_ioremap(struct drm_map *map,
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
index 2b6453a9ffce..fabc930c67a2 100644
--- a/drivers/char/drm/drm_agpsupport.c
+++ b/drivers/char/drm/drm_agpsupport.c
@@ -1,5 +1,5 @@
/**
- * \file drm_agpsupport.h
+ * \file drm_agpsupport.c
* DRM support for AGP/GART backend
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -91,7 +91,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp,
/**
* Acquire the AGP device.
*
- * \param dev DRM device that is to acquire AGP
+ * \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
@@ -134,7 +134,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp,
/**
* Release the AGP device.
*
- * \param dev DRM device that is to release AGP
+ * \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.
@@ -147,7 +147,6 @@ int drm_agp_release(drm_device_t * dev)
dev->agp->acquired = 0;
return 0;
}
-
EXPORT_SYMBOL(drm_agp_release);
int drm_agp_release_ioctl(struct inode *inode, struct file *filp,
@@ -208,30 +207,22 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp,
* Verifies the AGP device is present and has been acquired, allocates the
* memory via alloc_agp() and creates a drm_agp_mem entry for it.
*/
-int drm_agp_alloc(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_buffer_t request;
drm_agp_mem_t *entry;
DRM_AGP_MEM *memory;
unsigned long pages;
u32 type;
- drm_agp_buffer_t __user *argp = (void __user *)arg;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user(&request, argp, sizeof(request)))
- return -EFAULT;
if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS)))
return -ENOMEM;
memset(entry, 0, sizeof(*entry));
- pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
- type = (u32) request.type;
-
+ pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
+ type = (u32) request->type;
if (!(memory = drm_alloc_agp(dev, pages, type))) {
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -ENOMEM;
@@ -247,16 +238,39 @@ int drm_agp_alloc(struct inode *inode, struct file *filp,
dev->agp->memory->prev = entry;
dev->agp->memory = entry;
- request.handle = entry->handle;
- request.physical = memory->physical;
+ request->handle = entry->handle;
+ request->physical = memory->physical;
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_agp_alloc);
+
+int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_buffer_t request;
+ drm_agp_buffer_t __user *argp = (void __user *)arg;
+ int err;
+
+ if (copy_from_user(&request, argp, sizeof(request)))
+ return -EFAULT;
+
+ err = drm_agp_alloc(dev, &request);
+ if (err)
+ return err;
if (copy_to_user(argp, &request, sizeof(request))) {
+ drm_agp_mem_t *entry = dev->agp->memory;
+
dev->agp->memory = entry->next;
dev->agp->memory->prev = NULL;
- drm_free_agp(memory, pages);
+ drm_free_agp(entry->memory, entry->pages);
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return -EFAULT;
}
+
return 0;
}
@@ -293,21 +307,14 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev,
* Verifies the AGP device is present and acquired, looks-up the AGP memory
* entry and passes it to the unbind_agp() function.
*/
-int drm_agp_unbind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_binding_t request;
drm_agp_mem_t *entry;
int ret;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (!entry->bound)
return -EINVAL;
@@ -316,6 +323,21 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
entry->bound = 0;
return ret;
}
+EXPORT_SYMBOL(drm_agp_unbind);
+
+int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_binding_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_unbind(dev, &request);
+}
/**
* Bind AGP memory into the GATT (ioctl)
@@ -330,26 +352,19 @@ int drm_agp_unbind(struct inode *inode, struct file *filp,
* is currently bound into the GATT. Looks-up the AGP memory entry and passes
* it to bind_agp() function.
*/
-int drm_agp_bind(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_binding_t request;
drm_agp_mem_t *entry;
int retcode;
int page;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user
- (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (entry->bound)
return -EINVAL;
- page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE;
+ page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
if ((retcode = drm_bind_agp(entry->memory, page)))
return retcode;
entry->bound = dev->agp->base + (page << PAGE_SHIFT);
@@ -357,6 +372,21 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
dev->agp->base, entry->bound);
return 0;
}
+EXPORT_SYMBOL(drm_agp_bind);
+
+int drm_agp_bind_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_binding_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_binding_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_bind(dev, &request);
+}
/**
* Free AGP memory (ioctl).
@@ -372,20 +402,13 @@ int drm_agp_bind(struct inode *inode, struct file *filp,
* unbind_agp(). Frees it via free_agp() as well as the entry itself
* and unlinks from the doubly linked list it's inserted in.
*/
-int drm_agp_free(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- drm_agp_buffer_t request;
drm_agp_mem_t *entry;
if (!dev->agp || !dev->agp->acquired)
return -EINVAL;
- if (copy_from_user
- (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
- return -EFAULT;
- if (!(entry = drm_agp_lookup_entry(dev, request.handle)))
+ if (!(entry = drm_agp_lookup_entry(dev, request->handle)))
return -EINVAL;
if (entry->bound)
drm_unbind_agp(entry->memory);
@@ -402,12 +425,30 @@ int drm_agp_free(struct inode *inode, struct file *filp,
drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
return 0;
}
+EXPORT_SYMBOL(drm_agp_free);
+
+int drm_agp_free_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ drm_agp_buffer_t request;
+
+ if (copy_from_user
+ (&request, (drm_agp_buffer_t __user *) arg, sizeof(request)))
+ return -EFAULT;
+
+ return drm_agp_free(dev, &request);
+}
/**
* Initialize the AGP resources.
*
* \return pointer to a drm_agp_head structure.
*
+ * Gets the drm_agp_t structure which is made available by the agpgart module
+ * via the inter_module_* functions. Creates and initializes a drm_agp_head
+ * structure.
*/
drm_agp_head_t *drm_agp_init(drm_device_t * dev)
{
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 319bdea8de8a..1db12dcb6802 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -36,22 +36,21 @@
#include <linux/vmalloc.h>
#include "drmP.h"
-unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource)
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
{
return pci_resource_start(dev->pdev, resource);
}
-
EXPORT_SYMBOL(drm_get_resource_start);
-unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource)
+unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
{
return pci_resource_len(dev->pdev, resource);
}
EXPORT_SYMBOL(drm_get_resource_len);
-static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
- drm_local_map_t * map)
+static drm_map_list_t *drm_find_matching_map(drm_device_t *dev,
+ drm_local_map_t *map)
{
struct list_head *list;
@@ -74,7 +73,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t * dev,
#ifdef _LP64
static __inline__ unsigned int HandleID(unsigned long lhandle,
- drm_device_t * dev)
+ drm_device_t *dev)
{
static unsigned int map32_handle = START_RANGE;
unsigned int hash;
@@ -155,7 +154,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset,
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
- if (map->offset + map->size < map->offset ||
+ if (map->offset + (map->size-1) < map->offset ||
map->offset < virt_to_phys(high_memory)) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL;
@@ -301,6 +300,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
}
+ if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP))
+ return -EPERM;
+
err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags,
&maplist);
@@ -332,7 +334,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp,
*
* \sa drm_addmap
*/
-int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
+int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map)
{
struct list_head *list;
drm_map_list_t *r_list = NULL;
@@ -384,10 +386,9 @@ int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map)
return 0;
}
-
EXPORT_SYMBOL(drm_rmmap_locked);
-int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
+int drm_rmmap(drm_device_t *dev, drm_local_map_t *map)
{
int ret;
@@ -397,7 +398,6 @@ int drm_rmmap(drm_device_t * dev, drm_local_map_t * map)
return ret;
}
-
EXPORT_SYMBOL(drm_rmmap);
/* The rmmap ioctl appears to be unnecessary. All mappings are torn down on
@@ -548,7 +548,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
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("agp_offset: %lx\n", agp_offset);
DRM_DEBUG("alignment: %d\n", alignment);
DRM_DEBUG("page_order: %d\n", page_order);
DRM_DEBUG("total: %d\n", total);
@@ -649,6 +649,8 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -664,7 +666,6 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
-
EXPORT_SYMBOL(drm_addbufs_agp);
#endif /* __OS_HAS_AGP */
@@ -689,9 +690,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
if (!drm_core_check_feature(dev, DRIVER_PCI_DMA))
return -EINVAL;
+
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -882,7 +887,6 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-
EXPORT_SYMBOL(drm_addbufs_pci);
static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
@@ -908,6 +912,9 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -1026,6 +1033,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -1042,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request)
return 0;
}
-static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
+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;
@@ -1065,6 +1074,9 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
if (!dma)
return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
count = request->count;
order = drm_order(request->size);
size = 1 << order;
@@ -1181,6 +1193,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
}
dma->buf_count += entry->buf_count;
+ dma->seg_count += entry->seg_count;
+ dma->page_count += byte_count >> PAGE_SHIFT;
dma->byte_count += byte_count;
DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count);
@@ -1196,6 +1210,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request)
atomic_dec(&dev->buf_alloc);
return 0;
}
+EXPORT_SYMBOL(drm_addbufs_fb);
+
/**
* Add buffers for DMA transfers (ioctl).
@@ -1577,5 +1593,6 @@ int drm_order(unsigned long size)
return order;
}
-
EXPORT_SYMBOL(drm_order);
+
+
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index bd958d69a2ac..f84254526949 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -433,7 +433,7 @@ int drm_addctx(struct inode *inode, struct file *filp,
if (ctx.handle != DRM_KERNEL_CONTEXT) {
if (dev->driver->context_ctor)
if (!dev->driver->context_ctor(dev, ctx.handle)) {
- DRM_DEBUG( "Running out of ctxs or memory.\n");
+ DRM_DEBUG("Running out of ctxs or memory.\n");
return -ENOMEM;
}
}
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h
index cc97bb906dda..f4f9db6c7ed4 100644
--- a/drivers/char/drm/drm_core.h
+++ b/drivers/char/drm/drm_core.h
@@ -24,11 +24,11 @@
#define CORE_NAME "drm"
#define CORE_DESC "DRM shared core routines"
-#define CORE_DATE "20040925"
+#define CORE_DATE "20051102"
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 2
#define CORE_MAJOR 1
#define CORE_MINOR 0
-#define CORE_PATCHLEVEL 0
+#define CORE_PATCHLEVEL 1
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 4dff7554eb08..c4fa5a29582b 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -56,66 +56,66 @@ static int drm_version(struct inode *inode, struct file *filp,
/** Ioctl table */
static drm_ioctl_desc_t drm_ioctls[] = {
- [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, 0, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, 0, 1},
-
- [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, 1, 1},
- [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_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},
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, 1, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, 1, 0},
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, 1, 1},
-
- [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, 1, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, 1, 0},
-
- [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, 1, 0},
-
- [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, 1, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, 1, 0},
- [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, 1, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH},
+
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH},
/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH},
- [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
#if __OS_HAS_AGP
- [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},
- [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
#endif
- [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, 1, 1},
- [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, 1, 1},
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
- [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0},
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0},
};
#define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls )
@@ -129,7 +129,7 @@ static drm_ioctl_desc_t drm_ioctls[] = {
*
* \sa drm_device
*/
-int drm_takedown(drm_device_t * dev)
+int drm_lastclose(drm_device_t * dev)
{
drm_magic_entry_t *pt, *next;
drm_map_list_t *r_list;
@@ -138,9 +138,9 @@ int drm_takedown(drm_device_t * dev)
DRM_DEBUG("\n");
- if (dev->driver->pretakedown)
- dev->driver->pretakedown(dev);
- DRM_DEBUG("driver pretakedown completed\n");
+ if (dev->driver->lastclose)
+ dev->driver->lastclose(dev);
+ DRM_DEBUG("driver lastclose completed\n");
if (dev->unique) {
drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
@@ -233,7 +233,7 @@ int drm_takedown(drm_device_t * dev)
}
up(&dev->struct_sem);
- DRM_DEBUG("takedown completed\n");
+ DRM_DEBUG("lastclose completed\n");
return 0;
}
@@ -281,7 +281,7 @@ EXPORT_SYMBOL(drm_init);
/**
* Called via cleanup_module() at module unload time.
*
- * Cleans up all DRM device, calling takedown().
+ * Cleans up all DRM device, calling drm_lastclose().
*
* \sa drm_init
*/
@@ -294,7 +294,7 @@ static void drm_cleanup(drm_device_t * dev)
return;
}
- drm_takedown(dev);
+ drm_lastclose(dev);
if (dev->maplist) {
drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS);
@@ -317,8 +317,8 @@ static void drm_cleanup(drm_device_t * dev)
dev->agp = NULL;
}
- if (dev->driver->postcleanup)
- dev->driver->postcleanup(dev);
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
drm_put_head(&dev->primary);
if (drm_put_dev(dev))
@@ -342,12 +342,12 @@ void drm_exit(struct drm_driver *driver)
if (head->dev->driver != driver)
continue;
dev = head->dev;
- }
- if (dev) {
- /* release the pci driver */
- if (dev->pdev)
- pci_dev_put(dev->pdev);
- drm_cleanup(dev);
+ if (dev) {
+ /* release the pci driver */
+ if (dev->pdev)
+ pci_dev_put(dev->pdev);
+ drm_cleanup(dev);
+ }
}
DRM_INFO("Module unloaded\n");
}
@@ -432,14 +432,17 @@ static int drm_version(struct inode *inode, struct file *filp,
drm_device_t *dev = priv->head->dev;
drm_version_t __user *argp = (void __user *)arg;
drm_version_t version;
- int ret;
+ int len;
if (copy_from_user(&version, argp, sizeof(version)))
return -EFAULT;
- /* version is a required function to return the personality module version */
- if ((ret = dev->driver->version(&version)))
- return ret;
+ version.version_major = dev->driver->major;
+ version.version_minor = dev->driver->minor;
+ version.version_patchlevel = dev->driver->patchlevel;
+ DRM_COPY(version.name, dev->driver->name);
+ DRM_COPY(version.date, dev->driver->date);
+ DRM_COPY(version.desc, dev->driver->desc);
if (copy_to_user(argp, &version, sizeof(version)))
return -EFAULT;
@@ -493,8 +496,9 @@ int drm_ioctl(struct inode *inode, struct file *filp,
if (!func) {
DRM_DEBUG("no function\n");
retcode = -EINVAL;
- } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) ||
- (ioctl->auth_needed && !priv->authenticated)) {
+ } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
+ ((ioctl->flags & DRM_AUTH) && !priv->authenticated) ||
+ ((ioctl->flags & DRM_MASTER) && !priv->master)) {
retcode = -EACCES;
} else {
retcode = func(inode, filp, cmd, arg);
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index bf0a740122bf..403f44a1bf01 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -35,6 +35,7 @@
*/
#include "drmP.h"
+#include "drm_sarea.h"
#include <linux/poll.h>
static int drm_open_helper(struct inode *inode, struct file *filp,
@@ -42,15 +43,21 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
static int drm_setup(drm_device_t * dev)
{
+ drm_local_map_t *map;
int i;
int ret;
- if (dev->driver->presetup) {
- ret = dev->driver->presetup(dev);
+ if (dev->driver->firstopen) {
+ ret = dev->driver->firstopen(dev);
if (ret != 0)
return ret;
}
+ /* prebuild the SAREA */
+ i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map);
+ if (i != 0)
+ return i;
+
atomic_set(&dev->ioctl_count, 0);
atomic_set(&dev->vma_count, 0);
dev->buf_use = 0;
@@ -109,8 +116,6 @@ static int drm_setup(drm_device_t * dev)
* drm_select_queue fails between the time the interrupt is
* initialized and the time the queues are initialized.
*/
- if (dev->driver->postsetup)
- dev->driver->postsetup(dev);
return 0;
}
@@ -154,10 +159,168 @@ int drm_open(struct inode *inode, struct file *filp)
return retcode;
}
-
EXPORT_SYMBOL(drm_open);
/**
+ * File \c open operation.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ *
+ * Puts the dev->fops corresponding to the device minor number into
+ * \p filp, call the \c open method, and restore the file operations.
+ */
+int drm_stub_open(struct inode *inode, struct file *filp)
+{
+ drm_device_t *dev = NULL;
+ int minor = iminor(inode);
+ int err = -ENODEV;
+ struct file_operations *old_fops;
+
+ DRM_DEBUG("\n");
+
+ if (!((minor >= 0) && (minor < drm_cards_limit)))
+ return -ENODEV;
+
+ if (!drm_heads[minor])
+ return -ENODEV;
+
+ if (!(dev = drm_heads[minor]->dev))
+ return -ENODEV;
+
+ old_fops = filp->f_op;
+ filp->f_op = fops_get(&dev->driver->fops);
+ if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
+ fops_put(filp->f_op);
+ filp->f_op = fops_get(old_fops);
+ }
+ fops_put(old_fops);
+
+ return err;
+}
+
+/**
+ * Check whether DRI will run on this CPU.
+ *
+ * \return non-zero if the DRI will run on this CPU, or zero otherwise.
+ */
+static int drm_cpu_valid(void)
+{
+#if defined(__i386__)
+ if (boot_cpu_data.x86 == 3)
+ return 0; /* No cmpxchg on a 386 */
+#endif
+#if defined(__sparc__) && !defined(__sparc_v9__)
+ return 0; /* No cmpxchg before v9 sparc. */
+#endif
+ return 1;
+}
+
+/**
+ * Called whenever a process opens /dev/drm.
+ *
+ * \param inode device inode.
+ * \param filp file pointer.
+ * \param dev device.
+ * \return zero on success or a negative number on failure.
+ *
+ * Creates and initializes a drm_file structure for the file private data in \p
+ * filp and add it into the double linked list in \p dev.
+ */
+static int drm_open_helper(struct inode *inode, struct file *filp,
+ drm_device_t * dev)
+{
+ int minor = iminor(inode);
+ drm_file_t *priv;
+ int ret;
+
+ if (filp->f_flags & O_EXCL)
+ return -EBUSY; /* No exclusive opens */
+ if (!drm_cpu_valid())
+ return -EINVAL;
+
+ DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
+
+ priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
+ if (!priv)
+ return -ENOMEM;
+
+ memset(priv, 0, sizeof(*priv));
+ filp->private_data = priv;
+ priv->uid = current->euid;
+ priv->pid = current->pid;
+ priv->minor = minor;
+ priv->head = drm_heads[minor];
+ priv->ioctl_count = 0;
+ /* for compatibility root is always authenticated */
+ priv->authenticated = capable(CAP_SYS_ADMIN);
+ priv->lock_count = 0;
+
+ if (dev->driver->open) {
+ ret = dev->driver->open(dev, priv);
+ if (ret < 0)
+ goto out_free;
+ }
+
+ down(&dev->struct_sem);
+ if (!dev->file_last) {
+ priv->next = NULL;
+ priv->prev = NULL;
+ dev->file_first = priv;
+ dev->file_last = priv;
+ /* first opener automatically becomes master */
+ priv->master = 1;
+ } else {
+ priv->next = NULL;
+ priv->prev = dev->file_last;
+ dev->file_last->next = priv;
+ dev->file_last = priv;
+ }
+ up(&dev->struct_sem);
+
+#ifdef __alpha__
+ /*
+ * Default the hose
+ */
+ if (!dev->hose) {
+ struct pci_dev *pci_dev;
+ pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
+ if (pci_dev) {
+ dev->hose = pci_dev->sysdata;
+ pci_dev_put(pci_dev);
+ }
+ if (!dev->hose) {
+ struct pci_bus *b = pci_bus_b(pci_root_buses.next);
+ if (b)
+ dev->hose = b->sysdata;
+ }
+ }
+#endif
+
+ return 0;
+ out_free:
+ drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
+ filp->private_data = NULL;
+ return ret;
+}
+
+/** No-op. */
+int drm_fasync(int fd, struct file *filp, int on)
+{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->head->dev;
+ int retcode;
+
+ DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
+ (long)old_encode_dev(priv->head->device));
+ retcode = fasync_helper(fd, filp, on, &dev->buf_async);
+ if (retcode < 0)
+ return retcode;
+ return 0;
+}
+EXPORT_SYMBOL(drm_fasync);
+
+/**
* Release file.
*
* \param inode device inode
@@ -167,7 +330,7 @@ EXPORT_SYMBOL(drm_open);
* If the hardware lock is held then free it, and take it again for the kernel
* context since it's necessary to reclaim buffers. Unlink the file private
* data from its list and free it. Decreases the open count and if it reaches
- * zero calls takedown().
+ * zero calls drm_lastclose().
*/
int drm_release(struct inode *inode, struct file *filp)
{
@@ -180,8 +343,8 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("open_count = %d\n", dev->open_count);
- if (dev->driver->prerelease)
- dev->driver->prerelease(dev, filp);
+ if (dev->driver->preclose)
+ dev->driver->preclose(dev, filp);
/* ========================================================
* Begin inline drm_release
@@ -197,8 +360,8 @@ int drm_release(struct inode *inode, struct file *filp)
DRM_DEBUG("File %p released, freeing lock for context %d\n",
filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
- if (dev->driver->release)
- dev->driver->release(dev, filp);
+ if (dev->driver->reclaim_buffers_locked)
+ dev->driver->reclaim_buffers_locked(dev, filp);
drm_lock_free(dev, &dev->lock.hw_lock->lock,
_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock));
@@ -207,7 +370,7 @@ int drm_release(struct inode *inode, struct file *filp)
hardware at this point, possibly
processed via a callback to the X
server. */
- } else if (dev->driver->release && priv->lock_count
+ } else if (dev->driver->reclaim_buffers_locked && priv->lock_count
&& dev->lock.hw_lock) {
/* The lock is required to reclaim buffers */
DECLARE_WAITQUEUE(entry, current);
@@ -237,15 +400,14 @@ int drm_release(struct inode *inode, struct file *filp)
__set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry);
if (!retcode) {
- if (dev->driver->release)
- dev->driver->release(dev, filp);
+ dev->driver->reclaim_buffers_locked(dev, filp);
drm_lock_free(dev, &dev->lock.hw_lock->lock,
DRM_KERNEL_CONTEXT);
}
}
- if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)
- && !dev->driver->release) {
+ if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) &&
+ !dev->driver->reclaim_buffers_locked) {
dev->driver->reclaim_buffers(dev, filp);
}
@@ -292,9 +454,8 @@ int drm_release(struct inode *inode, struct file *filp)
}
up(&dev->struct_sem);
- if (dev->driver->free_filp_priv)
- dev->driver->free_filp_priv(dev, priv);
-
+ if (dev->driver->postclose)
+ dev->driver->postclose(dev, priv);
drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
/* ========================================================
@@ -313,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
}
spin_unlock(&dev->count_lock);
unlock_kernel();
- return drm_takedown(dev);
+ return drm_lastclose(dev);
}
spin_unlock(&dev->count_lock);
@@ -321,129 +482,11 @@ int drm_release(struct inode *inode, struct file *filp)
return retcode;
}
-
EXPORT_SYMBOL(drm_release);
-/**
- * Called whenever a process opens /dev/drm.
- *
- * \param inode device inode.
- * \param filp file pointer.
- * \param dev device.
- * \return zero on success or a negative number on failure.
- *
- * Creates and initializes a drm_file structure for the file private data in \p
- * filp and add it into the double linked list in \p dev.
- */
-static int drm_open_helper(struct inode *inode, struct file *filp,
- drm_device_t * dev)
-{
- int minor = iminor(inode);
- drm_file_t *priv;
- int ret;
-
- if (filp->f_flags & O_EXCL)
- return -EBUSY; /* No exclusive opens */
- if (!drm_cpu_valid())
- return -EINVAL;
-
- DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor);
-
- priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES);
- if (!priv)
- return -ENOMEM;
-
- memset(priv, 0, sizeof(*priv));
- filp->private_data = priv;
- priv->uid = current->euid;
- priv->pid = current->pid;
- priv->minor = minor;
- priv->head = drm_heads[minor];
- priv->ioctl_count = 0;
- priv->authenticated = capable(CAP_SYS_ADMIN);
- priv->lock_count = 0;
-
- if (dev->driver->open_helper) {
- ret = dev->driver->open_helper(dev, priv);
- if (ret < 0)
- goto out_free;
- }
-
- down(&dev->struct_sem);
- if (!dev->file_last) {
- priv->next = NULL;
- priv->prev = NULL;
- dev->file_first = priv;
- dev->file_last = priv;
- } else {
- priv->next = NULL;
- priv->prev = dev->file_last;
- dev->file_last->next = priv;
- dev->file_last = priv;
- }
- up(&dev->struct_sem);
-
-#ifdef __alpha__
- /*
- * Default the hose
- */
- if (!dev->hose) {
- struct pci_dev *pci_dev;
- pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
- if (pci_dev) {
- dev->hose = pci_dev->sysdata;
- pci_dev_put(pci_dev);
- }
- if (!dev->hose) {
- struct pci_bus *b = pci_bus_b(pci_root_buses.next);
- if (b)
- dev->hose = b->sysdata;
- }
- }
-#endif
-
- return 0;
- out_free:
- drm_free(priv, sizeof(*priv), DRM_MEM_FILES);
- filp->private_data = NULL;
- return ret;
-}
-
-/** No-op. */
-int drm_flush(struct file *filp)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
-
- DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
- current->pid, (long)old_encode_dev(priv->head->device),
- dev->open_count);
- return 0;
-}
-
-EXPORT_SYMBOL(drm_flush);
-
-/** No-op. */
-int drm_fasync(int fd, struct file *filp, int on)
-{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
- int retcode;
-
- DRM_DEBUG("fd = %d, device = 0x%lx\n", fd,
- (long)old_encode_dev(priv->head->device));
- retcode = fasync_helper(fd, filp, on, &dev->buf_async);
- if (retcode < 0)
- return retcode;
- return 0;
-}
-
-EXPORT_SYMBOL(drm_fasync);
-
/** No-op. */
unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
{
return 0;
}
-
EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c
deleted file mode 100644
index 754b934715c4..000000000000
--- a/drivers/char/drm/drm_init.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * \file drm_init.c
- * Setup/Cleanup for DRM
- *
- * \author Rickard E. (Rik) Faith <faith@valinux.com>
- * \author Gareth Hughes <gareth@valinux.com>
- */
-
-/*
- * Created: Mon Jan 4 08:58:31 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.
- */
-
-#include "drmP.h"
-
-/**
- * Check whether DRI will run on this CPU.
- *
- * \return non-zero if the DRI will run on this CPU, or zero otherwise.
- */
-int drm_cpu_valid(void)
-{
-#if defined(__i386__)
- if (boot_cpu_data.x86 == 3)
- return 0; /* No cmpxchg on a 386 */
-#endif
-#if defined(__sparc__) && !defined(__sparc_v9__)
- return 0; /* No cmpxchg before v9 sparc. */
-#endif
- return 1;
-}
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
index dd91ff6b474c..e9e2db18952d 100644
--- a/drivers/char/drm/drm_ioc32.c
+++ b/drivers/char/drm/drm_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm_core.h"
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
index 9b0feba6b063..bcd4e604d3ec 100644
--- a/drivers/char/drm/drm_ioctl.c
+++ b/drivers/char/drm/drm_ioctl.c
@@ -137,17 +137,22 @@ int drm_setunique(struct inode *inode, struct file *filp,
static int drm_set_busid(drm_device_t * dev)
{
+ int len;
+
if (dev->unique != NULL)
return EBUSY;
- dev->unique_len = 20;
+ dev->unique_len = 40;
dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER);
if (dev->unique == NULL)
return ENOMEM;
- snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
+ len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d",
dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func);
+ if (len > dev->unique_len)
+ DRM_ERROR("Unique buffer overflowed\n");
+
dev->devname =
drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len +
2, DRM_MEM_DRIVER);
@@ -239,7 +244,7 @@ int drm_getclient(struct inode *inode, struct file *filp,
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
- drm_client_t __user *argp = (void __user *)arg;
+ drm_client_t __user *argp = (drm_client_t __user *)arg;
drm_client_t client;
drm_file_t *pt;
int idx;
@@ -262,7 +267,7 @@ int drm_getclient(struct inode *inode, struct file *filp,
client.iocs = pt->ioctl_count;
up(&dev->struct_sem);
- if (copy_to_user((drm_client_t __user *) arg, &client, sizeof(client)))
+ if (copy_to_user(argp, &client, sizeof(client)))
return -EFAULT;
return 0;
}
@@ -325,17 +330,13 @@ int drm_setversion(DRM_IOCTL_ARGS)
drm_set_version_t retv;
int if_version;
drm_set_version_t __user *argp = (void __user *)data;
- drm_version_t version;
DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv));
- memset(&version, 0, sizeof(version));
-
- dev->driver->version(&version);
retv.drm_di_major = DRM_IF_MAJOR;
retv.drm_di_minor = DRM_IF_MINOR;
- retv.drm_dd_major = version.version_major;
- retv.drm_dd_minor = version.version_minor;
+ retv.drm_dd_major = dev->driver->major;
+ retv.drm_dd_minor = dev->driver->minor;
DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv));
@@ -343,7 +344,7 @@ int drm_setversion(DRM_IOCTL_ARGS)
if (sv.drm_di_major != DRM_IF_MAJOR ||
sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR)
return EINVAL;
- if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor);
+ if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor);
dev->if_version = DRM_MAX(if_version, dev->if_version);
if (sv.drm_di_minor >= 1) {
/*
@@ -354,9 +355,9 @@ int drm_setversion(DRM_IOCTL_ARGS)
}
if (sv.drm_dd_major != -1) {
- if (sv.drm_dd_major != version.version_major ||
+ if (sv.drm_dd_major != dev->driver->major ||
sv.drm_dd_minor < 0
- || sv.drm_dd_minor > version.version_minor)
+ || sv.drm_dd_minor > dev->driver->minor)
return EINVAL;
if (dev->driver->set_version)
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index b48a595d54ec..f9e45303498d 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -130,7 +130,6 @@ int drm_lock(struct inode *inode, struct file *filp,
/* dev->driver->kernel_context_switch isn't used by any of the x86
* drivers but is used by the Sparc driver.
*/
-
if (dev->driver->kernel_context_switch &&
dev->last_context != lock.context) {
dev->driver->kernel_context_switch(dev, dev->last_context,
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index abef2acf99f5..8074771e348f 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -145,30 +145,22 @@ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 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_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index b370aca718d2..e84605fc54af 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -1,5 +1,5 @@
/**
- * \file drm_memory.h
+ * \file drm_memory_debug.h
* Memory management wrappers for DRM.
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
@@ -43,42 +43,41 @@ typedef struct drm_mem_stats {
unsigned long bytes_freed;
} drm_mem_stats_t;
-static DEFINE_SPINLOCK(DRM(mem_lock));
-static unsigned long DRM(ram_available) = 0; /* In pages */
-static unsigned long DRM(ram_used) = 0;
-static drm_mem_stats_t DRM(mem_stats)[] =
+static spinlock_t drm_mem_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long drm_ram_available = 0; /* In pages */
+static unsigned long drm_ram_used = 0;
+static drm_mem_stats_t drm_mem_stats[] =
{
- [DRM_MEM_DMA] = {
- "dmabufs"},[DRM_MEM_SAREA] = {
- "sareas"},[DRM_MEM_DRIVER] = {
- "driver"},[DRM_MEM_MAGIC] = {
- "magic"},[DRM_MEM_IOCTLS] = {
- "ioctltab"},[DRM_MEM_MAPS] = {
- "maplist"},[DRM_MEM_VMAS] = {
- "vmalist"},[DRM_MEM_BUFS] = {
- "buflist"},[DRM_MEM_SEGS] = {
- "seglist"},[DRM_MEM_PAGES] = {
- "pagelist"},[DRM_MEM_FILES] = {
- "files"},[DRM_MEM_QUEUES] = {
- "queues"},[DRM_MEM_CMDS] = {
- "commands"},[DRM_MEM_MAPPINGS] = {
- "mappings"},[DRM_MEM_BUFLISTS] = {
- "buflists"},[DRM_MEM_AGPLISTS] = {
- "agplist"},[DRM_MEM_SGLISTS] = {
- "sglist"},[DRM_MEM_TOTALAGP] = {
- "totalagp"},[DRM_MEM_BOUNDAGP] = {
- "boundagp"},[DRM_MEM_CTXBITMAP] = {
- "ctxbitmap"},[DRM_MEM_CTXLIST] = {
- "ctxlist"},[DRM_MEM_STUB] = {
- "stub"}, {
- NULL, 0,} /* Last entry must be null */
+ [DRM_MEM_DMA] = {"dmabufs"},
+ [DRM_MEM_SAREA] = {"sareas"},
+ [DRM_MEM_DRIVER] = {"driver"},
+ [DRM_MEM_MAGIC] = {"magic"},
+ [DRM_MEM_IOCTLS] = {"ioctltab"},
+ [DRM_MEM_MAPS] = {"maplist"},
+ [DRM_MEM_VMAS] = {"vmalist"},
+ [DRM_MEM_BUFS] = {"buflist"},
+ [DRM_MEM_SEGS] = {"seglist"},
+ [DRM_MEM_PAGES] = {"pagelist"},
+ [DRM_MEM_FILES] = {"files"},
+ [DRM_MEM_QUEUES] = {"queues"},
+ [DRM_MEM_CMDS] = {"commands"},
+ [DRM_MEM_MAPPINGS] = {"mappings"},
+ [DRM_MEM_BUFLISTS] = {"buflists"},
+ [DRM_MEM_AGPLISTS] = {"agplist"},
+ [DRM_MEM_SGLISTS] = {"sglist"},
+ [DRM_MEM_TOTALAGP] = {"totalagp"},
+ [DRM_MEM_BOUNDAGP] = {"boundagp"},
+ [DRM_MEM_CTXBITMAP] = {"ctxbitmap"},
+ [DRM_MEM_CTXLIST] = {"ctxlist"},
+ [DRM_MEM_STUB] = {"stub"},
+ {NULL, 0,} /* Last entry must be null */
};
-void DRM(mem_init) (void) {
+void drm_mem_init (void) {
drm_mem_stats_t *mem;
struct sysinfo si;
- for (mem = DRM(mem_stats); mem->name; ++mem) {
+ for (mem = drm_mem_stats; mem->name; ++mem) {
mem->succeed_count = 0;
mem->free_count = 0;
mem->fail_count = 0;
@@ -87,13 +86,13 @@ void DRM(mem_init) (void) {
}
si_meminfo(&si);
- DRM(ram_available) = si.totalram;
- DRM(ram_used) = 0;
+ drm_ram_available = si.totalram;
+ drm_ram_used = 0;
}
/* drm_mem_info is called whenever a process reads /dev/drm/mem. */
-static int DRM(_mem_info) (char *buf, char **start, off_t offset,
+static int drm__mem_info (char *buf, char **start, off_t offset,
int request, int *eof, void *data) {
drm_mem_stats_t *pt;
int len = 0;
@@ -112,11 +111,11 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset,
" | allocs bytes\n\n");
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
"system", 0, 0, 0,
- DRM(ram_available) << (PAGE_SHIFT - 10));
+ drm_ram_available << (PAGE_SHIFT - 10));
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
- "locked", 0, 0, 0, DRM(ram_used) >> 10);
+ "locked", 0, 0, 0, drm_ram_used >> 10);
DRM_PROC_PRINT("\n");
- for (pt = DRM(mem_stats); pt->name; pt++) {
+ for (pt = drm_mem_stats; pt->name; pt++) {
DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
pt->name,
pt->succeed_count,
@@ -135,17 +134,17 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset,
return len - offset;
}
-int DRM(mem_info) (char *buf, char **start, off_t offset,
+int drm_mem_info (char *buf, char **start, off_t offset,
int len, int *eof, void *data) {
int ret;
- spin_lock(&DRM(mem_lock));
- ret = DRM(_mem_info) (buf, start, offset, len, eof, data);
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ret = drm__mem_info (buf, start, offset, len, eof, data);
+ spin_unlock(&drm_mem_lock);
return ret;
}
-void *DRM(alloc) (size_t size, int area) {
+void *drm_alloc (size_t size, int area) {
void *pt;
if (!size) {
@@ -154,41 +153,41 @@ void *DRM(alloc) (size_t size, int area) {
}
if (!(pt = kmalloc(size, GFP_KERNEL))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].succeed_count;
- DRM(mem_stats)[area].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].succeed_count;
+ drm_mem_stats[area].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
return pt;
}
-void *DRM(calloc) (size_t nmemb, size_t size, int area) {
+void *drm_calloc (size_t nmemb, size_t size, int area) {
void *addr;
- addr = DRM(alloc) (nmemb * size, area);
+ addr = drm_alloc (nmemb * size, area);
if (addr != NULL)
memset((void *)addr, 0, size * nmemb);
return addr;
}
-void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) {
+void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) {
void *pt;
- if (!(pt = DRM(alloc) (size, area)))
+ if (!(pt = drm_alloc (size, area)))
return NULL;
if (oldpt && oldsize) {
memcpy(pt, oldpt, oldsize);
- DRM(free) (oldpt, oldsize, area);
+ drm_free (oldpt, oldsize, area);
}
return pt;
}
-void DRM(free) (void *pt, size_t size, int area) {
+void drm_free (void *pt, size_t size, int area) {
int alloc_count;
int free_count;
@@ -196,43 +195,43 @@ void DRM(free) (void *pt, size_t size, int area) {
DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n");
else
kfree(pt);
- spin_lock(&DRM(mem_lock));
- DRM(mem_stats)[area].bytes_freed += size;
- free_count = ++DRM(mem_stats)[area].free_count;
- alloc_count = DRM(mem_stats)[area].succeed_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ drm_mem_stats[area].bytes_freed += size;
+ free_count = ++drm_mem_stats[area].free_count;
+ alloc_count = drm_mem_stats[area].succeed_count;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n",
free_count, alloc_count);
}
}
-unsigned long DRM(alloc_pages) (int order, int area) {
+unsigned long drm_alloc_pages (int order, int area) {
unsigned long address;
unsigned long bytes = PAGE_SIZE << order;
unsigned long addr;
unsigned int sz;
- spin_lock(&DRM(mem_lock));
- if ((DRM(ram_used) >> PAGE_SHIFT)
- > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ if ((drm_ram_used >> PAGE_SHIFT)
+ > (DRM_RAM_PERCENT * drm_ram_available) / 100) {
+ spin_unlock(&drm_mem_lock);
return 0;
}
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
if (!address) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].fail_count;
+ spin_unlock(&drm_mem_lock);
return 0;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[area].succeed_count;
- DRM(mem_stats)[area].bytes_allocated += bytes;
- DRM(ram_used) += bytes;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[area].succeed_count;
+ drm_mem_stats[area].bytes_allocated += bytes;
+ drm_ram_used += bytes;
+ spin_unlock(&drm_mem_lock);
/* Zero outside the lock */
memset((void *)address, 0, bytes);
@@ -246,7 +245,7 @@ unsigned long DRM(alloc_pages) (int order, int area) {
return address;
}
-void DRM(free_pages) (unsigned long address, int order, int area) {
+void drm_free_pages (unsigned long address, int order, int area) {
unsigned long bytes = PAGE_SIZE << order;
int alloc_count;
int free_count;
@@ -264,12 +263,12 @@ void DRM(free_pages) (unsigned long address, int order, int area) {
free_pages(address, order);
}
- spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[area].free_count;
- alloc_count = DRM(mem_stats)[area].succeed_count;
- DRM(mem_stats)[area].bytes_freed += bytes;
- DRM(ram_used) -= bytes;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ free_count = ++drm_mem_stats[area].free_count;
+ alloc_count = drm_mem_stats[area].succeed_count;
+ drm_mem_stats[area].bytes_freed += bytes;
+ drm_ram_used -= bytes;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(area,
"Excess frees: %d frees, %d allocs\n",
@@ -277,7 +276,7 @@ void DRM(free_pages) (unsigned long address, int order, int area) {
}
}
-void *DRM(ioremap) (unsigned long offset, unsigned long size,
+void *drm_ioremap (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -288,19 +287,19 @@ void *DRM(ioremap) (unsigned long offset, unsigned long size,
}
if (!(pt = drm_ioremap(offset, size, dev))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
return pt;
}
-void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
+void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
drm_device_t * dev) {
void *pt;
@@ -311,19 +310,19 @@ void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size,
}
if (!(pt = drm_ioremap_nocache(offset, size, dev))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size;
+ spin_unlock(&drm_mem_lock);
return pt;
}
-void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
+void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
int alloc_count;
int free_count;
@@ -333,11 +332,11 @@ void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
else
drm_ioremapfree(pt, size, dev);
- spin_lock(&DRM(mem_lock));
- DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
- free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
- alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size;
+ free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count;
+ alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count;
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Excess frees: %d frees, %d allocs\n",
@@ -347,7 +346,7 @@ void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) {
#if __OS_HAS_AGP
-DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
+DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) {
DRM_AGP_MEM *handle;
if (!pages) {
@@ -355,21 +354,21 @@ DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) {
return NULL;
}
- if ((handle = DRM(agp_allocate_memory) (pages, type))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
- DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
+ if ((handle = drm_agp_allocate_memory (pages, type))) {
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+ drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated
+= pages << PAGE_SHIFT;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
return handle;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count;
+ spin_unlock(&drm_mem_lock);
return NULL;
}
-int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
+int drm_free_agp (DRM_AGP_MEM * handle, int pages) {
int alloc_count;
int free_count;
int retval = -EINVAL;
@@ -380,13 +379,13 @@ int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
return retval;
}
- if (DRM(agp_free_memory) (handle)) {
- spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
- alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
- DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
+ if (drm_agp_free_memory (handle)) {
+ spin_lock(&drm_mem_lock);
+ free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count;
+ alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count;
+ drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed
+= pages << PAGE_SHIFT;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
"Excess frees: %d frees, %d allocs\n",
@@ -397,7 +396,7 @@ int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) {
return retval;
}
-int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
+int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) {
int retcode = -EINVAL;
if (!handle) {
@@ -406,21 +405,21 @@ int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) {
return retcode;
}
- if (!(retcode = DRM(agp_bind_memory) (handle, start))) {
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
- DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
+ if (!(retcode = drm_agp_bind_memory (handle, start))) {
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+ drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated
+= handle->page_count << PAGE_SHIFT;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
return retcode;
}
- spin_lock(&DRM(mem_lock));
- ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
- spin_unlock(&DRM(mem_lock));
+ spin_lock(&drm_mem_lock);
+ ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count;
+ spin_unlock(&drm_mem_lock);
return retcode;
}
-int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
+int drm_unbind_agp (DRM_AGP_MEM * handle) {
int alloc_count;
int free_count;
int retcode = -EINVAL;
@@ -431,14 +430,14 @@ int DRM(unbind_agp) (DRM_AGP_MEM * handle) {
return retcode;
}
- if ((retcode = DRM(agp_unbind_memory) (handle)))
+ if ((retcode = drm_agp_unbind_memory (handle)))
return retcode;
- spin_lock(&DRM(mem_lock));
- free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
- alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
- DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
+ spin_lock(&drm_mem_lock);
+ free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count;
+ alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count;
+ drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed
+= handle->page_count << PAGE_SHIFT;
- spin_unlock(&DRM(mem_lock));
+ spin_unlock(&drm_mem_lock);
if (free_count > alloc_count) {
DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
"Excess frees: %d frees, %d allocs\n",
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index d51aeb4966f4..695115d70382 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -13,6 +13,7 @@
#define DRM_ERR(d) -(d)
/** Current process ID */
#define DRM_CURRENTPID current->pid
+#define DRM_SUSER(p) capable(CAP_SYS_ADMIN)
#define DRM_UDELAY(d) udelay(d)
/** Read a byte from a MMIO region */
#define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset))
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index d66dc55e29a0..5b1d3a04458d 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -46,6 +46,7 @@
{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, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \
{0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \
{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}, \
@@ -69,6 +70,7 @@
{0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \
{0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
+ {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
{0x1002, 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}, \
@@ -82,10 +84,13 @@
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \
{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
{0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+ {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \
+ {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \
{0, 0, 0}
#define r128_PCI_IDS \
@@ -176,7 +181,7 @@
#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, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \
{0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
@@ -196,6 +201,10 @@
{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, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
{0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \
@@ -234,3 +243,4 @@
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2772, 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 3f452f763f0f..6f943e3309ef 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -61,16 +61,14 @@ static struct drm_proc_list {
const char *name; /**< file name */
int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/
} drm_proc_list[] = {
- {
- "name", drm_name_info}, {
- "mem", drm_mem_info}, {
- "vm", drm_vm_info}, {
- "clients", drm_clients_info}, {
- "queues", drm_queues_info}, {
- "bufs", drm_bufs_info},
+ {"name", drm_name_info},
+ {"mem", drm_mem_info},
+ {"vm", drm_vm_info},
+ {"clients", drm_clients_info},
+ {"queues", drm_queues_info},
+ {"bufs", drm_bufs_info},
#if DRM_DEBUG_CODE
- {
- "vma", drm_vma_info},
+ {"vma", drm_vma_info},
#endif
};
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 60b6f8e8bf69..42d766359caa 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -93,8 +93,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
dev->driver = driver;
- if (dev->driver->preinit)
- if ((retcode = dev->driver->preinit(dev, ent->driver_data)))
+ if (dev->driver->load)
+ if ((retcode = dev->driver->load(dev, ent->driver_data)))
goto error_out_unreg;
if (drm_core_has_AGP(dev)) {
@@ -124,47 +124,10 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev,
return 0;
error_out_unreg:
- drm_takedown(dev);
+ drm_lastclose(dev);
return retcode;
}
-/**
- * File \c open operation.
- *
- * \param inode device inode.
- * \param filp file pointer.
- *
- * Puts the dev->fops corresponding to the device minor number into
- * \p filp, call the \c open method, and restore the file operations.
- */
-int drm_stub_open(struct inode *inode, struct file *filp)
-{
- drm_device_t *dev = NULL;
- int minor = iminor(inode);
- int err = -ENODEV;
- struct file_operations *old_fops;
-
- DRM_DEBUG("\n");
-
- if (!((minor >= 0) && (minor < drm_cards_limit)))
- return -ENODEV;
-
- if (!drm_heads[minor])
- return -ENODEV;
-
- if (!(dev = drm_heads[minor]->dev))
- return -ENODEV;
-
- old_fops = filp->f_op;
- filp->f_op = fops_get(&dev->driver->fops);
- if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
- fops_put(filp->f_op);
- filp->f_op = fops_get(old_fops);
- }
- fops_put(old_fops);
-
- return err;
-}
/**
* Get a secondary minor number.
@@ -200,11 +163,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head)
goto err_g1;
}
- head->dev_class = drm_sysfs_device_add(drm_class,
- MKDEV(DRM_MAJOR,
- minor),
- &dev->pdev->dev,
- "card%d", minor);
+ head->dev_class = drm_sysfs_device_add(drm_class, head);
if (IS_ERR(head->dev_class)) {
printk(KERN_ERR
"DRM: Error sysfs_device_add.\n");
@@ -258,11 +217,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
}
if ((ret = drm_get_head(dev, &dev->primary)))
goto err_g1;
-
- /* postinit is a required function to display the signon banner */
- /* drivers add secondary heads here if needed */
- if ((ret = dev->driver->postinit(dev, ent->driver_data)))
- goto err_g1;
+
+ DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+ driver->name, driver->major, driver->minor, driver->patchlevel,
+ driver->date, dev->primary.minor);
return 0;
@@ -318,10 +276,9 @@ int drm_put_head(drm_head_t * head)
DRM_DEBUG("release secondary minor %d\n", minor);
drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
- drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
+ drm_sysfs_device_remove(head->dev_class);
- *head = (drm_head_t) {
- .dev = NULL};
+ *head = (drm_head_t) {.dev = NULL};
drm_heads[minor] = NULL;
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c
index 6d3449761914..68e43ddc16ae 100644
--- a/drivers/char/drm/drm_sysfs.c
+++ b/drivers/char/drm/drm_sysfs.c
@@ -15,8 +15,6 @@
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/string.h>
#include "drm_core.h"
#include "drmP.h"
@@ -28,15 +26,11 @@ struct drm_sysfs_class {
#define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
struct simple_dev {
- struct list_head node;
dev_t dev;
struct class_device class_dev;
};
#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-static LIST_HEAD(simple_dev_list);
-static DEFINE_SPINLOCK(simple_dev_list_lock);
-
static void release_simple_dev(struct class_device *class_dev)
{
struct simple_dev *s_dev = to_simple_dev(class_dev);
@@ -124,6 +118,18 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs)
class_unregister(&cs->class);
}
+static ssize_t show_dri(struct class_device *class_device, char *buf)
+{
+ drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev;
+ if (dev->driver->dri_library_name)
+ return dev->driver->dri_library_name(dev, buf);
+ return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name);
+}
+
+static struct class_device_attribute class_device_attrs[] = {
+ __ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
+};
+
/**
* drm_sysfs_device_add - adds a class device to sysfs for a character driver
* @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
@@ -138,13 +144,11 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs)
* Note: the struct drm_sysfs_class passed to this function must have previously been
* created with a call to drm_sysfs_create().
*/
-struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
- struct device *device,
- const char *fmt, ...)
+struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs,
+ drm_head_t *head)
{
- va_list args;
struct simple_dev *s_dev = NULL;
- int retval;
+ int i, retval;
if ((cs == NULL) || (IS_ERR(cs))) {
retval = -ENODEV;
@@ -158,26 +162,23 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
}
memset(s_dev, 0x00, sizeof(*s_dev));
- s_dev->dev = dev;
- s_dev->class_dev.dev = device;
+ s_dev->dev = MKDEV(DRM_MAJOR, head->minor);
+ s_dev->class_dev.dev = &(head->dev->pdev)->dev;
s_dev->class_dev.class = &cs->class;
- va_start(args, fmt);
- vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
- va_end(args);
+ snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor);
retval = class_device_register(&s_dev->class_dev);
if (retval)
goto error;
class_device_create_file(&s_dev->class_dev, &cs->attr);
+ class_set_devdata(&s_dev->class_dev, head);
- spin_lock(&simple_dev_list_lock);
- list_add(&s_dev->node, &simple_dev_list);
- spin_unlock(&simple_dev_list_lock);
-
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]);
return &s_dev->class_dev;
- error:
+error:
kfree(s_dev);
return ERR_PTR(retval);
}
@@ -189,23 +190,12 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
* This call unregisters and cleans up a class device that was created with a
* call to drm_sysfs_device_add()
*/
-void drm_sysfs_device_remove(dev_t dev)
+void drm_sysfs_device_remove(struct class_device *class_dev)
{
- struct simple_dev *s_dev = NULL;
- int found = 0;
-
- spin_lock(&simple_dev_list_lock);
- list_for_each_entry(s_dev, &simple_dev_list, node) {
- if (s_dev->dev == dev) {
- found = 1;
- break;
- }
- }
- if (found) {
- list_del(&s_dev->node);
- spin_unlock(&simple_dev_list_lock);
- class_device_unregister(&s_dev->class_dev);
- } else {
- spin_unlock(&simple_dev_list_lock);
- }
+ struct simple_dev *s_dev = to_simple_dev(class_dev);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+ class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]);
+ class_device_unregister(&s_dev->class_dev);
}
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index dba502373da1..cc1b89086876 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -114,7 +114,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static struct file_operations i810_buffer_fops = {
.open = drm_open,
- .flush = drm_flush,
.release = drm_release,
.ioctl = drm_ioctl,
.mmap = i810_mmap_buffers,
@@ -1319,12 +1318,24 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp,
return 0;
}
-void i810_driver_pretakedown(drm_device_t * dev)
+int i810_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i810 has 4 more counters */
+ dev->counters += 4;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+
+ return 0;
+}
+
+void i810_driver_lastclose(drm_device_t * dev)
{
i810_dma_cleanup(dev);
}
-void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i810_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1334,7 +1345,7 @@ void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void i810_driver_release(drm_device_t * dev, struct file *filp)
+void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
{
i810_reclaim_buffers(dev, filp);
}
@@ -1346,21 +1357,21 @@ int i810_driver_dma_quiescent(drm_device_t * dev)
}
drm_ioctl_desc_t i810_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, 1, 1},
- [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, 1, 1},
- [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, 1, 0},
- [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, 1, 0}
+ [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, DRM_AUTH}
};
int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
index 070cef6c2b46..dfe6ad2b6a6e 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -38,38 +38,6 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
-{
- /* i810 has 4 more counters */
- dev->counters += 4;
- dev->types[6] = _DRM_STAT_IRQ;
- dev->types[7] = _DRM_STAT_PRIMARY;
- dev->types[8] = _DRM_STAT_SECONDARY;
- dev->types[9] = _DRM_STAT_DMA;
-
- 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[] = {
i810_PCI_IDS
};
@@ -79,16 +47,14 @@ static struct drm_driver driver = {
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
.dev_priv_size = sizeof(drm_i810_buf_priv_t),
- .pretakedown = i810_driver_pretakedown,
- .prerelease = i810_driver_prerelease,
+ .load = i810_driver_load,
+ .lastclose = i810_driver_lastclose,
+ .preclose = i810_driver_preclose,
.device_is_agp = i810_driver_device_is_agp,
- .release = i810_driver_release,
+ .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
.dma_quiescent = i810_driver_dma_quiescent,
- .reclaim_buffers = i810_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = i810_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -98,13 +64,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
- ,
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i810_init(void)
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index c78f36aaa2f0..a18b80d91920 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -116,9 +116,13 @@ typedef struct drm_i810_private {
extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp);
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 void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+ struct file *filp);
+extern int i810_driver_load(struct drm_device *, unsigned long flags);
+extern void i810_driver_lastclose(drm_device_t * dev);
+extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev,
+ struct file *filp);
extern int i810_driver_device_is_agp(drm_device_t * dev);
extern drm_ioctl_desc_t i810_ioctls[];
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index dc94f1914425..4fea32aed6d2 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -116,7 +116,6 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
static struct file_operations i830_buffer_fops = {
.open = drm_open,
- .flush = drm_flush,
.release = drm_release,
.ioctl = drm_ioctl,
.mmap = i830_mmap_buffers,
@@ -1517,12 +1516,24 @@ static int i830_setparam(struct inode *inode, struct file *filp,
return 0;
}
-void i830_driver_pretakedown(drm_device_t * dev)
+int i830_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i830 has 4 more counters */
+ dev->counters += 4;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+
+ return 0;
+}
+
+void i830_driver_lastclose(drm_device_t * dev)
{
i830_dma_cleanup(dev);
}
-void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i830_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i830_private_t *dev_priv = dev->dev_private;
@@ -1532,7 +1543,7 @@ void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void i830_driver_release(drm_device_t * dev, struct file *filp)
+void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp)
{
i830_reclaim_buffers(dev, filp);
}
@@ -1544,20 +1555,20 @@ int i830_driver_dma_quiescent(drm_device_t * dev)
}
drm_ioctl_desc_t i830_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, 1, 1},
- [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, 1, 0},
- [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, 1, 0}
+ [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, DRM_AUTH}
};
int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index acd821e8fe4d..722658188f5f 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -40,37 +40,6 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
-{
- dev->counters += 4;
- dev->types[6] = _DRM_STAT_IRQ;
- dev->types[7] = _DRM_STAT_PRIMARY;
- dev->types[8] = _DRM_STAT_SECONDARY;
- dev->types[9] = _DRM_STAT_DMA;
-
- 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[] = {
i830_PCI_IDS
};
@@ -83,12 +52,12 @@ static struct drm_driver driver = {
.driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
#endif
.dev_priv_size = sizeof(drm_i830_buf_priv_t),
- .pretakedown = i830_driver_pretakedown,
- .prerelease = i830_driver_prerelease,
+ .load = i830_driver_load,
+ .lastclose = i830_driver_lastclose,
+ .preclose = i830_driver_preclose,
.device_is_agp = i830_driver_device_is_agp,
- .release = i830_driver_release,
+ .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
.dma_quiescent = i830_driver_dma_quiescent,
- .reclaim_buffers = i830_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
#if USE_IRQS
@@ -97,8 +66,6 @@ static struct drm_driver driver = {
.irq_uninstall = i830_driver_irq_uninstall,
.irq_handler = i830_driver_irq_handler,
#endif
- .postinit = postinit,
- .version = version,
.ioctls = i830_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -108,13 +75,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i830_init(void)
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index bc4bd49fb0cc..bf9075b576bd 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -136,10 +136,12 @@ extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
extern void i830_driver_irq_preinstall(drm_device_t * dev);
extern void i830_driver_irq_postinstall(drm_device_t * dev);
extern void i830_driver_irq_uninstall(drm_device_t * dev);
-extern void i830_driver_pretakedown(drm_device_t * dev);
-extern void i830_driver_release(drm_device_t * dev, struct file *filp);
+extern int i830_driver_load(struct drm_device *, unsigned long flags);
+extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void i830_driver_lastclose(drm_device_t * dev);
+extern void i830_driver_reclaim_buffers_locked(drm_device_t * dev,
+ 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_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index f3aa0c370127..9140703da1ba 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -1,7 +1,6 @@
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,7 +24,7 @@
* 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 "drm.h"
@@ -196,7 +195,7 @@ static int i915_initialize(drm_device_t * dev,
return 0;
}
-static int i915_resume(drm_device_t * dev)
+static int i915_dma_resume(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -253,7 +252,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS)
retcode = i915_dma_cleanup(dev);
break;
case I915_RESUME_DMA:
- retcode = i915_resume(dev);
+ retcode = i915_dma_resume(dev);
break;
default:
retcode = -EINVAL;
@@ -654,6 +653,9 @@ static int i915_getparam(DRM_IOCTL_ARGS)
case I915_PARAM_ALLOW_BATCHBUFFER:
value = dev_priv->allow_batchbuffer ? 1 : 0;
break;
+ case I915_PARAM_LAST_DISPATCH:
+ value = READ_BREADCRUMB(dev_priv);
+ break;
default:
DRM_ERROR("Unkown parameter %d\n", param.param);
return DRM_ERR(EINVAL);
@@ -699,7 +701,19 @@ static int i915_setparam(DRM_IOCTL_ARGS)
return 0;
}
-void i915_driver_pretakedown(drm_device_t * dev)
+int i915_driver_load(drm_device_t *dev, unsigned long flags)
+{
+ /* i915 has 4 more counters */
+ dev->counters += 4;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+ dev->types[9] = _DRM_STAT_DMA;
+
+ return 0;
+}
+
+void i915_driver_lastclose(drm_device_t * dev)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -708,7 +722,7 @@ void i915_driver_pretakedown(drm_device_t * dev)
i915_dma_cleanup(dev);
}
-void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void i915_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -717,18 +731,18 @@ void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
drm_ioctl_desc_t i915_ioctls[] = {
- [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
- [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
+ [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 23e027d29080..77412ddac007 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -1,5 +1,4 @@
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -23,7 +22,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#ifndef _I915_DRM_H_
#define _I915_DRM_H_
@@ -152,6 +151,7 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_IRQ_ACTIVE 1
#define I915_PARAM_ALLOW_BATCHBUFFER 2
+#define I915_PARAM_LAST_DISPATCH 3
typedef struct drm_i915_getparam {
int param;
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 0508240f4e3b..8e2e6095c4b3 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -1,6 +1,6 @@
/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
*/
-/**************************************************************************
+/*
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -25,7 +25,7 @@
* 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 "drm.h"
@@ -34,48 +34,22 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
-{
- dev->counters += 4;
- dev->types[6] = _DRM_STAT_IRQ;
- dev->types[7] = _DRM_STAT_PRIMARY;
- dev->types[8] = _DRM_STAT_SECONDARY;
- dev->types[9] = _DRM_STAT_DMA;
-
- 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[] = {
i915_PCI_IDS
};
static struct drm_driver driver = {
+ /* don't use mtrr's here, the Xserver or user space app should
+ * deal with them for intel hardware.
+ */
.driver_features =
- DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
- .pretakedown = i915_driver_pretakedown,
- .prerelease = i915_driver_prerelease,
+ DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .load = i915_driver_load,
+ .lastclose = i915_driver_lastclose,
+ .preclose = i915_driver_preclose,
.device_is_agp = i915_driver_device_is_agp,
+ .vblank_wait = i915_driver_vblank_wait,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
@@ -83,8 +57,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = i915_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -97,11 +69,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = i915_compat_ioctl,
#endif
- },
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init i915_init(void)
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 17e457c73dc7..c6c71b45f101 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -1,6 +1,6 @@
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
-/**************************************************************************
+/*
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
@@ -25,7 +25,7 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
- **************************************************************************/
+ */
#ifndef _I915_DRV_H_
#define _I915_DRV_H_
@@ -37,21 +37,18 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20040405"
+#define DRIVER_DATE "20051209"
/* Interface history:
*
* 1.1: Original.
+ * 1.2: Add Power Management
+ * 1.3: Add vblank support
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 1
+#define DRIVER_MINOR 3
#define DRIVER_PATCHLEVEL 0
-/* We use our own dma mechanisms, not the drm template code. However,
- * the shared IRQ code is useful to us:
- */
-#define __HAVE_PM 1
-
typedef struct _drm_i915_ring_buffer {
int tail_mask;
unsigned long Start;
@@ -97,6 +94,7 @@ typedef struct drm_i915_private {
int tex_lru_log_granularity;
int allow_batchbuffer;
struct mem_block *agp_heap;
+ unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
} drm_i915_private_t;
extern drm_ioctl_desc_t i915_ioctls[];
@@ -104,14 +102,18 @@ extern int i915_max_ioctl;
/* i915_dma.c */
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_load(struct drm_device *, unsigned long flags);
+extern void i915_driver_lastclose(drm_device_t * dev);
+extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp);
extern int i915_driver_device_is_agp(drm_device_t * dev);
+extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
/* i915_irq.c */
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
@@ -125,13 +127,10 @@ extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(drm_device_t * dev,
DRMFILE filp, struct mem_block *heap);
-extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
-
-#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
-#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
-#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
-#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val)
+#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
+#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
+#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
+#define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val))
#define I915_VERBOSE 0
@@ -195,6 +194,13 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define PPCR 0x61204
#define PPCR_ON (1<<0)
+#define DVOB 0x61140
+#define DVOB_ON (1<<31)
+#define DVOC 0x61160
+#define DVOC_ON (1<<31)
+#define LVDS 0x61180
+#define LVDS_ON (1<<31)
+
#define ADPA 0x61100
#define ADPA_DPMS_MASK (~(3<<10))
#define ADPA_DPMS_ON (0<<10)
@@ -258,4 +264,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5])
+
#endif
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
index 2218a946ec87..296248cdc767 100644
--- a/drivers/char/drm/i915_ioc32.c
+++ b/drivers/char/drm/i915_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 4fa448ee846b..a1381c61aa63 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -1,7 +1,6 @@
-/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
+/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,16 +24,18 @@
* 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 "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
-#define USER_INT_FLAG 0x2
+#define USER_INT_FLAG (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+
#define MAX_NOPID ((u32)~0)
-#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
@@ -43,7 +44,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
u16 temp;
temp = I915_READ16(I915REG_INT_IDENTITY_R);
- temp &= USER_INT_FLAG;
+ temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
@@ -51,7 +52,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
- DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & USER_INT_FLAG)
+ DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & VSYNC_PIPEA_FLAG) {
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+ }
return IRQ_HANDLED;
}
@@ -102,6 +111,27 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received))
+ - *sequence) <= (1<<23)));
+
+ *sequence = cur_vblank;
+
+ return ret;
+}
+
+
/* Needs the lock as it touches the ring.
*/
int i915_irq_emit(DRM_IOCTL_ARGS)
@@ -165,7 +195,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
+ I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index 13176d136a99..ba87ff17ff64 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -1,7 +1,6 @@
/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
*/
-/**************************************************************************
- *
+/*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
@@ -25,7 +24,7 @@
* 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 "drm.h"
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 70dc7f64b7b9..c2a4bac14521 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -44,7 +44,9 @@
#define MGA_DEFAULT_USEC_TIMEOUT 10000
#define MGA_FREELIST_DEBUG 0
-static int mga_do_cleanup_dma(drm_device_t * dev);
+#define MINIMAL_CLEANUP 0
+#define FULL_CLEANUP 1
+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup);
/* ================================================================
* Engine control
@@ -391,7 +393,7 @@ 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)
+int mga_driver_load(drm_device_t * dev, unsigned long flags)
{
drm_mga_private_t *dev_priv;
@@ -405,6 +407,14 @@ int mga_driver_preinit(drm_device_t * dev, unsigned long flags)
dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
dev_priv->chipset = flags;
+ dev_priv->mmio_base = drm_get_resource_start(dev, 1);
+ dev_priv->mmio_size = drm_get_resource_len(dev, 1);
+
+ dev->counters += 3;
+ dev->types[6] = _DRM_STAT_IRQ;
+ dev->types[7] = _DRM_STAT_PRIMARY;
+ dev->types[8] = _DRM_STAT_SECONDARY;
+
return 0;
}
@@ -438,17 +448,19 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
drm_buf_desc_t req;
drm_agp_mode_t mode;
drm_agp_info_t info;
+ drm_agp_buffer_t agp_req;
+ drm_agp_binding_t bind_req;
/* Acquire AGP. */
err = drm_agp_acquire(dev);
if (err) {
- DRM_ERROR("Unable to acquire AGP\n");
+ DRM_ERROR("Unable to acquire AGP: %d\n", err);
return err;
}
err = drm_agp_info(dev, &info);
if (err) {
- DRM_ERROR("Unable to get AGP info\n");
+ DRM_ERROR("Unable to get AGP info: %d\n", err);
return err;
}
@@ -472,18 +484,24 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
}
/* 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;
+ agp_req.size = agp_size;
+ agp_req.type = 0;
+ err = drm_agp_alloc(dev, &agp_req);
+ if (err) {
+ dev_priv->agp_size = 0;
DRM_ERROR("Unable to allocate %uMB AGP memory\n",
dma_bs->agp_size);
- return DRM_ERR(ENOMEM);
+ return err;
}
+
+ dev_priv->agp_size = agp_size;
+ dev_priv->agp_handle = agp_req.handle;
- err = drm_bind_agp(dev_priv->agp_mem, 0);
+ bind_req.handle = agp_req.handle;
+ bind_req.offset = 0;
+ err = drm_agp_bind(dev, &bind_req);
if (err) {
- DRM_ERROR("Unable to bind AGP memory\n");
+ DRM_ERROR("Unable to bind AGP memory: %d\n", err);
return err;
}
@@ -497,7 +515,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map WARP microcode: %d\n", err);
return err;
}
@@ -505,7 +523,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map primary DMA region: %d\n", err);
return err;
}
@@ -513,7 +531,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map secondary DMA region: %d\n", err);
return err;
}
@@ -525,15 +543,29 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev,
err = drm_addbufs_agp(dev, &req);
if (err) {
- DRM_ERROR("Unable to add secondary DMA buffers\n");
+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
return err;
}
+ {
+ drm_map_list_t *_entry;
+ unsigned long agp_token = 0;
+
+ list_for_each_entry(_entry, &dev->maplist->head, head) {
+ if (_entry->map == dev->agp_buffer_map)
+ agp_token = _entry->user_token;
+ }
+ if (!agp_token)
+ return -EFAULT;
+
+ dev->agp_buffer_token = agp_token;
+ }
+
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");
+ DRM_ERROR("Unable to map AGP texture region %d\n", err);
return err;
}
@@ -603,7 +635,8 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to create mapping for WARP microcode: %d\n",
+ err);
return err;
}
@@ -622,7 +655,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
}
if (err != 0) {
- DRM_ERROR("Unable to allocate primary DMA region\n");
+ DRM_ERROR("Unable to allocate primary DMA region: %d\n", err);
return DRM_ERR(ENOMEM);
}
@@ -646,7 +679,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev,
}
if (bin_count == 0) {
- DRM_ERROR("Unable to add secondary DMA buffers\n");
+ DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err);
return err;
}
@@ -682,7 +715,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
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");
+ DRM_ERROR("Unable to map MMIO region: %d\n", err);
return err;
}
@@ -690,7 +723,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
_DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL,
&dev_priv->status);
if (err) {
- DRM_ERROR("Unable to map status region\n");
+ DRM_ERROR("Unable to map status region: %d\n", err);
return err;
}
@@ -708,7 +741,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev,
*/
if (err) {
- mga_do_cleanup_dma(dev);
+ mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
}
/* Not only do we want to try and initialized PCI cards for PCI DMA,
@@ -731,35 +764,32 @@ int mga_dma_bootstrap(DRM_IOCTL_ARGS)
DRM_DEVICE;
drm_mga_dma_bootstrap_t bootstrap;
int 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;
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;
- }
+ if (err) {
+ mga_do_cleanup_dma(dev, FULL_CLEANUP);
+ return err;
+ }
- bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
- if (DRM_COPY_TO_USER((void __user *)data, &bootstrap,
- sizeof(bootstrap))) {
- err = DRM_ERR(EFAULT);
- }
+ if (dev_priv->agp_textures != NULL) {
+ bootstrap.texture_handle = dev_priv->agp_textures->offset;
+ bootstrap.texture_size = dev_priv->agp_textures->size;
} else {
- mga_do_cleanup_dma(dev);
+ bootstrap.texture_handle = 0;
+ bootstrap.texture_size = 0;
}
+ bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07];
+ DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data,
+ bootstrap, sizeof(bootstrap));
+
return err;
}
@@ -853,13 +883,13 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
ret = mga_warp_install_microcode(dev_priv);
if (ret < 0) {
- DRM_ERROR("failed to install WARP ucode!\n");
+ DRM_ERROR("failed to install WARP ucode!: %d\n", ret);
return ret;
}
ret = mga_warp_init(dev_priv);
if (ret < 0) {
- DRM_ERROR("failed to init WARP engine!\n");
+ DRM_ERROR("failed to init WARP engine!: %d\n", ret);
return ret;
}
@@ -904,7 +934,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
return 0;
}
-static int mga_do_cleanup_dma(drm_device_t * dev)
+static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup)
{
int err = 0;
DRM_DEBUG("\n");
@@ -932,31 +962,39 @@ static int mga_do_cleanup_dma(drm_device_t * 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);
+ if (dev_priv->agp_handle != 0) {
+ drm_agp_binding_t unbind_req;
+ drm_agp_buffer_t free_req;
+
+ unbind_req.handle = dev_priv->agp_handle;
+ drm_agp_unbind(dev, &unbind_req);
- drm_free_agp(dev_priv->agp_mem,
- dev_priv->agp_pages);
- dev_priv->agp_pages = 0;
- dev_priv->agp_mem = NULL;
+ free_req.handle = dev_priv->agp_handle;
+ drm_agp_free(dev, &free_req);
+
+ dev_priv->agp_textures = NULL;
+ dev_priv->agp_size = 0;
+ dev_priv->agp_handle = 0;
}
if ((dev->agp != NULL) && dev->agp->acquired) {
err = drm_agp_release(dev);
}
#endif
- dev_priv->used_new_dma_init = 0;
}
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;
+ if (full_cleanup) {
+ dev_priv->mmio = NULL;
+ dev_priv->status = NULL;
+ dev_priv->used_new_dma_init = 0;
+ }
+
memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
dev_priv->warp_pipe = 0;
memset(dev_priv->warp_pipe_phys, 0,
@@ -967,7 +1005,7 @@ static int mga_do_cleanup_dma(drm_device_t * dev)
}
}
- return err;
+ return 0;
}
int mga_dma_init(DRM_IOCTL_ARGS)
@@ -985,11 +1023,11 @@ int mga_dma_init(DRM_IOCTL_ARGS)
case MGA_INIT_DMA:
err = mga_do_init_dma(dev, &init);
if (err) {
- (void)mga_do_cleanup_dma(dev);
+ (void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
return err;
case MGA_CLEANUP_DMA:
- return mga_do_cleanup_dma(dev);
+ return mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
return DRM_ERR(EINVAL);
@@ -1118,7 +1156,7 @@ int mga_dma_buffers(DRM_IOCTL_ARGS)
/**
* Called just before the module is unloaded.
*/
-int mga_driver_postcleanup(drm_device_t * dev)
+int mga_driver_unload(drm_device_t * dev)
{
drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
dev->dev_private = NULL;
@@ -1129,9 +1167,9 @@ int mga_driver_postcleanup(drm_device_t * dev)
/**
* Called when the last opener of the device is closed.
*/
-void mga_driver_pretakedown(drm_device_t * dev)
+void mga_driver_lastclose(drm_device_t * dev)
{
- mga_do_cleanup_dma(dev);
+ mga_do_cleanup_dma(dev, FULL_CLEANUP);
}
int mga_driver_dma_quiescent(drm_device_t * dev)
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 1713451a5cc6..9f7ed0e0351b 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -38,41 +38,6 @@
#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;
- dev->types[8] = _DRM_STAT_SECONDARY;
-
- 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[] = {
mga_PCI_IDS
@@ -80,12 +45,12 @@ static struct pci_device_id pciidlist[] = {
static struct drm_driver driver = {
.driver_features =
- DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
+ DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL,
- .preinit = mga_driver_preinit,
- .postcleanup = mga_driver_postcleanup,
- .pretakedown = mga_driver_pretakedown,
+ .load = mga_driver_load,
+ .unload = mga_driver_unload,
+ .lastclose = mga_driver_lastclose,
.dma_quiescent = mga_driver_dma_quiescent,
.device_is_agp = mga_driver_device_is_agp,
.vblank_wait = mga_driver_vblank_wait,
@@ -96,8 +61,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = mga_ioctls,
.dma_ioctl = mga_dma_buffers,
.fops = {
@@ -113,9 +76,16 @@ static struct drm_driver driver = {
#endif
},
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init mga_init(void)
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 461728e6a58a..6b0c53193506 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -38,11 +38,11 @@
#define DRIVER_NAME "mga"
#define DRIVER_DESC "Matrox G200/G400"
-#define DRIVER_DATE "20050607"
+#define DRIVER_DATE "20051102"
#define DRIVER_MAJOR 3
#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 0
+#define DRIVER_PATCHLEVEL 1
typedef struct drm_mga_primary_buffer {
u8 *start;
@@ -144,22 +144,22 @@ typedef struct drm_mga_private {
drm_local_map_t *primary;
drm_local_map_t *agp_textures;
- DRM_AGP_MEM *agp_mem;
- unsigned int agp_pages;
+ unsigned long agp_handle;
+ unsigned int agp_size;
} drm_mga_private_t;
extern drm_ioctl_desc_t mga_ioctls[];
extern int mga_max_ioctl;
/* mga_dma.c */
-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_load(drm_device_t *dev, unsigned long flags);
+extern int mga_driver_unload(drm_device_t * dev);
+extern void mga_driver_lastclose(drm_device_t * dev);
extern int mga_driver_dma_quiescent(drm_device_t * dev);
extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
index 24a9d4e86af0..54a18eb2fc04 100644
--- a/drivers/char/drm/mga_ioc32.c
+++ b/drivers/char/drm/mga_ioc32.c
@@ -31,7 +31,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
index 47f54b5ae956..2837e669183a 100644
--- a/drivers/char/drm/mga_state.c
+++ b/drivers/char/drm/mga_state.c
@@ -1127,19 +1127,19 @@ static int mga_wait_fence(DRM_IOCTL_ARGS)
}
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_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},
+ [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
};
int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 7452753d4d01..db5a60450e68 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -1,6 +1,7 @@
-/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
+/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
- *
+ */
+/*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
@@ -559,7 +560,8 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init)
if (dev_priv->is_pci) {
#endif
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
- dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0;
+ dev_priv->gart_info.addr = NULL;
+ dev_priv->gart_info.bus_addr = 0;
dev_priv->gart_info.is_pcie = 0;
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
DRM_ERROR("failed to init PCI GART!\n");
@@ -601,15 +603,16 @@ int r128_do_cleanup_cce(drm_device_t * dev)
drm_core_ioremapfree(dev_priv->cce_ring, dev);
if (dev_priv->ring_rptr != NULL)
drm_core_ioremapfree(dev_priv->ring_rptr, dev);
- if (dev->agp_buffer_map != NULL)
+ if (dev->agp_buffer_map != NULL) {
drm_core_ioremapfree(dev->agp_buffer_map, dev);
+ dev->agp_buffer_map = NULL;
+ }
} else
#endif
{
if (dev_priv->gart_info.bus_addr)
if (!drm_ati_pcigart_cleanup(dev,
- &dev_priv->
- gart_info))
+ &dev_priv->gart_info))
DRM_ERROR
("failed to cleanup PCI GART!\n");
}
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h
index 5ddc03202411..5d835b006f55 100644
--- a/drivers/char/drm/r128_drm.h
+++ b/drivers/char/drm/r128_drm.h
@@ -1,7 +1,7 @@
/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*-
* Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com
- *
- * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
+ */
+/* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 1661e7351402..e20450ae220e 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -37,31 +37,6 @@
#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[] = {
r128_PCI_IDS
};
@@ -72,8 +47,8 @@ static struct drm_driver driver = {
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
DRIVER_IRQ_VBL,
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
- .prerelease = r128_driver_prerelease,
- .pretakedown = r128_driver_pretakedown,
+ .preclose = r128_driver_preclose,
+ .lastclose = r128_driver_lastclose,
.vblank_wait = r128_driver_vblank_wait,
.irq_preinstall = r128_driver_irq_preinstall,
.irq_postinstall = r128_driver_irq_postinstall,
@@ -82,8 +57,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = r128_ioctls,
.dma_ioctl = r128_cce_buffers,
.fops = {
@@ -97,12 +70,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = r128_compat_ioctl,
#endif
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init r128_init(void)
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 5c79e40eb88f..94abffb2cca5 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -1,7 +1,7 @@
/* r128_drv.h -- Private header for r128 driver -*- linux-c -*-
* Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ */
+/* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
@@ -154,8 +154,8 @@ extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
extern void r128_driver_irq_preinstall(drm_device_t * dev);
extern void r128_driver_irq_postinstall(drm_device_t * dev);
extern void r128_driver_irq_uninstall(drm_device_t * dev);
-extern void r128_driver_pretakedown(drm_device_t * dev);
-extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp);
+extern void r128_driver_lastclose(drm_device_t * dev);
+extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp);
extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
index 1e2e367b8b82..9dd6d4116e47 100644
--- a/drivers/char/drm/r128_ioc32.c
+++ b/drivers/char/drm/r128_ioc32.c
@@ -30,7 +30,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index 27eb0e31bd3b..87f8ca2b0685 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -1,5 +1,5 @@
-/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*-
- *
+/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */
+/*
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
* The Weather Channel (TM) funded Tungsten Graphics to develop the
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 14479cc08a57..a080cdd6081e 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1,7 +1,7 @@
/* r128_state.c -- State support for r128 -*- linux-c -*-
* Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
- *
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ */
+/* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -220,7 +220,7 @@ static __inline__ void r128_emit_tex1(drm_r128_private_t * dev_priv)
ADVANCE_RING();
}
-static __inline__ void r128_emit_state(drm_r128_private_t * dev_priv)
+static void r128_emit_state(drm_r128_private_t * dev_priv)
{
drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
unsigned int dirty = sarea_priv->dirty;
@@ -1674,7 +1674,7 @@ static int r128_getparam(DRM_IOCTL_ARGS)
return 0;
}
-void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void r128_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1684,29 +1684,29 @@ void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void r128_driver_pretakedown(drm_device_t * dev)
+void r128_driver_lastclose(drm_device_t * dev)
{
r128_do_cleanup_cce(dev);
}
drm_ioctl_desc_t r128_ioctls[] = {
- [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, 1, 1},
- [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, 1, 1},
- [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, 1, 1},
- [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, 1, 1},
- [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, 1, 0},
- [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, 1, 1},
- [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, 1, 0},
+ [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH},
};
int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index 3a1ac5f78b43..291dbf4c8186 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -52,8 +52,8 @@ static const int r300_cliprect_cntl[4] = {
* 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_kcmd_buffer_t * cmdbuf, int n)
+static int r300_emit_cliprects(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf, int n)
{
drm_clip_rect_t box;
int nr;
@@ -216,6 +216,7 @@ void r300_init_reg_flags(void)
ADD_RANGE(R300_TX_UNK1_0, 16);
ADD_RANGE(R300_TX_SIZE_0, 16);
ADD_RANGE(R300_TX_FORMAT_0, 16);
+ ADD_RANGE(R300_TX_PITCH_0, 16);
/* Texture offset is dangerous and needs more checking */
ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET);
ADD_RANGE(R300_TX_UNK4_0, 16);
@@ -242,7 +243,7 @@ static __inline__ int r300_check_range(unsigned reg, int count)
/* 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,
+static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
u32 offset)
{
/* we realy want to check against end of video aperture
@@ -317,8 +318,8 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
*
* 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_kcmd_buffer_t * cmdbuf,
+static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header)
{
int reg;
@@ -363,8 +364,8 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv,
* the graphics card.
* Called by r300_do_cp_cmdbuf.
*/
-static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf,
+static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header)
{
int sz;
@@ -400,8 +401,8 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv,
* 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_kcmd_buffer_t * cmdbuf)
+static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
RING_LOCALS;
@@ -421,8 +422,8 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf,
+static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
u32 header)
{
int count, i, k;
@@ -489,8 +490,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
u32 header;
int count;
@@ -554,8 +555,8 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv,
* 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_kcmd_buffer_t * cmdbuf,
+static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf,
drm_r300_cmd_header_t header)
{
int n;
@@ -623,7 +624,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv,
/**
* Emit the sequence to pacify R300.
*/
-static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv)
+static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
{
RING_LOCALS;
@@ -657,9 +658,10 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf)
* commands on the DMA ring buffer.
* Called by the ioctl handler function radeon_cp_cmdbuf.
*/
-int r300_do_cp_cmdbuf(drm_device_t * dev,
+int r300_do_cp_cmdbuf(drm_device_t *dev,
DRMFILE filp,
- drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_file_t *filp_priv,
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_device_dma_t *dma = dev->dma;
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
index e5b73c002394..a0ed20e25221 100644
--- a/drivers/char/drm/r300_reg.h
+++ b/drivers/char/drm/r300_reg.h
@@ -797,6 +797,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_TX_FORMAT_YUV_MODE 0x00800000
+#define R300_TX_PITCH_0 0x4500
#define R300_TX_OFFSET_0 0x4540
/* BEGIN: Guess from R200 */
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 342302d46743..915665c7fe7c 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -1,5 +1,5 @@
-/* radeon_cp.c -- CP support for Radeon -*- linux-c -*-
- *
+/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */
+/*
* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* All Rights Reserved.
@@ -824,7 +824,7 @@ static int RADEON_READ_PLL(drm_device_t * dev, int addr)
return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
}
-static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr)
+static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
{
RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff);
return RADEON_READ(RADEON_PCIE_DATA);
@@ -1125,7 +1125,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
| (dev_priv->fb_location >> 16));
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
RADEON_WRITE(RADEON_MC_AGP_LOCATION,
(((dev_priv->gart_vm_start - 1 +
dev_priv->gart_size) & 0xffff0000) |
@@ -1152,7 +1152,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev,
dev_priv->ring.tail = cur_read_ptr;
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* set RADEON_AGP_BASE here instead of relying on X from user space */
RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
@@ -1278,13 +1278,15 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
/* Enable or disable PCI GART on the chip */
static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
{
- u32 tmp = RADEON_READ(RADEON_AIC_CNTL);
+ u32 tmp;
if (dev_priv->flags & CHIP_IS_PCIE) {
radeon_set_pciegart(dev_priv, on);
return;
}
+ tmp = RADEON_READ(RADEON_AIC_CNTL);
+
if (on) {
RADEON_WRITE(RADEON_AIC_CNTL,
tmp | RADEON_PCIGART_TRANSLATE_EN);
@@ -1312,13 +1314,17 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
+
DRM_DEBUG("\n");
- dev_priv->is_pci = init->is_pci;
+ if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP))
+ {
+ DRM_DEBUG("Forcing AGP card to PCI mode\n");
+ dev_priv->flags &= ~CHIP_IS_AGP;
+ }
- if (dev_priv->is_pci && !dev->sg) {
+ if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) {
DRM_ERROR("PCI GART memory not allocated!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1327,12 +1333,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (dev_priv->usec_timeout < 1 ||
dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
DRM_DEBUG("TIMEOUT problem!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- switch (init->func) {
+ switch(init->func) {
case RADEON_INIT_R200_CP:
dev_priv->microcode_version = UCODE_R200;
break;
@@ -1353,7 +1358,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
(init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1416,8 +1420,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
DRM_GETSAREA();
- dev_priv->fb_offset = init->fb_offset;
- dev_priv->mmio_offset = init->mmio_offset;
dev_priv->ring_offset = init->ring_offset;
dev_priv->ring_rptr_offset = init->ring_rptr_offset;
dev_priv->buffers_offset = init->buffers_offset;
@@ -1425,29 +1427,19 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
- dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
- if (!dev_priv->mmio) {
- DRM_ERROR("could not find mmio region!\n");
- dev->dev_private = (void *)dev_priv;
- radeon_do_cleanup_cp(dev);
- return DRM_ERR(EINVAL);
- }
dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
if (!dev_priv->cp_ring) {
DRM_ERROR("could not find cp ring region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
if (!dev_priv->ring_rptr) {
DRM_ERROR("could not find ring read pointer!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1455,7 +1447,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
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");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1465,7 +1456,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
drm_core_findmap(dev, init->gart_textures_offset);
if (!dev_priv->gart_textures) {
DRM_ERROR("could not find GART texture region!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1476,7 +1466,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
init->sarea_priv_offset);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
drm_core_ioremap(dev_priv->cp_ring, dev);
drm_core_ioremap(dev_priv->ring_rptr, dev);
drm_core_ioremap(dev->agp_buffer_map, dev);
@@ -1484,7 +1474,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
!dev_priv->ring_rptr->handle ||
!dev->agp_buffer_map->handle) {
DRM_ERROR("could not find ioremap agp regions!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(EINVAL);
}
@@ -1525,7 +1514,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
+ RADEON_READ(RADEON_CONFIG_APER_SIZE);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci)
+ if (dev_priv->flags & CHIP_IS_AGP)
dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
- dev->agp->base
+ dev_priv->gart_vm_start);
@@ -1551,7 +1540,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
} else
@@ -1561,25 +1550,28 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (dev_priv->pcigart_offset) {
dev_priv->gart_info.bus_addr =
dev_priv->pcigart_offset + dev_priv->fb_location;
+ dev_priv->gart_info.mapping.offset =
+ dev_priv->gart_info.bus_addr;
+ dev_priv->gart_info.mapping.size =
+ RADEON_PCIGART_TABLE_SIZE;
+
+ drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr =
- (unsigned long)drm_ioremap(dev_priv->gart_info.
- bus_addr,
- RADEON_PCIGART_TABLE_SIZE,
- dev);
+ dev_priv->gart_info.mapping.handle;
dev_priv->gart_info.is_pcie =
!!(dev_priv->flags & CHIP_IS_PCIE);
dev_priv->gart_info.gart_table_location =
DRM_ATI_GART_FB;
- DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",
+ DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
dev_priv->gart_info.addr,
dev_priv->pcigart_offset);
} else {
dev_priv->gart_info.gart_table_location =
DRM_ATI_GART_MAIN;
- dev_priv->gart_info.addr =
- dev_priv->gart_info.bus_addr = 0;
+ dev_priv->gart_info.addr = NULL;
+ dev_priv->gart_info.bus_addr = 0;
if (dev_priv->flags & CHIP_IS_PCIE) {
DRM_ERROR
("Cannot use PCI Express without GART in FB memory\n");
@@ -1590,7 +1582,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
DRM_ERROR("failed to init PCI GART!\n");
- dev->dev_private = (void *)dev_priv;
radeon_do_cleanup_cp(dev);
return DRM_ERR(ENOMEM);
}
@@ -1604,8 +1595,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
dev_priv->last_buf = 0;
- dev->dev_private = (void *)dev_priv;
-
radeon_do_engine_reset(dev);
return 0;
@@ -1624,11 +1613,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
drm_irq_uninstall(dev);
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
- if (dev_priv->cp_ring != NULL)
+ if (dev_priv->flags & CHIP_IS_AGP) {
+ if (dev_priv->cp_ring != NULL) {
drm_core_ioremapfree(dev_priv->cp_ring, dev);
- if (dev_priv->ring_rptr != NULL)
+ dev_priv->cp_ring = NULL;
+ }
+ if (dev_priv->ring_rptr != NULL) {
drm_core_ioremapfree(dev_priv->ring_rptr, dev);
+ dev_priv->ring_rptr = NULL;
+ }
if (dev->agp_buffer_map != NULL) {
drm_core_ioremapfree(dev->agp_buffer_map, dev);
dev->agp_buffer_map = NULL;
@@ -1636,17 +1629,20 @@ static int radeon_do_cleanup_cp(drm_device_t * dev)
} else
#endif
{
- if (dev_priv->gart_info.bus_addr)
+
+ if (dev_priv->gart_info.bus_addr) {
+ /* Turn off PCI GART */
+ radeon_set_pcigart(dev_priv, 0);
if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
DRM_ERROR("failed to cleanup PCI GART!\n");
+ }
- if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
- drm_ioremapfree((void *)dev_priv->gart_info.addr,
- RADEON_PCIGART_TABLE_SIZE, dev);
+ if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
+ {
+ drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
dev_priv->gart_info.addr = 0;
}
}
-
/* only clear to the start of flags */
memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
@@ -1672,7 +1668,7 @@ static int radeon_do_resume_cp(drm_device_t * dev)
DRM_DEBUG("Starting radeon_do_resume_cp()\n");
#if __OS_HAS_AGP
- if (!dev_priv->is_pci) {
+ if (dev_priv->flags & CHIP_IS_AGP) {
/* Turn off PCI GART */
radeon_set_pcigart(dev_priv, 0);
} else
@@ -2103,7 +2099,7 @@ int radeon_cp_buffers(DRM_IOCTL_ARGS)
return ret;
}
-int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
+int radeon_driver_load(struct drm_device *dev, unsigned long flags)
{
drm_radeon_private_t *dev_priv;
int ret = 0;
@@ -2136,11 +2132,14 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags)
dev_priv->flags |= CHIP_IS_PCIE;
DRM_DEBUG("%s card detected\n",
- ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI"));
+ ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI"))));
return ret;
}
-int radeon_presetup(struct drm_device *dev)
+/* Create mappings for registers and framebuffer so userland doesn't necessarily
+ * have to find them.
+ */
+int radeon_driver_firstopen(struct drm_device *dev)
{
int ret;
drm_local_map_t *map;
@@ -2161,12 +2160,11 @@ int radeon_presetup(struct drm_device *dev)
return 0;
}
-int radeon_driver_postcleanup(struct drm_device *dev)
+int radeon_driver_unload(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("\n");
-
drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
dev->dev_private = NULL;
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index 1cd81a671a36..9c177a6b2a4c 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -624,6 +624,11 @@ typedef struct drm_radeon_indirect {
int discard;
} drm_radeon_indirect_t;
+/* enum for card type parameters */
+#define RADEON_CARD_PCI 0
+#define RADEON_CARD_AGP 1
+#define RADEON_CARD_PCIE 2
+
/* 1.3: An ioctl to get parameters that aren't available to the 3d
* client any other way.
*/
@@ -640,6 +645,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_SAREA_HANDLE 9
#define RADEON_PARAM_GART_TEX_HANDLE 10
#define RADEON_PARAM_SCRATCH_OFFSET 11
+#define RADEON_PARAM_CARD_TYPE 12
typedef struct drm_radeon_getparam {
int param;
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index ee49670d8162..b04ed1b562b9 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -42,29 +42,15 @@ int radeon_no_wb;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
module_param_named(no_wb, radeon_no_wb, int, 0444);
-static int postinit(struct drm_device *dev, unsigned long flags)
+static int dri_library_name(struct drm_device *dev, char *buf)
{
- 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;
+ drm_radeon_private_t *dev_priv = dev->dev_private;
+ int family = dev_priv->flags & CHIP_FAMILY_MASK;
- 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;
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ (family < CHIP_R200) ? "radeon" :
+ ((family < CHIP_R300) ? "r200" :
+ "r300"));
}
static struct pci_device_id pciidlist[] = {
@@ -77,23 +63,22 @@ static struct drm_driver driver = {
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,
- .open_helper = radeon_driver_open_helper,
+ .load = radeon_driver_load,
+ .firstopen = radeon_driver_firstopen,
+ .open = radeon_driver_open,
+ .preclose = radeon_driver_preclose,
+ .postclose = radeon_driver_postclose,
+ .lastclose = radeon_driver_lastclose,
+ .unload = radeon_driver_unload,
.vblank_wait = radeon_driver_vblank_wait,
+ .dri_library_name = dri_library_name,
.irq_preinstall = radeon_driver_irq_preinstall,
.irq_postinstall = radeon_driver_irq_postinstall,
.irq_uninstall = radeon_driver_irq_uninstall,
.irq_handler = radeon_driver_irq_handler,
- .free_filp_priv = radeon_driver_free_filp_priv,
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = radeon_ioctls,
.dma_ioctl = radeon_cp_buffers,
.fops = {
@@ -107,12 +92,19 @@ static struct drm_driver driver = {
#ifdef CONFIG_COMPAT
.compat_ioctl = radeon_compat_ioctl,
#endif
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init radeon_init(void)
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index d92ccee3e54c..498b19b1d641 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
-#define DRIVER_DATE "20050911"
+#define DRIVER_DATE "20051229"
/* Interface history:
*
@@ -73,7 +73,7 @@
* 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color
* and GL_EXT_blend_[func|equation]_separate on r200
* 1.12- Add R300 CP microcode support - this just loads the CP on r300
- * (No 3D support yet - just microcode loading)
+ * (No 3D support yet - just microcode loading).
* 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters
* - Add hyperz support, add hyperz flags to clear ioctl.
* 1.14- Add support for color tiling
@@ -88,14 +88,13 @@
* R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR
* (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6)
* 1.19- Add support for gart table in FB memory and PCIE r300
+ * 1.20- Add support for r300 texrect
+ * 1.21- Add support for card type getparam
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 19
+#define DRIVER_MINOR 21
#define DRIVER_PATCHLEVEL 0
-#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
-#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
-
/*
* Radeon chip families
*/
@@ -103,8 +102,8 @@ enum radeon_family {
CHIP_R100,
CHIP_RS100,
CHIP_RV100,
- CHIP_R200,
CHIP_RV200,
+ CHIP_R200,
CHIP_RS200,
CHIP_R250,
CHIP_RS250,
@@ -138,6 +137,9 @@ enum radeon_chip_flags {
CHIP_IS_PCIE = 0x00200000UL,
};
+#define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 )
+#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
+
typedef struct drm_radeon_freelist {
unsigned int age;
drm_buf_t *buf;
@@ -245,8 +247,6 @@ typedef struct drm_radeon_private {
drm_radeon_depth_clear_t depth_clear;
- unsigned long fb_offset;
- unsigned long mmio_offset;
unsigned long ring_offset;
unsigned long ring_rptr_offset;
unsigned long buffers_offset;
@@ -273,7 +273,6 @@ typedef struct drm_radeon_private {
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
- int is_pci;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@@ -330,17 +329,14 @@ extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(drm_device_t * dev);
extern void radeon_driver_irq_postinstall(drm_device_t * dev);
extern void radeon_driver_irq_uninstall(drm_device_t * dev);
-extern void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp);
-extern void radeon_driver_pretakedown(drm_device_t * dev);
-extern int radeon_driver_open_helper(drm_device_t * dev,
- drm_file_t * filp_priv);
-extern void radeon_driver_free_filp_priv(drm_device_t * dev,
- drm_file_t * filp_priv);
-
-extern int radeon_preinit(struct drm_device *dev, unsigned long flags);
-extern int radeon_postinit(struct drm_device *dev, unsigned long flags);
-extern int radeon_postcleanup(struct drm_device *dev);
+extern int radeon_driver_load(struct drm_device *dev, unsigned long flags);
+extern int radeon_driver_unload(struct drm_device *dev);
+extern int radeon_driver_firstopen(struct drm_device *dev);
+extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp);
+extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp);
+extern void radeon_driver_lastclose(drm_device_t * dev);
+extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv);
extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@@ -364,6 +360,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
*/
#define RADEON_AGP_COMMAND 0x0f60
+#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */
+# define RADEON_AGP_ENABLE (1<<8)
#define RADEON_AUX_SCISSOR_CNTL 0x26f0
# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24)
# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25)
@@ -651,6 +649,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
#define RADEON_WAIT_UNTIL 0x1720
# define RADEON_WAIT_CRTC_PFLIP (1 << 0)
+# define RADEON_WAIT_2D_IDLE (1 << 14)
+# define RADEON_WAIT_3D_IDLE (1 << 15)
# define RADEON_WAIT_2D_IDLECLEAN (1 << 16)
# define RADEON_WAIT_3D_IDLECLEAN (1 << 17)
# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18)
@@ -1105,7 +1105,6 @@ do { \
write = 0; \
_tab += _i; \
} \
- \
while (_size > 0) { \
*(ring + write) = *_tab++; \
write++; \
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index fef4a2b84c1e..0ccfd3618ff1 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
#include <linux/compat.h>
-#include <linux/ioctl32.h>
#include "drmP.h"
#include "drm.h"
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 231ac1438c69..7bc27516d425 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -1,5 +1,5 @@
-/* radeon_state.c -- State support for Radeon -*- linux-c -*-
- *
+/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
+/*
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* All Rights Reserved.
*
@@ -72,10 +72,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case RADEON_EMIT_PP_MISC:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
- &data[(RADEON_RB3D_DEPTHOFFSET
- -
- RADEON_PP_MISC) /
- 4])) {
+ &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
DRM_ERROR("Invalid depth buffer offset\n");
return DRM_ERR(EINVAL);
}
@@ -83,10 +80,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case RADEON_EMIT_PP_CNTL:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
- &data[(RADEON_RB3D_COLOROFFSET
- -
- RADEON_PP_CNTL) /
- 4])) {
+ &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
DRM_ERROR("Invalid colour buffer offset\n");
return DRM_ERR(EINVAL);
}
@@ -109,10 +103,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case RADEON_EMIT_PP_TXFILTER_1:
case RADEON_EMIT_PP_TXFILTER_2:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
- &data[(RADEON_PP_TXOFFSET_0
- -
- RADEON_PP_TXFILTER_0) /
- 4])) {
+ &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
DRM_ERROR("Invalid R100 texture offset\n");
return DRM_ERR(EINVAL);
}
@@ -126,8 +117,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
case R200_EMIT_PP_CUBIC_OFFSETS_5:{
int i;
for (i = 0; i < 5; i++) {
- if (radeon_check_and_fixup_offset
- (dev_priv, filp_priv, &data[i])) {
+ if (radeon_check_and_fixup_offset(dev_priv,
+ filp_priv,
+ &data[i])) {
DRM_ERROR
("Invalid R200 cubic texture offset\n");
return DRM_ERR(EINVAL);
@@ -239,8 +231,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
dev_priv,
- drm_file_t * filp_priv,
- drm_radeon_kcmd_buffer_t *cmdbuf,
+ drm_file_t *filp_priv,
+ drm_radeon_kcmd_buffer_t *
+ cmdbuf,
unsigned int *cmdsz)
{
u32 *cmd = (u32 *) cmdbuf->buf;
@@ -555,7 +548,8 @@ static struct {
{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"},
{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"},
{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"},
- {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
+ {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1,
+ "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"},
{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"},
{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"},
{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"},
@@ -569,7 +563,7 @@ static struct {
{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4,
"R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"},
{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */
- {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
+ {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */
{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"},
{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"},
{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"},
@@ -592,7 +586,7 @@ static struct {
{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"},
{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"},
{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"},
- {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
+ {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */
{R200_PP_AFS_1, 32, "R200_PP_AFS_1"},
{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"},
{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"},
@@ -985,8 +979,8 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev,
* rendering a quad into just those buffers. Thus, we have to
* make sure the 3D engine is configured correctly.
*/
- if ((dev_priv->microcode_version == UCODE_R200) &&
- (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
+ else if ((dev_priv->microcode_version == UCODE_R200) &&
+ (flags & (RADEON_DEPTH | RADEON_STENCIL))) {
int tempPP_CNTL;
int tempRE_CNTL;
@@ -1637,6 +1631,14 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
(u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
dwords = size / 4;
+#define RADEON_COPY_MT(_buf, _data, _width) \
+ do { \
+ if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\
+ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \
+ return DRM_ERR(EFAULT); \
+ } \
+ } while(0)
+
if (microtile) {
/* texture micro tiling in use, minimum texture width is thus 16 bytes.
however, we cannot use blitter directly for texture width < 64 bytes,
@@ -1648,46 +1650,19 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
from user space. */
if (tex->height == 1) {
if (tex_width >= 64 || tex_width <= 16) {
- if (DRM_COPY_FROM_USER(buffer, data,
- tex_width *
- sizeof(u32))) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(tex_width * sizeof(u32)));
} else if (tex_width == 32) {
- if (DRM_COPY_FROM_USER
- (buffer, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
- if (DRM_COPY_FROM_USER
- (buffer + 8, data + 16, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, 16);
+ RADEON_COPY_MT(buffer + 8,
+ data + 16, 16);
}
} else if (tex_width >= 64 || tex_width == 16) {
- if (DRM_COPY_FROM_USER(buffer, data,
- dwords * sizeof(u32))) {
- DRM_ERROR("EFAULT on data, %d dwords\n",
- dwords);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(dwords * sizeof(u32)));
} else if (tex_width < 16) {
for (i = 0; i < tex->height; i++) {
- if (DRM_COPY_FROM_USER
- (buffer, data, tex_width)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, tex_width);
buffer += 4;
data += tex_width;
}
@@ -1695,37 +1670,13 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
/* TODO: make sure this works when not fitting in one buffer
(i.e. 32bytes x 2048...) */
for (i = 0; i < tex->height; i += 2) {
- if (DRM_COPY_FROM_USER
- (buffer, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 8, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 8, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 4, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 4, data, 16);
data += 16;
- if (DRM_COPY_FROM_USER
- (buffer + 12, data, 16)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer + 12, data, 16);
data += 16;
buffer += 16;
}
@@ -1735,31 +1686,22 @@ static int radeon_cp_dispatch_texture(DRMFILE filp,
/* Texture image width is larger than the minimum, so we
* can upload it directly.
*/
- if (DRM_COPY_FROM_USER(buffer, data,
- dwords * sizeof(u32))) {
- DRM_ERROR("EFAULT on data, %d dwords\n",
- dwords);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data,
+ (int)(dwords * sizeof(u32)));
} else {
/* Texture image width is less than the minimum, so we
* need to pad out each image scanline to the minimum
* width.
*/
for (i = 0; i < tex->height; i++) {
- if (DRM_COPY_FROM_USER
- (buffer, data, tex_width)) {
- DRM_ERROR
- ("EFAULT on pad, %d bytes\n",
- tex_width);
- return DRM_ERR(EFAULT);
- }
+ RADEON_COPY_MT(buffer, data, tex_width);
buffer += 8;
data += tex_width;
}
}
}
+#undef RADEON_COPY_MT
buf->filp = filp;
buf->used = size;
offset = dev_priv->gart_buffers_offset + buf->offset;
@@ -1821,7 +1763,7 @@ static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple)
}
static void radeon_apply_surface_regs(int surf_index,
- drm_radeon_private_t * dev_priv)
+ drm_radeon_private_t *dev_priv)
{
if (!dev_priv->mmio)
return;
@@ -1847,8 +1789,8 @@ static void radeon_apply_surface_regs(int surf_index,
* freed, we suddenly need two surfaces to store A and C, which might
* not always be available.
*/
-static int alloc_surface(drm_radeon_surface_alloc_t * new,
- drm_radeon_private_t * dev_priv, DRMFILE filp)
+static int alloc_surface(drm_radeon_surface_alloc_t *new,
+ drm_radeon_private_t *dev_priv, DRMFILE filp)
{
struct radeon_virt_surface *s;
int i;
@@ -2158,6 +2100,11 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS)
LOCK_TEST_WITH_RETURN(dev, filp);
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
DRM_GET_PRIV_WITH_RETURN(filp_priv, filp);
DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data,
@@ -2596,9 +2543,9 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.scalars.count;
int start = header.scalars.offset;
@@ -2618,9 +2565,9 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv,
/* God this is ugly
*/
-static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.scalars.count;
int start = ((unsigned int)header.scalars.offset) + 0x100;
@@ -2638,9 +2585,9 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv,
return 0;
}
-static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv,
+static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
drm_radeon_cmd_header_t header,
- drm_radeon_kcmd_buffer_t * cmdbuf)
+ drm_radeon_kcmd_buffer_t *cmdbuf)
{
int sz = header.vectors.count;
int start = header.vectors.offset;
@@ -2685,8 +2632,8 @@ static int radeon_emit_packet3(drm_device_t * dev,
return 0;
}
-static int radeon_emit_packet3_cliprect(drm_device_t * dev,
- drm_file_t * filp_priv,
+static int radeon_emit_packet3_cliprect(drm_device_t *dev,
+ drm_file_t *filp_priv,
drm_radeon_kcmd_buffer_t *cmdbuf,
int orig_nbox)
{
@@ -2818,7 +2765,8 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
if (kbuf == NULL)
return DRM_ERR(ENOMEM);
- if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) {
+ if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf,
+ cmdbuf.bufsz)) {
drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
return DRM_ERR(EFAULT);
}
@@ -2981,7 +2929,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
value = dev_priv->gart_vm_start;
break;
case RADEON_PARAM_REGISTER_HANDLE:
- value = dev_priv->mmio_offset;
+ value = dev_priv->mmio->offset;
break;
case RADEON_PARAM_STATUS_HANDLE:
value = dev_priv->ring_rptr_offset;
@@ -3004,6 +2952,15 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS)
case RADEON_PARAM_GART_TEX_HANDLE:
value = dev_priv->gart_textures_offset;
break;
+
+ case RADEON_PARAM_CARD_TYPE:
+ if (dev_priv->flags & CHIP_IS_PCIE)
+ value = RADEON_CARD_PCIE;
+ else if (dev_priv->flags & CHIP_IS_AGP)
+ value = RADEON_CARD_AGP;
+ else
+ value = RADEON_CARD_PCI;
+ break;
default:
return DRM_ERR(EINVAL);
}
@@ -3066,10 +3023,11 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS)
/* When a client dies:
* - Check for and clean up flipped page state
* - Free any alloced GART memory.
+ * - Free any alloced radeon surfaces.
*
* DRM infrastructure takes care of reclaiming dma buffers.
*/
-void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
+void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -3082,16 +3040,17 @@ void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp)
}
}
-void radeon_driver_pretakedown(drm_device_t * dev)
+void radeon_driver_lastclose(drm_device_t * dev)
{
radeon_do_release(dev);
}
-int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
+int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_driver_file_fields *radeon_priv;
+ DRM_DEBUG("\n");
radeon_priv =
(struct drm_radeon_driver_file_fields *)
drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES);
@@ -3100,6 +3059,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
return -ENOMEM;
filp_priv->driver_priv = radeon_priv;
+
if (dev_priv)
radeon_priv->radeon_fb_delta = dev_priv->fb_location;
else
@@ -3107,7 +3067,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv)
return 0;
}
-void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
+void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv)
{
struct drm_radeon_driver_file_fields *radeon_priv =
filp_priv->driver_priv;
@@ -3116,33 +3076,33 @@ void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv)
}
drm_ioctl_desc_t radeon_ioctls[] = {
- [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1},
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0}
+ [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH}
};
int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c
index 6d10515795cc..0d426deeefec 100644
--- a/drivers/char/drm/savage_bci.c
+++ b/drivers/char/drm/savage_bci.c
@@ -533,16 +533,32 @@ static void savage_fake_dma_flush(drm_savage_private_t * dev_priv)
dev_priv->first_dma_page = dev_priv->current_dma_page = 0;
}
+int savage_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+ drm_savage_private_t *dev_priv;
+
+ 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;
+
+ return 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.
+ * in drm_addmap. Therefore we add them manually before the maps are
+ * initialized, and tear them down on last close.
*/
-int savage_preinit(drm_device_t * dev, unsigned long chipset)
+int savage_driver_firstopen(drm_device_t *dev)
{
- drm_savage_private_t *dev_priv;
+ drm_savage_private_t *dev_priv = dev->dev_private;
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
@@ -551,14 +567,6 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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;
@@ -576,26 +584,24 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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);
+ drm_mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, DRM_MTRR_WC);
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);
+ drm_mtrr_add(dev_priv->mtrr[1].base,
+ dev_priv->mtrr[1].size, DRM_MTRR_WC);
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);
+ drm_mtrr_add(dev_priv->mtrr[2].base,
+ dev_priv->mtrr[2].size, DRM_MTRR_WC);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
drm_get_resource_len(dev, 0));
}
- } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) {
+ } else if (dev_priv->chipset != S3_SUPERSAVAGE &&
+ dev_priv->chipset != S3_SAVAGE2000) {
mmio_base = drm_get_resource_start(dev, 0);
fb_rsrc = 1;
fb_base = drm_get_resource_start(dev, 1);
@@ -609,9 +615,8 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
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);
+ drm_mtrr_add(dev_priv->mtrr[0].base,
+ dev_priv->mtrr[0].size, DRM_MTRR_WC);
} else {
DRM_ERROR("strange pci_resource_len %08lx\n",
drm_get_resource_len(dev, 1));
@@ -648,16 +653,21 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset)
/*
* Delete MTRRs and free device-private data.
*/
-int savage_postcleanup(drm_device_t * dev)
+void savage_driver_lastclose(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,
+ drm_mtrr_del(dev_priv->mtrr[i].handle,
dev_priv->mtrr[i].base,
- dev_priv->mtrr[i].size);
+ dev_priv->mtrr[i].size, DRM_MTRR_WC);
+}
+
+int savage_driver_unload(drm_device_t *dev)
+{
+ drm_savage_private_t *dev_priv = dev->dev_private;
drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER);
@@ -994,8 +1004,7 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS)
* DMA buffer management
*/
-static int savage_bci_get_buffers(DRMFILE filp, drm_device_t * dev,
- drm_dma_t * d)
+static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d)
{
drm_buf_t *buf;
int i;
@@ -1057,7 +1066,7 @@ int savage_bci_buffers(DRM_IOCTL_ARGS)
return ret;
}
-void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp)
+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;
@@ -1090,10 +1099,10 @@ void savage_reclaim_buffers(drm_device_t * dev, DRMFILE 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},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH},
};
int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls);
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c
index 22d799cde41c..aa6c0d1a82f8 100644
--- a/drivers/char/drm/savage_drv.c
+++ b/drivers/char/drm/savage_drv.c
@@ -30,31 +30,6 @@
#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
};
@@ -63,13 +38,13 @@ 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,
+ .load = savage_driver_load,
+ .firstopen = savage_driver_firstopen,
+ .lastclose = savage_driver_lastclose,
+ .unload = savage_driver_unload,
.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 = {
@@ -80,12 +55,19 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- }
- ,
+ },
+
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init savage_init(void)
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h
index a4b0fa998a95..dd46cb85439c 100644
--- a/drivers/char/drm/savage_drv.h
+++ b/drivers/char/drm/savage_drv.h
@@ -1,5 +1,5 @@
-/* savage_drv.h -- Private header for the savage driver
- *
+/* savage_drv.h -- Private header for the savage driver */
+/*
* Copyright 2004 Felix Kuehling
* All Rights Reserved.
*
@@ -192,7 +192,7 @@ typedef struct drm_savage_private {
/* Err, there is a macro wait_event in include/linux/wait.h.
* Avoid unwanted macro expansion. */
void (*emit_clip_rect) (struct drm_savage_private * dev_priv,
- drm_clip_rect_t * pbox);
+ const drm_clip_rect_t * pbox);
void (*dma_flush) (struct drm_savage_private * dev_priv);
} drm_savage_private_t;
@@ -208,16 +208,18 @@ 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_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int savage_driver_firstopen(drm_device_t *dev);
+extern void savage_driver_lastclose(drm_device_t *dev);
+extern int savage_driver_unload(drm_device_t *dev);
extern 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);
+ const drm_clip_rect_t * pbox);
extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox);
+ const drm_clip_rect_t * pbox);
#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */
#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */
@@ -500,15 +502,6 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
#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
*/
@@ -534,8 +527,8 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
#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); \
+#define DMA_COPY(src, n) do { \
+ memcpy(dma_ptr, (src), (n)*4); \
dma_ptr += n; \
} while(0)
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c
index e87a5d59b99c..ef2581d16146 100644
--- a/drivers/char/drm/savage_state.c
+++ b/drivers/char/drm/savage_state.c
@@ -27,7 +27,7 @@
#include "savage_drv.h"
void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox)
+ const drm_clip_rect_t * pbox)
{
uint32_t scstart = dev_priv->state.s3d.new_scstart;
uint32_t scend = dev_priv->state.s3d.new_scend;
@@ -53,7 +53,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv,
}
void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv,
- drm_clip_rect_t * pbox)
+ const drm_clip_rect_t * pbox)
{
uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0;
uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1;
@@ -115,18 +115,19 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit,
#define SAVE_STATE(reg,where) \
if(start <= reg && start+count > reg) \
- DRM_GET_USER_UNCHECKED(dev_priv->state.where, &regs[reg-start])
+ 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]); \
+ 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)
+ const uint32_t *regs)
{
if (start < SAVAGE_TEXPALADDR_S3D ||
start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) {
@@ -148,8 +149,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
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);
+ dev_priv->state.s3d.texaddr);
}
return 0;
@@ -157,7 +157,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv,
static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
unsigned int start, unsigned int count,
- const uint32_t __user * regs)
+ const uint32_t *regs)
{
int ret = 0;
@@ -174,19 +174,18 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
~SAVAGE_SCISSOR_MASK_S4);
/* if any texture regs were changed ... */
- if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) {
+ 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);
+ 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);
+ ret |= savage_verify_texaddr(dev_priv, 1,
+ dev_priv->state.s4.texaddr1);
}
return ret;
@@ -197,7 +196,7 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv,
static int savage_dispatch_state(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
- const uint32_t __user * regs)
+ const uint32_t *regs)
{
unsigned int count = cmd_header->state.count;
unsigned int start = cmd_header->state.start;
@@ -209,9 +208,6 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
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)
@@ -236,8 +232,8 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
/* 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);
+ count2 = count -
+ (SAVAGE_DRAWCTRL1_S4 + 1 - start);
if (start + count > SAVAGE_DRAWCTRL0_S4)
count = SAVAGE_DRAWCTRL0_S4 - start;
} else if (start <= SAVAGE_DRAWCTRL1_S4) {
@@ -263,7 +259,7 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv,
while (count > 0) {
unsigned int n = count < 255 ? count : 255;
DMA_SET_REGISTERS(start, n);
- DMA_COPY_FROM_USER(regs, n);
+ DMA_COPY(regs, n);
count -= n;
start += n;
regs += n;
@@ -421,8 +417,8 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv,
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)
+ const uint32_t *vtxbuf, unsigned int vb_size,
+ unsigned int vb_stride)
{
unsigned char reorder = 0;
unsigned int prim = cmd_header->prim.prim;
@@ -507,8 +503,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
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_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
@@ -517,13 +512,12 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
DMA_DRAW_PRIMITIVE(count, prim, skip);
if (vb_stride == vtx_size) {
- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start],
- vtx_size * count);
+ DMA_COPY(&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_COPY(&vtxbuf [vb_stride * i],
+ vtx_size);
}
}
@@ -541,7 +535,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv,
static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
const drm_savage_cmd_header_t * cmd_header,
- const uint16_t __user * usr_idx,
+ const uint16_t *idx,
const drm_buf_t * dmabuf)
{
unsigned char reorder = 0;
@@ -628,11 +622,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
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);
+ /* check indices */
for (i = 0; i < count; ++i) {
if (idx[i] > dmabuf->total / 32) {
DRM_ERROR("idx[%u]=%u out of range (0-%u)\n",
@@ -652,8 +643,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
for (i = 1; i + 1 < count; i += 2)
BCI_WRITE(idx[i + reorder[i % 3]] |
- (idx[i + 1 + reorder[(i + 1) % 3]] <<
- 16));
+ (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)) {
@@ -674,7 +665,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
BCI_WRITE(idx[i]);
}
- usr_idx += count;
+ idx += count;
n -= count;
prim |= BCI_CMD_DRAW_CONT;
@@ -685,8 +676,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv,
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,
+ const uint16_t *idx,
+ const uint32_t *vtxbuf,
unsigned int vb_size, unsigned int vb_stride)
{
unsigned char reorder = 0;
@@ -751,11 +742,8 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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);
+
+ /* Check indices */
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",
@@ -775,8 +763,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
@@ -786,14 +773,13 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
for (i = 0; i < count; ++i) {
unsigned int j = idx[i];
- DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j],
- vtx_size);
+ DMA_COPY(&vtxbuf[vb_stride * j], vtx_size);
}
DMA_COMMIT();
}
- usr_idx += count;
+ idx += count;
n -= count;
prim |= BCI_CMD_DRAW_CONT;
@@ -804,11 +790,11 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv,
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,
+ const drm_savage_cmd_header_t *data,
unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ const drm_clip_rect_t *boxes)
{
- unsigned int flags = cmd_header->clear0.flags, mask, value;
+ unsigned int flags = cmd_header->clear0.flags;
unsigned int clear_cmd;
unsigned int i, nbufs;
DMA_LOCALS;
@@ -816,9 +802,6 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
if (nbox == 0)
return 0;
- DRM_GET_USER_UNCHECKED(mask, &data->clear1.mask);
- DRM_GET_USER_UNCHECKED(value, &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);
@@ -828,21 +811,19 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
if (nbufs == 0)
return 0;
- if (mask != 0xffffffff) {
+ if (data->clear1.mask != 0xffffffff) {
/* set mask */
BEGIN_DMA(2);
DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
- DMA_WRITE(mask);
+ DMA_WRITE(data->clear1.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;
+ x = boxes[i].x1, y = boxes[i].y1;
+ w = boxes[i].x2 - boxes[i].x1;
+ h = boxes[i].y2 - boxes[i].y1;
BEGIN_DMA(nbufs * 6);
for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {
if (!(flags & buf))
@@ -862,13 +843,13 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
DMA_WRITE(dev_priv->depth_bd);
break;
}
- DMA_WRITE(value);
+ DMA_WRITE(data->clear1.value);
DMA_WRITE(BCI_X_Y(x, y));
DMA_WRITE(BCI_W_H(w, h));
}
DMA_COMMIT();
}
- if (mask != 0xffffffff) {
+ if (data->clear1.mask != 0xffffffff) {
/* reset mask */
BEGIN_DMA(2);
DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);
@@ -880,8 +861,7 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv,
}
static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
- unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ unsigned int nbox, const drm_clip_rect_t *boxes)
{
unsigned int swap_cmd;
unsigned int i;
@@ -895,16 +875,14 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
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_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+ DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1));
+ DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1,
+ boxes[i].y2 - boxes[i].y1));
DMA_COMMIT();
}
@@ -912,68 +890,52 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv,
}
static int savage_dispatch_draw(drm_savage_private_t * dev_priv,
- const drm_savage_cmd_header_t __user * start,
- const drm_savage_cmd_header_t __user * end,
+ const drm_savage_cmd_header_t *start,
+ const drm_savage_cmd_header_t *end,
const drm_buf_t * dmabuf,
- const unsigned int __user * usr_vtxbuf,
+ const unsigned int *vtxbuf,
unsigned int vb_size, unsigned int vb_stride,
unsigned int nbox,
- const drm_clip_rect_t __user * usr_boxes)
+ const drm_clip_rect_t *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);
+ const drm_savage_cmd_header_t *cmdbuf;
+ dev_priv->emit_clip_rect(dev_priv, &boxes[i]);
- usr_cmdbuf = start;
- while (usr_cmdbuf < end) {
+ cmdbuf = start;
+ while (cmdbuf < end) {
drm_savage_cmd_header_t cmd_header;
- DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,
- sizeof(cmd_header));
- usr_cmdbuf++;
+ cmd_header = *cmdbuf;
+ cmdbuf++;
switch (cmd_header.cmd.cmd) {
case SAVAGE_CMD_DMA_PRIM:
- ret =
- savage_dispatch_dma_prim(dev_priv,
- &cmd_header,
- dmabuf);
+ 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);
+ ret = savage_dispatch_vb_prim(
+ dev_priv, &cmd_header,
+ 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;
+ ret = savage_dispatch_dma_idx(dev_priv,
+ &cmd_header, (const uint16_t *)cmdbuf,
+ dmabuf);
+ 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;
+ ret = savage_dispatch_vb_idx(dev_priv,
+ &cmd_header, (const uint16_t *)cmdbuf,
+ (const uint32_t *)vtxbuf, vb_size,
+ vb_stride);
+ cmdbuf += j;
break;
default:
/* What's the best return code? EFAULT? */
@@ -998,10 +960,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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;
+ drm_savage_cmd_header_t *kcmd_addr = NULL;
+ drm_savage_cmd_header_t *first_draw_cmd;
+ unsigned int *kvb_addr = NULL;
+ drm_clip_rect_t *kbox_addr = NULL;
unsigned int i, j;
int ret = 0;
@@ -1024,15 +986,53 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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);
+ /* Copy the user buffers into kernel temporary areas. This hasn't been
+ * a performance loss compared to VERIFYAREA_READ/
+ * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct
+ * for locking on FreeBSD.
+ */
+ if (cmdbuf.size) {
+ kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER);
+ if (kcmd_addr == NULL)
+ return ENOMEM;
+
+ if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr,
+ cmdbuf.size * 8))
+ {
+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+ return DRM_ERR(EFAULT);
+ }
+ cmdbuf.cmd_addr = kcmd_addr;
+ }
+ if (cmdbuf.vb_size) {
+ kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER);
+ if (kvb_addr == NULL) {
+ ret = DRM_ERR(ENOMEM);
+ goto done;
+ }
+
+ if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr,
+ cmdbuf.vb_size)) {
+ ret = DRM_ERR(EFAULT);
+ goto done;
+ }
+ cmdbuf.vb_addr = kvb_addr;
+ }
+ if (cmdbuf.nbox) {
+ kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ DRM_MEM_DRIVER);
+ if (kbox_addr == NULL) {
+ ret = DRM_ERR(ENOMEM);
+ goto done;
+ }
+
+ if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr,
+ cmdbuf.nbox * sizeof(drm_clip_rect_t))) {
+ ret = DRM_ERR(EFAULT);
+ goto done;
+ }
+ cmdbuf.box_addr = kbox_addr;
+ }
/* Make sure writes to DMA buffers are finished before sending
* DMA commands to the graphics hardware. */
@@ -1046,9 +1046,8 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
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++;
+ cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr;
+ cmdbuf.cmd_addr++;
i++;
/* Group drawing commands with same state to minimize
@@ -1068,21 +1067,18 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
case SAVAGE_CMD_DMA_PRIM:
case SAVAGE_CMD_VB_PRIM:
if (!first_draw_cmd)
- first_draw_cmd = usr_cmdbuf - 1;
- usr_cmdbuf += j;
+ first_draw_cmd = cmdbuf.cmd_addr - 1;
+ cmdbuf.cmd_addr += 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);
+ ret = savage_dispatch_draw(
+ dev_priv, first_draw_cmd,
+ cmdbuf.cmd_addr - 1,
+ dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size,
+ cmdbuf.vb_stride,
+ cmdbuf.nbox, cmdbuf.box_addr);
if (ret != 0)
return ret;
first_draw_cmd = NULL;
@@ -1098,12 +1094,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
DRM_ERROR("command SAVAGE_CMD_STATE extends "
"beyond end of command buffer\n");
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
ret = savage_dispatch_state(dev_priv, &cmd_header,
- (uint32_t __user *)
- usr_cmdbuf);
- usr_cmdbuf += j;
+ (const uint32_t *)cmdbuf.cmd_addr);
+ cmdbuf.cmd_addr += j;
i += j;
break;
case SAVAGE_CMD_CLEAR:
@@ -1111,39 +1107,40 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
DRM_ERROR("command SAVAGE_CMD_CLEAR extends "
"beyond end of command buffer\n");
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
ret = savage_dispatch_clear(dev_priv, &cmd_header,
- usr_cmdbuf,
- cmdbuf.nbox, usr_boxes);
- usr_cmdbuf++;
+ cmdbuf.cmd_addr,
+ cmdbuf.nbox, cmdbuf.box_addr);
+ cmdbuf.cmd_addr++;
i++;
break;
case SAVAGE_CMD_SWAP:
- ret = savage_dispatch_swap(dev_priv,
- cmdbuf.nbox, usr_boxes);
+ ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox,
+ cmdbuf.box_addr);
break;
default:
DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);
DMA_FLUSH();
- return DRM_ERR(EINVAL);
+ ret = DRM_ERR(EINVAL);
+ goto done;
}
if (ret != 0) {
DMA_FLUSH();
- return ret;
+ goto done;
}
}
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);
+ ret = savage_dispatch_draw (
+ dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf,
+ cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride,
+ cmdbuf.nbox, cmdbuf.box_addr);
if (ret != 0) {
DMA_FLUSH();
- return ret;
+ goto done;
}
}
@@ -1157,5 +1154,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS)
savage_freelist_put(dev, dmabuf);
}
- return 0;
+done:
+ /* If we didn't need to allocate them, these'll be NULL */
+ drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER);
+ drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER);
+ drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t),
+ DRM_MEM_DRIVER);
+
+ return ret;
}
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h
index 8f273da76ddb..30f7b3827466 100644
--- a/drivers/char/drm/sis_drm.h
+++ b/drivers/char/drm/sis_drm.h
@@ -1,3 +1,28 @@
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
+ * Copyright 2005 Eric Anholt
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
#ifndef __SIS_DRM_H__
#define __SIS_DRM_H__
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 3cef10643a8f..6f6d7d613ede 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -32,31 +32,6 @@
#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[] = {
sisdrv_PCI_IDS
};
@@ -68,8 +43,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.ioctls = sis_ioctls,
.fops = {
.owner = THIS_MODULE,
@@ -79,11 +52,18 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init sis_init(void)
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index b1fddad83a93..e218e5269503 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -1,5 +1,5 @@
-/* sis_drv.h -- Private header for sis driver -*- linux-c -*-
- *
+/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */
+/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
index da850b4f5440..94f2b4728b63 100644
--- a/drivers/char/drm/sis_ds.h
+++ b/drivers/char/drm/sis_ds.h
@@ -1,6 +1,7 @@
-/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
+/* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*-
* Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw
- *
+ */
+/*
* Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
* All rights reserved.
*
@@ -35,7 +36,7 @@
#define SET_SIZE 5000
-typedef unsigned int ITEM_TYPE;
+typedef unsigned long ITEM_TYPE;
typedef struct {
ITEM_TYPE val;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index a8529728fa63..6774d2fe3452 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -86,7 +86,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
drm_sis_mem_t fb;
struct sis_memreq req;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
int retval = 0;
DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
@@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
- DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
+ DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
return retval;
}
@@ -127,9 +127,9 @@ static int sis_fb_free(DRM_IOCTL_ARGS)
if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
retval = DRM_ERR(EINVAL);
- sis_free((u32) fb.free);
+ sis_free(fb.free);
- DRM_DEBUG("free fb, offset = %lu\n", fb.free);
+ DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
return retval;
}
@@ -176,7 +176,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
drm_sis_mem_t fb;
PMemBlock block;
int retval = 0;
@@ -267,7 +267,7 @@ static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_sis_private_t *dev_priv = dev->dev_private;
- drm_sis_mem_t __user *argp = (void __user *)data;
+ drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
drm_sis_mem_t agp;
PMemBlock block;
int retval = 0;
@@ -367,7 +367,7 @@ int sis_final_context(struct drm_device *dev, int context)
if (i < MAX_CONTEXT) {
set_t *set;
- unsigned int item;
+ ITEM_TYPE item;
int retval;
DRM_DEBUG("find socket %d, context = %d\n", i, context);
@@ -376,7 +376,7 @@ int sis_final_context(struct drm_device *dev, int context)
set = global_ppriv[i].sets[0];
retval = setFirst(set, &item);
while (retval) {
- DRM_DEBUG("free video memory 0x%x\n", item);
+ DRM_DEBUG("free video memory 0x%lx\n", item);
#if defined(__linux__) && defined(CONFIG_FB_SIS)
sis_free(item);
#else
@@ -390,7 +390,7 @@ int sis_final_context(struct drm_device *dev, int context)
set = global_ppriv[i].sets[1];
retval = setFirst(set, &item);
while (retval) {
- DRM_DEBUG("free agp memory 0x%x\n", item);
+ DRM_DEBUG("free agp memory 0x%lx\n", item);
mmFreeMem((PMemBlock) item);
retval = setNext(set, &item);
}
@@ -403,12 +403,12 @@ int sis_final_context(struct drm_device *dev, int context)
}
drm_ioctl_desc_t sis_ioctls[] = {
- [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, 1, 0},
- [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, 1, 1},
- [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, 1, 0},
- [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, 1, 1}
+ [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
};
int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
index c275cbb6e9ce..baa4416032a8 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -36,31 +36,6 @@
#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[] = {
tdfx_PCI_IDS
};
@@ -70,8 +45,6 @@ static struct drm_driver driver = {
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
.fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -80,11 +53,18 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init tdfx_init(void)
diff --git a/drivers/char/drm/tdfx_drv.h b/drivers/char/drm/tdfx_drv.h
index a582a3db4c75..84204ec1b046 100644
--- a/drivers/char/drm/tdfx_drv.h
+++ b/drivers/char/drm/tdfx_drv.h
@@ -1,6 +1,7 @@
/* tdfx.h -- 3dfx DRM template customization -*- linux-c -*-
* Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com
- *
+ */
+/*
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
@@ -30,10 +31,6 @@
#ifndef __TDFX_H__
#define __TDFX_H__
-/* This remains constant for all DRM template files.
- */
-#define DRM(x) tdfx_##x
-
/* General customization:
*/
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
index d4b1766608b0..593c0b8f650a 100644
--- a/drivers/char/drm/via_dma.c
+++ b/drivers/char/drm/via_dma.c
@@ -213,7 +213,9 @@ static int via_initialize(drm_device_t * dev,
dev_priv->dma_wrap = init->size;
dev_priv->dma_offset = init->offset;
dev_priv->last_pause_ptr = NULL;
- dev_priv->hw_addr_ptr = dev_priv->mmio->handle + init->reg_pause_addr;
+ dev_priv->hw_addr_ptr =
+ (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+ init->reg_pause_addr);
via_cmdbuf_start(dev_priv);
@@ -232,13 +234,13 @@ int via_dma_init(DRM_IOCTL_ARGS)
switch (init.func) {
case VIA_INIT_DMA:
- if (!capable(CAP_SYS_ADMIN))
+ if (!DRM_SUSER(DRM_CURPROC))
retcode = DRM_ERR(EPERM);
else
retcode = via_initialize(dev, dev_priv, &init);
break;
case VIA_CLEANUP_DMA:
- if (!capable(CAP_SYS_ADMIN))
+ if (!DRM_SUSER(DRM_CURPROC))
retcode = DRM_ERR(EPERM);
else
retcode = via_dma_cleanup(dev);
@@ -349,9 +351,6 @@ int via_cmdbuffer(DRM_IOCTL_ARGS)
return 0;
}
-extern int
-via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
- unsigned int size);
static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
drm_via_cmdbuffer_t * cmd)
{
@@ -450,9 +449,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
if ((count <= 8) && (count >= 0)) {
uint32_t rgtr, ptr;
rgtr = *(dev_priv->hw_addr_ptr);
- ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
- dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
- CMDBUF_ALIGNMENT_SIZE;
+ ptr = ((volatile char *)dev_priv->last_pause_ptr -
+ dev_priv->dma_ptr) + dev_priv->dma_offset +
+ (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE;
if (rgtr <= ptr) {
DRM_ERROR
("Command regulator\npaused at count %d, address %x, "
@@ -472,7 +471,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv,
&& count--) ;
rgtr = *(dev_priv->hw_addr_ptr);
- ptr = ((char *)paused_at - dev_priv->dma_ptr) +
+ ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ?
@@ -724,3 +723,22 @@ int via_cmdbuf_size(DRM_IOCTL_ARGS)
sizeof(d_siz));
return ret;
}
+
+drm_ioctl_desc_t via_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER},
+ [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH}
+};
+
+int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls);
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
new file mode 100644
index 000000000000..9d5e027dae0e
--- /dev/null
+++ b/drivers/char/drm/via_dmablit.c
@@ -0,0 +1,805 @@
+/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright (C) 2005 Thomas Hellstrom, 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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:
+ * Thomas Hellstrom.
+ * Partially based on code obtained from Digeo Inc.
+ */
+
+
+/*
+ * Unmaps the DMA mappings.
+ * FIXME: Is this a NoOp on x86? Also
+ * FIXME: What happens if this one is called and a pending blit has previously done
+ * the same DMA mappings?
+ */
+
+#include "drmP.h"
+#include "via_drm.h"
+#include "via_drv.h"
+#include "via_dmablit.h"
+
+#include <linux/pagemap.h>
+
+#define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK)
+#define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK)
+#define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT)
+
+typedef struct _drm_via_descriptor {
+ uint32_t mem_addr;
+ uint32_t dev_addr;
+ uint32_t size;
+ uint32_t next;
+} drm_via_descriptor_t;
+
+
+/*
+ * Unmap a DMA mapping.
+ */
+
+
+
+static void
+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+ int num_desc = vsg->num_desc;
+ unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
+ unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
+ drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+ descriptor_this_page;
+ dma_addr_t next = vsg->chain_start;
+
+ while(num_desc--) {
+ if (descriptor_this_page-- == 0) {
+ cur_descriptor_page--;
+ descriptor_this_page = vsg->descriptors_per_page - 1;
+ desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+ descriptor_this_page;
+ }
+ dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
+ dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
+ next = (dma_addr_t) desc_ptr->next;
+ desc_ptr--;
+ }
+}
+
+/*
+ * If mode = 0, count how many descriptors are needed.
+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the
+ * 'next' field without syncing calls when the descriptor is already mapped.
+ */
+
+static void
+via_map_blit_for_device(struct pci_dev *pdev,
+ const drm_via_dmablit_t *xfer,
+ drm_via_sg_info_t *vsg,
+ int mode)
+{
+ unsigned cur_descriptor_page = 0;
+ unsigned num_descriptors_this_page = 0;
+ unsigned char *mem_addr = xfer->mem_addr;
+ unsigned char *cur_mem;
+ unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
+ uint32_t fb_addr = xfer->fb_addr;
+ uint32_t cur_fb;
+ unsigned long line_len;
+ unsigned remaining_len;
+ int num_desc = 0;
+ int cur_line;
+ dma_addr_t next = 0 | VIA_DMA_DPR_EC;
+ drm_via_descriptor_t *desc_ptr = 0;
+
+ if (mode == 1)
+ desc_ptr = vsg->desc_pages[cur_descriptor_page];
+
+ for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
+
+ line_len = xfer->line_length;
+ cur_fb = fb_addr;
+ cur_mem = mem_addr;
+
+ while (line_len > 0) {
+
+ remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
+ line_len -= remaining_len;
+
+ if (mode == 1) {
+ desc_ptr->mem_addr =
+ dma_map_page(&pdev->dev,
+ vsg->pages[VIA_PFN(cur_mem) -
+ VIA_PFN(first_addr)],
+ VIA_PGOFF(cur_mem), remaining_len,
+ vsg->direction);
+ desc_ptr->dev_addr = cur_fb;
+
+ desc_ptr->size = remaining_len;
+ desc_ptr->next = (uint32_t) next;
+ next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
+ DMA_TO_DEVICE);
+ desc_ptr++;
+ if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
+ num_descriptors_this_page = 0;
+ desc_ptr = vsg->desc_pages[++cur_descriptor_page];
+ }
+ }
+
+ num_desc++;
+ cur_mem += remaining_len;
+ cur_fb += remaining_len;
+ }
+
+ mem_addr += xfer->mem_stride;
+ fb_addr += xfer->fb_stride;
+ }
+
+ if (mode == 1) {
+ vsg->chain_start = next;
+ vsg->state = dr_via_device_mapped;
+ }
+ vsg->num_desc = num_desc;
+}
+
+/*
+ * Function that frees up all resources for a blit. It is usable even if the
+ * blit info has only be partially built as long as the status enum is consistent
+ * with the actual status of the used resources.
+ */
+
+
+void
+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+ struct page *page;
+ int i;
+
+ switch(vsg->state) {
+ case dr_via_device_mapped:
+ via_unmap_blit_from_device(pdev, vsg);
+ case dr_via_desc_pages_alloc:
+ for (i=0; i<vsg->num_desc_pages; ++i) {
+ if (vsg->desc_pages[i] != NULL)
+ free_page((unsigned long)vsg->desc_pages[i]);
+ }
+ kfree(vsg->desc_pages);
+ case dr_via_pages_locked:
+ for (i=0; i<vsg->num_pages; ++i) {
+ if ( NULL != (page = vsg->pages[i])) {
+ if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction))
+ SetPageDirty(page);
+ page_cache_release(page);
+ }
+ }
+ case dr_via_pages_alloc:
+ vfree(vsg->pages);
+ default:
+ vsg->state = dr_via_sg_init;
+ }
+ if (vsg->bounce_buffer) {
+ vfree(vsg->bounce_buffer);
+ vsg->bounce_buffer = NULL;
+ }
+ vsg->free_on_sequence = 0;
+}
+
+/*
+ * Fire a blit engine.
+ */
+
+static void
+via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
+ VIA_DMA_CSR_DE);
+ VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
+ VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0);
+ VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
+}
+
+/*
+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
+ * occur here if the calling user does not have access to the submitted address.
+ */
+
+static int
+via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+ int ret;
+ unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
+ vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) -
+ first_pfn + 1;
+
+ if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages)))
+ return DRM_ERR(ENOMEM);
+ memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages);
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr,
+ vsg->num_pages, vsg->direction, 0, vsg->pages, NULL);
+
+ up_read(&current->mm->mmap_sem);
+ if (ret != vsg->num_pages) {
+ if (ret < 0)
+ return ret;
+ vsg->state = dr_via_pages_locked;
+ return DRM_ERR(EINVAL);
+ }
+ vsg->state = dr_via_pages_locked;
+ DRM_DEBUG("DMA pages locked\n");
+ return 0;
+}
+
+/*
+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
+ * quite large for some blits, and pages don't need to be contingous.
+ */
+
+static int
+via_alloc_desc_pages(drm_via_sg_info_t *vsg)
+{
+ int i;
+
+ vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t);
+ vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
+ vsg->descriptors_per_page;
+
+ if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL)))
+ return DRM_ERR(ENOMEM);
+
+ memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages);
+ vsg->state = dr_via_desc_pages_alloc;
+ for (i=0; i<vsg->num_desc_pages; ++i) {
+ if (NULL == (vsg->desc_pages[i] =
+ (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
+ return DRM_ERR(ENOMEM);
+ }
+ DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
+ vsg->num_desc);
+ return 0;
+}
+
+static void
+via_abort_dmablit(drm_device_t *dev, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
+}
+
+static void
+via_dmablit_engine_off(drm_device_t *dev, int engine)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
+}
+
+
+
+/*
+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
+ * the workqueue task takes care of processing associated with the old blit.
+ */
+
+void
+via_dmablit_handler(drm_device_t *dev, int engine, int from_irq)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+ int cur;
+ int done_transfer;
+ unsigned long irqsave=0;
+ uint32_t status = 0;
+
+ DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
+ engine, from_irq, (unsigned long) blitq);
+
+ if (from_irq) {
+ spin_lock(&blitq->blit_lock);
+ } else {
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ done_transfer = blitq->is_active &&
+ (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
+ done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE));
+
+ cur = blitq->cur;
+ if (done_transfer) {
+
+ blitq->blits[cur]->aborted = blitq->aborting;
+ blitq->done_blit_handle++;
+ DRM_WAKEUP(blitq->blit_queue + cur);
+
+ cur++;
+ if (cur >= VIA_NUM_BLIT_SLOTS)
+ cur = 0;
+ blitq->cur = cur;
+
+ /*
+ * Clear transfer done flag.
+ */
+
+ VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD);
+
+ blitq->is_active = 0;
+ blitq->aborting = 0;
+ schedule_work(&blitq->wq);
+
+ } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
+
+ /*
+ * Abort transfer after one second.
+ */
+
+ via_abort_dmablit(dev, engine);
+ blitq->aborting = 1;
+ blitq->end = jiffies + DRM_HZ;
+ }
+
+ if (!blitq->is_active) {
+ if (blitq->num_outstanding) {
+ via_fire_dmablit(dev, blitq->blits[cur], engine);
+ blitq->is_active = 1;
+ blitq->cur = cur;
+ blitq->num_outstanding--;
+ blitq->end = jiffies + DRM_HZ;
+ if (!timer_pending(&blitq->poll_timer)) {
+ blitq->poll_timer.expires = jiffies+1;
+ add_timer(&blitq->poll_timer);
+ }
+ } else {
+ if (timer_pending(&blitq->poll_timer)) {
+ del_timer(&blitq->poll_timer);
+ }
+ via_dmablit_engine_off(dev, engine);
+ }
+ }
+
+ if (from_irq) {
+ spin_unlock(&blitq->blit_lock);
+ } else {
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ }
+}
+
+
+
+/*
+ * Check whether this blit is still active, performing necessary locking.
+ */
+
+static int
+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
+{
+ unsigned long irqsave;
+ uint32_t slot;
+ int active;
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ /*
+ * Allow for handle wraparounds.
+ */
+
+ active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
+ ((blitq->cur_blit_handle - handle) <= (1 << 23));
+
+ if (queue && active) {
+ slot = handle - blitq->done_blit_handle + blitq->cur -1;
+ if (slot >= VIA_NUM_BLIT_SLOTS) {
+ slot -= VIA_NUM_BLIT_SLOTS;
+ }
+ *queue = blitq->blit_queue + slot;
+ }
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ return active;
+}
+
+/*
+ * Sync. Wait for at least three seconds for the blit to be performed.
+ */
+
+static int
+via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine)
+{
+
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+ wait_queue_head_t *queue;
+ int ret = 0;
+
+ if (via_dmablit_active(blitq, engine, handle, &queue)) {
+ DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ,
+ !via_dmablit_active(blitq, engine, handle, NULL));
+ }
+ DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
+ handle, engine, ret);
+
+ return ret;
+}
+
+
+/*
+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:
+ * a) Broken hardware (typically those that don't have any video capture facility).
+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has
+ * irqs, it will shorten the latency somewhat.
+ */
+
+
+
+static void
+via_dmablit_timer(unsigned long data)
+{
+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+ drm_device_t *dev = blitq->dev;
+ int engine = (int)
+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
+
+ DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
+ (unsigned long) jiffies);
+
+ via_dmablit_handler(dev, engine, 0);
+
+ if (!timer_pending(&blitq->poll_timer)) {
+ blitq->poll_timer.expires = jiffies+1;
+ add_timer(&blitq->poll_timer);
+ }
+ via_dmablit_handler(dev, engine, 0);
+
+}
+
+
+
+
+/*
+ * Workqueue task that frees data and mappings associated with a blit.
+ * Also wakes up waiting processes. Each of these tasks handles one
+ * blit engine only and may not be called on each interrupt.
+ */
+
+
+static void
+via_dmablit_workqueue(void *data)
+{
+ drm_via_blitq_t *blitq = (drm_via_blitq_t *) data;
+ drm_device_t *dev = blitq->dev;
+ unsigned long irqsave;
+ drm_via_sg_info_t *cur_sg;
+ int cur_released;
+
+
+ DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long)
+ (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ while(blitq->serviced != blitq->cur) {
+
+ cur_released = blitq->serviced++;
+
+ DRM_DEBUG("Releasing blit slot %d\n", cur_released);
+
+ if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
+ blitq->serviced = 0;
+
+ cur_sg = blitq->blits[cur_released];
+ blitq->num_free++;
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ DRM_WAKEUP(&blitq->busy_queue);
+
+ via_free_sg_info(dev->pdev, cur_sg);
+ kfree(cur_sg);
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+}
+
+
+/*
+ * Init all blit engines. Currently we use two, but some hardware have 4.
+ */
+
+
+void
+via_init_dmablit(drm_device_t *dev)
+{
+ int i,j;
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_blitq_t *blitq;
+
+ pci_set_master(dev->pdev);
+
+ for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) {
+ blitq = dev_priv->blit_queues + i;
+ blitq->dev = dev;
+ blitq->cur_blit_handle = 0;
+ blitq->done_blit_handle = 0;
+ blitq->head = 0;
+ blitq->cur = 0;
+ blitq->serviced = 0;
+ blitq->num_free = VIA_NUM_BLIT_SLOTS;
+ blitq->num_outstanding = 0;
+ blitq->is_active = 0;
+ blitq->aborting = 0;
+ blitq->blit_lock = SPIN_LOCK_UNLOCKED;
+ for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {
+ DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
+ }
+ DRM_INIT_WAITQUEUE(&blitq->busy_queue);
+ INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq);
+ init_timer(&blitq->poll_timer);
+ blitq->poll_timer.function = &via_dmablit_timer;
+ blitq->poll_timer.data = (unsigned long) blitq;
+ }
+}
+
+/*
+ * Build all info and do all mappings required for a blit.
+ */
+
+
+static int
+via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+ int draw = xfer->to_fb;
+ int ret = 0;
+
+ vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ vsg->bounce_buffer = 0;
+
+ vsg->state = dr_via_sg_init;
+
+ if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
+ DRM_ERROR("Zero size bitblt.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * Below check is a driver limitation, not a hardware one. We
+ * don't want to lock unused pages, and don't want to incoporate the
+ * extra logic of avoiding them. Make sure there are no.
+ * (Not a big limitation anyway.)
+ */
+
+ if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) ||
+ (xfer->mem_stride > 2048*4)) {
+ DRM_ERROR("Too large system memory stride. Stride: %d, "
+ "Length: %d\n", xfer->mem_stride, xfer->line_length);
+ return DRM_ERR(EINVAL);
+ }
+
+ if (xfer->num_lines > 2048) {
+ DRM_ERROR("Too many PCI DMA bitblt lines.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * we allow a negative fb stride to allow flipping of images in
+ * transfer.
+ */
+
+ if (xfer->mem_stride < xfer->line_length ||
+ abs(xfer->fb_stride) < xfer->line_length) {
+ DRM_ERROR("Invalid frame-buffer / memory stride.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ /*
+ * A hardware bug seems to be worked around if system memory addresses start on
+ * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
+ * about this. Meanwhile, impose the following restrictions:
+ */
+
+#ifdef VIA_BUGFREE
+ if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
+ ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) {
+ DRM_ERROR("Invalid DRM bitblt alignment.\n");
+ return DRM_ERR(EINVAL);
+ }
+#else
+ if ((((unsigned long)xfer->mem_addr & 15) ||
+ ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) ||
+ (xfer->fb_stride & 3)) {
+ DRM_ERROR("Invalid DRM bitblt alignment.\n");
+ return DRM_ERR(EINVAL);
+ }
+#endif
+
+ if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
+ DRM_ERROR("Could not lock DMA pages.\n");
+ via_free_sg_info(dev->pdev, vsg);
+ return ret;
+ }
+
+ via_map_blit_for_device(dev->pdev, xfer, vsg, 0);
+ if (0 != (ret = via_alloc_desc_pages(vsg))) {
+ DRM_ERROR("Could not allocate DMA descriptor pages.\n");
+ via_free_sg_info(dev->pdev, vsg);
+ return ret;
+ }
+ via_map_blit_for_device(dev->pdev, xfer, vsg, 1);
+
+ return 0;
+}
+
+
+/*
+ * Reserve one free slot in the blit queue. Will wait for one second for one
+ * to become available. Otherwise -EBUSY is returned.
+ */
+
+static int
+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
+{
+ int ret=0;
+ unsigned long irqsave;
+
+ DRM_DEBUG("Num free is %d\n", blitq->num_free);
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ while(blitq->num_free == 0) {
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0);
+ if (ret) {
+ return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret;
+ }
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ }
+
+ blitq->num_free--;
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+ return 0;
+}
+
+/*
+ * Hand back a free slot if we changed our mind.
+ */
+
+static void
+via_dmablit_release_slot(drm_via_blitq_t *blitq)
+{
+ unsigned long irqsave;
+
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+ blitq->num_free++;
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ DRM_WAKEUP( &blitq->busy_queue );
+}
+
+/*
+ * Grab a free slot. Build blit info and queue a blit.
+ */
+
+
+static int
+via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer)
+{
+ drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+ drm_via_sg_info_t *vsg;
+ drm_via_blitq_t *blitq;
+ int ret;
+ int engine;
+ unsigned long irqsave;
+
+ if (dev_priv == NULL) {
+ DRM_ERROR("Called without initialization.\n");
+ return DRM_ERR(EINVAL);
+ }
+
+ engine = (xfer->to_fb) ? 0 : 1;
+ blitq = dev_priv->blit_queues + engine;
+ if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) {
+ return ret;
+ }
+ if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
+ via_dmablit_release_slot(blitq);
+ return DRM_ERR(ENOMEM);
+ }
+ if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
+ via_dmablit_release_slot(blitq);
+ kfree(vsg);
+ return ret;
+ }
+ spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+ blitq->blits[blitq->head++] = vsg;
+ if (blitq->head >= VIA_NUM_BLIT_SLOTS)
+ blitq->head = 0;
+ blitq->num_outstanding++;
+ xfer->sync.sync_handle = ++blitq->cur_blit_handle;
+
+ spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+ xfer->sync.engine = engine;
+
+ via_dmablit_handler(dev, engine, 0);
+
+ return 0;
+}
+
+/*
+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and
+ * that there is a very big proability that this IOCTL will be interrupted by a signal. In that
+ * case it returns with -EAGAIN for the signal to be delivered.
+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
+ */
+
+int
+via_dma_blit_sync( DRM_IOCTL_ARGS )
+{
+ drm_via_blitsync_t sync;
+ int err;
+ DRM_DEVICE;
+
+ DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync));
+
+ if (sync.engine >= VIA_NUM_BLIT_ENGINES)
+ return DRM_ERR(EINVAL);
+
+ err = via_dmablit_sync(dev, sync.sync_handle, sync.engine);
+
+ if (DRM_ERR(EINTR) == err)
+ err = DRM_ERR(EAGAIN);
+
+ return err;
+}
+
+
+/*
+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
+ * be reissued. See the above IOCTL code.
+ */
+
+int
+via_dma_blit( DRM_IOCTL_ARGS )
+{
+ drm_via_dmablit_t xfer;
+ int err;
+ DRM_DEVICE;
+
+ DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer));
+
+ err = via_dmablit(dev, &xfer);
+
+ DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer));
+
+ return err;
+}
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h
new file mode 100644
index 000000000000..f4036cd5d0e0
--- /dev/null
+++ b/drivers/char/drm/via_dmablit.h
@@ -0,0 +1,140 @@
+/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro
+ *
+ * Copyright 2005 Thomas Hellstrom.
+ * 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
+ * THE COPYRIGHT HOLDERS, AUTHORS 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:
+ * Thomas Hellstrom.
+ * Register info from Digeo Inc.
+ */
+
+#ifndef _VIA_DMABLIT_H
+#define _VIA_DMABLIT_H
+
+#include <linux/dma-mapping.h>
+
+#define VIA_NUM_BLIT_ENGINES 2
+#define VIA_NUM_BLIT_SLOTS 8
+
+struct _drm_via_descriptor;
+
+typedef struct _drm_via_sg_info {
+ struct page **pages;
+ unsigned long num_pages;
+ struct _drm_via_descriptor **desc_pages;
+ int num_desc_pages;
+ int num_desc;
+ enum dma_data_direction direction;
+ unsigned char *bounce_buffer;
+ dma_addr_t chain_start;
+ uint32_t free_on_sequence;
+ unsigned int descriptors_per_page;
+ int aborted;
+ enum {
+ dr_via_device_mapped,
+ dr_via_desc_pages_alloc,
+ dr_via_pages_locked,
+ dr_via_pages_alloc,
+ dr_via_sg_init
+ } state;
+} drm_via_sg_info_t;
+
+typedef struct _drm_via_blitq {
+ drm_device_t *dev;
+ uint32_t cur_blit_handle;
+ uint32_t done_blit_handle;
+ unsigned serviced;
+ unsigned head;
+ unsigned cur;
+ unsigned num_free;
+ unsigned num_outstanding;
+ unsigned long end;
+ int aborting;
+ int is_active;
+ drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
+ spinlock_t blit_lock;
+ wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
+ wait_queue_head_t busy_queue;
+ struct work_struct wq;
+ struct timer_list poll_timer;
+} drm_via_blitq_t;
+
+
+/*
+ * PCI DMA Registers
+ * Channels 2 & 3 don't seem to be implemented in hardware.
+ */
+
+#define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */
+#define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */
+#define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */
+#define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */
+
+#define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */
+#define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */
+#define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */
+#define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */
+
+#define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */
+#define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */
+#define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */
+#define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */
+
+#define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */
+#define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */
+#define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */
+#define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */
+
+#define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */
+#define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */
+#define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */
+#define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */
+
+#define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */
+#define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */
+#define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */
+#define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */
+
+#define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */
+
+/* Define for DMA engine */
+/* DPR */
+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */
+#define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */
+#define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */
+
+/* MR */
+#define VIA_DMA_MR_CM (1<<0) /* chaining mode */
+#define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */
+#define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */
+
+/* CSR */
+#define VIA_DMA_CSR_DE (1<<0) /* DMA enable */
+#define VIA_DMA_CSR_TS (1<<1) /* transfer start */
+#define VIA_DMA_CSR_TA (1<<2) /* transfer abort */
+#define VIA_DMA_CSR_TD (1<<3) /* transfer done */
+#define VIA_DMA_CSR_DD (1<<4) /* descriptor done */
+#define VIA_DMA_DPR_EC (1<<1) /* end of chain */
+
+
+
+#endif
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
index ebde9206115e..47f0b5b26379 100644
--- a/drivers/char/drm/via_drm.h
+++ b/drivers/char/drm/via_drm.h
@@ -75,6 +75,8 @@
#define DRM_VIA_CMDBUF_SIZE 0x0b
#define NOT_USED
#define DRM_VIA_WAIT_IRQ 0x0d
+#define DRM_VIA_DMA_BLIT 0x0e
+#define DRM_VIA_BLIT_SYNC 0x0f
#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
@@ -89,6 +91,8 @@
#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
drm_via_cmdbuf_size_t)
#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
+#define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t)
+#define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t)
/* Indices into buf.Setup where various bits of state are mirrored per
* context and per buffer. These can be fired at the card as a unit,
@@ -103,8 +107,12 @@
#define VIA_BACK 0x2
#define VIA_DEPTH 0x4
#define VIA_STENCIL 0x8
-#define VIDEO 0
-#define AGP 1
+#define VIA_MEM_VIDEO 0 /* matches drm constant */
+#define VIA_MEM_AGP 1 /* matches drm constant */
+#define VIA_MEM_SYSTEM 2
+#define VIA_MEM_MIXED 3
+#define VIA_MEM_UNKNOWN 4
+
typedef struct {
uint32_t offset;
uint32_t size;
@@ -192,6 +200,9 @@ typedef struct _drm_via_sarea {
unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */
+ /* Used by the 3d driver only at this point, for pageflipping:
+ */
+ unsigned int pfCurrentOffset;
} drm_via_sarea_t;
typedef struct _drm_via_cmdbuf_size {
@@ -212,6 +223,16 @@ typedef enum {
#define VIA_IRQ_FLAGS_MASK 0xF0000000
+enum drm_via_irqs {
+ drm_via_irq_hqv0 = 0,
+ drm_via_irq_hqv1,
+ drm_via_irq_dma0_dd,
+ drm_via_irq_dma0_td,
+ drm_via_irq_dma1_dd,
+ drm_via_irq_dma1_td,
+ drm_via_irq_num
+};
+
struct drm_via_wait_irq_request {
unsigned irq;
via_irq_seq_type_t type;
@@ -224,20 +245,25 @@ typedef union drm_via_irqwait {
struct drm_wait_vblank_reply reply;
} drm_via_irqwait_t;
-#ifdef __KERNEL__
-
-int via_fb_init(DRM_IOCTL_ARGS);
-int via_mem_alloc(DRM_IOCTL_ARGS);
-int via_mem_free(DRM_IOCTL_ARGS);
-int via_agp_init(DRM_IOCTL_ARGS);
-int via_map_init(DRM_IOCTL_ARGS);
-int via_decoder_futex(DRM_IOCTL_ARGS);
-int via_dma_init(DRM_IOCTL_ARGS);
-int via_cmdbuffer(DRM_IOCTL_ARGS);
-int via_flush_ioctl(DRM_IOCTL_ARGS);
-int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
-int via_cmdbuf_size(DRM_IOCTL_ARGS);
-int via_wait_irq(DRM_IOCTL_ARGS);
+typedef struct drm_via_blitsync {
+ uint32_t sync_handle;
+ unsigned engine;
+} drm_via_blitsync_t;
+
+typedef struct drm_via_dmablit {
+ uint32_t num_lines;
+ uint32_t line_length;
+
+ uint32_t fb_addr;
+ uint32_t fb_stride;
+
+ unsigned char *mem_addr;
+ uint32_t mem_stride;
+
+ int bounce_buffer;
+ int to_fb;
+
+ drm_via_blitsync_t sync;
+} drm_via_dmablit_t;
-#endif
#endif /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
index 016665e0c69f..3f012255d315 100644
--- a/drivers/char/drm/via_drv.c
+++ b/drivers/char/drm/via_drv.c
@@ -29,54 +29,21 @@
#include "drm_pciids.h"
-static int postinit(struct drm_device *dev, unsigned long flags)
+static int dri_library_name(struct drm_device *dev, char *buf)
{
- 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;
+ return snprintf(buf, PAGE_SIZE, "unichrome");
}
static struct pci_device_id pciidlist[] = {
viadrv_PCI_IDS
};
-static drm_ioctl_desc_t ioctls[] = {
- [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0},
- [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0}
-};
-
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+ .load = via_driver_load,
+ .unload = via_driver_unload,
.context_ctor = via_init_context,
.context_dtor = via_final_context,
.vblank_wait = via_driver_vblank_wait,
@@ -85,13 +52,11 @@ static struct drm_driver driver = {
.irq_uninstall = via_driver_irq_uninstall,
.irq_handler = via_driver_irq_handler,
.dma_quiescent = via_driver_dma_quiescent,
+ .dri_library_name = dri_library_name,
.reclaim_buffers = drm_core_reclaim_buffers,
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
- .postinit = postinit,
- .version = version,
- .ioctls = ioctls,
- .num_ioctls = DRM_ARRAY_SIZE(ioctls),
+ .ioctls = via_ioctls,
.fops = {
.owner = THIS_MODULE,
.open = drm_open,
@@ -100,15 +65,23 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
- },
+ },
.pci_driver = {
- .name = DRIVER_NAME,
- .id_table = pciidlist,
- }
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ },
+
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .patchlevel = DRIVER_PATCHLEVEL,
};
static int __init via_init(void)
{
+ driver.num_ioctls = via_max_ioctl;
via_init_command_verifier();
return drm_init(&driver);
}
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
index 7d5daf43797e..aad4f99f5405 100644
--- a/drivers/char/drm/via_drv.h
+++ b/drivers/char/drm/via_drv.h
@@ -24,24 +24,26 @@
#ifndef _VIA_DRV_H_
#define _VIA_DRV_H_
-#define DRIVER_AUTHOR "VIA"
+#define DRIVER_AUTHOR "Various"
#define DRIVER_NAME "via"
#define DRIVER_DESC "VIA Unichrome / Pro"
-#define DRIVER_DATE "20050523"
+#define DRIVER_DATE "20051116"
#define DRIVER_MAJOR 2
-#define DRIVER_MINOR 6
-#define DRIVER_PATCHLEVEL 3
+#define DRIVER_MINOR 7
+#define DRIVER_PATCHLEVEL 4
#include "via_verifier.h"
+#include "via_dmablit.h"
+
#define VIA_PCI_BUF_SIZE 60000
#define VIA_FIRE_BUF_SIZE 1024
-#define VIA_NUM_IRQS 2
+#define VIA_NUM_IRQS 4
typedef struct drm_via_ring_buffer {
- drm_map_t map;
+ drm_local_map_t map;
char *virtual_start;
} drm_via_ring_buffer_t;
@@ -56,9 +58,9 @@ typedef struct drm_via_irq {
typedef struct drm_via_private {
drm_via_sarea_t *sarea_priv;
- drm_map_t *sarea;
- drm_map_t *fb;
- drm_map_t *mmio;
+ drm_local_map_t *sarea;
+ drm_local_map_t *fb;
+ drm_local_map_t *mmio;
unsigned long agpAddr;
wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
char *dma_ptr;
@@ -82,8 +84,15 @@ typedef struct drm_via_private {
maskarray_t *irq_masks;
uint32_t irq_enable_mask;
uint32_t irq_pending_mask;
+ int *irq_map;
+ drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
} drm_via_private_t;
+enum via_family {
+ VIA_OTHER = 0,
+ VIA_PRO_GROUP_A,
+};
+
/* VIA MMIO register access */
#define VIA_BASE ((dev_priv->mmio))
@@ -92,12 +101,31 @@ typedef struct drm_via_private {
#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)
#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)
+extern drm_ioctl_desc_t via_ioctls[];
+extern int via_max_ioctl;
+
+extern int via_fb_init(DRM_IOCTL_ARGS);
+extern int via_mem_alloc(DRM_IOCTL_ARGS);
+extern int via_mem_free(DRM_IOCTL_ARGS);
+extern int via_agp_init(DRM_IOCTL_ARGS);
+extern int via_map_init(DRM_IOCTL_ARGS);
+extern int via_decoder_futex(DRM_IOCTL_ARGS);
+extern int via_dma_init(DRM_IOCTL_ARGS);
+extern int via_cmdbuffer(DRM_IOCTL_ARGS);
+extern int via_flush_ioctl(DRM_IOCTL_ARGS);
+extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
+extern int via_cmdbuf_size(DRM_IOCTL_ARGS);
+extern int via_wait_irq(DRM_IOCTL_ARGS);
+extern int via_dma_blit_sync( DRM_IOCTL_ARGS );
+extern int via_dma_blit( DRM_IOCTL_ARGS );
+
+extern int via_driver_load(drm_device_t *dev, unsigned long chipset);
+extern int via_driver_unload(drm_device_t *dev);
+
extern int via_init_context(drm_device_t * dev, int context);
extern int via_final_context(drm_device_t * dev, int context);
extern int via_do_cleanup_map(drm_device_t * dev);
-extern int via_map_init(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
@@ -111,8 +139,10 @@ extern int via_driver_dma_quiescent(drm_device_t * dev);
extern void via_init_futex(drm_via_private_t * dev_priv);
extern void via_cleanup_futex(drm_via_private_t * dev_priv);
extern void via_release_futex(drm_via_private_t * dev_priv, int context);
+extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq,
+ int force_sequence, unsigned int *sequence);
-extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf,
- unsigned int size);
+extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq);
+extern void via_init_dmablit(drm_device_t *dev);
#endif
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
index 5c71e089246c..9429736b3b96 100644
--- a/drivers/char/drm/via_ds.c
+++ b/drivers/char/drm/via_ds.c
@@ -22,14 +22,7 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/pci.h>
-#include <asm/io.h>
+#include "drmP.h"
#include "via_ds.h"
extern unsigned int VIA_DEBUG;
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
index d023add1929b..56d7e3daea12 100644
--- a/drivers/char/drm/via_irq.c
+++ b/drivers/char/drm/via_irq.c
@@ -50,6 +50,15 @@
#define VIA_IRQ_HQV1_ENABLE (1 << 25)
#define VIA_IRQ_HQV0_PENDING (1 << 9)
#define VIA_IRQ_HQV1_PENDING (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
/*
* Device-specific IRQs go here. This type might need to be extended with
@@ -61,13 +70,24 @@ static maskarray_t via_pro_group_a_irqs[] = {
{VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
0x00000000},
{VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
- 0x00000000}
+ 0x00000000},
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
};
static int via_num_pro_group_a =
sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t);
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
-static maskarray_t via_unichrome_irqs[] = { };
+static maskarray_t via_unichrome_irqs[] = {
+ {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+ {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+ VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
static unsigned time_diff(struct timeval *now, struct timeval *then)
{
@@ -113,6 +133,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
atomic_inc(&cur_irq->irq_received);
DRM_WAKEUP(&cur_irq->irq_queue);
handled = 1;
+ if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) {
+ via_dmablit_handler(dev, 0, 1);
+ } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) {
+ via_dmablit_handler(dev, 1, 1);
+ }
}
cur_irq++;
}
@@ -165,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
return ret;
}
-static int
+int
via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
unsigned int *sequence)
{
@@ -174,6 +199,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
drm_via_irq_t *cur_irq = dev_priv->via_irqs;
int ret = 0;
maskarray_t *masks = dev_priv->irq_masks;
+ int real_irq;
DRM_DEBUG("%s\n", __FUNCTION__);
@@ -182,15 +208,23 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
return DRM_ERR(EINVAL);
}
- if (irq >= dev_priv->num_irqs) {
+ if (irq >= drm_via_irq_num) {
DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
irq);
return DRM_ERR(EINVAL);
}
- cur_irq += irq;
+ real_irq = dev_priv->irq_map[irq];
+
+ if (real_irq < 0) {
+ DRM_ERROR("%s Video IRQ %d not available on this hardware.\n",
+ __FUNCTION__, irq);
+ return DRM_ERR(EINVAL);
+ }
+
+ cur_irq += real_irq;
- if (masks[irq][2] && !force_sequence) {
+ if (masks[real_irq][2] && !force_sequence) {
DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
((VIA_READ(masks[irq][2]) & masks[irq][3]) ==
masks[irq][4]));
@@ -226,6 +260,8 @@ void via_driver_irq_preinstall(drm_device_t * dev)
via_pro_group_a_irqs : via_unichrome_irqs;
dev_priv->num_irqs = (dev_priv->pro_group_a) ?
via_num_pro_group_a : via_num_unichrome;
+ dev_priv->irq_map = (dev_priv->pro_group_a) ?
+ via_irqmap_pro_group_a : via_irqmap_unichrome;
for (i = 0; i < dev_priv->num_irqs; ++i) {
atomic_set(&cur_irq->irq_received, 0);
@@ -241,7 +277,7 @@ void via_driver_irq_preinstall(drm_device_t * dev)
dev_priv->last_vblank_valid = 0;
- // Clear VSync interrupt regs
+ /* Clear VSync interrupt regs */
status = VIA_READ(VIA_REG_INTERRUPT);
VIA_WRITE(VIA_REG_INTERRUPT, status &
~(dev_priv->irq_enable_mask));
@@ -291,8 +327,7 @@ void via_driver_irq_uninstall(drm_device_t * dev)
int via_wait_irq(DRM_IOCTL_ARGS)
{
- drm_file_t *priv = filp->private_data;
- drm_device_t *dev = priv->head->dev;
+ DRM_DEVICE;
drm_via_irqwait_t __user *argp = (void __user *)data;
drm_via_irqwait_t irqwait;
struct timeval now;
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
index 6bd6ac52ad1b..c6a08e96285b 100644
--- a/drivers/char/drm/via_map.c
+++ b/drivers/char/drm/via_map.c
@@ -27,16 +27,10 @@
static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
{
- drm_via_private_t *dev_priv;
+ drm_via_private_t *dev_priv = dev->dev_private;
DRM_DEBUG("%s\n", __FUNCTION__);
- dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER);
- if (dev_priv == NULL)
- return -ENOMEM;
-
- memset(dev_priv, 0, sizeof(drm_via_private_t));
-
DRM_GETSAREA();
if (!dev_priv->sarea) {
DRM_ERROR("could not find sarea!\n");
@@ -67,7 +61,8 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
dev_priv->agpAddr = init->agpAddr;
via_init_futex(dev_priv);
- dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
+
+ via_init_dmablit(dev);
dev->dev_private = (void *)dev_priv;
return 0;
@@ -75,15 +70,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
int via_do_cleanup_map(drm_device_t * dev)
{
- if (dev->dev_private) {
-
- drm_via_private_t *dev_priv = dev->dev_private;
-
- via_dma_cleanup(dev);
-
- drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- }
+ via_dma_cleanup(dev);
return 0;
}
@@ -107,3 +94,29 @@ int via_map_init(DRM_IOCTL_ARGS)
return -EINVAL;
}
+
+int via_driver_load(drm_device_t *dev, unsigned long chipset)
+{
+ drm_via_private_t *dev_priv;
+
+ dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+ if (dev_priv == NULL)
+ return DRM_ERR(ENOMEM);
+
+ dev->dev_private = (void *)dev_priv;
+
+ if (chipset == VIA_PRO_GROUP_A)
+ dev_priv->pro_group_a = 1;
+
+ return 0;
+}
+
+int via_driver_unload(drm_device_t *dev)
+{
+ drm_via_private_t *dev_priv = dev->dev_private;
+
+ drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
+
+ return 0;
+}
+
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
index 3baddacdff26..33e0cb12e4c3 100644
--- a/drivers/char/drm/via_mm.c
+++ b/drivers/char/drm/via_mm.c
@@ -42,7 +42,7 @@ static int via_agp_free(drm_via_mem_t * mem);
static int via_fb_alloc(drm_via_mem_t * mem);
static int via_fb_free(drm_via_mem_t * mem);
-static int add_alloc_set(int context, int type, unsigned int val)
+static int add_alloc_set(int context, int type, unsigned long val)
{
int i, retval = 0;
@@ -56,7 +56,7 @@ static int add_alloc_set(int context, int type, unsigned int val)
return retval;
}
-static int del_alloc_set(int context, int type, unsigned int val)
+static int del_alloc_set(int context, int type, unsigned long val)
{
int i, retval = 0;
@@ -199,13 +199,13 @@ int via_mem_alloc(DRM_IOCTL_ARGS)
sizeof(mem));
switch (mem.type) {
- case VIDEO:
+ case VIA_MEM_VIDEO:
if (via_fb_alloc(&mem) < 0)
return -EFAULT;
DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
sizeof(mem));
return 0;
- case AGP:
+ case VIA_MEM_AGP:
if (via_agp_alloc(&mem) < 0)
return -EFAULT;
DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
@@ -232,7 +232,7 @@ static int via_fb_alloc(drm_via_mem_t * mem)
if (block) {
fb.offset = block->ofs;
fb.free = (unsigned long)block;
- if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
+ if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
DRM_DEBUG("adding to allocation set fails\n");
via_mmFreeMem((PMemBlock) fb.free);
retval = -1;
@@ -269,7 +269,7 @@ static int via_agp_alloc(drm_via_mem_t * mem)
if (block) {
agp.offset = block->ofs;
agp.free = (unsigned long)block;
- if (!add_alloc_set(agp.context, AGP, agp.free)) {
+ if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
DRM_DEBUG("adding to allocation set fails\n");
via_mmFreeMem((PMemBlock) agp.free);
retval = -1;
@@ -297,11 +297,11 @@ int via_mem_free(DRM_IOCTL_ARGS)
switch (mem.type) {
- case VIDEO:
+ case VIA_MEM_VIDEO:
if (via_fb_free(&mem) == 0)
return 0;
break;
- case AGP:
+ case VIA_MEM_AGP:
if (via_agp_free(&mem) == 0)
return 0;
break;
@@ -329,7 +329,7 @@ static int via_fb_free(drm_via_mem_t * mem)
via_mmFreeMem((PMemBlock) fb.free);
- if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
+ if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) {
retval = -1;
}
@@ -352,7 +352,7 @@ static int via_agp_free(drm_via_mem_t * mem)
via_mmFreeMem((PMemBlock) agp.free);
- if (!del_alloc_set(agp.context, AGP, agp.free)) {
+ if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) {
retval = -1;
}
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
index 4ac495f297f7..70c897c88766 100644
--- a/drivers/char/drm/via_verifier.c
+++ b/drivers/char/drm/via_verifier.c
@@ -237,7 +237,7 @@ static hazard_t table3[256];
static __inline__ int
eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
{
- if ((*buf - buf_end) >= num_words) {
+ if ((buf_end - *buf) >= num_words) {
*buf += num_words;
return 0;
}
@@ -249,14 +249,14 @@ eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words)
* Partially stolen from drm_memory.h
*/
-static __inline__ drm_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq,
+static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
unsigned long offset,
unsigned long size,
drm_device_t * dev)
{
struct list_head *list;
drm_map_list_t *r_list;
- drm_map_t *map = seq->map_cache;
+ drm_local_map_t *map = seq->map_cache;
if (map && map->offset <= offset
&& (offset + size) <= (map->offset + map->size)) {
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
index eb4eda344345..256590fcc22a 100644
--- a/drivers/char/drm/via_verifier.h
+++ b/drivers/char/drm/via_verifier.h
@@ -47,7 +47,7 @@ typedef struct {
int agp_texture;
int multitex;
drm_device_t *dev;
- drm_map_t *map_cache;
+ drm_local_map_t *map_cache;
uint32_t vertex_count;
int agp;
const uint32_t *buf_start;
@@ -55,5 +55,7 @@ typedef struct {
extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
drm_device_t * dev, int agp);
+extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf,
+ unsigned int size);
#endif
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
index 7fab9fbdf424..300ac61b09ed 100644
--- a/drivers/char/drm/via_video.c
+++ b/drivers/char/drm/via_video.c
@@ -50,8 +50,11 @@ void via_release_futex(drm_via_private_t * dev_priv, int context)
unsigned int i;
volatile int *lock;
+ if (!dev_priv->sarea_priv)
+ return;
+
for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
- lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+ lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
if (_DRM_LOCK_IS_HELD(*lock)
&& (*lock & _DRM_LOCK_CONT)) {
@@ -79,7 +82,7 @@ int via_decoder_futex(DRM_IOCTL_ARGS)
if (fx.lock > VIA_NR_XVMC_LOCKS)
return -EFAULT;
- lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);
+ lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock);
switch (fx.func) {
case VIA_FUTEX_WAIT:
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8693835cb2d5..e233cf280bc0 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -165,7 +165,7 @@ static int dsp56k_reset(void)
return 0;
}
-static int dsp56k_upload(u_char *bin, int len)
+static int dsp56k_upload(u_char __user *bin, int len)
{
int i;
u_char *p;
@@ -199,7 +199,7 @@ static int dsp56k_upload(u_char *bin, int len)
return 0;
}
-static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
+static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
@@ -225,10 +225,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
case 2: /* 16 bit */
{
- short *data;
+ short __user *data;
count /= 2;
- data = (short*) buf;
+ data = (short __user *) buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
put_user(dsp56k_host_interface.data.w[1], data+n++));
return 2*n;
@@ -244,10 +244,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
case 4: /* 32 bit */
{
- long *data;
+ long __user *data;
count /= 4;
- data = (long*) buf;
+ data = (long __user *) buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
put_user(dsp56k_host_interface.data.l, data+n++));
return 4*n;
@@ -262,7 +262,7 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count,
}
}
-static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
+static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
@@ -287,10 +287,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
}
case 2: /* 16 bit */
{
- const short *data;
+ const short __user *data;
count /= 2;
- data = (const short *)buf;
+ data = (const short __user *)buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
get_user(dsp56k_host_interface.data.w[1], data+n++));
return 2*n;
@@ -306,10 +306,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count,
}
case 4: /* 32 bit */
{
- const long *data;
+ const long __user *data;
count /= 4;
- data = (const long *)buf;
+ data = (const long __user *)buf;
handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
get_user(dsp56k_host_interface.data.l, data+n++));
return 4*n;
@@ -328,6 +328,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int dev = iminor(inode) & 0x0f;
+ void __user *argp = (void __user *)arg;
switch(dev)
{
@@ -336,9 +337,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
switch(cmd) {
case DSP56K_UPLOAD:
{
- char *bin;
+ char __user *bin;
int r, len;
- struct dsp56k_upload *binary = (struct dsp56k_upload *) arg;
+ struct dsp56k_upload __user *binary = argp;
if(get_user(len, &binary->len) < 0)
return -EFAULT;
@@ -372,7 +373,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file,
case DSP56K_HOST_FLAGS:
{
int dir, out, status;
- struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg;
+ struct dsp56k_host_flags __user *hf = argp;
if(get_user(dir, &hf->dir) < 0)
return -EFAULT;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 407708a001e4..765c5c108bf4 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -1786,9 +1786,7 @@ static void doevent(int crd)
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_insert_flip_char(tty, 0, TTY_BREAK);
tty_schedule_flip(tty);
} else if (event & LOWTX_IND) { /* Begin LOWTX_IND */
if (ch->statusflags & LOWWAIT)
@@ -2124,7 +2122,6 @@ static void receive_data(struct channel *ch)
int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head;
unsigned int wrapmask;
- int rc;
/* ---------------------------------------------------------------
This routine is called by doint when a receive data event
@@ -2162,16 +2159,15 @@ static void receive_data(struct channel *ch)
return;
}
- if (tty->flip.count == TTY_FLIPBUF_SIZE)
+ if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
return;
if (readb(&bc->orun)) {
writeb(0, &bc->orun);
printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
rxwinon(ch);
- rptr = tty->flip.char_buf_ptr;
- rc = tty->flip.count;
while (bytesAvailable > 0) { /* Begin while there is data on the card */
wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
/* ---------------------------------------------------------------
@@ -2183,8 +2179,7 @@ static void receive_data(struct channel *ch)
/* --------------------------------------------------------------
Make sure we don't overflow the buffer
----------------------------------------------------------------- */
- if ((rc + dataToRead) > TTY_FLIPBUF_SIZE)
- dataToRead = TTY_FLIPBUF_SIZE - rc;
+ dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
if (dataToRead == 0)
break;
/* ---------------------------------------------------------------
@@ -2192,13 +2187,9 @@ static void receive_data(struct channel *ch)
for translation if necessary.
------------------------------------------------------------------ */
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);
writew(tail, &bc->rout);
/* Must be called with global data */
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 9f53d2fcc360..3f3ac039f4d9 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static inline int serial_paranoia_check(struct esp_struct *info,
char *name, const char *routine)
@@ -345,26 +344,22 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
for (i = 0; i < num_bytes; i++) {
if (!(err_buf->data[i] & status_mask)) {
- *(tty->flip.char_buf_ptr++) = pio_buf->data[i];
+ int flag = 0;
if (err_buf->data[i] & 0x04) {
- *(tty->flip.flag_buf_ptr++) = TTY_BREAK;
-
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
}
else if (err_buf->data[i] & 0x02)
- *(tty->flip.flag_buf_ptr++) = TTY_FRAME;
+ flag = TTY_FRAME;
else if (err_buf->data[i] & 0x01)
- *(tty->flip.flag_buf_ptr++) = TTY_PARITY;
- else
- *(tty->flip.flag_buf_ptr++) = 0;
-
- tty->flip.count++;
+ flag = TTY_PARITY;
+ tty_insert_flip_char(tty, pio_buf->data[i], flag);
}
}
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
release_pio_buffer(pio_buf);
@@ -397,7 +392,6 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
int num_bytes;
unsigned long flags;
-
flags=claim_dma_lock();
disable_dma(dma);
clear_dma_ff(dma);
@@ -408,38 +402,31 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
info->icount.rx += num_bytes;
- memcpy(tty->flip.char_buf_ptr, dma_buffer, num_bytes);
- tty->flip.char_buf_ptr += num_bytes;
- tty->flip.count += num_bytes;
- memset(tty->flip.flag_buf_ptr, 0, num_bytes);
- tty->flip.flag_buf_ptr += num_bytes;
-
if (num_bytes > 0) {
- tty->flip.flag_buf_ptr--;
+ tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
status &= (0x1c & info->read_status_mask);
+
+ /* Is the status significant or do we throw the last byte ? */
+ if (!(status & info->ignore_status_mask)) {
+ int statflag = 0;
- if (status & info->ignore_status_mask) {
- tty->flip.count--;
- tty->flip.char_buf_ptr--;
- tty->flip.flag_buf_ptr--;
- } else if (status & 0x10) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- (info->icount.brk)++;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (status & 0x08) {
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- (info->icount.frame)++;
- }
- else if (status & 0x04) {
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- (info->icount.parity)++;
+ if (status & 0x10) {
+ statflag = TTY_BREAK;
+ (info->icount.brk)++;
+ if (info->flags & ASYNC_SAK)
+ do_SAK(tty);
+ } else if (status & 0x08) {
+ statflag = TTY_FRAME;
+ (info->icount.frame)++;
+ }
+ else if (status & 0x04) {
+ statflag = TTY_PARITY;
+ (info->icount.parity)++;
+ }
+ tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
}
-
- tty->flip.flag_buf_ptr++;
-
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
if (dma_bytes != num_bytes) {
@@ -693,8 +680,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id,
num_bytes = serial_in(info, UART_ESI_STAT1) << 8;
num_bytes |= serial_in(info, UART_ESI_STAT2);
- if (num_bytes > (TTY_FLIPBUF_SIZE - info->tty->flip.count))
- num_bytes = TTY_FLIPBUF_SIZE - info->tty->flip.count;
+ num_bytes = tty_buffer_request_room(info->tty, num_bytes);
if (num_bytes) {
if (dma_bytes ||
@@ -2506,6 +2492,7 @@ static int __init espserial_init(void)
}
memset((void *)info, 0, sizeof(struct esp_struct));
+ spin_lock_init(&info->lock);
/* rx_trigger, tx_trigger are needed by autoconfig */
info->config.rx_trigger = rx_trigger;
info->config.tx_trigger = tx_trigger;
@@ -2542,7 +2529,6 @@ static int __init espserial_init(void)
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
- spin_lock_init(&info->lock);
ports = info;
printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
info->line, info->port, info->irq);
diff --git a/drivers/char/ftape/Kconfig b/drivers/char/ftape/Kconfig
index 7d3ecb56a1bd..0d65189a7ae8 100644
--- a/drivers/char/ftape/Kconfig
+++ b/drivers/char/ftape/Kconfig
@@ -25,17 +25,7 @@ config ZFTAPE
support", above) then `zft-compressor' will be loaded
automatically by zftape when needed.
- Despite its name, zftape does NOT use compression by default. The
- file <file:Documentation/ftape.txt> contains a short description of
- the most important changes in the file system interface compared to
- previous versions of ftape. The ftape home page
- <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
- further information.
-
- IMPORTANT NOTE: zftape can read archives created by previous
- versions of ftape and provide file mark support (i.e. fast skipping
- between tape archives) but previous version of ftape will lack file
- mark support when reading archives produced by zftape.
+ Despite its name, zftape does NOT use compression by default.
config ZFT_DFLT_BLK_SZ
int "Default block size"
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 204a7302a4a9..e38a5f0e07bb 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -34,7 +34,6 @@
#define DEBUG
static char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static int gs_debug;
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 66e53dd450ff..40a67c86420c 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -120,7 +120,7 @@ __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#if defined(CONFIG_X86)
# define HAVE_MONOTONIC
# define TIMER_FREQ 1000000000ULL
-#elif defined(CONFIG_ARCH_S390)
+#elif defined(CONFIG_S390)
/* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */
# define TIMER_FREQ 0xFA240000ULL
#elif defined(CONFIG_IA64)
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index f92177634677..1994a92d4733 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -597,9 +597,7 @@ static int hvc_poll(struct hvc_struct *hp)
/* Read data if any */
for (;;) {
- int count = N_INBUF;
- if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ int count = tty_buffer_request_room(tty, N_INBUF);
/* If flip is full, just reschedule a later read */
if (count == 0) {
@@ -635,7 +633,7 @@ static int hvc_poll(struct hvc_struct *hp)
tty_insert_flip_char(tty, buf[i], 0);
}
- if (tty->flip.count)
+ if (count)
tty_schedule_flip(tty);
/*
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 53dc77c760fc..831eb4e8d9d3 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -456,12 +456,11 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
/* remove the read masks */
hvcsd->todo_mask &= ~(HVCS_READ_MASK);
- if ((tty->flip.count + HVCS_BUFF_LEN) < TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, HVCS_BUFF_LEN) >= HVCS_BUFF_LEN) {
got = hvc_get_chars(unit_address,
&buf[0],
HVCS_BUFF_LEN);
- for (i=0;got && i<got;i++)
- tty_insert_flip_char(tty, buf[i], TTY_NORMAL);
+ tty_insert_flip_string(tty, buf, got);
}
/* Give the TTY time to process the data we just sent. */
@@ -469,10 +468,9 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
hvcsd->todo_mask |= HVCS_QUICK_READ;
spin_unlock_irqrestore(&hvcsd->lock, flags);
- if (tty->flip.count) {
- /* This is synch because tty->low_latency == 1 */
+ /* This is synch because tty->low_latency == 1 */
+ if(got)
tty_flip_buffer_push(tty);
- }
if (!got) {
/* Do this _after_ the flip_buffer_push */
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a22aa940e01e..a9522189fc9e 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -197,7 +197,7 @@ static inline void print_state(struct hvsi_struct *hp)
};
const char *name = state_names[hp->state];
- if (hp->state > (sizeof(state_names)/sizeof(char*)))
+ if (hp->state > ARRAY_SIZE(state_names))
name = "UNKNOWN";
pr_debug("hvsi%i: state = %s\n", hp->index, name);
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 6f673d2de0b1..b3bc2e37e616 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -1,4 +1,9 @@
/*
+ Added support for the AMD Geode LX RNG
+ (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+ derived from
+
Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
@@ -95,6 +100,11 @@ static unsigned int via_data_present (void);
static u32 via_data_read (void);
#endif
+static int __init geode_init(struct pci_dev *dev);
+static void geode_cleanup(void);
+static unsigned int geode_data_present (void);
+static u32 geode_data_read (void);
+
struct rng_operations {
int (*init) (struct pci_dev *dev);
void (*cleanup) (void);
@@ -122,6 +132,7 @@ enum {
rng_hw_intel,
rng_hw_amd,
rng_hw_via,
+ rng_hw_geode,
};
static struct rng_operations rng_vendor_ops[] = {
@@ -139,6 +150,9 @@ static struct rng_operations rng_vendor_ops[] = {
/* rng_hw_via */
{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
#endif
+
+ /* rng_hw_geode */
+ { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
};
/*
@@ -155,10 +169,14 @@ static struct pci_device_id rng_pci_tbl[] = {
{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
+
{ 0, }, /* terminate list */
};
MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
@@ -460,6 +478,57 @@ static void via_cleanup(void)
}
#endif
+/***********************************************************************
+ *
+ * AMD Geode RNG operations
+ *
+ */
+
+static void __iomem *geode_rng_base = NULL;
+
+#define GEODE_RNG_DATA_REG 0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+static u32 geode_data_read(void)
+{
+ u32 val;
+
+ assert(geode_rng_base != NULL);
+ val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
+ return val;
+}
+
+static unsigned int geode_data_present(void)
+{
+ u32 val;
+
+ assert(geode_rng_base != NULL);
+ val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
+ return val;
+}
+
+static void geode_cleanup(void)
+{
+ iounmap(geode_rng_base);
+ geode_rng_base = NULL;
+}
+
+static int geode_init(struct pci_dev *dev)
+{
+ unsigned long rng_base = pci_resource_start(dev, 0);
+
+ if (rng_base == 0)
+ return 1;
+
+ geode_rng_base = ioremap(rng_base, 0x58);
+
+ if (geode_rng_base == NULL) {
+ printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
/***********************************************************************
*
@@ -574,7 +643,7 @@ static int __init rng_init (void)
DPRINTK ("ENTER\n");
- /* Probe for Intel, AMD RNGs */
+ /* Probe for Intel, AMD, Geode RNGs */
for_each_pci_dev(pdev) {
ent = pci_match_id(rng_pci_tbl, pdev);
if (ent) {
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
index ba85eb1b6ec7..fc944d375be7 100644
--- a/drivers/char/ip2/i2lib.c
+++ b/drivers/char/ip2/i2lib.c
@@ -854,7 +854,7 @@ i2Input(i2ChanStrPtr pCh)
count += IBUF_SIZE;
}
// Don't give more than can be taken by the line discipline
- amountToMove = pCh->pTTY->ldisc.receive_room( pCh->pTTY );
+ amountToMove = pCh->pTTY->receive_room;
if (count > amountToMove) {
count = amountToMove;
}
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h
index e9b87a78622c..00342a677c90 100644
--- a/drivers/char/ip2/i2pack.h
+++ b/drivers/char/ip2/i2pack.h
@@ -358,7 +358,7 @@ typedef struct _failStat
#define MB_OUT_STRIPPED 0x40 // Board has read all output from fifo
#define MB_FATAL_ERROR 0x20 // Board has encountered a fatal error
-#pragma pack(4) // Reset padding to command-line default
+#pragma pack() // Reset padding to command-line default
#endif // I2PACK_H
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index d815d197dc3e..56e93a5a1e24 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -172,7 +172,7 @@ static int Fip_firmware_size;
/* Private (static) functions */
static int ip2_open(PTTY, struct file *);
static void ip2_close(PTTY, struct file *);
-static int ip2_write(PTTY, int, const unsigned char *, int);
+static int ip2_write(PTTY, const unsigned char *, int);
static void ip2_putchar(PTTY, unsigned char);
static void ip2_flush_chars(PTTY);
static int ip2_write_room(PTTY);
@@ -1713,7 +1713,7 @@ ip2_hangup ( PTTY tty )
/* */
/******************************************************************************/
static int
-ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
+ip2_write( PTTY tty, const unsigned char *pData, int count)
{
i2ChanStrPtr pCh = tty->driver_data;
int bytesSent = 0;
@@ -1726,7 +1726,7 @@ ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
/* This is the actual move bit. Make sure it does what we need!!!!! */
WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
- bytesSent = i2Output( pCh, pData, count, user );
+ bytesSent = i2Output( pCh, pData, count, 0 );
WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
@@ -2001,7 +2001,9 @@ ip2_stop ( PTTY tty )
static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
{
i2ChanStrPtr pCh = DevTable[tty->index];
+#ifdef ENABLE_DSSNOW
wait_queue_t wait;
+#endif
if (pCh == NULL)
return -ENODEV;
@@ -2089,15 +2091,17 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
{
wait_queue_t wait;
i2ChanStrPtr pCh = DevTable[tty->index];
+ i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser;
int rc = 0;
unsigned long flags;
void __user *argp = (void __user *)arg;
- if ( pCh == NULL ) {
+ if ( pCh == NULL )
return -ENODEV;
- }
+
+ pB = pCh->pMyBord;
ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
@@ -2206,9 +2210,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
* for masking). Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cprev = pCh->icount; /* note the counters on entry */
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4,
CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
init_waitqueue_entry(&wait, current);
@@ -2228,9 +2232,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
rc = -ERESTARTSYS;
break;
}
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount; /* atomic copy */
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
rc = -EIO; /* no change => rc */
@@ -2268,9 +2272,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
case TIOCGICOUNT:
ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
- save_flags(flags);cli();
+ WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
cnow = pCh->icount;
- restore_flags(flags);
+ WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
p_cuser = argp;
rc = put_user(cnow.cts, &p_cuser->cts);
rc = put_user(cnow.dsr, &p_cuser->dsr);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 1f56b4cf0f58..0097f06fa67b 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -57,6 +57,7 @@ static int initialized = 0;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_ipmi_root = NULL;
+EXPORT_SYMBOL(proc_ipmi_root);
#endif /* CONFIG_PROC_FS */
#define MAX_EVENTS_IN_QUEUE 25
@@ -787,7 +788,6 @@ int ipmi_destroy_user(ipmi_user_t user)
int i;
unsigned long flags;
struct cmd_rcvr *rcvr;
- struct list_head *entry1, *entry2;
struct cmd_rcvr *rcvrs = NULL;
user->valid = 1;
@@ -812,8 +812,7 @@ int ipmi_destroy_user(ipmi_user_t user)
* synchronize_rcu()) then free everything in that list.
*/
down(&intf->cmd_rcvrs_lock);
- list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
- rcvr = list_entry(entry1, struct cmd_rcvr, link);
+ list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
if (rcvr->user == user) {
list_del_rcu(&rcvr->link);
rcvr->next = rcvrs;
@@ -3297,6 +3296,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
EXPORT_SYMBOL(ipmi_set_my_LUN);
EXPORT_SYMBOL(ipmi_get_my_LUN);
EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
-EXPORT_SYMBOL(proc_ipmi_root);
EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
EXPORT_SYMBOL(ipmi_free_recv_msg);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e053eade0366..49c09ae004bf 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -612,11 +612,14 @@ static int ipmi_poweroff_init (void)
#endif
rv = ipmi_smi_watcher_register(&smi_watcher);
+
+#ifdef CONFIG_PROC_FS
if (rv) {
unregister_sysctl_table(ipmi_table_header);
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
goto out_err;
}
+#endif
out_err:
return rv;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index beea450ee4b2..c67ef3e47ad5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1056,7 +1056,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) || defined(CONFIG_X86) || defined(CONFIG_PCI)
+#if defined(CONFIG_ACPI) || defined(CONFIG_DMI) || defined(CONFIG_PCI)
static int is_new_interface(int intf, u8 addr_space, unsigned long base_addr)
{
int i;
@@ -1669,7 +1669,7 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
}
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
typedef struct dmi_ipmi_data
{
u8 type;
@@ -1829,7 +1829,7 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
ipmi_data->slave_addr);
return 0;
}
-#endif /* CONFIG_X86 */
+#endif /* CONFIG_DMI */
#ifdef CONFIG_PCI
@@ -2222,7 +2222,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
if (rv && si_trydefaults)
rv = try_init_acpi(intf_num, &new_smi);
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
if (rv && si_trydefaults)
rv = try_init_smbios(intf_num, &new_smi);
#endif
@@ -2433,7 +2433,7 @@ static __init int init_ipmi_si(void)
printk(KERN_INFO "IPMI System Interface driver.\n");
-#ifdef CONFIG_X86
+#ifdef CONFIG_DMI
dmi_find_bmc();
#endif
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 1bbf507adda5..e9ebabaf8cb0 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -20,7 +20,7 @@
* 3/9/99 sameer Added support for ISI4616 cards.
*
* 16/9/99 sameer We do not force RTS low anymore.
- * This is to prevent the firmware
+ * This is to prevent the firmware
* from getting confused.
*
* 26/10/99 sameer Cosmetic changes:The driver now
@@ -31,28 +31,28 @@
*
* 10/5/00 sameer Fixed isicom_shutdown_board()
* to not lower DTR on all the ports
- * when the last port on the card is
+ * when the last port on the card is
* closed.
*
* 10/5/00 sameer Signal mask setup command added
- * to isicom_setup_port and
+ * to isicom_setup_port and
* isicom_shutdown_port.
*
* 24/5/00 sameer The driver is now SMP aware.
- *
- *
+ *
+ *
* 27/11/00 Vinayak P Risbud Fixed the Driver Crash Problem
- *
- *
+ *
+ *
* 03/01/01 anil .s Added support for resetting the
* internal modems on ISI cards.
*
* 08/02/01 anil .s Upgraded the driver for kernel
* 2.4.x
*
- * 11/04/01 Kevin Fixed firmware load problem with
+ * 11/04/01 Kevin Fixed firmware load problem with
* ISIHP-4X card
- *
+ *
* 30/04/01 anil .s Fixed the remote login through
* ISI port problem. Now the link
* does not go down before password
@@ -62,9 +62,9 @@
* among ISI-PCI cards.
*
* 03/05/01 anil .s Added support to display the version
- * info during insmod as well as module
+ * info during insmod as well as module
* listing by lsmod.
- *
+ *
* 10/05/01 anil .s Done the modifications to the source
* file and Install script so that the
* same installation can be used for
@@ -73,19 +73,19 @@
* 06/06/01 anil .s Now we drop both dtr and rts during
* shutdown_port as well as raise them
* during isicom_config_port.
- *
+ *
* 09/06/01 acme@conectiva.com.br use capable, not suser, do
* restore_flags on failure in
* isicom_send_break, verify put_user
* result
*
- * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
- * Baud index extended to 21
- *
- * 20/03/03 ranjeeth Made to work for Linux Advanced server.
- * Taken care of license warning.
- *
- * 10/12/03 Ravindra Made to work for Fedora Core 1 of
+ * 11/02/03 ranjeeth Added support for 230 Kbps and 460 Kbps
+ * Baud index extended to 21
+ *
+ * 20/03/03 ranjeeth Made to work for Linux Advanced server.
+ * Taken care of license warning.
+ *
+ * 10/12/03 Ravindra Made to work for Fedora Core 1 of
* Red Hat Distribution
*
* 06/01/05 Alan Cox Merged the ISI and base kernel strands
@@ -93,10 +93,10 @@
*
* ***********************************************************
*
- * To use this driver you also need the support package. You
+ * To use this driver you also need the support package. You
* can find this in RPM format on
* ftp://ftp.linux.org.uk/pub/linux/alan
- *
+ *
* You can find the original tools for this direct from Multitech
* ftp://ftp.multitech.com/ISI-Cards/
*
@@ -107,20 +107,20 @@
* Omit those entries for boards you don't have installed.
*
* TODO
- * Hotplug
* Merge testing
* 64-bit verification
*/
#include <linux/module.h>
+#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/termios.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/serial.h>
#include <linux/mm.h>
-#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/delay.h>
@@ -134,50 +134,62 @@
#include <linux/isicom.h>
+#define InterruptTheCard(base) outw(0, (base) + 0xc)
+#define ClearInterrupt(base) inw((base) + 0x0a)
+
+#ifdef DEBUG
+#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str)
+#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
+#else
+#define pr_dbg(str...) do { } while (0)
+#define isicom_paranoia_check(a, b, c) 0
+#endif
+
+static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit isicom_remove(struct pci_dev *);
+
static struct pci_device_id isicom_pci_tbl[] = {
- { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(VENDOR_ID, 0x2028) },
+ { PCI_DEVICE(VENDOR_ID, 0x2051) },
+ { PCI_DEVICE(VENDOR_ID, 0x2052) },
+ { PCI_DEVICE(VENDOR_ID, 0x2053) },
+ { PCI_DEVICE(VENDOR_ID, 0x2054) },
+ { PCI_DEVICE(VENDOR_ID, 0x2055) },
+ { PCI_DEVICE(VENDOR_ID, 0x2056) },
+ { PCI_DEVICE(VENDOR_ID, 0x2057) },
+ { PCI_DEVICE(VENDOR_ID, 0x2058) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
+static struct pci_driver isicom_driver = {
+ .name = "isicom",
+ .id_table = isicom_pci_tbl,
+ .probe = isicom_probe,
+ .remove = __devexit_p(isicom_remove)
+};
+
static int prev_card = 3; /* start servicing isi_card[0] */
static struct tty_driver *isicom_normal;
static struct timer_list tx;
static char re_schedule = 1;
-#ifdef ISICOM_DEBUG
-static unsigned long tx_count = 0;
-#endif
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static void isicom_tx(unsigned long _data);
-static void isicom_start(struct tty_struct * tty);
-
-static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
+static void isicom_start(struct tty_struct *tty);
/* baud index mappings from linux defns to isi */
static signed char linuxb_to_isib[] = {
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,
- 18, 19
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19
};
struct isi_board {
- unsigned short base;
+ unsigned long base;
unsigned char irq;
unsigned char port_count;
unsigned short status;
- unsigned short port_status; /* each bit represents a single port */
+ unsigned short port_status; /* each bit for each port */
unsigned short shift_count;
struct isi_port * ports;
signed char count;
@@ -192,9 +204,9 @@ struct isi_port {
int count;
int blocked_open;
int close_delay;
- unsigned short channel;
- unsigned short status;
- unsigned short closing_wait;
+ u16 channel;
+ u16 status;
+ u16 closing_wait;
struct isi_board * card;
struct tty_struct * tty;
wait_queue_head_t close_wait;
@@ -215,35 +227,37 @@ static struct isi_port isi_ports[PORT_COUNT];
* the kernel lock for the card and have the card in a position that
* it wants to talk.
*/
-
+
static int lock_card(struct isi_board *card)
{
char retries;
- unsigned short base = card->base;
+ unsigned long base = card->base;
for (retries = 0; retries < 100; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
if (inw(base + 0xe) & 0x1) {
- return 1;
+ return 1;
} else {
spin_unlock_irqrestore(&card->card_lock, card->flags);
udelay(1000); /* 1ms */
}
}
- printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%x)\n", card->base);
+ printk(KERN_WARNING "ISICOM: Failed to lock Card (0x%lx)\n",
+ card->base);
+
return 0; /* Failed to aquire the card! */
}
static int lock_card_at_interrupt(struct isi_board *card)
{
unsigned char retries;
- unsigned short base = card->base;
+ unsigned long base = card->base;
for (retries = 0; retries < 200; retries++) {
spin_lock_irqsave(&card->card_lock, card->flags);
if (inw(base + 0xe) & 0x1)
- return 1;
+ return 1;
else
spin_unlock_irqrestore(&card->card_lock, card->flags);
}
@@ -259,373 +273,141 @@ static void unlock_card(struct isi_board *card)
/*
* ISI Card specific ops ...
*/
-
-static void raise_dtr(struct isi_port * port)
+
+static void raise_dtr(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0504, base);
InterruptTheCard(base);
port->status |= ISI_DTR;
unlock_card(card);
}
-static inline void drop_dtr(struct isi_port * port)
-{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+static inline void drop_dtr(struct isi_port *port)
+{
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0404, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~ISI_DTR;
unlock_card(card);
}
-static inline void raise_rts(struct isi_port * port)
+static inline void raise_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0a04, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status |= ISI_RTS;
unlock_card(card);
}
-static inline void drop_rts(struct isi_port * port)
+static inline void drop_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0804, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~ISI_RTS;
unlock_card(card);
}
-static inline void raise_dtr_rts(struct isi_port * port)
+static inline void raise_dtr_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0f04, base);
InterruptTheCard(base);
port->status |= (ISI_DTR | ISI_RTS);
unlock_card(card);
}
-static void drop_dtr_rts(struct isi_port * port)
+static void drop_dtr_rts(struct isi_port *port)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0c04, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
port->status &= ~(ISI_RTS | ISI_DTR);
unlock_card(card);
}
-static inline void kill_queue(struct isi_port * port, short queue)
+static inline void kill_queue(struct isi_port *port, short queue)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
- unsigned char channel = port->channel;
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+ u16 channel = port->channel;
if (!lock_card(card))
return;
- outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+ outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw((queue << 8) | 0x06, base);
- InterruptTheCard(base);
+ InterruptTheCard(base);
unlock_card(card);
}
-
-/*
- * Firmware loader driver specific routines. This needs to mostly die
- * and be replaced with request_firmware.
- */
-
-static struct file_operations ISILoad_fops = {
- .owner = THIS_MODULE,
- .ioctl = ISILoad_ioctl,
-};
-
-static struct miscdevice isiloader_device = {
- ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
-};
-
-
-static inline int WaitTillCardIsFree(unsigned short base)
-{
- unsigned long count=0;
- while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
- if (inw(base+0xe)&0x1)
- return 0;
- else
- return 1;
-}
-
-static int ISILoad_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- unsigned int card, i, j, signature, status, portcount = 0;
- unsigned long t;
- unsigned short word_count, base;
- bin_frame frame;
- void __user *argp = (void __user *)arg;
- /* exec_record exec_rec; */
-
- if(get_user(card, (int __user *)argp))
- return -EFAULT;
-
- if(card < 0 || card >= BOARD_COUNT)
- return -ENXIO;
-
- base=isi_card[card].base;
-
- if(base==0)
- return -ENXIO; /* disabled or not used */
-
- switch(cmd) {
- case MIOCTL_RESET_CARD:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
-
- inw(base+0x8);
-
- for(t=jiffies+HZ/100;time_before(jiffies, t););
-
- outw(0,base+0x8); /* Reset */
-
- for(j=1;j<=3;j++) {
- for(t=jiffies+HZ;time_before(jiffies, t););
- printk(".");
- }
- signature=(inw(base+0x4)) & 0xff;
- if (isi_card[card].isa) {
-
- if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
-#ifdef ISICOM_DEBUG
- printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
- printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
- return -EIO;
- }
- }
- else {
- portcount = inw(base+0x2);
- if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {
-#ifdef ISICOM_DEBUG
- printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
-#endif
- printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
- return -EIO;
- }
- }
- switch(signature) {
- case 0xa5:
- case 0xbb:
- case 0xdd:
- if (isi_card[card].isa)
- isi_card[card].port_count = 8;
- else {
- if (portcount == 4)
- isi_card[card].port_count = 4;
- else
- isi_card[card].port_count = 8;
- }
- isi_card[card].shift_count = 12;
- break;
-
- case 0xcc: isi_card[card].port_count = 16;
- isi_card[card].shift_count = 11;
- break;
-
- default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
-#ifdef ISICOM_DEBUG
- printk("Sig=0x%x\n",signature);
-#endif
- return -EIO;
- }
- printk("-Done\n");
- return put_user(signature,(unsigned __user *)argp);
-
- case MIOCTL_LOAD_FIRMWARE:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if(copy_from_user(&frame, argp, sizeof(bin_frame)))
- return -EFAULT;
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf0,base); /* start upload sequence */
- outw(0x00,base);
- outw((frame.addr), base);/* lsb of adderess */
-
- word_count=(frame.count >> 1) + frame.count % 2;
- outw(word_count, base);
- InterruptTheCard(base);
-
- for(i=0;i<=0x2f;i++); /* a wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
- card+1, frame.addr, frame.count, status);
- return -EIO;
- }
- outsw(base, (void *) frame.bin_data, word_count);
-
- InterruptTheCard(base);
-
- for(i=0;i<=0x0f;i++); /* another wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
- return -EIO;
- }
- return 0;
-
- case MIOCTL_READ_FIRMWARE:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- if(copy_from_user(&frame, argp, sizeof(bin_header)))
- return -EFAULT;
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf1,base); /* start download sequence */
- outw(0x00,base);
- outw((frame.addr), base);/* lsb of adderess */
-
- word_count=(frame.count >> 1) + frame.count % 2;
- outw(word_count+1, base);
- InterruptTheCard(base);
-
- for(i=0;i<=0xf;i++); /* a wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
- card+1, frame.addr, frame.count, status);
- return -EIO;
- }
-
- inw(base);
- insw(base, frame.bin_data, word_count);
- InterruptTheCard(base);
-
- for(i=0;i<=0x0f;i++); /* another wee bit of delay */
-
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- if ((status=inw(base+0x4))!=0) {
- printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
- return -EIO;
- }
-
- if(copy_to_user(argp, &frame, sizeof(bin_frame)))
- return -EFAULT;
- return 0;
-
- case MIOCTL_XFER_CTRL:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if (WaitTillCardIsFree(base))
- return -EIO;
-
- outw(0xf2, base);
- outw(0x800, base);
- outw(0x0, base);
- outw(0x0, base);
- InterruptTheCard(base);
- outw(0x0, base+0x4); /* for ISI4608 cards */
-
- isi_card[card].status |= FIRMWARE_LOADED;
- return 0;
-
- default:
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd);
-#endif
- return -ENOIOCTLCMD;
-
- }
-
-}
-
-
/*
* ISICOM Driver specific routines ...
*
*/
-
-static inline int isicom_paranoia_check(struct isi_port const * port, char *name,
- const char * routine)
+
+static inline int __isicom_paranoia_check(struct isi_port const *port,
+ char *name, const char *routine)
{
-#ifdef ISICOM_DEBUG
- static const char * badmagic =
- KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
- static const char * badport =
- KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";
if (!port) {
- printk(badport, name, routine);
+ printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for "
+ "dev %s in %s.\n", name, routine);
return 1;
}
if (port->magic != ISICOM_MAGIC) {
- printk(badmagic, name, routine);
+ printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for "
+ "dev %s in %s.\n", name, routine);
return 1;
- }
-#endif
+ }
+
return 0;
}
-
+
/*
- * Transmitter.
+ * Transmitter.
*
* We shovel data into the card buffers on a regular basis. The card
* will do the rest of the work for us.
@@ -635,25 +417,21 @@ static void isicom_tx(unsigned long _data)
{
short count = (BOARD_COUNT-1), card, base;
short txcount, wrd, residue, word_count, cnt;
- struct isi_port * port;
- struct tty_struct * tty;
-
-#ifdef ISICOM_DEBUG
- ++tx_count;
-#endif
-
+ struct isi_port *port;
+ struct tty_struct *tty;
+
/* find next active board */
card = (prev_card + 1) & 0x0003;
while(count-- > 0) {
- if (isi_card[card].status & BOARD_ACTIVE)
+ if (isi_card[card].status & BOARD_ACTIVE)
break;
- card = (card + 1) & 0x0003;
+ card = (card + 1) & 0x0003;
}
if (!(isi_card[card].status & BOARD_ACTIVE))
goto sched_again;
-
+
prev_card = card;
-
+
count = isi_card[card].port_count;
port = isi_card[card].ports;
base = isi_card[card].base;
@@ -662,18 +440,18 @@ static void isicom_tx(unsigned long _data)
continue;
/* port not active or tx disabled to force flow control */
if (!(port->flags & ASYNC_INITIALIZED) ||
- !(port->status & ISI_TXOK))
+ !(port->status & ISI_TXOK))
unlock_card(&isi_card[card]);
continue;
-
+
tty = port->tty;
-
-
- if(tty == NULL) {
+
+
+ if (tty == NULL) {
unlock_card(&isi_card[card]);
continue;
}
-
+
txcount = min_t(short, TX_SIZE, port->xmit_cnt);
if (txcount <= 0 || tty->stopped || tty->hw_stopped) {
unlock_card(&isi_card[card]);
@@ -681,44 +459,45 @@ static void isicom_tx(unsigned long _data)
}
if (!(inw(base + 0x02) & (1 << port->channel))) {
unlock_card(&isi_card[card]);
- continue;
+ continue;
}
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n",
- txcount, port->channel+1);
-#endif
- outw((port->channel << isi_card[card].shift_count) | txcount
- , base);
+ pr_dbg("txing %d bytes, port%d.\n", txcount,
+ port->channel + 1);
+ outw((port->channel << isi_card[card].shift_count) | txcount,
+ base);
residue = NO;
- wrd = 0;
+ wrd = 0;
while (1) {
- cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+ cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
+ - port->xmit_tail));
if (residue == YES) {
residue = NO;
if (cnt > 0) {
- wrd |= (port->xmit_buf[port->xmit_tail] << 8);
- port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ wrd |= (port->xmit_buf[port->xmit_tail]
+ << 8);
+ port->xmit_tail = (port->xmit_tail + 1)
+ & (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt--;
txcount--;
cnt--;
- outw(wrd, base);
- }
- else {
+ outw(wrd, base);
+ } else {
outw(wrd, base);
break;
}
- }
+ }
if (cnt <= 0) break;
word_count = cnt >> 1;
- outsw(base, port->xmit_buf+port->xmit_tail, word_count);
- port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
- (SERIAL_XMIT_SIZE - 1);
+ outsw(base, port->xmit_buf+port->xmit_tail,word_count);
+ port->xmit_tail = (port->xmit_tail
+ + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
txcount -= (word_count << 1);
port->xmit_cnt -= (word_count << 1);
if (cnt & 0x0001) {
residue = YES;
wrd = port->xmit_buf[port->xmit_tail];
- port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_tail = (port->xmit_tail + 1)
+ & (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt--;
txcount--;
}
@@ -730,81 +509,82 @@ static void isicom_tx(unsigned long _data)
if (port->xmit_cnt <= WAKEUP_CHARS)
schedule_work(&port->bh_tqueue);
unlock_card(&isi_card[card]);
- }
+ }
+
+ /* schedule another tx for hopefully in about 10ms */
+sched_again:
+ if (!re_schedule) {
+ re_schedule = 2;
+ return;
+ }
- /* schedule another tx for hopefully in about 10ms */
-sched_again:
- if (!re_schedule)
- return;
init_timer(&tx);
tx.expires = jiffies + HZ/100;
tx.data = 0;
tx.function = isicom_tx;
add_timer(&tx);
-
- return;
-}
-
+
+ return;
+}
+
/* Interrupt handlers */
-
-static void isicom_bottomhalf(void * data)
+
+static void isicom_bottomhalf(void *data)
{
- struct isi_port * port = (struct isi_port *) data;
- struct tty_struct * tty = port->tty;
-
+ struct isi_port *port = (struct isi_port *) data;
+ struct tty_struct *tty = port->tty;
+
if (!tty)
return;
- tty_wakeup(tty);
+ tty_wakeup(tty);
wake_up_interruptible(&tty->write_wait);
-}
-
+}
+
/*
- * Main interrupt handler routine
+ * Main interrupt handler routine
*/
-
-static irqreturn_t isicom_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+
+static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct isi_board * card;
- struct isi_port * port;
- struct tty_struct * tty;
- unsigned short base, header, word_count, count;
- unsigned char channel;
+ struct isi_board *card = dev_id;
+ struct isi_port *port;
+ struct tty_struct *tty;
+ unsigned long base;
+ u16 header, word_count, count, channel;
short byte_count;
-
- card = (struct isi_board *) dev_id;
+ unsigned char *rp;
if (!card || !(card->status & FIRMWARE_LOADED))
return IRQ_NONE;
-
+
base = card->base;
spin_lock(&card->card_lock);
-
+
if (card->isa == NO) {
/*
- * disable any interrupts from the PCI card and lower the
- * interrupt line
+ * disable any interrupts from the PCI card and lower the
+ * interrupt line
*/
outw(0x8000, base+0x04);
ClearInterrupt(base);
}
-
+
inw(base); /* get the dummy word out */
header = inw(base);
channel = (header & 0x7800) >> card->shift_count;
byte_count = header & 0xff;
if (channel + 1 > card->port_count) {
- printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
- base, channel+1);
+ printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): "
+ "%d(channel) > port_count.\n", base, channel+1);
if (card->isa)
ClearInterrupt(base);
else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
spin_unlock(&card->card_lock);
- return IRQ_HANDLED;
+ return IRQ_HANDLED;
}
port = card->ports + channel;
if (!(port->flags & ASYNC_INITIALIZED)) {
@@ -813,8 +593,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
else
outw(0x0000, base+0x04); /* enable interrupts */
return IRQ_HANDLED;
- }
-
+ }
+
tty = port->tty;
if (tty == NULL) {
word_count = byte_count >> 1;
@@ -831,224 +611,204 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
spin_unlock(&card->card_lock);
return IRQ_HANDLED;
}
-
+
if (header & 0x8000) { /* Status Packet */
header = inw(base);
switch(header & 0xff) {
- case 0: /* Change in EIA signals */
-
- if (port->flags & ASYNC_CHECK_CD) {
- if (port->status & ISI_DCD) {
- if (!(header & ISI_DCD)) {
- /* Carrier has been lost */
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
-#endif
- port->status &= ~ISI_DCD;
- schedule_work(&port->hangup_tq);
- }
- }
- else {
- if (header & ISI_DCD) {
- /* Carrier has been detected */
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
-#endif
- port->status |= ISI_DCD;
- wake_up_interruptible(&port->open_wait);
- }
- }
- }
- else {
- if (header & ISI_DCD)
- port->status |= ISI_DCD;
- else
+ case 0: /* Change in EIA signals */
+ if (port->flags & ASYNC_CHECK_CD) {
+ if (port->status & ISI_DCD) {
+ if (!(header & ISI_DCD)) {
+ /* Carrier has been lost */
+ pr_dbg("interrupt: DCD->low.\n"
+ );
port->status &= ~ISI_DCD;
- }
-
- if (port->flags & ASYNC_CTS_FLOW) {
- if (port->tty->hw_stopped) {
- if (header & ISI_CTS) {
- port->tty->hw_stopped = 0;
- /* start tx ing */
- port->status |= (ISI_TXOK | ISI_CTS);
- schedule_work(&port->bh_tqueue);
- }
- }
- else {
- if (!(header & ISI_CTS)) {
- port->tty->hw_stopped = 1;
- /* stop tx ing */
- port->status &= ~(ISI_TXOK | ISI_CTS);
- }
+ schedule_work(&port->hangup_tq);
}
+ } else if (header & ISI_DCD) {
+ /* Carrier has been detected */
+ pr_dbg("interrupt: DCD->high.\n");
+ port->status |= ISI_DCD;
+ wake_up_interruptible(&port->open_wait);
}
- else {
- if (header & ISI_CTS)
- port->status |= ISI_CTS;
- else
- port->status &= ~ISI_CTS;
- }
-
- if (header & ISI_DSR)
- port->status |= ISI_DSR;
+ } else {
+ if (header & ISI_DCD)
+ port->status |= ISI_DCD;
else
- port->status &= ~ISI_DSR;
-
- if (header & ISI_RI)
- port->status |= ISI_RI;
+ port->status &= ~ISI_DCD;
+ }
+
+ if (port->flags & ASYNC_CTS_FLOW) {
+ if (port->tty->hw_stopped) {
+ if (header & ISI_CTS) {
+ port->tty->hw_stopped = 0;
+ /* start tx ing */
+ port->status |= (ISI_TXOK
+ | ISI_CTS);
+ schedule_work(&port->bh_tqueue);
+ }
+ } else if (!(header & ISI_CTS)) {
+ port->tty->hw_stopped = 1;
+ /* stop tx ing */
+ port->status &= ~(ISI_TXOK | ISI_CTS);
+ }
+ } else {
+ if (header & ISI_CTS)
+ port->status |= ISI_CTS;
else
- port->status &= ~ISI_RI;
-
- break;
-
- case 1: /* Received Break !!! */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
- tty->flip.count++;
- if (port->flags & ASYNC_SAK)
- do_SAK(tty);
- schedule_delayed_work(&tty->flip.work, 1);
- break;
-
- case 2: /* Statistics */
- printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");
- break;
-
- default:
- printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
- break;
- }
- }
- else { /* Data Packet */
- count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n",
- count, byte_count);
-#endif
+ port->status &= ~ISI_CTS;
+ }
+
+ if (header & ISI_DSR)
+ port->status |= ISI_DSR;
+ else
+ port->status &= ~ISI_DSR;
+
+ if (header & ISI_RI)
+ port->status |= ISI_RI;
+ else
+ port->status &= ~ISI_RI;
+
+ break;
+
+ case 1: /* Received Break !!! */
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
+ if (port->flags & ASYNC_SAK)
+ do_SAK(tty);
+ tty_flip_buffer_push(tty);
+ break;
+
+ case 2: /* Statistics */
+ pr_dbg("isicom_interrupt: stats!!!.\n");
+ break;
+
+ default:
+ pr_dbg("Intr: Unknown code in status packet.\n");
+ break;
+ }
+ } else { /* Data Packet */
+
+ count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
+ pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count);
word_count = count >> 1;
- insw(base, tty->flip.char_buf_ptr, word_count);
- tty->flip.char_buf_ptr += (word_count << 1);
+ insw(base, rp, word_count);
byte_count -= (word_count << 1);
if (count & 0x0001) {
- *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+ tty_insert_flip_char(tty, inw(base) & 0xff,
+ TTY_NORMAL);
byte_count -= 2;
- }
- memset(tty->flip.flag_buf_ptr, 0, count);
- tty->flip.flag_buf_ptr += count;
- tty->flip.count += count;
-
+ }
if (byte_count > 0) {
- printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
- base, channel+1);
+ pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
+ "bytes...\n", base, channel + 1);
while(byte_count > 0) { /* drain out unread xtra data */
inw(base);
byte_count -= 2;
}
}
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
if (card->isa == YES)
ClearInterrupt(base);
else
- outw(0x0000, base+0x04); /* enable interrupts */
+ outw(0x0000, base+0x04); /* enable interrupts */
+
return IRQ_HANDLED;
-}
+}
-static void isicom_config_port(struct isi_port * port)
+static void isicom_config_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
- struct tty_struct * tty;
+ struct isi_board *card = port->card;
+ struct tty_struct *tty;
unsigned long baud;
- unsigned short channel_setup, base = card->base;
- unsigned short channel = port->channel, shift_count = card->shift_count;
+ unsigned long base = card->base;
+ u16 channel_setup, channel = port->channel,
+ shift_count = card->shift_count;
unsigned char flow_ctrl;
-
+
if (!(tty = port->tty) || !tty->termios)
return;
baud = C_BAUD(tty);
if (baud & CBAUDEX) {
baud &= ~CBAUDEX;
-
+
/* if CBAUDEX bit is on and the baud is set to either 50 or 75
* then the card is programmed for 57.6Kbps or 115Kbps
* respectively.
- */
-
+ */
+
if (baud < 1 || baud > 2)
port->tty->termios->c_cflag &= ~CBAUDEX;
else
baud += 15;
- }
+ }
if (baud == 15) {
-
- /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
+
+ /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
* by the set_serial_info ioctl ... this is done by
* the 'setserial' utility.
- */
-
+ */
+
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- baud++; /* 57.6 Kbps */
+ baud++; /* 57.6 Kbps */
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- baud +=2; /* 115 Kbps */
+ baud +=2; /* 115 Kbps */
}
if (linuxb_to_isib[baud] == -1) {
/* hang up */
- drop_dtr(port);
- return;
- }
- else
+ drop_dtr(port);
+ return;
+ }
+ else
raise_dtr(port);
-
+
if (lock_card(card)) {
outw(0x8000 | (channel << shift_count) |0x03, base);
outw(linuxb_to_isib[baud] << 8 | 0x03, base);
channel_setup = 0;
switch(C_CSIZE(tty)) {
- case CS5:
- channel_setup |= ISICOM_CS5;
- break;
- case CS6:
- channel_setup |= ISICOM_CS6;
- break;
- case CS7:
- channel_setup |= ISICOM_CS7;
- break;
- case CS8:
- channel_setup |= ISICOM_CS8;
- break;
+ case CS5:
+ channel_setup |= ISICOM_CS5;
+ break;
+ case CS6:
+ channel_setup |= ISICOM_CS6;
+ break;
+ case CS7:
+ channel_setup |= ISICOM_CS7;
+ break;
+ case CS8:
+ channel_setup |= ISICOM_CS8;
+ break;
}
-
+
if (C_CSTOPB(tty))
channel_setup |= ISICOM_2SB;
if (C_PARENB(tty)) {
channel_setup |= ISICOM_EVPAR;
if (C_PARODD(tty))
- channel_setup |= ISICOM_ODPAR;
+ channel_setup |= ISICOM_ODPAR;
}
- outw(channel_setup, base);
+ outw(channel_setup, base);
InterruptTheCard(base);
- unlock_card(card);
- }
+ unlock_card(card);
+ }
if (C_CLOCAL(tty))
port->flags &= ~ASYNC_CHECK_CD;
else
- port->flags |= ASYNC_CHECK_CD;
-
+ port->flags |= ASYNC_CHECK_CD;
+
/* flow control settings ...*/
flow_ctrl = 0;
port->flags &= ~ASYNC_CTS_FLOW;
if (C_CRTSCTS(tty)) {
port->flags |= ASYNC_CTS_FLOW;
flow_ctrl |= ISICOM_CTSRTS;
- }
- if (I_IXON(tty))
+ }
+ if (I_IXON(tty))
flow_ctrl |= ISICOM_RESPOND_XONXOFF;
if (I_IXOFF(tty))
- flow_ctrl |= ISICOM_INITIATE_XONXOFF;
-
+ flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
if (lock_card(card)) {
outw(0x8000 | (channel << shift_count) |0x04, base);
outw(flow_ctrl << 8 | 0x05, base);
@@ -1056,22 +816,22 @@ static void isicom_config_port(struct isi_port * port)
InterruptTheCard(base);
unlock_card(card);
}
-
+
/* rx enabled -> enable port for rx on the card */
if (C_CREAD(tty)) {
card->port_status |= (1 << channel);
outw(card->port_status, base + 0x02);
}
}
-
-/* open et all */
-static inline void isicom_setup_board(struct isi_board * bp)
+/* open et all */
+
+static inline void isicom_setup_board(struct isi_board *bp)
{
int channel;
- struct isi_port * port;
+ struct isi_port *port;
unsigned long flags;
-
+
spin_lock_irqsave(&bp->card_lock, flags);
if (bp->status & BOARD_ACTIVE) {
spin_unlock_irqrestore(&bp->card_lock, flags);
@@ -1080,53 +840,54 @@ static inline void isicom_setup_board(struct isi_board * bp)
port = bp->ports;
bp->status |= BOARD_ACTIVE;
spin_unlock_irqrestore(&bp->card_lock, flags);
- for(channel = 0; channel < bp->port_count; channel++, port++)
+ for (channel = 0; channel < bp->port_count; channel++, port++)
drop_dtr_rts(port);
return;
}
-
-static int isicom_setup_port(struct isi_port * port)
+
+static int isicom_setup_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (port->flags & ASYNC_INITIALIZED) {
return 0;
}
if (!port->xmit_buf) {
unsigned long page;
-
+
if (!(page = get_zeroed_page(GFP_KERNEL)))
return -ENOMEM;
-
+
if (port->xmit_buf) {
free_page(page);
return -ERESTARTSYS;
}
- port->xmit_buf = (unsigned char *) page;
- }
+ port->xmit_buf = (unsigned char *) page;
+ }
spin_lock_irqsave(&card->card_lock, flags);
if (port->tty)
clear_bit(TTY_IO_ERROR, &port->tty->flags);
if (port->count == 1)
card->count++;
-
+
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
+
/* discard any residual data */
kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
-
+
isicom_config_port(port);
port->flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&card->card_lock, flags);
-
- return 0;
-}
-
-static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port)
+
+ return 0;
+}
+
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct isi_port *port)
{
- struct isi_board * card = port->card;
+ struct isi_board *card = port->card;
int do_clocal = 0, retval;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
@@ -1134,30 +895,27 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
-#endif
+ pr_dbg("block_til_ready: close in progress.\n");
interruptible_sleep_on(&port->close_wait);
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
}
-
+
/* if non-blocking mode is set ... */
-
- if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
-#endif
+
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ pr_dbg("block_til_ready: non-block mode.\n");
port->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
+ return 0;
+ }
+
if (C_CLOCAL(tty))
do_clocal = 1;
-
- /* block waiting for DCD to be asserted, and while
+
+ /* block waiting for DCD to be asserted, and while
callout dev is busy */
retval = 0;
add_wait_queue(&port->open_wait, &wait);
@@ -1167,27 +925,27 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
port->count--;
port->blocked_open++;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
while (1) {
raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
- }
+ }
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || (port->status & ISI_DCD))) {
+ (do_clocal || (port->status & ISI_DCD))) {
break;
- }
+ }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
- schedule();
+ schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&port->open_wait, &wait);
@@ -1201,11 +959,11 @@ static int block_til_ready(struct tty_struct * tty, struct file * filp, struct i
port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
-
-static int isicom_open(struct tty_struct * tty, struct file * filp)
+
+static int isicom_open(struct tty_struct *tty, struct file *filp)
{
- struct isi_port * port;
- struct isi_board * card;
+ struct isi_port *port;
+ struct isi_board *card;
unsigned int line, board;
int error;
@@ -1214,20 +972,20 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
return -ENODEV;
board = BOARD(line);
card = &isi_card[board];
-
+
if (!(card->status & FIRMWARE_LOADED))
return -ENODEV;
-
+
/* open on a port greater than the port count for the card !!! */
if (line > ((board * 16) + card->port_count - 1))
return -ENODEV;
- port = &isi_ports[line];
+ port = &isi_ports[line];
if (isicom_paranoia_check(port, tty->name, "isicom_open"))
return -ENODEV;
-
- isicom_setup_board(card);
-
+
+ isicom_setup_board(card);
+
port->count++;
tty->driver_data = port;
port->tty = tty;
@@ -1236,12 +994,12 @@ static int isicom_open(struct tty_struct * tty, struct file * filp)
if ((error = block_til_ready(tty, filp, port))!=0)
return error;
- return 0;
+ return 0;
}
-
+
/* close et all */
-static inline void isicom_shutdown_board(struct isi_board * bp)
+static inline void isicom_shutdown_board(struct isi_board *bp)
{
unsigned long flags;
@@ -1252,15 +1010,15 @@ static inline void isicom_shutdown_board(struct isi_board * bp)
spin_unlock_irqrestore(&bp->card_lock, flags);
}
-static void isicom_shutdown_port(struct isi_port * port)
+static void isicom_shutdown_port(struct isi_port *port)
{
- struct isi_board * card = port->card;
- struct tty_struct * tty;
+ struct isi_board *card = port->card;
+ struct tty_struct *tty;
unsigned long flags;
-
+
tty = port->tty;
- spin_lock_irqsave(&card->card_lock, flags);
+ spin_lock_irqsave(&card->card_lock, flags);
if (!(port->flags & ASYNC_INITIALIZED)) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
@@ -1268,93 +1026,91 @@ static void isicom_shutdown_port(struct isi_port * port)
if (port->xmit_buf) {
free_page((unsigned long) port->xmit_buf);
port->xmit_buf = NULL;
- }
+ }
port->flags &= ~ASYNC_INITIALIZED;
/* 3rd October 2000 : Vinayak P Risbud */
port->tty = NULL;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
/*Fix done by Anil .S on 30-04-2001
remote login through isi port has dtr toggle problem
due to which the carrier drops before the password prompt
- appears on the remote end. Now we drop the dtr only if the
+ appears on the remote end. Now we drop the dtr only if the
HUPCL(Hangup on close) flag is set for the tty*/
-
- if (C_HUPCL(tty))
+
+ if (C_HUPCL(tty))
/* drop dtr on this port */
drop_dtr(port);
-
- /* any other port uninits */
+
+ /* any other port uninits */
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
-
+
if (--card->count < 0) {
- printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+ pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n",
card->base, card->count);
- card->count = 0;
+ card->count = 0;
}
-
- /* last port was closed , shutdown that boad too */
- if(C_HUPCL(tty)) {
+
+ /* last port was closed, shutdown that boad too */
+ if (C_HUPCL(tty)) {
if (!card->count)
isicom_shutdown_board(card);
}
}
-static void isicom_close(struct tty_struct * tty, struct file * filp)
+static void isicom_close(struct tty_struct *tty, struct file *filp)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (!port)
return;
if (isicom_paranoia_check(port, tty->name, "isicom_close"))
return;
-
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
-#endif
-
+
+ pr_dbg("Close start!!!.\n");
+
spin_lock_irqsave(&card->card_lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
-
+
if (tty->count == 1 && port->count != 1) {
- printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
- "tty->count = 1 port count = %d.\n",
+ printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+ "count tty->count = 1 port count = %d.\n",
card->base, port->count);
port->count = 1;
}
if (--port->count < 0) {
- printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
- "channel%d = %d", card->base, port->channel,
+ printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
+ "count for channel%d = %d", card->base, port->channel,
port->count);
- port->count = 0;
+ port->count = 0;
}
-
+
if (port->count) {
spin_unlock_irqrestore(&card->card_lock, flags);
return;
- }
+ }
port->flags |= ASYNC_CLOSING;
tty->closing = 1;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
- /* indicate to the card that no more data can be received
+ /* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
- if (port->flags & ASYNC_INITIALIZED) {
+ if (port->flags & ASYNC_INITIALIZED) {
card->port_status &= ~(1 << port->channel);
outw(card->port_status, card->base + 0x02);
- }
+ }
isicom_shutdown_port(port);
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
@@ -1365,65 +1121,65 @@ static void isicom_close(struct tty_struct * tty, struct file * filp)
if (port->blocked_open) {
spin_unlock_irqrestore(&card->card_lock, flags);
if (port->close_delay) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
-#endif
- msleep_interruptible(jiffies_to_msecs(port->close_delay));
+ pr_dbg("scheduling until time out.\n");
+ msleep_interruptible(
+ jiffies_to_msecs(port->close_delay));
}
spin_lock_irqsave(&card->card_lock, flags);
wake_up_interruptible(&port->open_wait);
- }
+ }
port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
wake_up_interruptible(&port->close_wait);
spin_unlock_irqrestore(&card->card_lock, flags);
}
/* write et all */
-static int isicom_write(struct tty_struct * tty,
- const unsigned char * buf, int count)
+static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
+ int count)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
int cnt, total = 0;
if (isicom_paranoia_check(port, tty->name, "isicom_write"))
return 0;
-
- if (!tty || !port->xmit_buf || !tmp_buf)
+
+ if (!tty || !port->xmit_buf)
return 0;
-
+
spin_lock_irqsave(&card->card_lock, flags);
-
- while(1) {
- cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - port->xmit_head));
- if (cnt <= 0)
+
+ while(1) {
+ cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
+ - 1, SERIAL_XMIT_SIZE - port->xmit_head));
+ if (cnt <= 0)
break;
-
+
memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
- port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
+ - 1);
port->xmit_cnt += cnt;
buf += cnt;
count -= cnt;
total += cnt;
- }
+ }
if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
port->status |= ISI_TXOK;
spin_unlock_irqrestore(&card->card_lock, flags);
- return total;
+ return total;
}
/* put_char et all */
-static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
return;
-
+
if (!tty || !port->xmit_buf)
return;
@@ -1432,7 +1188,7 @@ static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
spin_unlock_irqrestore(&card->card_lock, flags);
return;
}
-
+
port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt++;
@@ -1440,30 +1196,31 @@ static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
}
/* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct * tty)
+static void isicom_flush_chars(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
return;
-
- if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !port->xmit_buf)
+
+ if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !port->xmit_buf)
return;
-
+
/* this tells the transmitter to consider this port for
data output to the card ... that's the best we can do. */
- port->status |= ISI_TXOK;
+ port->status |= ISI_TXOK;
}
/* write_room et all */
-static int isicom_write_room(struct tty_struct * tty)
+static int isicom_write_room(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
int free;
if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
return 0;
-
+
free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
if (free < 0)
free = 0;
@@ -1471,23 +1228,24 @@ static int isicom_write_room(struct tty_struct * tty)
}
/* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct * tty)
+static int isicom_chars_in_buffer(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
return 0;
return port->xmit_cnt;
}
/* ioctl et all */
-static inline void isicom_send_break(struct isi_port * port, unsigned long length)
+static inline void isicom_send_break(struct isi_port *port,
+ unsigned long length)
{
- struct isi_board * card = port->card;
- unsigned short base = card->base;
-
- if(!lock_card(card))
+ struct isi_board *card = port->card;
+ unsigned long base = card->base;
+
+ if (!lock_card(card))
return;
-
+
outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
outw((length & 0xff) << 8 | 0x00, base);
outw((length & 0xff00), base);
@@ -1498,13 +1256,13 @@ static inline void isicom_send_break(struct isi_port * port, unsigned long lengt
static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
/* just send the port status */
- unsigned short status = port->status;
+ u16 status = port->status;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
-
+
return ((status & ISI_RTS) ? TIOCM_RTS : 0) |
((status & ISI_DTR) ? TIOCM_DTR : 0) |
((status & ISI_DCD) ? TIOCM_CAR : 0) |
@@ -1514,13 +1272,13 @@ static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
}
static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
- unsigned int set, unsigned int clear)
+ unsigned int set, unsigned int clear)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
-
+
if (set & TIOCM_RTS)
raise_rts(port);
if (set & TIOCM_DTR)
@@ -1532,46 +1290,46 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
drop_dtr(port);
return 0;
-}
+}
-static int isicom_set_serial_info(struct isi_port * port,
- struct serial_struct __user *info)
+static int isicom_set_serial_info(struct isi_port *port,
+ struct serial_struct __user *info)
{
struct serial_struct newinfo;
int reconfig_port;
- if(copy_from_user(&newinfo, info, sizeof(newinfo)))
+ if (copy_from_user(&newinfo, info, sizeof(newinfo)))
return -EFAULT;
-
- reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
- (newinfo.flags & ASYNC_SPD_MASK));
-
+
+ reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
+ (newinfo.flags & ASYNC_SPD_MASK));
+
if (!capable(CAP_SYS_ADMIN)) {
if ((newinfo.close_delay != port->close_delay) ||
- (newinfo.closing_wait != port->closing_wait) ||
- ((newinfo.flags & ~ASYNC_USR_MASK) !=
- (port->flags & ~ASYNC_USR_MASK)))
+ (newinfo.closing_wait != port->closing_wait) ||
+ ((newinfo.flags & ~ASYNC_USR_MASK) !=
+ (port->flags & ~ASYNC_USR_MASK)))
return -EPERM;
port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
(newinfo.flags & ASYNC_USR_MASK));
- }
+ }
else {
port->close_delay = newinfo.close_delay;
- port->closing_wait = newinfo.closing_wait;
- port->flags = ((port->flags & ~ASYNC_FLAGS) |
+ port->closing_wait = newinfo.closing_wait;
+ port->flags = ((port->flags & ~ASYNC_FLAGS) |
(newinfo.flags & ASYNC_FLAGS));
}
if (reconfig_port) {
isicom_config_port(port);
}
- return 0;
-}
+ return 0;
+}
-static int isicom_get_serial_info(struct isi_port * port,
- struct serial_struct __user *info)
+static int isicom_get_serial_info(struct isi_port *port,
+ struct serial_struct __user *info)
{
struct serial_struct out_info;
-
+
memset(&out_info, 0, sizeof(out_info));
/* out_info.type = ? */
out_info.line = port - isi_ports;
@@ -1581,15 +1339,15 @@ static int isicom_get_serial_info(struct isi_port * port,
/* out_info.baud_base = ? */
out_info.close_delay = port->close_delay;
out_info.closing_wait = port->closing_wait;
- if(copy_to_user(info, &out_info, sizeof(out_info)))
+ if (copy_to_user(info, &out_info, sizeof(out_info)))
return -EFAULT;
return 0;
-}
+}
-static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
+ unsigned int cmd, unsigned long arg)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
int retval;
@@ -1597,139 +1355,141 @@ static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
return -ENODEV;
switch(cmd) {
- case TCSBRK:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- if (!arg)
- isicom_send_break(port, HZ/4);
- return 0;
-
- case TCSBRKP:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
- tty_wait_until_sent(tty, 0);
- isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
- return 0;
-
- case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-
- case TIOCSSOFTCAR:
- if(get_user(arg, (unsigned long __user *) argp))
- return -EFAULT;
- tty->termios->c_cflag =
- ((tty->termios->c_cflag & ~CLOCAL) |
- (arg ? CLOCAL : 0));
- return 0;
-
- case TIOCGSERIAL:
- return isicom_get_serial_info(port, argp);
-
- case TIOCSSERIAL:
- return isicom_set_serial_info(port, argp);
-
- default:
- return -ENOIOCTLCMD;
+ case TCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ isicom_send_break(port, HZ/4);
+ return 0;
+
+ case TCSBRKP:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+ return 0;
+
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0,
+ (unsigned long __user *)argp);
+
+ case TIOCSSOFTCAR:
+ if (get_user(arg, (unsigned long __user *) argp))
+ return -EFAULT;
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+
+ case TIOCGSERIAL:
+ return isicom_get_serial_info(port, argp);
+
+ case TIOCSSERIAL:
+ return isicom_set_serial_info(port, argp);
+
+ default:
+ return -ENOIOCTLCMD;
}
return 0;
}
/* set_termios et all */
-static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+static void isicom_set_termios(struct tty_struct *tty,
+ struct termios *old_termios)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
return;
-
+
if (tty->termios->c_cflag == old_termios->c_cflag &&
- tty->termios->c_iflag == old_termios->c_iflag)
+ tty->termios->c_iflag == old_termios->c_iflag)
return;
-
+
isicom_config_port(port);
-
+
if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
+ !(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
- isicom_start(tty);
- }
+ isicom_start(tty);
+ }
}
/* throttle et all */
-static void isicom_throttle(struct tty_struct * tty)
+static void isicom_throttle(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
-
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
+
if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
return;
-
+
/* tell the card that this port cannot handle any more data for now */
card->port_status &= ~(1 << port->channel);
outw(card->port_status, card->base + 0x02);
}
/* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct * tty)
+static void isicom_unthrottle(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
-
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
+
if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
return;
-
+
/* tell the card that this port is ready to accept more data */
card->port_status |= (1 << port->channel);
outw(card->port_status, card->base + 0x02);
}
/* stop et all */
-static void isicom_stop(struct tty_struct * tty)
+static void isicom_stop(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_port *port = tty->driver_data;
if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
return;
-
+
/* this tells the transmitter not to consider this port for
data output to the card. */
port->status &= ~ISI_TXOK;
}
/* start et all */
-static void isicom_start(struct tty_struct * tty)
+static void isicom_start(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_start"))
return;
-
+
/* this tells the transmitter to consider this port for
data output to the card. */
port->status |= ISI_TXOK;
}
/* hangup et all */
-static void do_isicom_hangup(void * data)
+static void do_isicom_hangup(void *data)
{
- struct isi_port * port = (struct isi_port *) data;
- struct tty_struct * tty;
-
+ struct isi_port *port = data;
+ struct tty_struct *tty;
+
tty = port->tty;
if (tty)
tty_hangup(tty);
}
-static void isicom_hangup(struct tty_struct * tty)
+static void isicom_hangup(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
-
+ struct isi_port *port = tty->driver_data;
+
if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
return;
-
+
isicom_shutdown_port(port);
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
@@ -1738,342 +1498,540 @@ static void isicom_hangup(struct tty_struct * tty)
}
/* flush_buffer et all */
-static void isicom_flush_buffer(struct tty_struct * tty)
+static void isicom_flush_buffer(struct tty_struct *tty)
{
- struct isi_port * port = (struct isi_port *) tty->driver_data;
- struct isi_board * card = port->card;
+ struct isi_port *port = tty->driver_data;
+ struct isi_board *card = port->card;
unsigned long flags;
-
+
if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
return;
-
+
spin_lock_irqsave(&card->card_lock, flags);
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
spin_unlock_irqrestore(&card->card_lock, flags);
-
+
wake_up_interruptible(&tty->write_wait);
tty_wakeup(tty);
}
+/*
+ * Driver init and deinit functions
+ */
-static int __devinit register_ioregion(void)
+static int __devinit isicom_register_ioregion(struct pci_dev *pdev,
+ const unsigned int index)
{
- int count, done=0;
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base)
- if (!request_region(isi_card[count].base,16,ISICOM_NAME)) {
- printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
- isi_card[count].base,isi_card[count].base+15,count+1);
- isi_card[count].base=0;
- done++;
- }
- }
- return done;
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ if (!board->base)
+ return -EINVAL;
+
+ if (!request_region(board->base, 16, ISICOM_NAME)) {
+ dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+ "will be disabled.\n", board->base, board->base + 15,
+ index + 1);
+ return -EBUSY;
+ }
+
+ return 0;
}
-static void unregister_ioregion(void)
+static void isicom_unregister_ioregion(struct pci_dev *pdev)
{
- int count;
- for (count=0; count < BOARD_COUNT; count++ )
- if (isi_card[count].base) {
- release_region(isi_card[count].base,16);
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
-#endif
- }
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ if (!board->base)
+ return;
+
+ release_region(board->base, 16);
+ dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n",
+ board->base, board->base + 15);
+ board->base = 0;
}
static struct tty_operations isicom_ops = {
- .open = isicom_open,
- .close = isicom_close,
- .write = isicom_write,
- .put_char = isicom_put_char,
- .flush_chars = isicom_flush_chars,
- .write_room = isicom_write_room,
+ .open = isicom_open,
+ .close = isicom_close,
+ .write = isicom_write,
+ .put_char = isicom_put_char,
+ .flush_chars = isicom_flush_chars,
+ .write_room = isicom_write_room,
.chars_in_buffer = isicom_chars_in_buffer,
- .ioctl = isicom_ioctl,
- .set_termios = isicom_set_termios,
- .throttle = isicom_throttle,
- .unthrottle = isicom_unthrottle,
- .stop = isicom_stop,
- .start = isicom_start,
- .hangup = isicom_hangup,
- .flush_buffer = isicom_flush_buffer,
- .tiocmget = isicom_tiocmget,
- .tiocmset = isicom_tiocmset,
+ .ioctl = isicom_ioctl,
+ .set_termios = isicom_set_termios,
+ .throttle = isicom_throttle,
+ .unthrottle = isicom_unthrottle,
+ .stop = isicom_stop,
+ .start = isicom_start,
+ .hangup = isicom_hangup,
+ .flush_buffer = isicom_flush_buffer,
+ .tiocmget = isicom_tiocmget,
+ .tiocmset = isicom_tiocmset,
};
-static int __devinit register_drivers(void)
+static int __devinit isicom_register_tty_driver(void)
{
- int error;
+ int error = -ENOMEM;
/* tty driver structure initialization */
isicom_normal = alloc_tty_driver(PORT_COUNT);
if (!isicom_normal)
- return -ENOMEM;
-
- isicom_normal->owner = THIS_MODULE;
- isicom_normal->name = "ttyM";
- isicom_normal->devfs_name = "isicom/";
- isicom_normal->major = ISICOM_NMAJOR;
- isicom_normal->minor_start = 0;
- isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
- isicom_normal->subtype = SERIAL_TYPE_NORMAL;
- isicom_normal->init_termios = tty_std_termios;
- isicom_normal->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL |CLOCAL;
- isicom_normal->flags = TTY_DRIVER_REAL_RAW;
+ goto end;
+
+ isicom_normal->owner = THIS_MODULE;
+ isicom_normal->name = "ttyM";
+ isicom_normal->devfs_name = "isicom/";
+ isicom_normal->major = ISICOM_NMAJOR;
+ isicom_normal->minor_start = 0;
+ isicom_normal->type = TTY_DRIVER_TYPE_SERIAL;
+ isicom_normal->subtype = SERIAL_TYPE_NORMAL;
+ isicom_normal->init_termios = tty_std_termios;
+ isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
+ CLOCAL;
+ isicom_normal->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(isicom_normal, &isicom_ops);
-
- if ((error=tty_register_driver(isicom_normal))!=0) {
- printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+
+ if ((error = tty_register_driver(isicom_normal))) {
+ pr_dbg("Couldn't register the dialin driver, error=%d\n",
error);
put_tty_driver(isicom_normal);
- return error;
}
- return 0;
+end:
+ return error;
}
-static void unregister_drivers(void)
+static void isicom_unregister_tty_driver(void)
{
- int error = tty_unregister_driver(isicom_normal);
- if (error)
- printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+ int error;
+
+ if ((error = tty_unregister_driver(isicom_normal)))
+ pr_dbg("couldn't unregister normal driver, error=%d.\n", error);
+
put_tty_driver(isicom_normal);
}
-static int __devinit register_isr(void)
+static int __devinit isicom_register_isr(struct pci_dev *pdev,
+ const unsigned int index)
{
- int count, done=0;
- unsigned long irqflags;
-
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base) {
- irqflags = (isi_card[count].isa == YES) ?
- SA_INTERRUPT :
- (SA_INTERRUPT | SA_SHIRQ);
-
- if (request_irq(isi_card[count].irq,
- isicom_interrupt,
- irqflags,
- ISICOM_NAME, &isi_card[count])) {
-
- printk(KERN_WARNING "ISICOM: Could not"
- " install handler at Irq %d."
- " Card%d will be disabled.\n",
- isi_card[count].irq, count+1);
-
- release_region(isi_card[count].base,16);
- isi_card[count].base=0;
- }
- else
- done++;
- }
- }
- return done;
+ struct isi_board *board = pci_get_drvdata(pdev);
+ unsigned long irqflags = SA_INTERRUPT;
+ int retval = -EINVAL;
+
+ if (!board->base)
+ goto end;
+
+ if (board->isa == NO)
+ irqflags |= SA_SHIRQ;
+
+ retval = request_irq(board->irq, isicom_interrupt, irqflags,
+ ISICOM_NAME, board);
+ if (retval < 0)
+ dev_warn(&pdev->dev, "Could not install handler at Irq %d. "
+ "Card%d will be disabled.\n", board->irq, index + 1);
+ else
+ retval = 0;
+end:
+ return retval;
}
-static void __exit unregister_isr(void)
+static int __devinit reset_card(struct pci_dev *pdev,
+ const unsigned int card, unsigned int *signature)
{
- int count;
+ struct isi_board *board = pci_get_drvdata(pdev);
+ unsigned long base = board->base;
+ unsigned int portcount = 0;
+ int retval = 0;
+
+ dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
+ base);
- for (count=0; count < BOARD_COUNT; count++ ) {
- if (isi_card[count].base)
- free_irq(isi_card[count].irq, &isi_card[count]);
+ inw(base + 0x8);
+
+ mdelay(10);
+
+ outw(0, base + 0x8); /* Reset */
+
+ msleep(3000);
+
+ *signature = inw(base + 0x4) & 0xff;
+
+ if (board->isa == YES) {
+ if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) {
+ dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+ inw(base + 0x2), inw(base + 0xe));
+ dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure "
+ "(Possible bad I/O Port Address 0x%lx).\n",
+ card + 1, base);
+ retval = -EIO;
+ goto end;
+ }
+ } else {
+ portcount = inw(base + 0x2);
+ if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) &&
+ (portcount != 4) && (portcount != 8))) {
+ dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n",
+ inw(base + 0x2), inw(base + 0xe));
+ dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure "
+ "(Possible bad I/O Port Address 0x%lx).\n",
+ card + 1, base);
+ retval = -EIO;
+ goto end;
+ }
}
+
+ switch (*signature) {
+ case 0xa5:
+ case 0xbb:
+ case 0xdd:
+ board->port_count = (board->isa == NO && portcount == 4) ? 4 :
+ 8;
+ board->shift_count = 12;
+ break;
+ case 0xcc:
+ board->port_count = 16;
+ board->shift_count = 11;
+ break;
+ default:
+ dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible "
+ "bad I/O Port Address 0x%lx).\n", card + 1, base);
+ dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature);
+ retval = -EIO;
+ }
+ dev_info(&pdev->dev, "-Done\n");
+
+end:
+ return retval;
}
-static int __devinit isicom_init(void)
+static inline int WaitTillCardIsFree(u16 base)
{
- int card, channel, base;
- struct isi_port * port;
- unsigned long page;
-
- if (!tmp_buf) {
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
-#ifdef ISICOM_DEBUG
- printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
-#else
- printk(KERN_ERR "ISICOM: Not enough memory...\n");
-#endif
- return 0;
- }
- tmp_buf = (unsigned char *) page;
- }
-
- if (!register_ioregion())
- {
- printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
- free_page((unsigned long)tmp_buf);
- return 0;
- }
- if (register_drivers())
- {
- unregister_ioregion();
- free_page((unsigned long)tmp_buf);
- return 0;
- }
- if (!register_isr())
- {
- unregister_drivers();
- /* ioports already uregistered in register_isr */
- free_page((unsigned long)tmp_buf);
- return 0;
+ unsigned long count = 0;
+
+ while (!(inw(base + 0xe) & 0x1) && count++ < 100)
+ msleep(5);
+
+ return !(inw(base + 0xe) & 0x1);
+}
+
+static int __devinit load_firmware(struct pci_dev *pdev,
+ const unsigned int index, const unsigned int signature)
+{
+ struct isi_board *board = pci_get_drvdata(pdev);
+ const struct firmware *fw;
+ unsigned long base = board->base;
+ unsigned int a;
+ u16 word_count, status;
+ int retval = -EIO;
+ char *name;
+ u8 *data;
+
+ struct stframe {
+ u16 addr;
+ u16 count;
+ u8 data[0];
+ } *frame;
+
+ switch (signature) {
+ case 0xa5:
+ name = "isi608.bin";
+ break;
+ case 0xbb:
+ name = "isi608em.bin";
+ break;
+ case 0xcc:
+ name = "isi616em.bin";
+ break;
+ case 0xdd:
+ name = "isi4608.bin";
+ break;
+ case 0xee:
+ name = "isi4616.bin";
+ break;
+ default:
+ dev_err(&pdev->dev, "Unknown signature.\n");
+ goto end;
+ }
+
+ retval = request_firmware(&fw, name, &pdev->dev);
+ if (retval)
+ goto end;
+
+ for (frame = (struct stframe *)fw->data;
+ frame < (struct stframe *)(fw->data + fw->size);
+ frame++) {
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf0, base); /* start upload sequence */
+ outw(0x00, base);
+ outw(frame->addr, base); /* lsb of address */
+
+ word_count = frame->count / 2 + frame->count % 2;
+ outw(word_count, base);
+ InterruptTheCard(base);
+
+ udelay(100); /* 0x2f */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected load header:\n"
+ "Address:0x%x\nCount:0x%x\nStatus:0x%x\n",
+ index + 1, frame->addr, frame->count, status);
+ goto errrelfw;
+ }
+ outsw(base, frame->data, word_count);
+
+ InterruptTheCard(base);
+
+ udelay(50); /* 0x0f */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_err(&pdev->dev, "Card%d got out of sync.Card "
+ "Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+ }
+ }
+
+ retval = -EIO;
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf2, base);
+ outw(0x800, base);
+ outw(0x0, base);
+ outw(0x0, base);
+ InterruptTheCard(base);
+ outw(0x0, base + 0x4); /* for ISI4608 cards */
+
+/* XXX: should we test it by reading it back and comparing with original like
+ * in load firmware package? */
+ for (frame = (struct stframe*)fw->data;
+ frame < (struct stframe*)(fw->data + fw->size);
+ frame++) {
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ outw(0xf1, base); /* start download sequence */
+ outw(0x00, base);
+ outw(frame->addr, base); /* lsb of address */
+
+ word_count = (frame->count >> 1) + frame->count % 2;
+ outw(word_count + 1, base);
+ InterruptTheCard(base);
+
+ udelay(50); /* 0xf */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
+ "Address:0x%x\nCount:0x%x\nStatus: 0x%x\n",
+ index + 1, frame->addr, frame->count, status);
+ goto errrelfw;
+ }
+
+ data = kmalloc(word_count * 2, GFP_KERNEL);
+ inw(base);
+ insw(base, data, word_count);
+ InterruptTheCard(base);
+
+ for (a = 0; a < frame->count; a++)
+ if (data[a] != frame->data[a]) {
+ kfree(data);
+ dev_err(&pdev->dev, "Card%d, firmware upload "
+ "failed\n", index + 1);
+ goto errrelfw;
+ }
+ kfree(data);
+
+ udelay(50); /* 0xf */
+
+ if (WaitTillCardIsFree(base))
+ goto errrelfw;
+
+ if ((status = inw(base + 0x4)) != 0) {
+ dev_err(&pdev->dev, "Card%d verify got out of sync. "
+ "Card Status:0x%x\n", index + 1, status);
+ goto errrelfw;
+ }
}
-
- memset(isi_ports, 0, sizeof(isi_ports));
- for (card = 0; card < BOARD_COUNT; card++) {
- port = &isi_ports[card * 16];
- isi_card[card].ports = port;
- spin_lock_init(&isi_card[card].card_lock);
- base = isi_card[card].base;
- for (channel = 0; channel < 16; channel++, port++) {
- port->magic = ISICOM_MAGIC;
- port->card = &isi_card[card];
- port->channel = channel;
- port->close_delay = 50 * HZ/100;
- port->closing_wait = 3000 * HZ/100;
- INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
- INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
- port->status = 0;
- init_waitqueue_head(&port->open_wait);
- init_waitqueue_head(&port->close_wait);
- /* . . . */
- }
- }
-
- return 1;
+
+ board->status |= FIRMWARE_LOADED;
+ retval = 0;
+
+errrelfw:
+ release_firmware(fw);
+end:
+ return retval;
}
/*
* Insmod can set static symbols so keep these static
*/
-
static int io[4];
static int irq[4];
+static int card;
-MODULE_AUTHOR("MultiTech");
-MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
-MODULE_LICENSE("GPL");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for the cards");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for the cards");
+static int __devinit isicom_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ unsigned int ioaddr, signature, index;
+ int retval = -EPERM;
+ u8 pciirq;
+ struct isi_board *board = NULL;
+
+ if (card >= BOARD_COUNT)
+ goto err;
+
+ ioaddr = pci_resource_start(pdev, 3);
+ /* i.e at offset 0x1c in the PCI configuration register space. */
+ pciirq = pdev->irq;
+ dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
+
+ /* allot the first empty slot in the array */
+ for (index = 0; index < BOARD_COUNT; index++)
+ if (isi_card[index].base == 0) {
+ board = &isi_card[index];
+ break;
+ }
+
+ board->base = ioaddr;
+ board->irq = pciirq;
+ board->isa = NO;
+ card++;
+
+ pci_set_drvdata(pdev, board);
+
+ retval = isicom_register_ioregion(pdev, index);
+ if (retval < 0)
+ goto err;
+
+ retval = isicom_register_isr(pdev, index);
+ if (retval < 0)
+ goto errunrr;
+
+ retval = reset_card(pdev, index, &signature);
+ if (retval < 0)
+ goto errunri;
+
+ retval = load_firmware(pdev, index, signature);
+ if (retval < 0)
+ goto errunri;
+
+ return 0;
+
+errunri:
+ free_irq(board->irq, board);
+errunrr:
+ isicom_unregister_ioregion(pdev);
+err:
+ board->base = 0;
+ return retval;
+}
+
+static void __devexit isicom_remove(struct pci_dev *pdev)
+{
+ struct isi_board *board = pci_get_drvdata(pdev);
+
+ free_irq(board->irq, board);
+ isicom_unregister_ioregion(pdev);
+}
static int __devinit isicom_setup(void)
{
- struct pci_dev *dev = NULL;
- int retval, card, idx, count;
- unsigned char pciirq;
- unsigned int ioaddr;
-
+ int retval, idx, channel;
+ struct isi_port *port;
+
card = 0;
- for(idx=0; idx < BOARD_COUNT; idx++) {
- if (io[idx]) {
- isi_card[idx].base=io[idx];
- isi_card[idx].irq=irq[idx];
- isi_card[idx].isa=YES;
- card++;
- }
- else {
- isi_card[idx].base = 0;
- isi_card[idx].irq = 0;
- }
- }
-
- for (idx=0 ;idx < card; idx++) {
- if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
- (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
- (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
- (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
- (isi_card[idx].irq==15))) {
-
- if (isi_card[idx].base) {
- printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
- isi_card[idx].irq, idx+1);
- isi_card[idx].base=0;
- card--;
- }
- }
- }
-
- if (card < BOARD_COUNT) {
- for (idx=0; idx < DEVID_COUNT; idx++) {
- dev = NULL;
- for (;;){
- if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
- break;
- if (card >= BOARD_COUNT)
- break;
-
- if (pci_enable_device(dev))
- break;
+ memset(isi_ports, 0, sizeof(isi_ports));
- /* found a PCI ISI card! */
- ioaddr = pci_resource_start (dev, 3); /* i.e at offset 0x1c in the
- * PCI configuration register
- * space.
- */
- pciirq = dev->irq;
- printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device);
- /*
- * allot the first empty slot in the array
- */
- for (count=0; count < BOARD_COUNT; count++) {
- if (isi_card[count].base == 0) {
- isi_card[count].base = ioaddr;
- isi_card[count].irq = pciirq;
- isi_card[count].isa = NO;
- card++;
- break;
- }
- }
- }
- if (card >= BOARD_COUNT) break;
- }
+ for(idx = 0; idx < BOARD_COUNT; idx++) {
+ port = &isi_ports[idx * 16];
+ isi_card[idx].ports = port;
+ spin_lock_init(&isi_card[idx].card_lock);
+ for (channel = 0; channel < 16; channel++, port++) {
+ port->magic = ISICOM_MAGIC;
+ port->card = &isi_card[idx];
+ port->channel = channel;
+ port->close_delay = 50 * HZ/100;
+ port->closing_wait = 3000 * HZ/100;
+ INIT_WORK(&port->hangup_tq, do_isicom_hangup, port);
+ INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port);
+ port->status = 0;
+ init_waitqueue_head(&port->open_wait);
+ init_waitqueue_head(&port->close_wait);
+ /* . . . */
+ }
+ isi_card[idx].base = 0;
+ isi_card[idx].irq = 0;
+
+ if (!io[idx])
+ continue;
+
+ if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 ||
+ irq[idx] == 5 || irq[idx] == 7 ||
+ irq[idx] == 10 || irq[idx] == 11 ||
+ irq[idx] == 12 || irq[idx] == 15) {
+ printk(KERN_ERR "ISICOM: ISA not supported yet.\n");
+ retval = -EINVAL;
+ goto error;
+ } else
+ printk(KERN_ERR "ISICOM: Irq %d unsupported. "
+ "Disabling Card%d...\n", irq[idx], idx + 1);
}
-
- if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
- printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n");
- return -EIO;
- }
- retval = misc_register(&isiloader_device);
+ retval = isicom_register_tty_driver();
+ if (retval < 0)
+ goto error;
+
+ retval = pci_register_driver(&isicom_driver);
if (retval < 0) {
- printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
- return retval;
- }
-
- if (!isicom_init()) {
- if (misc_deregister(&isiloader_device))
- printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
- return -EIO;
+ printk(KERN_ERR "ISICOM: Unable to register pci driver.\n");
+ goto errtty;
}
-
+
init_timer(&tx);
tx.expires = jiffies + 1;
tx.data = 0;
tx.function = isicom_tx;
re_schedule = 1;
add_timer(&tx);
-
+
return 0;
+errtty:
+ isicom_unregister_tty_driver();
+error:
+ return retval;
}
static void __exit isicom_exit(void)
{
+ unsigned int index = 0;
+
re_schedule = 0;
- /* FIXME */
- msleep(1000);
- unregister_isr();
- unregister_drivers();
- unregister_ioregion();
- if(tmp_buf)
- free_page((unsigned long)tmp_buf);
- if (misc_deregister(&isiloader_device))
- printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+
+ while (re_schedule != 2 && index++ < 100)
+ msleep(10);
+
+ pci_unregister_driver(&isicom_driver);
+ isicom_unregister_tty_driver();
}
module_init(isicom_setup);
module_exit(isicom_exit);
+
+MODULE_AUTHOR("MultiTech");
+MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
+MODULE_LICENSE("GPL");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for the cards");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for the cards");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ce3bc0d45f1f..28c5a3193b81 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -135,7 +135,7 @@ static stlconf_t stli_brdconf[] = {
/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/
};
-static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
+static int stli_nrbrds = ARRAY_SIZE(stli_brdconf);
/*
* There is some experimental EISA board detection code in this driver.
@@ -406,7 +406,7 @@ static unsigned long stli_eisamemprobeaddrs[] = {
0xff000000, 0xff010000, 0xff020000, 0xff030000,
};
-static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
+static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
/*
* Define the Stallion PCI vendor and device IDs.
@@ -899,15 +899,13 @@ static void stli_argbrds(void)
{
stlconf_t conf;
stlibrd_t *brdp;
- int nrargs, i;
+ int i;
#ifdef DEBUG
printk("stli_argbrds()\n");
#endif
- nrargs = sizeof(stli_brdsp) / sizeof(char **);
-
- for (i = stli_nrbrds; (i < nrargs); i++) {
+ for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
memset(&conf, 0, sizeof(conf));
if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
continue;
@@ -967,7 +965,7 @@ static unsigned long stli_atol(char *str)
static int stli_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
- int nrbrdnames, i;
+ int i;
#ifdef DEBUG
printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
@@ -979,14 +977,13 @@ static int stli_parsebrd(stlconf_t *confp, char **argp)
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
- nrbrdnames = sizeof(stli_brdstr) / sizeof(stlibrdtype_t);
- for (i = 0; (i < nrbrdnames); i++) {
+ for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
break;
}
- if (i >= nrbrdnames) {
+ if (i == ARRAY_SIZE(stli_brdstr)) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
- return(0);
+ return 0;
}
confp->brdtype = stli_brdstr[i].type;
@@ -2714,17 +2711,13 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp)
stlen = size - tail;
}
- len = MIN(len, (TTY_FLIPBUF_SIZE - tty->flip.count));
+ len = tty_buffer_request_room(tty, len);
+ /* FIXME : iomap ? */
shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
while (len > 0) {
stlen = MIN(len, stlen);
- memcpy(tty->flip.char_buf_ptr, (char *) (shbuf + tail), stlen);
- memset(tty->flip.flag_buf_ptr, 0, stlen);
- tty->flip.char_buf_ptr += stlen;
- tty->flip.flag_buf_ptr += stlen;
- tty->flip.count += stlen;
-
+ tty_insert_flip_string(tty, (char *)(shbuf + tail), stlen);
len -= stlen;
tail += stlen;
if (tail >= size) {
@@ -2909,16 +2902,12 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
if (tty != (struct tty_struct *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = 0;
- if (portp->flags & ASYNC_SAK) {
- do_SAK(tty);
- EBRDENABLE(brdp);
- }
- tty_schedule_flip(tty);
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
+ if (portp->flags & ASYNC_SAK) {
+ do_SAK(tty);
+ EBRDENABLE(brdp);
}
+ tty_schedule_flip(tty);
}
}
@@ -4943,7 +4932,7 @@ static int stli_portcmdstats(stliport_t *portp)
if (portp->tty != (struct tty_struct *) NULL) {
if (portp->tty->driver_data == portp) {
stli_comstats.ttystate = portp->tty->flags;
- stli_comstats.rxbuffered = portp->tty->flip.count;
+ stli_comstats.rxbuffered = -1 /*portp->tty->flip.count*/;
if (portp->tty->termios != (struct termios *) NULL) {
stli_comstats.cflags = portp->tty->termios->c_cflag;
stli_comstats.iflags = portp->tty->termios->c_iflag;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 91dd669273e0..29c41f4418c0 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -101,6 +101,11 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
return 1;
}
+
+static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size)
+{
+ return 1;
+}
#endif
/*
@@ -228,26 +233,36 @@ static ssize_t write_mem(struct file * file, const char __user * buf,
return written;
}
+#ifndef __HAVE_PHYS_MEM_ACCESS_PROT
+static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+ unsigned long size, pgprot_t vma_prot)
+{
+#ifdef pgprot_noncached
+ unsigned long offset = pfn << PAGE_SHIFT;
+
+ if (uncached_access(file, offset))
+ return pgprot_noncached(vma_prot);
+#endif
+ return vma_prot;
+}
+#endif
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
-#if defined(__HAVE_PHYS_MEM_ACCESS_PROT)
+ size_t size = vma->vm_end - vma->vm_start;
+
+ if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size))
+ return -EINVAL;
+
vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
+ size,
vma->vm_page_prot);
-#elif defined(pgprot_noncached)
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- int uncached;
-
- uncached = uncached_access(file, offset);
- if (uncached)
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-#endif
/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
if (remap_pfn_range(vma,
vma->vm_start,
vma->vm_pgoff,
- vma->vm_end-vma->vm_start,
+ size,
vma->vm_page_prot))
return -EAGAIN;
return 0;
@@ -519,7 +534,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
return virtr + wrote;
}
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
static ssize_t read_port(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
@@ -726,7 +741,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
{
loff_t ret;
- down(&file->f_dentry->d_inode->i_sem);
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
switch (orig) {
case 0:
file->f_pos = offset;
@@ -741,7 +756,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return ret;
}
@@ -780,7 +795,7 @@ static struct file_operations null_fops = {
.write = write_null,
};
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
static struct file_operations port_fops = {
.llseek = memory_lseek,
.read = read_port,
@@ -817,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
char *tmp;
- int ret;
+ ssize_t ret;
tmp = kmalloc(count + 1, GFP_KERNEL);
if (tmp == NULL)
@@ -826,6 +841,9 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf,
if (!copy_from_user(tmp, buf, count)) {
tmp[count] = 0;
ret = printk("%s", tmp);
+ if (ret > count)
+ /* printk can add a prefix */
+ ret = count;
}
kfree(tmp);
return ret;
@@ -847,7 +865,7 @@ static int memory_open(struct inode * inode, struct file * filp)
case 3:
filp->f_op = &null_fops;
break;
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
case 4:
filp->f_op = &port_fops;
break;
@@ -894,7 +912,7 @@ static const struct {
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
{3, "null", S_IRUGO | S_IWUGO, &null_fops},
-#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
+#if defined(CONFIG_ISA) || !defined(__mc68000__)
{4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
#endif
{5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 78c89a3e7825..c92378121b4c 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -1,11 +1,11 @@
/*
- * Intel Multimedia Timer device implementation for SGI SN platforms.
+ * Timer device implementation for SGI SN platforms.
*
* 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) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (c) 2001-2006 Silicon Graphics, Inc. All rights reserved.
*
* This driver exports an API that should be supportable by any HPET or IA-PC
* multimedia timer. The code below is currently specific to the SGI Altix
@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
/* name of the device, usually in /dev */
#define MMTIMER_NAME "mmtimer"
#define MMTIMER_DESC "SGI Altix RTC Timer"
-#define MMTIMER_VERSION "2.0"
+#define MMTIMER_VERSION "2.1"
#define RTC_BITS 55 /* 55 bits for this implementation */
@@ -227,10 +227,7 @@ typedef struct mmtimer {
struct tasklet_struct tasklet;
} mmtimer_t;
-/*
- * Total number of comparators is comparators/node * MAX nodes/running kernel
- */
-static mmtimer_t timers[NUM_COMPARATORS*MAX_COMPACT_NODES];
+static mmtimer_t ** timers;
/**
* mmtimer_ioctl - ioctl interface for /dev/mmtimer
@@ -441,29 +438,29 @@ static irqreturn_t
mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
- mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) *
- NUM_COMPARATORS;
unsigned long expires = 0;
int result = IRQ_NONE;
+ unsigned indx = cpu_to_node(smp_processor_id());
/*
* Do this once for each comparison register
*/
for (i = 0; i < NUM_COMPARATORS; i++) {
+ mmtimer_t *base = timers[indx] + i;
/* Make sure this doesn't get reused before tasklet_sched */
- spin_lock(&base[i].lock);
- if (base[i].cpu == smp_processor_id()) {
- if (base[i].timer)
- expires = base[i].timer->it.mmtimer.expires;
+ spin_lock(&base->lock);
+ if (base->cpu == smp_processor_id()) {
+ if (base->timer)
+ expires = base->timer->it.mmtimer.expires;
/* expires test won't work with shared irqs */
if ((mmtimer_int_pending(i) > 0) ||
(expires && (expires < rtc_time()))) {
mmtimer_clr_int_pending(i);
- tasklet_schedule(&base[i].tasklet);
+ tasklet_schedule(&base->tasklet);
result = IRQ_HANDLED;
}
}
- spin_unlock(&base[i].lock);
+ spin_unlock(&base->lock);
expires = 0;
}
return result;
@@ -523,7 +520,7 @@ static int sgi_timer_del(struct k_itimer *timr)
{
int i = timr->it.mmtimer.clock;
cnodeid_t nodeid = timr->it.mmtimer.node;
- mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i;
+ mmtimer_t *t = timers[nodeid] + i;
unsigned long irqflags;
if (i != TIMER_OFF) {
@@ -609,11 +606,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
preempt_disable();
nodeid = cpu_to_node(smp_processor_id());
- base = timers + nodeid * NUM_COMPARATORS;
retry:
/* Don't use an allocated timer, or a deleted one that's pending */
for(i = 0; i< NUM_COMPARATORS; i++) {
- if (!base[i].timer && !base[i].tasklet.state) {
+ base = timers[nodeid] + i;
+ if (!base->timer && !base->tasklet.state) {
break;
}
}
@@ -623,14 +620,14 @@ retry:
return -EBUSY;
}
- spin_lock_irqsave(&base[i].lock, irqflags);
+ spin_lock_irqsave(&base->lock, irqflags);
- if (base[i].timer || base[i].tasklet.state != 0) {
- spin_unlock_irqrestore(&base[i].lock, irqflags);
+ if (base->timer || base->tasklet.state != 0) {
+ spin_unlock_irqrestore(&base->lock, irqflags);
goto retry;
}
- base[i].timer = timr;
- base[i].cpu = smp_processor_id();
+ base->timer = timr;
+ base->cpu = smp_processor_id();
timr->it.mmtimer.clock = i;
timr->it.mmtimer.node = nodeid;
@@ -645,11 +642,11 @@ retry:
}
} else {
timr->it.mmtimer.expires -= period;
- if (reschedule_periodic_timer(base+i))
+ if (reschedule_periodic_timer(base))
err = -EINVAL;
}
- spin_unlock_irqrestore(&base[i].lock, irqflags);
+ spin_unlock_irqrestore(&base->lock, irqflags);
preempt_enable();
@@ -675,6 +672,7 @@ static struct k_clock sgi_clock = {
static int __init mmtimer_init(void)
{
unsigned i;
+ cnodeid_t node, maxn = -1;
if (!ia64_platform_is("sn2"))
return -1;
@@ -691,14 +689,6 @@ static int __init mmtimer_init(void)
mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
2) / sn_rtc_cycles_per_second;
- for (i=0; i< NUM_COMPARATORS*MAX_COMPACT_NODES; i++) {
- spin_lock_init(&timers[i].lock);
- timers[i].timer = NULL;
- timers[i].cpu = 0;
- timers[i].i = i % NUM_COMPARATORS;
- tasklet_init(&timers[i].tasklet, mmtimer_tasklet, (unsigned long) (timers+i));
- }
-
if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, SA_PERCPU_IRQ, MMTIMER_NAME, NULL)) {
printk(KERN_WARNING "%s: unable to allocate interrupt.",
MMTIMER_NAME);
@@ -712,6 +702,40 @@ static int __init mmtimer_init(void)
return -1;
}
+ /* Get max numbered node, calculate slots needed */
+ for_each_online_node(node) {
+ maxn = node;
+ }
+ maxn++;
+
+ /* Allocate list of node ptrs to mmtimer_t's */
+ timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL);
+ if (timers == NULL) {
+ printk(KERN_ERR "%s: failed to allocate memory for device\n",
+ MMTIMER_NAME);
+ return -1;
+ }
+
+ /* Allocate mmtimer_t's for each online node */
+ for_each_online_node(node) {
+ timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
+ if (timers[node] == NULL) {
+ printk(KERN_ERR "%s: failed to allocate memory for device\n",
+ MMTIMER_NAME);
+ return -1;
+ }
+ for (i=0; i< NUM_COMPARATORS; i++) {
+ mmtimer_t * base = timers[node] + i;
+
+ spin_lock_init(&base->lock);
+ base->timer = NULL;
+ base->cpu = 0;
+ base->i = i;
+ tasklet_init(&base->tasklet, mmtimer_tasklet,
+ (unsigned long) (base));
+ }
+ }
+
sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 79e490ef2cf2..f43c2e04eadd 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -269,7 +269,7 @@ static int MoxaPortDCDChange(int);
static int MoxaPortDCDON(int);
static void MoxaPortFlushData(int, int);
static int MoxaPortWriteData(int, unsigned char *, int);
-static int MoxaPortReadData(int, unsigned char *, int);
+static int MoxaPortReadData(int, struct tty_struct *tty);
static int MoxaPortTxQueue(int);
static int MoxaPortRxQueue(int);
static int MoxaPortTxFree(int);
@@ -301,6 +301,8 @@ static struct tty_operations moxa_ops = {
.tiocmset = moxa_tiocmset,
};
+static spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
+
#ifdef CONFIG_PCI
static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
{
@@ -448,7 +450,7 @@ static int __init moxa_init(void)
#ifdef CONFIG_PCI
{
struct pci_dev *p = NULL;
- int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
+ int n = ARRAY_SIZE(moxa_pcibrds) - 1;
i = 0;
while (i < n) {
while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
@@ -645,10 +647,10 @@ static int moxa_write(struct tty_struct *tty,
if (ch == NULL)
return (0);
port = ch->port;
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&moxa_lock, flags);
len = MoxaPortWriteData(port, (unsigned char *) buf, count);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
/*********************************************
if ( !(ch->statusflags & LOWWAIT) &&
@@ -723,11 +725,10 @@ static void moxa_put_char(struct tty_struct *tty, unsigned char c)
if (ch == NULL)
return;
port = ch->port;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
moxaXmitBuff[0] = c;
MoxaPortWriteData(port, moxaXmitBuff, 1);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
/************************************************
if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
*************************************************/
@@ -1030,12 +1031,12 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
printk("block_til_ready before block: ttys%d, count = %d\n",
ch->line, ch->count);
#endif
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
if (!tty_hung_up_p(filp))
ch->count--;
- restore_flags(flags);
ch->blocked_open++;
+ spin_unlock_irqrestore(&moxa_lock, flags);
+
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
@@ -1062,17 +1063,21 @@ static int block_till_ready(struct tty_struct *tty, struct file *filp,
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&ch->open_wait, &wait);
+
+ spin_lock_irqsave(&moxa_lock, flags);
if (!tty_hung_up_p(filp))
ch->count++;
ch->blocked_open--;
+ spin_unlock_irqrestore(&moxa_lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready after blocking: ttys%d, count = %d\n",
ch->line, ch->count);
#endif
if (retval)
return (retval);
+ /* FIXME: review to see if we need to use set_bit on these */
ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
- return (0);
+ return 0;
}
static void setup_empty_event(struct tty_struct *tty)
@@ -1080,15 +1085,14 @@ static void setup_empty_event(struct tty_struct *tty)
struct moxa_str *ch = tty->driver_data;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&moxa_lock, flags);
ch->statusflags |= EMPTYWAIT;
moxaEmptyTimer_on[ch->port] = 0;
del_timer(&moxaEmptyTimer[ch->port]);
moxaEmptyTimer[ch->port].expires = jiffies + HZ;
moxaEmptyTimer_on[ch->port] = 1;
add_timer(&moxaEmptyTimer[ch->port]);
- restore_flags(flags);
+ spin_unlock_irqrestore(&moxa_lock, flags);
}
static void check_xmit_empty(unsigned long data)
@@ -1135,8 +1139,6 @@ static void receive_data(struct moxa_str *ch)
{
struct tty_struct *tp;
struct termios *ts;
- int i, count, rc, space;
- unsigned char *charptr, *flagptr;
unsigned long flags;
ts = NULL;
@@ -1150,24 +1152,10 @@ static void receive_data(struct moxa_str *ch)
MoxaPortFlushData(ch->port, 0);
return;
}
- space = TTY_FLIPBUF_SIZE - tp->flip.count;
- if (space <= 0)
- return;
- charptr = tp->flip.char_buf_ptr;
- flagptr = tp->flip.flag_buf_ptr;
- rc = tp->flip.count;
- save_flags(flags);
- cli();
- count = MoxaPortReadData(ch->port, charptr, space);
- restore_flags(flags);
- for (i = 0; i < count; i++)
- *flagptr++ = 0;
- charptr += count;
- rc += count;
- tp->flip.count = rc;
- tp->flip.char_buf_ptr = charptr;
- tp->flip.flag_buf_ptr = flagptr;
- tty_schedule_flip(ch->tty);
+ spin_lock_irqsave(&moxa_lock, flags);
+ MoxaPortReadData(ch->port, tp);
+ spin_unlock_irqrestore(&moxa_lock, flags);
+ tty_schedule_flip(tp);
}
#define Magic_code 0x404
@@ -1661,6 +1649,8 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
case MOXA_FIND_BOARD:
case MOXA_LOAD_C320B:
case MOXA_LOAD_CODE:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
break;
}
@@ -1774,7 +1764,7 @@ int MoxaPortsOfCard(int cardno)
* 14. MoxaPortDCDON(int port); *
* 15. MoxaPortFlushData(int port, int mode); *
* 16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
- * 17. MoxaPortReadData(int port, unsigned char * buffer, int length); *
+ * 17. MoxaPortReadData(int port, struct tty_struct *tty); *
* 18. MoxaPortTxBufSize(int port); *
* 19. MoxaPortRxBufSize(int port); *
* 20. MoxaPortTxQueue(int port); *
@@ -2003,10 +1993,9 @@ int MoxaPortsOfCard(int cardno)
*
* Function 21: Read data.
* Syntax:
- * int MoxaPortReadData(int port, unsigned char * buffer, int length);
+ * int MoxaPortReadData(int port, struct tty_struct *tty);
* int port : port number (0 - 127)
- * unsigned char * buffer : pointer to read data buffer.
- * int length : read data buffer length
+ * struct tty_struct *tty : tty for data
*
* return: 0 - length : real read data length
*
@@ -2504,7 +2493,7 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len)
return (total);
}
-int MoxaPortReadData(int port, unsigned char * buffer, int space)
+int MoxaPortReadData(int port, struct tty_struct *tty)
{
register ushort head, pageofs;
int i, count, cnt, len, total, remain;
@@ -2522,9 +2511,9 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
count = (tail >= head) ? (tail - head)
: (tail - head + rx_mask + 1);
if (count == 0)
- return (0);
+ return 0;
- total = (space > count) ? count : space;
+ total = count;
remain = count - total;
moxaLog.rxcnt[port] += total;
count = total;
@@ -2539,7 +2528,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
len = (count > len) ? len : count;
ofs = baseAddr + DynPage_addr + bufhead + head;
for (i = 0; i < len; i++)
- *buffer++ = readb(ofs + i);
+ tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
head = (head + len) & rx_mask;
count -= len;
}
@@ -2556,7 +2545,7 @@ int MoxaPortReadData(int port, unsigned char * buffer, int space)
writew(pageno, baseAddr + Control_reg);
ofs = baseAddr + DynPage_addr + pageofs;
for (i = 0; i < cnt; i++)
- *buffer++ = readb(ofs + i);
+ tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
if (count == 0) {
writew((head + len) & rx_mask, ofsAddr + RXrptr);
break;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 26448f176803..ea725a9964e2 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -813,7 +813,7 @@ static int mxser_init(void)
/* start finding PCI board here */
#ifdef CONFIG_PCI
- n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
+ n = ARRAY_SIZE(mxser_pcibrds) - 1;
index = 0;
b = 0;
while (b < n) {
@@ -1982,7 +1982,7 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
spin_lock_irqsave(&info->slock, flags);
- recv_room = tty->ldisc.receive_room(tty);
+ recv_room = tty->receive_room;
if ((recv_room == 0) && (!info->ldisc_stop_rx)) {
//mxser_throttle(tty);
mxser_stoprx(tty);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index c3660d8781a4..9f54733f1623 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -191,7 +191,6 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_table *wait);
static int n_hdlc_tty_open(struct tty_struct *tty);
static void n_hdlc_tty_close(struct tty_struct *tty);
-static int n_hdlc_tty_room(struct tty_struct *tty);
static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp,
char *fp, int count);
static void n_hdlc_tty_wakeup(struct tty_struct *tty);
@@ -212,7 +211,6 @@ static struct tty_ldisc n_hdlc_ldisc = {
.ioctl = n_hdlc_tty_ioctl,
.poll = n_hdlc_tty_poll,
.receive_buf = n_hdlc_tty_receive,
- .receive_room = n_hdlc_tty_room,
.write_wakeup = n_hdlc_tty_wakeup,
};
@@ -337,6 +335,7 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
tty->disc_data = n_hdlc;
n_hdlc->tty = tty;
+ tty->receive_room = 65536;
#if defined(TTY_NO_WRITE_SPLIT)
/* change tty_io write() to not split large writes into 8K chunks */
@@ -478,22 +477,6 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
} /* end of n_hdlc_tty_wakeup() */
/**
- * n_hdlc_tty_room - Return the amount of space left in the receiver's buffer
- * @tty - pointer to associated tty instance data
- *
- * Callback function from tty driver. Return the amount of space left in the
- * receiver's buffer to decide if remote transmitter is to be throttled.
- */
-static int n_hdlc_tty_room(struct tty_struct *tty)
-{
- if (debuglevel >= DEBUG_LEVEL_INFO)
- printk("%s(%d)n_hdlc_tty_room() called\n",__FILE__,__LINE__);
- /* always return a larger number to prevent */
- /* throttling of remote transmitter. */
- return 65536;
-} /* end of n_hdlc_tty_root() */
-
-/**
* n_hdlc_tty_receive - Called by tty driver when receive data is available
* @tty - pointer to tty instance data
* @data - pointer to received data
@@ -562,7 +545,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
} /* end of n_hdlc_tty_receive() */
/**
- * n_hdlc_tty_read - Called to retreive one frame of data (if available)
+ * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
* @tty - pointer to tty instance data
* @file - pointer to open file object
* @buf - pointer to returned data buffer
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 853c98cee64f..c48de09d68f0 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -147,7 +147,6 @@ static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
struct poll_table_struct *wait);
static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count);
-static int r3964_receive_room(struct tty_struct *tty);
static struct tty_ldisc tty_ldisc_N_R3964 = {
.owner = THIS_MODULE,
@@ -161,7 +160,6 @@ static struct tty_ldisc tty_ldisc_N_R3964 = {
.set_termios = r3964_set_termios,
.poll = r3964_poll,
.receive_buf = r3964_receive_buf,
- .receive_room = r3964_receive_room,
};
@@ -1119,6 +1117,7 @@ static int r3964_open(struct tty_struct *tty)
pInfo->nRetry = 0;
tty->disc_data = pInfo;
+ tty->receive_room = 65536;
init_timer(&pInfo->tmr);
pInfo->tmr.data = (unsigned long)pInfo;
@@ -1405,12 +1404,5 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
}
-static int r3964_receive_room(struct tty_struct *tty)
-{
- TRACE_L("receive_room");
- return -1;
-}
-
-
MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_R3964);
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index c556f4d3ccd7..ccad7ae94541 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -78,7 +78,32 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf);
}
-static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+/**
+ * n_tty_set__room - receive space
+ * @tty: terminal
+ *
+ * Called by the driver to find out how much data it is
+ * permitted to feed to the line discipline without any being lost
+ * and thus to manage flow control. Not serialized. Answers for the
+ * "instant".
+ */
+
+static void n_tty_set_room(struct tty_struct *tty)
+{
+ int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
+ /*
+ * If we are doing input canonicalization, and there are no
+ * pending newlines, let characters through without limit, so
+ * that erase characters will be handled. Other excess
+ * characters will be beeped.
+ */
+ if (left <= 0)
+ left = tty->icanon && !tty->canon_data;
+ tty->receive_room = left;
+}
+
+static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
{
if (tty->read_cnt < N_TTY_BUF_SIZE) {
tty->read_buf[tty->read_head] = c;
@@ -87,7 +112,7 @@ static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
}
}
-static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct tty_struct *tty)
{
unsigned long flags;
/*
@@ -136,6 +161,7 @@ static void reset_buffer_flags(struct tty_struct *tty)
spin_unlock_irqrestore(&tty->read_lock, flags);
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ n_tty_set_room(tty);
check_unthrottle(tty);
}
@@ -838,30 +864,6 @@ send_signal:
put_tty_queue(c, tty);
}
-/**
- * n_tty_receive_room - receive space
- * @tty: terminal
- *
- * Called by the driver to find out how much data it is
- * permitted to feed to the line discipline without any being lost
- * and thus to manage flow control. Not serialized. Answers for the
- * "instant".
- */
-
-static int n_tty_receive_room(struct tty_struct *tty)
-{
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
-
- /*
- * If we are doing input canonicalization, and there are no
- * pending newlines, let characters through without limit, so
- * that erase characters will be handled. Other excess
- * characters will be beeped.
- */
- if (left <= 0)
- left = tty->icanon && !tty->canon_data;
- return left;
-}
/**
* n_tty_write_wakeup - asynchronous I/O notifier
@@ -953,6 +955,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->driver->flush_chars(tty);
}
+ n_tty_set_room(tty);
+
if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
@@ -964,7 +968,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
* mode. We don't want to throttle the driver if we're in
* canonical mode and don't have a newline yet!
*/
- if (n_tty_receive_room(tty) < TTY_THRESHOLD_THROTTLE) {
+ if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
/* check TTY_THROTTLED first so it indicates our state */
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->throttle)
@@ -999,6 +1003,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
tty->raw = 1;
tty->real_raw = 1;
+ n_tty_set_room(tty);
return;
}
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
@@ -1051,6 +1056,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
else
tty->real_raw = 0;
}
+ n_tty_set_room(tty);
}
/**
@@ -1130,7 +1136,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
*
*/
-static inline int copy_from_read_buf(struct tty_struct *tty,
+static int copy_from_read_buf(struct tty_struct *tty,
unsigned char __user **b,
size_t *nr)
@@ -1308,6 +1314,7 @@ do_it_again:
retval = -ERESTARTSYS;
break;
}
+ n_tty_set_room(tty);
clear_bit(TTY_DONT_FLIP, &tty->flags);
timeout = schedule_timeout(timeout);
set_bit(TTY_DONT_FLIP, &tty->flags);
@@ -1401,6 +1408,8 @@ do_it_again:
} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
goto do_it_again;
+ n_tty_set_room(tty);
+
return retval;
}
@@ -1553,7 +1562,6 @@ struct tty_ldisc tty_ldisc_N_TTY = {
normal_poll, /* poll */
NULL, /* hangup */
n_tty_receive_buf, /* receive_buf */
- n_tty_receive_room, /* receive_room */
n_tty_write_wakeup /* write_wakeup */
};
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 1af733d07321..3556ccd77570 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -557,13 +557,13 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len,
(nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
PRINT_PROC("Floppy 0 type : ");
type = nvram[2] >> 4;
- if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+ if (type < ARRAY_SIZE(floppy_types))
PRINT_PROC("%s\n", floppy_types[type]);
else
PRINT_PROC("%d (unknown)\n", type);
PRINT_PROC("Floppy 1 type : ");
type = nvram[2] & 0x0f;
- if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+ if (type < ARRAY_SIZE(floppy_types))
PRINT_PROC("%s\n", floppy_types[type]);
else
PRINT_PROC("%d (unknown)\n", type);
@@ -843,8 +843,6 @@ static char *colors[] = {
"2", "4", "16", "256", "65536", "??", "??", "??"
};
-#define fieldsize(a) (sizeof(a)/sizeof(*a))
-
static int
atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
off_t *begin, off_t offset, int size)
@@ -856,7 +854,7 @@ atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
PRINT_PROC("Checksum status : %svalid\n", checksum ? "" : "not ");
PRINT_PROC("Boot preference : ");
- for (i = fieldsize(boot_prefs) - 1; i >= 0; --i) {
+ for (i = ARRAY_SIZE(boot_prefs) - 1; i >= 0; --i) {
if (nvram[1] == boot_prefs[i].val) {
PRINT_PROC("%s\n", boot_prefs[i].name);
break;
@@ -878,12 +876,12 @@ atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
return 1;
PRINT_PROC("OS language : ");
- if (nvram[6] < fieldsize(languages))
+ if (nvram[6] < ARRAY_SIZE(languages))
PRINT_PROC("%s\n", languages[nvram[6]]);
else
PRINT_PROC("%u (undefined)\n", nvram[6]);
PRINT_PROC("Keyboard language: ");
- if (nvram[7] < fieldsize(languages))
+ if (nvram[7] < ARRAY_SIZE(languages))
PRINT_PROC("%s\n", languages[nvram[7]]);
else
PRINT_PROC("%u (undefined)\n", nvram[7]);
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 61681c9f3f72..649677b5dc36 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
#define T_100MSEC msecs_to_jiffies(100)
#define T_500MSEC msecs_to_jiffies(500)
-static void cm4000_detach(dev_link_t *link);
static void cm4000_release(dev_link_t *link);
static int major; /* major number we get from the kernel */
@@ -156,7 +155,6 @@ struct cm4000_dev {
/*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t))
-static dev_info_t dev_info = MODULE_NAME;
static dev_link_t *dev_table[CM4000_MAX_DEV];
/* This table doesn't use spaces after the comma between fields and thus
@@ -1864,68 +1862,36 @@ cs_release:
link->state &= ~DEV_CONFIG_PENDING;
}
-static int cm4000_event(event_t event, int priority,
- event_callback_args_t *args)
+static int cm4000_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
+ dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev;
- int devno;
- link = args->client_data;
dev = link->priv;
- DEBUGP(3, dev, "-> cm4000_event\n");
- for (devno = 0; devno < CM4000_MAX_DEV; devno++)
- if (dev_table[devno] == link)
- break;
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+ stop_monitor(dev);
- if (devno == CM4000_MAX_DEV)
- return CS_BAD_ADAPTER;
+ return 0;
+}
- switch (event) {
- case CS_EVENT_CARD_INSERTION:
- DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- cm4000_config(link, devno);
- break;
- case CS_EVENT_CARD_REMOVAL:
- DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
- link->state &= ~DEV_PRESENT;
- stop_monitor(dev);
- break;
- case CS_EVENT_PM_SUSPEND:
- DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND "
- "(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
- link->state |= DEV_SUSPEND;
- /* fall-through */
- case CS_EVENT_RESET_PHYSICAL:
- DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG) {
- DEBUGP(5, dev, "ReleaseConfiguration\n");
- pcmcia_release_configuration(link->handle);
- }
- stop_monitor(dev);
- break;
- case CS_EVENT_PM_RESUME:
- DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
- "(fall-through to CS_EVENT_CARD_RESET)\n");
- link->state &= ~DEV_SUSPEND;
- /* fall-through */
- case CS_EVENT_CARD_RESET:
- DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
- if ((link->state & DEV_CONFIG)) {
- DEBUGP(5, dev, "RequestConfiguration\n");
- pcmcia_request_configuration(link->handle, &link->conf);
- }
- if (link->open)
- start_monitor(dev);
- break;
- default:
- DEBUGP(5, dev, "unknown event %.2x\n", event);
- break;
- }
- DEBUGP(3, dev, "<- cm4000_event\n");
- return CS_SUCCESS;
+static int cm4000_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct cm4000_dev *dev;
+
+ dev = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ if (link->open)
+ start_monitor(dev);
+
+ return 0;
}
static void cm4000_release(dev_link_t *link)
@@ -1935,11 +1901,10 @@ static void cm4000_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io);
}
-static dev_link_t *cm4000_attach(void)
+static int cm4000_attach(struct pcmcia_device *p_dev)
{
struct cm4000_dev *dev;
dev_link_t *link;
- client_reg_t client_reg;
int i;
for (i = 0; i < CM4000_MAX_DEV; i++)
@@ -1948,76 +1913,55 @@ static dev_link_t *cm4000_attach(void)
if (i == CM4000_MAX_DEV) {
printk(KERN_NOTICE MODULE_NAME ": all devices in use\n");
- return NULL;
+ return -ENODEV;
}
/* create a new cm4000_cs device */
dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL);
if (dev == NULL)
- return NULL;
+ return -ENOMEM;
link = &dev->link;
link->priv = dev;
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
- /* register with card services */
- client_reg.dev_info = &dev_info;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
-
- i = pcmcia_register_client(&link->handle, &client_reg);
- if (i) {
- cs_error(link->handle, RegisterClient, i);
- cm4000_detach(link);
- return NULL;
- }
-
init_waitqueue_head(&dev->devq);
init_waitqueue_head(&dev->ioq);
init_waitqueue_head(&dev->atrq);
init_waitqueue_head(&dev->readq);
- return link;
-}
-
-static void cm4000_detach_by_devno(int devno, dev_link_t * link)
-{
- struct cm4000_dev *dev = link->priv;
-
- DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
-
- if (link->state & DEV_CONFIG) {
- DEBUGP(5, dev, "device still configured (try to release it)\n");
- cm4000_release(link);
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- if (link->handle) {
- pcmcia_deregister_client(link->handle);
- }
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ cm4000_config(link, i);
- dev_table[devno] = NULL;
- kfree(dev);
- return;
+ return 0;
}
-static void cm4000_detach(dev_link_t * link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
{
- int i;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct cm4000_dev *dev = link->priv;
+ int devno;
/* find device */
- for (i = 0; i < CM4000_MAX_DEV; i++)
- if (dev_table[i] == link)
+ for (devno = 0; devno < CM4000_MAX_DEV; devno++)
+ if (dev_table[devno] == link)
break;
-
- if (i == CM4000_MAX_DEV)
+ if (devno == CM4000_MAX_DEV)
return;
- cm4000_detach_by_devno(i, link);
+ link->state &= ~DEV_PRESENT;
+ stop_monitor(dev);
+
+ if (link->state & DEV_CONFIG)
+ cm4000_release(link);
+
+ dev_table[devno] = NULL;
+ kfree(dev);
+
return;
}
@@ -2042,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = {
.drv = {
.name = "cm4000_cs",
},
- .attach = cm4000_attach,
- .detach = cm4000_detach,
- .event = cm4000_event,
+ .probe = cm4000_attach,
+ .remove = cm4000_detach,
+ .suspend = cm4000_suspend,
+ .resume = cm4000_resume,
.id_table = cm4000_ids,
};
@@ -2064,13 +2009,8 @@ static int __init cmm_init(void)
static void __exit cmm_exit(void)
{
- int i;
-
printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&cm4000_driver);
- for (i = 0; i < CM4000_MAX_DEV; i++)
- if (dev_table[i])
- cm4000_detach_by_devno(i, dev_table[i]);
unregister_chrdev(major, DEVICE_NAME);
};
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 4c698d908ffa..46eb371bf17e 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -65,7 +65,6 @@ static char *version =
#define POLL_PERIOD msecs_to_jiffies(10)
static void reader_release(dev_link_t *link);
-static void reader_detach(dev_link_t *link);
static int major;
@@ -86,7 +85,6 @@ struct reader_dev {
struct timer_list poll_timer;
};
-static dev_info_t dev_info = MODULE_NAME;
static dev_link_t *dev_table[CM_MAX_DEV];
#ifndef PCMCIA_DEBUG
@@ -629,65 +627,26 @@ cs_release:
link->state &= ~DEV_CONFIG_PENDING;
}
-static int reader_event(event_t event, int priority,
- event_callback_args_t *args)
+static int reader_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link;
- struct reader_dev *dev;
- int devno;
+ dev_link_t *link = dev_to_instance(p_dev);
- link = args->client_data;
- dev = link->priv;
- DEBUGP(3, dev, "-> reader_event\n");
- for (devno = 0; devno < CM_MAX_DEV; devno++) {
- if (dev_table[devno] == link)
- break;
- }
- if (devno == CM_MAX_DEV)
- return CS_BAD_ADAPTER;
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
- switch (event) {
- case CS_EVENT_CARD_INSERTION:
- DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- reader_config(link, devno);
- break;
- case CS_EVENT_CARD_REMOVAL:
- DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
- link->state &= ~DEV_PRESENT;
- break;
- case CS_EVENT_PM_SUSPEND:
- DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND "
- "(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
- link->state |= DEV_SUSPEND;
-
- case CS_EVENT_RESET_PHYSICAL:
- DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG) {
- DEBUGP(5, dev, "ReleaseConfiguration\n");
- pcmcia_release_configuration(link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
- "(fall-through to CS_EVENT_CARD_RESET)\n");
- link->state &= ~DEV_SUSPEND;
-
- case CS_EVENT_CARD_RESET:
- DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
- if ((link->state & DEV_CONFIG)) {
- DEBUGP(5, dev, "RequestConfiguration\n");
- pcmcia_request_configuration(link->handle,
- &link->conf);
- }
- break;
- default:
- DEBUGP(5, dev, "reader_event: unknown event %.2x\n",
- event);
- break;
- }
- DEBUGP(3, dev, "<- reader_event\n");
- return CS_SUCCESS;
+ return 0;
+}
+
+static int reader_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ return 0;
}
static void reader_release(dev_link_t *link)
@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io);
}
-static dev_link_t *reader_attach(void)
+static int reader_attach(struct pcmcia_device *p_dev)
{
struct reader_dev *dev;
dev_link_t *link;
- client_reg_t client_reg;
int i;
for (i = 0; i < CM_MAX_DEV; i++) {
@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void)
}
if (i == CM_MAX_DEV)
- return NULL;
+ return -ENODEV;
dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL);
if (dev == NULL)
- return NULL;
+ return -ENOMEM;
dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
dev->buffer_status = 0;
@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
- client_reg.dev_info = &dev_info;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
- client_reg.EventMask=
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
- CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
- CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
- i = pcmcia_register_client(&link->handle, &client_reg);
- if (i) {
- cs_error(link->handle, RegisterClient, i);
- reader_detach(link);
- return NULL;
- }
init_waitqueue_head(&dev->devq);
init_waitqueue_head(&dev->poll_wait);
init_waitqueue_head(&dev->read_wait);
@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void)
init_timer(&dev->poll_timer);
dev->poll_timer.function = &cm4040_do_poll;
- return link;
-}
-
-static void reader_detach_by_devno(int devno, dev_link_t *link)
-{
- struct reader_dev *dev = link->priv;
+ link->handle = p_dev;
+ p_dev->instance = link;
- if (link->state & DEV_CONFIG) {
- DEBUGP(5, dev, "device still configured (try to release it)\n");
- reader_release(link);
- }
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ reader_config(link, i);
- pcmcia_deregister_client(link->handle);
- dev_table[devno] = NULL;
- DEBUGP(5, dev, "freeing dev=%p\n", dev);
- cm4040_stop_poll(dev);
- kfree(dev);
- return;
+ return 0;
}
-static void reader_detach(dev_link_t *link)
+static void reader_detach(struct pcmcia_device *p_dev)
{
- int i;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct reader_dev *dev = link->priv;
+ int devno;
/* find device */
- for (i = 0; i < CM_MAX_DEV; i++) {
- if (dev_table[i] == link)
+ for (devno = 0; devno < CM_MAX_DEV; devno++) {
+ if (dev_table[devno] == link)
break;
}
- if (i == CM_MAX_DEV)
+ if (devno == CM_MAX_DEV)
return;
- reader_detach_by_devno(i, link);
+ link->state &= ~DEV_PRESENT;
+
+ if (link->state & DEV_CONFIG)
+ reader_release(link);
+
+ dev_table[devno] = NULL;
+ kfree(dev);
+
return;
}
@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = {
.drv = {
.name = "cm4040_cs",
},
- .attach = reader_attach,
- .detach = reader_detach,
- .event = reader_event,
+ .probe = reader_attach,
+ .remove = reader_detach,
+ .suspend = reader_suspend,
+ .resume = reader_resume,
.id_table = cm4040_ids,
};
@@ -825,14 +768,8 @@ static int __init cm4040_init(void)
static void __exit cm4040_exit(void)
{
- int i;
-
printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&reader_driver);
- for (i = 0; i < CM_MAX_DEV; i++) {
- if (dev_table[i])
- reader_detach_by_devno(i, dev_table[i]);
- }
unregister_chrdev(major, DEVICE_NAME);
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 2c326ea53421..8a8ca32822ba 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -486,13 +486,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
static void mgslpc_config(dev_link_t *link);
static void mgslpc_release(u_long arg);
-static int mgslpc_event(event_t event, int priority,
- event_callback_args_t *args);
-static dev_link_t *mgslpc_attach(void);
-static void mgslpc_detach(dev_link_t *);
-
-static dev_info_t dev_info = "synclink_cs";
-static dev_link_t *dev_list = NULL;
+static void mgslpc_detach(struct pcmcia_device *p_dev);
/*
* 1st function defined in .text section. Calling this function in
@@ -539,12 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty,
}
}
-static dev_link_t *mgslpc_attach(void)
+static int mgslpc_attach(struct pcmcia_device *p_dev)
{
MGSLPC_INFO *info;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n");
@@ -552,7 +544,7 @@ static dev_link_t *mgslpc_attach(void)
info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) {
printk("Error can't allocate device instance data\n");
- return NULL;
+ return -ENOMEM;
}
memset(info, 0, sizeof(MGSLPC_INFO));
@@ -587,24 +579,15 @@ static dev_link_t *mgslpc_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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;
+ link->handle = p_dev;
+ p_dev->instance = link;
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if (ret != CS_SUCCESS) {
- cs_error(link->handle, RegisterClient, ret);
- mgslpc_detach(link);
- return NULL;
- }
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ mgslpc_config(link);
mgslpc_add_device(info);
- return link;
+ return 0;
}
/* Card has been inserted.
@@ -736,85 +719,50 @@ static void mgslpc_release(u_long arg)
pcmcia_release_io(link->handle, &link->io);
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
- if (link->state & DEV_STALE_LINK)
- mgslpc_detach(link);
}
-static void mgslpc_detach(dev_link_t *link)
+static void mgslpc_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_detach(0x%p)\n", link);
-
- /* find device */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG) {
- /* device is configured/active, mark it so when
- * release() is called a proper detach() occurs.
- */
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "
- "still locked\n", link->dev->dev_name);
- link->state |= DEV_STALE_LINK;
- return;
+ ((MGSLPC_INFO *)link->priv)->stop = 1;
+ mgslpc_release((u_long)link);
}
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, and free it */
- *linkp = link->next;
mgslpc_remove_device((MGSLPC_INFO *)link->priv);
}
-static int mgslpc_event(event_t event, int priority,
- event_callback_args_t *args)
+static int mgslpc_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- MGSLPC_INFO *info = link->priv;
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgslpc_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- ((MGSLPC_INFO *)link->priv)->stop = 1;
- mgslpc_release((u_long)link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- mgslpc_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 */
- info->stop = 1;
- if (link->state & DEV_CONFIG)
- 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)
- pcmcia_request_configuration(link->handle, &link->conf);
- info->stop = 0;
- break;
- }
- return 0;
+ dev_link_t *link = dev_to_instance(dev);
+ MGSLPC_INFO *info = link->priv;
+
+ link->state |= DEV_SUSPEND;
+ info->stop = 1;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int mgslpc_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ MGSLPC_INFO *info = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+ info->stop = 0;
+
+ return 0;
}
+
static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
char *name, const char *routine)
{
@@ -1059,8 +1007,9 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
static void rx_ready_async(MGSLPC_INFO *info, int tcd)
{
- unsigned char data, status;
+ unsigned char data, status, flag;
int fifo_count;
+ int work = 0;
struct tty_struct *tty = info->tty;
struct mgsl_icount *icount = &info->icount;
@@ -1075,20 +1024,16 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
fifo_count = 32;
} else
fifo_count = 32;
-
+
+ tty_buffer_request_room(tty, fifo_count);
/* Flush received async data to receive data buffer. */
while (fifo_count) {
data = read_reg(info, CHA + RXFIFO);
status = read_reg(info, CHA + RXFIFO);
fifo_count -= 2;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
- *tty->flip.char_buf_ptr = data;
icount->rx++;
-
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
// if no frameing/crc error then save data
// BIT7:parity error
@@ -1107,26 +1052,23 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
status &= info->read_status_mask;
if (status & BIT7)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & BIT6)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ work += tty_insert_flip_char(tty, data, flag);
}
issue_command(info, CHA, CMD_RXFIFO);
if (debug_level >= DEBUG_LEVEL_ISR) {
- printk("%s(%d):rx_ready_async count=%d\n",
- __FILE__,__LINE__,tty->flip.count);
+ printk("%s(%d):rx_ready_async",
+ __FILE__,__LINE__);
printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,icount->rx,icount->brk,
icount->parity,icount->frame,icount->overrun);
}
- if (tty->flip.count)
+ if (work)
tty_flip_buffer_push(tty);
}
@@ -3091,10 +3033,11 @@ static struct pcmcia_driver mgslpc_driver = {
.drv = {
.name = "synclink_cs",
},
- .attach = mgslpc_attach,
- .event = mgslpc_event,
- .detach = mgslpc_detach,
+ .probe = mgslpc_attach,
+ .remove = mgslpc_detach,
.id_table = mgslpc_ids,
+ .suspend = mgslpc_suspend,
+ .resume = mgslpc_resume,
};
static struct tty_operations mgslpc_ops = {
@@ -3138,7 +3081,6 @@ static void synclink_cs_cleanup(void)
}
pcmcia_unregister_driver(&mgslpc_driver);
- BUG_ON(dev_list != NULL);
}
static int __init synclink_cs_init(void)
@@ -4057,7 +3999,7 @@ BOOLEAN register_test(MGSLPC_INFO *info)
{
static unsigned char patterns[] =
{ 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
- static unsigned int count = sizeof(patterns) / sizeof(patterns[0]);
+ static unsigned int count = ARRAY_SIZE(patterns);
unsigned int i;
BOOLEAN rc = TRUE;
unsigned long flags;
@@ -4068,7 +4010,7 @@ BOOLEAN register_test(MGSLPC_INFO *info)
for (i = 0; i < count; i++) {
write_reg(info, XAD1, patterns[i]);
write_reg(info, XAD2, patterns[(i + 1) % count]);
- if ((read_reg(info, XAD1) != patterns[i]) ||
+ if ((read_reg(info, XAD1) != patterns[i]) ||
(read_reg(info, XAD2) != patterns[(i + 1) % count])) {
rc = FALSE;
break;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 49f3997fd251..9b5a2c0e7008 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -111,7 +111,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun
if (!to || tty->stopped)
return 0;
- c = to->ldisc.receive_room(to);
+ c = to->receive_room;
if (c > count)
c = count;
to->ldisc.receive_buf(to, buf, NULL, c);
@@ -126,7 +126,7 @@ static int pty_write_room(struct tty_struct *tty)
if (!to || tty->stopped)
return 0;
- return to->ldisc.receive_room(to);
+ return to->receive_room;
}
/*
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 7999da25fe40..86be04b241e1 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -632,7 +632,7 @@ out:
preempt_enable();
}
-extern void add_input_randomness(unsigned int type, unsigned int code,
+void add_input_randomness(unsigned int type, unsigned int code,
unsigned int value)
{
static unsigned char last_value;
@@ -1554,10 +1554,8 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
EXPORT_SYMBOL(secure_tcp_sequence_number);
-
-
-/* Generate secure starting point for ephemeral TCP port search */
-u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
+/* Generate secure starting point for ephemeral IPV4 transport port search */
+u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
{
struct keydata *keyptr = get_keyptr();
u32 hash[4];
@@ -1575,7 +1573,7 @@ u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
+u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
{
struct keydata *keyptr = get_keyptr();
u32 hash[12];
@@ -1586,7 +1584,7 @@ u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dp
return twothirdsMD4Transform(daddr, hash);
}
-EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
+EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h
index 0b397e1c8f1c..29c980204098 100644
--- a/drivers/char/rio/board.h
+++ b/drivers/char/rio/board.h
@@ -52,63 +52,57 @@ static char *_board_h_sccs_ = "@(#)board.h 1.2";
/*
** The shape of the Host Control area, at offset 0x7C00, Write Only
*/
-struct s_Ctrl
-{
- BYTE DpCtl; /* 7C00 */
- BYTE Dp_Unused2_[127];
- BYTE DpIntSet; /* 7C80 */
- BYTE Dp_Unused3_[127];
- BYTE DpTpuReset; /* 7D00 */
- BYTE Dp_Unused4_[127];
- BYTE DpIntReset; /* 7D80 */
- BYTE Dp_Unused5_[127];
+struct s_Ctrl {
+ BYTE DpCtl; /* 7C00 */
+ BYTE Dp_Unused2_[127];
+ BYTE DpIntSet; /* 7C80 */
+ BYTE Dp_Unused3_[127];
+ BYTE DpTpuReset; /* 7D00 */
+ BYTE Dp_Unused4_[127];
+ BYTE DpIntReset; /* 7D80 */
+ BYTE Dp_Unused5_[127];
};
/*
** The PROM data area on the host (0x7C00), Read Only
*/
-struct s_Prom
-{
- WORD DpSlxCode[2];
- WORD DpRev;
- WORD Dp_Unused6_;
- WORD DpUniq[4];
- WORD DpJahre;
- WORD DpWoche;
- WORD DpHwFeature[5];
- WORD DpOemId;
- WORD DpSiggy[16];
+struct s_Prom {
+ WORD DpSlxCode[2];
+ WORD DpRev;
+ WORD Dp_Unused6_;
+ WORD DpUniq[4];
+ WORD DpJahre;
+ WORD DpWoche;
+ WORD DpHwFeature[5];
+ WORD DpOemId;
+ WORD DpSiggy[16];
};
/*
** Union of the Ctrl and Prom areas
*/
-union u_CtrlProm /* This is the control/PROM area (0x7C00) */
-{
- struct s_Ctrl DpCtrl;
- struct s_Prom DpProm;
+union u_CtrlProm { /* This is the control/PROM area (0x7C00) */
+ struct s_Ctrl DpCtrl;
+ struct s_Prom DpProm;
};
/*
** The top end of memory!
*/
-struct s_ParmMapS /* Area containing Parm Map Pointer */
-{
- BYTE Dp_Unused8_[DP_PARMMAP_ADDR];
- WORD DpParmMapAd;
+struct s_ParmMapS { /* Area containing Parm Map Pointer */
+ BYTE Dp_Unused8_[DP_PARMMAP_ADDR];
+ WORD DpParmMapAd;
};
-struct s_StartUpS
-{
- BYTE Dp_Unused9_[DP_STARTUP_ADDR];
- BYTE Dp_LongJump[0x4];
- BYTE Dp_Unused10_[2];
- BYTE Dp_ShortJump[0x2];
+struct s_StartUpS {
+ BYTE Dp_Unused9_[DP_STARTUP_ADDR];
+ BYTE Dp_LongJump[0x4];
+ BYTE Dp_Unused10_[2];
+ BYTE Dp_ShortJump[0x2];
};
-union u_Sram2ParmMap /* This is the top of memory (0x7E00-0x7FFF) */
-{
- BYTE DpSramMem[DP_SRAM2_SIZE];
+union u_Sram2ParmMap { /* This is the top of memory (0x7E00-0x7FFF) */
+ BYTE DpSramMem[DP_SRAM2_SIZE];
struct s_ParmMapS DpParmMapS;
struct s_StartUpS DpStartUpS;
};
@@ -116,13 +110,12 @@ union u_Sram2ParmMap /* This is the top of memory (0x7E00-0x7FFF) */
/*
** This is the DP RAM overlay.
*/
-struct DpRam
-{
- BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */
- union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */
- union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */
- BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
- BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */
+struct DpRam {
+ BYTE DpSram1[DP_SRAM1_SIZE]; /* 0000 - 7BFF */
+ union u_CtrlProm DpCtrlProm; /* 7C00 - 7DFF */
+ union u_Sram2ParmMap DpSram2ParmMap; /* 7E00 - 7FFF */
+ BYTE DpScratch[DP_SCRATCH_SIZE]; /* 8000 - 8FFF */
+ BYTE DpSram3[DP_SRAM3_SIZE]; /* 9000 - FFFF */
};
#define DpControl DpCtrlProm.DpCtrl.DpCtl
diff --git a/drivers/char/rio/bootpkt.h b/drivers/char/rio/bootpkt.h
index c329aeb7c871..602266e0c085 100644
--- a/drivers/char/rio/bootpkt.h
+++ b/drivers/char/rio/bootpkt.h
@@ -41,7 +41,7 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1" ;
+static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1";
#endif
#endif
@@ -49,14 +49,13 @@ static char *_rio_bootpkt_h_sccs = "@(#)bootpkt.h 1.1" ;
* Overlayed onto the Data fields of a regular
* Packet
************************************************/
-typedef struct BOOT_PKT BOOT_PKT ;
+typedef struct BOOT_PKT BOOT_PKT;
struct BOOT_PKT {
- short seq_num ;
- char data[10] ;
- } ;
+ short seq_num;
+ char data[10];
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/brates.h b/drivers/char/rio/brates.h
deleted file mode 100644
index bd4fc84ec6cf..000000000000
--- a/drivers/char/rio/brates.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* BRATES.H *******
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date : 1 Nov 1990
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _brates_h
-#ifndef lint
-/* static char * _brates_h_sccs = "@(#)brates.h 1.4"; */
-#endif
-#define _brates_h 1
-/* List of baud rate defines. Most are borrowed from /usr/include/sys/termio.h
-*/
-#ifndef INKERNEL
-
-#define B0 0x00
-#define B50 0x01
-#define B75 0x02
-#define B110 0x03
-#define B134 0x04
-#define B150 0x05
-#define B200 0x06
-#define B300 0x07
-#define B600 0x08
-#define B1200 0x09
-#define B1800 0x0a
-#define B2400 0x0b
-#define B4800 0x0c
-#define B9600 0x0d
-#define B19200 0x0e
-#define B38400 0x0f
-
-#endif
-
-/*
-** The following baudrates may or may not be defined
-** on various UNIX systems.
-** If they are not then we define them.
-** If they are then we do not define them ;-)
-**
-** This is appalling that we use same definitions as UNIX
-** for our own download code as there is no garuntee that
-** B57600 will be defined as 0x11 by a UNIX system....
-** Arghhhhh!!!!!!!!!!!!!!
-*/
-#if !defined(B56000)
-#define B56000 0x10
-#endif
-
-#if !defined(B57600)
-#define B57600 0x11
-#endif
-
-#if !defined(B64000)
-#define B64000 0x12
-#endif
-
-#if !defined(B115200)
-#define B115200 0x13
-#endif
-
-
-#if !defined(B2000)
-#define B2000 0x14
-#endif
-
-
-#define MAX_RATE B2000
-
-struct baud_rate /* Tag for baud rates */
-{
- /* short host_rate,*/ /* As passed by the driver */
- short divisor, /* The divisor */
- prescaler; /* The pre-scaler */
-};
-
-#endif
diff --git a/drivers/char/rio/chan.h b/drivers/char/rio/chan.h
deleted file mode 100644
index 5b306543328f..000000000000
--- a/drivers/char/rio/chan.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 _chan_h
-#define _chan_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_chan_h_sccs = "@(#)chan.h 1.1" ;
-#endif
-#endif
-
-#define Link0 0
-#define Link1 1
-#define Link2 2
-#define Link3 3
-
-#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
index cf056a990f18..217ff09f2fa1 100644
--- a/drivers/char/rio/cirrus.h
+++ b/drivers/char/rio/cirrus.h
@@ -73,20 +73,20 @@
#define TIMER_TICK 0x82
#define STOP_BREAK 0x83
#define BASE(a) ((a) < 4 ? (short*)CIRRUS_FIRST : ((a) < 8 ? (short *)CIRRUS_SECOND : ((a) < 12 ? (short*)CIRRUS_THIRD : (short *)CIRRUS_FOURTH)))
-#define txack1 ((short *)0x7104)
-#define rxack1 ((short *)0x7102)
+#define txack1 ((short *)0x7104)
+#define rxack1 ((short *)0x7102)
#define mdack1 ((short *)0x7106)
-#define txack2 ((short *)0x7006)
-#define rxack2 ((short *)0x7004)
-#define mdack2 ((short *)0x7100)
+#define txack2 ((short *)0x7006)
+#define rxack2 ((short *)0x7004)
+#define mdack2 ((short *)0x7100)
#define int_latch ((short *) 0x7800)
-#define int_status ((short *) 0x7c00)
-#define tx1_pending 0x20
-#define rx1_pending 0x10
-#define md1_pending 0x40
-#define tx2_pending 0x02
-#define rx2_pending 0x01
-#define md2_pending 0x40
+#define int_status ((short *) 0x7c00)
+#define tx1_pending 0x20
+#define rx1_pending 0x10
+#define md1_pending 0x40
+#define tx2_pending 0x02
+#define rx2_pending 0x01
+#define md2_pending 0x40
#define module1_bits 0x07
#define module1_modern 0x08
#define module2_bits 0x70
@@ -113,65 +113,65 @@
NB. These registers are relative values on 8 bit boundaries whereas
on the RTA's the CIRRUS registers are on word boundaries. Use pointer
arithmetic (short *) to obtain the real addresses required */
-#define ccr 0x05 /* Channel Command Register */
-#define ier 0x06 /* Interrupt Enable Register */
-#define cor1 0x08 /* Channel Option Register 1 */
-#define cor2 0x09 /* Channel Option Register 2 */
-#define cor3 0x0a /* Channel Option Register 3 */
-#define cor4 0x1e /* Channel Option Register 4 */
-#define cor5 0x1f /* Channel Option Register 5 */
-
-#define ccsr 0x0b /* Channel Control Status Register */
-#define rdcr 0x0e /* Receive Data Count Register */
-#define tdcr 0x12 /* Transmit Data Count Register */
-#define mcor1 0x15 /* Modem Change Option Register 1 */
-#define mcor2 0x16 /* Modem Change Option Regsiter 2 */
-
-#define livr 0x18 /* Local Interrupt Vector Register */
-#define schr1 0x1a /* Special Character Register 1 */
-#define schr2 0x1b /* Special Character Register 2 */
-#define schr3 0x1c /* Special Character Register 3 */
-#define schr4 0x1d /* Special Character Register 4 */
-
-#define rtr 0x20 /* Receive Timer Register */
-#define rtpr 0x21 /* Receive Timeout Period Register */
-#define lnc 0x24 /* Lnext character */
-
-#define rivr 0x43 /* Receive Interrupt Vector Register */
-#define tivr 0x42 /* Transmit Interrupt Vector Register */
-#define mivr 0x41 /* Modem Interrupt Vector Register */
-#define gfrcr 0x40 /* Global Firmware Revision code Reg */
-#define ricr 0x44 /* Receive Interrupting Channel Reg */
-#define ticr 0x45 /* Transmit Interrupting Channel Reg */
-#define micr 0x46 /* Modem Interrupting Channel Register */
-
-#define gcr 0x4b /* Global configuration register*/
-#define misr 0x4c /* Modem interrupt status register */
+#define ccr 0x05 /* Channel Command Register */
+#define ier 0x06 /* Interrupt Enable Register */
+#define cor1 0x08 /* Channel Option Register 1 */
+#define cor2 0x09 /* Channel Option Register 2 */
+#define cor3 0x0a /* Channel Option Register 3 */
+#define cor4 0x1e /* Channel Option Register 4 */
+#define cor5 0x1f /* Channel Option Register 5 */
+
+#define ccsr 0x0b /* Channel Control Status Register */
+#define rdcr 0x0e /* Receive Data Count Register */
+#define tdcr 0x12 /* Transmit Data Count Register */
+#define mcor1 0x15 /* Modem Change Option Register 1 */
+#define mcor2 0x16 /* Modem Change Option Regsiter 2 */
+
+#define livr 0x18 /* Local Interrupt Vector Register */
+#define schr1 0x1a /* Special Character Register 1 */
+#define schr2 0x1b /* Special Character Register 2 */
+#define schr3 0x1c /* Special Character Register 3 */
+#define schr4 0x1d /* Special Character Register 4 */
+
+#define rtr 0x20 /* Receive Timer Register */
+#define rtpr 0x21 /* Receive Timeout Period Register */
+#define lnc 0x24 /* Lnext character */
+
+#define rivr 0x43 /* Receive Interrupt Vector Register */
+#define tivr 0x42 /* Transmit Interrupt Vector Register */
+#define mivr 0x41 /* Modem Interrupt Vector Register */
+#define gfrcr 0x40 /* Global Firmware Revision code Reg */
+#define ricr 0x44 /* Receive Interrupting Channel Reg */
+#define ticr 0x45 /* Transmit Interrupting Channel Reg */
+#define micr 0x46 /* Modem Interrupting Channel Register */
+
+#define gcr 0x4b /* Global configuration register */
+#define misr 0x4c /* Modem interrupt status register */
#define rbusr 0x59
#define tbusr 0x5a
#define mbusr 0x5b
-#define eoir 0x60 /* End Of Interrupt Register */
-#define rdsr 0x62 /* Receive Data / Status Register */
-#define tdr 0x63 /* Transmit Data Register */
-#define svrr 0x67 /* Service Request Register */
+#define eoir 0x60 /* End Of Interrupt Register */
+#define rdsr 0x62 /* Receive Data / Status Register */
+#define tdr 0x63 /* Transmit Data Register */
+#define svrr 0x67 /* Service Request Register */
-#define car 0x68 /* Channel Access Register */
-#define mir 0x69 /* Modem Interrupt Register */
-#define tir 0x6a /* Transmit Interrupt Register */
-#define rir 0x6b /* Receive Interrupt Register */
-#define msvr1 0x6c /* Modem Signal Value Register 1 */
-#define msvr2 0x6d /* Modem Signal Value Register 2*/
-#define psvr 0x6f /* Printer Signal Value Register*/
+#define car 0x68 /* Channel Access Register */
+#define mir 0x69 /* Modem Interrupt Register */
+#define tir 0x6a /* Transmit Interrupt Register */
+#define rir 0x6b /* Receive Interrupt Register */
+#define msvr1 0x6c /* Modem Signal Value Register 1 */
+#define msvr2 0x6d /* Modem Signal Value Register 2 */
+#define psvr 0x6f /* Printer Signal Value Register */
-#define tbpr 0x72 /* Transmit Baud Rate Period Register */
-#define tcor 0x76 /* Transmit Clock Option Register */
+#define tbpr 0x72 /* Transmit Baud Rate Period Register */
+#define tcor 0x76 /* Transmit Clock Option Register */
-#define rbpr 0x78 /* Receive Baud Rate Period Register */
-#define rber 0x7a /* Receive Baud Rate Extension Register */
-#define rcor 0x7c /* Receive Clock Option Register*/
-#define ppr 0x7e /* Prescalar Period Register */
+#define rbpr 0x78 /* Receive Baud Rate Period Register */
+#define rber 0x7a /* Receive Baud Rate Extension Register */
+#define rcor 0x7c /* Receive Clock Option Register */
+#define ppr 0x7e /* Prescalar Period Register */
/* Misc registers used for forcing the 1400 out of its reset woes */
#define airl 0x6d
@@ -192,10 +192,10 @@
/* RDSR - when status read from FIFO */
#define RDSR_BREAK 0x08 /* Break received */
-#define RDSR_TIMEOUT 0x80 /* No new data timeout */
-#define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */
-#define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */
-#define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */
+#define RDSR_TIMEOUT 0x80 /* No new data timeout */
+#define RDSR_SC1 0x10 /* Special char 1 (tx XON) matched */
+#define RDSR_SC2 0x20 /* Special char 2 (tx XOFF) matched */
+#define RDSR_SC12_MASK 0x30 /* Mask for special chars 1 and 2 */
/* PPR */
#define PPR_DEFAULT 0x31 /* Default value - for a 25Mhz clock gives
@@ -244,7 +244,7 @@
#define IER_TIMEOUT 0x01 /* Timeout on no data */
#define IER_DEFAULT 0x94 /* Default values */
-#define IER_PARALLEL 0x84 /* Default for Parallel */
+#define IER_PARALLEL 0x84 /* Default for Parallel */
#define IER_EMPTY 0x92 /* Transmitter empty rather than ready */
/* COR1 - Driver only */
@@ -264,11 +264,11 @@
#define COR1_7BITS 0x02 /* 7 data bits */
#define COR1_8BITS 0x03 /* 8 data bits */
-#define COR1_HOST 0xef /* Safe host bits */
+#define COR1_HOST 0xef /* Safe host bits */
/* RTA only */
-#define COR1_CINPCK 0x00 /* Check parity of received characters */
-#define COR1_CNINPCK 0x10 /* Don't check parity */
+#define COR1_CINPCK 0x00 /* Check parity of received characters */
+#define COR1_CNINPCK 0x10 /* Don't check parity */
/* COR2 bits for both RTA and driver use */
#define COR2_IXANY 0x80 /* IXANY - any character is XON */
@@ -293,9 +293,9 @@
#define COR3_FCT 0x20 /* Flow control transparency */
#define COR3_SCD12 0x10 /* Special character detect for SCHR's 1 + 2 */
#define COR3_FIFO12 0x0c /* 12 chars for receive FIFO threshold */
-#define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
-#define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
-#define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
+#define COR3_FIFO10 0x0a /* 10 chars for receive FIFO threshold */
+#define COR3_FIFO8 0x08 /* 8 chars for receive FIFO threshold */
+#define COR3_FIFO6 0x06 /* 6 chars for receive FIFO threshold */
#define COR3_THRESHOLD COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */
@@ -386,7 +386,7 @@
#define MCOR_THRESHBITS 0x0F /* mask for ANDing out the above */
-#define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
+#define MCOR_THRESHOLD MCOR_THRESH9 /* MUST BE GREATER THAN COR3_THRESHOLD */
/* RTPR */
@@ -429,25 +429,25 @@
#define CONFIG 0x01 /* Configure a port */
#define MOPEN 0x02 /* Modem open (block for DCD) */
#define CLOSE 0x03 /* Close a port */
-#define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */
-#define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */
-#define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */
-#define SBREAK 0x07 /* Start break */
+#define WFLUSH (0x04 | PRE_EMPTIVE) /* Write flush */
+#define RFLUSH (0x05 | PRE_EMPTIVE) /* Read flush */
+#define RESUME (0x06 | PRE_EMPTIVE) /* Resume if xoffed */
+#define SBREAK 0x07 /* Start break */
#define EBREAK 0x08 /* End break */
-#define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
-#define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */
-#define XPRINT 0x0b /* Xprint packet */
-#define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */
-#define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */
-#define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */
+#define SUSPEND (0x09 | PRE_EMPTIVE) /* Susp op (behave as tho xoffed) */
+#define FCLOSE (0x0a | PRE_EMPTIVE) /* Force close */
+#define XPRINT 0x0b /* Xprint packet */
+#define MBIS (0x0c | PRE_EMPTIVE) /* Set modem lines */
+#define MBIC (0x0d | PRE_EMPTIVE) /* Clear modem lines */
+#define MSET (0x0e | PRE_EMPTIVE) /* Set modem lines */
#define PCLOSE 0x0f /* Pseudo close - Leaves rx/tx enabled */
-#define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */
-#define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
-#define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
+#define MGET (0x10 | PRE_EMPTIVE) /* Force update of modem status */
+#define MEMDUMP (0x11 | PRE_EMPTIVE) /* Send back mem from addr supplied */
+#define READ_REGISTER (0x12 | PRE_EMPTIVE) /* Read CD1400 register (debug) */
/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
use data[4] / data[3] to indicate current state and modem status respectively
-*/
+*/
#define COMPLETE (0x20 | PRE_EMPTIVE)
/* Command complete */
diff --git a/drivers/char/rio/cmd.h b/drivers/char/rio/cmd.h
deleted file mode 100644
index c369edaea2b3..000000000000
--- a/drivers/char/rio/cmd.h
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* C O M M A N D P A C K E T H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef _cmd_h
-#define _cmd_h
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_cmd_h_sccs = "@(#)cmd.h 1.1" ;
-#endif
-#endif
-
-
-#define PRE_EMPTIVE_CMD 0x80
-#define INLINE_CMD ~PRE_EMPTIVE_CMD
-
-#define CMD_IGNORE_PKT ( (ushort) 0)
-#define CMD_STATUS_REQ ( (ushort) 1)
-#define CMD_UNIT_STATUS_REQ ( (ushort) 2) /* Is this needed ??? */
-#define CMD_CONF_PORT ( (ushort) 3)
-#define CMD_CONF_UNIT ( (ushort) 4)
-#define CMD_ROUTE_MAP_REQ ( (ushort) 5)
-#define CMD_FLUSH_TX ( (ushort) 6)
-#define CMD_FLUSH_RX ( (ushort) 7)
-#define CMD_PARTION_PORT ( (ushort) 8)
-#define CMD_RESET_PORT ( (ushort) 0x0a)
-#define CMD_BOOT_UNIT ( (ushort) 0x0b)
-#define CMD_FOUND_UNIT ( (ushort) 0x0c)
-#define CMD_ATTACHED_RTA_2 ( (ushort) 0x0d)
-#define CMD_PROVIDE_BOOT ( (ushort) 0x0e)
-#define CMD_CIRRUS ( (ushort) 0x0f)
-
-#define FORM_STATUS_PKT ( (ushort) 1 )
-#define FORM_POLL_PKT ( (ushort) 2 )
-#define FORM_LINK_STATUS_PKT ( (ushort) 3 )
-
-
-#define CMD_DATA_PORT ( (ushort) 1 )
-#define CMD_DATA ( (ushort) 2 )
-
-#define CMD_TX_PART ( (ushort) 2 )
-#define CMD_RX_PART ( (ushort) 3 )
-#define CMD_RX_LIMIT ( (ushort) 4 )
-
-#endif
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h
index 2b8efbdbee1c..a9a8c45631d7 100644
--- a/drivers/char/rio/cmdblk.h
+++ b/drivers/char/rio/cmdblk.h
@@ -44,16 +44,15 @@ static char *_cmdblk_h_sccs_ = "@(#)cmdblk.h 1.2";
** a rup.
*/
-struct CmdBlk
-{
- struct CmdBlk *NextP; /* Pointer to next command block */
- struct PKT Packet; /* A packet, to copy to the rup */
- /* The func to call to check if OK */
- int (*PreFuncP)(int, struct CmdBlk *);
- int PreArg; /* The arg for the func */
- /* The func to call when completed */
- int (*PostFuncP)(int, struct CmdBlk *);
- int PostArg; /* The arg for the func */
+struct CmdBlk {
+ struct CmdBlk *NextP; /* Pointer to next command block */
+ struct PKT Packet; /* A packet, to copy to the rup */
+ /* The func to call to check if OK */
+ int (*PreFuncP) (int, struct CmdBlk *);
+ int PreArg; /* The arg for the func */
+ /* The func to call when completed */
+ int (*PostFuncP) (int, struct CmdBlk *);
+ int PostArg; /* The arg for the func */
};
#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h
index 46befd354f20..77cee8df68ef 100644
--- a/drivers/char/rio/cmdpkt.h
+++ b/drivers/char/rio/cmdpkt.h
@@ -54,135 +54,112 @@ static char *_cmdpkt_h_sccs_ = "@(#)cmdpkt.h 1.2";
** This structure overlays a PktCmd->CmdData structure, and so starts
** at Data[2] in the actual pkt!
*/
-struct BootSequence
-{
- WORD NumPackets;
- WORD LoadBase;
- WORD CodeSize;
+struct BootSequence {
+ WORD NumPackets;
+ WORD LoadBase;
+ WORD CodeSize;
};
#define BOOT_SEQUENCE_LEN 8
-struct SamTop
-{
- BYTE Unit;
- BYTE Link;
+struct SamTop {
+ BYTE Unit;
+ BYTE Link;
};
-struct CmdHdr
-{
- BYTE PcCommand;
- union
- {
- BYTE PcPhbNum;
- BYTE PcLinkNum;
- BYTE PcIDNum;
- } U0;
+struct CmdHdr {
+ BYTE PcCommand;
+ union {
+ BYTE PcPhbNum;
+ BYTE PcLinkNum;
+ BYTE PcIDNum;
+ } U0;
};
-struct PktCmd
-{
- union
- {
- struct
- {
- struct CmdHdr CmdHdr;
- struct BootSequence PcBootSequence;
- } S1;
- struct
- {
- WORD PcSequence;
- BYTE PcBootData[RTA_BOOT_DATA_SIZE];
- } S2;
- struct
- {
- WORD __crud__;
- BYTE PcUniqNum[4]; /* this is really a uint. */
- BYTE PcModuleTypes; /* what modules are fitted */
- } S3;
- struct
- {
- struct CmdHdr CmdHdr;
- BYTE __undefined__;
- BYTE PcModemStatus;
- BYTE PcPortStatus;
- BYTE PcSubCommand; /* commands like mem or register dump */
- WORD PcSubAddr; /* Address for command */
- BYTE PcSubData[64]; /* Date area for command */
- } S4;
- struct
- {
- struct CmdHdr CmdHdr;
- BYTE PcCommandText[1];
- BYTE __crud__[20];
- BYTE PcIDNum2; /* It had to go somewhere! */
- } S5;
- struct
- {
- struct CmdHdr CmdHdr;
- struct SamTop Topology[LINKS_PER_UNIT];
- } S6;
- } U1;
+struct PktCmd {
+ union {
+ struct {
+ struct CmdHdr CmdHdr;
+ struct BootSequence PcBootSequence;
+ } S1;
+ struct {
+ WORD PcSequence;
+ BYTE PcBootData[RTA_BOOT_DATA_SIZE];
+ } S2;
+ struct {
+ WORD __crud__;
+ BYTE PcUniqNum[4]; /* this is really a uint. */
+ BYTE PcModuleTypes; /* what modules are fitted */
+ } S3;
+ struct {
+ struct CmdHdr CmdHdr;
+ BYTE __undefined__;
+ BYTE PcModemStatus;
+ BYTE PcPortStatus;
+ BYTE PcSubCommand; /* commands like mem or register dump */
+ WORD PcSubAddr; /* Address for command */
+ BYTE PcSubData[64]; /* Date area for command */
+ } S4;
+ struct {
+ struct CmdHdr CmdHdr;
+ BYTE PcCommandText[1];
+ BYTE __crud__[20];
+ BYTE PcIDNum2; /* It had to go somewhere! */
+ } S5;
+ struct {
+ struct CmdHdr CmdHdr;
+ struct SamTop Topology[LINKS_PER_UNIT];
+ } S6;
+ } U1;
};
-struct PktCmd_M
-{
- union
- {
- struct
- {
- struct
- {
- uchar PcCommand;
- union
- {
- uchar PcPhbNum;
- uchar PcLinkNum;
- uchar PcIDNum;
- } U0;
- } CmdHdr;
- struct
- {
- ushort NumPackets;
- ushort LoadBase;
- ushort CodeSize;
- } PcBootSequence;
- } S1;
- struct
- {
- ushort PcSequence;
- uchar PcBootData[RTA_BOOT_DATA_SIZE];
- } S2;
- struct
- {
- ushort __crud__;
- uchar PcUniqNum[4]; /* this is really a uint. */
- uchar PcModuleTypes; /* what modules are fitted */
- } S3;
- struct
- {
- ushort __cmd_hdr__;
- uchar __undefined__;
- uchar PcModemStatus;
- uchar PcPortStatus;
- uchar PcSubCommand;
- ushort PcSubAddr;
- uchar PcSubData[64];
- } S4;
- struct
- {
- ushort __cmd_hdr__;
- uchar PcCommandText[1];
- uchar __crud__[20];
- uchar PcIDNum2; /* Tacked on end */
- } S5;
- struct
- {
- ushort __cmd_hdr__;
- struct Top Topology[LINKS_PER_UNIT];
- } S6;
- } U1;
+struct PktCmd_M {
+ union {
+ struct {
+ struct {
+ uchar PcCommand;
+ union {
+ uchar PcPhbNum;
+ uchar PcLinkNum;
+ uchar PcIDNum;
+ } U0;
+ } CmdHdr;
+ struct {
+ ushort NumPackets;
+ ushort LoadBase;
+ ushort CodeSize;
+ } PcBootSequence;
+ } S1;
+ struct {
+ ushort PcSequence;
+ uchar PcBootData[RTA_BOOT_DATA_SIZE];
+ } S2;
+ struct {
+ ushort __crud__;
+ uchar PcUniqNum[4]; /* this is really a uint. */
+ uchar PcModuleTypes; /* what modules are fitted */
+ } S3;
+ struct {
+ ushort __cmd_hdr__;
+ uchar __undefined__;
+ uchar PcModemStatus;
+ uchar PcPortStatus;
+ uchar PcSubCommand;
+ ushort PcSubAddr;
+ uchar PcSubData[64];
+ } S4;
+ struct {
+ ushort __cmd_hdr__;
+ uchar PcCommandText[1];
+ uchar __crud__[20];
+ uchar PcIDNum2; /* Tacked on end */
+ } S5;
+ struct {
+ ushort __cmd_hdr__;
+ struct Top Topology[LINKS_PER_UNIT];
+ } S6;
+ } U1;
};
#define Command U1.S1.CmdHdr.PcCommand
diff --git a/drivers/char/rio/control.h b/drivers/char/rio/control.h
index 1712f6261dd1..6853d03304a3 100644
--- a/drivers/char/rio/control.h
+++ b/drivers/char/rio/control.h
@@ -51,12 +51,11 @@
#define UFOAD ( CONTROL + 4 )
#define IWAIT ( CONTROL + 5 )
-#define IFOAD_MAGIC 0xF0AD /* of course */
+#define IFOAD_MAGIC 0xF0AD /* of course */
#define ZOMBIE_MAGIC (~0xDEAD) /* not dead -> zombie */
-#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */
-#define IWAIT_MAGIC 0xB1DE /* Bide your time */
+#define UFOAD_MAGIC 0xD1E /* kill-your-neighbour */
+#define IWAIT_MAGIC 0xB1DE /* Bide your time */
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h
index 62dba0e68b3e..28a991bd4fe6 100644
--- a/drivers/char/rio/daemon.h
+++ b/drivers/char/rio/daemon.h
@@ -44,18 +44,16 @@ static char *_daemon_h_sccs_ = "@(#)daemon.h 1.3";
** structures used on /dev/rio
*/
-struct Error
-{
- uint Error;
- uint Entry;
- uint Other;
+struct Error {
+ uint Error;
+ uint Entry;
+ uint Other;
};
-struct DownLoad
-{
- char *DataP;
- uint Count;
- uint ProductCode;
+struct DownLoad {
+ char *DataP;
+ uint Count;
+ uint ProductCode;
};
/*
@@ -66,46 +64,41 @@ struct DownLoad
#endif
#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */
+#define MAX_XP_CTRL_LEN 16 /* ALSO IN PORT.H */
#endif
-struct PortSetup
-{
- uint From; /* Set/Clear XP & IXANY Control from this port.... */
- uint To; /* .... to this port */
- uint XpCps; /* at this speed */
- char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */
- char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */
- uchar IxAny; /* enable/disable IXANY */
- uchar IxOn; /* enable/disable IXON */
- uchar Lock; /* lock port params */
- uchar Store; /* store params across closes */
- uchar Drain; /* close only when drained */
+struct PortSetup {
+ uint From; /* Set/Clear XP & IXANY Control from this port.... */
+ uint To; /* .... to this port */
+ uint XpCps; /* at this speed */
+ char XpOn[MAX_XP_CTRL_LEN]; /* this is the start string */
+ char XpOff[MAX_XP_CTRL_LEN]; /* this is the stop string */
+ uchar IxAny; /* enable/disable IXANY */
+ uchar IxOn; /* enable/disable IXON */
+ uchar Lock; /* lock port params */
+ uchar Store; /* store params across closes */
+ uchar Drain; /* close only when drained */
};
-struct LpbReq
-{
- uint Host;
- uint Link;
- struct LPB *LpbP;
+struct LpbReq {
+ uint Host;
+ uint Link;
+ struct LPB *LpbP;
};
-struct RupReq
-{
- uint HostNum;
- uint RupNum;
- struct RUP *RupP;
+struct RupReq {
+ uint HostNum;
+ uint RupNum;
+ struct RUP *RupP;
};
-struct PortReq
-{
- uint SysPort;
- struct Port *PortP;
+struct PortReq {
+ uint SysPort;
+ struct Port *PortP;
};
-struct StreamInfo
-{
- uint SysPort;
+struct StreamInfo {
+ uint SysPort;
#if 0
queue_t RQueue;
queue_t WQueue;
@@ -115,68 +108,59 @@ struct StreamInfo
#endif
};
-struct HostReq
-{
- uint HostNum;
- struct Host *HostP;
+struct HostReq {
+ uint HostNum;
+ struct Host *HostP;
};
-struct HostDpRam
-{
- uint HostNum;
- struct DpRam *DpRamP;
+struct HostDpRam {
+ uint HostNum;
+ struct DpRam *DpRamP;
};
-struct DebugCtrl
-{
- uint SysPort;
- uint Debug;
- uint Wait;
+struct DebugCtrl {
+ uint SysPort;
+ uint Debug;
+ uint Wait;
};
-struct MapInfo
-{
- uint FirstPort; /* 8 ports, starting from this (tty) number */
- uint RtaUnique; /* reside on this RTA (unique number) */
+struct MapInfo {
+ uint FirstPort; /* 8 ports, starting from this (tty) number */
+ uint RtaUnique; /* reside on this RTA (unique number) */
};
-struct MapIn
-{
- uint NumEntries; /* How many port sets are we mapping? */
- struct MapInfo *MapInfoP; /* Pointer to (user space) info */
+struct MapIn {
+ uint NumEntries; /* How many port sets are we mapping? */
+ struct MapInfo *MapInfoP; /* Pointer to (user space) info */
};
-struct SendPack
-{
- unsigned int PortNum;
- unsigned char Len;
- unsigned char Data[PKT_MAX_DATA_LEN];
+struct SendPack {
+ unsigned int PortNum;
+ unsigned char Len;
+ unsigned char Data[PKT_MAX_DATA_LEN];
};
-struct SpecialRupCmd
-{
- struct PKT Packet;
- unsigned short Host;
- unsigned short RupNum;
+struct SpecialRupCmd {
+ struct PKT Packet;
+ unsigned short Host;
+ unsigned short RupNum;
};
-struct IdentifyRta
-{
- ulong RtaUnique;
- uchar ID;
+struct IdentifyRta {
+ ulong RtaUnique;
+ uchar ID;
};
-struct KillNeighbour
-{
- ulong UniqueNum;
- uchar Link;
+struct KillNeighbour {
+ ulong UniqueNum;
+ uchar Link;
};
struct rioVersion {
- char version[MAX_VERSION_LEN];
- char relid[MAX_VERSION_LEN];
- int buildLevel;
- char buildDate[MAX_VERSION_LEN];
+ char version[MAX_VERSION_LEN];
+ char relid[MAX_VERSION_LEN];
+ int buildLevel;
+ char buildDate[MAX_VERSION_LEN];
};
@@ -316,16 +300,16 @@ struct rioVersion {
#define RIO_SET_XP_CPS rIOCW(155,int)
#define RIO_GET_IXANY rIOCR(156,int) /* ixany allowed? */
#define RIO_SET_IXANY rIOCW(157,int)
-#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */
-#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */
+#define RIO_SET_IXANY_ON rIOCN(158) /* allow ixany */
+#define RIO_SET_IXANY_OFF rIOCN(159) /* disallow ixany */
#define RIO_GET_MODEM rIOCR(160,int) /* port is modem/direct line? */
#define RIO_SET_MODEM rIOCW(161,int)
-#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */
-#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */
+#define RIO_SET_MODEM_ON rIOCN(162) /* port is a modem */
+#define RIO_SET_MODEM_OFF rIOCN(163) /* port is direct */
#define RIO_GET_IXON rIOCR(164,int) /* ixon allowed? */
#define RIO_SET_IXON rIOCW(165,int)
-#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */
-#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */
+#define RIO_SET_IXON_ON rIOCN(166) /* allow ixon */
+#define RIO_SET_IXON_OFF rIOCN(167) /* disallow ixon */
#define RIO_GET_SIVIEW ((('s')<<8) | 106) /* backwards compatible with SI */
diff --git a/drivers/char/rio/data.h b/drivers/char/rio/data.h
deleted file mode 100644
index dabc2d1fa40f..000000000000
--- a/drivers/char/rio/data.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : data.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:09
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)data.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_datadex__
-#define __rio_datadex__
-
-#ifndef lint
-static char *_data_h_sccs_ = "@(#)data.h 1.2";
-#endif
-
-#endif
diff --git a/drivers/char/rio/debug.h b/drivers/char/rio/debug.h
deleted file mode 100644
index b6e0d0935552..000000000000
--- a/drivers/char/rio/debug.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-** File: debug.h
-**
-** Author: David Dix
-**
-** Created: 12th March 1993
-**
-** Last modified: 93/04/27
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 _debug_h_
-#define _debug_h_
-
-
-#if defined(DCIRRUS)
-#define DBPACKET(pkt, opt, str, chn) debug_packet((pkt), (opt), (str), (chn))
-#else
-#define DBPACKET(pkt, opt, str, c)
-#endif /* DCIRRUS */
-
-
-#endif /* _debug_h_ */
diff --git a/drivers/char/rio/defaults.h b/drivers/char/rio/defaults.h
index 2e7309e27622..5b600c32ac02 100644
--- a/drivers/char/rio/defaults.h
+++ b/drivers/char/rio/defaults.h
@@ -37,13 +37,13 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1" ;
+static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1";
#endif
#endif
-#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
-#define SECOND (int) 15625 /* Low priority ticks */
+#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
+#define SECOND (int) 15625 /* Low priority ticks */
#ifdef RTA
#define RX_LIMIT (ushort) 3
@@ -56,4 +56,3 @@ static char *_rio_defaults_h_sccs = "@(#)defaults.h 1.1" ;
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/eisa.h b/drivers/char/rio/eisa.h
deleted file mode 100644
index 59371b0528b0..000000000000
--- a/drivers/char/rio/eisa.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : eisa.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:10
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)eisa.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_eisa_h__
-#define __rio_eisa_h__
-
-#ifdef SCCS_LABELS
-#ifndef lint
-static char *_eisa_h_sccs_ = "@(#)eisa.h 1.2";
-#endif
-#endif
-
-/*
-** things to do with the EISA bus
-*/
-
-#define RIO_EISA_STRING_ADDRESS 0xfffd9 /* where EISA is stored */
-
-#define RIO_MAX_EISA_SLOTS 16 /* how many EISA slots? */
-
-#define RIO_EISA_IDENT 0x984D /* Specialix */
-#define RIO_EISA_PRODUCT_CODE 0x14 /* Code 14 */
-#define RIO_EISA_ENABLE_BIT 0x01 /* To enable card */
-
-#define EISA_MEMORY_BASE_LO 0xC00 /* A16-A23 */
-#define EISA_MEMORY_BASE_HI 0xC01 /* A24-A31 */
-#define EISA_INTERRUPT_VEC 0xC02 /* see below */
-#define EISA_CONTROL_PORT 0xC02 /* see below */
-#define EISA_INTERRUPT_RESET 0xC03 /* read to clear IRQ */
-
-#define EISA_PRODUCT_IDENT_LO 0xC80 /* where RIO_EISA_IDENT is */
-#define EISA_PRODUCT_IDENT_HI 0xC81
-#define EISA_PRODUCT_NUMBER 0xC82 /* where PROD_CODE is */
-#define EISA_REVISION_NUMBER 0xC83 /* revision (1dp) */
-#define EISA_ENABLE 0xC84 /* set LSB to enable card */
-#define EISA_UNIQUE_NUM_0 0xC88 /* vomit */
-#define EISA_UNIQUE_NUM_1 0xC8A
-#define EISA_UNIQUE_NUM_2 0xC90 /* bit strangely arranged */
-#define EISA_UNIQUE_NUM_3 0xC92
-#define EISA_MANUF_YEAR 0xC98 /* when */
-#define EISA_MANUF_WEEK 0xC9A /* more when */
-
-#define EISA_TP_BOOT_FROM_RAM 0x01
-#define EISA_TP_BOOT_FROM_LINK 0x00
-#define EISA_TP_FAST_LINKS 0x02
-#define EISA_TP_SLOW_LINKS 0x00
-#define EISA_TP_BUS_ENABLE 0x04
-#define EISA_TP_BUS_DISABLE 0x00
-#define EISA_TP_RUN 0x08
-#define EISA_TP_RESET 0x00
-#define EISA_POLLED 0x00
-#define EISA_IRQ_3 0x30
-#define EISA_IRQ_4 0x40
-#define EISA_IRQ_5 0x50
-#define EISA_IRQ_6 0x60
-#define EISA_IRQ_7 0x70
-#define EISA_IRQ_9 0x90
-#define EISA_IRQ_10 0xA0
-#define EISA_IRQ_11 0xB0
-#define EISA_IRQ_12 0xC0
-#define EISA_IRQ_14 0xE0
-#define EISA_IRQ_15 0xF0
-
-#define EISA_INTERRUPT_MASK 0xF0
-#define EISA_CONTROL_MASK 0x0F
-
-#define RIO_EISA_DEFAULT_MODE EISA_TP_SLOW_LINKS
-
-#define RIOEisaToIvec(X) (uchar )((uchar)((X) & EISA_INTERRUPT_MASK)>>4)
-
-#define INBZ(z,x) inb(((z)<<12) | (x))
-#define OUTBZ(z,x,y) outb((((z)<<12) | (x)), y)
-
-#endif /* __rio_eisa_h__ */
diff --git a/drivers/char/rio/enable.h b/drivers/char/rio/enable.h
deleted file mode 100644
index 8e9a419e15b0..000000000000
--- a/drivers/char/rio/enable.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* E N A B L E H E A D E R S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_enable_h_sccs = "@(#)enable.h 1.1" ;
-#endif
-#endif
-
-
-#define ENABLE_LTT TRUE
-#define ENABLE_LRT TRUE
-
-
-/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/error.h b/drivers/char/rio/error.h
index 229438e355f2..f20f0789db8f 100644
--- a/drivers/char/rio/error.h
+++ b/drivers/char/rio/error.h
@@ -80,6 +80,3 @@
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h
index f920b9f3e2bd..1d0d89144337 100644
--- a/drivers/char/rio/errors.h
+++ b/drivers/char/rio/errors.h
@@ -101,4 +101,4 @@ static char *_errors_h_sccs_ = "@(#)errors.h 1.2";
#define NOT_ENOUGH_CORE_FOR_PCI_COPY 53
-#endif /* __rio_errors_h__ */
+#endif /* __rio_errors_h__ */
diff --git a/drivers/char/rio/formpkt.h b/drivers/char/rio/formpkt.h
deleted file mode 100644
index a8b65ae0de90..000000000000
--- a/drivers/char/rio/formpkt.h
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-/****************************************************************************
- ******* *******
- ******* F O R M P A C K E T H E A D E R F I L E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _formpkt_h
-#define _formpkt_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_formpkt_h_sccs = "@(#)formpkt.h 1.1" ;
-#endif
-#endif
-
-typedef struct FORM_BOOT_PKT_1 FORM_BOOT_PKT_1 ;
-struct FORM_BOOT_PKT_1 {
- ushort pkt_number ;
- ushort pkt_total ;
- ushort boot_top ;
- } ;
-
-typedef struct FORM_BOOT_PKT_2 FORM_BOOT_PKT_2 ;
-struct FORM_BOOT_PKT_2 {
- ushort pkt_number ;
- char boot_data[10] ;
- } ;
-
-
-typedef struct FORM_ATTACH_RTA FORM_ATTACH_RTA ;
-struct FORM_ATTACH_RTA {
- char cmd_code ;
- char booter_serial[4] ;
- char booter_link ;
- char bootee_serial[4] ;
- char bootee_link ;
- } ;
-
-
-typedef struct FORM_BOOT_ID FORM_BOOT_ID ;
-struct FORM_BOOT_ID {
- char cmd_code ;
- char bootee_serial[4] ;
- char bootee_prod_id ;
- char bootee_link ;
- } ;
-
-
-
-typedef struct FORM_ROUTE_1 FORM_ROUTE_1 ;
-struct FORM_ROUTE_1 {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char unit_id ;
- char host_unit_id ;
- } ;
-
-typedef struct FORM_ROUTE_2 FORM_ROUTE_2 ;
-struct FORM_ROUTE_2 {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char route_data[9] ;
- } ;
-
-typedef struct FORM_ROUTE_REQ FORM_ROUTE_REQ ;
-struct FORM_ROUTE_REQ {
- char cmd_code ;
- char pkt_number ;
- char total_in_sequence ;
- char route_data[10] ;
- } ;
-
-
-typedef struct FORM_ERROR FORM_ERROR ;
-struct FORM_ERROR {
- char cmd_code ;
- char error_code ;
-
- } ;
-
-typedef struct FORM_STATUS FORM_STATUS ;
-struct FORM_STATUS {
- char cmd_code ;
- char status_code ;
- char last_packet_valid ;
- char tx_buffer ;
- char rx_buffer ;
- char port_status ;
- char phb_status ;
- } ;
-
-
-typedef struct FORM_LINK_STATUS FORM_LINK_STATUS ;
-struct FORM_LINK_STATUS {
- char cmd_code ;
- char status_code ;
- char link_number ;
- ushort rx_errors ;
- ushort tx_errors ;
- ushort csum_errors ;
- ushort disconnects ;
- } ;
-
-
-
-typedef struct FORM_PARTITION FORM_PARTITION ;
-struct FORM_PARTITION {
- char cmd_code ;
- char status_code ;
- char port_number ;
- char tx_max ;
- char rx_max ;
- char rx_limit ;
- } ;
-
-
-#endif
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index 01987c6dc398..b4778410ec6e 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -47,20 +47,19 @@ int RIOBootCodeHOST(struct rio_info *, register struct DownLoad *);
int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
void msec_timeout(struct Host *);
int RIOBootRup(struct rio_info *, uint, struct Host *, struct PKT *);
-int RIOBootOk(struct rio_info *,struct Host *, ulong);
-int RIORtaBound(struct rio_info *, uint);
+int RIOBootOk(struct rio_info *, struct Host *, ulong);
+int RIORtaBound(struct rio_info *, uint);
void FillSlot(int, int, uint, struct Host *);
/* riocmd.c */
int RIOFoadRta(struct Host *, struct Map *);
int RIOZombieRta(struct Host *, struct Map *);
-int RIOCommandRta(struct rio_info *, uint, int (* func)( struct Host *,
- struct Map *));
-int RIOIdentifyRta(struct rio_info *, caddr_t);
+int RIOCommandRta(struct rio_info *, uint, int (*func) (struct Host *, struct Map *));
+int RIOIdentifyRta(struct rio_info *, caddr_t);
int RIOKillNeighbour(struct rio_info *, caddr_t);
int RIOSuspendBootRta(struct Host *, int, int);
int RIOFoadWakeup(struct rio_info *);
-struct CmdBlk * RIOGetCmdBlk(void);
+struct CmdBlk *RIOGetCmdBlk(void);
void RIOFreeCmdBlk(struct CmdBlk *);
int RIOQueueCmdBlk(struct Host *, uint, struct CmdBlk *);
void RIOPollHostCommands(struct rio_info *, struct Host *);
@@ -71,13 +70,13 @@ void ShowPacket(uint, struct PKT *);
/* rioctrl.c */
int copyin(int, caddr_t, int);
-int riocontrol(struct rio_info *, dev_t,int,caddr_t,int);
-int RIOPreemptiveCmd(struct rio_info *,struct Port *,uchar);
+int riocontrol(struct rio_info *, dev_t, int, caddr_t, int);
+int RIOPreemptiveCmd(struct rio_info *, struct Port *, uchar);
/* rioinit.c */
void rioinit(struct rio_info *, struct RioHostInfo *);
void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
-void RIOISAinit(struct rio_info *,int);
+void RIOISAinit(struct rio_info *, int);
int RIODoAT(struct rio_info *, int, int);
caddr_t RIOCheckForATCard(int);
int RIOAssignAT(struct rio_info *, int, caddr_t, int);
@@ -85,7 +84,7 @@ int RIOBoardTest(paddr_t, caddr_t, uchar, int);
void RIOAllocDataStructs(struct rio_info *);
void RIOSetupDataStructs(struct rio_info *);
int RIODefaultName(struct rio_info *, struct Host *, uint);
-struct rioVersion * RIOVersid(void);
+struct rioVersion *RIOVersid(void);
int RIOMapin(paddr_t, int, caddr_t *);
void RIOMapout(paddr_t, long, caddr_t);
void RIOHostReset(uint, volatile struct DpRam *, uint);
@@ -108,7 +107,7 @@ void remove_receive(struct Port *);
/* rioroute.c */
int RIORouteRup(struct rio_info *, uint, struct Host *, struct PKT *);
-void RIOFixPhbs(struct rio_info *, struct Host *, uint);
+void RIOFixPhbs(struct rio_info *, struct Host *, uint);
uint GetUnitType(uint);
int RIOSetChange(struct rio_info *);
int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
@@ -116,9 +115,9 @@ int RIOFindFreeID(struct rio_info *, struct Host *, uint *, uint *);
/* riotty.c */
-int riotopen(struct tty_struct * tty, struct file * filp);
-int riotclose(void *ptr);
-int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t);
+int riotopen(struct tty_struct *tty, struct file *filp);
+int riotclose(void *ptr);
+int riotioctl(struct rio_info *, struct tty_struct *, register int, register caddr_t);
void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
/* riotable.c */
@@ -127,27 +126,27 @@ int RIOApel(struct rio_info *);
int RIODeleteRta(struct rio_info *, struct Map *);
int RIOAssignRta(struct rio_info *, struct Map *);
int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
-int RIOChangeName(struct rio_info *, struct Map*);
+int RIOChangeName(struct rio_info *, struct Map *);
#if 0
/* riodrvr.c */
-struct rio_info * rio_install(struct RioHostInfo *);
+struct rio_info *rio_install(struct RioHostInfo *);
int rio_uninstall(register struct rio_info *);
int rio_open(struct rio_info *, int, struct file *);
int rio_close(struct rio_info *, struct file *);
int rio_read(struct rio_info *, struct file *, char *, int);
-int rio_write(struct rio_info *, struct file * f, char *, int);
+int rio_write(struct rio_info *, struct file *f, char *, int);
int rio_ioctl(struct rio_info *, struct file *, int, char *);
-int rio_select(struct rio_info *, struct file * f, int, struct sel *);
-int rio_intr(char *);
-int rio_isr_thread(char *);
-struct rio_info * rio_info_store( int cmd, struct rio_info * p);
+int rio_select(struct rio_info *, struct file *f, int, struct sel *);
+int rio_intr(char *);
+int rio_isr_thread(char *);
+struct rio_info *rio_info_store(int cmd, struct rio_info *p);
#endif
-extern int rio_pcicopy(char *src, char *dst, int n);
-extern int rio_minor (struct tty_struct *tty);
-extern int rio_ismodem (struct tty_struct *tty);
+extern int rio_pcicopy(char *src, char *dst, int n);
+extern int rio_minor(struct tty_struct *tty);
+extern int rio_ismodem(struct tty_struct *tty);
-extern void rio_start_card_running (struct Host * HostP);
+extern void rio_start_card_running(struct Host *HostP);
-#endif /* __func_h_def */
+#endif /* __func_h_def */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 4c65963870a4..f7dfcedf7d45 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -49,33 +49,32 @@ static char *_host_h_sccs_ = "@(#)host.h 1.2";
** Host data structure. This is used for the software equiv. of
** the host.
*/
-struct Host
-{
- uchar Type; /* RIO_EISA, RIO_MCA, ... */
- uchar Ivec; /* POLLED or ivec number */
- uchar Mode; /* Control stuff */
- uchar Slot; /* Slot */
- volatile caddr_t Caddr; /* KV address of DPRAM */
- volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
- paddr_t PaddrP; /* Phys. address of DPRAM */
- char Name[MAX_NAME_LEN]; /* The name of the host */
- uint UniqueNum; /* host unique number */
- spinlock_t HostLock; /* Lock structure for MPX */
- /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
- /*struct lockb HostLock; *//* Lock structure for MPX */
- uint WorkToBeDone; /* set to true each interrupt */
- uint InIntr; /* Being serviced? */
- uint IntSrvDone;/* host's interrupt has been serviced */
- int (*Copy)( caddr_t, caddr_t, int ); /* copy func */
- struct timer_list timer;
- /*
- ** I M P O R T A N T !
- **
- ** The rest of this data structure is cleared to zero after
- ** a RIO_HOST_FOAD command.
- */
-
- ulong Flags; /* Whats going down */
+struct Host {
+ uchar Type; /* RIO_EISA, RIO_MCA, ... */
+ uchar Ivec; /* POLLED or ivec number */
+ uchar Mode; /* Control stuff */
+ uchar Slot; /* Slot */
+ volatile caddr_t Caddr; /* KV address of DPRAM */
+ volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */
+ paddr_t PaddrP; /* Phys. address of DPRAM */
+ char Name[MAX_NAME_LEN]; /* The name of the host */
+ uint UniqueNum; /* host unique number */
+ spinlock_t HostLock; /* Lock structure for MPX */
+ /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */
+ /*struct lockb HostLock; *//* Lock structure for MPX */
+ uint WorkToBeDone; /* set to true each interrupt */
+ uint InIntr; /* Being serviced? */
+ uint IntSrvDone; /* host's interrupt has been serviced */
+ int (*Copy) (caddr_t, caddr_t, int); /* copy func */
+ struct timer_list timer;
+ /*
+ ** I M P O R T A N T !
+ **
+ ** The rest of this data structure is cleared to zero after
+ ** a RIO_HOST_FOAD command.
+ */
+
+ ulong Flags; /* Whats going down */
#define RC_WAITING 0
#define RC_STARTUP 1
#define RC_RUNNING 2
@@ -93,25 +92,25 @@ struct Host
#define RC_BOOT_OWN 0x10 /* Only boot RTAs bound to this system */
#define RC_BOOT_NONE 0x20 /* Don't boot any RTAs (slave mode) */
- struct Top Topology[LINKS_PER_UNIT]; /* one per link */
- struct Map Mapping[MAX_RUP]; /* Mappings for host */
- struct PHB *PhbP; /* Pointer to the PHB array */
- ushort *PhbNumP; /* Ptr to Number of PHB's */
- struct LPB *LinkStrP ; /* Link Structure Array */
- struct RUP *RupP; /* Sixteen real rups here */
- struct PARM_MAP *ParmMapP; /* points to the parmmap */
- uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
- uint NumExtraBooted; /* how many of the above */
- /*
- ** Twenty logical rups.
- ** The first sixteen are the real Rup entries (above), the last four
- ** are the link RUPs.
- */
- struct UnixRup UnixRups[MAX_RUP+LINKS_PER_UNIT];
- int timeout_id; /* For calling 100 ms delays */
- int timeout_sem;/* For calling 100 ms delays */
- long locks; /* long req'd for set_bit --RR */
- char ____end_marker____;
+ struct Top Topology[LINKS_PER_UNIT]; /* one per link */
+ struct Map Mapping[MAX_RUP]; /* Mappings for host */
+ struct PHB *PhbP; /* Pointer to the PHB array */
+ ushort *PhbNumP; /* Ptr to Number of PHB's */
+ struct LPB *LinkStrP; /* Link Structure Array */
+ struct RUP *RupP; /* Sixteen real rups here */
+ struct PARM_MAP *ParmMapP; /* points to the parmmap */
+ uint ExtraUnits[MAX_EXTRA_UNITS]; /* unknown things */
+ uint NumExtraBooted; /* how many of the above */
+ /*
+ ** Twenty logical rups.
+ ** The first sixteen are the real Rup entries (above), the last four
+ ** are the link RUPs.
+ */
+ struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
+ int timeout_id; /* For calling 100 ms delays */
+ int timeout_sem; /* For calling 100 ms delays */
+ long locks; /* long req'd for set_bit --RR */
+ char ____end_marker____;
};
#define Control CardP->DpControl
#define SetInt CardP->DpSetInt
@@ -129,6 +128,6 @@ struct Host
#define Year CardP->DpYear
#define Week CardP->DpWeek
-#define RIO_DUMBPARM 0x0860 /* what not to expect */
+#define RIO_DUMBPARM 0x0860 /* what not to expect */
#endif
diff --git a/drivers/char/rio/hosthw.h b/drivers/char/rio/hosthw.h
deleted file mode 100644
index f6f31ece6e32..000000000000
--- a/drivers/char/rio/hosthw.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* H O S T H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_hosthw_h_sccs = "@(#)hosthw.h 1.2" ;
-#endif
-#endif
-
-#define SET_OTHER_INTERRUPT ( (volatile u_short *) 0x7c80 )
-#define SET_EISA_INTERRUPT ( (volatile u_short *) 0x7ef0 )
-
-#define EISA_HOST 0x30
-#define AT_HOST 0xa0
-#define MCA_HOST 0xb0
-#define PCI_HOST 0xd0
-
-#define PRODUCT_MASK 0xf0
-
-
-/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
index 972250348f4a..bfba5b0c033e 100644
--- a/drivers/char/rio/link.h
+++ b/drivers/char/rio/link.h
@@ -70,27 +70,27 @@
#define DIE_NOW (ushort) 0x0200
/* Boot request stuff */
-#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */
-#define BOOT_ABORT ((ushort) 1) /* Abort a boot */
-#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets
- and load address */
-#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */
+#define BOOT_REQUEST ((ushort) 0) /* Request for a boot */
+#define BOOT_ABORT ((ushort) 1) /* Abort a boot */
+#define BOOT_SEQUENCE ((ushort) 2) /* Packet with the number of packets
+ and load address */
+#define BOOT_COMPLETED ((ushort) 3) /* Boot completed */
/* States that a link can be in */
-#define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */
-#define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */
-#define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */
-#define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */
-#define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */
-#define LINK_SYNC ((ushort) 5) /* Syncing */
+#define LINK_DISCONNECTED ((ushort) 0) /* Disconnected */
+#define LINK_BOOT1 ((ushort) 1) /* Trying to send 1st stage boot */
+#define LINK_BOOT2 ((ushort) 2) /* Trying to send 2nd stage boot */
+#define LINK_BOOT2WAIT ((ushort) 3) /* Waiting for selftest results */
+#define LINK_BOOT3 ((ushort) 4) /* Trying to send 3rd stage boots */
+#define LINK_SYNC ((ushort) 5) /* Syncing */
-#define LINK_INTRO ((ushort) 10) /* Introductory packet */
-#define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */
-#define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */
-#define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */
-#define LINK_CONNECTED ((ushort) 14) /* Connected */
+#define LINK_INTRO ((ushort) 10) /* Introductory packet */
+#define LINK_SUPPLYID ((ushort) 11) /* Trying to supply an ID */
+#define LINK_TOPOLOGY ((ushort) 12) /* Send a topology update */
+#define LINK_REQUESTID ((ushort) 13) /* Waiting for an ID */
+#define LINK_CONNECTED ((ushort) 14) /* Connected */
-#define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */
+#define LINK_INTERCONNECT ((ushort) 20) /* Subnets interconnected */
#define LINK_SPARE ((ushort) 40)
@@ -103,12 +103,12 @@
** LED stuff
*/
#if defined(RTA)
-#define LED_OFF ((ushort) 0) /* LED off */
-#define LED_RED ((ushort) 1) /* LED Red */
-#define LED_GREEN ((ushort) 2) /* LED Green */
-#define LED_ORANGE ((ushort) 4) /* LED Orange */
-#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */
-#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */
+#define LED_OFF ((ushort) 0) /* LED off */
+#define LED_RED ((ushort) 1) /* LED Red */
+#define LED_GREEN ((ushort) 2) /* LED Green */
+#define LED_ORANGE ((ushort) 4) /* LED Orange */
+#define LED_1TO8_OPEN ((ushort) 1) /* Port 1->8 LED on */
+#define LED_9TO16_OPEN ((ushort) 2) /* Port 9->16 LED on */
#define LED_SET_COLOUR(colour) (link->led = (colour))
#define LED_OR_COLOUR(colour) (link->led |= (colour))
#define LED_TIMEOUT(time) (link->led_timeout = RioTimePlus(RioTime(),(time)))
@@ -116,72 +116,72 @@
#define LED_SET_COLOUR(colour)
#define LED_OR_COLOUR(colour)
#define LED_TIMEOUT(time)
-#endif /* RTA */
+#endif /* RTA */
struct LPB {
- WORD link_number ; /* Link Number */
- Channel_ptr in_ch ; /* Link In Channel */
- Channel_ptr out_ch ; /* Link Out Channel */
+ WORD link_number; /* Link Number */
+ Channel_ptr in_ch; /* Link In Channel */
+ Channel_ptr out_ch; /* Link Out Channel */
#ifdef RTA
- uchar stat_led ; /* Port open leds */
- uchar led ; /* True, light led! */
+ uchar stat_led; /* Port open leds */
+ uchar led; /* True, light led! */
#endif
- BYTE attached_serial[4]; /* Attached serial number */
- BYTE attached_host_serial[4];
- /* Serial number of Host who
- booted the other end */
- WORD descheduled ; /* Currently Descheduled */
- WORD state; /* Current state */
- WORD send_poll ; /* Send a Poll Packet */
- Process_ptr ltt_p ; /* Process Descriptor */
- Process_ptr lrt_p ; /* Process Descriptor */
- WORD lrt_status ; /* Current lrt status */
- WORD ltt_status ; /* Current ltt status */
- WORD timeout ; /* Timeout value */
- WORD topology; /* Topology bits */
- WORD mon_ltt ;
- WORD mon_lrt ;
- WORD WaitNoBoot ; /* Secs to hold off booting */
- PKT_ptr add_packet_list; /* Add packets to here */
- PKT_ptr remove_packet_list; /* Send packets from here */
+ BYTE attached_serial[4]; /* Attached serial number */
+ BYTE attached_host_serial[4];
+ /* Serial number of Host who
+ booted the other end */
+ WORD descheduled; /* Currently Descheduled */
+ WORD state; /* Current state */
+ WORD send_poll; /* Send a Poll Packet */
+ Process_ptr ltt_p; /* Process Descriptor */
+ Process_ptr lrt_p; /* Process Descriptor */
+ WORD lrt_status; /* Current lrt status */
+ WORD ltt_status; /* Current ltt status */
+ WORD timeout; /* Timeout value */
+ WORD topology; /* Topology bits */
+ WORD mon_ltt;
+ WORD mon_lrt;
+ WORD WaitNoBoot; /* Secs to hold off booting */
+ PKT_ptr add_packet_list; /* Add packets to here */
+ PKT_ptr remove_packet_list; /* Send packets from here */
#ifdef RTA
#ifdef DCIRRUS
-#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
+#define QBUFS_PER_REDIRECT (4 / PKTS_PER_BUFFER + 1)
#else
-#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
+#define QBUFS_PER_REDIRECT (8 / PKTS_PER_BUFFER + 1)
#endif
- PKT_ptr_ptr rd_add ; /* Add a new Packet here */
- Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr rd_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rd_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rd_remove ; /* Remove a Packet here */
- Q_BUF_ptr rd_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rd_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rd_remove_end_qbb ; /* Pointer to the end of the Q buf */
- ushort pkts_in_q ; /* Packets in queue */
+ PKT_ptr_ptr rd_add; /* Add a new Packet here */
+ Q_BUF_ptr rd_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr rd_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr rd_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr rd_remove; /* Remove a Packet here */
+ Q_BUF_ptr rd_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr rd_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr rd_remove_end_qbb; /* Pointer to the end of the Q buf */
+ ushort pkts_in_q; /* Packets in queue */
#endif
- Channel_ptr lrt_fail_chan ; /* Lrt's failure channel */
- Channel_ptr ltt_fail_chan ; /* Ltt's failure channel */
+ Channel_ptr lrt_fail_chan; /* Lrt's failure channel */
+ Channel_ptr ltt_fail_chan; /* Ltt's failure channel */
#if defined (HOST) || defined (INKERNEL)
- /* RUP structure for HOST to driver communications */
- struct RUP rup ;
+ /* RUP structure for HOST to driver communications */
+ struct RUP rup;
#endif
- struct RUP link_rup; /* RUP for the link (POLL,
- topology etc.) */
- WORD attached_link ; /* Number of attached link */
- WORD csum_errors ; /* csum errors */
- WORD num_disconnects ; /* number of disconnects */
- WORD num_sync_rcvd ; /* # sync's received */
- WORD num_sync_rqst ; /* # sync requests */
- WORD num_tx ; /* Num pkts sent */
- WORD num_rx ; /* Num pkts received */
- WORD module_attached; /* Module tpyes of attached */
- WORD led_timeout; /* LED timeout */
- WORD first_port; /* First port to service */
- WORD last_port; /* Last port to service */
- } ;
+ struct RUP link_rup; /* RUP for the link (POLL,
+ topology etc.) */
+ WORD attached_link; /* Number of attached link */
+ WORD csum_errors; /* csum errors */
+ WORD num_disconnects; /* number of disconnects */
+ WORD num_sync_rcvd; /* # sync's received */
+ WORD num_sync_rqst; /* # sync requests */
+ WORD num_tx; /* Num pkts sent */
+ WORD num_rx; /* Num pkts received */
+ WORD module_attached; /* Module tpyes of attached */
+ WORD led_timeout; /* LED timeout */
+ WORD first_port; /* First port to service */
+ WORD last_port; /* Last port to service */
+};
#endif
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
index d53843abe02d..17a14c4a3420 100644
--- a/drivers/char/rio/linux_compat.h
+++ b/drivers/char/rio/linux_compat.h
@@ -41,7 +41,7 @@
#endif
struct ttystatics {
- struct termios tm;
+ struct termios tm;
};
#define bzero(d, n) memset((d), 0, (n))
@@ -97,26 +97,24 @@ the older driver. The older driver includes "brates.h" which shadows
the definitions from Linux, and is incompatible... */
/* RxBaud and TxBaud definitions... */
-#define RIO_B0 0x00 /* RTS / DTR signals dropped */
-#define RIO_B50 0x01 /* 50 baud */
-#define RIO_B75 0x02 /* 75 baud */
-#define RIO_B110 0x03 /* 110 baud */
-#define RIO_B134 0x04 /* 134.5 baud */
-#define RIO_B150 0x05 /* 150 baud */
-#define RIO_B200 0x06 /* 200 baud */
-#define RIO_B300 0x07 /* 300 baud */
-#define RIO_B600 0x08 /* 600 baud */
-#define RIO_B1200 0x09 /* 1200 baud */
-#define RIO_B1800 0x0A /* 1800 baud */
-#define RIO_B2400 0x0B /* 2400 baud */
-#define RIO_B4800 0x0C /* 4800 baud */
-#define RIO_B9600 0x0D /* 9600 baud */
-#define RIO_B19200 0x0E /* 19200 baud */
-#define RIO_B38400 0x0F /* 38400 baud */
-#define RIO_B56000 0x10 /* 56000 baud */
-#define RIO_B57600 0x11 /* 57600 baud */
-#define RIO_B64000 0x12 /* 64000 baud */
-#define RIO_B115200 0x13 /* 115200 baud */
-#define RIO_B2000 0x14 /* 2000 baud */
-
-
+#define RIO_B0 0x00 /* RTS / DTR signals dropped */
+#define RIO_B50 0x01 /* 50 baud */
+#define RIO_B75 0x02 /* 75 baud */
+#define RIO_B110 0x03 /* 110 baud */
+#define RIO_B134 0x04 /* 134.5 baud */
+#define RIO_B150 0x05 /* 150 baud */
+#define RIO_B200 0x06 /* 200 baud */
+#define RIO_B300 0x07 /* 300 baud */
+#define RIO_B600 0x08 /* 600 baud */
+#define RIO_B1200 0x09 /* 1200 baud */
+#define RIO_B1800 0x0A /* 1800 baud */
+#define RIO_B2400 0x0B /* 2400 baud */
+#define RIO_B4800 0x0C /* 4800 baud */
+#define RIO_B9600 0x0D /* 9600 baud */
+#define RIO_B19200 0x0E /* 19200 baud */
+#define RIO_B38400 0x0F /* 38400 baud */
+#define RIO_B56000 0x10 /* 56000 baud */
+#define RIO_B57600 0x11 /* 57600 baud */
+#define RIO_B64000 0x12 /* 64000 baud */
+#define RIO_B115200 0x13 /* 115200 baud */
+#define RIO_B2000 0x14 /* 2000 baud */
diff --git a/drivers/char/rio/list.h b/drivers/char/rio/list.h
index a4f7f1f56255..36aad4c9cb3a 100644
--- a/drivers/char/rio/list.h
+++ b/drivers/char/rio/list.h
@@ -38,7 +38,7 @@
#ifdef SCCS_LABELS
#ifndef lint
-static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
+static char *_rio_list_h_sccs = "@(#)list.h 1.9";
#endif
#endif
@@ -166,7 +166,7 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
#endif
-#else /* !IN_KERNEL */
+#else /* !IN_KERNEL */
#define ZERO_PTR NULL
@@ -192,5 +192,5 @@ static char *_rio_list_h_sccs = "@(#)list.h 1.9" ;
#define splx(oldspl) if ((oldspl) == 0) spl0()
#endif
-#endif /* ifndef _list.h */
+#endif /* ifndef _list.h */
/*********** end of file ***********/
diff --git a/drivers/char/rio/lrt.h b/drivers/char/rio/lrt.h
deleted file mode 100644
index bbac8fa18fee..000000000000
--- a/drivers/char/rio/lrt.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L R T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lrt_h_sccs = "@(#)lrt.h 1.1" ;
-#endif
-#endif
-
-
-#ifdef DCIRRUS
-#define LRT_STACK (unsigned short) 600
-#else
-#define LRT_STACK (ushort) 200
-#endif
-
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/ltt.h b/drivers/char/rio/ltt.h
deleted file mode 100644
index f27dcecf03ca..000000000000
--- a/drivers/char/rio/ltt.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* L T T
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_ltt_h_sccs = "@(#)ltt.h 1.1" ;
-#endif
-#endif
-
-#ifdef DCIRRUS
-#define LTT_STACK (unsigned short) 600
-#else
-#define LTT_STACK (ushort) 200
-#endif
-
-
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/lttwake.h b/drivers/char/rio/lttwake.h
deleted file mode 100644
index fe17d0ee4933..000000000000
--- a/drivers/char/rio/lttwake.h
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-/****************************************************************************
- ******* *******
- ******* L T T W A K E U P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_lttwake_h_sccs = "@(#)lttwake.h 1.1" ;
-#endif
-#endif
-
-#define LTT_WAKEUP_STACK 500
-#define LTT_WAKEUP_INTERVAL (int) (500 * MILLISECOND)
-
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h
index 400645a1ff28..97fe287aab2a 100644
--- a/drivers/char/rio/map.h
+++ b/drivers/char/rio/map.h
@@ -46,21 +46,20 @@ static char *_map_h_sccs_ = "@(#)map.h 1.2";
#define TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
#define MAX_NAME_LEN 32
-struct Map
-{
- uint HostUniqueNum; /* Supporting hosts unique number */
- uint RtaUniqueNum; /* Unique number */
+struct Map {
+ uint HostUniqueNum; /* Supporting hosts unique number */
+ uint RtaUniqueNum; /* Unique number */
/*
- ** The next two IDs must be swapped on big-endian architectures
- ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
- ** upgrading for example).
- */
- ushort ID; /* ID used in the subnet */
- ushort ID2; /* ID of 2nd block of 8 for 16 port */
- ulong Flags; /* Booted, ID Given, Disconnected */
- ulong SysPort; /* First tty mapped to this port */
- struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */
- char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */
+ ** The next two IDs must be swapped on big-endian architectures
+ ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
+ ** upgrading for example).
+ */
+ ushort ID; /* ID used in the subnet */
+ ushort ID2; /* ID of 2nd block of 8 for 16 port */
+ ulong Flags; /* Booted, ID Given, Disconnected */
+ ulong SysPort; /* First tty mapped to this port */
+ struct Top Topology[LINKS_PER_UNIT]; /* ID connected to each link */
+ char Name[MAX_NAME_LEN]; /* Cute name by which RTA is known */
};
/*
diff --git a/drivers/char/rio/mca.h b/drivers/char/rio/mca.h
deleted file mode 100644
index 08a327e473af..000000000000
--- a/drivers/char/rio/mca.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : mca.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:11
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mca.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mca_h__
-#define __rio_mca_h__
-
-#ifdef SCCS_LABELS
-static char *_mca_h_sccs_ = "@(#)mca.h 1.2";
-#endif
-
-/*
-** Micro Channel stuff
-*/
-
-#define McaMaxSlots 8
-#define McaSlotSelect 0x96
-#define McaSlotEnable 0x08
-#define McaIdLow 0x100
-#define McaIdHigh 0x101
-#define McaIrqEnable 0x102
-#define McaMemory 0x103
-#define McaRIOId 0x6a5c
-#define McaIrq9 0x00
-#define McaIrq3 0x02
-#define McaIrq4 0x04
-#define McaIrq7 0x06
-#define McaIrq10 0x08
-#define McaIrq11 0x0A
-#define McaIrq12 0x0C
-#define McaIrq15 0x0E
-#define McaIrqMask 0x0E
-#define McaCardEnable 0x01
-#define McaAddress(X) (((X)&0xFF)<<16)
-
-#define McaTpFastLinks 0x40
-#define McaTpSlowLinks 0x00
-#define McaTpBootFromRam 0x01
-#define McaTpBootFromLink 0x00
-#define McaTpBusEnable 0x02
-#define McaTpBusDisable 0x00
-
-#define RIO_MCA_DEFAULT_MODE SLOW_LINKS
-
-#endif /* __rio_mca_h__ */
diff --git a/drivers/char/rio/mesg.h b/drivers/char/rio/mesg.h
deleted file mode 100644
index 9cf6c0bacea4..000000000000
--- a/drivers/char/rio/mesg.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : mesg.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:12
-** Retrieved : 11/6/98 11:34:21
-**
-** ident @(#)mesg.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_mesg_h__
-#define __rio_mesg_h__
-
-#ifdef SCCS_LABELS
-static char *_mesg_h_sccs_ = "@(#)mesg.h 1.2";
-#endif
-
-
-#endif /* __rio_mesg_h__ */
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h
index 2dc30b9aab37..de7e57180c91 100644
--- a/drivers/char/rio/param.h
+++ b/drivers/char/rio/param.h
@@ -42,20 +42,19 @@ static char *_param_h_sccs_ = "@(#)param.h 1.2";
** the param command block, as used in OPEN and PARAM calls.
*/
-struct phb_param
-{
- BYTE Cmd; /* It is very important that these line up */
- BYTE Cor1; /* with what is expected at the other end. */
- BYTE Cor2; /* to confirm that you've got it right, */
- BYTE Cor4; /* check with cirrus/cirrus.h */
- BYTE Cor5;
- BYTE TxXon; /* Transmit X-On character */
- BYTE TxXoff; /* Transmit X-Off character */
- BYTE RxXon; /* Receive X-On character */
- BYTE RxXoff; /* Receive X-Off character */
- BYTE LNext; /* Literal-next character */
- BYTE TxBaud; /* Transmit baudrate */
- BYTE RxBaud; /* Receive baudrate */
+struct phb_param {
+ BYTE Cmd; /* It is very important that these line up */
+ BYTE Cor1; /* with what is expected at the other end. */
+ BYTE Cor2; /* to confirm that you've got it right, */
+ BYTE Cor4; /* check with cirrus/cirrus.h */
+ BYTE Cor5;
+ BYTE TxXon; /* Transmit X-On character */
+ BYTE TxXoff; /* Transmit X-Off character */
+ BYTE RxXon; /* Receive X-On character */
+ BYTE RxXoff; /* Receive X-Off character */
+ BYTE LNext; /* Literal-next character */
+ BYTE TxBaud; /* Transmit baudrate */
+ BYTE RxBaud; /* Receive baudrate */
};
#endif
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
index 46f99dfdac8d..fe4e00567065 100644
--- a/drivers/char/rio/parmmap.h
+++ b/drivers/char/rio/parmmap.h
@@ -44,53 +44,50 @@
#endif
#endif
-typedef struct PARM_MAP PARM_MAP ;
+typedef struct PARM_MAP PARM_MAP;
-struct PARM_MAP
-{
-PHB_ptr phb_ptr ; /* Pointer to the PHB array */
-WORD_ptr phb_num_ptr ; /* Ptr to Number of PHB's */
-FREE_LIST_ptr free_list; /* Free List pointer */
-FREE_LIST_ptr free_list_end; /* Free List End pointer */
-Q_BUF_ptr_ptr q_free_list_ptr ; /* Ptr to Q_BUF variable */
-BYTE_ptr unit_id_ptr ; /* Unit Id */
-LPB_ptr link_str_ptr ; /* Link Structure Array */
-BYTE_ptr bootloader_1 ; /* 1st Stage Boot Loader */
-BYTE_ptr bootloader_2 ; /* 2nd Stage Boot Loader */
-WORD_ptr port_route_map_ptr ; /* Port Route Map */
-ROUTE_STR_ptr route_ptr ; /* Unit Route Map */
-NUMBER_ptr map_present ; /* Route Map present */
-NUMBER pkt_num ; /* Total number of packets */
-NUMBER q_num ; /* Total number of Q packets */
-WORD buffers_per_port ; /* Number of buffers per port */
-WORD heap_size ; /* Initial size of heap */
-WORD heap_left ; /* Current Heap left */
-WORD error ; /* Error code */
-WORD tx_max; /* Max number of tx pkts per phb */
-WORD rx_max; /* Max number of rx pkts per phb */
-WORD rx_limit; /* For high / low watermarks */
-NUMBER links ; /* Links to use */
-NUMBER timer ; /* Interrupts per second */
-RUP_ptr rups ; /* Pointer to the RUPs */
-WORD max_phb ; /* Mostly for debugging */
-WORD living ; /* Just increments!! */
-WORD init_done ; /* Initialisation over */
-WORD booting_link ;
-WORD idle_count ; /* Idle time counter */
-WORD busy_count ; /* Busy counter */
-WORD idle_control ; /* Control Idle Process */
+struct PARM_MAP {
+ PHB_ptr phb_ptr; /* Pointer to the PHB array */
+ WORD_ptr phb_num_ptr; /* Ptr to Number of PHB's */
+ FREE_LIST_ptr free_list; /* Free List pointer */
+ FREE_LIST_ptr free_list_end; /* Free List End pointer */
+ Q_BUF_ptr_ptr q_free_list_ptr; /* Ptr to Q_BUF variable */
+ BYTE_ptr unit_id_ptr; /* Unit Id */
+ LPB_ptr link_str_ptr; /* Link Structure Array */
+ BYTE_ptr bootloader_1; /* 1st Stage Boot Loader */
+ BYTE_ptr bootloader_2; /* 2nd Stage Boot Loader */
+ WORD_ptr port_route_map_ptr; /* Port Route Map */
+ ROUTE_STR_ptr route_ptr; /* Unit Route Map */
+ NUMBER_ptr map_present; /* Route Map present */
+ NUMBER pkt_num; /* Total number of packets */
+ NUMBER q_num; /* Total number of Q packets */
+ WORD buffers_per_port; /* Number of buffers per port */
+ WORD heap_size; /* Initial size of heap */
+ WORD heap_left; /* Current Heap left */
+ WORD error; /* Error code */
+ WORD tx_max; /* Max number of tx pkts per phb */
+ WORD rx_max; /* Max number of rx pkts per phb */
+ WORD rx_limit; /* For high / low watermarks */
+ NUMBER links; /* Links to use */
+ NUMBER timer; /* Interrupts per second */
+ RUP_ptr rups; /* Pointer to the RUPs */
+ WORD max_phb; /* Mostly for debugging */
+ WORD living; /* Just increments!! */
+ WORD init_done; /* Initialisation over */
+ WORD booting_link;
+ WORD idle_count; /* Idle time counter */
+ WORD busy_count; /* Busy counter */
+ WORD idle_control; /* Control Idle Process */
#if defined(HOST) || defined(INKERNEL)
-WORD tx_intr; /* TX interrupt pending */
-WORD rx_intr; /* RX interrupt pending */
-WORD rup_intr; /* RUP interrupt pending */
+ WORD tx_intr; /* TX interrupt pending */
+ WORD rx_intr; /* RX interrupt pending */
+ WORD rup_intr; /* RUP interrupt pending */
#endif
#if defined(RTA)
-WORD dying_count; /* Count of processes dead */
+ WORD dying_count; /* Count of processes dead */
#endif
-} ;
+};
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h
index dc635bd25194..1eba9118079b 100644
--- a/drivers/char/rio/pci.h
+++ b/drivers/char/rio/pci.h
@@ -73,4 +73,4 @@ static char *_pci_h_sccs_ = "@(#)pci.h 1.2";
#define RIO_PCI_DEFAULT_MODE 0x05
-#endif /* __rio_pci_h__ */
+#endif /* __rio_pci_h__ */
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
index e1483a0e30bd..3baebf8513af 100644
--- a/drivers/char/rio/phb.h
+++ b/drivers/char/rio/phb.h
@@ -58,37 +58,37 @@
/*************************************************
* Handshake asserted. Deasserted by the LTT(s)
************************************************/
-#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */
+#define PHB_HANDSHAKE_SET ((ushort) 0x001) /* Set by LRT */
-#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */
+#define PHB_HANDSHAKE_RESET ((ushort) 0x002) /* Set by ISR / driver */
#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
- /* Reset by ltt */
+ /* Reset by ltt */
/*************************************************
* Maximum number of PHB's
************************************************/
#if defined (HOST) || defined (INKERNEL)
-#define MAX_PHB ((ushort) 128) /* range 0-127 */
+#define MAX_PHB ((ushort) 128) /* range 0-127 */
#else
-#define MAX_PHB ((ushort) 8) /* range 0-7 */
+#define MAX_PHB ((ushort) 8) /* range 0-7 */
#endif
/*************************************************
* Defines for the mode fields
************************************************/
-#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */
-#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */
-#define TX_TAB3 0x0004 /* TAB3 mode */
-#define TX_OCRNL 0x0008 /* OCRNL mode */
-#define TX_ONLCR 0x0010 /* ONLCR mode */
-#define TX_SENDSPACES 0x0020 /* Send n spaces command needs
- completing */
-#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */
-#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */
-#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
- port */
+#define TXPKT_INCOMPLETE 0x0001 /* Previous tx packet not completed */
+#define TXINTR_ENABLED 0x0002 /* Tx interrupt is enabled */
+#define TX_TAB3 0x0004 /* TAB3 mode */
+#define TX_OCRNL 0x0008 /* OCRNL mode */
+#define TX_ONLCR 0x0010 /* ONLCR mode */
+#define TX_SENDSPACES 0x0020 /* Send n spaces command needs
+ completing */
+#define TX_SENDNULL 0x0040 /* Escaping NULL needs completing */
+#define TX_SENDLF 0x0080 /* LF -> CR LF needs completing */
+#define TX_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
+ port */
#define TX_HANGOVER (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
#define TX_DTRFLOW 0x0200 /* DTR tx flow control */
#define TX_DTRFLOWED 0x0400 /* DTR is low - don't allow more data
@@ -96,34 +96,34 @@
#define TX_DATAINFIFO 0x0800 /* There is data in the FIFO */
#define TX_BUSY 0x1000 /* Data in FIFO, shift or holding regs */
-#define RX_SPARE 0x0001 /* SPARE */
-#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */
-#define RX_ICRNL 0x0008 /* ICRNL mode */
-#define RX_INLCR 0x0010 /* INLCR mode */
-#define RX_IGNCR 0x0020 /* IGNCR mode */
-#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */
-#define RX_IXOFF 0x0080 /* IXOFF enabled */
-#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */
-#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */
-#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */
+#define RX_SPARE 0x0001 /* SPARE */
+#define RXINTR_ENABLED 0x0002 /* Rx interrupt enabled */
+#define RX_ICRNL 0x0008 /* ICRNL mode */
+#define RX_INLCR 0x0010 /* INLCR mode */
+#define RX_IGNCR 0x0020 /* IGNCR mode */
+#define RX_CTSFLOW 0x0040 /* CTSFLOW enabled */
+#define RX_IXOFF 0x0080 /* IXOFF enabled */
+#define RX_CTSFLOWED 0x0100 /* CTSFLOW and CTS dropped */
+#define RX_IXOFFED 0x0200 /* IXOFF and xoff sent */
+#define RX_BUFFERED 0x0400 /* Try and pass on complete packets */
-#define PORT_ISOPEN 0x0001 /* Port open? */
-#define PORT_HUPCL 0x0002 /* Hangup on close? */
-#define PORT_MOPENPEND 0x0004 /* Modem open pending */
-#define PORT_ISPARALLEL 0x0008 /* Parallel port */
-#define PORT_BREAK 0x0010 /* Port on break */
-#define PORT_STATUSPEND 0x0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x0040 /* Break packet pending */
-#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */
-#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
- port */
-#define PORT_FULLMODEM 0x0200 /* Full modem signals */
-#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */
-#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */
+#define PORT_ISOPEN 0x0001 /* Port open? */
+#define PORT_HUPCL 0x0002 /* Hangup on close? */
+#define PORT_MOPENPEND 0x0004 /* Modem open pending */
+#define PORT_ISPARALLEL 0x0008 /* Parallel port */
+#define PORT_BREAK 0x0010 /* Port on break */
+#define PORT_STATUSPEND 0x0020 /* Status packet pending */
+#define PORT_BREAKPEND 0x0040 /* Break packet pending */
+#define PORT_MODEMPEND 0x0080 /* Modem status packet pending */
+#define PORT_PARALLELBUG 0x0100 /* CD1400 LF -> CR LF bug on parallel
+ port */
+#define PORT_FULLMODEM 0x0200 /* Full modem signals */
+#define PORT_RJ45 0x0400 /* RJ45 connector - no RI signal */
+#define PORT_RESTRICTED 0x0600 /* Restricted connector - no RI / DTR */
-#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */
+#define PORT_MODEMBITS 0x0600 /* Mask for modem fields */
-#define PORT_WCLOSE 0x0800 /* Waiting for close */
+#define PORT_WCLOSE 0x0800 /* Waiting for close */
#define PORT_HANDSHAKEFIX 0x1000 /* Port has H/W flow control fix */
#define PORT_WASPCLOSED 0x2000 /* Port closed with PCLOSE */
#define DUMPMODE 0x4000 /* Dump RTA mem */
@@ -155,139 +155,128 @@
#define rx_end u4.s1.rx_end_ptr_ptr
#define rx_remove u4.s1.rx_remove_ptr_ptr
#endif
-typedef struct PHB PHB ;
+typedef struct PHB PHB;
struct PHB {
#ifdef RTA
- ushort port;
+ ushort port;
#endif
#ifdef INKERNEL
- WORD source;
+ WORD source;
#else
- union
- {
- ushort source; /* Complete source */
- struct
- {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
+ union {
+ ushort source; /* Complete source */
+ struct {
+ unsigned char unit; /* Source unit */
+ unsigned char port; /* Source port */
+ } s2;
+ } u2;
#endif
- WORD handshake ;
- WORD status ;
- NUMBER timeout ; /* Maximum of 1.9 seconds */
- WORD link ; /* Send down this link */
+ WORD handshake;
+ WORD status;
+ NUMBER timeout; /* Maximum of 1.9 seconds */
+ WORD link; /* Send down this link */
#ifdef INKERNEL
- WORD destination;
+ WORD destination;
#else
- union
- {
- ushort destination; /* Complete destination */
- struct
- {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
+ union {
+ ushort destination; /* Complete destination */
+ struct {
+ unsigned char unit; /* Destination unit */
+ unsigned char port; /* Destination port */
+ } s1;
+ } u1;
#endif
#ifdef RTA
- ushort tx_pkts_added;
- ushort tx_pkts_removed;
- Q_BUF_ptr tx_q_start ; /* Start of the Q list chain */
- short num_tx_q_bufs ; /* Number of Q buffers in the chain */
- PKT_ptr_ptr tx_add ; /* Add a new Packet here */
- Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */
- PKT_ptr_ptr tx_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr tx_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr tx_remove ; /* Remove a Packet here */
- Q_BUF_ptr tx_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr tx_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr tx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+ ushort tx_pkts_added;
+ ushort tx_pkts_removed;
+ Q_BUF_ptr tx_q_start; /* Start of the Q list chain */
+ short num_tx_q_bufs; /* Number of Q buffers in the chain */
+ PKT_ptr_ptr tx_add; /* Add a new Packet here */
+ Q_BUF_ptr tx_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr tx_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr tx_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr tx_remove; /* Remove a Packet here */
+ Q_BUF_ptr tx_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr tx_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr tx_remove_end_qbb; /* Pointer to the end of the Q buf */
#endif
#ifdef INKERNEL
- PKT_ptr_ptr tx_start ;
- PKT_ptr_ptr tx_end ;
- PKT_ptr_ptr tx_add ;
- PKT_ptr_ptr tx_remove ;
+ PKT_ptr_ptr tx_start;
+ PKT_ptr_ptr tx_end;
+ PKT_ptr_ptr tx_add;
+ PKT_ptr_ptr tx_remove;
#endif
#ifdef HOST
- union
- {
- struct
- {
- PKT_ptr_ptr tx_start_ptr_ptr;
- PKT_ptr_ptr tx_end_ptr_ptr;
- PKT_ptr_ptr tx_add_ptr_ptr;
- PKT_ptr_ptr tx_remove_ptr_ptr;
- } s1;
- struct
- {
- ushort * tx_start_ptr;
- ushort * tx_end_ptr;
- ushort * tx_add_ptr;
- ushort * tx_remove_ptr;
- } s2;
- } u3;
+ union {
+ struct {
+ PKT_ptr_ptr tx_start_ptr_ptr;
+ PKT_ptr_ptr tx_end_ptr_ptr;
+ PKT_ptr_ptr tx_add_ptr_ptr;
+ PKT_ptr_ptr tx_remove_ptr_ptr;
+ } s1;
+ struct {
+ ushort *tx_start_ptr;
+ ushort *tx_end_ptr;
+ ushort *tx_add_ptr;
+ ushort *tx_remove_ptr;
+ } s2;
+ } u3;
#endif
#ifdef RTA
- ushort rx_pkts_added;
- ushort rx_pkts_removed;
- Q_BUF_ptr rx_q_start ; /* Start of the Q list chain */
- short num_rx_q_bufs ; /* Number of Q buffers in the chain */
- PKT_ptr_ptr rx_add ; /* Add a new Packet here */
- Q_BUF_ptr rx_add_qb ; /* Pointer to the add Q buf */
- PKT_ptr_ptr rx_add_st_qbb ; /* Pointer to start of the Q's buf */
- PKT_ptr_ptr rx_add_end_qbb ; /* Pointer to the end of the Q's buf */
- PKT_ptr_ptr rx_remove ; /* Remove a Packet here */
- Q_BUF_ptr rx_remove_qb ; /* Pointer to the remove Q buf */
- PKT_ptr_ptr rx_remove_st_qbb ; /* Pointer to the start of the Q buf */
- PKT_ptr_ptr rx_remove_end_qbb ; /* Pointer to the end of the Q buf */
+ ushort rx_pkts_added;
+ ushort rx_pkts_removed;
+ Q_BUF_ptr rx_q_start; /* Start of the Q list chain */
+ short num_rx_q_bufs; /* Number of Q buffers in the chain */
+ PKT_ptr_ptr rx_add; /* Add a new Packet here */
+ Q_BUF_ptr rx_add_qb; /* Pointer to the add Q buf */
+ PKT_ptr_ptr rx_add_st_qbb; /* Pointer to start of the Q's buf */
+ PKT_ptr_ptr rx_add_end_qbb; /* Pointer to the end of the Q's buf */
+ PKT_ptr_ptr rx_remove; /* Remove a Packet here */
+ Q_BUF_ptr rx_remove_qb; /* Pointer to the remove Q buf */
+ PKT_ptr_ptr rx_remove_st_qbb; /* Pointer to the start of the Q buf */
+ PKT_ptr_ptr rx_remove_end_qbb; /* Pointer to the end of the Q buf */
#endif
#ifdef INKERNEL
- PKT_ptr_ptr rx_start ;
- PKT_ptr_ptr rx_end ;
- PKT_ptr_ptr rx_add ;
- PKT_ptr_ptr rx_remove ;
+ PKT_ptr_ptr rx_start;
+ PKT_ptr_ptr rx_end;
+ PKT_ptr_ptr rx_add;
+ PKT_ptr_ptr rx_remove;
#endif
#ifdef HOST
- union
- {
- struct
- {
- PKT_ptr_ptr rx_start_ptr_ptr;
- PKT_ptr_ptr rx_end_ptr_ptr;
- PKT_ptr_ptr rx_add_ptr_ptr;
- PKT_ptr_ptr rx_remove_ptr_ptr;
- } s1;
- struct
- {
- ushort * rx_start_ptr;
- ushort * rx_end_ptr;
- ushort * rx_add_ptr;
- ushort * rx_remove_ptr;
- } s2;
- } u4;
+ union {
+ struct {
+ PKT_ptr_ptr rx_start_ptr_ptr;
+ PKT_ptr_ptr rx_end_ptr_ptr;
+ PKT_ptr_ptr rx_add_ptr_ptr;
+ PKT_ptr_ptr rx_remove_ptr_ptr;
+ } s1;
+ struct {
+ ushort *rx_start_ptr;
+ ushort *rx_end_ptr;
+ ushort *rx_add_ptr;
+ ushort *rx_remove_ptr;
+ } s2;
+ } u4;
#endif
-#ifdef RTA /* some fields for the remotes */
- ushort flush_count; /* Count of write flushes */
- ushort txmode; /* Modes for tx */
- ushort rxmode; /* Modes for rx */
- ushort portmode; /* Generic modes */
- ushort column; /* TAB3 column count */
- ushort tx_subscript; /* (TX) Subscript into data field */
- ushort rx_subscript; /* (RX) Subscript into data field */
- PKT_ptr rx_incomplete; /* Hold an incomplete packet here */
- ushort modem_bits; /* Modem bits to mask */
- ushort lastModem; /* Modem control lines. */
- ushort addr; /* Address for sub commands */
- ushort MonitorTstate; /* TRUE if monitoring tstop */
+#ifdef RTA /* some fields for the remotes */
+ ushort flush_count; /* Count of write flushes */
+ ushort txmode; /* Modes for tx */
+ ushort rxmode; /* Modes for rx */
+ ushort portmode; /* Generic modes */
+ ushort column; /* TAB3 column count */
+ ushort tx_subscript; /* (TX) Subscript into data field */
+ ushort rx_subscript; /* (RX) Subscript into data field */
+ PKT_ptr rx_incomplete; /* Hold an incomplete packet here */
+ ushort modem_bits; /* Modem bits to mask */
+ ushort lastModem; /* Modem control lines. */
+ ushort addr; /* Address for sub commands */
+ ushort MonitorTstate; /* TRUE if monitoring tstop */
#endif
- } ;
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
index 66bb2ff0f694..882fd429ac2e 100644
--- a/drivers/char/rio/pkt.h
+++ b/drivers/char/rio/pkt.h
@@ -69,52 +69,44 @@
#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
#define CONTROL_DATA_WNDW (DATA_WNDW << 8)
-struct PKT {
+struct PKT {
#ifdef INKERNEL
- BYTE dest_unit ; /* Destination Unit Id */
- BYTE dest_port ; /* Destination POrt */
- BYTE src_unit ; /* Source Unit Id */
- BYTE src_port ; /* Source POrt */
+ BYTE dest_unit; /* Destination Unit Id */
+ BYTE dest_port; /* Destination POrt */
+ BYTE src_unit; /* Source Unit Id */
+ BYTE src_port; /* Source POrt */
#else
- union
- {
- ushort destination; /* Complete destination */
- struct
- {
- unsigned char unit; /* Destination unit */
- unsigned char port; /* Destination port */
- } s1;
- } u1;
- union
- {
- ushort source; /* Complete source */
- struct
- {
- unsigned char unit; /* Source unit */
- unsigned char port; /* Source port */
- } s2;
- } u2;
+ union {
+ ushort destination; /* Complete destination */
+ struct {
+ unsigned char unit; /* Destination unit */
+ unsigned char port; /* Destination port */
+ } s1;
+ } u1;
+ union {
+ ushort source; /* Complete source */
+ struct {
+ unsigned char unit; /* Source unit */
+ unsigned char port; /* Source port */
+ } s2;
+ } u2;
#endif
#ifdef INKERNEL
- BYTE len ;
- BYTE control;
+ BYTE len;
+ BYTE control;
#else
- union
- {
- ushort control;
- struct
- {
- unsigned char len;
- unsigned char control;
- } s3;
- } u3;
+ union {
+ ushort control;
+ struct {
+ unsigned char len;
+ unsigned char control;
+ } s3;
+ } u3;
#endif
- BYTE data[PKT_MAX_DATA_LEN] ;
- /* Actual data :-) */
- WORD csum ; /* C-SUM */
- } ;
+ BYTE data[PKT_MAX_DATA_LEN];
+ /* Actual data :-) */
+ WORD csum; /* C-SUM */
+};
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/poll.h b/drivers/char/rio/poll.h
deleted file mode 100644
index d9b8e983e175..000000000000
--- a/drivers/char/rio/poll.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* P O L L
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra / Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _poll_h
-#define _poll_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_poll_h_sccs = "@(#)poll.h 1.2" ;
-#endif
-#endif
-
-
-#ifdef HOST
-#define POLL_STACK 100
-#endif
-#ifdef RTA
-#define POLL_STACK 200
-#endif
-
-#define POLL_PERIOD (int) SECOND
-
-/* The various poll commands */
-#define POLL_POLL 0 /* We are connected and happy.. */
-#define POLL_INTRO 1 /* Introduction packet */
-#define POLL_TOPOLOGY 2 /* Topology update */
-#define POLL_ASSIGN 3 /* ID assign */
-#define POLL_FOAD 4 /* F*** Off And Die */
-#define POLL_LMD 5 /* Let Me Die */
-#define POLL_DYB 6 /* Die You Ba***** */
-
-/* The way data fields are split up for POLL packets */
-#define POLL_HOST_SERIAL 2 /* Host who booted me */
-#define POLL_MY_SERIAL 6 /* My serial number */
-#define POLL_YOUR_ID 1 /* Your ID number */
-#define POLL_TOPOLOGY_FIELDS 2 /* Topology maps */
-
-#endif
-
-/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h
index 8506af06aa9f..c99b1e70fdc8 100644
--- a/drivers/char/rio/port.h
+++ b/drivers/char/rio/port.h
@@ -46,96 +46,94 @@ static char *_port_h_sccs_ = "@(#)port.h 1.3";
*/
#ifdef STATS
-struct RIOStats
-{
+struct RIOStats {
/*
- ** interrupt statistics
- */
- uint BreakIntCnt;
- uint ModemOffCnt;
- uint ModemOnCnt;
- uint RxIntCnt;
- uint TxIntCnt;
+ ** interrupt statistics
+ */
+ uint BreakIntCnt;
+ uint ModemOffCnt;
+ uint ModemOnCnt;
+ uint RxIntCnt;
+ uint TxIntCnt;
/*
- ** throughput statistics
- */
- uint RxCharCnt;
- uint RxPktCnt;
- uint RxSaveCnt;
- uint TxCharCnt;
- uint TxPktCnt;
+ ** throughput statistics
+ */
+ uint RxCharCnt;
+ uint RxPktCnt;
+ uint RxSaveCnt;
+ uint TxCharCnt;
+ uint TxPktCnt;
/*
- ** driver entry statistics
- */
- uint CloseCnt;
- uint IoctlCnt;
- uint OpenCnt;
- uint ReadCnt;
- uint WriteCnt;
+ ** driver entry statistics
+ */
+ uint CloseCnt;
+ uint IoctlCnt;
+ uint OpenCnt;
+ uint ReadCnt;
+ uint WriteCnt;
/*
- ** proc statistics
- */
- uint BlockCnt;
- uint OutputCnt;
- uint ResumeCnt;
- uint RflushCnt;
- uint SuspendCnt;
- uint TbreakCnt;
- uint TimeoutCnt;
- uint UnblockCnt;
- uint WflushCnt;
- uint WFBodgeCnt;
+ ** proc statistics
+ */
+ uint BlockCnt;
+ uint OutputCnt;
+ uint ResumeCnt;
+ uint RflushCnt;
+ uint SuspendCnt;
+ uint TbreakCnt;
+ uint TimeoutCnt;
+ uint UnblockCnt;
+ uint WflushCnt;
+ uint WFBodgeCnt;
};
#endif
/*
** Port data structure
*/
-struct Port
-{
- struct gs_port gs;
- int PortNum; /* RIO port no., 0-511 */
- struct Host *HostP;
- volatile caddr_t Caddr;
- ushort HostPort; /* Port number on host card */
- uchar RupNum; /* Number of RUP for port */
- uchar ID2; /* Second ID of RTA for port */
- ulong State; /* FLAGS for open & xopen */
-#define RIO_LOPEN 0x00001 /* Local open */
-#define RIO_MOPEN 0x00002 /* Modem open */
-#define RIO_WOPEN 0x00004 /* Waiting for open */
-#define RIO_CLOSING 0x00008 /* The port is being close */
-#define RIO_XPBUSY 0x00010 /* Transparent printer busy */
-#define RIO_BREAKING 0x00020 /* Break in progress */
-#define RIO_DIRECT 0x00040 /* Doing Direct output */
-#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */
-#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */
-#define RIO_CARR_ON 0x00200 /* Stream has carrier present */
-#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */
-#define RIO_RBLK 0x00800 /* Stream is read-blocked */
-#define RIO_BUSY 0x01000 /* Stream is BUSY for write */
-#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */
-#define RIO_TXSTOP 0x04000 /* Stream output is stopped */
-#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */
-#define RIO_DYNOROD 0x10000 /* Drain failed */
-#define RIO_DELETED 0x20000 /* RTA has been deleted */
-#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */
+struct Port {
+ struct gs_port gs;
+ int PortNum; /* RIO port no., 0-511 */
+ struct Host *HostP;
+ volatile caddr_t Caddr;
+ ushort HostPort; /* Port number on host card */
+ uchar RupNum; /* Number of RUP for port */
+ uchar ID2; /* Second ID of RTA for port */
+ ulong State; /* FLAGS for open & xopen */
+#define RIO_LOPEN 0x00001 /* Local open */
+#define RIO_MOPEN 0x00002 /* Modem open */
+#define RIO_WOPEN 0x00004 /* Waiting for open */
+#define RIO_CLOSING 0x00008 /* The port is being close */
+#define RIO_XPBUSY 0x00010 /* Transparent printer busy */
+#define RIO_BREAKING 0x00020 /* Break in progress */
+#define RIO_DIRECT 0x00040 /* Doing Direct output */
+#define RIO_EXCLUSIVE 0x00080 /* Stream open for exclusive use */
+#define RIO_NDELAY 0x00100 /* Stream is open FNDELAY */
+#define RIO_CARR_ON 0x00200 /* Stream has carrier present */
+#define RIO_XPWANTR 0x00400 /* Stream wanted by Xprint */
+#define RIO_RBLK 0x00800 /* Stream is read-blocked */
+#define RIO_BUSY 0x01000 /* Stream is BUSY for write */
+#define RIO_TIMEOUT 0x02000 /* Stream timeout in progress */
+#define RIO_TXSTOP 0x04000 /* Stream output is stopped */
+#define RIO_WAITFLUSH 0x08000 /* Stream waiting for flush */
+#define RIO_DYNOROD 0x10000 /* Drain failed */
+#define RIO_DELETED 0x20000 /* RTA has been deleted */
+#define RIO_ISSCANCODE 0x40000 /* This line is in scancode mode */
#define RIO_USING_EUC 0x100000 /* Using extended Unix chars */
#define RIO_CAN_COOK 0x200000 /* This line can do cooking */
-#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */
-#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */
-#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */
-#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */
+#define RIO_TRIAD_MODE 0x400000 /* Enable TRIAD special ops. */
+#define RIO_TRIAD_BLOCK 0x800000 /* Next read will block */
+#define RIO_TRIAD_FUNC 0x1000000 /* Seen a function key coming in */
+#define RIO_THROTTLE_RX 0x2000000 /* RX needs to be throttled. */
- ulong Config; /* FLAGS for NOREAD.... */
-#define RIO_NOREAD 0x0001 /* Are not allowed to read port */
-#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */
-#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */
-#define RIO_NOMASK 0x0007 /* All not allowed things */
-#define RIO_IXANY 0x0008 /* Port is allowed ixany */
-#define RIO_MODEM 0x0010 /* Stream is a modem device */
-#define RIO_IXON 0x0020 /* Port is allowed ixon */
-#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */
+ ulong Config; /* FLAGS for NOREAD.... */
+#define RIO_NOREAD 0x0001 /* Are not allowed to read port */
+#define RIO_NOWRITE 0x0002 /* Are not allowed to write port */
+#define RIO_NOXPRINT 0x0004 /* Are not allowed to xprint port */
+#define RIO_NOMASK 0x0007 /* All not allowed things */
+#define RIO_IXANY 0x0008 /* Port is allowed ixany */
+#define RIO_MODEM 0x0010 /* Stream is a modem device */
+#define RIO_IXON 0x0020 /* Port is allowed ixon */
+#define RIO_WAITDRAIN 0x0040 /* Wait for port to completely drain */
#define RIO_MAP_50_TO_50 0x0080 /* Map 50 baud to 50 baud */
#define RIO_MAP_110_TO_110 0x0100 /* Map 110 baud to 110 baud */
@@ -144,92 +142,90 @@ struct Port
** As LynxOS does not appear to support Hardware Flow Control .....
** Define our own flow control flags in 'Config'.
*/
-#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */
-#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */
+#define RIO_CTSFLOW 0x0200 /* RIO's own CTSFLOW flag */
+#define RIO_RTSFLOW 0x0400 /* RIO's own RTSFLOW flag */
- struct PHB *PhbP; /* pointer to PHB for port */
- WORD *TxAdd; /* Add packets here */
- WORD *TxStart; /* Start of add array */
- WORD *TxEnd; /* End of add array */
- WORD *RxRemove; /* Remove packets here */
- WORD *RxStart; /* Start of remove array */
- WORD *RxEnd; /* End of remove array */
- uint RtaUniqueNum; /* Unique number of RTA */
- ushort PortState; /* status of port */
- ushort ModemState; /* status of modem lines */
- ulong ModemLines; /* Modem bits sent to RTA */
- uchar CookMode; /* who expands CR/LF? */
- uchar ParamSem; /* Prevent write during param */
- uchar Mapped; /* if port mapped onto host */
- uchar SecondBlock; /* if port belongs to 2nd block
- of 16 port RTA */
- uchar InUse; /* how many pre-emptive cmds */
- uchar Lock; /* if params locked */
- uchar Store; /* if params stored across closes */
- uchar FirstOpen; /* TRUE if first time port opened */
- uchar FlushCmdBodge; /* if doing a (non)flush */
- uchar MagicFlags; /* require intr processing */
+ struct PHB *PhbP; /* pointer to PHB for port */
+ WORD *TxAdd; /* Add packets here */
+ WORD *TxStart; /* Start of add array */
+ WORD *TxEnd; /* End of add array */
+ WORD *RxRemove; /* Remove packets here */
+ WORD *RxStart; /* Start of remove array */
+ WORD *RxEnd; /* End of remove array */
+ uint RtaUniqueNum; /* Unique number of RTA */
+ ushort PortState; /* status of port */
+ ushort ModemState; /* status of modem lines */
+ ulong ModemLines; /* Modem bits sent to RTA */
+ uchar CookMode; /* who expands CR/LF? */
+ uchar ParamSem; /* Prevent write during param */
+ uchar Mapped; /* if port mapped onto host */
+ uchar SecondBlock; /* if port belongs to 2nd block
+ of 16 port RTA */
+ uchar InUse; /* how many pre-emptive cmds */
+ uchar Lock; /* if params locked */
+ uchar Store; /* if params stored across closes */
+ uchar FirstOpen; /* TRUE if first time port opened */
+ uchar FlushCmdBodge; /* if doing a (non)flush */
+ uchar MagicFlags; /* require intr processing */
#define MAGIC_FLUSH 0x01 /* mirror of WflushFlag */
#define MAGIC_REBOOT 0x02 /* RTA re-booted, re-open ports */
#define MORE_OUTPUT_EYGOR 0x04 /* riotproc failed to empty clists */
- uchar WflushFlag; /* 1 How many WFLUSHs active */
+ uchar WflushFlag; /* 1 How many WFLUSHs active */
/*
** Transparent print stuff
*/
- struct Xprint
- {
+ struct Xprint {
#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */
+#define MAX_XP_CTRL_LEN 16 /* ALSO IN DAEMON.H */
#endif
- uint XpCps;
- char XpOn[MAX_XP_CTRL_LEN];
- char XpOff[MAX_XP_CTRL_LEN];
- ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */
- uchar XpActive;
- uchar XpLastTickOk; /* TRUE if we can process */
+ uint XpCps;
+ char XpOn[MAX_XP_CTRL_LEN];
+ char XpOff[MAX_XP_CTRL_LEN];
+ ushort XpLen; /* strlen(XpOn)+strlen(XpOff) */
+ uchar XpActive;
+ uchar XpLastTickOk; /* TRUE if we can process */
#define XP_OPEN 00001
#define XP_RUNABLE 00002
- struct ttystatics *XttyP;
- } Xprint;
+ struct ttystatics *XttyP;
+ } Xprint;
#ifdef VPIX
- v86_t *StashP;
- uint IntMask;
- struct termss VpixSs;
- uchar ModemStatusReg; /* Modem status register */
+ v86_t *StashP;
+ uint IntMask;
+ struct termss VpixSs;
+ uchar ModemStatusReg; /* Modem status register */
#endif
- uchar RxDataStart;
- uchar Cor2Copy; /* copy of COR2 */
- char *Name; /* points to the Rta's name */
+ uchar RxDataStart;
+ uchar Cor2Copy; /* copy of COR2 */
+ char *Name; /* points to the Rta's name */
#ifdef STATS
- struct RIOStats Stat; /* ports statistics */
+ struct RIOStats Stat; /* ports statistics */
#endif
- char *TxRingBuffer;
- ushort TxBufferIn; /* New data arrives here */
- ushort TxBufferOut; /* Intr removes data here */
- ushort OldTxBufferOut; /* Indicates if draining */
- int TimeoutId; /* Timeout ID */
- uint Debug;
- uchar WaitUntilBooted; /* True if open should block */
- uint statsGather; /* True if gathering stats */
- ulong txchars; /* Chars transmitted */
- ulong rxchars; /* Chars received */
- ulong opens; /* port open count */
- ulong closes; /* port close count */
- ulong ioctls; /* ioctl count */
- uchar LastRxTgl; /* Last state of rx toggle bit */
- spinlock_t portSem; /* Lock using this sem */
- int MonitorTstate; /* Monitoring ? */
- int timeout_id; /* For calling 100 ms delays */
- int timeout_sem;/* For calling 100 ms delays */
- int firstOpen; /* First time open ? */
- char * p; /* save the global struc here .. */
+ char *TxRingBuffer;
+ ushort TxBufferIn; /* New data arrives here */
+ ushort TxBufferOut; /* Intr removes data here */
+ ushort OldTxBufferOut; /* Indicates if draining */
+ int TimeoutId; /* Timeout ID */
+ uint Debug;
+ uchar WaitUntilBooted; /* True if open should block */
+ uint statsGather; /* True if gathering stats */
+ ulong txchars; /* Chars transmitted */
+ ulong rxchars; /* Chars received */
+ ulong opens; /* port open count */
+ ulong closes; /* port close count */
+ ulong ioctls; /* ioctl count */
+ uchar LastRxTgl; /* Last state of rx toggle bit */
+ spinlock_t portSem; /* Lock using this sem */
+ int MonitorTstate; /* Monitoring ? */
+ int timeout_id; /* For calling 100 ms delays */
+ int timeout_sem; /* For calling 100 ms delays */
+ int firstOpen; /* First time open ? */
+ char *p; /* save the global struc here .. */
};
-struct ModuleInfo
-{
- char *Name;
- uint Flags[4]; /* one per port on a module */
+struct ModuleInfo {
+ char *Name;
+ uint Flags[4]; /* one per port on a module */
};
#endif
@@ -238,8 +234,8 @@ struct ModuleInfo
** runs into problems with differing struct sizes between driver and config.
*/
struct PortParams {
- uint Port;
- ulong Config;
- ulong State;
- struct ttystatics *TtyP;
+ uint Port;
+ ulong Config;
+ ulong State;
+ struct ttystatics *TtyP;
};
diff --git a/drivers/char/rio/proto.h b/drivers/char/rio/proto.h
deleted file mode 100644
index ddff0ef84e3a..000000000000
--- a/drivers/char/rio/proto.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 _prototypes_h
-#define _prototypes_h
-
-
-/*
-** boot.c
-*/
-void init_boot( char *p, short stage);
-
-/*
-** disconct.c
-*/
-void kill_boot ( LPB *link );
-void disconnected( LPB *link );
-short boot_3( LPB *link, PKT *pkt );
-short send_3_pkt( LPB *link, PKT *pkt);
-
-/*
-** error.c
-*/
-void du_error(void);
-
-/*
-** formpkt.c
-*/
-ushort sum_it( PKT *pkt ) ;
-void form_rup_pkt( RUP *form_rup, PKT *pkt );
-void form_poll_pkt ( int type, LPB *link, int node );
-void form_route_pkt ( int type, PKT *pkt, LPB *link );
-
-/*
-** idle.c
-*/
-void idle( Process *idle_p );
-
-/*
-** init.c
-*/
-void general_init(void);
-void mem_halt( int error);
-
-/*
-** linkinit.c
-*/
-void initlink( u_short number, LPB *link);
-void runlink( LPB *link);
-
-/*
-** list.c
-*/
-PKT *get_free_start(void);
-void put_free_start( PKT *pkt);
-
-#ifdef HOST
-int can_remove_transmit ( PKT **pkt, PKT *pointer );
-#endif
-
-#ifdef RTA
-int spl7 ( void );
-int spl0 ( void );
-Q_BUF *get_free_q( void );
-PKT *get_free_end(void);
-int add_end( PKT *pkt, PHB *phb, int type);
-unsigned short free_packets( PHB *phb, int type);
-int can_remove_start( PKT **pkt, PHB *phb, int type);
-int can_add_start( PHB *phb, int type);
-int can_add_end( PHB *phb, int type);
-void put_free_end( PKT *pkt);
-int remove_start( PKT **pkt, PHB *phb, int type);
-#endif
-
-/*
-** Lrt.c
-*/
-void lrt( Process *lrt_p, LPB *link );
-
-#ifdef RTA
-void set_led_red ( LPB *link );
-#endif
-
-/*
-** ltt.c
-*/
-void ltt( Process *ltt_p, LPB *link, PHB *phb_ptr[] );
-void send_poll ( LPB *link );
-void request_id ( LPB *link );
-void send_topology_update ( LPB *link );
-void send_topology ( LPB *link );
-void supply_id ( LPB *link );
-
-#ifdef RTA
-void redirect_queue ( LPB *link, ushort flush );
-int obtain_rup ( int rup_number, PKT **pkt_address, LPB *link );
-#endif
-
-#ifdef TESTING_PERF
-int consume_cpu( void );
-#endif
-
-/*
-** lttwake.c
-*/
-#ifdef HOST
-void ltt_wakeup( Process *ltt_wakeup_p );
-#endif
-
-/*
-** mapgen.c
-*/
-void generate_id_map( short mapping, ROUTE_STR route[] );
-void gen_map( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl );
-void adjust_ttl( int mapping, int looking_at, int come_from, ROUTE_STR route[], int link, int *ttl);
-void init_sys_map(void);
-
-/*
-** mmu.c
-*/
-char *rio_malloc( unsigned int amount);
-char *rio_calloc( unsigned int num, unsigned int size);
-ERROR rio_mmu_init( uint total_mem );
-
-/*
-** partn.c
-*/
-void partition_tx( struct PHB *phb, u_short tx_size, u_short rx_size, u_short rx_limit);
-
-/*
-** poll.c
-*/
-void tx_poll( Process *tx_poll_p);
-
-/*
-** process.c
-*/
-int get_proc_space( Process **pd, int **pws, int wssize);
-
-/*
-** readrom.c
-*/
-void read_serial_number(char *buf);
-
-/*
-** rio.c
-*/
-int main( void );
-
-/*
-** route.c
-*/
-void route_update ( PKT *pkt, LPB *link);
-
-/*
-** rtainit.c
-*/
-#if defined(RTA)
-void rta_init(ushort RtaType);
-#endif /* defined(RTA) */
-
-/*
-** rupboot.c
-*/
-void rup_boot( PKT *pkt, RUP *this_rup, LPB *link);
-
-#ifdef RTA
-void kill_your_neighbour( int link_to_kill );
-#endif
-
-/*
-** rupcmd.c
-*/
-void rup_command( PKT *pkt, struct RUP *this_rup, LPB *link);
-
-/*
-** ruperr.c
-*/
-void rup_error( PKT *pkt, RUP *this_rup, LPB *link );
-void illegal_cmd( PKT *src_pkt );
-
-/*
-** ruppoll.c
-*/
-void rup_poll( PKT *pkt, RUP *this_rup, LPB *link );
-
-/*
-** ruppower.c
-*/
-void rup_power( PKT *pkt, RUP *this_rup, LPB *link );
-
-/*
-** ruprm.c
-*/
-void rup_route_map( PKT *pkt, RUP *this_rup, LPB *link);
-
-/*
-** rupstat.c
-*/
-void rup_status( PKT *pkt, RUP *this_rup, LPB *link);
-
-/*
-** rupsync.c
-*/
-void rup_sync( PKT *pkt);
-
-/*
-** rxpkt.c
-*/
-ERROR rx_pkt( PKT_ptr_ptr pkt_address, LPB *link);
-
-/*
-** sendsts.c
-*/
-void send_status( PKT *requesting_pkt, RUP *this_rup);
-
-/*
-** serial.c
-*/
-void assign_serial ( char *ser_in, char *ser_out);
-int cmp_serial ( char *ser_1, char *ser_2);
-
-/*
-** txpkt.c
-*/
-ERROR tx_pkt( PKT *pkt, LPB *link);
-short send_sync( LPB *link);
-
-#endif /* _prototypes_h */
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h
index 848111ac9380..69fc4bc34153 100644
--- a/drivers/char/rio/protsts.h
+++ b/drivers/char/rio/protsts.h
@@ -115,5 +115,3 @@
#endif
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/qbuf.h b/drivers/char/rio/qbuf.h
index 1fce02f8fcfc..acd9e8e5307d 100644
--- a/drivers/char/rio/qbuf.h
+++ b/drivers/char/rio/qbuf.h
@@ -40,7 +40,7 @@
#ifndef lint
#ifdef SCCS_LABELS
-static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1" ;
+static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1";
#endif
#endif
@@ -52,16 +52,15 @@ static char *_rio_qbuf_h_sccs = "@(#)qbuf.h 1.1" ;
#define PKTS_PER_BUFFER (220 / PKT_LENGTH)
#endif
-typedef struct Q_BUF Q_BUF ;
-struct Q_BUF {
- Q_BUF_ptr next ;
- Q_BUF_ptr prev ;
- PKT_ptr buf[PKTS_PER_BUFFER] ;
- } ;
+typedef struct Q_BUF Q_BUF;
+struct Q_BUF {
+ Q_BUF_ptr next;
+ Q_BUF_ptr prev;
+ PKT_ptr buf[PKTS_PER_BUFFER];
+};
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
index 13a9931958b1..7f45e1ab5332 100644
--- a/drivers/char/rio/rio.h
+++ b/drivers/char/rio/rio.h
@@ -72,8 +72,8 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3";
#define RIO_HOSTS 4 /* number of hosts that can be found */
#define PORTS_PER_HOST 128 /* number of ports per host */
#define LINKS_PER_UNIT 4 /* number of links from a host */
-#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
-#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */
+#define RIO_PORTS (PORTS_PER_HOST * RIO_HOSTS) /* max. no. of ports */
+#define RTAS_PER_HOST (MAX_RUP) /* number of RTAs per host */
#define PORTS_PER_RTA (PORTS_PER_HOST/RTAS_PER_HOST) /* ports on a rta */
#define PORTS_PER_MODULE 4 /* number of ports on a plug-in module */
/* number of modules on an RTA */
@@ -216,10 +216,9 @@ static char *_rio_h_sccs_ = "@(#)rio.h 1.3";
#define RIO_PRI (PZERO+10)
#define RIO_CLOSE_PRI PZERO-1 /* uninterruptible sleeps for close */
-typedef struct DbInf
-{
- uint Flag;
- char Name[8];
+typedef struct DbInf {
+ uint Flag;
+ char Name[8];
} DbInf;
#ifndef TRUE
@@ -251,7 +250,7 @@ typedef struct DbInf
*((uint *)PK) = PP->PacketInfo; \
}
-#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */
+#define RIO_LINK_ENABLE 0x80FF /* FF is a hack, mainly for Mips, to */
/* prevent a really stupid race condition. */
#define NOT_INITIALISED 0
@@ -291,4 +290,4 @@ typedef struct DbInf
#define DIST_LINESW_OUTPUT 0x40
#define DIST_LINESW_MDMINT 0x80
-#endif /* __rio_h__ */
+#endif /* __rio_h__ */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d7d484024e2b..c9af283a811d 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -33,7 +33,7 @@
* */
#include <linux/module.h>
-#include <linux/config.h>
+#include <linux/config.h>
#include <linux/kdev_t.h>
#include <asm/io.h>
#include <linux/kernel.h>
@@ -56,10 +56,6 @@
#include <linux/generic_serial.h>
#include <asm/uaccess.h>
-#if BITS_PER_LONG != 32
-# error FIXME: this driver only works on 32-bit platforms
-#endif
-
#include "linux_compat.h"
#include "typdef.h"
#include "pkt.h"
@@ -116,7 +112,7 @@ more than 512 ports.... */
#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
#endif
-#ifndef RIO_WINDOW_LEN
+#ifndef RIO_WINDOW_LEN
#define RIO_WINDOW_LEN 0x10000
#endif
@@ -136,42 +132,49 @@ more than 512 ports.... */
*/
#define IRQ_RATE_LIMIT 200
-#if 0
-/* Not implemented */
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define RIO_REPORT_FIFO
-#define RIO_REPORT_OVERRUN
-#endif
-
/* These constants are derived from SCO Source */
static struct Conf
-RIOConf =
-{
- /* locator */ "RIO Config here",
- /* startuptime */ HZ*2, /* how long to wait for card to run */
- /* slowcook */ 0, /* TRUE -> always use line disc. */
- /* intrpolltime */ 1, /* The frequency of OUR polls */
- /* breakinterval */ 25, /* x10 mS XXX: units seem to be 1ms not 10! -- REW*/
- /* timer */ 10, /* mS */
- /* RtaLoadBase */ 0x7000,
- /* HostLoadBase */ 0x7C00,
- /* XpHz */ 5, /* number of Xprint hits per second */
- /* XpCps */ 120, /* Xprint characters per second */
- /* XpOn */ "\033d#", /* start Xprint for a wyse 60 */
- /* XpOff */ "\024", /* end Xprint for a wyse 60 */
- /* MaxXpCps */ 2000, /* highest Xprint speed */
- /* MinXpCps */ 10, /* slowest Xprint speed */
- /* SpinCmds */ 1, /* non-zero for mega fast boots */
- /* First Addr */ 0x0A0000, /* First address to look at */
- /* Last Addr */ 0xFF0000, /* Last address looked at */
- /* BufferSize */ 1024, /* Bytes per port of buffering */
- /* LowWater */ 256, /* how much data left before wakeup */
- /* LineLength */ 80, /* how wide is the console? */
- /* CmdTimeout */ HZ, /* how long a close command may take */
+ RIOConf = {
+ /* locator */ "RIO Config here",
+ /* startuptime */ HZ * 2,
+ /* how long to wait for card to run */
+ /* slowcook */ 0,
+ /* TRUE -> always use line disc. */
+ /* intrpolltime */ 1,
+ /* The frequency of OUR polls */
+ /* breakinterval */ 25,
+ /* x10 mS XXX: units seem to be 1ms not 10! -- REW */
+ /* timer */ 10,
+ /* mS */
+ /* RtaLoadBase */ 0x7000,
+ /* HostLoadBase */ 0x7C00,
+ /* XpHz */ 5,
+ /* number of Xprint hits per second */
+ /* XpCps */ 120,
+ /* Xprint characters per second */
+ /* XpOn */ "\033d#",
+ /* start Xprint for a wyse 60 */
+ /* XpOff */ "\024",
+ /* end Xprint for a wyse 60 */
+ /* MaxXpCps */ 2000,
+ /* highest Xprint speed */
+ /* MinXpCps */ 10,
+ /* slowest Xprint speed */
+ /* SpinCmds */ 1,
+ /* non-zero for mega fast boots */
+ /* First Addr */ 0x0A0000,
+ /* First address to look at */
+ /* Last Addr */ 0xFF0000,
+ /* Last address looked at */
+ /* BufferSize */ 1024,
+ /* Bytes per port of buffering */
+ /* LowWater */ 256,
+ /* how much data left before wakeup */
+ /* LineLength */ 80,
+ /* how wide is the console? */
+ /* CmdTimeout */ HZ,
+ /* how long a close command may take */
};
@@ -179,21 +182,20 @@ RIOConf =
/* Function prototypes */
-static void rio_disable_tx_interrupts (void * ptr);
-static void rio_enable_tx_interrupts (void * ptr);
-static void rio_disable_rx_interrupts (void * ptr);
-static void rio_enable_rx_interrupts (void * ptr);
-static int rio_get_CD (void * ptr);
-static void rio_shutdown_port (void * ptr);
-static int rio_set_real_termios (void *ptr);
-static void rio_hungup (void *ptr);
-static void rio_close (void *ptr);
-static int rio_chars_in_buffer (void * ptr);
-static int rio_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg);
+static void rio_disable_tx_interrupts(void *ptr);
+static void rio_enable_tx_interrupts(void *ptr);
+static void rio_disable_rx_interrupts(void *ptr);
+static void rio_enable_rx_interrupts(void *ptr);
+static int rio_get_CD(void *ptr);
+static void rio_shutdown_port(void *ptr);
+static int rio_set_real_termios(void *ptr);
+static void rio_hungup(void *ptr);
+static void rio_close(void *ptr);
+static int rio_chars_in_buffer(void *ptr);
+static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static int rio_init_drivers(void);
-static void my_hd (void *addr, int len);
+static void my_hd(void *addr, int len);
static struct tty_driver *rio_driver, *rio_driver2;
@@ -213,9 +215,9 @@ static int rio_poll = 1;
/* These are the only open spaces in my computer. Yours may have more
or less.... */
-static int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000};
+static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
-#define NR_RIO_ADDRS (sizeof(rio_probe_addrs)/sizeof (int))
+#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
/* Set the mask to all-ones. This alas, only supports 32 interrupts.
@@ -231,17 +233,17 @@ module_param(rio_debug, int, 0644);
module_param(rio_irqmask, long, 0);
static struct real_driver rio_real_driver = {
- rio_disable_tx_interrupts,
- rio_enable_tx_interrupts,
- rio_disable_rx_interrupts,
- rio_enable_rx_interrupts,
- rio_get_CD,
- rio_shutdown_port,
- rio_set_real_termios,
- rio_chars_in_buffer,
- rio_close,
- rio_hungup,
- NULL
+ rio_disable_tx_interrupts,
+ rio_enable_tx_interrupts,
+ rio_disable_rx_interrupts,
+ rio_enable_rx_interrupts,
+ rio_get_CD,
+ rio_shutdown_port,
+ rio_set_real_termios,
+ rio_chars_in_buffer,
+ rio_close,
+ rio_hungup,
+ NULL
};
/*
@@ -250,8 +252,8 @@ static struct real_driver rio_real_driver = {
*/
static struct file_operations rio_fw_fops = {
- .owner = THIS_MODULE,
- .ioctl = rio_fw_ioctl,
+ .owner = THIS_MODULE,
+ .ioctl = rio_fw_ioctl,
};
static struct miscdevice rio_fw_device = {
@@ -266,25 +268,22 @@ static struct miscdevice rio_fw_device = {
/* This doesn't work. Who's paranoid around here? Not me! */
-static inline int rio_paranoia_check(struct rio_port const * port,
- char *name, const char *routine)
+static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
{
- static const char *badmagic =
- KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
- static const char *badinfo =
- KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
-
- if (!port) {
- printk (badinfo, name, routine);
- return 1;
- }
- if (port->magic != RIO_MAGIC) {
- printk (badmagic, name, routine);
- return 1;
- }
-
- return 0;
+ static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
+ static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
+
+ if (!port) {
+ printk(badinfo, name, routine);
+ return 1;
+ }
+ if (port->magic != RIO_MAGIC) {
+ printk(badmagic, name, routine);
+ return 1;
+ }
+
+ return 0;
}
#else
#define rio_paranoia_check(a,b,c) 0
@@ -292,53 +291,53 @@ static inline int rio_paranoia_check(struct rio_port const * port,
#ifdef DEBUG
-static void my_hd (void *ad, int len)
+static void my_hd(void *ad, int len)
{
- int i, j, ch;
- unsigned char *addr = ad;
-
- for (i=0;i<len;i+=16) {
- rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
- for (j=0;j<16;j++) {
- rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
- }
- for (j=0;j<16;j++) {
- ch = addr[j+i];
- rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
- }
- rio_dprintk (RIO_DEBUG_PARAM, "\n");
- }
+ int i, j, ch;
+ unsigned char *addr = ad;
+
+ for (i = 0; i < len; i += 16) {
+ rio_dprintk(RIO_DEBUG_PARAM, "%08x ", (int) addr + i);
+ for (j = 0; j < 16; j++) {
+ rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
+ }
+ for (j = 0; j < 16; j++) {
+ ch = addr[j + i];
+ rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
+ }
+ rio_dprintk(RIO_DEBUG_PARAM, "\n");
+ }
}
#else
#define my_hd(ad,len) do{/* nothing*/ } while (0)
#endif
-/* Delay a number of jiffies, allowing a signal to interrupt */
-int RIODelay (struct Port *PortP, int njiffies)
+/* Delay a number of jiffies, allowing a signal to interrupt */
+int RIODelay(struct Port *PortP, int njiffies)
{
- func_enter ();
+ func_enter();
- rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
- msleep_interruptible(jiffies_to_msecs(njiffies));
- func_exit();
+ rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
+ msleep_interruptible(jiffies_to_msecs(njiffies));
+ func_exit();
- if (signal_pending(current))
- return RIO_FAIL;
- else
- return !RIO_FAIL;
+ if (signal_pending(current))
+ return RIO_FAIL;
+ else
+ return !RIO_FAIL;
}
-/* Delay a number of jiffies, disallowing a signal to interrupt */
-int RIODelay_ni (struct Port *PortP, int njiffies)
+/* Delay a number of jiffies, disallowing a signal to interrupt */
+int RIODelay_ni(struct Port *PortP, int njiffies)
{
- func_enter ();
+ func_enter();
- rio_dprintk (RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
- msleep(jiffies_to_msecs(njiffies));
- func_exit();
- return !RIO_FAIL;
+ rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
+ msleep(jiffies_to_msecs(njiffies));
+ func_exit();
+ return !RIO_FAIL;
}
@@ -354,126 +353,121 @@ int rio_ismodem(struct tty_struct *tty)
}
-static int rio_set_real_termios (void *ptr)
+static int rio_set_real_termios(void *ptr)
{
- int rv, modem;
- struct tty_struct *tty;
- func_enter();
+ int rv, modem;
+ struct tty_struct *tty;
+ func_enter();
- tty = ((struct Port *)ptr)->gs.tty;
+ tty = ((struct Port *) ptr)->gs.tty;
- modem = rio_ismodem(tty);
+ modem = rio_ismodem(tty);
- rv = RIOParam( (struct Port *) ptr, CONFIG, modem, 1);
+ rv = RIOParam((struct Port *) ptr, CONFIG, modem, 1);
- func_exit ();
+ func_exit();
- return rv;
+ return rv;
}
-static void rio_reset_interrupt (struct Host *HostP)
+static void rio_reset_interrupt(struct Host *HostP)
{
- func_enter();
+ func_enter();
- switch( HostP->Type ) {
- case RIO_AT:
- case RIO_MCA:
- case RIO_PCI:
- WBYTE(HostP->ResetInt , 0xff);
- }
+ switch (HostP->Type) {
+ case RIO_AT:
+ case RIO_MCA:
+ case RIO_PCI:
+ WBYTE(HostP->ResetInt, 0xff);
+ }
- func_exit();
+ func_exit();
}
-static irqreturn_t rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t rio_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
- struct Host *HostP;
- func_enter ();
+ struct Host *HostP;
+ func_enter();
- HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n",
- irq, HostP->Ivec);
+ HostP = (struct Host *) ptr; /* &p->RIOHosts[(long)ptr]; */
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
- /* AAargh! The order in which to do these things is essential and
- not trivial.
-
- - Rate limit goes before "recursive". Otherwise a series of
- recursive calls will hang the machine in the interrupt routine.
+ /* AAargh! The order in which to do these things is essential and
+ not trivial.
- - hardware twiddling goes before "recursive". Otherwise when we
- poll the card, and a recursive interrupt happens, we won't
- ack the card, so it might keep on interrupting us. (especially
- level sensitive interrupt systems like PCI).
+ - Rate limit goes before "recursive". Otherwise a series of
+ recursive calls will hang the machine in the interrupt routine.
- - Rate limit goes before hardware twiddling. Otherwise we won't
- catch a card that has gone bonkers.
+ - hardware twiddling goes before "recursive". Otherwise when we
+ poll the card, and a recursive interrupt happens, we won't
+ ack the card, so it might keep on interrupting us. (especially
+ level sensitive interrupt systems like PCI).
- - The "initialized" test goes after the hardware twiddling. Otherwise
- the card will stick us in the interrupt routine again.
+ - Rate limit goes before hardware twiddling. Otherwise we won't
+ catch a card that has gone bonkers.
- - The initialized test goes before recursive.
- */
+ - The "initialized" test goes after the hardware twiddling. Otherwise
+ the card will stick us in the interrupt routine again.
+
+ - The initialized test goes before recursive.
+ */
#ifdef IRQ_RATE_LIMIT
- /* Aaargh! I'm ashamed. This costs more lines-of-code than the
- actual interrupt routine!. (Well, used to when I wrote that comment) */
- {
- static int lastjif;
- static int nintr=0;
-
- if (lastjif == jiffies) {
- if (++nintr > IRQ_RATE_LIMIT) {
- free_irq (HostP->Ivec, ptr);
- printk (KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n",
- HostP->Ivec);
- }
- } else {
- lastjif = jiffies;
- nintr = 0;
- }
- }
+ /* Aaargh! I'm ashamed. This costs more lines-of-code than the
+ actual interrupt routine!. (Well, used to when I wrote that comment) */
+ {
+ static int lastjif;
+ static int nintr = 0;
+
+ if (lastjif == jiffies) {
+ if (++nintr > IRQ_RATE_LIMIT) {
+ free_irq(HostP->Ivec, ptr);
+ printk(KERN_ERR "rio: Too many interrupts. Turning off interrupt %d.\n", HostP->Ivec);
+ }
+ } else {
+ lastjif = jiffies;
+ nintr = 0;
+ }
+ }
#endif
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
- if (HostP->Ivec == irq) {
- /* Tell the card we've noticed the interrupt. */
- rio_reset_interrupt (HostP);
- }
-
- if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
- return IRQ_HANDLED;
-
- if (test_and_set_bit (RIO_BOARD_INTR_LOCK, &HostP->locks)) {
- printk (KERN_ERR "Recursive interrupt! (host %d/irq%d)\n",
- (int) ptr, HostP->Ivec);
- return IRQ_HANDLED;
- }
-
- RIOServiceHost(p, HostP, irq);
-
- rio_dprintk ( RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n",
- (int) ptr, HostP->Type);
-
- clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
- rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n",
- irq, HostP->Ivec);
- func_exit ();
- return IRQ_HANDLED;
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
+ if (HostP->Ivec == irq) {
+ /* Tell the card we've noticed the interrupt. */
+ rio_reset_interrupt(HostP);
+ }
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
+ return IRQ_HANDLED;
+
+ if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
+ printk(KERN_ERR "Recursive interrupt! (host %d/irq%d)\n", (int) ptr, HostP->Ivec);
+ return IRQ_HANDLED;
+ }
+
+ RIOServiceHost(p, HostP, irq);
+
+ rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %d type %d\n", (int) ptr, HostP->Type);
+
+ clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
+ rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
+ func_exit();
+ return IRQ_HANDLED;
}
-static void rio_pollfunc (unsigned long data)
+static void rio_pollfunc(unsigned long data)
{
- func_enter ();
+ func_enter();
- rio_interrupt (0, &p->RIOHosts[data], NULL);
- p->RIOHosts[data].timer.expires = jiffies + rio_poll;
- add_timer (&p->RIOHosts[data].timer);
+ rio_interrupt(0, &p->RIOHosts[data], NULL);
+ p->RIOHosts[data].timer.expires = jiffies + rio_poll;
+ add_timer(&p->RIOHosts[data].timer);
- func_exit ();
+ func_exit();
}
@@ -485,106 +479,91 @@ static void rio_pollfunc (unsigned long data)
/* Ehhm. I don't know how to fiddle with interrupts on the Specialix
cards. .... Hmm. Ok I figured it out. You don't. -- REW */
-static void rio_disable_tx_interrupts (void * ptr)
+static void rio_disable_tx_interrupts(void *ptr)
{
- func_enter();
+ func_enter();
- /* port->gs.flags &= ~GS_TX_INTEN; */
+ /* port->gs.flags &= ~GS_TX_INTEN; */
- func_exit();
+ func_exit();
}
-static void rio_enable_tx_interrupts (void * ptr)
+static void rio_enable_tx_interrupts(void *ptr)
{
- struct Port *PortP = ptr;
- /* int hn; */
+ struct Port *PortP = ptr;
+ /* int hn; */
- func_enter();
+ func_enter();
- /* hn = PortP->HostP - p->RIOHosts;
+ /* hn = PortP->HostP - p->RIOHosts;
- rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
- rio_interrupt (-1,(void *) hn, NULL); */
+ rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
+ rio_interrupt (-1,(void *) hn, NULL); */
- RIOTxEnable((char *) PortP);
+ RIOTxEnable((char *) PortP);
- /*
- * In general we cannot count on "tx empty" interrupts, although
- * the interrupt routine seems to be able to tell the difference.
- */
- PortP->gs.flags &= ~GS_TX_INTEN;
+ /*
+ * In general we cannot count on "tx empty" interrupts, although
+ * the interrupt routine seems to be able to tell the difference.
+ */
+ PortP->gs.flags &= ~GS_TX_INTEN;
- func_exit();
+ func_exit();
}
-static void rio_disable_rx_interrupts (void * ptr)
+static void rio_disable_rx_interrupts(void *ptr)
{
- func_enter();
- func_exit();
+ func_enter();
+ func_exit();
}
-static void rio_enable_rx_interrupts (void * ptr)
+static void rio_enable_rx_interrupts(void *ptr)
{
- /* struct rio_port *port = ptr; */
- func_enter();
- func_exit();
+ /* struct rio_port *port = ptr; */
+ func_enter();
+ func_exit();
}
/* Jeez. Isn't this simple? */
-static int rio_get_CD (void * ptr)
+static int rio_get_CD(void *ptr)
{
- struct Port *PortP = ptr;
- int rv;
+ struct Port *PortP = ptr;
+ int rv;
- func_enter();
- rv = (PortP->ModemState & MSVR1_CD) != 0;
+ func_enter();
+ rv = (PortP->ModemState & MSVR1_CD) != 0;
+
+ rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
- rio_dprintk (RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
-
- func_exit();
- return rv;
+ func_exit();
+ return rv;
}
/* Jeez. Isn't this simple? Actually, we can sync with the actual port
by just pushing stuff into the queue going to the port... */
-static int rio_chars_in_buffer (void * ptr)
+static int rio_chars_in_buffer(void *ptr)
{
- func_enter();
+ func_enter();
- func_exit();
- return 0;
+ func_exit();
+ return 0;
}
/* Nothing special here... */
-static void rio_shutdown_port (void * ptr)
+static void rio_shutdown_port(void *ptr)
{
- struct Port *PortP;
-
- func_enter();
-
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
-#if 0
- port->gs.flags &= ~ GS_ACTIVE;
- if (!port->gs.tty) {
- rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
- return;
- }
- if (!port->gs.tty->termios) {
- rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
- return;
- }
- if (port->gs.tty->termios->c_cflag & HUPCL) {
- rio_setsignals (port, 0, 0);
- }
-#endif
+ struct Port *PortP;
+
+ func_enter();
- func_exit();
+ PortP = (struct Port *) ptr;
+ PortP->gs.tty = NULL;
+ func_exit();
}
@@ -595,16 +574,16 @@ static void rio_shutdown_port (void * ptr)
running minicom on a serial port that is driven by a modularized
driver. Have the modem hangup. Then remove the driver module. Then
exit minicom. I expect an "oops". -- REW */
-static void rio_hungup (void *ptr)
+static void rio_hungup(void *ptr)
{
- struct Port *PortP;
+ struct Port *PortP;
+
+ func_enter();
- func_enter();
-
- PortP = (struct Port *)ptr;
- PortP->gs.tty = NULL;
+ PortP = (struct Port *) ptr;
+ PortP->gs.tty = NULL;
- func_exit ();
+ func_exit();
}
@@ -612,146 +591,100 @@ static void rio_hungup (void *ptr)
this.
rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
*/
-static void rio_close (void *ptr)
+static void rio_close(void *ptr)
{
- struct Port *PortP;
+ struct Port *PortP;
- func_enter ();
+ func_enter();
- PortP = (struct Port *)ptr;
+ PortP = (struct Port *) ptr;
- riotclose (ptr);
+ riotclose(ptr);
- if(PortP->gs.count) {
- printk (KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
- PortP->gs.count = 0;
- }
+ if (PortP->gs.count) {
+ printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.count);
+ PortP->gs.count = 0;
+ }
- PortP->gs.tty = NULL;
- func_exit ();
+ PortP->gs.tty = NULL;
+ func_exit();
}
-static int rio_fw_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
- int rc = 0;
- func_enter();
+ int rc = 0;
+ func_enter();
- /* The "dev" argument isn't used. */
- rc = riocontrol (p, 0, cmd, (void *)arg, capable(CAP_SYS_ADMIN));
+ /* The "dev" argument isn't used. */
+ rc = riocontrol(p, 0, cmd, (void *) arg, capable(CAP_SYS_ADMIN));
- func_exit ();
- return rc;
+ func_exit();
+ return rc;
}
-extern int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg);
+extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-static int rio_ioctl (struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
+static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
{
- int rc;
- struct Port *PortP;
- int ival;
-
- func_enter();
+ int rc;
+ struct Port *PortP;
+ int ival;
- PortP = (struct Port *)tty->driver_data;
+ func_enter();
- rc = 0;
- switch (cmd) {
-#if 0
- case TIOCGSOFTCAR:
- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
- (unsigned int *) arg);
- break;
-#endif
- case TIOCSSOFTCAR:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- tty->termios->c_cflag =
- (tty->termios->c_cflag & ~CLOCAL) |
- (ival ? CLOCAL : 0);
- }
- break;
- case TIOCGSERIAL:
- rc = -EFAULT;
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct)))
- rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
- break;
- case TCSBRK:
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
- rc = -EIO;
- } else {
- if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- rc = -EIO;
- }
- }
- break;
- case TCSBRKP:
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
- rc = -EIO;
- } else {
- int l;
- l = arg?arg*100:250;
- if (l > 255) l = 255;
- if (RIOShortCommand(p, PortP, SBREAK, 2, arg?arg*100:250) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- rc = -EIO;
- }
- }
- break;
- case TIOCSSERIAL:
- rc = -EFAULT;
- if (access_ok(VERIFY_READ, (void *) arg,
- sizeof(struct serial_struct)))
- rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
- break;
-#if 0
- /*
- * note: these IOCTLs no longer reach here. Use
- * tiocmset/tiocmget driver methods instead. The
- * #if 0 disablement predates this comment.
- */
- case TIOCMGET:
- rc = -EFAULT;
- if (access_ok(VERIFY_WRITE, (void *) arg,
- sizeof(unsigned int))) {
- rc = 0;
- ival = rio_getsignals(port);
- put_user(ival, (unsigned int *) arg);
- }
- break;
- case TIOCMBIS:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1),
- ((ival & TIOCM_RTS) ? 1 : -1));
- }
- break;
- case TIOCMBIC:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1),
- ((ival & TIOCM_RTS) ? 0 : -1));
- }
- break;
- case TIOCMSET:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0),
- ((ival & TIOCM_RTS) ? 1 : 0));
- }
- break;
-#endif
- default:
- rc = -ENOIOCTLCMD;
- break;
- }
- func_exit();
- return rc;
+ PortP = (struct Port *) tty->driver_data;
+
+ rc = 0;
+ switch (cmd) {
+ case TIOCSSOFTCAR:
+ if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+ tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
+ }
+ break;
+ case TIOCGSERIAL:
+ rc = -EFAULT;
+ if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)))
+ rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
+ break;
+ case TCSBRK:
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+ rc = -EIO;
+ } else {
+ if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+ }
+ break;
+ case TCSBRKP:
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+ rc = -EIO;
+ } else {
+ int l;
+ l = arg ? arg * 100 : 250;
+ if (l > 255)
+ l = 255;
+ if (RIOShortCommand(p, PortP, SBREAK, 2, arg ? arg * 100 : 250) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+ rc = -EIO;
+ }
+ }
+ break;
+ case TIOCSSERIAL:
+ rc = -EFAULT;
+ if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct)))
+ rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ func_exit();
+ return rc;
}
@@ -771,37 +704,37 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp,
* flow control scheme is in use for that port. -- Simon Allen
*/
-static void rio_throttle (struct tty_struct * tty)
+static void rio_throttle(struct tty_struct *tty)
{
- struct Port *port = (struct Port *)tty->driver_data;
-
- func_enter();
- /* If the port is using any type of input flow
- * control then throttle the port.
- */
-
- if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) {
- port->State |= RIO_THROTTLE_RX;
- }
-
- func_exit();
+ struct Port *port = (struct Port *) tty->driver_data;
+
+ func_enter();
+ /* If the port is using any type of input flow
+ * control then throttle the port.
+ */
+
+ if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
+ port->State |= RIO_THROTTLE_RX;
+ }
+
+ func_exit();
}
-static void rio_unthrottle (struct tty_struct * tty)
+static void rio_unthrottle(struct tty_struct *tty)
{
- struct Port *port = (struct Port *)tty->driver_data;
+ struct Port *port = (struct Port *) tty->driver_data;
- func_enter();
- /* Always unthrottle even if flow control is not enabled on
- * this port in case we disabled flow control while the port
- * was throttled
- */
+ func_enter();
+ /* Always unthrottle even if flow control is not enabled on
+ * this port in case we disabled flow control while the port
+ * was throttled
+ */
- port->State &= ~RIO_THROTTLE_RX;
+ port->State &= ~RIO_THROTTLE_RX;
- func_exit();
- return;
+ func_exit();
+ return;
}
@@ -813,35 +746,34 @@ static void rio_unthrottle (struct tty_struct * tty)
* ********************************************************************** */
-static struct vpd_prom *get_VPD_PROM (struct Host *hp)
+static struct vpd_prom *get_VPD_PROM(struct Host *hp)
{
- static struct vpd_prom vpdp;
- char *p;
- int i;
+ static struct vpd_prom vpdp;
+ char *p;
+ int i;
+
+ func_enter();
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
- func_enter();
- rio_dprintk (RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
- hp->Caddr + RIO_VPD_ROM);
+ p = (char *) &vpdp;
+ for (i = 0; i < sizeof(struct vpd_prom); i++)
+ *p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
+ /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
- p = (char *) &vpdp;
- for (i=0;i< sizeof (struct vpd_prom);i++)
- *p++ = readb (hp->Caddr+RIO_VPD_ROM + i*2);
- /* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
+ /* Terminate the identifier string.
+ *** requires one extra byte in struct vpd_prom *** */
+ *p++ = 0;
- /* Terminate the identifier string.
- *** requires one extra byte in struct vpd_prom *** */
- *p++=0;
+ if (rio_debug & RIO_DEBUG_PROBE)
+ my_hd((char *) &vpdp, 0x20);
- if (rio_debug & RIO_DEBUG_PROBE)
- my_hd ((char *)&vpdp, 0x20);
-
- func_exit();
+ func_exit();
- return &vpdp;
+ return &vpdp;
}
static struct tty_operations rio_ops = {
- .open = riotopen,
+ .open = riotopen,
.close = gs_close,
.write = gs_write,
.put_char = gs_put_char,
@@ -893,7 +825,7 @@ static int rio_init_drivers(void)
rio_driver2->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(rio_driver2, &rio_ops);
- rio_dprintk (RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+ rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
if ((error = tty_register_driver(rio_driver)))
goto out2;
@@ -901,116 +833,111 @@ static int rio_init_drivers(void)
goto out3;
func_exit();
return 0;
-out3:
+ out3:
tty_unregister_driver(rio_driver);
-out2:
+ out2:
put_tty_driver(rio_driver2);
-out1:
+ out1:
put_tty_driver(rio_driver);
-out:
- printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n",
- error);
+ out:
+ printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
return 1;
}
-static void * ckmalloc (int size)
+static void *ckmalloc(int size)
{
- void *p;
+ void *p;
- p = kmalloc(size, GFP_KERNEL);
- if (p)
- memset(p, 0, size);
- return p;
+ p = kmalloc(size, GFP_KERNEL);
+ if (p)
+ memset(p, 0, size);
+ return p;
}
-static int rio_init_datastructures (void)
+static int rio_init_datastructures(void)
{
- int i;
- struct Port *port;
- func_enter();
-
- /* Many drivers statically allocate the maximum number of ports
- There is no reason not to allocate them dynamically. Is there? -- REW */
- /* However, the RIO driver allows users to configure their first
- RTA as the ports numbered 504-511. We therefore need to allocate
- the whole range. :-( -- REW */
-
+ int i;
+ struct Port *port;
+ func_enter();
+
+ /* Many drivers statically allocate the maximum number of ports
+ There is no reason not to allocate them dynamically. Is there? -- REW */
+ /* However, the RIO driver allows users to configure their first
+ RTA as the ports numbered 504-511. We therefore need to allocate
+ the whole range. :-( -- REW */
+
#define RI_SZ sizeof(struct rio_info)
#define HOST_SZ sizeof(struct Host)
#define PORT_SZ sizeof(struct Port *)
#define TMIO_SZ sizeof(struct termios *)
- rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n",
- RI_SZ,
- RIO_HOSTS * HOST_SZ,
- RIO_PORTS * PORT_SZ,
- RIO_PORTS * TMIO_SZ,
- RIO_PORTS * TMIO_SZ);
-
- if (!(p = ckmalloc ( RI_SZ))) goto free0;
- if (!(p->RIOHosts = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1;
- if (!(p->RIOPortp = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2;
- p->RIOConf = RIOConf;
- rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n",
- p, p->RIOHosts, p->RIOPortp);
+ rio_dprintk(RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
+
+ if (!(p = ckmalloc(RI_SZ)))
+ goto free0;
+ if (!(p->RIOHosts = ckmalloc(RIO_HOSTS * HOST_SZ)))
+ goto free1;
+ if (!(p->RIOPortp = ckmalloc(RIO_PORTS * PORT_SZ)))
+ goto free2;
+ p->RIOConf = RIOConf;
+ rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
#if 1
- for (i = 0; i < RIO_PORTS; i++) {
- port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port));
- if (!port) {
- goto free6;
- }
- rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
- port->PortNum = i;
- port->gs.magic = RIO_MAGIC;
- port->gs.close_delay = HZ/2;
- port->gs.closing_wait = 30 * HZ;
- port->gs.rd = &rio_real_driver;
- spin_lock_init(&port->portSem);
- /*
- * Initializing wait queue
- */
- init_waitqueue_head(&port->gs.open_wait);
- init_waitqueue_head(&port->gs.close_wait);
- }
+ for (i = 0; i < RIO_PORTS; i++) {
+ port = p->RIOPortp[i] = ckmalloc(sizeof(struct Port));
+ if (!port) {
+ goto free6;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+ port->PortNum = i;
+ port->gs.magic = RIO_MAGIC;
+ port->gs.close_delay = HZ / 2;
+ port->gs.closing_wait = 30 * HZ;
+ port->gs.rd = &rio_real_driver;
+ spin_lock_init(&port->portSem);
+ /*
+ * Initializing wait queue
+ */
+ init_waitqueue_head(&port->gs.open_wait);
+ init_waitqueue_head(&port->gs.close_wait);
+ }
#else
- /* We could postpone initializing them to when they are configured. */
+ /* We could postpone initializing them to when they are configured. */
#endif
-
- if (rio_debug & RIO_DEBUG_INIT) {
- my_hd (&rio_real_driver, sizeof (rio_real_driver));
- }
-
- func_exit();
- return 0;
+ if (rio_debug & RIO_DEBUG_INIT) {
+ my_hd(&rio_real_driver, sizeof(rio_real_driver));
+ }
- free6:for (i--;i>=0;i--)
- kfree (p->RIOPortp[i]);
+
+ func_exit();
+ return 0;
+
+ free6:for (i--; i >= 0; i--)
+ kfree(p->RIOPortp[i]);
/*free5:
free4:
- free3:*/kfree (p->RIOPortp);
- free2:kfree (p->RIOHosts);
- free1:
- rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n",
- p, p->RIOHosts, p->RIOPortp);
- kfree(p);
- free0:
- return -ENOMEM;
+ free3:*/ kfree(p->RIOPortp);
+ free2:kfree(p->RIOHosts);
+ free1:
+ rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
+ kfree(p);
+ free0:
+ return -ENOMEM;
}
-static void __exit rio_release_drivers(void)
+static void __exit rio_release_drivers(void)
{
- func_enter();
- tty_unregister_driver(rio_driver2);
- tty_unregister_driver(rio_driver);
- put_tty_driver(rio_driver2);
- put_tty_driver(rio_driver);
- func_exit();
+ func_enter();
+ tty_unregister_driver(rio_driver2);
+ tty_unregister_driver(rio_driver);
+ put_tty_driver(rio_driver2);
+ put_tty_driver(rio_driver);
+ func_exit();
}
@@ -1021,7 +948,7 @@ static void __exit rio_release_drivers(void)
There is another bit besides Bit 17. Turning that bit off
(on boards shipped with the fix in the eeprom) results in a
hang on the next access to the card.
- */
+ */
/********************************************************
* Setting bit 17 in the CNTRL register of the PLX 9050 *
@@ -1034,319 +961,293 @@ static void __exit rio_release_drivers(void)
EEprom. As the bit is read/write for the CPU, we can fix it here,
if we detect that it isn't set correctly. -- REW */
-static void fix_rio_pci (struct pci_dev *pdev)
+static void fix_rio_pci(struct pci_dev *pdev)
{
- unsigned int hwbase;
- unsigned long rebase;
- unsigned int t;
+ unsigned int hwbase;
+ unsigned long rebase;
+ unsigned int t;
#define CNTRL_REG_OFFSET 0x50
#define CNTRL_REG_GOODVALUE 0x18260000
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
- hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
- rebase = (ulong) ioremap(hwbase, 0x80);
- t = readl (rebase + CNTRL_REG_OFFSET);
- if (t != CNTRL_REG_GOODVALUE) {
- printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n",
- t, CNTRL_REG_GOODVALUE);
- writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
- }
- iounmap((char*) rebase);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+ hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+ rebase = (ulong) ioremap(hwbase, 0x80);
+ t = readl(rebase + CNTRL_REG_OFFSET);
+ if (t != CNTRL_REG_GOODVALUE) {
+ printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
+ writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+ }
+ iounmap((char *) rebase);
}
#endif
-static int __init rio_init(void)
+static int __init rio_init(void)
{
- int found = 0;
- int i;
- struct Host *hp;
- int retval;
- struct vpd_prom *vpdp;
- int okboard;
+ int found = 0;
+ int i;
+ struct Host *hp;
+ int retval;
+ struct vpd_prom *vpdp;
+ int okboard;
#ifdef CONFIG_PCI
- struct pci_dev *pdev = NULL;
- unsigned int tint;
- unsigned short tshort;
+ struct pci_dev *pdev = NULL;
+ unsigned int tint;
+ unsigned short tshort;
#endif
- func_enter();
- rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n",
- rio_debug);
-
- if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) {
- printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. "
- "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
- rio_debug=-1;
- }
-
- if (misc_register(&rio_fw_device) < 0) {
- printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
- return -EIO;
- }
-
- retval = rio_init_datastructures ();
- if (retval < 0) {
- misc_deregister(&rio_fw_device);
- return retval;
- }
-
+ func_enter();
+ rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
+
+ if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
+ printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
+ rio_debug = -1;
+ }
+
+ if (misc_register(&rio_fw_device) < 0) {
+ printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+ return -EIO;
+ }
+
+ retval = rio_init_datastructures();
+ if (retval < 0) {
+ misc_deregister(&rio_fw_device);
+ return retval;
+ }
#ifdef CONFIG_PCI
- /* First look for the JET devices: */
- while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- pdev))) {
- if (pci_enable_device(pdev)) continue;
-
- /* Specialix has a whole bunch of cards with
- 0x2000 as the device ID. They say its because
- the standard requires it. Stupid standard. */
- /* It seems that reading a word doesn't work reliably on 2.0.
- Also, reading a non-aligned dword doesn't work. So we read the
- whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
- ourselves */
- /* I don't know why the define doesn't work, constant 0x2c does --REW */
- pci_read_config_dword (pdev, 0x2c, &tint);
- tshort = (tint >> 16) & 0xffff;
- rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
- if (tshort != 0x0100) {
- rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n",
- tshort);
- continue;
- }
- rio_dprintk (RIO_DEBUG_PROBE, "cp1\n");
-
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
-
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
- hp->Ivec = pdev->irq;
- if (((1 << hp->Ivec) & rio_irqmask) == 0)
- hp->Ivec = 0;
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_PCI;
- hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_BOOT_FROM_RAM;
- spin_lock_init(&hp->HostLock);
- rio_reset_interrupt (hp);
- rio_start_card_running (hp);
-
- rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
- (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr);
- if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr,
- RIO_PCI, 0 ) == RIO_SUCCESS) {
- rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- fix_rio_pci (pdev);
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- found++;
- } else {
- iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
- }
- }
-
- /* Then look for the older PCI card.... : */
-
- /* These older PCI cards have problems (only byte-mode access is
- supported), which makes them a bit awkward to support.
- They also have problems sharing interrupts. Be careful.
- (The driver now refuses to share interrupts for these
- cards. This should be sufficient).
- */
-
- /* Then look for the older RIO/PCI devices: */
- while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
- PCI_DEVICE_ID_SPECIALIX_RIO,
- pdev))) {
- if (pci_enable_device(pdev)) continue;
+ /* First look for the JET devices: */
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
+ if (pci_enable_device(pdev))
+ continue;
+
+ /* Specialix has a whole bunch of cards with
+ 0x2000 as the device ID. They say its because
+ the standard requires it. Stupid standard. */
+ /* It seems that reading a word doesn't work reliably on 2.0.
+ Also, reading a non-aligned dword doesn't work. So we read the
+ whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
+ ourselves */
+ /* I don't know why the define doesn't work, constant 0x2c does --REW */
+ pci_read_config_dword(pdev, 0x2c, &tint);
+ tshort = (tint >> 16) & 0xffff;
+ rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
+ if (tshort != 0x0100) {
+ rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
+ continue;
+ }
+ rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
+
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint);
+
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
+ hp->Ivec = pdev->irq;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+ spin_lock_init(&hp->HostLock);
+ rio_reset_interrupt(hp);
+ rio_start_card_running(hp);
+
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+ if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) {
+ rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+ WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+ p->RIOHosts[p->RIONumHosts].UniqueNum =
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+ fix_rio_pci(pdev);
+ p->RIOLastPCISearch = RIO_SUCCESS;
+ p->RIONumHosts++;
+ found++;
+ } else {
+ iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+ }
+ }
+
+ /* Then look for the older PCI card.... : */
+
+ /* These older PCI cards have problems (only byte-mode access is
+ supported), which makes them a bit awkward to support.
+ They also have problems sharing interrupts. Be careful.
+ (The driver now refuses to share interrupts for these
+ cards. This should be sufficient).
+ */
+
+ /* Then look for the older RIO/PCI devices: */
+ while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
+ if (pci_enable_device(pdev))
+ continue;
#ifdef CONFIG_RIO_OLDPCI
- pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
-
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
- hp->Ivec = pdev->irq;
- if (((1 << hp->Ivec) & rio_irqmask) == 0)
- hp->Ivec = 0;
- hp->Ivec |= 0x8000; /* Mark as non-sharable */
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_PCI;
- hp->Copy = rio_pcicopy;
- hp->Mode = RIO_PCI_BOOT_FROM_RAM;
- spin_lock_init(&hp->HostLock);
-
- rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
- rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
-
- rio_reset_interrupt (hp);
- rio_start_card_running (hp);
- rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
- (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr);
- if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
- p->RIOHosts[p->RIONumHosts].Caddr,
- RIO_PCI, 0 ) == RIO_SUCCESS) {
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- found++;
- } else {
- iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr));
- }
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint);
+
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK;
+ hp->Ivec = pdev->irq;
+ if (((1 << hp->Ivec) & rio_irqmask) == 0)
+ hp->Ivec = 0;
+ hp->Ivec |= 0x8000; /* Mark as non-sharable */
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_PCI;
+ hp->Copy = rio_pcicopy;
+ hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+ spin_lock_init(&hp->HostLock);
+
+ rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+ rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+ rio_reset_interrupt(hp);
+ rio_start_card_running(hp);
+ rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+ if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == RIO_SUCCESS) {
+ WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+ p->RIOHosts[p->RIONumHosts].UniqueNum =
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+ ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+ p->RIOLastPCISearch = RIO_SUCCESS;
+ p->RIONumHosts++;
+ found++;
+ } else {
+ iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+ }
#else
- printk (KERN_ERR "Found an older RIO PCI card, but the driver is not "
- "compiled to support it.\n");
+ printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
#endif
- }
-#endif /* PCI */
-
- /* Now probe for ISA cards... */
- for (i=0;i<NR_RIO_ADDRS;i++) {
- hp = &p->RIOHosts[p->RIONumHosts];
- hp->PaddrP = rio_probe_addrs[i];
- /* There was something about the IRQs of these cards. 'Forget what.--REW */
- hp->Ivec = 0;
- hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
- hp->CardP = (struct DpRam *) hp->Caddr;
- hp->Type = RIO_AT;
- hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
- * -- YES! this is now a normal copy. Only the
- * old PCI card uses the special PCI copy.
- * Moreover, the ISA card will work with the
- * special PCI copy anyway. -- REW */
- hp->Mode = 0;
- spin_lock_init(&hp->HostLock);
-
- vpdp = get_VPD_PROM (hp);
- rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
- okboard = 0;
- if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
- (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
- (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
- /* Board is present... */
- if (RIOBoardTest (hp->PaddrP,
- hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
- /* ... and feeling fine!!!! */
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
- if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
- rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n",
- p->RIONumHosts,
- p->RIOHosts[p->RIONumHosts-1].UniqueNum);
- okboard++;
- found++;
- }
- }
-
- if (!okboard)
- iounmap ((char*) (hp->Caddr));
- }
- }
-
-
- for (i=0;i<p->RIONumHosts;i++) {
- hp = &p->RIOHosts[i];
- if (hp->Ivec) {
- int mode = SA_SHIRQ;
- if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
- rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
- retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
- rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
- if (retval) {
- printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
- hp->Ivec = 0;
- }
- rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
- if (hp->Ivec != 0){
- rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
- hp->Mode |= RIO_PCI_INT_ENABLE;
- } else
- hp->Mode &= !RIO_PCI_INT_ENABLE;
- rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
- rio_start_card_running (hp);
- }
- /* Init the timer "always" to make sure that it can safely be
- deleted when we unload... */
-
- init_timer (&hp->timer);
- if (!hp->Ivec) {
- rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n",
- rio_poll);
- hp->timer.data = i;
- hp->timer.function = rio_pollfunc;
- hp->timer.expires = jiffies + rio_poll;
- add_timer (&hp->timer);
- }
- }
-
- if (found) {
- rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
- rio_init_drivers ();
- } else {
- /* deregister the misc device we created earlier */
- misc_deregister(&rio_fw_device);
- }
-
- func_exit();
- return found?0:-EIO;
+ }
+#endif /* PCI */
+
+ /* Now probe for ISA cards... */
+ for (i = 0; i < NR_RIO_ADDRS; i++) {
+ hp = &p->RIOHosts[p->RIONumHosts];
+ hp->PaddrP = rio_probe_addrs[i];
+ /* There was something about the IRQs of these cards. 'Forget what.--REW */
+ hp->Ivec = 0;
+ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+ hp->CardP = (struct DpRam *) hp->Caddr;
+ hp->Type = RIO_AT;
+ hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+ * -- YES! this is now a normal copy. Only the
+ * old PCI card uses the special PCI copy.
+ * Moreover, the ISA card will work with the
+ * special PCI copy anyway. -- REW */
+ hp->Mode = 0;
+ spin_lock_init(&hp->HostLock);
+
+ vpdp = get_VPD_PROM(hp);
+ rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
+ okboard = 0;
+ if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
+ /* Board is present... */
+ if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) {
+ /* ... and feeling fine!!!! */
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+ if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
+ rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
+ okboard++;
+ found++;
+ }
+ }
+
+ if (!okboard)
+ iounmap((char *) (hp->Caddr));
+ }
+ }
+
+
+ for (i = 0; i < p->RIONumHosts; i++) {
+ hp = &p->RIOHosts[i];
+ if (hp->Ivec) {
+ int mode = SA_SHIRQ;
+ if (hp->Ivec & 0x8000) {
+ mode = 0;
+ hp->Ivec &= 0x7fff;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
+ retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
+ rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+ if (retval) {
+ printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+ hp->Ivec = 0;
+ }
+ rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+ if (hp->Ivec != 0) {
+ rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
+ hp->Mode |= RIO_PCI_INT_ENABLE;
+ } else
+ hp->Mode &= !RIO_PCI_INT_ENABLE;
+ rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+ rio_start_card_running(hp);
+ }
+ /* Init the timer "always" to make sure that it can safely be
+ deleted when we unload... */
+
+ init_timer(&hp->timer);
+ if (!hp->Ivec) {
+ rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
+ hp->timer.data = i;
+ hp->timer.function = rio_pollfunc;
+ hp->timer.expires = jiffies + rio_poll;
+ add_timer(&hp->timer);
+ }
+ }
+
+ if (found) {
+ rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
+ rio_init_drivers();
+ } else {
+ /* deregister the misc device we created earlier */
+ misc_deregister(&rio_fw_device);
+ }
+
+ func_exit();
+ return found ? 0 : -EIO;
}
-static void __exit rio_exit (void)
+static void __exit rio_exit(void)
{
- int i;
- struct Host *hp;
-
- func_enter();
+ int i;
+ struct Host *hp;
+
+ func_enter();
- for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
- RIOHostReset (hp->Type, hp->CardP, hp->Slot);
- if (hp->Ivec) {
- free_irq (hp->Ivec, hp);
- rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
- }
- /* It is safe/allowed to del_timer a non-active timer */
- del_timer (&hp->timer);
- }
+ for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
+ RIOHostReset(hp->Type, hp->CardP, hp->Slot);
+ if (hp->Ivec) {
+ free_irq(hp->Ivec, hp);
+ rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
+ }
+ /* It is safe/allowed to del_timer a non-active timer */
+ del_timer(&hp->timer);
+ }
- if (misc_deregister(&rio_fw_device) < 0) {
- printk (KERN_INFO "rio: couldn't deregister control-device\n");
- }
+ if (misc_deregister(&rio_fw_device) < 0) {
+ printk(KERN_INFO "rio: couldn't deregister control-device\n");
+ }
- rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
+ rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
- rio_release_drivers ();
+ rio_release_drivers();
- /* Release dynamically allocated memory */
- kfree (p->RIOPortp);
- kfree (p->RIOHosts);
- kfree (p);
+ /* Release dynamically allocated memory */
+ kfree(p->RIOPortp);
+ kfree(p->RIOHosts);
+ kfree(p);
- func_exit();
+ func_exit();
}
module_init(rio_init);
@@ -1372,4 +1273,3 @@ module_exit(rio_exit);
* tab-width: 8
* End:
*/
-
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
index 1fba19d5b66a..4ce77fb1fae5 100644
--- a/drivers/char/rio/rio_linux.h
+++ b/drivers/char/rio/rio_linux.h
@@ -37,15 +37,15 @@
struct vpd_prom {
- unsigned short id;
- char hwrev;
- char hwass;
- int uniqid;
- char myear;
- char mweek;
- char hw_feature[5];
- char oem_id;
- char identifier[16];
+ unsigned short id;
+ char hwrev;
+ char hwass;
+ int uniqid;
+ char myear;
+ char mweek;
+ char hw_feature[5];
+ char oem_id;
+ char identifier[16];
};
@@ -75,13 +75,13 @@ struct vpd_prom {
(L_ISIG(tty)))
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
#define RIO_BOARD_INTR_LOCK 1
-#ifndef RIOCTL_MISC_MINOR
+#ifndef RIOCTL_MISC_MINOR
/* Allow others to gather this into "major.h" or something like that */
#define RIOCTL_MISC_MINOR 169
#endif
@@ -121,39 +121,39 @@ struct vpd_prom {
spin_unlock_irqrestore(sem, flags)
#define rio_spin_lock(sem) \
- spin_lock(sem)
+ spin_lock(sem)
#define rio_spin_unlock(sem) \
- spin_unlock(sem)
+ spin_unlock(sem)
#endif
#ifdef CONFIG_RIO_OLDPCI
-static inline void *rio_memcpy_toio (void *dummy, void *dest, void *source, int n)
+static inline void *rio_memcpy_toio(void *dummy, void *dest, void *source, int n)
{
- char *dst = dest;
- char *src = source;
+ char *dst = dest;
+ char *src = source;
- while (n--) {
- writeb (*src++, dst++);
- (void) readb (dummy);
- }
+ while (n--) {
+ writeb(*src++, dst++);
+ (void) readb(dummy);
+ }
- return dest;
+ return dest;
}
-static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
+static inline void *rio_memcpy_fromio(void *dest, void *source, int n)
{
- char *dst = dest;
- char *src = source;
+ char *dst = dest;
+ char *src = source;
- while (n--)
- *dst++ = readb (src++);
+ while (n--)
+ *dst++ = readb(src++);
- return dest;
+ return dest;
}
#else
@@ -179,9 +179,8 @@ static inline void *rio_memcpy_fromio (void *dest, void *source, int n)
#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit %s\n", __FUNCTION__)
#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
#else
-#define rio_dprintk(f, str...) /* nothing */
+#define rio_dprintk(f, str...) /* nothing */
#define func_enter()
#define func_exit()
#define func_enter2()
#endif
-
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h
index cc6ac6a98f65..822c071a693b 100644
--- a/drivers/char/rio/rioboard.h
+++ b/drivers/char/rio/rioboard.h
@@ -35,7 +35,7 @@
*/
-#ifndef _rioboard_h /* If RIOBOARD.H not already defined */
+#ifndef _rioboard_h /* If RIOBOARD.H not already defined */
#define _rioboard_h 1
/*****************************************************************************
@@ -46,7 +46,7 @@
/* Hardware Registers... */
-#define RIO_REG_BASE 0x7C00 /* Base of control registers */
+#define RIO_REG_BASE 0x7C00 /* Base of control registers */
#define RIO_CONFIG RIO_REG_BASE + 0x0000 /* WRITE: Configuration Register */
#define RIO_INTSET RIO_REG_BASE + 0x0080 /* WRITE: Interrupt Set */
@@ -58,30 +58,30 @@
#define RIO_RESETSTAT RIO_REG_BASE + 0x0100 /* READ: Reset Status (Jet boards only) */
/* RIO_VPD_ROM definitions... */
-#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */
-#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */
-#define VPD_HW_REV 0x02 /* READ: Hardware Revision */
-#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */
-#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */
-#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */
-#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */
-#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */
-#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */
-#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */
-#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */
-#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */
-#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */
-#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */
-#define VPD_OEMID 0x0F /* READ: OEM Identifier */
-#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */
+#define VPD_SLX_ID1 0x00 /* READ: Specialix Identifier #1 */
+#define VPD_SLX_ID2 0x01 /* READ: Specialix Identifier #2 */
+#define VPD_HW_REV 0x02 /* READ: Hardware Revision */
+#define VPD_HW_ASSEM 0x03 /* READ: Hardware Assembly Level */
+#define VPD_UNIQUEID4 0x04 /* READ: Unique Identifier #4 */
+#define VPD_UNIQUEID3 0x05 /* READ: Unique Identifier #3 */
+#define VPD_UNIQUEID2 0x06 /* READ: Unique Identifier #2 */
+#define VPD_UNIQUEID1 0x07 /* READ: Unique Identifier #1 */
+#define VPD_MANU_YEAR 0x08 /* READ: Year Of Manufacture (0 = 1970) */
+#define VPD_MANU_WEEK 0x09 /* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define VPD_HWFEATURE1 0x0A /* READ: Hardware Feature Byte 1 */
+#define VPD_HWFEATURE2 0x0B /* READ: Hardware Feature Byte 2 */
+#define VPD_HWFEATURE3 0x0C /* READ: Hardware Feature Byte 3 */
+#define VPD_HWFEATURE4 0x0D /* READ: Hardware Feature Byte 4 */
+#define VPD_HWFEATURE5 0x0E /* READ: Hardware Feature Byte 5 */
+#define VPD_OEMID 0x0F /* READ: OEM Identifier */
+#define VPD_IDENT 0x10 /* READ: Identifier string (16 bytes) */
#define VPD_IDENT_LEN 0x10
/* VPD ROM Definitions... */
#define SLX_ID1 0x4D
#define SLX_ID2 0x98
-#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */
+#define PRODUCT_ID(a) ((a>>4)&0xF) /* Use to obtain Product ID from VPD_UNIQUEID1 */
#define ID_SX_ISA 0x2
#define ID_RIO_EISA 0x3
@@ -101,7 +101,7 @@
/* Firmware load position... */
-#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */
+#define FIRMWARELOADADDR 0x7C00 /* Firmware is loaded _before_ this address */
/*****************************************************************************
***************************** *****************************
@@ -112,14 +112,14 @@
/* Control Register Definitions... */
#define RIO_ISA_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */
-#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */
-#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */
-#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */
-#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
+#define RIO_ISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_ISA_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA_CFG_IRQMASK 0x30 /* Interrupt mask */
+#define RIO_ISA_CFG_IRQ12 0x10 /* Interrupt Level 12 */
+#define RIO_ISA_CFG_IRQ11 0x20 /* Interrupt Level 11 */
+#define RIO_ISA_CFG_IRQ9 0x30 /* Interrupt Level 9 */
+#define RIO_ISA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_ISA_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
/*****************************************************************************
***************************** *****************************
@@ -130,17 +130,17 @@
/* Control Register Definitions... */
#define RIO_ISA2_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */
-#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */
-#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */
-#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */
-#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */
-#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */
-#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
+#define RIO_ISA2_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_ISA2_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_ISA2_CFG_16BIT 0x08 /* 16bit mode, else 8bit */
+#define RIO_ISA2_CFG_IRQMASK 0x30 /* Interrupt mask */
+#define RIO_ISA2_CFG_IRQ15 0x00 /* Interrupt Level 15 */
+#define RIO_ISA2_CFG_IRQ12 0x10 /* Interrupt Level 12 */
+#define RIO_ISA2_CFG_IRQ11 0x20 /* Interrupt Level 11 */
+#define RIO_ISA2_CFG_IRQ9 0x30 /* Interrupt Level 9 */
+#define RIO_ISA2_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_ISA2_CFG_WAITSTATE0 0x80 /* 0 waitstates, else 1 */
/*****************************************************************************
***************************** ******************************
@@ -151,14 +151,14 @@
/* Control Register Definitions... */
#define RIO_ISA3_IDENT "JET HOST BY KEV#"
-#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */
-#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
-#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
-#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
-#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
-#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */
+#define RIO_ISA3_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_ISA3_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_ISA32_CFG_IRQMASK 0xF30 /* Interrupt mask */
+#define RIO_ISA3_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
+#define RIO_ISA3_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
+#define RIO_ISA3_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
+#define RIO_ISA3_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
+#define RIO_ISA3_CFG_IRQ9 0x90 /* Interrupt Level 9 */
/*****************************************************************************
********************************* ********************************
@@ -169,9 +169,9 @@
/* Control Register Definitions... */
#define RIO_MCA_IDENT "JBJGPGGHINSMJPJR"
-#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_MCA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_MCA_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_MCA_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
/*****************************************************************************
******************************** ********************************
@@ -185,35 +185,35 @@
#define EISA_PRODUCT_NUMBER 0xC82
#define EISA_REVISION_NUMBER 0xC83
#define EISA_CARD_ENABLE 0xC84
-#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */
-#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */
-#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */
-#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */
-#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */
-#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define EISA_VPD_UNIQUEID4 0xC88 /* READ: Unique Identifier #4 */
+#define EISA_VPD_UNIQUEID3 0xC8A /* READ: Unique Identifier #3 */
+#define EISA_VPD_UNIQUEID2 0xC90 /* READ: Unique Identifier #2 */
+#define EISA_VPD_UNIQUEID1 0xC92 /* READ: Unique Identifier #1 */
+#define EISA_VPD_MANU_YEAR 0xC98 /* READ: Year Of Manufacture (0 = 1970) */
+#define EISA_VPD_MANU_WEEK 0xC9A /* READ: Week Of Manufacture (0 = week 1 Jan) */
#define EISA_MEM_ADDR_23_16 0xC00
#define EISA_MEM_ADDR_31_24 0xC01
-#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */
-#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */
-#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */
+#define EISA_RIO_CONFIG 0xC02 /* WRITE: Configuration Register */
+#define EISA_RIO_INTSET 0xC03 /* WRITE: Interrupt Set */
+#define EISA_RIO_INTRESET 0xC03 /* READ: Interrupt Reset */
/* Control Register Definitions... */
-#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */
-#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */
-#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */
-#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */
-#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
-#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */
-#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
-#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
-#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
-#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */
-#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */
-#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */
-#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */
-#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */
-#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */
+#define RIO_EISA_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_EISA_CFG_LINK20 0x02 /* 20Mbps link, else 10Mbps */
+#define RIO_EISA_CFG_BUSENABLE 0x04 /* Enable processor bus */
+#define RIO_EISA_CFG_PROCRUN 0x08 /* Processor running, else reset */
+#define RIO_EISA_CFG_IRQMASK 0xF0 /* Interrupt mask */
+#define RIO_EISA_CFG_IRQ15 0xF0 /* Interrupt Level 15 */
+#define RIO_EISA_CFG_IRQ14 0xE0 /* Interrupt Level 14 */
+#define RIO_EISA_CFG_IRQ12 0xC0 /* Interrupt Level 12 */
+#define RIO_EISA_CFG_IRQ11 0xB0 /* Interrupt Level 11 */
+#define RIO_EISA_CFG_IRQ10 0xA0 /* Interrupt Level 10 */
+#define RIO_EISA_CFG_IRQ9 0x90 /* Interrupt Level 9 */
+#define RIO_EISA_CFG_IRQ7 0x70 /* Interrupt Level 7 */
+#define RIO_EISA_CFG_IRQ6 0x60 /* Interrupt Level 6 */
+#define RIO_EISA_CFG_IRQ5 0x50 /* Interrupt Level 5 */
+#define RIO_EISA_CFG_IRQ4 0x40 /* Interrupt Level 4 */
+#define RIO_EISA_CFG_IRQ3 0x30 /* Interrupt Level 3 */
/*****************************************************************************
******************************** ********************************
@@ -224,20 +224,20 @@
/* Control Register Definitions... */
#define RIO_SBUS_IDENT "JBPGK#\0\0\0\0\0\0\0\0\0\0"
-#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */
-#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */
-#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */
-#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */
-#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */
-#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */
-#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */
-#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */
-#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */
-#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
+#define RIO_SBUS_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_SBUS_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_SBUS_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_SBUS_CFG_IRQMASK 0x38 /* Interrupt mask */
+#define RIO_SBUS_CFG_IRQNONE 0x00 /* No Interrupt */
+#define RIO_SBUS_CFG_IRQ7 0x38 /* Interrupt Level 7 */
+#define RIO_SBUS_CFG_IRQ6 0x30 /* Interrupt Level 6 */
+#define RIO_SBUS_CFG_IRQ5 0x28 /* Interrupt Level 5 */
+#define RIO_SBUS_CFG_IRQ4 0x20 /* Interrupt Level 4 */
+#define RIO_SBUS_CFG_IRQ3 0x18 /* Interrupt Level 3 */
+#define RIO_SBUS_CFG_IRQ2 0x10 /* Interrupt Level 2 */
+#define RIO_SBUS_CFG_IRQ1 0x08 /* Interrupt Level 1 */
+#define RIO_SBUS_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_SBUS_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
/*****************************************************************************
********************************* ********************************
@@ -248,18 +248,18 @@
/* Control Register Definitions... */
#define RIO_PCI_IDENT "ECDDPGJGJHJRGSK#"
-#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
-#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
-#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
-#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
+#define RIO_PCI_CFG_BOOTRAM 0x01 /* Boot from RAM, else Link */
+#define RIO_PCI_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_PCI_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_PCI_CFG_LINK20 0x40 /* 20Mbps link, else 10Mbps */
+#define RIO_PCI_CFG_PROC25 0x80 /* 25Mhz processor clock, else 20Mhz */
/* PCI Definitions... */
-#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */
-#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */
-#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */
+#define SPX_VENDOR_ID 0x11CB /* Assigned by the PCI SIG */
+#define SPX_DEVICE_ID 0x8000 /* RIO bridge boards */
+#define SPX_PLXDEVICE_ID 0x2000 /* PLX bridge boards */
#define SPX_SUB_VENDOR_ID SPX_VENDOR_ID /* Same as vendor id */
-#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */
+#define RIO_SUB_SYS_ID 0x0800 /* RIO PCI board */
/*****************************************************************************
***************************** ******************************
@@ -270,11 +270,11 @@
/* Control Register Definitions... */
#define RIO_PCI2_IDENT "JET HOST BY KEV#"
-#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */
-#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
+#define RIO_PCI2_CFG_BUSENABLE 0x02 /* Enable processor bus */
+#define RIO_PCI2_CFG_INTENABLE 0x04 /* Interrupt enable, else disable */
/* PCI Definitions... */
-#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */
+#define RIO2_SUB_SYS_ID 0x0100 /* RIO (Jet) PCI board */
#endif /*_rioboard_h */
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index 34cbb13aad4b..92df43552f15 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -665,13 +665,6 @@ struct PKT *PacketP;
struct CmdBlk *CmdBlkP;
uint sequence;
-#ifdef CHECK
- CheckHost(Host);
- CheckRup(Rup);
- CheckHostP(HostP);
- CheckPacketP(PacketP);
-#endif
-
/*
** If we haven't been told what to boot, we can't boot it.
*/
@@ -956,11 +949,6 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
MyType = "RTA";
MyName = HostP->Mapping[Rup].Name;
}
-#ifdef CHECK
- CheckString(MyType);
- CheckString(MyName);
-#endif
-
MyLink = RBYTE(PktCmdP->LinkNum);
/*
@@ -1309,52 +1297,3 @@ struct Host *HostP;
}
}
-#if 0
-/*
- Function: This function is to disable the disk interrupt
- Returns : Nothing
-*/
-void
-disable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- __outb(S8259+1, __inb(S8259+1) | val);
- }
- else {
- val = 1 << (vector - 32);
- __outb(M8259+1, __inb(M8259+1) | val);
- }
- restore(ps);
-}
-
-/*
- Function: This function is to enable the disk interrupt
- Returns : Nothing
-*/
-void
-enable_interrupt(vector)
-int vector;
-{
- int ps;
- int val;
-
- disable(ps);
- if (vector > 40) {
- val = 1 << (vector - 40);
- val = ~val;
- __outb(S8259+1, __inb(S8259+1) & val);
- }
- else {
- val = 1 << (vector - 32);
- val = ~val;
- __outb(M8259+1, __inb(M8259+1) & val);
- }
- restore(ps);
-}
-#endif
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 533085ec6f1b..694bfb9d9378 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -83,102 +83,98 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2";
static struct IdentifyRta IdRta;
static struct KillNeighbour KillUnit;
-int
-RIOFoadRta(struct Host *HostP, struct Map *MapP)
+int RIOFoadRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IFOAD;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IFOAD;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
return -EIO;
}
return 0;
}
-int
-RIOZombieRta(struct Host *HostP, struct Map *MapP)
+int RIOZombieRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = ZOMBIE;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = ZOMBIE;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
return -EIO;
}
return 0;
}
-int
-RIOCommandRta(struct rio_info *p, uint RtaUnique,
- int (* func)(struct Host *HostP, struct Map *MapP))
+int RIOCommandRta(struct rio_info *p, uint RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
{
uint Host;
- rio_dprintk (RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int)func);
+ rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%x func 0x%x\n", RtaUnique, (int) func);
- if ( !RtaUnique )
- return(0);
+ if (!RtaUnique)
+ return (0);
- for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
uint Rta;
struct Host *HostP = &p->RIOHosts[Host];
- for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+ for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
struct Map *MapP = &HostP->Mapping[Rta];
- if ( MapP->RtaUniqueNum == RtaUnique ) {
+ if (MapP->RtaUniqueNum == RtaUnique) {
uint Link;
/*
- ** now, lets just check we have a route to it...
- ** IF the routing stuff is working, then one of the
- ** topology entries for this unit will have a legit
- ** route *somewhere*. We care not where - if its got
- ** any connections, we can get to it.
- */
- for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
- if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+ ** now, lets just check we have a route to it...
+ ** IF the routing stuff is working, then one of the
+ ** topology entries for this unit will have a legit
+ ** route *somewhere*. We care not where - if its got
+ ** any connections, we can get to it.
+ */
+ for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+ if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {
/*
- ** Its worth trying the operation...
- */
- return (*func)( HostP, MapP );
+ ** Its worth trying the operation...
+ */
+ return (*func) (HostP, MapP);
}
}
}
@@ -188,60 +184,59 @@ RIOCommandRta(struct rio_info *p, uint RtaUnique,
}
-int
-RIOIdentifyRta(struct rio_info *p, caddr_t arg)
+int RIOIdentifyRta(struct rio_info *p, caddr_t arg)
{
uint Host;
- if ( copyin( (int)arg, (caddr_t)&IdRta, sizeof(IdRta) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
+ if (copyin((int) arg, (caddr_t) & IdRta, sizeof(IdRta)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
p->RIOError.Error = COPYIN_FAILED;
return -EFAULT;
}
- for ( Host = 0 ; Host < p->RIONumHosts; Host++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
uint Rta;
struct Host *HostP = &p->RIOHosts[Host];
- for ( Rta = 0; Rta < RTAS_PER_HOST; Rta++ ) {
+ for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
struct Map *MapP = &HostP->Mapping[Rta];
- if ( MapP->RtaUniqueNum == IdRta.RtaUnique ) {
+ if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
uint Link;
/*
- ** now, lets just check we have a route to it...
- ** IF the routing stuff is working, then one of the
- ** topology entries for this unit will have a legit
- ** route *somewhere*. We care not where - if its got
- ** any connections, we can get to it.
- */
- for ( Link = 0; Link < LINKS_PER_UNIT; Link++ ) {
- if ( MapP->Topology[Link].Unit <= (uchar)MAX_RUP ) {
+ ** now, lets just check we have a route to it...
+ ** IF the routing stuff is working, then one of the
+ ** topology entries for this unit will have a legit
+ ** route *somewhere*. We care not where - if its got
+ ** any connections, we can get to it.
+ */
+ for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+ if (MapP->Topology[Link].Unit <= (uchar) MAX_RUP) {
/*
- ** Its worth trying the operation...
- */
+ ** Its worth trying the operation...
+ */
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA\n");
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
return -ENXIO;
}
-
+
CmdBlkP->Packet.dest_unit = MapP->ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IDENTIFY;
- CmdBlkP->Packet.data[1] = 0;
- CmdBlkP->Packet.data[2] = IdRta.ID;
-
- if ( RIOQueueCmdBlk( HostP, MapP->ID-1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IDENTIFY;
+ CmdBlkP->Packet.data[1] = 0;
+ CmdBlkP->Packet.data[2] = IdRta.ID;
+
+ if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
return -EIO;
}
return 0;
@@ -249,114 +244,110 @@ RIOIdentifyRta(struct rio_info *p, caddr_t arg)
}
}
}
- }
+ }
return -ENOENT;
}
-int
-RIOKillNeighbour(struct rio_info *p, caddr_t arg)
+int RIOKillNeighbour(struct rio_info *p, caddr_t arg)
{
uint Host;
uint ID;
struct Host *HostP;
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
+ rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
- if ( copyin( (int)arg, (caddr_t)&KillUnit, sizeof(KillUnit) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
+ if (copyin((int) arg, (caddr_t) & KillUnit, sizeof(KillUnit)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
p->RIOError.Error = COPYIN_FAILED;
return -EFAULT;
}
- if ( KillUnit.Link > 3 )
+ if (KillUnit.Link > 3)
return -ENXIO;
-
+
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = 0;
- CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_unit = 0;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = UFOAD;
- CmdBlkP->Packet.data[1] = KillUnit.Link;
- CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
-
- for ( Host = 0; Host < p->RIONumHosts; Host++ ) {
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = UFOAD;
+ CmdBlkP->Packet.data[1] = KillUnit.Link;
+ CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
+
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
ID = 0;
HostP = &p->RIOHosts[Host];
- if ( HostP->UniqueNum == KillUnit.UniqueNum ) {
- if ( RIOQueueCmdBlk( HostP, RTAS_PER_HOST+KillUnit.Link,
- CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+ if (HostP->UniqueNum == KillUnit.UniqueNum) {
+ if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
return -EIO;
}
return 0;
}
- for ( ID=0; ID < RTAS_PER_HOST; ID++ ) {
- if ( HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum ) {
- CmdBlkP->Packet.dest_unit = ID+1;
- if ( RIOQueueCmdBlk( HostP, ID, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+ for (ID = 0; ID < RTAS_PER_HOST; ID++) {
+ if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
+ CmdBlkP->Packet.dest_unit = ID + 1;
+ if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
return -EIO;
}
return 0;
}
}
}
- RIOFreeCmdBlk( CmdBlkP );
+ RIOFreeCmdBlk(CmdBlkP);
return -ENXIO;
}
-int
-RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
+int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
{
struct CmdBlk *CmdBlkP;
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
return -ENXIO;
}
CmdBlkP->Packet.dest_unit = ID;
CmdBlkP->Packet.dest_port = BOOT_RUP;
- CmdBlkP->Packet.src_unit = 0;
- CmdBlkP->Packet.src_port = BOOT_RUP;
- CmdBlkP->Packet.len = 0x84;
- CmdBlkP->Packet.data[0] = IWAIT;
- CmdBlkP->Packet.data[1] = Link;
- CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
- CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
-
- if ( RIOQueueCmdBlk( HostP, ID - 1, CmdBlkP) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
+ CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_port = BOOT_RUP;
+ CmdBlkP->Packet.len = 0x84;
+ CmdBlkP->Packet.data[0] = IWAIT;
+ CmdBlkP->Packet.data[1] = Link;
+ CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
+ CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
+
+ if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
return -EIO;
}
return 0;
}
-int
-RIOFoadWakeup(struct rio_info *p)
+int RIOFoadWakeup(struct rio_info *p)
{
int port;
register struct Port *PortP;
unsigned long flags;
- for ( port=0; port<RIO_PORTS; port++) {
+ for (port = 0; port < RIO_PORTS; port++) {
PortP = p->RIOPortp[port];
rio_spin_lock_irqsave(&PortP->portSem, flags);
@@ -377,16 +368,15 @@ RIOFoadWakeup(struct rio_info *p)
PortP->TxBufferOut = 0;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
- return(0);
+ return (0);
}
/*
** Incoming command on the COMMAND_RUP to be processed.
*/
-static int
-RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
+static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP)
{
- struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
+ struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
struct Port *PortP;
struct UnixRup *UnixRupP;
ushort SysPort;
@@ -395,128 +385,101 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
ushort subCommand;
unsigned long flags;
- func_enter ();
-
-#ifdef CHECK
- CheckHost( Host );
- CheckHostP( HostP );
- CheckPacketP( PacketP );
-#endif
+ func_enter();
/*
- ** 16 port RTA note:
- ** Command rup packets coming from the RTA will have pkt->data[1] (which
- ** translates to PktCmdP->PhbNum) set to the host port number for the
- ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
- ** we can use PhbNum to get the rup number for the appropriate 8 port
- ** block (for the first block, this should be equal to 'Rup').
- */
- rup = RBYTE(PktCmdP->PhbNum) / (ushort)PORTS_PER_RTA;
+ ** 16 port RTA note:
+ ** Command rup packets coming from the RTA will have pkt->data[1] (which
+ ** translates to PktCmdP->PhbNum) set to the host port number for the
+ ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
+ ** we can use PhbNum to get the rup number for the appropriate 8 port
+ ** block (for the first block, this should be equal to 'Rup').
+ */
+ rup = RBYTE(PktCmdP->PhbNum) / (ushort) PORTS_PER_RTA;
UnixRupP = &HostP->UnixRups[rup];
- SysPort = UnixRupP->BaseSysPort +
- (RBYTE(PktCmdP->PhbNum) % (ushort)PORTS_PER_RTA);
- rio_dprintk (RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
+ SysPort = UnixRupP->BaseSysPort + (RBYTE(PktCmdP->PhbNum) % (ushort) PORTS_PER_RTA);
+ rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-#ifdef CHECK
- CheckRup( rup );
- CheckUnixRupP( UnixRupP );
-#endif
- if ( UnixRupP->BaseSysPort == NO_PORT ) {
- rio_dprintk (RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
- rio_dprintk (RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n",
- HostP-p->RIOHosts, HostP->Name );
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup);
-
- if ( Rup >= (ushort)MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n",
- HostP->Mapping[Rup].Name);
+ if (UnixRupP->BaseSysPort == NO_PORT) {
+ rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %d, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup);
+
+ if (Rup >= (ushort) MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
} else
- rio_dprintk (RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n",
- ('A' + Rup - MAX_RUP), HostP->Name);
-
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n",
- PacketP->dest_unit, PacketP->dest_port );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n",
- PacketP->src_unit, PacketP->src_port );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len,PacketP->len );
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control);
- rio_dprintk (RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum );
- rio_dprintk (RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, "
- "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command );
+ rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
+
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source 0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length 0x%x (%d)\n", PacketP->len, PacketP->len);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control 0x%x (%d)\n", PacketP->control, PacketP->control);
+ rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check 0x%x (%d)\n", PacketP->csum, PacketP->csum);
+ rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command);
return TRUE;
}
-
-#ifdef CHECK
- CheckSysPort( SysPort );
-#endif
- PortP = p->RIOPortp[ SysPort ];
+ PortP = p->RIOPortp[SysPort];
rio_spin_lock_irqsave(&PortP->portSem, flags);
- switch( RBYTE(PktCmdP->Command) ) {
- case BREAK_RECEIVED:
- rio_dprintk (RIO_DEBUG_CMD, "Received a break!\n");
- /* If the current line disc. is not multi-threading and
- the current processor is not the default, reset rup_intr
- and return FALSE to ensure that the command packet is
- not freed. */
- /* Call tmgr HANGUP HERE */
- /* Fix this later when every thing works !!!! RAMRAJ */
- gs_got_break (&PortP->gs);
+ switch (RBYTE(PktCmdP->Command)) {
+ case BREAK_RECEIVED:
+ rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
+ /* If the current line disc. is not multi-threading and
+ the current processor is not the default, reset rup_intr
+ and return FALSE to ensure that the command packet is
+ not freed. */
+ /* Call tmgr HANGUP HERE */
+ /* Fix this later when every thing works !!!! RAMRAJ */
+ gs_got_break(&PortP->gs);
+ break;
+
+ case COMPLETE:
+ rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %d\n", RBYTE(PktCmdP->PhbNum), HostP - p->RIOHosts);
+ subCommand = 1;
+ switch (RBYTE(PktCmdP->SubCommand)) {
+ case MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));
break;
+ case READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));
+ p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
+ break;
+ default:
+ subCommand = 0;
+ break;
+ }
+ if (subCommand)
+ break;
+ rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", RBYTE(PktCmdP->PortStatus), PortP->PortState);
+ if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
+ PortP->PortState = RBYTE(PktCmdP->PortStatus);
+ /* What should we do here ...
+ wakeup( &PortP->PortState );
+ */
+ } else
+ rio_dprintk(RIO_DEBUG_CMD, "No change\n");
- case COMPLETE:
- rio_dprintk (RIO_DEBUG_CMD, "Command complete on phb %d host %d\n",
- RBYTE(PktCmdP->PhbNum), HostP-p->RIOHosts);
- subCommand = 1;
- switch (RBYTE(PktCmdP->SubCommand)) {
- case MEMDUMP :
- rio_dprintk (RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n",
- RBYTE(PktCmdP->SubCommand), RWORD(PktCmdP->SubAddr));
- break;
- case READ_REGISTER :
- rio_dprintk (RIO_DEBUG_CMD, "Read register (0x%x)\n", RWORD(PktCmdP->SubAddr));
- p->CdRegister = (RBYTE(PktCmdP->ModemStatus) & MSVR1_HOST);
- break;
- default :
- subCommand = 0;
- break;
- }
- if (subCommand)
- break;
- rio_dprintk (RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n",
- RBYTE(PktCmdP->PortStatus),PortP->PortState);
- if (PortP->PortState != RBYTE(PktCmdP->PortStatus)) {
- rio_dprintk (RIO_DEBUG_CMD, "Mark status & wakeup\n");
- PortP->PortState = RBYTE(PktCmdP->PortStatus);
- /* What should we do here ...
- wakeup( &PortP->PortState );
- */
- } else
- rio_dprintk (RIO_DEBUG_CMD, "No change\n");
-
- /* FALLTHROUGH */
- case MODEM_STATUS:
+ /* FALLTHROUGH */
+ case MODEM_STATUS:
+ /*
+ ** Knock out the tbusy and tstop bits, as these are not relevant
+ ** to the check for modem status change (they're just there because
+ ** it's a convenient place to put them!).
+ */
+ ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
+ if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
/*
- ** Knock out the tbusy and tstop bits, as these are not relevant
- ** to the check for modem status change (they're just there because
- ** it's a convenient place to put them!).
- */
- ReportedModemStatus = RBYTE(PktCmdP->ModemStatus);
- if ((PortP->ModemState & MSVR1_HOST) ==
- (ReportedModemStatus & MSVR1_HOST)) {
- rio_dprintk (RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
- /*
- ** Update ModemState just in case tbusy or tstop states have
- ** changed.
- */
- PortP->ModemState = ReportedModemStatus;
- }
- else {
- rio_dprintk (RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n",
- PortP->ModemState, ReportedModemStatus);
- PortP->ModemState = ReportedModemStatus;
+ ** Update ModemState just in case tbusy or tstop states have
+ ** changed.
+ */
+ PortP->ModemState = ReportedModemStatus;
+ } else {
+ rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
+ PortP->ModemState = ReportedModemStatus;
#ifdef MODEM_SUPPORT
- if ( PortP->Mapped ) {
+ if (PortP->Mapped) {
/***********************************************************\
*************************************************************
*** ***
@@ -525,68 +488,67 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
*************************************************************
\***********************************************************/
/*
- ** If the device is a modem, then check the modem
- ** carrier.
- */
+ ** If the device is a modem, then check the modem
+ ** carrier.
+ */
if (PortP->gs.tty == NULL)
break;
if (PortP->gs.tty->termios == NULL)
break;
-
- if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) &&
- ((PortP->State & (RIO_MOPEN|RIO_WOPEN)))) {
- rio_dprintk (RIO_DEBUG_CMD, "Is there a Carrier?\n");
- /*
- ** Is there a carrier?
- */
- if ( PortP->ModemState & MSVR1_CD ) {
- /*
- ** Has carrier just appeared?
- */
+ if (!(PortP->gs.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
+
+ rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
+ /*
+ ** Is there a carrier?
+ */
+ if (PortP->ModemState & MSVR1_CD) {
+ /*
+ ** Has carrier just appeared?
+ */
if (!(PortP->State & RIO_CARR_ON)) {
- rio_dprintk (RIO_DEBUG_CMD, "Carrier just came up.\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
PortP->State |= RIO_CARR_ON;
- /*
- ** wakeup anyone in WOPEN
- */
- if (PortP->State & (PORT_ISOPEN | RIO_WOPEN) )
- wake_up_interruptible (&PortP->gs.open_wait);
+ /*
+ ** wakeup anyone in WOPEN
+ */
+ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
+ wake_up_interruptible(&PortP->gs.open_wait);
#ifdef STATS
- PortP->Stat.ModemOnCnt++;
+ PortP->Stat.ModemOnCnt++;
#endif
- }
+ }
} else {
- /*
- ** Has carrier just dropped?
- */
+ /*
+ ** Has carrier just dropped?
+ */
if (PortP->State & RIO_CARR_ON) {
- if (PortP->State & (PORT_ISOPEN|RIO_WOPEN|RIO_MOPEN))
- tty_hangup (PortP->gs.tty);
+ if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
+ tty_hangup(PortP->gs.tty);
PortP->State &= ~RIO_CARR_ON;
- rio_dprintk (RIO_DEBUG_CMD, "Carrirer just went down\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
#ifdef STATS
- PortP->Stat.ModemOffCnt++;
+ PortP->Stat.ModemOffCnt++;
#endif
+ }
+ }
+ }
}
- }
- }
- }
#endif
- }
- break;
+ }
+ break;
- default:
- rio_dprintk (RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n",
- RBYTE(PktCmdP->Command),HostP-p->RIOHosts);
- break;
+ default:
+ rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %d\n", RBYTE(PktCmdP->Command), HostP - p->RIOHosts);
+ break;
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- func_exit ();
+ func_exit();
return TRUE;
}
+
/*
** The command mechanism:
** Each rup has a chain of commands associated with it.
@@ -600,12 +562,11 @@ RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
/*
** Allocate an empty command block.
*/
-struct CmdBlk *
-RIOGetCmdBlk(void)
+struct CmdBlk *RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
- CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk));
+ CmdBlkP = (struct CmdBlk *) sysbrk(sizeof(struct CmdBlk));
if (CmdBlkP)
bzero(CmdBlkP, sizeof(struct CmdBlk));
@@ -615,31 +576,24 @@ RIOGetCmdBlk(void)
/*
** Return a block to the head of the free list.
*/
-void
-RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
+void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
{
- sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
+ sysfree((void *) CmdBlkP, sizeof(struct CmdBlk));
}
/*
** attach a command block to the list of commands to be performed for
** a given rup.
*/
-int
-RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
+int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
struct CmdBlk **Base;
struct UnixRup *UnixRupP;
unsigned long flags;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckRup( Rup );
- CheckCmdBlkP( CmdBlkP );
-#endif
- if ( Rup >= (ushort)(MAX_RUP+LINKS_PER_UNIT) ) {
- rio_dprintk (RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n",Rup);
- RIOFreeCmdBlk( CmdBlkP );
+ if (Rup >= (ushort) (MAX_RUP + LINKS_PER_UNIT)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
+ RIOFreeCmdBlk(CmdBlkP);
return RIO_FAIL;
}
@@ -648,57 +602,52 @@ RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
/*
- ** If the RUP is currently inactive, then put the request
- ** straight on the RUP....
- */
- if ( (UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) &&
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE ) &&
- (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg,CmdBlkP)
- :TRUE)) {
- rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
- CmdBlkP->Packet.data[0]);
+ ** If the RUP is currently inactive, then put the request
+ ** straight on the RUP....
+ */
+ if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
+ : TRUE)) {
+ rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
/*
- ** Whammy! blat that pack!
- */
- HostP->Copy( (caddr_t)&CmdBlkP->Packet,
- RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt ), sizeof(PKT) );
+ ** Whammy! blat that pack!
+ */
+ HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
/*
- ** place command packet on the pending position.
- */
+ ** place command packet on the pending position.
+ */
UnixRupP->CmdPendingP = CmdBlkP;
/*
- ** set the command register
- */
- WWORD(UnixRupP->RupP->txcontrol , TX_PACKET_READY);
+ ** set the command register
+ */
+ WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY);
rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
return RIO_SUCCESS;
}
- rio_dprintk (RIO_DEBUG_CMD, "RUP active - en-queing\n");
+ rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
- if ( UnixRupP->CmdsWaitingP != NULL)
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command waiting\n");
- if ( UnixRupP->CmdPendingP != NULL )
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command pending\n");
- if ( RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE )
- rio_dprintk (RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
+ if (UnixRupP->CmdsWaitingP != NULL)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
+ if (UnixRupP->CmdPendingP != NULL)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
+ if (RWORD(UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
+ rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
Base = &UnixRupP->CmdsWaitingP;
- rio_dprintk (RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
- while ( *Base ) {
- rio_dprintk (RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int)(*Base));
+ while (*Base) {
+ rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk 0x%x here\n", (int) (*Base));
Base = &((*Base)->NextP);
- rio_dprintk (RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n",
- (int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
}
- rio_dprintk (RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n",(int)CmdBlkP,(int)Base);
+ rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk 0x%x at 0x%x\n", (int) CmdBlkP, (int) Base);
*Base = CmdBlkP;
@@ -713,8 +662,7 @@ RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
** Here we go - if there is an empty rup, fill it!
** must be called at splrio() or higher.
*/
-void
-RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
+void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
register struct CmdBlk *CmdBlkP;
register struct UnixRup *UnixRupP;
@@ -723,262 +671,234 @@ RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
unsigned long flags;
- Rup = MAX_RUP+LINKS_PER_UNIT;
+ Rup = MAX_RUP + LINKS_PER_UNIT;
- do { /* do this loop for each RUP */
+ do { /* do this loop for each RUP */
/*
- ** locate the rup we are processing & lock it
- */
+ ** locate the rup we are processing & lock it
+ */
UnixRupP = &HostP->UnixRups[--Rup];
spin_lock_irqsave(&UnixRupP->RupLock, flags);
/*
- ** First check for incoming commands:
- */
- if ( RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE ) {
+ ** First check for incoming commands:
+ */
+ if (RWORD(UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
int FreeMe;
- PacketP =(PKT *)RIO_PTR(HostP->Caddr,RWORD(UnixRupP->RupP->rxpkt));
+ PacketP = (PKT *) RIO_PTR(HostP->Caddr, RWORD(UnixRupP->RupP->rxpkt));
- ShowPacket( DBG_CMD, PacketP );
+ ShowPacket(DBG_CMD, PacketP);
- switch ( RBYTE(PacketP->dest_port) ) {
- case BOOT_RUP:
- rio_dprintk (RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n",
- RBYTE(PacketP->len) & 0x80 ? "Command":"Data",
- RBYTE(PacketP->data[0]));
- rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- FreeMe= RIOBootRup(p, Rup,HostP,PacketP);
- rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
- break;
+ switch (RBYTE(PacketP->dest_port)) {
+ case BOOT_RUP:
+ rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", RBYTE(PacketP->len) & 0x80 ? "Command" : "Data", RBYTE(PacketP->data[0]));
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- case COMMAND_RUP:
- /*
- ** Free the RUP lock as loss of carrier causes a
- ** ttyflush which will (eventually) call another
- ** routine that uses the RUP lock.
- */
- rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- FreeMe= RIOCommandRup(p, Rup,HostP,PacketP);
- if (PacketP->data[5] == MEMDUMP) {
- rio_dprintk (RIO_DEBUG_CMD, "Memdump from 0x%x complete\n",
- *(ushort *) &(PacketP->data[6]));
- HostP->Copy( (caddr_t)&(PacketP->data[8]),
- (caddr_t)p->RIOMemDump, 32 );
- }
- rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
- break;
+ case COMMAND_RUP:
+ /*
+ ** Free the RUP lock as loss of carrier causes a
+ ** ttyflush which will (eventually) call another
+ ** routine that uses the RUP lock.
+ */
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
+ if (PacketP->data[5] == MEMDUMP) {
+ rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(ushort *) & (PacketP->data[6]));
+ HostP->Copy((caddr_t) & (PacketP->data[8]), (caddr_t) p->RIOMemDump, 32);
+ }
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- case ROUTE_RUP:
- rio_spin_unlock_irqrestore( &UnixRupP->RupLock, flags);
- FreeMe = RIORouteRup(p, Rup, HostP, PacketP );
- rio_spin_lock_irqsave( &UnixRupP->RupLock, flags );
- break;
+ case ROUTE_RUP:
+ rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+ FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
+ rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+ break;
- default:
- rio_dprintk (RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port));
- FreeMe = 1;
- break;
+ default:
+ rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", RBYTE(PacketP->dest_port));
+ FreeMe = 1;
+ break;
}
- if ( FreeMe ) {
- rio_dprintk (RIO_DEBUG_CMD, "Free processed incoming command packet\n");
- put_free_end(HostP,PacketP);
+ if (FreeMe) {
+ rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
+ put_free_end(HostP, PacketP);
- WWORD(UnixRupP->RupP->rxcontrol , RX_RUP_INACTIVE);
+ WWORD(UnixRupP->RupP->rxcontrol, RX_RUP_INACTIVE);
- if ( RWORD(UnixRupP->RupP->handshake)==PHB_HANDSHAKE_SET ) {
- rio_dprintk (RIO_DEBUG_CMD, "Handshake rup %d\n",Rup);
- WWORD(UnixRupP->RupP->handshake,
- PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+ if (RWORD(UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
+ rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
+ WWORD(UnixRupP->RupP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
}
}
}
/*
- ** IF a command was running on the port,
- ** and it has completed, then tidy it up.
- */
- if ( (CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+ ** IF a command was running on the port,
+ ** and it has completed, then tidy it up.
+ */
+ if ((CmdBlkP = UnixRupP->CmdPendingP) && /* ASSIGN! */
+ (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
/*
- ** we are idle.
- ** there is a command in pending.
- ** Therefore, this command has finished.
- ** So, wakeup whoever is waiting for it (and tell them
- ** what happened).
- */
- if ( CmdBlkP->Packet.dest_port == BOOT_RUP )
- rio_dprintk (RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n",
- CmdBlkP->Packet.len & 0x80 ? "Command":"Data",
- CmdBlkP->Packet.data[0]);
-
- rio_dprintk (RIO_DEBUG_CMD, "Command 0x%x completed\n",(int)CmdBlkP);
+ ** we are idle.
+ ** there is a command in pending.
+ ** Therefore, this command has finished.
+ ** So, wakeup whoever is waiting for it (and tell them
+ ** what happened).
+ */
+ if (CmdBlkP->Packet.dest_port == BOOT_RUP)
+ rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
+
+ rio_dprintk(RIO_DEBUG_CMD, "Command 0x%x completed\n", (int) CmdBlkP);
/*
- ** Clear the Rup lock to prevent mutual exclusion.
- */
- if ( CmdBlkP->PostFuncP ) {
+ ** Clear the Rup lock to prevent mutual exclusion.
+ */
+ if (CmdBlkP->PostFuncP) {
rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg,CmdBlkP);
+ (*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
}
/*
- ** ....clear the pending flag....
- */
+ ** ....clear the pending flag....
+ */
UnixRupP->CmdPendingP = NULL;
/*
- ** ....and return the command block to the freelist.
- */
- RIOFreeCmdBlk( CmdBlkP );
+ ** ....and return the command block to the freelist.
+ */
+ RIOFreeCmdBlk(CmdBlkP);
}
/*
- ** If there is a command for this rup, and the rup
- ** is idle, then process the command
- */
- if ( (CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
- (UnixRupP->CmdPendingP == NULL) &&
- (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+ ** If there is a command for this rup, and the rup
+ ** is idle, then process the command
+ */
+ if ((CmdBlkP = UnixRupP->CmdsWaitingP) && /* ASSIGN! */
+ (UnixRupP->CmdPendingP == NULL) && (RWORD(UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
/*
- ** if the pre-function is non-zero, call it.
- ** If it returns RIO_FAIL then don't
- ** send this command yet!
- */
-#ifdef CHECK
- CheckCmdBlkP (CmdBlkP);
-#endif
- if ( !(CmdBlkP->PreFuncP ?
- (*CmdBlkP->PreFuncP)(CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
- rio_dprintk (RIO_DEBUG_CMD, "Not ready to start command 0x%x\n",(int)CmdBlkP);
- }
- else {
- rio_dprintk (RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n",
- (int)CmdBlkP, CmdBlkP->Packet.data[0]);
+ ** if the pre-function is non-zero, call it.
+ ** If it returns RIO_FAIL then don't
+ ** send this command yet!
+ */
+ if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : TRUE)) {
+ rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command 0x%x\n", (int) CmdBlkP);
+ } else {
+ rio_dprintk(RIO_DEBUG_CMD, "Start new command 0x%x Cmd byte is 0x%x\n", (int) CmdBlkP, CmdBlkP->Packet.data[0]);
/*
- ** Whammy! blat that pack!
- */
-#ifdef CHECK
- CheckPacketP ((PKT *)RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt));
-#endif
- HostP->Copy( (caddr_t)&CmdBlkP->Packet,
- RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
+ ** Whammy! blat that pack!
+ */
+ HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(PKT));
/*
- ** remove the command from the rup command queue...
- */
+ ** remove the command from the rup command queue...
+ */
UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
/*
- ** ...and place it on the pending position.
- */
+ ** ...and place it on the pending position.
+ */
UnixRupP->CmdPendingP = CmdBlkP;
/*
- ** set the command register
- */
- WWORD(UnixRupP->RupP->txcontrol,TX_PACKET_READY);
+ ** set the command register
+ */
+ WWORD(UnixRupP->RupP->txcontrol, TX_PACKET_READY);
/*
- ** the command block will be freed
- ** when the command has been processed.
- */
+ ** the command block will be freed
+ ** when the command has been processed.
+ */
}
}
spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
- } while ( Rup );
+ } while (Rup);
}
-int
-RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
+int RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
PortP->WflushFlag++;
PortP->MagicFlags |= MAGIC_FLUSH;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return RIOUnUse( iPortP, CmdBlkP );
+ return RIOUnUse(iPortP, CmdBlkP);
}
-int
-RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
+int RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
PKT *PacketP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
- while ( can_remove_receive(&PacketP, PortP) ) {
+ while (can_remove_receive(&PacketP, PortP)) {
remove_receive(PortP);
- ShowPacket(DBG_PROC, PacketP );
- put_free_end( PortP->HostP, PacketP );
+ ShowPacket(DBG_PROC, PacketP);
+ put_free_end(PortP->HostP, PacketP);
}
- if ( RWORD(PortP->PhbP->handshake)==PHB_HANDSHAKE_SET ) {
+ if (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
/*
- ** MAGIC! (Basically, handshake the RX buffer, so that
- ** the RTAs upstream can be re-enabled.)
- */
- rio_dprintk (RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
- WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET);
+ ** MAGIC! (Basically, handshake the RX buffer, so that
+ ** the RTAs upstream can be re-enabled.)
+ */
+ rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
+ WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return RIOUnUse( iPortP, CmdBlkP );
+ return RIOUnUse(iPortP, CmdBlkP);
}
-int
-RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
+int RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
{
- struct Port * PortP = (struct Port *)iPortP;
+ struct Port *PortP = (struct Port *) iPortP;
unsigned long flags;
rio_spin_lock_irqsave(&PortP->portSem, flags);
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
- rio_dprintk (RIO_DEBUG_CMD, "Decrement in use count for port\n");
+ rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
if (PortP->InUse) {
- if ( --PortP->InUse != NOT_INUSE ) {
+ if (--PortP->InUse != NOT_INUSE) {
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return 0;
}
}
/*
- ** While PortP->InUse is set (i.e. a preemptive command has been sent to
- ** the RTA and is awaiting completion), any transmit data is prevented from
- ** being transferred from the write queue into the transmit packets
- ** (add_transmit) and no furthur transmit interrupt will be sent for that
- ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
- ** twice a second as a saftey measure). This was the case when kermit was
- ** used to send data into a RIO port. After each packet was sent, TCFLSH
- ** was called to flush the read queue preemptively. PortP->InUse was
- ** incremented, thereby blocking the 6 byte acknowledgement packet
- ** transmitted back. This acknowledgment hung around for 500ms before
- ** being sent, thus reducing input performance substantially!.
- ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
- ** hanging around in the transmit buffer is sent immediately.
- */
+ ** While PortP->InUse is set (i.e. a preemptive command has been sent to
+ ** the RTA and is awaiting completion), any transmit data is prevented from
+ ** being transferred from the write queue into the transmit packets
+ ** (add_transmit) and no furthur transmit interrupt will be sent for that
+ ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
+ ** twice a second as a saftey measure). This was the case when kermit was
+ ** used to send data into a RIO port. After each packet was sent, TCFLSH
+ ** was called to flush the read queue preemptively. PortP->InUse was
+ ** incremented, thereby blocking the 6 byte acknowledgement packet
+ ** transmitted back. This acknowledgment hung around for 500ms before
+ ** being sent, thus reducing input performance substantially!.
+ ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
+ ** hanging around in the transmit buffer is sent immediately.
+ */
WWORD(PortP->HostP->ParmMapP->tx_intr, 1);
/* What to do here ..
- wakeup( (caddr_t)&(PortP->InUse) );
- */
+ wakeup( (caddr_t)&(PortP->InUse) );
+ */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return 0;
}
-void
-ShowPacket(uint Flags, struct PKT *PacketP)
+void ShowPacket(uint Flags, struct PKT *PacketP)
{
}
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index b4d1a23e27e4..fcf18a061228 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -82,16 +82,16 @@ static char *_rioctrl_c_sccs_ = "@(#)rioctrl.c 1.3";
#include "rioioctl.h"
-static struct LpbReq LpbReq;
-static struct RupReq RupReq;
-static struct PortReq PortReq;
-static struct HostReq HostReq;
+static struct LpbReq LpbReq;
+static struct RupReq RupReq;
+static struct PortReq PortReq;
+static struct HostReq HostReq;
static struct HostDpRam HostDpRam;
static struct DebugCtrl DebugCtrl;
-static struct Map MapEnt;
+static struct Map MapEnt;
static struct PortSetup PortSetup;
-static struct DownLoad DownLoad;
-static struct SendPack SendPack;
+static struct DownLoad DownLoad;
+static struct SendPack SendPack;
/* static struct StreamInfo StreamInfo; */
/* static char modemtable[RIO_PORTS]; */
static struct SpecialRupCmd SpecialRupCmd;
@@ -99,18 +99,18 @@ static struct PortParams PortParams;
static struct portStats portStats;
static struct SubCmdStruct {
- ushort Host;
- ushort Rup;
- ushort Port;
- ushort Addr;
+ ushort Host;
+ ushort Rup;
+ ushort Port;
+ ushort Addr;
} SubCmd;
struct PortTty {
- uint port;
- struct ttystatics Tty;
+ uint port;
+ struct ttystatics Tty;
};
-static struct PortTty PortTty;
+static struct PortTty PortTty;
typedef struct ttystatics TERMIO;
/*
@@ -121,267 +121,259 @@ typedef struct ttystatics TERMIO;
** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
** process to bog off.
*/
-static int
-(*RIOBootTable[MAX_PRODUCT])(struct rio_info *, struct DownLoad *) =
-{
-/* 0 */ RIOBootCodeHOST, /* Host Card */
-/* 1 */ RIOBootCodeRTA, /* RTA */
+static int
+ (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
+ /* 0 */ RIOBootCodeHOST,
+ /* Host Card */
+ /* 1 */ RIOBootCodeRTA,
+ /* RTA */
};
#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
-int copyin (int arg, caddr_t dp, int siz)
+int copyin(int arg, caddr_t dp, int siz)
{
- int rv;
+ int rv;
- rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *)arg, dp);
- rv = copy_from_user (dp, (void *)arg, siz);
- if (rv) return COPYFAIL;
- else return rv;
+ rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes from user %p to %p.\n", siz, (void *) arg, dp);
+ rv = copy_from_user(dp, (void *) arg, siz);
+ if (rv)
+ return COPYFAIL;
+ else
+ return rv;
}
-static int copyout (caddr_t dp, int arg, int siz)
+static int copyout(caddr_t dp, int arg, int siz)
{
- int rv;
+ int rv;
- rio_dprintk (RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *)arg, dp);
- rv = copy_to_user ((void *)arg, dp, siz);
- if (rv) return COPYFAIL;
- else return rv;
+ rio_dprintk(RIO_DEBUG_CTRL, "Copying %d bytes to user %p from %p.\n", siz, (void *) arg, dp);
+ rv = copy_to_user((void *) arg, dp, siz);
+ if (rv)
+ return COPYFAIL;
+ else
+ return rv;
}
-int
-riocontrol(p, dev, cmd, arg, su)
-struct rio_info * p;
-dev_t dev;
-int cmd;
-caddr_t arg;
-int su;
+int riocontrol(p, dev, cmd, arg, su)
+struct rio_info *p;
+dev_t dev;
+int cmd;
+caddr_t arg;
+int su;
{
- uint Host; /* leave me unsigned! */
- uint port; /* and me! */
- struct Host *HostP;
- ushort loop;
- int Entry;
- struct Port *PortP;
- PKT *PacketP;
- int retval = 0;
+ uint Host; /* leave me unsigned! */
+ uint port; /* and me! */
+ struct Host *HostP;
+ ushort loop;
+ int Entry;
+ struct Port *PortP;
+ PKT *PacketP;
+ int retval = 0;
unsigned long flags;
-
- func_enter ();
-
+
+ func_enter();
+
/* Confuse the compiler to think that we've initialized these */
- Host=0;
+ Host = 0;
PortP = NULL;
- rio_dprintk (RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int)arg);
+ rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: 0x%x\n", cmd, (int) arg);
switch (cmd) {
/*
- ** RIO_SET_TIMER
- **
- ** Change the value of the host card interrupt timer.
- ** If the host card number is -1 then all host cards are changed
- ** otherwise just the specified host card will be changed.
- */
- case RIO_SET_TIMER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint)arg);
- {
- int host, value;
- host = (uint)arg >> 16;
- value = (uint)arg & 0x0000ffff;
- if (host == -1) {
- for (host = 0; host < p->RIONumHosts; host++) {
- if (p->RIOHosts[host].Flags == RC_RUNNING) {
- WWORD(p->RIOHosts[host].ParmMapP->timer , value);
- }
- }
- } else if (host >= p->RIONumHosts) {
- return -EINVAL;
- } else {
- if ( p->RIOHosts[host].Flags == RC_RUNNING ) {
- WWORD(p->RIOHosts[host].ParmMapP->timer , value);
+ ** RIO_SET_TIMER
+ **
+ ** Change the value of the host card interrupt timer.
+ ** If the host card number is -1 then all host cards are changed
+ ** otherwise just the specified host card will be changed.
+ */
+ case RIO_SET_TIMER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %dms\n", (uint) arg);
+ {
+ int host, value;
+ host = (uint) arg >> 16;
+ value = (uint) arg & 0x0000ffff;
+ if (host == -1) {
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (p->RIOHosts[host].Flags == RC_RUNNING) {
+ WWORD(p->RIOHosts[host].ParmMapP->timer, value);
}
}
- }
- return 0;
-
- case RIO_IDENTIFY_DRIVER:
- /*
- ** 15.10.1998 ARG - ESIL 0760 part fix
- ** Added driver ident string output.
- **
-#ifndef __THIS_RELEASE__
-#warning Driver Version string not defined !
-#endif
- cprintf("%s %s %s %s\n",
- RIO_DRV_STR,
- __THIS_RELEASE__,
- __DATE__, __TIME__ );
-
- return 0;
-
- case RIO_DISPLAY_HOST_CFG:
- **
- ** 15.10.1998 ARG - ESIL 0760 part fix
- ** Added driver host card ident string output.
- **
- ** Note that the only types currently supported
- ** are ISA and PCI. Also this driver does not
- ** (yet) distinguish between the Old PCI card
- ** and the Jet PCI card. In fact I think this
- ** driver only supports JET PCI !
- **
-
- for (Host = 0; Host < p->RIONumHosts; Host++)
- {
- HostP = &(p->RIOHosts[Host]);
-
- switch ( HostP->Type )
- {
- case RIO_AT :
- strcpy( host_type, RIO_AT_HOST_STR );
- break;
-
- case RIO_PCI :
- strcpy( host_type, RIO_PCI_HOST_STR );
- break;
-
- default :
- strcpy( host_type, "Unknown" );
- break;
+ } else if (host >= p->RIONumHosts) {
+ return -EINVAL;
+ } else {
+ if (p->RIOHosts[host].Flags == RC_RUNNING) {
+ WWORD(p->RIOHosts[host].ParmMapP->timer, value);
}
+ }
+ }
+ return 0;
- cprintf(
- "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
- Host, host_type,
- (uint)HostP->PaddrP,
- (int)HostP->Ivec - 32 );
+ case RIO_IDENTIFY_DRIVER:
+ /*
+ ** 15.10.1998 ARG - ESIL 0760 part fix
+ ** Added driver ident string output.
+ **
+ #ifndef __THIS_RELEASE__
+ #warning Driver Version string not defined !
+ #endif
+ cprintf("%s %s %s %s\n",
+ RIO_DRV_STR,
+ __THIS_RELEASE__,
+ __DATE__, __TIME__ );
+
+ return 0;
+
+ case RIO_DISPLAY_HOST_CFG:
+ **
+ ** 15.10.1998 ARG - ESIL 0760 part fix
+ ** Added driver host card ident string output.
+ **
+ ** Note that the only types currently supported
+ ** are ISA and PCI. Also this driver does not
+ ** (yet) distinguish between the Old PCI card
+ ** and the Jet PCI card. In fact I think this
+ ** driver only supports JET PCI !
+ **
+
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ {
+ HostP = &(p->RIOHosts[Host]);
+
+ switch ( HostP->Type )
+ {
+ case RIO_AT :
+ strcpy( host_type, RIO_AT_HOST_STR );
+ break;
+
+ case RIO_PCI :
+ strcpy( host_type, RIO_PCI_HOST_STR );
+ break;
+
+ default :
+ strcpy( host_type, "Unknown" );
+ break;
+ }
+
+ cprintf(
+ "RIO Host %d - Type:%s Addr:%X IRQ:%d\n",
+ Host, host_type,
+ (uint)HostP->PaddrP,
+ (int)HostP->Ivec - 32 );
+ }
+ return 0;
+ **
+ */
+
+ case RIO_FOAD_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
+ return RIOCommandRta(p, (uint) arg, RIOFoadRta);
+
+ case RIO_ZOMBIE_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
+ return RIOCommandRta(p, (uint) arg, RIOZombieRta);
+
+ case RIO_IDENTIFY_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
+ return RIOIdentifyRta(p, arg);
+
+ case RIO_KILL_NEIGHBOUR:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
+ return RIOKillNeighbour(p, arg);
+
+ case SPECIAL_RUP_CMD:
+ {
+ struct CmdBlk *CmdBlkP;
+
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
+ if (copyin((int) arg, (caddr_t) & SpecialRupCmd, sizeof(SpecialRupCmd)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ CmdBlkP = RIOGetCmdBlk();
+ if (!CmdBlkP) {
+ rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
+ return -ENXIO;
+ }
+ CmdBlkP->Packet = SpecialRupCmd.Packet;
+ if (SpecialRupCmd.Host >= p->RIONumHosts)
+ SpecialRupCmd.Host = 0;
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
+ if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
+ cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
}
return 0;
- **
- */
-
- case RIO_FOAD_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
- return RIOCommandRta(p, (uint)arg, RIOFoadRta);
-
- case RIO_ZOMBIE_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
- return RIOCommandRta(p, (uint)arg, RIOZombieRta);
-
- case RIO_IDENTIFY_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
- return RIOIdentifyRta(p, arg);
-
- case RIO_KILL_NEIGHBOUR:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
- return RIOKillNeighbour(p, arg);
-
- case SPECIAL_RUP_CMD:
- {
- struct CmdBlk *CmdBlkP;
-
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
- if (copyin((int)arg, (caddr_t)&SpecialRupCmd,
- sizeof(SpecialRupCmd)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- CmdBlkP = RIOGetCmdBlk();
- if ( !CmdBlkP ) {
- rio_dprintk (RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
- return -ENXIO;
- }
- CmdBlkP->Packet = SpecialRupCmd.Packet;
- if ( SpecialRupCmd.Host >= p->RIONumHosts )
- SpecialRupCmd.Host = 0;
- rio_dprintk (RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n",
- SpecialRupCmd.Host, SpecialRupCmd.RupNum);
- if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host],
- SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
- cprintf("FAILED TO QUEUE SPECIAL RUP COMMAND\n");
- }
- return 0;
- }
-
- case RIO_DEBUG_MEM:
-#ifdef DEBUG_MEM_SUPPORT
-RIO_DEBUG_CTRL, if (su)
- return rio_RIODebugMemory(RIO_DEBUG_CTRL, arg);
- else
-#endif
- return -EPERM;
-
- case RIO_ALL_MODEM:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
- p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
- return -EINVAL;
+ }
- case RIO_GET_TABLE:
- /*
- ** Read the routing table from the device driver to user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+ case RIO_DEBUG_MEM:
+ return -EPERM;
- if ((retval = RIOApel(p)) != 0)
- return retval;
+ case RIO_ALL_MODEM:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
+ p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+ return -EINVAL;
- if (copyout((caddr_t)p->RIOConnectTable, (int)arg,
- TOTAL_MAP_ENTRIES*sizeof(struct Map)) == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
+ case RIO_GET_TABLE:
+ /*
+ ** Read the routing table from the device driver to user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+
+ if ((retval = RIOApel(p)) != 0)
+ return retval;
+
+ if (copyout((caddr_t) p->RIOConnectTable, (int) arg, TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+
+ {
+ int entry;
+ rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
+ continue;
+
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
+ rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
+ }
+ p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */
+ return 0;
- {
- int entry;
- rio_dprintk (RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
- for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
- {
- if ((p->RIOConnectTable[entry].ID == 0) &&
- (p->RIOConnectTable[entry].HostUniqueNum == 0) &&
- (p->RIOConnectTable[entry].RtaUniqueNum == 0)) continue;
-
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int)p->RIOConnectTable[entry].Flags );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int)p->RIOConnectTable[entry].SysPort );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link );
- rio_dprintk (RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name );
- }
- rio_dprintk (RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
- }
- p->RIOQuickCheck = NOT_CHANGED; /* a table has been gotten */
- return 0;
-
- case RIO_PUT_TABLE:
- /*
- ** Write the routing table to the device driver from user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
-
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&p->RIOConnectTable[0],
- TOTAL_MAP_ENTRIES*sizeof(struct Map) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
+ case RIO_PUT_TABLE:
+ /*
+ ** Write the routing table to the device driver from user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOConnectTable[0], TOTAL_MAP_ENTRIES * sizeof(struct Map)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
/*
***********************************
{
@@ -409,1353 +401,1144 @@ RIO_DEBUG_CTRL, if (su)
}
***********************************
*/
- return RIONewTable(p);
-
- case RIO_GET_BINDINGS :
- /*
- ** Send bindings table, containing unique numbers of RTAs owned
- ** by this system to user space
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
-
- if ( !su )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyout((caddr_t) p->RIOBindTab, (int)arg,
- (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
+ return RIONewTable(p);
- case RIO_PUT_BINDINGS :
+ case RIO_GET_BINDINGS:
+ /*
+ ** Send bindings table, containing unique numbers of RTAs owned
+ ** by this system to user space
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyout((caddr_t) p->RIOBindTab, (int) arg, (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_PUT_BINDINGS:
+ /*
+ ** Receive a bindings table, containing unique numbers of RTAs owned
+ ** by this system
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOBindTab[0], (sizeof(ulong) * MAX_RTA_BINDINGS)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_BIND_RTA:
+ {
+ int EmptySlot = -1;
/*
- ** Receive a bindings table, containing unique numbers of RTAs owned
- ** by this system
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
-
- if ( !su )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&p->RIOBindTab[0],
- (sizeof(ulong) * MAX_RTA_BINDINGS))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_BIND_RTA :
- {
- int EmptySlot = -1;
- /*
- ** Bind this RTA to host, so that it will be booted by
- ** host in 'boot owned RTAs' mode.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
-
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
- if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
- EmptySlot = Entry;
- else if (p->RIOBindTab[Entry] == (int) arg) {
- /*
- ** Already exists - delete
- */
- p->RIOBindTab[Entry] = 0L;
- rio_dprintk (RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n",
- (int) arg);
- return 0;
- }
- }
+ ** Bind this RTA to host, so that it will be booted by
+ ** host in 'boot owned RTAs' mode.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
+
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
+ if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
+ EmptySlot = Entry;
+ else if (p->RIOBindTab[Entry] == (int) arg) {
/*
- ** Dosen't exist - add
- */
- if (EmptySlot != -1) {
- p->RIOBindTab[EmptySlot] = (int) arg;
- rio_dprintk (RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n",
- (int) arg);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n",
- (int) arg);
- return -ENOMEM;
- }
+ ** Already exists - delete
+ */
+ p->RIOBindTab[Entry] = 0L;
+ rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %x from p->RIOBindTab\n", (int) arg);
return 0;
}
-
- case RIO_RESUME :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME\n");
- port = (uint) arg;
- if ((port < 0) || (port > 511)) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- PortP = p->RIOPortp[port];
- if (!PortP->Mapped) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
- p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
- return -EINVAL;
- }
- if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
- return -EINVAL;
- }
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) ==
- RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EBUSY;
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
- PortP->State |= RIO_BUSY;
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return retval;
-
- case RIO_ASSIGN_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIOAssignRta(p, &MapEnt);
-
- case RIO_CHANGE_NAME:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+ }
+ /*
+ ** Dosen't exist - add
+ */
+ if (EmptySlot != -1) {
+ p->RIOBindTab[EmptySlot] = (int) arg;
+ rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %x to p->RIOBindTab\n", (int) arg);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", (int) arg);
+ return -ENOMEM;
+ }
+ return 0;
+ }
+
+ case RIO_RESUME:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
+ port = (uint) arg;
+ if ((port < 0) || (port > 511)) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ PortP = p->RIOPortp[port];
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
+ p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+ return -EINVAL;
+ }
+ if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
+ return -EINVAL;
+ }
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
+ PortP->State |= RIO_BUSY;
+ }
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_ASSIGN_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIOAssignRta(p, &MapEnt);
+
+ case RIO_CHANGE_NAME:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIOChangeName(p, &MapEnt);
+
+ case RIO_DELETE_RTA:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & MapEnt, sizeof(MapEnt))
+ == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ return RIODeleteRta(p, &MapEnt);
+
+ case RIO_QUICK_CHECK:
+ /*
+ ** 09.12.1998 ARG - ESIL 0776 part fix
+ ** A customer was using this to get the RTAs
+ ** connect/disconnect status.
+ ** RIOConCon() had been botched use RIOHalted
+ ** to keep track of RTA connections and
+ ** disconnections. That has been changed and
+ ** RIORtaDisCons in the rio_info struct now
+ ** does the job. So we need to return the value
+ ** of RIORtaCons instead of RIOHalted.
+ **
+ if (copyout((caddr_t)&p->RIOHalted,(int)arg,
+ sizeof(uint))==COPYFAIL) {
+ **
+ */
+
+ if (copyout((caddr_t) & p->RIORtaDisCons, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_LAST_ERROR:
+ if (copyout((caddr_t) & p->RIOError, (int) arg, sizeof(struct Error)) == COPYFAIL)
+ return -EFAULT;
+ return 0;
+
+ case RIO_GET_LOG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
+ return -EINVAL;
+
+ case RIO_GET_MODTYPE:
+ if (copyin((int) arg, (caddr_t) & port, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
+ if (port < 0 || port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ PortP = (p->RIOPortp[port]);
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
+ p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+ return -EINVAL;
+ }
+ /*
+ ** Return module type of port
+ */
+ port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
+ if (copyout((caddr_t) & port, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return (0);
+ /*
+ ** 02.03.1999 ARG - ESIL 0820 fix
+ ** We are no longer using "Boot Mode", so these ioctls
+ ** are not required :
+ **
+ case RIO_GET_BOOT_MODE :
+ rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
+ **
+ ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
+ **
+ if (copyout((caddr_t)&p->RIOBootMode, (int)arg,
+ sizeof(p->RIOBootMode)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return(0);
+
+ case RIO_SET_BOOT_MODE :
+ p->RIOBootMode = (uint) arg;
+ rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
+ return(0);
+ **
+ ** End ESIL 0820 fix
+ */
+
+ case RIO_BLOCK_OPENS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
+ for (Entry = 0; Entry < RIO_PORTS; Entry++) {
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[Entry]->WaitUntilBooted = 1;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ return 0;
+
+ case RIO_SETUP_PORTS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
+ if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
+ return -EFAULT;
+ }
+ if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
+ return -ENXIO;
+ }
+ if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
+ p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
+ return -EINVAL;
+ }
+ if (!p->RIOPortp) {
+ cprintf("No p->RIOPortp array!\n");
+ rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
+ for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
+ rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
+ rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
+ return retval;
+
+ case RIO_GET_PORT_SETUP:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
+ if (copyin((int) arg, (caddr_t) & PortSetup, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortSetup.From >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ port = PortSetup.To = PortSetup.From;
+ PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
+ PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
+ PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
+ PortSetup.Store = p->RIOPortp[port]->Store;
+ PortSetup.Lock = p->RIOPortp[port]->Lock;
+ PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
+ bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn, MAX_XP_CTRL_LEN);
+ bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff, MAX_XP_CTRL_LEN);
+ PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
+ PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
+
+ if (copyout((caddr_t) & PortSetup, (int) arg, sizeof(PortSetup))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_GET_PORT_PARAMS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
+ if (copyin((int) arg, (caddr_t) & PortParams, sizeof(struct PortParams)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortParams.Port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortParams.Port]);
+ PortParams.Config = PortP->Config;
+ PortParams.State = PortP->State;
+ rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
+
+ if (copyout((caddr_t) & PortParams, (int) arg, sizeof(struct PortParams)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_GET_PORT_TTY:
+ rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
+ if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortTty.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
+ PortP = (p->RIOPortp[PortTty.port]);
+ if (copyout((caddr_t) & PortTty, (int) arg, sizeof(struct PortTty)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_PORT_TTY:
+ if (copyin((int) arg, (caddr_t) & PortTty, sizeof(struct PortTty)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
+ if (PortTty.port >= (ushort) RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortTty.port]);
+ RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
+ return retval;
+
+ case RIO_SET_PORT_PARAMS:
+ rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
+ if (copyin((int) arg, (caddr_t) & PortParams, sizeof(PortParams))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (PortParams.Port >= (ushort) RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[PortParams.Port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->Config = PortParams.Config;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_GET_PORT_STATS:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
+ if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (portStats.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[portStats.port]);
+ portStats.gather = PortP->statsGather;
+ portStats.txchars = PortP->txchars;
+ portStats.rxchars = PortP->rxchars;
+ portStats.opens = PortP->opens;
+ portStats.closes = PortP->closes;
+ portStats.ioctls = PortP->ioctls;
+ if (copyout((caddr_t) & portStats, (int) arg, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_RESET_PORT_STATS:
+ port = (uint) arg;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
+ if (port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->txchars = 0;
+ PortP->rxchars = 0;
+ PortP->opens = 0;
+ PortP->closes = 0;
+ PortP->ioctls = 0;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_GATHER_PORT_STATS:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
+ if (copyin((int) arg, (caddr_t) & portStats, sizeof(struct portStats)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (portStats.port >= RIO_PORTS) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ PortP = (p->RIOPortp[portStats.port]);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->statsGather = portStats.gather;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_READ_CONFIG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
+ if (copyout((caddr_t) & p->RIOConf, (int) arg, sizeof(struct Conf)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_CONFIG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & p->RIOConf, sizeof(struct Conf))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ /*
+ ** move a few value around
+ */
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
+ WWORD(p->RIOHosts[Host].ParmMapP->timer, p->RIOConf.Timer);
+ return retval;
+
+ case RIO_START_POLLER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
+ return -EINVAL;
+
+ case RIO_STOP_POLLER:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ p->RIOPolling = NOT_POLLING;
+ return retval;
+
+ case RIO_SETDEBUG:
+ case RIO_GETDEBUG:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
+ if (copyin((int) arg, (caddr_t) & DebugCtrl, sizeof(DebugCtrl))
+ == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (DebugCtrl.SysPort == NO_PORT) {
+ if (cmd == RIO_SETDEBUG) {
+ if (!su) {
p->RIOError.Error = NOT_SUPER_USER;
return -EPERM;
}
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIOChangeName(p, &MapEnt);
-
- case RIO_DELETE_RTA:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if (copyin((int)arg, (caddr_t)&MapEnt, sizeof(MapEnt))
- == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Copy from data space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- return RIODeleteRta(p, &MapEnt);
-
- case RIO_QUICK_CHECK:
- /*
- ** 09.12.1998 ARG - ESIL 0776 part fix
- ** A customer was using this to get the RTAs
- ** connect/disconnect status.
- ** RIOConCon() had been botched use RIOHalted
- ** to keep track of RTA connections and
- ** disconnections. That has been changed and
- ** RIORtaDisCons in the rio_info struct now
- ** does the job. So we need to return the value
- ** of RIORtaCons instead of RIOHalted.
- **
- if (copyout((caddr_t)&p->RIOHalted,(int)arg,
- sizeof(uint))==COPYFAIL) {
- **
- */
-
- if (copyout((caddr_t)&p->RIORtaDisCons,(int)arg,
- sizeof(uint))==COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_LAST_ERROR:
- if (copyout((caddr_t)&p->RIOError, (int)arg,
- sizeof(struct Error)) ==COPYFAIL )
- return -EFAULT;
- return 0;
-
- case RIO_GET_LOG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-#ifdef LOGGING
- RIOGetLog(arg);
- return 0;
-#else
- return -EINVAL;
-#endif
-
- case RIO_GET_MODTYPE:
- if ( copyin( (int)arg, (caddr_t)&port,
- sizeof(uint)) == COPYFAIL )
- {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
- if ( port < 0 || port > 511 )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- PortP = (p->RIOPortp[port]);
- if (!PortP->Mapped)
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
- p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
- return -EINVAL;
- }
- /*
- ** Return module type of port
- */
- port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
- if (copyout((caddr_t)&port, (int)arg,
- sizeof(uint)) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return(0);
- /*
- ** 02.03.1999 ARG - ESIL 0820 fix
- ** We are no longer using "Boot Mode", so these ioctls
- ** are not required :
- **
- case RIO_GET_BOOT_MODE :
- rio_dprint(RIO_DEBUG_CTRL, ("Get boot mode - %x\n", p->RIOBootMode));
- **
- ** Return boot state of system - BOOT_ALL, BOOT_OWN or BOOT_NONE
- **
- if (copyout((caddr_t)&p->RIOBootMode, (int)arg,
- sizeof(p->RIOBootMode)) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return(0);
-
- case RIO_SET_BOOT_MODE :
- p->RIOBootMode = (uint) arg;
- rio_dprint(RIO_DEBUG_CTRL, ("Set boot mode to 0x%x\n", p->RIOBootMode));
- return(0);
- **
- ** End ESIL 0820 fix
- */
-
- case RIO_BLOCK_OPENS:
- rio_dprintk (RIO_DEBUG_CTRL, "Opens block until booted\n");
- for ( Entry=0; Entry < RIO_PORTS; Entry++ ) {
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[Entry]->WaitUntilBooted = 1;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
- return 0;
-
- case RIO_SETUP_PORTS:
- rio_dprintk (RIO_DEBUG_CTRL, "Setup ports\n");
- if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "EFAULT");
- return -EFAULT;
- }
- if ( PortSetup.From > PortSetup.To ||
- PortSetup.To >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "ENXIO");
- return -ENXIO;
- }
- if ( PortSetup.XpCps > p->RIOConf.MaxXpCps ||
- PortSetup.XpCps < p->RIOConf.MinXpCps ) {
- p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "EINVAL");
- return -EINVAL;
- }
- if ( !p->RIOPortp ) {
- cprintf("No p->RIOPortp array!\n");
- rio_dprintk (RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
- for (loop=PortSetup.From; loop<=PortSetup.To; loop++) {
- rio_dprintk (RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-#if 0
- PortP = p->RIOPortp[loop];
- if ( !PortP->TtyP )
- PortP->TtyP = &p->channel[loop];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- if ( PortSetup.IxAny )
- PortP->Config |= RIO_IXANY;
- else
- PortP->Config &= ~RIO_IXANY;
- if ( PortSetup.IxOn )
- PortP->Config |= RIO_IXON;
- else
- PortP->Config &= ~RIO_IXON;
-
- /*
- ** If the port needs to wait for all a processes output
- ** to drain before closing then this flag will be set.
- */
- if (PortSetup.Drain) {
- PortP->Config |= RIO_WAITDRAIN;
- } else {
- PortP->Config &= ~RIO_WAITDRAIN;
- }
- /*
- ** Store settings if locking or unlocking port or if the
- ** port is not locked, when setting the store option.
- */
- if (PortP->Mapped &&
- ((PortSetup.Lock && !PortP->Lock) ||
- (!PortP->Lock &&
- (PortSetup.Store && !PortP->Store)))) {
- PortP->StoredTty.iflag = PortP->TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = PortP->TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = PortP->TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = PortP->TtyP->tm.c_lflag;
- PortP->StoredTty.line = PortP->TtyP->tm.c_line;
- bcopy(PortP->TtyP->tm.c_cc, PortP->StoredTty.cc,
- NCC + 5);
- }
- PortP->Lock = PortSetup.Lock;
- PortP->Store = PortSetup.Store;
- PortP->Xprint.XpCps = PortSetup.XpCps;
- bcopy(PortSetup.XpOn,PortP->Xprint.XpOn,MAX_XP_CTRL_LEN);
- bcopy(PortSetup.XpOff,PortP->Xprint.XpOff,MAX_XP_CTRL_LEN);
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = RIOStrlen(PortP->Xprint.XpOn)+
- RIOStrlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
-#endif
- }
- rio_dprintk (RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
- rio_dprintk (RIO_DEBUG_CTRL, "Retval:%x\n", retval);
- return retval;
-
- case RIO_GET_PORT_SETUP :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port setup\n");
- if (copyin((int)arg, (caddr_t)&PortSetup, sizeof(PortSetup))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( PortSetup.From >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- port = PortSetup.To = PortSetup.From;
- PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ?
- 1 : 0;
- PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ?
- 1 : 0;
- PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ?
- 1 : 0;
- PortSetup.Store = p->RIOPortp[port]->Store;
- PortSetup.Lock = p->RIOPortp[port]->Lock;
- PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
- bcopy(p->RIOPortp[port]->Xprint.XpOn, PortSetup.XpOn,
- MAX_XP_CTRL_LEN);
- bcopy(p->RIOPortp[port]->Xprint.XpOff, PortSetup.XpOff,
- MAX_XP_CTRL_LEN);
- PortSetup.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortSetup.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
-
- if ( copyout((caddr_t)&PortSetup,(int)arg,sizeof(PortSetup))
- ==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_GET_PORT_PARAMS :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port params\n");
- if (copyin( (int)arg, (caddr_t)&PortParams,
- sizeof(struct PortParams)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (PortParams.Port >= RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortParams.Port]);
- PortParams.Config = PortP->Config;
- PortParams.State = PortP->State;
- rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
-
- if (copyout((caddr_t)&PortParams, (int)arg,
- sizeof(struct PortParams)) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_GET_PORT_TTY :
- rio_dprintk (RIO_DEBUG_CTRL, "Get port tty\n");
- if (copyin((int)arg, (caddr_t)&PortTty, sizeof(struct PortTty))
- == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( PortTty.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- rio_dprintk (RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
- PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- PortTty.Tty.tm.c_iflag = PortP->TtyP->tm.c_iflag;
- PortTty.Tty.tm.c_oflag = PortP->TtyP->tm.c_oflag;
- PortTty.Tty.tm.c_cflag = PortP->TtyP->tm.c_cflag;
- PortTty.Tty.tm.c_lflag = PortP->TtyP->tm.c_lflag;
-#endif
- if (copyout((caddr_t)&PortTty, (int)arg,
- sizeof(struct PortTty)) == COPYFAIL) {
+ p->rio_debug = DebugCtrl.Debug;
+ p->RIODebugWait = DebugCtrl.Wait;
+ rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
+ DebugCtrl.Debug = p->rio_debug;
+ DebugCtrl.Wait = p->RIODebugWait;
+ if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
p->RIOError.Error = COPYOUT_FAILED;
return -EFAULT;
}
- return retval;
-
- case RIO_SET_PORT_TTY :
- if (copyin((int)arg, (caddr_t)&PortTty,
- sizeof(struct PortTty)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
- if (PortTty.port >= (ushort) RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortTty.port]);
-#if 0
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->TtyP->tm.c_iflag = PortTty.Tty.tm.c_iflag;
- PortP->TtyP->tm.c_oflag = PortTty.Tty.tm.c_oflag;
- PortP->TtyP->tm.c_cflag = PortTty.Tty.tm.c_cflag;
- PortP->TtyP->tm.c_lflag = PortTty.Tty.tm.c_lflag;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
-#endif
-
- RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
- return retval;
-
- case RIO_SET_PORT_PARAMS :
- rio_dprintk (RIO_DEBUG_CTRL, "Set port params\n");
- if ( copyin((int)arg, (caddr_t)&PortParams, sizeof(PortParams))
- == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (PortParams.Port >= (ushort) RIO_PORTS) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[PortParams.Port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->Config = PortParams.Config;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_GET_PORT_STATS :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
- if ( copyin((int)arg, (caddr_t)&portStats,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( portStats.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[portStats.port]);
- portStats.gather = PortP->statsGather;
- portStats.txchars = PortP->txchars;
- portStats.rxchars = PortP->rxchars;
- portStats.opens = PortP->opens;
- portStats.closes = PortP->closes;
- portStats.ioctls = PortP->ioctls;
- if ( copyout((caddr_t)&portStats, (int)arg,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_RESET_PORT_STATS :
- port = (uint) arg;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
- if ( port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->txchars = 0;
- PortP->rxchars = 0;
- PortP->opens = 0;
- PortP->closes = 0;
- PortP->ioctls = 0;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return retval;
-
- case RIO_GATHER_PORT_STATS :
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
- if ( copyin( (int)arg, (caddr_t)&portStats,
- sizeof(struct portStats)) == COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( portStats.port >= RIO_PORTS ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- PortP = (p->RIOPortp[portStats.port]);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->statsGather = portStats.gather;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
-#ifdef DEBUG_SUPPORTED
- case RIO_READ_LEVELS:
- {
- int num;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_LEVELS\n");
- for ( num=0; RIODbInf[num].Flag; num++ ) ;
- rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copy\n",num);
- if (copyout((caddr_t)RIODbInf,(int)arg,
- sizeof(struct DbInf)*(num+1))==COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "ReadLevels Copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "%d levels to copied\n",num);
- return retval;
- }
-#endif
-
- case RIO_READ_CONFIG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
- if (copyout((caddr_t)&p->RIOConf, (int)arg,
- sizeof(struct Conf)) ==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
+ }
+ } else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ } else if (cmd == RIO_SETDEBUG) {
+ if (!su) {
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+ DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
+ if (copyout((caddr_t) & DebugCtrl, (int) arg, sizeof(DebugCtrl)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ }
+ return retval;
- case RIO_SET_CONFIG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&p->RIOConf, sizeof(struct Conf) )
- ==COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- /*
- ** move a few value around
- */
- for (Host=0; Host < p->RIONumHosts; Host++)
- if ( (p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING )
- WWORD(p->RIOHosts[Host].ParmMapP->timer ,
- p->RIOConf.Timer);
- return retval;
-
- case RIO_START_POLLER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
- return -EINVAL;
+ case RIO_VERSID:
+ /*
+ ** Enquire about the release and version.
+ ** We return MAX_VERSION_LEN bytes, being a
+ ** textual null terminated string.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
+ if (copyout((caddr_t) RIOVersid(), (int) arg, sizeof(struct rioVersion)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
- case RIO_STOP_POLLER:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->RIOPolling = NOT_POLLING;
- return retval;
-
- case RIO_SETDEBUG:
- case RIO_GETDEBUG:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
- if ( copyin( (int)arg, (caddr_t)&DebugCtrl, sizeof(DebugCtrl) )
- ==COPYFAIL ) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( DebugCtrl.SysPort == NO_PORT ) {
- if ( cmd == RIO_SETDEBUG ) {
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->rio_debug = DebugCtrl.Debug;
- p->RIODebugWait = DebugCtrl.Wait;
- rio_dprintk (RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n",
- p->rio_debug,p->RIODebugWait);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n",
- p->rio_debug,p->RIODebugWait);
- DebugCtrl.Debug = p->rio_debug;
- DebugCtrl.Wait = p->RIODebugWait;
- if ( copyout((caddr_t)&DebugCtrl,(int)arg,
- sizeof(DebugCtrl)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
- DebugCtrl.SysPort);
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- }
- }
- else if ( DebugCtrl.SysPort >= RIO_PORTS &&
- DebugCtrl.SysPort != NO_PORT ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n",
- DebugCtrl.SysPort);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- else if ( cmd == RIO_SETDEBUG ) {
- if ( !su ) {
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n",
- p->RIOPortp[DebugCtrl.SysPort]->Debug);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n",
- p->RIOPortp[DebugCtrl.SysPort]->Debug);
- DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
- if ( copyout((caddr_t)&DebugCtrl,(int)arg,
- sizeof(DebugCtrl))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- }
- return retval;
-
- case RIO_VERSID:
- /*
- ** Enquire about the release and version.
- ** We return MAX_VERSION_LEN bytes, being a
- ** textual null terminated string.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID\n");
- if ( copyout( (caddr_t)RIOVersid(),
- (int)arg,
- sizeof(struct rioVersion) ) == COPYFAIL )
- {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
+ /*
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ ** !! commented out previous 'RIO_VERSID' functionality !!
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ **
+ case RIO_VERSID:
+ **
+ ** Enquire about the release and version.
+ ** We return MAX_VERSION_LEN bytes, being a textual null
+ ** terminated string.
+ **
+ rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
+ if (copyout((caddr_t)RIOVersid(),
+ (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
+ rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+ **
+ ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+ case RIO_NUM_HOSTS:
+ /*
+ ** Enquire as to the number of hosts located
+ ** at init time.
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
+ if (copyout((caddr_t) & p->RIONumHosts, (int) arg, sizeof(p->RIONumHosts)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_FOAD:
+ /*
+ ** Kill host. This may not be in the final version...
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int) arg);
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ p->RIOHalted = 1;
+ p->RIOSystemUp = 0;
+
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
+ (void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
+ bzero((caddr_t) & p->RIOHosts[Host].Flags, ((int) &p->RIOHosts[Host].____end_marker____) - ((int) &p->RIOHosts[Host].Flags));
+ p->RIOHosts[Host].Flags = RC_WAITING;
+ }
+ RIOFoadWakeup(p);
+ p->RIONumBootPkts = 0;
+ p->RIOBooting = 0;
+ printk("HEEEEELP!\n");
+
+ for (loop = 0; loop < RIO_PORTS; loop++) {
+ spin_lock_init(&p->RIOPortp[loop]->portSem);
+ p->RIOPortp[loop]->InUse = NOT_INUSE;
+ }
+
+ p->RIOSystemUp = 0;
+ return retval;
+
+ case RIO_DOWNLOAD:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
+ if (!su) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
+ p->RIOError.Error = NOT_SUPER_USER;
+ return -EPERM;
+ }
+ if (copyin((int) arg, (caddr_t) & DownLoad, sizeof(DownLoad)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
+ /*
+ ** It is important that the product code is an unsigned object!
+ */
+ if (DownLoad.ProductCode > MAX_PRODUCT) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
+ p->RIOError.Error = NO_SUCH_PRODUCT;
+ return -ENXIO;
+ }
+ /*
+ ** do something!
+ */
+ retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
+ /* <-- Panic */
+ p->RIOHalted = 0;
+ /*
+ ** and go back, content with a job well completed.
+ */
+ return retval;
+
+ case RIO_PARMS:
+ {
+ uint host;
+
+ if (copyin((int) arg, (caddr_t) & host, sizeof(host)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
/*
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ** !! commented out previous 'RIO_VERSID' functionality !!
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- **
- case RIO_VERSID:
- **
- ** Enquire about the release and version.
- ** We return MAX_VERSION_LEN bytes, being a textual null
- ** terminated string.
- **
- rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID\n"));
- if (copyout((caddr_t)RIOVersid(),
- (int)arg, MAX_VERSION_LEN ) == COPYFAIL ) {
- rio_dprint(RIO_DEBUG_CTRL, ("RIO_VERSID: Bad copy to user space\n",Host));
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
- **
- ** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- */
-
- case RIO_NUM_HOSTS:
- /*
- ** Enquire as to the number of hosts located
- ** at init time.
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
- if (copyout((caddr_t)&p->RIONumHosts, (int)arg,
- sizeof(p->RIONumHosts) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_FOAD:
- /*
- ** Kill host. This may not be in the final version...
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD %d\n", (int)arg);
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- p->RIOHalted = 1;
- p->RIOSystemUp = 0;
-
- for ( Host=0; Host<p->RIONumHosts; Host++ ) {
- (void)RIOBoardTest( p->RIOHosts[Host].PaddrP,
- p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type,
- p->RIOHosts[Host].Slot );
- bzero( (caddr_t)&p->RIOHosts[Host].Flags,
- ((int)&p->RIOHosts[Host].____end_marker____) -
- ((int)&p->RIOHosts[Host].Flags) );
- p->RIOHosts[Host].Flags = RC_WAITING;
-#if 0
- RIOSetupDataStructs(p);
-#endif
- }
- RIOFoadWakeup(p);
- p->RIONumBootPkts = 0;
- p->RIOBooting = 0;
-
-#ifdef RINGBUFFER_SUPPORT
- for( loop=0; loop<RIO_PORTS; loop++ )
- if ( p->RIOPortp[loop]->TxRingBuffer )
- sysfree((void *)p->RIOPortp[loop]->TxRingBuffer,
- RIOBufferSize );
-#endif
-#if 0
- bzero((caddr_t)&p->RIOPortp[0],RIO_PORTS*sizeof(struct Port));
-#else
- printk ("HEEEEELP!\n");
-#endif
-
- for( loop=0; loop<RIO_PORTS; loop++ ) {
-#if 0
- p->RIOPortp[loop]->TtyP = &p->channel[loop];
-#endif
-
- spin_lock_init(&p->RIOPortp[loop]->portSem);
- p->RIOPortp[loop]->InUse = NOT_INUSE;
- }
-
- p->RIOSystemUp = 0;
- return retval;
-
- case RIO_DOWNLOAD:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
- if ( !su ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
- p->RIOError.Error = NOT_SUPER_USER;
- return -EPERM;
- }
- if ( copyin((int)arg, (caddr_t)&DownLoad,
- sizeof(DownLoad) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n",
- DownLoad.ProductCode);
-
- /*
- ** It is important that the product code is an unsigned object!
- */
- if ( DownLoad.ProductCode > MAX_PRODUCT ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n",
- DownLoad.ProductCode);
- p->RIOError.Error = NO_SUCH_PRODUCT;
- return -ENXIO;
- }
- /*
- ** do something!
- */
- retval = (*(RIOBootTable[DownLoad.ProductCode]))(p, &DownLoad);
- /* <-- Panic */
- p->RIOHalted = 0;
- /*
- ** and go back, content with a job well completed.
- */
- return retval;
-
- case RIO_PARMS:
- {
- uint host;
-
- if (copyin((int)arg, (caddr_t)&host,
- sizeof(host) ) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL,
- "RIO_HOST_REQ: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- /*
- ** Fetch the parmmap
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS\n");
- if ( copyout( (caddr_t)p->RIOHosts[host].ParmMapP,
- (int)arg, sizeof(PARM_MAP) )==COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
- return -EFAULT;
- }
- }
- return retval;
-
- case RIO_HOST_REQ:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
- if (copyin((int)arg, (caddr_t)&HostReq,
- sizeof(HostReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( HostReq.HostNum >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n",
- HostReq.HostNum);
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
-
- if (copyout((caddr_t)&p->RIOHosts[HostReq.HostNum],
- (int)HostReq.HostP,sizeof(struct Host) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_DPRAM:
- rio_dprintk (RIO_DEBUG_CTRL, "Request for DPRAM\n");
- if ( copyin( (int)arg, (caddr_t)&HostDpRam,
- sizeof(HostDpRam) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( HostDpRam.HostNum >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n",
- HostDpRam.HostNum);
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
-
- if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
- int off;
- /* It's hardware like this that really gets on my tits. */
- static unsigned char copy[sizeof(struct DpRam)];
- for ( off=0; off<sizeof(struct DpRam); off++ )
- copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
- if ( copyout( (caddr_t)copy, (int)HostDpRam.DpRamP,
- sizeof(struct DpRam) ) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
- return -EFAULT;
- }
- }
- else if (copyout((caddr_t)p->RIOHosts[HostDpRam.HostNum].Caddr,
- (int)HostDpRam.DpRamP,
- sizeof(struct DpRam) ) == COPYFAIL ) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_SET_BUSY:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
- if ( (int)arg < 0 || (int)arg > 511 ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n",(int)arg);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- p->RIOPortp[(int)arg]->State |= RIO_BUSY;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_HOST_PORT:
- /*
- ** The daemon want port information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
- if ( copyin((int)arg, (caddr_t)&PortReq,
- sizeof(PortReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
-
- if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n",
- PortReq.SysPort);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
- if (copyout((caddr_t)p->RIOPortp[PortReq.SysPort],
- (int)PortReq.PortP,
- sizeof(struct Port) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_RUP:
- /*
- ** The daemon want rup information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
- if (copyin((int)arg, (caddr_t)&RupReq,
- sizeof(RupReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n",
- RupReq.HostNum);
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- if ( RupReq.RupNum >= MAX_RUP+LINKS_PER_UNIT ) { /* eek! */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n",
- RupReq.RupNum);
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- HostP = &p->RIOHosts[RupReq.HostNum];
-
- if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n",
- RupReq.HostNum);
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for rup %d from host %d\n",
- RupReq.RupNum,RupReq.HostNum);
-
- if (copyout((caddr_t)HostP->UnixRups[RupReq.RupNum].RupP,
- (int)RupReq.RupP,sizeof(struct RUP) ) == COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
- return -EFAULT;
- }
- return retval;
-
- case RIO_HOST_LPB:
- /*
- ** The daemon want lpb information
- ** (probably for debug reasons)
- */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
- if (copyin((int)arg, (caddr_t)&LpbReq,
- sizeof(LpbReq) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n",
- LpbReq.Host);
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
- if ( LpbReq.Link >= LINKS_PER_UNIT ) { /* eek! */
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n",
- LpbReq.Link);
- p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- HostP = &p->RIOHosts[LpbReq.Host];
-
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n",
- LpbReq.Host );
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -EIO;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n",
- LpbReq.Link, LpbReq.Host);
-
- if (copyout((caddr_t)&HostP->LinkStrP[LpbReq.Link],
- (int)LpbReq.LpbP,sizeof(struct LPB) ) == COPYFAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return retval;
-
- /*
- ** Here 3 IOCTL's that allow us to change the way in which
- ** rio logs errors. send them just to syslog or send them
- ** to both syslog and console or send them to just the console.
- **
- ** See RioStrBuf() in util.c for the other half.
- */
- case RIO_SYSLOG_ONLY:
- p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */
- return 0;
-
- case RIO_SYSLOG_CONS:
- p->RIOPrintLogState = PRINT_TO_LOG_CONS;/* syslog and console */
- return 0;
-
- case RIO_CONS_ONLY:
- p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */
- return 0;
-
- case RIO_SIGNALS_ON:
- if ( p->RIOSignalProcess ) {
- p->RIOError.Error = SIGNALS_ALREADY_SET;
- return -EBUSY;
- }
- p->RIOSignalProcess = getpid();
- p->RIOPrintDisabled = DONT_PRINT;
- return retval;
-
- case RIO_SIGNALS_OFF:
- if ( p->RIOSignalProcess != getpid() ) {
- p->RIOError.Error = NOT_RECEIVING_PROCESS;
- return -EPERM;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "Clear signal process to zero\n");
- p->RIOSignalProcess = 0;
- return retval;
-
- case RIO_SET_BYTE_MODE:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
- return retval;
-
- case RIO_SET_WORD_MODE:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode |= WORD_OPERATION;
- return retval;
-
- case RIO_SET_FAST_BUS:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode |= FAST_AT_BUS;
- return retval;
-
- case RIO_SET_SLOW_BUS:
- for ( Host=0; Host<p->RIONumHosts; Host++ )
- if ( p->RIOHosts[Host].Type == RIO_AT )
- p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
- return retval;
-
- case RIO_MAP_B50_TO_50:
- case RIO_MAP_B50_TO_57600:
- case RIO_MAP_B110_TO_110:
- case RIO_MAP_B110_TO_115200:
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping\n");
- port = (uint) arg;
- if ( port < 0 || port > 511 ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- switch( cmd )
- {
- case RIO_MAP_B50_TO_50 :
- p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
- break;
- case RIO_MAP_B50_TO_57600 :
- p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
- break;
- case RIO_MAP_B110_TO_110 :
- p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
- break;
- case RIO_MAP_B110_TO_115200 :
- p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
- break;
- }
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_STREAM_INFO:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
- return -EINVAL;
-
- case RIO_SEND_PACKET:
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
- if ( copyin( (int)arg, (caddr_t)&SendPack,
- sizeof(SendPack) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- if ( SendPack.PortNum >= 128 ) {
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -ENXIO;
- }
-
- PortP = p->RIOPortp[SendPack.PortNum];
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if ( !can_add_transmit(&PacketP,PortP) ) {
- p->RIOError.Error = UNIT_IS_IN_USE;
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -ENOSPC;
- }
-
- for ( loop=0; loop<(ushort)(SendPack.Len & 127); loop++ )
- WBYTE(PacketP->data[loop], SendPack.Data[loop] );
-
- WBYTE(PacketP->len, SendPack.Len);
-
- add_transmit( PortP );
- /*
- ** Count characters transmitted for port statistics reporting
- */
- if (PortP->statsGather)
- PortP->txchars += (SendPack.Len & 127);
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return retval;
-
- case RIO_NO_MESG:
- if ( su )
- p->RIONoMessage = 1;
- return su ? 0 : -EPERM;
-
- case RIO_MESG:
- if ( su )
- p->RIONoMessage = 0;
- return su ? 0 : -EPERM;
-
- case RIO_WHAT_MESG:
- if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg,
- sizeof(p->RIONoMessage) )==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_MEM_DUMP :
- if (copyin((int)arg, (caddr_t)&SubCmd,
- sizeof(struct SubCmdStruct)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n",
- SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
-
- if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Host >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- port = p->RIOHosts[SubCmd.Host].
- UnixRups[SubCmd.Rup].BaseSysPort;
-
- PortP = p->RIOPortp[port];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if ( RIOPreemptiveCmd(p, PortP, MEMDUMP ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -EBUSY;
- }
- else
- PortP->State |= RIO_BUSY;
-
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- if ( copyout( (caddr_t)p->RIOMemDump, (int)arg,
- MEMDUMP_SIZE) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_TICK:
- if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
- return -EINVAL;
- rio_dprintk (RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int)arg);
- WBYTE(p->RIOHosts[(int)arg].SetInt , 0xff);
- return 0;
-
- case RIO_TOCK:
- if ((int)arg < 0 || (int)arg >= p->RIONumHosts)
- return -EINVAL;
- rio_dprintk (RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int)arg);
- WBYTE((p->RIOHosts[(int)arg].ResetInt) , 0xff);
- return 0;
-
- case RIO_READ_CHECK:
- /* Check reads for pkts with data[0] the same */
- p->RIOReadCheck = !p->RIOReadCheck;
- if (copyout((caddr_t)&p->RIOReadCheck,(int)arg,
- sizeof(uint))== COPYFAIL) {
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
-
- case RIO_READ_REGISTER :
- if (copyin((int)arg, (caddr_t)&SubCmd,
- sizeof(struct SubCmdStruct)) == COPYFAIL) {
- p->RIOError.Error = COPYIN_FAILED;
- return -EFAULT;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n",
- SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
-
- if (SubCmd.Port > 511) {
- rio_dprintk (RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n",
- SubCmd.Port);
- p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Rup >= MAX_RUP+LINKS_PER_UNIT ) {
- p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- if (SubCmd.Host >= p->RIONumHosts ) {
- p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- port = p->RIOHosts[SubCmd.Host].
- UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
- PortP = p->RIOPortp[port];
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- return -EBUSY;
- }
- else
- PortP->State |= RIO_BUSY;
-
- rio_spin_unlock_irqrestore( &PortP->portSem , flags);
- if (copyout((caddr_t)&p->CdRegister, (int)arg,
- sizeof(uint)) == COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
- p->RIOError.Error = COPYOUT_FAILED;
- return -EFAULT;
- }
- return 0;
- /*
- ** rio_make_dev: given port number (0-511) ORed with port type
- ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
- ** value to pass to mknod to create the correct device node.
- */
- case RIO_MAKE_DEV:
- {
- uint port = (uint)arg & RIO_MODEM_MASK;
-
- switch ( (uint)arg & RIO_DEV_MASK ) {
- case RIO_DEV_DIRECT:
- arg = (caddr_t)drv_makedev(MAJOR(dev), port);
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- case RIO_DEV_MODEM:
- arg = (caddr_t)drv_makedev(MAJOR(dev), (port|RIO_MODEM_BIT) );
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- case RIO_DEV_XPRINT:
- arg = (caddr_t)drv_makedev(MAJOR(dev), port);
- rio_dprintk (RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n",port, (int)arg);
- return (int)arg;
- }
- rio_dprintk (RIO_DEBUG_CTRL, "MAKE Device is called\n");
- return -EINVAL;
- }
- /*
- ** rio_minor: given a dev_t from a stat() call, return
- ** the port number (0-511) ORed with the port type
- ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
- */
- case RIO_MINOR:
- {
- dev_t dv;
- int mino;
-
- dv = (dev_t)((int)arg);
- mino = RIO_UNMODEM(dv);
+ ** Fetch the parmmap
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
+ if (copyout((caddr_t) p->RIOHosts[host].ParmMapP, (int) arg, sizeof(PARM_MAP)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
+ return -EFAULT;
+ }
+ }
+ return retval;
+
+ case RIO_HOST_REQ:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
+ if (copyin((int) arg, (caddr_t) & HostReq, sizeof(HostReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (HostReq.HostNum >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
+
+ if (copyout((caddr_t) & p->RIOHosts[HostReq.HostNum], (int) HostReq.HostP, sizeof(struct Host)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_DPRAM:
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
+ if (copyin((int) arg, (caddr_t) & HostDpRam, sizeof(HostDpRam)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (HostDpRam.HostNum >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
+
+ if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
+ int off;
+ /* It's hardware like this that really gets on my tits. */
+ static unsigned char copy[sizeof(struct DpRam)];
+ for (off = 0; off < sizeof(struct DpRam); off++)
+ copy[off] = p->RIOHosts[HostDpRam.HostNum].Caddr[off];
+ if (copyout((caddr_t) copy, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ } else if (copyout((caddr_t) p->RIOHosts[HostDpRam.HostNum].Caddr, (int) HostDpRam.DpRamP, sizeof(struct DpRam)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_SET_BUSY:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
+ if ((int) arg < 0 || (int) arg > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %d\n", (int) arg);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ p->RIOPortp[(int) arg]->State |= RIO_BUSY;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_HOST_PORT:
+ /*
+ ** The daemon want port information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
+ if (copyin((int) arg, (caddr_t) & PortReq, sizeof(PortReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+
+ if (PortReq.SysPort >= RIO_PORTS) { /* SysPort is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
+ if (copyout((caddr_t) p->RIOPortp[PortReq.SysPort], (int) PortReq.PortP, sizeof(struct Port)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_RUP:
+ /*
+ ** The daemon want rup information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
+ if (copyin((int) arg, (caddr_t) & RupReq, sizeof(RupReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (RupReq.HostNum >= p->RIONumHosts) { /* host is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) { /* eek! */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ HostP = &p->RIOHosts[RupReq.HostNum];
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
+
+ if (copyout((caddr_t) HostP->UnixRups[RupReq.RupNum].RupP, (int) RupReq.RupP, sizeof(struct RUP)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
+ return -EFAULT;
+ }
+ return retval;
+
+ case RIO_HOST_LPB:
+ /*
+ ** The daemon want lpb information
+ ** (probably for debug reasons)
+ */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
+ if (copyin((int) arg, (caddr_t) & LpbReq, sizeof(LpbReq)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (LpbReq.Host >= p->RIONumHosts) { /* host is unsigned */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+ if (LpbReq.Link >= LINKS_PER_UNIT) { /* eek! */
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
+ p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ HostP = &p->RIOHosts[LpbReq.Host];
+
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -EIO;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
+
+ if (copyout((caddr_t) & HostP->LinkStrP[LpbReq.Link], (int) LpbReq.LpbP, sizeof(struct LPB)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return retval;
- if ( RIO_ISMODEM(dv) ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
- arg = (caddr_t)(mino | RIO_DEV_MODEM);
- }
- else {
- rio_dprintk (RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
- arg = (caddr_t)(mino | RIO_DEV_DIRECT);
- }
- return (int)arg;
- }
+ /*
+ ** Here 3 IOCTL's that allow us to change the way in which
+ ** rio logs errors. send them just to syslog or send them
+ ** to both syslog and console or send them to just the console.
+ **
+ ** See RioStrBuf() in util.c for the other half.
+ */
+ case RIO_SYSLOG_ONLY:
+ p->RIOPrintLogState = PRINT_TO_LOG; /* Just syslog */
+ return 0;
+
+ case RIO_SYSLOG_CONS:
+ p->RIOPrintLogState = PRINT_TO_LOG_CONS; /* syslog and console */
+ return 0;
+
+ case RIO_CONS_ONLY:
+ p->RIOPrintLogState = PRINT_TO_CONS; /* Just console */
+ return 0;
+
+ case RIO_SIGNALS_ON:
+ if (p->RIOSignalProcess) {
+ p->RIOError.Error = SIGNALS_ALREADY_SET;
+ return -EBUSY;
+ }
+ p->RIOSignalProcess = getpid();
+ p->RIOPrintDisabled = DONT_PRINT;
+ return retval;
+
+ case RIO_SIGNALS_OFF:
+ if (p->RIOSignalProcess != getpid()) {
+ p->RIOError.Error = NOT_RECEIVING_PROCESS;
+ return -EPERM;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
+ p->RIOSignalProcess = 0;
+ return retval;
+
+ case RIO_SET_BYTE_MODE:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
+ return retval;
+
+ case RIO_SET_WORD_MODE:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode |= WORD_OPERATION;
+ return retval;
+
+ case RIO_SET_FAST_BUS:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode |= FAST_AT_BUS;
+ return retval;
+
+ case RIO_SET_SLOW_BUS:
+ for (Host = 0; Host < p->RIONumHosts; Host++)
+ if (p->RIOHosts[Host].Type == RIO_AT)
+ p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
+ return retval;
+
+ case RIO_MAP_B50_TO_50:
+ case RIO_MAP_B50_TO_57600:
+ case RIO_MAP_B110_TO_110:
+ case RIO_MAP_B110_TO_115200:
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
+ port = (uint) arg;
+ if (port < 0 || port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ switch (cmd) {
+ case RIO_MAP_B50_TO_50:
+ p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
+ break;
+ case RIO_MAP_B50_TO_57600:
+ p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
+ break;
+ case RIO_MAP_B110_TO_110:
+ p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
+ break;
+ case RIO_MAP_B110_TO_115200:
+ p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
+ break;
+ }
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_STREAM_INFO:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
+ return -EINVAL;
+
+ case RIO_SEND_PACKET:
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
+ if (copyin((int) arg, (caddr_t) & SendPack, sizeof(SendPack)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ if (SendPack.PortNum >= 128) {
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -ENXIO;
+ }
+
+ PortP = p->RIOPortp[SendPack.PortNum];
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (!can_add_transmit(&PacketP, PortP)) {
+ p->RIOError.Error = UNIT_IS_IN_USE;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -ENOSPC;
+ }
+
+ for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
+ WBYTE(PacketP->data[loop], SendPack.Data[loop]);
+
+ WBYTE(PacketP->len, SendPack.Len);
+
+ add_transmit(PortP);
+ /*
+ ** Count characters transmitted for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += (SendPack.Len & 127);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return retval;
+
+ case RIO_NO_MESG:
+ if (su)
+ p->RIONoMessage = 1;
+ return su ? 0 : -EPERM;
+
+ case RIO_MESG:
+ if (su)
+ p->RIONoMessage = 0;
+ return su ? 0 : -EPERM;
+
+ case RIO_WHAT_MESG:
+ if (copyout((caddr_t) & p->RIONoMessage, (int) arg, sizeof(p->RIONoMessage)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_MEM_DUMP:
+ if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
+
+ if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Host >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
+
+ PortP = p->RIOPortp[port];
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else
+ PortP->State |= RIO_BUSY;
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (copyout((caddr_t) p->RIOMemDump, (int) arg, MEMDUMP_SIZE) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_TICK:
+ if ((int) arg < 0 || (int) arg >= p->RIONumHosts)
+ return -EINVAL;
+ rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %d\n", (int) arg);
+ WBYTE(p->RIOHosts[(int) arg].SetInt, 0xff);
+ return 0;
+
+ case RIO_TOCK:
+ if ((int) arg < 0 || (int) arg >= p->RIONumHosts)
+ return -EINVAL;
+ rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %d\n", (int) arg);
+ WBYTE((p->RIOHosts[(int) arg].ResetInt), 0xff);
+ return 0;
+
+ case RIO_READ_CHECK:
+ /* Check reads for pkts with data[0] the same */
+ p->RIOReadCheck = !p->RIOReadCheck;
+ if (copyout((caddr_t) & p->RIOReadCheck, (int) arg, sizeof(uint)) == COPYFAIL) {
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+
+ case RIO_READ_REGISTER:
+ if (copyin((int) arg, (caddr_t) & SubCmd, sizeof(struct SubCmdStruct)) == COPYFAIL) {
+ p->RIOError.Error = COPYIN_FAILED;
+ return -EFAULT;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
+
+ if (SubCmd.Port > 511) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
+ p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+ p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ if (SubCmd.Host >= p->RIONumHosts) {
+ p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
+ PortP = p->RIOPortp[port];
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ return -EBUSY;
+ } else
+ PortP->State |= RIO_BUSY;
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (copyout((caddr_t) & p->CdRegister, (int) arg, sizeof(uint)) == COPYFAIL) {
+ rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
+ p->RIOError.Error = COPYOUT_FAILED;
+ return -EFAULT;
+ }
+ return 0;
+ /*
+ ** rio_make_dev: given port number (0-511) ORed with port type
+ ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
+ ** value to pass to mknod to create the correct device node.
+ */
+ case RIO_MAKE_DEV:
+ {
+ uint port = (uint) arg & RIO_MODEM_MASK;
+
+ switch ((uint) arg & RIO_DEV_MASK) {
+ case RIO_DEV_DIRECT:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), port);
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ case RIO_DEV_MODEM:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ case RIO_DEV_XPRINT:
+ arg = (caddr_t) drv_makedev(MAJOR(dev), port);
+ rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, (int) arg);
+ return (int) arg;
+ }
+ rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
+ return -EINVAL;
+ }
+ /*
+ ** rio_minor: given a dev_t from a stat() call, return
+ ** the port number (0-511) ORed with the port type
+ ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
+ */
+ case RIO_MINOR:
+ {
+ dev_t dv;
+ int mino;
+
+ dv = (dev_t) ((int) arg);
+ mino = RIO_UNMODEM(dv);
+
+ if (RIO_ISMODEM(dv)) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
+ arg = (caddr_t) (mino | RIO_DEV_MODEM);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
+ arg = (caddr_t) (mino | RIO_DEV_DIRECT);
+ }
+ return (int) arg;
+ }
}
- rio_dprintk (RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n",cmd);
+ rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
- func_exit ();
+ func_exit();
return -EINVAL;
}
/*
** Pre-emptive commands go on RUPs and are only one byte long.
*/
-int
-RIOPreemptiveCmd(p, PortP, Cmd)
-struct rio_info * p;
+int RIOPreemptiveCmd(p, PortP, Cmd)
+struct rio_info *p;
struct Port *PortP;
uchar Cmd;
{
@@ -1765,105 +1548,96 @@ uchar Cmd;
ushort rup;
int port;
-#ifdef CHECK
- CheckPortP( PortP );
-#endif
-
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
return RIO_FAIL;
}
- if (((int)((char)PortP->InUse) == -1) || ! (CmdBlkP = RIOGetCmdBlk()) ) {
- rio_dprintk (RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n",
- Cmd, PortP->PortNum);
+ if (((int) ((char) PortP->InUse) == -1) || !(CmdBlkP = RIOGetCmdBlk())) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block for command %d on port %d\n", Cmd, PortP->PortNum);
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n",
- (int)CmdBlkP,PortP->InUse);
+ rio_dprintk(RIO_DEBUG_CTRL, "Command blk 0x%x - InUse now %d\n", (int) CmdBlkP, PortP->InUse);
- PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
+ PktCmdP = (struct PktCmd_M *) &CmdBlkP->Packet.data[0];
- CmdBlkP->Packet.src_unit = 0;
+ CmdBlkP->Packet.src_unit = 0;
if (PortP->SecondBlock)
rup = PortP->ID2;
else
rup = PortP->RupNum;
CmdBlkP->Packet.dest_unit = rup;
- CmdBlkP->Packet.src_port = COMMAND_RUP;
+ CmdBlkP->Packet.src_port = COMMAND_RUP;
CmdBlkP->Packet.dest_port = COMMAND_RUP;
- CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
- CmdBlkP->PostFuncP = RIOUnUse;
- CmdBlkP->PostArg = (int)PortP;
- PktCmdP->Command = Cmd;
- port = PortP->HostPort % (ushort)PORTS_PER_RTA;
+ CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
+ CmdBlkP->PostFuncP = RIOUnUse;
+ CmdBlkP->PostArg = (int) PortP;
+ PktCmdP->Command = Cmd;
+ port = PortP->HostPort % (ushort) PORTS_PER_RTA;
/*
- ** Index ports 8-15 for 2nd block of 16 port RTA.
- */
+ ** Index ports 8-15 for 2nd block of 16 port RTA.
+ */
if (PortP->SecondBlock)
port += (ushort) PORTS_PER_RTA;
- PktCmdP->PhbNum = port;
-
- switch ( Cmd ) {
- case MEMDUMP:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n",
- (int)CmdBlkP, (int)SubCmd.Addr);
- PktCmdP->SubCommand = MEMDUMP;
- PktCmdP->SubAddr = SubCmd.Addr;
- break;
- case FCLOSE:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n",(int)CmdBlkP);
- break;
- case READ_REGISTER:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n",
- (int)SubCmd.Addr, (int)CmdBlkP);
- PktCmdP->SubCommand = READ_REGISTER;
- PktCmdP->SubAddr = SubCmd.Addr;
- break;
- case RESUME:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n",(int)CmdBlkP);
- break;
- case RFLUSH:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n",(int)CmdBlkP);
- CmdBlkP->PostFuncP = RIORFlushEnable;
- break;
- case SUSPEND:
- rio_dprintk (RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n",(int)CmdBlkP);
- break;
-
- case MGET :
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int)CmdBlkP);
- break;
-
- case MSET :
- case MBIC :
- case MBIS :
- CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
- rio_dprintk (RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int)CmdBlkP);
- break;
-
- case WFLUSH:
- /*
- ** If we have queued up the maximum number of Write flushes
- ** allowed then we should not bother sending any more to the
- ** RTA.
- */
- if ((int)((char)PortP->WflushFlag) == (int)-1) {
- rio_dprintk (RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
- RIOFreeCmdBlk(CmdBlkP);
- return(RIO_FAIL);
- } else {
- rio_dprintk (RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n",
- (int)CmdBlkP);
- CmdBlkP->PostFuncP = RIOWFlushMark;
- }
- break;
+ PktCmdP->PhbNum = port;
+
+ switch (Cmd) {
+ case MEMDUMP:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk 0x%x (addr 0x%x)\n", (int) CmdBlkP, (int) SubCmd.Addr);
+ PktCmdP->SubCommand = MEMDUMP;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+ case FCLOSE:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk 0x%x\n", (int) CmdBlkP);
+ break;
+ case READ_REGISTER:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) command blk 0x%x\n", (int) SubCmd.Addr, (int) CmdBlkP);
+ PktCmdP->SubCommand = READ_REGISTER;
+ PktCmdP->SubAddr = SubCmd.Addr;
+ break;
+ case RESUME:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk 0x%x\n", (int) CmdBlkP);
+ break;
+ case RFLUSH:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk 0x%x\n", (int) CmdBlkP);
+ CmdBlkP->PostFuncP = RIORFlushEnable;
+ break;
+ case SUSPEND:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case MGET:
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case MSET:
+ case MBIC:
+ case MBIS:
+ CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command blk 0x%x\n", (int) CmdBlkP);
+ break;
+
+ case WFLUSH:
+ /*
+ ** If we have queued up the maximum number of Write flushes
+ ** allowed then we should not bother sending any more to the
+ ** RTA.
+ */
+ if ((int) ((char) PortP->WflushFlag) == (int) -1) {
+ rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, WflushFlag about to wrap!");
+ RIOFreeCmdBlk(CmdBlkP);
+ return (RIO_FAIL);
+ } else {
+ rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command blk 0x%x\n", (int) CmdBlkP);
+ CmdBlkP->PostFuncP = RIOWFlushMark;
+ }
+ break;
}
PortP->InUse++;
- Ret = RIOQueueCmdBlk( PortP->HostP, rup, CmdBlkP );
+ Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
return Ret;
}
diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h
index bc38ac5dfbde..663ee0914ed7 100644
--- a/drivers/char/rio/riodrvr.h
+++ b/drivers/char/rio/riodrvr.h
@@ -33,7 +33,7 @@
#ifndef __riodrvr_h
#define __riodrvr_h
-#include <asm/param.h> /* for HZ */
+#include <asm/param.h> /* for HZ */
#ifdef SCCS_LABELS
static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3";
@@ -44,15 +44,15 @@ static char *_riodrvr_h_sccs_ = "@(#)riodrvr.h 1.3";
struct rio_info {
- int mode; /* Intr or polled, word/byte */
- spinlock_t RIOIntrSem; /* Interrupt thread sem */
- int current_chan; /* current channel */
- int RIOFailed; /* Not initialised ? */
- int RIOInstallAttempts; /* no. of rio-install() calls */
- int RIOLastPCISearch; /* status of last search */
- int RIONumHosts; /* Number of RIO Hosts */
- struct Host * RIOHosts; /* RIO Host values */
- struct Port **RIOPortp; /* RIO port values */
+ int mode; /* Intr or polled, word/byte */
+ spinlock_t RIOIntrSem; /* Interrupt thread sem */
+ int current_chan; /* current channel */
+ int RIOFailed; /* Not initialised ? */
+ int RIOInstallAttempts; /* no. of rio-install() calls */
+ int RIOLastPCISearch; /* status of last search */
+ int RIONumHosts; /* Number of RIO Hosts */
+ struct Host *RIOHosts; /* RIO Host values */
+ struct Port **RIOPortp; /* RIO port values */
/*
** 02.03.1999 ARG - ESIL 0820 fix
** We no longer use RIOBootMode
@@ -60,9 +60,9 @@ struct rio_info {
int RIOBootMode; * RIO boot mode *
**
*/
- int RIOPrintDisabled; /* RIO printing disabled ? */
- int RIOPrintLogState; /* RIO printing state ? */
- int RIOPolling; /* Polling ? */
+ int RIOPrintDisabled; /* RIO printing disabled ? */
+ int RIOPrintLogState; /* RIO printing state ? */
+ int RIOPolling; /* Polling ? */
/*
** 09.12.1998 ARG - ESIL 0776 part fix
** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
@@ -70,61 +70,61 @@ struct rio_info {
** updated in RIOConCon() - to keep track of RTA connections/disconnections.
** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
*/
- int RIOHalted; /* halted ? */
- int RIORtaDisCons; /* RTA connections/disconnections */
- uint RIOReadCheck; /* Rio read check */
- uint RIONoMessage; /* To display message or not */
- uint RIONumBootPkts; /* how many packets for an RTA */
- uint RIOBootCount; /* size of RTA code */
- uint RIOBooting; /* count of outstanding boots */
- uint RIOSystemUp; /* Booted ?? */
- uint RIOCounting; /* for counting interrupts */
- uint RIOIntCount; /* # of intr since last check */
- uint RIOTxCount; /* number of xmit intrs */
- uint RIORxCount; /* number of rx intrs */
- uint RIORupCount; /* number of rup intrs */
- int RIXTimer;
- int RIOBufferSize; /* Buffersize */
- int RIOBufferMask; /* Buffersize */
-
- int RIOFirstMajor; /* First host card's major no */
-
- uint RIOLastPortsMapped; /* highest port number known */
- uint RIOFirstPortsMapped; /* lowest port number known */
-
- uint RIOLastPortsBooted; /* highest port number running */
- uint RIOFirstPortsBooted; /* lowest port number running */
-
- uint RIOLastPortsOpened; /* highest port number running */
- uint RIOFirstPortsOpened; /* lowest port number running */
+ int RIOHalted; /* halted ? */
+ int RIORtaDisCons; /* RTA connections/disconnections */
+ uint RIOReadCheck; /* Rio read check */
+ uint RIONoMessage; /* To display message or not */
+ uint RIONumBootPkts; /* how many packets for an RTA */
+ uint RIOBootCount; /* size of RTA code */
+ uint RIOBooting; /* count of outstanding boots */
+ uint RIOSystemUp; /* Booted ?? */
+ uint RIOCounting; /* for counting interrupts */
+ uint RIOIntCount; /* # of intr since last check */
+ uint RIOTxCount; /* number of xmit intrs */
+ uint RIORxCount; /* number of rx intrs */
+ uint RIORupCount; /* number of rup intrs */
+ int RIXTimer;
+ int RIOBufferSize; /* Buffersize */
+ int RIOBufferMask; /* Buffersize */
+
+ int RIOFirstMajor; /* First host card's major no */
+
+ uint RIOLastPortsMapped; /* highest port number known */
+ uint RIOFirstPortsMapped; /* lowest port number known */
+
+ uint RIOLastPortsBooted; /* highest port number running */
+ uint RIOFirstPortsBooted; /* lowest port number running */
+
+ uint RIOLastPortsOpened; /* highest port number running */
+ uint RIOFirstPortsOpened; /* lowest port number running */
/* Flag to say that the topology information has been changed. */
- uint RIOQuickCheck;
- uint CdRegister; /* ??? */
- int RIOSignalProcess; /* Signalling process */
- int rio_debug; /* To debug ... */
- int RIODebugWait; /* For what ??? */
- int tpri; /* Thread prio */
- int tid; /* Thread id */
- uint _RIO_Polled; /* Counter for polling */
- uint _RIO_Interrupted; /* Counter for interrupt */
- int intr_tid; /* iointset return value */
- int TxEnSem; /* TxEnable Semaphore */
-
-
- struct Error RIOError; /* to Identify what went wrong */
- struct Conf RIOConf; /* Configuration ??? */
- struct ttystatics channel[RIO_PORTS]; /* channel information */
- char RIOBootPackets[1+(SIXTY_FOUR_K/RTA_BOOT_DATA_SIZE)]
- [RTA_BOOT_DATA_SIZE];
- struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
- struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
+ uint RIOQuickCheck;
+ uint CdRegister; /* ??? */
+ int RIOSignalProcess; /* Signalling process */
+ int rio_debug; /* To debug ... */
+ int RIODebugWait; /* For what ??? */
+ int tpri; /* Thread prio */
+ int tid; /* Thread id */
+ uint _RIO_Polled; /* Counter for polling */
+ uint _RIO_Interrupted; /* Counter for interrupt */
+ int intr_tid; /* iointset return value */
+ int TxEnSem; /* TxEnable Semaphore */
+
+
+ struct Error RIOError; /* to Identify what went wrong */
+ struct Conf RIOConf; /* Configuration ??? */
+ struct ttystatics channel[RIO_PORTS]; /* channel information */
+ char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
+ [RTA_BOOT_DATA_SIZE];
+ struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
+ struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
/* RTA to host binding table for master/slave operation */
- ulong RIOBindTab[MAX_RTA_BINDINGS];
+ ulong RIOBindTab[MAX_RTA_BINDINGS];
/* RTA memory dump variable */
- uchar RIOMemDump[MEMDUMP_SIZE];
- struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
+ uchar RIOMemDump[MEMDUMP_SIZE];
+ struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
};
@@ -141,4 +141,4 @@ struct rio_info {
#define WRBYTE(x,y) *(volatile unsigned char *)((x)) = \
(unsigned char)(y)
-#endif /* __riodrvr.h */
+#endif /* __riodrvr.h */
diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h
index e08421c9558e..8de7966e603a 100644
--- a/drivers/char/rio/rioinfo.h
+++ b/drivers/char/rio/rioinfo.h
@@ -41,29 +41,29 @@ static char *_rioinfo_h_sccs_ = "@(#)rioinfo.h 1.2";
** Host card data structure
*/
struct RioHostInfo {
- long location; /* RIO Card Base I/O address */
- long vector; /* RIO Card IRQ vector */
- int bus; /* ISA/EISA/MCA/PCI */
- int mode; /* pointer to host mode - INTERRUPT / POLLED */
+ long location; /* RIO Card Base I/O address */
+ long vector; /* RIO Card IRQ vector */
+ int bus; /* ISA/EISA/MCA/PCI */
+ int mode; /* pointer to host mode - INTERRUPT / POLLED */
struct old_sgttyb
- * Sg; /* pointer to default term characteristics */
+ *Sg; /* pointer to default term characteristics */
};
/* Mode in rio device info */
-#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */
-#define POLLED_MODE 0x02 /* No interrupt */
-#define AUTO_MODE 0x03 /* Auto mode */
+#define INTERRUPTED_MODE 0x01 /* Interrupt is generated */
+#define POLLED_MODE 0x02 /* No interrupt */
+#define AUTO_MODE 0x03 /* Auto mode */
-#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */
-#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */
+#define WORD_ACCESS_MODE 0x10 /* Word Access Mode */
+#define BYTE_ACCESS_MODE 0x20 /* Byte Access Mode */
/* Bus type that RIO supports */
-#define ISA_BUS 0x01 /* The card is ISA */
-#define EISA_BUS 0x02 /* The card is EISA */
-#define MCA_BUS 0x04 /* The card is MCA */
-#define PCI_BUS 0x08 /* The card is PCI */
+#define ISA_BUS 0x01 /* The card is ISA */
+#define EISA_BUS 0x02 /* The card is EISA */
+#define MCA_BUS 0x04 /* The card is MCA */
+#define PCI_BUS 0x08 /* The card is PCI */
/*
** 11.11.1998 ARG - ESIL ???? part fix
@@ -93,4 +93,4 @@ struct RioHostInfo {
'V' - '@' /* literal next char */ \
}
-#endif /* __rioinfo_h */
+#endif /* __rioinfo_h */
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index 898a126ae3e6..0d44ef464e6b 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -87,222 +87,8 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
int RIOPCIinit(struct rio_info *p, int Mode);
-#if 0
-static void RIOAllocateInterrupts(struct rio_info *);
-static int RIOReport(struct rio_info *);
-static void RIOStopInterrupts(struct rio_info *, int, int);
-#endif
-
static int RIOScrub(int, BYTE *, int);
-#if 0
-extern int rio_intr();
-
-/*
-** Init time code.
-*/
-void
-rioinit( p, info )
-struct rio_info * p;
-struct RioHostInfo * info;
-{
- /*
- ** Multi-Host card support - taking the easy way out - sorry !
- ** We allocate and set up the Host and Port structs when the
- ** driver is called to 'install' the first host.
- ** We check for this first 'call' by testing the RIOPortp pointer.
- */
- if ( !p->RIOPortp )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Allocating and setting up driver data structures\n");
-
- RIOAllocDataStructs(p); /* allocate host/port structs */
- RIOSetupDataStructs(p); /* setup topology structs */
- }
-
- RIOInitHosts( p, info ); /* hunt down the hardware */
-
- RIOAllocateInterrupts(p); /* allocate interrupts */
- RIOReport(p); /* show what we found */
-}
-
-/*
-** Initialise the Cards
-*/
-void
-RIOInitHosts(p, info)
-struct rio_info * p;
-struct RioHostInfo * info;
-{
-/*
-** 15.10.1998 ARG - ESIL 0762 part fix
-** If there is no ISA card definition - we always look for PCI cards.
-** As we currently only support one host card this lets an ISA card
-** definition take precedence over PLUG and PLAY.
-** No ISA card - we are PLUG and PLAY with PCI.
-*/
-
- /*
- ** Note - for PCI both these will be zero, that's okay because
- ** RIOPCIInit() fills them in if a card is found.
- */
- p->RIOHosts[p->RIONumHosts].Ivec = info->vector;
- p->RIOHosts[p->RIONumHosts].PaddrP = info->location;
-
- /*
- ** Check that we are able to accommodate another host
- */
- if ( p->RIONumHosts >= RIO_HOSTS )
- {
- p->RIOFailed++;
- return;
- }
-
- if ( info->bus & ISA_BUS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (ISA)\n", p->RIONumHosts);
- RIOISAinit(p, p->mode);
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "initialising card %d (PCI)\n", p->RIONumHosts);
- RIOPCIinit(p, RIO_PCI_DEFAULT_MODE);
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Total hosts initialised so far : %d\n", p->RIONumHosts);
-
-
-#ifdef FUTURE_RELEASE
- if (p->bus & EISA_BUS)
- /* EISA card */
- RIOEISAinit(p, RIO_EISA_DEFAULT_MODE);
-
- if (p->bus & MCA_BUS)
- /* MCA card */
- RIOMCAinit(p, RIO_MCA_DEFAULT_MODE);
-#endif
-}
-
-/*
-** go through memory for an AT host that we pass in the device info
-** structure and initialise
-*/
-void
-RIOISAinit(p, mode)
-struct rio_info * p;
-int mode;
-{
-
- /* XXX Need to implement this. */
-#if 0
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char*)p->RIONumHosts);
-
- rio_dprintk (RIO_DEBUG_INIT, "Set interrupt handler, intr_tid = 0x%x\n", p->intr_tid );
-
- if (RIODoAT(p, p->RIOHosts[p->RIONumHosts].PaddrP, mode)) {
- return;
- }
- else {
- rio_dprintk (RIO_DEBUG_INIT, "RIODoAT failed\n");
- p->RIOFailed++;
- }
-#endif
-
-}
-
-/*
-** RIODoAT :
-**
-** Map in a boards physical address, check that the board is there,
-** test the board and if everything is okay assign the board an entry
-** in the Rio Hosts structure.
-*/
-int
-RIODoAT(p, Base, mode)
-struct rio_info * p;
-int Base;
-int mode;
-{
-#define FOUND 1
-#define NOT_FOUND 0
-
- caddr_t cardAddr;
-
- /*
- ** Check to see if we actually have a board at this physical address.
- */
- if ((cardAddr = RIOCheckForATCard(Base)) != 0) {
- /*
- ** Now test the board to see if it is working.
- */
- if (RIOBoardTest(Base, cardAddr, RIO_AT, 0) == RIO_SUCCESS) {
- /*
- ** Fill out a slot in the Rio host structure.
- */
- if (RIOAssignAT(p, Base, cardAddr, mode)) {
- return(FOUND);
- }
- }
- RIOMapout(Base, RIO_AT_MEM_SIZE, cardAddr);
- }
- return(NOT_FOUND);
-}
-
-caddr_t
-RIOCheckForATCard(Base)
-int Base;
-{
- int off;
- struct DpRam *cardp; /* (Points at the host) */
- caddr_t virtAddr;
- unsigned char RIOSigTab[24];
-/*
-** Table of values to search for as prom signature of a host card
-*/
- strcpy(RIOSigTab, "JBJGPGGHINSMJPJR");
-
- /*
- ** Hey! Yes, You reading this code! Yo, grab a load a this:
- **
- ** IF the card is using WORD MODE rather than BYTE MODE
- ** then it will occupy 128K of PHYSICAL memory area. So,
- ** you might think that the following Mapin is wrong. Well,
- ** it isn't, because the SECOND 64K of occupied space is an
- ** EXACT COPY of the FIRST 64K. (good?), so, we need only
- ** map it in in one 64K block.
- */
- if (RIOMapin(Base, RIO_AT_MEM_SIZE, &virtAddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't map the board in!\n");
- return((caddr_t)0);
- }
-
- /*
- ** virtAddr points to the DP ram of the system.
- ** We now cast this to a pointer to a RIO Host,
- ** and have a rummage about in the PROM.
- */
- cardp = (struct DpRam *)virtAddr;
-
- for (off=0; RIOSigTab[off]; off++) {
- if ((RBYTE(cardp->DpSignature[off]) & 0xFF) != RIOSigTab[off]) {
- /*
- ** Signature mismatch - card not at this address
- */
- RIOMapout(Base, RIO_AT_MEM_SIZE, virtAddr);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Couldn't match the signature 0x%x 0x%x!\n",
- (int)cardp, off);
- return((caddr_t)0);
- }
- }
-
- /*
- ** If we get here then we must have found a valid board so return
- ** its virtual address.
- */
- return(virtAddr);
-}
-#endif
/**
** RIOAssignAT :
@@ -367,667 +153,6 @@ int mode;
rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
return(1);
}
-#if 0
-#ifdef FUTURE_RELEASE
-int RIOMCAinit(int Mode)
-{
- uchar SlotNumber;
- caddr_t Caddr;
- uint Paddr;
- uint Ivec;
- int Handle;
- int ret = 0;
-
- /*
- ** Valid mode information for MCA cards
- ** is only FAST LINKS
- */
- Mode = (Mode & FAST_LINKS) ? McaTpFastLinks : McaTpSlowLinks;
- rio_dprintk (RIO_DEBUG_INIT, "RIOMCAinit(%d)\n",Mode);
-
-
- /*
- ** Check out each of the slots
- */
- for (SlotNumber = 0; SlotNumber < McaMaxSlots; SlotNumber++) {
- /*
- ** Enable the slot we want to talk to
- */
- outb( McaSlotSelect, SlotNumber | McaSlotEnable );
-
- /*
- ** Read the ID word from the slot
- */
- if (((inb(McaIdHigh)<< 8)|inb(McaIdLow)) == McaRIOId)
- {
- rio_dprintk (RIO_DEBUG_INIT, "Potential MCA card in slot %d\n", SlotNumber);
-
- /*
- ** Card appears to be a RIO MCA card!
- */
- RIOMachineType |= (1<<RIO_MCA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return(ret);
- }
-
- /*
- ** McaIrqEnable contains the interrupt vector, and a card
- ** enable bit.
- */
- Ivec = inb(McaIrqEnable);
-
- rio_dprintk (RIO_DEBUG_INIT, "Ivec is %x\n", Ivec);
-
- switch ( Ivec & McaIrqMask )
- {
- case McaIrq9:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ9\n");
- break;
- case McaIrq3:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ3\n");
- break;
- case McaIrq4:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ4\n");
- break;
- case McaIrq7:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ7\n");
- break;
- case McaIrq10:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ10\n");
- break;
- case McaIrq11:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ11\n");
- break;
- case McaIrq12:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ12\n");
- break;
- case McaIrq15:
- rio_dprintk (RIO_DEBUG_INIT, "IRQ15\n");
- break;
- }
-
- /*
- ** If the card enable bit isn't set, then set it!
- */
- if ((Ivec & McaCardEnable) != McaCardEnable) {
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable not set - setting!\n");
- outb(McaIrqEnable,Ivec|McaCardEnable);
- } else
- rio_dprintk (RIO_DEBUG_INIT, "McaCardEnable already set\n");
-
- /*
- ** Convert the IRQ enable mask into something useful
- */
- Ivec = RIOMcaToIvec[Ivec & McaIrqMask];
-
- /*
- ** Find the physical address
- */
- rio_dprintk (RIO_DEBUG_INIT, "inb(McaMemory) is %x\n", inb(McaMemory));
- Paddr = McaAddress(inb(McaMemory));
-
- rio_dprintk (RIO_DEBUG_INIT, "MCA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr != 0 )
- {
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- Handle = RIOMapin( Paddr, RIO_MCA_MEM_SIZE, &Caddr );
-
- if ( Handle == -1 ) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n", RIO_MCA_MEM_SIZE, Paddr;
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_MCA,SlotNumber ) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- SlotNumber, RIO_MCA, Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = SlotNumber;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_MCA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt , 0xff);
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
- RIOMapout(Paddr, RIO_MCA_MEM_SIZE, Caddr );
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d - Paddr zero!\n", SlotNumber);
- }
- }
- else
- {
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- }
- }
- /*
- ** Now we have checked all the slots, turn off the MCA slot selector
- */
- outb(McaSlotSelect,0);
- rio_dprintk (RIO_DEBUG_INIT, "Slot %d NOT RIO\n", SlotNumber);
- return ret;
-}
-
-int RIOEISAinit( int Mode )
-{
- static int EISADone = 0;
- uint Paddr;
- int PollIntMixMsgDone = 0;
- caddr_t Caddr;
- ushort Ident;
- uchar EisaSlot;
- uchar Ivec;
- int ret = 0;
-
- /*
- ** The only valid mode information for EISA hosts is fast or slow
- ** links.
- */
- Mode = (Mode & FAST_LINKS) ? EISA_TP_FAST_LINKS : EISA_TP_SLOW_LINKS;
-
- if ( EISADone )
- {
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit() - already done, return.\n");
- return(0);
- }
-
- EISADone++;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIOEISAinit()\n");
-
-
- /*
- ** First check all cards to see if ANY are set for polled mode operation.
- ** If so, set ALL to polled.
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Found Specialix product\n");
-
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Not Specialix RIO - Product number %x\n",
- INBZ(EisaSlot, EISA_PRODUCT_NUMBER));
- continue; /* next slot */
- }
- /*
- ** Its a Specialix RIO!
- */
- rio_dprintk (RIO_DEBUG_INIT, "RIO Revision %d\n",
- INBZ(EisaSlot, EISA_REVISION_NUMBER));
-
- RIOMachineType |= (1<<RIO_EISA);
-
- /*
- ** Just check we haven't found too many wonderful objects
- */
- if ( RIONumHosts >= RIO_HOSTS )
- {
- Rprintf(RIOMesgTooManyCards);
- return 0;
- }
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
-#ifdef RIODEBUG
- switch ( Ivec & EISA_INTERRUPT_MASK )
- {
- case EISA_IRQ_3:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 3\n");
- break;
- case EISA_IRQ_4:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 4\n");
- break;
- case EISA_IRQ_5:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 5\n");
- break;
- case EISA_IRQ_6:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 6\n");
- break;
- case EISA_IRQ_7:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 7\n");
- break;
- case EISA_IRQ_9:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 9\n");
- break;
- case EISA_IRQ_10:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 10\n");
- break;
- case EISA_IRQ_11:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 11\n");
- break;
- case EISA_IRQ_12:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 12\n");
- break;
- case EISA_IRQ_14:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 14\n");
- break;
- case EISA_IRQ_15:
- rio_dprintk (RIO_DEBUG_INIT, "EISA IRQ 15\n");
- break;
- case EISA_POLLED:
- rio_dprintk (RIO_DEBUG_INIT, "EISA POLLED\n");
- break;
- default:
- rio_dprintk (RIO_DEBUG_INIT, NULL,DBG_INIT|DBG_FAIL,"Shagged interrupt number!\n");
- Ivec &= EISA_CONTROL_MASK;
- }
-#endif
-
- if ( (Ivec & EISA_INTERRUPT_MASK) ==
- EISA_POLLED )
- {
- RIOWillPoll = 1;
- break; /* From EisaSlot loop */
- }
- }
- }
-
- /*
- ** Do it all again now we know whether to change all cards to polled
- ** mode or not
- */
-
- for ( EisaSlot=1; EisaSlot<=RIO_MAX_EISA_SLOTS; EisaSlot++ )
- {
- Ident = (INBZ(EisaSlot,EISA_PRODUCT_IDENT_HI)<<8) |
- INBZ(EisaSlot,EISA_PRODUCT_IDENT_LO);
-
- if ( Ident == RIO_EISA_IDENT )
- {
- if ( INBZ(EisaSlot,EISA_PRODUCT_NUMBER) != RIO_EISA_PRODUCT_CODE )
- continue; /* next slot */
-
- /*
- ** Its a Specialix RIO!
- */
-
- /*
- ** Ensure that the enable bit is set!
- */
- OUTBZ( EisaSlot, EISA_ENABLE, RIO_EISA_ENABLE_BIT );
-
- /*
- ** EISA_INTERRUPT_VEC contains the interrupt vector.
- */
- Ivec = INBZ(EisaSlot,EISA_INTERRUPT_VEC);
-
- if ( RIOWillPoll )
- {
- /*
- ** If we are going to operate in polled mode, but this
- ** board is configured to be interrupt driven, display
- ** the message explaining the situation to the punter,
- ** assuming we haven't already done so.
- */
-
- if ( !PollIntMixMsgDone &&
- (Ivec & EISA_INTERRUPT_MASK) != EISA_POLLED )
- {
- Rprintf(RIOMesgAllPolled);
- PollIntMixMsgDone = 1;
- }
-
- /*
- ** Ungraciously ignore whatever the board reports as its
- ** interrupt vector...
- */
-
- Ivec &= ~EISA_INTERRUPT_MASK;
-
- /*
- ** ...and force it to dance to the poll tune.
- */
-
- Ivec |= EISA_POLLED;
- }
-
- /*
- ** Convert the IRQ enable mask into something useful (0-15)
- */
- Ivec = RIOEisaToIvec(Ivec);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA host in slot %d has Ivec 0x%x\n",
- EisaSlot, Ivec);
-
- /*
- ** Find the physical address
- */
- Paddr = (INBZ(EisaSlot,EISA_MEMORY_BASE_HI)<<24) |
- (INBZ(EisaSlot,EISA_MEMORY_BASE_LO)<<16);
-
- rio_dprintk (RIO_DEBUG_INIT, "EISA card has Ivec %d Addr %x\n", Ivec, Paddr);
-
- if ( Paddr == 0 )
- {
- rio_dprintk (RIO_DEBUG_INIT,
- "Board in slot %d configured for address zero!\n", EisaSlot);
- continue;
- }
-
- /*
- ** Tell the memory mapper that we want to talk to it
- */
- rio_dprintk (RIO_DEBUG_INIT, "About to map EISA card \n");
-
- if (RIOMapin( Paddr, RIO_EISA_MEM_SIZE, &Caddr) == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at %x\n",
- RIO_EISA_MEM_SIZE,Paddr);
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INIT, "Board mapped to vaddr 0x%x\n", Caddr);
-
- /*
- ** And check that it is actually there!
- */
- if ( RIOBoardTest( Paddr,Caddr,RIO_EISA,EisaSlot) == RIO_SUCCESS )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT,
- "Slot %d. Ivec %d. Type %d. Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n",
- EisaSlot,Ivec,RIO_EISA,Paddr,Caddr,Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[RIONumHosts].Slot = EisaSlot;
- p->RIOHosts[RIONumHosts].Ivec = Ivec;
- p->RIOHosts[RIONumHosts].Type = RIO_EISA;
- p->RIOHosts[RIONumHosts].Copy = bcopy;
- p->RIOHosts[RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[RIONumHosts].Caddr = Caddr;
- p->RIOHosts[RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[RIONumHosts].Mode = Mode;
- /*
- ** because the EISA prom is mapped into IO space, we
- ** need to copy the unqiue number into the memory area
- ** that it would have occupied, so that the download
- ** code can determine its ID and card type.
- */
- WBYTE(p->RIOHosts[RIONumHosts].Unique[0],INBZ(EisaSlot,EISA_UNIQUE_NUM_0));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[1],INBZ(EisaSlot,EISA_UNIQUE_NUM_1));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[2],INBZ(EisaSlot,EISA_UNIQUE_NUM_2));
- WBYTE(p->RIOHosts[RIONumHosts].Unique[3],INBZ(EisaSlot,EISA_UNIQUE_NUM_3));
- p->RIOHosts[RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[RIONumHosts].Unique[3])&0xFF)<<24);
- INBZ(EisaSlot,EISA_INTERRUPT_RESET);
- RIONumHosts++;
- ret++;
- }
- else
- {
- /*
- ** It failed the test, so ignore it.
- */
- rio_dprintk (RIO_DEBUG_INIT, "TEST FAILED\n");
-
- RIOMapout(Paddr, RIO_EISA_MEM_SIZE, Caddr );
- }
- }
- }
- if (RIOMachineType & RIO_EISA)
- return ret+1;
- return ret;
-}
-#endif
-
-
-#ifndef linux
-
-#define CONFIG_ADDRESS 0xcf8
-#define CONFIG_DATA 0xcfc
-#define FORWARD_REG 0xcfa
-
-
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- unsigned int cav;
- unsigned int val;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS,cav);
- val = inpd(CONFIG_DATA);
- outpd(CONFIG_ADDRESS,0);
- return val;
-}
-
-static
-write_config(bus_number,device_num,r_number,val)
-{
- unsigned int cav;
-
-/*
- Build config_address_value:
-
- 31 24 23 16 15 11 10 8 7 0
- ------------------------------------------------------
- |1| 0000000 | bus_number | device # | 000 | register |
- ------------------------------------------------------
-*/
-
- cav = r_number & 0xff;
- cav |= ((device_num & 0x1f) << 11);
- cav |= ((bus_number & 0xff) << 16);
- cav |= 0x80000000; /* Enable bit */
- outpd(CONFIG_ADDRESS, cav);
- outpd(CONFIG_DATA, val);
- outpd(CONFIG_ADDRESS, 0);
- return val;
-}
-#else
-/* XXX Implement these... */
-static int
-read_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-static int
-write_config(int bus_number, int device_num, int r_number)
-{
- return 0;
-}
-
-#endif
-
-int
-RIOPCIinit(p, Mode)
-struct rio_info *p;
-int Mode;
-{
- #define MAX_PCI_SLOT 32
- #define RIO_PCI_JET_CARD 0x200011CB
-
- static int slot; /* count of machine's PCI slots searched so far */
- caddr_t Caddr; /* Virtual address of the current PCI host card. */
- unsigned char Ivec; /* interrupt vector for the current PCI host */
- unsigned long Paddr; /* Physical address for the current PCI host */
- int Handle; /* Handle to Virtual memory allocated for current PCI host */
-
-
- rio_dprintk (RIO_DEBUG_INIT, "Search for a RIO PCI card - start at slot %d\n", slot);
-
- /*
- ** Initialise the search status
- */
- p->RIOLastPCISearch = RIO_FAIL;
-
- while ( (slot < MAX_PCI_SLOT) & (p->RIOLastPCISearch != RIO_SUCCESS) )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Currently testing slot %d\n", slot);
-
- if (read_config(0,slot,0) == RIO_PCI_JET_CARD) {
- p->RIOHosts[p->RIONumHosts].Ivec = 0;
- Paddr = read_config(0,slot,0x18);
- Paddr = Paddr - (Paddr & 0x1); /* Mask off the io bit */
-
- if ( (Paddr == 0) || ((Paddr & 0xffff0000) == 0xffff0000) ) {
- rio_dprintk (RIO_DEBUG_INIT, "Goofed up slot\n"); /* what! */
- slot++;
- continue;
- }
-
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- Ivec = (read_config(0,slot,0x3c) & 0xff);
-
- rio_dprintk (RIO_DEBUG_INIT, "PCI Host at 0x%x, Intr %d\n", (int)Paddr, Ivec);
-
- Handle = RIOMapin( Paddr, RIO_PCI_MEM_SIZE, &Caddr );
- if (Handle == -1) {
- rio_dprintk (RIO_DEBUG_INIT, "Couldn't map %d bytes at 0x%x\n", RIO_PCI_MEM_SIZE, (int)Paddr);
- slot++;
- continue;
- }
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->intr_tid = iointset(p->RIOHosts[p->RIONumHosts].Ivec,
- (int (*)())rio_intr, (char *)p->RIONumHosts);
- if (RIOBoardTest( Paddr, Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) {
- rio_dprintk (RIO_DEBUG_INIT, ("Board has passed test\n");
- rio_dprintk (RIO_DEBUG_INIT, ("Paddr 0x%x. Caddr 0x%x. Mode 0x%x.\n", Paddr, Caddr, Mode);
-
- /*
- ** Board has passed its scrub test. Fill in all the
- ** transient stuff.
- */
- p->RIOHosts[p->RIONumHosts].Slot = 0;
- p->RIOHosts[p->RIONumHosts].Ivec = Ivec + 32;
- p->RIOHosts[p->RIONumHosts].Type = RIO_PCI;
- p->RIOHosts[p->RIONumHosts].Copy = rio_pcicopy;
- p->RIOHosts[p->RIONumHosts].PaddrP = Paddr;
- p->RIOHosts[p->RIONumHosts].Caddr = Caddr;
- p->RIOHosts[p->RIONumHosts].CardP = (struct DpRam *)Caddr;
- p->RIOHosts[p->RIONumHosts].Mode = Mode;
-
-#if 0
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
- WBYTE(p->RIOHosts[p->RIONumHosts].Control,
- BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
- p->RIOHosts[p->RIONumHosts].Mode |
- INTERRUPT_DISABLE );
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt,0xff);
-#else
- WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
-#endif
- p->RIOHosts[p->RIONumHosts].UniqueNum =
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
- ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-
- rio_dprintk (RIO_DEBUG_INIT, "Unique no 0x%x.\n",
- p->RIOHosts[p->RIONumHosts].UniqueNum);
-
- p->RIOLastPCISearch = RIO_SUCCESS;
- p->RIONumHosts++;
- }
- }
- slot++;
- }
-
- if ( slot >= MAX_PCI_SLOT ) {
- rio_dprintk (RIO_DEBUG_INIT, "All %d PCI slots have tested for RIO cards !!!\n",
- MAX_PCI_SLOT);
- }
-
-
- /*
- ** I don't think we want to do this anymore
- **
-
- if (!p->RIOLastPCISearch == RIO_FAIL ) {
- p->RIOFailed++;
- }
-
- **
- */
-}
-
-#ifdef FUTURE_RELEASE
-void riohalt( void )
-{
- int host;
- for ( host=0; host<p->RIONumHosts; host++ )
- {
- rio_dprintk (RIO_DEBUG_INIT, "Stop host %d\n", host);
- (void)RIOBoardTest( p->RIOHosts[host].PaddrP, p->RIOHosts[host].Caddr, p->RIOHosts[host].Type,p->RIOHosts[host].Slot );
- }
-}
-#endif
-#endif
static uchar val[] = {
#ifdef VERY_LONG_TEST
@@ -1262,200 +387,6 @@ int size;
return RIO_SUCCESS;
}
-/*
-** try to ensure that every host is either in polled mode
-** or is in interrupt mode. Only allow interrupt mode if
-** all hosts can interrupt (why?)
-** and force into polled mode if told to. Patch up the
-** interrupt vector & salute The Queen when you've done.
-*/
-#if 0
-static void
-RIOAllocateInterrupts(p)
-struct rio_info * p;
-{
- int Host;
-
- /*
- ** Easy case - if we have been told to poll, then we poll.
- */
- if (p->mode & POLLED_MODE) {
- RIOStopInterrupts(p, 0, 0);
- return;
- }
-
- /*
- ** check - if any host has been set to polled mode, then all must be.
- */
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if ( (p->RIOHosts[Host].Type != RIO_AT) &&
- (p->RIOHosts[Host].Ivec == POLLED) ) {
- RIOStopInterrupts(p, 1, Host );
- return;
- }
- }
- for (Host=0; Host<p->RIONumHosts; Host++) {
- if (p->RIOHosts[Host].Type == RIO_AT) {
- if ( (p->RIOHosts[Host].Ivec - 32) == 0) {
- RIOStopInterrupts(p, 2, Host );
- return;
- }
- }
- }
-}
-
-/*
-** something has decided that we can't be doing with these
-** new-fangled interrupt thingies. Set everything up to just
-** poll.
-*/
-static void
-RIOStopInterrupts(p, Reason, Host)
-struct rio_info * p;
-int Reason;
-int Host;
-{
-#ifdef FUTURE_RELEASE
- switch (Reason) {
- case 0: /* forced into polling by rio_polled */
- break;
- case 1: /* SCU has set 'Host' into polled mode */
- break;
- case 2: /* there aren't enough interrupt vectors for 'Host' */
- break;
- }
-#endif
-
- for (Host=0; Host<p->RIONumHosts; Host++ ) {
- struct Host *HostP = &p->RIOHosts[Host];
-
- switch (HostP->Type) {
- case RIO_AT:
- /*
- ** The AT host has it's interrupts disabled by clearing the
- ** int_enable bit.
- */
- HostP->Mode &= ~INTERRUPT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** The EISA host has it's interrupts disabled by setting the
- ** Ivec to zero
- */
- HostP->Ivec = POLLED;
- break;
-#endif
- case RIO_PCI:
- /*
- ** The PCI host has it's interrupts disabled by clearing the
- ** int_enable bit, like a regular host card.
- */
- HostP->Mode &= ~RIO_PCI_INT_ENABLE;
- HostP->Ivec = POLLED;
- break;
-#ifdef FUTURE_RELEASE
- case RIO_MCA:
- /*
- ** There's always one, isn't there?
- ** The MCA host card cannot have it's interrupts disabled.
- */
- RIOPatchVec(HostP);
- break;
-#endif
- }
- }
-}
-
-/*
-** This function is called at init time to setup the data structures.
-*/
-void
-RIOAllocDataStructs(p)
-struct rio_info * p;
-{
- int port,
- host,
- tm;
-
- p->RIOPortp = (struct Port *)sysbrk(RIO_PORTS * sizeof(struct Port));
- if (!p->RIOPortp) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for port structures\n");
- p->RIOFailed++;
- return;
- }
- bzero( p->RIOPortp, sizeof(struct Port) * RIO_PORTS );
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for port structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO port struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOPortp, sizeof(struct Port));
-
- for( port=0; port<RIO_PORTS; port++ ) {
- p->RIOPortp[port].PortNum = port;
- p->RIOPortp[port].TtyP = &p->channel[port];
- sreset (p->RIOPortp[port].InUse); /* Let the first guy uses it */
- p->RIOPortp[port].portSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].ParamSem = -1; /* Let the first guy takes it */
- p->RIOPortp[port].timeout_id = 0; /* Let the first guy takes it */
- }
-
- p->RIOHosts = (struct Host *)sysbrk(RIO_HOSTS * sizeof(struct Host));
- if (!p->RIOHosts) {
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: No memory for host structures\n");
- p->RIOFailed++;
- return;
- }
- bzero(p->RIOHosts, sizeof(struct Host)*RIO_HOSTS);
- rio_dprintk (RIO_DEBUG_INIT, "RIO-init: allocated and cleared memory for host structs\n");
- rio_dprintk (RIO_DEBUG_INIT, "First RIO host struct @0x%x, size=0x%x bytes\n",
- (int)p->RIOHosts, sizeof(struct Host));
-
- for( host=0; host<RIO_HOSTS; host++ ) {
- spin_lock_init (&p->RIOHosts[host].HostLock);
- p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
- }
- /*
- ** check that the buffer size is valid, round down to the next power of
- ** two if necessary; if the result is zero, then, hey, no double buffers.
- */
- for ( tm = 1; tm && tm <= p->RIOConf.BufferSize; tm <<= 1 )
- ;
- tm >>= 1;
- p->RIOBufferSize = tm;
- p->RIOBufferMask = tm ? tm - 1 : 0;
-}
-
-/*
-** this function gets called whenever the data structures need to be
-** re-setup, for example, after a riohalt (why did I ever invent it?)
-*/
-void
-RIOSetupDataStructs(p)
-struct rio_info * p;
-{
- int host, entry, rup;
-
- for ( host=0; host<RIO_HOSTS; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- for ( entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Topology[entry].Link = NO_LINK;
- }
- bcopy("HOST X", HostP->Name, 7);
- HostP->Name[5] = '1'+host;
- for (rup=0; rup<(MAX_RUP + LINKS_PER_UNIT); rup++) {
- if (rup < MAX_RUP) {
- for (entry=0; entry<LINKS_PER_UNIT; entry++ ) {
- HostP->Mapping[rup].Topology[entry].Unit = ROUTE_DISCONNECT;
- HostP->Mapping[rup].Topology[entry].Link = NO_LINK;
- }
- RIODefaultName(p, HostP, rup);
- }
- spin_lock_init(&HostP->UnixRups[rup].RupLock);
- }
- }
-}
-#endif
int
RIODefaultName(p, HostP, UnitId)
@@ -1463,10 +394,6 @@ struct rio_info * p;
struct Host * HostP;
uint UnitId;
{
-#ifdef CHECK
- CheckHost( Host );
- CheckUnitId( UnitId );
-#endif
bcopy("UNKNOWN RTA X-XX",HostP->Mapping[UnitId].Name,17);
HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
if ((UnitId+1) > 9) {
@@ -1483,33 +410,6 @@ uint UnitId;
#define RIO_RELEASE "Linux"
#define RELEASE_ID "1.0"
-#if 0
-static int
-RIOReport(p)
-struct rio_info * p;
-{
- char * RIORelease = RIO_RELEASE;
- char * RIORelID = RELEASE_ID;
- int host;
-
- rio_dprintk (RIO_DEBUG_INIT, "RIO : Release: %s ID: %s\n", RIORelease, RIORelID);
-
- if ( p->RIONumHosts==0 ) {
- rio_dprintk (RIO_DEBUG_INIT, "\nNo Hosts configured\n");
- return(0);
- }
-
- for ( host=0; host < p->RIONumHosts; host++ ) {
- struct Host *HostP = &p->RIOHosts[host];
- switch ( HostP->Type ) {
- case RIO_AT:
- rio_dprintk (RIO_DEBUG_INIT, "AT BUS : found the card at 0x%x\n", HostP->PaddrP);
- }
- }
- return 0;
-}
-#endif
-
static struct rioVersion stVersion;
struct rioVersion *
@@ -1523,27 +423,6 @@ RIOVersid(void)
return &stVersion;
}
-#if 0
-int
-RIOMapin(paddr, size, vaddr)
-paddr_t paddr;
-int size;
-caddr_t * vaddr;
-{
- *vaddr = (caddr_t)permap( (long)paddr, size);
- return ((int)*vaddr);
-}
-
-void
-RIOMapout(paddr, size, vaddr)
-paddr_t paddr;
-long size;
-caddr_t vaddr;
-{
-}
-#endif
-
-
void
RIOHostReset(Type, DpRamP, Slot)
uint Type;
@@ -1570,31 +449,6 @@ uint Slot;
WBYTE(DpRamP->DpResetTpu, 0xFF);
udelay(3);
break;
-#ifdef FUTURE_RELEASE
- case RIO_EISA:
- /*
- ** Bet this doesn't work!
- */
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RESET | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- suspend( 3 );
- OUTBZ( Slot, EISA_CONTROL_PORT,
- EISA_TP_RUN | EISA_TP_BUS_DISABLE |
- EISA_TP_SLOW_LINKS | EISA_TP_BOOT_FROM_RAM );
- break;
- case RIO_MCA:
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- WBYTE(DpRamP->DpControl , McaTpBootFromRam | McaTpBusDisable );
- WBYTE(DpRamP->DpResetTpu , 0xFF );
- suspend( 3 );
- break;
-#endif
case RIO_PCI:
rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
@@ -1604,12 +458,6 @@ uint Slot;
/* for (i=0; i<6000; i++); */
/* suspend( 3 ); */
break;
-#ifdef FUTURE_RELEASE
- default:
- Rprintf(RIOMesgNoSupport,Type,DpRamP,Slot);
- return;
-#endif
-
default:
rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
break;
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index e42e7b50bf6b..34d8787557a1 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -38,6 +38,7 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/string.h>
@@ -87,99 +88,93 @@ static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
static void RIOReceive(struct rio_info *, struct Port *);
-static char *firstchars (char *p, int nch)
+static char *firstchars(char *p, int nch)
{
- static char buf[2][128];
- static int t=0;
- t = ! t;
- memcpy (buf[t], p, nch);
- buf[t][nch] = 0;
- return buf[t];
+ static char buf[2][128];
+ static int t = 0;
+ t = !t;
+ memcpy(buf[t], p, nch);
+ buf[t][nch] = 0;
+ return buf[t];
}
#define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask))
/* Enable and start the transmission of packets */
-void
-RIOTxEnable(en)
-char * en;
+void RIOTxEnable(en)
+char *en;
{
- struct Port * PortP;
- struct rio_info *p;
- struct tty_struct* tty;
- int c;
- struct PKT * PacketP;
- unsigned long flags;
-
- PortP = (struct Port *)en;
- p = (struct rio_info *)PortP->p;
- tty = PortP->gs.tty;
-
-
- rio_dprintk (RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n",
- PortP->PortNum, PortP->gs.xmit_cnt);
-
- if (!PortP->gs.xmit_cnt) return;
-
-
- /* This routine is an order of magnitude simpler than the specialix
- version. One of the disadvantages is that this version will send
- an incomplete packet (usually 64 bytes instead of 72) once for
- every 4k worth of data. Let's just say that this won't influence
- performance significantly..... */
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
- while (can_add_transmit( &PacketP, PortP )) {
- c = PortP->gs.xmit_cnt;
- if (c > PKT_MAX_DATA_LEN) c = PKT_MAX_DATA_LEN;
-
- /* Don't copy past the end of the source buffer */
- if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
- c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
-
- { int t;
- t = (c > 10)?10:c;
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n",
- PortP->PortNum, c,
- firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail , t),
- firstchars (PortP->gs.xmit_buf + PortP->gs.xmit_tail + c-t, t));
- }
- /* If for one reason or another, we can't copy more data,
- we're done! */
- if (c == 0) break;
-
- rio_memcpy_toio (PortP->HostP->Caddr, (caddr_t)PacketP->data,
- PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
- /* udelay (1); */
-
- writeb (c, &(PacketP->len));
- if (!( PortP->State & RIO_DELETED ) ) {
- add_transmit ( PortP );
- /*
- ** Count chars tx'd for port statistics reporting
- */
- if ( PortP->statsGather )
- PortP->txchars += c;
- }
- PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1);
- PortP->gs.xmit_cnt -= c;
- }
-
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
- if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2*PKT_MAX_DATA_LEN)) {
- rio_dprintk (RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....",
- (int)(PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)),
- PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
- if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- PortP->gs.tty->ldisc.write_wakeup)
- (PortP->gs.tty->ldisc.write_wakeup)(PortP->gs.tty);
- rio_dprintk (RIO_DEBUG_INTR, "(%d/%d)\n",
- PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
- wake_up_interruptible(&PortP->gs.tty->write_wait);
- }
+ struct Port *PortP;
+ struct rio_info *p;
+ struct tty_struct *tty;
+ int c;
+ struct PKT *PacketP;
+ unsigned long flags;
+
+ PortP = (struct Port *) en;
+ p = (struct rio_info *) PortP->p;
+ tty = PortP->gs.tty;
+
+
+ rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
+
+ if (!PortP->gs.xmit_cnt)
+ return;
+
+
+ /* This routine is an order of magnitude simpler than the specialix
+ version. One of the disadvantages is that this version will send
+ an incomplete packet (usually 64 bytes instead of 72) once for
+ every 4k worth of data. Let's just say that this won't influence
+ performance significantly..... */
+
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+ while (can_add_transmit(&PacketP, PortP)) {
+ c = PortP->gs.xmit_cnt;
+ if (c > PKT_MAX_DATA_LEN)
+ c = PKT_MAX_DATA_LEN;
+
+ /* Don't copy past the end of the source buffer */
+ if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
+ c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
+
+ {
+ int t;
+ t = (c > 10) ? 10 : c;
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
+ }
+ /* If for one reason or another, we can't copy more data,
+ we're done! */
+ if (c == 0)
+ break;
+
+ rio_memcpy_toio(PortP->HostP->Caddr, (caddr_t) PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+ /* udelay (1); */
+
+ writeb(c, &(PacketP->len));
+ if (!(PortP->State & RIO_DELETED)) {
+ add_transmit(PortP);
+ /*
+ ** Count chars tx'd for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += c;
+ }
+ PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
+ PortP->gs.xmit_cnt -= c;
+ }
+
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+ if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) {
+ rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
+ if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup)
+ (PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty);
+ rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
+ wake_up_interruptible(&PortP->gs.tty->write_wait);
+ }
}
@@ -188,361 +183,349 @@ char * en;
** RIO Host Service routine. Does all the work traditionally associated with an
** interrupt.
*/
-static int RupIntr;
-static int RxIntr;
-static int TxIntr;
-void
-RIOServiceHost(p, HostP, From)
-struct rio_info * p;
+static int RupIntr;
+static int RxIntr;
+static int TxIntr;
+void RIOServiceHost(p, HostP, From)
+struct rio_info *p;
struct Host *HostP;
-int From;
+int From;
{
- rio_spin_lock (&HostP->HostLock);
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- static int t =0;
- rio_spin_unlock (&HostP->HostLock);
- if ((t++ % 200) == 0)
- rio_dprintk (RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int)HostP->Flags);
- return;
- }
- rio_spin_unlock (&HostP->HostLock);
-
- if ( RWORD( HostP->ParmMapP->rup_intr ) ) {
- WWORD( HostP->ParmMapP->rup_intr , 0 );
- p->RIORupCount++;
- RupIntr++;
- rio_dprintk (RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP-p->RIOHosts);
- RIOPollHostCommands(p, HostP );
- }
-
- if ( RWORD( HostP->ParmMapP->rx_intr ) ) {
- int port;
-
- WWORD( HostP->ParmMapP->rx_intr , 0 );
- p->RIORxCount++;
- RxIntr++;
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP-p->RIOHosts);
- /*
- ** Loop through every port. If the port is mapped into
- ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
- ** worth checking. If the port isn't open, grab any packets
- ** hanging on its receive queue and stuff them on the free
- ** list; check for commands on the way.
- */
- for ( port=p->RIOFirstPortsBooted;
- port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
- struct Port *PortP = p->RIOPortp[port];
- struct tty_struct *ttyP;
- struct PKT *PacketP;
-
- /*
- ** not mapped in - most of the RIOPortp[] information
- ** has not been set up!
- ** Optimise: ports come in bundles of eight.
- */
- if ( !PortP->Mapped ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** If the host board isn't THIS host board, check the next one.
- ** optimise: ports come in bundles of eight.
- */
- if ( PortP->HostP != HostP ) {
- port += 7;
- continue;
- }
-
- /*
- ** Let us see - is the port open? If not, then don't service it.
- */
- if ( !( PortP->PortState & PORT_ISOPEN ) ) {
- continue;
- }
-
- /*
- ** find corresponding tty structure. The process of mapping
- ** the ports puts these here.
- */
- ttyP = PortP->gs.tty;
-
- /*
- ** Lock the port before we begin working on it.
- */
- rio_spin_lock(&PortP->portSem);
-
- /*
- ** Process received data if there is any.
- */
- if ( can_remove_receive( &PacketP, PortP ) )
- RIOReceive(p, PortP);
-
- /*
- ** If there is no data left to be read from the port, and
- ** it's handshake bit is set, then we must clear the handshake,
- ** so that that downstream RTA is re-enabled.
- */
- if ( !can_remove_receive( &PacketP, PortP ) &&
- ( RWORD( PortP->PhbP->handshake )==PHB_HANDSHAKE_SET ) ) {
+ rio_spin_lock(&HostP->HostLock);
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ static int t = 0;
+ rio_spin_unlock(&HostP->HostLock);
+ if ((t++ % 200) == 0)
+ rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
+ return;
+ }
+ rio_spin_unlock(&HostP->HostLock);
+
+ if (RWORD(HostP->ParmMapP->rup_intr)) {
+ WWORD(HostP->ParmMapP->rup_intr, 0);
+ p->RIORupCount++;
+ RupIntr++;
+ rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %d\n", HostP - p->RIOHosts);
+ RIOPollHostCommands(p, HostP);
+ }
+
+ if (RWORD(HostP->ParmMapP->rx_intr)) {
+ int port;
+
+ WWORD(HostP->ParmMapP->rx_intr, 0);
+ p->RIORxCount++;
+ RxIntr++;
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %d\n", HostP - p->RIOHosts);
+ /*
+ ** Loop through every port. If the port is mapped into
+ ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
+ ** worth checking. If the port isn't open, grab any packets
+ ** hanging on its receive queue and stuff them on the free
+ ** list; check for commands on the way.
+ */
+ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+ struct Port *PortP = p->RIOPortp[port];
+ struct tty_struct *ttyP;
+ struct PKT *PacketP;
+
+ /*
+ ** not mapped in - most of the RIOPortp[] information
+ ** has not been set up!
+ ** Optimise: ports come in bundles of eight.
+ */
+ if (!PortP->Mapped) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** If the host board isn't THIS host board, check the next one.
+ ** optimise: ports come in bundles of eight.
+ */
+ if (PortP->HostP != HostP) {
+ port += 7;
+ continue;
+ }
+
+ /*
+ ** Let us see - is the port open? If not, then don't service it.
+ */
+ if (!(PortP->PortState & PORT_ISOPEN)) {
+ continue;
+ }
+
+ /*
+ ** find corresponding tty structure. The process of mapping
+ ** the ports puts these here.
+ */
+ ttyP = PortP->gs.tty;
+
+ /*
+ ** Lock the port before we begin working on it.
+ */
+ rio_spin_lock(&PortP->portSem);
+
+ /*
+ ** Process received data if there is any.
+ */
+ if (can_remove_receive(&PacketP, PortP))
+ RIOReceive(p, PortP);
+
+ /*
+ ** If there is no data left to be read from the port, and
+ ** it's handshake bit is set, then we must clear the handshake,
+ ** so that that downstream RTA is re-enabled.
+ */
+ if (!can_remove_receive(&PacketP, PortP) && (RWORD(PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
/*
- ** MAGIC! ( Basically, handshake the RX buffer, so that
- ** the RTAs upstream can be re-enabled. )
- */
- rio_dprintk (RIO_DEBUG_INTR, "Set RX handshake bit\n");
- WWORD( PortP->PhbP->handshake,
- PHB_HANDSHAKE_SET|PHB_HANDSHAKE_RESET );
- }
- rio_spin_unlock(&PortP->portSem);
- }
- }
-
- if ( RWORD( HostP->ParmMapP->tx_intr ) ) {
- int port;
-
- WWORD( HostP->ParmMapP->tx_intr , 0);
-
- p->RIOTxCount++;
- TxIntr++;
- rio_dprintk (RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP-p->RIOHosts);
-
- /*
- ** Loop through every port.
- ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
- ** associated ) then it is worth checking.
- */
- for ( port=p->RIOFirstPortsBooted;
- port<p->RIOLastPortsBooted+PORTS_PER_RTA; port++ ) {
- struct Port *PortP = p->RIOPortp[port];
- struct tty_struct *ttyP;
- struct PKT *PacketP;
-
- /*
- ** not mapped in - most of the RIOPortp[] information
- ** has not been set up!
- */
- if ( !PortP->Mapped ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** If the host board isn't running, then its data structures
- ** are no use to us - continue quietly.
- */
- if ( PortP->HostP != HostP ) {
- port += 7;
- continue; /* with the next port */
- }
-
- /*
- ** Let us see - is the port open? If not, then don't service it.
- */
- if ( !( PortP->PortState & PORT_ISOPEN ) ) {
- continue;
- }
-
- rio_dprintk (RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
- /*
- ** Lock the port before we begin working on it.
- */
- rio_spin_lock(&PortP->portSem);
-
- /*
- ** If we can't add anything to the transmit queue, then
- ** we need do none of this processing.
- */
- if ( !can_add_transmit( &PacketP, PortP ) ) {
- rio_dprintk (RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
-
- /*
- ** find corresponding tty structure. The process of mapping
- ** the ports puts these here.
- */
- ttyP = PortP->gs.tty;
- /* If ttyP is NULL, the port is getting closed. Forget about it. */
- if (!ttyP) {
- rio_dprintk (RIO_DEBUG_INTR, "no tty, so skipping.\n");
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
- /*
- ** If there is more room available we start up the transmit
- ** data process again. This can be direct I/O, if the cookmode
- ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
- ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
- ** characters via the line discipline. We must always call
- ** the line discipline,
- ** so that user input characters can be echoed correctly.
- **
- ** ++++ Update +++++
- ** With the advent of double buffering, we now see if
- ** TxBufferOut-In is non-zero. If so, then we copy a packet
- ** to the output place, and set it going. If this empties
- ** the buffer, then we must issue a wakeup( ) on OUT.
- ** If it frees space in the buffer then we must issue
- ** a wakeup( ) on IN.
- **
- ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
- ** have to send a WFLUSH command down the PHB, to mark the
- ** end point of a WFLUSH. We also need to clear out any
- ** data from the double buffer! ( note that WflushFlag is a
- ** *count* of the number of WFLUSH commands outstanding! )
- **
- ** ++++ And there's more!
- ** If an RTA is powered off, then on again, and rebooted,
- ** whilst it has ports open, then we need to re-open the ports.
- ** ( reasonable enough ). We can't do this when we spot the
- ** re-boot, in interrupt time, because the queue is probably
- ** full. So, when we come in here, we need to test if any
- ** ports are in this condition, and re-open the port before
- ** we try to send any more data to it. Now, the re-booted
- ** RTA will be discarding packets from the PHB until it
- ** receives this open packet, but don't worry tooo much
- ** about that. The one thing that is interesting is the
- ** combination of this effect and the WFLUSH effect!
- */
- /* For now don't handle RTA reboots. -- REW.
- Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
- if ( PortP->MagicFlags ) {
-#if 1
- if ( PortP->MagicFlags & MAGIC_REBOOT ) {
- /*
- ** well, the RTA has been rebooted, and there is room
- ** on its queue to add the open packet that is required.
- **
- ** The messy part of this line is trying to decide if
- ** we need to call the Param function as a tty or as
- ** a modem.
- ** DONT USE CLOCAL AS A TEST FOR THIS!
- **
- ** If we can't param the port, then move on to the
- ** next port.
- */
- PortP->InUse = NOT_INUSE;
-
- rio_spin_unlock(&PortP->portSem);
- if ( RIOParam(PortP, OPEN, ((PortP->Cor2Copy &
- (COR2_RTSFLOW|COR2_CTSFLOW ) )==
- (COR2_RTSFLOW|COR2_CTSFLOW ) ) ?
- TRUE : FALSE, DONT_SLEEP ) == RIO_FAIL ) {
- continue; /* with next port */
- }
- rio_spin_lock(&PortP->portSem);
- PortP->MagicFlags &= ~MAGIC_REBOOT;
+ ** MAGIC! ( Basically, handshake the RX buffer, so that
+ ** the RTAs upstream can be re-enabled. )
+ */
+ rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
+ WWORD(PortP->PhbP->handshake, PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET);
+ }
+ rio_spin_unlock(&PortP->portSem);
+ }
}
+
+ if (RWORD(HostP->ParmMapP->tx_intr)) {
+ int port;
+
+ WWORD(HostP->ParmMapP->tx_intr, 0);
+
+ p->RIOTxCount++;
+ TxIntr++;
+ rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %d\n", HostP - p->RIOHosts);
+
+ /*
+ ** Loop through every port.
+ ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
+ ** associated ) then it is worth checking.
+ */
+ for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+ struct Port *PortP = p->RIOPortp[port];
+ struct tty_struct *ttyP;
+ struct PKT *PacketP;
+
+ /*
+ ** not mapped in - most of the RIOPortp[] information
+ ** has not been set up!
+ */
+ if (!PortP->Mapped) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** If the host board isn't running, then its data structures
+ ** are no use to us - continue quietly.
+ */
+ if (PortP->HostP != HostP) {
+ port += 7;
+ continue; /* with the next port */
+ }
+
+ /*
+ ** Let us see - is the port open? If not, then don't service it.
+ */
+ if (!(PortP->PortState & PORT_ISOPEN)) {
+ continue;
+ }
+
+ rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
+ /*
+ ** Lock the port before we begin working on it.
+ */
+ rio_spin_lock(&PortP->portSem);
+
+ /*
+ ** If we can't add anything to the transmit queue, then
+ ** we need do none of this processing.
+ */
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+
+ /*
+ ** find corresponding tty structure. The process of mapping
+ ** the ports puts these here.
+ */
+ ttyP = PortP->gs.tty;
+ /* If ttyP is NULL, the port is getting closed. Forget about it. */
+ if (!ttyP) {
+ rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+ /*
+ ** If there is more room available we start up the transmit
+ ** data process again. This can be direct I/O, if the cookmode
+ ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
+ ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
+ ** characters via the line discipline. We must always call
+ ** the line discipline,
+ ** so that user input characters can be echoed correctly.
+ **
+ ** ++++ Update +++++
+ ** With the advent of double buffering, we now see if
+ ** TxBufferOut-In is non-zero. If so, then we copy a packet
+ ** to the output place, and set it going. If this empties
+ ** the buffer, then we must issue a wakeup( ) on OUT.
+ ** If it frees space in the buffer then we must issue
+ ** a wakeup( ) on IN.
+ **
+ ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
+ ** have to send a WFLUSH command down the PHB, to mark the
+ ** end point of a WFLUSH. We also need to clear out any
+ ** data from the double buffer! ( note that WflushFlag is a
+ ** *count* of the number of WFLUSH commands outstanding! )
+ **
+ ** ++++ And there's more!
+ ** If an RTA is powered off, then on again, and rebooted,
+ ** whilst it has ports open, then we need to re-open the ports.
+ ** ( reasonable enough ). We can't do this when we spot the
+ ** re-boot, in interrupt time, because the queue is probably
+ ** full. So, when we come in here, we need to test if any
+ ** ports are in this condition, and re-open the port before
+ ** we try to send any more data to it. Now, the re-booted
+ ** RTA will be discarding packets from the PHB until it
+ ** receives this open packet, but don't worry tooo much
+ ** about that. The one thing that is interesting is the
+ ** combination of this effect and the WFLUSH effect!
+ */
+ /* For now don't handle RTA reboots. -- REW.
+ Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
+ if (PortP->MagicFlags) {
+#if 1
+ if (PortP->MagicFlags & MAGIC_REBOOT) {
+ /*
+ ** well, the RTA has been rebooted, and there is room
+ ** on its queue to add the open packet that is required.
+ **
+ ** The messy part of this line is trying to decide if
+ ** we need to call the Param function as a tty or as
+ ** a modem.
+ ** DONT USE CLOCAL AS A TEST FOR THIS!
+ **
+ ** If we can't param the port, then move on to the
+ ** next port.
+ */
+ PortP->InUse = NOT_INUSE;
+
+ rio_spin_unlock(&PortP->portSem);
+ if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? TRUE : FALSE, DONT_SLEEP) == RIO_FAIL) {
+ continue; /* with next port */
+ }
+ rio_spin_lock(&PortP->portSem);
+ PortP->MagicFlags &= ~MAGIC_REBOOT;
+ }
#endif
- /*
- ** As mentioned above, this is a tacky hack to cope
- ** with WFLUSH
- */
- if ( PortP->WflushFlag ) {
- rio_dprintk (RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
-
- if ( PortP->InUse )
- rio_dprintk (RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
- }
-
- while ( PortP->WflushFlag &&
- can_add_transmit( &PacketP, PortP ) &&
- ( PortP->InUse == NOT_INUSE ) ) {
- int p;
- struct PktCmd *PktCmdP;
-
- rio_dprintk (RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
- /*
- ** make it look just like a WFLUSH command
- */
- PktCmdP = ( struct PktCmd * )&PacketP->data[0];
-
- WBYTE( PktCmdP->Command , WFLUSH );
-
- p = PortP->HostPort % ( ushort )PORTS_PER_RTA;
-
- /*
- ** If second block of ports for 16 port RTA, add 8
- ** to index 8-15.
- */
- if ( PortP->SecondBlock )
- p += PORTS_PER_RTA;
-
- WBYTE( PktCmdP->PhbNum, p );
-
- /*
- ** to make debuggery easier
- */
- WBYTE( PacketP->data[ 2], 'W' );
- WBYTE( PacketP->data[ 3], 'F' );
- WBYTE( PacketP->data[ 4], 'L' );
- WBYTE( PacketP->data[ 5], 'U' );
- WBYTE( PacketP->data[ 6], 'S' );
- WBYTE( PacketP->data[ 7], 'H' );
- WBYTE( PacketP->data[ 8], ' ' );
- WBYTE( PacketP->data[ 9], '0'+PortP->WflushFlag );
- WBYTE( PacketP->data[10], ' ' );
- WBYTE( PacketP->data[11], ' ' );
- WBYTE( PacketP->data[12], '\0' );
-
- /*
- ** its two bytes long!
- */
- WBYTE( PacketP->len , PKT_CMD_BIT | 2 );
-
- /*
- ** queue it!
- */
- if ( !( PortP->State & RIO_DELETED ) ) {
- add_transmit( PortP );
- /*
- ** Count chars tx'd for port statistics reporting
- */
- if ( PortP->statsGather )
- PortP->txchars += 2;
- }
-
- if ( --( PortP->WflushFlag ) == 0 ) {
- PortP->MagicFlags &= ~MAGIC_FLUSH;
- }
-
- rio_dprintk (RIO_DEBUG_INTR, "Wflush count now stands at %d\n",
- PortP->WflushFlag);
- }
- if ( PortP->MagicFlags & MORE_OUTPUT_EYGOR ) {
- if ( PortP->MagicFlags & MAGIC_FLUSH ) {
- PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
- }
- else {
- if ( !can_add_transmit( &PacketP, PortP ) ) {
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
- rio_spin_unlock(&PortP->portSem);
- RIOTxEnable((char *)PortP);
- rio_spin_lock(&PortP->portSem);
- PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
- }
+ /*
+ ** As mentioned above, this is a tacky hack to cope
+ ** with WFLUSH
+ */
+ if (PortP->WflushFlag) {
+ rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
+
+ if (PortP->InUse)
+ rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
+ }
+
+ while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
+ int p;
+ struct PktCmd *PktCmdP;
+
+ rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
+ /*
+ ** make it look just like a WFLUSH command
+ */
+ PktCmdP = (struct PktCmd *) &PacketP->data[0];
+
+ WBYTE(PktCmdP->Command, WFLUSH);
+
+ p = PortP->HostPort % (ushort) PORTS_PER_RTA;
+
+ /*
+ ** If second block of ports for 16 port RTA, add 8
+ ** to index 8-15.
+ */
+ if (PortP->SecondBlock)
+ p += PORTS_PER_RTA;
+
+ WBYTE(PktCmdP->PhbNum, p);
+
+ /*
+ ** to make debuggery easier
+ */
+ WBYTE(PacketP->data[2], 'W');
+ WBYTE(PacketP->data[3], 'F');
+ WBYTE(PacketP->data[4], 'L');
+ WBYTE(PacketP->data[5], 'U');
+ WBYTE(PacketP->data[6], 'S');
+ WBYTE(PacketP->data[7], 'H');
+ WBYTE(PacketP->data[8], ' ');
+ WBYTE(PacketP->data[9], '0' + PortP->WflushFlag);
+ WBYTE(PacketP->data[10], ' ');
+ WBYTE(PacketP->data[11], ' ');
+ WBYTE(PacketP->data[12], '\0');
+
+ /*
+ ** its two bytes long!
+ */
+ WBYTE(PacketP->len, PKT_CMD_BIT | 2);
+
+ /*
+ ** queue it!
+ */
+ if (!(PortP->State & RIO_DELETED)) {
+ add_transmit(PortP);
+ /*
+ ** Count chars tx'd for port statistics reporting
+ */
+ if (PortP->statsGather)
+ PortP->txchars += 2;
+ }
+
+ if (--(PortP->WflushFlag) == 0) {
+ PortP->MagicFlags &= ~MAGIC_FLUSH;
+ }
+
+ rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
+ }
+ if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
+ if (PortP->MagicFlags & MAGIC_FLUSH) {
+ PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ } else {
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+ rio_spin_unlock(&PortP->portSem);
+ RIOTxEnable((char *) PortP);
+ rio_spin_lock(&PortP->portSem);
+ PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+ }
+ }
+ }
+
+
+ /*
+ ** If we can't add anything to the transmit queue, then
+ ** we need do none of the remaining processing.
+ */
+ if (!can_add_transmit(&PacketP, PortP)) {
+ rio_spin_unlock(&PortP->portSem);
+ continue;
+ }
+
+ rio_spin_unlock(&PortP->portSem);
+ RIOTxEnable((char *) PortP);
+ }
}
- }
-
-
- /*
- ** If we can't add anything to the transmit queue, then
- ** we need do none of the remaining processing.
- */
- if (!can_add_transmit( &PacketP, PortP ) ) {
- rio_spin_unlock(&PortP->portSem);
- continue;
- }
-
- rio_spin_unlock(&PortP->portSem);
- RIOTxEnable((char *)PortP);
- }
- }
}
/*
@@ -550,180 +533,162 @@ int From;
** NB: Called with the tty locked. The spl from the lockb( ) is passed.
** we return the ttySpl level that we re-locked at.
*/
-static void
-RIOReceive(p, PortP)
-struct rio_info * p;
-struct Port * PortP;
+static void RIOReceive(p, PortP)
+struct rio_info *p;
+struct Port *PortP;
{
- struct tty_struct *TtyP;
- register ushort transCount;
- struct PKT *PacketP;
- register uint DataCnt;
- uchar * ptr;
- int copied =0;
-
- static int intCount, RxIntCnt;
-
- /*
- ** The receive data process is to remove packets from the
- ** PHB until there aren't any more or the current cblock
- ** is full. When this occurs, there will be some left over
- ** data in the packet, that we must do something with.
- ** As we haven't unhooked the packet from the read list
- ** yet, we can just leave the packet there, having first
- ** made a note of how far we got. This means that we need
- ** a pointer per port saying where we start taking the
- ** data from - this will normally be zero, but when we
- ** run out of space it will be set to the offset of the
- ** next byte to copy from the packet data area. The packet
- ** length field is decremented by the number of bytes that
- ** we succesfully removed from the packet. When this reaches
- ** zero, we reset the offset pointer to be zero, and free
- ** the packet from the front of the queue.
- */
-
- intCount++;
-
- TtyP = PortP->gs.tty;
- if (!TtyP) {
- rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
- return;
- }
-
- if (PortP->State & RIO_THROTTLE_RX) {
- rio_dprintk (RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
- return;
- }
-
- if ( PortP->State & RIO_DELETED )
- {
- while ( can_remove_receive( &PacketP, PortP ) )
- {
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
+ struct tty_struct *TtyP;
+ register ushort transCount;
+ struct PKT *PacketP;
+ register uint DataCnt;
+ uchar *ptr;
+ unsigned char *buf;
+ int copied = 0;
+
+ static int intCount, RxIntCnt;
+
+ /*
+ ** The receive data process is to remove packets from the
+ ** PHB until there aren't any more or the current cblock
+ ** is full. When this occurs, there will be some left over
+ ** data in the packet, that we must do something with.
+ ** As we haven't unhooked the packet from the read list
+ ** yet, we can just leave the packet there, having first
+ ** made a note of how far we got. This means that we need
+ ** a pointer per port saying where we start taking the
+ ** data from - this will normally be zero, but when we
+ ** run out of space it will be set to the offset of the
+ ** next byte to copy from the packet data area. The packet
+ ** length field is decremented by the number of bytes that
+ ** we succesfully removed from the packet. When this reaches
+ ** zero, we reset the offset pointer to be zero, and free
+ ** the packet from the front of the queue.
+ */
+
+ intCount++;
+
+ TtyP = PortP->gs.tty;
+ if (!TtyP) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
+ return;
}
- }
- else
- {
- /*
- ** loop, just so long as:
- ** i ) there's some data ( i.e. can_remove_receive )
- ** ii ) we haven't been blocked
- ** iii ) there's somewhere to put the data
- ** iv ) we haven't outstayed our welcome
- */
- transCount = 1;
- while ( can_remove_receive(&PacketP, PortP)
- && transCount)
- {
+
+ if (PortP->State & RIO_THROTTLE_RX) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
+ return;
+ }
+
+ if (PortP->State & RIO_DELETED) {
+ while (can_remove_receive(&PacketP, PortP)) {
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ }
+ } else {
+ /*
+ ** loop, just so long as:
+ ** i ) there's some data ( i.e. can_remove_receive )
+ ** ii ) we haven't been blocked
+ ** iii ) there's somewhere to put the data
+ ** iv ) we haven't outstayed our welcome
+ */
+ transCount = 1;
+ while (can_remove_receive(&PacketP, PortP)
+ && transCount) {
#ifdef STATS
- PortP->Stat.RxIntCnt++;
-#endif /* STATS */
- RxIntCnt++;
-
- /*
- ** check that it is not a command!
- */
- if ( PacketP->len & PKT_CMD_BIT ) {
- rio_dprintk (RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
- /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */
- rio_dprintk (RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
- rio_dprintk (RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
- rio_dprintk (RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit);
- rio_dprintk (RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port);
- rio_dprintk (RIO_DEBUG_INTR, " len = %d\n", PacketP->len);
- rio_dprintk (RIO_DEBUG_INTR, " control = %d\n", PacketP->control);
- rio_dprintk (RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum);
- rio_dprintk (RIO_DEBUG_INTR, " data bytes: ");
- for ( DataCnt=0; DataCnt<PKT_MAX_DATA_LEN; DataCnt++ )
- rio_dprintk (RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
- continue; /* with next packet */
- }
-
- /*
- ** How many characters can we move 'upstream' ?
- **
- ** Determine the minimum of the amount of data
- ** available and the amount of space in which to
- ** put it.
- **
- ** 1. Get the packet length by masking 'len'
- ** for only the length bits.
- ** 2. Available space is [buffer size] - [space used]
- **
- ** Transfer count is the minimum of packet length
- ** and available space.
- */
-
- transCount = min_t(unsigned int, PacketP->len & PKT_LEN_MASK,
- TTY_FLIPBUF_SIZE - TtyP->flip.count);
- rio_dprintk (RIO_DEBUG_REC, "port %d: Copy %d bytes\n",
- PortP->PortNum, transCount);
- /*
- ** To use the following 'kkprintfs' for debugging - change the '#undef'
- ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
- ** driver).
- */
+ PortP->Stat.RxIntCnt++;
+#endif /* STATS */
+ RxIntCnt++;
+
+ /*
+ ** check that it is not a command!
+ */
+ if (PacketP->len & PKT_CMD_BIT) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
+ /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */
+ rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
+ rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
+ rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", PacketP->src_unit);
+ rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", PacketP->src_port);
+ rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", PacketP->len);
+ rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", PacketP->control);
+ rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", PacketP->csum);
+ rio_dprintk(RIO_DEBUG_INTR, " data bytes: ");
+ for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
+ rio_dprintk(RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ continue; /* with next packet */
+ }
+
+ /*
+ ** How many characters can we move 'upstream' ?
+ **
+ ** Determine the minimum of the amount of data
+ ** available and the amount of space in which to
+ ** put it.
+ **
+ ** 1. Get the packet length by masking 'len'
+ ** for only the length bits.
+ ** 2. Available space is [buffer size] - [space used]
+ **
+ ** Transfer count is the minimum of packet length
+ ** and available space.
+ */
+
+ transCount = tty_buffer_request_room(TtyP, PacketP->len & PKT_LEN_MASK);
+ rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
+ /*
+ ** To use the following 'kkprintfs' for debugging - change the '#undef'
+ ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
+ ** driver).
+ */
#undef ___DEBUG_IT___
#ifdef ___DEBUG_IT___
- kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ",
- intCount,
- RxIntCnt,
- PortP->PortNum,
- TtyP->rxqueue.count,
- transCount,
- TtyP->flags );
+ kkprintf("I:%d R:%d P:%d Q:%d C:%d F:%x ", intCount, RxIntCnt, PortP->PortNum, TtyP->rxqueue.count, transCount, TtyP->flags);
#endif
- ptr = (uchar *) PacketP->data + PortP->RxDataStart;
-
- rio_memcpy_fromio (TtyP->flip.char_buf_ptr, ptr, transCount);
- memset(TtyP->flip.flag_buf_ptr, TTY_NORMAL, transCount);
+ ptr = (uchar *) PacketP->data + PortP->RxDataStart;
+ tty_prepare_flip_string(TtyP, &buf, transCount);
+ rio_memcpy_fromio(buf, ptr, transCount);
#ifdef STATS
- /*
- ** keep a count for statistical purposes
- */
- PortP->Stat.RxCharCnt += transCount;
+ /*
+ ** keep a count for statistical purposes
+ */
+ PortP->Stat.RxCharCnt += transCount;
#endif
- PortP->RxDataStart += transCount;
- PacketP->len -= transCount;
- copied += transCount;
- TtyP->flip.count += transCount;
- TtyP->flip.char_buf_ptr += transCount;
- TtyP->flip.flag_buf_ptr += transCount;
+ PortP->RxDataStart += transCount;
+ PacketP->len -= transCount;
+ copied += transCount;
#ifdef ___DEBUG_IT___
- kkprintf("T:%d L:%d\n", DataCnt, PacketP->len );
+ kkprintf("T:%d L:%d\n", DataCnt, PacketP->len);
#endif
- if ( PacketP->len == 0 )
- {
+ if (PacketP->len == 0) {
/*
- ** If we have emptied the packet, then we can
- ** free it, and reset the start pointer for
- ** the next packet.
- */
- remove_receive( PortP );
- put_free_end( PortP->HostP, PacketP );
- PortP->RxDataStart = 0;
+ ** If we have emptied the packet, then we can
+ ** free it, and reset the start pointer for
+ ** the next packet.
+ */
+ remove_receive(PortP);
+ put_free_end(PortP->HostP, PacketP);
+ PortP->RxDataStart = 0;
#ifdef STATS
/*
- ** more lies ( oops, I mean statistics )
- */
- PortP->Stat.RxPktCnt++;
-#endif /* STATS */
- }
+ ** more lies ( oops, I mean statistics )
+ */
+ PortP->Stat.RxPktCnt++;
+#endif /* STATS */
+ }
+ }
+ }
+ if (copied) {
+ rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
+ tty_flip_buffer_push(TtyP);
}
- }
- if (copied) {
- rio_dprintk (RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
- tty_flip_buffer_push (TtyP);
- }
- return;
+ return;
}
#ifdef FUTURE_RELEASE
@@ -731,221 +696,210 @@ struct Port * PortP;
** The proc routine called by the line discipline to do the work for it.
** The proc routine works hand in hand with the interrupt routine.
*/
-int
-riotproc(p, tp, cmd, port)
-struct rio_info * p;
+int riotproc(p, tp, cmd, port)
+struct rio_info *p;
register struct ttystatics *tp;
int cmd;
-int port;
+int port;
{
register struct Port *PortP;
int SysPort;
struct PKT *PacketP;
- SysPort = port; /* Believe me, it works. */
+ SysPort = port; /* Believe me, it works. */
- if ( SysPort < 0 || SysPort >= RIO_PORTS ) {
- rio_dprintk (RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n",SysPort);
+ if (SysPort < 0 || SysPort >= RIO_PORTS) {
+ rio_dprintk(RIO_DEBUG_INTR, "Illegal port %d derived from TTY in riotproc()\n", SysPort);
return 0;
}
PortP = p->RIOPortp[SysPort];
- if ((uint)PortP->PhbP < (uint)PortP->Caddr ||
- (uint)PortP->PhbP >= (uint)PortP->Caddr+SIXTY_FOUR_K ) {
- rio_dprintk (RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n",
- SysPort);
- rio_dprintk (RIO_DEBUG_INTR, " PortP = 0x%x\n",PortP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n",PortP->PhbP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n",PortP->PhbP);
- rio_dprintk (RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n",PortP->HostPort);
+ if ((uint) PortP->PhbP < (uint) PortP->Caddr || (uint) PortP->PhbP >= (uint) PortP->Caddr + SIXTY_FOUR_K) {
+ rio_dprintk(RIO_DEBUG_INTR, "RIO: NULL or BAD PhbP on sys port %d in proc routine\n", SysPort);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP = 0x%x\n", PortP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->PhbP = 0x%x\n", PortP->PhbP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->Caddr = 0x%x\n", PortP->PhbP);
+ rio_dprintk(RIO_DEBUG_INTR, " PortP->HostPort = 0x%x\n", PortP->HostPort);
return 0;
}
- switch(cmd) {
- case T_WFLUSH:
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH\n");
+ switch (cmd) {
+ case T_WFLUSH:
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH\n");
+ /*
+ ** Because of the spooky way the RIO works, we don't need
+ ** to issue a flush command on any of the SET*F commands,
+ ** as that causes trouble with getty and login, which issue
+ ** these commands to incur a READ flush, and rely on the fact
+ ** that the line discipline does a wait for drain for them.
+ ** As the rio doesn't wait for drain, the write flush would
+ ** destroy the Password: prompt. This isn't very friendly, so
+ ** here we only issue a WFLUSH command if we are in the interrupt
+ ** routine, or we aren't executing a SET*F command.
+ */
+ if (PortP->HostP->InIntr || !PortP->FlushCmdBodge) {
/*
- ** Because of the spooky way the RIO works, we don't need
- ** to issue a flush command on any of the SET*F commands,
- ** as that causes trouble with getty and login, which issue
- ** these commands to incur a READ flush, and rely on the fact
- ** that the line discipline does a wait for drain for them.
- ** As the rio doesn't wait for drain, the write flush would
- ** destroy the Password: prompt. This isn't very friendly, so
- ** here we only issue a WFLUSH command if we are in the interrupt
- ** routine, or we aren't executing a SET*F command.
- */
- if ( PortP->HostP->InIntr || !PortP->FlushCmdBodge ) {
- /*
- ** form a wflush packet - 1 byte long, no data
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");
- }
- else {
- if ( RIOPreemptiveCmd(p, PortP, WFLUSH ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");
- }
- else
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command\n");
- }
- /*
- ** WFLUSH operation - flush the data!
- */
- PortP->TxBufferIn = PortP->TxBufferOut = 0;
- }
- else {
- rio_dprintk (RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");
+ ** form a wflush packet - 1 byte long, no data
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "WFLUSH on deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, WFLUSH) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command failed\n");
+ } else
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command\n");
}
/*
- ** sort out the line discipline
- */
- if (PortP->CookMode == COOK_WELL)
- goto start;
- break;
-
- case T_RESUME:
- rio_dprintk (RIO_DEBUG_INTR, "T_RESUME\n");
- /*
- ** send pre-emptive resume packet
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "RESUME on deleted RTA\n");
+ ** WFLUSH operation - flush the data!
+ */
+ PortP->TxBufferIn = PortP->TxBufferOut = 0;
+ } else {
+ rio_dprintk(RIO_DEBUG_INTR, "T_WFLUSH Command ignored\n");
+ }
+ /*
+ ** sort out the line discipline
+ */
+ if (PortP->CookMode == COOK_WELL)
+ goto start;
+ break;
+
+ case T_RESUME:
+ rio_dprintk(RIO_DEBUG_INTR, "T_RESUME\n");
+ /*
+ ** send pre-emptive resume packet
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "RESUME on deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, RESUME) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_RESUME Command failed\n");
}
- else {
- if ( RIOPreemptiveCmd(p, PortP, RESUME ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_RESUME Command failed\n");
- }
+ }
+ /*
+ ** and re-start the sender software!
+ */
+ if (PortP->CookMode == COOK_WELL)
+ goto start;
+ break;
+
+ case T_TIME:
+ rio_dprintk(RIO_DEBUG_INTR, "T_TIME\n");
+ /*
+ ** T_TIME is called when xDLY is set in oflags and
+ ** the line discipline timeout has expired. It's
+ ** function in life is to clear the TIMEOUT flag
+ ** and to re-start output to the port.
+ */
+ /*
+ ** Fall through and re-start output
+ */
+ case T_OUTPUT:
+ start:
+ if (PortP->MagicFlags & MAGIC_FLUSH) {
+ PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ return 0;
+ }
+ RIOTxEnable((char *) PortP);
+ PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+ /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n"); */
+ break;
+
+ case T_SUSPEND:
+ rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND\n");
+ /*
+ ** send a suspend pre-emptive packet.
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, SUSPEND) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");
}
- /*
- ** and re-start the sender software!
- */
- if (PortP->CookMode == COOK_WELL)
- goto start;
- break;
-
- case T_TIME:
- rio_dprintk (RIO_DEBUG_INTR, "T_TIME\n");
- /*
- ** T_TIME is called when xDLY is set in oflags and
- ** the line discipline timeout has expired. It's
- ** function in life is to clear the TIMEOUT flag
- ** and to re-start output to the port.
- */
- /*
- ** Fall through and re-start output
- */
- case T_OUTPUT:
-start:
- if ( PortP->MagicFlags & MAGIC_FLUSH ) {
- PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+ }
+ /*
+ ** done!
+ */
+ break;
+
+ case T_BLOCK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_BLOCK\n");
+ break;
+
+ case T_RFLUSH:
+ rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");
+ PortP->RxDataStart = 0;
+ } else {
+ if (RIOPreemptiveCmd(p, PortP, RFLUSH) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");
return 0;
}
- RIOTxEnable((char *)PortP);
- PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
- /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"T_OUTPUT finished\n");*/
- break;
-
- case T_SUSPEND:
- rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND\n");
- /*
- ** send a suspend pre-emptive packet.
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "SUSPEND deleted RTA\n");
- }
- else {
- if ( RIOPreemptiveCmd(p, PortP, SUSPEND ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_SUSPEND Command failed\n");
- }
+ PortP->RxDataStart = 0;
+ while (can_remove_receive(&PacketP, PortP)) {
+ remove_receive(PortP);
+ ShowPacket(DBG_PROC, PacketP);
+ put_free_end(PortP->HostP, PacketP);
}
- /*
- ** done!
- */
- break;
-
- case T_BLOCK:
- rio_dprintk (RIO_DEBUG_INTR, "T_BLOCK\n");
- break;
-
- case T_RFLUSH:
- rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH\n");
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "RFLUSH on deleted RTA\n");
- PortP->RxDataStart = 0;
- }
- else {
- if ( RIOPreemptiveCmd( p, PortP, RFLUSH ) == RIO_FAIL ) {
- rio_dprintk (RIO_DEBUG_INTR, "T_RFLUSH Command failed\n");
- return 0;
- }
- PortP->RxDataStart = 0;
- while ( can_remove_receive(&PacketP, PortP) ) {
- remove_receive(PortP);
- ShowPacket(DBG_PROC, PacketP );
- put_free_end(PortP->HostP, PacketP );
- }
- if ( PortP->PhbP->handshake == PHB_HANDSHAKE_SET ) {
- /*
- ** MAGIC!
- */
- rio_dprintk (RIO_DEBUG_INTR, "Set receive handshake bit\n");
- PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
- }
- }
- break;
- /* FALLTHROUGH */
- case T_UNBLOCK:
- rio_dprintk (RIO_DEBUG_INTR, "T_UNBLOCK\n");
- /*
- ** If there is any data to receive set a timeout to service it.
- */
- RIOReceive(p, PortP);
- break;
-
- case T_BREAK:
- rio_dprintk (RIO_DEBUG_INTR, "T_BREAK\n");
- /*
- ** Send a break command. For Sys V
- ** this is a timed break, so we
- ** send a SBREAK[time] packet
- */
- /*
- ** Build a BREAK command
- */
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_INTR, "BREAK on deleted RTA\n");
+ if (PortP->PhbP->handshake == PHB_HANDSHAKE_SET) {
+ /*
+ ** MAGIC!
+ */
+ rio_dprintk(RIO_DEBUG_INTR, "Set receive handshake bit\n");
+ PortP->PhbP->handshake |= PHB_HANDSHAKE_RESET;
}
- else {
- if (RIOShortCommand(PortP,SBREAK,2,
- p->RIOConf.BreakInterval)==RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
- }
+ }
+ break;
+ /* FALLTHROUGH */
+ case T_UNBLOCK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_UNBLOCK\n");
+ /*
+ ** If there is any data to receive set a timeout to service it.
+ */
+ RIOReceive(p, PortP);
+ break;
+
+ case T_BREAK:
+ rio_dprintk(RIO_DEBUG_INTR, "T_BREAK\n");
+ /*
+ ** Send a break command. For Sys V
+ ** this is a timed break, so we
+ ** send a SBREAK[time] packet
+ */
+ /*
+ ** Build a BREAK command
+ */
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_INTR, "BREAK on deleted RTA\n");
+ } else {
+ if (RIOShortCommand(PortP, SBREAK, 2, p->RIOConf.BreakInterval) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
}
-
- /*
- ** done!
- */
- break;
-
- case T_INPUT:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");
- break;
- case T_PARM:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");
- break;
-
- case T_SWTCH:
- rio_dprintk (RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");
- break;
-
- default:
- rio_dprintk (RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n",cmd);
+ }
+
+ /*
+ ** done!
+ */
+ break;
+
+ case T_INPUT:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_INPUT called - I don't know what to do!\n");
+ break;
+ case T_PARM:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_PARM called - I don't know what to do!\n");
+ break;
+
+ case T_SWTCH:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc T_SWTCH called - I don't know what to do!\n");
+ break;
+
+ default:
+ rio_dprintk(RIO_DEBUG_INTR, "Proc UNKNOWN command %d\n", cmd);
}
/*
- ** T_OUTPUT returns without passing through this point!
- */
- /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n");*/
- return(0);
+ ** T_OUTPUT returns without passing through this point!
+ */
+ /*rio_dprint(RIO_DEBUG_INTR, PortP,DBG_PROC,"riotproc done\n"); */
+ return (0);
}
#endif
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
index c3d679733c9a..14b83fae75c8 100644
--- a/drivers/char/rio/rioioctl.h
+++ b/drivers/char/rio/rioioctl.h
@@ -42,14 +42,14 @@ static char *_rioioctl_h_sccs_ = "@(#)rioioctl.h 1.2";
*/
struct portStats {
- int port;
- int gather;
- ulong txchars;
- ulong rxchars;
- ulong opens;
- ulong closes;
- ulong ioctls;
-};
+ int port;
+ int gather;
+ ulong txchars;
+ ulong rxchars;
+ ulong opens;
+ ulong closes;
+ ulong ioctls;
+};
#define rIOC ('r'<<8)
@@ -100,4 +100,4 @@ struct portStats {
#define RIO_RESET_PORT_STATS (RIOC | 194)
#define RIO_GET_PORT_STATS (RIOC | 195)
-#endif /* __rioioctl_h__ */
+#endif /* __rioioctl_h__ */
diff --git a/drivers/char/rio/riolocks.h b/drivers/char/rio/riolocks.h
deleted file mode 100644
index 0e0cdacebe0b..000000000000
--- a/drivers/char/rio/riolocks.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : riolocks.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:13
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riolocks.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riolocks_h__
-#define __rio_riolocks_h__
-
-#ifdef SCCS_LABELS
-static char *_riolocks_h_sccs_ = "@(#)riolocks.h 1.2";
-#endif
-
-#define LOCKB(lk) lockb(lk);
-#define UNLOCKB(lk, oldspl) unlockb(lk, oldspl);
-
-#endif
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
index f10916326ecc..c622f46d6d77 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -157,295 +157,253 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3";
** NB. for MPX
** tty lock must NOT have been previously acquired.
*/
-int
-RIOParam(PortP, cmd, Modem, SleepFlag)
+int RIOParam(PortP, cmd, Modem, SleepFlag)
struct Port *PortP;
int cmd;
int Modem;
-int SleepFlag;
+int SleepFlag;
{
register struct tty_struct *TtyP;
- int retval;
+ int retval;
register struct phb_param *phb_param_ptr;
PKT *PacketP;
int res;
- uchar Cor1=0, Cor2=0, Cor4=0, Cor5=0;
- uchar TxXon=0, TxXoff=0, RxXon=0, RxXoff=0;
- uchar LNext=0, TxBaud=0, RxBaud=0;
- int retries = 0xff;
+ uchar Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
+ uchar TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
+ uchar LNext = 0, TxBaud = 0, RxBaud = 0;
+ int retries = 0xff;
unsigned long flags;
- func_enter ();
+ func_enter();
TtyP = PortP->gs.tty;
- rio_dprintk (RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n",
- PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
+ rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
if (!TtyP) {
- rio_dprintk (RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
- func_exit ();
+ func_exit();
- return RIO_FAIL;
+ return RIO_FAIL;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags );
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
if (cmd == OPEN) {
/*
- ** If the port is set to store or lock the parameters, and it is
- ** paramed with OPEN, we want to restore the saved port termio, but
- ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
- */
-#if 0
- if (PortP->FirstOpen) {
- PortP->StoredTty.iflag = TtyP->tm.c_iflag;
- PortP->StoredTty.oflag = TtyP->tm.c_oflag;
- PortP->StoredTty.cflag = TtyP->tm.c_cflag;
- PortP->StoredTty.lflag = TtyP->tm.c_lflag;
- PortP->StoredTty.line = TtyP->tm.c_line;
- for (i = 0; i < NCC + 5; i++)
- PortP->StoredTty.cc[i] = TtyP->tm.c_cc[i];
- PortP->FirstOpen = 0;
- }
- else if (PortP->Store || PortP->Lock) {
- rio_dprintk (RIO_DEBUG_PARAM, "OPEN: Restoring stored/locked params\n");
- TtyP->tm.c_iflag = PortP->StoredTty.iflag;
- TtyP->tm.c_oflag = PortP->StoredTty.oflag;
- TtyP->tm.c_cflag = PortP->StoredTty.cflag;
- TtyP->tm.c_lflag = PortP->StoredTty.lflag;
- TtyP->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 5; i++)
- TtyP->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
-#endif
+ ** If the port is set to store or lock the parameters, and it is
+ ** paramed with OPEN, we want to restore the saved port termio, but
+ ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
+ */
}
/*
- ** wait for space
- */
- while ( !(res=can_add_transmit(&PacketP,PortP)) ||
- (PortP->InUse != NOT_INUSE) ) {
- if (retries -- <= 0) {
+ ** wait for space
+ */
+ while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
+ if (retries-- <= 0) {
break;
}
- if ( PortP->InUse != NOT_INUSE ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
+ if (PortP->InUse != NOT_INUSE) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
}
- if ( !res ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
+ if (!res) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
}
- if ( SleepFlag != OK_TO_SLEEP ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ if (SleepFlag != OK_TO_SLEEP) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
func_exit();
-
+
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
retval = RIODelay(PortP, HUNDRED_MS);
- rio_spin_lock_irqsave( &PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
if (retval == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
pseterr(EINTR);
func_exit();
return RIO_FAIL;
}
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ if (PortP->State & RIO_DELETED) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_SUCCESS;
}
}
if (!res) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_FAIL;
}
- rio_dprintk (RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n",res);
- rio_dprintk (RIO_DEBUG_PARAM, "Packet is 0x%x\n",(int) PacketP);
+ rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
+ rio_dprintk(RIO_DEBUG_PARAM, "Packet is 0x%x\n", (int) PacketP);
- phb_param_ptr = (struct phb_param *)PacketP->data;
+ phb_param_ptr = (struct phb_param *) PacketP->data;
-#if 0
- /*
- ** COR 1
- */
- if ( TtyP->tm.c_iflag & INPCK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Parity checking on input enabled\n");
- Cor1 |= COR1_INPCK;
- }
-#endif
-
- switch ( TtyP->termios->c_cflag & CSIZE ) {
- case CS5:
+ switch (TtyP->termios->c_cflag & CSIZE) {
+ case CS5:
{
- rio_dprintk (RIO_DEBUG_PARAM, "5 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
Cor1 |= COR1_5BITS;
break;
}
- case CS6:
+ case CS6:
{
- rio_dprintk (RIO_DEBUG_PARAM, "6 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
Cor1 |= COR1_6BITS;
break;
}
- case CS7:
+ case CS7:
{
- rio_dprintk (RIO_DEBUG_PARAM, "7 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
Cor1 |= COR1_7BITS;
break;
}
- case CS8:
+ case CS8:
{
- rio_dprintk (RIO_DEBUG_PARAM, "8 bit data\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
Cor1 |= COR1_8BITS;
break;
}
}
- if ( TtyP->termios->c_cflag & CSTOPB ) {
- rio_dprintk (RIO_DEBUG_PARAM, "2 stop bits\n");
+ if (TtyP->termios->c_cflag & CSTOPB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
Cor1 |= COR1_2STOP;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "1 stop bit\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
Cor1 |= COR1_1STOP;
}
- if ( TtyP->termios->c_cflag & PARENB ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable parity\n");
+ if (TtyP->termios->c_cflag & PARENB) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
Cor1 |= COR1_NORMAL;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Disable parity\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
Cor1 |= COR1_NOP;
}
- if ( TtyP->termios->c_cflag & PARODD ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Odd parity\n");
+ if (TtyP->termios->c_cflag & PARODD) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
Cor1 |= COR1_ODD;
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Even parity\n");
- Cor1 |= COR1_EVEN;
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
+ Cor1 |= COR1_EVEN;
}
/*
- ** COR 2
- */
- if ( TtyP->termios->c_iflag & IXON ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop output control\n");
+ ** COR 2
+ */
+ if (TtyP->termios->c_iflag & IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
Cor2 |= COR2_IXON;
- }
- else {
- if ( PortP->Config & RIO_IXON ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
+ } else {
+ if (PortP->Config & RIO_IXON) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
Cor2 |= COR2_IXON;
- }
- else
- rio_dprintk (RIO_DEBUG_PARAM, "IXON has been disabled.\n");
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
}
if (TtyP->termios->c_iflag & IXANY) {
- if ( PortP->Config & RIO_IXANY ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable any key to restart output\n");
+ if (PortP->Config & RIO_IXANY) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
Cor2 |= COR2_IXANY;
- }
- else
- rio_dprintk (RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
+ } else
+ rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
}
- if ( TtyP->termios->c_iflag & IXOFF ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
+ if (TtyP->termios->c_iflag & IXOFF) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
Cor2 |= COR2_IXOFF;
}
- if ( TtyP->termios->c_cflag & HUPCL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Hangup on last close\n");
+ if (TtyP->termios->c_cflag & HUPCL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
Cor2 |= COR2_HUPCL;
}
- if ( C_CRTSCTS (TtyP)) {
- rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
+ if (C_CRTSCTS(TtyP)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
Cor2 |= COR2_CTSFLOW;
Cor2 |= COR2_RTSFLOW;
} else {
- rio_dprintk (RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
Cor2 &= ~COR2_CTSFLOW;
Cor2 &= ~COR2_RTSFLOW;
}
- if ( TtyP->termios->c_cflag & CLOCAL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Local line\n");
- }
- else {
- rio_dprintk (RIO_DEBUG_PARAM, "Possible Modem line\n");
+ if (TtyP->termios->c_cflag & CLOCAL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
+ } else {
+ rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
}
/*
- ** COR 4 (there is no COR 3)
- */
- if ( TtyP->termios->c_iflag & IGNBRK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore break condition\n");
+ ** COR 4 (there is no COR 3)
+ */
+ if (TtyP->termios->c_iflag & IGNBRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
Cor4 |= COR4_IGNBRK;
}
- if ( !(TtyP->termios->c_iflag & BRKINT) ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Break generates NULL condition\n");
+ if (!(TtyP->termios->c_iflag & BRKINT)) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
Cor4 |= COR4_NBRKINT;
} else {
- rio_dprintk (RIO_DEBUG_PARAM, "Interrupt on break condition\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on break condition\n");
}
- if ( TtyP->termios->c_iflag & INLCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
+ if (TtyP->termios->c_iflag & INLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
Cor4 |= COR4_INLCR;
}
- if ( TtyP->termios->c_iflag & IGNCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
+ if (TtyP->termios->c_iflag & IGNCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
Cor4 |= COR4_IGNCR;
}
- if ( TtyP->termios->c_iflag & ICRNL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
+ if (TtyP->termios->c_iflag & ICRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
Cor4 |= COR4_ICRNL;
}
- if ( TtyP->termios->c_iflag & IGNPAR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
+ if (TtyP->termios->c_iflag & IGNPAR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
Cor4 |= COR4_IGNPAR;
}
- if ( TtyP->termios->c_iflag & PARMRK ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Mark parity errors\n");
+ if (TtyP->termios->c_iflag & PARMRK) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
Cor4 |= COR4_PARMRK;
}
/*
- ** Set the RAISEMOD flag to ensure that the modem lines are raised
- ** on reception of a config packet.
- ** The download code handles the zero baud condition.
- */
+ ** Set the RAISEMOD flag to ensure that the modem lines are raised
+ ** on reception of a config packet.
+ ** The download code handles the zero baud condition.
+ */
Cor4 |= COR4_RAISEMOD;
/*
- ** COR 5
- */
+ ** COR 5
+ */
Cor5 = COR5_CMOE;
/*
- ** Set to monitor tbusy/tstop (or not).
- */
+ ** Set to monitor tbusy/tstop (or not).
+ */
if (PortP->MonitorTstate)
Cor5 |= COR5_TSTATE_ON;
@@ -453,182 +411,183 @@ int SleepFlag;
Cor5 |= COR5_TSTATE_OFF;
/*
- ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
- */
- if ( TtyP->termios->c_iflag & ISTRIP ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Strip input characters\n");
- if (! (PortP->State & RIO_TRIAD_MODE)) {
+ ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+ */
+ if (TtyP->termios->c_iflag & ISTRIP) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
+ if (!(PortP->State & RIO_TRIAD_MODE)) {
Cor5 |= COR5_ISTRIP;
}
}
- if ( TtyP->termios->c_oflag & ONLCR ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if (TtyP->termios->c_oflag & ONLCR) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_ONLCR;
}
- if ( TtyP->termios->c_oflag & OCRNL ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if (TtyP->termios->c_oflag & OCRNL) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_OCRNL;
}
- if ( ( TtyP->termios->c_oflag & TABDLY) == TAB3 ) {
- rio_dprintk (RIO_DEBUG_PARAM, "Tab delay 3 set\n");
- if ( PortP->CookMode == COOK_MEDIUM )
+ if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
+ rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
+ if (PortP->CookMode == COOK_MEDIUM)
Cor5 |= COR5_TAB3;
}
/*
- ** Flow control bytes.
- */
+ ** Flow control bytes.
+ */
TxXon = TtyP->termios->c_cc[VSTART];
TxXoff = TtyP->termios->c_cc[VSTOP];
RxXon = TtyP->termios->c_cc[VSTART];
RxXoff = TtyP->termios->c_cc[VSTOP];
/*
- ** LNEXT byte
- */
+ ** LNEXT byte
+ */
LNext = 0;
/*
- ** Baud rate bytes
- */
- rio_dprintk (RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n",
- TtyP->termios->c_cflag, CBAUD);
+ ** Baud rate bytes
+ */
+ rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
switch (TtyP->termios->c_cflag & CBAUD) {
#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
- e(50);e(75);e(110);e(134);e(150);e(200);e(300);e(600);e(1200);
- e(1800);e(2400);e(4800);e(9600);e(19200);e(38400);e(57600);
- e(115200); /* e(230400);e(460800); e(921600); */
+ e(50);
+ e(75);
+ e(110);
+ e(134);
+ e(150);
+ e(200);
+ e(300);
+ e(600);
+ e(1200);
+ e(1800);
+ e(2400);
+ e(4800);
+ e(9600);
+ e(19200);
+ e(38400);
+ e(57600);
+ e(115200); /* e(230400);e(460800); e(921600); */
}
/* XXX MIssing conversion table. XXX */
- /* (TtyP->termios->c_cflag & V_CBAUD); */
+ /* (TtyP->termios->c_cflag & V_CBAUD); */
- rio_dprintk (RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
+ rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
/*
- ** Leftovers
- */
- if ( TtyP->termios->c_cflag & CREAD )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable receiver\n");
+ ** Leftovers
+ */
+ if (TtyP->termios->c_cflag & CREAD)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
#ifdef RCV1EN
- if ( TtyP->termios->c_cflag & RCV1EN )
- rio_dprintk (RIO_DEBUG_PARAM, "RCV1EN (?)\n");
+ if (TtyP->termios->c_cflag & RCV1EN)
+ rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
#endif
#ifdef XMT1EN
- if ( TtyP->termios->c_cflag & XMT1EN )
- rio_dprintk (RIO_DEBUG_PARAM, "XMT1EN (?)\n");
-#endif
-#if 0
- if ( TtyP->termios->c_cflag & LOBLK )
- rio_dprintk (RIO_DEBUG_PARAM, "LOBLK - JCL output blocks when not current\n");
+ if (TtyP->termios->c_cflag & XMT1EN)
+ rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
#endif
- if ( TtyP->termios->c_lflag & ISIG )
- rio_dprintk (RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
- if ( TtyP->termios->c_lflag & ICANON )
- rio_dprintk (RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
- if ( TtyP->termios->c_lflag & XCASE )
- rio_dprintk (RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
- if ( TtyP->termios->c_lflag & ECHO )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable input echo\n");
- if ( TtyP->termios->c_lflag & ECHOE )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo erase\n");
- if ( TtyP->termios->c_lflag & ECHOK )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo kill\n");
- if ( TtyP->termios->c_lflag & ECHONL )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable echo newline\n");
- if ( TtyP->termios->c_lflag & NOFLSH )
- rio_dprintk (RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
+ if (TtyP->termios->c_lflag & ISIG)
+ rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
+ if (TtyP->termios->c_lflag & ICANON)
+ rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
+ if (TtyP->termios->c_lflag & XCASE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
+ if (TtyP->termios->c_lflag & ECHO)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
+ if (TtyP->termios->c_lflag & ECHOE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
+ if (TtyP->termios->c_lflag & ECHOK)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
+ if (TtyP->termios->c_lflag & ECHONL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
+ if (TtyP->termios->c_lflag & NOFLSH)
+ rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
#ifdef TOSTOP
- if ( TtyP->termios->c_lflag & TOSTOP )
- rio_dprintk (RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
+ if (TtyP->termios->c_lflag & TOSTOP)
+ rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
#endif
#ifdef XCLUDE
- if ( TtyP->termios->c_lflag & XCLUDE )
- rio_dprintk (RIO_DEBUG_PARAM, "Exclusive use of this line\n");
-#endif
- if ( TtyP->termios->c_iflag & IUCLC )
- rio_dprintk (RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
- if ( TtyP->termios->c_oflag & OPOST )
- rio_dprintk (RIO_DEBUG_PARAM, "Enable output post-processing\n");
- if ( TtyP->termios->c_oflag & OLCUC )
- rio_dprintk (RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
- if ( TtyP->termios->c_oflag & ONOCR )
- rio_dprintk (RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
- if ( TtyP->termios->c_oflag & ONLRET )
- rio_dprintk (RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
- if ( TtyP->termios->c_oflag & OFILL )
- rio_dprintk (RIO_DEBUG_PARAM, "Use fill characters for delay\n");
- if ( TtyP->termios->c_oflag & OFDEL )
- rio_dprintk (RIO_DEBUG_PARAM, "Fill character is DEL\n");
- if ( TtyP->termios->c_oflag & NLDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Newline delay set\n");
- if ( TtyP->termios->c_oflag & CRDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Carriage return delay set\n");
- if ( TtyP->termios->c_oflag & TABDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Tab delay set\n");
-#if 0
- if ( TtyP->termios->c_oflag & BSDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Back-space delay set\n");
- if ( TtyP->termios->c_oflag & VTDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Vertical tab delay set\n");
- if ( TtyP->termios->c_oflag & FFDLY )
- rio_dprintk (RIO_DEBUG_PARAM, "Form-feed delay set\n");
+ if (TtyP->termios->c_lflag & XCLUDE)
+ rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
#endif
+ if (TtyP->termios->c_iflag & IUCLC)
+ rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
+ if (TtyP->termios->c_oflag & OPOST)
+ rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
+ if (TtyP->termios->c_oflag & OLCUC)
+ rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
+ if (TtyP->termios->c_oflag & ONOCR)
+ rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
+ if (TtyP->termios->c_oflag & ONLRET)
+ rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
+ if (TtyP->termios->c_oflag & OFILL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
+ if (TtyP->termios->c_oflag & OFDEL)
+ rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
+ if (TtyP->termios->c_oflag & NLDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
+ if (TtyP->termios->c_oflag & CRDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
+ if (TtyP->termios->c_oflag & TABDLY)
+ rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
/*
- ** These things are kind of useful in a later life!
- */
+ ** These things are kind of useful in a later life!
+ */
PortP->Cor2Copy = Cor2;
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
- func_exit ();
+ if (PortP->State & RIO_DELETED) {
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
return RIO_FAIL;
}
/*
- ** Actually write the info into the packet to be sent
- */
- WBYTE(phb_param_ptr->Cmd, cmd);
- WBYTE(phb_param_ptr->Cor1, Cor1);
- WBYTE(phb_param_ptr->Cor2, Cor2);
- WBYTE(phb_param_ptr->Cor4, Cor4);
- WBYTE(phb_param_ptr->Cor5, Cor5);
- WBYTE(phb_param_ptr->TxXon, TxXon);
- WBYTE(phb_param_ptr->RxXon, RxXon);
+ ** Actually write the info into the packet to be sent
+ */
+ WBYTE(phb_param_ptr->Cmd, cmd);
+ WBYTE(phb_param_ptr->Cor1, Cor1);
+ WBYTE(phb_param_ptr->Cor2, Cor2);
+ WBYTE(phb_param_ptr->Cor4, Cor4);
+ WBYTE(phb_param_ptr->Cor5, Cor5);
+ WBYTE(phb_param_ptr->TxXon, TxXon);
+ WBYTE(phb_param_ptr->RxXon, RxXon);
WBYTE(phb_param_ptr->TxXoff, TxXoff);
WBYTE(phb_param_ptr->RxXoff, RxXoff);
- WBYTE(phb_param_ptr->LNext, LNext);
+ WBYTE(phb_param_ptr->LNext, LNext);
WBYTE(phb_param_ptr->TxBaud, TxBaud);
WBYTE(phb_param_ptr->RxBaud, RxBaud);
/*
- ** Set the length/command field
- */
- WBYTE(PacketP->len , 12 | PKT_CMD_BIT);
+ ** Set the length/command field
+ */
+ WBYTE(PacketP->len, 12 | PKT_CMD_BIT);
/*
- ** The packet is formed - now, whack it off
- ** to its final destination:
- */
+ ** The packet is formed - now, whack it off
+ ** to its final destination:
+ */
add_transmit(PortP);
/*
- ** Count characters transmitted for port statistics reporting
- */
+ ** Count characters transmitted for port statistics reporting
+ */
if (PortP->statsGather)
PortP->txchars += 12;
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_PARAM, "add_transmit returned.\n");
+ rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
/*
- ** job done.
- */
- func_exit ();
+ ** job done.
+ */
+ func_exit();
return RIO_SUCCESS;
}
@@ -638,16 +597,15 @@ int SleepFlag;
** We can add another packet to a transmit queue if the packet pointer pointed
** to by the TxAdd pointer has PKT_IN_USE clear in its address.
*/
-int
-can_add_transmit(PktP, PortP)
+int can_add_transmit(PktP, PortP)
PKT **PktP;
-struct Port *PortP;
+struct Port *PortP;
{
register PKT *tp;
- *PktP = tp = (PKT *)RIO_PTR(PortP->Caddr,RWORD(*PortP->TxAdd));
+ *PktP = tp = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->TxAdd));
- return !((uint)tp & PKT_IN_USE);
+ return !((uint) tp & PKT_IN_USE);
}
/*
@@ -655,25 +613,22 @@ struct Port *PortP;
** and then move the TxAdd pointer along one position to point to the next
** packet pointer. You must wrap the pointer from the end back to the start.
*/
-void
-add_transmit(PortP)
-struct Port *PortP;
+void add_transmit(PortP)
+struct Port *PortP;
{
- if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
- rio_dprintk (RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
- }
- WWORD( *(ushort *)PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
- PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart :
- PortP->TxAdd + 1;
- WWORD( PortP->PhbP->tx_add , RIO_OFF(PortP->Caddr,PortP->TxAdd) );
+ if (RWORD(*PortP->TxAdd) & PKT_IN_USE) {
+ rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
+ }
+ WWORD(*(ushort *) PortP->TxAdd, RWORD(*PortP->TxAdd) | PKT_IN_USE);
+ PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
+ WWORD(PortP->PhbP->tx_add, RIO_OFF(PortP->Caddr, PortP->TxAdd));
}
/****************************************
* Put a packet onto the end of the
* free list
****************************************/
-void
-put_free_end(HostP, PktP)
+void put_free_end(HostP, PktP)
struct Host *HostP;
PKT *PktP;
{
@@ -688,24 +643,23 @@ PKT *PktP;
*
************************************************/
- rio_dprintk (RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n",(int)PktP);
+ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%x)\n", (int) PktP);
- if ((old_end=RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
- new_end = RIO_OFF(HostP->Caddr,PktP);
- tmp_pointer = (FREE_LIST *)RIO_PTR(HostP->Caddr,old_end);
- WWORD(tmp_pointer->next , new_end );
- WWORD(((FREE_LIST *)PktP)->prev , old_end);
- WWORD(((FREE_LIST *)PktP)->next , TPNULL);
+ if ((old_end = RWORD(HostP->ParmMapP->free_list_end)) != TPNULL) {
+ new_end = RIO_OFF(HostP->Caddr, PktP);
+ tmp_pointer = (FREE_LIST *) RIO_PTR(HostP->Caddr, old_end);
+ WWORD(tmp_pointer->next, new_end);
+ WWORD(((FREE_LIST *) PktP)->prev, old_end);
+ WWORD(((FREE_LIST *) PktP)->next, TPNULL);
WWORD(HostP->ParmMapP->free_list_end, new_end);
- }
- else { /* First packet on the free list this should never happen! */
- rio_dprintk (RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
- WWORD(HostP->ParmMapP->free_list_end , RIO_OFF(HostP->Caddr,PktP));
- tmp_pointer = (FREE_LIST *)PktP;
- WWORD(tmp_pointer->prev , TPNULL);
- WWORD(tmp_pointer->next , TPNULL);
- }
- rio_dprintk (RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
+ } else { /* First packet on the free list this should never happen! */
+ rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
+ WWORD(HostP->ParmMapP->free_list_end, RIO_OFF(HostP->Caddr, PktP));
+ tmp_pointer = (FREE_LIST *) PktP;
+ WWORD(tmp_pointer->prev, TPNULL);
+ WWORD(tmp_pointer->next, TPNULL);
+ }
+ rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
}
@@ -715,14 +669,12 @@ PKT *PktP;
** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
** then can_remove_receive() returns 0.
*/
-int
-can_remove_receive(PktP, PortP)
+int can_remove_receive(PktP, PortP)
PKT **PktP;
struct Port *PortP;
{
- if ( RWORD(*PortP->RxRemove) & PKT_IN_USE) {
- *PktP = (PKT *)RIO_PTR(PortP->Caddr,
- RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+ if (RWORD(*PortP->RxRemove) & PKT_IN_USE) {
+ *PktP = (PKT *) RIO_PTR(PortP->Caddr, RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
return 1;
}
return 0;
@@ -733,12 +685,10 @@ struct Port *PortP;
** and then bump the pointers. Once the pointers get to the end, they must
** be wrapped back to the start.
*/
-void
-remove_receive(PortP)
-struct Port *PortP;
+void remove_receive(PortP)
+struct Port *PortP;
{
- WWORD( *PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE );
- PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart :
- PortP->RxRemove + 1;
- WWORD( PortP->PhbP->rx_remove , RIO_OFF(PortP->Caddr, PortP->RxRemove) );
+ WWORD(*PortP->RxRemove, RWORD(*PortP->RxRemove) & ~PKT_IN_USE);
+ PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
+ WWORD(PortP->PhbP->rx_remove, RIO_OFF(PortP->Caddr, PortP->RxRemove));
}
diff --git a/drivers/char/rio/riopcicopy.c b/drivers/char/rio/riopcicopy.c
index 2ea99a60aa32..535afaa51ca5 100644
--- a/drivers/char/rio/riopcicopy.c
+++ b/drivers/char/rio/riopcicopy.c
@@ -1,8 +1,8 @@
/* Yeah. We have copyright on this one. Sure. */
-void rio_pcicopy( char *from, char *to, int amount)
+void rio_pcicopy(char *from, char *to, int amount)
{
- while ( amount-- )
- *to++ = *from++;
+ while (amount--)
+ *to++ = *from++;
}
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index e9564c9fb37c..f98888f52659 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -93,625 +93,505 @@ static void RIOConCon(struct rio_info *, struct Host *, uint, uint, uint, uint,
** Incoming on the ROUTE_RUP
** I wrote this while I was tired. Forgive me.
*/
-int RIORouteRup( struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP )
+int RIORouteRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT * PacketP)
{
- struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
- struct PktCmd_M *PktReplyP;
- struct CmdBlk *CmdBlkP;
- struct Port *PortP;
- struct Map *MapP;
- struct Top *TopP;
- int ThisLink, ThisLinkMin, ThisLinkMax;
- int port;
- int Mod, Mod1, Mod2;
- ushort RtaType;
- uint RtaUniq;
- uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */
- uint OldUnit, NewUnit, OldLink, NewLink;
- char *MyType, *MyName;
- int Lies;
- unsigned long flags;
-
-#ifdef STACK
- RIOStackCheck("RIORouteRup");
-#endif
-#ifdef CHECK
- CheckPacketP(PacketP);
- CheckHostP(HostP);
- CheckRup(Rup);
- CheckHost(Host);
-#endif
- /*
- ** Is this unit telling us it's current link topology?
- */
- if ( RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY )
- {
- MapP = HostP->Mapping;
-
- /*
- ** The packet can be sent either by the host or by an RTA.
- ** If it comes from the host, then we need to fill in the
- ** Topology array in the host structure. If it came in
- ** from an RTA then we need to fill in the Mapping structure's
- ** Topology array for the unit.
- */
- if ( Rup >= (ushort)MAX_RUP )
- {
- ThisUnit = HOST_ID;
- TopP = HostP->Topology;
- MyType = "Host";
- MyName = HostP->Name;
- ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
- }
- else
- {
- ThisUnit = Rup+1;
- TopP = HostP->Mapping[Rup].Topology;
- MyType = "RTA";
- MyName = HostP->Mapping[Rup].Name;
- ThisLinkMin = 0;
- ThisLinkMax = LINKS_PER_UNIT - 1;
- }
-
- /*
- ** Lies will not be tolerated.
- ** If any pair of links claim to be connected to the same
- ** place, then ignore this packet completely.
- */
- Lies = 0;
- for ( ThisLink=ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++)
- {
- /*
- ** it won't lie about network interconnect, total disconnects
- ** and no-IDs. (or at least, it doesn't *matter* if it does)
- */
- if ( RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort)MAX_RUP )
- continue;
-
- for ( NewLink=ThisLinkMin; NewLink < ThisLink; NewLink++ )
- {
- if ( (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) ==
- RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) &&
- (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) ==
- RBYTE(PktCmdP->RouteTopology[NewLink].Link)) )
- {
- Lies++;
- }
- }
- }
-
- if ( Lies )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n",Lies);
- rio_dprintk (RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
- RBYTE(PktCmdP->RouteTopology[0].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[0].Link),
- RBYTE(PktCmdP->RouteTopology[1].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[1].Link),
- RBYTE(PktCmdP->RouteTopology[2].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[2].Link),
- RBYTE(PktCmdP->RouteTopology[3].Unit),
- 'A'+RBYTE(PktCmdP->RouteTopology[3].Link));
- return TRUE;
- }
-
- /*
- ** now, process each link.
- */
- for ( ThisLink=ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++)
- {
- /*
- ** this is what it was connected to
- */
- OldUnit = TopP[ThisLink].Unit;
- OldLink = TopP[ThisLink].Link;
-
- /*
- ** this is what it is now connected to
- */
- NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
- NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
-
- if ( OldUnit != NewUnit || OldLink != NewLink )
- {
+ struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
+ struct PktCmd_M *PktReplyP;
+ struct CmdBlk *CmdBlkP;
+ struct Port *PortP;
+ struct Map *MapP;
+ struct Top *TopP;
+ int ThisLink, ThisLinkMin, ThisLinkMax;
+ int port;
+ int Mod, Mod1, Mod2;
+ ushort RtaType;
+ uint RtaUniq;
+ uint ThisUnit, ThisUnit2; /* 2 ids to accommodate 16 port RTA */
+ uint OldUnit, NewUnit, OldLink, NewLink;
+ char *MyType, *MyName;
+ int Lies;
+ unsigned long flags;
+
/*
- ** something has changed!
- */
-
- if ( NewUnit > MAX_RUP &&
- NewUnit != ROUTE_DISCONNECT &&
- NewUnit != ROUTE_NO_ID &&
- NewUnit != ROUTE_INTERCONNECT )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n",
- MyType,
- MyName,
- NewUnit,
- NewLink);
- }
- else
- {
- /*
- ** put the new values in
- */
- TopP[ThisLink].Unit = NewUnit;
- TopP[ThisLink].Link = NewLink;
-
- RIOSetChange(p);
-
- if ( OldUnit <= MAX_RUP )
- {
- /*
- ** If something has become bust, then re-enable them messages
- */
- if (! p->RIONoMessage)
- RIOConCon(p,HostP,ThisUnit,ThisLink,OldUnit,OldLink,DISCONNECT);
- }
-
- if ( ( NewUnit <= MAX_RUP ) && !p->RIONoMessage )
- RIOConCon(p,HostP,ThisUnit,ThisLink,NewUnit,NewLink,CONNECT);
-
- if ( NewUnit == ROUTE_NO_ID )
- rio_dprintk (RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n",
- MyType,MyName,'A'+ThisLink);
-
- if ( NewUnit == ROUTE_INTERCONNECT )
- {
- if (! p->RIONoMessage)
- cprintf("%s '%s' (%c) is connected to another network.\n", MyType,MyName,'A'+ThisLink);
- }
-
- /*
- ** perform an update for 'the other end', so that these messages
- ** only appears once. Only disconnect the other end if it is pointing
- ** at us!
- */
- if ( OldUnit == HOST_ID )
- {
- if ( HostP->Topology[OldLink].Unit == ThisUnit &&
- HostP->Topology[OldLink].Link == ThisLink )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink+'A');
- HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
- HostP->Topology[OldLink].Link = NO_LINK;
- }
- else
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n",
- OldLink+'A',HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
- }
- }
- else if ( OldUnit <= MAX_RUP )
- {
- if ( HostP->Mapping[OldUnit-1].Topology[OldLink].Unit == ThisUnit &&
- HostP->Mapping[OldUnit-1].Topology[OldLink].Link == ThisLink )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n",
- HostP->Mapping[OldUnit-1].Name,OldLink+'A');
- HostP->Mapping[OldUnit-1].Topology[OldLink].Unit=ROUTE_DISCONNECT;
- HostP->Mapping[OldUnit-1].Topology[OldLink].Link=NO_LINK;
- }
- else
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n",
- HostP->Mapping[OldUnit-1].Name,OldLink+'A',
- HostP->Mapping[ThisUnit-1].Name,ThisLink+'A');
- }
- }
- if ( NewUnit == HOST_ID )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n",
- NewLink+'A',MyName,ThisLink+'A');
- HostP->Topology[NewLink].Unit = ThisUnit;
- HostP->Topology[NewLink].Link = ThisLink;
- }
- else if ( NewUnit <= MAX_RUP )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n",
- HostP->Mapping[NewUnit-1].Name,NewLink+'A',MyName,ThisLink+'A');
- HostP->Mapping[NewUnit-1].Topology[NewLink].Unit=ThisUnit;
- HostP->Mapping[NewUnit-1].Topology[NewLink].Link=ThisLink;
- }
+ ** Is this unit telling us it's current link topology?
+ */
+ if (RBYTE(PktCmdP->Command) == ROUTE_TOPOLOGY) {
+ MapP = HostP->Mapping;
+
+ /*
+ ** The packet can be sent either by the host or by an RTA.
+ ** If it comes from the host, then we need to fill in the
+ ** Topology array in the host structure. If it came in
+ ** from an RTA then we need to fill in the Mapping structure's
+ ** Topology array for the unit.
+ */
+ if (Rup >= (ushort) MAX_RUP) {
+ ThisUnit = HOST_ID;
+ TopP = HostP->Topology;
+ MyType = "Host";
+ MyName = HostP->Name;
+ ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
+ } else {
+ ThisUnit = Rup + 1;
+ TopP = HostP->Mapping[Rup].Topology;
+ MyType = "RTA";
+ MyName = HostP->Mapping[Rup].Name;
+ ThisLinkMin = 0;
+ ThisLinkMax = LINKS_PER_UNIT - 1;
+ }
+
+ /*
+ ** Lies will not be tolerated.
+ ** If any pair of links claim to be connected to the same
+ ** place, then ignore this packet completely.
+ */
+ Lies = 0;
+ for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
+ /*
+ ** it won't lie about network interconnect, total disconnects
+ ** and no-IDs. (or at least, it doesn't *matter* if it does)
+ */
+ if (RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) > (ushort) MAX_RUP)
+ continue;
+
+ for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
+ if ((RBYTE(PktCmdP->RouteTopology[ThisLink].Unit) == RBYTE(PktCmdP->RouteTopology[NewLink].Unit)) && (RBYTE(PktCmdP->RouteTopology[ThisLink].Link) == RBYTE(PktCmdP->RouteTopology[NewLink].Link))) {
+ Lies++;
+ }
+ }
+ }
+
+ if (Lies) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
+ rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
+ RBYTE(PktCmdP->RouteTopology[0].Unit),
+ 'A' + RBYTE(PktCmdP->RouteTopology[0].Link),
+ RBYTE(PktCmdP->RouteTopology[1].Unit),
+ 'A' + RBYTE(PktCmdP->RouteTopology[1].Link), RBYTE(PktCmdP->RouteTopology[2].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[2].Link), RBYTE(PktCmdP->RouteTopology[3].Unit), 'A' + RBYTE(PktCmdP->RouteTopology[3].Link));
+ return TRUE;
+ }
+
+ /*
+ ** now, process each link.
+ */
+ for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
+ /*
+ ** this is what it was connected to
+ */
+ OldUnit = TopP[ThisLink].Unit;
+ OldLink = TopP[ThisLink].Link;
+
+ /*
+ ** this is what it is now connected to
+ */
+ NewUnit = RBYTE(PktCmdP->RouteTopology[ThisLink].Unit);
+ NewLink = RBYTE(PktCmdP->RouteTopology[ThisLink].Link);
+
+ if (OldUnit != NewUnit || OldLink != NewLink) {
+ /*
+ ** something has changed!
+ */
+
+ if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
+ } else {
+ /*
+ ** put the new values in
+ */
+ TopP[ThisLink].Unit = NewUnit;
+ TopP[ThisLink].Link = NewLink;
+
+ RIOSetChange(p);
+
+ if (OldUnit <= MAX_RUP) {
+ /*
+ ** If something has become bust, then re-enable them messages
+ */
+ if (!p->RIONoMessage)
+ RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
+ }
+
+ if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
+ RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
+
+ if (NewUnit == ROUTE_NO_ID)
+ rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
+
+ if (NewUnit == ROUTE_INTERCONNECT) {
+ if (!p->RIONoMessage)
+ cprintf("%s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
+ }
+
+ /*
+ ** perform an update for 'the other end', so that these messages
+ ** only appears once. Only disconnect the other end if it is pointing
+ ** at us!
+ */
+ if (OldUnit == HOST_ID) {
+ if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
+ HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
+ HostP->Topology[OldLink].Link = NO_LINK;
+ } else {
+ rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+ }
+ } else if (OldUnit <= MAX_RUP) {
+ if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
+ HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
+ HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
+ } else {
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+ }
+ }
+ if (NewUnit == HOST_ID) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
+ HostP->Topology[NewLink].Unit = ThisUnit;
+ HostP->Topology[NewLink].Link = ThisLink;
+ } else if (NewUnit <= MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
+ HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
+ HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
+ }
+ }
+ RIOSetChange(p);
+ RIOCheckIsolated(p, HostP, OldUnit);
+ }
+ }
+ return TRUE;
}
- RIOSetChange(p);
- RIOCheckIsolated(p, HostP, OldUnit );
- }
- }
- return TRUE;
- }
-
- /*
- ** The only other command we recognise is a route_request command
- */
- if ( RBYTE(PktCmdP->Command) != ROUTE_REQUEST )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n",
- RBYTE(PktCmdP->Command),Rup,(int)HostP);
- return TRUE;
- }
-
- RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) +
- (RBYTE(PktCmdP->UniqNum[1]) << 8) +
- (RBYTE(PktCmdP->UniqNum[2]) << 16) +
- (RBYTE(PktCmdP->UniqNum[3]) << 24);
-
- /*
- ** Determine if 8 or 16 port RTA
- */
- RtaType = GetUnitType(RtaUniq);
-
- rio_dprintk (RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
-
- Mod = RBYTE(PktCmdP->ModuleTypes);
- Mod1 = LONYBLE(Mod);
- if (RtaType == TYPE_RTA16)
- {
- /*
- ** Only one ident is set for a 16 port RTA. To make compatible
- ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
- */
- Mod2 = Mod1;
- rio_dprintk (RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n",
- p->RIOModuleTypes[Mod1].Name);
- }
- else
- {
- Mod2 = HINYBLE(Mod);
- rio_dprintk (RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n",
- p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
- }
-
- if ( RtaUniq == 0xffffffff )
- {
- ShowPacket( DBG_SPECIAL, PacketP );
- }
-
- /*
- ** try to unhook a command block from the command free list.
- */
- if ( !(CmdBlkP = RIOGetCmdBlk()) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
- return 0;
- }
-
- /*
- ** Fill in the default info on the command block
- */
- CmdBlkP->Packet.dest_unit = Rup;
- CmdBlkP->Packet.dest_port = ROUTE_RUP;
- CmdBlkP->Packet.src_unit = HOST_ID;
- CmdBlkP->Packet.src_port = ROUTE_RUP;
- CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
- CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
- PktReplyP = (struct PktCmd_M *)CmdBlkP->Packet.data;
-
- if (! RIOBootOk(p, HostP, RtaUniq))
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n",
- RtaUniq);
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
- RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
- return TRUE;
- }
-
- /*
- ** Check to see if the RTA is configured for this host
- */
- for ( ThisUnit=0; ThisUnit<MAX_RUP; ThisUnit++ )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
- ThisUnit,
- HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ?
- "Slot-In-Use":"Not In Use",
- HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ?
- "Slot-Tentative":"Not Tentative",
- HostP->Mapping[ThisUnit].RtaUniqueNum);
-
- /*
- ** We have an entry for it.
- */
- if ( (HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) &&
- (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq) )
- {
- if (RtaType == TYPE_RTA16)
- {
- ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
- rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n",
- RtaUniq,ThisUnit,ThisUnit2);
- }
- else
- rio_dprintk (RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n",
- RtaUniq,ThisUnit);
- /*
- ** If we have no knowledge of booting it, then the host has
- ** been re-booted, and so we must kill the RTA, so that it
- ** will be booted again (potentially with new bins)
- ** and it will then re-ask for an ID, which we will service.
- */
- if ( (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) &&
- !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED) )
- {
- if ( !(HostP->Mapping[ThisUnit].Flags & MSG_DONE) )
- {
- if ( !p->RIONoMessage )
- cprintf("RTA '%s' is being updated.\n",HostP->Mapping[ThisUnit].Name);
- HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+
+ /*
+ ** The only other command we recognise is a route_request command
+ */
+ if (RBYTE(PktCmdP->Command) != ROUTE_REQUEST) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %d ROUTE_RUP\n", RBYTE(PktCmdP->Command), Rup, (int) HostP);
+ return TRUE;
}
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
- RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
- return TRUE;
- }
-
- /*
- ** Send the ID (entry) to this RTA. The ID number is implicit as
- ** the offset into the table. It is worth noting at this stage
- ** that offset zero in the table contains the entries for the
- ** RTA with ID 1!!!!
- */
- PktReplyP->Command = ROUTE_ALLOCATE;
- PktReplyP->IDNum = ThisUnit+1;
- if (RtaType == TYPE_RTA16)
- {
- if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
- /*
- ** Adjust the phb and tx pkt dest_units for 2nd block of 8
- ** only if the RTA has ports associated (SLOT_IN_USE)
- */
- RIOFixPhbs(p, HostP, ThisUnit2);
- PktReplyP->IDNum2 = ThisUnit2+1;
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n",
- HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
- }
- else
- {
- PktReplyP->IDNum2 = ROUTE_NO_ID;
- rio_dprintk (RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n",
- HostP->Mapping[ThisUnit].Name,PktReplyP->IDNum);
- }
- HostP->Copy("RT_ALLOCAT",PktReplyP->CommandText,10);
-
- RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
-
- /*
- ** If this is a freshly booted RTA, then we need to re-open
- ** the ports, if any where open, so that data may once more
- ** flow around the system!
- */
- if ( (HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) &&
- (HostP->Mapping[ThisUnit].SysPort != NO_PORT) )
- {
+
+ RtaUniq = (RBYTE(PktCmdP->UniqNum[0])) + (RBYTE(PktCmdP->UniqNum[1]) << 8) + (RBYTE(PktCmdP->UniqNum[2]) << 16) + (RBYTE(PktCmdP->UniqNum[3]) << 24);
+
/*
- ** look at the ports associated with this beast and
- ** see if any where open. If they was, then re-open
- ** them, using the info from the tty flags.
- */
- for ( port=0; port<PORTS_PER_RTA; port++ )
- {
- PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort];
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->MagicFlags |= MAGIC_REBOOT;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
+ ** Determine if 8 or 16 port RTA
+ */
+ RtaType = GetUnitType(RtaUniq);
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
+
+ Mod = RBYTE(PktCmdP->ModuleTypes);
+ Mod1 = LONYBLE(Mod);
+ if (RtaType == TYPE_RTA16) {
+ /*
+ ** Only one ident is set for a 16 port RTA. To make compatible
+ ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
+ */
+ Mod2 = Mod1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
+ } else {
+ Mod2 = HINYBLE(Mod);
+ rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
}
- if (RtaType == TYPE_RTA16)
- {
- for ( port=0; port<PORTS_PER_RTA; port++ )
- {
- PortP = p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort];
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) )
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Re-opened this port\n");
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- PortP->MagicFlags |= MAGIC_REBOOT;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- }
- }
+
+ if (RtaUniq == 0xffffffff) {
+ ShowPacket(DBG_SPECIAL, PacketP);
}
- }
-
- /*
- ** keep a copy of the module types!
- */
- HostP->UnixRups[ThisUnit].ModTypes = Mod;
- if (RtaType == TYPE_RTA16)
- HostP->UnixRups[ThisUnit2].ModTypes = Mod;
-
- /*
- ** If either of the modules on this unit is read-only or write-only
- ** or none-xprint, then we need to transfer that info over to the
- ** relevant ports.
- */
- if ( HostP->Mapping[ThisUnit].SysPort != NO_PORT )
- {
- for ( port=0; port<PORTS_PER_MODULE; port++ )
- {
- p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+HostP->Mapping[ThisUnit].SysPort]->Config |=
- p->RIOModuleTypes[Mod1].Flags[port];
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+
+ /*
+ ** try to unhook a command block from the command free list.
+ */
+ if (!(CmdBlkP = RIOGetCmdBlk())) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
+ return 0;
}
- if (RtaType == TYPE_RTA16)
- {
- for ( port=0; port<PORTS_PER_MODULE; port++ )
- {
- p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
- p->RIOPortp[port+PORTS_PER_MODULE+HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
- }
+
+ /*
+ ** Fill in the default info on the command block
+ */
+ CmdBlkP->Packet.dest_unit = Rup;
+ CmdBlkP->Packet.dest_port = ROUTE_RUP;
+ CmdBlkP->Packet.src_unit = HOST_ID;
+ CmdBlkP->Packet.src_port = ROUTE_RUP;
+ CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
+ CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+ PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
+
+ if (!RIOBootOk(p, HostP, RtaUniq)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
}
- }
-
- /*
- ** Job done, get on with the interrupts!
- */
- return TRUE;
- }
- }
- /*
- ** There is no table entry for this RTA at all.
- **
- ** Lets check to see if we actually booted this unit - if not,
- ** then we reset it and it will go round the loop of being booted
- ** we can then worry about trying to fit it into the table.
- */
- for ( ThisUnit=0; ThisUnit<HostP->NumExtraBooted; ThisUnit++ )
- if ( HostP->ExtraUnits[ThisUnit] == RtaUniq )
- break;
- if ( ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS )
- {
- /*
- ** if the unit wasn't in the table, and the table wasn't full, then
- ** we reset the unit, because we didn't boot it.
- ** However, if the table is full, it could be that we did boot
- ** this unit, and so we won't reboot it, because it isn't really
- ** all that disasterous to keep the old bins in most cases. This
- ** is a rather tacky feature, but we are on the edge of reallity
- ** here, because the implication is that someone has connected
- ** 16+MAX_EXTRA_UNITS onto one host.
- */
- static int UnknownMesgDone = 0;
-
- if ( !UnknownMesgDone )
- {
- if (! p->RIONoMessage)
- cprintf("One or more unknown RTAs are being updated.\n");
- UnknownMesgDone = 1;
- }
-
- PktReplyP->Command = ROUTE_FOAD;
- HostP->Copy("RT_FOAD",PktReplyP->CommandText,7);
- }
- else
- {
- /*
- ** we did boot it (as an extra), and there may now be a table
- ** slot free (because of a delete), so we will try to make
- ** a tentative entry for it, so that the configurator can see it
- ** and fill in the details for us.
- */
- if (RtaType == TYPE_RTA16)
- {
- if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0)
- {
- RIODefaultName(p, HostP, ThisUnit);
- FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+
+ /*
+ ** Check to see if the RTA is configured for this host
+ */
+ for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
+ ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
+
+ /*
+ ** We have an entry for it.
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
+ if (RtaType == TYPE_RTA16) {
+ ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
+ } else
+ rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
+ /*
+ ** If we have no knowledge of booting it, then the host has
+ ** been re-booted, and so we must kill the RTA, so that it
+ ** will be booted again (potentially with new bins)
+ ** and it will then re-ask for an ID, which we will service.
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
+ if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
+ if (!p->RIONoMessage)
+ cprintf("RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
+ HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+ }
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
+ }
+
+ /*
+ ** Send the ID (entry) to this RTA. The ID number is implicit as
+ ** the offset into the table. It is worth noting at this stage
+ ** that offset zero in the table contains the entries for the
+ ** RTA with ID 1!!!!
+ */
+ PktReplyP->Command = ROUTE_ALLOCATE;
+ PktReplyP->IDNum = ThisUnit + 1;
+ if (RtaType == TYPE_RTA16) {
+ if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
+ /*
+ ** Adjust the phb and tx pkt dest_units for 2nd block of 8
+ ** only if the RTA has ports associated (SLOT_IN_USE)
+ */
+ RIOFixPhbs(p, HostP, ThisUnit2);
+ PktReplyP->IDNum2 = ThisUnit2 + 1;
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
+ } else {
+ PktReplyP->IDNum2 = ROUTE_NO_ID;
+ rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
+ }
+ HostP->Copy("RT_ALLOCAT", PktReplyP->CommandText, 10);
+
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+
+ /*
+ ** If this is a freshly booted RTA, then we need to re-open
+ ** the ports, if any where open, so that data may once more
+ ** flow around the system!
+ */
+ if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
+ /*
+ ** look at the ports associated with this beast and
+ ** see if any where open. If they was, then re-open
+ ** them, using the info from the tty flags.
+ */
+ for (port = 0; port < PORTS_PER_RTA; port++) {
+ PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->MagicFlags |= MAGIC_REBOOT;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ }
+ if (RtaType == TYPE_RTA16) {
+ for (port = 0; port < PORTS_PER_RTA; port++) {
+ PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ PortP->MagicFlags |= MAGIC_REBOOT;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ }
+ }
+ }
+ }
+
+ /*
+ ** keep a copy of the module types!
+ */
+ HostP->UnixRups[ThisUnit].ModTypes = Mod;
+ if (RtaType == TYPE_RTA16)
+ HostP->UnixRups[ThisUnit2].ModTypes = Mod;
+
+ /*
+ ** If either of the modules on this unit is read-only or write-only
+ ** or none-xprint, then we need to transfer that info over to the
+ ** relevant ports.
+ */
+ if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
+ for (port = 0; port < PORTS_PER_MODULE; port++) {
+ p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+ }
+ if (RtaType == TYPE_RTA16) {
+ for (port = 0; port < PORTS_PER_MODULE; port++) {
+ p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+ p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+ }
+ }
+ }
+
+ /*
+ ** Job done, get on with the interrupts!
+ */
+ return TRUE;
+ }
}
- }
- else
- {
- if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0)
- {
- RIODefaultName(p, HostP, ThisUnit);
- FillSlot(ThisUnit, 0, RtaUniq, HostP);
+ /*
+ ** There is no table entry for this RTA at all.
+ **
+ ** Lets check to see if we actually booted this unit - if not,
+ ** then we reset it and it will go round the loop of being booted
+ ** we can then worry about trying to fit it into the table.
+ */
+ for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
+ if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
+ break;
+ if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
+ /*
+ ** if the unit wasn't in the table, and the table wasn't full, then
+ ** we reset the unit, because we didn't boot it.
+ ** However, if the table is full, it could be that we did boot
+ ** this unit, and so we won't reboot it, because it isn't really
+ ** all that disasterous to keep the old bins in most cases. This
+ ** is a rather tacky feature, but we are on the edge of reallity
+ ** here, because the implication is that someone has connected
+ ** 16+MAX_EXTRA_UNITS onto one host.
+ */
+ static int UnknownMesgDone = 0;
+
+ if (!UnknownMesgDone) {
+ if (!p->RIONoMessage)
+ cprintf("One or more unknown RTAs are being updated.\n");
+ UnknownMesgDone = 1;
+ }
+
+ PktReplyP->Command = ROUTE_FOAD;
+ HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+ } else {
+ /*
+ ** we did boot it (as an extra), and there may now be a table
+ ** slot free (because of a delete), so we will try to make
+ ** a tentative entry for it, so that the configurator can see it
+ ** and fill in the details for us.
+ */
+ if (RtaType == TYPE_RTA16) {
+ if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
+ RIODefaultName(p, HostP, ThisUnit);
+ FillSlot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+ }
+ } else {
+ if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
+ RIODefaultName(p, HostP, ThisUnit);
+ FillSlot(ThisUnit, 0, RtaUniq, HostP);
+ }
+ }
+ PktReplyP->Command = ROUTE_USED;
+ HostP->Copy("RT_USED", PktReplyP->CommandText, 7);
}
- }
- PktReplyP->Command = ROUTE_USED;
- HostP->Copy("RT_USED",PktReplyP->CommandText,7);
- }
- RIOQueueCmdBlk( HostP, Rup, CmdBlkP);
- return TRUE;
+ RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+ return TRUE;
}
-void
-RIOFixPhbs(p, HostP, unit)
+void RIOFixPhbs(p, HostP, unit)
struct rio_info *p;
struct Host *HostP;
uint unit;
{
- ushort link, port;
- struct Port *PortP;
+ ushort link, port;
+ struct Port *PortP;
unsigned long flags;
int PortN = HostP->Mapping[unit].SysPort;
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
if (PortN != -1) {
- ushort dest_unit = HostP->Mapping[unit].ID2;
+ ushort dest_unit = HostP->Mapping[unit].ID2;
/*
- ** Get the link number used for the 1st 8 phbs on this unit.
- */
+ ** Get the link number used for the 1st 8 phbs on this unit.
+ */
PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
link = RWORD(PortP->PhbP->link);
for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
- ushort dest_port = port + 8;
-#if 0
- uint PktInt;
-#endif
- WORD *TxPktP;
- PKT *Pkt;
+ ushort dest_port = port + 8;
+ WORD *TxPktP;
+ PKT *Pkt;
PortP = p->RIOPortp[PortN];
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** If RTA is not powered on, the tx packets will be
- ** unset, so go no further.
- */
+ ** If RTA is not powered on, the tx packets will be
+ ** unset, so go no further.
+ */
if (PortP->TxStart == 0) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- break;
+ rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ break;
}
/*
- ** For the second slot of a 16 port RTA, the driver needs to
- ** sort out the phb to port mappings. The dest_unit for this
- ** group of 8 phbs is set to the dest_unit of the accompanying
- ** 8 port block. The dest_port of the second unit is set to
- ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
- ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
- ** (being the second map ID) will be sent to dest_unit 5, port
- ** 14. When this RTA is deleted, dest_unit for ID 6 will be
- ** restored, and the dest_port will be reduced by 8.
- ** Transmit packets also have a destination field which needs
- ** adjusting in the same manner.
- ** Note that the unit/port bytes in 'dest' are swapped.
- ** We also need to adjust the phb and rup link numbers for the
- ** second block of 8 ttys.
- */
+ ** For the second slot of a 16 port RTA, the driver needs to
+ ** sort out the phb to port mappings. The dest_unit for this
+ ** group of 8 phbs is set to the dest_unit of the accompanying
+ ** 8 port block. The dest_port of the second unit is set to
+ ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
+ ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
+ ** (being the second map ID) will be sent to dest_unit 5, port
+ ** 14. When this RTA is deleted, dest_unit for ID 6 will be
+ ** restored, and the dest_port will be reduced by 8.
+ ** Transmit packets also have a destination field which needs
+ ** adjusting in the same manner.
+ ** Note that the unit/port bytes in 'dest' are swapped.
+ ** We also need to adjust the phb and rup link numbers for the
+ ** second block of 8 ttys.
+ */
for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
/*
- ** *TxPktP is the pointer to the transmit packet on the host
- ** card. This needs to be translated into a 32 bit pointer
- ** so it can be accessed from the driver.
- */
- Pkt = (PKT *) RIO_PTR(HostP->Caddr,RINDW(TxPktP));
+ ** *TxPktP is the pointer to the transmit packet on the host
+ ** card. This needs to be translated into a 32 bit pointer
+ ** so it can be accessed from the driver.
+ */
+ Pkt = (PKT *) RIO_PTR(HostP->Caddr, RINDW(TxPktP));
/*
- ** If the packet is used, reset it.
- */
- Pkt = (PKT *)((uint)Pkt & ~PKT_IN_USE);
+ ** If the packet is used, reset it.
+ */
+ Pkt = (PKT *) ((uint) Pkt & ~PKT_IN_USE);
WBYTE(Pkt->dest_unit, dest_unit);
WBYTE(Pkt->dest_port, dest_port);
}
- rio_dprintk (RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n",
- RWORD(PortP->PhbP->destination) & 0xff,
- (RWORD(PortP->PhbP->destination) >> 8) & 0xff,
- dest_unit, dest_port);
+ rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", RWORD(PortP->PhbP->destination) & 0xff, (RWORD(PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
WWORD(PortP->PhbP->link, link);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
/*
- ** Now make sure the range of ports to be serviced includes
- ** the 2nd 8 on this 16 port RTA.
- */
- if (link > 3) return;
+ ** Now make sure the range of ports to be serviced includes
+ ** the 2nd 8 on this 16 port RTA.
+ */
+ if (link > 3)
+ return;
if (((unit * 8) + 7) > RWORD(HostP->LinkStrP[link].last_port)) {
- rio_dprintk (RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
+ rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
WWORD(HostP->LinkStrP[link].last_port, (unit * 8) + 7);
}
}
@@ -723,26 +603,21 @@ uint unit;
** the world about it. This is done to ensure that the configurator
** only gets up-to-date information about what is going on.
*/
-static int
-RIOCheckIsolated(p, HostP, UnitId)
-struct rio_info * p;
+static int RIOCheckIsolated(p, HostP, UnitId)
+struct rio_info *p;
struct Host *HostP;
uint UnitId;
{
unsigned long flags;
rio_spin_lock_irqsave(&HostP->HostLock, flags);
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
- if ( RIOCheck( HostP, UnitId ) ) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
+ if (RIOCheck(HostP, UnitId)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
- return(0);
+ return (0);
}
- RIOIsolate(p, HostP, UnitId );
+ RIOIsolate(p, HostP, UnitId);
RIOSetChange(p);
rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
return 1;
@@ -753,85 +628,75 @@ uint UnitId;
** all the units attached to it. This will mean that the entire
** subnet will re-introduce itself.
*/
-static int
-RIOIsolate(p, HostP, UnitId)
-struct rio_info * p;
-struct Host * HostP;
-uint UnitId;
+static int RIOIsolate(p, HostP, UnitId)
+struct rio_info *p;
+struct Host *HostP;
+uint UnitId;
{
uint link, unit;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
UnitId--; /* this trick relies on the Unit Id being UNSIGNED! */
- if ( UnitId >= MAX_RUP ) /* dontcha just lurv unsigned maths! */
- return(0);
+ if (UnitId >= MAX_RUP) /* dontcha just lurv unsigned maths! */
+ return (0);
- if ( HostP->Mapping[UnitId].Flags & BEEN_HERE )
- return(0);
+ if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
+ return (0);
HostP->Mapping[UnitId].Flags |= BEEN_HERE;
- if ( p->RIOPrintDisabled == DO_PRINT )
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
+ if (p->RIOPrintDisabled == DO_PRINT)
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
- for ( link=0; link<LINKS_PER_UNIT; link++) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
unit = HostP->Mapping[UnitId].Topology[link].Unit;
HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
- RIOIsolate(p, HostP, unit );
+ RIOIsolate(p, HostP, unit);
}
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
return 1;
}
-static int
-RIOCheck(HostP, UnitId)
+static int RIOCheck(HostP, UnitId)
struct Host *HostP;
uint UnitId;
{
- unsigned char link;
+ unsigned char link;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckUnitId( UnitId );
-#endif
/* rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
- if ( UnitId == HOST_ID ) {
+ if (UnitId == HOST_ID) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
return 1;
}
UnitId--;
- if ( UnitId >= MAX_RUP ) {
+ if (UnitId >= MAX_RUP) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
return 0;
}
- for ( link=0; link<LINKS_PER_UNIT; link++ ) {
- if ( HostP->Mapping[UnitId].Topology[link].Unit==HOST_ID ) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n",
- UnitId, 'A'+link)); */
+ UnitId, 'A'+link)); */
return 1;
}
}
- if ( HostP->Mapping[UnitId].Flags & BEEN_HERE ) {
+ if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
return 0;
}
HostP->Mapping[UnitId].Flags |= BEEN_HERE;
- for ( link=0; link < LINKS_PER_UNIT; link++ ) {
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
- if ( RIOCheck( HostP, HostP->Mapping[UnitId].Topology[link].Unit ) ) {
+ if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
return 1;
@@ -841,7 +706,7 @@ uint UnitId;
HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
-
+
return 0;
}
@@ -849,61 +714,57 @@ uint UnitId;
** Returns the type of unit (host, 16/8 port RTA)
*/
-uint
-GetUnitType(Uniq)
+uint GetUnitType(Uniq)
uint Uniq;
{
- switch ( (Uniq >> 28) & 0xf)
- {
- case RIO_AT:
- case RIO_MCA:
- case RIO_EISA:
- case RIO_PCI:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Host\n");
- return(TYPE_HOST);
- case RIO_RTA_16:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
- return(TYPE_RTA16);
- case RIO_RTA:
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
- return(TYPE_RTA8);
- default :
- rio_dprintk (RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
- return(99);
+ switch ((Uniq >> 28) & 0xf) {
+ case RIO_AT:
+ case RIO_MCA:
+ case RIO_EISA:
+ case RIO_PCI:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
+ return (TYPE_HOST);
+ case RIO_RTA_16:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
+ return (TYPE_RTA16);
+ case RIO_RTA:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
+ return (TYPE_RTA8);
+ default:
+ rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
+ return (99);
}
}
-int
-RIOSetChange(p)
-struct rio_info * p;
+int RIOSetChange(p)
+struct rio_info *p;
{
- if ( p->RIOQuickCheck != NOT_CHANGED )
- return(0);
+ if (p->RIOQuickCheck != NOT_CHANGED)
+ return (0);
p->RIOQuickCheck = CHANGED;
- if ( p->RIOSignalProcess ) {
- rio_dprintk (RIO_DEBUG_ROUTE, "Send SIG-HUP");
+ if (p->RIOSignalProcess) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
/*
- psignal( RIOSignalProcess, SIGHUP );
- */
+ psignal( RIOSignalProcess, SIGHUP );
+ */
}
- return(0);
+ return (0);
}
-static void
-RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
-struct rio_info * p;
+static void RIOConCon(p, HostP, FromId, FromLink, ToId, ToLink, Change)
+struct rio_info *p;
struct Host *HostP;
uint FromId;
uint FromLink;
uint ToId;
uint ToLink;
-int Change;
+int Change;
{
- char *FromName;
- char *FromType;
- char *ToName;
- char *ToType;
- unsigned int tp;
+ char *FromName;
+ char *FromType;
+ char *ToName;
+ char *ToType;
+ unsigned int tp;
/*
** 15.10.1998 ARG - ESIL 0759
@@ -932,38 +793,32 @@ int Change;
** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
** connections and disconnections.
*/
- if (Change == CONNECT) {
- if (p->RIORtaDisCons) p->RIORtaDisCons--;
- }
- else {
+ if (Change == CONNECT) {
+ if (p->RIORtaDisCons)
+ p->RIORtaDisCons--;
+ } else {
p->RIORtaDisCons++;
- }
+ }
- if ( p->RIOPrintDisabled == DONT_PRINT )
+ if (p->RIOPrintDisabled == DONT_PRINT)
return;
- if ( FromId > ToId ) {
+ if (FromId > ToId) {
tp = FromId;
FromId = ToId;
ToId = tp;
tp = FromLink;
FromLink = ToLink;
ToLink = tp;
- }
-
- FromName = FromId ? HostP->Mapping[FromId-1].Name : HostP->Name;
- FromType = FromId ? "RTA" : "HOST";
- ToName = ToId ? HostP->Mapping[ToId-1].Name : HostP->Name;
- ToType = ToId ? "RTA" : "HOST";
-
- rio_dprintk (RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
- FromType, FromName, 'A'+FromLink,
- ToType, ToName, 'A'+ToLink,
- (Change==CONNECT) ? "established" : "disconnected");
- cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n",
- FromType, FromName, 'A'+FromLink,
- ToType, ToName, 'A'+ToLink,
- (Change==CONNECT) ? "established" : "disconnected");
+ }
+
+ FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
+ FromType = FromId ? "RTA" : "HOST";
+ ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
+ ToType = ToId ? "RTA" : "HOST";
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
+ cprintf("Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
}
/*
@@ -972,24 +827,21 @@ int Change;
** Delete and RTA entry from the saved table given to us
** by the configuration program.
*/
-static int
-RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
+static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
{
- int entry;
-
- /*
- ** We loop for all entries even after finding an entry and
- ** zeroing it because we may have two entries to delete if
- ** it's a 16 port RTA.
- */
- for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++)
- {
- if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum)
- {
- bzero((caddr_t)&p->RIOSavedTable[entry], sizeof(struct Map));
+ int entry;
+
+ /*
+ ** We loop for all entries even after finding an entry and
+ ** zeroing it because we may have two entries to delete if
+ ** it's a 16 port RTA.
+ */
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
+ bzero((caddr_t) & p->RIOSavedTable[entry], sizeof(struct Map));
+ }
}
- }
- return 0;
+ return 0;
}
@@ -999,64 +851,58 @@ RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
** Scan the unit links to and return zero if the unit is completely
** disconnected.
*/
-static int
-RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
{
- int link;
-
-
- rio_dprintk (RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
- /*
- ** If the slot is tentative and does not belong to the
- ** second half of a 16 port RTA then scan to see if
- ** is disconnected.
- */
- for (link = 0; link < LINKS_PER_UNIT; link++)
- {
- if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
- break;
- }
-
- /*
- ** If not all links are disconnected then we can forget about it.
- */
- if (link < LINKS_PER_UNIT)
- return 1;
+ int link;
+
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
+ /*
+ ** If the slot is tentative and does not belong to the
+ ** second half of a 16 port RTA then scan to see if
+ ** is disconnected.
+ */
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
+ break;
+ }
+
+ /*
+ ** If not all links are disconnected then we can forget about it.
+ */
+ if (link < LINKS_PER_UNIT)
+ return 1;
#ifdef NEED_TO_FIX_THIS
- /* Ok so all the links are disconnected. But we may have only just
- ** made this slot tentative and not yet received a topology update.
- ** Lets check how long ago we made it tentative.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
- if (drv_getparm(LBOLT, (ulong_t *) &current_time))
- rio_dprintk (RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
-
- elapse_time = current_time - TentTime[unit];
- rio_dprintk (RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n",
- elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
- if (drv_hztousec(elapse_time) < WAIT_TO_FINISH)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n",
- unit, drv_hztousec(elapse_time));
- return 1;
- }
+ /* Ok so all the links are disconnected. But we may have only just
+ ** made this slot tentative and not yet received a topology update.
+ ** Lets check how long ago we made it tentative.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
+ if (drv_getparm(LBOLT, (ulong_t *) & current_time))
+ rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
+
+ elapse_time = current_time - TentTime[unit];
+ rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
+ if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
+ return 1;
+ }
#endif
- /*
- ** We have found an usable slot.
- ** If it is half of a 16 port RTA then delete the other half.
- */
- if (HostP->Mapping[unit].ID2 != 0)
- {
- int nOther = (HostP->Mapping[unit].ID2) -1;
-
- rio_dprintk (RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
- bzero((caddr_t)&HostP->Mapping[nOther], sizeof(struct Map));
- }
- RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
+ /*
+ ** We have found an usable slot.
+ ** If it is half of a 16 port RTA then delete the other half.
+ */
+ if (HostP->Mapping[unit].ID2 != 0) {
+ int nOther = (HostP->Mapping[unit].ID2) - 1;
+
+ rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
+ bzero((caddr_t) & HostP->Mapping[nOther], sizeof(struct Map));
+ }
+ RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
- return 0;
+ return 0;
}
@@ -1066,150 +912,134 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
** This function scans the given host table for either one
** or two free unit ID's.
*/
-int
-RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint *pID1, uint *pID2)
+int RIOFindFreeID(struct rio_info *p, struct Host *HostP, uint * pID1, uint * pID2)
{
- int unit,tempID;
-
- /*
- ** Initialise the ID's to MAX_RUP.
- ** We do this to make the loop for setting the ID's as simple as
- ** possible.
- */
- *pID1 = MAX_RUP;
- if (pID2 != NULL)
- *pID2 = MAX_RUP;
-
- /*
- ** Scan all entries of the host mapping table for free slots.
- ** We scan for free slots first and then if that is not successful
- ** we start all over again looking for tentative slots we can re-use.
- */
- for (unit = 0; unit < MAX_RUP; unit++)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Scanning unit %d\n",unit);
+ int unit, tempID;
+
/*
- ** If the flags are zero then the slot is empty.
- */
- if (HostP->Mapping[unit].Flags == 0)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " This slot is empty.\n");
- /*
- ** If we haven't allocated the first ID then do it now.
- */
- if (*pID1 == MAX_RUP)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
- *pID1 = unit;
+ ** Initialise the ID's to MAX_RUP.
+ ** We do this to make the loop for setting the ID's as simple as
+ ** possible.
+ */
+ *pID1 = MAX_RUP;
+ if (pID2 != NULL)
+ *pID2 = MAX_RUP;
+ /*
+ ** Scan all entries of the host mapping table for free slots.
+ ** We scan for free slots first and then if that is not successful
+ ** we start all over again looking for tentative slots we can re-use.
+ */
+ for (unit = 0; unit < MAX_RUP; unit++) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
/*
- ** If the second ID is not needed then we can return
- ** now.
- */
- if (pID2 == NULL)
- return 0;
- }
- else
- {
- /*
- ** Allocate the second slot and return.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
- *pID2 = unit;
- return 0;
- }
+ ** If the flags are zero then the slot is empty.
+ */
+ if (HostP->Mapping[unit].Flags == 0) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " This slot is empty.\n");
+ /*
+ ** If we haven't allocated the first ID then do it now.
+ */
+ if (*pID1 == MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
+ *pID1 = unit;
+
+ /*
+ ** If the second ID is not needed then we can return
+ ** now.
+ */
+ if (pID2 == NULL)
+ return 0;
+ } else {
+ /*
+ ** Allocate the second slot and return.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
+ *pID2 = unit;
+ return 0;
+ }
+ }
}
- }
-
- /*
- ** If we manage to come out of the free slot loop then we
- ** need to start all over again looking for tentative slots
- ** that we can re-use.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
- for (unit = 0; unit < MAX_RUP; unit++)
- {
- if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) ||
- (HostP->Mapping[unit].Flags == 0)) && !
- (HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT ))
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " Slot %d looks promising.\n",unit);
-
- if(unit == *pID1)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n");
- continue;
- }
-
- /*
- ** Slot is Tentative or Empty, but not a tentative second
- ** slot of a 16 porter.
- ** Attempt to free up this slot (and its parnter if
- ** it is a 16 port slot. The second slot will become
- ** empty after a call to RIOFreeDisconnected so thats why
- ** we look for empty slots above as well).
- */
- if (HostP->Mapping[unit].Flags != 0)
- if (RIOFreeDisconnected(p, HostP, unit) != 0)
- continue;
- /*
- ** If we haven't allocated the first ID then do it now.
- */
- if (*pID1 == MAX_RUP)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
- *pID1 = unit;
- /*
- ** Clear out this slot now that we intend to use it.
- */
- bzero(&HostP->Mapping[unit], sizeof(struct Map));
+ /*
+ ** If we manage to come out of the free slot loop then we
+ ** need to start all over again looking for tentative slots
+ ** that we can re-use.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
+ for (unit = 0; unit < MAX_RUP; unit++) {
+ if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " Slot %d looks promising.\n", unit);
+
+ if (unit == *pID1) {
+ rio_dprintk(RIO_DEBUG_ROUTE, " No it isn't, its the 1st half\n");
+ continue;
+ }
- /*
- ** If the second ID is not needed then we can return
- ** now.
- */
- if (pID2 == NULL)
- return 0;
- }
- else
- {
- /*
- ** Allocate the second slot and return.
- */
- rio_dprintk (RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n",
- unit);
- *pID2 = unit;
+ /*
+ ** Slot is Tentative or Empty, but not a tentative second
+ ** slot of a 16 porter.
+ ** Attempt to free up this slot (and its parnter if
+ ** it is a 16 port slot. The second slot will become
+ ** empty after a call to RIOFreeDisconnected so thats why
+ ** we look for empty slots above as well).
+ */
+ if (HostP->Mapping[unit].Flags != 0)
+ if (RIOFreeDisconnected(p, HostP, unit) != 0)
+ continue;
+ /*
+ ** If we haven't allocated the first ID then do it now.
+ */
+ if (*pID1 == MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
+ *pID1 = unit;
- /*
- ** Clear out this slot now that we intend to use it.
- */
- bzero(&HostP->Mapping[unit], sizeof(struct Map));
-
- /* At this point under the right(wrong?) conditions
- ** we may have a first unit ID being higher than the
- ** second unit ID. This is a bad idea if we are about
- ** to fill the slots with a 16 port RTA.
- ** Better check and swap them over.
- */
-
- if (*pID1 > *pID2)
- {
- rio_dprintk (RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
- tempID = *pID1;
- *pID1 = *pID2;
- *pID2 = tempID;
+ /*
+ ** Clear out this slot now that we intend to use it.
+ */
+ bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+ /*
+ ** If the second ID is not needed then we can return
+ ** now.
+ */
+ if (pID2 == NULL)
+ return 0;
+ } else {
+ /*
+ ** Allocate the second slot and return.
+ */
+ rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty entry for second unit %d\n", unit);
+ *pID2 = unit;
+
+ /*
+ ** Clear out this slot now that we intend to use it.
+ */
+ bzero(&HostP->Mapping[unit], sizeof(struct Map));
+
+ /* At this point under the right(wrong?) conditions
+ ** we may have a first unit ID being higher than the
+ ** second unit ID. This is a bad idea if we are about
+ ** to fill the slots with a 16 port RTA.
+ ** Better check and swap them over.
+ */
+
+ if (*pID1 > *pID2) {
+ rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
+ tempID = *pID1;
+ *pID1 = *pID2;
+ *pID2 = tempID;
+ }
+ return 0;
+ }
}
- return 0;
- }
}
- }
- /*
- ** If we manage to get to the end of the second loop then we
- ** can give up and return a failure.
- */
- return 1;
+ /*
+ ** If we manage to get to the end of the second loop then we
+ ** can give up and return a failure.
+ */
+ return 1;
}
diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h
index 32b09b0f23aa..534f1f5b9f53 100644
--- a/drivers/char/rio/riospace.h
+++ b/drivers/char/rio/riospace.h
@@ -47,9 +47,8 @@ static char *_riospace_h_sccs_ = "@(#)riospace.h 1.2";
** In particular, it won't be able to see changes to RIO_SLOTS
*/
-struct Conf
-{
- char Locator[24];
+struct Conf {
+ char Locator[24];
unsigned int StartupTime;
unsigned int SlowCook;
unsigned int IntrPollTime;
@@ -59,8 +58,8 @@ struct Conf
unsigned int HostLoadBase;
unsigned int XpHz;
unsigned int XpCps;
- char *XpOn;
- char *XpOff;
+ char *XpOn;
+ char *XpOff;
unsigned int MaxXpCps;
unsigned int MinXpCps;
unsigned int SpinCmds;
@@ -74,7 +73,7 @@ struct Conf
/*
** Board types - these MUST correspond to product codes!
-*/
+*/
#define RIO_EMPTY 0x0
#define RIO_EISA 0x3
#define RIO_RTA_16 0x9
@@ -86,18 +85,16 @@ struct Conf
/*
** Board data structure. This is used for configuration info
*/
-struct Brd
-{
- unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
- unsigned char Ivec; /* POLLED or ivec number */
- unsigned char Mode; /* Control stuff, see below */
+struct Brd {
+ unsigned char Type; /* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
+ unsigned char Ivec; /* POLLED or ivec number */
+ unsigned char Mode; /* Control stuff, see below */
};
-struct Board
-{
- char Locator[RIO_LOCATOR_LEN];
- int NumSlots;
- struct Brd Boards[MAX_RIO_BOARDS];
+struct Board {
+ char Locator[RIO_LOCATOR_LEN];
+ int NumSlots;
+ struct Brd Boards[MAX_RIO_BOARDS];
};
#define BOOT_FROM_LINK 0x00
@@ -158,4 +155,4 @@ struct Board
#define DBG_ALWAYS 0x80000000
-#endif /* __rio_riospace_h__ */
+#endif /* __rio_riospace_h__ */
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index e45bc275907a..a86b216ab653 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -91,9 +91,8 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2";
** A configuration table has been loaded. It is now up to us
** to sort it out and use the information contained therein.
*/
-int
-RIONewTable(p)
-struct rio_info * p;
+int RIONewTable(p)
+struct rio_info *p;
{
int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
struct Map *MapP;
@@ -103,26 +102,26 @@ struct rio_info * p;
char *cptr;
/*
- ** We have been sent a new table to install. We need to break
- ** it down into little bits and spread it around a bit to see
- ** what we have got.
- */
+ ** We have been sent a new table to install. We need to break
+ ** it down into little bits and spread it around a bit to see
+ ** what we have got.
+ */
/*
- ** Things to check:
- ** (things marked 'xx' aren't checked any more!)
- ** (1) That there are no booted Hosts/RTAs out there.
- ** (2) That the names are properly formed
- ** (3) That blank entries really are.
- ** xx (4) That hosts mentioned in the table actually exist. xx
- ** (5) That the IDs are unique (per host).
- ** (6) That host IDs are zero
- ** (7) That port numbers are valid
- ** (8) That port numbers aren't duplicated
- ** (9) That names aren't duplicated
- ** xx (10) That hosts that actually exist are mentioned in the table. xx
- */
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
- if ( p->RIOSystemUp ) { /* (1) */
+ ** Things to check:
+ ** (things marked 'xx' aren't checked any more!)
+ ** (1) That there are no booted Hosts/RTAs out there.
+ ** (2) That the names are properly formed
+ ** (3) That blank entries really are.
+ ** xx (4) That hosts mentioned in the table actually exist. xx
+ ** (5) That the IDs are unique (per host).
+ ** (6) That host IDs are zero
+ ** (7) That port numbers are valid
+ ** (8) That port numbers aren't duplicated
+ ** (9) That names aren't duplicated
+ ** xx (10) That hosts that actually exist are mentioned in the table. xx
+ */
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
+ if (p->RIOSystemUp) { /* (1) */
p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
return -EBUSY;
}
@@ -131,19 +130,19 @@ struct rio_info * p;
p->RIOError.Entry = -1;
p->RIOError.Other = -1;
- for ( Entry=0; Entry<TOTAL_MAP_ENTRIES; Entry++ ) {
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
MapP = &p->RIOConnectTable[Entry];
if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
- cptr = MapP->Name; /* (2) */
- cptr[MAX_NAME_LEN-1]='\0';
- if ( cptr[0]=='\0' ) {
- bcopy(MapP->RtaUniqueNum?"RTA NN":"HOST NN",MapP->Name,8);
- MapP->Name[5] = '0'+Entry/10;
- MapP->Name[6] = '0'+Entry%10;
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
+ cptr = MapP->Name; /* (2) */
+ cptr[MAX_NAME_LEN - 1] = '\0';
+ if (cptr[0] == '\0') {
+ bcopy(MapP->RtaUniqueNum ? "RTA NN" : "HOST NN", MapP->Name, 8);
+ MapP->Name[5] = '0' + Entry / 10;
+ MapP->Name[6] = '0' + Entry % 10;
}
- while ( *cptr ) {
- if ( *cptr<' ' || *cptr>'~' ) {
+ while (*cptr) {
+ if (*cptr < ' ' || *cptr > '~') {
p->RIOError.Error = BAD_CHARACTER_IN_NAME;
p->RIOError.Entry = Entry;
return -ENXIO;
@@ -153,133 +152,119 @@ struct rio_info * p;
}
/*
- ** If the entry saved was a tentative entry then just forget
- ** about it.
- */
- if ( MapP->Flags & SLOT_TENTATIVE ) {
+ ** If the entry saved was a tentative entry then just forget
+ ** about it.
+ */
+ if (MapP->Flags & SLOT_TENTATIVE) {
MapP->HostUniqueNum = 0;
MapP->RtaUniqueNum = 0;
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
- if ( !MapP->RtaUniqueNum && !MapP->HostUniqueNum ) { /* (3) */
- if ( MapP->ID || MapP->SysPort || MapP->Flags ) {
- rio_dprintk (RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n",MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
+ if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) { /* (3) */
+ if (MapP->ID || MapP->SysPort || MapP->Flags) {
+ rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
- for ( Host=0; Host<p->RIONumHosts; Host++ ) { /* (4) */
- if ( p->RIOHosts[Host].UniqueNum==MapP->HostUniqueNum ) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
+ for (Host = 0; Host < p->RIONumHosts; Host++) { /* (4) */
+ if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
HostP = &p->RIOHosts[Host];
/*
- ** having done the lookup, we don't really want to do
- ** it again, so hang the host number in a safe place
- */
+ ** having done the lookup, we don't really want to do
+ ** it again, so hang the host number in a safe place
+ */
MapP->Topology[0].Unit = Host;
break;
}
}
- if ( Host >= p->RIONumHosts ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n",
- MapP->Name, MapP->HostUniqueNum);
+ if (Host >= p->RIONumHosts) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
MapP->HostUniqueNum = 0;
- /* MapP->RtaUniqueNum = 0; */
- /* MapP->ID = 0; */
- /* MapP->Flags = 0; */
- /* MapP->SysPort = 0; */
- /* MapP->Name[0] = 0; */
+ /* MapP->RtaUniqueNum = 0; */
+ /* MapP->ID = 0; */
+ /* MapP->Flags = 0; */
+ /* MapP->SysPort = 0; */
+ /* MapP->Name[0] = 0; */
continue;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
- if ( MapP->RtaUniqueNum ) { /* (5) */
- if ( !MapP->ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n",
- MapP->Name);
- p->RIOError.Error = ZERO_RTA_ID;
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
+ if (MapP->RtaUniqueNum) { /* (5) */
+ if (!MapP->ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
+ p->RIOError.Error = ZERO_RTA_ID;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- if ( MapP->ID > MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n",
- MapP->Name, MapP->ID);
+ if (MapP->ID > MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
- if ( MapP->HostUniqueNum ==
- p->RIOConnectTable[SubEnt].HostUniqueNum &&
- MapP->ID == p->RIOConnectTable[SubEnt].ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n",
- MapP->Name, p->RIOConnectTable[SubEnt].Name);
+ for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+ if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
p->RIOError.Error = DUPLICATED_RTA_ID;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
/*
- ** If the RtaUniqueNum is the same, it may be looking at both
- ** entries for a 16 port RTA, so check the ids
- */
- if ((MapP->RtaUniqueNum ==
- p->RIOConnectTable[SubEnt].RtaUniqueNum)
- && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",MapP->Name);
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n",
- p->RIOConnectTable[SubEnt].Name);
+ ** If the RtaUniqueNum is the same, it may be looking at both
+ ** entries for a 16 port RTA, so check the ids
+ */
+ if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
+ && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
/* (7a) */
- if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort % PORTS_PER_RTA)) {
- rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n",
- (int)MapP->SysPort,MapP->Name, PORTS_PER_RTA);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
/* (7b) */
- if ((MapP->SysPort != NO_PORT)&&(MapP->SysPort >= RIO_PORTS)) {
- rio_dprintk (RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n",
- (int)MapP->SysPort, MapP->Name);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- for ( SubEnt=0; SubEnt<Entry; SubEnt++ ) {
- if ( p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT )
- continue;
- if ( p->RIOConnectTable[SubEnt].RtaUniqueNum ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
+ for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+ if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
+ continue;
+ if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
/* (8) */
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort ==
- p->RIOConnectTable[SubEnt].SysPort) ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n",
- MapP->Name, p->RIOConnectTable[SubEnt].Name,
- (int)MapP->SysPort);
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
p->RIOError.Error = TTY_NUMBER_IN_USE;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
- if (strcmp(MapP->Name,
- p->RIOConnectTable[SubEnt].Name)==0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
- rio_dprintk (RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
+ if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) { /* (9) */
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
p->RIOError.Error = NAME_USED_TWICE;
p->RIOError.Entry = Entry;
p->RIOError.Other = SubEnt;
@@ -287,19 +272,16 @@ struct rio_info * p;
}
}
}
- }
- else { /* (6) */
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
- if ( MapP->ID ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n",
- MapP->Name);
+ } else { /* (6) */
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
+ if (MapP->ID) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
p->RIOError.Error = HOST_ID_NOT_ZERO;
p->RIOError.Entry = Entry;
return -ENXIO;
}
- if ( MapP->SysPort != NO_PORT ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n",
- MapP->Name);
+ if (MapP->SysPort != NO_PORT) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
p->RIOError.Error = HOST_SYSPORT_BAD;
p->RIOError.Entry = Entry;
return -ENXIO;
@@ -308,106 +290,101 @@ struct rio_info * p;
}
/*
- ** wow! if we get here then it's a goody!
- */
+ ** wow! if we get here then it's a goody!
+ */
/*
- ** Zero the (old) entries for each host...
- */
- for ( Host=0; Host<RIO_HOSTS; Host++ ) {
- for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
- bzero((caddr_t)&p->RIOHosts[Host].Mapping[Entry],
- sizeof(struct Map));
+ ** Zero the (old) entries for each host...
+ */
+ for (Host = 0; Host < RIO_HOSTS; Host++) {
+ for (Entry = 0; Entry < MAX_RUP; Entry++) {
+ bzero((caddr_t) & p->RIOHosts[Host].Mapping[Entry], sizeof(struct Map));
}
- bzero((caddr_t)&p->RIOHosts[Host].Name[0],
- sizeof(p->RIOHosts[Host].Name) );
+ bzero((caddr_t) & p->RIOHosts[Host].Name[0], sizeof(p->RIOHosts[Host].Name));
}
/*
- ** Copy in the new table entries
- */
- for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
- rio_dprintk (RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
+ ** Copy in the new table entries
+ */
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
MapP = &p->RIOConnectTable[Entry];
/*
- ** Now, if it is an empty slot ignore it!
- */
- if ( MapP->HostUniqueNum==0 )
+ ** Now, if it is an empty slot ignore it!
+ */
+ if (MapP->HostUniqueNum == 0)
continue;
/*
- ** we saved the host number earlier, so grab it back
- */
+ ** we saved the host number earlier, so grab it back
+ */
HostP = &p->RIOHosts[MapP->Topology[0].Unit];
/*
- ** If it is a host, then we only need to fill in the name field.
- */
- if ( MapP->ID==0 ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
- bcopy(MapP->Name,HostP->Name,MAX_NAME_LEN);
+ ** If it is a host, then we only need to fill in the name field.
+ */
+ if (MapP->ID == 0) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
+ bcopy(MapP->Name, HostP->Name, MAX_NAME_LEN);
continue;
}
/*
- ** Its an RTA entry, so fill in the host mapping entries for it
- ** and the port mapping entries. Notice that entry zero is for
- ** ID one.
- */
- HostMapP = &HostP->Mapping[MapP->ID-1];
+ ** Its an RTA entry, so fill in the host mapping entries for it
+ ** and the port mapping entries. Notice that entry zero is for
+ ** ID one.
+ */
+ HostMapP = &HostP->Mapping[MapP->ID - 1];
if (MapP->Flags & SLOT_IN_USE) {
- rio_dprintk (RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
/*
- ** structure assign, then sort out the bits we shouldn't have done
- */
+ ** structure assign, then sort out the bits we shouldn't have done
+ */
*HostMapP = *MapP;
HostMapP->Flags = SLOT_IN_USE;
if (MapP->Flags & RTA16_SECOND_SLOT)
HostMapP->Flags |= RTA16_SECOND_SLOT;
- RIOReMapPorts(p, HostP, HostMapP );
- }
- else {
- rio_dprintk (RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
+ RIOReMapPorts(p, HostP, HostMapP);
+ } else {
+ rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
}
}
- for ( Entry=0; Entry< TOTAL_MAP_ENTRIES; Entry++ ) {
+ for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
}
- for ( Host=0; Host<p->RIONumHosts; Host++ ) {
- for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
+ for (Host = 0; Host < p->RIONumHosts; Host++) {
+ for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
}
- for ( Entry=0; Entry<MAX_RUP; Entry++ ) {
- for ( SubEnt=0; SubEnt<LINKS_PER_UNIT; SubEnt++ ) {
- p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit =
- ROUTE_DISCONNECT;
- p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link =
- NO_LINK;
+ for (Entry = 0; Entry < MAX_RUP; Entry++) {
+ for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
+ p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+ p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
}
}
- if ( !p->RIOHosts[Host].Name[0] ) {
- bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+ if (!p->RIOHosts[Host].Name[0]) {
+ bcopy("HOST 1", p->RIOHosts[Host].Name, 7);
p->RIOHosts[Host].Name[5] += Host;
}
/*
- ** Check that default name assigned is unique.
- */
+ ** Check that default name assigned is unique.
+ */
Host1 = Host;
NameIsUnique = 0;
while (!NameIsUnique) {
NameIsUnique = 1;
- for ( Host2=0; Host2<p->RIONumHosts; Host2++ ) {
+ for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
if (Host2 == Host)
continue;
if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
- == 0) {
+ == 0) {
NameIsUnique = 0;
Host1++;
if (Host1 >= p->RIONumHosts)
@@ -417,15 +394,14 @@ struct rio_info * p;
}
}
/*
- ** Rename host if name already used.
- */
- if (Host1 != Host)
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
- bcopy("HOST 1",p->RIOHosts[Host].Name,7);
+ ** Rename host if name already used.
+ */
+ if (Host1 != Host) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
+ bcopy("HOST 1", p->RIOHosts[Host].Name, 7);
p->RIOHosts[Host].Name[5] += Host1;
}
- rio_dprintk (RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
}
return 0;
}
@@ -434,9 +410,8 @@ struct rio_info * p;
** User process needs the config table - build it from first
** principles.
*/
-int
-RIOApel(p)
-struct rio_info * p;
+int RIOApel(p)
+struct rio_info *p;
{
int Host;
int link;
@@ -446,35 +421,34 @@ struct rio_info * p;
struct Host *HostP;
long oldspl;
- disable(oldspl); /* strange but true! */
-
- rio_dprintk (RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
+ disable(oldspl); /* strange but true! */
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
- bzero((caddr_t)&p->RIOConnectTable[0],
- sizeof(struct Map) * TOTAL_MAP_ENTRIES );
+ bzero((caddr_t) & p->RIOConnectTable[0], sizeof(struct Map) * TOTAL_MAP_ENTRIES);
- for ( Host=0; Host<RIO_HOSTS; Host++ ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Processing host %d\n", Host);
+ for (Host = 0; Host < RIO_HOSTS; Host++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
HostP = &p->RIOHosts[Host];
MapP = &p->RIOConnectTable[Next++];
MapP->HostUniqueNum = HostP->UniqueNum;
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING )
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
continue;
MapP->RtaUniqueNum = 0;
MapP->ID = 0;
MapP->Flags = SLOT_IN_USE;
MapP->SysPort = NO_PORT;
- for ( link=0; link<LINKS_PER_UNIT; link++ )
+ for (link = 0; link < LINKS_PER_UNIT; link++)
MapP->Topology[link] = HostP->Topology[link];
- bcopy(HostP->Name,MapP->Name,MAX_NAME_LEN);
- for ( Rup=0; Rup<MAX_RUP; Rup++ ) {
- if ( HostP->Mapping[Rup].Flags & (SLOT_IN_USE|SLOT_TENTATIVE) ) {
+ bcopy(HostP->Name, MapP->Name, MAX_NAME_LEN);
+ for (Rup = 0; Rup < MAX_RUP; Rup++) {
+ if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
p->RIOConnectTable[Next] = HostP->Mapping[Rup];
- if ( HostP->Mapping[Rup].Flags & SLOT_IN_USE)
+ if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
- if ( HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
+ if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
- if ( HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT )
+ if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
Next++;
}
@@ -489,8 +463,7 @@ struct rio_info * p;
** if the entry is suitably inactive, then we can gob on it and remove
** it from the table.
*/
-int
-RIODeleteRta(p, MapP)
+int RIODeleteRta(p, MapP)
struct rio_info *p;
struct Map *MapP;
{
@@ -502,110 +475,98 @@ struct Map *MapP;
int work_done = 0;
unsigned long lock_flags, sem_flags;
- rio_dprintk (RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n",
- MapP->HostUniqueNum, MapP->RtaUniqueNum);
+ rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
- for ( host=0; host < p->RIONumHosts; host++ ) {
+ for (host = 0; host < p->RIONumHosts; host++) {
HostP = &p->RIOHosts[host];
- rio_spin_lock_irqsave( &HostP->HostLock, lock_flags );
+ rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
- if ( (HostP->Flags & RUN_STATE) != RC_RUNNING ) {
+ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
continue;
}
- for ( entry=0; entry<MAX_RUP; entry++ ) {
- if ( MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum ) {
+ for (entry = 0; entry < MAX_RUP; entry++) {
+ if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
HostMapP = &HostP->Mapping[entry];
- rio_dprintk (RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n",
- entry, HostP->Name);
+ rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
/*
- ** Check all four links of the unit are disconnected
- */
- for ( link=0; link< LINKS_PER_UNIT; link++ ) {
- if ( HostMapP->Topology[link].Unit != ROUTE_DISCONNECT ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
+ ** Check all four links of the unit are disconnected
+ */
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
p->RIOError.Error = UNIT_IS_IN_USE;
- rio_spin_unlock_irqrestore( &HostP->HostLock, lock_flags);
+ rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
return -EBUSY;
}
}
/*
- ** Slot has been allocated, BUT not booted/routed/
- ** connected/selected or anything else-ed
- */
+ ** Slot has been allocated, BUT not booted/routed/
+ ** connected/selected or anything else-ed
+ */
SysPort = HostMapP->SysPort;
- if ( SysPort != NO_PORT ) {
- for (port=SysPort; port < SysPort+PORTS_PER_RTA; port++) {
+ if (SysPort != NO_PORT) {
+ for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
PortP = p->RIOPortp[port];
- rio_dprintk (RIO_DEBUG_TABLE, "Unmap port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
- rio_spin_lock_irqsave( &PortP->portSem, sem_flags );
+ rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
PortP->Mapped = 0;
- if ( PortP->State & (RIO_MOPEN|RIO_LOPEN) ) {
+ if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
- rio_dprintk (RIO_DEBUG_TABLE, "Gob on port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
PortP->TxBufferIn = PortP->TxBufferOut = 0;
/* What should I do
- wakeup( &PortP->TxBufferIn );
- wakeup( &PortP->TxBufferOut);
- */
+ wakeup( &PortP->TxBufferIn );
+ wakeup( &PortP->TxBufferOut);
+ */
PortP->InUse = NOT_INUSE;
/* What should I do
- wakeup( &PortP->InUse );
- signal(PortP->TtyP->t_pgrp,SIGKILL);
- ttyflush(PortP->TtyP,(FREAD|FWRITE));
- */
+ wakeup( &PortP->InUse );
+ signal(PortP->TtyP->t_pgrp,SIGKILL);
+ ttyflush(PortP->TtyP,(FREAD|FWRITE));
+ */
PortP->State |= RIO_CLOSING | RIO_DELETED;
}
/*
- ** For the second slot of a 16 port RTA, the
- ** driver needs to reset the changes made to
- ** the phb to port mappings in RIORouteRup.
- */
+ ** For the second slot of a 16 port RTA, the
+ ** driver needs to reset the changes made to
+ ** the phb to port mappings in RIORouteRup.
+ */
if (PortP->SecondBlock) {
ushort dest_unit = HostMapP->ID;
ushort dest_port = port - SysPort;
- WORD *TxPktP;
- PKT *Pkt;
+ WORD *TxPktP;
+ PKT *Pkt;
- for (TxPktP = PortP->TxStart;
- TxPktP <= PortP->TxEnd; TxPktP++) {
+ for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
/*
- ** *TxPktP is the pointer to the
- ** transmit packet on the host card.
- ** This needs to be translated into
- ** a 32 bit pointer so it can be
- ** accessed from the driver.
- */
- Pkt = (PKT *) RIO_PTR(HostP->Caddr,
- RWORD(*TxPktP));
- rio_dprintk (RIO_DEBUG_TABLE,
- "Tx packet (%x) destination: Old %x:%x New %x:%x\n",
- *TxPktP, Pkt->dest_unit,
- Pkt->dest_port, dest_unit, dest_port);
+ ** *TxPktP is the pointer to the
+ ** transmit packet on the host card.
+ ** This needs to be translated into
+ ** a 32 bit pointer so it can be
+ ** accessed from the driver.
+ */
+ Pkt = (PKT *) RIO_PTR(HostP->Caddr, RWORD(*TxPktP));
+ rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port);
WWORD(Pkt->dest_unit, dest_unit);
WWORD(Pkt->dest_port, dest_port);
}
- rio_dprintk (RIO_DEBUG_TABLE,
- "Port %d phb destination: Old %x:%x New %x:%x\n",
- port, PortP->PhbP->destination & 0xff,
- (PortP->PhbP->destination >> 8) & 0xff,
- dest_unit, dest_port);
- WWORD(PortP->PhbP->destination,
- dest_unit + (dest_port << 8));
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port);
+ WWORD(PortP->PhbP->destination, dest_unit + (dest_port << 8));
}
rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
}
}
- rio_dprintk (RIO_DEBUG_TABLE, "Entry nulled.\n");
- bzero((char *)HostMapP,sizeof(struct Map));
+ rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
+ bzero((char *) HostMapP, sizeof(struct Map));
work_done++;
}
}
@@ -613,203 +574,178 @@ struct Map *MapP;
}
/* XXXXX lock me up */
- for ( entry=0; entry< TOTAL_MAP_ENTRIES; entry++ ) {
- if ( p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
- bzero((char *)&p->RIOSavedTable[entry],sizeof(struct Map));
+ for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+ if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+ bzero((char *) &p->RIOSavedTable[entry], sizeof(struct Map));
work_done++;
}
- if ( p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum ) {
- bzero((char *)&p->RIOConnectTable[entry],sizeof(struct Map));
+ if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+ bzero((char *) &p->RIOConnectTable[entry], sizeof(struct Map));
work_done++;
}
}
- if ( work_done )
+ if (work_done)
return 0;
- rio_dprintk (RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
p->RIOError.Error = COULDNT_FIND_ENTRY;
return -ENXIO;
}
-int RIOAssignRta( struct rio_info *p, struct Map *MapP )
+int RIOAssignRta(struct rio_info *p, struct Map *MapP)
{
- int host;
- struct Map *HostMapP;
- char *sptr;
- int link;
-
-
- rio_dprintk (RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n",
- MapP->HostUniqueNum,MapP->RtaUniqueNum,
- MapP->ID, (int)MapP->SysPort);
-
- if ((MapP->ID != (ushort)-1) &&
- ((int)MapP->ID < (int)1 || (int)MapP->ID > MAX_RUP ))
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
- p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- if (MapP->RtaUniqueNum == 0)
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
- p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
- return -EINVAL;
- }
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA) )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n",(int)MapP->SysPort,PORTS_PER_RTA);
- p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
- if ( (MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS) )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Port %d not valid!\n",(int)MapP->SysPort);
- p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
- return -EINVAL;
- }
-
- /*
- ** Copy the name across to the map entry.
- */
- MapP->Name[MAX_NAME_LEN-1] = '\0';
- sptr = MapP->Name;
- while ( *sptr )
- {
- if ( *sptr<' ' || *sptr>'~' )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
- p->RIOError.Error = BAD_CHARACTER_IN_NAME;
- return -EINVAL;
- }
- sptr++;
- }
-
- for ( host=0; host < p->RIONumHosts; host++ )
- {
- if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum )
- {
- if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING )
- {
- p->RIOError.Error = HOST_NOT_RUNNING;
- return -ENXIO;
- }
-
- /*
- ** Now we have a host we need to allocate an ID
- ** if the entry does not already have one.
- */
- if (MapP->ID == (ushort)-1)
- {
- int nNewID;
-
- rio_dprintk (RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n",
- MapP->Name);
- /*
- ** The idea here is to allow RTA's to be assigned
- ** before they actually appear on the network.
- ** This allows the addition of RTA's without having
- ** to plug them in.
- ** What we do is:
- ** - Find a free ID and allocate it to the RTA.
- ** - If this map entry is the second half of a
- ** 16 port entry then find the other half and
- ** make sure the 2 cross reference each other.
- */
- if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0)
- {
- p->RIOError.Error = COULDNT_FIND_ENTRY;
- return -EBUSY;
- }
- MapP->ID = (ushort)nNewID + 1;
- rio_dprintk (RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
- HostMapP = &p->RIOHosts[host].Mapping[nNewID];
- HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
- HostMapP->HostUniqueNum = MapP->HostUniqueNum;
- HostMapP->ID = MapP->ID;
- for (link = 0; link < LINKS_PER_UNIT; link++)
- {
- HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
- HostMapP->Topology[link].Link = NO_LINK;
- }
- if (MapP->Flags & RTA16_SECOND_SLOT)
- {
- int unit;
-
- for (unit = 0; unit < MAX_RUP; unit++)
- if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum ==
- MapP->RtaUniqueNum)
- break;
- if (unit == MAX_RUP)
- {
- p->RIOError.Error = COULDNT_FIND_ENTRY;
- return -EBUSY;
- }
- HostMapP->Flags |= RTA16_SECOND_SLOT;
- HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
- p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
- rio_dprintk (RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n",
- MapP->ID,
- p->RIOHosts[host].Mapping[unit].ID);
+ int host;
+ struct Map *HostMapP;
+ char *sptr;
+ int link;
+
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
+
+ if ((MapP->ID != (ushort) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+ p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ if (MapP->RtaUniqueNum == 0) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
+ p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
+ return -EINVAL;
+ }
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
+ p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+ if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
+ p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+ return -EINVAL;
+ }
+
+ /*
+ ** Copy the name across to the map entry.
+ */
+ MapP->Name[MAX_NAME_LEN - 1] = '\0';
+ sptr = MapP->Name;
+ while (*sptr) {
+ if (*sptr < ' ' || *sptr > '~') {
+ rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+ p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+ return -EINVAL;
}
- }
+ sptr++;
+ }
- HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+ if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
+ p->RIOError.Error = HOST_NOT_RUNNING;
+ return -ENXIO;
+ }
- if ( HostMapP->Flags & SLOT_IN_USE )
- {
- rio_dprintk (RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
- p->RIOError.Error = ID_ALREADY_IN_USE;
- return -EBUSY;
- }
-
- /*
- ** Assign the sys ports and the name, and mark the slot as
- ** being in use.
- */
- HostMapP->SysPort = MapP->SysPort;
- if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
- CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
- HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
+ /*
+ ** Now we have a host we need to allocate an ID
+ ** if the entry does not already have one.
+ */
+ if (MapP->ID == (ushort) - 1) {
+ int nNewID;
+
+ rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
+ /*
+ ** The idea here is to allow RTA's to be assigned
+ ** before they actually appear on the network.
+ ** This allows the addition of RTA's without having
+ ** to plug them in.
+ ** What we do is:
+ ** - Find a free ID and allocate it to the RTA.
+ ** - If this map entry is the second half of a
+ ** 16 port entry then find the other half and
+ ** make sure the 2 cross reference each other.
+ */
+ if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
+ p->RIOError.Error = COULDNT_FIND_ENTRY;
+ return -EBUSY;
+ }
+ MapP->ID = (ushort) nNewID + 1;
+ rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
+ HostMapP = &p->RIOHosts[host].Mapping[nNewID];
+ HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
+ HostMapP->HostUniqueNum = MapP->HostUniqueNum;
+ HostMapP->ID = MapP->ID;
+ for (link = 0; link < LINKS_PER_UNIT; link++) {
+ HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
+ HostMapP->Topology[link].Link = NO_LINK;
+ }
+ if (MapP->Flags & RTA16_SECOND_SLOT) {
+ int unit;
+
+ for (unit = 0; unit < MAX_RUP; unit++)
+ if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
+ break;
+ if (unit == MAX_RUP) {
+ p->RIOError.Error = COULDNT_FIND_ENTRY;
+ return -EBUSY;
+ }
+ HostMapP->Flags |= RTA16_SECOND_SLOT;
+ HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
+ p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
+ rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
+ }
+ }
+
+ HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
+
+ if (HostMapP->Flags & SLOT_IN_USE) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
+ p->RIOError.Error = ID_ALREADY_IN_USE;
+ return -EBUSY;
+ }
+
+ /*
+ ** Assign the sys ports and the name, and mark the slot as
+ ** being in use.
+ */
+ HostMapP->SysPort = MapP->SysPort;
+ if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
+ CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN);
+ HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
#ifdef NEED_TO_FIX
- RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
+ RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
#endif
- if (MapP->Flags & RTA16_SECOND_SLOT)
- HostMapP->Flags |= RTA16_SECOND_SLOT;
-
- RIOReMapPorts( p, &p->RIOHosts[host], HostMapP );
- /*
- ** Adjust 2nd block of 8 phbs
- */
- if (MapP->Flags & RTA16_SECOND_SLOT)
- RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
-
- if ( HostMapP->SysPort != NO_PORT )
- {
- if ( HostMapP->SysPort < p->RIOFirstPortsBooted )
- p->RIOFirstPortsBooted = HostMapP->SysPort;
- if ( HostMapP->SysPort > p->RIOLastPortsBooted )
- p->RIOLastPortsBooted = HostMapP->SysPort;
- }
- if (MapP->Flags & RTA16_SECOND_SLOT)
- rio_dprintk (RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n",
- p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
- else
- rio_dprintk (RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
- return 0;
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+ RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
+ /*
+ ** Adjust 2nd block of 8 phbs
+ */
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
+
+ if (HostMapP->SysPort != NO_PORT) {
+ if (HostMapP->SysPort < p->RIOFirstPortsBooted)
+ p->RIOFirstPortsBooted = HostMapP->SysPort;
+ if (HostMapP->SysPort > p->RIOLastPortsBooted)
+ p->RIOLastPortsBooted = HostMapP->SysPort;
+ }
+ if (MapP->Flags & RTA16_SECOND_SLOT)
+ rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
+ else
+ rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
+ return 0;
+ }
}
- }
- p->RIOError.Error = UNKNOWN_HOST_NUMBER;
- rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
- return -ENXIO;
+ p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+ rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+ return -ENXIO;
}
-int
-RIOReMapPorts(p, HostP, HostMapP)
-struct rio_info * p;
+int RIOReMapPorts(p, HostP, HostMapP)
+struct rio_info *p;
struct Host *HostP;
-struct Map *HostMapP;
+struct Map *HostMapP;
{
register struct Port *PortP;
uint SubEnt;
@@ -818,136 +754,120 @@ struct Map *HostMapP;
ushort RtaType;
unsigned long flags;
-#ifdef CHECK
- CheckHostP( HostP );
- CheckHostMapP( HostMapP );
-#endif
-
- rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int)HostMapP->SysPort, HostMapP->ID);
+ rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
/*
- ** We need to tell the UnixRups which sysport the rup corresponds to
- */
- HostP->UnixRups[HostMapP->ID-1].BaseSysPort = HostMapP->SysPort;
+ ** We need to tell the UnixRups which sysport the rup corresponds to
+ */
+ HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
- if ( HostMapP->SysPort == NO_PORT )
- return(0);
+ if (HostMapP->SysPort == NO_PORT)
+ return (0);
RtaType = GetUnitType(HostMapP->RtaUniqueNum);
- rio_dprintk (RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n",
- (int)HostMapP->SysPort, (int)HostMapP->SysPort+PORTS_PER_RTA-1);
+ rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
/*
- ** now map each of its eight ports
- */
- for ( SubEnt=0; SubEnt<PORTS_PER_RTA; SubEnt++) {
- rio_dprintk (RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n",
- SubEnt, (int)HostMapP->SysPort);
- SysPort = HostMapP->SysPort+SubEnt; /* portnumber within system */
- /* portnumber on host */
-
- HostPort = (HostMapP->ID-1)*PORTS_PER_RTA+SubEnt;
-
- rio_dprintk (RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
+ ** now map each of its eight ports
+ */
+ for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
+ rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
+ SysPort = HostMapP->SysPort + SubEnt; /* portnumber within system */
+ /* portnumber on host */
+
+ HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
+
+ rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
PortP = p->RIOPortp[SysPort];
-#if 0
- PortP->TtyP = &p->channel[SysPort];
-#endif
- rio_dprintk (RIO_DEBUG_TABLE, "Map port\n");
+ rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
/*
- ** Point at all the real neat data structures
- */
+ ** Point at all the real neat data structures
+ */
rio_spin_lock_irqsave(&PortP->portSem, flags);
PortP->HostP = HostP;
PortP->Caddr = HostP->Caddr;
/*
- ** The PhbP cannot be filled in yet
- ** unless the host has been booted
- */
+ ** The PhbP cannot be filled in yet
+ ** unless the host has been booted
+ */
if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
- PortP->TxAdd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_add));
- PortP->TxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_start));
- PortP->TxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->tx_end));
- PortP->RxRemove=(WORD *)RIO_PTR(HostP->Caddr,
- RWORD(PhbP->rx_remove));
- PortP->RxStart =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_start));
- PortP->RxEnd =(WORD *)RIO_PTR(HostP->Caddr,RWORD(PhbP->rx_end));
- }
- else
+ PortP->TxAdd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_add));
+ PortP->TxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_start));
+ PortP->TxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->tx_end));
+ PortP->RxRemove = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_remove));
+ PortP->RxStart = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_start));
+ PortP->RxEnd = (WORD *) RIO_PTR(HostP->Caddr, RWORD(PhbP->rx_end));
+ } else
PortP->PhbP = NULL;
/*
- ** port related flags
- */
- PortP->HostPort = HostPort;
+ ** port related flags
+ */
+ PortP->HostPort = HostPort;
/*
- ** For each part of a 16 port RTA, RupNum is ID - 1.
- */
+ ** For each part of a 16 port RTA, RupNum is ID - 1.
+ */
PortP->RupNum = HostMapP->ID - 1;
if (HostMapP->Flags & RTA16_SECOND_SLOT) {
- PortP->ID2 = HostMapP->ID2 - 1;
- PortP->SecondBlock = TRUE;
- }
- else {
- PortP->ID2 = 0;
- PortP->SecondBlock = FALSE;
+ PortP->ID2 = HostMapP->ID2 - 1;
+ PortP->SecondBlock = TRUE;
+ } else {
+ PortP->ID2 = 0;
+ PortP->SecondBlock = FALSE;
}
- PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
+ PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
/*
- ** If the port was already mapped then thats all we need to do.
- */
+ ** If the port was already mapped then thats all we need to do.
+ */
if (PortP->Mapped) {
- rio_spin_unlock_irqrestore( &PortP->portSem, flags);
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
continue;
- }
- else HostMapP->Flags &= ~RTA_NEWBOOT;
+ } else
+ HostMapP->Flags &= ~RTA_NEWBOOT;
- PortP->State = 0;
- PortP->Config = 0;
+ PortP->State = 0;
+ PortP->Config = 0;
/*
- ** Check out the module type - if it is special (read only etc.)
- ** then we need to set flags in the PortP->Config.
- ** Note: For 16 port RTA, all ports are of the same type.
- */
+ ** Check out the module type - if it is special (read only etc.)
+ ** then we need to set flags in the PortP->Config.
+ ** Note: For 16 port RTA, all ports are of the same type.
+ */
if (RtaType == TYPE_RTA16) {
- PortP->Config |= p->RIOModuleTypes[HostP->UnixRups
- [HostMapP->ID-1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
+ PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
} else {
- if ( SubEnt < PORTS_PER_MODULE )
- PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups
- [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+ if (SubEnt < PORTS_PER_MODULE)
+ PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
else
- PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups
- [HostMapP->ID-1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+ PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
}
/*
- ** more port related flags
- */
- PortP->PortState = 0;
- PortP->ModemLines = 0;
- PortP->ModemState = 0;
- PortP->CookMode = COOK_WELL;
- PortP->ParamSem = 0;
- PortP->FlushCmdBodge= 0;
- PortP->WflushFlag = 0;
- PortP->MagicFlags = 0;
- PortP->Lock = 0;
- PortP->Store = 0;
- PortP->FirstOpen = 1;
+ ** more port related flags
+ */
+ PortP->PortState = 0;
+ PortP->ModemLines = 0;
+ PortP->ModemState = 0;
+ PortP->CookMode = COOK_WELL;
+ PortP->ParamSem = 0;
+ PortP->FlushCmdBodge = 0;
+ PortP->WflushFlag = 0;
+ PortP->MagicFlags = 0;
+ PortP->Lock = 0;
+ PortP->Store = 0;
+ PortP->FirstOpen = 1;
/*
- ** Buffers 'n things
- */
- PortP->RxDataStart = 0;
- PortP->Cor2Copy = 0;
- PortP->Name = &HostMapP->Name[0];
+ ** Buffers 'n things
+ */
+ PortP->RxDataStart = 0;
+ PortP->Cor2Copy = 0;
+ PortP->Name = &HostMapP->Name[0];
#ifdef STATS
- bzero( (caddr_t)&PortP->Stat, sizeof(struct RIOStats) );
+ bzero((caddr_t) & PortP->Stat, sizeof(struct RIOStats));
#endif
PortP->statsGather = 0;
PortP->txchars = 0;
@@ -955,90 +875,87 @@ struct Map *HostMapP;
PortP->opens = 0;
PortP->closes = 0;
PortP->ioctls = 0;
- if ( PortP->TxRingBuffer )
- bzero( PortP->TxRingBuffer, p->RIOBufferSize );
- else if ( p->RIOBufferSize ) {
+ if (PortP->TxRingBuffer)
+ bzero(PortP->TxRingBuffer, p->RIOBufferSize);
+ else if (p->RIOBufferSize) {
PortP->TxRingBuffer = sysbrk(p->RIOBufferSize);
- bzero( PortP->TxRingBuffer, p->RIOBufferSize );
+ bzero(PortP->TxRingBuffer, p->RIOBufferSize);
}
- PortP->TxBufferOut = 0;
- PortP->TxBufferIn = 0;
- PortP->Debug = 0;
+ PortP->TxBufferOut = 0;
+ PortP->TxBufferIn = 0;
+ PortP->Debug = 0;
/*
- ** LastRxTgl stores the state of the rx toggle bit for this
- ** port, to be compared with the state of the next pkt received.
- ** If the same, we have received the same rx pkt from the RTA
- ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
- */
- PortP->LastRxTgl = ~(uchar)PHB_RX_TGL;
+ ** LastRxTgl stores the state of the rx toggle bit for this
+ ** port, to be compared with the state of the next pkt received.
+ ** If the same, we have received the same rx pkt from the RTA
+ ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
+ */
+ PortP->LastRxTgl = ~(uchar) PHB_RX_TGL;
/*
- ** and mark the port as usable
- */
+ ** and mark the port as usable
+ */
PortP->Mapped = 1;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
}
- if ( HostMapP->SysPort < p->RIOFirstPortsMapped )
+ if (HostMapP->SysPort < p->RIOFirstPortsMapped)
p->RIOFirstPortsMapped = HostMapP->SysPort;
- if ( HostMapP->SysPort > p->RIOLastPortsMapped )
+ if (HostMapP->SysPort > p->RIOLastPortsMapped)
p->RIOLastPortsMapped = HostMapP->SysPort;
return 0;
}
-int
-RIOChangeName(p, MapP)
+int RIOChangeName(p, MapP)
struct rio_info *p;
-struct Map* MapP;
+struct Map *MapP;
{
int host;
struct Map *HostMapP;
char *sptr;
- rio_dprintk (RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n",
- MapP->HostUniqueNum,MapP->RtaUniqueNum,
- MapP->ID, (int)MapP->SysPort);
+ rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
- if ( MapP->ID > MAX_RUP ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+ if (MapP->ID > MAX_RUP) {
+ rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
return -EINVAL;
}
- MapP->Name[MAX_NAME_LEN-1] = '\0';
+ MapP->Name[MAX_NAME_LEN - 1] = '\0';
sptr = MapP->Name;
- while ( *sptr ) {
- if ( *sptr<' ' || *sptr>'~' ) {
- rio_dprintk (RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+ while (*sptr) {
+ if (*sptr < ' ' || *sptr > '~') {
+ rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
p->RIOError.Error = BAD_CHARACTER_IN_NAME;
return -EINVAL;
}
sptr++;
}
- for ( host=0; host < p->RIONumHosts; host++ ) {
- if ( MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum ) {
- if ( (p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING ) {
+ for (host = 0; host < p->RIONumHosts; host++) {
+ if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+ if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
p->RIOError.Error = HOST_NOT_RUNNING;
return -ENXIO;
}
- if ( MapP->ID==0 ) {
- CCOPY( MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN );
+ if (MapP->ID == 0) {
+ CCOPY(MapP->Name, p->RIOHosts[host].Name, MAX_NAME_LEN);
return 0;
}
- HostMapP = &p->RIOHosts[host].Mapping[MapP->ID-1];
+ HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
- if ( HostMapP->RtaUniqueNum != MapP->RtaUniqueNum ) {
+ if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
p->RIOError.Error = RTA_NUMBER_WRONG;
return -ENXIO;
}
- CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
+ CCOPY(MapP->Name, HostMapP->Name, MAX_NAME_LEN);
return 0;
}
}
p->RIOError.Error = UNKNOWN_HOST_NUMBER;
- rio_dprintk (RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+ rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
return -ENXIO;
}
diff --git a/drivers/char/rio/riotime.h b/drivers/char/rio/riotime.h
deleted file mode 100644
index 66d52bc0549b..000000000000
--- a/drivers/char/rio/riotime.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* T I M E
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _riotime_h
-#define _riotime_h 1
-
-#ifndef lint
-#ifdef SCCS
-static char *_rio_riotime_h_sccs = "@(#)riotime.h 1.1" ;
-#endif
-#endif
-
-#define TWO_POWER_FIFTEEN (ushort)32768
-#define RioTime() riotime
-#define RioTimeAfter(time1,time2) ((ushort)time1 - (ushort)time2) < TWO_POWER_FIFTEEN
-#define RioTimePlus(time1,time2) ((ushort)time1 + (ushort)time2)
-
-/**************************************
- * Convert a RIO tick (1/10th second)
- * into transputer low priority ticks
- *************************************/
-#define RioTimeToLow(time) (time*(100000 / 64))
-#define RioLowToTime(time) ((time*64)/100000)
-
-#define RIOTENTHSECOND (ushort)1
-#define RIOSECOND (ushort)(RIOTENTHSECOND * 10)
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 78a321afdf4f..6379816ed173 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -89,22 +89,13 @@ static char *_riotty_c_sccs_ = "@(#)riotty.c 1.3";
#include "list.h"
#include "sam.h"
-#if 0
-static void ttyseth_pv(struct Port *, struct ttystatics *,
- struct termios *sg, int);
-#endif
-
static void RIOClearUp(struct Port *PortP);
-int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg);
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-#if 0
-static int RIOCookMode(struct ttystatics *);
-#endif
-extern int conv_vb[]; /* now defined in ttymgr.c */
-extern int conv_bv[]; /* now defined in ttymgr.c */
-
+extern int conv_vb[]; /* now defined in ttymgr.c */
+extern int conv_bv[]; /* now defined in ttymgr.c */
+
/*
** 16.09.1998 ARG - Fix to build riotty.k.o for Modular Kernel Support
**
@@ -117,27 +108,25 @@ extern int conv_bv[]; /* now defined in ttymgr.c */
#endif
#ifdef NEED_THIS2
-static struct old_sgttyb
-default_sg =
-{
- B19200, B19200, /* input and output speed */
- 'H' - '@', /* erase char */
- -1, /* 2nd erase char */
- 'U' - '@', /* kill char */
- ECHO | CRMOD, /* mode */
- 'C' - '@', /* interrupt character */
- '\\' - '@', /* quit char */
- 'Q' - '@', /* start char */
- 'S' - '@', /* stop char */
- 'D' - '@', /* EOF */
- -1, /* brk */
- (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */
- 'Z' - '@', /* process stop */
- 'Y' - '@', /* delayed stop */
- 'R' - '@', /* reprint line */
- 'O' - '@', /* flush output */
- 'W' - '@', /* word erase */
- 'V' - '@' /* literal next char */
+static struct old_sgttyb default_sg = {
+ B19200, B19200, /* input and output speed */
+ 'H' - '@', /* erase char */
+ -1, /* 2nd erase char */
+ 'U' - '@', /* kill char */
+ ECHO | CRMOD, /* mode */
+ 'C' - '@', /* interrupt character */
+ '\\' - '@', /* quit char */
+ 'Q' - '@', /* start char */
+ 'S' - '@', /* stop char */
+ 'D' - '@', /* EOF */
+ -1, /* brk */
+ (LCRTBS | LCRTERA | LCRTKIL | LCTLECH), /* local mode word */
+ 'Z' - '@', /* process stop */
+ 'Y' - '@', /* delayed stop */
+ 'R' - '@', /* reprint line */
+ 'O' - '@', /* flush output */
+ 'W' - '@', /* word erase */
+ 'V' - '@' /* literal next char */
};
#endif
@@ -145,62 +134,59 @@ default_sg =
extern struct rio_info *p;
-int
-riotopen(struct tty_struct * tty, struct file * filp)
+int riotopen(struct tty_struct *tty, struct file *filp)
{
register uint SysPort;
int Modem;
int repeat_this = 250;
- struct Port *PortP; /* pointer to the port structure */
+ struct Port *PortP; /* pointer to the port structure */
unsigned long flags;
int retval = 0;
- func_enter ();
+ func_enter();
/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
is going to oops.
- */
+ */
tty->driver_data = NULL;
-
+
SysPort = rio_minor(tty);
- Modem = rio_ismodem(tty);
+ Modem = rio_ismodem(tty);
- if ( p->RIOFailed ) {
- rio_dprintk (RIO_DEBUG_TTY, "System initialisation failed\n");
+ if (p->RIOFailed) {
+ rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
pseterr(ENXIO);
- func_exit ();
+ func_exit();
return -ENXIO;
}
- rio_dprintk (RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n",
- SysPort, Modem ? "Modem" : "tty",
- p->RIOPortp[SysPort]->Mapped);
+ rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (%s) (mapped:%d)\n", SysPort, Modem ? "Modem" : "tty", p->RIOPortp[SysPort]->Mapped);
/*
- ** Validate that we have received a legitimate request.
- ** Currently, just check that we are opening a port on
- ** a host card that actually exists, and that the port
- ** has been mapped onto a host.
- */
+ ** Validate that we have received a legitimate request.
+ ** Currently, just check that we are opening a port on
+ ** a host card that actually exists, and that the port
+ ** has been mapped onto a host.
+ */
if (SysPort >= RIO_PORTS) { /* out of range ? */
- rio_dprintk (RIO_DEBUG_TTY, "Illegal port number %d\n",SysPort);
+ rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
pseterr(ENXIO);
func_exit();
return -ENXIO;
}
/*
- ** Grab pointer to the port stucture
- */
+ ** Grab pointer to the port stucture
+ */
PortP = p->RIOPortp[SysPort]; /* Get control struc */
- rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP);
- if ( !PortP->Mapped ) { /* we aren't mapped yet! */
+ rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
+ if (!PortP->Mapped) { /* we aren't mapped yet! */
/*
- ** The system doesn't know which RTA this port
- ** corresponds to.
- */
- rio_dprintk (RIO_DEBUG_TTY, "port not mapped into system\n");
- func_exit ();
+ ** The system doesn't know which RTA this port
+ ** corresponds to.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
+ func_exit();
pseterr(ENXIO);
return -ENXIO;
}
@@ -210,132 +196,93 @@ riotopen(struct tty_struct * tty, struct file * filp)
PortP->gs.tty = tty;
PortP->gs.count++;
- rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n",
- PortP->gs.xmit_cnt);
+ rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
- retval = gs_init_port (&PortP->gs);
+ retval = gs_init_port(&PortP->gs);
if (retval) {
PortP->gs.count--;
return -ENXIO;
}
/*
- ** If the host hasn't been booted yet, then
- ** fail
- */
- if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
- rio_dprintk (RIO_DEBUG_TTY, "Host not running\n");
+ ** If the host hasn't been booted yet, then
+ ** fail
+ */
+ if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
+ rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
pseterr(ENXIO);
- func_exit ();
+ func_exit();
return -ENXIO;
}
/*
- ** If the RTA has not booted yet and the user has choosen to block
- ** until the RTA is present then we must spin here waiting for
- ** the RTA to boot.
- */
-#if 0
- if (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
- if (PortP->WaitUntilBooted) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot\n");
- do {
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- func_exit ();
- return -EINTR;
- }
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
- pseterr(EINTR);
- func_exit ();
- return -EIO;
- }
- } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
- rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
- } else {
- rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
- pseterr(ENXIO);
- func_exit ();
- return 0;
- }
- }
-#else
+ ** If the RTA has not booted yet and the user has choosen to block
+ ** until the RTA is present then we must spin here waiting for
+ ** the RTA to boot.
+ */
/* I find the above code a bit hairy. I find the below code
- easier to read and shorter. Now, if it works too that would
+ easier to read and shorter. Now, if it works too that would
be great... -- REW
- */
- rio_dprintk (RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
- if (!PortP->WaitUntilBooted) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA never booted\n");
- func_exit ();
- return -ENXIO;
- }
-
- /* Under Linux you'd normally use a wait instead of this
- busy-waiting. I'll stick with the old implementation for
- now. --REW
- */
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
- func_exit ();
- return -EINTR;
- }
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
- func_exit ();
- return -EIO;
- }
+ if (!PortP->WaitUntilBooted) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
+ func_exit();
+ return -ENXIO;
+ }
+
+ /* Under Linux you'd normally use a wait instead of this
+ busy-waiting. I'll stick with the old implementation for
+ now. --REW
+ */
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
+ func_exit();
+ return -EINTR;
+ }
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+ func_exit();
+ return -EIO;
+ }
}
- rio_dprintk (RIO_DEBUG_TTY, "RTA has been booted\n");
-#endif
-#if 0
- tp = PortP->TtyP; /* get tty struct */
-#endif
+ rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
rio_spin_lock_irqsave(&PortP->portSem, flags);
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
-#if 0
- retval = gs_init_port(&PortP->gs);
- if (retval){
- func_exit ();
- return retval;
- }
-#endif
/*
- ** If the port is in the final throws of being closed,
- ** we should wait here (politely), waiting
- ** for it to finish, so that it doesn't close us!
- */
- while ( (PortP->State & RIO_CLOSING) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
- if (repeat_this -- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
+ ** If the port is in the final throws of being closed,
+ ** we should wait here (politely), waiting
+ ** for it to finish, so that it doesn't close us!
+ */
+ while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
+ if (repeat_this-- <= 0) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
retval = -EINTR;
goto bombout;
}
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_spin_lock_irqsave(&PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
retval = -EINTR;
goto bombout;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags);
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( !PortP->Mapped ) {
- rio_dprintk (RIO_DEBUG_TTY, "Port unmapped while closing!\n");
+ if (!PortP->Mapped) {
+ rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
retval = -ENXIO;
- func_exit ();
+ func_exit();
return retval;
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
@@ -346,16 +293,16 @@ riotopen(struct tty_struct * tty, struct file * filp)
*/
/* Uh? Suppose I turn these on and then another process opens
the port again? The flags get cleared! Not good. -- REW */
- if ( !(PortP->State & (RIO_LOPEN | RIO_MOPEN)) ) {
- PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+ if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+ PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
}
if (!(PortP->firstOpen)) { /* First time ? */
- rio_dprintk (RIO_DEBUG_TTY, "First open for this port\n");
-
+ rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
+
PortP->firstOpen++;
- PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
+ PortP->CookMode = 0; /* XXX RIOCookMode(tp); */
PortP->InUse = NOT_INUSE;
/* Tentative fix for bug PR27. Didn't work. */
@@ -363,26 +310,21 @@ riotopen(struct tty_struct * tty, struct file * filp)
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
#ifdef NEED_THIS
- ttyseth(PortP, tp, (struct old_sgttyb *)&default_sg);
+ ttyseth(PortP, tp, (struct old_sgttyb *) &default_sg);
#endif
/* Someone explain to me why this delay/config is
- here. If I read the docs correctly the "open"
- command piggybacks the parameters immediately.
+ here. If I read the docs correctly the "open"
+ command piggybacks the parameters immediately.
-- REW */
- RIOParam(PortP,OPEN,Modem,OK_TO_SLEEP); /* Open the port */
-#if 0
- /* This delay of 1 second was annoying. I removed it. -- REW */
- RIODelay(PortP, HUNDRED_MS*10);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); /* Config the port */
-#endif
+ RIOParam(PortP, OPEN, Modem, OK_TO_SLEEP); /* Open the port */
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** wait for the port to be not closed.
- */
- while ( !(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n",PortP->PortState);
+ ** wait for the port to be not closed.
+ */
+ while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
/*
** 15.10.1998 ARG - ESIL 0759
** (Part) fix for port being trashed when opened whilst RTA "disconnected"
@@ -399,115 +341,106 @@ riotopen(struct tty_struct * tty, struct file * filp)
*/
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
- func_exit ();
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ func_exit();
return -EINTR;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( p->RIOHalted ) {
- retval = -EIO;
-bombout:
- /* RIOClearUp( PortP ); */
+ if (p->RIOHalted) {
+ retval = -EIO;
+ bombout:
+ /* RIOClearUp( PortP ); */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return retval;
}
- rio_dprintk (RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
+ rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
}
-
-#ifdef MODEM_SUPPORT
+#ifdef MODEM_SUPPORT
if (Modem) {
- rio_dprintk (RIO_DEBUG_TTY, "Modem - test for carrier\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
/*
- ** ACTION
- ** insert test for carrier here. -- ???
- ** I already see that test here. What's the deal? -- REW
- */
- if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD))
- {
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
+ ** ACTION
+ ** insert test for carrier here. -- ???
+ ** I already see that test here. What's the deal? -- REW
+ */
+ if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
/*
- tp->tm.c_state |= CARR_ON;
- wakeup((caddr_t) &tp->tm.c_canq);
- */
+ tp->tm.c_state |= CARR_ON;
+ wakeup((caddr_t) &tp->tm.c_canq);
+ */
PortP->State |= RIO_CARR_ON;
- wake_up_interruptible (&PortP->gs.open_wait);
- }
- else /* no carrier - wait for DCD */
- {
- /*
- while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&
- !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
- */
- while (!(PortP->State & RIO_CARR_ON) &&
- !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted ) {
-
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n",SysPort);
+ wake_up_interruptible(&PortP->gs.open_wait);
+ } else { /* no carrier - wait for DCD */
+
+ /*
+ while (!(PortP->gs.tty->termios->c_state & CARR_ON) &&
+ !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
+ */
+ while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
+
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
/*
- PortP->gs.tty->termios->c_state |= WOPEN;
- */
+ PortP->gs.tty->termios->c_state |= WOPEN;
+ */
PortP->State |= RIO_WOPEN;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- if (RIODelay (PortP, HUNDRED_MS) == RIO_FAIL)
-#if 0
- if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH))
-#endif
- {
- /*
- ** ACTION: verify that this is a good thing
- ** to do here. -- ???
- ** I think it's OK. -- REW
- */
- rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n",
- SysPort);
- RIOPreemptiveCmd( p, PortP, FCLOSE );
- /*
- tp->tm.c_state &= ~WOPEN;
- */
- PortP->State &= ~RIO_WOPEN;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- func_exit ();
- return -EINTR;
- }
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL)
+ {
+ /*
+ ** ACTION: verify that this is a good thing
+ ** to do here. -- ???
+ ** I think it's OK. -- REW
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ /*
+ tp->tm.c_state &= ~WOPEN;
+ */
+ PortP->State &= ~RIO_WOPEN;
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ func_exit();
+ return -EINTR;
+ }
}
PortP->State &= ~RIO_WOPEN;
}
- if ( p->RIOHalted )
+ if (p->RIOHalted)
goto bombout;
- rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
PortP->State |= RIO_MOPEN;
- }
- else
+ } else
#endif
{
/*
- ** ACTION
- ** Direct line open - force carrier (will probably mean
- ** that sleeping Modem line fubar)
- */
+ ** ACTION
+ ** Direct line open - force carrier (will probably mean
+ ** that sleeping Modem line fubar)
+ */
PortP->State |= RIO_LOPEN;
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
goto bombout;
}
- rio_dprintk (RIO_DEBUG_TTY, "high level open done\n");
+ rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
#ifdef STATS
PortP->Stat.OpenCnt++;
#endif
/*
- ** Count opens for port statistics reporting
- */
+ ** Count opens for port statistics reporting
+ */
if (PortP->statsGather)
PortP->opens++;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n");
- func_exit ();
+ rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
+ func_exit();
return 0;
}
@@ -516,85 +449,73 @@ bombout:
** The operating system thinks that this is last close for the device.
** As there are two interfaces to the port (Modem and tty), we need to
** check that both are closed before we close the device.
-*/
-int
-riotclose(void *ptr)
+*/
+int riotclose(void *ptr)
{
-#if 0
- register uint SysPort = dev;
- struct ttystatics *tp; /* pointer to our ttystruct */
-#endif
struct Port *PortP = ptr; /* pointer to the port structure */
int deleted = 0;
- int try = -1; /* Disable the timeouts by setting them to -1 */
- int repeat_this = -1; /* Congrats to those having 15 years of
- uptime! (You get to break the driver.) */
+ int try = -1; /* Disable the timeouts by setting them to -1 */
+ int repeat_this = -1; /* Congrats to those having 15 years of
+ uptime! (You get to break the driver.) */
unsigned long end_time;
- struct tty_struct * tty;
+ struct tty_struct *tty;
unsigned long flags;
int Modem;
int rv = 0;
-
- rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
+
+ rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
/* PortP = p->RIOPortp[SysPort]; */
- rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP);
- /* tp = PortP->TtyP;*/ /* Get tty */
+ rio_dprintk(RIO_DEBUG_TTY, "Port is at address 0x%x\n", (int) PortP);
+ /* tp = PortP->TtyP; *//* Get tty */
tty = PortP->gs.tty;
- rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty);
+ rio_dprintk(RIO_DEBUG_TTY, "TTY is at address 0x%x\n", (int) tty);
- if (PortP->gs.closing_wait)
+ if (PortP->gs.closing_wait)
end_time = jiffies + PortP->gs.closing_wait;
- else
+ else
end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
Modem = rio_ismodem(tty);
-#if 0
- /* What F.CKING cache? Even then, a higly idle multiprocessor,
- system with large caches this won't work . Better find out when
- this doesn't work asap, and fix the cause. -- REW */
-
- RIODelay(PortP, HUNDRED_MS*10); /* To flush the cache */
-#endif
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** Setting this flag will make any process trying to open
- ** this port block until we are complete closing it.
- */
+ ** Setting this flag will make any process trying to open
+ ** this port block until we are complete closing it.
+ */
PortP->State |= RIO_CLOSING;
- if ( (PortP->State & RIO_DELETED) ) {
- rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n");
+ if ((PortP->State & RIO_DELETED)) {
+ rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
deleted = 1;
}
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
rv = -EIO;
goto close_end;
}
- rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
/*
- ** clear the open bits for this device
- */
+ ** clear the open bits for this device
+ */
PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN);
PortP->State &= ~RIO_CARR_ON;
PortP->ModemState &= ~MSVR1_CD;
/*
- ** If the device was open as both a Modem and a tty line
- ** then we need to wimp out here, as the port has not really
- ** been finally closed (gee, whizz!) The test here uses the
- ** bit for the OTHER mode of operation, to see if THAT is
- ** still active!
- */
- if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+ ** If the device was open as both a Modem and a tty line
+ ** then we need to wimp out here, as the port has not really
+ ** been finally closed (gee, whizz!) The test here uses the
+ ** bit for the OTHER mode of operation, to see if THAT is
+ ** still active!
+ */
+ if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
/*
- ** The port is still open for the other task -
- ** return, pretending that we are still active.
- */
- rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum);
+ ** The port is still open for the other task -
+ ** return, pretending that we are still active.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
PortP->State &= ~RIO_CLOSING;
if (PortP->firstOpen)
PortP->firstOpen--;
@@ -602,48 +523,47 @@ riotclose(void *ptr)
return -EIO;
}
- rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
PortP->State &= ~RIO_DYNOROD;
/*
- ** This is where we wait for the port
- ** to drain down before closing. Bye-bye....
- ** (We never meant to do this)
- */
- rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n");
+ ** This is where we wait for the port
+ ** to drain down before closing. Bye-bye....
+ ** (We never meant to do this)
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
if (!deleted)
- while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted &&
- (PortP->TxBufferIn != PortP->TxBufferOut) ) {
- cprintf("Need to flush the ttyport\n");
- if (repeat_this -- <= 0) {
- rv = -EINTR;
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE);
- goto close_end;
- }
- rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- rv = -EINTR;
+ while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
+ cprintf("Need to flush the ttyport\n");
+ if (repeat_this-- <= 0) {
+ rv = -EINTR;
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ goto close_end;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
+ rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+ if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+ rv = -EINTR;
+ rio_spin_lock_irqsave(&PortP->portSem, flags);
+ goto close_end;
+ }
rio_spin_lock_irqsave(&PortP->portSem, flags);
- goto close_end;
}
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- }
PortP->TxBufferIn = PortP->TxBufferOut = 0;
repeat_this = 0xff;
PortP->InUse = 0;
- if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) {
+ if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
/*
- ** The port has been re-opened for the other task -
- ** return, pretending that we are still active.
- */
- rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
+ ** The port has been re-opened for the other task -
+ ** return, pretending that we are still active.
+ */
+ rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
PortP->State &= ~RIO_CLOSING;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (PortP->firstOpen)
@@ -651,8 +571,8 @@ riotclose(void *ptr)
return -EIO;
}
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
goto close_end;
}
@@ -665,115 +585,73 @@ riotclose(void *ptr)
}
if (!deleted)
- while (try && (PortP->PortState & PORT_ISOPEN)) {
- try--;
- if (time_after (jiffies, end_time)) {
- rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" );
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- break;
- }
- rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n",
- PortP->PortState & PORT_ISOPEN);
+ while (try && (PortP->PortState & PORT_ISOPEN)) {
+ try--;
+ if (time_after(jiffies, end_time)) {
+ rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ break;
+ }
+ rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- goto close_end;
- }
- if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
- rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n");
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- break;
+ if (p->RIOHalted) {
+ RIOClearUp(PortP);
+ goto close_end;
+ }
+ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+ rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ break;
+ }
}
- }
rio_spin_lock_irqsave(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try );
-
+ rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
+
/* RIOPreemptiveCmd(p, PortP, FCLOSE); */
/*
** 15.10.1998 ARG - ESIL 0761 part fix
** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
*/
- PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
+ PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
#ifdef STATS
PortP->Stat.CloseCnt++;
#endif
/*
- ** Count opens for port statistics reporting
- */
+ ** Count opens for port statistics reporting
+ */
if (PortP->statsGather)
PortP->closes++;
-close_end:
+ close_end:
/* XXX: Why would a "DELETED" flag be reset here? I'd have
thought that a "deleted" flag means that the port was
permanently gone, but here we can make it reappear by it
being in close during the "deletion".
- */
- PortP->State &= ~(RIO_CLOSING|RIO_DELETED);
+ */
+ PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
if (PortP->firstOpen)
PortP->firstOpen--;
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Return from close\n");
+ rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
return rv;
}
-/*
-** decide if we need to use the line discipline.
-** This routine can return one of three values:
-** COOK_RAW if no processing has to be done by the line discipline or the card
-** COOK_WELL if the line discipline must be used to do the processing
-** COOK_MEDIUM if the card can do all the processing necessary.
-*/
-#if 0
-static int
-RIOCookMode(struct ttystatics *tp)
-{
- /*
- ** We can't handle tm.c_mstate != 0 on SCO
- ** We can't handle mapping
- ** We can't handle non-ttwrite line disc.
- ** We can't handle lflag XCASE
- ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3)
- */
-
-#ifdef CHECK
- CheckTtyP( tp );
-#endif
- if (!(tp->tm.c_oflag & OPOST)) /* No post processing */
- return COOK_RAW; /* Raw mode o/p */
-
- if ( tp->tm.c_lflag & XCASE )
- return COOK_WELL; /* Use line disc */
- if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) )
- return COOK_WELL; /* Use line disc for strange modes */
-
- if ( tp->tm.c_oflag == OPOST ) /* If only OPOST is set, do RAW */
- return COOK_RAW;
-
- /*
- ** So, we need to output process!
- */
- return COOK_MEDIUM;
-}
-#endif
-
-static void
-RIOClearUp(PortP)
+static void RIOClearUp(PortP)
struct Port *PortP;
{
- rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n");
- PortP->Config = 0; /* Direct semaphore */
+ rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
+ PortP->Config = 0; /* Direct semaphore */
PortP->PortState = 0;
PortP->firstOpen = 0;
PortP->FlushCmdBodge = 0;
PortP->ModemState = PortP->CookMode = 0;
PortP->Mapped = 0;
PortP->WflushFlag = 0;
- PortP->MagicFlags = 0;
+ PortP->MagicFlags = 0;
PortP->RxDataStart = 0;
PortP->TxBufferIn = 0;
PortP->TxBufferOut = 0;
@@ -788,33 +666,26 @@ struct Port *PortP;
** Other values of len aren't allowed, and will cause
** a panic.
*/
-int RIOShortCommand(struct rio_info *p, struct Port *PortP,
- int command, int len, int arg)
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
{
PKT *PacketP;
- int retries = 20; /* at 10 per second -> 2 seconds */
+ int retries = 20; /* at 10 per second -> 2 seconds */
unsigned long flags;
- rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n");
-#ifdef CHECK
- CheckPortP( PortP );
- if ( len < 1 || len > 2 )
- cprintf(("STUPID LENGTH %d\n",len));
-#endif
+ rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
return RIO_FAIL;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
/*
- ** If the port is in use for pre-emptive command, then wait for it to
- ** be free again.
- */
- while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n",
- retries);
+ ** If the port is in use for pre-emptive command, then wait for it to
+ ** be free again.
+ */
+ while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (retries-- <= 0) {
return RIO_FAIL;
@@ -824,47 +695,47 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP,
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( PortP->State & RIO_DELETED ) {
- rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+ if (PortP->State & RIO_DELETED) {
+ rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return RIO_FAIL;
}
- while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) {
- rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
+ while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
+ rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (retries-- <= 0) {
- rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n");
+ rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
return RIO_FAIL;
}
- if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) {
+ if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
return RIO_FAIL;
}
rio_spin_lock_irqsave(&PortP->portSem, flags);
}
- if ( p->RIOHalted ) {
+ if (p->RIOHalted) {
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
return RIO_FAIL;
}
/*
- ** set the command byte and the argument byte
- */
- WBYTE(PacketP->data[0] , command);
+ ** set the command byte and the argument byte
+ */
+ WBYTE(PacketP->data[0], command);
- if ( len==2 )
- WBYTE(PacketP->data[1] , arg);
+ if (len == 2)
+ WBYTE(PacketP->data[1], arg);
/*
- ** set the length of the packet and set the command bit.
- */
- WBYTE(PacketP->len , PKT_CMD_BIT | len);
+ ** set the length of the packet and set the command bit.
+ */
+ WBYTE(PacketP->len, PKT_CMD_BIT | len);
add_transmit(PortP);
/*
- ** Count characters transmitted for port statistics reporting
- */
+ ** Count characters transmitted for port statistics reporting
+ */
if (PortP->statsGather)
PortP->txchars += len;
@@ -873,501 +744,3 @@ int RIOShortCommand(struct rio_info *p, struct Port *PortP,
}
-#if 0
-/*
-** This is an ioctl interface. This is the twentieth century. You know what
-** its all about.
-*/
-int
-riotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg)
-{
- register struct Port *PortP;
- register struct ttystatics *tp;
- int current;
- int ParamSemIncremented = 0;
- int old_oflag, old_cflag, old_iflag, changed, oldcook;
- int i;
- unsigned char sio_regs[5]; /* Here be magic */
- short vpix_cflag;
- short divisor;
- int baud;
- uint SysPort = rio_minor(tty);
- int Modem = rio_ismodem(tty);
- int ioctl_processed;
-
- rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n",
- SysPort, cmd, arg, Modem?"Modem":"tty") ;
-
- if ( SysPort >= RIO_PORTS ) {
- rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort);
- return -ENXIO;
- }
-
- PortP = p->RIOPortp[SysPort];
- tp = PortP->TtyP;
-
- rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-#ifdef STATS
- PortP->Stat.IoctlCnt++;
-#endif
-
- if ( PortP->State & RIO_DELETED ) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return -EIO;
- }
-
- /*
- ** Count ioctls for port statistics reporting
- */
- if (PortP->statsGather)
- PortP->ioctls++;
-
- /*
- ** Specialix RIO Ioctl calls
- */
- switch (cmd) {
-
- case TCRIOTRIAD:
- if ( arg )
- PortP->State |= RIO_TRIAD_MODE;
- else
- PortP->State &= ~RIO_TRIAD_MODE;
- /*
- ** Normally, when istrip is set on a port, a config is
- ** sent to the RTA instructing the CD1400 to do the
- ** stripping. In TRIAD mode, the interrupt receive routine
- ** must do the stripping instead, since it has to detect
- ** an 8 bit function key sequence. If istrip is set with
- ** TRIAD mode on(off), and 8 bit data is being read by
- ** the port, the user then turns TRIAD mode off(on), the RTA
- ** must be reconfigured (not) to do the stripping.
- ** Hence we call RIOParam here.
- */
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIOTSTATE:
- rio_dprintk (RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n",
- arg ? "en" : "dis");
- /* MonitorTstate = 0 ;*/
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP);
- return 0;
-
- case TCRIOSTATE: /* current state of Modem input pins */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n");
- if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n");
- PortP->State |= RIO_BUSY;
- current = PortP->ModemState;
- if ( copyout((caddr_t)&current, (int)arg,
- sizeof(current))==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n");
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOMBIS: /* Set modem lines */
- case TCRIOMBIC: /* Clear modem lines */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n");
- if (cmd == TCRIOMBIS) {
- uint state;
- state = (uint)arg;
- PortP->ModemState |= (ushort)state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY,
- "TCRIOMBIS command failed\n");
- }
- else {
- uint state;
-
- state = (uint)arg;
- PortP->ModemState &= ~(ushort)state;
- PortP->ModemLines = (ulong) arg;
- if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL)
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n");
- }
- PortP->State |= RIO_BUSY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPON: /* set Xprint ON string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n");
- if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn,
- MAX_XP_CTRL_LEN)==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOn[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
- strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPOFF: /* set Xprint OFF string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n");
- if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff,
- MAX_XP_CTRL_LEN)==COPYFAIL ) {
- rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n");
- PortP->Xprint.XpOff[0] = '\0';
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0';
- PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+
- strlen(PortP->Xprint.XpOff);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPCPS: /* set Xprint CPS string */
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n");
- if ( (uint)arg > p->RIOConf.MaxXpCps ||
- (uint)arg < p->RIOConf.MinXpCps ) {
- rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg);
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EINVAL);
- return 0;
- }
- PortP->Xprint.XpCps = (uint)arg;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOXPRINT:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPRINT\n");
- if ( copyout((caddr_t)&PortP->Xprint, (int)arg,
- sizeof(struct Xprint))==COPYFAIL ) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EFAULT);
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYON:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n");
- PortP->Config |= RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXANYOFF:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n");
- PortP->Config &= ~RIO_IXANY;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONON:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n");
- PortP->Config |= RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
- case TCRIOIXONOFF:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n");
- PortP->Config &= ~RIO_IXON;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** Added support for CTS and RTS flow control ioctls :
-*/
- case TCRIOCTSFLOWEN:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n");
- PortP->Config |= RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIOCTSFLOWDIS:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n");
- PortP->Config &= ~RIO_CTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWEN:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n");
- PortP->Config |= RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
- case TCRIORTSFLOWDIS:
- rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n");
- PortP->Config &= ~RIO_RTSFLOW;
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- return 0;
-
-/* end ESIL 0761 part fix */
-
- }
-
-
- /* Lynx IOCTLS */
- switch (cmd) {
- case TIOCSETP:
- case TIOCSETN:
- case OTIOCSETP:
- case OTIOCSETN:
- ioctl_processed++;
- ttyseth(PortP, tp, (struct old_sgttyb *)arg);
- break;
- case TCSETA:
- case TCSETAW:
- case TCSETAF:
- ioctl_processed++;
- rio_dprintk (RIO_DEBUG_TTY, "NON POSIX ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *)arg, 0);
- break;
- case TCSETAP: /* posix tcsetattr() */
- case TCSETAWP: /* posix tcsetattr() */
- case TCSETAFP: /* posix tcsetattr() */
- rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n");
- ttyseth_pv(PortP, tp, (struct termios *)arg, 1);
- ioctl_processed++;
- break;
- }
-
- /*
- ** If its any of the commands that require the port to be in the
- ** non-busy state wait until all output has drained
- */
- if (!ioctl_processed)
- switch(cmd) {
- case TCSETAW:
- case TCSETAF:
- case TCSETA:
- case TCSBRK:
-#define OLD_POSIX ('x' << 8)
-#define OLD_POSIX_SETA (OLD_POSIX | 2)
-#define OLD_POSIX_SETAW (OLD_POSIX | 3)
-#define OLD_POSIX_SETAF (OLD_POSIX | 4)
-#define NEW_POSIX (('i' << 24) | ('X' << 16))
-#define NEW_POSIX_SETA (NEW_POSIX | 2)
-#define NEW_POSIX_SETAW (NEW_POSIX | 3)
-#define NEW_POSIX_SETAF (NEW_POSIX | 4)
- case OLD_POSIX_SETA:
- case OLD_POSIX_SETAW:
- case OLD_POSIX_SETAF:
- case NEW_POSIX_SETA:
- case NEW_POSIX_SETAW:
- case NEW_POSIX_SETAF:
-#ifdef TIOCSETP
- case TIOCSETP:
-#endif
- case TIOCSETD:
- case TIOCSETN:
- rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n");
- /*
- ** Wait for drain here, at least as far as the double buffer
- ** being empty.
- */
- /* XXX Does the above comment mean that this has
- still to be implemented? -- REW */
- /* XXX Is the locking OK together with locking
- in txenable? (Deadlock?) -- REW */
-
- RIOTxEnable((char *)PortP);
- break;
- default:
- break;
- }
-
- old_cflag = tp->tm.c_cflag;
- old_iflag = tp->tm.c_iflag;
- old_oflag = tp->tm.c_oflag;
- oldcook = PortP->CookMode;
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
-
- PortP->FlushCmdBodge = 0;
-
- /*
- ** If the port is locked, and it is reconfigured, we want
- ** to restore the state of the tty structure so the change is NOT
- ** made.
- */
- if (PortP->Lock) {
- tp->tm.c_iflag = PortP->StoredTty.iflag;
- tp->tm.c_oflag = PortP->StoredTty.oflag;
- tp->tm.c_cflag = PortP->StoredTty.cflag;
- tp->tm.c_lflag = PortP->StoredTty.lflag;
- tp->tm.c_line = PortP->StoredTty.line;
- for (i = 0; i < NCC + 1; i++)
- tp->tm.c_cc[i] = PortP->StoredTty.cc[i];
- }
- else {
- /*
- ** If the port is set to store the parameters, and it is
- ** reconfigured, we want to save the current tty struct so it
- ** may be restored on the next open.
- */
- if (PortP->Store) {
- PortP->StoredTty.iflag = tp->tm.c_iflag;
- PortP->StoredTty.oflag = tp->tm.c_oflag;
- PortP->StoredTty.cflag = tp->tm.c_cflag;
- PortP->StoredTty.lflag = tp->tm.c_lflag;
- PortP->StoredTty.line = tp->tm.c_line;
- for (i = 0; i < NCC + 1; i++)
- PortP->StoredTty.cc[i] = tp->tm.c_cc[i];
- }
- }
-
- changed = (tp->tm.c_cflag != old_cflag) ||
- (tp->tm.c_iflag != old_iflag) ||
- (tp->tm.c_oflag != old_oflag);
-
- PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */
-
- rio_dprintk (RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n",
- changed,PortP->CookMode,oldcook);
-
-#ifdef MODEM_SUPPORT
- /*
- ** kludge to force CARR_ON if CLOCAL set
- */
- if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
- tp->tm.c_state |= CARR_ON;
- wakeup ((caddr_t)&tp->tm.c_canq);
- }
-#endif
-
- if ( p->RIOHalted ) {
- RIOClearUp( PortP );
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- pseterr(EIO);
- return 0;
- }
- /*
- ** Re-configure if modes or cooking have changed
- */
- if (changed || oldcook != PortP->CookMode || (ioctl_processed)) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- rio_dprintk (RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n");
- RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP);
- rio_spin_lock_irqsave(&PortP->portSem, flags);
- }
-
- if (p->RIOHalted) {
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- RIOClearUp( PortP );
- pseterr(EIO);
- return 0;
- }
- rio_spin_unlock_irqrestore(&PortP->portSem, flags);
- return 0;
-}
-
-/*
- ttyseth -- set hardware dependent tty settings
-*/
-void
-ttyseth(PortP, s, sg)
-struct Port * PortP;
-struct ttystatics * s;
-struct old_sgttyb *sg;
-{
- struct old_sgttyb * tsg;
- struct termios *tp = &s->tm;
-
- tsg = &s->sg;
-
- if (sg->sg_flags & (EVENP|ODDP)) {
- tp->c_cflag &= PARENB;
- if (sg->sg_flags & EVENP) {
- if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= ~PARENB;
- }
- else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- }
- }
- else if (sg->sg_flags & ODDP) {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- tp->c_cflag &= PARODD;
- }
- else {
- tp->c_cflag &= V_CS7;
- tp->c_cflag &= PARENB;
- }
- }
-/*
- * Use ispeed as the desired speed. Most implementations don't handle
- * separate input and output speeds very well. If the RIO handles this,
- * I will have to use separate sets of flags to store them in the
- * Port structure.
- */
- if ( !sg->sg_ospeed )
- sg->sg_ospeed = sg->sg_ispeed;
- else
- sg->sg_ispeed = sg->sg_ospeed;
- if (sg->sg_ispeed > V_EXTB )
- sg->sg_ispeed = V_EXTB;
- if (sg->sg_ispeed < V_B0)
- sg->sg_ispeed = V_B0;
- *tsg = *sg;
- tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed];
-}
-
-/*
- ttyseth_pv -- set hardware dependent tty settings using either the
- POSIX termios structure or the System V termio structure.
- sysv = 0 => (POSIX): struct termios *sg
- sysv != 0 => (System V): struct termio *sg
-*/
-static void
-ttyseth_pv(PortP, s, sg, sysv)
-struct Port *PortP;
-struct ttystatics *s;
-struct termios *sg;
-int sysv;
-{
- int speed;
- unsigned char csize;
- unsigned char cread;
- unsigned int lcr_flags;
- int ps;
-
- if (sysv) {
- /* sg points to a System V termio structure */
- csize = ((struct termio *)sg)->c_cflag & CSIZE;
- cread = ((struct termio *)sg)->c_cflag & CREAD;
- speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD];
- }
- else {
- /* sg points to a POSIX termios structure */
- csize = sg->c_cflag & CSIZE;
- cread = sg->c_cflag & CREAD;
- speed = conv_vb[sg->c_cflag & V_CBAUD];
- }
- if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) {
- s->sg.sg_ispeed = speed;
- s->sg.sg_ospeed = speed;
- s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) |
- conv_bv[(int)s->sg.sg_ispeed];
- }
-}
-#endif
diff --git a/drivers/char/rio/riotypes.h b/drivers/char/rio/riotypes.h
index 1c7c42c638f0..9b67e2468bec 100644
--- a/drivers/char/rio/riotypes.h
+++ b/drivers/char/rio/riotypes.h
@@ -89,47 +89,46 @@ typedef RIO_POINTER u_short_ptr;
typedef RIO_POINTER ushort_ptr;
#endif
-#else /* not INKERNEL */
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned long DWORD;
-typedef short NUMBER;
-typedef short *NUMBER_ptr;
-typedef unsigned short *WORD_ptr;
-typedef unsigned char *BYTE_ptr;
-typedef unsigned char uchar ;
-typedef unsigned short ushort ;
-typedef unsigned int uint ;
-typedef unsigned long ulong ;
-typedef unsigned char u_char ;
-typedef unsigned short u_short ;
-typedef unsigned int u_int ;
-typedef unsigned long u_long ;
-typedef unsigned short ERROR ;
-typedef unsigned long ID ;
-typedef char *char_ptr;
-typedef Channel *Channel_ptr;
+#else /* not INKERNEL */
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef short NUMBER;
+typedef short *NUMBER_ptr;
+typedef unsigned short *WORD_ptr;
+typedef unsigned char *BYTE_ptr;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+typedef unsigned short ERROR;
+typedef unsigned long ID;
+typedef char *char_ptr;
+typedef Channel *Channel_ptr;
typedef struct FREE_LIST *FREE_LIST_ptr;
typedef struct FREE_LIST **FREE_LIST_ptr_ptr;
-typedef struct LPB *LPB_ptr;
-typedef struct Process *Process_ptr;
-typedef struct PHB *PHB_ptr;
-typedef struct PKT *PKT_ptr;
-typedef struct PKT **PKT_ptr_ptr;
-typedef struct Q_BUF *Q_BUF_ptr;
-typedef struct Q_BUF **Q_BUF_ptr_ptr;
+typedef struct LPB *LPB_ptr;
+typedef struct Process *Process_ptr;
+typedef struct PHB *PHB_ptr;
+typedef struct PKT *PKT_ptr;
+typedef struct PKT **PKT_ptr_ptr;
+typedef struct Q_BUF *Q_BUF_ptr;
+typedef struct Q_BUF **Q_BUF_ptr_ptr;
typedef struct ROUTE_STR *ROUTE_STR_ptr;
-typedef struct RUP *RUP_ptr;
-typedef short *short_ptr;
-typedef u_short *u_short_ptr;
-typedef ushort *ushort_ptr;
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
+typedef struct RUP *RUP_ptr;
+typedef short *short_ptr;
+typedef u_short *u_short_ptr;
+typedef ushort *ushort_ptr;
+typedef struct PKT PKT;
+typedef struct LPB LPB;
+typedef struct RUP RUP;
#endif
-#endif /* __riotypes__ */
+#endif /* __riotypes__ */
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/riowinif.h b/drivers/char/rio/riowinif.h
deleted file mode 100644
index 18a4f147edc2..000000000000
--- a/drivers/char/rio/riowinif.h
+++ /dev/null
@@ -1,1335 +0,0 @@
-/************************************************************************/
-/* */
-/* Title : RIO Shared Memory Window Inteface */
-/* */
-/* Author : N.P.Vassallo */
-/* */
-/* Creation : 7th June 1999 */
-/* */
-/* Version : 1.0.0 */
-/* */
-/* Copyright : (c) Specialix International Ltd. 1999 *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public 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.
- * */
-/* Description : Prototypes, structures and definitions */
-/* describing RIO host card shared memory */
-/* window interface structures: */
-/* PARMMAP */
-/* RUP */
-/* PHB */
-/* LPB */
-/* PKT */
-/* */
-/************************************************************************/
-
-/* History...
-
-1.0.0 07/06/99 NPV Creation. (based on PARMMAP.H)
-
-*/
-
-#ifndef _riowinif_h /* If RIOWINDIF.H not already defined */
-#define _riowinif_h 1
-
-/*****************************************************************************
-******************************** *********************************
-******************************** General *********************************
-******************************** *********************************
-*****************************************************************************/
-
-#define TPNULL ((_u16)(0x8000))
-
-/*****************************************************************************
-******************************** ********************************
-******************************** PARM_MAP ********************************
-******************************** ********************************
-*****************************************************************************/
-
-/* The PARM_MAP structure defines global values relating to the Host Card / RTA
- and is the main structure from which all other structures are referenced. */
-
-typedef struct _PARM_MAP
-{
- _u16 phb_ptr; /* 0x00 Pointer to the PHB array */
- _u16 phb_num_ptr; /* 0x02 Ptr to Number of PHB's */
- _u16 free_list; /* 0x04 Free List pointer */
- _u16 free_list_end; /* 0x06 Free List End pointer */
- _u16 q_free_list_ptr; /* 0x08 Ptr to Q_BUF variable */
- _u16 unit_id_ptr; /* 0x0A Unit Id */
- _u16 link_str_ptr; /* 0x0C Link Structure Array */
- _u16 bootloader_1; /* 0x0E 1st Stage Boot Loader */
- _u16 bootloader_2; /* 0x10 2nd Stage Boot Loader */
- _u16 port_route_map_ptr; /* 0x12 Port Route Map */
- _u16 route_ptr; /* 0x14 Route Map */
- _u16 map_present; /* 0x16 Route Map present */
- _u16 pkt_num; /* 0x18 Total number of packets */
- _u16 q_num; /* 0x1A Total number of Q packets */
- _u16 buffers_per_port; /* 0x1C Number of buffers per port */
- _u16 heap_size; /* 0x1E Initial size of heap */
- _u16 heap_left; /* 0x20 Current Heap left */
- _u16 error; /* 0x22 Error code */
- _u16 tx_max; /* 0x24 Max number of tx pkts per phb */
- _u16 rx_max; /* 0x26 Max number of rx pkts per phb */
- _u16 rx_limit; /* 0x28 For high / low watermarks */
- _u16 links; /* 0x2A Links to use */
- _u16 timer; /* 0x2C Interrupts per second */
- _u16 rups; /* 0x2E Pointer to the RUPs */
- _u16 max_phb; /* 0x30 Mostly for debugging */
- _u16 living; /* 0x32 Just increments!! */
- _u16 init_done; /* 0x34 Initialisation over */
- _u16 booting_link; /* 0x36 */
- _u16 idle_count; /* 0x38 Idle time counter */
- _u16 busy_count; /* 0x3A Busy counter */
- _u16 idle_control; /* 0x3C Control Idle Process */
- _u16 tx_intr; /* 0x3E TX interrupt pending */
- _u16 rx_intr; /* 0x40 RX interrupt pending */
- _u16 rup_intr; /* 0x42 RUP interrupt pending */
-
-} PARM_MAP;
-
-/* Same thing again, but defined as offsets... */
-
-#define PM_phb_ptr 0x00 /* 0x00 Pointer to the PHB array */
-#define PM_phb_num_ptr 0x02 /* 0x02 Ptr to Number of PHB's */
-#define PM_free_list 0x04 /* 0x04 Free List pointer */
-#define PM_free_list_end 0x06 /* 0x06 Free List End pointer */
-#define PM_q_free_list_ptr 0x08 /* 0x08 Ptr to Q_BUF variable */
-#define PM_unit_id_ptr 0x0A /* 0x0A Unit Id */
-#define PM_link_str_ptr 0x0C /* 0x0C Link Structure Array */
-#define PM_bootloader_1 0x0E /* 0x0E 1st Stage Boot Loader */
-#define PM_bootloader_2 0x10 /* 0x10 2nd Stage Boot Loader */
-#define PM_port_route_map_ptr 0x12 /* 0x12 Port Route Map */
-#define PM_route_ptr 0x14 /* 0x14 Route Map */
-#define PM_map_present 0x16 /* 0x16 Route Map present */
-#define PM_pkt_num 0x18 /* 0x18 Total number of packets */
-#define PM_q_num 0x1A /* 0x1A Total number of Q packets */
-#define PM_buffers_per_port 0x1C /* 0x1C Number of buffers per port */
-#define PM_heap_size 0x1E /* 0x1E Initial size of heap */
-#define PM_heap_left 0x20 /* 0x20 Current Heap left */
-#define PM_error 0x22 /* 0x22 Error code */
-#define PM_tx_max 0x24 /* 0x24 Max number of tx pkts per phb */
-#define PM_rx_max 0x26 /* 0x26 Max number of rx pkts per phb */
-#define PM_rx_limit 0x28 /* 0x28 For high / low watermarks */
-#define PM_links 0x2A /* 0x2A Links to use */
-#define PM_timer 0x2C /* 0x2C Interrupts per second */
-#define PM_rups 0x2E /* 0x2E Pointer to the RUPs */
-#define PM_max_phb 0x30 /* 0x30 Mostly for debugging */
-#define PM_living 0x32 /* 0x32 Just increments!! */
-#define PM_init_done 0x34 /* 0x34 Initialisation over */
-#define PM_booting_link 0x36 /* 0x36 */
-#define PM_idle_count 0x38 /* 0x38 Idle time counter */
-#define PM_busy_count 0x3A /* 0x3A Busy counter */
-#define PM_idle_control 0x3C /* 0x3C Control Idle Process */
-#define PM_tx_intr 0x3E /* 0x4E TX interrupt pending */
-#define PM_rx_intr 0x40 /* 0x40 RX interrupt pending */
-#define PM_rup_intr 0x42 /* 0x42 RUP interrupt pending */
-#define sizeof_PARM_MAP 0x44 /* structure size = 0x44 */
-
-/* PARM_MAP.error definitions... */
-#define E_NO_ERROR 0x00
-#define E_PROCESS_NOT_INIT 0x01
-#define E_LINK_TIMEOUT 0x02
-#define E_NO_ROUTE 0x03
-#define E_CONFUSED 0x04
-#define E_HOME 0x05
-#define E_CSUM_FAIL 0x06
-#define E_DISCONNECTED 0x07
-#define E_BAD_RUP 0x08
-#define E_NO_VIRGIN 0x09
-#define E_BOOT_RUP_BUSY 0x10
-#define E_CHANALLOC 0x80
-#define E_POLL_ALLOC 0x81
-#define E_LTTWAKE 0x82
-#define E_LTT_ALLOC 0x83
-#define E_LRT_ALLOC 0x84
-#define E_CIRRUS 0x85
-#define E_MONITOR 0x86
-#define E_PHB_ALLOC 0x87
-#define E_ARRAY_ALLOC 0x88
-#define E_QBUF_ALLOC 0x89
-#define E_PKT_ALLOC 0x8a
-#define E_GET_TX_Q_BUF 0x8b
-#define E_GET_RX_Q_BUF 0x8c
-#define E_MEM_OUT 0x8d
-#define E_MMU_INIT 0x8e
-#define E_LTT_INIT 0x8f
-#define E_LRT_INIT 0x90
-#define E_LINK_RUN 0x91
-#define E_MONITOR_ALLOC 0x92
-#define E_MONITOR_INIT 0x93
-#define E_POLL_INIT 0x94
-
-/* PARM_MAP.links definitions... */
-#define RIO_LINK_ENABLE 0x80FF
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** RUP ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The RUP (Remote Unit Port) structure relates to the Remote Terminal Adapters
- attached to the system and there is normally an array of MAX_RUPS (=16) structures
- in a host card, defined by PARM_MAP->rup. */
-
-typedef struct _RUP
-{
- _u16 txpkt; /* 0x00 Outgoing packet */
- _u16 rxpkt; /* 0x02 ncoming packet */
- _u16 link; /* 0x04 Which link to send packet down ? */
- _u8 rup_dest_unit[2]; /* 0x06 Destination Unit */
- _u16 handshake; /* 0x08 Handshaking */
- _u16 timeout; /* 0x0A Timeout */
- _u16 status; /* 0x0C Status */
- _u16 txcontrol; /* 0x0E Transmit control */
- _u16 rxcontrol; /* 0x10 Receive control */
-
-} RUP;
-
-/* Same thing again, but defined as offsets... */
-
-#define RUP_txpkt 0x00 /* 0x00 Outgoing packet */
-#define RUP_rxpkt 0x02 /* 0x02 Incoming packet */
-#define RUP_link 0x04 /* 0x04 Which link to send packet down ? */
-#define RUP_rup_dest_unit 0x06 /* 0x06 Destination Unit */
-#define RUP_handshake 0x08 /* 0x08 Handshaking */
-#define RUP_timeout 0x0A /* 0x0A Timeout */
-#define RUP_status 0x0C /* 0x0C Status */
-#define RUP_txcontrol 0x0E /* 0x0E Transmit control */
-#define RUP_rxcontrol 0x10 /* 0x10 Receive control */
-#define sizeof_RUP 0x12 /* structure size = 0x12 */
-
-#define MAX_RUP 16
-
-/* RUP.txcontrol definitions... */
-#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
-#define TX_PACKET_READY 1 /* Transmit packet ready */
-#define TX_LOCK_RUP 2 /* Transmit side locked */
-
-/* RUP.txcontrol definitions... */
-#define RX_RUP_INACTIVE 0 /* Nothing received */
-#define RX_PACKET_READY 1 /* Packet received */
-
-#define RUP_NO_OWNER 0xFF /* RUP not owned by any process */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PHB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PHB (Port Header Block) structure relates to the serial ports attached
- to the system and there is normally an array of MAX_PHBS (=128) structures
- in a host card, defined by PARM_MAP->phb_ptr and PARM_MAP->phb_num_ptr. */
-
-typedef struct _PHB
-{
- _u16 source; /* 0x00 Location of the PHB in the host card */
- _u16 handshake; /* 0x02 Used to manage receive packet flow control */
- _u16 status; /* 0x04 Internal port transmit/receive status */
- _u16 timeout; /* 0x06 Time period to wait for an ACK */
- _u16 link; /* 0x08 The host link associated with the PHB */
- _u16 destination; /* 0x0A Location of the remote port on the network */
-
- _u16 tx_start; /* 0x0C first entry in the packet array for transmit packets */
- _u16 tx_end; /* 0x0E last entry in the packet array for transmit packets */
- _u16 tx_add; /* 0x10 position in the packet array for new transmit packets */
- _u16 tx_remove; /* 0x12 current position in the packet pointer array */
-
- _u16 rx_start; /* 0x14 first entry in the packet array for receive packets */
- _u16 rx_end; /* 0x16 last entry in the packet array for receive packets */
- _u16 rx_add; /* 0x18 position in the packet array for new receive packets */
- _u16 rx_remove; /* 0x1A current position in the packet pointer array */
-
-} PHB;
-
-/* Same thing again, but defined as offsets... */
-
-#define PHB_source 0x00 /* 0x00 Location of the PHB in the host card */
-#define PHB_handshake 0x02 /* 0x02 Used to manage receive packet flow control */
-#define PHB_status 0x04 /* 0x04 Internal port transmit/receive status */
-#define PHB_timeout 0x06 /* 0x06 Time period to wait for an ACK */
-#define PHB_link 0x08 /* 0x08 The host link associated with the PHB */
-#define PHB_destination 0x0A /* 0x0A Location of the remote port on the network */
-#define PHB_tx_start 0x0C /* 0x0C first entry in the packet array for transmit packets */
-#define PHB_tx_end 0x0E /* 0x0E last entry in the packet array for transmit packets */
-#define PHB_tx_add 0x10 /* 0x10 position in the packet array for new transmit packets */
-#define PHB_tx_remove 0x12 /* 0x12 current position in the packet pointer array */
-#define PHB_rx_start 0x14 /* 0x14 first entry in the packet array for receive packets */
-#define PHB_rx_end 0x16 /* 0x16 last entry in the packet array for receive packets */
-#define PHB_rx_add 0x18 /* 0x18 position in the packet array for new receive packets */
-#define PHB_rx_remove 0x1A /* 0x1A current position in the packet pointer array */
-#define sizeof_PHB 0x1C /* structure size = 0x1C */
-
-/* PHB.handshake definitions... */
-#define PHB_HANDSHAKE_SET 0x0001 /* Set by LRT */
-#define PHB_HANDSHAKE_RESET 0x0002 /* Set by ISR / driver */
-#define PHB_HANDSHAKE_FLAGS (PHB_HANDSHAKE_RESET|PHB_HANDSHAKE_SET)
- /* Reset by ltt */
-
-#define MAX_PHB 128 /* range 0-127 */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** LPB ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The LPB (Link Parameter Block) structure relates to a RIO Network Link
- and there is normally an array of MAX_LINKS (=4) structures in a host card,
- defined by PARM_MAP->link_str_ptr. */
-
-typedef struct _LPB
-{
- _u16 link_number; /* 0x00 Link Number */
- _u16 in_ch; /* 0x02 Link In Channel */
- _u16 out_ch; /* 0x04 Link Out Channel */
- _u8 attached_serial[4]; /* 0x06 Attached serial number */
- _u8 attached_host_serial[4];/* 0x0A Serial number of Host who booted other end */
- _u16 descheduled; /* 0x0E Currently Descheduled */
- _u16 state; /* 0x10 Current state */
- _u16 send_poll; /* 0x12 Send a Poll Packet */
- _u16 ltt_p; /* 0x14 Process Descriptor */
- _u16 lrt_p; /* 0x16 Process Descriptor */
- _u16 lrt_status; /* 0x18 Current lrt status */
- _u16 ltt_status; /* 0x1A Current ltt status */
- _u16 timeout; /* 0x1C Timeout value */
- _u16 topology; /* 0x1E Topology bits */
- _u16 mon_ltt; /* 0x20 */
- _u16 mon_lrt; /* 0x22 */
- _u16 num_pkts; /* 0x24 */
- _u16 add_packet_list; /* 0x26 Add packets to here */
- _u16 remove_packet_list; /* 0x28 Send packets from here */
-
- _u16 lrt_fail_chan; /* 0x2A Lrt's failure channel */
- _u16 ltt_fail_chan; /* 0x2C Ltt's failure channel */
-
- RUP rup; /* 0x2E RUP structure for HOST to driver comms */
- RUP link_rup; /* 0x40 RUP for the link (POLL, topology etc.) */
- _u16 attached_link; /* 0x52 Number of attached link */
- _u16 csum_errors; /* 0x54 csum errors */
- _u16 num_disconnects; /* 0x56 number of disconnects */
- _u16 num_sync_rcvd; /* 0x58 # sync's received */
- _u16 num_sync_rqst; /* 0x5A # sync requests */
- _u16 num_tx; /* 0x5C Num pkts sent */
- _u16 num_rx; /* 0x5E Num pkts received */
- _u16 module_attached; /* 0x60 Module tpyes of attached */
- _u16 led_timeout; /* 0x62 LED timeout */
- _u16 first_port; /* 0x64 First port to service */
- _u16 last_port; /* 0x66 Last port to service */
-
-} LPB;
-
-/* Same thing again, but defined as offsets... */
-
-#define LPB_link_number 0x00 /* 0x00 Link Number */
-#define LPB_in_ch 0x02 /* 0x02 Link In Channel */
-#define LPB_out_ch 0x04 /* 0x04 Link Out Channel */
-#define LPB_attached_serial 0x06 /* 0x06 Attached serial number */
-#define LPB_attached_host_serial 0x0A /* 0x0A Serial number of Host who booted other end */
-#define LPB_descheduled 0x0E /* 0x0E Currently Descheduled */
-#define LPB_state 0x10 /* 0x10 Current state */
-#define LPB_send_poll 0x12 /* 0x12 Send a Poll Packet */
-#define LPB_ltt_p 0x14 /* 0x14 Process Descriptor */
-#define LPB_lrt_p 0x16 /* 0x16 Process Descriptor */
-#define LPB_lrt_status 0x18 /* 0x18 Current lrt status */
-#define LPB_ltt_status 0x1A /* 0x1A Current ltt status */
-#define LPB_timeout 0x1C /* 0x1C Timeout value */
-#define LPB_topology 0x1E /* 0x1E Topology bits */
-#define LPB_mon_ltt 0x20 /* 0x20 */
-#define LPB_mon_lrt 0x22 /* 0x22 */
-#define LPB_num_pkts 0x24 /* 0x24 */
-#define LPB_add_packet_list 0x26 /* 0x26 Add packets to here */
-#define LPB_remove_packet_list 0x28 /* 0x28 Send packets from here */
-#define LPB_lrt_fail_chan 0x2A /* 0x2A Lrt's failure channel */
-#define LPB_ltt_fail_chan 0x2C /* 0x2C Ltt's failure channel */
-#define LPB_rup 0x2E /* 0x2E RUP structure for HOST to driver comms */
-#define LPB_link_rup 0x40 /* 0x40 RUP for the link (POLL, topology etc.) */
-#define LPB_attached_link 0x52 /* 0x52 Number of attached link */
-#define LPB_csum_errors 0x54 /* 0x54 csum errors */
-#define LPB_num_disconnects 0x56 /* 0x56 number of disconnects */
-#define LPB_num_sync_rcvd 0x58 /* 0x58 # sync's received */
-#define LPB_num_sync_rqst 0x5A /* 0x5A # sync requests */
-#define LPB_num_tx 0x5C /* 0x5C Num pkts sent */
-#define LPB_num_rx 0x5E /* 0x5E Num pkts received */
-#define LPB_module_attached 0x60 /* 0x60 Module tpyes of attached */
-#define LPB_led_timeout 0x62 /* 0x62 LED timeout */
-#define LPB_first_port 0x64 /* 0x64 First port to service */
-#define LPB_last_port 0x66 /* 0x66 Last port to service */
-#define sizeof_LPB 0x68 /* structure size = 0x68 */
-
-#define LINKS_PER_UNIT 4 /* number of links from a host */
-
-/*****************************************************************************
-******************************** *******************************
-******************************** FREE_LIST *******************************
-******************************** *******************************
-*****************************************************************************/
-
-/* Used to overlay packet headers when allocating/freeing packets from the free list */
-
-typedef struct _FREE_LIST
-{
- _u16 next; /* 0x00 offset of next list item */
- _u16 prev; /* 0x02 offset of previous list item */
-
-} FREE_LIST;
-
-/* Same thing again, but defined as offsets... */
-
-#define FL_next 0x00 /* 0x00 offset of next list item */
-#define FL_prev 0x02 /* 0x02 offset of previous list item */
-
-/*****************************************************************************
-********************************** ***********************************
-********************************** PKT ***********************************
-********************************** ***********************************
-*****************************************************************************/
-
-/* The PKT is the main unit of communication between Host Cards and RTAs across
- the RIO network. */
-
-#define PKT_MAX_DATA_LEN 72 /* Size of packet data */
-
-typedef struct _PKT
-{
- _u8 dest_unit; /* 0x00 Destination Unit Id */
- _u8 dest_port; /* 0x01 Destination Port */
- _u8 src_unit; /* 0x02 Source Unit Id */
- _u8 src_port; /* 0x03 Source Port */
- _u8 len; /* 0x04 Length (in bytes) of data field */
- _u8 control; /* 0x05 */
- _u8 data[PKT_MAX_DATA_LEN]; /* 0x06 Actual data */
- _u16 csum; /* 0x4E C-SUM */
-
-} PKT;
-
-/* Same thing again, but defined as offsets... */
-
-#define PKT_dest_unit 0x00 /* 0x00 Destination Unit Id */
-#define PKT_dest_port 0x01 /* 0x01 Destination Port */
-#define PKT_src_unit 0x02 /* 0x02 Source Unit Id */
-#define PKT_src_port 0x03 /* 0x03 Source Port */
-#define PKT_len 0x04 /* 0x04 Length (in bytes) of data field */
-#define PKT_control 0x05 /* 0x05 */
-#define PKT_data 0x06 /* 0x06 Actual data */
-#define PKT_csum 0x4E /* 0x4E C-SUM */
-#define sizeof_PKT 0x50 /* structure size = 0x50 */
-
-/* PKT.len definitions... */
-#define PKT_CMD_BIT 0x80
-#define PKT_CMD_DATA 0x80
-#define PKT_LEN_MASK 0x7F
-
-/* PKT.control definitions... */
-#define PKT_ACK 0x40
-#define PKT_TGL 0x20
-#define DATA_WNDW 0x10
-#define PKT_TTL_MASK 0x0F
-#define MAX_TTL 0x0F
-
-/*****************************************************************************
-***************************** ****************************
-***************************** Control Packets ****************************
-***************************** ****************************
-*****************************************************************************/
-
-/* The following definitions and structures define the control packets sent
- between the driver and RIO Ports, RTAs and Host Cards. */
-
-#define PRE_EMPTIVE 0x80 /* Pre-emptive command (sent via port's RUP) */
-
-/* "in-band" and "pre-emptive" port commands... */
-#define OPEN 0x00 /* Driver->RIO Open a port */
-#define CONFIG 0x01 /* Driver->RIO Configure a port */
-#define MOPEN 0x02 /* Driver->RIO Modem open (wait for DCD) */
-#define CLOSE 0x03 /* Driver->RIO Close a port */
-#define WFLUSH (0x04|PRE_EMPTIVE) /* Driver->RIO Write flush */
-#define RFLUSH (0x05|PRE_EMPTIVE) /* Driver->RIO Read flush */
-#define RESUME (0x06|PRE_EMPTIVE) /* Driver->RIO Behave as if XON received */
-#define SBREAK 0x07 /* Driver->RIO Start break */
-#define EBREAK 0x08 /* Driver->RIO End break */
-#define SUSPEND (0x09|PRE_EMPTIVE) /* Driver->RIO Behave as if XOFF received */
-#define FCLOSE (0x0A|PRE_EMPTIVE) /* Driver->RIO Force close */
-#define XPRINT 0x0B /* Driver->RIO Xprint packet */
-#define MBIS (0x0C|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define MBIC (0x0D|PRE_EMPTIVE) /* Driver->RIO Clear modem lines */
-#define MSET (0x0E|PRE_EMPTIVE) /* Driver->RIO Set modem lines */
-#define PCLOSE 0x0F /* Driver->RIO Pseudo close */
-#define MGET (0x10|PRE_EMPTIVE) /* Driver->RIO Force update of modem status */
-#define MEMDUMP (0x11|PRE_EMPTIVE) /* Driver->RIO DEBUG request for RTA memory */
-#define READ_REGISTER (0x12|PRE_EMPTIVE) /* Driver->RIO DEBUG read CD1400 register */
-
-/* Remote Unit Port (RUP) packet definitions... (specified in PKT.dest_unit and PKT.src_unit) */
-#define SYNC_RUP 0xFF /* Download internal */
-#define COMMAND_RUP 0xFE /* Command ack/status */
-#define ERROR_RUP 0xFD /* Download internal */
-#define POLL_RUP 0xFC /* Download internal */
-#define BOOT_RUP 0xFB /* Used to boot RTAs */
-#define ROUTE_RUP 0xFA /* Used to specify routing/topology */
-#define STATUS_RUP 0xF9 /* Not used */
-#define POWER_RUP 0xF8 /* Download internal */
-
-/* COMMAND_RUP definitions... */
-#define COMPLETE (0x20|PRE_EMPTIVE) /* RIO->Driver Command complete */
-#define BREAK_RECEIVED (0x21|PRE_EMPTIVE) /* RIO->Driver Break received */
-#define MODEM_STATUS (0x22|PRE_EMPTIVE) /* RIO->Driver Modem status change */
-
-/* BOOT_RUP definitions... */
-#define BOOT_REQUEST 0x00 /* RIO->Driver Request for boot */
-#define BOOT_ABORT 0x01 /* Driver->RIO Abort a boot */
-#define BOOT_SEQUENCE 0x02 /* Driver->RIO Packet with firmware details */
-#define BOOT_COMPLETED 0x03 /* RIO->Driver Boot completed */
-#define IFOAD 0x2F /* Driver->RIO Shutdown/Reboot RTA (Fall Over And Die) */
-#define IDENTIFY 0x30 /* Driver->RIO Identify RTA */
-#define ZOMBIE 0x31 /* Driver->RIO Shutdown/Flash LEDs */
-#define UFOAD 0x32 /* Driver->RIO Shutdown/Reboot neighbouring RTA */
-#define IWAIT 0x33 /* Driver->RIO Pause booting process */
-
-/* ROUTE_RUP definitions... */
-#define ROUTE_REQUEST 0x00 /* RIO->Driver Request an ID */
-#define ROUTE_FOAD 0x01 /* Driver->RIO Shutdown/reboot RTA */
-#define ROUTE_ALREADY 0x02 /* Driver->RIO Not used */
-#define ROUTE_USED 0x03 /* Driver->RIO Not used */
-#define ROUTE_ALLOCATE 0x04 /* Driver->RIO Allocate RTA RUP numbers */
-#define ROUTE_REQ_TOP 0x05 /* Driver->RIO Not used */
-#define ROUTE_TOPOLOGY 0x06 /* RIO->Driver Route/Topology status */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** OPEN **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- Sent to open a port.
- Structure of configuration info used with OPEN, CONFIG and MOPEN packets... */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_Cor1 (PKT_Data+1) /* Channel Option Register 1 */
-#define PKT_Cor2 (PKT_Data+2) /* Channel Option Register 2 */
-#define PKT_Cor4 (PKT_Data+3) /* Channel Option Register 4 */
-#define PKT_Cor5 (PKT_Data+4) /* Channel Option Register 5 */
-#define PKT_TxXon (PKT_Data+5) /* Transmit XON character */
-#define PKT_TxXoff (PKT_Data+6) /* Transmit XOFF character */
-#define PKT_RxXon (PKT_Data+7) /* Receive XON character */
-#define PKT_RxXoff (PKT_Data+8) /* Receive XOFF character */
-#define PKT_Lnext (PKT_Data+9) /* Lnext character */
-#define PKT_TxBaud (PKT_Data+10) /* Transmit baud rate */
-#define PKT_RxBaud (PKT_Data+11) /* Receive baud rate */
-
-/* COR1 definitions... */
-#define COR1_PARITY 0xE0 /* Parity mask */
-#define COR1_NONE 0x00 /* No parity */
-#define COR1_SPACE 0x20 /* Space parity */
-#define COR1_EVEN 0x40 /* Even parity */
-#define COR1_MARK 0xA0 /* Mark parity */
-#define COR1_ODD 0xC0 /* Odd parity */
-
-#define COR1_STOPBITS 0x0C /* Stop bits mask */
-#define COR1_STOP1 0x00 /* 1 stop bit */
-#define COR1_STOP1_5 0x04 /* 1.5 stop bits */
-#define COR1_STOP2 0x08 /* 2 stop bits */
-
-#define COR1_DATABITS 0x03 /* Data bits mask */
-#define COR1_DATA5 0x00 /* 5 data bits */
-#define COR1_DATA6 0x01 /* 6 data bits */
-#define COR1_DATA7 0x02 /* 7 data bits */
-#define COR1_DATA8 0x03 /* 8 data bits */
-
-/* COR2 definitions... */
-#define COR2_XON_TXFLOW 0x40 /* XON/XOFF Transmit Flow */
-#define COR2_XANY_TXFLOW 0xC0 /* XON/XANY Transmit Flow */
-#define COR2_HUPCL 0x20 /* Hang Up On Close */
-#define COR2_DSR_TXFLOW 0x08 /* DSR Transmit Flow Control */
-#define COR2_RTS_RXFLOW 0x04 /* RTS Receive Flow Control */
-#define COR2_CTS_TXFLOW 0x02 /* CTS Transmit Flow Control */
-#define COR2_XON_RXFLOW 0x01 /* XON/XOFF Receive Flow */
-
-/* COR4 definition... */
-#define COR4_IGNCR 0x80 /* Discard received CR */
-#define COR4_ICRNL 0x40 /* Map received CR -> NL */
-#define COR4_INLCR 0x20 /* Map received NL -> CR */
-#define COR4_IGNBRK 0x10 /* Ignore Received Break */
-#define COR4_NBRKINT 0x08 /* No interrupt on rx Break */
-#define COR4_IGNPAR 0x04 /* ignore rx parity error chars */
-#define COR4_PARMRK 0x02 /* Mark rx parity error chars */
-#define COR4_RAISEMOD 0x01 /* Raise modem lines on !0 baud */
-
-/* COR5 definitions... */
-#define COR5_ISTRIP 0x80 /* Strip input chars to 7 bits */
-#define COR5_LNE 0x40 /* Enable LNEXT processing */
-#define COR5_CMOE 0x20 /* Match good & error characters */
-#define COR5_TAB3 0x10 /* TAB3 mode */
-#define COR5_TSTATE_ON 0x08 /* Enable tbusy/tstop monitoring */
-#define COR5_TSTATE_OFF 0x04 /* Disable tbusy/tstop monitoring */
-#define COR5_ONLCR 0x02 /* NL -> CR NL on output */
-#define COR5_OCRNL 0x01 /* CR -> NL on output */
-
-/* RxBaud and TxBaud definitions... */
-#define RIO_B0 0x00 /* RTS / DTR signals dropped */
-#define RIO_B50 0x01 /* 50 baud */
-#define RIO_B75 0x02 /* 75 baud */
-#define RIO_B110 0x03 /* 110 baud */
-#define RIO_B134 0x04 /* 134.5 baud */
-#define RIO_B150 0x05 /* 150 baud */
-#define RIO_B200 0x06 /* 200 baud */
-#define RIO_B300 0x07 /* 300 baud */
-#define RIO_B600 0x08 /* 600 baud */
-#define RIO_B1200 0x09 /* 1200 baud */
-#define RIO_B1800 0x0A /* 1800 baud */
-#define RIO_B2400 0x0B /* 2400 baud */
-#define RIO_B4800 0x0C /* 4800 baud */
-#define RIO_B9600 0x0D /* 9600 baud */
-#define RIO_B19200 0x0E /* 19200 baud */
-#define RIO_B38400 0x0F /* 38400 baud */
-#define RIO_B56000 0x10 /* 56000 baud */
-#define RIO_B57600 0x11 /* 57600 baud */
-#define RIO_B64000 0x12 /* 64000 baud */
-#define RIO_B115200 0x13 /* 115200 baud */
-#define RIO_B2000 0x14 /* 2000 baud */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* CONFIG *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CONFIG is sent from the driver to configure an already opened port.
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* MOPEN **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- MOPEN is sent from the driver to open a port attached to a modem. (in-band)
- Packet structure is same as OPEN. */
-
-/*****************************************************************************
-********************************* **********************************
-********************************* CLOSE **********************************
-********************************* **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- CLOSE is sent from the driver to close a previously opened port.
- No parameters.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-/*****************************************************************************
-********************************* *********************************
-********************************* WFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- WFLUSH is sent pre-emptively from the driver to flush the write buffers and
- packets of a port. (pre-emptive)
-
- WFLUSH is also sent in-band from the driver to a port as a marker to end
- write flushing previously started by a pre-emptive WFLUSH packet. (in-band)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RFLUSH *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RFLUSH is sent pre-emptively from the driver to flush the read buffers and
- packets of a port.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* RESUME *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- RESUME is sent pre-emptively from the driver to cause a port to resume
- transmission of data if blocked by XOFF. (as if XON had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* SBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- SBREAK is sent in-band from the driver to a port to suspend data and start
- break signal transmission.
-
- If the break delay is 0, the break signal will be acknowledged with a
- RUP_COMMAND, COMPLETE packet and continue until an EBREAK packet is received.
-
- Otherwise, there is no acknowledgement and the break signal will last for the
- specified number of mS.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_BreakDelay (PKT_Data+1) /* Break delay in mS */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* EBREAK *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- EBREAK is sent in-band from the driver to a port to stop transmission of a
- break signal.
-
- No parameters. */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* SUSPEND ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- SUSPEND is sent pre-emptively from the driver to cause a port to suspend
- transmission of data. (as if XOFF had been received)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* FCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- FCLOSE is sent pre-emptively from the driver to force close a port.
- A force close flushes receive and transmit queues, and also lowers all output
- modem signals if the COR5_HUPCL (Hang Up On Close) flag is set.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************* *********************************
-********************************* XPRINT *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- XPRINT is sent as a normal I/O data packet except that the PKT_CMD_BIT of
- the "len" field is set, and the first "data" byte is XPRINT.
-
- The I/O data in the XPRINT packet will contain the following:
- - Transparent Print Start Sequence
- - Transparent Print Data
- - Transparent Print Stop Sequence.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIS **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIS is sent pre-emptively from the driver to set a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MBIS_RTS 0x01 /* RTS modem signal */
-#define MBIS_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MBIC **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MBIC is sent pre-emptively from the driver to clear a port's modem signals.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemClear (PKT_Data+4) /* Modem clear signals mask */
-
-/* ModemClear definitions... */
-#define MBIC_RTS 0x01 /* RTS modem signal */
-#define MBIC_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MSET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MSET is sent pre-emptively from the driver to set/clear a port's modem signals. */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#endif
-
-#define PKT_ModemSet (PKT_Data+4) /* Modem set signals mask */
-
-/* ModemSet definitions... */
-#define MSET_RTS 0x01 /* RTS modem signal */
-#define MSET_DTR 0x02 /* DTR modem signal */
-
-/*****************************************************************************
-********************************* *********************************
-********************************* PCLOSE *********************************
-********************************* *********************************
-*****************************************************************************/
-
-/* (Driver->RIO,in-band)
-
- PCLOSE is sent from the driver to pseudo close a previously opened port.
-
- The port will close when all data has been sent/received, however, the
- port's transmit / receive and modem signals will be left enabled and the
- port marked internally as Pseudo Closed. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-
-/*****************************************************************************
-********************************** **********************************
-********************************** MGET **********************************
-********************************** **********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MGET is sent pre-emptively from the driver to request the port's current modem signals. */
-
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-
-/*****************************************************************************
-********************************* ********************************
-********************************* MEMDUMP ********************************
-********************************* ********************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- MEMDUMP is sent pre-emptively from the driver to request a dump of 32 bytes
- of the specified port's RTA address space.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-****************************** *****************************
-****************************** READ_REGISTER *****************************
-****************************** *****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- READ_REGISTER is sent pre-emptively from the driver to request the contents
- of the CD1400 register specified in address.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-************************ **************************
-************************ COMMAND_RUP - COMPLETE **************************
-************************ **************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE is sent in response to all port I/O control command
- packets, except MEMDUMP and READ_REGISTER.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#if 0
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/* ModemStatus definitions... */
-#define MODEM_DSR 0x80 /* Data Set Ready modem state */
-#define MODEM_CTS 0x40 /* Clear To Send modem state */
-#define MODEM_RI 0x20 /* Ring Indicate modem state */
-#define MODEM_CD 0x10 /* Carrier Detect modem state */
-#define MODEM_TSTOP 0x08 /* Transmit Stopped state */
-#define MODEM_TEMPTY 0x04 /* Transmit Empty state */
-#define MODEM_DTR 0x02 /* DTR modem output state */
-#define MODEM_RTS 0x01 /* RTS modem output state */
-
-/* PortStatus definitions... */
-#define PORT_ISOPEN 0x01 /* Port open ? */
-#define PORT_HUPCL 0x02 /* Hangup on close? */
-#define PORT_MOPENPEND 0x04 /* Modem open pending */
-#define PORT_ISPARALLEL 0x08 /* Parallel port */
-#define PORT_BREAK 0x10 /* Port on break */
-#define PORT_STATUSPEND 0020 /* Status packet pending */
-#define PORT_BREAKPEND 0x40 /* Break packet pending */
-#define PORT_MODEMPEND 0x80 /* Modem status packet pending */
-
-/*****************************************************************************
-******************** ********************
-******************** COMMAND_RUP - COMPLETE - MEMDUMP ********************
-******************** ********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - MEMDUMP is sent as an acknowledgement for a MEMDUMP
- port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#define PKT_Address (PKT_Data+6) /* Requested address */
-#endif
-#define PKT_Dump (PKT_Data+8) /* 32bytes of requested dump data */
-
-/*****************************************************************************
-***************** *****************
-***************** COMMAND_RUP - COMPLETE - READ_REGISTER *****************
-***************** *****************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - COMPLETE - READ_REGISTER is sent as an acknowledgement for a
- READ_REGISTER port I/O control command packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /*Command code */
-#define PKT_PhbNum (PKT_Data+1) /*Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-#define PKT_RegisterValue (PKT_Data+3) /* Modem signal status */
-#if 0
-#define PKT_PortStatus (PKT_Data+4) /* Port signal status */
-#define PKT_SubCmd (PKT_Data+5) /* Sub Command */
-#endif
-
-/*****************************************************************************
-********************* ***********************
-********************* COMMAND_RUP - BREAK_RECEIVED ***********************
-********************* ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - BREAK_RECEIVED packets are sent when the port detects a receive BREAK signal.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#endif
-
-/*****************************************************************************
-********************* *************************
-********************* COMMAND_RUP - MODEM_STATUS *************************
-********************* *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- COMMAND_RUP - MODEM_STATUS packets are sent whenever the port detects a
- change in the input modem signal states.
-
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_PhbNum (PKT_Data+1) /* Port number wrt RTA */
-#define PKT_Cmd2 (PKT_Data+2) /* Command code copy */
-#define PKT_ModemStatus (PKT_Data+3) /* Modem signal status */
-#endif
-
-/*****************************************************************************
-************************ *************************
-************************ BOOT_RUP - BOOT_REQUEST *************************
-************************ *************************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_REQUEST packets are sent to the Driver from RIO to request
- firmware code to load onto attached RTAs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-
-/*****************************************************************************
-************************ ************************
-************************ BOOT_RUP - BOOT_SEQUENCE ************************
-************************ ************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - BOOT_SEQUENCE packets are sent from the Driver to RIO in response
- to a BOOT_RUP - BOOT_REQUEST packet.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_NumPackets (PKT_Data+2) /* Packets required to load firmware */
-#define PKT_LoadBase (PKT_Data+4) /* RTA firmware load address */
-#define PKT_CodeSize (PKT_Data+6) /* Size of firmware in bytes */
-#define PKT_CmdString (PKT_Data+8) /* Command string */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - BOOT_COMPLETED ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP - BOOT_COMPLETE is sent to the Driver from RIO when downloading of
- RTA firmware has completed.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_LinkNumber (PKT_Data+1) /* Link number RTA booted on */
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-
-/*****************************************************************************
-************************ ***********************
-************************ BOOT_RUP - Packet Request ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- BOOT_RUP packet without the PKT_CMD_BIT set in the PKT->len field is sent
- from RIO to the Driver as a request for a firmware boot packet. */
-
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** BOOT_RUP - Packet Response ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- In response to a BOOT_RUP boot packet request, the driver fills out the response
- packet with the 70 bytes of the requested sequence.
- */
-#if 0
-#define PKT_SequenceNumber (PKT_Data+0) /* Packet sequence number */
-#endif
-#define PKT_FirmwarePacket (PKT_Data+2) /* Firmware packet */
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IFOAD packets are sent from the Driver to an RTA to cause the
- RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IfoadId1 (PKT_Data+2) /* IFOAD Id 1 */
-#define PKT_IfoadId2 (PKT_Data+3) /* IFOAD Id 2 */
-
-#define IFOADID1 0xAD
-#define IFOADID2 0xF0
-
-/*****************************************************************************
-************************** ***************************
-************************** BOOT_RUP - IDENTIFY ***************************
-************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IDENTIFY packets are sent from the Driver to an RTA to cause the
- RTA to flash its LEDs for a period of time.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdentifyId (PKT_Data+2) /* defines pattern to flash */
-
-/*****************************************************************************
-**************************** ***************************
-**************************** BOOT_RUP - ZOMBIE ***************************
-**************************** ***************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - ZOMBIE packets are sent from the Driver to an RTA to cause the
- RTA to shut down and flash it's LEDs.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_ZombieId1 (PKT_Data+2) /* ZOMBIE Id 1 */
-#define PKT_ZombieId2 (PKT_Data+3) /* ZOMBIE Id 2 */
-
-#define ZOMBIEID1 0x52
-#define ZOMBIEID2 0x21
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - UFOAD ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - UFOAD packets are sent from the Driver to an RTA to cause the RTA
- to ask it's neighbouring RTA to shut down and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_UfoadId1 (PKT_Data+2) /* UFOAD Id 1 */
-#define PKT_UfoadId2 (PKT_Data+3) /* UFOAD Id 2 */
-
-#define UFOADID1 0x1E
-#define UFOADID2 0x0D
-
-/*****************************************************************************
-**************************** ****************************
-**************************** BOOT_RUP - IWAIT ****************************
-**************************** ****************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- BOOT_RUP - IWAIT packets are sent from the Driver to an RTA to cause the RTA
- to pause booting on the specified link for 30 seconds.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#define PKT_LinkNumber (PKT_Data+1) /* Link number of RTA to UFOAD */
-#endif
-#define PKT_IwaitId1 (PKT_Data+2) /* IWAIT Id 1 */
-#define PKT_IwaitId2 (PKT_Data+3) /* IWAIT Id 2 */
-
-#define IWAITID1 0xDE
-#define IWAITID2 0xB1
-
-/*****************************************************************************
-************************ ***********************
-************************ ROUTE_RUP - ROUTE_REQUEST ***********************
-************************ ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_REQUEST packets are sent from a newly booted or connected
- RTA to a Driver to request an ID (RUP or unit number).
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_SerialNumber (PKT_Data+2) /* 4 byte serial number */
-#define PKT_ModuleTypes (PKT_Data+6) /* RTA Module types */
-
-/* ModuleTypes definitions... */
-#define MOD_BLANK 0x0F /* Blank plate attached */
-#define MOD_RS232DB25 0x00 /* RS232 DB25 connector */
-#define MOD_RS232RJ45 0x01 /* RS232 RJ45 connector */
-#define MOD_RS422DB25 0x02 /* RS422 DB25 connector */
-#define MOD_RS485DB25 0x03 /* RS485 DB25 connector */
-#define MOD_PARALLEL 0x04 /* Centronics parallel */
-
-#define MOD2 0x08 /* Set to indicate Rev2 module */
-
-/*****************************************************************************
-************************* *************************
-************************* ROUTE_RUP - ROUTE_FOAD *************************
-************************* *************************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_FOAD packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to cause the RTA to "Fall Over And Die"., i.e. shutdown and reboot.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_ALLOCATE ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (Driver->RIO,pre-emptive)
-
- ROUTE_RUP - ROUTE_ALLOCATE packet is sent as a response to a ROUTE_RUP - ROUTE_REQUEST
- packet to allocate the RTA's Id number (RUP number 1..16)
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_IdNum (PKT_Data+1) /* RUP number for ports 1..8 */
-#if 0
-#define PKT_RouteCmdString (PKT_Data+2) /* Command string */
-#endif
-#define PKT_IdNum2 (PKT_Data+0x17) /* RUP number for ports 9..16 */
-
-/*****************************************************************************
-*********************** ***********************
-*********************** ROUTE_RUP - ROUTE_TOPOLOGY ***********************
-*********************** ***********************
-*****************************************************************************/
-
-/* (RIO->Driver,pre-emptive)
-
- ROUTE_RUP - ROUTE_TOPOLOGY packet is sent to inform the driver of an RTA's
- current link status.
- */
-#if 0
-#define PKT_Cmd (PKT_Data+0) /* Command code */
-#endif
-#define PKT_Link1Rup (PKT_Data+2) /* Link 1 RUP number */
-#define PKT_Link1Link (PKT_Data+3) /* Link 1 link number */
-#define PKT_Link2Rup (PKT_Data+4) /* Link 2 RUP number */
-#define PKT_Link2Link (PKT_Data+5) /* Link 2 link number */
-#define PKT_Link3Rup (PKT_Data+6) /* Link 3 RUP number */
-#define PKT_Link3Link (PKT_Data+7) /* Link 3 link number */
-#define PKT_Link4Rup (PKT_Data+8) /* Link 4 RUP number */
-#define PKT_Link4Link (PKT_Data+9) /* Link 4 link number */
-#define PKT_RtaVpdProm (PKT_Data+10) /* 32 bytes of RTA VPD PROM Contents */
-
-#endif /* _sxwinif_h */
-
-/* End of RIOWINIF.H */
diff --git a/drivers/char/rio/riscos.h b/drivers/char/rio/riscos.h
deleted file mode 100644
index 7685cc1d9e7b..000000000000
--- a/drivers/char/rio/riscos.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-** Perle Specialix driver for Linux
-** Ported from existing RIO Driver for SCO sources.
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-**
-** Module : riscos.h
-** SID : 1.2
-** Last Modified : 11/6/98 11:34:19
-** Retrieved : 11/6/98 11:34:22
-**
-** ident @(#)riscos.h 1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riscos_h__
-#define __rio_riscos_h__
-
-#ifdef SCCS_LABELS
-static char *_riscos_h_sccs_ = "@(#)riscos.h 1.2";
-#endif
-
-/*
-** This module used to define all those little itsy bits required for RISC/OS
-** now it's full of null macros.
-*/
-
-/*
-** RBYTE reads a byte from a location.
-** RWORD reads a word from a location.
-** WBYTE writes a byte to a location.
-** WWORD writes a word to a location.
-** RINDW reads a word through a pointer.
-** WINDW writes a word through a pointer.
-** RIOSWAB swaps the two bytes of a word, if needed.
-*/
-
-#define RIOSWAB(N) (N)
-#define WBYTE(A,V) (A)=(uchar)(V)
-#define WWORD(A,V) (A)=(ushort)(V)
-#define RBYTE(A) (uchar)(A)
-#define RWORD(A) (ushort)(A)
-#define RINDW(A) (*(ushort *)(A))
-#define WINDW(A,V) (*(ushort *)(A)=(ushort)(V))
-
-#endif /* __rio_riscos_h__ */
diff --git a/drivers/char/rio/rom.h b/drivers/char/rio/rom.h
index ee79b8e5b972..58a7843625ff 100644
--- a/drivers/char/rio/rom.h
+++ b/drivers/char/rio/rom.h
@@ -39,19 +39,19 @@
#ifndef lint
#ifdef SCCS
-static char *_rio_rom_h_sccs = "@(#)rom.h 1.1" ;
+static char *_rio_rom_h_sccs = "@(#)rom.h 1.1";
#endif
#endif
-typedef struct ROM ROM ;
-struct ROM {
- u_short slx ;
- char pcb_letter_rev ;
- char pcb_number_rev ;
- char serial[4] ;
- char year ;
- char week ;
- } ;
+typedef struct ROM ROM;
+struct ROM {
+ u_short slx;
+ char pcb_letter_rev;
+ char pcb_number_rev;
+ char serial[4];
+ char year;
+ char week;
+};
#endif
@@ -60,5 +60,3 @@ struct ROM {
#define ROM_LENGTH 0x20
/*********** end of file ***********/
-
-
diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h
index c42dbb971718..769744e575ab 100644
--- a/drivers/char/rio/route.h
+++ b/drivers/char/rio/route.h
@@ -44,26 +44,26 @@
#endif
#define MAX_LINKS 4
-#define MAX_NODES 17 /* Maximum nodes in a subnet */
-#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for
- 1 bit per node */
-#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete
- info about cost etc. */
+#define MAX_NODES 17 /* Maximum nodes in a subnet */
+#define NODE_BYTES ((MAX_NODES / 8) + 1) /* Number of bytes needed for
+ 1 bit per node */
+#define ROUTE_DATA_SIZE (NODE_BYTES + 2) /* Number of bytes for complete
+ info about cost etc. */
#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
- /* Number of nodes we can squeeze
- into one packet */
+ /* Number of nodes we can squeeze
+ into one packet */
#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
/************************************************
* Define the types of command for the ROUTE RUP.
************************************************/
-#define ROUTE_REQUEST 0 /* Request an ID */
-#define ROUTE_FOAD 1 /* Kill the RTA */
-#define ROUTE_ALREADY 2 /* ID given already */
-#define ROUTE_USED 3 /* All ID's used */
-#define ROUTE_ALLOCATE 4 /* Here it is */
-#define ROUTE_REQ_TOP 5 /* I bet you didn't expect....
- the Topological Inquisition */
-#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */
+#define ROUTE_REQUEST 0 /* Request an ID */
+#define ROUTE_FOAD 1 /* Kill the RTA */
+#define ROUTE_ALREADY 2 /* ID given already */
+#define ROUTE_USED 3 /* All ID's used */
+#define ROUTE_ALLOCATE 4 /* Here it is */
+#define ROUTE_REQ_TOP 5 /* I bet you didn't expect....
+ the Topological Inquisition */
+#define ROUTE_TOPOLOGY 6 /* Topology request answered FD */
/*******************************************************************
* Define the Route Map Structure
*
@@ -72,22 +72,22 @@
******************************************************************/
typedef struct COST_ROUTE COST_ROUTE;
struct COST_ROUTE {
- unsigned char cost; /* Cost down this link */
- unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
- } ;
+ unsigned char cost; /* Cost down this link */
+ unsigned char route[NODE_BYTES]; /* Nodes thorough this route */
+};
-typedef struct ROUTE_STR ROUTE_STR ;
-struct ROUTE_STR {
- COST_ROUTE cost_route[MAX_LINKS];
- /* cost / route for this link */
- ushort favoured; /* favoured link */
- } ;
+typedef struct ROUTE_STR ROUTE_STR;
+struct ROUTE_STR {
+ COST_ROUTE cost_route[MAX_LINKS];
+ /* cost / route for this link */
+ ushort favoured; /* favoured link */
+};
-#define NO_LINK (short) 5 /* Link unattached */
-#define ROUTE_NO_ID (short) 100 /* No Id */
-#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */
-#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */
+#define NO_LINK (short) 5 /* Link unattached */
+#define ROUTE_NO_ID (short) 100 /* No Id */
+#define ROUTE_DISCONNECT (ushort) 0xff /* Not connected */
+#define ROUTE_INTERCONNECT (ushort) 0x40 /* Sub-net interconnect */
#define SYNC_RUP (ushort) 255
@@ -99,10 +99,9 @@ struct ROUTE_STR {
#define STATUS_RUP (ushort) 249
#define POWER_RUP (ushort) 248
-#define HIGHEST_RUP (ushort) 255 /* Set to Top one */
-#define LOWEST_RUP (ushort) 248 /* Set to bottom one */
+#define HIGHEST_RUP (ushort) 255 /* Set to Top one */
+#define LOWEST_RUP (ushort) 248 /* Set to bottom one */
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rtahw.h b/drivers/char/rio/rtahw.h
deleted file mode 100644
index 06860118cbc5..000000000000
--- a/drivers/char/rio/rtahw.h
+++ /dev/null
@@ -1,75 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* R T A H A R D W A R E
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rtahw_h_sccs = "@(#)rtahw.h 1.5" ;
-#endif
-#endif
-
-#define WATCHDOG_ADDR ((unsigned short *)0x7a00)
-#define RTA_LED_ADDR ((unsigned short *)0x7c00)
-#define SERIALNUM_ADDR ((unsigned char *)0x7809)
-#define LATCH_ADDR ((unsigned char *)0x7800)
-
-/*
-** Here we define where the cd1400 chips are in memory.
-*/
-#define CD1400_ONE_ADDR (0x7300)
-#define CD1400_TWO_ADDR (0x7200)
-#define CD1400_THREE_ADDR (0x7100)
-#define CD1400_FOUR_ADDR (0x7000)
-
-/*
-** Define the different types of modules we can have
-*/
-enum module {
- MOD_BLANK = 0x0f, /* Blank plate attached */
- MOD_RS232DB25 = 0x00, /* RS232 DB25 connector */
- MOD_RS232RJ45 = 0x01, /* RS232 RJ45 connector */
- MOD_RS422DB25 = 0x02, /* RS422 DB25 connector */
- MOD_RS485DB25 = 0x03, /* RS485 DB25 connector */
- MOD_PARALLEL = 0x04 /* Centronics parallel */
-};
-
-#define TYPE_HOST 0
-#define TYPE_RTA8 1
-#define TYPE_RTA16 2
-
-#define WATCH_DOG WATCHDOG_ADDR
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
index b9d2bc03d14b..8d44fec91dd5 100644
--- a/drivers/char/rio/rup.h
+++ b/drivers/char/rio/rup.h
@@ -44,39 +44,38 @@
#endif
#if defined( HOST ) || defined( INKERNEL )
-#define MAX_RUP ((short) 16)
+#define MAX_RUP ((short) 16)
#endif
#ifdef RTA
#define MAX_RUP ((short) 1)
#endif
-#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */
+#define PKTS_PER_RUP ((short) 2) /* They are always used in pairs */
/*************************************************
* Define all the packet request stuff
************************************************/
-#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
-#define TX_PACKET_READY 1 /* Transmit packet ready */
-#define TX_LOCK_RUP 2 /* Transmit side locked */
+#define TX_RUP_INACTIVE 0 /* Nothing to transmit */
+#define TX_PACKET_READY 1 /* Transmit packet ready */
+#define TX_LOCK_RUP 2 /* Transmit side locked */
-#define RX_RUP_INACTIVE 0 /* Nothing received */
-#define RX_PACKET_READY 1 /* Packet received */
+#define RX_RUP_INACTIVE 0 /* Nothing received */
+#define RX_PACKET_READY 1 /* Packet received */
-#define RUP_NO_OWNER 0xff /* RUP not owned by any process */
+#define RUP_NO_OWNER 0xff /* RUP not owned by any process */
struct RUP {
- PKT_ptr txpkt; /* Outgoing packet */
- PKT_ptr rxpkt; /* Incoming packet */
- WORD link; /* Which link to send down? */
- BYTE rup_dest_unit[2]; /* Destination unit */
- WORD handshake; /* For handshaking */
- WORD timeout; /* Timeout */
- WORD status; /* Status */
- WORD txcontrol; /* Transmit control */
- WORD rxcontrol; /* Receive control */
- };
-
+ PKT_ptr txpkt; /* Outgoing packet */
+ PKT_ptr rxpkt; /* Incoming packet */
+ WORD link; /* Which link to send down? */
+ BYTE rup_dest_unit[2]; /* Destination unit */
+ WORD handshake; /* For handshaking */
+ WORD timeout; /* Timeout */
+ WORD status; /* Status */
+ WORD txcontrol; /* Transmit control */
+ WORD rxcontrol; /* Receive control */
+};
+
#endif
/*********** end of file ***********/
-
diff --git a/drivers/char/rio/rupstat.h b/drivers/char/rio/rupstat.h
deleted file mode 100644
index b4aafaff0d78..000000000000
--- a/drivers/char/rio/rupstat.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/****************************************************************************
- ******* *******
- ******* RUPSTAT
- ******* *******
- ****************************************************************************
-
- Author : Jeremy Rolls
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rupstat_h
-#define _rupstat_h
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_rupstat_h_sccs = "@(#)rupstat.h 1.1" ;
-#endif
-#endif
-
-#define STATUS_SYNC 0
-#define STATUS_REQ_TOP 1
-#define STATUS_TOPOLOGY 2
-
-#endif
-
diff --git a/drivers/char/rio/sam.h b/drivers/char/rio/sam.h
index c1accb8cb624..31494054b213 100644
--- a/drivers/char/rio/sam.h
+++ b/drivers/char/rio/sam.h
@@ -60,15 +60,12 @@
#define RX FALSE
-typedef struct FREE_LIST FREE_LIST ;
-struct FREE_LIST {
- FREE_LIST_ptr next ;
- FREE_LIST_ptr prev ;
- } ;
+typedef struct FREE_LIST FREE_LIST;
+struct FREE_LIST {
+ FREE_LIST_ptr next;
+ FREE_LIST_ptr prev;
+};
#endif
/*********** end of file ***********/
-
-
-
diff --git a/drivers/char/rio/selftest.h b/drivers/char/rio/selftest.h
deleted file mode 100644
index deae48722a21..000000000000
--- a/drivers/char/rio/selftest.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-** File: selftest.h
-**
-** Author: David Dix
-**
-** Created: 15th March 1993
-**
-** Last modified: 94/06/14
-**
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 _selftests_h_
-#define _selftests_h_
-
-/*
-** Selftest identifier...
-*/
-#define SELFTEST_MAGIC 0x5a5a
-
-/*
-** This is the structure of the packet that is sent back after each
-** selftest on a booting RTA.
-*/
-typedef struct {
- short magic; /* Identifies packet type */
- int test; /* Test number, see below */
- unsigned int result; /* Result value */
- unsigned int dataIn;
- unsigned int dataOut;
-}selftestStruct;
-
-/*
-** The different tests are identified by the following data values.
-*/
-enum test {
- TESTS_COMPLETE = 0x00,
- MEMTEST_ADDR = 0x01,
- MEMTEST_BIT = 0x02,
- MEMTEST_FILL = 0x03,
- MEMTEST_DATABUS = 0x04,
- MEMTEST_ADDRBUS = 0x05,
- CD1400_INIT = 0x10,
- CD1400_LOOP = 0x11,
- CD1400_INTERRUPT = 0x12
-};
-
-enum result {
- E_PORT = 0x10,
- E_TX = 0x11,
- E_RX = 0x12,
- E_EXCEPT = 0x13,
- E_COMPARE = 0x14,
- E_MODEM = 0x15,
- E_TIMEOUT = 0x16,
- E_INTERRUPT = 0x17
-};
-#endif /* _selftests_h_ */
diff --git a/drivers/char/rio/space.h b/drivers/char/rio/space.h
index 72398d342051..1f12690f9d1f 100644
--- a/drivers/char/rio/space.h
+++ b/drivers/char/rio/space.h
@@ -42,4 +42,4 @@ extern int rio_bases[];
extern int rio_limits[];
extern int rio_vects[];
-#endif /* __rio_space_h__ */
+#endif /* __rio_space_h__ */
diff --git a/drivers/char/rio/sysmap.h b/drivers/char/rio/sysmap.h
deleted file mode 100644
index fdc731393576..000000000000
--- a/drivers/char/rio/sysmap.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* S Y S T E M M A P H E A D E R
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_sysmap_h_sccs = "@(#)sysmap.h 1.1" ;
-#endif
-#endif
-
-#define SYSTEM_MAP_LEN 64 /* Len of System Map array */
-
-
-typedef struct SYS_MAP SYS_MAP ;
-typedef struct SYS_MAP_LINK SYS_MAP_LINK ;
-
-struct SYS_MAP_LINK {
- short id ; /* Unit Id */
- short link ; /* Id's Link */
- short been_here ; /* Used by map_gen */
- } ;
-
-struct SYS_MAP {
- char serial_num[4] ;
- SYS_MAP_LINK link[4] ;
- } ;
-
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/timeouts.h b/drivers/char/rio/timeouts.h
deleted file mode 100644
index 11b31330c901..000000000000
--- a/drivers/char/rio/timeouts.h
+++ /dev/null
@@ -1,51 +0,0 @@
-
-/****************************************************************************
- ******* *******
- ******* T I M E O U T S
- ******* *******
- ****************************************************************************
-
- Author : Ian Nandhra
- Date :
-
- *
- * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
-
- Version : 0.01
-
-
- Mods
- ----------------------------------------------------------------------------
- Date By Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef lint
-#ifdef SCCS_LABELS
-static char *_rio_defaults_h_sccs = "@(#)timeouts.h 1.3" ;
-#endif
-#endif
-
-#define MILLISECOND (int) (1000/64) /* 15.625 low ticks */
-#define SECOND (int) 15625 /* Low priority ticks */
-
-#define TX_TIMEOUT (int) (200 * MILLISECOND)
-
-
-/*********** end of file ***********/
-
diff --git a/drivers/char/rio/top.h b/drivers/char/rio/top.h
index 255c40d463a6..d15a11dc4f73 100644
--- a/drivers/char/rio/top.h
+++ b/drivers/char/rio/top.h
@@ -40,10 +40,9 @@ static char *_top_h_sccs_ = "@(#)top.h 1.2";
/*
** Topology information
*/
-struct Top
-{
- uchar Unit;
- uchar Link;
+struct Top {
+ uchar Unit;
+ uchar Link;
};
-#endif /* __rio_top_h__ */
+#endif /* __rio_top_h__ */
diff --git a/drivers/char/rio/typdef.h b/drivers/char/rio/typdef.h
index 2cb9dd693fa1..185b889e1510 100644
--- a/drivers/char/rio/typdef.h
+++ b/drivers/char/rio/typdef.h
@@ -45,11 +45,11 @@ static char *_typdef_h_sccs_ = "@(#)typdef.h 1.2";
** These types are ONLY to be used for refering to data structures
** on the RIO Host card!
*/
-typedef volatile unsigned char BYTE;
-typedef volatile unsigned short WORD;
-typedef volatile unsigned int DWORD;
-typedef volatile unsigned short RIOP;
-typedef volatile short NUMBER;
+typedef volatile unsigned char BYTE;
+typedef volatile unsigned short WORD;
+typedef volatile unsigned int DWORD;
+typedef volatile unsigned short RIOP;
+typedef volatile short NUMBER;
/*
@@ -59,13 +59,13 @@ typedef volatile short NUMBER;
** are here only to make the source compile.
*/
/* typedef unsigned int uint; */
-typedef unsigned long ulong_t;
-typedef unsigned short ushort_t;
-typedef unsigned char uchar_t;
-typedef unsigned char queue_t;
-typedef unsigned char mblk_t;
-typedef unsigned int paddr_t;
-typedef unsigned char uchar;
+typedef unsigned long ulong_t;
+typedef unsigned short ushort_t;
+typedef unsigned char uchar_t;
+typedef unsigned char queue_t;
+typedef unsigned char mblk_t;
+typedef unsigned int paddr_t;
+typedef unsigned char uchar;
#define TPNULL ((ushort)(0x8000))
@@ -73,10 +73,10 @@ typedef unsigned char uchar;
/*
** RIO structures defined in other include files.
*/
-typedef struct PKT PKT;
-typedef struct LPB LPB;
-typedef struct RUP RUP;
-typedef struct Port Port;
-typedef struct DpRam DpRam;
+typedef struct PKT PKT;
+typedef struct LPB LPB;
+typedef struct RUP RUP;
+typedef struct Port Port;
+typedef struct DpRam DpRam;
-#endif /* __rio_typdef_h__ */
+#endif /* __rio_typdef_h__ */
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h
index eddf86278abc..a126c7cabac6 100644
--- a/drivers/char/rio/unixrup.h
+++ b/drivers/char/rio/unixrup.h
@@ -41,16 +41,15 @@ static char *_unixrup_h_sccs_ = "@(#)unixrup.h 1.2";
** UnixRup data structure. This contains pointers to actual RUPs on the
** host card, and all the command/boot control stuff.
*/
-struct UnixRup
-{
- struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */
- struct CmdBlk *CmdPendingP; /* The command currently being sent */
- struct RUP *RupP; /* the Rup to send it to */
- uint Id; /* Id number */
- uint BaseSysPort; /* SysPort of first tty on this RTA */
- uint ModTypes; /* Modules on this RTA */
- spinlock_t RupLock; /* Lock structure for MPX */
-/* struct lockb RupLock; */ /* Lock structure for MPX */
+struct UnixRup {
+ struct CmdBlk *CmdsWaitingP; /* Commands waiting to be done */
+ struct CmdBlk *CmdPendingP; /* The command currently being sent */
+ struct RUP *RupP; /* the Rup to send it to */
+ uint Id; /* Id number */
+ uint BaseSysPort; /* SysPort of first tty on this RTA */
+ uint ModTypes; /* Modules on this RTA */
+ spinlock_t RupLock; /* Lock structure for MPX */
+ /* struct lockb RupLock; *//* Lock structure for MPX */
};
-#endif /* __rio_unixrup_h__ */
+#endif /* __rio_unixrup_h__ */
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 55a3a0188eda..119e629656b7 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -46,6 +46,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/tty_flip.h>
#include <asm/uaccess.h>
@@ -81,7 +82,6 @@
static struct riscom_board * IRQ_to_board[16];
static struct tty_driver *riscom_driver;
static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static unsigned long baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -107,15 +107,15 @@ static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
/* RISCom/8 I/O ports addresses (without address translation) */
static unsigned short rc_ioport[] = {
-#if 1
+#if 1
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else
+#else
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif
+#endif
};
-#define RC_NIOPORT (sizeof(rc_ioport) / sizeof(rc_ioport[0]))
+#define RC_NIOPORT ARRAY_SIZE(rc_ioport)
static inline int rc_paranoia_check(struct riscom_port const * port,
@@ -354,28 +354,17 @@ static inline void rc_receive_exc(struct riscom_board const * bp)
struct riscom_port *port;
struct tty_struct *tty;
unsigned char status;
- unsigned char ch;
+ unsigned char ch, flag;
if (!(port = rc_get_port(bp, "Receive")))
return;
tty = port->tty;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- printk(KERN_WARNING "rc%d: port %d: Working around flip "
- "buffer overflow.\n",
- board_No(bp), port_No(port));
- return;
- }
#ifdef RC_REPORT_OVERRUN
status = rc_in(bp, CD180_RCSR);
- if (status & RCSR_OE) {
+ if (status & RCSR_OE)
port->overrun++;
-#if 0
- printk(KERN_ERR "rc%d: port %d: Overrun. Total %ld overruns\n",
- board_No(bp), port_No(port), port->overrun);
-#endif
- }
status &= port->mark_mask;
#else
status = rc_in(bp, CD180_RCSR) & port->mark_mask;
@@ -393,25 +382,24 @@ static inline void rc_receive_exc(struct riscom_board const * bp)
} else if (status & RCSR_BREAK) {
printk(KERN_INFO "rc%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RCSR_PE)
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RCSR_FE)
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
else if (status & RCSR_OE)
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
else
- *tty->flip.flag_buf_ptr++ = 0;
+ flag = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_insert_flip_char(tty, ch, flag);
+ tty_flip_buffer_push(tty);
}
static inline void rc_receive(struct riscom_board const * bp)
@@ -432,17 +420,15 @@ static inline void rc_receive(struct riscom_board const * bp)
#endif
while (count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, 1) == 0) {
printk(KERN_WARNING "rc%d: port %d: Working around "
"flip buffer overflow.\n",
board_No(bp), port_No(port));
break;
}
- *tty->flip.char_buf_ptr++ = rc_in(bp, CD180_RDR);
- *tty->flip.flag_buf_ptr++ = 0;
- tty->flip.count++;
+ tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
}
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
static inline void rc_transmit(struct riscom_board const * bp)
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index d3bc731fbb27..0949dcef0697 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -325,19 +325,16 @@ static void rp_do_receive(struct r_port *info,
{
unsigned int CharNStat;
int ToRecv, wRecv, space = 0, count;
- unsigned char *cbuf;
- char *fbuf;
+ unsigned char *cbuf, *chead;
+ char *fbuf, *fhead;
struct tty_ldisc *ld;
ld = tty_ldisc_ref(tty);
ToRecv = sGetRxCnt(cp);
- if (ld)
- space = ld->receive_room(tty);
+ space = tty->receive_room;
if (space > 2 * TTY_FLIPBUF_SIZE)
space = 2 * TTY_FLIPBUF_SIZE;
- cbuf = tty->flip.char_buf;
- fbuf = tty->flip.flag_buf;
count = 0;
#ifdef ROCKET_DEBUG_INTR
printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
@@ -350,9 +347,13 @@ static void rp_do_receive(struct r_port *info,
if (ToRecv > space)
ToRecv = space;
+ ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
if (ToRecv <= 0)
goto done;
+ cbuf = chead;
+ fbuf = fhead;
+
/*
* if status indicates there are errored characters in the
* FIFO, then enter status mode (a word in FIFO holds
@@ -399,7 +400,7 @@ static void rp_do_receive(struct r_port *info,
else if (CharNStat & STMRCVROVRH)
*fbuf++ = TTY_OVERRUN;
else
- *fbuf++ = 0;
+ *fbuf++ = TTY_NORMAL;
*cbuf++ = CharNStat & 0xff;
count++;
ToRecv--;
@@ -426,13 +427,13 @@ static void rp_do_receive(struct r_port *info,
sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
if (ToRecv & 1)
cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
- memset(fbuf, 0, ToRecv);
+ memset(fbuf, TTY_NORMAL, ToRecv);
cbuf += ToRecv;
fbuf += ToRecv;
count += ToRecv;
}
/* Push the data up to the tty layer */
- ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+ ld->receive_buf(tty, cbuf, fbuf, count);
done:
tty_ldisc_deref(ld);
}
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index a7f099fb7dfe..7cac6d05d723 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -46,10 +46,10 @@
* 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init
* 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
* CONFIG_HPET_EMULATE_RTC
- *
+ * 1.12ac Alan Cox: Allow read access to the day of week register
*/
-#define RTC_VERSION "1.12"
+#define RTC_VERSION "1.12ac"
#define RTC_IO_EXTENT 0x8
@@ -1250,9 +1250,9 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
/*
* Only the values that we read from the RTC are set. We leave
- * tm_wday, tm_yday and tm_isdst untouched. Even though the
- * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
- * by the RTC when initially set to a non-zero value.
+ * tm_wday, tm_yday and tm_isdst untouched. Note that while the
+ * RTC has RTC_DAY_OF_WEEK, we should usually ignore it, as it is
+ * only updated by the RTC when initially set to a non-zero value.
*/
spin_lock_irq(&rtc_lock);
rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
@@ -1261,6 +1261,9 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
+ /* Only set from 2.6.16 onwards */
+ rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK);
+
#ifdef CONFIG_MACH_DECSTATION
real_year = CMOS_READ(RTC_DEC_YEAR);
#endif
@@ -1275,6 +1278,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
BCD_TO_BIN(rtc_tm->tm_mday);
BCD_TO_BIN(rtc_tm->tm_mon);
BCD_TO_BIN(rtc_tm->tm_year);
+ BCD_TO_BIN(rtc_tm->tm_wday);
}
#ifdef CONFIG_MACH_DECSTATION
diff --git a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
index 3df7a574267b..2e308657f6f6 100644
--- a/drivers/char/s3c2410-rtc.c
+++ b/drivers/char/s3c2410-rtc.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/uaccess.h>
@@ -33,7 +34,6 @@
#include <asm/mach/time.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-rtc.h>
/* need this for the RTC_AF definitions */
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
index 51810f72f1a9..93998f5baff5 100644
--- a/drivers/char/scc.h
+++ b/drivers/char/scc.h
@@ -399,7 +399,7 @@ struct scc_port {
__asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
} while (0)
-extern unsigned char scc_shadow[2][16];
+static unsigned char scc_shadow[2][16];
/* The following functions should relax the somehow complicated
* register access of the SCC. _SCCwrite() stores all written values
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 5b187c895c18..71093a9fc462 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -275,7 +275,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
int paste_selection(struct tty_struct *tty)
{
struct vc_data *vc = (struct vc_data *)tty->driver_data;
- int pasted = 0, count;
+ int pasted = 0;
+ unsigned int count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
@@ -293,7 +294,7 @@ int paste_selection(struct tty_struct *tty)
continue;
}
count = sel_buffer_lth - pasted;
- count = min(count, tty->ldisc.receive_room(tty));
+ count = min(count, tty->receive_room);
tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index dda30e42ec79..80a5b840e22f 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -194,11 +194,6 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
*/
struct tty_struct *tty = port->gs.tty;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return;
-
- tty->flip.count++;
-
#if 0
switch(err) {
case TTY_BREAK:
@@ -212,8 +207,7 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
}
#endif
- *tty->flip.flag_buf_ptr++ = err;
- *tty->flip.char_buf_ptr++ = ch;
+ tty_insert_flip_char(tty, ch, err);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index c2deac968bdd..037c940ac71b 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -117,7 +117,7 @@ struct cyclades_port cy_port[] = {
{-1 }, /* ttyS2 */
{-1 }, /* ttyS3 */
};
-#define NR_PORTS (sizeof(cy_port)/sizeof(struct cyclades_port))
+#define NR_PORTS ARRAY_SIZE(cy_port)
/*
* tmp_buf is used as a temporary buffer by serial_write. We need to
@@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = {
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf = 0;
-DECLARE_MUTEX(tmp_buf_sem);
/*
* This is used to look up the divisor speeds and the timeouts
@@ -422,45 +421,35 @@ cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
return IRQ_HANDLED;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
+ if (tty_buffer_request_room(tty, 1) != 0){
if (err & info->read_status_mask){
if(err & CyBREAK){
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_BREAK);
if (info->flags & ASYNC_SAK){
do_SAK(tty);
}
}else if(err & CyFRAME){
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_FRAME);
}else if(err & CyPARITY){
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_PARITY);
}else if(err & CyOVERRUN){
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
/*
If the flip buffer itself is
overflowing, we still loose
the next incoming character.
*/
- if(tty->flip.count < TTY_FLIPBUF_SIZE){
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
- }
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
+ }
/* These two conditions may imply */
/* a normal read should be done. */
/* else if(data & CyTIMEOUT) */
/* else if(data & CySPECHAR) */
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, 0, TTY_NORMAL);
}
}else{
- *tty->flip.flag_buf_ptr++ = 0;
- *tty->flip.char_buf_ptr++ = 0;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
}
}else{
/* there was a software buffer overrun
@@ -692,12 +681,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
#endif
while(char_count--){
data = base_addr[CyRDR];
- if (tty->flip.count >= TTY_FLIPBUF_SIZE){
- continue;
- }
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = data;
+ tty_insert_flip_char(tty, data, TTY_NORMAL);
#ifdef CYCLOM_16Y_HACK
udelay(10L);
#endif
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 51a07370e636..f8dd8527c6aa 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -471,7 +471,6 @@ struct sonypi_keypress {
static struct sonypi_device {
struct pci_dev *dev;
- struct platform_device *pdev;
u16 irq;
u16 bits;
u16 ioport1;
@@ -511,6 +510,11 @@ static struct sonypi_device {
#define SONYPI_ACPI_ACTIVE 0
#endif /* CONFIG_ACPI */
+#ifdef CONFIG_ACPI
+static struct acpi_device *sonypi_acpi_device;
+static int acpi_enabled;
+#endif
+
static int sonypi_ec_write(u8 addr, u8 value)
{
#ifdef CONFIG_ACPI_EC
@@ -864,6 +868,11 @@ found:
if (useinput)
sonypi_report_input_event(event);
+#ifdef CONFIG_ACPI
+ if (acpi_enabled)
+ acpi_bus_generate_event(sonypi_acpi_device, 1, event);
+#endif
+
kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
wake_up_interruptible(&sonypi_device.fifo_proc_list);
@@ -1165,45 +1174,38 @@ static int sonypi_disable(void)
return 0;
}
-#ifdef CONFIG_PM
-static int old_camera_power;
-
-static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_ACPI
+static int sonypi_acpi_add(struct acpi_device *device)
{
- old_camera_power = sonypi_device.camera_power;
- sonypi_disable();
-
+ sonypi_acpi_device = device;
+ strcpy(acpi_device_name(device), "Sony laptop hotkeys");
+ strcpy(acpi_device_class(device), "sony/hotkey");
return 0;
}
-static int sonypi_resume(struct platform_device *dev)
+static int sonypi_acpi_remove(struct acpi_device *device, int type)
{
- sonypi_enable(old_camera_power);
+ sonypi_acpi_device = NULL;
return 0;
}
-#endif
-
-static void sonypi_shutdown(struct platform_device *dev)
-{
- sonypi_disable();
-}
-static struct platform_driver sonypi_driver = {
-#ifdef CONFIG_PM
- .suspend = sonypi_suspend,
- .resume = sonypi_resume,
-#endif
- .shutdown = sonypi_shutdown,
- .driver = {
- .name = "sonypi",
+static struct acpi_driver sonypi_acpi_driver = {
+ .name = "sonypi",
+ .class = "hkey",
+ .ids = "SNY6001",
+ .ops = {
+ .add = sonypi_acpi_add,
+ .remove = sonypi_acpi_remove,
},
};
+#endif
static int __devinit sonypi_create_input_devices(void)
{
struct input_dev *jog_dev;
struct input_dev *key_dev;
int i;
+ int error;
sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
if (!jog_dev)
@@ -1219,9 +1221,8 @@ static int __devinit sonypi_create_input_devices(void)
sonypi_device.input_key_dev = key_dev = input_allocate_device();
if (!key_dev) {
- input_free_device(jog_dev);
- sonypi_device.input_jog_dev = NULL;
- return -ENOMEM;
+ error = -ENOMEM;
+ goto err_free_jogdev;
}
key_dev->name = "Sony Vaio Keys";
@@ -1234,56 +1235,122 @@ static int __devinit sonypi_create_input_devices(void)
if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
- input_register_device(jog_dev);
- input_register_device(key_dev);
+ error = input_register_device(jog_dev);
+ if (error)
+ goto err_free_keydev;
+
+ error = input_register_device(key_dev);
+ if (error)
+ goto err_unregister_jogdev;
return 0;
+
+ err_unregister_jogdev:
+ input_unregister_device(jog_dev);
+ /* Set to NULL so we don't free it again below */
+ jog_dev = NULL;
+ err_free_keydev:
+ input_free_device(key_dev);
+ sonypi_device.input_key_dev = NULL;
+ err_free_jogdev:
+ input_free_device(jog_dev);
+ sonypi_device.input_jog_dev = NULL;
+
+ return error;
}
-static int __devinit sonypi_probe(void)
+static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
+ const struct sonypi_ioport_list *ioport_list)
{
- int i, ret;
- struct sonypi_ioport_list *ioport_list;
- struct sonypi_irq_list *irq_list;
- struct pci_dev *pcidev;
+ while (ioport_list->port1) {
- 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;
+ if (request_region(ioport_list->port1,
+ sonypi_device.region_size,
+ "Sony Programable I/O Device")) {
+ dev->ioport1 = ioport_list->port1;
+ dev->ioport2 = ioport_list->port2;
+ return 0;
+ }
+ ioport_list++;
+ }
- sonypi_device.dev = pcidev;
+ return -EBUSY;
+}
+
+static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
+ const struct sonypi_irq_list *irq_list)
+{
+ while (irq_list->irq) {
+
+ if (!request_irq(irq_list->irq, sonypi_irq,
+ SA_SHIRQ, "sonypi", sonypi_irq)) {
+ dev->irq = irq_list->irq;
+ dev->bits = irq_list->bits;
+ return 0;
+ }
+ irq_list++;
+ }
+
+ return -EBUSY;
+}
+
+static void __devinit sonypi_display_info(void)
+{
+ 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,
+ verbose,
+ fnkeyinit ? "on" : "off",
+ camera ? "on" : "off",
+ compat ? "on" : "off",
+ mask,
+ useinput ? "on" : "off",
+ SONYPI_ACPI_ACTIVE ? "on" : "off");
+ printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
+ sonypi_device.irq,
+ sonypi_device.ioport1, sonypi_device.ioport2);
+
+ if (minor == -1)
+ printk(KERN_INFO "sonypi: device allocated minor is %d\n",
+ sonypi_misc_device.minor);
+}
+
+static int __devinit sonypi_probe(struct platform_device *dev)
+{
+ const struct sonypi_ioport_list *ioport_list;
+ const struct sonypi_irq_list *irq_list;
+ struct pci_dev *pcidev;
+ int error;
spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock);
if (IS_ERR(sonypi_device.fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
- ret = PTR_ERR(sonypi_device.fifo);
- goto out_fifo;
+ return PTR_ERR(sonypi_device.fifo);
}
init_waitqueue_head(&sonypi_device.fifo_proc_list);
init_MUTEX(&sonypi_device.lock);
sonypi_device.bluetooth_power = -1;
+ 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;
+
if (pcidev && pci_enable_device(pcidev)) {
printk(KERN_ERR "sonypi: pci_enable_device failed\n");
- ret = -EIO;
- goto out_pcienable;
- }
-
- if (minor != -1)
- sonypi_misc_device.minor = minor;
- if ((ret = misc_register(&sonypi_misc_device))) {
- printk(KERN_ERR "sonypi: misc_register failed\n");
- goto out_miscreg;
+ error = -EIO;
+ goto err_put_pcidev;
}
+ sonypi_device.dev = pcidev;
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
ioport_list = sonypi_type1_ioport_list;
@@ -1302,43 +1369,36 @@ static int __devinit sonypi_probe(void)
irq_list = sonypi_type3_irq_list;
}
- for (i = 0; ioport_list[i].port1; i++) {
- if (request_region(ioport_list[i].port1,
- sonypi_device.region_size,
- "Sony Programable I/O Device")) {
- /* get the ioport */
- sonypi_device.ioport1 = ioport_list[i].port1;
- sonypi_device.ioport2 = ioport_list[i].port2;
- break;
- }
- }
- if (!sonypi_device.ioport1) {
- printk(KERN_ERR "sonypi: request_region failed\n");
- ret = -ENODEV;
- goto out_reqreg;
+ error = sonypi_setup_ioports(&sonypi_device, ioport_list);
+ if (error) {
+ printk(KERN_ERR "sonypi: failed to request ioports\n");
+ goto err_disable_pcidev;
}
- for (i = 0; irq_list[i].irq; i++) {
-
- sonypi_device.irq = irq_list[i].irq;
- sonypi_device.bits = irq_list[i].bits;
-
- if (!request_irq(sonypi_device.irq, sonypi_irq,
- SA_SHIRQ, "sonypi", sonypi_irq))
- break;
+ error = sonypi_setup_irq(&sonypi_device, irq_list);
+ if (error) {
+ printk(KERN_ERR "sonypi: request_irq failed\n");
+ goto err_free_ioports;
}
- if (!irq_list[i].irq) {
- printk(KERN_ERR "sonypi: request_irq failed\n");
- ret = -ENODEV;
- goto out_reqirq;
+ if (minor != -1)
+ sonypi_misc_device.minor = minor;
+ error = misc_register(&sonypi_misc_device);
+ if (error) {
+ printk(KERN_ERR "sonypi: misc_register failed\n");
+ goto err_free_irq;
}
+ sonypi_display_info();
+
if (useinput) {
- ret = sonypi_create_input_devices();
- if (ret)
- goto out_inputdevices;
+ error = sonypi_create_input_devices();
+ if (error) {
+ printk(KERN_ERR
+ "sonypi: failed to create input devices\n");
+ goto err_miscdev_unregister;
+ }
spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo =
@@ -1346,91 +1406,104 @@ static int __devinit sonypi_probe(void)
&sonypi_device.input_fifo_lock);
if (IS_ERR(sonypi_device.input_fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
- ret = PTR_ERR(sonypi_device.input_fifo);
- goto out_infifo;
+ error = PTR_ERR(sonypi_device.input_fifo);
+ goto err_inpdev_unregister;
}
INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
}
- sonypi_device.pdev = platform_device_register_simple("sonypi", -1,
- NULL, 0);
- if (IS_ERR(sonypi_device.pdev)) {
- ret = PTR_ERR(sonypi_device.pdev);
- goto out_platformdev;
- }
-
sonypi_enable(0);
- printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
- "v%s.\n", SONYPI_DRIVER_VERSION);
- 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,
- verbose,
- fnkeyinit ? "on" : "off",
- camera ? "on" : "off",
- compat ? "on" : "off",
- mask,
- useinput ? "on" : "off",
- SONYPI_ACPI_ACTIVE ? "on" : "off");
- printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
- sonypi_device.irq,
- sonypi_device.ioport1, sonypi_device.ioport2);
-
- if (minor == -1)
- printk(KERN_INFO "sonypi: device allocated minor is %d\n",
- sonypi_misc_device.minor);
-
return 0;
-out_platformdev:
- kfifo_free(sonypi_device.input_fifo);
-out_infifo:
+ err_inpdev_unregister:
input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev);
-out_inputdevices:
+ err_miscdev_unregister:
+ misc_deregister(&sonypi_misc_device);
+ err_free_irq:
free_irq(sonypi_device.irq, sonypi_irq);
-out_reqirq:
+ err_free_ioports:
release_region(sonypi_device.ioport1, sonypi_device.region_size);
-out_reqreg:
- misc_deregister(&sonypi_misc_device);
-out_miscreg:
+ err_disable_pcidev:
if (pcidev)
pci_disable_device(pcidev);
-out_pcienable:
+ err_put_pcidev:
+ pci_dev_put(pcidev);
kfifo_free(sonypi_device.fifo);
-out_fifo:
- pci_dev_put(sonypi_device.dev);
- return ret;
+
+ return error;
}
-static void __devexit sonypi_remove(void)
+static int __devexit sonypi_remove(struct platform_device *dev)
{
sonypi_disable();
synchronize_sched(); /* Allow sonypi interrupt to complete. */
flush_scheduled_work();
- platform_device_unregister(sonypi_device.pdev);
-
if (useinput) {
input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo);
}
+ misc_deregister(&sonypi_misc_device);
+
free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size);
- misc_deregister(&sonypi_misc_device);
- if (sonypi_device.dev)
+
+ if (sonypi_device.dev) {
pci_disable_device(sonypi_device.dev);
+ pci_dev_put(sonypi_device.dev);
+ }
+
kfifo_free(sonypi_device.fifo);
- pci_dev_put(sonypi_device.dev);
- printk(KERN_INFO "sonypi: removed.\n");
+
+ return 0;
}
+#ifdef CONFIG_PM
+static int old_camera_power;
+
+static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+{
+ old_camera_power = sonypi_device.camera_power;
+ sonypi_disable();
+
+ return 0;
+}
+
+static int sonypi_resume(struct platform_device *dev)
+{
+ sonypi_enable(old_camera_power);
+ return 0;
+}
+#else
+#define sonypi_suspend NULL
+#define sonypi_resume NULL
+#endif
+
+static void sonypi_shutdown(struct platform_device *dev)
+{
+ sonypi_disable();
+}
+
+static struct platform_driver sonypi_driver = {
+ .driver = {
+ .name = "sonypi",
+ .owner = THIS_MODULE,
+ },
+ .probe = sonypi_probe,
+ .remove = __devexit_p(sonypi_remove),
+ .shutdown = sonypi_shutdown,
+ .suspend = sonypi_suspend,
+ .resume = sonypi_resume,
+};
+
+static struct platform_device *sonypi_platform_device;
+
static struct dmi_system_id __initdata sonypi_dmi_table[] = {
{
.ident = "Sony Vaio",
@@ -1451,26 +1524,52 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = {
static int __init sonypi_init(void)
{
- int ret;
+ int error;
+
+ printk(KERN_INFO
+ "sonypi: Sony Programmable I/O Controller Driver v%s.\n",
+ SONYPI_DRIVER_VERSION);
if (!dmi_check_system(sonypi_dmi_table))
return -ENODEV;
- ret = platform_driver_register(&sonypi_driver);
- if (ret)
- return ret;
+ error = platform_driver_register(&sonypi_driver);
+ if (error)
+ return error;
- ret = sonypi_probe();
- if (ret)
- platform_driver_unregister(&sonypi_driver);
+ sonypi_platform_device = platform_device_alloc("sonypi", -1);
+ if (!sonypi_platform_device) {
+ error = -ENOMEM;
+ goto err_driver_unregister;
+ }
- return ret;
+ error = platform_device_add(sonypi_platform_device);
+ if (error)
+ goto err_free_device;
+
+#ifdef CONFIG_ACPI
+ if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0)
+ acpi_enabled = 1;
+#endif
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(sonypi_platform_device);
+ err_driver_unregister:
+ platform_driver_unregister(&sonypi_driver);
+ return error;
}
static void __exit sonypi_exit(void)
{
+#ifdef CONFIG_ACPI
+ if (acpi_enabled)
+ acpi_bus_unregister_driver(&sonypi_acpi_driver);
+#endif
+ platform_device_unregister(sonypi_platform_device);
platform_driver_unregister(&sonypi_driver);
- sonypi_remove();
+ printk(KERN_INFO "sonypi: removed.\n");
}
module_init(sonypi_init);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 0bbfce43031c..5343e9fc6ab7 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -85,6 +85,7 @@
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/mm.h>
#include <linux/serial.h>
#include <linux/fcntl.h>
@@ -183,7 +184,6 @@ static int sx_poll = HZ;
static struct tty_driver *specialix_driver;
static unsigned char * tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static unsigned long baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -665,7 +665,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
struct specialix_port *port;
struct tty_struct *tty;
unsigned char status;
- unsigned char ch;
+ unsigned char ch, flag;
func_enter();
@@ -676,8 +676,6 @@ static inline void sx_receive_exc(struct specialix_board * bp)
return;
}
tty = port->tty;
- dprintk (SX_DEBUG_RX, "port: %p count: %d BUFF_SIZE: %d\n",
- port, tty->flip.count, TTY_FLIPBUF_SIZE);
status = sx_in(bp, CD186x_RCSR);
@@ -691,7 +689,7 @@ static inline void sx_receive_exc(struct specialix_board * bp)
/* This flip buffer check needs to be below the reading of the
status register to reset the chip's IRQ.... */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_buffer_request_room(tty, 1) == 0) {
dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n",
board_No(bp), port_No(port));
func_exit();
@@ -712,26 +710,24 @@ static inline void sx_receive_exc(struct specialix_board * bp)
} else if (status & RCSR_BREAK) {
dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
if (port->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RCSR_PE)
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RCSR_FE)
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
else if (status & RCSR_OE)
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
else
- *tty->flip.flag_buf_ptr++ = 0;
-
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- schedule_delayed_work(&tty->flip.work, 1);
+ flag = TTY_NORMAL;
+ if(tty_insert_flip_char(tty, ch, flag))
+ tty_flip_buffer_push(tty);
func_exit();
}
@@ -755,18 +751,11 @@ static inline void sx_receive(struct specialix_board * bp)
dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
port->hits[count > 8 ? 9 : count]++;
- while (count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- printk(KERN_INFO "sx%d: port %d: Working around flip buffer overflow.\n",
- board_No(bp), port_No(port));
- break;
- }
- *tty->flip.char_buf_ptr++ = sx_in(bp, CD186x_RDR);
- *tty->flip.flag_buf_ptr++ = 0;
- tty->flip.count++;
- }
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_buffer_request_room(tty, count);
+ while (count--)
+ tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
+ tty_flip_buffer_push(tty);
func_exit();
}
@@ -2566,8 +2555,6 @@ static int __init specialix_init_module(void)
func_enter();
- init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */
-
if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
for(i = 0; i < SX_NBOARD; i++) {
sx_board[i].base = iobase[i];
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 95af2a941595..bdaab6992109 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -103,7 +103,7 @@ static stlconf_t stl_brdconf[] = {
/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
};
-static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+static int stl_nrbrds = ARRAY_SIZE(stl_brdconf);
/*****************************************************************************/
@@ -424,7 +424,7 @@ static stlpcibrd_t stl_pcibrds[] = {
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
};
-static int stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);
+static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
#endif
@@ -704,7 +704,7 @@ static unsigned int sc26198_baudtable[] = {
230400, 460800, 921600
};
-#define SC26198_NRBAUDS (sizeof(sc26198_baudtable) / sizeof(unsigned int))
+#define SC26198_NRBAUDS ARRAY_SIZE(sc26198_baudtable)
/*****************************************************************************/
@@ -738,7 +738,7 @@ static int __init stallion_module_init(void)
stl_init();
restore_flags(flags);
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -889,7 +889,7 @@ static unsigned long stl_atol(char *str)
}
val = (val * base) + c;
}
- return(val);
+ return val;
}
/*****************************************************************************/
@@ -901,26 +901,25 @@ static unsigned long stl_atol(char *str)
static int stl_parsebrd(stlconf_t *confp, char **argp)
{
char *sp;
- int nrbrdnames, i;
+ int i;
#ifdef DEBUG
printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
#endif
if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
- return(0);
+ return 0;
for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
*sp = TOLOWER(*sp);
- nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
- for (i = 0; (i < nrbrdnames); i++) {
+ for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
break;
}
- if (i >= nrbrdnames) {
+ if (i == ARRAY_SIZE(stl_brdstr)) {
printk("STALLION: unknown board name, %s?\n", argp[0]);
- return(0);
+ return 0;
}
confp->brdtype = stl_brdstr[i].type;
@@ -936,7 +935,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
}
if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
confp->irq = stl_atol(argp[i]);
- return(1);
+ return 1;
}
/*****************************************************************************/
@@ -947,7 +946,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
static void *stl_memalloc(int len)
{
- return((void *) kmalloc(len, GFP_KERNEL));
+ return (void *) kmalloc(len, GFP_KERNEL);
}
/*****************************************************************************/
@@ -964,12 +963,12 @@ static stlbrd_t *stl_allocbrd(void)
if (brdp == (stlbrd_t *) NULL) {
printk("STALLION: failed to allocate memory (size=%d)\n",
sizeof(stlbrd_t));
- return((stlbrd_t *) NULL);
+ return (stlbrd_t *) NULL;
}
memset(brdp, 0, sizeof(stlbrd_t));
brdp->magic = STL_BOARDMAGIC;
- return(brdp);
+ return brdp;
}
/*****************************************************************************/
@@ -989,10 +988,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
minordev = tty->index;
brdnr = MINOR2BRD(minordev);
if (brdnr >= stl_nrbrds)
- return(-ENODEV);
+ return -ENODEV;
brdp = stl_brds[brdnr];
if (brdp == (stlbrd_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
minordev = MINOR2PORT(minordev);
for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
if (brdp->panels[panelnr] == (stlpanel_t *) NULL)
@@ -1004,11 +1003,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
minordev -= brdp->panels[panelnr]->nrports;
}
if (portnr < 0)
- return(-ENODEV);
+ return -ENODEV;
portp = brdp->panels[panelnr]->ports[portnr];
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
/*
* On the first open of the device setup the port hardware, and
@@ -1022,7 +1021,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
if (portp->tx.buf == (char *) NULL) {
portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE);
if (portp->tx.buf == (char *) NULL)
- return(-ENOMEM);
+ return -ENOMEM;
portp->tx.head = portp->tx.buf;
portp->tx.tail = portp->tx.buf;
}
@@ -1044,8 +1043,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
if (portp->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&portp->close_wait);
if (portp->flags & ASYNC_HUP_NOTIFY)
- return(-EAGAIN);
- return(-ERESTARTSYS);
+ return -EAGAIN;
+ return -ERESTARTSYS;
}
/*
@@ -1055,11 +1054,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
*/
if (!(filp->f_flags & O_NONBLOCK)) {
if ((rc = stl_waitcarrier(portp, filp)) != 0)
- return(rc);
+ return rc;
}
portp->flags |= ASYNC_NORMAL_ACTIVE;
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -1116,7 +1115,7 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
portp->openwaitcnt--;
restore_flags(flags);
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -1212,12 +1211,12 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
if ((tty == (struct tty_struct *) NULL) ||
(stl_tmpwritebuf == (char *) NULL))
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
/*
* If copying direct from user space we must cater for page faults,
@@ -1256,7 +1255,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count
clear_bit(ASYI_TXLOW, &portp->istate);
stl_startrxtx(portp, -1, 1);
- return(count);
+ return count;
}
/*****************************************************************************/
@@ -1337,16 +1336,16 @@ static int stl_writeroom(struct tty_struct *tty)
#endif
if (tty == (struct tty_struct *) NULL)
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
head = portp->tx.head;
tail = portp->tx.tail;
- return((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
+ return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
}
/*****************************************************************************/
@@ -1371,19 +1370,19 @@ static int stl_charsinbuffer(struct tty_struct *tty)
#endif
if (tty == (struct tty_struct *) NULL)
- return(0);
+ return 0;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (portp->tx.buf == (char *) NULL)
- return(0);
+ return 0;
head = portp->tx.head;
tail = portp->tx.tail;
size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
size = 1;
- return(size);
+ return size;
}
/*****************************************************************************/
@@ -1448,7 +1447,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
(sio.close_delay != portp->close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
(portp->flags & ~ASYNC_USR_MASK)))
- return(-EPERM);
+ return -EPERM;
}
portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
@@ -1458,7 +1457,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
stl_setport(portp, portp->tty->termios);
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -1468,12 +1467,12 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
stlport_t *portp;
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
return stl_getsignals(portp);
}
@@ -1485,12 +1484,12 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
int rts = -1, dtr = -1;
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
if (set & TIOCM_RTS)
rts = 1;
@@ -1518,15 +1517,15 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
#endif
if (tty == (struct tty_struct *) NULL)
- return(-ENODEV);
+ return -ENODEV;
portp = tty->driver_data;
if (portp == (stlport_t *) NULL)
- return(-ENODEV);
+ return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
if (tty->flags & (1 << TTY_IO_ERROR))
- return(-EIO);
+ return -EIO;
}
rc = 0;
@@ -1567,7 +1566,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
break;
}
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -1873,7 +1872,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
pos[(MAXLINE - 2)] = '+';
pos[(MAXLINE - 1)] = '\n';
- return(MAXLINE);
+ return MAXLINE;
}
/*****************************************************************************/
@@ -1958,7 +1957,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
stl_readdone:
*start = page;
- return(pos - page);
+ return (pos - page);
}
/*****************************************************************************/
@@ -2350,7 +2349,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
} else {
rc = 0;
}
- return(rc);
+ return rc;
}
/*****************************************************************************/
@@ -2902,7 +2901,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
if (portp->tty != (struct tty_struct *) NULL) {
if (portp->tty->driver_data == portp) {
portp->stats.ttystate = portp->tty->flags;
- portp->stats.rxbuffered = portp->tty->flip.count;
+ /* No longer available as a statistic */
+ portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
if (portp->tty->termios != (struct termios *) NULL) {
portp->stats.cflags = portp->tty->termios->c_cflag;
portp->stats.iflags = portp->tty->termios->c_iflag;
@@ -3116,7 +3116,7 @@ static int __init stl_init(void)
return -1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -3132,7 +3132,7 @@ static int __init stl_init(void)
static int stl_cd1400getreg(stlport_t *portp, int regnr)
{
outb((regnr + portp->uartaddr), portp->ioaddr);
- return(inb(portp->ioaddr + EREG_DATA));
+ return inb(portp->ioaddr + EREG_DATA);
}
static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
@@ -3146,9 +3146,9 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
outb((regnr + portp->uartaddr), portp->ioaddr);
if (inb(portp->ioaddr + EREG_DATA) != value) {
outb(value, portp->ioaddr + EREG_DATA);
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -3206,7 +3206,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
}
BRDDISABLE(panelp->brdnr);
- return(chipmask);
+ return chipmask;
}
/*****************************************************************************/
@@ -3557,7 +3557,7 @@ static int stl_cd1400getsignals(stlport_t *portp)
#else
sigs |= TIOCM_DSR;
#endif
- return(sigs);
+ return sigs;
}
/*****************************************************************************/
@@ -3830,9 +3830,9 @@ static int stl_cd1400datastate(stlport_t *portp)
#endif
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
- return(test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0);
+ return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
}
/*****************************************************************************/
@@ -3912,20 +3912,20 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
outb((SRER + portp->uartaddr), ioaddr);
outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
(ioaddr + EREG_DATA));
- return(1);
+ return 1;
} else if (portp->brklen > 1) {
outb((TDR + portp->uartaddr), ioaddr);
outb(ETC_CMD, (ioaddr + EREG_DATA));
outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
portp->brklen = -1;
- return(1);
+ return 1;
} else {
outb((COR2 + portp->uartaddr), ioaddr);
outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
(ioaddr + EREG_DATA));
portp->brklen = 0;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -4046,9 +4046,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
outb((RDCR + portp->uartaddr), ioaddr);
len = inb(ioaddr + EREG_DATA);
- if ((tty == (struct tty_struct *) NULL) ||
- (tty->flip.char_buf_ptr == (char *) NULL) ||
- ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+ if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
len = MIN(len, sizeof(stl_unwanted));
outb((RDSR + portp->uartaddr), ioaddr);
insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
@@ -4057,12 +4055,10 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
} else {
len = MIN(len, buflen);
if (len > 0) {
+ unsigned char *ptr;
outb((RDSR + portp->uartaddr), ioaddr);
- insb((ioaddr + EREG_DATA), tty->flip.char_buf_ptr, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.count += len;
+ tty_prepare_flip_string(tty, &ptr, len);
+ insb((ioaddr + EREG_DATA), ptr, len);
tty_schedule_flip(tty);
portp->stats.rxtotal += len;
}
@@ -4086,8 +4082,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
portp->stats.txxoff++;
goto stl_rxalldone;
}
- if ((tty != (struct tty_struct *) NULL) &&
- ((portp->rxignoremsk & status) == 0)) {
+ if (tty != NULL && (portp->rxignoremsk & status) == 0) {
if (portp->rxmarkmsk & status) {
if (status & ST_BREAK) {
status = TTY_BREAK;
@@ -4107,14 +4102,8 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
} else {
status = 0;
}
- if (tty->flip.char_buf_ptr != (char *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = status;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- }
- tty_schedule_flip(tty);
- }
+ tty_insert_flip_char(tty, ch, status);
+ tty_schedule_flip(tty);
}
} else {
printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
@@ -4177,7 +4166,7 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
static int stl_sc26198getreg(stlport_t *portp, int regnr)
{
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
- return(inb(portp->ioaddr + XP_DATA));
+ return inb(portp->ioaddr + XP_DATA);
}
static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
@@ -4191,9 +4180,9 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
if (inb(portp->ioaddr + XP_DATA) != value) {
outb(value, (portp->ioaddr + XP_DATA));
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
/*****************************************************************************/
@@ -4205,7 +4194,7 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
{
outb(regnr, (portp->ioaddr + XP_ADDR));
- return(inb(portp->ioaddr + XP_DATA));
+ return inb(portp->ioaddr + XP_DATA);
}
#if 0
@@ -4263,7 +4252,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
}
BRDDISABLE(panelp->brdnr);
- return(chipmask);
+ return chipmask;
}
/*****************************************************************************/
@@ -4557,7 +4546,7 @@ static int stl_sc26198getsignals(stlport_t *portp)
sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
sigs |= TIOCM_DSR;
- return(sigs);
+ return sigs;
}
/*****************************************************************************/
@@ -4839,9 +4828,9 @@ static int stl_sc26198datastate(stlport_t *portp)
#endif
if (portp == (stlport_t *) NULL)
- return(0);
+ return 0;
if (test_bit(ASYI_TXBUSY, &portp->istate))
- return(1);
+ return 1;
save_flags(flags);
cli();
@@ -4850,7 +4839,7 @@ static int stl_sc26198datastate(stlport_t *portp)
BRDDISABLE(portp->brdnr);
restore_flags(flags);
- return((sr & SR_TXEMPTY) ? 0 : 1);
+ return (sr & SR_TXEMPTY) ? 0 : 1;
}
/*****************************************************************************/
@@ -5013,9 +5002,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
len = inb(ioaddr + XP_DATA) + 1;
if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
- if ((tty == (struct tty_struct *) NULL) ||
- (tty->flip.char_buf_ptr == (char *) NULL) ||
- ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+ if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
len = MIN(len, sizeof(stl_unwanted));
outb(GRXFIFO, (ioaddr + XP_ADDR));
insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
@@ -5024,12 +5011,10 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
} else {
len = MIN(len, buflen);
if (len > 0) {
+ unsigned char *ptr;
outb(GRXFIFO, (ioaddr + XP_ADDR));
- insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.count += len;
+ tty_prepare_flip_string(tty, &ptr, len);
+ insb((ioaddr + XP_DATA), ptr, len);
tty_schedule_flip(tty);
portp->stats.rxtotal += len;
}
@@ -5097,14 +5082,8 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
status = 0;
}
- if (tty->flip.char_buf_ptr != (char *) NULL) {
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = status;
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
- }
- tty_schedule_flip(tty);
- }
+ tty_insert_flip_char(tty, ch, status);
+ tty_schedule_flip(tty);
if (status == 0)
portp->stats.rxtotal++;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 3ad758a9a1dc..64bf89cb574f 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -345,9 +345,9 @@ static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000,
0xc8000, 0xd8000, 0xe8000, 0xa0000};
static int si1_probe_addrs[]= { 0xd0000};
-#define NR_SX_ADDRS (sizeof(sx_probe_addrs)/sizeof (int))
-#define NR_SI_ADDRS (sizeof(si_probe_addrs)/sizeof (int))
-#define NR_SI1_ADDRS (sizeof(si1_probe_addrs)/sizeof (int))
+#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
+#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
+#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
/* Set the mask to all-ones. This alas, only supports 32 interrupts.
@@ -1085,6 +1085,7 @@ static inline void sx_receive_chars (struct sx_port *port)
int rx_op;
struct tty_struct *tty;
int copied=0;
+ unsigned char *rp;
func_enter2 ();
tty = port->gs.tty;
@@ -1095,8 +1096,8 @@ static inline void sx_receive_chars (struct sx_port *port)
sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
/* Don't copy more bytes than there is room for in the buffer */
- if (tty->flip.count + c > TTY_FLIPBUF_SIZE)
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+ c = tty_prepare_flip_string(tty, &rp, c);
sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c);
@@ -1111,14 +1112,8 @@ static inline void sx_receive_chars (struct sx_port *port)
sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c,
read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op),
CHAN_OFFSET(port, hi_rxbuf));
- memcpy_fromio (tty->flip.char_buf_ptr,
+ memcpy_fromio (rp,
port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c);
- memset(tty->flip.flag_buf_ptr, TTY_NORMAL, c);
-
- /* Update the kernel buffer end */
- tty->flip.count += c;
- tty->flip.char_buf_ptr += c;
- tty->flip.flag_buf_ptr += c;
/* This one last. ( Not essential.)
It allows the card to start putting more data into the buffer!
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 62aa0e534a6d..ede688a4e141 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void)
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-static DECLARE_MUTEX(tmp_buf_sem);
static inline int mgsl_paranoia_check(struct mgsl_struct *info,
char *name, const char *routine)
@@ -1467,6 +1466,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
{
int Fifocount;
u16 status;
+ int work = 0;
unsigned char DataByte;
struct tty_struct *tty = info->tty;
struct mgsl_icount *icount = &info->icount;
@@ -1487,6 +1487,8 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
/* flush the receive FIFO */
while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
+ int flag;
+
/* read one byte from RxFIFO */
outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
info->io_base + CCAR );
@@ -1498,13 +1500,9 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = DataByte;
icount->rx++;
- *tty->flip.flag_buf_ptr = 0;
+ flag = 0;
if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
printk("rxerr=%04X\n",status);
@@ -1530,41 +1528,31 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
status &= info->read_status_mask;
if (status & RXSTATUS_BREAK_RECEIVED) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & RXSTATUS_PARITY_ERROR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & RXSTATUS_FRAMING_ERROR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & RXSTATUS_OVERRUN) {
- /* Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
} /* end of if (error) */
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, DataByte, flag);
+ if (status & RXSTATUS_OVERRUN) {
+ /* Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
}
if ( debug_level >= DEBUG_LEVEL_ISR ) {
- printk("%s(%d):mgsl_isr_receive_data flip count=%d\n",
- __FILE__,__LINE__,tty->flip.count);
printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,icount->rx,icount->brk,
icount->parity,icount->frame,icount->overrun);
}
- if ( tty->flip.count )
+ if(work)
tty_flip_buffer_push(tty);
}
@@ -7058,7 +7046,7 @@ static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
{
static unsigned short BitPatterns[] =
{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
- static unsigned int Patterncount = sizeof(BitPatterns)/sizeof(unsigned short);
+ static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
unsigned int i;
BOOLEAN rc = TRUE;
unsigned long flags;
@@ -7501,9 +7489,9 @@ static int mgsl_adapter_test( struct mgsl_struct *info )
*/
static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
{
- static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa,
- 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
- unsigned long Patterncount = sizeof(BitPatterns)/sizeof(unsigned long);
+ static unsigned long BitPatterns[] =
+ { 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+ unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
unsigned long i;
unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
unsigned long * TestAddr;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
new file mode 100644
index 000000000000..a85a60a93deb
--- /dev/null
+++ b/drivers/char/synclink_gt.c
@@ -0,0 +1,4491 @@
+/*
+ * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $
+ *
+ * Device driver for Microgate SyncLink GT serial adapters.
+ *
+ * written by Paul Fulghum for Microgate Corporation
+ * paulkf@microgate.com
+ *
+ * Microgate and SyncLink are trademarks of Microgate Corporation
+ *
+ * This code is released under the GNU General Public License (GPL)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DEBUG OUTPUT DEFINITIONS
+ *
+ * uncomment lines below to enable specific types of debug output
+ *
+ * DBGINFO information - most verbose output
+ * DBGERR serious errors
+ * DBGBH bottom half service routine debugging
+ * DBGISR interrupt service routine debugging
+ * DBGDATA output receive and transmit data
+ * DBGTBUF output transmit DMA buffers and registers
+ * DBGRBUF output receive DMA buffers and registers
+ */
+
+#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
+#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
+#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
+#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
+#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
+//#define DBGTBUF(info) dump_tbufs(info)
+//#define DBGRBUF(info) dump_rbufs(info)
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/termios.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+#include "linux/synclink.h"
+
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
+#endif
+
+/*
+ * module identification
+ */
+static char *driver_name = "SyncLink GT";
+static char *driver_version = "$Revision: 4.22 $";
+static char *tty_driver_name = "synclink_gt";
+static char *tty_dev_prefix = "ttySLG";
+MODULE_LICENSE("GPL");
+#define MGSL_MAGIC 0x5401
+#define MAX_DEVICES 12
+
+static struct pci_device_id pci_table[] = {
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {0,}, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_table);
+
+static int init_one(struct pci_dev *dev,const struct pci_device_id *ent);
+static void remove_one(struct pci_dev *dev);
+static struct pci_driver pci_driver = {
+ .name = "synclink_gt",
+ .id_table = pci_table,
+ .probe = init_one,
+ .remove = __devexit_p(remove_one),
+};
+
+static int pci_registered;
+
+/*
+ * module configuration and status
+ */
+static struct slgt_info *slgt_device_list;
+static int slgt_device_count;
+
+static int ttymajor;
+static int debug_level;
+static int maxframe[MAX_DEVICES];
+static int dosyncppp[MAX_DEVICES];
+
+module_param(ttymajor, int, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+module_param_array(dosyncppp, int, NULL, 0);
+
+MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
+MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
+MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
+MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable");
+
+/*
+ * tty support and callbacks
+ */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+static struct tty_driver *serial_driver;
+
+static int open(struct tty_struct *tty, struct file * filp);
+static void close(struct tty_struct *tty, struct file * filp);
+static void hangup(struct tty_struct *tty);
+static void set_termios(struct tty_struct *tty, struct termios *old_termios);
+
+static int write(struct tty_struct *tty, const unsigned char *buf, int count);
+static void put_char(struct tty_struct *tty, unsigned char ch);
+static void send_xchar(struct tty_struct *tty, char ch);
+static void wait_until_sent(struct tty_struct *tty, int timeout);
+static int write_room(struct tty_struct *tty);
+static void flush_chars(struct tty_struct *tty);
+static void flush_buffer(struct tty_struct *tty);
+static void tx_hold(struct tty_struct *tty);
+static void tx_release(struct tty_struct *tty);
+
+static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
+static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data);
+static int chars_in_buffer(struct tty_struct *tty);
+static void throttle(struct tty_struct * tty);
+static void unthrottle(struct tty_struct * tty);
+static void set_break(struct tty_struct *tty, int break_state);
+
+/*
+ * generic HDLC support and callbacks
+ */
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct slgt_info *info);
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
+static int hdlcdev_init(struct slgt_info *info);
+static void hdlcdev_exit(struct slgt_info *info);
+#endif
+
+
+/*
+ * device specific structures, macros and functions
+ */
+
+#define SLGT_MAX_PORTS 4
+#define SLGT_REG_SIZE 256
+
+/*
+ * DMA buffer descriptor and access macros
+ */
+struct slgt_desc
+{
+ unsigned short count;
+ unsigned short status;
+ unsigned int pbuf; /* physical address of data buffer */
+ unsigned int next; /* physical address of next descriptor */
+
+ /* driver book keeping */
+ char *buf; /* virtual address of data buffer */
+ unsigned int pdesc; /* physical address of this descriptor */
+ dma_addr_t buf_dma_addr;
+};
+
+#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
+#define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b))
+#define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b))
+#define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
+#define desc_count(a) (le16_to_cpu((a).count))
+#define desc_status(a) (le16_to_cpu((a).status))
+#define desc_complete(a) (le16_to_cpu((a).status) & BIT15)
+#define desc_eof(a) (le16_to_cpu((a).status) & BIT2)
+#define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1)
+#define desc_abort(a) (le16_to_cpu((a).status) & BIT0)
+#define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3)
+
+struct _input_signal_events {
+ int ri_up;
+ int ri_down;
+ int dsr_up;
+ int dsr_down;
+ int dcd_up;
+ int dcd_down;
+ int cts_up;
+ int cts_down;
+};
+
+/*
+ * device instance data structure
+ */
+struct slgt_info {
+ void *if_ptr; /* General purpose pointer (used by SPPP) */
+
+ struct slgt_info *next_device; /* device list link */
+
+ int magic;
+ int flags;
+
+ char device_name[25];
+ struct pci_dev *pdev;
+
+ int port_count; /* count of ports on adapter */
+ int adapter_num; /* adapter instance number */
+ int port_num; /* port instance number */
+
+ /* array of pointers to port contexts on this adapter */
+ struct slgt_info *port_array[SLGT_MAX_PORTS];
+
+ int count; /* count of opens */
+ int line; /* tty line instance number */
+ unsigned short close_delay;
+ unsigned short closing_wait; /* time to wait before closing */
+
+ struct mgsl_icount icount;
+
+ struct tty_struct *tty;
+ int timeout;
+ int x_char; /* xon/xoff character */
+ int blocked_open; /* # of blocked opens */
+ unsigned int read_status_mask;
+ unsigned int ignore_status_mask;
+
+ wait_queue_head_t open_wait;
+ wait_queue_head_t close_wait;
+
+ wait_queue_head_t status_event_wait_q;
+ wait_queue_head_t event_wait_q;
+ struct timer_list tx_timer;
+ struct timer_list rx_timer;
+
+ spinlock_t lock; /* spinlock for synchronizing with ISR */
+
+ struct work_struct task;
+ u32 pending_bh;
+ int bh_requested;
+ int bh_running;
+
+ int isr_overflow;
+ int irq_requested; /* nonzero if IRQ requested */
+ int irq_occurred; /* for diagnostics use */
+
+ /* device configuration */
+
+ unsigned int bus_type;
+ unsigned int irq_level;
+ unsigned long irq_flags;
+
+ unsigned char __iomem * reg_addr; /* memory mapped registers address */
+ u32 phys_reg_addr;
+ int reg_addr_requested;
+
+ MGSL_PARAMS params; /* communications parameters */
+ u32 idle_mode;
+ u32 max_frame_size; /* as set by device config */
+
+ unsigned int raw_rx_size;
+ unsigned int if_mode;
+
+ /* device status */
+
+ int rx_enabled;
+ int rx_restart;
+
+ int tx_enabled;
+ int tx_active;
+
+ unsigned char signals; /* serial signal states */
+ unsigned int init_error; /* initialization error */
+
+ unsigned char *tx_buf;
+ int tx_count;
+
+ char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+ char char_buf[MAX_ASYNC_BUFFER_SIZE];
+ BOOLEAN drop_rts_on_tx_done;
+ struct _input_signal_events input_signal_events;
+
+ int dcd_chkcount; /* check counts to prevent */
+ int cts_chkcount; /* too many IRQs if a signal */
+ int dsr_chkcount; /* is floating */
+ int ri_chkcount;
+
+ char *bufs; /* virtual address of DMA buffer lists */
+ dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
+
+ unsigned int rbuf_count;
+ struct slgt_desc *rbufs;
+ unsigned int rbuf_current;
+ unsigned int rbuf_index;
+
+ unsigned int tbuf_count;
+ struct slgt_desc *tbufs;
+ unsigned int tbuf_current;
+ unsigned int tbuf_start;
+
+ unsigned char *tmp_rbuf;
+ unsigned int tmp_rbuf_count;
+
+ /* SPPP/Cisco HDLC device parts */
+
+ int netcount;
+ int dosyncppp;
+ spinlock_t netlock;
+#ifdef CONFIG_HDLC
+ struct net_device *netdev;
+#endif
+
+};
+
+static MGSL_PARAMS default_params = {
+ .mode = MGSL_MODE_HDLC,
+ .loopback = 0,
+ .flags = HDLC_FLAG_UNDERRUN_ABORT15,
+ .encoding = HDLC_ENCODING_NRZI_SPACE,
+ .clock_speed = 0,
+ .addr_filter = 0xff,
+ .crc_type = HDLC_CRC_16_CCITT,
+ .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
+ .preamble = HDLC_PREAMBLE_PATTERN_NONE,
+ .data_rate = 9600,
+ .data_bits = 8,
+ .stop_bits = 1,
+ .parity = ASYNC_PARITY_NONE
+};
+
+
+#define BH_RECEIVE 1
+#define BH_TRANSMIT 2
+#define BH_STATUS 4
+#define IO_PIN_SHUTDOWN_LIMIT 100
+
+#define DMABUFSIZE 256
+#define DESC_LIST_SIZE 4096
+
+#define MASK_PARITY BIT1
+#define MASK_FRAMING BIT2
+#define MASK_BREAK BIT3
+#define MASK_OVERRUN BIT4
+
+#define GSR 0x00 /* global status */
+#define TDR 0x80 /* tx data */
+#define RDR 0x80 /* rx data */
+#define TCR 0x82 /* tx control */
+#define TIR 0x84 /* tx idle */
+#define TPR 0x85 /* tx preamble */
+#define RCR 0x86 /* rx control */
+#define VCR 0x88 /* V.24 control */
+#define CCR 0x89 /* clock control */
+#define BDR 0x8a /* baud divisor */
+#define SCR 0x8c /* serial control */
+#define SSR 0x8e /* serial status */
+#define RDCSR 0x90 /* rx DMA control/status */
+#define TDCSR 0x94 /* tx DMA control/status */
+#define RDDAR 0x98 /* rx DMA descriptor address */
+#define TDDAR 0x9c /* tx DMA descriptor address */
+
+#define RXIDLE BIT14
+#define RXBREAK BIT14
+#define IRQ_TXDATA BIT13
+#define IRQ_TXIDLE BIT12
+#define IRQ_TXUNDER BIT11 /* HDLC */
+#define IRQ_RXDATA BIT10
+#define IRQ_RXIDLE BIT9 /* HDLC */
+#define IRQ_RXBREAK BIT9 /* async */
+#define IRQ_RXOVER BIT8
+#define IRQ_DSR BIT7
+#define IRQ_CTS BIT6
+#define IRQ_DCD BIT5
+#define IRQ_RI BIT4
+#define IRQ_ALL 0x3ff0
+#define IRQ_MASTER BIT0
+
+#define slgt_irq_on(info, mask) \
+ wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
+#define slgt_irq_off(info, mask) \
+ wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
+
+static __u8 rd_reg8(struct slgt_info *info, unsigned int addr);
+static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
+static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
+static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
+
+static void msc_set_vcr(struct slgt_info *info);
+
+static int startup(struct slgt_info *info);
+static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
+static void shutdown(struct slgt_info *info);
+static void program_hw(struct slgt_info *info);
+static void change_params(struct slgt_info *info);
+
+static int register_test(struct slgt_info *info);
+static int irq_test(struct slgt_info *info);
+static int loopback_test(struct slgt_info *info);
+static int adapter_test(struct slgt_info *info);
+
+static void reset_adapter(struct slgt_info *info);
+static void reset_port(struct slgt_info *info);
+static void async_mode(struct slgt_info *info);
+static void hdlc_mode(struct slgt_info *info);
+
+static void rx_stop(struct slgt_info *info);
+static void rx_start(struct slgt_info *info);
+static void reset_rbufs(struct slgt_info *info);
+static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
+static void rdma_reset(struct slgt_info *info);
+static int rx_get_frame(struct slgt_info *info);
+static int rx_get_buf(struct slgt_info *info);
+
+static void tx_start(struct slgt_info *info);
+static void tx_stop(struct slgt_info *info);
+static void tx_set_idle(struct slgt_info *info);
+static unsigned int free_tbuf_count(struct slgt_info *info);
+static void reset_tbufs(struct slgt_info *info);
+static void tdma_reset(struct slgt_info *info);
+static void tx_load(struct slgt_info *info, const char *buf, unsigned int count);
+
+static void get_signals(struct slgt_info *info);
+static void set_signals(struct slgt_info *info);
+static void enable_loopback(struct slgt_info *info);
+static void set_rate(struct slgt_info *info, u32 data_rate);
+
+static int bh_action(struct slgt_info *info);
+static void bh_handler(void* context);
+static void bh_transmit(struct slgt_info *info);
+static void isr_serial(struct slgt_info *info);
+static void isr_rdma(struct slgt_info *info);
+static void isr_txeom(struct slgt_info *info, unsigned short status);
+static void isr_tdma(struct slgt_info *info);
+static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+
+static int alloc_dma_bufs(struct slgt_info *info);
+static void free_dma_bufs(struct slgt_info *info);
+static int alloc_desc(struct slgt_info *info);
+static void free_desc(struct slgt_info *info);
+static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+
+static int alloc_tmp_rbuf(struct slgt_info *info);
+static void free_tmp_rbuf(struct slgt_info *info);
+
+static void tx_timeout(unsigned long context);
+static void rx_timeout(unsigned long context);
+
+/*
+ * ioctl handlers
+ */
+static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
+static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int get_txidle(struct slgt_info *info, int __user *idle_mode);
+static int set_txidle(struct slgt_info *info, int idle_mode);
+static int tx_enable(struct slgt_info *info, int enable);
+static int tx_abort(struct slgt_info *info);
+static int rx_enable(struct slgt_info *info, int enable);
+static int modem_input_wait(struct slgt_info *info,int arg);
+static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
+static int tiocmget(struct tty_struct *tty, struct file *file);
+static int tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear);
+static void set_break(struct tty_struct *tty, int break_state);
+static int get_interface(struct slgt_info *info, int __user *if_mode);
+static int set_interface(struct slgt_info *info, int if_mode);
+
+/*
+ * driver functions
+ */
+static void add_device(struct slgt_info *info);
+static void device_init(int adapter_num, struct pci_dev *pdev);
+static int claim_resources(struct slgt_info *info);
+static void release_resources(struct slgt_info *info);
+
+/*
+ * DEBUG OUTPUT CODE
+ */
+#ifndef DBGINFO
+#define DBGINFO(fmt)
+#endif
+#ifndef DBGERR
+#define DBGERR(fmt)
+#endif
+#ifndef DBGBH
+#define DBGBH(fmt)
+#endif
+#ifndef DBGISR
+#define DBGISR(fmt)
+#endif
+
+#ifdef DBGDATA
+static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
+{
+ int i;
+ int linecount;
+ printk("%s %s data:\n",info->device_name, label);
+ while(count) {
+ linecount = (count > 16) ? 16 : count;
+ for(i=0; i < linecount; i++)
+ printk("%02X ",(unsigned char)data[i]);
+ for(;i<17;i++)
+ printk(" ");
+ for(i=0;i<linecount;i++) {
+ if (data[i]>=040 && data[i]<=0176)
+ printk("%c",data[i]);
+ else
+ printk(".");
+ }
+ printk("\n");
+ data += linecount;
+ count -= linecount;
+ }
+}
+#else
+#define DBGDATA(info, buf, size, label)
+#endif
+
+#ifdef DBGTBUF
+static void dump_tbufs(struct slgt_info *info)
+{
+ int i;
+ printk("tbuf_current=%d\n", info->tbuf_current);
+ for (i=0 ; i < info->tbuf_count ; i++) {
+ printk("%d: count=%04X status=%04X\n",
+ i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
+ }
+}
+#else
+#define DBGTBUF(info)
+#endif
+
+#ifdef DBGRBUF
+static void dump_rbufs(struct slgt_info *info)
+{
+ int i;
+ printk("rbuf_current=%d\n", info->rbuf_current);
+ for (i=0 ; i < info->rbuf_count ; i++) {
+ printk("%d: count=%04X status=%04X\n",
+ i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
+ }
+}
+#else
+#define DBGRBUF(info)
+#endif
+
+static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
+{
+#ifdef SANITY_CHECK
+ if (!info) {
+ printk("null struct slgt_info for (%s) in %s\n", devname, name);
+ return 1;
+ }
+ if (info->magic != MGSL_MAGIC) {
+ printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
+ return 1;
+ }
+#else
+ if (!info)
+ return 1;
+#endif
+ return 0;
+}
+
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf - pass receive data to line discipline
+ */
+static void ldisc_receive_buf(struct tty_struct *tty,
+ const __u8 *data, char *flags, int count)
+{
+ struct tty_ldisc *ld;
+ if (!tty)
+ return;
+ ld = tty_ldisc_ref(tty);
+ if (ld) {
+ if (ld->receive_buf)
+ ld->receive_buf(tty, data, flags, count);
+ tty_ldisc_deref(ld);
+ }
+}
+
+/* tty callbacks */
+
+static int open(struct tty_struct *tty, struct file *filp)
+{
+ struct slgt_info *info;
+ int retval, line;
+ unsigned long flags;
+
+ line = tty->index;
+ if ((line < 0) || (line >= slgt_device_count)) {
+ DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
+ return -ENODEV;
+ }
+
+ info = slgt_device_list;
+ while(info && info->line != line)
+ info = info->next_device;
+ if (sanity_check(info, tty->name, "open"))
+ return -ENODEV;
+ if (info->init_error) {
+ DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
+ return -ENODEV;
+ }
+
+ tty->driver_data = info;
+ info->tty = tty;
+
+ DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->count));
+
+ /* If port is closing, signal caller to try again */
+ if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){
+ if (info->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&info->close_wait);
+ retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS);
+ goto cleanup;
+ }
+
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ spin_lock_irqsave(&info->netlock, flags);
+ if (info->netcount) {
+ retval = -EBUSY;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ goto cleanup;
+ }
+ info->count++;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ if (info->count == 1) {
+ /* 1st open on this device, init hardware */
+ retval = startup(info);
+ if (retval < 0)
+ goto cleanup;
+ }
+
+ retval = block_til_ready(tty, filp, info);
+ if (retval) {
+ DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
+ goto cleanup;
+ }
+
+ retval = 0;
+
+cleanup:
+ if (retval) {
+ if (tty->count == 1)
+ info->tty = NULL; /* tty layer will release tty struct */
+ if(info->count)
+ info->count--;
+ }
+
+ DBGINFO(("%s open rc=%d\n", info->device_name, retval));
+ return retval;
+}
+
+static void close(struct tty_struct *tty, struct file *filp)
+{
+ struct slgt_info *info = tty->driver_data;
+
+ if (sanity_check(info, tty->name, "close"))
+ return;
+ DBGINFO(("%s close entry, count=%d\n", info->device_name, info->count));
+
+ if (!info->count)
+ return;
+
+ if (tty_hung_up_p(filp))
+ goto cleanup;
+
+ if ((tty->count == 1) && (info->count != 1)) {
+ /*
+ * tty->count is 1 and the tty structure will be freed.
+ * info->count should be one in this case.
+ * if it's not, correct it so that the port is shutdown.
+ */
+ DBGERR(("%s close: bad refcount; tty->count=1, "
+ "info->count=%d\n", info->device_name, info->count));
+ info->count = 1;
+ }
+
+ info->count--;
+
+ /* if at least one open remaining, leave hardware active */
+ if (info->count)
+ goto cleanup;
+
+ info->flags |= ASYNC_CLOSING;
+
+ /* set tty->closing to notify line discipline to
+ * only process XON/XOFF characters. Only the N_TTY
+ * discipline appears to use this (ppp does not).
+ */
+ tty->closing = 1;
+
+ /* wait for transmit data to clear all layers */
+
+ if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
+ DBGINFO(("%s call tty_wait_until_sent\n", info->device_name));
+ tty_wait_until_sent(tty, info->closing_wait);
+ }
+
+ if (info->flags & ASYNC_INITIALIZED)
+ wait_until_sent(tty, info->timeout);
+ if (tty->driver->flush_buffer)
+ tty->driver->flush_buffer(tty);
+ tty_ldisc_flush(tty);
+
+ shutdown(info);
+
+ tty->closing = 0;
+ info->tty = NULL;
+
+ if (info->blocked_open) {
+ if (info->close_delay) {
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
+ }
+ wake_up_interruptible(&info->open_wait);
+ }
+
+ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+
+ wake_up_interruptible(&info->close_wait);
+
+cleanup:
+ DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->count));
+}
+
+static void hangup(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+
+ if (sanity_check(info, tty->name, "hangup"))
+ return;
+ DBGINFO(("%s hangup\n", info->device_name));
+
+ flush_buffer(tty);
+ shutdown(info);
+
+ info->count = 0;
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
+ info->tty = NULL;
+
+ wake_up_interruptible(&info->open_wait);
+}
+
+static void set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ DBGINFO(("%s set_termios\n", tty->driver->name));
+
+ /* just return if nothing has changed */
+ if ((tty->termios->c_cflag == old_termios->c_cflag)
+ && (RELEVANT_IFLAG(tty->termios->c_iflag)
+ == RELEVANT_IFLAG(old_termios->c_iflag)))
+ return;
+
+ change_params(info);
+
+ /* Handle transition to B0 status */
+ if (old_termios->c_cflag & CBAUD &&
+ !(tty->termios->c_cflag & CBAUD)) {
+ info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ /* Handle transition away from B0 status */
+ if (!(old_termios->c_cflag & CBAUD) &&
+ tty->termios->c_cflag & CBAUD) {
+ info->signals |= SerialSignal_DTR;
+ if (!(tty->termios->c_cflag & CRTSCTS) ||
+ !test_bit(TTY_THROTTLED, &tty->flags)) {
+ info->signals |= SerialSignal_RTS;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ /* Handle turning off CRTSCTS */
+ if (old_termios->c_cflag & CRTSCTS &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ tx_release(tty);
+ }
+}
+
+static int write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ int ret = 0;
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "write"))
+ goto cleanup;
+ DBGINFO(("%s write count=%d\n", info->device_name, count));
+
+ if (!tty || !info->tx_buf)
+ goto cleanup;
+
+ if (count > info->max_frame_size) {
+ ret = -EIO;
+ goto cleanup;
+ }
+
+ if (!count)
+ goto cleanup;
+
+ if (info->params.mode == MGSL_MODE_RAW) {
+ unsigned int bufs_needed = (count/DMABUFSIZE);
+ unsigned int bufs_free = free_tbuf_count(info);
+ if (count % DMABUFSIZE)
+ ++bufs_needed;
+ if (bufs_needed > bufs_free)
+ goto cleanup;
+ } else {
+ if (info->tx_active)
+ goto cleanup;
+ if (info->tx_count) {
+ /* send accumulated data from send_char() calls */
+ /* as frame and wait before accepting more data. */
+ tx_load(info, info->tx_buf, info->tx_count);
+ goto start;
+ }
+ }
+
+ ret = info->tx_count = count;
+ tx_load(info, buf, count);
+ goto start;
+
+start:
+ if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+cleanup:
+ DBGINFO(("%s write rc=%d\n", info->device_name, ret));
+ return ret;
+}
+
+static void put_char(struct tty_struct *tty, unsigned char ch)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "put_char"))
+ return;
+ DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
+ if (!tty || !info->tx_buf)
+ return;
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && (info->tx_count < info->max_frame_size))
+ info->tx_buf[info->tx_count++] = ch;
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+static void send_xchar(struct tty_struct *tty, char ch)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "send_xchar"))
+ return;
+ DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
+ info->x_char = ch;
+ if (ch) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_enabled)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+static void wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long orig_jiffies, char_time;
+
+ if (!info )
+ return;
+ if (sanity_check(info, tty->name, "wait_until_sent"))
+ return;
+ DBGINFO(("%s wait_until_sent entry\n", info->device_name));
+ if (!(info->flags & ASYNC_INITIALIZED))
+ goto exit;
+
+ orig_jiffies = jiffies;
+
+ /* Set check interval to 1/5 of estimated time to
+ * send a character, and make it at least 1. The check
+ * interval should also be less than the timeout.
+ * Note: use tight timings here to satisfy the NIST-PCTS.
+ */
+
+ if (info->params.data_rate) {
+ char_time = info->timeout/(32 * 5);
+ if (!char_time)
+ char_time++;
+ } else
+ char_time = 1;
+
+ if (timeout)
+ char_time = min_t(unsigned long, char_time, timeout);
+
+ while (info->tx_active) {
+ msleep_interruptible(jiffies_to_msecs(char_time));
+ if (signal_pending(current))
+ break;
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
+ break;
+ }
+
+exit:
+ DBGINFO(("%s wait_until_sent exit\n", info->device_name));
+}
+
+static int write_room(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ int ret;
+
+ if (sanity_check(info, tty->name, "write_room"))
+ return 0;
+ ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+ DBGINFO(("%s write_room=%d\n", info->device_name, ret));
+ return ret;
+}
+
+static void flush_chars(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "flush_chars"))
+ return;
+ DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
+
+ if (info->tx_count <= 0 || tty->stopped ||
+ tty->hw_stopped || !info->tx_buf)
+ return;
+
+ DBGINFO(("%s flush_chars start transmit\n", info->device_name));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && info->tx_count) {
+ tx_load(info, info->tx_buf,info->tx_count);
+ tx_start(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+static void flush_buffer(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "flush_buffer"))
+ return;
+ DBGINFO(("%s flush_buffer\n", info->device_name));
+
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ wake_up_interruptible(&tty->write_wait);
+ tty_wakeup(tty);
+}
+
+/*
+ * throttle (stop) transmitter
+ */
+static void tx_hold(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "tx_hold"))
+ return;
+ DBGINFO(("%s tx_hold\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
+ tx_stop(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * release (start) transmitter
+ */
+static void tx_release(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "tx_release"))
+ return;
+ DBGINFO(("%s tx_release\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active && info->tx_count) {
+ tx_load(info, info->tx_buf, info->tx_count);
+ tx_start(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * Service an IOCTL request
+ *
+ * Arguments
+ *
+ * tty pointer to tty instance data
+ * file pointer to associated file object for device
+ * cmd IOCTL command code
+ * arg command argument/context
+ *
+ * Return 0 if success, otherwise error code
+ */
+static int ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct slgt_info *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ unsigned long flags;
+ void __user *argp = (void __user *)arg;
+
+ if (sanity_check(info, tty->name, "ioctl"))
+ return -ENODEV;
+ DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
+
+ if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ if (tty->flags & (1 << TTY_IO_ERROR))
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case MGSL_IOCGPARAMS:
+ return get_params(info, argp);
+ case MGSL_IOCSPARAMS:
+ return set_params(info, argp);
+ case MGSL_IOCGTXIDLE:
+ return get_txidle(info, argp);
+ case MGSL_IOCSTXIDLE:
+ return set_txidle(info, (int)arg);
+ case MGSL_IOCTXENABLE:
+ return tx_enable(info, (int)arg);
+ case MGSL_IOCRXENABLE:
+ return rx_enable(info, (int)arg);
+ case MGSL_IOCTXABORT:
+ return tx_abort(info);
+ case MGSL_IOCGSTATS:
+ return get_stats(info, argp);
+ case MGSL_IOCWAITEVENT:
+ return wait_mgsl_event(info, argp);
+ case TIOCMIWAIT:
+ return modem_input_wait(info,(int)arg);
+ case MGSL_IOCGIF:
+ return get_interface(info, argp);
+ case MGSL_IOCSIF:
+ return set_interface(info,(int)arg);
+ case TIOCGICOUNT:
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+ p_cuser = argp;
+ if (put_user(cnow.cts, &p_cuser->cts) ||
+ put_user(cnow.dsr, &p_cuser->dsr) ||
+ put_user(cnow.rng, &p_cuser->rng) ||
+ put_user(cnow.dcd, &p_cuser->dcd) ||
+ put_user(cnow.rx, &p_cuser->rx) ||
+ put_user(cnow.tx, &p_cuser->tx) ||
+ put_user(cnow.frame, &p_cuser->frame) ||
+ put_user(cnow.overrun, &p_cuser->overrun) ||
+ put_user(cnow.parity, &p_cuser->parity) ||
+ put_user(cnow.brk, &p_cuser->brk) ||
+ put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
+ return -EFAULT;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/*
+ * proc fs support
+ */
+static inline int line_info(char *buf, struct slgt_info *info)
+{
+ char stat_buf[30];
+ int ret;
+ unsigned long flags;
+
+ ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",
+ info->device_name, info->phys_reg_addr,
+ info->irq_level, info->max_frame_size);
+
+ /* output current serial signal states */
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ stat_buf[0] = 0;
+ stat_buf[1] = 0;
+ if (info->signals & SerialSignal_RTS)
+ strcat(stat_buf, "|RTS");
+ if (info->signals & SerialSignal_CTS)
+ strcat(stat_buf, "|CTS");
+ if (info->signals & SerialSignal_DTR)
+ strcat(stat_buf, "|DTR");
+ if (info->signals & SerialSignal_DSR)
+ strcat(stat_buf, "|DSR");
+ if (info->signals & SerialSignal_DCD)
+ strcat(stat_buf, "|CD");
+ if (info->signals & SerialSignal_RI)
+ strcat(stat_buf, "|RI");
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d",
+ info->icount.txok, info->icount.rxok);
+ if (info->icount.txunder)
+ ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder);
+ if (info->icount.txabort)
+ ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort);
+ if (info->icount.rxshort)
+ ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort);
+ if (info->icount.rxlong)
+ ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong);
+ if (info->icount.rxover)
+ ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
+ if (info->icount.rxcrc)
+ ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
+ } else {
+ ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d",
+ info->icount.tx, info->icount.rx);
+ if (info->icount.frame)
+ ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+ if (info->icount.parity)
+ ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+ if (info->icount.brk)
+ ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+ if (info->icount.overrun)
+ ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+ }
+
+ /* Append serial signal status to end */
+ ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+
+ ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
+ info->tx_active,info->bh_requested,info->bh_running,
+ info->pending_bh);
+
+ return ret;
+}
+
+/* Called to print information about devices
+ */
+static int read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len = 0, l;
+ off_t begin = 0;
+ struct slgt_info *info;
+
+ len += sprintf(page, "synclink_gt driver:%s\n", driver_version);
+
+ info = slgt_device_list;
+ while( info ) {
+ l = line_info(page + len, info);
+ len += l;
+ if (len+begin > off+count)
+ goto done;
+ if (len+begin < off) {
+ begin += len;
+ len = 0;
+ }
+ info = info->next_device;
+ }
+
+ *eof = 1;
+done:
+ if (off >= len+begin)
+ return 0;
+ *start = page + (off-begin);
+ return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * return count of bytes in transmit buffer
+ */
+static int chars_in_buffer(struct tty_struct *tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ if (sanity_check(info, tty->name, "chars_in_buffer"))
+ return 0;
+ DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count));
+ return info->tx_count;
+}
+
+/*
+ * signal remote device to throttle send data (our receive data)
+ */
+static void throttle(struct tty_struct * tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "throttle"))
+ return;
+ DBGINFO(("%s throttle\n", info->device_name));
+ if (I_IXOFF(tty))
+ send_xchar(tty, STOP_CHAR(tty));
+ if (tty->termios->c_cflag & CRTSCTS) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals &= ~SerialSignal_RTS;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+/*
+ * signal remote device to stop throttling send data (our receive data)
+ */
+static void unthrottle(struct tty_struct * tty)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "unthrottle"))
+ return;
+ DBGINFO(("%s unthrottle\n", info->device_name));
+ if (I_IXOFF(tty)) {
+ if (info->x_char)
+ info->x_char = 0;
+ else
+ send_xchar(tty, START_CHAR(tty));
+ }
+ if (tty->termios->c_cflag & CRTSCTS) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals |= SerialSignal_RTS;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+}
+
+/*
+ * set or clear transmit break condition
+ * break_state -1=set break condition, 0=clear
+ */
+static void set_break(struct tty_struct *tty, int break_state)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned short value;
+ unsigned long flags;
+
+ if (sanity_check(info, tty->name, "set_break"))
+ return;
+ DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
+
+ spin_lock_irqsave(&info->lock,flags);
+ value = rd_reg16(info, TCR);
+ if (break_state == -1)
+ value |= BIT6;
+ else
+ value &= ~BIT6;
+ wr_reg16(info, TCR, value);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev pointer to network device structure
+ * encoding serial encoding setting
+ * parity FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned char new_encoding;
+ unsigned short new_crctype;
+
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
+
+ DBGINFO(("%s hdlcdev_attach\n", info->device_name));
+
+ switch (encoding)
+ {
+ case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break;
+ case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+ case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+ case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+ case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+ default: return -EINVAL;
+ }
+
+ switch (parity)
+ {
+ case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break;
+ case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+ case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+ default: return -EINVAL;
+ }
+
+ info->params.encoding = new_encoding;
+ info->params.crc_type = new_crctype;;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ program_hw(info);
+
+ return 0;
+}
+
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb socket buffer containing HDLC frame
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlc_xmit\n", dev->name));
+
+ /* stop sending until this frame completes */
+ netif_stop_queue(dev);
+
+ /* copy data to device buffers */
+ info->tx_count = skb->len;
+ tx_load(info, skb->data, skb->len);
+
+ /* update network statistics */
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+
+ /* done with socket buffer, so free it */
+ dev_kfree_skb(skb);
+
+ /* save start time for transmit timeout detection */
+ dev->trans_start = jiffies;
+
+ /* start hardware transmitter if necessary */
+ spin_lock_irqsave(&info->lock,flags);
+ if (!info->tx_active)
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return 0;
+}
+
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ int rc;
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_open\n", dev->name));
+
+ /* generic HDLC layer open processing */
+ if ((rc = hdlc_open(dev)))
+ return rc;
+
+ /* arbitrate between network and tty opens */
+ spin_lock_irqsave(&info->netlock, flags);
+ if (info->count != 0 || info->netcount != 0) {
+ DBGINFO(("%s hdlc_open busy\n", dev->name));
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return -EBUSY;
+ }
+ info->netcount=1;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ /* claim resources and init adapter */
+ if ((rc = startup(info)) != 0) {
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return rc;
+ }
+
+ /* assert DTR and RTS, apply hardware settings */
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ program_hw(info);
+
+ /* enable network layer transmit */
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
+
+ /* inform generic HDLC layer of current DCD status */
+ spin_lock_irqsave(&info->lock, flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+ hdlc_set_carrier(info->signals & SerialSignal_DCD, dev);
+
+ return 0;
+}
+
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_close\n", dev->name));
+
+ netif_stop_queue(dev);
+
+ /* shutdown adapter and release resources */
+ shutdown(info);
+
+ hdlc_close(dev);
+
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ return 0;
+}
+
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev pointer to network device structure
+ * ifr pointer to network interface request structure
+ * cmd IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line;
+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+ struct slgt_info *info = dev_to_port(dev);
+ unsigned int flags;
+
+ DBGINFO(("%s hdlcdev_ioctl\n", dev->name));
+
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
+
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
+
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE: /* return current sync_serial_settings */
+
+ ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
+
+ flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+
+ switch (flags){
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+ case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+ default: new_line.clock_type = CLOCK_DEFAULT;
+ }
+
+ new_line.clock_rate = info->params.clock_speed;
+ new_line.loopback = info->params.loopback ? 1:0;
+
+ if (copy_to_user(line, &new_line, size))
+ return -EFAULT;
+ return 0;
+
+ case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ switch (new_line.clock_type)
+ {
+ case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+ case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+ case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_DEFAULT: flags = info->params.flags &
+ (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break;
+ default: return -EINVAL;
+ }
+
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
+
+ info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+ info->params.flags |= flags;
+
+ info->params.loopback = new_line.loopback;
+
+ if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+ info->params.clock_speed = new_line.clock_rate;
+ else
+ info->params.clock_speed = 0;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ program_hw(info);
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
+}
+
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
+{
+ struct slgt_info *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
+ DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));
+
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
+
+ spin_lock_irqsave(&info->lock,flags);
+ tx_stop(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct slgt_info *info)
+{
+ if (netif_queue_stopped(info->netdev))
+ netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info pointer to device instance information
+ * buf pointer to buffer contianing frame data
+ * size count of data bytes in buf
+ */
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
+{
+ struct sk_buff *skb = dev_alloc_skb(size);
+ struct net_device *dev = info->netdev;
+ struct net_device_stats *stats = hdlc_stats(dev);
+
+ DBGINFO(("%s hdlcdev_rx\n", dev->name));
+
+ if (skb == NULL) {
+ DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));
+ stats->rx_dropped++;
+ return;
+ }
+
+ memcpy(skb_put(skb, size),buf,size);
+
+ skb->protocol = hdlc_type_trans(skb, info->netdev);
+
+ stats->rx_packets++;
+ stats->rx_bytes += size;
+
+ netif_rx(skb);
+
+ info->netdev->last_rx = jiffies;
+}
+
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct slgt_info *info)
+{
+ int rc;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+
+ /* allocate and initialize network and HDLC layer objects */
+
+ if (!(dev = alloc_hdlcdev(info))) {
+ printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
+ return -ENOMEM;
+ }
+
+ /* for network layer reporting purposes only */
+ dev->mem_start = info->phys_reg_addr;
+ dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1;
+ dev->irq = info->irq_level;
+
+ /* network layer callbacks and settings */
+ dev->do_ioctl = hdlcdev_ioctl;
+ dev->open = hdlcdev_open;
+ dev->stop = hdlcdev_close;
+ dev->tx_timeout = hdlcdev_tx_timeout;
+ dev->watchdog_timeo = 10*HZ;
+ dev->tx_queue_len = 50;
+
+ /* generic HDLC layer callbacks and settings */
+ hdlc = dev_to_hdlc(dev);
+ hdlc->attach = hdlcdev_attach;
+ hdlc->xmit = hdlcdev_xmit;
+
+ /* register objects with HDLC layer */
+ if ((rc = register_hdlc_device(dev))) {
+ printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+ free_netdev(dev);
+ return rc;
+ }
+
+ info->netdev = dev;
+ return 0;
+}
+
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_exit(struct slgt_info *info)
+{
+ unregister_hdlc_device(info->netdev);
+ free_netdev(info->netdev);
+ info->netdev = NULL;
+}
+
+#endif /* ifdef CONFIG_HDLC */
+
+/*
+ * get async data from rx DMA buffers
+ */
+static void rx_async(struct slgt_info *info)
+{
+ struct tty_struct *tty = info->tty;
+ struct mgsl_icount *icount = &info->icount;
+ unsigned int start, end;
+ unsigned char *p;
+ unsigned char status;
+ struct slgt_desc *bufs = info->rbufs;
+ int i, count;
+ int chars = 0;
+ int stat;
+ unsigned char ch;
+
+ start = end = info->rbuf_current;
+
+ while(desc_complete(bufs[end])) {
+ count = desc_count(bufs[end]) - info->rbuf_index;
+ p = bufs[end].buf + info->rbuf_index;
+
+ DBGISR(("%s rx_async count=%d\n", info->device_name, count));
+ DBGDATA(info, p, count, "rx");
+
+ for(i=0 ; i < count; i+=2, p+=2) {
+ if (tty && chars) {
+ tty_flip_buffer_push(tty);
+ chars = 0;
+ }
+ ch = *p;
+ icount->rx++;
+
+ stat = 0;
+
+ if ((status = *(p+1) & (BIT9 + BIT8))) {
+ if (status & BIT9)
+ icount->parity++;
+ else if (status & BIT8)
+ icount->frame++;
+ /* discard char if tty control flags say so */
+ if (status & info->ignore_status_mask)
+ continue;
+ if (status & BIT9)
+ stat = TTY_PARITY;
+ else if (status & BIT8)
+ stat = TTY_FRAME;
+ }
+ if (tty) {
+ tty_insert_flip_char(tty, ch, stat);
+ chars++;
+ }
+ }
+
+ if (i < count) {
+ /* receive buffer not completed */
+ info->rbuf_index += i;
+ info->rx_timer.expires = jiffies + 1;
+ add_timer(&info->rx_timer);
+ break;
+ }
+
+ info->rbuf_index = 0;
+ free_rbufs(info, end, end);
+
+ if (++end == info->rbuf_count)
+ end = 0;
+
+ /* if entire list searched then no frame available */
+ if (end == start)
+ break;
+ }
+
+ if (tty && chars)
+ tty_flip_buffer_push(tty);
+}
+
+/*
+ * return next bottom half action to perform
+ */
+static int bh_action(struct slgt_info *info)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ if (info->pending_bh & BH_RECEIVE) {
+ info->pending_bh &= ~BH_RECEIVE;
+ rc = BH_RECEIVE;
+ } else if (info->pending_bh & BH_TRANSMIT) {
+ info->pending_bh &= ~BH_TRANSMIT;
+ rc = BH_TRANSMIT;
+ } else if (info->pending_bh & BH_STATUS) {
+ info->pending_bh &= ~BH_STATUS;
+ rc = BH_STATUS;
+ } else {
+ /* Mark BH routine as complete */
+ info->bh_running = 0;
+ info->bh_requested = 0;
+ rc = 0;
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ return rc;
+}
+
+/*
+ * perform bottom half processing
+ */
+static void bh_handler(void* context)
+{
+ struct slgt_info *info = context;
+ int action;
+
+ if (!info)
+ return;
+ info->bh_running = 1;
+
+ while((action = bh_action(info))) {
+ switch (action) {
+ case BH_RECEIVE:
+ DBGBH(("%s bh receive\n", info->device_name));
+ switch(info->params.mode) {
+ case MGSL_MODE_ASYNC:
+ rx_async(info);
+ break;
+ case MGSL_MODE_HDLC:
+ while(rx_get_frame(info));
+ break;
+ case MGSL_MODE_RAW:
+ while(rx_get_buf(info));
+ break;
+ }
+ /* restart receiver if rx DMA buffers exhausted */
+ if (info->rx_restart)
+ rx_start(info);
+ break;
+ case BH_TRANSMIT:
+ bh_transmit(info);
+ break;
+ case BH_STATUS:
+ DBGBH(("%s bh status\n", info->device_name));
+ info->ri_chkcount = 0;
+ info->dsr_chkcount = 0;
+ info->dcd_chkcount = 0;
+ info->cts_chkcount = 0;
+ break;
+ default:
+ DBGBH(("%s unknown action\n", info->device_name));
+ break;
+ }
+ }
+ DBGBH(("%s bh_handler exit\n", info->device_name));
+}
+
+static void bh_transmit(struct slgt_info *info)
+{
+ struct tty_struct *tty = info->tty;
+
+ DBGBH(("%s bh_transmit\n", info->device_name));
+ if (tty) {
+ tty_wakeup(tty);
+ wake_up_interruptible(&tty->write_wait);
+ }
+}
+
+static void dsr_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_DSR);
+ return;
+ }
+ info->icount.dsr++;
+ if (info->signals & SerialSignal_DSR)
+ info->input_signal_events.dsr_up++;
+ else
+ info->input_signal_events.dsr_down++;
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+}
+
+static void cts_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_CTS);
+ return;
+ }
+ info->icount.cts++;
+ if (info->signals & SerialSignal_CTS)
+ info->input_signal_events.cts_up++;
+ else
+ info->input_signal_events.cts_down++;
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+
+ if (info->flags & ASYNC_CTS_FLOW) {
+ if (info->tty) {
+ if (info->tty->hw_stopped) {
+ if (info->signals & SerialSignal_CTS) {
+ info->tty->hw_stopped = 0;
+ info->pending_bh |= BH_TRANSMIT;
+ return;
+ }
+ } else {
+ if (!(info->signals & SerialSignal_CTS))
+ info->tty->hw_stopped = 1;
+ }
+ }
+ }
+}
+
+static void dcd_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_DCD);
+ return;
+ }
+ info->icount.dcd++;
+ if (info->signals & SerialSignal_DCD) {
+ info->input_signal_events.dcd_up++;
+ } else {
+ info->input_signal_events.dcd_down++;
+ }
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev);
+#endif
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+
+ if (info->flags & ASYNC_CHECK_CD) {
+ if (info->signals & SerialSignal_DCD)
+ wake_up_interruptible(&info->open_wait);
+ else {
+ if (info->tty)
+ tty_hangup(info->tty);
+ }
+ }
+}
+
+static void ri_change(struct slgt_info *info)
+{
+ get_signals(info);
+ DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
+ if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+ slgt_irq_off(info, IRQ_RI);
+ return;
+ }
+ info->icount.dcd++;
+ if (info->signals & SerialSignal_RI) {
+ info->input_signal_events.ri_up++;
+ } else {
+ info->input_signal_events.ri_down++;
+ }
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+ info->pending_bh |= BH_STATUS;
+}
+
+static void isr_serial(struct slgt_info *info)
+{
+ unsigned short status = rd_reg16(info, SSR);
+
+ DBGISR(("%s isr_serial status=%04X\n", info->device_name, status));
+
+ wr_reg16(info, SSR, status); /* clear pending */
+
+ info->irq_occurred = 1;
+
+ if (info->params.mode == MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXIDLE) {
+ if (info->tx_count)
+ isr_txeom(info, status);
+ }
+ if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
+ info->icount.brk++;
+ /* process break detection if tty control allows */
+ if (info->tty) {
+ if (!(status & info->ignore_status_mask)) {
+ if (info->read_status_mask & MASK_BREAK) {
+ tty_insert_flip_char(info->tty, 0, TTY_BREAK);
+ if (info->flags & ASYNC_SAK)
+ do_SAK(info->tty);
+ }
+ }
+ }
+ }
+ } else {
+ if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
+ isr_txeom(info, status);
+
+ if (status & IRQ_RXIDLE) {
+ if (status & RXIDLE)
+ info->icount.rxidle++;
+ else
+ info->icount.exithunt++;
+ wake_up_interruptible(&info->event_wait_q);
+ }
+
+ if (status & IRQ_RXOVER)
+ rx_start(info);
+ }
+
+ if (status & IRQ_DSR)
+ dsr_change(info);
+ if (status & IRQ_CTS)
+ cts_change(info);
+ if (status & IRQ_DCD)
+ dcd_change(info);
+ if (status & IRQ_RI)
+ ri_change(info);
+}
+
+static void isr_rdma(struct slgt_info *info)
+{
+ unsigned int status = rd_reg32(info, RDCSR);
+
+ DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status));
+
+ /* RDCSR (rx DMA control/status)
+ *
+ * 31..07 reserved
+ * 06 save status byte to DMA buffer
+ * 05 error
+ * 04 eol (end of list)
+ * 03 eob (end of buffer)
+ * 02 IRQ enable
+ * 01 reset
+ * 00 enable
+ */
+ wr_reg32(info, RDCSR, status); /* clear pending */
+
+ if (status & (BIT5 + BIT4)) {
+ DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
+ info->rx_restart = 1;
+ }
+ info->pending_bh |= BH_RECEIVE;
+}
+
+static void isr_tdma(struct slgt_info *info)
+{
+ unsigned int status = rd_reg32(info, TDCSR);
+
+ DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status));
+
+ /* TDCSR (tx DMA control/status)
+ *
+ * 31..06 reserved
+ * 05 error
+ * 04 eol (end of list)
+ * 03 eob (end of buffer)
+ * 02 IRQ enable
+ * 01 reset
+ * 00 enable
+ */
+ wr_reg32(info, TDCSR, status); /* clear pending */
+
+ if (status & (BIT5 + BIT4 + BIT3)) {
+ // another transmit buffer has completed
+ // run bottom half to get more send data from user
+ info->pending_bh |= BH_TRANSMIT;
+ }
+}
+
+static void isr_txeom(struct slgt_info *info, unsigned short status)
+{
+ DBGISR(("%s txeom status=%04x\n", info->device_name, status));
+
+ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+ tdma_reset(info);
+ reset_tbufs(info);
+ if (status & IRQ_TXUNDER) {
+ unsigned short val = rd_reg16(info, TCR);
+ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, TCR, val); /* clear reset bit */
+ }
+
+ if (info->tx_active) {
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ if (status & IRQ_TXUNDER)
+ info->icount.txunder++;
+ else if (status & IRQ_TXIDLE)
+ info->icount.txok++;
+ }
+
+ info->tx_active = 0;
+ info->tx_count = 0;
+
+ del_timer(&info->tx_timer);
+
+ if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
+ info->signals &= ~SerialSignal_RTS;
+ info->drop_rts_on_tx_done = 0;
+ set_signals(info);
+ }
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_tx_done(info);
+ else
+#endif
+ {
+ if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
+ tx_stop(info);
+ return;
+ }
+ info->pending_bh |= BH_TRANSMIT;
+ }
+ }
+}
+
+/* interrupt service routine
+ *
+ * irq interrupt number
+ * dev_id device ID supplied during interrupt registration
+ * regs interrupted processor context
+ */
+static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct slgt_info *info;
+ unsigned int gsr;
+ unsigned int i;
+
+ DBGISR(("slgt_interrupt irq=%d entry\n", irq));
+
+ info = dev_id;
+ if (!info)
+ return IRQ_NONE;
+
+ spin_lock(&info->lock);
+
+ while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
+ DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
+ info->irq_occurred = 1;
+ for(i=0; i < info->port_count ; i++) {
+ if (info->port_array[i] == NULL)
+ continue;
+ if (gsr & (BIT8 << i))
+ isr_serial(info->port_array[i]);
+ if (gsr & (BIT16 << (i*2)))
+ isr_rdma(info->port_array[i]);
+ if (gsr & (BIT17 << (i*2)))
+ isr_tdma(info->port_array[i]);
+ }
+ }
+
+ for(i=0; i < info->port_count ; i++) {
+ struct slgt_info *port = info->port_array[i];
+
+ if (port && (port->count || port->netcount) &&
+ port->pending_bh && !port->bh_running &&
+ !port->bh_requested) {
+ DBGISR(("%s bh queued\n", port->device_name));
+ schedule_work(&port->task);
+ port->bh_requested = 1;
+ }
+ }
+
+ spin_unlock(&info->lock);
+
+ DBGISR(("slgt_interrupt irq=%d exit\n", irq));
+ return IRQ_HANDLED;
+}
+
+static int startup(struct slgt_info *info)
+{
+ DBGINFO(("%s startup\n", info->device_name));
+
+ if (info->flags & ASYNC_INITIALIZED)
+ return 0;
+
+ if (!info->tx_buf) {
+ info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ if (!info->tx_buf) {
+ DBGERR(("%s can't allocate tx buffer\n", info->device_name));
+ return -ENOMEM;
+ }
+ }
+
+ info->pending_bh = 0;
+
+ memset(&info->icount, 0, sizeof(info->icount));
+
+ /* program hardware for current parameters */
+ change_params(info);
+
+ if (info->tty)
+ clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags |= ASYNC_INITIALIZED;
+
+ return 0;
+}
+
+/*
+ * called by close() and hangup() to shutdown hardware
+ */
+static void shutdown(struct slgt_info *info)
+{
+ unsigned long flags;
+
+ if (!(info->flags & ASYNC_INITIALIZED))
+ return;
+
+ DBGINFO(("%s shutdown\n", info->device_name));
+
+ /* clear status wait queue because status changes */
+ /* can't happen after shutting down the hardware */
+ wake_up_interruptible(&info->status_event_wait_q);
+ wake_up_interruptible(&info->event_wait_q);
+
+ del_timer_sync(&info->tx_timer);
+ del_timer_sync(&info->rx_timer);
+
+ kfree(info->tx_buf);
+ info->tx_buf = NULL;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ tx_stop(info);
+ rx_stop(info);
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+
+ if (!info->tty || info->tty->termios->c_cflag & HUPCL) {
+ info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+ set_signals(info);
+ }
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if (info->tty)
+ set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+ info->flags &= ~ASYNC_INITIALIZED;
+}
+
+static void program_hw(struct slgt_info *info)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ rx_stop(info);
+ tx_stop(info);
+
+ if (info->params.mode == MGSL_MODE_HDLC ||
+ info->params.mode == MGSL_MODE_RAW ||
+ info->netcount)
+ hdlc_mode(info);
+ else
+ async_mode(info);
+
+ set_signals(info);
+
+ info->dcd_chkcount = 0;
+ info->cts_chkcount = 0;
+ info->ri_chkcount = 0;
+ info->dsr_chkcount = 0;
+
+ slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR);
+ get_signals(info);
+
+ if (info->netcount ||
+ (info->tty && info->tty->termios->c_cflag & CREAD))
+ rx_start(info);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * reconfigure adapter based on new parameters
+ */
+static void change_params(struct slgt_info *info)
+{
+ unsigned cflag;
+ int bits_per_char;
+
+ if (!info->tty || !info->tty->termios)
+ return;
+ DBGINFO(("%s change_params\n", info->device_name));
+
+ cflag = info->tty->termios->c_cflag;
+
+ /* if B0 rate (hangup) specified then negate DTR and RTS */
+ /* otherwise assert DTR and RTS */
+ if (cflag & CBAUD)
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ else
+ info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+
+ /* byte size and parity */
+
+ switch (cflag & CSIZE) {
+ case CS5: info->params.data_bits = 5; break;
+ case CS6: info->params.data_bits = 6; break;
+ case CS7: info->params.data_bits = 7; break;
+ case CS8: info->params.data_bits = 8; break;
+ default: info->params.data_bits = 7; break;
+ }
+
+ info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1;
+
+ if (cflag & PARENB)
+ info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN;
+ else
+ info->params.parity = ASYNC_PARITY_NONE;
+
+ /* calculate number of jiffies to transmit a full
+ * FIFO (32 bytes) at specified data rate
+ */
+ bits_per_char = info->params.data_bits +
+ info->params.stop_bits + 1;
+
+ info->params.data_rate = tty_get_baud_rate(info->tty);
+
+ if (info->params.data_rate) {
+ info->timeout = (32*HZ*bits_per_char) /
+ info->params.data_rate;
+ }
+ info->timeout += HZ/50; /* Add .02 seconds of slop */
+
+ if (cflag & CRTSCTS)
+ info->flags |= ASYNC_CTS_FLOW;
+ else
+ info->flags &= ~ASYNC_CTS_FLOW;
+
+ if (cflag & CLOCAL)
+ info->flags &= ~ASYNC_CHECK_CD;
+ else
+ info->flags |= ASYNC_CHECK_CD;
+
+ /* process tty input control flags */
+
+ info->read_status_mask = IRQ_RXOVER;
+ if (I_INPCK(info->tty))
+ info->read_status_mask |= MASK_PARITY | MASK_FRAMING;
+ if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+ info->read_status_mask |= MASK_BREAK;
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING;
+ if (I_IGNBRK(info->tty)) {
+ info->ignore_status_mask |= MASK_BREAK;
+ /* If ignoring parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (I_IGNPAR(info->tty))
+ info->ignore_status_mask |= MASK_OVERRUN;
+ }
+
+ program_hw(info);
+}
+
+static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount)
+{
+ DBGINFO(("%s get_stats\n", info->device_name));
+ if (!user_icount) {
+ memset(&info->icount, 0, sizeof(info->icount));
+ } else {
+ if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params)
+{
+ DBGINFO(("%s get_params\n", info->device_name));
+ if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS)))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params)
+{
+ unsigned long flags;
+ MGSL_PARAMS tmp_params;
+
+ DBGINFO(("%s set_params\n", info->device_name));
+ if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS)))
+ return -EFAULT;
+
+ spin_lock_irqsave(&info->lock, flags);
+ memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS));
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ change_params(info);
+
+ return 0;
+}
+
+static int get_txidle(struct slgt_info *info, int __user *idle_mode)
+{
+ DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode));
+ if (put_user(info->idle_mode, idle_mode))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_txidle(struct slgt_info *info, int idle_mode)
+{
+ unsigned long flags;
+ DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
+ spin_lock_irqsave(&info->lock,flags);
+ info->idle_mode = idle_mode;
+ tx_set_idle(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int tx_enable(struct slgt_info *info, int enable)
+{
+ unsigned long flags;
+ DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable));
+ spin_lock_irqsave(&info->lock,flags);
+ if (enable) {
+ if (!info->tx_enabled)
+ tx_start(info);
+ } else {
+ if (info->tx_enabled)
+ tx_stop(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * abort transmit HDLC frame
+ */
+static int tx_abort(struct slgt_info *info)
+{
+ unsigned long flags;
+ DBGINFO(("%s tx_abort\n", info->device_name));
+ spin_lock_irqsave(&info->lock,flags);
+ tdma_reset(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int rx_enable(struct slgt_info *info, int enable)
+{
+ unsigned long flags;
+ DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable));
+ spin_lock_irqsave(&info->lock,flags);
+ if (enable) {
+ if (!info->rx_enabled)
+ rx_start(info);
+ } else {
+ if (info->rx_enabled)
+ rx_stop(info);
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * wait for specified event to occur
+ */
+static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr)
+{
+ unsigned long flags;
+ int s;
+ int rc=0;
+ struct mgsl_icount cprev, cnow;
+ int events;
+ int mask;
+ struct _input_signal_events oldsigs, newsigs;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (get_user(mask, mask_ptr))
+ return -EFAULT;
+
+ DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask));
+
+ spin_lock_irqsave(&info->lock,flags);
+
+ /* return immediately if state matches requested events */
+ get_signals(info);
+ s = info->signals;
+
+ events = mask &
+ ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+ ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+ ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+ if (events) {
+ spin_unlock_irqrestore(&info->lock,flags);
+ goto exit;
+ }
+
+ /* save current irq counts */
+ cprev = info->icount;
+ oldsigs = info->input_signal_events;
+
+ /* enable hunt and idle irqs if needed */
+ if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
+ unsigned short val = rd_reg16(info, SCR);
+ if (!(val & IRQ_RXIDLE))
+ wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE));
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&info->event_wait_q, &wait);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ for(;;) {
+ schedule();
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ break;
+ }
+
+ /* get current irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ newsigs = info->input_signal_events;
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ /* if no change, wait aborted for some reason */
+ if (newsigs.dsr_up == oldsigs.dsr_up &&
+ newsigs.dsr_down == oldsigs.dsr_down &&
+ newsigs.dcd_up == oldsigs.dcd_up &&
+ newsigs.dcd_down == oldsigs.dcd_down &&
+ newsigs.cts_up == oldsigs.cts_up &&
+ newsigs.cts_down == oldsigs.cts_down &&
+ newsigs.ri_up == oldsigs.ri_up &&
+ newsigs.ri_down == oldsigs.ri_down &&
+ cnow.exithunt == cprev.exithunt &&
+ cnow.rxidle == cprev.rxidle) {
+ rc = -EIO;
+ break;
+ }
+
+ events = mask &
+ ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) +
+ (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+ (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) +
+ (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+ (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) +
+ (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+ (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) +
+ (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) +
+ (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) +
+ (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) );
+ if (events)
+ break;
+
+ cprev = cnow;
+ oldsigs = newsigs;
+ }
+
+ remove_wait_queue(&info->event_wait_q, &wait);
+ set_current_state(TASK_RUNNING);
+
+
+ if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+ spin_lock_irqsave(&info->lock,flags);
+ if (!waitqueue_active(&info->event_wait_q)) {
+ /* disable enable exit hunt mode/idle rcvd IRQs */
+ wr_reg16(info, SCR,
+ (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE));
+ }
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+exit:
+ if (rc == 0)
+ rc = put_user(events, mask_ptr);
+ return rc;
+}
+
+static int get_interface(struct slgt_info *info, int __user *if_mode)
+{
+ DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode));
+ if (put_user(info->if_mode, if_mode))
+ return -EFAULT;
+ return 0;
+}
+
+static int set_interface(struct slgt_info *info, int if_mode)
+{
+ unsigned long flags;
+ unsigned short val;
+
+ DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
+ spin_lock_irqsave(&info->lock,flags);
+ info->if_mode = if_mode;
+
+ msc_set_vcr(info);
+
+ /* TCR (tx control) 07 1=RTS driver control */
+ val = rd_reg16(info, TCR);
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+ else
+ val &= ~BIT7;
+ wr_reg16(info, TCR, val);
+
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+static int modem_input_wait(struct slgt_info *info,int arg)
+{
+ unsigned long flags;
+ int rc;
+ struct mgsl_icount cprev, cnow;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* save current irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cprev = info->icount;
+ add_wait_queue(&info->status_event_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ for(;;) {
+ schedule();
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ break;
+ }
+
+ /* get new irq counts */
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ /* if no change, wait aborted for some reason */
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+ rc = -EIO;
+ break;
+ }
+
+ /* check for change in caller specified modem input */
+ if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
+ (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
+ (arg & TIOCM_CD && cnow.dcd != cprev.dcd) ||
+ (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
+ rc = 0;
+ break;
+ }
+
+ cprev = cnow;
+ }
+ remove_wait_queue(&info->status_event_wait_q, &wait);
+ set_current_state(TASK_RUNNING);
+ return rc;
+}
+
+/*
+ * return state of serial control and status signals
+ */
+static int tiocmget(struct tty_struct *tty, struct file *file)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
+ ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
+ ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
+ ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) +
+ ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
+ ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0);
+
+ DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result));
+ return result;
+}
+
+/*
+ * set modem control signals (DTR/RTS)
+ *
+ * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit
+ * TIOCMSET = set/clear signal values
+ * value bit mask for command
+ */
+static int tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct slgt_info *info = tty->driver_data;
+ unsigned long flags;
+
+ DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear));
+
+ if (set & TIOCM_RTS)
+ info->signals |= SerialSignal_RTS;
+ if (set & TIOCM_DTR)
+ info->signals |= SerialSignal_DTR;
+ if (clear & TIOCM_RTS)
+ info->signals &= ~SerialSignal_RTS;
+ if (clear & TIOCM_DTR)
+ info->signals &= ~SerialSignal_DTR;
+
+ spin_lock_irqsave(&info->lock,flags);
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return 0;
+}
+
+/*
+ * block current process until the device is ready to open
+ */
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+ struct slgt_info *info)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int retval;
+ int do_clocal = 0, extra_count = 0;
+ unsigned long flags;
+
+ DBGINFO(("%s block_til_ready\n", tty->driver->name));
+
+ if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+ /* nonblock mode is set or port is not enabled */
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (tty->termios->c_cflag & CLOCAL)
+ do_clocal = 1;
+
+ /* Wait for carrier detect and the line to become
+ * free (i.e., not in use by the callout). While we are in
+ * this loop, info->count is dropped by one, so that
+ * close() knows when to free things. We restore it upon
+ * exit, either normal or abnormal.
+ */
+
+ retval = 0;
+ add_wait_queue(&info->open_wait, &wait);
+
+ spin_lock_irqsave(&info->lock, flags);
+ if (!tty_hung_up_p(filp)) {
+ extra_count = 1;
+ info->count--;
+ }
+ spin_unlock_irqrestore(&info->lock, flags);
+ info->blocked_open++;
+
+ while (1) {
+ if ((tty->termios->c_cflag & CBAUD)) {
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
+ retval = (info->flags & ASYNC_HUP_NOTIFY) ?
+ -EAGAIN : -ERESTARTSYS;
+ break;
+ }
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ if (!(info->flags & ASYNC_CLOSING) &&
+ (do_clocal || (info->signals & SerialSignal_DCD)) ) {
+ break;
+ }
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+
+ DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
+ schedule();
+ }
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&info->open_wait, &wait);
+
+ if (extra_count)
+ info->count++;
+ info->blocked_open--;
+
+ if (!retval)
+ info->flags |= ASYNC_NORMAL_ACTIVE;
+
+ DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
+ return retval;
+}
+
+static int alloc_tmp_rbuf(struct slgt_info *info)
+{
+ info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ if (info->tmp_rbuf == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static void free_tmp_rbuf(struct slgt_info *info)
+{
+ kfree(info->tmp_rbuf);
+ info->tmp_rbuf = NULL;
+}
+
+/*
+ * allocate DMA descriptor lists.
+ */
+static int alloc_desc(struct slgt_info *info)
+{
+ unsigned int i;
+ unsigned int pbufs;
+
+ /* allocate memory to hold descriptor lists */
+ info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr);
+ if (info->bufs == NULL)
+ return -ENOMEM;
+
+ memset(info->bufs, 0, DESC_LIST_SIZE);
+
+ info->rbufs = (struct slgt_desc*)info->bufs;
+ info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count;
+
+ pbufs = (unsigned int)info->bufs_dma_addr;
+
+ /*
+ * Build circular lists of descriptors
+ */
+
+ for (i=0; i < info->rbuf_count; i++) {
+ /* physical address of this descriptor */
+ info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc));
+
+ /* physical address of next descriptor */
+ if (i == info->rbuf_count - 1)
+ info->rbufs[i].next = cpu_to_le32(pbufs);
+ else
+ info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc)));
+ set_desc_count(info->rbufs[i], DMABUFSIZE);
+ }
+
+ for (i=0; i < info->tbuf_count; i++) {
+ /* physical address of this descriptor */
+ info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc));
+
+ /* physical address of next descriptor */
+ if (i == info->tbuf_count - 1)
+ info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc));
+ else
+ info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc)));
+ }
+
+ return 0;
+}
+
+static void free_desc(struct slgt_info *info)
+{
+ if (info->bufs != NULL) {
+ pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr);
+ info->bufs = NULL;
+ info->rbufs = NULL;
+ info->tbufs = NULL;
+ }
+}
+
+static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+ int i;
+ for (i=0; i < count; i++) {
+ if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL)
+ return -ENOMEM;
+ bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr);
+ }
+ return 0;
+}
+
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+ int i;
+ for (i=0; i < count; i++) {
+ if (bufs[i].buf == NULL)
+ continue;
+ pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr);
+ bufs[i].buf = NULL;
+ }
+}
+
+static int alloc_dma_bufs(struct slgt_info *info)
+{
+ info->rbuf_count = 32;
+ info->tbuf_count = 32;
+
+ if (alloc_desc(info) < 0 ||
+ alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 ||
+ alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 ||
+ alloc_tmp_rbuf(info) < 0) {
+ DBGERR(("%s DMA buffer alloc fail\n", info->device_name));
+ return -ENOMEM;
+ }
+ reset_rbufs(info);
+ return 0;
+}
+
+static void free_dma_bufs(struct slgt_info *info)
+{
+ if (info->bufs) {
+ free_bufs(info, info->rbufs, info->rbuf_count);
+ free_bufs(info, info->tbufs, info->tbuf_count);
+ free_desc(info);
+ }
+ free_tmp_rbuf(info);
+}
+
+static int claim_resources(struct slgt_info *info)
+{
+ if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) {
+ DBGERR(("%s reg addr conflict, addr=%08X\n",
+ info->device_name, info->phys_reg_addr));
+ info->init_error = DiagStatus_AddressConflict;
+ goto errout;
+ }
+ else
+ info->reg_addr_requested = 1;
+
+ info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE);
+ if (!info->reg_addr) {
+ DBGERR(("%s cant map device registers, addr=%08X\n",
+ info->device_name, info->phys_reg_addr));
+ info->init_error = DiagStatus_CantAssignPciResources;
+ goto errout;
+ }
+ return 0;
+
+errout:
+ release_resources(info);
+ return -ENODEV;
+}
+
+static void release_resources(struct slgt_info *info)
+{
+ if (info->irq_requested) {
+ free_irq(info->irq_level, info);
+ info->irq_requested = 0;
+ }
+
+ if (info->reg_addr_requested) {
+ release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
+ info->reg_addr_requested = 0;
+ }
+
+ if (info->reg_addr) {
+ iounmap(info->reg_addr);
+ info->reg_addr = NULL;
+ }
+}
+
+/* Add the specified device instance data structure to the
+ * global linked list of devices and increment the device count.
+ */
+static void add_device(struct slgt_info *info)
+{
+ char *devstr;
+
+ info->next_device = NULL;
+ info->line = slgt_device_count;
+ sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line);
+
+ if (info->line < MAX_DEVICES) {
+ if (maxframe[info->line])
+ info->max_frame_size = maxframe[info->line];
+ info->dosyncppp = dosyncppp[info->line];
+ }
+
+ slgt_device_count++;
+
+ if (!slgt_device_list)
+ slgt_device_list = info;
+ else {
+ struct slgt_info *current_dev = slgt_device_list;
+ while(current_dev->next_device)
+ current_dev = current_dev->next_device;
+ current_dev->next_device = info;
+ }
+
+ if (info->max_frame_size < 4096)
+ info->max_frame_size = 4096;
+ else if (info->max_frame_size > 65535)
+ info->max_frame_size = 65535;
+
+ switch(info->pdev->device) {
+ case SYNCLINK_GT_DEVICE_ID:
+ devstr = "GT";
+ break;
+ case SYNCLINK_GT4_DEVICE_ID:
+ devstr = "GT4";
+ break;
+ case SYNCLINK_AC_DEVICE_ID:
+ devstr = "AC";
+ info->params.mode = MGSL_MODE_ASYNC;
+ break;
+ default:
+ devstr = "(unknown model)";
+ }
+ printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n",
+ devstr, info->device_name, info->phys_reg_addr,
+ info->irq_level, info->max_frame_size);
+
+#ifdef CONFIG_HDLC
+ hdlcdev_init(info);
+#endif
+}
+
+/*
+ * allocate device instance structure, return NULL on failure
+ */
+static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+{
+ struct slgt_info *info;
+
+ info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL);
+
+ if (!info) {
+ DBGERR(("%s device alloc failed adapter=%d port=%d\n",
+ driver_name, adapter_num, port_num));
+ } else {
+ memset(info, 0, sizeof(struct slgt_info));
+ info->magic = MGSL_MAGIC;
+ INIT_WORK(&info->task, bh_handler, info);
+ info->max_frame_size = 4096;
+ info->raw_rx_size = DMABUFSIZE;
+ info->close_delay = 5*HZ/10;
+ info->closing_wait = 30*HZ;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->status_event_wait_q);
+ init_waitqueue_head(&info->event_wait_q);
+ spin_lock_init(&info->netlock);
+ memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+ info->idle_mode = HDLC_TXIDLE_FLAGS;
+ info->adapter_num = adapter_num;
+ info->port_num = port_num;
+
+ init_timer(&info->tx_timer);
+ info->tx_timer.data = (unsigned long)info;
+ info->tx_timer.function = tx_timeout;
+
+ init_timer(&info->rx_timer);
+ info->rx_timer.data = (unsigned long)info;
+ info->rx_timer.function = rx_timeout;
+
+ /* Copy configuration info to device instance data */
+ info->pdev = pdev;
+ info->irq_level = pdev->irq;
+ info->phys_reg_addr = pci_resource_start(pdev,0);
+
+ info->bus_type = MGSL_BUS_TYPE_PCI;
+ info->irq_flags = SA_SHIRQ;
+
+ info->init_error = -1; /* assume error, set to 0 on successful init */
+ }
+
+ return info;
+}
+
+static void device_init(int adapter_num, struct pci_dev *pdev)
+{
+ struct slgt_info *port_array[SLGT_MAX_PORTS];
+ int i;
+ int port_count = 1;
+
+ if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+ port_count = 4;
+
+ /* allocate device instances for all ports */
+ for (i=0; i < port_count; ++i) {
+ port_array[i] = alloc_dev(adapter_num, i, pdev);
+ if (port_array[i] == NULL) {
+ for (--i; i >= 0; --i)
+ kfree(port_array[i]);
+ return;
+ }
+ }
+
+ /* give copy of port_array to all ports and add to device list */
+ for (i=0; i < port_count; ++i) {
+ memcpy(port_array[i]->port_array, port_array, sizeof(port_array));
+ add_device(port_array[i]);
+ port_array[i]->port_count = port_count;
+ spin_lock_init(&port_array[i]->lock);
+ }
+
+ /* Allocate and claim adapter resources */
+ if (!claim_resources(port_array[0])) {
+
+ alloc_dma_bufs(port_array[0]);
+
+ /* copy resource information from first port to others */
+ for (i = 1; i < port_count; ++i) {
+ port_array[i]->lock = port_array[0]->lock;
+ port_array[i]->irq_level = port_array[0]->irq_level;
+ port_array[i]->reg_addr = port_array[0]->reg_addr;
+ alloc_dma_bufs(port_array[i]);
+ }
+
+ if (request_irq(port_array[0]->irq_level,
+ slgt_interrupt,
+ port_array[0]->irq_flags,
+ port_array[0]->device_name,
+ port_array[0]) < 0) {
+ DBGERR(("%s request_irq failed IRQ=%d\n",
+ port_array[0]->device_name,
+ port_array[0]->irq_level));
+ } else {
+ port_array[0]->irq_requested = 1;
+ adapter_test(port_array[0]);
+ for (i=1 ; i < port_count ; i++)
+ port_array[i]->init_error = port_array[0]->init_error;
+ }
+ }
+}
+
+static int __devinit init_one(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ if (pci_enable_device(dev)) {
+ printk("error enabling pci device %p\n", dev);
+ return -EIO;
+ }
+ pci_set_master(dev);
+ device_init(slgt_device_count, dev);
+ return 0;
+}
+
+static void __devexit remove_one(struct pci_dev *dev)
+{
+}
+
+static struct tty_operations ops = {
+ .open = open,
+ .close = close,
+ .write = write,
+ .put_char = put_char,
+ .flush_chars = flush_chars,
+ .write_room = write_room,
+ .chars_in_buffer = chars_in_buffer,
+ .flush_buffer = flush_buffer,
+ .ioctl = ioctl,
+ .throttle = throttle,
+ .unthrottle = unthrottle,
+ .send_xchar = send_xchar,
+ .break_ctl = set_break,
+ .wait_until_sent = wait_until_sent,
+ .read_proc = read_proc,
+ .set_termios = set_termios,
+ .stop = tx_hold,
+ .start = tx_release,
+ .hangup = hangup,
+ .tiocmget = tiocmget,
+ .tiocmset = tiocmset,
+};
+
+static void slgt_cleanup(void)
+{
+ int rc;
+ struct slgt_info *info;
+ struct slgt_info *tmp;
+
+ printk("unload %s %s\n", driver_name, driver_version);
+
+ if (serial_driver) {
+ if ((rc = tty_unregister_driver(serial_driver)))
+ DBGERR(("tty_unregister_driver error=%d\n", rc));
+ put_tty_driver(serial_driver);
+ }
+
+ /* reset devices */
+ info = slgt_device_list;
+ while(info) {
+ reset_port(info);
+ info = info->next_device;
+ }
+
+ /* release devices */
+ info = slgt_device_list;
+ while(info) {
+#ifdef CONFIG_HDLC
+ hdlcdev_exit(info);
+#endif
+ free_dma_bufs(info);
+ free_tmp_rbuf(info);
+ if (info->port_num == 0)
+ release_resources(info);
+ tmp = info;
+ info = info->next_device;
+ kfree(tmp);
+ }
+
+ if (pci_registered)
+ pci_unregister_driver(&pci_driver);
+}
+
+/*
+ * Driver initialization entry point.
+ */
+static int __init slgt_init(void)
+{
+ int rc;
+
+ printk("%s %s\n", driver_name, driver_version);
+
+ slgt_device_count = 0;
+ if ((rc = pci_register_driver(&pci_driver)) < 0) {
+ printk("%s pci_register_driver error=%d\n", driver_name, rc);
+ return rc;
+ }
+ pci_registered = 1;
+
+ if (!slgt_device_list) {
+ printk("%s no devices found\n",driver_name);
+ return -ENODEV;
+ }
+
+ serial_driver = alloc_tty_driver(MAX_DEVICES);
+ if (!serial_driver) {
+ rc = -ENOMEM;
+ goto error;
+ }
+
+ /* Initialize the tty_driver structure */
+
+ serial_driver->owner = THIS_MODULE;
+ serial_driver->driver_name = tty_driver_name;
+ serial_driver->name = tty_dev_prefix;
+ serial_driver->major = ttymajor;
+ serial_driver->minor_start = 64;
+ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ serial_driver->init_termios = tty_std_termios;
+ serial_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(serial_driver, &ops);
+ if ((rc = tty_register_driver(serial_driver)) < 0) {
+ DBGERR(("%s can't register serial driver\n", driver_name));
+ put_tty_driver(serial_driver);
+ serial_driver = NULL;
+ goto error;
+ }
+
+ printk("%s %s, tty major#%d\n",
+ driver_name, driver_version,
+ serial_driver->major);
+
+ return 0;
+
+error:
+ slgt_cleanup();
+ return rc;
+}
+
+static void __exit slgt_exit(void)
+{
+ slgt_cleanup();
+}
+
+module_init(slgt_init);
+module_exit(slgt_exit);
+
+/*
+ * register access routines
+ */
+
+#define CALC_REGADDR() \
+ unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
+ if (addr >= 0x80) \
+ reg_addr += (info->port_num) * 32;
+
+static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readb((void __iomem *)reg_addr);
+}
+
+static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value)
+{
+ CALC_REGADDR();
+ writeb(value, (void __iomem *)reg_addr);
+}
+
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readw((void __iomem *)reg_addr);
+}
+
+static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value)
+{
+ CALC_REGADDR();
+ writew(value, (void __iomem *)reg_addr);
+}
+
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr)
+{
+ CALC_REGADDR();
+ return readl((void __iomem *)reg_addr);
+}
+
+static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value)
+{
+ CALC_REGADDR();
+ writel(value, (void __iomem *)reg_addr);
+}
+
+static void rdma_reset(struct slgt_info *info)
+{
+ unsigned int i;
+
+ /* set reset bit */
+ wr_reg32(info, RDCSR, BIT1);
+
+ /* wait for enable bit cleared */
+ for(i=0 ; i < 1000 ; i++)
+ if (!(rd_reg32(info, RDCSR) & BIT0))
+ break;
+}
+
+static void tdma_reset(struct slgt_info *info)
+{
+ unsigned int i;
+
+ /* set reset bit */
+ wr_reg32(info, TDCSR, BIT1);
+
+ /* wait for enable bit cleared */
+ for(i=0 ; i < 1000 ; i++)
+ if (!(rd_reg32(info, TDCSR) & BIT0))
+ break;
+}
+
+/*
+ * enable internal loopback
+ * TxCLK and RxCLK are generated from BRG
+ * and TxD is looped back to RxD internally.
+ */
+static void enable_loopback(struct slgt_info *info)
+{
+ /* SCR (serial control) BIT2=looopback enable */
+ wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2));
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ /* CCR (clock control)
+ * 07..05 tx clock source (010 = BRG)
+ * 04..02 rx clock source (010 = BRG)
+ * 01 auxclk enable (0 = disable)
+ * 00 BRG enable (1 = enable)
+ *
+ * 0100 1001
+ */
+ wr_reg8(info, CCR, 0x49);
+
+ /* set speed if available, otherwise use default */
+ if (info->params.clock_speed)
+ set_rate(info, info->params.clock_speed);
+ else
+ set_rate(info, 3686400);
+ }
+}
+
+/*
+ * set baud rate generator to specified rate
+ */
+static void set_rate(struct slgt_info *info, u32 rate)
+{
+ unsigned int div;
+ static unsigned int osc = 14745600;
+
+ /* div = osc/rate - 1
+ *
+ * Round div up if osc/rate is not integer to
+ * force to next slowest rate.
+ */
+
+ if (rate) {
+ div = osc/rate;
+ if (!(osc % rate) && div)
+ div--;
+ wr_reg16(info, BDR, (unsigned short)div);
+ }
+}
+
+static void rx_stop(struct slgt_info *info)
+{
+ unsigned short val;
+
+ /* disable and reset receiver */
+ val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, RCR, val); /* clear reset bit */
+
+ slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE);
+
+ /* clear pending rx interrupts */
+ wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER);
+
+ rdma_reset(info);
+
+ info->rx_enabled = 0;
+ info->rx_restart = 0;
+}
+
+static void rx_start(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA);
+
+ /* clear pending rx overrun IRQ */
+ wr_reg16(info, SSR, IRQ_RXOVER);
+
+ /* reset and disable receiver */
+ val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, RCR, val); /* clear reset bit */
+
+ rdma_reset(info);
+ reset_rbufs(info);
+
+ /* set 1st descriptor address */
+ wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ /* enable rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT2 + BIT0));
+ } else {
+ /* enable saving of rx status, rx DMA and DMA interrupt */
+ wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+ }
+
+ slgt_irq_on(info, IRQ_RXOVER);
+
+ /* enable receiver */
+ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
+
+ info->rx_restart = 0;
+ info->rx_enabled = 1;
+}
+
+static void tx_start(struct slgt_info *info)
+{
+ if (!info->tx_enabled) {
+ wr_reg16(info, TCR,
+ (unsigned short)(rd_reg16(info, TCR) | BIT1));
+ info->tx_enabled = TRUE;
+ }
+
+ if (info->tx_count) {
+ info->drop_rts_on_tx_done = 0;
+
+ if (info->params.mode != MGSL_MODE_ASYNC) {
+ if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
+ get_signals(info);
+ if (!(info->signals & SerialSignal_RTS)) {
+ info->signals |= SerialSignal_RTS;
+ set_signals(info);
+ info->drop_rts_on_tx_done = 1;
+ }
+ }
+
+ slgt_irq_off(info, IRQ_TXDATA);
+ slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
+ /* clear tx idle and underrun status bits */
+ wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+
+ if (!(rd_reg32(info, TDCSR) & BIT0)) {
+ /* tx DMA stopped, restart tx DMA */
+ tdma_reset(info);
+ /* set 1st descriptor address */
+ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+ if (info->params.mode == MGSL_MODE_RAW)
+ wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
+ else
+ wr_reg32(info, TDCSR, BIT0); /* DMA enable */
+ }
+
+ if (info->params.mode != MGSL_MODE_RAW) {
+ info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
+ add_timer(&info->tx_timer);
+ }
+ } else {
+ tdma_reset(info);
+ /* set 1st descriptor address */
+ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+
+ slgt_irq_off(info, IRQ_TXDATA);
+ slgt_irq_on(info, IRQ_TXIDLE);
+ /* clear tx idle status bit */
+ wr_reg16(info, SSR, IRQ_TXIDLE);
+
+ /* enable tx DMA */
+ wr_reg32(info, TDCSR, BIT0);
+ }
+
+ info->tx_active = 1;
+ }
+}
+
+static void tx_stop(struct slgt_info *info)
+{
+ unsigned short val;
+
+ del_timer(&info->tx_timer);
+
+ tdma_reset(info);
+
+ /* reset and disable transmitter */
+ val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */
+ wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+ wr_reg16(info, TCR, val); /* clear reset */
+
+ slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+
+ /* clear tx idle and underrun status bit */
+ wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+
+ reset_tbufs(info);
+
+ info->tx_enabled = 0;
+ info->tx_active = 0;
+}
+
+static void reset_port(struct slgt_info *info)
+{
+ if (!info->reg_addr)
+ return;
+
+ tx_stop(info);
+ rx_stop(info);
+
+ info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+ set_signals(info);
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+}
+
+static void reset_adapter(struct slgt_info *info)
+{
+ int i;
+ for (i=0; i < info->port_count; ++i) {
+ if (info->port_array[i])
+ reset_port(info->port_array[i]);
+ }
+}
+
+static void async_mode(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+ tx_stop(info);
+ rx_stop(info);
+
+ /* TCR (tx control)
+ *
+ * 15..13 mode, 010=async
+ * 12..10 encoding, 000=NRZ
+ * 09 parity enable
+ * 08 1=odd parity, 0=even parity
+ * 07 1=RTS driver control
+ * 06 1=break enable
+ * 05..04 character length
+ * 00=5 bits
+ * 01=6 bits
+ * 10=7 bits
+ * 11=8 bits
+ * 03 0=1 stop bit, 1=2 stop bits
+ * 02 reset
+ * 01 enable
+ * 00 auto-CTS enable
+ */
+ val = 0x4000;
+
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+
+ if (info->params.parity != ASYNC_PARITY_NONE) {
+ val |= BIT9;
+ if (info->params.parity == ASYNC_PARITY_ODD)
+ val |= BIT8;
+ }
+
+ switch (info->params.data_bits)
+ {
+ case 6: val |= BIT4; break;
+ case 7: val |= BIT5; break;
+ case 8: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.stop_bits != 1)
+ val |= BIT3;
+
+ if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+ val |= BIT0;
+
+ wr_reg16(info, TCR, val);
+
+ /* RCR (rx control)
+ *
+ * 15..13 mode, 010=async
+ * 12..10 encoding, 000=NRZ
+ * 09 parity enable
+ * 08 1=odd parity, 0=even parity
+ * 07..06 reserved, must be 0
+ * 05..04 character length
+ * 00=5 bits
+ * 01=6 bits
+ * 10=7 bits
+ * 11=8 bits
+ * 03 reserved, must be zero
+ * 02 reset
+ * 01 enable
+ * 00 auto-DCD enable
+ */
+ val = 0x4000;
+
+ if (info->params.parity != ASYNC_PARITY_NONE) {
+ val |= BIT9;
+ if (info->params.parity == ASYNC_PARITY_ODD)
+ val |= BIT8;
+ }
+
+ switch (info->params.data_bits)
+ {
+ case 6: val |= BIT4; break;
+ case 7: val |= BIT5; break;
+ case 8: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+ val |= BIT0;
+
+ wr_reg16(info, RCR, val);
+
+ /* CCR (clock control)
+ *
+ * 07..05 011 = tx clock source is BRG/16
+ * 04..02 010 = rx clock source is BRG
+ * 01 0 = auxclk disabled
+ * 00 1 = BRG enabled
+ *
+ * 0110 1001
+ */
+ wr_reg8(info, CCR, 0x69);
+
+ msc_set_vcr(info);
+
+ tx_set_idle(info);
+
+ /* SCR (serial control)
+ *
+ * 15 1=tx req on FIFO half empty
+ * 14 1=rx req on FIFO half full
+ * 13 tx data IRQ enable
+ * 12 tx idle IRQ enable
+ * 11 rx break on IRQ enable
+ * 10 rx data IRQ enable
+ * 09 rx break off IRQ enable
+ * 08 overrun IRQ enable
+ * 07 DSR IRQ enable
+ * 06 CTS IRQ enable
+ * 05 DCD IRQ enable
+ * 04 RI IRQ enable
+ * 03 reserved, must be zero
+ * 02 1=txd->rxd internal loopback enable
+ * 01 reserved, must be zero
+ * 00 1=master IRQ enable
+ */
+ val = BIT15 + BIT14 + BIT0;
+ wr_reg16(info, SCR, val);
+
+ slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER);
+
+ set_rate(info, info->params.data_rate * 16);
+
+ if (info->params.loopback)
+ enable_loopback(info);
+}
+
+static void hdlc_mode(struct slgt_info *info)
+{
+ unsigned short val;
+
+ slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+ tx_stop(info);
+ rx_stop(info);
+
+ /* TCR (tx control)
+ *
+ * 15..13 mode, 000=HDLC 001=raw sync
+ * 12..10 encoding
+ * 09 CRC enable
+ * 08 CRC32
+ * 07 1=RTS driver control
+ * 06 preamble enable
+ * 05..04 preamble length
+ * 03 share open/close flag
+ * 02 reset
+ * 01 enable
+ * 00 auto-CTS enable
+ */
+ val = 0;
+
+ if (info->params.mode == MGSL_MODE_RAW)
+ val |= BIT13;
+ if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+ val |= BIT7;
+
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_NRZB: val |= BIT10; break;
+ case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break;
+ case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break;
+ case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+ }
+
+ switch (info->params.crc_type)
+ {
+ case HDLC_CRC_16_CCITT: val |= BIT9; break;
+ case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+ }
+
+ if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
+ val |= BIT6;
+
+ switch (info->params.preamble_length)
+ {
+ case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break;
+ case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break;
+ case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+ val |= BIT0;
+
+ wr_reg16(info, TCR, val);
+
+ /* TPR (transmit preamble) */
+
+ switch (info->params.preamble)
+ {
+ case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;
+ case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break;
+ case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break;
+ case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break;
+ case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break;
+ default: val = 0x7e; break;
+ }
+ wr_reg8(info, TPR, (unsigned char)val);
+
+ /* RCR (rx control)
+ *
+ * 15..13 mode, 000=HDLC 001=raw sync
+ * 12..10 encoding
+ * 09 CRC enable
+ * 08 CRC32
+ * 07..03 reserved, must be 0
+ * 02 reset
+ * 01 enable
+ * 00 auto-DCD enable
+ */
+ val = 0;
+
+ if (info->params.mode == MGSL_MODE_RAW)
+ val |= BIT13;
+
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_NRZB: val |= BIT10; break;
+ case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break;
+ case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break;
+ case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+ }
+
+ switch (info->params.crc_type)
+ {
+ case HDLC_CRC_16_CCITT: val |= BIT9; break;
+ case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+ }
+
+ if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+ val |= BIT0;
+
+ wr_reg16(info, RCR, val);
+
+ /* CCR (clock control)
+ *
+ * 07..05 tx clock source
+ * 04..02 rx clock source
+ * 01 auxclk enable
+ * 00 BRG enable
+ */
+ val = 0;
+
+ if (info->params.flags & HDLC_FLAG_TXC_BRG)
+ {
+ // when RxC source is DPLL, BRG generates 16X DPLL
+ // reference clock, so take TxC from BRG/16 to get
+ // transmit clock at actual data rate
+ if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+ val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */
+ else
+ val |= BIT6; /* 010, txclk = BRG */
+ }
+ else if (info->params.flags & HDLC_FLAG_TXC_DPLL)
+ val |= BIT7; /* 100, txclk = DPLL Input */
+ else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN)
+ val |= BIT5; /* 001, txclk = RXC Input */
+
+ if (info->params.flags & HDLC_FLAG_RXC_BRG)
+ val |= BIT3; /* 010, rxclk = BRG */
+ else if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+ val |= BIT4; /* 100, rxclk = DPLL */
+ else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN)
+ val |= BIT2; /* 001, rxclk = TXC Input */
+
+ if (info->params.clock_speed)
+ val |= BIT1 + BIT0;
+
+ wr_reg8(info, CCR, (unsigned char)val);
+
+ if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL))
+ {
+ // program DPLL mode
+ switch(info->params.encoding)
+ {
+ case HDLC_ENCODING_BIPHASE_MARK:
+ case HDLC_ENCODING_BIPHASE_SPACE:
+ val = BIT7; break;
+ case HDLC_ENCODING_BIPHASE_LEVEL:
+ case HDLC_ENCODING_DIFF_BIPHASE_LEVEL:
+ val = BIT7 + BIT6; break;
+ default: val = BIT6; // NRZ encodings
+ }
+ wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val));
+
+ // DPLL requires a 16X reference clock from BRG
+ set_rate(info, info->params.clock_speed * 16);
+ }
+ else
+ set_rate(info, info->params.clock_speed);
+
+ tx_set_idle(info);
+
+ msc_set_vcr(info);
+
+ /* SCR (serial control)
+ *
+ * 15 1=tx req on FIFO half empty
+ * 14 1=rx req on FIFO half full
+ * 13 tx data IRQ enable
+ * 12 tx idle IRQ enable
+ * 11 underrun IRQ enable
+ * 10 rx data IRQ enable
+ * 09 rx idle IRQ enable
+ * 08 overrun IRQ enable
+ * 07 DSR IRQ enable
+ * 06 CTS IRQ enable
+ * 05 DCD IRQ enable
+ * 04 RI IRQ enable
+ * 03 reserved, must be zero
+ * 02 1=txd->rxd internal loopback enable
+ * 01 reserved, must be zero
+ * 00 1=master IRQ enable
+ */
+ wr_reg16(info, SCR, BIT15 + BIT14 + BIT0);
+
+ if (info->params.loopback)
+ enable_loopback(info);
+}
+
+/*
+ * set transmit idle mode
+ */
+static void tx_set_idle(struct slgt_info *info)
+{
+ unsigned char val = 0xff;
+
+ switch(info->idle_mode)
+ {
+ case HDLC_TXIDLE_FLAGS: val = 0x7e; break;
+ case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break;
+ case HDLC_TXIDLE_ZEROS: val = 0x00; break;
+ case HDLC_TXIDLE_ONES: val = 0xff; break;
+ case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
+ case HDLC_TXIDLE_SPACE: val = 0x00; break;
+ case HDLC_TXIDLE_MARK: val = 0xff; break;
+ }
+
+ wr_reg8(info, TIR, val);
+}
+
+/*
+ * get state of V24 status (input) signals
+ */
+static void get_signals(struct slgt_info *info)
+{
+ unsigned short status = rd_reg16(info, SSR);
+
+ /* clear all serial signals except DTR and RTS */
+ info->signals &= SerialSignal_DTR + SerialSignal_RTS;
+
+ if (status & BIT3)
+ info->signals |= SerialSignal_DSR;
+ if (status & BIT2)
+ info->signals |= SerialSignal_CTS;
+ if (status & BIT1)
+ info->signals |= SerialSignal_DCD;
+ if (status & BIT0)
+ info->signals |= SerialSignal_RI;
+}
+
+/*
+ * set V.24 Control Register based on current configuration
+ */
+static void msc_set_vcr(struct slgt_info *info)
+{
+ unsigned char val = 0;
+
+ /* VCR (V.24 control)
+ *
+ * 07..04 serial IF select
+ * 03 DTR
+ * 02 RTS
+ * 01 LL
+ * 00 RL
+ */
+
+ switch(info->if_mode & MGSL_INTERFACE_MASK)
+ {
+ case MGSL_INTERFACE_RS232:
+ val |= BIT5; /* 0010 */
+ break;
+ case MGSL_INTERFACE_V35:
+ val |= BIT7 + BIT6 + BIT5; /* 1110 */
+ break;
+ case MGSL_INTERFACE_RS422:
+ val |= BIT6; /* 0100 */
+ break;
+ }
+
+ if (info->signals & SerialSignal_DTR)
+ val |= BIT3;
+ if (info->signals & SerialSignal_RTS)
+ val |= BIT2;
+ if (info->if_mode & MGSL_INTERFACE_LL)
+ val |= BIT1;
+ if (info->if_mode & MGSL_INTERFACE_RL)
+ val |= BIT0;
+ wr_reg8(info, VCR, val);
+}
+
+/*
+ * set state of V24 control (output) signals
+ */
+static void set_signals(struct slgt_info *info)
+{
+ unsigned char val = rd_reg8(info, VCR);
+ if (info->signals & SerialSignal_DTR)
+ val |= BIT3;
+ else
+ val &= ~BIT3;
+ if (info->signals & SerialSignal_RTS)
+ val |= BIT2;
+ else
+ val &= ~BIT2;
+ wr_reg8(info, VCR, val);
+}
+
+/*
+ * free range of receive DMA buffers (i to last)
+ */
+static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last)
+{
+ int done = 0;
+
+ while(!done) {
+ /* reset current buffer for reuse */
+ info->rbufs[i].status = 0;
+ if (info->params.mode == MGSL_MODE_RAW)
+ set_desc_count(info->rbufs[i], info->raw_rx_size);
+ else
+ set_desc_count(info->rbufs[i], DMABUFSIZE);
+
+ if (i == last)
+ done = 1;
+ if (++i == info->rbuf_count)
+ i = 0;
+ }
+ info->rbuf_current = i;
+}
+
+/*
+ * mark all receive DMA buffers as free
+ */
+static void reset_rbufs(struct slgt_info *info)
+{
+ free_rbufs(info, 0, info->rbuf_count - 1);
+}
+
+/*
+ * pass receive HDLC frame to upper layer
+ *
+ * return 1 if frame available, otherwise 0
+ */
+static int rx_get_frame(struct slgt_info *info)
+{
+ unsigned int start, end;
+ unsigned short status;
+ unsigned int framesize = 0;
+ int rc = 0;
+ unsigned long flags;
+ struct tty_struct *tty = info->tty;
+ unsigned char addr_field = 0xff;
+
+check_again:
+
+ framesize = 0;
+ addr_field = 0xff;
+ start = end = info->rbuf_current;
+
+ for (;;) {
+ if (!desc_complete(info->rbufs[end]))
+ goto cleanup;
+
+ if (framesize == 0 && info->params.addr_filter != 0xff)
+ addr_field = info->rbufs[end].buf[0];
+
+ framesize += desc_count(info->rbufs[end]);
+
+ if (desc_eof(info->rbufs[end]))
+ break;
+
+ if (++end == info->rbuf_count)
+ end = 0;
+
+ if (end == info->rbuf_current) {
+ if (info->rx_enabled){
+ spin_lock_irqsave(&info->lock,flags);
+ rx_start(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ }
+ goto cleanup;
+ }
+ }
+
+ /* status
+ *
+ * 15 buffer complete
+ * 14..06 reserved
+ * 05..04 residue
+ * 02 eof (end of frame)
+ * 01 CRC error
+ * 00 abort
+ */
+ status = desc_status(info->rbufs[end]);
+
+ /* ignore CRC bit if not using CRC (bit is undefined) */
+ if (info->params.crc_type == HDLC_CRC_NONE)
+ status &= ~BIT1;
+
+ if (framesize == 0 ||
+ (addr_field != 0xff && addr_field != info->params.addr_filter)) {
+ free_rbufs(info, start, end);
+ goto check_again;
+ }
+
+ if (framesize < 2 || status & (BIT1+BIT0)) {
+ if (framesize < 2 || (status & BIT0))
+ info->icount.rxshort++;
+ else
+ info->icount.rxcrc++;
+ framesize = 0;
+
+#ifdef CONFIG_HDLC
+ {
+ struct net_device_stats *stats = hdlc_stats(info->netdev);
+ stats->rx_errors++;
+ stats->rx_frame_errors++;
+ }
+#endif
+ } else {
+ /* adjust frame size for CRC, if any */
+ if (info->params.crc_type == HDLC_CRC_16_CCITT)
+ framesize -= 2;
+ else if (info->params.crc_type == HDLC_CRC_32_CCITT)
+ framesize -= 4;
+ }
+
+ DBGBH(("%s rx frame status=%04X size=%d\n",
+ info->device_name, status, framesize));
+ DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
+
+ if (framesize) {
+ if (framesize > info->max_frame_size)
+ info->icount.rxlong++;
+ else {
+ /* copy dma buffer(s) to contiguous temp buffer */
+ int copy_count = framesize;
+ int i = start;
+ unsigned char *p = info->tmp_rbuf;
+ info->tmp_rbuf_count = framesize;
+
+ info->icount.rxok++;
+
+ while(copy_count) {
+ int partial_count = min(copy_count, DMABUFSIZE);
+ memcpy(p, info->rbufs[i].buf, partial_count);
+ p += partial_count;
+ copy_count -= partial_count;
+ if (++i == info->rbuf_count)
+ i = 0;
+ }
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_rx(info,info->tmp_rbuf, framesize);
+ else
+#endif
+ ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
+ }
+ }
+ free_rbufs(info, start, end);
+ rc = 1;
+
+cleanup:
+ return rc;
+}
+
+/*
+ * pass receive buffer (RAW synchronous mode) to tty layer
+ * return 1 if buffer available, otherwise 0
+ */
+static int rx_get_buf(struct slgt_info *info)
+{
+ unsigned int i = info->rbuf_current;
+
+ if (!desc_complete(info->rbufs[i]))
+ return 0;
+ DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx");
+ DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i])));
+ ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+ info->flag_buf, desc_count(info->rbufs[i]));
+ free_rbufs(info, i, i);
+ return 1;
+}
+
+static void reset_tbufs(struct slgt_info *info)
+{
+ unsigned int i;
+ info->tbuf_current = 0;
+ for (i=0 ; i < info->tbuf_count ; i++) {
+ info->tbufs[i].status = 0;
+ info->tbufs[i].count = 0;
+ }
+}
+
+/*
+ * return number of free transmit DMA buffers
+ */
+static unsigned int free_tbuf_count(struct slgt_info *info)
+{
+ unsigned int count = 0;
+ unsigned int i = info->tbuf_current;
+
+ do
+ {
+ if (desc_count(info->tbufs[i]))
+ break; /* buffer in use */
+ ++count;
+ if (++i == info->tbuf_count)
+ i=0;
+ } while (i != info->tbuf_current);
+
+ /* last buffer with zero count may be in use, assume it is */
+ if (count)
+ --count;
+
+ return count;
+}
+
+/*
+ * load transmit DMA buffer(s) with data
+ */
+static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
+{
+ unsigned short count;
+ unsigned int i;
+ struct slgt_desc *d;
+
+ if (size == 0)
+ return;
+
+ DBGDATA(info, buf, size, "tx");
+
+ info->tbuf_start = i = info->tbuf_current;
+
+ while (size) {
+ d = &info->tbufs[i];
+ if (++i == info->tbuf_count)
+ i = 0;
+
+ count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
+ memcpy(d->buf, buf, count);
+
+ size -= count;
+ buf += count;
+
+ if (!size && info->params.mode != MGSL_MODE_RAW)
+ set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */
+ else
+ set_desc_eof(*d, 0);
+
+ set_desc_count(*d, count);
+ }
+
+ info->tbuf_current = i;
+}
+
+static int register_test(struct slgt_info *info)
+{
+ static unsigned short patterns[] =
+ {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696};
+ static unsigned int count = sizeof(patterns)/sizeof(patterns[0]);
+ unsigned int i;
+ int rc = 0;
+
+ for (i=0 ; i < count ; i++) {
+ wr_reg16(info, TIR, patterns[i]);
+ wr_reg16(info, BDR, patterns[(i+1)%count]);
+ if ((rd_reg16(info, TIR) != patterns[i]) ||
+ (rd_reg16(info, BDR) != patterns[(i+1)%count])) {
+ rc = -ENODEV;
+ break;
+ }
+ }
+
+ info->init_error = rc ? 0 : DiagStatus_AddressFailure;
+ return rc;
+}
+
+static int irq_test(struct slgt_info *info)
+{
+ unsigned long timeout;
+ unsigned long flags;
+ struct tty_struct *oldtty = info->tty;
+ u32 speed = info->params.data_rate;
+
+ info->params.data_rate = 921600;
+ info->tty = NULL;
+
+ spin_lock_irqsave(&info->lock, flags);
+ async_mode(info);
+ slgt_irq_on(info, IRQ_TXIDLE);
+
+ /* enable transmitter */
+ wr_reg16(info, TCR,
+ (unsigned short)(rd_reg16(info, TCR) | BIT1));
+
+ /* write one byte and wait for tx idle */
+ wr_reg16(info, TDR, 0);
+
+ /* assume failure */
+ info->init_error = DiagStatus_IrqFailure;
+ info->irq_occurred = FALSE;
+
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ timeout=100;
+ while(timeout-- && !info->irq_occurred)
+ msleep_interruptible(10);
+
+ spin_lock_irqsave(&info->lock,flags);
+ reset_port(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ info->params.data_rate = speed;
+ info->tty = oldtty;
+
+ info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure;
+ return info->irq_occurred ? 0 : -ENODEV;
+}
+
+static int loopback_test_rx(struct slgt_info *info)
+{
+ unsigned char *src, *dest;
+ int count;
+
+ if (desc_complete(info->rbufs[0])) {
+ count = desc_count(info->rbufs[0]);
+ src = info->rbufs[0].buf;
+ dest = info->tmp_rbuf;
+
+ for( ; count ; count-=2, src+=2) {
+ /* src=data byte (src+1)=status byte */
+ if (!(*(src+1) & (BIT9 + BIT8))) {
+ *dest = *src;
+ dest++;
+ info->tmp_rbuf_count++;
+ }
+ }
+ DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx");
+ return 1;
+ }
+ return 0;
+}
+
+static int loopback_test(struct slgt_info *info)
+{
+#define TESTFRAMESIZE 20
+
+ unsigned long timeout;
+ u16 count = TESTFRAMESIZE;
+ unsigned char buf[TESTFRAMESIZE];
+ int rc = -ENODEV;
+ unsigned long flags;
+
+ struct tty_struct *oldtty = info->tty;
+ MGSL_PARAMS params;
+
+ memcpy(&params, &info->params, sizeof(params));
+
+ info->params.mode = MGSL_MODE_ASYNC;
+ info->params.data_rate = 921600;
+ info->params.loopback = 1;
+ info->tty = NULL;
+
+ /* build and send transmit frame */
+ for (count = 0; count < TESTFRAMESIZE; ++count)
+ buf[count] = (unsigned char)count;
+
+ info->tmp_rbuf_count = 0;
+ memset(info->tmp_rbuf, 0, TESTFRAMESIZE);
+
+ /* program hardware for HDLC and enabled receiver */
+ spin_lock_irqsave(&info->lock,flags);
+ async_mode(info);
+ rx_start(info);
+ info->tx_count = count;
+ tx_load(info, buf, count);
+ tx_start(info);
+ spin_unlock_irqrestore(&info->lock, flags);
+
+ /* wait for receive complete */
+ for (timeout = 100; timeout; --timeout) {
+ msleep_interruptible(10);
+ if (loopback_test_rx(info)) {
+ rc = 0;
+ break;
+ }
+ }
+
+ /* verify received frame length and contents */
+ if (!rc && (info->tmp_rbuf_count != count ||
+ memcmp(buf, info->tmp_rbuf, count))) {
+ rc = -ENODEV;
+ }
+
+ spin_lock_irqsave(&info->lock,flags);
+ reset_adapter(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ memcpy(&info->params, &params, sizeof(info->params));
+ info->tty = oldtty;
+
+ info->init_error = rc ? DiagStatus_DmaFailure : 0;
+ return rc;
+}
+
+static int adapter_test(struct slgt_info *info)
+{
+ DBGINFO(("testing %s\n", info->device_name));
+ if ((info->init_error = register_test(info)) < 0) {
+ printk("register test failure %s addr=%08X\n",
+ info->device_name, info->phys_reg_addr);
+ } else if ((info->init_error = irq_test(info)) < 0) {
+ printk("IRQ test failure %s IRQ=%d\n",
+ info->device_name, info->irq_level);
+ } else if ((info->init_error = loopback_test(info)) < 0) {
+ printk("loopback test failure %s\n", info->device_name);
+ }
+ return info->init_error;
+}
+
+/*
+ * transmit timeout handler
+ */
+static void tx_timeout(unsigned long context)
+{
+ struct slgt_info *info = (struct slgt_info*)context;
+ unsigned long flags;
+
+ DBGINFO(("%s tx_timeout\n", info->device_name));
+ if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
+ info->icount.txtimeout++;
+ }
+ spin_lock_irqsave(&info->lock,flags);
+ info->tx_active = 0;
+ info->tx_count = 0;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_tx_done(info);
+ else
+#endif
+ bh_transmit(info);
+}
+
+/*
+ * receive buffer polling timer
+ */
+static void rx_timeout(unsigned long context)
+{
+ struct slgt_info *info = (struct slgt_info*)context;
+ unsigned long flags;
+
+ DBGINFO(("%s rx_timeout\n", info->device_name));
+ spin_lock_irqsave(&info->lock, flags);
+ info->pending_bh |= BH_RECEIVE;
+ spin_unlock_irqrestore(&info->lock, flags);
+ bh_handler(info);
+}
+
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ee5a40be9f99..960adb256fbb 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2196,7 +2196,7 @@ void isr_rxint(SLMP_INFO * info)
if ( tty ) {
if (!(status & info->ignore_status_mask1)) {
if (info->read_status_mask1 & BRKD) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
if (info->flags & ASYNC_SAK)
do_SAK(tty);
}
@@ -2240,16 +2240,10 @@ void isr_rxrdy(SLMP_INFO * info)
while((status = read_reg(info,CST0)) & BIT0)
{
+ int flag = 0;
+ int over = 0;
DataByte = read_reg(info,TRB);
- if ( tty ) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = DataByte;
- *tty->flip.flag_buf_ptr = 0;
- }
-
icount->rx++;
if ( status & (PE + FRME + OVRN) ) {
@@ -2272,42 +2266,34 @@ void isr_rxrdy(SLMP_INFO * info)
if ( tty ) {
if (status & PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & FRME)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
if (status & OVRN) {
/* Overrun is special, since it's
* reported immediately, and doesn't
* affect the current character
*/
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ over = 1;
}
}
} /* end of if (error) */
if ( tty ) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, DataByte, flag);
+ if (over)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
}
if ( debug_level >= DEBUG_LEVEL_ISR ) {
- printk("%s(%d):%s isr_rxrdy() flip count=%d\n",
- __FILE__,__LINE__,info->device_name,
- tty ? tty->flip.count : 0);
printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
__FILE__,__LINE__,info->device_name,
icount->rx,icount->brk,icount->parity,
icount->frame,icount->overrun);
}
- if ( tty && tty->flip.count )
+ if ( tty )
tty_flip_buffer_push(tty);
}
@@ -5104,7 +5090,7 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
int register_test(SLMP_INFO *info)
{
static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
- static unsigned int count = sizeof(testval)/sizeof(unsigned char);
+ static unsigned int count = ARRAY_SIZE(testval);
unsigned int i;
int rc = TRUE;
unsigned long flags;
@@ -5422,7 +5408,7 @@ int memory_test(SLMP_INFO *info)
{
static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
- unsigned long count = sizeof(testval)/sizeof(unsigned long);
+ unsigned long count = ARRAY_SIZE(testval);
unsigned long i;
unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
unsigned long * addr = (unsigned long *)info->memory_base;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 145275ebdd7e..5765f672e853 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -153,6 +153,21 @@ static struct sysrq_key_op sysrq_mountro_op = {
/* END SYNC SYSRQ HANDLERS BLOCK */
+#ifdef CONFIG_DEBUG_MUTEXES
+
+static void
+sysrq_handle_showlocks(int key, struct pt_regs *pt_regs, struct tty_struct *tty)
+{
+ mutex_debug_show_all_locks();
+}
+
+static struct sysrq_key_op sysrq_showlocks_op = {
+ .handler = sysrq_handle_showlocks,
+ .help_msg = "show-all-locks(D)",
+ .action_msg = "Show Locks Held",
+};
+
+#endif
/* SHOW SYSRQ HANDLERS BLOCK */
@@ -294,7 +309,11 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
#else
/* c */ NULL,
#endif
+#ifdef CONFIG_DEBUG_MUTEXES
+/* d */ &sysrq_showlocks_op,
+#else
/* d */ NULL,
+#endif
/* e */ &sysrq_term_op,
/* f */ &sysrq_moom_op,
/* g */ NULL,
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index b3d411a756fe..ac2a297ce37c 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -1,7 +1,7 @@
/*
* Driver for TANBAC TB0219 base board.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/tb0219.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 12167c04fa4c..4c272189cd42 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -34,7 +34,6 @@
#include <linux/kernel.h> /* printk() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
-#include <linux/delay.h> /* udelay */
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
@@ -156,6 +155,8 @@ This directory exports the following interfaces. There operation is
documented in the MCPBL0010 TPS under the Telecom Clock API section, 11.4.
alarms :
current_ref :
+received_ref_clk3a :
+received_ref_clk3b :
enable_clk3a_output :
enable_clk3b_output :
enable_clka0_output :
@@ -165,7 +166,7 @@ enable_clkb1_output :
filter_select :
hardware_switching :
hardware_switching_mode :
-interrupt_switch :
+telclock_version :
mode_select :
refalign :
reset :
@@ -173,7 +174,6 @@ select_amcb1_transmit_clock :
select_amcb2_transmit_clock :
select_redundant_clock :
select_ref_frequency :
-test_mode :
All sysfs interfaces are integers in hex format, i.e echo 99 > refalign
has the same effect as echo 0x99 > refalign.
@@ -211,7 +211,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
result = request_irq(telclk_interrupt, &tlclk_interrupt,
SA_INTERRUPT, "telco_clock", tlclk_interrupt);
if (result == -EBUSY) {
- printk(KERN_ERR "telco_clock: Interrupt can't be reserved!\n");
+ printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
return -EBUSY;
}
inb(TLCLK_REG6); /* Clear interrupt events */
@@ -226,7 +226,7 @@ static int tlclk_release(struct inode *inode, struct file *filp)
return 0;
}
-ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
+static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
if (count < sizeof(struct tlclk_alarms))
@@ -242,7 +242,7 @@ ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count,
return sizeof(struct tlclk_alarms);
}
-ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
+static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
return 0;
@@ -278,21 +278,21 @@ static ssize_t show_current_ref(struct device *d,
static DEVICE_ATTR(current_ref, S_IRUGO, show_current_ref, NULL);
-static ssize_t show_interrupt_switch(struct device *d,
+static ssize_t show_telclock_version(struct device *d,
struct device_attribute *attr, char *buf)
{
unsigned long ret_val;
unsigned long flags;
spin_lock_irqsave(&event_lock, flags);
- ret_val = inb(TLCLK_REG6);
+ ret_val = inb(TLCLK_REG5);
spin_unlock_irqrestore(&event_lock, flags);
return sprintf(buf, "0x%lX\n", ret_val);
}
-static DEVICE_ATTR(interrupt_switch, S_IRUGO,
- show_interrupt_switch, NULL);
+static DEVICE_ATTR(telclock_version, S_IRUGO,
+ show_telclock_version, NULL);
static ssize_t show_alarms(struct device *d,
struct device_attribute *attr, char *buf)
@@ -309,6 +309,50 @@ static ssize_t show_alarms(struct device *d,
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t store_received_ref_clk3a(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xef, val);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL,
+ store_received_ref_clk3a);
+
+
+static ssize_t store_received_ref_clk3b(struct device *d,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long tmp;
+ unsigned char val;
+ unsigned long flags;
+
+ sscanf(buf, "%lX", &tmp);
+ dev_dbg(d, ": tmp = 0x%lX\n", tmp);
+
+ val = (unsigned char)tmp;
+ spin_lock_irqsave(&event_lock, flags);
+ SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1);
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL,
+ store_received_ref_clk3b);
+
+
static ssize_t store_enable_clk3b_output(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -436,26 +480,6 @@ static ssize_t store_enable_clka0_output(struct device *d,
static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL,
store_enable_clka0_output);
-static ssize_t store_test_mode(struct device *d,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned long flags;
- unsigned long tmp;
- unsigned char val;
-
- sscanf(buf, "%lX", &tmp);
- dev_dbg(d, "tmp = 0x%lX\n", tmp);
-
- val = (unsigned char)tmp;
- spin_lock_irqsave(&event_lock, flags);
- SET_PORT_BITS(TLCLK_REG4, 0xfd, 2);
- spin_unlock_irqrestore(&event_lock, flags);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(test_mode, S_IWUGO, NULL, store_test_mode);
-
static ssize_t store_select_amcb2_transmit_clock(struct device *d,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -475,7 +499,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG3, 0xc7, 0x38);
switch (val) {
case CLK_8_592MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
break;
case CLK_11_184MHz:
SET_PORT_BITS(TLCLK_REG0, 0xfc, 0);
@@ -484,7 +508,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d,
SET_PORT_BITS(TLCLK_REG0, 0xfc, 3);
break;
case CLK_44_736MHz:
- SET_PORT_BITS(TLCLK_REG0, 0xfc, 2);
+ SET_PORT_BITS(TLCLK_REG0, 0xfc, 1);
break;
}
} else
@@ -653,9 +677,7 @@ static ssize_t store_refalign (struct device *d,
dev_dbg(d, "tmp = 0x%lX\n", tmp);
spin_lock_irqsave(&event_lock, flags);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
- udelay(2);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0x08);
- udelay(2);
SET_PORT_BITS(TLCLK_REG0, 0xf7, 0);
spin_unlock_irqrestore(&event_lock, flags);
@@ -706,15 +728,16 @@ static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset);
static struct attribute *tlclk_sysfs_entries[] = {
&dev_attr_current_ref.attr,
- &dev_attr_interrupt_switch.attr,
+ &dev_attr_telclock_version.attr,
&dev_attr_alarms.attr,
+ &dev_attr_received_ref_clk3a.attr,
+ &dev_attr_received_ref_clk3b.attr,
&dev_attr_enable_clk3a_output.attr,
&dev_attr_enable_clk3b_output.attr,
&dev_attr_enable_clkb1_output.attr,
&dev_attr_enable_clka1_output.attr,
&dev_attr_enable_clkb0_output.attr,
&dev_attr_enable_clka0_output.attr,
- &dev_attr_test_mode.attr,
&dev_attr_select_amcb1_transmit_clock.attr,
&dev_attr_select_amcb2_transmit_clock.attr,
&dev_attr_select_redundant_clock.attr,
@@ -741,7 +764,7 @@ static int __init tlclk_init(void)
ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
if (ret < 0) {
- printk(KERN_ERR "telco_clock: can't get major! %d\n", tlclk_major);
+ printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
return ret;
}
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
@@ -750,7 +773,7 @@ static int __init tlclk_init(void)
/* Read telecom clock IRQ number (Set by BIOS) */
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
- printk(KERN_ERR "tlclk: request_region failed! 0x%X\n",
+ printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
TLCLK_BASE);
ret = -EBUSY;
goto out2;
@@ -758,7 +781,7 @@ static int __init tlclk_init(void)
telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
- printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw\n",
+ printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n",
telclk_interrupt);
ret = -ENXIO;
goto out3;
@@ -768,7 +791,7 @@ static int __init tlclk_init(void)
ret = misc_register(&tlclk_miscdev);
if (ret < 0) {
- printk(KERN_ERR " misc_register retruns %d\n", ret);
+ printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret);
ret = -EBUSY;
goto out3;
}
@@ -776,8 +799,7 @@ static int __init tlclk_init(void)
tlclk_device = platform_device_register_simple("telco_clock",
-1, NULL, 0);
if (!tlclk_device) {
- printk(KERN_ERR " platform_device_register retruns 0x%X\n",
- (unsigned int) tlclk_device);
+ printk(KERN_ERR "tlclk: platform_device_register failed.\n");
ret = -EBUSY;
goto out4;
}
@@ -785,7 +807,7 @@ static int __init tlclk_init(void)
ret = sysfs_create_group(&tlclk_device->dev.kobj,
&tlclk_attribute_group);
if (ret) {
- printk(KERN_ERR "failed to create sysfs device attributes\n");
+ printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n");
sysfs_remove_group(&tlclk_device->dev.kobj,
&tlclk_attribute_group);
goto out5;
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 2392e404e8d1..ba4582d160fd 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,6 +2,9 @@
# Makefile for the kernel tpm device drivers.
#
obj-$(CONFIG_TCG_TPM) += tpm.o
+ifdef CONFIG_ACPI
+ obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+endif
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index a9be0e8eaea5..5a3870477ef1 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -466,6 +466,7 @@ void tpm_remove_hardware(struct device *dev)
kfree(chip->vendor->miscdev.name);
sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ tpm_bios_log_teardown(chip->bios_dir);
dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
@@ -593,6 +594,8 @@ dev_num_search_complete:
sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ chip->bios_dir = tpm_bios_log_setup(devname);
+
return 0;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 159882ca69dd..fd3a4beaa53d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -82,6 +82,8 @@ struct tpm_chip {
struct tpm_vendor_specific *vendor;
+ struct dentry **bios_dir;
+
struct list_head list;
};
@@ -107,3 +109,16 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *, pm_message_t);
extern int tpm_pm_resume(struct device *);
+
+#ifdef CONFIG_ACPI
+extern struct dentry ** tpm_bios_log_setup(char *);
+extern void tpm_bios_log_teardown(struct dentry **);
+#else
+static inline struct dentry* tpm_bios_log_setup(char *name)
+{
+ return NULL;
+}
+static inline void tpm_bios_log_teardown(struct dentry **dir)
+{
+}
+#endif
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
new file mode 100644
index 000000000000..aedf7a8e6da7
--- /dev/null
+++ b/drivers/char/tpm/tpm_bios.c
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ * Seiji Munetoh <munetoh@jp.ibm.com>
+ * Stefan Berger <stefanb@us.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Access to the eventlog extended by the TCG BIOS of PC platform
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <acpi/acpi.h>
+#include <acpi/actypes.h>
+#include <acpi/actbl.h>
+#include "tpm.h"
+
+#define TCG_EVENT_NAME_LEN_MAX 255
+#define MAX_TEXT_EVENT 1000 /* Max event string length */
+#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+
+struct tpm_bios_log {
+ void *bios_event_log;
+ void *bios_event_log_end;
+};
+
+struct acpi_tcpa {
+ struct acpi_table_header hdr;
+ u16 reserved;
+ u32 log_max_len __attribute__ ((packed));
+ u32 log_start_addr __attribute__ ((packed));
+};
+
+struct tcpa_event {
+ u32 pcr_index;
+ u32 event_type;
+ u8 pcr_value[20]; /* SHA1 */
+ u32 event_size;
+ u8 event_data[0];
+};
+
+enum tcpa_event_types {
+ PREBOOT = 0,
+ POST_CODE,
+ UNUSED,
+ NO_ACTION,
+ SEPARATOR,
+ ACTION,
+ EVENT_TAG,
+ SCRTM_CONTENTS,
+ SCRTM_VERSION,
+ CPU_MICROCODE,
+ PLATFORM_CONFIG_FLAGS,
+ TABLE_OF_DEVICES,
+ COMPACT_HASH,
+ IPL,
+ IPL_PARTITION_DATA,
+ NONHOST_CODE,
+ NONHOST_CONFIG,
+ NONHOST_INFO,
+};
+
+static const char* tcpa_event_type_strings[] = {
+ "PREBOOT",
+ "POST CODE",
+ "",
+ "NO ACTION",
+ "SEPARATOR",
+ "ACTION",
+ "EVENT TAG",
+ "S-CRTM Contents",
+ "S-CRTM Version",
+ "CPU Microcode",
+ "Platform Config Flags",
+ "Table of Devices",
+ "Compact Hash",
+ "IPL",
+ "IPL Partition Data",
+ "Non-Host Code",
+ "Non-Host Config",
+ "Non-Host Info"
+};
+
+enum tcpa_pc_event_ids {
+ SMBIOS = 1,
+ BIS_CERT,
+ POST_BIOS_ROM,
+ ESCD,
+ CMOS,
+ NVRAM,
+ OPTION_ROM_EXEC,
+ OPTION_ROM_CONFIG,
+ OPTION_ROM_MICROCODE,
+ S_CRTM_VERSION,
+ S_CRTM_CONTENTS,
+ POST_CONTENTS,
+};
+
+static const char* tcpa_pc_event_id_strings[] = {
+ ""
+ "SMBIOS",
+ "BIS Certificate",
+ "POST BIOS ",
+ "ESCD ",
+ "CMOS",
+ "NVRAM",
+ "Option ROM",
+ "Option ROM config",
+ "Option ROM microcode",
+ "S-CRTM Version",
+ "S-CRTM Contents",
+ "S-CRTM POST Contents",
+};
+
+/* returns pointer to start of pos. entry of tcg log */
+static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t i;
+ struct tpm_bios_log *log = m->private;
+ void *addr = log->bios_event_log;
+ void *limit = log->bios_event_log_end;
+ struct tcpa_event *event;
+
+ /* read over *pos measurements */
+ for (i = 0; i < *pos; i++) {
+ event = addr;
+
+ if ((addr + sizeof(struct tcpa_event)) < limit) {
+ if (event->event_type == 0 && event->event_size == 0)
+ return NULL;
+ addr += sizeof(struct tcpa_event) + event->event_size;
+ }
+ }
+
+ /* now check if current entry is valid */
+ if ((addr + sizeof(struct tcpa_event)) >= limit)
+ return NULL;
+
+ event = addr;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+ ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ return NULL;
+
+ return addr;
+}
+
+static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
+ loff_t *pos)
+{
+ struct tcpa_event *event = v;
+ struct tpm_bios_log *log = m->private;
+ void *limit = log->bios_event_log_end;
+
+ v += sizeof(struct tcpa_event) + event->event_size;
+
+ /* now check if current entry is valid */
+ if ((v + sizeof(struct tcpa_event)) >= limit)
+ return NULL;
+
+ event = v;
+
+ if (event->event_type == 0 && event->event_size == 0)
+ return NULL;
+
+ if ((event->event_type == 0 && event->event_size == 0) ||
+ ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
+ return NULL;
+
+ (*pos)++;
+ return v;
+}
+
+static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int get_event_name(char *dest, struct tcpa_event *event,
+ unsigned char * event_entry)
+{
+ const char *name = "";
+ char data[40] = "";
+ int i, n_len = 0, d_len = 0;
+ u32 event_id, event_data_size;
+
+ switch(event->event_type) {
+ case PREBOOT:
+ case POST_CODE:
+ case UNUSED:
+ case NO_ACTION:
+ case SCRTM_CONTENTS:
+ case SCRTM_VERSION:
+ case CPU_MICROCODE:
+ case PLATFORM_CONFIG_FLAGS:
+ case TABLE_OF_DEVICES:
+ case COMPACT_HASH:
+ case IPL:
+ case IPL_PARTITION_DATA:
+ case NONHOST_CODE:
+ case NONHOST_CONFIG:
+ case NONHOST_INFO:
+ name = tcpa_event_type_strings[event->event_type];
+ n_len = strlen(name);
+ break;
+ case SEPARATOR:
+ case ACTION:
+ if (MAX_TEXT_EVENT > event->event_size) {
+ name = event_entry;
+ n_len = event->event_size;
+ }
+ break;
+ case EVENT_TAG:
+ event_id = be32_to_cpu(event_entry);
+ event_data_size = be32_to_cpu(&event_entry[4]);
+
+ /* ToDo Row data -> Base64 */
+
+ switch (event_id) {
+ case SMBIOS:
+ case BIS_CERT:
+ case CMOS:
+ case NVRAM:
+ case OPTION_ROM_EXEC:
+ case OPTION_ROM_CONFIG:
+ case OPTION_ROM_MICROCODE:
+ case S_CRTM_VERSION:
+ case S_CRTM_CONTENTS:
+ case POST_CONTENTS:
+ name = tcpa_pc_event_id_strings[event_id];
+ n_len = strlen(name);
+ break;
+ case POST_BIOS_ROM:
+ case ESCD:
+ name = tcpa_pc_event_id_strings[event_id];
+ n_len = strlen(name);
+ for (i = 0; i < 20; i++)
+ d_len += sprintf(data, "%02x",
+ event_entry[8 + i]);
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
+ n_len, name, d_len, data);
+
+}
+
+static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+
+ char *eventname;
+ char data[4];
+ u32 help;
+ int i, len;
+ struct tcpa_event *event = (struct tcpa_event *) v;
+ unsigned char *event_entry =
+ (unsigned char *) (v + sizeof(struct tcpa_event));
+
+ eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+ if (!eventname) {
+ printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+ __func__);
+ return -ENOMEM;
+ }
+
+ /* 1st: PCR used is in little-endian format (4 bytes) */
+ help = le32_to_cpu(event->pcr_index);
+ memcpy(data, &help, 4);
+ for (i = 0; i < 4; i++)
+ seq_putc(m, data[i]);
+
+ /* 2nd: SHA1 (20 bytes) */
+ for (i = 0; i < 20; i++)
+ seq_putc(m, event->pcr_value[i]);
+
+ /* 3rd: event type identifier (4 bytes) */
+ help = le32_to_cpu(event->event_type);
+ memcpy(data, &help, 4);
+ for (i = 0; i < 4; i++)
+ seq_putc(m, data[i]);
+
+ len = 0;
+
+ len += get_event_name(eventname, event, event_entry);
+
+ /* 4th: filename <= 255 + \'0' delimiter */
+ if (len > TCG_EVENT_NAME_LEN_MAX)
+ len = TCG_EVENT_NAME_LEN_MAX;
+
+ for (i = 0; i < len; i++)
+ seq_putc(m, eventname[i]);
+
+ /* 5th: delimiter */
+ seq_putc(m, '\0');
+
+ return 0;
+}
+
+static int tpm_bios_measurements_release(struct inode *inode,
+ struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+ struct tpm_bios_log *log = seq->private;
+
+ if (log) {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+
+ return seq_release(inode, file);
+}
+
+static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
+{
+ int len = 0;
+ int i;
+ char *eventname;
+ struct tcpa_event *event = v;
+ unsigned char *event_entry =
+ (unsigned char *) (v + sizeof(struct tcpa_event));
+
+ eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+ if (!eventname) {
+ printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+ __func__);
+ return -EFAULT;
+ }
+
+ seq_printf(m, "%2d ", event->pcr_index);
+
+ /* 2nd: SHA1 */
+ for (i = 0; i < 20; i++)
+ seq_printf(m, "%02x", event->pcr_value[i]);
+
+ /* 3rd: event type identifier */
+ seq_printf(m, " %02x", event->event_type);
+
+ len += get_event_name(eventname, event, event_entry);
+
+ /* 4th: eventname <= max + \'0' delimiter */
+ seq_printf(m, " %s\n", eventname);
+
+ return 0;
+}
+
+static struct seq_operations tpm_ascii_b_measurments_seqops = {
+ .start = tpm_bios_measurements_start,
+ .next = tpm_bios_measurements_next,
+ .stop = tpm_bios_measurements_stop,
+ .show = tpm_ascii_bios_measurements_show,
+};
+
+static struct seq_operations tpm_binary_b_measurments_seqops = {
+ .start = tpm_bios_measurements_start,
+ .next = tpm_bios_measurements_next,
+ .stop = tpm_bios_measurements_stop,
+ .show = tpm_binary_bios_measurements_show,
+};
+
+/* read binary bios log */
+static int read_log(struct tpm_bios_log *log)
+{
+ struct acpi_tcpa *buff;
+ acpi_status status;
+ void *virt;
+
+ if (log->bios_event_log != NULL) {
+ printk(KERN_ERR
+ "%s: ERROR - Eventlog already initialized\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
+ status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1,
+ ACPI_LOGICAL_ADDRESSING,
+ (struct acpi_table_header **)
+ &buff);
+
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (buff->log_max_len == 0) {
+ printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+ return -EIO;
+ }
+
+ /* malloc EventLog space */
+ log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
+ if (!log->bios_event_log) {
+ printk
+ ("%s: ERROR - Not enough Memory for BIOS measurements\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
+
+ acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
+
+ memcpy(log->bios_event_log, virt, buff->log_max_len);
+
+ acpi_os_unmap_memory(virt, buff->log_max_len);
+ return 0;
+}
+
+static int tpm_ascii_bios_measurements_open(struct inode *inode,
+ struct file *file)
+{
+ int err;
+ struct tpm_bios_log *log;
+ struct seq_file *seq;
+
+ log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+ if (!log)
+ return -ENOMEM;
+
+ if ((err = read_log(log)))
+ return err;
+
+ /* now register seq file */
+ err = seq_open(file, &tpm_ascii_b_measurments_seqops);
+ if (!err) {
+ seq = file->private_data;
+ seq->private = log;
+ } else {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+ return err;
+}
+
+struct file_operations tpm_ascii_bios_measurements_ops = {
+ .open = tpm_ascii_bios_measurements_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = tpm_bios_measurements_release,
+};
+
+static int tpm_binary_bios_measurements_open(struct inode *inode,
+ struct file *file)
+{
+ int err;
+ struct tpm_bios_log *log;
+ struct seq_file *seq;
+
+ log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+ if (!log)
+ return -ENOMEM;
+
+ if ((err = read_log(log)))
+ return err;
+
+ /* now register seq file */
+ err = seq_open(file, &tpm_binary_b_measurments_seqops);
+ if (!err) {
+ seq = file->private_data;
+ seq->private = log;
+ } else {
+ kfree(log->bios_event_log);
+ kfree(log);
+ }
+ return err;
+}
+
+struct file_operations tpm_binary_bios_measurements_ops = {
+ .open = tpm_binary_bios_measurements_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = tpm_bios_measurements_release,
+};
+
+struct dentry **tpm_bios_log_setup(char *name)
+{
+ struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
+
+ tpm_dir = securityfs_create_dir(name, NULL);
+ if (!tpm_dir)
+ goto out;
+
+ bin_file =
+ securityfs_create_file("binary_bios_measurements",
+ S_IRUSR | S_IRGRP, tpm_dir, NULL,
+ &tpm_binary_bios_measurements_ops);
+ if (!bin_file)
+ goto out_tpm;
+
+ ascii_file =
+ securityfs_create_file("ascii_bios_measurements",
+ S_IRUSR | S_IRGRP, tpm_dir, NULL,
+ &tpm_ascii_bios_measurements_ops);
+ if (!ascii_file)
+ goto out_bin;
+
+ ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
+ if (!ret)
+ goto out_ascii;
+
+ ret[0] = ascii_file;
+ ret[1] = bin_file;
+ ret[2] = tpm_dir;
+
+ return ret;
+
+out_ascii:
+ securityfs_remove(ascii_file);
+out_bin:
+ securityfs_remove(bin_file);
+out_tpm:
+ securityfs_remove(tpm_dir);
+out:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
+
+void tpm_bios_log_teardown(struct dentry **lst)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ securityfs_remove(lst[i]);
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 4b1eef51ec59..eb8b5be4e249 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -166,9 +166,12 @@ static struct tty_struct *alloc_tty_struct(void)
return tty;
}
+static void tty_buffer_free_all(struct tty_struct *);
+
static inline void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
+ tty_buffer_free_all(tty);
kfree(tty);
}
@@ -231,6 +234,200 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
}
/*
+ * Tty buffer allocation management
+ */
+
+static void tty_buffer_free_all(struct tty_struct *tty)
+{
+ struct tty_buffer *thead;
+ while((thead = tty->buf.head) != NULL) {
+ tty->buf.head = thead->next;
+ kfree(thead);
+ }
+ while((thead = tty->buf.free) != NULL) {
+ tty->buf.free = thead->next;
+ kfree(thead);
+ }
+ tty->buf.tail = NULL;
+}
+
+static void tty_buffer_init(struct tty_struct *tty)
+{
+ tty->buf.head = NULL;
+ tty->buf.tail = NULL;
+ tty->buf.free = NULL;
+}
+
+static struct tty_buffer *tty_buffer_alloc(size_t size)
+{
+ struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ if(p == NULL)
+ return NULL;
+ p->used = 0;
+ p->size = size;
+ p->next = NULL;
+ p->char_buf_ptr = (char *)(p->data);
+ p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
+/* printk("Flip create %p\n", p); */
+ return p;
+}
+
+/* Must be called with the tty_read lock held. This needs to acquire strategy
+ code to decide if we should kfree or relink a given expired buffer */
+
+static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+{
+ /* Dumb strategy for now - should keep some stats */
+/* printk("Flip dispose %p\n", b); */
+ if(b->size >= 512)
+ kfree(b);
+ else {
+ b->next = tty->buf.free;
+ tty->buf.free = b;
+ }
+}
+
+static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer **tbh = &tty->buf.free;
+ while((*tbh) != NULL) {
+ struct tty_buffer *t = *tbh;
+ if(t->size >= size) {
+ *tbh = t->next;
+ t->next = NULL;
+ t->used = 0;
+ /* DEBUG ONLY */
+ memset(t->data, '*', size);
+/* printk("Flip recycle %p\n", t); */
+ return t;
+ }
+ tbh = &((*tbh)->next);
+ }
+ /* Round the buffer size out */
+ size = (size + 0xFF) & ~ 0xFF;
+ return tty_buffer_alloc(size);
+ /* Should possibly check if this fails for the largest buffer we
+ have queued and recycle that ? */
+}
+
+int tty_buffer_request_room(struct tty_struct *tty, size_t size)
+{
+ struct tty_buffer *b = tty->buf.tail, *n;
+ int left = 0;
+
+ /* OPTIMISATION: We could keep a per tty "zero" sized buffer to
+ remove this conditional if its worth it. This would be invisible
+ to the callers */
+ if(b != NULL)
+ left = b->size - b->used;
+ if(left >= size)
+ return size;
+ /* This is the slow path - looking for new buffers to use */
+ n = tty_buffer_find(tty, size);
+ if(n == NULL)
+ return left;
+ if(b != NULL)
+ b->next = n;
+ else
+ tty->buf.head = n;
+ tty->buf.tail = n;
+ return size;
+}
+
+EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+
+int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+/* printk("Flip insert %d.\n", space); */
+ }
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ while (unlikely(size > copied));
+ return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string);
+
+int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size)
+{
+ int copied = 0;
+ do {
+ int space = tty_buffer_request_room(tty, size - copied);
+ struct tty_buffer *tb = tty->buf.tail;
+ /* If there is no space then tb may be NULL */
+ if(unlikely(space == 0))
+ break;
+ memcpy(tb->char_buf_ptr + tb->used, chars, space);
+ memcpy(tb->flag_buf_ptr + tb->used, flags, space);
+ tb->used += space;
+ copied += space;
+ chars += space;
+ flags += space;
+ }
+ /* There is a small chance that we need to split the data over
+ several buffers. If this is the case we must loop */
+ while (unlikely(size > copied));
+ return copied;
+}
+
+EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags);
+
+
+/*
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for normal characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
+ tb->used += space;
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
+
+/*
+ * Prepare a block of space in the buffer for data. Returns the length
+ * available and buffer pointer to the space which is now allocated and
+ * accounted for as ready for characters. This is used for drivers
+ * that need their own block copy routines into the buffer. There is no
+ * guarantee the buffer is a DMA target!
+ */
+
+int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
+{
+ int space = tty_buffer_request_room(tty, size);
+ struct tty_buffer *tb = tty->buf.tail;
+ *chars = tb->char_buf_ptr + tb->used;
+ *flags = tb->flag_buf_ptr + tb->used;
+ tb->used += space;
+ return space;
+}
+
+EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
+
+
+
+/*
* This is probably overkill for real world processors but
* they are not on hot paths so a little discipline won't do
* any harm.
@@ -492,6 +689,17 @@ restart:
if (ld == NULL)
return -EINVAL;
+ /*
+ * No more input please, we are switching. The new ldisc
+ * will update this value in the ldisc open function
+ */
+
+ tty->receive_room = 0;
+
+ /*
+ * Problem: What do we do if this blocks ?
+ */
+
tty_wait_until_sent(tty, 0);
if (tty->ldisc.num == ldisc) {
@@ -560,9 +768,9 @@ restart:
* we say so later on.
*/
- work = cancel_delayed_work(&tty->flip.work);
+ work = cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -616,7 +824,7 @@ restart:
/* Restart it in case no characters kick it off. Safe if
already running */
if (work)
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
return retval;
}
@@ -1721,10 +1929,10 @@ static void release_dev(struct file * filp)
*/
clear_bit(TTY_LDISC, &tty->flags);
clear_bit(TTY_DONT_FLIP, &tty->flags);
- cancel_delayed_work(&tty->flip.work);
+ cancel_delayed_work(&tty->buf.work);
/*
- * Wait for ->hangup_work and ->flip.work handlers to terminate
+ * Wait for ->hangup_work and ->buf.work handlers to terminate
*/
flush_scheduled_work();
@@ -2518,17 +2726,15 @@ EXPORT_SYMBOL(do_SAK);
/*
* This routine is called out of the software interrupt to flush data
- * from the flip buffer to the line discipline.
+ * from the buffer chain to the line discipline.
*/
static void flush_to_ldisc(void *private_)
{
struct tty_struct *tty = (struct tty_struct *) private_;
- unsigned char *cp;
- char *fp;
- int count;
unsigned long flags;
struct tty_ldisc *disc;
+ struct tty_buffer *tbuf;
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
@@ -2538,28 +2744,23 @@ static void flush_to_ldisc(void *private_)
/*
* Do it after the next timer tick:
*/
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
goto out;
}
spin_lock_irqsave(&tty->read_lock, flags);
- if (tty->flip.buf_num) {
- cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
- fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
- tty->flip.buf_num = 0;
- tty->flip.char_buf_ptr = tty->flip.char_buf;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf;
- } else {
- cp = tty->flip.char_buf;
- fp = tty->flip.flag_buf;
- tty->flip.buf_num = 1;
- tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
- }
- count = tty->flip.count;
- tty->flip.count = 0;
+ while((tbuf = tty->buf.head) != NULL) {
+ tty->buf.head = tbuf->next;
+ if (tty->buf.head == NULL)
+ tty->buf.tail = NULL;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+ /* printk("Process buffer %p for %d\n", tbuf, tbuf->used); */
+ disc->receive_buf(tty, tbuf->char_buf_ptr,
+ tbuf->flag_buf_ptr,
+ tbuf->used);
+ spin_lock_irqsave(&tty->read_lock, flags);
+ tty_buffer_free(tty, tbuf);
+ }
spin_unlock_irqrestore(&tty->read_lock, flags);
-
- disc->receive_buf(tty, cp, fp, count);
out:
tty_ldisc_deref(disc);
}
@@ -2654,11 +2855,12 @@ void tty_flip_buffer_push(struct tty_struct *tty)
if (tty->low_latency)
flush_to_ldisc((void *) tty);
else
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
EXPORT_SYMBOL(tty_flip_buffer_push);
+
/*
* This subroutine initializes a tty structure.
*/
@@ -2669,10 +2871,10 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
tty->pgrp = -1;
tty->overrun_time = jiffies;
- tty->flip.char_buf_ptr = tty->flip.char_buf;
- tty->flip.flag_buf_ptr = tty->flip.flag_buf;
- INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
- init_MUTEX(&tty->flip.pty_sem);
+ tty->buf.head = tty->buf.tail = NULL;
+ tty_buffer_init(tty);
+ INIT_WORK(&tty->buf.work, flush_to_ldisc, tty);
+ init_MUTEX(&tty->buf.pty_sem);
init_MUTEX(&tty->termios_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index 4d75c261f98a..4e5360388748 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -131,7 +131,7 @@ static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
static struct tty_driver *viotty_driver;
-void hvlog(char *fmt, ...)
+static void hvlog(char *fmt, ...)
{
int i;
unsigned long flags;
@@ -147,7 +147,7 @@ void hvlog(char *fmt, ...)
spin_unlock_irqrestore(&consoleloglock, flags);
}
-void hvlogOutput(const char *buf, int count)
+static void hvlogOutput(const char *buf, int count)
{
unsigned long flags;
int begin;
@@ -476,19 +476,19 @@ static struct port_info *get_port_data(struct tty_struct *tty)
*/
static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp)
{
+ struct HvLpEvent *hev = &viochar->event;
+
memset(viochar, 0, sizeof(struct viocharlpevent));
- viochar->event.xFlags.xValid = 1;
- viochar->event.xFlags.xFunction = HvLpEvent_Function_Int;
- viochar->event.xFlags.xAckInd = HvLpEvent_AckInd_NoAck;
- viochar->event.xFlags.xAckType = HvLpEvent_AckType_DeferredAck;
- viochar->event.xType = HvLpEvent_Type_VirtualIo;
- viochar->event.xSubtype = viomajorsubtype_chario | viochardata;
- viochar->event.xSourceLp = HvLpConfig_getLpIndex();
- viochar->event.xTargetLp = lp;
- viochar->event.xSizeMinus1 = sizeof(struct viocharlpevent);
- viochar->event.xSourceInstanceId = viopath_sourceinst(lp);
- viochar->event.xTargetInstanceId = viopath_targetinst(lp);
+ hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
+ HV_LP_EVENT_INT;
+ hev->xType = HvLpEvent_Type_VirtualIo;
+ hev->xSubtype = viomajorsubtype_chario | viochardata;
+ hev->xSourceLp = HvLpConfig_getLpIndex();
+ hev->xTargetLp = lp;
+ hev->xSizeMinus1 = sizeof(struct viocharlpevent);
+ hev->xSourceInstanceId = viopath_sourceinst(lp);
+ hev->xTargetInstanceId = viopath_targetinst(lp);
}
/*
@@ -752,7 +752,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event)
struct port_info *pi;
int reject = 0;
- if (event->xFlags.xFunction == HvLpEvent_Function_Ack) {
+ if (hvlpevent_is_ack(event)) {
if (port >= VTTY_PORTS)
return;
@@ -788,7 +788,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event)
}
/* This had better require an ack, otherwise complain */
- if (event->xFlags.xAckInd != HvLpEvent_AckInd_DoAck) {
+ if (!hvlpevent_need_ack(event)) {
printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
return;
}
@@ -856,7 +856,7 @@ static void vioHandleCloseEvent(struct HvLpEvent *event)
struct viocharlpevent *cevent = (struct viocharlpevent *)event;
u8 port = cevent->virtual_device;
- if (event->xFlags.xFunction == HvLpEvent_Function_Int) {
+ if (hvlpevent_is_int(event)) {
if (port >= VTTY_PORTS) {
printk(VIOCONS_KERN_WARN
"close message from invalid virtual device.\n");
@@ -904,6 +904,7 @@ static void vioHandleData(struct HvLpEvent *event)
struct viocharlpevent *cevent = (struct viocharlpevent *)event;
struct port_info *pi;
int index;
+ int num_pushed;
u8 port = cevent->virtual_device;
if (port >= VTTY_PORTS) {
@@ -964,6 +965,7 @@ static void vioHandleData(struct HvLpEvent *event)
* functionality will only work if built into the kernel and
* then only if sysrq is enabled through the proc filesystem.
*/
+ num_pushed = 0;
for (index = 0; index < cevent->len; index++) {
#ifdef CONFIG_MAGIC_SYSRQ
if (sysrq_enabled) {
@@ -993,16 +995,14 @@ static void vioHandleData(struct HvLpEvent *event)
* Don't attempt to copy more data into the buffer than we
* have room for because it would fail without indication.
*/
- if ((tty->flip.count + 1) > TTY_FLIPBUF_SIZE) {
+ if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
break;
}
- tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL);
+ num_pushed++;
}
- /* if cevent->len == 0 then no data was added to the buffer and flip.count == 0 */
- if (tty->flip.count)
- /* The next call resets flip.count when the data is flushed. */
+ if (num_pushed)
tty_flip_buffer_push(tty);
}
@@ -1056,8 +1056,7 @@ static void vioHandleCharEvent(struct HvLpEvent *event)
vioHandleConfig(event);
break;
default:
- if ((event->xFlags.xFunction == HvLpEvent_Function_Int) &&
- (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) {
+ if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
event->xRc = HvLpEvent_Rc_InvalidSubtype;
HvCallEvent_ackLpEvent(event);
}
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 19ba83635dd7..d9325281e482 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -434,13 +434,7 @@ static irqreturn_t scc_rx_int(int irq, void *data, struct pt_regs *fp)
SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
return IRQ_HANDLED;
}
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, ch, 0);
/* Check if another character is already ready; in that case, the
* spcond_int() function must be used, because this character may have an
@@ -487,13 +481,7 @@ static irqreturn_t scc_spcond_int(int irq, void *data, struct pt_regs *fp)
else
err = 0;
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = err;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, ch, err);
/* ++TeSche: *All* errors have to be cleared manually,
* else the condition persists for the next chars
@@ -875,13 +863,13 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
local_irq_save(flags);
#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
- for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
+ for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
}
#endif
#if defined(CONFIG_BVME6000_SCC)
if (MACH_IS_BVME6000) {
- for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)
+ for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
}
#endif
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 9ac6d43437b3..2267c7b81799 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 MontaVista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/vr41xx.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
MODULE_LICENSE("GPL");
@@ -718,7 +718,7 @@ static struct platform_driver giu_device_driver = {
},
};
-static int __devinit vr41xx_giu_init(void)
+static int __init vr41xx_giu_init(void)
{
int retval;
@@ -733,7 +733,7 @@ static int __devinit vr41xx_giu_init(void)
return retval;
}
-static void __devexit vr41xx_giu_exit(void)
+static void __exit vr41xx_giu_exit(void)
{
platform_driver_unregister(&giu_device_driver);
diff --git a/drivers/char/vr41xx_rtc.c b/drivers/char/vr41xx_rtc.c
index 435b30748e23..bc1b4a15212c 100644
--- a/drivers/char/vr41xx_rtc.c
+++ b/drivers/char/vr41xx_rtc.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Real Time Clock unit.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
#include <asm/uaccess.h>
#include <asm/vr41xx/vr41xx.h>
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
MODULE_LICENSE("GPL");
@@ -127,8 +127,6 @@ struct resource rtc_resource[2] = {
.flags = IORESOURCE_MEM, },
};
-#define RTC_NUM_RESOURCES sizeof(rtc_resource) / sizeof(struct resource)
-
static inline unsigned long read_elapsed_second(void)
{
unsigned long first_low, first_mid, first_high;
@@ -686,7 +684,8 @@ static int __devinit vr41xx_rtc_init(void)
break;
}
- rtc_platform_device = platform_device_register_simple("RTC", -1, rtc_resource, RTC_NUM_RESOURCES);
+ rtc_platform_device = platform_device_register_simple("RTC", -1,
+ rtc_resource, ARRAY_SIZE(rtc_resource));
if (IS_ERR(rtc_platform_device))
return PTR_ERR(rtc_platform_device);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e91268e86833..f1d9cb7feae6 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2758,29 +2758,6 @@ static void set_vesa_blanking(char __user *p)
vesa_blank_mode = (mode < 4) ? mode : 0;
}
-/*
- * This is called by a timer handler
- */
-static void vesa_powerdown(void)
-{
- struct vc_data *c = vc_cons[fg_console].d;
- /*
- * Power down if currently suspended (1 or 2),
- * suspend if currently blanked (0),
- * else do nothing (i.e. already powered down (3)).
- * Called only if powerdown features are allowed.
- */
- switch (vesa_blank_mode) {
- case VESA_NO_BLANKING:
- c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0);
- break;
- case VESA_VSYNC_SUSPEND:
- case VESA_HSYNC_SUSPEND:
- c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0);
- break;
- }
-}
-
void do_blank_screen(int entering_gfx)
{
struct vc_data *vc = vc_cons[fg_console].d;
@@ -2791,8 +2768,7 @@ void do_blank_screen(int entering_gfx)
if (console_blanked) {
if (blank_state == blank_vesa_wait) {
blank_state = blank_off;
- vesa_powerdown();
-
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
return;
}
@@ -2822,7 +2798,7 @@ void do_blank_screen(int entering_gfx)
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = vc->vc_sw->con_blank(vc, 1, 0);
+ i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
console_blanked = fg_console + 1;
if (i)
set_origin(vc);
@@ -2830,13 +2806,10 @@ void do_blank_screen(int entering_gfx)
if (console_blank_hook && console_blank_hook(1))
return;
- if (vesa_off_interval) {
+ if (vesa_off_interval && vesa_blank_mode) {
blank_state = blank_vesa_wait;
mod_timer(&console_timer, jiffies + vesa_off_interval);
}
-
- if (vesa_blank_mode)
- vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
EXPORT_SYMBOL(do_blank_screen);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 344001b45af9..c0dfcf273f0a 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -395,12 +395,38 @@ config MACHZ_WDT
To compile this driver as a module, choose M here: the
module will be called machzwd.
+config SBC_EPX_C3_WATCHDOG
+ tristate "Winsystems SBC EPX-C3 watchdog"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the built-in watchdog timer on the EPX-C3
+ Single-board computer made by Winsystems, Inc.
+
+ *Note*: This hardware watchdog is not probeable and thus there
+ is no way to know if writing to its IO address will corrupt
+ your system or have any real effect. The only way to be sure
+ that this driver does what you want is to make sure you
+ are runnning it on an EPX-C3 from Winsystems with the watchdog
+ timer at IO address 0x1ee and 0x1ef. It will write to both those
+ IO ports. Basically, the assumption is made that if you compile
+ this driver into your kernel and/or load it as a module, that you
+ know what you are doing and that you are in fact running on an
+ EPX-C3 board!
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc_epx_c3.
+
+
# PowerPC Architecture
config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config 83xx_WDT
+ tristate "MPC83xx Watchdog Timer"
+ depends on WATCHDOG && PPC_83xx
+
config MV64X60_WDT
tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
depends on WATCHDOG && MV64X60
@@ -438,7 +464,7 @@ config INDYDOG
config ZVM_WATCHDOG
tristate "z/VM Watchdog Timer"
- depends on WATCHDOG && ARCH_S390
+ depends on WATCHDOG && S390
help
IBM s/390 and zSeries machines running under z/VM 5.1 or later
provide a virtual watchdog timer to their guest that cause a
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index cfd0a3987710..36c0b282b8ba 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -52,9 +52,11 @@ 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
+obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o
obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index e75045fe2641..3e8410b5a65e 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/timer.h>
+#include <linux/completion.h>
#include <linux/jiffies.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -57,7 +58,7 @@ static int ticks = 10000;
/* some device data */
static struct {
- struct semaphore stop;
+ struct completion stop;
volatile int running;
struct timer_list timer;
volatile int queue;
@@ -85,7 +86,7 @@ static void cpu5wdt_trigger(unsigned long unused)
}
else {
/* ticks doesn't matter anyway */
- up(&cpu5wdt_device.stop);
+ complete(&cpu5wdt_device.stop);
}
}
@@ -239,7 +240,7 @@ static int __devinit cpu5wdt_init(void)
if ( !val )
printk(KERN_INFO PFX "sorry, was my fault\n");
- init_MUTEX_LOCKED(&cpu5wdt_device.stop);
+ init_completion(&cpu5wdt_device.stop);
cpu5wdt_device.queue = 0;
clear_bit(0, &cpu5wdt_device.inuse);
@@ -269,7 +270,7 @@ static void __devexit cpu5wdt_exit(void)
{
if ( cpu5wdt_device.queue ) {
cpu5wdt_device.queue = 0;
- down(&cpu5wdt_device.stop);
+ wait_for_completion(&cpu5wdt_device.stop);
}
misc_deregister(&cpu5wdt_misc);
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index b5be8b11104a..3800835ca8f3 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -186,8 +186,8 @@ static int __init ixp4xx_wdt_init(void)
unsigned long processor_id;
asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :);
- if (!(processor_id & 0xf)) {
- printk("IXP4XXX Watchdog: Rev. A0 CPU detected - "
+ if (!(processor_id & 0xf) && !cpu_is_ixp46x()) {
+ printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - "
"watchdog disabled\n");
return -ENODEV;
diff --git a/drivers/char/watchdog/mpc83xx_wdt.c b/drivers/char/watchdog/mpc83xx_wdt.c
new file mode 100644
index 000000000000..5d6f5061603a
--- /dev/null
+++ b/drivers/char/watchdog/mpc83xx_wdt.c
@@ -0,0 +1,229 @@
+/*
+ * mpc83xx_wdt.c - MPC83xx watchdog userspace interface
+ *
+ * Authors: Dave Updegraff <dave@cray.org>
+ * Kumar Gala <galak@kernel.crashing.org>
+ * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
+ * ..and from sc520_wdt
+ *
+ * Note: it appears that you can only actually ENABLE or DISABLE the thing
+ * once after POR. Once enabled, you cannot disable, and vice versa.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+struct mpc83xx_wdt {
+ __be32 res0;
+ __be32 swcrr; /* System watchdog control register */
+#define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */
+#define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */
+#define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/
+#define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */
+ __be32 swcnr; /* System watchdog count register */
+ u8 res1[2];
+ __be16 swsrr; /* System watchdog service register */
+ u8 res2[0xF0];
+};
+
+static struct mpc83xx_wdt __iomem *wd_base;
+
+static u16 timeout = 0xffff;
+module_param(timeout, ushort, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535");
+
+static int reset = 1;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset");
+
+/*
+ * We always prescale, but if someone really doesn't want to they can set this
+ * to 0
+ */
+static int prescale = 1;
+static unsigned int timeout_sec;
+
+static unsigned long wdt_is_open;
+static spinlock_t wdt_spinlock;
+
+static void mpc83xx_wdt_keepalive(void)
+{
+ /* Ping the WDT */
+ spin_lock(&wdt_spinlock);
+ out_be16(&wd_base->swsrr, 0x556c);
+ out_be16(&wd_base->swsrr, 0xaa39);
+ spin_unlock(&wdt_spinlock);
+}
+
+static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count)
+ mpc83xx_wdt_keepalive();
+ return count;
+}
+
+static int mpc83xx_wdt_open(struct inode *inode, struct file *file)
+{
+ u32 tmp = SWCRR_SWEN;
+ if (test_and_set_bit(0, &wdt_is_open))
+ return -EBUSY;
+
+ /* Once we start the watchdog we can't stop it */
+ __module_get(THIS_MODULE);
+
+ /* Good, fire up the show */
+ if (prescale)
+ tmp |= SWCRR_SWPR;
+ if (reset)
+ tmp |= SWCRR_SWRI;
+
+ tmp |= timeout << 16;
+
+ out_be32(&wd_base->swcrr, tmp);
+
+ return nonseekable_open(inode, file);
+}
+
+static int mpc83xx_wdt_release(struct inode *inode, struct file *file)
+{
+ printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
+ mpc83xx_wdt_keepalive();
+ clear_bit(0, &wdt_is_open);
+ return 0;
+}
+
+static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = "MPC83xx",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+ case WDIOC_KEEPALIVE:
+ mpc83xx_wdt_keepalive();
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout_sec, p);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct file_operations mpc83xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mpc83xx_wdt_write,
+ .ioctl = mpc83xx_wdt_ioctl,
+ .open = mpc83xx_wdt_open,
+ .release = mpc83xx_wdt_release,
+};
+
+static struct miscdevice mpc83xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mpc83xx_wdt_fops,
+};
+
+static int __devinit mpc83xx_wdt_probe(struct platform_device *dev)
+{
+ struct resource *r;
+ int ret;
+ unsigned int *freq = dev->dev.platform_data;
+
+ /* get a pointer to the register memory */
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
+ if (!r) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt));
+
+ if (wd_base == NULL) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ ret = misc_register(&mpc83xx_wdt_miscdev);
+ if (ret) {
+ printk(KERN_ERR "cannot register miscdev on minor=%d "
+ "(err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_unmap;
+ }
+
+ /* Calculate the timeout in seconds */
+ if (prescale)
+ timeout_sec = (timeout * 0x10000) / (*freq);
+ else
+ timeout_sec = timeout / (*freq);
+
+ printk(KERN_INFO "WDT driver for MPC83xx initialized. "
+ "mode:%s timeout=%d (%d seconds)\n",
+ reset ? "reset":"interrupt", timeout, timeout_sec);
+
+ spin_lock_init(&wdt_spinlock);
+
+ return 0;
+
+err_unmap:
+ iounmap(wd_base);
+err_out:
+ return ret;
+}
+
+static int __devexit mpc83xx_wdt_remove(struct platform_device *dev)
+{
+ misc_deregister(&mpc83xx_wdt_miscdev);
+ iounmap(wd_base);
+
+ return 0;
+}
+
+static struct platform_driver mpc83xx_wdt_driver = {
+ .probe = mpc83xx_wdt_probe,
+ .remove = __devexit_p(mpc83xx_wdt_remove),
+ .driver = {
+ .name = "mpc83xx_wdt",
+ },
+};
+
+static int __init mpc83xx_wdt_init(void)
+{
+ return platform_driver_register(&mpc83xx_wdt_driver);
+}
+
+static void __exit mpc83xx_wdt_exit(void)
+{
+ platform_driver_unregister(&mpc83xx_wdt_driver);
+}
+
+module_init(mpc83xx_wdt_init);
+module_exit(mpc83xx_wdt_exit);
+
+MODULE_AUTHOR("Dave Updegraff, Kumar Gala");
+MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c
index 56d62ba7c6ce..b2fc71e20850 100644
--- a/drivers/char/watchdog/mpc8xx_wdt.c
+++ b/drivers/char/watchdog/mpc8xx_wdt.c
@@ -18,6 +18,7 @@
#include <linux/watchdog.h>
#include <asm/8xx_immap.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
#include <syslib/m8xx_wdt.h>
static unsigned long wdt_opened;
@@ -25,18 +26,26 @@ static int wdt_status;
static void mpc8xx_wdt_handler_disable(void)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ volatile uint __iomem *piscr;
+ piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
- imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE);
+ if (!m8xx_has_internal_rtc)
+ m8xx_wdt_stop_timer();
+ else
+ out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE));
printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n");
}
static void mpc8xx_wdt_handler_enable(void)
{
- volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR;
+ volatile uint __iomem *piscr;
+ piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr;
- imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE;
+ if (!m8xx_has_internal_rtc)
+ m8xx_wdt_install_timer();
+ else
+ out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n");
}
@@ -68,9 +77,6 @@ static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len,
loff_t * ppos)
{
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
if (len)
m8xx_wdt_reset();
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 092e9b133750..1533f56baa42 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -151,7 +151,6 @@ static void usb_pcwd_disconnect (struct usb_interface *interface);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver usb_pcwd_driver = {
- .owner = THIS_MODULE,
.name = DRIVER_NAME,
.probe = usb_pcwd_probe,
.disconnect = usb_pcwd_disconnect,
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index eb667daee19b..9dc54736e4eb 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -46,12 +46,12 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/clk.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/arch/map.h>
-#include <asm/hardware/clock.h>
#undef S3C24XX_VA_WATCHDOG
#define S3C24XX_VA_WATCHDOG (0)
@@ -397,7 +397,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
return -ENOENT;
}
- clk_use(wdt_clock);
clk_enable(wdt_clock);
/* see if we can actually set the requested timer margin, and if
@@ -444,7 +443,6 @@ static int s3c2410wdt_remove(struct platform_device *dev)
if (wdt_clock != NULL) {
clk_disable(wdt_clock);
- clk_unuse(wdt_clock);
clk_put(wdt_clock);
wdt_clock = NULL;
}
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index fb88b4041dca..b474ea52d6e8 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -74,7 +74,7 @@ static int sa1100dog_release(struct inode *inode, struct file *file)
return 0;
}
-static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
{
if (len)
/* Refresh OSMR3 timer. */
@@ -96,20 +96,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case WDIOC_GETSUPPORT:
- ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
sizeof(ident)) ? -EFAULT : 0;
break;
case WDIOC_GETSTATUS:
- ret = put_user(0, (int *)arg);
+ ret = put_user(0, (int __user *)arg);
break;
case WDIOC_GETBOOTSTATUS:
- ret = put_user(boot_status, (int *)arg);
+ ret = put_user(boot_status, (int __user *)arg);
break;
case WDIOC_SETTIMEOUT:
- ret = get_user(time, (int *)arg);
+ ret = get_user(time, (int __user *)arg);
if (ret)
break;
@@ -123,7 +123,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
/*fall through*/
case WDIOC_GETTIMEOUT:
- ret = put_user(pre_margin / OSCR_FREQ, (int *)arg);
+ ret = put_user(pre_margin / OSCR_FREQ, (int __user *)arg);
break;
case WDIOC_KEEPALIVE:
diff --git a/drivers/char/watchdog/sbc_epx_c3.c b/drivers/char/watchdog/sbc_epx_c3.c
new file mode 100644
index 000000000000..951764614ebf
--- /dev/null
+++ b/drivers/char/watchdog/sbc_epx_c3.c
@@ -0,0 +1,216 @@
+/*
+ * SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3
+ * single board computer
+ *
+ * (c) Copyright 2006 Calin A. Culianu <calin@ajvar.org>, 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.
+ *
+ * based on softdog.c by Alan Cox <alan@redhat.com>
+ */
+
+#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/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define PFX "epx_c3: "
+static int epx_c3_alive;
+
+#define WATCHDOG_TIMEOUT 1 /* 1 sec default timeout */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+#define EPXC3_WATCHDOG_CTL_REG 0x1ee /* write 1 to enable, 0 to disable */
+#define EPXC3_WATCHDOG_PET_REG 0x1ef /* write anything to pet once enabled */
+
+static void epx_c3_start(void)
+{
+ outb(1, EPXC3_WATCHDOG_CTL_REG);
+}
+
+static void epx_c3_stop(void)
+{
+
+ outb(0, EPXC3_WATCHDOG_CTL_REG);
+
+ printk(KERN_INFO PFX "Stopped watchdog timer.\n");
+}
+
+static void epx_c3_pet(void)
+{
+ outb(1, EPXC3_WATCHDOG_PET_REG);
+}
+
+/*
+ * Allow only one person to hold it open
+ */
+static int epx_c3_open(struct inode *inode, struct file *file)
+{
+ if (epx_c3_alive)
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate timer */
+ epx_c3_start();
+ epx_c3_pet();
+
+ epx_c3_alive = 1;
+ printk(KERN_INFO "Started watchdog timer.\n");
+
+ return nonseekable_open(inode, file);
+}
+
+static int epx_c3_release(struct inode *inode, struct file *file)
+{
+ /* Shut off the timer.
+ * Lock it in if it's a module and we defined ...NOWAYOUT */
+ if (!nowayout)
+ epx_c3_stop(); /* Turn the WDT off */
+
+ epx_c3_alive = 0;
+
+ return 0;
+}
+
+static ssize_t epx_c3_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ /* Refresh the timer. */
+ if (len)
+ epx_c3_pet();
+ return len;
+}
+
+static int epx_c3_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int options, retval = -EINVAL;
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = "Winsystems EPX-C3 H/W Watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((struct watchdog_info *)arg,
+ &ident, sizeof(ident)))
+ return -EFAULT;
+ return 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0,(int *)arg);
+ case WDIOC_KEEPALIVE:
+ epx_c3_pet();
+ return 0;
+ case WDIOC_GETTIMEOUT:
+ return put_user(WATCHDOG_TIMEOUT,(int *)arg);
+ case WDIOC_SETOPTIONS: {
+ if (get_user(options, (int *)arg))
+ return -EFAULT;
+
+ if (options & WDIOS_DISABLECARD) {
+ epx_c3_stop();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ epx_c3_start();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT)
+ epx_c3_stop(); /* Turn the WDT off */
+
+ return NOTIFY_DONE;
+}
+
+static struct file_operations epx_c3_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = epx_c3_write,
+ .ioctl = epx_c3_ioctl,
+ .open = epx_c3_open,
+ .release = epx_c3_release,
+};
+
+static struct miscdevice epx_c3_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &epx_c3_fops,
+};
+
+static struct notifier_block epx_c3_notifier = {
+ .notifier_call = epx_c3_notify_sys,
+};
+
+static const char banner[] __initdata =
+ KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n";
+
+static int __init watchdog_init(void)
+{
+ int ret;
+
+ ret = register_reboot_notifier(&epx_c3_notifier);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register reboot notifier "
+ "(err=%d)\n", ret);
+ return ret;
+ }
+
+ ret = misc_register(&epx_c3_miscdev);
+ if (ret) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d "
+ "(err=%d)\n", WATCHDOG_MINOR, ret);
+ unregister_reboot_notifier(&epx_c3_notifier);
+ return ret;
+ }
+
+ printk(banner);
+
+ return 0;
+}
+
+static void __exit watchdog_exit(void)
+{
+ misc_deregister(&epx_c3_miscdev);
+ unregister_reboot_notifier(&epx_c3_notifier);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
+
+MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
+MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC. Note that there is no way to probe for this device -- so only use it if you are *sure* you are runnning on this specific SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index 44d49dfacbb3..3843900e94c4 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -1,5 +1,5 @@
/*
- * Wdt977 0.03: A Watchdog Device for Netwinder W83977AF chip
+ * Wdt977 0.04: A Watchdog Device for Netwinder W83977AF chip
*
* (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
*
@@ -18,6 +18,8 @@
* from minutes to seconds.
* 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in
* nwwatchdog_init.
+ * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks
+ * remove limitiation to be used on Netwinders only
*/
#include <linux/module.h>
@@ -28,6 +30,7 @@
#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>
@@ -37,8 +40,18 @@
#include <asm/mach-types.h>
#include <asm/uaccess.h>
-#define PFX "Wdt977: "
-#define WATCHDOG_MINOR 130
+#define WATCHDOG_VERSION "0.04"
+#define WATCHDOG_NAME "Wdt977"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
#define DEFAULT_TIMEOUT 60 /* default timeout in seconds */
@@ -47,6 +60,7 @@ static int timeoutM; /* timeout in minutes */
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 (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
@@ -63,9 +77,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
static int wdt977_start(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
* F2 has the timeout in minutes
@@ -73,28 +91,29 @@ static int wdt977_start(void)
* at timeout, and to reset timer on kbd/mouse activity (not impl.)
* F4 is used to just clear the TIMEOUT'ed state (bit 0)
*/
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(timeoutM,0x371);
- outb(0xF3,0x370);
- outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */
- outb(0xF4,0x370);
- outb(0x00,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
+ outb_p(0xF2, IO_INDEX_PORT);
+ outb_p(timeoutM, IO_DATA_PORT);
+ outb_p(0xF3, IO_INDEX_PORT);
+ outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */
+ outb_p(0xF4, IO_INDEX_PORT);
+ outb_p(0x00, IO_DATA_PORT);
/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
/* in test mode watch the bit 1 on F4 to indicate "triggered" */
if (!testmode)
{
- outb(0x07,0x370);
- outb(0x07,0x371);
- outb(0xE6,0x370);
- outb(0x08,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x07, IO_DATA_PORT);
+ outb_p(0xE6, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
}
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
printk(KERN_INFO PFX "activated.\n");
return 0;
@@ -106,35 +125,39 @@ static int wdt977_start(void)
static int wdt977_stop(void)
{
+ unsigned long flags;
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
* F3 is reset to its default state
* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
*/
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(0xFF,0x371);
- outb(0xF3,0x370);
- outb(0x00,0x371);
- outb(0xF4,0x370);
- outb(0x00,0x371);
- outb(0xF2,0x370);
- outb(0x00,0x371);
+ 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);
/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
- outb(0x07,0x370);
- outb(0x07,0x371);
- outb(0xE6,0x370);
- outb(0x08,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x07, IO_DATA_PORT);
+ outb_p(0xE6, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
printk(KERN_INFO PFX "shutdown.\n");
return 0;
@@ -147,19 +170,23 @@ static int wdt977_stop(void)
static int wdt977_keepalive(void)
{
+ unsigned long flags;
+ spin_lock_irqsave(&spinlock, flags);
+
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and kicks watchdog reg F2 */
/* F2 has the timeout in minutes */
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF2,0x370);
- outb(timeoutM,0x371);
+ outb_p(DEVICE_REGISTER, IO_INDEX_PORT);
+ outb_p(0x08, IO_DATA_PORT);
+ outb_p(0xF2, IO_INDEX_PORT);
+ outb_p(timeoutM, IO_DATA_PORT);
/* lock the SuperIO chip */
- outb(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
return 0;
}
@@ -198,22 +225,26 @@ static int wdt977_set_timeout(int t)
static int wdt977_get_status(int *status)
{
int new_status;
+ unsigned long flags;
- *status=0;
+ spin_lock_irqsave(&spinlock, flags);
/* unlock the SuperIO chip */
- outb(0x87,0x370);
- outb(0x87,0x370);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA, IO_INDEX_PORT);
/* select device Aux2 (device=8) and read watchdog reg F4 */
- outb(0x07,0x370);
- outb(0x08,0x371);
- outb(0xF4,0x370);
- new_status = inb(0x371);
+ 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(0xAA,0x370);
+ outb_p(LOCK_DATA, IO_INDEX_PORT);
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status=0;
if (new_status & 1)
*status |= WDIOF_CARDRESET;
@@ -249,8 +280,8 @@ static int wdt977_release(struct inode *inode, struct file *file)
wdt977_stop();
clear_bit(0,&timer_alive);
} else {
- printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
wdt977_keepalive();
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
}
expect_close = 0;
return 0;
@@ -271,14 +302,17 @@ static int wdt977_release(struct inode *inode, struct file *file)
static ssize_t wdt977_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- if (count) {
- if (!nowayout) {
+ if (count)
+ {
+ if (!nowayout)
+ {
size_t i;
/* In case it was set long ago */
expect_close = 0;
- for (i = 0; i != count; i++) {
+ for (i = 0; i != count; i++)
+ {
char c;
if (get_user(c, buf + i))
return -EFAULT;
@@ -287,6 +321,7 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf,
}
}
+ /* someone wrote to us, we should restart timer */
wdt977_keepalive();
}
return count;
@@ -308,7 +343,7 @@ static struct watchdog_info ident = {
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 1,
- .identity = "Winbond 83977",
+ .identity = WATCHDOG_NAME,
};
static int wdt977_ioctl(struct inode *inode, struct file *file,
@@ -405,50 +440,81 @@ static struct notifier_block wdt977_notifier = {
.notifier_call = wdt977_notify_sys,
};
-static int __init nwwatchdog_init(void)
+static int __init wd977_init(void)
{
- int retval;
- if (!machine_is_netwinder())
- return -ENODEV;
+ int rc;
+
+ //if (!machine_is_netwinder())
+ // return -ENODEV;
+
+ 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 (wdt977_set_timeout(timeout)) {
+ if (wdt977_set_timeout(timeout))
+ {
wdt977_set_timeout(DEFAULT_TIMEOUT);
printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n",
DEFAULT_TIMEOUT);
}
- retval = register_reboot_notifier(&wdt977_notifier);
- if (retval) {
- printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
- retval);
- return retval;
+ /* on Netwinder the IOports are already reserved by
+ * arch/arm/mach-footbridge/netwinder-hw.c
+ */
+ if (!machine_is_netwinder())
+ {
+ 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;
+ }
}
- retval = misc_register(&wdt977_miscdev);
- if (retval) {
+ rc = misc_register(&wdt977_miscdev);
+ if (rc)
+ {
printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
- WATCHDOG_MINOR, retval);
- unregister_reboot_notifier(&wdt977_notifier);
- return retval;
+ wdt977_miscdev.minor, rc);
+ goto err_out_region;
+ }
+
+ rc = register_reboot_notifier(&wdt977_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 = %i)\n",
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n",
timeout, nowayout, testmode);
return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt977_miscdev);
+err_out_region:
+ if (!machine_is_netwinder())
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
}
-static void __exit nwwatchdog_exit(void)
+static void __exit wd977_exit(void)
{
+ wdt977_stop();
misc_deregister(&wdt977_miscdev);
unregister_reboot_notifier(&wdt977_notifier);
+ release_region(IO_INDEX_PORT,2);
}
-module_init(nwwatchdog_init);
-module_exit(nwwatchdog_exit);
+module_init(wd977_init);
+module_exit(wd977_exit);
-MODULE_AUTHOR("Woody Suwalski <woody@netwinder.org>");
+MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>");
MODULE_DESCRIPTION("W83977AF Watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 969d2b4aaec0..4b4d7db1ff7b 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <linux/init.h>
#include <asm/atomic.h>
@@ -34,14 +35,14 @@
static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
-/* proc_counts is used as the sequence number of the netlink message */
+/* proc_event_counts is used as the sequence number of the netlink message */
static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
static inline void get_seq(__u32 *ts, int *cpu)
{
*ts = get_cpu_var(proc_event_counts)++;
*cpu = smp_processor_id();
- put_cpu_var(proc_counts);
+ put_cpu_var(proc_event_counts);
}
void proc_fork_connector(struct task_struct *task)
@@ -56,7 +57,7 @@ void proc_fork_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
ev->what = PROC_EVENT_FORK;
ev->event_data.fork.parent_pid = task->real_parent->pid;
ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -82,7 +83,7 @@ void proc_exec_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->what = PROC_EVENT_EXEC;
ev->event_data.exec.process_pid = task->pid;
ev->event_data.exec.process_tgid = task->tgid;
@@ -116,7 +117,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
} else
return;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
@@ -136,7 +137,7 @@ void proc_exit_connector(struct task_struct *task)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
get_seq(&msg->seq, &ev->cpu);
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->what = PROC_EVENT_EXIT;
ev->event_data.exit.process_pid = task->pid;
ev->event_data.exit.process_tgid = task->tgid;
@@ -169,7 +170,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
msg = (struct cn_msg*)buffer;
ev = (struct proc_event*)msg->data;
msg->seq = rcvd_seq;
- getnstimestamp(&ev->timestamp);
+ ktime_get_ts(&ev->timestamp);
ev->cpu = -1;
ev->what = PROC_EVENT_NONE;
ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 815902c2c856..277a843a87a6 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -41,7 +41,6 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock);
/* internal prototypes */
static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
static void handle_update(void *data);
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci);
/**
* Two notifier lists: the "policy" list is involved in the
@@ -127,7 +126,7 @@ static unsigned int debug_ratelimit = 1;
static unsigned int disable_ratelimit = 1;
static DEFINE_SPINLOCK(disable_ratelimit_lock);
-static inline void cpufreq_debug_enable_ratelimit(void)
+static void cpufreq_debug_enable_ratelimit(void)
{
unsigned long flags;
@@ -137,7 +136,7 @@ static inline void cpufreq_debug_enable_ratelimit(void)
spin_unlock_irqrestore(&disable_ratelimit_lock, flags);
}
-static inline void cpufreq_debug_disable_ratelimit(void)
+static void cpufreq_debug_disable_ratelimit(void)
{
unsigned long flags;
@@ -206,7 +205,7 @@ static inline void cpufreq_debug_disable_ratelimit(void) { return; }
static unsigned long l_p_j_ref;
static unsigned int l_p_j_ref_freq;
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
{
if (ci->flags & CPUFREQ_CONST_LOOPS)
return;
@@ -823,6 +822,30 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
/**
+ * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur
+ * @cpu: CPU number
+ *
+ * This is the last known freq, without actually getting it from the driver.
+ * Return value will be same as what is shown in scaling_cur_freq in sysfs.
+ */
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+ unsigned int ret = 0;
+
+ if (policy) {
+ down(&policy->lock);
+ ret = policy->cur;
+ up(&policy->lock);
+ cpufreq_cpu_put(policy);
+ }
+
+ return (ret);
+}
+EXPORT_SYMBOL(cpufreq_quick_get);
+
+
+/**
* cpufreq_get - get the current CPU frequency (in kHz)
* @cpu: CPU number
*
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 2ed5c4363b53..39543a2bed0f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -93,7 +93,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
{
return kstat_cpu(cpu).cpustat.idle +
kstat_cpu(cpu).cpustat.iowait +
- ( !dbs_tuners_ins.ignore_nice ?
+ ( dbs_tuners_ins.ignore_nice ?
kstat_cpu(cpu).cpustat.nice :
0);
}
@@ -127,7 +127,7 @@ show_one(sampling_rate, sampling_rate);
show_one(sampling_down_factor, sampling_down_factor);
show_one(up_threshold, up_threshold);
show_one(down_threshold, down_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
show_one(freq_step, freq_step);
static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
@@ -207,7 +207,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
const char *buf, size_t count)
{
unsigned int input;
@@ -272,7 +272,7 @@ define_one_rw(sampling_rate);
define_one_rw(sampling_down_factor);
define_one_rw(up_threshold);
define_one_rw(down_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
define_one_rw(freq_step);
static struct attribute * dbs_attributes[] = {
@@ -282,7 +282,7 @@ static struct attribute * dbs_attributes[] = {
&sampling_down_factor.attr,
&up_threshold.attr,
&down_threshold.attr,
- &ignore_nice.attr,
+ &ignore_nice_load.attr,
&freq_step.attr,
NULL
};
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 17741111246b..e69fd8dd1f1c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -89,7 +89,7 @@ static inline unsigned int get_cpu_idle_time(unsigned int cpu)
{
return kstat_cpu(cpu).cpustat.idle +
kstat_cpu(cpu).cpustat.iowait +
- ( !dbs_tuners_ins.ignore_nice ?
+ ( dbs_tuners_ins.ignore_nice ?
kstat_cpu(cpu).cpustat.nice :
0);
}
@@ -122,7 +122,7 @@ static ssize_t show_##file_name \
show_one(sampling_rate, sampling_rate);
show_one(sampling_down_factor, sampling_down_factor);
show_one(up_threshold, up_threshold);
-show_one(ignore_nice, ignore_nice);
+show_one(ignore_nice_load, ignore_nice);
static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
const char *buf, size_t count)
@@ -182,7 +182,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
const char *buf, size_t count)
{
unsigned int input;
@@ -223,7 +223,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
define_one_rw(sampling_rate);
define_one_rw(sampling_down_factor);
define_one_rw(up_threshold);
-define_one_rw(ignore_nice);
+define_one_rw(ignore_nice_load);
static struct attribute * dbs_attributes[] = {
&sampling_rate_max.attr,
@@ -231,7 +231,7 @@ static struct attribute * dbs_attributes[] = {
&sampling_rate.attr,
&sampling_down_factor.attr,
&up_threshold.attr,
- &ignore_nice.attr,
+ &ignore_nice_load.attr,
NULL
};
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 71407c578afe..64819aa7cac4 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -99,9 +99,6 @@ byte(const uint32_t x, const unsigned n)
return x >> (n << 3);
}
-#define uint32_t_in(x) le32_to_cpu(*(const uint32_t *)(x))
-#define uint32_t_out(to, from) (*(uint32_t *)(to) = cpu_to_le32(from))
-
#define E_KEY ctx->E
#define D_KEY ctx->D
@@ -294,6 +291,7 @@ static int
aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags)
{
struct aes_ctx *ctx = aes_ctx(ctx_arg);
+ const __le32 *key = (const __le32 *)in_key;
uint32_t i, t, u, v, w;
uint32_t P[AES_EXTENDED_KEY_SIZE];
uint32_t rounds;
@@ -313,10 +311,10 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t
ctx->E = ctx->e_data;
ctx->D = ctx->e_data;
- E_KEY[0] = uint32_t_in (in_key);
- E_KEY[1] = uint32_t_in (in_key + 4);
- E_KEY[2] = uint32_t_in (in_key + 8);
- E_KEY[3] = uint32_t_in (in_key + 12);
+ E_KEY[0] = le32_to_cpu(key[0]);
+ E_KEY[1] = le32_to_cpu(key[1]);
+ E_KEY[2] = le32_to_cpu(key[2]);
+ E_KEY[3] = le32_to_cpu(key[3]);
/* Prepare control words. */
memset(&ctx->cword, 0, sizeof(ctx->cword));
@@ -343,17 +341,17 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t
break;
case 24:
- E_KEY[4] = uint32_t_in (in_key + 16);
- t = E_KEY[5] = uint32_t_in (in_key + 20);
+ E_KEY[4] = le32_to_cpu(key[4]);
+ t = E_KEY[5] = le32_to_cpu(key[5]);
for (i = 0; i < 8; ++i)
loop6 (i);
break;
case 32:
- E_KEY[4] = uint32_t_in (in_key + 16);
- E_KEY[5] = uint32_t_in (in_key + 20);
- E_KEY[6] = uint32_t_in (in_key + 24);
- t = E_KEY[7] = uint32_t_in (in_key + 28);
+ E_KEY[4] = le32_to_cpu(in_key[4]);
+ E_KEY[5] = le32_to_cpu(in_key[5]);
+ E_KEY[6] = le32_to_cpu(in_key[6]);
+ t = E_KEY[7] = le32_to_cpu(in_key[7]);
for (i = 0; i < 7; ++i)
loop8 (i);
break;
@@ -468,6 +466,8 @@ static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
static struct crypto_alg aes_alg = {
.cra_name = "aes",
+ .cra_driver_name = "aes-padlock",
+ .cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct aes_ctx),
diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h
index 3cf2b7a12348..b78489bc298a 100644
--- a/drivers/crypto/padlock.h
+++ b/drivers/crypto/padlock.h
@@ -17,7 +17,7 @@
/* Control word. */
struct cword {
- int __attribute__ ((__packed__))
+ unsigned int __attribute__ ((__packed__))
rounds:4,
algo:3,
keygen:1,
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c
index ffe6f44ac76f..ca8e69d2f64d 100644
--- a/drivers/dio/dio-driver.c
+++ b/drivers/dio/dio-driver.c
@@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &dio_bus_type;
- drv->driver.probe = dio_device_probe;
/* register with core */
count = driver_register(&drv->driver);
@@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv)
struct bus_type dio_bus_type = {
.name = "dio",
- .match = dio_bus_match
+ .match = dio_bus_match,
+ .probe = dio_device_probe,
};
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
new file mode 100644
index 000000000000..4819e7fc00dd
--- /dev/null
+++ b/drivers/edac/Kconfig
@@ -0,0 +1,102 @@
+#
+# EDAC Kconfig
+# Copyright (c) 2003 Linux Networx
+# Licensed and distributed under the GPL
+#
+# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
+#
+
+menu 'EDAC - error detection and reporting (RAS)'
+
+config EDAC
+ tristate "EDAC core system error reporting"
+ depends on X86
+ default y
+ help
+ EDAC is designed to report errors in the core system.
+ These are low-level errors that are reported in the CPU or
+ supporting chipset: memory errors, cache errors, PCI errors,
+ thermal throttling, etc.. If unsure, select 'Y'.
+
+
+comment "Reporting subsystems"
+ depends on EDAC
+
+config EDAC_DEBUG
+ bool "Debugging"
+ depends on EDAC
+ help
+ This turns on debugging information for the entire EDAC
+ sub-system. You can insert module with "debug_level=x", current
+ there're four debug levels (x=0,1,2,3 from low to high).
+ Usually you should select 'N'.
+
+config EDAC_MM_EDAC
+ tristate "Main Memory EDAC (Error Detection And Correction) reporting"
+ depends on EDAC
+ default y
+ help
+ Some systems are able to detect and correct errors in main
+ memory. EDAC can report statistics on memory error
+ detection and correction (EDAC - or commonly referred to ECC
+ errors). EDAC will also try to decode where these errors
+ occurred so that a particular failing memory module can be
+ replaced. If unsure, select 'Y'.
+
+
+config EDAC_AMD76X
+ tristate "AMD 76x (760, 762, 768)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the AMD 76x
+ series of chipsets used with the Athlon processor.
+
+config EDAC_E7XXX
+ tristate "Intel e7xxx (e7205, e7500, e7501, e7505)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7205, E7500, E7501 and E7505 server chipsets.
+
+config EDAC_E752X
+ tristate "Intel e752x (e7520, e7525, e7320)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ E7520, E7525, E7320 server chipsets.
+
+config EDAC_I82875P
+ tristate "Intel 82875p (D82875P, E7210)"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ DP82785P and E7210 server chipsets.
+
+config EDAC_I82860
+ tristate "Intel 82860"
+ depends on EDAC_MM_EDAC && PCI
+ help
+ Support for error detection and correction on the Intel
+ 82860 chipset.
+
+config EDAC_R82600
+ tristate "Radisys 82600 embedded chipset"
+ depends on EDAC_MM_EDAC
+ help
+ Support for error detection and correction on the Radisys
+ 82600 embedded chipset.
+
+choice
+ prompt "Error detecting method"
+ depends on EDAC
+ default EDAC_POLL
+
+config EDAC_POLL
+ bool "Poll for errors"
+ depends on EDAC
+ help
+ Poll the chipset periodically to detect errors.
+
+endchoice
+
+endmenu
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
new file mode 100644
index 000000000000..93137fdab4b3
--- /dev/null
+++ b/drivers/edac/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux kernel EDAC drivers.
+#
+# Copyright 02 Jul 2003, Linux Networx (http://lnxi.com)
+# This file may be distributed under the terms of the
+# GNU General Public License.
+#
+# $Id: Makefile,v 1.4.2.3 2005/07/08 22:05:38 dsp_llnl Exp $
+
+
+obj-$(CONFIG_EDAC_MM_EDAC) += edac_mc.o
+obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
+obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
+obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
+obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
+obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
+obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
+
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c
new file mode 100644
index 000000000000..2fcc8120b53c
--- /dev/null
+++ b/drivers/edac/amd76x_edac.c
@@ -0,0 +1,356 @@
+/*
+ * AMD 76x Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * $Id: edac_amd76x.c,v 1.4.2.5 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#define AMD76X_NR_CSROWS 8
+#define AMD76X_NR_CHANS 1
+#define AMD76X_NR_DIMMS 4
+
+
+/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
+#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
+ *
+ * 31:16 reserved
+ * 15:14 SERR enabled: x1=ue 1x=ce
+ * 13 reserved
+ * 12 diag: disabled, enabled
+ * 11:10 mode: dis, EC, ECC, ECC+scrub
+ * 9:8 status: x1=ue 1x=ce
+ * 7:4 UE cs row
+ * 3:0 CE cs row
+ */
+#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
+ *
+ * 31:26 clock disable 5 - 0
+ * 25 SDRAM init
+ * 24 reserved
+ * 23 mode register service
+ * 22:21 suspend to RAM
+ * 20 burst refresh enable
+ * 19 refresh disable
+ * 18 reserved
+ * 17:16 cycles-per-refresh
+ * 15:8 reserved
+ * 7:0 x4 mode enable 7 - 0
+ */
+#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
+ *
+ * 31:23 chip-select base
+ * 22:16 reserved
+ * 15:7 chip-select mask
+ * 6:3 reserved
+ * 2:1 address mode
+ * 0 chip-select enable
+ */
+
+
+struct amd76x_error_info {
+ u32 ecc_mode_status;
+};
+
+
+enum amd76x_chips {
+ AMD761 = 0,
+ AMD762
+};
+
+
+struct amd76x_dev_info {
+ const char *ctl_name;
+};
+
+
+static const struct amd76x_dev_info amd76x_devs[] = {
+ [AMD761] = {.ctl_name = "AMD761"},
+ [AMD762] = {.ctl_name = "AMD762"},
+};
+
+
+/**
+ * amd76x_get_error_info - fetch error information
+ * @mci: Memory controller
+ * @info: Info to fill in
+ *
+ * Fetch and store the AMD76x ECC status. Clear pending status
+ * on the chip so that further errors will be reported
+ */
+
+static void amd76x_get_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ &info->ecc_mode_status);
+
+ if (info->ecc_mode_status & BIT(8))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(8), (u32) BIT(8));
+
+ if (info->ecc_mode_status & BIT(9))
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
+ (u32) BIT(9), (u32) BIT(9));
+}
+
+
+/**
+ * amd76x_process_error_info - Error check
+ * @mci: Memory controller
+ * @info: Previously fetched information from chip
+ * @handle_errors: 1 if we should do recovery
+ *
+ * Process the chip state and decide if an error has occurred.
+ * A return of 1 indicates an error. Also if handle_errors is true
+ * then attempt to handle and clean up after the error
+ */
+
+static int amd76x_process_error_info (struct mem_ctl_info *mci,
+ struct amd76x_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 row;
+
+ error_found = 0;
+
+ /*
+ * Check for an uncorrectable error
+ */
+ if (info->ecc_mode_status & BIT(8)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = (info->ecc_mode_status >> 4) & 0xf;
+ edac_mc_handle_ue(mci,
+ mci->csrows[row].first_page, 0, row,
+ mci->ctl_name);
+ }
+ }
+
+ /*
+ * Check for a correctable error
+ */
+ if (info->ecc_mode_status & BIT(9)) {
+ error_found = 1;
+
+ if (handle_errors) {
+ row = info->ecc_mode_status & 0xf;
+ edac_mc_handle_ce(mci,
+ mci->csrows[row].first_page, 0, 0, row, 0,
+ mci->ctl_name);
+ }
+ }
+ return error_found;
+}
+
+/**
+ * amd76x_check - Poll the controller
+ * @mci: Memory controller
+ *
+ * Called by the poll handlers this function reads the status
+ * from the controller and checks for errors.
+ */
+
+static void amd76x_check(struct mem_ctl_info *mci)
+{
+ struct amd76x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ amd76x_get_error_info(mci, &info);
+ amd76x_process_error_info(mci, &info, 1);
+}
+
+
+/**
+ * amd76x_probe1 - Perform set up for detected device
+ * @pdev; PCI device detected
+ * @dev_idx: Device type index
+ *
+ * We have found an AMD76x and now need to set up the memory
+ * controller status reporting. We configure and set up the
+ * memory controller reporting and claim the device.
+ */
+
+static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ enum edac_type ems_modes[] = {
+ EDAC_NONE,
+ EDAC_EC,
+ EDAC_SECDED,
+ EDAC_SECDED
+ };
+ u32 ems;
+ u32 ems_mode;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
+ ems_mode = (ems >> 10) & 0x3;
+
+ mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pci_dev_get(pdev);
+ mci->mtype_cap = MEM_FLAG_RDDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ mci->edac_cap = ems_mode ?
+ (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.4.2.5 $";
+ mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
+ mci->edac_check = amd76x_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u32 mba;
+ u32 mba_base;
+ u32 mba_mask;
+ u32 dms;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_dword(mci->pdev,
+ AMD76X_MEM_BASE_ADDR + (index * 4),
+ &mba);
+
+ if (!(mba & BIT(0)))
+ continue;
+
+ mba_base = mba & 0xff800000UL;
+ mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
+
+ pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
+ &dms);
+
+ csrow->first_page = mba_base >> PAGE_SHIFT;
+ csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
+ csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+ csrow->page_mask = mba_mask >> PAGE_SHIFT;
+ csrow->grain = csrow->nr_pages << PAGE_SHIFT;
+ csrow->mtype = MEM_RDDR;
+ csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
+ csrow->edac_mode = ems_modes[ems_mode];
+ }
+
+ /* clear counters */
+ pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, (u32) (0x3 << 8),
+ (u32) (0x3 << 8));
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if(mci->pdev)
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit amd76x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return amd76x_probe1(pdev, ent->driver_data);
+}
+
+
+/**
+ * amd76x_remove_one - driver shutdown
+ * @pdev: PCI device being handed back
+ *
+ * Called when the driver is unloaded. Find the matching mci
+ * structure for the device then delete the mci and free the
+ * resources.
+ */
+
+static void __devexit amd76x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+ if (edac_mc_del_mc(mci))
+ return;
+ pci_dev_put(mci->pdev);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD762},
+ {PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ AMD761},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
+
+
+static struct pci_driver amd76x_driver = {
+ .name = BS_MOD_STR,
+ .probe = amd76x_init_one,
+ .remove = __devexit_p(amd76x_remove_one),
+ .id_table = amd76x_pci_tbl,
+};
+
+static int __init amd76x_init(void)
+{
+ return pci_register_driver(&amd76x_driver);
+}
+
+static void __exit amd76x_exit(void)
+{
+ pci_unregister_driver(&amd76x_driver);
+}
+
+module_init(amd76x_init);
+module_exit(amd76x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
new file mode 100644
index 000000000000..770a5a633079
--- /dev/null
+++ b/drivers/edac/e752x_edac.c
@@ -0,0 +1,1071 @@
+/*
+ * Intel e752x Memory Controller kernel module
+ * (C) 2004 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e752x_chips" below for supported chipsets
+ *
+ * Written by Tom Zimmerman
+ *
+ * Contributors:
+ * Thayne Harbaugh at realmsys.com (?)
+ * Wang Zhenyu at intel.com
+ * Dave Jiang at mvista.com
+ *
+ * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_0
+#define PCI_DEVICE_ID_INTEL_7520_0 0x3590
+#endif /* PCI_DEVICE_ID_INTEL_7520_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR
+#define PCI_DEVICE_ID_INTEL_7520_1_ERR 0x3591
+#endif /* PCI_DEVICE_ID_INTEL_7520_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_0
+#define PCI_DEVICE_ID_INTEL_7525_0 0x359E
+#endif /* PCI_DEVICE_ID_INTEL_7525_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR
+#define PCI_DEVICE_ID_INTEL_7525_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7525_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_0
+#define PCI_DEVICE_ID_INTEL_7320_0 0x3592
+#endif /* PCI_DEVICE_ID_INTEL_7320_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR
+#define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
+#endif /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
+
+#define E752X_NR_CSROWS 8 /* number of csrows */
+
+
+/* E752X register addresses - device 0 function 0 */
+#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31:30 Device width row 7
+ * 01=x8 10=x4 11=x8 DDR2
+ * 27:26 Device width row 6
+ * 23:22 Device width row 5
+ * 19:20 Device width row 4
+ * 15:14 Device width row 3
+ * 11:10 Device width row 2
+ * 7:6 Device width row 1
+ * 3:2 Device width row 0
+ */
+#define E752X_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /* FIXME:IS THIS RIGHT? */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E752X_DRM 0x80 /* Dimm mapping register */
+#define E752X_DDRCSR 0x9A /* DDR control and status reg (16b) */
+ /*
+ * 14:12 1 single A, 2 single B, 3 dual
+ */
+#define E752X_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E752X_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E752X_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+#define E752X_REMAPOFFSET 0xCA /* DRAM remap limit offset reg (16b) */
+
+/* E752X register addresses - device 0 function 1 */
+#define E752X_FERR_GLOBAL 0x40 /* Global first error register (32b) */
+#define E752X_NERR_GLOBAL 0x44 /* Global next error register (32b) */
+#define E752X_HI_FERR 0x50 /* Hub interface first error reg (8b) */
+#define E752X_HI_NERR 0x52 /* Hub interface next error reg (8b) */
+#define E752X_HI_ERRMASK 0x54 /* Hub interface error mask reg (8b) */
+#define E752X_HI_SMICMD 0x5A /* Hub interface SMI command reg (8b) */
+#define E752X_SYSBUS_FERR 0x60 /* System buss first error reg (16b) */
+#define E752X_SYSBUS_NERR 0x62 /* System buss next error reg (16b) */
+#define E752X_SYSBUS_ERRMASK 0x64 /* System buss error mask reg (16b) */
+#define E752X_SYSBUS_SMICMD 0x6A /* System buss SMI command reg (16b) */
+#define E752X_BUF_FERR 0x70 /* Memory buffer first error reg (8b) */
+#define E752X_BUF_NERR 0x72 /* Memory buffer next error reg (8b) */
+#define E752X_BUF_ERRMASK 0x74 /* Memory buffer error mask reg (8b) */
+#define E752X_BUF_SMICMD 0x7A /* Memory buffer SMI command reg (8b) */
+#define E752X_DRAM_FERR 0x80 /* DRAM first error register (16b) */
+#define E752X_DRAM_NERR 0x82 /* DRAM next error register (16b) */
+#define E752X_DRAM_ERRMASK 0x84 /* DRAM error mask register (8b) */
+#define E752X_DRAM_SMICMD 0x8A /* DRAM SMI command register (8b) */
+#define E752X_DRAM_RETR_ADD 0xAC /* DRAM Retry address register (32b) */
+#define E752X_DRAM_SEC1_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC2_ADD 0xC8 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_DED_ADD 0xA4 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SCRB_ADD 0xA8 /* DRAM first uncorrectable scrub memory */
+ /* error address register (32b) */
+ /*
+ * 31 Reserved
+ * 30:2 CE address (64 byte block 34:6)
+ * 1 Reserved
+ * 0 HiLoCS
+ */
+#define E752X_DRAM_SEC1_SYNDROME 0xC4 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DRAM_SEC2_SYNDROME 0xC6 /* DRAM second correctable memory */
+ /* error syndrome register (16b) */
+#define E752X_DEVPRES1 0xF4 /* Device Present 1 register (8b) */
+
+/* ICH5R register addresses - device 30 function 0 */
+#define ICH5R_PCI_STAT 0x06 /* PCI status register (16b) */
+#define ICH5R_PCI_2ND_STAT 0x1E /* PCI status secondary reg (16b) */
+#define ICH5R_PCI_BRIDGE_CTL 0x3E /* PCI bridge control register (16b) */
+
+enum e752x_chips {
+ E7520 = 0,
+ E7525 = 1,
+ E7320 = 2
+};
+
+
+struct e752x_pvt {
+ struct pci_dev *bridge_ck;
+ struct pci_dev *dev_d0f0;
+ struct pci_dev *dev_d0f1;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ int mc_symmetric;
+ u8 map[8];
+ int map_type;
+ const struct e752x_dev_info *dev_info;
+};
+
+
+struct e752x_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+struct e752x_error_info {
+ u32 ferr_global;
+ u32 nerr_global;
+ u8 hi_ferr;
+ u8 hi_nerr;
+ u16 sysbus_ferr;
+ u16 sysbus_nerr;
+ u8 buf_ferr;
+ u8 buf_nerr;
+ u16 dram_ferr;
+ u16 dram_nerr;
+ u32 dram_sec1_add;
+ u32 dram_sec2_add;
+ u16 dram_sec1_syndrome;
+ u16 dram_sec2_syndrome;
+ u32 dram_ded_add;
+ u32 dram_scrb_add;
+ u32 dram_retr_add;
+};
+
+static const struct e752x_dev_info e752x_devs[] = {
+ [E7520] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
+ .ctl_name = "E7520"},
+ [E7525] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
+ .ctl_name = "E7525"},
+ [E7320] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
+ .ctl_name = "E7320"},
+};
+
+
+static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ u32 remap;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (page < pvt->tolm)
+ return page;
+ if ((page >= 0x100000) && (page < pvt->remapbase))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome)
+{
+ u32 page;
+ int row;
+ int channel;
+ int i;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* convert the addr to 4k page */
+ page = sec1_add >> (PAGE_SHIFT - 4);
+
+ /* FIXME - check for -1 */
+ if (pvt->mc_symmetric) {
+ /* chip select are bits 14 & 13 */
+ row = ((page >> 1) & 3);
+ printk(KERN_WARNING
+ "Test row %d Table %d %d %d %d %d %d %d %d\n",
+ row, pvt->map[0], pvt->map[1], pvt->map[2],
+ pvt->map[3], pvt->map[4], pvt->map[5],
+ pvt->map[6], pvt->map[7]);
+
+ /* test for channel remapping */
+ for (i = 0; i < 8; i++) {
+ if (pvt->map[i] == row)
+ break;
+ }
+ printk(KERN_WARNING "Test computed row %d\n", i);
+ if (i < 8)
+ row = i;
+ else
+ printk(KERN_WARNING
+ "MC%d: row %d not found in remap table\n",
+ mci->mc_idx, row);
+ } else
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* 0 = channel A, 1 = channel B */
+ channel = !(error_one & 1);
+
+ if (!pvt->map_type)
+ row = 7 - row;
+ edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
+ "e752x CE");
+}
+
+
+static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
+ u32 sec1_add, u16 sec1_syndrome, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
+}
+
+static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
+ u32 scrb_add)
+{
+ u32 error_2b, block_page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (error_one & 0x0202) {
+ error_2b = ded_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Read");
+ }
+ if (error_one & 0x0404) {
+ error_2b = scrb_add;
+ /* convert to 4k address */
+ block_page = error_2b >> (PAGE_SHIFT - 4);
+ row = pvt->mc_symmetric ?
+ /* chip select are bits 14 & 13 */
+ ((block_page >> 1) & 3) :
+ edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row,
+ "e752x UE from Scruber");
+ }
+}
+
+static inline void process_ue(struct mem_ctl_info *mci, u16 error_one,
+ u32 ded_add, u32 scrb_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ue(mci, error_one, ded_add, scrb_add);
+}
+
+static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (!handle_error)
+ return;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
+}
+
+static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add)
+{
+ u32 error_1b, page;
+ int row;
+ struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
+
+ error_1b = retry_add;
+ page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
+ row = pvt->mc_symmetric ?
+ ((page >> 1) & 3) : /* chip select are bits 14 & 13 */
+ edac_mc_find_csrow_by_page(mci, page);
+ printk(KERN_WARNING
+ "MC%d: CE page 0x%lx, row %d : Memory read retry\n",
+ mci->mc_idx, (long unsigned int) page, row);
+}
+
+static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
+ u32 retry_add, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_process_ded_retry(mci, error, retry_add);
+}
+
+static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
+ int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ printk(KERN_WARNING "MC%d: Memory threshold CE\n",
+ mci->mc_idx);
+}
+
+static char *global_message[11] = {
+ "PCI Express C1", "PCI Express C", "PCI Express B1",
+ "PCI Express B", "PCI Express A1", "PCI Express A",
+ "DMA Controler", "HUB Interface", "System Bus",
+ "DRAM Controler", "Internal Buffer"
+};
+
+static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
+
+static void do_global_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 11; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void global_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_global_error(fatal, errors);
+}
+
+static char *hub_message[7] = {
+ "HI Address or Command Parity", "HI Illegal Access",
+ "HI Internal Parity", "Out of Range Access",
+ "HI Data Parity", "Enhanced Config Access",
+ "Hub Interface Target Abort"
+};
+
+static void do_hub_error(int fatal, u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError %s\n",
+ fatal_message[fatal], hub_message[i]);
+ }
+}
+
+static inline void hub_error(int fatal, u8 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_hub_error(fatal, errors);
+}
+
+static char *membuf_message[4] = {
+ "Internal PMWB to DRAM parity",
+ "Internal PMWB to System Bus Parity",
+ "Internal System Bus or IO to PMWB Parity",
+ "Internal DRAM to PMWB Parity"
+};
+
+static void do_membuf_error(u8 errors)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "Non-Fatal Error %s\n",
+ membuf_message[i]);
+ }
+}
+
+static inline void membuf_error(u8 errors, int *error_found, int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_membuf_error(errors);
+}
+
+#if 0
+char *sysbus_message[10] = {
+ "Addr or Request Parity",
+ "Data Strobe Glitch",
+ "Addr Strobe Glitch",
+ "Data Parity",
+ "Addr Above TOM",
+ "Non DRAM Lock Error",
+ "MCERR", "BINIT",
+ "Memory Parity",
+ "IO Subsystem Parity"
+};
+#endif /* 0 */
+
+static void do_sysbus_error(int fatal, u32 errors)
+{
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if (errors & (1 << i))
+ printk(KERN_WARNING "%sError System Bus %s\n",
+ fatal_message[fatal], global_message[i]);
+ }
+}
+
+static inline void sysbus_error(int fatal, u32 errors, int *error_found,
+ int handle_error)
+{
+ *error_found = 1;
+
+ if (handle_error)
+ do_sysbus_error(fatal, errors);
+}
+
+static void e752x_check_hub_interface (struct e752x_error_info *info,
+ int *error_found, int handle_error)
+{
+ u8 stat8;
+
+ //pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
+ stat8 = info->hi_ferr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if(stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+ //pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
+ stat8 = info->hi_nerr;
+ if(stat8 & 0x7f) { /* Error, so process */
+ stat8 &= 0x7f;
+ if (stat8 & 0x2b)
+ hub_error(1, stat8 & 0x2b, error_found, handle_error);
+ if(stat8 & 0x54)
+ hub_error(0, stat8 & 0x54, error_found, handle_error);
+ }
+}
+
+static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u32 stat32, error32;
+
+ //pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32);
+ stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16);
+
+ if (stat32 == 0)
+ return; /* no errors */
+
+ error32 = (stat32 >> 16) & 0x3ff;
+ stat32 = stat32 & 0x3ff;
+ if(stat32 & 0x083)
+ sysbus_error(1, stat32 & 0x083, error_found, handle_error);
+ if(stat32 & 0x37c)
+ sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
+ if(error32 & 0x083)
+ sysbus_error(1, error32 & 0x083, error_found, handle_error);
+ if(error32 & 0x37c)
+ sysbus_error(0, error32 & 0x37c, error_found, handle_error);
+}
+
+static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
+ int handle_error)
+{
+ u8 stat8;
+
+ stat8 = info->buf_ferr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+ stat8 = info->buf_nerr;
+ if (stat8 & 0x0f) { /* Error, so process */
+ stat8 &= 0x0f;
+ membuf_error(stat8, error_found, handle_error);
+ }
+}
+
+static void e752x_check_dram (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int *error_found, int handle_error)
+{
+ u16 error_one, error_next;
+
+ error_one = info->dram_ferr;
+ error_next = info->dram_nerr;
+
+ /* decode and report errors */
+ if(error_one & 0x0101) /* check first error correctable */
+ process_ce(mci, error_one, info->dram_sec1_add,
+ info->dram_sec1_syndrome, error_found,
+ handle_error);
+
+ if(error_next & 0x0101) /* check next error correctable */
+ process_ce(mci, error_next, info->dram_sec2_add,
+ info->dram_sec2_syndrome, error_found,
+ handle_error);
+
+ if(error_one & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_next & 0x4040)
+ process_ue_no_info_wr(mci, error_found, handle_error);
+
+ if(error_one & 0x2020)
+ process_ded_retry(mci, error_one, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_next & 0x2020)
+ process_ded_retry(mci, error_next, info->dram_retr_add,
+ error_found, handle_error);
+
+ if(error_one & 0x0808)
+ process_threshold_ce(mci, error_one, error_found,
+ handle_error);
+
+ if(error_next & 0x0808)
+ process_threshold_ce(mci, error_next, error_found,
+ handle_error);
+
+ if(error_one & 0x0606)
+ process_ue(mci, error_one, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+
+ if(error_next & 0x0606)
+ process_ue(mci, error_next, info->dram_ded_add,
+ info->dram_scrb_add, error_found, handle_error);
+}
+
+static void e752x_get_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info)
+{
+ struct pci_dev *dev;
+ struct e752x_pvt *pvt;
+
+ memset(info, 0, sizeof(*info));
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ dev = pvt->dev_d0f1;
+
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
+
+ if (info->ferr_global) {
+ pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
+ pci_read_config_word(dev, E752X_SYSBUS_FERR,
+ &info->sysbus_ferr);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
+ pci_read_config_word(dev, E752X_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD,
+ &info->dram_sec1_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME,
+ &info->dram_sec1_syndrome);
+ pci_read_config_dword(dev, E752X_DRAM_DED_ADD,
+ &info->dram_ded_add);
+ pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD,
+ &info->dram_scrb_add);
+ pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
+ &info->dram_retr_add);
+
+ if (info->hi_ferr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_FERR,
+ info->hi_ferr);
+
+ if (info->sysbus_ferr)
+ pci_write_config_word(dev, E752X_SYSBUS_FERR,
+ info->sysbus_ferr);
+
+ if (info->buf_ferr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_FERR,
+ info->buf_ferr);
+
+ if (info->dram_ferr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
+ info->dram_ferr, info->dram_ferr);
+
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL,
+ info->ferr_global);
+ }
+
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
+
+ if (info->nerr_global) {
+ pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
+ pci_read_config_word(dev, E752X_SYSBUS_NERR,
+ &info->sysbus_nerr);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
+ pci_read_config_word(dev, E752X_DRAM_NERR,
+ &info->dram_nerr);
+ pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD,
+ &info->dram_sec2_add);
+ pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME,
+ &info->dram_sec2_syndrome);
+
+ if (info->hi_nerr & 0x7f)
+ pci_write_config_byte(dev, E752X_HI_NERR,
+ info->hi_nerr);
+
+ if (info->sysbus_nerr)
+ pci_write_config_word(dev, E752X_SYSBUS_NERR,
+ info->sysbus_nerr);
+
+ if (info->buf_nerr & 0x0f)
+ pci_write_config_byte(dev, E752X_BUF_NERR,
+ info->buf_nerr);
+
+ if (info->dram_nerr)
+ pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
+ info->dram_nerr, info->dram_nerr);
+
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL,
+ info->nerr_global);
+ }
+}
+
+static int e752x_process_error_info (struct mem_ctl_info *mci,
+ struct e752x_error_info *info, int handle_errors)
+{
+ u32 error32, stat32;
+ int error_found;
+
+ error_found = 0;
+ error32 = (info->ferr_global >> 18) & 0x3ff;
+ stat32 = (info->ferr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ error32 = (info->nerr_global >> 18) & 0x3ff;
+ stat32 = (info->nerr_global >> 4) & 0x7ff;
+
+ if (error32)
+ global_error(1, error32, &error_found, handle_errors);
+
+ if (stat32)
+ global_error(0, stat32, &error_found, handle_errors);
+
+ e752x_check_hub_interface(info, &error_found, handle_errors);
+ e752x_check_sysbus(info, &error_found, handle_errors);
+ e752x_check_membuf(info, &error_found, handle_errors);
+ e752x_check_dram(mci, info, &error_found, handle_errors);
+ return error_found;
+}
+
+static void e752x_check(struct mem_ctl_info *mci)
+{
+ struct e752x_error_info info;
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e752x_get_error_info(mci, &info);
+ e752x_process_error_info(mci, &info, 1);
+}
+
+static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data, stat;
+ u32 stat32;
+ u16 stat16;
+ u8 stat8;
+ struct mem_ctl_info *mci = NULL;
+ struct e752x_pvt *pvt = NULL;
+ u16 ddrcsr;
+ u32 drc;
+ int drc_chan; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg; /* DRB granularity 0=64mb,1=128mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+ struct pci_dev *pres_dev;
+ struct pci_dev *dev = NULL;
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+ debugf0("Starting Probe1\n");
+
+ /* enable device 0 function 1 */
+ pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+ stat8 |= (1 << 5);
+ pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E752X_DRC, &drc);
+ pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr);
+ /* FIXME: should check >>12 or 0xf, true for all? */
+ /* Dual channel = 1, Single channel = 0 */
+ drc_chan = (((ddrcsr >> 12) & 3) == 3);
+ drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
+ EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pvt->dev_info = &e752x_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (pvt->bridge_ck == NULL)
+ pvt->bridge_ck = pci_scan_single_device(pdev->bus,
+ PCI_DEVFN(0, 1));
+ if (pvt->bridge_ck == NULL) {
+ printk(KERN_ERR "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
+ goto fail;
+ }
+ pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+ mci->edac_check = e752x_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E752X_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address for
+ * each DRAM row with a granularity of 64 or 128MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ mem_dev = (mem_dev == 2);
+ pci_read_config_byte(mci->pdev, E752X_DRB + index, &value);
+ /* convert a 128 or 64 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ /* Fill in the memory map table */
+ {
+ u8 value;
+ u8 last = 0;
+ u8 row = 0;
+ for (index = 0; index < 8; index += 2) {
+
+ pci_read_config_byte(mci->pdev, E752X_DRB + index,
+ &value);
+ /* test if there is a dimm in this slot */
+ if (value == last) {
+ /* no dimm in the slot, so flag it as empty */
+ pvt->map[index] = 0xff;
+ pvt->map[index + 1] = 0xff;
+ } else { /* there is a dimm in the slot */
+ pvt->map[index] = row;
+ row++;
+ last = value;
+ /* test the next value to see if the dimm is
+ double sided */
+ pci_read_config_byte(mci->pdev,
+ E752X_DRB + index + 1,
+ &value);
+ pvt->map[index + 1] = (value == last) ?
+ 0xff : /* the dimm is single sided,
+ so flag as empty */
+ row; /* this is a double sided dimm
+ to save the next row # */
+ row++;
+ last = value;
+ }
+ }
+ }
+
+ /* set the map type. 1 = normal, 0 = reversed */
+ pci_read_config_byte(mci->pdev, E752X_DRM, &stat8);
+ pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E752X_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* Walk through the PCI table and clear errors */
+ switch (dev_idx) {
+ case E7520:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7520_0, NULL);
+ break;
+ case E7525:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7525_0, NULL);
+ break;
+ case E7320:
+ dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_7320_0, NULL);
+ break;
+ }
+
+
+ pvt->dev_d0f0 = dev;
+ for (pres_dev = dev;
+ ((struct pci_dev *) pres_dev->global_list.next != dev);
+ pres_dev = (struct pci_dev *) pres_dev->global_list.next) {
+ pci_read_config_dword(pres_dev, PCI_COMMAND, &stat32);
+ stat = (u16) (stat32 >> 16);
+ /* clear any error bits */
+ if (stat32 & ((1 << 6) + (1 << 8)))
+ pci_write_config_word(pres_dev, PCI_STATUS, stat);
+ }
+ /* find the error reporting device and clear errors */
+ dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
+ /* Turn off error disable & SMI in case the BIOS turned it on */
+ pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
+ pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
+ pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
+ /* clear other MCH errors */
+ pci_read_config_dword(dev, E752X_FERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_FERR_GLOBAL, stat32);
+ pci_read_config_dword(dev, E752X_NERR_GLOBAL, &stat32);
+ pci_write_config_dword(dev, E752X_NERR_GLOBAL, stat32);
+ pci_read_config_byte(dev, E752X_HI_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_FERR, stat8);
+ pci_read_config_byte(dev, E752X_HI_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_HI_NERR, stat8);
+ pci_read_config_dword(dev, E752X_SYSBUS_FERR, &stat32);
+ pci_write_config_dword(dev, E752X_SYSBUS_FERR, stat32);
+ pci_read_config_byte(dev, E752X_BUF_FERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_FERR, stat8);
+ pci_read_config_byte(dev, E752X_BUF_NERR, &stat8);
+ pci_write_config_byte(dev, E752X_BUF_NERR, stat8);
+ pci_read_config_word(dev, E752X_DRAM_FERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_FERR, stat16);
+ pci_read_config_word(dev, E752X_DRAM_NERR, &stat16);
+ pci_write_config_word(dev, E752X_DRAM_NERR, stat16);
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci) {
+ if (pvt->dev_d0f0)
+ pci_dev_put(pvt->dev_d0f0);
+ if (pvt->dev_d0f1)
+ pci_dev_put(pvt->dev_d0f1);
+ if (pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit e752x_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ return e752x_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e752x_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e752x_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ pvt = (struct e752x_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->dev_d0f0);
+ pci_dev_put(pvt->dev_d0f1);
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7520},
+ {PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7525},
+ {PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7320},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
+
+
+static struct pci_driver e752x_driver = {
+ name: BS_MOD_STR,
+ probe: e752x_init_one,
+ remove: __devexit_p(e752x_remove_one),
+ id_table: e752x_pci_tbl,
+};
+
+
+static int __init e752x_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&e752x_driver);
+ return (pci_rc < 0) ? pci_rc : 0;
+}
+
+
+static void __exit e752x_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&e752x_driver);
+}
+
+
+module_init(e752x_init);
+module_exit(e752x_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
new file mode 100644
index 000000000000..d5e320dfc66f
--- /dev/null
+++ b/drivers/edac/e7xxx_edac.c
@@ -0,0 +1,558 @@
+/*
+ * Intel e7xxx Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * See "enum e7xxx_chips" below for supported chipsets
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Contributors:
+ * Eric Biederman (Linux Networx)
+ * Tom Zimmerman (Linux Networx)
+ * Jim Garlick (Lawrence Livermore National Labs)
+ * Dave Peterson (Lawrence Livermore National Labs)
+ * That One Guy (Some other place)
+ * Wang Zhenyu (intel.com)
+ *
+ * $Id: edac_e7xxx.c,v 1.5.2.9 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_0
+#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
+#endif /* PCI_DEVICE_ID_INTEL_7205_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7205_1_ERR
+#define PCI_DEVICE_ID_INTEL_7205_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7205_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_0
+#define PCI_DEVICE_ID_INTEL_7500_0 0x2540
+#endif /* PCI_DEVICE_ID_INTEL_7500_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7500_1_ERR
+#define PCI_DEVICE_ID_INTEL_7500_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7500_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_0
+#define PCI_DEVICE_ID_INTEL_7501_0 0x254c
+#endif /* PCI_DEVICE_ID_INTEL_7501_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7501_1_ERR
+#define PCI_DEVICE_ID_INTEL_7501_1_ERR 0x2541
+#endif /* PCI_DEVICE_ID_INTEL_7501_1_ERR */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_0
+#define PCI_DEVICE_ID_INTEL_7505_0 0x2550
+#endif /* PCI_DEVICE_ID_INTEL_7505_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_7505_1_ERR
+#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551
+#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */
+
+
+#define E7XXX_NR_CSROWS 8 /* number of csrows */
+#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */
+
+
+/* E7XXX register addresses - device 0 function 0 */
+#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */
+#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */
+ /*
+ * 31 Device width row 7 0=x8 1=x4
+ * 27 Device width row 6
+ * 23 Device width row 5
+ * 19 Device width row 4
+ * 15 Device width row 3
+ * 11 Device width row 2
+ * 7 Device width row 1
+ * 3 Device width row 0
+ */
+#define E7XXX_DRC 0x7C /* DRAM controller mode reg (32b) */
+ /*
+ * 22 Number channels 0=1,1=2
+ * 19:18 DRB Granularity 32/64MB
+ */
+#define E7XXX_TOLM 0xC4 /* DRAM top of low memory reg (16b) */
+#define E7XXX_REMAPBASE 0xC6 /* DRAM remap base address reg (16b) */
+#define E7XXX_REMAPLIMIT 0xC8 /* DRAM remap limit address reg (16b) */
+
+/* E7XXX register addresses - device 0 function 1 */
+#define E7XXX_DRAM_FERR 0x80 /* DRAM first error register (8b) */
+#define E7XXX_DRAM_NERR 0x82 /* DRAM next error register (8b) */
+#define E7XXX_DRAM_CELOG_ADD 0xA0 /* DRAM first correctable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_UELOG_ADD 0xB0 /* DRAM first uncorrectable memory */
+ /* error address register (32b) */
+ /*
+ * 31:28 Reserved
+ * 27:6 CE address (4k block 33:12)
+ * 5:0 Reserved
+ */
+#define E7XXX_DRAM_CELOG_SYNDROME 0xD0 /* DRAM first correctable memory */
+ /* error syndrome register (16b) */
+
+enum e7xxx_chips {
+ E7500 = 0,
+ E7501,
+ E7505,
+ E7205,
+};
+
+
+struct e7xxx_pvt {
+ struct pci_dev *bridge_ck;
+ u32 tolm;
+ u32 remapbase;
+ u32 remaplimit;
+ const struct e7xxx_dev_info *dev_info;
+};
+
+
+struct e7xxx_dev_info {
+ u16 err_dev;
+ const char *ctl_name;
+};
+
+
+struct e7xxx_error_info {
+ u8 dram_ferr;
+ u8 dram_nerr;
+ u32 dram_celog_add;
+ u16 dram_celog_syndrome;
+ u32 dram_uelog_add;
+};
+
+static const struct e7xxx_dev_info e7xxx_devs[] = {
+ [E7500] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
+ .ctl_name = "E7500"},
+ [E7501] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
+ .ctl_name = "E7501"},
+ [E7505] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
+ .ctl_name = "E7505"},
+ [E7205] = {
+ .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
+ .ctl_name = "E7205"},
+};
+
+
+/* FIXME - is this valid for both SECDED and S4ECD4ED? */
+static inline int e7xxx_find_channel(u16 syndrome)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((syndrome & 0xff00) == 0)
+ return 0;
+ if ((syndrome & 0x00ff) == 0)
+ return 1;
+ if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
+ return 0;
+ return 1;
+}
+
+
+static unsigned long
+ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
+{
+ u32 remap;
+ struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if ((page < pvt->tolm) ||
+ ((page >= 0x100000) && (page < pvt->remapbase)))
+ return page;
+ remap = (page - pvt->tolm) + pvt->remapbase;
+ if (remap < pvt->remaplimit)
+ return remap;
+ printk(KERN_ERR "Invalid page %lx - out of range\n", page);
+ return pvt->tolm - 1;
+}
+
+
+static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_1b, page;
+ u16 syndrome;
+ int row;
+ int channel;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_1b = info->dram_celog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ page = error_1b >> 6; /* convert the address to 4k page */
+ /* read the syndrome */
+ syndrome = info->dram_celog_syndrome;
+ /* FIXME - check for -1 */
+ row = edac_mc_find_csrow_by_page(mci, page);
+ /* convert syndrome to channel */
+ channel = e7xxx_find_channel(syndrome);
+ edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
+ "e7xxx CE");
+}
+
+
+static void process_ce_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
+}
+
+
+static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
+{
+ u32 error_2b, block_page;
+ int row;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* read the error address */
+ error_2b = info->dram_uelog_add;
+ /* FIXME - should use PAGE_SHIFT */
+ block_page = error_2b >> 6; /* convert to 4k address */
+ row = edac_mc_find_csrow_by_page(mci, block_page);
+ edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
+}
+
+
+static void process_ue_no_info(struct mem_ctl_info *mci)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
+}
+
+
+static void e7xxx_get_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info)
+{
+ struct e7xxx_pvt *pvt;
+
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
+ &info->dram_ferr);
+ pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
+ &info->dram_nerr);
+
+ if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
+ &info->dram_celog_add);
+ pci_read_config_word(pvt->bridge_ck,
+ E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
+ }
+
+ if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
+ pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
+ &info->dram_uelog_add);
+
+ if (info->dram_ferr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
+ 0x03);
+
+ if (info->dram_nerr & 3)
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
+ 0x03);
+}
+
+
+static int e7xxx_process_error_info (struct mem_ctl_info *mci,
+ struct e7xxx_error_info *info, int handle_errors)
+{
+ int error_found;
+
+ error_found = 0;
+
+ /* decode and report errors */
+ if (info->dram_ferr & 1) { /* check first error correctable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ce(mci, info);
+ }
+
+ if (info->dram_ferr & 2) { /* check first error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors)
+ process_ue(mci, info);
+ }
+
+ if (info->dram_nerr & 1) { /* check next error correctable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 1)
+ process_ce_no_info(mci);
+ else
+ process_ce(mci, info);
+ }
+ }
+
+ if (info->dram_nerr & 2) { /* check next error uncorrectable */
+ error_found = 1;
+
+ if (handle_errors) {
+ if (info->dram_ferr & 2)
+ process_ue_no_info(mci);
+ else
+ process_ue(mci, info);
+ }
+ }
+
+ return error_found;
+}
+
+
+static void e7xxx_check(struct mem_ctl_info *mci)
+{
+ struct e7xxx_error_info info;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ e7xxx_get_error_info(mci, &info);
+ e7xxx_process_error_info(mci, &info, 1);
+}
+
+
+static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ u16 pci_data;
+ struct mem_ctl_info *mci = NULL;
+ struct e7xxx_pvt *pvt = NULL;
+ u32 drc;
+ int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */
+ int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */
+ int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+ u32 dra;
+ unsigned long last_cumul_size;
+
+
+ debugf0("MC: " __FILE__ ": %s(): mci\n", __func__);
+
+ /* need to find out the number of channels */
+ pci_read_config_dword(pdev, E7XXX_DRC, &drc);
+ /* only e7501 can be single channel */
+ if (dev_idx == E7501) {
+ drc_chan = ((drc >> 22) & 0x1);
+ drc_drbg = (drc >> 18) & 0x3;
+ }
+ drc_ddim = (drc >> 20) & 0x3;
+
+ mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->mtype_cap = MEM_FLAG_RDDR;
+ mci->edac_ctl_cap =
+ EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
+ /* FIXME - what if different memory types are in different csrows? */
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.9 $";
+ mci->pdev = pdev;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pvt->dev_info = &e7xxx_devs[dev_idx];
+ pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pvt->dev_info->err_dev,
+ pvt->bridge_ck);
+ if (!pvt->bridge_ck) {
+ printk(KERN_ERR
+ "MC: error reporting device not found:"
+ "vendor %x device 0x%x (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): more mci init\n", __func__);
+ mci->ctl_name = pvt->dev_info->ctl_name;
+
+ mci->edac_check = e7xxx_check;
+ mci->ctl_page_to_phys = ctl_page_to_phys;
+
+ /* find out the device types */
+ pci_read_config_dword(pdev, E7XXX_DRA, &dra);
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ /* mem_dev 0=x8, 1=x4 */
+ int mem_dev = (dra >> (index * 4 + 3)) & 0x1;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_byte(mci->pdev, E7XXX_DRB + index, &value);
+ /* convert a 64 or 32 MiB DRB to a page size. */
+ cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
+ csrow->mtype = MEM_RDDR; /* only one type supported */
+ csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
+
+ /*
+ * if single channel or x8 devices then SECDED
+ * if dual channel and x4 then S4ECD4ED
+ */
+ if (drc_ddim) {
+ if (drc_chan && mem_dev) {
+ csrow->edac_mode = EDAC_S4ECD4ED;
+ mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
+ } else {
+ csrow->edac_mode = EDAC_SECDED;
+ mci->edac_cap |= EDAC_FLAG_SECDED;
+ }
+ } else
+ csrow->edac_mode = EDAC_NONE;
+ }
+
+ mci->edac_cap |= EDAC_FLAG_NONE;
+
+ debugf3("MC: " __FILE__ ": %s(): tolm, remapbase, remaplimit\n",
+ __func__);
+ /* load the top of low memory, remap base, and remap limit vars */
+ pci_read_config_word(mci->pdev, E7XXX_TOLM, &pci_data);
+ pvt->tolm = ((u32) pci_data) << 4;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPBASE, &pci_data);
+ pvt->remapbase = ((u32) pci_data) << 14;
+ pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
+ pvt->remaplimit = ((u32) pci_data) << 14;
+ printk("tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
+ pvt->remapbase, pvt->remaplimit);
+
+ /* clear any pending errors, or initial state bits */
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
+ pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
+
+ if (edac_mc_add_mc(mci) != 0) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci != NULL) {
+ if(pvt != NULL && pvt->bridge_ck)
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit
+e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up and enable device */
+ return pci_enable_device(pdev) ?
+ -EIO : e7xxx_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct e7xxx_pvt *pvt;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != 0) &&
+ edac_mc_del_mc(mci)) {
+ pvt = (struct e7xxx_pvt *) mci->pvt_info;
+ pci_dev_put(pvt->bridge_ck);
+ edac_mc_free(mci);
+ }
+}
+
+
+static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7205},
+ {PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7500},
+ {PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7501},
+ {PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ E7505},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
+
+
+static struct pci_driver e7xxx_driver = {
+ .name = BS_MOD_STR,
+ .probe = e7xxx_init_one,
+ .remove = __devexit_p(e7xxx_remove_one),
+ .id_table = e7xxx_pci_tbl,
+};
+
+
+static int __init e7xxx_init(void)
+{
+ return pci_register_driver(&e7xxx_driver);
+}
+
+
+static void __exit e7xxx_exit(void)
+{
+ pci_unregister_driver(&e7xxx_driver);
+}
+
+module_init(e7xxx_init);
+module_exit(e7xxx_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
new file mode 100644
index 000000000000..4be9bd0a1267
--- /dev/null
+++ b/drivers/edac/edac_mc.c
@@ -0,0 +1,2209 @@
+/*
+ * edac_mc kernel module
+ * (C) 2005 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * Modified by Dave Peterson and Doug Thompson
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/highmem.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/sysdev.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/edac.h>
+
+#include "edac_mc.h"
+
+#define EDAC_MC_VERSION "edac_mc Ver: 2.0.0 " __DATE__
+
+#ifdef CONFIG_EDAC_DEBUG
+/* Values of 0 to 4 will generate output */
+int edac_debug_level = 1;
+EXPORT_SYMBOL(edac_debug_level);
+#endif
+
+/* EDAC Controls, setable by module parameter, and sysfs */
+static int log_ue = 1;
+static int log_ce = 1;
+static int panic_on_ue = 1;
+static int poll_msec = 1000;
+
+static int check_pci_parity = 0; /* default YES check PCI parity */
+static int panic_on_pci_parity; /* default no panic on PCI Parity */
+static atomic_t pci_parity_count = ATOMIC_INIT(0);
+
+/* lock to memory controller's control array */
+static DECLARE_MUTEX(mem_ctls_mutex);
+static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+
+/* Structure of the whitelist and blacklist arrays */
+struct edac_pci_device_list {
+ unsigned int vendor; /* Vendor ID */
+ unsigned int device; /* Deviice ID */
+};
+
+
+#define MAX_LISTED_PCI_DEVICES 32
+
+/* List of PCI devices (vendor-id:device-id) that should be skipped */
+static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
+static int pci_blacklist_count;
+
+/* List of PCI devices (vendor-id:device-id) that should be scanned */
+static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
+static int pci_whitelist_count ;
+
+/* START sysfs data and methods */
+
+static const char *mem_types[] = {
+ [MEM_EMPTY] = "Empty",
+ [MEM_RESERVED] = "Reserved",
+ [MEM_UNKNOWN] = "Unknown",
+ [MEM_FPM] = "FPM",
+ [MEM_EDO] = "EDO",
+ [MEM_BEDO] = "BEDO",
+ [MEM_SDR] = "Unbuffered-SDR",
+ [MEM_RDR] = "Registered-SDR",
+ [MEM_DDR] = "Unbuffered-DDR",
+ [MEM_RDDR] = "Registered-DDR",
+ [MEM_RMBS] = "RMBS"
+};
+
+static const char *dev_types[] = {
+ [DEV_UNKNOWN] = "Unknown",
+ [DEV_X1] = "x1",
+ [DEV_X2] = "x2",
+ [DEV_X4] = "x4",
+ [DEV_X8] = "x8",
+ [DEV_X16] = "x16",
+ [DEV_X32] = "x32",
+ [DEV_X64] = "x64"
+};
+
+static const char *edac_caps[] = {
+ [EDAC_UNKNOWN] = "Unknown",
+ [EDAC_NONE] = "None",
+ [EDAC_RESERVED] = "Reserved",
+ [EDAC_PARITY] = "PARITY",
+ [EDAC_EC] = "EC",
+ [EDAC_SECDED] = "SECDED",
+ [EDAC_S2ECD2ED] = "S2ECD2ED",
+ [EDAC_S4ECD4ED] = "S4ECD4ED",
+ [EDAC_S8ECD8ED] = "S8ECD8ED",
+ [EDAC_S16ECD16ED] = "S16ECD16ED"
+};
+
+
+/* sysfs object: /sys/devices/system/edac */
+static struct sysdev_class edac_class = {
+ set_kset_name("edac"),
+};
+
+/* sysfs objects:
+ * /sys/devices/system/edac/mc
+ * /sys/devices/system/edac/pci
+ */
+static struct kobject edac_memctrl_kobj;
+static struct kobject edac_pci_kobj;
+
+/*
+ * /sys/devices/system/edac/mc;
+ * data structures and methods
+ */
+static ssize_t memctrl_string_show(void *ptr, char *buffer)
+{
+ char *value = (char*) ptr;
+ return sprintf(buffer, "%s\n", value);
+}
+
+static ssize_t memctrl_int_show(void *ptr, char *buffer)
+{
+ int *value = (int*) ptr;
+ return sprintf(buffer, "%d\n", *value);
+}
+
+static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = (int*) ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer, NULL, 0);
+
+ return count;
+}
+
+struct memctrl_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *, size_t);
+};
+
+/* Set of show/store abstract level functions for memory control object */
+static ssize_t
+memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->show)
+ return memctrl_dev->show(memctrl_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t
+memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct memctrl_dev_attribute *memctrl_dev;
+ memctrl_dev = (struct memctrl_dev_attribute*)attr;
+
+ if (memctrl_dev->store)
+ return memctrl_dev->store(memctrl_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops memctrlfs_ops = {
+ .show = memctrl_dev_show,
+ .store = memctrl_dev_store
+};
+
+#define MEMCTRL_ATTR(_name,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct memctrl_dev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id> attribute f*/
+MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
+
+/* csrow<id> control files */
+MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
+
+
+/* Base Attributes of the memory ECC object */
+static struct memctrl_dev_attribute *memctrl_attr[] = {
+ &attr_panic_on_ue,
+ &attr_log_ue,
+ &attr_log_ce,
+ &attr_poll_msec,
+ &attr_mc_version,
+ NULL,
+};
+
+/* Main MC kobject release() function */
+static void edac_memctrl_master_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_memctrl = {
+ .release = edac_memctrl_master_release,
+ .sysfs_ops = &memctrlfs_ops,
+ .default_attrs = (struct attribute **) memctrl_attr,
+};
+
+
+/* Initialize the main sysfs entries for edac:
+ * /sys/devices/system/edac
+ *
+ * and children
+ *
+ * Return: 0 SUCCESS
+ * !0 FAILURE
+ */
+static int edac_sysfs_memctrl_setup(void)
+{
+ int err=0;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* create the /sys/devices/system/edac directory */
+ err = sysdev_class_register(&edac_class);
+ if (!err) {
+ /* Init the MC's kobject */
+ memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
+ kobject_init(&edac_memctrl_kobj);
+
+ edac_memctrl_kobj.parent = &edac_class.kset.kobj;
+ edac_memctrl_kobj.ktype = &ktype_memctrl;
+
+ /* generate sysfs "..../edac/mc" */
+ err = kobject_set_name(&edac_memctrl_kobj,"mc");
+ if (!err) {
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_memctrl_kobj);
+ if (err) {
+ debugf1("Failed to register '.../edac/mc'\n");
+ } else {
+ debugf1("Registered '.../edac/mc' kobject\n");
+ }
+ }
+ } else {
+ debugf1(KERN_WARNING "__FILE__ %s() error=%d\n", __func__,err);
+ }
+
+ return err;
+}
+
+/*
+ * MC teardown:
+ * the '..../edac/mc' kobject followed by '..../edac' itself
+ */
+static void edac_sysfs_memctrl_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Unregister the MC's kobject */
+ kobject_unregister(&edac_memctrl_kobj);
+
+ /* release the master edac mc kobject */
+ kobject_put(&edac_memctrl_kobj);
+
+ /* Unregister the 'edac' object */
+ sysdev_class_unregister(&edac_class);
+}
+
+/*
+ * /sys/devices/system/edac/pci;
+ * data structures and methods
+ */
+
+struct list_control {
+ struct edac_pci_device_list *list;
+ int *count;
+};
+
+/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
+static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ char *p = buffer;
+ int len=0;
+ int i;
+
+ listctl = ptr;
+ list = listctl->list;
+
+ for (i = 0; i < *(listctl->count); i++, list++ ) {
+ if (len > 0)
+ len += snprintf(p + len, (PAGE_SIZE-len), ",");
+
+ len += snprintf(p + len,
+ (PAGE_SIZE-len),
+ "%x:%x",
+ list->vendor,list->device);
+ }
+
+ len += snprintf(p + len,(PAGE_SIZE-len), "\n");
+
+ return (ssize_t) len;
+}
+
+/**
+ *
+ * Scan string from **s to **e looking for one 'vendor:device' tuple
+ * where each field is a hex value
+ *
+ * return 0 if an entry is NOT found
+ * return 1 if an entry is found
+ * fill in *vendor_id and *device_id with values found
+ *
+ * In both cases, make sure *s has been moved forward toward *e
+ */
+static int parse_one_device(const char **s,const char **e,
+ unsigned int *vendor_id, unsigned int *device_id)
+{
+ const char *runner, *p;
+
+ /* if null byte, we are done */
+ if (!**s) {
+ (*s)++; /* keep *s moving */
+ return 0;
+ }
+
+ /* skip over newlines & whitespace */
+ if ((**s == '\n') || isspace(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ if (!isxdigit(**s)) {
+ (*s)++;
+ return 0;
+ }
+
+ /* parse vendor_id */
+ runner = *s;
+ while (runner < *e) {
+ /* scan for vendor:device delimiter */
+ if (*runner == ':') {
+ *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
+ runner = p + 1;
+ break;
+ }
+ runner++;
+ }
+
+ if (!isxdigit(*runner)) {
+ *s = ++runner;
+ return 0;
+ }
+
+ /* parse device_id */
+ if (runner < *e) {
+ *device_id = simple_strtol((char*)runner, (char**)&p, 16);
+ runner = p;
+ }
+
+ *s = runner;
+
+ return 1;
+}
+
+static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
+ size_t count)
+{
+ struct list_control *listctl;
+ struct edac_pci_device_list *list;
+ unsigned int vendor_id, device_id;
+ const char *s, *e;
+ int *index;
+
+ s = (char*)buffer;
+ e = s + count;
+
+ listctl = ptr;
+ list = listctl->list;
+ index = listctl->count;
+
+ *index = 0;
+ while (*index < MAX_LISTED_PCI_DEVICES) {
+
+ if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
+ list[ *index ].vendor = vendor_id;
+ list[ *index ].device = device_id;
+ (*index)++;
+ }
+
+ /* check for all data consume */
+ if (s >= e)
+ break;
+ }
+
+ return count;
+}
+
+static ssize_t edac_pci_int_show(void *ptr, char *buffer)
+{
+ int *value = ptr;
+ return sprintf(buffer,"%d\n",*value);
+}
+
+static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
+{
+ int *value = ptr;
+
+ if (isdigit(*buffer))
+ *value = simple_strtoul(buffer,NULL,0);
+
+ return count;
+}
+
+struct edac_pci_dev_attribute {
+ struct attribute attr;
+ void *value;
+ ssize_t (*show)(void *,char *);
+ ssize_t (*store)(void *, const char *,size_t);
+};
+
+/* Set of show/store abstract level functions for PCI Parity object */
+static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->show(edac_pci_dev->value, buffer);
+ return -EIO;
+}
+
+static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct edac_pci_dev_attribute *edac_pci_dev;
+ edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
+
+ if (edac_pci_dev->show)
+ return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops edac_pci_sysfs_ops = {
+ .show = edac_pci_dev_show,
+ .store = edac_pci_dev_store
+};
+
+
+#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = &_name, \
+ .show = _show, \
+ .store = _store, \
+};
+
+#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \
+struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .value = _data, \
+ .show = _show, \
+ .store = _store, \
+};
+
+static struct list_control pci_whitelist_control = {
+ .list = pci_whitelist,
+ .count = &pci_whitelist_count
+};
+
+static struct list_control pci_blacklist_control = {
+ .list = pci_blacklist,
+ .count = &pci_blacklist_count
+};
+
+/* whitelist attribute */
+EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
+ &pci_whitelist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
+ &pci_blacklist_control,
+ S_IRUGO|S_IWUSR,
+ edac_pci_list_string_show,
+ edac_pci_list_string_store);
+
+/* PCI Parity control files */
+EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
+EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
+
+/* Base Attributes of the memory ECC object */
+static struct edac_pci_dev_attribute *edac_pci_attr[] = {
+ &edac_pci_attr_check_pci_parity,
+ &edac_pci_attr_panic_on_pci_parity,
+ &edac_pci_attr_pci_parity_count,
+ &edac_pci_attr_pci_parity_whitelist,
+ &edac_pci_attr_pci_parity_blacklist,
+ NULL,
+};
+
+/* No memory to release */
+static void edac_pci_release(struct kobject *kobj)
+{
+ debugf1("EDAC PCI: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_edac_pci = {
+ .release = edac_pci_release,
+ .sysfs_ops = &edac_pci_sysfs_ops,
+ .default_attrs = (struct attribute **) edac_pci_attr,
+};
+
+/**
+ * edac_sysfs_pci_setup()
+ *
+ */
+static int edac_sysfs_pci_setup(void)
+{
+ int err;
+
+ debugf1("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
+
+ kobject_init(&edac_pci_kobj);
+ edac_pci_kobj.parent = &edac_class.kset.kobj;
+ edac_pci_kobj.ktype = &ktype_edac_pci;
+
+ err = kobject_set_name(&edac_pci_kobj, "pci");
+ if (!err) {
+ /* Instanstiate the csrow object */
+ /* FIXME: maybe new sysdev_create_subdir() */
+ err = kobject_register(&edac_pci_kobj);
+ if (err)
+ debugf1("Failed to register '.../edac/pci'\n");
+ else
+ debugf1("Registered '.../edac/pci' kobject\n");
+ }
+ return err;
+}
+
+
+static void edac_sysfs_pci_teardown(void)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ kobject_unregister(&edac_pci_kobj);
+ kobject_put(&edac_pci_kobj);
+}
+
+/* EDAC sysfs CSROW data structures and methods */
+
+/* Set of more detailed csrow<id> attribute show/store functions */
+static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
+ csrow->channels[0].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
+ csrow->channels[1].label);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 0) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[0].label, data, max_size);
+ csrow->channels[0].label[max_size] = '\0';
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
+ const char *data, size_t size)
+{
+ ssize_t max_size = 0;
+
+ if (csrow->nr_channels > 1) {
+ max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
+ strncpy(csrow->channels[1].label, data, max_size);
+ csrow->channels[1].label[max_size] = '\0';
+ }
+ return max_size;
+}
+
+static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ue_count);
+}
+
+static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", csrow->ce_count);
+}
+
+static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 0) {
+ size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
+{
+ ssize_t size = 0;
+
+ if (csrow->nr_channels > 1) {
+ size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
+ }
+ return size;
+}
+
+static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
+}
+
+static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", mem_types[csrow->mtype]);
+}
+
+static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", dev_types[csrow->dtype]);
+}
+
+static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
+{
+ return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
+}
+
+struct csrowdev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct csrow_info *,char *);
+ ssize_t (*store)(struct csrow_info *, const char *,size_t);
+};
+
+#define to_csrow(k) container_of(k, struct csrow_info, kobj)
+#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
+
+/* Set of show/store higher level functions for csrow objects */
+static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->show)
+ return csrowdev_attr->show(csrow, buffer);
+ return -EIO;
+}
+
+static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct csrow_info *csrow = to_csrow(kobj);
+ struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
+
+ if (csrowdev_attr->store)
+ return csrowdev_attr->store(csrow, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops csrowfs_ops = {
+ .show = csrowdev_show,
+ .store = csrowdev_store
+};
+
+#define CSROWDEV_ATTR(_name,_mode,_show,_store) \
+struct csrowdev_attribute attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* cwrow<id>/attribute files */
+CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
+CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
+CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
+CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
+CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
+CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
+CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
+CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
+
+/* control/attribute files */
+CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch0_dimm_label_show,
+ csrow_ch0_dimm_label_store);
+CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
+ csrow_ch1_dimm_label_show,
+ csrow_ch1_dimm_label_store);
+
+
+/* Attributes of the CSROW<id> object */
+static struct csrowdev_attribute *csrow_attr[] = {
+ &attr_dev_type,
+ &attr_mem_type,
+ &attr_edac_mode,
+ &attr_size_mb,
+ &attr_ue_count,
+ &attr_ce_count,
+ &attr_ch0_ce_count,
+ &attr_ch1_ce_count,
+ &attr_ch0_dimm_label,
+ &attr_ch1_dimm_label,
+ NULL,
+};
+
+
+/* No memory to release */
+static void edac_csrow_instance_release(struct kobject *kobj)
+{
+ debugf1("EDAC MC: " __FILE__ ": %s()\n", __func__);
+}
+
+static struct kobj_type ktype_csrow = {
+ .release = edac_csrow_instance_release,
+ .sysfs_ops = &csrowfs_ops,
+ .default_attrs = (struct attribute **) csrow_attr,
+};
+
+/* Create a CSROW object under specifed edac_mc_device */
+static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
+ struct csrow_info *csrow, int index )
+{
+ int err = 0;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ memset(&csrow->kobj, 0, sizeof(csrow->kobj));
+
+ /* generate ..../edac/mc/mc<id>/csrow<index> */
+
+ kobject_init(&csrow->kobj);
+ csrow->kobj.parent = edac_mci_kobj;
+ csrow->kobj.ktype = &ktype_csrow;
+
+ /* name this instance of csrow<id> */
+ err = kobject_set_name(&csrow->kobj,"csrow%d",index);
+ if (!err) {
+ /* Instanstiate the csrow object */
+ err = kobject_register(&csrow->kobj);
+ if (err)
+ debugf0("Failed to register CSROW%d\n",index);
+ else
+ debugf0("Registered CSROW%d\n",index);
+ }
+
+ return err;
+}
+
+/* sysfs data structures and methods for the MCI kobjects */
+
+static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
+ const char *data, size_t count )
+{
+ int row, chan;
+
+ mci->ue_noinfo_count = 0;
+ mci->ce_noinfo_count = 0;
+ mci->ue_count = 0;
+ mci->ce_count = 0;
+ for (row = 0; row < mci->nr_csrows; row++) {
+ struct csrow_info *ri = &mci->csrows[row];
+
+ ri->ue_count = 0;
+ ri->ce_count = 0;
+ for (chan = 0; chan < ri->nr_channels; chan++)
+ ri->channels[chan].ce_count = 0;
+ }
+ mci->start_time = jiffies;
+
+ return count;
+}
+
+static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_count);
+}
+
+static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_count);
+}
+
+static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ce_noinfo_count);
+}
+
+static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%d\n", mci->ue_noinfo_count);
+}
+
+static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
+}
+
+static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
+}
+
+static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
+{
+ return sprintf(data,"%s\n", mci->ctl_name);
+}
+
+static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
+ if ((edac_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", edac_caps[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_ctl_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
+ char *data)
+{
+ char *p = data;
+
+ p += mci_output_edac_cap(p,mci->edac_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
+{
+ char *p = buf;
+ int bit_idx;
+
+ for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
+ if ((mtype_cap >> bit_idx) & 0x1)
+ p += sprintf(p, "%s ", mem_types[bit_idx]);
+ }
+
+ return p - buf;
+}
+
+static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
+{
+ char *p = data;
+
+ p += mci_output_mtype_cap(p,mci->mtype_cap);
+ p += sprintf(p, "\n");
+
+ return p - data;
+}
+
+static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
+{
+ int total_pages, csrow_idx;
+
+ for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
+ csrow_idx++) {
+ struct csrow_info *csrow = &mci->csrows[csrow_idx];
+
+ if (!csrow->nr_pages)
+ continue;
+ total_pages += csrow->nr_pages;
+ }
+
+ return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages));
+}
+
+struct mcidev_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct mem_ctl_info *,char *);
+ ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
+};
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
+#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
+
+static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
+ char *buffer)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->show)
+ return mcidev_attr->show(mem_ctl_info, buffer);
+ return -EIO;
+}
+
+static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
+ struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
+
+ if (mcidev_attr->store)
+ return mcidev_attr->store(mem_ctl_info, buffer, count);
+ return -EIO;
+}
+
+static struct sysfs_ops mci_ops = {
+ .show = mcidev_show,
+ .store = mcidev_store
+};
+
+#define MCIDEV_ATTR(_name,_mode,_show,_store) \
+struct mcidev_attribute mci_attr_##_name = { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
+/* Control file */
+MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
+
+/* Attribute files */
+MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
+MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
+MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
+MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
+MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
+MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
+MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
+MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
+MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
+MCIDEV_ATTR(edac_current_capability,S_IRUGO,
+ mci_edac_current_capability_show,NULL);
+MCIDEV_ATTR(supported_mem_type,S_IRUGO,
+ mci_supported_mem_type_show,NULL);
+
+
+static struct mcidev_attribute *mci_attr[] = {
+ &mci_attr_reset_counters,
+ &mci_attr_module_name,
+ &mci_attr_mc_name,
+ &mci_attr_edac_capability,
+ &mci_attr_edac_current_capability,
+ &mci_attr_supported_mem_type,
+ &mci_attr_size_mb,
+ &mci_attr_seconds_since_reset,
+ &mci_attr_ue_noinfo_count,
+ &mci_attr_ce_noinfo_count,
+ &mci_attr_ue_count,
+ &mci_attr_ce_count,
+ NULL
+};
+
+
+/*
+ * Release of a MC controlling instance
+ */
+static void edac_mci_instance_release(struct kobject *kobj)
+{
+ struct mem_ctl_info *mci;
+ mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d calling kfree\n",
+ __func__, mci->mc_idx);
+
+ kfree(mci);
+}
+
+static struct kobj_type ktype_mci = {
+ .release = edac_mci_instance_release,
+ .sysfs_ops = &mci_ops,
+ .default_attrs = (struct attribute **) mci_attr,
+};
+
+#define EDAC_DEVICE_SYMLINK "device"
+
+/*
+ * Create a new Memory Controller kobject instance,
+ * mc<id> under the 'mc' directory
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+ int err;
+ struct csrow_info *csrow;
+ struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
+
+ debugf0("MC: " __FILE__ ": %s() idx=%d\n", __func__, mci->mc_idx);
+
+ memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
+ kobject_init(edac_mci_kobj);
+
+ /* set the name of the mc<id> object */
+ err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
+ if (err)
+ return err;
+
+ /* link to our parent the '..../edac/mc' object */
+ edac_mci_kobj->parent = &edac_memctrl_kobj;
+ edac_mci_kobj->ktype = &ktype_mci;
+
+ /* register the mc<id> kobject */
+ err = kobject_register(edac_mci_kobj);
+ if (err)
+ return err;
+
+ /* create a symlink for the device */
+ err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
+ EDAC_DEVICE_SYMLINK);
+ if (err) {
+ kobject_unregister(edac_mci_kobj);
+ return err;
+ }
+
+ /* Make directories for each CSROW object
+ * under the mc<id> kobject
+ */
+ for (i = 0; i < mci->nr_csrows; i++) {
+
+ csrow = &mci->csrows[i];
+
+ /* Only expose populated CSROWs */
+ if (csrow->nr_pages > 0) {
+ err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
+ if (err)
+ goto fail;
+ }
+ }
+
+ /* Mark this MCI instance as having sysfs entries */
+ mci->sysfs_active = MCI_SYSFS_ACTIVE;
+
+ return 0;
+
+
+ /* CSROW error: backout what has already been registered, */
+fail:
+ for ( i--; i >= 0; i--) {
+ if (csrow->nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ kobject_unregister(edac_mci_kobj);
+ kobject_put(edac_mci_kobj);
+
+ return err;
+}
+
+/*
+ * remove a Memory Controller instance
+ */
+static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+{
+ int i;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* remove all csrow kobjects */
+ for (i = 0; i < mci->nr_csrows; i++) {
+ if (mci->csrows[i].nr_pages > 0) {
+ kobject_unregister(&mci->csrows[i].kobj);
+ kobject_put(&mci->csrows[i].kobj);
+ }
+ }
+
+ sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
+
+ kobject_unregister(&mci->edac_mci_kobj);
+ kobject_put(&mci->edac_mci_kobj);
+}
+
+/* END OF sysfs data and methods */
+
+#ifdef CONFIG_EDAC_DEBUG
+
+EXPORT_SYMBOL(edac_mc_dump_channel);
+
+void edac_mc_dump_channel(struct channel_info *chan)
+{
+ debugf4("\tchannel = %p\n", chan);
+ debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
+ debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
+ debugf4("\tchannel->label = '%s'\n", chan->label);
+ debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_csrow);
+
+void edac_mc_dump_csrow(struct csrow_info *csrow)
+{
+ debugf4("\tcsrow = %p\n", csrow);
+ debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);
+ debugf4("\tcsrow->first_page = 0x%lx\n",
+ csrow->first_page);
+ debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
+ debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
+ debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
+ debugf4("\tcsrow->nr_channels = %d\n",
+ csrow->nr_channels);
+ debugf4("\tcsrow->channels = %p\n", csrow->channels);
+ debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
+}
+
+
+EXPORT_SYMBOL(edac_mc_dump_mci);
+
+void edac_mc_dump_mci(struct mem_ctl_info *mci)
+{
+ debugf3("\tmci = %p\n", mci);
+ debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap);
+ debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
+ debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap);
+ debugf4("\tmci->edac_check = %p\n", mci->edac_check);
+ debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
+ mci->nr_csrows, mci->csrows);
+ debugf3("\tpdev = %p\n", mci->pdev);
+ debugf3("\tmod_name:ctl_name = %s:%s\n",
+ mci->mod_name, mci->ctl_name);
+ debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
+}
+
+
+#endif /* CONFIG_EDAC_DEBUG */
+
+/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
+ * Adjust 'ptr' so that its alignment is at least as stringent as what the
+ * compiler would provide for X and return the aligned result.
+ *
+ * If 'size' is a constant, the compiler will optimize this whole function
+ * down to either a no-op or the addition of a constant to the value of 'ptr'.
+ */
+static inline char * align_ptr (void *ptr, unsigned size)
+{
+ unsigned align, r;
+
+ /* Here we assume that the alignment of a "long long" is the most
+ * stringent alignment that the compiler will ever provide by default.
+ * As far as I know, this is a reasonable assumption.
+ */
+ if (size > sizeof(long))
+ align = sizeof(long long);
+ else if (size > sizeof(int))
+ align = sizeof(long);
+ else if (size > sizeof(short))
+ align = sizeof(int);
+ else if (size > sizeof(char))
+ align = sizeof(short);
+ else
+ return (char *) ptr;
+
+ r = size % align;
+
+ if (r == 0)
+ return (char *) ptr;
+
+ return (char *) (((unsigned long) ptr) + align - r);
+}
+
+
+EXPORT_SYMBOL(edac_mc_alloc);
+
+/**
+ * edac_mc_alloc: Allocate a struct mem_ctl_info structure
+ * @size_pvt: size of private storage needed
+ * @nr_csrows: Number of CWROWS needed for this MC
+ * @nr_chans: Number of channels for the MC
+ *
+ * Everything is kmalloc'ed as one big chunk - more efficient.
+ * Only can be used if all structures have the same lifetime - otherwise
+ * you have to allocate and initialize your own structures.
+ *
+ * Use edac_mc_free() to free mc structures allocated by this function.
+ *
+ * Returns:
+ * NULL allocation failed
+ * struct mem_ctl_info pointer
+ */
+struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
+ unsigned nr_chans)
+{
+ struct mem_ctl_info *mci;
+ struct csrow_info *csi, *csrow;
+ struct channel_info *chi, *chp, *chan;
+ void *pvt;
+ unsigned size;
+ int row, chn;
+
+ /* Figure out the offsets of the various items from the start of an mc
+ * structure. We want the alignment of each item to be at least as
+ * stringent as what the compiler would provide if we could simply
+ * hardcode everything into a single struct.
+ */
+ mci = (struct mem_ctl_info *) 0;
+ csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi));
+ chi = (struct channel_info *)
+ align_ptr(&csi[nr_csrows], sizeof(*chi));
+ pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
+ size = ((unsigned long) pvt) + sz_pvt;
+
+ if ((mci = kmalloc(size, GFP_KERNEL)) == NULL)
+ return NULL;
+
+ /* Adjust pointers so they point within the memory we just allocated
+ * rather than an imaginary chunk of memory located at address 0.
+ */
+ csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi));
+ chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
+ pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
+
+ memset(mci, 0, size); /* clear all fields */
+
+ mci->csrows = csi;
+ mci->pvt_info = pvt;
+ mci->nr_csrows = nr_csrows;
+
+ for (row = 0; row < nr_csrows; row++) {
+ csrow = &csi[row];
+ csrow->csrow_idx = row;
+ csrow->mci = mci;
+ csrow->nr_channels = nr_chans;
+ chp = &chi[row * nr_chans];
+ csrow->channels = chp;
+
+ for (chn = 0; chn < nr_chans; chn++) {
+ chan = &chp[chn];
+ chan->chan_idx = chn;
+ chan->csrow = csrow;
+ }
+ }
+
+ return mci;
+}
+
+
+EXPORT_SYMBOL(edac_mc_free);
+
+/**
+ * edac_mc_free: Free a previously allocated 'mci' structure
+ * @mci: pointer to a struct mem_ctl_info structure
+ *
+ * Free up a previously allocated mci structure
+ * A MCI structure can be in 2 states after being allocated
+ * by edac_mc_alloc().
+ * 1) Allocated in a MC driver's probe, but not yet committed
+ * 2) Allocated and committed, by a call to edac_mc_add_mc()
+ * edac_mc_add_mc() is the function that adds the sysfs entries
+ * thus, this free function must determine which state the 'mci'
+ * structure is in, then either free it directly or
+ * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
+ *
+ * VOID Return
+ */
+void edac_mc_free(struct mem_ctl_info *mci)
+{
+ /* only if sysfs entries for this mci instance exist
+ * do we remove them and defer the actual kfree via
+ * the kobject 'release()' callback.
+ *
+ * Otherwise, do a straight kfree now.
+ */
+ if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
+ edac_remove_sysfs_mci_device(mci);
+ else
+ kfree(mci);
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
+
+struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct list_head *item;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->pdev == pdev)
+ return mci;
+ }
+
+ return NULL;
+}
+
+static int add_mc_to_global_list (struct mem_ctl_info *mci)
+{
+ struct list_head *item, *insert_before;
+ struct mem_ctl_info *p;
+ int i;
+
+ if (list_empty(&mc_devices)) {
+ mci->mc_idx = 0;
+ insert_before = &mc_devices;
+ } else {
+ if (edac_mc_find_mci_by_pdev(mci->pdev)) {
+ printk(KERN_WARNING
+ "EDAC MC: %s (%s) %s %s already assigned %d\n",
+ mci->pdev->dev.bus_id, pci_name(mci->pdev),
+ mci->mod_name, mci->ctl_name, mci->mc_idx);
+ return 1;
+ }
+
+ insert_before = NULL;
+ i = 0;
+
+ list_for_each(item, &mc_devices) {
+ p = list_entry(item, struct mem_ctl_info, link);
+
+ if (p->mc_idx != i) {
+ insert_before = item;
+ break;
+ }
+
+ i++;
+ }
+
+ mci->mc_idx = i;
+
+ if (insert_before == NULL)
+ insert_before = &mc_devices;
+ }
+
+ list_add_tail_rcu(&mci->link, insert_before);
+ return 0;
+}
+
+
+
+EXPORT_SYMBOL(edac_mc_add_mc);
+
+/**
+ * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
+ * @mci: pointer to the mci structure to be added to the list
+ *
+ * Return:
+ * 0 Success
+ * !0 Failure
+ */
+
+/* FIXME - should a warning be printed if no error detection? correction? */
+int edac_mc_add_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+#ifdef CONFIG_EDAC_DEBUG
+ if (edac_debug_level >= 3)
+ edac_mc_dump_mci(mci);
+ if (edac_debug_level >= 4) {
+ int i;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ int j;
+ edac_mc_dump_csrow(&mci->csrows[i]);
+ for (j = 0; j < mci->csrows[i].nr_channels; j++)
+ edac_mc_dump_channel(&mci->csrows[i].
+ channels[j]);
+ }
+ }
+#endif
+ down(&mem_ctls_mutex);
+
+ if (add_mc_to_global_list(mci))
+ goto finish;
+
+ /* set load time so that error rate can be tracked */
+ mci->start_time = jiffies;
+
+ if (edac_create_sysfs_mci_device(mci)) {
+ printk(KERN_WARNING
+ "EDAC MC%d: failed to create sysfs device\n",
+ mci->mc_idx);
+ /* FIXME - should there be an error code and unwind? */
+ goto finish;
+ }
+
+ /* Report action taken */
+ printk(KERN_INFO
+ "EDAC MC%d: Giving out device to %s %s: PCI %s\n",
+ mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+
+
+ rc = 0;
+
+finish:
+ up(&mem_ctls_mutex);
+ return rc;
+}
+
+
+
+static void complete_mc_list_del (struct rcu_head *head)
+{
+ struct mem_ctl_info *mci;
+
+ mci = container_of(head, struct mem_ctl_info, rcu);
+ INIT_LIST_HEAD(&mci->link);
+ complete(&mci->complete);
+}
+
+static void del_mc_from_global_list (struct mem_ctl_info *mci)
+{
+ list_del_rcu(&mci->link);
+ init_completion(&mci->complete);
+ call_rcu(&mci->rcu, complete_mc_list_del);
+ wait_for_completion(&mci->complete);
+}
+
+EXPORT_SYMBOL(edac_mc_del_mc);
+
+/**
+ * edac_mc_del_mc: Remove the specified mci structure from global list
+ * @mci: Pointer to struct mem_ctl_info structure
+ *
+ * Returns:
+ * 0 Success
+ * 1 Failure
+ */
+int edac_mc_del_mc(struct mem_ctl_info *mci)
+{
+ int rc = 1;
+
+ debugf0("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ down(&mem_ctls_mutex);
+ del_mc_from_global_list(mci);
+ printk(KERN_INFO
+ "EDAC MC%d: Removed device %d for %s %s: PCI %s\n",
+ mci->mc_idx, mci->mc_idx, mci->mod_name, mci->ctl_name,
+ pci_name(mci->pdev));
+ rc = 0;
+ up(&mem_ctls_mutex);
+
+ return rc;
+}
+
+
+EXPORT_SYMBOL(edac_mc_scrub_block);
+
+void edac_mc_scrub_block(unsigned long page, unsigned long offset,
+ u32 size)
+{
+ struct page *pg;
+ void *virt_addr;
+ unsigned long flags = 0;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* ECC error page was not in our memory. Ignore it. */
+ if(!pfn_valid(page))
+ return;
+
+ /* Find the actual page structure then map it and fix */
+ pg = pfn_to_page(page);
+
+ if (PageHighMem(pg))
+ local_irq_save(flags);
+
+ virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
+
+ /* Perform architecture specific atomic scrub operation */
+ atomic_scrub(virt_addr + offset, size);
+
+ /* Unmap and complete */
+ kunmap_atomic(virt_addr, KM_BOUNCE_READ);
+
+ if (PageHighMem(pg))
+ local_irq_restore(flags);
+}
+
+
+/* FIXME - should return -1 */
+EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
+
+int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page)
+{
+ struct csrow_info *csrows = mci->csrows;
+ int row, i;
+
+ debugf1("MC%d: " __FILE__ ": %s(): 0x%lx\n", mci->mc_idx, __func__,
+ page);
+ row = -1;
+
+ for (i = 0; i < mci->nr_csrows; i++) {
+ struct csrow_info *csrow = &csrows[i];
+
+ if (csrow->nr_pages == 0)
+ continue;
+
+ debugf3("MC%d: " __FILE__
+ ": %s(): first(0x%lx) page(0x%lx)"
+ " last(0x%lx) mask(0x%lx)\n", mci->mc_idx,
+ __func__, csrow->first_page, page,
+ csrow->last_page, csrow->page_mask);
+
+ if ((page >= csrow->first_page) &&
+ (page <= csrow->last_page) &&
+ ((page & csrow->page_mask) ==
+ (csrow->first_page & csrow->page_mask))) {
+ row = i;
+ break;
+ }
+ }
+
+ if (row == -1)
+ printk(KERN_ERR
+ "EDAC MC%d: could not look up page error address %lx\n",
+ mci->mc_idx, (unsigned long) page);
+
+ return row;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce);
+
+/* FIXME - setable log (warning/emerg) levels */
+/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
+void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome, int row, int channel,
+ const char *msg)
+{
+ unsigned long remapped_page;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+ if (channel >= mci->csrows[row].nr_channels || channel < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: channel out of range "
+ "(%d >= %d)\n",
+ mci->mc_idx, channel, mci->csrows[row].nr_channels);
+ edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ if (log_ce)
+ /* FIXME - put in DIMM location */
+ printk(KERN_WARNING
+ "EDAC MC%d: CE page 0x%lx, offset 0x%lx,"
+ " grain %d, syndrome 0x%lx, row %d, channel %d,"
+ " label \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, syndrome, row, channel,
+ mci->csrows[row].channels[channel].label, msg);
+
+ mci->ce_count++;
+ mci->csrows[row].ce_count++;
+ mci->csrows[row].channels[channel].ce_count++;
+
+ if (mci->scrub_mode & SCRUB_SW_SRC) {
+ /*
+ * Some MC's can remap memory so that it is still available
+ * at a different address when PCI devices map into memory.
+ * MC's that can't do this lose the memory where PCI devices
+ * are mapped. This mapping is MC dependant and so we call
+ * back into the MC driver for it to map the MC page to
+ * a physical (CPU) page which can then be mapped to a virtual
+ * page - which can then be scrubbed.
+ */
+ remapped_page = mci->ctl_page_to_phys ?
+ mci->ctl_page_to_phys(mci, page_frame_number) :
+ page_frame_number;
+
+ edac_mc_scrub_block(remapped_page, offset_in_page,
+ mci->csrows[row].grain);
+ }
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
+
+void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (log_ce)
+ printk(KERN_WARNING
+ "EDAC MC%d: CE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ce_noinfo_count++;
+ mci->ce_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue);
+
+void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page, int row,
+ const char *msg)
+{
+ int len = EDAC_MC_LABEL_LEN * 4;
+ char labels[len + 1];
+ char *pos = labels;
+ int chan;
+ int chars;
+
+ debugf3("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+
+ /* FIXME - maybe make panic on INTERNAL ERROR an option */
+ if (row >= mci->nr_csrows || row < 0) {
+ /* something is wrong */
+ printk(KERN_ERR
+ "EDAC MC%d: INTERNAL ERROR: row out of range (%d >= %d)\n",
+ mci->mc_idx, row, mci->nr_csrows);
+ edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
+ return;
+ }
+
+ chars = snprintf(pos, len + 1, "%s",
+ mci->csrows[row].channels[0].label);
+ len -= chars;
+ pos += chars;
+ for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
+ chan++) {
+ chars = snprintf(pos, len + 1, ":%s",
+ mci->csrows[row].channels[chan].label);
+ len -= chars;
+ pos += chars;
+ }
+
+ if (log_ue)
+ printk(KERN_EMERG
+ "EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ if (panic_on_ue)
+ panic
+ ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
+ " labels \"%s\": %s\n", mci->mc_idx,
+ page_frame_number, offset_in_page,
+ mci->csrows[row].grain, row, labels, msg);
+
+ mci->ue_count++;
+ mci->csrows[row].ue_count++;
+}
+
+
+EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
+
+void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg)
+{
+ if (panic_on_ue)
+ panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
+
+ if (log_ue)
+ printk(KERN_WARNING
+ "EDAC MC%d: UE - no information available: %s\n",
+ mci->mc_idx, msg);
+ mci->ue_noinfo_count++;
+ mci->ue_count++;
+}
+
+
+#ifdef CONFIG_PCI
+
+static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
+{
+ int where;
+ u16 status;
+
+ where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
+ pci_read_config_word(dev, where, &status);
+
+ /* If we get back 0xFFFF then we must suspect that the card has been pulled but
+ the Linux PCI layer has not yet finished cleaning up. We don't want to report
+ on such devices */
+
+ if (status == 0xFFFF) {
+ u32 sanity;
+ pci_read_config_dword(dev, 0, &sanity);
+ if (sanity == 0xFFFFFFFF)
+ return 0;
+ }
+ status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
+ PCI_STATUS_PARITY;
+
+ if (status)
+ /* reset only the bits we are interested in */
+ pci_write_config_word(dev, where, status);
+
+ return status;
+}
+
+typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
+
+/* Clear any PCI parity errors logged by this device. */
+static void edac_pci_dev_parity_clear( struct pci_dev *dev )
+{
+ u8 header_type;
+
+ get_pci_parity_status(dev, 0);
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
+ get_pci_parity_status(dev, 1);
+}
+
+/*
+ * PCI Parity polling
+ *
+ */
+static void edac_pci_dev_parity_test(struct pci_dev *dev)
+{
+ u16 status;
+ u8 header_type;
+
+ /* read the STATUS register on this device
+ */
+ status = get_pci_parity_status(dev, 0);
+
+ debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
+
+ /* check the status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+
+ /* read the device TYPE, looking for bridges */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
+
+ debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
+
+ if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
+ /* On bridges, need to examine secondary status register */
+ status = get_pci_parity_status(dev, 1);
+
+ debugf2("PCI SEC_STATUS= 0x%04x %s\n",
+ status, dev->dev.bus_id );
+
+ /* check the secondary status reg for errors */
+ if (status) {
+ if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Signaled System Error on %s\n",
+ pci_name (dev));
+
+ if (status & (PCI_STATUS_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Master Data Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+
+ if (status & (PCI_STATUS_DETECTED_PARITY)) {
+ printk(KERN_CRIT
+ "EDAC PCI-Bridge- "
+ "Detected Parity Error on %s\n",
+ pci_name (dev));
+
+ atomic_inc(&pci_parity_count);
+ }
+ }
+ }
+}
+
+/*
+ * check_dev_on_list: Scan for a PCI device on a white/black list
+ * @list: an EDAC &edac_pci_device_list white/black list pointer
+ * @free_index: index of next free entry on the list
+ * @pci_dev: PCI Device pointer
+ *
+ * see if list contains the device.
+ *
+ * Returns: 0 not found
+ * 1 found on list
+ */
+static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
+ struct pci_dev *dev)
+{
+ int i;
+ int rc = 0; /* Assume not found */
+ unsigned short vendor=dev->vendor;
+ unsigned short device=dev->device;
+
+ /* Scan the list, looking for a vendor/device match
+ */
+ for (i = 0; i < free_index; i++, list++ ) {
+ if ( (list->vendor == vendor ) &&
+ (list->device == device )) {
+ rc = 1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * pci_dev parity list iterator
+ * Scan the PCI device list for one iteration, looking for SERRORs
+ * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ */
+static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
+{
+ struct pci_dev *dev=NULL;
+
+ /* request for kernel access to the next PCI device, if any,
+ * and while we are looking at it have its reference count
+ * bumped until we are done with it
+ */
+ while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+
+ /* if whitelist exists then it has priority, so only scan those
+ * devices on the whitelist
+ */
+ if (pci_whitelist_count > 0 ) {
+ if (check_dev_on_list(pci_whitelist,
+ pci_whitelist_count, dev))
+ fn(dev);
+ } else {
+ /*
+ * if no whitelist, then check if this devices is
+ * blacklisted
+ */
+ if (!check_dev_on_list(pci_blacklist,
+ pci_blacklist_count, dev))
+ fn(dev);
+ }
+ }
+}
+
+static void do_pci_parity_check(void)
+{
+ unsigned long flags;
+ int before_count;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ if (!check_pci_parity)
+ return;
+
+ before_count = atomic_read(&pci_parity_count);
+
+ /* scan all PCI devices looking for a Parity Error on devices and
+ * bridges
+ */
+ local_irq_save(flags);
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
+ local_irq_restore(flags);
+
+ /* Only if operator has selected panic on PCI Error */
+ if (panic_on_pci_parity) {
+ /* If the count is different 'after' from 'before' */
+ if (before_count != atomic_read(&pci_parity_count))
+ panic("EDAC: PCI Parity Error");
+ }
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* Clear any PCI bus parity errors that devices initially have logged
+ * in their registers.
+ */
+ edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
+}
+
+
+#else /* CONFIG_PCI */
+
+
+static inline void do_pci_parity_check(void)
+{
+ /* no-op */
+}
+
+
+static inline void clear_pci_parity_errors(void)
+{
+ /* no-op */
+}
+
+
+#endif /* CONFIG_PCI */
+
+/*
+ * Iterate over all MC instances and check for ECC, et al, errors
+ */
+static inline void check_mc_devices (void)
+{
+ unsigned long flags;
+ struct list_head *item;
+ struct mem_ctl_info *mci;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* during poll, have interrupts off */
+ local_irq_save(flags);
+
+ list_for_each(item, &mc_devices) {
+ mci = list_entry(item, struct mem_ctl_info, link);
+
+ if (mci->edac_check != NULL)
+ mci->edac_check(mci);
+ }
+
+ local_irq_restore(flags);
+}
+
+
+/*
+ * Check MC status every poll_msec.
+ * Check PCI status every poll_msec as well.
+ *
+ * This where the work gets done for edac.
+ *
+ * SMP safe, doesn't use NMI, and auto-rate-limits.
+ */
+static void do_edac_check(void)
+{
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ check_mc_devices();
+
+ do_pci_parity_check();
+}
+
+
+/*
+ * EDAC thread state information
+ */
+struct bs_thread_info
+{
+ struct task_struct *task;
+ struct completion *event;
+ char *name;
+ void (*run)(void);
+};
+
+static struct bs_thread_info bs_thread;
+
+/*
+ * edac_kernel_thread
+ * This the kernel thread that processes edac operations
+ * in a normal thread environment
+ */
+static int edac_kernel_thread(void *arg)
+{
+ struct bs_thread_info *thread = (struct bs_thread_info *) arg;
+
+ /* detach thread */
+ daemonize(thread->name);
+
+ current->exit_signal = SIGCHLD;
+ allow_signal(SIGKILL);
+ thread->task = current;
+
+ /* indicate to starting task we have started */
+ complete(thread->event);
+
+ /* loop forever, until we are told to stop */
+ while(thread->run != NULL) {
+ void (*run)(void);
+
+ /* call the function to check the memory controllers */
+ run = thread->run;
+ if (run)
+ run();
+
+ if (signal_pending(current))
+ flush_signals(current);
+
+ /* ensure we are interruptable */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* goto sleep for the interval */
+ schedule_timeout((HZ * poll_msec) / 1000);
+ try_to_freeze();
+ }
+
+ /* notify waiter that we are exiting */
+ complete(thread->event);
+
+ return 0;
+}
+
+/*
+ * edac_mc_init
+ * module initialization entry point
+ */
+static int __init edac_mc_init(void)
+{
+ int ret;
+ struct completion event;
+
+ printk(KERN_INFO "MC: " __FILE__ " version " EDAC_MC_VERSION "\n");
+
+ /*
+ * Harvest and clear any boot/initialization PCI parity errors
+ *
+ * FIXME: This only clears errors logged by devices present at time of
+ * module initialization. We should also do an initial clear
+ * of each newly hotplugged device.
+ */
+ clear_pci_parity_errors();
+
+ /* perform check for first time to harvest boot leftovers */
+ do_edac_check();
+
+ /* Create the MC sysfs entires */
+ if (edac_sysfs_memctrl_setup()) {
+ printk(KERN_ERR "EDAC MC: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create the PCI parity sysfs entries */
+ if (edac_sysfs_pci_setup()) {
+ edac_sysfs_memctrl_teardown();
+ printk(KERN_ERR "EDAC PCI: Error initializing sysfs code\n");
+ return -ENODEV;
+ }
+
+ /* Create our kernel thread */
+ init_completion(&event);
+ bs_thread.event = &event;
+ bs_thread.name = "kedac";
+ bs_thread.run = do_edac_check;
+
+ /* create our kernel thread */
+ ret = kernel_thread(edac_kernel_thread, &bs_thread, CLONE_KERNEL);
+ if (ret < 0) {
+ /* remove the sysfs entries */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+ return -ENOMEM;
+ }
+
+ /* wait for our kernel theard ack that it is up and running */
+ wait_for_completion(&event);
+
+ return 0;
+}
+
+
+/*
+ * edac_mc_exit()
+ * module exit/termination functioni
+ */
+static void __exit edac_mc_exit(void)
+{
+ struct completion event;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ init_completion(&event);
+ bs_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
+ */
+ read_lock(&tasklist_lock);
+ bs_thread.run = NULL;
+ send_sig(SIGKILL, bs_thread.task, 1);
+ read_unlock(&tasklist_lock);
+ wait_for_completion(&event);
+
+ /* tear down the sysfs device */
+ edac_sysfs_memctrl_teardown();
+ edac_sysfs_pci_teardown();
+}
+
+
+
+
+module_init(edac_mc_init);
+module_exit(edac_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
+ "Based on.work by Dan Hollis et al");
+MODULE_DESCRIPTION("Core library routines for MC reporting");
+
+module_param(panic_on_ue, int, 0644);
+MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
+module_param(check_pci_parity, int, 0644);
+MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on");
+module_param(panic_on_pci_parity, int, 0644);
+MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on");
+module_param(log_ue, int, 0644);
+MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on");
+module_param(log_ce, int, 0644);
+MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on");
+module_param(poll_msec, int, 0644);
+MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds");
+#ifdef CONFIG_EDAC_DEBUG
+module_param(edac_debug_level, int, 0644);
+MODULE_PARM_DESC(edac_debug_level, "Debug level");
+#endif
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
new file mode 100644
index 000000000000..75ecf484a43a
--- /dev/null
+++ b/drivers/edac/edac_mc.h
@@ -0,0 +1,448 @@
+/*
+ * MC kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ * http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ * Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * $Id: edac_mc.h,v 1.4.2.10 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ */
+
+
+#ifndef _EDAC_MC_H_
+#define _EDAC_MC_H_
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/nmi.h>
+#include <linux/rcupdate.h>
+#include <linux/completion.h>
+#include <linux/kobject.h>
+
+
+#define EDAC_MC_LABEL_LEN 31
+#define MC_PROC_NAME_MAX_LEN 7
+
+#if PAGE_SHIFT < 20
+#define PAGES_TO_MiB( pages ) ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#else /* PAGE_SHIFT > 20 */
+#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#endif
+
+#ifdef CONFIG_EDAC_DEBUG
+extern int edac_debug_level;
+#define edac_debug_printk(level, fmt, args...) \
+do { if (level <= edac_debug_level) printk(KERN_DEBUG fmt, ##args); } while(0)
+#define debugf0( ... ) edac_debug_printk(0, __VA_ARGS__ )
+#define debugf1( ... ) edac_debug_printk(1, __VA_ARGS__ )
+#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
+#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
+#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
+#else /* !CONFIG_EDAC_DEBUG */
+#define debugf0( ... )
+#define debugf1( ... )
+#define debugf2( ... )
+#define debugf3( ... )
+#define debugf4( ... )
+#endif /* !CONFIG_EDAC_DEBUG */
+
+
+#define bs_xstr(s) bs_str(s)
+#define bs_str(s) #s
+#define BS_MOD_STR bs_xstr(KBUILD_BASENAME)
+
+#define BIT(x) (1 << (x))
+
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
+
+/* memory devices */
+enum dev_type {
+ DEV_UNKNOWN = 0,
+ DEV_X1,
+ DEV_X2,
+ DEV_X4,
+ DEV_X8,
+ DEV_X16,
+ DEV_X32, /* Do these parts exist? */
+ DEV_X64 /* Do these parts exist? */
+};
+
+#define DEV_FLAG_UNKNOWN BIT(DEV_UNKNOWN)
+#define DEV_FLAG_X1 BIT(DEV_X1)
+#define DEV_FLAG_X2 BIT(DEV_X2)
+#define DEV_FLAG_X4 BIT(DEV_X4)
+#define DEV_FLAG_X8 BIT(DEV_X8)
+#define DEV_FLAG_X16 BIT(DEV_X16)
+#define DEV_FLAG_X32 BIT(DEV_X32)
+#define DEV_FLAG_X64 BIT(DEV_X64)
+
+/* memory types */
+enum mem_type {
+ MEM_EMPTY = 0, /* Empty csrow */
+ MEM_RESERVED, /* Reserved csrow type */
+ MEM_UNKNOWN, /* Unknown csrow type */
+ MEM_FPM, /* Fast page mode */
+ MEM_EDO, /* Extended data out */
+ MEM_BEDO, /* Burst Extended data out */
+ MEM_SDR, /* Single data rate SDRAM */
+ MEM_RDR, /* Registered single data rate SDRAM */
+ MEM_DDR, /* Double data rate SDRAM */
+ MEM_RDDR, /* Registered Double data rate SDRAM */
+ MEM_RMBS /* Rambus DRAM */
+};
+
+#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
+#define MEM_FLAG_RESERVED BIT(MEM_RESERVED)
+#define MEM_FLAG_UNKNOWN BIT(MEM_UNKNOWN)
+#define MEM_FLAG_FPM BIT(MEM_FPM)
+#define MEM_FLAG_EDO BIT(MEM_EDO)
+#define MEM_FLAG_BEDO BIT(MEM_BEDO)
+#define MEM_FLAG_SDR BIT(MEM_SDR)
+#define MEM_FLAG_RDR BIT(MEM_RDR)
+#define MEM_FLAG_DDR BIT(MEM_DDR)
+#define MEM_FLAG_RDDR BIT(MEM_RDDR)
+#define MEM_FLAG_RMBS BIT(MEM_RMBS)
+
+
+/* chipset Error Detection and Correction capabilities and mode */
+enum edac_type {
+ EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
+ EDAC_NONE, /* Doesnt support ECC */
+ EDAC_RESERVED, /* Reserved ECC type */
+ EDAC_PARITY, /* Detects parity errors */
+ EDAC_EC, /* Error Checking - no correction */
+ EDAC_SECDED, /* Single bit error correction, Double detection */
+ EDAC_S2ECD2ED, /* Chipkill x2 devices - do these exist? */
+ EDAC_S4ECD4ED, /* Chipkill x4 devices */
+ EDAC_S8ECD8ED, /* Chipkill x8 devices */
+ EDAC_S16ECD16ED, /* Chipkill x16 devices */
+};
+
+#define EDAC_FLAG_UNKNOWN BIT(EDAC_UNKNOWN)
+#define EDAC_FLAG_NONE BIT(EDAC_NONE)
+#define EDAC_FLAG_PARITY BIT(EDAC_PARITY)
+#define EDAC_FLAG_EC BIT(EDAC_EC)
+#define EDAC_FLAG_SECDED BIT(EDAC_SECDED)
+#define EDAC_FLAG_S2ECD2ED BIT(EDAC_S2ECD2ED)
+#define EDAC_FLAG_S4ECD4ED BIT(EDAC_S4ECD4ED)
+#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
+#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
+
+
+/* scrubbing capabilities */
+enum scrub_type {
+ SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
+ SCRUB_NONE, /* No scrubber */
+ SCRUB_SW_PROG, /* SW progressive (sequential) scrubbing */
+ SCRUB_SW_SRC, /* Software scrub only errors */
+ SCRUB_SW_PROG_SRC, /* Progressive software scrub from an error */
+ SCRUB_SW_TUNABLE, /* Software scrub frequency is tunable */
+ SCRUB_HW_PROG, /* HW progressive (sequential) scrubbing */
+ SCRUB_HW_SRC, /* Hardware scrub only errors */
+ SCRUB_HW_PROG_SRC, /* Progressive hardware scrub from an error */
+ SCRUB_HW_TUNABLE /* Hardware scrub frequency is tunable */
+};
+
+#define SCRUB_FLAG_SW_PROG BIT(SCRUB_SW_PROG)
+#define SCRUB_FLAG_SW_SRC BIT(SCRUB_SW_SRC_CORR)
+#define SCRUB_FLAG_SW_PROG_SRC BIT(SCRUB_SW_PROG_SRC_CORR)
+#define SCRUB_FLAG_SW_TUN BIT(SCRUB_SW_SCRUB_TUNABLE)
+#define SCRUB_FLAG_HW_PROG BIT(SCRUB_HW_PROG)
+#define SCRUB_FLAG_HW_SRC BIT(SCRUB_HW_SRC_CORR)
+#define SCRUB_FLAG_HW_PROG_SRC BIT(SCRUB_HW_PROG_SRC_CORR)
+#define SCRUB_FLAG_HW_TUN BIT(SCRUB_HW_TUNABLE)
+
+enum mci_sysfs_status {
+ MCI_SYSFS_INACTIVE = 0, /* sysfs entries NOT registered */
+ MCI_SYSFS_ACTIVE /* sysfs entries ARE registered */
+};
+
+/* FIXME - should have notify capabilities: NMI, LOG, PROC, etc */
+
+/*
+ * There are several things to be aware of that aren't at all obvious:
+ *
+ *
+ * SOCKETS, SOCKET SETS, BANKS, ROWS, CHIP-SELECT ROWS, CHANNELS, etc..
+ *
+ * These are some of the many terms that are thrown about that don't always
+ * mean what people think they mean (Inconceivable!). In the interest of
+ * creating a common ground for discussion, terms and their definitions
+ * will be established.
+ *
+ * Memory devices: The individual chip on a memory stick. These devices
+ * commonly output 4 and 8 bits each. Grouping several
+ * of these in parallel provides 64 bits which is common
+ * for a memory stick.
+ *
+ * Memory Stick: A printed circuit board that agregates multiple
+ * memory devices in parallel. This is the atomic
+ * memory component that is purchaseable by Joe consumer
+ * and loaded into a memory socket.
+ *
+ * Socket: A physical connector on the motherboard that accepts
+ * a single memory stick.
+ *
+ * Channel: Set of memory devices on a memory stick that must be
+ * grouped in parallel with one or more additional
+ * channels from other memory sticks. This parallel
+ * grouping of the output from multiple channels are
+ * necessary for the smallest granularity of memory access.
+ * Some memory controllers are capable of single channel -
+ * which means that memory sticks can be loaded
+ * individually. Other memory controllers are only
+ * capable of dual channel - which means that memory
+ * sticks must be loaded as pairs (see "socket set").
+ *
+ * Chip-select row: All of the memory devices that are selected together.
+ * for a single, minimum grain of memory access.
+ * This selects all of the parallel memory devices across
+ * all of the parallel channels. Common chip-select rows
+ * for single channel are 64 bits, for dual channel 128
+ * bits.
+ *
+ * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memmory.
+ * Motherboards commonly drive two chip-select pins to
+ * a memory stick. A single-ranked stick, will occupy
+ * only one of those rows. The other will be unused.
+ *
+ * Double-Ranked stick: A double-ranked stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently.
+ *
+ * Double-sided stick: DEPRECATED TERM, see Double-Ranked stick.
+ * A double-sided stick has two chip-select rows which
+ * access different sets of memory devices. The two
+ * rows cannot be accessed concurrently. "Double-sided"
+ * is irrespective of the memory devices being mounted
+ * on both sides of the memory stick.
+ *
+ * Socket set: All of the memory sticks that are required for for
+ * a single memory access or all of the memory sticks
+ * spanned by a chip-select row. A single socket set
+ * has two chip-select rows and if double-sided sticks
+ * are used these will occupy those chip-select rows.
+ *
+ * Bank: This term is avoided because it is unclear when
+ * needing to distinguish between chip-select rows and
+ * socket sets.
+ *
+ * Controller pages:
+ *
+ * Physical pages:
+ *
+ * Virtual pages:
+ *
+ *
+ * STRUCTURE ORGANIZATION AND CHOICES
+ *
+ *
+ *
+ * PS - I enjoyed writing all that about as much as you enjoyed reading it.
+ */
+
+
+struct channel_info {
+ int chan_idx; /* channel index */
+ u32 ce_count; /* Correctable Errors for this CHANNEL */
+ char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
+ struct csrow_info *csrow; /* the parent */
+};
+
+
+struct csrow_info {
+ unsigned long first_page; /* first page number in dimm */
+ unsigned long last_page; /* last page number in dimm */
+ unsigned long page_mask; /* used for interleaving -
+ 0UL for non intlv */
+ u32 nr_pages; /* number of pages in csrow */
+ u32 grain; /* granularity of reported error in bytes */
+ int csrow_idx; /* the chip-select row */
+ enum dev_type dtype; /* memory device type */
+ u32 ue_count; /* Uncorrectable Errors for this csrow */
+ u32 ce_count; /* Correctable Errors for this csrow */
+ enum mem_type mtype; /* memory csrow type */
+ enum edac_type edac_mode; /* EDAC mode for this csrow */
+ struct mem_ctl_info *mci; /* the parent */
+
+ struct kobject kobj; /* sysfs kobject for this csrow */
+
+ /* FIXME the number of CHANNELs might need to become dynamic */
+ u32 nr_channels;
+ struct channel_info *channels;
+};
+
+
+struct mem_ctl_info {
+ struct list_head link; /* for global list of mem_ctl_info structs */
+ unsigned long mtype_cap; /* memory types supported by mc */
+ unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
+ unsigned long edac_cap; /* configuration capabilities - this is
+ closely related to edac_ctl_cap. The
+ difference is that the controller
+ may be capable of s4ecd4ed which would
+ be listed in edac_ctl_cap, but if
+ channels aren't capable of s4ecd4ed then the
+ edac_cap would not have that capability. */
+ unsigned long scrub_cap; /* chipset scrub capabilities */
+ enum scrub_type scrub_mode; /* current scrub mode */
+
+ enum mci_sysfs_status sysfs_active; /* status of sysfs */
+
+ /* pointer to edac checking routine */
+ void (*edac_check) (struct mem_ctl_info * mci);
+ /*
+ * Remaps memory pages: controller pages to physical pages.
+ * For most MC's, this will be NULL.
+ */
+ /* FIXME - why not send the phys page to begin with? */
+ unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
+ unsigned long page);
+ int mc_idx;
+ int nr_csrows;
+ struct csrow_info *csrows;
+ /*
+ * FIXME - what about controllers on other busses? - IDs must be
+ * unique. pdev pointer should be sufficiently unique, but
+ * BUS:SLOT.FUNC numbers may not be unique.
+ */
+ struct pci_dev *pdev;
+ const char *mod_name;
+ const char *mod_ver;
+ const char *ctl_name;
+ char proc_name[MC_PROC_NAME_MAX_LEN + 1];
+ void *pvt_info;
+ u32 ue_noinfo_count; /* Uncorrectable Errors w/o info */
+ u32 ce_noinfo_count; /* Correctable Errors w/o info */
+ u32 ue_count; /* Total Uncorrectable Errors for this MC */
+ u32 ce_count; /* Total Correctable Errors for this MC */
+ unsigned long start_time; /* mci load start time (in jiffies) */
+
+ /* this stuff is for safe removal of mc devices from global list while
+ * NMI handlers may be traversing list
+ */
+ struct rcu_head rcu;
+ struct completion complete;
+
+ /* edac sysfs device control */
+ struct kobject edac_mci_kobj;
+};
+
+
+
+/* write all or some bits in a byte-register*/
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
+ u8 value, u8 mask)
+{
+ if (mask != 0xff) {
+ u8 buf;
+ pci_read_config_byte(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_byte(pdev, offset, value);
+}
+
+
+/* write all or some bits in a word-register*/
+static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
+ u16 value, u16 mask)
+{
+ if (mask != 0xffff) {
+ u16 buf;
+ pci_read_config_word(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_word(pdev, offset, value);
+}
+
+
+/* write all or some bits in a dword-register*/
+static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
+ u32 value, u32 mask)
+{
+ if (mask != 0xffff) {
+ u32 buf;
+ pci_read_config_dword(pdev, offset, &buf);
+ value &= mask;
+ buf &= ~mask;
+ value |= buf;
+ }
+ pci_write_config_dword(pdev, offset, value);
+}
+
+
+#ifdef CONFIG_EDAC_DEBUG
+void edac_mc_dump_channel(struct channel_info *chan);
+void edac_mc_dump_mci(struct mem_ctl_info *mci);
+void edac_mc_dump_csrow(struct csrow_info *csrow);
+#endif /* CONFIG_EDAC_DEBUG */
+
+extern int edac_mc_add_mc(struct mem_ctl_info *mci);
+extern int edac_mc_del_mc(struct mem_ctl_info *mci);
+
+extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+ unsigned long page);
+
+extern struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev
+ *pdev);
+
+extern void edac_mc_scrub_block(unsigned long page,
+ unsigned long offset, u32 size);
+
+/*
+ * The no info errors are used when error overflows are reported.
+ * There are a limited number of error logging registers that can
+ * be exausted. When all registers are exhausted and an additional
+ * error occurs then an error overflow register records that an
+ * error occured and the type of error, but doesn't have any
+ * further information. The ce/ue versions make for cleaner
+ * reporting logic and function interface - reduces conditional
+ * statement clutter and extra function arguments.
+ */
+extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ unsigned long syndrome,
+ int row, int channel, const char *msg);
+
+extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
+ unsigned long page_frame_number,
+ unsigned long offset_in_page,
+ int row, const char *msg);
+
+extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
+ const char *msg);
+
+/*
+ * This kmalloc's and initializes all the structures.
+ * Can't be used if all structures don't have the same lifetime.
+ */
+extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
+ unsigned nr_csrows, unsigned nr_chans);
+
+/* Free an mc previously allocated by edac_mc_alloc() */
+extern void edac_mc_free(struct mem_ctl_info *mci);
+
+
+#endif /* _EDAC_MC_H_ */
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
new file mode 100644
index 000000000000..52596e75f9c2
--- /dev/null
+++ b/drivers/edac/i82860_edac.c
@@ -0,0 +1,299 @@
+/*
+ * Intel 82860 Memory Controller kernel module
+ * (C) 2005 Red Hat (http://www.redhat.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Ben Woodard <woodard@redhat.com>
+ * shamelessly copied from and based upon the edac_i82875 driver
+ * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82860_0
+#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
+#endif /* PCI_DEVICE_ID_INTEL_82860_0 */
+
+#define I82860_MCHCFG 0x50
+#define I82860_GBA 0x60
+#define I82860_GBA_MASK 0x7FF
+#define I82860_GBA_SHIFT 24
+#define I82860_ERRSTS 0xC8
+#define I82860_EAP 0xE4
+#define I82860_DERRCTL_STS 0xE2
+
+enum i82860_chips {
+ I82860 = 0,
+};
+
+struct i82860_dev_info {
+ const char *ctl_name;
+};
+
+struct i82860_error_info {
+ u16 errsts;
+ u32 eap;
+ u16 derrsyn;
+ u16 errsts2;
+};
+
+static const struct i82860_dev_info i82860_devs[] = {
+ [I82860] = {
+ .ctl_name = "i82860"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+
+static int i82860_registered = 1;
+
+static void i82860_get_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82860_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ /*
+ * If the error is the same for both reads then the first set of reads
+ * is valid. If there is a change then there is a CE no info and the
+ * second set of reads is valid and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0003))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
+ pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
+ &info->derrsyn);
+ }
+}
+
+static int i82860_process_error_info (struct mem_ctl_info *mci,
+ struct i82860_error_info *info, int handle_errors)
+{
+ int row;
+
+ if (!(info->errsts2 & 0x0003))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0003) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0002)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ 0, "i82860 UE");
+
+ return 1;
+}
+
+static void i82860_check(struct mem_ctl_info *mci)
+{
+ struct i82860_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82860_get_error_info(mci, &info);
+ i82860_process_error_info(mci, &info, 1);
+}
+
+static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ unsigned long last_cumul_size;
+
+ u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ /* RDRAM has channels but these don't map onto the abstractions that
+ edac uses.
+ The device groups from the GRA registers seem to map reasonably
+ well onto the notion of a chip select row.
+ There are 16 GRA registers and since the name is associated with
+ the channel and the GRA registers map to physical devices so we are
+ going to make 1 channel for group.
+ */
+ mci = edac_mc_alloc(0, 16, 1);
+ if (!mci)
+ return -ENOMEM;
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ /* I"m not sure about this but I think that all RDRAM is SECDED */
+ mci->edac_cap = EDAC_FLAG_SECDED;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = i82860_devs[dev_idx].ctl_name;
+ mci->edac_check = i82860_check;
+ mci->ctl_page_to_phys = NULL;
+
+ pci_read_config_word(mci->pdev, I82860_MCHCFG, &mchcfg_ddim);
+ mchcfg_ddim = mchcfg_ddim & 0x180;
+
+ /*
+ * The group row boundary (GRA) reg values are boundary address
+ * for each DRAM row with a granularity of 16MB. GRA regs are
+ * cumulative; therefore GRA15 will contain the total memory contained
+ * in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u16 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
+ &value);
+
+ cumul_size = (value & I82860_GBA_MASK) <<
+ (I82860_GBA_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
+ csrow->mtype = MEM_RMBS;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n",
+ __func__);
+ edac_mc_free(mci);
+ } else {
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ rc = 0;
+ }
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82860_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82860 init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82860_probe1(pdev, ent->driver_data);
+ if(rc == 0)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+static void __devexit i82860_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ mci = edac_mc_find_mci_by_pdev(pdev);
+ if ((mci != NULL) && (edac_mc_del_mc(mci) == 0))
+ edac_mc_free(mci);
+}
+
+static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82860},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
+
+static struct pci_driver i82860_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82860_init_one,
+ .remove = __devexit_p(i82860_remove_one),
+ .id_table = i82860_pci_tbl,
+};
+
+static int __init i82860_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
+ return pci_rc;
+
+ if (!mci_pdev) {
+ i82860_registered = 0;
+ mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82860_0, NULL);
+ if (mci_pdev == NULL) {
+ debugf0("860 pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("860 init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static void __exit i82860_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82860_driver);
+ if (!i82860_registered) {
+ i82860_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+module_init(i82860_init);
+module_exit(i82860_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR
+ ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>");
+MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
new file mode 100644
index 000000000000..009c08fe5d69
--- /dev/null
+++ b/drivers/edac/i82875p_edac.c
@@ -0,0 +1,532 @@
+/*
+ * Intel D82875P Memory Controller kernel module
+ * (C) 2003 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Contributors:
+ * Wang Zhenyu at intel.com
+ *
+ * $Id: edac_i82875p.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_0
+#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
+#endif /* PCI_DEVICE_ID_INTEL_82875_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_82875_6
+#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
+#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
+
+
+/* four csrows in dual channel, eight in single channel */
+#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
+
+
+/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
+#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
+ *
+ * 31:12 block address
+ * 11:0 reserved
+ */
+
+#define I82875P_DERRSYN 0x5c /* DRAM Error Syndrome (8b)
+ *
+ * 7:0 DRAM ECC Syndrome
+ */
+
+#define I82875P_DES 0x5d /* DRAM Error Status (8b)
+ *
+ * 7:1 reserved
+ * 0 Error channel 0/1
+ */
+
+#define I82875P_ERRSTS 0xc8 /* Error Status Register (16b)
+ *
+ * 15:10 reserved
+ * 9 non-DRAM lock error (ndlock)
+ * 8 Sftwr Generated SMI
+ * 7 ECC UE
+ * 6 reserved
+ * 5 MCH detects unimplemented cycle
+ * 4 AGP access outside GA
+ * 3 Invalid AGP access
+ * 2 Invalid GA translation table
+ * 1 Unsupported AGP command
+ * 0 ECC CE
+ */
+
+#define I82875P_ERRCMD 0xca /* Error Command (16b)
+ *
+ * 15:10 reserved
+ * 9 SERR on non-DRAM lock
+ * 8 SERR on ECC UE
+ * 7 SERR on ECC CE
+ * 6 target abort on high exception
+ * 5 detect unimplemented cyc
+ * 4 AGP access outside of GA
+ * 3 SERR on invalid AGP access
+ * 2 invalid translation table
+ * 1 SERR on unsupported AGP command
+ * 0 reserved
+ */
+
+
+/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
+#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
+ *
+ * 15:10 reserved
+ * 9 fast back-to-back - ro 0
+ * 8 SERR enable - ro 0
+ * 7 addr/data stepping - ro 0
+ * 6 parity err enable - ro 0
+ * 5 VGA palette snoop - ro 0
+ * 4 mem wr & invalidate - ro 0
+ * 3 special cycle - ro 0
+ * 2 bus master - ro 0
+ * 1 mem access dev6 - 0(dis),1(en)
+ * 0 IO access dev3 - 0(dis),1(en)
+ */
+
+#define I82875P_BAR6 0x10 /* Mem Delays Base ADDR Reg (32b)
+ *
+ * 31:12 mem base addr [31:12]
+ * 11:4 address mask - ro 0
+ * 3 prefetchable - ro 0(non),1(pre)
+ * 2:1 mem type - ro 0
+ * 0 mem space - ro 0
+ */
+
+/* Intel 82875p MMIO register space - device 0 function 0 - MMR space */
+
+#define I82875P_DRB_SHIFT 26 /* 64MiB grain */
+#define I82875P_DRB 0x00 /* DRAM Row Boundary (8b x 8)
+ *
+ * 7 reserved
+ * 6:0 64MiB row boundary addr
+ */
+
+#define I82875P_DRA 0x10 /* DRAM Row Attribute (4b x 8)
+ *
+ * 7 reserved
+ * 6:4 row attr row 1
+ * 3 reserved
+ * 2:0 row attr row 0
+ *
+ * 000 = 4KiB
+ * 001 = 8KiB
+ * 010 = 16KiB
+ * 011 = 32KiB
+ */
+
+#define I82875P_DRC 0x68 /* DRAM Controller Mode (32b)
+ *
+ * 31:30 reserved
+ * 29 init complete
+ * 28:23 reserved
+ * 22:21 nr chan 00=1,01=2
+ * 20 reserved
+ * 19:18 Data Integ Mode 00=none,01=ecc
+ * 17:11 reserved
+ * 10:8 refresh mode
+ * 7 reserved
+ * 6:4 mode select
+ * 3:2 reserved
+ * 1:0 DRAM type 01=DDR
+ */
+
+
+enum i82875p_chips {
+ I82875P = 0,
+};
+
+
+struct i82875p_pvt {
+ struct pci_dev *ovrfl_pdev;
+ void *ovrfl_window;
+};
+
+
+struct i82875p_dev_info {
+ const char *ctl_name;
+};
+
+
+struct i82875p_error_info {
+ u16 errsts;
+ u32 eap;
+ u8 des;
+ u8 derrsyn;
+ u16 errsts2;
+};
+
+
+static const struct i82875p_dev_info i82875p_devs[] = {
+ [I82875P] = {
+ .ctl_name = "i82875p"},
+};
+
+static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
+ has already registered driver */
+static int i82875p_registered = 1;
+
+static void i82875p_get_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info)
+{
+ /*
+ * This is a mess because there is no atomic way to read all the
+ * registers at once and the registers can transition from CE being
+ * overwritten by UE.
+ */
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts);
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN, &info->derrsyn);
+ pci_read_config_word(mci->pdev, I82875P_ERRSTS, &info->errsts2);
+
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ /*
+ * If the error is the same then we can for both reads then
+ * the first set of reads is valid. If there is a change then
+ * there is a CE no info and the second set of reads is valid
+ * and should be UE info.
+ */
+ if (!(info->errsts2 & 0x0081))
+ return;
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
+ pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
+ pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
+ &info->derrsyn);
+ }
+}
+
+static int i82875p_process_error_info (struct mem_ctl_info *mci,
+ struct i82875p_error_info *info, int handle_errors)
+{
+ int row, multi_chan;
+
+ multi_chan = mci->csrows[0].nr_channels - 1;
+
+ if (!(info->errsts2 & 0x0081))
+ return 0;
+
+ if (!handle_errors)
+ return 1;
+
+ if ((info->errsts ^ info->errsts2) & 0x0081) {
+ edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
+ info->errsts = info->errsts2;
+ }
+
+ info->eap >>= PAGE_SHIFT;
+ row = edac_mc_find_csrow_by_page(mci, info->eap);
+
+ if (info->errsts & 0x0080)
+ edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
+ else
+ edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+ multi_chan ? (info->des & 0x1) : 0,
+ "i82875p CE");
+
+ return 1;
+}
+
+
+static void i82875p_check(struct mem_ctl_info *mci)
+{
+ struct i82875p_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i82875p_get_error_info(mci, &info);
+ i82875p_process_error_info(mci, &info, 1);
+}
+
+
+#ifdef CONFIG_PROC_FS
+extern int pci_proc_attach_device(struct pci_dev *);
+#endif
+
+static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ struct i82875p_pvt *pvt = NULL;
+ unsigned long last_cumul_size;
+ struct pci_dev *ovrfl_pdev;
+ void __iomem *ovrfl_window = NULL;
+
+ u32 drc;
+ u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
+ u32 nr_chans;
+ u32 drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ ovrfl_pdev = pci_find_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
+
+ if (!ovrfl_pdev) {
+ /*
+ * Intel tells BIOS developers to hide device 6 which
+ * configures the overflow device access containing
+ * the DRBs - this is where we expose device 6.
+ * http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm
+ */
+ pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
+ ovrfl_pdev =
+ pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
+ if (!ovrfl_pdev)
+ goto fail;
+ }
+#ifdef CONFIG_PROC_FS
+ if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to attach overflow device\n",
+ __func__);
+ goto fail;
+ }
+#endif /* CONFIG_PROC_FS */
+ if (pci_enable_device(ovrfl_pdev)) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to enable overflow device\n",
+ __func__);
+ goto fail;
+ }
+
+ if (pci_request_regions(ovrfl_pdev, pci_name(ovrfl_pdev))) {
+#ifdef CORRECT_BIOS
+ goto fail;
+#endif
+ }
+ /* cache is irrelevant for PCI bus reads/writes */
+ ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
+ pci_resource_len(ovrfl_pdev, 0));
+
+ if (!ovrfl_window) {
+ printk(KERN_ERR "MC: " __FILE__
+ ": %s(): Failed to ioremap bar6\n", __func__);
+ goto fail;
+ }
+
+ /* need to find out the number of channels */
+ drc = readl(ovrfl_window + I82875P_DRC);
+ drc_chan = ((drc >> 21) & 0x1);
+ nr_chans = drc_chan + 1;
+ drc_ddim = (drc >> 18) & 0x1;
+
+ mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
+ nr_chans);
+
+ if (!mci) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+ mci->edac_cap = EDAC_FLAG_UNKNOWN;
+ /* adjust FLAGS */
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.5.2.11 $";
+ mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
+ mci->edac_check = i82875p_check;
+ mci->ctl_page_to_phys = NULL;
+
+ debugf3("MC: " __FILE__ ": %s(): init pvt\n", __func__);
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ pvt->ovrfl_pdev = ovrfl_pdev;
+ pvt->ovrfl_window = ovrfl_window;
+
+ /*
+ * The dram row boundary (DRB) reg values are boundary address
+ * for each DRAM row with a granularity of 32 or 64MB (single/dual
+ * channel operation). DRB regs are cumulative; therefore DRB7 will
+ * contain the total memory contained in all eight rows.
+ */
+ for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
+ u8 value;
+ u32 cumul_size;
+ struct csrow_info *csrow = &mci->csrows[index];
+
+ value = readb(ovrfl_window + I82875P_DRB + index);
+ cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
+ debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n",
+ __func__, index, cumul_size);
+ if (cumul_size == last_cumul_size)
+ continue; /* not populated */
+
+ csrow->first_page = last_cumul_size;
+ csrow->last_page = cumul_size - 1;
+ csrow->nr_pages = cumul_size - last_cumul_size;
+ last_cumul_size = cumul_size;
+ csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
+ csrow->mtype = MEM_DDR;
+ csrow->dtype = DEV_UNKNOWN;
+ csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
+ }
+
+ /* clear counters */
+ pci_write_bits16(mci->pdev, I82875P_ERRSTS, 0x0081, 0x0081);
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+ fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ if (ovrfl_window)
+ iounmap(ovrfl_window);
+
+ if (ovrfl_pdev) {
+ pci_release_regions(ovrfl_pdev);
+ pci_disable_device(ovrfl_pdev);
+ }
+
+ /* NOTE: the ovrfl proc entry and pci_dev are intentionally left */
+ return rc;
+}
+
+
+/* returns count (>= 0), or negative on error */
+static int __devinit i82875p_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ printk(KERN_INFO "i82875p init one\n");
+ if(pci_enable_device(pdev) < 0)
+ return -EIO;
+ rc = i82875p_probe1(pdev, ent->driver_data);
+ if (mci_pdev == NULL)
+ mci_pdev = pci_dev_get(pdev);
+ return rc;
+}
+
+
+static void __devexit i82875p_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+ struct i82875p_pvt *pvt = NULL;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if ((mci = edac_mc_find_mci_by_pdev(pdev)) == NULL)
+ return;
+
+ pvt = (struct i82875p_pvt *) mci->pvt_info;
+ if (pvt->ovrfl_window)
+ iounmap(pvt->ovrfl_window);
+
+ if (pvt->ovrfl_pdev) {
+#ifdef CORRECT_BIOS
+ pci_release_regions(pvt->ovrfl_pdev);
+#endif /*CORRECT_BIOS */
+ pci_disable_device(pvt->ovrfl_pdev);
+ pci_dev_put(pvt->ovrfl_pdev);
+ }
+
+ if (edac_mc_del_mc(mci))
+ return;
+
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
+ {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ I82875P},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
+
+
+static struct pci_driver i82875p_driver = {
+ .name = BS_MOD_STR,
+ .probe = i82875p_init_one,
+ .remove = __devexit_p(i82875p_remove_one),
+ .id_table = i82875p_pci_tbl,
+};
+
+
+static int __init i82875p_init(void)
+{
+ int pci_rc;
+
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+ pci_rc = pci_register_driver(&i82875p_driver);
+ if (pci_rc < 0)
+ return pci_rc;
+ if (mci_pdev == NULL) {
+ i82875p_registered = 0;
+ mci_pdev =
+ pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82875_0, NULL);
+ if (!mci_pdev) {
+ debugf0("875p pci_get_device fail\n");
+ return -ENODEV;
+ }
+ pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
+ if (pci_rc < 0) {
+ debugf0("875p init fail\n");
+ pci_dev_put(mci_pdev);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+
+static void __exit i82875p_exit(void)
+{
+ debugf3("MC: " __FILE__ ": %s()\n", __func__);
+
+ pci_unregister_driver(&i82875p_driver);
+ if (!i82875p_registered) {
+ i82875p_remove_one(mci_pdev);
+ pci_dev_put(mci_pdev);
+ }
+}
+
+
+module_init(i82875p_init);
+module_exit(i82875p_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
+MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
diff --git a/drivers/edac/r82600_edac.c b/drivers/edac/r82600_edac.c
new file mode 100644
index 000000000000..e90892831b90
--- /dev/null
+++ b/drivers/edac/r82600_edac.c
@@ -0,0 +1,407 @@
+/*
+ * Radisys 82600 Embedded chipset Memory Controller kernel module
+ * (C) 2005 EADS Astrium
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Tim Small <tim@buttersideup.com>, based on work by Thayne
+ * Harbaugh, Dan Hollis <goemon at anime dot net> and others.
+ *
+ * $Id: edac_r82600.c,v 1.1.2.6 2005/10/05 00:43:44 dsp_llnl Exp $
+ *
+ * Written with reference to 82600 High Integration Dual PCI System
+ * Controller Data Book:
+ * http://www.radisys.com/files/support_downloads/007-01277-0002.82600DataBook.pdf
+ * references to this document given in []
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/slab.h>
+
+#include "edac_mc.h"
+
+/* Radisys say "The 82600 integrates a main memory SDRAM controller that
+ * supports up to four banks of memory. The four banks can support a mix of
+ * sizes of 64 bit wide (72 bits with ECC) Synchronous DRAM (SDRAM) DIMMs,
+ * each of which can be any size from 16MB to 512MB. Both registered (control
+ * signals buffered) and unbuffered DIMM types are supported. Mixing of
+ * registered and unbuffered DIMMs as well as mixing of ECC and non-ECC DIMMs
+ * is not allowed. The 82600 SDRAM interface operates at the same frequency as
+ * the CPU bus, 66MHz, 100MHz or 133MHz."
+ */
+
+#define R82600_NR_CSROWS 4
+#define R82600_NR_CHANS 1
+#define R82600_NR_DIMMS 4
+
+#define R82600_BRIDGE_ID 0x8200
+
+/* Radisys 82600 register addresses - device 0 function 0 - PCI bridge */
+#define R82600_DRAMC 0x57 /* Various SDRAM related control bits
+ * all bits are R/W
+ *
+ * 7 SDRAM ISA Hole Enable
+ * 6 Flash Page Mode Enable
+ * 5 ECC Enable: 1=ECC 0=noECC
+ * 4 DRAM DIMM Type: 1=
+ * 3 BIOS Alias Disable
+ * 2 SDRAM BIOS Flash Write Enable
+ * 1:0 SDRAM Refresh Rate: 00=Disabled
+ * 01=7.8usec (256Mbit SDRAMs)
+ * 10=15.6us 11=125usec
+ */
+
+#define R82600_SDRAMC 0x76 /* "SDRAM Control Register"
+ * More SDRAM related control bits
+ * all bits are R/W
+ *
+ * 15:8 Reserved.
+ *
+ * 7:5 Special SDRAM Mode Select
+ *
+ * 4 Force ECC
+ *
+ * 1=Drive ECC bits to 0 during
+ * write cycles (i.e. ECC test mode)
+ *
+ * 0=Normal ECC functioning
+ *
+ * 3 Enhanced Paging Enable
+ *
+ * 2 CAS# Latency 0=3clks 1=2clks
+ *
+ * 1 RAS# to CAS# Delay 0=3 1=2
+ *
+ * 0 RAS# Precharge 0=3 1=2
+ */
+
+#define R82600_EAP 0x80 /* ECC Error Address Pointer Register
+ *
+ * 31 Disable Hardware Scrubbing (RW)
+ * 0=Scrub on corrected read
+ * 1=Don't scrub on corrected read
+ *
+ * 30:12 Error Address Pointer (RO)
+ * Upper 19 bits of error address
+ *
+ * 11:4 Syndrome Bits (RO)
+ *
+ * 3 BSERR# on multibit error (RW)
+ * 1=enable 0=disable
+ *
+ * 2 NMI on Single Bit Eror (RW)
+ * 1=NMI triggered by SBE n.b. other
+ * prerequeists
+ * 0=NMI not triggered
+ *
+ * 1 MBE (R/WC)
+ * read 1=MBE at EAP (see above)
+ * read 0=no MBE, or SBE occurred first
+ * write 1=Clear MBE status (must also
+ * clear SBE)
+ * write 0=NOP
+ *
+ * 1 SBE (R/WC)
+ * read 1=SBE at EAP (see above)
+ * read 0=no SBE, or MBE occurred first
+ * write 1=Clear SBE status (must also
+ * clear MBE)
+ * write 0=NOP
+ */
+
+#define R82600_DRBA 0x60 /* + 0x60..0x63 SDRAM Row Boundry Address
+ * Registers
+ *
+ * 7:0 Address lines 30:24 - upper limit of
+ * each row [p57]
+ */
+
+struct r82600_error_info {
+ u32 eapr;
+};
+
+
+static unsigned int disable_hardware_scrub = 0;
+
+
+static void r82600_get_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info)
+{
+ pci_read_config_dword(mci->pdev, R82600_EAP, &info->eapr);
+
+ if (info->eapr & BIT(0))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+
+ if (info->eapr & BIT(1))
+ /* Clear error to allow next error to be reported [p.62] */
+ pci_write_bits32(mci->pdev, R82600_EAP,
+ ((u32) BIT(0) & (u32) BIT(1)),
+ ((u32) BIT(0) & (u32) BIT(1)));
+}
+
+
+static int r82600_process_error_info (struct mem_ctl_info *mci,
+ struct r82600_error_info *info, int handle_errors)
+{
+ int error_found;
+ u32 eapaddr, page;
+ u32 syndrome;
+
+ error_found = 0;
+
+ /* bits 30:12 store the upper 19 bits of the 32 bit error address */
+ eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
+ /* Syndrome in bits 11:4 [p.62] */
+ syndrome = (info->eapr >> 4) & 0xFF;
+
+ /* the R82600 reports at less than page *
+ * granularity (upper 19 bits only) */
+ page = eapaddr >> PAGE_SHIFT;
+
+ if (info->eapr & BIT(0)) { /* CE? */
+ error_found = 1;
+
+ if (handle_errors)
+ edac_mc_handle_ce(
+ mci, page, 0, /* not avail */
+ syndrome,
+ edac_mc_find_csrow_by_page(mci, page),
+ 0, /* channel */
+ mci->ctl_name);
+ }
+
+ if (info->eapr & BIT(1)) { /* UE? */
+ error_found = 1;
+
+ if (handle_errors)
+ /* 82600 doesn't give enough info */
+ edac_mc_handle_ue(mci, page, 0,
+ edac_mc_find_csrow_by_page(mci, page),
+ mci->ctl_name);
+ }
+
+ return error_found;
+}
+
+static void r82600_check(struct mem_ctl_info *mci)
+{
+ struct r82600_error_info info;
+
+ debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ r82600_get_error_info(mci, &info);
+ r82600_process_error_info(mci, &info, 1);
+}
+
+static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ int rc = -ENODEV;
+ int index;
+ struct mem_ctl_info *mci = NULL;
+ u8 dramcr;
+ u32 ecc_on;
+ u32 reg_sdram;
+ u32 eapr;
+ u32 scrub_disabled;
+ u32 sdram_refresh_rate;
+ u32 row_high_limit_last = 0;
+ u32 eap_init_bits;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+
+ pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
+ pci_read_config_dword(pdev, R82600_EAP, &eapr);
+
+ ecc_on = dramcr & BIT(5);
+ reg_sdram = dramcr & BIT(4);
+ scrub_disabled = eapr & BIT(31);
+ sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
+
+ debugf2("MC: " __FILE__ ": %s(): sdram refresh rate = %#0x\n",
+ __func__, sdram_refresh_rate);
+
+ debugf2("MC: " __FILE__ ": %s(): DRAMC register = %#0x\n", __func__,
+ dramcr);
+
+ mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
+
+ if (mci == NULL) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->pdev = pdev;
+ mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
+
+ mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ /* FIXME try to work out if the chip leads have been *
+ * used for COM2 instead on this board? [MA6?] MAYBE: */
+
+ /* On the R82600, the pins for memory bits 72:65 - i.e. the *
+ * EC bits are shared with the pins for COM2 (!), so if COM2 *
+ * is enabled, we assume COM2 is wired up, and thus no EDAC *
+ * is possible. */
+ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+ if (ecc_on) {
+ if (scrub_disabled)
+ debugf3("MC: " __FILE__ ": %s(): mci = %p - "
+ "Scrubbing disabled! EAP: %#0x\n", __func__,
+ mci, eapr);
+ } else
+ mci->edac_cap = EDAC_FLAG_NONE;
+
+ mci->mod_name = BS_MOD_STR;
+ mci->mod_ver = "$Revision: 1.1.2.6 $";
+ mci->ctl_name = "R82600";
+ mci->edac_check = r82600_check;
+ mci->ctl_page_to_phys = NULL;
+
+ for (index = 0; index < mci->nr_csrows; index++) {
+ struct csrow_info *csrow = &mci->csrows[index];
+ u8 drbar; /* sDram Row Boundry Address Register */
+ u32 row_high_limit;
+ u32 row_base;
+
+ /* find the DRAM Chip Select Base address and mask */
+ pci_read_config_byte(mci->pdev, R82600_DRBA + index, &drbar);
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d DRBA = %#0x\n",
+ mci->mc_idx, __func__, index, drbar);
+
+ row_high_limit = ((u32) drbar << 24);
+/* row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
+
+ debugf1("MC%d: " __FILE__ ": %s() Row=%d, "
+ "Boundry Address=%#0x, Last = %#0x \n",
+ mci->mc_idx, __func__, index, row_high_limit,
+ row_high_limit_last);
+
+ /* Empty row [p.57] */
+ if (row_high_limit == row_high_limit_last)
+ continue;
+
+ row_base = row_high_limit_last;
+
+ csrow->first_page = row_base >> PAGE_SHIFT;
+ csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
+ csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
+ /* Error address is top 19 bits - so granularity is *
+ * 14 bits */
+ csrow->grain = 1 << 14;
+ csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
+ /* FIXME - check that this is unknowable with this chipset */
+ csrow->dtype = DEV_UNKNOWN;
+
+ /* Mode is global on 82600 */
+ csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
+ row_high_limit_last = row_high_limit;
+ }
+
+ /* clear counters */
+ /* FIXME should we? */
+
+ if (edac_mc_add_mc(mci)) {
+ debugf3("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ goto fail;
+ }
+
+ /* get this far and it's successful */
+
+ /* Clear error flags to allow next error to be reported [p.62] */
+ /* Test systems seem to always have the UE flag raised on boot */
+
+ eap_init_bits = BIT(0) & BIT(1);
+ if (disable_hardware_scrub) {
+ eap_init_bits |= BIT(31);
+ debugf3("MC: " __FILE__ ": %s(): Disabling Hardware Scrub "
+ "(scrub on error)\n", __func__);
+ }
+
+ pci_write_bits32(mci->pdev, R82600_EAP, eap_init_bits,
+ eap_init_bits);
+
+ debugf3("MC: " __FILE__ ": %s(): success\n", __func__);
+ return 0;
+
+fail:
+ if (mci)
+ edac_mc_free(mci);
+
+ return rc;
+}
+
+/* returns count (>= 0), or negative on error */
+static int __devinit r82600_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* don't need to call pci_device_enable() */
+ return r82600_probe1(pdev, ent->driver_data);
+}
+
+
+static void __devexit r82600_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (((mci = edac_mc_find_mci_by_pdev(pdev)) != NULL) &&
+ !edac_mc_del_mc(mci))
+ edac_mc_free(mci);
+}
+
+
+static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
+
+
+static struct pci_driver r82600_driver = {
+ .name = BS_MOD_STR,
+ .probe = r82600_init_one,
+ .remove = __devexit_p(r82600_remove_one),
+ .id_table = r82600_pci_tbl,
+};
+
+
+static int __init r82600_init(void)
+{
+ return pci_register_driver(&r82600_driver);
+}
+
+
+static void __exit r82600_exit(void)
+{
+ pci_unregister_driver(&r82600_driver);
+}
+
+
+module_init(r82600_init);
+module_exit(r82600_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
+ "on behalf of EADS Astrium");
+MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
+
+module_param(disable_hardware_scrub, bool, 0644);
+MODULE_PARM_DESC(disable_hardware_scrub,
+ "If set, disable the chipset's automatic scrub for CEs");
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index dfedb777d8c9..fdb8b042e64d 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -49,7 +49,7 @@
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
MODULE_LICENSE("GPL");
-MODULE_VERSION("3.1");
+MODULE_VERSION("3.2");
#define BIOS_SCAN_LIMIT 0xffffffff
#define MAX_IMAGE_LENGTH 16
@@ -564,12 +564,10 @@ static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
static void callbackfn_rbu(const struct firmware *fw, void *context)
{
- int rc = 0;
+ rbu_data.entry_created = 0;
- if (!fw || !fw->size) {
- rbu_data.entry_created = 0;
+ if (!fw || !fw->size)
return;
- }
spin_lock(&rbu_data.lock);
if (!strcmp(image_type, "mono")) {
@@ -592,15 +590,6 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
} 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);
- else
- rbu_data.entry_created = 1;
}
static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
@@ -735,14 +724,7 @@ static int __init dcdrbu_init(void)
sysfs_create_bin_file(&rbu_device->dev.kobj,
&rbu_packet_size_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);
- else
- rbu_data.entry_created = 1;
-
+ rbu_data.entry_created = 0;
return rc;
}
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index bda5bce681b6..343379f23a53 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -65,11 +65,11 @@
* v0.01 release to linux-ia64@linuxia64.org
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/sched.h> /* for capable() */
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/string.h>
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index db358cfa7cbf..c58295914365 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -350,6 +350,18 @@ config SENSORS_VIA686A
This driver can also be built as a module. If so, the module
will be called via686a.
+config SENSORS_VT8231
+ tristate "VT8231"
+ depends on HWMON && I2C && PCI && EXPERIMENTAL
+ select HWMON_VID
+ select I2C_ISA
+ help
+ If you say yes here then you get support for the integrated sensors
+ in the VIA VT8231 device.
+
+ This driver can also be built as a module. If so, the module
+ will be called vt8231.
+
config SENSORS_W83781D
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
depends on HWMON && I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f7d6a2f61ee7..06d4a1d14105 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
+obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 8102876c7c3f..665612729cb9 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -126,10 +126,10 @@ static int read_only;
/* This is the driver that will be inserted */
static struct i2c_driver adm1021_driver = {
- .owner = THIS_MODULE,
- .name = "adm1021",
+ .driver = {
+ .name = "adm1021",
+ },
.id = I2C_DRIVERID_ADM1021,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm1021_attach_adapter,
.detach_client = adm1021_detach_client,
};
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 3ec12421694f..9331c56d2ba6 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -118,10 +118,10 @@ static struct adm1025_data *adm1025_update_device(struct device *dev);
*/
static struct i2c_driver adm1025_driver = {
- .owner = THIS_MODULE,
- .name = "adm1025",
+ .driver = {
+ .name = "adm1025",
+ },
.id = I2C_DRIVERID_ADM1025,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm1025_attach_adapter,
.detach_client = adm1025_detach_client,
};
@@ -287,8 +287,6 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char
struct adm1025_data *data = adm1025_update_device(dev);
return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
}
-/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
@@ -444,8 +442,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
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_alarms);
- /* in1_ref is deprecated, remove after 2005-11-11 */
- device_create_file(&new_client->dev, &dev_attr_in1_ref);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index e0f56549d1d8..fefe6e74fd02 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -308,9 +308,9 @@ static void adm1026_init_client(struct i2c_client *client);
static struct i2c_driver adm1026_driver = {
- .owner = THIS_MODULE,
- .name = "adm1026",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "adm1026",
+ },
.attach_adapter = adm1026_attach_adapter,
.detach_client = adm1026_detach_client,
};
@@ -1227,8 +1227,6 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
}
-/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
-static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1673,8 +1671,6 @@ static int adm1026_detect(struct i2c_adapter *adapter, int address,
device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
- /* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
- device_create_file(&new_client->dev, &dev_attr_vid);
device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &dev_attr_alarms);
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index 7c545d5eee45..d06397966081 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -105,9 +105,9 @@ static struct adm1031_data *adm1031_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver adm1031_driver = {
- .owner = THIS_MODULE,
- .name = "adm1031",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "adm1031",
+ },
.attach_adapter = adm1031_attach_adapter,
.detach_client = adm1031_detach_client,
};
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 11dc95f8a17e..5ddc22fea4a3 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -137,10 +137,10 @@ static struct adm9240_data *adm9240_update_device(struct device *dev);
/* driver data */
static struct i2c_driver adm9240_driver = {
- .owner = THIS_MODULE,
- .name = "adm9240",
+ .driver = {
+ .name = "adm9240",
+ },
.id = I2C_DRIVERID_ADM9240,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adm9240_attach_adapter,
.detach_client = adm9240_detach_client,
};
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 52c469722a65..ae9de63cf2e0 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -217,10 +217,10 @@ static struct asb100_data *asb100_update_device(struct device *dev);
static void asb100_init_client(struct i2c_client *client);
static struct i2c_driver asb100_driver = {
- .owner = THIS_MODULE,
- .name = "asb100",
+ .driver = {
+ .name = "asb100",
+ },
.id = I2C_DRIVERID_ASB100,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = asb100_attach_adapter,
.detach_client = asb100_detach_client,
};
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 53324f56404e..b0c490073c8e 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -50,9 +50,9 @@ static struct atxp1_data * atxp1_update_device(struct device *dev);
static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
static struct i2c_driver atxp1_driver = {
- .owner = THIS_MODULE,
- .name = "atxp1",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "atxp1",
+ },
.attach_adapter = atxp1_attach_adapter,
.detach_client = atxp1_detach_client,
};
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 34f71b7c7f37..203f9c7abb20 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -89,10 +89,10 @@ static struct ds1621_data *ds1621_update_client(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver ds1621_driver = {
- .owner = THIS_MODULE,
- .name = "ds1621",
+ .driver = {
+ .name = "ds1621",
+ },
.id = I2C_DRIVERID_DS1621,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ds1621_attach_adapter,
.detach_client = ds1621_detach_client,
};
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index a02e1c34c757..25409181d1eb 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -118,10 +118,10 @@ static int fscher_write_value(struct i2c_client *client, u8 reg, u8 value);
*/
static struct i2c_driver fscher_driver = {
- .owner = THIS_MODULE,
- .name = "fscher",
+ .driver = {
+ .name = "fscher",
+ },
.id = I2C_DRIVERID_FSCHER,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = fscher_attach_adapter,
.detach_client = fscher_detach_client,
};
diff --git a/drivers/hwmon/fscpos.c b/drivers/hwmon/fscpos.c
index 64e4edc64f8d..6d0146b57020 100644
--- a/drivers/hwmon/fscpos.c
+++ b/drivers/hwmon/fscpos.c
@@ -100,10 +100,10 @@ static void reset_fan_alarm(struct i2c_client *client, int nr);
* Driver data (common to all clients)
*/
static struct i2c_driver fscpos_driver = {
- .owner = THIS_MODULE,
- .name = "fscpos",
+ .driver = {
+ .name = "fscpos",
+ },
.id = I2C_DRIVERID_FSCPOS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = fscpos_attach_adapter,
.detach_client = fscpos_detach_client,
};
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index 2f178dbe3d87..9e685e3a3bc9 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -151,10 +151,10 @@ static struct gl518_data *gl518_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver gl518_driver = {
- .owner = THIS_MODULE,
- .name = "gl518sm",
+ .driver = {
+ .name = "gl518sm",
+ },
.id = I2C_DRIVERID_GL518,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = gl518_attach_adapter,
.detach_client = gl518_detach_client,
};
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index c39ba1239426..baee60e44b52 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -109,10 +109,10 @@ static struct gl520_data *gl520_update_device(struct device *dev);
/* Driver data */
static struct i2c_driver gl520_driver = {
- .owner = THIS_MODULE,
- .name = "gl520sm",
+ .driver = {
+ .name = "gl520sm",
+ },
.id = I2C_DRIVERID_GL520,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = gl520_attach_adapter,
.detach_client = gl520_detach_client,
};
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 312769ad4dab..e497274916ce 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -49,20 +49,22 @@
. . . .
11110 = 0.800 V
11111 = 0.000 V (off)
+
+ The 17 specification is in fact Intel Mobile Voltage Positioning -
+ (IMVP-II). You can find more information in the datasheet of Max1718
+ http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452
+
*/
/* 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_from_reg(int val, u8 vrm)
{
int vid;
switch(vrm) {
- case 0:
- return 0;
-
case 100: /* VRD 10.0 */
if((val & 0x1f) == 0x1f)
return 0;
@@ -91,10 +93,16 @@ int vid_from_reg(int val, int vrm)
case 84: /* VRM 8.4 */
val &= 0x0f;
/* fall through */
- default: /* VRM 8.2 */
+ case 82: /* VRM 8.2 */
return(val == 0x1f ? 0 :
val & 0x10 ? 5100 - (val) * 100 :
2050 - (val) * 50);
+ case 17: /* Intel IMVP-II */
+ return(val & 0x10 ? 975 - (val & 0xF) * 25 :
+ 1750 - val * 50);
+ default: /* report 0 for unknown */
+ printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
+ return 0;
}
}
@@ -108,30 +116,36 @@ struct vrm_model {
u8 vendor;
u8 eff_family;
u8 eff_model;
- int vrm_type;
+ u8 eff_stepping;
+ u8 vrm_type;
};
#define ANY 0xFF
#ifdef CONFIG_X86
+/* the stepping parameter is highest acceptable stepping for current line */
+
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 */
+ {X86_VENDOR_AMD, 0x6, ANY, ANY, 90}, /* Athlon Duron etc */
+ {X86_VENDOR_AMD, 0xF, ANY, ANY, 24}, /* Athlon 64, Opteron and above VRM 24 */
+ {X86_VENDOR_INTEL, 0x6, 0x9, ANY, 85}, /* 0.13um too */
+ {X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
+ {X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
+ {X86_VENDOR_INTEL, 0x7, ANY, ANY, 0}, /* Itanium */
+ {X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */
+ {X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */
+ {X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */
+ {X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */
+ {X86_VENDOR_INTEL, 0x10, ANY, ANY, 0}, /* Itanium 2 */
+ {X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */
+ {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
+ {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */
+ {X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M */
+ {X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
};
-static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
{
int i = 0;
@@ -139,7 +153,8 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
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)))
+ (vrm_models[i].eff_model==ANY)) &&
+ (eff_stepping <= vrm_models[i].eff_stepping))
return vrm_models[i].vrm_type;
i++;
}
@@ -147,12 +162,11 @@ static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
return 0;
}
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
{
struct cpuinfo_x86 *c = cpu_data;
u32 eax;
- u8 eff_family, eff_model;
- int vrm_ret;
+ u8 eff_family, eff_model, eff_stepping, vrm_ret;
if (c->x86 < 6) /* Any CPU with family lower than 6 */
return 0; /* doesn't have VID and/or CPUID */
@@ -160,20 +174,21 @@ int vid_which_vrm(void)
eax = cpuid_eax(1);
eff_family = ((eax & 0x00000F00)>>8);
eff_model = ((eax & 0x000000F0)>>4);
+ eff_stepping = eax & 0xF;
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);
+ vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, 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 */
+/* and now for something completely different for the non-x86 world */
#else
-int vid_which_vrm(void)
+u8 vid_which_vrm(void)
{
printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
return 0;
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index a61f5d00f10a..0da7c9c508c3 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -213,7 +213,7 @@ struct it87_data {
u8 sensor; /* Register value */
u8 fan_div[3]; /* Register encoding, shifted right */
u8 vid; /* Register encoding, combined */
- int vrm;
+ u8 vrm;
u32 alarms; /* Register encoding, combined */
u8 fan_main_ctrl; /* Register value */
u8 manual_pwm_ctl[3]; /* manual PWM value set by user */
@@ -234,17 +234,18 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data);
static struct i2c_driver it87_driver = {
- .owner = THIS_MODULE,
- .name = "it87",
+ .driver = {
+ .name = "it87",
+ },
.id = I2C_DRIVERID_IT87,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = it87_attach_adapter,
.detach_client = it87_detach_client,
};
static struct i2c_driver it87_isa_driver = {
- .owner = THIS_MODULE,
- .name = "it87-isa",
+ .driver = {
+ .name = "it87-isa",
+ },
.attach_adapter = it87_isa_attach_adapter,
.detach_client = it87_detach_client,
};
@@ -668,7 +669,7 @@ static ssize_t
show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf, "%ld\n", (long) data->vrm);
+ return sprintf(buf, "%u\n", data->vrm);
}
static ssize_t
store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
@@ -761,7 +762,8 @@ static 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_isa_driver.name))
+ if (!request_region(address, IT87_EXTENT,
+ it87_isa_driver.driver.name))
goto ERROR0;
/* For now, we presume we have a valid client. We create the
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index 954ec2497249..6b1aa7ef552e 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -139,9 +139,9 @@ static void lm63_init_client(struct i2c_client *client);
*/
static struct i2c_driver lm63_driver = {
- .owner = THIS_MODULE,
- .name = "lm63",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "lm63",
+ },
.attach_adapter = lm63_attach_adapter,
.detach_client = lm63_detach_client,
};
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index d70f4c8fc1e6..74ca2c8c61c3 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -66,10 +66,10 @@ static struct lm75_data *lm75_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver lm75_driver = {
- .owner = THIS_MODULE,
- .name = "lm75",
+ .driver = {
+ .name = "lm75",
+ },
.id = I2C_DRIVERID_LM75,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm75_attach_adapter,
.detach_client = lm75_detach_client,
};
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 9380fda7dcd1..a2f420d01fb7 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -74,9 +74,9 @@ static struct lm77_data *lm77_update_device(struct device *dev);
/* This is the driver that will be inserted */
static struct i2c_driver lm77_driver = {
- .owner = THIS_MODULE,
- .name = "lm77",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "lm77",
+ },
.attach_adapter = lm77_attach_adapter,
.detach_client = lm77_detach_client,
};
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 78cdd506439f..e404001e20da 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -164,17 +164,18 @@ static void lm78_init_client(struct i2c_client *client);
static struct i2c_driver lm78_driver = {
- .owner = THIS_MODULE,
- .name = "lm78",
+ .driver = {
+ .name = "lm78",
+ },
.id = I2C_DRIVERID_LM78,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm78_attach_adapter,
.detach_client = lm78_detach_client,
};
static struct i2c_driver lm78_isa_driver = {
- .owner = THIS_MODULE,
- .name = "lm78-isa",
+ .driver = {
+ .name = "lm78-isa",
+ },
.attach_adapter = lm78_isa_attach_adapter,
.detach_client = lm78_detach_client,
};
@@ -497,7 +498,7 @@ static 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_isa_driver.name)) {
+ lm78_isa_driver.driver.name)) {
err = -EBUSY;
goto ERROR0;
}
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index c359fdea211e..c9a7cdea7bd7 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -143,10 +143,10 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
*/
static struct i2c_driver lm80_driver = {
- .owner = THIS_MODULE,
- .name = "lm80",
+ .driver = {
+ .name = "lm80",
+ },
.id = I2C_DRIVERID_LM80,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm80_attach_adapter,
.detach_client = lm80_detach_client,
};
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 9a70611a9f69..26dfa9e216c2 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -124,10 +124,10 @@ static struct lm83_data *lm83_update_device(struct device *dev);
*/
static struct i2c_driver lm83_driver = {
- .owner = THIS_MODULE,
- .name = "lm83",
+ .driver = {
+ .name = "lm83",
+ },
.id = I2C_DRIVERID_LM83,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm83_attach_adapter,
.detach_client = lm83_detach_client,
};
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index d1070ed2bee6..7389a0127547 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -380,10 +380,10 @@ static void lm85_init_client(struct i2c_client *client);
static struct i2c_driver lm85_driver = {
- .owner = THIS_MODULE,
- .name = "lm85",
+ .driver = {
+ .name = "lm85",
+ },
.id = I2C_DRIVERID_LM85,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm85_attach_adapter,
.detach_client = lm85_detach_client,
};
@@ -443,7 +443,17 @@ show_fan_offset(4);
static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+ int vid;
+
+ if (data->type == adt7463 && (data->vid & 0x80)) {
+ /* 6-pin VID (VRM 10) */
+ vid = vid_from_reg(data->vid & 0x3f, data->vrm);
+ } else {
+ /* 5-pin VID (VRM 9) */
+ vid = vid_from_reg(data->vid & 0x1f, data->vrm);
+ }
+
+ return sprintf(buf, "%d\n", vid);
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
@@ -1176,17 +1186,14 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
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_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_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_temp1_input);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_temp3_input);
@@ -1224,6 +1231,15 @@ static int lm85_detect(struct i2c_adapter *adapter, int address,
device_create_file(&new_client->dev, &dev_attr_temp2_auto_temp_crit);
device_create_file(&new_client->dev, &dev_attr_temp3_auto_temp_crit);
+ /* The ADT7463 has an optional VRM 10 mode where pin 21 is used
+ as a sixth digital VID input rather than an analog input. */
+ data->vid = lm85_read_value(new_client, LM85_REG_VID);
+ if (!(kind == adt7463 && (data->vid & 0x80))) {
+ device_create_file(&new_client->dev, &dev_attr_in4_input);
+ device_create_file(&new_client->dev, &dev_attr_in4_min);
+ device_create_file(&new_client->dev, &dev_attr_in4_max);
+ }
+
return 0;
/* Error out and cleanup code */
@@ -1382,11 +1398,18 @@ static struct lm85_data *lm85_update_device(struct device *dev)
irrelevant. So it is left in 4*/
data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
- for (i = 0; i <= 4; ++i) {
+ data->vid = lm85_read_value(client, LM85_REG_VID);
+
+ for (i = 0; i <= 3; ++i) {
data->in[i] =
lm85_read_value(client, LM85_REG_IN(i));
}
+ if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ data->in[4] = lm85_read_value(client,
+ LM85_REG_IN(4));
+ }
+
for (i = 0; i <= 3; ++i) {
data->fan[i] =
lm85_read_value(client, LM85_REG_FAN(i));
@@ -1450,13 +1473,20 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* Things that don't change often */
dev_dbg(&client->dev, "Reading config values\n");
- for (i = 0; i <= 4; ++i) {
+ for (i = 0; i <= 3; ++i) {
data->in_min[i] =
lm85_read_value(client, LM85_REG_IN_MIN(i));
data->in_max[i] =
lm85_read_value(client, LM85_REG_IN_MAX(i));
}
+ if (!(data->type == adt7463 && (data->vid & 0x80))) {
+ data->in_min[4] = lm85_read_value(client,
+ LM85_REG_IN_MIN(4));
+ data->in_max[4] = lm85_read_value(client,
+ LM85_REG_IN_MAX(4));
+ }
+
if ( data->type == emc6d100 ) {
for (i = 5; i <= 7; ++i) {
data->in_min[i] =
@@ -1478,8 +1508,6 @@ static struct lm85_data *lm85_update_device(struct device *dev)
lm85_read_value(client, LM85_REG_TEMP_MAX(i));
}
- data->vid = lm85_read_value(client, LM85_REG_VID);
-
for (i = 0; i <= 2; ++i) {
int val ;
data->autofan[i].config =
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index eeec18177861..6ba34c302d8d 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -161,10 +161,10 @@ static struct lm87_data *lm87_update_device(struct device *dev);
*/
static struct i2c_driver lm87_driver = {
- .owner = THIS_MODULE,
- .name = "lm87",
+ .driver = {
+ .name = "lm87",
+ },
.id = I2C_DRIVERID_LM87,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm87_attach_adapter,
.detach_client = lm87_detach_client,
};
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 83cf2e1b09f5..5679464447cc 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -186,10 +186,10 @@ static struct lm90_data *lm90_update_device(struct device *dev);
*/
static struct i2c_driver lm90_driver = {
- .owner = THIS_MODULE,
- .name = "lm90",
+ .driver = {
+ .name = "lm90",
+ },
.id = I2C_DRIVERID_LM90,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm90_attach_adapter,
.detach_client = lm90_detach_client,
};
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 7a4b3701ed1a..b0c4cb730a7e 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -410,10 +410,10 @@ static int lm92_detach_client(struct i2c_client *client)
*/
static struct i2c_driver lm92_driver = {
- .owner = THIS_MODULE,
- .name = "lm92",
+ .driver = {
+ .name = "lm92",
+ },
.id = I2C_DRIVERID_LM92,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = lm92_attach_adapter,
.detach_client = lm92_detach_client,
};
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 69e7e125683b..3abe330b22ce 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -90,9 +90,9 @@ static struct max1619_data *max1619_update_device(struct device *dev);
*/
static struct i2c_driver max1619_driver = {
- .owner = THIS_MODULE,
- .name = "max1619",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "max1619",
+ },
.attach_adapter = max1619_attach_adapter,
.detach_client = max1619_detach_client,
};
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 17f745a23d04..f161e88e3bb6 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -236,8 +236,9 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
*/
static struct i2c_driver pc87360_driver = {
- .owner = THIS_MODULE,
- .name = "pc87360",
+ .driver = {
+ .name = "pc87360",
+ },
.attach_adapter = pc87360_detect,
.detach_client = pc87360_detach_client,
};
@@ -798,7 +799,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
for (i = 0; i < 3; i++) {
if (((data->address[i] = extra_isa[i]))
&& !request_region(extra_isa[i], PC87360_EXTENT,
- pc87360_driver.name)) {
+ pc87360_driver.driver.name)) {
dev_err(&new_client->dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 9c6cadec1087..8be5189d9bd9 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -198,8 +198,9 @@ static struct sis5595_data *sis5595_update_device(struct device *dev);
static void sis5595_init_client(struct i2c_client *client);
static struct i2c_driver sis5595_driver = {
- .owner = THIS_MODULE,
- .name = "sis5595",
+ .driver = {
+ .name = "sis5595",
+ },
.attach_adapter = sis5595_detect,
.detach_client = sis5595_detach_client,
};
@@ -484,7 +485,8 @@ static int sis5595_detect(struct i2c_adapter *adapter)
if (force_addr)
address = force_addr & ~(SIS5595_EXTENT - 1);
/* Reserve the ISA region */
- if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
+ if (!request_region(address, SIS5595_EXTENT,
+ sis5595_driver.driver.name)) {
err = -EBUSY;
goto exit;
}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 2a3e21b5b6b4..8663bbbe97f5 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -226,8 +226,9 @@ static int smsc47b397_detach_client(struct i2c_client *client)
static int smsc47b397_detect(struct i2c_adapter *adapter);
static struct i2c_driver smsc47b397_driver = {
- .owner = THIS_MODULE,
- .name = "smsc47b397",
+ .driver = {
+ .name = "smsc47b397",
+ },
.attach_adapter = smsc47b397_detect,
.detach_client = smsc47b397_detach_client,
};
@@ -238,7 +239,8 @@ static int smsc47b397_detect(struct i2c_adapter *adapter)
struct smsc47b397_data *data;
int err = 0;
- if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+ if (!request_region(address, SMSC_EXTENT,
+ smsc47b397_driver.driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n",
address);
return -EBUSY;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 5905c1af88f2..d1e3ec0fe4df 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -126,8 +126,9 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
static struct i2c_driver smsc47m1_driver = {
- .owner = THIS_MODULE,
- .name = "smsc47m1",
+ .driver = {
+ .name = "smsc47m1",
+ },
.attach_adapter = smsc47m1_detect,
.detach_client = smsc47m1_detach_client,
};
@@ -394,7 +395,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter)
int err = 0;
int fan1, fan2, pwm1, pwm2;
- if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
+ if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
}
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 6f696f897176..cb01848729b5 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -572,8 +572,9 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/* The driver. I choose to use type i2c_driver, as at is identical to both
smbus_driver and isa_driver, and clients could be of either kind */
static struct i2c_driver via686a_driver = {
- .owner = THIS_MODULE,
- .name = "via686a",
+ .driver = {
+ .name = "via686a",
+ },
.attach_adapter = via686a_detect,
.detach_client = via686a_detach_client,
};
@@ -615,7 +616,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
}
/* Reserve the ISA region */
- if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
+ if (!request_region(address, VIA686A_EXTENT,
+ via686a_driver.driver.name)) {
dev_err(&adapter->dev, "region 0x%x already in use!\n",
address);
return -ENODEV;
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
new file mode 100644
index 000000000000..3eb08f004c0f
--- /dev/null
+++ b/drivers/hwmon/vt8231.c
@@ -0,0 +1,862 @@
+/*
+ vt8231.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Copyright (c) 2005 Roger Lucas <roger@planbit.co.uk>
+ Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Aaron M. Marsh <amarsh@sdf.lonestar.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.
+*/
+
+/* Supports VIA VT8231 South Bridge embedded sensors
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.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 int force_addr;
+module_param(force_addr, int, 0);
+MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors");
+
+/* Device address
+ Note that we can't determine the ISA address until we have initialized
+ our module */
+static unsigned short isa_address;
+
+#define VT8231_EXTENT 0x80
+#define VT8231_BASE_REG 0x70
+#define VT8231_ENABLE_REG 0x74
+
+/* The VT8231 registers
+
+ The reset value for the input channel configuration is used (Reg 0x4A=0x07)
+ which sets the selected inputs marked with '*' below if multiple options are
+ possible:
+
+ Voltage Mode Temperature Mode
+ Sensor Linux Id Linux Id VIA Id
+ -------- -------- -------- ------
+ CPU Diode N/A temp1 0
+ UIC1 in0 temp2 * 1
+ UIC2 in1 * temp3 2
+ UIC3 in2 * temp4 3
+ UIC4 in3 * temp5 4
+ UIC5 in4 * temp6 5
+ 3.3V in5 N/A
+
+ Note that the BIOS may set the configuration register to a different value
+ to match the motherboard configuration.
+*/
+
+/* fans numbered 0-1 */
+#define VT8231_REG_FAN_MIN(nr) (0x3b + (nr))
+#define VT8231_REG_FAN(nr) (0x29 + (nr))
+
+/* Voltage inputs numbered 0-5 */
+
+static const u8 regvolt[] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 };
+static const u8 regvoltmax[] = { 0x3d, 0x2b, 0x2d, 0x2f, 0x31, 0x33 };
+static const u8 regvoltmin[] = { 0x3e, 0x2c, 0x2e, 0x30, 0x32, 0x34 };
+
+/* Temperatures are numbered 1-6 according to the Linux kernel specification.
+**
+** In the VIA datasheet, however, the temperatures are numbered from zero.
+** Since it is important that this driver can easily be compared to the VIA
+** datasheet, we will use the VIA numbering within this driver and map the
+** kernel sysfs device name to the VIA number in the sysfs callback.
+*/
+
+#define VT8231_REG_TEMP_LOW01 0x49
+#define VT8231_REG_TEMP_LOW25 0x4d
+
+static const u8 regtemp[] = { 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25 };
+static const u8 regtempmax[] = { 0x39, 0x3d, 0x2b, 0x2d, 0x2f, 0x31 };
+static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 };
+
+#define TEMP_FROM_REG(reg) (((253 * 4 - (reg)) * 550 + 105) / 210)
+#define TEMP_MAXMIN_FROM_REG(reg) (((253 - (reg)) * 2200 + 105) / 210)
+#define TEMP_MAXMIN_TO_REG(val) (253 - ((val) * 210 + 1100) / 2200)
+
+#define VT8231_REG_CONFIG 0x40
+#define VT8231_REG_ALARM1 0x41
+#define VT8231_REG_ALARM2 0x42
+#define VT8231_REG_FANDIV 0x47
+#define VT8231_REG_UCH_CONFIG 0x4a
+#define VT8231_REG_TEMP1_CONFIG 0x4b
+#define VT8231_REG_TEMP2_CONFIG 0x4c
+
+/* temps 0-5 as numbered in VIA datasheet - see later for mapping to Linux
+** numbering
+*/
+#define ISTEMP(i, ch_config) ((i) == 0 ? 1 : \
+ ((ch_config) >> ((i)+1)) & 0x01)
+/* voltages 0-5 */
+#define ISVOLT(i, ch_config) ((i) == 5 ? 1 : \
+ !(((ch_config) >> ((i)+2)) & 0x01))
+
+#define DIV_FROM_REG(val) (1 << (val))
+
+/* NB The values returned here are NOT temperatures. The calibration curves
+** for the thermistor curves are board-specific and must go in the
+** sensors.conf file. Temperature sensors are actually ten bits, but the
+** VIA datasheet only considers the 8 MSBs obtained from the regtemp[]
+** register. The temperature value returned should have a magnitude of 3,
+** so we use the VIA scaling as the "true" scaling and use the remaining 2
+** LSBs as fractional precision.
+**
+** All the on-chip hardware temperature comparisons for the alarms are only
+** 8-bits wide, and compare against the 8 MSBs of the temperature. The bits
+** in the registers VT8231_REG_TEMP_LOW01 and VT8231_REG_TEMP_LOW25 are
+** ignored.
+*/
+
+/******** FAN RPM CONVERSIONS ********
+** This chip saturates back at 0, not at 255 like many the other chips.
+** So, 0 means 0 RPM
+*/
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+ if (rpm == 0)
+ return 0;
+ return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255);
+}
+
+#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
+
+struct vt8231_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ struct class_device *class_dev;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ u8 in[6]; /* Register value */
+ u8 in_max[6]; /* Register value */
+ u8 in_min[6]; /* Register value */
+ u16 temp[6]; /* Register value 10 bit, right aligned */
+ u8 temp_max[6]; /* Register value */
+ u8 temp_min[6]; /* Register value */
+ u8 fan[2]; /* Register value */
+ u8 fan_min[2]; /* Register value */
+ u8 fan_div[2]; /* Register encoding, shifted right */
+ u16 alarms; /* Register encoding */
+ u8 uch_config;
+};
+
+static struct pci_dev *s_bridge;
+static int vt8231_detect(struct i2c_adapter *adapter);
+static int vt8231_detach_client(struct i2c_client *client);
+static struct vt8231_data *vt8231_update_device(struct device *dev);
+static void vt8231_init_client(struct i2c_client *client);
+
+static inline int vt8231_read_value(struct i2c_client *client, u8 reg)
+{
+ return inb_p(client->addr + reg);
+}
+
+static inline void vt8231_write_value(struct i2c_client *client, u8 reg,
+ u8 value)
+{
+ outb_p(value, client->addr + reg);
+}
+
+/* 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 vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", ((data->in[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_min(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 vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", ((data->in_min[nr] - 3) * 10000) / 958);
+}
+
+static ssize_t show_in_max(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 vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n", (((data->in_max[nr] - 3) * 10000) / 958));
+}
+
+static ssize_t set_in_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;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+ vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_in_max(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 vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
+ vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+/* Special case for input 5 as this has 3.3V scaling built into the chip */
+static ssize_t show_in5(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in_min[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+
+ return sprintf(buf, "%d\n",
+ (((data->in_max[5] - 3) * 10000 * 54) / (958 * 34)));
+}
+
+static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+ 0, 255);
+ vt8231_write_value(client, regvoltmin[5], data->in_min[5]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
+ 0, 255);
+ vt8231_write_value(client, regvoltmax[5], data->in_max[5]);
+ up(&data->update_lock);
+ return count;
+}
+
+#define define_voltage_sysfs(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, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset)
+
+define_voltage_sysfs(0);
+define_voltage_sysfs(1);
+define_voltage_sysfs(2);
+define_voltage_sysfs(3);
+define_voltage_sysfs(4);
+
+static DEVICE_ATTR(in5_input, S_IRUGO, show_in5, NULL);
+static DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, show_in5_min, set_in5_min);
+static DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, show_in5_max, set_in5_max);
+
+/* Temperatures */
+static ssize_t show_temp0(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp[0] * 250);
+}
+
+static ssize_t show_temp0_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_max[0] * 1000);
+}
+
+static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->temp_min[0] * 1000);
+}
+
+static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+ vt8231_write_value(client, regtempmax[0], data->temp_max[0]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
+ vt8231_write_value(client, regtempmin[0], data->temp_min[0]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_temp(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 vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(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 vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_max[nr]));
+}
+
+static ssize_t show_temp_min(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 vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_min[nr]));
+}
+
+static ssize_t set_temp_max(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 vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+ vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]);
+ up(&data->update_lock);
+ return count;
+}
+static ssize_t set_temp_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;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
+ vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+/* Note that these map the Linux temperature sensor numbering (1-6) to the VIA
+** temperature sensor numbering (0-5)
+*/
+#define define_temperature_sysfs(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+ show_temp_min, set_temp_min, offset - 1)
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
+static DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+
+define_temperature_sysfs(2);
+define_temperature_sysfs(3);
+define_temperature_sysfs(4);
+define_temperature_sysfs(5);
+define_temperature_sysfs(6);
+
+#define CFG_INFO_TEMP(id) { &sensor_dev_attr_temp##id##_input.dev_attr, \
+ &sensor_dev_attr_temp##id##_min.dev_attr, \
+ &sensor_dev_attr_temp##id##_max.dev_attr }
+#define CFG_INFO_VOLT(id) { &sensor_dev_attr_in##id##_input.dev_attr, \
+ &sensor_dev_attr_in##id##_min.dev_attr, \
+ &sensor_dev_attr_in##id##_max.dev_attr }
+
+struct str_device_attr_table {
+ struct device_attribute *input;
+ struct device_attribute *min;
+ struct device_attribute *max;
+};
+
+static struct str_device_attr_table cfg_info_temp[] = {
+ { &dev_attr_temp1_input, &dev_attr_temp1_min, &dev_attr_temp1_max },
+ CFG_INFO_TEMP(2),
+ CFG_INFO_TEMP(3),
+ CFG_INFO_TEMP(4),
+ CFG_INFO_TEMP(5),
+ CFG_INFO_TEMP(6)
+};
+
+static struct str_device_attr_table cfg_info_volt[] = {
+ CFG_INFO_VOLT(0),
+ CFG_INFO_VOLT(1),
+ CFG_INFO_VOLT(2),
+ CFG_INFO_VOLT(3),
+ CFG_INFO_VOLT(4),
+ { &dev_attr_in5_input, &dev_attr_in5_min, &dev_attr_in5_max }
+};
+
+/* Fans */
+static ssize_t show_fan(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 vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+ DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr])));
+}
+
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+static ssize_t set_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;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+ vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int nr = sensor_attr->index;
+ int old = vt8231_read_value(client, VT8231_REG_FANDIV);
+ long min = FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr]));
+
+ down(&data->update_lock);
+ switch (val) {
+ case 1: data->fan_div[nr] = 0; break;
+ case 2: data->fan_div[nr] = 1; break;
+ case 4: data->fan_div[nr] = 2; break;
+ case 8: data->fan_div[nr] = 3; break;
+ default:
+ dev_err(&client->dev, "fan_div value %ld not supported."
+ "Choose one of 1, 2, 4 or 8!\n", val);
+ up(&data->update_lock);
+ return -EINVAL;
+ }
+
+ /* Correct the fan minimum speed */
+ data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+ vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+
+ old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
+ vt8231_write_value(client, VT8231_REG_FANDIV, old);
+ up(&data->update_lock);
+ return count;
+}
+
+
+#define define_fan_sysfs(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, set_fan_div, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1)
+
+define_fan_sysfs(1);
+define_fan_sysfs(2);
+
+/* Alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct vt8231_data *data = vt8231_update_device(dev);
+ return sprintf(buf, "%d\n", data->alarms);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct i2c_driver vt8231_driver = {
+ .driver = {
+ .name = "vt8231",
+ },
+ .attach_adapter = vt8231_detect,
+ .detach_client = vt8231_detach_client,
+};
+
+static struct pci_device_id vt8231_pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id);
+
+static struct pci_driver vt8231_pci_driver = {
+ .name = "vt8231",
+ .id_table = vt8231_pci_ids,
+ .probe = vt8231_pci_probe,
+};
+
+int vt8231_detect(struct i2c_adapter *adapter)
+{
+ struct i2c_client *client;
+ struct vt8231_data *data;
+ int err = 0, i;
+ u16 val;
+
+ /* 8231 requires multiple of 256 */
+ if (force_addr) {
+ isa_address = force_addr & 0xFF00;
+ dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+ isa_address);
+ if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge,
+ VT8231_BASE_REG, isa_address))
+ return -ENODEV;
+ }
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(s_bridge, VT8231_ENABLE_REG, &val))
+ return -ENODEV;
+
+ if (!(val & 0x0001)) {
+ dev_warn(&adapter->dev, "enabling sensors\n");
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_write_config_word(s_bridge, VT8231_ENABLE_REG,
+ val | 0x0001))
+ return -ENODEV;
+ }
+
+ /* Reserve the ISA region */
+ if (!request_region(isa_address, VT8231_EXTENT,
+ vt8231_pci_driver.name)) {
+ dev_err(&adapter->dev, "region 0x%x already in use!\n",
+ isa_address);
+ return -ENODEV;
+ }
+
+ if (!(data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+
+ client = &data->client;
+ i2c_set_clientdata(client, data);
+ client->addr = isa_address;
+ client->adapter = adapter;
+ client->driver = &vt8231_driver;
+ client->dev.parent = &adapter->dev;
+
+ /* Fill in the remaining client fields and put into the global list */
+ strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
+
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto exit_free;
+
+ vt8231_init_client(client);
+
+ /* 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;
+ }
+
+ /* Must update device information to find out the config field */
+ data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
+
+ for (i = 0; i < ARRAY_SIZE(cfg_info_temp); i++) {
+ if (ISTEMP(i, data->uch_config)) {
+ device_create_file(&client->dev,
+ cfg_info_temp[i].input);
+ device_create_file(&client->dev, cfg_info_temp[i].max);
+ device_create_file(&client->dev, cfg_info_temp[i].min);
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cfg_info_volt); i++) {
+ if (ISVOLT(i, data->uch_config)) {
+ device_create_file(&client->dev,
+ cfg_info_volt[i].input);
+ device_create_file(&client->dev, cfg_info_volt[i].max);
+ device_create_file(&client->dev, cfg_info_volt[i].min);
+ }
+ }
+
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+
+ device_create_file(&client->dev, &dev_attr_alarms);
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+exit_free:
+ kfree(data);
+exit_release:
+ release_region(isa_address, VT8231_EXTENT);
+ return err;
+}
+
+static int vt8231_detach_client(struct i2c_client *client)
+{
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int err;
+
+ hwmon_device_unregister(data->class_dev);
+
+ if ((err = i2c_detach_client(client))) {
+ return err;
+ }
+
+ release_region(client->addr, VT8231_EXTENT);
+ kfree(data);
+
+ return 0;
+}
+
+static void vt8231_init_client(struct i2c_client *client)
+{
+ vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0);
+ vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0);
+}
+
+static struct vt8231_data *vt8231_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct vt8231_data *data = i2c_get_clientdata(client);
+ int i;
+ u16 low;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ for (i = 0; i < 6; i++) {
+ if (ISVOLT(i, data->uch_config)) {
+ data->in[i] = vt8231_read_value(client,
+ regvolt[i]);
+ data->in_min[i] = vt8231_read_value(client,
+ regvoltmin[i]);
+ data->in_max[i] = vt8231_read_value(client,
+ regvoltmax[i]);
+ }
+ }
+ for (i = 0; i < 2; i++) {
+ data->fan[i] = vt8231_read_value(client,
+ VT8231_REG_FAN(i));
+ data->fan_min[i] = vt8231_read_value(client,
+ VT8231_REG_FAN_MIN(i));
+ }
+
+ low = vt8231_read_value(client, VT8231_REG_TEMP_LOW01);
+ low = (low >> 6) | ((low & 0x30) >> 2)
+ | (vt8231_read_value(client, VT8231_REG_TEMP_LOW25) << 4);
+ for (i = 0; i < 6; i++) {
+ if (ISTEMP(i, data->uch_config)) {
+ data->temp[i] = (vt8231_read_value(client,
+ regtemp[i]) << 2)
+ | ((low >> (2 * i)) & 0x03);
+ data->temp_max[i] = vt8231_read_value(client,
+ regtempmax[i]);
+ data->temp_min[i] = vt8231_read_value(client,
+ regtempmin[i]);
+ }
+ }
+
+ i = vt8231_read_value(client, VT8231_REG_FANDIV);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = i >> 6;
+ data->alarms = vt8231_read_value(client, VT8231_REG_ALARM1) |
+ (vt8231_read_value(client, VT8231_REG_ALARM2) << 8);
+
+ /* Set alarm flags correctly */
+ if (!data->fan[0] && data->fan_min[0]) {
+ data->alarms |= 0x40;
+ } else if (data->fan[0] && !data->fan_min[0]) {
+ data->alarms &= ~0x40;
+ }
+
+ if (!data->fan[1] && data->fan_min[1]) {
+ data->alarms |= 0x80;
+ } else if (data->fan[1] && !data->fan_min[1]) {
+ data->alarms &= ~0x80;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+static int __devinit vt8231_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ u16 val;
+
+ if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
+ &val))
+ return -ENODEV;
+
+ isa_address = val & ~(VT8231_EXTENT - 1);
+ if (isa_address == 0 && force_addr == 0) {
+ dev_err(&dev->dev, "base address not set -\
+ upgrade BIOS or use force_addr=0xaddr\n");
+ return -ENODEV;
+ }
+
+ s_bridge = pci_dev_get(dev);
+
+ if (i2c_isa_add_driver(&vt8231_driver)) {
+ pci_dev_put(s_bridge);
+ s_bridge = NULL;
+ }
+
+ /* Always return failure here. This is to allow other drivers to bind
+ * to this pci device. We don't really want to have control over the
+ * pci device, we only wanted to read as few register values from it.
+ */
+ return -ENODEV;
+}
+
+static int __init sm_vt8231_init(void)
+{
+ return pci_register_driver(&vt8231_pci_driver);
+}
+
+static void __exit sm_vt8231_exit(void)
+{
+ pci_unregister_driver(&vt8231_pci_driver);
+ if (s_bridge != NULL) {
+ i2c_isa_del_driver(&vt8231_driver);
+ pci_dev_put(s_bridge);
+ s_bridge = NULL;
+ }
+}
+
+MODULE_AUTHOR("Roger Lucas <roger@planbit.co.uk>");
+MODULE_DESCRIPTION("VT8231 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(sm_vt8231_init);
+module_exit(sm_vt8231_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index eee22a57e929..12d79f5e4900 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -676,7 +676,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
int i, err = 0;
if (!request_region(address + REGION_OFFSET, REGION_LENGTH,
- w83627ehf_driver.name)) {
+ w83627ehf_driver.driver.name)) {
err = -EBUSY;
goto exit;
}
@@ -785,8 +785,9 @@ static int w83627ehf_detach_client(struct i2c_client *client)
}
static struct i2c_driver w83627ehf_driver = {
- .owner = THIS_MODULE,
- .name = "w83627ehf",
+ .driver = {
+ .name = "w83627ehf",
+ },
.attach_adapter = w83627ehf_detect,
.detach_client = w83627ehf_detach_client,
};
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index bbb3dcde146b..7ea441d4da63 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -332,8 +332,9 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev);
static void w83627hf_init_client(struct i2c_client *client);
static struct i2c_driver w83627hf_driver = {
- .owner = THIS_MODULE,
- .name = "w83627hf",
+ .driver = {
+ .name = "w83627hf",
+ },
.attach_adapter = w83627hf_detect,
.detach_client = w83627hf_detach_client,
};
@@ -1009,7 +1010,7 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
address = force_addr & WINB_ALIGNMENT;
if (!request_region(address + WINB_REGION_OFFSET, WINB_REGION_SIZE,
- w83627hf_driver.name)) {
+ w83627hf_driver.driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -1122,11 +1123,10 @@ static int w83627hf_detect(struct i2c_adapter *adapter)
if (kind != w83697hf)
device_create_file_temp(new_client, 3);
- if (kind != w83697hf)
+ if (kind != w83697hf && data->vid != 0xff) {
device_create_file_vid(new_client);
-
- if (kind != w83697hf)
device_create_file_vrm(new_client);
+ }
device_create_file_fan_div(new_client, 1);
device_create_file_fan_div(new_client, 2);
@@ -1232,7 +1232,7 @@ static int w83627thf_read_gpio5(struct i2c_client *client)
/* Make sure the pins are configured for input
There must be at least five (VRM 9), and possibly 6 (VRM 10) */
- sel = superio_inb(W83627THF_GPIO5_IOSR);
+ sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
if ((sel & 0x1f) != 0x1f) {
dev_dbg(&client->dev, "GPIO5 not configured for VID "
"function\n");
@@ -1323,19 +1323,18 @@ static void w83627hf_init_client(struct i2c_client *client)
int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) {
- data->vid = w83627thf_read_gpio5(client) & 0x3f;
+ data->vid = w83627thf_read_gpio5(client);
}
/* Read VRM & OVT Config only once */
if (w83627thf == data->type || w83637hf == data->type) {
data->vrm_ovt =
w83627hf_read_value(client, W83627THF_REG_VRM_OVT_CFG);
- data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
- } else {
- /* Convert VID to voltage based on default VRM */
- data->vrm = vid_which_vrm();
}
+ /* Convert VID to voltage based on VRM */
+ data->vrm = vid_which_vrm();
+
tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
for (i = 1; i <= 3; i++) {
if (!(tmp & BIT_SCFG1[i - 1])) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index ffdb3a03e2b5..557114872f3c 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -269,17 +269,18 @@ static struct w83781d_data *w83781d_update_device(struct device *dev);
static void w83781d_init_client(struct i2c_client *client);
static struct i2c_driver w83781d_driver = {
- .owner = THIS_MODULE,
- .name = "w83781d",
+ .driver = {
+ .name = "w83781d",
+ },
.id = I2C_DRIVERID_W83781D,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = w83781d_attach_adapter,
.detach_client = w83781d_detach_client,
};
static struct i2c_driver w83781d_isa_driver = {
- .owner = THIS_MODULE,
- .name = "w83781d-isa",
+ .driver = {
+ .name = "w83781d-isa",
+ },
.attach_adapter = w83781d_isa_attach_adapter,
.detach_client = w83781d_detach_client,
};
@@ -1012,7 +1013,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa)
if (!request_region(address, W83781D_EXTENT,
- w83781d_isa_driver.name)) {
+ w83781d_isa_driver.driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 1ba072630361..b176bf0c4c7b 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -269,7 +269,6 @@ DIV_TO_REG(long val)
struct w83792d_data {
struct i2c_client client;
struct class_device *class_dev;
- struct semaphore lock;
enum chips type;
struct semaphore update_lock;
@@ -282,7 +281,7 @@ struct w83792d_data {
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 */
+ u16 low_bits; /* Additional resolution to voltage in6-0 */
u8 fan[7]; /* Register value */
u8 fan_min[7]; /* Register value */
u8 temp1[3]; /* current, over, thyst */
@@ -317,45 +316,17 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
static void w83792d_init_client(struct i2c_client *client);
static struct i2c_driver w83792d_driver = {
- .owner = THIS_MODULE,
- .name = "w83792d",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "w83792d",
+ },
.attach_adapter = w83792d_attach_adapter,
.detach_client = w83792d_detach_client,
};
-static long in_count_from_reg(int nr, struct w83792d_data *data)
+static inline 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;
+ /* in7 and in8 do not have low bits, but the formula still works */
+ return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
}
/* following are the sysfs callback functions */
@@ -1192,7 +1163,6 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
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;
@@ -1243,7 +1213,7 @@ w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR1;
}
val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
- if (val1 == 0x7a && address >= 0x2c) {
+ if (val1 == 0x7a) {
kind = w83792d;
} else {
if (kind == 0)
@@ -1416,26 +1386,17 @@ w83792d_detach_client(struct i2c_client *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)
+/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+ but the driver only accesses registers in bank 0, so we don't have
+ to switch banks and lock access between switches. */
+static int w83792d_read_value(struct i2c_client *client, u8 reg)
{
- int res=0;
- res = i2c_smbus_read_byte_data(client, reg);
-
- return res;
+ return i2c_smbus_read_byte_data(client, reg);
}
-static int
-w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
{
- i2c_smbus_write_byte_data(client, reg, value);
- return 0;
+ return i2c_smbus_write_byte_data(client, reg, value);
}
static void
@@ -1492,10 +1453,10 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
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);
+ data->low_bits = w83792d_read_value(client,
+ W83792D_REG_LOW_BITS1) +
+ (w83792d_read_value(client,
+ W83792D_REG_LOW_BITS2) << 8);
for (i = 0; i < 7; i++) {
/* Update the Fan measured value and limits */
data->fan[i] = w83792d_read_value(client,
@@ -1506,7 +1467,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
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;
+ data->pwm_mode[i] = pwm_array_tmp[i] >> 7;
}
reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
@@ -1607,8 +1568,8 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
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, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
+ dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
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]);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index f495b6378668..f66c0cfdeda7 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -92,10 +92,10 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
*/
static struct i2c_driver w83l785ts_driver = {
- .owner = THIS_MODULE,
- .name = "w83l785ts",
+ .driver = {
+ .name = "w83l785ts",
+ },
.id = I2C_DRIVERID_W83L785TS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = w83l785ts_attach_adapter,
.detach_client = w83l785ts_detach_client,
};
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4010fe92e72b..08d5b8fed2dc 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -236,27 +236,17 @@ config I2C_IXP2000
This support is also available as a module. If so, the module
will be called i2c-ixp2000.
-config I2C_KEYWEST
- tristate "Powermac Keywest I2C interface"
+config I2C_POWERMAC
+ tristate "Powermac I2C interface"
depends on I2C && PPC_PMAC
+ default y
help
- This supports the use of the I2C interface in the combo-I/O
- chip on recent Apple machines. Say Y if you have such a machine.
-
- This support is also available as a module. If so, the module
- will be called i2c-keywest.
-
-config I2C_PMAC_SMU
- tristate "Powermac SMU I2C interface"
- depends on I2C && PMAC_SMU
- help
- This supports the use of the I2C interface in the SMU
- chip on recent Apple machines like the iMac G5. It is used
- among others by the thermal control driver for those machines.
- Say Y if you have such a machine.
+ This exposes the various PowerMac i2c interfaces to the linux i2c
+ layer and to userland. It is used by various drivers on the powemac
+ platform, thus should generally be enabled.
This support is also available as a module. If so, the module
- will be called i2c-pmac-smu.
+ will be called i2c-powermac.
config I2C_MPC
tristate "MPC107/824x/85xx/52xx"
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index f1df00f66c6c..b44831dff683 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -19,8 +19,7 @@ obj-$(CONFIG_I2C_ISA) += i2c-isa.o
obj-$(CONFIG_I2C_ITE) += i2c-ite.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_IXP4XX) += i2c-ixp4xx.o
-obj-$(CONFIG_I2C_KEYWEST) += i2c-keywest.o
-obj-$(CONFIG_I2C_PMAC_SMU) += i2c-pmac-smu.o
+obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index ac3eafa8aac0..1c752ddc10e2 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -468,8 +468,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1;
}
- if (hwpec)
- outb_p(1, SMBAUXCTL); /* enable hardware PEC */
+ outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
if(block)
ret = i801_block_transaction(data, read_write, size, hwpec);
@@ -478,9 +477,6 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
ret = i801_transaction();
}
- if (hwpec)
- outb_p(0, SMBAUXCTL); /* disable hardware PEC */
-
if(block)
return ret;
if(ret)
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 1a587253d716..87fae937e666 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -725,6 +725,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
strcpy(adap->name, "IBM IIC");
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
+ adap->class = I2C_CLASS_HWMON;
adap->algo = &iic_algo;
adap->client_register = NULL;
adap->client_unregister = NULL;
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 03672c9ca409..9f2ffef4d812 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -92,15 +92,13 @@ 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.owner = driver->owner;
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);
+ dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
/* Now look for clients */
driver->attach_adapter(&isa_adapter);
@@ -124,14 +122,14 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
if ((res = driver->detach_client(client))) {
dev_err(&isa_adapter.dev, "Failed, driver "
"%s not unregistered!\n",
- driver->name);
+ driver->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);
+ dev_dbg(&isa_adapter.dev, "Driver %s unregistered\n", driver->driver.name);
return 0;
}
@@ -176,7 +174,7 @@ static void __exit i2c_isa_exit(void)
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,
+ "ISA client at 0x%x\n", client->driver->driver.name,
client->addr);
}
if (client != NULL)
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
deleted file mode 100644
index d61f748278fc..000000000000
--- a/drivers/i2c/busses/i2c-keywest.c
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- i2c Support for Apple Keywest I2C Bus Controller
-
- Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
-
- Original work by
-
- Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.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.
-
- Changes:
-
- 2001/12/13 BenH New implementation
- 2001/12/15 BenH Add support for "byte" and "quick"
- transfers. Add i2c_xfer routine.
- 2003/09/21 BenH Rework state machine with Paulus help
- 2004/01/21 BenH Merge in Greg KH changes, polled mode is back
- 2004/02/05 BenH Merge 64 bits fixes from the g5 ppc64 tree
-
- My understanding of the various modes supported by keywest are:
-
- - Dumb mode : not implemented, probably direct tweaking of lines
- - Standard mode : simple i2c transaction of type
- S Addr R/W A Data A Data ... T
- - Standard sub mode : combined 8 bit subaddr write with data read
- S Addr R/W A SubAddr A Data A Data ... T
- - Combined mode : Subaddress and Data sequences appended with no stop
- S Addr R/W A SubAddr S Addr R/W A Data A Data ... T
-
- Currently, this driver uses only Standard mode for i2c xfer, and
- smbus byte & quick transfers ; and uses StandardSub mode for
- other smbus transfers instead of combined as we need that for the
- sound driver to be happy
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/pmac_low_i2c.h>
-
-#include "i2c-keywest.h"
-
-#undef POLLED_MODE
-
-/* Some debug macros */
-#define WRONG_STATE(name) do {\
- pr_debug("KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
- name, __kw_state_names[iface->state], isr); \
- } while(0)
-
-#ifdef DEBUG
-static const char *__kw_state_names[] = {
- "state_idle",
- "state_addr",
- "state_read",
- "state_write",
- "state_stop",
- "state_dead"
-};
-#endif /* DEBUG */
-
-MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
-MODULE_LICENSE("GPL");
-
-#ifdef POLLED_MODE
-/* Don't schedule, the g5 fan controller is too
- * timing sensitive
- */
-static u8
-wait_interrupt(struct keywest_iface* iface)
-{
- int i;
- u8 isr;
-
- for (i = 0; i < 200000; i++) {
- isr = read_reg(reg_isr) & KW_I2C_IRQ_MASK;
- if (isr != 0)
- return isr;
- udelay(10);
- }
- return isr;
-}
-#endif /* POLLED_MODE */
-
-static void
-do_stop(struct keywest_iface* iface, int result)
-{
- write_reg(reg_control, KW_I2C_CTL_STOP);
- iface->state = state_stop;
- iface->result = result;
-}
-
-/* Main state machine for standard & standard sub mode */
-static void
-handle_interrupt(struct keywest_iface *iface, u8 isr)
-{
- int ack;
-
- if (isr == 0) {
- if (iface->state != state_stop) {
- pr_debug("KW: Timeout !\n");
- do_stop(iface, -EIO);
- }
- if (iface->state == state_stop) {
- ack = read_reg(reg_status);
- if (!(ack & KW_I2C_STAT_BUSY)) {
- iface->state = state_idle;
- write_reg(reg_ier, 0x00);
-#ifndef POLLED_MODE
- complete(&iface->complete);
-#endif /* POLLED_MODE */
- }
- }
- return;
- }
-
- if (isr & KW_I2C_IRQ_ADDR) {
- ack = read_reg(reg_status);
- if (iface->state != state_addr) {
- write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- WRONG_STATE("KW_I2C_IRQ_ADDR");
- do_stop(iface, -EIO);
- return;
- }
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- iface->state = state_stop;
- iface->result = -ENODEV;
- pr_debug("KW: NAK on address\n");
- } else {
- /* Handle rw "quick" mode */
- if (iface->datalen == 0) {
- do_stop(iface, 0);
- } else if (iface->read_write == I2C_SMBUS_READ) {
- iface->state = state_read;
- if (iface->datalen > 1)
- write_reg(reg_control, KW_I2C_CTL_AAK);
- } else {
- iface->state = state_write;
- write_reg(reg_data, *(iface->data++));
- iface->datalen--;
- }
- }
- write_reg(reg_isr, KW_I2C_IRQ_ADDR);
- }
-
- if (isr & KW_I2C_IRQ_DATA) {
- if (iface->state == state_read) {
- *(iface->data++) = read_reg(reg_data);
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- iface->datalen--;
- if (iface->datalen == 0)
- iface->state = state_stop;
- else if (iface->datalen == 1)
- write_reg(reg_control, 0);
- } else if (iface->state == state_write) {
- /* Check ack status */
- ack = read_reg(reg_status);
- if ((ack & KW_I2C_STAT_LAST_AAK) == 0) {
- pr_debug("KW: nack on data write (%x): %x\n",
- iface->data[-1], ack);
- do_stop(iface, -EIO);
- } else if (iface->datalen) {
- write_reg(reg_data, *(iface->data++));
- iface->datalen--;
- } else {
- write_reg(reg_control, KW_I2C_CTL_STOP);
- iface->state = state_stop;
- iface->result = 0;
- }
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- } else {
- write_reg(reg_isr, KW_I2C_IRQ_DATA);
- WRONG_STATE("KW_I2C_IRQ_DATA");
- if (iface->state != state_stop)
- do_stop(iface, -EIO);
- }
- }
-
- if (isr & KW_I2C_IRQ_STOP) {
- write_reg(reg_isr, KW_I2C_IRQ_STOP);
- if (iface->state != state_stop) {
- WRONG_STATE("KW_I2C_IRQ_STOP");
- iface->result = -EIO;
- }
- iface->state = state_idle;
- write_reg(reg_ier, 0x00);
-#ifndef POLLED_MODE
- complete(&iface->complete);
-#endif /* POLLED_MODE */
- }
-
- if (isr & KW_I2C_IRQ_START)
- write_reg(reg_isr, KW_I2C_IRQ_START);
-}
-
-#ifndef POLLED_MODE
-
-/* Interrupt handler */
-static irqreturn_t
-keywest_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct keywest_iface *iface = (struct keywest_iface *)dev_id;
- unsigned long flags;
-
- spin_lock_irqsave(&iface->lock, flags);
- del_timer(&iface->timeout_timer);
- handle_interrupt(iface, read_reg(reg_isr));
- if (iface->state != state_idle) {
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- }
- spin_unlock_irqrestore(&iface->lock, flags);
- return IRQ_HANDLED;
-}
-
-static void
-keywest_timeout(unsigned long data)
-{
- struct keywest_iface *iface = (struct keywest_iface *)data;
- unsigned long flags;
-
- pr_debug("timeout !\n");
- spin_lock_irqsave(&iface->lock, flags);
- handle_interrupt(iface, read_reg(reg_isr));
- if (iface->state != state_idle) {
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
- }
- spin_unlock_irqrestore(&iface->lock, flags);
-}
-
-#endif /* POLLED_MODE */
-
-/*
- * SMBUS-type transfer entrypoint
- */
-static s32
-keywest_smbus_xfer( struct i2c_adapter* adap,
- u16 addr,
- unsigned short flags,
- char read_write,
- u8 command,
- int size,
- union i2c_smbus_data* data)
-{
- struct keywest_chan* chan = i2c_get_adapdata(adap);
- struct keywest_iface* iface = chan->iface;
- int len;
- u8* buffer;
- u16 cur_word;
- int rc = 0;
-
- if (iface->state == state_dead)
- return -ENXIO;
-
- /* Prepare datas & select mode */
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- switch (size) {
- case I2C_SMBUS_QUICK:
- len = 0;
- buffer = NULL;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
- break;
- case I2C_SMBUS_BYTE:
- len = 1;
- buffer = &data->byte;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
- break;
- case I2C_SMBUS_BYTE_DATA:
- len = 1;
- buffer = &data->byte;
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- case I2C_SMBUS_WORD_DATA:
- len = 2;
- cur_word = cpu_to_le16(data->word);
- buffer = (u8 *)&cur_word;
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- case I2C_SMBUS_BLOCK_DATA:
- len = data->block[0];
- buffer = &data->block[1];
- iface->cur_mode |= KW_I2C_MODE_STANDARDSUB;
- break;
- default:
- return -1;
- }
-
- /* Turn a standardsub read into a combined mode access */
- if (read_write == I2C_SMBUS_READ
- && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) {
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- iface->cur_mode |= KW_I2C_MODE_COMBINED;
- }
-
- /* Original driver had this limitation */
- if (len > 32)
- len = 32;
-
- if (pmac_low_i2c_lock(iface->node))
- return -ENXIO;
-
- pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n",
- chan->chan_no, addr, len, read_write == I2C_SMBUS_READ);
-
- iface->data = buffer;
- iface->datalen = len;
- iface->state = state_addr;
- iface->result = 0;
- iface->read_write = read_write;
-
- /* Setup channel & clear pending irqs */
- write_reg(reg_isr, read_reg(reg_isr));
- write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
- write_reg(reg_status, 0);
-
- /* Set up address and r/w bit */
- write_reg(reg_addr,
- (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));
-
- /* Set up the sub address */
- if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
- || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
- write_reg(reg_subaddr, command);
-
-#ifndef POLLED_MODE
- /* Arm timeout */
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
-#endif
-
- /* Start sending address & enable interrupt*/
- write_reg(reg_control, KW_I2C_CTL_XADDR);
- write_reg(reg_ier, KW_I2C_IRQ_MASK);
-
-#ifdef POLLED_MODE
- pr_debug("using polled mode...\n");
- /* State machine, to turn into an interrupt handler */
- while(iface->state != state_idle) {
- unsigned long flags;
-
- u8 isr = wait_interrupt(iface);
- spin_lock_irqsave(&iface->lock, flags);
- handle_interrupt(iface, isr);
- spin_unlock_irqrestore(&iface->lock, flags);
- }
-#else /* POLLED_MODE */
- pr_debug("using interrupt mode...\n");
- wait_for_completion(&iface->complete);
-#endif /* POLLED_MODE */
-
- rc = iface->result;
- pr_debug("transfer done, result: %d\n", rc);
-
- if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ)
- data->word = le16_to_cpu(cur_word);
-
- /* Release sem */
- pmac_low_i2c_unlock(iface->node);
-
- return rc;
-}
-
-/*
- * Generic i2c master transfer entrypoint
- */
-static int
-keywest_xfer( struct i2c_adapter *adap,
- struct i2c_msg *msgs,
- int num)
-{
- struct keywest_chan* chan = i2c_get_adapdata(adap);
- struct keywest_iface* iface = chan->iface;
- struct i2c_msg *pmsg;
- int i, completed;
- int rc = 0;
-
- if (iface->state == state_dead)
- return -ENXIO;
-
- if (pmac_low_i2c_lock(iface->node))
- return -ENXIO;
-
- /* Set adapter to standard mode */
- iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK;
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
-
- completed = 0;
- for (i = 0; rc >= 0 && i < num;) {
- u8 addr;
-
- pmsg = &msgs[i++];
- addr = pmsg->addr;
- if (pmsg->flags & I2C_M_TEN) {
- printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n");
- rc = -EINVAL;
- break;
- }
- pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n",
- chan->chan_no,
- pmsg->flags & I2C_M_RD ? "read" : "write",
- pmsg->len, addr, i, num);
-
- /* Setup channel & clear pending irqs */
- write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4));
- write_reg(reg_isr, read_reg(reg_isr));
- write_reg(reg_status, 0);
-
- iface->data = pmsg->buf;
- iface->datalen = pmsg->len;
- iface->state = state_addr;
- iface->result = 0;
- if (pmsg->flags & I2C_M_RD)
- iface->read_write = I2C_SMBUS_READ;
- else
- iface->read_write = I2C_SMBUS_WRITE;
-
- /* Set up address and r/w bit */
- if (pmsg->flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
- write_reg(reg_addr,
- (addr << 1) |
- ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00));
-
-#ifndef POLLED_MODE
- /* Arm timeout */
- iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
- add_timer(&iface->timeout_timer);
-#endif
-
- /* Start sending address & enable interrupt*/
- write_reg(reg_ier, KW_I2C_IRQ_MASK);
- write_reg(reg_control, KW_I2C_CTL_XADDR);
-
-#ifdef POLLED_MODE
- pr_debug("using polled mode...\n");
- /* State machine, to turn into an interrupt handler */
- while(iface->state != state_idle) {
- u8 isr = wait_interrupt(iface);
- handle_interrupt(iface, isr);
- }
-#else /* POLLED_MODE */
- pr_debug("using interrupt mode...\n");
- wait_for_completion(&iface->complete);
-#endif /* POLLED_MODE */
-
- rc = iface->result;
- if (rc == 0)
- completed++;
- pr_debug("transfer done, result: %d\n", rc);
- }
-
- /* Release sem */
- pmac_low_i2c_unlock(iface->node);
-
- return completed;
-}
-
-static u32
-keywest_func(struct i2c_adapter * adapter)
-{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA;
-}
-
-/* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm keywest_algorithm = {
- .smbus_xfer = keywest_smbus_xfer,
- .master_xfer = keywest_xfer,
- .functionality = keywest_func,
-};
-
-
-static int
-create_iface(struct device_node *np, struct device *dev)
-{
- unsigned long steps;
- unsigned bsteps, tsize, i, nchan, addroffset;
- struct keywest_iface* iface;
- u32 *psteps, *prate;
- int rc;
-
- if (np->n_intrs < 1 || np->n_addrs < 1) {
- printk(KERN_ERR "%s: Missing interrupt or address !\n",
- np->full_name);
- return -ENODEV;
- }
- if (pmac_low_i2c_lock(np))
- return -ENODEV;
-
- psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
- steps = psteps ? (*psteps) : 0x10;
-
- /* Hrm... maybe we can be smarter here */
- for (bsteps = 0; (steps & 0x01) == 0; bsteps++)
- steps >>= 1;
-
- if (np->parent->name[0] == 'u') {
- nchan = 2;
- addroffset = 3;
- } else {
- addroffset = 0;
- nchan = 1;
- }
-
- tsize = sizeof(struct keywest_iface) +
- (sizeof(struct keywest_chan) + 4) * nchan;
- iface = kzalloc(tsize, GFP_KERNEL);
- if (iface == NULL) {
- printk(KERN_ERR "i2c-keywest: can't allocate inteface !\n");
- pmac_low_i2c_unlock(np);
- return -ENOMEM;
- }
- spin_lock_init(&iface->lock);
- init_completion(&iface->complete);
- iface->node = of_node_get(np);
- iface->bsteps = bsteps;
- iface->chan_count = nchan;
- iface->state = state_idle;
- iface->irq = np->intrs[0].line;
- iface->channels = (struct keywest_chan *)
- (((unsigned long)(iface + 1) + 3UL) & ~3UL);
- iface->base = ioremap(np->addrs[0].address + addroffset,
- np->addrs[0].size);
- if (!iface->base) {
- printk(KERN_ERR "i2c-keywest: can't map inteface !\n");
- kfree(iface);
- pmac_low_i2c_unlock(np);
- return -ENOMEM;
- }
-
-#ifndef POLLED_MODE
- init_timer(&iface->timeout_timer);
- iface->timeout_timer.function = keywest_timeout;
- iface->timeout_timer.data = (unsigned long)iface;
-#endif
-
- /* Select interface rate */
- iface->cur_mode = KW_I2C_MODE_100KHZ;
- prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
- if (prate) switch(*prate) {
- case 100:
- iface->cur_mode = KW_I2C_MODE_100KHZ;
- break;
- case 50:
- iface->cur_mode = KW_I2C_MODE_50KHZ;
- break;
- case 25:
- iface->cur_mode = KW_I2C_MODE_25KHZ;
- break;
- default:
- printk(KERN_WARNING "i2c-keywest: unknown rate %ldKhz, using 100KHz\n",
- (long)*prate);
- }
-
- /* Select standard mode by default */
- iface->cur_mode |= KW_I2C_MODE_STANDARD;
-
- /* Write mode */
- write_reg(reg_mode, iface->cur_mode);
-
- /* Switch interrupts off & clear them*/
- write_reg(reg_ier, 0x00);
- write_reg(reg_isr, KW_I2C_IRQ_MASK);
-
-#ifndef POLLED_MODE
- /* Request chip interrupt */
- rc = request_irq(iface->irq, keywest_irq, SA_INTERRUPT, "keywest i2c", iface);
- if (rc) {
- printk(KERN_ERR "i2c-keywest: can't get IRQ %d !\n", iface->irq);
- iounmap(iface->base);
- kfree(iface);
- pmac_low_i2c_unlock(np);
- return -ENODEV;
- }
-#endif /* POLLED_MODE */
-
- pmac_low_i2c_unlock(np);
- dev_set_drvdata(dev, iface);
-
- for (i=0; i<nchan; i++) {
- struct keywest_chan* chan = &iface->channels[i];
-
- sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
- chan->iface = iface;
- chan->chan_no = i;
- chan->adapter.algo = &keywest_algorithm;
- chan->adapter.algo_data = NULL;
- chan->adapter.client_register = NULL;
- chan->adapter.client_unregister = NULL;
- i2c_set_adapdata(&chan->adapter, chan);
- chan->adapter.dev.parent = dev;
-
- rc = i2c_add_adapter(&chan->adapter);
- if (rc) {
- printk("i2c-keywest.c: Adapter %s registration failed\n",
- chan->adapter.name);
- i2c_set_adapdata(&chan->adapter, NULL);
- }
- }
-
- printk(KERN_INFO "Found KeyWest i2c on \"%s\", %d channel%s, stepping: %d bits\n",
- np->parent->name, nchan, nchan > 1 ? "s" : "", bsteps);
-
- return 0;
-}
-
-static int
-dispose_iface(struct device *dev)
-{
- struct keywest_iface *iface = dev_get_drvdata(dev);
- int i, rc;
-
- /* Make sure we stop all activity */
- if (pmac_low_i2c_lock(iface->node))
- return -ENODEV;
-
-#ifndef POLLED_MODE
- spin_lock_irq(&iface->lock);
- while (iface->state != state_idle) {
- spin_unlock_irq(&iface->lock);
- msleep(100);
- spin_lock_irq(&iface->lock);
- }
-#endif /* POLLED_MODE */
- iface->state = state_dead;
-#ifndef POLLED_MODE
- spin_unlock_irq(&iface->lock);
- free_irq(iface->irq, iface);
-#endif /* POLLED_MODE */
-
- pmac_low_i2c_unlock(iface->node);
-
- /* Release all channels */
- for (i=0; i<iface->chan_count; i++) {
- struct keywest_chan* chan = &iface->channels[i];
- if (i2c_get_adapdata(&chan->adapter) == NULL)
- continue;
- rc = i2c_del_adapter(&chan->adapter);
- i2c_set_adapdata(&chan->adapter, NULL);
- /* We aren't that prepared to deal with this... */
- if (rc)
- printk("i2c-keywest.c: i2c_del_adapter failed, that's bad !\n");
- }
- iounmap(iface->base);
- dev_set_drvdata(dev, NULL);
- of_node_put(iface->node);
- kfree(iface);
-
- return 0;
-}
-
-static int
-create_iface_macio(struct macio_dev* dev, const struct of_device_id *match)
-{
- return create_iface(dev->ofdev.node, &dev->ofdev.dev);
-}
-
-static int
-dispose_iface_macio(struct macio_dev* dev)
-{
- return dispose_iface(&dev->ofdev.dev);
-}
-
-static int
-create_iface_of_platform(struct of_device* dev, const struct of_device_id *match)
-{
- return create_iface(dev->node, &dev->dev);
-}
-
-static int
-dispose_iface_of_platform(struct of_device* dev)
-{
- return dispose_iface(&dev->dev);
-}
-
-static struct of_device_id i2c_keywest_match[] =
-{
- {
- .type = "i2c",
- .compatible = "keywest"
- },
- {},
-};
-
-static struct macio_driver i2c_keywest_macio_driver =
-{
- .owner = THIS_MODULE,
- .name = "i2c-keywest",
- .match_table = i2c_keywest_match,
- .probe = create_iface_macio,
- .remove = dispose_iface_macio
-};
-
-static struct of_platform_driver i2c_keywest_of_platform_driver =
-{
- .owner = THIS_MODULE,
- .name = "i2c-keywest",
- .match_table = i2c_keywest_match,
- .probe = create_iface_of_platform,
- .remove = dispose_iface_of_platform
-};
-
-static int __init
-i2c_keywest_init(void)
-{
- of_register_driver(&i2c_keywest_of_platform_driver);
- macio_register_driver(&i2c_keywest_macio_driver);
-
- return 0;
-}
-
-static void __exit
-i2c_keywest_cleanup(void)
-{
- of_unregister_driver(&i2c_keywest_of_platform_driver);
- macio_unregister_driver(&i2c_keywest_macio_driver);
-}
-
-module_init(i2c_keywest_init);
-module_exit(i2c_keywest_cleanup);
diff --git a/drivers/i2c/busses/i2c-keywest.h b/drivers/i2c/busses/i2c-keywest.h
deleted file mode 100644
index c5022e1ca6ff..000000000000
--- a/drivers/i2c/busses/i2c-keywest.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef __I2C_KEYWEST_H__
-#define __I2C_KEYWEST_H__
-
-/* The Tumbler audio equalizer can be really slow sometimes */
-#define POLL_TIMEOUT (2*HZ)
-
-/* Register indices */
-typedef enum {
- reg_mode = 0,
- reg_control,
- reg_status,
- reg_isr,
- reg_ier,
- reg_addr,
- reg_subaddr,
- reg_data
-} reg_t;
-
-
-/* Mode register */
-#define KW_I2C_MODE_100KHZ 0x00
-#define KW_I2C_MODE_50KHZ 0x01
-#define KW_I2C_MODE_25KHZ 0x02
-#define KW_I2C_MODE_DUMB 0x00
-#define KW_I2C_MODE_STANDARD 0x04
-#define KW_I2C_MODE_STANDARDSUB 0x08
-#define KW_I2C_MODE_COMBINED 0x0C
-#define KW_I2C_MODE_MODE_MASK 0x0C
-#define KW_I2C_MODE_CHAN_MASK 0xF0
-
-/* Control register */
-#define KW_I2C_CTL_AAK 0x01
-#define KW_I2C_CTL_XADDR 0x02
-#define KW_I2C_CTL_STOP 0x04
-#define KW_I2C_CTL_START 0x08
-
-/* Status register */
-#define KW_I2C_STAT_BUSY 0x01
-#define KW_I2C_STAT_LAST_AAK 0x02
-#define KW_I2C_STAT_LAST_RW 0x04
-#define KW_I2C_STAT_SDA 0x08
-#define KW_I2C_STAT_SCL 0x10
-
-/* IER & ISR registers */
-#define KW_I2C_IRQ_DATA 0x01
-#define KW_I2C_IRQ_ADDR 0x02
-#define KW_I2C_IRQ_STOP 0x04
-#define KW_I2C_IRQ_START 0x08
-#define KW_I2C_IRQ_MASK 0x0F
-
-/* Physical interface */
-struct keywest_iface
-{
- struct device_node *node;
- void __iomem * base;
- unsigned bsteps;
- int irq;
- spinlock_t lock;
- struct keywest_chan *channels;
- unsigned chan_count;
- u8 cur_mode;
- char read_write;
- u8 *data;
- unsigned datalen;
- int state;
- int result;
- struct timer_list timeout_timer;
- struct completion complete;
-};
-
-enum {
- state_idle,
- state_addr,
- state_read,
- state_write,
- state_stop,
- state_dead
-};
-
-/* Channel on an interface */
-struct keywest_chan
-{
- struct i2c_adapter adapter;
- struct keywest_iface* iface;
- unsigned chan_no;
-};
-
-/* Register access */
-
-static inline u8 __read_reg(struct keywest_iface *iface, reg_t reg)
-{
- return in_8(iface->base
- + (((unsigned)reg) << iface->bsteps));
-}
-
-static inline void __write_reg(struct keywest_iface *iface, reg_t reg, u8 val)
-{
- out_8(iface->base
- + (((unsigned)reg) << iface->bsteps), val);
- (void)__read_reg(iface, reg_subaddr);
-}
-
-#define write_reg(reg, val) __write_reg(iface, reg, val)
-#define read_reg(reg) __read_reg(iface, reg)
-
-
-
-#endif /* __I2C_KEYWEST_H__ */
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 81031eb51056..22781d84f79f 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -1,6 +1,4 @@
/*
- * drivers/i2c/busses/i2c-mv64xxx.c
- *
* Driver for the i2c controller on the Marvell line of host bridges for MIPS
* and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
*
@@ -65,7 +63,6 @@ enum {
MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,
- MV64XXX_I2C_STATE_ABORTING,
};
/* Driver actions */
@@ -85,6 +82,7 @@ struct mv64xxx_i2c_data {
int irq;
u32 state;
u32 action;
+ u32 aborting;
u32 cntl_bits;
void __iomem *reg_base;
u32 reg_base_p;
@@ -122,12 +120,6 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
return;
}
- if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) {
- drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
- drv_data->state = MV64XXX_I2C_STATE_IDLE;
- return;
- }
-
/* The status from the ctlr [mostly] tells us what to do next */
switch (status) {
/* Start condition interrupt */
@@ -148,14 +140,16 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
/* FALLTHRU */
case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
- if (drv_data->bytes_left > 0) {
+ if ((drv_data->bytes_left == 0)
+ || (drv_data->aborting
+ && (drv_data->byte_posn != 0))) {
+ drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+ drv_data->state = MV64XXX_I2C_STATE_IDLE;
+ } else {
drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
drv_data->state =
MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;
drv_data->bytes_left--;
- } else {
- drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
- drv_data->state = MV64XXX_I2C_STATE_IDLE;
}
break;
@@ -184,7 +178,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
}
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
- if (drv_data->bytes_left == 1)
+ if ((drv_data->bytes_left == 1) || drv_data->aborting)
drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;
break;
@@ -320,6 +314,7 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
drv_data->msg = msg;
drv_data->byte_posn = 0;
drv_data->bytes_left = msg->len;
+ drv_data->aborting = 0;
drv_data->rc = 0;
drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
@@ -359,17 +354,19 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
}
if (abort && drv_data->block) {
- drv_data->state = MV64XXX_I2C_STATE_ABORTING;
+ drv_data->aborting = 1;
spin_unlock_irqrestore(&drv_data->lock, flags);
time_left = wait_event_timeout(drv_data->waitq,
!drv_data->block,
msecs_to_jiffies(drv_data->adapter.timeout));
- if (time_left <= 0) {
+ if ((time_left <= 0) && drv_data->block) {
drv_data->state = MV64XXX_I2C_STATE_IDLE;
dev_err(&drv_data->adapter.dev,
- "mv64xxx: I2C bus locked\n");
+ "mv64xxx: I2C bus locked, block: %d, "
+ "time_left: %d\n", drv_data->block,
+ (int)time_left);
}
} else
spin_unlock_irqrestore(&drv_data->lock, flags);
@@ -510,7 +507,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_kfree;
}
- strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+ strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
I2C_NAME_SIZE);
init_waitqueue_head(&drv_data->waitq);
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 4d18e6e5f159..2d80eb26f688 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -30,6 +30,7 @@
nForce3 Pro150 MCP 00D4
nForce3 250Gb MCP 00E4
nForce4 MCP 0052
+ nForce4 MCP-04 0034
This driver supports the 2 SMBuses that are included in the MCP of the
nForce2/3/4 chipsets.
@@ -257,6 +258,7 @@ static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
{ 0 }
};
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index f63a53779281..d702e5e0388d 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -80,6 +80,14 @@ static struct adapter_parm adapter_parm[] = {
.setscl = { 0x01, DATA, 1 },
.getsda = { 0x10, STAT, 1 },
},
+ /* type 6: Barco LPT->DVI (K5800236) adapter */
+ {
+ .setsda = { 0x02, DATA, 1 },
+ .setscl = { 0x01, DATA, 1 },
+ .getsda = { 0x20, STAT, 0 },
+ .getscl = { 0x40, STAT, 0 },
+ .init = { 0xfc, DATA, 0 },
+ },
};
static int type;
@@ -91,4 +99,6 @@ MODULE_PARM_DESC(type,
" 2 = Velleman K8000 adapter\n"
" 3 = ELV adapter\n"
" 4 = ADM1032 evaluation board\n"
- " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n");
+ " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
+ " 6 = Barco LPT->DVI (K5800236) adapter\n"
+);
diff --git a/drivers/i2c/busses/i2c-pmac-smu.c b/drivers/i2c/busses/i2c-pmac-smu.c
deleted file mode 100644
index bfefe7f7a53d..000000000000
--- a/drivers/i2c/busses/i2c-pmac-smu.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- i2c Support for Apple SMU Controller
-
- Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
- <benh@kernel.crashing.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/types.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/completion.h>
-#include <linux/device.h>
-#include <asm/prom.h>
-#include <asm/of_device.h>
-#include <asm/smu.h>
-
-static int probe;
-
-MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
-MODULE_DESCRIPTION("I2C driver for Apple's SMU");
-MODULE_LICENSE("GPL");
-module_param(probe, bool, 0);
-
-
-/* Physical interface */
-struct smu_iface
-{
- struct i2c_adapter adapter;
- struct completion complete;
- u32 busid;
-};
-
-static void smu_i2c_done(struct smu_i2c_cmd *cmd, void *misc)
-{
- struct smu_iface *iface = misc;
- complete(&iface->complete);
-}
-
-/*
- * SMBUS-type transfer entrypoint
- */
-static s32 smu_smbus_xfer( struct i2c_adapter* adap,
- u16 addr,
- unsigned short flags,
- char read_write,
- u8 command,
- int size,
- union i2c_smbus_data* data)
-{
- struct smu_iface *iface = i2c_get_adapdata(adap);
- struct smu_i2c_cmd cmd;
- int rc = 0;
- int read = (read_write == I2C_SMBUS_READ);
-
- cmd.info.bus = iface->busid;
- cmd.info.devaddr = (addr << 1) | (read ? 0x01 : 0x00);
-
- /* Prepare datas & select mode */
- switch (size) {
- case I2C_SMBUS_QUICK:
- cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
- cmd.info.datalen = 0;
- break;
- case I2C_SMBUS_BYTE:
- cmd.info.type = SMU_I2C_TRANSFER_SIMPLE;
- cmd.info.datalen = 1;
- if (!read)
- cmd.info.data[0] = data->byte;
- break;
- case I2C_SMBUS_BYTE_DATA:
- cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
- cmd.info.datalen = 1;
- cmd.info.sublen = 1;
- cmd.info.subaddr[0] = command;
- cmd.info.subaddr[1] = 0;
- cmd.info.subaddr[2] = 0;
- if (!read)
- cmd.info.data[0] = data->byte;
- break;
- case I2C_SMBUS_WORD_DATA:
- cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
- cmd.info.datalen = 2;
- cmd.info.sublen = 1;
- cmd.info.subaddr[0] = command;
- cmd.info.subaddr[1] = 0;
- cmd.info.subaddr[2] = 0;
- if (!read) {
- cmd.info.data[0] = data->byte & 0xff;
- cmd.info.data[1] = (data->byte >> 8) & 0xff;
- }
- break;
- /* Note that these are broken vs. the expected smbus API where
- * on reads, the lenght is actually returned from the function,
- * but I think the current API makes no sense and I don't want
- * any driver that I haven't verified for correctness to go
- * anywhere near a pmac i2c bus anyway ...
- */
- case I2C_SMBUS_BLOCK_DATA:
- cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
- cmd.info.datalen = data->block[0] + 1;
- if (cmd.info.datalen > 6)
- return -EINVAL;
- if (!read)
- memcpy(cmd.info.data, data->block, cmd.info.datalen);
- cmd.info.sublen = 1;
- cmd.info.subaddr[0] = command;
- cmd.info.subaddr[1] = 0;
- cmd.info.subaddr[2] = 0;
- break;
- case I2C_SMBUS_I2C_BLOCK_DATA:
- cmd.info.type = SMU_I2C_TRANSFER_STDSUB;
- cmd.info.datalen = data->block[0];
- if (cmd.info.datalen > 7)
- return -EINVAL;
- if (!read)
- memcpy(cmd.info.data, &data->block[1],
- cmd.info.datalen);
- cmd.info.sublen = 1;
- cmd.info.subaddr[0] = command;
- cmd.info.subaddr[1] = 0;
- cmd.info.subaddr[2] = 0;
- break;
-
- default:
- return -EINVAL;
- }
-
- /* Turn a standardsub read into a combined mode access */
- if (read_write == I2C_SMBUS_READ &&
- cmd.info.type == SMU_I2C_TRANSFER_STDSUB)
- cmd.info.type = SMU_I2C_TRANSFER_COMBINED;
-
- /* Finish filling command and submit it */
- cmd.done = smu_i2c_done;
- cmd.misc = iface;
- rc = smu_queue_i2c(&cmd);
- if (rc < 0)
- return rc;
- wait_for_completion(&iface->complete);
- rc = cmd.status;
-
- if (!read || rc < 0)
- return rc;
-
- switch (size) {
- case I2C_SMBUS_BYTE:
- case I2C_SMBUS_BYTE_DATA:
- data->byte = cmd.info.data[0];
- break;
- case I2C_SMBUS_WORD_DATA:
- data->word = ((u16)cmd.info.data[1]) << 8;
- data->word |= cmd.info.data[0];
- break;
- /* Note that these are broken vs. the expected smbus API where
- * on reads, the lenght is actually returned from the function,
- * but I think the current API makes no sense and I don't want
- * any driver that I haven't verified for correctness to go
- * anywhere near a pmac i2c bus anyway ...
- */
- case I2C_SMBUS_BLOCK_DATA:
- case I2C_SMBUS_I2C_BLOCK_DATA:
- memcpy(&data->block[0], cmd.info.data, cmd.info.datalen);
- break;
- }
-
- return rc;
-}
-
-static u32
-smu_smbus_func(struct i2c_adapter * adapter)
-{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA;
-}
-
-/* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm smu_algorithm = {
- .smbus_xfer = smu_smbus_xfer,
- .functionality = smu_smbus_func,
-};
-
-static int create_iface(struct device_node *np, struct device *dev)
-{
- struct smu_iface* iface;
- u32 *reg, busid;
- int rc;
-
- reg = (u32 *)get_property(np, "reg", NULL);
- if (reg == NULL) {
- printk(KERN_ERR "i2c-pmac-smu: can't find bus number !\n");
- return -ENXIO;
- }
- busid = *reg;
-
- iface = kzalloc(sizeof(struct smu_iface), GFP_KERNEL);
- if (iface == NULL) {
- printk(KERN_ERR "i2c-pmac-smu: can't allocate inteface !\n");
- return -ENOMEM;
- }
- init_completion(&iface->complete);
- iface->busid = busid;
-
- dev_set_drvdata(dev, iface);
-
- sprintf(iface->adapter.name, "smu-i2c-%02x", busid);
- iface->adapter.algo = &smu_algorithm;
- iface->adapter.algo_data = NULL;
- iface->adapter.client_register = NULL;
- iface->adapter.client_unregister = NULL;
- i2c_set_adapdata(&iface->adapter, iface);
- iface->adapter.dev.parent = dev;
-
- rc = i2c_add_adapter(&iface->adapter);
- if (rc) {
- printk(KERN_ERR "i2c-pamc-smu.c: Adapter %s registration "
- "failed\n", iface->adapter.name);
- i2c_set_adapdata(&iface->adapter, NULL);
- }
-
- if (probe) {
- unsigned char addr;
- printk("Probe: ");
- for (addr = 0x00; addr <= 0x7f; addr++) {
- if (i2c_smbus_xfer(&iface->adapter,addr,
- 0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- printk("%02x ", addr);
- }
- printk("\n");
- }
-
- printk(KERN_INFO "SMU i2c bus %x registered\n", busid);
-
- return 0;
-}
-
-static int dispose_iface(struct device *dev)
-{
- struct smu_iface *iface = dev_get_drvdata(dev);
- int rc;
-
- rc = i2c_del_adapter(&iface->adapter);
- i2c_set_adapdata(&iface->adapter, NULL);
- /* We aren't that prepared to deal with this... */
- if (rc)
- printk("i2c-pmac-smu.c: Failed to remove bus %s !\n",
- iface->adapter.name);
- dev_set_drvdata(dev, NULL);
- kfree(iface);
-
- return 0;
-}
-
-
-static int create_iface_of_platform(struct of_device* dev,
- const struct of_device_id *match)
-{
- return create_iface(dev->node, &dev->dev);
-}
-
-
-static int dispose_iface_of_platform(struct of_device* dev)
-{
- return dispose_iface(&dev->dev);
-}
-
-
-static struct of_device_id i2c_smu_match[] =
-{
- {
- .compatible = "smu-i2c",
- },
- {},
-};
-static struct of_platform_driver i2c_smu_of_platform_driver =
-{
- .name = "i2c-smu",
- .match_table = i2c_smu_match,
- .probe = create_iface_of_platform,
- .remove = dispose_iface_of_platform
-};
-
-
-static int __init i2c_pmac_smu_init(void)
-{
- of_register_driver(&i2c_smu_of_platform_driver);
- return 0;
-}
-
-
-static void __exit i2c_pmac_smu_cleanup(void)
-{
- of_unregister_driver(&i2c_smu_of_platform_driver);
-}
-
-module_init(i2c_pmac_smu_init);
-module_exit(i2c_pmac_smu_cleanup);
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
new file mode 100644
index 000000000000..df786eb55295
--- /dev/null
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -0,0 +1,290 @@
+/*
+ i2c Support for Apple SMU Controller
+
+ Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp.
+ <benh@kernel.crashing.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/types.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/prom.h>
+#include <asm/pmac_low_i2c.h>
+
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("I2C driver for Apple PowerMac");
+MODULE_LICENSE("GPL");
+
+/*
+ * SMBUS-type transfer entrypoint
+ */
+static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
+ u16 addr,
+ unsigned short flags,
+ char read_write,
+ u8 command,
+ int size,
+ union i2c_smbus_data* data)
+{
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adap);
+ int rc = 0;
+ int read = (read_write == I2C_SMBUS_READ);
+ int addrdir = (addr << 1) | read;
+ u8 local[2];
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc)
+ return rc;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
+ break;
+ case I2C_SMBUS_BYTE:
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ if (!read) {
+ local[0] = data->word & 0xff;
+ local[1] = (data->word >> 8) & 0xff;
+ }
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2);
+ if (rc == 0 && read) {
+ data->word = ((u16)local[1]) << 8;
+ data->word |= local[0];
+ }
+ break;
+
+ /* Note that these are broken vs. the expected smbus API where
+ * on reads, the lenght is actually returned from the function,
+ * but I think the current API makes no sense and I don't want
+ * any driver that I haven't verified for correctness to go
+ * anywhere near a pmac i2c bus anyway ...
+ *
+ * I'm also not completely sure what kind of phases to do between
+ * the actual command and the data (what I am _supposed_ to do that
+ * is). For now, I assume writes are a single stream and reads have
+ * a repeat start/addr phase (but not stop in between)
+ */
+ case I2C_SMBUS_BLOCK_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
+ data->block[0] + 1);
+
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ rc = pmac_i2c_setmode(bus, read ?
+ pmac_i2c_mode_combined :
+ pmac_i2c_mode_stdsub);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 1, command,
+ read ? data->block : &data->block[1],
+ data->block[0]);
+ break;
+
+ default:
+ rc = -EINVAL;
+ }
+ bail:
+ pmac_i2c_close(bus);
+ return rc;
+}
+
+/*
+ * Generic i2c master transfer entrypoint. This driver only support single
+ * messages (for "lame i2c" transfers). Anything else should use the smbus
+ * entry point
+ */
+static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
+ struct i2c_msg *msgs,
+ int num)
+{
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adap);
+ int rc = 0;
+ int read;
+ int addrdir;
+
+ if (num != 1)
+ return -EINVAL;
+ if (msgs->flags & I2C_M_TEN)
+ return -EINVAL;
+ read = (msgs->flags & I2C_M_RD) != 0;
+ addrdir = (msgs->addr << 1) | read;
+ if (msgs->flags & I2C_M_REV_DIR_ADDR)
+ addrdir ^= 1;
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc)
+ return rc;
+ rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
+ if (rc)
+ goto bail;
+ rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
+ bail:
+ pmac_i2c_close(bus);
+ return rc < 0 ? rc : msgs->len;
+}
+
+static u32 i2c_powermac_func(struct i2c_adapter * adapter)
+{
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C;
+}
+
+/* For now, we only handle smbus */
+static struct i2c_algorithm i2c_powermac_algorithm = {
+ .smbus_xfer = i2c_powermac_smbus_xfer,
+ .master_xfer = i2c_powermac_master_xfer,
+ .functionality = i2c_powermac_func,
+};
+
+
+static int i2c_powermac_remove(struct device *dev)
+{
+ struct i2c_adapter *adapter = dev_get_drvdata(dev);
+ struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter);
+ int rc;
+
+ rc = i2c_del_adapter(adapter);
+ pmac_i2c_detach_adapter(bus, adapter);
+ i2c_set_adapdata(adapter, NULL);
+ /* We aren't that prepared to deal with this... */
+ if (rc)
+ printk("i2c-powermac.c: Failed to remove bus %s !\n",
+ adapter->name);
+ dev_set_drvdata(dev, NULL);
+ kfree(adapter);
+
+ return 0;
+}
+
+
+static int i2c_powermac_probe(struct device *dev)
+{
+ struct pmac_i2c_bus *bus = dev->platform_data;
+ struct device_node *parent = NULL;
+ struct i2c_adapter *adapter;
+ char name[32], *basename;
+ int rc;
+
+ if (bus == NULL)
+ return -EINVAL;
+
+ /* Ok, now we need to make up a name for the interface that will
+ * match what we used to do in the past, that is basically the
+ * controller's parent device node for keywest. PMU didn't have a
+ * naming convention and SMU has a different one
+ */
+ switch(pmac_i2c_get_type(bus)) {
+ case pmac_i2c_bus_keywest:
+ parent = of_get_parent(pmac_i2c_get_controller(bus));
+ if (parent == NULL)
+ return -EINVAL;
+ basename = parent->name;
+ break;
+ case pmac_i2c_bus_pmu:
+ basename = "pmu";
+ break;
+ case pmac_i2c_bus_smu:
+ /* This is not what we used to do but I'm fixing drivers at
+ * the same time as this change
+ */
+ basename = "smu";
+ break;
+ default:
+ return -EINVAL;
+ }
+ snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus));
+ of_node_put(parent);
+
+ adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, adapter);
+ strcpy(adapter->name, name);
+ adapter->algo = &i2c_powermac_algorithm;
+ i2c_set_adapdata(adapter, bus);
+ adapter->dev.parent = dev;
+ pmac_i2c_attach_adapter(bus, adapter);
+ rc = i2c_add_adapter(adapter);
+ if (rc) {
+ printk(KERN_ERR "i2c-powermac: Adapter %s registration "
+ "failed\n", name);
+ i2c_set_adapdata(adapter, NULL);
+ pmac_i2c_detach_adapter(bus, adapter);
+ }
+
+ printk(KERN_INFO "PowerMac i2c bus %s registered\n", name);
+ return rc;
+}
+
+
+static struct device_driver i2c_powermac_driver = {
+ .name = "i2c-powermac",
+ .bus = &platform_bus_type,
+ .probe = i2c_powermac_probe,
+ .remove = i2c_powermac_remove,
+};
+
+static int __init i2c_powermac_init(void)
+{
+ driver_register(&i2c_powermac_driver);
+ return 0;
+}
+
+
+static void __exit i2c_powermac_cleanup(void)
+{
+ driver_unregister(&i2c_powermac_driver);
+}
+
+module_init(i2c_powermac_init);
+module_exit(i2c_powermac_cleanup);
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 70f7ab829d36..86e2234faf80 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -899,6 +899,12 @@ 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;
+ /* If the I2C controller is disabled we need to reset it (probably due
+ to a suspend/resume destroying state). We do this here as we can then
+ avoid worrying about resuming the controller before its users. */
+ if (!(ICR & ICR_IUE))
+ i2c_pxa_reset(i2c);
+
for (i = adap->retries; i >= 0; i--) {
ret = i2c_pxa_do_xfer(i2c, msgs, num);
if (ret != I2C_RETRY)
@@ -939,7 +945,9 @@ static struct pxa_i2c i2c_pxa = {
static int i2c_pxa_probe(struct platform_device *dev)
{
struct pxa_i2c *i2c = &i2c_pxa;
+#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
+#endif
int ret;
#ifdef CONFIG_PXA27x
@@ -1024,5 +1032,7 @@ static void i2c_adap_pxa_exit(void)
return platform_driver_unregister(&i2c_pxa_driver);
}
+MODULE_LICENSE("GPL");
+
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 58cfd3111ef6..f7d40f8e5f5c 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -34,12 +34,12 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-iic.h>
#include <asm/arch/iic.h>
@@ -738,7 +738,6 @@ static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
{
if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
clk_disable(i2c->clk);
- clk_unuse(i2c->clk);
clk_put(i2c->clk);
i2c->clk = NULL;
}
@@ -778,7 +777,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
- clk_use(i2c->clk);
clk_enable(i2c->clk);
/* map the registers */
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 02682fb794c8..93d483b8b770 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -52,9 +52,9 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd,
* Driver data (common to all clients)
*/
static struct i2c_driver ds1337_driver = {
- .owner = THIS_MODULE,
- .name = "ds1337",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "ds1337",
+ },
.attach_adapter = ds1337_attach_adapter,
.detach_client = ds1337_detach_client,
.command = ds1337_command,
@@ -337,13 +337,38 @@ exit:
static void ds1337_init_client(struct i2c_client *client)
{
- s32 val;
+ u8 status, control;
- /* Ensure that device is set in 24-hour mode */
- val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
- if ((val >= 0) && (val & (1 << 6)))
- i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
- val & 0x3f);
+ /* On some boards, the RTC isn't configured by boot firmware.
+ * Handle that case by starting/configuring the RTC now.
+ */
+ status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+ control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+
+ if ((status & 0x80) || (control & 0x80)) {
+ /* RTC not running */
+ u8 buf[16];
+ struct i2c_msg msg[1];
+
+ dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+
+ /* Initialize all, including STATUS and CONTROL to zero */
+ memset(buf, 0, sizeof(buf));
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = sizeof(buf);
+ msg[0].buf = &buf[0];
+
+ i2c_transfer(client->adapter, msg, 1);
+ } else {
+ /* Running: ensure that device is set in 24-hour mode */
+ s32 val;
+
+ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+ if ((val >= 0) && (val & (1 << 6)))
+ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+ val & 0x3f);
+ }
}
static int ds1337_detach_client(struct i2c_client *client)
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
index da488b735abf..0710b9da9d54 100644
--- a/drivers/i2c/chips/ds1374.c
+++ b/drivers/i2c/chips/ds1374.c
@@ -232,10 +232,10 @@ static int ds1374_detach(struct i2c_client *client)
}
static struct i2c_driver ds1374_driver = {
- .owner = THIS_MODULE,
- .name = DS1374_DRV_NAME,
+ .driver = {
+ .name = DS1374_DRV_NAME,
+ },
.id = I2C_DRIVERID_DS1374,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ds1374_attach,
.detach_client = ds1374_detach,
};
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 4baf573fa04f..41116b7947f6 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -68,10 +68,10 @@ static int eeprom_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver eeprom_driver = {
- .owner = THIS_MODULE,
- .name = "eeprom",
+ .driver = {
+ .name = "eeprom",
+ },
.id = I2C_DRIVERID_EEPROM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = eeprom_attach_adapter,
.detach_client = eeprom_detach_client,
};
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index d2a100d77839..1251c7fc18d5 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -1632,11 +1632,11 @@ static int isp1301_scan_bus(struct i2c_adapter *bus)
}
static struct i2c_driver isp1301_driver = {
- .owner = THIS_MODULE,
- .name = "isp1301_omap",
+ .driver = {
+ .name = "isp1301_omap",
+ },
.id = 1301, /* FIXME "official", i2c-ids.h */
.class = I2C_CLASS_HWMON,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = isp1301_scan_bus,
.detach_client = isp1301_detach_client,
};
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 3df309ae44a6..2dc3d48375fc 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -211,10 +211,10 @@ m41t00_detach(struct i2c_client *client)
}
static struct i2c_driver m41t00_driver = {
- .owner = THIS_MODULE,
- .name = M41T00_DRV_NAME,
+ .driver = {
+ .name = M41T00_DRV_NAME,
+ },
.id = I2C_DRIVERID_STM41T00,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = m41t00_attach,
.detach_client = m41t00_detach,
};
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index b376a006883c..6d3ff584155e 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -67,9 +67,9 @@ static int max6875_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver max6875_driver = {
- .owner = THIS_MODULE,
- .name = "max6875",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "max6875",
+ },
.attach_adapter = max6875_attach_adapter,
.detach_client = max6875_detach_client,
};
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
index 59a930346229..54b6e6a4beed 100644
--- a/drivers/i2c/chips/pca9539.c
+++ b/drivers/i2c/chips/pca9539.c
@@ -38,9 +38,9 @@ static int pca9539_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pca9539_driver = {
- .owner = THIS_MODULE,
- .name = "pca9539",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "pca9539",
+ },
.attach_adapter = pca9539_attach_adapter,
.detach_client = pca9539_detach_client,
};
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index c323c2de236c..c3e6449c4481 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -65,10 +65,10 @@ static void pcf8574_init_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8574_driver = {
- .owner = THIS_MODULE,
- .name = "pcf8574",
+ .driver = {
+ .name = "pcf8574",
+ },
.id = I2C_DRIVERID_PCF8574,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8574_attach_adapter,
.detach_client = pcf8574_detach_client,
};
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index ce420a67560b..36cff09c678d 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -88,10 +88,10 @@ static int pcf8591_read_channel(struct device *dev, int channel);
/* This is the driver that will be inserted */
static struct i2c_driver pcf8591_driver = {
- .owner = THIS_MODULE,
- .name = "pcf8591",
+ .driver = {
+ .name = "pcf8591",
+ },
.id = I2C_DRIVERID_PCF8591,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = pcf8591_attach_adapter,
.detach_client = pcf8591_detach_client,
};
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 916cdc1af23c..ceaa6b0bdfd6 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -14,6 +14,7 @@
*/
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -52,9 +53,6 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
#define CTRL1(c) _rtc8564_ctrl1(c)
#define CTRL2(c) _rtc8564_ctrl2(c)
-#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
-#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
-
static int debug;;
module_param(debug, int, S_IRUGO | S_IWUSR);
@@ -157,7 +155,6 @@ static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind)
strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
i2c_set_clientdata(new_client, d);
- new_client->flags = I2C_CLIENT_ALLOW_USE;
new_client->addr = addr;
new_client->adapter = adap;
new_client->driver = &rtc8564_driver;
@@ -224,16 +221,16 @@ static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt)
return ret;
/* century stored in minute alarm reg */
- dt->year = BCD_TO_BIN(buf[RTC8564_REG_YEAR]);
- dt->year += 100 * BCD_TO_BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
- dt->mday = BCD_TO_BIN(buf[RTC8564_REG_DAY] & 0x3f);
- dt->wday = BCD_TO_BIN(buf[RTC8564_REG_WDAY] & 7);
- dt->mon = BCD_TO_BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
+ dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]);
+ dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f);
+ dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f);
+ dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7);
+ dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f);
- dt->secs = BCD_TO_BIN(buf[RTC8564_REG_SEC] & 0x7f);
+ dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f);
dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80;
- dt->mins = BCD_TO_BIN(buf[RTC8564_REG_MIN] & 0x7f);
- dt->hours = BCD_TO_BIN(buf[RTC8564_REG_HR] & 0x3f);
+ dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f);
+ dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f);
_DBGRTCTM(2, *dt);
@@ -255,18 +252,18 @@ rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo)
buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP;
buf[RTC8564_REG_CTRL2] = CTRL2(client);
- buf[RTC8564_REG_SEC] = BIN_TO_BCD(dt->secs);
- buf[RTC8564_REG_MIN] = BIN_TO_BCD(dt->mins);
- buf[RTC8564_REG_HR] = BIN_TO_BCD(dt->hours);
+ buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs);
+ buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins);
+ buf[RTC8564_REG_HR] = BIN2BCD(dt->hours);
if (datetoo) {
len += 5;
- buf[RTC8564_REG_DAY] = BIN_TO_BCD(dt->mday);
- buf[RTC8564_REG_WDAY] = BIN_TO_BCD(dt->wday);
- buf[RTC8564_REG_MON_CENT] = BIN_TO_BCD(dt->mon) & 0x1f;
+ buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday);
+ buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday);
+ buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f;
/* century stored in minute alarm reg */
- buf[RTC8564_REG_YEAR] = BIN_TO_BCD(dt->year % 100);
- buf[RTC8564_REG_AL_MIN] = BIN_TO_BCD(dt->year / 100);
+ buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100);
+ buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100);
}
ret = rtc8564_write(client, 0, buf, len);
@@ -361,10 +358,10 @@ rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver rtc8564_driver = {
- .owner = THIS_MODULE,
- .name = "RTC8564",
+ .driver = {
+ .name = "RTC8564",
+ },
.id = I2C_DRIVERID_RTC8564,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = rtc8564_probe,
.detach_client = rtc8564_detach,
.command = rtc8564_command
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index 280dd7a45db6..1af3dfbb8086 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -494,6 +494,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
{
struct tps65010 *tps;
int status;
+ unsigned long irqflags;
if (the_tps) {
dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
@@ -520,13 +521,14 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
}
#ifdef CONFIG_ARM
+ irqflags = SA_SAMPLE_RANDOM | SA_TRIGGER_LOW;
if (machine_is_omap_h2()) {
tps->model = TPS65010;
omap_cfg_reg(W4_GPIO58);
tps->irq = OMAP_GPIO_IRQ(58);
omap_request_gpio(58);
omap_set_gpio_direction(58, 1);
- set_irq_type(tps->irq, IRQT_FALLING);
+ irqflags |= SA_TRIGGER_FALLING;
}
if (machine_is_omap_osk()) {
tps->model = TPS65010;
@@ -534,7 +536,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
omap_request_gpio(OMAP_MPUIO(1));
omap_set_gpio_direction(OMAP_MPUIO(1), 1);
- set_irq_type(tps->irq, IRQT_FALLING);
+ irqflags |= SA_TRIGGER_FALLING;
}
if (machine_is_omap_h3()) {
tps->model = TPS65013;
@@ -542,13 +544,12 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind)
// FIXME set up this board's IRQ ...
}
#else
-#define set_irq_type(num,trigger) do{}while(0)
+ irqflags = SA_SAMPLE_RANDOM;
#endif
if (tps->irq > 0) {
- set_irq_type(tps->irq, IRQT_LOW);
status = request_irq(tps->irq, tps65010_irq,
- SA_SAMPLE_RANDOM, DRIVER_NAME, tps);
+ irqflags, DRIVER_NAME, tps);
if (status < 0) {
dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n",
tps->irq, status);
@@ -637,9 +638,9 @@ static int __init tps65010_scan_bus(struct i2c_adapter *bus)
}
static struct i2c_driver tps65010_driver = {
- .owner = THIS_MODULE,
- .name = "tps65010",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "tps65010",
+ },
.attach_adapter = tps65010_scan_bus,
.detach_client = __exit_p(tps65010_detach_client),
};
diff --git a/drivers/i2c/chips/x1205.c b/drivers/i2c/chips/x1205.c
index 7da366cdc18c..245fffa92dbd 100644
--- a/drivers/i2c/chips/x1205.c
+++ b/drivers/i2c/chips/x1205.c
@@ -105,9 +105,9 @@ static int x1205_command(struct i2c_client *client, unsigned int cmd,
void *arg);
static struct i2c_driver x1205_driver = {
- .owner = THIS_MODULE,
- .name = "x1205",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "x1205",
+ },
.attach_adapter = &x1205_attach,
.detach_client = &x1205_detach,
};
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 82ea1b7ec914..0ce58b506046 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev)
return rc;
}
-struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
- .suspend = i2c_bus_suspend,
- .resume = i2c_bus_resume,
-};
-
static int i2c_device_probe(struct device *dev)
{
return -ENODEV;
@@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev)
return 0;
}
+struct bus_type i2c_bus_type = {
+ .name = "i2c",
+ .match = i2c_device_match,
+ .probe = i2c_device_probe,
+ .remove = i2c_device_remove,
+ .suspend = i2c_bus_suspend,
+ .resume = i2c_bus_resume,
+};
+
void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = {
.owner = THIS_MODULE,
.name = "i2c_adapter",
.bus = &i2c_bus_type,
- .probe = i2c_device_probe,
- .remove = i2c_device_remove,
};
static void i2c_adapter_class_dev_release(struct class_device *dev)
@@ -197,7 +197,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
/* inform drivers of new adapters */
list_for_each(item,&drivers) {
driver = list_entry(item, struct i2c_driver, list);
- if (driver->flags & I2C_DF_NOTIFY)
+ if (driver->attach_adapter)
/* We ignore the return code; if it fails, too bad */
driver->attach_adapter(adap);
}
@@ -235,7 +235,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
if (driver->detach_adapter)
if ((res = driver->detach_adapter(adap))) {
dev_err(&adap->dev, "detach_adapter failed "
- "for driver [%s]\n", driver->name);
+ "for driver [%s]\n",
+ driver->driver.name);
goto out_unlock;
}
}
@@ -245,10 +246,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
list_for_each_safe(item, _n, &adap->clients) {
client = list_entry(item, struct i2c_client, list);
- /* detaching devices is unconditional of the set notify
- * flag, as _all_ clients that reside on the adapter
- * must be deleted, as this would cause invalid states.
- */
if ((res=client->driver->detach_client(client))) {
dev_err(&adap->dev, "detach_client failed for client "
"[%s] at address 0x%02x\n", client->name,
@@ -286,7 +283,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
* chips.
*/
-int i2c_add_driver(struct i2c_driver *driver)
+int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
{
struct list_head *item;
struct i2c_adapter *adapter;
@@ -295,21 +292,18 @@ int i2c_add_driver(struct i2c_driver *driver)
down(&core_lists);
/* add the driver to the list of i2c drivers in the driver core */
- driver->driver.owner = driver->owner;
- driver->driver.name = driver->name;
+ driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
- driver->driver.probe = i2c_device_probe;
- driver->driver.remove = i2c_device_remove;
res = driver_register(&driver->driver);
if (res)
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->driver.name);
/* now look for instances of driver on our adapters */
- if (driver->flags & I2C_DF_NOTIFY) {
+ if (driver->attach_adapter) {
list_for_each(item,&adapters) {
adapter = list_entry(item, struct i2c_adapter, list);
driver->attach_adapter(adapter);
@@ -320,6 +314,7 @@ int i2c_add_driver(struct i2c_driver *driver)
up(&core_lists);
return res;
}
+EXPORT_SYMBOL(i2c_register_driver);
int i2c_del_driver(struct i2c_driver *driver)
{
@@ -334,17 +329,14 @@ 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.
- *
- * 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);
if (driver->detach_adapter) {
if ((res = driver->detach_adapter(adap))) {
dev_err(&adap->dev, "detach_adapter failed "
- "for driver [%s]\n", driver->name);
+ "for driver [%s]\n",
+ driver->driver.name);
goto out_unlock;
}
} else {
@@ -368,7 +360,7 @@ int i2c_del_driver(struct i2c_driver *driver)
driver_unregister(&driver->driver);
list_del(&driver->list);
- pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
+ pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
out_unlock:
up(&core_lists);
@@ -419,8 +411,7 @@ int i2c_attach_client(struct i2c_client *client)
}
}
- if (client->flags & I2C_CLIENT_ALLOW_USE)
- client->usage_count = 0;
+ client->usage_count = 0;
client->dev.parent = &client->adapter->dev;
client->dev.driver = &client->driver->driver;
@@ -443,8 +434,7 @@ 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->usage_count > 0) {
dev_warn(&client->dev, "Client [%s] still busy, "
"can't detach\n", client->name);
return -EBUSY;
@@ -475,10 +465,10 @@ int i2c_detach_client(struct i2c_client *client)
static int i2c_inc_use_client(struct i2c_client *client)
{
- if (!try_module_get(client->driver->owner))
+ if (!try_module_get(client->driver->driver.owner))
return -ENODEV;
if (!try_module_get(client->adapter->owner)) {
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
return -ENODEV;
}
@@ -487,7 +477,7 @@ static int i2c_inc_use_client(struct i2c_client *client)
static void i2c_dec_use_client(struct i2c_client *client)
{
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
module_put(client->adapter->owner);
}
@@ -499,33 +489,20 @@ int i2c_use_client(struct i2c_client *client)
if (ret)
return ret;
- if (client->flags & I2C_CLIENT_ALLOW_USE) {
- if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
- client->usage_count++;
- else if (client->usage_count > 0)
- goto busy;
- else
- client->usage_count++;
- }
+ client->usage_count++;
return 0;
- busy:
- i2c_dec_use_client(client);
- return -EBUSY;
}
int i2c_release_client(struct i2c_client *client)
{
- if(client->flags & I2C_CLIENT_ALLOW_USE) {
- if(client->usage_count>0)
- client->usage_count--;
- else {
- pr_debug("i2c-core: %s used one too many times\n",
- __FUNCTION__);
- return -EPERM;
- }
+ if (!client->usage_count) {
+ pr_debug("i2c-core: %s used one too many times\n",
+ __FUNCTION__);
+ return -EPERM;
}
+ client->usage_count--;
i2c_dec_use_client(client);
return 0;
@@ -539,14 +516,14 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
down(&adap->clist_lock);
list_for_each(item,&adap->clients) {
client = list_entry(item, struct i2c_client, list);
- if (!try_module_get(client->driver->owner))
+ if (!try_module_get(client->driver->driver.owner))
continue;
if (NULL != client->driver->command) {
up(&adap->clist_lock);
client->driver->command(client,cmd,arg);
down(&adap->clist_lock);
}
- module_put(client->driver->owner);
+ module_put(client->driver->driver.owner);
}
up(&adap->clist_lock);
}
@@ -1147,7 +1124,6 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
-EXPORT_SYMBOL(i2c_add_driver);
EXPORT_SYMBOL(i2c_del_driver);
EXPORT_SYMBOL(i2c_attach_client);
EXPORT_SYMBOL(i2c_detach_client);
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 8af0bd1424d2..ed7eed388bae 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -42,8 +42,7 @@ static struct i2c_client i2cdev_client_template;
struct i2c_dev {
int minor;
struct i2c_adapter *adap;
- struct class_device class_dev;
- struct completion released; /* FIXME, we need a class_device_unregister() */
+ struct class_device *class_dev;
};
#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
@@ -105,7 +104,10 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
{
- struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
+ struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
+
+ if (!i2c_dev)
+ return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name);
}
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
@@ -408,21 +410,12 @@ static struct file_operations i2cdev_fops = {
.release = i2cdev_release,
};
-static void release_i2c_dev(struct class_device *dev)
-{
- struct i2c_dev *i2c_dev = to_i2c_dev(dev);
- complete(&i2c_dev->released);
-}
-
-static struct class i2c_dev_class = {
- .name = "i2c-dev",
- .release = &release_i2c_dev,
-};
+static struct class *i2c_dev_class;
static int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
struct i2c_dev *i2c_dev;
- int retval;
+ struct device *dev;
i2c_dev = get_free_i2c_dev(adap);
if (IS_ERR(i2c_dev))
@@ -434,21 +427,20 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
/* register this i2c device with the driver core */
i2c_dev->adap = adap;
if (adap->dev.parent == &platform_bus)
- i2c_dev->class_dev.dev = &adap->dev;
+ dev = &adap->dev;
else
- i2c_dev->class_dev.dev = adap->dev.parent;
- i2c_dev->class_dev.class = &i2c_dev_class;
- i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor);
- snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor);
- retval = class_device_register(&i2c_dev->class_dev);
- if (retval)
+ dev = adap->dev.parent;
+ i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
+ MKDEV(I2C_MAJOR, i2c_dev->minor),
+ dev, "i2c-%d", i2c_dev->minor);
+ if (!i2c_dev->class_dev)
goto error;
- class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
+ class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
return 0;
error:
return_i2c_dev(i2c_dev);
kfree(i2c_dev);
- return retval;
+ return -ENODEV;
}
static int i2cdev_detach_adapter(struct i2c_adapter *adap)
@@ -459,10 +451,8 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
if (!i2c_dev)
return -ENODEV;
- init_completion(&i2c_dev->released);
return_i2c_dev(i2c_dev);
- class_device_unregister(&i2c_dev->class_dev);
- wait_for_completion(&i2c_dev->released);
+ class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -474,21 +464,14 @@ static int i2cdev_detach_client(struct i2c_client *client)
return 0;
}
-static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
- void *arg)
-{
- return -1;
-}
-
static struct i2c_driver i2cdev_driver = {
- .owner = THIS_MODULE,
- .name = "dev_driver",
+ .driver = {
+ .name = "dev_driver",
+ },
.id = I2C_DRIVERID_I2CDEV,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = i2cdev_attach_adapter,
.detach_adapter = i2cdev_detach_adapter,
.detach_client = i2cdev_detach_client,
- .command = i2cdev_command,
};
static struct i2c_client i2cdev_client_template = {
@@ -507,8 +490,8 @@ static int __init i2c_dev_init(void)
if (res)
goto out;
- res = class_register(&i2c_dev_class);
- if (res)
+ i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
+ if (IS_ERR(i2c_dev_class))
goto out_unreg_chrdev;
res = i2c_add_driver(&i2cdev_driver);
@@ -518,7 +501,7 @@ static int __init i2c_dev_init(void)
return 0;
out_unreg_class:
- class_unregister(&i2c_dev_class);
+ class_destroy(i2c_dev_class);
out_unreg_chrdev:
unregister_chrdev(I2C_MAJOR, "i2c");
out:
@@ -529,7 +512,7 @@ out:
static void __exit i2c_dev_exit(void)
{
i2c_del_driver(&i2cdev_driver);
- class_unregister(&i2c_dev_class);
+ class_destroy(i2c_dev_class);
unregister_chrdev(I2C_MAJOR,"i2c");
}
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b4d7a3efb90f..3325660f7248 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
*/
spin_lock_irqsave(&ide_lock, flags);
end_that_request_chunk(failed, 0, failed->data_len);
- end_that_request_last(failed);
+ end_that_request_last(failed, 0);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -980,7 +980,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
* and attempt to recover if there are problems. Returns 0 if everything's
* ok; nonzero if the request has been terminated.
*/
-static inline
+static
int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
{
if (ireason == 2)
@@ -1332,8 +1332,6 @@ static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
if (cdrom_read_from_buffer(drive))
return ide_stopped;
- blk_attempt_remerge(drive->queue, rq);
-
/* Clear the local sector buffer. */
info->nsectors_buffered = 0;
@@ -1541,7 +1539,7 @@ int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
/*
* Write handling
*/
-static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
+static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
{
/* Two notes about IDE interrupt reason here - 0 means that
* the drive wants to receive data from us, 2 means that
@@ -1735,7 +1733,7 @@ end_request:
spin_lock_irqsave(&ide_lock, flags);
blkdev_dequeue_request(rq);
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
HWGROUP(drive)->rq = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
@@ -1874,14 +1872,6 @@ static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
return ide_stopped;
}
- /*
- * for dvd-ram and such media, it's a really big deal to get
- * big writes all the time. so scour the queue and attempt to
- * remerge requests, often the plugging will not have had time
- * to do this properly
- */
- blk_attempt_remerge(drive->queue, rq);
-
info->nsectors_buffered = 0;
/* use dma, if possible. we don't need to check more, since we
@@ -2905,6 +2895,8 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
devinfo->mask |= CDC_CLOSE_TRAY;
if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
devinfo->mask |= CDC_MO_DRIVE;
+ if (!CDROM_CONFIG_FLAGS(drive)->ram)
+ devinfo->mask |= CDC_RAM;
devinfo->disk = info->disk;
return register_cdrom(devinfo);
@@ -3264,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
}
#endif
-static int ide_cd_remove(struct device *dev)
+static void ide_cd_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info = drive->driver_data;
ide_unregister_subdriver(drive, info->driver);
@@ -3274,8 +3265,6 @@ static int ide_cd_remove(struct device *dev)
del_gendisk(info->disk);
ide_cd_put(info);
-
- return 0;
}
static void ide_cd_release(struct kref *kref)
@@ -3299,7 +3288,7 @@ static void ide_cd_release(struct kref *kref)
kfree(info);
}
-static int ide_cd_probe(struct device *);
+static int ide_cd_probe(ide_drive_t *);
#ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity
@@ -3325,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
.bus = &ide_bus_type,
- .probe = ide_cd_probe,
- .remove = ide_cd_remove,
},
+ .probe = ide_cd_probe,
+ .remove = ide_cd_remove,
.version = IDECD_VERSION,
.media = ide_cdrom,
.supports_dsc_overlap = 1,
@@ -3421,9 +3410,8 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400);
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-static int ide_cd_probe(struct device *dev)
+static int ide_cd_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info;
struct gendisk *g;
struct request_sense sense;
@@ -3509,6 +3497,7 @@ static int __init ide_cdrom_init(void)
return driver_register(&ide_cdrom_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-cdrom*");
module_init(ide_cdrom_init);
module_exit(ide_cdrom_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 449522f0540c..ca25f9e3d0f4 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -477,7 +477,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id)
&& id->lba_capacity_2;
}
-static inline void idedisk_check_hpa(ide_drive_t *drive)
+static void idedisk_check_hpa(ide_drive_t *drive)
{
unsigned long long capacity, set_max;
int lba48 = idedisk_supports_lba48(drive->id);
@@ -681,50 +681,9 @@ static ide_proc_entry_t idedisk_proc[] = {
#endif /* CONFIG_PROC_FS */
-static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq)
+static void idedisk_prepare_flush(request_queue_t *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
- struct request *rq = flush_rq->end_io_data;
- int good_sectors = rq->hard_nr_sectors;
- int bad_sectors;
- sector_t sector;
-
- if (flush_rq->errors & ABRT_ERR) {
- printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
- blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);
- blk_queue_issue_flush_fn(drive->queue, NULL);
- good_sectors = 0;
- } else if (flush_rq->errors) {
- good_sectors = 0;
- if (blk_barrier_preflush(rq)) {
- sector = ide_get_error_location(drive,flush_rq->buffer);
- if ((sector >= rq->hard_sector) &&
- (sector < rq->hard_sector + rq->hard_nr_sectors))
- good_sectors = sector - rq->hard_sector;
- }
- }
-
- if (flush_rq->errors)
- printk(KERN_ERR "%s: failed barrier write: "
- "sector=%Lx(good=%d/bad=%d)\n",
- drive->name, (unsigned long long)rq->sector,
- good_sectors,
- (int) (rq->hard_nr_sectors-good_sectors));
-
- bad_sectors = rq->hard_nr_sectors - good_sectors;
-
- if (good_sectors)
- __ide_end_request(drive, rq, 1, good_sectors);
- if (bad_sectors)
- __ide_end_request(drive, rq, 0, bad_sectors);
-}
-
-static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
-{
- ide_drive_t *drive = q->queuedata;
-
- if (!drive->wcache)
- return 0;
memset(rq->cmd, 0, sizeof(rq->cmd));
@@ -735,9 +694,8 @@ static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
rq->cmd[0] = WIN_FLUSH_CACHE;
- rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
+ rq->flags |= REQ_DRIVE_TASK;
rq->buffer = rq->cmd;
- return 1;
}
static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -794,27 +752,64 @@ static int set_nowerr(ide_drive_t *drive, int arg)
return 0;
}
+static void update_ordered(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ unsigned ordered = QUEUE_ORDERED_NONE;
+ prepare_flush_fn *prep_fn = NULL;
+ issue_flush_fn *issue_fn = NULL;
+
+ if (drive->wcache) {
+ unsigned long long capacity;
+ int barrier;
+ /*
+ * We must avoid issuing commands a drive does not
+ * understand or we may crash it. We check flush cache
+ * is supported. We also check we have the LBA48 flush
+ * cache if the drive capacity is too large. By this
+ * time we have trimmed the drive capacity if LBA48 is
+ * not available so we don't need to recheck that.
+ */
+ capacity = idedisk_capacity(drive);
+ barrier = ide_id_has_flush_cache(id) &&
+ (drive->addressing == 0 || capacity <= (1ULL << 28) ||
+ ide_id_has_flush_cache_ext(id));
+
+ printk(KERN_INFO "%s: cache flushes %ssupported\n",
+ drive->name, barrier ? "" : "not");
+
+ if (barrier) {
+ ordered = QUEUE_ORDERED_DRAIN_FLUSH;
+ prep_fn = idedisk_prepare_flush;
+ issue_fn = idedisk_issue_flush;
+ }
+ } else
+ ordered = QUEUE_ORDERED_DRAIN;
+
+ blk_queue_ordered(drive->queue, ordered, prep_fn);
+ blk_queue_issue_flush_fn(drive->queue, issue_fn);
+}
+
static int write_cache(ide_drive_t *drive, int arg)
{
ide_task_t args;
- int err;
-
- if (!ide_id_has_flush_cache(drive->id))
- return 1;
+ int err = 1;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
+ if (ide_id_has_flush_cache(drive->id)) {
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ?
SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
- args.command_type = IDE_DRIVE_TASK_NO_DATA;
- args.handler = &task_no_data_intr;
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES;
+ args.command_type = IDE_DRIVE_TASK_NO_DATA;
+ args.handler = &task_no_data_intr;
+ err = ide_raw_taskfile(drive, &args, NULL);
+ if (err == 0)
+ drive->wcache = arg;
+ }
- err = ide_raw_taskfile(drive, &args, NULL);
- if (err)
- return err;
+ update_ordered(drive);
- drive->wcache = arg;
- return 0;
+ return err;
}
static int do_idedisk_flushcache (ide_drive_t *drive)
@@ -888,7 +883,6 @@ static void idedisk_setup (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
unsigned long long capacity;
- int barrier;
idedisk_add_settings(drive);
@@ -992,31 +986,6 @@ static void idedisk_setup (ide_drive_t *drive)
drive->wcache = 1;
write_cache(drive, 1);
-
- /*
- * We must avoid issuing commands a drive does not understand
- * or we may crash it. We check flush cache is supported. We also
- * check we have the LBA48 flush cache if the drive capacity is
- * too large. By this time we have trimmed the drive capacity if
- * LBA48 is not available so we don't need to recheck that.
- */
- barrier = 0;
- if (ide_id_has_flush_cache(id))
- barrier = 1;
- if (drive->addressing == 1) {
- /* Can't issue the correct flush ? */
- if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id))
- barrier = 0;
- }
-
- printk(KERN_INFO "%s: cache flushes %ssupported\n",
- drive->name, barrier ? "" : "not ");
- if (barrier) {
- blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH);
- drive->queue->prepare_flush_fn = idedisk_prepare_flush;
- drive->queue->end_flush_fn = idedisk_end_flush;
- blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
- }
}
static void ide_cacheflush_p(ide_drive_t *drive)
@@ -1028,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}
-static int ide_disk_remove(struct device *dev)
+static void ide_disk_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = idkp->disk;
@@ -1041,8 +1009,6 @@ static int ide_disk_remove(struct device *dev)
ide_cacheflush_p(drive);
ide_disk_put(idkp);
-
- return 0;
}
static void ide_disk_release(struct kref *kref)
@@ -1058,12 +1024,10 @@ static void ide_disk_release(struct kref *kref)
kfree(idkp);
}
-static int ide_disk_probe(struct device *dev);
+static int ide_disk_probe(ide_drive_t *drive);
-static void ide_device_shutdown(struct device *dev)
+static void ide_device_shutdown(ide_drive_t *drive)
{
- ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
-
#ifdef CONFIG_ALPHA
/* On Alpha, halt(8) doesn't actually turn the machine off,
it puts you into the sort of firmware monitor. Typically,
@@ -1085,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev)
}
printk("Shutdown: %s\n", drive->name);
- dev->bus->suspend(dev, PMSG_SUSPEND);
+ drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND);
}
static ide_driver_t idedisk_driver = {
@@ -1093,10 +1057,10 @@ static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE,
.name = "ide-disk",
.bus = &ide_bus_type,
- .probe = ide_disk_probe,
- .remove = ide_disk_remove,
- .shutdown = ide_device_shutdown,
},
+ .probe = ide_disk_probe,
+ .remove = ide_disk_remove,
+ .shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
.media = ide_disk,
.supports_dsc_overlap = 0,
@@ -1161,6 +1125,17 @@ static int idedisk_release(struct inode *inode, struct file *filp)
return 0;
}
+static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
+ ide_drive_t *drive = idkp->drive;
+
+ geo->heads = drive->bios_head;
+ geo->sectors = drive->bios_sect;
+ geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+ return 0;
+}
+
static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -1195,15 +1170,15 @@ static struct block_device_operations idedisk_ops = {
.open = idedisk_open,
.release = idedisk_release,
.ioctl = idedisk_ioctl,
+ .getgeo = idedisk_getgeo,
.media_changed = idedisk_media_changed,
.revalidate_disk= idedisk_revalidate_disk
};
MODULE_DESCRIPTION("ATA DISK Driver");
-static int ide_disk_probe(struct device *dev)
+static int ide_disk_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp;
struct gendisk *g;
@@ -1271,6 +1246,7 @@ static int __init idedisk_init(void)
return driver_register(&idedisk_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-disk*");
module_init(idedisk_init);
module_exit(idedisk_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 9e293c8063dc..1f8db9ac05d1 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
idefloppy_add_settings(drive);
}
-static int ide_floppy_remove(struct device *dev)
+static void ide_floppy_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy = drive->driver_data;
struct gendisk *g = floppy->disk;
@@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev)
del_gendisk(g);
ide_floppy_put(floppy);
-
- return 0;
}
static void ide_floppy_release(struct kref *kref)
@@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int ide_floppy_probe(struct device *);
+static int ide_floppy_probe(ide_drive_t *);
static ide_driver_t idefloppy_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-floppy",
.bus = &ide_bus_type,
- .probe = ide_floppy_probe,
- .remove = ide_floppy_remove,
},
+ .probe = ide_floppy_probe,
+ .remove = ide_floppy_remove,
.version = IDEFLOPPY_VERSION,
.media = ide_floppy,
.supports_dsc_overlap = 0,
@@ -2031,6 +2028,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
return 0;
}
+static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ ide_drive_t *drive = floppy->drive;
+
+ geo->heads = drive->bios_head;
+ geo->sectors = drive->bios_sect;
+ geo->cylinders = (u16)drive->bios_cyl; /* truncate */
+ return 0;
+}
+
static int idefloppy_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -2120,13 +2128,13 @@ static struct block_device_operations idefloppy_ops = {
.open = idefloppy_open,
.release = idefloppy_release,
.ioctl = idefloppy_ioctl,
+ .getgeo = idefloppy_getgeo,
.media_changed = idefloppy_media_changed,
.revalidate_disk= idefloppy_revalidate_disk
};
-static int ide_floppy_probe(struct device *dev)
+static int ide_floppy_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy;
struct gendisk *g;
@@ -2197,6 +2205,7 @@ static int __init idefloppy_init(void)
return driver_register(&idefloppy_driver.gen_driver);
}
+MODULE_ALIAS("ide:*m-floppy*");
module_init(idefloppy_init);
module_exit(idefloppy_exit);
MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecfafcdafea4..8d50df4526a4 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -83,15 +83,12 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
if (!end_that_request_first(rq, uptodate, nr_sectors)) {
add_disk_randomness(rq->rq_disk);
-
- if (blk_rq_tagged(rq))
- blk_queue_end_tag(drive->queue, rq);
-
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
+ end_that_request_last(rq, uptodate);
ret = 0;
}
+
return ret;
}
EXPORT_SYMBOL(__ide_end_request);
@@ -113,16 +110,17 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
unsigned long flags;
int ret = 1;
+ /*
+ * room for locking improvements here, the calls below don't
+ * need the queue lock held at all
+ */
spin_lock_irqsave(&ide_lock, flags);
rq = HWGROUP(drive)->rq;
if (!nr_sectors)
nr_sectors = rq->hard_cur_sectors;
- if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors))
- ret = rq->nr_sectors != 0;
- else
- ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+ ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
spin_unlock_irqrestore(&ide_lock, flags);
return ret;
@@ -247,7 +245,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
}
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- end_that_request_last(rq);
+ end_that_request_last(rq, 1);
spin_unlock_irqrestore(&ide_lock, flags);
}
@@ -379,7 +377,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
rq->errors = err;
- end_that_request_last(rq);
+ end_that_request_last(rq, !rq->errors);
spin_unlock_irqrestore(&ide_lock, flags);
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 02167a5b751d..e7425546b4b1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -655,7 +655,7 @@ static void hwif_release_dev (struct device *dev)
{
ide_hwif_t *hwif = container_of(dev, ide_hwif_t, gendev);
- up(&hwif->gendev_rel_sem);
+ complete(&hwif->gendev_rel_comp);
}
static void hwif_register (ide_hwif_t *hwif)
@@ -1325,7 +1325,7 @@ static void drive_release_dev (struct device *dev)
drive->queue = NULL;
spin_unlock_irq(&ide_lock);
- up(&drive->gendev_rel_sem);
+ complete(&drive->gendev_rel_comp);
}
/*
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 7d7944ed4158..0101d0def7c5 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
idetape_add_settings(drive);
}
-static int ide_tape_remove(struct device *dev)
+static void ide_tape_remove(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape = drive->driver_data;
ide_unregister_subdriver(drive, tape->driver);
@@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev)
ide_unregister_region(tape->disk);
ide_tape_put(tape);
-
- return 0;
}
static void ide_tape_release(struct kref *kref)
@@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = {
#endif
-static int ide_tape_probe(struct device *);
+static int ide_tape_probe(ide_drive_t *);
static ide_driver_t idetape_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-tape",
.bus = &ide_bus_type,
- .probe = ide_tape_probe,
- .remove = ide_tape_remove,
},
+ .probe = ide_tape_probe,
+ .remove = ide_tape_remove,
.version = IDETAPE_VERSION,
.media = ide_tape,
.supports_dsc_overlap = 1,
@@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = {
.ioctl = idetape_ioctl,
};
-static int ide_tape_probe(struct device *dev)
+static int ide_tape_probe(ide_drive_t *drive)
{
- ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape;
struct gendisk *g;
int minor;
@@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev)
idetape_setup(drive, tape, minor);
class_device_create(idetape_sysfs_class, NULL,
- MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name);
+ MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
class_device_create(idetape_sysfs_class, NULL,
- MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name);
+ MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
S_IFCHR | S_IRUGO | S_IWUGO,
@@ -4947,6 +4943,7 @@ out:
return error;
}
+MODULE_ALIAS("ide:*m-tape*");
module_init(idetape_init);
module_exit(idetape_exit);
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 62ebefd6394a..9834dce4e20f 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -308,7 +308,7 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
ide_pio_sector(drive, write);
}
-static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
unsigned int write)
{
if (rq->bio) /* fs request */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8af179b531c3..afeb02bbb722 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -222,7 +222,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
hwif->mwdma_mask = 0x80; /* disable all mwdma */
hwif->swdma_mask = 0x80; /* disable all swdma */
- sema_init(&hwif->gendev_rel_sem, 0);
+ init_completion(&hwif->gendev_rel_comp);
default_hwif_iops(hwif);
default_hwif_transport(hwif);
@@ -245,7 +245,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
drive->is_flash = 0;
drive->vdma = 0;
INIT_LIST_HEAD(&drive->list);
- sema_init(&drive->gendev_rel_sem, 0);
+ init_completion(&drive->gendev_rel_comp);
}
}
@@ -602,7 +602,7 @@ void ide_unregister(unsigned int index)
}
spin_unlock_irq(&ide_lock);
device_unregister(&drive->gendev);
- down(&drive->gendev_rel_sem);
+ wait_for_completion(&drive->gendev_rel_comp);
spin_lock_irq(&ide_lock);
}
hwif->present = 0;
@@ -662,7 +662,7 @@ void ide_unregister(unsigned int index)
/* More messed up locking ... */
spin_unlock_irq(&ide_lock);
device_unregister(&hwif->gendev);
- down(&hwif->gendev_rel_sem);
+ wait_for_completion(&hwif->gendev_rel_comp);
/*
* Remove us from the kernel's knowledge
@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
up(&ide_setting_sem);
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry geom;
- if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
- geom.heads = drive->bios_head;
- geom.sectors = drive->bios_sect;
- geom.cylinders = (u16)drive->bios_cyl; /* truncate */
- geom.start = get_start_sect(bdev);
- if (copy_to_user(p, &geom, sizeof(struct hd_geometry)))
- return -EFAULT;
- return 0;
- }
-
case HDIO_OBSOLETE_IDENTITY:
case HDIO_GET_IDENTITY:
if (bdev != bdev->bd_contains)
@@ -1904,9 +1891,100 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}
+static char *media_string(ide_drive_t *drive)
+{
+ switch (drive->media) {
+ case ide_disk:
+ return "disk";
+ case ide_cdrom:
+ return "cdrom";
+ case ide_tape:
+ return "tape";
+ case ide_floppy:
+ return "floppy";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", media_string(drive));
+}
+
+static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->name);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "ide:m-%s\n", media_string(drive));
+}
+
+static struct device_attribute ide_dev_attrs[] = {
+ __ATTR_RO(media),
+ __ATTR_RO(drivename),
+ __ATTR_RO(modalias),
+ __ATTR_NULL
+};
+
+static int ide_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ int i = 0;
+ int length = 0;
+
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MEDIA=%s", media_string(drive));
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "DRIVENAME=%s", drive->name);
+ add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+ "MODALIAS=ide:m-%s", media_string(drive));
+ envp[i] = NULL;
+ return 0;
+}
+
+static int generic_ide_probe(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ return drv->probe ? drv->probe(drive) : -ENODEV;
+}
+
+static int generic_ide_remove(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (drv->remove)
+ drv->remove(drive);
+
+ return 0;
+}
+
+static void generic_ide_shutdown(struct device *dev)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (dev->driver && drv->shutdown)
+ drv->shutdown(drive);
+}
+
struct bus_type ide_bus_type = {
.name = "ide",
.match = ide_bus_match,
+ .uevent = ide_uevent,
+ .probe = generic_ide_probe,
+ .remove = generic_ide_remove,
+ .shutdown = generic_ide_shutdown,
+ .dev_attrs = ide_dev_attrs,
.suspend = generic_ide_suspend,
.resume = generic_ide_resume,
};
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 242029c9c0ca..6439dec66881 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q)
enable_irq(HD_IRQ);
}
-static int hd_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
+static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data;
- struct hd_geometry __user *loc = (struct hd_geometry __user *) arg;
- struct hd_geometry g;
-
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
- if (!loc)
- return -EINVAL;
- g.heads = disk->head;
- g.sectors = disk->sect;
- g.cylinders = disk->cyl;
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
+ struct hd_i_struct *disk = bdev->bd_disk->private_data;
+
+ geo->heads = disk->head;
+ geo->sectors = disk->sect;
+ geo->cylinders = disk->cyl;
+ return 0;
}
/*
@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
static struct block_device_operations hd_fops = {
- .ioctl = hd_ioctl,
+ .getgeo = hd_getgeo,
};
/*
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index ef79805218e4..4c2af9020905 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -88,15 +88,12 @@ typedef struct ide_info_t {
} ide_info_t;
static void ide_release(dev_link_t *);
-static int ide_event(event_t event, int priority,
- event_callback_args_t *args);
+static void ide_config(dev_link_t *);
+
+static void ide_detach(struct pcmcia_device *p_dev);
-static dev_info_t dev_info = "ide-cs";
-static dev_link_t *ide_attach(void);
-static void ide_detach(dev_link_t *);
-static dev_link_t *dev_list = NULL;
/*======================================================================
@@ -106,18 +103,17 @@ static dev_link_t *dev_list = NULL;
======================================================================*/
-static dev_link_t *ide_attach(void)
+static int ide_attach(struct pcmcia_device *p_dev)
{
ide_info_t *info;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
-
+
DEBUG(0, "ide_attach()\n");
/* Create new ide device */
info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return NULL;
+ if (!info)
+ return -ENOMEM;
link = &info->link; link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -128,21 +124,14 @@ static dev_link_t *ide_attach(void)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
-
- /* Register with Card Services */
- 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);
- ide_detach(link);
- return NULL;
- }
-
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ ide_config(link);
+
+ return 0;
} /* ide_attach */
/*======================================================================
@@ -154,32 +143,16 @@ static dev_link_t *ide_attach(void)
======================================================================*/
-static void ide_detach(dev_link_t *link)
+static void ide_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
- int ret;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "ide_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
ide_release(link);
-
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink, free device structure */
- *linkp = link->next;
+
kfree(link->priv);
-
} /* ide_detach */
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
@@ -406,6 +379,28 @@ void ide_release(dev_link_t *link)
} /* ide_release */
+static int ide_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int ide_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ return 0;
+}
+
/*======================================================================
The card status event handler. Mostly, this schedules other
@@ -415,48 +410,15 @@ void ide_release(dev_link_t *link)
======================================================================*/
-int ide_event(event_t event, int priority,
- event_callback_args_t *args)
-{
- dev_link_t *link = args->client_data;
-
- DEBUG(1, "ide_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- ide_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ide_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
- return 0;
-} /* ide_event */
-
static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4),
+ PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
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(0x0319, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */
PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
@@ -471,6 +433,8 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
+ PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
+ PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
@@ -494,10 +458,11 @@ static struct pcmcia_driver ide_cs_driver = {
.drv = {
.name = "ide-cs",
},
- .attach = ide_attach,
- .event = ide_event,
- .detach = ide_detach,
+ .probe = ide_attach,
+ .remove = ide_detach,
.id_table = ide_ids,
+ .suspend = ide_suspend,
+ .resume = ide_resume,
};
static int __init init_ide_cs(void)
@@ -508,7 +473,6 @@ static int __init init_ide_cs(void)
static void __exit exit_ide_cs(void)
{
pcmcia_unregister_driver(&ide_cs_driver);
- BUG_ON(dev_list != NULL);
}
late_initcall(init_ide_cs);
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 211641a54398..fe06ebb0e5bf 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -39,7 +39,7 @@
#define PDC202_DEBUG_CABLE 0
-const static char *pdc_quirk_drives[] = {
+static const char *pdc_quirk_drives[] = {
"QUANTUM FIREBALLlct08 08",
"QUANTUM FIREBALLP KA6.4",
"QUANTUM FIREBALLP KA9.1",
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index ff2e217a8c84..0d3073f4eab4 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -69,7 +69,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
static u8 svwks_ratemask (ide_drive_t *drive)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
- u8 mode;
+ u8 mode = 0;
if (!svwks_revision)
pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 86fb1e0286d3..c85b87cb59d1 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -439,7 +439,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
hwif->speedproc = &via_set_drive;
-#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_PPC32)
+#if defined(CONFIG_PPC_CHRP) && defined(CONFIG_PPC32)
if(_machine == _MACH_chrp && _chrp_type == _CHRP_Pegasos) {
hwif->irq = hwif->channel ? 15 : 14;
}
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 16b28357885b..5013b1285e22 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1271,7 +1271,7 @@ static int
pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
{
struct device_node *np = pmif->node;
- int *bidp, i;
+ int *bidp;
pmif->cable_80 = 0;
pmif->broken_dma = pmif->broken_dma_warn = 0;
@@ -1430,7 +1430,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
pmif = &pmac_ide[i];
hwif = &ide_hwifs[i];
- if (mdev->ofdev.node->n_addrs == 0) {
+ if (macio_resource_count(mdev) == 0) {
printk(KERN_WARNING "ide%d: no address for %s\n",
i, mdev->ofdev.node->full_name);
return -ENXIO;
@@ -1686,7 +1686,7 @@ pmac_ide_probe(void)
#else
macio_register_driver(&pmac_ide_macio_driver);
pci_register_driver(&pmac_ide_pci_driver);
-#endif
+#endif
}
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
diff --git a/drivers/ieee1394/.gitignore b/drivers/ieee1394/.gitignore
new file mode 100644
index 000000000000..33da10a25323
--- /dev/null
+++ b/drivers/ieee1394/.gitignore
@@ -0,0 +1 @@
+oui.c
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 25103a0ef9b3..39142e2f804b 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -169,27 +169,4 @@ config IEEE1394_RAWIO
To compile this driver as a module, say M here: the
module will be called raw1394.
-config IEEE1394_CMP
- tristate "IEC61883-1 Plug support"
- depends on IEEE1394
- help
- This option enables the Connection Management Procedures
- (IEC61883-1) driver, which implements input and output plugs.
-
- To compile this driver as a module, say M here: the
- module will be called cmp.
-
-config IEEE1394_AMDTP
- tristate "IEC61883-6 (Audio transmission) support"
- depends on IEEE1394 && IEEE1394_OHCI1394 && IEEE1394_CMP
- help
- This option enables the Audio & Music Data Transmission Protocol
- (IEC61883-6) driver, which implements audio transmission over
- IEEE1394.
-
- The userspace interface is documented in amdtp.h.
-
- To compile this driver as a module, say M here: the
- module will be called amdtp.
-
endmenu
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
index e8b4d48d376e..6f53611fe255 100644
--- a/drivers/ieee1394/Makefile
+++ b/drivers/ieee1394/Makefile
@@ -14,8 +14,6 @@ obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
-obj-$(CONFIG_IEEE1394_AMDTP) += amdtp.o
-obj-$(CONFIG_IEEE1394_CMP) += cmp.o
quiet_cmd_oui2c = OUI2C $@
cmd_oui2c = $(CONFIG_SHELL) $(srctree)/$(src)/oui2c.sh < $< > $@
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
deleted file mode 100644
index 75897509c401..000000000000
--- a/drivers/ieee1394/amdtp.c
+++ /dev/null
@@ -1,1298 +0,0 @@
-/* -*- c-basic-offset: 8 -*-
- *
- * amdtp.c - Audio and Music Data Transmission Protocol Driver
- * Copyright (C) 2001 Kristian Høgsberg
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- */
-
-/* OVERVIEW
- * --------
- *
- * The AMDTP driver is designed to expose the IEEE1394 bus as a
- * regular OSS soundcard, i.e. you can link /dev/dsp to /dev/amdtp and
- * then your favourite MP3 player, game or whatever sound program will
- * output to an IEEE1394 isochronous channel. The signal destination
- * could be a set of IEEE1394 loudspeakers (if and when such things
- * become available) or an amplifier with IEEE1394 input (like the
- * Sony STR-LSA1). The driver only handles the actual streaming, some
- * connection management is also required for this to actually work.
- * That is outside the scope of this driver, and furthermore it is not
- * really standardized yet.
- *
- * The Audio and Music Data Tranmission Protocol is available at
- *
- * http://www.1394ta.org/Download/Technology/Specifications/2001/AM20Final-jf2.pdf
- *
- *
- * TODO
- * ----
- *
- * - We should be able to change input sample format between LE/BE, as
- * we already shift the bytes around when we construct the iso
- * packets.
- *
- * - Fix DMA stop after bus reset!
- *
- * - Clean up iso context handling in ohci1394.
- *
- *
- * MAYBE TODO
- * ----------
- *
- * - Receive data for local playback or recording. Playback requires
- * soft syncing with the sound card.
- *
- * - Signal processing, i.e. receive packets, do some processing, and
- * transmit them again using the same packet structure and timestamps
- * offset by processing time.
- *
- * - Maybe make an ALSA interface, that is, create a file_ops
- * implementation that recognizes ALSA ioctls and uses defaults for
- * things that can't be controlled through ALSA (iso channel).
- *
- * Changes:
- *
- * - Audit copy_from_user in amdtp_write.
- * Daniele Bellucci <bellucda@tiscali.it>
- *
- */
-
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/poll.h>
-#include <linux/ioctl32.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-
-#include "hosts.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ohci1394.h"
-
-#include "amdtp.h"
-#include "cmp.h"
-
-#define FMT_AMDTP 0x10
-#define FDF_AM824 0x00
-#define FDF_SFC_32KHZ 0x00
-#define FDF_SFC_44K1HZ 0x01
-#define FDF_SFC_48KHZ 0x02
-#define FDF_SFC_88K2HZ 0x03
-#define FDF_SFC_96KHZ 0x04
-#define FDF_SFC_176K4HZ 0x05
-#define FDF_SFC_192KHZ 0x06
-
-struct descriptor_block {
- struct output_more_immediate {
- u32 control;
- u32 pad0;
- u32 skip;
- u32 pad1;
- u32 header[4];
- } header_desc;
-
- struct output_last {
- u32 control;
- u32 data_address;
- u32 branch;
- u32 status;
- } payload_desc;
-};
-
-struct packet {
- struct descriptor_block *db;
- dma_addr_t db_bus;
- struct iso_packet *payload;
- dma_addr_t payload_bus;
-};
-
-#include <asm/byteorder.h>
-
-#if defined __BIG_ENDIAN_BITFIELD
-
-struct iso_packet {
- /* First quadlet */
- unsigned int dbs : 8;
- unsigned int eoh0 : 2;
- unsigned int sid : 6;
-
- unsigned int dbc : 8;
- unsigned int fn : 2;
- unsigned int qpc : 3;
- unsigned int sph : 1;
- unsigned int reserved : 2;
-
- /* Second quadlet */
- unsigned int fdf : 8;
- unsigned int eoh1 : 2;
- unsigned int fmt : 6;
-
- unsigned int syt : 16;
-
- quadlet_t data[0];
-};
-
-#elif defined __LITTLE_ENDIAN_BITFIELD
-
-struct iso_packet {
- /* First quadlet */
- unsigned int sid : 6;
- unsigned int eoh0 : 2;
- unsigned int dbs : 8;
-
- unsigned int reserved : 2;
- unsigned int sph : 1;
- unsigned int qpc : 3;
- unsigned int fn : 2;
- unsigned int dbc : 8;
-
- /* Second quadlet */
- unsigned int fmt : 6;
- unsigned int eoh1 : 2;
- unsigned int fdf : 8;
-
- unsigned int syt : 16;
-
- quadlet_t data[0];
-};
-
-#else
-
-#error Unknown bitfield type
-
-#endif
-
-struct fraction {
- int integer;
- int numerator;
- int denominator;
-};
-
-#define PACKET_LIST_SIZE 256
-#define MAX_PACKET_LISTS 4
-
-struct packet_list {
- struct list_head link;
- int last_cycle_count;
- struct packet packets[PACKET_LIST_SIZE];
-};
-
-#define BUFFER_SIZE 128
-
-/* This implements a circular buffer for incoming samples. */
-
-struct buffer {
- size_t head, tail, length, size;
- unsigned char data[0];
-};
-
-struct stream {
- int iso_channel;
- int format;
- int rate;
- int dimension;
- int fdf;
- int mode;
- int sample_format;
- struct cmp_pcr *opcr;
-
- /* Input samples are copied here. */
- struct buffer *input;
-
- /* ISO Packer state */
- unsigned char dbc;
- struct packet_list *current_packet_list;
- int current_packet;
- struct fraction ready_samples, samples_per_cycle;
-
- /* We use these to generate control bits when we are packing
- * iec958 data.
- */
- int iec958_frame_count;
- int iec958_rate_code;
-
- /* The cycle_count and cycle_offset fields are used for the
- * synchronization timestamps (syt) in the cip header. They
- * are incremented by at least a cycle every time we put a
- * time stamp in a packet. As we don't time stamp all
- * packages, cycle_count isn't updated in every cycle, and
- * sometimes it's incremented by 2. Thus, we have
- * cycle_count2, which is simply incremented by one with each
- * packet, so we can compare it to the transmission time
- * written back in the dma programs.
- */
- atomic_t cycle_count, cycle_count2;
- struct fraction cycle_offset, ticks_per_syt_offset;
- int syt_interval;
- int stale_count;
-
- /* Theses fields control the sample output to the DMA engine.
- * The dma_packet_lists list holds packet lists currently
- * queued for dma; the head of the list is currently being
- * processed. The last program in a packet list generates an
- * interrupt, which removes the head from dma_packet_lists and
- * puts it back on the free list.
- */
- struct list_head dma_packet_lists;
- struct list_head free_packet_lists;
- wait_queue_head_t packet_list_wait;
- spinlock_t packet_list_lock;
- struct ohci1394_iso_tasklet iso_tasklet;
- struct pci_pool *descriptor_pool, *packet_pool;
-
- /* Streams at a host controller are chained through this field. */
- struct list_head link;
- struct amdtp_host *host;
-};
-
-struct amdtp_host {
- struct hpsb_host *host;
- struct ti_ohci *ohci;
- struct list_head stream_list;
- spinlock_t stream_list_lock;
-};
-
-static struct hpsb_highlevel amdtp_highlevel;
-
-
-/* FIXME: This doesn't belong here... */
-
-#define OHCI1394_CONTEXT_CYCLE_MATCH 0x80000000
-#define OHCI1394_CONTEXT_RUN 0x00008000
-#define OHCI1394_CONTEXT_WAKE 0x00001000
-#define OHCI1394_CONTEXT_DEAD 0x00000800
-#define OHCI1394_CONTEXT_ACTIVE 0x00000400
-
-static void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
- dma_addr_t first_cmd, int z, int cycle_match)
-{
- reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx);
- reg_write(ohci, OHCI1394_IsoXmitCommandPtr + ctx * 16, first_cmd | z);
- reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16, ~0);
- wmb();
- reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
- OHCI1394_CONTEXT_CYCLE_MATCH | (cycle_match << 16) |
- OHCI1394_CONTEXT_RUN);
-}
-
-static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
-{
- reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
- OHCI1394_CONTEXT_WAKE);
-}
-
-static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
-{
- u32 control;
- int wait;
-
- reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << ctx);
- reg_write(ohci, OHCI1394_IsoXmitContextControlClear + ctx * 16,
- OHCI1394_CONTEXT_RUN);
- wmb();
-
- if (synchronous) {
- for (wait = 0; wait < 5; wait++) {
- control = reg_read(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16);
- if ((control & OHCI1394_CONTEXT_ACTIVE) == 0)
- break;
-
- schedule_timeout_interruptible(1);
- }
- }
-}
-
-/* Note: we can test if free_packet_lists is empty without aquiring
- * the packet_list_lock. The interrupt handler only adds to the free
- * list, there is no race condition between testing the list non-empty
- * and acquiring the lock.
- */
-
-static struct packet_list *stream_get_free_packet_list(struct stream *s)
-{
- struct packet_list *pl;
- unsigned long flags;
-
- if (list_empty(&s->free_packet_lists))
- return NULL;
-
- spin_lock_irqsave(&s->packet_list_lock, flags);
- pl = list_entry(s->free_packet_lists.next, struct packet_list, link);
- list_del(&pl->link);
- spin_unlock_irqrestore(&s->packet_list_lock, flags);
-
- return pl;
-}
-
-static void stream_start_dma(struct stream *s, struct packet_list *pl)
-{
- u32 syt_cycle, cycle_count, start_cycle;
-
- cycle_count = reg_read(s->host->ohci,
- OHCI1394_IsochronousCycleTimer) >> 12;
- syt_cycle = (pl->last_cycle_count - PACKET_LIST_SIZE + 1) & 0x0f;
-
- /* We program the DMA controller to start transmission at
- * least 17 cycles from now - this happens when the lower four
- * bits of cycle_count is 0x0f and syt_cycle is 0, in this
- * case the start cycle is cycle_count - 15 + 32. */
- start_cycle = (cycle_count & ~0x0f) + 32 + syt_cycle;
- if ((start_cycle & 0x1fff) >= 8000)
- start_cycle = start_cycle - 8000 + 0x2000;
-
- ohci1394_start_it_ctx(s->host->ohci, s->iso_tasklet.context,
- pl->packets[0].db_bus, 3,
- start_cycle & 0x7fff);
-}
-
-static void stream_put_dma_packet_list(struct stream *s,
- struct packet_list *pl)
-{
- unsigned long flags;
- struct packet_list *prev;
-
- /* Remember the cycle_count used for timestamping the last packet. */
- pl->last_cycle_count = atomic_read(&s->cycle_count2) - 1;
- pl->packets[PACKET_LIST_SIZE - 1].db->payload_desc.branch = 0;
-
- spin_lock_irqsave(&s->packet_list_lock, flags);
- list_add_tail(&pl->link, &s->dma_packet_lists);
- spin_unlock_irqrestore(&s->packet_list_lock, flags);
-
- prev = list_entry(pl->link.prev, struct packet_list, link);
- if (pl->link.prev != &s->dma_packet_lists) {
- struct packet *last = &prev->packets[PACKET_LIST_SIZE - 1];
- last->db->payload_desc.branch = pl->packets[0].db_bus | 3;
- last->db->header_desc.skip = pl->packets[0].db_bus | 3;
- ohci1394_wake_it_ctx(s->host->ohci, s->iso_tasklet.context);
- }
- else
- stream_start_dma(s, pl);
-}
-
-static void stream_shift_packet_lists(unsigned long l)
-{
- struct stream *s = (struct stream *) l;
- struct packet_list *pl;
- struct packet *last;
- int diff;
-
- if (list_empty(&s->dma_packet_lists)) {
- HPSB_ERR("empty dma_packet_lists in %s", __FUNCTION__);
- return;
- }
-
- /* Now that we know the list is non-empty, we can get the head
- * of the list without locking, because the process context
- * only adds to the tail.
- */
- pl = list_entry(s->dma_packet_lists.next, struct packet_list, link);
- last = &pl->packets[PACKET_LIST_SIZE - 1];
-
- /* This is weird... if we stop dma processing in the middle of
- * a packet list, the dma context immediately generates an
- * interrupt if we enable it again later. This only happens
- * when amdtp_release is interrupted while waiting for dma to
- * complete, though. Anyway, we detect this by seeing that
- * the status of the dma descriptor that we expected an
- * interrupt from is still 0.
- */
- if (last->db->payload_desc.status == 0) {
- HPSB_INFO("weird interrupt...");
- return;
- }
-
- /* If the last descriptor block does not specify a branch
- * address, we have a sample underflow.
- */
- if (last->db->payload_desc.branch == 0)
- HPSB_INFO("FIXME: sample underflow...");
-
- /* Here we check when (which cycle) the last packet was sent
- * and compare it to what the iso packer was using at the
- * time. If there is a mismatch, we adjust the cycle count in
- * the iso packer. However, there are still up to
- * MAX_PACKET_LISTS packet lists queued with bad time stamps,
- * so we disable time stamp monitoring for the next
- * MAX_PACKET_LISTS packet lists.
- */
- diff = (last->db->payload_desc.status - pl->last_cycle_count) & 0xf;
- if (diff > 0 && s->stale_count == 0) {
- atomic_add(diff, &s->cycle_count);
- atomic_add(diff, &s->cycle_count2);
- s->stale_count = MAX_PACKET_LISTS;
- }
-
- if (s->stale_count > 0)
- s->stale_count--;
-
- /* Finally, we move the packet list that was just processed
- * back to the free list, and notify any waiters.
- */
- spin_lock(&s->packet_list_lock);
- list_del(&pl->link);
- list_add_tail(&pl->link, &s->free_packet_lists);
- spin_unlock(&s->packet_list_lock);
-
- wake_up_interruptible(&s->packet_list_wait);
-}
-
-static struct packet *stream_current_packet(struct stream *s)
-{
- if (s->current_packet_list == NULL &&
- (s->current_packet_list = stream_get_free_packet_list(s)) == NULL)
- return NULL;
-
- return &s->current_packet_list->packets[s->current_packet];
-}
-
-static void stream_queue_packet(struct stream *s)
-{
- s->current_packet++;
- if (s->current_packet == PACKET_LIST_SIZE) {
- stream_put_dma_packet_list(s, s->current_packet_list);
- s->current_packet_list = NULL;
- s->current_packet = 0;
- }
-}
-
-/* Integer fractional math. When we transmit a 44k1Hz signal we must
- * send 5 41/80 samples per isochronous cycle, as these occur 8000
- * times a second. Of course, we must send an integral number of
- * samples in a packet, so we use the integer math to alternate
- * between sending 5 and 6 samples per packet.
- */
-
-static void fraction_init(struct fraction *f, int numerator, int denominator)
-{
- f->integer = numerator / denominator;
- f->numerator = numerator % denominator;
- f->denominator = denominator;
-}
-
-static __inline__ void fraction_add(struct fraction *dst,
- struct fraction *src1,
- struct fraction *src2)
-{
- /* assert: src1->denominator == src2->denominator */
-
- int sum, denom;
-
- /* We use these two local variables to allow gcc to optimize
- * the division and the modulo into only one division. */
-
- sum = src1->numerator + src2->numerator;
- denom = src1->denominator;
- dst->integer = src1->integer + src2->integer + sum / denom;
- dst->numerator = sum % denom;
- dst->denominator = denom;
-}
-
-static __inline__ void fraction_sub_int(struct fraction *dst,
- struct fraction *src, int integer)
-{
- dst->integer = src->integer - integer;
- dst->numerator = src->numerator;
- dst->denominator = src->denominator;
-}
-
-static __inline__ int fraction_floor(struct fraction *frac)
-{
- return frac->integer;
-}
-
-static __inline__ int fraction_ceil(struct fraction *frac)
-{
- return frac->integer + (frac->numerator > 0 ? 1 : 0);
-}
-
-static void packet_initialize(struct packet *p, struct packet *next)
-{
- /* Here we initialize the dma descriptor block for
- * transferring one iso packet. We use two descriptors per
- * packet: an OUTPUT_MORE_IMMMEDIATE descriptor for the
- * IEEE1394 iso packet header and an OUTPUT_LAST descriptor
- * for the payload.
- */
-
- p->db->header_desc.control =
- DMA_CTL_OUTPUT_MORE | DMA_CTL_IMMEDIATE | 8;
-
- if (next) {
- p->db->payload_desc.control =
- DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH;
- p->db->payload_desc.branch = next->db_bus | 3;
- p->db->header_desc.skip = next->db_bus | 3;
- }
- else {
- p->db->payload_desc.control =
- DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH |
- DMA_CTL_UPDATE | DMA_CTL_IRQ;
- p->db->payload_desc.branch = 0;
- p->db->header_desc.skip = 0;
- }
- p->db->payload_desc.data_address = p->payload_bus;
- p->db->payload_desc.status = 0;
-}
-
-static struct packet_list *packet_list_alloc(struct stream *s)
-{
- int i;
- struct packet_list *pl;
- struct packet *next;
-
- pl = kmalloc(sizeof *pl, SLAB_KERNEL);
- if (pl == NULL)
- return NULL;
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- struct packet *p = &pl->packets[i];
- p->db = pci_pool_alloc(s->descriptor_pool, SLAB_KERNEL,
- &p->db_bus);
- p->payload = pci_pool_alloc(s->packet_pool, SLAB_KERNEL,
- &p->payload_bus);
- }
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- if (i < PACKET_LIST_SIZE - 1)
- next = &pl->packets[i + 1];
- else
- next = NULL;
- packet_initialize(&pl->packets[i], next);
- }
-
- return pl;
-}
-
-static void packet_list_free(struct packet_list *pl, struct stream *s)
-{
- int i;
-
- for (i = 0; i < PACKET_LIST_SIZE; i++) {
- struct packet *p = &pl->packets[i];
- pci_pool_free(s->descriptor_pool, p->db, p->db_bus);
- pci_pool_free(s->packet_pool, p->payload, p->payload_bus);
- }
- kfree(pl);
-}
-
-static struct buffer *buffer_alloc(int size)
-{
- struct buffer *b;
-
- b = kmalloc(sizeof *b + size, SLAB_KERNEL);
- if (b == NULL)
- return NULL;
- b->head = 0;
- b->tail = 0;
- b->length = 0;
- b->size = size;
-
- return b;
-}
-
-static unsigned char *buffer_get_bytes(struct buffer *buffer, int size)
-{
- unsigned char *p;
-
- if (buffer->head + size > buffer->size)
- BUG();
-
- p = &buffer->data[buffer->head];
- buffer->head += size;
- if (buffer->head == buffer->size)
- buffer->head = 0;
- buffer->length -= size;
-
- return p;
-}
-
-static unsigned char *buffer_put_bytes(struct buffer *buffer,
- size_t max, size_t *actual)
-{
- size_t length;
- unsigned char *p;
-
- p = &buffer->data[buffer->tail];
- length = min(buffer->size - buffer->length, max);
- if (buffer->tail + length < buffer->size) {
- *actual = length;
- buffer->tail += length;
- }
- else {
- *actual = buffer->size - buffer->tail;
- buffer->tail = 0;
- }
-
- buffer->length += *actual;
- return p;
-}
-
-static u32 get_iec958_header_bits(struct stream *s, int sub_frame, u32 sample)
-{
- int csi, parity, shift;
- int block_start;
- u32 bits;
-
- switch (s->iec958_frame_count) {
- case 1:
- csi = s->format == AMDTP_FORMAT_IEC958_AC3;
- break;
- case 2:
- case 9:
- csi = 1;
- break;
- case 24 ... 27:
- csi = (s->iec958_rate_code >> (27 - s->iec958_frame_count)) & 0x01;
- break;
- default:
- csi = 0;
- break;
- }
-
- block_start = (s->iec958_frame_count == 0 && sub_frame == 0);
-
- /* The parity bit is the xor of the sample bits and the
- * channel status info bit. */
- for (shift = 16, parity = sample ^ csi; shift > 0; shift >>= 1)
- parity ^= (parity >> shift);
-
- bits = (block_start << 5) | /* Block start bit */
- ((sub_frame == 0) << 4) | /* Subframe bit */
- ((parity & 1) << 3) | /* Parity bit */
- (csi << 2); /* Channel status info bit */
-
- return bits;
-}
-
-static u32 get_header_bits(struct stream *s, int sub_frame, u32 sample)
-{
- switch (s->format) {
- case AMDTP_FORMAT_IEC958_PCM:
- case AMDTP_FORMAT_IEC958_AC3:
- return get_iec958_header_bits(s, sub_frame, sample);
-
- case AMDTP_FORMAT_RAW:
- return 0x40;
-
- default:
- return 0;
- }
-}
-
-static void fill_payload_le16(struct stream *s, quadlet_t *data, int nevents)
-{
- quadlet_t *event, sample, bits;
- unsigned char *p;
- int i, j;
-
- for (i = 0, event = data; i < nevents; i++) {
-
- for (j = 0; j < s->dimension; j++) {
- p = buffer_get_bytes(s->input, 2);
- sample = (p[1] << 16) | (p[0] << 8);
- bits = get_header_bits(s, j, sample);
- event[j] = cpu_to_be32((bits << 24) | sample);
- }
-
- event += s->dimension;
- if (++s->iec958_frame_count == 192)
- s->iec958_frame_count = 0;
- }
-}
-
-static void fill_packet(struct stream *s, struct packet *packet, int nevents)
-{
- int syt_index, syt, size;
- u32 control;
-
- size = (nevents * s->dimension + 2) * sizeof(quadlet_t);
-
- /* Update DMA descriptors */
- packet->db->payload_desc.status = 0;
- control = packet->db->payload_desc.control & 0xffff0000;
- packet->db->payload_desc.control = control | size;
-
- /* Fill IEEE1394 headers */
- packet->db->header_desc.header[0] =
- (IEEE1394_SPEED_100 << 16) | (0x01 << 14) |
- (s->iso_channel << 8) | (TCODE_ISO_DATA << 4);
- packet->db->header_desc.header[1] = size << 16;
-
- /* Calculate synchronization timestamp (syt). First we
- * determine syt_index, that is, the index in the packet of
- * the sample for which the timestamp is valid. */
- syt_index = (s->syt_interval - s->dbc) & (s->syt_interval - 1);
- if (syt_index < nevents) {
- syt = ((atomic_read(&s->cycle_count) << 12) |
- s->cycle_offset.integer) & 0xffff;
- fraction_add(&s->cycle_offset,
- &s->cycle_offset, &s->ticks_per_syt_offset);
-
- /* This next addition should be modulo 8000 (0x1f40),
- * but we only use the lower 4 bits of cycle_count, so
- * we don't need the modulo. */
- atomic_add(s->cycle_offset.integer / 3072, &s->cycle_count);
- s->cycle_offset.integer %= 3072;
- }
- else
- syt = 0xffff;
-
- atomic_inc(&s->cycle_count2);
-
- /* Fill cip header */
- packet->payload->eoh0 = 0;
- packet->payload->sid = s->host->host->node_id & 0x3f;
- packet->payload->dbs = s->dimension;
- packet->payload->fn = 0;
- packet->payload->qpc = 0;
- packet->payload->sph = 0;
- packet->payload->reserved = 0;
- packet->payload->dbc = s->dbc;
- packet->payload->eoh1 = 2;
- packet->payload->fmt = FMT_AMDTP;
- packet->payload->fdf = s->fdf;
- packet->payload->syt = cpu_to_be16(syt);
-
- switch (s->sample_format) {
- case AMDTP_INPUT_LE16:
- fill_payload_le16(s, packet->payload->data, nevents);
- break;
- }
-
- s->dbc += nevents;
-}
-
-static void stream_flush(struct stream *s)
-{
- struct packet *p;
- int nevents;
- struct fraction next;
-
- /* The AMDTP specifies two transmission modes: blocking and
- * non-blocking. In blocking mode you always transfer
- * syt_interval or zero samples, whereas in non-blocking mode
- * you send as many samples as you have available at transfer
- * time.
- *
- * The fraction samples_per_cycle specifies the number of
- * samples that become available per cycle. We add this to
- * the fraction ready_samples, which specifies the number of
- * leftover samples from the previous transmission. The sum,
- * stored in the fraction next, specifies the number of
- * samples available for transmission, and from this we
- * determine the number of samples to actually transmit.
- */
-
- while (1) {
- fraction_add(&next, &s->ready_samples, &s->samples_per_cycle);
- if (s->mode == AMDTP_MODE_BLOCKING) {
- if (fraction_floor(&next) >= s->syt_interval)
- nevents = s->syt_interval;
- else
- nevents = 0;
- }
- else
- nevents = fraction_floor(&next);
-
- p = stream_current_packet(s);
- if (s->input->length < nevents * s->dimension * 2 || p == NULL)
- break;
-
- fill_packet(s, p, nevents);
- stream_queue_packet(s);
-
- /* Now that we have successfully queued the packet for
- * transmission, we update the fraction ready_samples. */
- fraction_sub_int(&s->ready_samples, &next, nevents);
- }
-}
-
-static int stream_alloc_packet_lists(struct stream *s)
-{
- int max_nevents, max_packet_size, i;
-
- if (s->mode == AMDTP_MODE_BLOCKING)
- max_nevents = s->syt_interval;
- else
- max_nevents = fraction_ceil(&s->samples_per_cycle);
-
- max_packet_size = max_nevents * s->dimension * 4 + 8;
- s->packet_pool = pci_pool_create("packet pool", s->host->ohci->dev,
- max_packet_size, 0, 0);
-
- if (s->packet_pool == NULL)
- return -1;
-
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
- for (i = 0; i < MAX_PACKET_LISTS; i++) {
- struct packet_list *pl = packet_list_alloc(s);
- if (pl == NULL)
- break;
- list_add_tail(&pl->link, &s->free_packet_lists);
- }
-
- return i < MAX_PACKET_LISTS ? -1 : 0;
-}
-
-static void stream_free_packet_lists(struct stream *s)
-{
- struct packet_list *packet_l, *packet_l_next;
-
- if (s->current_packet_list != NULL)
- packet_list_free(s->current_packet_list, s);
- list_for_each_entry_safe(packet_l, packet_l_next, &s->dma_packet_lists, link)
- packet_list_free(packet_l, s);
- list_for_each_entry_safe(packet_l, packet_l_next, &s->free_packet_lists, link)
- packet_list_free(packet_l, s);
- if (s->packet_pool != NULL)
- pci_pool_destroy(s->packet_pool);
-
- s->current_packet_list = NULL;
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
- s->packet_pool = NULL;
-}
-
-static void plug_update(struct cmp_pcr *plug, void *data)
-{
- struct stream *s = data;
-
- HPSB_INFO("plug update: p2p_count=%d, channel=%d",
- plug->p2p_count, plug->channel);
- s->iso_channel = plug->channel;
- if (plug->p2p_count > 0) {
- struct packet_list *pl;
-
- pl = list_entry(s->dma_packet_lists.next, struct packet_list, link);
- stream_start_dma(s, pl);
- }
- else {
- ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 0);
- }
-}
-
-static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg)
-{
- const int transfer_delay = 9000;
-
- if (cfg->format <= AMDTP_FORMAT_IEC958_AC3)
- s->format = cfg->format;
- else
- return -EINVAL;
-
- switch (cfg->rate) {
- case 32000:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_32KHZ;
- s->iec958_rate_code = 0x0c;
- break;
- case 44100:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_44K1HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 48000:
- s->syt_interval = 8;
- s->fdf = FDF_SFC_48KHZ;
- s->iec958_rate_code = 0x04;
- break;
- case 88200:
- s->syt_interval = 16;
- s->fdf = FDF_SFC_88K2HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 96000:
- s->syt_interval = 16;
- s->fdf = FDF_SFC_96KHZ;
- s->iec958_rate_code = 0x00;
- break;
- case 176400:
- s->syt_interval = 32;
- s->fdf = FDF_SFC_176K4HZ;
- s->iec958_rate_code = 0x00;
- break;
- case 192000:
- s->syt_interval = 32;
- s->fdf = FDF_SFC_192KHZ;
- s->iec958_rate_code = 0x00;
- break;
-
- default:
- return -EINVAL;
- }
-
- s->rate = cfg->rate;
- fraction_init(&s->samples_per_cycle, s->rate, 8000);
- fraction_init(&s->ready_samples, 0, 8000);
-
- /* The ticks_per_syt_offset is initialized to the number of
- * ticks between syt_interval events. The number of ticks per
- * second is 24.576e6, so the number of ticks between
- * syt_interval events is 24.576e6 * syt_interval / rate.
- */
- fraction_init(&s->ticks_per_syt_offset,
- 24576000 * s->syt_interval, s->rate);
- fraction_init(&s->cycle_offset, (transfer_delay % 3072) * s->rate, s->rate);
- atomic_set(&s->cycle_count, transfer_delay / 3072);
- atomic_set(&s->cycle_count2, 0);
-
- s->mode = cfg->mode;
- s->sample_format = AMDTP_INPUT_LE16;
-
- /* When using the AM824 raw subformat we can stream signals of
- * any dimension. The IEC958 subformat, however, only
- * supports 2 channels.
- */
- if (s->format == AMDTP_FORMAT_RAW || cfg->dimension == 2)
- s->dimension = cfg->dimension;
- else
- return -EINVAL;
-
- if (s->opcr != NULL) {
- cmp_unregister_opcr(s->host->host, s->opcr);
- s->opcr = NULL;
- }
-
- switch(cmd) {
- case AMDTP_IOC_PLUG:
- s->opcr = cmp_register_opcr(s->host->host, cfg->u.plug,
- /*payload*/ 12, plug_update, s);
- if (s->opcr == NULL)
- return -EINVAL;
- s->iso_channel = s->opcr->channel;
- break;
-
- case AMDTP_IOC_CHANNEL:
- if (cfg->u.channel >= 0 && cfg->u.channel < 64)
- s->iso_channel = cfg->u.channel;
- else
- return -EINVAL;
- break;
- }
-
- /* The ioctl settings were all valid, so we realloc the packet
- * lists to make sure the packet size is big enough.
- */
- if (s->packet_pool != NULL)
- stream_free_packet_lists(s);
-
- if (stream_alloc_packet_lists(s) < 0) {
- stream_free_packet_lists(s);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static struct stream *stream_alloc(struct amdtp_host *host)
-{
- struct stream *s;
- unsigned long flags;
-
- s = kmalloc(sizeof(struct stream), SLAB_KERNEL);
- if (s == NULL)
- return NULL;
-
- memset(s, 0, sizeof(struct stream));
- s->host = host;
-
- s->input = buffer_alloc(BUFFER_SIZE);
- if (s->input == NULL) {
- kfree(s);
- return NULL;
- }
-
- s->descriptor_pool = pci_pool_create("descriptor pool", host->ohci->dev,
- sizeof(struct descriptor_block),
- 16, 0);
-
- if (s->descriptor_pool == NULL) {
- kfree(s->input);
- kfree(s);
- return NULL;
- }
-
- INIT_LIST_HEAD(&s->free_packet_lists);
- INIT_LIST_HEAD(&s->dma_packet_lists);
-
- init_waitqueue_head(&s->packet_list_wait);
- spin_lock_init(&s->packet_list_lock);
-
- ohci1394_init_iso_tasklet(&s->iso_tasklet, OHCI_ISO_TRANSMIT,
- stream_shift_packet_lists,
- (unsigned long) s);
-
- if (ohci1394_register_iso_tasklet(host->ohci, &s->iso_tasklet) < 0) {
- pci_pool_destroy(s->descriptor_pool);
- kfree(s->input);
- kfree(s);
- return NULL;
- }
-
- spin_lock_irqsave(&host->stream_list_lock, flags);
- list_add_tail(&s->link, &host->stream_list);
- spin_unlock_irqrestore(&host->stream_list_lock, flags);
-
- return s;
-}
-
-static void stream_free(struct stream *s)
-{
- unsigned long flags;
-
- /* Stop the DMA. We wait for the dma packet list to become
- * empty and let the dma controller run out of programs. This
- * seems to be more reliable than stopping it directly, since
- * that sometimes generates an it transmit interrupt if we
- * later re-enable the context.
- */
- wait_event_interruptible(s->packet_list_wait,
- list_empty(&s->dma_packet_lists));
-
- ohci1394_stop_it_ctx(s->host->ohci, s->iso_tasklet.context, 1);
- ohci1394_unregister_iso_tasklet(s->host->ohci, &s->iso_tasklet);
-
- if (s->opcr != NULL)
- cmp_unregister_opcr(s->host->host, s->opcr);
-
- spin_lock_irqsave(&s->host->stream_list_lock, flags);
- list_del(&s->link);
- spin_unlock_irqrestore(&s->host->stream_list_lock, flags);
-
- kfree(s->input);
-
- stream_free_packet_lists(s);
- pci_pool_destroy(s->descriptor_pool);
-
- kfree(s);
-}
-
-/* File operations */
-
-static ssize_t amdtp_write(struct file *file, const char __user *buffer, size_t count,
- loff_t *offset_is_ignored)
-{
- struct stream *s = file->private_data;
- unsigned char *p;
- int i;
- size_t length;
-
- if (s->packet_pool == NULL)
- return -EBADFD;
-
- /* Fill the circular buffer from the input buffer and call the
- * iso packer when the buffer is full. The iso packer may
- * leave bytes in the buffer for two reasons: either the
- * remaining bytes wasn't enough to build a new packet, or
- * there were no free packet lists. In the first case we
- * re-fill the buffer and call the iso packer again or return
- * if we used all the data from userspace. In the second
- * case, the wait_event_interruptible will block until the irq
- * handler frees a packet list.
- */
-
- for (i = 0; i < count; i += length) {
- p = buffer_put_bytes(s->input, count - i, &length);
- if (copy_from_user(p, buffer + i, length))
- return -EFAULT;
- if (s->input->length < s->input->size)
- continue;
-
- stream_flush(s);
-
- if (s->current_packet_list != NULL)
- continue;
-
- if (file->f_flags & O_NONBLOCK)
- return i + length > 0 ? i + length : -EAGAIN;
-
- if (wait_event_interruptible(s->packet_list_wait,
- !list_empty(&s->free_packet_lists)))
- return -EINTR;
- }
-
- return count;
-}
-
-static long amdtp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- struct stream *s = file->private_data;
- struct amdtp_ioctl cfg;
- int err;
- lock_kernel();
- switch(cmd)
- {
- case AMDTP_IOC_PLUG:
- case AMDTP_IOC_CHANNEL:
- if (copy_from_user(&cfg, (struct amdtp_ioctl __user *) arg, sizeof cfg))
- err = -EFAULT;
- else
- err = stream_configure(s, cmd, &cfg);
- break;
-
- default:
- err = -EINVAL;
- break;
- }
- unlock_kernel();
- return err;
-}
-
-static unsigned int amdtp_poll(struct file *file, poll_table *pt)
-{
- struct stream *s = file->private_data;
-
- poll_wait(file, &s->packet_list_wait, pt);
-
- if (!list_empty(&s->free_packet_lists))
- return POLLOUT | POLLWRNORM;
- else
- return 0;
-}
-
-static int amdtp_open(struct inode *inode, struct file *file)
-{
- struct amdtp_host *host;
- int i = ieee1394_file_to_instance(file);
-
- host = hpsb_get_hostinfo_bykey(&amdtp_highlevel, i);
- if (host == NULL)
- return -ENODEV;
-
- file->private_data = stream_alloc(host);
- if (file->private_data == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-static int amdtp_release(struct inode *inode, struct file *file)
-{
- struct stream *s = file->private_data;
-
- stream_free(s);
-
- return 0;
-}
-
-static struct cdev amdtp_cdev;
-static struct file_operations amdtp_fops =
-{
- .owner = THIS_MODULE,
- .write = amdtp_write,
- .poll = amdtp_poll,
- .unlocked_ioctl = amdtp_ioctl,
- .compat_ioctl = amdtp_ioctl, /* All amdtp ioctls are compatible */
- .open = amdtp_open,
- .release = amdtp_release
-};
-
-/* IEEE1394 Subsystem functions */
-
-static void amdtp_add_host(struct hpsb_host *host)
-{
- struct amdtp_host *ah;
- int minor;
-
- if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0)
- return;
-
- ah = hpsb_create_hostinfo(&amdtp_highlevel, host, sizeof(*ah));
- if (!ah) {
- HPSB_ERR("amdtp: Unable able to alloc hostinfo");
- return;
- }
-
- ah->host = host;
- ah->ohci = host->hostdata;
-
- hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id);
-
- minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id;
-
- INIT_LIST_HEAD(&ah->stream_list);
- spin_lock_init(&ah->stream_list_lock);
-
- devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
- S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id);
-}
-
-static void amdtp_remove_host(struct hpsb_host *host)
-{
- struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host);
-
- if (ah)
- devfs_remove("amdtp/%d", ah->host->id);
-
- return;
-}
-
-static struct hpsb_highlevel amdtp_highlevel = {
- .name = "amdtp",
- .add_host = amdtp_add_host,
- .remove_host = amdtp_remove_host,
-};
-
-/* Module interface */
-
-MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
-MODULE_DESCRIPTION("Driver for Audio & Music Data Transmission Protocol "
- "on OHCI boards.");
-MODULE_SUPPORTED_DEVICE("amdtp");
-MODULE_LICENSE("GPL");
-
-static int __init amdtp_init_module (void)
-{
- cdev_init(&amdtp_cdev, &amdtp_fops);
- amdtp_cdev.owner = THIS_MODULE;
- kobject_set_name(&amdtp_cdev.kobj, "amdtp");
- if (cdev_add(&amdtp_cdev, IEEE1394_AMDTP_DEV, 16)) {
- HPSB_ERR("amdtp: unable to add char device");
- return -EIO;
- }
-
- devfs_mk_dir("amdtp");
-
- hpsb_register_highlevel(&amdtp_highlevel);
-
- HPSB_INFO("Loaded AMDTP driver");
-
- return 0;
-}
-
-static void __exit amdtp_exit_module (void)
-{
- hpsb_unregister_highlevel(&amdtp_highlevel);
- devfs_remove("amdtp");
- cdev_del(&amdtp_cdev);
-
- HPSB_INFO("Unloaded AMDTP driver");
-}
-
-module_init(amdtp_init_module);
-module_exit(amdtp_exit_module);
diff --git a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h
deleted file mode 100644
index 531f28e3ab50..000000000000
--- a/drivers/ieee1394/amdtp.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*- c-basic-offset: 8 -*- */
-
-#ifndef __AMDTP_H
-#define __AMDTP_H
-
-#include <asm/types.h>
-#include "ieee1394-ioctl.h"
-
-/* The userspace interface for the Audio & Music Data Transmission
- * Protocol driver is really simple. First, open /dev/amdtp, use the
- * ioctl to configure format, rate, dimension and either plug or
- * channel, then start writing samples.
- *
- * The formats supported by the driver are listed below.
- * AMDTP_FORMAT_RAW corresponds to the AM824 raw format, which can
- * carry any number of channels, so use this if you're streaming
- * multichannel audio. The AMDTP_FORMAT_IEC958_PCM corresponds to the
- * AM824 IEC958 encapsulation without the IEC958 data bit set, using
- * AMDTP_FORMAT_IEC958_AC3 will transmit the samples with the data bit
- * set, suitable for transmitting compressed AC-3 audio.
- *
- * The rate field specifies the transmission rate; supported values
- * are 32000, 44100, 48000, 88200, 96000, 176400 and 192000.
- *
- * The dimension field specifies the dimension of the signal, that is,
- * the number of audio channels. Only AMDTP_FORMAT_RAW supports
- * settings greater than 2.
- *
- * The mode field specifies which transmission mode to use. The AMDTP
- * specifies two different transmission modes: blocking and
- * non-blocking. The blocking transmission mode always send a fixed
- * number of samples, typically 8, 16 or 32. To exactly match the
- * transmission rate, the driver alternates between sending empty and
- * non-empty packets. In non-blocking mode, the driver transmits as
- * small packets as possible. For example, for a transmission rate of
- * 44100Hz, the driver should send 5 41/80 samples in every cycle, but
- * this is not possible so instead the driver alternates between
- * sending 5 and 6 samples.
- *
- * The last thing to specify is either the isochronous channel to use
- * or the output plug to connect to. If you know what channel the
- * destination device will listen on, you can specify the channel
- * directly and use the AMDTP_IOC_CHANNEL ioctl. However, if the
- * destination device chooses the channel and uses the IEC61883-1 plug
- * mechanism, you can specify an output plug to connect to. The
- * driver will pick up the channel number from the plug once the
- * destination device locks the output plug control register. In this
- * case set the plug field and use the AMDTP_IOC_PLUG ioctl.
- *
- * Having configured the interface, the driver now accepts writes of
- * regular 16 bit signed little endian samples, with the channels
- * interleaved. For example, 4 channels would look like:
- *
- * | sample 0 | sample 1 ...
- * | ch. 0 | ch. 1 | ch. 2 | ch. 3 | ch. 0 | ...
- * | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ...
- *
- */
-
-enum {
- AMDTP_FORMAT_RAW,
- AMDTP_FORMAT_IEC958_PCM,
- AMDTP_FORMAT_IEC958_AC3
-};
-
-enum {
- AMDTP_MODE_BLOCKING,
- AMDTP_MODE_NON_BLOCKING,
-};
-
-enum {
- AMDTP_INPUT_LE16,
- AMDTP_INPUT_BE16,
-};
-
-struct amdtp_ioctl {
- __u32 format;
- __u32 rate;
- __u32 dimension;
- __u32 mode;
- union { __u32 channel; __u32 plug; } u;
-};
-
-#endif /* __AMDTP_H */
diff --git a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c
deleted file mode 100644
index 69aed26e83a1..000000000000
--- a/drivers/ieee1394/cmp.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* -*- c-basic-offset: 8 -*-
- *
- * cmp.c - Connection Management Procedures
- * Copyright (C) 2001 Kristian Høgsberg
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* TODO
- * ----
- *
- * - Implement IEC61883-1 output plugs and connection management.
- * This should probably be part of the general subsystem, as it could
- * be shared with dv1394.
- *
- * - Add IEC61883 unit directory when loading this module. This
- * requires a run-time changeable config rom.
- */
-
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-
-#include "hosts.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "cmp.h"
-
-struct plug {
- union {
- struct cmp_pcr pcr;
- quadlet_t quadlet;
- } u;
- void (*update)(struct cmp_pcr *plug, void *data);
- void *data;
-};
-
-struct cmp_host {
- struct hpsb_host *host;
-
- union {
- struct cmp_mpr ompr;
- quadlet_t ompr_quadlet;
- } u;
- struct plug opcr[2];
-
- union {
- struct cmp_mpr impr;
- quadlet_t impr_quadlet;
- } v;
- struct plug ipcr[2];
-};
-
-enum {
- CMP_P2P_CONNECTION,
- CMP_BC_CONNECTION
-};
-
-#define CSR_PCR_MAP 0x900
-#define CSR_PCR_MAP_END 0x9fc
-
-static struct hpsb_highlevel cmp_highlevel;
-
-static void cmp_add_host(struct hpsb_host *host);
-static void cmp_host_reset(struct hpsb_host *host);
-static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
- u64 addr, size_t length, u16 flags);
-static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags);
-
-static struct hpsb_highlevel cmp_highlevel = {
- .name = "cmp",
- .add_host = cmp_add_host,
- .host_reset = cmp_host_reset,
-};
-
-static struct hpsb_address_ops pcr_ops = {
- .read = pcr_read,
- .lock = pcr_lock,
-};
-
-
-struct cmp_pcr *
-cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
- void (*update)(struct cmp_pcr *pcr, void *data),
- void *data)
-{
- struct cmp_host *ch;
- struct plug *plug;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
-
- if (opcr_number >= ch->u.ompr.nplugs ||
- ch->opcr[opcr_number].update != NULL)
- return NULL;
-
- plug = &ch->opcr[opcr_number];
- plug->u.pcr.online = 1;
- plug->u.pcr.bcast_count = 0;
- plug->u.pcr.p2p_count = 0;
- plug->u.pcr.overhead = 0;
- plug->u.pcr.payload = payload;
- plug->update = update;
- plug->data = data;
-
- return &plug->u.pcr;
-}
-
-void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *opcr)
-{
- struct cmp_host *ch;
- struct plug *plug;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- plug = (struct plug *)opcr;
- if (plug - ch->opcr >= ch->u.ompr.nplugs) BUG();
-
- plug->u.pcr.online = 0;
- plug->update = NULL;
-}
-
-static void reset_plugs(struct cmp_host *ch)
-{
- int i;
-
- ch->u.ompr.non_persistent_ext = 0xff;
- for (i = 0; i < ch->u.ompr.nplugs; i++) {
- ch->opcr[i].u.pcr.bcast_count = 0;
- ch->opcr[i].u.pcr.p2p_count = 0;
- ch->opcr[i].u.pcr.overhead = 0;
- }
-}
-
-static void cmp_add_host(struct hpsb_host *host)
-{
- struct cmp_host *ch = hpsb_create_hostinfo(&cmp_highlevel, host, sizeof (*ch));
-
- if (ch == NULL) {
- HPSB_ERR("Failed to allocate cmp_host");
- return;
- }
-
- hpsb_register_addrspace(&cmp_highlevel, host, &pcr_ops,
- CSR_REGISTER_BASE + CSR_PCR_MAP,
- CSR_REGISTER_BASE + CSR_PCR_MAP_END);
-
- ch->host = host;
- ch->u.ompr.rate = IEEE1394_SPEED_100;
- ch->u.ompr.bcast_channel_base = 63;
- ch->u.ompr.nplugs = 2;
-
- reset_plugs(ch);
-}
-
-static void cmp_host_reset(struct hpsb_host *host)
-{
- struct cmp_host *ch;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- if (ch == NULL) {
- HPSB_ERR("cmp: Tried to reset unknown host");
- return;
- }
-
- reset_plugs(ch);
-}
-
-static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
- u64 addr, size_t length, u16 flags)
-{
- int csraddr = addr - CSR_REGISTER_BASE;
- int plug;
- struct cmp_host *ch;
-
- if (length != 4)
- return RCODE_TYPE_ERROR;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
- if (csraddr == 0x900) {
- *buf = cpu_to_be32(ch->u.ompr_quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
- plug = (csraddr - 0x904) / 4;
- *buf = cpu_to_be32(ch->opcr[plug].u.quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x980) {
- return RCODE_ADDRESS_ERROR;
- }
- else if (csraddr == 0x980) {
- *buf = cpu_to_be32(ch->v.impr_quadlet);
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
- plug = (csraddr - 0x984) / 4;
- *buf = cpu_to_be32(ch->ipcr[plug].u.quadlet);
- return RCODE_COMPLETE;
- }
- else
- return RCODE_ADDRESS_ERROR;
-}
-
-static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
- u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags)
-{
- int csraddr = addr - CSR_REGISTER_BASE;
- int plug;
- struct cmp_host *ch;
-
- ch = hpsb_get_hostinfo(&cmp_highlevel, host);
-
- if (extcode != EXTCODE_COMPARE_SWAP)
- return RCODE_TYPE_ERROR;
-
- if (csraddr == 0x900) {
- /* FIXME: Ignore writes to bits 30-31 and 0-7 */
- *store = cpu_to_be32(ch->u.ompr_quadlet);
- if (arg == cpu_to_be32(ch->u.ompr_quadlet))
- ch->u.ompr_quadlet = be32_to_cpu(data);
-
- return RCODE_COMPLETE;
- }
- if (csraddr < 0x904 + ch->u.ompr.nplugs * 4) {
- plug = (csraddr - 0x904) / 4;
- *store = cpu_to_be32(ch->opcr[plug].u.quadlet);
-
- if (arg == *store)
- ch->opcr[plug].u.quadlet = be32_to_cpu(data);
-
- if (be32_to_cpu(*store) != ch->opcr[plug].u.quadlet &&
- ch->opcr[plug].update != NULL)
- ch->opcr[plug].update(&ch->opcr[plug].u.pcr,
- ch->opcr[plug].data);
-
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x980) {
- return RCODE_ADDRESS_ERROR;
- }
- else if (csraddr == 0x980) {
- /* FIXME: Ignore writes to bits 24-31 and 0-7 */
- *store = cpu_to_be32(ch->u.ompr_quadlet);
- if (arg == cpu_to_be32(ch->u.ompr_quadlet))
- ch->u.ompr_quadlet = be32_to_cpu(data);
-
- return RCODE_COMPLETE;
- }
- else if (csraddr < 0x984 + ch->v.impr.nplugs * 4) {
- plug = (csraddr - 0x984) / 4;
- *store = cpu_to_be32(ch->ipcr[plug].u.quadlet);
-
- if (arg == *store)
- ch->ipcr[plug].u.quadlet = be32_to_cpu(data);
-
- if (be32_to_cpu(*store) != ch->ipcr[plug].u.quadlet &&
- ch->ipcr[plug].update != NULL)
- ch->ipcr[plug].update(&ch->ipcr[plug].u.pcr,
- ch->ipcr[plug].data);
-
- return RCODE_COMPLETE;
- }
- else
- return RCODE_ADDRESS_ERROR;
-}
-
-
-/* Module interface */
-
-MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
-MODULE_DESCRIPTION("Connection Management Procedures (CMP)");
-MODULE_SUPPORTED_DEVICE("cmp");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cmp_register_opcr);
-EXPORT_SYMBOL(cmp_unregister_opcr);
-
-static int __init cmp_init_module (void)
-{
- hpsb_register_highlevel (&cmp_highlevel);
-
- HPSB_INFO("Loaded CMP driver");
-
- return 0;
-}
-
-static void __exit cmp_exit_module (void)
-{
- hpsb_unregister_highlevel(&cmp_highlevel);
-
- HPSB_INFO("Unloaded CMP driver");
-}
-
-module_init(cmp_init_module);
-module_exit(cmp_exit_module);
diff --git a/drivers/ieee1394/cmp.h b/drivers/ieee1394/cmp.h
deleted file mode 100644
index f9288bfcd494..000000000000
--- a/drivers/ieee1394/cmp.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __CMP_H
-#define __CMP_H
-
-struct cmp_mpr {
- u32 nplugs:5;
- u32 reserved:3;
- u32 persistent_ext:8;
- u32 non_persistent_ext:8;
- u32 bcast_channel_base:6;
- u32 rate:2;
-} __attribute__((packed));
-
-struct cmp_pcr {
- u32 payload:10;
- u32 overhead:4;
- u32 speed:2;
- u32 channel:6;
- u32 reserved:2;
- u32 p2p_count:6;
- u32 bcast_count:1;
- u32 online:1;
-} __attribute__((packed));
-
-struct cmp_pcr *cmp_register_opcr(struct hpsb_host *host, int plug,
- int payload,
- void (*update)(struct cmp_pcr *plug,
- void *data),
- void *data);
-void cmp_unregister_opcr(struct hpsb_host *host, struct cmp_pcr *plug);
-
-#endif /* __CMP_H */
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 61ddd5d37eff..15773544234b 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -1261,7 +1261,7 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
return CSR1212_EINVAL;
#endif
- cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ cr = CSR1212_MALLOC(sizeof(*cr));
if (!cr)
return CSR1212_ENOMEM;
@@ -1393,8 +1393,7 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv,
case CSR1212_KV_TYPE_LEAF:
if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
- if (!kv->value.leaf.data)
- {
+ if (!kv->value.leaf.data) {
ret = CSR1212_ENOMEM;
goto fail;
}
@@ -1462,7 +1461,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
cache->next = NULL;
csr->cache_tail = cache;
cache->filled_head =
- CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ CSR1212_MALLOC(sizeof(*cache->filled_head));
if (!cache->filled_head) {
return CSR1212_ENOMEM;
}
@@ -1484,7 +1483,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
/* Now seach read portions of the cache to see if it is there. */
for (cr = cache->filled_head; cr; cr = cr->next) {
if (cache_index < cr->offset_start) {
- newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ newcr = CSR1212_MALLOC(sizeof(*newcr));
if (!newcr)
return CSR1212_ENOMEM;
@@ -1508,7 +1507,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
if (!cr) {
cr = cache->filled_tail;
- newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
+ newcr = CSR1212_MALLOC(sizeof(*newcr));
if (!newcr)
return CSR1212_ENOMEM;
@@ -1611,15 +1610,17 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
csr->root_kv->valid = 0;
csr->root_kv->next = csr->root_kv;
csr->root_kv->prev = csr->root_kv;
- csr1212_get_keyval(csr, csr->root_kv);
+ ret = _csr1212_read_keyval(csr, csr->root_kv);
+ if (ret != CSR1212_SUCCESS)
+ return ret;
/* Scan through the Root directory finding all extended ROM regions
* and make cache regions for them */
for (dentry = csr->root_kv->value.directory.dentries_head;
dentry; dentry = dentry->next) {
- if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
- csr1212_get_keyval(csr, dentry->kv);
-
+ if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
+ !dentry->kv->valid) {
+ ret = _csr1212_read_keyval(csr, dentry->kv);
if (ret != CSR1212_SUCCESS)
return ret;
}
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index 28c5f4b726e2..cecd5871f2de 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -646,7 +646,7 @@ static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t o
{
struct csr1212_csr_rom_cache *cache;
- cache = CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size);
+ cache = CSR1212_MALLOC(sizeof(*cache) + size);
if (!cache)
return NULL;
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index b79ddb43e746..9fb2769d9abc 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -23,7 +23,8 @@ void dma_prog_region_init(struct dma_prog_region *prog)
prog->bus_addr = 0;
}
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev)
+int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
+ struct pci_dev *dev)
{
/* round up to page size */
n_bytes = PAGE_ALIGN(n_bytes);
@@ -32,7 +33,8 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
if (!prog->kvirt) {
- printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
+ printk(KERN_ERR
+ "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
dma_prog_region_free(prog);
return -ENOMEM;
}
@@ -45,7 +47,8 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
void dma_prog_region_free(struct dma_prog_region *prog)
{
if (prog->kvirt) {
- pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT, prog->kvirt, prog->bus_addr);
+ pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
+ prog->kvirt, prog->bus_addr);
}
prog->kvirt = NULL;
@@ -65,7 +68,8 @@ void dma_region_init(struct dma_region *dma)
dma->sglist = NULL;
}
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction)
+int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
+ struct pci_dev *dev, int direction)
{
unsigned int i;
@@ -95,14 +99,16 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
/* fill scatter/gather list with pages */
for (i = 0; i < dma->n_pages; i++) {
- unsigned long va = (unsigned long) dma->kvirt + (i << PAGE_SHIFT);
+ unsigned long va =
+ (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
dma->sglist[i].page = vmalloc_to_page((void *)va);
dma->sglist[i].length = PAGE_SIZE;
}
/* map sglist to the IOMMU */
- dma->n_dma_pages = pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
+ dma->n_dma_pages =
+ pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
if (dma->n_dma_pages == 0) {
printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
@@ -114,7 +120,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
return 0;
-err:
+ err:
dma_region_free(dma);
return -ENOMEM;
}
@@ -122,7 +128,8 @@ err:
void dma_region_free(struct dma_region *dma)
{
if (dma->n_dma_pages) {
- pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction);
+ pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
+ dma->direction);
dma->n_dma_pages = 0;
dma->dev = NULL;
}
@@ -137,7 +144,8 @@ void dma_region_free(struct dma_region *dma)
/* find the scatterlist index and remaining offset corresponding to a
given offset from the beginning of the buffer */
-static inline int dma_region_find(struct dma_region *dma, unsigned long offset, unsigned long *rem)
+static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
+ unsigned long *rem)
{
int i;
unsigned long off = offset;
@@ -156,15 +164,18 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
return i;
}
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
+dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
+ unsigned long offset)
{
unsigned long rem = 0;
- struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
+ struct scatterlist *sg =
+ &dma->sglist[dma_region_find(dma, offset, &rem)];
return sg_dma_address(sg) + rem;
}
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
+ unsigned long len)
{
int first, last;
unsigned long rem;
@@ -175,10 +186,12 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsig
first = dma_region_find(dma, offset, &rem);
last = dma_region_find(dma, offset + len - 1, &rem);
- pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+ pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
+ dma->direction);
}
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len)
+void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
+ unsigned long len)
{
int first, last;
unsigned long rem;
@@ -189,44 +202,47 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, un
first = dma_region_find(dma, offset, &rem);
last = dma_region_find(dma, offset + len - 1, &rem);
- pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+ pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
+ last - first + 1, dma->direction);
}
#ifdef CONFIG_MMU
/* nopage() handler for mmap access */
-static struct page*
-dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page *dma_region_pagefault(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
unsigned long offset;
unsigned long kernel_virt_addr;
struct page *ret = NOPAGE_SIGBUS;
- struct dma_region *dma = (struct dma_region*) area->vm_private_data;
+ struct dma_region *dma = (struct dma_region *)area->vm_private_data;
if (!dma->kvirt)
goto out;
- if ( (address < (unsigned long) area->vm_start) ||
- (address > (unsigned long) area->vm_start + (dma->n_pages << PAGE_SHIFT)) )
+ if ((address < (unsigned long)area->vm_start) ||
+ (address >
+ (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
goto out;
if (type)
*type = VM_FAULT_MINOR;
offset = address - area->vm_start;
- kernel_virt_addr = (unsigned long) dma->kvirt + offset;
- ret = vmalloc_to_page((void*) kernel_virt_addr);
+ kernel_virt_addr = (unsigned long)dma->kvirt + offset;
+ ret = vmalloc_to_page((void *)kernel_virt_addr);
get_page(ret);
-out:
+ out:
return ret;
}
static struct vm_operations_struct dma_region_vm_ops = {
- .nopage = dma_region_pagefault,
+ .nopage = dma_region_pagefault,
};
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+ struct vm_area_struct *vma)
{
unsigned long size;
@@ -250,11 +266,12 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_st
return 0;
}
-#else /* CONFIG_MMU */
+#else /* CONFIG_MMU */
-int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
+int dma_region_mmap(struct dma_region *dma, struct file *file,
+ struct vm_area_struct *vma)
{
return -EINVAL;
}
-#endif /* CONFIG_MMU */
+#endif /* CONFIG_MMU */
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index cbbbe14b8849..efeaa944bd0a 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -108,7 +108,6 @@
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/cdev.h>
@@ -123,15 +122,6 @@
#include "ohci1394.h"
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
-
/* DEBUG LEVELS:
0 - no debugging messages
1 - some debugging messages, but none during DMA frame transmission
@@ -2218,14 +2208,12 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
unsigned long flags;
int i;
- video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+ video = kzalloc(sizeof(*video), GFP_KERNEL);
if (!video) {
printk(KERN_ERR "dv1394: cannot allocate video_card\n");
goto err;
}
- memset(video, 0, sizeof(struct video_card));
-
video->ohci = ohci;
/* lower 2 bits of id indicate which of four "plugs"
per host */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index c9e92d85c893..30fa0d43a43a 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -88,9 +88,6 @@
printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args)
#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
-static char version[] __devinitdata =
- "$Rev: 1312 $ Ben Collins <bcollins@debian.org>";
-
struct fragment_info {
struct list_head list;
int offset;
@@ -355,12 +352,12 @@ static int eth1394_probe(struct device *dev)
if (!hi)
return -ENOENT;
- new_node = kmalloc(sizeof(struct eth1394_node_ref),
+ new_node = kmalloc(sizeof(*new_node),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!new_node)
return -ENOMEM;
- node_info = kmalloc(sizeof(struct eth1394_node_info),
+ node_info = kmalloc(sizeof(*node_info),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node_info) {
kfree(new_node);
@@ -436,12 +433,12 @@ static int eth1394_update(struct unit_directory *ud)
node = eth1394_find_node(&priv->ip_node_list, ud);
if (!node) {
- node = kmalloc(sizeof(struct eth1394_node_ref),
+ node = kmalloc(sizeof(*node),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node)
return -ENOMEM;
- node_info = kmalloc(sizeof(struct eth1394_node_info),
+ node_info = kmalloc(sizeof(*node_info),
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!node_info) {
kfree(node);
@@ -566,7 +563,6 @@ static void ether1394_add_host (struct hpsb_host *host)
struct eth1394_host_info *hi = NULL;
struct net_device *dev = NULL;
struct eth1394_priv *priv;
- static int version_printed = 0;
u64 fifo_addr;
if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
@@ -581,9 +577,6 @@ static void ether1394_add_host (struct hpsb_host *host)
if (fifo_addr == ~0ULL)
goto out;
- if (version_printed++ == 0)
- ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
-
/* We should really have our own alloc_hpsbdev() function in
* net_init.c instead of calling the one for ethernet then hijacking
* it for ourselves. That way we'd be a real networking device. */
@@ -1021,7 +1014,7 @@ static inline int new_fragment(struct list_head *frag_info, int offset, int len)
}
}
- new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
if (!new)
return -ENOMEM;
@@ -1040,7 +1033,7 @@ static inline int new_partial_datagram(struct net_device *dev,
{
struct partial_datagram *new;
- new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
if (!new)
return -ENOMEM;
@@ -1768,7 +1761,6 @@ fail:
static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
strcpy (info->driver, driver_name);
- strcpy (info->version, "$Rev: 1312 $");
/* FIXME XXX provide sane businfo */
strcpy (info->bus_info, "ieee1394");
}
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 997e1bf6297f..734b121a0554 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -101,12 +101,10 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return NULL;
}
- hi = kmalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
+ hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
if (!hi)
return NULL;
- memset(hi, 0, sizeof(*hi) + data_size);
-
if (data_size) {
data = hi->data = hi + 1;
hi->size = data_size;
@@ -326,11 +324,9 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
return retval;
}
- as = (struct hpsb_address_serve *)
- kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
- if (as == NULL) {
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
+ if (!as)
return retval;
- }
INIT_LIST_HEAD(&as->host_list);
INIT_LIST_HEAD(&as->hl_list);
@@ -383,11 +379,9 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return 0;
}
- as = (struct hpsb_address_serve *)
- kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC);
- if (as == NULL) {
- return 0;
- }
+ as = kmalloc(sizeof(*as), GFP_ATOMIC);
+ if (!as)
+ return 0;
INIT_LIST_HEAD(&as->host_list);
INIT_LIST_HEAD(&as->hl_list);
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index aeeaeb670d03..ba09741fc826 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -61,12 +61,12 @@ static void delayed_reset_bus(void * __reset_info)
static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
{
- return 0;
+ return 0;
}
static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
{
- return -1;
+ return -1;
}
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
@@ -75,9 +75,9 @@ static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned
}
static struct hpsb_host_driver dummy_driver = {
- .transmit_packet = dummy_transmit_packet,
- .devctl = dummy_devctl,
- .isoctl = dummy_isoctl
+ .transmit_packet = dummy_transmit_packet,
+ .devctl = dummy_devctl,
+ .isoctl = dummy_isoctl
};
static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
@@ -110,13 +110,13 @@ static DECLARE_MUTEX(host_num_alloc);
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev)
{
- struct hpsb_host *h;
+ struct hpsb_host *h;
int i;
int hostnum = 0;
- h = kmalloc(sizeof(struct hpsb_host) + extra, SLAB_KERNEL);
- if (!h) return NULL;
- memset(h, 0, sizeof(struct hpsb_host) + extra);
+ h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL);
+ if (!h)
+ return NULL;
h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
if (!h->csr.rom) {
@@ -125,7 +125,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
}
h->hostdata = h + 1;
- h->driver = drv;
+ h->driver = drv;
skb_queue_head_init(&h->pending_packet_queue);
INIT_LIST_HEAD(&h->addr_space);
@@ -145,8 +145,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->timeout.function = abort_timedouts;
h->timeout_interval = HZ / 20; // 50ms by default
- h->topology_map = h->csr.topology_map + 3;
- h->speed_map = (u8 *)(h->csr.speed_map + 2);
+ h->topology_map = h->csr.topology_map + 3;
+ h->speed_map = (u8 *)(h->csr.speed_map + 2);
down(&host_num_alloc);
@@ -186,14 +186,14 @@ int hpsb_add_host(struct hpsb_host *host)
void hpsb_remove_host(struct hpsb_host *host)
{
- host->is_shutdown = 1;
+ host->is_shutdown = 1;
cancel_delayed_work(&host->delayed_reset);
flush_scheduled_work();
- host->driver = &dummy_driver;
+ host->driver = &dummy_driver;
- highlevel_remove_host(host);
+ highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index ae9b02cc013f..07d188ca8495 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -17,47 +17,47 @@ struct hpsb_packet;
struct hpsb_iso;
struct hpsb_host {
- struct list_head host_list;
+ struct list_head host_list;
- void *hostdata;
+ void *hostdata;
- atomic_t generation;
+ atomic_t generation;
struct sk_buff_head pending_packet_queue;
struct timer_list timeout;
unsigned long timeout_interval;
- unsigned char iso_listen_count[64];
+ unsigned char iso_listen_count[64];
- int node_count; /* number of identified nodes on this bus */
- int selfid_count; /* total number of SelfIDs received */
+ int node_count; /* number of identified nodes on this bus */
+ int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes that are actually active */
- nodeid_t node_id; /* node ID of this host */
- nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
- nodeid_t busmgr_id; /* ID of this bus' bus manager */
+ nodeid_t node_id; /* node ID of this host */
+ nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
+ nodeid_t busmgr_id; /* ID of this bus' bus manager */
- /* this nodes state */
- unsigned in_bus_reset:1;
- unsigned is_shutdown:1;
+ /* this nodes state */
+ unsigned in_bus_reset:1;
+ unsigned is_shutdown:1;
unsigned resume_packet_sent:1;
- /* this nodes' duties on the bus */
- unsigned is_root:1;
- unsigned is_cycmst:1;
- unsigned is_irm:1;
- unsigned is_busmgr:1;
+ /* this nodes' duties on the bus */
+ unsigned is_root:1;
+ unsigned is_cycmst:1;
+ unsigned is_irm:1;
+ unsigned is_busmgr:1;
- int reset_retries;
- quadlet_t *topology_map;
- u8 *speed_map;
- struct csr_control csr;
+ int reset_retries;
+ quadlet_t *topology_map;
+ u8 *speed_map;
+ struct csr_control csr;
/* Per node tlabel pool allocation */
struct hpsb_tlabel_pool tpool[64];
- struct hpsb_host_driver *driver;
+ struct hpsb_host_driver *driver;
struct pci_dev *pdev;
@@ -77,34 +77,34 @@ struct hpsb_host {
enum devctl_cmd {
- /* Host is requested to reset its bus and cancel all outstanding async
- * requests. If arg == 1, it shall also attempt to become root on the
- * bus. Return void. */
- RESET_BUS,
-
- /* Arg is void, return value is the hardware cycle counter value. */
- GET_CYCLE_COUNTER,
-
- /* Set the hardware cycle counter to the value in arg, return void.
- * FIXME - setting is probably not required. */
- SET_CYCLE_COUNTER,
-
- /* Configure hardware for new bus ID in arg, return void. */
- SET_BUS_ID,
-
- /* If arg true, start sending cycle start packets, stop if arg == 0.
- * Return void. */
- ACT_CYCLE_MASTER,
-
- /* Cancel all outstanding async requests without resetting the bus.
- * Return void. */
- CANCEL_REQUESTS,
-
- /* Start or stop receiving isochronous channel in arg. Return void.
- * This acts as an optimization hint, hosts are not required not to
- * listen on unrequested channels. */
- ISO_LISTEN_CHANNEL,
- ISO_UNLISTEN_CHANNEL
+ /* Host is requested to reset its bus and cancel all outstanding async
+ * requests. If arg == 1, it shall also attempt to become root on the
+ * bus. Return void. */
+ RESET_BUS,
+
+ /* Arg is void, return value is the hardware cycle counter value. */
+ GET_CYCLE_COUNTER,
+
+ /* Set the hardware cycle counter to the value in arg, return void.
+ * FIXME - setting is probably not required. */
+ SET_CYCLE_COUNTER,
+
+ /* Configure hardware for new bus ID in arg, return void. */
+ SET_BUS_ID,
+
+ /* If arg true, start sending cycle start packets, stop if arg == 0.
+ * Return void. */
+ ACT_CYCLE_MASTER,
+
+ /* Cancel all outstanding async requests without resetting the bus.
+ * Return void. */
+ CANCEL_REQUESTS,
+
+ /* Start or stop receiving isochronous channel in arg. Return void.
+ * This acts as an optimization hint, hosts are not required not to
+ * listen on unrequested channels. */
+ ISO_LISTEN_CHANNEL,
+ ISO_UNLISTEN_CHANNEL
};
enum isoctl_cmd {
@@ -135,13 +135,13 @@ enum isoctl_cmd {
};
enum reset_types {
- /* 166 microsecond reset -- only type of reset available on
- non-1394a capable controllers */
- LONG_RESET,
+ /* 166 microsecond reset -- only type of reset available on
+ non-1394a capable controllers */
+ LONG_RESET,
- /* Short (arbitrated) reset -- only available on 1394a capable
- controllers */
- SHORT_RESET,
+ /* Short (arbitrated) reset -- only available on 1394a capable
+ controllers */
+ SHORT_RESET,
/* Variants that set force_root before issueing the bus reset */
LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
@@ -159,22 +159,22 @@ struct hpsb_host_driver {
* reads to the ConfigROM on its own. */
void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom);
- /* This function shall implement packet transmission based on
- * packet->type. It shall CRC both parts of the packet (unless
- * packet->type == raw) and do byte-swapping as necessary or instruct
- * the hardware to do so. It can return immediately after the packet
- * was queued for sending. After sending, hpsb_sent_packet() has to be
- * called. Return 0 on success, negative errno on failure.
- * NOTE: The function must be callable in interrupt context.
- */
- int (*transmit_packet) (struct hpsb_host *host,
- struct hpsb_packet *packet);
-
- /* This function requests miscellanous services from the driver, see
- * above for command codes and expected actions. Return -1 for unknown
- * command, though that should never happen.
- */
- int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
+ /* This function shall implement packet transmission based on
+ * packet->type. It shall CRC both parts of the packet (unless
+ * packet->type == raw) and do byte-swapping as necessary or instruct
+ * the hardware to do so. It can return immediately after the packet
+ * was queued for sending. After sending, hpsb_sent_packet() has to be
+ * called. Return 0 on success, negative errno on failure.
+ * NOTE: The function must be callable in interrupt context.
+ */
+ int (*transmit_packet) (struct hpsb_host *host,
+ struct hpsb_packet *packet);
+
+ /* This function requests miscellanous services from the driver, see
+ * above for command codes and expected actions. Return -1 for unknown
+ * command, though that should never happen.
+ */
+ int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
/* ISO transmission/reception functions. Return 0 on success, -1
* (or -EXXX errno code) on failure. If the low-level driver does not
@@ -182,15 +182,15 @@ struct hpsb_host_driver {
*/
int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
- /* This function is mainly to redirect local CSR reads/locks to the iso
- * management registers (bus manager id, bandwidth available, channels
- * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus
- * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
- * as OHCI uses). data and compare are the new data and expected data
- * respectively, return value is the old value.
- */
- quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
- quadlet_t data, quadlet_t compare);
+ /* This function is mainly to redirect local CSR reads/locks to the iso
+ * management registers (bus manager id, bandwidth available, channels
+ * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus
+ * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
+ * as OHCI uses). data and compare are the new data and expected data
+ * respectively, return value is the old value.
+ */
+ quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
+ quadlet_t data, quadlet_t compare);
};
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
index f92b566363d5..156703986348 100644
--- a/drivers/ieee1394/ieee1394-ioctl.h
+++ b/drivers/ieee1394/ieee1394-ioctl.h
@@ -7,14 +7,6 @@
#include <linux/ioctl.h>
#include <linux/types.h>
-
-/* AMDTP Gets 6 */
-#define AMDTP_IOC_CHANNEL _IOW('#', 0x00, struct amdtp_ioctl)
-#define AMDTP_IOC_PLUG _IOW('#', 0x01, struct amdtp_ioctl)
-#define AMDTP_IOC_PING _IOW('#', 0x02, struct amdtp_ioctl)
-#define AMDTP_IOC_ZAP _IO ('#', 0x03)
-
-
/* DV1394 Gets 10 */
/* Get the driver ready to transmit video. pass a struct dv1394_init* as
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
index b634a9bb365c..936d776de00a 100644
--- a/drivers/ieee1394/ieee1394.h
+++ b/drivers/ieee1394/ieee1394.h
@@ -62,6 +62,7 @@
extern const char *hpsb_speedto_str[];
+/* 1394a cable PHY packets */
#define SELFID_PWRCL_NO_POWER 0x0
#define SELFID_PWRCL_PROVIDE_15W 0x1
#define SELFID_PWRCL_PROVIDE_30W 0x2
@@ -76,8 +77,24 @@ extern const char *hpsb_speedto_str[];
#define SELFID_PORT_NCONN 0x1
#define SELFID_PORT_NONE 0x0
+#define PHYPACKET_LINKON 0x40000000
+#define PHYPACKET_PHYCONFIG_R 0x00800000
+#define PHYPACKET_PHYCONFIG_T 0x00400000
+#define EXTPHYPACKET_TYPE_PING 0x00000000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE 0x00040000
+#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED 0x00140000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE 0x000C0000
+#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED 0x001C0000
+#define EXTPHYPACKET_TYPE_REMOTECOMMAND 0x00200000
+#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION 0x00280000
+#define EXTPHYPACKET_TYPE_RESUME 0x003C0000
-/* 1394a PHY bitmasks */
+#define EXTPHYPACKET_TYPEMASK 0xC0FC0000
+
+#define PHYPACKET_PORT_SHIFT 24
+#define PHYPACKET_GAPCOUNT_SHIFT 16
+
+/* 1394a PHY register map bitmasks */
#define PHY_00_PHYSICAL_ID 0xFC
#define PHY_00_R 0x02 /* Root */
#define PHY_00_PS 0x01 /* Power Status*/
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 32a1e016c85e..25ef5a86f5f0 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -179,34 +179,34 @@ void hpsb_free_packet(struct hpsb_packet *packet)
int hpsb_reset_bus(struct hpsb_host *host, int type)
{
- if (!host->in_bus_reset) {
- host->driver->devctl(host, RESET_BUS, type);
- return 0;
- } else {
- return 1;
- }
+ if (!host->in_bus_reset) {
+ host->driver->devctl(host, RESET_BUS, type);
+ return 0;
+ } else {
+ return 1;
+ }
}
int hpsb_bus_reset(struct hpsb_host *host)
{
- if (host->in_bus_reset) {
- HPSB_NOTICE("%s called while bus reset already in progress",
+ if (host->in_bus_reset) {
+ HPSB_NOTICE("%s called while bus reset already in progress",
__FUNCTION__);
- return 1;
- }
+ return 1;
+ }
- abort_requests(host);
- host->in_bus_reset = 1;
- host->irm_id = -1;
+ abort_requests(host);
+ host->in_bus_reset = 1;
+ host->irm_id = -1;
host->is_irm = 0;
- host->busmgr_id = -1;
+ host->busmgr_id = -1;
host->is_busmgr = 0;
host->is_cycmst = 0;
- host->node_count = 0;
- host->selfid_count = 0;
+ host->node_count = 0;
+ host->selfid_count = 0;
- return 0;
+ return 0;
}
@@ -216,150 +216,156 @@ int hpsb_bus_reset(struct hpsb_host *host)
*/
static int check_selfids(struct hpsb_host *host)
{
- int nodeid = -1;
- int rest_of_selfids = host->selfid_count;
- struct selfid *sid = (struct selfid *)host->topology_map;
- struct ext_selfid *esid;
- int esid_seq = 23;
+ int nodeid = -1;
+ int rest_of_selfids = host->selfid_count;
+ struct selfid *sid = (struct selfid *)host->topology_map;
+ struct ext_selfid *esid;
+ int esid_seq = 23;
host->nodes_active = 0;
- while (rest_of_selfids--) {
- if (!sid->extended) {
- nodeid++;
- esid_seq = 0;
+ while (rest_of_selfids--) {
+ if (!sid->extended) {
+ nodeid++;
+ esid_seq = 0;
- if (sid->phy_id != nodeid) {
- HPSB_INFO("SelfIDs failed monotony check with "
- "%d", sid->phy_id);
- return 0;
- }
+ if (sid->phy_id != nodeid) {
+ HPSB_INFO("SelfIDs failed monotony check with "
+ "%d", sid->phy_id);
+ return 0;
+ }
if (sid->link_active) {
host->nodes_active++;
if (sid->contender)
host->irm_id = LOCAL_BUS | sid->phy_id;
}
- } else {
- esid = (struct ext_selfid *)sid;
-
- if ((esid->phy_id != nodeid)
- || (esid->seq_nr != esid_seq)) {
- HPSB_INFO("SelfIDs failed monotony check with "
- "%d/%d", esid->phy_id, esid->seq_nr);
- return 0;
- }
- esid_seq++;
- }
- sid++;
- }
-
- esid = (struct ext_selfid *)(sid - 1);
- while (esid->extended) {
- if ((esid->porta == 0x2) || (esid->portb == 0x2)
- || (esid->portc == 0x2) || (esid->portd == 0x2)
- || (esid->porte == 0x2) || (esid->portf == 0x2)
- || (esid->portg == 0x2) || (esid->porth == 0x2)) {
+ } else {
+ esid = (struct ext_selfid *)sid;
+
+ if ((esid->phy_id != nodeid)
+ || (esid->seq_nr != esid_seq)) {
+ HPSB_INFO("SelfIDs failed monotony check with "
+ "%d/%d", esid->phy_id, esid->seq_nr);
+ return 0;
+ }
+ esid_seq++;
+ }
+ sid++;
+ }
+
+ esid = (struct ext_selfid *)(sid - 1);
+ while (esid->extended) {
+ if ((esid->porta == SELFID_PORT_PARENT) ||
+ (esid->portb == SELFID_PORT_PARENT) ||
+ (esid->portc == SELFID_PORT_PARENT) ||
+ (esid->portd == SELFID_PORT_PARENT) ||
+ (esid->porte == SELFID_PORT_PARENT) ||
+ (esid->portf == SELFID_PORT_PARENT) ||
+ (esid->portg == SELFID_PORT_PARENT) ||
+ (esid->porth == SELFID_PORT_PARENT)) {
HPSB_INFO("SelfIDs failed root check on "
"extended SelfID");
return 0;
- }
- esid--;
- }
+ }
+ esid--;
+ }
- sid = (struct selfid *)esid;
- if ((sid->port0 == 0x2) || (sid->port1 == 0x2) || (sid->port2 == 0x2)) {
+ sid = (struct selfid *)esid;
+ if ((sid->port0 == SELFID_PORT_PARENT) ||
+ (sid->port1 == SELFID_PORT_PARENT) ||
+ (sid->port2 == SELFID_PORT_PARENT)) {
HPSB_INFO("SelfIDs failed root check");
return 0;
- }
+ }
host->node_count = nodeid + 1;
- return 1;
+ return 1;
}
static void build_speed_map(struct hpsb_host *host, int nodecount)
{
u8 speedcap[nodecount];
u8 cldcnt[nodecount];
- u8 *map = host->speed_map;
- struct selfid *sid;
- struct ext_selfid *esid;
- int i, j, n;
-
- for (i = 0; i < (nodecount * 64); i += 64) {
- for (j = 0; j < nodecount; j++) {
- map[i+j] = IEEE1394_SPEED_MAX;
- }
- }
-
- for (i = 0; i < nodecount; i++) {
- cldcnt[i] = 0;
- }
-
- /* find direct children count and speed */
- for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
- n = nodecount - 1;
- (void *)sid >= (void *)host->topology_map; sid--) {
- if (sid->extended) {
- esid = (struct ext_selfid *)sid;
-
- if (esid->porta == 0x3) cldcnt[n]++;
- if (esid->portb == 0x3) cldcnt[n]++;
- if (esid->portc == 0x3) cldcnt[n]++;
- if (esid->portd == 0x3) cldcnt[n]++;
- if (esid->porte == 0x3) cldcnt[n]++;
- if (esid->portf == 0x3) cldcnt[n]++;
- if (esid->portg == 0x3) cldcnt[n]++;
- if (esid->porth == 0x3) cldcnt[n]++;
+ u8 *map = host->speed_map;
+ struct selfid *sid;
+ struct ext_selfid *esid;
+ int i, j, n;
+
+ for (i = 0; i < (nodecount * 64); i += 64) {
+ for (j = 0; j < nodecount; j++) {
+ map[i+j] = IEEE1394_SPEED_MAX;
+ }
+ }
+
+ for (i = 0; i < nodecount; i++) {
+ cldcnt[i] = 0;
+ }
+
+ /* find direct children count and speed */
+ for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
+ n = nodecount - 1;
+ (void *)sid >= (void *)host->topology_map; sid--) {
+ if (sid->extended) {
+ esid = (struct ext_selfid *)sid;
+
+ if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
} else {
- if (sid->port0 == 0x3) cldcnt[n]++;
- if (sid->port1 == 0x3) cldcnt[n]++;
- if (sid->port2 == 0x3) cldcnt[n]++;
-
- speedcap[n] = sid->speed;
- n--;
- }
- }
-
- /* set self mapping */
- for (i = 0; i < nodecount; i++) {
- map[64*i + i] = speedcap[i];
- }
-
- /* fix up direct children count to total children count;
- * also fix up speedcaps for sibling and parent communication */
- for (i = 1; i < nodecount; i++) {
- for (j = cldcnt[i], n = i - 1; j > 0; j--) {
- cldcnt[i] += cldcnt[n];
- speedcap[n] = min(speedcap[n], speedcap[i]);
- n -= cldcnt[n] + 1;
- }
- }
-
- for (n = 0; n < nodecount; n++) {
- for (i = n - cldcnt[n]; i <= n; i++) {
- for (j = 0; j < (n - cldcnt[n]); j++) {
- map[j*64 + i] = map[i*64 + j] =
- min(map[i*64 + j], speedcap[n]);
- }
- for (j = n + 1; j < nodecount; j++) {
- map[j*64 + i] = map[i*64 + j] =
- min(map[i*64 + j], speedcap[n]);
- }
- }
- }
+ if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
+ if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
+
+ speedcap[n] = sid->speed;
+ n--;
+ }
+ }
+
+ /* set self mapping */
+ for (i = 0; i < nodecount; i++) {
+ map[64*i + i] = speedcap[i];
+ }
+
+ /* fix up direct children count to total children count;
+ * also fix up speedcaps for sibling and parent communication */
+ for (i = 1; i < nodecount; i++) {
+ for (j = cldcnt[i], n = i - 1; j > 0; j--) {
+ cldcnt[i] += cldcnt[n];
+ speedcap[n] = min(speedcap[n], speedcap[i]);
+ n -= cldcnt[n] + 1;
+ }
+ }
+
+ for (n = 0; n < nodecount; n++) {
+ for (i = n - cldcnt[n]; i <= n; i++) {
+ for (j = 0; j < (n - cldcnt[n]); j++) {
+ map[j*64 + i] = map[i*64 + j] =
+ min(map[i*64 + j], speedcap[n]);
+ }
+ for (j = n + 1; j < nodecount; j++) {
+ map[j*64 + i] = map[i*64 + j] =
+ min(map[i*64 + j], speedcap[n]);
+ }
+ }
+ }
}
void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
{
- if (host->in_bus_reset) {
- HPSB_VERBOSE("Including SelfID 0x%x", sid);
- host->topology_map[host->selfid_count++] = sid;
- } else {
- HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
+ if (host->in_bus_reset) {
+ HPSB_VERBOSE("Including SelfID 0x%x", sid);
+ host->topology_map[host->selfid_count++] = sid;
+ } else {
+ HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
sid, NODEID_TO_BUS(host->node_id));
- }
+ }
}
void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
@@ -367,50 +373,50 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
if (!host->in_bus_reset)
HPSB_NOTICE("SelfID completion called outside of bus reset!");
- host->node_id = LOCAL_BUS | phyid;
- host->is_root = isroot;
+ host->node_id = LOCAL_BUS | phyid;
+ host->is_root = isroot;
- if (!check_selfids(host)) {
- if (host->reset_retries++ < 20) {
- /* selfid stage did not complete without error */
- HPSB_NOTICE("Error in SelfID stage, resetting");
+ if (!check_selfids(host)) {
+ if (host->reset_retries++ < 20) {
+ /* selfid stage did not complete without error */
+ HPSB_NOTICE("Error in SelfID stage, resetting");
host->in_bus_reset = 0;
/* this should work from ohci1394 now... */
- hpsb_reset_bus(host, LONG_RESET);
- return;
- } else {
- HPSB_NOTICE("Stopping out-of-control reset loop");
- HPSB_NOTICE("Warning - topology map and speed map will not be valid");
+ hpsb_reset_bus(host, LONG_RESET);
+ return;
+ } else {
+ HPSB_NOTICE("Stopping out-of-control reset loop");
+ HPSB_NOTICE("Warning - topology map and speed map will not be valid");
host->reset_retries = 0;
- }
- } else {
+ }
+ } else {
host->reset_retries = 0;
- build_speed_map(host, host->node_count);
- }
+ build_speed_map(host, host->node_count);
+ }
HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
"... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
- /* irm_id is kept up to date by check_selfids() */
- if (host->irm_id == host->node_id) {
- host->is_irm = 1;
- } else {
- host->is_busmgr = 0;
- host->is_irm = 0;
- }
+ /* irm_id is kept up to date by check_selfids() */
+ if (host->irm_id == host->node_id) {
+ host->is_irm = 1;
+ } else {
+ host->is_busmgr = 0;
+ host->is_irm = 0;
+ }
- if (isroot) {
+ if (isroot) {
host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
host->is_cycmst = 1;
}
atomic_inc(&host->generation);
host->in_bus_reset = 0;
- highlevel_host_reset(host);
+ highlevel_host_reset(host);
}
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
- int ackcode)
+ int ackcode)
{
unsigned long flags;
@@ -457,6 +463,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
{
struct hpsb_packet *packet;
+ quadlet_t d = 0;
int retval = 0;
if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
@@ -466,26 +473,16 @@ int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
return -EINVAL;
}
- packet = hpsb_alloc_packet(0);
- if (!packet)
- return -ENOMEM;
-
- packet->host = host;
- packet->header_size = 8;
- packet->data_size = 0;
- packet->expect_response = 0;
- packet->no_waiter = 0;
- packet->type = hpsb_raw;
- packet->header[0] = 0;
if (rootid != -1)
- packet->header[0] |= rootid << 24 | 1 << 23;
+ d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
if (gapcnt != -1)
- packet->header[0] |= gapcnt << 16 | 1 << 22;
+ d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
- packet->header[1] = ~packet->header[0];
+ packet = hpsb_make_phypacket(host, d);
+ if (!packet)
+ return -ENOMEM;
packet->generation = get_hpsb_generation(host);
-
retval = hpsb_send_packet_and_wait(packet);
hpsb_free_packet(packet);
@@ -510,13 +507,13 @@ int hpsb_send_packet(struct hpsb_packet *packet)
{
struct hpsb_host *host = packet->host;
- if (host->is_shutdown)
+ if (host->is_shutdown)
return -EINVAL;
if (host->in_bus_reset ||
(packet->generation != get_hpsb_generation(host)))
- return -EAGAIN;
+ return -EAGAIN;
- packet->state = hpsb_queued;
+ packet->state = hpsb_queued;
/* This just seems silly to me */
WARN_ON(packet->no_waiter && packet->expect_response);
@@ -530,42 +527,42 @@ int hpsb_send_packet(struct hpsb_packet *packet)
skb_queue_tail(&host->pending_packet_queue, packet->skb);
}
- if (packet->node_id == host->node_id) {
+ if (packet->node_id == host->node_id) {
/* it is a local request, so handle it locally */
- quadlet_t *data;
- size_t size = packet->data_size + packet->header_size;
+ quadlet_t *data;
+ size_t size = packet->data_size + packet->header_size;
- data = kmalloc(size, GFP_ATOMIC);
- if (!data) {
- HPSB_ERR("unable to allocate memory for concatenating header and data");
- return -ENOMEM;
- }
+ data = kmalloc(size, GFP_ATOMIC);
+ if (!data) {
+ HPSB_ERR("unable to allocate memory for concatenating header and data");
+ return -ENOMEM;
+ }
- memcpy(data, packet->header, packet->header_size);
+ memcpy(data, packet->header, packet->header_size);
- if (packet->data_size)
+ if (packet->data_size)
memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
- dump_packet("send packet local", packet->header, packet->header_size, -1);
+ dump_packet("send packet local", packet->header, packet->header_size, -1);
- hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
- hpsb_packet_received(host, data, size, 0);
+ hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
+ hpsb_packet_received(host, data, size, 0);
- kfree(data);
+ kfree(data);
- return 0;
- }
+ return 0;
+ }
- if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
- packet->speed_code =
- host->speed_map[NODEID_TO_NODE(host->node_id) * 64
- + NODEID_TO_NODE(packet->node_id)];
- }
+ if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
+ packet->speed_code =
+ host->speed_map[NODEID_TO_NODE(host->node_id) * 64
+ + NODEID_TO_NODE(packet->node_id)];
+ }
- dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
+ dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
- return host->driver->transmit_packet(host, packet);
+ return host->driver->transmit_packet(host, packet);
}
/* We could just use complete() directly as the packet complete
@@ -593,81 +590,81 @@ int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
static void send_packet_nocare(struct hpsb_packet *packet)
{
- if (hpsb_send_packet(packet) < 0) {
- hpsb_free_packet(packet);
- }
+ if (hpsb_send_packet(packet) < 0) {
+ hpsb_free_packet(packet);
+ }
}
static void handle_packet_response(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size)
{
- struct hpsb_packet *packet = NULL;
+ struct hpsb_packet *packet = NULL;
struct sk_buff *skb;
- int tcode_match = 0;
- int tlabel;
- unsigned long flags;
+ int tcode_match = 0;
+ int tlabel;
+ unsigned long flags;
- tlabel = (data[0] >> 10) & 0x3f;
+ tlabel = (data[0] >> 10) & 0x3f;
spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
skb_queue_walk(&host->pending_packet_queue, skb) {
packet = (struct hpsb_packet *)skb->data;
- if ((packet->tlabel == tlabel)
- && (packet->node_id == (data[1] >> 16))){
- break;
- }
+ if ((packet->tlabel == tlabel)
+ && (packet->node_id == (data[1] >> 16))){
+ break;
+ }
packet = NULL;
- }
+ }
if (packet == NULL) {
- HPSB_DEBUG("unsolicited response packet received - no tlabel match");
- dump_packet("contents", data, 16, -1);
+ HPSB_DEBUG("unsolicited response packet received - no tlabel match");
+ dump_packet("contents", data, 16, -1);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
- return;
- }
+ return;
+ }
- switch (packet->tcode) {
- case TCODE_WRITEQ:
- case TCODE_WRITEB:
- if (tcode != TCODE_WRITE_RESPONSE)
+ switch (packet->tcode) {
+ case TCODE_WRITEQ:
+ case TCODE_WRITEB:
+ if (tcode != TCODE_WRITE_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 12);
- break;
- case TCODE_READQ:
- if (tcode != TCODE_READQ_RESPONSE)
+ break;
+ case TCODE_READQ:
+ if (tcode != TCODE_READQ_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 16);
- break;
- case TCODE_READB:
- if (tcode != TCODE_READB_RESPONSE)
+ break;
+ case TCODE_READB:
+ if (tcode != TCODE_READB_RESPONSE)
break;
tcode_match = 1;
BUG_ON(packet->skb->len - sizeof(*packet) < size - 16);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size - 16);
- break;
- case TCODE_LOCK_REQUEST:
- if (tcode != TCODE_LOCK_RESPONSE)
+ break;
+ case TCODE_LOCK_REQUEST:
+ if (tcode != TCODE_LOCK_RESPONSE)
break;
tcode_match = 1;
size = min((size - 16), (size_t)8);
BUG_ON(packet->skb->len - sizeof(*packet) < size);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size);
- break;
- }
+ break;
+ }
- if (!tcode_match) {
+ if (!tcode_match) {
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
- HPSB_INFO("unsolicited response packet received - tcode mismatch");
- dump_packet("contents", data, 16, -1);
- return;
- }
+ HPSB_INFO("unsolicited response packet received - tcode mismatch");
+ dump_packet("contents", data, 16, -1);
+ return;
+ }
__skb_unlink(skb, &host->pending_packet_queue);
@@ -686,27 +683,27 @@ static void handle_packet_response(struct hpsb_host *host, int tcode,
static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
quadlet_t *data, size_t dsize)
{
- struct hpsb_packet *p;
+ struct hpsb_packet *p;
- p = hpsb_alloc_packet(dsize);
- if (unlikely(p == NULL)) {
- /* FIXME - send data_error response */
- return NULL;
- }
+ p = hpsb_alloc_packet(dsize);
+ if (unlikely(p == NULL)) {
+ /* FIXME - send data_error response */
+ return NULL;
+ }
- p->type = hpsb_async;
- p->state = hpsb_unused;
- p->host = host;
- p->node_id = data[1] >> 16;
- p->tlabel = (data[0] >> 10) & 0x3f;
- p->no_waiter = 1;
+ p->type = hpsb_async;
+ p->state = hpsb_unused;
+ p->host = host;
+ p->node_id = data[1] >> 16;
+ p->tlabel = (data[0] >> 10) & 0x3f;
+ p->no_waiter = 1;
p->generation = get_hpsb_generation(host);
if (dsize % 4)
p->data[dsize / 4] = 0;
- return p;
+ return p;
}
#define PREP_ASYNC_HEAD_RCODE(tc) \
@@ -717,7 +714,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
packet->header[2] = 0
static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
- quadlet_t data)
+ quadlet_t data)
{
PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
packet->header[3] = data;
@@ -726,7 +723,7 @@ static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
}
static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
- int length)
+ int length)
{
if (rcode != RCODE_COMPLETE)
length = 0;
@@ -746,7 +743,7 @@ static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
}
static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
- int length)
+ int length)
{
if (rcode != RCODE_COMPLETE)
length = 0;
@@ -758,184 +755,184 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc
}
#define PREP_REPLY_PACKET(length) \
- packet = create_reply_packet(host, data, length); \
- if (packet == NULL) break
+ packet = create_reply_packet(host, data, length); \
+ if (packet == NULL) break
static void handle_incoming_packet(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size, int write_acked)
{
- struct hpsb_packet *packet;
- int length, rcode, extcode;
- quadlet_t buffer;
- nodeid_t source = data[1] >> 16;
- nodeid_t dest = data[0] >> 16;
- u16 flags = (u16) data[0];
- u64 addr;
-
- /* big FIXME - no error checking is done for an out of bounds length */
-
- switch (tcode) {
- case TCODE_WRITEQ:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_write(host, source, dest, data+3,
+ struct hpsb_packet *packet;
+ int length, rcode, extcode;
+ quadlet_t buffer;
+ nodeid_t source = data[1] >> 16;
+ nodeid_t dest = data[0] >> 16;
+ u16 flags = (u16) data[0];
+ u64 addr;
+
+ /* big FIXME - no error checking is done for an out of bounds length */
+
+ switch (tcode) {
+ case TCODE_WRITEQ:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_write(host, source, dest, data+3,
addr, 4, flags);
- if (!write_acked
- && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
- && (rcode >= 0)) {
- /* not a broadcast write, reply */
- PREP_REPLY_PACKET(0);
- fill_async_write_resp(packet, rcode);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_WRITEB:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_write(host, source, dest, data+4,
+ if (!write_acked
+ && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+ && (rcode >= 0)) {
+ /* not a broadcast write, reply */
+ PREP_REPLY_PACKET(0);
+ fill_async_write_resp(packet, rcode);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_WRITEB:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_write(host, source, dest, data+4,
addr, data[3]>>16, flags);
- if (!write_acked
- && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
- && (rcode >= 0)) {
- /* not a broadcast write, reply */
- PREP_REPLY_PACKET(0);
- fill_async_write_resp(packet, rcode);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_READQ:
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
-
- if (rcode >= 0) {
- PREP_REPLY_PACKET(0);
- fill_async_readquad_resp(packet, rcode, buffer);
- send_packet_nocare(packet);
- }
- break;
-
- case TCODE_READB:
- length = data[3] >> 16;
- PREP_REPLY_PACKET(length);
-
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
- rcode = highlevel_read(host, source, packet->data, addr,
- length, flags);
-
- if (rcode >= 0) {
- fill_async_readblock_resp(packet, rcode, length);
- send_packet_nocare(packet);
- } else {
- hpsb_free_packet(packet);
- }
- break;
-
- case TCODE_LOCK_REQUEST:
- length = data[3] >> 16;
- extcode = data[3] & 0xffff;
- addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-
- PREP_REPLY_PACKET(8);
-
- if ((extcode == 0) || (extcode >= 7)) {
- /* let switch default handle error */
- length = 0;
- }
-
- switch (length) {
- case 4:
- rcode = highlevel_lock(host, source, packet->data, addr,
- data[4], 0, extcode,flags);
- fill_async_lock_resp(packet, rcode, extcode, 4);
- break;
- case 8:
- if ((extcode != EXTCODE_FETCH_ADD)
- && (extcode != EXTCODE_LITTLE_ADD)) {
- rcode = highlevel_lock(host, source,
- packet->data, addr,
- data[5], data[4],
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 4);
- } else {
- rcode = highlevel_lock64(host, source,
- (octlet_t *)packet->data, addr,
- *(octlet_t *)(data + 4), 0ULL,
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 8);
- }
- break;
- case 16:
- rcode = highlevel_lock64(host, source,
- (octlet_t *)packet->data, addr,
- *(octlet_t *)(data + 6),
- *(octlet_t *)(data + 4),
- extcode, flags);
- fill_async_lock_resp(packet, rcode, extcode, 8);
- break;
- default:
- rcode = RCODE_TYPE_ERROR;
- fill_async_lock_resp(packet, rcode,
- extcode, 0);
- }
-
- if (rcode >= 0) {
- send_packet_nocare(packet);
- } else {
- hpsb_free_packet(packet);
- }
- break;
- }
+ if (!write_acked
+ && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
+ && (rcode >= 0)) {
+ /* not a broadcast write, reply */
+ PREP_REPLY_PACKET(0);
+ fill_async_write_resp(packet, rcode);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_READQ:
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
+
+ if (rcode >= 0) {
+ PREP_REPLY_PACKET(0);
+ fill_async_readquad_resp(packet, rcode, buffer);
+ send_packet_nocare(packet);
+ }
+ break;
+
+ case TCODE_READB:
+ length = data[3] >> 16;
+ PREP_REPLY_PACKET(length);
+
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+ rcode = highlevel_read(host, source, packet->data, addr,
+ length, flags);
+
+ if (rcode >= 0) {
+ fill_async_readblock_resp(packet, rcode, length);
+ send_packet_nocare(packet);
+ } else {
+ hpsb_free_packet(packet);
+ }
+ break;
+
+ case TCODE_LOCK_REQUEST:
+ length = data[3] >> 16;
+ extcode = data[3] & 0xffff;
+ addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+
+ PREP_REPLY_PACKET(8);
+
+ if ((extcode == 0) || (extcode >= 7)) {
+ /* let switch default handle error */
+ length = 0;
+ }
+
+ switch (length) {
+ case 4:
+ rcode = highlevel_lock(host, source, packet->data, addr,
+ data[4], 0, extcode,flags);
+ fill_async_lock_resp(packet, rcode, extcode, 4);
+ break;
+ case 8:
+ if ((extcode != EXTCODE_FETCH_ADD)
+ && (extcode != EXTCODE_LITTLE_ADD)) {
+ rcode = highlevel_lock(host, source,
+ packet->data, addr,
+ data[5], data[4],
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 4);
+ } else {
+ rcode = highlevel_lock64(host, source,
+ (octlet_t *)packet->data, addr,
+ *(octlet_t *)(data + 4), 0ULL,
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 8);
+ }
+ break;
+ case 16:
+ rcode = highlevel_lock64(host, source,
+ (octlet_t *)packet->data, addr,
+ *(octlet_t *)(data + 6),
+ *(octlet_t *)(data + 4),
+ extcode, flags);
+ fill_async_lock_resp(packet, rcode, extcode, 8);
+ break;
+ default:
+ rcode = RCODE_TYPE_ERROR;
+ fill_async_lock_resp(packet, rcode,
+ extcode, 0);
+ }
+
+ if (rcode >= 0) {
+ send_packet_nocare(packet);
+ } else {
+ hpsb_free_packet(packet);
+ }
+ break;
+ }
}
#undef PREP_REPLY_PACKET
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
- int write_acked)
+ int write_acked)
{
- int tcode;
-
- if (host->in_bus_reset) {
- HPSB_INFO("received packet during reset; ignoring");
- return;
- }
-
- dump_packet("received packet", data, size, -1);
-
- tcode = (data[0] >> 4) & 0xf;
-
- switch (tcode) {
- case TCODE_WRITE_RESPONSE:
- case TCODE_READQ_RESPONSE:
- case TCODE_READB_RESPONSE:
- case TCODE_LOCK_RESPONSE:
- handle_packet_response(host, tcode, data, size);
- break;
-
- case TCODE_WRITEQ:
- case TCODE_WRITEB:
- case TCODE_READQ:
- case TCODE_READB:
- case TCODE_LOCK_REQUEST:
- handle_incoming_packet(host, tcode, data, size, write_acked);
- break;
-
-
- case TCODE_ISO_DATA:
- highlevel_iso_receive(host, data, size);
- break;
-
- case TCODE_CYCLE_START:
- /* simply ignore this packet if it is passed on */
- break;
-
- default:
- HPSB_NOTICE("received packet with bogus transaction code %d",
- tcode);
- break;
- }
+ int tcode;
+
+ if (host->in_bus_reset) {
+ HPSB_INFO("received packet during reset; ignoring");
+ return;
+ }
+
+ dump_packet("received packet", data, size, -1);
+
+ tcode = (data[0] >> 4) & 0xf;
+
+ switch (tcode) {
+ case TCODE_WRITE_RESPONSE:
+ case TCODE_READQ_RESPONSE:
+ case TCODE_READB_RESPONSE:
+ case TCODE_LOCK_RESPONSE:
+ handle_packet_response(host, tcode, data, size);
+ break;
+
+ case TCODE_WRITEQ:
+ case TCODE_WRITEB:
+ case TCODE_READQ:
+ case TCODE_READB:
+ case TCODE_LOCK_REQUEST:
+ handle_incoming_packet(host, tcode, data, size, write_acked);
+ break;
+
+
+ case TCODE_ISO_DATA:
+ highlevel_iso_receive(host, data, size);
+ break;
+
+ case TCODE_CYCLE_START:
+ /* simply ignore this packet if it is passed on */
+ break;
+
+ default:
+ HPSB_NOTICE("received packet with bogus transaction code %d",
+ tcode);
+ break;
+ }
}
@@ -1030,10 +1027,10 @@ static int hpsbpkt_thread(void *__hi)
daemonize("khpsbpkt");
+ current->flags |= PF_NOFREEZE;
+
while (1) {
if (down_interruptible(&khpsbpkt_sig)) {
- if (try_to_freeze())
- continue;
printk("khpsbpkt: received unexpected signal?!\n" );
break;
}
@@ -1129,7 +1126,7 @@ static int __init ieee1394_init(void)
nodemgr implements functionality required of ieee1394a-2000
IRMs */
hpsb_disable_irm = 1;
-
+
return 0;
}
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 0b31429d0a68..b35466023f00 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -10,8 +10,8 @@
struct hpsb_packet {
- /* This struct is basically read-only for hosts with the exception of
- * the data buffer contents and xnext - see below. */
+ /* This struct is basically read-only for hosts with the exception of
+ * the data buffer contents and xnext - see below. */
/* This can be used for host driver internal linking.
*
@@ -21,47 +21,47 @@ struct hpsb_packet {
* driver_list when free'ing it. */
struct list_head driver_list;
- nodeid_t node_id;
+ nodeid_t node_id;
- /* Async and Iso types should be clear, raw means send-as-is, do not
- * CRC! Byte swapping shall still be done in this case. */
- enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+ /* Async and Iso types should be clear, raw means send-as-is, do not
+ * CRC! Byte swapping shall still be done in this case. */
+ enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
- /* Okay, this is core internal and a no care for hosts.
- * queued = queued for sending
- * pending = sent, waiting for response
- * complete = processing completed, successful or not
- */
- enum {
- hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
- } __attribute__((packed)) state;
+ /* Okay, this is core internal and a no care for hosts.
+ * queued = queued for sending
+ * pending = sent, waiting for response
+ * complete = processing completed, successful or not
+ */
+ enum {
+ hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
+ } __attribute__((packed)) state;
- /* These are core internal. */
- signed char tlabel;
+ /* These are core internal. */
+ signed char tlabel;
signed char ack_code;
unsigned char tcode;
- unsigned expect_response:1;
- unsigned no_waiter:1;
+ unsigned expect_response:1;
+ unsigned no_waiter:1;
- /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
- unsigned speed_code:2;
+ /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
+ unsigned speed_code:2;
- /*
- * *header and *data are guaranteed to be 32-bit DMAable and may be
- * overwritten to allow in-place byte swapping. Neither of these is
- * CRCed (the sizes also don't include CRC), but contain space for at
- * least one additional quadlet to allow in-place CRCing. The memory is
- * also guaranteed to be DMA mappable.
- */
- quadlet_t *header;
- quadlet_t *data;
- size_t header_size;
- size_t data_size;
+ /*
+ * *header and *data are guaranteed to be 32-bit DMAable and may be
+ * overwritten to allow in-place byte swapping. Neither of these is
+ * CRCed (the sizes also don't include CRC), but contain space for at
+ * least one additional quadlet to allow in-place CRCing. The memory is
+ * also guaranteed to be DMA mappable.
+ */
+ quadlet_t *header;
+ quadlet_t *data;
+ size_t header_size;
+ size_t data_size;
- struct hpsb_host *host;
- unsigned int generation;
+ struct hpsb_host *host;
+ unsigned int generation;
atomic_t refcnt;
@@ -73,10 +73,10 @@ struct hpsb_packet {
/* XXX This is just a hack at the moment */
struct sk_buff *skb;
- /* Store jiffies for implementing bus timeouts. */
- unsigned long sendtime;
+ /* Store jiffies for implementing bus timeouts. */
+ unsigned long sendtime;
- quadlet_t embedded_header[5];
+ quadlet_t embedded_header[5];
};
/* Set a task for when a packet completes */
@@ -102,7 +102,7 @@ void hpsb_free_packet(struct hpsb_packet *packet);
*/
static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
{
- return atomic_read(&host->generation);
+ return atomic_read(&host->generation);
}
/*
@@ -157,7 +157,7 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
* from within a transmit packet routine.
*/
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
- int ackcode);
+ int ackcode);
/*
* Hand over received packet to the core. The contents of data are expected to
@@ -171,7 +171,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
* packet type.
*/
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
- int write_acked);
+ int write_acked);
/*
@@ -197,20 +197,20 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
* Block 15 (240-255) reserved for drivers under development, etc.
*/
-#define IEEE1394_MAJOR 171
+#define IEEE1394_MAJOR 171
-#define IEEE1394_MINOR_BLOCK_RAW1394 0
-#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
-#define IEEE1394_MINOR_BLOCK_DV1394 2
-#define IEEE1394_MINOR_BLOCK_AMDTP 3
+#define IEEE1394_MINOR_BLOCK_RAW1394 0
+#define IEEE1394_MINOR_BLOCK_VIDEO1394 1
+#define IEEE1394_MINOR_BLOCK_DV1394 2
+#define IEEE1394_MINOR_BLOCK_AMDTP 3
#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
-#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
-#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
+#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
+#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)
+#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
+#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16)
+#define IEEE1394_AMDTP_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_AMDTP * 16)
+#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */
static inline unsigned char ieee1394_file_to_instance(struct file *file)
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 0aa876360f9b..3fe2f6c4a253 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -22,7 +22,7 @@
#include "ieee1394_core.h"
#include "highlevel.h"
#include "nodemgr.h"
-
+#include "ieee1394_transactions.h"
#define PREP_ASYNC_HEAD_ADDRESS(tc) \
packet->tcode = tc; \
@@ -31,80 +31,82 @@
packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
packet->header[2] = addr & 0xffffffff
-
static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
- packet->header_size = 12;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
+ packet->header_size = 12;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_readblock(struct hpsb_packet *packet, u64 addr,
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
- packet->header[3] = length << 16;
- packet->header_size = 16;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
+ packet->header[3] = length << 16;
+ packet->header_size = 16;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
+static void fill_async_writequad(struct hpsb_packet *packet, u64 addr,
+ quadlet_t data)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
- packet->header[3] = data;
- packet->header_size = 16;
- packet->data_size = 0;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
+ packet->header[3] = data;
+ packet->header_size = 16;
+ packet->data_size = 0;
+ packet->expect_response = 1;
}
-static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
+static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr,
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
- packet->header[3] = length << 16;
- packet->header_size = 16;
- packet->expect_response = 1;
- packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
+ packet->header[3] = length << 16;
+ packet->header_size = 16;
+ packet->expect_response = 1;
+ packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
}
static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
- int length)
+ int length)
{
- PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
- packet->header[3] = (length << 16) | extcode;
- packet->header_size = 16;
- packet->data_size = length;
- packet->expect_response = 1;
+ PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
+ packet->header[3] = (length << 16) | extcode;
+ packet->header_size = 16;
+ packet->data_size = length;
+ packet->expect_response = 1;
}
static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
- int tag, int sync)
+ int tag, int sync)
{
- packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_ISO_DATA << 4) | sync;
+ packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+ | (TCODE_ISO_DATA << 4) | sync;
- packet->header_size = 4;
- packet->data_size = length;
- packet->type = hpsb_iso;
- packet->tcode = TCODE_ISO_DATA;
+ packet->header_size = 4;
+ packet->data_size = length;
+ packet->type = hpsb_iso;
+ packet->tcode = TCODE_ISO_DATA;
}
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{
- packet->header[0] = data;
- packet->header[1] = ~data;
- packet->header_size = 8;
- packet->data_size = 0;
- packet->expect_response = 0;
- packet->type = hpsb_raw; /* No CRC added */
- packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
+ packet->header[0] = data;
+ packet->header[1] = ~data;
+ packet->header_size = 8;
+ packet->data_size = 0;
+ packet->expect_response = 0;
+ packet->type = hpsb_raw; /* No CRC added */
+ packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */
}
static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
int channel, int tag, int sync)
{
packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_STREAM_DATA << 4) | sync;
+ | (TCODE_STREAM_DATA << 4) | sync;
packet->header_size = 4;
packet->data_size = length;
@@ -171,99 +173,96 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
*/
void hpsb_free_tlabel(struct hpsb_packet *packet)
{
- unsigned long flags;
+ unsigned long flags;
struct hpsb_tlabel_pool *tp;
tp = &packet->host->tpool[packet->node_id & NODE_MASK];
BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
- spin_lock_irqsave(&tp->lock, flags);
+ spin_lock_irqsave(&tp->lock, flags);
BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
- spin_unlock_irqrestore(&tp->lock, flags);
+ spin_unlock_irqrestore(&tp->lock, flags);
up(&tp->count);
}
-
-
int hpsb_packet_success(struct hpsb_packet *packet)
{
- switch (packet->ack_code) {
- case ACK_PENDING:
- switch ((packet->header[1] >> 12) & 0xf) {
- case RCODE_COMPLETE:
- return 0;
- case RCODE_CONFLICT_ERROR:
- return -EAGAIN;
- case RCODE_DATA_ERROR:
- return -EREMOTEIO;
- case RCODE_TYPE_ERROR:
- return -EACCES;
- case RCODE_ADDRESS_ERROR:
- return -EINVAL;
- default:
- HPSB_ERR("received reserved rcode %d from node %d",
- (packet->header[1] >> 12) & 0xf,
- packet->node_id);
- return -EAGAIN;
- }
- HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
-
- case ACK_BUSY_X:
- case ACK_BUSY_A:
- case ACK_BUSY_B:
- return -EBUSY;
-
- case ACK_TYPE_ERROR:
- return -EACCES;
-
- case ACK_COMPLETE:
- if (packet->tcode == TCODE_WRITEQ
- || packet->tcode == TCODE_WRITEB) {
- return 0;
- } else {
- HPSB_ERR("impossible ack_complete from node %d "
- "(tcode %d)", packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
-
- case ACK_DATA_ERROR:
- if (packet->tcode == TCODE_WRITEB
- || packet->tcode == TCODE_LOCK_REQUEST) {
- return -EAGAIN;
- } else {
- HPSB_ERR("impossible ack_data_error from node %d "
- "(tcode %d)", packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
- case ACK_ADDRESS_ERROR:
- return -EINVAL;
-
- case ACK_TARDY:
- case ACK_CONFLICT_ERROR:
- case ACKX_NONE:
- case ACKX_SEND_ERROR:
- case ACKX_ABORTED:
- case ACKX_TIMEOUT:
- /* error while sending */
- return -EAGAIN;
-
- default:
- HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
- packet->ack_code, packet->node_id, packet->tcode);
- return -EAGAIN;
- }
-
- HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
+ switch (packet->ack_code) {
+ case ACK_PENDING:
+ switch ((packet->header[1] >> 12) & 0xf) {
+ case RCODE_COMPLETE:
+ return 0;
+ case RCODE_CONFLICT_ERROR:
+ return -EAGAIN;
+ case RCODE_DATA_ERROR:
+ return -EREMOTEIO;
+ case RCODE_TYPE_ERROR:
+ return -EACCES;
+ case RCODE_ADDRESS_ERROR:
+ return -EINVAL;
+ default:
+ HPSB_ERR("received reserved rcode %d from node %d",
+ (packet->header[1] >> 12) & 0xf,
+ packet->node_id);
+ return -EAGAIN;
+ }
+ HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__);
+
+ case ACK_BUSY_X:
+ case ACK_BUSY_A:
+ case ACK_BUSY_B:
+ return -EBUSY;
+
+ case ACK_TYPE_ERROR:
+ return -EACCES;
+
+ case ACK_COMPLETE:
+ if (packet->tcode == TCODE_WRITEQ
+ || packet->tcode == TCODE_WRITEB) {
+ return 0;
+ } else {
+ HPSB_ERR("impossible ack_complete from node %d "
+ "(tcode %d)", packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ case ACK_DATA_ERROR:
+ if (packet->tcode == TCODE_WRITEB
+ || packet->tcode == TCODE_LOCK_REQUEST) {
+ return -EAGAIN;
+ } else {
+ HPSB_ERR("impossible ack_data_error from node %d "
+ "(tcode %d)", packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ case ACK_ADDRESS_ERROR:
+ return -EINVAL;
+
+ case ACK_TARDY:
+ case ACK_CONFLICT_ERROR:
+ case ACKX_NONE:
+ case ACKX_SEND_ERROR:
+ case ACKX_ABORTED:
+ case ACKX_TIMEOUT:
+ /* error while sending */
+ return -EAGAIN;
+
+ default:
+ HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
+ packet->ack_code, packet->node_id, packet->tcode);
+ return -EAGAIN;
+ }
+
+ HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
}
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, size_t length)
{
- struct hpsb_packet *packet;
+ struct hpsb_packet *packet;
if (length == 0)
return NULL;
@@ -288,8 +287,9 @@ struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
return packet;
}
-struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node,
- u64 addr, quadlet_t *buffer, size_t length)
+struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node,
+ u64 addr, quadlet_t * buffer,
+ size_t length)
{
struct hpsb_packet *packet;
@@ -300,7 +300,7 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
if (!packet)
return NULL;
- if (length % 4) { /* zero padding bytes */
+ if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
@@ -322,8 +322,9 @@ struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node
return packet;
}
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, int length,
- int channel, int tag, int sync)
+struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
+ int length, int channel, int tag,
+ int sync)
{
struct hpsb_packet *packet;
@@ -334,7 +335,7 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
if (!packet)
return NULL;
- if (length % 4) { /* zero padding bytes */
+ if (length % 4) { /* zero padding bytes */
packet->data[length >> 2] = 0;
}
packet->host = host;
@@ -352,14 +353,15 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer, i
}
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
- u64 addr, int extcode, quadlet_t *data,
- quadlet_t arg)
+ u64 addr, int extcode,
+ quadlet_t * data, quadlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(8);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
p->node_id = node;
@@ -388,15 +390,16 @@ struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
return p;
}
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node,
- u64 addr, int extcode, octlet_t *data,
- octlet_t arg)
+struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
+ nodeid_t node, u64 addr, int extcode,
+ octlet_t * data, octlet_t arg)
{
struct hpsb_packet *p;
u32 length;
p = hpsb_alloc_packet(16);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
p->node_id = node;
@@ -429,18 +432,18 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node
return p;
}
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host,
- quadlet_t data)
+struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
{
- struct hpsb_packet *p;
+ struct hpsb_packet *p;
- p = hpsb_alloc_packet(0);
- if (!p) return NULL;
+ p = hpsb_alloc_packet(0);
+ if (!p)
+ return NULL;
- p->host = host;
- fill_phy_packet(p, data);
+ p->host = host;
+ fill_phy_packet(p, data);
- return p;
+ return p;
}
struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
@@ -450,7 +453,8 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
struct hpsb_packet *p;
p = hpsb_alloc_packet(length);
- if (!p) return NULL;
+ if (!p)
+ return NULL;
p->host = host;
fill_iso_packet(p, length, channel, tag, sync);
@@ -466,47 +470,46 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
*/
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, quadlet_t *buffer, size_t length)
+ u64 addr, quadlet_t * buffer, size_t length)
{
- struct hpsb_packet *packet;
- int retval = 0;
+ struct hpsb_packet *packet;
+ int retval = 0;
- if (length == 0)
- return -EINVAL;
+ if (length == 0)
+ return -EINVAL;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_readpacket(host, node, addr, length);
- if (!packet) {
- return -ENOMEM;
- }
+ if (!packet) {
+ return -ENOMEM;
+ }
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_read_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
- if (retval == 0) {
- if (length == 4) {
- *buffer = packet->header[3];
- } else {
- memcpy(buffer, packet->data, length);
- }
- }
+ if (retval == 0) {
+ if (length == 4) {
+ *buffer = packet->header[3];
+ } else {
+ memcpy(buffer, packet->data, length);
+ }
+ }
-hpsb_read_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_read_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
-
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, quadlet_t *buffer, size_t length)
+ u64 addr, quadlet_t * buffer, size_t length)
{
struct hpsb_packet *packet;
int retval;
@@ -514,62 +517,61 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
if (length == 0)
return -EINVAL;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
- packet = hpsb_make_writepacket (host, node, addr, buffer, length);
+ packet = hpsb_make_writepacket(host, node, addr, buffer, length);
if (!packet)
return -ENOMEM;
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_write_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
-hpsb_write_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_write_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
#if 0
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
+ u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
{
- struct hpsb_packet *packet;
- int retval = 0;
+ struct hpsb_packet *packet;
+ int retval = 0;
- BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
+ BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
- if (!packet)
- return -ENOMEM;
+ if (!packet)
+ return -ENOMEM;
packet->generation = generation;
- retval = hpsb_send_packet_and_wait(packet);
+ retval = hpsb_send_packet_and_wait(packet);
if (retval < 0)
goto hpsb_lock_fail;
- retval = hpsb_packet_success(packet);
+ retval = hpsb_packet_success(packet);
- if (retval == 0) {
- *data = packet->data[0];
- }
+ if (retval == 0) {
+ *data = packet->data[0];
+ }
-hpsb_lock_fail:
- hpsb_free_tlabel(packet);
- hpsb_free_packet(packet);
+ hpsb_lock_fail:
+ hpsb_free_tlabel(packet);
+ hpsb_free_packet(packet);
- return retval;
+ return retval;
}
-
int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
- quadlet_t *buffer, size_t length, u32 specifier_id,
+ quadlet_t * buffer, size_t length, u32 specifier_id,
unsigned int version)
{
struct hpsb_packet *packet;
@@ -586,7 +588,8 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
return -ENOMEM;
packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
- packet->data[1] = cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+ packet->data[1] =
+ cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
memcpy(&(packet->data[2]), buffer, length - 8);
@@ -601,4 +604,4 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
return retval;
}
-#endif /* 0 */
+#endif /* 0 */
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
index 615541b8b90f..f26680ebef7c 100644
--- a/drivers/ieee1394/iso.c
+++ b/drivers/ieee1394/iso.c
@@ -36,20 +36,22 @@ void hpsb_iso_shutdown(struct hpsb_iso *iso)
kfree(iso);
}
-static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_iso_type type,
+static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
+ enum hpsb_iso_type type,
unsigned int data_buf_size,
unsigned int buf_packets,
- int channel,
- int dma_mode,
+ int channel, int dma_mode,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso
+ *))
{
struct hpsb_iso *iso;
int dma_direction;
/* make sure driver supports the ISO API */
if (!host->driver->isoctl) {
- printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n",
+ printk(KERN_INFO
+ "ieee1394: host driver '%s' does not support the rawiso API\n",
host->driver->name);
return NULL;
}
@@ -59,12 +61,13 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
if (buf_packets < 2)
buf_packets = 2;
- if ((dma_mode < HPSB_ISO_DMA_DEFAULT) || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
- dma_mode=HPSB_ISO_DMA_DEFAULT;
+ if ((dma_mode < HPSB_ISO_DMA_DEFAULT)
+ || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
+ dma_mode = HPSB_ISO_DMA_DEFAULT;
if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
- irq_interval = buf_packets / 4;
- if (irq_interval == 0) /* really interrupt for each packet*/
+ irq_interval = buf_packets / 4;
+ if (irq_interval == 0) /* really interrupt for each packet */
irq_interval = 1;
if (channel < -1 || channel >= 64)
@@ -76,7 +79,10 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
/* allocate and write the struct hpsb_iso */
- iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL);
+ iso =
+ kmalloc(sizeof(*iso) +
+ buf_packets * sizeof(struct hpsb_iso_packet_info),
+ GFP_KERNEL);
if (!iso)
return NULL;
@@ -111,17 +117,18 @@ static struct hpsb_iso* hpsb_iso_common_init(struct hpsb_host *host, enum hpsb_i
iso->prebuffer = 0;
/* allocate the packet buffer */
- if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
+ if (dma_region_alloc
+ (&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
goto err;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
-int hpsb_iso_n_ready(struct hpsb_iso* iso)
+int hpsb_iso_n_ready(struct hpsb_iso *iso)
{
unsigned long flags;
int val;
@@ -133,18 +140,19 @@ int hpsb_iso_n_ready(struct hpsb_iso* iso)
return val;
}
-
-struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int speed,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso *))
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
data_buf_size, buf_packets,
- channel, HPSB_ISO_DMA_DEFAULT, irq_interval, callback);
+ channel,
+ HPSB_ISO_DMA_DEFAULT,
+ irq_interval, callback);
if (!iso)
return NULL;
@@ -157,22 +165,23 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
iso->flags |= HPSB_ISO_DRIVER_INIT;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
-struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
+struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
int channel,
int dma_mode,
int irq_interval,
- void (*callback)(struct hpsb_iso*))
+ void (*callback) (struct hpsb_iso *))
{
struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
data_buf_size, buf_packets,
- channel, dma_mode, irq_interval, callback);
+ channel, dma_mode,
+ irq_interval, callback);
if (!iso)
return NULL;
@@ -183,7 +192,7 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
iso->flags |= HPSB_ISO_DRIVER_INIT;
return iso;
-err:
+ err:
hpsb_iso_shutdown(iso);
return NULL;
}
@@ -197,16 +206,17 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
{
- if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
- return -EINVAL;
- return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
+ if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
+ return -EINVAL;
+ return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
}
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
{
if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
return -EINVAL;
- return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask);
+ return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK,
+ (unsigned long)&mask);
}
int hpsb_iso_recv_flush(struct hpsb_iso *iso)
@@ -283,7 +293,9 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
isoctl_args[2] = sync;
- retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]);
+ retval =
+ iso->host->driver->isoctl(iso, RECV_START,
+ (unsigned long)&isoctl_args[0]);
if (retval)
return retval;
@@ -296,7 +308,8 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
unsigned int offset, unsigned short len,
- unsigned int *out_offset, unsigned short *out_len)
+ unsigned int *out_offset,
+ unsigned short *out_len)
{
if (offset >= iso->buf_size)
return -EFAULT;
@@ -316,8 +329,8 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
return 0;
}
-
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy)
+int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
+ u8 tag, u8 sy)
{
struct hpsb_iso_packet_info *info;
unsigned long flags;
@@ -334,7 +347,8 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
info = &iso->infos[iso->first_packet];
/* check for bogus offset/length */
- if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len))
+ if (hpsb_iso_check_offset_len
+ (iso, offset, len, &info->offset, &info->len))
return -EFAULT;
info->tag = tag;
@@ -342,13 +356,13 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
spin_lock_irqsave(&iso->lock, flags);
- rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info);
+ rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info);
if (rv)
goto out;
/* increment cursors */
- iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
- iso->xmit_cycle = (iso->xmit_cycle+1) % 8000;
+ iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
+ iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000;
iso->n_ready_packets--;
if (iso->prebuffer != 0) {
@@ -359,7 +373,7 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag
}
}
-out:
+ out:
spin_unlock_irqrestore(&iso->lock, flags);
return rv;
}
@@ -369,7 +383,9 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
if (iso->type != HPSB_ISO_XMIT)
return -EINVAL;
- return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets);
+ return wait_event_interruptible(iso->waitq,
+ hpsb_iso_n_ready(iso) ==
+ iso->buf_packets);
}
void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
@@ -396,7 +412,8 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
}
void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
- u16 total_len, u16 cycle, u8 channel, u8 tag, u8 sy)
+ u16 total_len, u16 cycle, u8 channel, u8 tag,
+ u8 sy)
{
unsigned long flags;
spin_lock_irqsave(&iso->lock, flags);
@@ -416,7 +433,7 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
info->tag = tag;
info->sy = sy;
- iso->pkt_dma = (iso->pkt_dma+1) % iso->buf_packets;
+ iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
iso->n_ready_packets++;
}
@@ -435,20 +452,21 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
spin_lock_irqsave(&iso->lock, flags);
for (i = 0; i < n_packets; i++) {
rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
- (unsigned long) &iso->infos[iso->first_packet]);
+ (unsigned long)&iso->infos[iso->
+ first_packet]);
if (rv)
break;
- iso->first_packet = (iso->first_packet+1) % iso->buf_packets;
+ iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
iso->n_ready_packets--;
/* release memory from packets discarded when queue was full */
- if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
+ if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */
if (iso->bytes_discarded != 0) {
struct hpsb_iso_packet_info inf;
inf.total_len = iso->bytes_discarded;
iso->host->driver->isoctl(iso, RECV_RELEASE,
- (unsigned long) &inf);
+ (unsigned long)&inf);
iso->bytes_discarded = 0;
}
}
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 0ea37b1bccb2..082c7fd239f5 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -121,8 +121,8 @@ struct host_info {
};
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size);
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
static struct node_entry *find_entry_by_guid(u64 guid);
@@ -162,7 +162,7 @@ static void ud_cls_release(struct class_device *class_dev)
static struct class nodemgr_ud_class = {
.name = "ieee1394",
.release = ud_cls_release,
- .hotplug = nodemgr_hotplug,
+ .uevent = nodemgr_uevent,
};
static struct hpsb_highlevel nodemgr_highlevel;
@@ -743,21 +743,20 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
unsigned int generation)
{
struct hpsb_host *host = hi->host;
- struct node_entry *ne;
-
- ne = kmalloc(sizeof(struct node_entry), GFP_KERNEL);
- if (!ne) return NULL;
+ struct node_entry *ne;
- memset(ne, 0, sizeof(struct node_entry));
+ ne = kzalloc(sizeof(*ne), GFP_KERNEL);
+ if (!ne)
+ return NULL;
ne->tpool = &host->tpool[nodeid & NODE_MASK];
- ne->host = host;
- ne->nodeid = nodeid;
+ ne->host = host;
+ ne->nodeid = nodeid;
ne->generation = generation;
ne->needs_probe = 1;
- ne->guid = guid;
+ ne->guid = guid;
ne->guid_vendor_id = (guid >> 40) & 0xffffff;
ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id);
ne->csr = csr;
@@ -787,7 +786,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
(host->node_id == nodeid) ? "Host" : "Node",
NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
- return ne;
+ return ne;
}
@@ -872,12 +871,10 @@ static struct unit_directory *nodemgr_process_unit_directory
struct csr1212_keyval *kv;
u8 last_key_id = 0;
- ud = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+ ud = kzalloc(sizeof(*ud), GFP_KERNEL);
if (!ud)
goto unit_directory_error;
- memset (ud, 0, sizeof(struct unit_directory));
-
ud->ne = ne;
ud->ignore_driver = ignore_drivers;
ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
@@ -937,10 +934,10 @@ static struct unit_directory *nodemgr_process_unit_directory
/* Logical Unit Number */
if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
- ud_child = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+ ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL);
if (!ud_child)
goto unit_directory_error;
- memcpy(ud_child, ud, sizeof(struct unit_directory));
+ memcpy(ud_child, ud, sizeof(*ud_child));
nodemgr_register_device(ne, ud_child, &ne->device);
ud_child = NULL;
@@ -966,7 +963,7 @@ static struct unit_directory *nodemgr_process_unit_directory
if (ud_child == NULL)
break;
- /* inherit unspecified values so hotplug picks it up */
+ /* inherit unspecified values, the driver core picks it up */
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
!(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
{
@@ -1062,8 +1059,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
#ifdef CONFIG_HOTPLUG
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct unit_directory *ud;
int i = 0;
@@ -1112,8 +1109,8 @@ do { \
#else
-static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -1200,7 +1197,7 @@ static void nodemgr_node_scan_one(struct host_info *hi,
struct csr1212_csr *csr;
struct nodemgr_csr_info *ci;
- ci = kmalloc(sizeof(struct nodemgr_csr_info), GFP_KERNEL);
+ ci = kmalloc(sizeof(*ci), GFP_KERNEL);
if (!ci)
return;
@@ -1410,14 +1407,28 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
struct hpsb_host *host = hi->host;
struct class *class = &nodemgr_ne_class;
struct class_device *cdev;
+ struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them
* into the sysfs layer if needed, and can result in processing of
* unit-directories, or just updating the node and it's
- * unit-directories. */
+ * unit-directories.
+ *
+ * Run updates before probes. Usually, updates are time-critical
+ * while probes are time-consuming. (Well, those probes need some
+ * improvement...) */
+
down_read(&class->subsys.rwsem);
- list_for_each_entry(cdev, &class->children, node)
- nodemgr_probe_ne(hi, container_of(cdev, struct node_entry, class_dev), generation);
+ list_for_each_entry(cdev, &class->children, node) {
+ ne = container_of(cdev, struct node_entry, class_dev);
+ if (!ne->needs_probe)
+ nodemgr_probe_ne(hi, ne, generation);
+ }
+ list_for_each_entry(cdev, &class->children, node) {
+ ne = container_of(cdev, struct node_entry, class_dev);
+ if (ne->needs_probe)
+ nodemgr_probe_ne(hi, ne, generation);
+ }
up_read(&class->subsys.rwsem);
@@ -1448,7 +1459,8 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host)
int ret = 1;
packet = hpsb_make_phypacket(host,
- 0x003c0000 | NODEID_TO_NODE(host->node_id) << 24);
+ EXTPHYPACKET_TYPE_RESUME |
+ NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT);
if (packet) {
packet->no_waiter = 1;
packet->generation = get_hpsb_generation(host);
@@ -1618,8 +1630,8 @@ static int nodemgr_host_thread(void *__hi)
/* Scan our nodes to get the bus options and create node
* entries. This does not do the sysfs stuff, since that
- * would trigger hotplug callbacks and such, which is a
- * bad idea at this point. */
+ * would trigger uevents and such, which is a bad idea at
+ * this point. */
nodemgr_node_scan(hi, generation);
/* This actually does the full probe, with sysfs
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 3a2f0c02fd08..0b26616e16c3 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -151,24 +151,6 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
}
/*
- * Returns a node entry (which has its reference count incremented) or NULL if
- * the GUID in question is not known. Getting a valid entry does not mean that
- * the node with this GUID is currently accessible (might be powered down).
- */
-struct node_entry *hpsb_guid_get_entry(u64 guid);
-
-/* Same as above, but use the nodeid to get an node entry. This is not
- * fool-proof by itself, since the nodeid can change. */
-struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid);
-
-/*
- * If the entry refers to a local host, this function will return the pointer
- * to the hpsb_host structure. It will return NULL otherwise. Once you have
- * established it is a local host, you can use that knowledge from then on (the
- * GUID won't wander to an external node). */
-struct hpsb_host *hpsb_get_host_by_ne(struct node_entry *ne);
-
-/*
* This will fill in the given, pre-initialised hpsb_packet with the current
* information from the node entry (host, node ID, generation number). It will
* return false if the node owning the GUID is not accessible (and not modify the
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 4cf9b8f3e336..b6b96fa04d62 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -161,9 +161,6 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
#define PRINT(level, fmt, args...) \
printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-static char version[] __devinitdata =
- "$Rev: 1313 $ Ben Collins <bcollins@debian.org>";
-
/* Module Parameters */
static int phys_dma = 1;
module_param(phys_dma, int, 0644);
@@ -587,12 +584,13 @@ static void ohci_initialize(struct ti_ohci *ohci)
sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
#endif
PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] "
- "MMIO=[%lx-%lx] Max Packet=[%d]",
+ "MMIO=[%lx-%lx] Max Packet=[%d] IR/IT contexts=[%d/%d]",
((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
pci_resource_start(ohci->dev, 0),
pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
- ohci->max_packet_size);
+ ohci->max_packet_size,
+ ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
/* Check all of our ports to make sure that if anything is
* connected, we enable that port. */
@@ -2960,28 +2958,23 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
d->ctrlClear = 0;
d->cmdPtr = 0;
- d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_ATOMIC);
- d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+ d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
+ d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
if (d->buf_cpu == NULL || d->buf_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate dma buffer");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
- memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
- memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t));
- d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*),
- GFP_ATOMIC);
- d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_ATOMIC);
+ d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate dma prg");
free_dma_rcv_ctx(d);
return -ENOMEM;
}
- memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
- memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
@@ -3093,17 +3086,14 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
d->ctrlClear = 0;
d->cmdPtr = 0;
- d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*),
- GFP_KERNEL);
- d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+ d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
+ d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, "Failed to allocate at dma prg");
free_dma_trm_ctx(d);
return -ENOMEM;
}
- memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*));
- memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
len = sprintf(pool_name, "ohci1394_trm_prg");
sprintf(pool_name+len, "%d", num_allocs);
@@ -3201,8 +3191,6 @@ static struct hpsb_host_driver ohci1394_driver = {
.hw_csr_reg = ohci_hw_csr_reg,
};
-
-
/***********************************
* PCI Driver Interface functions *
***********************************/
@@ -3217,15 +3205,10 @@ do { \
static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
- static int version_printed = 0;
-
struct hpsb_host *host;
struct ti_ohci *ohci; /* shortcut to currently handled device */
unsigned long ohci_base;
- if (version_printed++ == 0)
- PRINT_G(KERN_INFO, "%s", version);
-
if (pci_enable_device(dev))
FAIL(-ENXIO, "Failed to enable OHCI hardware");
pci_set_master(dev);
@@ -3369,13 +3352,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
/* Determine the number of available IR and IT contexts. */
ohci->nb_iso_rcv_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
- DBGMSG("%d iso receive contexts available",
- ohci->nb_iso_rcv_ctx);
-
ohci->nb_iso_xmit_ctx =
get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
- DBGMSG("%d iso transmit contexts available",
- ohci->nb_iso_xmit_ctx);
/* Set the usage bits for non-existent contexts so they can't
* be allocated */
@@ -3606,8 +3584,6 @@ static struct pci_driver ohci1394_pci_driver = {
.suspend = ohci1394_pci_suspend,
};
-
-
/***********************************
* OHCI1394 Video Interface *
***********************************/
@@ -3714,7 +3690,6 @@ EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
-
/***********************************
* General module initialization *
***********************************/
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index cc66c1cae250..7df0962144e3 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -219,8 +219,8 @@ struct ti_ohci {
int self_id_errors;
- /* Tasklets for iso receive and transmit, used by video1394,
- * amdtp and dv1394 */
+ /* Tasklets for iso receive and transmit, used by video1394
+ * and dv1394 */
struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 6b1ab875333b..e2edc41e1b6f 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1435,7 +1435,7 @@ static int __devinit add_card(struct pci_dev *dev,
struct i2c_algo_bit_data i2c_adapter_data;
error = -ENOMEM;
- i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL);
+ i2c_ad = kmalloc(sizeof(*i2c_ad), SLAB_KERNEL);
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 24411e666b21..b05235639918 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -102,12 +102,9 @@ static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
- req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
- flags);
- if (req != NULL) {
- memset(req, 0, sizeof(struct pending_request));
+ req = kzalloc(sizeof(*req), flags);
+ if (req)
INIT_LIST_HEAD(&req->list);
- }
return req;
}
@@ -192,9 +189,9 @@ static void add_host(struct hpsb_host *host)
struct host_info *hi;
unsigned long flags;
- hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
+ hi = kmalloc(sizeof(*hi), GFP_KERNEL);
- if (hi != NULL) {
+ if (hi) {
INIT_LIST_HEAD(&hi->list);
hi->host = host;
INIT_LIST_HEAD(&hi->file_info_list);
@@ -315,8 +312,8 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
break;
if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
+ ibs = kmalloc(sizeof(*ibs) + length,
+ SLAB_ATOMIC);
if (!ibs) {
kfree(req);
break;
@@ -376,8 +373,8 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
break;
if (!ibs) {
- ibs = kmalloc(sizeof(struct iso_block_store)
- + length, SLAB_ATOMIC);
+ ibs = kmalloc(sizeof(*ibs) + length,
+ SLAB_ATOMIC);
if (!ibs) {
kfree(req);
break;
@@ -502,10 +499,9 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
switch (req->req.type) {
case RAW1394_REQ_LIST_CARDS:
spin_lock_irqsave(&host_info_lock, flags);
- khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
- SLAB_ATOMIC);
+ khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC);
- if (khl != NULL) {
+ if (khl) {
req->req.misc = host_count;
req->data = (quadlet_t *) khl;
@@ -517,7 +513,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
}
spin_unlock_irqrestore(&host_info_lock, flags);
- if (khl != NULL) {
+ if (khl) {
req->req.error = RAW1394_ERROR_NONE;
req->req.length = min(req->req.length,
(u32) (sizeof
@@ -1647,13 +1643,13 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EINVAL);
}
/* addr-list-entry for fileinfo */
- addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL);
+ addr = kmalloc(sizeof(*addr), SLAB_KERNEL);
if (!addr) {
req->req.length = 0;
return (-ENOMEM);
}
/* allocation of addr_space_buffer */
- addr->addr_space_buffer = (u8 *) vmalloc(req->req.length);
+ addr->addr_space_buffer = vmalloc(req->req.length);
if (!(addr->addr_space_buffer)) {
kfree(addr);
req->req.length = 0;
@@ -2122,8 +2118,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
return -ENOMEM;
}
- cache->filled_head =
- kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
+ cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
if (!cache->filled_head) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
@@ -2136,7 +2131,6 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
req->req.length)) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
- CSR1212_FREE(cache);
ret = -EFAULT;
} else {
cache->len = req->req.length;
@@ -2172,7 +2166,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
}
}
kfree(cache->filled_head);
- kfree(cache);
+ CSR1212_FREE(cache);
if (ret >= 0) {
/* we have to free the request, because we queue no response,
@@ -2488,8 +2482,8 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_WRITE, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the packet_infos out */
@@ -2522,8 +2516,8 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_READ, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the infos structs in and queue the packets */
@@ -2684,11 +2678,10 @@ static int raw1394_open(struct inode *inode, struct file *file)
{
struct file_info *fi;
- fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
- if (fi == NULL)
+ fi = kzalloc(sizeof(*fi), SLAB_KERNEL);
+ if (!fi)
return -ENOMEM;
- memset(fi, 0, sizeof(struct file_info));
fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
INIT_LIST_HEAD(&fi->list);
@@ -2748,8 +2741,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
list) {
entry = fi_hlp->addr_list.next;
while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry,
- struct
+ arm_addr = list_entry(entry, struct
arm_addr,
addr_list);
if (arm_addr->start ==
@@ -2912,16 +2904,17 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- NULL, RAW1394_DEVICE_NAME))) {
+ if (IS_ERR
+ (class_device_create
+ (hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
-
- devfs_mk_cdev(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
+
+ devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+ S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
@@ -2943,20 +2936,22 @@ static int __init init_raw1394(void)
goto out;
-out_dev:
+ out_dev:
devfs_remove(RAW1394_DEVICE_NAME);
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-out_unreg:
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
-out:
+ out:
return ret;
}
static void __exit cleanup_raw1394(void)
{
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index f7e18ccc5c0a..18d7eda38851 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -80,9 +80,6 @@
#include "ieee1394_transactions.h"
#include "sbp2.h"
-static char version[] __devinitdata =
- "$Rev: 1306 $ Ben Collins <bcollins@debian.org>";
-
/*
* Module load parameter definitions
*/
@@ -151,18 +148,15 @@ static int force_inquiry_hack;
module_param(force_inquiry_hack, int, 0444);
MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");
-
/*
* Export information about protocols/devices supported by this driver.
*/
static struct ieee1394_device_id sbp2_id_table[] = {
{
- .match_flags =IEEE1394_MATCH_SPECIFIER_ID |
- IEEE1394_MATCH_VERSION,
- .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
- .version = SBP2_SW_VERSION_ENTRY & 0xffffff
- },
- { }
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+ .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
+ .version = SBP2_SW_VERSION_ENTRY & 0xffffff},
+ {}
};
MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
@@ -221,7 +215,6 @@ static u32 global_outstanding_dmas = 0;
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
-
/*
* Globals
*/
@@ -254,8 +247,8 @@ static struct hpsb_address_ops sbp2_ops = {
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
static struct hpsb_address_ops sbp2_physdma_ops = {
- .read = sbp2_handle_physdma_read,
- .write = sbp2_handle_physdma_write,
+ .read = sbp2_handle_physdma_read,
+ .write = sbp2_handle_physdma_write,
};
#endif
@@ -287,7 +280,6 @@ static u32 sbp2_broken_inquiry_list[] = {
* General utility functions
**************************************/
-
#ifndef __BIG_ENDIAN
/*
* Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
@@ -324,7 +316,8 @@ static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
/*
* Debug packet dump routine. Length is in bytes.
*/
-static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32 dump_phys_addr)
+static void sbp2util_packet_dump(void *buffer, int length, char *dump_name,
+ u32 dump_phys_addr)
{
int i;
unsigned char *dump = buffer;
@@ -345,7 +338,7 @@ static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32
printk(" ");
if ((i & 0xf) == 0)
printk("\n ");
- printk("%02x ", (int) dump[i]);
+ printk("%02x ", (int)dump[i]);
}
printk("\n");
@@ -364,9 +357,9 @@ static int sbp2util_down_timeout(atomic_t *done, int timeout)
for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {
if (msleep_interruptible(100)) /* 100ms */
- return(1);
+ return 1;
}
- return ((i > 0) ? 0:1);
+ return (i > 0) ? 0 : 1;
}
/* Free's an allocated packet */
@@ -380,21 +373,22 @@ static void sbp2_free_packet(struct hpsb_packet *packet)
* subaction and returns immediately. Can be used from interrupts.
*/
static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
- quadlet_t *buffer, size_t length)
+ quadlet_t *buffer, size_t length)
{
struct hpsb_packet *packet;
packet = hpsb_make_writepacket(ne->host, ne->nodeid,
addr, buffer, length);
- if (!packet)
- return -ENOMEM;
+ if (!packet)
+ return -ENOMEM;
- hpsb_set_packet_complete_task(packet, (void (*)(void*))sbp2_free_packet,
+ hpsb_set_packet_complete_task(packet,
+ (void (*)(void *))sbp2_free_packet,
packet);
hpsb_node_fill_packet(ne, packet);
- if (hpsb_send_packet(packet) < 0) {
+ if (hpsb_send_packet(packet) < 0) {
sbp2_free_packet(packet);
return -EIO;
}
@@ -417,22 +411,22 @@ static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_i
spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags);
for (i = 0; i < orbs; i++) {
- command = (struct sbp2_command_info *)
- kmalloc(sizeof(struct sbp2_command_info), GFP_ATOMIC);
+ command = kzalloc(sizeof(*command), GFP_ATOMIC);
if (!command) {
- spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return(-ENOMEM);
+ spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock,
+ flags);
+ return -ENOMEM;
}
- memset(command, '\0', sizeof(struct sbp2_command_info));
command->command_orb_dma =
- pci_map_single (hi->host->pdev, &command->command_orb,
- sizeof(struct sbp2_command_orb),
- PCI_DMA_BIDIRECTIONAL);
+ pci_map_single(hi->host->pdev, &command->command_orb,
+ sizeof(struct sbp2_command_orb),
+ PCI_DMA_BIDIRECTIONAL);
SBP2_DMA_ALLOC("single command orb DMA");
command->sge_dma =
- pci_map_single (hi->host->pdev, &command->scatter_gather_element,
- sizeof(command->scatter_gather_element),
- PCI_DMA_BIDIRECTIONAL);
+ pci_map_single(hi->host->pdev,
+ &command->scatter_gather_element,
+ sizeof(command->scatter_gather_element),
+ PCI_DMA_BIDIRECTIONAL);
SBP2_DMA_ALLOC("scatter_gather_element");
INIT_LIST_HEAD(&command->list);
list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed);
@@ -488,7 +482,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
if (command->command_orb_dma == orb) {
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
}
}
@@ -496,7 +490,7 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb(
SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb);
- return(NULL);
+ return NULL;
}
/*
@@ -513,12 +507,12 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_
list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) {
if (command->Current_SCpnt == SCpnt) {
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
}
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return(NULL);
+ return NULL;
}
/*
@@ -545,7 +539,7 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
SBP2_ERR("sbp2util_allocate_command_orb - No orbs available!");
}
spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags);
- return (command);
+ return command;
}
/* Free our DMA's */
@@ -587,7 +581,8 @@ static void sbp2util_free_command_dma(struct sbp2_command_info *command)
/*
* This function moves a command to the completed orb list.
*/
-static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command)
+static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command)
{
unsigned long flags;
@@ -606,8 +601,6 @@ static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_
return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo;
}
-
-
/*********************************************
* IEEE-1394 core driver stack related section
*********************************************/
@@ -627,14 +620,14 @@ static int sbp2_probe(struct device *dev)
if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
return -ENODEV;
- scsi_id = sbp2_alloc_device(ud);
+ scsi_id = sbp2_alloc_device(ud);
- if (!scsi_id)
- return -ENOMEM;
+ if (!scsi_id)
+ return -ENOMEM;
- sbp2_parse_unit_directory(scsi_id, ud);
+ sbp2_parse_unit_directory(scsi_id, ud);
- return sbp2_start_device(scsi_id);
+ return sbp2_start_device(scsi_id);
}
static int sbp2_remove(struct device *dev)
@@ -719,12 +712,11 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
SBP2_DEBUG("sbp2_alloc_device");
- scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL);
+ scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL);
if (!scsi_id) {
SBP2_ERR("failed to create scsi_id");
goto failed_alloc;
}
- memset(scsi_id, 0, sizeof(*scsi_id));
scsi_id->ne = ud->ne;
scsi_id->ud = ud;
@@ -735,7 +727,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
INIT_LIST_HEAD(&scsi_id->scsi_list);
spin_lock_init(&scsi_id->sbp2_command_orb_lock);
- scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED;
+ scsi_id->sbp2_lun = 0;
ud->device.driver_data = scsi_id;
@@ -769,7 +761,7 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
/* Register our host with the SCSI stack. */
scsi_host = scsi_host_alloc(&scsi_driver_template,
- sizeof (unsigned long));
+ sizeof(unsigned long));
if (!scsi_host) {
SBP2_ERR("failed to register scsi host");
goto failed_alloc;
@@ -790,7 +782,6 @@ failed_alloc:
return NULL;
}
-
static void sbp2_host_reset(struct hpsb_host *host)
{
struct sbp2scsi_host_info *hi;
@@ -804,7 +795,6 @@ static void sbp2_host_reset(struct hpsb_host *host)
}
}
-
/*
* This function is where we first pull the node unique ids, and then
* allocate memory and register a SBP-2 device.
@@ -818,7 +808,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Login FIFO DMA */
scsi_id->login_response =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_response),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_response),
&scsi_id->login_response_dma);
if (!scsi_id->login_response)
goto alloc_fail;
@@ -826,7 +817,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Query logins ORB DMA */
scsi_id->query_logins_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_query_logins_orb),
&scsi_id->query_logins_orb_dma);
if (!scsi_id->query_logins_orb)
goto alloc_fail;
@@ -834,7 +826,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Query logins response DMA */
scsi_id->query_logins_response =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_query_logins_response),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_query_logins_response),
&scsi_id->query_logins_response_dma);
if (!scsi_id->query_logins_response)
goto alloc_fail;
@@ -842,7 +835,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Reconnect ORB DMA */
scsi_id->reconnect_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_reconnect_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_reconnect_orb),
&scsi_id->reconnect_orb_dma);
if (!scsi_id->reconnect_orb)
goto alloc_fail;
@@ -850,7 +844,8 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Logout ORB DMA */
scsi_id->logout_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_logout_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_logout_orb),
&scsi_id->logout_orb_dma);
if (!scsi_id->logout_orb)
goto alloc_fail;
@@ -858,58 +853,11 @@ static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)
/* Login ORB DMA */
scsi_id->login_orb =
- pci_alloc_consistent(hi->host->pdev, sizeof(struct sbp2_login_orb),
+ pci_alloc_consistent(hi->host->pdev,
+ sizeof(struct sbp2_login_orb),
&scsi_id->login_orb_dma);
- if (!scsi_id->login_orb) {
-alloc_fail:
- if (scsi_id->query_logins_response) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_query_logins_response),
- scsi_id->query_logins_response,
- scsi_id->query_logins_response_dma);
- SBP2_DMA_FREE("query logins response DMA");
- }
-
- if (scsi_id->query_logins_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_query_logins_orb),
- scsi_id->query_logins_orb,
- scsi_id->query_logins_orb_dma);
- SBP2_DMA_FREE("query logins ORB DMA");
- }
-
- if (scsi_id->logout_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_logout_orb),
- scsi_id->logout_orb,
- scsi_id->logout_orb_dma);
- SBP2_DMA_FREE("logout ORB DMA");
- }
-
- if (scsi_id->reconnect_orb) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_reconnect_orb),
- scsi_id->reconnect_orb,
- scsi_id->reconnect_orb_dma);
- SBP2_DMA_FREE("reconnect ORB DMA");
- }
-
- if (scsi_id->login_response) {
- pci_free_consistent(hi->host->pdev,
- sizeof(struct sbp2_login_response),
- scsi_id->login_response,
- scsi_id->login_response_dma);
- SBP2_DMA_FREE("login FIFO DMA");
- }
-
- list_del(&scsi_id->scsi_list);
-
- kfree(scsi_id);
-
- SBP2_ERR ("Could not allocate memory for scsi_id");
-
- return -ENOMEM;
- }
+ if (!scsi_id->login_orb)
+ goto alloc_fail;
SBP2_DMA_ALLOC("consistent DMA region for login ORB");
SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id);
@@ -935,7 +883,7 @@ alloc_fail:
sbp2_remove_device(scsi_id);
return -EINTR;
}
-
+
/*
* Login to the sbp-2 device
*/
@@ -964,10 +912,17 @@ alloc_fail:
error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);
if (error) {
SBP2_ERR("scsi_add_device failed");
+ sbp2_logout_device(scsi_id);
+ sbp2_remove_device(scsi_id);
return error;
}
return 0;
+
+alloc_fail:
+ SBP2_ERR("Could not allocate memory for scsi_id");
+ sbp2_remove_device(scsi_id);
+ return -ENOMEM;
}
/*
@@ -1054,51 +1009,44 @@ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id)
* This function deals with physical dma write requests (for adapters that do not support
* physical dma in hardware). Mostly just here for debugging...
*/
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data,
- u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
+ int destid, quadlet_t *data, u64 addr,
+ size_t length, u16 flags)
{
- /*
- * Manually put the data in the right place.
- */
- memcpy(bus_to_virt((u32)addr), data, length);
- sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", (u32)addr);
- return(RCODE_COMPLETE);
+ /*
+ * Manually put the data in the right place.
+ */
+ memcpy(bus_to_virt((u32) addr), data, length);
+ sbp2util_packet_dump(data, length, "sbp2 phys dma write by device",
+ (u32) addr);
+ return RCODE_COMPLETE;
}
/*
* This function deals with physical dma read requests (for adapters that do not support
* physical dma in hardware). Mostly just here for debugging...
*/
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data,
- u64 addr, size_t length, u16 flags)
+static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
+ quadlet_t *data, u64 addr, size_t length,
+ u16 flags)
{
- /*
- * Grab data from memory and send a read response.
- */
- memcpy(data, bus_to_virt((u32)addr), length);
- sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", (u32)addr);
- return(RCODE_COMPLETE);
+ /*
+ * Grab data from memory and send a read response.
+ */
+ memcpy(data, bus_to_virt((u32) addr), length);
+ sbp2util_packet_dump(data, length, "sbp2 phys dma read by device",
+ (u32) addr);
+ return RCODE_COMPLETE;
}
#endif
-
/**************************************
* SBP-2 protocol related section
**************************************/
/*
- * This function determines if we should convert scsi commands for a particular sbp2 device type
- */
-static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
-{
- return (((device_type == TYPE_DISK) ||
- (device_type == TYPE_RBC) ||
- (device_type == TYPE_ROM)) ? 1:0);
-}
-
-/*
* This function queries the device for the maximum concurrent logins it
* supports.
*/
@@ -1120,11 +1068,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
- if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
- SBP2_DEBUG("sbp2_query_logins: set lun to %d",
- ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
- }
+ scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
SBP2_DEBUG("sbp2_query_logins: lun_misc initialized");
scsi_id->query_logins_orb->reserved_resp_length =
@@ -1161,12 +1105,12 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) ||
@@ -1174,7 +1118,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_INFO("Error querying logins to SBP-2 device - timed out");
- return(-EIO);
+ return -EIO;
}
sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response));
@@ -1191,7 +1135,7 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG("Number of active logins: %d", active_logins);
if (active_logins >= max_logins) {
- return(-EIO);
+ return -EIO;
}
return 0;
@@ -1210,13 +1154,13 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
if (!scsi_id->login_orb) {
SBP2_DEBUG("sbp2_login_device: login_orb not alloc'd!");
- return(-EIO);
+ return -EIO;
}
if (!exclusive_login) {
if (sbp2_query_logins(scsi_id)) {
SBP2_INFO("Device does not support any more concurrent logins");
- return(-EIO);
+ return -EIO;
}
}
@@ -1233,12 +1177,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */
scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */
scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */
- /* Set the lun if we were able to pull it from the device's unit directory */
- if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
- SBP2_DEBUG("sbp2_query_logins: set lun to %d",
- ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun));
- }
+ scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun);
SBP2_DEBUG("sbp2_login_device: lun_misc initialized");
scsi_id->login_orb->passwd_resp_lengths =
@@ -1288,7 +1227,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
*/
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) {
SBP2_ERR("Error logging into SBP-2 device - login timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1296,7 +1235,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) {
SBP2_ERR("Error logging into SBP-2 device - login timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1307,7 +1246,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_ERR("Error logging into SBP-2 device - login failed");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1331,7 +1270,7 @@ static int sbp2_login_device(struct scsi_id_instance_data *scsi_id)
SBP2_INFO("Logged into SBP-2 device");
- return(0);
+ return 0;
}
@@ -1385,8 +1324,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
atomic_set(&scsi_id->sbp2_login_complete, 0);
error = hpsb_node_write(scsi_id->ne,
- scsi_id->sbp2_management_agent_addr,
- data, 8);
+ scsi_id->sbp2_management_agent_addr, data, 8);
if (error)
return error;
@@ -1396,7 +1334,7 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id)
SBP2_INFO("Logged out of SBP-2 device");
- return(0);
+ return 0;
}
@@ -1456,8 +1394,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
atomic_set(&scsi_id->sbp2_login_complete, 0);
error = hpsb_node_write(scsi_id->ne,
- scsi_id->sbp2_management_agent_addr,
- data, 8);
+ scsi_id->sbp2_management_agent_addr, data, 8);
if (error)
return error;
@@ -1466,7 +1403,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
*/
if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1474,7 +1411,7 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
*/
if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out");
- return(-EIO);
+ return -EIO;
}
/*
@@ -1485,12 +1422,12 @@ static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id)
STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) {
SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed");
- return(-EIO);
+ return -EIO;
}
HPSB_DEBUG("Reconnected to SBP-2 device");
- return(0);
+ return 0;
}
@@ -1513,10 +1450,9 @@ static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id)
SBP2_ERR("sbp2_set_busy_timeout error");
}
- return(0);
+ return 0;
}
-
/*
* This function is called to parse sbp2 device's config rom unit
* directory. Used to determine things like sbp2 management agent offset,
@@ -1529,7 +1465,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
struct csr1212_dentry *dentry;
u64 management_agent_addr;
u32 command_set_spec_id, command_set, unit_characteristics,
- firmware_revision, workarounds;
+ firmware_revision, workarounds;
int i;
SBP2_DEBUG("sbp2_parse_unit_directory");
@@ -1547,13 +1483,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) {
/* Save off the management agent address */
management_agent_addr =
- CSR1212_REGISTER_SPACE_BASE +
- (kv->value.csr_offset << 2);
+ CSR1212_REGISTER_SPACE_BASE +
+ (kv->value.csr_offset << 2);
SBP2_DEBUG("sbp2_management_agent_addr = %x",
- (unsigned int) management_agent_addr);
+ (unsigned int)management_agent_addr);
} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
- scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
+ scsi_id->sbp2_lun =
+ ORB_SET_LUN(kv->value.immediate);
}
break;
@@ -1561,14 +1498,14 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
/* Command spec organization */
command_set_spec_id = kv->value.immediate;
SBP2_DEBUG("sbp2_command_set_spec_id = %x",
- (unsigned int) command_set_spec_id);
+ (unsigned int)command_set_spec_id);
break;
case SBP2_COMMAND_SET_KEY:
/* Command set used by sbp2 device */
command_set = kv->value.immediate;
SBP2_DEBUG("sbp2_command_set = %x",
- (unsigned int) command_set);
+ (unsigned int)command_set);
break;
case SBP2_UNIT_CHARACTERISTICS_KEY:
@@ -1578,7 +1515,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
*/
unit_characteristics = kv->value.immediate;
SBP2_DEBUG("sbp2_unit_characteristics = %x",
- (unsigned int) unit_characteristics);
+ (unsigned int)unit_characteristics);
break;
case SBP2_FIRMWARE_REVISION_KEY:
@@ -1586,9 +1523,10 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
firmware_revision = kv->value.immediate;
if (force_inquiry_hack)
SBP2_INFO("sbp2_firmware_revision = %x",
- (unsigned int) firmware_revision);
- else SBP2_DEBUG("sbp2_firmware_revision = %x",
- (unsigned int) firmware_revision);
+ (unsigned int)firmware_revision);
+ else
+ SBP2_DEBUG("sbp2_firmware_revision = %x",
+ (unsigned int)firmware_revision);
break;
default:
@@ -1646,7 +1584,7 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
scsi_id->sbp2_firmware_revision = firmware_revision;
scsi_id->workarounds = workarounds;
if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
- scsi_id->sbp2_device_type_and_lun = ud->lun;
+ scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun);
}
}
@@ -1666,8 +1604,9 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
SBP2_DEBUG("sbp2_max_speed_and_size");
/* Initial setting comes from the hosts speed map */
- scsi_id->speed_code = hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64
- + NODEID_TO_NODE(scsi_id->ne->nodeid)];
+ scsi_id->speed_code =
+ hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
+ NODEID_TO_NODE(scsi_id->ne->nodeid)];
/* Bump down our speed if the user requested it */
if (scsi_id->speed_code > max_speed) {
@@ -1678,15 +1617,16 @@ static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
/* Payload size is the lesser of what our speed supports and what
* our host supports. */
- scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code],
- (u8)(hi->host->csr.max_rec - 1));
+ scsi_id->max_payload_size =
+ min(sbp2_speedto_max_payload[scsi_id->speed_code],
+ (u8) (hi->host->csr.max_rec - 1));
HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
hpsb_speedto_str[scsi_id->speed_code],
- 1 << ((u32)scsi_id->max_payload_size + 2));
+ 1 << ((u32) scsi_id->max_payload_size + 2));
- return(0);
+ return 0;
}
/*
@@ -1721,30 +1661,187 @@ static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait)
*/
scsi_id->last_orb = NULL;
- return(0);
+ return 0;
+}
+
+static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ struct sbp2scsi_host_info *hi,
+ struct sbp2_command_info *command,
+ unsigned int scsi_use_sg,
+ struct scatterlist *sgpnt,
+ u32 orb_direction,
+ enum dma_data_direction dma_dir)
+{
+ command->dma_dir = dma_dir;
+ orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+ orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+ /* Special case if only one element (and less than 64KB in size) */
+ if ((scsi_use_sg == 1) &&
+ (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
+
+ SBP2_DEBUG("Only one s/g element");
+ command->dma_size = sgpnt[0].length;
+ command->dma_type = CMD_DMA_PAGE;
+ command->cmd_dma = pci_map_page(hi->host->pdev,
+ sgpnt[0].page,
+ sgpnt[0].offset,
+ command->dma_size,
+ command->dma_dir);
+ SBP2_DMA_ALLOC("single page scatter element");
+
+ orb->data_descriptor_lo = command->cmd_dma;
+ orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
+
+ } else {
+ struct sbp2_unrestricted_page_table *sg_element =
+ &command->scatter_gather_element[0];
+ u32 sg_count, sg_len;
+ dma_addr_t sg_addr;
+ int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
+ dma_dir);
+
+ SBP2_DMA_ALLOC("scatter list");
+
+ command->dma_size = scsi_use_sg;
+ command->sge_buffer = sgpnt;
+
+ /* use page tables (s/g) */
+ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+ orb->data_descriptor_lo = command->sge_dma;
+
+ /*
+ * Loop through and fill out our sbp-2 page tables
+ * (and split up anything too large)
+ */
+ for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
+ sg_len = sg_dma_len(sgpnt);
+ sg_addr = sg_dma_address(sgpnt);
+ while (sg_len) {
+ sg_element[sg_count].segment_base_lo = sg_addr;
+ if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+ sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+ sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+ } else {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+ sg_len = 0;
+ }
+ sg_count++;
+ }
+ }
+
+ /* Number of page table (s/g) elements */
+ orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+ sbp2util_packet_dump(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+ "sbp2 s/g list", command->sge_dma);
+
+ /* Byte swap page tables if necessary */
+ sbp2util_cpu_to_be32_buffer(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) *
+ sg_count);
+ }
+}
+
+static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
+ struct sbp2scsi_host_info *hi,
+ struct sbp2_command_info *command,
+ struct scatterlist *sgpnt,
+ u32 orb_direction,
+ unsigned int scsi_request_bufflen,
+ void *scsi_request_buffer,
+ enum dma_data_direction dma_dir)
+{
+ command->dma_dir = dma_dir;
+ command->dma_size = scsi_request_bufflen;
+ command->dma_type = CMD_DMA_SINGLE;
+ command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
+ command->dma_size, command->dma_dir);
+ orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
+ orb->misc |= ORB_SET_DIRECTION(orb_direction);
+
+ SBP2_DMA_ALLOC("single bulk");
+
+ /*
+ * Handle case where we get a command w/o s/g enabled (but
+ * check for transfers larger than 64K)
+ */
+ if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
+
+ orb->data_descriptor_lo = command->cmd_dma;
+ orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
+
+ } else {
+ struct sbp2_unrestricted_page_table *sg_element =
+ &command->scatter_gather_element[0];
+ u32 sg_count, sg_len;
+ dma_addr_t sg_addr;
+
+ /*
+ * Need to turn this into page tables, since the
+ * buffer is too large.
+ */
+ orb->data_descriptor_lo = command->sge_dma;
+
+ /* Use page tables (s/g) */
+ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+
+ /*
+ * fill out our sbp-2 page tables (and split up
+ * the large buffer)
+ */
+ sg_count = 0;
+ sg_len = scsi_request_bufflen;
+ sg_addr = command->cmd_dma;
+ while (sg_len) {
+ sg_element[sg_count].segment_base_lo = sg_addr;
+ if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
+ sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
+ sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
+ } else {
+ sg_element[sg_count].length_segment_base_hi =
+ PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
+ sg_len = 0;
+ }
+ sg_count++;
+ }
+
+ /* Number of page table (s/g) elements */
+ orb->misc |= ORB_SET_DATA_SIZE(sg_count);
+
+ sbp2util_packet_dump(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
+ "sbp2 s/g list", command->sge_dma);
+
+ /* Byte swap page tables if necessary */
+ sbp2util_cpu_to_be32_buffer(sg_element,
+ (sizeof(struct sbp2_unrestricted_page_table)) *
+ sg_count);
+ }
}
/*
* This function is called to create the actual command orb and s/g list
* out of the scsi command itself.
*/
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command,
- unchar *scsi_cmd,
- unsigned int scsi_use_sg,
- unsigned int scsi_request_bufflen,
- void *scsi_request_buffer,
- enum dma_data_direction dma_dir)
-
+static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
+ struct sbp2_command_info *command,
+ unchar *scsi_cmd,
+ unsigned int scsi_use_sg,
+ unsigned int scsi_request_bufflen,
+ void *scsi_request_buffer,
+ enum dma_data_direction dma_dir)
{
struct sbp2scsi_host_info *hi = scsi_id->hi;
- struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer;
+ struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
struct sbp2_command_orb *command_orb = &command->command_orb;
- struct sbp2_unrestricted_page_table *scatter_gather_element =
- &command->scatter_gather_element[0];
- u32 sg_count, sg_len, orb_direction;
- dma_addr_t sg_addr;
- int i;
+ u32 orb_direction;
/*
* Set-up our command ORB..
@@ -1758,222 +1855,42 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
command_orb->next_ORB_lo = 0x0;
command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size);
command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code);
- command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
+ command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */
- /*
- * Get the direction of the transfer. If the direction is unknown, then use our
- * goofy table as a back-up.
- */
- switch (dma_dir) {
- case DMA_NONE:
- orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
- break;
- case DMA_TO_DEVICE:
- orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
- break;
- case DMA_FROM_DEVICE:
- orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
- break;
- case DMA_BIDIRECTIONAL:
- default:
- SBP2_ERR("SCSI data transfer direction not specified. "
- "Update the SBP2 direction table in sbp2.h if "
- "necessary for your application");
- __scsi_print_command(scsi_cmd);
- orb_direction = sbp2scsi_direction_table[*scsi_cmd];
- break;
+ if (dma_dir == DMA_NONE)
+ orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
+ else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
+ orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
+ else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
+ orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
+ else {
+ SBP2_WARN("Falling back to DMA_NONE");
+ orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
}
- /*
- * Set-up our pagetable stuff... unfortunately, this has become
- * messier than I'd like. Need to clean this up a bit. ;-)
- */
+ /* Set-up our pagetable stuff */
if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-
SBP2_DEBUG("No data transfer");
-
- /*
- * Handle no data transfer
- */
command_orb->data_descriptor_hi = 0x0;
command_orb->data_descriptor_lo = 0x0;
command_orb->misc |= ORB_SET_DIRECTION(1);
-
} else if (scsi_use_sg) {
-
SBP2_DEBUG("Use scatter/gather");
-
- /*
- * Special case if only one element (and less than 64KB in size)
- */
- if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-
- SBP2_DEBUG("Only one s/g element");
- command->dma_dir = dma_dir;
- command->dma_size = sgpnt[0].length;
- command->dma_type = CMD_DMA_PAGE;
- command->cmd_dma = pci_map_page(hi->host->pdev,
- sgpnt[0].page,
- sgpnt[0].offset,
- command->dma_size,
- command->dma_dir);
- SBP2_DMA_ALLOC("single page scatter element");
-
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->cmd_dma;
- command_orb->misc |= ORB_SET_DATA_SIZE(command->dma_size);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- } else {
- int count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, dma_dir);
- SBP2_DMA_ALLOC("scatter list");
-
- command->dma_size = scsi_use_sg;
- command->dma_dir = dma_dir;
- command->sge_buffer = sgpnt;
-
- /* use page tables (s/g) */
- command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->sge_dma;
-
- /*
- * Loop through and fill out our sbp-2 page tables
- * (and split up anything too large)
- */
- for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
- sg_len = sg_dma_len(sgpnt);
- sg_addr = sg_dma_address(sgpnt);
- while (sg_len) {
- scatter_gather_element[sg_count].segment_base_lo = sg_addr;
- if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
- sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
- sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
- } else {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
- sg_len = 0;
- }
- sg_count++;
- }
- }
-
- /* Number of page table (s/g) elements */
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
- sbp2util_packet_dump(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
- "sbp2 s/g list", command->sge_dma);
-
- /*
- * Byte swap page tables if necessary
- */
- sbp2util_cpu_to_be32_buffer(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) *
- sg_count);
-
- }
-
+ sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg,
+ sgpnt, orb_direction, dma_dir);
} else {
-
SBP2_DEBUG("No scatter/gather");
-
- command->dma_dir = dma_dir;
- command->dma_size = scsi_request_bufflen;
- command->dma_type = CMD_DMA_SINGLE;
- command->cmd_dma = pci_map_single (hi->host->pdev, scsi_request_buffer,
- command->dma_size,
- command->dma_dir);
- SBP2_DMA_ALLOC("single bulk");
-
- /*
- * Handle case where we get a command w/o s/g enabled (but
- * check for transfers larger than 64K)
- */
- if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) {
-
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->cmd_dma;
- command_orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- /*
- * Sanity, in case our direction table is not
- * up-to-date
- */
- if (!scsi_request_bufflen) {
- command_orb->data_descriptor_hi = 0x0;
- command_orb->data_descriptor_lo = 0x0;
- command_orb->misc |= ORB_SET_DIRECTION(1);
- }
-
- } else {
- /*
- * Need to turn this into page tables, since the
- * buffer is too large.
- */
- command_orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
- command_orb->data_descriptor_lo = command->sge_dma;
-
- /* Use page tables (s/g) */
- command_orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
- command_orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
- /*
- * fill out our sbp-2 page tables (and split up
- * the large buffer)
- */
- sg_count = 0;
- sg_len = scsi_request_bufflen;
- sg_addr = command->cmd_dma;
- while (sg_len) {
- scatter_gather_element[sg_count].segment_base_lo = sg_addr;
- if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH);
- sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH;
- sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH;
- } else {
- scatter_gather_element[sg_count].length_segment_base_hi =
- PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len);
- sg_len = 0;
- }
- sg_count++;
- }
-
- /* Number of page table (s/g) elements */
- command_orb->misc |= ORB_SET_DATA_SIZE(sg_count);
-
- sbp2util_packet_dump(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) * sg_count,
- "sbp2 s/g list", command->sge_dma);
-
- /*
- * Byte swap page tables if necessary
- */
- sbp2util_cpu_to_be32_buffer(scatter_gather_element,
- (sizeof(struct sbp2_unrestricted_page_table)) *
- sg_count);
-
- }
-
+ sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt,
+ orb_direction, scsi_request_bufflen,
+ scsi_request_buffer, dma_dir);
}
- /*
- * Byte swap command ORB if necessary
- */
+ /* Byte swap command ORB if necessary */
sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb));
- /*
- * Put our scsi command in the command ORB
- */
+ /* Put our scsi command in the command ORB */
memset(command_orb->cdb, 0, 12);
memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
-
- return(0);
}
/*
@@ -1989,7 +1906,7 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
outstanding_orb_incr;
SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x",
- command_orb, global_outstanding_command_orbs);
+ command_orb, global_outstanding_command_orbs);
pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma,
sizeof(struct sbp2_command_orb),
@@ -2034,10 +1951,11 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
* both by the sbp2 device and us.
*/
scsi_id->last_orb->next_ORB_lo =
- cpu_to_be32(command->command_orb_dma);
+ cpu_to_be32(command->command_orb_dma);
/* Tells hardware that this pointer is valid */
scsi_id->last_orb->next_ORB_hi = 0x0;
- pci_dma_sync_single_for_device(hi->host->pdev, scsi_id->last_orb_dma,
+ pci_dma_sync_single_for_device(hi->host->pdev,
+ scsi_id->last_orb_dma,
sizeof(struct sbp2_command_orb),
PCI_DMA_BIDIRECTIONAL);
@@ -2051,14 +1969,14 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) {
SBP2_ERR("sbp2util_node_write_no_wait failed");
- return(-EIO);
+ return -EIO;
}
scsi_id->last_orb = command_orb;
scsi_id->last_orb_dma = command->command_orb_dma;
}
- return(0);
+ return 0;
}
/*
@@ -2085,7 +2003,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done);
if (!command) {
- return(-EIO);
+ return -EIO;
}
/*
@@ -2106,11 +2024,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg,
request_bufflen, SCpnt->request_buffer,
SCpnt->sc_data_direction);
- /*
- * Update our cdb if necessary (to handle sbp2 RBC command set
- * differences). This is where the command set hacks go! =)
- */
- sbp2_check_sbp2_command(scsi_id, command->command_orb.cdb);
sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb),
"sbp2 command orb", command->command_orb_dma);
@@ -2125,112 +2038,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
sbp2_link_orb_command(scsi_id, command);
- return(0);
-}
-
-
-/*
- * This function deals with command set differences between Linux scsi
- * command set and sbp2 RBC command set.
- */
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
-{
- unchar new_cmd[16];
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
-
- SBP2_DEBUG("sbp2_check_sbp2_command");
-
- switch (*cmd) {
-
- case READ_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert READ_6 to READ_10");
-
- /*
- * Need to turn read_6 into read_10
- */
- new_cmd[0] = 0x28;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case WRITE_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
-
- /*
- * Need to turn write_6 into write_10
- */
- new_cmd[0] = 0x2a;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
-
- /*
- * Need to turn mode_sense_6 into mode_sense_10
- */
- new_cmd[0] = 0x5a;
- new_cmd[1] = cmd[1];
- new_cmd[2] = cmd[2];
- new_cmd[3] = 0x0;
- new_cmd[4] = 0x0;
- new_cmd[5] = 0x0;
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SELECT:
-
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
-
- default:
- break;
- }
-
- return;
+ return 0;
}
/*
@@ -2260,80 +2068,40 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense
sense_data[14] = sbp2_status[20];
sense_data[15] = sbp2_status[21];
- return(sbp2_status[8] & 0x3f); /* return scsi status */
+ return sbp2_status[8] & 0x3f; /* return scsi status */
}
/*
* This function is called after a command is completed, in order to do any necessary SBP-2
* response data translations for the SCSI stack
*/
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
+static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt)
{
u8 *scsi_buf = SCpnt->request_buffer;
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
SBP2_DEBUG("sbp2_check_sbp2_response");
switch (SCpnt->cmnd[0]) {
- case INQUIRY:
-
- /*
- * If scsi_id->sbp2_device_type_and_lun is uninitialized, then fill
- * this information in from the inquiry response data. Lun is set to zero.
- */
- if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) {
- SBP2_DEBUG("Creating sbp2_device_type_and_lun from scsi inquiry data");
- scsi_id->sbp2_device_type_and_lun = (scsi_buf[0] & 0x1f) << 16;
- }
-
- /*
- * Make sure data length is ok. Minimum length is 36 bytes
- */
- if (scsi_buf[4] == 0) {
- scsi_buf[4] = 36 - 5;
- }
-
- /*
- * Check for Simple Direct Access Device and change it to TYPE_DISK
- */
- if ((scsi_buf[0] & 0x1f) == TYPE_RBC) {
- SBP2_DEBUG("Changing TYPE_RBC to TYPE_DISK");
- scsi_buf[0] &= 0xe0;
- }
-
- /*
- * Fix ansi revision and response data format
- */
- scsi_buf[2] |= 2;
- scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-
- break;
-
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Modify mode sense response (10 byte version)");
-
- scsi_buf[0] = scsi_buf[1]; /* Mode data length */
- scsi_buf[1] = scsi_buf[2]; /* Medium type */
- scsi_buf[2] = scsi_buf[3]; /* Device specific parameter */
- scsi_buf[3] = scsi_buf[7]; /* Block descriptor length */
- memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
- }
-
- break;
+ case INQUIRY:
+ /*
+ * Make sure data length is ok. Minimum length is 36 bytes
+ */
+ if (scsi_buf[4] == 0) {
+ scsi_buf[4] = 36 - 5;
+ }
- case MODE_SELECT:
+ /*
+ * Fix ansi revision and response data format
+ */
+ scsi_buf[2] |= 2;
+ scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
+ break;
- default:
- break;
+ default:
+ break;
}
return;
}
@@ -2358,14 +2126,14 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
if (!host) {
SBP2_ERR("host is NULL - this is bad!");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
if (!hi) {
SBP2_ERR("host info is NULL - this is bad!");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
/*
@@ -2382,7 +2150,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
if (!scsi_id) {
SBP2_ERR("scsi_id is NULL - device is gone?");
- return(RCODE_ADDRESS_ERROR);
+ return RCODE_ADDRESS_ERROR;
}
/*
@@ -2480,10 +2248,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest
SBP2_ORB_DEBUG("command orb completed");
}
- return(RCODE_COMPLETE);
+ return RCODE_COMPLETE;
}
-
/**************************************
* SCSI interface related section
**************************************/
@@ -2541,6 +2308,16 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
/*
+ * Bidirectional commands are not yet implemented,
+ * and unknown transfer direction not handled.
+ */
+ if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) {
+ SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+ result = DID_ERROR << 16;
+ goto done;
+ }
+
+ /*
* Try and send our SCSI command
*/
if (sbp2_send_command(scsi_id, SCpnt, done)) {
@@ -2616,55 +2393,56 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* complete the command, just let it get retried at the end of the
* bus reset.
*/
- if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne)
+ && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("Bus reset in progress - retry command later");
return;
}
-
+
/*
* Switch on scsi status
*/
switch (scsi_status) {
- case SBP2_SCSI_STATUS_GOOD:
- SCpnt->result = DID_OK;
- break;
+ case SBP2_SCSI_STATUS_GOOD:
+ SCpnt->result = DID_OK;
+ break;
- case SBP2_SCSI_STATUS_BUSY:
- SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
- SCpnt->result = DID_BUS_BUSY << 16;
- break;
+ case SBP2_SCSI_STATUS_BUSY:
+ SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
+ SCpnt->result = DID_BUS_BUSY << 16;
+ break;
- case SBP2_SCSI_STATUS_CHECK_CONDITION:
- SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
- SCpnt->result = CHECK_CONDITION << 1;
+ case SBP2_SCSI_STATUS_CHECK_CONDITION:
+ SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION");
+ SCpnt->result = CHECK_CONDITION << 1;
- /*
- * Debug stuff
- */
+ /*
+ * Debug stuff
+ */
#if CONFIG_IEEE1394_SBP2_DEBUG >= 1
- scsi_print_command(SCpnt);
- scsi_print_sense("bh", SCpnt);
+ scsi_print_command(SCpnt);
+ scsi_print_sense("bh", SCpnt);
#endif
- break;
+ break;
- case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
- SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
- SCpnt->result = DID_NO_CONNECT << 16;
- scsi_print_command(SCpnt);
- break;
+ case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
+ SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
+ SCpnt->result = DID_NO_CONNECT << 16;
+ scsi_print_command(SCpnt);
+ break;
- case SBP2_SCSI_STATUS_CONDITION_MET:
- case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
- case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
- SBP2_ERR("Bad SCSI status = %x", scsi_status);
- SCpnt->result = DID_ERROR << 16;
- scsi_print_command(SCpnt);
- break;
+ case SBP2_SCSI_STATUS_CONDITION_MET:
+ case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
+ case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
+ SBP2_ERR("Bad SCSI status = %x", scsi_status);
+ SCpnt->result = DID_ERROR << 16;
+ scsi_print_command(SCpnt);
+ break;
- default:
- SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
- SCpnt->result = DID_ERROR << 16;
+ default:
+ SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
+ SCpnt->result = DID_ERROR << 16;
}
/*
@@ -2678,7 +2456,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
* If a bus reset is in progress and there was an error, complete
* the command as busy so that it will get retried.
*/
- if (!hpsb_node_entry_valid(scsi_id->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
+ if (!hpsb_node_entry_valid(scsi_id->ne)
+ && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
SBP2_ERR("Completing command with busy (bus reset)");
SCpnt->result = DID_BUS_BUSY << 16;
}
@@ -2699,31 +2478,29 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Tell scsi stack that we're done with this command
*/
- done (SCpnt);
+ done(SCpnt);
}
-
static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
{
((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = sdev;
return 0;
}
-
static int sbp2scsi_slave_configure(struct scsi_device *sdev)
{
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+ sdev->use_10_for_rw = 1;
+ sdev->use_10_for_ms = 1;
return 0;
}
-
static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
{
((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL;
return;
}
-
/*
* Called by scsi stack when something has really gone wrong. Usually
* called when a command has timed-out for some reason.
@@ -2769,7 +2546,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY);
}
- return(SUCCESS);
+ return SUCCESS;
}
/*
@@ -2779,28 +2556,20 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
- unsigned long flags;
SBP2_ERR("reset requested");
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
-
if (sbp2util_node_is_available(scsi_id)) {
SBP2_ERR("Generating sbp2 fetch agent reset");
sbp2_agent_reset(scsi_id, 0);
}
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
-
return SUCCESS;
}
-static const char *sbp2scsi_info (struct Scsi_Host *host)
-{
- return "SCSI emulation for IEEE-1394 SBP-2 Devices";
-}
-
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct scsi_device *sdev;
struct scsi_id_instance_data *scsi_id;
@@ -2812,10 +2581,7 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_att
if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0]))
return 0;
- if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED)
- lun = 0;
- else
- lun = ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun);
+ lun = ORB_SET_LUN(scsi_id->sbp2_lun);
return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid,
scsi_id->ud->id, lun);
@@ -2837,12 +2603,9 @@ static struct scsi_host_template scsi_driver_template = {
.module = THIS_MODULE,
.name = "SBP-2 IEEE-1394",
.proc_name = SBP2_DEVICE_NAME,
- .info = sbp2scsi_info,
.queuecommand = sbp2scsi_queuecommand,
.eh_abort_handler = sbp2scsi_abort,
.eh_device_reset_handler = sbp2scsi_reset,
- .eh_bus_reset_handler = sbp2scsi_reset,
- .eh_host_reset_handler = sbp2scsi_reset,
.slave_alloc = sbp2scsi_slave_alloc,
.slave_configure = sbp2scsi_slave_configure,
.slave_destroy = sbp2scsi_slave_destroy,
@@ -2861,8 +2624,6 @@ static int sbp2_module_init(void)
SBP2_DEBUG("sbp2_module_init");
- printk(KERN_INFO "sbp2: %s\n", version);
-
/* Module load debug option to force one command at a time (serializing I/O) */
if (serialize_io) {
SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)");
@@ -2874,7 +2635,6 @@ static int sbp2_module_init(void)
/* Set max sectors (module load option). Default is 255 sectors. */
scsi_driver_template.max_sectors = max_sectors;
-
/* Register our high level driver with 1394 stack */
hpsb_register_highlevel(&sbp2_highlevel);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index cd425be74841..900ea1d25e71 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -119,8 +119,8 @@ struct sbp2_query_logins_response {
struct sbp2_reconnect_orb {
u32 reserved1;
u32 reserved2;
- u32 reserved3;
- u32 reserved4;
+ u32 reserved3;
+ u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
u32 status_FIFO_hi;
@@ -130,8 +130,8 @@ struct sbp2_reconnect_orb {
struct sbp2_logout_orb {
u32 reserved1;
u32 reserved2;
- u32 reserved3;
- u32 reserved4;
+ u32 reserved3;
+ u32 reserved4;
u32 login_ID_misc;
u32 reserved5;
u32 status_FIFO_hi;
@@ -188,7 +188,7 @@ struct sbp2_unrestricted_page_table {
struct sbp2_status_block {
u32 ORB_offset_hi_misc;
u32 ORB_offset_lo;
- u8 command_set_dependent[24];
+ u8 command_set_dependent[24];
};
/*
@@ -211,7 +211,7 @@ struct sbp2_status_block {
* specified for write posting, where the ohci controller will
* automatically send an ack_complete when the status is written by the
* sbp2 device... saving a split transaction. =)
- */
+ */
#define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL
#define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe
#define SBP2_STATUS_FIFO_ADDRESS_LO 0x0
@@ -229,9 +229,6 @@ struct sbp2_status_block {
#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14
#define SBP2_FIRMWARE_REVISION_KEY 0x3c
-#define SBP2_DEVICE_TYPE(q) (((q) >> 16) & 0x1f)
-#define SBP2_DEVICE_LUN(q) ((q) & 0xffff)
-
#define SBP2_AGENT_STATE_OFFSET 0x00ULL
#define SBP2_AGENT_RESET_OFFSET 0x04ULL
#define SBP2_ORB_POINTER_OFFSET 0x08ULL
@@ -256,8 +253,6 @@ struct sbp2_status_block {
*/
#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800
-#define SBP2_DEVICE_TYPE_LUN_UNINITIALIZED 0xffffffff
-
/*
* SCSI specific stuff
*/
@@ -265,45 +260,7 @@ struct sbp2_status_block {
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
-
-/*
- * SCSI direction table...
- * (now used as a back-up in case the direction passed down from above is "unknown")
- *
- * DIN = IN data direction
- * DOU = OUT data direction
- * DNO = No data transfer
- * DUN = Unknown data direction
- *
- * Opcode 0xec (Teac specific "opc execute") possibly should be DNO,
- * but we'll change it when somebody reports a problem with this.
- */
-#define DIN ORB_DIRECTION_READ_FROM_MEDIA
-#define DOU ORB_DIRECTION_WRITE_TO_MEDIA
-#define DNO ORB_DIRECTION_NO_DATA_TRANSFER
-#define DUN DIN
-
-static unchar sbp2scsi_direction_table[0x100] = {
- DNO,DNO,DIN,DIN,DOU,DIN,DIN,DOU,DIN,DUN,DOU,DOU,DUN,DUN,DUN,DIN,
- DNO,DIN,DIN,DOU,DIN,DOU,DNO,DNO,DOU,DNO,DIN,DNO,DIN,DOU,DNO,DUN,
- DIN,DUN,DIN,DIN,DOU,DIN,DUN,DUN,DIN,DIN,DOU,DNO,DUN,DIN,DOU,DOU,
- DOU,DOU,DOU,DNO,DIN,DNO,DNO,DIN,DOU,DOU,DOU,DOU,DIN,DOU,DIN,DOU,
- DOU,DOU,DIN,DIN,DIN,DNO,DIN,DNO,DNO,DNO,DUN,DNO,DOU,DIN,DNO,DUN,
- DUN,DIN,DIN,DNO,DNO,DOU,DUN,DUN,DNO,DIN,DIN,DNO,DIN,DOU,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DNO,DOU,DOU,DIN,DNO,DNO,DNO,DIN,DNO,DOU,DUN,DNO,DIN,DOU,DOU,
- DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DIN,DNO,DNO,DNO,DIN,DIN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
- DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
-};
-
-/* This should be safe */
-#define SBP2_MAX_CMDS 8
+#define SBP2_MAX_CMDS 8 /* This should be safe */
/* This is the two dma types we use for cmd_dma below */
enum cmd_dma_types {
@@ -338,10 +295,8 @@ struct sbp2_command_info {
#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1
#define SBP2_BREAKAGE_INQUIRY_HACK 0x2
-
struct sbp2scsi_host_info;
-
/*
* Information needed on a per scsi id basis (one for each sbp2 device)
*/
@@ -379,7 +334,7 @@ struct scsi_id_instance_data {
u32 sbp2_command_set_spec_id;
u32 sbp2_command_set;
u32 sbp2_unit_characteristics;
- u32 sbp2_device_type_and_lun;
+ u32 sbp2_lun;
u32 sbp2_firmware_revision;
/*
@@ -411,7 +366,6 @@ struct scsi_id_instance_data {
u32 workarounds;
};
-
/* Sbp2 host data structure (one per IEEE1394 host) */
struct sbp2scsi_host_info {
struct hpsb_host *host; /* IEEE1394 host */
@@ -456,20 +410,12 @@ static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id);
static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 flags);
static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait);
-static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id,
- struct sbp2_command_info *command,
- unchar *scsi_cmd,
- unsigned int scsi_use_sg,
- unsigned int scsi_request_bufflen,
- void *scsi_request_buffer,
- enum dma_data_direction dma_dir);
static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
struct sbp2_command_info *command);
static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *));
static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
-static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt);
static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 23911da50154..39fb88309e8e 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -19,12 +19,6 @@
*
* NOTES:
*
- * jds -- add private data to file to keep track of iso contexts associated
- * with each open -- so release won't kill all iso transfers.
- *
- * Damien Douxchamps: Fix failure when the number of DMA pages per frame is
- * one.
- *
* ioctl return codes:
* EFAULT is only for invalid address for the argp
* EINVAL for out of range values
@@ -34,12 +28,6 @@
* ENOTTY for unsupported ioctl request
*
*/
-
-/* Markus Tavenrath <speedygoo@speedygoo.de> :
- - fixed checks for valid buffer-numbers in video1394_icotl
- - changed the ways the dma prg's are used, now it's possible to use
- even a single dma buffer
-*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -60,7 +48,6 @@
#include <linux/vmalloc.h>
#include <linux/timex.h>
#include <linux/mm.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/cdev.h>
@@ -77,14 +64,6 @@
#define ISO_CHANNELS 64
-#ifndef virt_to_page
-#define virt_to_page(x) MAP_NR(x)
-#endif
-
-#ifndef vmalloc_32
-#define vmalloc_32(x) vmalloc(x)
-#endif
-
struct it_dma_prg {
struct dma_cmd begin;
quadlet_t data[4];
@@ -206,14 +185,12 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
struct dma_iso_ctx *d;
int i;
- d = kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL);
- if (d == NULL) {
+ d = kzalloc(sizeof(*d), GFP_KERNEL);
+ if (!d) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
return NULL;
}
- memset(d, 0, sizeof *d);
-
d->ohci = ohci;
d->type = type;
d->channel = channel;
@@ -251,9 +228,8 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
}
d->ctx = d->iso_tasklet.context;
- d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
- GFP_KERNEL);
- if (d->prg_reg == NULL) {
+ d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
+ if (!d->prg_reg) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
free_dma_iso_ctx(d);
return NULL;
@@ -268,15 +244,14 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
- d->ir_prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *),
+ d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
GFP_KERNEL);
- if (d->ir_prg == NULL) {
+ if (!d->ir_prg) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
d->left_size = (d->frame_size % PAGE_SIZE) ?
@@ -297,16 +272,15 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
- d->it_prg = kmalloc(d->num_desc * sizeof(struct it_dma_prg *),
+ d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
GFP_KERNEL);
- if (d->it_prg == NULL) {
+ if (!d->it_prg) {
PRINT(KERN_ERR, ohci->host->id,
"Failed to allocate dma it prg");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *));
d->packet_size = packet_size;
@@ -337,47 +311,24 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
}
}
- d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
- GFP_KERNEL);
- d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
- d->next_buffer = kmalloc(d->num_desc * sizeof(int),
- GFP_KERNEL);
-
- if (d->buffer_status == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_status");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->buffer_prg_assignment == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_prg_assignment");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->buffer_time == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->last_used_cmd == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate last_used_cmd");
- free_dma_iso_ctx(d);
- return NULL;
- }
- if (d->next_buffer == NULL) {
- PRINT(KERN_ERR, ohci->host->id, "Failed to allocate next_buffer");
+ d->buffer_status =
+ kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
+ d->buffer_prg_assignment =
+ kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
+ d->buffer_time =
+ kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
+ d->last_used_cmd =
+ kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
+ d->next_buffer =
+ kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
+
+ if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
+ !d->last_used_cmd || !d->next_buffer) {
+ PRINT(KERN_ERR, ohci->host->id,
+ "Failed to allocate dma_iso_ctx member");
free_dma_iso_ctx(d);
return NULL;
}
- memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
- memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
- memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
- memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
- memset(d->next_buffer, -1, d->num_desc * sizeof(int));
spin_lock_init(&d->lock);
@@ -539,7 +490,7 @@ static void wakeup_dma_ir_ctx(unsigned long l)
if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
reset_ir_status(d, i);
d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
- do_gettimeofday(&d->buffer_time[i]);
+ do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
}
}
@@ -1046,7 +997,6 @@ static int __video1394_ioctl(struct file *file,
/* set time of buffer */
v.filltime = d->buffer_time[v.buffer];
-// printk("Buffer %d time %d\n", v.buffer, (d->buffer_time[v.buffer]).tv_usec);
/*
* Look ahead to see how many more buffers have been received
@@ -1085,7 +1035,7 @@ static int __video1394_ioctl(struct file *file,
}
if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
- int buf_size = d->nb_cmd * sizeof(unsigned int);
+ int buf_size = d->nb_cmd * sizeof(*psizes);
struct video1394_queue_variable __user *p = argp;
unsigned int __user *qv;
@@ -1104,7 +1054,7 @@ static int __video1394_ioctl(struct file *file,
spin_lock_irqsave(&d->lock,flags);
- // last_buffer is last_prg
+ /* last_buffer is last_prg */
next_prg = (d->last_buffer + 1) % d->num_desc;
if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
PRINT(KERN_ERR, ohci->host->id,
@@ -1251,13 +1201,12 @@ static int video1394_open(struct inode *inode, struct file *file)
if (ohci == NULL)
return -EIO;
- ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL);
- if (ctx == NULL) {
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx) {
PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
return -ENOMEM;
}
- memset(ctx, 0, sizeof(struct file_ctx));
ctx->ohci = ohci;
INIT_LIST_HEAD(&ctx->context_list);
ctx->current_ctx = NULL;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 02110e00d145..2514de3480d8 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -308,10 +308,11 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
{
unsigned long flags;
int ret;
+ static int next_id;
do {
spin_lock_irqsave(&cm.lock, flags);
- ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1,
+ ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_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) );
@@ -684,6 +685,13 @@ retest:
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
break;
case IB_CM_REQ_SENT:
+ ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+ spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
+ &cm_id_priv->av.port->cm_dev->ca_guid,
+ sizeof cm_id_priv->av.port->cm_dev->ca_guid,
+ NULL, 0);
+ break;
case IB_CM_MRA_REQ_RCVD:
case IB_CM_REP_SENT:
case IB_CM_MRA_REP_RCVD:
@@ -694,10 +702,8 @@ retest:
case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
- &cm_id_priv->av.port->cm_dev->ca_guid,
- sizeof cm_id_priv->av.port->cm_dev->ca_guid,
- NULL, 0);
+ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
+ NULL, 0, NULL, 0);
break;
case IB_CM_ESTABLISHED:
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
@@ -850,7 +856,7 @@ static void cm_format_req(struct cm_req_msg *req_msg,
param->private_data_len);
}
-static inline int cm_validate_req_param(struct ib_cm_req_param *param)
+static int cm_validate_req_param(struct ib_cm_req_param *param)
{
/* peer-to-peer not supported */
if (param->peer_to_peer)
@@ -999,7 +1005,7 @@ static inline int cm_is_active_peer(__be64 local_ca_guid, __be64 remote_ca_guid,
(be32_to_cpu(local_qpn) > be32_to_cpu(remote_qpn))));
}
-static inline void cm_format_paths_from_req(struct cm_req_msg *req_msg,
+static void cm_format_paths_from_req(struct cm_req_msg *req_msg,
struct ib_sa_path_rec *primary_path,
struct ib_sa_path_rec *alt_path)
{
@@ -3157,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
-static __be64 cm_get_ca_guid(struct ib_device *device)
-{
- struct ib_device_attr *device_attr;
- __be64 guid;
- int ret;
-
- device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
- if (!device_attr)
- return 0;
-
- ret = ib_query_device(device, device_attr);
- guid = ret ? 0 : device_attr->node_guid;
- kfree(device_attr);
- return guid;
-}
-
static void cm_add_one(struct ib_device *device)
{
struct cm_device *cm_dev;
@@ -3194,9 +3184,7 @@ static void cm_add_one(struct ib_device *device)
return;
cm_dev->device = device;
- cm_dev->ca_guid = cm_get_ca_guid(device);
- if (!cm_dev->ca_guid)
- goto error1;
+ cm_dev->ca_guid = device->node_guid;
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= device->phys_port_cnt; i++) {
@@ -3211,11 +3199,11 @@ static void cm_add_one(struct ib_device *device)
cm_recv_handler,
port);
if (IS_ERR(port->mad_agent))
- goto error2;
+ goto error1;
ret = ib_modify_port(device, i, 0, &port_modify);
if (ret)
- goto error3;
+ goto error2;
}
ib_set_client_data(device, &cm_client, cm_dev);
@@ -3224,9 +3212,9 @@ static void cm_add_one(struct ib_device *device)
write_unlock_irqrestore(&cm.device_lock, flags);
return;
-error3:
- ib_unregister_mad_agent(port->mad_agent);
error2:
+ ib_unregister_mad_agent(port->mad_agent);
+error1:
port_modify.set_port_cap_mask = 0;
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
@@ -3234,7 +3222,6 @@ error2:
ib_modify_port(device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
}
-error1:
kfree(cm_dev);
}
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index e169e798354b..b2f3cb91d9bc 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -38,8 +38,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/init.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include "core_priv.h"
@@ -57,13 +56,13 @@ static LIST_HEAD(device_list);
static LIST_HEAD(client_list);
/*
- * device_sem protects access to both device_list and client_list.
+ * device_mutex protects access to both device_list and client_list.
* There's no real point to using multiple locks or something fancier
* like an rwsem: we always access both lists, and we're always
* modifying one list or the other list. In any case this is not a
* hot path so there's no point in trying to optimize.
*/
-static DECLARE_MUTEX(device_sem);
+static DEFINE_MUTEX(device_mutex);
static int ib_device_check_mandatory(struct ib_device *device)
{
@@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device)
{
int ret;
- down(&device_sem);
+ mutex_lock(&device_mutex);
if (strchr(device->name, '%')) {
ret = alloc_name(device->name);
@@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device)
}
out:
- up(&device_sem);
+ mutex_unlock(&device_mutex);
return ret;
}
EXPORT_SYMBOL(ib_register_device);
@@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device)
struct ib_client_data *context, *tmp;
unsigned long flags;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_for_each_entry_reverse(client, &client_list, list)
if (client->remove)
@@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device)
list_del(&device->core_list);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
spin_lock_irqsave(&device->client_data_lock, flags);
list_for_each_entry_safe(context, tmp, &device->client_data_list, list)
@@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client)
{
struct ib_device *device;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_add_tail(&client->list, &client_list);
list_for_each_entry(device, &device_list, core_list)
if (client->add && !add_client_context(device, client))
client->add(device);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
return 0;
}
@@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client)
struct ib_device *device;
unsigned long flags;
- down(&device_sem);
+ mutex_lock(&device_mutex);
list_for_each_entry(device, &device_list, core_list) {
if (client->remove)
@@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client)
}
list_del(&client->list);
- up(&device_sem);
+ mutex_unlock(&device_mutex);
}
EXPORT_SYMBOL(ib_unregister_client);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 08648b1a387e..5982d687a000 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -434,24 +434,18 @@ static void ib_device_release(struct class_device *cdev)
kfree(dev);
}
-static int ib_device_hotplug(struct class_device *cdev, char **envp,
- int num_envp, char *buf, int size)
+static int ib_device_uevent(struct class_device *cdev, char **envp,
+ int num_envp, char *buf, int size)
{
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
int i = 0, len = 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buf, size, &len,
- "NAME=%s", dev->name))
+ if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
+ "NAME=%s", dev->name))
return -ENOMEM;
/*
- * It might be nice to pass the node GUID to hotplug, but
- * right now the only way to get it is to query the device
- * provider, and this can crash during device removal because
- * we are will be running after driver removal has started.
- * We could add a node_guid field to struct ib_device, or we
- * could just let the hotplug script read the node GUID from
- * sysfs when devices are added.
+ * It would be nice to pass the node GUID with the event...
*/
envp[i] = NULL;
@@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf)
static ssize_t show_node_guid(struct class_device *cdev, char *buf)
{
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
- struct ib_device_attr attr;
- ssize_t ret;
if (!ibdev_is_alive(dev))
return -ENODEV;
- ret = ib_query_device(dev, &attr);
- if (ret)
- return ret;
-
return sprintf(buf, "%04x:%04x:%04x:%04x\n",
- 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]));
+ be16_to_cpu(((__be16 *) &dev->node_guid)[0]),
+ be16_to_cpu(((__be16 *) &dev->node_guid)[1]),
+ be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
+ be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
}
static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
@@ -653,7 +641,7 @@ static struct class_device_attribute *ib_class_attributes[] = {
static struct class ib_class = {
.name = "infiniband",
.release = ib_device_release,
- .hotplug = ib_device_hotplug,
+ .uevent = ib_device_uevent,
};
int ib_device_register_sysfs(struct ib_device *device)
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 6e15787d1de1..e95c4293a496 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -42,6 +42,7 @@
#include <linux/mount.h>
#include <linux/cdev.h>
#include <linux/idr.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -113,7 +114,7 @@ static struct ib_client ucm_client = {
.remove = ib_ucm_remove_one
};
-static DECLARE_MUTEX(ctx_id_mutex);
+static DEFINE_MUTEX(ctx_id_mutex);
static DEFINE_IDR(ctx_id_table);
static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES);
@@ -121,7 +122,7 @@ 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);
+ mutex_lock(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, id);
if (!ctx)
ctx = ERR_PTR(-ENOENT);
@@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id)
ctx = ERR_PTR(-EINVAL);
else
atomic_inc(&ctx->ref);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
return ctx;
}
@@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
if (!result)
goto error;
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
result = idr_get_new(&ctx_id_table, ctx, &ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
} while (result == -EAGAIN);
if (result)
@@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file,
err2:
ib_destroy_cm_id(ctx->cm_id);
err1:
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
kfree(ctx);
return result;
}
@@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
ctx = idr_find(&ctx_id_table, cmd.id);
if (!ctx)
ctx = ERR_PTR(-ENOENT);
@@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file,
ctx = ERR_PTR(-EINVAL);
else
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
struct ib_ucm_context, file_list);
up(&file->mutex);
- down(&ctx_id_mutex);
+ mutex_lock(&ctx_id_mutex);
idr_remove(&ctx_id_table, ctx->id);
- up(&ctx_id_mutex);
+ mutex_unlock(&ctx_id_mutex);
ib_destroy_cm_id(ctx->cm_id);
ib_ucm_cleanup_events(ctx);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index eb7f52537ccc..c908de8db5a9 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -197,8 +197,8 @@ static void send_handler(struct ib_mad_agent *agent,
memcpy(timeout->mad.data, packet->mad.data,
sizeof (struct ib_mad_hdr));
- if (!queue_packet(file, agent, timeout))
- return;
+ if (queue_packet(file, agent, timeout))
+ kfree(timeout);
}
out:
kfree(packet);
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 7114e3fbab00..f7eecbc6af6c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -41,6 +41,7 @@
#include <linux/kref.h>
#include <linux/idr.h>
+#include <linux/mutex.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_user_verbs.h>
@@ -88,7 +89,7 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file {
struct kref ref;
- struct semaphore mutex;
+ struct mutex mutex;
struct ib_uverbs_device *device;
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
@@ -131,7 +132,7 @@ struct ib_ucq_object {
u32 async_events_reported;
};
-extern struct semaphore ib_uverbs_idr_mutex;
+extern struct mutex ib_uverbs_idr_mutex;
extern struct idr ib_uverbs_pd_idr;
extern struct idr ib_uverbs_mr_idr;
extern struct idr ib_uverbs_mw_idr;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a57d021d435a..407b6284d7d5 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&file->mutex);
+ mutex_lock(&file->mutex);
if (file->ucontext) {
ret = -EINVAL;
@@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
fd_install(resp.async_fd, filp);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
return in_len;
@@ -131,7 +131,7 @@ err_free:
ibdev->dealloc_ucontext(ucontext);
err:
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
return ret;
}
@@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
resp.fw_ver = attr.fw_ver;
- resp.node_guid = attr.node_guid;
+ resp.node_guid = file->device->ib_dev->node_guid;
resp.sys_image_guid = attr.sys_image_guid;
resp.max_mr_size = attr.max_mr_size;
resp.page_size_cap = attr.page_size_cap;
@@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file,
pd->uobject = uobj;
atomic_set(&pd->usecnt, 0);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
retry:
if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
@@ -314,11 +314,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->pd_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -326,7 +326,7 @@ err_idr:
idr_remove(&ib_uverbs_pd_idr, uobj->id);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_dealloc_pd(pd);
err:
@@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext)
@@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
kfree(uobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
obj->umem.virt_base = cmd.hca_va;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext) {
@@ -476,11 +476,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -489,9 +489,10 @@ err_idr:
err_unreg:
ib_dereg_mr(mr);
+ atomic_dec(&pd->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_umem_release(file->device->ib_dev, &obj->umem);
@@ -512,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
if (!mr || mr->uobject->context != file->ucontext)
@@ -526,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&memobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_umem_release(file->device->ib_dev, &memobj->umem);
kfree(memobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -593,13 +594,18 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
if (cmd.comp_vector >= file->device->num_comp_vectors)
return -EINVAL;
- if (cmd.comp_channel >= 0)
- ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
-
uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
if (!uobj)
return -ENOMEM;
+ if (cmd.comp_channel >= 0) {
+ ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
+ if (!ev_file) {
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
uobj->uobject.user_handle = cmd.user_handle;
uobj->uobject.context = file->ucontext;
uobj->uverbs_file = file;
@@ -622,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file,
cq->cq_context = ev_file;
atomic_set(&cq->usecnt, 0);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
retry:
if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
@@ -647,11 +653,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -659,10 +665,12 @@ err_idr:
idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
ib_destroy_cq(cq);
err:
+ if (ev_file)
+ ib_uverbs_release_ucq(file, ev_file, uobj);
kfree(uobj);
return ret;
}
@@ -693,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
goto out_wc;
}
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext) {
ret = -EINVAL;
@@ -723,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(resp);
out_wc:
@@ -742,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (cq && cq->uobject->context == file->ucontext) {
ib_req_notify_cq(cq, cmd.solicited_only ?
IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
ret = in_len;
}
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret;
}
@@ -771,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
if (!cq || cq->uobject->context != file->ucontext)
@@ -787,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_ucq(file, ev_file, uobj);
@@ -803,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -837,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
@@ -922,11 +930,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -935,9 +943,14 @@ err_idr:
err_destroy:
ib_destroy_qp(qp);
+ atomic_dec(&pd->usecnt);
+ atomic_dec(&attr.send_cq->usecnt);
+ atomic_dec(&attr.recv_cq->usecnt);
+ if (attr.srq)
+ atomic_dec(&attr.srq->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -959,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
if (!attr)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext) {
@@ -1020,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
ret = in_len;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(attr);
return ret;
@@ -1041,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
memset(&resp, 0, sizeof resp);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1060,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uevent.uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_uevent(file, &uobj->uevent);
@@ -1075,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1106,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
if (!user_wr)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1211,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1328,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
if (IS_ERR(wr))
return PTR_ERR(wr);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1349,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1379,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
if (IS_ERR(wr))
return PTR_ERR(wr);
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
if (!srq || srq->uobject->context != file->ucontext)
@@ -1400,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
while (wr) {
next = wr->next;
@@ -1433,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
if (!pd || pd->uobject->context != file->ucontext) {
@@ -1448,6 +1461,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,
attr.sl = cmd.attr.sl;
attr.src_path_bits = cmd.attr.src_path_bits;
attr.static_rate = cmd.attr.static_rate;
+ attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0;
attr.port_num = cmd.attr.port_num;
attr.grh.flow_label = cmd.attr.grh.flow_label;
attr.grh.sgid_index = cmd.attr.grh.sgid_index;
@@ -1484,11 +1498,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->list, &file->ucontext->ah_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -1499,7 +1513,7 @@ err_destroy:
ib_destroy_ah(ah);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -1516,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
if (!ah || ah->uobject->context != file->ucontext)
@@ -1530,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
kfree(uobj);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1555,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1588,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
kfree(mcast);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1606,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
if (!qp || qp->uobject->context != file->ucontext)
@@ -1627,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file,
}
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1659,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
if (!uobj)
return -ENOMEM;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
@@ -1716,11 +1730,11 @@ retry:
goto err_idr;
}
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return in_len;
@@ -1729,9 +1743,10 @@ err_idr:
err_destroy:
ib_destroy_srq(srq);
+ atomic_dec(&pd->usecnt);
err_up:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
kfree(uobj);
return ret;
@@ -1749,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
if (!srq || srq->uobject->context != file->ucontext) {
@@ -1763,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return ret ? ret : in_len;
}
@@ -1781,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
memset(&resp, 0, sizeof resp);
@@ -1797,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
- down(&file->mutex);
+ mutex_lock(&file->mutex);
list_del(&uobj->uobject.list);
- up(&file->mutex);
+ mutex_unlock(&file->mutex);
ib_uverbs_release_uevent(file, uobj);
@@ -1812,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
ret = -EFAULT;
out:
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&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 81737bd6faea..96ea79b63df7 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -66,7 +66,7 @@ enum {
static struct class *uverbs_class;
-DECLARE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_MUTEX(ib_uverbs_idr_mutex);
DEFINE_IDR(ib_uverbs_pd_idr);
DEFINE_IDR(ib_uverbs_mr_idr);
DEFINE_IDR(ib_uverbs_mw_idr);
@@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
if (!context)
return 0;
- down(&ib_uverbs_idr_mutex);
+ mutex_lock(&ib_uverbs_idr_mutex);
list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
@@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uobj);
}
- up(&ib_uverbs_idr_mutex);
+ mutex_unlock(&ib_uverbs_idr_mutex);
return context->device->dealloc_ucontext(context);
}
@@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file->ucontext = NULL;
file->async_file = NULL;
kref_init(&file->ref);
- init_MUTEX(&file->mutex);
+ mutex_init(&file->mutex);
filp->private_data = file;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 4c15e112736c..c857361be449 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -107,9 +107,9 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
if (wc->wc_flags & IB_WC_GRH) {
ah_attr.ah_flags = IB_AH_GRH;
- ah_attr.grh.dgid = grh->dgid;
+ ah_attr.grh.dgid = grh->sgid;
- ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num,
+ ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num,
&gid_index);
if (ret)
return ERR_PTR(ret);
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
index 22fdc446f25c..a14eed08a0fc 100644
--- a/drivers/infiniband/hw/mthca/mthca_av.c
+++ b/drivers/infiniband/hw/mthca/mthca_av.c
@@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
return 0;
}
+int mthca_ah_grh_present(struct mthca_ah *ah)
+{
+ return !!(ah->av->g_slid & 0x80);
+}
+
int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header)
{
@@ -172,8 +177,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 = cpu_to_be16(ah->av->g_slid & 0x7f);
- if (ah->av->g_slid & 0x80) {
- header->grh_present = 1;
+ if (mthca_ah_grh_present(ah)) {
header->grh.traffic_class =
(be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff;
header->grh.flow_label =
@@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
&header->grh.source_gid);
memcpy(header->grh.destination_gid.raw,
ah->av->dgid, 16);
- } else {
- header->grh_present = 0;
}
return 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 9ed34587fc5c..be1791be627b 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm,
err = -EINVAL;
goto out;
}
- for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) {
+ for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) {
if (virt != -1) {
pages[nent * 2] = cpu_to_be64(virt);
virt += 1 << lg;
@@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
* system pages needed.
*/
dev->fw.arbel.fw_pages =
- (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >>
- (PAGE_SHIFT - 12);
+ ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >>
+ (PAGE_SHIFT - 12);
mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n",
(unsigned long long) dev->fw.arbel.clr_int_base,
@@ -937,10 +937,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
if (err)
goto out;
- MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
- dev_lim->max_srq_sz = (1 << field) - 1;
- MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
- dev_lim->max_qp_sz = (1 << field) - 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET);
dev_lim->reserved_qps = 1 << (field & 0xf);
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET);
@@ -1056,6 +1052,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags);
if (mthca_is_memfree(dev)) {
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
+ dev_lim->max_srq_sz = 1 << field;
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
+ dev_lim->max_qp_sz = 1 << field;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET);
dev_lim->hca.arbel.resize_srq = field & 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET);
@@ -1087,6 +1087,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
mthca_dbg(dev, "Max ICM size %lld MB\n",
(unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20);
} else {
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET);
+ dev_lim->max_srq_sz = (1 << field) - 1;
+ MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET);
+ dev_lim->max_qp_sz = (1 << field) - 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET);
dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f);
dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE;
@@ -1441,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages,
* pages needed.
*/
*aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12);
+ *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12);
return 0;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 4a8adcef2079..96f1a86bf049 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -128,12 +128,12 @@ struct mthca_err_cqe {
__be32 my_qpn;
u32 reserved1[3];
u8 syndrome;
- u8 reserved2;
+ u8 vendor_err;
__be16 db_cnt;
- u32 reserved3;
+ u32 reserved2;
__be32 wqe;
u8 opcode;
- u8 reserved4[2];
+ u8 reserved3[2];
u8 owner;
};
@@ -253,6 +253,15 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn,
wake_up(&cq->wait);
}
+static inline int is_recv_cqe(struct mthca_cqe *cqe)
+{
+ if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
+ MTHCA_ERROR_CQE_OPCODE_MASK)
+ return !(cqe->opcode & 0x01);
+ else
+ return !(cqe->is_send & 0x80);
+}
+
void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
struct mthca_srq *srq)
{
@@ -296,7 +305,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
while ((int) --prod_index - (int) cq->cons_index >= 0) {
cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
if (cqe->my_qpn == cpu_to_be32(qpn)) {
- if (srq)
+ if (srq && is_recv_cqe(cqe))
mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
++nfreed;
} else if (nfreed)
@@ -333,8 +342,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
}
/*
- * For completions in error, only work request ID, status (and
- * freed resource count for RD) have to be set.
+ * For completions in error, only work request ID, status, vendor error
+ * (and freed resource count for RD) have to be set.
*/
switch (cqe->syndrome) {
case SYNDROME_LOCAL_LENGTH_ERR:
@@ -396,6 +405,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq,
break;
}
+ entry->vendor_err = cqe->vendor_err;
+
/*
* 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.
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index 497ff794ef6a..a104ab041ea3 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -43,6 +43,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
+#include <linux/timer.h>
#include <asm/semaphore.h>
#include "mthca_provider.h"
@@ -519,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev,
int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah);
int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
struct ib_ud_header *header);
+int mthca_ah_grh_present(struct mthca_ah *ah);
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid);
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 34d68e5a72d8..2eabb27804cd 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -45,6 +45,7 @@
enum {
MTHCA_NUM_ASYNC_EQE = 0x80,
MTHCA_NUM_CMD_EQE = 0x80,
+ MTHCA_NUM_SPARE_EQE = 0x80,
MTHCA_EQ_ENTRY_SIZE = 0x20
};
@@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
{
struct mthca_eqe *eqe;
int disarm_cqn;
- int eqes_found = 0;
+ int eqes_found = 0;
+ int set_ci = 0;
while ((eqe = next_eqe_sw(eq))) {
- int set_ci = 0;
-
/*
* Make sure we read EQ entry contents after we've
* checked the ownership bit.
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
be16_to_cpu(eqe->event.cmd.token),
eqe->event.cmd.status,
be64_to_cpu(eqe->event.cmd.out_param));
- /*
- * cmd_event() may add more commands.
- * The card will think the queue has overflowed if
- * we don't tell it we've been processing events.
- */
- set_ci = 1;
break;
case MTHCA_EVENT_TYPE_PORT_CHANGE:
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
set_eqe_hw(eqe);
++eq->cons_index;
eqes_found = 1;
+ ++set_ci;
- if (unlikely(set_ci)) {
+ /*
+ * The HCA will think the queue has overflowed if we
+ * don't tell it we've been processing events. We
+ * create our EQs with MTHCA_NUM_SPARE_EQE extra
+ * entries, so we must update our consumer index at
+ * least that often.
+ */
+ if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) {
/*
* Conditional on hca_type is OK here because
* this is a rare case, not the fast path.
@@ -484,8 +486,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
u8 intr,
struct mthca_eq *eq)
{
- int npages = (nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
- PAGE_SIZE;
+ int npages;
u64 *dma_list = NULL;
dma_addr_t t;
struct mthca_mailbox *mailbox;
@@ -496,6 +497,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev,
eq->dev = dev;
eq->nent = roundup_pow_of_two(max(nent, 2));
+ npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE;
eq->page_list = kmalloc(npages * sizeof *eq->page_list,
GFP_KERNEL);
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev)
intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
128 : dev->eq_table.inta_pin;
- err = mthca_create_eq(dev, dev->limits.num_cqs,
+ err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
&dev->eq_table.eq[MTHCA_EQ_COMP]);
if (err)
goto err_out_unmap;
- err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE,
+ err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
&dev->eq_table.eq[MTHCA_EQ_ASYNC]);
if (err)
goto err_out_comp;
- err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE,
+ err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
(dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
&dev->eq_table.eq[MTHCA_EQ_CMD]);
if (err)
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 6f94b25f3acd..8b00d9a0f6f4 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -261,6 +261,10 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev)
}
err = mthca_dev_lim(mdev, &dev_lim);
+ if (err) {
+ mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");
+ goto err_disable;
+ }
profile = default_profile;
profile.num_uar = dev_lim.uar_size / PAGE_SIZE;
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c
index 2fc449da418d..77bc6c746f43 100644
--- a/drivers/infiniband/hw/mthca/mthca_mcg.c
+++ b/drivers/infiniband/hw/mthca/mthca_mcg.c
@@ -111,7 +111,8 @@ static int find_mgm(struct mthca_dev *dev,
goto out;
if (status) {
mthca_err(dev, "READ_MGM returned status %02x\n", status);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
if (!memcmp(mgm->gid, zero_gid, 16)) {
@@ -126,7 +127,7 @@ static int find_mgm(struct mthca_dev *dev,
goto out;
*prev = *index;
- *index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ *index = be32_to_cpu(mgm->next_gid_index) >> 6;
} while (*index);
*index = -1;
@@ -153,8 +154,10 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ if (down_interruptible(&dev->mcg_table.sem)) {
+ err = -EINTR;
+ goto err_sem;
+ }
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -181,9 +184,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
-
+ memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid->raw, 16);
- mgm->next_gid_index = 0;
}
for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
@@ -209,6 +211,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (status) {
mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
err = -EINVAL;
+ goto out;
}
if (!link)
@@ -223,7 +226,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
@@ -234,7 +237,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
}
out:
+ if (err && link && index != -1) {
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
+ }
up(&dev->mcg_table.sem);
+ err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -255,8 +263,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ if (down_interruptible(&dev->mcg_table.sem)) {
+ err = -EINTR;
+ goto err_sem;
+ }
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
@@ -305,13 +315,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (i != 1)
goto out;
- goto out;
-
if (prev == -1) {
/* Remove entry from MGM */
- if (be32_to_cpu(mgm->next_gid_index) >> 5) {
- err = mthca_READ_MGM(dev,
- be32_to_cpu(mgm->next_gid_index) >> 5,
+ int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
+ if (amgm_index_to_free) {
+ err = mthca_READ_MGM(dev, amgm_index_to_free,
mailbox, &status);
if (err)
goto out;
@@ -332,9 +340,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
+ if (amgm_index_to_free) {
+ BUG_ON(amgm_index_to_free < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, amgm_index_to_free);
+ }
} else {
/* Remove entry from AMGM */
- index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
err = mthca_READ_MGM(dev, prev, mailbox, &status);
if (err)
goto out;
@@ -344,7 +356,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
@@ -354,10 +366,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
err = -EINVAL;
goto out;
}
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
}
out:
up(&dev->mcg_table.sem);
+ err_sem:
mthca_free_mailbox(dev, mailbox);
return err;
}
@@ -365,11 +380,12 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
{
int err;
+ int table_size = dev->limits.num_mgms + dev->limits.num_amgms;
err = mthca_alloc_init(&dev->mcg_table.alloc,
- dev->limits.num_amgms,
- dev->limits.num_amgms - 1,
- 0);
+ table_size,
+ table_size - 1,
+ dev->limits.num_mgms);
if (err)
return err;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index d72fe95cba08..9fb985a016e9 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -233,7 +233,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj)
for (i = 0; i < chunk->npages; ++i) {
if (chunk->mem[i].length >= offset) {
page = chunk->mem[i].page;
- break;
+ goto out;
}
offset -= chunk->mem[i].length;
}
@@ -485,6 +485,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
put_page(db_tab->page[i].mem.page);
}
}
+
+ kfree(db_tab);
}
int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 4cc7e2846df1..484a7e6b7f8c 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -33,7 +33,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
- * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $
+ * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $
*/
#include <rdma/ib_smi.h>
@@ -45,6 +45,14 @@
#include "mthca_user.h"
#include "mthca_memfree.h"
+static void init_query_mad(struct ib_smp *mad)
+{
+ mad->base_version = 1;
+ mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+ mad->class_version = 1;
+ mad->method = IB_MGMT_METHOD_GET;
+}
+
static int mthca_query_device(struct ib_device *ibdev,
struct ib_device_attr *props)
{
@@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev,
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
@@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev,
props->fw_ver = mdev->fw_ver;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
err = mthca_MAD_IFC(mdev, 1, 1,
1, NULL, NULL, in_mad, out_mad,
@@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev,
props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30));
props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32));
memcpy(&props->sys_image_guid, out_mad->data + 4, 8);
- memcpy(&props->node_guid, out_mad->data + 12, 8);
props->max_mr_size = ~0ull;
props->page_size_cap = mdev->limits.page_size_cap;
@@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
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;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
- in_mad->attr_mod = cpu_to_be32(port);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
- in_mad->attr_mod = cpu_to_be32(index / 32);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE;
+ in_mad->attr_mod = cpu_to_be32(index / 32);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
int err = -ENOMEM;
u8 status;
- in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad)
goto out;
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
- in_mad->attr_mod = cpu_to_be32(port);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
+ in_mad->attr_mod = cpu_to_be32(port);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
memcpy(gid->raw, out_mad->data + 8, 8);
- memset(in_mad, 0, sizeof *in_mad);
- in_mad->base_version = 1;
- in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
- in_mad->class_version = 1;
- in_mad->method = IB_MGMT_METHOD_GET;
- in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
- in_mad->attr_mod = cpu_to_be32(index / 8);
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_GUID_INFO;
+ in_mad->attr_mod = cpu_to_be32(index / 8);
err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
port, NULL, NULL, in_mad, out_mad,
@@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd,
if (pd->uobject) {
context = to_mucontext(pd->uobject->context);
- if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
- return ERR_PTR(-EFAULT);
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+ err = -EFAULT;
+ goto err_free;
+ }
err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
context->db_tab, ucmd.db_index,
@@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
if (pd->uobject) {
context = to_mucontext(pd->uobject->context);
- if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+ if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+ kfree(qp);
return ERR_PTR(-EFAULT);
+ }
err = mthca_map_user_db(to_mdev(pd->device), &context->uar,
context->db_tab,
@@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd,
if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK))
return ERR_PTR(-EINVAL);
- if (num_phys_buf > 1 &&
- ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK))
- return ERR_PTR(-EINVAL);
-
mask = 0;
total_size = 0;
for (i = 0; i < num_phys_buf; ++i) {
- if (i != 0 && buffer_list[i].addr & ~PAGE_MASK)
- return ERR_PTR(-EINVAL);
- if (i != 0 && i != num_phys_buf - 1 &&
- (buffer_list[i].size & ~PAGE_MASK))
- return ERR_PTR(-EINVAL);
+ if (i != 0)
+ mask |= buffer_list[i].addr;
+ if (i != num_phys_buf - 1)
+ mask |= buffer_list[i].addr + buffer_list[i].size;
total_size += buffer_list[i].size;
- if (i > 0)
- mask |= buffer_list[i].addr;
}
+ if (mask & ~PAGE_MASK)
+ return ERR_PTR(-EINVAL);
+
/* Find largest page shift we can use to cover buffers */
for (shift = PAGE_SHIFT; shift < 31; ++shift)
if (num_phys_buf > 1) {
@@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = {
&class_device_attr_board_id
};
+static int mthca_init_node_data(struct mthca_dev *dev)
+{
+ struct ib_smp *in_mad = NULL;
+ struct ib_smp *out_mad = NULL;
+ int err = -ENOMEM;
+ u8 status;
+
+ in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
+ out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
+ if (!in_mad || !out_mad)
+ goto out;
+
+ init_query_mad(in_mad);
+ in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
+
+ err = mthca_MAD_IFC(dev, 1, 1,
+ 1, NULL, NULL, in_mad, out_mad,
+ &status);
+ if (err)
+ goto out;
+ if (status) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
+
+out:
+ kfree(in_mad);
+ kfree(out_mad);
+ return err;
+}
+
int mthca_register_device(struct mthca_dev *dev)
{
int ret;
int i;
+ ret = mthca_init_node_data(dev);
+ if (ret)
+ return ret;
+
strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX);
dev->ib_dev.owner = THIS_MODULE;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 7450550db736..fba608ed7df2 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -383,12 +383,10 @@ static const struct {
[UC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
IB_QP_PATH_MIG_STATE),
[RC] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
- IB_QP_PKEY_INDEX |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
[MLX] = (IB_QP_CUR_STATE |
@@ -476,9 +474,8 @@ static const struct {
.opt_param = {
[UD] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
- [UC] = IB_QP_CUR_STATE,
- [RC] = (IB_QP_CUR_STATE |
- IB_QP_MIN_RNR_TIMER),
+ [UC] = (IB_QP_CUR_STATE |
+ IB_QP_ACCESS_FLAGS),
[MLX] = (IB_QP_CUR_STATE |
IB_QP_QKEY),
}
@@ -522,6 +519,55 @@ static void init_port(struct mthca_dev *dev, int port)
mthca_warn(dev, "INIT_IB returned status %02x.\n", status);
}
+static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr,
+ int attr_mask)
+{
+ u8 dest_rd_atomic;
+ u32 access_flags;
+ u32 hw_access_flags = 0;
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ dest_rd_atomic = attr->max_dest_rd_atomic;
+ else
+ dest_rd_atomic = qp->resp_depth;
+
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ access_flags = attr->qp_access_flags;
+ else
+ access_flags = qp->atomic_rd_en;
+
+ if (!dest_rd_atomic)
+ access_flags &= IB_ACCESS_REMOTE_WRITE;
+
+ if (access_flags & IB_ACCESS_REMOTE_READ)
+ hw_access_flags |= MTHCA_QP_BIT_RRE;
+ if (access_flags & IB_ACCESS_REMOTE_ATOMIC)
+ hw_access_flags |= MTHCA_QP_BIT_RAE;
+ if (access_flags & IB_ACCESS_REMOTE_WRITE)
+ hw_access_flags |= MTHCA_QP_BIT_RWE;
+
+ return cpu_to_be32(hw_access_flags);
+}
+
+static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path)
+{
+ path->g_mylmc = ah->src_path_bits & 0x7f;
+ path->rlid = cpu_to_be16(ah->dlid);
+ path->static_rate = !!ah->static_rate;
+
+ if (ah->ah_flags & IB_AH_GRH) {
+ path->g_mylmc |= 1 << 7;
+ path->mgid_index = ah->grh.sgid_index;
+ path->hop_limit = ah->grh.hop_limit;
+ path->sl_tclass_flowlabel =
+ cpu_to_be32((ah->sl << 28) |
+ (ah->grh.traffic_class << 20) |
+ (ah->grh.flow_label));
+ memcpy(path->rgid, ah->grh.dgid.raw, 16);
+ } else
+ path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28);
+}
+
int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
@@ -591,6 +637,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return -EINVAL;
}
+ if ((attr_mask & IB_QP_PORT) &&
+ (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
+ mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
+ return -EINVAL;
+ }
+
+ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+ attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
+ mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
+ attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
+ return -EINVAL;
+ }
+
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+ attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
+ mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
+ attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
+ return -EINVAL;
+ }
+
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
@@ -665,28 +731,14 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_RNR_RETRY) {
- qp_context->pri_path.rnr_retry = attr->rnr_retry << 5;
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY);
+ qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry =
+ attr->rnr_retry << 5;
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY |
+ MTHCA_QP_OPTPAR_ALT_RNR_RETRY);
}
if (attr_mask & IB_QP_AV) {
- qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f;
- qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid);
- qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate;
- if (attr->ah_attr.ah_flags & IB_AH_GRH) {
- qp_context->pri_path.g_mylmc |= 1 << 7;
- qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index;
- qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit;
- qp_context->pri_path.sl_tclass_flowlabel =
- cpu_to_be32((attr->ah_attr.sl << 28) |
- (attr->ah_attr.grh.traffic_class << 20) |
- (attr->ah_attr.grh.flow_label));
- memcpy(qp_context->pri_path.rgid,
- attr->ah_attr.grh.dgid.raw, 16);
- } else {
- qp_context->pri_path.sl_tclass_flowlabel =
- cpu_to_be32(attr->ah_attr.sl << 28);
- }
+ mthca_path_set(&attr->ah_attr, &qp_context->pri_path);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
}
@@ -695,7 +747,19 @@ 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_ACK_TIMEOUT);
}
- /* XXX alt_path */
+ if (attr_mask & IB_QP_ALT_PATH) {
+ if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
+ mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
+ attr->alt_port_num);
+ return -EINVAL;
+ }
+
+ mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path);
+ qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
+ attr->alt_port_num << 24);
+ qp_context->alt_path.ackto = attr->alt_timeout << 3;
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH);
+ }
/* leave rdd as 0 */
qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num);
@@ -703,9 +767,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->wqe_lkey = cpu_to_be32(qp->mr.ibmr.lkey);
qp_context->params1 = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) |
(MTHCA_FLIGHT_LIMIT << 24) |
- MTHCA_QP_BIT_SRE |
- MTHCA_QP_BIT_SWE |
- MTHCA_QP_BIT_SAE);
+ MTHCA_QP_BIT_SWE);
if (qp->sq_policy == IB_SIGNAL_ALL_WR)
qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC);
if (attr_mask & IB_QP_RETRY_CNT) {
@@ -714,9 +776,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
- qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ?
- ffs(attr->max_rd_atomic) - 1 : 0,
- 7) << 21);
+ if (attr->max_rd_atomic) {
+ qp_context->params1 |=
+ cpu_to_be32(MTHCA_QP_BIT_SRE |
+ MTHCA_QP_BIT_SAE);
+ qp_context->params1 |=
+ cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21);
+ }
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX);
}
@@ -729,71 +795,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index);
}
- if (attr_mask & IB_QP_ACCESS_FLAGS) {
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ?
- MTHCA_QP_BIT_RWE : 0);
-
- /*
- * Only enable RDMA reads and atomics if we have
- * responder resources set to a non-zero value.
- */
- if (qp->resp_depth) {
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ?
- MTHCA_QP_BIT_RRE : 0);
- qp_context->params2 |=
- cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC ?
- MTHCA_QP_BIT_RAE : 0);
- }
-
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
- MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
-
- qp->atomic_rd_en = attr->qp_access_flags;
- }
-
if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
- u8 rra_max;
-
- if (qp->resp_depth && !attr->max_dest_rd_atomic) {
- /*
- * Lowering our responder resources to zero.
- * Turn off reads RDMA and atomics as responder.
- * (RRE/RAE in params2 already zero)
- */
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
- }
-
- if (!qp->resp_depth && attr->max_dest_rd_atomic) {
- /*
- * Increasing our responder resources from
- * zero. Turn on RDMA reads and atomics as
- * appropriate.
- */
+ if (attr->max_dest_rd_atomic)
qp_context->params2 |=
- cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ?
- MTHCA_QP_BIT_RRE : 0);
- qp_context->params2 |=
- cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ?
- MTHCA_QP_BIT_RAE : 0);
-
- qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
- MTHCA_QP_OPTPAR_RAE);
- }
+ cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21);
- for (rra_max = 0;
- 1 << rra_max < attr->max_dest_rd_atomic &&
- rra_max < dev->qp_table.rdb_shift;
- ++rra_max)
- ; /* nothing */
-
- qp_context->params2 |= cpu_to_be32(rra_max << 21);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX);
+ }
- qp->resp_depth = attr->max_dest_rd_atomic;
+ if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) {
+ qp_context->params2 |= get_hw_access_flags(qp, attr, attr_mask);
+ qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
+ MTHCA_QP_OPTPAR_RRE |
+ MTHCA_QP_OPTPAR_RAE);
}
qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
@@ -835,8 +849,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
err = -EINVAL;
}
- if (!err)
+ if (!err) {
qp->state = new_state;
+ if (attr_mask & IB_QP_ACCESS_FLAGS)
+ qp->atomic_rd_en = attr->qp_access_flags;
+ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ qp->resp_depth = attr->max_dest_rd_atomic;
+ }
mthca_free_mailbox(dev, mailbox);
@@ -885,18 +904,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return err;
}
-static void mthca_adjust_qp_caps(struct mthca_dev *dev,
- struct mthca_pd *pd,
- struct mthca_qp *qp)
+static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz)
{
- int max_data_size;
-
/*
* Calculate the maximum size of WQE s/g segments, excluding
* the next segment and other non-data segments.
*/
- max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) -
- sizeof (struct mthca_next_seg);
+ int max_data_size = desc_sz - sizeof (struct mthca_next_seg);
switch (qp->transport) {
case MLX:
@@ -915,11 +929,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev,
break;
}
+ return max_data_size;
+}
+
+static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size)
+{
/* We don't support inline data for kernel QPs (yet). */
- if (!pd->ibpd.uobject)
- qp->max_inline_data = 0;
- else
- qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE;
+ return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0;
+}
+
+static void mthca_adjust_qp_caps(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_qp *qp)
+{
+ int max_data_size = mthca_max_data_size(dev, qp,
+ min(dev->limits.max_desc_sz,
+ 1 << qp->sq.wqe_shift));
+
+ qp->max_inline_data = mthca_max_inline_data(pd, max_data_size);
qp->sq.max_gs = min_t(int, dev->limits.max_sg,
max_data_size / sizeof (struct mthca_data_seg));
@@ -1186,13 +1213,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
}
static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
- struct mthca_qp *qp)
+ struct mthca_pd *pd, struct mthca_qp *qp)
{
+ int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz);
+
/* Sanity check QP size before proceeding */
- if (cap->max_send_wr > dev->limits.max_wqes ||
- cap->max_recv_wr > dev->limits.max_wqes ||
- cap->max_send_sge > dev->limits.max_sg ||
- cap->max_recv_sge > dev->limits.max_sg)
+ if (cap->max_send_wr > dev->limits.max_wqes ||
+ cap->max_recv_wr > dev->limits.max_wqes ||
+ cap->max_send_sge > dev->limits.max_sg ||
+ cap->max_recv_sge > dev->limits.max_sg ||
+ cap->max_inline_data > mthca_max_inline_data(pd, max_data_size))
+ return -EINVAL;
+
+ /*
+ * For MLX transport we need 2 extra S/G entries:
+ * one for the header and one for the checksum at the end
+ */
+ if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg)
return -EINVAL;
if (mthca_is_memfree(dev)) {
@@ -1211,14 +1248,6 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap,
MTHCA_INLINE_CHUNK_SIZE) /
sizeof (struct mthca_data_seg));
- /*
- * For MLX transport we need 2 extra S/G entries:
- * one for the header and one for the checksum at the end
- */
- if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) ||
- qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg)
- return -EINVAL;
-
return 0;
}
@@ -1233,7 +1262,7 @@ int mthca_alloc_qp(struct mthca_dev *dev,
{
int err;
- err = mthca_set_qp_size(dev, cap, qp);
+ err = mthca_set_qp_size(dev, cap, pd, qp);
if (err)
return err;
@@ -1276,7 +1305,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
int err;
- err = mthca_set_qp_size(dev, cap, &sqp->qp);
+ err = mthca_set_qp_size(dev, cap, pd, &sqp->qp);
if (err)
return err;
@@ -1405,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
u16 pkey;
ib_ud_header_init(256, /* assume a MAD */
- sqp->ud_header.grh_present,
+ mthca_ah_grh_present(to_mah(wr->wr.ud.ah)),
&sqp->ud_header);
err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header);
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index f7d234295efe..e7e153d9c4c6 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -201,7 +201,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd,
if (mthca_is_memfree(dev))
srq->max = roundup_pow_of_two(srq->max + 1);
- ds = min(64UL,
+ ds = max(64UL,
roundup_pow_of_two(sizeof (struct mthca_next_seg) +
srq->max_gs * sizeof (struct mthca_data_seg)));
srq->wqe_shift = long_log2(ds);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 9923a15a9996..e0a5412b7e68 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -45,11 +45,11 @@
#include <linux/config.h>
#include <linux/kref.h>
#include <linux/if_infiniband.h>
+#include <linux/mutex.h>
#include <net/neighbour.h>
#include <asm/atomic.h>
-#include <asm/semaphore.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_pack.h>
@@ -123,8 +123,8 @@ struct ipoib_dev_priv {
unsigned long flags;
- struct semaphore mcast_mutex;
- struct semaphore vlan_mutex;
+ struct mutex mcast_mutex;
+ struct mutex vlan_mutex;
struct rb_root path_tree;
struct list_head path_list;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 23885801b6d2..86bcdd72a107 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level,
#define IPOIB_OP_RECV (1ul << 31)
-static DECLARE_MUTEX(pkey_sem);
+static DEFINE_MUTEX(pkey_mutex);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
struct ib_pd *pd, struct ib_ah_attr *attr)
@@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev)
/* Shutdown the P_Key thread if still active */
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
set_bit(IPOIB_PKEY_STOP, &priv->flags);
cancel_delayed_work(&priv->pkey_task);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
flush_workqueue(ipoib_workqueue);
}
ipoib_mcast_stop_thread(dev, 1);
-
- /*
- * Flush the multicast groups first so we stop any multicast joins. The
- * completion thread may have already died and we may deadlock waiting
- * for the completion thread to finish some multicast joins.
- */
ipoib_mcast_dev_flush(dev);
- /* Delete broadcast and local addresses since they will be recreated */
- ipoib_mcast_dev_down(dev);
-
ipoib_flush_paths(dev);
return 0;
@@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev)
if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
ipoib_ib_dev_up(dev);
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
/* Flush any child interfaces too */
list_for_each_entry(cpriv, &priv->child_intfs, list)
ipoib_ib_dev_flush(&cpriv->dev);
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
ipoib_dbg(priv, "cleaning up ib_dev\n");
ipoib_mcast_stop_thread(dev, 1);
-
- /* Delete the broadcast address and the local address */
- ipoib_mcast_dev_down(dev);
+ ipoib_mcast_dev_flush(dev);
ipoib_transport_dev_cleanup(dev);
}
@@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr)
if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
ipoib_open(dev);
else {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->pkey_task,
HZ);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
}
}
@@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev)
/* P_Key value not assigned yet - start polling */
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
- down(&pkey_sem);
+ mutex_lock(&pkey_mutex);
clear_bit(IPOIB_PKEY_STOP, &priv->flags);
queue_delayed_work(ipoib_workqueue,
&priv->pkey_task,
HZ);
- up(&pkey_sem);
+ mutex_unlock(&pkey_mutex);
return 1;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 475d98fa9e26..fd3f5c862a5d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -47,6 +47,8 @@
#include <linux/ip.h>
#include <linux/in.h>
+#include <net/dst.h>
+
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("IP-over-InfiniBand net driver");
MODULE_LICENSE("Dual BSD/GPL");
@@ -103,7 +105,7 @@ int ipoib_open(struct net_device *dev)
struct ipoib_dev_priv *cpriv;
/* Bring up any child interfaces too */
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
list_for_each_entry(cpriv, &priv->child_intfs, list) {
int flags;
@@ -113,7 +115,7 @@ int ipoib_open(struct net_device *dev)
dev_change_flags(cpriv->dev, flags | IFF_UP);
}
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
netif_start_queue(dev);
@@ -138,7 +140,7 @@ static int ipoib_stop(struct net_device *dev)
struct ipoib_dev_priv *cpriv;
/* Bring down any child interfaces too */
- down(&priv->vlan_mutex);
+ mutex_lock(&priv->vlan_mutex);
list_for_each_entry(cpriv, &priv->child_intfs, list) {
int flags;
@@ -148,7 +150,7 @@ static int ipoib_stop(struct net_device *dev)
dev_change_flags(cpriv->dev, flags & ~IFF_UP);
}
- up(&priv->vlan_mutex);
+ mutex_unlock(&priv->vlan_mutex);
}
return 0;
@@ -890,8 +892,8 @@ static void ipoib_setup(struct net_device *dev)
spin_lock_init(&priv->lock);
spin_lock_init(&priv->tx_lock);
- init_MUTEX(&priv->mcast_mutex);
- init_MUTEX(&priv->vlan_mutex);
+ mutex_init(&priv->mcast_mutex);
+ mutex_init(&priv->vlan_mutex);
INIT_LIST_HEAD(&priv->path_list);
INIT_LIST_HEAD(&priv->child_intfs);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ef3ee035bbc8..98039da0caf0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -43,6 +43,8 @@
#include <linux/delay.h>
#include <linux/completion.h>
+#include <net/dst.h>
+
#include "ipoib.h"
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
@@ -53,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level,
"Enable multicast debug tracing if > 0");
#endif
-static DECLARE_MUTEX(mcast_mutex);
+static DEFINE_MUTEX(mcast_mutex);
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
struct ipoib_mcast {
@@ -95,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
unsigned long flags;
- LIST_HEAD(ah_list);
- struct ipoib_ah *ah, *tah;
ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -105,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
+ /*
+ * It's safe to call ipoib_put_ah() inside priv->lock
+ * here, because we know that mcast->ah will always
+ * hold one more reference, so ipoib_put_ah() will
+ * never do more than decrement the ref count.
+ */
if (neigh->ah)
- list_add_tail(&neigh->ah->list, &ah_list);
+ ipoib_put_ah(neigh->ah);
*to_ipoib_neigh(neigh->neighbour) = NULL;
neigh->neighbour->ops->destructor = NULL;
kfree(neigh);
@@ -114,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry_safe(ah, tah, &ah_list, list)
- ipoib_put_ah(ah);
-
if (mcast->ah)
ipoib_put_ah(mcast->ah);
@@ -382,10 +385,10 @@ static void ipoib_mcast_join_complete(int status,
if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
mcast->backoff = 1;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
complete(&mcast->done);
return;
}
@@ -415,7 +418,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->query = NULL;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
if (status == -ETIMEDOUT)
queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -424,7 +427,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->backoff * HZ);
} else
complete(&mcast->done);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -479,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task,
mcast->backoff * HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
} else
mcast->query_id = ret;
}
@@ -517,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
priv->broadcast = ipoib_mcast_alloc(dev, 1);
if (!priv->broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task, HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -577,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
ipoib_dbg_mcast(priv, "starting multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return 0;
}
@@ -592,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
cancel_delayed_work(&priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
if (flush)
flush_workqueue(ipoib_workqueue);
@@ -739,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
LIST_HEAD(remove_list);
- struct ipoib_mcast *mcast, *tmcast, *nmcast;
+ struct ipoib_mcast *mcast, *tmcast;
unsigned long flags;
ipoib_dbg_mcast(priv, "flushing multicast list\n");
spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->flags =
- mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY);
-
- nmcast->mcmember.mgid = mcast->mcmember.mgid;
-
- /* Add the new group in before the to-be-destroyed group */
- list_add_tail(&nmcast->list, &mcast->list);
- list_del_init(&mcast->list);
-
- rb_replace_node(&mcast->rb_node, &nmcast->rb_node,
- &priv->multicast_tree);
- list_add_tail(&mcast->list, &remove_list);
- } else {
- ipoib_warn(priv, "could not reallocate multicast group "
- IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- }
+ list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
+ list_del(&mcast->list);
+ rb_erase(&mcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&mcast->list, &remove_list);
}
if (priv->broadcast) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid;
-
- rb_replace_node(&priv->broadcast->rb_node,
- &nmcast->rb_node,
- &priv->multicast_tree);
-
- list_add_tail(&priv->broadcast->list, &remove_list);
- }
-
- priv->broadcast = nmcast;
+ rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&priv->broadcast->list, &remove_list);
+ priv->broadcast = NULL;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -791,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
}
}
-void ipoib_mcast_dev_down(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
-
- /* Delete broadcast since it will be recreated */
- if (priv->broadcast) {
- ipoib_dbg_mcast(priv, "deleting broadcast group\n");
-
- spin_lock_irqsave(&priv->lock, flags);
- rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
- spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_mcast_leave(dev, priv->broadcast);
- ipoib_mcast_free(priv->broadcast);
- priv->broadcast = NULL;
- }
-}
-
void ipoib_mcast_restart_task(void *dev_ptr)
{
struct net_device *dev = dev_ptr;
@@ -822,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
ipoib_mcast_stop_thread(dev, 0);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&dev->xmit_lock, flags);
+ spin_lock(&priv->lock);
/*
* Unfortunately, the networking core only gives us a list of all of
@@ -894,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr)
list_add_tail(&mcast->list, &remove_list);
}
}
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&dev->xmit_lock, flags);
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index e829e10400e3..faaf10e5fc7b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
}
/* attach QP to multicast group */
- down(&priv->mcast_mutex);
+ mutex_lock(&priv->mcast_mutex);
ret = ib_attach_mcast(priv->qp, mgid, mlid);
- up(&priv->mcast_mutex);
+ mutex_unlock(&priv->mcast_mutex);
if (ret)
ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret);
@@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
struct ipoib_dev_priv *priv = netdev_priv(dev);
int ret;
- down(&priv->mcast_mutex);
+ mutex_lock(&priv->mcast_mutex);
ret = ib_detach_mcast(priv->qp, mgid, mlid);
- up(&priv->mcast_mutex);
+ mutex_unlock(&priv->mcast_mutex);
if (ret)
ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d280b341a37f..4ca175553f9f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
- down(&ppriv->vlan_mutex);
+ mutex_lock(&ppriv->vlan_mutex);
/*
* First ensure this isn't a duplicate. We check the parent device and
@@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
list_add_tail(&priv->list, &ppriv->child_intfs);
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return 0;
@@ -139,7 +139,7 @@ device_init_failed:
free_netdev(priv->dev);
err:
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return result;
}
@@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
- down(&ppriv->vlan_mutex);
+ mutex_lock(&ppriv->vlan_mutex);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
unregister_netdev(priv->dev);
@@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
break;
}
}
- up(&ppriv->vlan_mutex);
+ mutex_unlock(&ppriv->vlan_mutex);
return ret;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index ee9fe226ae99..31207e664148 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -39,6 +39,7 @@
#include <linux/string.h>
#include <linux/parser.h>
#include <linux/random.h>
+#include <linux/jiffies.h>
#include <asm/atomic.h>
@@ -1515,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf)
static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
-static struct srp_host *srp_add_port(struct ib_device *device,
- __be64 node_guid, u8 port)
+static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
{
struct srp_host *host;
@@ -1531,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device,
host->port = port;
host->initiator_port_id[7] = port;
- memcpy(host->initiator_port_id + 8, &node_guid, 8);
+ memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
host->pd = ib_alloc_pd(device);
if (IS_ERR(host->pd))
@@ -1579,22 +1579,11 @@ static void srp_add_one(struct ib_device *device)
{
struct list_head *dev_list;
struct srp_host *host;
- struct ib_device_attr *dev_attr;
int s, e, p;
- dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
- if (!dev_attr)
- return;
-
- if (ib_query_device(device, dev_attr)) {
- printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n",
- device->name);
- goto out;
- }
-
dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
if (!dev_list)
- goto out;
+ return;
INIT_LIST_HEAD(dev_list);
@@ -1607,15 +1596,12 @@ static void srp_add_one(struct ib_device *device)
}
for (p = s; p <= e; ++p) {
- host = srp_add_port(device, dev_attr->node_guid, p);
+ host = srp_add_port(device, p);
if (host)
list_add_tail(&host->list, dev_list);
}
ib_set_client_data(device, &srp_client, dev_list);
-
-out:
- kfree(dev_attr);
}
static void srp_remove_one(struct ib_device *device)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9f2352bd8348..745979f33dc2 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -146,6 +146,7 @@ static int evdev_open(struct inode * inode, struct file * file)
}
#ifdef CONFIG_COMPAT
+
struct input_event_compat {
struct compat_timeval time;
__u16 type;
@@ -153,11 +154,13 @@ struct input_event_compat {
__s32 value;
};
+/* Note to the author of this code: did it ever occur to
+ you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
-# define COMPAT_TEST test_thread_flag(TIF_IA32)
+# define COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
-# define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current))
-#elif defined(CONFIG_ARCH_S390)
+# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
+#elif defined(CONFIG_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
# define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
@@ -165,98 +168,107 @@ struct input_event_compat {
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
-static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static inline size_t evdev_event_size(void)
{
- struct evdev_list *list = file->private_data;
- struct input_event_compat event;
- int retval = 0;
+ return COMPAT_TEST ?
+ sizeof(struct input_event_compat) : sizeof(struct input_event);
+}
- while (retval < count) {
- if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat)))
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+ if (COMPAT_TEST) {
+ struct input_event_compat compat_event;
+
+ if (copy_from_user(&compat_event, buffer, sizeof(struct input_event_compat)))
+ return -EFAULT;
+
+ event->time.tv_sec = compat_event.time.tv_sec;
+ event->time.tv_usec = compat_event.time.tv_usec;
+ event->type = compat_event.type;
+ event->code = compat_event.code;
+ event->value = compat_event.value;
+
+ } else {
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
- retval += sizeof(struct input_event_compat);
}
- return retval;
+ return 0;
}
-#endif
-static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
{
- struct evdev_list *list = file->private_data;
- struct input_event event;
- int retval = 0;
-
- if (!list->evdev->exist) return -ENODEV;
+ if (COMPAT_TEST) {
+ struct input_event_compat compat_event;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_write_compat(file, buffer, count, ppos);
-#endif
+ compat_event.time.tv_sec = event->time.tv_sec;
+ compat_event.time.tv_usec = event->time.tv_usec;
+ compat_event.type = event->type;
+ compat_event.code = event->code;
+ compat_event.value = event->value;
- while (retval < count) {
+ if (copy_to_user(buffer, &compat_event, sizeof(struct input_event_compat)))
+ return -EFAULT;
- if (copy_from_user(&event, buffer + retval, sizeof(struct input_event)))
+ } else {
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
return -EFAULT;
- input_event(list->evdev->handle.dev, event.type, event.code, event.value);
- retval += sizeof(struct input_event);
}
- return retval;
+ return 0;
}
-#ifdef CONFIG_COMPAT
-static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
+#else
+
+static inline size_t evdev_event_size(void)
{
- struct evdev_list *list = file->private_data;
- int retval;
+ return sizeof(struct input_event);
+}
- if (count < sizeof(struct input_event_compat))
- return -EINVAL;
+static int evdev_event_from_user(const char __user *buffer, struct input_event *event)
+{
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
+ return -EFAULT;
- if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
- return -EAGAIN;
+ return 0;
+}
- retval = wait_event_interruptible(list->evdev->wait,
- list->head != list->tail || (!list->evdev->exist));
+static int evdev_event_to_user(char __user *buffer, const struct input_event *event)
+{
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
+ return -EFAULT;
- if (retval)
- return retval;
+ return 0;
+}
+
+#endif /* CONFIG_COMPAT */
+
+static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos)
+{
+ struct evdev_list *list = file->private_data;
+ struct input_event event;
+ int retval = 0;
if (!list->evdev->exist)
return -ENODEV;
- while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) {
- struct input_event *event = (struct input_event *) list->buffer + list->tail;
- struct input_event_compat event_compat;
- event_compat.time.tv_sec = event->time.tv_sec;
- event_compat.time.tv_usec = event->time.tv_usec;
- event_compat.type = event->type;
- event_compat.code = event->code;
- event_compat.value = event->value;
-
- if (copy_to_user(buffer + retval, &event_compat,
- sizeof(struct input_event_compat))) return -EFAULT;
- list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct input_event_compat);
+ while (retval < count) {
+
+ if (evdev_event_from_user(buffer + retval, &event))
+ return -EFAULT;
+ input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+ retval += evdev_event_size();
}
return retval;
}
-#endif
static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos)
{
struct evdev_list *list = file->private_data;
int retval;
-#ifdef CONFIG_COMPAT
- if (COMPAT_TEST)
- return evdev_read_compat(file, buffer, count, ppos);
-#endif
-
- if (count < sizeof(struct input_event))
+ if (count < evdev_event_size())
return -EINVAL;
if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
@@ -271,11 +283,15 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
if (!list->evdev->exist)
return -ENODEV;
- while (list->head != list->tail && retval + sizeof(struct input_event) <= count) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail,
- sizeof(struct input_event))) return -EFAULT;
+ while (list->head != list->tail && retval + evdev_event_size() <= count) {
+
+ struct input_event *event = (struct input_event *) list->buffer + list->tail;
+
+ if (evdev_event_to_user(buffer + retval, event))
+ return -EFAULT;
+
list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1);
- retval += sizeof(struct input_event);
+ retval += evdev_event_size();
}
return retval;
@@ -290,17 +306,95 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
}
-static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#ifdef CONFIG_COMPAT
+
+#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
+#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+
+#ifdef __BIG_ENDIAN
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len, i;
+
+ if (compat) {
+ len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+ if (len < maxlen)
+ len = maxlen;
+
+ for (i = 0; i < len / sizeof(compat_long_t); i++)
+ if (copy_to_user((compat_long_t __user *) p + i,
+ (compat_long_t *) bits +
+ i + 1 - ((i % 2) << 1),
+ sizeof(compat_long_t)))
+ return -EFAULT;
+ } else {
+ len = NBITS(maxbit) * sizeof(long);
+ if (len > maxlen)
+ len = maxlen;
+
+ if (copy_to_user(p, bits, len))
+ return -EFAULT;
+ }
+
+ return len;
+}
+#else
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len = compat ?
+ NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
+ NBITS(maxbit) * sizeof(long);
+
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+#endif /* __BIG_ENDIAN */
+
+#else
+
+static int bits_to_user(unsigned long *bits, unsigned int maxbit,
+ unsigned int maxlen, void __user *p, int compat)
+{
+ int len = NBITS(maxbit) * sizeof(long);
+
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, bits, len) ? -EFAULT : len;
+}
+
+#endif /* CONFIG_COMPAT */
+
+static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
+{
+ int len;
+
+ if (!str)
+ return -ENOENT;
+
+ len = strlen(str) + 1;
+ if (len > maxlen)
+ len = maxlen;
+
+ return copy_to_user(p, str, len) ? -EFAULT : len;
+}
+
+static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
+ void __user *p, int compat_mode)
{
struct evdev_list *list = file->private_data;
struct evdev *evdev = list->evdev;
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
- void __user *p = (void __user *)arg;
- int __user *ip = (int __user *)arg;
+ int __user *ip = (int __user *)p;
int i, t, u, v;
- if (!evdev->exist) return -ENODEV;
+ if (!evdev->exist)
+ return -ENODEV;
switch (cmd) {
@@ -308,26 +402,39 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return put_user(EV_VERSION, ip);
case EVIOCGID:
- return copy_to_user(p, &dev->id, sizeof(struct input_id)) ? -EFAULT : 0;
+ if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
+ return -EFAULT;
+
+ return 0;
case EVIOCGKEYCODE:
- if (get_user(t, ip)) return -EFAULT;
- if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
- if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
+ if (get_user(t, ip))
+ return -EFAULT;
+ if (t < 0 || t >= dev->keycodemax || !dev->keycodesize)
+ return -EINVAL;
+ if (put_user(INPUT_KEYCODE(dev, t), ip + 1))
+ return -EFAULT;
return 0;
case EVIOCSKEYCODE:
- if (get_user(t, ip)) return -EFAULT;
- 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 (dev->keycodesize < sizeof(v) && (v >> (dev->keycodesize * 8))) return -EINVAL;
+ if (get_user(t, ip))
+ return -EFAULT;
+ 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 (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);
for (i = 0; i < dev->keycodemax; i++)
- if (INPUT_KEYCODE(dev,i) == u)
+ if (INPUT_KEYCODE(dev, i) == u)
set_bit(u, dev->keybit);
+
return 0;
case EVIOCSFF:
@@ -338,17 +445,17 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (copy_from_user(&effect, p, sizeof(effect)))
return -EFAULT;
err = dev->upload_effect(dev, &effect);
- if (put_user(effect.id, &(((struct ff_effect __user *)arg)->id)))
+ if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
return -EFAULT;
return err;
- }
- else return -ENOSYS;
+ } else
+ return -ENOSYS;
case EVIOCRMFF:
- if (dev->erase_effect) {
- return dev->erase_effect(dev, (int)arg);
- }
- else return -ENOSYS;
+ if (!dev->erase_effect)
+ return -ENOSYS;
+
+ return dev->erase_effect(dev, (int)(unsigned long) p);
case EVIOCGEFFECTS:
if (put_user(dev->ff_effects_max, ip))
@@ -356,7 +463,7 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return 0;
case EVIOCGRAB:
- if (arg) {
+ if (p) {
if (evdev->grab)
return -EBUSY;
if (input_grab_device(&evdev->handle))
@@ -395,62 +502,33 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case EV_SW: bits = dev->swbit; len = SW_MAX; break;
default: return -EINVAL;
}
- len = NBITS(len) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, bits, len) ? -EFAULT : len;
+ return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
- int len;
- len = NBITS(KEY_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->key, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
+ return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
- int len;
- len = NBITS(LED_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->led, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
+ return bits_to_user(dev->led, LED_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
- int len;
- len = NBITS(SND_MAX) * sizeof(long);
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->snd, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
+ return bits_to_user(dev->snd, SND_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- 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(EVIOCGSW(0)))
+ return bits_to_user(dev->sw, SW_MAX, _IOC_SIZE(cmd),
+ p, compat_mode);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
- int len;
- if (!dev->name) return -ENOENT;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
+ return str_to_user(dev->name, _IOC_SIZE(cmd), p);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
+ return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
+ if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
+ return str_to_user(dev->uniq, _IOC_SIZE(cmd), p);
if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
@@ -492,158 +570,15 @@ static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EINVAL;
}
-#ifdef CONFIG_COMPAT
-
-#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1)
-#define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT)
-#define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x))
-#define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT)
-#define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1)
-
-#ifdef __BIG_ENDIAN
-#define bit_to_user(bit, max) \
-do { \
- int i; \
- 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 __user *) p + i, \
- (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \
- sizeof(compat_long_t))) \
- return -EFAULT; \
- return len; \
-} while (0)
-#else
-#define bit_to_user(bit, max) \
-do { \
- int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \
- return copy_to_user(p, (bit), len) ? -EFAULT : len; \
-} while (0)
-#endif
+static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return evdev_ioctl_handler(file, cmd, (void __user *)arg, 0);
+}
+#ifdef CONFIG_COMPAT
static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct evdev_list *list = file->private_data;
- struct evdev *evdev = list->evdev;
- struct input_dev *dev = evdev->handle.dev;
- struct input_absinfo abs;
- void __user *p = compat_ptr(arg);
-
- if (!evdev->exist) return -ENODEV;
-
- switch (cmd) {
-
- case EVIOCGVERSION:
- case EVIOCGID:
- case EVIOCGKEYCODE:
- case EVIOCSKEYCODE:
- case EVIOCSFF:
- case EVIOCRMFF:
- case EVIOCGEFFECTS:
- case EVIOCGRAB:
- return evdev_ioctl(file, cmd, (unsigned long) p);
-
- default:
-
- if (_IOC_TYPE(cmd) != 'E')
- return -EINVAL;
-
- if (_IOC_DIR(cmd) == _IOC_READ) {
-
- if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) {
- long *bits;
- int max;
-
- switch (_IOC_NR(cmd) & EV_MAX) {
- case 0: bits = dev->evbit; max = EV_MAX; break;
- case EV_KEY: bits = dev->keybit; max = KEY_MAX; break;
- case EV_REL: bits = dev->relbit; max = REL_MAX; break;
- case EV_ABS: bits = dev->absbit; max = ABS_MAX; break;
- case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break;
- case EV_LED: bits = dev->ledbit; max = LED_MAX; break;
- case EV_SND: bits = dev->sndbit; max = SND_MAX; break;
- case EV_FF: bits = dev->ffbit; max = FF_MAX; break;
- case EV_SW: bits = dev->swbit; max = SW_MAX; break;
- default: return -EINVAL;
- }
- bit_to_user(bits, max);
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
- bit_to_user(dev->key, KEY_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
- bit_to_user(dev->led, LED_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
- bit_to_user(dev->snd, SND_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
- bit_to_user(dev->sw, SW_MAX);
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
- int len;
- if (!dev->name) return -ENOENT;
- len = strlen(dev->name) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->name, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
- int len;
- if (!dev->phys) return -ENOENT;
- len = strlen(dev->phys) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->phys, len) ? -EFAULT : len;
- }
-
- if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
- int len;
- if (!dev->uniq) return -ENOENT;
- len = strlen(dev->uniq) + 1;
- if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
- return copy_to_user(p, dev->uniq, len) ? -EFAULT : len;
- }
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- abs.value = dev->abs[t];
- abs.minimum = dev->absmin[t];
- abs.maximum = dev->absmax[t];
- abs.fuzz = dev->absfuzz[t];
- abs.flat = dev->absflat[t];
-
- if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- return 0;
- }
- }
-
- if (_IOC_DIR(cmd) == _IOC_WRITE) {
-
- if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
-
- int t = _IOC_NR(cmd) & ABS_MAX;
-
- if (copy_from_user(&abs, p, sizeof(struct input_absinfo)))
- return -EFAULT;
-
- dev->abs[t] = abs.value;
- dev->absmin[t] = abs.minimum;
- dev->absmax[t] = abs.maximum;
- dev->absfuzz[t] = abs.fuzz;
- dev->absflat[t] = abs.flat;
-
- return 0;
- }
- }
- }
- return -EINVAL;
+ return evdev_ioctl_handler(file, cmd, compat_ptr(arg), 1);
}
#endif
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
index 7524bd7d8b8f..d279454a5c9e 100644
--- a/drivers/input/gameport/Kconfig
+++ b/drivers/input/gameport/Kconfig
@@ -52,5 +52,12 @@ config GAMEPORT_EMU10K1
config GAMEPORT_FM801
tristate "ForteMedia FM801 gameport support"
depends on PCI
+ help
+ Say Y here if you have ForteMedia FM801 PCI audio controller
+ (Abit AU10, Genius Sound Maker, HP Workstation zx2000,
+ and others), and want to use its gameport.
+
+ To compile this driver as a module, choose M here: the
+ module will be called fm801-gp.
endif
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index caac6d63d46f..b765a155c008 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem);
static LIST_HEAD(gameport_list);
-static struct bus_type gameport_bus = {
- .name = "gameport",
-};
+static struct bus_type gameport_bus;
static void gameport_add_port(struct gameport *gameport);
static void gameport_destroy_port(struct gameport *gameport);
@@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev)
return 0;
}
+static struct bus_type gameport_bus = {
+ .name = "gameport",
+ .probe = gameport_driver_probe,
+ .remove = gameport_driver_remove,
+};
+
void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
{
drv->driver.bus = &gameport_bus;
- drv->driver.probe = gameport_driver_probe;
- drv->driver.remove = gameport_driver_remove;
gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
}
diff --git a/drivers/input/input.c b/drivers/input/input.c
index bdd2a7fc268d..4fe3da3c667a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -18,7 +18,6 @@
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
-#include <linux/kobject_uevent.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
#include <linux/device.h>
@@ -478,8 +477,8 @@ static int __init input_proc_init(void)
entry->owner = THIS_MODULE;
input_fileops = *entry->proc_fops;
+ input_fileops.poll = input_devices_poll;
entry->proc_fops = &input_fileops;
- entry->proc_fops->poll = input_devices_poll;
entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
if (!entry)
@@ -529,10 +528,65 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
INPUT_DEV_STRING_ATTR_SHOW(uniq);
+static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr,
+ unsigned int min, unsigned int max)
+{
+ int len, i;
+
+ len = snprintf(buf, size, "%c", prefix);
+ for (i = min; i < max; i++)
+ if (arr[LONG(i)] & BIT(i))
+ len += snprintf(buf + len, size - len, "%X,", i);
+ return len;
+}
+
+static int print_modalias(char *buf, int size, struct input_dev *id)
+{
+ int len;
+
+ len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-",
+ id->id.bustype,
+ id->id.vendor,
+ id->id.product,
+ id->id.version);
+
+ len += print_modalias_bits(buf + len, size - len, 'e', id->evbit,
+ 0, EV_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'k', id->keybit,
+ KEY_MIN_INTERESTING, KEY_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'r', id->relbit,
+ 0, REL_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'a', id->absbit,
+ 0, ABS_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit,
+ 0, MSC_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit,
+ 0, LED_MAX);
+ len += print_modalias_bits(buf + len, size - len, 's', id->sndbit,
+ 0, SND_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit,
+ 0, FF_MAX);
+ len += print_modalias_bits(buf + len, size - len, 'w', id->swbit,
+ 0, SW_MAX);
+ return len;
+}
+
+static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+{
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len;
+
+ len = print_modalias(buf, PAGE_SIZE, id);
+ len += snprintf(buf + len, PAGE_SIZE-len, "\n");
+ return len;
+}
+static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+
static struct attribute *input_dev_attrs[] = {
&class_device_attr_name.attr,
&class_device_attr_phys.attr,
&class_device_attr_uniq.attr,
+ &class_device_attr_modalias.attr,
NULL
};
@@ -611,10 +665,10 @@ static void input_dev_release(struct class_device *class_dev)
}
/*
- * Input hotplugging interface - loading event handlers based on
+ * Input uevent interface - loading event handlers based on
* device bitfields.
*/
-static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
+static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *name, unsigned long *bitmap, int max)
{
@@ -639,7 +693,7 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
do { \
- int err = add_hotplug_env_var(envp, num_envp, &i, \
+ int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
@@ -648,15 +702,15 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
do { \
- int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
+ int err = input_add_uevent_bm_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
name, bm, max); \
if (err) \
return err; \
} while (0)
-static int input_dev_hotplug(struct class_device *cdev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int input_dev_uevent(struct class_device *cdev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct input_dev *dev = to_input_dev(cdev);
int i = 0;
@@ -690,15 +744,18 @@ static int input_dev_hotplug(struct class_device *cdev, char **envp,
if (test_bit(EV_SW, dev->evbit))
INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX);
- envp[i] = NULL;
+ envp[i++] = buffer + len;
+ len += snprintf(buffer + len, buffer_size - len, "MODALIAS=");
+ len += print_modalias(buffer + len, buffer_size - len, dev) + 1;
+ envp[i] = NULL;
return 0;
}
struct class input_class = {
.name = "input",
.release = input_dev_release,
- .hotplug = input_dev_hotplug,
+ .uevent = input_dev_uevent,
};
struct input_dev *input_allocate_device(void)
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 8558a99f6635..ec55a29fc861 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -64,8 +64,8 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
if (amijoy[i]) {
switch (i) {
- case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
- case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
+ case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
+ case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
}
input_regs(amijoy_dev[i], fp);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 51a912222e85..62438944a69a 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -53,17 +53,8 @@ struct grip_port {
struct grip_mp {
struct gameport *gameport;
struct grip_port *port[GRIP_MAX_PORTS];
-// struct input_dev *dev[4];
-// int mode[4];
-// int registered[4];
int reads;
int bads;
-
- /* individual gamepad states */
-// int buttons[4];
-// int xaxes[4];
-// int yaxes[4];
-// int dirty[4]; /* has the state been updated? */
};
/*
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 64b4a3080985..bc2fce60f9f8 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -235,7 +235,6 @@ static struct usb_device_id iforce_usb_ids [] = {
MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
struct usb_driver iforce_usb_driver = {
- .owner = THIS_MODULE,
.name = "iforce",
.probe = iforce_usb_probe,
.disconnect = iforce_usb_disconnect,
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 4a917748fd9f..3b0ac3b43c54 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -143,16 +143,6 @@ config KEYBOARD_SPITZ
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
- help
- Say Y here if you have a DreamCast console running Linux and have
- a keyboard attached to its Maple bus.
-
- To compile this driver as a module, choose M here: the
- module will be called maple_keyb.
-
config KEYBOARD_AMIGA
tristate "Amiga keyboard"
depends on AMIGA
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 9ce0b87f2fac..6e0afbb22383 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -5,7 +5,6 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
-obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index a0256f8de8ef..ffacf6eca5f5 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -321,7 +321,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
switch (code) {
case ATKBD_RET_BAT:
atkbd->enabled = 0;
- serio_rescan(atkbd->ps2dev.serio);
+ serio_reconnect(atkbd->ps2dev.serio);
goto out;
case ATKBD_RET_EMUL0:
atkbd->emul = 1;
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
index 64672d491222..e301ee4ca264 100644
--- a/drivers/input/keyboard/corgikbd.c
+++ b/drivers/input/keyboard/corgikbd.c
@@ -19,7 +19,6 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/irq.h>
#include <asm/arch/corgi.h>
#include <asm/arch/hardware.h>
@@ -343,10 +342,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
- SA_INTERRUPT, "corgikbd", corgikbd))
+ SA_INTERRUPT | SA_TRIGGER_RISING,
+ "corgikbd", corgikbd))
printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
- else
- set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING);
}
/* Set Strobe lines as outputs - set high */
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index 6a15fe3bc527..83999d583122 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -19,7 +19,6 @@
#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>
@@ -407,10 +406,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
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))
+ SA_INTERRUPT|SA_TRIGGER_RISING,
+ "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 */
@@ -422,15 +420,18 @@ static int __init spitzkbd_probe(struct platform_device *dev)
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);
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
+ SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING,
+ "Spitzkbd SWB", spitzkbd);
printk(KERN_INFO "input: Spitz Keyboard Registered\n");
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 1cd7657f7e42..1be963961c15 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -60,8 +60,6 @@ static struct fasync_struct *hp_sdc_rtc_async_queue;
static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
-static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin);
-
static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
size_t count, loff_t *ppos);
@@ -387,11 +385,6 @@ static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
return 0;
}
-static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
-
static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
size_t count, loff_t *ppos) {
ssize_t retval;
@@ -679,7 +672,7 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
static struct file_operations hp_sdc_rtc_fops = {
.owner = THIS_MODULE,
- .llseek = hp_sdc_rtc_llseek,
+ .llseek = no_llseek,
.read = hp_sdc_rtc_read,
.poll = hp_sdc_rtc_poll,
.ioctl = hp_sdc_rtc_ioctl,
diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c
index 04489ad7702a..8d6c3837badb 100644
--- a/drivers/input/misc/m68kspkr.c
+++ b/drivers/input/misc/m68kspkr.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -24,7 +25,7 @@ MODULE_AUTHOR("Richard Zidlicky <rz@linux-m68k.org>");
MODULE_DESCRIPTION("m68k beeper driver");
MODULE_LICENSE("GPL");
-static struct input_dev *m68kspkr_dev;
+static struct platform_device *m68kspkr_platform_device;
static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -47,36 +48,103 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0;
}
+static int __devinit m68kspkr_probe(struct platform_device *dev)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ return -ENOMEM;
+
+ input_dev->name = "m68k beeper";
+ input_dev->phys = "m68k/generic";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &dev->dev;
+
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
+ input_dev->event = m68kspkr_event;
+
+ err = input_register_device(input_dev);
+ if (err) {
+ input_free_device(input_dev);
+ return err;
+ }
+
+ platform_set_drvdata(dev, input_dev);
+
+ return 0;
+}
+
+static int __devexit m68kspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(input_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void m68kspkr_shutdown(struct platform_device *dev)
+{
+ /* turn off the speaker */
+ m68kspkr_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver m68kspkr_platform_driver = {
+ .driver = {
+ .name = "m68kspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = m68kspkr_probe,
+ .remove = __devexit_p(m68kspkr_remove),
+ .shutdown = m68kspkr_shutdown,
+};
+
static int __init m68kspkr_init(void)
{
- if (!mach_beep) {
+ int err;
+
+ if (!mach_beep) {
printk(KERN_INFO "m68kspkr: no lowlevel beep support\n");
return -ENODEV;
}
- m68kspkr_dev = input_allocate_device();
- if (!m68kspkr_dev)
- return -ENOMEM;
-
- m68kspkr_dev->name = "m68k beeper";
- m68kspkr_dev->phys = "m68k/generic";
- m68kspkr_dev->id.bustype = BUS_HOST;
- m68kspkr_dev->id.vendor = 0x001f;
- m68kspkr_dev->id.product = 0x0001;
- m68kspkr_dev->id.version = 0x0100;
+ err = platform_driver_register(&m68kspkr_platform_driver);
+ if (err)
+ return err;
- m68kspkr_dev->evbit[0] = BIT(EV_SND);
- m68kspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- m68kspkr_dev->event = m68kspkr_event;
+ m68kspkr_platform_device = platform_device_alloc("m68kspkr", -1);
+ if (!m68kspkr_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
- input_register_device(m68kspkr_dev);
+ err = platform_device_add(m68kspkr_platform_device);
+ if (err)
+ goto err_free_device;
return 0;
+
+ err_free_device:
+ platform_device_put(m68kspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&m68kspkr_platform_driver);
+
+ return err;
}
static void __exit m68kspkr_exit(void)
{
- input_unregister_device(m68kspkr_dev);
+ platform_device_unregister(m68kspkr_platform_device);
+ platform_driver_unregister(&m68kspkr_platform_driver);
}
module_init(m68kspkr_init);
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 68ac97f101b0..1ef477f4469c 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/8253pit.h>
#include <asm/io.h>
@@ -23,8 +24,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("PC Speaker beeper driver");
MODULE_LICENSE("GPL");
-static struct input_dev *pcspkr_dev;
-
+static struct platform_device *pcspkr_platform_device;
static DEFINE_SPINLOCK(i8253_beep_lock);
static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -64,8 +64,11 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
return 0;
}
-static int __init pcspkr_init(void)
+static int __devinit pcspkr_probe(struct platform_device *dev)
{
+ struct input_dev *pcspkr_dev;
+ int err;
+
pcspkr_dev = input_allocate_device();
if (!pcspkr_dev)
return -ENOMEM;
@@ -76,22 +79,93 @@ static int __init pcspkr_init(void)
pcspkr_dev->id.vendor = 0x001f;
pcspkr_dev->id.product = 0x0001;
pcspkr_dev->id.version = 0x0100;
+ pcspkr_dev->cdev.dev = &dev->dev;
pcspkr_dev->evbit[0] = BIT(EV_SND);
pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
pcspkr_dev->event = pcspkr_event;
- input_register_device(pcspkr_dev);
+ err = input_register_device(pcspkr_dev);
+ if (err) {
+ input_free_device(pcspkr_dev);
+ return err;
+ }
+
+ platform_set_drvdata(dev, pcspkr_dev);
return 0;
}
-static void __exit pcspkr_exit(void)
+static int __devexit pcspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *pcspkr_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(pcspkr_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+{
+ pcspkr_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void pcspkr_shutdown(struct platform_device *dev)
{
- input_unregister_device(pcspkr_dev);
/* turn off the speaker */
pcspkr_event(NULL, EV_SND, SND_BELL, 0);
}
+static struct platform_driver pcspkr_platform_driver = {
+ .driver = {
+ .name = "pcspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = pcspkr_probe,
+ .remove = __devexit_p(pcspkr_remove),
+ .suspend = pcspkr_suspend,
+ .shutdown = pcspkr_shutdown,
+};
+
+
+static int __init pcspkr_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&pcspkr_platform_driver);
+ if (err)
+ return err;
+
+ pcspkr_platform_device = platform_device_alloc("pcspkr", -1);
+ if (!pcspkr_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ err = platform_device_add(pcspkr_platform_device);
+ if (err)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(pcspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&pcspkr_platform_driver);
+
+ return err;
+}
+
+static void __exit pcspkr_exit(void)
+{
+ platform_device_unregister(pcspkr_platform_device);
+ platform_driver_unregister(&pcspkr_platform_driver);
+}
+
module_init(pcspkr_init);
module_exit(pcspkr_exit);
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 29d97b12be7a..f0fd2c4740f1 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/ebus.h>
@@ -20,22 +21,10 @@ MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
MODULE_DESCRIPTION("Sparc Speaker beeper driver");
MODULE_LICENSE("GPL");
+const char *beep_name;
static unsigned long beep_iobase;
-static struct input_dev *sparcspkr_dev;
-
-DEFINE_SPINLOCK(beep_lock);
-
-static void __init init_sparcspkr_struct(void)
-{
- sparcspkr_dev->evbit[0] = BIT(EV_SND);
- sparcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
-
- sparcspkr_dev->phys = "sparc/input0";
- sparcspkr_dev->id.bustype = BUS_ISA;
- sparcspkr_dev->id.vendor = 0x001f;
- sparcspkr_dev->id.product = 0x0001;
- sparcspkr_dev->id.version = 0x0100;
-}
+static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+static DEFINE_SPINLOCK(beep_lock);
static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -59,39 +48,16 @@ static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned in
/* EBUS speaker only has on/off state, the frequency does not
* appear to be programmable.
*/
- if (count) {
- if (beep_iobase & 0x2UL)
- outb(1, beep_iobase);
- else
- outl(1, beep_iobase);
- } else {
- if (beep_iobase & 0x2UL)
- outb(0, beep_iobase);
- else
- outl(0, beep_iobase);
- }
+ if (beep_iobase & 0x2UL)
+ outb(!!count, beep_iobase);
+ else
+ outl(!!count, beep_iobase);
spin_unlock_irqrestore(&beep_lock, flags);
return 0;
}
-static int __init init_ebus_beep(struct linux_ebus_device *edev)
-{
- beep_iobase = edev->resource[0].start;
-
- sparcspkr_dev = input_allocate_device();
- if (!sparcspkr_dev)
- return -ENOMEM;
-
- sparcspkr_dev->name = "Sparc EBUS Speaker";
- sparcspkr_dev->event = ebus_spkr_event;
-
- input_register_device(sparcspkr_dev);
-
- return 0;
-}
-
#ifdef CONFIG_SPARC64
static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -129,30 +95,103 @@ static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int
return 0;
}
+#endif
-static int __init init_isa_beep(struct sparc_isa_device *isa_dev)
+static int __devinit sparcspkr_probe(struct platform_device *dev)
{
- beep_iobase = isa_dev->resource.start;
+ struct input_dev *input_dev;
+ int error;
- sparcspkr_dev = input_allocate_device();
- if (!sparcspkr_dev)
+ input_dev = input_allocate_device();
+ if (!input_dev)
return -ENOMEM;
- init_sparcspkr_struct();
+ input_dev->name = beep_name;
+ input_dev->phys = "sparc/input0";
+ input_dev->id.bustype = BUS_ISA;
+ input_dev->id.vendor = 0x001f;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0100;
+ input_dev->cdev.dev = &dev->dev;
- sparcspkr_dev->name = "Sparc ISA Speaker";
- sparcspkr_dev->event = isa_spkr_event;
+ input_dev->evbit[0] = BIT(EV_SND);
+ input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
- input_register_device(sparcspkr_dev);
+ input_dev->event = beep_event;
+
+ error = input_register_device(input_dev);
+ if (error) {
+ input_free_device(input_dev);
+ return error;
+ }
+
+ platform_set_drvdata(dev, input_dev);
return 0;
}
-#endif
+
+static int __devexit sparcspkr_remove(struct platform_device *dev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+
+ input_unregister_device(input_dev);
+ platform_set_drvdata(dev, NULL);
+ /* turn off the speaker */
+ beep_event(NULL, EV_SND, SND_BELL, 0);
+
+ return 0;
+}
+
+static void sparcspkr_shutdown(struct platform_device *dev)
+{
+ /* turn off the speaker */
+ beep_event(NULL, EV_SND, SND_BELL, 0);
+}
+
+static struct platform_driver sparcspkr_platform_driver = {
+ .driver = {
+ .name = "sparcspkr",
+ .owner = THIS_MODULE,
+ },
+ .probe = sparcspkr_probe,
+ .remove = __devexit_p(sparcspkr_remove),
+ .shutdown = sparcspkr_shutdown,
+};
+
+static struct platform_device *sparcspkr_platform_device;
+
+static int __init sparcspkr_drv_init(void)
+{
+ int error;
+
+ error = platform_driver_register(&sparcspkr_platform_driver);
+ if (error)
+ return error;
+
+ sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1);
+ if (!sparcspkr_platform_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ error = platform_device_add(sparcspkr_platform_device);
+ if (error)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(sparcspkr_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&sparcspkr_platform_driver);
+
+ return error;
+}
static int __init sparcspkr_init(void)
{
struct linux_ebus *ebus;
- struct linux_ebus_device *edev = NULL;
+ struct linux_ebus_device *edev;
#ifdef CONFIG_SPARC64
struct sparc_isa_bridge *isa_br;
struct sparc_isa_device *isa_dev;
@@ -160,8 +199,12 @@ static int __init sparcspkr_init(void)
for_each_ebus(ebus) {
for_each_ebusdev(edev, ebus) {
- if (!strcmp(edev->prom_name, "beep"))
- return init_ebus_beep(edev);
+ if (!strcmp(edev->prom_name, "beep")) {
+ beep_name = "Sparc EBUS Speaker";
+ beep_event = ebus_spkr_event;
+ beep_iobase = edev->resource[0].start;
+ return sparcspkr_drv_init();
+ }
}
}
#ifdef CONFIG_SPARC64
@@ -170,8 +213,12 @@ static int __init sparcspkr_init(void)
/* A hack, the beep device's base lives in
* the DMA isa node.
*/
- if (!strcmp(isa_dev->prom_name, "dma"))
- return init_isa_beep(isa_dev);
+ if (!strcmp(isa_dev->prom_name, "dma")) {
+ beep_name = "Sparc ISA Speaker";
+ beep_event = isa_spkr_event,
+ beep_iobase = isa_dev->resource.start;
+ return sparcspkr_drv_init();
+ }
}
}
#endif
@@ -181,7 +228,8 @@ static int __init sparcspkr_init(void)
static void __exit sparcspkr_exit(void)
{
- input_unregister_device(sparcspkr_dev);
+ platform_device_unregister(sparcspkr_platform_device);
+ platform_driver_unregister(&sparcspkr_platform_driver);
}
module_init(sparcspkr_init);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index bac3085185fe..4b415d9b0123 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -92,11 +92,11 @@ static void call_bios(struct regs *regs)
preempt_enable();
}
-static size_t __init locate_wistron_bios(void __iomem *base)
+static ssize_t __init locate_wistron_bios(void __iomem *base)
{
static const unsigned char __initdata signature[] =
{ 0x42, 0x21, 0x55, 0x30 };
- size_t offset;
+ ssize_t offset;
for (offset = 0; offset < 0x10000; offset += 0x10) {
if (check_signature(base + offset, signature,
@@ -109,7 +109,7 @@ static size_t __init locate_wistron_bios(void __iomem *base)
static int __init map_bios(void)
{
void __iomem *base;
- size_t offset;
+ ssize_t offset;
u32 entry_point;
base = ioremap(0xF0000, 0x10000); /* Can't fail */
@@ -174,7 +174,7 @@ static u16 bios_pop_queue(void)
return regs.eax;
}
-static void __init bios_attach(void)
+static void __devinit bios_attach(void)
{
struct regs regs;
@@ -194,7 +194,7 @@ static void bios_detach(void)
call_bios(&regs);
}
-static u8 __init bios_get_cmos_address(void)
+static u8 __devinit bios_get_cmos_address(void)
{
struct regs regs;
@@ -206,7 +206,7 @@ static u8 __init bios_get_cmos_address(void)
return regs.ecx;
}
-static u16 __init bios_get_default_setting(u8 subsys)
+static u16 __devinit bios_get_default_setting(u8 subsys)
{
struct regs regs;
@@ -296,6 +296,16 @@ static struct key_entry keymap_acer_aspire_1500[] = {
{ KE_END, 0 }
};
+static struct key_entry keymap_acer_travelmate_240[] = {
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_BLUETOOTH, 0x44, 0 },
+ { KE_WIFI, 0x30, 0 },
+ { KE_END, 0 }
+};
+
/*
* If your machine is not here (which is currently rather likely), please send
* a list of buttons and their key codes (reported when loading this module
@@ -320,6 +330,15 @@ static struct dmi_system_id dmi_ids[] = {
},
.driver_data = keymap_acer_aspire_1500
},
+ {
+ .callback = dmi_matched,
+ .ident = "Acer TravelMate 240",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"),
+ },
+ .driver_data = keymap_acer_travelmate_240
+ },
{ NULL, }
};
@@ -348,7 +367,7 @@ static int __init select_keymap(void)
static struct input_dev *input_dev;
-static int __init setup_input_dev(void)
+static int __devinit setup_input_dev(void)
{
const struct key_entry *key;
int error;
@@ -447,6 +466,52 @@ static void poll_bios(unsigned long discard)
mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
}
+static int __devinit wistron_probe(struct platform_device *dev)
+{
+ int err = setup_input_dev();
+ if (err)
+ return err;
+
+ bios_attach();
+ cmos_address = bios_get_cmos_address();
+
+ if (have_wifi) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1)
+ wifi_enabled = (wifi & 2) ? 1 : 0;
+ else
+ have_wifi = 0;
+
+ if (have_wifi)
+ bios_set_state(WIFI, wifi_enabled);
+ }
+
+ if (have_bluetooth) {
+ u16 bt = bios_get_default_setting(BLUETOOTH);
+ if (bt & 1)
+ bluetooth_enabled = (bt & 2) ? 1 : 0;
+ else
+ have_bluetooth = 0;
+
+ if (have_bluetooth)
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
+ }
+
+ poll_bios(1); /* Flush stale event queue and arm timer */
+
+ return 0;
+}
+
+static int __devexit wistron_remove(struct platform_device *dev)
+{
+ del_timer_sync(&poll_timer);
+ input_unregister_device(input_dev);
+ bios_detach();
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{
del_timer_sync(&poll_timer);
@@ -472,13 +537,20 @@ static int wistron_resume(struct platform_device *dev)
return 0;
}
+#else
+#define wistron_suspend NULL
+#define wistron_resume NULL
+#endif
static struct platform_driver wistron_driver = {
- .suspend = wistron_suspend,
- .resume = wistron_resume,
.driver = {
.name = "wistron-bios",
+ .owner = THIS_MODULE,
},
+ .probe = wistron_probe,
+ .remove = __devexit_p(wistron_remove),
+ .suspend = wistron_suspend,
+ .resume = wistron_resume,
};
static int __init wb_module_init(void)
@@ -493,55 +565,27 @@ static int __init wb_module_init(void)
if (err)
return err;
- bios_attach();
- cmos_address = bios_get_cmos_address();
-
err = platform_driver_register(&wistron_driver);
if (err)
- goto err_detach_bios;
+ goto err_unmap_bios;
- wistron_device = platform_device_register_simple("wistron-bios", -1, NULL, 0);
- if (IS_ERR(wistron_device)) {
- err = PTR_ERR(wistron_device);
+ wistron_device = platform_device_alloc("wistron-bios", -1);
+ if (!wistron_device) {
+ err = -ENOMEM;
goto err_unregister_driver;
}
- if (have_wifi) {
- u16 wifi = bios_get_default_setting(WIFI);
- if (wifi & 1)
- wifi_enabled = (wifi & 2) ? 1 : 0;
- else
- have_wifi = 0;
-
- if (have_wifi)
- bios_set_state(WIFI, wifi_enabled);
- }
-
- if (have_bluetooth) {
- u16 bt = bios_get_default_setting(BLUETOOTH);
- if (bt & 1)
- bluetooth_enabled = (bt & 2) ? 1 : 0;
- else
- have_bluetooth = 0;
-
- if (have_bluetooth)
- bios_set_state(BLUETOOTH, bluetooth_enabled);
- }
-
- err = setup_input_dev();
+ err = platform_device_add(wistron_device);
if (err)
- goto err_unregister_device;
-
- poll_bios(1); /* Flush stale event queue and arm timer */
+ goto err_free_device;
return 0;
- err_unregister_device:
- platform_device_unregister(wistron_device);
+ err_free_device:
+ platform_device_put(wistron_device);
err_unregister_driver:
platform_driver_unregister(&wistron_driver);
- err_detach_bios:
- bios_detach();
+ err_unmap_bios:
unmap_bios();
return err;
@@ -549,11 +593,8 @@ static int __init wb_module_init(void)
static void __exit wb_module_exit(void)
{
- del_timer_sync(&poll_timer);
- input_unregister_device(input_dev);
platform_device_unregister(wistron_device);
platform_driver_unregister(&wistron_driver);
- bios_detach();
unmap_bios();
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 574b18a523af..f15ccf781688 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -86,16 +86,6 @@ config MOUSE_PC110PAD
To compile this driver as a module, choose M here: the
module will be called pc110pad.
-config MOUSE_MAPLE
- tristate "Maple bus mouse"
- depends on SH_DREAMCAST && MAPLE
- help
- Say Y if you have a DreamCast console and a mouse attached to
- its Maple bus.
-
- To compile this driver as a module, choose M here: the
- module will be called maplemouse.
-
config MOUSE_AMIGA
tristate "Amiga mouse"
depends on AMIGA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 82b330bbf068..21a1de61a79b 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
-obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o
obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4f41ec3e4332..2141501e9f2e 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -40,6 +40,7 @@ static struct alps_model_info alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
+ { { 0x60, 0x03, 0xc8 }, 0xf8, 0xf8, 0 }, /* HP ze1115 */
{ { 0x63, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Fujitsu Siemens S6010 */
@@ -347,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable)
return 0;
}
+/*
+ * alps_poll() - poll the touchpad for current motion packet.
+ * Used in resync.
+ */
+static int alps_poll(struct psmouse *psmouse)
+{
+ struct alps_data *priv = psmouse->private;
+ unsigned char buf[6];
+ int poll_failed;
+
+ if (priv->i->flags & ALPS_PASS)
+ alps_passthrough_mode(psmouse, 1);
+
+ poll_failed = ps2_command(&psmouse->ps2dev, buf,
+ PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
+
+ if (priv->i->flags & ALPS_PASS)
+ alps_passthrough_mode(psmouse, 0);
+
+ if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0)
+ return -1;
+
+ if ((psmouse->badbyte & 0xc8) == 0x08) {
+/*
+ * Poll the track stick ...
+ */
+ if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
+ return -1;
+ }
+
+ memcpy(psmouse->packet, buf, sizeof(buf));
+ return 0;
+}
+
static int alps_reconnect(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
@@ -450,10 +485,14 @@ int alps_init(struct psmouse *psmouse)
input_register_device(priv->dev2);
psmouse->protocol_handler = alps_process_byte;
+ psmouse->poll = alps_poll;
psmouse->disconnect = alps_disconnect;
psmouse->reconnect = alps_reconnect;
psmouse->pktsize = 6;
+ /* We are having trouble resyncing ALPS touchpads so disable it for now */
+ psmouse->resync_time = 0;
+
return 0;
init_fail:
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index d13d4c8fe3c5..c8b2cc9f184c 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -41,7 +41,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
unsigned short joy0dat, potgor;
int nx, ny, dx, dy;
- joy0dat = custom.joy0dat;
+ joy0dat = amiga_custom.joy0dat;
nx = joy0dat & 0xff;
ny = joy0dat >> 8;
@@ -57,7 +57,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
amimouse_lastx = nx;
amimouse_lasty = ny;
- potgor = custom.potgor;
+ potgor = amiga_custom.potgor;
input_regs(amimouse_dev, fp);
@@ -77,7 +77,7 @@ static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
- joy0dat = custom.joy0dat;
+ joy0dat = amiga_custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c
index 55991424ac91..5ccc3ef3b89e 100644
--- a/drivers/input/mouse/lifebook.c
+++ b/drivers/input/mouse/lifebook.c
@@ -27,6 +27,13 @@ static struct dmi_system_id lifebook_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
+ {
+ .ident = "Lifebook B142",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
+ },
+
+ },
{ }
};
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 31a59f7abfaf..c88520d3d13c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha
if (psmouse_sliced_command(psmouse, command))
return -1;
- if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL))
+ if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300))
return -1;
return 0;
@@ -226,7 +226,9 @@ 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 },
+ { 85, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 86, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
+ { 87, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 88, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 96, 0, 0 },
{ 97, PS2PP_KIND_TP3, PS2PP_WHEEL | PS2PP_HWHEEL },
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
deleted file mode 100644
index b5b34fe4fee8..000000000000
--- a/drivers/input/mouse/maplemouse.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
- * SEGA Dreamcast mouse driver
- * Based on drivers/usb/usbmouse.c
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/input.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/maple.h>
-
-MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
-MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
-
-static void dc_mouse_callback(struct mapleq *mq)
-{
- int buttons, relx, rely, relz;
- struct maple_device *mapledev = mq->dev;
- struct input_dev *dev = mapledev->private_data;
- unsigned char *res = mq->recvbuf;
-
- buttons = ~res[8];
- relx = *(unsigned short *)(res + 12) - 512;
- rely = *(unsigned short *)(res + 14) - 512;
- relz = *(unsigned short *)(res + 16) - 512;
-
- input_report_key(dev, BTN_LEFT, buttons & 4);
- input_report_key(dev, BTN_MIDDLE, buttons & 9);
- input_report_key(dev, BTN_RIGHT, buttons & 2);
- input_report_rel(dev, REL_X, relx);
- input_report_rel(dev, REL_Y, rely);
- input_report_rel(dev, REL_WHEEL, relz);
- input_sync(dev);
-}
-
-static int dc_mouse_connect(struct maple_device *dev)
-{
- unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
- struct input_dev *input_dev;
-
- dev->private_data = input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
-
- dev->private_data = input_dev;
-
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-
- input_dev->name = dev->product_name;
- input_dev->id.bustype = BUS_MAPLE;
-
- input_register_device(input_dev);
-
- maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
-
- return 0;
-}
-
-
-static void dc_mouse_disconnect(struct maple_device *dev)
-{
- struct input_dev *input_dev = dev->private_data;
-
- input_unregister_device(input_dev);
-}
-
-
-static struct maple_driver dc_mouse_driver = {
- .function = MAPLE_FUNC_MOUSE,
- .name = "Dreamcast mouse",
- .connect = dc_mouse_connect,
- .disconnect = dc_mouse_disconnect,
-};
-
-
-static int __init dc_mouse_init(void)
-{
- maple_register_driver(&dc_mouse_driver);
- return 0;
-}
-
-
-static void __exit dc_mouse_exit(void)
-{
- maple_unregister_driver(&dc_mouse_driver);
-}
-
-
-module_init(dc_mouse_init);
-module_exit(dc_mouse_exit);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 6ee9999a2eaa..7665fd9ce559 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1;
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
-static unsigned int psmouse_resetafter;
+static unsigned int psmouse_resetafter = 5;
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
+static unsigned int psmouse_resync_time = 5;
+module_param_named(resync_time, psmouse_resync_time, uint, 0644);
+MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never).");
+
PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO,
NULL,
psmouse_attr_show_protocol, psmouse_attr_set_protocol);
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO,
PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO,
(void *) offsetof(struct psmouse, resetafter),
psmouse_show_int_attr, psmouse_set_int_attr);
+PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO,
+ (void *) offsetof(struct psmouse, resync_time),
+ 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,
+ &psmouse_attr_resync_time.dattr.attr,
NULL
};
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate=");
*/
static DECLARE_MUTEX(psmouse_sem);
+static struct workqueue_struct *kpsmoused_wq;
+
struct psmouse_protocol {
enum psmouse_type type;
char *name;
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg
}
/*
- * psmouse_interrupt() handles incoming characters, either gathering them into
- * packets or passing them to the command routine as command output.
+ * __psmouse_set_state() sets new psmouse state and resets all flags.
+ */
+
+static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+ psmouse->state = new_state;
+ psmouse->pktcnt = psmouse->out_of_sync = 0;
+ psmouse->ps2dev.flags = 0;
+ psmouse->last = jiffies;
+}
+
+
+/*
+ * psmouse_set_state() sets new psmouse state and resets all flags and
+ * counters while holding serio lock so fighting with interrupt handler
+ * is not a concern.
+ */
+
+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+ serio_pause_rx(psmouse->ps2dev.serio);
+ __psmouse_set_state(psmouse, new_state);
+ serio_continue_rx(psmouse->ps2dev.serio);
+}
+
+/*
+ * psmouse_handle_byte() processes one byte of the input data stream
+ * by calling corresponding protocol handler.
+ */
+
+static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs)
+{
+ psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs);
+
+ switch (rc) {
+ case PSMOUSE_BAD_DATA:
+ if (psmouse->state == PSMOUSE_ACTIVATED) {
+ printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
+ psmouse->name, psmouse->phys, psmouse->pktcnt);
+ if (++psmouse->out_of_sync == psmouse->resetafter) {
+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
+ serio_reconnect(psmouse->ps2dev.serio);
+ return -1;
+ }
+ }
+ psmouse->pktcnt = 0;
+ break;
+
+ case PSMOUSE_FULL_PACKET:
+ psmouse->pktcnt = 0;
+ if (psmouse->out_of_sync) {
+ psmouse->out_of_sync = 0;
+ printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
+ psmouse->name, psmouse->phys);
+ }
+ break;
+
+ case PSMOUSE_GOOD_DATA:
+ break;
+ }
+ return 0;
+}
+
+/*
+ * psmouse_interrupt() handles incoming characters, either passing them
+ * for normal processing or gathering them as command response.
*/
static irqreturn_t psmouse_interrupt(struct serio *serio,
unsigned char data, unsigned int flags, struct pt_regs *regs)
{
struct psmouse *psmouse = serio_get_drvdata(serio);
- psmouse_ret_t rc;
if (psmouse->state == PSMOUSE_IGNORE)
goto out;
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (ps2_handle_response(&psmouse->ps2dev, data))
goto out;
- if (psmouse->state == PSMOUSE_INITIALIZING)
+ if (psmouse->state <= PSMOUSE_RESYNCING)
goto out;
if (psmouse->state == PSMOUSE_ACTIVATED &&
psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
- printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
+ printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
psmouse->name, psmouse->phys, psmouse->pktcnt);
- psmouse->pktcnt = 0;
+ psmouse->badbyte = psmouse->packet[0];
+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ queue_work(kpsmoused_wq, &psmouse->resync_work);
+ goto out;
}
- psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data;
-
- if (psmouse->packet[0] == PSMOUSE_RET_BAT) {
+/*
+ * Check if this is a new device announcement (0xAA 0x00)
+ */
+ if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
if (psmouse->pktcnt == 1)
goto out;
- if (psmouse->pktcnt == 2) {
- if (psmouse->packet[1] == PSMOUSE_RET_ID) {
- psmouse->state = PSMOUSE_IGNORE;
- serio_reconnect(serio);
- goto out;
- }
- if (psmouse->type == PSMOUSE_SYNAPTICS) {
- /* neither 0xAA nor 0x00 are valid first bytes
- * for a packet in absolute mode
- */
- psmouse->pktcnt = 0;
- goto out;
- }
+ if (psmouse->packet[1] == PSMOUSE_RET_ID) {
+ __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ serio_reconnect(serio);
+ goto out;
}
- }
-
- rc = psmouse->protocol_handler(psmouse, regs);
+/*
+ * Not a new device, try processing first byte normally
+ */
+ psmouse->pktcnt = 1;
+ if (psmouse_handle_byte(psmouse, regs))
+ goto out;
- switch (rc) {
- case PSMOUSE_BAD_DATA:
- printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n",
- psmouse->name, psmouse->phys, psmouse->pktcnt);
- psmouse->pktcnt = 0;
+ psmouse->packet[psmouse->pktcnt++] = data;
+ }
- if (++psmouse->out_of_sync == psmouse->resetafter) {
- psmouse->state = PSMOUSE_IGNORE;
- printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n");
- serio_reconnect(psmouse->ps2dev.serio);
- }
- break;
+/*
+ * See if we need to force resync because mouse was idle for too long
+ */
+ if (psmouse->state == PSMOUSE_ACTIVATED &&
+ psmouse->pktcnt == 1 && psmouse->resync_time &&
+ time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) {
+ psmouse->badbyte = psmouse->packet[0];
+ __psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ queue_work(kpsmoused_wq, &psmouse->resync_work);
+ goto out;
+ }
- case PSMOUSE_FULL_PACKET:
- psmouse->pktcnt = 0;
- if (psmouse->out_of_sync) {
- psmouse->out_of_sync = 0;
- printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n",
- psmouse->name, psmouse->phys);
- }
- break;
+ psmouse->last = jiffies;
+ psmouse_handle_byte(psmouse, regs);
- case PSMOUSE_GOOD_DATA:
- break;
- }
-out:
+ out:
return IRQ_HANDLED;
}
@@ -527,11 +592,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
if (max_proto > PSMOUSE_IMEX && ps2pp_init(psmouse, set_properties) == 0)
return PSMOUSE_PS2PP;
+ if (max_proto > PSMOUSE_IMEX && trackpoint_detect(psmouse, set_properties) == 0)
+ return PSMOUSE_TRACKPOINT;
+
/*
* Reset to defaults in case the device got confused by extended
- * protocol probes.
+ * protocol probes. Note that we do full reset becuase some mice
+ * put themselves to sleep when see PSMOUSE_RESET_DIS.
*/
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
+ psmouse_reset(psmouse);
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
return PSMOUSE_IMEX;
@@ -540,12 +609,6 @@ 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.
*/
@@ -559,7 +622,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
* extensions.
*/
psmouse_reset(psmouse);
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
}
return PSMOUSE_PS2;
@@ -755,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse)
}
/*
- * psmouse_set_state() sets new psmouse state and resets all flags and
- * counters while holding serio lock so fighting with interrupt handler
- * is not a concern.
- */
-
-static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
-{
- serio_pause_rx(psmouse->ps2dev.serio);
- psmouse->state = new_state;
- psmouse->pktcnt = psmouse->out_of_sync = 0;
- psmouse->ps2dev.flags = 0;
- serio_continue_rx(psmouse->ps2dev.serio);
-}
-
-/*
* psmouse_activate() enables the mouse so that we get motion reports from it.
*/
@@ -797,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
}
+/*
+ * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it.
+ */
+
+static int psmouse_poll(struct psmouse *psmouse)
+{
+ return ps2_command(&psmouse->ps2dev, psmouse->packet,
+ PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
+}
+
+
+/*
+ * psmouse_resync() attempts to re-validate current protocol.
+ */
+
+static void psmouse_resync(void *p)
+{
+ struct psmouse *psmouse = p, *parent = NULL;
+ struct serio *serio = psmouse->ps2dev.serio;
+ psmouse_ret_t rc = PSMOUSE_GOOD_DATA;
+ int failed = 0, enabled = 0;
+ int i;
+
+ down(&psmouse_sem);
+
+ if (psmouse->state != PSMOUSE_RESYNCING)
+ goto out;
+
+ if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+ parent = serio_get_drvdata(serio->parent);
+ psmouse_deactivate(parent);
+ }
+
+/*
+ * Some mice don't ACK commands sent while they are in the middle of
+ * transmitting motion packet. To avoid delay we use ps2_sendbyte()
+ * instead of ps2_command() which would wait for 200ms for an ACK
+ * that may never come.
+ * As an additional quirk ALPS touchpads may not only forget to ACK
+ * disable command but will stop reporting taps, so if we see that
+ * mouse at least once ACKs disable we will do full reconnect if ACK
+ * is missing.
+ */
+ psmouse->num_resyncs++;
+
+ if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) {
+ if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command)
+ failed = 1;
+ } else
+ psmouse->acks_disable_command = 1;
+
+/*
+ * Poll the mouse. If it was reset the packet will be shorter than
+ * psmouse->pktsize and ps2_command will fail. We do not expect and
+ * do not handle scenario when mouse "upgrades" its protocol while
+ * disconnected since it would require additional delay. If we ever
+ * see a mouse that does it we'll adjust the code.
+ */
+ if (!failed) {
+ if (psmouse->poll(psmouse))
+ failed = 1;
+ else {
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ for (i = 0; i < psmouse->pktsize; i++) {
+ psmouse->pktcnt++;
+ rc = psmouse->protocol_handler(psmouse, NULL);
+ if (rc != PSMOUSE_GOOD_DATA)
+ break;
+ }
+ if (rc != PSMOUSE_FULL_PACKET)
+ failed = 1;
+ psmouse_set_state(psmouse, PSMOUSE_RESYNCING);
+ }
+ }
+/*
+ * Now try to enable mouse. We try to do that even if poll failed and also
+ * repeat our attempts 5 times, otherwise we may be left out with disabled
+ * mouse.
+ */
+ for (i = 0; i < 5; i++) {
+ if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
+ enabled = 1;
+ break;
+ }
+ msleep(200);
+ }
+
+ if (!enabled) {
+ printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n",
+ psmouse->ps2dev.serio->phys);
+ failed = 1;
+ }
+
+ if (failed) {
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n");
+ serio_reconnect(serio);
+ } else
+ psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+
+ if (parent)
+ psmouse_activate(parent);
+ out:
+ up(&psmouse_sem);
+}
/*
* psmouse_cleanup() resets the mouse into power-on state.
@@ -825,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio)
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ /* make sure we don't have a resync in progress */
+ up(&psmouse_sem);
+ flush_workqueue(kpsmoused_wq);
+ down(&psmouse_sem);
+
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
parent = serio_get_drvdata(serio->parent);
psmouse_deactivate(parent);
@@ -862,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
psmouse->set_rate = psmouse_set_rate;
psmouse->set_resolution = psmouse_set_resolution;
+ psmouse->poll = psmouse_poll;
psmouse->protocol_handler = psmouse_process_byte;
psmouse->pktsize = 3;
@@ -877,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto
else
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
+ /*
+ * If mouse's packet size is 3 there is no point in polling the
+ * device in hopes to detect protocol reset - we won't get less
+ * than 3 bytes response anyhow.
+ */
+ if (psmouse->pktsize == 3)
+ psmouse->resync_time = 0;
+
+ /*
+ * Some smart KVMs fake response to POLL command returning just
+ * 3 bytes and messing up our resync logic, so if initial poll
+ * fails we won't try polling the device anymore. Hopefully
+ * such KVM will maintain initially selected protocol.
+ */
+ if (psmouse->resync_time && psmouse->poll(psmouse))
+ psmouse->resync_time = 0;
+
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
@@ -917,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto out;
ps2_init(&psmouse->ps2dev, serio);
+ INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
psmouse->dev = input_dev;
sprintf(psmouse->phys, "%s/input0", serio->phys);
@@ -937,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
psmouse->rate = psmouse_rate;
psmouse->resolution = psmouse_resolution;
psmouse->resetafter = psmouse_resetafter;
+ psmouse->resync_time = parent ? 0 : psmouse_resync_time;
psmouse->smartscroll = psmouse_smartscroll;
psmouse_switch_protocol(psmouse, NULL);
@@ -1281,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
static int __init psmouse_init(void)
{
+ kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
+ if (!kpsmoused_wq) {
+ printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
+ return -ENOMEM;
+ }
+
serio_register_driver(&psmouse_drv);
+
return 0;
}
static void __exit psmouse_exit(void)
{
serio_unregister_driver(&psmouse_drv);
+ destroy_workqueue(kpsmoused_wq);
}
module_init(psmouse_init);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 7c4192bd1279..4d9107fba6a1 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -7,7 +7,7 @@
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_SETPOLL 0x00f0
-#define PSMOUSE_CMD_POLL 0x03eb
+#define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
@@ -23,6 +23,7 @@
enum psmouse_state {
PSMOUSE_IGNORE,
PSMOUSE_INITIALIZING,
+ PSMOUSE_RESYNCING,
PSMOUSE_CMD_MODE,
PSMOUSE_ACTIVATED,
};
@@ -38,15 +39,19 @@ struct psmouse {
void *private;
struct input_dev *dev;
struct ps2dev ps2dev;
+ struct work_struct resync_work;
char *vendor;
char *name;
unsigned char packet[8];
+ unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
unsigned char type;
+ unsigned char acks_disable_command;
unsigned int model;
unsigned long last;
unsigned long out_of_sync;
+ unsigned long num_resyncs;
enum psmouse_state state;
char devname[64];
char phys[32];
@@ -54,6 +59,7 @@ struct psmouse {
unsigned int rate;
unsigned int resolution;
unsigned int resetafter;
+ unsigned int resync_time;
unsigned int smartscroll; /* Logitech only */
psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
@@ -62,6 +68,7 @@ struct psmouse {
int (*reconnect)(struct psmouse *psmouse);
void (*disconnect)(struct psmouse *psmouse);
+ int (*poll)(struct psmouse *psmouse);
void (*pt_activate)(struct psmouse *psmouse);
void (*pt_deactivate)(struct psmouse *psmouse);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 97cdfd6acaca..2051bec2c394 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse)
psmouse->disconnect = synaptics_disconnect;
psmouse->reconnect = synaptics_reconnect;
psmouse->pktsize = 6;
+ /* Synaptics can usually stay in sync without extra help */
+ psmouse->resync_time = 0;
if (SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 2d0af44ac4b9..81fd7a97a93d 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -40,15 +40,15 @@ MODULE_LICENSE("GPL");
#endif
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
-module_param(xres, uint, 0);
+module_param(xres, uint, 0644);
MODULE_PARM_DESC(xres, "Horizontal screen resolution");
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
-module_param(yres, uint, 0);
+module_param(yres, uint, 0644);
MODULE_PARM_DESC(yres, "Vertical screen resolution");
static unsigned tap_time = 200;
-module_param(tap_time, uint, 0);
+module_param(tap_time, uint, 0644);
MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
struct mousedev_hw_data {
@@ -155,7 +155,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
switch (code) {
case ABS_X:
size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
- if (size == 0) size = xres;
+ if (size == 0) size = xres ? : 1;
if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
@@ -164,7 +164,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
case ABS_Y:
size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
- if (size == 0) size = yres;
+ if (size == 0) size = yres ? : 1;
if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 9b1ab5e7a98d..3df5eedf8f31 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -19,12 +19,12 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/kmi.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_kmi.h>
-#include <asm/hardware/clock.h>
#define KMI_BASE (kmi->base)
@@ -72,13 +72,9 @@ static int amba_kmi_open(struct serio *io)
unsigned int divisor;
int ret;
- ret = clk_use(kmi->clk);
- if (ret)
- goto out;
-
ret = clk_enable(kmi->clk);
if (ret)
- goto clk_unuse;
+ goto out;
divisor = clk_get_rate(kmi->clk) / 8000000 - 1;
writeb(divisor, KMICLKDIV);
@@ -97,8 +93,6 @@ static int amba_kmi_open(struct serio *io)
clk_disable:
clk_disable(kmi->clk);
- clk_unuse:
- clk_unuse(kmi->clk);
out:
return ret;
}
@@ -111,7 +105,6 @@ static void amba_kmi_close(struct serio *io)
free_irq(kmi->irq, kmi);
clk_disable(kmi->clk);
- clk_unuse(kmi->clk);
}
static int amba_kmi_probe(struct amba_device *dev, void *id)
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 4da6c86b5d76..096b6a0b5cca 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -154,7 +154,7 @@ static int ct82c710_write(struct serio *port, unsigned char c)
* See if we can find a 82C710 device. Read mouse address.
*/
-static int __init ct82c710_probe(void)
+static int __init ct82c710_detect(void)
{
outb_p(0x55, 0x2fa); /* Any value except 9, ff or 36 */
outb_p(0xaa, 0x3fa); /* Inverse of 55 */
@@ -163,7 +163,7 @@ static int __init ct82c710_probe(void)
outb_p(0x1b, 0x2fa); /* Inverse of e4 */
outb_p(0x0f, 0x390); /* Write index */
if (inb_p(0x391) != 0xe4) /* Config address found? */
- return -1; /* No: no 82C710 here */
+ return -ENODEV; /* No: no 82C710 here */
outb_p(0x0d, 0x390); /* Write index */
ct82c710_iores.start = inb_p(0x391) << 2; /* Get mouse I/O address */
@@ -175,51 +175,88 @@ static int __init ct82c710_probe(void)
return 0;
}
-static struct serio * __init ct82c710_allocate_port(void)
+static int __devinit ct82c710_probe(struct platform_device *dev)
{
- struct serio *serio;
-
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->open = ct82c710_open;
- serio->close = ct82c710_close;
- serio->write = ct82c710_write;
- serio->dev.parent = &ct82c710_device->dev;
- strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
- snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
- }
+ ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!ct82c710_port)
+ return -ENOMEM;
+
+ ct82c710_port->id.type = SERIO_8042;
+ ct82c710_port->dev.parent = &dev->dev;
+ ct82c710_port->open = ct82c710_open;
+ ct82c710_port->close = ct82c710_close;
+ ct82c710_port->write = ct82c710_write;
+ strlcpy(ct82c710_port->name, "C&T 82c710 mouse port",
+ sizeof(ct82c710_port->name));
+ snprintf(ct82c710_port->phys, sizeof(ct82c710_port->phys),
+ "isa%04lx/serio0", CT82C710_DATA);
+
+ serio_register_port(ct82c710_port);
+
+ return 0;
+}
+
+static int __devexit ct82c710_remove(struct platform_device *dev)
+{
+ serio_unregister_port(ct82c710_port);
- return serio;
+ return 0;
}
+static struct platform_driver ct82c710_driver = {
+ .driver = {
+ .name = "ct82c710",
+ .owner = THIS_MODULE,
+ },
+ .probe = ct82c710_probe,
+ .remove = __devexit_p(ct82c710_remove),
+};
+
+
static int __init ct82c710_init(void)
{
- if (ct82c710_probe())
- return -ENODEV;
+ int error;
- ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
- if (IS_ERR(ct82c710_device))
- return PTR_ERR(ct82c710_device);
+ error = ct82c710_detect();
+ if (error)
+ return error;
- if (!(ct82c710_port = ct82c710_allocate_port())) {
- platform_device_unregister(ct82c710_device);
- return -ENOMEM;
+ error = platform_driver_register(&ct82c710_driver);
+ if (error)
+ return error;
+
+ ct82c710_device = platform_device_alloc("ct82c710", -1);
+ if (!ct82c710_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
}
+ error = platform_device_add_resources(ct82c710_device, &ct82c710_iores, 1);
+ if (error)
+ goto err_free_device;
+
+ error = platform_device_add(ct82c710_device);
+ if (error)
+ goto err_free_device;
+
serio_register_port(ct82c710_port);
printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
CT82C710_DATA, CT82C710_IRQ);
return 0;
+
+ err_free_device:
+ platform_device_put(ct82c710_device);
+ err_unregister_driver:
+ platform_driver_unregister(&ct82c710_driver);
+ return error;
}
static void __exit ct82c710_exit(void)
{
- serio_unregister_port(ct82c710_port);
platform_device_unregister(ct82c710_device);
+ platform_driver_unregister(&ct82c710_driver);
}
module_init(ct82c710_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 273bb3b08cfa..a4c6f3522723 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -84,6 +84,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
},
},
+ {
+ .ident = "OQO Model 01",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+ },
+ },
{ }
};
@@ -158,6 +166,20 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
},
},
+ {
+ .ident = "Sharp Actius MM20",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+ },
+ },
+ {
+ .ident = "Sony Vaio FS-115b",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index ac86c1d1d83e..a7d91d5356a5 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -572,7 +572,7 @@ static int i8042_enable_mux_ports(void)
* LCS/Telegraphics.
*/
-static int __init i8042_check_mux(void)
+static int __devinit i8042_check_mux(void)
{
unsigned char mux_version;
@@ -600,7 +600,7 @@ static int __init i8042_check_mux(void)
* the presence of an AUX interface.
*/
-static int __init i8042_check_aux(void)
+static int __devinit i8042_check_aux(void)
{
unsigned char param;
static int i8042_check_aux_cookie;
@@ -678,7 +678,7 @@ static int __init i8042_check_aux(void)
* registers it, and reports to the user.
*/
-static int __init i8042_port_register(struct i8042_port *port)
+static int __devinit i8042_port_register(struct i8042_port *port)
{
i8042_ctr &= ~port->disable;
@@ -956,7 +956,6 @@ static int i8042_resume(struct platform_device *dev)
panic_blink = i8042_panic_blink;
return 0;
-
}
/*
@@ -969,16 +968,7 @@ static void i8042_shutdown(struct platform_device *dev)
i8042_controller_cleanup();
}
-static struct platform_driver i8042_driver = {
- .suspend = i8042_suspend,
- .resume = i8042_resume,
- .shutdown = i8042_shutdown,
- .driver = {
- .name = "i8042",
- },
-};
-
-static int __init i8042_create_kbd_port(void)
+static int __devinit i8042_create_kbd_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
@@ -1003,7 +993,7 @@ static int __init i8042_create_kbd_port(void)
return i8042_port_register(port);
}
-static int __init i8042_create_aux_port(void)
+static int __devinit i8042_create_aux_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
@@ -1028,7 +1018,7 @@ static int __init i8042_create_aux_port(void)
return i8042_port_register(port);
}
-static int __init i8042_create_mux_port(int index)
+static int __devinit i8042_create_mux_port(int index)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
@@ -1057,37 +1047,16 @@ static int __init i8042_create_mux_port(int index)
return i8042_port_register(port);
}
-static int __init i8042_init(void)
+static int __devinit i8042_probe(struct platform_device *dev)
{
int i, have_ports = 0;
int err;
- dbg_init();
-
init_timer(&i8042_timer);
i8042_timer.function = i8042_timer_func;
- 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()) {
- err = -ENODEV;
- goto err_platform_exit;
- }
-
- err = platform_driver_register(&i8042_driver);
- if (err)
- goto err_controller_cleanup;
-
- i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
- if (IS_ERR(i8042_platform_device)) {
- err = PTR_ERR(i8042_platform_device);
- goto err_unregister_driver;
- }
+ if (i8042_controller_init())
+ return -ENODEV;
if (!i8042_noaux && !i8042_check_aux()) {
if (!i8042_nomux && !i8042_check_mux()) {
@@ -1113,30 +1082,23 @@ static int __init i8042_init(void)
if (!have_ports) {
err = -ENODEV;
- goto err_unregister_device;
+ goto err_controller_cleanup;
}
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:
- platform_driver_unregister(&i8042_driver);
err_controller_cleanup:
i8042_controller_cleanup();
- err_platform_exit:
- i8042_platform_exit();
return err;
}
-static void __exit i8042_exit(void)
+static int __devexit i8042_remove(struct platform_device *dev)
{
int i;
@@ -1148,6 +1110,62 @@ static void __exit i8042_exit(void)
del_timer_sync(&i8042_timer);
+ return 0;
+}
+
+static struct platform_driver i8042_driver = {
+ .driver = {
+ .name = "i8042",
+ .owner = THIS_MODULE,
+ },
+ .probe = i8042_probe,
+ .remove = __devexit_p(i8042_remove),
+ .suspend = i8042_suspend,
+ .resume = i8042_resume,
+ .shutdown = i8042_shutdown,
+};
+
+static int __init i8042_init(void)
+{
+ int err;
+
+ dbg_init();
+
+ 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;
+
+ err = platform_driver_register(&i8042_driver);
+ if (err)
+ goto err_platform_exit;
+
+ i8042_platform_device = platform_device_alloc("i8042", -1);
+ if (!i8042_platform_device) {
+ err = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ err = platform_device_add(i8042_platform_device);
+ if (err)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(i8042_platform_device);
+ err_unregister_driver:
+ platform_driver_unregister(&i8042_driver);
+ err_platform_exit:
+ i8042_platform_exit();
+
+ return err;
+}
+
+static void __exit i8042_exit(void)
+{
platform_device_unregister(i8042_platform_device);
platform_driver_unregister(&i8042_driver);
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index d857f7081adb..f08a5d0cd5fa 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -118,13 +118,12 @@ static void maceps2_close(struct serio *dev)
}
-static struct serio * __init maceps2_allocate_port(int idx)
+static struct serio * __devinit maceps2_allocate_port(int idx)
{
struct serio *serio;
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+ serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (serio) {
- memset(serio, 0, sizeof(struct serio));
serio->id.type = SERIO_8042;
serio->write = maceps2_write;
serio->open = maceps2_open;
@@ -138,24 +137,13 @@ static struct serio * __init maceps2_allocate_port(int idx)
return serio;
}
-
-static int __init maceps2_init(void)
+static int __devinit maceps2_probe(struct platform_device *dev)
{
- maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
- if (IS_ERR(maceps2_device))
- return PTR_ERR(maceps2_device);
-
- port_data[0].port = &mace->perif.ps2.keyb;
- port_data[0].irq = MACEISA_KEYB_IRQ;
- port_data[1].port = &mace->perif.ps2.mouse;
- port_data[1].irq = MACEISA_MOUSE_IRQ;
-
maceps2_port[0] = maceps2_allocate_port(0);
maceps2_port[1] = maceps2_allocate_port(1);
if (!maceps2_port[0] || !maceps2_port[1]) {
kfree(maceps2_port[0]);
kfree(maceps2_port[1]);
- platform_device_unregister(maceps2_device);
return -ENOMEM;
}
@@ -165,11 +153,59 @@ static int __init maceps2_init(void)
return 0;
}
-static void __exit maceps2_exit(void)
+static int __devexit maceps2_remove(struct platform_device *dev)
{
serio_unregister_port(maceps2_port[0]);
serio_unregister_port(maceps2_port[1]);
+
+ return 0;
+}
+
+static struct platform_driver maceps2_driver = {
+ .driver = {
+ .name = "maceps2",
+ .owner = THIS_MODULE,
+ },
+ .probe = maceps2_probe,
+ .remove = __devexit_p(maceps2_remove),
+};
+
+static int __init maceps2_init(void)
+{
+ int error;
+
+ error = platform_driver_register(&maceps2_driver);
+ if (error)
+ return error;
+
+ maceps2_device = platform_device_alloc("maceps2", -1);
+ if (!maceps2_device) {
+ error = -ENOMEM;
+ goto err_unregister_driver;
+ }
+
+ port_data[0].port = &mace->perif.ps2.keyb;
+ port_data[0].irq = MACEISA_KEYB_IRQ;
+ port_data[1].port = &mace->perif.ps2.mouse;
+ port_data[1].irq = MACEISA_MOUSE_IRQ;
+
+ error = platform_device_add(maceps2_device);
+ if (error)
+ goto err_free_device;
+
+ return 0;
+
+ err_free_device:
+ platform_device_put(maceps2_device);
+ err_unregister_driver:
+ platform_driver_unregister(&maceps2_driver);
+ return error;
+}
+
+static void __exit maceps2_exit(void)
+{
platform_device_unregister(maceps2_device);
+ platform_driver_unregister(&maceps2_driver);
}
module_init(maceps2_init);
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index b44d255596c2..d3827c5fe119 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -75,13 +75,13 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void q40kbd_flush(void)
{
- int maxread = 100;
+ int maxread = 100;
unsigned long flags;
spin_lock_irqsave(&q40kbd_lock, flags);
- while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
- master_inb(KEYCODE_REG);
+ while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+ master_inb(KEYCODE_REG);
spin_unlock_irqrestore(&q40kbd_lock, flags);
}
@@ -97,14 +97,14 @@ static int q40kbd_open(struct serio *port)
if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
- return -1;
+ return -EBUSY;
}
- /* off we go */
- master_outb(-1, KEYBOARD_UNLOCK_REG);
- master_outb(1, KEY_IRQ_ENABLE_REG);
+ /* off we go */
+ master_outb(-1, KEYBOARD_UNLOCK_REG);
+ master_outb(1, KEY_IRQ_ENABLE_REG);
- return 0;
+ return 0;
}
static void q40kbd_close(struct serio *port)
@@ -116,48 +116,73 @@ static void q40kbd_close(struct serio *port)
q40kbd_flush();
}
-static struct serio * __init q40kbd_allocate_port(void)
+static int __devinit q40kbd_probe(struct platform_device *dev)
{
- struct serio *serio;
-
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (serio) {
- memset(serio, 0, sizeof(struct serio));
- serio->id.type = SERIO_8042;
- serio->open = q40kbd_open;
- serio->close = q40kbd_close;
- serio->dev.parent = &q40kbd_device->dev;
- strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
- strlcpy(serio->phys, "Q40", sizeof(serio->phys));
- }
+ q40kbd_port = kzalloc(sizeof(struct serio), GFP_KERNEL);
+ if (!q40kbd_port)
+ return -ENOMEM;
+
+ q40kbd_port->id.type = SERIO_8042;
+ q40kbd_port->open = q40kbd_open;
+ q40kbd_port->close = q40kbd_close;
+ q40kbd_port->dev.parent = &dev->dev;
+ strlcpy(q40kbd_port->name, "Q40 Kbd Port", sizeof(q40kbd_port->name));
+ strlcpy(q40kbd_port->phys, "Q40", sizeof(q40kbd_port->phys));
+
+ serio_register_port(q40kbd_port);
+ printk(KERN_INFO "serio: Q40 kbd registered\n");
- return serio;
+ return 0;
}
+static int __devexit q40kbd_remove(struct platform_device *dev)
+{
+ serio_unregister_port(q40kbd_port);
+
+ return 0;
+}
+
+static struct platform_driver q40kbd_driver = {
+ .driver = {
+ .name = "q40kbd",
+ .owner = THIS_MODULE,
+ },
+ .probe = q40kbd_probe,
+ .remove = __devexit_p(q40kbd_remove),
+};
+
static int __init q40kbd_init(void)
{
+ int error;
+
if (!MACH_IS_Q40)
return -EIO;
- q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
- if (IS_ERR(q40kbd_device))
- return PTR_ERR(q40kbd_device);
+ error = platform_driver_register(&q40kbd_driver);
+ if (error)
+ return error;
- if (!(q40kbd_port = q40kbd_allocate_port())) {
- platform_device_unregister(q40kbd_device);
- return -ENOMEM;
- }
+ q40kbd_device = platform_device_alloc("q40kbd", -1);
+ if (!q40kbd_device)
+ goto err_unregister_driver;
- serio_register_port(q40kbd_port);
- printk(KERN_INFO "serio: Q40 kbd registered\n");
+ error = platform_device_add(q40kbd_device);
+ if (error)
+ goto err_free_device;
return 0;
+
+ err_free_device:
+ platform_device_put(q40kbd_device);
+ err_unregister_driver:
+ platform_driver_unregister(&q40kbd_driver);
+ return error;
}
static void __exit q40kbd_exit(void)
{
- serio_unregister_port(q40kbd_port);
platform_device_unregister(q40kbd_device);
+ platform_driver_unregister(&q40kbd_driver);
}
module_init(q40kbd_init);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 3f0df3330fb2..ebd9976fc811 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -20,7 +20,6 @@
#include <linux/spinlock.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/system.h>
#include <asm/hardware/sa1111.h>
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index fbb69ef6a77b..2f76813c3a64 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem);
static LIST_HEAD(serio_list);
-static struct bus_type serio_bus = {
- .name = "serio",
-};
+static struct bus_type serio_bus;
static void serio_add_port(struct serio *serio);
static void serio_destroy_port(struct serio *serio);
@@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev)
return 0;
}
+static struct bus_type serio_bus = {
+ .name = "serio",
+ .probe = serio_driver_probe,
+ .remove = serio_driver_remove,
+};
+
void __serio_register_driver(struct serio_driver *drv, struct module *owner)
{
drv->driver.bus = &serio_bus;
- drv->driver.probe = serio_driver_probe;
- drv->driver.remove = serio_driver_remove;
serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
}
@@ -800,16 +802,16 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
#ifdef CONFIG_HOTPLUG
-#define SERIO_ADD_HOTPLUG_VAR(fmt, val...) \
+#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
do { \
- int err = add_hotplug_env_var(envp, num_envp, &i, \
+ int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
struct serio *serio;
int i = 0;
@@ -820,21 +822,21 @@ static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *bu
serio = to_serio_port(dev);
- SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type);
- SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto);
- SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id);
- SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra);
- SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
+ SERIO_ADD_UEVENT_VAR("SERIO_TYPE=%02x", serio->id.type);
+ SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
+ SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
+ SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
+ SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
envp[i] = NULL;
return 0;
}
-#undef SERIO_ADD_HOTPLUG_VAR
+#undef SERIO_ADD_UEVENT_VAR
#else
-static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -908,7 +910,7 @@ static int __init serio_init(void)
serio_bus.dev_attrs = serio_device_attrs;
serio_bus.drv_attrs = serio_driver_attrs;
serio_bus.match = serio_bus_match;
- serio_bus.hotplug = serio_hotplug;
+ serio_bus.uevent = serio_uevent;
serio_bus.resume = serio_resume;
bus_register(&serio_bus);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 1bd88fca0542..54a680cc704d 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -96,6 +96,7 @@ static int serport_ldisc_open(struct tty_struct *tty)
init_waitqueue_head(&serport->wait);
tty->disc_data = serport;
+ tty->receive_room = 256;
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
return 0;
@@ -140,17 +141,6 @@ out:
}
/*
- * serport_ldisc_room() reports how much room we do have for receiving data.
- * Although we in fact have infinite room, we need to specify some value
- * here, and 256 seems to be reasonable.
- */
-
-static int serport_ldisc_room(struct tty_struct *tty)
-{
- return 256;
-}
-
-/*
* serport_ldisc_read() just waits indefinitely if everything goes well.
* However, when the serio driver closes the serio port, it finishes,
* returning 0 characters.
@@ -237,7 +227,6 @@ static struct tty_ldisc serport_ldisc = {
.read = serport_ldisc_read,
.ioctl = serport_ldisc_ioctl,
.receive_buf = serport_ldisc_receive,
- .receive_room = serport_ldisc_room,
.write_wakeup = serport_ldisc_write_wakeup
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 21d55ed4b88a..b1b14f8d4dd6 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN
if INPUT_TOUCHSCREEN
+config TOUCHSCREEN_ADS7846
+ tristate "ADS 7846 based touchscreens"
+ depends on SPI_MASTER
+ help
+ Say Y here if you have a touchscreen interface using the
+ ADS7846 controller, and your board-specific initialization
+ code includes that in its table of SPI devices.
+
+ If unsure, say N (but it's safe to say "Y").
+
+ To compile this driver as a module, choose M here: the
+ module will be called ads7846.
+
config TOUCHSCREEN_BITSY
tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
depends on SA1100_BITSY
@@ -85,7 +98,7 @@ config TOUCHSCREEN_MK712
config TOUCHSCREEN_HP600
tristate "HP Jornada 680/690 touchscreen"
- depends on SH_HP600 && SH_ADC
+ depends on SH_HP6XX && SH_ADC
help
Say Y here if you have a HP Jornada 680 or 690 and want to
support the built-in touchscreen.
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 6842869c9a26..5e5557c43121 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -4,6 +4,7 @@
# Each configuration option enables a list of files.
+obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
new file mode 100644
index 000000000000..dd8c6a9ffc76
--- /dev/null
+++ b/drivers/input/touchscreen/ads7846.c
@@ -0,0 +1,625 @@
+/*
+ * ADS7846 based touchscreen and sensor driver
+ *
+ * Copyright (c) 2005 David Brownell
+ *
+ * Using code from:
+ * - corgi_ts.c
+ * Copyright (C) 2004-2005 Richard Purdie
+ * - omap_ts.[hc], ads7846.h, ts_osk.c
+ * Copyright (C) 2002 MontaVista Software
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2005 Dirk Behme
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#ifdef CONFIG_ARM
+#include <asm/mach-types.h>
+#ifdef CONFIG_ARCH_OMAP
+#include <asm/arch/gpio.h>
+#endif
+
+#else
+#define set_irq_type(irq,type) do{}while(0)
+#endif
+
+
+/*
+ * This code has been lightly tested on an ads7846.
+ * Support for ads7843 and ads7845 has only been stubbed in.
+ *
+ * Not yet done: investigate the values reported. Are x/y/pressure
+ * event values sane enough for X11? How accurate are the temperature
+ * and voltage readings? (System-specific calibration should support
+ * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
+ *
+ * app note sbaa036 talks in more detail about accurate sampling...
+ * that ought to help in situations like LCDs inducing noise (which
+ * can also be helped by using synch signals) and more generally.
+ */
+
+#define TS_POLL_PERIOD msecs_to_jiffies(10)
+
+struct ts_event {
+ /* For portability, we can't read 12 bit values using SPI (which
+ * would make the controller deliver them as native byteorder u16
+ * with msbs zeroed). Instead, we read them as two 8-byte values,
+ * which need byteswapping then range adjustment.
+ */
+ __be16 x;
+ __be16 y;
+ __be16 z1, z2;
+};
+
+struct ads7846 {
+ struct input_dev input;
+ char phys[32];
+
+ struct spi_device *spi;
+ u16 model;
+ u16 vref_delay_usecs;
+ u16 x_plate_ohms;
+
+ struct ts_event tc;
+
+ struct spi_transfer xfer[8];
+ struct spi_message msg;
+
+ spinlock_t lock;
+ struct timer_list timer; /* P: lock */
+ unsigned pendown:1; /* P: lock */
+ unsigned pending:1; /* P: lock */
+// FIXME remove "irq_disabled"
+ unsigned irq_disabled:1; /* P: lock */
+};
+
+/* leave chip selected when we're done, for quicker re-select? */
+#if 0
+#define CS_CHANGE(xfer) ((xfer).cs_change = 1)
+#else
+#define CS_CHANGE(xfer) ((xfer).cs_change = 0)
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+/* The ADS7846 has touchscreen and other sensors.
+ * Earlier ads784x chips are somewhat compatible.
+ */
+#define ADS_START (1 << 7)
+#define ADS_A2A1A0_d_y (1 << 4) /* differential */
+#define ADS_A2A1A0_d_z1 (3 << 4) /* differential */
+#define ADS_A2A1A0_d_z2 (4 << 4) /* differential */
+#define ADS_A2A1A0_d_x (5 << 4) /* differential */
+#define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */
+#define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */
+#define ADS_A2A1A0_vaux (6 << 4) /* non-differential */
+#define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */
+#define ADS_8_BIT (1 << 3)
+#define ADS_12_BIT (0 << 3)
+#define ADS_SER (1 << 2) /* non-differential */
+#define ADS_DFR (0 << 2) /* differential */
+#define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */
+#define ADS_PD10_ADC_ON (1 << 0) /* ADC on */
+#define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */
+#define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */
+
+#define MAX_12BIT ((1<<12)-1)
+
+/* leave ADC powered up (disables penirq) between differential samples */
+#define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
+ | ADS_12_BIT | ADS_DFR)
+
+static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON;
+static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON;
+static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON;
+static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */
+
+/* single-ended samples need to first power up reference voltage;
+ * we leave both ADC and VREF powered
+ */
+#define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
+ | ADS_12_BIT | ADS_SER)
+
+static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON;
+static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN;
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Non-touchscreen sensors only use single-ended conversions.
+ */
+
+struct ser_req {
+ u8 command;
+ u16 scratch;
+ __be16 sample;
+ struct spi_message msg;
+ struct spi_transfer xfer[6];
+};
+
+static int ads7846_read12_ser(struct device *dev, unsigned command)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL);
+ int status;
+ int sample;
+ int i;
+
+ if (!req)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&req->msg.transfers);
+
+ /* activate reference, so it has time to settle; */
+ req->xfer[0].tx_buf = &ref_on;
+ req->xfer[0].len = 1;
+ req->xfer[1].rx_buf = &req->scratch;
+ req->xfer[1].len = 2;
+
+ /*
+ * for external VREF, 0 usec (and assume it's always on);
+ * for 1uF, use 800 usec;
+ * no cap, 100 usec.
+ */
+ req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+
+ /* take sample */
+ req->command = (u8) command;
+ req->xfer[2].tx_buf = &req->command;
+ req->xfer[2].len = 1;
+ req->xfer[3].rx_buf = &req->sample;
+ req->xfer[3].len = 2;
+
+ /* REVISIT: take a few more samples, and compare ... */
+
+ /* turn off reference */
+ req->xfer[4].tx_buf = &ref_off;
+ req->xfer[4].len = 1;
+ req->xfer[5].rx_buf = &req->scratch;
+ req->xfer[5].len = 2;
+
+ CS_CHANGE(req->xfer[5]);
+
+ /* group all the transfers together, so we can't interfere with
+ * reading touchscreen state; disable penirq while sampling
+ */
+ for (i = 0; i < 6; i++)
+ spi_message_add_tail(&req->xfer[i], &req->msg);
+
+ disable_irq(spi->irq);
+ status = spi_sync(spi, &req->msg);
+ enable_irq(spi->irq);
+
+ if (req->msg.status)
+ status = req->msg.status;
+ sample = be16_to_cpu(req->sample);
+ sample = sample >> 4;
+ kfree(req);
+
+ return status ? status : sample;
+}
+
+#define SHOW(name) static ssize_t \
+name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ ssize_t v = ads7846_read12_ser(dev, \
+ READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
+ if (v < 0) \
+ return v; \
+ return sprintf(buf, "%u\n", (unsigned) v); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
+
+SHOW(temp0)
+SHOW(temp1)
+SHOW(vaux)
+SHOW(vbatt)
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
+ * to retrieve touchscreen status.
+ *
+ * The SPI transfer completion callback does the real work. It reports
+ * touchscreen events and reactivates the timer (or IRQ) as appropriate.
+ */
+
+static void ads7846_rx(void *ads)
+{
+ struct ads7846 *ts = ads;
+ unsigned Rt;
+ unsigned sync = 0;
+ u16 x, y, z1, z2;
+ unsigned long flags;
+
+ /* adjust: 12 bit samples (left aligned), built from
+ * two 8 bit values writen msb-first.
+ */
+ x = be16_to_cpu(ts->tc.x) >> 4;
+ y = be16_to_cpu(ts->tc.y) >> 4;
+ z1 = be16_to_cpu(ts->tc.z1) >> 4;
+ z2 = be16_to_cpu(ts->tc.z2) >> 4;
+
+ /* range filtering */
+ if (x == MAX_12BIT)
+ x = 0;
+
+ if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ /* compute touch pressure resistance using equation #2 */
+ Rt = z2;
+ Rt -= z1;
+ Rt *= x;
+ Rt *= ts->x_plate_ohms;
+ Rt /= z1;
+ Rt = (Rt + 2047) >> 12;
+ } else
+ Rt = 0;
+
+ /* NOTE: "pendown" is inferred from pressure; we don't rely on
+ * being able to check nPENIRQ status, or "friendly" trigger modes
+ * (both-edges is much better than just-falling or low-level).
+ *
+ * REVISIT: some boards may require reading nPENIRQ; it's
+ * needed on 7843. and 7845 reads pressure differently...
+ *
+ * REVISIT: the touchscreen might not be connected; this code
+ * won't notice that, even if nPENIRQ never fires ...
+ */
+ if (!ts->pendown && Rt != 0) {
+ input_report_key(&ts->input, BTN_TOUCH, 1);
+ sync = 1;
+ } else if (ts->pendown && Rt == 0) {
+ input_report_key(&ts->input, BTN_TOUCH, 0);
+ sync = 1;
+ }
+
+ if (Rt) {
+ input_report_abs(&ts->input, ABS_X, x);
+ input_report_abs(&ts->input, ABS_Y, y);
+ input_report_abs(&ts->input, ABS_PRESSURE, Rt);
+ sync = 1;
+ }
+ if (sync)
+ input_sync(&ts->input);
+
+#ifdef VERBOSE
+ if (Rt || ts->pendown)
+ pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
+ x, y, Rt, Rt ? "" : " UP");
+#endif
+
+ /* don't retrigger while we're suspended */
+ spin_lock_irqsave(&ts->lock, flags);
+
+ ts->pendown = (Rt != 0);
+ ts->pending = 0;
+
+ if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ if (ts->pendown)
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+ else if (ts->irq_disabled) {
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ }
+ }
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void ads7846_timer(unsigned long handle)
+{
+ struct ads7846 *ts = (void *)handle;
+ int status = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+ if (!ts->pending) {
+ ts->pending = 1;
+ if (!ts->irq_disabled) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
+ }
+ status = spi_async(ts->spi, &ts->msg);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n",
+ status);
+ }
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
+{
+ ads7846_timer((unsigned long) handle);
+ return IRQ_HANDLED;
+}
+
+/*--------------------------------------------------------------------------*/
+
+static int
+ads7846_suspend(struct spi_device *spi, pm_message_t message)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+
+ spi->dev.power.power_state = message;
+
+ /* are we waiting for IRQ, or polling? */
+ if (!ts->pendown) {
+ if (!ts->irq_disabled) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
+ }
+ } else {
+ /* polling; force a final SPI completion;
+ * that will clean things up neatly
+ */
+ if (!ts->pending)
+ mod_timer(&ts->timer, jiffies);
+
+ while (ts->pendown || ts->pending) {
+ spin_unlock_irqrestore(&ts->lock, flags);
+ udelay(10);
+ spin_lock_irqsave(&ts->lock, flags);
+ }
+ }
+
+ /* we know the chip's in lowpower mode since we always
+ * leave it that way after every request
+ */
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+ return 0;
+}
+
+static int ads7846_resume(struct spi_device *spi)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ spi->dev.power.power_state = PMSG_ON;
+ return 0;
+}
+
+static int __devinit ads7846_probe(struct spi_device *spi)
+{
+ struct ads7846 *ts;
+ struct ads7846_platform_data *pdata = spi->dev.platform_data;
+ struct spi_transfer *x;
+ int i;
+
+ if (!spi->irq) {
+ dev_dbg(&spi->dev, "no IRQ?\n");
+ return -ENODEV;
+ }
+
+ if (!pdata) {
+ dev_dbg(&spi->dev, "no platform data?\n");
+ return -ENODEV;
+ }
+
+ /* don't exceed max specified sample rate */
+ if (spi->max_speed_hz > (125000 * 16)) {
+ dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+ (spi->max_speed_hz/16)/1000);
+ return -EINVAL;
+ }
+
+ /* We'd set the wordsize to 12 bits ... except that some controllers
+ * will then treat the 8 bit command words as 12 bits (and drop the
+ * four MSBs of the 12 bit result). Result: inputs must be shifted
+ * to discard the four garbage LSBs.
+ */
+
+ if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL)))
+ return -ENOMEM;
+
+ dev_set_drvdata(&spi->dev, ts);
+
+ ts->spi = spi;
+ spi->dev.power.power_state = PMSG_ON;
+
+ init_timer(&ts->timer);
+ ts->timer.data = (unsigned long) ts;
+ ts->timer.function = ads7846_timer;
+
+ ts->model = pdata->model ? : 7846;
+ ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
+ ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+
+ init_input_dev(&ts->input);
+
+ ts->input.dev = &spi->dev;
+ ts->input.name = "ADS784x Touchscreen";
+ snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id);
+ ts->input.phys = ts->phys;
+
+ ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+ input_set_abs_params(&ts->input, ABS_X,
+ pdata->x_min ? : 0,
+ pdata->x_max ? : MAX_12BIT,
+ 0, 0);
+ input_set_abs_params(&ts->input, ABS_Y,
+ pdata->y_min ? : 0,
+ pdata->y_max ? : MAX_12BIT,
+ 0, 0);
+ input_set_abs_params(&ts->input, ABS_PRESSURE,
+ pdata->pressure_min, pdata->pressure_max, 0, 0);
+
+ input_register_device(&ts->input);
+
+ /* set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
+ x = ts->xfer;
+
+ /* y- still on; turn on only y+ (and ADC) */
+ x->tx_buf = &read_y;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.y;
+ x->len = 2;
+ x++;
+
+ /* turn y+ off, x- on; we'll use formula #2 */
+ if (ts->model == 7846) {
+ x->tx_buf = &read_z1;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.z1;
+ x->len = 2;
+ x++;
+
+ x->tx_buf = &read_z2;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.z2;
+ x->len = 2;
+ x++;
+ }
+
+ /* turn y- off, x+ on, then leave in lowpower */
+ x->tx_buf = &read_x;
+ x->len = 1;
+ x++;
+ x->rx_buf = &ts->tc.x;
+ x->len = 2;
+ x++;
+
+ CS_CHANGE(x[-1]);
+
+ for (i = 0; i < x - ts->xfer; i++)
+ spi_message_add_tail(&ts->xfer[i], &ts->msg);
+ ts->msg.complete = ads7846_rx;
+ ts->msg.context = ts;
+
+ if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM,
+ spi->dev.bus_id, ts)) {
+ dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
+ input_unregister_device(&ts->input);
+ kfree(ts);
+ return -EBUSY;
+ }
+ set_irq_type(spi->irq, IRQT_FALLING);
+
+ dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
+
+ /* take a first sample, leaving nPENIRQ active; avoid
+ * the touchscreen, in case it's not connected.
+ */
+ (void) ads7846_read12_ser(&spi->dev,
+ READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+
+ /* ads7843/7845 don't have temperature sensors, and
+ * use the other sensors a bit differently too
+ */
+ if (ts->model == 7846) {
+ device_create_file(&spi->dev, &dev_attr_temp0);
+ device_create_file(&spi->dev, &dev_attr_temp1);
+ }
+ if (ts->model != 7845)
+ device_create_file(&spi->dev, &dev_attr_vbatt);
+ device_create_file(&spi->dev, &dev_attr_vaux);
+
+ return 0;
+}
+
+static int __devexit ads7846_remove(struct spi_device *spi)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ ads7846_suspend(spi, PMSG_SUSPEND);
+ free_irq(ts->spi->irq, ts);
+ if (ts->irq_disabled)
+ enable_irq(ts->spi->irq);
+
+ if (ts->model == 7846) {
+ device_remove_file(&spi->dev, &dev_attr_temp0);
+ device_remove_file(&spi->dev, &dev_attr_temp1);
+ }
+ if (ts->model != 7845)
+ device_remove_file(&spi->dev, &dev_attr_vbatt);
+ device_remove_file(&spi->dev, &dev_attr_vaux);
+
+ input_unregister_device(&ts->input);
+ kfree(ts);
+
+ dev_dbg(&spi->dev, "unregistered touchscreen\n");
+ return 0;
+}
+
+static struct spi_driver ads7846_driver = {
+ .driver = {
+ .name = "ads7846",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = ads7846_probe,
+ .remove = __devexit_p(ads7846_remove),
+ .suspend = ads7846_suspend,
+ .resume = ads7846_resume,
+};
+
+static int __init ads7846_init(void)
+{
+ /* grr, board-specific init should stay out of drivers!! */
+
+#ifdef CONFIG_ARCH_OMAP
+ if (machine_is_omap_osk()) {
+ /* GPIO4 = PENIRQ; GPIO6 = BUSY */
+ omap_request_gpio(4);
+ omap_set_gpio_direction(4, 1);
+ omap_request_gpio(6);
+ omap_set_gpio_direction(6, 1);
+ }
+ // also TI 1510 Innovator, bitbanging through FPGA
+ // also Nokia 770
+ // also Palm Tungsten T2
+#endif
+
+ // PXA:
+ // also Dell Axim X50
+ // also HP iPaq H191x/H192x/H415x/H435x
+ // also Intel Lubbock (additional to UCB1400; as temperature sensor)
+ // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
+
+ // Atmel at91sam9261-EK uses ads7843
+
+ // also various AMD Au1x00 devel boards
+
+ return spi_register_driver(&ads7846_driver);
+}
+module_init(ads7846_init);
+
+static void __exit ads7846_exit(void)
+{
+ spi_unregister_driver(&ads7846_driver);
+
+#ifdef CONFIG_ARCH_OMAP
+ if (machine_is_omap_osk()) {
+ omap_free_gpio(4);
+ omap_free_gpio(6);
+ }
+#endif
+
+}
+module_exit(ads7846_exit);
+
+MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h
index b091d1a54125..d4c50512a1ff 100644
--- a/drivers/isdn/act2000/act2000.h
+++ b/drivers/isdn/act2000/act2000.h
@@ -181,17 +181,17 @@ typedef struct act2000_card {
char regname[35]; /* Name used for request_region */
} act2000_card;
-extern __inline__ void act2000_schedule_tx(act2000_card *card)
+static inline void act2000_schedule_tx(act2000_card *card)
{
schedule_work(&card->snd_tq);
}
-extern __inline__ void act2000_schedule_rx(act2000_card *card)
+static inline void act2000_schedule_rx(act2000_card *card)
{
schedule_work(&card->rcv_tq);
}
-extern __inline__ void act2000_schedule_poll(act2000_card *card)
+static inline void act2000_schedule_poll(act2000_card *card)
{
schedule_work(&card->poll_tq);
}
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index f6d5f530b86b..49f453c53c64 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -78,29 +78,29 @@ typedef union actcapi_infoel { /* info element */
typedef struct actcapi_msn {
__u8 eaz;
__u8 len; /* Length of MSN */
- __u8 msn[15] __attribute__ ((packed));
-} actcapi_msn;
+ __u8 msn[15];
+} __attribute__((packed)) actcapi_msn;
typedef struct actcapi_dlpd {
__u8 len; /* Length of structure */
- __u16 dlen __attribute__ ((packed)); /* Data Length */
- __u8 laa __attribute__ ((packed)); /* Link Address A */
+ __u16 dlen; /* Data Length */
+ __u8 laa; /* Link Address A */
__u8 lab; /* Link Address B */
__u8 modulo; /* Modulo Mode */
__u8 win; /* Window size */
__u8 xid[100]; /* XID Information */
-} actcapi_dlpd;
+} __attribute__((packed)) actcapi_dlpd;
typedef struct actcapi_ncpd {
__u8 len; /* Length of structure */
- __u16 lic __attribute__ ((packed));
- __u16 hic __attribute__ ((packed));
- __u16 ltc __attribute__ ((packed));
- __u16 htc __attribute__ ((packed));
- __u16 loc __attribute__ ((packed));
- __u16 hoc __attribute__ ((packed));
- __u8 modulo __attribute__ ((packed));
-} actcapi_ncpd;
+ __u16 lic;
+ __u16 hic;
+ __u16 ltc;
+ __u16 htc;
+ __u16 loc;
+ __u16 hoc;
+ __u8 modulo;
+} __attribute__((packed)) actcapi_ncpd;
#define actcapi_ncpi actcapi_ncpd
/*
@@ -168,19 +168,19 @@ typedef struct actcapi_msg {
__u16 manuf_msg;
__u16 controller;
actcapi_msn msnmap;
- } manufacturer_req_msn;
+ } __attribute ((packed)) manufacturer_req_msn;
/* TODO: TraceInit-req/conf/ind/resp and
* TraceDump-req/conf/ind/resp
*/
struct connect_req {
__u8 controller;
__u8 bchan;
- __u32 infomask __attribute__ ((packed));
+ __u32 infomask;
__u8 si1;
__u8 si2;
__u8 eaz;
actcapi_addr addr;
- } connect_req;
+ } __attribute__ ((packed)) connect_req;
struct connect_conf {
__u16 plci;
__u16 info;
@@ -192,7 +192,7 @@ typedef struct actcapi_msg {
__u8 si2;
__u8 eaz;
actcapi_addr addr;
- } connect_ind;
+ } __attribute__ ((packed)) connect_ind;
struct connect_resp {
__u16 plci;
__u8 rejectcause;
@@ -200,14 +200,14 @@ typedef struct actcapi_msg {
struct connect_active_ind {
__u16 plci;
actcapi_addr addr;
- } connect_active_ind;
+ } __attribute__ ((packed)) connect_active_ind;
struct connect_active_resp {
__u16 plci;
} connect_active_resp;
struct connect_b3_req {
__u16 plci;
actcapi_ncpi ncpi;
- } connect_b3_req;
+ } __attribute__ ((packed)) connect_b3_req;
struct connect_b3_conf {
__u16 plci;
__u16 ncci;
@@ -217,12 +217,12 @@ typedef struct actcapi_msg {
__u16 ncci;
__u16 plci;
actcapi_ncpi ncpi;
- } connect_b3_ind;
+ } __attribute__ ((packed)) connect_b3_ind;
struct connect_b3_resp {
__u16 ncci;
__u8 rejectcause;
- actcapi_ncpi ncpi __attribute__ ((packed));
- } connect_b3_resp;
+ actcapi_ncpi ncpi;
+ } __attribute__ ((packed)) connect_b3_resp;
struct disconnect_req {
__u16 plci;
__u8 cause;
@@ -241,14 +241,14 @@ typedef struct actcapi_msg {
struct connect_b3_active_ind {
__u16 ncci;
actcapi_ncpi ncpi;
- } connect_b3_active_ind;
+ } __attribute__ ((packed)) connect_b3_active_ind;
struct connect_b3_active_resp {
__u16 ncci;
} connect_b3_active_resp;
struct disconnect_b3_req {
__u16 ncci;
actcapi_ncpi ncpi;
- } disconnect_b3_req;
+ } __attribute__ ((packed)) disconnect_b3_req;
struct disconnect_b3_conf {
__u16 ncci;
__u16 info;
@@ -257,7 +257,7 @@ typedef struct actcapi_msg {
__u16 ncci;
__u16 info;
actcapi_ncpi ncpi;
- } disconnect_b3_ind;
+ } __attribute__ ((packed)) disconnect_b3_ind;
struct disconnect_b3_resp {
__u16 ncci;
} disconnect_b3_resp;
@@ -265,7 +265,7 @@ typedef struct actcapi_msg {
__u16 plci;
actcapi_infonr nr;
actcapi_infoel el;
- } info_ind;
+ } __attribute__ ((packed)) info_ind;
struct info_resp {
__u16 plci;
} info_resp;
@@ -279,8 +279,8 @@ typedef struct actcapi_msg {
struct select_b2_protocol_req {
__u16 plci;
__u8 protocol;
- actcapi_dlpd dlpd __attribute__ ((packed));
- } select_b2_protocol_req;
+ actcapi_dlpd dlpd;
+ } __attribute__ ((packed)) select_b2_protocol_req;
struct select_b2_protocol_conf {
__u16 plci;
__u16 info;
@@ -288,49 +288,49 @@ typedef struct actcapi_msg {
struct select_b3_protocol_req {
__u16 plci;
__u8 protocol;
- actcapi_ncpd ncpd __attribute__ ((packed));
- } select_b3_protocol_req;
+ actcapi_ncpd ncpd;
+ } __attribute__ ((packed)) select_b3_protocol_req;
struct select_b3_protocol_conf {
__u16 plci;
__u16 info;
} select_b3_protocol_conf;
struct listen_req {
__u8 controller;
- __u32 infomask __attribute__ ((packed));
- __u16 eazmask __attribute__ ((packed));
- __u16 simask __attribute__ ((packed));
- } listen_req;
+ __u32 infomask;
+ __u16 eazmask;
+ __u16 simask;
+ } __attribute__ ((packed)) listen_req;
struct listen_conf {
__u8 controller;
- __u16 info __attribute__ ((packed));
- } listen_conf;
+ __u16 info;
+ } __attribute__ ((packed)) listen_conf;
struct data_b3_req {
__u16 fakencci;
__u16 datalen;
__u32 unused;
__u8 blocknr;
- __u16 flags __attribute__ ((packed));
- } data_b3_req;
+ __u16 flags;
+ } __attribute ((packed)) data_b3_req;
struct data_b3_ind {
__u16 fakencci;
__u16 datalen;
__u32 unused;
__u8 blocknr;
- __u16 flags __attribute__ ((packed));
- } data_b3_ind;
+ __u16 flags;
+ } __attribute__ ((packed)) data_b3_ind;
struct data_b3_resp {
__u16 ncci;
__u8 blocknr;
- } data_b3_resp;
+ } __attribute__ ((packed)) data_b3_resp;
struct data_b3_conf {
__u16 ncci;
__u8 blocknr;
- __u16 info __attribute__ ((packed));
- } data_b3_conf;
+ __u16 info;
+ } __attribute__ ((packed)) data_b3_conf;
} msg;
-} actcapi_msg;
+} __attribute__ ((packed)) actcapi_msg;
-extern __inline__ unsigned short
+static inline unsigned short
actcapi_nextsmsg(act2000_card *card)
{
unsigned long flags;
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 11ae0fddea04..623adbb0d13a 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -463,8 +463,7 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
#endif
goto bad;
}
- if (ld->receive_room &&
- ld->receive_room(mp->tty) < datalen) {
+ if (mp->tty->receive_room < datalen) {
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
printk(KERN_DEBUG "capi: no room in tty\n");
#endif
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 7b564c0dd996..0a37aded4b54 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -17,6 +17,8 @@
#include <linux/ctype.h>
#include <linux/sched.h> /* current */
+#include "capifs.h"
+
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
@@ -136,7 +138,7 @@ static struct dentry *get_node(int num)
{
char s[10];
struct dentry *root = capifs_root;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
return lookup_one_len(s, root, sprintf(s, "%d", num));
}
@@ -157,7 +159,7 @@ void capifs_new_ncci(unsigned int number, dev_t device)
dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
- up(&capifs_root->d_inode->i_sem);
+ mutex_unlock(&capifs_root->d_inode->i_mutex);
}
void capifs_free_ncci(unsigned int number)
@@ -173,7 +175,7 @@ void capifs_free_ncci(unsigned int number)
}
dput(dentry);
}
- up(&capifs_root->d_inode->i_sem);
+ mutex_unlock(&capifs_root->d_inode->i_mutex);
}
static int __init capifs_init(void)
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 27391c32f3eb..2a2b03ff096b 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -53,8 +53,6 @@ MODULE_LICENSE("GPL");
static void avmcs_config(dev_link_t *link);
static void avmcs_release(dev_link_t *link);
-static int avmcs_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -62,16 +60,7 @@ static int avmcs_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *avmcs_attach(void);
-static void avmcs_detach(dev_link_t *);
-
-/*
- 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 = "avm_cs";
+static void avmcs_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the skeleton device. Each actual
@@ -83,15 +72,7 @@ static dev_info_t dev_info = "avm_cs";
device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list = NULL;
-
/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -118,13 +99,11 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *avmcs_attach(void)
+static int avmcs_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
-
+
/* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
@@ -155,25 +134,19 @@ static dev_link_t *avmcs_attach(void)
goto err_kfree;
memset(local, 0, sizeof(local_info_t));
link->priv = local;
-
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- avmcs_detach(link);
- goto err;
- }
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ avmcs_config(link);
+
+ return 0;
err_kfree:
kfree(link);
err:
- return NULL;
+ return -EINVAL;
} /* avmcs_attach */
/*======================================================================
@@ -185,33 +158,13 @@ static dev_link_t *avmcs_attach(void)
======================================================================*/
-static void avmcs_detach(dev_link_t *link)
+static void avmcs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
+ dev_link_t *link = dev_to_instance(p_dev);
- /*
- If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
- if (link->state & DEV_CONFIG) {
- link->state |= DEV_STALE_LINK;
- return;
- }
+ if (link->state & DEV_CONFIG)
+ avmcs_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free pieces */
- *linkp = link->next;
kfree(link->priv);
kfree(link);
} /* avmcs_detach */
@@ -424,12 +377,30 @@ static void avmcs_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
-
- if (link->state & DEV_STALE_LINK)
- avmcs_detach(link);
-
} /* avmcs_release */
+static int avmcs_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int avmcs_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ return 0;
+}
+
/*======================================================================
The card status event handler. Mostly, this schedules other
@@ -444,38 +415,6 @@ static void avmcs_release(dev_link_t *link)
======================================================================*/
-static int avmcs_event(event_t event, int priority,
- event_callback_args_t *args)
-{
- dev_link_t *link = args->client_data;
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- avmcs_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avmcs_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- 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)
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
- return 0;
-} /* avmcs_event */
static struct pcmcia_device_id avmcs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
@@ -490,10 +429,11 @@ static struct pcmcia_driver avmcs_driver = {
.drv = {
.name = "avm_cs",
},
- .attach = avmcs_attach,
- .event = avmcs_event,
- .detach = avmcs_detach,
+ .probe = avmcs_attach,
+ .remove = avmcs_detach,
.id_table = avmcs_ids,
+ .suspend= avmcs_suspend,
+ .resume = avmcs_resume,
};
static int __init avmcs_init(void)
@@ -504,7 +444,6 @@ static int __init avmcs_init(void)
static void __exit avmcs_exit(void)
{
pcmcia_unregister_driver(&avmcs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(avmcs_init);
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index cccfabc1117d..11e6f937c1e4 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -16,6 +16,7 @@
#include "diva_pci.h"
#include "mi_pc.h"
#include "dsrv4bri.h"
+#include "helpers.h"
static void *diva_xdiLoadFileFile = NULL;
static dword diva_xdiLoadFileLength = 0;
@@ -815,7 +816,7 @@ diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
return (ret);
}
-void *xdiLoadFile(char *FileName, unsigned long *FileLength,
+void *xdiLoadFile(char *FileName, dword *FileLength,
unsigned long lim)
{
void *ret = diva_xdiLoadFileFile;
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c
index 4cc44a5dd1db..f31bba5b16ff 100644
--- a/drivers/isdn/hardware/eicon/os_bri.c
+++ b/drivers/isdn/hardware/eicon/os_bri.c
@@ -16,6 +16,7 @@
#include "diva_pci.h"
#include "mi_pc.h"
#include "pc_maint.h"
+#include "dsrv_bri.h"
/*
** IMPORTS
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
index 8ac207f75e54..a296a846f296 100644
--- a/drivers/isdn/hardware/eicon/os_pri.c
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -18,6 +18,7 @@
#include "pc_maint.h"
#include "dsp_tst.h"
#include "diva_dma.h"
+#include "dsrv_pri.h"
/* --------------------------------------------------------------------------
OS Dependent part of XDI driver for DIVA PRI Adapter
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index c82105920d71..0ef560144be3 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -110,7 +110,7 @@ config HISAX_16_3
config HISAX_TELESPCI
bool "Teles PCI"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Teles PCI.
See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -238,7 +238,7 @@ config HISAX_MIC
config HISAX_NETJET
bool "NETjet card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the NetJet from Traverse
Technologies.
@@ -249,7 +249,7 @@ config HISAX_NETJET
config HISAX_NETJET_U
bool "NETspider U card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies.
@@ -317,7 +317,7 @@ config HISAX_GAZEL
config HISAX_HFC_PCI
bool "HFC PCI-Bus cards"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
@@ -344,7 +344,7 @@ config HISAX_HFC_SX
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card"
- depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
+ depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV))
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 5d8ee7368f7b..4abe5ff10e72 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -358,7 +358,7 @@ hdlc_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
HDLC_irq(struct BCState *bcs, u_int stat) {
int len;
struct sk_buff *skb;
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 5f5a5ae740d2..969da40c4248 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -69,8 +69,6 @@ module_param(isdnprot, int, 0);
static void avma1cs_config(dev_link_t *link);
static void avma1cs_release(dev_link_t *link);
-static int avma1cs_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -78,16 +76,8 @@ static int avma1cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *avma1cs_attach(void);
-static void avma1cs_detach(dev_link_t *);
+static void avma1cs_detach(struct pcmcia_device *p_dev);
-/*
- 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 = "avma1_cs";
/*
A linked list of "instances" of the skeleton device. Each actual
@@ -99,15 +89,7 @@ static dev_info_t dev_info = "avma1_cs";
device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list = NULL;
-
/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -134,26 +116,24 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *avma1cs_attach(void)
+static int avma1cs_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
-
+
DEBUG(0, "avma1cs_attach()\n");
/* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
- return NULL;
+ return -ENOMEM;
memset(link, 0, sizeof(struct dev_link_t));
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
kfree(link);
- return NULL;
+ return -ENOMEM;
}
memset(local, 0, sizeof(local_info_t));
link->priv = local;
@@ -178,20 +158,13 @@ static dev_link_t *avma1cs_attach(void)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- avma1cs_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ avma1cs_config(link);
+
+ return 0;
} /* avma1cs_attach */
/*======================================================================
@@ -203,42 +176,17 @@ static dev_link_t *avma1cs_attach(void)
======================================================================*/
-static void avma1cs_detach(dev_link_t *link)
+static void avma1cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
- /*
- If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
- if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
- printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
- "still locked\n", link->dev->dev_name);
-#endif
- link->state |= DEV_STALE_LINK;
- return;
- }
+ if (link->state & DEV_CONFIG)
+ avma1cs_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free pieces */
- *linkp = link->next;
kfree(link->priv);
kfree(link);
-
} /* avma1cs_detach */
/*======================================================================
@@ -440,58 +388,30 @@ static void avma1cs_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
-
- if (link->state & DEV_STALE_LINK)
- avma1cs_detach(link);
} /* avma1cs_release */
-/*======================================================================
+static int avma1cs_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
-
-======================================================================*/
+ return 0;
+}
-static int avma1cs_event(event_t event, int priority,
- event_callback_args_t *args)
+static int avma1cs_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
- DEBUG(1, "avma1cs_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- if (link->state & DEV_CONFIG)
- avma1cs_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- avma1cs_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- 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)
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
- return 0;
-} /* avma1cs_event */
+
+ return 0;
+}
+
static struct pcmcia_device_id avma1cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
@@ -505,10 +425,11 @@ static struct pcmcia_driver avma1cs_driver = {
.drv = {
.name = "avma1_cs",
},
- .attach = avma1cs_attach,
- .event = avma1cs_event,
- .detach = avma1cs_detach,
+ .probe = avma1cs_attach,
+ .remove = avma1cs_detach,
.id_table = avma1cs_ids,
+ .suspend = avma1cs_suspend,
+ .resume = avma1cs_resume,
};
/*====================================================================*/
@@ -521,7 +442,6 @@ static int __init init_avma1_cs(void)
static void __exit exit_avma1_cs(void)
{
pcmcia_unregister_driver(&avma1cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_avma1_cs);
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index b62d6b30b72b..b0ff1cc97d7c 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -476,7 +476,7 @@ Memhscx_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
u_char r;
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 6fc6868de0b0..062fb8f0739f 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -96,8 +96,6 @@ module_param(protocol, int, 0);
static void elsa_cs_config(dev_link_t *link);
static void elsa_cs_release(dev_link_t *link);
-static int elsa_cs_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -105,39 +103,9 @@ static int elsa_cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *elsa_cs_attach(void);
-static void elsa_cs_detach(dev_link_t *);
+static void elsa_cs_detach(struct pcmcia_device *p_dev);
/*
- 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 = "elsa_cs";
-
-/*
- A linked list of "instances" of the elsa_cs device. Each actual
- PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
-
- You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
- device numbers are used to derive the corresponding array index.
-*/
-
-static dev_link_t *dev_list = NULL;
-
-/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
- To simplify the data structure handling, we actually include the
- dev_link_t structure in the device's private data structure.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -171,18 +139,16 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *elsa_cs_attach(void)
+static int elsa_cs_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
DEBUG(0, "elsa_cs_attach()\n");
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) return NULL;
+ if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
link = &local->link; link->priv = local;
@@ -207,20 +173,13 @@ static dev_link_t *elsa_cs_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- elsa_cs_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ elsa_cs_config(link);
+
+ return 0;
} /* elsa_cs_attach */
/*======================================================================
@@ -232,32 +191,18 @@ static dev_link_t *elsa_cs_attach(void)
======================================================================*/
-static void elsa_cs_detach(dev_link_t *link)
+static void elsa_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
local_info_t *info = link->priv;
- int ret;
DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
- if (link->state & DEV_CONFIG)
- elsa_cs_release(link);
-
- /* Break the link with Card Services */
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
+ if (link->state & DEV_CONFIG) {
+ info->busy = 1;
+ elsa_cs_release(link);
}
- /* Unlink device structure and free it */
- *linkp = link->next;
kfree(info);
} /* elsa_cs_detach */
@@ -447,60 +392,31 @@ static void elsa_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
} /* elsa_cs_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
+static int elsa_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
+ link->state |= DEV_SUSPEND;
+ dev->busy = 1;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
-======================================================================*/
+ return 0;
+}
-static int elsa_cs_event(event_t event, int priority,
- event_callback_args_t *args)
+static int elsa_resume(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- local_info_t *dev = link->priv;
-
- DEBUG(1, "elsa_cs_event(%d)\n", event);
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- ((local_info_t*)link->priv)->busy = 1;
- elsa_cs_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- elsa_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 */
- dev->busy = 1;
- if (link->state & DEV_CONFIG)
- 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)
- pcmcia_request_configuration(link->handle, &link->conf);
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
- break;
- }
- return 0;
-} /* elsa_cs_event */
+
+ return 0;
+}
static struct pcmcia_device_id elsa_ids[] = {
PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257),
@@ -514,10 +430,11 @@ static struct pcmcia_driver elsa_cs_driver = {
.drv = {
.name = "elsa_cs",
},
- .attach = elsa_cs_attach,
- .event = elsa_cs_event,
- .detach = elsa_cs_detach,
+ .probe = elsa_cs_attach,
+ .remove = elsa_cs_detach,
.id_table = elsa_ids,
+ .suspend = elsa_suspend,
+ .resume = elsa_resume,
};
static int __init init_elsa_cs(void)
@@ -528,7 +445,6 @@ static int __init init_elsa_cs(void)
static void __exit exit_elsa_cs(void)
{
pcmcia_unregister_driver(&elsa_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_elsa_cs);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index f8457ef48826..ca5b4a3b683e 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1715,7 +1715,6 @@ hfc_usb_disconnect(struct usb_interface
/* our driver information structure */
/************************************/
static struct usb_driver hfc_drv = {
- .owner = THIS_MODULE,
.name = "hfc_usb",
.id_table = hfcusb_idtab,
.probe = hfc_usb_probe,
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index 26c545fa223b..1b85ce166af8 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -396,17 +396,17 @@ struct isar_hw {
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
- u_char fill __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char cmd __attribute__((packed));
+ u_char fill;
+ u_char mode;
+ u_char xml;
+ u_char cmd;
#else
- u_char cmd __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char fill __attribute__((packed));
+ u_char cmd;
+ u_char xml;
+ u_char mode;
+ u_char fill;
#endif
-};
+} __attribute__((packed));
struct hdlc_hw {
union {
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h
index bd8a22e4d6a2..21fbcedf3a94 100644
--- a/drivers/isdn/hisax/hisax_fcpcipnp.h
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.h
@@ -12,17 +12,17 @@ enum {
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
- u_char fill __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char cmd __attribute__((packed));
+ u_char fill;
+ u_char mode;
+ u_char xml;
+ u_char cmd;
#else
- u_char cmd __attribute__((packed));
- u_char xml __attribute__((packed));
- u_char mode __attribute__((packed));
- u_char fill __attribute__((packed));
+ u_char cmd;
+ u_char xml;
+ u_char mode;
+ u_char fill;
#endif
-};
+} __attribute__((packed));
struct fritz_bcs {
struct hisax_b_if b_if;
diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c
index 5fe9d42d03a3..7b1ad5e4ecda 100644
--- a/drivers/isdn/hisax/hscx_irq.c
+++ b/drivers/isdn/hisax/hscx_irq.c
@@ -119,7 +119,7 @@ hscx_fill_fifo(struct BCState *bcs)
}
}
-static inline void
+static void
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
{
u_char r;
@@ -221,7 +221,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
}
}
-static inline void
+static void
hscx_int_main(struct IsdnCardState *cs, u_char val)
{
diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c
index 08563400e4fd..1f201af15a0f 100644
--- a/drivers/isdn/hisax/jade_irq.c
+++ b/drivers/isdn/hisax/jade_irq.c
@@ -110,7 +110,7 @@ jade_fill_fifo(struct BCState *bcs)
}
-static inline void
+static void
jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
{
u_char r;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index dc334aab433e..6f5213a18a8d 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -97,8 +97,6 @@ module_param(protocol, int, 0);
static void sedlbauer_config(dev_link_t *link);
static void sedlbauer_release(dev_link_t *link);
-static int sedlbauer_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -106,8 +104,7 @@ static int sedlbauer_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *sedlbauer_attach(void);
-static void sedlbauer_detach(dev_link_t *);
+static void sedlbauer_detach(struct pcmcia_device *p_dev);
/*
You'll also need to prototype all the functions that will actually
@@ -117,35 +114,6 @@ static void sedlbauer_detach(dev_link_t *);
*/
/*
- 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 = "sedlbauer_cs";
-
-/*
- A linked list of "instances" of the sedlbauer device. Each actual
- PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
-
- You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
- device numbers are used to derive the corresponding array index.
-*/
-
-static dev_link_t *dev_list = NULL;
-
-/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
- To simplify the data structure handling, we actually include the
- dev_link_t structure in the device's private data structure.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -180,18 +148,16 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *sedlbauer_attach(void)
+static int sedlbauer_attach(struct pcmcia_device *p_dev)
{
local_info_t *local;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) return NULL;
+ if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
link = &local->link; link->priv = local;
@@ -221,20 +187,13 @@ static dev_link_t *sedlbauer_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- sedlbauer_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ sedlbauer_config(link);
- return link;
+ return 0;
} /* sedlbauer_attach */
/*======================================================================
@@ -246,39 +205,17 @@ static dev_link_t *sedlbauer_attach(void)
======================================================================*/
-static void sedlbauer_detach(dev_link_t *link)
+static void sedlbauer_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
- /*
- If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
- printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' "
- "still locked\n", link->dev->dev_name);
-#endif
- link->state |= DEV_STALE_LINK;
- return;
+ ((local_info_t *)link->priv)->stop = 1;
+ sedlbauer_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;
/* This points to the parent local_info_t struct */
kfree(link->priv);
} /* sedlbauer_detach */
@@ -547,68 +484,34 @@ static void sedlbauer_release(dev_link_t *link)
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
-
- if (link->state & DEV_STALE_LINK)
- sedlbauer_detach(link);
-
} /* sedlbauer_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received.
-
- When a CARD_REMOVAL event is received, we immediately set a
- private flag to block future accesses to this device. All the
- functions that actually access the device should check this flag
- to make sure the card is still present.
-
-======================================================================*/
-
-static int sedlbauer_event(event_t event, int priority,
- event_callback_args_t *args)
+static int sedlbauer_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- local_info_t *dev = link->priv;
-
- DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- ((local_info_t *)link->priv)->stop = 1;
- sedlbauer_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sedlbauer_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
+
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- /* Mark the device as stopped, to block IO until later */
dev->stop = 1;
if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int sedlbauer_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
+ pcmcia_request_configuration(link->handle, &link->conf);
dev->stop = 0;
- /*
- In a normal driver, additional code may go here to restore
- the device state and restart IO.
- */
- break;
- }
- return 0;
-} /* sedlbauer_event */
+
+ return 0;
+}
+
static struct pcmcia_device_id sedlbauer_ids[] = {
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
@@ -627,10 +530,11 @@ static struct pcmcia_driver sedlbauer_driver = {
.drv = {
.name = "sedlbauer_cs",
},
- .attach = sedlbauer_attach,
- .event = sedlbauer_event,
- .detach = sedlbauer_detach,
+ .probe = sedlbauer_attach,
+ .remove = sedlbauer_detach,
.id_table = sedlbauer_ids,
+ .suspend = sedlbauer_suspend,
+ .resume = sedlbauer_resume,
};
static int __init init_sedlbauer_cs(void)
@@ -641,7 +545,6 @@ static int __init init_sedlbauer_cs(void)
static void __exit exit_sedlbauer_cs(void)
{
pcmcia_unregister_driver(&sedlbauer_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_sedlbauer_cs);
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 8e192a3a3490..99cb0f3d59a1 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -180,7 +180,6 @@ static struct usb_device_id st5481_ids[] = {
MODULE_DEVICE_TABLE (usb, st5481_ids);
static struct usb_driver st5481_usb_driver = {
- .owner = THIS_MODULE,
.name = "st5481_usb",
.probe = probe_st5481,
.disconnect = disconnect_st5481,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 0ddef1bf778b..4e5c14c7240e 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -77,8 +77,6 @@ module_param(protocol, int, 0);
static void teles_cs_config(dev_link_t *link);
static void teles_cs_release(dev_link_t *link);
-static int teles_cs_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -86,16 +84,7 @@ static int teles_cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *teles_attach(void);
-static void teles_detach(dev_link_t *);
-
-/*
- 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 = "teles_cs";
+static void teles_detach(struct pcmcia_device *p_dev);
/*
A linked list of "instances" of the teles_cs device. Each actual
@@ -107,18 +96,7 @@ static dev_info_t dev_info = "teles_cs";
device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list = NULL;
-
/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
- To simplify the data structure handling, we actually include the
- dev_link_t structure in the device's private data structure.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -152,18 +130,16 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *teles_attach(void)
+static int teles_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
DEBUG(0, "teles_attach()\n");
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
- if (!local) return NULL;
+ if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
local->cardnr = -1;
link = &local->link; link->priv = local;
@@ -188,20 +164,13 @@ static dev_link_t *teles_attach(void)
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- teles_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ teles_cs_config(link);
- return link;
+ return 0;
} /* teles_attach */
/*======================================================================
@@ -213,32 +182,18 @@ static dev_link_t *teles_attach(void)
======================================================================*/
-static void teles_detach(dev_link_t *link)
+static void teles_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
local_info_t *info = link->priv;
- int ret;
DEBUG(0, "teles_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
- if (link->state & DEV_CONFIG)
- teles_cs_release(link);
-
- /* Break the link with Card Services */
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
+ if (link->state & DEV_CONFIG) {
+ info->busy = 1;
+ teles_cs_release(link);
}
- /* Unlink device structure and free it */
- *linkp = link->next;
kfree(info);
} /* teles_detach */
@@ -428,60 +383,32 @@ static void teles_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
} /* teles_cs_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
+static int teles_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
+ link->state |= DEV_SUSPEND;
+ dev->busy = 1;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
-======================================================================*/
+ return 0;
+}
-static int teles_cs_event(event_t event, int priority,
- event_callback_args_t *args)
+static int teles_resume(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- local_info_t *dev = link->priv;
-
- DEBUG(1, "teles_cs_event(%d)\n", event);
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *dev = link->priv;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- ((local_info_t*)link->priv)->busy = 1;
- teles_cs_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- teles_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 */
- dev->busy = 1;
- if (link->state & DEV_CONFIG)
- 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)
- pcmcia_request_configuration(link->handle, &link->conf);
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0;
- break;
- }
- return 0;
-} /* teles_cs_event */
+
+ return 0;
+}
+
static struct pcmcia_device_id teles_ids[] = {
PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
@@ -494,10 +421,11 @@ static struct pcmcia_driver teles_cs_driver = {
.drv = {
.name = "teles_cs",
},
- .attach = teles_attach,
- .event = teles_cs_event,
- .detach = teles_detach,
+ .probe = teles_attach,
+ .remove = teles_detach,
.id_table = teles_ids,
+ .suspend = teles_suspend,
+ .resume = teles_resume,
};
static int __init init_teles_cs(void)
@@ -508,7 +436,6 @@ static int __init init_teles_cs(void)
static void __exit exit_teles_cs(void)
{
pcmcia_unregister_driver(&teles_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_teles_cs);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4643df097bfe..22759c01746a 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -857,6 +857,118 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
return count;
}
+/*
+ * isdn_readbchan_tty() tries to get data from the read-queue.
+ * It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he
+ */
+int
+isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack)
+{
+ int count;
+ int count_pull;
+ int count_put;
+ int dflag;
+ struct sk_buff *skb;
+ char last = 0;
+ int len;
+
+ if (!dev->drv[di])
+ return 0;
+ if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
+ return 0;
+
+ len = tty_buffer_request_room(tty, dev->drv[di]->rcvcount[channel]);
+ if(len == 0)
+ return len;
+
+ count = 0;
+ while (len) {
+ if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
+ break;
+#ifdef CONFIG_ISDN_AUDIO
+ if (ISDN_AUDIO_SKB_LOCK(skb))
+ break;
+ ISDN_AUDIO_SKB_LOCK(skb) = 1;
+ if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
+ char *p = skb->data;
+ unsigned long DLEmask = (1 << channel);
+
+ dflag = 0;
+ count_pull = count_put = 0;
+ while ((count_pull < skb->len) && (len > 0)) {
+ len--;
+ if (dev->drv[di]->DLEflag & DLEmask) {
+ last = DLE;
+ dev->drv[di]->DLEflag &= ~DLEmask;
+ } else {
+ last = *p;
+ if (last == DLE) {
+ dev->drv[di]->DLEflag |= DLEmask;
+ (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
+ }
+ p++;
+ count_pull++;
+ }
+ count_put++;
+ }
+ if (count_pull >= skb->len)
+ dflag = 1;
+ } else {
+#endif
+ /* No DLE's in buff, so simply copy it */
+ dflag = 1;
+ if ((count_pull = skb->len) > len) {
+ count_pull = len;
+ dflag = 0;
+ }
+ count_put = count_pull;
+ if(count_put > 1)
+ tty_insert_flip_string(tty, skb->data, count_put - 1);
+ last = skb->data[count_put] - 1;
+ len -= count_put;
+#ifdef CONFIG_ISDN_AUDIO
+ }
+#endif
+ count += count_put;
+ if (dflag) {
+ /* We got all the data in this buff.
+ * Now we can dequeue it.
+ */
+ if(cisco_hack)
+ tty_insert_flip_char(tty, last, 0xFF);
+ else
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
+ dev_kfree_skb(skb);
+ } else {
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+ /* Not yet emptied this buff, so it
+ * must stay in the queue, for further calls
+ * but we pull off the data we got until now.
+ */
+ skb_pull(skb, count_pull);
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ }
+ dev->drv[di]->rcvcount[channel] -= count_put;
+ }
+ return count;
+}
+
+
static __inline int
isdn_minor2drv(int minor)
{
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index e27e9c3a81ed..082735dbb412 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -37,6 +37,7 @@ extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+extern int isdn_readbchan_tty(int, int, struct tty_struct *, int);
extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 8c404b4e2482..f190a99604f0 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -64,37 +64,42 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
int c;
int len;
struct tty_struct *tty;
+ char last;
if (info->online) {
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
len = skb->len
#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_DLECOUNT(skb)
#endif
;
+
+ c = tty_buffer_request_room(tty, len);
if (c >= len) {
#ifdef CONFIG_ISDN_AUDIO
- if (ISDN_AUDIO_SKB_DLECOUNT(skb))
- while (skb->len--) {
+ if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
+ int l = skb->len;
+ unsigned char *dp = skb->data;
+ while (--l) {
if (*skb->data == DLE)
tty_insert_flip_char(tty, DLE, 0);
- tty_insert_flip_char(tty, *skb->data++, 0);
+ tty_insert_flip_char(tty, *dp++, 0);
+ }
+ last = *dp;
} else {
#endif
- memcpy(tty->flip.char_buf_ptr,
- skb->data, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.flag_buf_ptr += len;
+ if(len > 1)
+ tty_insert_flip_string(tty, skb->data, len - 1);
+ last = skb->data[len - 1];
#ifdef CONFIG_ISDN_AUDIO
}
#endif
if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
- tty->flip.flag_buf_ptr[len - 1] = 0xff;
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_insert_flip_char(tty, last, 0xFF);
+ else
+ tty_insert_flip_char(tty, last, TTY_NORMAL);
+ tty_flip_buffer_push(tty);
kfree_skb(skb);
return 1;
}
@@ -114,7 +119,6 @@ isdn_tty_readmodem(void)
int resched = 0;
int midx;
int i;
- int c;
int r;
struct tty_struct *tty;
modem_info *info;
@@ -131,20 +135,13 @@ isdn_tty_readmodem(void)
#endif
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
- if (c > 0) {
- r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
- tty->flip.char_buf_ptr,
- tty->flip.flag_buf_ptr, c, NULL);
- /* CISCO AsyncPPP Hack */
- if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
- memset(tty->flip.flag_buf_ptr, 0, r);
- tty->flip.count += r;
- tty->flip.flag_buf_ptr += r;
- tty->flip.char_buf_ptr += r;
- if (r)
- schedule_delayed_work(&tty->flip.work, 1);
- }
+ /* CISCO AsyncPPP Hack */
+ if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 0);
+ else
+ r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, tty, 1);
+ if (r)
+ tty_flip_buffer_push(tty);
} else
r = 1;
} else
@@ -249,7 +246,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
}
#endif
#endif
- /* Try to deliver directly via tty-flip-buf if queue is empty */
+ /* Try to deliver directly via tty-buf if queue is empty */
spin_lock_irqsave(&info->readlock, flags);
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
if (isdn_tty_try_read(info, skb)) {
@@ -534,7 +531,7 @@ isdn_tty_senddown(modem_info * info)
/* The next routine is called once from within timer-interrupt
* triggered within isdn_tty_modem_ncarrier(). It calls
* isdn_tty_modem_result() to stuff a "NO CARRIER" Message
- * into the tty's flip-buffer.
+ * into the tty's buffer.
*/
static void
isdn_tty_modem_do_ncarrier(unsigned long data)
@@ -2347,6 +2344,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
u_long flags;
struct sk_buff *skb = NULL;
char *sp = NULL;
+ int l = strlen(msg);
if (!msg) {
printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
@@ -2359,16 +2357,16 @@ isdn_tty_at_cout(char *msg, modem_info * info)
return;
}
- /* use queue instead of direct flip, if online and */
- /* data is in queue or flip buffer is full */
- if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
- (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
- skb = alloc_skb(strlen(msg), GFP_ATOMIC);
+ /* use queue instead of direct, if online and */
+ /* data is in queue or buffer is full */
+ if ((info->online && tty_buffer_request_room(tty, l) < l) ||
+ (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
+ skb = alloc_skb(l, GFP_ATOMIC);
if (!skb) {
spin_unlock_irqrestore(&info->readlock, flags);
return;
}
- sp = skb_put(skb, strlen(msg));
+ sp = skb_put(skb, l);
#ifdef CONFIG_ISDN_AUDIO
ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
ISDN_AUDIO_SKB_LOCK(skb) = 0;
@@ -2392,9 +2390,8 @@ isdn_tty_at_cout(char *msg, modem_info * info)
if (skb) {
*sp++ = c;
} else {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ if(tty_insert_flip_char(tty, c, TTY_NORMAL) == 0)
break;
- tty_insert_flip_char(tty, c, 0);
}
}
if (skb) {
@@ -2402,12 +2399,12 @@ isdn_tty_at_cout(char *msg, modem_info * info)
dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
spin_unlock_irqrestore(&info->readlock, flags);
/* Schedule dequeuing */
- if ((dev->modempoll) && (info->rcvsched))
+ if (dev->modempoll && info->rcvsched)
isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
} else {
spin_unlock_irqrestore(&info->readlock, flags);
- schedule_delayed_work(&tty->flip.work, 1);
+ tty_flip_buffer_push(tty);
}
}
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index 19f2fcf0ae4a..b4b24335f716 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -43,7 +43,6 @@ extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
RspMessage *, int);
extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int *);
-extern inline void pullphone(char *, char *);
#ifdef DEBUG
/*
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index a0ea44c3e8b1..7d4a0ac28c06 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -149,14 +149,14 @@ config MAC_EMUMOUSEBTN
config THERM_WINDTUNNEL
tristate "Support for thermal management on Windtunnel G4s"
- depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64
help
This driver provides some thermostat and fan control for the desktop
G4 "Windtunnel"
config THERM_ADT746X
tristate "Support for thermal mgmnt on laptops with ADT 746x chipset"
- depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64
help
This driver provides some thermostat and fan control for the
iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty
@@ -164,7 +164,7 @@ config THERM_ADT746X
config THERM_PM72
tristate "Support for thermal management on PowerMac G5"
- depends on I2C && I2C_KEYWEST && PPC_PMAC64
+ depends on I2C && I2C_POWERMAC && PPC_PMAC64
help
This driver provides thermostat and fan control for the desktop
G5 machines.
@@ -175,14 +175,14 @@ config WINDFARM
config WINDFARM_PM81
tristate "Support for thermal management on iMac G5"
depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
- select I2C_PMAC_SMU
+ select I2C_POWERMAC
help
This driver provides thermal control for the iMacG5
config WINDFARM_PM91
tristate "Support for thermal management on PowerMac9,1"
depends on WINDFARM && I2C && CPU_FREQ_PMAC64 && PMAC_SMU
- select I2C_PMAC_SMU
+ select I2C_POWERMAC
help
This driver provides thermal control for the PowerMac9,1
which is the recent (SMU based) single CPU desktop G5
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index 71aeb912ec61..d56d400b6aaa 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -239,7 +239,7 @@ static int adb_iop_write(struct adb_request *req)
local_irq_save(flags);
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c
index cf6a6f2248ac..314fc0830d90 100644
--- a/drivers/macintosh/macio-adb.c
+++ b/drivers/macintosh/macio-adb.c
@@ -17,6 +17,7 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <linux/init.h>
+#include <linux/ioport.h>
struct preg {
unsigned char r;
@@ -88,24 +89,26 @@ int macio_probe(void)
int macio_init(void)
{
struct device_node *adbs;
+ struct resource r;
adbs = find_compatible_devices("adb", "chrp,adb0");
if (adbs == 0)
return -ENXIO;
#if 0
- { int i;
+ { int i = 0;
printk("macio_adb_init: node = %p, addrs =", adbs->node);
- for (i = 0; i < adbs->n_addrs; ++i)
- printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size);
+ while(!of_address_to_resource(adbs, i, &r))
+ printk(" %x(%x)", r.start, r.end - r.start);
printk(", intrs =");
for (i = 0; i < adbs->n_intrs; ++i)
printk(" %x", adbs->intrs[i].line);
printk("\n"); }
#endif
-
- adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs));
+ if (of_address_to_resource(adbs, 0, &r))
+ return -ENXIO;
+ adb = ioremap(r.start, sizeof(struct adb_regs));
out_8(&adb->ctrl.r, 0);
out_8(&adb->intr.r, 0);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index c34c96d18907..ed6d3174d660 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -3,6 +3,13 @@
* a MacIO ASIC. Interface to new driver model mostly
* stolen from the PCI version.
*
+ * Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.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.
+ *
* TODO:
*
* - Don't probe below media bay by default, but instead provide
@@ -128,7 +135,7 @@ static int macio_device_resume(struct device * dev)
return 0;
}
-static int macio_hotplug (struct device *dev, char **envp, int num_envp,
+static int macio_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct macio_dev * macio_dev;
@@ -203,7 +210,10 @@ extern struct device_attribute macio_dev_attrs[];
struct bus_type macio_bus_type = {
.name = "macio",
.match = macio_bus_match,
- .hotplug = macio_hotplug,
+ .uevent = macio_uevent,
+ .probe = macio_device_probe,
+ .remove = macio_device_remove,
+ .shutdown = macio_device_shutdown,
.suspend = macio_device_suspend,
.resume = macio_device_resume,
.dev_attrs = macio_dev_attrs,
@@ -218,12 +228,14 @@ postcore_initcall(macio_bus_driver_init);
/**
- * macio_release_dev - free a macio device structure when all users of it are finished.
+ * macio_release_dev - free a macio device structure when all users of it are
+ * finished.
* @dev: device that's been disconnected
*
- * Will be called only by the device core when all users of this macio device are
- * done. This currently means never as we don't hot remove any macio device yet,
- * though that will happen with mediabay based devices in a later implementation.
+ * Will be called only by the device core when all users of this macio device
+ * are done. This currently means never as we don't hot remove any macio
+ * device yet, though that will happen with mediabay based devices in a later
+ * implementation.
*/
static void macio_release_dev(struct device *dev)
{
@@ -242,49 +254,114 @@ static void macio_release_dev(struct device *dev)
* If this routine returns non-null, then the resource is completely
* skipped.
*/
-static int macio_resource_quirks(struct device_node *np, struct resource *res, int index)
+static int macio_resource_quirks(struct device_node *np, struct resource *res,
+ int index)
{
if (res->flags & IORESOURCE_MEM) {
/* Grand Central has too large resource 0 on some machines */
- if (index == 0 && !strcmp(np->name, "gc")) {
- np->addrs[0].size = 0x20000;
+ if (index == 0 && !strcmp(np->name, "gc"))
res->end = res->start + 0x1ffff;
- }
+
/* Airport has bogus resource 2 */
if (index >= 2 && !strcmp(np->name, "radio"))
return 1;
+
+#ifndef CONFIG_PPC64
/* DBDMAs may have bogus sizes */
- if ((res->start & 0x0001f000) == 0x00008000) {
- np->addrs[index].size = 0x100;
+ if ((res->start & 0x0001f000) == 0x00008000)
res->end = res->start + 0xff;
- }
- /* ESCC parent eats child resources. We could have added a level of hierarchy,
- * but I don't really feel the need for it */
+#endif /* CONFIG_PPC64 */
+
+ /* ESCC parent eats child resources. We could have added a
+ * level of hierarchy, but I don't really feel the need
+ * for it
+ */
if (!strcmp(np->name, "escc"))
return 1;
+
/* ESCC has bogus resources >= 3 */
- if (index >= 3 && !(strcmp(np->name, "ch-a") && strcmp(np->name, "ch-b")))
+ if (index >= 3 && !(strcmp(np->name, "ch-a") &&
+ strcmp(np->name, "ch-b")))
return 1;
+
/* Media bay has too many resources, keep only first one */
if (index > 0 && !strcmp(np->name, "media-bay"))
return 1;
+
/* Some older IDE resources have bogus sizes */
if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") &&
strcmp(np->type, "ide") && strcmp(np->type, "ata"))) {
- if (index == 0 && np->addrs[0].size > 0x1000) {
- np->addrs[0].size = 0x1000;
+ if (index == 0 && (res->end - res->start) > 0xfff)
res->end = res->start + 0xfff;
- }
- if (index == 1 && np->addrs[1].size > 0x100) {
- np->addrs[1].size = 0x100;
+ if (index == 1 && (res->end - res->start) > 0xff)
res->end = res->start + 0xff;
- }
}
}
return 0;
}
+static void macio_setup_interrupts(struct macio_dev *dev)
+{
+ struct device_node *np = dev->ofdev.node;
+ int i,j;
+
+ /* For now, we use pre-parsed entries in the device-tree for
+ * interrupt routing and addresses, but we should change that
+ * to dynamically parsed entries and so get rid of most of the
+ * clutter in struct device_node
+ */
+ for (i = j = 0; i < np->n_intrs; i++) {
+ struct resource *res = &dev->interrupt[j];
+
+ if (j >= MACIO_DEV_COUNT_IRQS)
+ break;
+ res->start = np->intrs[i].line;
+ res->flags = IORESOURCE_IO;
+ if (np->intrs[j].sense)
+ res->flags |= IORESOURCE_IRQ_LOWLEVEL;
+ else
+ res->flags |= IORESOURCE_IRQ_HIGHEDGE;
+ res->name = dev->ofdev.dev.bus_id;
+ if (macio_resource_quirks(np, res, i))
+ memset(res, 0, sizeof(struct resource));
+ else
+ j++;
+ }
+ dev->n_interrupts = j;
+}
+
+static void macio_setup_resources(struct macio_dev *dev,
+ struct resource *parent_res)
+{
+ struct device_node *np = dev->ofdev.node;
+ struct resource r;
+ int index;
+
+ for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) {
+ struct resource *res = &dev->resource[index];
+ if (index >= MACIO_DEV_COUNT_RESOURCES)
+ break;
+ *res = r;
+ res->name = dev->ofdev.dev.bus_id;
+
+ if (macio_resource_quirks(np, res, index)) {
+ memset(res, 0, sizeof(struct resource));
+ continue;
+ }
+ /* Currently, we consider failure as harmless, this may
+ * change in the future, once I've found all the device
+ * tree bugs in older machines & worked around them
+ */
+ if (insert_resource(parent_res, res)) {
+ printk(KERN_WARNING "Can't request resource "
+ "%d for MacIO device %s\n",
+ index, dev->ofdev.dev.bus_id);
+ }
+ }
+ dev->n_resources = index;
+}
+
/**
* macio_add_one_device - Add one device from OF node to the device tree
* @chip: pointer to the macio_chip holding the device
@@ -294,12 +371,13 @@ static int macio_resource_quirks(struct device_node *np, struct resource *res, i
* When media-bay is changed to hotswap drivers, this function will
* be exposed to the bay driver some way...
*/
-static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct device *parent,
- struct device_node *np, struct macio_dev *in_bay,
+static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
+ struct device *parent,
+ struct device_node *np,
+ struct macio_dev *in_bay,
struct resource *parent_res)
{
struct macio_dev *dev;
- int i, j;
u32 *reg;
if (np == NULL)
@@ -326,7 +404,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d
/* MacIO itself has a different reg, we use it's PCI base */
if (np == chip->of_node) {
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s", chip->lbus.index,
+ sprintf(dev->ofdev.dev.bus_id, "%1d.%08lx:%.*s",
+ chip->lbus.index,
#ifdef CONFIG_PCI
pci_resource_start(chip->lbus.pdev, 0),
#else
@@ -335,57 +414,16 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct d
MAX_NODE_NAME_SIZE, np->name);
} else {
reg = (u32 *)get_property(np, "reg", NULL);
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index,
+ sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
+ chip->lbus.index,
reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
}
- /* For now, we use pre-parsed entries in the device-tree for
- * interrupt routing and addresses, but we should change that
- * to dynamically parsed entries and so get rid of most of the
- * clutter in struct device_node
- */
- for (i = j = 0; i < np->n_intrs; i++) {
- struct resource *res = &dev->interrupt[j];
-
- if (j >= MACIO_DEV_COUNT_IRQS)
- break;
- res->start = np->intrs[i].line;
- res->flags = IORESOURCE_IO;
- if (np->intrs[j].sense)
- res->flags |= IORESOURCE_IRQ_LOWLEVEL;
- else
- res->flags |= IORESOURCE_IRQ_HIGHEDGE;
- res->name = dev->ofdev.dev.bus_id;
- if (macio_resource_quirks(np, res, i))
- memset(res, 0, sizeof(struct resource));
- else
- j++;
- }
- dev->n_interrupts = j;
- for (i = j = 0; i < np->n_addrs; i++) {
- struct resource *res = &dev->resource[j];
-
- if (j >= MACIO_DEV_COUNT_RESOURCES)
- break;
- res->start = np->addrs[i].address;
- res->end = np->addrs[i].address + np->addrs[i].size - 1;
- res->flags = IORESOURCE_MEM;
- res->name = dev->ofdev.dev.bus_id;
- if (macio_resource_quirks(np, res, i))
- memset(res, 0, sizeof(struct resource));
- else {
- j++;
- /* Currently, we consider failure as harmless, this may
- * change in the future, once I've found all the device
- * tree bugs in older machines & worked around them
- */
- if (insert_resource(parent_res, res))
- printk(KERN_WARNING "Can't request resource %d for MacIO"
- " device %s\n", i, dev->ofdev.dev.bus_id);
- }
- }
- dev->n_resources = j;
+ /* Setup interrupts & resources */
+ macio_setup_interrupts(dev);
+ macio_setup_resources(dev, parent_res);
+ /* Register with core */
if (of_device_register(&dev->ofdev) != 0) {
printk(KERN_DEBUG"macio: device registration error for %s!\n",
dev->ofdev.dev.bus_id);
@@ -442,36 +480,42 @@ static void macio_pci_add_devices(struct macio_chip *chip)
/* First scan 1st level */
for (np = NULL; (np = of_get_next_child(pnode, np)) != NULL;) {
- if (!macio_skip_device(np)) {
- of_node_get(np);
- mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, root_res);
- if (mdev == NULL)
- of_node_put(np);
- else if (strncmp(np->name, "media-bay", 9) == 0)
- mbdev = mdev;
- else if (strncmp(np->name, "escc", 4) == 0)
- sdev = mdev;
- }
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL,
+ root_res);
+ if (mdev == NULL)
+ of_node_put(np);
+ else if (strncmp(np->name, "media-bay", 9) == 0)
+ mbdev = mdev;
+ else if (strncmp(np->name, "escc", 4) == 0)
+ sdev = mdev;
}
/* Add media bay devices if any */
if (mbdev)
- for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np)) != NULL;)
- if (!macio_skip_device(np)) {
- of_node_get(np);
- if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, mbdev,
- root_res) == NULL)
- of_node_put(np);
- }
+ for (np = NULL; (np = of_get_next_child(mbdev->ofdev.node, np))
+ != NULL;) {
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ if (macio_add_one_device(chip, &mbdev->ofdev.dev, np,
+ mbdev, root_res) == NULL)
+ of_node_put(np);
+ }
+
/* Add serial ports if any */
if (sdev) {
- for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np)) != NULL;)
- if (!macio_skip_device(np)) {
- of_node_get(np);
- if (macio_add_one_device(chip, &sdev->ofdev.dev, np, NULL,
- root_res) == NULL)
- of_node_put(np);
- }
+ for (np = NULL; (np = of_get_next_child(sdev->ofdev.node, np))
+ != NULL;) {
+ if (macio_skip_device(np))
+ continue;
+ of_node_get(np);
+ if (macio_add_one_device(chip, &sdev->ofdev.dev, np,
+ NULL, root_res) == NULL)
+ of_node_put(np);
+ }
}
}
@@ -487,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &macio_bus_type;
- drv->driver.probe = macio_device_probe;
- drv->driver.remove = macio_device_remove;
- drv->driver.shutdown = macio_device_shutdown;
/* register with core */
count = driver_register(&drv->driver);
@@ -519,7 +560,8 @@ void macio_unregister_driver(struct macio_driver *drv)
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
-int macio_request_resource(struct macio_dev *dev, int resource_no, const char *name)
+int macio_request_resource(struct macio_dev *dev, int resource_no,
+ const char *name)
{
if (macio_resource_len(dev, resource_no) == 0)
return 0;
@@ -606,20 +648,20 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi
if (ent->vendor != PCI_VENDOR_ID_APPLE)
return -ENODEV;
- /* Note regarding refcounting: We assume pci_device_to_OF_node() is ported
- * to new OF APIs and returns a node with refcount incremented. This isn't
- * the case today, but on the other hand ppc32 doesn't do refcounting. This
- * will have to be fixed when going to ppc64. --BenH.
+ /* Note regarding refcounting: We assume pci_device_to_OF_node() is
+ * ported to new OF APIs and returns a node with refcount incremented.
*/
np = pci_device_to_OF_node(pdev);
if (np == NULL)
return -ENODEV;
- /* This assumption is wrong, fix that here for now until I fix the arch */
+ /* The above assumption is wrong !!!
+ * fix that here for now until I fix the arch code
+ */
of_node_get(np);
- /* We also assume that pmac_feature will have done a get() on nodes stored
- * in the macio chips array
+ /* We also assume that pmac_feature will have done a get() on nodes
+ * stored in the macio chips array
*/
chip = macio_find(np, macio_unknown);
of_node_put(np);
@@ -639,9 +681,9 @@ static int __devinit macio_pci_probe(struct pci_dev *pdev, const struct pci_devi
/*
* HACK ALERT: The WallStreet PowerBook and some OHare based machines
- * have 2 macio ASICs. I must probe the "main" one first or IDE ordering
- * will be incorrect. So I put on "hold" the second one since it seem to
- * appear first on PCI
+ * have 2 macio ASICs. I must probe the "main" one first or IDE
+ * ordering will be incorrect. So I put on "hold" the second one since
+ * it seem to appear first on PCI
*/
if (chip->type == macio_gatwick || chip->type == macio_ohareII)
if (macio_chips[0].lbus.pdev == NULL) {
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index b856bb67169c..8dbf2852bae0 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -647,6 +647,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
struct media_bay_info* bay;
u32 __iomem *regbase;
struct device_node *ofnode;
+ unsigned long base;
int i;
ofnode = mdev->ofdev.node;
@@ -656,10 +657,11 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
if (macio_request_resources(mdev, "media-bay"))
return -EBUSY;
/* Media bay registers are located at the beginning of the
- * mac-io chip, we get the parent address for now (hrm...)
+ * mac-io chip, for now, we trick and align down the first
+ * resource passed in
*/
- regbase = (u32 __iomem *)
- ioremap(ofnode->parent->addrs[0].address, 0x100);
+ base = macio_resource_start(mdev, 0) & 0xffff0000u;
+ regbase = (u32 __iomem *)ioremap(base, 0x100);
if (regbase == NULL) {
macio_release_resources(mdev);
return -ENOMEM;
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index e8378274d710..db2ae71d07ef 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -53,7 +53,7 @@
#undef DEBUG_SMU
#ifdef DEBUG_SMU
-#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0)
+#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
#else
#define DPRINTK(fmt, args...) do { } while (0)
#endif
@@ -94,6 +94,8 @@ struct smu_device {
static struct smu_device *smu;
static DECLARE_MUTEX(smu_part_access);
+static void smu_i2c_retry(unsigned long data);
+
/*
* SMU driver low level stuff
*/
@@ -469,7 +471,6 @@ int __init smu_init (void)
smu->of_node = np;
smu->db_irq = NO_IRQ;
smu->msg_irq = NO_IRQ;
- init_timer(&smu->i2c_timer);
/* smu_cmdbuf_abs is in the low 2G of RAM, can be converted to a
* 32 bits value safely
@@ -544,6 +545,10 @@ static int smu_late_init(void)
if (!smu)
return 0;
+ init_timer(&smu->i2c_timer);
+ smu->i2c_timer.function = smu_i2c_retry;
+ smu->i2c_timer.data = (unsigned long)smu;
+
/*
* Try to request the interrupts
*/
@@ -570,7 +575,10 @@ static int smu_late_init(void)
return 0;
}
-arch_initcall(smu_late_init);
+/* This has to be before arch_initcall as the low i2c stuff relies on the
+ * above having been done before we reach arch_initcalls
+ */
+core_initcall(smu_late_init);
/*
* sysfs visibility
@@ -580,20 +588,10 @@ static void smu_expose_childs(void *unused)
{
struct device_node *np;
- for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;) {
- if (device_is_compatible(np, "smu-i2c")) {
- char name[32];
- u32 *reg = (u32 *)get_property(np, "reg", NULL);
-
- if (reg == NULL)
- continue;
- sprintf(name, "smu-i2c-%02x", *reg);
- of_platform_device_create(np, name, &smu->of_dev->dev);
- }
+ for (np = NULL; (np = of_get_next_child(smu->of_node, np)) != NULL;)
if (device_is_compatible(np, "smu-sensors"))
- of_platform_device_create(np, "smu-sensors", &smu->of_dev->dev);
- }
-
+ of_platform_device_create(np, "smu-sensors",
+ &smu->of_dev->dev);
}
static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL);
@@ -712,13 +710,13 @@ static void smu_i2c_complete_command(struct smu_i2c_cmd *cmd, int fail)
static void smu_i2c_retry(unsigned long data)
{
- struct smu_i2c_cmd *cmd = (struct smu_i2c_cmd *)data;
+ struct smu_i2c_cmd *cmd = smu->cmd_i2c_cur;
DPRINTK("SMU: i2c failure, requeuing...\n");
/* requeue command simply by resetting reply_len */
cmd->pdata[0] = 0xff;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
smu_queue_cmd(&cmd->scmd);
}
@@ -747,10 +745,8 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
*/
if (fail && --cmd->retries > 0) {
DPRINTK("SMU: i2c failure, starting timer...\n");
- smu->i2c_timer.function = smu_i2c_retry;
- smu->i2c_timer.data = (unsigned long)cmd;
- smu->i2c_timer.expires = jiffies + msecs_to_jiffies(5);
- add_timer(&smu->i2c_timer);
+ BUG_ON(cmd != smu->cmd_i2c_cur);
+ mod_timer(&smu->i2c_timer, jiffies + msecs_to_jiffies(5));
return;
}
@@ -764,7 +760,7 @@ static void smu_i2c_low_completion(struct smu_cmd *scmd, void *misc)
/* Ok, initial command complete, now poll status */
scmd->reply_buf = cmd->pdata;
- scmd->reply_len = 0x10;
+ scmd->reply_len = sizeof(cmd->pdata);
scmd->data_buf = cmd->pdata;
scmd->data_len = 1;
cmd->pdata[0] = 0;
@@ -786,7 +782,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd)
cmd->scmd.done = smu_i2c_low_completion;
cmd->scmd.misc = cmd;
cmd->scmd.reply_buf = cmd->pdata;
- cmd->scmd.reply_len = 0x10;
+ cmd->scmd.reply_len = sizeof(cmd->pdata);
cmd->scmd.data_buf = (u8 *)(char *)&cmd->info;
cmd->scmd.status = 1;
cmd->stage = 0;
@@ -909,10 +905,13 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
struct property *prop;
/* First query the partition info */
+ DPRINTK("SMU: Query partition infos ... (irq=%d)\n", smu->db_irq);
smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2,
smu_done_complete, &comp,
SMU_CMD_PARTITION_LATEST, id);
wait_for_completion(&comp);
+ DPRINTK("SMU: done, status: %d, reply_len: %d\n",
+ cmd.cmd.status, cmd.cmd.reply_len);
/* Partition doesn't exist (or other error) */
if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6)
@@ -975,6 +974,8 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
sprintf(pname, "sdb-partition-%02x", id);
+ DPRINTK("smu_get_sdb_partition(%02x)\n", id);
+
if (interruptible) {
int rc;
rc = down_interruptible(&smu_part_access);
@@ -986,6 +987,7 @@ struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size,
part = (struct smu_sdbp_header *)get_property(smu->of_node,
pname, size);
if (part == NULL) {
+ DPRINTK("trying to extract from SMU ...\n");
part = smu_create_sdb_partition(id);
if (part != NULL && size)
*size = part->len << 2;
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index f38696622eb4..5ebfd1d138da 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -52,6 +52,7 @@ static char *sensor_location[3] = {NULL, NULL, NULL};
static int limit_adjust = 0;
static int fan_speed = -1;
+static int verbose = 0;
MODULE_AUTHOR("Colin Leroy <colin@colino.net>");
MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
@@ -66,6 +67,10 @@ module_param(fan_speed, int, 0644);
MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) "
"(default 64)");
+module_param(verbose, bool, 0);
+MODULE_PARM_DESC(verbose,"Verbose log operations "
+ "(default 0)");
+
struct thermostat {
struct i2c_client clt;
u8 temps[3];
@@ -149,13 +154,13 @@ detach_thermostat(struct i2c_adapter *adapter)
if (thread_therm != NULL) {
kthread_stop(thread_therm);
}
-
+
printk(KERN_INFO "adt746x: Putting max temperatures back from "
"%d, %d, %d to %d, %d, %d\n",
th->limits[0], th->limits[1], th->limits[2],
th->initial_limits[0], th->initial_limits[1],
th->initial_limits[2]);
-
+
for (i = 0; i < 3; i++)
write_reg(th, LIMIT_REG[i], th->initial_limits[i]);
@@ -171,9 +176,9 @@ detach_thermostat(struct i2c_adapter *adapter)
}
static struct i2c_driver thermostat_driver = {
- .owner = THIS_MODULE,
- .name = "therm_adt746x",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "therm_adt746x",
+ },
.attach_adapter = attach_thermostat,
.detach_adapter = detach_thermostat,
};
@@ -212,12 +217,14 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
return;
if (th->last_speed[fan] != speed) {
- if (speed == -1)
- printk(KERN_DEBUG "adt746x: Setting speed to automatic "
- "for %s fan.\n", sensor_location[fan+1]);
- else
- printk(KERN_DEBUG "adt746x: Setting speed to %d "
- "for %s fan.\n", speed, sensor_location[fan+1]);
+ if (verbose) {
+ if (speed == -1)
+ printk(KERN_DEBUG "adt746x: Setting speed to automatic "
+ "for %s fan.\n", sensor_location[fan+1]);
+ else
+ printk(KERN_DEBUG "adt746x: Setting speed to %d "
+ "for %s fan.\n", speed, sensor_location[fan+1]);
+ }
} else
return;
@@ -298,10 +305,11 @@ static void update_fans_speed (struct thermostat *th)
if (new_speed > 255)
new_speed = 255;
- printk(KERN_DEBUG "adt746x: setting fans speed to %d "
- "(limit exceeded by %d on %s) \n",
- new_speed, var,
- sensor_location[fan_number+1]);
+ if (verbose)
+ printk(KERN_DEBUG "adt746x: Setting fans speed to %d "
+ "(limit exceeded by %d on %s) \n",
+ new_speed, var,
+ sensor_location[fan_number+1]);
write_both_fan_speed(th, new_speed);
th->last_var[fan_number] = var;
} else if (var < -2) {
@@ -309,8 +317,9 @@ static void update_fans_speed (struct thermostat *th)
* so cold (lastvar >= -1) */
if (i == 2 && lastvar < -1) {
if (th->last_speed[fan_number] != 0)
- printk(KERN_DEBUG "adt746x: Stopping "
- "fans.\n");
+ if (verbose)
+ printk(KERN_DEBUG "adt746x: Stopping "
+ "fans.\n");
write_both_fan_speed(th, 0);
}
}
@@ -406,7 +415,7 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
th->initial_limits[i] = read_reg(th, LIMIT_REG[i]);
set_limit(th, i);
}
-
+
printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
" to %d, %d, %d\n",
th->initial_limits[0], th->initial_limits[1],
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 190878eef990..4f50ee5767a2 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -283,9 +283,9 @@ static int therm_pm72_detach(struct i2c_adapter *adapter);
static struct i2c_driver therm_pm72_driver =
{
- .owner = THIS_MODULE,
- .name = "therm_pm72",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "therm_pm72",
+ },
.attach_adapter = therm_pm72_attach,
.detach_adapter = therm_pm72_detach,
};
@@ -630,12 +630,12 @@ static int read_eeprom(int cpu, struct mpu_data *out)
sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
np = of_find_node_by_path(nodename);
if (np == NULL) {
- printk(KERN_ERR "therm_pm72: Failed to retreive cpuid node from device-tree\n");
+ printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n");
return -ENODEV;
}
data = (u8 *)get_property(np, "cpuid", &len);
if (data == NULL) {
- printk(KERN_ERR "therm_pm72: Failed to retreive cpuid property from device-tree\n");
+ printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n");
of_node_put(np);
return -ENODEV;
}
@@ -1988,18 +1988,13 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match)
{
- int rc;
-
state = state_detached;
/* Lookup the fans in the device tree */
fcu_lookup_fans(dev->node);
/* Add the driver */
- rc = i2c_add_driver(&therm_pm72_driver);
- if (rc < 0)
- return rc;
- return 0;
+ return i2c_add_driver(&therm_pm72_driver);
}
static int fcu_of_remove(struct of_device* dev)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 6aaa1df1a64e..3d9dd2e166aa 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -354,10 +354,10 @@ do_detach( struct i2c_client *client )
}
static struct i2c_driver g4fan_driver = {
- .owner = THIS_MODULE,
- .name = "therm_windtunnel",
+ .driver = {
+ .name = "therm_windtunnel",
+ },
.id = I2C_DRIVERID_G4FAN,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = do_attach,
.detach_client = do_detach,
};
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index d843a6c9c6df..2d9d79150403 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -127,39 +127,34 @@ struct adb_driver via_cuda_driver = {
#endif /* CONFIG_ADB */
#ifdef CONFIG_PPC
-int __init
-find_via_cuda(void)
+int __init find_via_cuda(void)
{
- int err;
struct adb_request req;
+ phys_addr_t taddr;
+ u32 *reg;
+ int err;
if (vias != 0)
return 1;
- vias = find_devices("via-cuda");
+ vias = of_find_node_by_name(NULL, "via-cuda");
if (vias == 0)
return 0;
- if (vias->next != 0)
- printk(KERN_WARNING "Warning: only using 1st via-cuda\n");
-
-#if 0
- { int i;
-
- printk("find_via_cuda: node = %p, addrs =", vias->node);
- for (i = 0; i < vias->n_addrs; ++i)
- printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size);
- printk(", intrs =");
- for (i = 0; i < vias->n_intrs; ++i)
- printk(" %x", vias->intrs[i].line);
- printk("\n"); }
-#endif
- if (vias->n_addrs != 1 || vias->n_intrs != 1) {
- printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n",
- vias->n_addrs, vias->n_intrs);
- if (vias->n_addrs < 1 || vias->n_intrs < 1)
- return 0;
+ reg = (u32 *)get_property(vias, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
+ goto fail;
+ }
+ taddr = of_translate_address(vias, reg);
+ if (taddr == 0) {
+ printk(KERN_ERR "via-cuda: Can't translate address !\n");
+ goto fail;
+ }
+ via = ioremap(taddr, 0x2000);
+ if (via == NULL) {
+ printk(KERN_ERR "via-cuda: Can't map address !\n");
+ goto fail;
}
- via = ioremap(vias->addrs->address, 0x2000);
cuda_state = idle;
sys_ctrler = SYS_CTRLER_CUDA;
@@ -185,6 +180,11 @@ find_via_cuda(void)
cuda_poll();
return 1;
+
+ fail:
+ of_node_put(vias);
+ vias = NULL;
+ return 0;
}
#endif /* CONFIG_PPC */
@@ -193,10 +193,6 @@ static int __init via_cuda_start(void)
if (via == NULL)
return -ENODEV;
-#ifdef CONFIG_PPC
- request_OF_resource(vias, 0, NULL);
-#endif
-
if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ);
return -EAGAIN;
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index e9a159ad3022..2a2ffe060169 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -260,7 +260,7 @@ static int macii_write(struct adb_request *req)
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
@@ -295,7 +295,7 @@ static void macii_poll(void)
unsigned long flags;
local_irq_save(flags);
- if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0);
+ if (via[IFR] & SR_INT) macii_interrupt(0, NULL, NULL);
local_irq_restore(flags);
}
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index a1966975d58f..0129fcc3b183 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -294,6 +294,24 @@ static void maciisi_sync(struct adb_request *req)
printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
}
+int
+maciisi_request(struct adb_request *req, void (*done)(struct adb_request *),
+ int nbytes, ...)
+{
+ va_list list;
+ int i;
+
+ req->nbytes = nbytes;
+ req->done = done;
+ req->reply_expected = 0;
+ va_start(list, nbytes);
+ for (i = 0; i < nbytes; i++)
+ req->data[i++] = va_arg(list, int);
+ va_end(list);
+
+ return maciisi_send_request(req, 1);
+}
+
/* Enqueue a request, and run the queue if possible */
static int
maciisi_write(struct adb_request* req)
@@ -308,7 +326,7 @@ maciisi_write(struct adb_request* req)
req->complete = 1;
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
req->reply_len = 0;
@@ -403,7 +421,7 @@ maciisi_poll(void)
local_irq_save(flags);
if (via[IFR] & SR_INT) {
- maciisi_interrupt(0, 0, 0);
+ maciisi_interrupt(0, NULL, NULL);
}
else /* avoid calling this function too quickly in a loop */
udelay(ADB_DELAY);
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 564043508569..6eb93e45fcd3 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -55,6 +55,8 @@
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include <asm/pmac_low_i2c.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/cputable.h>
@@ -147,6 +149,7 @@ static struct device_node *vias;
static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0;
static int pmu_has_adb;
+static struct device_node *gpio_node;
static unsigned char __iomem *gpio_reg = NULL;
static int gpio_irq = -1;
static int gpio_irq_enabled = -1;
@@ -157,8 +160,8 @@ static int pmu_version;
static int drop_interrupts;
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
static int option_lid_wakeup = 1;
-static int sleep_in_progress;
#endif /* CONFIG_PM && CONFIG_PPC32 */
+static int sleep_in_progress;
static unsigned long async_req_locks;
static unsigned int pmu_irq_stats[11];
@@ -196,7 +199,6 @@ static int pmu_adb_reset_bus(void);
#endif /* CONFIG_ADB */
static int init_pmu(void);
-static int pmu_queue_request(struct adb_request *req);
static void pmu_start(void);
static irqreturn_t via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
static irqreturn_t gpio1_interrupt(int irq, void *arg, struct pt_regs *regs);
@@ -295,22 +297,26 @@ static struct backlight_controller pmu_backlight_controller = {
};
#endif /* CONFIG_PMAC_BACKLIGHT */
-int
-find_via_pmu(void)
+int __init find_via_pmu(void)
{
+ u64 taddr;
+ u32 *reg;
+
if (via != 0)
return 1;
- vias = find_devices("via-pmu");
- if (vias == 0)
+ vias = of_find_node_by_name(NULL, "via-pmu");
+ if (vias == NULL)
return 0;
- if (vias->next != 0)
- printk(KERN_WARNING "Warning: only using 1st via-pmu\n");
- if (vias->n_addrs < 1 || vias->n_intrs < 1) {
- printk(KERN_ERR "via-pmu: %d addresses, %d interrupts!\n",
- vias->n_addrs, vias->n_intrs);
- if (vias->n_addrs < 1 || vias->n_intrs < 1)
- return 0;
+ reg = (u32 *)get_property(vias, "reg", NULL);
+ if (reg == NULL) {
+ printk(KERN_ERR "via-pmu: No \"reg\" property !\n");
+ goto fail;
+ }
+ taddr = of_translate_address(vias, reg);
+ if (taddr == OF_BAD_ADDR) {
+ printk(KERN_ERR "via-pmu: Can't translate address !\n");
+ goto fail;
}
spin_lock_init(&pmu_lock);
@@ -331,7 +337,8 @@ find_via_pmu(void)
pmu_kind = PMU_HEATHROW_BASED;
else if (device_is_compatible(vias->parent, "Keylargo")
|| device_is_compatible(vias->parent, "K2-Keylargo")) {
- struct device_node *gpio, *gpiop;
+ struct device_node *gpiop;
+ u64 gaddr = OF_BAD_ADDR;
pmu_kind = PMU_KEYLARGO_BASED;
pmu_has_adb = (find_type_devices("adb") != NULL);
@@ -341,19 +348,24 @@ find_via_pmu(void)
PMU_INT_TICK |
PMU_INT_ENVIRONMENT;
- gpiop = find_devices("gpio");
- if (gpiop && gpiop->n_addrs) {
- gpio_reg = ioremap(gpiop->addrs->address, 0x10);
- gpio = find_devices("extint-gpio1");
- if (gpio == NULL)
- gpio = find_devices("pmu-interrupt");
- if (gpio && gpio->parent == gpiop && gpio->n_intrs)
- gpio_irq = gpio->intrs[0].line;
+ gpiop = of_find_node_by_name(NULL, "gpio");
+ if (gpiop) {
+ reg = (u32 *)get_property(gpiop, "reg", NULL);
+ if (reg)
+ gaddr = of_translate_address(gpiop, reg);
+ if (gaddr != OF_BAD_ADDR)
+ gpio_reg = ioremap(gaddr, 0x10);
}
+ if (gpio_reg == NULL)
+ printk(KERN_ERR "via-pmu: Can't find GPIO reg !\n");
} else
pmu_kind = PMU_UNKNOWN;
- via = ioremap(vias->addrs->address, 0x2000);
+ via = ioremap(taddr, 0x2000);
+ if (via == NULL) {
+ printk(KERN_ERR "via-pmu: Can't map address !\n");
+ goto fail;
+ }
out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */
out_8(&via[IFR], 0x7f); /* clear IFR */
@@ -365,23 +377,25 @@ find_via_pmu(void)
return 0;
}
- printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n",
+ printk(KERN_INFO "PMU driver v%d initialized for %s, firmware: %02x\n",
PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version);
sys_ctrler = SYS_CTRLER_PMU;
return 1;
+ fail:
+ of_node_put(vias);
+ vias = NULL;
+ return 0;
}
#ifdef CONFIG_ADB
-static int
-pmu_probe(void)
+static int pmu_probe(void)
{
return vias == NULL? -ENODEV: 0;
}
-static int __init
-pmu_init(void)
+static int __init pmu_init(void)
{
if (vias == NULL)
return -ENODEV;
@@ -405,7 +419,7 @@ static int __init via_pmu_start(void)
bright_req_2.complete = 1;
batt_req.complete = 1;
-#if defined(CONFIG_PPC32) && !defined(CONFIG_PPC_MERGE)
+#ifndef CONFIG_PPC_MERGE
if (pmu_kind == PMU_KEYLARGO_BASED)
openpic_set_irq_priority(vias->intrs[0].line,
OPENPIC_PRIORITY_DEFAULT + 1);
@@ -418,10 +432,22 @@ static int __init via_pmu_start(void)
return -EAGAIN;
}
- if (pmu_kind == PMU_KEYLARGO_BASED && gpio_irq != -1) {
- if (request_irq(gpio_irq, gpio1_interrupt, 0, "GPIO1 ADB", (void *)0))
- printk(KERN_ERR "pmu: can't get irq %d (GPIO1)\n", gpio_irq);
- gpio_irq_enabled = 1;
+ if (pmu_kind == PMU_KEYLARGO_BASED) {
+ gpio_node = of_find_node_by_name(NULL, "extint-gpio1");
+ if (gpio_node == NULL)
+ gpio_node = of_find_node_by_name(NULL,
+ "pmu-interrupt");
+ if (gpio_node && gpio_node->n_intrs > 0)
+ gpio_irq = gpio_node->intrs[0].line;
+
+ if (gpio_irq != -1) {
+ if (request_irq(gpio_irq, gpio1_interrupt, 0,
+ "GPIO1 ADB", (void *)0))
+ printk(KERN_ERR "pmu: can't get irq %d"
+ " (GPIO1)\n", gpio_irq);
+ else
+ gpio_irq_enabled = 1;
+ }
}
/* Enable interrupts */
@@ -454,9 +480,6 @@ static int __init via_pmu_dev_init(void)
if (vias == NULL)
return -ENODEV;
-#ifndef CONFIG_PPC64
- request_OF_resource(vias, 0, NULL);
-#endif
#ifdef CONFIG_PMAC_BACKLIGHT
/* Enable backlight */
register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
@@ -1371,7 +1394,6 @@ next:
}
pmu_done(req);
} else {
-#if defined(CONFIG_XMON) && !defined(CONFIG_PPC64)
if (len == 4 && data[1] == 0x2c) {
extern int xmon_wants_key, xmon_adb_keycode;
if (xmon_wants_key) {
@@ -1379,7 +1401,6 @@ next:
return;
}
}
-#endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */
#ifdef CONFIG_ADB
/*
* XXX On the [23]400 the PMU gives us an up
@@ -1782,258 +1803,6 @@ pmu_present(void)
return via != 0;
}
-struct pmu_i2c_hdr {
- u8 bus;
- u8 mode;
- u8 bus2;
- u8 address;
- u8 sub_addr;
- u8 comb_addr;
- u8 count;
-};
-
-int
-pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_COMBINED;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr | 1;
- hdr->count = len;
-
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_STDSUB;
- hdr->bus2 = 0;
- hdr->sub_addr = subaddr;
- hdr->comb_addr = addr & 0xfe;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_read(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr | 1;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- req.nbytes = sizeof(struct pmu_i2c_hdr) + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) {
- memcpy(data, &req.reply[1], req.reply_len - 1);
- return req.reply_len - 1;
- }
- }
- return -1;
-}
-
-int
-pmu_i2c_simple_write(int bus, int addr, u8* data, int len)
-{
- struct adb_request req;
- struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1];
- int retry;
- int rc;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- hdr->bus = bus;
- hdr->address = addr & 0xfe;
- hdr->mode = PMU_I2C_MODE_SIMPLE;
- hdr->bus2 = 0;
- hdr->sub_addr = 0;
- hdr->comb_addr = 0;
- hdr->count = len;
-
- req.data[0] = PMU_I2C_CMD;
- memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len);
- req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.reply[0] = 0xff;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- break;
- mdelay(15);
- }
- if (req.reply[0] != PMU_I2C_STATUS_OK)
- return -1;
-
- for (retry=0; retry<16; retry++) {
- memset(&req, 0, sizeof(req));
-
- mdelay(15);
-
- hdr->bus = PMU_I2C_BUS_STATUS;
- req.reply[0] = 0xff;
-
- req.nbytes = 2;
- req.reply_expected = 0;
- req.reply_len = 0;
- req.data[0] = PMU_I2C_CMD;
- rc = pmu_queue_request(&req);
- if (rc)
- return rc;
- while(!req.complete)
- pmu_poll();
- if (req.reply[0] == PMU_I2C_STATUS_OK)
- return len;
- }
- return -1;
-}
-
#ifdef CONFIG_PM
static LIST_HEAD(sleep_notifiers);
@@ -2338,8 +2107,9 @@ pmac_suspend_devices(void)
return -EBUSY;
}
- /* Disable clock spreading on some machines */
- pmac_tweak_clock_spreading(0);
+ /* Call platform functions marked "on sleep" */
+ pmac_pfunc_i2c_suspend();
+ pmac_pfunc_base_suspend();
/* Stop preemption */
preempt_disable();
@@ -2411,8 +2181,9 @@ pmac_wakeup_devices(void)
mdelay(10);
preempt_enable();
- /* Re-enable clock spreading on some machines */
- pmac_tweak_clock_spreading(1);
+ /* Call platform functions marked "on wake" */
+ pmac_pfunc_base_resume();
+ pmac_pfunc_i2c_resume();
/* Resume devices */
device_resume();
@@ -3130,16 +2901,13 @@ static int __init init_pmu_sysfs(void)
subsys_initcall(init_pmu_sysfs);
EXPORT_SYMBOL(pmu_request);
+EXPORT_SYMBOL(pmu_queue_request);
EXPORT_SYMBOL(pmu_poll);
EXPORT_SYMBOL(pmu_poll_adb);
EXPORT_SYMBOL(pmu_wait_complete);
EXPORT_SYMBOL(pmu_suspend);
EXPORT_SYMBOL(pmu_resume);
EXPORT_SYMBOL(pmu_unlock);
-EXPORT_SYMBOL(pmu_i2c_combined_read);
-EXPORT_SYMBOL(pmu_i2c_stdsub_write);
-EXPORT_SYMBOL(pmu_i2c_simple_read);
-EXPORT_SYMBOL(pmu_i2c_simple_write);
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
EXPORT_SYMBOL(pmu_enable_irled);
EXPORT_SYMBOL(pmu_battery_count);
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 6f80d76ac17c..f08e52f2107b 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -493,7 +493,7 @@ pmu_queue_request(struct adb_request *req)
return -EINVAL;
}
- req->next = 0;
+ req->next = NULL;
req->sent = 0;
req->complete = 0;
local_irq_save(flags);
@@ -717,7 +717,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs)
printk(KERN_ERR "PMU: extra ADB reply\n");
return;
}
- req_awaiting_reply = 0;
+ req_awaiting_reply = NULL;
if (len <= 2)
req->reply_len = 0;
else {
diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c
index a0a41ad0f2b5..906d3ecae6e6 100644
--- a/drivers/macintosh/windfarm_lm75_sensor.c
+++ b/drivers/macintosh/windfarm_lm75_sensor.c
@@ -21,6 +21,7 @@
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sections.h>
+#include <asm/pmac_low_i2c.h>
#include "windfarm.h"
@@ -47,9 +48,9 @@ static int wf_lm75_attach(struct i2c_adapter *adapter);
static int wf_lm75_detach(struct i2c_client *client);
static struct i2c_driver wf_lm75_driver = {
- .owner = THIS_MODULE,
- .name = "wf_lm75",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "wf_lm75",
+ },
.attach_adapter = wf_lm75_attach,
.detach_client = wf_lm75_detach,
};
@@ -157,53 +158,21 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter,
static int wf_lm75_attach(struct i2c_adapter *adapter)
{
- u8 bus_id;
- struct device_node *smu, *bus, *dev;
-
- /* We currently only deal with LM75's hanging off the SMU
- * i2c busses. If we extend that driver to other/older
- * machines, we should split this function into SMU-i2c,
- * keywest-i2c, PMU-i2c, ...
- */
+ struct device_node *busnode, *dev;
+ struct pmac_i2c_bus *bus;
DBG("wf_lm75: adapter %s detected\n", adapter->name);
- if (strncmp(adapter->name, "smu-i2c-", 8) != 0)
- return 0;
- smu = of_find_node_by_type(NULL, "smu");
- if (smu == NULL)
- return 0;
-
- /* Look for the bus in the device-tree */
- bus_id = (u8)simple_strtoul(adapter->name + 8, NULL, 16);
-
- DBG("wf_lm75: bus ID is %x\n", bus_id);
-
- /* Look for sensors subdir */
- for (bus = NULL;
- (bus = of_get_next_child(smu, bus)) != NULL;) {
- u32 *reg;
-
- if (strcmp(bus->name, "i2c"))
- continue;
- reg = (u32 *)get_property(bus, "reg", NULL);
- if (reg == NULL)
- continue;
- if (bus_id == *reg)
- break;
- }
- of_node_put(smu);
- if (bus == NULL) {
- printk(KERN_WARNING "windfarm: SMU i2c bus 0x%x not found"
- " in device-tree !\n", bus_id);
- return 0;
- }
+ bus = pmac_i2c_adapter_to_bus(adapter);
+ if (bus == NULL)
+ return -ENODEV;
+ busnode = pmac_i2c_get_bus_node(bus);
DBG("wf_lm75: bus found, looking for device...\n");
/* Now look for lm75(s) in there */
for (dev = NULL;
- (dev = of_get_next_child(bus, dev)) != NULL;) {
+ (dev = of_get_next_child(busnode, dev)) != NULL;) {
const char *loc =
get_property(dev, "hwsensor-location", NULL);
u32 *reg = (u32 *)get_property(dev, "reg", NULL);
@@ -217,9 +186,6 @@ static int wf_lm75_attach(struct i2c_adapter *adapter)
else if (device_is_compatible(dev, "ds1775"))
wf_lm75_create(adapter, *reg, 1, loc);
}
-
- of_node_put(bus);
-
return 0;
}
@@ -240,12 +206,7 @@ static int wf_lm75_detach(struct i2c_client *client)
static int __init wf_lm75_sensor_init(void)
{
- int rc;
-
- rc = i2c_add_driver(&wf_lm75_driver);
- if (rc < 0)
- return rc;
- return 0;
+ return i2c_add_driver(&wf_lm75_driver);
}
static void __exit wf_lm75_sensor_exit(void)
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 80ddf9776bde..eb69a601e765 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -26,7 +26,7 @@
* (typically the drive fan)
* - the main control (first control) gets the target value scaled with
* the first pair of factors, and is then modified as below
- * - the value of the target of the CPU Fan control loop is retreived,
+ * - the value of the target of the CPU Fan control loop is retrieved,
* scaled with the second pair of factors, and the max of that and
* the scaled target is applied to the main control.
*
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 2c3158c81ff2..4d811600bdab 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/completion.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c
index b558cc209d49..1a00d9c75a23 100644
--- a/drivers/macintosh/windfarm_smu_sensors.c
+++ b/drivers/macintosh/windfarm_smu_sensors.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/completion.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
diff --git a/drivers/md/.gitignore b/drivers/md/.gitignore
new file mode 100644
index 000000000000..a7afec6b19c6
--- /dev/null
+++ b/drivers/md/.gitignore
@@ -0,0 +1,4 @@
+mktables
+raid6altivec*.c
+raid6int*.c
+raid6tables.c
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 252d55df9642..eae4473eadde 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -200,7 +200,7 @@ out:
/* if page is completely empty, put it back on the free list, or dealloc it */
/* if page was hijacked, unmark the flag so it might get alloced next time */
/* Note: lock should be held when calling this */
-static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
{
char *ptr;
@@ -315,6 +315,8 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
if (bitmap->file == NULL)
return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+ flush_dcache_page(page); /* make sure visible to anyone reading the file */
+
if (wait)
lock_page(page);
else {
@@ -341,7 +343,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
/* add to list to be waited for by daemon */
struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
item->page = page;
- page_cache_get(page);
+ get_page(page);
spin_lock(&bitmap->write_lock);
list_add(&item->list, &bitmap->complete_pages);
spin_unlock(&bitmap->write_lock);
@@ -357,10 +359,10 @@ static struct page *read_page(struct file *file, unsigned long index,
struct inode *inode = file->f_mapping->host;
struct page *page = NULL;
loff_t isize = i_size_read(inode);
- unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+ unsigned long end_index = isize >> PAGE_SHIFT;
- PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
- (unsigned long long)index << PAGE_CACHE_SHIFT);
+ PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT);
page = read_cache_page(inode->i_mapping, index,
(filler_t *)inode->i_mapping->a_ops->readpage, file);
@@ -368,7 +370,7 @@ static struct page *read_page(struct file *file, unsigned long index,
goto out;
wait_on_page_locked(page);
if (!PageUptodate(page) || PageError(page)) {
- page_cache_release(page);
+ put_page(page);
page = ERR_PTR(-EIO);
goto out;
}
@@ -376,14 +378,14 @@ static struct page *read_page(struct file *file, unsigned long index,
if (index > end_index) /* we have read beyond EOF */
*bytes_read = 0;
else if (index == end_index) /* possible short read */
- *bytes_read = isize & ~PAGE_CACHE_MASK;
+ *bytes_read = isize & ~PAGE_MASK;
else
- *bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+ *bytes_read = PAGE_SIZE; /* got a full page */
out:
if (IS_ERR(page))
printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
- (int)PAGE_CACHE_SIZE,
- (unsigned long long)index << PAGE_CACHE_SHIFT,
+ (int)PAGE_SIZE,
+ (unsigned long long)index << PAGE_SHIFT,
PTR_ERR(page));
return page;
}
@@ -406,11 +408,11 @@ int bitmap_update_sb(struct bitmap *bitmap)
return 0;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
sb->events = cpu_to_le64(bitmap->mddev->events);
if (!bitmap->mddev->degraded)
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
- kunmap(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
return write_page(bitmap, bitmap->sb_page, 1);
}
@@ -421,7 +423,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
if (!bitmap || !bitmap->sb_page)
return;
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic));
printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
@@ -440,7 +442,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
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);
+ kunmap_atomic(sb, KM_USER0);
}
/* read the superblock from the bitmap file and initialize some bitmap fields */
@@ -466,7 +468,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
return err;
}
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
if (bytes_read < sizeof(*sb)) { /* short read */
printk(KERN_INFO "%s: bitmap file superblock truncated\n",
@@ -485,12 +487,12 @@ static int bitmap_read_sb(struct bitmap *bitmap)
else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
reason = "unrecognized superblock version";
- else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
- reason = "bitmap chunksize out of range (512B - 4MB)";
+ else if (chunksize < PAGE_SIZE)
+ reason = "bitmap chunksize too small";
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 (1-15s)";
+ else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ)
+ reason = "daemon sleep period out of range";
else if (write_behind > COUNTER_MAX)
reason = "write-behind limit out of range (0 - 16383)";
if (reason) {
@@ -535,7 +537,7 @@ success:
bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
- kunmap(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
if (err)
bitmap_print_sb(bitmap);
return err;
@@ -558,9 +560,9 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
spin_unlock_irqrestore(&bitmap->lock, flags);
return;
}
- page_cache_get(bitmap->sb_page);
+ get_page(bitmap->sb_page);
spin_unlock_irqrestore(&bitmap->lock, flags);
- sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
switch (op) {
case MASK_SET: sb->state |= bits;
break;
@@ -568,8 +570,8 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
break;
default: BUG();
}
- kunmap(bitmap->sb_page);
- page_cache_release(bitmap->sb_page);
+ kunmap_atomic(sb, KM_USER0);
+ put_page(bitmap->sb_page);
}
/*
@@ -622,12 +624,11 @@ static void bitmap_file_unmap(struct bitmap *bitmap)
while (pages--)
if (map[pages]->index != 0) /* 0 is sb_page, release it below */
- page_cache_release(map[pages]);
+ put_page(map[pages]);
kfree(map);
kfree(attr);
- if (sb_page)
- page_cache_release(sb_page);
+ safe_put_page(sb_page);
}
static void bitmap_stop_daemon(struct bitmap *bitmap);
@@ -654,7 +655,7 @@ static void drain_write_queues(struct bitmap *bitmap)
while ((item = dequeue_page(bitmap))) {
/* don't bother to wait */
- page_cache_release(item->page);
+ put_page(item->page);
mempool_free(item, bitmap->write_pool);
}
@@ -763,7 +764,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
/* make sure the page stays cached until it gets written out */
if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
- page_cache_get(page);
+ get_page(page);
/* set the bit */
kaddr = kmap_atomic(page, KM_USER0);
@@ -854,6 +855,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
unsigned long bytes, offset, dummy;
int outofdate;
int ret = -ENOSPC;
+ void *paddr;
chunks = bitmap->chunks;
file = bitmap->file;
@@ -887,12 +889,10 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
if (!bitmap->filemap)
goto out;
- bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+ bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL);
if (!bitmap->filemap_attr)
goto out;
- memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
-
oldindex = ~0L;
for (i = 0; i < chunks; i++) {
@@ -901,8 +901,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
bit = file_page_offset(i);
if (index != oldindex) { /* this is a new page, read it in */
/* unmap the old page, we're done with it */
- if (oldpage != NULL)
- kunmap(oldpage);
if (index == 0) {
/*
* if we're here then the superblock page
@@ -925,30 +923,32 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
oldindex = index;
oldpage = page;
- kmap(page);
if (outofdate) {
/*
* if bitmap is out of date, dirty the
* whole page and write it out
*/
- memset(page_address(page) + offset, 0xff,
+ paddr = kmap_atomic(page, KM_USER0);
+ memset(paddr + offset, 0xff,
PAGE_SIZE - offset);
+ kunmap_atomic(paddr, KM_USER0);
ret = write_page(bitmap, page, 1);
if (ret) {
- kunmap(page);
/* release, page not in filemap yet */
- page_cache_release(page);
+ put_page(page);
goto out;
}
}
bitmap->filemap[bitmap->file_pages++] = page;
}
+ paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
- b = test_bit(bit, page_address(page));
+ b = test_bit(bit, paddr);
else
- b = ext2_test_bit(bit, page_address(page));
+ b = ext2_test_bit(bit, paddr);
+ kunmap_atomic(paddr, KM_USER0);
if (b) {
/* if the disk bit is set, set the memory bit */
bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
@@ -963,9 +963,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
ret = 0;
bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
- if (page) /* unmap the last page */
- kunmap(page);
-
if (bit_cnt) { /* Kick recovery if any bits were set */
set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
md_wakeup_thread(bitmap->mddev->thread);
@@ -1021,6 +1018,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
int err = 0;
int blocks;
int attr;
+ void *paddr;
if (bitmap == NULL)
return 0;
@@ -1043,7 +1041,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
/* skip this page unless it's marked as needing cleaning */
if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
if (attr & BITMAP_PAGE_NEEDWRITE) {
- page_cache_get(page);
+ get_page(page);
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1057,13 +1055,13 @@ int bitmap_daemon_work(struct bitmap *bitmap)
default:
bitmap_file_kick(bitmap);
}
- page_cache_release(page);
+ put_page(page);
}
continue;
}
/* grab the new page, sync and release the old */
- page_cache_get(page);
+ get_page(page);
if (lastpage != NULL) {
if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1077,14 +1075,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
}
- kunmap(lastpage);
- page_cache_release(lastpage);
+ put_page(lastpage);
if (err)
bitmap_file_kick(bitmap);
} else
spin_unlock_irqrestore(&bitmap->lock, flags);
lastpage = page;
- kmap(page);
/*
printk("bitmap clean at page %lu\n", j);
*/
@@ -1107,10 +1103,12 @@ int bitmap_daemon_work(struct bitmap *bitmap)
-1);
/* clear the bit */
+ paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
- clear_bit(file_page_offset(j), page_address(page));
+ clear_bit(file_page_offset(j), paddr);
else
- ext2_clear_bit(file_page_offset(j), page_address(page));
+ ext2_clear_bit(file_page_offset(j), paddr);
+ kunmap_atomic(paddr, KM_USER0);
}
}
spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1118,7 +1116,6 @@ int bitmap_daemon_work(struct bitmap *bitmap)
/* now sync the final page */
if (lastpage != NULL) {
- kunmap(lastpage);
spin_lock_irqsave(&bitmap->lock, flags);
if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
@@ -1133,7 +1130,7 @@ int bitmap_daemon_work(struct bitmap *bitmap)
spin_unlock_irqrestore(&bitmap->lock, flags);
}
- page_cache_release(lastpage);
+ put_page(lastpage);
}
return err;
@@ -1184,7 +1181,7 @@ static void bitmap_writeback_daemon(mddev_t *mddev)
PRINTK("finished page writeback: %p\n", page);
err = PageError(page);
- page_cache_release(page);
+ put_page(page);
if (err) {
printk(KERN_WARNING "%s: bitmap file writeback "
"failed (page %lu): %d\n",
@@ -1530,6 +1527,8 @@ void bitmap_destroy(mddev_t *mddev)
return;
mddev->bitmap = NULL; /* disconnect from the md device */
+ if (mddev->thread)
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
bitmap_free(bitmap);
}
@@ -1555,12 +1554,10 @@ int bitmap_create(mddev_t *mddev)
BUG_ON(file && mddev->bitmap_offset);
- bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+ bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
if (!bitmap)
return -ENOMEM;
- memset(bitmap, 0, sizeof(*bitmap));
-
spin_lock_init(&bitmap->lock);
bitmap->mddev = mddev;
@@ -1601,12 +1598,11 @@ int bitmap_create(mddev_t *mddev)
#ifdef INJECT_FATAL_FAULT_1
bitmap->bp = NULL;
#else
- bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+ bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
#endif
err = -ENOMEM;
if (!bitmap->bp)
goto error;
- memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
bitmap->flags |= BITMAP_ACTIVE;
@@ -1636,6 +1632,8 @@ int bitmap_create(mddev_t *mddev)
if (IS_ERR(bitmap->writeback_daemon))
return PTR_ERR(bitmap->writeback_daemon);
+ mddev->thread->timeout = bitmap->daemon_sleep * HZ;
+
return bitmap_update_sb(bitmap);
error:
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index cf6631056683..e7a650f9ca07 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -228,7 +228,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
};
-static inline int
+static int
crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out,
struct scatterlist *in, unsigned int length,
int write, sector_t sector)
@@ -690,6 +690,8 @@ bad3:
bad2:
crypto_free_tfm(tfm);
bad1:
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
return -EINVAL;
}
@@ -706,6 +708,9 @@ static void crypt_dtr(struct dm_target *ti)
cc->iv_gen_ops->dtr(cc);
crypto_free_tfm(cc->tfm);
dm_put_device(ti, cc->dev);
+
+ /* Must zero key material before freeing */
+ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8));
kfree(cc);
}
diff --git a/drivers/md/dm-io.h b/drivers/md/dm-io.h
index 1a77f3265706..f9035bfd1a9f 100644
--- a/drivers/md/dm-io.h
+++ b/drivers/md/dm-io.h
@@ -9,9 +9,6 @@
#include "dm.h"
-/* FIXME make this configurable */
-#define DM_MAX_IO_REGIONS 8
-
struct io_region {
struct block_device *bdev;
sector_t sector;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 07d44e19536e..1235135b384b 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -270,6 +270,7 @@ static int dm_hash_rename(const char *old, const char *new)
{
char *new_name, *old_name;
struct hash_cell *hc;
+ struct dm_table *table;
/*
* duplicate new.
@@ -317,6 +318,15 @@ static int dm_hash_rename(const char *old, const char *new)
/* rename the device node in devfs */
register_with_devfs(hc);
+ /*
+ * Wake up any dm event waiters.
+ */
+ table = dm_get_table(hc->md);
+ if (table) {
+ dm_table_event(table);
+ dm_table_put(table);
+ }
+
up_write(&_hash_lock);
kfree(old_name);
return 0;
@@ -588,7 +598,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size)
/*
* Always use UUID for lookups if it's present, otherwise use name or dev.
*/
-static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
+static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
{
if (*param->uuid)
return __get_uuid_cell(param->uuid);
@@ -598,7 +608,7 @@ static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param)
return dm_get_mdptr(huge_decode_dev(param->dev));
}
-static inline struct mapped_device *find_device(struct dm_ioctl *param)
+static struct mapped_device *find_device(struct dm_ioctl *param)
{
struct hash_cell *hc;
struct mapped_device *md = NULL;
@@ -683,14 +693,18 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
static int do_suspend(struct dm_ioctl *param)
{
int r = 0;
+ int do_lockfs = 1;
struct mapped_device *md;
md = find_device(param);
if (!md)
return -ENXIO;
+ if (param->flags & DM_SKIP_LOCKFS_FLAG)
+ do_lockfs = 0;
+
if (!dm_suspended(md))
- r = dm_suspend(md);
+ r = dm_suspend(md, do_lockfs);
if (!r)
r = __dev_status(md, param);
@@ -702,6 +716,7 @@ static int do_suspend(struct dm_ioctl *param)
static int do_resume(struct dm_ioctl *param)
{
int r = 0;
+ int do_lockfs = 1;
struct hash_cell *hc;
struct mapped_device *md;
struct dm_table *new_map;
@@ -727,8 +742,10 @@ static int do_resume(struct dm_ioctl *param)
/* Do we need to load a new map ? */
if (new_map) {
/* Suspend if it isn't already suspended */
+ if (param->flags & DM_SKIP_LOCKFS_FLAG)
+ do_lockfs = 0;
if (!dm_suspended(md))
- dm_suspend(md);
+ dm_suspend(md, do_lockfs);
r = dm_swap_table(md, new_map);
if (r) {
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a76349cb10a5..efe4adf78530 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -573,7 +573,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region)
lc->sync_search);
lc->sync_search = *region + 1;
- if (*region == lc->region_count)
+ if (*region >= lc->region_count)
return 0;
} while (log_test_bit(lc->recovering_bits, *region));
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6b0fc1670929..6cfa8d435d55 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -562,6 +562,8 @@ struct mirror_set {
region_t nr_regions;
int in_sync;
+ struct mirror *default_mirror; /* Default mirror */
+
unsigned int nr_mirrors;
struct mirror mirror[0];
};
@@ -611,7 +613,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
unsigned long flags = 0;
/* fill in the source */
- m = ms->mirror + DEFAULT_MIRROR;
+ m = ms->default_mirror;
from.bdev = m->dev->bdev;
from.sector = m->offset + region_to_sector(reg->rh, reg->key);
if (reg->key == (ms->nr_regions - 1)) {
@@ -627,7 +629,7 @@ static int recover(struct mirror_set *ms, struct region *reg)
/* fill in the destinations */
for (i = 0, dest = to; i < ms->nr_mirrors; i++) {
- if (i == DEFAULT_MIRROR)
+ if (&ms->mirror[i] == ms->default_mirror)
continue;
m = ms->mirror + i;
@@ -682,7 +684,7 @@ static void do_recovery(struct mirror_set *ms)
static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector)
{
/* FIXME: add read balancing */
- return ms->mirror + DEFAULT_MIRROR;
+ return ms->default_mirror;
}
/*
@@ -709,7 +711,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
if (rh_in_sync(&ms->rh, region, 0))
m = choose_mirror(ms, bio->bi_sector);
else
- m = ms->mirror + DEFAULT_MIRROR;
+ m = ms->default_mirror;
map_bio(ms, m, bio);
generic_make_request(bio);
@@ -833,7 +835,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
rh_delay(&ms->rh, bio);
while ((bio = bio_list_pop(&nosync))) {
- map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio);
+ map_bio(ms, ms->default_mirror, bio);
generic_make_request(bio);
}
}
@@ -900,6 +902,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
ms->nr_mirrors = nr_mirrors;
ms->nr_regions = dm_sector_div_up(ti->len, region_size);
ms->in_sync = 0;
+ ms->default_mirror = &ms->mirror[DEFAULT_MIRROR];
if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
ti->error = "dm-mirror: Error creating dirty region hash";
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ab54f99b7c3b..87727d84dbba 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -371,6 +371,20 @@ static inline ulong round_up(ulong n, ulong size)
return (n + size) & ~size;
}
+static void read_snapshot_metadata(struct dm_snapshot *s)
+{
+ if (s->have_metadata)
+ return;
+
+ if (s->store.read_metadata(&s->store)) {
+ down_write(&s->lock);
+ s->valid = 0;
+ up_write(&s->lock);
+ }
+
+ s->have_metadata = 1;
+}
+
/*
* Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
*/
@@ -677,7 +691,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
/*
* Dispatches the copy operation to kcopyd.
*/
-static inline void start_copy(struct pending_exception *pe)
+static void start_copy(struct pending_exception *pe)
{
struct dm_snapshot *s = pe->snap;
struct io_region src, dest;
@@ -848,16 +862,7 @@ static void snapshot_resume(struct dm_target *ti)
{
struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
- if (s->have_metadata)
- return;
-
- if (s->store.read_metadata(&s->store)) {
- down_write(&s->lock);
- s->valid = 0;
- up_write(&s->lock);
- }
-
- s->have_metadata = 1;
+ read_snapshot_metadata(s);
}
static int snapshot_status(struct dm_target *ti, status_type_t type,
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a6d3baa46f61..a6f2dc66c3db 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -638,7 +638,7 @@ int dm_split_args(int *argc, char ***argvp, char *input)
static void check_for_valid_limits(struct io_restrictions *rs)
{
if (!rs->max_sectors)
- rs->max_sectors = MAX_SECTORS;
+ rs->max_sectors = SAFE_MAX_SECTORS;
if (!rs->max_phys_segments)
rs->max_phys_segments = MAX_PHYS_SEGMENTS;
if (!rs->max_hw_segments)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 930b9fc27953..8c16359f8b01 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -55,6 +55,7 @@ union map_info *dm_get_mapinfo(struct bio *bio)
*/
#define DMF_BLOCK_IO 0
#define DMF_SUSPENDED 1
+#define DMF_FROZEN 2
struct mapped_device {
struct rw_semaphore io_lock;
@@ -97,7 +98,7 @@ struct mapped_device {
* freeze/thaw support require holding onto a super block
*/
struct super_block *frozen_sb;
- struct block_device *frozen_bdev;
+ struct block_device *suspended_bdev;
};
#define MIN_IOS 256
@@ -292,7 +293,7 @@ struct dm_table *dm_get_table(struct mapped_device *md)
* Decrements the number of outstanding ios that a bio has been
* cloned into, completing the original io if necc.
*/
-static inline void dec_pending(struct dm_io *io, int error)
+static void dec_pending(struct dm_io *io, int error)
{
if (error)
io->error = error;
@@ -767,6 +768,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
md->queue->backing_dev_info.congested_fn = dm_any_congested;
md->queue->backing_dev_info.congested_data = md;
blk_queue_make_request(md->queue, dm_request);
+ blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
md->queue->unplug_fn = dm_unplug_all;
md->queue->issue_flush_fn = dm_flush_all;
@@ -836,9 +838,9 @@ static void __set_size(struct mapped_device *md, sector_t size)
{
set_capacity(md->disk, size);
- down(&md->frozen_bdev->bd_inode->i_sem);
- i_size_write(md->frozen_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
- up(&md->frozen_bdev->bd_inode->i_sem);
+ mutex_lock(&md->suspended_bdev->bd_inode->i_mutex);
+ i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT);
+ mutex_unlock(&md->suspended_bdev->bd_inode->i_mutex);
}
static int __bind(struct mapped_device *md, struct dm_table *t)
@@ -902,10 +904,9 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
return create_aux(minor, 1, result);
}
-void *dm_get_mdptr(dev_t dev)
+static struct mapped_device *dm_find_md(dev_t dev)
{
struct mapped_device *md;
- void *mdptr = NULL;
unsigned minor = MINOR(dev);
if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
@@ -914,12 +915,32 @@ void *dm_get_mdptr(dev_t dev)
down(&_minor_lock);
md = idr_find(&_minor_idr, minor);
-
- if (md && (dm_disk(md)->first_minor == minor))
- mdptr = md->interface_ptr;
+ if (!md || (dm_disk(md)->first_minor != minor))
+ md = NULL;
up(&_minor_lock);
+ return md;
+}
+
+struct mapped_device *dm_get_md(dev_t dev)
+{
+ struct mapped_device *md = dm_find_md(dev);
+
+ if (md)
+ dm_get(md);
+
+ return md;
+}
+
+void *dm_get_mdptr(dev_t dev)
+{
+ struct mapped_device *md;
+ void *mdptr = NULL;
+
+ md = dm_find_md(dev);
+ if (md)
+ mdptr = md->interface_ptr;
return mdptr;
}
@@ -991,43 +1012,33 @@ out:
*/
static int lock_fs(struct mapped_device *md)
{
- int r = -ENOMEM;
-
- md->frozen_bdev = bdget_disk(md->disk, 0);
- if (!md->frozen_bdev) {
- DMWARN("bdget failed in lock_fs");
- goto out;
- }
+ int r;
WARN_ON(md->frozen_sb);
- md->frozen_sb = freeze_bdev(md->frozen_bdev);
+ md->frozen_sb = freeze_bdev(md->suspended_bdev);
if (IS_ERR(md->frozen_sb)) {
r = PTR_ERR(md->frozen_sb);
- goto out_bdput;
+ md->frozen_sb = NULL;
+ return r;
}
+ set_bit(DMF_FROZEN, &md->flags);
+
/* don't bdput right now, we don't want the bdev
- * to go away while it is locked. We'll bdput
- * in unlock_fs
+ * to go away while it is locked.
*/
return 0;
-
-out_bdput:
- bdput(md->frozen_bdev);
- md->frozen_sb = NULL;
- md->frozen_bdev = NULL;
-out:
- return r;
}
static void unlock_fs(struct mapped_device *md)
{
- thaw_bdev(md->frozen_bdev, md->frozen_sb);
- bdput(md->frozen_bdev);
+ if (!test_bit(DMF_FROZEN, &md->flags))
+ return;
+ thaw_bdev(md->suspended_bdev, md->frozen_sb);
md->frozen_sb = NULL;
- md->frozen_bdev = NULL;
+ clear_bit(DMF_FROZEN, &md->flags);
}
/*
@@ -1037,7 +1048,7 @@ static void unlock_fs(struct mapped_device *md)
* dm_bind_table, dm_suspend must be called to flush any in
* flight bios and ensure that any further io gets deferred.
*/
-int dm_suspend(struct mapped_device *md)
+int dm_suspend(struct mapped_device *md, int do_lockfs)
{
struct dm_table *map = NULL;
DECLARE_WAITQUEUE(wait, current);
@@ -1053,10 +1064,19 @@ int dm_suspend(struct mapped_device *md)
/* This does not get reverted if there's an error later. */
dm_table_presuspend_targets(map);
- /* Flush I/O to the device. */
- r = lock_fs(md);
- if (r)
+ md->suspended_bdev = bdget_disk(md->disk, 0);
+ if (!md->suspended_bdev) {
+ DMWARN("bdget failed in dm_suspend");
+ r = -ENOMEM;
goto out;
+ }
+
+ /* Flush I/O to the device. */
+ if (do_lockfs) {
+ r = lock_fs(md);
+ if (r)
+ goto out;
+ }
/*
* First we set the BLOCK_IO flag so no more ios will be mapped.
@@ -1105,6 +1125,11 @@ int dm_suspend(struct mapped_device *md)
r = 0;
out:
+ if (r && md->suspended_bdev) {
+ bdput(md->suspended_bdev);
+ md->suspended_bdev = NULL;
+ }
+
dm_table_put(map);
up(&md->suspend_lock);
return r;
@@ -1135,6 +1160,9 @@ int dm_resume(struct mapped_device *md)
unlock_fs(md);
+ bdput(md->suspended_bdev);
+ md->suspended_bdev = NULL;
+
clear_bit(DMF_SUSPENDED, &md->flags);
dm_table_unplug_all(map);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index e38c3fc1a1db..4eaf075da217 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -28,7 +28,7 @@
* in types.h.
*/
#ifdef CONFIG_LBD
-#define SECTOR_FORMAT "%Lu"
+#define SECTOR_FORMAT "%llu"
#else
#define SECTOR_FORMAT "%lu"
#endif
@@ -58,6 +58,7 @@ int dm_create(struct mapped_device **md);
int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
void dm_set_mdptr(struct mapped_device *md, void *ptr);
void *dm_get_mdptr(dev_t dev);
+struct mapped_device *dm_get_md(dev_t dev);
/*
* Reference counting for md.
@@ -68,7 +69,7 @@ void dm_put(struct mapped_device *md);
/*
* A device can still be used while suspended, but I/O is deferred.
*/
-int dm_suspend(struct mapped_device *md);
+int dm_suspend(struct mapped_device *md, int with_lockfs);
int dm_resume(struct mapped_device *md);
/*
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index 0248f8e7eac0..a7a5ab554338 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -316,9 +316,10 @@ static int stop(mddev_t *mddev)
return 0;
}
-static mdk_personality_t faulty_personality =
+static struct mdk_personality faulty_personality =
{
.name = "faulty",
+ .level = LEVEL_FAULTY,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -329,15 +330,17 @@ static mdk_personality_t faulty_personality =
static int __init raid_init(void)
{
- return register_md_personality(FAULTY, &faulty_personality);
+ return register_md_personality(&faulty_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(FAULTY);
+ unregister_md_personality(&faulty_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-10"); /* faulty */
+MODULE_ALIAS("md-faulty");
+MODULE_ALIAS("md-level--5");
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index eb7036485975..8b3515f394a6 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -8,6 +8,7 @@
* completion notification.
*/
+#include <asm/types.h>
#include <asm/atomic.h>
#include <linux/blkdev.h>
@@ -561,11 +562,13 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from,
* Cancels a kcopyd job, eg. someone might be deactivating a
* mirror.
*/
+#if 0
int kcopyd_cancel(struct kcopyd_job *job, int block)
{
/* FIXME: finish */
return -1;
}
+#endif /* 0 */
/*-----------------------------------------------------------------
* Unit setup
@@ -684,4 +687,3 @@ void kcopyd_client_destroy(struct kcopyd_client *kc)
EXPORT_SYMBOL(kcopyd_client_create);
EXPORT_SYMBOL(kcopyd_client_destroy);
EXPORT_SYMBOL(kcopyd_copy);
-EXPORT_SYMBOL(kcopyd_cancel);
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 946efef3a8f5..777585458c85 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -121,11 +121,10 @@ static int linear_run (mddev_t *mddev)
sector_t curr_offset;
struct list_head *tmp;
- conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
+ conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
GFP_KERNEL);
if (!conf)
goto out;
- memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t));
mddev->private = conf;
cnt = 0;
@@ -352,9 +351,10 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev)
}
-static mdk_personality_t linear_personality=
+static struct mdk_personality linear_personality =
{
.name = "linear",
+ .level = LEVEL_LINEAR,
.owner = THIS_MODULE,
.make_request = linear_make_request,
.run = linear_run,
@@ -364,16 +364,18 @@ static mdk_personality_t linear_personality=
static int __init linear_init (void)
{
- return register_md_personality (LINEAR, &linear_personality);
+ return register_md_personality (&linear_personality);
}
static void linear_exit (void)
{
- unregister_md_personality (LINEAR);
+ unregister_md_personality (&linear_personality);
}
module_init(linear_init);
module_exit(linear_exit);
MODULE_LICENSE("GPL");
-MODULE_ALIAS("md-personality-1"); /* LINEAR */
+MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
+MODULE_ALIAS("md-linear");
+MODULE_ALIAS("md-level--1");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8175a2a222da..7145cd150f7b 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -42,6 +42,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/buffer_head.h> /* for invalidate_bdev */
#include <linux/suspend.h>
+#include <linux/poll.h>
#include <linux/init.h>
@@ -67,7 +68,7 @@
static void autostart_arrays (int part);
#endif
-static mdk_personality_t *pers[MAX_PERSONALITY];
+static LIST_HEAD(pers_list);
static DEFINE_SPINLOCK(pers_lock);
/*
@@ -80,10 +81,22 @@ static DEFINE_SPINLOCK(pers_lock);
* idle IO detection.
*
* you can change it via /proc/sys/dev/raid/speed_limit_min and _max.
+ * or /sys/block/mdX/md/sync_speed_{min,max}
*/
static int sysctl_speed_limit_min = 1000;
static int sysctl_speed_limit_max = 200000;
+static inline int speed_min(mddev_t *mddev)
+{
+ return mddev->sync_speed_min ?
+ mddev->sync_speed_min : sysctl_speed_limit_min;
+}
+
+static inline int speed_max(mddev_t *mddev)
+{
+ return mddev->sync_speed_max ?
+ mddev->sync_speed_max : sysctl_speed_limit_max;
+}
static struct ctl_table_header *raid_table_header;
@@ -134,6 +147,24 @@ static struct block_device_operations md_fops;
static int start_readonly;
/*
+ * We have a system wide 'event count' that is incremented
+ * on any 'interesting' event, and readers of /proc/mdstat
+ * can use 'poll' or 'select' to find out when the event
+ * count increases.
+ *
+ * Events are:
+ * start array, stop array, error, add device, remove device,
+ * start build, activate spare
+ */
+static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters);
+static atomic_t md_event_count;
+static void md_new_event(mddev_t *mddev)
+{
+ atomic_inc(&md_event_count);
+ wake_up(&md_event_waiters);
+}
+
+/*
* Enables to iterate over all existing md arrays
* all_mddevs_lock protects this list.
*/
@@ -209,12 +240,10 @@ static mddev_t * mddev_find(dev_t unit)
}
spin_unlock(&all_mddevs_lock);
- new = (mddev_t *) kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return NULL;
- memset(new, 0, sizeof(*new));
-
new->unit = unit;
if (MAJOR(unit) == MD_MAJOR)
new->md_minor = MINOR(unit);
@@ -262,7 +291,7 @@ static inline void mddev_unlock(mddev_t * mddev)
md_wakeup_thread(mddev->thread);
}
-mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
+static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
{
mdk_rdev_t * rdev;
struct list_head *tmp;
@@ -286,6 +315,18 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
return NULL;
}
+static struct mdk_personality *find_pers(int level, char *clevel)
+{
+ struct mdk_personality *pers;
+ list_for_each_entry(pers, &pers_list, list) {
+ if (level != LEVEL_NONE && pers->level == level)
+ return pers;
+ if (strcmp(pers->name, clevel)==0)
+ return pers;
+ }
+ return NULL;
+}
+
static inline sector_t calc_dev_sboffset(struct block_device *bdev)
{
sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -320,7 +361,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
static void free_disk_sb(mdk_rdev_t * rdev)
{
if (rdev->sb_page) {
- page_cache_release(rdev->sb_page);
+ put_page(rdev->sb_page);
rdev->sb_loaded = 0;
rdev->sb_page = NULL;
rdev->sb_offset = 0;
@@ -461,6 +502,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
bio_put(bio);
return ret;
}
+EXPORT_SYMBOL_GPL(sync_page_io);
static int read_disk_sb(mdk_rdev_t * rdev, int size)
{
@@ -665,6 +707,10 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
}
rdev->size = calc_dev_size(rdev, sb->chunk_size);
+ if (rdev->size < sb->size && sb->level > 1)
+ /* "this cannot possibly happen" ... */
+ ret = -EINVAL;
+
abort:
return ret;
}
@@ -688,6 +734,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->ctime = sb->ctime;
mddev->utime = sb->utime;
mddev->level = sb->level;
+ mddev->clevel[0] = 0;
mddev->layout = sb->layout;
mddev->raid_disks = sb->raid_disks;
mddev->size = sb->size;
@@ -714,9 +761,10 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ && mddev->level != 10) {
/* FIXME use a better test */
- printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
return -EINVAL;
}
mddev->bitmap_offset = mddev->default_bitmap_offset;
@@ -968,6 +1016,7 @@ 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);
+ atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
@@ -1006,6 +1055,9 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
rdev->size = le64_to_cpu(sb->data_size)/2;
if (le32_to_cpu(sb->chunksize))
rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1);
+
+ if (le32_to_cpu(sb->size) > rdev->size*2)
+ return -EINVAL;
return 0;
}
@@ -1023,6 +1075,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
mddev->level = le32_to_cpu(sb->level);
+ mddev->clevel[0] = 0;
mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->size = le64_to_cpu(sb->size)/2;
@@ -1037,8 +1090,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
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");
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6
+ && mddev->level != 10) {
+ printk(KERN_WARNING "md: bitmaps not supported for this level.\n");
return -EINVAL;
}
mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
@@ -1105,6 +1159,8 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
else
sb->resync_offset = cpu_to_le64(0);
+ sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors);
+
if (mddev->bitmap && mddev->bitmap_file == NULL) {
sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
@@ -1182,11 +1238,20 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
mdk_rdev_t *same_pdev;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
struct kobject *ko;
+ char *s;
if (rdev->mddev) {
MD_BUG();
return -EINVAL;
}
+ /* make sure rdev->size exceeds mddev->size */
+ if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
+ if (mddev->pers)
+ /* Cannot change size, so fail */
+ return -ENOSPC;
+ else
+ mddev->size = rdev->size;
+ }
same_pdev = match_dev_unit(mddev, rdev);
if (same_pdev)
printk(KERN_WARNING
@@ -1213,6 +1278,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
bdevname(rdev->bdev,b);
if (kobject_set_name(&rdev->kobj, "dev-%s", b) < 0)
return -ENOMEM;
+ while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL)
+ *s = '!';
list_add(&rdev->same_set, &mddev->disks);
rdev->mddev = mddev;
@@ -1496,6 +1563,26 @@ repeat:
}
+/* words written to sysfs files may, or my not, be \n terminated.
+ * We want to accept with case. For this we use cmd_match.
+ */
+static int cmd_match(const char *cmd, const char *str)
+{
+ /* See if cmd, written into a sysfs file, matches
+ * str. They must either be the same, or cmd can
+ * have a trailing newline
+ */
+ while (*cmd && *str && *cmd == *str) {
+ cmd++;
+ str++;
+ }
+ if (*cmd == '\n')
+ cmd++;
+ if (*str || *cmd)
+ return 0;
+ return 1;
+}
+
struct rdev_sysfs_entry {
struct attribute attr;
ssize_t (*show)(mdk_rdev_t *, char *);
@@ -1538,9 +1625,113 @@ super_show(mdk_rdev_t *rdev, char *page)
}
static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super);
+static ssize_t
+errors_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors));
+}
+
+static ssize_t
+errors_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+ if (*buf && (*e == 0 || *e == '\n')) {
+ atomic_set(&rdev->corrected_errors, n);
+ return len;
+ }
+ return -EINVAL;
+}
+static struct rdev_sysfs_entry rdev_errors =
+__ATTR(errors, 0644, errors_show, errors_store);
+
+static ssize_t
+slot_show(mdk_rdev_t *rdev, char *page)
+{
+ if (rdev->raid_disk < 0)
+ return sprintf(page, "none\n");
+ else
+ return sprintf(page, "%d\n", rdev->raid_disk);
+}
+
+static ssize_t
+slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ int slot = simple_strtoul(buf, &e, 10);
+ if (strncmp(buf, "none", 4)==0)
+ slot = -1;
+ else if (e==buf || (*e && *e!= '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ /* Cannot set slot in active array (yet) */
+ return -EBUSY;
+ if (slot >= rdev->mddev->raid_disks)
+ return -ENOSPC;
+ rdev->raid_disk = slot;
+ /* assume it is working */
+ rdev->flags = 0;
+ set_bit(In_sync, &rdev->flags);
+ return len;
+}
+
+
+static struct rdev_sysfs_entry rdev_slot =
+__ATTR(slot, 0644, slot_show, slot_store);
+
+static ssize_t
+offset_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset);
+}
+
+static ssize_t
+offset_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long offset = simple_strtoull(buf, &e, 10);
+ if (e==buf || (*e && *e != '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ return -EBUSY;
+ rdev->data_offset = offset;
+ return len;
+}
+
+static struct rdev_sysfs_entry rdev_offset =
+__ATTR(offset, 0644, offset_show, offset_store);
+
+static ssize_t
+rdev_size_show(mdk_rdev_t *rdev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
+}
+
+static ssize_t
+rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+ char *e;
+ unsigned long long size = simple_strtoull(buf, &e, 10);
+ if (e==buf || (*e && *e != '\n'))
+ return -EINVAL;
+ if (rdev->mddev->pers)
+ return -EBUSY;
+ rdev->size = size;
+ if (size < rdev->mddev->size || rdev->mddev->size == 0)
+ rdev->mddev->size = size;
+ return len;
+}
+
+static struct rdev_sysfs_entry rdev_size =
+__ATTR(size, 0644, rdev_size_show, rdev_size_store);
+
static struct attribute *rdev_default_attrs[] = {
&rdev_state.attr,
&rdev_super.attr,
+ &rdev_errors.attr,
+ &rdev_slot.attr,
+ &rdev_offset.attr,
+ &rdev_size.attr,
NULL,
};
static ssize_t
@@ -1598,12 +1789,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
mdk_rdev_t *rdev;
sector_t size;
- rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
if (!rdev) {
printk(KERN_ERR "md: could not alloc mem for new device!\n");
return ERR_PTR(-ENOMEM);
}
- memset(rdev, 0, sizeof(*rdev));
if ((err = alloc_disk_sb(rdev)))
goto abort_free;
@@ -1621,6 +1811,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
rdev->data_offset = 0;
atomic_set(&rdev->nr_pending, 0);
atomic_set(&rdev->read_errors, 0);
+ atomic_set(&rdev->corrected_errors, 0);
size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
if (!size) {
@@ -1725,16 +1916,37 @@ static void analyze_sbs(mddev_t * mddev)
static ssize_t
level_show(mddev_t *mddev, char *page)
{
- mdk_personality_t *p = mddev->pers;
- if (p == NULL && mddev->raid_disks == 0)
- return 0;
- if (mddev->level >= 0)
- return sprintf(page, "raid%d\n", mddev->level);
- else
+ struct mdk_personality *p = mddev->pers;
+ if (p)
return sprintf(page, "%s\n", p->name);
+ else if (mddev->clevel[0])
+ return sprintf(page, "%s\n", mddev->clevel);
+ else if (mddev->level != LEVEL_NONE)
+ return sprintf(page, "%d\n", mddev->level);
+ else
+ return 0;
}
-static struct md_sysfs_entry md_level = __ATTR_RO(level);
+static ssize_t
+level_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int rv = len;
+ if (mddev->pers)
+ return -EBUSY;
+ if (len == 0)
+ return 0;
+ if (len >= sizeof(mddev->clevel))
+ return -ENOSPC;
+ strncpy(mddev->clevel, buf, len);
+ if (mddev->clevel[len-1] == '\n')
+ len--;
+ mddev->clevel[len] = 0;
+ mddev->level = LEVEL_NONE;
+ return rv;
+}
+
+static struct md_sysfs_entry md_level =
+__ATTR(level, 0644, level_show, level_store);
static ssize_t
raid_disks_show(mddev_t *mddev, char *page)
@@ -1744,7 +1956,197 @@ raid_disks_show(mddev_t *mddev, char *page)
return sprintf(page, "%d\n", mddev->raid_disks);
}
-static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks);
+static int update_raid_disks(mddev_t *mddev, int raid_disks);
+
+static ssize_t
+raid_disks_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* can only set raid_disks if array is not yet active */
+ char *e;
+ int rv = 0;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+
+ if (!*buf || (*e && *e != '\n'))
+ return -EINVAL;
+
+ if (mddev->pers)
+ rv = update_raid_disks(mddev, n);
+ else
+ mddev->raid_disks = n;
+ return rv ? rv : len;
+}
+static struct md_sysfs_entry md_raid_disks =
+__ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store);
+
+static ssize_t
+chunk_size_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d\n", mddev->chunk_size);
+}
+
+static ssize_t
+chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* can only set chunk_size if array is not yet active */
+ char *e;
+ unsigned long n = simple_strtoul(buf, &e, 10);
+
+ if (mddev->pers)
+ return -EBUSY;
+ if (!*buf || (*e && *e != '\n'))
+ return -EINVAL;
+
+ mddev->chunk_size = n;
+ return len;
+}
+static struct md_sysfs_entry md_chunk_size =
+__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
+
+static ssize_t
+null_show(mddev_t *mddev, char *page)
+{
+ return -EINVAL;
+}
+
+static ssize_t
+new_dev_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* buf must be %d:%d\n? giving major and minor numbers */
+ /* The new device is added to the array.
+ * If the array has a persistent superblock, we read the
+ * superblock to initialise info and check validity.
+ * Otherwise, only checking done is that in bind_rdev_to_array,
+ * which mainly checks size.
+ */
+ char *e;
+ int major = simple_strtoul(buf, &e, 10);
+ int minor;
+ dev_t dev;
+ mdk_rdev_t *rdev;
+ int err;
+
+ if (!*buf || *e != ':' || !e[1] || e[1] == '\n')
+ return -EINVAL;
+ minor = simple_strtoul(e+1, &e, 10);
+ if (*e && *e != '\n')
+ return -EINVAL;
+ dev = MKDEV(major, minor);
+ if (major != MAJOR(dev) ||
+ minor != MINOR(dev))
+ return -EOVERFLOW;
+
+
+ if (mddev->persistent) {
+ rdev = md_import_device(dev, mddev->major_version,
+ mddev->minor_version);
+ if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) {
+ mdk_rdev_t *rdev0 = list_entry(mddev->disks.next,
+ mdk_rdev_t, same_set);
+ err = super_types[mddev->major_version]
+ .load_super(rdev, rdev0, mddev->minor_version);
+ if (err < 0)
+ goto out;
+ }
+ } else
+ rdev = md_import_device(dev, -1, -1);
+
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+ err = bind_rdev_to_array(rdev, mddev);
+ out:
+ if (err)
+ export_rdev(rdev);
+ return err ? err : len;
+}
+
+static struct md_sysfs_entry md_new_device =
+__ATTR(new_dev, 0200, null_show, new_dev_store);
+
+static ssize_t
+size_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
+}
+
+static int update_size(mddev_t *mddev, unsigned long size);
+
+static ssize_t
+size_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ /* If array is inactive, we can reduce the component size, but
+ * not increase it (except from 0).
+ * If array is active, we can try an on-line resize
+ */
+ char *e;
+ int err = 0;
+ unsigned long long size = simple_strtoull(buf, &e, 10);
+ if (!*buf || *buf == '\n' ||
+ (*e && *e != '\n'))
+ return -EINVAL;
+
+ if (mddev->pers) {
+ err = update_size(mddev, size);
+ md_update_sb(mddev);
+ } else {
+ if (mddev->size == 0 ||
+ mddev->size > size)
+ mddev->size = size;
+ else
+ err = -ENOSPC;
+ }
+ return err ? err : len;
+}
+
+static struct md_sysfs_entry md_size =
+__ATTR(component_size, 0644, size_show, size_store);
+
+
+/* Metdata version.
+ * This is either 'none' for arrays with externally managed metadata,
+ * or N.M for internally known formats
+ */
+static ssize_t
+metadata_show(mddev_t *mddev, char *page)
+{
+ if (mddev->persistent)
+ return sprintf(page, "%d.%d\n",
+ mddev->major_version, mddev->minor_version);
+ else
+ return sprintf(page, "none\n");
+}
+
+static ssize_t
+metadata_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int major, minor;
+ char *e;
+ if (!list_empty(&mddev->disks))
+ return -EBUSY;
+
+ if (cmd_match(buf, "none")) {
+ mddev->persistent = 0;
+ mddev->major_version = 0;
+ mddev->minor_version = 90;
+ return len;
+ }
+ major = simple_strtoul(buf, &e, 10);
+ if (e==buf || *e != '.')
+ return -EINVAL;
+ buf = e+1;
+ minor = simple_strtoul(buf, &e, 10);
+ if (e==buf || *e != '\n')
+ return -EINVAL;
+ if (major >= sizeof(super_types)/sizeof(super_types[0]) ||
+ super_types[major].name == NULL)
+ return -ENOENT;
+ mddev->major_version = major;
+ mddev->minor_version = minor;
+ mddev->persistent = 1;
+ return len;
+}
+
+static struct md_sysfs_entry md_metadata =
+__ATTR(metadata_version, 0644, metadata_show, metadata_store);
static ssize_t
action_show(mddev_t *mddev, char *page)
@@ -1771,31 +2173,27 @@ action_store(mddev_t *mddev, const char *page, size_t len)
if (!mddev->pers || !mddev->pers->sync_request)
return -EINVAL;
- if (strcmp(page, "idle")==0 || strcmp(page, "idle\n")==0) {
+ if (cmd_match(page, "idle")) {
if (mddev->sync_thread) {
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
md_unregister_thread(mddev->sync_thread);
mddev->sync_thread = NULL;
mddev->recovery = 0;
}
- return len;
- }
-
- if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
- test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+ } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
return -EBUSY;
- if (strcmp(page, "resync")==0 || strcmp(page, "resync\n")==0 ||
- strcmp(page, "recover")==0 || strcmp(page, "recover\n")==0)
+ else if (cmd_match(page, "resync") || cmd_match(page, "recover"))
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
else {
- if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0)
+ if (cmd_match(page, "check"))
set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
- else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0)
+ else if (cmd_match(page, "repair"))
return -EINVAL;
set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
- set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
}
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
return len;
}
@@ -1814,15 +2212,107 @@ md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store);
static struct md_sysfs_entry
md_mismatches = __ATTR_RO(mismatch_cnt);
+static ssize_t
+sync_min_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d (%s)\n", speed_min(mddev),
+ mddev->sync_speed_min ? "local": "system");
+}
+
+static ssize_t
+sync_min_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int min;
+ char *e;
+ if (strncmp(buf, "system", 6)==0) {
+ mddev->sync_speed_min = 0;
+ return len;
+ }
+ min = simple_strtoul(buf, &e, 10);
+ if (buf == e || (*e && *e != '\n') || min <= 0)
+ return -EINVAL;
+ mddev->sync_speed_min = min;
+ return len;
+}
+
+static struct md_sysfs_entry md_sync_min =
+__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
+
+static ssize_t
+sync_max_show(mddev_t *mddev, char *page)
+{
+ return sprintf(page, "%d (%s)\n", speed_max(mddev),
+ mddev->sync_speed_max ? "local": "system");
+}
+
+static ssize_t
+sync_max_store(mddev_t *mddev, const char *buf, size_t len)
+{
+ int max;
+ char *e;
+ if (strncmp(buf, "system", 6)==0) {
+ mddev->sync_speed_max = 0;
+ return len;
+ }
+ max = simple_strtoul(buf, &e, 10);
+ if (buf == e || (*e && *e != '\n') || max <= 0)
+ return -EINVAL;
+ mddev->sync_speed_max = max;
+ return len;
+}
+
+static struct md_sysfs_entry md_sync_max =
+__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
+
+
+static ssize_t
+sync_speed_show(mddev_t *mddev, char *page)
+{
+ unsigned long resync, dt, db;
+ resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ dt = ((jiffies - mddev->resync_mark) / HZ);
+ if (!dt) dt++;
+ db = resync - (mddev->resync_mark_cnt);
+ return sprintf(page, "%ld\n", db/dt/2); /* K/sec */
+}
+
+static struct md_sysfs_entry
+md_sync_speed = __ATTR_RO(sync_speed);
+
+static ssize_t
+sync_completed_show(mddev_t *mddev, char *page)
+{
+ unsigned long max_blocks, resync;
+
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ max_blocks = mddev->resync_max_sectors;
+ else
+ max_blocks = mddev->size << 1;
+
+ resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+ return sprintf(page, "%lu / %lu\n", resync, max_blocks);
+}
+
+static struct md_sysfs_entry
+md_sync_completed = __ATTR_RO(sync_completed);
+
static struct attribute *md_default_attrs[] = {
&md_level.attr,
&md_raid_disks.attr,
+ &md_chunk_size.attr,
+ &md_size.attr,
+ &md_metadata.attr,
+ &md_new_device.attr,
NULL,
};
static struct attribute *md_redundancy_attrs[] = {
&md_scan_mode.attr,
&md_mismatches.attr,
+ &md_sync_min.attr,
+ &md_sync_max.attr,
+ &md_sync_speed.attr,
+ &md_sync_completed.attr,
NULL,
};
static struct attribute_group md_redundancy_group = {
@@ -1937,14 +2427,16 @@ static void md_safemode_timeout(unsigned long data)
md_wakeup_thread(mddev->thread);
}
+static int start_dirty_degraded;
static int do_md_run(mddev_t * mddev)
{
- int pnum, err;
+ int err;
int chunk_size;
struct list_head *tmp;
mdk_rdev_t *rdev;
struct gendisk *disk;
+ struct mdk_personality *pers;
char b[BDEVNAME_SIZE];
if (list_empty(&mddev->disks))
@@ -1961,20 +2453,8 @@ static int do_md_run(mddev_t * mddev)
analyze_sbs(mddev);
chunk_size = mddev->chunk_size;
- pnum = level_to_pers(mddev->level);
- if ((pnum != MULTIPATH) && (pnum != RAID1)) {
- if (!chunk_size) {
- /*
- * 'default chunksize' in the old md code used to
- * be PAGE_SIZE, baaad.
- * we abort here to be on the safe side. We don't
- * want to continue the bad practice.
- */
- printk(KERN_ERR
- "no chunksize specified, see 'man raidtab'\n");
- return -EINVAL;
- }
+ if (chunk_size) {
if (chunk_size > MAX_CHUNK_SIZE) {
printk(KERN_ERR "too big chunk_size: %d > %d\n",
chunk_size, MAX_CHUNK_SIZE);
@@ -2010,10 +2490,10 @@ static int do_md_run(mddev_t * mddev)
}
#ifdef CONFIG_KMOD
- if (!pers[pnum])
- {
- request_module("md-personality-%d", pnum);
- }
+ if (mddev->level != LEVEL_NONE)
+ request_module("md-level-%d", mddev->level);
+ else if (mddev->clevel[0])
+ request_module("md-%s", mddev->clevel);
#endif
/*
@@ -2035,30 +2515,39 @@ static int do_md_run(mddev_t * mddev)
return -ENOMEM;
spin_lock(&pers_lock);
- if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) {
+ pers = find_pers(mddev->level, mddev->clevel);
+ if (!pers || !try_module_get(pers->owner)) {
spin_unlock(&pers_lock);
- printk(KERN_WARNING "md: personality %d is not loaded!\n",
- pnum);
+ if (mddev->level != LEVEL_NONE)
+ printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
+ mddev->level);
+ else
+ printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
+ mddev->clevel);
return -EINVAL;
}
-
- mddev->pers = pers[pnum];
+ mddev->pers = pers;
spin_unlock(&pers_lock);
+ mddev->level = pers->level;
+ strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
mddev->recovery = 0;
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
mddev->barriers_work = 1;
+ mddev->ok_start_degraded = start_dirty_degraded;
if (start_readonly)
mddev->ro = 2; /* read-only, but switch on first write */
- /* before we start the array running, initialise the bitmap */
- err = bitmap_create(mddev);
- if (err)
- printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
- mdname(mddev), err);
- else
- err = mddev->pers->run(mddev);
+ err = mddev->pers->run(mddev);
+ if (!err && mddev->pers->sync_request) {
+ err = bitmap_create(mddev);
+ if (err) {
+ printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+ mdname(mddev), err);
+ mddev->pers->stop(mddev);
+ }
+ }
if (err) {
printk(KERN_ERR "md: pers->run() failed ...\n");
module_put(mddev->pers->owner);
@@ -2104,6 +2593,7 @@ static int do_md_run(mddev_t * mddev)
mddev->queue->make_request_fn = mddev->pers->make_request;
mddev->changed = 1;
+ md_new_event(mddev);
return 0;
}
@@ -2231,6 +2721,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
printk(KERN_INFO "md: %s switched to read-only mode.\n",
mdname(mddev));
err = 0;
+ md_new_event(mddev);
out:
return err;
}
@@ -2668,12 +3159,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
set_bit(WriteMostly, &rdev->flags);
- err = bind_rdev_to_array(rdev, mddev);
- if (err) {
- export_rdev(rdev);
- return err;
- }
-
if (!mddev->persistent) {
printk(KERN_INFO "md: nonpersistent superblock ...\n");
rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS;
@@ -2681,8 +3166,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
rdev->sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->size = calc_dev_size(rdev, mddev->chunk_size);
- if (!mddev->size || (mddev->size > rdev->size))
- mddev->size = rdev->size;
+ err = bind_rdev_to_array(rdev, mddev);
+ if (err) {
+ export_rdev(rdev);
+ return err;
+ }
}
return 0;
@@ -2705,6 +3193,7 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
kick_rdev_from_array(rdev);
md_update_sb(mddev);
+ md_new_event(mddev);
return 0;
busy:
@@ -2753,15 +3242,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
size = calc_dev_size(rdev, mddev->chunk_size);
rdev->size = size;
- if (size < mddev->size) {
- printk(KERN_WARNING
- "%s: disk size %llu blocks < array size %llu\n",
- mdname(mddev), (unsigned long long)size,
- (unsigned long long)mddev->size);
- err = -ENOSPC;
- goto abort_export;
- }
-
if (test_bit(Faulty, &rdev->flags)) {
printk(KERN_WARNING
"md: can not hot-add faulty %s disk to %s!\n",
@@ -2771,7 +3251,9 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
}
clear_bit(In_sync, &rdev->flags);
rdev->desc_nr = -1;
- bind_rdev_to_array(rdev, mddev);
+ err = bind_rdev_to_array(rdev, mddev);
+ if (err)
+ goto abort_export;
/*
* The rest should better be atomic, we can have disk failures
@@ -2795,7 +3277,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
*/
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
-
+ md_new_event(mddev);
return 0;
abort_unbind_export:
@@ -2913,6 +3395,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
mddev->ctime = get_seconds();
mddev->level = info->level;
+ mddev->clevel[0] = 0;
mddev->size = info->size;
mddev->raid_disks = info->raid_disks;
/* don't set md_minor, it is determined by which /dev/md* was
@@ -2942,6 +3425,81 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
return 0;
}
+static int update_size(mddev_t *mddev, unsigned long size)
+{
+ mdk_rdev_t * rdev;
+ int rv;
+ struct list_head *tmp;
+
+ if (mddev->pers->resize == NULL)
+ return -EINVAL;
+ /* The "size" is the amount of each device that is used.
+ * This can only make sense for arrays with redundancy.
+ * linear and raid0 always use whatever space is available
+ * We can only consider changing the size if no resync
+ * or reconstruction is happening, and if the new size
+ * is acceptable. It must fit before the sb_offset or,
+ * if that is <data_offset, it must fit before the
+ * size of each device.
+ * If size is zero, we find the largest size that fits.
+ */
+ if (mddev->sync_thread)
+ return -EBUSY;
+ ITERATE_RDEV(mddev,rdev,tmp) {
+ sector_t avail;
+ int fit = (size == 0);
+ if (rdev->sb_offset > rdev->data_offset)
+ avail = (rdev->sb_offset*2) - rdev->data_offset;
+ else
+ avail = get_capacity(rdev->bdev->bd_disk)
+ - rdev->data_offset;
+ if (fit && (size == 0 || size > avail/2))
+ size = avail/2;
+ if (avail < ((sector_t)size << 1))
+ return -ENOSPC;
+ }
+ rv = mddev->pers->resize(mddev, (sector_t)size *2);
+ if (!rv) {
+ struct block_device *bdev;
+
+ bdev = bdget_disk(mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ }
+ return rv;
+}
+
+static int update_raid_disks(mddev_t *mddev, int raid_disks)
+{
+ int rv;
+ /* change the number of raid disks */
+ if (mddev->pers->reshape == NULL)
+ return -EINVAL;
+ if (raid_disks <= 0 ||
+ raid_disks >= mddev->max_disks)
+ return -EINVAL;
+ if (mddev->sync_thread)
+ return -EBUSY;
+ rv = mddev->pers->reshape(mddev, raid_disks);
+ if (!rv) {
+ struct block_device *bdev;
+
+ bdev = bdget_disk(mddev->gendisk, 0);
+ if (bdev) {
+ mutex_lock(&bdev->bd_inode->i_mutex);
+ i_size_write(bdev->bd_inode, mddev->array_size << 10);
+ mutex_unlock(&bdev->bd_inode->i_mutex);
+ bdput(bdev);
+ }
+ }
+ return rv;
+}
+
+
/*
* update_array_info is used to change the configuration of an
* on-line array.
@@ -2990,71 +3548,12 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
else
return mddev->pers->reconfig(mddev, info->layout, -1);
}
- if (mddev->size != info->size) {
- mdk_rdev_t * rdev;
- struct list_head *tmp;
- if (mddev->pers->resize == NULL)
- return -EINVAL;
- /* The "size" is the amount of each device that is used.
- * This can only make sense for arrays with redundancy.
- * linear and raid0 always use whatever space is available
- * We can only consider changing the size if no resync
- * or reconstruction is happening, and if the new size
- * is acceptable. It must fit before the sb_offset or,
- * if that is <data_offset, it must fit before the
- * size of each device.
- * If size is zero, we find the largest size that fits.
- */
- if (mddev->sync_thread)
- return -EBUSY;
- ITERATE_RDEV(mddev,rdev,tmp) {
- sector_t avail;
- int fit = (info->size == 0);
- if (rdev->sb_offset > rdev->data_offset)
- avail = (rdev->sb_offset*2) - rdev->data_offset;
- else
- avail = get_capacity(rdev->bdev->bd_disk)
- - rdev->data_offset;
- if (fit && (info->size == 0 || info->size > avail/2))
- info->size = avail/2;
- if (avail < ((sector_t)info->size << 1))
- return -ENOSPC;
- }
- rv = mddev->pers->resize(mddev, (sector_t)info->size *2);
- if (!rv) {
- struct block_device *bdev;
-
- bdev = bdget_disk(mddev->gendisk, 0);
- if (bdev) {
- down(&bdev->bd_inode->i_sem);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
- bdput(bdev);
- }
- }
- }
- if (mddev->raid_disks != info->raid_disks) {
- /* change the number of raid disks */
- if (mddev->pers->reshape == NULL)
- return -EINVAL;
- if (info->raid_disks <= 0 ||
- info->raid_disks >= mddev->max_disks)
- return -EINVAL;
- if (mddev->sync_thread)
- return -EBUSY;
- rv = mddev->pers->reshape(mddev, info->raid_disks);
- if (!rv) {
- struct block_device *bdev;
-
- bdev = bdget_disk(mddev->gendisk, 0);
- if (bdev) {
- down(&bdev->bd_inode->i_sem);
- i_size_write(bdev->bd_inode, mddev->array_size << 10);
- up(&bdev->bd_inode->i_sem);
- bdput(bdev);
- }
- }
- }
+ if (mddev->size != info->size)
+ rv = update_size(mddev, info->size);
+
+ if (mddev->raid_disks != info->raid_disks)
+ rv = update_raid_disks(mddev, info->raid_disks);
+
if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
if (mddev->pers->quiesce == NULL)
return -EINVAL;
@@ -3103,12 +3602,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
return 0;
}
+static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ mddev_t *mddev = bdev->bd_disk->private_data;
+
+ geo->heads = 2;
+ geo->sectors = 4;
+ geo->cylinders = get_capacity(mddev->gendisk) / 8;
+ return 0;
+}
+
static int md_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int err = 0;
void __user *argp = (void __user *)arg;
- struct hd_geometry __user *loc = argp;
mddev_t *mddev = NULL;
if (!capable(CAP_SYS_ADMIN))
@@ -3270,24 +3778,6 @@ static int md_ioctl(struct inode *inode, struct file *file,
* 4 sectors (with a BIG number of cylinders...). This drives
* dosfs just mad... ;-)
*/
- case HDIO_GETGEO:
- if (!loc) {
- err = -EINVAL;
- goto abort_unlock;
- }
- err = put_user (2, (char __user *) &loc->heads);
- if (err)
- goto abort_unlock;
- err = put_user (4, (char __user *) &loc->sectors);
- if (err)
- goto abort_unlock;
- err = put_user(get_capacity(mddev->gendisk)/8,
- (short __user *) &loc->cylinders);
- if (err)
- goto abort_unlock;
- err = put_user (get_start_sect(inode->i_bdev),
- (long __user *) &loc->start);
- goto done_unlock;
}
/*
@@ -3416,6 +3906,7 @@ static struct block_device_operations md_fops =
.open = md_open,
.release = md_release,
.ioctl = md_ioctl,
+ .getgeo = md_getgeo,
.media_changed = md_media_changed,
.revalidate_disk= md_revalidate,
};
@@ -3476,11 +3967,10 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
{
mdk_thread_t *thread;
- thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
- memset(thread, 0, sizeof(mdk_thread_t));
init_waitqueue_head(&thread->wqueue);
thread->run = run;
@@ -3524,6 +4014,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
+ md_new_event(mddev);
}
/* seq_file implementation /proc/mdstat */
@@ -3664,24 +4155,29 @@ static void md_seq_stop(struct seq_file *seq, void *v)
mddev_put(mddev);
}
+struct mdstat_info {
+ int event;
+};
+
static int md_seq_show(struct seq_file *seq, void *v)
{
mddev_t *mddev = v;
sector_t size;
struct list_head *tmp2;
mdk_rdev_t *rdev;
- int i;
+ struct mdstat_info *mi = seq->private;
struct bitmap *bitmap;
if (v == (void*)1) {
+ struct mdk_personality *pers;
seq_printf(seq, "Personalities : ");
spin_lock(&pers_lock);
- for (i = 0; i < MAX_PERSONALITY; i++)
- if (pers[i])
- seq_printf(seq, "[%s] ", pers[i]->name);
+ list_for_each_entry(pers, &pers_list, list)
+ seq_printf(seq, "[%s] ", pers->name);
spin_unlock(&pers_lock);
seq_printf(seq, "\n");
+ mi->event = atomic_read(&md_event_count);
return 0;
}
if (v == (void*)2) {
@@ -3790,47 +4286,68 @@ static struct seq_operations md_seq_ops = {
static int md_seq_open(struct inode *inode, struct file *file)
{
int error;
+ struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL);
+ if (mi == NULL)
+ return -ENOMEM;
error = seq_open(file, &md_seq_ops);
+ if (error)
+ kfree(mi);
+ else {
+ struct seq_file *p = file->private_data;
+ p->private = mi;
+ mi->event = atomic_read(&md_event_count);
+ }
return error;
}
+static int md_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = file->private_data;
+ struct mdstat_info *mi = m->private;
+ m->private = NULL;
+ kfree(mi);
+ return seq_release(inode, file);
+}
+
+static unsigned int mdstat_poll(struct file *filp, poll_table *wait)
+{
+ struct seq_file *m = filp->private_data;
+ struct mdstat_info *mi = m->private;
+ int mask;
+
+ poll_wait(filp, &md_event_waiters, wait);
+
+ /* always allow read */
+ mask = POLLIN | POLLRDNORM;
+
+ if (mi->event != atomic_read(&md_event_count))
+ mask |= POLLERR | POLLPRI;
+ return mask;
+}
+
static struct file_operations md_seq_fops = {
.open = md_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = md_seq_release,
+ .poll = mdstat_poll,
};
-int register_md_personality(int pnum, mdk_personality_t *p)
+int register_md_personality(struct mdk_personality *p)
{
- if (pnum >= MAX_PERSONALITY) {
- printk(KERN_ERR
- "md: tried to install personality %s as nr %d, but max is %lu\n",
- p->name, pnum, MAX_PERSONALITY-1);
- return -EINVAL;
- }
-
spin_lock(&pers_lock);
- if (pers[pnum]) {
- spin_unlock(&pers_lock);
- return -EBUSY;
- }
-
- pers[pnum] = p;
- printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum);
+ list_add_tail(&p->list, &pers_list);
+ printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level);
spin_unlock(&pers_lock);
return 0;
}
-int unregister_md_personality(int pnum)
+int unregister_md_personality(struct mdk_personality *p)
{
- if (pnum >= MAX_PERSONALITY)
- return -EINVAL;
-
- printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name);
+ printk(KERN_INFO "md: %s personality unregistered\n", p->name);
spin_lock(&pers_lock);
- pers[pnum] = NULL;
+ list_del_init(&p->list);
spin_unlock(&pers_lock);
return 0;
}
@@ -4012,10 +4529,10 @@ 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);
+ " %d KB/sec/disc.\n", speed_min(mddev));
printk(KERN_INFO "md: using maximum available idle IO bandwidth "
"(but not more than %d KB/sec) for reconstruction.\n",
- sysctl_speed_limit_max);
+ speed_max(mddev));
is_mddev_idle(mddev); /* this also initializes IO event counters */
/* we don't use the checkpoint if there's a bitmap */
@@ -4056,7 +4573,7 @@ static void md_do_sync(mddev_t *mddev)
skipped = 0;
sectors = mddev->pers->sync_request(mddev, j, &skipped,
- currspeed < sysctl_speed_limit_min);
+ currspeed < speed_min(mddev));
if (sectors == 0) {
set_bit(MD_RECOVERY_ERR, &mddev->recovery);
goto out;
@@ -4069,7 +4586,11 @@ static void md_do_sync(mddev_t *mddev)
j += sectors;
if (j>1) mddev->curr_resync = j;
-
+ if (last_check == 0)
+ /* this is the earliers that rebuilt will be
+ * visible in /proc/mdstat
+ */
+ md_new_event(mddev);
if (last_check + window > io_sectors || j == max_sectors)
continue;
@@ -4117,8 +4638,8 @@ static void md_do_sync(mddev_t *mddev)
currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
/((jiffies-mddev->resync_mark)/HZ +1) +1;
- if (currspeed > sysctl_speed_limit_min) {
- if ((currspeed > sysctl_speed_limit_max) ||
+ if (currspeed > speed_min(mddev)) {
+ if ((currspeed > speed_max(mddev)) ||
!is_mddev_idle(mddev)) {
msleep(500);
goto repeat;
@@ -4255,6 +4776,7 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+ md_new_event(mddev);
goto unlock;
}
/* Clear some bits that don't mean anything, but
@@ -4292,6 +4814,7 @@ void md_check_recovery(mddev_t *mddev)
sprintf(nm, "rd%d", rdev->raid_disk);
sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
spares++;
+ md_new_event(mddev);
} else
break;
}
@@ -4324,9 +4847,9 @@ void md_check_recovery(mddev_t *mddev)
mdname(mddev));
/* leave the spares where they are, it shouldn't hurt */
mddev->recovery = 0;
- } else {
+ } else
md_wakeup_thread(mddev->sync_thread);
- }
+ md_new_event(mddev);
}
unlock:
mddev_unlock(mddev);
@@ -4503,12 +5026,14 @@ static int set_ro(const char *val, struct kernel_param *kp)
int num = simple_strtoul(val, &e, 10);
if (*val && (*e == '\0' || *e == '\n')) {
start_readonly = num;
- return 0;;
+ return 0;
}
return -EINVAL;
}
module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
+module_param(start_dirty_degraded, int, 0644);
+
EXPORT_SYMBOL(register_md_personality);
EXPORT_SYMBOL(unregister_md_personality);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 145cdc5ad008..96f7af4ae400 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -35,15 +35,10 @@
#define NR_RESERVED_BUFS 32
-static mdk_personality_t multipath_personality;
-
-
static void *mp_pool_alloc(gfp_t gfp_flags, void *data)
{
struct multipath_bh *mpb;
- mpb = kmalloc(sizeof(*mpb), gfp_flags);
- if (mpb)
- memset(mpb, 0, sizeof(*mpb));
+ mpb = kzalloc(sizeof(*mpb), gfp_flags);
return mpb;
}
@@ -308,6 +303,7 @@ static void print_multipath_conf (multipath_conf_t *conf)
static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
multipath_conf_t *conf = mddev->private;
+ struct request_queue *q;
int found = 0;
int path;
struct multipath_info *p;
@@ -316,8 +312,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
for (path=0; path<mddev->raid_disks; path++)
if ((p=conf->multipaths+path)->rdev == NULL) {
- blk_queue_stack_limits(mddev->queue,
- rdev->bdev->bd_disk->queue);
+ q = rdev->bdev->bd_disk->queue;
+ blk_queue_stack_limits(mddev->queue, q);
/* as we don't honour merge_bvec_fn, we must never risk
* violating it, so limit ->max_sector to one PAGE, as
@@ -325,7 +321,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
* (Note: it is very unlikely that a device with
* merge_bvec_fn will be involved in multipath.)
*/
- if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
+ if (q->merge_bvec_fn &&
mddev->queue->max_sectors > (PAGE_SIZE>>9))
blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
@@ -444,7 +440,7 @@ static int multipath_run (mddev_t *mddev)
* should be freed in multipath_stop()]
*/
- conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf) {
printk(KERN_ERR
@@ -452,9 +448,8 @@ static int multipath_run (mddev_t *mddev)
mdname(mddev));
goto out;
}
- memset(conf, 0, sizeof(*conf));
- conf->multipaths = kmalloc(sizeof(struct multipath_info)*mddev->raid_disks,
+ conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->multipaths) {
printk(KERN_ERR
@@ -462,7 +457,6 @@ static int multipath_run (mddev_t *mddev)
mdname(mddev));
goto out_free_conf;
}
- memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks);
conf->working_disks = 0;
ITERATE_RDEV(mddev,rdev,tmp) {
@@ -557,9 +551,10 @@ static int multipath_stop (mddev_t *mddev)
return 0;
}
-static mdk_personality_t multipath_personality=
+static struct mdk_personality multipath_personality =
{
.name = "multipath",
+ .level = LEVEL_MULTIPATH,
.owner = THIS_MODULE,
.make_request = multipath_make_request,
.run = multipath_run,
@@ -572,15 +567,17 @@ static mdk_personality_t multipath_personality=
static int __init multipath_init (void)
{
- return register_md_personality (MULTIPATH, &multipath_personality);
+ return register_md_personality (&multipath_personality);
}
static void __exit multipath_exit (void)
{
- unregister_md_personality (MULTIPATH);
+ unregister_md_personality (&multipath_personality);
}
module_init(multipath_init);
module_exit(multipath_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-7"); /* MULTIPATH */
+MODULE_ALIAS("md-multipath");
+MODULE_ALIAS("md-level--4");
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index fece3277c2a5..d03f99cf4b7d 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -113,21 +113,16 @@ static int create_strip_zones (mddev_t *mddev)
}
printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
- conf->strip_zone = kmalloc(sizeof(struct strip_zone)*
+ conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones, GFP_KERNEL);
if (!conf->strip_zone)
return 1;
- conf->devlist = kmalloc(sizeof(mdk_rdev_t*)*
+ conf->devlist = kzalloc(sizeof(mdk_rdev_t*)*
conf->nr_strip_zones*mddev->raid_disks,
GFP_KERNEL);
if (!conf->devlist)
return 1;
- memset(conf->strip_zone, 0,sizeof(struct strip_zone)*
- conf->nr_strip_zones);
- memset(conf->devlist, 0,
- sizeof(mdk_rdev_t*) * conf->nr_strip_zones * mddev->raid_disks);
-
/* The first zone must contain all devices, so here we check that
* there is a proper alignment of slots to devices and find them all
*/
@@ -280,7 +275,11 @@ static int raid0_run (mddev_t *mddev)
mdk_rdev_t *rdev;
struct list_head *tmp;
- printk("%s: setting max_sectors to %d, segment boundary to %d\n",
+ if (mddev->chunk_size == 0) {
+ printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
+ return -EINVAL;
+ }
+ printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n",
mdname(mddev),
mddev->chunk_size >> 9,
(mddev->chunk_size>>1)-1);
@@ -307,9 +306,6 @@ static int raid0_run (mddev_t *mddev)
printk("raid0 : conf->hash_spacing is %llu blocks.\n",
(unsigned long long)conf->hash_spacing);
{
-#if __GNUC__ < 3
- volatile
-#endif
sector_t s = mddev->array_size;
sector_t space = conf->hash_spacing;
int round;
@@ -361,7 +357,7 @@ static int raid0_run (mddev_t *mddev)
* chunksize should be used in that case.
*/
{
- int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+ int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
mddev->queue->backing_dev_info.ra_pages = 2* stripe;
}
@@ -440,9 +436,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
{
-#if __GNUC__ < 3
- volatile
-#endif
sector_t x = block >> conf->preshift;
sector_div(x, (u32)conf->hash_spacing);
zone = conf->hash_table[x];
@@ -512,9 +505,10 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
return;
}
-static mdk_personality_t raid0_personality=
+static struct mdk_personality raid0_personality=
{
.name = "raid0",
+ .level = 0,
.owner = THIS_MODULE,
.make_request = raid0_make_request,
.run = raid0_run,
@@ -524,15 +518,17 @@ static mdk_personality_t raid0_personality=
static int __init raid0_init (void)
{
- return register_md_personality (RAID0, &raid0_personality);
+ return register_md_personality (&raid0_personality);
}
static void raid0_exit (void)
{
- unregister_md_personality (RAID0);
+ unregister_md_personality (&raid0_personality);
}
module_init(raid0_init);
module_exit(raid0_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-2"); /* RAID0 */
+MODULE_ALIAS("md-raid0");
+MODULE_ALIAS("md-level-0");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 229d7b204297..d39f584cd8b3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -47,10 +47,11 @@
*/
#define NR_RAID1_BIOS 256
-static mdk_personality_t raid1_personality;
static void unplug_slaves(mddev_t *mddev);
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
{
@@ -59,10 +60,8 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
int size = offsetof(r1bio_t, bios[pi->raid_disks]);
/* allocate a r1bio with room for raid_disks entries in the bios array */
- r1_bio = kmalloc(size, gfp_flags);
- if (r1_bio)
- memset(r1_bio, 0, size);
- else
+ r1_bio = kzalloc(size, gfp_flags);
+ if (!r1_bio)
unplug_slaves(pi->mddev);
return r1_bio;
@@ -104,15 +103,30 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
}
/*
* Allocate RESYNC_PAGES data pages and attach them to
- * the first bio;
+ * the first bio.
+ * If this is a user-requested check/repair, allocate
+ * RESYNC_PAGES for each bio.
*/
- bio = r1_bio->bios[0];
- for (i = 0; i < RESYNC_PAGES; i++) {
- page = alloc_page(gfp_flags);
- if (unlikely(!page))
- goto out_free_pages;
-
- bio->bi_io_vec[i].bv_page = page;
+ if (test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery))
+ j = pi->raid_disks;
+ else
+ j = 1;
+ while(j--) {
+ bio = r1_bio->bios[j];
+ for (i = 0; i < RESYNC_PAGES; i++) {
+ page = alloc_page(gfp_flags);
+ if (unlikely(!page))
+ goto out_free_pages;
+
+ bio->bi_io_vec[i].bv_page = page;
+ }
+ }
+ /* If not user-requests, copy the page pointers to all bios */
+ if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) {
+ for (i=0; i<RESYNC_PAGES ; i++)
+ for (j=1; j<pi->raid_disks; j++)
+ r1_bio->bios[j]->bi_io_vec[i].bv_page =
+ r1_bio->bios[0]->bi_io_vec[i].bv_page;
}
r1_bio->master_bio = NULL;
@@ -120,8 +134,10 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
return r1_bio;
out_free_pages:
- for ( ; i > 0 ; i--)
- __free_page(bio->bi_io_vec[i-1].bv_page);
+ for (i=0; i < RESYNC_PAGES ; i++)
+ for (j=0 ; j < pi->raid_disks; j++)
+ safe_put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
+ j = -1;
out_free_bio:
while ( ++j < pi->raid_disks )
bio_put(r1_bio->bios[j]);
@@ -132,14 +148,16 @@ out_free_bio:
static void r1buf_pool_free(void *__r1_bio, void *data)
{
struct pool_info *pi = data;
- int i;
+ int i,j;
r1bio_t *r1bio = __r1_bio;
- struct bio *bio = r1bio->bios[0];
- for (i = 0; i < RESYNC_PAGES; i++) {
- __free_page(bio->bi_io_vec[i].bv_page);
- bio->bi_io_vec[i].bv_page = NULL;
- }
+ for (i = 0; i < RESYNC_PAGES; i++)
+ for (j = pi->raid_disks; j-- ;) {
+ if (j == 0 ||
+ r1bio->bios[j]->bi_io_vec[i].bv_page !=
+ r1bio->bios[0]->bi_io_vec[i].bv_page)
+ safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page);
+ }
for (i=0 ; i < pi->raid_disks; i++)
bio_put(r1bio->bios[i]);
@@ -152,52 +170,40 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
for (i = 0; i < conf->raid_disks; i++) {
struct bio **bio = r1_bio->bios + i;
- if (*bio)
+ if (*bio && *bio != IO_BLOCKED)
bio_put(*bio);
*bio = NULL;
}
}
-static inline void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(r1bio_t *r1_bio)
{
- unsigned long flags;
-
conf_t *conf = mddev_to_conf(r1_bio->mddev);
/*
* Wake up any possible resync thread that waits for the device
* to go idle.
*/
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ allow_barrier(conf);
put_all_bios(conf, r1_bio);
mempool_free(r1_bio, conf->r1bio_pool);
}
-static inline void put_buf(r1bio_t *r1_bio)
+static void put_buf(r1bio_t *r1_bio)
{
conf_t *conf = mddev_to_conf(r1_bio->mddev);
- unsigned long flags;
+ int i;
- mempool_free(r1_bio, conf->r1buf_pool);
+ for (i=0; i<conf->raid_disks; i++) {
+ struct bio *bio = r1_bio->bios[i];
+ if (bio->bi_end_io)
+ rdev_dec_pending(conf->mirrors[i].rdev, r1_bio->mddev);
+ }
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!conf->barrier)
- BUG();
- --conf->barrier;
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
+ mempool_free(r1_bio, conf->r1buf_pool);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ lower_barrier(conf);
}
static void reschedule_retry(r1bio_t *r1_bio)
@@ -208,8 +214,10 @@ static void reschedule_retry(r1bio_t *r1_bio)
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r1_bio->retry_list, &conf->retry_list);
+ conf->nr_queued ++;
spin_unlock_irqrestore(&conf->device_lock, flags);
+ wake_up(&conf->wait_barrier);
md_wakeup_thread(mddev->thread);
}
@@ -261,9 +269,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
- md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
- else
+ update_head_pos(mirror, r1_bio);
+
+ if (uptodate || conf->working_disks <= 1) {
/*
* Set R1BIO_Uptodate in our master bio, so that
* we will return a good error code for to the higher
@@ -273,16 +281,11 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
* user-side. So if something waits for IO, then it will
* wait for the 'master' bio.
*/
- set_bit(R1BIO_Uptodate, &r1_bio->state);
-
- update_head_pos(mirror, r1_bio);
+ if (uptodate)
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
- /*
- * we have only one bio on the read side
- */
- if (uptodate)
raid_end_bio_io(r1_bio);
- else {
+ } else {
/*
* oops, read error:
*/
@@ -378,7 +381,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
/* free extra copy of the data pages */
int i = bio->bi_vcnt;
while (i--)
- __free_page(bio->bi_io_vec[i].bv_page);
+ safe_put_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,
@@ -433,11 +436,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
new_disk = 0;
for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+ r1_bio->bios[new_disk] == IO_BLOCKED ||
!rdev || !test_bit(In_sync, &rdev->flags)
|| test_bit(WriteMostly, &rdev->flags);
rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) {
- if (rdev && test_bit(In_sync, &rdev->flags))
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ r1_bio->bios[new_disk] != IO_BLOCKED)
wonly_disk = new_disk;
if (new_disk == conf->raid_disks - 1) {
@@ -451,11 +456,13 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* make sure the disk is operational */
for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
+ r1_bio->bios[new_disk] == IO_BLOCKED ||
!rdev || !test_bit(In_sync, &rdev->flags) ||
test_bit(WriteMostly, &rdev->flags);
rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) {
- if (rdev && test_bit(In_sync, &rdev->flags))
+ if (rdev && test_bit(In_sync, &rdev->flags) &&
+ r1_bio->bios[new_disk] != IO_BLOCKED)
wonly_disk = new_disk;
if (new_disk <= 0)
@@ -492,7 +499,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
rdev = rcu_dereference(conf->mirrors[disk].rdev);
- if (!rdev ||
+ if (!rdev || r1_bio->bios[disk] == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags) ||
test_bit(WriteMostly, &rdev->flags))
continue;
@@ -520,7 +527,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
/* cannot risk returning a device that failed
* before we inc'ed nr_pending
*/
- atomic_dec(&rdev->nr_pending);
+ rdev_dec_pending(rdev, conf->mddev);
goto retry;
}
conf->next_seq_sect = this_sector + sectors;
@@ -593,42 +600,119 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
return ret;
}
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down. This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'. When that returns there
+ * is no backgroup IO happening, It must arrange to call
+ * allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier. Once that returns
+ * there is no normal IO happeing. It must arrange to call
+ * lower_barrier when the particular background IO completes.
*/
#define RESYNC_DEPTH 32
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf)
{
spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
-
- if (!conf->barrier++) {
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- if (conf->nr_pending)
- BUG();
+
+ /* Wait until no block IO is waiting */
+ wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+
+ /* block any new IO from starting */
+ conf->barrier++;
+
+ /* No wait for all pending IO to complete */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->barrier--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
+{
+ spin_lock_irq(&conf->resync_lock);
+ if (conf->barrier) {
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+ conf->nr_waiting--;
}
- wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- conf->next_resync = sect;
+ conf->nr_pending++;
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->nr_pending--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+ /* stop syncio and normal IO and wait for everything to
+ * go quite.
+ * We increment barrier and nr_waiting, and then
+ * wait until barrier+nr_pending match nr_queued+2
+ */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier,
+ conf->barrier+conf->nr_pending == conf->nr_queued+2,
+ conf->resync_lock,
+ raid1_unplug(conf->mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+}
+static void unfreeze_array(conf_t *conf)
+{
+ /* reverse the effect of the freeze */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ conf->nr_waiting--;
+ wake_up(&conf->wait_barrier);
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 *),
+ struct page **pages = kzalloc(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]))
@@ -644,7 +728,7 @@ static struct page **alloc_behind_pages(struct bio *bio)
do_sync_io:
if (pages)
for (i = 0; i < bio->bi_vcnt && pages[i]; i++)
- __free_page(pages[i]);
+ put_page(pages[i]);
kfree(pages);
PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size);
return NULL;
@@ -678,10 +762,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
*/
md_write_start(mddev, bio); /* wait on superblock update early */
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -749,7 +830,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
!test_bit(Faulty, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
if (test_bit(Faulty, &rdev->flags)) {
- atomic_dec(&rdev->nr_pending);
+ rdev_dec_pending(rdev, mddev);
r1_bio->bios[i] = NULL;
} else
r1_bio->bios[i] = bio;
@@ -909,13 +990,8 @@ static void print_conf(conf_t *conf)
static void close_sync(conf_t *conf)
{
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier,
- conf->resync_lock, raid1_unplug(conf->mddev->queue));
- spin_unlock_irq(&conf->resync_lock);
-
- if (conf->barrier) BUG();
- if (waitqueue_active(&conf->wait_idle)) BUG();
+ wait_barrier(conf);
+ allow_barrier(conf);
mempool_destroy(conf->r1buf_pool);
conf->r1buf_pool = NULL;
@@ -1015,28 +1091,27 @@ abort:
static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
{
- int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
- conf_t *conf = mddev_to_conf(r1_bio->mddev);
+ int i;
if (bio->bi_size)
return 1;
- if (r1_bio->bios[r1_bio->read_disk] != bio)
- BUG();
- update_head_pos(r1_bio->read_disk, r1_bio);
+ for (i=r1_bio->mddev->raid_disks; i--; )
+ if (r1_bio->bios[i] == bio)
+ break;
+ BUG_ON(i < 0);
+ update_head_pos(i, r1_bio);
/*
* we have read a block, now it needs to be re-written,
* or re-read if the read failed.
* We don't do much here, just schedule handling by raid1d
*/
- if (!uptodate) {
- md_error(r1_bio->mddev,
- conf->mirrors[r1_bio->read_disk].rdev);
- } else
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
set_bit(R1BIO_Uptodate, &r1_bio->state);
- rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
- reschedule_retry(r1_bio);
+
+ if (atomic_dec_and_test(&r1_bio->remaining))
+ reschedule_retry(r1_bio);
return 0;
}
@@ -1066,7 +1141,6 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
md_done_sync(mddev, r1_bio->sectors, uptodate);
put_buf(r1_bio);
}
- rdev_dec_pending(conf->mirrors[mirror].rdev, mddev);
return 0;
}
@@ -1079,34 +1153,173 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
bio = r1_bio->bios[r1_bio->read_disk];
-/*
- if (r1_bio->sector == 0) printk("First sync write startss\n");
-*/
- /*
- * schedule writes
- */
+
+ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ /* We have read all readable devices. If we haven't
+ * got the block, then there is no hope left.
+ * If we have, then we want to do a comparison
+ * and skip the write if everything is the same.
+ * If any blocks failed to read, then we need to
+ * attempt an over-write
+ */
+ int primary;
+ if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
+ for (i=0; i<mddev->raid_disks; i++)
+ if (r1_bio->bios[i]->bi_end_io == end_sync_read)
+ md_error(mddev, conf->mirrors[i].rdev);
+
+ md_done_sync(mddev, r1_bio->sectors, 1);
+ put_buf(r1_bio);
+ return;
+ }
+ for (primary=0; primary<mddev->raid_disks; primary++)
+ if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
+ test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
+ r1_bio->bios[primary]->bi_end_io = NULL;
+ rdev_dec_pending(conf->mirrors[primary].rdev, mddev);
+ break;
+ }
+ r1_bio->read_disk = primary;
+ for (i=0; i<mddev->raid_disks; i++)
+ if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
+ test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+ int j;
+ int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
+ struct bio *pbio = r1_bio->bios[primary];
+ struct bio *sbio = r1_bio->bios[i];
+ for (j = vcnt; j-- ; )
+ if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
+ page_address(sbio->bi_io_vec[j].bv_page),
+ PAGE_SIZE))
+ break;
+ if (j >= 0)
+ mddev->resync_mismatches += r1_bio->sectors;
+ if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
+ sbio->bi_end_io = NULL;
+ rdev_dec_pending(conf->mirrors[i].rdev, mddev);
+ } else {
+ /* fixup the bio for reuse */
+ sbio->bi_vcnt = vcnt;
+ sbio->bi_size = r1_bio->sectors << 9;
+ sbio->bi_idx = 0;
+ sbio->bi_phys_segments = 0;
+ sbio->bi_hw_segments = 0;
+ sbio->bi_hw_front_size = 0;
+ sbio->bi_hw_back_size = 0;
+ sbio->bi_flags &= ~(BIO_POOL_MASK - 1);
+ sbio->bi_flags |= 1 << BIO_UPTODATE;
+ sbio->bi_next = NULL;
+ sbio->bi_sector = r1_bio->sector +
+ conf->mirrors[i].rdev->data_offset;
+ sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ }
+ }
+ }
if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
- /*
- * There is no point trying a read-for-reconstruct as
- * reconstruct is about to be aborted
+ /* ouch - failed to read all of that.
+ * Try some synchronous reads of other devices to get
+ * good data, much like with normal read errors. Only
+ * read into the pages we already have so they we don't
+ * need to re-issue the read request.
+ * We don't need to freeze the array, because being in an
+ * active sync request, there is no normal IO, and
+ * no overlapping syncs.
*/
- char b[BDEVNAME_SIZE];
- printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
- " for block %llu\n",
- bdevname(bio->bi_bdev,b),
- (unsigned long long)r1_bio->sector);
- md_done_sync(mddev, r1_bio->sectors, 0);
- put_buf(r1_bio);
- return;
+ sector_t sect = r1_bio->sector;
+ int sectors = r1_bio->sectors;
+ int idx = 0;
+
+ while(sectors) {
+ int s = sectors;
+ int d = r1_bio->read_disk;
+ int success = 0;
+ mdk_rdev_t *rdev;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+ do {
+ if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+ rdev = conf->mirrors[d].rdev;
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ READ)) {
+ success = 1;
+ break;
+ }
+ }
+ d++;
+ if (d == conf->raid_disks)
+ d = 0;
+ } while (!success && d != r1_bio->read_disk);
+
+ if (success) {
+ int start = d;
+ /* write it back and re-read */
+ set_bit(R1BIO_Uptodate, &r1_bio->state);
+ while (d != r1_bio->read_disk) {
+ if (d == 0)
+ d = conf->raid_disks;
+ d--;
+ if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+ continue;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ WRITE) == 0)
+ md_error(mddev, rdev);
+ }
+ d = start;
+ while (d != r1_bio->read_disk) {
+ if (d == 0)
+ d = conf->raid_disks;
+ d--;
+ if (r1_bio->bios[d]->bi_end_io != end_sync_read)
+ continue;
+ rdev = conf->mirrors[d].rdev;
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ bio->bi_io_vec[idx].bv_page,
+ READ) == 0)
+ md_error(mddev, rdev);
+ }
+ } else {
+ char b[BDEVNAME_SIZE];
+ /* Cannot read from anywhere, array is toast */
+ md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+ printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
+ " for block %llu\n",
+ bdevname(bio->bi_bdev,b),
+ (unsigned long long)r1_bio->sector);
+ md_done_sync(mddev, r1_bio->sectors, 0);
+ put_buf(r1_bio);
+ return;
+ }
+ sectors -= s;
+ sect += s;
+ idx ++;
+ }
}
+ /*
+ * schedule writes
+ */
atomic_set(&r1_bio->remaining, 1);
for (i = 0; i < disks ; i++) {
wbio = r1_bio->bios[i];
- if (wbio->bi_end_io != end_sync_write)
+ if (wbio->bi_end_io == NULL ||
+ (wbio->bi_end_io == end_sync_read &&
+ (i == r1_bio->read_disk ||
+ !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
continue;
- atomic_inc(&conf->mirrors[i].rdev->nr_pending);
+ wbio->bi_rw = WRITE;
+ wbio->bi_end_io = end_sync_write;
atomic_inc(&r1_bio->remaining);
md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
@@ -1167,6 +1380,7 @@ static void raid1d(mddev_t *mddev)
break;
r1_bio = list_entry(head->prev, r1bio_t, retry_list);
list_del(head->prev);
+ conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r1_bio->mddev;
@@ -1206,6 +1420,86 @@ static void raid1d(mddev_t *mddev)
}
} else {
int disk;
+
+ /* we got a read error. Maybe the drive is bad. Maybe just
+ * the block and we can fix it.
+ * We freeze all other IO, and try reading the block from
+ * other devices. When we find one, we re-write
+ * and check it that fixes the read error.
+ * This is all done synchronously while the array is
+ * frozen
+ */
+ sector_t sect = r1_bio->sector;
+ int sectors = r1_bio->sectors;
+ freeze_array(conf);
+ if (mddev->ro == 0) while(sectors) {
+ int s = sectors;
+ int d = r1_bio->read_disk;
+ int success = 0;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+
+ do {
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags) &&
+ sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ))
+ success = 1;
+ else {
+ d++;
+ if (d == conf->raid_disks)
+ d = 0;
+ }
+ } while (!success && d != r1_bio->read_disk);
+
+ if (success) {
+ /* write it back and re-read */
+ int start = d;
+ while (d != r1_bio->read_disk) {
+ if (d==0)
+ d = conf->raid_disks;
+ d--;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, WRITE) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ d = start;
+ while (d != r1_bio->read_disk) {
+ if (d==0)
+ d = conf->raid_disks;
+ d--;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, READ) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ } else {
+ /* Cannot read from anywhere -- bye bye array */
+ md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+ break;
+ }
+ sectors -= s;
+ sect += s;
+ }
+
+ unfreeze_array(conf);
+
bio = r1_bio->bios[r1_bio->read_disk];
if ((disk=read_balance(conf, r1_bio)) == -1) {
printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
@@ -1214,7 +1508,8 @@ static void raid1d(mddev_t *mddev)
(unsigned long long)r1_bio->sector);
raid_end_bio_io(r1_bio);
} else {
- r1_bio->bios[r1_bio->read_disk] = NULL;
+ r1_bio->bios[r1_bio->read_disk] =
+ mddev->ro ? IO_BLOCKED : NULL;
r1_bio->read_disk = disk;
bio_put(bio);
bio = bio_clone(r1_bio->master_bio, GFP_NOIO);
@@ -1269,14 +1564,13 @@ static int init_resync(conf_t *conf)
static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
conf_t *conf = mddev_to_conf(mddev);
- mirror_info_t *mirror;
r1bio_t *r1_bio;
struct bio *bio;
sector_t max_sector, nr_sectors;
- int disk;
+ int disk = -1;
int i;
- int wonly;
- int write_targets = 0;
+ int wonly = -1;
+ int write_targets = 0, read_targets = 0;
int sync_blocks;
int still_degraded = 0;
@@ -1317,55 +1611,35 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return sync_blocks;
}
/*
- * If there is non-resync activity waiting for us then
- * put in a delay to throttle resync.
+ * If there is non-resync activity waiting for a turn,
+ * and resync is going fast enough,
+ * then let it though before starting on this new sync request.
*/
- if (!go_faster && waitqueue_active(&conf->wait_resume))
+ if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- device_barrier(conf, sector_nr + RESYNC_SECTORS);
-
- /*
- * If reconstructing, and >1 working disc,
- * could dedicate one to rebuild and others to
- * service read requests ..
- */
- disk = conf->last_used;
- /* make sure disk is operational */
- wonly = disk;
- while (conf->mirrors[disk].rdev == NULL ||
- !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) ||
- test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags)
- ) {
- if (conf->mirrors[disk].rdev &&
- test_bit(In_sync, &conf->mirrors[disk].rdev->flags))
- wonly = disk;
- if (disk <= 0)
- disk = conf->raid_disks;
- disk--;
- if (disk == conf->last_used) {
- disk = wonly;
- break;
- }
- }
- conf->last_used = disk;
- atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+ raise_barrier(conf);
- mirror = conf->mirrors + disk;
+ conf->next_resync = sector_nr;
r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
-
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ rcu_read_lock();
+ /*
+ * If we get a correctably read error during resync or recovery,
+ * we might want to read from a different device. So we
+ * flag all drives that could conceivably be read from for READ,
+ * and any others (which will be non-In_sync devices) for WRITE.
+ * If a read fails, we try reading from something else for which READ
+ * is OK.
+ */
r1_bio->mddev = mddev;
r1_bio->sector = sector_nr;
r1_bio->state = 0;
set_bit(R1BIO_IsSync, &r1_bio->state);
- r1_bio->read_disk = disk;
for (i=0; i < conf->raid_disks; i++) {
+ mdk_rdev_t *rdev;
bio = r1_bio->bios[i];
/* take from bio_init */
@@ -1380,35 +1654,49 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
bio->bi_end_io = NULL;
bio->bi_private = NULL;
- if (i == disk) {
- bio->bi_rw = READ;
- bio->bi_end_io = end_sync_read;
- } else if (conf->mirrors[i].rdev == NULL ||
- test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+ rdev = rcu_dereference(conf->mirrors[i].rdev);
+ if (rdev == NULL ||
+ test_bit(Faulty, &rdev->flags)) {
still_degraded = 1;
continue;
- } else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) ||
- sector_nr + RESYNC_SECTORS > mddev->recovery_cp ||
- test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ } else if (!test_bit(In_sync, &rdev->flags)) {
bio->bi_rw = WRITE;
bio->bi_end_io = end_sync_write;
write_targets ++;
- } else
- /* no need to read or write here */
- continue;
- bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
- bio->bi_bdev = conf->mirrors[i].rdev->bdev;
+ } else {
+ /* may need to read from here */
+ bio->bi_rw = READ;
+ bio->bi_end_io = end_sync_read;
+ if (test_bit(WriteMostly, &rdev->flags)) {
+ if (wonly < 0)
+ wonly = i;
+ } else {
+ if (disk < 0)
+ disk = i;
+ }
+ read_targets++;
+ }
+ atomic_inc(&rdev->nr_pending);
+ bio->bi_sector = sector_nr + rdev->data_offset;
+ bio->bi_bdev = rdev->bdev;
bio->bi_private = r1_bio;
}
+ rcu_read_unlock();
+ if (disk < 0)
+ disk = wonly;
+ r1_bio->read_disk = disk;
+
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && read_targets > 0)
+ /* extra read targets are also write targets */
+ write_targets += read_targets-1;
- if (write_targets == 0) {
+ if (write_targets == 0 || read_targets == 0) {
/* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished
*/
sector_t rv = max_sector - sector_nr;
*skipped = 1;
put_buf(r1_bio);
- rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
return rv;
}
@@ -1436,10 +1724,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0 ; i < conf->raid_disks; i++) {
bio = r1_bio->bios[i];
if (bio->bi_end_io) {
- page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page;
+ page = bio->bi_io_vec[bio->bi_vcnt].bv_page;
if (bio_add_page(bio, page, len, 0) == 0) {
/* stop here */
- r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page;
+ bio->bi_io_vec[bio->bi_vcnt].bv_page = page;
while (i > 0) {
i--;
bio = r1_bio->bios[i];
@@ -1459,12 +1747,28 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
sync_blocks -= (len>>9);
} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
bio_full:
- bio = r1_bio->bios[disk];
r1_bio->sectors = nr_sectors;
- md_sync_acct(mirror->rdev->bdev, nr_sectors);
+ /* For a user-requested sync, we read all readable devices and do a
+ * compare
+ */
+ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ atomic_set(&r1_bio->remaining, read_targets);
+ for (i=0; i<conf->raid_disks; i++) {
+ bio = r1_bio->bios[i];
+ if (bio->bi_end_io == end_sync_read) {
+ md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+ generic_make_request(bio);
+ }
+ }
+ } else {
+ atomic_set(&r1_bio->remaining, 1);
+ bio = r1_bio->bios[r1_bio->read_disk];
+ md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
+ nr_sectors);
+ generic_make_request(bio);
- generic_make_request(bio);
+ }
return nr_sectors;
}
@@ -1487,18 +1791,19 @@ static int run(mddev_t *mddev)
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
- conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf)
goto out_no_mem;
- memset(conf, 0, sizeof(*conf));
- conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+ conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->mirrors)
goto out_no_mem;
- memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+ conf->tmppage = alloc_page(GFP_KERNEL);
+ if (!conf->tmppage)
+ goto out_no_mem;
conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
if (!conf->poolinfo)
@@ -1542,8 +1847,7 @@ static int run(mddev_t *mddev)
mddev->recovery_cp = MaxSector;
spin_lock_init(&conf->resync_lock);
- init_waitqueue_head(&conf->wait_idle);
- init_waitqueue_head(&conf->wait_resume);
+ init_waitqueue_head(&conf->wait_barrier);
bio_list_init(&conf->pending_bio_list);
bio_list_init(&conf->flushing_bio_list);
@@ -1583,7 +1887,6 @@ static int run(mddev_t *mddev)
mdname(mddev));
goto out_free_conf;
}
- if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
printk(KERN_INFO
"raid1: raid set %s active with %d out of %d mirrors\n",
@@ -1608,6 +1911,7 @@ out_free_conf:
if (conf->r1bio_pool)
mempool_destroy(conf->r1bio_pool);
kfree(conf->mirrors);
+ safe_put_page(conf->tmppage);
kfree(conf->poolinfo);
kfree(conf);
mddev->private = NULL;
@@ -1706,19 +2010,14 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
kfree(newpoolinfo);
return -ENOMEM;
}
- newmirrors = kmalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
+ newmirrors = kzalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL);
if (!newmirrors) {
kfree(newpoolinfo);
mempool_destroy(newpool);
return -ENOMEM;
}
- memset(newmirrors, 0, sizeof(struct mirror_info)*raid_disks);
- 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);
+ raise_barrier(conf);
/* ok, everything is stopped */
oldpool = conf->r1bio_pool;
@@ -1738,12 +2037,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
conf->raid_disks = mddev->raid_disks = raid_disks;
conf->last_used = 0; /* just make sure it is in-range */
- spin_lock_irq(&conf->resync_lock);
- conf->barrier--;
- spin_unlock_irq(&conf->resync_lock);
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
-
+ lower_barrier(conf);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
@@ -1758,33 +2052,19 @@ static void raid1_quiesce(mddev_t *mddev, int state)
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);
+ raise_barrier(conf);
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);
+ lower_barrier(conf);
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 =
+static struct mdk_personality raid1_personality =
{
.name = "raid1",
+ .level = 1,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -1802,15 +2082,17 @@ static mdk_personality_t raid1_personality =
static int __init raid_init(void)
{
- return register_md_personality(RAID1, &raid1_personality);
+ return register_md_personality(&raid1_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(RAID1);
+ unregister_md_personality(&raid1_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-3"); /* RAID1 */
+MODULE_ALIAS("md-raid1");
+MODULE_ALIAS("md-level-1");
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 713dc9c2c730..9130d051b474 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -18,7 +18,9 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "dm-bio-list.h"
#include <linux/raid/raid10.h>
+#include <linux/raid/bitmap.h>
/*
* RAID10 provides a combination of RAID0 and RAID1 functionality.
@@ -47,6 +49,9 @@
static void unplug_slaves(mddev_t *mddev);
+static void allow_barrier(conf_t *conf);
+static void lower_barrier(conf_t *conf);
+
static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
{
conf_t *conf = data;
@@ -54,10 +59,8 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
int size = offsetof(struct r10bio_s, devs[conf->copies]);
/* allocate a r10bio with room for raid_disks entries in the bios array */
- r10_bio = kmalloc(size, gfp_flags);
- if (r10_bio)
- memset(r10_bio, 0, size);
- else
+ r10_bio = kzalloc(size, gfp_flags);
+ if (!r10_bio)
unplug_slaves(conf->mddev);
return r10_bio;
@@ -129,10 +132,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
out_free_pages:
for ( ; i > 0 ; i--)
- __free_page(bio->bi_io_vec[i-1].bv_page);
+ safe_put_page(bio->bi_io_vec[i-1].bv_page);
while (j--)
for (i = 0; i < RESYNC_PAGES ; i++)
- __free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+ safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
j = -1;
out_free_bio:
while ( ++j < nalloc )
@@ -152,7 +155,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data)
struct bio *bio = r10bio->devs[j].bio;
if (bio) {
for (i = 0; i < RESYNC_PAGES; i++) {
- __free_page(bio->bi_io_vec[i].bv_page);
+ safe_put_page(bio->bi_io_vec[i].bv_page);
bio->bi_io_vec[i].bv_page = NULL;
}
bio_put(bio);
@@ -167,52 +170,33 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
for (i = 0; i < conf->copies; i++) {
struct bio **bio = & r10_bio->devs[i].bio;
- if (*bio)
+ if (*bio && *bio != IO_BLOCKED)
bio_put(*bio);
*bio = NULL;
}
}
-static inline void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(r10bio_t *r10_bio)
{
- unsigned long flags;
-
conf_t *conf = mddev_to_conf(r10_bio->mddev);
/*
* Wake up any possible resync thread that waits for the device
* to go idle.
*/
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ allow_barrier(conf);
put_all_bios(conf, r10_bio);
mempool_free(r10_bio, conf->r10bio_pool);
}
-static inline void put_buf(r10bio_t *r10_bio)
+static void put_buf(r10bio_t *r10_bio)
{
conf_t *conf = mddev_to_conf(r10_bio->mddev);
- unsigned long flags;
mempool_free(r10_bio, conf->r10buf_pool);
- spin_lock_irqsave(&conf->resync_lock, flags);
- if (!conf->barrier)
- BUG();
- --conf->barrier;
- wake_up(&conf->wait_resume);
- wake_up(&conf->wait_idle);
-
- if (!--conf->nr_pending) {
- wake_up(&conf->wait_idle);
- wake_up(&conf->wait_resume);
- }
- spin_unlock_irqrestore(&conf->resync_lock, flags);
+ lower_barrier(conf);
}
static void reschedule_retry(r10bio_t *r10_bio)
@@ -223,6 +207,7 @@ static void reschedule_retry(r10bio_t *r10_bio)
spin_lock_irqsave(&conf->device_lock, flags);
list_add(&r10_bio->retry_list, &conf->retry_list);
+ conf->nr_queued ++;
spin_unlock_irqrestore(&conf->device_lock, flags);
md_wakeup_thread(mddev->thread);
@@ -268,9 +253,9 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
- md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
- else
+ update_head_pos(slot, r10_bio);
+
+ if (uptodate) {
/*
* Set R10BIO_Uptodate in our master bio, so that
* we will return a good error code to the higher
@@ -281,15 +266,8 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int
* wait for the 'master' bio.
*/
set_bit(R10BIO_Uptodate, &r10_bio->state);
-
- update_head_pos(slot, r10_bio);
-
- /*
- * we have only one bio on the read side
- */
- if (uptodate)
raid_end_bio_io(r10_bio);
- else {
+ } else {
/*
* oops, read error:
*/
@@ -322,9 +300,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
+ if (!uptodate) {
md_error(r10_bio->mddev, conf->mirrors[dev].rdev);
- else
+ /* an I/O failed, we can't clear the bitmap */
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+ } else
/*
* Set R10BIO_Uptodate in our master bio, so that
* we will return a good error code for to the higher
@@ -344,6 +324,11 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in
* already.
*/
if (atomic_dec_and_test(&r10_bio->remaining)) {
+ /* clear the bitmap if all writes complete successfully */
+ bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector,
+ r10_bio->sectors,
+ !test_bit(R10BIO_Degraded, &r10_bio->state),
+ 0);
md_write_end(r10_bio->mddev);
raid_end_bio_io(r10_bio);
}
@@ -502,8 +487,9 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
rcu_read_lock();
/*
* 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.
+ * device if no resync is going on (recovery is ok), or below
+ * the resync window. We take the first readable disk when
+ * above the resync window.
*/
if (conf->mddev->recovery_cp < MaxSector
&& (this_sector + sectors >= conf->next_resync)) {
@@ -512,6 +498,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
disk = r10_bio->devs[slot].devnum;
while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+ r10_bio->devs[slot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags)) {
slot++;
if (slot == conf->copies) {
@@ -529,6 +516,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
slot = 0;
disk = r10_bio->devs[slot].devnum;
while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
+ r10_bio->devs[slot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags)) {
slot ++;
if (slot == conf->copies) {
@@ -549,6 +537,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio)
if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL ||
+ r10_bio->devs[nslot].bio == IO_BLOCKED ||
!test_bit(In_sync, &rdev->flags))
continue;
@@ -607,7 +596,10 @@ static void unplug_slaves(mddev_t *mddev)
static void raid10_unplug(request_queue_t *q)
{
+ mddev_t *mddev = q->queuedata;
+
unplug_slaves(q->queuedata);
+ md_wakeup_thread(mddev->thread);
}
static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -640,27 +632,107 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk,
return ret;
}
-/*
- * Throttle resync depth, so that we can both get proper overlapping of
- * requests, but are still able to handle normal requests quickly.
+/* Barriers....
+ * Sometimes we need to suspend IO while we do something else,
+ * either some resync/recovery, or reconfigure the array.
+ * To do this we raise a 'barrier'.
+ * The 'barrier' is a counter that can be raised multiple times
+ * to count how many activities are happening which preclude
+ * normal IO.
+ * We can only raise the barrier if there is no pending IO.
+ * i.e. if nr_pending == 0.
+ * We choose only to raise the barrier if no-one is waiting for the
+ * barrier to go down. This means that as soon as an IO request
+ * is ready, no other operations which require a barrier will start
+ * until the IO request has had a chance.
+ *
+ * So: regular IO calls 'wait_barrier'. When that returns there
+ * is no backgroup IO happening, It must arrange to call
+ * allow_barrier when it has finished its IO.
+ * backgroup IO calls must call raise_barrier. Once that returns
+ * there is no normal IO happeing. It must arrange to call
+ * lower_barrier when the particular background IO completes.
*/
#define RESYNC_DEPTH 32
-static void device_barrier(conf_t *conf, sector_t sect)
+static void raise_barrier(conf_t *conf, int force)
+{
+ BUG_ON(force && !conf->barrier);
+ spin_lock_irq(&conf->resync_lock);
+
+ /* Wait until no block IO is waiting (unless 'force') */
+ wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+
+ /* block any new IO from starting */
+ conf->barrier++;
+
+ /* No wait for all pending IO to complete */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void lower_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->barrier--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void wait_barrier(conf_t *conf)
{
spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
- conf->resync_lock, unplug_slaves(conf->mddev));
-
- if (!conf->barrier++) {
- wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, unplug_slaves(conf->mddev));
- if (conf->nr_pending)
- BUG();
+ if (conf->barrier) {
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+ conf->nr_waiting--;
}
- wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
- conf->resync_lock, unplug_slaves(conf->mddev));
- conf->next_resync = sect;
+ conf->nr_pending++;
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void allow_barrier(conf_t *conf)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&conf->resync_lock, flags);
+ conf->nr_pending--;
+ spin_unlock_irqrestore(&conf->resync_lock, flags);
+ wake_up(&conf->wait_barrier);
+}
+
+static void freeze_array(conf_t *conf)
+{
+ /* stop syncio and normal IO and wait for everything to
+ * go quiet.
+ * We increment barrier and nr_waiting, and then
+ * wait until barrier+nr_pending match nr_queued+2
+ */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier++;
+ conf->nr_waiting++;
+ wait_event_lock_irq(conf->wait_barrier,
+ conf->barrier+conf->nr_pending == conf->nr_queued+2,
+ conf->resync_lock,
+ raid10_unplug(conf->mddev->queue));
+ spin_unlock_irq(&conf->resync_lock);
+}
+
+static void unfreeze_array(conf_t *conf)
+{
+ /* reverse the effect of the freeze */
+ spin_lock_irq(&conf->resync_lock);
+ conf->barrier--;
+ conf->nr_waiting--;
+ wake_up(&conf->wait_barrier);
spin_unlock_irq(&conf->resync_lock);
}
@@ -674,6 +746,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
int i;
int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio);
+ struct bio_list bl;
+ unsigned long flags;
if (unlikely(bio_barrier(bio))) {
bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
@@ -719,10 +793,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
*/
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio));
@@ -734,6 +805,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r10_bio->mddev = mddev;
r10_bio->sector = bio->bi_sector;
+ r10_bio->state = 0;
if (rw == READ) {
/*
@@ -778,13 +850,16 @@ static int make_request(request_queue_t *q, struct bio * bio)
!test_bit(Faulty, &rdev->flags)) {
atomic_inc(&rdev->nr_pending);
r10_bio->devs[i].bio = bio;
- } else
+ } else {
r10_bio->devs[i].bio = NULL;
+ set_bit(R10BIO_Degraded, &r10_bio->state);
+ }
}
rcu_read_unlock();
- atomic_set(&r10_bio->remaining, 1);
+ atomic_set(&r10_bio->remaining, 0);
+ bio_list_init(&bl);
for (i = 0; i < conf->copies; i++) {
struct bio *mbio;
int d = r10_bio->devs[i].devnum;
@@ -802,13 +877,14 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_private = r10_bio;
atomic_inc(&r10_bio->remaining);
- generic_make_request(mbio);
+ bio_list_add(&bl, mbio);
}
- if (atomic_dec_and_test(&r10_bio->remaining)) {
- md_write_end(mddev);
- raid_end_bio_io(r10_bio);
- }
+ bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0);
+ spin_lock_irqsave(&conf->device_lock, flags);
+ bio_list_merge(&conf->pending_bio_list, &bl);
+ blk_plug_device(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
return 0;
}
@@ -897,13 +973,8 @@ static void print_conf(conf_t *conf)
static void close_sync(conf_t *conf)
{
- spin_lock_irq(&conf->resync_lock);
- wait_event_lock_irq(conf->wait_resume, !conf->barrier,
- conf->resync_lock, unplug_slaves(conf->mddev));
- spin_unlock_irq(&conf->resync_lock);
-
- if (conf->barrier) BUG();
- if (waitqueue_active(&conf->wait_idle)) BUG();
+ wait_barrier(conf);
+ allow_barrier(conf);
mempool_destroy(conf->r10buf_pool);
conf->r10buf_pool = NULL;
@@ -971,7 +1042,12 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
if (!enough(conf))
return 0;
- for (mirror=0; mirror < mddev->raid_disks; mirror++)
+ if (rdev->saved_raid_disk >= 0 &&
+ conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+ mirror = rdev->saved_raid_disk;
+ else
+ mirror = 0;
+ for ( ; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
blk_queue_stack_limits(mddev->queue,
@@ -987,6 +1063,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
found = 1;
+ if (rdev->saved_raid_disk != mirror)
+ conf->fullsync = 1;
rcu_assign_pointer(p->rdev, rdev);
break;
}
@@ -1027,7 +1105,6 @@ abort:
static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
{
- int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private);
conf_t *conf = mddev_to_conf(r10_bio->mddev);
int i,d;
@@ -1042,9 +1119,16 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
BUG();
update_head_pos(i, r10_bio);
d = r10_bio->devs[i].devnum;
- if (!uptodate)
- md_error(r10_bio->mddev,
- conf->mirrors[d].rdev);
+
+ if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+ set_bit(R10BIO_Uptodate, &r10_bio->state);
+ else {
+ atomic_add(r10_bio->sectors,
+ &conf->mirrors[d].rdev->corrected_errors);
+ if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+ md_error(r10_bio->mddev,
+ conf->mirrors[d].rdev);
+ }
/* for reconstruct, we always reschedule after a read.
* for resync, only after all reads
@@ -1132,23 +1216,32 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio)
fbio = r10_bio->devs[i].bio;
/* now find blocks with errors */
- for (i=first+1 ; i < conf->copies ; i++) {
- int vcnt, j, d;
+ for (i=0 ; i < conf->copies ; i++) {
+ int j, d;
+ int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
- if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags))
- continue;
- /* We know that the bi_io_vec layout is the same for
- * both 'first' and 'i', so we just compare them.
- * All vec entries are PAGE_SIZE;
- */
tbio = r10_bio->devs[i].bio;
- vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
- for (j = 0; j < vcnt; j++)
- if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
- page_address(tbio->bi_io_vec[j].bv_page),
- PAGE_SIZE))
- break;
- if (j == vcnt)
+
+ if (tbio->bi_end_io != end_sync_read)
+ continue;
+ if (i == first)
+ continue;
+ if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) {
+ /* We know that the bi_io_vec layout is the same for
+ * both 'first' and 'i', so we just compare them.
+ * All vec entries are PAGE_SIZE;
+ */
+ for (j = 0; j < vcnt; j++)
+ if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
+ page_address(tbio->bi_io_vec[j].bv_page),
+ PAGE_SIZE))
+ break;
+ if (j == vcnt)
+ continue;
+ mddev->resync_mismatches += r10_bio->sectors;
+ }
+ if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+ /* Don't fix anything. */
continue;
/* Ok, we need to write this bio
* First we need to fixup bv_offset, bv_len and
@@ -1227,7 +1320,10 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
- generic_make_request(wbio);
+ if (test_bit(R10BIO_Uptodate, &r10_bio->state))
+ generic_make_request(wbio);
+ else
+ bio_endio(wbio, wbio->bi_size, -EIO);
}
@@ -1254,10 +1350,31 @@ static void raid10d(mddev_t *mddev)
for (;;) {
char b[BDEVNAME_SIZE];
spin_lock_irqsave(&conf->device_lock, flags);
+
+ if (conf->pending_bio_list.head) {
+ bio = bio_list_get(&conf->pending_bio_list);
+ blk_remove_plug(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ /* flush any pending bitmap writes to disk before proceeding w/ I/O */
+ if (bitmap_unplug(mddev->bitmap) != 0)
+ printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+ while (bio) { /* submit pending writes */
+ struct bio *next = bio->bi_next;
+ bio->bi_next = NULL;
+ generic_make_request(bio);
+ bio = next;
+ }
+ unplug = 1;
+
+ continue;
+ }
+
if (list_empty(head))
break;
r10_bio = list_entry(head->prev, r10bio_t, retry_list);
list_del(head->prev);
+ conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r10_bio->mddev;
@@ -1270,8 +1387,96 @@ static void raid10d(mddev_t *mddev)
unplug = 1;
} else {
int mirror;
+ /* we got a read error. Maybe the drive is bad. Maybe just
+ * the block and we can fix it.
+ * We freeze all other IO, and try reading the block from
+ * other devices. When we find one, we re-write
+ * and check it that fixes the read error.
+ * This is all done synchronously while the array is
+ * frozen.
+ */
+ int sect = 0; /* Offset from r10_bio->sector */
+ int sectors = r10_bio->sectors;
+ freeze_array(conf);
+ if (mddev->ro == 0) while(sectors) {
+ int s = sectors;
+ int sl = r10_bio->read_slot;
+ int success = 0;
+
+ if (s > (PAGE_SIZE>>9))
+ s = PAGE_SIZE >> 9;
+
+ do {
+ int d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags) &&
+ sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ))
+ success = 1;
+ else {
+ sl++;
+ if (sl == conf->copies)
+ sl = 0;
+ }
+ } while (!success && sl != r10_bio->read_slot);
+
+ if (success) {
+ int start = sl;
+ /* write it back and re-read */
+ while (sl != r10_bio->read_slot) {
+ int d;
+ if (sl==0)
+ sl = conf->copies;
+ sl--;
+ d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ atomic_add(s, &rdev->corrected_errors);
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, WRITE) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ sl = start;
+ while (sl != r10_bio->read_slot) {
+ int d;
+ if (sl==0)
+ sl = conf->copies;
+ sl--;
+ d = r10_bio->devs[sl].devnum;
+ rdev = conf->mirrors[d].rdev;
+ if (rdev &&
+ test_bit(In_sync, &rdev->flags)) {
+ if (sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9, conf->tmppage, READ) == 0)
+ /* Well, this device is dead */
+ md_error(mddev, rdev);
+ }
+ }
+ } else {
+ /* Cannot read from anywhere -- bye bye array */
+ md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
+ break;
+ }
+ sectors -= s;
+ sect += s;
+ }
+
+ unfreeze_array(conf);
+
bio = r10_bio->devs[r10_bio->read_slot].bio;
- r10_bio->devs[r10_bio->read_slot].bio = NULL;
+ r10_bio->devs[r10_bio->read_slot].bio =
+ mddev->ro ? IO_BLOCKED : NULL;
bio_put(bio);
mirror = read_balance(conf, r10_bio);
if (mirror == -1) {
@@ -1360,6 +1565,8 @@ 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 max_sync;
+ int sync_blocks;
sector_t sectors_skipped = 0;
int chunks_skipped = 0;
@@ -1373,6 +1580,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
max_sector = mddev->resync_max_sectors;
if (sector_nr >= max_sector) {
+ /* If we aborted, we need to abort the
+ * sync on the 'current' bitmap chucks (there can
+ * be several when recovering multiple devices).
+ * as we may have started syncing it but not finished.
+ * We can find the current address in
+ * mddev->curr_resync, but for recovery,
+ * we need to convert that to several
+ * virtual addresses.
+ */
+ if (mddev->curr_resync < max_sector) { /* aborted */
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else for (i=0; i<conf->raid_disks; i++) {
+ sector_t sect =
+ raid10_find_virt(conf, mddev->curr_resync, i);
+ bitmap_end_sync(mddev->bitmap, sect,
+ &sync_blocks, 1);
+ }
+ } else /* completed sync */
+ conf->fullsync = 0;
+
+ bitmap_close_sync(mddev->bitmap);
close_sync(conf);
*skipped = 1;
return sectors_skipped;
@@ -1395,9 +1625,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
* If there is non-resync activity waiting for us then
* put in a delay to throttle resync.
*/
- if (!go_faster && waitqueue_active(&conf->wait_resume))
+ if (!go_faster && conf->nr_waiting)
msleep_interruptible(1000);
- device_barrier(conf, sector_nr + RESYNC_SECTORS);
/* Again, very different code for resync and recovery.
* Both must result in an r10bio with a list of bios that
@@ -1414,6 +1643,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
* end_sync_write if we will want to write.
*/
+ max_sync = RESYNC_PAGES << (PAGE_SHIFT-9);
if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
/* recovery... the complicated one */
int i, j, k;
@@ -1422,14 +1652,29 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
for (i=0 ; i<conf->raid_disks; i++)
if (conf->mirrors[i].rdev &&
!test_bit(In_sync, &conf->mirrors[i].rdev->flags)) {
+ int still_degraded = 0;
/* want to reconstruct this device */
r10bio_t *rb2 = r10_bio;
+ sector_t sect = raid10_find_virt(conf, sector_nr, i);
+ int must_sync;
+ /* Unless we are doing a full sync, we only need
+ * to recover the block if it is set in the bitmap
+ */
+ must_sync = bitmap_start_sync(mddev->bitmap, sect,
+ &sync_blocks, 1);
+ if (sync_blocks < max_sync)
+ max_sync = sync_blocks;
+ if (!must_sync &&
+ !conf->fullsync) {
+ /* yep, skip the sync_blocks here, but don't assume
+ * that there will never be anything to do here
+ */
+ chunks_skipped = -1;
+ continue;
+ }
r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- if (rb2) conf->barrier++;
- spin_unlock_irq(&conf->resync_lock);
+ raise_barrier(conf, rb2 != NULL);
atomic_set(&r10_bio->remaining, 0);
r10_bio->master_bio = (struct bio*)rb2;
@@ -1437,8 +1682,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
atomic_inc(&rb2->remaining);
r10_bio->mddev = mddev;
set_bit(R10BIO_IsRecover, &r10_bio->state);
- r10_bio->sector = raid10_find_virt(conf, sector_nr, i);
+ r10_bio->sector = sect;
+
raid10_find_phys(conf, r10_bio);
+ /* Need to check if this section will still be
+ * degraded
+ */
+ for (j=0; j<conf->copies;j++) {
+ int d = r10_bio->devs[j].devnum;
+ if (conf->mirrors[d].rdev == NULL ||
+ test_bit(Faulty, &conf->mirrors[d].rdev->flags)) {
+ still_degraded = 1;
+ break;
+ }
+ }
+ must_sync = bitmap_start_sync(mddev->bitmap, sect,
+ &sync_blocks, still_degraded);
+
for (j=0; j<conf->copies;j++) {
int d = r10_bio->devs[j].devnum;
if (conf->mirrors[d].rdev &&
@@ -1498,14 +1758,22 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
} else {
/* resync. Schedule a read for every block at this virt offset */
int count = 0;
- r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
- spin_lock_irq(&conf->resync_lock);
- conf->nr_pending++;
- spin_unlock_irq(&conf->resync_lock);
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr,
+ &sync_blocks, mddev->degraded) &&
+ !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
+ /* We can skip this block */
+ *skipped = 1;
+ return sync_blocks + sectors_skipped;
+ }
+ if (sync_blocks < max_sync)
+ max_sync = sync_blocks;
+ r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO);
r10_bio->mddev = mddev;
atomic_set(&r10_bio->remaining, 0);
+ raise_barrier(conf, 0);
+ conf->next_resync = sector_nr;
r10_bio->master_bio = NULL;
r10_bio->sector = sector_nr;
@@ -1558,6 +1826,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
}
nr_sectors = 0;
+ if (sector_nr + max_sync < max_sector)
+ max_sector = sector_nr + max_sync;
do {
struct page *page;
int len = PAGE_SIZE;
@@ -1632,11 +1902,11 @@ static int run(mddev_t *mddev)
int nc, fc;
sector_t stride, size;
- if (mddev->level != 10) {
- printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n",
- mdname(mddev), mddev->level);
- goto out;
+ if (mddev->chunk_size == 0) {
+ printk(KERN_ERR "md/raid10: non-zero chunk size required.\n");
+ return -EINVAL;
}
+
nc = mddev->layout & 255;
fc = (mddev->layout >> 8) & 255;
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
@@ -1650,22 +1920,24 @@ static int run(mddev_t *mddev)
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
- conf = kmalloc(sizeof(conf_t), GFP_KERNEL);
+ conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
mddev->private = conf;
if (!conf) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out;
}
- memset(conf, 0, sizeof(*conf));
- conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks,
+ conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
GFP_KERNEL);
if (!conf->mirrors) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out_free_conf;
}
- memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks);
+
+ conf->tmppage = alloc_page(GFP_KERNEL);
+ if (!conf->tmppage)
+ goto out_free_conf;
conf->near_copies = nc;
conf->far_copies = fc;
@@ -1713,8 +1985,7 @@ static int run(mddev_t *mddev)
INIT_LIST_HEAD(&conf->retry_list);
spin_lock_init(&conf->resync_lock);
- init_waitqueue_head(&conf->wait_idle);
- init_waitqueue_head(&conf->wait_resume);
+ init_waitqueue_head(&conf->wait_barrier);
/* need to check that every block has at least one working mirror */
if (!enough(conf)) {
@@ -1763,7 +2034,7 @@ static int run(mddev_t *mddev)
* maybe...
*/
{
- int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE;
+ int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE;
stripe /= conf->near_copies;
if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
mddev->queue->backing_dev_info.ra_pages = 2* stripe;
@@ -1776,6 +2047,7 @@ static int run(mddev_t *mddev)
out_free_conf:
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
+ safe_put_page(conf->tmppage);
kfree(conf->mirrors);
kfree(conf);
mddev->private = NULL;
@@ -1798,10 +2070,31 @@ static int stop(mddev_t *mddev)
return 0;
}
+static void raid10_quiesce(mddev_t *mddev, int state)
+{
+ conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1:
+ raise_barrier(conf, 0);
+ break;
+ case 0:
+ lower_barrier(conf);
+ 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 raid10_personality =
+static struct mdk_personality raid10_personality =
{
.name = "raid10",
+ .level = 10,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -1812,19 +2105,22 @@ static mdk_personality_t raid10_personality =
.hot_remove_disk= raid10_remove_disk,
.spare_active = raid10_spare_active,
.sync_request = sync_request,
+ .quiesce = raid10_quiesce,
};
static int __init raid_init(void)
{
- return register_md_personality(RAID10, &raid10_personality);
+ return register_md_personality(&raid10_personality);
}
static void raid_exit(void)
{
- unregister_md_personality(RAID10);
+ unregister_md_personality(&raid10_personality);
}
module_init(raid_init);
module_exit(raid_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-9"); /* RAID10 */
+MODULE_ALIAS("md-raid10");
+MODULE_ALIAS("md-level-10");
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index fafc4bc045f7..25976bfb6f9c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -35,12 +35,10 @@
#define STRIPE_SHIFT (PAGE_SHIFT - 9)
#define STRIPE_SECTORS (STRIPE_SIZE>>9)
#define IO_THRESHOLD 1
-#define HASH_PAGES 1
-#define HASH_PAGES_ORDER 0
-#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
#define HASH_MASK (NR_HASH - 1)
-#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
/* bio's attached to a stripe+device for I/O are linked together in bi_sector
* order without overlap. There may be several bio's per stripe+device, and
@@ -71,7 +69,7 @@
static void print_raid5_conf (raid5_conf_t *conf);
-static inline void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
if (!list_empty(&sh->lru))
@@ -113,29 +111,21 @@ static void release_stripe(struct stripe_head *sh)
spin_unlock_irqrestore(&conf->device_lock, flags);
}
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
{
PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
- if (sh->hash_pprev) {
- if (sh->hash_next)
- sh->hash_next->hash_pprev = sh->hash_pprev;
- *sh->hash_pprev = sh->hash_next;
- sh->hash_pprev = NULL;
- }
+ hlist_del_init(&sh->hash);
}
-static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
{
- struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+ struct hlist_head *hp = stripe_hash(conf, sh->sector);
PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
CHECK_DEVLOCK();
- if ((sh->hash_next = *shp) != NULL)
- (*shp)->hash_pprev = &sh->hash_next;
- *shp = sh;
- sh->hash_pprev = shp;
+ hlist_add_head(&sh->hash, hp);
}
@@ -167,7 +157,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
if (!p)
continue;
sh->dev[i].page = NULL;
- page_cache_release(p);
+ put_page(p);
}
}
@@ -188,7 +178,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid5_build_block (struct stripe_head *sh, int i);
-static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
{
raid5_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
@@ -228,10 +218,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
- for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+ hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -417,7 +408,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- printk("R5: read error corrected!!\n");
+ printk(KERN_INFO "raid5: read error corrected!!\n");
clear_bit(R5_ReadError, &sh->dev[i].flags);
clear_bit(R5_ReWrite, &sh->dev[i].flags);
}
@@ -428,13 +419,14 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
atomic_inc(&conf->disks[i].rdev->read_errors);
if (conf->mddev->degraded)
- printk("R5: read error not correctable.\n");
+ printk(KERN_WARNING "raid5: read error not correctable.\n");
else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
/* Oh, no!!! */
- printk("R5: read error NOT corrected!!\n");
+ printk(KERN_WARNING "raid5: read error NOT corrected!!\n");
else if (atomic_read(&conf->disks[i].rdev->read_errors)
> conf->max_nr_stripes)
- printk("raid5: Too many read errors, failing device.\n");
+ printk(KERN_WARNING
+ "raid5: Too many read errors, failing device.\n");
else
retry = 1;
if (retry)
@@ -604,7 +596,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks,
*dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks;
break;
default:
- printk("raid5: unsupported algorithm %d\n",
+ printk(KERN_ERR "raid5: unsupported algorithm %d\n",
conf->algorithm);
}
@@ -645,7 +637,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
i -= (sh->pd_idx + 1);
break;
default:
- printk("raid5: unsupported algorithm %d\n",
+ printk(KERN_ERR "raid5: unsupported algorithm %d\n",
conf->algorithm);
}
@@ -654,7 +646,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
- printk("compute_blocknr: map not correct\n");
+ printk(KERN_ERR "compute_blocknr: map not correct\n");
return 0;
}
return r_sector;
@@ -737,7 +729,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
ptr[count++] = p;
else
- printk("compute_block() %d, stripe %llu, %d"
+ printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
" not present\n", dd_idx,
(unsigned long long)sh->sector, i);
@@ -960,11 +952,11 @@ static void handle_stripe(struct stripe_head *sh)
syncing = test_bit(STRIPE_SYNCING, &sh->state);
/* Now to look around and see what can be done */
+ rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- clear_bit(R5_Syncio, &dev->flags);
PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1003,9 +995,9 @@ static void handle_stripe(struct stripe_head *sh)
non_overwrite++;
}
if (dev->written) written++;
- rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
- /* The ReadError flag wil just be confusing now */
+ /* The ReadError flag will just be confusing now */
clear_bit(R5_ReadError, &dev->flags);
clear_bit(R5_ReWrite, &dev->flags);
}
@@ -1016,6 +1008,7 @@ static void handle_stripe(struct stripe_head *sh)
} else
set_bit(R5_Insync, &dev->flags);
}
+ rcu_read_unlock();
PRINTK("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d\n",
locked, uptodate, to_read, to_write, failed, failed_num);
@@ -1027,10 +1020,13 @@ static void handle_stripe(struct stripe_head *sh)
int bitmap_end = 0;
if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- mdk_rdev_t *rdev = conf->disks[i].rdev;
+ mdk_rdev_t *rdev;
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && test_bit(In_sync, &rdev->flags))
/* multiple read failures in one stripe */
md_error(conf->mddev, rdev);
+ rcu_read_unlock();
}
spin_lock_irq(&conf->device_lock);
@@ -1179,9 +1175,6 @@ static void handle_stripe(struct stripe_head *sh)
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
- if (syncing)
- md_sync_acct(conf->disks[i].rdev->bdev,
- STRIPE_SECTORS);
}
}
}
@@ -1288,7 +1281,7 @@ static void handle_stripe(struct stripe_head *sh)
* is available
*/
if (syncing && locked == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 1) {
+ !test_bit(STRIPE_INSYNC, &sh->state)) {
set_bit(STRIPE_HANDLE, &sh->state);
if (failed == 0) {
char *pagea;
@@ -1306,27 +1299,25 @@ static void handle_stripe(struct stripe_head *sh)
if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
/* don't try to repair!! */
set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ compute_block(sh, sh->pd_idx);
+ uptodate++;
+ }
}
}
if (!test_bit(STRIPE_INSYNC, &sh->state)) {
+ /* either failed parity check, or recovery is happening */
if (failed==0)
failed_num = sh->pd_idx;
- /* should be able to compute the missing block and write it to spare */
- if (!test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)) {
- if (uptodate+1 != disks)
- BUG();
- compute_block(sh, failed_num);
- uptodate++;
- }
- if (uptodate != disks)
- BUG();
dev = &sh->dev[failed_num];
+ BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+ BUG_ON(uptodate != disks);
+
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);
}
}
if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
@@ -1392,7 +1383,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (test_bit(R5_Syncio, &sh->dev[i].flags))
+ if (syncing)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1409,6 +1400,9 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_io_vec[0].bv_offset = 0;
bi->bi_size = STRIPE_SIZE;
bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
if (rw == 1)
@@ -1421,7 +1415,7 @@ static void handle_stripe(struct stripe_head *sh)
}
}
-static inline void raid5_activate_delayed(raid5_conf_t *conf)
+static void raid5_activate_delayed(raid5_conf_t *conf)
{
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
while (!list_empty(&conf->delayed_list)) {
@@ -1437,7 +1431,7 @@ static inline void raid5_activate_delayed(raid5_conf_t *conf)
}
}
-static inline void activate_bit_delay(raid5_conf_t *conf)
+static void activate_bit_delay(raid5_conf_t *conf)
{
/* device_lock is held */
struct list_head head;
@@ -1822,21 +1816,21 @@ static int run(mddev_t *mddev)
struct list_head *tmp;
if (mddev->level != 5 && mddev->level != 4) {
- printk("raid5: %s: raid level not set to 4/5 (%d)\n", mdname(mddev), mddev->level);
+ printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n",
+ mdname(mddev), mddev->level);
return -EIO;
}
- mddev->private = kmalloc (sizeof (raid5_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid5_conf_t)
+ + mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
- memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
+
conf->mddev = mddev;
- if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+ if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
goto abort;
- memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
@@ -1903,10 +1897,17 @@ static int run(mddev_t *mddev)
if (mddev->degraded == 1 &&
mddev->recovery_cp != MaxSector) {
- printk(KERN_ERR
- "raid5: cannot start dirty degraded array for %s\n",
- mdname(mddev));
- goto abort;
+ if (mddev->ok_start_degraded)
+ printk(KERN_WARNING
+ "raid5: starting dirty degraded array: %s"
+ "- data corruption possible.\n",
+ mdname(mddev));
+ else {
+ printk(KERN_ERR
+ "raid5: cannot start dirty degraded array for %s\n",
+ mdname(mddev));
+ goto abort;
+ }
}
{
@@ -1948,7 +1949,7 @@ static int run(mddev_t *mddev)
*/
{
int stripe = (mddev->raid_disks-1) * mddev->chunk_size
- / PAGE_CACHE_SIZE;
+ / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
}
@@ -1956,9 +1957,6 @@ static int run(mddev_t *mddev)
/* Ok, everything is just fine now */
sysfs_create_group(&mddev->kobj, &raid5_attrs_group);
- 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;
@@ -1967,9 +1965,7 @@ static int run(mddev_t *mddev)
abort:
if (conf) {
print_raid5_conf(conf);
- if (conf->stripe_hashtbl)
- free_pages((unsigned long) conf->stripe_hashtbl,
- HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
kfree(conf);
}
mddev->private = NULL;
@@ -1986,7 +1982,7 @@ static int stop(mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
shrink_stripes(conf);
- free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
kfree(conf);
@@ -2014,12 +2010,12 @@ static void print_sh (struct stripe_head *sh)
static void printall (raid5_conf_t *conf)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
int i;
spin_lock_irq(&conf->device_lock);
for (i = 0; i < NR_HASH; i++) {
- sh = conf->stripe_hashtbl[i];
- for (; sh; sh = sh->hash_next) {
+ hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
if (sh->raid_conf != conf)
continue;
print_sh(sh);
@@ -2192,17 +2188,12 @@ static void raid5_quiesce(mddev_t *mddev, int state)
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=
+
+static struct mdk_personality raid5_personality =
{
.name = "raid5",
+ .level = 5,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -2217,17 +2208,42 @@ static mdk_personality_t raid5_personality=
.quiesce = raid5_quiesce,
};
-static int __init raid5_init (void)
+static struct mdk_personality raid4_personality =
{
- return register_md_personality (RAID5, &raid5_personality);
+ .name = "raid4",
+ .level = 4,
+ .owner = THIS_MODULE,
+ .make_request = make_request,
+ .run = run,
+ .stop = stop,
+ .status = status,
+ .error_handler = error,
+ .hot_add_disk = raid5_add_disk,
+ .hot_remove_disk= raid5_remove_disk,
+ .spare_active = raid5_spare_active,
+ .sync_request = sync_request,
+ .resize = raid5_resize,
+ .quiesce = raid5_quiesce,
+};
+
+static int __init raid5_init(void)
+{
+ register_md_personality(&raid5_personality);
+ register_md_personality(&raid4_personality);
+ return 0;
}
-static void raid5_exit (void)
+static void raid5_exit(void)
{
- unregister_md_personality (RAID5);
+ unregister_md_personality(&raid5_personality);
+ unregister_md_personality(&raid4_personality);
}
module_init(raid5_init);
module_exit(raid5_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-4"); /* RAID5 */
+MODULE_ALIAS("md-raid5");
+MODULE_ALIAS("md-raid4");
+MODULE_ALIAS("md-level-5");
+MODULE_ALIAS("md-level-4");
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 0000d162d198..f618a53b98be 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -40,12 +40,10 @@
#define STRIPE_SHIFT (PAGE_SHIFT - 9)
#define STRIPE_SECTORS (STRIPE_SIZE>>9)
#define IO_THRESHOLD 1
-#define HASH_PAGES 1
-#define HASH_PAGES_ORDER 0
-#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
+#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))
#define HASH_MASK (NR_HASH - 1)
-#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])
+#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
/* bio's attached to a stripe+device for I/O are linked together in bi_sector
* order without overlap. There may be several bio's per stripe+device, and
@@ -90,7 +88,7 @@ static inline int raid6_next_disk(int disk, int raid_disks)
static void print_raid6_conf (raid6_conf_t *conf);
-static inline void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
+static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count)) {
if (!list_empty(&sh->lru))
@@ -132,29 +130,21 @@ static void release_stripe(struct stripe_head *sh)
spin_unlock_irqrestore(&conf->device_lock, flags);
}
-static void remove_hash(struct stripe_head *sh)
+static inline void remove_hash(struct stripe_head *sh)
{
PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
- if (sh->hash_pprev) {
- if (sh->hash_next)
- sh->hash_next->hash_pprev = sh->hash_pprev;
- *sh->hash_pprev = sh->hash_next;
- sh->hash_pprev = NULL;
- }
+ hlist_del_init(&sh->hash);
}
-static __inline__ void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
{
- struct stripe_head **shp = &stripe_hash(conf, sh->sector);
+ struct hlist_head *hp = stripe_hash(conf, sh->sector);
PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
CHECK_DEVLOCK();
- if ((sh->hash_next = *shp) != NULL)
- (*shp)->hash_pprev = &sh->hash_next;
- *shp = sh;
- sh->hash_pprev = shp;
+ hlist_add_head(&sh->hash, hp);
}
@@ -186,7 +176,7 @@ static void shrink_buffers(struct stripe_head *sh, int num)
if (!p)
continue;
sh->dev[i].page = NULL;
- page_cache_release(p);
+ put_page(p);
}
}
@@ -207,7 +197,7 @@ static int grow_buffers(struct stripe_head *sh, int num)
static void raid6_build_block (struct stripe_head *sh, int i);
-static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
{
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks, i;
@@ -247,10 +237,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i
static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
CHECK_DEVLOCK();
PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
- for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next)
+ hlist_for_each_entry (sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector)
return sh;
PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
@@ -367,8 +358,8 @@ static void shrink_stripes(raid6_conf_t *conf)
conf->slab_cache = NULL;
}
-static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
- int error)
+static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done,
+ int error)
{
struct stripe_head *sh = bi->bi_private;
raid6_conf_t *conf = sh->raid_conf;
@@ -420,9 +411,35 @@ static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done,
#else
set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif
+ if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+ printk(KERN_INFO "raid6: read error corrected!!\n");
+ clear_bit(R5_ReadError, &sh->dev[i].flags);
+ clear_bit(R5_ReWrite, &sh->dev[i].flags);
+ }
+ if (atomic_read(&conf->disks[i].rdev->read_errors))
+ atomic_set(&conf->disks[i].rdev->read_errors, 0);
} else {
- md_error(conf->mddev, conf->disks[i].rdev);
+ int retry = 0;
clear_bit(R5_UPTODATE, &sh->dev[i].flags);
+ atomic_inc(&conf->disks[i].rdev->read_errors);
+ if (conf->mddev->degraded)
+ printk(KERN_WARNING "raid6: read error not correctable.\n");
+ else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
+ /* Oh, no!!! */
+ printk(KERN_WARNING "raid6: read error NOT corrected!!\n");
+ else if (atomic_read(&conf->disks[i].rdev->read_errors)
+ > conf->max_nr_stripes)
+ printk(KERN_WARNING
+ "raid6: Too many read errors, failing device.\n");
+ else
+ retry = 1;
+ if (retry)
+ set_bit(R5_ReadError, &sh->dev[i].flags);
+ else {
+ clear_bit(R5_ReadError, &sh->dev[i].flags);
+ clear_bit(R5_ReWrite, &sh->dev[i].flags);
+ md_error(conf->mddev, conf->disks[i].rdev);
+ }
}
rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
#if 0
@@ -805,7 +822,7 @@ static void compute_parity(struct stripe_head *sh, int method)
}
/* Compute one missing block */
-static void compute_block_1(struct stripe_head *sh, int dd_idx)
+static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
{
raid6_conf_t *conf = sh->raid_conf;
int i, count, disks = conf->raid_disks;
@@ -821,7 +838,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
compute_parity(sh, UPDATE_PARITY);
} else {
ptr[0] = page_address(sh->dev[dd_idx].page);
- memset(ptr[0], 0, STRIPE_SIZE);
+ if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
count = 1;
for (i = disks ; i--; ) {
if (i == dd_idx || i == qd_idx)
@@ -838,7 +855,8 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx)
}
if (count != 1)
xor_block(count, STRIPE_SIZE, ptr);
- set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+ if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+ else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
}
}
@@ -871,7 +889,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
return;
} else {
/* We're missing D+Q; recompute D from P */
- compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1);
+ compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */
return;
}
@@ -982,6 +1000,12 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
}
+static int page_is_zero(struct page *p)
+{
+ char *a = page_address(p);
+ return ((*(u32*)a) == 0 &&
+ memcmp(a, a+4, STRIPE_SIZE-4)==0);
+}
/*
* handle_stripe - do things to a stripe.
*
@@ -1000,7 +1024,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
*
*/
-static void handle_stripe(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
{
raid6_conf_t *conf = sh->raid_conf;
int disks = conf->raid_disks;
@@ -1027,11 +1051,11 @@ static void handle_stripe(struct stripe_head *sh)
syncing = test_bit(STRIPE_SYNCING, &sh->state);
/* Now to look around and see what can be done */
+ rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- clear_bit(R5_Syncio, &dev->flags);
PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
@@ -1070,14 +1094,21 @@ static void handle_stripe(struct stripe_head *sh)
non_overwrite++;
}
if (dev->written) written++;
- rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
+ rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+ /* The ReadError flag will just be confusing now */
+ clear_bit(R5_ReadError, &dev->flags);
+ clear_bit(R5_ReWrite, &dev->flags);
+ }
+ if (!rdev || !test_bit(In_sync, &rdev->flags)
+ || test_bit(R5_ReadError, &dev->flags)) {
if ( failed < 2 )
failed_num[failed] = i;
failed++;
} else
set_bit(R5_Insync, &dev->flags);
}
+ rcu_read_unlock();
PRINTK("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n",
locked, uptodate, to_read, to_write, failed,
@@ -1088,6 +1119,17 @@ static void handle_stripe(struct stripe_head *sh)
if (failed > 2 && to_read+to_write+written) {
for (i=disks; i--; ) {
int bitmap_end = 0;
+
+ if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+ mdk_rdev_t *rdev;
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(In_sync, &rdev->flags))
+ /* multiple read failures in one stripe */
+ md_error(conf->mddev, rdev);
+ rcu_read_unlock();
+ }
+
spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
@@ -1123,7 +1165,8 @@ static void handle_stripe(struct stripe_head *sh)
}
/* fail any reads if this device is non-operational */
- if (!test_bit(R5_Insync, &sh->dev[i].flags)) {
+ if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+ test_bit(R5_ReadError, &sh->dev[i].flags)) {
bi = sh->dev[i].toread;
sh->dev[i].toread = NULL;
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
@@ -1228,7 +1271,7 @@ static void handle_stripe(struct stripe_head *sh)
if (uptodate == disks-1) {
PRINTK("Computing stripe %llu block %d\n",
(unsigned long long)sh->sector, i);
- compute_block_1(sh, i);
+ compute_block_1(sh, i, 0);
uptodate++;
} else if ( uptodate == disks-2 && failed >= 2 ) {
/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
@@ -1259,9 +1302,6 @@ static void handle_stripe(struct stripe_head *sh)
locked++;
PRINTK("Reading block %d (sync=%d)\n",
i, syncing);
- if (syncing)
- md_sync_acct(conf->disks[i].rdev->bdev,
- STRIPE_SECTORS);
}
}
}
@@ -1323,7 +1363,7 @@ static void handle_stripe(struct stripe_head *sh)
/* We have failed blocks and need to compute them */
switch ( failed ) {
case 0: BUG();
- case 1: compute_block_1(sh, failed_num[0]); break;
+ case 1: compute_block_1(sh, failed_num[0], 0); break;
case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
default: BUG(); /* This request should have been failed? */
}
@@ -1338,12 +1378,10 @@ static void handle_stripe(struct stripe_head *sh)
(unsigned long long)sh->sector, i);
locked++;
set_bit(R5_Wantwrite, &sh->dev[i].flags);
-#if 0 /**** FIX: I don't understand the logic here... ****/
- if (!test_bit(R5_Insync, &sh->dev[i].flags)
- || ((i==pd_idx || i==qd_idx) && failed == 0)) /* FIX? */
- set_bit(STRIPE_INSYNC, &sh->state);
-#endif
}
+ /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+ set_bit(STRIPE_INSYNC, &sh->state);
+
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
atomic_dec(&conf->preread_active_stripes);
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -1356,84 +1394,119 @@ static void handle_stripe(struct stripe_head *sh)
* Any reads will already have been scheduled, so we just see if enough data
* is available
*/
- if (syncing && locked == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 2) {
- set_bit(STRIPE_HANDLE, &sh->state);
-#if 0 /* RAID-6: Don't support CHECK PARITY yet */
- if (failed == 0) {
- char *pagea;
- if (uptodate != disks)
- BUG();
- compute_parity(sh, CHECK_PARITY);
- uptodate--;
- pagea = page_address(sh->dev[pd_idx].page);
- if ((*(u32*)pagea) == 0 &&
- !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) {
- /* parity is correct (on disc, not in buffer any more) */
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- }
-#endif
- if (!test_bit(STRIPE_INSYNC, &sh->state)) {
- int failed_needupdate[2];
- struct r5dev *adev, *bdev;
-
- if ( failed < 1 )
- failed_num[0] = pd_idx;
- if ( failed < 2 )
- failed_num[1] = (failed_num[0] == qd_idx) ? pd_idx : qd_idx;
+ if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
+ int update_p = 0, update_q = 0;
+ struct r5dev *dev;
- failed_needupdate[0] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[0]].flags);
- failed_needupdate[1] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[1]].flags);
+ set_bit(STRIPE_HANDLE, &sh->state);
- PRINTK("sync: failed=%d num=%d,%d fnu=%u%u\n",
- failed, failed_num[0], failed_num[1], failed_needupdate[0], failed_needupdate[1]);
+ BUG_ON(failed>2);
+ BUG_ON(uptodate < disks);
+ /* Want to check and possibly repair P and Q.
+ * However there could be one 'failed' device, in which
+ * case we can only check one of them, possibly using the
+ * other to generate missing data
+ */
-#if 0 /* RAID-6: This code seems to require that CHECK_PARITY destroys the uptodateness of the parity */
- /* should be able to compute the missing block(s) and write to spare */
- if ( failed_needupdate[0] ^ failed_needupdate[1] ) {
- if (uptodate+1 != disks)
- BUG();
- compute_block_1(sh, failed_needupdate[0] ? failed_num[0] : failed_num[1]);
- uptodate++;
- } else if ( failed_needupdate[0] & failed_needupdate[1] ) {
- if (uptodate+2 != disks)
- BUG();
- compute_block_2(sh, failed_num[0], failed_num[1]);
- uptodate += 2;
+ /* If !tmp_page, we cannot do the calculations,
+ * but as we have set STRIPE_HANDLE, we will soon be called
+ * by stripe_handle with a tmp_page - just wait until then.
+ */
+ if (tmp_page) {
+ if (failed == q_failed) {
+ /* The only possible failed device holds 'Q', so it makes
+ * sense to check P (If anything else were failed, we would
+ * have used P to recreate it).
+ */
+ compute_block_1(sh, pd_idx, 1);
+ if (!page_is_zero(sh->dev[pd_idx].page)) {
+ compute_block_1(sh,pd_idx,0);
+ update_p = 1;
+ }
+ }
+ if (!q_failed && failed < 2) {
+ /* q is not failed, and we didn't use it to generate
+ * anything, so it makes sense to check it
+ */
+ memcpy(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE);
+ compute_parity(sh, UPDATE_PARITY);
+ if (memcmp(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE)!= 0) {
+ clear_bit(STRIPE_INSYNC, &sh->state);
+ update_q = 1;
+ }
+ }
+ if (update_p || update_q) {
+ conf->mddev->resync_mismatches += STRIPE_SECTORS;
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ /* don't try to repair!! */
+ update_p = update_q = 0;
}
-#else
- compute_block_2(sh, failed_num[0], failed_num[1]);
- uptodate += failed_needupdate[0] + failed_needupdate[1];
-#endif
- if (uptodate != disks)
- BUG();
+ /* now write out any block on a failed drive,
+ * or P or Q if they need it
+ */
- PRINTK("Marking for sync stripe %llu blocks %d,%d\n",
- (unsigned long long)sh->sector, failed_num[0], failed_num[1]);
+ if (failed == 2) {
+ dev = &sh->dev[failed_num[1]];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (failed >= 1) {
+ dev = &sh->dev[failed_num[0]];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
- /**** FIX: Should we really do both of these unconditionally? ****/
- adev = &sh->dev[failed_num[0]];
- locked += !test_bit(R5_LOCKED, &adev->flags);
- set_bit(R5_LOCKED, &adev->flags);
- set_bit(R5_Wantwrite, &adev->flags);
- bdev = &sh->dev[failed_num[1]];
- locked += !test_bit(R5_LOCKED, &bdev->flags);
- set_bit(R5_LOCKED, &bdev->flags);
+ if (update_p) {
+ dev = &sh->dev[pd_idx];
+ locked ++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (update_q) {
+ dev = &sh->dev[qd_idx];
+ locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
clear_bit(STRIPE_DEGRADED, &sh->state);
- set_bit(R5_Wantwrite, &bdev->flags);
set_bit(STRIPE_INSYNC, &sh->state);
- set_bit(R5_Syncio, &adev->flags);
- set_bit(R5_Syncio, &bdev->flags);
}
}
+
if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
md_done_sync(conf->mddev, STRIPE_SECTORS,1);
clear_bit(STRIPE_SYNCING, &sh->state);
}
+ /* If the failed drives are just a ReadError, then we might need
+ * to progress the repair/check process
+ */
+ if (failed <= 2 && ! conf->mddev->ro)
+ for (i=0; i<failed;i++) {
+ dev = &sh->dev[failed_num[i]];
+ if (test_bit(R5_ReadError, &dev->flags)
+ && !test_bit(R5_LOCKED, &dev->flags)
+ && test_bit(R5_UPTODATE, &dev->flags)
+ ) {
+ if (!test_bit(R5_ReWrite, &dev->flags)) {
+ set_bit(R5_Wantwrite, &dev->flags);
+ set_bit(R5_ReWrite, &dev->flags);
+ set_bit(R5_LOCKED, &dev->flags);
+ } else {
+ /* let's read it back */
+ set_bit(R5_Wantread, &dev->flags);
+ set_bit(R5_LOCKED, &dev->flags);
+ }
+ }
+ }
spin_unlock(&sh->lock);
while ((bi=return_bi)) {
@@ -1472,7 +1545,7 @@ static void handle_stripe(struct stripe_head *sh)
rcu_read_unlock();
if (rdev) {
- if (test_bit(R5_Syncio, &sh->dev[i].flags))
+ if (syncing)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
@@ -1489,6 +1562,9 @@ static void handle_stripe(struct stripe_head *sh)
bi->bi_io_vec[0].bv_offset = 0;
bi->bi_size = STRIPE_SIZE;
bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
generic_make_request(bi);
} else {
if (rw == 1)
@@ -1501,7 +1577,7 @@ static void handle_stripe(struct stripe_head *sh)
}
}
-static inline void raid6_activate_delayed(raid6_conf_t *conf)
+static void raid6_activate_delayed(raid6_conf_t *conf)
{
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
while (!list_empty(&conf->delayed_list)) {
@@ -1517,7 +1593,7 @@ static inline void raid6_activate_delayed(raid6_conf_t *conf)
}
}
-static inline void activate_bit_delay(raid6_conf_t *conf)
+static void activate_bit_delay(raid6_conf_t *conf)
{
/* device_lock is held */
struct list_head head;
@@ -1664,7 +1740,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
finish_wait(&conf->wait_for_overlap, &w);
raid6_plug_device(conf);
- handle_stripe(sh);
+ handle_stripe(sh, NULL);
release_stripe(sh);
} else {
/* cannot get stripe for read-ahead, just give-up */
@@ -1728,6 +1804,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return rv;
}
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
!conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
/* we can skip this block, and probably more */
sync_blocks /= STRIPE_SECTORS;
@@ -1765,7 +1842,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
clear_bit(STRIPE_INSYNC, &sh->state);
spin_unlock(&sh->lock);
- handle_stripe(sh);
+ handle_stripe(sh, NULL);
release_stripe(sh);
return STRIPE_SECTORS;
@@ -1821,7 +1898,7 @@ static void raid6d (mddev_t *mddev)
spin_unlock_irq(&conf->device_lock);
handled++;
- handle_stripe(sh);
+ handle_stripe(sh, conf->spare_page);
release_stripe(sh);
spin_lock_irq(&conf->device_lock);
@@ -1848,17 +1925,19 @@ static int run(mddev_t *mddev)
return -EIO;
}
- mddev->private = kmalloc (sizeof (raid6_conf_t)
- + mddev->raid_disks * sizeof(struct disk_info),
- GFP_KERNEL);
+ mddev->private = kzalloc(sizeof (raid6_conf_t)
+ + mddev->raid_disks * sizeof(struct disk_info),
+ GFP_KERNEL);
if ((conf = mddev->private) == NULL)
goto abort;
- memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) );
conf->mddev = mddev;
- if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL)
+ if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
+ goto abort;
+
+ conf->spare_page = alloc_page(GFP_KERNEL);
+ if (!conf->spare_page)
goto abort;
- memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
@@ -1929,13 +2008,18 @@ static int run(mddev_t *mddev)
goto abort;
}
-#if 0 /* FIX: For now */
if (mddev->degraded > 0 &&
mddev->recovery_cp != MaxSector) {
- printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev));
- goto abort;
+ if (mddev->ok_start_degraded)
+ printk(KERN_WARNING "raid6: starting dirty degraded array:%s"
+ "- data corruption possible.\n",
+ mdname(mddev));
+ else {
+ printk(KERN_ERR "raid6: cannot start dirty degraded array"
+ " for %s\n", mdname(mddev));
+ goto abort;
+ }
}
-#endif
{
mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
@@ -1977,7 +2061,7 @@ static int run(mddev_t *mddev)
*/
{
int stripe = (mddev->raid_disks-2) * mddev->chunk_size
- / PAGE_CACHE_SIZE;
+ / PAGE_SIZE;
if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
}
@@ -1985,18 +2069,14 @@ 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;
abort:
if (conf) {
print_raid6_conf(conf);
- if (conf->stripe_hashtbl)
- free_pages((unsigned long) conf->stripe_hashtbl,
- HASH_PAGES_ORDER);
+ safe_put_page(conf->spare_page);
+ kfree(conf->stripe_hashtbl);
kfree(conf);
}
mddev->private = NULL;
@@ -2013,7 +2093,7 @@ static int stop (mddev_t *mddev)
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
shrink_stripes(conf);
- free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
+ kfree(conf->stripe_hashtbl);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;
@@ -2040,12 +2120,13 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh)
static void printall (struct seq_file *seq, raid6_conf_t *conf)
{
struct stripe_head *sh;
+ struct hlist_node *hn;
int i;
spin_lock_irq(&conf->device_lock);
for (i = 0; i < NR_HASH; i++) {
sh = conf->stripe_hashtbl[i];
- for (; sh; sh = sh->hash_next) {
+ hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
if (sh->raid_conf != conf)
continue;
print_sh(seq, sh);
@@ -2223,17 +2304,12 @@ static void raid6_quiesce(mddev_t *mddev, int state)
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=
+
+static struct mdk_personality raid6_personality =
{
.name = "raid6",
+ .level = 6,
.owner = THIS_MODULE,
.make_request = make_request,
.run = run,
@@ -2248,7 +2324,7 @@ static mdk_personality_t raid6_personality=
.quiesce = raid6_quiesce,
};
-static int __init raid6_init (void)
+static int __init raid6_init(void)
{
int e;
@@ -2256,15 +2332,17 @@ static int __init raid6_init (void)
if ( e )
return e;
- return register_md_personality (RAID6, &raid6_personality);
+ return register_md_personality(&raid6_personality);
}
static void raid6_exit (void)
{
- unregister_md_personality (RAID6);
+ unregister_md_personality(&raid6_personality);
}
module_init(raid6_init);
module_exit(raid6_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("md-personality-8"); /* RAID6 */
+MODULE_ALIAS("md-raid6");
+MODULE_ALIAS("md-level-6");
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 2899d34e5f7e..04c1938b9c91 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -109,10 +109,9 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
struct page *pg;
int i;
- sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
@@ -306,15 +305,13 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
struct saa7146_dev *dev;
int err = -ENOMEM;
- dev = kmalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
+ /* clear out mem for sure */
+ dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
if (!dev) {
ERR(("out of memory.\n"));
goto out;
}
- /* clear out mem for sure */
- memset(dev, 0x0, sizeof(struct saa7146_dev));
-
DEB_EE(("pci:%p\n",pci));
err = pci_enable_device(pci);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 09ec964dec5c..f8cf73ed49ad 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -239,13 +239,12 @@ static int fops_open(struct inode *inode, struct file *file)
}
/* allocate per open data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh) {
DEB_S(("cannot allocate memory for per open data.\n"));
result = -ENOMEM;
goto out;
}
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
@@ -253,7 +252,10 @@ static int fops_open(struct inode *inode, struct file *file)
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
DEB_S(("initializing vbi...\n"));
- result = saa7146_vbi_uops.open(dev,file);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ result = saa7146_vbi_uops.open(dev,file);
+ if (dev->ext_vv_data->vbi_fops.open)
+ dev->ext_vv_data->vbi_fops.open(inode, file);
} else {
DEB_S(("initializing video...\n"));
result = saa7146_video_uops.open(dev,file);
@@ -289,7 +291,10 @@ static int fops_release(struct inode *inode, struct file *file)
return -ERESTARTSYS;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
- saa7146_vbi_uops.release(dev,file);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.release(dev,file);
+ if (dev->ext_vv_data->vbi_fops.release)
+ dev->ext_vv_data->vbi_fops.release(inode, file);
} else {
saa7146_video_uops.release(dev,file);
}
@@ -332,6 +337,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
BUG();
return 0;
}
+
return videobuf_mmap_mapper(q,vma);
}
@@ -381,7 +387,10 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
case V4L2_BUF_TYPE_VBI_CAPTURE: {
// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
- return saa7146_vbi_uops.read(file,data,count,ppos);
+ if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ return saa7146_vbi_uops.read(file,data,count,ppos);
+ else
+ return -EINVAL;
}
break;
default:
@@ -390,12 +399,31 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
}
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+
+ switch (fh->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return -EINVAL;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (fh->dev->ext_vv_data->vbi_fops.write)
+ return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+ else
+ return -EINVAL;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+}
+
static struct file_operations video_fops =
{
.owner = THIS_MODULE,
.open = fops_open,
.release = fops_release,
.read = fops_read,
+ .write = fops_write,
.poll = fops_poll,
.mmap = fops_mmap,
.ioctl = fops_ioctl,
@@ -435,12 +463,11 @@ static struct video_device device_template =
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
{
- struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
+ struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
if( NULL == vv ) {
ERR(("out of memory. aborting.\n"));
return -1;
}
- memset(vv, 0x0, sizeof(*vv));
DEB_EE(("dev:%p\n",dev));
@@ -467,7 +494,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
saa7146_video_uops.init(dev,vv);
- saa7146_vbi_uops.init(dev,vv);
+ if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+ saa7146_vbi_uops.init(dev,vv);
dev->vv_data = vv;
dev->vv_callback = &vv_callback;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index ec52dff8cb69..33bec8a6843b 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -562,19 +562,26 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
int b_depth = vv->ov_fmt->depth;
int b_bpl = vv->ov_fb.fmt.bytesperline;
- u32 base = (u32)vv->ov_fb.base;
+ /* The unsigned long cast is to remove a 64-bit compile warning since
+ it looks like a 64-bit address is cast to a 32-bit value, even
+ though the base pointer is really a 32-bit physical address that
+ goes into a 32-bit DMA register.
+ FIXME: might not work on some 64-bit platforms, but see the FIXME
+ in struct v4l2_framebuffer (videodev2.h) for that.
+ */
+ u32 base = (u32)(unsigned long)vv->ov_fb.base;
struct saa7146_video_dma vdma1;
/* calculate memory offsets for picture, look if we shall top-down-flip */
vdma1.pitch = 2*b_bpl;
if ( 0 == vv->vflip ) {
- vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
}
else {
- vdma1.base_even = (u32)base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+ vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
index 063986ec16b5..468d3c959075 100644
--- a/drivers/media/common/saa7146_vbi.c
+++ b/drivers/media/common/saa7146_vbi.c
@@ -500,9 +500,9 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
}
struct saa7146_use_ops saa7146_vbi_uops = {
- .init = vbi_init,
- .open = vbi_open,
+ .init = vbi_init,
+ .open = vbi_open,
.release = vbi_close,
.irq_done = vbi_irq_done,
- .read = vbi_read,
+ .read = vbi_read,
};
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 1d961023b837..7ebac7949df3 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -151,8 +151,8 @@ static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
if (V4L2_FIELD_ANY == field) {
field = (win->w.height > maxh/2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_TOP;
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_TOP;
}
switch (field) {
case V4L2_FIELD_TOP:
@@ -1114,10 +1114,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
}
case VIDIOC_OVERLAY:
-
-
-
-
{
int on = *(int *)arg;
int err = 0;
@@ -1359,7 +1355,6 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
-
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct file *file = q->priv_data;
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 21a9045b3ef6..0b940e152b79 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -298,7 +298,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
}
static int lgdt3303_pll_set(struct dvb_frontend* fe,
- struct dvb_frontend_parameters* params)
+ struct dvb_frontend_parameters* params)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
@@ -485,12 +485,16 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
/* try to figure out the frontend, each card/box can have on of the following list */
int flexcop_frontend_init(struct flexcop_device *fc)
{
+ struct dvb_frontend_ops *ops;
+
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY;
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
@@ -522,15 +526,17 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
- fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
- fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
- fc->fe->ops->set_tone = flexcop_set_tone;
- fc->fe->ops->set_voltage = flexcop_set_voltage;
+ ops = fc->fe->ops;
+
+ ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+ ops->diseqc_send_burst = flexcop_diseqc_send_burst;
+ ops->set_tone = flexcop_set_tone;
+ ops->set_voltage = flexcop_set_voltage;
- fc->fe_sleep = fc->fe->ops->sleep;
- fc->fe->ops->sleep = flexcop_sleep;
+ fc->fe_sleep = ops->sleep;
+ ops->sleep = flexcop_sleep;
- fc->dev_type = FC_SKY_OLD;
+ fc->dev_type = FC_SKY_OLD;
info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
}
@@ -540,8 +546,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
- if (fc->fe->ops->release != NULL)
- fc->fe->ops->release(fc->fe);
+ ops = fc->fe->ops;
+ if (ops->release != NULL)
+ ops->release(fc->fe);
fc->fe = NULL;
return -EINVAL;
}
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 23cc6431e2b8..3153f9513c63 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -39,11 +39,13 @@ extern const char *flexcop_device_names[];
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
-#elif defined(__BIG_ENDIAN)
+#else
+#if defined(__BIG_ENDIAN)
#include "flexcop_ibi_value_be.h"
#else
#error no endian defined
#endif
+#endif
#define fc_data_Tag_ID_DVB 0x3e
#define fc_data_Tag_ID_ATSC 0x3f
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 0a78ba3737a5..a6c91db40ad6 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -544,7 +544,6 @@ static struct usb_device_id flexcop_usb_table [] = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver flexcop_usb_driver = {
- .owner = THIS_MODULE,
.name = "b2c2_flexcop_usb",
.probe = flexcop_usb_probe,
.disconnect = flexcop_usb_disconnect,
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 123ed96f6faa..56ba52470676 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -220,20 +220,18 @@ EXPORT_SYMBOL(flexcop_reset_block_300);
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
{
void *bus;
- struct flexcop_device *fc = kmalloc(sizeof(struct flexcop_device), GFP_KERNEL);
+ struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), GFP_KERNEL);
if (!fc) {
err("no memory");
return NULL;
}
- memset(fc, 0, sizeof(struct flexcop_device));
- bus = kmalloc(bus_specific_len, GFP_KERNEL);
+ bus = kzalloc(bus_specific_len, GFP_KERNEL);
if (!bus) {
err("no memory");
kfree(fc);
return NULL;
}
- memset(bus, 0, bus_specific_len);
fc->bus_specific = bus;
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index f29571450038..a04bb61f21f4 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -542,7 +542,7 @@ static struct pci_driver bt878_pci_driver = {
.remove = bt878_remove,
};
-static int bt878_pci_driver_registered = 0;
+static int bt878_pci_driver_registered;
/*******************************/
/* Module management functions */
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 8977c7a313df..3a2ff1cc24b7 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1341,30 +1341,40 @@ 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,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
- dst_set_freq(state, p->frequency);
- dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+ if (p != NULL) {
+ dst_set_freq(state, p->frequency);
+ dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
- 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);
- dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
-
- } 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) {
- 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);
+ 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);
+ dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+ } 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) {
+ 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);
+ }
+ dst_write_tuna(fe);
}
- dst_write_tuna(fe);
+ if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+ dst_read_status(fe, status);
+
+ *delay = HZ/10;
return 0;
}
@@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release,
.init = dst_init,
- .set_frontend = dst_set_frontend,
+ .tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index 2239651969c8..c650b4bf7f5f 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -283,16 +283,17 @@ 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;
}
-
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) {
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index 77977e9c013e..ea27b15007e9 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -600,7 +600,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
struct dst_state* state = NULL;
switch(type) {
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
if (card->fe != NULL) {
@@ -608,22 +607,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->fe->ops->info.frequency_max = 862000000;
}
break;
-#endif
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
lgdt330x_reset(card);
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL)
dprintk ("dvb_bt8xx: lgdt330x detected\n");
break;
-#endif
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_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.
@@ -787,17 +779,15 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
return 0;
}
-static int dvb_bt8xx_probe(struct device *dev)
+static int dvb_bt8xx_probe(struct bttv_sub_device *sub)
{
- struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
struct dvb_bt8xx_card *card;
struct pci_dev* bttv_pci_dev;
int ret;
- if (!(card = kmalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
+ if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
return -ENOMEM;
- memset(card, 0, sizeof(*card));
init_MUTEX(&card->lock);
card->bttv_nr = sub->core->nr;
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name));
@@ -812,9 +802,7 @@ static int dvb_bt8xx_probe(struct device *dev)
card->irq_err_ignore = 0;
break;
-#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
-#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
@@ -823,19 +811,13 @@ static int dvb_bt8xx_probe(struct device *dev)
* DA_APP(parallel) */
break;
-#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
-#endif
card->gpio_mode = 0x0400c060;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
break;
-#ifdef BTTV_BOARD_TWINHAN_VP3021
- case BTTV_BOARD_TWINHAN_VP3021:
-#else
case BTTV_BOARD_NEBULA_DIGITV:
-#endif
case BTTV_BOARD_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;
@@ -907,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev)
return ret;
}
- dev_set_drvdata(dev, card);
+ dev_set_drvdata(&sub->dev, card);
return 0;
}
-static int dvb_bt8xx_remove(struct device *dev)
+static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
{
- struct dvb_bt8xx_card *card = dev_get_drvdata(dev);
+ struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
@@ -929,21 +911,19 @@ static int dvb_bt8xx_remove(struct device *dev)
dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
-
- return 0;
}
static struct bttv_sub_driver driver = {
.drv = {
.name = "dvb-bt8xx",
- .probe = dvb_bt8xx_probe,
- .remove = dvb_bt8xx_remove,
- /* FIXME:
- * .shutdown = dvb_bt8xx_shutdown,
- * .suspend = dvb_bt8xx_suspend,
- * .resume = dvb_bt8xx_resume,
- */
},
+ .probe = dvb_bt8xx_probe,
+ .remove = dvb_bt8xx_remove,
+ /* FIXME:
+ * .shutdown = dvb_bt8xx_shutdown,
+ * .suspend = dvb_bt8xx_suspend,
+ * .resume = dvb_bt8xx_resume,
+ */
};
static int __init dvb_bt8xx_init(void)
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 7cf4c4a888ec..6018fcdba1e6 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -21,35 +21,35 @@ config DVB_CINERGYT2_TUNING
config DVB_CINERGYT2_STREAM_URB_COUNT
int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
depends on DVB_CINERGYT2_TUNING
- default "32"
+ default "32"
help
USB Request Blocks for Highspeed Stream transfers are scheduled in
a queue for the Host Controller.
Usually the default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_STREAM_BUF_SIZE
int "Size of URB Stream Buffers for Highspeed Transfers"
depends on DVB_CINERGYT2_TUNING
- default "512"
+ default "512"
help
Should be a multiple of native buffer size of 512 bytes.
Default value is a safe choice.
- You may increase this number if you are using this device in a
- Server Environment with many high-traffic USB Highspeed devices
+ You may increase this number if you are using this device in a
+ Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_QUERY_INTERVAL
int "Status update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING
- default "250"
+ default "250"
help
This is the interval for status readouts from the demodulator.
You may try lower values if you need more responsive signal quality
@@ -64,9 +64,9 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
- default "yes"
+ default "yes"
help
- Enable this option if you want to use the onboard Infrared Remote
+ Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device.
Right now only the keycode table for the default Remote Control
@@ -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 "50"
+ 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 336fc284fa52..c4b4c5b6b7c8 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -60,7 +60,7 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk(level, args...) \
do { \
if ((debug & level)) { \
- printk("%s: %s(): ", __stringify(KBUILD_MODNAME), \
+ printk("%s: %s(): ", KBUILD_MODNAME, \
__FUNCTION__); \
printk(args); } \
} while (0)
@@ -131,6 +131,8 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
+ int disconnect_pending;
+ atomic_t inuse;
void *streambuf;
dma_addr_t streambuf_dmahandle;
@@ -343,7 +345,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (cinergyt2->streaming == 0)
@@ -359,7 +361,7 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (--cinergyt2->streaming == 0)
@@ -479,23 +481,37 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- int err;
+ int err = -ERESTARTSYS;
- if ((err = dvb_generic_open(inode, file)))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
+ if ((err = dvb_generic_open(inode, file))) {
+ up(&cinergyt2->sem);
return err;
+ }
- if (down_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
+ atomic_inc(&cinergyt2->inuse);
+
up(&cinergyt2->sem);
return 0;
}
+static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
+{
+ dvb_unregister_device(cinergyt2->fedev);
+ dvb_unregister_adapter(&cinergyt2->adapter);
+
+ cinergyt2_free_stream_urbs(cinergyt2);
+ kfree(cinergyt2);
+}
+
static int cinergyt2_release (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@@ -504,7 +520,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
- if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+ if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work);
flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
@@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
up(&cinergyt2->sem);
+ if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
+ warn("delayed unregister in release");
+ cinergyt2_unregister(cinergyt2);
+ }
+
return dvb_generic_release(inode, file);
}
@@ -519,7 +540,14 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
+
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
+ return -ERESTARTSYS;
+
poll_wait(file, &cinergyt2->poll_wq, wait);
+
+ up(&cinergyt2->sem);
+
return (POLLIN | POLLRDNORM | POLLPRI);
}
@@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
(__u16 __user *) arg);
case FE_READ_UNCORRECTED_BLOCKS:
- /* UNC are already converted to host byte order... */
- return put_user(stat->uncorrected_block_count,
- (__u32 __user *) arg);
+ {
+ uint32_t unc_count;
+
+ unc_count = stat->uncorrected_block_count;
+ stat->uncorrected_block_count = 0;
+ /* UNC are already converted to host byte order... */
+ return put_user(unc_count,(__u32 __user *) arg);
+ }
case FE_SET_FRONTEND:
{
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
@@ -580,7 +613,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
return -EFAULT;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
@@ -691,7 +724,7 @@ static void cinergyt2_query_rc (void *data)
struct cinergyt2_rc_event rc_events[12];
int n, len, i;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
@@ -786,7 +819,6 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
{
cancel_delayed_work(&cinergyt2->rc_query_work);
- flush_scheduled_work();
input_unregister_device(cinergyt2->rc_input_dev);
}
@@ -817,7 +849,7 @@ static void cinergyt2_query (void *data)
uint8_t lock_bits;
uint32_t unc;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
unc = s->uncorrected_block_count;
@@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
- return;
+ flush_scheduled_work();
cinergyt2_unregister_rc(cinergyt2);
+ cancel_delayed_work(&cinergyt2->query_work);
+ wake_up_interruptible(&cinergyt2->poll_wq);
+
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
- dvb_net_release(&cinergyt2->dvbnet);
- dvb_dmxdev_release(&cinergyt2->dmxdev);
- dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_device(cinergyt2->fedev);
- dvb_unregister_adapter(&cinergyt2->adapter);
+ cinergyt2->disconnect_pending = 1;
- cinergyt2_free_stream_urbs(cinergyt2);
- up(&cinergyt2->sem);
- kfree(cinergyt2);
+ if (!atomic_read(&cinergyt2->inuse))
+ cinergyt2_unregister(cinergyt2);
}
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (state.event > PM_EVENT_ON) {
@@ -961,7 +990,7 @@ static int cinergyt2_resume (struct usb_interface *intf)
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
- if (down_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (!cinergyt2->sleeping) {
@@ -986,7 +1015,6 @@ static const struct usb_device_id cinergyt2_table [] __devinitdata = {
MODULE_DEVICE_TABLE(usb, cinergyt2_table);
static struct usb_driver cinergyt2_driver = {
- .owner = THIS_MODULE,
.name = "cinergyT2",
.probe = cinergyt2_probe,
.disconnect = cinergyt2_disconnect,
@@ -1015,4 +1043,3 @@ module_exit (cinergyt2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
-
diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
index a9a7b3421048..12ee912a5705 100644
--- a/drivers/media/dvb/dvb-core/Kconfig
+++ b/drivers/media/dvb/dvb-core/Kconfig
@@ -5,7 +5,7 @@ config DVB_CORE
help
DVB core utility functions for device handling, software fallbacks etc.
Say Y when you have a DVB card and want to use it. Say Y if your want
- to build your drivers outside the kernel, but need the DVB core. All
+ to build your drivers outside the kernel, but need the DVB core. All
in-kernel drivers will select this automatically if needed.
If unsure say N.
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index c6baac20f529..7adb50c1e8eb 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -3,7 +3,7 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_frontend.o \
+ dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 5956c35d34ac..00347a750681 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1649,21 +1649,17 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
return -EINVAL;
/* initialise the system data */
- if ((ca =
- (struct dvb_ca_private *) kmalloc(sizeof(struct dvb_ca_private),
- GFP_KERNEL)) == NULL) {
+ if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto error;
}
- memset(ca, 0, sizeof(struct dvb_ca_private));
ca->pub = pubca;
ca->flags = flags;
ca->slot_count = slot_count;
- if ((ca->slot_info = kmalloc(sizeof(struct dvb_ca_slot) * slot_count, GFP_KERNEL)) == NULL) {
+ if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
ret = -ENOMEM;
goto error;
}
- memset(ca->slot_info, 0, sizeof(struct dvb_ca_slot) * slot_count);
init_waitqueue_head(&ca->wait_queue);
ca->thread_pid = 0;
init_waitqueue_head(&ca->thread_queue);
@@ -1745,9 +1741,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
- if (ca->slot_info[i].rx_buffer.data != NULL) {
- vfree(ca->slot_info[i].rx_buffer.data);
- }
+ vfree(ca->slot_info[i].rx_buffer.data);
}
kfree(ca->slot_info);
dvb_unregister_device(ca->dvbdev);
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
index c49fd0bd7181..772003fb1821 100644
--- a/drivers/media/dvb/dvb-core/dvb_filter.c
+++ b/drivers/media/dvb/dvb-core/dvb_filter.c
@@ -409,16 +409,16 @@ static u8 *skip_pes_header(u8 **bufp)
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
- pts = buf+9;
+ pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
- if (buf == inbuf + 6 + 16) {
- break;
- }
+ if (buf == inbuf + 6 + 16) {
+ break;
+ }
if ((*buf & 0xc0) == 0x40)
- buf += 2;
+ buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
@@ -529,9 +529,9 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
- | ( INIT_VERTICAL_SIZE << 8 )
- | ( INIT_ASPECT_RATIO << 4 )
- | ( INIT_FRAME_RATE );
+ | ( INIT_VERTICAL_SIZE << 8 )
+ | ( INIT_ASPECT_RATIO << 4 )
+ | ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 95ea5095e07e..771f32d889e6 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
+ /* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
@@ -100,20 +101,25 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
pid_t thread_pid;
unsigned long release_jiffies;
- int state;
- int bending;
- int lnb_drift;
- int inversion;
- int auto_step;
- int auto_sub_step;
- int started_auto_step;
- int min_delay;
- int max_drift;
- int step_size;
- int exit;
- int wakeup;
+ unsigned int exit;
+ unsigned int wakeup;
fe_status_t status;
- fe_sec_tone_mode_t tone;
+ unsigned long tune_mode_flags;
+ unsigned int delay;
+
+ /* swzigzag values */
+ unsigned int state;
+ unsigned int bending;
+ int lnb_drift;
+ unsigned int inversion;
+ unsigned int auto_step;
+ unsigned int auto_sub_step;
+ unsigned int started_auto_step;
+ unsigned int min_delay;
+ unsigned int max_drift;
+ unsigned int step_size;
+ int quality;
+ unsigned int check_wrapped;
};
@@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
-static void update_delay(int *quality, int *delay, int min_delay, int locked)
+static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
- int q2;
+ int q2;
- dprintk ("%s\n", __FUNCTION__);
+ dprintk ("%s\n", __FUNCTION__);
- if (locked)
- (*quality) = (*quality * 220 + 36*256) / 256;
- else
- (*quality) = (*quality * 220 + 0) / 256;
+ if (locked)
+ (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+ else
+ (fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
- q2 = *quality - 128;
- q2 *= q2;
+ q2 = fepriv->quality - 128;
+ q2 *= q2;
- *delay = min_delay + q2 * HZ / (128*128);
+ fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
}
/**
@@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked)
* @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed.
*/
-static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
+static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{
int autoinversion;
int ready = 0;
@@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
return 0;
}
+static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+{
+ fe_status_t s;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ /* if we've got no parameters, just keep idling */
+ if (fepriv->state & FESTATE_IDLE) {
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* in SCAN mode, we just set the frontend when asked and leave it alone */
+ if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
+ if (fepriv->state & FESTATE_RETUNE) {
+ if (fe->ops->set_frontend)
+ fe->ops->set_frontend(fe, &fepriv->parameters);
+ fepriv->state = FESTATE_TUNED;
+ }
+ fepriv->delay = 3*HZ;
+ fepriv->quality = 0;
+ return;
+ }
+
+ /* get the frontend status */
+ if (fepriv->state & FESTATE_RETUNE) {
+ s = 0;
+ } else {
+ if (fe->ops->read_status)
+ fe->ops->read_status(fe, &s);
+ if (s != fepriv->status) {
+ dvb_frontend_add_event(fe, s);
+ fepriv->status = s;
+ }
+ }
+
+ /* if we're not tuned, and we have a lock, move to the TUNED state */
+ if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ fepriv->state = FESTATE_TUNED;
+
+ /* if we're tuned, then we have determined the correct inversion */
+ if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+ (fepriv->parameters.inversion == INVERSION_AUTO)) {
+ fepriv->parameters.inversion = fepriv->inversion;
+ }
+ return;
+ }
+
+ /* if we are tuned already, check we're still locked */
+ if (fepriv->state & FESTATE_TUNED) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* we're tuned, and the lock is still good... */
+ if (s & FE_HAS_LOCK) {
+ return;
+ } else { /* if we _WERE_ tuned, but now don't have a lock */
+ fepriv->state = FESTATE_ZIGZAG_FAST;
+ fepriv->started_auto_step = fepriv->auto_step;
+ fepriv->check_wrapped = 0;
+ }
+ }
+
+ /* don't actually do anything if we're in the LOSTLOCK state,
+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+ if ((fepriv->state & FESTATE_LOSTLOCK) &&
+ (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* don't do anything if we're in the DISEQC state, since this
+ * might be someone with a motorized dish controlled by DISEQC.
+ * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
+ if (fepriv->state & FESTATE_DISEQC) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+ return;
+ }
+
+ /* if we're in the RETUNE state, set everything up for a brand
+ * new scan, keeping the current inversion setting, as the next
+ * tune is _very_ likely to require the same */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->lnb_drift = 0;
+ fepriv->auto_step = 0;
+ fepriv->auto_sub_step = 0;
+ fepriv->started_auto_step = 0;
+ fepriv->check_wrapped = 0;
+ }
+
+ /* fast zigzag. */
+ if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
+ fepriv->delay = fepriv->min_delay;
+
+ /* peform a tune */
+ if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
+ /* OK, if we've run out of trials at the fast speed.
+ * Drop back to slow for the _next_ attempt */
+ fepriv->state = FESTATE_SEARCHING_SLOW;
+ fepriv->started_auto_step = fepriv->auto_step;
+ return;
+ }
+ fepriv->check_wrapped = 1;
+
+ /* if we've just retuned, enter the ZIGZAG_FAST state.
+ * This ensures we cannot return from an
+ * FE_SET_FRONTEND ioctl before the first frontend tune
+ * occurs */
+ if (fepriv->state & FESTATE_RETUNE) {
+ fepriv->state = FESTATE_TUNING_FAST;
+ }
+ }
+
+ /* slow zigzag */
+ if (fepriv->state & FESTATE_SEARCHING_SLOW) {
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ /* Note: don't bother checking for wrapping; we stay in this
+ * state until we get a lock */
+ dvb_frontend_swzigzag_autotune(fe, 0);
+ }
+}
+
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
- dvb_shutdown_timeout * HZ))
+ dvb_shutdown_timeout * HZ))
return 1;
return 0;
@@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
wake_up_interruptible(&fepriv->wait_queue);
}
-/*
- * FIXME: use linux/kthread.h
- */
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
- int quality = 0, delay = 3*HZ;
fe_status_t s;
- int check_wrapped = 0;
+ struct dvb_frontend_parameters *params;
dprintk("%s\n", __FUNCTION__);
@@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data)
sigfillset(&current->blocked);
unlock_kernel();
+ fepriv->check_wrapped = 0;
+ fepriv->quality = 0;
+ fepriv->delay = 3*HZ;
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
@@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data)
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
- delay);
+ fepriv->delay);
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
@@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
- /* if we've got no parameters, just keep idling */
- if (fepriv->state & FESTATE_IDLE) {
- delay = 3*HZ;
- quality = 0;
- continue;
- }
+ /* do an iteration of the tuning loop */
+ if (fe->ops->tune) {
+ /* have we been asked to retune? */
+ params = NULL;
+ if (fepriv->state & FESTATE_RETUNE) {
+ params = &fepriv->parameters;
+ fepriv->state = FESTATE_TUNED;
+ }
- /* get the frontend status */
- if (fepriv->state & FESTATE_RETUNE) {
- s = 0;
- } else {
- if (fe->ops->read_status)
- fe->ops->read_status(fe, &s);
+ fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
- }
- /* if we're not tuned, and we have a lock, move to the TUNED state */
- if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- fepriv->state = FESTATE_TUNED;
-
- /* if we're tuned, then we have determined the correct inversion */
- if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters.inversion == INVERSION_AUTO)) {
- fepriv->parameters.inversion = fepriv->inversion;
- }
- continue;
- }
-
- /* if we are tuned already, check we're still locked */
- if (fepriv->state & FESTATE_TUNED) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* we're tuned, and the lock is still good... */
- if (s & FE_HAS_LOCK)
- continue;
- else { /* if we _WERE_ tuned, but now don't have a lock */
- fepriv->state = FESTATE_ZIGZAG_FAST;
- fepriv->started_auto_step = fepriv->auto_step;
- check_wrapped = 0;
- }
- }
-
- /* don't actually do anything if we're in the LOSTLOCK state,
- * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
- if ((fepriv->state & FESTATE_LOSTLOCK) &&
- (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* don't do anything if we're in the DISEQC state, since this
- * might be someone with a motorized dish controlled by DISEQC.
- * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
- if (fepriv->state & FESTATE_DISEQC) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
- continue;
- }
-
- /* if we're in the RETUNE state, set everything up for a brand
- * new scan, keeping the current inversion setting, as the next
- * tune is _very_ likely to require the same */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->lnb_drift = 0;
- fepriv->auto_step = 0;
- fepriv->auto_sub_step = 0;
- fepriv->started_auto_step = 0;
- check_wrapped = 0;
- }
-
- /* fast zigzag. */
- if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
- delay = fepriv->min_delay;
-
- /* peform a tune */
- if (dvb_frontend_autotune(fe, check_wrapped)) {
- /* OK, if we've run out of trials at the fast speed.
- * Drop back to slow for the _next_ attempt */
- fepriv->state = FESTATE_SEARCHING_SLOW;
- fepriv->started_auto_step = fepriv->auto_step;
- continue;
- }
- check_wrapped = 1;
-
- /* if we've just retuned, enter the ZIGZAG_FAST state.
- * This ensures we cannot return from an
- * FE_SET_FRONTEND ioctl before the first frontend tune
- * occurs */
- if (fepriv->state & FESTATE_RETUNE) {
- fepriv->state = FESTATE_TUNING_FAST;
- }
- }
-
- /* slow zigzag */
- if (fepriv->state & FESTATE_SEARCHING_SLOW) {
- update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
-
- /* Note: don't bother checking for wrapping; we stay in this
- * state until we get a lock */
- dvb_frontend_autotune(fe, 0);
+ } else {
+ dvb_frontend_swzigzag(fe);
}
}
@@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
- fepriv->tone = (fe_sec_tone_mode_t) parg;
}
break;
@@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_DISHNETWORK_SEND_LEGACY_CMD:
if (fe->ops->dishnetwork_send_legacy_command) {
- err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
+ err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} else if (fe->ops->set_voltage) {
@@ -767,13 +808,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
- unsigned int cmd = ((unsigned int) parg) << 1;
+ unsigned long cmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
- printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
+ printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@@ -814,7 +855,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops->enable_high_lnb_voltage)
- err = fe->ops->enable_high_lnb_voltage(fe, (int) parg);
+ err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
break;
case FE_SET_FRONTEND: {
@@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
}
break;
+
+ case FE_SET_FRONTEND_TUNE_MODE:
+ fepriv->tune_mode_flags = (unsigned long) parg;
+ break;
};
up (&fepriv->sem);
@@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
+
+ /* normal tune mode when opened R/W */
+ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
}
return ret;
@@ -976,13 +1024,12 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
if (down_interruptible (&frontend_mutex))
return -ERESTARTSYS;
- fe->frontend_priv = kmalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
+ fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
if (fe->frontend_priv == NULL) {
up(&frontend_mutex);
return -ENOMEM;
}
fepriv = fe->frontend_priv;
- memset(fe->frontend_priv, 0, sizeof(struct dvb_frontend_private));
init_MUTEX (&fepriv->sem);
init_waitqueue_head (&fepriv->wait_queue);
@@ -990,7 +1037,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->events.sem);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
- fepriv->tone = SEC_TONE_OFF;
printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num,
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 1e0840d02f1f..70a6d14efda7 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -58,10 +58,19 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
+ /* if this is set, it overrides the default swzigzag */
+ int (*tune)(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ unsigned int mode_flags,
+ int *delay,
+ fe_status_t *status);
+
+ /* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
- int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
+ int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
@@ -74,8 +83,9 @@ struct dvb_frontend_ops {
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
- int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
+ int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
+ int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
};
#define MAX_EVENT 8
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 86bba81e851e..6711eb6a058c 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -1222,7 +1222,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
return if_num;
}
-static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
+static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
{
struct net_device *net = dvbnet->device[num];
struct dvb_net_priv *priv;
@@ -1296,9 +1296,9 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)
+ if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
return -EINVAL;
- ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);
+ ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
if (!ret)
module_put(dvbdev->adapter->module);
return ret;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 283c6e9339a4..77ad2410f4d3 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -112,10 +112,10 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+rbuf->pread, split);
+ memcpy(buf, rbuf->data+rbuf->pread, split);
else
- if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+ return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
@@ -124,7 +124,7 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
memcpy(buf, rbuf->data+rbuf->pread, todo);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
- return -EFAULT;
+ return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
@@ -167,7 +167,7 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem)
+ int offset, u8* buf, size_t len, int usermem)
{
size_t todo;
size_t split;
@@ -183,10 +183,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
if (!usermem)
- memcpy(buf, rbuf->data+idx, split);
+ memcpy(buf, rbuf->data+idx, split);
else
- if (copy_to_user(buf, rbuf->data+idx, split))
- return -EFAULT;
+ if (copy_to_user(buf, rbuf->data+idx, split))
+ return -EFAULT;
buf += split;
todo -= split;
idx = 0;
@@ -195,7 +195,7 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
memcpy(buf, rbuf->data+idx, todo);
else
if (copy_to_user(buf, rbuf->data+idx, todo))
- return -EFAULT;
+ return -EFAULT;
return len;
}
@@ -209,12 +209,12 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
- pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
- pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
- DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
+ pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
+ pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
+ DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
} else {
- // first packet is not disposed, so we stop cleaning now
- break;
+ // first packet is not disposed, so we stop cleaning now
+ break;
}
}
}
@@ -242,8 +242,8 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
if (curpktstatus == PKT_READY) {
- *pktlen = curpktlen;
- return idx;
+ *pktlen = curpktlen;
+ return idx;
}
consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index fa476f662f82..6d2560972771 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -106,7 +106,7 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
- size_t len, int usermem);
+ size_t len, int usermem);
/* write routines & macros */
@@ -121,7 +121,7 @@ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
- size_t len);
+ size_t len);
/**
@@ -133,7 +133,7 @@ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
- size_t len);
+ size_t len);
/**
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
@@ -149,7 +149,7 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* returns Number of bytes read, or -EFAULT.
*/
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
- int offset, u8* buf, size_t len, int usermem);
+ int offset, u8* buf, size_t len, int usermem);
/**
* Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index a4aee8665854..54f8b95717b0 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -33,7 +33,7 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
-
+#include <linux/mutex.h>
#include "dvbdev.h"
static int dvbdev_debug;
@@ -44,7 +44,7 @@ MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
#define dprintk if (dvbdev_debug) printk
static LIST_HEAD(dvb_adapter_list);
-static DECLARE_MUTEX(dvbdev_register_lock);
+static DEFINE_MUTEX(dvbdev_register_lock);
static const char * const dnames[] = {
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
@@ -92,10 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
if(file->f_op->open)
- err = file->f_op->open(inode,file);
+ err = file->f_op->open(inode,file);
if (err) {
- fops_put(file->f_op);
- file->f_op = fops_get(old_fops);
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
@@ -202,11 +202,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
struct dvb_device *dvbdev;
int id;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((id = dvbdev_get_free_id (adap, type)) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
*pdvbdev = NULL;
printk ("%s: could get find free device id...\n", __FUNCTION__);
return -ENFILE;
@@ -215,11 +215,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
if (!dvbdev) {
- up(&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENOMEM;
}
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
memcpy(dvbdev, template, sizeof(struct dvb_device));
dvbdev->type = type;
@@ -289,11 +289,11 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
{
int num;
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
if ((num = dvbdev_get_free_adapter_num ()) < 0) {
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return -ENFILE;
}
@@ -309,7 +309,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
list_add_tail (&adap->list_head, &dvb_adapter_list);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return num;
}
@@ -320,10 +320,10 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
{
devfs_remove("dvb/adapter%d", adap->num);
- if (down_interruptible (&dvbdev_register_lock))
+ if (mutex_lock_interruptible(&dvbdev_register_lock))
return -ERESTARTSYS;
list_del (&adap->list_head);
- up (&dvbdev_register_lock);
+ mutex_unlock(&dvbdev_register_lock);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
@@ -356,18 +356,18 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
- parg = sbuf;
+ parg = sbuf;
} else {
- /* too big to allocate from stack */
- mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
- if (NULL == mbuf)
- return -ENOMEM;
- parg = mbuf;
+ /* too big to allocate from stack */
+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+ if (NULL == mbuf)
+ return -ENOMEM;
+ parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
- goto out;
+ goto out;
break;
}
@@ -384,7 +384,7 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
- err = -EFAULT;
+ err = -EFAULT;
break;
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 0cc6e4a0e27c..74ed5853f0fb 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -97,7 +97,7 @@ we simply define out own dvb_usercopy(), which will hopefully become
generic_usercopy() someday... */
extern int dvb_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
+ unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 54e2b29076b1..90a69d343b79 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
Devices supported by this driver:
- TwinhanDTV USB-Ter (VP7041)
- TwinhanDTV Magic Box (VP7041e)
- KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
- Hama DVB-T USB1.1-Box
- DiBcom USB1.1 reference devices (non-public)
- Ultima Electronic/Artec T1 USB TVBOX
+ Artec T1 USB1.1 boxes
+ Avermedia AverTV DVBT USB1.1
Compro Videomate DVB-U2000 - DVB-T USB
+ DiBcom USB1.1 reference devices (non-public)
Grandtec DVB-T USB
- Avermedia AverTV DVBT USB1.1
- Artec T1 USB1.1 boxes
+ Hama DVB-T USB1.1-Box
+ KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+ TwinhanDTV Magic Box (VP7041e)
+ TwinhanDTV USB-Ter (VP7041)
+ Ultima Electronic/Artec T1 USB TVBOX
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
@@ -54,6 +54,12 @@ config DVB_USB_DIBUSB_MB
Say Y if you own such a device and want to use it. You should build it as
a module.
+config DVB_USB_DIBUSB_MB_FAULTY
+ bool "Support faulty USB IDs"
+ depends on DVB_USB_DIBUSB_MB
+ help
+ Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
+
config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB
@@ -63,8 +69,8 @@ config DVB_USB_DIBUSB_MC
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
Devices supported by this driver:
- DiBcom USB2.0 reference devices (non-public)
Artec T1 USB2.0 boxes
+ DiBcom USB2.0 reference devices (non-public)
Say Y if you own such a device and want to use it. You should build it as
a module.
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index 8c7beffb045f..ce44aa6bbb83 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -144,7 +144,6 @@ static struct dvb_usb_properties a800_properties = {
};
static struct usb_driver a800_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_a800",
.probe = a800_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 3fe383f4bb4c..a7fb06f4cd34 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -11,10 +11,11 @@
* design, so it can be reused for the "analogue-only" device (if it will
* appear at all).
*
- * TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
- * part
+ * TODO: Use the cx25840-driver for the analogue part
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
+ * Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -25,6 +26,9 @@
#include "cxusb.h"
#include "cx22702.h"
+#include "lgdt330x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
/* debug */
int dvb_usb_cxusb_debug;
@@ -156,6 +160,119 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
+static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ u8 ircode[4];
+ int i;
+
+ cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
+
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ if (keymap[i].custom == ircode[2] &&
+ keymap[i].data == ircode[3]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
+ { 0xfe, 0x02, KEY_TV },
+ { 0xfe, 0x0e, KEY_MP3 },
+ { 0xfe, 0x1a, KEY_DVD },
+ { 0xfe, 0x1e, KEY_FAVORITES },
+ { 0xfe, 0x16, KEY_SETUP },
+ { 0xfe, 0x46, KEY_POWER2 },
+ { 0xfe, 0x0a, KEY_EPG },
+ { 0xfe, 0x49, KEY_BACK },
+ { 0xfe, 0x4d, KEY_MENU },
+ { 0xfe, 0x51, KEY_UP },
+ { 0xfe, 0x5b, KEY_LEFT },
+ { 0xfe, 0x5f, KEY_RIGHT },
+ { 0xfe, 0x53, KEY_DOWN },
+ { 0xfe, 0x5e, KEY_OK },
+ { 0xfe, 0x59, KEY_INFO },
+ { 0xfe, 0x55, KEY_TAB },
+ { 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */
+ { 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */
+ { 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */
+ { 0xfe, 0x15, KEY_VOLUMEUP },
+ { 0xfe, 0x05, KEY_VOLUMEDOWN },
+ { 0xfe, 0x11, KEY_CHANNELUP },
+ { 0xfe, 0x09, KEY_CHANNELDOWN },
+ { 0xfe, 0x52, KEY_CAMERA },
+ { 0xfe, 0x5a, KEY_TUNER }, /* Live */
+ { 0xfe, 0x19, KEY_OPEN },
+ { 0xfe, 0x0b, KEY_1 },
+ { 0xfe, 0x17, KEY_2 },
+ { 0xfe, 0x1b, KEY_3 },
+ { 0xfe, 0x07, KEY_4 },
+ { 0xfe, 0x50, KEY_5 },
+ { 0xfe, 0x54, KEY_6 },
+ { 0xfe, 0x48, KEY_7 },
+ { 0xfe, 0x4c, KEY_8 },
+ { 0xfe, 0x58, KEY_9 },
+ { 0xfe, 0x13, KEY_ANGLE }, /* Aspect */
+ { 0xfe, 0x03, KEY_0 },
+ { 0xfe, 0x1f, KEY_ZOOM },
+ { 0xfe, 0x43, KEY_REWIND },
+ { 0xfe, 0x47, KEY_PLAYPAUSE },
+ { 0xfe, 0x4f, KEY_FASTFORWARD },
+ { 0xfe, 0x57, KEY_MUTE },
+ { 0xfe, 0x0d, KEY_STOP },
+ { 0xfe, 0x01, KEY_RECORD },
+ { 0xfe, 0x4e, KEY_POWER },
+};
+
+static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
+{ /* used in both lgz201 and th7579 */
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+ return 0;
+}
+
struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
@@ -165,17 +282,68 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
+struct lgdt330x_config cxusb_lgdt330x_config = {
+ .demod_address = 0x0e,
+ .demod_chip = LGDT3303,
+ .pll_set = dvb_usb_pll_set_i2c,
+};
+
+struct mt352_config cxusb_dee1601_config = {
+ .demod_address = 0x0f,
+ .demod_init = cxusb_dee1601_demod_init,
+ .pll_set = dvb_usb_pll_set,
+};
+
+struct mt352_config cxusb_mt352_config = {
+ /* used in both lgz201 and th7579 */
+ .demod_address = 0x0f,
+ .demod_init = cxusb_mt352_demod_init,
+ .pll_set = dvb_usb_pll_set,
+};
+
/* Callbacks for DVB USB */
-static int cxusb_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
{
u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
d->pll_addr = 0x61;
- memcpy(d->pll_init,bpll,4);
+ memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_fmd1216me;
return 0;
}
-static int cxusb_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
+{
+ u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
+ /* bpll[2] : unset bit 3, set bits 4&5
+ bpll[3] : 0x50 - digital, 0x20 - analog */
+ d->pll_addr = 0x61;
+ memcpy(d->pll_init, bpll, 4);
+ d->pll_desc = &dvb_pll_tdvs_tua6034;
+ return 0;
+}
+
+static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_thomson_dtt7579;
+ return 0;
+}
+
+static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_lg_z201;
+ return 0;
+}
+
+static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x60;
+ d->pll_desc = &dvb_pll_thomson_dtt7579;
+ return 0;
+}
+
+static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
{
u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
@@ -189,22 +357,107 @@ static int cxusb_frontend_attach(struct dvb_usb_device *d)
return -EIO;
}
+static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,7) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
+{ /* used in both lgz201 and th7579 */
+ if (usb_set_interface(d->udev,0,0) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
+{
+ if (usb_set_interface(d->udev,0,0) < 0)
+ err("set interface failed");
+
+ cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+
+ if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+ return 0;
+
+ return -EIO;
+}
+
+/*
+ * DViCO bluebird firmware needs the "warm" product ID to be patched into the
+ * firmware file before download.
+ */
+
+#define BLUEBIRD_01_ID_OFFSET 6638
+static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
+{
+ if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
+ return -EINVAL;
+
+ if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
+ fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
+
+ /* FIXME: are we allowed to change the fw-data ? */
+ fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
+ fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
+
+ return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
+ }
+
+ return -EINVAL;
+}
+
/* DVB USB Driver stuff */
-static struct dvb_usb_properties cxusb_properties;
+static struct dvb_usb_properties cxusb_medion_properties;
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
+static struct dvb_usb_properties cxusb_bluebird_lgz201_properties;
+static struct dvb_usb_properties cxusb_bluebird_dtt7579_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,NULL);
+ if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
+ dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
+ return 0;
+ }
+
+ return -EINVAL;
}
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD) },
+ { USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
-static struct dvb_usb_properties cxusb_properties = {
+static struct dvb_usb_properties cxusb_medion_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
@@ -213,8 +466,8 @@ static struct dvb_usb_properties cxusb_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
- .frontend_attach = cxusb_frontend_attach,
- .tuner_attach = cxusb_tuner_attach,
+ .frontend_attach = cxusb_cx22702_frontend_attach,
+ .tuner_attach = cxusb_fmd1216me_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
@@ -240,8 +493,176 @@ static struct dvb_usb_properties cxusb_properties = {
}
};
+static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_lgdt330x_frontend_attach,
+ .tuner_attach = cxusb_lgh064f_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV5 USB Gold",
+ { &cxusb_table[1], NULL },
+ { &cxusb_table[2], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_dee1601_frontend_attach,
+ .tuner_attach = cxusb_dee1601_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .rc_interval = 150,
+ .rc_key_map = dvico_mce_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
+ .rc_query = cxusb_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T Dual USB",
+ { &cxusb_table[3], NULL },
+ { &cxusb_table[4], NULL },
+ },
+ { "DigitalNow DVB-T Dual USB",
+ { &cxusb_table[9], NULL },
+ { &cxusb_table[10], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_lgz201_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T USB (LGZ201)",
+ { &cxusb_table[5], NULL },
+ { &cxusb_table[6], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = DEVICE_SPECIFIC,
+ .firmware = "dvb-usb-bluebird-01.fw",
+ .download_firmware = bluebird_patch_dvico_firmware_download,
+ /* use usb alt setting 0 for EP4 transfer (dvb-t),
+ use usb alt setting 7 for EP2 transfer (atsc) */
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ .power_ctrl = cxusb_power_ctrl,
+ .frontend_attach = cxusb_mt352_frontend_attach,
+ .tuner_attach = cxusb_dtt7579_tuner_attach,
+
+ .i2c_algo = &cxusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 5,
+ .endpoint = 0x04,
+ .u = {
+ .bulk = {
+ .buffersize = 8192,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "DViCO FusionHDTV DVB-T USB (TH7579)",
+ { &cxusb_table[7], NULL },
+ { &cxusb_table[8], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
.disconnect = dvb_usb_device_exit,
@@ -270,6 +691,8 @@ module_init (cxusb_module_init);
module_exit (cxusb_module_exit);
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
MODULE_VERSION("1.0-alpha");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 135c2a81f581..087c99427853 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
#define CMD_STREAMING_ON 0x36
#define CMD_STREAMING_OFF 0x37
+#define CMD_GET_IR_CODE 0x47
+
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index aa271a2496d5..dd5a13195886 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -65,11 +65,11 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
if (b2[0] == 0xfe) {
- info("this device has the Thomson Cable onboard. Which is default.");
+ info("This device has the Thomson Cable onboard. Which is default.");
dibusb_thomson_tuner_attach(d);
} else {
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
- info("this device has the Panasonic ENV77H11D5 onboard.");
+ info("This device has the Panasonic ENV77H11D5 onboard.");
d->pll_addr = 0x60;
memcpy(d->pll_init,bpll,4);
d->pll_desc = &dvb_pll_tda665x;
@@ -98,15 +98,15 @@ static int dibusb_probe(struct usb_interface *intf,
/* do not change the order of the ID table */
static struct usb_device_id dibusb_dib3000mb_table [] = {
-/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) },
/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
-/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
-/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
+/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
@@ -117,27 +117,34 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
-/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
-/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
-/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
-/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
-/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
+/* 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) },
-/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
+/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
-// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+/*
+ * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices
+ * we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that
+ * have been left on the device. If you don't have such a device but an Artec
+ * device that's supposed to work with this driver but is not detected by it,
+ * free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config.
+ */
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
+
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
@@ -257,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
}
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
.num_device_descs = 2,
#else
.num_device_descs = 1,
@@ -267,11 +274,12 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
{ &dibusb_dib3000mb_table[20], NULL },
{ &dibusb_dib3000mb_table[21], NULL },
},
-#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
+#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
{ &dibusb_dib3000mb_table[30], NULL },
{ NULL },
},
+ { NULL },
#endif
}
};
@@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
{ &dibusb_dib3000mb_table[27], NULL },
{ NULL }
},
+ { NULL },
}
};
@@ -369,11 +378,11 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
{ &dibusb_dib3000mb_table[28], NULL },
{ &dibusb_dib3000mb_table[29], NULL },
},
+ { NULL },
}
};
static struct usb_driver dibusb_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_dibusb_mb",
.probe = dibusb_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index 6a0912eab396..55802fba3c29 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -82,7 +82,6 @@ static struct dvb_usb_properties dibusb_mc_properties = {
};
static struct usb_driver dibusb_mc_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_dibusb_mc",
.probe = dibusb_mc_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f98e306a5759..e6c55c9c9417 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -32,7 +32,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen;
- if (!wo) {
+ if (wo) {
memcpy(&sndbuf[3],wbuf,wlen);
dvb_usb_generic_write(d,sndbuf,7);
} else {
@@ -233,7 +233,6 @@ static struct dvb_usb_properties digitv_properties = {
};
static struct usb_driver digitv_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_digitv",
.probe = digitv_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index 0a94ec22aeb8..cd21ddbfd054 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -156,10 +156,9 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
struct dtt200u_fe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dtt200u_fe_state));
deb_info("attaching frontend dtt200u\n");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index b595476332cd..130ea7f21f5e 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
- { NULL },
+ { 0 },
}
};
@@ -160,7 +160,7 @@ static struct dvb_usb_properties wt220u_properties = {
.pid_filter_count = 15,
.usb_ctrl = CYPRESS_FX2,
- .firmware = "dvb-usb-wt220u-01.fw",
+ .firmware = "dvb-usb-wt220u-02.fw",
.power_ctrl = dtt200u_power_ctrl,
.streaming_ctrl = dtt200u_streaming_ctrl,
@@ -192,13 +192,12 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver dtt200u_usb_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_dtt200u",
.probe = dtt200u_usb_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
index 6f1f3042e21a..005b0a7df358 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.h
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -13,6 +13,7 @@
#define _DVB_USB_DTT200U_H_
#define DVB_USB_LOG_PREFIX "dtt200u"
+
#include "dvb-usb.h"
extern int dvb_usb_dtt200u_debug;
@@ -25,15 +26,15 @@ extern int dvb_usb_dtt200u_debug;
* 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
*/
-#define GET_SPEED 0x00
-#define GET_TUNE_STATUS 0x81
-#define GET_RC_CODE 0x84
-#define GET_CONFIGURATION 0x88
-#define GET_AGC 0x89
-#define GET_SNR 0x8a
-#define GET_VIT_ERR_CNT 0x8c
-#define GET_RS_ERR_CNT 0x8d
-#define GET_RS_UNCOR_BLK_CNT 0x8e
+#define GET_SPEED 0x00
+#define GET_TUNE_STATUS 0x81
+#define GET_RC_CODE 0x84
+#define GET_CONFIGURATION 0x88
+#define GET_AGC 0x89
+#define GET_SNR 0x8a
+#define GET_VIT_ERR_CNT 0x8c
+#define GET_RS_ERR_CNT 0x8d
+#define GET_RS_UNCOR_BLK_CNT 0x8e
/* write
* 01 - init
@@ -44,12 +45,12 @@ extern int dvb_usb_dtt200u_debug;
* 08 - transfer switch
*/
-#define SET_INIT 0x01
-#define SET_RF_FREQ 0x02
-#define SET_BANDWIDTH 0x03
-#define SET_PID_FILTER 0x04
-#define RESET_PID_FILTER 0x05
-#define SET_STREAMING 0x08
+#define SET_INIT 0x01
+#define SET_RF_FREQ 0x02
+#define SET_BANDWIDTH 0x03
+#define SET_PID_FILTER 0x04
+#define RESET_PID_FILTER 0x05
+#define SET_STREAMING 0x08
extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
index 7300489d3e24..a3460bf2d9fa 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling;
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
/* commonly used methods */
-extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
+extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *);
extern int dvb_usb_urb_submit(struct dvb_usb_device *);
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 5244e39770a0..8535895819fb 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -9,7 +9,6 @@
*/
#include "dvb-usb-common.h"
-#include <linux/firmware.h>
#include <linux/usb.h>
struct usb_cypress_controller {
@@ -19,9 +18,10 @@ struct usb_cypress_controller {
};
static struct usb_cypress_controller cypress[] = {
- { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
- { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
+ { .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
+ { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
/*
@@ -30,71 +30,117 @@ static struct usb_cypress_controller cypress[] = {
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
{
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+ 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
}
-int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
+int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
{
- const struct firmware *fw = NULL;
- u16 addr;
- u8 *b,*p;
- int ret = 0,i;
+ struct hexline hx;
+ u8 reset;
+ int ret,pos=0;
- if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
- err("did not find the firmware file. (%s) "
- "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
- filename);
+ /* stop the CPU */
+ reset = 1;
+ if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+ err("could not stop the USB controller CPU.");
+
+ while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
+ deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
+ ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
+
+ if (ret != hx.len) {
+ err("error while transferring firmware "
+ "(transferred size: %d, block size: %d)",
+ ret,hx.len);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ if (ret < 0) {
+ err("firmware download failed at %d with %d",pos,ret);
return ret;
}
- info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
-
- p = kmalloc(fw->size,GFP_KERNEL);
- if (p != NULL) {
- u8 reset;
- /*
- * you cannot use the fw->data as buffer for
- * usb_control_msg, a new buffer has to be
- * created
- */
- memcpy(p,fw->data,fw->size);
-
- /* stop the CPU */
- reset = 1;
- if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
- err("could not stop the USB controller CPU.");
- for(i = 0; p[i+3] == 0 && i < fw->size; ) {
- b = (u8 *) &p[i];
- addr = cpu_to_le16( *((u16 *) &b[1]) );
-
- deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
-
- ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
-
- if (ret != b[0]) {
- err("error while transferring firmware "
- "(transferred size: %d, block size: %d)",
- ret,b[0]);
- ret = -EINVAL;
- break;
- }
- i += 5 + b[0];
- }
- /* length in ret */
- if (ret > 0)
- ret = 0;
+ if (ret == 0) {
/* restart the CPU */
reset = 0;
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
+ } else
+ ret = -EIO;
- kfree(p);
- } else {
- ret = -ENOMEM;
+ return ret;
+}
+EXPORT_SYMBOL(usb_cypress_load_firmware);
+
+int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
+{
+ int ret;
+ const struct firmware *fw = NULL;
+
+ if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ props->firmware,ret);
+ return ret;
}
- release_firmware(fw);
+ info("downloading firmware from file '%s'",props->firmware);
+
+ switch (props->usb_ctrl) {
+ case CYPRESS_AN2135:
+ case CYPRESS_AN2235:
+ case CYPRESS_FX2:
+ ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl);
+ break;
+ case DEVICE_SPECIFIC:
+ if (props->download_firmware)
+ ret = props->download_firmware(udev,fw);
+ else {
+ err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
+ ret = -EINVAL;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ release_firmware(fw);
return ret;
}
+
+int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
+{
+ u8 *b = (u8 *) &fw->data[*pos];
+ int data_offs = 4;
+ if (*pos >= fw->size)
+ return 0;
+
+ memset(hx,0,sizeof(struct hexline));
+
+ hx->len = b[0];
+
+ if ((*pos + hx->len + 4) >= fw->size)
+ return -EINVAL;
+
+ hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
+ hx->type = b[3];
+
+ if (hx->type == 0x04) {
+ /* b[4] and b[5] are the Extended linear address record data field */
+ hx->addr |= (b[4] << 24) | (b[5] << 16);
+/* hx->len -= 2;
+ data_offs += 2; */
+ }
+ memcpy(hx->data,&b[data_offs],hx->len);
+ hx->chk = b[hx->len + data_offs];
+
+ *pos += hx->len + 5;
+
+ return *pos;
+}
+EXPORT_SYMBOL(dvb_usb_get_hexline);
+
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index da970947dfc7..9b254532af4d 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -52,9 +52,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
int ret = 0;
- /* if there is nothing to initialize */
- if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
- d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
+ /* if pll_desc is not used */
+ if (d->pll_desc == NULL)
return 0;
if (d->tuner_pass_ctrl)
@@ -80,6 +79,9 @@ int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep
{
struct dvb_usb_device *d = fe->dvb->priv;
+ if (d->pll_desc == NULL)
+ return 0;
+
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
b[0] = d->pll_addr << 1;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 6be99e537e12..4a1b9e77e339 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -86,11 +86,17 @@
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
#define USB_PID_NEBULA_DIGITV 0x0201
-#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
-#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
-#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
-#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
+#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10
+#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD 0xdb50
+#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM 0xdb51
+#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD 0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index dd8e0b94edba..716f8bf528cd 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -138,6 +138,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
int ret = -ENOMEM,cold=0;
+ if (du != NULL)
+ *du = NULL;
+
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
return -ENODEV;
@@ -145,38 +148,38 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
if (cold) {
info("found a '%s' in cold state, will try to load a firmware",desc->name);
- ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
- } else {
- info("found a '%s' in warm state.",desc->name);
- d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
- if (d == NULL) {
- err("no memory for 'struct dvb_usb_device'");
+ ret = dvb_usb_download_firmware(udev,props);
+ if (!props->no_reconnect)
return ret;
+ }
+
+ info("found a '%s' in warm state.",desc->name);
+ d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+ if (d == NULL) {
+ err("no memory for 'struct dvb_usb_device'");
+ return ret;
+ }
+
+ d->udev = udev;
+ memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+ d->desc = desc;
+ d->owner = owner;
+
+ if (d->props.size_of_priv > 0) {
+ d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
+ if (d->priv == NULL) {
+ err("no memory for priv in 'struct dvb_usb_device'");
+ kfree(d);
+ return -ENOMEM;
}
- memset(d,0,sizeof(struct dvb_usb_device));
-
- d->udev = udev;
- memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
- d->desc = desc;
- d->owner = owner;
-
- if (d->props.size_of_priv > 0) {
- d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
- if (d->priv == NULL) {
- err("no memory for priv in 'struct dvb_usb_device'");
- kfree(d);
- return -ENOMEM;
- }
- memset(d->priv,0,d->props.size_of_priv);
- }
+ }
- usb_set_intfdata(intf, d);
+ usb_set_intfdata(intf, d);
- if (du != NULL)
- *du = d;
+ if (du != NULL)
+ *du = d;
- ret = dvb_usb_init(d);
- }
+ ret = dvb_usb_init(d);
if (ret == 0)
info("%s successfully initialized and connected.",desc->name);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 36b7048c02d2..ee821974dc60 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -175,15 +175,13 @@ static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, un
deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
- if ((d->buf_list = kmalloc(num*sizeof(u8 *), GFP_ATOMIC)) == NULL)
+ if ((d->buf_list = kcalloc(num, sizeof(u8 *), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- if ((d->dma_addr = kmalloc(num*sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
+ if ((d->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
kfree(d->buf_list);
return -ENOMEM;
}
- memset(d->buf_list,0,num*sizeof(u8 *));
- memset(d->dma_addr,0,num*sizeof(dma_addr_t));
d->state |= DVB_USB_STATE_URB_BUF;
@@ -285,10 +283,9 @@ int dvb_usb_urb_init(struct dvb_usb_device *d)
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
/* allocate the array for the data transfer URBs */
- d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
+ d->urb_list = kzalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
if (d->urb_list == NULL)
return -ENOMEM;
- memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
d->state |= DVB_USB_STATE_URB_LIST;
switch (d->props.urb.type) {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index b4a1a98006c7..dd568396e594 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -10,8 +10,8 @@
#include <linux/config.h>
#include <linux/input.h>
-#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/firmware.h>
#include "dvb_frontend.h"
#include "dvb_demux.h"
@@ -94,7 +94,11 @@ struct dvb_usb_device;
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
* download.
* @firmware: name of the firmware file.
- *
+ * @download_firmware: called to download the firmware when the usb_ctrl is
+ * DEVICE_SPECIFIC.
+ * @no_reconnect: device doesn't do a reconnect after downloading the firmware,
+ so do the warm initialization right after it
+
* @size_of_priv: how many bytes shall be allocated for the private field
* of struct dvb_usb_device.
*
@@ -142,11 +146,14 @@ struct dvb_usb_properties {
int caps;
int pid_filter_count;
-#define CYPRESS_AN2135 0
-#define CYPRESS_AN2235 1
-#define CYPRESS_FX2 2
+#define DEVICE_SPECIFIC 0
+#define CYPRESS_AN2135 1
+#define CYPRESS_AN2235 2
+#define CYPRESS_FX2 3
int usb_ctrl;
- const char *firmware;
+ const char firmware[FIRMWARE_NAME_MAX];
+ int (*download_firmware) (struct usb_device *, const struct firmware *);
+ int no_reconnect;
int size_of_priv;
@@ -326,5 +333,15 @@ extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+/* commonly used firmware download types and function */
+struct hexline {
+ u8 len;
+ u32 addr;
+ u8 type;
+ u8 data[255];
+ u8 chk;
+};
+extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
+extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 1841a66427bf..412039d8dbae 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -129,10 +129,6 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
dibusb_read_eeprom_byte(d,i, &b);
mac[5 - (i - 136)] = b;
-
-/* deb_ee("%02x ",b);
- if ((i+1) % 16 == 0)
- deb_ee("\n");*/
}
return 0;
@@ -153,7 +149,7 @@ static struct usb_device_id nova_t_table [] = {
/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
{ } /* Terminating entry */
};
-MODULE_DEVICE_TABLE (usb, nova_t_table);
+MODULE_DEVICE_TABLE(usb, nova_t_table);
static struct dvb_usb_properties nova_t_properties = {
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
@@ -198,11 +194,11 @@ static struct dvb_usb_properties nova_t_properties = {
{ &nova_t_table[0], NULL },
{ &nova_t_table[1], NULL },
},
+ { NULL },
}
};
static struct usb_driver nova_t_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_nova_t_usb2",
.probe = nova_t_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 6fd67657c269..14f1911c79bb 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -128,7 +128,6 @@ static struct dvb_usb_properties umt_properties = {
};
static struct usb_driver umt_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_umt_010",
.probe = umt_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 104b5d016c7b..b6d95e1c9c52 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -190,7 +190,7 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
}
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
- struct dvb_diseqc_master_cmd *m)
+ struct dvb_diseqc_master_cmd *m)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 cmd[8],ibuf[10];
@@ -281,10 +281,9 @@ 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);
+ struct vp702x_fe_state *s = kzalloc(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;
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index de13c04e8e64..afa00fdb5ec0 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -256,7 +256,6 @@ static struct dvb_usb_properties vp702x_properties = {
/* 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,
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index 4a3e8c7eca2b..a808d48e7bf2 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -13,47 +13,47 @@ extern int dvb_usb_vp702x_debug;
/* commands are read and written with USB control messages */
/* consecutive read/write operation */
-#define REQUEST_OUT 0xB2
-#define REQUEST_IN 0xB3
+#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
+#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
+#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
+#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 */
+ * N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */
-#define SET_LNB_POWER 0x09
+#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 */
+ * N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */
-#define GET_MAC_ADDRESS 0x0A
+#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
+#define SET_PID_FILTER 0x11
/* additional in buffer:
* 0 1 ... 14 15 16
* PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
@@ -64,39 +64,38 @@ extern int dvb_usb_vp702x_debug;
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
*/
-
/* one direction requests */
-#define READ_REMOTE_REQ 0xB4
+#define READ_REMOTE_REQ 0xB4
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
-#define READ_PID_NUMBER_REQ 0xB5
+#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
+#define WRITE_EEPROM_REQ 0xB6
/* OUT i: offset; v: value to write; no extra buffer */
-#define READ_EEPROM_REQ 0xB7
+#define READ_EEPROM_REQ 0xB7
/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
-#define READ_STATUS 0xB8
+#define READ_STATUS 0xB8
/* IN i: 0; v: 0; bufferlen 10 */
-#define READ_TUNER_REG_REQ 0xB9
+#define READ_TUNER_REG_REQ 0xB9
/* IN i: 0; v: register; b[0] = value */
-#define READ_FX2_REG_REQ 0xBA
+#define READ_FX2_REG_REQ 0xBA
/* IN i: offset; v: 0; b[0] = value */
-#define WRITE_FX2_REG_REQ 0xBB
+#define WRITE_FX2_REG_REQ 0xBB
/* OUT i: offset; v: value to write; 1 byte extra buffer */
-#define SET_TUNER_POWER_REQ 0xBC
+#define SET_TUNER_POWER_REQ 0xBC
/* IN i: 0 = power off, 1 = power on */
-#define WRITE_TUNER_REG_REQ 0xBD
+#define WRITE_TUNER_REG_REQ 0xBD
/* IN i: register, v: value to write, no extra buffer */
-#define RESET_TUNER 0xBE
+#define RESET_TUNER 0xBE
/* IN i: 0, v: 0, no extra buffer */
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 83f1de1e7e57..5242cca5db4a 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -145,10 +145,9 @@ static struct dvb_frontend_ops vp7045_fe_ops;
struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
{
- struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
+ struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
if (s == NULL)
goto error;
- memset(s,0,sizeof(struct vp7045_fe_state));
s->d = d;
s->fe.ops = &vp7045_fe_ops;
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 75765e3a569c..028204956bb0 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -247,13 +247,12 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
- { NULL },
+ { 0 },
}
};
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver vp7045_usb_driver = {
- .owner = THIS_MODULE,
.name = "dvb_usb_vp7045",
.probe = vp7045_usb_probe,
.disconnect = dvb_usb_device_exit,
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 8e269e1c1f9d..db3a8b40031e 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -16,6 +16,12 @@ config DVB_CX24110
help
A DVB-S tuner module. Say Y when you want to support this frontend.
+config DVB_CX24123
+ tristate "Conexant CX24123 based"
+ depends on DVB_CORE
+ help
+ A DVB-S tuner module. Say Y when you want to support this frontend.
+
config DVB_TDA8083
tristate "Philips TDA8083 based"
depends on DVB_CORE
@@ -50,18 +56,19 @@ comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
config DVB_SP8870
- tristate "Spase sp8870 based"
+ tristate "Spase sp8870 based"
depends on DVB_CORE
select FW_LOADER
help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_SP887X
- tristate "Spase sp887x based"
+ tristate "Spase sp887x based"
depends on DVB_CORE
select FW_LOADER
help
@@ -69,7 +76,8 @@ config DVB_SP887X
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_CX22700
tristate "Conexant CX22700 based"
@@ -78,10 +86,10 @@ config DVB_CX22700
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_CX22702
- tristate "Conexant cx22702 demodulator (OFDM)"
- depends on DVB_CORE
- help
- A DVB-T tuner module. Say Y when you want to support this frontend.
+ tristate "Conexant cx22702 demodulator (OFDM)"
+ depends on DVB_CORE
+ help
+ A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_L64781
tristate "LSI L64781"
@@ -98,8 +106,9 @@ config DVB_TDA1004X
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT6000
tristate "NxtWave Communications NXT6000 based"
@@ -140,13 +149,13 @@ config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_TDA10021
tristate "Philips TDA10021 based"
depends on DVB_CORE
help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_STV0297
tristate "ST STV0297 based"
@@ -164,6 +173,11 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+ This driver needs external firmware. Please use the command
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
@@ -172,6 +186,12 @@ config DVB_NXT200X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
+
config DVB_OR51211
tristate "or51211 based (pcHDTV HD2000 card)"
depends on DVB_CORE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index a98760fe08a1..615ec830e1c9 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_CX24123) += cx24123.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 8ceb9a33c7af..caaee893ca76 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -255,7 +255,7 @@ static int bcm3510_bert_reset(struct bcm3510_state *st)
bcm3510_register_value b;
int ret;
- if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
+ if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
return ret;
b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
@@ -623,13 +623,13 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
return ret;
}
- deb_info("got firmware: %d\n",fw->size);
+ deb_info("got firmware: %zd\n",fw->size);
b = fw->data;
for (i = 0; i < fw->size;) {
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
- deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
+ deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
err("firmware download failed: %d\n",ret);
return ret;
@@ -782,10 +782,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
bcm3510_register_value v;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct bcm3510_state));
/* setup the state */
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 5de0e6d350b1..0fc899f81c5e 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
return 0;
}
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+ struct cx22702_state* state = fe->demodulator_priv;
+ dprintk ("%s(%d)\n", __FUNCTION__, enable);
+ if (enable)
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
+ else
+ return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
+}
+
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
@@ -202,7 +212,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
struct cx22702_state* state = fe->demodulator_priv;
/* set PLL */
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
+ cx22702_i2c_gate_ctrl(fe, 1);
if (state->config->pll_set) {
state->config->pll_set(fe, p);
} else if (state->config->pll_desc) {
@@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
} else {
BUG();
}
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
+ cx22702_i2c_gate_ctrl(fe, 0);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@@ -349,11 +359,10 @@ static int cx22702_init (struct dvb_frontend* fe)
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
/* init PLL */
- if (state->config->pll_init) {
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
+ if (state->config->pll_init)
state->config->pll_init(fe);
- cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
- }
+
+ cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
@@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
+ .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 0c4db80ec332..d15d32c51dc5 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
@@ -56,7 +55,7 @@ static int debug;
static struct {u8 reg; u8 data;} cx24110_regdata[]=
/* Comments beginning with @ denote this value should
- be the default */
+ be the default */
{{0x09,0x01}, /* SoftResetAll */
{0x09,0x00}, /* release reset */
{0x01,0xe8}, /* MSB of code rate 27.5MS/s */
@@ -67,26 +66,26 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]=
{0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
{0x0a,0x00}, /* @ partial chip disables, do not set */
{0x0b,0x01}, /* set output clock in gapped mode, start signal low
- active for first byte */
+ active for first byte */
{0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
{0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
{0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
- to avoid starting the BER counter. Reset the
- CRC test bit. Finite counting selected */
+ to avoid starting the BER counter. Reset the
+ CRC test bit. Finite counting selected */
{0x15,0xff}, /* @ size of the limited time window for RS BER
- estimation. It is <value>*256 RS blocks, this
- gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*256 RS blocks, this
+ gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
{0x16,0x00}, /* @ enable all RS output ports */
{0x17,0x04}, /* @ time window allowed for the RS to sync */
{0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
- for automatically */
+ for automatically */
/* leave the current code rate and normalization
- registers as they are after reset... */
+ registers as they are after reset... */
{0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
- only once */
+ only once */
{0x23,0x18}, /* @ size of the limited time window for Viterbi BER
- estimation. It is <value>*65536 channel bits, i.e.
- approx. 38ms at 27.5MS/s, rate 3/4 */
+ estimation. It is <value>*65536 channel bits, i.e.
+ approx. 38ms at 27.5MS/s, rate 3/4 */
{0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
/* leave front-end AGC parameters at default values */
/* leave decimation AGC parameters at default values */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
new file mode 100644
index 000000000000..d661c6f9cbe5
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -0,0 +1,889 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24123.h"
+
+static int debug;
+#define dprintk(args...) \
+ do { \
+ if (debug) printk (KERN_DEBUG "cx24123: " args); \
+ } while (0)
+
+struct cx24123_state
+{
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+ const struct cx24123_config* config;
+
+ struct dvb_frontend frontend;
+
+ u32 lastber;
+ u16 snr;
+ u8 lnbreg;
+
+ /* Some PLL specifics for tuning */
+ u32 VCAarg;
+ u32 VGAarg;
+ u32 bandselectarg;
+ u32 pllarg;
+
+ /* The Demod/Tuner can't easily provide these, we cache them */
+ u32 currentfreq;
+ u32 currentsymbolrate;
+};
+
+/* Various tuner defaults need to be established for a given symbol rate Sps */
+static struct
+{
+ u32 symbolrate_low;
+ u32 symbolrate_high;
+ u32 VCAslope;
+ u32 VCAoffset;
+ u32 VGA1offset;
+ u32 VGA2offset;
+ u32 VCAprogdata;
+ u32 VGAprogdata;
+} cx24123_AGC_vals[] =
+{
+ {
+ .symbolrate_low = 1000000,
+ .symbolrate_high = 4999999,
+ .VCAslope = 0x07,
+ .VCAoffset = 0x0f,
+ .VGA1offset = 0x1f8,
+ .VGA2offset = 0x1f8,
+ .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
+ },
+ {
+ .symbolrate_low = 5000000,
+ .symbolrate_high = 14999999,
+ .VCAslope = 0x1f,
+ .VCAoffset = 0x1f,
+ .VGA1offset = 0x1e0,
+ .VGA2offset = 0x180,
+ .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
+ },
+ {
+ .symbolrate_low = 15000000,
+ .symbolrate_high = 45000000,
+ .VCAslope = 0x3f,
+ .VCAoffset = 0x3f,
+ .VGA1offset = 0x180,
+ .VGA2offset = 0x100,
+ .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
+ .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
+ },
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct
+{
+ u32 freq_low;
+ u32 freq_high;
+ u32 bandselect;
+ u32 VCOdivider;
+ u32 VCOnumber;
+ u32 progdata;
+} cx24123_bandselect_vals[] =
+{
+ {
+ .freq_low = 950000,
+ .freq_high = 1018999,
+ .bandselect = 0x40,
+ .VCOdivider = 4,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (0 << 9) | 0x40,
+ },
+ {
+ .freq_low = 1019000,
+ .freq_high = 1074999,
+ .bandselect = 0x80,
+ .VCOdivider = 4,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (0 << 9) | 0x80,
+ },
+ {
+ .freq_low = 1075000,
+ .freq_high = 1227999,
+ .bandselect = 0x01,
+ .VCOdivider = 2,
+ .VCOnumber = 1,
+ .progdata = (0 << 18) | (1 << 9) | 0x01,
+ },
+ {
+ .freq_low = 1228000,
+ .freq_high = 1349999,
+ .bandselect = 0x02,
+ .VCOdivider = 2,
+ .VCOnumber = 2,
+ .progdata = (0 << 18) | (1 << 9) | 0x02,
+ },
+ {
+ .freq_low = 1350000,
+ .freq_high = 1481999,
+ .bandselect = 0x04,
+ .VCOdivider = 2,
+ .VCOnumber = 3,
+ .progdata = (0 << 18) | (1 << 9) | 0x04,
+ },
+ {
+ .freq_low = 1482000,
+ .freq_high = 1595999,
+ .bandselect = 0x08,
+ .VCOdivider = 2,
+ .VCOnumber = 4,
+ .progdata = (0 << 18) | (1 << 9) | 0x08,
+ },
+ {
+ .freq_low = 1596000,
+ .freq_high = 1717999,
+ .bandselect = 0x10,
+ .VCOdivider = 2,
+ .VCOnumber = 5,
+ .progdata = (0 << 18) | (1 << 9) | 0x10,
+ },
+ {
+ .freq_low = 1718000,
+ .freq_high = 1855999,
+ .bandselect = 0x20,
+ .VCOdivider = 2,
+ .VCOnumber = 6,
+ .progdata = (0 << 18) | (1 << 9) | 0x20,
+ },
+ {
+ .freq_low = 1856000,
+ .freq_high = 2035999,
+ .bandselect = 0x40,
+ .VCOdivider = 2,
+ .VCOnumber = 7,
+ .progdata = (0 << 18) | (1 << 9) | 0x40,
+ },
+ {
+ .freq_low = 2036000,
+ .freq_high = 2149999,
+ .bandselect = 0x80,
+ .VCOdivider = 2,
+ .VCOnumber = 8,
+ .progdata = (0 << 18) | (1 << 9) | 0x80,
+ },
+};
+
+static struct {
+ u8 reg;
+ u8 data;
+} cx24123_regdata[] =
+{
+ {0x00, 0x03}, /* Reset system */
+ {0x00, 0x00}, /* Clear reset */
+ {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
+ {0x03, 0x07},
+ {0x04, 0x10},
+ {0x05, 0x04},
+ {0x06, 0x31},
+ {0x0d, 0x02},
+ {0x0e, 0x03},
+ {0x0f, 0xfe},
+ {0x10, 0x01},
+ {0x14, 0x01},
+ {0x15, 0x98},
+ {0x16, 0x00},
+ {0x17, 0x01},
+ {0x1b, 0x05},
+ {0x1c, 0x80},
+ {0x1d, 0x00},
+ {0x1e, 0x00},
+ {0x20, 0x41},
+ {0x21, 0x15},
+ {0x27, 0x14},
+ {0x28, 0x46},
+ {0x29, 0x00},
+ {0x2a, 0xb0},
+ {0x2b, 0x73},
+ {0x2c, 0x00},
+ {0x2d, 0x00},
+ {0x2e, 0x00},
+ {0x2f, 0x00},
+ {0x30, 0x00},
+ {0x31, 0x00},
+ {0x32, 0x8c},
+ {0x33, 0x00},
+ {0x34, 0x00},
+ {0x35, 0x03},
+ {0x36, 0x02},
+ {0x37, 0x3a},
+ {0x3a, 0x00}, /* Enable AGC accumulator */
+ {0x44, 0x00},
+ {0x45, 0x00},
+ {0x46, 0x05},
+ {0x56, 0x41},
+ {0x57, 0xff},
+ {0x67, 0x83},
+};
+
+static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writereg error(err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
+{
+ u8 buf[] = { reg, data };
+ /* fixme: put the intersil addr int the config */
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
+ int err;
+
+ if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+ printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
+ " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
+ return -EREMOTEIO;
+ }
+
+ /* cache the write, no way to read back */
+ state->lnbreg = data;
+
+ return 0;
+}
+
+static int cx24123_readreg(struct cx24123_state* state, u8 reg)
+{
+ int ret;
+ u8 b0[] = { reg };
+ u8 b1[] = { 0 };
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+ };
+
+ ret = i2c_transfer(state->i2c, msg, 2);
+
+ if (ret != 2) {
+ printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
+ return ret;
+ }
+
+ return b1[0];
+}
+
+static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
+{
+ return state->lnbreg;
+}
+
+static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
+{
+ switch (inversion) {
+ case INVERSION_OFF:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_ON:
+ cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
+ break;
+ case INVERSION_AUTO:
+ cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
+{
+ u8 val;
+
+ val = cx24123_readreg(state, 0x1b) >> 7;
+
+ if (val == 0)
+ *inversion = INVERSION_OFF;
+ else
+ *inversion = INVERSION_ON;
+
+ return 0;
+}
+
+static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
+{
+ if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
+ fec = FEC_AUTO;
+
+ /* Hardware has 5/11 and 3/5 but are never unused */
+ switch (fec) {
+ case FEC_NONE:
+ return cx24123_writereg(state, 0x0f, 0x01);
+ case FEC_1_2:
+ return cx24123_writereg(state, 0x0f, 0x02);
+ case FEC_2_3:
+ return cx24123_writereg(state, 0x0f, 0x04);
+ case FEC_3_4:
+ return cx24123_writereg(state, 0x0f, 0x08);
+ case FEC_5_6:
+ return cx24123_writereg(state, 0x0f, 0x20);
+ case FEC_7_8:
+ return cx24123_writereg(state, 0x0f, 0x80);
+ case FEC_AUTO:
+ return cx24123_writereg(state, 0x0f, 0xae);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
+{
+ int ret;
+ u8 val;
+
+ ret = cx24123_readreg (state, 0x1b);
+ if (ret < 0)
+ return ret;
+ val = ret & 0x07;
+ switch (val) {
+ case 1:
+ *fec = FEC_1_2;
+ break;
+ case 3:
+ *fec = FEC_2_3;
+ break;
+ case 4:
+ *fec = FEC_3_4;
+ break;
+ case 5:
+ *fec = FEC_4_5;
+ break;
+ case 6:
+ *fec = FEC_5_6;
+ break;
+ case 7:
+ *fec = FEC_7_8;
+ break;
+ case 2: /* *fec = FEC_3_5; break; */
+ case 0: /* *fec = FEC_5_11; break; */
+ *fec = FEC_AUTO;
+ break;
+ default:
+ *fec = FEC_NONE; // can't happen
+ }
+
+ return 0;
+}
+
+/* fixme: Symbol rates < 3MSps may not work because of precision loss */
+static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
+{
+ u32 val;
+
+ val = (srate / 1185) * 100;
+
+ /* Compensate for scaling up, by removing 17 symbols per 1Msps */
+ val = val - (17 * (srate / 1000000));
+
+ cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
+ cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
+ cx24123_writereg(state, 0x0a, (val ) & 0xff );
+
+ return 0;
+}
+
+/*
+ * Based on the required frequency and symbolrate, the tuner AGC has to be configured
+ * and the correct band selected. Calculate those values
+ */
+static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u32 ndiv = 0, adiv = 0, vco_div = 0;
+ int i = 0;
+
+ /* Defaults for low freq, low rate */
+ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
+ state->bandselectarg = cx24123_bandselect_vals[0].progdata;
+ vco_div = cx24123_bandselect_vals[0].VCOdivider;
+
+ /* For the given symbolerate, determine the VCA and VGA programming bits */
+ for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
+ {
+ if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
+ (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
+ state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
+ state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
+ }
+ }
+
+ /* For the given frequency, determine the bandselect programming bits */
+ for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
+ {
+ if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
+ (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
+ state->bandselectarg = cx24123_bandselect_vals[i].progdata;
+ vco_div = cx24123_bandselect_vals[i].VCOdivider;
+ }
+ }
+
+ /* Determine the N/A dividers for the requested lband freq (in kHz). */
+ /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
+ ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
+ adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
+
+ if (adiv == 0)
+ adiv++;
+
+ /* determine the correct pll frequency values. */
+ /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
+ state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
+ state->pllarg |= (ndiv << 5) | adiv;
+
+ return 0;
+}
+
+/*
+ * Tuner data is 21 bits long, must be left-aligned in data.
+ * Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
+ */
+static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ unsigned long timeout;
+
+ /* align the 21 bytes into to bit23 boundary */
+ data = data << 3;
+
+ /* Reset the demod pll word length to 0x15 bits */
+ cx24123_writereg(state, 0x21, 0x15);
+
+ /* write the msb 8 bits, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send another 8 bytes, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data>>8) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
+ timeout = jiffies + msecs_to_jiffies(40);
+ cx24123_writereg(state, 0x22, (data) & 0xff );
+ while ((cx24123_readreg(state, 0x20) & 0x80)) {
+ if (time_after(jiffies, timeout)) {
+ printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
+ return -EREMOTEIO;
+ }
+ msleep(10);
+ }
+
+ /* Trigger the demod to configure the tuner */
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
+ cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
+
+ return 0;
+}
+
+static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_pll_calculate(fe, p) != 0) {
+ printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
+ return -EINVAL;
+ }
+
+ /* Write the new VCO/VGA */
+ cx24123_pll_writereg(fe, p, state->VCAarg);
+ cx24123_pll_writereg(fe, p, state->VGAarg);
+
+ /* Write the new bandselect and pll args */
+ cx24123_pll_writereg(fe, p, state->bandselectarg);
+ cx24123_pll_writereg(fe, p, state->pllarg);
+
+ return 0;
+}
+
+static int cx24123_initfe(struct dvb_frontend* fe)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ int i;
+
+ /* Configure the demod to a good set of defaults */
+ for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
+ cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
+
+ if (state->config->pll_init)
+ state->config->pll_init(fe);
+
+ /* Configure the LNB for 14V */
+ if (state->config->use_isl6421)
+ cx24123_writelnbreg(state, 0x0, 0x2a);
+
+ return 0;
+}
+
+static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
+ case SEC_VOLTAGE_18:
+ return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
+ case SEC_VOLTAGE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x30);
+ default:
+ return -EINVAL;
+ };
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (voltage) {
+ case SEC_VOLTAGE_13:
+ dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val | 0x80);
+ case SEC_VOLTAGE_18:
+ dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 1);
+ return cx24123_writereg(state, 0x29, val & 0x7f);
+ case SEC_VOLTAGE_OFF:
+ dprintk("%s: setting voltage off\n", __FUNCTION__);
+ if (state->config->enable_lnb_voltage)
+ state->config->enable_lnb_voltage(fe, 0);
+ return 0;
+ default:
+ return -EINVAL;
+ };
+ }
+
+ return 0;
+}
+
+static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
+ struct dvb_diseqc_master_cmd *cmd)
+{
+ /* fixme: Implement diseqc */
+ printk("%s: No support yet\n",__FUNCTION__);
+
+ return -ENOTSUPP;
+}
+
+static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ int sync = cx24123_readreg(state, 0x14);
+ int lock = cx24123_readreg(state, 0x20);
+
+ *status = 0;
+ if (lock & 0x01)
+ *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+ if (sync & 0x04)
+ *status |= FE_HAS_VITERBI;
+ if (sync & 0x08)
+ *status |= FE_HAS_CARRIER;
+ if (sync & 0x80)
+ *status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+ return 0;
+}
+
+/*
+ * Configured to return the measurement of errors in blocks, because no UCBLOCKS value
+ * is available, so this value doubles up to satisfy both measurements
+ */
+static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ state->lastber =
+ ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+ (cx24123_readreg(state, 0x1d) << 8 |
+ cx24123_readreg(state, 0x1e));
+
+ /* Do the signal quality processing here, it's derived from the BER. */
+ /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
+ if (state->lastber < 5000)
+ state->snr = 655*100;
+ else if ( (state->lastber >= 5000) && (state->lastber < 55000) )
+ state->snr = 655*90;
+ else if ( (state->lastber >= 55000) && (state->lastber < 150000) )
+ state->snr = 655*80;
+ else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
+ state->snr = 655*70;
+ else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
+ state->snr = 655*65;
+ else
+ state->snr = 0;
+
+ *ber = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
+
+ return 0;
+}
+
+static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *snr = state->snr;
+
+ return 0;
+}
+
+static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ *ucblocks = state->lastber;
+
+ return 0;
+}
+
+static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (state->config->set_ts_params)
+ state->config->set_ts_params(fe, 0);
+
+ state->currentfreq=p->frequency;
+ state->currentsymbolrate = p->u.qpsk.symbol_rate;
+
+ cx24123_set_inversion(state, p->inversion);
+ cx24123_set_fec(state, p->u.qpsk.fec_inner);
+ cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ cx24123_pll_tune(fe, p);
+
+ /* Enable automatic aquisition and reset cycle */
+ cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+ cx24123_writereg(state, 0x00, 0x10);
+ cx24123_writereg(state, 0x00, 0);
+
+ return 0;
+}
+
+static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+
+ if (cx24123_get_inversion(state, &p->inversion) != 0) {
+ printk("%s: Failed to get inversion status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
+ printk("%s: Failed to get fec status\n",__FUNCTION__);
+ return -EREMOTEIO;
+ }
+ p->frequency = state->currentfreq;
+ p->u.qpsk.symbol_rate = state->currentsymbolrate;
+
+ return 0;
+}
+
+static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+ struct cx24123_state *state = fe->demodulator_priv;
+ u8 val;
+
+ switch (state->config->use_isl6421) {
+ case 1:
+
+ val = cx24123_readlnbreg(state, 0x0);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ return cx24123_writelnbreg(state, 0x0, val | 0x10);
+ case SEC_TONE_OFF:
+ return cx24123_writelnbreg(state, 0x0, val & 0x2f);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+
+ case 0:
+
+ val = cx24123_readreg(state, 0x29);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ dprintk("%s: setting tone on\n", __FUNCTION__);
+ return cx24123_writereg(state, 0x29, val | 0x10);
+ case SEC_TONE_OFF:
+ dprintk("%s: setting tone off\n",__FUNCTION__);
+ return cx24123_writereg(state, 0x29, val & 0xef);
+ default:
+ printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void cx24123_release(struct dvb_frontend* fe)
+{
+ struct cx24123_state* state = fe->demodulator_priv;
+ dprintk("%s\n",__FUNCTION__);
+ kfree(state);
+}
+
+static struct dvb_frontend_ops cx24123_ops;
+
+struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct cx24123_state* state = NULL;
+ int ret;
+
+ dprintk("%s\n",__FUNCTION__);
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
+ if (state == NULL) {
+ printk("Unable to kmalloc\n");
+ goto error;
+ }
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
+ state->lastber = 0;
+ state->snr = 0;
+ state->lnbreg = 0;
+ state->VCAarg = 0;
+ state->VGAarg = 0;
+ state->bandselectarg = 0;
+ state->pllarg = 0;
+ state->currentfreq = 0;
+ state->currentsymbolrate = 0;
+
+ /* check if the demod is there */
+ ret = cx24123_readreg(state, 0x00);
+ if ((ret != 0xd1) && (ret != 0xe1)) {
+ printk("Version != d1 or e1\n");
+ goto error;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+
+error:
+ kfree(state);
+
+ return NULL;
+}
+
+static struct dvb_frontend_ops cx24123_ops = {
+
+ .info = {
+ .name = "Conexant CX24123/CX24109",
+ .type = FE_QPSK,
+ .frequency_min = 950000,
+ .frequency_max = 2150000,
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
+ .frequency_tolerance = 29500,
+ .symbol_rate_min = 1000000,
+ .symbol_rate_max = 45000000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_RECOVER
+ },
+
+ .release = cx24123_release,
+
+ .init = cx24123_initfe,
+ .set_frontend = cx24123_set_frontend,
+ .get_frontend = cx24123_get_frontend,
+ .read_status = cx24123_read_status,
+ .read_ber = cx24123_read_ber,
+ .read_signal_strength = cx24123_read_signal_strength,
+ .read_snr = cx24123_read_snr,
+ .read_ucblocks = cx24123_read_ucblocks,
+ .diseqc_send_master_cmd = cx24123_send_diseqc_msg,
+ .set_tone = cx24123_set_tone,
+ .set_voltage = cx24123_set_voltage,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx24123_attach);
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
new file mode 100644
index 000000000000..0c922b5e9263
--- /dev/null
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -0,0 +1,51 @@
+/*
+ Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+ Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef CX24123_H
+#define CX24123_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24123_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /*
+ cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
+ for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
+ from register 0x29 of the CX24123 demodulator
+ */
+ int use_isl6421;
+
+ /* PLL maintenance */
+ int (*pll_init)(struct dvb_frontend* fe);
+ int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+
+ /* Need to set device param for start_dma */
+ int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+ void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
+};
+
+extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+ struct i2c_adapter* i2c);
+
+#endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index 6b0553608610..ae589adb1c0a 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -700,10 +700,9 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct dib3000_state* state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index c024fad17337..3b303dbb6156 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -832,10 +832,9 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
u16 devid;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(struct dib3000_state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index f857b869616c..1b9934ea5b06 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -107,18 +107,19 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = {
};
EXPORT_SYMBOL(dvb_pll_microtune_4042);
-struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
- .name = "Thomson dtt7611",
- .min = 44000000,
- .max = 958000000,
+struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson dtt761x",
+ .min = 57000000,
+ .max = 863000000,
.count = 3,
.entries = {
- { 157250000, 44000000, 62500, 0x8e, 0x39 },
- { 454000000, 44000000, 62500, 0x8e, 0x3a },
+ { 147000000, 44000000, 62500, 0x8e, 0x39 },
+ { 417000000, 44000000, 62500, 0x8e, 0x3a },
{ 999999999, 44000000, 62500, 0x8e, 0x3c },
},
};
-EXPORT_SYMBOL(dvb_pll_thomson_dtt7611);
+EXPORT_SYMBOL(dvb_pll_thomson_dtt761x);
struct dvb_pll_desc dvb_pll_unknown_1 = {
.name = "unknown 1", /* used by dntv live dvb-t */
@@ -332,7 +333,7 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
.name = "Samsung TBMV30111IN",
.min = 54000000,
.max = 860000000,
- .count = 4,
+ .count = 6,
.entries = {
{ 172000000, 44000000, 166666, 0xb4, 0x01 },
{ 214000000, 44000000, 166666, 0xb4, 0x02 },
@@ -344,6 +345,23 @@ struct dvb_pll_desc dvb_pll_tbmv30111in = {
};
EXPORT_SYMBOL(dvb_pll_tbmv30111in);
+/*
+ * Philips SD1878 Tuner.
+ */
+struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+ .name = "Philips SD1878",
+ .min = 950000,
+ .max = 2150000,
+ .count = 4,
+ .entries = {
+ { 1250000, 499, 500, 0xc4, 0x00},
+ { 1550000, 499, 500, 0xc4, 0x40},
+ { 2050000, 499, 500, 0xc4, 0x80},
+ { 2150000, 499, 500, 0xc4, 0xc0},
+ },
+};
+EXPORT_SYMBOL(dvb_pll_philips_sd1878_tda8261);
+
/* ----------------------------------------------------------- */
/* code */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 497d31dcf41e..f682c09189b3 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -25,7 +25,7 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
extern struct dvb_pll_desc dvb_pll_lg_z201;
extern struct dvb_pll_desc dvb_pll_microtune_4042;
-extern struct dvb_pll_desc dvb_pll_thomson_dtt7611;
+extern struct dvb_pll_desc dvb_pll_thomson_dtt761x;
extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;
@@ -39,6 +39,7 @@ extern struct dvb_pll_desc dvb_pll_tded4;
extern struct dvb_pll_desc dvb_pll_tuv1236d;
extern struct dvb_pll_desc dvb_pll_tdhu2;
extern struct dvb_pll_desc dvb_pll_tbmv30111in;
+extern struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261;
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
u32 freq, int bandwidth);
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index cb5301865d07..4691ac54bc1d 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -27,6 +27,7 @@
* DViCO FusionHDTV 3 Gold-T
* DViCO FusionHDTV 5 Gold
* DViCO FusionHDTV 5 Lite
+ * DViCO FusionHDTV 5 USB Gold
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
*
* TODO:
@@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
state->config->pll_set(fe, param);
/* Keep track of the new frequency */
+ /* FIXME this is the wrong way to do this... */
+ /* The tuner is shared with the video4linux analog API */
state->current_frequency = param->frequency;
lgdt330x_SwReset(state);
@@ -711,10 +714,9 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
u8 buf[1];
/* Allocate memory for the internal state */
- state = (struct lgdt330x_state*) kmalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(*state));
/* Setup the state */
state->config = config;
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 8d672283c93d..ec4e641acc64 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -501,7 +501,8 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
case ID_VP310:
// For now we will do this only for the VP310.
// It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
- if ((ret = mt312_readreg(state, CONFIG, &config_val) < 0))
+ ret = mt312_readreg(state, CONFIG, &config_val);
+ if (ret < 0)
return ret;
if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
{
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index f0c610f2c2df..aaaec909ddf8 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -535,9 +535,8 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct mt352_state* state = NULL;
/* allocate memory for the internal state */
- state = kmalloc(sizeof(struct mt352_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct mt352_state), GFP_KERNEL);
if (state == NULL) goto error;
- memset(state,0,sizeof(*state));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 52c416043a62..4f263e65ba14 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
#define CRC_CCIT_MASK 0x1021
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index aeafef46e3eb..78d2b93d35b9 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -1110,10 +1110,9 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
u8 buf [] = {0,0,0,0,0};
/* allocate memory for the internal state */
- state = (struct nxt200x_state*) kmalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
if (state == NULL)
goto error;
- memset(state,0,sizeof(*state));
/* setup the state */
state->config = config;
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a458a3bfff70..a16eeba0020d 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -574,11 +574,11 @@ static struct dvb_frontend_ops nxt6000_ops = {
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
- FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
- FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+ FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_HIERARCHY_AUTO,
},
.release = nxt6000_release,
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 531f76246e5f..7c3aed1f546b 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -25,7 +25,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
@@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
u8 tudata[585];
int i;
- dprintk("Firmware is %d bytes\n",fw->size);
+ dprintk("Firmware is %zd bytes\n",fw->size);
/* Get eprom data */
tudata[0] = 17;
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index 18715091aed8..d69477596921 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -521,8 +521,8 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
case FEC_3_4:
s5h1420_writereg(state, 0x30, 0x04);
- s5h1420_writereg(state, 0x31, 0x12 | inversion);
- break;
+ s5h1420_writereg(state, 0x31, 0x12 | inversion);
+ break;
case FEC_5_6:
s5h1420_writereg(state, 0x30, 0x08);
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index fc06cd6b46c3..73829e647e50 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index e3b665782243..eb8a602198ca 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -5,7 +5,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
@@ -581,7 +582,7 @@ static struct dvb_frontend_ops sp887x_ops = {
.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_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
- FE_CAN_RECOVER
+ FE_CAN_RECOVER
},
.release = sp887x_release,
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 177d71d56b67..5bcd00f792e6 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
+int stv0299_enable_plli2c (struct dvb_frontend* fe)
+{
+ struct stv0299_state* state = fe->demodulator_priv;
+
+ return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
+}
+
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@@ -387,7 +394,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
@@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
cmd = cmd << 1;
if (debug_legacy_dish_switch)
- printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+ printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
do_gettimeofday (&nexttime);
if (debug_legacy_dish_switch)
@@ -717,5 +724,6 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(stv0299_enable_plli2c);
EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 9af3d71c89db..32c87b4c2f13 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -94,6 +94,7 @@ struct stv0299_config
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
+extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 425cd19136fe..21255cac9793 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -95,7 +95,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
u8 b0 [] = { reg };
u8 b1 [] = { 0 };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
- { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
@@ -434,7 +434,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.frequency_max = 858000000,
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
- #if 0
+#if 0
.frequency_tolerance = ???,
.symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
#endif
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index dd02aff467fe..c63e9a5084eb 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -23,7 +23,8 @@
* This driver needs external firmware. Please use the commands
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- * download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ * download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
@@ -271,32 +272,57 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
fe_bandwidth_t bandwidth)
{
- static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e };
- static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 };
- static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd };
-
+ static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
+ static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
+ static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
+
+ static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
+ static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
+ static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
switch (bandwidth) {
case BANDWIDTH_6_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
+ sizeof(bandwidth_6mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
+ sizeof(bandwidth_6mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
}
break;
case BANDWIDTH_7_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
+ sizeof(bandwidth_7mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
+ sizeof(bandwidth_7mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
}
break;
case BANDWIDTH_8_MHZ:
- tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+ if (tda10046_clk53m)
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
+ sizeof(bandwidth_8mhz_53M));
+ else
+ tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
+ sizeof(bandwidth_8mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
}
break;
@@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
static void tda10046_init_plls(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
+ int tda10046_clk53m;
+
+ if ((state->config->if_freq == TDA10046_FREQ_045) ||
+ (state->config->if_freq == TDA10046_FREQ_052))
+ tda10046_clk53m = 0;
+ else
+ tda10046_clk53m = 1;
tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
- tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10
+ if(tda10046_clk53m) {
+ printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
+ } else {
+ printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+ }
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
@@ -428,26 +467,32 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
}
- tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
+ if(tda10046_clk53m)
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
+ else
+ tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
+ /* Note clock frequency is handled implicitly */
switch (state->config->if_freq) {
- case TDA10046_FREQ_3617:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
- break;
- case TDA10046_FREQ_3613:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13);
- break;
case TDA10046_FREQ_045:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
break;
case TDA10046_FREQ_052:
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
- tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
+ break;
+ case TDA10046_FREQ_3617:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
+ break;
+ case TDA10046_FREQ_3613:
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+ tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
break;
}
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
+ /* let the PLLs settle */
+ msleep(120);
}
static int tda10046_fwupload(struct dvb_frontend* fe)
@@ -462,13 +507,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
/* let the clocks recover from sleep */
msleep(5);
+ /* The PLLs need to be reprogrammed after sleep */
+ tda10046_init_plls(fe);
+
/* don't re-upload unless necessary */
if (tda1004x_check_upload_ok(state) == 0)
return 0;
- /* set parameters */
- tda10046_init_plls(fe);
-
if (state->config->request_firmware != NULL) {
/* request the firmware, this will block until someone uploads it */
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
@@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret;
} else {
/* boot from firmware eeprom */
- /* Hac Note: we might need to do some GPIO Magic here */
printk(KERN_INFO "tda1004x: booting from eeprom\n");
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
msleep(300);
@@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
- tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream
- tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
+ tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
+ tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
- tda10046_init_plls(fe);
switch (state->config->agc_config) {
case TDA10046_AGC_DEFAULT:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
@@ -626,25 +669,22 @@ static int tda10046_init(struct dvb_frontend* fe)
case TDA10046_AGC_TDA827X:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
- tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
- tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
+ tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+ tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
}
+ tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
- tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1
+ tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
- tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup
- tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config
- tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select
-
state->initialised = 1;
return 0;
}
@@ -686,9 +726,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Set standard params.. or put them to auto
if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
- (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
- (fe_params->u.ofdm.constellation == QAM_AUTO) ||
- (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
+ (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
+ (fe_params->u.ofdm.constellation == QAM_AUTO) ||
+ (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
@@ -851,6 +891,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
{
struct tda1004x_state* state = fe->demodulator_priv;
+
dprintk("%s\n", __FUNCTION__);
// inversion status
@@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
break;
}
break;
-
case TDA1004X_DEMOD_TDA10046:
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
- case 0x60:
+ case 0x5c:
+ case 0x54:
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
break;
- case 0x6e:
+ case 0x6a:
+ case 0x60:
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
break;
- case 0x80:
+ case 0x7b:
+ case 0x70:
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
break;
}
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
index f02842be0d60..84f8f9f52869 100644
--- a/drivers/media/dvb/pluto2/Kconfig
+++ b/drivers/media/dvb/pluto2/Kconfig
@@ -8,7 +8,7 @@ config DVB_PLUTO2
Support for PCI cards based on the Pluto2 FPGA like the Satelco
Easywatch Mobile Terrestrial DVB-T Receiver.
- Since these cards have no MPEG decoder onboard, they transmit
+ Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index bbebd1c4caca..1c5316e209ef 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -584,11 +584,10 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
struct dmx_demux *dmx;
int ret = -ENOMEM;
- pluto = kmalloc(sizeof(struct pluto), GFP_KERNEL);
+ pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL);
if (!pluto)
goto out;
- memset(pluto, 0, sizeof(struct pluto));
pluto->pdev = pdev;
ret = pci_enable_device(pdev);
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index fa5034a9ecf5..5b2aadb8385c 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -18,9 +18,10 @@ config DVB_AV7110
This driver only supports the fullfeatured cards with
onboard MPEG2 decoder.
- This driver needs an external firmware. Please use the script
- "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
- download/extract it, and then copy it to /usr/lib/hotplug/firmware.
+ This driver needs an external firmware. Please use the script
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
+ download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a card and want to use it.
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 825ab1c38a4f..a690730ac39d 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -16,7 +16,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110_firm.h:
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 7dae91e5863c..27494901975f 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -81,7 +81,7 @@ static int adac = DVB_ADAC_TI;
static int hw_sections;
static int rgb_on;
static int volume = 255;
-static int budgetpatch = 0;
+static int budgetpatch;
module_param_named(debug, av7110_debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0
static void restart_feeds(struct av7110 *av7110);
-static int av7110_num = 0;
+static int av7110_num;
#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
{\
@@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110)
/* remaining inits according to card and frontend type */
av7110->analog_tuner_flags = 0;
av7110->current_input = 0;
- if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+ if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
+ printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
+ av7110->dvb_adapter.num);
+ av7110->adac_type = DVB_ADAC_MSP34x5;
+ av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
+ }
+ else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_CRYSTAL;
@@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110)
else {
av7110->adac_type = adac;
printk("dvb-ttpci: adac type set to %d @ card %d\n",
- av7110->dvb_adapter.num, av7110->adac_type);
+ av7110->adac_type, av7110->dvb_adapter.num);
}
- if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
+ if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
// switch DVB SCART on
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
if (ret < 0)
@@ -190,17 +196,15 @@ static void recover_arm(struct av7110 *av7110)
av7110_bootarm(av7110);
msleep(100);
- restart_feeds(av7110);
- av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
-}
-static void arm_error(struct av7110 *av7110)
-{
- dprintk(4, "%p\n",av7110);
+ init_av7110_av(av7110);
+
+ /* card-specific recovery */
+ if (av7110->recover)
+ av7110->recover(av7110);
- av7110->arm_errors++;
- av7110->arm_ready = 0;
- recover_arm(av7110);
+ restart_feeds(av7110);
+ av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
}
static void av7110_arm_sync(struct av7110 *av7110)
@@ -240,26 +244,22 @@ static int arm_thread(void *data)
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
up(&av7110->dcomlock);
- if (newloops == av7110->arm_loops) {
+ if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
av7110->dvb_adapter.num);
- arm_error(av7110);
- av7710_set_video_mode(av7110, vidmode);
-
- init_av7110_av(av7110);
+ recover_arm(av7110);
if (down_interruptible(&av7110->dcomlock))
break;
-
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
up(&av7110->dcomlock);
}
av7110->arm_loops = newloops;
+ av7110->arm_errors = 0;
}
av7110->arm_thread = NULL;
@@ -510,10 +510,6 @@ static void gpioirq(unsigned long data)
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
av7110->video_size.h = h_ar & 0xfff;
- dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
- av7110->video_size.w,
- av7110->video_size.h,
- av7110->video_size.aspect_ratio);
event.type = VIDEO_EVENT_SIZE_CHANGED;
event.u.size.w = av7110->video_size.w;
@@ -535,6 +531,11 @@ static void gpioirq(unsigned long data)
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
}
+
+ dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
+ av7110->video_size.w, av7110->video_size.h,
+ av7110->video_size.aspect_ratio);
+
dvb_video_add_event(av7110, &event);
break;
}
@@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = {
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
{
+ u16 aflags = 0;
+
dprintk(4, "%p\n", av7110);
if (vpid == 0x1fff || apid == 0x1fff ||
@@ -725,8 +728,11 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
av7110->pids[DMX_PES_PCR] = 0;
}
- return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5,
- pcrpid, vpid, apid, ttpid, subpid);
+ if (av7110->audiostate.bypass_mode)
+ aflags |= 0x8000;
+
+ return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
+ pcrpid, vpid, apid, ttpid, subpid, aflags);
}
int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
@@ -1043,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
struct dvb_demux *dvbdmx = &av7110->demux;
struct dvb_demux_feed *feed;
int mode;
- int i;
+ int i, j;
dprintk(4, "%p\n", av7110);
@@ -1051,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
av7110->playing = 0;
av7110->rec_mode = 0;
- for (i = 0; i < dvbdmx->filternum; i++) {
+ for (i = 0; i < dvbdmx->feednum; i++) {
feed = &dvbdmx->feed[i];
- if (feed->state == DMX_STATE_GO)
+ if (feed->state == DMX_STATE_GO) {
+ if (feed->type == DMX_TYPE_SEC) {
+ for (j = 0; j < dvbdmx->filternum; j++) {
+ if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
+ continue;
+ if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
+ continue;
+ if (dvbdmx->filter[j].state == DMX_STATE_GO)
+ dvbdmx->filter[j].state = DMX_STATE_READY;
+ }
+ }
av7110_start_feed(feed);
+ }
}
if (mode)
@@ -1483,9 +1500,9 @@ static int get_firmware(struct av7110* av7110)
if (ret == -ENOENT) {
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
" file not found: dvb-ttpci-01.fw\n");
- printk(KERN_ERR "dvb-ttpci: usually this should be in"
- " /usr/lib/hotplug/firmware\n");
- printk(KERN_ERR "dvb-ttpci: and can be downloaded here"
+ printk(KERN_ERR "dvb-ttpci: usually this should be in "
+ "/usr/lib/hotplug/firmware or /lib/firmware\n");
+ printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
" http://www.linuxtv.org/download/dvb/firmware/\n");
} else
printk(KERN_ERR "dvb-ttpci: cannot request firmware"
@@ -2110,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_fe_params = *params;
ret = av7110->fe_set_frontend(fe, params);
+ }
return ret;
}
@@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_master_cmd = *cmd;
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
+ }
return ret;
}
@@ -2163,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_minicmd = minicmd;
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
+ }
return ret;
}
@@ -2173,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_tone = tone;
ret = av7110->fe_set_tone(fe, tone);
+ }
return ret;
}
@@ -2183,12 +2208,14 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
- if (!ret)
+ if (!ret) {
+ av7110->saved_voltage = voltage;
ret = av7110->fe_set_voltage(fe, voltage);
+ }
return ret;
}
-static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
+static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
{
struct av7110* av7110 = fe->dvb->priv;
@@ -2198,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
return ret;
}
+static void dvb_s_recover(struct av7110* av7110)
+{
+ av7110_fe_init(av7110->fe);
+
+ av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
+ if (av7110->saved_master_cmd.msg_len) {
+ msleep(20);
+ av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
+ }
+ msleep(20);
+ av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
+ msleep(20);
+ av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
+
+ av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
+}
+
static u8 read_pwm(struct av7110* av7110)
{
u8 b = 0xff;
@@ -2235,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2244,15 +2289,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
// Try the grundig 29504-451
- av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
+ av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
break;
}
@@ -2274,12 +2321,12 @@ static int frontend_init(struct av7110 *av7110)
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
// ALPS TDLB7
- av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+ av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
break;
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
- av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+ av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
@@ -2289,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
+ av7110->recover = dvb_s_recover;
}
break;
@@ -2314,8 +2362,11 @@ static int frontend_init(struct av7110 *av7110)
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
/* ALPS BSBE1 */
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
- if (av7110->fe)
+ if (av7110->fe) {
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
+ av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+ av7110->recover = dvb_s_recover;
+ }
break;
}
}
@@ -2514,14 +2565,12 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
}
/* prepare the av7110 device struct */
- av7110 = kmalloc(sizeof(struct av7110), GFP_KERNEL);
+ av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
if (!av7110) {
dprintk(1, "out of memory\n");
return -ENOMEM;
}
- memset(av7110, 0, sizeof(struct av7110));
-
av7110->card_name = (char*) pci_ext->ext_priv;
av7110->dev = dev;
dev->ext_priv = av7110;
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index cce00ef293e9..6ea30df2e823 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -98,7 +98,8 @@ struct av7110 {
int adac_type; /* audio DAC type */
#define DVB_ADAC_TI 0
#define DVB_ADAC_CRYSTAL 1
-#define DVB_ADAC_MSP 2
+#define DVB_ADAC_MSP34x0 2
+#define DVB_ADAC_MSP34x5 3
#define DVB_ADAC_NONE -1
@@ -228,6 +229,9 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
+ u16 wssMode;
+ u16 wssData;
+
u32 ir_config;
u32 ir_command;
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
@@ -245,6 +249,15 @@ struct av7110 {
struct dvb_frontend* fe;
fe_status_t fe_status;
+
+ /* crash recovery */
+ void (*recover)(struct av7110* av7110);
+ struct dvb_frontend_parameters saved_fe_params;
+ fe_sec_voltage_t saved_voltage;
+ fe_sec_tone_mode_t saved_tone;
+ struct dvb_diseqc_master_cmd saved_master_cmd;
+ fe_sec_mini_cmd_t saved_minicmd;
+
int (*fe_init)(struct dvb_frontend* fe);
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
@@ -252,7 +265,7 @@ struct av7110 {
int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
- int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+ int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 0696a5a4f855..400facec7407 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -309,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
i2c_writereg(av7110, 0x20, 0x04, volright);
return 0;
- case DVB_ADAC_MSP:
+ case DVB_ADAC_MSP34x0:
vol = (volleft > volright) ? volleft : volright;
val = (vol * 0x73 / 255) << 8;
if (vol > 0)
@@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_SET_BYPASS_MODE:
- ret = -EINVAL;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ ret = -EINVAL;
+ av7110->audiostate.bypass_mode = (int)arg;
break;
case AUDIO_CHANNEL_SELECT:
@@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_GET_CAPABILITIES:
- *(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ if (FW_VERSION(av7110->arm_app) < 0x2621)
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
+ else
+ *(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
+ AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
break;
case AUDIO_CLEAR_BUFFER:
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index 87106e8bf35b..b2e63e9fc053 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -146,52 +146,52 @@ static int load_dram(struct av7110 *av7110, u32 *data, int len)
{
int i;
int blocks, rest;
- u32 base, bootblock = BOOT_BLOCK;
+ u32 base, bootblock = AV7110_BOOT_BLOCK;
dprintk(4, "%p\n", av7110);
- blocks = len / BOOT_MAX_SIZE;
- rest = len % BOOT_MAX_SIZE;
+ blocks = len / AV7110_BOOT_MAX_SIZE;
+ rest = len % AV7110_BOOT_MAX_SIZE;
base = DRAM_START_CODE;
for (i = 0; i < blocks; i++) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
return -ETIMEDOUT;
}
dprintk(4, "writing DRAM block %d\n", i);
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, BOOT_MAX_SIZE);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
bootblock ^= 0x1400;
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, BOOT_MAX_SIZE, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- base += BOOT_MAX_SIZE;
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ base += AV7110_BOOT_MAX_SIZE;
}
if (rest > 0) {
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
return -ETIMEDOUT;
}
if (rest > 4)
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE, rest);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE, rest);
else
mwdebi(av7110, DEBISWAB, bootblock,
- ((char*)data) + i * BOOT_MAX_SIZE - 4, rest + 4);
+ ((char*)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
- iwdebi(av7110, DEBISWAB, BOOT_BASE, swab32(base), 4);
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, rest, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
}
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
return -ETIMEDOUT;
}
- iwdebi(av7110, DEBINOSWAP, BOOT_SIZE, 0, 2);
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
- if (waitdebi(av7110, BOOT_STATE, BOOTSTATE_BOOT_COMPLETE) < 0) {
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
return -ETIMEDOUT;
}
@@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(4, "%p\n", av7110);
+ av7110->arm_ready = 0;
+
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
@@ -260,7 +262,7 @@ int av7110_bootarm(struct av7110 *av7110)
//saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode));
- iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
+ iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
@@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
+ av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@@ -1206,9 +1209,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
switch (cap->cmd) {
case OSD_CAP_MEMSIZE:
if (FW_4M_SDRAM(av7110->arm_app))
- cap->val = 1000000;
+ cap->val = 1000000;
else
- cap->val = 92000;
+ cap->val = 92000;
return 0;
default:
return -EINVAL;
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 2a5e87ba1052..4e173c67fbb2 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -18,7 +18,7 @@ enum av7110_bootstate
{
BOOTSTATE_BUFFER_EMPTY = 0,
BOOTSTATE_BUFFER_FULL = 1,
- BOOTSTATE_BOOT_COMPLETE = 2
+ BOOTSTATE_AV7110_BOOT_COMPLETE = 2
};
enum av7110_type_rec_play_format
@@ -167,7 +167,8 @@ enum av7110_encoder_command {
LoadVidCode,
SetMonitorType,
SetPanScanType,
- SetFreezeMode
+ SetFreezeMode,
+ SetWSSConfig
};
enum av7110_rec_play_state {
@@ -294,11 +295,11 @@ enum av7110_command_type {
#define DPRAM_BASE 0x4000
/* boot protocol area */
-#define BOOT_STATE (DPRAM_BASE + 0x3F8)
-#define BOOT_SIZE (DPRAM_BASE + 0x3FA)
-#define BOOT_BASE (DPRAM_BASE + 0x3FC)
-#define BOOT_BLOCK (DPRAM_BASE + 0x400)
-#define BOOT_MAX_SIZE 0xc00
+#define AV7110_BOOT_STATE (DPRAM_BASE + 0x3F8)
+#define AV7110_BOOT_SIZE (DPRAM_BASE + 0x3FA)
+#define AV7110_BOOT_BASE (DPRAM_BASE + 0x3FC)
+#define AV7110_BOOT_BLOCK (DPRAM_BASE + 0x400)
+#define AV7110_BOOT_MAX_SIZE 0xc00
/* firmware command protocol area */
#define IRQ_STATE (DPRAM_BASE + 0x0F4)
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index f5e59fc924af..9138132ad25f 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -17,6 +17,8 @@ static int av_cnt;
static struct av7110 *av_list[4];
static struct input_dev *input_dev;
+static u8 delay_timer_finished;
+
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,
@@ -112,13 +114,16 @@ static void av7110_emit_key(unsigned long parm)
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
+ delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
input_event(input_dev, EV_KEY, keycode, !0);
} else
- input_event(input_dev, EV_KEY, keycode, 2);
-
- } else
+ if (delay_timer_finished)
+ input_event(input_dev, EV_KEY, keycode, 2);
+ } else {
+ delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keycode, !0);
+ }
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@@ -145,7 +150,8 @@ static void input_register_keys(void)
static void input_repeat_key(unsigned long data)
{
- /* dummy routine to disable autorepeat in the input driver */
+ /* called by the input driver after rep[REP_DELAY] ms */
+ delay_timer_finished = 1;
}
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index b5aea4129fa7..94cf38c7e8a8 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
break;
}
+ case VIDIOC_G_SLICED_VBI_CAP:
+ {
+ struct v4l2_sliced_vbi_cap *cap = arg;
+ dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
+ memset(cap, 0, sizeof *cap);
+ if (FW_VERSION(av7110->arm_app) >= 0x2623) {
+ cap->service_set = V4L2_SLICED_WSS_625;
+ cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+ }
+ break;
+ }
+ case VIDIOC_G_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_G_FMT:\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ if (av7110->wssMode) {
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ }
+ break;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *f = arg;
+ dprintk(2, "VIDIOC_S_FMT\n");
+ if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
+ FW_VERSION(av7110->arm_app) < 0x2623)
+ return -EAGAIN; /* handled by core driver */
+ if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
+ f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ /* WSS controlled by firmware */
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
+ SetWSSConfig, 1, 0);
+ } else {
+ memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
+ f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
+ f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
+ /* WSS controlled by userspace */
+ av7110->wssMode = 1;
+ av7110->wssData = 0;
+ }
+ break;
+ }
default:
printk("no such ioctl\n");
return -ENOIOCTLCMD;
@@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
+static int av7110_vbi_reset(struct inode *inode, struct file *file)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ av7110->wssMode = 0;
+ av7110->wssData = 0;
+ if (FW_VERSION(av7110->arm_app) < 0x2623)
+ return 0;
+ else
+ return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+}
+
+static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+ struct saa7146_fh *fh = file->private_data;
+ struct saa7146_dev *dev = fh->dev;
+ struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
+ struct v4l2_sliced_vbi_data d;
+ int rc;
+
+ dprintk(2, "%s\n", __FUNCTION__);
+ if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
+ return -EINVAL;
+ if (copy_from_user(&d, data, count))
+ return -EFAULT;
+ if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
+ return -EINVAL;
+ if (d.id) {
+ av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig,
+ 2, 1, av7110->wssData);
+ } else {
+ av7110->wssData = 0;
+ rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
+ }
+ return (rc < 0) ? rc : count;
+}
/****************************************************************************
* INITIALIZATION
@@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
+ { VIDIOC_G_FMT, SAA7146_BEFORE },
+ { VIDIOC_S_FMT, SAA7146_BEFORE },
{ 0, 0 }
};
@@ -587,7 +682,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
- av7110->adac_type = DVB_ADAC_MSP;
+ av7110->adac_type = DVB_ADAC_MSP34x0;
msleep(100); // the probing above resets the msp...
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
@@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110)
saa7146_vv_release(dev);
return -ENODEV;
}
- if (av7110->analog_tuner_flags) {
- if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
- ERR(("cannot register vbi v4l2 device. skipping.\n"));
- } else {
+ if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
+ ERR(("cannot register vbi v4l2 device. skipping.\n"));
+ } else {
+ if (av7110->analog_tuner_flags)
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
- }
}
return 0;
}
@@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
static struct saa7146_ext_vv av7110_vv_data_st = {
.inputs = 1,
.audios = 1,
- .capabilities = 0,
+ .capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = 0,
.stds = &standard[0],
@@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
static struct saa7146_ext_vv av7110_vv_data_c = {
.inputs = 1,
.audios = 1,
- .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
+ .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
@@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
+
+ .vbi_fops.open = av7110_vbi_reset,
+ .vbi_fops.release = av7110_vbi_reset,
+ .vbi_fops.write = av7110_vbi_write,
};
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 9f51bae7194c..1465c04e49aa 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -37,6 +37,7 @@
#include "stv0299.h"
#include "tda10021.h"
#include "tda1004x.h"
+#include "dvb-pll.h"
#include <media/saa7146_vv.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -127,7 +128,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
+ result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -145,7 +146,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
- result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
+ result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@@ -192,7 +193,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 = 500; // 5 seconds (4.4.6 Ready)
+ int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@@ -256,19 +257,37 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
+ int cam_present = 0;
if (slot != 0)
return -EINVAL;
- if (!budget_av->slot_status) {
+ if (!budget_av->slot_status)
+ {
+ // first of all test the card detect line
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
if (saa7146_read(saa, PSR) & MASK_06)
{
+ cam_present = 1;
+ }
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+
+ // that is unreliable however, so try and read from IO memory
+ if (!cam_present)
+ {
+ saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+ if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
+ {
+ cam_present = 1;
+ }
+ }
+
+ // did we find something?
+ if (cam_present) {
printk(KERN_INFO "budget-av: cam inserted\n");
budget_av->slot_status = 1;
}
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
@@ -484,6 +503,140 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
return 0;
}
+#define MIN2(a,b) ((a) < (b) ? (a) : (b))
+#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
+
+static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend_parameters *params)
+{
+ u8 reg0 [2] = { 0x00, 0x00 };
+ u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
+ u8 reg2 [3] = { 0x02, 0x00, 0x00 };
+ int _fband;
+ int first_ZF;
+ int R, A, N, P, M;
+ struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
+ int freq = params->frequency;
+
+ first_ZF = (freq) / 1000;
+
+ if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
+ abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
+ _fband = 2;
+ else
+ _fband = 3;
+
+ if (_fband == 2) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1430) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ }
+
+ if(_fband == 3) {
+ if (((first_ZF >= 950) && (first_ZF < 1350)) ||
+ ((first_ZF >= 1455) && (first_ZF < 1950)))
+ reg0[1] = 0x07;
+ else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
+ ((first_ZF >= 1950) && (first_ZF < 2150)))
+ reg0[1] = 0x0B;
+ else if ((first_ZF >= 1420) && (first_ZF < 1455))
+ reg0[1] = 0x0F;
+ }
+
+ if (first_ZF > 1525)
+ reg1[1] |= 0x80;
+ else
+ reg1[1] &= 0x7F;
+
+ if (_fband == 2) {
+ if (first_ZF > 1430) { /* 1430MHZ */
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+
+ if (_fband == 3) {
+ if ((first_ZF >= 1455) &&
+ (first_ZF < 1630)) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ } else {
+ if (first_ZF < 1455) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg1[1] |= 0x20;
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ } else {
+ if (first_ZF >= 1630) {
+ reg1[1] &= 0xCF; /* N2 */
+ reg2[1] &= 0xCF; /* R2 */
+ reg2[1] |= 0x10;
+ }
+ }
+ }
+ }
+
+ /* set ports, enable P0 for symbol rates > 4Ms/s */
+ if (params->u.qpsk.symbol_rate >= 4000000)
+ reg1[1] |= 0x0c;
+ else
+ reg1[1] |= 0x04;
+
+ reg2[1] |= 0x0c;
+
+ R = 64;
+ A = 64;
+ P = 64; //32
+
+ M = (freq * R) / 4; /* in Mhz */
+ N = (M - A * 1000) / (P * 1000);
+
+ reg1[1] |= (N >> 9) & 0x03;
+ reg1[2] = (N >> 1) & 0xff;
+ reg1[3] = (N << 7) & 0x80;
+
+ reg2[1] |= (R >> 8) & 0x03;
+ reg2[2] = R & 0xFF; /* R */
+
+ reg1[3] |= A & 0x7f; /* A */
+
+ if (P == 64)
+ reg1[1] |= 0x40; /* Prescaler 64/65 */
+
+ reg0[1] |= 0x03;
+
+ /* already enabled - do not reenable i2c repeater or TX fails */
+ msg.buf = reg0;
+ msg.len = sizeof(reg0);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg1;
+ msg.len = sizeof(reg1);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ stv0299_enable_plli2c(fe);
+ msg.buf = reg2;
+ msg.len = sizeof(reg2);
+ if (i2c_transfer(i2c, &msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+
static u8 typhoon_cinergy1200s_inittab[] = {
0x01, 0x15,
0x02, 0x30,
@@ -553,6 +706,18 @@ static struct stv0299_config cinergy_1200s_config = {
.pll_set = philips_su1278_ty_ci_pll_set,
};
+static struct stv0299_config cinergy_1200s_1894_0010_config = {
+ .demod_address = 0x68,
+ .inittab = typhoon_cinergy1200s_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+ .pll_set = philips_su1278sh2_tua6100_pll_set,
+};
static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
@@ -700,8 +865,117 @@ static struct tda1004x_config philips_tu1216_config = {
.request_firmware = philips_tu1216_request_firmware,
};
+static u8 philips_sd1878_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7d,
+ 0x05, 0x35,
+ 0x06, 0x40,
+ 0x07, 0x00,
+ 0x08, 0x43,
+ 0x09, 0x02,
+ 0x0C, 0x51,
+ 0x0D, 0x82,
+ 0x0E, 0x23,
+ 0x10, 0x3f,
+ 0x11, 0x84,
+ 0x12, 0xb9,
+ 0x15, 0xc9,
+ 0x16, 0x19,
+ 0x17, 0x8c,
+ 0x18, 0x59,
+ 0x19, 0xf8,
+ 0x1a, 0xfe,
+ 0x1c, 0x7f,
+ 0x1d, 0x00,
+ 0x1e, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00,
+ 0x29, 0x28,
+ 0x2a, 0x14,
+ 0x2b, 0x0f,
+ 0x2c, 0x09,
+ 0x2d, 0x09,
+ 0x31, 0x1f,
+ 0x32, 0x19,
+ 0x33, 0xfc,
+ 0x34, 0x93,
+ 0xff, 0xff
+};
+
+static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c,
+ struct dvb_frontend_parameters *params)
+{
+ u8 buf[4];
+ int rc;
+ struct i2c_msg tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+
+ if((params->frequency < 950000) || (params->frequency > 2150000))
+ return -EINVAL;
+
+ rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
+ params->frequency, 0);
+ if(rc < 0) return rc;
+
+ if(i2c_transfer(i2c, &tuner_msg, 1) != 1)
+ return -EIO;
+
+ return 0;
+}
+static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
+ u32 srate, u32 ratio)
+{
+ u8 aclk = 0;
+ u8 bclk = 0;
+ u8 m1;
+ aclk = 0xb5;
+ if (srate < 2000000)
+ bclk = 0x86;
+ else if (srate < 5000000)
+ bclk = 0x89;
+ else if (srate < 15000000)
+ bclk = 0x8f;
+ else if (srate < 45000000)
+ bclk = 0x95;
+
+ m1 = 0x14;
+ if (srate < 4000000)
+ m1 = 0x10;
+
+ stv0299_writereg(fe, 0x0e, 0x23);
+ stv0299_writereg(fe, 0x0f, 0x94);
+ stv0299_writereg(fe, 0x10, 0x39);
+ stv0299_writereg(fe, 0x13, aclk);
+ stv0299_writereg(fe, 0x14, bclk);
+ stv0299_writereg(fe, 0x15, 0xc9);
+ stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+ stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+ stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+ stv0299_writereg(fe, 0x0f, 0x80 | m1);
+
+ return 0;
+}
+
+static struct stv0299_config philips_sd1878_config = {
+ .demod_address = 0x68,
+ .inittab = philips_sd1878_inittab,
+ .mclk = 88000000UL,
+ .invert = 0,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_1,
+ .volt13_op0_op1 = STV0299_VOLT13_OP0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
+ .pll_set = philips_sd1878_tda8261_pll_set,
+};
static u8 read_pwm(struct budget_av *budget_av)
{
@@ -722,7 +996,10 @@ static u8 read_pwm(struct budget_av *budget_av)
#define SUBID_DVBS_KNC1_PLUS 0x0011
#define SUBID_DVBS_TYPHOON 0x4f56
#define SUBID_DVBS_CINERGY1200 0x1154
+#define SUBID_DVBS_CYNERGY1200N 0x1155
+#define SUBID_DVBS_TV_STAR 0x0014
+#define SUBID_DVBS_TV_STAR_CI 0x0016
#define SUBID_DVBC_KNC1 0x0020
#define SUBID_DVBC_KNC1_PLUS 0x0021
#define SUBID_DVBC_CINERGY1200 0x1156
@@ -749,6 +1026,22 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
+ if (saa->pci->subsystem_vendor == 0x1894) {
+ fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
+ &budget_av->budget.i2c_adap);
+ } else {
+ fe = stv0299_attach(&typhoon_config,
+ &budget_av->budget.i2c_adap);
+ }
+ break;
+
+ case SUBID_DVBS_TV_STAR:
+ case SUBID_DVBS_TV_STAR_CI:
+ case SUBID_DVBS_CYNERGY1200N:
+ fe = stv0299_attach(&philips_sd1878_config,
+ &budget_av->budget.i2c_adap);
+ break;
+
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_TYPHOON:
fe = stv0299_attach(&typhoon_config,
@@ -854,11 +1147,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
dprintk(2, "dev: %p\n", dev);
- if (!(budget_av = kmalloc(sizeof(struct budget_av), GFP_KERNEL)))
+ if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
return -ENOMEM;
- memset(budget_av, 0, sizeof(struct budget_av));
-
budget_av->has_saa7113 = 0;
budget_av->budget.ci_present = 0;
@@ -993,22 +1284,28 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
+MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
+MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+ MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
+ MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
+ MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
+ MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
{
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 017fcbccb8cc..633e68c341c8 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -404,9 +404,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
/* frontend power on */
- if (bi->type == BUDGET_FS_ACTIVY)
- saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
- else
+ if (bi->type != BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
if (budget_register(budget) == 0) {
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index fafe6407b3d0..238c77b52f89 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -112,6 +112,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
+ * GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
@@ -121,11 +122,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
+ case SEC_VOLTAGE_OFF:
+ saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
+ break;
default:
return -EINVAL;
}
@@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
return 0;
}
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 buf;
@@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
if (lnbp21_init(budget)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
goto error_out;
@@ -624,7 +631,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
@@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
- break;
+ budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index fdaa3318ad3a..c7bb63c4d98d 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -19,7 +19,7 @@ extern int budget_debug;
#endif
#define dprintk(level,args...) \
- do { if ((budget_debug & level)) { printk("%s: %s(): ",__stringify(KBUILD_MODNAME), __FUNCTION__); printk(args); } } while (0)
+ do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
struct budget_info {
char *name;
@@ -95,6 +95,7 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_KNC1SP 11
#define BUDGET_KNC1CP 12
#define BUDGET_KNC1TP 13
+#define BUDGET_TVSTAR 14
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
index 18aa22b5478d..1f31e91195b0 100644
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c
@@ -13,7 +13,7 @@
Holger Waechtler Convergence
Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
- Metzler Brothers Systementwicklung GbR
+ Metzler Brothers Systementwicklung GbR
This 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/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index c6c1d41a2efb..914587d52b57 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -10,7 +10,7 @@ config DVB_TTUSB_BUDGET
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
- These devices don't have a MPEG decoder built in, so you need
+ These devices don't have a MPEG decoder built in, so you need
an external software decoder to watch TV.
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 104df610dbe1..5a13c4744f61 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1489,11 +1489,9 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;
- if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL)))
+ if (!(ttusb = kzalloc(sizeof(struct ttusb), GFP_KERNEL)))
return -ENOMEM;
- memset(ttusb, 0, sizeof(struct ttusb));
-
ttusb->dev = udev;
ttusb->c = 0;
ttusb->mux_state = 0;
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index c334526af66f..83611012ef34 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -8,14 +8,15 @@ config DVB_TTUSB_DEC
produced by Hauppauge, shipped under the brand name 'DEC2000-t'
and 'DEC3000-s'.
- Even if these devices have a MPEG decoder built in, they transmit
+ Even if these devices have a MPEG decoder built in, they transmit
only compressed MPEG data over the USB bus, so you need
an external software decoder to watch TV on your computer.
- This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
- download/extract them, and then copy them to /usr/lib/hotplug/firmware.
+ This driver needs external firmware. Please use the commands
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
+ "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
+ download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 8abc21890129..df831171e03c 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -369,7 +369,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->audio_filter->feed->feed.ts,
@@ -380,7 +380,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
{
- struct ttusb_dec *dec = (struct ttusb_dec *)priv;
+ struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->video_filter->feed->feed.ts,
@@ -965,8 +965,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TS_PES_TELETEXT:
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
- dprintk(" pes_type: DMX_TS_PES_TELETEXT\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
+ return -ENOSYS;
case DMX_TS_PES_PCR:
dprintk(" pes_type: DMX_TS_PES_PCR\n");
@@ -975,8 +975,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
break;
case DMX_TS_PES_OTHER:
- dprintk(" pes_type: DMX_TS_PES_OTHER\n");
- break;
+ dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n");
+ return -ENOSYS;
default:
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
@@ -1182,7 +1182,7 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
-static int ttusb_init_rc(struct ttusb_dec *dec)
+static int ttusb_init_rc( struct ttusb_dec *dec)
{
struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
@@ -1203,13 +1203,12 @@ static int ttusb_init_rc(struct ttusb_dec *dec)
input_dev->keycode = rc_keys;
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
- set_bit(rc_keys[i], input_dev->keybit);
+ set_bit(rc_keys[i], input_dev->keybit);
input_register_device(input_dev);
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
-
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
@@ -1395,6 +1394,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
/* We can't trust the USB IDs that some firmwares
give the box */
switch (model) {
+ case 0x00070001:
case 0x00070008:
case 0x0007000c:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@@ -1588,7 +1588,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
{
- struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
+ struct ttusb_dec* dec = fe->dvb->priv;
return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
}
@@ -1606,15 +1606,13 @@ static int ttusb_dec_probe(struct usb_interface *intf,
udev = interface_to_usbdev(intf);
- if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
+ if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
printk("%s: couldn't allocate memory.\n", __FUNCTION__);
return -ENOMEM;
}
usb_set_intfdata(intf, (void *)dec);
- memset(dec, 0, sizeof(struct ttusb_dec));
-
switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index 725af3af5b27..a5a46175fa09 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -42,8 +42,39 @@ struct ttusbdecfe_state {
static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
- FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ struct ttusbdecfe_state* state = fe->demodulator_priv;
+ u8 b[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+ u8 result[4];
+ int len, ret;
+
+ *status=0;
+
+ ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
+ if(ret)
+ return ret;
+
+ if(len != 4) {
+ printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ switch(result[3]) {
+ case 1: /* not tuned yet */
+ case 2: /* no signal/no lock*/
+ break;
+ case 3: /* signal found and locked*/
+ *status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
+ break;
+ case 4:
+ *status = FE_TIMEDOUT;
+ break;
+ default:
+ pr_info("%s: returned unknown value: %d\n",
+ __FUNCTION__, result[3]);
+ return -EIO;
+ }
return 0;
}
@@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
+static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
+ struct dvb_frontend_tune_settings* fesettings)
+{
+ fesettings->min_delay_ms = 1500;
+ /* Drift compensation makes no sense for DVB-T */
+ fesettings->step_size = 0;
+ fesettings->max_drift = 0;
+ return 0;
+}
+
static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
@@ -212,6 +253,8 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
.set_frontend = ttusbdecfe_dvbt_set_frontend,
+ .get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
+
.read_status = ttusbdecfe_read_status,
};
@@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
+ .symbol_rate_min = 1000000, /* guessed */
+ .symbol_rate_max = 45000000, /* guessed */
.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_FEC_AUTO |
- FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
- FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
- FE_CAN_HIERARCHY_AUTO,
+ FE_CAN_QPSK
},
.release = ttusbdecfe_release,
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index c2ebe8754a95..dc292da2605f 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -220,6 +220,7 @@ static struct file_operations pcm20_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = pcm20_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 877c770558e9..914deab4e044 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -299,6 +299,7 @@ static struct file_operations rtrack_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 5319a9c9a979..523be820f9c6 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -256,6 +256,7 @@ static struct file_operations aztech_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = az_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 9b0406318f2d..f1b5ac81e9d2 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -490,6 +490,7 @@ static struct file_operations cadet_fops = {
.release = cadet_release,
.read = cadet_read,
.ioctl = cadet_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 630cc786d0a4..8e499b8f64c7 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -301,6 +301,7 @@ static struct file_operations gemtek_pci_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_pci_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -317,11 +318,10 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
struct gemtek_pci_card *card;
struct video_device *devradio;
- if ( (card = kmalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
+ if ( (card = kzalloc( sizeof( struct gemtek_pci_card ), GFP_KERNEL )) == NULL ) {
printk( KERN_ERR "gemtek_pci: out of memory\n" );
return -ENOMEM;
}
- memset( card, 0, sizeof( struct gemtek_pci_card ) );
if ( pci_enable_device( pci_dev ) )
goto err_pci;
@@ -394,7 +394,7 @@ static struct pci_driver gemtek_pci_driver =
static int __init gemtek_pci_init_module( void )
{
- return pci_module_init( &gemtek_pci_driver );
+ return pci_register_driver( &gemtek_pci_driver );
}
static void __exit gemtek_pci_cleanup_module( void )
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 6418f03b9ce4..47173be97b9f 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -233,6 +233,7 @@ static struct file_operations gemtek_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index e5e2021a7312..36c9f5bf8cdd 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -27,34 +27,30 @@
#include <linux/pci.h>
#include <linux/videodev.h>
-#define DRIVER_VERSION "0.04"
+#define DRIVER_VERSION "0.05"
-#define PCI_VENDOR_ESS 0x125D
-#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 /* Maestro 2 */
-#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 /* Maestro 2E */
-
-#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
+#define GPIO_DATA 0x60 /* port offset from ESS_IO_BASE */
#define IO_MASK 4 /* mask register offset from GPIO_DATA
bits 1=unmask write to given bit */
#define IO_DIR 8 /* direction register offset from GPIO_DATA
bits 0/1=read/write direction */
-#define GPIO6 0x0040 /* mask bits for GPIO lines */
-#define GPIO7 0x0080
-#define GPIO8 0x0100
-#define GPIO9 0x0200
+#define GPIO6 0x0040 /* mask bits for GPIO lines */
+#define GPIO7 0x0080
+#define GPIO8 0x0100
+#define GPIO9 0x0200
-#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */
-#define STR_CLK GPIO7
-#define STR_WREN GPIO8
-#define STR_MOST GPIO9
+#define STR_DATA GPIO6 /* radio TEA5757 pins and GPIO bits */
+#define STR_CLK GPIO7
+#define STR_WREN GPIO8
+#define STR_MOST GPIO9
#define FREQ_LO 50*16000
#define FREQ_HI 150*16000
-#define FREQ_IF 171200 /* 10.7*16000 */
-#define FREQ_STEP 200 /* 12.5*16 */
+#define FREQ_IF 171200 /* 10.7*16000 */
+#define FREQ_STEP 200 /* 12.5*16 */
#define FREQ2BITS(x) ((((unsigned int)(x)+FREQ_IF+(FREQ_STEP<<1))\
/(FREQ_STEP<<2))<<2) /* (x==fmhz*16*1000) -> bits */
@@ -65,39 +61,58 @@ static int radio_nr = -1;
module_param(radio_nr, int, 0);
static int radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+ unsigned int cmd, unsigned long arg);
+static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void maestro_remove(struct pci_dev *pdev);
+
+static struct pci_device_id maestro_r_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1968),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00 },
+ { PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ESS1978),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, maestro_r_pci_tbl);
+
+static struct pci_driver maestro_r_driver = {
+ .name = "maestro_radio",
+ .id_table = maestro_r_pci_tbl,
+ .probe = maestro_probe,
+ .remove = __devexit_p(maestro_remove),
+};
static struct file_operations maestro_fops = {
.owner = THIS_MODULE,
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
-static struct video_device maestro_radio=
-{
- .owner = THIS_MODULE,
+static struct video_device maestro_radio = {
.name = "Maestro radio",
.type = VID_TYPE_TUNER,
.hardware = VID_HARDWARE_SF16MI,
- .fops = &maestro_fops,
+ .fops = &maestro_fops,
};
-static struct radio_device
-{
- __u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
+struct radio_device {
+ u16 io, /* base of Maestro card radio io (GPIO_DATA)*/
muted, /* VIDEO_AUDIO_MUTE */
stereo, /* VIDEO_TUNER_STEREO_ON */
tuned; /* signal strength (0 or 0xffff) */
- struct semaphore lock;
-} radio_unit = {0, 0, 0, 0, };
+ struct semaphore lock;
+};
-static __u32 radio_bits_get(struct radio_device *dev)
+static u32 radio_bits_get(struct radio_device *dev)
{
- register __u16 io=dev->io, l, rdata;
- register __u32 data=0;
- __u16 omask;
+ register u16 io=dev->io, l, rdata;
+ register u32 data=0;
+ u16 omask;
+
omask = inw(io + IO_MASK);
outw(~(STR_CLK | STR_WREN), io + IO_MASK);
outw(0, io);
@@ -120,17 +135,21 @@ static __u32 radio_bits_get(struct radio_device *dev)
data++;
udelay(2);
}
+
if(dev->muted)
outw(STR_WREN, io);
+
udelay(4);
outw(omask, io + IO_MASK);
+
return data & 0x3ffe;
}
-static void radio_bits_set(struct radio_device *dev, __u32 data)
+static void radio_bits_set(struct radio_device *dev, u32 data)
{
- register __u16 io=dev->io, l, bits;
- __u16 omask, odir;
+ register u16 io=dev->io, l, bits;
+ u16 omask, odir;
+
omask = inw(io + IO_MASK);
odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
outw(odir | STR_DATA, io + IO_DIR);
@@ -146,8 +165,10 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
outw(bits, io); /* LO level */
udelay(4);
}
+
if(!dev->muted)
outw(0, io);
+
udelay(4);
outw(omask, io + IO_MASK);
outw(odir, io + IO_DIR);
@@ -155,141 +176,103 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
}
static inline int radio_function(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+ unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
-
- switch(cmd) {
- case VIDIOCGCAP: {
- struct video_capability *v = arg;
- memset(v,0,sizeof(*v));
- strcpy(v->name, "Maestro radio");
- v->type=VID_TYPE_TUNER;
- v->channels=v->audios=1;
- return 0;
- }
- case VIDIOCGTUNER: {
- struct video_tuner *v = arg;
- if(v->tuner)
- return -EINVAL;
- (void)radio_bits_get(card);
- v->flags = VIDEO_TUNER_LOW | card->stereo;
- v->signal = card->tuned;
- strcpy(v->name, "FM");
- v->rangelow = FREQ_LO;
- v->rangehigh = FREQ_HI;
- v->mode = VIDEO_MODE_AUTO;
- return 0;
- }
- case VIDIOCSTUNER: {
- struct video_tuner *v = arg;
- if(v->tuner!=0)
- return -EINVAL;
- return 0;
- }
- case VIDIOCGFREQ: {
- unsigned long *freq = arg;
- *freq = BITS2FREQ(radio_bits_get(card));
- return 0;
- }
- case VIDIOCSFREQ: {
- unsigned long *freq = arg;
- if (*freq<FREQ_LO || *freq>FREQ_HI )
- return -EINVAL;
- radio_bits_set(card, FREQ2BITS(*freq));
+ struct radio_device *card = video_get_drvdata(dev);
+
+ switch (cmd) {
+ case VIDIOCGCAP: {
+ struct video_capability *v = arg;
+ memset(v, 0, sizeof(*v));
+ strcpy(v->name, "Maestro radio");
+ v->type = VID_TYPE_TUNER;
+ v->channels = v->audios = 1;
+ return 0;
+ } case VIDIOCGTUNER: {
+ struct video_tuner *v = arg;
+ if (v->tuner)
+ return -EINVAL;
+ (void)radio_bits_get(card);
+ v->flags = VIDEO_TUNER_LOW | card->stereo;
+ v->signal = card->tuned;
+ strcpy(v->name, "FM");
+ v->rangelow = FREQ_LO;
+ v->rangehigh = FREQ_HI;
+ v->mode = VIDEO_MODE_AUTO;
+ return 0;
+ } case VIDIOCSTUNER: {
+ struct video_tuner *v = arg;
+ if (v->tuner != 0)
+ return -EINVAL;
+ return 0;
+ } case VIDIOCGFREQ: {
+ unsigned long *freq = arg;
+ *freq = BITS2FREQ(radio_bits_get(card));
+ return 0;
+ } case VIDIOCSFREQ: {
+ unsigned long *freq = arg;
+ if (*freq < FREQ_LO || *freq > FREQ_HI)
+ return -EINVAL;
+ radio_bits_set(card, FREQ2BITS(*freq));
+ return 0;
+ } case VIDIOCGAUDIO: {
+ struct video_audio *v = arg;
+ memset(v, 0, sizeof(*v));
+ strcpy(v->name, "Radio");
+ v->flags = VIDEO_AUDIO_MUTABLE | card->muted;
+ v->mode = VIDEO_SOUND_STEREO;
+ return 0;
+ } case VIDIOCSAUDIO: {
+ struct video_audio *v = arg;
+ if (v->audio)
+ return -EINVAL;
+ {
+ register u16 io = card->io;
+ register u16 omask = inw(io + IO_MASK);
+ outw(~STR_WREN, io + IO_MASK);
+ outw((card->muted = v->flags & VIDEO_AUDIO_MUTE) ?
+ STR_WREN : 0, io);
+ udelay(4);
+ outw(omask, io + IO_MASK);
+ msleep(125);
return 0;
}
- case VIDIOCGAUDIO: {
- struct video_audio *v = arg;
- memset(v,0,sizeof(*v));
- strcpy(v->name, "Radio");
- v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
- v->mode=VIDEO_SOUND_STEREO;
- return 0;
- }
- case VIDIOCSAUDIO: {
- struct video_audio *v = arg;
- if(v->audio)
- return -EINVAL;
- {
- register __u16 io=card->io;
- register __u16 omask = inw(io + IO_MASK);
- outw(~STR_WREN, io + IO_MASK);
- outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
- ? STR_WREN : 0, io);
- udelay(4);
- outw(omask, io + IO_MASK);
- msleep(125);
- return 0;
- }
- }
- case VIDIOCGUNIT: {
- struct video_unit *v = arg;
- v->video=VIDEO_NO_UNIT;
- v->vbi=VIDEO_NO_UNIT;
- v->radio=dev->minor;
- v->audio=0;
- v->teletext=VIDEO_NO_UNIT;
- return 0;
- }
- default: return -ENOIOCTLCMD;
+ } case VIDIOCGUNIT: {
+ struct video_unit *v = arg;
+ v->video = VIDEO_NO_UNIT;
+ v->vbi = VIDEO_NO_UNIT;
+ v->radio = dev->minor;
+ v->audio = 0;
+ v->teletext = VIDEO_NO_UNIT;
+ return 0;
+ } default:
+ return -ENOIOCTLCMD;
}
}
static int radio_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct video_device *dev = video_devdata(file);
- struct radio_device *card=dev->priv;
+ struct radio_device *card = video_get_drvdata(dev);
int ret;
down(&card->lock);
ret = video_usercopy(inode, file, cmd, arg, radio_function);
up(&card->lock);
- return ret;
-}
-static __u16 radio_install(struct pci_dev *pcidev);
-
-MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
-MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
-MODULE_LICENSE("GPL");
-
-static void __exit maestro_radio_exit(void)
-{
- video_unregister_device(&maestro_radio);
+ return ret;
}
-static int __init maestro_radio_init(void)
+static u16 __devinit radio_power_on(struct radio_device *dev)
{
- register __u16 found=0;
- struct pci_dev *pcidev = NULL;
- while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
- PCI_DEVICE_ID_ESS_ESS1968,
- pcidev)))
- found |= radio_install(pcidev);
- while(!found && (pcidev = pci_find_device(PCI_VENDOR_ESS,
- PCI_DEVICE_ID_ESS_ESS1978,
- pcidev)))
- found |= radio_install(pcidev);
- if(!found) {
- printk(KERN_INFO "radio-maestro: no devices found.\n");
- return -ENODEV;
- }
- return 0;
-}
+ register u16 io = dev->io;
+ register u32 ofreq;
+ u16 omask, odir;
-module_init(maestro_radio_init);
-module_exit(maestro_radio_exit);
-
-static inline __u16 radio_power_on(struct radio_device *dev)
-{
- register __u16 io=dev->io;
- register __u32 ofreq;
- __u16 omask, odir;
omask = inw(io + IO_MASK);
- odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
+ odir = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
outw(odir & ~STR_WREN, io + IO_DIR);
dev->muted = inw(io) & STR_WREN ? 0 : VIDEO_AUDIO_MUTE;
outw(odir, io + IO_DIR);
@@ -298,35 +281,101 @@ static inline __u16 radio_power_on(struct radio_device *dev)
udelay(16);
outw(omask, io + IO_MASK);
ofreq = radio_bits_get(dev);
- if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
+
+ if ((ofreq < FREQ2BITS(FREQ_LO)) || (ofreq > FREQ2BITS(FREQ_HI)))
ofreq = FREQ2BITS(FREQ_LO);
radio_bits_set(dev, ofreq);
+
return (ofreq == radio_bits_get(dev));
}
-static __u16 radio_install(struct pci_dev *pcidev)
+static int __devinit maestro_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
- if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
- return 0;
-
- radio_unit.io = pcidev->resource[0].start + GPIO_DATA;
- maestro_radio.priv = &radio_unit;
- init_MUTEX(&radio_unit.lock);
-
- if(radio_power_on(&radio_unit)) {
- if(video_register_device(&maestro_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
- printk("radio-maestro: can't register device!");
- return 0;
- }
- printk(KERN_INFO "radio-maestro: version "
- DRIVER_VERSION
- " time "
- __TIME__ " "
- __DATE__
- "\n");
- printk(KERN_INFO "radio-maestro: radio chip initialized\n");
- return 1;
- } else
- return 0;
+ struct radio_device *radio_unit;
+ struct video_device *maestro_radio_inst;
+ int retval;
+
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "enabling pci device failed!\n");
+ goto err;
+ }
+
+ retval = -ENOMEM;
+
+ radio_unit = kzalloc(sizeof(*radio_unit), GFP_KERNEL);
+ if (radio_unit == NULL) {
+ dev_err(&pdev->dev, "not enough memory\n");
+ goto err;
+ }
+
+ radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
+ init_MUTEX(&radio_unit->lock);
+
+ maestro_radio_inst = video_device_alloc();
+ if (maestro_radio_inst == NULL) {
+ dev_err(&pdev->dev, "not enough memory\n");
+ goto errfr;
+ }
+
+ memcpy(maestro_radio_inst, &maestro_radio, sizeof(maestro_radio));
+ video_set_drvdata(maestro_radio_inst, radio_unit);
+ pci_set_drvdata(pdev, maestro_radio_inst);
+
+ retval = video_register_device(maestro_radio_inst, VFL_TYPE_RADIO,
+ radio_nr);
+ if (retval) {
+ printk(KERN_ERR "can't register video device!\n");
+ goto errfr1;
+ }
+
+ if (!radio_power_on(radio_unit)) {
+ retval = -EIO;
+ goto errunr;
+ }
+
+ dev_info(&pdev->dev, "version " DRIVER_VERSION " time " __TIME__ " "
+ __DATE__ "\n");
+ dev_info(&pdev->dev, "radio chip initialized\n");
+
+ return 0;
+errunr:
+ video_unregister_device(maestro_radio_inst);
+errfr1:
+ kfree(maestro_radio_inst);
+errfr:
+ kfree(radio_unit);
+err:
+ return retval;
+
+}
+
+static void __devexit maestro_remove(struct pci_dev *pdev)
+{
+ struct video_device *vdev = pci_get_drvdata(pdev);
+
+ video_unregister_device(vdev);
}
+static int __init maestro_radio_init(void)
+{
+ int retval = pci_register_driver(&maestro_r_driver);
+
+ if (retval)
+ printk(KERN_ERR "error during registration pci driver\n");
+
+ return retval;
+}
+
+static void __exit maestro_radio_exit(void)
+{
+ pci_unregister_driver(&maestro_r_driver);
+}
+
+module_init(maestro_radio_init);
+module_exit(maestro_radio_exit);
+
+MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
+MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 02d39a50d5ed..c975ddd86cd5 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -80,6 +80,7 @@ static struct file_operations maxiradio_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device maxiradio_radio =
@@ -337,7 +338,7 @@ static struct pci_driver maxiradio_driver = {
static int __init maxiradio_radio_init(void)
{
- return pci_module_init(&maxiradio_driver);
+ return pci_register_driver(&maxiradio_driver);
}
static void __exit maxiradio_radio_exit(void)
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index b2256d675b44..28a47c9e7a81 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -199,6 +199,7 @@ static struct file_operations rtrack2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 6f03ce4dd7b0..0229f792a059 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -225,6 +225,7 @@ static struct file_operations fmi_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmi_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 71971e9bb342..099ffb3b9c71 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -48,7 +48,7 @@ static int io = 0x384;
static int radio_nr = -1;
/* hw precision is 12.5 kHz
- * It is only usefull to give freq in intervall of 200 (=0.0125Mhz),
+ * It is only useful to give freq in intervall of 200 (=0.0125Mhz),
* other bits will be truncated
*/
#define RSF16_ENCODE(x) ((x)/200+856)
@@ -356,6 +356,7 @@ static struct file_operations fmr2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmr2_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index b03573c6840e..fcfde2e4f195 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -276,6 +276,7 @@ static struct file_operations terratec_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tt_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index b300bedf7c74..5a099a50d4d0 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -255,6 +255,7 @@ static struct file_operations trust_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tr_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index f304f3c14763..8ac9a8ef9094 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -261,6 +261,7 @@ static struct file_operations typhoon_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = typhoon_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 4c6d6fb49034..d590e80c922e 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -313,6 +313,7 @@ static struct file_operations zoltrix_fops =
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = zol_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index fc87efc5049c..d82c8a30ba44 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,6 +7,15 @@ menu "Video For Linux"
comment "Video Adapters"
+config VIDEO_ADV_DEBUG
+ bool "Enable advanced debug functionality"
+ depends on VIDEO_DEV
+ default n
+ ---help---
+ Say Y here to enable advanced debugging functionality on some
+ V4L devices.
+ In doubt, say N.
+
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
@@ -174,7 +183,7 @@ config VIDEO_STRADIS
help
Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
driver for PCI. There is a product page at
- <http://www.stradis.com/decoder.html>.
+ <http://www.stradis.com/>.
config VIDEO_ZORAN
tristate "Zoran ZR36057/36067 Video For Linux"
@@ -342,6 +351,6 @@ config VIDEO_DECODER
depends on VIDEO_DEV && I2C && EXPERIMENTAL
---help---
Say Y here to compile drivers for SAA7115, SAA7127 and CX25840
- video decoders.
+ video decoders.
endmenu
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 82060f9909d8..faf728366c4e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -3,15 +3,20 @@
#
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
- bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
+ bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+ bttv-input.o
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.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
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
+tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
+ mt20xx.o tda8290.o tea5767.o
+
+msp3400-objs := msp3400-driver.o msp3400-kthreads.o
+
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
- tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o
+ tda7432.o tda9875.o ir-kbd-i2c.o
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 1ca2b67aedfb..4ce07ae62dac 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -413,14 +413,12 @@ adv7170_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_adv7170;
- client->flags = I2C_CLIENT_ALLOW_USE;
if ((client->addr == I2C_ADV7170 >> 1) ||
(client->addr == (I2C_ADV7170 >> 1) + 1)) {
dname = adv7170_name;
@@ -434,12 +432,11 @@ adv7170_detect_client (struct i2c_adapter *adapter,
}
strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct adv7170), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct adv7170));
encoder->norm = VIDEO_MODE_NTSC;
encoder->input = 0;
encoder->enable = 1;
@@ -498,11 +495,11 @@ adv7170_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_adv7170 = {
- .owner = THIS_MODULE,
- .name = "adv7170", /* name */
+ .driver = {
+ .name = "adv7170", /* name */
+ },
.id = I2C_DRIVERID_ADV7170,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adv7170_attach_adapter,
.detach_client = adv7170_detach_client,
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 173bca1e0295..4e218f22b214 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -463,14 +463,12 @@ adv7175_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_adv7175;
- client->flags = I2C_CLIENT_ALLOW_USE;
if ((client->addr == I2C_ADV7175 >> 1) ||
(client->addr == (I2C_ADV7175 >> 1) + 1)) {
dname = adv7175_name;
@@ -484,12 +482,11 @@ adv7175_detect_client (struct i2c_adapter *adapter,
}
strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct adv7175));
encoder->norm = VIDEO_MODE_PAL;
encoder->input = 0;
encoder->enable = 1;
@@ -548,11 +545,11 @@ adv7175_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_adv7175 = {
- .owner = THIS_MODULE,
- .name = "adv7175", /* name */
+ .driver = {
+ .name = "adv7175", /* name */
+ },
.id = I2C_DRIVERID_ADV7175,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = adv7175_attach_adapter,
.detach_client = adv7175_detach_client,
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 881cdcb1875d..994b75fe165a 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -129,9 +129,9 @@ static unsigned char yuv[MAX_AR_FRAME_BYTES];
static int freq = DEFAULT_FREQ; /* BCLK: available 50 or 70 (MHz) */
static int vga = 0; /* default mode(0:QVGA mode, other:VGA mode) */
static int vga_interlace = 0; /* 0 is normal mode for, else interlace mode */
-MODULE_PARM(freq, "i");
-MODULE_PARM(vga, "i");
-MODULE_PARM(vga_interlace, "i");
+module_param(freq, int, 0);
+module_param(vga, int, 0);
+module_param(vga_interlace, int, 0);
static int ar_initialize(struct video_device *dev);
@@ -749,6 +749,7 @@ static struct file_operations ar_fops = {
.release = video_exclusive_release,
.read = ar_read,
.ioctl = ar_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 3ee0afca76a7..d6447791d0e5 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -528,22 +528,18 @@ bt819_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_bt819;
- client->flags = I2C_CLIENT_ALLOW_USE;
- decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
-
- memset(decoder, 0, sizeof(struct bt819));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
@@ -623,11 +619,11 @@ bt819_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_bt819 = {
- .owner = THIS_MODULE,
- .name = "bt819",
+ .driver = {
+ .name = "bt819",
+ },
.id = I2C_DRIVERID_BT819,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = bt819_attach_adapter,
.detach_client = bt819_detach_client,
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index 3ca1d768bfd3..cc54b62f4601 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -30,8 +30,9 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
-
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
+
#include "bttv.h"
#include "bt832.h"
@@ -42,9 +43,10 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
-/* ---------------------------------------------------------------------- */
+int debug; /* debug output */
+module_param(debug, int, 0644);
-#define dprintk if (debug) printk
+/* ---------------------------------------------------------------------- */
static int bt832_detach(struct i2c_client *client);
@@ -61,23 +63,26 @@ int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf)
int i,rc;
buf[0]=0x80; // start at register 0 with auto-increment
if (1 != (rc = i2c_master_send(i2c_client_s,buf,1)))
- printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc);
for(i=0;i<65;i++)
buf[i]=0;
if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65)))
- printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc);
// Note: On READ the first byte is the current index
// (e.g. 0x80, what we just wrote)
- if(1) {
+ if(debug>1) {
int i;
- printk("BT832 hexdump:\n");
+ v4l_dbg(2, debug,i2c_client_s,"hexdump:");
for(i=1;i<65;i++) {
if(i!=1) {
- if(((i-1)%8)==0) printk(" ");
- if(((i-1)%16)==0) printk("\n");
+ if(((i-1)%8)==0) printk(" ");
+ if(((i-1)%16)==0) {
+ printk("\n");
+ v4l_dbg(2, debug,i2c_client_s,"hexdump:");
+ }
}
printk(" %02x",buf[i]);
}
@@ -96,56 +101,56 @@ int bt832_init(struct i2c_client *i2c_client_s)
bt832_hexdump(i2c_client_s,buf);
if(buf[0x40] != 0x31) {
- printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
+ v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
kfree(buf);
return 0;
}
- printk("Write 0 tp VPSTATUS\n");
+ v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n");
buf[0]=BT832_VP_STATUS; // Reg.52
buf[1]= 0x00;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// Leave low power mode:
- printk("Bt832: leave low power mode.\n");
+ v4l_err(i2c_client_s,"leave low power mode.\n");
buf[0]=BT832_CAM_SETUP0; //0x39 57
buf[1]=0x08;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
- printk("Write 0 tp VPSTATUS\n");
+ v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n");
buf[0]=BT832_VP_STATUS; // Reg.52
buf[1]= 0x00;
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// Enable Output
- printk("Enable Output\n");
+ v4l_info(i2c_client_s,"Enable Output\n");
buf[0]=BT832_VP_CONTROL1; // Reg.40
buf[1]= 0x27 & (~0x01); // Default | !skip
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
+ v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc);
bt832_hexdump(i2c_client_s,buf);
// for testing (even works when no camera attached)
- printk("bt832: *** Generate NTSC M Bars *****\n");
+ v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n");
buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42
buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
- printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
+ v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
- printk("Bt832: Camera Present: %s\n",
+ v4l_info(i2c_client_s,"Camera Present: %s\n",
(buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no");
bt832_hexdump(i2c_client_s,buf);
@@ -159,20 +164,18 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct bt832 *t;
- printk("bt832_attach\n");
-
client_template.adapter = adap;
client_template.addr = addr;
- printk("bt832: chip found @ 0x%x\n", addr<<1);
-
- if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
+ if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
- memset(t,0,sizeof(*t));
t->client = client_template;
i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
+ v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1);
+
+
if(! bt832_init(&t->client)) {
bt832_detach(&t->client);
return -1;
@@ -183,13 +186,8 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
static int bt832_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, bt832_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, bt832_attach);
-#endif
return 0;
}
@@ -197,7 +195,7 @@ static int bt832_detach(struct i2c_client *client)
{
struct bt832 *t = i2c_get_clientdata(client);
- printk("bt832: detach.\n");
+ v4l_info(&t->client,"dettach\n");
i2c_detach_client(client);
kfree(t);
return 0;
@@ -208,7 +206,8 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct bt832 *t = i2c_get_clientdata(client);
- printk("bt832: command %x\n",cmd);
+ if (debug>1)
+ v4l_i2c_print_ioctl(&t->client,cmd);
switch (cmd) {
case BT832_HEXDUMP: {
@@ -219,7 +218,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
break;
case BT832_REATTACH:
- printk("bt832: re-attach\n");
+ v4l_info(&t->client,"re-attach\n");
i2c_del_driver(&driver);
i2c_add_driver(&driver);
break;
@@ -230,10 +229,10 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c bt832 driver",
- .id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "bt832",
+ },
+ .id = 0, /* FIXME */
.attach_adapter = bt832_probe,
.detach_client = bt832_detach,
.command = bt832_command,
@@ -241,7 +240,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "bt832",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 8eb871d0e85b..909b593530ed 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -316,22 +316,19 @@ bt856_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_bt856;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct bt856));
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
@@ -405,11 +402,11 @@ bt856_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_bt856 = {
- .owner = THIS_MODULE,
- .name = "bt856",
+ .driver = {
+ .name = "bt856",
+ },
.id = I2C_DRIVERID_BT856,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = bt856_attach_adapter,
.detach_client = bt856_detach_client,
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c
index a48de3c0e3f0..b4aca7249276 100644
--- a/drivers/media/video/btcx-risc.c
+++ b/drivers/media/video/btcx-risc.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
-static unsigned int debug = 0;
+static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 012be639aa18..9749d6ed6231 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -38,6 +38,7 @@
#include <asm/io.h>
#include "bttvp.h"
+#include <media/v4l2-common.h>
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
@@ -91,8 +92,8 @@ static void identify_by_eeprom(struct bttv *btv,
static int __devinit pvr_boot(struct bttv *btv);
/* config variables */
-static unsigned int triton1=0;
-static unsigned int vsfx=0;
+static unsigned int triton1;
+static unsigned int vsfx;
static unsigned int latency = UNSET;
int no_overlay=-1;
@@ -105,7 +106,7 @@ static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL };
#ifdef MODULE
static unsigned int autoload = 1;
#else
-static unsigned int autoload = 0;
+static unsigned int autoload;
#endif
static unsigned int gpiomask = UNSET;
static unsigned int audioall = UNSET;
@@ -292,6 +293,9 @@ static struct CARD {
/* likely broken, vendor id doesn't match the other magic views ...
* { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+ /* Duplicate PCI ID, reconfigure for this board during the eeprom read.
+ * { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */
+
/* DVB cards (using pci function .1 for mpeg data xfer) */
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
@@ -317,7 +321,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -329,8 +333,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -343,8 +347,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -357,8 +361,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 4, 0, 2, 3, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 4, 0, 2, 3, 1 },
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -376,7 +380,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 2,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
@@ -390,8 +394,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 0, 1, 0, 1, 3},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 0, 1, 0, 1, 3 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -403,9 +407,9 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 3,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.gpiomask = 0x0f,
- .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0},
+ .audiomux = { 0x0c, 0x04, 0x08, 0x04, 0 },
/* 0x04 for some cards ?? */
.needs_tvaudio = 1,
.tuner_type = -1,
@@ -421,8 +425,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 3,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
- .audiomux = {0 },
+ .muxsel = { 2, 3, 1, 0, 0 },
+ .audiomux = { 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -437,8 +441,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xc00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0xc00, 0x800, 0x400, 0xc00, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -452,8 +456,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 1, 2, 3, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 2, 3, 0 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -467,8 +471,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x0f, /* old: 7 */
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -482,8 +486,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x3014f,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20001,0x10001, 0, 0,10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20001,0x10001, 0, 0,10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -498,8 +502,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 14, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 14, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -512,8 +516,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 14, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 14, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.msp34xx_alt = 1,
.pll = PLL_28,
@@ -530,8 +534,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 2, 1, 3, 4}, /* old: { 0, 1, 2, 3, 4} */
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 2, 1, 3, 4 }, /* old: {0, 1, 2, 3, 4} */
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -545,8 +549,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0 , 0, 1 , 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0 , 0, 1 , 0, 10 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -561,7 +565,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x01fe00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
#if 0
/* old */
.audiomux = { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },
@@ -580,8 +584,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x8300f8,
- .muxsel = { 2, 3, 1, 1,0},
- .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},
+ .muxsel = { 2, 3, 1, 1,0 },
+ .audiomux = { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -596,8 +600,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {1, 0, 0, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 0, 0, 0, 0 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -610,7 +614,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = -1,
.gpiomask = 0x8dff00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.no_msp34xx = 1,
.tuner_type = -1,
@@ -625,7 +629,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 3,
.tuner = 0,
.svhs = 2,
- .muxsel = {2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -637,8 +641,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL_I,
.tuner_addr = ADDR_UNSET,
@@ -651,8 +655,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xc00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0, 1, 0x800, 0x400, 0xc00, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 0x800, 0x400, 0xc00, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -684,8 +688,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xe00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = {0x400, 0x400, 0x400, 0x400, 0xc00 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -700,8 +704,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1f0fff,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000 },
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -715,8 +719,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 7,
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.needs_tvaudio = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -729,8 +733,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_SECAM,
.tuner_addr = ADDR_UNSET,
@@ -745,8 +749,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1f0fff,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x20000, 0x30000, 0x10000, 0x00000, 0x40000 },
.needs_tvaudio = 0,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -808,7 +812,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800, /* 0x8dfe00 */
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x0800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
@@ -822,7 +826,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 1,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 1, 0, 0, 0, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -838,7 +842,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 2,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = 4,
@@ -852,8 +856,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xffff00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x500, 0, 0x300, 0x900, 0x900},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x500, 0, 0x300, 0x900, 0x900 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -866,7 +870,7 @@ struct tvcard bttv_tvcards[] = {
.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 */
#if 0
.gpiomask = 0xc33000,
.audiomux = { 0x422000,0x1000,0x0000,0x620000,0x800000 },
@@ -902,8 +906,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800 },
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -918,7 +922,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = -1,
@@ -948,7 +952,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x551e00,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.audiomux = { 0x551400, 0x551200, 0, 0, 0x551c00, 0x551200 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -964,8 +968,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0xd0001, 0, 0, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0xd0001, 0, 0, 1 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = -1,
@@ -981,8 +985,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 4, 0, 2, 3, 1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 4, 0, 2, 3, 1 },
.no_msp34xx = 1,
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_NTSC,
@@ -998,8 +1002,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 13, 4, 11, 7, 0, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 13, 4, 11, 7, 0, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1031,8 +1035,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xe00b,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc },
.no_msp34xx = 1,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1047,8 +1051,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 3,
- .muxsel = {2, 3, 1, 1},
- .audiomux = {1, 1, 0, 2, 3},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 0, 2, 3 },
.no_msp34xx = 1,
.pll = PLL_NONE,
.tuner_type = -1,
@@ -1062,8 +1066,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 3,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
- .audiomux = {0 },
+ .muxsel = { 2, 3, 1, 0, 0 },
+ .audiomux = { 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1077,8 +1081,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xbcf03f,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = 21,
@@ -1092,7 +1096,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x70000,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x20000, 0x30000, 0x10000, 0, 0x40000, 0x20000 },
.needs_tvaudio = 1,
.no_msp34xx = 1,
@@ -1111,8 +1115,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {2,0,0,0,1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = {2,0,0,0,1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1126,8 +1130,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x010f00,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0},
+ .muxsel = {2, 3, 0, 0 },
+ .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
@@ -1168,8 +1172,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 7,
- .muxsel = { 2, 0, 1, 1},
- .audiomux = { 0, 1, 2, 3, 4},
+ .muxsel = { 2, 0, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
.pll = PLL_28,
.tuner_type = -1 /* TUNER_ALPS_TMDH2_NTSC */,
.tuner_addr = ADDR_UNSET,
@@ -1185,8 +1189,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 3,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 0xd0001, 0, 0, 10},
+ .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)
0= ext. Audio IN
@@ -1211,7 +1215,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1c,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0, 0x10, 8, 4 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -1232,7 +1236,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x18e0,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x0000,0x0800,0x1000,0x1000,0x18e0 },
/* For cards with tda9820/tda9821:
0x0000: Tuner normal stereo
@@ -1252,8 +1256,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xF,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_PAL,
@@ -1270,7 +1274,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x1800,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0x800, 0x1000, 0x1000, 0x1800, 0 },
.pll = PLL_28,
.tuner_type = 5,
@@ -1320,8 +1324,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x03000F,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 2,0,0,0,1 },
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 2, 0, 0, 0, 1 },
.pll = PLL_28,
.tuner_type = 0,
.tuner_addr = ADDR_UNSET,
@@ -1337,8 +1341,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 11,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 1, 8},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 1, 8 },
.pll = PLL_35,
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1352,7 +1356,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 1,
.gpiomask = 0xF,
- .muxsel = { 2, 2},
+ .muxsel = { 2, 2 },
.audiomux = { },
.no_msp34xx = 1,
.needs_tvaudio = 0,
@@ -1371,8 +1375,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xFF,
- .muxsel = { 2, 3, 1, 0},
- .audiomux = { 1, 0, 4, 4, 9},
+ .muxsel = { 2, 3, 1, 0 },
+ .audiomux = { 1, 0, 4, 4, 9 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1388,7 +1392,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0xf03f,
.muxsel = { 2, 3, 1, 0 },
- .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe},
+ .audiomux = { 0xbffe, 0, 0xbfff, 0, 0xbffe },
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
.tuner_addr = ADDR_UNSET,
@@ -1404,8 +1408,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 1,
- .muxsel = { 2, 3, 0, 1},
- .audiomux = { 0, 0, 1, 0, 0},
+ .muxsel = { 2, 3, 0, 1 },
+ .audiomux = { 0, 0, 1, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_TEMIC_4006FN5_MULTI_PAL,
@@ -1420,7 +1424,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x18e0,
- .muxsel = { 2, 3, 0, 1},
+ .muxsel = { 2, 3, 0, 1 },
/* Radio changed from 1e80 to 0x800 to make
FlyVideo2000S in .hu happy (gm)*/
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
@@ -1441,8 +1445,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0xffff00,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0x500, 0x500, 0x300, 0x900, 0x900 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -1458,8 +1462,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x010f00,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0x10000, 0, 0x10000, 0, 0, 0},
+ .muxsel = {2, 3, 0, 0 },
+ .audiomux = {0x10000, 0, 0x10000, 0, 0, 0 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
@@ -1483,7 +1487,7 @@ struct tvcard bttv_tvcards[] = {
.audiomux = {0x947fff, 0x987fff,0x947fff,0x947fff, 0x947fff},
/* tvtuner, radio, external,internal, mute, stereo
* tuner, Composit, SVid, Composit-on-Svid-adapter */
- .muxsel = { 2, 3 ,0 ,1},
+ .muxsel = { 2, 3 ,0 ,1 },
.tuner_type = TUNER_MT2032,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1511,8 +1515,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 0, 0, 11, 7, 13, 0}, /* TV and Radio with same GPIO ! */
+ .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,
@@ -1533,7 +1537,7 @@ struct tvcard bttv_tvcards[] = {
.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,
@@ -1579,7 +1583,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1,
.svhs = 4,
.gpiomask = 0,
- .muxsel = { 2, 3, 1, 0, 0},
+ .muxsel = { 2, 3, 1, 0, 0 },
.audiomux = { 0 },
.needs_tvaudio = 0,
.tuner_type = -1,
@@ -1692,7 +1696,7 @@ struct tvcard bttv_tvcards[] = {
.name = "DSP Design TCVIDEO",
.video_inputs = 4,
.svhs = -1,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.pll = PLL_28,
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
@@ -1706,7 +1710,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 0, 1, 1},
+ .muxsel = { 2, 0, 1, 1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = -1,
@@ -1723,7 +1727,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x0f0f80,
- .muxsel = {2, 3, 1, 0},
+ .muxsel = {2, 3, 1, 0 },
.audiomux = {0x030000, 0x010000, 0, 0, 0x020000, 0},
.no_msp34xx = 1,
.pll = PLL_28,
@@ -1940,7 +1944,7 @@ struct tvcard bttv_tvcards[] = {
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
- .muxsel = { 3, 0, 1, 2},
+ .muxsel = { 3, 0, 1, 2 },
.pll = PLL_28,
.no_gpioirq = 1,
.has_dvb = 1,
@@ -1953,7 +1957,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 3,
.gpiomask = 2,
/* TV, Comp1, Composite over SVID con, SVID */
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 2, 2, 0, 0, 0 },
.pll = PLL_28,
.has_radio = 1,
@@ -2070,7 +2074,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 1}, /* Tuner, CVid, SVid, CVid over SVid connector */
+ .muxsel = { 2, 3, 1, 1 }, /* Tuner, CVid, SVid, CVid over SVid connector */
.gpiomask = 0,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2124,7 +2128,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 1,
.tuner = -1,
.svhs = -1,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2136,7 +2140,6 @@ struct tvcard bttv_tvcards[] = {
.has_remote = 1,
.gpiomask = 0x1b,
.no_gpioirq = 1,
- .any_irq = 1,
},
[BTTV_BOARD_PV143] = {
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
@@ -2163,7 +2166,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2178,7 +2181,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = -1, /* card has no tuner */
.svhs = 3,
.gpiomask = 0x00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0, 0, 0, 0, 0, 0 }, /* card has no audio */
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2265,7 +2268,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = TUNER_PHILIPS_ATSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2288,7 +2291,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 0,
.svhs = 1,
.tuner = -1,
- .muxsel = { 3, 1, 1, 3}, /* Vid In, SVid In, Vid over SVid in connector */
+ .muxsel = { 3, 1, 1, 3 }, /* Vid In, SVid In, Vid over SVid in connector */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2304,8 +2307,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 3,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 1, 1, 1, 1, 0},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 1, 1, 1, 1, 0 },
.needs_tvaudio = 1,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2324,7 +2327,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.pll = PLL_28,
- .muxsel = { 2, 2, 2, 2},
+ .muxsel = { 2, 2, 2, 2 },
.gpiomask = 0x3F,
.muxsel_hook = gvc1100_muxsel,
},
@@ -2335,8 +2338,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x008007,
- .muxsel = {2, 3, 0, 0},
- .audiomux = {0, 0, 0, 0, 0x000003, 0},
+ .muxsel = { 2, 3, 0, 0 },
+ .audiomux = { 0, 0, 0, 0, 0x000003, 0 },
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
@@ -2371,7 +2374,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.needs_tvaudio = 0,
.gpiomask = 0x68,
- .muxsel = { 2, 3, 1},
+ .muxsel = { 2, 3, 1 },
.audiomux = { 0x68, 0x68, 0x61, 0x61, 0x00 },
.pll = PLL_28,
},
@@ -2430,7 +2433,7 @@ struct tvcard bttv_tvcards[] = {
.svhs = 2,
.gpiomask = 0x0000000f,
.muxsel = { 2, 1, 1 },
- .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00},
+ .audiomux = { 0x02, 0x00, 0x00, 0x00, 0x00 },
.tuner_type = TUNER_TEMIC_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2463,7 +2466,7 @@ struct tvcard bttv_tvcards[] = {
.video_inputs = 2,
.tuner = -1,
.svhs = 1,
- .muxsel = { 3, 1, 2, 0}, /* Comp0, S-Video, ?, ? */
+ .muxsel = { 3, 1, 2, 0 }, /* Comp0, S-Video, ?, ? */
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2520,8 +2523,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = -1,
.gpiomask = 0xFF,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 2, 0, 0, 0, 10},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 10 },
.needs_tvaudio = 0,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_PAL,
@@ -2554,8 +2557,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x3f,
- .muxsel = {2, 3, 1, 0},
- .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31},
+ .muxsel = {2, 3, 1, 0 },
+ .audiomux = {0x31, 0x31, 0x31, 0x31, 0x31, 0x31 },
.no_msp34xx = 1,
.pll = PLL_28,
.tuner_type = TUNER_PHILIPS_NTSC_M,
@@ -2573,12 +2576,12 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.gpiomask = 0x008007,
- .audiomux = { 0, 0x000001,0,0, 0},
+ .audiomux = { 0, 0x000001,0,0, 0 },
.needs_tvaudio = 1,
.has_radio = 1,
},
@@ -2669,7 +2672,7 @@ struct tvcard bttv_tvcards[] = {
.audio_inputs = 1,
.tuner = 0,
.svhs = 2,
- .muxsel = { 2, 3, 1, 0},
+ .muxsel = { 2, 3, 1, 0 },
.tuner_type = -1,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2703,7 +2706,7 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x01fe00,
- .muxsel = { 2, 3, 1, 1},
+ .muxsel = { 2, 3, 1, 1 },
.audiomux = { 0x001e00, 0, 0x018000, 0x014000, 0x002000, 0 },
.needs_tvaudio = 1,
.pll = PLL_28,
@@ -2791,8 +2794,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 15,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = {2,0,0,0,1},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 2, 0, 0, 0, 1 },
.needs_tvaudio = 1,
.pll = PLL_28,
.tuner_type = 2,
@@ -2807,8 +2810,8 @@ struct tvcard bttv_tvcards[] = {
.tuner = 0,
.svhs = 2,
.gpiomask = 0x108007,
- .muxsel = { 2, 3, 1, 1},
- .audiomux = { 100000, 100002, 100002, 100000},
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 100000, 100002, 100002, 100000 },
.no_msp34xx = 1,
.no_tda9875 = 1,
.no_tda7432 = 1,
@@ -2817,6 +2820,45 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.has_radio = 1,
},
+ /* ---- card 0x8f ---------------------------------- */
+ [BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
+ .name = "Hauppauge ImpactVCB (bt878)",
+ .video_inputs = 4,
+ .audio_inputs = 0,
+ .tuner = -1,
+ .svhs = -1,
+ .gpiomask = 0x0f, /* old: 7 */
+ .muxsel = { 0, 1, 3, 2 }, /* Composite 0-3 */
+ .no_msp34xx = 1,
+ .no_tda9875 = 1,
+ .no_tda7432 = 1,
+ .tuner_type = -1,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ },
+ [BTTV_BOARD_MACHTV_MAGICTV] = {
+ /* Julian Calaby <julian.calaby@gmail.com>
+ * Slightly different from original MachTV definition (0x60)
+
+ * FIXME: RegSpy says gpiomask should be "0x001c800f", but it
+ * stuffs up remote chip. Bug is a pin on the jaecs is not set
+ * properly (methinks) causing no keyup bits being set */
+
+ .name = "MagicTV", /* rebranded MachTV */
+ .video_inputs = 3,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .gpiomask = 7,
+ .muxsel = { 2, 3, 1, 1 },
+ .audiomux = { 0, 1, 2, 3, 4 },
+ .tuner_type = TUNER_TEMIC_4009FR5_PAL,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .pll = PLL_28,
+ .has_radio = 1,
+ .has_remote = 1,
+ },
};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -3037,26 +3079,33 @@ static void miro_pinnacle_gpio(struct bttv *btv)
switch (id) {
case 1:
info = "PAL / mono";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 2:
info = "PAL+SECAM / stereo";
btv->has_radio = 1;
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 3:
info = "NTSC / stereo";
btv->has_radio = 1;
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 4:
info = "PAL+SECAM / mono";
+ btv->tda9887_conf = TDA9887_QSS;
break;
case 5:
info = "NTSC / mono";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 6:
info = "NTSC / stereo";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
case 7:
info = "PAL / stereo";
+ btv->tda9887_conf = TDA9887_INTERCARRIER;
break;
default:
info = "oops: unknown card";
@@ -3067,8 +3116,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
printk(KERN_INFO
"bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
- btv->tuner_type = 33;
- btv->pinnacle_id = id;
+ btv->tuner_type = TUNER_MT2032;
}
}
@@ -3370,9 +3418,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
}
- if (btv->pinnacle_id != UNSET) {
- bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE,
- &btv->pinnacle_id);
+ if (btv->tda9887_conf) {
+ bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG,
+ &btv->tda9887_conf);
}
btv->svhs = bttv_tvcards[btv->c.type].svhs;
@@ -3387,8 +3435,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->has_remote=1;
if (!bttv_tvcards[btv->c.type].no_gpioirq)
btv->gpioirq=1;
- if (bttv_tvcards[btv->c.type].any_irq)
- btv->any_irq = 1;
if (bttv_tvcards[btv->c.type].audio_hook)
btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
@@ -3424,7 +3470,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
/* tuner modules */
tda9887 = 0;
- if (btv->pinnacle_id != UNSET)
+ if (btv->tda9887_conf)
tda9887 = 1;
if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
@@ -3471,6 +3517,21 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
btv->tuner_type = tv.tuner_type;
btv->has_radio = tv.has_radio;
+
+ printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
+ btv->c.nr, tv.model);
+
+ /*
+ * Some of the 878 boards have duplicate PCI IDs. Switch the board
+ * type based on model #.
+ */
+ if(tv.model == 64900) {
+ printk("bttv%d: Switching board type from %s to %s\n",
+ btv->c.nr,
+ bttv_tvcards[btv->c.type].name,
+ bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
+ btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
+ }
}
static int terratec_active_radio_upgrade(struct bttv *btv)
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 1ddf9ba613ef..aa4c4c521880 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -34,60 +34,60 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kdev_t.h>
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/byteorder.h>
-#include "bttvp.h"
-
#include "rds.h"
unsigned int bttv_num; /* number of Bt848s in use */
struct bttv bttvs[BTTV_MAX];
-unsigned int bttv_debug = 0;
+unsigned int bttv_debug;
unsigned int bttv_verbose = 1;
-unsigned int bttv_gpio = 0;
+unsigned int bttv_gpio;
/* config variables */
#ifdef __BIG_ENDIAN
static unsigned int bigendian=1;
#else
-static unsigned int bigendian=0;
+static unsigned int bigendian;
#endif
static unsigned int radio[BTTV_MAX];
-static unsigned int irq_debug = 0;
+static unsigned int irq_debug;
static unsigned int gbuffers = 8;
static unsigned int gbufsize = 0x208000;
static int video_nr = -1;
static int radio_nr = -1;
static int vbi_nr = -1;
-static int debug_latency = 0;
+static int debug_latency;
-static unsigned int fdsr = 0;
+static unsigned int fdsr;
/* options */
-static unsigned int combfilter = 0;
-static unsigned int lumafilter = 0;
+static unsigned int combfilter;
+static unsigned int lumafilter;
static unsigned int automute = 1;
-static unsigned int chroma_agc = 0;
+static unsigned int chroma_agc;
static unsigned int adc_crush = 1;
static unsigned int whitecrush_upper = 0xCF;
static unsigned int whitecrush_lower = 0x7F;
-static unsigned int vcr_hack = 0;
-static unsigned int irq_iswitch = 0;
+static unsigned int vcr_hack;
+static unsigned int irq_iswitch;
static unsigned int uv_ratio = 50;
-static unsigned int full_luma_range = 0;
-static unsigned int coring = 0;
+static unsigned int full_luma_range;
+static unsigned int coring;
extern int no_overlay;
/* API features (turn on/off stuff for testing) */
static unsigned int v4l2 = 1;
-
/* insmod args */
module_param(bttv_verbose, int, 0644);
module_param(bttv_gpio, int, 0644);
@@ -210,6 +210,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 255,
.sram = 0,
+ /* ITU-R frame line number of the first VBI line
+ we can capture, of the first and second field. */
+ .vbistart = { 7,320 },
},{
.v4l2_id = V4L2_STD_NTSC_M,
.name = "NTSC",
@@ -226,6 +229,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = 1,
+ .vbistart = { 10, 273 },
},{
.v4l2_id = V4L2_STD_SECAM,
.name = "SECAM",
@@ -242,6 +246,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 255,
.sram = 0, /* like PAL, correct? */
+ .vbistart = { 7, 320 },
},{
.v4l2_id = V4L2_STD_PAL_Nc,
.name = "PAL-Nc",
@@ -258,6 +263,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 7, 320 },
},{
.v4l2_id = V4L2_STD_PAL_M,
.name = "PAL-M",
@@ -274,6 +280,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x1a,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 10, 273 },
},{
.v4l2_id = V4L2_STD_PAL_N,
.name = "PAL-N",
@@ -290,6 +297,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x20,
.vbipack = 144,
.sram = -1,
+ .vbistart = { 7, 320},
},{
.v4l2_id = V4L2_STD_NTSC_M_JP,
.name = "NTSC-JP",
@@ -306,6 +314,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vdelay = 0x16,
.vbipack = 144,
.sram = -1,
+ .vbistart = {10, 273},
},{
/* that one hopefully works with the strange timing
* which video recorders produce when playing a NTSC
@@ -326,6 +335,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
.vbipack = 255,
.vtotal = 524,
.sram = -1,
+ .vbistart = { 10, 273 },
}
};
static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
@@ -674,16 +684,16 @@ int check_alloc_btres(struct bttv *btv, struct bttv_fh *fh, int bit)
return 1;
/* is it free? */
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
if (btv->resources & bit) {
/* no, someone else uses it */
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 0;
}
/* it's free, grab it */
fh->resources |= bit;
btv->resources |= bit;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
return 1;
}
@@ -706,10 +716,10 @@ void free_btres(struct bttv *btv, struct bttv_fh *fh, int bits)
/* trying to free ressources not allocated by us ... */
printk("bttv: BUG! (btres)\n");
}
- down(&btv->reslock);
+ mutex_lock(&btv->reslock);
fh->resources &= ~bits;
btv->resources &= ~bits;
- up(&btv->reslock);
+ mutex_unlock(&btv->reslock);
}
/* ----------------------------------------------------------------------- */
@@ -1510,14 +1520,6 @@ static struct videobuf_queue_ops bttv_video_qops = {
.buf_release = buffer_release,
};
-static const char *v4l1_ioctls[] = {
- "?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -1534,12 +1536,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
case VIDIOCSFREQ:
{
unsigned long *freq = arg;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq=*freq;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,*freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1569,10 +1571,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->mode >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,v->mode);
bttv_call_i2c_clients(btv,cmd,v);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1609,17 +1611,17 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (v->norm >= BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
if (channel == btv->input &&
v->norm == btv->tvnorm) {
/* nothing to do */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
btv->tvnorm = v->norm;
set_input(btv,v->channel);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1632,14 +1634,14 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
v->flags |= VIDEO_AUDIO_MUTABLE;
v->mode = VIDEO_SOUND_MONO;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
bttv_call_i2c_clients(btv,cmd,v);
/* card specific hooks */
if (btv->audio_hook)
btv->audio_hook(btv,v,0);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOCSAUDIO:
@@ -1650,7 +1652,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (audio >= bttv_tvcards[btv->c.type].audio_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
audio_mux(btv, (v->flags&VIDEO_AUDIO_MUTE) ? AUDIO_MUTE : AUDIO_UNMUTE);
bttv_call_i2c_clients(btv,cmd,v);
@@ -1658,7 +1660,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,v,1);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1692,10 +1694,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (i == BTTV_TVNORMS)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_tvnorm(btv,i);
i2c_vidiocschan(btv);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_QUERYSTD:
@@ -1753,9 +1755,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (*i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
set_input(btv,*i);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1767,7 +1769,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
memset(t,0,sizeof(*t));
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
@@ -1802,7 +1804,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
}
}
/* FIXME: fill capability+audmode */
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_S_TUNER:
@@ -1813,7 +1815,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (0 != t->index)
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
{
struct video_audio va;
memset(&va, 0, sizeof(struct video_audio));
@@ -1830,7 +1832,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (btv->audio_hook)
btv->audio_hook(btv,&va,1);
}
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -1851,12 +1853,12 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return -EINVAL;
if (unlikely (f->type != V4L2_TUNER_ANALOG_TV))
return -EINVAL;
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->freq = f->frequency;
bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq);
if (btv->has_matchbox && btv->radio_user)
tea5757_set_freq(btv,btv->freq);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
case VIDIOC_LOG_STATUS:
@@ -2206,22 +2208,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
unsigned long flags;
int retval = 0;
- if (bttv_debug > 1) {
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
- btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
- btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
- break;
- default:
- printk("bttv%d: ioctl 0x%x (???)\n",
- btv->c.nr, cmd);
- }
- }
+ if (bttv_debug > 1)
+ v4l_print_ioctl(btv->c.name, cmd);
+
if (btv->errors)
bttv_reinit_bt848(btv);
@@ -2570,10 +2559,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
fmt->count[0] = fmt2.fmt.vbi.count[0];
fmt->start[1] = fmt2.fmt.vbi.start[1];
fmt->count[1] = fmt2.fmt.vbi.count[1];
- if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
- fmt->flags |= V4L2_VBI_UNSYNC;
- if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
- fmt->flags |= V4L2_VBI_INTERLACED;
+ if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
+ fmt->flags |= VBI_UNSYNC;
+ if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
+ fmt->flags |= VBI_INTERLACED;
return 0;
}
case VIDIOCSVBIFMT:
@@ -3120,6 +3109,7 @@ static struct file_operations bttv_fops =
.open = bttv_open,
.release = bttv_release,
.ioctl = bttv_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
.read = bttv_read,
.mmap = bttv_mmap,
@@ -3166,7 +3156,7 @@ static int radio_open(struct inode *inode, struct file *file)
return -ENODEV;
dprintk("bttv%d: open called (radio)\n",btv->c.nr);
- down(&btv->lock);
+ mutex_lock(&btv->lock);
btv->radio_user++;
@@ -3175,7 +3165,7 @@ static int radio_open(struct inode *inode, struct file *file)
bttv_call_i2c_clients(btv,AUDC_SET_RADIO,&btv->tuner_type);
audio_mux(btv,AUDIO_RADIO);
- up(&btv->lock);
+ mutex_unlock(&btv->lock);
return 0;
}
@@ -3229,6 +3219,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
case VIDIOCSFREQ:
case VIDIOCGAUDIO:
case VIDIOCSAUDIO:
+ case VIDIOC_LOG_STATUS:
return bttv_common_ioctls(btv,cmd,arg);
default:
@@ -3701,8 +3692,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
btv=(struct bttv *)dev_id;
- if (btv->any_irq)
- handled = bttv_any_irq(&btv->c);
+ if (btv->custom_irq)
+ handled = btv->custom_irq(btv);
count=0;
while (1) {
@@ -3738,9 +3729,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
if (astat&BT848_INT_VSYNC)
btv->field_count++;
- if (astat & BT848_INT_GPINT) {
+ if ((astat & BT848_INT_GPINT) && btv->remote) {
wake_up(&btv->gpioq);
- bttv_gpio_irq(&btv->c);
+ bttv_input_irq(btv);
}
if (astat & BT848_INT_I2CDONE) {
@@ -3929,8 +3920,8 @@ static int __devinit bttv_probe(struct pci_dev *dev,
sprintf(btv->c.name,"bttv%d",btv->c.nr);
/* initialize structs / fill in defaults */
- init_MUTEX(&btv->lock);
- init_MUTEX(&btv->reslock);
+ mutex_init(&btv->lock);
+ mutex_init(&btv->reslock);
spin_lock_init(&btv->s_lock);
spin_lock_init(&btv->gpio_lock);
init_waitqueue_head(&btv->gpioq);
@@ -3946,7 +3937,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
btv->i2c_rc = -1;
btv->tuner_type = UNSET;
- btv->pinnacle_id = UNSET;
btv->new_input = UNSET;
btv->has_radio=radio[btv->c.nr];
@@ -4065,11 +4055,11 @@ static int __devinit bttv_probe(struct pci_dev *dev,
}
/* add subdevices */
- if (btv->has_remote)
- bttv_sub_add_device(&btv->c, "remote");
if (bttv_tvcards[btv->c.type].has_dvb)
bttv_sub_add_device(&btv->c, "dvb");
+ bttv_input_init(btv);
+
/* everything is fine */
bttv_num++;
return 0;
@@ -4104,6 +4094,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
/* tell gpio modules we are leaving ... */
btv->shutdown=1;
wake_up(&btv->gpioq);
+ bttv_input_fini(btv);
bttv_sub_del_devices(&btv->c);
/* unregister i2c_bus + input */
@@ -4253,7 +4244,7 @@ static int bttv_init_module(void)
bttv_check_chipset();
bus_register(&bttv_sub_bus_type);
- return pci_module_init(&bttv_pci_driver);
+ return pci_register_driver(&bttv_pci_driver);
}
static void bttv_cleanup_module(void)
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index 616a5b7e510c..c4d5e2b70c28 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
+static int bttv_sub_probe(struct device *dev)
+{
+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+ return sub->probe ? sub->probe(sdev) : -ENODEV;
+}
+
+static int bttv_sub_remove(struct device *dev)
+{
+ struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+ struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+ if (sub->remove)
+ sub->remove(sdev);
+ return 0;
+}
+
struct bus_type bttv_sub_bus_type = {
- .name = "bttv-sub",
- .match = &bttv_sub_bus_match,
+ .name = "bttv-sub",
+ .match = &bttv_sub_bus_match,
+ .probe = bttv_sub_probe,
+ .remove = bttv_sub_remove,
};
EXPORT_SYMBOL(bttv_sub_bus_type);
@@ -64,10 +84,9 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
struct bttv_sub_device *sub;
int err;
- sub = kmalloc(sizeof(*sub),GFP_KERNEL);
+ sub = kzalloc(sizeof(*sub),GFP_KERNEL);
if (NULL == sub)
return -ENOMEM;
- memset(sub,0,sizeof(*sub));
sub->core = core;
sub->dev.parent = &core->pci->dev;
@@ -113,24 +132,6 @@ void bttv_gpio_irq(struct bttv_core *core)
}
}
-int bttv_any_irq(struct bttv_core *core)
-{
- struct bttv_sub_driver *drv;
- struct bttv_sub_device *dev;
- struct list_head *item;
- int handled = 0;
-
- list_for_each(item,&core->subs) {
- dev = list_entry(item,struct bttv_sub_device,list);
- drv = to_bttv_sub_drv(dev->dev.driver);
- if (drv && drv->any_irq) {
- if (drv->any_irq(dev))
- handled = 1;
- }
- }
- return handled;
-}
-
/* ----------------------------------------------------------------------- */
/* external: sub-driver register/unregister */
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index 77619eb131f6..614c12018557 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -28,10 +28,11 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
static struct i2c_adapter bttv_i2c_adap_sw_template;
@@ -40,9 +41,9 @@ static struct i2c_client bttv_i2c_client_template;
static int attach_inform(struct i2c_client *client);
-static int i2c_debug = 0;
-static int i2c_hw = 0;
-static int i2c_scan = 0;
+static int i2c_debug;
+static int i2c_hw;
+static int i2c_scan;
module_param(i2c_debug, int, 0644);
module_param(i2c_hw, int, 0444);
module_param(i2c_scan, int, 0444);
@@ -105,10 +106,8 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
static struct i2c_adapter bttv_i2c_adap_sw_template = {
.owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
- .name = "bt848",
+ .name = "bttv",
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
};
@@ -275,10 +274,8 @@ static struct i2c_algorithm bttv_algo = {
};
static struct i2c_adapter bttv_i2c_adap_hw_template = {
- .owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
+ .owner = THIS_MODULE,
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "bt878",
.id = I2C_HW_B_BT848 /* FIXME */,
.algo = &bttv_algo,
@@ -300,7 +297,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,
+ btv->c.nr, client->driver->driver.name, client->addr,
client->name);
if (!client->driver->command)
return 0;
@@ -441,12 +438,10 @@ int __devinit init_bttv_i2c(struct bttv *btv)
i2c_set_adapdata(&btv->c.i2c_adap, btv);
btv->i2c_client.adapter = &btv->c.i2c_adap;
-#ifdef I2C_CLASS_TV_ANALOG
if (bttv_tvcards[btv->c.type].no_video)
btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG;
if (bttv_tvcards[btv->c.type].has_dvb)
btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
-#endif
if (btv->use_i2c_hw) {
btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/bttv-input.c
index de1385e5d05e..221b36e7f392 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/bttv-input.c
@@ -24,11 +24,9 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/input.h>
-#include <linux/pci.h>
-
-#include <media/ir-common.h>
#include "bttv.h"
+#include "bttvp.h"
/* ---------------------------------------------------------------------- */
@@ -156,9 +154,6 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
-/* Ricardo Cerqueira <v4l@cerqueira.org> */
-/* Weird matching, since the remote has "uncommon" keys */
-
static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = {
[ 30 ] = KEY_POWER, // power
@@ -279,34 +274,6 @@ static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
[0x36] = KEY_PC
};
-struct IR {
- struct bttv_sub_device *sub;
- struct input_dev *input;
- struct ir_input_state ir;
- char name[32];
- char phys[32];
-
- /* Usual gpio signalling */
-
- u32 mask_keycode;
- u32 mask_keydown;
- u32 mask_keyup;
- u32 polling;
- u32 last_gpio;
- struct work_struct work;
- struct timer_list timer;
-
- /* RC5 gpio */
- u32 rc5_gpio;
- struct timer_list timer_end; /* timer_end for code completion */
- struct timer_list timer_keyup; /* timer_end for key release */
- u32 last_rc5; /* last good rc5 code */
- u32 last_bit; /* last raw bit seen */
- u32 code; /* raw code under construction */
- struct timeval base_time; /* time of last seen code */
- int active; /* building raw code */
-};
-
static int debug;
module_param(debug, int, 0644); /* debug level (0,1,2) */
static int repeat_delay = 500;
@@ -314,31 +281,17 @@ module_param(repeat_delay, int, 0644);
static int repeat_period = 33;
module_param(repeat_period, int, 0644);
-#define DEVNAME "ir-kbd-gpio"
-#define dprintk(fmt, arg...) if (debug) \
- printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
-
-static void ir_irq(struct bttv_sub_device *sub);
-static int ir_probe(struct device *dev);
-static int ir_remove(struct device *dev);
-
-static struct bttv_sub_driver driver = {
- .drv = {
- .name = DEVNAME,
- .probe = ir_probe,
- .remove = ir_remove,
- },
- .gpio_irq = ir_irq,
-};
+#define DEVNAME "bttv-input"
/* ---------------------------------------------------------------------- */
-static void ir_handle_key(struct IR *ir)
+static void ir_handle_key(struct bttv *btv)
{
+ struct bttv_ir *ir = btv->remote;
u32 gpio,data;
/* read gpio value */
- gpio = bttv_gpio_read(ir->sub->core);
+ gpio = bttv_gpio_read(&btv->c);
if (ir->polling) {
if (ir->last_gpio == gpio)
return;
@@ -347,56 +300,36 @@ static void ir_handle_key(struct IR *ir)
/* extract data */
data = ir_extract_bits(gpio, ir->mask_keycode);
- dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
+ dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
gpio, data,
ir->polling ? "poll" : "irq",
(gpio & ir->mask_keydown) ? " down" : "",
(gpio & ir->mask_keyup) ? " up" : "");
- if (ir->mask_keydown) {
- /* bit set on keydown */
- if (gpio & ir->mask_keydown) {
- ir_input_keydown(ir->input, &ir->ir, data, data);
- } else {
- ir_input_nokey(ir->input, &ir->ir);
- }
-
- } else if (ir->mask_keyup) {
- /* bit cleared on keydown */
- if (0 == (gpio & ir->mask_keyup)) {
- ir_input_keydown(ir->input, &ir->ir, data, data);
- } else {
- ir_input_nokey(ir->input, &ir->ir);
- }
-
+ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
+ (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
+ ir_input_keydown(ir->dev,&ir->ir,data,data);
} else {
- /* can't disturgissh keydown/up :-/ */
- ir_input_keydown(ir->input, &ir->ir, data, data);
- ir_input_nokey(ir->input, &ir->ir);
+ ir_input_nokey(ir->dev,&ir->ir);
}
-}
-static void ir_irq(struct bttv_sub_device *sub)
-{
- struct IR *ir = dev_get_drvdata(&sub->dev);
-
- if (!ir->polling)
- ir_handle_key(ir);
}
-static void ir_timer(unsigned long data)
+void bttv_input_irq(struct bttv *btv)
{
- struct IR *ir = (struct IR*)data;
+ struct bttv_ir *ir = btv->remote;
- schedule_work(&ir->work);
+ if (!ir->polling)
+ ir_handle_key(btv);
}
-static void ir_work(void *data)
+static void bttv_input_timer(unsigned long data)
{
- struct IR *ir = data;
+ struct bttv *btv = (struct bttv*)data;
+ struct bttv_ir *ir = btv->remote;
unsigned long timeout;
- ir_handle_key(ir);
+ ir_handle_key(btv);
timeout = jiffies + (ir->polling * HZ / 1000);
mod_timer(&ir->timer, timeout);
}
@@ -435,26 +368,26 @@ static u32 rc5_decode(unsigned int code)
rc5 |= 1;
break;
case 3:
- dprintk("bad code: %x\n", org_code);
+ dprintk(KERN_WARNING "bad code: %x\n", org_code);
return 0;
}
}
- dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+ dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
"instr=%x\n", rc5, org_code, RC5_START(rc5),
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
return rc5;
}
-static int ir_rc5_irq(struct bttv_sub_device *sub)
+static int bttv_rc5_irq(struct bttv *btv)
{
- struct IR *ir = dev_get_drvdata(&sub->dev);
+ struct bttv_ir *ir = btv->remote;
struct timeval tv;
u32 gpio;
u32 gap;
unsigned long current_jiffies, timeout;
/* read gpio port */
- gpio = bttv_gpio_read(ir->sub->core);
+ gpio = bttv_gpio_read(&btv->c);
/* remote IRQ? */
if (!(gpio & 0x20))
@@ -493,14 +426,15 @@ static int ir_rc5_irq(struct bttv_sub_device *sub)
}
/* toggle GPIO pin 4 to reset the irq */
- bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
- bttv_gpio_write(ir->sub->core, gpio | (1 << 4));
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+ bttv_gpio_write(&btv->c, gpio | (1 << 4));
return 1;
}
-static void ir_rc5_timer_end(unsigned long data)
+
+static void bttv_rc5_timer_end(unsigned long data)
{
- struct IR *ir = (struct IR *)data;
+ struct bttv_ir *ir = (struct bttv_ir *)data;
struct timeval tv;
unsigned long current_jiffies, timeout;
u32 gap;
@@ -519,20 +453,20 @@ static void ir_rc5_timer_end(unsigned long data)
/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
if (gap < 28000) {
- dprintk("spurious timer_end\n");
+ dprintk(KERN_WARNING "spurious timer_end\n");
return;
}
ir->active = 0;
if (ir->last_bit < 20) {
/* ignore spurious codes (caused by light/other remotes) */
- dprintk("short code: %x\n", ir->code);
+ dprintk(KERN_WARNING "short code: %x\n", ir->code);
} else {
u32 rc5 = rc5_decode(ir->code);
/* two start bits? */
if (RC5_START(rc5) != 3) {
- dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5));
+ dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
/* right address? */
} else if (RC5_ADDR(rc5) == 0x0) {
@@ -542,10 +476,10 @@ static void ir_rc5_timer_end(unsigned long data)
/* Good code, decide if repeat/repress */
if (toggle != RC5_TOGGLE(ir->last_rc5) ||
instr != RC5_INSTR(ir->last_rc5)) {
- dprintk("instruction %x, toggle %x\n", instr,
+ dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
toggle);
- ir_input_nokey(ir->input, &ir->ir);
- ir_input_keydown(ir->input, &ir->ir, instr,
+ ir_input_nokey(ir->dev, &ir->ir);
+ ir_input_keydown(ir->dev, &ir->ir, instr,
instr);
}
@@ -560,34 +494,37 @@ static void ir_rc5_timer_end(unsigned long data)
}
}
-static void ir_rc5_timer_keyup(unsigned long data)
+static void bttv_rc5_timer_keyup(unsigned long data)
{
- struct IR *ir = (struct IR *)data;
+ struct bttv_ir *ir = (struct bttv_ir *)data;
- dprintk("key released\n");
- ir_input_nokey(ir->input, &ir->ir);
+ dprintk(KERN_DEBUG "key released\n");
+ ir_input_nokey(ir->dev, &ir->ir);
}
/* ---------------------------------------------------------------------- */
-static int ir_probe(struct device *dev)
+int bttv_input_init(struct bttv *btv)
{
- struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
- struct IR *ir;
- struct input_dev *input_dev;
+ struct bttv_ir *ir;
IR_KEYTAB_TYPE *ir_codes = NULL;
+ struct input_dev *input_dev;
int ir_type = IR_TYPE_OTHER;
- ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+ if (!btv->has_remote)
+ return -ENODEV;
+
+ ir = kzalloc(sizeof(*ir),GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
kfree(ir);
input_free_device(input_dev);
return -ENOMEM;
}
+ memset(ir,0,sizeof(*ir));
/* detect & configure */
- switch (sub->core->type) {
+ switch (btv->c.type) {
case BTTV_BOARD_AVERMEDIA:
case BTTV_BOARD_AVPHONE98:
case BTTV_BOARD_AVERMEDIA98:
@@ -643,12 +580,18 @@ static int ir_probe(struct device *dev)
break;
case BTTV_BOARD_NEBULA_DIGITV:
ir_codes = ir_codes_nebula;
- driver.any_irq = ir_rc5_irq;
- driver.gpio_irq = NULL;
+ btv->custom_irq = bttv_rc5_irq;
ir->rc5_gpio = 1;
break;
+ case BTTV_BOARD_MACHTV_MAGICTV:
+ ir_codes = ir_codes_apac_viewcomp;
+ ir->mask_keycode = 0x001F00;
+ ir->mask_keyup = 0x004000;
+ ir->polling = 50; /* ms */
+ break;
}
if (NULL == ir_codes) {
+ dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
kfree(ir);
input_free_device(input_dev);
return -ENODEV;
@@ -657,109 +600,92 @@ static int ir_probe(struct device *dev)
if (ir->rc5_gpio) {
u32 gpio;
/* enable remote irq */
- bttv_gpio_inout(sub->core, (1 << 4), 1 << 4);
- gpio = bttv_gpio_read(sub->core);
- bttv_gpio_write(sub->core, gpio & ~(1 << 4));
- bttv_gpio_write(sub->core, gpio | (1 << 4));
+ bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
+ gpio = bttv_gpio_read(&btv->c);
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+ bttv_gpio_write(&btv->c, gpio | (1 << 4));
} else {
/* init hardware-specific stuff */
- bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0);
+ bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
}
/* init input device */
+ ir->dev = input_dev;
+
snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
- sub->core->type);
+ btv->c.type);
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
- pci_name(sub->core->pci));
+ pci_name(btv->c.pci));
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
input_dev->name = ir->name;
input_dev->phys = ir->phys;
input_dev->id.bustype = BUS_PCI;
input_dev->id.version = 1;
- if (sub->core->pci->subsystem_vendor) {
- input_dev->id.vendor = sub->core->pci->subsystem_vendor;
- input_dev->id.product = sub->core->pci->subsystem_device;
+ if (btv->c.pci->subsystem_vendor) {
+ input_dev->id.vendor = btv->c.pci->subsystem_vendor;
+ input_dev->id.product = btv->c.pci->subsystem_device;
} else {
- input_dev->id.vendor = sub->core->pci->vendor;
- input_dev->id.product = sub->core->pci->device;
+ input_dev->id.vendor = btv->c.pci->vendor;
+ input_dev->id.product = btv->c.pci->device;
}
- input_dev->cdev.dev = &sub->core->pci->dev;
-
- ir->input = input_dev;
- ir->sub = sub;
+ input_dev->cdev.dev = &btv->c.pci->dev;
+ btv->remote = ir;
if (ir->polling) {
- INIT_WORK(&ir->work, ir_work, ir);
init_timer(&ir->timer);
- ir->timer.function = ir_timer;
- ir->timer.data = (unsigned long)ir;
- schedule_work(&ir->work);
+ ir->timer.function = bttv_input_timer;
+ ir->timer.data = (unsigned long)btv;
+ ir->timer.expires = jiffies + HZ;
+ add_timer(&ir->timer);
} else if (ir->rc5_gpio) {
/* set timer_end for code completion */
init_timer(&ir->timer_end);
- ir->timer_end.function = ir_rc5_timer_end;
+ ir->timer_end.function = bttv_rc5_timer_end;
ir->timer_end.data = (unsigned long)ir;
init_timer(&ir->timer_keyup);
- ir->timer_keyup.function = ir_rc5_timer_keyup;
+ ir->timer_keyup.function = bttv_rc5_timer_keyup;
ir->timer_keyup.data = (unsigned long)ir;
}
/* all done */
- dev_set_drvdata(dev, ir);
- input_register_device(ir->input);
+ input_register_device(btv->remote->dev);
+ printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
/* the remote isn't as bouncy as a keyboard */
- ir->input->rep[REP_DELAY] = repeat_delay;
- ir->input->rep[REP_PERIOD] = repeat_period;
+ ir->dev->rep[REP_DELAY] = repeat_delay;
+ ir->dev->rep[REP_PERIOD] = repeat_period;
return 0;
}
-static int ir_remove(struct device *dev)
+void bttv_input_fini(struct bttv *btv)
{
- struct IR *ir = dev_get_drvdata(dev);
+ if (btv->remote == NULL)
+ return;
- if (ir->polling) {
- del_timer(&ir->timer);
+ if (btv->remote->polling) {
+ del_timer_sync(&btv->remote->timer);
flush_scheduled_work();
}
- if (ir->rc5_gpio) {
+
+ if (btv->remote->rc5_gpio) {
u32 gpio;
- del_timer(&ir->timer_end);
+ del_timer_sync(&btv->remote->timer_end);
flush_scheduled_work();
- gpio = bttv_gpio_read(ir->sub->core);
- bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
+ gpio = bttv_gpio_read(&btv->c);
+ bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
}
- input_unregister_device(ir->input);
- kfree(ir);
- return 0;
+ input_unregister_device(btv->remote->dev);
+ kfree(btv->remote);
+ btv->remote = NULL;
}
-/* ---------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Gerd Knorr, Pavel Machek");
-MODULE_DESCRIPTION("input driver for bt8x8 gpio IR remote controls");
-MODULE_LICENSE("GPL");
-
-static int ir_init(void)
-{
- return bttv_sub_register(&driver, "remote");
-}
-
-static void ir_fini(void)
-{
- bttv_sub_unregister(&driver);
-}
-
-module_init(ir_init);
-module_exit(ir_fini);
-
/*
* Local variables:
diff --git a/drivers/media/video/bttv-vbi.c b/drivers/media/video/bttv-vbi.c
index f4f58c60f152..72afdd64b882 100644
--- a/drivers/media/video/bttv-vbi.c
+++ b/drivers/media/video/bttv-vbi.c
@@ -31,6 +31,12 @@
#include <asm/io.h>
#include "bttvp.h"
+/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
+ bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
+ HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
+ of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
+#define VBI_OFFSET ((64 + 0) * 2)
+
#define VBI_DEFLINES 16
#define VBI_MAXLINES 32
@@ -163,40 +169,30 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
{
const struct bttv_tvnorm *tvnorm;
- u32 start0,start1;
- s32 count0,count1,count;
+ s64 count0,count1,count;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
f->fmt.vbi.samples_per_line = 2048;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- f->fmt.vbi.offset = 244;
+ f->fmt.vbi.offset = VBI_OFFSET;
f->fmt.vbi.flags = 0;
- switch (fh->btv->tvnorm) {
- case 1: /* NTSC */
- start0 = 10;
- start1 = 273;
- break;
- case 0: /* PAL */
- case 2: /* SECAM */
- default:
- start0 = 7;
- start1 = 320;
- }
- count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0;
- count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1;
- count = max(count0,count1);
- if (count > VBI_MAXLINES)
- count = VBI_MAXLINES;
- if (count < 1)
- count = 1;
+ /* s64 to prevent overflow. */
+ count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
+ - tvnorm->vbistart[0];
+ count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
+ - tvnorm->vbistart[1];
+ count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
- f->fmt.vbi.start[0] = start0;
- f->fmt.vbi.start[1] = start1;
+ f->fmt.vbi.start[0] = tvnorm->vbistart[0];
+ f->fmt.vbi.start[1] = tvnorm->vbistart[1];
f->fmt.vbi.count[0] = count;
f->fmt.vbi.count[1] = count;
+
+ f->fmt.vbi.reserved[0] = 0;
+ f->fmt.vbi.reserved[1] = 0;
}
void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
@@ -209,21 +205,12 @@ void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
f->fmt.vbi.samples_per_line = 2048;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- f->fmt.vbi.offset = 244;
+ f->fmt.vbi.offset = VBI_OFFSET;
+ f->fmt.vbi.start[0] = tvnorm->vbistart[0];
+ f->fmt.vbi.start[1] = tvnorm->vbistart[1];
f->fmt.vbi.count[0] = fh->lines;
f->fmt.vbi.count[1] = fh->lines;
f->fmt.vbi.flags = 0;
- switch (fh->btv->tvnorm) {
- case 1: /* NTSC */
- f->fmt.vbi.start[0] = 10;
- f->fmt.vbi.start[1] = 273;
- break;
- case 0: /* PAL */
- case 2: /* SECAM */
- default:
- f->fmt.vbi.start[0] = 7;
- f->fmt.vbi.start[1] = 319;
- }
}
/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 93298f06e019..9908c8e0c951 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -16,6 +16,8 @@
#include <linux/videodev.h>
#include <linux/i2c.h>
+#include <media/ir-common.h>
+#include <media/ir-kbd-i2c.h>
/* ---------------------------------------------------------- */
/* exported by bttv-cards.c */
@@ -163,6 +165,8 @@
#define BTTV_BOARD_OSPREY440 0x8c
#define BTTV_BOARD_ASOUND_SKYEYE 0x8d
#define BTTV_BOARD_SABRENT_TVFM 0x8e
+#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f
+#define BTTV_BOARD_MACHTV_MAGICTV 0x90
/* i2c address list */
#define I2C_TSA5522 0xc2
@@ -210,6 +214,34 @@ struct bttv_core {
struct bttv;
+
+struct bttv_ir {
+ struct input_dev *dev;
+ struct ir_input_state ir;
+ char name[32];
+ char phys[32];
+
+ /* Usual gpio signalling */
+
+ u32 mask_keycode;
+ u32 mask_keydown;
+ u32 mask_keyup;
+ u32 polling;
+ u32 last_gpio;
+ struct work_struct work;
+ struct timer_list timer;
+
+ /* RC5 gpio */
+ u32 rc5_gpio;
+ struct timer_list timer_end; /* timer_end for code completion */
+ struct timer_list timer_keyup; /* timer_end for key release */
+ u32 last_rc5; /* last good rc5 code */
+ u32 last_bit; /* last raw bit seen */
+ u32 code; /* raw code under construction */
+ struct timeval base_time; /* time of last seen code */
+ int active; /* building raw code */
+};
+
struct tvcard
{
char *name;
@@ -235,7 +267,6 @@ struct tvcard
unsigned int has_dvb:1;
unsigned int has_remote:1;
unsigned int no_gpioirq:1;
- unsigned int any_irq:1;
/* other settings */
unsigned int pll;
@@ -334,8 +365,9 @@ struct bttv_sub_device {
struct bttv_sub_driver {
struct device_driver drv;
char wanted[BUS_ID_SIZE];
+ int (*probe)(struct bttv_sub_device *sub);
+ void (*remove)(struct bttv_sub_device *sub);
void (*gpio_irq)(struct bttv_sub_device *sub);
- int (*any_irq)(struct bttv_sub_device *sub);
};
#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
@@ -363,6 +395,10 @@ extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
unsigned char b2, int both);
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
+extern int bttv_input_init(struct bttv *dev);
+extern void bttv_input_fini(struct bttv *dev);
+extern void bttv_input_irq(struct bttv *dev);
+
#endif /* _BTTV_H_ */
/*
* Local variables:
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 1e6a5632c3c7..9cb72f176f7d 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -35,6 +35,7 @@
#include <linux/videodev.h>
#include <linux/pci.h>
#include <linux/input.h>
+#include <linux/mutex.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
@@ -73,6 +74,8 @@
#define UNSET (-1U)
+#define clamp(x, low, high) min (max (low, x), high)
+
/* ---------------------------------------------------------- */
struct bttv_tvnorm {
@@ -88,6 +91,9 @@ struct bttv_tvnorm {
u8 vbipack;
u16 vtotal;
int sram;
+ /* ITU-R frame line number of the first VBI line we can
+ capture, of the first and second field. */
+ u16 vbistart[2];
};
extern const struct bttv_tvnorm bttv_tvnorms[];
@@ -209,7 +215,6 @@ extern struct bus_type bttv_sub_bus_type;
int bttv_sub_add_device(struct bttv_core *core, char *name);
int bttv_sub_del_devices(struct bttv_core *core);
void bttv_gpio_irq(struct bttv_core *core);
-int bttv_any_irq(struct bttv_core *core);
/* ---------------------------------------------------------- */
@@ -270,12 +275,13 @@ struct bttv {
/* card configuration info */
unsigned int cardid; /* pci subsystem id (bt878 based ones) */
unsigned int tuner_type; /* tuner chip type */
- unsigned int pinnacle_id;
+ unsigned int tda9887_conf;
unsigned int svhs;
struct bttv_pll_info pll;
int triton1;
int gpioirq;
- int any_irq;
+ int (*custom_irq)(struct bttv *btv);
+
int use_i2c_hw;
/* old gpio interface */
@@ -300,13 +306,13 @@ struct bttv {
/* infrared remote */
int has_remote;
- struct bttv_input *remote;
+ struct bttv_ir *remote;
/* locking */
spinlock_t s_lock;
- struct semaphore lock;
+ struct mutex lock;
int resources;
- struct semaphore reslock;
+ struct mutex reslock;
#ifdef VIDIOC_G_PRIORITY
struct v4l2_prio_state prio;
#endif
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 0065d0c240d1..6bad93ef969f 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -875,6 +875,7 @@ static struct file_operations qcam_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = qcam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = qcam_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 75442ec49f35..9976db4f6da8 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -687,6 +687,7 @@ static struct file_operations qcam_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = qcam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = qcam_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
new file mode 100644
index 000000000000..297c32ab51e3
--- /dev/null
+++ b/drivers/media/video/compat_ioctl32.c
@@ -0,0 +1,879 @@
+/*
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
+ *
+ * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
+ * Copyright (C) 2003 Pavel Machek (pavel@suse.cz)
+ * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * ioctls.
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <media/v4l2-common.h>
+
+#ifdef CONFIG_COMPAT
+
+
+struct video_tuner32 {
+ compat_int_t tuner;
+ char name[32];
+ compat_ulong_t rangelow, rangehigh;
+ u32 flags; /* It is really u32 in videodev.h */
+ u16 mode, signal;
+};
+
+static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
+{
+ if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
+ get_user(kp->tuner, &up->tuner) ||
+ copy_from_user(kp->name, up->name, 32) ||
+ get_user(kp->rangelow, &up->rangelow) ||
+ get_user(kp->rangehigh, &up->rangehigh) ||
+ get_user(kp->flags, &up->flags) ||
+ get_user(kp->mode, &up->mode) ||
+ get_user(kp->signal, &up->signal))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
+ put_user(kp->tuner, &up->tuner) ||
+ copy_to_user(up->name, kp->name, 32) ||
+ put_user(kp->rangelow, &up->rangelow) ||
+ put_user(kp->rangehigh, &up->rangehigh) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->mode, &up->mode) ||
+ put_user(kp->signal, &up->signal))
+ return -EFAULT;
+ return 0;
+}
+
+struct video_buffer32 {
+ compat_caddr_t base;
+ compat_int_t height, width, depth, bytesperline;
+};
+
+static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
+{
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
+ get_user(tmp, &up->base) ||
+ get_user(kp->height, &up->height) ||
+ get_user(kp->width, &up->width) ||
+ get_user(kp->depth, &up->depth) ||
+ get_user(kp->bytesperline, &up->bytesperline))
+ return -EFAULT;
+
+ /* This is actually a physical address stored
+ * as a void pointer.
+ */
+ kp->base = (void *)(unsigned long) tmp;
+
+ return 0;
+}
+
+static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
+{
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
+ put_user(tmp, &up->base) ||
+ put_user(kp->height, &up->height) ||
+ put_user(kp->width, &up->width) ||
+ put_user(kp->depth, &up->depth) ||
+ put_user(kp->bytesperline, &up->bytesperline))
+ return -EFAULT;
+ return 0;
+}
+
+struct video_clip32 {
+ s32 x, y, width, height; /* Its really s32 in videodev.h */
+ compat_caddr_t next;
+};
+
+struct video_window32 {
+ u32 x, y, width, height, chromakey, flags;
+ compat_caddr_t clips;
+ compat_int_t clipcount;
+};
+
+static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ if (file->f_op->unlocked_ioctl)
+ ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+ else if (file->f_op->ioctl) {
+ lock_kernel();
+ ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+ unlock_kernel();
+ }
+
+ return ret;
+}
+
+
+/* You get back everything except the clips... */
+static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
+ put_user(kp->x, &up->x) ||
+ put_user(kp->y, &up->y) ||
+ put_user(kp->width, &up->width) ||
+ put_user(kp->height, &up->height) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_clip32
+{
+ struct v4l2_rect c;
+ compat_caddr_t next;
+};
+
+struct v4l2_window32
+{
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ __u32 chromakey;
+ compat_caddr_t clips; /* actually struct v4l2_clip32 * */
+ __u32 clipcount;
+ compat_caddr_t bitmap;
+};
+
+static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
+ copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
+ get_user(kp->field, &up->field) ||
+ get_user(kp->chromakey, &up->chromakey) ||
+ get_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ if (kp->clipcount > 2048)
+ return -EINVAL;
+ if (kp->clipcount) {
+ struct v4l2_clip32 *uclips = compat_ptr(up->clips);
+ struct v4l2_clip *kclips;
+ int n = kp->clipcount;
+
+ kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
+ kp->clips = kclips;
+ while (--n >= 0) {
+ if (!access_ok(VERIFY_READ, &uclips->c, sizeof(uclips->c)) ||
+ copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
+ return -EFAULT;
+ kclips->next = n ? kclips + 1 : 0;
+ uclips += 1;
+ kclips += 1;
+ }
+ } else
+ kp->clips = 0;
+ return 0;
+}
+
+static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_window32)) ||
+ copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->chromakey, &up->chromakey) ||
+ put_user(kp->clipcount, &up->clipcount))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_pix_format)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_pix_format)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_vbi_format)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_vbi_format)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_format32
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+ __u8 raw_data[200]; // user-defined
+ } fmt;
+};
+
+static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
+ get_user(kp->type, &up->type))
+ return -EFAULT;
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ default:
+ printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n",
+ kp->type);
+ return -ENXIO;
+ }
+}
+
+static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ put_user(kp->type, &up->type))
+ return -EFAULT;
+ switch (kp->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+ default:
+ return -ENXIO;
+ }
+}
+
+static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_standard)))
+ return -EFAULT;
+ return 0;
+
+}
+
+static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_standard)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_standard32
+{
+ __u32 index;
+ __u32 id[2]; /* __u64 would get the alignment wrong */
+ __u8 name[24];
+ struct v4l2_fract frameperiod; /* Frames, not fields */
+ __u32 framelines;
+ __u32 reserved[4];
+};
+
+static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+{
+ /* other fields are not set by the user, nor used by the driver */
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
+ get_user(kp->index, &up->index))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
+{
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
+ put_user(kp->index, &up->index) ||
+ copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
+ copy_to_user(up->name, kp->name, 24) ||
+ copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
+ put_user(kp->framelines, &up->framelines) ||
+ copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_tuner)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
+ return 0;
+
+}
+
+static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_tuner)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_buffer32
+{
+ __u32 index;
+ enum v4l2_buf_type type;
+ __u32 bytesused;
+ __u32 flags;
+ enum v4l2_field field;
+ struct compat_timeval timestamp;
+ struct v4l2_timecode timecode;
+ __u32 sequence;
+
+ /* memory location */
+ enum v4l2_memory memory;
+ union {
+ __u32 offset;
+ compat_long_t userptr;
+ } m;
+ __u32 length;
+ __u32 input;
+ __u32 reserved;
+};
+
+static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+{
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
+ get_user(kp->index, &up->index) ||
+ get_user(kp->type, &up->type) ||
+ get_user(kp->flags, &up->flags) ||
+ get_user(kp->memory, &up->memory) ||
+ get_user(kp->input, &up->input))
+ return -EFAULT;
+ switch(kp->memory) {
+ case V4L2_MEMORY_MMAP:
+ break;
+ case V4L2_MEMORY_USERPTR:
+ {
+ unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
+
+ if(get_user(kp->length, &up->length) ||
+ get_user(kp->m.userptr, &tmp))
+ return -EFAULT;
+ }
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ if(get_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ }
+ return 0;
+}
+
+static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
+ put_user(kp->index, &up->index) ||
+ put_user(kp->type, &up->type) ||
+ put_user(kp->flags, &up->flags) ||
+ put_user(kp->memory, &up->memory) ||
+ put_user(kp->input, &up->input))
+ return -EFAULT;
+ switch(kp->memory) {
+ case V4L2_MEMORY_MMAP:
+ if (put_user(kp->length, &up->length) ||
+ put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_USERPTR:
+ if (put_user(kp->length, &up->length) ||
+ put_user(kp->m.userptr, &up->m.userptr))
+ return -EFAULT;
+ break;
+ case V4L2_MEMORY_OVERLAY:
+ if (put_user(kp->m.offset, &up->m.offset))
+ return -EFAULT;
+ break;
+ }
+ if (put_user(kp->bytesused, &up->bytesused) ||
+ put_user(kp->field, &up->field) ||
+ put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+ put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
+ copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
+ put_user(kp->sequence, &up->sequence) ||
+ put_user(kp->reserved, &up->reserved))
+ return -EFAULT;
+ return 0;
+}
+
+struct v4l2_framebuffer32
+{
+ __u32 capability;
+ __u32 flags;
+ compat_caddr_t base;
+ struct v4l2_pix_format fmt;
+};
+
+static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+{
+ u32 tmp;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
+ get_user(tmp, &up->base) ||
+ get_user(kp->capability, &up->capability) ||
+ get_user(kp->flags, &up->flags))
+ return -EFAULT;
+ kp->base = compat_ptr(tmp);
+ get_v4l2_pix_format(&kp->fmt, &up->fmt);
+ return 0;
+}
+
+static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
+{
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
+ put_user(tmp, &up->base) ||
+ put_user(kp->capability, &up->capability) ||
+ put_user(kp->flags, &up->flags))
+ return -EFAULT;
+ put_v4l2_pix_format(&kp->fmt, &up->fmt);
+ return 0;
+}
+
+static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input) - 4) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input) - 4) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_input)) ||
+ copy_from_user(kp, up, sizeof(struct v4l2_input)))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
+{
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_input)) ||
+ copy_to_user(up, kp, sizeof(struct v4l2_input)))
+ return -EFAULT;
+ return 0;
+}
+
+#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32 _IOR('v',14, u32)
+#define VIDIOCSFREQ32 _IOW('v',15, u32)
+
+/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
+#define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
+#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32)
+#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32)
+#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32)
+#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
+#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
+/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */
+#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t)
+#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32)
+#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32)
+#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t)
+#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t)
+#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32)
+/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */
+#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control)
+#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t)
+#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t)
+#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32)
+
+enum {
+ MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
+};
+
+static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_window32 __user *up = compat_ptr(arg);
+ struct video_window __user *vw;
+ struct video_clip __user *p;
+ int nclips;
+ u32 n;
+
+ if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
+ return -EFAULT;
+
+ if (get_user(nclips, &up->clipcount))
+ return -EFAULT;
+
+ /* Peculiar interface... */
+ if (nclips < 0)
+ nclips = VIDEO_CLIPMAP_SIZE;
+
+ if (nclips > MaxClips)
+ return -ENOMEM;
+
+ vw = compat_alloc_user_space(sizeof(struct video_window) +
+ nclips * sizeof(struct video_clip));
+
+ p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
+
+ if (get_user(n, &up->x) || put_user(n, &vw->x) ||
+ get_user(n, &up->y) || put_user(n, &vw->y) ||
+ get_user(n, &up->width) || put_user(n, &vw->width) ||
+ get_user(n, &up->height) || put_user(n, &vw->height) ||
+ get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
+ get_user(n, &up->flags) || put_user(n, &vw->flags) ||
+ get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
+ get_user(n, &up->clips) || put_user(p, &vw->clips))
+ return -EFAULT;
+
+ if (nclips) {
+ struct video_clip32 __user *u = compat_ptr(n);
+ int i;
+ if (!u)
+ return -EINVAL;
+ for (i = 0; i < nclips; i++, u++, p++) {
+ s32 v;
+ if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) ||
+ !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) ||
+ get_user(v, &u->x) ||
+ put_user(v, &p->x) ||
+ get_user(v, &u->y) ||
+ put_user(v, &p->y) ||
+ get_user(v, &u->width) ||
+ put_user(v, &p->width) ||
+ get_user(v, &u->height) ||
+ put_user(v, &p->height) ||
+ put_user(NULL, &p->next))
+ return -EFAULT;
+ }
+ }
+
+ return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
+}
+
+static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ union {
+ struct video_tuner vt;
+ struct video_buffer vb;
+ struct video_window vw;
+ struct v4l2_format v2f;
+ struct v4l2_buffer v2b;
+ struct v4l2_framebuffer v2fb;
+ struct v4l2_standard v2s;
+ struct v4l2_input v2i;
+ struct v4l2_tuner v2t;
+ unsigned long vx;
+ } karg;
+ void __user *up = compat_ptr(arg);
+ int compatible_arg = 1;
+ int err = 0;
+ int realcmd = cmd;
+
+ /* First, convert the command. */
+ switch(cmd) {
+ case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
+ case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
+ case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
+ case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
+ case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
+ case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
+ case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+ case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
+ case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
+ case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
+ case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
+ case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
+ case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
+ case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
+ case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
+ case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
+ case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
+ case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
+ case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
+ case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;
+ case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
+ case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
+ case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
+ };
+
+ switch(cmd) {
+ case VIDIOCSTUNER:
+ case VIDIOCGTUNER:
+ err = get_video_tuner32(&karg.vt, up);
+ compatible_arg = 0;
+
+ break;
+
+ case VIDIOCSFBUF:
+ err = get_video_buffer32(&karg.vb, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_INPUT:
+ case VIDIOC_OVERLAY:
+ case VIDIOC_STREAMON:
+ case VIDIOC_STREAMOFF:
+ err = get_user(karg.vx, (u32 __user *)up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_S_FBUF:
+ err = get_v4l2_framebuffer32(&karg.v2fb, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ err = get_v4l2_format32(&karg.v2f, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ err = get_v4l2_buffer32(&karg.v2b, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMSTD:
+ err = get_v4l2_standard(&karg.v2s, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMSTD32:
+ err = get_v4l2_standard32(&karg.v2s, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMINPUT:
+ err = get_v4l2_input(&karg.v2i, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_ENUMINPUT32:
+ err = get_v4l2_input32(&karg.v2i, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ err = get_v4l2_tuner(&karg.v2t, up);
+ compatible_arg = 0;
+ break;
+
+ case VIDIOCGWIN:
+ case VIDIOCGFBUF:
+ case VIDIOCGFREQ:
+ case VIDIOC_G_FBUF:
+ case VIDIOC_G_INPUT:
+ compatible_arg = 0;
+ };
+
+ if(err)
+ goto out;
+
+ if(compatible_arg)
+ err = native_ioctl(file, realcmd, (unsigned long)up);
+ else {
+ mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ err = native_ioctl(file, realcmd, (unsigned long)&karg);
+ set_fs(old_fs);
+ }
+ if(err == 0) {
+ switch(cmd) {
+ case VIDIOCGTUNER:
+ err = put_video_tuner32(&karg.vt, up);
+ break;
+
+ case VIDIOCGWIN:
+ err = put_video_window32(&karg.vw, up);
+ break;
+
+ case VIDIOCGFBUF:
+ err = put_video_buffer32(&karg.vb, up);
+ break;
+
+ case VIDIOC_G_FBUF:
+ err = put_v4l2_framebuffer32(&karg.v2fb, up);
+ break;
+
+ case VIDIOC_G_FMT:
+ case VIDIOC_S_FMT:
+ case VIDIOC_TRY_FMT:
+ err = put_v4l2_format32(&karg.v2f, up);
+ break;
+
+ case VIDIOC_QUERYBUF:
+ case VIDIOC_QBUF:
+ case VIDIOC_DQBUF:
+ err = put_v4l2_buffer32(&karg.v2b, up);
+ break;
+
+ case VIDIOC_ENUMSTD:
+ err = put_v4l2_standard(&karg.v2s, up);
+ break;
+
+ case VIDIOC_ENUMSTD32:
+ err = put_v4l2_standard32(&karg.v2s, up);
+ break;
+
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ err = put_v4l2_tuner(&karg.v2t, up);
+ break;
+
+ case VIDIOC_ENUMINPUT:
+ err = put_v4l2_input(&karg.v2i, up);
+ break;
+
+ case VIDIOC_ENUMINPUT32:
+ err = put_v4l2_input32(&karg.v2i, up);
+ break;
+
+ case VIDIOCGFREQ:
+ case VIDIOC_G_INPUT:
+ err = put_user(((u32)karg.vx), (u32 __user *)up);
+ break;
+ };
+ }
+out:
+ return err;
+}
+
+long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOIOCTLCMD;
+
+ if (!file->f_op->ioctl)
+ return ret;
+
+ switch (cmd) {
+ case VIDIOCSWIN32:
+ ret = do_set_window(file, cmd, arg);
+ break;
+ case VIDIOCGTUNER32:
+ case VIDIOCSTUNER32:
+ case VIDIOCGWIN32:
+ case VIDIOCGFBUF32:
+ case VIDIOCSFBUF32:
+ case VIDIOCGFREQ32:
+ case VIDIOCSFREQ32:
+ case VIDIOC_QUERYCAP:
+ case VIDIOC_ENUM_FMT:
+ case VIDIOC_G_FMT32:
+ case VIDIOC_S_FMT32:
+ case VIDIOC_REQBUFS:
+ case VIDIOC_QUERYBUF32:
+ case VIDIOC_G_FBUF32:
+ case VIDIOC_S_FBUF32:
+ case VIDIOC_OVERLAY32:
+ case VIDIOC_QBUF32:
+ case VIDIOC_DQBUF32:
+ case VIDIOC_STREAMON32:
+ case VIDIOC_STREAMOFF32:
+ case VIDIOC_G_PARM:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+ case VIDIOC_G_TUNER:
+ case VIDIOC_S_TUNER:
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_ENUMSTD32:
+ case VIDIOC_ENUMINPUT:
+ case VIDIOC_ENUMINPUT32:
+ case VIDIOC_G_CTRL:
+ case VIDIOC_S_CTRL32:
+ case VIDIOC_QUERYCTRL:
+ case VIDIOC_G_INPUT32:
+ case VIDIOC_S_INPUT32:
+ case VIDIOC_TRY_FMT32:
+ ret = do_video_ioctl(file, cmd, arg);
+ break;
+
+ /* Little v, the video4linux ioctls (conflict?) */
+ case VIDIOCGCAP:
+ case VIDIOCGCHAN:
+ case VIDIOCSCHAN:
+ case VIDIOCGPICT:
+ case VIDIOCSPICT:
+ case VIDIOCCAPTURE:
+ case VIDIOCKEY:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ case VIDIOCSYNC:
+ case VIDIOCMCAPTURE:
+ case VIDIOCGMBUF:
+ case VIDIOCGUNIT:
+ case VIDIOCGCAPTURE:
+ case VIDIOCSCAPTURE:
+
+ /* BTTV specific... */
+ case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
+ case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
+ case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
+ case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
+ ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
+ break;
+ default:
+ v4l_print_ioctl("compat_ioctl32", cmd);
+ }
+ return ret;
+}
+#else
+long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+#endif
+EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index b7ec9bf45085..9f59541155d9 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3807,6 +3807,7 @@ static struct file_operations cpia_fops = {
.read = cpia_read,
.mmap = cpia_mmap,
.ioctl = cpia_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index ddf184f95d80..74cff626e044 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -170,16 +170,9 @@ static size_t cpia_read_nibble (struct parport *port,
/* Does the error line indicate end of data? */
if (((i /*& 1*/) == 0) &&
(parport_read_status(port) & PARPORT_STATUS_ERROR)) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DBG("%s: No more nibble data (%d bytes)\n",
- port->name, i/2);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ DBG("%s: No more nibble data (%d bytes)\n",
+ port->name, i/2);
+ goto end_of_data;
}
/* Event 7: Set nAutoFd low. */
@@ -227,18 +220,21 @@ static size_t cpia_read_nibble (struct parport *port,
byte = nibble;
}
- i /= 2; /* i is now in bytes */
-
if (i == len) {
/* Read the last nibble without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
- return i;
+ return i/2;
}
/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1)
@@ -706,12 +702,11 @@ static int cpia_pp_register(struct parport *port)
return -ENXIO;
}
- cam = kmalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
+ cam = kzalloc(sizeof(struct pp_cam_entry), GFP_KERNEL);
if (cam == NULL) {
LOG("failed to allocate camera structure\n");
return -ENOMEM;
}
- memset(cam,0,sizeof(struct pp_cam_entry));
pdev = parport_register_device(port, "cpia_pp", NULL, NULL,
NULL, 0, cam);
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 9774e94d1e7d..03275c37c5d3 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -499,14 +499,12 @@ static int cpia_probe(struct usb_interface *intf,
printk(KERN_INFO "USB CPiA camera found\n");
- ucpia = kmalloc(sizeof(*ucpia), GFP_KERNEL);
+ ucpia = kzalloc(sizeof(*ucpia), GFP_KERNEL);
if (!ucpia) {
printk(KERN_ERR "couldn't kmalloc cpia struct\n");
return -ENOMEM;
}
- memset(ucpia, 0, sizeof(*ucpia));
-
ucpia->dev = udev;
ucpia->iface = interface->desc.bInterfaceNumber;
init_waitqueue_head(&ucpia->wq_stream);
@@ -582,7 +580,6 @@ MODULE_LICENSE("GPL");
static struct usb_driver cpia_driver = {
- .owner = THIS_MODULE,
.name = "cpia",
.probe = cpia_probe,
.disconnect = cpia_disconnect,
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index 780b352ec119..8739c64785ef 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -27,7 +27,7 @@
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
MODULE_AUTHOR("Martin Vaughan");
@@ -39,20 +39,6 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
-#define cs53l32a_dbg(fmt, arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define cs53l32a_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define cs53l32a_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
@@ -73,50 +59,59 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
- int *input = arg;
+ struct v4l2_audio *input = arg;
+ struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
- switch (*input) {
- case AUDIO_TUNER:
- cs53l32a_write(client, 0x01, 0x01);
- break;
- case AUDIO_EXTERN:
- cs53l32a_write(client, 0x01, 0x21);
- break;
- case AUDIO_MUTE:
- cs53l32a_write(client, 0x03, 0xF0);
- break;
- case AUDIO_UNMUTE:
- cs53l32a_write(client, 0x03, 0x30);
- break;
- default:
- cs53l32a_err("Invalid input %d.\n", *input);
+ case VIDIOC_S_AUDIO:
+ /* There are 2 physical inputs, but the second input can be
+ placed in two modes, the first mode bypasses the PGA (gain),
+ the second goes through the PGA. Hence there are three
+ possible inputs to choose from. */
+ if (input->index > 2) {
+ v4l_err(client, "Invalid input %d.\n", input->index);
return -EINVAL;
}
+ cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
+ break;
+
+ case VIDIOC_G_AUDIO:
+ memset(input, 0, sizeof(*input));
+ input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
+ break;
+
+ case VIDIOC_G_CTRL:
+ if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
+ ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0;
+ break;
+ }
+ if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
+ return -EINVAL;
+ ctrl->value = (s8)cs53l32a_read(client, 0x04);
break;
case VIDIOC_S_CTRL:
- {
- struct v4l2_control *ctrl = arg;
-
- if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
- return -EINVAL;
- if (ctrl->value > 12 || ctrl->value < -90)
- return -EINVAL;
- cs53l32a_write(client, 0x04, (u8) ctrl->value);
- cs53l32a_write(client, 0x05, (u8) ctrl->value);
+ if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
+ cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30);
break;
}
+ if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
+ return -EINVAL;
+ if (ctrl->value > 12 || ctrl->value < -96)
+ return -EINVAL;
+ cs53l32a_write(client, 0x04, (u8) ctrl->value);
+ cs53l32a_write(client, 0x05, (u8) ctrl->value);
+ break;
case VIDIOC_LOG_STATUS:
{
u8 v = cs53l32a_read(client, 0x01);
u8 m = cs53l32a_read(client, 0x03);
+ s8 vol = cs53l32a_read(client, 0x04);
- cs53l32a_info("Input: %s%s\n",
- v == 0x21 ? "external line in" : "tuner",
+ v4l_info(client, "Input: %d%s\n", (v >> 4) & 3,
(m & 0xC0) ? " (muted)" : "");
+ v4l_info(client, "Volume: %d dB\n", vol);
break;
}
@@ -146,23 +141,21 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
- cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
for (i = 1; i <= 7; i++) {
u8 v = cs53l32a_read(client, i);
- cs53l32a_dbg("Read Reg %d %02x\n", i, v);
+ v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v);
}
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
@@ -180,7 +173,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
for (i = 1; i <= 7; i++) {
u8 v = cs53l32a_read(client, i);
- cs53l32a_dbg("Read Reg %d %02x\n", i, v);
+ v4l_dbg(1, debug, client, "Read Reg %d %02x\n", i, v);
}
i2c_attach_client(client);
@@ -190,11 +183,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
static int cs53l32a_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, cs53l32a_attach);
return 0;
}
@@ -216,13 +205,13 @@ static int cs53l32a_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver = {
- .name = "cs53l32a",
+ .driver = {
+ .name = "cs53l32a",
+ },
.id = I2C_DRIVERID_CS53L32A,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = cs53l32a_probe,
.detach_client = cs53l32a_detach,
.command = cs53l32a_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 740908f8027d..cb9a7981e408 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -23,11 +23,13 @@
#include "cx25840.h"
-inline static int set_audclk_freq(struct i2c_client *client,
- enum v4l2_audio_clock_freq freq)
+static int set_audclk_freq(struct i2c_client *client, u32 freq)
{
struct cx25840_state *state = i2c_get_clientdata(client);
+ if (freq != 32000 && freq != 44100 && freq != 48000)
+ return -EINVAL;
+
/* assert soft reset */
cx25840_and_or(client, 0x810, ~0x1, 0x01);
@@ -35,10 +37,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
cx25840_write(client, 0x127, 0x50);
- switch (state->audio_input) {
- case AUDIO_TUNER:
+ if (state->aud_input != CX25840_AUDIO_SERIAL) {
switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
+ case 32000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040610);
@@ -51,7 +52,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x7ff70108);
break;
- case V4L2_AUDCLK_441_KHZ:
+ case 44100:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040910);
@@ -64,7 +65,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x596d0108);
break;
- case V4L2_AUDCLK_48_KHZ:
+ case 48000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040a10);
@@ -77,14 +78,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0xaa4f0108);
break;
}
- break;
-
- case AUDIO_EXTERN_1:
- case AUDIO_EXTERN_2:
- case AUDIO_INTERN:
- case AUDIO_RADIO:
+ } else {
switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
+ case 32000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f04081e);
@@ -103,7 +99,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write(client, 0x127, 0x54);
break;
- case V4L2_AUDCLK_441_KHZ:
+ case 44100:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040918);
@@ -119,7 +115,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x85730108);
break;
- case V4L2_AUDCLK_48_KHZ:
+ case 48000:
/* VID_PLL and AUX_PLL */
cx25840_write4(client, 0x108, 0x0f040a18);
@@ -135,7 +131,6 @@ inline static int set_audclk_freq(struct i2c_client *client,
cx25840_write4(client, 0x90c, 0x55550108);
break;
}
- break;
}
/* deassert soft reset */
@@ -146,51 +141,36 @@ inline static int set_audclk_freq(struct i2c_client *client,
return 0;
}
-static int set_input(struct i2c_client *client, int audio_input)
+void cx25840_audio_set_path(struct i2c_client *client)
{
struct cx25840_state *state = i2c_get_clientdata(client);
- cx25840_dbg("set audio input (%d)\n", audio_input);
-
/* stop microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0);
/* Mute everything to prevent the PFFT! */
cx25840_write(client, 0x8d3, 0x1f);
- switch (audio_input) {
- case AUDIO_TUNER:
- /* Set Path1 to Analog Demod Main Channel */
- cx25840_write4(client, 0x8d0, 0x7038061f);
-
- /* When the microcontroller detects the
- * audio format, it will unmute the lines */
- cx25840_and_or(client, 0x803, ~0x10, 0x10);
- break;
-
- case AUDIO_EXTERN_1:
- case AUDIO_EXTERN_2:
- case AUDIO_INTERN:
- case AUDIO_RADIO:
+ if (state->aud_input == CX25840_AUDIO_SERIAL) {
/* Set Path1 to Serial Audio Input */
cx25840_write4(client, 0x8d0, 0x12100101);
/* The microcontroller should not be started for the
* non-tuner inputs: autodetection is specific for
* TV audio. */
- break;
+ } else {
+ /* Set Path1 to Analog Demod Main Channel */
+ cx25840_write4(client, 0x8d0, 0x7038061f);
- default:
- cx25840_dbg("Invalid audio input selection %d\n", audio_input);
- return -EINVAL;
+ /* When the microcontroller detects the
+ * audio format, it will unmute the lines */
+ cx25840_and_or(client, 0x803, ~0x10, 0x10);
}
- state->audio_input = audio_input;
-
- return set_audclk_freq(client, state->audclk_freq);
+ set_audclk_freq(client, state->audclk_freq);
}
-inline static int get_volume(struct i2c_client *client)
+static int get_volume(struct i2c_client *client)
{
/* Volume runs +18dB to -96dB in 1/2dB steps
* change to fit the msp3400 -114dB to +12dB range */
@@ -201,7 +181,7 @@ inline static int get_volume(struct i2c_client *client)
return vol << 9;
}
-inline static void set_volume(struct i2c_client *client, int volume)
+static void set_volume(struct i2c_client *client, int volume)
{
/* First convert the volume to msp3400 values (0-127) */
int vol = volume >> 9;
@@ -218,7 +198,7 @@ inline static void set_volume(struct i2c_client *client, int volume)
cx25840_write(client, 0x8d4, 228 - (vol * 2));
}
-inline static int get_bass(struct i2c_client *client)
+static int get_bass(struct i2c_client *client)
{
/* bass is 49 steps +12dB to -12dB */
@@ -228,13 +208,13 @@ inline static int get_bass(struct i2c_client *client)
return bass;
}
-inline static void set_bass(struct i2c_client *client, int bass)
+static void set_bass(struct i2c_client *client, int bass)
{
/* PATH1_EQ_BASS_VOL */
cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
}
-inline static int get_treble(struct i2c_client *client)
+static int get_treble(struct i2c_client *client)
{
/* treble is 49 steps +12dB to -12dB */
@@ -244,13 +224,13 @@ inline static int get_treble(struct i2c_client *client)
return treble;
}
-inline static void set_treble(struct i2c_client *client, int treble)
+static void set_treble(struct i2c_client *client, int treble)
{
/* PATH1_EQ_TREBLE_VOL */
cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
}
-inline static int get_balance(struct i2c_client *client)
+static int get_balance(struct i2c_client *client)
{
/* balance is 7 bit, 0 to -96dB */
@@ -264,7 +244,7 @@ inline static int get_balance(struct i2c_client *client)
return balance << 8;
}
-inline static void set_balance(struct i2c_client *client, int balance)
+static void set_balance(struct i2c_client *client, int balance)
{
int bal = balance >> 8;
if (bal > 0x80) {
@@ -280,17 +260,17 @@ inline static void set_balance(struct i2c_client *client, int balance)
}
}
-inline static int get_mute(struct i2c_client *client)
+static int get_mute(struct i2c_client *client)
{
/* check SRC1_MUTE_EN */
return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
}
-inline static void set_mute(struct i2c_client *client, int mute)
+static void set_mute(struct i2c_client *client, int mute)
{
struct cx25840_state *state = i2c_get_clientdata(client);
- if (state->audio_input == AUDIO_TUNER) {
+ if (state->aud_input != CX25840_AUDIO_SERIAL) {
/* Must turn off microcontroller in order to mute sound.
* Not sure if this is the best method, but it does work.
* If the microcontroller is running, then it will undo any
@@ -314,10 +294,9 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
- return set_input(client, *(int *)arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg);
+ return set_audclk_freq(client, *(u32 *)arg);
+
case VIDIOC_G_CTRL:
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -339,6 +318,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
}
break;
+
case VIDIOC_S_CTRL:
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
@@ -360,6 +340,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
return -EINVAL;
}
break;
+
default:
return -EINVAL;
}
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 5b93723a1768..c66c2c1f4809 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -43,11 +43,11 @@ MODULE_LICENSE("GPL");
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
-int cx25840_debug = 0;
+static int cx25840_debug;
-module_param(cx25840_debug, bool, 0644);
+module_param_named(debug,cx25840_debug, int, 0644);
-MODULE_PARM_DESC(cx25840_debug, "Debugging messages [0=Off (default) 1=On]");
+MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
I2C_CLIENT_INSMOD;
@@ -115,13 +115,13 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
/* ----------------------------------------------------------------------- */
-static int set_input(struct i2c_client *, enum cx25840_input);
-static void input_change(struct i2c_client *);
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+ enum cx25840_audio_input aud_input);
static void log_status(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
-static inline void init_dll1(struct i2c_client *client)
+static void init_dll1(struct i2c_client *client)
{
/* This is the Hauppauge sequence used to
* initialize the Delay Lock Loop 1 (ADC DLL). */
@@ -135,7 +135,7 @@ static inline void init_dll1(struct i2c_client *client)
cx25840_write(client, 0x15b, 0x10);
}
-static inline void init_dll2(struct i2c_client *client)
+static void init_dll2(struct i2c_client *client)
{
/* This is the Hauppauge sequence used to
* initialize the Delay Lock Loop 2 (ADC DLL). */
@@ -195,10 +195,8 @@ static void cx25840_initialize(struct i2c_client *client, int loadfw)
/* AC97 shift */
cx25840_write(client, 0x8cf, 0x0f);
- /* (re)set video input */
- set_input(client, state->input);
- /* (re)set audio input */
- cx25840_audio(client, AUDC_SET_INPUT, &state->audio_input);
+ /* (re)set input */
+ set_input(client, state->vid_input, state->aud_input);
/* start microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0x10);
@@ -223,7 +221,7 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) {
/* NTSC */
- if (state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
+ if (state->pvr150_workaround) {
/* Certain Hauppauge PVR150 models have a hardware bug
that causes audio to drop out. For these models the
audio standard must be set explicitly.
@@ -259,72 +257,68 @@ static void input_change(struct i2c_client *client)
}
}
-static int set_input(struct i2c_client *client, enum cx25840_input input)
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+ enum cx25840_audio_input aud_input)
{
struct cx25840_state *state = i2c_get_clientdata(client);
+ u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
+ vid_input <= CX25840_COMPOSITE8);
+ u8 reg;
- cx25840_dbg("decoder set input (%d)\n", input);
+ v4l_dbg(1, cx25840_debug, client, "decoder set video input %d, audio input %d\n",
+ vid_input, aud_input);
- switch (input) {
- case CX25840_TUNER:
- cx25840_dbg("now setting Tuner input\n");
-
- if (state->cardtype == CARDTYPE_PVR150 ||
- state->cardtype == CARDTYPE_PVR150_WORKAROUND) {
- /* CH_SEL_ADC2=1 */
- cx25840_and_or(client, 0x102, ~0x2, 0x02);
- }
-
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x11);
- } else {
- cx25840_write(client, 0x103, 0x46);
- }
-
- /* INPUT_MODE=0 */
- cx25840_and_or(client, 0x401, ~0x6, 0x00);
- break;
-
- case CX25840_COMPOSITE0:
- case CX25840_COMPOSITE1:
- cx25840_dbg("now setting Composite input\n");
+ if (is_composite) {
+ reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
+ } else {
+ int luma = vid_input & 0xf0;
+ int chroma = vid_input & 0xf00;
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x00);
- } else {
- cx25840_write(client, 0x103, 0x02);
+ if ((vid_input & ~0xff0) ||
+ luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 ||
+ chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
+ v4l_err(client, "0x%04x is not a valid video input!\n", vid_input);
+ return -EINVAL;
}
-
- /* INPUT_MODE=0 */
- cx25840_and_or(client, 0x401, ~0x6, 0x00);
- break;
-
- case CX25840_SVIDEO0:
- case CX25840_SVIDEO1:
- cx25840_dbg("now setting S-Video input\n");
-
- /* CH_SEL_ADC2=0 */
- cx25840_and_or(client, 0x102, ~0x2, 0x00);
-
- /* Video Input Control */
- if (state->cardtype == CARDTYPE_PG600) {
- cx25840_write(client, 0x103, 0x02);
+ reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
+ if (chroma >= CX25840_SVIDEO_CHROMA7) {
+ reg &= 0x3f;
+ reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2;
} else {
- cx25840_write(client, 0x103, 0x10);
+ reg &= 0xcf;
+ reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4;
}
+ }
- /* INPUT_MODE=1 */
- cx25840_and_or(client, 0x401, ~0x6, 0x02);
+ switch (aud_input) {
+ case CX25840_AUDIO_SERIAL:
+ /* do nothing, use serial audio input */
break;
+ case CX25840_AUDIO4: reg &= ~0x30; break;
+ case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+ case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+ case CX25840_AUDIO7: reg &= ~0xc0; break;
+ case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
default:
- cx25840_err("%d is not a valid input!\n", input);
+ v4l_err(client, "0x%04x is not a valid audio input!\n", aud_input);
return -EINVAL;
}
- state->input = input;
+ cx25840_write(client, 0x103, reg);
+ /* Set INPUT_MODE to Composite (0) or S-Video (1) */
+ cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
+ /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+ cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+ /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+ if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+ cx25840_and_or(client, 0x102, ~0x4, 4);
+ else
+ cx25840_and_or(client, 0x102, ~0x4, 0);
+
+ state->vid_input = vid_input;
+ state->aud_input = aud_input;
+ cx25840_audio_set_path(client);
input_change(client);
return 0;
}
@@ -395,23 +389,14 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
struct cx25840_state *state = i2c_get_clientdata(client);
switch (ctrl->id) {
- case CX25840_CID_CARDTYPE:
- switch (ctrl->value) {
- case CARDTYPE_PVR150:
- case CARDTYPE_PVR150_WORKAROUND:
- case CARDTYPE_PG600:
- state->cardtype = ctrl->value;
- break;
- default:
- return -ERANGE;
- }
-
- set_input(client, state->input);
+ case CX25840_CID_ENABLE_PVR150_WORKAROUND:
+ state->pvr150_workaround = ctrl->value;
+ set_input(client, state->vid_input, state->aud_input);
break;
case V4L2_CID_BRIGHTNESS:
if (ctrl->value < 0 || ctrl->value > 255) {
- cx25840_err("invalid brightness setting %d\n",
+ v4l_err(client, "invalid brightness setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -421,7 +406,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_CONTRAST:
if (ctrl->value < 0 || ctrl->value > 127) {
- cx25840_err("invalid contrast setting %d\n",
+ v4l_err(client, "invalid contrast setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -431,7 +416,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_SATURATION:
if (ctrl->value < 0 || ctrl->value > 127) {
- cx25840_err("invalid saturation setting %d\n",
+ v4l_err(client, "invalid saturation setting %d\n",
ctrl->value);
return -ERANGE;
}
@@ -442,7 +427,7 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
if (ctrl->value < -127 || ctrl->value > 127) {
- cx25840_err("invalid hue setting %d\n", ctrl->value);
+ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -455,6 +440,9 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -465,11 +453,11 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
struct cx25840_state *state = i2c_get_clientdata(client);
switch (ctrl->id) {
- case CX25840_CID_CARDTYPE:
- ctrl->value = state->cardtype;
+ case CX25840_CID_ENABLE_PVR150_WORKAROUND:
+ ctrl->value = state->pvr150_workaround;
break;
case V4L2_CID_BRIGHTNESS:
- ctrl->value = cx25840_read(client, 0x414) + 128;
+ ctrl->value = (s8)cx25840_read(client, 0x414) + 128;
break;
case V4L2_CID_CONTRAST:
ctrl->value = cx25840_read(client, 0x415) >> 1;
@@ -478,7 +466,7 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
ctrl->value = cx25840_read(client, 0x420) >> 1;
break;
case V4L2_CID_HUE:
- ctrl->value = cx25840_read(client, 0x422);
+ ctrl->value = (s8)cx25840_read(client, 0x422);
break;
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
@@ -527,7 +515,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
- cx25840_err("%dx%d is not a valid size!\n",
+ v4l_err(client, "%dx%d is not a valid size!\n",
pix->width, pix->height);
return -ERANGE;
}
@@ -545,7 +533,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
else
filter = 3;
- cx25840_dbg("decoder set size %dx%d -> scale %ux%u\n",
+ v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale %ux%u\n",
pix->width, pix->height, HSC, VSC);
/* HSCALE=HSC */
@@ -574,17 +562,98 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
/* ----------------------------------------------------------------------- */
+static struct v4l2_queryctrl cx25840_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_AUDIO_BASS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Bass",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ }, {
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Treble",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ },
+};
+
+/* ----------------------------------------------------------------------- */
+
static int cx25840_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
struct cx25840_state *state = i2c_get_clientdata(client);
struct v4l2_tuner *vt = arg;
- int result = 0;
switch (cmd) {
- case 0:
- break;
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the
* cx25840 registers for testing */
@@ -615,18 +684,16 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
return cx25840_vbi(client, cmd, arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- case AUDC_SET_INPUT:
- result = cx25840_audio(client, cmd, arg);
- break;
+ return cx25840_audio(client, cmd, arg);
case VIDIOC_STREAMON:
- cx25840_dbg("enable output\n");
+ v4l_dbg(1, cx25840_debug, client, "enable output\n");
cx25840_write(client, 0x115, 0x8c);
cx25840_write(client, 0x116, 0x07);
break;
case VIDIOC_STREAMOFF:
- cx25840_dbg("disable output\n");
+ v4l_dbg(1, cx25840_debug, client, "disable output\n");
cx25840_write(client, 0x115, 0x00);
cx25840_write(client, 0x116, 0x00);
break;
@@ -636,28 +703,58 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
case VIDIOC_G_CTRL:
- result = get_v4lctrl(client, (struct v4l2_control *)arg);
- break;
+ return get_v4lctrl(client, (struct v4l2_control *)arg);
case VIDIOC_S_CTRL:
- result = set_v4lctrl(client, (struct v4l2_control *)arg);
- break;
+ return set_v4lctrl(client, (struct v4l2_control *)arg);
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)
+ if (qc->id && qc->id == cx25840_qctrl[i].id) {
+ memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
case VIDIOC_G_STD:
*(v4l2_std_id *)arg = cx25840_get_v4lstd(client);
break;
case VIDIOC_S_STD:
- result = set_v4lstd(client, *(v4l2_std_id *)arg);
+ state->radio = 0;
+ return set_v4lstd(client, *(v4l2_std_id *)arg);
+
+ case AUDC_SET_RADIO:
+ state->radio = 1;
break;
case VIDIOC_G_INPUT:
- *(int *)arg = state->input;
+ *(int *)arg = state->vid_input;
break;
case VIDIOC_S_INPUT:
- result = set_input(client, *(int *)arg);
+ return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input);
+
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *input = arg;
+
+ return set_input(client, state->vid_input, input->index);
+ }
+
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *input = arg;
+
+ memset(input, 0, sizeof(*input));
+ input->index = state->aud_input;
break;
+ }
case VIDIOC_S_FREQUENCY:
input_change(client);
@@ -670,6 +767,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
u8 vpres = cx25840_read(client, 0x80a) & 0x10;
int val = 0;
+ if (state->radio)
+ break;
+
vt->capability |=
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
@@ -724,12 +824,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
case VIDIOC_G_FMT:
- result = get_v4lfmt(client, (struct v4l2_format *)arg);
- break;
+ return get_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_S_FMT:
- result = set_v4lfmt(client, (struct v4l2_format *)arg);
- break;
+ return set_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_INT_RESET:
cx25840_initialize(client, 0);
@@ -741,11 +839,10 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
break;
default:
- cx25840_err("invalid ioctl %x\n", cmd);
return -EINVAL;
}
- return result;
+ return 0;
}
/* ----------------------------------------------------------------------- */
@@ -765,18 +862,16 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_cx25840;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "cx25840");
- cx25840_dbg("detecting cx25840 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", address << 1);
device_id = cx25840_read(client, 0x101) << 8;
device_id |= cx25840_read(client, 0x100);
@@ -784,12 +879,12 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
/* The high byte of the device ID should be
* 0x84 if chip is present */
if ((device_id & 0xff00) != 0x8400) {
- cx25840_dbg("cx25840 not found\n");
+ v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
kfree(client);
return 0;
}
- cx25840_info("cx25%3x-2%x found @ 0x%x (%s)\n",
+ v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
(device_id & 0xfff0) >> 4,
(device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
address << 1, adapter->name);
@@ -802,10 +897,10 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
i2c_set_clientdata(client, state);
memset(state, 0, sizeof(struct cx25840_state));
- state->input = CX25840_TUNER;
- state->audclk_freq = V4L2_AUDCLK_48_KHZ;
- state->audio_input = AUDIO_TUNER;
- state->cardtype = CARDTYPE_PVR150;
+ state->vid_input = CX25840_COMPOSITE7;
+ state->aud_input = CX25840_AUDIO8;
+ state->audclk_freq = 48000;
+ state->pvr150_workaround = 0;
cx25840_initialize(client, 1);
@@ -816,11 +911,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
static int cx25840_attach_adapter(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, &cx25840_detect_client);
return 0;
}
@@ -844,15 +935,13 @@ static int cx25840_detach_client(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_cx25840 = {
- .name = "cx25840",
-
+ .driver = {
+ .name = "cx25840",
+ },
.id = I2C_DRIVERID_CX25840,
- .flags = I2C_DF_NOTIFY,
-
.attach_adapter = cx25840_attach_adapter,
.detach_client = cx25840_detach_client,
.command = cx25840_command,
- .owner = THIS_MODULE,
};
@@ -893,11 +982,13 @@ static void log_status(struct i2c_client *client)
u8 pref_mode = cx25840_read(client, 0x809);
u8 afc0 = cx25840_read(client, 0x80b);
u8 mute_ctl = cx25840_read(client, 0x8d3);
+ int vid_input = state->vid_input;
+ int aud_input = state->aud_input;
char *p;
- cx25840_info("Video signal: %spresent\n",
+ v4l_info(client, "Video signal: %spresent\n",
(microctrl_vidfmt & 0x10) ? "" : "not ");
- cx25840_info("Detected format: %s\n",
+ v4l_info(client, "Detected format: %s\n",
fmt_strs[gen_stat1 & 0xf]);
switch (mod_det_stat0) {
@@ -912,7 +1003,7 @@ static void log_status(struct i2c_client *client)
case 0xfe: p = "forced mode"; break;
default: p = "not defined";
}
- cx25840_info("Detected audio mode: %s\n", p);
+ v4l_info(client, "Detected audio mode: %s\n", p);
switch (mod_det_stat1) {
case 0x00: p = "not defined"; break;
@@ -938,10 +1029,10 @@ static void log_status(struct i2c_client *client)
case 0xff: p = "no detected audio standard"; break;
default: p = "not defined";
}
- cx25840_info("Detected audio standard: %s\n", p);
- cx25840_info("Audio muted: %s\n",
+ v4l_info(client, "Detected audio standard: %s\n", p);
+ v4l_info(client, "Audio muted: %s\n",
(mute_ctl & 0x2) ? "yes" : "no");
- cx25840_info("Audio microcontroller: %s\n",
+ v4l_info(client, "Audio microcontroller: %s\n",
(download_ctl & 0x10) ? "running" : "stopped");
switch (audio_config >> 4) {
@@ -963,7 +1054,7 @@ static void log_status(struct i2c_client *client)
case 0x0f: p = "automatic detection"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio standard: %s\n", p);
+ v4l_info(client, "Configured audio standard: %s\n", p);
if ((audio_config >> 4) < 0xF) {
switch (audio_config & 0xF) {
@@ -980,7 +1071,7 @@ static void log_status(struct i2c_client *client)
case 0x0a: p = "SAP"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio mode: %s\n", p);
+ v4l_info(client, "Configured audio mode: %s\n", p);
} else {
switch (audio_config & 0xF) {
case 0x00: p = "BG"; break;
@@ -996,30 +1087,27 @@ static void log_status(struct i2c_client *client)
case 0x0f: p = "automatic standard and mode detection"; break;
default: p = "undefined";
}
- cx25840_info("Configured audio system: %s\n", p);
+ v4l_info(client, "Configured audio system: %s\n", p);
}
- cx25840_info("Specified standard: %s\n",
+ v4l_info(client, "Specified standard: %s\n",
vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
- switch (state->input) {
- case CX25840_COMPOSITE0: p = "Composite 0"; break;
- case CX25840_COMPOSITE1: p = "Composite 1"; break;
- case CX25840_SVIDEO0: p = "S-Video 0"; break;
- case CX25840_SVIDEO1: p = "S-Video 1"; break;
- case CX25840_TUNER: p = "Tuner"; break;
+ if (vid_input >= CX25840_COMPOSITE1 &&
+ vid_input <= CX25840_COMPOSITE8) {
+ v4l_info(client, "Specified video input: Composite %d\n",
+ vid_input - CX25840_COMPOSITE1 + 1);
+ } else {
+ v4l_info(client, "Specified video input: S-Video (Luma In%d, Chroma In%d)\n",
+ (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
}
- cx25840_info("Specified input: %s\n", p);
- cx25840_info("Specified audio input: %s\n",
- state->audio_input == 0 ? "Tuner" : "External");
-
- switch (state->audclk_freq) {
- case V4L2_AUDCLK_441_KHZ: p = "44.1 kHz"; break;
- case V4L2_AUDCLK_48_KHZ: p = "48 kHz"; break;
- case V4L2_AUDCLK_32_KHZ: p = "32 kHz"; break;
- default: p = "undefined";
+ if (aud_input) {
+ v4l_info(client, "Specified audio input: Tuner (In%d)\n", aud_input);
+ } else {
+ v4l_info(client, "Specified audio input: External\n");
}
- cx25840_info("Specified audioclock freq: %s\n", p);
+
+ v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
switch (pref_mode & 0xf) {
case 0: p = "mono/language A"; break;
@@ -1032,7 +1120,7 @@ static void log_status(struct i2c_client *client)
case 7: p = "language AB"; break;
default: p = "undefined";
}
- cx25840_info("Preferred audio mode: %s\n", p);
+ v4l_info(client, "Preferred audio mode: %s\n", p);
if ((audio_config & 0xf) == 0xf) {
switch ((afc0 >> 3) & 0x3) {
@@ -1041,7 +1129,7 @@ static void log_status(struct i2c_client *client)
case 2: p = "autodetect"; break;
default: p = "undefined";
}
- cx25840_info("Selected 65 MHz format: %s\n", p);
+ v4l_info(client, "Selected 65 MHz format: %s\n", p);
switch (afc0 & 0x7) {
case 0: p = "chroma"; break;
@@ -1051,6 +1139,6 @@ static void log_status(struct i2c_client *client)
case 4: p = "autodetect"; break;
default: p = "undefined";
}
- cx25840_info("Selected 45 MHz format: %s\n", p);
+ v4l_info(client, "Selected 45 MHz format: %s\n", p);
}
}
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index df9d50a75542..e1a7823d82cd 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -15,7 +15,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
@@ -38,7 +37,7 @@ module_param(firmware, charp, 0444);
MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]");
MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]");
-static inline void set_i2c_delay(struct i2c_client *client, int delay)
+static void set_i2c_delay(struct i2c_client *client, int delay)
{
struct i2c_algo_bit_data *algod = client->adapter->algo_data;
@@ -52,7 +51,7 @@ static inline void set_i2c_delay(struct i2c_client *client, int delay)
}
}
-static inline void start_fw_load(struct i2c_client *client)
+static void start_fw_load(struct i2c_client *client)
{
/* DL_ADDR_LB=0 DL_ADDR_HB=0 */
cx25840_write(client, 0x800, 0x00);
@@ -66,7 +65,7 @@ static inline void start_fw_load(struct i2c_client *client)
set_i2c_delay(client, 3);
}
-static inline void end_fw_load(struct i2c_client *client)
+static void end_fw_load(struct i2c_client *client)
{
if (fastfw)
set_i2c_delay(client, 10);
@@ -77,38 +76,47 @@ static inline void end_fw_load(struct i2c_client *client)
cx25840_write(client, 0x803, 0x03);
}
-static inline int check_fw_load(struct i2c_client *client, int size)
+static int check_fw_load(struct i2c_client *client, int size)
{
/* DL_ADDR_HB DL_ADDR_LB */
int s = cx25840_read(client, 0x801) << 8;
s |= cx25840_read(client, 0x800);
if (size != s) {
- cx25840_err("firmware %s load failed\n", firmware);
+ v4l_err(client, "firmware %s load failed\n", firmware);
return -EINVAL;
}
- cx25840_info("loaded %s firmware (%d bytes)\n", firmware, size);
+ v4l_info(client, "loaded %s firmware (%d bytes)\n", firmware, size);
return 0;
}
-static inline int fw_write(struct i2c_client *client, u8 * data, int size)
+static int fw_write(struct i2c_client *client, u8 * data, int size)
{
- if (i2c_master_send(client, data, size) < size) {
+ int sent;
+
+ if ((sent = i2c_master_send(client, data, size)) < size) {
if (fastfw) {
- cx25840_err("333MHz i2c firmware load failed\n");
+ v4l_err(client, "333MHz i2c firmware load failed\n");
fastfw = 0;
set_i2c_delay(client, 10);
+ if (sent > 2) {
+ u16 dl_addr = cx25840_read(client, 0x801) << 8;
+ dl_addr |= cx25840_read(client, 0x800);
+ dl_addr -= sent - 2;
+ cx25840_write(client, 0x801, dl_addr >> 8);
+ cx25840_write(client, 0x800, dl_addr & 0xff);
+ }
+
if (i2c_master_send(client, data, size) < size) {
- cx25840_err
- ("100MHz i2c firmware load failed\n");
+ v4l_err(client, "100MHz i2c firmware load failed\n");
return -ENOSYS;
}
} else {
- cx25840_err("firmware load i2c failure\n");
+ v4l_err(client, "firmware load i2c failure\n");
return -ENOSYS;
}
@@ -124,7 +132,7 @@ int cx25840_loadfw(struct i2c_client *client)
int size, send, retval;
if (request_firmware(&fw, firmware, FWDEV(client)) != 0) {
- cx25840_err("unable to open firmware %s\n", firmware);
+ v4l_err(client, "unable to open firmware %s\n", firmware);
return -EINVAL;
}
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 13ba4e15ddea..04d879da7d63 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -22,7 +22,7 @@
#include "cx25840.h"
-static inline int odd_parity(u8 c)
+static int odd_parity(u8 c)
{
c ^= (c >> 4);
c ^= (c >> 2);
@@ -31,7 +31,7 @@ static inline int odd_parity(u8 c)
return c & 1;
}
-static inline int decode_vps(u8 * dst, u8 * p)
+static int decode_vps(u8 * dst, u8 * p)
{
static const u8 biphase_tbl[] = {
0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840.h
index 4932ed1c9b19..fd22f30dcc1b 100644
--- a/drivers/media/video/cx25840/cx25840.h
+++ b/drivers/media/video/cx25840/cx25840.h
@@ -24,47 +24,60 @@
#include <linux/videodev2.h>
#include <linux/i2c.h>
-extern int cx25840_debug;
-
-#define cx25840_dbg(fmt, arg...) do { if (cx25840_debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define cx25840_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define CX25840_CID_CARDTYPE (V4L2_CID_PRIVATE_BASE+0)
-
-/* The CARDTYPE_PVR150_WORKAROUND cardtype activates a workaround for a
- hardware bug that is present in PVR150 (and possible PVR500) cards that
- have certain NTSC tuners (tveeprom model numbers 85, 99 and 112). The
+/* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
+ present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
+ certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
audio autodetect fails on some channels for these models and the workaround
is to select the audio standard explicitly. Many thanks to Hauppauge for
providing this information. */
-enum cx25840_cardtype {
- CARDTYPE_PVR150,
- CARDTYPE_PG600,
- CARDTYPE_PVR150_WORKAROUND,
+#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
+
+enum cx25840_video_input {
+ /* Composite video inputs In1-In8 */
+ CX25840_COMPOSITE1 = 1,
+ CX25840_COMPOSITE2,
+ CX25840_COMPOSITE3,
+ CX25840_COMPOSITE4,
+ CX25840_COMPOSITE5,
+ CX25840_COMPOSITE6,
+ CX25840_COMPOSITE7,
+ CX25840_COMPOSITE8,
+
+ /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+ chroma input (In5-In8) */
+ CX25840_SVIDEO_LUMA1 = 0x10,
+ CX25840_SVIDEO_LUMA2 = 0x20,
+ CX25840_SVIDEO_LUMA3 = 0x30,
+ CX25840_SVIDEO_LUMA4 = 0x40,
+ CX25840_SVIDEO_CHROMA4 = 0x400,
+ CX25840_SVIDEO_CHROMA5 = 0x500,
+ CX25840_SVIDEO_CHROMA6 = 0x600,
+ CX25840_SVIDEO_CHROMA7 = 0x700,
+ CX25840_SVIDEO_CHROMA8 = 0x800,
+
+ /* S-Video aliases for common luma/chroma combinations */
+ CX25840_SVIDEO1 = 0x510,
+ CX25840_SVIDEO2 = 0x620,
+ CX25840_SVIDEO3 = 0x730,
+ CX25840_SVIDEO4 = 0x840,
};
-enum cx25840_input {
- CX25840_TUNER,
- CX25840_COMPOSITE0,
- CX25840_COMPOSITE1,
- CX25840_SVIDEO0,
- CX25840_SVIDEO1
+enum cx25840_audio_input {
+ /* Audio inputs: serial or In4-In8 */
+ CX25840_AUDIO_SERIAL,
+ CX25840_AUDIO4 = 4,
+ CX25840_AUDIO5,
+ CX25840_AUDIO6,
+ CX25840_AUDIO7,
+ CX25840_AUDIO8,
};
struct cx25840_state {
- enum cx25840_cardtype cardtype;
- enum cx25840_input input;
- int audio_input;
- enum v4l2_audio_clock_freq audclk_freq;
+ int pvr150_workaround;
+ int radio;
+ enum cx25840_video_input vid_input;
+ enum cx25840_audio_input aud_input;
+ u32 audclk_freq;
};
/* ----------------------------------------------------------------------- */
@@ -83,6 +96,7 @@ int cx25840_loadfw(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-audio.c */
int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg);
+void cx25840_audio_set_path(struct i2c_client *client);
/* ----------------------------------------------------------------------- */
/* cx25850-vbi.c */
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 85ba4106dc79..53308911ae6e 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -29,6 +29,20 @@ config VIDEO_CX88_DVB
You must also select one or more DVB/ATSC demodulators.
If you are unsure which you need, choose all of them.
+config VIDEO_CX88_ALSA
+ tristate "ALSA DMA audio support"
+ depends on VIDEO_CX88 && SND && EXPERIMENTAL
+ ---help---
+ This is a video4linux driver for direct (DMA) audio on
+ Conexant 2388x based TV cards.
+ It only works with boards with function 01 enabled.
+ To check if your board supports, use lspci -n.
+ If supported, you should see 1471:8801 or 1471:8811
+ PCI device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cx88-alsa.
+
config VIDEO_CX88_DVB_ALL_FRONTENDS
bool "Build all supported frontends for cx2388x based TV cards"
default y
@@ -38,6 +52,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
select DVB_CX22702
select DVB_LGDT330X
select DVB_NXT200X
+ select DVB_CX24123
---help---
This builds cx88-dvb with all currently supported frontend
demodulators. If you wish to tweak your configuration, and
@@ -89,3 +104,12 @@ config VIDEO_CX88_DVB_NXT200X
---help---
This adds ATSC 8VSB and QAM64/256 support for cards based on the
Connexant 2388x chip and the NXT2002/NXT2004 demodulator.
+
+config VIDEO_CX88_DVB_CX24123
+ bool "Conexant CX24123 DVB-S Support"
+ default y
+ depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
+ select DVB_CX24123
+ ---help---
+ This adds DVB-S support for cards based on the
+ Connexant 2388x chip and the CX24123 demodulator.
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 54401b02b7ce..6e5eaa22619e 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -4,7 +4,8 @@ cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
+obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
EXTRA_CFLAGS += -I$(src)/..
EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -16,5 +17,7 @@ extra-cflags-$(CONFIG_DVB_OR51132) += -DHAVE_OR51132=1
extra-cflags-$(CONFIG_DVB_LGDT330X) += -DHAVE_LGDT330X=1
extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1
extra-cflags-$(CONFIG_DVB_NXT200X) += -DHAVE_NXT200X=1
+extra-cflags-$(CONFIG_DVB_CX24123) += -DHAVE_CX24123=1
+extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
new file mode 100644
index 000000000000..a2e36a1e5f59
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -0,0 +1,847 @@
+/*
+ *
+ * Support for audio capture
+ * PCI function #1 of the cx2388x.
+ *
+ * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
+ * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+ * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
+ * Based on dummy.c by Jaroslav Kysela <perex@suse.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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <asm/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define dprintk(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...) if (debug >= level) \
+ printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+
+
+/****************************************************************************
+ Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+/* These can be replaced after done */
+#define MIXER_ADDR_LAST MAX_CX88_INPUT
+
+struct cx88_audio_dev {
+ struct cx88_core *core;
+ struct cx88_dmaqueue q;
+
+ /* pci i/o */
+ struct pci_dev *pci;
+ unsigned char pci_rev,pci_lat;
+
+ /* audio controls */
+ int irq;
+
+ snd_card_t *card;
+
+ spinlock_t reg_lock;
+
+ unsigned int dma_size;
+ unsigned int period_size;
+ unsigned int num_periods;
+
+ struct videobuf_dmabuf dma_risc;
+
+ int mixer_volume[MIXER_ADDR_LAST+1][2];
+ int capture_source[MIXER_ADDR_LAST+1][2];
+
+ long int read_count;
+ long int read_offset;
+
+ struct cx88_buffer *buf;
+
+ long opened;
+ snd_pcm_substream_t *substream;
+
+};
+typedef struct cx88_audio_dev snd_cx88_card_t;
+
+
+
+/****************************************************************************
+ Module global static vars
+ ****************************************************************************/
+
+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] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+static snd_card_t *snd_cx88_cards[SNDRV_CARDS];
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
+
+
+/****************************************************************************
+ Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Ricardo Cerqueira");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
+ "{{Conexant,23882},"
+ "{{Conexant,23883}");
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+/****************************************************************************
+ Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+{
+ struct cx88_buffer *buf = chip->buf;
+ struct cx88_core *core=chip->core;
+ struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
+
+
+ dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start);
+
+ /* setup fifo + format - out channel */
+ cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25],
+ buf->bpl, buf->risc.dma);
+
+ /* sets bpl size */
+ cx_write(MO_AUDD_LNGTH, buf->bpl);
+
+ /* reset counter */
+ cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET);
+
+ dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02));
+ /* enable irqs */
+ cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02);
+
+
+ /* Enables corresponding bits at AUD_INT_STAT */
+ cx_write(MO_AUD_INTMSK,
+ (1<<16)|
+ (1<<12)|
+ (1<<4)|
+ (1<<0)
+ );
+
+ /* start dma */
+ cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+ cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
+
+ if (debug)
+ cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+ return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+{
+ struct cx88_core *core=chip->core;
+ dprintk(1, "Stopping audio DMA\n");
+
+ /* stop dma */
+ cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+ /* disable irqs */
+ cx_clear(MO_PCI_INTMSK, 0x02);
+ cx_clear(MO_AUD_INTMSK,
+ (1<<16)|
+ (1<<12)|
+ (1<<4)|
+ (1<<0)
+ );
+
+ if (debug)
+ cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+ return 0;
+}
+
+#define MAX_IRQ_LOOP 10
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx88_aud_irqs[32] = {
+ "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+ NULL, /* reserved */
+ "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+ NULL, /* reserved */
+ "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */
+ NULL, /* reserved */
+ "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */
+ NULL, /* reserved */
+ "opc_err", "par_err", "rip_err", /* 16-18 */
+ "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx8801_aud_irq(snd_cx88_card_t *chip)
+{
+ struct cx88_core *core = chip->core;
+ u32 status, mask;
+ u32 count;
+
+ status = cx_read(MO_AUD_INTSTAT);
+ mask = cx_read(MO_AUD_INTMSK);
+ if (0 == (status & mask)) {
+ spin_unlock(&chip->reg_lock);
+ return;
+ }
+ cx_write(MO_AUD_INTSTAT, status);
+ if (debug > 1 || (status & mask & ~0xff))
+ cx88_print_irqbits(core->name, "irq aud",
+ cx88_aud_irqs, status, mask);
+ /* risc op code error */
+ if (status & (1 << 16)) {
+ printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name);
+ cx_clear(MO_AUD_DMACNTRL, 0x11);
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
+ }
+
+ /* risc1 downstream */
+ if (status & 0x01) {
+ spin_lock(&chip->reg_lock);
+ count = cx_read(MO_AUDD_GPCNT);
+ spin_unlock(&chip->reg_lock);
+ if (chip->read_count == 0)
+ chip->read_count += chip->dma_size;
+ }
+
+ if (chip->read_count >= chip->period_size) {
+ dprintk(2, "Elapsing period\n");
+ snd_pcm_period_elapsed(chip->substream);
+ }
+
+ dprintk(3,"Leaving audio IRQ handler...\n");
+
+ /* FIXME: Any other status should deserve a special handling? */
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ snd_cx88_card_t *chip = dev_id;
+ struct cx88_core *core = chip->core;
+ u32 status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+ status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02);
+ if (0 == status)
+ goto out;
+ dprintk( 3, "cx8801_irq\n" );
+ dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+ dprintk( 3, " status: %d\n", status );
+ handled = 1;
+ cx_write(MO_PCI_INTSTAT, status);
+
+ if (status & 0x02)
+ {
+ dprintk( 2, " ALSA IRQ handling\n" );
+ cx8801_aud_irq(chip);
+ }
+ };
+
+ if (MAX_IRQ_LOOP == loop) {
+ dprintk( 0, "clearing mask\n" );
+ dprintk(1,"%s/0: irq loop -- clearing mask\n",
+ core->name);
+ cx_clear(MO_PCI_INTMSK,0x02);
+ }
+
+ out:
+ return IRQ_RETVAL(handled);
+}
+
+
+static int dsp_buffer_free(snd_cx88_card_t *chip)
+{
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2,"Freeing buffer\n");
+ videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc);
+ videobuf_dma_free(&chip->dma_risc);
+ btcx_riscmem_free(chip->pci,&chip->buf->risc);
+ kfree(chip->buf);
+
+ chip->dma_size = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+static snd_pcm_hardware_t snd_cx88_digital_hw = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (2*2048),
+ .period_bytes_min = 2048,
+ .period_bytes_max = 2048,
+ .periods_min = 2,
+ .periods_max = 2,
+};
+
+/*
+ * audio pcm capture runtime free
+ */
+static void snd_card_cx88_runtime_free(snd_pcm_runtime_t *runtime)
+{
+}
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx88_pcm_open(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
+
+ if (test_and_set_bit(0, &chip->opened))
+ return -EBUSY;
+
+ err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
+ goto _error;
+
+ chip->substream = substream;
+
+ chip->read_count = 0;
+ chip->read_offset = 0;
+
+ runtime->private_free = snd_card_cx88_runtime_free;
+ runtime->hw = snd_cx88_digital_hw;
+
+ return 0;
+_error:
+ dprintk(1,"Error opening PCM!\n");
+ clear_bit(0, &chip->opened);
+ smp_mb__after_clear_bit();
+ return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx88_close(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+ clear_bit(0, &chip->opened);
+ smp_mb__after_clear_bit();
+
+ return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx88_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ struct cx88_buffer *buf;
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+
+ chip->period_size = params_period_bytes(hw_params);
+ chip->num_periods = params_periods(hw_params);
+ chip->dma_size = chip->period_size * params_periods(hw_params);
+
+ BUG_ON(!chip->dma_size);
+
+ dprintk(1,"Setting buffer\n");
+
+ buf = kmalloc(sizeof(*buf),GFP_KERNEL);
+ if (NULL == buf)
+ return -ENOMEM;
+ memset(buf,0,sizeof(*buf));
+
+
+ buf->vb.memory = V4L2_MEMORY_MMAP;
+ buf->vb.width = chip->period_size;
+ buf->vb.height = chip->num_periods;
+ buf->vb.size = chip->dma_size;
+ buf->vb.field = V4L2_FIELD_NONE;
+
+ videobuf_dma_init(&buf->vb.dma);
+ videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE,
+ (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+
+ videobuf_dma_pci_map(chip->pci,&buf->vb.dma);
+
+
+ cx88_risc_databuffer(chip->pci, &buf->risc,
+ buf->vb.dma.sglist,
+ buf->vb.width, buf->vb.height);
+
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+ buf->vb.state = STATE_PREPARED;
+
+ buf->bpl = chip->period_size;
+ chip->buf = buf;
+ chip->dma_risc = buf->vb.dma;
+
+ dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages);
+ substream->runtime->dma_area = chip->dma_risc.vmalloc;
+ return 0;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx88_hw_free(snd_pcm_substream_t * substream)
+{
+
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+ if (substream->runtime->dma_area) {
+ dsp_buffer_free(chip);
+ substream->runtime->dma_area = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx88_prepare(snd_pcm_substream_t *substream)
+{
+ return 0;
+}
+
+
+/*
+ * trigger callback
+ */
+static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ int err;
+
+ spin_lock(&chip->reg_lock);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ err=_cx88_start_audio_dma(chip);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ err=_cx88_stop_audio_dma(chip);
+ break;
+ default:
+ err=-EINVAL;
+ break;
+ }
+
+ spin_unlock(&chip->reg_lock);
+
+ return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream)
+{
+ snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ if (chip->read_count) {
+ chip->read_count -= snd_pcm_lib_period_bytes(substream);
+ chip->read_offset += snd_pcm_lib_period_bytes(substream);
+ if (chip->read_offset == chip->dma_size)
+ chip->read_offset = 0;
+ }
+
+ dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count);
+ return bytes_to_frames(runtime, chip->read_offset);
+
+}
+
+/*
+ * operators
+ */
+static snd_pcm_ops_t snd_cx88_pcm_ops = {
+ .open = snd_cx88_pcm_open,
+ .close = snd_cx88_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cx88_hw_params,
+ .hw_free = snd_cx88_hw_free,
+ .prepare = snd_cx88_prepare,
+ .trigger = snd_cx88_card_trigger,
+ .pointer = snd_cx88_pointer,
+};
+
+/*
+ * create a PCM device
+ */
+static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name)
+{
+ int err;
+ snd_pcm_t *pcm;
+
+ err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+ if (err < 0)
+ return err;
+ pcm->private_data = chip;
+ strcpy(pcm->name, name);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
+
+ return 0;
+}
+
+/****************************************************************************
+ CONTROL INTERFACE
+ ****************************************************************************/
+static int snd_cx88_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+{
+ info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ info->count = 1;
+ info->value.integer.min = 0;
+ info->value.integer.max = 0x3f;
+
+ return 0;
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core=chip->core;
+
+ value->value.integer.value[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
+
+ return 0;
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+{
+ snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cx88_core *core=chip->core;
+ int v;
+ u32 old_control;
+
+ spin_lock_irq(&chip->reg_lock);
+ old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
+ v = 0x3f - (value->value.integer.value[0] & 0x3f);
+ cx_andor(AUD_VOL_CTL, 0x3f, v);
+ spin_unlock_irq(&chip->reg_lock);
+
+ return v != old_control;
+}
+
+static snd_kcontrol_new_t snd_cx88_capture_volume = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Volume",
+ .info = snd_cx88_capture_volume_info,
+ .get = snd_cx88_capture_volume_get,
+ .put = snd_cx88_capture_volume_put,
+};
+
+
+/****************************************************************************
+ Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+struct pci_device_id cx88_audio_pci_tbl[] = {
+ {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+ {0, }
+};
+MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+
+/*
+ * Chip-specific destructor
+ */
+
+static int snd_cx88_free(snd_cx88_card_t *chip)
+{
+
+ if (chip->irq >= 0){
+ synchronize_irq(chip->irq);
+ free_irq(chip->irq, chip);
+ }
+
+ cx88_core_put(chip->core,chip->pci);
+
+ pci_disable_device(chip->pci);
+ return 0;
+}
+
+/*
+ * Component Destructor
+ */
+static void snd_cx88_dev_free(snd_card_t * card)
+{
+ snd_cx88_card_t *chip = card->private_data;
+
+ snd_cx88_free(chip);
+}
+
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+static int devno;
+static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci,
+ snd_cx88_card_t **rchip)
+{
+ snd_cx88_card_t *chip;
+ struct cx88_core *core;
+ int err;
+
+ *rchip = NULL;
+
+ err = pci_enable_device(pci);
+ if (err < 0)
+ return err;
+
+ pci_set_master(pci);
+
+ chip = (snd_cx88_card_t *) card->private_data;
+
+ core = cx88_core_get(pci);
+
+ if (!pci_dma_supported(pci,0xffffffff)) {
+ dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
+ err = -EIO;
+ cx88_core_put(core,pci);
+ return err;
+ }
+
+
+ /* pci init */
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+ spin_lock_init(&chip->reg_lock);
+
+ cx88_reset(core);
+ if (NULL == core) {
+ err = -EINVAL;
+ kfree (chip);
+ return err;
+ }
+ chip->core = core;
+
+ /* get irq */
+ err = request_irq(chip->pci->irq, cx8801_irq,
+ SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip);
+ if (err < 0) {
+ dprintk(0, "%s: can't get IRQ %d\n",
+ chip->core->name, chip->pci->irq);
+ return err;
+ }
+
+ /* print pci info */
+ pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev);
+ pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat);
+
+ dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
+ "latency: %d, mmio: 0x%lx\n", core->name, devno,
+ pci_name(pci), chip->pci_rev, pci->irq,
+ chip->pci_lat,pci_resource_start(pci,0));
+
+ chip->irq = pci->irq;
+ synchronize_irq(chip->irq);
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rchip = chip;
+
+ return 0;
+}
+
+static int __devinit cx88_audio_initdev(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ snd_card_t *card;
+ snd_cx88_card_t *chip;
+ int err;
+
+ if (devno >= SNDRV_CARDS)
+ return (-ENODEV);
+
+ if (!enable[devno]) {
+ ++devno;
+ return (-ENOENT);
+ }
+
+ card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t));
+ if (!card)
+ return (-ENOMEM);
+
+ card->private_free = snd_cx88_dev_free;
+
+ err = snd_cx88_create(card, pci, &chip);
+ if (err < 0)
+ return (err);
+
+ err = snd_cx88_pcm(chip, 0, "CX88 Digital");
+
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip));
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+
+ strcpy (card->driver, "CX88x");
+ sprintf(card->shortname, "Conexant CX%x", pci->device);
+ sprintf(card->longname, "%s at %#lx",
+ card->shortname, pci_resource_start(pci, 0));
+ strcpy (card->mixername, "CX88");
+
+ dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
+ card->driver,devno);
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ snd_card_free(card);
+ return (err);
+ }
+ snd_cx88_cards[devno] = card;
+
+ pci_set_drvdata(pci,card);
+
+ devno++;
+ return 0;
+}
+/*
+ * ALSA destructor
+ */
+static void __devexit cx88_audio_finidev(struct pci_dev *pci)
+{
+ struct cx88_audio_dev *card = pci_get_drvdata(pci);
+
+ snd_card_free((void *)card);
+
+ pci_set_drvdata(pci, NULL);
+
+ devno--;
+}
+
+/*
+ * PCI driver definition
+ */
+
+static struct pci_driver cx88_audio_pci_driver = {
+ .name = "cx88_audio",
+ .id_table = cx88_audio_pci_tbl,
+ .probe = cx88_audio_initdev,
+ .remove = cx88_audio_finidev,
+};
+
+/****************************************************************************
+ LINUX MODULE INIT
+ ****************************************************************************/
+
+/*
+ * module init
+ */
+static int cx88_audio_init(void)
+{
+ printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n",
+ (CX88_VERSION_CODE >> 16) & 0xff,
+ (CX88_VERSION_CODE >> 8) & 0xff,
+ CX88_VERSION_CODE & 0xff);
+#ifdef SNAPSHOT
+ printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
+ SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
+#endif
+ return pci_register_driver(&cx88_audio_pci_driver);
+}
+
+/*
+ * module remove
+ */
+static void cx88_audio_fini(void)
+{
+
+ pci_unregister_driver(&cx88_audio_pci_driver);
+}
+
+module_init(cx88_audio_init);
+module_exit(cx88_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 74e57a53116f..a502a4d6e4ae 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -32,10 +32,10 @@
#include <linux/firmware.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
-MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
static unsigned int mpegbufs = 32;
@@ -1375,7 +1375,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
struct cx88_core *core = dev->core;
if (debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
@@ -1539,10 +1539,9 @@ static int mpeg_open(struct inode *inode, struct file *file)
dprintk(1,"open minor=%d\n",minor);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
@@ -1678,10 +1677,9 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
goto fail_core;
err = -ENOMEM;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
goto fail_core;
- memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
dev->width = 720;
@@ -1689,6 +1687,18 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params));
memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params));
+ if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) {
+
+ if (core->tuner_formats & V4L2_STD_525_60) {
+ dev->height = 480;
+ dev->params.vi_frame_rate = 30;
+ } else {
+ dev->height = 576;
+ dev->params.vi_frame_rate = 25;
+ }
+
+ }
+
err = cx8802_init_common(dev);
if (0 != err)
goto fail_free;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 951709aa88ba..ad2f565f522c 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -611,12 +611,12 @@ struct cx88_board cx88_boards[] = {
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0xed12, /* internal decoder */
+ .gpio0 = 0xed1a,
.gpio2 = 0x00ff,
},{
.type = CX88_VMUX_DEBUG,
.vmux = 0,
- .gpio0 = 0xff01, /* mono from tuner chip */
+ .gpio0 = 0xff01,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -708,7 +708,7 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
.name = "DViCO FusionHDTV 3 Gold-T",
- .tuner_type = TUNER_THOMSON_DTT7611,
+ .tuner_type = TUNER_THOMSON_DTT761X,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -897,6 +897,158 @@ struct cx88_board cx88_boards[] = {
.gpio3 = 0x0000,
}},
},
+ [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
+ .name = "Hauppauge Nova-S-Plus DVB-S",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
+ .name = "Hauppauge Nova-SE2 DVB-S",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_KWORLD_DVBS_100] = {
+ .name = "KWorld DVB-S 100",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_DVB,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_HVR1100] = {
+ .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ }},
+ /* fixme: Add radio support */
+ .dvb = 1,
+ },
+ [CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
+ .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ }},
+ /* fixme: Add radio support */
+ .dvb = 1,
+ },
+ [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
+ .name = "digitalnow DNTV Live! DVB-T Pro",
+ .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+ TDA9887_PORT2_ACTIVE,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xf80808,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xf80808,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xf80808,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xf80808,
+ },
+ .dvb = 1,
+ },
+ [CX88_BOARD_KWORLD_DVB_T_CX22702] = {
+ /* Kworld V-stream Xpert DVB-T with Thomson tuner */
+ /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */
+ /* Manenti Marco <marco_manenti@colman.it> */
+ .name = "KWorld/VStream XPert DVB-T with cx22702",
+ .tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0700,
+ .gpio2 = 0x0101,
+ }},
+ .dvb = 1,
+ },
+ [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
+ .name = "DViCO FusionHDTV DVB-T Dual Digital",
+ .tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x000027df,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x000027df,
+ }},
+ .dvb = 1,
+ },
+
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1044,6 +1196,59 @@ struct cx88_subid cx88_subids[] = {
.subvendor = 0x1461,
.subdevice = 0x000a,
.card = CX88_BOARD_AVERTV_303,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9200,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9201,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9202,
+ .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+ },{
+ .subvendor = 0x17de,
+ .subdevice = 0x08b2,
+ .card = CX88_BOARD_KWORLD_DVBS_100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9400,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9402,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9800,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9802,
+ .card = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+ },{
+ .subvendor = 0x0070,
+ .subdevice = 0x9001,
+ .card = CX88_BOARD_HAUPPAUGE_DVB_T1,
+ },{
+ .subvendor = 0x1822,
+ .subdevice = 0x0025,
+ .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+ },{
+ .subvendor = 0x17de,
+ .subdevice = 0x08a1,
+ .card = CX88_BOARD_KWORLD_DVB_T_CX22702,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb50,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+ },{
+ .subvendor = 0x18ac,
+ .subdevice = 0xdb11,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+ /* Re-branded DViCO: UltraView DVB-T Plus */
},
};
const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1075,20 +1280,19 @@ static void __devinit leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
core->name, core->tuner_type, eeprom_data[0]);
}
-
-/* ----------------------------------------------------------------------- */
-
static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
{
struct tveeprom tv;
tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
core->tuner_type = tv.tuner_type;
+ core->tuner_formats = tv.tuner_formats;
core->has_radio = tv.has_radio;
/* Make sure we support the board model */
switch (tv.model)
{
+ case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
case 90002: /* Nova-T-PCI (9002) */
case 92001: /* Nova-S-Plus (Video and IR) */
case 92002: /* Nova-S-Plus (Video and IR) */
@@ -1096,7 +1300,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
case 90500: /* Nova-T-PCI (oem) */
case 90501: /* Nova-T-PCI (oem/IR) */
case 92000: /* Nova-SE2 (OEM, No Video or IR) */
-
+ case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
+ case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
+ case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
/* known */
break;
default:
@@ -1211,12 +1417,21 @@ void cx88_card_setup(struct cx88_core *core)
if (0 == core->i2c_rc)
leadtek_eeprom(core,eeprom);
break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
+ case CX88_BOARD_HAUPPAUGE_HVR1100LP:
if (0 == core->i2c_rc)
hauppauge_eeprom(core,eeprom);
break;
+ case CX88_BOARD_KWORLD_DVBS_100:
+ cx_write(MO_GP0_IO, 0x000007f8);
+ cx_write(MO_GP1_IO, 0x00000001);
+ break;
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
/* GPIO0:0 is hooked to mt352 reset pin */
cx_set(MO_GP0_IO, 0x00000101);
cx_clear(MO_GP0_IO, 0x00000001);
@@ -1232,6 +1447,9 @@ void cx88_card_setup(struct cx88_core *core)
cx_clear(MO_GP0_IO, 0x00000007);
cx_set(MO_GP2_IO, 0x00000101);
break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ cx_write(MO_GP0_IO, 0x00080808);
+ break;
case CX88_BOARD_ATI_HDTVWONDER:
if (0 == core->i2c_rc) {
/* enable tuner */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index bb6eb54e19ce..8d6d6a6cf785 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -32,8 +32,10 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
+#include <linux/mutex.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -74,62 +76,8 @@ MODULE_PARM_DESC(nocomb,"disable comb filter");
static unsigned int cx88_devcount;
static LIST_HEAD(cx88_devlist);
-static DECLARE_MUTEX(devlist);
+static DEFINE_MUTEX(devlist);
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void cx88_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
-/* ------------------------------------------------------------------ */
#define NO_SYNC_LINE (-1U)
static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist,
@@ -291,9 +239,9 @@ cx88_free_buffer(struct pci_dev *pci, struct cx88_buffer *buf)
* channel 22 (u video) - 2.0k
* channel 23 (v video) - 2.0k
* channel 24 (vbi) - 4.0k
- * channels 25+26 (audio) - 0.5k
+ * channels 25+26 (audio) - 4.0k
* channel 28 (mpeg) - 4.0k
- * TOTAL = 25.5k
+ * TOTAL = 29.0k
*
* Every channel has 160 bytes control data (64 bytes instruction
* queue and 6 CDT entries), which is close to 2k total.
@@ -359,7 +307,7 @@ struct sram_channel cx88_sram_channels[] = {
.ctrl_start = 0x180680,
.cdt = 0x180680 + 64,
.fifo_start = 0x185400,
- .fifo_size = 0x000200,
+ .fifo_size = 0x001000,
.ptr1_reg = MO_DMA25_PTR1,
.ptr2_reg = MO_DMA25_PTR2,
.cnt1_reg = MO_DMA25_CNT1,
@@ -371,7 +319,7 @@ struct sram_channel cx88_sram_channels[] = {
.ctrl_start = 0x180720,
.cdt = 0x180680 + 64, /* same as audio IN */
.fifo_start = 0x185400, /* same as audio IN */
- .fifo_size = 0x000200, /* same as audio IN */
+ .fifo_size = 0x001000, /* same as audio IN */
.ptr1_reg = MO_DMA26_PTR1,
.ptr2_reg = MO_DMA26_PTR2,
.cnt1_reg = MO_DMA26_CNT1,
@@ -382,7 +330,7 @@ struct sram_channel cx88_sram_channels[] = {
.cmds_start = 0x180200,
.ctrl_start = 0x1807C0,
.cdt = 0x1807C0 + 64,
- .fifo_start = 0x185600,
+ .fifo_start = 0x186400,
.fifo_size = 0x001000,
.ptr1_reg = MO_DMA28_PTR1,
.ptr2_reg = MO_DMA28_PTR2,
@@ -848,7 +796,6 @@ int cx88_start_audio_dma(struct cx88_core *core)
/* start dma */
cx_write(MO_AUD_DMACNTRL, 0x0003); /* Up and Down fifo enable */
-
return 0;
}
@@ -1090,7 +1037,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
struct list_head *item;
int i;
- down(&devlist);
+ mutex_lock(&devlist);
list_for_each(item,&cx88_devlist) {
core = list_entry(item, struct cx88_core, devlist);
if (pci->bus->number != core->pci_bus)
@@ -1101,14 +1048,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
if (0 != get_ressources(core,pci))
goto fail_unlock;
atomic_inc(&core->refcount);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
}
- core = kmalloc(sizeof(*core),GFP_KERNEL);
+ core = kzalloc(sizeof(*core),GFP_KERNEL);
if (NULL == core)
goto fail_unlock;
- memset(core,0,sizeof(*core));
atomic_inc(&core->refcount);
core->pci_bus = pci->bus->number;
core->pci_slot = PCI_SLOT(pci->devfn);
@@ -1177,13 +1123,13 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
cx88_card_setup(core);
cx88_ir_init(core,pci);
- up(&devlist);
+ mutex_unlock(&devlist);
return core;
fail_free:
kfree(core);
fail_unlock:
- up(&devlist);
+ mutex_unlock(&devlist);
return NULL;
}
@@ -1195,20 +1141,19 @@ void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
if (!atomic_dec_and_test(&core->refcount))
return;
- down(&devlist);
+ mutex_lock(&devlist);
cx88_ir_fini(core);
if (0 == core->i2c_rc)
i2c_bit_del_bus(&core->i2c_adap);
list_del(&core->devlist);
iounmap(core->lmmio);
cx88_devcount--;
- up(&devlist);
+ mutex_unlock(&devlist);
kfree(core);
}
/* ------------------------------------------------------------------ */
-EXPORT_SYMBOL(cx88_print_ioctl);
EXPORT_SYMBOL(cx88_print_irqbits);
EXPORT_SYMBOL(cx88_core_irq);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 99ea955f5987..e48aa3f6e500 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -3,7 +3,7 @@
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
*
- * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
* This program is free software; you can redistribute it and/or modify
@@ -31,10 +31,14 @@
#include "cx88.h"
#include "dvb-pll.h"
+#include <media/v4l2-common.h>
#ifdef HAVE_MT352
# include "mt352.h"
# include "mt352_priv.h"
+# ifdef HAVE_VP3054_I2C
+# include "cx88-vp3054-i2c.h"
+# endif
#endif
#ifdef HAVE_CX22702
# include "cx22702.h"
@@ -48,6 +52,9 @@
#ifdef HAVE_NXT200X
# include "nxt200x.h"
#endif
+#ifdef HAVE_CX24123
+# include "cx24123.h"
+#endif
MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -125,6 +132,27 @@ static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
return 0;
}
+static int dvico_dual_demod_init(struct dvb_frontend *fe)
+{
+ static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
+ static u8 reset [] = { RESET, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
+ static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
+ static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
+ static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(200);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { 0x89, 0x38, 0x39 };
@@ -172,6 +200,98 @@ static struct mt352_config dntv_live_dvbt_config = {
.demod_init = dntv_live_dvbt_demod_init,
.pll_set = mt352_pll_set,
};
+
+static struct mt352_config dvico_fusionhdtv_dual = {
+ .demod_address = 0x0F,
+ .demod_init = dvico_dual_demod_init,
+ .pll_set = mt352_pll_set,
+};
+
+#ifdef HAVE_VP3054_I2C
+static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
+{
+ static u8 clock_config [] = { 0x89, 0x38, 0x38 };
+ static u8 reset [] = { 0x50, 0x80 };
+ static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+ 0x00, 0xFF, 0x00, 0x40, 0x40 };
+ static u8 dntv_extra[] = { 0xB5, 0x7A };
+ static u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, clock_config, sizeof(clock_config));
+ udelay(2000);
+ mt352_write(fe, reset, sizeof(reset));
+ mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
+
+ mt352_write(fe, agc_cfg, sizeof(agc_cfg));
+ udelay(2000);
+ mt352_write(fe, dntv_extra, sizeof(dntv_extra));
+ mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+ return 0;
+}
+
+static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+
+ /* this message is to set up ATC and ALC */
+ static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0,
+ .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
+ int err;
+
+ if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters* params,
+ u8* pllbuf)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct i2c_msg msg =
+ { .addr = dev->core->pll_addr, .flags = 0,
+ .buf = pllbuf+1, .len = 4 };
+ int err;
+
+ /* Switch PLL to DVB mode */
+ err = philips_fmd1216_pll_init(fe);
+ if (err)
+ return err;
+
+ /* Tune PLL */
+ pllbuf[0] = dev->core->pll_addr << 1;
+ dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+ params->frequency,
+ params->u.ofdm.bandwidth);
+ if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+ printk(KERN_WARNING "cx88-dvb: %s error "
+ "(addr %02x <- %02x, err = %i)\n",
+ __FUNCTION__, pllbuf[0], pllbuf[1], err);
+ if (err < 0)
+ return err;
+ else
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static struct mt352_config dntv_live_dvbt_pro_config = {
+ .demod_address = 0x0f,
+ .no_tuner = 1,
+ .demod_init = dntv_live_dvbt_pro_demod_init,
+ .pll_set = dntv_live_dvbt_pro_pll_set,
+};
+#endif
#endif
#ifdef HAVE_CX22702
@@ -188,6 +308,12 @@ static struct cx22702_config hauppauge_novat_config = {
.pll_address = 0x61,
.pll_desc = &dvb_pll_thomson_dtt759x,
};
+static struct cx22702_config hauppauge_hvr1100_config = {
+ .demod_address = 0x63,
+ .output_mode = CX22702_SERIAL_OUTPUT,
+ .pll_address = 0x61,
+ .pll_desc = &dvb_pll_fmd1216me,
+};
#endif
#ifdef HAVE_OR51132
@@ -314,6 +440,40 @@ static struct nxt200x_config ati_hdtvwonder = {
};
#endif
+#ifdef HAVE_CX24123
+static int cx24123_set_ts_param(struct dvb_frontend* fe,
+ int is_punctured)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ dev->ts_gen_cntrl = 0x2;
+ return 0;
+}
+
+static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
+{
+ struct cx8802_dev *dev= fe->dvb->priv;
+ struct cx88_core *core = dev->core;
+
+ if (on)
+ cx_write(MO_GP0_IO, 0x000006f9);
+ else
+ cx_write(MO_GP0_IO, 0x000006fB);
+}
+
+static struct cx24123_config hauppauge_novas_config = {
+ .demod_address = 0x55,
+ .use_isl6421 = 1,
+ .set_ts_params = cx24123_set_ts_param,
+};
+
+static struct cx24123_config kworld_dvbs_100_config = {
+ .demod_address = 0x15,
+ .use_isl6421 = 0,
+ .set_ts_params = cx24123_set_ts_param,
+ .enable_lnb_voltage = cx24123_enable_lnb_voltage,
+};
+#endif
+
static int dvb_register(struct cx8802_dev *dev)
{
/* init struct videobuf_dvb */
@@ -329,10 +489,16 @@ static int dvb_register(struct cx8802_dev *dev)
break;
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
case CX88_BOARD_CONEXANT_DVB_T1:
+ case CX88_BOARD_KWORLD_DVB_T_CX22702:
case CX88_BOARD_WINFAST_DTV1000:
dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
&dev->core->i2c_adap);
break;
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
+ case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+ dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
+ &dev->core->i2c_adap);
+ break;
#endif
#ifdef HAVE_MT352
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
@@ -355,6 +521,24 @@ static int dvb_register(struct cx8802_dev *dev)
dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
&dev->core->i2c_adap);
break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+#ifdef HAVE_VP3054_I2C
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_fmd1216me;
+ dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
+ &((struct vp3054_i2c_state *)dev->card_priv)->adap);
+#else
+ printk("%s: built without vp3054 support\n", dev->core->name);
+#endif
+ break;
+ case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+ /* The tin box says DEE1601, but it seems to be DTT7579
+ * compatible, with a slightly different MT352 AGC gain. */
+ dev->core->pll_addr = 0x61;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+ dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+ &dev->core->i2c_adap);
+ break;
#endif
#ifdef HAVE_OR51132
case CX88_BOARD_PCHDTV_HD3000:
@@ -393,7 +577,7 @@ static int dvb_register(struct cx8802_dev *dev)
cx_set(MO_GP0_IO, 9);
mdelay(200);
dev->core->pll_addr = 0x61;
- dev->core->pll_desc = &dvb_pll_thomson_dtt7611;
+ dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
&dev->core->i2c_adap);
}
@@ -421,6 +605,17 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->core->i2c_adap);
break;
#endif
+#ifdef HAVE_CX24123
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
+ &dev->core->i2c_adap);
+ break;
+ case CX88_BOARD_KWORLD_DVBS_100:
+ dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
+ &dev->core->i2c_adap);
+ break;
+#endif
default:
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->core->name);
@@ -462,10 +657,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
goto fail_core;
err = -ENOMEM;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
goto fail_core;
- memset(dev,0,sizeof(*dev));
dev->pci = pci_dev;
dev->core = core;
@@ -473,6 +667,12 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
if (0 != err)
goto fail_free;
+#ifdef HAVE_VP3054_I2C
+ err = vp3054_i2c_probe(dev);
+ if (0 != err)
+ goto fail_free;
+#endif
+
/* dvb stuff */
printk("%s/2: cx2388x based dvb card\n", core->name);
videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
@@ -484,6 +684,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
err = dvb_register(dev);
if (0 != err)
goto fail_fini;
+
+ /* Maintain a reference to cx88-video can query the 8802 device. */
+ core->dvbdev = dev;
return 0;
fail_fini:
@@ -499,9 +702,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
{
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+ /* Destroy any 8802 reference. */
+ dev->core->dvbdev = NULL;
+
/* dvb */
videobuf_dvb_unregister(&dev->dvb);
+#ifdef HAVE_VP3054_I2C
+ vp3054_i2c_remove(dev);
+#endif
+
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 9790d412f192..f720901e9638 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -30,6 +30,7 @@
#include <asm/io.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
static unsigned int i2c_debug = 0;
module_param(i2c_debug, int, 0644);
@@ -94,7 +95,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, client->name);
+ client->driver->driver.name, client->addr, client->name);
if (!client->driver->command)
return 0;
@@ -135,7 +136,17 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
if (0 != core->i2c_rc)
return;
- i2c_clients_command(&core->i2c_adap, cmd, arg);
+
+ if (core->dvbdev) {
+ if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
+ core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+
+ i2c_clients_command(&core->i2c_adap, cmd, arg);
+
+ if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
+ core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+ } else
+ i2c_clients_command(&core->i2c_adap, cmd, arg);
}
static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 461019dca901..da2ad5c4b553 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2003 Pavel Machek
* Copyright (c) 2004 Gerd Knorr
- * Copyright (c) 2004 Chris Pascoe
+ * Copyright (c) 2004, 2005 Chris Pascoe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,9 +29,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <media/ir-common.h>
-
#include "cx88.h"
+#include <media/ir-common.h>
/* ---------------------------------------------------------------------- */
@@ -258,6 +257,114 @@ static IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = {
/* ---------------------------------------------------------------------- */
+/* AVERTV STUDIO 303 Remote */
+static IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE] = {
+ [ 0x2a ] = KEY_KP1,
+ [ 0x32 ] = KEY_KP2,
+ [ 0x3a ] = KEY_KP3,
+ [ 0x4a ] = KEY_KP4,
+ [ 0x52 ] = KEY_KP5,
+ [ 0x5a ] = KEY_KP6,
+ [ 0x6a ] = KEY_KP7,
+ [ 0x72 ] = KEY_KP8,
+ [ 0x7a ] = KEY_KP9,
+ [ 0x0e ] = KEY_KP0,
+
+ [ 0x02 ] = KEY_POWER,
+ [ 0x22 ] = KEY_VIDEO,
+ [ 0x42 ] = KEY_AUDIO,
+ [ 0x62 ] = KEY_ZOOM,
+ [ 0x0a ] = KEY_TV,
+ [ 0x12 ] = KEY_CD,
+ [ 0x1a ] = KEY_TEXT,
+
+ [ 0x16 ] = KEY_SUBTITLE,
+ [ 0x1e ] = KEY_REWIND,
+ [ 0x06 ] = KEY_PRINT,
+
+ [ 0x2e ] = KEY_SEARCH,
+ [ 0x36 ] = KEY_SLEEP,
+ [ 0x3e ] = KEY_SHUFFLE,
+ [ 0x26 ] = KEY_MUTE,
+
+ [ 0x4e ] = KEY_RECORD,
+ [ 0x56 ] = KEY_PAUSE,
+ [ 0x5e ] = KEY_STOP,
+ [ 0x46 ] = KEY_PLAY,
+
+ [ 0x6e ] = KEY_RED,
+ [ 0x0b ] = KEY_GREEN,
+ [ 0x66 ] = KEY_YELLOW,
+ [ 0x03 ] = KEY_BLUE,
+
+ [ 0x76 ] = KEY_LEFT,
+ [ 0x7e ] = KEY_RIGHT,
+ [ 0x13 ] = KEY_DOWN,
+ [ 0x1b ] = KEY_UP,
+};
+
+/* ---------------------------------------------------------------------- */
+
+/* DigitalNow DNTV Live! DVB-T Pro Remote */
+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = {
+ [ 0x16 ] = KEY_POWER,
+ [ 0x5b ] = KEY_HOME,
+
+ [ 0x55 ] = KEY_TV, /* live tv */
+ [ 0x58 ] = KEY_TUNER, /* digital Radio */
+ [ 0x5a ] = KEY_RADIO, /* FM radio */
+ [ 0x59 ] = KEY_DVD, /* dvd menu */
+ [ 0x03 ] = KEY_1,
+ [ 0x01 ] = KEY_2,
+ [ 0x06 ] = KEY_3,
+ [ 0x09 ] = KEY_4,
+ [ 0x1d ] = KEY_5,
+ [ 0x1f ] = KEY_6,
+ [ 0x0d ] = KEY_7,
+ [ 0x19 ] = KEY_8,
+ [ 0x1b ] = KEY_9,
+ [ 0x0c ] = KEY_CANCEL,
+ [ 0x15 ] = KEY_0,
+ [ 0x4a ] = KEY_CLEAR,
+ [ 0x13 ] = KEY_BACK,
+ [ 0x00 ] = KEY_TAB,
+ [ 0x4b ] = KEY_UP,
+ [ 0x4e ] = KEY_LEFT,
+ [ 0x4f ] = KEY_OK,
+ [ 0x52 ] = KEY_RIGHT,
+ [ 0x51 ] = KEY_DOWN,
+ [ 0x1e ] = KEY_VOLUMEUP,
+ [ 0x0a ] = KEY_VOLUMEDOWN,
+ [ 0x02 ] = KEY_CHANNELDOWN,
+ [ 0x05 ] = KEY_CHANNELUP,
+ [ 0x11 ] = KEY_RECORD,
+ [ 0x14 ] = KEY_PLAY,
+ [ 0x4c ] = KEY_PAUSE,
+ [ 0x1a ] = KEY_STOP,
+ [ 0x40 ] = KEY_REWIND,
+ [ 0x12 ] = KEY_FASTFORWARD,
+ [ 0x41 ] = KEY_PREVIOUSSONG, /* replay |< */
+ [ 0x42 ] = KEY_NEXTSONG, /* skip >| */
+ [ 0x54 ] = KEY_CAMERA, /* capture */
+ [ 0x50 ] = KEY_LANGUAGE, /* sap */
+ [ 0x47 ] = KEY_TV2, /* pip */
+ [ 0x4d ] = KEY_SCREEN,
+ [ 0x43 ] = KEY_SUBTITLE,
+ [ 0x10 ] = KEY_MUTE,
+ [ 0x49 ] = KEY_AUDIO, /* l/r */
+ [ 0x07 ] = KEY_SLEEP,
+ [ 0x08 ] = KEY_VIDEO, /* a/v */
+ [ 0x0e ] = KEY_PREVIOUS, /* recall */
+ [ 0x45 ] = KEY_ZOOM, /* zoom + */
+ [ 0x46 ] = KEY_ANGLE, /* zoom - */
+ [ 0x56 ] = KEY_RED,
+ [ 0x57 ] = KEY_GREEN,
+ [ 0x5c ] = KEY_YELLOW,
+ [ 0x5d ] = KEY_BLUE,
+};
+
+/* ---------------------------------------------------------------------- */
+
struct cx88_IR {
struct cx88_core *core;
struct input_dev *input;
@@ -266,7 +373,7 @@ struct cx88_IR {
char phys[32];
/* sample from gpio pin 16 */
- int sampling;
+ u32 sampling;
u32 samples[16];
int scount;
unsigned long release;
@@ -384,10 +491,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
ir_codes = ir_codes_cinergy_1400;
ir_type = IR_TYPE_PD;
- ir->sampling = 1;
+ ir->sampling = 0xeb04; /* address */
break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
ir_codes = ir_codes_hauppauge_new;
ir_type = IR_TYPE_RC5;
ir->sampling = 1;
@@ -427,6 +537,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keyup = 0x40;
ir->polling = 1; /* ms */
break;
+ case CX88_BOARD_AVERTV_303:
+ case CX88_BOARD_AVERTV_STUDIO_303:
+ ir_codes = ir_codes_avertv_303;
+ ir->gpio_addr = MO_GP2_IO;
+ ir->mask_keycode = 0xfb;
+ ir->mask_keydown = 0x02;
+ ir->polling = 50; /* ms */
+ break;
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+ ir_codes = ir_codes_dntv_live_dvbt_pro;
+ ir_type = IR_TYPE_PD;
+ ir->sampling = 0xff00; /* address */
+ break;
}
if (NULL == ir_codes) {
@@ -484,6 +607,10 @@ int cx88_ir_fini(struct cx88_core *core)
if (NULL == ir)
return 0;
+ if (ir->sampling) {
+ cx_write(MO_DDSCFG_IO, 0x0);
+ core->pci_irqmask &= ~(1 << 18);
+ }
if (ir->polling) {
del_timer(&ir->timer);
flush_scheduled_work();
@@ -535,6 +662,7 @@ void cx88_ir_irq(struct cx88_core *core)
/* decode it */
switch (core->board) {
case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+ case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
if (ircode == 0xffffffff) { /* decoding error */
@@ -550,7 +678,7 @@ void cx88_ir_irq(struct cx88_core *core)
break;
}
- if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+ if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
ir_dprintk("pulse distance decoded wrong address\n");
break;
}
@@ -567,6 +695,9 @@ void cx88_ir_irq(struct cx88_core *core)
break;
case CX88_BOARD_HAUPPAUGE:
case CX88_BOARD_HAUPPAUGE_DVB_T1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_HVR1100:
ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7);
ir_dprintk("biphase decoded: %x\n", ircode);
if ((ircode & 0xfffff000) != 0x3000)
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 35e6d0c2b872..c79cc1d2bf8b 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -78,6 +78,11 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
cx_write(TS_SOP_STAT, 1<<13);
break;
+ case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+ case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+ cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
+ udelay(100);
+ break;
default:
cx_write(TS_SOP_STAT, 0x00);
break;
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index a1b120c8a9b5..da8d97ce0c4b 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -60,6 +60,11 @@ static unsigned int audio_debug = 0;
module_param(audio_debug, int, 0644);
MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+static unsigned int always_analog = 0;
+module_param(always_analog,int,0644);
+MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+
#define dprintk(fmt, arg...) if (audio_debug) \
printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
@@ -132,14 +137,22 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
{
u32 volume;
+#ifndef USING_CX88_ALSA
/* restart dma; This avoids buzz in NICAM and is good in others */
cx88_stop_audio_dma(core);
+#endif
cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
+#ifndef USING_CX88_ALSA
cx88_start_audio_dma(core);
+#endif
if (cx88_boards[core->board].blackbird) {
/* sets sound input from external adc */
- cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+ if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN)
+ cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+ else
+ cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+
cx_write(AUD_I2SINPUTCNTL, 4);
cx_write(AUD_BAUDRATE, 1);
/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
@@ -147,7 +160,8 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
cx_write(AUD_I2SOUTPUTCNTL, 1);
cx_write(AUD_I2SCNTL, 0);
/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
- } else {
+ }
+ if ((always_analog) || (!cx88_boards[core->board].blackbird)) {
ctl |= EN_DAC_ENABLE;
cx_write(AUD_CTL, ctl);
}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 24a48f8a48c1..073494ceab0f 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -33,6 +33,7 @@
#include <asm/div64.h>
#include "cx88.h"
+#include <media/v4l2-common.h>
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
@@ -240,7 +241,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0,
+ .default_value = 0x3f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -271,7 +272,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0xff,
.step = 1,
- .default_value = 0,
+ .default_value = 0x7f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.off = 0,
@@ -285,6 +286,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.name = "Mute",
.minimum = 0,
.maximum = 1,
+ .default_value = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
},
.reg = AUD_VOL_CTL,
@@ -298,7 +300,7 @@ static struct cx88_ctrl cx8800_ctls[] = {
.minimum = 0,
.maximum = 0x3f,
.step = 1,
- .default_value = 0,
+ .default_value = 0x1f,
.type = V4L2_CTRL_TYPE_INTEGER,
},
.reg = AUD_VOL_CTL,
@@ -748,10 +750,9 @@ static int video_open(struct inode *inode, struct file *file)
minor,radio,v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -917,6 +918,9 @@ static int get_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = ((value + (c->off << c->shift)) & c->mask) >> c->shift;
break;
}
+ printk("get_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+ ctl->id, c->reg, ctl->value,
+ c->mask, c->sreg ? " [shadowed]" : "");
return 0;
}
@@ -925,13 +929,13 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
{
/* struct cx88_core *core = dev->core; */
struct cx88_ctrl *c = NULL;
- u32 v_sat_value;
- u32 value;
+ u32 value,mask;
int i;
-
- for (i = 0; i < CX8800_CTLS; i++)
- if (cx8800_ctls[i].v.id == ctl->id)
+ for (i = 0; i < CX8800_CTLS; i++) {
+ if (cx8800_ctls[i].v.id == ctl->id) {
c = &cx8800_ctls[i];
+ }
+ }
if (NULL == c)
return -EINVAL;
@@ -939,6 +943,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
ctl->value = c->v.minimum;
if (ctl->value > c->v.maximum)
ctl->value = c->v.maximum;
+ mask=c->mask;
switch (ctl->id) {
case V4L2_CID_AUDIO_BALANCE:
value = (ctl->value < 0x40) ? (0x40 - ctl->value) : ctl->value;
@@ -948,56 +953,44 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl)
break;
case V4L2_CID_SATURATION:
/* special v_sat handling */
- v_sat_value = ctl->value - (0x7f - 0x5a);
- if (v_sat_value > 0xff)
- v_sat_value = 0xff;
- if (v_sat_value < 0x00)
- v_sat_value = 0x00;
- cx_andor(MO_UV_SATURATION, 0xff00, v_sat_value << 8);
- /* fall through to default route for u_sat */
+
+ value = ((ctl->value - c->off) << c->shift) & c->mask;
+
+ if (core->tvnorm->id & V4L2_STD_SECAM) {
+ /* For SECAM, both U and V sat should be equal */
+ value=value<<8|value;
+ } else {
+ /* Keeps U Saturation proportional to V Sat */
+ value=(value*0x5a)/0x7f<<8|value;
+ }
+ mask=0xffff;
+ break;
default:
value = ((ctl->value - c->off) << c->shift) & c->mask;
break;
}
- dprintk(1,"set_control id=0x%X reg=0x%x val=0x%x%s\n",
- ctl->id, c->reg, value, c->sreg ? " [shadowed]" : "");
+ printk("set_control id=0x%X reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+ ctl->id, c->reg, value,
+ mask, c->sreg ? " [shadowed]" : "");
if (c->sreg) {
- cx_sandor(c->sreg, c->reg, c->mask, value);
+ cx_sandor(c->sreg, c->reg, mask, value);
} else {
- cx_andor(c->reg, c->mask, value);
+ cx_andor(c->reg, mask, value);
}
return 0;
}
-/* 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,
- .value = 1,
- };
- static struct v4l2_control volume = {
- .id = V4L2_CID_AUDIO_VOLUME,
- .value = 0x3f,
- };
- static struct v4l2_control hue = {
- .id = V4L2_CID_HUE,
- .value = 0x80,
- };
- static struct v4l2_control contrast = {
- .id = V4L2_CID_CONTRAST,
- .value = 0x80,
- };
- static struct v4l2_control brightness = {
- .id = V4L2_CID_BRIGHTNESS,
- .value = 0x80,
- };
+ struct v4l2_control ctrl;
+ int i;
- set_control(core,&mute);
- set_control(core,&volume);
- set_control(core,&hue);
- set_control(core,&contrast);
- set_control(core,&brightness);
+ for (i = 0; i < CX8800_CTLS; i++) {
+ ctrl.id=cx8800_ctls[i].v.id;
+ ctrl.value=cx8800_ctls[i].v.default_value
+ +cx8800_ctls[i].off;
+ set_control(core, &ctrl);
+ }
}
/* ------------------------------------------------------------------ */
@@ -1125,7 +1118,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
int err;
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
/* --- capabilities ------------------------------------------ */
@@ -1261,7 +1254,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
dprintk( 1, "CORE IOCTL: 0x%x\n", cmd );
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
/* ---------- tv norms ---------- */
@@ -1481,7 +1474,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
struct cx88_core *core = dev->core;
if (video_debug > 1)
- cx88_print_ioctl(core->name,cmd);
+ v4l_print_ioctl(core->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
@@ -1740,6 +1733,7 @@ static struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -1767,6 +1761,7 @@ static struct file_operations radio_fops =
.open = video_open,
.release = video_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -1813,10 +1808,9 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
struct cx88_core *core;
int err;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
return -ENOMEM;
- memset(dev,0,sizeof(*dev));
/* pci init */
dev->pci = pci_dev;
@@ -1928,8 +1922,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
/* initial device configuration */
down(&core->lock);
- init_controls(core);
cx88_set_tvnorm(core,tvnorms);
+ init_controls(core);
video_mux(core,0);
up(&core->lock);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
new file mode 100644
index 000000000000..751a754a45e9
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -0,0 +1,177 @@
+/*
+
+ cx88-vp3054-i2c.c -- support for the secondary I2C bus of the
+ DNTV Live! DVB-T Pro (VP-3054), wired as:
+ GPIO[0] -> SCL, GPIO[1] -> SDA
+
+ (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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/moduleparam.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "cx88.h"
+#include "cx88-vp3054-i2c.h"
+
+
+MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_LICENSE("GPL");
+
+/* ----------------------------------------------------------------------- */
+
+static void vp3054_bit_setscl(void *data, int state)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (state) {
+ vp3054_i2c->state |= 0x0001; /* SCL high */
+ vp3054_i2c->state &= ~0x0100; /* external pullup */
+ } else {
+ vp3054_i2c->state &= ~0x0001; /* SCL low */
+ vp3054_i2c->state |= 0x0100; /* drive pin */
+ }
+ cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
+ cx_read(MO_GP0_IO);
+}
+
+static void vp3054_bit_setsda(void *data, int state)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (state) {
+ vp3054_i2c->state |= 0x0002; /* SDA high */
+ vp3054_i2c->state &= ~0x0200; /* tristate pin */
+ } else {
+ vp3054_i2c->state &= ~0x0002; /* SDA low */
+ vp3054_i2c->state |= 0x0200; /* drive pin */
+ }
+ cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
+ cx_read(MO_GP0_IO);
+}
+
+static int vp3054_bit_getscl(void *data)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ u32 state;
+
+ state = cx_read(MO_GP0_IO);
+ return (state & 0x01) ? 1 : 0;
+}
+
+static int vp3054_bit_getsda(void *data)
+{
+ struct cx8802_dev *dev = data;
+ struct cx88_core *core = dev->core;
+ u32 state;
+
+ state = cx_read(MO_GP0_IO);
+ return (state & 0x02) ? 1 : 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+ .setsda = vp3054_bit_setsda,
+ .setscl = vp3054_bit_setscl,
+ .getsda = vp3054_bit_getsda,
+ .getscl = vp3054_bit_getscl,
+ .udelay = 16,
+ .mdelay = 10,
+ .timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter vp3054_i2c_adap_template = {
+ .name = "cx2388x",
+ .owner = THIS_MODULE,
+ .id = I2C_HW_B_CX2388x,
+};
+
+static struct i2c_client vp3054_i2c_client_template = {
+ .name = "VP-3054",
+};
+
+int vp3054_i2c_probe(struct cx8802_dev *dev)
+{
+ struct cx88_core *core = dev->core;
+ struct vp3054_i2c_state *vp3054_i2c;
+ int rc;
+
+ if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ return 0;
+
+ dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+ if (dev->card_priv == NULL)
+ return -ENOMEM;
+ vp3054_i2c = dev->card_priv;
+
+ memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template,
+ sizeof(vp3054_i2c->adap));
+ memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
+ sizeof(vp3054_i2c->algo));
+ memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
+ sizeof(vp3054_i2c->client));
+
+ vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
+
+ vp3054_i2c->adap.dev.parent = &dev->pci->dev;
+ strlcpy(vp3054_i2c->adap.name, core->name,
+ sizeof(vp3054_i2c->adap.name));
+ vp3054_i2c->algo.data = dev;
+ i2c_set_adapdata(&vp3054_i2c->adap, dev);
+ vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
+ vp3054_i2c->client.adapter = &vp3054_i2c->adap;
+
+ vp3054_bit_setscl(dev,1);
+ vp3054_bit_setsda(dev,1);
+
+ rc = i2c_bit_add_bus(&vp3054_i2c->adap);
+ if (0 != rc) {
+ printk("%s: vp3054_i2c register FAILED\n", core->name);
+
+ kfree(dev->card_priv);
+ dev->card_priv = NULL;
+ }
+
+ return rc;
+}
+
+void vp3054_i2c_remove(struct cx8802_dev *dev)
+{
+ struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+ if (vp3054_i2c == NULL ||
+ dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+ return;
+
+ i2c_bit_del_bus(&vp3054_i2c->adap);
+ kfree(vp3054_i2c);
+}
+
+EXPORT_SYMBOL(vp3054_i2c_probe);
+EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
new file mode 100644
index 000000000000..b7a0a04d2423
--- /dev/null
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.h
@@ -0,0 +1,35 @@
+/*
+
+ cx88-vp3054-i2c.h -- support for the secondary I2C bus of the
+ DNTV Live! DVB-T Pro (VP-3054), wired as:
+ GPIO[0] -> SCL, GPIO[1] -> SDA
+
+ (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the 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.
+
+*/
+
+/* ----------------------------------------------------------------------- */
+struct vp3054_i2c_state {
+ struct i2c_adapter adap;
+ struct i2c_algo_bit_data algo;
+ struct i2c_client client;
+ u32 state;
+};
+
+/* ----------------------------------------------------------------------- */
+int vp3054_i2c_probe(struct cx8802_dev *dev);
+void vp3054_i2c_remove(struct cx8802_dev *dev);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 77beafc5c327..e9fd55b57fa6 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -179,6 +179,14 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_ATI_HDTVWONDER 34
#define CX88_BOARD_WINFAST_DTV1000 35
#define CX88_BOARD_AVERTV_303 36
+#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37
+#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38
+#define CX88_BOARD_KWORLD_DVBS_100 39
+#define CX88_BOARD_HAUPPAUGE_HVR1100 40
+#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41
+#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42
+#define CX88_BOARD_KWORLD_DVB_T_CX22702 43
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -280,6 +288,9 @@ struct cx88_core {
unsigned int tda9887_conf;
unsigned int has_radio;
+ /* Supported V4L _STD_ tuner formats */
+ unsigned int tuner_formats;
+
/* config info -- dvb */
struct dvb_pll_desc *pll_desc;
unsigned int pll_addr;
@@ -301,6 +312,9 @@ struct cx88_core {
/* various v4l controls */
u32 freq;
+
+ /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
+ struct cx8802_dev *dvbdev;
};
struct cx8800_dev;
@@ -411,6 +425,8 @@ struct cx8802_dev {
struct videobuf_dvb dvb;
void* fe_handle;
int (*fe_release)(void *handle);
+
+ void *card_priv;
/* for switching modulation types */
unsigned char ts_gen_cntrl;
@@ -447,7 +463,6 @@ struct cx8802_dev {
extern void cx88_print_irqbits(char *name, char *tag, char **strings,
u32 bits, u32 mask);
-extern void cx88_print_ioctl(char *name, unsigned int cmd);
extern int cx88_core_irq(struct cx88_core *core, u32 status);
extern void cx88_wakeup(struct cx88_core *core,
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
index da9481198c53..2831bdd12057 100644
--- a/drivers/media/video/dpc7146.c
+++ b/drivers/media/video/dpc7146.c
@@ -94,12 +94,11 @@ static int dpc_probe(struct saa7146_dev* dev)
struct i2c_client *client;
struct list_head *item;
- dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL);
+ dpc = kzalloc(sizeof(struct dpc), GFP_KERNEL);
if( NULL == dpc ) {
printk("dpc_v4l2.o: dpc_probe: not enough kernel memory.\n");
return -ENOMEM;
}
- memset(dpc, 0x0, sizeof(struct dpc));
/* FIXME: enable i2c-port pins, video-port-pins
video port pins should be enabled here ?! */
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 57779e63f35d..58f7b4194a0d 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -30,6 +30,7 @@
#include <media/tuner.h>
#include <media/audiochip.h>
#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
#include "msp3400.h"
#include "em28xx.h"
@@ -261,7 +262,6 @@ void em28xx_card_setup(struct em28xx *dev)
/* request some modules */
if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) {
struct tveeprom tv;
- struct v4l2_audioout ao;
#ifdef CONFIG_MODULES
request_module("tveeprom");
request_module("ir-kbd-i2c");
@@ -274,12 +274,8 @@ void em28xx_card_setup(struct em28xx *dev)
dev->tuner_type= tv.tuner_type;
if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
+ dev->i2s_speed=2048000;
dev->has_msp34xx=1;
- memset (&ao,0,sizeof(ao));
-
- ao.index=2;
- ao.mode=V4L2_AUDMODE_32BITS;
- em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao);
} else
dev->has_msp34xx=0;
}
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 0cfe75416ec6..dff3893f32fd 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -32,7 +32,7 @@
/* #define ENABLE_DEBUG_ISOC_FRAMES */
-static unsigned int core_debug;
+static unsigned int core_debug = 0;
module_param(core_debug,int,0644);
MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
printk(KERN_INFO "%s %s :"fmt, \
dev->name, __FUNCTION__ , ##arg); } while (0)
-static unsigned int reg_debug;
+static unsigned int reg_debug = 0;
module_param(reg_debug,int,0644);
MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
@@ -50,7 +50,7 @@ MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
printk(KERN_INFO "%s %s :"fmt, \
dev->name, __FUNCTION__ , ##arg); } while (0)
-static unsigned int isoc_debug;
+static unsigned int isoc_debug = 0;
module_param(isoc_debug,int,0644);
MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]");
@@ -63,59 +63,6 @@ static int alt = EM28XX_PINOUT;
module_param(alt, int, 0644);
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void em28xx_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
/*
* em28xx_request_buffers()
@@ -126,7 +73,7 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count)
const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */
void *buff = NULL;
u32 i;
- em28xx_coredbg("requested %i buffers with size %zd", count, imagesize);
+ em28xx_coredbg("requested %i buffers with size %zi", count, imagesize);
if (count > EM28XX_NUM_FRAMES)
count = EM28XX_NUM_FRAMES;
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 7f5603054f02..0591a705b7a1 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -28,6 +28,7 @@
#include <linux/video_decoder.h>
#include "em28xx.h"
+#include <media/v4l2-common.h>
#include <media/tuner.h>
/* ----------------------------------------------------------- */
@@ -486,9 +487,7 @@ static struct i2c_adapter em28xx_adap_template = {
.inc_use = inc_use,
.dec_use = dec_use,
#endif
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "em28xx",
.id = I2C_HW_B_EM28XX,
.algo = &em28xx_algo,
@@ -497,7 +496,6 @@ static struct i2c_adapter em28xx_adap_template = {
static struct i2c_client em28xx_client_template = {
.name = "em28xx internal",
- .flags = I2C_CLIENT_ALLOW_USE,
};
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 9b94f77d6fd7..30dfa5370c73 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -76,6 +76,58 @@ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
[ 0x40 ] = KEY_ZOOM,
};
+static IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+ [ 0x3a ] = KEY_KP0,
+ [ 0x31 ] = KEY_KP1,
+ [ 0x32 ] = KEY_KP2,
+ [ 0x33 ] = KEY_KP3,
+ [ 0x34 ] = KEY_KP4,
+ [ 0x35 ] = KEY_KP5,
+ [ 0x36 ] = KEY_KP6,
+ [ 0x37 ] = KEY_KP7,
+ [ 0x38 ] = KEY_KP8,
+ [ 0x39 ] = KEY_KP9,
+
+ [ 0x2f ] = KEY_POWER,
+
+ [ 0x2e ] = KEY_P,
+ [ 0x1f ] = KEY_L,
+ [ 0x2b ] = KEY_I,
+
+ [ 0x2d ] = KEY_ZOOM,
+ [ 0x1e ] = KEY_ZOOM,
+ [ 0x1b ] = KEY_VOLUMEUP,
+ [ 0x0f ] = KEY_VOLUMEDOWN,
+ [ 0x17 ] = KEY_CHANNELUP,
+ [ 0x1c ] = KEY_CHANNELDOWN,
+ [ 0x25 ] = KEY_INFO,
+
+ [ 0x3c ] = KEY_MUTE,
+
+ [ 0x3d ] = KEY_LEFT,
+ [ 0x3b ] = KEY_RIGHT,
+
+ [ 0x3f ] = KEY_UP,
+ [ 0x3e ] = KEY_DOWN,
+ [ 0x1a ] = KEY_PAUSE,
+
+ [ 0x1d ] = KEY_MENU,
+ [ 0x19 ] = KEY_PLAY,
+ [ 0x16 ] = KEY_REWIND,
+ [ 0x13 ] = KEY_FORWARD,
+ [ 0x15 ] = KEY_PAUSE,
+ [ 0x0e ] = KEY_REWIND,
+ [ 0x0d ] = KEY_PLAY,
+ [ 0x0b ] = KEY_STOP,
+ [ 0x07 ] = KEY_FORWARD,
+ [ 0x27 ] = KEY_RECORD,
+ [ 0x26 ] = KEY_TUNER,
+ [ 0x29 ] = KEY_TEXT,
+ [ 0x2a ] = KEY_MEDIA,
+ [ 0x18 ] = KEY_EPG,
+ [ 0x27 ] = KEY_RECORD,
+};
+
/* ----------------------------------------------------------------------- */
static int get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
@@ -138,6 +190,28 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
+static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+ unsigned char buf[3];
+
+ /* poll IR chip */
+
+ if (3 != i2c_master_recv(&ir->c,buf,3)) {
+ dprintk("read error\n");
+ return -EIO;
+ }
+
+ dprintk("key %02x\n", buf[2]&0x3f);
+ if (buf[0]!=0x00){
+ return 0;
+ }
+
+ *ir_key = buf[2]&0x3f;
+ *ir_raw = buf[2]&0x3f;
+
+ return 1;
+}
+
/* ----------------------------------------------------------------------- */
void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
{
@@ -159,6 +233,9 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
break;
case (EM2820_BOARD_PINNACLE_USB_2):
+ ir->ir_codes = ir_codes_em_pinnacle_usb;
+ ir->get_key = get_key_pinnacle_usb;
+ snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
break;
case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
ir->ir_codes = ir_codes_hauppauge_new;
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 06d76879bde2..eea304f75176 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -29,9 +29,11 @@
#include <linux/i2c.h>
#include <linux/version.h>
#include <linux/video_decoder.h>
+#include <linux/mutex.h>
#include "em28xx.h"
#include <media/tuner.h>
+#include <media/v4l2-common.h>
#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
"Markus Rechberger <mrechberger@gmail.com>, " \
@@ -106,8 +108,32 @@ static const unsigned char saa7114_i2c_init[] = {
#define TVNORMS ARRAY_SIZE(tvnorms)
/* supported controls */
+/* Common to all boards */
static struct v4l2_queryctrl em28xx_qctrl[] = {
{
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Volume",
+ .minimum = 0x0,
+ .maximum = 0x1f,
+ .step = 0x1,
+ .default_value = 0x1f,
+ .flags = 0,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ }
+};
+
+/* FIXME: These are specific to saa711x - should be moved to its code */
+static struct v4l2_queryctrl saa711x_qctrl[] = {
+ {
.id = V4L2_CID_BRIGHTNESS,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
@@ -135,24 +161,6 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.default_value = 0x10,
.flags = 0,
},{
- .id = V4L2_CID_AUDIO_VOLUME,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Volume",
- .minimum = 0x0,
- .maximum = 0x1f,
- .step = 0x1,
- .default_value = 0x1f,
- .flags = 0,
- },{
- .id = V4L2_CID_AUDIO_MUTE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "Mute",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 1,
- .flags = 0,
- },{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Red chroma balance",
@@ -179,12 +187,12 @@ static struct v4l2_queryctrl em28xx_qctrl[] = {
.step = 0x1,
.default_value = 0x20,
.flags = 0,
- }
+ }
};
static struct usb_driver em28xx_usb_driver;
-static DECLARE_MUTEX(em28xx_sysfs_lock);
+static DEFINE_MUTEX(em28xx_sysfs_lock);
static DECLARE_RWSEM(em28xx_disconnect);
/********************* v4l2 interface ******************************************/
@@ -280,6 +288,8 @@ static void video_mux(struct em28xx *dev, int index)
em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
if (dev->has_msp34xx) {
+ if (dev->i2s_speed)
+ em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput);
ainput = EM28XX_AUDIO_SRC_TUNER;
em28xx_audio_source(dev, ainput);
@@ -385,7 +395,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
*/
static void em28xx_release_resources(struct em28xx *dev)
{
- down(&em28xx_sysfs_lock);
+ mutex_lock(&em28xx_sysfs_lock);
em28xx_info("V4L2 device /dev/video%d deregistered\n",
dev->vdev->minor);
@@ -394,7 +404,7 @@ static void em28xx_release_resources(struct em28xx *dev)
/* video_unregister_device(dev->vbi_dev); */
em28xx_i2c_unregister(dev);
usb_put_dev(dev->udev);
- up(&em28xx_sysfs_lock);
+ mutex_unlock(&em28xx_sysfs_lock);
}
/*
@@ -674,7 +684,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
*/
static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
{
- s32 tmp;
switch (ctrl->id) {
case V4L2_CID_AUDIO_MUTE:
ctrl->value = dev->mute;
@@ -682,6 +691,16 @@ static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_VOLUME:
ctrl->value = dev->volume;
return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+/*FIXME: should be moved to saa711x */
+static int saa711x_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
+{
+ s32 tmp;
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if ((tmp = em28xx_brightness_get(dev)) < 0)
return -EIO;
@@ -731,6 +750,15 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
case V4L2_CID_AUDIO_VOLUME:
dev->volume = ctrl->value;
return em28xx_audio_analog_set(dev);
+ default:
+ return -EINVAL;
+ }
+}
+
+/*FIXME: should be moved to saa711x */
+static int saa711x_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
+{
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
return em28xx_brightness_set(dev, ctrl->value);
case V4L2_CID_CONTRAST:
@@ -994,14 +1022,34 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
- u8 i, n;
- n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
- for (i = 0; i < n; i++)
- if (qc->id && qc->id == em28xx_qctrl[i].id) {
- memcpy(qc, &(em28xx_qctrl[i]),
+ int i, id=qc->id;
+
+ memset(qc,0,sizeof(*qc));
+ qc->id=id;
+
+ if (!dev->has_msp34xx) {
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (qc->id && qc->id == em28xx_qctrl[i].id) {
+ memcpy(qc, &(em28xx_qctrl[i]),
+ sizeof(*qc));
+ return 0;
+ }
+ }
+ }
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,qc);
+ if (qc->type)
+ return 0;
+ else
+ return -EINVAL;
+ }
+ for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
+ if (qc->id && qc->id == saa711x_qctrl[i].id) {
+ memcpy(qc, &(saa711x_qctrl[i]),
sizeof(*qc));
return 0;
}
+ }
return -EINVAL;
}
@@ -1009,29 +1057,64 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
+ int retval=-EINVAL;
+ if (!dev->has_msp34xx)
+ retval=em28xx_get_ctrl(dev, ctrl);
+ if (retval==-EINVAL) {
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ }
- return em28xx_get_ctrl(dev, ctrl);
+ return saa711x_get_ctrl(dev, ctrl);
+ } else return retval;
}
- case VIDIOC_S_CTRL_OLD: /* ??? */
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
- u8 i, n;
-
-
- n = sizeof(em28xx_qctrl) / sizeof(em28xx_qctrl[0]);
- for (i = 0; i < n; i++)
- if (ctrl->id == em28xx_qctrl[i].id) {
- if (ctrl->value <
- em28xx_qctrl[i].minimum
- || ctrl->value >
- em28xx_qctrl[i].maximum)
- return -ERANGE;
+ u8 i;
+
+ if (!dev->has_msp34xx){
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (ctrl->id == em28xx_qctrl[i].id) {
+ if (ctrl->value <
+ em28xx_qctrl[i].minimum
+ || ctrl->value >
+ em28xx_qctrl[i].maximum)
+ return -ERANGE;
+ return em28xx_set_ctrl(dev, ctrl);
+ }
+ }
+ }
- return em28xx_set_ctrl(dev, ctrl);
+ if (dev->decoder == EM28XX_TVP5150) {
+ em28xx_i2c_call_clients(dev,cmd,arg);
+ return 0;
+ } else if (!dev->has_msp34xx) {
+ for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) {
+ if (ctrl->id == em28xx_qctrl[i].id) {
+ if (ctrl->value <
+ em28xx_qctrl[i].minimum
+ || ctrl->value >
+ em28xx_qctrl[i].maximum)
+ return -ERANGE;
+ return em28xx_set_ctrl(dev, ctrl);
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE(saa711x_qctrl); i++) {
+ if (ctrl->id == saa711x_qctrl[i].id) {
+ if (ctrl->value <
+ saa711x_qctrl[i].minimum
+ || ctrl->value >
+ saa711x_qctrl[i].maximum)
+ return -ERANGE;
+ return saa711x_set_ctrl(dev, ctrl);
+ }
}
+ }
+
return -EINVAL;
}
@@ -1187,7 +1270,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp,
return -ENODEV;
if (video_debug > 1)
- em28xx_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
@@ -1564,6 +1647,8 @@ static struct file_operations em28xx_v4l_fops = {
.poll = em28xx_v4l2_poll,
.mmap = em28xx_v4l2_mmap,
.llseek = no_llseek,
+ .compat_ioctl = v4l_compat_ioctl32,
+
};
/******************************** usb interface *****************************************/
@@ -1777,12 +1862,11 @@ static int em28xx_usb_probe(struct usb_interface *interface,
}
/* allocate memory for our device state and initialize it */
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
em28xx_err(DRIVER_NAME ": out of memory!\n");
return -ENOMEM;
}
- memset(dev, 0, sizeof(*dev));
/* compute alternate max packet sizes */
uif = udev->actconfig->interface[0];
@@ -1848,9 +1932,12 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
struct em28xx *dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
+/*FIXME: IR should be disconnected */
+
if (!dev)
return;
+
down_write(&em28xx_disconnect);
down(&dev->lock);
@@ -1884,7 +1971,6 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
}
static struct usb_driver em28xx_usb_driver = {
- .owner = THIS_MODULE,
.name = "em28xx",
.probe = em28xx_usb_probe,
.disconnect = em28xx_usb_disconnect,
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 5c7a41ce69f3..33de9d846af5 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -1,5 +1,5 @@
/*
- em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+ em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
Ludovico Cavedon <cavedon@sssup.it>
@@ -216,6 +216,8 @@ struct em28xx {
unsigned int has_msp34xx:1;
unsigned int has_tda9887:1;
+ u32 i2s_speed; /* I2S speed for audio digital stream */
+
enum em28xx_decoder decoder;
int tuner_type; /* type of the tuner */
@@ -293,8 +295,6 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir);
/* Provided by em28xx-core.c */
-void em28xx_print_ioctl(char *name, unsigned int cmd);
-
u32 em28xx_request_buffers(struct em28xx *dev, u32 count);
void em28xx_queue_unusedframes(struct em28xx *dev);
void em28xx_release_buffers(struct em28xx *dev);
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index c9b00eafefde..e7bbeb11553d 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -240,12 +240,11 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
DEB_EE((".\n"));
- hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+ hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_gemini: not enough kernel memory in hexium_attach().\n");
return -ENOMEM;
}
- memset(hexium, 0x0, sizeof(struct hexium));
dev->ext_priv = hexium;
/* enable i2c-port pins */
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 42a9414155c3..0b6c2096ec66 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -224,12 +224,11 @@ static int hexium_probe(struct saa7146_dev *dev)
return -EFAULT;
}
- hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL);
+ hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL);
if (NULL == hexium) {
printk("hexium_orion: hexium_probe: not enough kernel memory.\n");
return -ENOMEM;
}
- memset(hexium, 0x0, sizeof(struct hexium));
/* enable i2c-port pins */
saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26));
diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
index deeef125eb92..7420b79e987a 100644
--- a/drivers/media/video/indycam.c
+++ b/drivers/media/video/indycam.c
@@ -289,18 +289,15 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
printk(KERN_INFO "SGI IndyCam driver version %s\n",
INDYCAM_MODULE_VERSION);
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- camera = kmalloc(sizeof(struct indycam), GFP_KERNEL);
+ camera = kzalloc(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;
@@ -451,10 +448,10 @@ static int indycam_command(struct i2c_client *client, unsigned int cmd,
}
static struct i2c_driver i2c_driver_indycam = {
- .owner = THIS_MODULE,
- .name = "indycam",
+ .driver = {
+ .name = "indycam",
+ },
.id = I2C_DRIVERID_INDYCAM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = indycam_probe,
.detach_client = indycam_detach,
.command = indycam_command,
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 740e543311af..58b0e6982822 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -278,9 +278,10 @@ static int ir_detach(struct i2c_client *client);
static int ir_probe(struct i2c_adapter *adap);
static struct i2c_driver driver = {
- .name = "ir remote kbd driver",
+ .driver = {
+ .name = "ir-kbd-i2c",
+ },
.id = I2C_DRIVERID_INFRARED,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ir_probe,
.detach_client = ir_detach,
};
@@ -303,18 +304,20 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
input_dev = input_allocate_device();
if (!ir || !input_dev) {
- kfree(ir);
input_free_device(input_dev);
+ kfree(ir);
return -ENOMEM;
}
+ memset(ir,0,sizeof(*ir));
ir->c = client_template;
ir->input = input_dev;
- i2c_set_clientdata(&ir->c, ir);
ir->c.adapter = adap;
ir->c.addr = addr;
+ i2c_set_clientdata(&ir->c, ir);
+
switch(addr) {
case 0x64:
name = "Pixelview";
@@ -377,13 +380,15 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
ir->c.dev.bus_id);
/* init + register input device */
- ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
- input_dev->id.bustype = BUS_I2C;
- input_dev->name = ir->c.name;
- input_dev->phys = ir->phys;
+ ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->name = ir->c.name;
+ input_dev->phys = ir->phys;
/* register event device */
input_register_device(ir->input);
+ printk(DEVNAME ": %s detected at %s [%s]\n",
+ ir->input->name,ir->input->phys,adap->name);
/* start polling via eventd */
INIT_WORK(&ir->work, ir_work, ir);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 3f2a882bc20a..2869464aee0d 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1754,6 +1754,7 @@ static struct file_operations meye_fops = {
.release = meye_release,
.mmap = meye_mmap,
.ioctl = meye_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.poll = meye_poll,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
new file mode 100644
index 000000000000..69ed369c2f48
--- /dev/null
+++ b/drivers/media/video/msp3400-driver.c
@@ -0,0 +1,1274 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * what works and what doesn't:
+ *
+ * AM-Mono
+ * Support for Hauppauge cards added (decoding handled by tuner) added by
+ * Frederic Crozat <fcrozat@mail.dotcom.fr>
+ *
+ * FM-Mono
+ * should work. The stereo modes are backward compatible to FM-mono,
+ * therefore FM-Mono should be allways available.
+ *
+ * FM-Stereo (B/G, used in germany)
+ * should work, with autodetect
+ *
+ * FM-Stereo (satellite)
+ * should work, no autodetect (i.e. default is mono, but you can
+ * switch to stereo -- untested)
+ *
+ * NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
+ * should work, with autodetect. Support for NICAM was added by
+ * Pekka Pietikainen <pp@netppl.fi>
+ *
+ * TODO:
+ * - better SAT support
+ *
+ * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * using soundcore instead of OSS
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+#include "msp3400.h"
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+/* module parameters */
+static int opmode = OPMODE_AUTO;
+int msp_debug; /* msp_debug output */
+int msp_once; /* no continous stereo monitoring */
+int msp_amsound; /* hard-wire AM sound at 6.5 Hz (france),
+ the autoscan seems work well only with FM... */
+int msp_standard = 1; /* Override auto detect of audio msp_standard, if needed. */
+int msp_dolby;
+
+int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
+ (msp34xxg only) 0x00a0-0x03c0 */
+
+/* read-only */
+module_param(opmode, int, 0444);
+
+/* read-write */
+module_param_named(once,msp_once, bool, 0644);
+module_param_named(debug,msp_debug, int, 0644);
+module_param_named(stereo_threshold,msp_stereo_thresh, int, 0644);
+module_param_named(standard,msp_standard, int, 0644);
+module_param_named(amsound,msp_amsound, bool, 0644);
+module_param_named(dolby,msp_dolby, bool, 0644);
+
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect");
+MODULE_PARM_DESC(once, "No continuous stereo monitoring");
+MODULE_PARM_DESC(debug, "Enable debug messages [0-3]");
+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");
+
+/* ---------------------------------------------------------------------- */
+
+/* control subaddress */
+#define I2C_MSP_CONTROL 0x00
+/* demodulator unit subaddress */
+#define I2C_MSP_DEM 0x10
+/* DSP unit subaddress */
+#define I2C_MSP_DSP 0x12
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END };
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+/* functions for talking to the MSP3400C Sound processor */
+
+int msp_reset(struct i2c_client *client)
+{
+ /* reset and read revision code */
+ static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 };
+ static u8 reset_on[3] = { I2C_MSP_CONTROL, 0x00, 0x00 };
+ static u8 write[3] = { I2C_MSP_DSP + 1, 0x00, 0x1e };
+ u8 read[2];
+ struct i2c_msg reset[2] = {
+ { client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
+ { client->addr, I2C_M_IGNORE_NAK, 3, reset_on },
+ };
+ struct i2c_msg test[2] = {
+ { client->addr, 0, 3, write },
+ { client->addr, I2C_M_RD, 2, read },
+ };
+
+ v4l_dbg(3, msp_debug, client, "msp_reset\n");
+ if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
+ i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
+ i2c_transfer(client->adapter, test, 2) != 2) {
+ v4l_err(client, "chip reset failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int msp_read(struct i2c_client *client, int dev, int addr)
+{
+ int err, retval;
+ u8 write[3];
+ u8 read[2];
+ struct i2c_msg msgs[2] = {
+ { client->addr, 0, 3, write },
+ { client->addr, I2C_M_RD, 2, read }
+ };
+
+ write[0] = dev + 1;
+ write[1] = addr >> 8;
+ write[2] = addr & 0xff;
+
+ for (err = 0; err < 3; err++) {
+ if (i2c_transfer(client->adapter, msgs, 2) == 2)
+ break;
+ v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
+ dev, addr);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(msecs_to_jiffies(10));
+ }
+ if (err == 3) {
+ v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+ msp_reset(client);
+ return -1;
+ }
+ retval = read[0] << 8 | read[1];
+ v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval);
+ return retval;
+}
+
+int msp_read_dem(struct i2c_client *client, int addr)
+{
+ return msp_read(client, I2C_MSP_DEM, addr);
+}
+
+int msp_read_dsp(struct i2c_client *client, int addr)
+{
+ return msp_read(client, I2C_MSP_DSP, addr);
+}
+
+static int msp_write(struct i2c_client *client, int dev, int addr, int val)
+{
+ int err;
+ u8 buffer[5];
+
+ buffer[0] = dev;
+ buffer[1] = addr >> 8;
+ buffer[2] = addr & 0xff;
+ buffer[3] = val >> 8;
+ buffer[4] = val & 0xff;
+
+ v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val);
+ for (err = 0; err < 3; err++) {
+ if (i2c_master_send(client, buffer, 5) == 5)
+ break;
+ v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
+ dev, addr);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(msecs_to_jiffies(10));
+ }
+ if (err == 3) {
+ v4l_warn(client, "giving up, resetting chip. Sound will go off, sorry folks :-|\n");
+ msp_reset(client);
+ return -1;
+ }
+ return 0;
+}
+
+int msp_write_dem(struct i2c_client *client, int addr, int val)
+{
+ return msp_write(client, I2C_MSP_DEM, addr, val);
+}
+
+int msp_write_dsp(struct i2c_client *client, int addr, int val)
+{
+ return msp_write(client, I2C_MSP_DSP, addr, val);
+}
+
+/* ----------------------------------------------------------------------- *
+ * bits 9 8 5 - SCART DSP input Select:
+ * 0 0 0 - SCART 1 to DSP input (reset position)
+ * 0 1 0 - MONO to DSP input
+ * 1 0 0 - SCART 2 to DSP input
+ * 1 1 1 - Mute DSP input
+ *
+ * bits 11 10 6 - SCART 1 Output Select:
+ * 0 0 0 - undefined (reset position)
+ * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
+ * 1 0 0 - MONO input to SCART 1 Output
+ * 1 1 0 - SCART 1 DA to SCART 1 Output
+ * 0 0 1 - SCART 2 DA to SCART 1 Output
+ * 0 1 1 - SCART 1 Input to SCART 1 Output
+ * 1 1 1 - Mute SCART 1 Output
+ *
+ * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART):
+ * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position)
+ * 0 1 0 - SCART 1 Input to SCART 2 Output
+ * 1 0 0 - MONO input to SCART 2 Output
+ * 0 0 1 - SCART 2 DA to SCART 2 Output
+ * 0 1 1 - SCART 2 Input to SCART 2 Output
+ * 1 1 0 - Mute SCART 2 Output
+ *
+ * Bits 4 to 0 should be zero.
+ * ----------------------------------------------------------------------- */
+
+static int scarts[3][9] = {
+ /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
+ /* SCART DSP Input select */
+ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
+ /* SCART1 Output select */
+ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
+ /* SCART2 Output select */
+ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
+};
+
+static char *scart_names[] = {
+ "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
+};
+
+void msp_set_scart(struct i2c_client *client, int in, int out)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ state->in_scart=in;
+
+ if (in >= 1 && in <= 8 && out >= 0 && out <= 2) {
+ if (-1 == scarts[out][in])
+ return;
+
+ state->acb &= ~scarts[out][SCART_MASK];
+ state->acb |= scarts[out][in];
+ } else
+ state->acb = 0xf60; /* Mute Input and SCART 1 Output */
+
+ v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n",
+ scart_names[in], out, state->acb);
+ msp_write_dsp(client, 0x13, state->acb);
+
+ /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
+ msp_write_dem(client, 0x40, state->i2s_mode);
+}
+
+void msp_set_mute(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ v4l_dbg(1, msp_debug, client, "mute audio\n");
+ msp_write_dsp(client, 0x0000, 0);
+ msp_write_dsp(client, 0x0007, 1);
+ if (state->has_scart2_out_volume)
+ msp_write_dsp(client, 0x0040, 1);
+ if (state->has_headphones)
+ msp_write_dsp(client, 0x0006, 0);
+}
+
+void msp_set_audio(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int bal = 0, bass, treble, loudness;
+ int val = 0;
+
+ if (!state->muted)
+ val = (state->volume * 0x7f / 65535) << 8;
+
+ v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n",
+ state->muted ? "on" : "off", state->volume);
+
+ msp_write_dsp(client, 0x0000, val);
+ msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1));
+ if (state->has_scart2_out_volume)
+ msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1));
+ if (state->has_headphones)
+ msp_write_dsp(client, 0x0006, val);
+ if (!state->has_sound_processing)
+ return;
+
+ if (val)
+ bal = (u8)((state->balance / 256) - 128);
+ bass = ((state->bass - 32768) * 0x60 / 65535) << 8;
+ treble = ((state->treble - 32768) * 0x60 / 65535) << 8;
+ loudness = state->loudness ? ((5 * 4) << 8) : 0;
+
+ v4l_dbg(1, msp_debug, client, "balance=%d bass=%d treble=%d loudness=%d\n",
+ state->balance, state->bass, state->treble, state->loudness);
+
+ msp_write_dsp(client, 0x0001, bal << 8);
+ msp_write_dsp(client, 0x0002, bass);
+ msp_write_dsp(client, 0x0003, treble);
+ msp_write_dsp(client, 0x0004, loudness);
+ if (!state->has_headphones)
+ return;
+ msp_write_dsp(client, 0x0030, bal << 8);
+ msp_write_dsp(client, 0x0031, bass);
+ msp_write_dsp(client, 0x0032, treble);
+ msp_write_dsp(client, 0x0033, loudness);
+}
+
+int msp_modus(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (state->radio) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to Radio\n");
+ return 0x0003;
+ }
+
+ if (state->v4l2_std & V4L2_STD_PAL) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to PAL\n");
+
+#if 1
+ /* experimental: not sure this works with all chip versions */
+ return 0x7003;
+#else
+ /* previous value, try this if it breaks ... */
+ return 0x1003;
+#endif
+ }
+ if (state->v4l2_std & V4L2_STD_NTSC) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to NTSC\n");
+ return 0x2003;
+ }
+ if (state->v4l2_std & V4L2_STD_SECAM) {
+ v4l_dbg(1, msp_debug, client, "video mode selected to SECAM\n");
+ return 0x0003;
+ }
+ return 0x0003;
+}
+
+/* ------------------------------------------------------------------------ */
+
+
+static void msp_wake_thread(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (NULL == state->kthread)
+ return;
+ msp_set_mute(client);
+ state->watch_stereo = 0;
+ state->restart = 1;
+ wake_up_interruptible(&state->wq);
+}
+
+int msp_sleep(struct msp_state *state, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ add_wait_queue(&state->wq, &wait);
+ if (!kthread_should_stop()) {
+ if (timeout < 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ } else {
+ schedule_timeout_interruptible
+ (msecs_to_jiffies(timeout));
+ }
+ }
+
+ remove_wait_queue(&state->wq, &wait);
+ try_to_freeze();
+ return state->restart;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int msp_mode_v4l2_to_v4l1(int rxsubchans)
+{
+ int mode = 0;
+
+ if (rxsubchans & V4L2_TUNER_SUB_STEREO)
+ mode |= VIDEO_SOUND_STEREO;
+ if (rxsubchans & V4L2_TUNER_SUB_LANG2)
+ mode |= VIDEO_SOUND_LANG2;
+ if (rxsubchans & V4L2_TUNER_SUB_LANG1)
+ mode |= VIDEO_SOUND_LANG1;
+ if (mode == 0)
+ mode |= VIDEO_SOUND_MONO;
+ return mode;
+}
+
+static int msp_mode_v4l1_to_v4l2(int mode)
+{
+ if (mode & VIDEO_SOUND_STEREO)
+ return V4L2_TUNER_MODE_STEREO;
+ if (mode & VIDEO_SOUND_LANG2)
+ return V4L2_TUNER_MODE_LANG2;
+ if (mode & VIDEO_SOUND_LANG1)
+ return V4L2_TUNER_MODE_LANG1;
+ return V4L2_TUNER_MODE_MONO;
+}
+
+static void msp_any_detect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ case OPMODE_AUTODETECT:
+ autodetect_stereo(client);
+ break;
+ case OPMODE_AUTOSELECT:
+ msp34xxg_detect_stereo(client);
+ break;
+ }
+}
+
+static struct v4l2_queryctrl msp_qctrl_std[] = {
+ {
+ .id = V4L2_CID_AUDIO_VOLUME,
+ .name = "Volume",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 58880,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+
+static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
+ {
+ .id = V4L2_CID_AUDIO_BALANCE,
+ .name = "Balance",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_BASS,
+ .name = "Bass",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_TREBLE,
+ .name = "Treble",
+ .minimum = 0,
+ .maximum = 65535,
+ .step = 65535/100,
+ .default_value = 32768,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ },{
+ .id = V4L2_CID_AUDIO_LOUDNESS,
+ .name = "Loudness",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 1,
+ .flags = 0,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ },
+};
+
+
+static void msp_any_set_audmode(struct i2c_client *client, int audmode)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ case OPMODE_AUTODETECT:
+ state->watch_stereo = 0;
+ msp3400c_setstereo(client, audmode);
+ break;
+ case OPMODE_AUTOSELECT:
+ msp34xxg_set_audmode(client, audmode);
+ break;
+ }
+}
+
+static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ ctrl->value = state->volume;
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ ctrl->value = state->muted;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->balance;
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->bass;
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->treble;
+ break;
+
+ case V4L2_CID_AUDIO_LOUDNESS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ ctrl->value = state->loudness;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msp_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_VOLUME:
+ state->volume = ctrl->value;
+ if (state->volume == 0)
+ state->balance = 32768;
+ break;
+
+ case V4L2_CID_AUDIO_MUTE:
+ if (ctrl->value < 0 || ctrl->value >= 2)
+ return -ERANGE;
+ state->muted = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BASS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->bass = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_TREBLE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->treble = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_LOUDNESS:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->loudness = ctrl->value;
+ break;
+
+ case V4L2_CID_AUDIO_BALANCE:
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ state->balance = ctrl->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ msp_set_audio(client);
+ return 0;
+}
+
+static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ u16 *sarg = arg;
+ int scart = 0;
+
+ if (msp_debug >= 2)
+ v4l_i2c_print_ioctl(client, cmd);
+
+ switch (cmd) {
+ case AUDC_SET_INPUT:
+ if (*sarg == state->input)
+ break;
+ state->input = *sarg;
+ switch (*sarg) {
+ case AUDIO_RADIO:
+ /* Hauppauge uses IN2 for the radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_EXTERN_1:
+ /* IN1 is often used for external input ... */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN1;
+ break;
+ case AUDIO_EXTERN_2:
+ /* ... sometimes it is IN2 through ;) */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_TUNER:
+ state->mode = -1;
+ break;
+ default:
+ if (*sarg & AUDIO_MUTE)
+ msp_set_scart(client, SCART_MUTE, 0);
+ break;
+ }
+ if (scart) {
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ msp_set_scart(client, scart, 0);
+ msp_write_dsp(client, 0x000d, 0x1900);
+ if (state->opmode != OPMODE_AUTOSELECT)
+ msp3400c_setstereo(client, state->audmode);
+ }
+ msp_wake_thread(client);
+ break;
+
+ case AUDC_SET_RADIO:
+ if (state->radio)
+ return 0;
+ state->radio = 1;
+ v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
+ state->watch_stereo = 0;
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ /* set msp3400 to FM radio mode */
+ msp3400c_setmode(client, MSP_MODE_FM_RADIO);
+ msp3400c_setcarrier(client, MSP_CARRIER(10.7),
+ MSP_CARRIER(10.7));
+ msp_set_audio(client);
+ break;
+ case OPMODE_AUTODETECT:
+ case OPMODE_AUTOSELECT:
+ /* the thread will do for us */
+ msp_wake_thread(client);
+ break;
+ }
+ break;
+
+ /* --- v4l ioctls --- */
+ /* take care: bttv does userspace copying, we'll get a
+ kernel pointer here... */
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio *va = arg;
+
+ va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_MUTABLE;
+ if (state->has_sound_processing)
+ va->flags |= VIDEO_AUDIO_BALANCE |
+ VIDEO_AUDIO_BASS |
+ VIDEO_AUDIO_TREBLE;
+ if (state->muted)
+ va->flags |= VIDEO_AUDIO_MUTE;
+ va->volume = state->volume;
+ va->balance = state->volume ? state->balance : 32768;
+ va->bass = state->bass;
+ va->treble = state->treble;
+
+ if (state->radio)
+ break;
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans);
+ break;
+ }
+
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio *va = arg;
+
+ state->muted = (va->flags & VIDEO_AUDIO_MUTE);
+ state->volume = va->volume;
+ state->balance = va->balance;
+ state->bass = va->bass;
+ state->treble = va->treble;
+ msp_set_audio(client);
+
+ if (va->mode != 0 && state->radio == 0)
+ msp_any_set_audmode(client, msp_mode_v4l1_to_v4l2(va->mode));
+ break;
+ }
+
+ case VIDIOCSCHAN:
+ {
+ struct video_channel *vc = arg;
+ int update = 0;
+ v4l2_std_id std;
+
+ if (state->radio)
+ update = 1;
+ state->radio = 0;
+ if (vc->norm == VIDEO_MODE_PAL)
+ std = V4L2_STD_PAL;
+ else if (vc->norm == VIDEO_MODE_SECAM)
+ std = V4L2_STD_SECAM;
+ else
+ std = V4L2_STD_NTSC;
+ if (std != state->v4l2_std) {
+ state->v4l2_std = std;
+ update = 1;
+ }
+ if (update)
+ msp_wake_thread(client);
+ break;
+ }
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_FREQUENCY:
+ {
+ /* new channel -- kick audio carrier scan */
+ msp_wake_thread(client);
+ break;
+ }
+
+ /* msp34xx specific */
+ case MSP_SET_MATRIX:
+ {
+ struct msp_matrix *mspm = arg;
+
+ msp_set_scart(client, mspm->input, mspm->output);
+ break;
+ }
+
+ /* --- v4l2 ioctls --- */
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *id = arg;
+ int update = state->radio || state->v4l2_std != *id;
+
+ state->v4l2_std = *id;
+ state->radio = 0;
+ if (update)
+ msp_wake_thread(client);
+ return 0;
+ }
+
+ case VIDIOC_ENUMINPUT:
+ {
+ struct v4l2_input *i = arg;
+
+ if (i->index != 0)
+ return -EINVAL;
+
+ i->type = V4L2_INPUT_TYPE_TUNER;
+ switch (i->index) {
+ case AUDIO_RADIO:
+ strcpy(i->name, "Radio");
+ break;
+ case AUDIO_EXTERN_1:
+ strcpy(i->name, "Extern 1");
+ break;
+ case AUDIO_EXTERN_2:
+ strcpy(i->name, "Extern 2");
+ break;
+ case AUDIO_TUNER:
+ strcpy(i->name, "Television");
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *a = arg;
+
+ memset(a, 0, sizeof(*a));
+
+ switch (a->index) {
+ case AUDIO_RADIO:
+ strcpy(a->name, "Radio");
+ break;
+ case AUDIO_EXTERN_1:
+ strcpy(a->name, "Extern 1");
+ break;
+ case AUDIO_EXTERN_2:
+ strcpy(a->name, "Extern 2");
+ break;
+ case AUDIO_TUNER:
+ strcpy(a->name, "Television");
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ msp_any_detect_stereo(client);
+ if (state->audmode == V4L2_TUNER_MODE_STEREO) {
+ a->capability = V4L2_AUDCAP_STEREO;
+ }
+
+ break;
+ }
+
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *sarg = arg;
+
+ switch (sarg->index) {
+ case AUDIO_RADIO:
+ /* Hauppauge uses IN2 for the radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_EXTERN_1:
+ /* IN1 is often used for external input ... */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN1;
+ break;
+ case AUDIO_EXTERN_2:
+ /* ... sometimes it is IN2 through ;) */
+ state->mode = MSP_MODE_EXTERN;
+ scart = SCART_IN2;
+ break;
+ case AUDIO_TUNER:
+ state->mode = -1;
+ break;
+ }
+ if (scart) {
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ msp_set_scart(client, scart, 0);
+ msp_write_dsp(client, 0x000d, 0x1900);
+ }
+ if (sarg->capability == V4L2_AUDCAP_STEREO) {
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ } else {
+ state->audmode &= ~V4L2_TUNER_MODE_STEREO;
+ }
+ msp_any_set_audmode(client, state->audmode);
+ msp_wake_thread(client);
+ break;
+ }
+
+ case VIDIOC_G_TUNER:
+ {
+ struct v4l2_tuner *vt = arg;
+
+ if (state->radio)
+ break;
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ vt->audmode = state->audmode;
+ vt->rxsubchans = state->rxsubchans;
+ vt->capability = V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+ break;
+ }
+
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+
+ if (state->radio)
+ break;
+ /* only set audmode */
+ if (vt->audmode != -1 && vt->audmode != 0)
+ msp_any_set_audmode(client, vt->audmode);
+ break;
+ }
+
+ case VIDIOC_G_AUDOUT:
+ {
+ struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
+ int idx = a->index;
+
+ memset(a, 0, sizeof(*a));
+
+ switch (idx) {
+ case 0:
+ strcpy(a->name, "Scart1 Out");
+ break;
+ case 1:
+ strcpy(a->name, "Scart2 Out");
+ break;
+ case 2:
+ strcpy(a->name, "I2S Out");
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+
+ }
+
+ case VIDIOC_S_AUDOUT:
+ {
+ struct v4l2_audioout *a = (struct v4l2_audioout *)arg;
+
+ if (a->index < 0 || a->index > 2)
+ return -EINVAL;
+
+ v4l_dbg(1, msp_debug, client, "Setting audio out on msp34xx to input %i\n", a->index);
+ msp_set_scart(client, state->in_scart, a->index + 1);
+
+ break;
+ }
+
+ case VIDIOC_INT_I2S_CLOCK_FREQ:
+ {
+ u32 *a = (u32 *)arg;
+
+ v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", *a);
+
+ switch (*a) {
+ case 1024000:
+ state->i2s_mode = 0;
+ break;
+ case 2048000:
+ state->i2s_mode = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
+ if (qc->id && qc->id == msp_qctrl_std[i].id) {
+ memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
+ return 0;
+ }
+ if (!state->has_sound_processing)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
+ if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
+ memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
+ case VIDIOC_G_CTRL:
+ return msp_get_ctrl(client, arg);
+
+ case VIDIOC_S_CTRL:
+ return msp_set_ctrl(client, arg);
+
+ case VIDIOC_LOG_STATUS:
+ {
+ const char *p;
+
+ if (state->opmode == OPMODE_AUTOSELECT)
+ msp_any_detect_stereo(client);
+ v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
+ client->name, state->rev1, state->rev2);
+ v4l_info(client, "Audio: volume %d%s\n",
+ state->volume, state->muted ? " (muted)" : "");
+ if (state->has_sound_processing) {
+ v4l_info(client, "Audio: balance %d bass %d treble %d loudness %s\n",
+ state->balance, state->bass, state->treble,
+ state->loudness ? "on" : "off");
+ }
+ switch (state->mode) {
+ case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
+ case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
+ case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono + FM-stereo"; break;
+ case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
+ case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
+ case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
+ case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break;
+ case MSP_MODE_BTSC: p = "BTSC"; break;
+ case MSP_MODE_EXTERN: p = "External input"; break;
+ default: p = "unknown"; break;
+ }
+ if (state->opmode == OPMODE_MANUAL) {
+ v4l_info(client, "Mode: %s (%s%s)\n", p,
+ (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+ (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+ } else {
+ v4l_info(client, "Mode: %s\n", p);
+ v4l_info(client, "Standard: %s (%s%s)\n",
+ msp_standard_std_name(state->std),
+ (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+ (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+ }
+ v4l_info(client, "ACB: 0x%04x\n", state->acb);
+ break;
+ }
+
+ default:
+ /* unknown */
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msp_suspend(struct device * dev, pm_message_t state)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ v4l_dbg(1, msp_debug, client, "suspend\n");
+ msp_reset(client);
+ return 0;
+}
+
+static int msp_resume(struct device * dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+ v4l_dbg(1, msp_debug, client, "resume\n");
+ msp_wake_thread(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver i2c_driver;
+
+static int msp_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct msp_state *state;
+ int (*thread_func)(void *data) = NULL;
+ int msp_hard;
+ int msp_family;
+ int msp_revision;
+ int msp_product, msp_prod_hi, msp_prod_lo;
+ int msp_rom;
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memset(client, 0, sizeof(*client));
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &i2c_driver;
+ snprintf(client->name, sizeof(client->name) - 1, "msp3400");
+
+ if (msp_reset(client) == -1) {
+ v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
+ kfree(client);
+ return -1;
+ }
+
+ state = kmalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(client, state);
+
+ memset(state, 0, sizeof(*state));
+ state->v4l2_std = V4L2_STD_NTSC;
+ state->volume = 58880; /* 0db gain */
+ state->balance = 32768; /* 0db gain */
+ state->bass = 32768;
+ state->treble = 32768;
+ state->loudness = 0;
+ state->input = -1;
+ state->muted = 0;
+ state->i2s_mode = 0;
+ init_waitqueue_head(&state->wq);
+
+ state->rev1 = msp_read_dsp(client, 0x1e);
+ if (state->rev1 != -1)
+ state->rev2 = msp_read_dsp(client, 0x1f);
+ v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n", state->rev1, state->rev2);
+ if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
+ v4l_dbg(1, msp_debug, client, "not an msp3400 (cannot read chip version)\n");
+ kfree(state);
+ kfree(client);
+ return -1;
+ }
+
+ msp_set_audio(client);
+
+ msp_family = ((state->rev1 >> 4) & 0x0f) + 3;
+ msp_product = (state->rev2 >> 8) & 0xff;
+ msp_prod_hi = msp_product / 10;
+ msp_prod_lo = msp_product % 10;
+ msp_revision = (state->rev1 & 0x0f) + '@';
+ msp_hard = ((state->rev1 >> 8) & 0xff) + '@';
+ msp_rom = state->rev2 & 0x1f;
+ snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d",
+ msp_family, msp_product,
+ msp_revision, msp_hard, msp_rom);
+
+ /* Has NICAM support: all mspx41x and mspx45x products have NICAM */
+ state->has_nicam = msp_prod_hi == 1 || msp_prod_hi == 5;
+ /* Has radio support: was added with revision G */
+ state->has_radio = msp_revision >= 'G';
+ /* Has headphones output: not for stripped down products */
+ state->has_headphones = msp_prod_lo < 5;
+ /* Has scart4 input: not in pre D revisions, not in stripped D revs */
+ state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
+ /* Has scart2 and scart3 inputs and scart2 output: not in stripped
+ down products of the '3' family */
+ state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5;
+ /* Has scart2 a volume control? Not in pre-D revisions. */
+ state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out;
+ /* Has a configurable i2s out? */
+ state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7;
+ /* Has subwoofer output: not in pre-D revs and not in stripped down products */
+ state->has_subwoofer = msp_revision >= 'D' && msp_prod_lo < 5;
+ /* Has soundprocessing (bass/treble/balance/loudness/equalizer): not in
+ stripped down products */
+ state->has_sound_processing = msp_prod_lo < 7;
+ /* Has Virtual Dolby Surround: only in msp34x1 */
+ state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1;
+ /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */
+ state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2;
+
+ state->opmode = opmode;
+ if (state->opmode == OPMODE_AUTO) {
+ /* MSP revision G and up have both autodetect and autoselect */
+ if (msp_revision >= 'G')
+ state->opmode = OPMODE_AUTOSELECT;
+ /* MSP revision D and up have autodetect */
+ else if (msp_revision >= 'D')
+ state->opmode = OPMODE_AUTODETECT;
+ else
+ state->opmode = OPMODE_MANUAL;
+ }
+
+ /* hello world :-) */
+ v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, address << 1, adapter->name);
+ v4l_info(client, "%s ", client->name);
+ if (state->has_nicam && state->has_radio)
+ printk("supports nicam and radio, ");
+ else if (state->has_nicam)
+ printk("supports nicam, ");
+ else if (state->has_radio)
+ printk("supports radio, ");
+ printk("mode is ");
+
+ /* version-specific initialization */
+ switch (state->opmode) {
+ case OPMODE_MANUAL:
+ printk("manual");
+ thread_func = msp3400c_thread;
+ break;
+ case OPMODE_AUTODETECT:
+ printk("autodetect");
+ thread_func = msp3410d_thread;
+ break;
+ case OPMODE_AUTOSELECT:
+ printk("autodetect and autoselect");
+ thread_func = msp34xxg_thread;
+ break;
+ }
+ printk("\n");
+
+ /* startup control thread if needed */
+ if (thread_func) {
+ state->kthread = kthread_run(thread_func, client, "msp34xx");
+
+ if (state->kthread == NULL)
+ v4l_warn(client, "kernel_thread() failed\n");
+ msp_wake_thread(client);
+ }
+
+ /* done */
+ i2c_attach_client(client);
+
+ return 0;
+}
+
+static int msp_probe(struct i2c_adapter *adapter)
+{
+ if (adapter->class & I2C_CLASS_TV_ANALOG)
+ return i2c_probe(adapter, &addr_data, msp_attach);
+ return 0;
+}
+
+static int msp_detach(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int err;
+
+ /* shutdown control thread */
+ if (state->kthread) {
+ state->restart = 1;
+ kthread_stop(state->kthread);
+ }
+ msp_reset(client);
+
+ err = i2c_detach_client(client);
+ if (err) {
+ return err;
+ }
+
+ kfree(state);
+ kfree(client);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+ .id = I2C_DRIVERID_MSP3400,
+ .attach_adapter = msp_probe,
+ .detach_client = msp_detach,
+ .command = msp_command,
+ .driver = {
+ .name = "msp3400",
+ .suspend = msp_suspend,
+ .resume = msp_resume,
+ },
+};
+
+static int __init msp3400_init_module(void)
+{
+ return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit msp3400_cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver);
+}
+
+module_init(msp3400_init_module);
+module_exit(msp3400_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/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
new file mode 100644
index 000000000000..2072c3efebb3
--- /dev/null
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -0,0 +1,1010 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+#include "msp3400.h"
+
+/* this one uses the automatic sound standard detection of newer msp34xx
+ chip versions */
+static struct {
+ int retval;
+ int main, second;
+ char *name;
+} msp_stdlist[] = {
+ { 0x0000, 0, 0, "could not detect sound standard" },
+ { 0x0001, 0, 0, "autodetect start" },
+ { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" },
+ { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" },
+ { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
+ { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
+ { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
+ { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
+ { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
+ { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
+ { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
+ { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
+ { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
+ { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
+ { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
+ { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" },
+ { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" },
+ { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" },
+ { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" },
+ { -1, 0, 0, NULL }, /* EOF */
+};
+
+static struct msp3400c_init_data_dem {
+ int fir1[6];
+ int fir2[6];
+ int cdo1;
+ int cdo2;
+ int ad_cv;
+ int mode_reg;
+ int dsp_src;
+ int dsp_matrix;
+} msp3400c_init_data[] = {
+ { /* AM (for carrier detect / msp3400) */
+ {75, 19, 36, 35, 39, 40},
+ {75, 19, 36, 35, 39, 40},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0500, 0x0020, 0x3000
+ },{ /* AM (for carrier detect / msp3410) */
+ {-1, -1, -8, 2, 59, 126},
+ {-1, -1, -8, 2, 59, 126},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0100, 0x0020, 0x3000
+ },{ /* FM Radio */
+ {-8, -8, 4, 6, 78, 107},
+ {-8, -8, 4, 6, 78, 107},
+ MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+ 0x00d0, 0x0480, 0x0020, 0x3000
+ },{ /* Terrestial FM-mono + FM-stereo */
+ {3, 18, 27, 48, 66, 72},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0480, 0x0030, 0x3000
+ },{ /* Sat FM-mono */
+ { 1, 9, 14, 24, 33, 37},
+ { 3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ 0x00c6, 0x0480, 0x0000, 0x3000
+ },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */
+ {-2, -8, -10, 10, 50, 86},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ 0x00d0, 0x0040, 0x0120, 0x3000
+ },{ /* NICAM/FM -- I (6.0/6.552) */
+ {2, 4, -6, -4, 40, 94},
+ {3, 18, 27, 48, 66, 72},
+ MSP_CARRIER(6.0), MSP_CARRIER(6.0),
+ 0x00d0, 0x0040, 0x0120, 0x3000
+ },{ /* NICAM/AM -- L (6.5/5.85) */
+ {-2, -8, -10, 10, 50, 86},
+ {-4, -12, -9, 23, 79, 126},
+ MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+ 0x00c6, 0x0140, 0x0120, 0x7c03
+ },
+};
+
+struct msp3400c_carrier_detect {
+ int cdo;
+ char *name;
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = {
+ /* main carrier */
+ { MSP_CARRIER(4.5), "4.5 NTSC" },
+ { MSP_CARRIER(5.5), "5.5 PAL B/G" },
+ { MSP_CARRIER(6.0), "6.0 PAL I" },
+ { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = {
+ /* PAL B/G */
+ { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
+ { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = {
+ /* PAL SAT / SECAM */
+ { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
+ { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
+ { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
+ { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
+ { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
+ { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
+};
+
+/* ------------------------------------------------------------------------ */
+
+const char *msp_standard_std_name(int std)
+{
+ int i;
+
+ for (i = 0; msp_stdlist[i].name != NULL; i++)
+ if (msp_stdlist[i].retval == std)
+ return msp_stdlist[i].name;
+ return "unknown";
+}
+
+void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2)
+{
+ msp_write_dem(client, 0x0093, cdo1 & 0xfff);
+ msp_write_dem(client, 0x009b, cdo1 >> 12);
+ msp_write_dem(client, 0x00a3, cdo2 & 0xfff);
+ msp_write_dem(client, 0x00ab, cdo2 >> 12);
+ msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/
+}
+
+void msp3400c_setmode(struct i2c_client *client, int type)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int i;
+
+ v4l_dbg(1, msp_debug, client, "setmode: %d\n", type);
+ state->mode = type;
+ state->audmode = V4L2_TUNER_MODE_MONO;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+ msp_write_dem(client, 0x00bb, msp3400c_init_data[type].ad_cv);
+
+ for (i = 5; i >= 0; i--) /* fir 1 */
+ msp_write_dem(client, 0x0001, msp3400c_init_data[type].fir1[i]);
+
+ msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */
+ msp_write_dem(client, 0x0005, 0x0040);
+ msp_write_dem(client, 0x0005, 0x0000);
+ for (i = 5; i >= 0; i--)
+ msp_write_dem(client, 0x0005, msp3400c_init_data[type].fir2[i]);
+
+ msp_write_dem(client, 0x0083, msp3400c_init_data[type].mode_reg);
+
+ msp3400c_setcarrier(client, msp3400c_init_data[type].cdo1,
+ msp3400c_init_data[type].cdo2);
+
+ msp_write_dem(client, 0x0056, 0); /*LOAD_REG_1/2*/
+
+ if (msp_dolby) {
+ msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */
+ msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */
+ msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src);
+ } else {
+ msp_write_dsp(client, 0x0008, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x0009, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x000b, msp3400c_init_data[type].dsp_src);
+ }
+ msp_write_dsp(client, 0x000a, msp3400c_init_data[type].dsp_src);
+ msp_write_dsp(client, 0x000e, msp3400c_init_data[type].dsp_matrix);
+
+ if (state->has_nicam) {
+ /* nicam prescale */
+ msp_write_dsp(client, 0x0010, 0x5a00); /* was: 0x3000 */
+ }
+}
+
+/* turn on/off nicam + stereo */
+void msp3400c_setstereo(struct i2c_client *client, int mode)
+{
+ static char *strmode[] = { "mono", "stereo", "lang2", "lang1" };
+ struct msp_state *state = i2c_get_clientdata(client);
+ int nicam = 0; /* channel source: FM/AM or nicam */
+ int src = 0;
+
+ if (state->opmode == OPMODE_AUTOSELECT) {
+ /* this method would break everything, let's make sure
+ * it's never called
+ */
+ v4l_dbg(1, msp_debug, client, "setstereo called with mode=%d instead of set_source (ignored)\n",
+ mode);
+ return;
+ }
+
+ /* switch demodulator */
+ switch (state->mode) {
+ case MSP_MODE_FM_TERRA:
+ v4l_dbg(1, msp_debug, client, "FM setstereo: %s\n", strmode[mode]);
+ msp3400c_setcarrier(client, state->second, state->main);
+ switch (mode) {
+ case V4L2_TUNER_MODE_STEREO:
+ msp_write_dsp(client, 0x000e, 0x3001);
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ msp_write_dsp(client, 0x000e, 0x3000);
+ break;
+ }
+ break;
+ case MSP_MODE_FM_SAT:
+ v4l_dbg(1, msp_debug, client, "SAT setstereo: %s\n", strmode[mode]);
+ switch (mode) {
+ case V4L2_TUNER_MODE_MONO:
+ msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+ break;
+ }
+ break;
+ case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
+ case MSP_MODE_AM_NICAM:
+ v4l_dbg(1, msp_debug, client, "NICAM setstereo: %s\n",strmode[mode]);
+ msp3400c_setcarrier(client,state->second,state->main);
+ if (state->nicam_on)
+ nicam=0x0100;
+ break;
+ case MSP_MODE_BTSC:
+ v4l_dbg(1, msp_debug, client, "BTSC setstereo: %s\n",strmode[mode]);
+ nicam=0x0300;
+ break;
+ case MSP_MODE_EXTERN:
+ v4l_dbg(1, msp_debug, client, "extern setstereo: %s\n",strmode[mode]);
+ nicam = 0x0200;
+ break;
+ case MSP_MODE_FM_RADIO:
+ v4l_dbg(1, msp_debug, client, "FM-Radio setstereo: %s\n",strmode[mode]);
+ break;
+ default:
+ v4l_dbg(1, msp_debug, client, "mono setstereo\n");
+ return;
+ }
+
+ /* switch audio */
+ switch (mode) {
+ case V4L2_TUNER_MODE_STEREO:
+ src = 0x0020 | nicam;
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ if (state->mode == MSP_MODE_AM_NICAM) {
+ v4l_dbg(1, msp_debug, client, "switching to AM mono\n");
+ /* AM mono decoding is handled by tuner, not MSP chip */
+ /* SCART switching control register */
+ msp_set_scart(client, SCART_MONO, 0);
+ src = 0x0200;
+ break;
+ }
+ case V4L2_TUNER_MODE_LANG1:
+ src = 0x0000 | nicam;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ src = 0x0010 | nicam;
+ break;
+ }
+ v4l_dbg(1, msp_debug, client, "setstereo final source/matrix = 0x%x\n", src);
+
+ if (msp_dolby) {
+ msp_write_dsp(client, 0x0008, 0x0520);
+ msp_write_dsp(client, 0x0009, 0x0620);
+ msp_write_dsp(client, 0x000a, src);
+ msp_write_dsp(client, 0x000b, src);
+ } else {
+ msp_write_dsp(client, 0x0008, src);
+ msp_write_dsp(client, 0x0009, src);
+ msp_write_dsp(client, 0x000a, src);
+ msp_write_dsp(client, 0x000b, src);
+ msp_write_dsp(client, 0x000c, src);
+ if (state->has_scart23_in_scart2_out)
+ msp_write_dsp(client, 0x0041, src);
+ }
+}
+
+static void msp3400c_print_mode(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (state->main == state->second) {
+ v4l_dbg(1, msp_debug, client, "mono sound carrier: %d.%03d MHz\n",
+ state->main / 910000, (state->main / 910) % 1000);
+ } else {
+ v4l_dbg(1, msp_debug, client, "main sound carrier: %d.%03d MHz\n",
+ state->main / 910000, (state->main / 910) % 1000);
+ }
+ if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
+ v4l_dbg(1, msp_debug, client, "NICAM/FM carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second/910) % 1000);
+ if (state->mode == MSP_MODE_AM_NICAM)
+ v4l_dbg(1, msp_debug, client, "NICAM/AM carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second / 910) % 1000);
+ if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
+ v4l_dbg(1, msp_debug, client, "FM-stereo carrier : %d.%03d MHz\n",
+ state->second / 910000, (state->second / 910) % 1000);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+int autodetect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val;
+ int rxsubchans = state->rxsubchans;
+ int newnicam = state->nicam_on;
+ int update = 0;
+
+ switch (state->mode) {
+ case MSP_MODE_FM_TERRA:
+ val = msp_read_dsp(client, 0x18);
+ if (val > 32767)
+ val -= 65536;
+ v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val);
+ if (val > 4096) {
+ rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+ } else if (val < -4096) {
+ rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ } else {
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+ newnicam = 0;
+ break;
+ case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
+ case MSP_MODE_AM_NICAM:
+ val = msp_read_dem(client, 0x23);
+ v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n",
+ val & 1, (val & 0x1e) >> 1);
+
+ if (val & 1) {
+ /* nicam synced */
+ switch ((val & 0x1e) >> 1) {
+ case 0:
+ case 8:
+ rxsubchans = V4L2_TUNER_SUB_STEREO;
+ break;
+ case 1:
+ case 9:
+ rxsubchans = V4L2_TUNER_SUB_MONO
+ | V4L2_TUNER_SUB_LANG1;
+ break;
+ case 2:
+ case 10:
+ rxsubchans = V4L2_TUNER_SUB_MONO
+ | V4L2_TUNER_SUB_LANG1
+ | V4L2_TUNER_SUB_LANG2;
+ break;
+ default:
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ break;
+ }
+ newnicam = 1;
+ } else {
+ newnicam = 0;
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ }
+ break;
+ case MSP_MODE_BTSC:
+ val = msp_read_dem(client, 0x200);
+ v4l_dbg(2, msp_debug, client, "status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
+ val,
+ (val & 0x0002) ? "no" : "yes",
+ (val & 0x0004) ? "no" : "yes",
+ (val & 0x0040) ? "stereo" : "mono",
+ (val & 0x0080) ? ", nicam 2nd mono" : "",
+ (val & 0x0100) ? ", bilingual/SAP" : "");
+ rxsubchans = V4L2_TUNER_SUB_MONO;
+ if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1;
+ break;
+ }
+ if (rxsubchans != state->rxsubchans) {
+ update = 1;
+ v4l_dbg(1, msp_debug, client, "watch: rxsubchans %d => %d\n",
+ state->rxsubchans,rxsubchans);
+ state->rxsubchans = rxsubchans;
+ }
+ if (newnicam != state->nicam_on) {
+ update = 1;
+ v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n",
+ state->nicam_on,newnicam);
+ state->nicam_on = newnicam;
+ }
+ return update;
+}
+
+/*
+ * A kernel thread for msp3400 control -- we don't want to block the
+ * in the ioctl while doing the sound carrier & stereo detect
+ */
+/* stereo/multilang monitoring */
+static void watch_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ if (autodetect_stereo(client)) {
+ if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO);
+ else if (state->rxsubchans & V4L2_TUNER_SUB_LANG1)
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1);
+ else
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ }
+
+ if (msp_once)
+ state->watch_stereo = 0;
+}
+
+int msp3400c_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ struct msp3400c_carrier_detect *cd;
+ int count, max1,max2,val1,val2, val,this;
+
+
+ v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
+ msp_sleep(state, -1);
+ v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ if (state->radio || MSP_MODE_EXTERN == state->mode) {
+ /* no carrier scan, just unmute */
+ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ msp_set_audio(client);
+ continue;
+ }
+
+ /* mute */
+ msp_set_mute(client);
+ msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
+ val1 = val2 = 0;
+ max1 = max2 = -1;
+ state->watch_stereo = 0;
+
+ /* some time for the tuner to sync */
+ if (msp_sleep(state,200))
+ goto restart;
+
+ /* carrier detect pass #1 -- main carrier */
+ cd = msp3400c_carrier_detect_main;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_main);
+
+ if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ max1 = 3;
+ count = 0;
+ v4l_dbg(1, msp_debug, client, "AM sound override\n");
+ }
+
+ for (this = 0; this < count; this++) {
+ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
+ if (msp_sleep(state,100))
+ goto restart;
+ val = msp_read_dsp(client, 0x1b);
+ if (val > 32767)
+ val -= 65536;
+ if (val1 < val)
+ val1 = val, max1 = this;
+ v4l_dbg(1, msp_debug, client, "carrier1 val: %5d / %s\n", val,cd[this].name);
+ }
+
+ /* carrier detect pass #2 -- second (stereo) carrier */
+ switch (max1) {
+ case 1: /* 5.5 */
+ cd = msp3400c_carrier_detect_55;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_55);
+ break;
+ case 3: /* 6.5 */
+ cd = msp3400c_carrier_detect_65;
+ count = ARRAY_SIZE(msp3400c_carrier_detect_65);
+ break;
+ case 0: /* 4.5 */
+ case 2: /* 6.0 */
+ default:
+ cd = NULL;
+ count = 0;
+ break;
+ }
+
+ if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* autodetect doesn't work well with AM ... */
+ cd = NULL;
+ count = 0;
+ max2 = 0;
+ }
+ for (this = 0; this < count; this++) {
+ msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
+ if (msp_sleep(state,100))
+ goto restart;
+ val = msp_read_dsp(client, 0x1b);
+ if (val > 32767)
+ val -= 65536;
+ if (val2 < val)
+ val2 = val, max2 = this;
+ v4l_dbg(1, msp_debug, client, "carrier2 val: %5d / %s\n", val,cd[this].name);
+ }
+
+ /* program the msp3400 according to the results */
+ state->main = msp3400c_carrier_detect_main[max1].cdo;
+ switch (max1) {
+ case 1: /* 5.5 */
+ if (max2 == 0) {
+ /* B/G FM-stereo */
+ state->second = msp3400c_carrier_detect_55[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ } else if (max2 == 1 && state->has_nicam) {
+ /* B/G NICAM */
+ state->second = msp3400c_carrier_detect_55[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 2: /* 6.0 */
+ /* PAL I NICAM */
+ state->second = MSP_CARRIER(6.552);
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM2);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ break;
+ case 3: /* 6.5 */
+ if (max2 == 1 || max2 == 2) {
+ /* D/K FM-stereo */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ } else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
+ /* L NICAM or AM-mono */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_AM_NICAM);
+ state->nicam_on = 0;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ msp3400c_setcarrier(client, state->second, state->main);
+ /* volume prescale for SCART (AM mono input) */
+ msp_write_dsp(client, 0x000d, 0x1900);
+ state->watch_stereo = 1;
+ } else if (max2 == 0 && state->has_nicam) {
+ /* D/K NICAM */
+ state->second = msp3400c_carrier_detect_65[max2].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
+ state->nicam_on = 1;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 0: /* 4.5 */
+ default:
+ no_second:
+ state->second = msp3400c_carrier_detect_main[max1].cdo;
+ msp3400c_setmode(client, MSP_MODE_FM_TERRA);
+ state->nicam_on = 0;
+ msp3400c_setcarrier(client, state->second, state->main);
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
+ break;
+ }
+
+ /* unmute */
+ msp_set_audio(client);
+
+ if (msp_debug)
+ msp3400c_print_mode(client);
+
+ /* monitor tv audio mode */
+ while (state->watch_stereo) {
+ if (msp_sleep(state,5000))
+ goto restart;
+ watch_stereo(client);
+ }
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+
+int msp3410d_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val, i, std;
+
+ v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
+ msp_sleep(state,-1);
+ v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ if (state->mode == MSP_MODE_EXTERN) {
+ /* no carrier scan needed, just unmute */
+ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+ msp_set_audio(client);
+ continue;
+ }
+
+ /* put into sane state (and mute) */
+ msp_reset(client);
+
+ /* some time for the tuner to sync */
+ if (msp_sleep(state,200))
+ goto restart;
+
+ /* start autodetect */
+ if (state->radio)
+ std = 0x40;
+ else
+ std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
+ state->watch_stereo = 0;
+
+ if (msp_debug)
+ v4l_dbg(1, msp_debug, client, "setting standard: %s (0x%04x)\n",
+ msp_standard_std_name(std), std);
+
+ if (std != 1) {
+ /* programmed some specific mode */
+ val = std;
+ } else {
+ /* triggered autodetect */
+ msp_write_dem(client, 0x20, std);
+ for (;;) {
+ if (msp_sleep(state, 100))
+ goto restart;
+
+ /* check results */
+ val = msp_read_dem(client, 0x7e);
+ if (val < 0x07ff)
+ break;
+ v4l_dbg(1, msp_debug, client, "detection still in progress\n");
+ }
+ }
+ for (i = 0; msp_stdlist[i].name != NULL; i++)
+ if (msp_stdlist[i].retval == val)
+ break;
+ v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+ msp_standard_std_name(val), val);
+ state->main = msp_stdlist[i].main;
+ state->second = msp_stdlist[i].second;
+ state->std = val;
+
+ if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) &&
+ (val != 0x0009)) {
+ /* autodetection has failed, let backup */
+ v4l_dbg(1, msp_debug, client, "autodetection failed,"
+ " switching to backup standard: %s (0x%04x)\n",
+ msp_stdlist[8].name ? msp_stdlist[8].name : "unknown",val);
+ val = 0x0009;
+ msp_write_dem(client, 0x20, val);
+ }
+
+ /* set various prescales */
+ msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+ msp_write_dsp(client, 0x0e, 0x2403); /* FM */
+ msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
+
+ /* set stereo */
+ switch (val) {
+ case 0x0008: /* B/G NICAM */
+ case 0x000a: /* I NICAM */
+ if (val == 0x0008)
+ state->mode = MSP_MODE_FM_NICAM1;
+ else
+ state->mode = MSP_MODE_FM_NICAM2;
+ /* just turn on stereo */
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->nicam_on = 1;
+ state->watch_stereo = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
+ break;
+ case 0x0009:
+ state->mode = MSP_MODE_AM_NICAM;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ state->nicam_on = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO);
+ state->watch_stereo = 1;
+ break;
+ case 0x0020: /* BTSC */
+ /* just turn on stereo */
+ state->mode = MSP_MODE_BTSC;
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->nicam_on = 0;
+ state->watch_stereo = 1;
+ msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
+ break;
+ case 0x0040: /* FM radio */
+ state->mode = MSP_MODE_FM_RADIO;
+ state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ state->audmode = V4L2_TUNER_MODE_STEREO;
+ state->nicam_on = 0;
+ state->watch_stereo = 0;
+ /* not needed in theory if we have radio, but
+ short programming enables carrier mute */
+ msp3400c_setmode(client, MSP_MODE_FM_RADIO);
+ msp3400c_setcarrier(client, MSP_CARRIER(10.7),
+ MSP_CARRIER(10.7));
+ /* scart routing */
+ msp_set_scart(client,SCART_IN2,0);
+ /* msp34xx does radio decoding */
+ msp_write_dsp(client, 0x08, 0x0020);
+ msp_write_dsp(client, 0x09, 0x0020);
+ msp_write_dsp(client, 0x0b, 0x0020);
+ break;
+ case 0x0003:
+ case 0x0004:
+ case 0x0005:
+ state->mode = MSP_MODE_FM_TERRA;
+ state->rxsubchans = V4L2_TUNER_SUB_MONO;
+ state->audmode = V4L2_TUNER_MODE_MONO;
+ state->nicam_on = 0;
+ state->watch_stereo = 1;
+ break;
+ }
+
+ /* unmute, restore misc registers */
+ msp_set_audio(client);
+ msp_write_dsp(client, 0x13, state->acb);
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
+
+ /* monitor tv audio mode */
+ while (state->watch_stereo) {
+ if (msp_sleep(state,5000))
+ goto restart;
+ watch_stereo(client);
+ }
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* msp34xxG + (autoselect no-thread) */
+/* this one uses both automatic standard detection and automatic sound */
+/* select which are available in the newer G versions */
+/* struct msp: only norm, acb and source are really used in this mode */
+
+/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
+ * the value for source is the same as bit 15:8 of DSP registers 0x08,
+ * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
+ *
+ * this function replaces msp3400c_setstereo
+ */
+static void msp34xxg_set_source(struct i2c_client *client, int source)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ /* fix matrix mode to stereo and let the msp choose what
+ * to output according to 'source', as recommended
+ * for MONO (source==0) downmixing set bit[7:0] to 0x30
+ */
+ int value = (source & 0x07) << 8 | (source == 0 ? 0x30 : 0x20);
+
+ v4l_dbg(1, msp_debug, client, "set source to %d (0x%x)\n", source, value);
+ /* Loudspeaker Output */
+ msp_write_dsp(client, 0x08, value);
+ /* SCART1 DA Output */
+ msp_write_dsp(client, 0x0a, value);
+ /* Quasi-peak detector */
+ msp_write_dsp(client, 0x0c, value);
+ /*
+ * set identification threshold. Personally, I
+ * I set it to a higher value that the default
+ * of 0x190 to ignore noisy stereo signals.
+ * this needs tuning. (recommended range 0x00a0-0x03c0)
+ * 0x7f0 = forced mono mode
+ */
+ /* a2 threshold for stereo/bilingual */
+ msp_write_dem(client, 0x22, msp_stereo_thresh);
+ state->source = source;
+}
+
+/* (re-)initialize the msp34xxg, according to the current norm in state->norm
+ * return 0 if it worked, -1 if it failed
+ */
+static int msp34xxg_reset(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int modus, std;
+
+ if (msp_reset(client))
+ return -1;
+
+ /* make sure that input/output is muted (paranoid mode) */
+ /* ACB, mute DSP input, mute SCART 1 */
+ if (msp_write_dsp(client, 0x13, 0x0f20))
+ return -1;
+
+ if (state->has_i2s_conf)
+ msp_write_dem(client, 0x40, state->i2s_mode);
+
+ /* step-by-step initialisation, as described in the manual */
+ modus = msp_modus(client);
+ if (state->radio)
+ std = 0x40;
+ else
+ std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
+ modus &= ~0x03; /* STATUS_CHANGE = 0 */
+ modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION = 1 */
+ if (msp_write_dem(client, 0x30, modus))
+ return -1;
+ if (msp_write_dem(client, 0x20, std))
+ return -1;
+
+ /* write the dsps that may have an influence on
+ standard/audio autodetection right now */
+ msp34xxg_set_source(client, state->source);
+
+ /* AM/FM Prescale [15:8] 75khz deviation */
+ if (msp_write_dsp(client, 0x0e, 0x3000))
+ return -1;
+
+ /* NICAM Prescale 9db gain (as recommended) */
+ if (msp_write_dsp(client, 0x10, 0x5a00))
+ return -1;
+
+ return 0;
+}
+
+int msp34xxg_thread(void *data)
+{
+ struct i2c_client *client = data;
+ struct msp_state *state = i2c_get_clientdata(client);
+ int val, std, i;
+
+ v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+
+ state->source = 1; /* default */
+ for (;;) {
+ v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
+ msp_sleep(state, -1);
+ v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");
+
+ restart:
+ v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+ state->restart = 0;
+ if (kthread_should_stop())
+ break;
+
+ /* setup the chip*/
+ msp34xxg_reset(client);
+ std = msp_standard;
+ if (std != 0x01)
+ goto unmute;
+
+ /* watch autodetect */
+ v4l_dbg(1, msp_debug, client, "triggered autodetect, waiting for result\n");
+ for (i = 0; i < 10; i++) {
+ if (msp_sleep(state, 100))
+ goto restart;
+
+ /* check results */
+ val = msp_read_dem(client, 0x7e);
+ if (val < 0x07ff) {
+ std = val;
+ break;
+ }
+ v4l_dbg(2, msp_debug, client, "detection still in progress\n");
+ }
+ if (std == 1) {
+ v4l_dbg(1, msp_debug, client, "detection still in progress after 10 tries. giving up.\n");
+ continue;
+ }
+
+ unmute:
+ state->std = std;
+ v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+ msp_standard_std_name(std), std);
+
+ /* unmute: dispatch sound to scart output, set scart volume */
+ msp_set_audio(client);
+
+ /* restore ACB */
+ if (msp_write_dsp(client, 0x13, state->acb))
+ return -1;
+
+ msp_write_dem(client, 0x40, state->i2s_mode);
+ }
+ v4l_dbg(1, msp_debug, client, "thread: exit\n");
+ return 0;
+}
+
+void msp34xxg_detect_stereo(struct i2c_client *client)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+
+ int status = msp_read_dem(client, 0x0200);
+ int is_bilingual = status & 0x100;
+ int is_stereo = status & 0x40;
+
+ state->rxsubchans = 0;
+ if (is_stereo)
+ state->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ else
+ state->rxsubchans |= V4L2_TUNER_SUB_MONO;
+ if (is_bilingual) {
+ state->rxsubchans |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ /* I'm supposed to check whether it's SAP or not
+ * and set only LANG2/SAP in this case. Yet, the MSP
+ * does a lot of work to hide this and handle everything
+ * the same way. I don't want to work around it so unless
+ * this is a problem, I'll handle SAP just like lang1/lang2.
+ */
+ }
+ v4l_dbg(1, msp_debug, client, "status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
+ status, is_stereo, is_bilingual, state->rxsubchans);
+}
+
+void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
+{
+ struct msp_state *state = i2c_get_clientdata(client);
+ int source;
+
+ switch (audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ source = 0; /* mono only */
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ source = 1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
+ /* problem: that could also mean 2 (scart input) */
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ source = 3; /* stereo or A */
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ source = 4; /* stereo or B */
+ break;
+ default:
+ audmode = 0;
+ source = 1;
+ break;
+ }
+ state->audmode = audmode;
+ msp34xxg_set_source(client, source);
+}
+
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
deleted file mode 100644
index d86f8e92e534..000000000000
--- a/drivers/media/video/msp3400.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/*
- * programming the msp34* sound processor family
- *
- * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
- *
- * what works and what doesn't:
- *
- * AM-Mono
- * Support for Hauppauge cards added (decoding handled by tuner) added by
- * Frederic Crozat <fcrozat@mail.dotcom.fr>
- *
- * FM-Mono
- * should work. The stereo modes are backward compatible to FM-mono,
- * therefore FM-Mono should be allways available.
- *
- * FM-Stereo (B/G, used in germany)
- * should work, with autodetect
- *
- * FM-Stereo (satellite)
- * should work, no autodetect (i.e. default is mono, but you can
- * switch to stereo -- untested)
- *
- * NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
- * should work, with autodetect. Support for NICAM was added by
- * Pekka Pietikainen <pp@netppl.fi>
- *
- *
- * TODO:
- * - better SAT support
- *
- *
- * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
- * using soundcore instead of OSS
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/kthread.h>
-#include <linux/suspend.h>
-#include <asm/semaphore.h>
-#include <asm/pgtable.h>
-
-#include <media/audiochip.h>
-#include "msp3400.h"
-
-#define msp3400_dbg(fmt, arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* Medium volume debug. */
-#define msp3400_dbg_mediumvol(fmt, arg...) \
- do { \
- if (debug >= 2) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* High volume debug. Use with care. */
-#define msp3400_dbg_highvol(fmt, arg...) \
- do { \
- if (debug >= 16) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define msp3400_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_warn(fmt, arg...) do { \
- printk(KERN_WARNING "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define msp3400_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-#define OPMODE_AUTO -1
-#define OPMODE_MANUAL 0
-#define OPMODE_SIMPLE 1 /* use short programming (>= msp3410 only) */
-#define OPMODE_SIMPLER 2 /* use shorter programming (>= msp34xxG) */
-
-/* insmod parameters */
-static int opmode = OPMODE_AUTO;
-static int debug = 0; /* debug output */
-static int once = 0; /* no continous stereo monitoring */
-static int amsound = 0; /* hard-wire AM sound at 6.5 Hz (france),
- the autoscan seems work well only with FM... */
-static int standard = 1; /* Override auto detect of audio standard, if needed. */
-static int dolby = 0;
-
-static int stereo_threshold = 0x190; /* a2 threshold for stereo/bilingual
- (msp34xxg only) 0x00a0-0x03c0 */
-#define DFP_COUNT 0x41
-static const int bl_dfp[] = {
- 0x00, 0x01, 0x02, 0x03, 0x06, 0x08, 0x09, 0x0a,
- 0x0b, 0x0d, 0x0e, 0x10
-};
-
-#define IS_MSP34XX_G(msp) ((msp)->opmode==2)
-
-struct msp3400c {
- int rev1,rev2;
-
- int opmode;
- int nicam;
- int mode;
- int norm;
- int stereo;
- int nicam_on;
- int acb;
- int in_scart;
- int i2s_mode;
- int main, second; /* sound carrier */
- int input;
- int source; /* see msp34xxg_set_source */
-
- /* v4l2 */
- int audmode;
- int rxsubchans;
-
- int muted;
- int left, right; /* volume */
- int bass, treble;
-
- /* shadow register set */
- int dfp_regs[DFP_COUNT];
-
- /* thread */
- struct task_struct *kthread;
- wait_queue_head_t wq;
- int restart:1;
- int watch_stereo:1;
-};
-
-#define MIN(a,b) (((a)>(b))?(b):(a))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-#define HAVE_NICAM(msp) (((msp->rev2>>8) & 0xff) != 00)
-#define HAVE_SIMPLE(msp) ((msp->rev1 & 0xff) >= 'D'-'@')
-#define HAVE_SIMPLER(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
-#define HAVE_RADIO(msp) ((msp->rev1 & 0xff) >= 'G'-'@')
-
-#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
-
-/* ---------------------------------------------------------------------- */
-
-/* read-only */
-module_param(opmode, int, 0444);
-
-/* read-write */
-module_param(once, int, 0644);
-module_param(debug, int, 0644);
-module_param(stereo_threshold, int, 0644);
-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");
-
-/* ---------------------------------------------------------------------- */
-
-#define I2C_MSP3400C 0x80
-#define I2C_MSP3400C_ALT 0x88
-
-#define I2C_MSP3400C_DEM 0x10
-#define I2C_MSP3400C_DFP 0x12
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {
- I2C_MSP3400C >> 1,
- I2C_MSP3400C_ALT >> 1,
- I2C_CLIENT_END
-};
-I2C_CLIENT_INSMOD;
-
-MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/* ----------------------------------------------------------------------- */
-/* functions for talking to the MSP3400C Sound processor */
-
-static int msp3400c_reset(struct i2c_client *client)
-{
- /* reset and read revision code */
- static char reset_off[3] = { 0x00, 0x80, 0x00 };
- static char reset_on[3] = { 0x00, 0x00, 0x00 };
- static char write[3] = { I2C_MSP3400C_DFP + 1, 0x00, 0x1e };
- char read[2];
- struct i2c_msg reset[2] = {
- { client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
- { client->addr, I2C_M_IGNORE_NAK, 3, reset_on },
- };
- struct i2c_msg test[2] = {
- { client->addr, 0, 3, write },
- { client->addr, I2C_M_RD, 2, read },
- };
-
- msp3400_dbg_highvol("msp3400c_reset\n");
- if ( (1 != i2c_transfer(client->adapter,&reset[0],1)) ||
- (1 != i2c_transfer(client->adapter,&reset[1],1)) ||
- (2 != i2c_transfer(client->adapter,test,2)) ) {
- msp3400_err("chip reset failed\n");
- return -1;
- }
- return 0;
-}
-
-static int msp3400c_read(struct i2c_client *client, int dev, int addr)
-{
- int err,retval;
-
- unsigned char write[3];
- unsigned char read[2];
- struct i2c_msg msgs[2] = {
- { client->addr, 0, 3, write },
- { client->addr, I2C_M_RD, 2, read }
- };
-
- write[0] = dev+1;
- write[1] = addr >> 8;
- write[2] = addr & 0xff;
-
- for (err = 0; err < 3;) {
- if (2 == i2c_transfer(client->adapter,msgs,2))
- break;
- err++;
- msp3400_warn("I/O error #%d (read 0x%02x/0x%02x)\n", err,
- dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
- }
- if (3 == err) {
- msp3400_warn("giving up, resetting chip. Sound will go off, sorry folks :-|\n");
- msp3400c_reset(client);
- return -1;
- }
- retval = read[0] << 8 | read[1];
- msp3400_dbg_highvol("msp3400c_read(0x%x, 0x%x): 0x%x\n", dev, addr, retval);
- return retval;
-}
-
-static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val)
-{
- int err;
- unsigned char buffer[5];
-
- buffer[0] = dev;
- buffer[1] = addr >> 8;
- buffer[2] = addr & 0xff;
- buffer[3] = val >> 8;
- buffer[4] = val & 0xff;
-
- msp3400_dbg_highvol("msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val);
- for (err = 0; err < 3;) {
- if (5 == i2c_master_send(client, buffer, 5))
- break;
- err++;
- msp3400_warn("I/O error #%d (write 0x%02x/0x%02x)\n", err,
- dev, addr);
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(msecs_to_jiffies(10));
- }
- if (3 == err) {
- msp3400_warn("giving up, reseting chip. Sound will go off, sorry folks :-|\n");
- msp3400c_reset(client);
- return -1;
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------ */
-
-/* This macro is allowed for *constants* only, gcc must calculate it
- at compile time. Remember -- no floats in kernel mode */
-#define MSP_CARRIER(freq) ((int)((float)(freq/18.432)*(1<<24)))
-
-#define MSP_MODE_AM_DETECT 0
-#define MSP_MODE_FM_RADIO 2
-#define MSP_MODE_FM_TERRA 3
-#define MSP_MODE_FM_SAT 4
-#define MSP_MODE_FM_NICAM1 5
-#define MSP_MODE_FM_NICAM2 6
-#define MSP_MODE_AM_NICAM 7
-#define MSP_MODE_BTSC 8
-#define MSP_MODE_EXTERN 9
-
-static struct MSP_INIT_DATA_DEM {
- int fir1[6];
- int fir2[6];
- int cdo1;
- int cdo2;
- int ad_cv;
- int mode_reg;
- int dfp_src;
- int dfp_matrix;
-} msp_init_data[] = {
- { /* AM (for carrier detect / msp3400) */
- {75, 19, 36, 35, 39, 40},
- {75, 19, 36, 35, 39, 40},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0500, 0x0020, 0x3000
- },{ /* AM (for carrier detect / msp3410) */
- {-1, -1, -8, 2, 59, 126},
- {-1, -1, -8, 2, 59, 126},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0100, 0x0020, 0x3000
- },{ /* FM Radio */
- {-8, -8, 4, 6, 78, 107},
- {-8, -8, 4, 6, 78, 107},
- MSP_CARRIER(10.7), MSP_CARRIER(10.7),
- 0x00d0, 0x0480, 0x0020, 0x3000
- },{ /* Terrestial FM-mono + FM-stereo */
- {3, 18, 27, 48, 66, 72},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0480, 0x0030, 0x3000
- },{ /* Sat FM-mono */
- { 1, 9, 14, 24, 33, 37},
- { 3, 18, 27, 48, 66, 72},
- MSP_CARRIER(6.5), MSP_CARRIER(6.5),
- 0x00c6, 0x0480, 0x0000, 0x3000
- },{ /* NICAM/FM -- B/G (5.5/5.85), D/K (6.5/5.85) */
- {-2, -8, -10, 10, 50, 86},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
- 0x00d0, 0x0040, 0x0120, 0x3000
- },{ /* NICAM/FM -- I (6.0/6.552) */
- {2, 4, -6, -4, 40, 94},
- {3, 18, 27, 48, 66, 72},
- MSP_CARRIER(6.0), MSP_CARRIER(6.0),
- 0x00d0, 0x0040, 0x0120, 0x3000
- },{ /* NICAM/AM -- L (6.5/5.85) */
- {-2, -8, -10, 10, 50, 86},
- {-4, -12, -9, 23, 79, 126},
- MSP_CARRIER(6.5), MSP_CARRIER(6.5),
- 0x00c6, 0x0140, 0x0120, 0x7c03
- },
-};
-
-struct CARRIER_DETECT {
- int cdo;
- char *name;
-};
-
-static struct CARRIER_DETECT carrier_detect_main[] = {
- /* main carrier */
- { MSP_CARRIER(4.5), "4.5 NTSC" },
- { MSP_CARRIER(5.5), "5.5 PAL B/G" },
- { MSP_CARRIER(6.0), "6.0 PAL I" },
- { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
-};
-
-static struct CARRIER_DETECT carrier_detect_55[] = {
- /* PAL B/G */
- { MSP_CARRIER(5.7421875), "5.742 PAL B/G FM-stereo" },
- { MSP_CARRIER(5.85), "5.85 PAL B/G NICAM" }
-};
-
-static struct CARRIER_DETECT carrier_detect_65[] = {
- /* PAL SAT / SECAM */
- { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" },
- { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
- { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
- { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
- { MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
- { MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
-};
-
-#define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT))
-
-/* ----------------------------------------------------------------------- *
- * bits 9 8 5 - SCART DSP input Select:
- * 0 0 0 - SCART 1 to DSP input (reset position)
- * 0 1 0 - MONO to DSP input
- * 1 0 0 - SCART 2 to DSP input
- * 1 1 1 - Mute DSP input
- *
- * bits 11 10 6 - SCART 1 Output Select:
- * 0 0 0 - undefined (reset position)
- * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
- * 1 0 0 - MONO input to SCART 1 Output
- * 1 1 0 - SCART 1 DA to SCART 1 Output
- * 0 0 1 - SCART 2 DA to SCART 1 Output
- * 0 1 1 - SCART 1 Input to SCART 1 Output
- * 1 1 1 - Mute SCART 1 Output
- *
- * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART):
- * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position)
- * 0 1 0 - SCART 1 Input to SCART 2 Output
- * 1 0 0 - MONO input to SCART 2 Output
- * 0 0 1 - SCART 2 DA to SCART 2 Output
- * 0 1 1 - SCART 2 Input to SCART 2 Output
- * 1 1 0 - Mute SCART 2 Output
- *
- * Bits 4 to 0 should be zero.
- * ----------------------------------------------------------------------- */
-
-static int scarts[3][9] = {
- /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */
- /* SCART DSP Input select */
- { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 },
- /* SCART1 Output select */
- { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 },
- /* SCART2 Output select */
- { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 },
-};
-
-static char *scart_names[] = {
- "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute"
-};
-
-static void msp3400c_set_scart(struct i2c_client *client, int in, int out)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- msp->in_scart=in;
-
- if (in >= 1 && in <= 8 && out >= 0 && out <= 2) {
- if (-1 == scarts[out][in])
- return;
-
- msp->acb &= ~scarts[out][SCART_MASK];
- msp->acb |= scarts[out][in];
- } else
- msp->acb = 0xf60; /* Mute Input and SCART 1 Output */
-
- msp3400_dbg("scart switch: %s => %d (ACB=0x%04x)\n",
- scart_names[in], out, msp->acb);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb);
-
- /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
-}
-
-/* ------------------------------------------------------------------------ */
-
-static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2)
-{
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0093, cdo1 & 0xfff);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
-}
-
-static void msp3400c_setvolume(struct i2c_client *client,
- int muted, int left, int right)
- {
- int vol = 0, val = 0, balance = 0;
-
- if (!muted) {
- /* 0x7f instead if 0x73 here has sound quality issues,
- * probably due to overmodulation + clipping ... */
- vol = (left > right) ? left : right;
- val = (vol * 0x73 / 65535) << 8;
- }
- if (vol > 0) {
- balance = ((right - left) * 127) / vol;
- }
-
- msp3400_dbg("setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n",
- muted ? "on" : "off", left, right, val >> 8, balance);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0007,
- muted ? 0x1 : (val | 0x1));
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0001, balance << 8);
-}
-
-static void msp3400c_setbass(struct i2c_client *client, int bass)
-{
- int val = ((bass-32768) * 0x60 / 65535) << 8;
-
- msp3400_dbg("setbass: %d 0x%02x\n", bass, val >> 8);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
-}
-
-static void msp3400c_settreble(struct i2c_client *client, int treble)
-{
- int val = ((treble-32768) * 0x60 / 65535) << 8;
-
- msp3400_dbg("settreble: %d 0x%02x\n",treble, val>>8);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
-}
-
-static void msp3400c_setmode(struct i2c_client *client, int type)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- msp3400_dbg("setmode: %d\n",type);
- msp->mode = type;
- msp->audmode = V4L2_TUNER_MODE_MONO;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x00bb, /* ad_cv */
- msp_init_data[type].ad_cv);
-
- for (i = 5; i >= 0; i--) /* fir 1 */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0001,
- msp_init_data[type].fir1[i]);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0004); /* fir 2 */
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0040);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005, 0x0000);
- for (i = 5; i >= 0; i--)
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0005,
- msp_init_data[type].fir2[i]);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
- msp_init_data[type].mode_reg);
-
- msp3400c_setcarrier(client, msp_init_data[type].cdo1,
- msp_init_data[type].cdo2);
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
-
- if (dolby) {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,
- 0x0520); /* I2S1 */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
- 0x0620); /* I2S2 */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
- msp_init_data[type].dfp_src);
- } else {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,
- msp_init_data[type].dfp_src);
- }
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,
- msp_init_data[type].dfp_src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e,
- msp_init_data[type].dfp_matrix);
-
- if (HAVE_NICAM(msp)) {
- /* nicam prescale */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */
- }
-}
-
-/* given a bitmask of VIDEO_SOUND_XXX returns the "best" in the bitmask */
-static int best_video_sound(int rxsubchans)
-{
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- return V4L2_TUNER_MODE_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- return V4L2_TUNER_MODE_LANG1;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- return V4L2_TUNER_MODE_LANG2;
- return V4L2_TUNER_MODE_MONO;
-}
-
-/* turn on/off nicam + stereo */
-static void msp3400c_setstereo(struct i2c_client *client, int mode)
-{
- static char *strmode[] = { "0", "mono", "stereo", "3",
- "lang1", "5", "6", "7", "lang2"
- };
- struct msp3400c *msp = i2c_get_clientdata(client);
- int nicam = 0; /* channel source: FM/AM or nicam */
- int src = 0;
-
- if (IS_MSP34XX_G(msp)) {
- /* this method would break everything, let's make sure
- * it's never called
- */
- msp3400_dbg
- ("DEBUG WARNING setstereo called with mode=%d instead of set_source (ignored)\n",
- mode);
- return;
- }
-
- /* switch demodulator */
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- msp3400_dbg("FM setstereo: %s\n", strmode[mode]);
- msp3400c_setcarrier(client,msp->second,msp->main);
- switch (mode) {
- case V4L2_TUNER_MODE_STEREO:
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3001);
- break;
- case V4L2_TUNER_MODE_MONO:
- case V4L2_TUNER_MODE_LANG1:
- case V4L2_TUNER_MODE_LANG2:
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000e, 0x3000);
- break;
- }
- break;
- case MSP_MODE_FM_SAT:
- msp3400_dbg("SAT setstereo: %s\n", strmode[mode]);
- switch (mode) {
- case V4L2_TUNER_MODE_MONO:
- msp3400c_setcarrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
- break;
- case V4L2_TUNER_MODE_STEREO:
- msp3400c_setcarrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
- break;
- case V4L2_TUNER_MODE_LANG1:
- msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
- break;
- case V4L2_TUNER_MODE_LANG2:
- msp3400c_setcarrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
- break;
- }
- break;
- case MSP_MODE_FM_NICAM1:
- case MSP_MODE_FM_NICAM2:
- case MSP_MODE_AM_NICAM:
- msp3400_dbg("NICAM setstereo: %s\n",strmode[mode]);
- msp3400c_setcarrier(client,msp->second,msp->main);
- if (msp->nicam_on)
- nicam=0x0100;
- break;
- case MSP_MODE_BTSC:
- msp3400_dbg("BTSC setstereo: %s\n",strmode[mode]);
- nicam=0x0300;
- break;
- case MSP_MODE_EXTERN:
- msp3400_dbg("extern setstereo: %s\n",strmode[mode]);
- nicam = 0x0200;
- break;
- case MSP_MODE_FM_RADIO:
- msp3400_dbg("FM-Radio setstereo: %s\n",strmode[mode]);
- break;
- default:
- msp3400_dbg("mono setstereo\n");
- return;
- }
-
- /* switch audio */
- switch (best_video_sound(mode)) {
- case V4L2_TUNER_MODE_STEREO:
- src = 0x0020 | nicam;
- break;
- case V4L2_TUNER_MODE_MONO:
- if (msp->mode == MSP_MODE_AM_NICAM) {
- msp3400_dbg("switching to AM mono\n");
- /* AM mono decoding is handled by tuner, not MSP chip */
- /* SCART switching control register */
- msp3400c_set_scart(client,SCART_MONO,0);
- src = 0x0200;
- break;
- }
- case V4L2_TUNER_MODE_LANG1:
- src = 0x0000 | nicam;
- break;
- case V4L2_TUNER_MODE_LANG2:
- src = 0x0010 | nicam;
- break;
- }
- msp3400_dbg("setstereo final source/matrix = 0x%x\n", src);
-
- if (dolby) {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,0x0520);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,0x0620);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);
- } else {
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0008,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0009,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000a,src);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000b,src);
- }
-}
-
-static void
-msp3400c_print_mode(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (msp->main == msp->second) {
- msp3400_dbg("mono sound carrier: %d.%03d MHz\n",
- msp->main/910000,(msp->main/910)%1000);
- } else {
- msp3400_dbg("main sound carrier: %d.%03d MHz\n",
- msp->main/910000,(msp->main/910)%1000);
- }
- if (msp->mode == MSP_MODE_FM_NICAM1 || msp->mode == MSP_MODE_FM_NICAM2)
- msp3400_dbg("NICAM/FM carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- if (msp->mode == MSP_MODE_AM_NICAM)
- msp3400_dbg("NICAM/AM carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- if (msp->mode == MSP_MODE_FM_TERRA &&
- msp->main != msp->second) {
- msp3400_dbg("FM-stereo carrier : %d.%03d MHz\n",
- msp->second/910000,(msp->second/910)%1000);
- }
-}
-
-#define MSP3400_MAX 4
-static struct i2c_client *msps[MSP3400_MAX];
-static void msp3400c_restore_dfp(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- for (i = 0; i < DFP_COUNT; i++) {
- if (-1 == msp->dfp_regs[i])
- continue;
- msp3400c_write(client, I2C_MSP3400C_DFP, i, msp->dfp_regs[i]);
- }
-}
-
-/* if the dfp_regs is set, set what's in there. Otherwise, set the default value */
-static int msp3400c_write_dfp_with_default(struct i2c_client *client,
- int addr, int default_value)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int value = default_value;
- if (addr < DFP_COUNT && -1 != msp->dfp_regs[addr])
- value = msp->dfp_regs[addr];
- return msp3400c_write(client, I2C_MSP3400C_DFP, addr, value);
-}
-
-/* ----------------------------------------------------------------------- */
-
-struct REGISTER_DUMP {
- int addr;
- char *name;
-};
-
-struct REGISTER_DUMP d1[] = {
- {0x007e, "autodetect"},
- {0x0023, "C_AD_BITS "},
- {0x0038, "ADD_BITS "},
- {0x003e, "CIB_BITS "},
- {0x0057, "ERROR_RATE"},
-};
-
-static int autodetect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int val;
- int rxsubchans = msp->rxsubchans;
- int newnicam = msp->nicam_on;
- int update = 0;
-
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18);
- if (val > 32767)
- val -= 65536;
- msp3400_dbg("stereo detect register: %d\n",val);
- if (val > 4096) {
- rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
- } else if (val < -4096) {
- rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
- } else {
- rxsubchans = V4L2_TUNER_SUB_MONO;
- }
- newnicam = 0;
- break;
- case MSP_MODE_FM_NICAM1:
- case MSP_MODE_FM_NICAM2:
- case MSP_MODE_AM_NICAM:
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23);
- msp3400_dbg("nicam sync=%d, mode=%d\n",
- val & 1, (val & 0x1e) >> 1);
-
- if (val & 1) {
- /* nicam synced */
- switch ((val & 0x1e) >> 1) {
- case 0:
- case 8:
- rxsubchans = V4L2_TUNER_SUB_STEREO;
- break;
- case 1:
- case 9:
- rxsubchans = V4L2_TUNER_SUB_MONO
- | V4L2_TUNER_SUB_LANG1;
- break;
- case 2:
- case 10:
- rxsubchans = V4L2_TUNER_SUB_MONO
- | V4L2_TUNER_SUB_LANG1
- | V4L2_TUNER_SUB_LANG2;
- break;
- default:
- rxsubchans = V4L2_TUNER_SUB_MONO;
- break;
- }
- newnicam=1;
- } else {
- newnicam = 0;
- rxsubchans = V4L2_TUNER_SUB_MONO;
- }
- break;
- case MSP_MODE_BTSC:
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200);
- msp3400_dbg("status=0x%x (pri=%s, sec=%s, %s%s%s)\n",
- val,
- (val & 0x0002) ? "no" : "yes",
- (val & 0x0004) ? "no" : "yes",
- (val & 0x0040) ? "stereo" : "mono",
- (val & 0x0080) ? ", nicam 2nd mono" : "",
- (val & 0x0100) ? ", bilingual/SAP" : "");
- rxsubchans = V4L2_TUNER_SUB_MONO;
- if (val & 0x0040) rxsubchans |= V4L2_TUNER_SUB_STEREO;
- if (val & 0x0100) rxsubchans |= V4L2_TUNER_SUB_LANG1;
- break;
- }
- if (rxsubchans != msp->rxsubchans) {
- update = 1;
- msp3400_dbg("watch: rxsubchans %d => %d\n",
- msp->rxsubchans,rxsubchans);
- msp->rxsubchans = rxsubchans;
- }
- if (newnicam != msp->nicam_on) {
- update = 1;
- msp3400_dbg("watch: nicam %d => %d\n",
- msp->nicam_on,newnicam);
- msp->nicam_on = newnicam;
- }
- return update;
-}
-
-/*
- * A kernel thread for msp3400 control -- we don't want to block the
- * in the ioctl while doing the sound carrier & stereo detect
- */
-
-static int msp34xx_sleep(struct msp3400c *msp, int timeout)
-{
- DECLARE_WAITQUEUE(wait, current);
-
- add_wait_queue(&msp->wq, &wait);
- if (!kthread_should_stop()) {
- if (timeout < 0) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- } else {
- schedule_timeout_interruptible
- (msecs_to_jiffies(timeout));
- }
- }
-
- remove_wait_queue(&msp->wq, &wait);
- try_to_freeze();
- return msp->restart;
-}
-
-/* stereo/multilang monitoring */
-static void watch_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (autodetect_stereo(client)) {
- if (msp->stereo & V4L2_TUNER_MODE_STEREO)
- msp3400c_setstereo(client, V4L2_TUNER_MODE_STEREO);
- else if (msp->stereo & VIDEO_SOUND_LANG1)
- msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1);
- else
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- }
-
- if (once)
- msp->watch_stereo = 0;
-}
-
-
-static int msp3400c_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- struct CARRIER_DETECT *cd;
- int count, max1,max2,val1,val2, val,this;
-
-
- msp3400_info("msp3400 daemon started\n");
- for (;;) {
- msp3400_dbg_mediumvol("msp3400 thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp3400 thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- if (VIDEO_MODE_RADIO == msp->norm ||
- MSP_MODE_EXTERN == msp->mode) {
- /* no carrier scan, just unmute */
- msp3400_info("thread: no carrier scan\n");
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- continue;
- }
-
- /* mute */
- msp3400c_setvolume(client, msp->muted, 0, 0);
- msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
- val1 = val2 = 0;
- max1 = max2 = -1;
- msp->watch_stereo = 0;
-
- /* some time for the tuner to sync */
- if (msp34xx_sleep(msp,200))
- goto restart;
-
- /* carrier detect pass #1 -- main carrier */
- cd = carrier_detect_main;
- count = CARRIER_COUNT(carrier_detect_main);
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
- /* autodetect doesn't work well with AM ... */
- max1 = 3;
- count = 0;
- msp3400_dbg("AM sound override\n");
- }
-
- for (this = 0; this < count; this++) {
- msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- if (msp34xx_sleep(msp,100))
- goto restart;
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
- if (val > 32767)
- val -= 65536;
- if (val1 < val)
- val1 = val, max1 = this;
- msp3400_dbg("carrier1 val: %5d / %s\n", val,cd[this].name);
- }
-
- /* carrier detect pass #2 -- second (stereo) carrier */
- switch (max1) {
- case 1: /* 5.5 */
- cd = carrier_detect_55;
- count = CARRIER_COUNT(carrier_detect_55);
- break;
- case 3: /* 6.5 */
- cd = carrier_detect_65;
- count = CARRIER_COUNT(carrier_detect_65);
- break;
- case 0: /* 4.5 */
- case 2: /* 6.0 */
- default:
- cd = NULL;
- count = 0;
- break;
- }
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM)) {
- /* autodetect doesn't work well with AM ... */
- cd = NULL;
- count = 0;
- max2 = 0;
- }
- for (this = 0; this < count; this++) {
- msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo);
- if (msp34xx_sleep(msp,100))
- goto restart;
- val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b);
- if (val > 32767)
- val -= 65536;
- if (val2 < val)
- val2 = val, max2 = this;
- msp3400_dbg("carrier2 val: %5d / %s\n", val,cd[this].name);
- }
-
- /* programm the msp3400 according to the results */
- msp->main = carrier_detect_main[max1].cdo;
- switch (max1) {
- case 1: /* 5.5 */
- if (max2 == 0) {
- /* B/G FM-stereo */
- msp->second = carrier_detect_55[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- } else if (max2 == 1 && HAVE_NICAM(msp)) {
- /* B/G NICAM */
- msp->second = carrier_detect_55[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- } else {
- goto no_second;
- }
- break;
- case 2: /* 6.0 */
- /* PAL I NICAM */
- msp->second = MSP_CARRIER(6.552);
- msp3400c_setmode(client, MSP_MODE_FM_NICAM2);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- break;
- case 3: /* 6.5 */
- if (max2 == 1 || max2 == 2) {
- /* D/K FM-stereo */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- } else if (max2 == 0 &&
- msp->norm == VIDEO_MODE_SECAM) {
- /* L NICAM or AM-mono */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_AM_NICAM);
- msp->nicam_on = 0;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- msp3400c_setcarrier(client, msp->second, msp->main);
- /* volume prescale for SCART (AM mono input) */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900);
- msp->watch_stereo = 1;
- } else if (max2 == 0 && HAVE_NICAM(msp)) {
- /* D/K NICAM */
- msp->second = carrier_detect_65[max2].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_NICAM1);
- msp->nicam_on = 1;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->watch_stereo = 1;
- } else {
- goto no_second;
- }
- break;
- case 0: /* 4.5 */
- default:
- no_second:
- msp->second = carrier_detect_main[max1].cdo;
- msp3400c_setmode(client, MSP_MODE_FM_TERRA);
- msp->nicam_on = 0;
- msp3400c_setcarrier(client, msp->second, msp->main);
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO);
- break;
- }
-
- /* unmute */
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_restore_dfp(client);
-
- if (debug)
- msp3400c_print_mode(client);
-
- /* monitor tv audio mode */
- while (msp->watch_stereo) {
- if (msp34xx_sleep(msp,5000))
- goto restart;
- watch_stereo(client);
- }
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-/* this one uses the automatic sound standard detection of newer */
-/* msp34xx chip versions */
-
-static struct MODES {
- int retval;
- int main, second;
- char *name;
-} modelist[] = {
- { 0x0000, 0, 0, "ERROR" },
- { 0x0001, 0, 0, "autodetect start" },
- { 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72), "4.5/4.72 M Dual FM-Stereo" },
- { 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875), "5.5/5.74 B/G Dual FM-Stereo" },
- { 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125), "6.5/6.25 D/K1 Dual FM-Stereo" },
- { 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875), "6.5/6.74 D/K2 Dual FM-Stereo" },
- { 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 D/K FM-Mono (HDEV3)" },
- { 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85), "5.5/5.85 B/G NICAM FM" },
- { 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 L NICAM AM" },
- { 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55), "6.0/6.55 I NICAM FM" },
- { 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM" },
- { 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85), "6.5/5.85 D/K NICAM FM (HDEV2)" },
- { 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Stereo" },
- { 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M BTSC-Mono + SAP" },
- { 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5), "4.5 M EIA-J Japan Stereo" },
- { 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7), "10.7 FM-Stereo Radio" },
- { 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5), "6.5 SAT-Mono" },
- { 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20), "7.02/7.20 SAT-Stereo" },
- { 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2), "7.2 SAT ADR" },
- { -1, 0, 0, NULL }, /* EOF */
-};
-
-static inline const char *msp34xx_standard_mode_name(int mode)
-{
- int i;
- for (i = 0; modelist[i].name != NULL; i++)
- if (modelist[i].retval == mode)
- return modelist[i].name;
- return "unknown";
-}
-
-static int msp34xx_modus(struct i2c_client *client, int norm)
-{
- switch (norm) {
- case VIDEO_MODE_PAL:
- msp3400_dbg("video mode selected to PAL\n");
-
-#if 1
- /* experimental: not sure this works with all chip versions */
- return 0x7003;
-#else
- /* previous value, try this if it breaks ... */
- return 0x1003;
-#endif
- case VIDEO_MODE_NTSC: /* BTSC */
- msp3400_dbg("video mode selected to NTSC\n");
- return 0x2003;
- case VIDEO_MODE_SECAM:
- msp3400_dbg("video mode selected to SECAM\n");
- return 0x0003;
- case VIDEO_MODE_RADIO:
- msp3400_dbg("video mode selected to Radio\n");
- return 0x0003;
- case VIDEO_MODE_AUTO:
- msp3400_dbg("video mode selected to Auto\n");
- return 0x2003;
- default:
- return 0x0003;
- }
-}
-
-static int msp34xx_standard(int norm)
-{
- switch (norm) {
- case VIDEO_MODE_PAL:
- return 1;
- case VIDEO_MODE_NTSC: /* BTSC */
- return 0x0020;
- case VIDEO_MODE_SECAM:
- return 1;
- case VIDEO_MODE_RADIO:
- return 0x0040;
- default:
- return 1;
- }
-}
-
-static int msp3410d_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- int mode,val,i,std;
-
- msp3400_info("msp3410 daemon started\n");
-
- for (;;) {
- msp3400_dbg_mediumvol("msp3410 thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp3410 thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- if (msp->mode == MSP_MODE_EXTERN) {
- /* no carrier scan needed, just unmute */
- msp3400_dbg("thread: no carrier scan\n");
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- continue;
- }
-
- /* put into sane state (and mute) */
- msp3400c_reset(client);
-
- /* some time for the tuner to sync */
- if (msp34xx_sleep(msp,200))
- goto restart;
-
- /* start autodetect */
- mode = msp34xx_modus(client, msp->norm);
- std = msp34xx_standard(msp->norm);
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode);
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std);
- msp->watch_stereo = 0;
-
- if (debug)
- msp3400_dbg("setting mode: %s (0x%04x)\n",
- msp34xx_standard_mode_name(std) ,std);
-
- if (std != 1) {
- /* programmed some specific mode */
- val = std;
- } else {
- /* triggered autodetect */
- for (;;) {
- if (msp34xx_sleep(msp,100))
- goto restart;
-
- /* check results */
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
- if (val < 0x07ff)
- break;
- msp3400_dbg("detection still in progress\n");
- }
- }
- for (i = 0; modelist[i].name != NULL; i++)
- if (modelist[i].retval == val)
- break;
- msp3400_dbg("current mode: %s (0x%04x)\n",
- modelist[i].name ? modelist[i].name : "unknown",
- val);
- msp->main = modelist[i].main;
- msp->second = modelist[i].second;
-
- if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) {
- /* autodetection has failed, let backup */
- msp3400_dbg("autodetection failed,"
- " switching to backup mode: %s (0x%04x)\n",
- modelist[8].name ? modelist[8].name : "unknown",val);
- val = 0x0009;
- msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
- }
-
- /* set various prescales */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */
-
- /* set stereo */
- switch (val) {
- case 0x0008: /* B/G NICAM */
- case 0x000a: /* I NICAM */
- if (val == 0x0008)
- msp->mode = MSP_MODE_FM_NICAM1;
- else
- msp->mode = MSP_MODE_FM_NICAM2;
- /* just turn on stereo */
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->nicam_on = 1;
- msp->watch_stereo = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
- break;
- case 0x0009:
- msp->mode = MSP_MODE_AM_NICAM;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp->nicam_on = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_MONO);
- msp->watch_stereo = 1;
- break;
- case 0x0020: /* BTSC */
- /* just turn on stereo */
- msp->mode = MSP_MODE_BTSC;
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->nicam_on = 0;
- msp->watch_stereo = 1;
- msp3400c_setstereo(client,V4L2_TUNER_MODE_STEREO);
- break;
- case 0x0040: /* FM radio */
- msp->mode = MSP_MODE_FM_RADIO;
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp->nicam_on = 0;
- msp->watch_stereo = 0;
- /* not needed in theory if HAVE_RADIO(), but
- short programming enables carrier mute */
- msp3400c_setmode(client,MSP_MODE_FM_RADIO);
- msp3400c_setcarrier(client, MSP_CARRIER(10.7),
- MSP_CARRIER(10.7));
- /* scart routing */
- msp3400c_set_scart(client,SCART_IN2,0);
- /* msp34xx does radio decoding */
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0020);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x09, 0x0020);
- msp3400c_write(client,I2C_MSP3400C_DFP, 0x0b, 0x0020);
- break;
- case 0x0003:
- case 0x0004:
- case 0x0005:
- msp->mode = MSP_MODE_FM_TERRA;
- msp->rxsubchans = V4L2_TUNER_SUB_MONO;
- msp->audmode = V4L2_TUNER_MODE_MONO;
- msp->nicam_on = 0;
- msp->watch_stereo = 1;
- break;
- }
-
- /* unmute, restore misc registers */
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb);
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
- msp3400c_restore_dfp(client);
-
- /* monitor tv audio mode */
- while (msp->watch_stereo) {
- if (msp34xx_sleep(msp,5000))
- goto restart;
- watch_stereo(client);
- }
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-/* msp34xxG + (simpler no-thread) */
-/* this one uses both automatic standard detection and automatic sound */
-/* select which are available in the newer G versions */
-/* struct msp: only norm, acb and source are really used in this mode */
-
-static void msp34xxg_set_source(struct i2c_client *client, int source);
-
-/* (re-)initialize the msp34xxg, according to the current norm in msp->norm
- * return 0 if it worked, -1 if it failed
- */
-static int msp34xxg_reset(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int modus,std;
-
- if (msp3400c_reset(client))
- return -1;
-
- /* make sure that input/output is muted (paranoid mode) */
- if (msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x13, /* ACB */
- 0x0f20 /* mute DSP input, mute SCART 1 */))
- return -1;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
-
- /* step-by-step initialisation, as described in the manual */
- modus = msp34xx_modus(client, msp->norm);
- std = msp34xx_standard(msp->norm);
- modus &= ~0x03; /* STATUS_CHANGE=0 */
- modus |= 0x01; /* AUTOMATIC_SOUND_DETECTION=1 */
- if (msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x30/*MODUS*/,
- modus))
- return -1;
- if (msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x20/*standard*/,
- std))
- return -1;
-
- /* write the dfps that may have an influence on
- standard/audio autodetection right now */
- msp34xxg_set_source(client, msp->source);
-
- if (msp3400c_write_dfp_with_default(client, 0x0e, /* AM/FM Prescale */
- 0x3000
- /* default: [15:8] 75khz deviation */
- ))
- return -1;
-
- if (msp3400c_write_dfp_with_default(client, 0x10, /* NICAM Prescale */
- 0x5a00
- /* default: 9db gain (as recommended) */
- ))
- return -1;
-
- return 0;
-}
-
-static int msp34xxg_thread(void *data)
-{
- struct i2c_client *client = data;
- struct msp3400c *msp = i2c_get_clientdata(client);
- int val, std, i;
-
- msp3400_info("msp34xxg daemon started\n");
-
- msp->source = 1; /* default */
- for (;;) {
- msp3400_dbg_mediumvol("msp34xxg thread: sleep\n");
- msp34xx_sleep(msp,-1);
- msp3400_dbg_mediumvol("msp34xxg thread: wakeup\n");
-
- restart:
- msp3400_dbg("thread: restart scan\n");
- msp->restart = 0;
- if (kthread_should_stop())
- break;
-
- /* setup the chip*/
- msp34xxg_reset(client);
- std = standard;
- if (std != 0x01)
- goto unmute;
-
- /* watch autodetect */
- msp3400_dbg("triggered autodetect, waiting for result\n");
- for (i = 0; i < 10; i++) {
- if (msp34xx_sleep(msp,100))
- goto restart;
-
- /* check results */
- val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e);
- if (val < 0x07ff) {
- std = val;
- break;
- }
- msp3400_dbg("detection still in progress\n");
- }
- if (0x01 == std) {
- msp3400_dbg("detection still in progress after 10 tries. giving up.\n");
- continue;
- }
-
- unmute:
- msp3400_dbg("current mode: %s (0x%04x)\n",
- msp34xx_standard_mode_name(std), std);
-
- /* unmute: dispatch sound to scart output, set scart volume */
- msp3400_dbg("unmute\n");
-
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
-
- /* restore ACB */
- if (msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x13, /* ACB */
- msp->acb))
- return -1;
-
- msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode);
- }
- msp3400_dbg("thread: exit\n");
- return 0;
-}
-
-/* set the same 'source' for the loudspeaker, scart and quasi-peak detector
- * the value for source is the same as bit 15:8 of DFP registers 0x08,
- * 0x0a and 0x0c: 0=mono, 1=stereo or A|B, 2=SCART, 3=stereo or A, 4=stereo or B
- *
- * this function replaces msp3400c_setstereo
- */
-static void msp34xxg_set_source(struct i2c_client *client, int source)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- /* fix matrix mode to stereo and let the msp choose what
- * to output according to 'source', as recommended
- * for MONO (source==0) downmixing set bit[7:0] to 0x30
- */
- int value = (source&0x07)<<8|(source==0 ? 0x30:0x20);
- msp3400_dbg("set source to %d (0x%x)\n", source, value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x08, /* Loudspeaker Output */
- value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x0a, /* SCART1 DA Output */
- value);
- msp3400c_write(client,
- I2C_MSP3400C_DFP,
- 0x0c, /* Quasi-peak detector */
- value);
- /*
- * set identification threshold. Personally, I
- * I set it to a higher value that the default
- * of 0x190 to ignore noisy stereo signals.
- * this needs tuning. (recommended range 0x00a0-0x03c0)
- * 0x7f0 = forced mono mode
- */
- msp3400c_write(client,
- I2C_MSP3400C_DEM,
- 0x22, /* a2 threshold for stereo/bilingual */
- stereo_threshold);
- msp->source=source;
-}
-
-static void msp34xxg_detect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- int status = msp3400c_read(client,
- I2C_MSP3400C_DEM,
- 0x0200 /* STATUS */);
- int is_bilingual = status&0x100;
- int is_stereo = status&0x40;
-
- msp->rxsubchans = 0;
- if (is_stereo)
- msp->rxsubchans |= V4L2_TUNER_SUB_STEREO;
- else
- msp->rxsubchans |= V4L2_TUNER_SUB_MONO;
- if (is_bilingual) {
- msp->rxsubchans |= V4L2_TUNER_SUB_LANG1|V4L2_TUNER_SUB_LANG2;
- /* I'm supposed to check whether it's SAP or not
- * and set only LANG2/SAP in this case. Yet, the MSP
- * does a lot of work to hide this and handle everything
- * the same way. I don't want to work around it so unless
- * this is a problem, I'll handle SAP just like lang1/lang2.
- */
- }
- msp3400_dbg("status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
- status, is_stereo, is_bilingual, msp->rxsubchans);
-}
-
-static void msp34xxg_set_audmode(struct i2c_client *client, int audmode)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int source;
-
- switch (audmode) {
- case V4L2_TUNER_MODE_MONO:
- source=0; /* mono only */
- break;
- case V4L2_TUNER_MODE_STEREO:
- source=1; /* stereo or A|B, see comment in msp34xxg_get_v4l2_stereo() */
- /* problem: that could also mean 2 (scart input) */
- break;
- case V4L2_TUNER_MODE_LANG1:
- source=3; /* stereo or A */
- break;
- case V4L2_TUNER_MODE_LANG2:
- source=4; /* stereo or B */
- break;
- default:
- audmode = 0;
- source = 1;
- break;
- }
- msp->audmode = audmode;
- msp34xxg_set_source(client, source);
-}
-
-
-/* ----------------------------------------------------------------------- */
-
-static int msp_attach(struct i2c_adapter *adap, int addr, int kind);
-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, pm_message_t state);
-static int msp_resume(struct device * dev);
-
-static void msp_wake_thread(struct i2c_client *client);
-
-static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "msp3400",
- .id = I2C_DRIVERID_MSP3400,
- .flags = I2C_DF_NOTIFY,
- .attach_adapter = msp_probe,
- .detach_client = msp_detach,
- .command = msp_command,
- .driver = {
- .suspend = msp_suspend,
- .resume = msp_resume,
- },
-};
-
-static struct i2c_client client_template =
-{
- .name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
-};
-
-static int msp_attach(struct i2c_adapter *adap, int addr, int kind)
-{
- struct msp3400c *msp;
- struct i2c_client *client = &client_template;
- int (*thread_func)(void *data) = NULL;
- int i;
-
- client_template.adapter = adap;
- client_template.addr = addr;
-
- if (-1 == msp3400c_reset(&client_template)) {
- msp3400_dbg("no chip found\n");
- return -1;
- }
-
- if (NULL == (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
- return -ENOMEM;
- memcpy(client,&client_template,sizeof(struct i2c_client));
- if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) {
- kfree(client);
- return -ENOMEM;
- }
-
- memset(msp,0,sizeof(struct msp3400c));
- msp->norm = VIDEO_MODE_NTSC;
- msp->left = 58880; /* 0db gain */
- msp->right = 58880; /* 0db gain */
- msp->bass = 32768;
- msp->treble = 32768;
- msp->input = -1;
- msp->muted = 0;
- msp->i2s_mode = 0;
- for (i = 0; i < DFP_COUNT; i++)
- msp->dfp_regs[i] = -1;
-
- i2c_set_clientdata(client, msp);
- init_waitqueue_head(&msp->wq);
-
- if (-1 == msp3400c_reset(client)) {
- kfree(msp);
- kfree(client);
- msp3400_dbg("no chip found\n");
- return -1;
- }
-
- msp->rev1 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1e);
- if (-1 != msp->rev1)
- msp->rev2 = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1f);
- if ((-1 == msp->rev1) || (0 == msp->rev1 && 0 == msp->rev2)) {
- kfree(msp);
- kfree(client);
- msp3400_dbg("error while reading chip version\n");
- return -1;
- }
- msp3400_dbg("rev1=0x%04x, rev2=0x%04x\n", msp->rev1, msp->rev2);
-
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
-
- snprintf(client->name, sizeof(client->name), "MSP%c4%02d%c-%c%d",
- ((msp->rev1>>4)&0x0f) + '3',
- (msp->rev2>>8)&0xff, (msp->rev1&0x0f)+'@',
- ((msp->rev1>>8)&0xff)+'@', msp->rev2&0x1f);
-
- msp->opmode = opmode;
- if (OPMODE_AUTO == msp->opmode) {
- if (HAVE_SIMPLER(msp))
- msp->opmode = OPMODE_SIMPLER;
- else if (HAVE_SIMPLE(msp))
- msp->opmode = OPMODE_SIMPLE;
- else
- msp->opmode = OPMODE_MANUAL;
- }
-
- /* hello world :-) */
- msp3400_info("chip=%s", client->name);
- if (HAVE_NICAM(msp))
- printk(" +nicam");
- if (HAVE_SIMPLE(msp))
- printk(" +simple");
- if (HAVE_SIMPLER(msp))
- printk(" +simpler");
- if (HAVE_RADIO(msp))
- printk(" +radio");
-
- /* version-specific initialization */
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- printk(" mode=manual");
- thread_func = msp3400c_thread;
- break;
- case OPMODE_SIMPLE:
- printk(" mode=simple");
- thread_func = msp3410d_thread;
- break;
- case OPMODE_SIMPLER:
- printk(" mode=simpler");
- thread_func = msp34xxg_thread;
- break;
- }
- printk("\n");
-
- /* startup control thread if needed */
- if (thread_func) {
- msp->kthread = kthread_run(thread_func, client, "msp34xx");
-
- if (NULL == msp->kthread)
- msp3400_warn("kernel_thread() failed\n");
- msp_wake_thread(client);
- }
-
- /* done */
- i2c_attach_client(client);
-
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (NULL == msps[i]) {
- msps[i] = client;
- break;
- }
- }
-
- return 0;
-}
-
-static int msp_detach(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- int i;
-
- /* shutdown control thread */
- if (msp->kthread) {
- msp->restart = 1;
- kthread_stop(msp->kthread);
- }
- msp3400c_reset(client);
-
- /* update our own array */
- for (i = 0; i < MSP3400_MAX; i++) {
- if (client == msps[i]) {
- msps[i] = NULL;
- break;
- }
- }
-
- i2c_detach_client(client);
-
- kfree(msp);
- kfree(client);
- return 0;
-}
-
-static int msp_probe(struct i2c_adapter *adap)
-{
- if (adap->class & I2C_CLASS_TV_ANALOG)
- return i2c_probe(adap, &addr_data, msp_attach);
- return 0;
-}
-
-static void msp_wake_thread(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- if (NULL == msp->kthread)
- return;
- msp3400c_setvolume(client,msp->muted,0,0);
- msp->watch_stereo = 0;
- msp->restart = 1;
- wake_up_interruptible(&msp->wq);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int mode_v4l2_to_v4l1(int rxsubchans)
-{
- int mode = 0;
-
- if (rxsubchans & V4L2_TUNER_SUB_STEREO)
- mode |= VIDEO_SOUND_STEREO;
- if (rxsubchans & V4L2_TUNER_SUB_LANG2)
- mode |= VIDEO_SOUND_LANG2;
- if (rxsubchans & V4L2_TUNER_SUB_LANG1)
- mode |= VIDEO_SOUND_LANG1;
- if (0 == mode)
- mode |= VIDEO_SOUND_MONO;
- return mode;
-}
-
-static int mode_v4l1_to_v4l2(int mode)
-{
- if (mode & VIDEO_SOUND_STEREO)
- return V4L2_TUNER_MODE_STEREO;
- if (mode & VIDEO_SOUND_LANG2)
- return V4L2_TUNER_MODE_LANG2;
- if (mode & VIDEO_SOUND_LANG1)
- return V4L2_TUNER_MODE_LANG1;
- return V4L2_TUNER_MODE_MONO;
-}
-
-static void msp_any_detect_stereo(struct i2c_client *client)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- case OPMODE_SIMPLE:
- autodetect_stereo(client);
- break;
- case OPMODE_SIMPLER:
- msp34xxg_detect_stereo(client);
- break;
- }
-}
-
-static void msp_any_set_audmode(struct i2c_client *client, int audmode)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
-
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- case OPMODE_SIMPLE:
- msp->watch_stereo = 0;
- msp3400c_setstereo(client, audmode);
- break;
- case OPMODE_SIMPLER:
- msp34xxg_set_audmode(client, audmode);
- break;
- }
-}
-
-
-static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
- struct msp3400c *msp = i2c_get_clientdata(client);
- __u16 *sarg = arg;
- int scart = 0;
-
- switch (cmd) {
-
- case AUDC_SET_INPUT:
- msp3400_dbg("AUDC_SET_INPUT(%d)\n",*sarg);
-
- if (*sarg == msp->input)
- break;
- msp->input = *sarg;
- switch (*sarg) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- msp->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- msp->mode = -1;
- break;
- default:
- if (*sarg & AUDIO_MUTE)
- msp3400c_set_scart(client,SCART_MUTE,0);
- break;
- }
- if (scart) {
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp3400c_set_scart(client,scart,0);
- msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
- if (msp->opmode != OPMODE_SIMPLER)
- msp3400c_setstereo(client, msp->audmode);
- }
- msp_wake_thread(client);
- break;
-
- case AUDC_SET_RADIO:
- msp3400_dbg("AUDC_SET_RADIO\n");
- msp->norm = VIDEO_MODE_RADIO;
- msp3400_dbg("switching to radio mode\n");
- msp->watch_stereo = 0;
- switch (msp->opmode) {
- case OPMODE_MANUAL:
- /* set msp3400 to FM radio mode */
- msp3400c_setmode(client,MSP_MODE_FM_RADIO);
- msp3400c_setcarrier(client, MSP_CARRIER(10.7),
- MSP_CARRIER(10.7));
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- break;
- case OPMODE_SIMPLE:
- case OPMODE_SIMPLER:
- /* the thread will do for us */
- msp_wake_thread(client);
- break;
- }
- break;
- /* work-in-progress: hook to control the DFP registers */
- case MSP_SET_DFPREG:
- {
- struct msp_dfpreg *r = arg;
- int i;
-
- if (r->reg < 0 || r->reg >= DFP_COUNT)
- return -EINVAL;
- for (i = 0; i < sizeof(bl_dfp) / sizeof(int); i++)
- if (r->reg == bl_dfp[i])
- return -EINVAL;
- msp->dfp_regs[r->reg] = r->value;
- msp3400c_write(client, I2C_MSP3400C_DFP, r->reg, r->value);
- return 0;
- }
- case MSP_GET_DFPREG:
- {
- struct msp_dfpreg *r = arg;
-
- if (r->reg < 0 || r->reg >= DFP_COUNT)
- return -EINVAL;
- r->value = msp3400c_read(client, I2C_MSP3400C_DFP, r->reg);
- return 0;
- }
-
- /* --- v4l ioctls --- */
- /* take care: bttv does userspace copying, we'll get a
- kernel pointer here... */
- case VIDIOCGAUDIO:
- {
- struct video_audio *va = arg;
-
- msp3400_dbg("VIDIOCGAUDIO\n");
- va->flags |= VIDEO_AUDIO_VOLUME |
- VIDEO_AUDIO_BASS |
- VIDEO_AUDIO_TREBLE |
- VIDEO_AUDIO_MUTABLE;
- if (msp->muted)
- va->flags |= VIDEO_AUDIO_MUTE;
-
- if (msp->muted)
- va->flags |= VIDEO_AUDIO_MUTE;
- va->volume = MAX(msp->left, msp->right);
- va->balance = (32768 * MIN(msp->left, msp->right)) /
- (va->volume ? va->volume : 1);
- va->balance = (msp->left < msp->right) ?
- (65535 - va->balance) : va->balance;
- if (0 == va->volume)
- va->balance = 32768;
- va->bass = msp->bass;
- va->treble = msp->treble;
-
- msp_any_detect_stereo(client);
- va->mode = mode_v4l2_to_v4l1(msp->rxsubchans);
- break;
- }
- case VIDIOCSAUDIO:
- {
- struct video_audio *va = arg;
-
- msp3400_dbg("VIDIOCSAUDIO\n");
- msp->muted = (va->flags & VIDEO_AUDIO_MUTE);
- msp->left = (MIN(65536 - va->balance, 32768) *
- va->volume) / 32768;
- msp->right = (MIN(va->balance, 32768) * va->volume) / 32768;
- msp->bass = va->bass;
- msp->treble = va->treble;
- msp3400_dbg("VIDIOCSAUDIO setting va->volume to %d\n",
- va->volume);
- msp3400_dbg("VIDIOCSAUDIO setting va->balance to %d\n",
- va->balance);
- msp3400_dbg("VIDIOCSAUDIO setting va->flags to %d\n",
- va->flags);
- msp3400_dbg("VIDIOCSAUDIO setting msp->left to %d\n",
- msp->left);
- msp3400_dbg("VIDIOCSAUDIO setting msp->right to %d\n",
- msp->right);
- msp3400_dbg("VIDIOCSAUDIO setting msp->bass to %d\n",
- msp->bass);
- msp3400_dbg("VIDIOCSAUDIO setting msp->treble to %d\n",
- msp->treble);
- msp3400_dbg("VIDIOCSAUDIO setting msp->mode to %d\n",
- msp->mode);
- msp3400c_setvolume(client, msp->muted, msp->left, msp->right);
- msp3400c_setbass(client, msp->bass);
- msp3400c_settreble(client, msp->treble);
-
- if (va->mode != 0 && msp->norm != VIDEO_MODE_RADIO)
- msp_any_set_audmode(client,mode_v4l1_to_v4l2(va->mode));
- break;
- }
-
- case VIDIOCSCHAN:
- {
- struct video_channel *vc = arg;
-
- msp3400_dbg("VIDIOCSCHAN (norm=%d)\n",vc->norm);
- msp->norm = vc->norm;
- msp_wake_thread(client);
- break;
- }
-
- case VIDIOCSFREQ:
- case VIDIOC_S_FREQUENCY:
- {
- /* new channel -- kick audio carrier scan */
- msp3400_dbg("VIDIOCSFREQ\n");
- msp_wake_thread(client);
- break;
- }
-
- /* msp34xx specific */
- case MSP_SET_MATRIX:
- {
- struct msp_matrix *mspm = arg;
-
- msp3400_dbg("MSP_SET_MATRIX\n");
- msp3400c_set_scart(client, mspm->input, mspm->output);
- break;
- }
-
- /* --- v4l2 ioctls --- */
- case VIDIOC_S_STD:
- {
- v4l2_std_id *id = arg;
-
- /*FIXME: use V4L2 mode flags on msp3400 instead of V4L1*/
- if (*id & V4L2_STD_PAL) {
- msp->norm=VIDEO_MODE_PAL;
- } else if (*id & V4L2_STD_SECAM) {
- msp->norm=VIDEO_MODE_SECAM;
- } else {
- msp->norm=VIDEO_MODE_NTSC;
- }
-
- msp_wake_thread(client);
- return 0;
- }
-
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *i = arg;
-
- if (i->index != 0)
- return -EINVAL;
-
- i->type = V4L2_INPUT_TYPE_TUNER;
- switch (i->index) {
- case AUDIO_RADIO:
- strcpy(i->name,"Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(i->name,"Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(i->name,"Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(i->name,"Television");
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
-
- case VIDIOC_G_AUDIO:
- {
- struct v4l2_audio *a = arg;
-
- memset(a,0,sizeof(*a));
-
- switch (a->index) {
- case AUDIO_RADIO:
- strcpy(a->name,"Radio");
- break;
- case AUDIO_EXTERN_1:
- strcpy(a->name,"Extern 1");
- break;
- case AUDIO_EXTERN_2:
- strcpy(a->name,"Extern 2");
- break;
- case AUDIO_TUNER:
- strcpy(a->name,"Television");
- break;
- default:
- return -EINVAL;
- }
-
- msp_any_detect_stereo(client);
- if (msp->audmode == V4L2_TUNER_MODE_STEREO) {
- a->capability=V4L2_AUDCAP_STEREO;
- }
-
- break;
- }
- case VIDIOC_S_AUDIO:
- {
- struct v4l2_audio *sarg = arg;
-
- switch (sarg->index) {
- case AUDIO_RADIO:
- /* Hauppauge uses IN2 for the radio */
- msp->mode = MSP_MODE_FM_RADIO;
- scart = SCART_IN2;
- break;
- case AUDIO_EXTERN_1:
- /* IN1 is often used for external input ... */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN1;
- break;
- case AUDIO_EXTERN_2:
- /* ... sometimes it is IN2 through ;) */
- msp->mode = MSP_MODE_EXTERN;
- scart = SCART_IN2;
- break;
- case AUDIO_TUNER:
- msp->mode = -1;
- break;
- }
- if (scart) {
- msp->rxsubchans = V4L2_TUNER_SUB_STEREO;
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- msp3400c_set_scart(client,scart,0);
- msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900);
- }
- if (sarg->capability==V4L2_AUDCAP_STEREO) {
- msp->audmode = V4L2_TUNER_MODE_STEREO;
- } else {
- msp->audmode &= ~V4L2_TUNER_MODE_STEREO;
- }
- msp_any_set_audmode(client, msp->audmode);
- msp_wake_thread(client);
- break;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *vt = arg;
-
- msp_any_detect_stereo(client);
- vt->audmode = msp->audmode;
- vt->rxsubchans = msp->rxsubchans;
- vt->capability = V4L2_TUNER_CAP_STEREO |
- V4L2_TUNER_CAP_LANG1|
- V4L2_TUNER_CAP_LANG2;
- break;
- }
- case VIDIOC_S_TUNER:
- {
- struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
-
- /* only set audmode */
- if (vt->audmode != -1 && vt->audmode != 0)
- msp_any_set_audmode(client, vt->audmode);
- break;
- }
-
- case VIDIOC_G_AUDOUT:
- {
- struct v4l2_audioout *a=(struct v4l2_audioout *)arg;
- int idx=a->index;
-
- memset(a,0,sizeof(*a));
-
- switch (idx) {
- case 0:
- strcpy(a->name,"Scart1 Out");
- break;
- case 1:
- strcpy(a->name,"Scart2 Out");
- break;
- case 2:
- strcpy(a->name,"I2S Out");
- break;
- default:
- return -EINVAL;
- }
- break;
-
- }
- case VIDIOC_S_AUDOUT:
- {
- struct v4l2_audioout *a=(struct v4l2_audioout *)arg;
-
- if (a->index<0||a->index>2)
- return -EINVAL;
-
- if (a->index==2) {
- if (a->mode == V4L2_AUDMODE_32BITS)
- msp->i2s_mode=1;
- else
- msp->i2s_mode=0;
- }
- msp3400_dbg("Setting audio out on msp34xx to input %i, mode %i\n",
- a->index,msp->i2s_mode);
- msp3400c_set_scart(client,msp->in_scart,a->index+1);
-
- break;
- }
-
- default:
- /* nothing */
- break;
- }
- return 0;
-}
-
-static int msp_suspend(struct device * dev, pm_message_t state)
-{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-
- msp3400_dbg("msp34xx: suspend\n");
- msp3400c_reset(client);
- return 0;
-}
-
-static int msp_resume(struct device * dev)
-{
- struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-
- msp3400_dbg("msp34xx: resume\n");
- msp_wake_thread(client);
- return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int __init msp3400_init_module(void)
-{
- return i2c_add_driver(&driver);
-}
-
-static void __exit msp3400_cleanup_module(void)
-{
- i2c_del_driver(&driver);
-}
-
-module_init(msp3400_init_module);
-module_exit(msp3400_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/msp3400.h b/drivers/media/video/msp3400.h
index 2d9ff40f0b09..a9ac57d0700b 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -6,21 +6,19 @@
/* ---------------------------------------------------------------------- */
-struct msp_dfpreg {
- int reg;
- int value;
-};
-
-struct msp_matrix {
- int input;
- int output;
-};
-
-#define MSP_SET_DFPREG _IOW('m',15,struct msp_dfpreg)
-#define MSP_GET_DFPREG _IOW('m',16,struct msp_dfpreg)
+/* This macro is allowed for *constants* only, gcc must calculate it
+ at compile time. Remember -- no floats in kernel mode */
+#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24)))
-/* ioctl for MSP_SET_MATRIX will have to be registered */
-#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
+#define MSP_MODE_AM_DETECT 0
+#define MSP_MODE_FM_RADIO 2
+#define MSP_MODE_FM_TERRA 3
+#define MSP_MODE_FM_SAT 4
+#define MSP_MODE_FM_NICAM1 5
+#define MSP_MODE_FM_NICAM2 6
+#define MSP_MODE_AM_NICAM 7
+#define MSP_MODE_BTSC 8
+#define MSP_MODE_EXTERN 9
#define SCART_MASK 0
#define SCART_IN1 1
@@ -36,4 +34,84 @@ struct msp_matrix {
#define SCART1_OUT 1
#define SCART2_OUT 2
+#define OPMODE_AUTO -1
+#define OPMODE_MANUAL 0
+#define OPMODE_AUTODETECT 1 /* use autodetect (>= msp3410 only) */
+#define OPMODE_AUTOSELECT 2 /* use autodetect & autoselect (>= msp34xxG) */
+
+/* module parameters */
+extern int msp_debug;
+extern int msp_once;
+extern int msp_amsound;
+extern int msp_standard;
+extern int msp_dolby;
+extern int msp_stereo_thresh;
+
+struct msp_state {
+ int rev1, rev2;
+ u8 has_nicam;
+ u8 has_radio;
+ u8 has_headphones;
+ u8 has_ntsc_jp_d_k3;
+ u8 has_scart4;
+ u8 has_scart23_in_scart2_out;
+ u8 has_scart2_out_volume;
+ u8 has_i2s_conf;
+ u8 has_subwoofer;
+ u8 has_sound_processing;
+ u8 has_virtual_dolby_surround;
+ u8 has_dolby_pro_logic;
+
+ int radio;
+ int opmode;
+ int std;
+ int mode;
+ v4l2_std_id v4l2_std;
+ int nicam_on;
+ int acb;
+ int in_scart;
+ int i2s_mode;
+ int main, second; /* sound carrier */
+ int input;
+ int source; /* see msp34xxg_set_source */
+
+ /* v4l2 */
+ int audmode;
+ int rxsubchans;
+
+ int volume, muted;
+ int balance, loudness;
+ int bass, treble;
+
+ /* thread */
+ struct task_struct *kthread;
+ wait_queue_head_t wq;
+ int restart:1;
+ int watch_stereo:1;
+};
+
+/* msp3400-driver.c */
+int msp_write_dem(struct i2c_client *client, int addr, int val);
+int msp_write_dsp(struct i2c_client *client, int addr, int val);
+int msp_read_dem(struct i2c_client *client, int addr);
+int msp_read_dsp(struct i2c_client *client, int addr);
+int msp_reset(struct i2c_client *client);
+void msp_set_scart(struct i2c_client *client, int in, int out);
+void msp_set_mute(struct i2c_client *client);
+void msp_set_audio(struct i2c_client *client);
+int msp_modus(struct i2c_client *client);
+int msp_sleep(struct msp_state *state, int timeout);
+
+/* msp3400-kthreads.c */
+const char *msp_standard_std_name(int std);
+void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2);
+void msp3400c_setmode(struct i2c_client *client, int type);
+void msp3400c_setstereo(struct i2c_client *client, int mode);
+int autodetect_stereo(struct i2c_client *client);
+int msp3400c_thread(void *data);
+int msp3410d_thread(void *data);
+int msp34xxg_thread(void *data);
+void msp34xxg_detect_stereo(struct i2c_client *client);
+void msp34xxg_set_audmode(struct i2c_client *client, int audmode);
+
#endif /* MSP3400_H */
diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
index 2180018f06de..c7c9f3f8715c 100644
--- a/drivers/media/video/mt20xx.c
+++ b/drivers/media/video/mt20xx.c
@@ -20,6 +20,9 @@ module_param(tv_antenna, int, 0644);
static unsigned int radio_antenna = 0;
module_param(radio_antenna, int, 0644);
+/* from tuner-core.c */
+extern int tuner_debug;
+
/* ---------------------------------------------------------------------- */
#define MT2032 0x04
@@ -350,8 +353,8 @@ static int mt2032_init(struct i2c_client *c)
} while (xok != 1 );
t->xogc=xogc;
- t->tv_freq = mt2032_set_tv_freq;
- t->radio_freq = mt2032_set_radio_freq;
+ t->set_tv_freq = mt2032_set_tv_freq;
+ t->set_radio_freq = mt2032_set_radio_freq;
return(1);
}
@@ -478,8 +481,8 @@ static int mt2050_init(struct i2c_client *c)
i2c_master_recv(c,buf,1);
tuner_dbg("mt2050: sro is %x\n",buf[0]);
- t->tv_freq = mt2050_set_tv_freq;
- t->radio_freq = mt2050_set_radio_freq;
+ t->set_tv_freq = mt2050_set_tv_freq;
+ t->set_radio_freq = mt2050_set_radio_freq;
return 0;
}
@@ -491,9 +494,16 @@ int microtune_init(struct i2c_client *c)
int company_code;
memset(buf,0,sizeof(buf));
- t->tv_freq = NULL;
- t->radio_freq = NULL;
+ t->set_tv_freq = NULL;
+ t->set_radio_freq = NULL;
t->standby = NULL;
+ if (t->std & V4L2_STD_525_60) {
+ tuner_dbg("pinnacle ntsc\n");
+ t->radio_if2 = 41300 * 1000;
+ } else {
+ tuner_dbg("pinnacle pal\n");
+ t->radio_if2 = 33300 * 1000;
+ }
name = "unknown";
i2c_master_send(c,buf,1);
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index d04793fb80fc..8416ceff524b 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -26,6 +26,7 @@
#include <media/saa7146_vv.h>
#include <media/tuner.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#include "mxb.h"
#include "tea6415c.h"
@@ -176,12 +177,11 @@ static int mxb_probe(struct saa7146_dev* dev)
return -ENODEV;
}
- mxb = (struct mxb*)kmalloc(sizeof(struct mxb), GFP_KERNEL);
+ mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
if( NULL == mxb ) {
DEB_D(("not enough kernel memory.\n"));
return -ENOMEM;
}
- memset(mxb, 0x0, sizeof(struct mxb));
mxb->i2c_adapter = (struct i2c_adapter) {
.class = I2C_CLASS_TV_ANALOG,
diff --git a/drivers/media/video/ovcamchip/ov6x20.c b/drivers/media/video/ovcamchip/ov6x20.c
index b3f4d266cede..c04130dab127 100644
--- a/drivers/media/video/ovcamchip/ov6x20.c
+++ b/drivers/media/video/ovcamchip/ov6x20.c
@@ -178,10 +178,9 @@ static int ov6x20_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov6x30.c b/drivers/media/video/ovcamchip/ov6x30.c
index 6eab458ab792..73b94f51a85a 100644
--- a/drivers/media/video/ovcamchip/ov6x30.c
+++ b/drivers/media/video/ovcamchip/ov6x30.c
@@ -141,10 +141,9 @@ static int ov6x30_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov76be.c b/drivers/media/video/ovcamchip/ov76be.c
index 29bbdc05e3b6..11f6be924d8b 100644
--- a/drivers/media/video/ovcamchip/ov76be.c
+++ b/drivers/media/video/ovcamchip/ov76be.c
@@ -105,10 +105,9 @@ static int ov76be_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov7x10.c b/drivers/media/video/ovcamchip/ov7x10.c
index 6c383d4b14fa..5206e7913924 100644
--- a/drivers/media/video/ovcamchip/ov7x10.c
+++ b/drivers/media/video/ovcamchip/ov7x10.c
@@ -115,10 +115,9 @@ static int ov7x10_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = 1;
diff --git a/drivers/media/video/ovcamchip/ov7x20.c b/drivers/media/video/ovcamchip/ov7x20.c
index 3c8c48f338ba..8e26ae338f31 100644
--- a/drivers/media/video/ovcamchip/ov7x20.c
+++ b/drivers/media/video/ovcamchip/ov7x20.c
@@ -232,10 +232,9 @@ static int ov7x20_init(struct i2c_client *c)
if (rc < 0)
return rc;
- ov->spriv = s = kmalloc(sizeof *s, GFP_KERNEL);
+ ov->spriv = s = kzalloc(sizeof *s, GFP_KERNEL);
if (!s)
return -ENOMEM;
- memset(s, 0, sizeof *s);
s->auto_brt = 1;
s->auto_exp = DFL_AUTO_EXP;
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 2de34ebf0673..e76b53d5909c 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -316,12 +316,11 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
c->adapter = adap;
strcpy(c->name, "OV????");
- ov = kmalloc(sizeof *ov, GFP_KERNEL);
+ ov = kzalloc(sizeof *ov, GFP_KERNEL);
if (!ov) {
rc = -ENOMEM;
goto no_ov;
}
- memset(ov, 0, sizeof *ov);
i2c_set_clientdata(c, ov);
rc = ovcamchip_detect(c);
@@ -410,11 +409,11 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "ovcamchip",
+ .driver = {
+ .name = "ovcamchip",
+ },
.id = I2C_DRIVERID_OVCAMCHIP,
.class = I2C_CLASS_CAM_DIGITAL,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = ovcamchip_attach,
.detach_client = ovcamchip_detach,
.command = ovcamchip_command,
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index b19c33434eaf..f3fc361bec97 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -76,9 +76,9 @@ static volatile struct planb_registers *planb_regs;
static int def_norm = PLANB_DEF_NORM; /* default norm */
static int video_nr = -1;
-MODULE_PARM(def_norm, "i");
+module_param(def_norm, int, 0);
MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
-MODULE_PARM(video_nr,"i");
+module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 2504207b2e3d..9e6448639480 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -883,6 +883,7 @@ static struct file_operations pms_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = pms_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = pms_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index b8054da31ffd..2ce010201308 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -83,13 +83,12 @@ static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL)
{
kfree(client);
return -ENOMEM;
}
- memset(t, 0, sizeof(*t));
strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
init_MUTEX(&t->lock);
@@ -151,25 +150,18 @@ static int saa5246a_detach(struct i2c_client *client)
return 0;
}
-static int saa5246a_command(struct i2c_client *device, unsigned int cmd,
- void *arg)
-{
- return -EINVAL;
-}
-
/*
* I2C interfaces
*/
static struct i2c_driver i2c_driver_videotext =
{
- .owner = THIS_MODULE,
- .name = IF_NAME, /* name */
+ .driver = {
+ .name = IF_NAME, /* name */
+ },
.id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa5246a_probe,
.detach_client = saa5246a_detach,
- .command = saa5246a_command
};
static struct i2c_client client_template = {
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 7ffa2e9a9bf3..5694eb58c3a1 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -151,13 +151,12 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
memcpy(client, &client_template, sizeof(*client));
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
if(t==NULL)
{
kfree(client);
return -ENOMEM;
}
- memset(t, 0, sizeof(*t));
strlcpy(client->name, IF_NAME, I2C_NAME_SIZE);
init_MUTEX(&t->lock);
@@ -165,7 +164,7 @@ static int saa5249_attach(struct i2c_adapter *adap, int addr, int kind)
* Now create a video4linux device
*/
- vd = (struct video_device *)kmalloc(sizeof(struct video_device), GFP_KERNEL);
+ vd = kmalloc(sizeof(struct video_device), GFP_KERNEL);
if(vd==NULL)
{
kfree(t);
@@ -226,23 +225,16 @@ static int saa5249_detach(struct i2c_client *client)
return 0;
}
-static int saa5249_command(struct i2c_client *device,
- unsigned int cmd, void *arg)
-{
- return -EINVAL;
-}
-
/* new I2C driver support */
static struct i2c_driver i2c_driver_videotext =
{
- .owner = THIS_MODULE,
- .name = IF_NAME, /* name */
+ .driver = {
+ .name = IF_NAME, /* name */
+ },
.id = I2C_DRIVERID_SAA5249, /* in i2c.h */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa5249_probe,
.detach_client = saa5249_detach,
- .command = saa5249_command
};
static struct i2c_client client_template = {
@@ -709,6 +701,7 @@ static struct file_operations saa_fops = {
.open = saa5249_open,
.release = saa5249_release,
.ioctl = saa5249_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 923322503e8f..d17395c4f55c 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -50,15 +50,15 @@ static unsigned int rbds = 0;
static unsigned int plvl = 0;
static unsigned int bufblocks = 100;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
-MODULE_PARM(xtal, "i");
+module_param(xtal, int, 0);
MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
-MODULE_PARM(rbds, "i");
+module_param(rbds, int, 0);
MODULE_PARM_DESC(rbds, "select mode, 0=RDS, 1=RBDS, default 0");
-MODULE_PARM(plvl, "i");
+module_param(plvl, int, 0);
MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
-MODULE_PARM(bufblocks, "i");
+module_param(bufblocks, int, 0);
MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
@@ -427,18 +427,8 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind)
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_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, saa6588_attach);
- break;
- }
-#endif
return 0;
}
@@ -495,10 +485,10 @@ static int saa6588_command(struct i2c_client *client, unsigned int cmd,
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c saa6588 driver",
+ .driver = {
+ .name = "saa6588",
+ },
.id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa6588_probe,
.detach_client = saa6588_detach,
.command = saa6588_command,
@@ -506,7 +496,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template = {
.name = "saa6588",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index e116bdbed310..7bb85a7b326e 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -494,22 +494,19 @@ saa7110_detect_client (struct i2c_adapter *adapter,
I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7110;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
if (decoder == 0) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7110));
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
@@ -587,11 +584,11 @@ saa7110_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7110 = {
- .owner = THIS_MODULE,
- .name = "saa7110",
+ .driver = {
+ .name = "saa7110",
+ },
.id = I2C_DRIVERID_SAA7110,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7110_attach_adapter,
.detach_client = saa7110_detach_client,
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index fe8a5e453969..8c06592b37ff 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -511,22 +511,19 @@ saa7111_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7111;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7111));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
@@ -590,11 +587,11 @@ saa7111_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7111 = {
- .owner = THIS_MODULE,
- .name = "saa7111",
+ .driver = {
+ .name = "saa7111",
+ },
.id = I2C_DRIVERID_SAA7111A,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7111_attach_adapter,
.detach_client = saa7111_detach_client,
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index d9f50e2f7b92..fd0a4b4ef014 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -852,22 +852,19 @@ saa7114_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7114;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa7114), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa7114));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = -1;
decoder->enable = 1;
@@ -1204,11 +1201,11 @@ saa7114_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7114 = {
- .owner = THIS_MODULE,
- .name = "saa7114",
+ .driver = {
+ .name = "saa7114",
+ },
.id = I2C_DRIVERID_SAA7114,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7114_attach_adapter,
.detach_client = saa7114_detach_client,
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index e717e30d8187..048d000941c7 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -39,30 +39,18 @@
#include <linux/i2c.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
+#include <media/audiochip.h>
+#include <asm/div64.h>
MODULE_DESCRIPTION("Philips SAA7114/SAA7115 video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, Hans Verkuil");
MODULE_LICENSE("GPL");
static int debug = 0;
-module_param(debug, int, 0644);
+module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define saa7115_dbg(fmt,arg...) \
- do { \
- if (debug) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7115_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7115_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
@@ -72,12 +60,13 @@ struct saa7115_state {
v4l2_std_id std;
int input;
int enable;
+ int radio;
int bright;
int contrast;
int hue;
int sat;
enum v4l2_chip_ident ident;
- enum v4l2_audio_clock_freq audclk_freq;
+ u32 audclk_freq;
};
/* ----------------------------------------------------------------------- */
@@ -468,80 +457,6 @@ static const unsigned char saa7115_init_misc[] = {
0x00, 0x00
};
-/* ============== SAA7715 AUDIO settings ============= */
-
-/* 48.0 kHz */
-static const unsigned char saa7115_cfg_48_audio[] = {
- 0x34, 0xce,
- 0x35, 0xfb,
- 0x36, 0x30,
- 0x00, 0x00
-};
-
-/* 44.1 kHz */
-static const unsigned char saa7115_cfg_441_audio[] = {
- 0x34, 0xf2,
- 0x35, 0x00,
- 0x36, 0x2d,
- 0x00, 0x00
-};
-
-/* 32.0 kHz */
-static const unsigned char saa7115_cfg_32_audio[] = {
- 0x34, 0xdf,
- 0x35, 0xa7,
- 0x36, 0x20,
- 0x00, 0x00
-};
-
-/* 48.0 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_48_audio[] = {
- 0x30, 0xcd,
- 0x31, 0x20,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 48.0 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_48_audio[] = {
- 0x30, 0x00,
- 0x31, 0xc0,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 44.1 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_441_audio[] = {
- 0x30, 0xbc,
- 0x31, 0xdf,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
-/* 44.1 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_441_audio[] = {
- 0x30, 0x00,
- 0x31, 0x72,
- 0x32, 0x03,
- 0x00, 0x00
-};
-
-/* 32.0 kHz 60hz */
-static const unsigned char saa7115_cfg_60hz_32_audio[] = {
- 0x30, 0xde,
- 0x31, 0x15,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
-/* 32.0 kHz 50hz */
-static const unsigned char saa7115_cfg_50hz_32_audio[] = {
- 0x30, 0x00,
- 0x31, 0x80,
- 0x32, 0x02,
- 0x00, 0x00
-};
-
static int saa7115_odd_parity(u8 c)
{
c ^= (c >> 4);
@@ -626,40 +541,38 @@ static int saa7115_decode_wss(u8 * p)
}
-static int saa7115_set_audio_clock_freq(struct i2c_client *client, enum v4l2_audio_clock_freq freq)
+static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
{
struct saa7115_state *state = i2c_get_clientdata(client);
+ u32 acpf;
+ u32 acni;
+ u32 hz;
+ u64 f;
- saa7115_dbg("set audio clock freq: %d\n", freq);
- switch (freq) {
- case V4L2_AUDCLK_32_KHZ:
- saa7115_writeregs(client, saa7115_cfg_32_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_32_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_32_audio);
- }
- break;
- case V4L2_AUDCLK_441_KHZ:
- saa7115_writeregs(client, saa7115_cfg_441_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_441_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_441_audio);
- }
- break;
- case V4L2_AUDCLK_48_KHZ:
- saa7115_writeregs(client, saa7115_cfg_48_audio);
- if (state->std & V4L2_STD_525_60) {
- saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
- } else {
- saa7115_writeregs(client, saa7115_cfg_50hz_48_audio);
- }
- break;
- default:
- saa7115_dbg("invalid audio setting %d\n", freq);
- return -EINVAL;
- }
+ v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
+
+ /* sanity check */
+ if (freq < 32000 || freq > 48000)
+ return -EINVAL;
+
+ /* hz is the refresh rate times 100 */
+ hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
+ /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
+ acpf = (25600 * freq) / hz;
+ /* acni = (256 * freq * 2^23) / crystal_frequency =
+ (freq * 2^(8+23)) / crystal_frequency =
+ (freq << 31) / 32.11 MHz */
+ f = freq;
+ f = f << 31;
+ do_div(f, 32110000);
+ acni = f;
+
+ saa7115_write(client, 0x30, acpf & 0xff);
+ saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
+ saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
+ saa7115_write(client, 0x34, acni & 0xff);
+ saa7115_write(client, 0x35, (acni >> 8) & 0xff);
+ saa7115_write(client, 0x36, (acni >> 16) & 0x3f);
state->audclk_freq = freq;
return 0;
}
@@ -671,7 +584,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if (ctrl->value < 0 || ctrl->value > 255) {
- saa7115_err("invalid brightness setting %d\n", ctrl->value);
+ v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -681,7 +594,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_CONTRAST:
if (ctrl->value < 0 || ctrl->value > 127) {
- saa7115_err("invalid contrast setting %d\n", ctrl->value);
+ v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -691,7 +604,7 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_SATURATION:
if (ctrl->value < 0 || ctrl->value > 127) {
- saa7115_err("invalid saturation setting %d\n", ctrl->value);
+ v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
return -ERANGE;
}
@@ -701,13 +614,16 @@ static int saa7115_set_v4lctrl(struct i2c_client *client, struct v4l2_control *c
case V4L2_CID_HUE:
if (ctrl->value < -127 || ctrl->value > 127) {
- saa7115_err("invalid hue setting %d\n", ctrl->value);
+ v4l_err(client, "invalid hue setting %d\n", ctrl->value);
return -ERANGE;
}
state->hue = ctrl->value;
saa7115_write(client, 0x0d, state->hue);
break;
+
+ default:
+ return -EINVAL;
}
return 0;
@@ -742,12 +658,22 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
struct saa7115_state *state = i2c_get_clientdata(client);
int taskb = saa7115_read(client, 0x80) & 0x10;
+ /* Prevent unnecessary standard changes. During a standard
+ change the I-Port is temporarily disabled. Any devices
+ reading from that port can get confused.
+ Note that VIDIOC_S_STD is also used to switch from
+ radio to TV mode, so if a VIDIOC_S_STD is broadcast to
+ all I2C devices then you do not want to have an unwanted
+ side-effect here. */
+ if (std == state->std)
+ return;
+
// This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
if (std & V4L2_STD_525_60) {
- saa7115_dbg("decoder set standard 60 Hz\n");
+ v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
saa7115_writeregs(client, saa7115_cfg_60hz_video);
} else {
- saa7115_dbg("decoder set standard 50 Hz\n");
+ v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
saa7115_writeregs(client, saa7115_cfg_50hz_video);
}
@@ -772,24 +698,17 @@ static v4l2_std_id saa7115_get_v4lstd(struct i2c_client *client)
static void saa7115_log_status(struct i2c_client *client)
{
struct saa7115_state *state = i2c_get_clientdata(client);
- char *audfreq = "undefined";
int reg1e, reg1f;
int signalOk;
int vcr;
- switch (state->audclk_freq) {
- case V4L2_AUDCLK_32_KHZ: audfreq = "32 kHz"; break;
- case V4L2_AUDCLK_441_KHZ: audfreq = "44.1 kHz"; break;
- case V4L2_AUDCLK_48_KHZ: audfreq = "48 kHz"; break;
- }
-
- saa7115_info("Audio frequency: %s\n", audfreq);
+ v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq);
if (client->name[6] == '4') {
/* status for the saa7114 */
reg1f = saa7115_read(client, 0x1f);
signalOk = (reg1f & 0xc1) == 0x81;
- saa7115_info("Video signal: %s\n", signalOk ? "ok" : "bad");
- saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
+ v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad");
+ v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
return;
}
@@ -800,21 +719,26 @@ static void saa7115_log_status(struct i2c_client *client)
signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
vcr = !(reg1f & 0x10);
- saa7115_info("Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
- saa7115_info("Frequency: %s\n", (reg1f & 0x20) ? "60Hz" : "50Hz");
+ if (state->input >= 6) {
+ v4l_info(client, "Input: S-Video %d\n", state->input - 6);
+ } else {
+ v4l_info(client, "Input: Composite %d\n", state->input);
+ }
+ v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
+ v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
switch (reg1e & 0x03) {
case 1:
- saa7115_info("Detected format: NTSC\n");
+ v4l_info(client, "Detected format: NTSC\n");
break;
case 2:
- saa7115_info("Detected format: PAL\n");
+ v4l_info(client, "Detected format: PAL\n");
break;
case 3:
- saa7115_info("Detected format: SECAM\n");
+ v4l_info(client, "Detected format: SECAM\n");
break;
default:
- saa7115_info("Detected format: BW/No color\n");
+ v4l_info(client, "Detected format: BW/No color\n");
break;
}
}
@@ -939,7 +863,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
pix = &(fmt->fmt.pix);
- saa7115_dbg("decoder set size\n");
+ v4l_dbg(1, debug, client, "decoder set size\n");
/* FIXME need better bounds checking here */
if ((pix->width < 1) || (pix->width > 1440))
@@ -965,7 +889,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
HPSC = HPSC ? HPSC : 1;
HFSC = (int)((1024 * 720) / (HPSC * pix->width));
- saa7115_dbg("Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
+ v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
/* FIXME hardcodes to "Task B"
* write H prescaler integer */
saa7115_write(client, 0xd0, (u8) (HPSC & 0x3f));
@@ -979,10 +903,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
saa7115_write(client, 0xDD, (u8) ((HFSC >> 9) & 0xff));
} else {
if (is_50hz) {
- saa7115_dbg("Setting full 50hz width\n");
+ v4l_dbg(1, debug, client, "Setting full 50hz width\n");
saa7115_writeregs(client, saa7115_cfg_50hz_fullres_x);
} else {
- saa7115_dbg("Setting full 60hz width\n");
+ v4l_dbg(1, debug, client, "Setting full 60hz width\n");
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
}
}
@@ -991,7 +915,7 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
if (pix->height != Vsrc) {
VSCY = (int)((1024 * Vsrc) / pix->height);
- saa7115_dbg("Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
+ v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
/* Correct Contrast and Luminance */
saa7115_write(client, 0xd5, (u8) (64 * 1024 / VSCY));
@@ -1005,10 +929,10 @@ static int saa7115_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt
saa7115_write(client, 0xe3, (u8) ((VSCY >> 8) & 0xff));
} else {
if (is_50hz) {
- saa7115_dbg("Setting full 50Hz height\n");
+ v4l_dbg(1, debug, client, "Setting full 50Hz height\n");
saa7115_writeregs(client, saa7115_cfg_50hz_fullres_y);
} else {
- saa7115_dbg("Setting full 60hz height\n");
+ v4l_dbg(1, debug, client, "Setting full 60hz height\n");
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
}
}
@@ -1088,6 +1012,48 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
/* ============ SAA7115 AUDIO settings (end) ============= */
+static struct v4l2_queryctrl saa7115_qctrl[] = {
+ {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 128,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Saturation",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 64,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+};
+
+/* ----------------------------------------------------------------------- */
+
static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct saa7115_state *state = i2c_get_clientdata(client);
@@ -1102,16 +1068,18 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
return saa7115_get_v4lfmt(client, (struct v4l2_format *)arg);
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
- return saa7115_set_audio_clock_freq(client, *(enum v4l2_audio_clock_freq *)arg);
+ return saa7115_set_audio_clock_freq(client, *(u32 *)arg);
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *vt = arg;
int status;
+ if (state->radio)
+ break;
status = saa7115_read(client, 0x1f);
- saa7115_dbg("status: 0x%02x\n", status);
+ v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
break;
}
@@ -1126,20 +1094,38 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
case VIDIOC_S_CTRL:
return saa7115_set_v4lctrl(client, (struct v4l2_control *)arg);
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *qc = arg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++)
+ if (qc->id && qc->id == saa7115_qctrl[i].id) {
+ memcpy(qc, &saa7115_qctrl[i], sizeof(*qc));
+ return 0;
+ }
+ return -EINVAL;
+ }
+
case VIDIOC_G_STD:
*(v4l2_std_id *)arg = saa7115_get_v4lstd(client);
break;
case VIDIOC_S_STD:
+ state->radio = 0;
saa7115_set_v4lstd(client, *(v4l2_std_id *)arg);
break;
+ case AUDC_SET_RADIO:
+ state->radio = 1;
+ break;
+
case VIDIOC_G_INPUT:
*(int *)arg = state->input;
break;
case VIDIOC_S_INPUT:
- saa7115_dbg("decoder set input %d\n", *iarg);
+ v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
/* inputs from 0-9 are available */
if (*iarg < 0 || *iarg > 9) {
return -EINVAL;
@@ -1147,7 +1133,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
if (state->input == *iarg)
break;
- saa7115_dbg("now setting %s input\n",
+ v4l_dbg(1, debug, client, "now setting %s input\n",
*iarg >= 6 ? "S-Video" : "Composite");
state->input = *iarg;
@@ -1164,7 +1150,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
- saa7115_dbg("%s output\n",
+ v4l_dbg(1, debug, client, "%s output\n",
(cmd == VIDIOC_STREAMON) ? "enable" : "disable");
if (state->enable != (cmd == VIDIOC_STREAMON)) {
@@ -1178,7 +1164,7 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
break;
case VIDIOC_INT_RESET:
- saa7115_dbg("decoder RESET\n");
+ v4l_dbg(1, debug, client, "decoder RESET\n");
saa7115_writeregs(client, saa7115_cfg_reset_scaler);
break;
@@ -1263,48 +1249,46 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7115;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
- saa7115_dbg("detecting saa7115 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
saa7115_write(client, 0, 5);
chip_id = saa7115_read(client, 0) & 0x0f;
if (chip_id != 4 && chip_id != 5) {
- saa7115_dbg("saa7115 not found\n");
+ v4l_dbg(1, debug, client, "saa7115 not found\n");
kfree(client);
return 0;
}
if (chip_id == 4) {
snprintf(client->name, sizeof(client->name) - 1, "saa7114");
}
- saa7115_info("saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
+ v4l_info(client, "saa711%d found @ 0x%x (%s)\n", chip_id, address << 1, adapter->name);
- state = kmalloc(sizeof(struct saa7115_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct saa7115_state), GFP_KERNEL);
i2c_set_clientdata(client, state);
if (state == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(state, 0, sizeof(struct saa7115_state));
state->std = V4L2_STD_NTSC;
state->input = -1;
state->enable = 1;
+ state->radio = 0;
state->bright = 128;
state->contrast = 64;
state->hue = 0;
state->sat = 64;
state->ident = (chip_id == 4) ? V4L2_IDENT_SAA7114 : V4L2_IDENT_SAA7115;
- state->audclk_freq = V4L2_AUDCLK_48_KHZ;
+ state->audclk_freq = 48000;
- saa7115_dbg("writing init values\n");
+ v4l_dbg(1, debug, client, "writing init values\n");
/* init to 60hz/48khz */
saa7115_writeregs(client, saa7115_init_auto_input);
@@ -1312,13 +1296,12 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
saa7115_writeregs(client, saa7115_cfg_60hz_video);
- saa7115_writeregs(client, saa7115_cfg_48_audio);
- saa7115_writeregs(client, saa7115_cfg_60hz_48_audio);
+ saa7115_set_audio_clock_freq(client, state->audclk_freq);
saa7115_writeregs(client, saa7115_cfg_reset_scaler);
i2c_attach_client(client);
- saa7115_dbg("status: (1E) 0x%02x, (1F) 0x%02x\n",
+ v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
saa7115_read(client, 0x1e), saa7115_read(client, 0x1f));
return 0;
@@ -1326,11 +1309,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
static int saa7115_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, &saa7115_attach);
return 0;
}
@@ -1354,13 +1333,13 @@ static int saa7115_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver_saa7115 = {
- .name = "saa7115",
+ .driver = {
+ .name = "saa7115",
+ },
.id = I2C_DRIVERID_SAA711X,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7115_probe,
.detach_client = saa7115_detach,
.command = saa7115_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
index 31f7b950b01c..6c161f2f5e2c 100644
--- a/drivers/media/video/saa711x.c
+++ b/drivers/media/video/saa711x.c
@@ -52,7 +52,7 @@ MODULE_LICENSE("GPL");
#include <linux/video_decoder.h>
static int debug = 0;
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)");
@@ -487,21 +487,18 @@ saa711x_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa711x;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "saa711x", sizeof(I2C_NAME(client)));
- decoder = kmalloc(sizeof(struct saa711x), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct saa711x), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct saa711x));
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
@@ -565,12 +562,10 @@ saa711x_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa711x = {
- .owner = THIS_MODULE,
- .name = "saa711x",
-
+ .driver = {
+ .name = "saa711x",
+ },
.id = I2C_DRIVERID_SAA711X,
- .flags = I2C_DF_NOTIFY,
-
.attach_adapter = saa711x_attach_adapter,
.detach_client = saa711x_detach_client,
.command = saa711x_command,
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index c36f014f1fdf..992c71774f30 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -66,28 +66,6 @@ module_param(test_image, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
MODULE_PARM_DESC(test_image, "test_image (0-1)");
-#define saa7127_dbg(fmt, arg...) \
- do { \
- if (debug >= 1) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-/* High volume debug. Use with care. */
-#define saa7127_dbg_highvol(fmt, arg...) \
- do { \
- if (debug == 2) \
- printk(KERN_INFO "%s debug %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); \
- } while (0)
-
-#define saa7127_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define saa7127_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
@@ -334,7 +312,7 @@ static int saa7127_write(struct i2c_client *client, u8 reg, u8 val)
if (i2c_smbus_write_byte_data(client, reg, val) == 0)
return 0;
}
- saa7127_err("I2C Write Problem\n");
+ v4l_err(client, "I2C Write Problem\n");
return -1;
}
@@ -360,7 +338,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 0 || data->line != 16))
return -EINVAL;
if (state->vps_enable != enable) {
- saa7127_dbg("Turn VPS Signal %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off");
saa7127_write(client, 0x54, enable << 7);
state->vps_enable = enable;
}
@@ -372,7 +350,7 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
state->vps_data[2] = data->data[11];
state->vps_data[3] = data->data[12];
state->vps_data[4] = data->data[13];
- saa7127_dbg("Set VPS data %02x %02x %02x %02x %02x\n",
+ v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
state->vps_data[0], state->vps_data[1],
state->vps_data[2], state->vps_data[3],
state->vps_data[4]);
@@ -395,7 +373,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data
if (enable && (data->field != 0 || data->line != 21))
return -EINVAL;
if (state->cc_enable != enable) {
- saa7127_dbg("Turn CC %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn CC %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
(state->xds_enable << 7) | (enable << 6) | 0x11);
state->cc_enable = enable;
@@ -403,7 +381,7 @@ static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data
if (!enable)
return 0;
- saa7127_dbg_highvol("CC data: %04x\n", cc);
+ v4l_dbg(2, debug, client, "CC data: %04x\n", cc);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
state->cc_data = cc;
@@ -421,7 +399,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 1 || data->line != 21))
return -EINVAL;
if (state->xds_enable != enable) {
- saa7127_dbg("Turn XDS %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
(enable << 7) | (state->cc_enable << 6) | 0x11);
state->xds_enable = enable;
@@ -429,7 +407,7 @@ static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (!enable)
return 0;
- saa7127_dbg_highvol("XDS data: %04x\n", xds);
+ v4l_dbg(2, debug, client, "XDS data: %04x\n", xds);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
state->xds_data = xds;
@@ -446,7 +424,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat
if (enable && (data->field != 0 || data->line != 23))
return -EINVAL;
if (state->wss_enable != enable) {
- saa7127_dbg("Turn WSS %s\n", enable ? "on" : "off");
+ v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off");
saa7127_write(client, 0x27, enable << 7);
state->wss_enable = enable;
}
@@ -455,7 +433,7 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat
saa7127_write(client, 0x26, data->data[0]);
saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f));
- saa7127_dbg("WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
+ v4l_dbg(1, debug, client, "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
return 0;
}
@@ -467,11 +445,11 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable)
struct saa7127_state *state = i2c_get_clientdata(client);
if (enable) {
- saa7127_dbg("Enable Video Output\n");
+ v4l_dbg(1, debug, client, "Enable Video Output\n");
saa7127_write(client, 0x2d, state->reg_2d);
saa7127_write(client, 0x61, state->reg_61);
} else {
- saa7127_dbg("Disable Video Output\n");
+ v4l_dbg(1, debug, client, "Disable Video Output\n");
saa7127_write(client, 0x2d, (state->reg_2d & 0xf0));
saa7127_write(client, 0x61, (state->reg_61 | 0xc0));
}
@@ -487,11 +465,11 @@ static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std)
const struct i2c_reg_value *inittab;
if (std & V4L2_STD_525_60) {
- saa7127_dbg("Selecting 60 Hz video Standard\n");
+ v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n");
inittab = saa7127_init_config_60hz;
state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
} else {
- saa7127_dbg("Selecting 50 Hz video Standard\n");
+ v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n");
inittab = saa7127_init_config_50hz;
state->reg_61 = SAA7127_50HZ_DAC_CONTROL;
}
@@ -542,7 +520,7 @@ static int saa7127_set_output_type(struct i2c_client *client, int output)
default:
return -EINVAL;
}
- saa7127_dbg("Selecting %s output type\n", output_strs[output]);
+ v4l_dbg(1, debug, client, "Selecting %s output type\n", output_strs[output]);
/* Configure Encoder */
saa7127_write(client, 0x2d, state->reg_2d);
@@ -559,12 +537,12 @@ static int saa7127_set_input_type(struct i2c_client *client, int input)
switch (input) {
case SAA7127_INPUT_TYPE_NORMAL: /* avia */
- saa7127_dbg("Selecting Normal Encoder Input\n");
+ v4l_dbg(1, debug, client, "Selecting Normal Encoder Input\n");
state->reg_3a_cb = 0;
break;
case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */
- saa7127_dbg("Selecting Color Bar generator\n");
+ v4l_dbg(1, debug, client, "Selecting Color Bar generator\n");
state->reg_3a_cb = 0x80;
break;
@@ -631,14 +609,14 @@ static int saa7127_command(struct i2c_client *client,
break;
case VIDIOC_LOG_STATUS:
- saa7127_info("Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
- saa7127_info("Input: %s\n", state->input_type ? "color bars" : "normal");
- saa7127_info("Output: %s\n", state->video_enable ?
+ v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
+ v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal");
+ v4l_info(client, "Output: %s\n", state->video_enable ?
output_strs[state->output_type] : "disabled");
- saa7127_info("WSS: %s\n", state->wss_enable ?
+ v4l_info(client, "WSS: %s\n", state->wss_enable ?
wss_strs[state->wss_mode] : "disabled");
- saa7127_info("VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
- saa7127_info("CC: %s\n", state->cc_enable ? "enabled" : "disabled");
+ v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
+ v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled");
break;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -711,18 +689,16 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7127;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "saa7127");
- saa7127_dbg("detecting saa7127 client on address 0x%x\n", address << 1);
+ v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", address << 1);
/* First test register 0: Bits 5-7 are a version ID (should be 0),
and bit 2 should also be 0.
@@ -731,11 +707,11 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
0x1d after a reset and not expected to ever change. */
if ((saa7127_read(client, 0) & 0xe4) != 0 ||
(saa7127_read(client, 0x29) & 0x3f) != 0x1d) {
- saa7127_dbg("saa7127 not found\n");
+ v4l_dbg(1, debug, client, "saa7127 not found\n");
kfree(client);
return 0;
}
- state = kmalloc(sizeof(struct saa7127_state), GFP_KERNEL);
+ state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
if (state == NULL) {
kfree(client);
@@ -743,11 +719,10 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
}
i2c_set_clientdata(client, state);
- memset(state, 0, sizeof(struct saa7127_state));
/* Configure Encoder */
- saa7127_dbg("Configuring encoder\n");
+ v4l_dbg(1, debug, client, "Configuring encoder\n");
saa7127_write_inittab(client, saa7127_init_config_common);
saa7127_set_std(client, V4L2_STD_NTSC);
saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH);
@@ -768,12 +743,12 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
- saa7127_info("saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name);
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result);
saa7127_write_inittab(client, saa7129_init_config_extra);
state->ident = V4L2_IDENT_SAA7129;
} else {
- saa7127_info("saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name);
state->ident = V4L2_IDENT_SAA7127;
}
@@ -786,11 +761,7 @@ static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
static int saa7127_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, saa7127_attach);
return 0;
}
@@ -819,13 +790,13 @@ static int saa7127_detach(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7127 = {
- .name = "saa7127",
+ .driver = {
+ .name = "saa7127",
+ },
.id = I2C_DRIVERID_SAA7127,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7127_probe,
.detach_client = saa7127_detach,
.command = saa7127_command,
- .owner = THIS_MODULE,
};
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 8a5c3e71b37d..86671a43e769 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -15,7 +15,7 @@ config VIDEO_SAA7134
config VIDEO_SAA7134_ALSA
tristate "Philips SAA7134 DMA audio support"
depends on VIDEO_SAA7134 && SND
- select SND_PCM_OSS
+ select SND_PCM
---help---
This is a video4linux driver for direct (DMA) audio in
Philips SAA713x based TV cards using ALSA
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index a61d24f588f7..0e0ba50946e8 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -9,7 +9,8 @@
#include <linux/poll.h>
#include <linux/i2c.h>
#include <linux/types.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
#include <linux/init.h>
#include <linux/crc32.h>
@@ -509,11 +510,9 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct saa6752hs_state *h;
- printk("saa6752hs: chip found @ 0x%x\n", addr<<1);
- if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL)))
+ if (NULL == (h = kzalloc(sizeof(*h), GFP_KERNEL)))
return -ENOMEM;
- memset(h,0,sizeof(*h));
h->client = client_template;
h->params = param_defaults;
h->client.adapter = adap;
@@ -525,6 +524,8 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(&h->client, h);
i2c_attach_client(&h->client);
+ v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
+
return 0;
}
@@ -597,10 +598,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c saa6752hs MPEG encoder",
+ .driver = {
+ .name = "saa6752hs",
+ },
.id = I2C_DRIVERID_SAA6752HS,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa6752hs_probe,
.detach_client = saa6752hs_detach,
.command = saa6752hs_command,
@@ -609,7 +610,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "saa6752hs",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index ade05f75fdb0..a7a6ab9298a9 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -20,13 +20,13 @@
*
*/
-#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
#include <linux/module.h>
+#include <sound/driver.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 672fb205959f..c64718aec9cb 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -25,6 +25,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* commly used strings */
static char name_mute[] = "mute";
@@ -1665,7 +1666,7 @@ struct saa7134_board saa7134_boards[] = {
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
- .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
+ .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE,
.mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
@@ -2514,6 +2515,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.mpeg = SAA7134_MPEG_DVB,
+ .gpiomask = 1 << 21,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -2528,6 +2530,11 @@ struct saa7134_board saa7134_boards[] = {
.vmux = 8,
.amux = LINE1,
}},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x0200000,
+ },
},
[SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
.name = "MSI TV@Anywhere plus",
@@ -2555,6 +2562,69 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
},
},
+ [SAA7134_BOARD_CINERGY250PCI] = {
+ /* remote-control does not work. The signal about a
+ key press comes in via gpio, but the key code
+ doesn't. Neither does it have an i2c remote control
+ interface. */
+ .name = "Terratec Cinergy 250 PCI TV",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x80200000,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_svideo, /* NOT tested */
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x0200000,
+ },
+ },
+ [SAA7134_BOARD_FLYDVB_TRIO] = {
+ /* LifeView LR319 FlyDVB Trio */
+ /* Peter Missel <peter.missel@onlinehome.de> */
+ .name = "LifeView FlyDVB Trio",
+ .audio_clock = 0x00200000,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00200000,
+ .inputs = {{
+ .name = name_tv, /* Analog broadcast/cable TV */
+ .vmux = 1,
+ .amux = TV,
+ .gpio = 0x200000, /* GPIO21=High for TV input */
+ .tv = 1,
+ },{
+ .name = name_svideo, /* S-Video signal on S-Video input */
+ .vmux = 8,
+ .amux = LINE2,
+ },{
+ .name = name_comp1, /* Composite signal on S-Video input */
+ .vmux = 0,
+ .amux = LINE2,
+ },{
+ .name = name_comp2, /* Composite input */
+ .vmux = 3,
+ .amux = LINE2,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2895,6 +2965,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
.subvendor = 0x1421,
+ .subdevice = 0x0351, /* PCI version, new revision */
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1421,
.subdevice = 0x0370, /* cardbus version */
.driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
},{
@@ -3002,6 +3078,18 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x6231,
.driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x153b,
+ .subdevice = 0x1160,
+ .driver_data = SAA7134_BOARD_CINERGY250PCI,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA 7131E */
+ .subvendor = 0x5168,
+ .subdevice = 0x0319,
+ .driver_data = SAA7134_BOARD_FLYDVB_TRIO,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3090,6 +3178,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+ case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 23d8747338ed..028904bd94a2 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -31,6 +31,7 @@
#include <linux/sound.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -84,7 +85,7 @@ MODULE_PARM_DESC(radio_nr, "radio device number");
MODULE_PARM_DESC(tuner, "tuner type");
MODULE_PARM_DESC(card, "card type");
-static DECLARE_MUTEX(devlist_lock);
+static DEFINE_MUTEX(devlist_lock);
LIST_HEAD(saa7134_devlist);
static LIST_HEAD(mops_list);
static unsigned int saa7134_devcount;
@@ -95,77 +96,6 @@ int (*dmasound_exit)(struct saa7134_dev *dev);
#define dprintk(fmt, arg...) if (core_debug) \
printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
-/* ------------------------------------------------------------------ */
-/* debug help functions */
-
-static const char *v4l1_ioctls[] = {
- "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
- "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
- "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
- "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
- "SMICROCODE", "GVBIFMT", "SVBIFMT" };
-#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
-
-static const char *v4l2_ioctls[] = {
- "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
- "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
- "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
- "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
- "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
- "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
- "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
- "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
- "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
- "S_MODULATOR"
-};
-#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-static const char *osspcm_ioctls[] = {
- "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
- "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
- "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
- "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
- "SETDUPLEX", "GETODELAY"
-};
-#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
-
-void saa7134_print_ioctl(char *name, unsigned int cmd)
-{
- char *dir;
-
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE: dir = "--"; break;
- case _IOC_READ: dir = "r-"; break;
- case _IOC_WRITE: dir = "-w"; break;
- case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
- default: dir = "??"; break;
- }
- switch (_IOC_TYPE(cmd)) {
- case 'v':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
- v4l1_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'V':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
- v4l2_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'P':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
- name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
- osspcm_ioctls[_IOC_NR(cmd)] : "???");
- break;
- case 'M':
- printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- break;
- default:
- printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
- name, cmd, dir, _IOC_NR(cmd));
- }
-}
-
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
{
unsigned long mode,status;
@@ -610,11 +540,38 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
card_has_mpeg(dev))
saa7134_irq_ts_done(dev,status);
- if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
- SAA7134_IRQ_REPORT_GPIO18)) &&
- dev->remote)
- saa7134_input_irq(dev);
+ if (report & SAA7134_IRQ_REPORT_GPIO16) {
+ switch (dev->has_remote) {
+ case SAA7134_REMOTE_GPIO:
+ if (dev->remote->mask_keydown & 0x10000) {
+ saa7134_input_irq(dev);
+ }
+ break;
+
+ case SAA7134_REMOTE_I2C:
+ break; /* FIXME: invoke I2C get_key() */
+ default: /* GPIO16 not used by IR remote */
+ break;
+ }
+ }
+
+ if (report & SAA7134_IRQ_REPORT_GPIO18) {
+ switch (dev->has_remote) {
+ case SAA7134_REMOTE_GPIO:
+ if ((dev->remote->mask_keydown & 0x40000) ||
+ (dev->remote->mask_keyup & 0x40000)) {
+ saa7134_input_irq(dev);
+ }
+ break;
+
+ case SAA7134_REMOTE_I2C:
+ break; /* FIXME: invoke I2C get_key() */
+
+ default: /* GPIO18 not used by IR remote */
+ break;
+ }
+ }
}
if (10 == loop) {
@@ -624,13 +581,16 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_WARNING "%s/irq: looping -- "
"clearing PE (parity error!) enable bit\n",dev->name);
saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
- } else if (report & (SAA7134_IRQ_REPORT_GPIO16 |
- SAA7134_IRQ_REPORT_GPIO18)) {
- /* disable gpio IRQs */
+ } else if (report & SAA7134_IRQ_REPORT_GPIO16) {
+ /* disable gpio16 IRQ */
printk(KERN_WARNING "%s/irq: looping -- "
- "clearing GPIO enable bits\n",dev->name);
- saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 |
- SAA7134_IRQ2_INTE_GPIO18));
+ "clearing GPIO16 enable bit\n",dev->name);
+ saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16);
+ } else if (report & SAA7134_IRQ_REPORT_GPIO18) {
+ /* disable gpio18 IRQs */
+ printk(KERN_WARNING "%s/irq: looping -- "
+ "clearing GPIO18 enable bit\n",dev->name);
+ saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
} else {
/* disable all irqs */
printk(KERN_WARNING "%s/irq: looping -- "
@@ -711,10 +671,14 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
SAA7134_IRQ2_INTE_PE |
SAA7134_IRQ2_INTE_AR;
- if (dev->has_remote == SAA7134_REMOTE_GPIO)
- irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
- SAA7134_IRQ2_INTE_GPIO18A |
- SAA7134_IRQ2_INTE_GPIO16 );
+ if (dev->has_remote == SAA7134_REMOTE_GPIO) {
+ if (dev->remote->mask_keydown & 0x10000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO16;
+ else if (dev->remote->mask_keydown & 0x40000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO18;
+ else if (dev->remote->mask_keyup & 0x40000)
+ irq2_mask |= SAA7134_IRQ2_INTE_GPIO18A;
+ }
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, irq2_mask);
@@ -840,10 +804,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
struct saa7134_mpeg_ops *mops;
int err;
- dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev),GFP_KERNEL);
if (NULL == dev)
return -ENOMEM;
- memset(dev,0,sizeof(*dev));
/* pci init */
dev->pci = pci_dev;
@@ -1007,13 +970,13 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_attach(mops, dev);
}
list_add_tail(&dev->devlist,&saa7134_devlist);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
/* check for signal */
saa7134_irq_video_intl(dev);
@@ -1069,13 +1032,13 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_hwfini(dev);
/* unregister */
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&dev->devlist);
list_for_each(item,&mops_list) {
mops = list_entry(item, struct saa7134_mpeg_ops, next);
mpeg_ops_detach(mops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
saa7134_devcount--;
saa7134_i2c_unregister(dev);
@@ -1109,13 +1072,13 @@ int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_attach(ops, dev);
}
list_add_tail(&ops->next,&mops_list);
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
return 0;
}
@@ -1124,13 +1087,13 @@ void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
struct list_head *item;
struct saa7134_dev *dev;
- down(&devlist_lock);
+ mutex_lock(&devlist_lock);
list_del(&ops->next);
list_for_each(item,&saa7134_devlist) {
dev = list_entry(item, struct saa7134_dev, devlist);
mpeg_ops_detach(ops, dev);
}
- up(&devlist_lock);
+ mutex_unlock(&devlist_lock);
}
EXPORT_SYMBOL(saa7134_ts_register);
@@ -1156,7 +1119,7 @@ static int saa7134_init(void)
printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
#endif
- return pci_module_init(&saa7134_pci_driver);
+ return pci_register_driver(&saa7134_pci_driver);
}
static void saa7134_fini(void)
@@ -1173,7 +1136,6 @@ module_exit(saa7134_fini);
/* ----------------------------------------------------------- */
-EXPORT_SYMBOL(saa7134_print_ioctl);
EXPORT_SYMBOL(saa7134_i2c_call_clients);
EXPORT_SYMBOL(saa7134_devlist);
EXPORT_SYMBOL(saa7134_boards);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index e016480c3468..399f9952596c 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -31,6 +31,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
#ifdef HAVE_MT352
# include "mt352.h"
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 575f3e835f91..bd4c389d4c37 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -29,6 +29,7 @@
#include "saa7134.h"
#include <media/saa6752hs.h>
+#include <media/v4l2-common.h>
/* ------------------------------------------------------------------ */
@@ -163,7 +164,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
struct saa7134_dev *dev = file->private_data;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
{
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index df9dd36721e0..6162550c4136 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -30,6 +30,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* ----------------------------------------------------------- */
@@ -333,7 +334,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, client->name);
+ client->driver->driver.name, client->addr, client->name);
/* Am I an i2c remote control? */
@@ -343,7 +344,7 @@ static int attach_inform(struct i2c_client *client)
{
struct IR_i2c *ir = i2c_get_clientdata(client);
d1printk("%s i2c IR detected (%s).\n",
- client->driver->name,ir->phys);
+ client->driver->driver.name, ir->phys);
saa7134_set_i2c_ir(dev,ir);
break;
}
@@ -390,9 +391,7 @@ static struct i2c_algorithm saa7134_algo = {
static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE,
-#ifdef I2C_CLASS_TV_ANALOG
.class = I2C_CLASS_TV_ANALOG,
-#endif
.name = "saa7134",
.id = I2C_HW_SAA7134,
.algo = &saa7134_algo,
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ab75ca5ac356..82d28cbf289f 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -56,23 +56,23 @@ static IR_KEYTAB_TYPE flyvideo_codes[IR_KEYTAB_SIZE] = {
[ 12 ] = KEY_KP8,
[ 13 ] = KEY_KP9,
- [ 14 ] = KEY_TUNER, // Air/Cable
+ [ 14 ] = KEY_MODE, // Air/Cable
[ 17 ] = KEY_VIDEO, // Video
[ 21 ] = KEY_AUDIO, // Audio
- [ 0 ] = KEY_POWER, // Pover
+ [ 0 ] = KEY_POWER, // Power
+ [ 24 ] = KEY_TUNER, // AV Source
[ 2 ] = KEY_ZOOM, // Fullscreen
+ [ 26 ] = KEY_LANGUAGE, // Stereo
[ 27 ] = KEY_MUTE, // Mute
- [ 20 ] = KEY_VOLUMEUP,
- [ 23 ] = KEY_VOLUMEDOWN,
+ [ 20 ] = KEY_VOLUMEUP, // Volume +
+ [ 23 ] = KEY_VOLUMEDOWN, // Volume -
[ 18 ] = KEY_CHANNELUP, // Channel +
[ 19 ] = KEY_CHANNELDOWN, // Channel -
- [ 6 ] = KEY_AGAIN, // Recal
- [ 16 ] = KEY_KPENTER, // Enter
-
- [ 26 ] = KEY_F22, // Stereo
- [ 24 ] = KEY_EDIT, // AV Source
+ [ 6 ] = KEY_AGAIN, // Recall
+ [ 16 ] = KEY_ENTER, // Enter
};
+
static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = {
[ 0 ] = KEY_KP0,
[ 1 ] = KEY_KP1,
@@ -543,12 +543,22 @@ static int build_key(struct saa7134_dev *dev)
dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
gpio, ir->mask_keycode, data);
- if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
- (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
- ir_input_keydown(ir->dev, &ir->ir, data, data);
- } else {
- ir_input_nokey(ir->dev, &ir->ir);
+ if (ir->polling) {
+ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
+ (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
+ } else {
+ ir_input_nokey(ir->dev, &ir->ir);
+ }
+ }
+ else { /* IRQ driven mode - handle key press and release in one go */
+ if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
+ (ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
+ ir_input_keydown(ir->dev, &ir->ir, data, data);
+ ir_input_nokey(ir->dev, &ir->ir);
+ }
}
+
return 0;
}
@@ -686,6 +696,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
polling = 50; // ms
break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+ case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
ir_codes = videomate_tv_pvr_codes;
mask_keycode = 0x00003F;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 8badd2a9cb2f..7448e386a804 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -373,6 +373,42 @@ static ssize_t dsp_write(struct file *file, const char __user *buffer,
return -EINVAL;
}
+static const char *osspcm_ioctls[] = {
+ "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
+ "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
+ "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
+ "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
+ "SETDUPLEX", "GETODELAY"
+};
+#define OSSPCM_IOCTLS ARRAY_SIZE(osspcm_ioctls)
+
+static void saa7134_oss_print_ioctl(char *name, unsigned int cmd)
+{
+ char *dir;
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "??"; break;
+ }
+ switch (_IOC_TYPE(cmd)) {
+ case 'P':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
+ name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
+ osspcm_ioctls[_IOC_NR(cmd)] : "???");
+ break;
+ case 'M':
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ break;
+ default:
+ printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
+ name, cmd, dir, _IOC_NR(cmd));
+ }
+}
+
static int dsp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -382,7 +418,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
int val = 0;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
@@ -678,7 +714,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
int __user *p = argp;
if (debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ saa7134_oss_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 93268427750d..afa4dcb3f96d 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -180,8 +180,8 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
- // frame locked audio was reported not to be reliable
- saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02);
+ /* frame locked audio is mandatory for NICAM */
+ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01);
saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14);
saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -809,7 +809,12 @@ static int tvaudio_thread_ddep(void *data)
dprintk("ddep override: %s\n",stdres[audio_ddep]);
} else if (&card(dev).radio == dev->input) {
dprintk("FM Radio\n");
- norms = (0x0f << 2) | 0x01;
+ if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
+ norms = (0x11 << 2) | 0x01;
+ saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
+ } else {
+ norms = (0x0f << 2) | 0x01;
+ }
} else {
/* (let chip) scan for sound carrier */
norms = 0;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 45c852df13ed..e97426bc85df 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -29,6 +29,7 @@
#include "saa7134-reg.h"
#include "saa7134.h"
+#include <media/v4l2-common.h>
/* Include V4L1 specific functions. Should be removed soon */
#include <linux/videodev.h>
@@ -1263,10 +1264,9 @@ static int video_open(struct inode *inode, struct file *file)
v4l2_type_names[type]);
/* allocate + initialize per filehandle data */
- fh = kmalloc(sizeof(*fh),GFP_KERNEL);
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
if (NULL == fh)
return -ENOMEM;
- memset(fh,0,sizeof(*fh));
file->private_data = fh;
fh->dev = dev;
fh->radio = radio;
@@ -1689,7 +1689,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
int err;
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_S_CTRL:
@@ -2142,7 +2142,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
struct saa7134_dev *dev = fh->dev;
if (video_debug > 1)
- saa7134_print_ioctl(dev->name,cmd);
+ v4l_print_ioctl(dev->name,cmd);
switch (cmd) {
case VIDIOC_QUERYCAP:
{
@@ -2262,6 +2262,7 @@ static struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -2271,6 +2272,7 @@ static struct file_operations radio_fops =
.open = video_open,
.release = video_release,
.ioctl = radio_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index add49db1ad41..e70eae8d29bb 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -37,6 +37,9 @@
#include <media/ir-common.h>
#include <media/ir-kbd-i2c.h>
#include <media/video-buf.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
#include <media/video-buf-dvb.h>
#ifndef TRUE
@@ -47,10 +50,6 @@
#endif
#define UNSET (-1U)
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-
/* ----------------------------------------------------------- */
/* enums */
@@ -209,6 +208,8 @@ struct saa7134_format {
#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
#define SAA7134_BOARD_PHILIPS_TIGER 81
#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82
+#define SAA7134_BOARD_CINERGY250PCI 83
+#define SAA7134_BOARD_FLYDVB_TRIO 84
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -546,7 +547,6 @@ struct saa7134_dev {
extern struct list_head saa7134_devlist;
-void saa7134_print_ioctl(char *name, unsigned int cmd);
void saa7134_track_gpio(struct saa7134_dev *dev, char *msg);
#define SAA7134_PGTABLE_SIZE 4096
diff --git a/drivers/media/video/saa7146.h b/drivers/media/video/saa7146.h
index f305ec802ea6..756963f01bbd 100644
--- a/drivers/media/video/saa7146.h
+++ b/drivers/media/video/saa7146.h
@@ -73,7 +73,6 @@ struct saa7146
unsigned int nr;
unsigned long irq; /* IRQ used by SAA7146 card */
unsigned short id;
- struct pci_dev *dev;
unsigned char revision;
unsigned char boardcfg[64]; /* 64 bytes of config from eeprom */
unsigned long saa7146_adr; /* bus address of IO mem from PCI BIOS */
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 132aa7943c16..3ed0edb870a4 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -408,22 +408,19 @@ saa7185_detect_client (struct i2c_adapter *adapter,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_saa7185;
- client->flags = I2C_CLIENT_ALLOW_USE;
strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
- encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
+ encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
if (encoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(encoder, 0, sizeof(struct saa7185));
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
@@ -487,11 +484,11 @@ saa7185_detach_client (struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver i2c_driver_saa7185 = {
- .owner = THIS_MODULE,
- .name = "saa7185", /* name */
+ .driver = {
+ .name = "saa7185", /* name */
+ },
.id = I2C_DRIVERID_SAA7185B,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7185_attach_adapter,
.detach_client = saa7185_detach_client,
diff --git a/drivers/media/video/saa7191.c b/drivers/media/video/saa7191.c
index cbca896e8cfa..746cadb8f1c4 100644
--- a/drivers/media/video/saa7191.c
+++ b/drivers/media/video/saa7191.c
@@ -571,18 +571,15 @@ static int saa7191_attach(struct i2c_adapter *adap, int addr, int kind)
printk(KERN_INFO "Philips SAA7191 driver version %s\n",
SAA7191_MODULE_VERSION);
- client = kmalloc(sizeof(*client), GFP_KERNEL);
+ client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return -ENOMEM;
- decoder = kmalloc(sizeof(*decoder), GFP_KERNEL);
+ decoder = kzalloc(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;
@@ -788,10 +785,10 @@ static int saa7191_command(struct i2c_client *client, unsigned int cmd,
}
static struct i2c_driver i2c_driver_saa7191 = {
- .owner = THIS_MODULE,
- .name = "saa7191",
+ .driver = {
+ .name = "saa7191",
+ },
.id = I2C_DRIVERID_SAA7191,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = saa7191_probe,
.detach_client = saa7191_detach,
.command = saa7191_command
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index d4497dbae05c..54fc33011ffb 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -49,9 +49,9 @@
#include "saa7121.h"
#include "cs8420.h"
-#define DEBUG(x) /* debug driver */
-#undef IDEBUG /* debug irq handler */
-#undef MDEBUG /* debug memory management */
+#define DEBUG(x) /* debug driver */
+#undef IDEBUG /* debug irq handler */
+#undef MDEBUG /* debug memory management */
#define SAA7146_MAX 6
@@ -63,7 +63,6 @@ static int video_nr = -1;
module_param(video_nr, int, 0);
MODULE_LICENSE("GPL");
-
#define nDebNormal 0x00480000
#define nDebNoInc 0x00480000
#define nDebVideo 0xd0480000
@@ -99,7 +98,12 @@ MODULE_LICENSE("GPL");
#ifdef USE_RESCUE_EEPROM_SDM275
static unsigned char rescue_eeprom[64] = {
-0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00, 0x01, 0x04, 0x13, 0x26, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x43, 0x63,
+ 0x22, 0x01, 0x29, 0x15, 0x73, 0x00, 0x1f, 'd', 'e', 'c', 'x', 'l',
+ 'd', 'v', 'a', 0x02, 0x00, 0x01, 0x00, 0xcc, 0xa4, 0x63, 0x09, 0xe2,
+ 0x10, 0x00, 0x0a, 0x00, 0x02, 0x02, 'd', 'e', 'c', 'x', 'l', 'a',
+ 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
};
#endif
@@ -140,17 +144,18 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
if (saaread(SAA7146_I2C_STATUS) & 0x3c)
I2CWipe(saa);
- for (i = 0; i < 1000 &&
- (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++)
+ for (i = 0;
+ i < 1000 && (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY);
+ i++)
schedule();
if (i == 1000)
I2CWipe(saa);
if (dosub)
saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) |
- ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
+ ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER);
else
saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) |
- 0xf1, SAA7146_I2C_TRANSFER);
+ 0xf1, SAA7146_I2C_TRANSFER);
saawrite((SAA7146_MC2_UPLD_I2C << 16) |
SAA7146_MC2_UPLD_I2C, SAA7146_MC2);
/* wait for i2c registers to be programmed */
@@ -163,7 +168,7 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
schedule();
if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR)
return -1;
- if (i == 1000)
+ if (i == 1000)
printk("i2c setup read timeout\n");
saawrite(0x41, SAA7146_I2C_TRANSFER);
saawrite((SAA7146_MC2_UPLD_I2C << 16) |
@@ -178,7 +183,7 @@ static int I2CRead(struct saa7146 *saa, unsigned char addr,
schedule();
if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR)
return -1;
- if (i == 1000)
+ if (i == 1000)
printk("i2c read timeout\n");
return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
}
@@ -213,20 +218,22 @@ static void attach_inform(struct saa7146 *saa, int id)
{
int i;
- DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id));
- if (id == 0xa0) { /* we have rev2 or later board, fill in info */
+ DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr,
+ id));
+ if (id == 0xa0) { /* we have rev2 or later board, fill in info */
for (i = 0; i < 64; i++)
saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
#ifdef USE_RESCUE_EEPROM_SDM275
if (saa->boardcfg[0] != 0) {
- printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr);
+ printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE "
+ "BEEN IGNORED\n", saa->nr);
for (i = 0; i < 64; i++)
saa->boardcfg[i] = rescue_eeprom[i];
}
#endif
printk("stradis%d: config =", saa->nr);
for (i = 0; i < 51; i++) {
- printk(" %02x",saa->boardcfg[i]);
+ printk(" %02x", saa->boardcfg[i]);
}
printk("\n");
}
@@ -254,17 +261,19 @@ static int wait_for_debi_done(struct saa7146 *saa)
for (i = 0; i < 500000 &&
(saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++)
saaread(SAA7146_MC2);
+
if (i > debiwait_maxwait)
printk("wait-for-debi-done maxwait: %d\n",
debiwait_maxwait = i);
-
+
if (i == 500000)
return -1;
+
return 0;
}
static int debiwrite(struct saa7146 *saa, u32 config, int addr,
- u32 val, int count)
+ u32 val, int count)
{
u32 cmd;
if (count <= 0 || count > 32764)
@@ -309,41 +318,6 @@ static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count)
return result;
}
-#if 0 /* unused */
-/* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */
-/* data copied into saa->dmadebi buffer, caller must re-enable interrupts */
-static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes)
-{
- int i, j;
- u32 *buf;
- buf = (u32 *) saa->dmadebi;
- if (bytes > 0x7000)
- bytes = 0x7000;
- saawrite(0, SAA7146_IER); /* disable interrupts */
- for (i=0; i < 10000 &&
- (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
- & 0x8000); i++)
- saaread(SAA7146_MC2);
- if (i == 10000)
- printk(KERN_ERR "stradis%d: dram_busy never cleared\n",
- saa->nr);
- debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) |
- (address>>16), 4);
- debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2);
- debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2);
- for (j = 0; j < bytes/4; j++) {
- for (i = 0; i < 10000 &&
- (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2)
- & 0x4000)); i++)
- saaread(SAA7146_MC2);
- if (i == 10000)
- printk(KERN_ERR "stradis%d: dram_ready never set\n",
- saa->nr);
- buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4);
- }
-}
-#endif /* unused */
-
static void do_irq_send_data(struct saa7146 *saa)
{
int split, audbytes, vidbytes;
@@ -365,16 +339,15 @@ static void do_irq_send_data(struct saa7146 *saa)
return;
}
/* if at least 1 block audio waiting and audio fifo isn't full */
- if (audbytes >= 2048 && (debiread(saa, debNormal,
- IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) {
+ if (audbytes >= 2048 && (debiread(saa, debNormal, IBM_MP2_AUD_FIFO, 2)
+ & 0xff) < 60) {
if (saa->audhead > saa->audtail)
split = 65536 - saa->audhead;
else
split = 0;
audbytes = 2048;
if (split > 0 && split < 2048) {
- memcpy(saa->dmadebi, saa->audbuf + saa->audhead,
- split);
+ memcpy(saa->dmadebi, saa->audbuf + saa->audhead, split);
saa->audhead = 0;
audbytes -= split;
} else
@@ -383,20 +356,19 @@ static void do_irq_send_data(struct saa7146 *saa)
audbytes);
saa->audhead += audbytes;
saa->audhead &= 0xffff;
- debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO :
- IBM_MP2_AUD_FIFOW), 0, 2048);
+ debiwrite(saa, debAudio, (NewCard ? IBM_MP2_AUD_FIFO :
+ IBM_MP2_AUD_FIFOW), 0, 2048);
wake_up_interruptible(&saa->audq);
- /* if at least 1 block video waiting and video fifo isn't full */
+ /* if at least 1 block video waiting and video fifo isn't full */
} else if (vidbytes >= 30720 && (debiread(saa, debNormal,
- IBM_MP2_FIFO, 2)) < 16384) {
+ IBM_MP2_FIFO, 2)) < 16384) {
if (saa->vidhead > saa->vidtail)
split = 524288 - saa->vidhead;
else
split = 0;
vidbytes = 30720;
if (split > 0 && split < 30720) {
- memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead,
- split);
+ memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, split);
saa->vidhead = 0;
vidbytes -= split;
} else
@@ -406,7 +378,7 @@ static void do_irq_send_data(struct saa7146 *saa)
saa->vidhead += vidbytes;
saa->vidhead &= 0x7ffff;
debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO :
- IBM_MP2_FIFOW), 0, 30720);
+ IBM_MP2_FIFOW), 0, 30720);
wake_up_interruptible(&saa->vidq);
}
saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER);
@@ -418,10 +390,10 @@ static void send_osd_data(struct saa7146 *saa)
if (size > 30720)
size = 30720;
/* ensure some multiple of 8 bytes is transferred */
- size = 8 * ((size + 8)>>3);
+ size = 8 * ((size + 8) >> 3);
if (size) {
debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR,
- (saa->osdhead>>3), 2);
+ (saa->osdhead >> 3), 2);
memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size);
saa->osdhead += size;
/* block transfer of next 8 bytes to ~32k bytes */
@@ -435,7 +407,7 @@ static void send_osd_data(struct saa7146 *saa)
static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct saa7146 *saa = (struct saa7146 *) dev_id;
+ struct saa7146 *saa = dev_id;
u32 stat, astat;
int count;
int handled = 0;
@@ -484,7 +456,7 @@ static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
saa->vidinfo.v_size = 480;
#if 0
if (saa->endmarkhead != saa->endmarktail) {
- saa->audhead =
+ saa->audhead =
saa->endmark[saa->endmarkhead];
saa->endmarkhead++;
if (saa->endmarkhead >= MAX_MARKS)
@@ -494,7 +466,7 @@ static irqreturn_t saa7146_irq(int irq, void *dev_id, struct pt_regs *regs)
}
if (istat & 0x4000) { /* Sequence Error Code */
if (saa->endmarkhead != saa->endmarktail) {
- saa->audhead =
+ saa->audhead =
saa->endmark[saa->endmarkhead];
saa->endmarkhead++;
if (saa->endmarkhead >= MAX_MARKS)
@@ -613,7 +585,7 @@ static int ibm_send_command(struct saa7146 *saa,
int i;
if (chain)
- debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2);
+ debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1)| 1,2);
else
debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2);
debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2);
@@ -663,11 +635,9 @@ static void initialize_cs8420(struct saa7146 *saa, int pro)
else
sequence = mode8420con;
for (i = 0; i < INIT8420LEN; i++)
- I2CWrite(saa, 0x20, init8420[i * 2],
- init8420[i * 2 + 1], 2);
+ I2CWrite(saa, 0x20, init8420[i * 2], init8420[i * 2 + 1], 2);
for (i = 0; i < MODE8420LEN; i++)
- I2CWrite(saa, 0x20, sequence[i * 2],
- sequence[i * 2 + 1], 2);
+ I2CWrite(saa, 0x20, sequence[i * 2], sequence[i * 2 + 1], 2);
printk("stradis%d: CS8420 initialized\n", saa->nr);
}
@@ -683,35 +653,36 @@ static void initialize_saa7121(struct saa7146 *saa, int dopal)
/* initialize PAL/NTSC video encoder */
for (i = 0; i < INIT7121LEN; i++) {
if (NewCard) { /* handle new card encoder differences */
- if (sequence[i*2] == 0x3a)
+ if (sequence[i * 2] == 0x3a)
I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
- else if (sequence[i*2] == 0x6b)
+ else if (sequence[i * 2] == 0x6b)
I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
- else if (sequence[i*2] == 0x6c)
+ else if (sequence[i * 2] == 0x6c)
I2CWrite(saa, 0x88, 0x6c,
dopal ? 0x09 : 0xf5, 2);
- else if (sequence[i*2] == 0x6d)
+ else if (sequence[i * 2] == 0x6d)
I2CWrite(saa, 0x88, 0x6d,
dopal ? 0x20 : 0x00, 2);
- else if (sequence[i*2] == 0x7a)
+ else if (sequence[i * 2] == 0x7a)
I2CWrite(saa, 0x88, 0x7a,
dopal ? (PALFirstActive - 1) :
(NTSCFirstActive - 4), 2);
- else if (sequence[i*2] == 0x7b)
+ else if (sequence[i * 2] == 0x7b)
I2CWrite(saa, 0x88, 0x7b,
dopal ? PALLastActive :
NTSCLastActive, 2);
- else I2CWrite(saa, 0x88, sequence[i * 2],
- sequence[i * 2 + 1], 2);
+ else
+ I2CWrite(saa, 0x88, sequence[i * 2],
+ sequence[i * 2 + 1], 2);
} else {
- if (sequence[i*2] == 0x6b && mod)
- I2CWrite(saa, 0x88, 0x6b,
- (sequence[i * 2 + 1] ^ 0x09), 2);
- else if (sequence[i*2] == 0x7a)
+ if (sequence[i * 2] == 0x6b && mod)
+ I2CWrite(saa, 0x88, 0x6b,
+ (sequence[i * 2 + 1] ^ 0x09), 2);
+ else if (sequence[i * 2] == 0x7a)
I2CWrite(saa, 0x88, 0x7a,
dopal ? (PALFirstActive - 1) :
(NTSCFirstActive - 4), 2);
- else if (sequence[i*2] == 0x7b)
+ else if (sequence[i * 2] == 0x7b)
I2CWrite(saa, 0x88, 0x7b,
dopal ? PALLastActive :
NTSCLastActive, 2);
@@ -735,7 +706,8 @@ static void set_genlock_offset(struct saa7146 *saa, int noffset)
nCode = noffset + 0x100;
if (nCode == 1)
nCode = 0x401;
- else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode;
+ else if (nCode < 1)
+ nCode = 0x400 + PixelsPerLine + nCode;
debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2);
}
@@ -745,33 +717,31 @@ static void set_out_format(struct saa7146 *saa, int mode)
saa->boardcfg[2] = mode;
/* do not adjust analog video parameters here, use saa7121 init */
/* you will affect the SDI output on the new card */
- if (mode == VIDEO_MODE_PAL) { /* PAL */
+ if (mode == VIDEO_MODE_PAL) { /* PAL */
debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2);
mdelay(50);
saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1);
if (NewCard) {
- debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- 0xe100, 2);
+ debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, 0xe100, 2);
mdelay(50);
}
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- NewCard ? 0xe500: 0x6500, 2);
+ NewCard ? 0xe500 : 0x6500, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
(1 << 8) |
- (NewCard ? PALFirstActive : PALFirstActive-6), 2);
+ (NewCard ? PALFirstActive : PALFirstActive - 6), 2);
} else { /* NTSC */
debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2);
mdelay(50);
saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1);
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- NewCard ? 0xe100: 0x6100, 2);
+ NewCard ? 0xe100 : 0x6100, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_DLY,
(1 << 8) |
- (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2);
+ (NewCard ? NTSCFirstActive : NTSCFirstActive - 6), 2);
}
}
-
/* Intialize bitmangler to map from a byte value to the mangled word that
* must be output to program the Xilinx part through the DEBI port.
* Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0
@@ -799,43 +769,41 @@ static int initialize_fpga(struct video_code *bitdata)
for (num = 0; num < saa_num; num++) {
saa = &saa7146s[num];
if (saa->boardcfg[0] > 20)
- continue; /* card was programmed */
+ continue; /* card was programmed */
loadtwo = (saa->boardcfg[18] & 0x10);
if (!NewCard) /* we have an old board */
for (i = 0; i < 256; i++)
- bitmangler[i] = ((i & 0x01) << 15) |
- ((i & 0x02) << 6) | ((i & 0x04) << 4) |
- ((i & 0x08) << 9) | ((i & 0x10) << 7) |
- ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
- ((i & 0x80) >> 7);
- else /* else we have a new board */
+ bitmangler[i] = ((i & 0x01) << 15) |
+ ((i & 0x02) << 6) | ((i & 0x04) << 4) |
+ ((i & 0x08) << 9) | ((i & 0x10) << 7) |
+ ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+ ((i & 0x80) >> 7);
+ else /* else we have a new board */
for (i = 0; i < 256; i++)
- bitmangler[i] = ((i & 0x01) << 7) |
- ((i & 0x02) << 5) | ((i & 0x04) << 3) |
- ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
- ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
- ((i & 0x80) >> 7);
+ bitmangler[i] = ((i & 0x01) << 7) |
+ ((i & 0x02) << 5) | ((i & 0x04) << 3) |
+ ((i & 0x08) << 1) | ((i & 0x10) >> 1) |
+ ((i & 0x20) >> 3) | ((i & 0x40) >> 5) |
+ ((i & 0x80) >> 7);
dmabuf = (u16 *) saa->dmadebi;
newdma = (u8 *) saa->dmadebi;
if (NewCard) { /* SDM2xxx */
if (!strncmp(bitdata->loadwhat, "decoder2", 8))
continue; /* fpga not for this card */
- if (!strncmp(&saa->boardcfg[42],
- bitdata->loadwhat, 8)) {
+ if (!strncmp(&saa->boardcfg[42], bitdata->loadwhat, 8))
loadfile = 1;
- } else if (loadtwo && !strncmp(&saa->boardcfg[19],
- bitdata->loadwhat, 8)) {
+ else if (loadtwo && !strncmp(&saa->boardcfg[19],
+ bitdata->loadwhat, 8))
loadfile = 2;
- } else if (!saa->boardcfg[42] && /* special */
- !strncmp("decxl", bitdata->loadwhat, 8)) {
- loadfile = 1;
- } else
+ else if (!saa->boardcfg[42] && !strncmp("decxl",
+ bitdata->loadwhat, 8))
+ loadfile = 1; /* special */
+ else
continue; /* fpga not for this card */
- if (loadfile != 1 && loadfile != 2) {
+ if (loadfile != 1 && loadfile != 2)
continue; /* skip to next card */
- }
- if (saa->boardcfg[0] && loadfile == 1 )
+ if (saa->boardcfg[0] && loadfile == 1)
continue; /* skip to next card */
if (saa->boardcfg[0] != 1 && loadfile == 2)
continue; /* skip to next card */
@@ -870,8 +838,9 @@ static int initialize_fpga(struct video_code *bitdata)
/* Release Xilinx INIT signal (WS2) */
saawrite(0x00000000, SAA7146_GPIO_CTRL);
/* Wait for the INIT to go High */
- for (i = 0; i < 10000 &&
- !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+ for (i = 0;
+ i < 10000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
+ i++)
schedule();
if (i == 1000) {
printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr);
@@ -881,17 +850,13 @@ send_fpga_stuff:
if (NewCard) {
for (i = startindex; i < bitdata->datasize; i++)
newdma[i - startindex] =
- bitmangler[bitdata->data[i]];
+ bitmangler[bitdata->data[i]];
debiwrite(saa, 0x01420000, 0, 0,
((bitdata->datasize - startindex) + 5));
- if (loadtwo) {
- if (loadfile == 1) {
- printk("stradis%d: "
- "awaiting 2nd FPGA bitfile\n",
- saa->nr);
- continue; /* skip to next card */
- }
-
+ if (loadtwo && loadfile == 1) {
+ printk("stradis%d: awaiting 2nd FPGA bitfile\n",
+ saa->nr);
+ continue; /* skip to next card */
}
} else {
for (i = startindex; i < bitdata->datasize; i++)
@@ -900,8 +865,9 @@ send_fpga_stuff:
debiwrite(saa, 0x014a0000, 0, 0,
((bitdata->datasize - startindex) + 5) * 2);
}
- for (i = 0; i < 1000 &&
- !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++)
+ for (i = 0;
+ i < 1000 && !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2);
+ i++)
schedule();
if (i == 1000) {
printk(KERN_INFO "stradis%d: FPGA load failed\n",
@@ -925,14 +891,14 @@ send_fpga_stuff:
/* mute CS3310 */
if (HaveCS3310)
debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
- 0, 2);
+ 0, 2);
/* set VXCO to PWM mode, release reset, blank on */
debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2);
mdelay(10);
/* unmute CS3310 */
if (HaveCS3310)
debiwrite(saa, debNormal, XILINX_CTL0,
- 0x2020, 2);
+ 0x2020, 2);
}
/* set source Black */
debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2);
@@ -958,10 +924,10 @@ send_fpga_stuff:
/* we must init CS8420 first since rev b pulls i2s */
/* master clock low and CS4341 needs i2s master to */
/* run the i2c port. */
- if (HaveCS8420) {
+ if (HaveCS8420)
/* 0=consumer, 1=pro */
initialize_cs8420(saa, 0);
- }
+
mdelay(5);
if (HaveCS4341)
initialize_cs4341(saa);
@@ -981,6 +947,7 @@ send_fpga_stuff:
debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2);
#endif
}
+
return failure;
}
@@ -1021,10 +988,10 @@ static int do_ibm_reset(struct saa7146 *saa)
/* we must init CS8420 first since rev b pulls i2s */
/* master clock low and CS4341 needs i2s master to */
/* run the i2c port. */
- if (HaveCS8420) {
+ if (HaveCS8420)
/* 0=consumer, 1=pro */
initialize_cs8420(saa, 1);
- }
+
mdelay(5);
if (HaveCS4341)
initialize_cs4341(saa);
@@ -1039,12 +1006,12 @@ static int do_ibm_reset(struct saa7146 *saa)
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
- (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
+ (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) {
printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr);
}
if (HaveCS3310) {
int i = CS3310MaxLvl;
- debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+ debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i << 8)| i),2);
}
/* start video decoder */
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2);
@@ -1057,6 +1024,7 @@ static int do_ibm_reset(struct saa7146 *saa)
/* clear pending interrupts */
debiread(saa, debNormal, IBM_MP2_HOST_INT, 2);
debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2);
+
return 0;
}
@@ -1070,8 +1038,8 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
saa = &saa7146s[num];
/* check that FPGA is loaded */
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2);
- if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) !=
- 0xa55a) {
+ i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2);
+ if (i != 0xa55a) {
printk(KERN_INFO "stradis%d: %04x != 0xa55a\n",
saa->nr, i);
#if 0
@@ -1082,17 +1050,17 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
if (saa->boardcfg[0] > 27)
continue; /* skip to next card */
/* load video control store */
- saa->boardcfg[1] = 0x13; /* no-sync default */
+ saa->boardcfg[1] = 0x13; /* no-sync default */
debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2);
debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
for (i = 0; i < microcode->datasize / 2; i++)
debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA,
(microcode->data[i * 2] << 8) |
- microcode->data[i * 2 + 1], 2);
+ microcode->data[i * 2 + 1], 2);
debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
+ ChipControl, 2);
saa->boardcfg[0] = 28;
}
if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) {
@@ -1109,34 +1077,32 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2);
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2);
if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER,
- 0xe000, 1)) {
- printk(KERN_ERR
- "stradis%d: IBM config failed\n",
- saa->nr);
+ 0xe000, 1)) {
+ printk(KERN_ERR "stradis%d: IBM config "
+ "failed\n", saa->nr);
return -1;
}
/* set PWM to center value */
if (NewCard) {
debiwrite(saa, debNormal, XILINX_PWM,
- saa->boardcfg[14] +
- (saa->boardcfg[13]<<8), 2);
+ saa->boardcfg[14] +
+ (saa->boardcfg[13] << 8), 2);
} else
- debiwrite(saa, debNormal, XILINX_PWM,
- 0x46, 2);
+ debiwrite(saa, debNormal, XILINX_PWM, 0x46, 2);
+
if (HaveCS3310) {
i = CS3310MaxLvl;
- debiwrite(saa, debNormal,
- XILINX_CS3310_CMPLT, ((i<<8)|i), 2);
+ debiwrite(saa, debNormal, XILINX_CS3310_CMPLT,
+ (i << 8) | i, 2);
}
- printk(KERN_INFO
- "stradis%d: IBM MPEGCD%d Initialized\n",
- saa->nr, 18 + (debiread(saa, debNormal,
- IBM_MP2_CHIP_CONTROL, 2) >> 12));
+ printk(KERN_INFO "stradis%d: IBM MPEGCD%d Inited\n",
+ saa->nr, 18 + (debiread(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, 2) >> 12));
/* start video decoder */
debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
ChipControl, 2);
- debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD,
- 0x4037, 2); /* 256k vid, 3520 bytes aud */
+ debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037,
+ 2); /* 256k vid, 3520 bytes aud */
debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2);
ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
/* enable buffer threshold irq */
@@ -1149,52 +1115,48 @@ static int initialize_ibmmpeg2(struct video_code *microcode)
saa->boardcfg[0] = 37;
}
}
+
return 0;
}
-static u32 palette2fmt[] =
-{ /* some of these YUV translations are wrong */
- 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
- 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
- 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
+static u32 palette2fmt[] = { /* some of these YUV translations are wrong */
+ 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000,
+ 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000,
+ 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000
};
-static int bpp2fmt[4] =
-{
+static int bpp2fmt[4] = {
VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24,
VIDEO_PALETTE_RGB32
};
/* I wish I could find a formula to calculate these... */
-static u32 h_prescale[64] =
-{
- 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
- 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
- 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
- 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
- 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
- 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
- 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
- 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
- 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
- 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
- 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
+static u32 h_prescale[64] = {
+ 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808,
+ 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460,
+ 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f,
+ 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000,
+ 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000,
+ 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000,
+ 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000,
+ 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000,
+ 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000,
+ 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000,
+ 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000,
};
-static u32 v_gain[64] =
-{
- 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
- 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
- 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
- 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+static u32 v_gain[64] = {
+ 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff,
+ 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff,
+ 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
+ 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff,
};
-
static void saa7146_set_winsize(struct saa7146 *saa)
{
u32 format;
@@ -1209,24 +1171,23 @@ static void saa7146_set_winsize(struct saa7146 *saa)
saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight,
SAA7146_PROT_ADDR1);
saawrite(0, SAA7146_PAGE1);
- saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+ saawrite(format | 0x60, SAA7146_CLIP_FORMAT_CTRL);
offset = (704 / (saa->win.width - 1)) & 0x3f;
saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE);
offset = (720896 / saa->win.width) / (offset + 1);
- saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE);
+ saawrite((offset << 12) | 0x0c, SAA7146_HPS_H_SCALE);
if (CurrentMode == VIDEO_MODE_NTSC) {
- yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0;
+ yacl = /*(480 / saa->win.height - 1) & 0x3f */ 0;
ysci = 1024 - (saa->win.height * 1024 / 480);
} else {
- yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0;
+ yacl = /*(576 / saa->win.height - 1) & 0x3f */ 0;
ysci = 1024 - (saa->win.height * 1024 / 576);
}
- saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE);
+ saawrite((1 << 31) | (ysci << 21) | (yacl << 15), SAA7146_HPS_V_SCALE);
saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN);
saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V |
- SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
- SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H),
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 |
+ SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), SAA7146_MC2);
}
/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area
@@ -1261,8 +1222,8 @@ static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h)
startword = (x >> 5);
endword = ((x + w) >> 5);
bitsleft = (0xffffffff >> (x & 31));
- bitsright = (0xffffffff << (~((x + w) - (endword<<5))));
- temp = &clipmap[(y<<5) + startword];
+ bitsright = (0xffffffff << (~((x + w) - (endword << 5))));
+ temp = &clipmap[(y << 5) + startword];
w = endword - startword;
if (!w) {
bitsleft |= bitsright;
@@ -1287,13 +1248,13 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
u32 *clipmap;
clipmap = saa->dmavid2;
- if((width=saa->win.width)>1023)
- width = 1023; /* sanity check */
- if((height=saa->win.height)>640)
- height = 639; /* sanity check */
- if (ncr > 0) { /* rectangles pased */
+ if ((width = saa->win.width) > 1023)
+ width = 1023; /* sanity check */
+ if ((height = saa->win.height) > 640)
+ height = 639; /* sanity check */
+ if (ncr > 0) { /* rectangles pased */
/* convert rectangular clips to a bitmap */
- memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
+ memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
for (i = 0; i < ncr; i++)
clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
cr[i].width, cr[i].height);
@@ -1301,14 +1262,15 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
/* clip against viewing window AND screen
so we do not have to rely on the user program
*/
- clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ?
- (saa->win.swidth-saa->win.x) : width, 0, 1024, 768);
- clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ?
- (saa->win.sheight-saa->win.y) : height,1024,768);
- if (saa->win.x<0)
- clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768);
- if (saa->win.y<0)
- clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y));
+ clip_draw_rectangle(clipmap, (saa->win.x + width > saa->win.swidth) ?
+ (saa->win.swidth - saa->win.x) : width, 0, 1024, 768);
+ clip_draw_rectangle(clipmap, 0,
+ (saa->win.y + height > saa->win.sheight) ?
+ (saa->win.sheight - saa->win.y) : height, 1024, 768);
+ if (saa->win.x < 0)
+ clip_draw_rectangle(clipmap, 0, 0, -saa->win.x, 768);
+ if (saa->win.y < 0)
+ clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
}
static int saa_ioctl(struct inode *inode, struct file *file,
@@ -1322,11 +1284,9 @@ static int saa_ioctl(struct inode *inode, struct file *file,
{
struct video_capability b;
strcpy(b.name, saa->video_dev.name);
- b.type = VID_TYPE_CAPTURE |
- VID_TYPE_OVERLAY |
- VID_TYPE_CLIPPING |
- VID_TYPE_FRAMERAM |
- VID_TYPE_SCALES;
+ b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY |
+ VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM |
+ VID_TYPE_SCALES;
b.channels = 1;
b.audios = 1;
b.maxwidth = 768;
@@ -1363,17 +1323,18 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (p.palette < sizeof(palette2fmt) / sizeof(u32)) {
format = palette2fmt[p.palette];
saa->win.color_fmt = format;
- saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL);
+ saawrite(format | 0x60,
+ SAA7146_CLIP_FORMAT_CTRL);
}
saawrite(((p.brightness & 0xff00) << 16) |
- ((p.contrast & 0xfe00) << 7) |
- ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
+ ((p.contrast & 0xfe00) << 7) |
+ ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL);
saa->picture = p;
/* upload changed registers */
saawrite(((SAA7146_MC2_UPLD_HPS_H |
- SAA7146_MC2_UPLD_HPS_V) << 16) |
- SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V,
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_HPS_V) << 16) |
+ SAA7146_MC2_UPLD_HPS_H |
+ SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2);
return 0;
}
case VIDIOCSWIN:
@@ -1384,11 +1345,14 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&vw, arg, sizeof(vw)))
return -EFAULT;
- if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */
- saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1);
+ /* stop capture */
+ if (vw.flags || vw.width < 16 || vw.height < 16) {
+ saawrite((SAA7146_MC1_TR_E_1 << 16),
+ SAA7146_MC1);
return -EINVAL;
}
- if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */
+ /* 32-bit align start and adjust width */
+ if (saa->win.bpp < 4) {
int i = vw.x;
vw.x = (vw.x + 3) & ~3;
i = vw.x - i;
@@ -1417,23 +1381,24 @@ static int saa_ioctl(struct inode *inode, struct file *file,
*/
if (vw.clipcount < 0) {
if (copy_from_user(saa->dmavid2, vw.clips,
- VIDEO_CLIPMAP_SIZE))
+ VIDEO_CLIPMAP_SIZE))
return -EFAULT;
- }
- else if (vw.clipcount > 16384) {
+ } else if (vw.clipcount > 16384) {
return -EINVAL;
} else if (vw.clipcount > 0) {
- if ((vcp = vmalloc(sizeof(struct video_clip) *
- (vw.clipcount))) == NULL)
- return -ENOMEM;
+ vcp = vmalloc(sizeof(struct video_clip) *
+ vw.clipcount);
+ if (vcp == NULL)
+ return -ENOMEM;
if (copy_from_user(vcp, vw.clips,
- sizeof(struct video_clip) *
- vw.clipcount)) {
+ sizeof(struct video_clip) *
+ vw.clipcount)) {
vfree(vcp);
return -EFAULT;
}
} else /* nothing clipped */
memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE);
+
make_clip_tab(saa, vcp, vw.clipcount);
if (vw.clipcount > 0)
vfree(vcp);
@@ -1466,21 +1431,21 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (v == 0) {
saa->cap &= ~1;
saawrite((SAA7146_MC1_TR_E_1 << 16),
- SAA7146_MC1);
+ SAA7146_MC1);
} else {
if (saa->win.vidadr == 0 || saa->win.width == 0
- || saa->win.height == 0)
+ || saa->win.height == 0)
return -EINVAL;
saa->cap |= 1;
saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff,
- SAA7146_MC1);
+ SAA7146_MC1);
}
return 0;
}
case VIDIOCGFBUF:
{
struct video_buffer v;
- v.base = (void *) saa->win.vidadr;
+ v.base = (void *)saa->win.vidadr;
v.height = saa->win.sheight;
v.width = saa->win.swidth;
v.depth = saa->win.depth;
@@ -1498,19 +1463,20 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
if (v.depth != 8 && v.depth != 15 && v.depth != 16 &&
- v.depth != 24 && v.depth != 32 && v.width > 16 &&
+ v.depth != 24 && v.depth != 32 && v.width > 16 &&
v.height > 16 && v.bytesperline > 16)
return -EINVAL;
if (v.base)
- saa->win.vidadr = (unsigned long) v.base;
+ saa->win.vidadr = (unsigned long)v.base;
saa->win.sheight = v.height;
saa->win.swidth = v.width;
saa->win.bpp = ((v.depth + 7) & 0x38) / 8;
saa->win.depth = v.depth;
saa->win.bpl = v.bytesperline;
- DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
- v.base, v.width, v.height, saa->win.bpp, saa->win.bpl));
+ DEBUG(printk("Display at %p is %d by %d, bytedepth %d, "
+ "bpl %d\n", v.base, v.width, v.height,
+ saa->win.bpp, saa->win.bpl));
saa7146_set_winsize(saa);
return 0;
}
@@ -1538,21 +1504,18 @@ static int saa_ioctl(struct inode *inode, struct file *file,
int i;
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- i = (~(v.volume>>8))&0xff;
+ i = (~(v.volume >> 8)) & 0xff;
if (!HaveCS4341) {
- if (v.flags & VIDEO_AUDIO_MUTE) {
+ if (v.flags & VIDEO_AUDIO_MUTE)
debiwrite(saa, debNormal,
- IBM_MP2_FRNT_ATTEN,
- 0xffff, 2);
- }
+ IBM_MP2_FRNT_ATTEN, 0xffff, 2);
if (!(v.flags & VIDEO_AUDIO_MUTE))
debiwrite(saa, debNormal,
- IBM_MP2_FRNT_ATTEN,
- 0x0000, 2);
+ IBM_MP2_FRNT_ATTEN, 0x0000, 2);
if (v.flags & VIDEO_AUDIO_VOLUME)
debiwrite(saa, debNormal,
IBM_MP2_FRNT_ATTEN,
- (i<<8)|i, 2);
+ (i << 8) | i, 2);
} else {
if (v.flags & VIDEO_AUDIO_MUTE)
cs4341_setlevel(saa, 0xff, 0xff);
@@ -1580,163 +1543,138 @@ static int saa_ioctl(struct inode *inode, struct file *file,
case VIDIOCSPLAYMODE:
{
struct video_play_mode pmode;
- if (copy_from_user((void *) &pmode, arg,
- sizeof(struct video_play_mode)))
+ if (copy_from_user((void *)&pmode, arg,
+ sizeof(struct video_play_mode)))
return -EFAULT;
switch (pmode.mode) {
- case VID_PLAY_VID_OUT_MODE:
- if (pmode.p1 != VIDEO_MODE_NTSC &&
+ case VID_PLAY_VID_OUT_MODE:
+ if (pmode.p1 != VIDEO_MODE_NTSC &&
pmode.p1 != VIDEO_MODE_PAL)
- return -EINVAL;
- set_out_format(saa, pmode.p1);
- return 0;
- case VID_PLAY_GENLOCK:
- debiwrite(saa, debNormal,
- XILINX_CTL0,
- (pmode.p1 ? 0x8000 : 0x8080),
- 2);
- if (NewCard)
- set_genlock_offset(saa,
- pmode.p2);
- return 0;
- case VID_PLAY_NORMAL:
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_PLAY, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_PAUSE:
- /* IBM removed the PAUSE command */
- /* they say use SINGLE_FRAME now */
- case VID_PLAY_SINGLE_FRAME:
- ibm_send_command(saa,
- IBM_MP2_SINGLE_FRAME,
- 0, 0);
- if (saa->playmode == pmode.mode) {
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- }
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_FAST_FORWARD:
- ibm_send_command(saa,
- IBM_MP2_FAST_FORWARD, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_SLOW_MOTION:
- ibm_send_command(saa,
- IBM_MP2_SLOW_MOTION,
- pmode.p1, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_IMMEDIATE_NORMAL:
- /* ensure transfers resume */
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_IMED_NORM_PLAY, 0, 0);
- saa->playmode = VID_PLAY_NORMAL;
- return 0;
- case VID_PLAY_SWITCH_CHANNELS:
- saa->audhead = saa->audtail = 0;
- saa->vidhead = saa->vidtail = 0;
- ibm_send_command(saa,
- IBM_MP2_FREEZE_FRAME, 0, 1);
- ibm_send_command(saa,
- IBM_MP2_RESET_AUD_RATE, 0, 1);
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL, 0, 2);
- ibm_send_command(saa,
- IBM_MP2_CHANNEL_SWITCH, 0, 1);
+ return -EINVAL;
+ set_out_format(saa, pmode.p1);
+ return 0;
+ case VID_PLAY_GENLOCK:
+ debiwrite(saa, debNormal, XILINX_CTL0,
+ pmode.p1 ? 0x8000 : 0x8080, 2);
+ if (NewCard)
+ set_genlock_offset(saa, pmode.p2);
+ return 0;
+ case VID_PLAY_NORMAL:
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_PAUSE:
+ /* IBM removed the PAUSE command */
+ /* they say use SINGLE_FRAME now */
+ case VID_PLAY_SINGLE_FRAME:
+ ibm_send_command(saa, IBM_MP2_SINGLE_FRAME,0,0);
+ if (saa->playmode == pmode.mode) {
debiwrite(saa, debNormal,
IBM_MP2_CHIP_CONTROL,
ChipControl, 2);
- ibm_send_command(saa,
- IBM_MP2_PLAY, 0, 0);
- saa->playmode = VID_PLAY_NORMAL;
- return 0;
- case VID_PLAY_FREEZE_FRAME:
- ibm_send_command(saa,
- IBM_MP2_FREEZE_FRAME, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_STILL_MODE:
- ibm_send_command(saa,
- IBM_MP2_SET_STILL_MODE, 0, 0);
- saa->playmode = pmode.mode;
- return 0;
- case VID_PLAY_MASTER_MODE:
- if (pmode.p1 == VID_PLAY_MASTER_NONE)
- saa->boardcfg[1] = 0x13;
- else if (pmode.p1 ==
- VID_PLAY_MASTER_VIDEO)
- saa->boardcfg[1] = 0x23;
- else if (pmode.p1 ==
- VID_PLAY_MASTER_AUDIO)
- saa->boardcfg[1] = 0x43;
- else
+ }
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_FAST_FORWARD:
+ ibm_send_command(saa, IBM_MP2_FAST_FORWARD,0,0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_SLOW_MOTION:
+ ibm_send_command(saa, IBM_MP2_SLOW_MOTION,
+ pmode.p1, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_IMMEDIATE_NORMAL:
+ /* ensure transfers resume */
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY,
+ 0, 0);
+ saa->playmode = VID_PLAY_NORMAL;
+ return 0;
+ case VID_PLAY_SWITCH_CHANNELS:
+ saa->audhead = saa->audtail = 0;
+ saa->vidhead = saa->vidtail = 0;
+ ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,1);
+ ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE,
+ 0, 1);
+ debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+ 0, 2);
+ ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH,
+ 0, 1);
+ debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL,
+ ChipControl, 2);
+ ibm_send_command(saa, IBM_MP2_PLAY, 0, 0);
+ saa->playmode = VID_PLAY_NORMAL;
+ return 0;
+ case VID_PLAY_FREEZE_FRAME:
+ ibm_send_command(saa, IBM_MP2_FREEZE_FRAME,0,0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_STILL_MODE:
+ ibm_send_command(saa, IBM_MP2_SET_STILL_MODE,
+ 0, 0);
+ saa->playmode = pmode.mode;
+ return 0;
+ case VID_PLAY_MASTER_MODE:
+ if (pmode.p1 == VID_PLAY_MASTER_NONE)
+ saa->boardcfg[1] = 0x13;
+ else if (pmode.p1 == VID_PLAY_MASTER_VIDEO)
+ saa->boardcfg[1] = 0x23;
+ else if (pmode.p1 == VID_PLAY_MASTER_AUDIO)
+ saa->boardcfg[1] = 0x43;
+ else
+ return -EINVAL;
+ debiwrite(saa, debNormal,
+ IBM_MP2_CHIP_CONTROL, ChipControl, 2);
+ return 0;
+ case VID_PLAY_ACTIVE_SCANLINES:
+ if (CurrentMode == VIDEO_MODE_PAL) {
+ if (pmode.p1 < 1 || pmode.p2 > 625)
return -EINVAL;
- debiwrite(saa, debNormal,
- IBM_MP2_CHIP_CONTROL,
- ChipControl, 2);
- return 0;
- case VID_PLAY_ACTIVE_SCANLINES:
- if (CurrentMode == VIDEO_MODE_PAL) {
- if (pmode.p1 < 1 ||
- pmode.p2 > 625)
- return -EINVAL;
- saa->boardcfg[5] = pmode.p1;
- saa->boardcfg[55] = (pmode.p1 +
- (pmode.p2/2) - 1) &
- 0xff;
- } else {
- if (pmode.p1 < 4 ||
- pmode.p2 > 525)
- return -EINVAL;
- saa->boardcfg[4] = pmode.p1;
- saa->boardcfg[54] = (pmode.p1 +
- (pmode.p2/2) - 4) &
- 0xff;
- }
- set_out_format(saa, CurrentMode);
- case VID_PLAY_RESET:
- return do_ibm_reset(saa);
- case VID_PLAY_END_MARK:
- if (saa->endmarktail <
- saa->endmarkhead) {
- if (saa->endmarkhead -
+ saa->boardcfg[5] = pmode.p1;
+ saa->boardcfg[55] = (pmode.p1 +
+ (pmode.p2 / 2) - 1) & 0xff;
+ } else {
+ if (pmode.p1 < 4 || pmode.p2 > 525)
+ return -EINVAL;
+ saa->boardcfg[4] = pmode.p1;
+ saa->boardcfg[54] = (pmode.p1 +
+ (pmode.p2 / 2) - 4) & 0xff;
+ }
+ set_out_format(saa, CurrentMode);
+ case VID_PLAY_RESET:
+ return do_ibm_reset(saa);
+ case VID_PLAY_END_MARK:
+ if (saa->endmarktail < saa->endmarkhead) {
+ if (saa->endmarkhead -
saa->endmarktail < 2)
- return -ENOSPC;
- } else if (saa->endmarkhead <=
- saa->endmarktail) {
- if (saa->endmarktail -
- saa->endmarkhead >
- (MAX_MARKS - 2))
- return -ENOSPC;
- } else
return -ENOSPC;
- saa->endmark[saa->endmarktail] =
- saa->audtail;
- saa->endmarktail++;
- if (saa->endmarktail >= MAX_MARKS)
- saa->endmarktail = 0;
+ } else if (saa->endmarkhead <=saa->endmarktail){
+ if (saa->endmarktail - saa->endmarkhead
+ > (MAX_MARKS - 2))
+ return -ENOSPC;
+ } else
+ return -ENOSPC;
+ saa->endmark[saa->endmarktail] = saa->audtail;
+ saa->endmarktail++;
+ if (saa->endmarktail >= MAX_MARKS)
+ saa->endmarktail = 0;
}
return -EINVAL;
}
case VIDIOCSWRITEMODE:
{
int mode;
- if (copy_from_user((void *) &mode, arg, sizeof(int)))
- return -EFAULT;
+ if (copy_from_user((void *)&mode, arg, sizeof(int)))
+ return -EFAULT;
if (mode == VID_WRITE_MPEG_AUD ||
- mode == VID_WRITE_MPEG_VID ||
- mode == VID_WRITE_CC ||
- mode == VID_WRITE_TTX ||
- mode == VID_WRITE_OSD) {
+ mode == VID_WRITE_MPEG_VID ||
+ mode == VID_WRITE_CC ||
+ mode == VID_WRITE_TTX ||
+ mode == VID_WRITE_OSD) {
saa->writemode = mode;
return 0;
}
@@ -1750,7 +1688,7 @@ static int saa_ioctl(struct inode *inode, struct file *file,
if (copy_from_user(&ucode, arg, sizeof(ucode)))
return -EFAULT;
if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
- strncmp(ucode.loadwhat, "dec", 3))
+ strncmp(ucode.loadwhat, "dec", 3))
return -EINVAL;
if ((udata = vmalloc(ucode.datasize)) == NULL)
return -ENOMEM;
@@ -1759,8 +1697,8 @@ static int saa_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
ucode.data = udata;
- if (!strncmp(ucode.loadwhat, "decoder.aud", 11)
- || !strncmp(ucode.loadwhat, "decoder.vid", 11))
+ if (!strncmp(ucode.loadwhat, "decoder.aud", 11) ||
+ !strncmp(ucode.loadwhat, "decoder.vid", 11))
i = initialize_ibmmpeg2(&ucode);
else
i = initialize_fpga(&ucode);
@@ -1805,14 +1743,14 @@ static int saa_mmap(struct file *file, struct vm_area_struct *vma)
return -EINVAL;
}
-static ssize_t saa_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t saa_read(struct file *file, char __user * buf,
+ size_t count, loff_t * ppos)
{
return -EINVAL;
}
-static ssize_t saa_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t saa_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
{
struct saa7146 *saa = file->private_data;
unsigned long todo = count;
@@ -1823,20 +1761,22 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
if (saa->writemode == VID_WRITE_MPEG_AUD) {
spin_lock_irqsave(&saa->lock, flags);
if (saa->audhead <= saa->audtail)
- blocksize = 65536-(saa->audtail - saa->audhead);
+ blocksize = 65536 -
+ (saa->audtail - saa->audhead);
else
blocksize = saa->audhead - saa->audtail;
spin_unlock_irqrestore(&saa->lock, flags);
if (blocksize < 16384) {
saawrite(SAA7146_PSR_DEBI_S |
- SAA7146_PSR_PIN1, SAA7146_IER);
+ SAA7146_PSR_PIN1, SAA7146_IER);
saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
/* wait for buffer space to open */
interruptible_sleep_on(&saa->audq);
}
spin_lock_irqsave(&saa->lock, flags);
if (saa->audhead <= saa->audtail) {
- blocksize = 65536-(saa->audtail - saa->audhead);
+ blocksize = 65536 -
+ (saa->audtail - saa->audhead);
split = 65536 - saa->audtail;
} else {
blocksize = saa->audhead - saa->audtail;
@@ -1851,7 +1791,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
return -ENOSPC;
if (split < blocksize) {
if (copy_from_user(saa->audbuf +
- saa->audtail, buf, split))
+ saa->audtail, buf, split))
return -EFAULT;
buf += split;
todo -= split;
@@ -1859,7 +1799,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
saa->audtail = 0;
}
if (copy_from_user(saa->audbuf + saa->audtail, buf,
- blocksize))
+ blocksize))
return -EFAULT;
saa->audtail += blocksize;
todo -= blocksize;
@@ -1868,20 +1808,22 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
} else if (saa->writemode == VID_WRITE_MPEG_VID) {
spin_lock_irqsave(&saa->lock, flags);
if (saa->vidhead <= saa->vidtail)
- blocksize=524288-(saa->vidtail - saa->vidhead);
+ blocksize = 524288 -
+ (saa->vidtail - saa->vidhead);
else
blocksize = saa->vidhead - saa->vidtail;
spin_unlock_irqrestore(&saa->lock, flags);
if (blocksize < 65536) {
saawrite(SAA7146_PSR_DEBI_S |
- SAA7146_PSR_PIN1, SAA7146_IER);
+ SAA7146_PSR_PIN1, SAA7146_IER);
saawrite(SAA7146_PSR_PIN1, SAA7146_PSR);
/* wait for buffer space to open */
interruptible_sleep_on(&saa->vidq);
}
spin_lock_irqsave(&saa->lock, flags);
if (saa->vidhead <= saa->vidtail) {
- blocksize=524288-(saa->vidtail - saa->vidhead);
+ blocksize = 524288 -
+ (saa->vidtail - saa->vidhead);
split = 524288 - saa->vidtail;
} else {
blocksize = saa->vidhead - saa->vidtail;
@@ -1896,7 +1838,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
return -ENOSPC;
if (split < blocksize) {
if (copy_from_user(saa->vidbuf +
- saa->vidtail, buf, split))
+ saa->vidtail, buf, split))
return -EFAULT;
buf += split;
todo -= split;
@@ -1904,7 +1846,7 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
saa->vidtail = 0;
}
if (copy_from_user(saa->vidbuf + saa->vidtail, buf,
- blocksize))
+ blocksize))
return -EFAULT;
saa->vidtail += blocksize;
todo -= blocksize;
@@ -1922,8 +1864,8 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2);
debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2);
debiwrite(saa, debNormal, IBM_MP2_DISP_MODE,
- debiread(saa, debNormal,
- IBM_MP2_DISP_MODE, 2) | 1, 2);
+ debiread(saa, debNormal,
+ IBM_MP2_DISP_MODE, 2) | 1, 2);
/* trigger osd data transfer */
saawrite(SAA7146_PSR_DEBI_S |
SAA7146_PSR_PIN1, SAA7146_IER);
@@ -1935,21 +1877,11 @@ static ssize_t saa_write(struct file *file, const char __user *buf,
static int saa_open(struct inode *inode, struct file *file)
{
- struct saa7146 *saa = NULL;
- unsigned int minor = iminor(inode);
- int i;
+ struct video_device *vdev = video_devdata(file);
+ struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
- for (i = 0; i < SAA7146_MAX; i++) {
- if (saa7146s[i].video_dev.minor == minor) {
- saa = &saa7146s[i];
- }
- }
- if (saa == NULL) {
- return -ENODEV;
- }
file->private_data = saa;
- //saa->video_dev.busy = 0; /* old hack to support multiple open */
saa->user++;
if (saa->user > 1)
return 0; /* device open already, don't reset */
@@ -1961,42 +1893,39 @@ static int saa_release(struct inode *inode, struct file *file)
{
struct saa7146 *saa = file->private_data;
saa->user--;
- //saa->video_dev.busy = 0; /* old hack to support multiple open */
+
if (saa->user > 0) /* still someone using device */
return 0;
saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */
return 0;
}
-static struct file_operations saa_fops =
-{
- .owner = THIS_MODULE,
- .open = saa_open,
- .release = saa_release,
- .ioctl = saa_ioctl,
- .read = saa_read,
- .llseek = no_llseek,
- .write = saa_write,
- .mmap = saa_mmap,
+static struct file_operations saa_fops = {
+ .owner = THIS_MODULE,
+ .open = saa_open,
+ .release = saa_release,
+ .ioctl = saa_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
+ .read = saa_read,
+ .llseek = no_llseek,
+ .write = saa_write,
+ .mmap = saa_mmap,
};
/* template for video_device-structure */
-static struct video_device saa_template =
-{
- .name = "SAA7146A",
- .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
- .hardware = VID_HARDWARE_SAA7146,
- .fops = &saa_fops,
- .minor = -1,
+static struct video_device saa_template = {
+ .name = "SAA7146A",
+ .type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY,
+ .hardware = VID_HARDWARE_SAA7146,
+ .fops = &saa_fops,
+ .minor = -1,
};
-static int configure_saa7146(struct pci_dev *dev, int num)
+static int __devinit configure_saa7146(struct pci_dev *pdev, int num)
{
- int result;
- struct saa7146 *saa;
+ int retval;
+ struct saa7146 *saa = pci_get_drvdata(pdev);
- saa = &saa7146s[num];
-
saa->endmarkhead = saa->endmarktail = 0;
saa->win.x = saa->win.y = 0;
saa->win.width = saa->win.cropwidth = 720;
@@ -2012,7 +1941,6 @@ static int configure_saa7146(struct pci_dev *dev, int num)
saa->picture.contrast = 38768;
saa->picture.colour = 32768;
saa->cap = 0;
- saa->dev = dev;
saa->nr = num;
saa->playmode = VID_PLAY_NORMAL;
memset(saa->boardcfg, 0, 64); /* clear board config area */
@@ -2032,45 +1960,59 @@ static int configure_saa7146(struct pci_dev *dev, int num)
init_waitqueue_head(&saa->vidq);
spin_lock_init(&saa->lock);
- if (pci_enable_device(dev))
- return -EIO;
-
- saa->id = dev->device;
- saa->irq = dev->irq;
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "%d: pci_enable_device failed!\n", num);
+ goto err;
+ }
+
+ saa->id = pdev->device;
+ saa->irq = pdev->irq;
saa->video_dev.minor = -1;
- saa->saa7146_adr = pci_resource_start(dev, 0);
- pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision);
+ saa->saa7146_adr = pci_resource_start(pdev, 0);
+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &saa->revision);
saa->saa7146_mem = ioremap(saa->saa7146_adr, 0x200);
- if (!saa->saa7146_mem)
- return -EIO;
+ if (saa->saa7146_mem == NULL) {
+ dev_err(&pdev->dev, "%d: ioremap failed!\n", num);
+ retval = -EIO;
+ goto err;
+ }
memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
saawrite(0, SAA7146_IER); /* turn off all interrupts */
- result = request_irq(saa->irq, saa7146_irq,
- SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa);
- if (result == -EINVAL)
- printk(KERN_ERR "stradis%d: Bad irq number or handler\n",
- num);
- if (result == -EBUSY)
- printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP"
- " config in BIOS\n", num, saa->irq);
- if (result < 0) {
- iounmap(saa->saa7146_mem);
- return result;
- }
- pci_set_master(dev);
- if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) {
- iounmap(saa->saa7146_mem);
- return -1;
+
+ retval = request_irq(saa->irq, saa7146_irq, SA_SHIRQ | SA_INTERRUPT,
+ "stradis", saa);
+ if (retval == -EINVAL)
+ dev_err(&pdev->dev, "%d: Bad irq number or handler\n", num);
+ else if (retval == -EBUSY)
+ dev_err(&pdev->dev, "%d: IRQ %ld busy, change your PnP config "
+ "in BIOS\n", num, saa->irq);
+ if (retval < 0)
+ goto errio;
+
+ pci_set_master(pdev);
+ retval = video_register_device(&saa->video_dev, VFL_TYPE_GRABBER,
+ video_nr);
+ if (retval < 0) {
+ dev_err(&pdev->dev, "%d: error in registering video device!\n",
+ num);
+ goto errio;
}
+
return 0;
+errio:
+ iounmap(saa->saa7146_mem);
+err:
+ return retval;
}
-static int init_saa7146(int i)
+static int __devinit init_saa7146(struct pci_dev *pdev)
{
- struct saa7146 *saa = &saa7146s[i];
+ struct saa7146 *saa = pci_get_drvdata(pdev);
+ memset(saa, 0, sizeof(*saa));
saa->user = 0;
/* reset the saa7146 */
saawrite(0xffff0000, SAA7146_MC1);
@@ -2088,23 +2030,23 @@ static int init_saa7146(int i)
saawrite(0x00000000, SAA7146_DD1_STREAM_A);
saawrite(0x00000000, SAA7146_BRS_CTRL);
saawrite(0x80400040, SAA7146_BCS_CTRL);
- saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL);
+ saawrite(0x0000e000 /*| (1<<29) */ , SAA7146_HPS_CTRL);
saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL);
saawrite(0x00000000, SAA7146_ACON1);
saawrite(0x00000000, SAA7146_ACON2);
saawrite(0x00000600, SAA7146_I2C_STATUS);
saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A |
- SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
- SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
- SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
- SAA7146_MC2);
+ SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H |
+ SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 |
+ SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff,
+ SAA7146_MC2);
/* setup arbitration control registers */
saawrite(0x1412121a, SAA7146_PCI_BT_V1);
/* allocate 32k dma buffer + 4k for page table */
if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i);
- return -1;
+ dev_err(&pdev->dev, "%d: debi kmalloc failed\n", saa->nr);
+ goto err;
}
#if 0
saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */
@@ -2114,133 +2056,162 @@ static int init_saa7146(int i)
#endif
saa->audhead = saa->vidhead = saa->osdhead = 0;
saa->audtail = saa->vidtail = saa->osdtail = 0;
- if (saa->vidbuf == NULL)
- if ((saa->vidbuf = vmalloc(524288)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- return -ENOMEM;
- }
- if (saa->audbuf == NULL)
- if ((saa->audbuf = vmalloc(65536)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- saa->vidbuf = NULL;
- return -ENOMEM;
- }
- if (saa->osdbuf == NULL)
- if ((saa->osdbuf = vmalloc(131072)) == NULL) {
- printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- saa->vidbuf = saa->audbuf = NULL;
- return -ENOMEM;
- }
+ if (saa->vidbuf == NULL && (saa->vidbuf = vmalloc(524288)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto err;
+ }
+ if (saa->audbuf == NULL && (saa->audbuf = vmalloc(65536)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto errvid;
+ }
+ if (saa->osdbuf == NULL && (saa->osdbuf = vmalloc(131072)) == NULL) {
+ dev_err(&pdev->dev, "%d: malloc failed\n", saa->nr);
+ goto erraud;
+ }
/* allocate 81920 byte buffer for clipping */
- if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr);
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- vfree(saa->osdbuf);
- saa->vidbuf = saa->audbuf = saa->osdbuf = NULL;
- saa->dmavid2 = NULL;
- return -1;
+ if ((saa->dmavid2 = kzalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) {
+ dev_err(&pdev->dev, "%d: clip kmalloc failed\n", saa->nr);
+ goto errosd;
}
- memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */
/* setup clipping registers */
saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2);
saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2);
saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE,
- SAA7146_PROT_ADDR2);
+ SAA7146_PROT_ADDR2);
saawrite(256, SAA7146_PITCH2);
- saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
+ saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
SAA7146_MC2);
I2CBusScan(saa);
+
return 0;
+errosd:
+ vfree(saa->osdbuf);
+ saa->osdbuf = NULL;
+erraud:
+ vfree(saa->audbuf);
+ saa->audbuf = NULL;
+errvid:
+ vfree(saa->vidbuf);
+ saa->vidbuf = NULL;
+err:
+ return -ENOMEM;
}
-static void release_saa(void)
+static void stradis_release_saa(struct pci_dev *pdev)
{
u8 command;
- int i;
- struct saa7146 *saa;
+ struct saa7146 *saa = pci_get_drvdata(pdev);
- for (i = 0; i < saa_num; i++) {
- saa = &saa7146s[i];
+ /* turn off all capturing, DMA and IRQs */
+ saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
+ saawrite(0, SAA7146_MC2);
+ saawrite(0, SAA7146_IER);
+ saawrite(0xffffffffUL, SAA7146_ISR);
+
+ /* disable PCI bus-mastering */
+ pci_read_config_byte(pdev, PCI_COMMAND, &command);
+ command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_byte(pdev, PCI_COMMAND, command);
+
+ /* unmap and free memory */
+ saa->audhead = saa->audtail = saa->osdhead = 0;
+ saa->vidhead = saa->vidtail = saa->osdtail = 0;
+ vfree(saa->vidbuf);
+ vfree(saa->audbuf);
+ vfree(saa->osdbuf);
+ kfree(saa->dmavid2);
+ saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
+ saa->dmavid2 = NULL;
+ 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);
+ if (saa->video_dev.minor != -1)
+ video_unregister_device(&saa->video_dev);
+}
- /* turn off all capturing, DMA and IRQs */
- saawrite(0xffff0000, SAA7146_MC1); /* reset chip */
- saawrite(0, SAA7146_MC2);
- saawrite(0, SAA7146_IER);
- saawrite(0xffffffffUL, SAA7146_ISR);
-
- /* disable PCI bus-mastering */
- pci_read_config_byte(saa->dev, PCI_COMMAND, &command);
- command &= ~PCI_COMMAND_MASTER;
- pci_write_config_byte(saa->dev, PCI_COMMAND, command);
-
- /* unmap and free memory */
- saa->audhead = saa->audtail = saa->osdhead = 0;
- saa->vidhead = saa->vidtail = saa->osdtail = 0;
- vfree(saa->vidbuf);
- vfree(saa->audbuf);
- vfree(saa->osdbuf);
- kfree(saa->dmavid2);
- saa->audbuf = saa->vidbuf = saa->osdbuf = NULL;
- saa->dmavid2 = NULL;
- 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);
- if (saa->video_dev.minor != -1)
- video_unregister_device(&saa->video_dev);
+static int __devinit stradis_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ int retval = -EINVAL;
+
+ if (saa_num >= SAA7146_MAX)
+ goto err;
+
+ if (!pdev->subsystem_vendor)
+ dev_info(&pdev->dev, "%d: rev1 decoder\n", saa_num);
+ else
+ dev_info(&pdev->dev, "%d: SDM2xx found\n", saa_num);
+
+ pci_set_drvdata(pdev, &saa7146s[saa_num]);
+
+ retval = configure_saa7146(pdev, saa_num);
+ if (retval) {
+ dev_err(&pdev->dev, "%d: error in configuring\n", saa_num);
+ goto err;
+ }
+
+ if (init_saa7146(pdev) < 0) {
+ dev_err(&pdev->dev, "%d: error in initialization\n", saa_num);
+ retval = -EIO;
+ goto errrel;
}
+
+ saa_num++;
+
+ return 0;
+errrel:
+ stradis_release_saa(pdev);
+err:
+ return retval;
+}
+
+static void __devexit stradis_remove(struct pci_dev *pdev)
+{
+ stradis_release_saa(pdev);
}
+static struct pci_device_id stradis_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
+
+static struct pci_driver stradis_driver = {
+ .name = "stradis",
+ .id_table = stradis_pci_tbl,
+ .probe = stradis_probe,
+ .remove = __devexit_p(stradis_remove)
+};
-static int __init stradis_init (void)
+int __init stradis_init(void)
{
- struct pci_dev *dev = NULL;
- int result = 0, i;
+ int retval;
saa_num = 0;
- while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) {
- if (!dev->subsystem_vendor)
- printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num);
- else
- printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num);
- result = configure_saa7146(dev, saa_num++);
- if (result)
- return result;
- }
- if (saa_num)
- printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num);
- else
- return -EINVAL;
- for (i = 0; i < saa_num; i++)
- if (init_saa7146(i) < 0) {
- release_saa();
- return -EIO;
- }
- return 0;
-}
+ retval = pci_register_driver(&stradis_driver);
+ if (retval)
+ printk(KERN_ERR "stradis: Unable to register pci driver.\n");
+ return retval;
+}
-static void __exit stradis_exit (void)
+void __exit stradis_exit(void)
{
- release_saa();
+ pci_unregister_driver(&stradis_driver);
printk(KERN_INFO "stradis: module cleanup complete\n");
}
-
module_init(stradis_init);
module_exit(stradis_exit);
-
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index d32737dd2142..fc3d5824efff 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -50,6 +50,7 @@
#include "bttv.h"
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#ifndef VIDEO_AUDIO_BALANCE
# define VIDEO_AUDIO_BALANCE 32
@@ -90,9 +91,6 @@ struct tda7432 {
static struct i2c_driver driver;
static struct i2c_client client_template;
-#define dprintk if (debug) printk
-#define d2printk if (debug > 1) printk
-
/* The TDA7432 is made by STS-Thompson
* http://www.st.com
* http://us.st.com/stonline/books/pdf/docs/4056.pdf
@@ -229,12 +227,12 @@ static struct i2c_client client_template;
static int tda7432_write(struct i2c_client *client, int subaddr, int val)
{
unsigned char buffer[2];
- d2printk("tda7432: In tda7432_write\n");
- dprintk("tda7432: Writing %d 0x%x\n", subaddr, val);
+ v4l_dbg(2, debug,client,"In tda7432_write\n");
+ v4l_dbg(1, debug,client,"Writing %d 0x%x\n", subaddr, val);
buffer[0] = subaddr;
buffer[1] = val;
if (2 != i2c_master_send(client,buffer,2)) {
- printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n",
+ v4l_err(client,"I/O error, trying (write %d 0x%x)\n",
subaddr, val);
return -1;
}
@@ -247,9 +245,9 @@ static int tda7432_set(struct i2c_client *client)
{
struct tda7432 *t = i2c_get_clientdata(client);
unsigned char buf[16];
- d2printk("tda7432: In tda7432_set\n");
+ v4l_dbg(2, debug,client,"In tda7432_set\n");
- dprintk(KERN_INFO
+ v4l_dbg(1, debug,client,
"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud);
buf[0] = TDA7432_IN;
@@ -263,7 +261,7 @@ static int tda7432_set(struct i2c_client *client)
buf[8] = t->rr;
buf[9] = t->loud;
if (10 != i2c_master_send(client,buf,10)) {
- printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n");
+ v4l_err(client,"I/O error, trying tda7432_set\n");
return -1;
}
@@ -273,7 +271,7 @@ static int tda7432_set(struct i2c_client *client)
static void do_tda7432_init(struct i2c_client *client)
{
struct tda7432 *t = i2c_get_clientdata(client);
- d2printk("tda7432: In tda7432_init\n");
+ v4l_dbg(2, debug,client,"In tda7432_init\n");
t->input = TDA7432_STEREO_IN | /* Main (stereo) input */
TDA7432_BASS_SYM | /* Symmetric bass cut */
@@ -301,12 +299,10 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct tda7432 *t;
struct i2c_client *client;
- d2printk("tda7432: In tda7432_attach\n");
- t = kmalloc(sizeof *t,GFP_KERNEL);
+ t = kzalloc(sizeof *t,GFP_KERNEL);
if (!t)
return -ENOMEM;
- memset(t,0,sizeof *t);
client = &t->c;
memcpy(client,&client_template,sizeof(struct i2c_client));
@@ -315,21 +311,16 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
i2c_set_clientdata(client, t);
do_tda7432_init(client);
- printk(KERN_INFO "tda7432: init\n");
-
i2c_attach_client(client);
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name);
return 0;
}
static int tda7432_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda7432_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, tda7432_attach);
-#endif
return 0;
}
@@ -348,7 +339,9 @@ static int tda7432_command(struct i2c_client *client,
unsigned int cmd, void *arg)
{
struct tda7432 *t = i2c_get_clientdata(client);
- d2printk("tda7432: In tda7432_command\n");
+ v4l_dbg(2, debug,client,"In tda7432_command\n");
+ if (debug>1)
+ v4l_i2c_print_ioctl(client,cmd);
switch (cmd) {
/* --- v4l ioctls --- */
@@ -359,7 +352,6 @@ static int tda7432_command(struct i2c_client *client,
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
- dprintk("tda7432: VIDIOCGAUDIO\n");
va->flags |= VIDEO_AUDIO_VOLUME |
VIDEO_AUDIO_BASS |
@@ -414,7 +406,6 @@ static int tda7432_command(struct i2c_client *client,
case VIDIOCSAUDIO:
{
struct video_audio *va = arg;
- dprintk("tda7432: VIDEOCSAUDIO\n");
if(va->flags & VIDEO_AUDIO_VOLUME){
if(!maxvol){ /* max +20db */
@@ -490,21 +481,16 @@ static int tda7432_command(struct i2c_client *client,
} /* end of VIDEOCSAUDIO case */
- default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
-
- /* nothing */
- d2printk("tda7432: Default\n");
-
} /* end of (cmd) switch */
return 0;
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda7432 driver",
+ .driver = {
+ .name = "tda7432",
+ },
.id = I2C_DRIVERID_TDA7432,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda7432_probe,
.detach_client = tda7432_detach,
.command = tda7432_command,
@@ -519,7 +505,7 @@ static struct i2c_client client_template =
static int __init tda7432_init(void)
{
if ( (loudness < 0) || (loudness > 15) ) {
- printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n");
+ printk(KERN_ERR "loudness parameter must be between 0 and 15\n");
return -EINVAL;
}
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
index 61d94ddaff41..7b4fb282ac82 100644
--- a/drivers/media/video/tda8290.c
+++ b/drivers/media/video/tda8290.c
@@ -398,14 +398,8 @@ static int tda8290_tune(struct i2c_client *c, u16 ifc, unsigned int freq)
return 0;
}
-
/*---------------------------------------------------------------------*/
-#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
-#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
-#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
-#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
-
static void set_audio(struct tuner *t)
{
char* mode;
@@ -573,8 +567,8 @@ int tda8290_init(struct i2c_client *c)
}
tuner_info("tuner: type set to %s\n", c->name);
- t->tv_freq = set_tv_freq;
- t->radio_freq = set_radio_freq;
+ t->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = has_signal;
t->standby = standby;
t->tda827x_lpsel = 0;
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 1794686612c6..ed4c04119ccc 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -34,7 +34,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define SWITCH 0x00
#define LEVEL_ADJUST 0x02
@@ -221,10 +221,10 @@ static int detach(struct i2c_client *client)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tda9840",
+ .driver = {
+ .name = "tda9840",
+ },
.id = I2C_DRIVERID_TDA9840,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index a5e37dc91f39..ef98c4982250 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -232,10 +232,9 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind)
struct i2c_client *client;
dprintk("In tda9875_attach\n");
- t = kmalloc(sizeof *t,GFP_KERNEL);
+ t = kzalloc(sizeof *t,GFP_KERNEL);
if (!t)
return -ENOMEM;
- memset(t,0,sizeof *t);
client = &t->c;
memcpy(client,&client_template,sizeof(struct i2c_client));
@@ -257,13 +256,8 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind)
static int tda9875_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9875_attach);
-#else
- if (adap->id == I2C_HW_B_BT848)
- return i2c_probe(adap, &addr_data, tda9875_attach);
-#endif
return 0;
}
@@ -372,10 +366,10 @@ static int tda9875_command(struct i2c_client *client,
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda9875 driver",
+ .driver = {
+ .name = "tda9875",
+ },
.id = I2C_DRIVERID_TDA9875,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda9875_probe,
.detach_client = tda9875_detach,
.command = tda9875_command,
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 2f2414e90e8b..5815649bdc78 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -9,7 +9,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#include <media/tuner.h>
@@ -57,7 +57,6 @@ struct tda9887 {
v4l2_std_id std;
enum tuner_mode mode;
unsigned int config;
- unsigned int pinnacle_id;
unsigned int using_v4l2;
unsigned int radio_mode;
unsigned char data[4];
@@ -115,6 +114,9 @@ static struct i2c_client client_template;
#define cAudioGain0 0x00 // bit c7
#define cAudioGain6 0x80 // bit c7
+#define cTopMask 0x1f // bit c0:4
+#define cTopPalSecamDefault 0x14 // bit c0:4
+#define cTopNtscRadioDefault 0x10 // bit c0:4
//// third reg (e)
#define cAudioIF_4_5 0x00 // bit e0:1
@@ -146,13 +148,15 @@ static struct i2c_client client_template;
static struct tvnorm tvnorms[] = {
{
- .std = V4L2_STD_PAL_BG,
- .name = "PAL-BG",
+ .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
+ .name = "PAL-BGHN",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_5_5 |
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_5_5 |
cVideoIF_38_90 ),
},{
.std = V4L2_STD_PAL_I,
@@ -160,8 +164,10 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_0 |
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_0 |
cVideoIF_38_90 ),
},{
.std = V4L2_STD_PAL_DK,
@@ -169,52 +175,80 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_5 |
- cVideoIF_38_00 ),
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_38_90 ),
},{
- .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N,
- .name = "PAL-M/N",
+ .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
+ .name = "PAL-M/Nc",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis75 ),
- .e = ( cAudioIF_4_5 |
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
+ .e = ( cGating_36 |
+ cAudioIF_4_5 |
cVideoIF_45_75 ),
},{
+ .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
+ .name = "SECAM-BGH",
+ .b = ( cPositiveAmTV |
+ cQSS ),
+ .c = ( cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_5_5 |
+ cVideoIF_38_90 ),
+ },{
.std = V4L2_STD_SECAM_L,
.name = "SECAM-L",
.b = ( cPositiveAmTV |
cQSS ),
+ .c = ( cTopPalSecamDefault),
.e = ( cGating_36 |
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{
+ .std = V4L2_STD_SECAM_LC,
+ .name = "SECAM-L'",
+ .b = ( cOutputPort2Inactive |
+ cPositiveAmTV |
+ cQSS ),
+ .c = ( cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_33_90 ),
+ },{
.std = V4L2_STD_SECAM_DK,
.name = "SECAM-DK",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
- .e = ( cAudioIF_6_5 |
- cVideoIF_38_00 ),
+ cDeemphasis50 |
+ cTopPalSecamDefault),
+ .e = ( cGating_36 |
+ cAudioIF_6_5 |
+ cVideoIF_38_90 ),
},{
.std = V4L2_STD_NTSC_M,
.name = "NTSC-M",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis75 ),
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_45_75 ),
},{
.std = V4L2_STD_NTSC_M_JP,
- .name = "NTSC-JP",
+ .name = "NTSC-M-JP",
.b = ( cNegativeFmTV |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
+ cDeemphasis50 |
+ cTopNtscRadioDefault),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_58_75 ),
@@ -226,8 +260,10 @@ static struct tvnorm radio_stereo = {
.b = ( cFmRadio |
cQSS ),
.c = ( cDeemphasisOFF |
- cAudioGain6 ),
- .e = ( cAudioIF_5_5 |
+ cAudioGain6 |
+ cTopNtscRadioDefault),
+ .e = ( cTunerGainLow |
+ cAudioIF_5_5 |
cRadioIF_38_90 ),
};
@@ -236,8 +272,10 @@ static struct tvnorm radio_mono = {
.b = ( cFmRadio |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50),
- .e = ( cAudioIF_5_5 |
+ cDeemphasis75 |
+ cTopNtscRadioDefault),
+ .e = ( cTunerGainLow |
+ cAudioIF_5_5 |
cRadioIF_38_90 ),
};
@@ -400,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
static unsigned int port1 = UNSET;
static unsigned int port2 = UNSET;
static unsigned int qss = UNSET;
-static unsigned int adjust = 0x10;
+static unsigned int adjust = UNSET;
+
module_param(port1, int, 0644);
module_param(port2, int, 0644);
module_param(qss, int, 0644);
@@ -428,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
buf[1] &= ~cQSS;
}
- if (adjust >= 0x00 && adjust < 0x20)
+ if (adjust >= 0x00 && adjust < 0x20) {
+ buf[2] &= ~cTopMask;
buf[2] |= adjust;
+ }
return 0;
}
@@ -465,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
break;
}
}
+ if (t->config & TDA9887_TOP_SET) {
+ buf[2] &= ~cTopMask;
+ buf[2] |= (t->config >> 8) & cTopMask;
+ }
if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
buf[1] &= ~cQSS;
return 0;
@@ -472,38 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
/* ---------------------------------------------------------------------- */
-static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
-{
- unsigned int bCarrierMode = UNSET;
-
- if (t->std & V4L2_STD_625_50) {
- if ((1 == t->pinnacle_id) || (7 == t->pinnacle_id)) {
- bCarrierMode = cIntercarrier;
- } else {
- bCarrierMode = cQSS;
- }
- }
- if (t->std & V4L2_STD_525_60) {
- if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) {
- bCarrierMode = cIntercarrier;
- } else {
- bCarrierMode = cQSS;
- }
- }
-
- if (bCarrierMode != UNSET) {
- buf[1] &= ~0x04;
- buf[1] |= bCarrierMode;
- }
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
-static char pal[] = "-";
module_param_string(pal, pal, sizeof(pal), 0644);
-static char secam[] = "-";
module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
static int tda9887_fixup_std(struct tda9887 *t)
{
@@ -514,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t)
case 'B':
case 'g':
case 'G':
- tda9887_dbg("insmod fixup: PAL => PAL-BG\n");
- t->std = V4L2_STD_PAL_BG;
+ case 'h':
+ case 'H':
+ case 'n':
+ case 'N':
+ if (pal[1] == 'c' || pal[1] == 'C') {
+ tda9887_dbg("insmod fixup: PAL => PAL-Nc\n");
+ t->std = V4L2_STD_PAL_Nc;
+ } else {
+ tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n");
+ t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N;
+ }
break;
case 'i':
case 'I':
@@ -529,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
t->std = V4L2_STD_PAL_DK;
break;
+ case 'm':
+ case 'M':
+ tda9887_dbg("insmod fixup: PAL => PAL-M\n");
+ t->std = V4L2_STD_PAL_M;
+ break;
case '-':
/* default parameter, do nothing */
break;
@@ -539,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t)
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
switch (secam[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n");
+ t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ break;
case 'd':
case 'D':
case 'k':
@@ -548,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t)
break;
case 'l':
case 'L':
- tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
- t->std = V4L2_STD_SECAM_L;
+ if (secam[1] == 'c' || secam[1] == 'C') {
+ tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n");
+ t->std = V4L2_STD_SECAM_LC;
+ } else {
+ tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
+ t->std = V4L2_STD_SECAM_L;
+ }
break;
case '-':
/* default parameter, do nothing */
@@ -559,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t)
break;
}
}
+ if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
+ tda9887_dbg("insmod fixup: NTSC => NTSC-M\n");
+ t->std = V4L2_STD_NTSC_M;
+ break;
+ case 'j':
+ case 'J':
+ tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
+ t->std = V4L2_STD_NTSC_M_JP;
+ break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tda9887_info("ntsc= argument not recognised\n");
+ break;
+ }
+ }
return 0;
}
@@ -581,12 +649,22 @@ static int tda9887_configure(struct tda9887 *t)
memset(t->data,0,sizeof(t->data));
tda9887_set_tvnorm(t,t->data);
+ /* A note on the port settings:
+ These settings tend to depend on the specifics of the board.
+ By default they are set to inactive (bit value 1) by this driver,
+ overwriting any changes made by the tvnorm. This means that it
+ is the responsibility of the module using the tda9887 to set
+ these values in case of changes in the tvnorm.
+ In many cases port 2 should be made active (0) when selecting
+ SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
+
+ For the other standards the tda9887 application note says that
+ the ports should be set to active (0), but, again, that may
+ differ depending on the precise hardware configuration.
+ */
t->data[1] |= cOutputPort1Inactive;
t->data[1] |= cOutputPort2Inactive;
- if (UNSET != t->pinnacle_id) {
- tda9887_set_pinnacle(t,t->data);
- }
tda9887_set_config(t,t->data);
tda9887_set_insmod(t,t->data);
@@ -594,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t)
t->data[1] |= cForcedMuteAudioON;
}
-
tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
t->data[1],t->data[2],t->data[3]);
if (debug > 1)
@@ -619,13 +696,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
- if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
+ if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
- memset(t,0,sizeof(*t));
t->client = client_template;
t->std = 0;
- t->pinnacle_id = UNSET;
t->radio_mode = V4L2_TUNER_MODE_STEREO;
tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name);
@@ -638,18 +713,8 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
static int tda9887_probe(struct i2c_adapter *adap)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9887_attach);
-#else
- switch (adap->id) {
- case I2C_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, tda9887_attach);
- break;
- }
-#endif
return 0;
}
@@ -689,14 +754,6 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
tda9887_configure(t);
break;
}
- case AUDC_CONFIG_PINNACLE:
- {
- int *i = arg;
-
- t->pinnacle_id = *i;
- tda9887_configure(t);
- break;
- }
case TDA9887_SET_CONFIG:
{
int *i = arg;
@@ -787,7 +844,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
case VIDIOC_LOG_STATUS:
{
- tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]);
+ tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]);
break;
}
default:
@@ -819,14 +876,12 @@ static int tda9887_resume(struct device * dev)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "i2c tda9887 driver",
.id = -1, /* FIXME */
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tda9887_probe,
.detach_client = tda9887_detach,
.command = tda9887_command,
.driver = {
+ .name = "tda9887",
.suspend = tda9887_suspend,
.resume = tda9887_resume,
},
@@ -834,7 +889,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "tda9887",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index a9375ef05de1..c2b98f81c192 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -17,6 +17,9 @@
#define PREFIX "TEA5767 "
+/* from tuner-core.c */
+extern int tuner_debug;
+
/*****************************************************************************/
/******************************
@@ -59,7 +62,7 @@
#define TEA5767_PORT1_HIGH 0x01
-/* Forth register */
+/* Fourth register */
#define TEA5767_PORT2_HIGH 0x80
/* Chips stops working. Only I2C bus remains on */
#define TEA5767_STDBY 0x40
@@ -82,7 +85,7 @@
/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
#define TEA5767_SRCH_IND 0x01
-/* Fiveth register */
+/* Fifth register */
/* By activating, it will use Xtal at 13 MHz as reference for divider */
#define TEA5767_PLLREF_ENABLE 0x80
@@ -106,13 +109,13 @@
#define TEA5767_STEREO_MASK 0x80
#define TEA5767_IF_CNTR_MASK 0x7f
-/* Four register */
+/* Fourth register */
#define TEA5767_ADC_LEVEL_MASK 0xf0
/* should be 0 */
#define TEA5767_CHIP_ID_MASK 0x0f
-/* Fiveth register */
+/* Fifth register */
/* Reserved for future extensions */
#define TEA5767_RESERVED_MASK 0xff
@@ -217,19 +220,19 @@ static void set_radio_freq(struct i2c_client *c, unsigned int frq)
tuner_dbg ("TEA5767 radio HIGH LO inject xtal @ 13 MHz\n");
buffer[2] |= TEA5767_HIGH_LO_INJECT;
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 + 700000 + 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_13MHz:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 13 MHz\n");
buffer[4] |= TEA5767_PLLREF_ENABLE;
- div = (frq * 4000 / 16 - 700000 - 225000 + 25000) / 50000;
+ div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
break;
case TEA5767_LOW_LO_32768:
tuner_dbg ("TEA5767 radio LOW LO inject xtal @ 32,768 MHz\n");
buffer[3] |= TEA5767_XTAL_32768;
/* const 700=4000*175 Khz - to adjust freq to right value */
- div = ((frq * 4000 / 16 - 700000 - 225000) + 16384) >> 15;
+ div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
break;
case TEA5767_HIGH_LO_32768:
default:
@@ -264,7 +267,7 @@ static int tea5767_signal(struct i2c_client *c)
if (5 != (rc = i2c_master_recv(c, buffer, 5)))
tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
- return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << (13 - 4));
+ return ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
}
static int tea5767_stereo(struct i2c_client *c)
@@ -347,8 +350,8 @@ int tea5767_tuner_init(struct i2c_client *c)
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->set_tv_freq = set_tv_freq;
+ t->set_radio_freq = set_radio_freq;
t->has_signal = tea5767_signal;
t->is_stereo = tea5767_stereo;
t->standby = tea5767_standby;
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index ee3688348b66..bb35844e3842 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -36,7 +36,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
#define TEA6415C_NUM_INPUTS 8
#define TEA6415C_NUM_OUTPUTS 6
@@ -190,10 +190,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tea6415c",
+ .driver = {
+ .name = "tea6415c",
+ },
.id = I2C_DRIVERID_TEA6415C,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 17975c19da5e..4dcba5a4fff0 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -36,7 +36,7 @@ static int debug = 0; /* insmod parameter */
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
#define dprintk(args...) \
- do { if (debug) { printk("%s: %s()[%d]: ",__stringify(KBUILD_MODNAME), __FUNCTION__, __LINE__); printk(args); } } while (0)
+ do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __FUNCTION__, __LINE__); printk(args); } } while (0)
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
@@ -99,11 +99,10 @@ static int tea6420_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* allocate memory for client structure */
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (0 == client) {
return -ENOMEM;
}
- memset(client, 0x0, sizeof(struct i2c_client));
/* fill client structure */
memcpy(client, &client_template, sizeof(struct i2c_client));
@@ -167,10 +166,10 @@ static int command(struct i2c_client *client, unsigned int cmd, void *arg)
}
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tea6420",
+ .driver = {
+ .name = "tea6420",
+ },
.id = I2C_DRIVERID_TEA6420,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = attach,
.detach_client = detach,
.command = command,
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 79203595b9c1..c4a78e7a5a58 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -175,10 +175,10 @@ tuner_probe(struct i2c_adapter *adap)
static struct i2c_driver
i2c_driver_tuner =
{
- .owner = THIS_MODULE,
- .name = "sab3036",
+ .driver = {
+ .name = "sab3036",
+ },
.id = I2C_DRIVERID_SAB3036,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command
@@ -193,8 +193,7 @@ static struct i2c_client client_template =
static int __init
tuner3036_init(void)
{
- i2c_add_driver(&i2c_driver_tuner);
- return 0;
+ return i2c_add_driver(&i2c_driver_tuner);
}
static void __exit
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index e58abdfcaab8..2995b22acb43 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -20,10 +20,9 @@
#include <linux/init.h>
#include <media/tuner.h>
+#include <media/v4l2-common.h>
#include <media/audiochip.h>
-#include "msp3400.h"
-
#define UNSET (-1U)
/* standard i2c insmod options */
@@ -38,21 +37,30 @@ I2C_CLIENT_INSMOD;
/* insmod options used at init time => read/only */
static unsigned int addr = 0;
-module_param(addr, int, 0444);
-
static unsigned int no_autodetect = 0;
-module_param(no_autodetect, int, 0444);
-
static unsigned int show_i2c = 0;
-module_param(show_i2c, int, 0444);
/* insmod options used at runtime => read/write */
-unsigned int tuner_debug = 0;
-module_param(tuner_debug, int, 0644);
+static unsigned int tuner_debug_old = 0;
+int tuner_debug = 0;
static unsigned int tv_range[2] = { 44, 958 };
static unsigned int radio_range[2] = { 65, 108 };
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+
+module_param(addr, int, 0444);
+module_param(no_autodetect, int, 0444);
+module_param(show_i2c, int, 0444);
+/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */
+module_param_named(tuner_debug,tuner_debug_old, int, 0444);
+module_param_named(debug,tuner_debug, int, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
module_param_array(tv_range, int, NULL, 0644);
module_param_array(radio_range, int, NULL, 0644);
@@ -74,7 +82,7 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->tv_freq) {
+ if (NULL == t->set_tv_freq) {
tuner_warn ("Tuner has no way to set tv freq\n");
return;
}
@@ -82,8 +90,14 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
freq / 16, freq % 16 * 100 / 16, tv_range[0],
tv_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < tv_range[0] * 16)
+ freq = tv_range[0] * 16;
+ else
+ freq = tv_range[1] * 16;
}
- t->tv_freq(c, freq);
+ t->set_tv_freq(c, freq);
}
static void set_radio_freq(struct i2c_client *c, unsigned int freq)
@@ -94,18 +108,23 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
tuner_warn ("tuner type not set\n");
return;
}
- if (NULL == t->radio_freq) {
+ if (NULL == t->set_radio_freq) {
tuner_warn ("tuner has no way to set radio frequency\n");
return;
}
- if (freq <= radio_range[0] * 16000 || freq >= radio_range[1] * 16000) {
+ if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
freq / 16000, freq % 16000 * 100 / 16000,
radio_range[0], radio_range[1]);
+ /* V4L2 spec: if the freq is not possible then the closest
+ possible value should be selected */
+ if (freq < radio_range[0] * 16000)
+ freq = radio_range[0] * 16000;
+ else
+ freq = radio_range[1] * 16000;
}
- t->radio_freq(c, freq);
- return;
+ t->set_radio_freq(c, freq);
}
static void set_freq(struct i2c_client *c, unsigned long freq)
@@ -117,15 +136,16 @@ static void set_freq(struct i2c_client *c, unsigned long freq)
tuner_dbg("radio freq set to %lu.%02lu\n",
freq / 16000, freq % 16000 * 100 / 16000);
set_radio_freq(c, freq);
+ t->radio_freq = freq;
break;
case V4L2_TUNER_ANALOG_TV:
case V4L2_TUNER_DIGITAL_TV:
tuner_dbg("tv freq set to %lu.%02lu\n",
freq / 16, freq % 16 * 100 / 16);
set_tv_freq(c, freq);
+ t->tv_freq = freq;
break;
}
- t->freq = freq;
}
static void set_type(struct i2c_client *c, unsigned int type,
@@ -204,9 +224,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
if (t->mode_mask == T_UNINITIALIZED)
t->mode_mask = new_mode_mask;
- set_freq(c, t->freq);
+ set_freq(c, (V4L2_TUNER_RADIO == t->mode) ? t->radio_freq : t->tv_freq);
tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
- c->adapter->name, c->driver->name, c->addr << 1, type,
+ c->adapter->name, c->driver->driver.name, c->addr << 1, type,
t->mode_mask);
}
@@ -249,11 +269,6 @@ static inline int check_mode(struct tuner *t, char *cmd)
return 0;
}
-static char pal[] = "-";
-module_param_string(pal, pal, sizeof(pal), 0644);
-static char secam[] = "--";
-module_param_string(secam, secam, sizeof(secam), 0644);
-
/* get more precise norm info from insmod option */
static int tuner_fixup_std(struct tuner *t)
{
@@ -285,8 +300,13 @@ static int tuner_fixup_std(struct tuner *t)
break;
case 'N':
case 'n':
- tuner_dbg ("insmod fixup: PAL => PAL-N\n");
- t->std = V4L2_STD_PAL_N;
+ if (pal[1] == 'c' || pal[1] == 'C') {
+ tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
+ t->std = V4L2_STD_PAL_Nc;
+ } else {
+ tuner_dbg ("insmod fixup: PAL => PAL-N\n");
+ t->std = V4L2_STD_PAL_N;
+ }
break;
case '-':
/* default parameter, do nothing */
@@ -298,6 +318,15 @@ static int tuner_fixup_std(struct tuner *t)
}
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
switch (secam[0]) {
+ case 'b':
+ case 'B':
+ case 'g':
+ case 'G':
+ case 'h':
+ case 'H':
+ tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
+ t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+ break;
case 'd':
case 'D':
case 'k':
@@ -324,9 +353,60 @@ static int tuner_fixup_std(struct tuner *t)
}
}
+ if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
+ switch (ntsc[0]) {
+ case 'm':
+ case 'M':
+ tuner_dbg("insmod fixup: NTSC => NTSC-M\n");
+ t->std = V4L2_STD_NTSC_M;
+ break;
+ case 'j':
+ case 'J':
+ tuner_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
+ t->std = V4L2_STD_NTSC_M_JP;
+ break;
+ case '-':
+ /* default parameter, do nothing */
+ break;
+ default:
+ tuner_info("ntsc= argument not recognised\n");
+ break;
+ }
+ }
return 0;
}
+static void tuner_status(struct i2c_client *client)
+{
+ struct tuner *t = i2c_get_clientdata(client);
+ unsigned long freq, freq_fraction;
+ const char *p;
+
+ switch (t->mode) {
+ case V4L2_TUNER_RADIO: p = "radio"; break;
+ case V4L2_TUNER_ANALOG_TV: p = "analog TV"; break;
+ case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
+ default: p = "undefined"; break;
+ }
+ if (t->mode == V4L2_TUNER_RADIO) {
+ freq = t->radio_freq / 16000;
+ freq_fraction = (t->radio_freq % 16000) * 100 / 16000;
+ } else {
+ freq = t->tv_freq / 16;
+ freq_fraction = (t->tv_freq % 16) * 100 / 16;
+ }
+ tuner_info("Tuner mode: %s\n", p);
+ tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction);
+ tuner_info("Standard: 0x%08llx\n", t->std);
+ if (t->mode == V4L2_TUNER_RADIO) {
+ if (t->has_signal) {
+ tuner_info("Signal strength: %d\n", t->has_signal(client));
+ }
+ if (t->is_stereo) {
+ tuner_info("Stereo: %s\n", t->is_stereo(client) ? "yes" : "no");
+ }
+ }
+}
/* ---------------------------------------------------------------------- */
/* static var Used only in tuner_attach and tuner_probe */
@@ -342,16 +422,20 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
client_template.adapter = adap;
client_template.addr = addr;
- t = kmalloc(sizeof(struct tuner), GFP_KERNEL);
+ t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
if (NULL == t)
return -ENOMEM;
- memset(t, 0, sizeof(struct tuner));
memcpy(&t->i2c, &client_template, sizeof(struct i2c_client));
i2c_set_clientdata(&t->i2c, t);
t->type = UNSET;
t->radio_if2 = 10700 * 1000; /* 10.7MHz - FM radio */
t->audmode = V4L2_TUNER_MODE_STEREO;
t->mode_mask = T_UNINITIALIZED;
+ if (tuner_debug_old) {
+ tuner_debug = tuner_debug_old;
+ printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
+ printk(KERN_ERR "tuner: use the debug option instead.\n");
+ }
if (show_i2c) {
unsigned char buffer[16];
@@ -384,7 +468,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
t->type = TUNER_TEA5767;
t->mode_mask = T_RADIO;
t->mode = T_STANDBY;
- t->freq = 87.5 * 16; /* Sets freq to FM range */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask &= ~T_RADIO;
goto register_client;
@@ -397,7 +481,8 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
if (default_mode_mask != T_UNINITIALIZED) {
tuner_dbg ("Setting mode_mask to 0x%02x\n", default_mode_mask);
t->mode_mask = default_mode_mask;
- t->freq = 400 * 16; /* Sets freq to VHF High */
+ t->tv_freq = 400 * 16; /* Sets freq to VHF High */
+ t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
default_mode_mask = T_UNINITIALIZED;
}
@@ -478,7 +563,9 @@ static inline int check_v4l2(struct tuner *t)
static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct tuner *t = i2c_get_clientdata(client);
- unsigned int *iarg = (int *)arg;
+
+ if (tuner_debug>1)
+ v4l_i2c_print_ioctl(&(t->i2c),cmd);
switch (cmd) {
/* --- configuration --- */
@@ -491,27 +578,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
set_addr(client, (struct tuner_setup *)arg);
break;
case AUDC_SET_RADIO:
- set_mode(client,t,V4L2_TUNER_RADIO, "AUDC_SET_RADIO");
+ if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO")
+ == EINVAL)
+ return 0;
+ if (t->radio_freq)
+ set_freq(client, t->radio_freq);
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:
- switch (*iarg) {
- case 2:
- tuner_dbg("pinnacle pal\n");
- t->radio_if2 = 33300 * 1000;
- break;
- case 3:
- tuner_dbg("pinnacle ntsc\n");
- t->radio_if2 = 41300 * 1000;
- break;
- }
+ if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
+ return 0;
+ if (t->standby)
+ t->standby (client);
break;
case VIDIOCSAUDIO:
if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
@@ -521,10 +598,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
/* Should be implemented, since bttv calls it */
tuner_dbg("VIDIOCSAUDIO not implemented.\n");
-
- break;
- case MSP_SET_MATRIX:
- case TDA9887_SET_CONFIG:
break;
/* --- v4l ioctls --- */
/* take care: bttv does userspace copying, we'll get a
@@ -550,8 +623,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tuner_fixup_std(t);
- if (t->freq)
- set_tv_freq(client, t->freq);
+ if (t->tv_freq)
+ set_tv_freq(client, t->tv_freq);
return 0;
}
case VIDIOCSFREQ:
@@ -625,15 +698,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
t->std = *id;
tuner_fixup_std(t);
- if (t->freq)
- set_freq(client, t->freq);
+ if (t->tv_freq)
+ set_freq(client, t->tv_freq);
break;
}
case VIDIOC_S_FREQUENCY:
{
struct v4l2_frequency *f = arg;
- t->freq = f->frequency;
switch_v4l2();
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode) {
@@ -641,7 +713,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
== EINVAL)
return 0;
}
- set_freq(client,t->freq);
+ set_freq(client,f->frequency);
break;
}
@@ -653,7 +725,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
switch_v4l2();
f->type = t->mode;
- f->frequency = t->freq;
+ f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+ t->radio_freq : t->tv_freq;
break;
}
case VIDIOC_G_TUNER:
@@ -704,14 +777,12 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
if (V4L2_TUNER_RADIO == t->mode) {
t->audmode = tuner->audmode;
- set_radio_freq(client, t->freq);
+ set_radio_freq(client, t->radio_freq);
}
break;
}
- default:
- tuner_dbg("Unimplemented IOCTL 0x%08x(dir=%d,tp='%c',nr=%d,sz=%d)\n",
- cmd, _IOC_DIR(cmd), _IOC_TYPE(cmd),
- _IOC_NR(cmd), _IOC_SIZE(cmd));
+ case VIDIOC_LOG_STATUS:
+ tuner_status(client);
break;
}
@@ -734,29 +805,31 @@ static int tuner_resume(struct device *dev)
struct tuner *t = i2c_get_clientdata (c);
tuner_dbg ("resume\n");
- if (t->freq)
- set_freq(c, t->freq);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->radio_freq)
+ set_freq(c, t->radio_freq);
+ } else {
+ if (t->tv_freq)
+ set_freq(c, t->tv_freq);
+ }
return 0;
}
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tuner",
.id = I2C_DRIVERID_TUNER,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tuner_probe,
.detach_client = tuner_detach,
.command = tuner_command,
.driver = {
- .suspend = tuner_suspend,
- .resume = tuner_resume,
- },
+ .name = "tuner",
+ .suspend = tuner_suspend,
+ .resume = tuner_resume,
+ },
};
static struct i2c_client client_template = {
.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 e0c9fdb9914a..37977ff49780 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -8,6 +8,10 @@
#include <linux/videodev.h>
#include <media/tuner.h>
+static int offset = 0;
+module_param(offset, int, 0666);
+MODULE_PARM_DESC(offset,"Allows to specify an offset for tuner");
+
/* ---------------------------------------------------------------------- */
/* tv standard selection for Temic 4046 FM5
@@ -75,188 +79,16 @@
#define TUNER_PLL_LOCKED 0x40
#define TUNER_STEREO_MK3 0x04
-/* ---------------------------------------------------------------------- */
-
-struct tunertype
-{
- char *name;
- unsigned char Vendor;
- unsigned char Type;
-
- unsigned short thresh1; /* band switch VHF_LO <=> VHF_HI */
- unsigned short thresh2; /* band switch VHF_HI <=> UHF */
- unsigned char VHF_L;
- unsigned char VHF_H;
- unsigned char UHF;
- unsigned char config;
- unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL,
- 732 =16*45.75 NTSCi,
- 940 =16*58.75 NTSC-Japan
- 704 =16*44 ATSC */
-};
-
-/*
- * The floats in the tuner struct are computed at compile time
- * by gcc and cast back to integers. Thus we don't violate the
- * "no float in kernel" rule.
+#define TUNER_PARAM_ANALOG 0 /* to be removed */
+/* FIXME:
+ * Right now, all tuners are using the first tuner_params[] array element
+ * for analog mode. In the future, we will be merging similar tuner
+ * definitions together, such that each tuner definition will have a
+ * tuner_params struct for each available video standard. At that point,
+ * TUNER_PARAM_ANALOG will be removed, and the tuner_params[] array
+ * element will be chosen based on the video standard in use.
+ *
*/
-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,
- 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
- { "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC,
- 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,
- 16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
- { "Temic NTSC (4032 FY5)", TEMIC, NTSC,
- 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},
-
- /* 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,
- 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
- { "Temic PAL_DK (4016 FY5)", TEMIC, PAL,
- 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
- { "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,
- 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
- { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
- 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,
- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
- { "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I,
- 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 */
- 16*169,16*464,0xA0,0x90,0x30,0x8e,623},
- { "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,
- 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
- { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL,
- 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
- { "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,
- 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,
- 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,
- /* see tda8290.c for details */ },
- { "TCL 2002MB", TCL, 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,
- 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
- { "Ymec TVision TVF-8531MF/8831MF/8731MF", Philips, NTSC,
- 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
- { "Ymec TVision TVF-5533MF", Philips, NTSC,
- 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
-
- /* 60-69 */
- { "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,
- 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623},
- { "Philips TEA5767HN FM Radio", Philips, RADIO,
- /* 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, 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 },
- { "Philips TD1316 Hybrid Tuner", Philips, PAL,
- 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 },
- { "Philips TUV1236D ATSC/NTSC dual in", Philips, ATSC,
- 16*157.25,16*454.00,0x01,0x02,0x04,0xce,732 },
- { "Tena TNF 5335 MF", Philips, NTSC,
- 16*157.25,16*454.00,0x01,0x02,0x04,0x8e,732 },
-};
-
-unsigned const int tuner_count = ARRAY_SIZE(tuners);
/* ---------------------------------------------------------------------- */
@@ -304,21 +136,27 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
u8 config, tuneraddr;
u16 div;
struct tunertype *tun;
- unsigned char buffer[4];
- int rc;
+ u8 buffer[4];
+ int rc, IFPCoff, i, j;
tun = &tuners[t->type];
- if (freq < tun->thresh1) {
- config = tun->VHF_L;
- tuner_dbg("tv: VHF lowrange\n");
- } else if (freq < tun->thresh2) {
- config = tun->VHF_H;
- tuner_dbg("tv: VHF high range\n");
- } else {
- config = tun->UHF;
- tuner_dbg("tv: UHF range\n");
- }
+ j = TUNER_PARAM_ANALOG;
+ for (i = 0; i < tun->params[j].count; i++) {
+ if (freq > tun->params[j].ranges[i].limit)
+ continue;
+ break;
+ }
+ if (i == tun->params[j].count) {
+ tuner_dbg("TV frequency out of range (%d > %d)",
+ freq, tun->params[j].ranges[i - 1].limit);
+ freq = tun->params[j].ranges[--i].limit;
+ }
+ config = tun->params[j].ranges[i].cb;
+ /* i == 0 -> VHF_LO */
+ /* i == 1 -> VHF_HI */
+ /* i == 2 -> UHF */
+ tuner_dbg("tv: range %d\n",i);
/* tv norm specific stuff for multi-norm tuners */
switch (t->type) {
@@ -377,7 +215,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
case TUNER_MICROTUNE_4042FI5:
/* Set the charge pump for fast tuning */
- tun->config |= TUNER_CHARGE_PUMP;
+ tun->params[j].config |= TUNER_CHARGE_PUMP;
break;
case TUNER_PHILIPS_TUV1236D:
@@ -406,32 +244,49 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
break;
}
- /*
- * Philips FI1216MK2 remark from specification :
- * for channel selection involving band switching, and to ensure
- * smooth tuning to the desired channel without causing
- * unnecessary charge pump action, it is recommended to consider
- * the difference between wanted channel frequency and the
- * current channel frequency. Unnecessary charge pump action
- * will result in very low tuning voltage which may drive the
- * oscillator to extreme conditions.
- *
- * Progfou: specification says to send config data before
- * frequency in case (wanted frequency < current frequency).
- */
-
- div=freq + tun->IFPCoff;
- if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
- buffer[0] = tun->config;
+ /* IFPCoff = Video Intermediate Frequency - Vif:
+ 940 =16*58.75 NTSC/J (Japan)
+ 732 =16*45.75 M/N STD
+ 704 =16*44 ATSC (at DVB code)
+ 632 =16*39.50 I U.K.
+ 622.4=16*38.90 B/G D/K I, L STD
+ 592 =16*37.00 D China
+ 590 =16.36.875 B Australia
+ 543.2=16*33.95 L' STD
+ 171.2=16*10.70 FM Radio (at set_radio_freq)
+ */
+
+ if (t->std == V4L2_STD_NTSC_M_JP) {
+ IFPCoff = 940;
+ } else if ((t->std & V4L2_STD_MN) &&
+ !(t->std & ~V4L2_STD_MN)) {
+ IFPCoff = 732;
+ } else if (t->std == V4L2_STD_SECAM_LC) {
+ IFPCoff = 543;
+ } else {
+ IFPCoff = 623;
+ }
+
+ div=freq + IFPCoff + offset;
+
+ tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
+ freq / 16, freq % 16 * 100 / 16,
+ IFPCoff / 16, IFPCoff % 16 * 100 / 16,
+ offset / 16, offset % 16 * 100 / 16,
+ div);
+
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = tun->params[j].config;
buffer[1] = config;
buffer[2] = (div>>8) & 0x7f;
buffer[3] = div & 0xff;
} else {
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
}
+ t->last_div = div;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -457,10 +312,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
}
/* Set the charge pump for optimized phase noise figure */
- tun->config &= ~TUNER_CHARGE_PUMP;
+ tun->params[j].config &= ~TUNER_CHARGE_PUMP;
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
- buffer[2] = tun->config;
+ buffer[2] = tun->params[j].config;
buffer[3] = config;
tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
@@ -474,13 +329,15 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
{
struct tunertype *tun;
struct tuner *t = i2c_get_clientdata(c);
- unsigned char buffer[4];
- unsigned div;
- int rc;
+ u8 buffer[4];
+ u16 div;
+ int rc, j;
tun = &tuners[t->type];
+ j = TUNER_PARAM_ANALOG;
+
div = (20 * freq / 16000) + (int)(20*10.7); /* IF 10.7 MHz */
- buffer[2] = (tun->config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
+ buffer[2] = (tun->params[j].config & ~TUNER_RATIO_MASK) | TUNER_RATIO_SELECT_50; /* 50 kHz step */
switch (t->type) {
case TUNER_TENA_9533_DI:
@@ -509,9 +366,19 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
}
buffer[0] = (div>>8) & 0x7f;
buffer[1] = div & 0xff;
+ if (tuners[t->type].params->cb_first_if_lower_freq && div < t->last_div) {
+ buffer[0] = buffer[2];
+ buffer[1] = buffer[3];
+ buffer[2] = (div>>8) & 0x7f;
+ buffer[3] = div & 0xff;
+ } else {
+ buffer[0] = (div>>8) & 0x7f;
+ buffer[1] = div & 0xff;
+ }
tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
buffer[0],buffer[1],buffer[2],buffer[3]);
+ t->last_div = div;
if (4 != (rc = i2c_master_send(c,buffer,4)))
tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
@@ -525,10 +392,10 @@ int default_tuner_init(struct i2c_client *c)
t->type, tuners[t->type].name);
strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
- t->tv_freq = default_set_tv_freq;
- t->radio_freq = default_set_radio_freq;
+ t->set_tv_freq = default_set_tv_freq;
+ t->set_radio_freq = default_set_radio_freq;
t->has_signal = tuner_signal;
- t->is_stereo = tuner_stereo;
+ t->is_stereo = tuner_stereo;
t->standby = NULL;
return 0;
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
new file mode 100644
index 000000000000..6fe781798d89
--- /dev/null
+++ b/drivers/media/video/tuner-types.c
@@ -0,0 +1,1406 @@
+/*
+ *
+ * i2c tv tuner chip device type database.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <media/tuner.h>
+#include <media/tuner-types.h>
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * The floats in the tuner struct are computed at compile time
+ * by gcc and cast back to integers. Thus we don't violate the
+ * "no float in kernel" rule.
+ *
+ * A tuner_range may be referenced by multiple tuner_params structs.
+ * There are many duplicates in here. Reusing tuner_range structs,
+ * rather than defining new ones for each tuner, will cut down on
+ * memory usage, and is preferred when possible.
+ *
+ * Each tuner_params array may contain one or more elements, one
+ * for each video standard.
+ *
+ * FIXME: Some tuner_range definitions are duplicated, and
+ * should be eliminated.
+ *
+ * FIXME: tunertype struct contains an element, has_tda988x.
+ * We must set this for all tunertypes that contain a tda988x
+ * chip, and then we can remove this setting from the various
+ * card structs.
+ */
+
+/* 0-9 */
+/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
+
+static struct tuner_range tuner_philips_pal_i_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 451.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
+
+static struct tuner_range tuner_philips_secam_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa7, },
+ { 16 * 447.25 /*MHz*/, 0x97, },
+ { 16 * 999.99 , 0x37, },
+};
+
+static struct tuner_params tuner_philips_secam_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_SECAM,
+ .ranges = tuner_philips_secam_ranges,
+ .count = ARRAY_SIZE(tuner_philips_secam_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 447.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_pal_i_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x02, },
+ { 16 * 450.00 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_i_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_i_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4036fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_alps_tsb_1_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 385.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 10-19 */
+/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_alps_tsb_1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_1_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
+
+static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
+ { 16 * 133.25 /*MHz*/, 0x01, },
+ { 16 * 351.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_alps_tsbb5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbe5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
+
+static struct tuner_params tuner_alps_tsbc5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_alps_tsb_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4006fh5_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4006fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4006fh5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4006fh5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
+
+static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x14, },
+ { 16 * 385.25 /*MHz*/, 0x12, },
+ { 16 * 999.99 , 0x11, },
+};
+
+static struct tuner_params tuner_alps_tshc6_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_alps_tshc6_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_pal_dk_ranges[] = {
+ { 16 * 168.25 /*MHz*/, 0xa0, },
+ { 16 * 456.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_pal_dk_ranges,
+ .count = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_ntsc_m_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_ntsc_m_ranges,
+ .count = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
+
+static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_40x6f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 20-29 */
+/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
+ { 16 * 141.00 /*MHz*/, 0xa0, },
+ { 16 * 464.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4009f_5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4039fr5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4039fr5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4039fr5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4039fr5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4046fm5_pal_ranges[] = {
+ { 16 * 169.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4046fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4046fm5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4046fm5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
+
+static struct tuner_range tuner_lg_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0xa0, },
+ { 16 * 450.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_pal_dk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
+
+static struct tuner_params tuner_philips_fq1216me_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
+
+static struct tuner_params tuner_lg_pal_i_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
+ { 16 * 210.00 /*MHz*/, 0xa0, },
+ { 16 * 497.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_lg_ntsc_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_fm_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
+
+static struct tuner_params tuner_lg_pal_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_pal_ranges,
+ .count = ARRAY_SIZE(tuner_lg_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 30-39 */
+/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
+
+static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 317.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
+
+static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
+ { 16 * 169 /*MHz*/, 0xa0, },
+ { 16 * 464 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
+
+static struct tuner_params tuner_temic_4106fh5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
+
+static struct tuner_range tuner_temic_4012fy5_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x02, },
+ { 16 * 463.25 /*MHz*/, 0x04, },
+ { 16 * 999.99 , 0x01, },
+};
+
+static struct tuner_params tuner_temic_4012fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4012fy5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4012fy5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
+
+static struct tuner_range tuner_temic_4136_fy5_ntsc_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0xa0, },
+ { 16 * 453.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_temic_4136_fy5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_temic_4136_fy5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4136_fy5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
+
+static struct tuner_range tuner_lg_new_tapc_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
+ { 16 * 158.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_fm1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
+
+static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 40-49 */
+/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
+
+static struct tuner_params tuner_hitachi_ntsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_new_tapc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
+ { 16 * 140.25 /*MHz*/, 0x01, },
+ { 16 * 463.25 /*MHz*/, 0xc2, },
+ { 16 * 999.99 , 0xcf, },
+};
+
+static struct tuner_params tuner_philips_pal_mk_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_pal_mk_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_ATSC - Philips ATSC ------------ */
+
+static struct tuner_range tuner_philips_atsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_philips_atsc_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_atsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_atsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_fm1236_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_fm1236_mk3_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_4in1_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_4in1_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_4in1_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_4in1_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
+
+static struct tuner_params tuner_microtune_4049_fm5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_temic_4009f_5_pal_ranges,
+ .count = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
+
+static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_panasonic_vp27_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_panasonic_vp27_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_ntsc_tape_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_lg_ntsc_tape_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_ntsc_tape_ranges,
+ .count = ARRAY_SIZE(tuner_lg_ntsc_tape_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
+ { 16 * 161.25 /*MHz*/, 0xa0, },
+ { 16 * 463.25 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_tnf_8831bgff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tnf_8831bgff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
+
+static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
+ { 16 * 162.00 /*MHz*/, 0xa2, },
+ { 16 * 457.00 /*MHz*/, 0x94, },
+ { 16 * 999.99 , 0x31, },
+};
+
+static struct tuner_params tuner_microtune_4042fi5_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_microtune_4042fi5_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 50-59 */
+/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
+
+static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
+ { 16 * 172.00 /*MHz*/, 0x01, },
+ { 16 * 448.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002n_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tcl_2002n_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
+ .config = 0x8e,
+ .cb_first_if_lower_freq = 1,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fm1256_ih3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fm1256_ih3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fm1256_ih3_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
+
+static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x39, },
+ { 16 * 454.00 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+static struct tuner_params tuner_thomson_dtt7610_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt7610_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
+
+static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x41, },
+ { 16 * 454.00 /*MHz*/, 0x42, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1286_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq1286_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
+
+static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
+ { 16 * 170.00 /*MHz*/, 0x01, },
+ { 16 * 450.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_tcl_2002mb_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tcl_2002mb_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fq12_6a___mk4_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 442.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
+
+static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_philips_fq12_6a___mk4_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_8531mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa0, },
+ { 16 * 454.00 /*MHz*/, 0x90, },
+ { 16 * 999.99 , 0x30, },
+};
+
+static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_8531mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_8531mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 60-69 */
+/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
+/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+
+static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
+ { 16 * 145.25 /*MHz*/, 0x39, },
+ { 16 * 415.25 /*MHz*/, 0x3a, },
+ { 16 * 999.99 , 0x3c, },
+};
+
+
+static struct tuner_params tuner_thomson_dtt761x_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_thomson_dtt761x_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
+
+static struct tuner_range tuner_tuner_tena_9533_di_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tena_9533_di_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_tuner_tena_9533_di_pal_ranges,
+ .count = ARRAY_SIZE(tuner_tuner_tena_9533_di_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_FMD1216ME_MK3 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x51, },
+ { 16 * 442.00 /*MHz*/, 0x52, },
+ { 16 * 999.99 , 0x54, },
+};
+
+
+static struct tuner_params tuner_tuner_philips_fmd1216me_mk3_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
+ .config = 0x86,
+ },
+};
+
+
+/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
+
+static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0x01 },
+ { 16 * 455.00 /*MHz*/, 0x02 },
+ { 16 * 999.99 , 0x04 },
+};
+
+
+static struct tuner_params tuner_tua6034_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tua6034_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
+
+static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
+ { 16 * 160.25 /*MHz*/, 0x01, },
+ { 16 * 464.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
+ .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
+
+static struct tuner_range tuner_lg_taln_mini_ntsc_ranges[] = {
+ { 16 * 137.25 /*MHz*/, 0x01, },
+ { 16 * 373.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_lg_taln_mini_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_lg_taln_mini_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_lg_taln_mini_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
+
+static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
+ { 16 * 160.00 /*MHz*/, 0xa1, },
+ { 16 * 442.00 /*MHz*/, 0xa2, },
+ { 16 * 999.99 , 0xa4, },
+};
+
+static struct tuner_params tuner_philips_td1316_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_PAL,
+ .ranges = tuner_philips_td1316_pal_ranges,
+ .count = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
+ .config = 0xc8,
+ },
+};
+
+/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
+
+static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+
+static struct tuner_params tuner_tuner_tuv1236d_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tuv1236d_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* ------------ TUNER_TNF_5335MF - Philips NTSC ------------ */
+
+static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
+ { 16 * 157.25 /*MHz*/, 0x01, },
+ { 16 * 454.00 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x04, },
+};
+
+static struct tuner_params tuner_tnf_5335mf_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_tnf_5335mf_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
+ .config = 0x8e,
+ },
+};
+
+/* 70-79 */
+/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
+
+static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
+ { 16 * 175.75 /*MHz*/, 0x01, },
+ { 16 * 410.25 /*MHz*/, 0x02, },
+ { 16 * 999.99 , 0x08, },
+};
+
+static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
+ {
+ .type = TUNER_PARAM_TYPE_NTSC,
+ .ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
+ .count = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
+ .config = 0xce,
+ },
+};
+
+/* --------------------------------------------------------------------- */
+
+struct tunertype tuners[] = {
+ /* 0-9 */
+ [TUNER_TEMIC_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL (4002 FH5)",
+ .params = tuner_temic_pal_params,
+ },
+ [TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
+ .name = "Philips PAL_I (FI1246 and compatibles)",
+ .params = tuner_philips_pal_i_params,
+ },
+ [TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
+ .name = "Philips NTSC (FI1236,FM1236 and compatibles)",
+ .params = tuner_philips_ntsc_params,
+ },
+ [TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
+ .name = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
+ .params = tuner_philips_secam_params,
+ },
+ [TUNER_ABSENT] = { /* Tuner Absent */
+ .name = "NoTuner",
+ },
+ [TUNER_PHILIPS_PAL] = { /* Philips PAL */
+ .name = "Philips PAL_BG (FI1216 and compatibles)",
+ .params = tuner_philips_pal_params,
+ },
+ [TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4032 FY5)",
+ .params = tuner_temic_ntsc_params,
+ },
+ [TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4062 FY5)",
+ .params = tuner_temic_pal_i_params,
+ },
+ [TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4036 FY5)",
+ .params = tuner_temic_4036fy5_ntsc_params,
+ },
+ [TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
+ .name = "Alps HSBH1",
+ .params = tuner_alps_tsbh1_ntsc_params,
+ },
+
+ /* 10-19 */
+ [TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
+ .name = "Alps TSBE1",
+ .params = tuner_alps_tsb_1_params,
+ },
+ [TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
+ .name = "Alps TSBB5",
+ .params = tuner_alps_tsbb5_params,
+ },
+ [TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBE5",
+ .params = tuner_alps_tsbe5_params,
+ },
+ [TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
+ .name = "Alps TSBC5",
+ .params = tuner_alps_tsbc5_params,
+ },
+ [TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4006FH5)",
+ .params = tuner_temic_4006fh5_params,
+ },
+ [TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
+ .name = "Alps TSCH6",
+ .params = tuner_alps_tshc6_params,
+ },
+ [TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK (4016 FY5)",
+ .params = tuner_temic_pal_dk_params,
+ },
+ [TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
+ .name = "Philips NTSC_M (MK2)",
+ .params = tuner_philips_ntsc_m_params,
+ },
+ [TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
+ .name = "Temic PAL_I (4066 FY5)",
+ .params = tuner_temic_4066fy5_pal_i_params,
+ },
+ [TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto (4006 FN5)",
+ .params = tuner_temic_4006fn5_multi_params,
+ },
+
+ /* 20-29 */
+ [TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
+ .params = tuner_temic_4009f_5_params,
+ },
+ [TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4039 FR5)",
+ .params = tuner_temic_4039fr5_params,
+ },
+ [TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
+ .name = "Temic PAL/SECAM multi (4046 FM5)",
+ .params = tuner_temic_4046fm5_params,
+ },
+ [TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
+ .name = "Philips PAL_DK (FI1256 and compatibles)",
+ .params = tuner_philips_pal_dk_params,
+ },
+ [TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216ME)",
+ .params = tuner_philips_fq1216me_params,
+ },
+ [TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I+FM (TAPC-I001D)",
+ .params = tuner_lg_pal_i_fm_params,
+ },
+ [TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
+ .name = "LG PAL_I (TAPC-I701D)",
+ .params = tuner_lg_pal_i_params,
+ },
+ [TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC+FM (TPI8NSR01F)",
+ .params = tuner_lg_ntsc_fm_params,
+ },
+ [TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG+FM (TPI8PSB01D)",
+ .params = tuner_lg_pal_fm_params,
+ },
+ [TUNER_LG_PAL] = { /* LGINNOTEK PAL */
+ .name = "LG PAL_BG (TPI8PSB11D)",
+ .params = tuner_lg_pal_params,
+ },
+
+ /* 30-39 */
+ [TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
+ .name = "Temic PAL* auto + FM (4009 FN5)",
+ .params = tuner_temic_4009_fn5_multi_pal_fm_params,
+ },
+ [TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
+ .name = "SHARP NTSC_JP (2U5JF5540)",
+ .params = tuner_sharp_2u5jf5540_params,
+ },
+ [TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
+ .name = "Samsung PAL TCPM9091PD27",
+ .params = tuner_samsung_pal_tcpm9091pd27_params,
+ },
+ [TUNER_MT2032] = { /* Microtune PAL|NTSC */
+ .name = "MT20xx universal",
+ /* see mt20xx.c for details */ },
+ [TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
+ .name = "Temic PAL_BG (4106 FH5)",
+ .params = tuner_temic_4106fh5_params,
+ },
+ [TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
+ .name = "Temic PAL_DK/SECAM_L (4012 FY5)",
+ .params = tuner_temic_4012fy5_params,
+ },
+ [TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
+ .name = "Temic NTSC (4136 FY5)",
+ .params = tuner_temic_4136_fy5_params,
+ },
+ [TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
+ .name = "LG PAL (newer TAPC series)",
+ .params = tuner_lg_pal_new_tapc_params,
+ },
+ [TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FM1216ME MK3)",
+ .params = tuner_fm1216me_mk3_params,
+ },
+ [TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (newer TAPC series)",
+ .params = tuner_lg_ntsc_new_tapc_params,
+ },
+
+ /* 40-49 */
+ [TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
+ .name = "HITACHI V7-J180AT",
+ .params = tuner_hitachi_ntsc_params,
+ },
+ [TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
+ .name = "Philips PAL_MK (FI1216 MK)",
+ .params = tuner_philips_pal_mk_params,
+ },
+ [TUNER_PHILIPS_ATSC] = { /* Philips ATSC */
+ .name = "Philips 1236D ATSC/NTSC dual in",
+ .params = tuner_philips_atsc_params,
+ },
+ [TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
+ .name = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
+ .params = tuner_fm1236_mk3_params,
+ },
+ [TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
+ .name = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
+ .params = tuner_philips_4in1_params,
+ },
+ [TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
+ .name = "Microtune 4049 FM5",
+ .params = tuner_microtune_4049_fm5_params,
+ },
+ [TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
+ .name = "Panasonic VP27s/ENGE4324D",
+ .params = tuner_panasonic_vp27_params,
+ },
+ [TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TAPE series)",
+ .params = tuner_lg_ntsc_tape_params,
+ },
+ [TUNER_TNF_8831BGFF] = { /* Philips PAL */
+ .name = "Tenna TNF 8831 BGFF)",
+ .params = tuner_tnf_8831bgff_params,
+ },
+ [TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
+ .name = "Microtune 4042 FI5 ATSC/NTSC dual in",
+ .params = tuner_microtune_4042fi5_params,
+ },
+
+ /* 50-59 */
+ [TUNER_TCL_2002N] = { /* TCL NTSC */
+ .name = "TCL 2002N",
+ .params = tuner_tcl_2002n_params,
+ },
+ [TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM_D (FM 1256 I-H3)",
+ .params = tuner_philips_fm1256_ih3_params,
+ },
+ [TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
+ .name = "Thomson DTT 7610 (ATSC/NTSC)",
+ .params = tuner_thomson_dtt7610_params,
+ },
+ [TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
+ .name = "Philips FQ1286",
+ .params = tuner_philips_fq1286_params,
+ },
+ [TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
+ .name = "tda8290+75",
+ /* see tda8290.c for details */ },
+ [TUNER_TCL_2002MB] = { /* TCL PAL */
+ .name = "TCL 2002MB",
+ .params = tuner_tcl_2002mb_params,
+ },
+ [TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
+ .name = "Philips PAL/SECAM multi (FQ1216AME MK4)",
+ .params = tuner_philips_fq1216ame_mk4_params,
+ },
+ [TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
+ .name = "Philips FQ1236A MK4",
+ .params = tuner_philips_fq1236a_mk4_params,
+ },
+ [TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-8531MF/8831MF/8731MF",
+ .params = tuner_ymec_tvf_8531mf_params,
+ },
+ [TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
+ .name = "Ymec TVision TVF-5533MF",
+ .params = tuner_ymec_tvf_5533mf_params,
+ },
+
+ /* 60-69 */
+ [TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
+ /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
+ .name = "Thomson DTT 761X (ATSC/NTSC)",
+ .params = tuner_thomson_dtt761x_params,
+ },
+ [TUNER_TENA_9533_DI] = { /* Philips PAL */
+ .name = "Tena TNF9533-D/IF/TNF9533-B/DF",
+ .params = tuner_tena_9533_di_params,
+ },
+ [TUNER_TEA5767] = { /* Philips RADIO */
+ .name = "Philips TEA5767HN FM Radio",
+ /* see tea5767.c for details */
+ },
+ [TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
+ .name = "Philips FMD1216ME MK3 Hybrid Tuner",
+ .params = tuner_tuner_philips_fmd1216me_mk3_params,
+ },
+ [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
+ .name = "LG TDVS-H062F/TUA6034",
+ .params = tuner_tua6034_params,
+ },
+ [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
+ .name = "Ymec TVF66T5-B/DFF",
+ .params = tuner_ymec_tvf66t5_b_dff_params,
+ },
+ [TUNER_LG_NTSC_TALN_MINI] = { /* LGINNOTEK NTSC */
+ .name = "LG NTSC (TALN mini series)",
+ .params = tuner_lg_taln_mini_params,
+ },
+ [TUNER_PHILIPS_TD1316] = { /* Philips PAL */
+ .name = "Philips TD1316 Hybrid Tuner",
+ .params = tuner_philips_td1316_params,
+ },
+ [TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
+ .name = "Philips TUV1236D ATSC/NTSC dual in",
+ .params = tuner_tuner_tuv1236d_params,
+ },
+ [TUNER_TNF_5335MF] = { /* Philips NTSC */
+ .name = "Tena TNF 5335 MF",
+ .params = tuner_tnf_5335mf_params,
+ },
+
+ /* 70-79 */
+ [TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
+ .name = "Samsung TCPN 2121P30A",
+ .params = tuner_samsung_tcpn_2121p30a_params,
+ },
+};
+
+unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 5b20e8177cad..6d03b9b05c6e 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -31,6 +31,7 @@
#include <linux/smp_lock.h>
#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#include "tvaudio.h"
@@ -46,17 +47,6 @@ MODULE_LICENSE("GPL");
#define UNSET (-1U)
-#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 */
@@ -131,7 +121,7 @@ struct CHIPSTATE {
/* current settings */
__u16 left,right,treble,bass,mode;
int prevmode;
- int norm;
+ int radio;
/* thread */
pid_t tpid;
@@ -142,8 +132,6 @@ struct CHIPSTATE {
int watch_stereo;
};
-#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
-
/* ---------------------------------------------------------------------- */
/* i2c addresses */
@@ -171,23 +159,23 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
unsigned char buffer[2];
if (-1 == subaddr) {
- tvaudio_dbg("%s: chip_write: 0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%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)) {
- tvaudio_warn("%s: I/O error (write 0x%x)\n",
+ v4l_warn(&chip->c, "%s: I/O error (write 0x%x)\n",
chip->c.name, val);
return -1;
}
} else {
- tvaudio_dbg("%s: chip_write: reg%d=0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%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)) {
- tvaudio_warn("%s: I/O error (write reg%d=0x%x)\n",
+ v4l_warn(&chip->c, "%s: I/O error (write reg%d=0x%x)\n",
chip->c.name, subaddr, val);
return -1;
}
@@ -212,11 +200,11 @@ static int chip_read(struct CHIPSTATE *chip)
unsigned char buffer;
if (1 != i2c_master_recv(&chip->c,&buffer,1)) {
- tvaudio_warn("%s: I/O error (read)\n",
+ v4l_warn(&chip->c, "%s: I/O error (read)\n",
chip->c.name);
return -1;
}
- tvaudio_dbg("%s: chip_read: 0x%x\n",chip->c.name, buffer);
+ v4l_dbg(1, debug, &chip->c, "%s: chip_read: 0x%x\n",chip->c.name, buffer);
return buffer;
}
@@ -231,10 +219,10 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr)
write[0] = subaddr;
if (2 != i2c_transfer(chip->c.adapter,msgs,2)) {
- tvaudio_warn("%s: I/O error (read2)\n", chip->c.name);
+ v4l_warn(&chip->c, "%s: I/O error (read2)\n", chip->c.name);
return -1;
}
- tvaudio_dbg("%s: chip_read2: reg%d=0x%x\n",
+ v4l_dbg(1, debug, &chip->c, "%s: chip_read2: reg%d=0x%x\n",
chip->c.name, subaddr,read[0]);
return read[0];
}
@@ -247,7 +235,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
return 0;
/* update our shadow register set; print bytes if (debug > 0) */
- tvaudio_dbg("%s: chip_cmd(%s): reg=%d, data:",
+ v4l_dbg(1, debug, &chip->c, "%s: chip_cmd(%s): reg=%d, data:",
chip->c.name, name,cmd->bytes[0]);
for (i = 1; i < cmd->count; i++) {
if (debug)
@@ -259,7 +247,7 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
/* send data to the chip */
if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) {
- tvaudio_warn("%s: I/O error (%s)\n", chip->c.name, name);
+ v4l_warn(&chip->c, "%s: I/O error (%s)\n", chip->c.name, name);
return -1;
}
return 0;
@@ -286,7 +274,7 @@ static int chip_thread(void *data)
daemonize("%s", chip->c.name);
allow_signal(SIGTERM);
- tvaudio_dbg("%s: thread started\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread started\n", chip->c.name);
for (;;) {
add_wait_queue(&chip->wq, &wait);
@@ -298,10 +286,10 @@ static int chip_thread(void *data)
try_to_freeze();
if (chip->done || signal_pending(current))
break;
- tvaudio_dbg("%s: thread wakeup\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%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)
+ if (chip->radio || chip->mode != 0)
continue;
/* have a look what's going on */
@@ -311,7 +299,7 @@ static int chip_thread(void *data)
mod_timer(&chip->wt, jiffies+2*HZ);
}
- tvaudio_dbg("%s: thread exiting\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread exiting\n", chip->c.name);
complete_and_exit(&chip->texit, 0);
return 0;
}
@@ -324,7 +312,7 @@ static void generic_checkmode(struct CHIPSTATE *chip)
if (mode == chip->prevmode)
return;
- tvaudio_dbg("%s: thread checkmode\n", chip->c.name);
+ v4l_dbg(1, debug, &chip->c, "%s: thread checkmode\n", chip->c.name);
chip->prevmode = mode;
if (mode & VIDEO_SOUND_STEREO)
@@ -371,7 +359,7 @@ static int tda9840_getmode(struct CHIPSTATE *chip)
if (val & TDA9840_ST_STEREO)
mode |= VIDEO_SOUND_STEREO;
- tvaudio_dbg ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9840_getmode(): raw chip read: %d, return: %d\n",
val, mode);
return mode;
}
@@ -667,7 +655,7 @@ static int tda9873_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_STEREO;
if (val & TDA9873_DUAL)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
- tvaudio_dbg ("tda9873_getmode(): raw chip read: %d, return: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9873_getmode(): raw chip read: %d, return: %d\n",
val, mode);
return mode;
}
@@ -678,12 +666,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) {
- tvaudio_dbg("tda9873_setmode(): external input\n");
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): external input\n");
return;
}
- 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);
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): sw_data = %d\n", sw_data);
switch (mode) {
case VIDEO_SOUND_MONO:
@@ -704,7 +692,7 @@ static void tda9873_setmode(struct CHIPSTATE *chip, int mode)
}
chip_write(chip, TDA9873_SW, sw_data);
- tvaudio_dbg("tda9873_setmode(): req. mode %d; chip_write: %d\n",
+ v4l_dbg(1, debug, &chip->c, "tda9873_setmode(): req. mode %d; chip_write: %d\n",
mode, sw_data);
}
@@ -843,7 +831,7 @@ static int tda9874a_setup(struct CHIPSTATE *chip)
chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
}
- tvaudio_dbg("tda9874a_setup(): %s [0x%02X].\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setup(): %s [0x%02X].\n",
tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
return 1;
}
@@ -886,7 +874,7 @@ static int tda9874a_getmode(struct CHIPSTATE *chip)
mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
- tvaudio_dbg("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
dsr, nsr, necr, mode);
return mode;
}
@@ -932,7 +920,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_AOSR, aosr);
chip_write(chip, TDA9874A_MDACOSR, mdacosr);
- tvaudio_dbg("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
mode, aosr, mdacosr);
} else { /* dic == 0x07 */
@@ -967,7 +955,7 @@ static void tda9874a_setmode(struct CHIPSTATE *chip, int mode)
chip_write(chip, TDA9874A_FMMR, fmmr);
chip_write(chip, TDA9874A_AOSR, aosr);
- tvaudio_dbg("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+ v4l_dbg(1, debug, &chip->c, "tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
mode, fmmr, aosr);
}
}
@@ -981,10 +969,10 @@ static int tda9874a_checkit(struct CHIPSTATE *chip)
if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
return 0;
- tvaudio_dbg("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+ v4l_dbg(1, debug, &chip->c, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
if((dic == 0x11)||(dic == 0x07)) {
- tvaudio_info("found tda9874%s.\n", (dic == 0x11) ? "a":"h");
+ v4l_info(&chip->c, "found tda9874%s.\n", (dic == 0x11) ? "a":"h");
tda9874a_dic = dic; /* remember device id. */
return 1;
}
@@ -1196,7 +1184,7 @@ static int ta8874z_getmode(struct CHIPSTATE *chip)
}else if (!(val & TA8874Z_B0)){
mode |= VIDEO_SOUND_STEREO;
}
- /* tvaudio_dbg ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
+ /* v4l_dbg(1, debug, &chip->c, "ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); */
return mode;
}
@@ -1209,7 +1197,7 @@ static void ta8874z_setmode(struct CHIPSTATE *chip, int mode)
{
int update = 1;
audiocmd *t = NULL;
- tvaudio_dbg("ta8874z_setmode(): mode: 0x%02x\n", mode);
+ v4l_dbg(1, debug, &chip->c, "ta8874z_setmode(): mode: 0x%02x\n", mode);
switch(mode){
case VIDEO_SOUND_MONO:
@@ -1480,17 +1468,16 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
struct CHIPSTATE *chip;
struct CHIPDESC *desc;
- chip = kmalloc(sizeof(*chip),GFP_KERNEL);
+ chip = kzalloc(sizeof(*chip),GFP_KERNEL);
if (!chip)
return -ENOMEM;
- memset(chip,0,sizeof(*chip));
memcpy(&chip->c,&client_template,sizeof(struct i2c_client));
chip->c.adapter = adap;
chip->c.addr = addr;
i2c_set_clientdata(&chip->c, chip);
/* find description for the chip */
- tvaudio_dbg("chip found @ 0x%x\n", addr<<1);
+ v4l_dbg(1, debug, &chip->c, "chip found @ 0x%x\n", addr<<1);
for (desc = chiplist; desc->name != NULL; desc++) {
if (0 == *(desc->insmodopt))
continue;
@@ -1502,12 +1489,12 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind)
break;
}
if (desc->name == NULL) {
- tvaudio_dbg("no matching chip description found\n");
+ v4l_dbg(1, debug, &chip->c, "no matching chip description found\n");
return -EIO;
}
- tvaudio_info("%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
+ v4l_info(&chip->c, "%s found @ 0x%x (%s)\n", desc->name, addr<<1, adap->name);
if (desc->flags) {
- tvaudio_dbg("matches:%s%s%s.\n",
+ v4l_dbg(1, debug, &chip->c, "matches:%s%s%s.\n",
(desc->flags & CHIP_HAS_VOLUME) ? " volume" : "",
(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
(desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : "");
@@ -1550,7 +1537,7 @@ 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)
- tvaudio_warn("%s: kernel_thread() failed\n",
+ v4l_warn(&chip->c, "%s: kernel_thread() failed\n",
chip->c.name);
wake_up_interruptible(&chip->wq);
}
@@ -1563,17 +1550,8 @@ static int chip_probe(struct i2c_adapter *adap)
because dedicated drivers are used */
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_HW_B_BT848:
- case I2C_HW_B_RIVA:
- case I2C_HW_SAA7134:
- return i2c_probe(adap, &addr_data, chip_attach);
- }
-#endif
return 0;
}
@@ -1604,7 +1582,7 @@ static int chip_command(struct i2c_client *client,
struct CHIPSTATE *chip = i2c_get_clientdata(client);
struct CHIPDESC *desc = chiplist + chip->type;
- tvaudio_dbg("%s: chip_command 0x%x\n", chip->c.name, cmd);
+ v4l_dbg(1, debug, &chip->c, "%s: chip_command 0x%x\n", chip->c.name, cmd);
switch (cmd) {
case AUDC_SET_INPUT:
@@ -1617,7 +1595,7 @@ static int chip_command(struct i2c_client *client,
break;
case AUDC_SET_RADIO:
- chip->norm = VIDEO_MODE_RADIO;
+ chip->radio = 1;
chip->watch_stereo = 0;
/* del_timer(&chip->wt); */
break;
@@ -1643,7 +1621,7 @@ static int chip_command(struct i2c_client *client,
va->bass = chip->bass;
va->treble = chip->treble;
}
- if (chip->norm != VIDEO_MODE_RADIO) {
+ if (!chip->radio) {
if (desc->getmode)
va->mode = desc->getmode(chip);
else
@@ -1678,15 +1656,80 @@ static int chip_command(struct i2c_client *client,
}
break;
}
- case VIDIOCSCHAN:
+
+ case VIDIOC_S_TUNER:
{
- struct video_channel *vc = arg;
+ struct v4l2_tuner *vt = arg;
+ int mode = 0;
+
+ switch (vt->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ mode = VIDEO_SOUND_MONO;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ mode = VIDEO_SOUND_STEREO;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ mode = VIDEO_SOUND_LANG1;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ mode = VIDEO_SOUND_LANG2;
+ break;
+ default:
+ break;
+ }
- chip->norm = vc->norm;
+ if (desc->setmode && mode) {
+ chip->watch_stereo = 0;
+ /* del_timer(&chip->wt); */
+ chip->mode = mode;
+ desc->setmode(chip, mode);
+ }
break;
}
- case VIDIOCSFREQ:
+
+ case VIDIOC_G_TUNER:
{
+ struct v4l2_tuner *vt = arg;
+ int mode = VIDEO_SOUND_MONO;
+
+ if (chip->radio)
+ break;
+ vt->audmode = 0;
+ vt->rxsubchans = 0;
+ vt->capability = V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+
+ if (desc->getmode)
+ mode = desc->getmode(chip);
+
+ if (mode & VIDEO_SOUND_MONO)
+ vt->rxsubchans |= V4L2_TUNER_SUB_MONO;
+ if (mode & VIDEO_SOUND_STEREO)
+ vt->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ if (mode & VIDEO_SOUND_LANG1)
+ vt->rxsubchans |= V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ mode = chip->mode;
+ if (mode & VIDEO_SOUND_MONO)
+ vt->audmode = V4L2_TUNER_MODE_MONO;
+ if (mode & VIDEO_SOUND_STEREO)
+ vt->audmode = V4L2_TUNER_MODE_STEREO;
+ if (mode & VIDEO_SOUND_LANG1)
+ vt->audmode = V4L2_TUNER_MODE_LANG1;
+ if (mode & VIDEO_SOUND_LANG2)
+ vt->audmode = V4L2_TUNER_MODE_LANG2;
+ break;
+ }
+
+ case VIDIOCSCHAN:
+ case VIDIOC_S_STD:
+ chip->radio = 0;
+ break;
+
+ case VIDIOCSFREQ:
+ case VIDIOC_S_FREQUENCY:
chip->mode = 0; /* automatic */
if (desc->checkmode) {
desc->setmode(chip,VIDEO_SOUND_MONO);
@@ -1695,17 +1738,16 @@ static int chip_command(struct i2c_client *client,
mod_timer(&chip->wt, jiffies+2*HZ);
/* the thread will call checkmode() later */
}
- }
+ break;
}
return 0;
}
-
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "generic i2c audio driver",
+ .driver = {
+ .name = "tvaudio",
+ },
.id = I2C_DRIVERID_TVAUDIO,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = chip_probe,
.detach_client = chip_detach,
.command = chip_command,
@@ -1714,7 +1756,6 @@ static struct i2c_driver driver = {
static struct i2c_client client_template =
{
.name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 5ac235365dd8..582551b0969b 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -40,6 +40,7 @@
#include <media/tuner.h>
#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
#include <media/audiochip.h>
MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
@@ -52,21 +53,19 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
#define STRM(array,i) (i < sizeof(array)/sizeof(char*) ? array[i] : "unknown")
-#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 {\
+#define tveeprom_info(fmt, arg...) \
+ v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_warn(fmt, arg...) \
+ v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_dbg(fmt, arg...) do { \
if (debug) \
- printk(KERN_INFO "tveeprom %d-%04x: " fmt, \
- c->adapter->nr, c->addr , ##arg); } while (0)
-
-
-/* ----------------------------------------------------------------------- */
-/* some hauppauge specific stuff */
+ v4l_printk(KERN_DEBUG, "tveeprom", c->adapter, c->addr, fmt , ## arg); \
+ } while (0)
+/*
+ * The Hauppauge eeprom uses an 8bit field to determine which
+ * tuner formats the tuner supports.
+ */
static struct HAUPPAUGE_TUNER_FMT
{
int id;
@@ -74,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/DVB Digital" },
+ { V4L2_STD_UNKNOWN," UNKNOWN" },
+ { V4L2_STD_UNKNOWN," FM" },
+ { V4L2_STD_PAL_BG, " PAL(B/G)" },
+ { V4L2_STD_NTSC_M, " NTSC(M)" },
+ { V4L2_STD_PAL_I, " PAL(I)" },
+ { V4L2_STD_SECAM_L," SECAM(L/L')" },
+ { V4L2_STD_PAL_DK, " PAL(D/D1/K)" },
+ { V4L2_STD_ATSC, " ATSC/DVB Digital" },
};
/* This is the full list of possible tuners. Many thanks to Hauppauge for
@@ -191,7 +190,7 @@ hauppauge_tuner[] =
{ TUNER_LG_PAL_NEW_TAPC, "TCL 2002MI 3"},
{ TUNER_TCL_2002N, "TCL 2002N 6A"},
{ TUNER_PHILIPS_FM1236_MK3, "Philips FQ1236 MK3"},
- { TUNER_ABSENT, "Samsung TCPN 2121P30A"},
+ { TUNER_SAMSUNG_TCPN_2121P30A, "Samsung TCPN 2121P30A"},
{ TUNER_ABSENT, "Samsung TCPE 4121P30A"},
{ TUNER_PHILIPS_FM1216ME_MK3, "TCL MFPE05 2"},
/* 90-99 */
@@ -387,7 +386,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
if ((eeprom_data[0] == 0x1a) && (eeprom_data[1] == 0xeb) &&
(eeprom_data[2] == 0x67) && (eeprom_data[3] == 0x95))
start=0xa0; /* Generic em28xx offset */
- else if (((eeprom_data[0] & 0xf0) == 0x10) &&
+ else if (((eeprom_data[0] & 0xe1) == 0x01) &&
(eeprom_data[1] == 0x00) &&
(eeprom_data[2] == 0x00) &&
(eeprom_data[8] == 0x84))
@@ -720,8 +719,7 @@ tveeprom_command(struct i2c_client *client,
switch (cmd) {
case 0:
- buf = kmalloc(256,GFP_KERNEL);
- memset(buf,0,256);
+ buf = kzalloc(256,GFP_KERNEL);
tveeprom_read(client,buf,256);
tveeprom_hauppauge_analog(client, &eeprom,buf);
kfree(buf);
@@ -744,14 +742,12 @@ tveeprom_detect_client(struct i2c_adapter *adapter,
{
struct i2c_client *client;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (NULL == client)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver_tveeprom;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name), "tveeprom");
i2c_attach_client(client);
@@ -779,10 +775,10 @@ tveeprom_detach_client (struct i2c_client *client)
}
static struct i2c_driver i2c_driver_tveeprom = {
- .owner = THIS_MODULE,
- .name = "tveeprom",
+ .driver = {
+ .name = "tveeprom",
+ },
.id = I2C_DRIVERID_TVEEPROM,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = tveeprom_attach_adapter,
.detach_client = tveeprom_detach_client,
.command = tveeprom_command,
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 8318bd1aad00..9e86caeb96a7 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -227,17 +227,11 @@ static int tvmixer_release(struct inode *inode, struct file *file)
}
static struct i2c_driver driver = {
-#ifdef I2C_PEC
- .owner = THIS_MODULE,
-#endif
- .name = "tv card mixer driver",
+ .driver = {
+ .name = "tvmixer",
+ },
.id = I2C_DRIVERID_TVMIXER,
-#ifdef I2C_DF_DUMMY
- .flags = I2C_DF_DUMMY,
-#else
- .flags = I2C_DF_NOTIFY,
.detach_adapter = tvmixer_adapters,
-#endif
.attach_adapter = tvmixer_adapters,
.detach_client = tvmixer_clients,
};
@@ -269,22 +263,8 @@ static int tvmixer_clients(struct i2c_client *client)
struct video_audio va;
int i,minor;
-#ifdef I2C_CLASS_TV_ANALOG
if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
return -1;
-#else
- /* TV card ??? */
- switch (client->adapter->id) {
- case I2C_HW_SMBUS_VOODOO3:
- case I2C_HW_B_BT848:
- case I2C_HW_B_RIVA:
- /* ok, have a look ... */
- break;
- default:
- /* ignore that one */
- return -1;
- }
-#endif
/* unregister ?? */
for (i = 0; i < DEV_MAX; i++) {
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index 97431e26d229..fad9ea0ae4f2 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -9,6 +9,7 @@
#include <linux/videodev.h>
#include <linux/delay.h>
#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#include "tvp5150_reg.h"
@@ -28,33 +29,38 @@ static int debug = 0;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
-#define dprintk(num, format, args...) \
+#define tvp5150_info(fmt, arg...) do { \
+ printk(KERN_INFO "%s %d-%04x: " fmt, c->driver->driver.name, \
+ i2c_adapter_id(c->adapter), c->addr , ## arg); } while (0)
+#define tvp5150_dbg(num, fmt, arg...) \
do { \
if (debug >= num) \
- printk(format, ##args); \
- } while (0)
+ printk(KERN_DEBUG "%s debug %d-%04x: " fmt,\
+ c->driver->driver.name, \
+ i2c_adapter_id(c->adapter), \
+ c->addr , ## arg); } while (0)
/* supported controls */
static struct v4l2_queryctrl tvp5150_qctrl[] = {
{
- .id = V4L2_CID_BRIGHTNESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Brightness",
- .minimum = 0,
- .maximum = 255,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- }, {
- .id = V4L2_CID_CONTRAST,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Contrast",
- .minimum = 0,
- .maximum = 255,
- .step = 0x1,
- .default_value = 0x10,
- .flags = 0,
- }, {
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ }, {
+ .id = V4L2_CID_CONTRAST,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Contrast",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 0x1,
+ .default_value = 0x10,
+ .flags = 0,
+ }, {
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Saturation",
@@ -63,16 +69,16 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = {
.step = 0x1,
.default_value = 0x10,
.flags = 0,
- }, {
- .id = V4L2_CID_HUE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Hue",
- .minimum = -128,
- .maximum = 127,
- .step = 0x1,
- .default_value = 0x10,
- .flags = 0,
- }
+ }, {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = -128,
+ .maximum = 127,
+ .step = 0x1,
+ .default_value = 0x10,
+ .flags = 0,
+ }
};
struct tvp5150 {
@@ -87,19 +93,21 @@ struct tvp5150 {
int sat;
};
-static inline int tvp5150_read(struct i2c_client *c, unsigned char addr)
+static int tvp5150_read(struct i2c_client *c, unsigned char addr)
{
unsigned char buffer[1];
int rc;
buffer[0] = addr;
if (1 != (rc = i2c_master_send(c, buffer, 1)))
- dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
msleep(10);
if (1 != (rc = i2c_master_recv(c, buffer, 1)))
- dprintk(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 1)\n", rc);
+
+ tvp5150_dbg(2, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
return (buffer[0]);
}
@@ -109,13 +117,12 @@ static inline void tvp5150_write(struct i2c_client *c, unsigned char addr,
{
unsigned char buffer[2];
int rc;
-/* struct tvp5150 *core = i2c_get_clientdata(c); */
buffer[0] = addr;
buffer[1] = value;
- dprintk(1, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+ tvp5150_dbg(2, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
if (2 != (rc = i2c_master_send(c, buffer, 2)))
- dprintk(0, "i2c i/o error: rc == %d (should be 2)\n", rc);
+ tvp5150_dbg(0, "i2c i/o error: rc == %d (should be 2)\n", rc);
}
static void dump_reg(struct i2c_client *c)
@@ -437,48 +444,346 @@ enum tvp5150_input {
static inline void tvp5150_selmux(struct i2c_client *c,
enum tvp5150_input input)
{
+ int opmode=0;
+
struct tvp5150 *decoder = i2c_get_clientdata(c);
if (!decoder->enable)
input |= TVP5150_BLACK_SCREEN;
+ switch (input) {
+ case TVP5150_ANALOG_CH0:
+ case TVP5150_ANALOG_CH1:
+ opmode=0x30; /* TV Mode */
+ break;
+ default:
+ opmode=0; /* Auto Mode */
+ break;
+ }
+
+ tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode);
tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input);
};
-static inline void tvp5150_reset(struct i2c_client *c)
+struct i2c_reg_value {
+ unsigned char reg;
+ unsigned char value;
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_default[] = {
+ { /* 0x00 */
+ TVP5150_VD_IN_SRC_SEL_1,0x00
+ },
+ { /* 0x01 */
+ TVP5150_ANAL_CHL_CTL,0x15
+ },
+ { /* 0x02 */
+ TVP5150_OP_MODE_CTL,0x00
+ },
+ { /* 0x03 */
+ TVP5150_MISC_CTL,0x01
+ },
+ { /* 0x06 */
+ TVP5150_COLOR_KIL_THSH_CTL,0x10
+ },
+ { /* 0x07 */
+ TVP5150_LUMA_PROC_CTL_1,0x60
+ },
+ { /* 0x08 */
+ TVP5150_LUMA_PROC_CTL_2,0x00
+ },
+ { /* 0x09 */
+ TVP5150_BRIGHT_CTL,0x80
+ },
+ { /* 0x0a */
+ TVP5150_SATURATION_CTL,0x80
+ },
+ { /* 0x0b */
+ TVP5150_HUE_CTL,0x00
+ },
+ { /* 0x0c */
+ TVP5150_CONTRAST_CTL,0x80
+ },
+ { /* 0x0d */
+ TVP5150_DATA_RATE_SEL,0x47
+ },
+ { /* 0x0e */
+ TVP5150_LUMA_PROC_CTL_3,0x00
+ },
+ { /* 0x0f */
+ TVP5150_CONF_SHARED_PIN,0x08
+ },
+ { /* 0x11 */
+ TVP5150_ACT_VD_CROP_ST_MSB,0x00
+ },
+ { /* 0x12 */
+ TVP5150_ACT_VD_CROP_ST_LSB,0x00
+ },
+ { /* 0x13 */
+ TVP5150_ACT_VD_CROP_STP_MSB,0x00
+ },
+ { /* 0x14 */
+ TVP5150_ACT_VD_CROP_STP_LSB,0x00
+ },
+ { /* 0x15 */
+ TVP5150_GENLOCK,0x01
+ },
+ { /* 0x16 */
+ TVP5150_HORIZ_SYNC_START,0x80
+ },
+ { /* 0x18 */
+ TVP5150_VERT_BLANKING_START,0x00
+ },
+ { /* 0x19 */
+ TVP5150_VERT_BLANKING_STOP,0x00
+ },
+ { /* 0x1a */
+ TVP5150_CHROMA_PROC_CTL_1,0x0c
+ },
+ { /* 0x1b */
+ TVP5150_CHROMA_PROC_CTL_2,0x14
+ },
+ { /* 0x1c */
+ TVP5150_INT_RESET_REG_B,0x00
+ },
+ { /* 0x1d */
+ TVP5150_INT_ENABLE_REG_B,0x00
+ },
+ { /* 0x1e */
+ TVP5150_INTT_CONFIG_REG_B,0x00
+ },
+ { /* 0x28 */
+ TVP5150_VIDEO_STD,0x00
+ },
+ { /* 0x2e */
+ TVP5150_MACROVISION_ON_CTR,0x0f
+ },
+ { /* 0x2f */
+ TVP5150_MACROVISION_OFF_CTR,0x01
+ },
+ { /* 0xbb */
+ TVP5150_TELETEXT_FIL_ENA,0x00
+ },
+ { /* 0xc0 */
+ TVP5150_INT_STATUS_REG_A,0x00
+ },
+ { /* 0xc1 */
+ TVP5150_INT_ENABLE_REG_A,0x00
+ },
+ { /* 0xc2 */
+ TVP5150_INT_CONF,0x04
+ },
+ { /* 0xc8 */
+ TVP5150_FIFO_INT_THRESHOLD,0x80
+ },
+ { /* 0xc9 */
+ TVP5150_FIFO_RESET,0x00
+ },
+ { /* 0xca */
+ TVP5150_LINE_NUMBER_INT,0x00
+ },
+ { /* 0xcb */
+ TVP5150_PIX_ALIGN_REG_LOW,0x4e
+ },
+ { /* 0xcc */
+ TVP5150_PIX_ALIGN_REG_HIGH,0x00
+ },
+ { /* 0xcd */
+ TVP5150_FIFO_OUT_CTRL,0x01
+ },
+ { /* 0xcf */
+ TVP5150_FULL_FIELD_ENA_1,0x00
+ },
+ { /* 0xd0 */
+ TVP5150_FULL_FIELD_ENA_2,0x00
+ },
+ { /* 0xfc */
+ TVP5150_FULL_FIELD_MODE_REG,0x7f
+ },
+ { /* end of data */
+ 0xff,0xff
+ }
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_enable[] = {
+ {
+ TVP5150_CONF_SHARED_PIN, 2
+ },{ /* Automatic offset and AGC enabled */
+ TVP5150_ANAL_CHL_CTL, 0x15
+ },{ /* Activate YCrCb output 0x9 or 0xd ? */
+ TVP5150_MISC_CTL, 0x6f
+ },{ /* Activates video std autodetection for all standards */
+ TVP5150_AUTOSW_MSK, 0x0
+ },{ /* Default format: 0x47. For 4:2:2: 0x40 */
+ TVP5150_DATA_RATE_SEL, 0x47
+ },{
+ TVP5150_CHROMA_PROC_CTL_1, 0x0c
+ },{
+ TVP5150_CHROMA_PROC_CTL_2, 0x54
+ },{ /* Non documented, but initialized on WinTV USB2 */
+ 0x27, 0x20
+ },{
+ 0xff,0xff
+ }
+};
+
+struct i2c_vbi_ram_value {
+ u16 reg;
+ unsigned char values[26];
+};
+
+static struct i2c_vbi_ram_value vbi_ram_default[] =
{
- struct tvp5150 *decoder = i2c_get_clientdata(c);
+ {0x010, /* WST SECAM 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x030, /* WST PAL B 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x050, /* WST PAL C 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0xa6, 0x98, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x070, /* WST NTSC 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0x27, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x090, /* NABTS, NTSC 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xe7, 0x2e, 0x20, 0x22, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x15, 0x0 }
+ },
+ {0x0b0, /* NABTS, NTSC-J 6 */
+ { 0xaa, 0xaa, 0xff, 0xff , 0xa7, 0x2e, 0x20, 0x23, 0x69, 0x93, 0x0d, 0x0, 0x0, 0x0, 0x10, 0x0 }
+ },
+ {0x0d0, /* CC, PAL/SECAM 6 */
+ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 }
+ },
+ {0x0f0, /* CC, NTSC 6 */
+ { 0xaa, 0x2a, 0xff, 0x3f , 0x04, 0x51, 0x6e, 0x02, 0x69, 0x8c, 0x09, 0x0, 0x0, 0x0, 0x27, 0x0 }
+ },
+ {0x110, /* WSS, PAL/SECAM 6 */
+ { 0x5b, 0x55, 0xc5, 0xff , 0x0, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x0, 0x0, 0x0, 0x3a, 0x0 }
+ },
+ {0x130, /* WSS, NTSC C */
+ { 0x38, 0x00, 0x3f, 0x00 , 0x0, 0x71, 0x6e, 0x43, 0x69, 0x7c, 0x08, 0x0, 0x0, 0x0, 0x39, 0x0 }
+ },
+ {0x150, /* VITC, PAL/SECAM 6 */
+ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0xa6, 0x85, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 }
+ },
+ {0x170, /* VITC, NTSC 6 */
+ { 0x0, 0x0, 0x0, 0x0 , 0x0, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x0, 0x0, 0x0, 0x4c, 0x0 }
+ },
+ { (u16)-1 }
+};
- tvp5150_write(c, TVP5150_CONF_SHARED_PIN, 2);
+static int tvp5150_write_inittab(struct i2c_client *c,
+ const struct i2c_reg_value *regs)
+{
+ while (regs->reg != 0xff) {
+ tvp5150_write(c, regs->reg, regs->value);
+ regs++;
+ }
+ return 0;
+}
- /* Automatic offset and AGC enabled */
- tvp5150_write(c, TVP5150_ANAL_CHL_CTL, 0x15);
+static int tvp5150_vdp_init(struct i2c_client *c,
+ const struct i2c_vbi_ram_value *regs)
+{
+ unsigned int i;
- /* Normal Operation */
-// tvp5150_write(c, TVP5150_OP_MODE_CTL, 0x00);
+ /* Disable Full Field */
+ tvp5150_write(c, TVP5150_FULL_FIELD_ENA_1, 0);
- /* Activate YCrCb output 0x9 or 0xd ? */
- tvp5150_write(c, TVP5150_MISC_CTL, 0x6f);
+ /* Before programming, Line mode should be at 0xff */
+ for (i=TVP5150_FULL_FIELD_ENA_2; i<=TVP5150_LINE_MODE_REG_44; i++)
+ tvp5150_write(c, i, 0xff);
- /* Activates video std autodetection for all standards */
- tvp5150_write(c, TVP5150_AUTOSW_MSK, 0x0);
+ /* Load Ram Table */
+ while (regs->reg != (u16)-1 ) {
+ tvp5150_write(c, TVP5150_CONF_RAM_ADDR_HIGH,regs->reg>>8);
+ tvp5150_write(c, TVP5150_CONF_RAM_ADDR_LOW,regs->reg);
- /* Default format: 0x47, 4:2:2: 0x40 */
- tvp5150_write(c, TVP5150_DATA_RATE_SEL, 0x47);
+ for (i=0;i<16;i++)
+ tvp5150_write(c, TVP5150_VDP_CONF_RAM_DATA,regs->values[i]);
- tvp5150_selmux(c, decoder->input);
+ regs++;
+ }
+ return 0;
+}
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_1, 0x0c);
- tvp5150_write(c, TVP5150_CHROMA_PROC_CTL_2, 0x54);
+static int tvp5150_set_std(struct i2c_client *c, v4l2_std_id std)
+{
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
+ int fmt=0;
+
+ decoder->norm=std;
+
+ /* First tests should be against specific std */
+
+ if (std == V4L2_STD_ALL) {
+ fmt=0; /* Autodetect mode */
+ } else if (std & V4L2_STD_NTSC_443) {
+ fmt=0xa;
+ } else if (std & V4L2_STD_PAL_M) {
+ fmt=0x6;
+ } else if (std & (V4L2_STD_PAL_N| V4L2_STD_PAL_Nc)) {
+ fmt=0x8;
+ } else {
+ /* Then, test against generic ones */
+ if (std & V4L2_STD_NTSC) {
+ fmt=0x2;
+ } else if (std & V4L2_STD_PAL) {
+ fmt=0x4;
+ } else if (std & V4L2_STD_SECAM) {
+ fmt=0xc;
+ }
+ }
- tvp5150_write(c, 0x27, 0x20); /* ?????????? */
+ tvp5150_dbg(1,"Set video std register to %d.\n",fmt);
+ tvp5150_write(c, TVP5150_VIDEO_STD, fmt);
- tvp5150_write(c, TVP5150_VIDEO_STD, 0x0); /* Auto switch */
+ return 0;
+}
+static inline void tvp5150_reset(struct i2c_client *c)
+{
+ u8 type, ver_656, msb_id, lsb_id, msb_rom, lsb_rom;
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
+
+ type=tvp5150_read(c,TVP5150_AUTOSW_MSK);
+ msb_id=tvp5150_read(c,TVP5150_MSB_DEV_ID);
+ lsb_id=tvp5150_read(c,TVP5150_LSB_DEV_ID);
+ msb_rom=tvp5150_read(c,TVP5150_ROM_MAJOR_VER);
+ lsb_rom=tvp5150_read(c,TVP5150_ROM_MINOR_VER);
+
+ if (type==0xdc) {
+ ver_656=tvp5150_read(c,TVP5150_REV_SELECT);
+ tvp5150_info("tvp%02x%02xam1 detected 656 version is %d.\n",msb_id, lsb_id,ver_656);
+ } else if (type==0xfc) {
+ tvp5150_info("tvp%02x%02xa detected.\n",msb_id, lsb_id);
+ } else {
+ tvp5150_info("unknown tvp%02x%02x chip detected(%d).\n",msb_id,lsb_id,type);
+ }
+ tvp5150_info("Rom ver is %d.%d\n",msb_rom,lsb_rom);
+
+ /* Initializes TVP5150 to its default values */
+ tvp5150_write_inittab(c, tvp5150_init_default);
+
+ /* Initializes VDP registers */
+ tvp5150_vdp_init(c, vbi_ram_default);
+
+ /* Selects decoder input */
+ tvp5150_selmux(c, decoder->input);
+
+ /* Initializes TVP5150 to stream enabled values */
+ tvp5150_write_inittab(c, tvp5150_init_enable);
+
+ /* Initialize image preferences */
tvp5150_write(c, TVP5150_BRIGHT_CTL, decoder->bright >> 8);
tvp5150_write(c, TVP5150_CONTRAST_CTL, decoder->contrast >> 8);
tvp5150_write(c, TVP5150_SATURATION_CTL, decoder->contrast >> 8);
tvp5150_write(c, TVP5150_HUE_CTL, (decoder->hue - 32768) >> 8);
+
+ tvp5150_set_std(c, decoder->norm);
};
static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
@@ -498,9 +803,8 @@ static int tvp5150_get_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
ctrl->value = tvp5150_read(c, TVP5150_HUE_CTL);
return 0;
- default:
- return -EINVAL;
}
+ return -EINVAL;
}
static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
@@ -520,28 +824,59 @@ static int tvp5150_set_ctrl(struct i2c_client *c, struct v4l2_control *ctrl)
case V4L2_CID_HUE:
tvp5150_write(c, TVP5150_HUE_CTL, ctrl->value);
return 0;
- default:
- return -EINVAL;
}
+ return -EINVAL;
}
/****************************************************************************
I2C Command
****************************************************************************/
-static int tvp5150_command(struct i2c_client *client,
+static int tvp5150_command(struct i2c_client *c,
unsigned int cmd, void *arg)
{
- struct tvp5150 *decoder = i2c_get_clientdata(client);
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
switch (cmd) {
case 0:
+ case VIDIOC_INT_RESET:
case DECODER_INIT:
- tvp5150_reset(client);
+ tvp5150_reset(c);
+ break;
+ case VIDIOC_S_STD:
+ if (decoder->norm == *(v4l2_std_id *)arg)
+ break;
+ return tvp5150_set_std(c, *(v4l2_std_id *)arg);
+ case VIDIOC_G_STD:
+ *(v4l2_std_id *)arg = decoder->norm;
break;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ case VIDIOC_INT_G_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_TVP5150)
+ return -EINVAL;
+ reg->val = tvp5150_read(c, reg->reg & 0xff);
+ break;
+ }
+
+ case VIDIOC_INT_S_REGISTER:
+ {
+ struct v4l2_register *reg = arg;
+
+ if (reg->i2c_id != I2C_DRIVERID_TVP5150)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
+ break;
+ }
+#endif
+
case DECODER_DUMP:
- dump_reg(client);
+ dump_reg(c);
break;
case DECODER_GET_CAPABILITIES:
@@ -600,7 +935,7 @@ static int tvp5150_command(struct i2c_client *client,
}
decoder->input = *iarg;
- tvp5150_selmux(client, decoder->input);
+ tvp5150_selmux(c, decoder->input);
break;
}
@@ -620,19 +955,18 @@ static int tvp5150_command(struct i2c_client *client,
decoder->enable = (*iarg != 0);
- tvp5150_selmux(client, decoder->input);
+ tvp5150_selmux(c, decoder->input);
break;
}
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *qc = arg;
- u8 i, n;
+ int i;
- dprintk(1, KERN_DEBUG "VIDIOC_QUERYCTRL");
+ tvp5150_dbg(1, "VIDIOC_QUERYCTRL called\n");
- n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
- for (i = 0; i < n; i++)
+ for (i = 0; i < ARRAY_SIZE(tvp5150_qctrl); i++)
if (qc->id && qc->id == tvp5150_qctrl[i].id) {
memcpy(qc, &(tvp5150_qctrl[i]),
sizeof(*qc));
@@ -644,16 +978,14 @@ static int tvp5150_command(struct i2c_client *client,
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
- dprintk(1, KERN_DEBUG "VIDIOC_G_CTRL");
+ tvp5150_dbg(1, "VIDIOC_G_CTRL called\n");
- return tvp5150_get_ctrl(client, ctrl);
+ return tvp5150_get_ctrl(c, ctrl);
}
- case VIDIOC_S_CTRL_OLD: /* ??? */
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
u8 i, n;
- dprintk(1, KERN_DEBUG "VIDIOC_S_CTRL");
n = sizeof(tvp5150_qctrl) / sizeof(tvp5150_qctrl[0]);
for (i = 0; i < n; i++)
if (ctrl->id == tvp5150_qctrl[i].id) {
@@ -662,11 +994,10 @@ static int tvp5150_command(struct i2c_client *client,
|| ctrl->value >
tvp5150_qctrl[i].maximum)
return -ERANGE;
- dprintk(1,
- KERN_DEBUG
- "VIDIOC_S_CTRL: id=%d, value=%d",
+ tvp5150_dbg(1,
+ "VIDIOC_S_CTRL: id=%d, value=%d\n",
ctrl->id, ctrl->value);
- return tvp5150_set_ctrl(client, ctrl);
+ return tvp5150_set_ctrl(c, ctrl);
}
return -EINVAL;
}
@@ -677,25 +1008,25 @@ static int tvp5150_command(struct i2c_client *client,
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness;
- tvp5150_write(client, TVP5150_BRIGHT_CTL,
+ tvp5150_write(c, TVP5150_BRIGHT_CTL,
decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 255 we get 0-65535 */
decoder->contrast = pic->contrast;
- tvp5150_write(client, TVP5150_CONTRAST_CTL,
+ tvp5150_write(c, TVP5150_CONTRAST_CTL,
decoder->contrast >> 8);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 255 we get 0-65535 */
decoder->sat = pic->colour;
- tvp5150_write(client, TVP5150_SATURATION_CTL,
+ tvp5150_write(c, TVP5150_SATURATION_CTL,
decoder->contrast >> 8);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
- tvp5150_write(client, TVP5150_HUE_CTL,
+ tvp5150_write(c, TVP5150_HUE_CTL,
(decoder->hue - 32768) >> 8);
}
break;
@@ -714,19 +1045,18 @@ static struct i2c_driver driver;
static struct i2c_client client_template = {
.name = "(unset)",
- .flags = I2C_CLIENT_ALLOW_USE,
.driver = &driver,
};
static int tvp5150_detect_client(struct i2c_adapter *adapter,
int address, int kind)
{
- struct i2c_client *client;
+ struct i2c_client *c;
struct tvp5150 *core;
int rv;
- dprintk(1,
- KERN_INFO
+ if (debug)
+ printk( KERN_INFO
"tvp5150.c: detecting tvp5150 client on address 0x%x\n",
address << 1);
@@ -739,22 +1069,21 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
- if (client == 0)
+ c = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (c == 0)
return -ENOMEM;
- memcpy(client, &client_template, sizeof(struct i2c_client));
+ memcpy(c, &client_template, sizeof(struct i2c_client));
- core = kmalloc(sizeof(struct tvp5150), GFP_KERNEL);
+ core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL);
if (core == 0) {
- kfree(client);
+ kfree(c);
return -ENOMEM;
}
- memset(core, 0, sizeof(struct tvp5150));
- i2c_set_clientdata(client, core);
+ i2c_set_clientdata(c, core);
- rv = i2c_attach_client(client);
+ rv = i2c_attach_client(c);
- core->norm = VIDEO_MODE_AUTO;
+ core->norm = V4L2_STD_ALL;
core->input = 2;
core->enable = 1;
core->bright = 32768;
@@ -763,37 +1092,41 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
core->sat = 32768;
if (rv) {
- kfree(client);
+ kfree(c);
kfree(core);
return rv;
}
if (debug > 1)
- dump_reg(client);
+ dump_reg(c);
return 0;
}
static int tvp5150_attach_adapter(struct i2c_adapter *adapter)
{
- dprintk(1,
- KERN_INFO
+ if (debug)
+ printk( KERN_INFO
"tvp5150.c: starting probe for adapter %s (0x%x)\n",
adapter->name, adapter->id);
return i2c_probe(adapter, &addr_data, &tvp5150_detect_client);
}
-static int tvp5150_detach_client(struct i2c_client *client)
+static int tvp5150_detach_client(struct i2c_client *c)
{
- struct tvp5150 *decoder = i2c_get_clientdata(client);
+ struct tvp5150 *decoder = i2c_get_clientdata(c);
int err;
- err = i2c_detach_client(client);
+ tvp5150_dbg(1,
+ "tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
+ c->addr << 1);
+
+ err = i2c_detach_client(c);
if (err) {
return err;
}
kfree(decoder);
- kfree(client);
+ kfree(c);
return 0;
}
@@ -801,12 +1134,10 @@ static int tvp5150_detach_client(struct i2c_client *client)
/* ----------------------------------------------------------------------- */
static struct i2c_driver driver = {
- .owner = THIS_MODULE,
- .name = "tvp5150",
-
- /* FIXME */
- .id = I2C_DRIVERID_SAA7110,
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "tvp5150",
+ },
+ .id = I2C_DRIVERID_TVP5150,
.attach_adapter = tvp5150_attach_adapter,
.detach_client = tvp5150_detach_client,
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 4134549d11a8..474a29bc1760 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -305,9 +305,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_capability *cap = arg;
- cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
+ cap2 = kzalloc(sizeof(*cap2),GFP_KERNEL);
memset(cap, 0, sizeof(*cap));
- memset(cap2, 0, sizeof(*cap2));
memset(&fbuf2, 0, sizeof(fbuf2));
err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
@@ -422,9 +421,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_window *win = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
memset(win,0,sizeof(*win));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -461,8 +459,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
struct video_window *win = arg;
int err1,err2;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -595,8 +592,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
pict->whiteness = get_v4l_control(inode, file,
V4L2_CID_WHITENESS, drv);
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
@@ -622,8 +618,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
set_v4l_control(inode, file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0)
@@ -846,9 +841,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct video_mmap *mm = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
memset(&buf2,0,sizeof(buf2));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -942,8 +936,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
@@ -951,6 +944,10 @@ v4l_compat_translate_ioctl(struct inode *inode,
dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
break;
}
+ if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+ err = -EINVAL;
+ break;
+ }
memset(fmt, 0, sizeof(*fmt));
fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
@@ -966,8 +963,12 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+ err = -EINVAL;
+ break;
+ }
+
+ fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
@@ -986,7 +987,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
- VIDEO_PALETTE_RAW != fmt->sample_format ||
+ fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
fmt2->fmt.vbi.start[0] != fmt->start[0] ||
fmt2->fmt.vbi.count[0] != fmt->count[0] ||
fmt2->fmt.vbi.start[1] != fmt->start[1] ||
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 597b8db35a13..cd2c4475525e 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -58,6 +58,8 @@
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/div64.h>
+#include <linux/video_decoder.h>
+#include <media/v4l2-common.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
@@ -190,57 +192,175 @@ char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
};
-char *v4l2_ioctl_names[256] = {
-#if __GNUC__ >= 3
- [0 ... 255] = "UNKNOWN",
+/* ------------------------------------------------------------------ */
+/* debug help functions */
+
+#ifdef HAVE_V4L1
+static const char *v4l1_ioctls[] = {
+ [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
+ [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
+ [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
+ [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
+ [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
+ [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
+ [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
+ [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
+ [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
+ [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
+ [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
+ [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
+ [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
+ [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
+ [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
+ [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
+ [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
+ [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
+ [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
+ [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
+ [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
+ [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
+ [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
+ [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
+ [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
+ [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
+ [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
+ [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
+ [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
+};
+#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
+#endif
+
+static const char *v4l2_ioctls[] = {
+ [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
+ [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
+ [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
+ [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
+ [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
+ [_IOC_NR(VIDIOC_G_MPEGCOMP)] = "VIDIOC_G_MPEGCOMP",
+ [_IOC_NR(VIDIOC_S_MPEGCOMP)] = "VIDIOC_S_MPEGCOMP",
+ [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
+ [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
+ [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
+ [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
+ [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
+ [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
+ [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
+ [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
+ [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
+ [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
+ [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
+ [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
+ [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
+ [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
+ [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
+ [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
+ [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
+ [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
+ [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
+ [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
+ [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
+ [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
+ [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
+ [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
+ [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
+ [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
+ [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
+ [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
+ [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
+ [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
+ [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
+ [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
+ [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
+ [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
+ [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
+ [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
+ [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
+ [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
+ [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
+ [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
+ [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
+ [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
+ [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
+ [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
+ [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
+#if 1
+ [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
#endif
- [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
- [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
- [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
- [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
- [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
- [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
- [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
- [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
- [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
- [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
- [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
- [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
- [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
- [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
- [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
- [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
- [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
- [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
- [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
- [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
- [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
- [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
- [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
- [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
- [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
- [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
- [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
- [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
- [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
- [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
- [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
- [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
- [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
- [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
- [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
- [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
- [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
- [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
- [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
- [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
- [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
- [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
- [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
- [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
- [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
- [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
+ [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS"
};
+#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
+
+static const char *v4l2_int_ioctls[] = {
+#ifdef HAVE_VIDEO_DECODER
+ [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES",
+ [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS",
+ [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM",
+ [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT",
+ [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT",
+ [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT",
+ [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE",
+ [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO",
+ [_IOC_NR(DECODER_INIT)] = "DECODER_INIT",
+ [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS",
+ [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP",
+#endif
+ [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
+ [_IOC_NR(AUDC_SET_INPUT)] = "AUDC_SET_INPUT",
+ [_IOC_NR(MSP_SET_MATRIX)] = "MSP_SET_MATRIX",
+
+ [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
+ [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
+ [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG",
+
+ [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER",
+ [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER",
+ [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
+ [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
+ [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE",
+ [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
+ [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
+ [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT",
+ [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ"
+};
+#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
+
+/* Common ioctl debug function. This function can be used by
+ external ioctl messages as well as internal V4L ioctl */
+void v4l_printk_ioctl(unsigned int cmd)
+{
+ char *dir;
+
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE: dir = "--"; break;
+ case _IOC_READ: dir = "r-"; break;
+ case _IOC_WRITE: dir = "-w"; break;
+ case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
+ default: dir = "*ERR*"; break;
+ }
+ switch (_IOC_TYPE(cmd)) {
+ case 'd':
+ printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
+ v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+#ifdef HAVE_V4L1
+ case 'v':
+ printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L1_IOCTLS) ?
+ v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+#endif
+ case 'V':
+ printk("v4l2 ioctl %s, dir=%s (0x%08x)\n",
+ (_IOC_NR(cmd) < V4L2_IOCTLS) ?
+ v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
+ break;
+
+ default:
+ printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n",
+ _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
+ }
+}
/* ----------------------------------------------------------------- */
@@ -255,7 +375,7 @@ EXPORT_SYMBOL(v4l2_prio_check);
EXPORT_SYMBOL(v4l2_field_names);
EXPORT_SYMBOL(v4l2_type_names);
-EXPORT_SYMBOL(v4l2_ioctl_names);
+EXPORT_SYMBOL(v4l_printk_ioctl);
/*
* Local variables:
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index 9a6bf287e26a..9ef477523d27 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -52,10 +52,9 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages)
struct page *pg;
int i;
- sglist = kmalloc(sizeof(struct scatterlist)*nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist,0,sizeof(struct scatterlist)*nr_pages);
for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
pg = vmalloc_to_page(virt);
if (NULL == pg)
@@ -80,10 +79,9 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
if (NULL == pages[0])
return NULL;
- sglist = kmalloc(sizeof(*sglist) * nr_pages, GFP_KERNEL);
+ sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL);
if (NULL == sglist)
return NULL;
- memset(sglist, 0, sizeof(*sglist) * nr_pages);
if (NULL == pages[0])
goto nopage;
@@ -284,9 +282,8 @@ void* videobuf_alloc(unsigned int size)
{
struct videobuf_buffer *vb;
- vb = kmalloc(size,GFP_KERNEL);
+ vb = kzalloc(size,GFP_KERNEL);
if (NULL != vb) {
- memset(vb,0,size);
videobuf_dma_init(&vb->dma);
init_waitqueue_head(&vb->done);
vb->magic = MAGIC_BUFFER;
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index 839db622040d..8f271de57fd6 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -124,17 +124,13 @@ videocodec_attach (struct videocodec_master *master)
if (res == 0) {
dprintk(3, "videocodec_attach '%s'\n",
codec->name);
- ptr = (struct attached_list *)
- kmalloc(sizeof(struct attached_list),
- GFP_KERNEL);
+ ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
if (!ptr) {
dprintk(1,
KERN_ERR
"videocodec_attach: no memory\n");
goto out_kfree;
}
- memset(ptr, 0,
- sizeof(struct attached_list));
ptr->codec = codec;
a = h->list;
@@ -249,14 +245,11 @@ videocodec_register (const struct videocodec *codec)
"videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
codec->name, codec->type, codec->flags, codec->magic);
- ptr =
- (struct codec_list *) kmalloc(sizeof(struct codec_list),
- GFP_KERNEL);
+ ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
if (!ptr) {
dprintk(1, KERN_ERR "videocodec_register: no memory\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct codec_list));
ptr->codec = codec;
if (!h) {
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 6de5b0094b82..078880e4c8c0 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -29,7 +29,6 @@
#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/semaphore.h>
#include <linux/videodev.h>
@@ -52,10 +51,7 @@ struct video_device *video_device_alloc(void)
{
struct video_device *vfd;
- vfd = kmalloc(sizeof(*vfd),GFP_KERNEL);
- if (NULL == vfd)
- return NULL;
- memset(vfd,0,sizeof(*vfd));
+ vfd = kzalloc(sizeof(*vfd),GFP_KERNEL);
return vfd;
}
@@ -68,7 +64,8 @@ static void video_release(struct class_device *cd)
{
struct video_device *vfd = container_of(cd, struct video_device, class_dev);
-#if 1 /* needed until all drivers are fixed */
+#if 1
+ /* needed until all drivers are fixed */
if (!vfd->release)
return;
#endif
@@ -85,7 +82,7 @@ static struct class video_class = {
*/
static struct video_device *video_device[VIDEO_NUM_DEVICES];
-static DECLARE_MUTEX(videodev_lock);
+static DEFINE_MUTEX(videodev_lock);
struct video_device* video_devdata(struct file *file)
{
@@ -104,15 +101,15 @@ static int video_open(struct inode *inode, struct file *file)
if(minor>=VIDEO_NUM_DEVICES)
return -ENODEV;
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if(vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
request_module("char-major-%d-%d", VIDEO_MAJOR, minor);
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
vfl=video_device[minor];
if (vfl==NULL) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENODEV;
}
}
@@ -125,7 +122,7 @@ static int video_open(struct inode *inode, struct file *file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return err;
}
@@ -306,12 +303,12 @@ int video_register_device(struct video_device *vfd, int type, int nr)
}
/* pick a minor number */
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if (nr >= 0 && nr < end-base) {
/* use the one the driver asked for */
i = base+nr;
if (NULL != video_device[i]) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
} else {
@@ -320,13 +317,13 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (NULL == video_device[i])
break;
if (i == end) {
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
return -ENFILE;
}
}
video_device[i]=vfd;
vfd->minor=i;
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base);
devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor),
@@ -338,13 +335,14 @@ int video_register_device(struct video_device *vfd, int type, int nr)
if (vfd->dev)
vfd->class_dev.dev = vfd->dev;
vfd->class_dev.class = &video_class;
- vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
+ vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE);
class_device_register(&vfd->class_dev);
class_device_create_file(&vfd->class_dev,
- &class_device_attr_name);
+ &class_device_attr_name);
-#if 1 /* needed until all drivers are fixed */
+#if 1
+ /* needed until all drivers are fixed */
if (!vfd->release)
printk(KERN_WARNING "videodev: \"%s\" has no release callback. "
"Please fix your driver for proper sysfs support, see "
@@ -363,14 +361,14 @@ int video_register_device(struct video_device *vfd, int type, int nr)
void video_unregister_device(struct video_device *vfd)
{
- down(&videodev_lock);
+ mutex_lock(&videodev_lock);
if(video_device[vfd->minor]!=vfd)
panic("videodev: bad unregister");
devfs_remove(vfd->devfs_name);
video_device[vfd->minor]=NULL;
class_device_unregister(&vfd->class_dev);
- up(&videodev_lock);
+ mutex_unlock(&videodev_lock);
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index 71b28e9e0850..c8fd8238904d 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4499,13 +4499,11 @@ 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);
+ vino_drvdata = kzalloc(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++;
/* create a dummy dma descriptor */
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 137b58f2c666..d0a1e72ea8c4 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -621,17 +621,14 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == NULL) {
return -ENOMEM;
}
- memset(client, 0, sizeof(struct i2c_client));
-
client->addr = address;
client->adapter = adapter;
client->driver = &vpx3220_i2c_driver;
- client->flags = I2C_CLIENT_ALLOW_USE;
/* Check for manufacture ID and part number */
if (kind < 0) {
@@ -676,12 +673,11 @@ vpx3220_detect_client (struct i2c_adapter *adapter,
sizeof(I2C_NAME(client)));
}
- decoder = kmalloc(sizeof(struct vpx3220), GFP_KERNEL);
+ decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
- memset(decoder, 0, sizeof(struct vpx3220));
decoder->norm = VIDEO_MODE_PAL;
decoder->input = 0;
decoder->enable = 1;
@@ -722,11 +718,11 @@ vpx3220_attach_adapter (struct i2c_adapter *adapter)
*/
static struct i2c_driver vpx3220_i2c_driver = {
- .owner = THIS_MODULE,
- .name = "vpx3220",
+ .driver = {
+ .name = "vpx3220",
+ },
.id = I2C_DRIVERID_VPX3220,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = vpx3220_attach_adapter,
.detach_client = vpx3220_detach_client,
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index c318ba32fbaf..b7b0afffd214 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -187,6 +187,7 @@ static struct file_operations w9966_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = w9966_v4l_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.read = w9966_v4l_read,
.llseek = no_llseek,
};
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index a6936ad74fcf..8cb64f8a8a91 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -25,7 +25,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
@@ -33,20 +32,12 @@
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
MODULE_DESCRIPTION("wm8775 driver");
MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
MODULE_LICENSE("GPL");
-#define wm8775_err(fmt, arg...) do { \
- printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-#define wm8775_info(fmt, arg...) do { \
- printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \
- i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
-
-
static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END };
@@ -70,7 +61,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val)
int i;
if (reg < 0 || reg >= TOT_REGS) {
- wm8775_err("Invalid register R%d\n", reg);
+ v4l_err(client, "Invalid register R%d\n", reg);
return -1;
}
@@ -80,7 +71,7 @@ static int wm8775_write(struct i2c_client *client, int reg, u16 val)
return 0;
}
}
- wm8775_err("I2C: cannot write %03x to register R%d\n", val, reg);
+ v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
return -1;
}
@@ -88,38 +79,53 @@ static int wm8775_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
struct wm8775_state *state = i2c_get_clientdata(client);
- int *input = arg;
+ struct v4l2_audio *input = arg;
+ struct v4l2_control *ctrl = arg;
switch (cmd) {
- case AUDC_SET_INPUT:
+ case VIDIOC_S_AUDIO:
+ /* There are 4 inputs and one output. Zero or more inputs
+ are multiplexed together to the output. Hence there are
+ 16 combinations.
+ If only one input is active (the normal case) then the
+ input values 1, 2, 4 or 8 should be used. */
+ if (input->index > 15) {
+ v4l_err(client, "Invalid input %d.\n", input->index);
+ return -EINVAL;
+ }
+ state->input = input->index;
+ if (state->muted)
+ break;
wm8775_write(client, R21, 0x0c0);
wm8775_write(client, R14, 0x1d4);
wm8775_write(client, R15, 0x1d4);
+ wm8775_write(client, R21, 0x100 + state->input);
+ break;
- if (*input == AUDIO_RADIO) {
- wm8775_write(client, R21, 0x108);
- state->input = 8;
- state->muted = 0;
- break;
- }
- if (*input == AUDIO_MUTE) {
- state->muted = 1;
- break;
- }
- if (*input == AUDIO_UNMUTE) {
+ case VIDIOC_G_AUDIO:
+ memset(input, 0, sizeof(*input));
+ input->index = state->input;
+ break;
+
+ case VIDIOC_G_CTRL:
+ if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+ return -EINVAL;
+ ctrl->value = state->muted;
+ break;
+
+ case VIDIOC_S_CTRL:
+ if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+ return -EINVAL;
+ state->muted = ctrl->value;
+ wm8775_write(client, R21, 0x0c0);
+ wm8775_write(client, R14, 0x1d4);
+ wm8775_write(client, R15, 0x1d4);
+ if (!state->muted)
wm8775_write(client, R21, 0x100 + state->input);
- state->muted = 0;
- break;
- }
- /* All other inputs... */
- wm8775_write(client, R21, 0x102);
- state->input = 2;
- state->muted = 0;
break;
case VIDIOC_LOG_STATUS:
- wm8775_info("Input: %s%s\n",
- state->input == 8 ? "radio" : "default",
+ v4l_info(client, "Input: %d%s\n", state->input,
state->muted ? " (muted)" : "");
break;
@@ -160,18 +166,16 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind)
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
- client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (client == 0)
return -ENOMEM;
- memset(client, 0, sizeof(struct i2c_client));
client->addr = address;
client->adapter = adapter;
client->driver = &i2c_driver;
- client->flags = I2C_CLIENT_ALLOW_USE;
snprintf(client->name, sizeof(client->name) - 1, "wm8775");
- wm8775_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+ v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
state = kmalloc(sizeof(struct wm8775_state), GFP_KERNEL);
if (state == NULL) {
@@ -207,11 +211,7 @@ static int wm8775_attach(struct i2c_adapter *adapter, int address, int kind)
static int wm8775_probe(struct i2c_adapter *adapter)
{
-#ifdef I2C_CLASS_TV_ANALOG
if (adapter->class & I2C_CLASS_TV_ANALOG)
-#else
- if (adapter->id == I2C_HW_B_BT848)
-#endif
return i2c_probe(adapter, &addr_data, wm8775_attach);
return 0;
}
@@ -233,15 +233,13 @@ static int wm8775_detach(struct i2c_client *client)
/* i2c implementation */
static struct i2c_driver i2c_driver = {
- .name = "wm8775",
-
- .id = I2C_DRIVERID_WM8775,
- .flags = I2C_DF_NOTIFY,
-
+ .driver = {
+ .name = "wm8775",
+ },
+ .id = I2C_DRIVERID_WM8775,
.attach_adapter = wm8775_probe,
- .detach_client = wm8775_detach,
- .command = wm8775_command,
- .owner = THIS_MODULE,
+ .detach_client = wm8775_detach,
+ .command = wm8775_command,
};
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 39a0d238900e..246e67cd8b51 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -995,7 +995,7 @@ test_interrupts (struct zoran *zr)
static int __devinit
zr36057_init (struct zoran *zr)
{
- unsigned long mem;
+ u32 *mem;
void *vdev;
unsigned mem_needed;
int j;
@@ -1050,7 +1050,7 @@ zr36057_init (struct zoran *zr)
/* allocate memory *before* doing anything to the hardware
* in case allocation fails */
mem_needed = BUZ_NUM_STAT_COM * 4;
- mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL);
+ mem = kzalloc(mem_needed, GFP_KERNEL);
vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL);
if (!mem || !vdev) {
dprintk(1,
@@ -1058,11 +1058,10 @@ zr36057_init (struct zoran *zr)
"%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
ZR_DEVNAME(zr));
kfree(vdev);
- kfree((void *)mem);
+ kfree(mem);
return -ENOMEM;
}
- memset((void *) mem, 0, mem_needed);
- zr->stat_com = (u32 *) mem;
+ zr->stat_com = mem;
for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */
}
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 07bde9acd672..485553be190b 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -1311,7 +1311,7 @@ zoran_open (struct inode *inode,
res = -ENODEV;
goto open_unlock_and_return;
}
- if (!try_module_get(zr->decoder->driver->owner)) {
+ if (!try_module_get(zr->decoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
"%s: failed to grab ownership of i2c decoder\n",
@@ -1321,13 +1321,13 @@ zoran_open (struct inode *inode,
goto open_unlock_and_return;
}
if (zr->encoder &&
- !try_module_get(zr->encoder->driver->owner)) {
+ !try_module_get(zr->encoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
"%s: failed to grab ownership of i2c encoder\n",
ZR_DEVNAME(zr));
res = -EIO;
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
module_put(THIS_MODULE);
goto open_unlock_and_return;
}
@@ -1345,7 +1345,7 @@ zoran_open (struct inode *inode,
ZR_DEVNAME(zr), current->comm, current->pid, zr->user);
/* now, create the open()-specific file_ops struct */
- fh = kmalloc(sizeof(struct zoran_fh), GFP_KERNEL);
+ fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
if (!fh) {
dprintk(1,
KERN_ERR
@@ -1354,7 +1354,6 @@ zoran_open (struct inode *inode,
res = -ENOMEM;
goto open_unlock_and_return;
}
- memset(fh, 0, sizeof(struct zoran_fh));
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */
fh->overlay_mask =
@@ -1393,9 +1392,9 @@ zoran_open (struct inode *inode,
open_unlock_and_return:
/* if we grabbed locks, release them accordingly */
if (have_module_locks) {
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
if (zr->encoder) {
- module_put(zr->encoder->driver->owner);
+ module_put(zr->encoder->driver->driver.owner);
}
module_put(THIS_MODULE);
}
@@ -1461,9 +1460,9 @@ zoran_close (struct inode *inode,
kfree(fh);
/* release locks on the i2c modules */
- module_put(zr->decoder->driver->owner);
+ module_put(zr->decoder->driver->driver.owner);
if (zr->encoder) {
- module_put(zr->encoder->driver->owner);
+ module_put(zr->encoder->driver->driver.owner);
}
module_put(THIS_MODULE);
@@ -4678,6 +4677,7 @@ static struct file_operations zoran_fops = {
.open = zoran_open,
.release = zoran_close,
.ioctl = zoran_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
.read = zoran_read,
.write = zoran_write,
diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c
index 4ed898585c70..10130ef67ea7 100644
--- a/drivers/media/video/zr36016.c
+++ b/drivers/media/video/zr36016.c
@@ -451,12 +451,11 @@ zr36016_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36016), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36016));
snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
zr36016_codecs);
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 0144576a6123..bd0cd28543ca 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -813,12 +813,11 @@ zr36050_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36050), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36050));
snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
zr36050_codecs);
diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
index 129744a07abd..28fa31a5f150 100644
--- a/drivers/media/video/zr36060.c
+++ b/drivers/media/video/zr36060.c
@@ -919,12 +919,11 @@ zr36060_setup (struct videocodec *codec)
return -ENOSPC;
}
//mem structure init
- codec->data = ptr = kmalloc(sizeof(struct zr36060), GFP_KERNEL);
+ codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
if (NULL == ptr) {
dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
return -ENOMEM;
}
- memset(ptr, 0, sizeof(struct zr36060));
snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
zr36060_codecs);
diff --git a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c
index 07286816d7df..d4c633b8a7f5 100644
--- a/drivers/media/video/zr36120.c
+++ b/drivers/media/video/zr36120.c
@@ -1490,6 +1490,7 @@ static struct video_device zr36120_template=
.write = zoran_write,
.poll = zoran_poll,
.ioctl = zoran_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.mmap = zoran_mmap,
.minor = -1,
};
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 1883d22cffeb..e67cf15e9c39 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -23,6 +23,7 @@ config FUSION_FC
tristate "Fusion MPT ScsiHost drivers for FC"
depends on PCI && SCSI
select FUSION
+ select SCSI_FC_ATTRS
---help---
SCSI HOST support for a Fiber Channel host adapters.
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index b61e3d175070..02cdc840a06b 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.08
+ * mpi.h Version: 01.05.10
*
* Version History
* ---------------
@@ -74,6 +74,8 @@
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
*/
@@ -104,7 +106,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x0A)
+#define MPI_HEADER_VERSION_UNIT (0x0C)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
/****************************************************************************/
/* Additional FCP target values (obsolete) */
@@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_LAN_CANCELED (0x0087)
/****************************************************************************/
-/* Serial Attached SCSI values */
+/* Serial Attached SCSI values */
/****************************************************************************/
#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index d8339896f734..b1becec27e1b 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.09
+ * mpi_cnfg.h Version: 01.05.11
*
* Version History
* ---------------
@@ -249,6 +249,23 @@
* 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.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
*/
@@ -494,7 +511,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)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949E (0x0646)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A)
#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054)
#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058)
-#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0062)
typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
U32 IMVolumeSettings; /* 50h */
U32 Reserved3; /* 54h */
U32 Reserved4; /* 58h */
- U8 ISDataScrubRate; /* 5Ch */
- U8 ISResyncRate; /* 5Dh */
- U16 Reserved5; /* 5Eh */
+ U32 Reserved5; /* 5Ch */
U8 IMEDataScrubRate; /* 60h */
U8 IMEResyncRate; /* 61h */
U16 Reserved6; /* 62h */
@@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
-#define MPI_MANUFACTURING4_PAGEVERSION (0x02)
+#define MPI_MANUFACTURING4_PAGEVERSION (0x03)
/* defines for the Flags field */
+#define MPI_MANPAGE4_IME_DISABLE (0x20)
+#define MPI_MANPAGE4_IM_DISABLE (0x10)
+#define MPI_MANPAGE4_IS_DISABLE (0x08)
+#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE (0x04)
+#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x02)
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
@@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
-#define MPI_IOUNITPAGE1_PAGEVERSION (0x01)
+#define MPI_IOUNITPAGE1_PAGEVERSION (0x02)
/* IO Unit Page 1 Flags defines */
#define MPI_IOUNITPAGE1_MULTI_FUNCTION (0x00000000)
@@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
#define MPI_IOUNITPAGE1_DISABLE_IR (0x00000040)
#define MPI_IOUNITPAGE1_FORCE_32 (0x00000080)
#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
-
+#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE (0x00000200)
typedef struct _MPI_ADAPTER_INFO
{
@@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
U32 Reserved1; /* 0Ch */
U32 DeviceSettings; /* 10h */
U16 NumberOfDevices; /* 14h */
- U16 Reserved2; /* 16h */
+ U8 ExpanderSpinup; /* 16h */
+ U8 Reserved2; /* 17h */
U16 IOTimeoutBlockDevicesNonRM; /* 18h */
U16 IOTimeoutSequential; /* 1Ah */
U16 IOTimeoutOther; /* 1Ch */
@@ -976,7 +997,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 (0x02)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x03)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY (0x0F000000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY (0x00F00000)
#define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY (20)
+
+#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE (0x00080000)
+#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE (0x00040000)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
@@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+/* defines for the ExpanderSpinup field */
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET (0xF0)
+#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET (4)
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY (0x0F)
+
typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
{
U32 Reserved1; /* 00h */
@@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD (8)
#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD \
)
#define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK (0x00FF0000)
#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET (16)
#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap) \
- ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+ ( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \
)
#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000)
@@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
-#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x05)
/* 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)
-#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
-
-#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
-#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 (0x02)
-
-#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)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
-#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
-#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
-#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
-#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+#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)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
+#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 (0x02)
+
+#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT (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)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
/* values for SAS IO Unit Page 1 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
/* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
@@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
{
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ U8 NumDevsPerEnclosure; /* 08h */
+ U8 Reserved1; /* 09h */
+ U16 Reserved2; /* 0Ah */
U16 MaxPersistentIDs; /* 0Ch */
U16 NumPersistentIDsUsed; /* 0Eh */
U8 Status; /* 10h */
U8 Flags; /* 11h */
- U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */
+ U16 MaxNumPhysicalMappedIDs;/* 12h */
} 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 (0x04)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x05)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00)
#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01)
#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
+#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP (0x07)
#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
#define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT (0x20)
@@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U8 PhysicalPort; /* 08h */
U8 Reserved1; /* 09h */
- U16 Reserved2; /* 0Ah */
+ U16 EnclosureHandle; /* 0Ah */
U64 SASAddress; /* 0Ch */
U32 DiscoveryStatus; /* 14h */
U16 DevHandle; /* 18h */
@@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
-#define MPI_SASEXPANDER0_PAGEVERSION (0x02)
+#define MPI_SASEXPANDER0_PAGEVERSION (0x03)
/* values for SAS Expander Page 0 DiscoveryStatus field */
#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
@@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
U8 NegotiatedLinkRate; /* 1Fh */
U8 PhyIdentifier; /* 20h */
U8 AttachedPhyIdentifier; /* 21h */
- U8 NumTableEntriesProg; /* 22h */
+ U8 Reserved3; /* 22h */
U8 DiscoveryInfo; /* 23h */
- U32 Reserved3; /* 24h */
+ U32 Reserved4; /* 24h */
} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
@@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
#define MPI_LOG_0_NUM_LOG_ENTRIES (1)
#endif
-#define MPI_LOG_0_LOG_DATA_LENGTH (20)
+#define MPI_LOG_0_LOG_DATA_LENGTH (0x1C)
typedef struct _MPI_LOG_0_ENTRY
{
- U64 WWID; /* 00h */
- U32 TimeStamp; /* 08h */
- U32 Reserved1; /* 0Ch */
- U16 LogSequence; /* 10h */
- U16 LogEntryQualifier; /* 12h */
- U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
@@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0
} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
LogPage0_t, MPI_POINTER pLogPage0_t;
-#define MPI_LOG_0_PAGEVERSION (0x00)
+#define MPI_LOG_0_PAGEVERSION (0x01)
#endif
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 1a30ef16adb4..4a5f8dd1d766 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -6,25 +6,25 @@
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.05.10
- Header Set Release Date: 03-11-05
+ Header Set Release Version: 01.05.12
+ Header Set Release Date: 08-30-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- 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.h 01.05.10 01.05.09
+ mpi_ioc.h 01.05.10 01.05.09
+ mpi_cnfg.h 01.05.11 01.05.10
+ mpi_init.h 01.05.06 01.05.06
+ mpi_targ.h 01.05.05 01.05.05
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
- mpi_history.txt 01.05.09 01.05.09
+ mpi_sas.h 01.05.02 01.05.01
+ mpi_type.h 01.05.02 01.05.01
+ mpi_history.txt 01.05.12 01.05.11
* Date Version Description
@@ -91,6 +91,8 @@ mpi.h
* 06-24-05 01.05.08 Added function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Added EEDP IOCStatus codes.
+ * 08-03-05 01.05.09 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-30-05 01.05.10 Added 2 new IOCStatus codes for Target.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -164,6 +166,10 @@ mpi_ioc.h
* 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.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -402,6 +408,23 @@ mpi_cnfg.h
* 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.
+ * 08-03-05 01.05.10 Removed ISDataScrubRate and ISResyncRate from
+ * Manufacturing Page 4.
+ * Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ * Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ * Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ * define.
+ * Added EnclosureHandle field to SAS Expander page 0.
+ * Removed redundant NumTableEntriesProg field from SAS
+ * Expander Page 1.
+ * 08-30-05 01.05.11 Added DeviceID for FC949E and changed the DeviceID for
+ * SAS1078.
+ * Added more defines for Manufacturing Page 4 Flags field.
+ * Added more defines for IOCSettings and added
+ * ExpanderSpinup field to Bios Page 1.
+ * Added postpone SATA Init bit to SAS IO Unit Page 1
+ * ControlFlags.
+ * Changed LogEntry format for Log Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@@ -442,6 +465,8 @@ mpi_init.h
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -582,6 +607,9 @@ mpi_inb.h
mpi_sas.h
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
mpi_type.h
@@ -592,24 +620,25 @@ mpi_type.h
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 08-30-05 01.05.02 Added PowerPC option to #ifdef's.
* --------------------------------------------------------------------------
mpi_history.txt Parts list history
-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.12 01.05.11 01.05.10 01.05.09
+---------- -------- -------- -------- --------
+mpi.h 01.05.10 01.05.09 01.05.08 01.05.07
+mpi_ioc.h 01.05.10 01.05.09 01.05.09 01.05.08
+mpi_cnfg.h 01.05.11 01.05.10 01.05.09 01.05.08
+mpi_init.h 01.05.06 01.05.06 01.05.05 01.05.04
+mpi_targ.h 01.05.05 01.05.05 01.05.05 01.05.04
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.02 01.05.01 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 d5af75afbd94..68941f459ca3 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.05
+ * mpi_init.h Version: 01.05.06
*
* Version History
* ---------------
@@ -50,6 +50,8 @@
* addressing.
* 06-24-05 01.05.05 Added SCSI IO 32 structures and defines.
* Added four new defines for SEP SlotStatus.
+ * 08-03-05 01.05.06 Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ * unique in the first 32 characters.
* --------------------------------------------------------------------------
*/
@@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST
/* 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_32_SENSE_WIDTH (0x00)
+#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH (0x01)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION (0x02)
#define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST (0x00)
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 93b70e2b4266..2c5f43fa7c73 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.09
+ * mpi_ioc.h Version: 01.05.10
*
* Version History
* ---------------
@@ -83,6 +83,10 @@
* 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.
+ * 08-30-05 01.05.10 Added 4 new events and their event data structures.
+ * Added new ReasonCode value for SAS Device Status Change
+ * event.
+ * Added new family code for FC949E.
* --------------------------------------------------------------------------
*/
@@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE (0x00000014)
+#define MPI_EVENT_IR2 (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY (0x00000016)
+#define MPI_EVENT_LOG_ENTRY_ADDED (0x00000021)
/* AckRequired field values */
@@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE
} EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
+/* LogEntryAdded Event data */
+
+/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
+#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH (0x1C)
+typedef struct _EVENT_DATA_LOG_ENTRY
+{
+ U32 TimeStamp; /* 00h */
+ U32 Reserved1; /* 04h */
+ U16 LogSequence; /* 08h */
+ U16 LogEntryQualifier; /* 0Ah */
+ U8 LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
+} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
+ MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
+
+typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
+{
+ U16 LogSequence; /* 00h */
+ U16 Reserved1; /* 02h */
+ U32 Reserved2; /* 04h */
+ EVENT_DATA_LOG_ENTRY LogEntry; /* 08h */
+} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
+ MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
+
/* SCSI Event data for Port, Bus and Device forms */
typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
/* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
+
+/* MPI Integrated RAID Resync Update Event data */
+
+typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
+{
+ U8 VolumeID; /* 00h */
+ U8 VolumeBus; /* 01h */
+ U8 ResyncComplete; /* 02h */
+ U8 Reserved1; /* 03h */
+ U32 Reserved2; /* 04h */
+} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+ MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
+
+/* MPI IR2 Event data */
+
+/* MPI_LD_STATE or MPI_PD_STATE */
+typedef struct _IR2_STATE_CHANGED
+{
+ U16 PreviousState; /* 00h */
+ U16 NewState; /* 02h */
+} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
+
+typedef struct _IR2_PD_INFO
+{
+ U16 DeviceHandle; /* 00h */
+ U8 TruncEnclosureHandle; /* 02h */
+ U8 TruncatedSlot; /* 03h */
+} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
+
+typedef union _MPI_IR2_RC_EVENT_DATA
+{
+ IR2_STATE_CHANGED StateChanged;
+ U32 Lba;
+ IR2_PD_INFO PdInfo;
+} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
+
+typedef struct _MPI_EVENT_DATA_IR2
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 ReasonCode; /* 02h */
+ U8 PhysDiskNum; /* 03h */
+ MPI_IR2_RC_EVENT_DATA IR2EventData; /* 04h */
+} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
+ MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
+
+/* MPI IR2 Event data ReasonCode values */
+#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED (0x01)
+#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED (0x02)
+#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL (0x03)
+#define MPI_EVENT_IR2_RC_PD_INSERTED (0x04)
+#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
+#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
+#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
+
+/* defines for logical disk states */
+#define MPI_LD_STATE_OPTIMAL (0x00)
+#define MPI_LD_STATE_DEGRADED (0x01)
+#define MPI_LD_STATE_FAILED (0x02)
+#define MPI_LD_STATE_MISSING (0x03)
+#define MPI_LD_STATE_OFFLINE (0x04)
+
+/* defines for physical disk states */
+#define MPI_PD_STATE_ONLINE (0x00)
+#define MPI_PD_STATE_MISSING (0x01)
+#define MPI_PD_STATE_NOT_COMPATIBLE (0x02)
+#define MPI_PD_STATE_FAILED (0x03)
+#define MPI_PD_STATE_INITIALIZING (0x04)
+#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST (0x05)
+#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST (0x06)
+#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON (0xFF)
+
/* MPI Link Status Change Event data */
typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
+/* SAS Discovery Event data */
+
+typedef struct _EVENT_DATA_SAS_DISCOVERY
+{
+ U32 DiscoveryStatus; /* 00h */
+ U32 Reserved1; /* 04h */
+} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
+ EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
+
+#define MPI_EVENT_SAS_DSCVRY_COMPLETE (0x00000000)
+#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS (0x00000001)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK (0xFFFF0000)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT (16)
+
/* SAS Discovery Errror Event data */
typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
+#define MPI_FW_HEADER_PID_FAMILY_949E_FC (0x0006)
/* SAS */
#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644
index 000000000000..dc98d46f9071
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ * NAME: fc_log.h
+ * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
+ * DESCRIPTION: Contains the enumerated list of values that may be returned
+ * in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ * CREATION DATE: 6/02/2000
+ * ID: $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ * a = The type of log info as per the MPI spec. Since these codes are
+ * all for Fibre Channel this value will always be 2.
+ * b = Specifies a subclass of the firmware where
+ * 0 = FCP Initiator
+ * 1 = FCP Target
+ * 2 = LAN
+ * 3 = MPI Message Layer
+ * 4 = FC Link
+ * 5 = Context Manager
+ * 6 = Invalid Field Offset
+ * 7 = State Change Info
+ * all others are reserved for future use
+ * c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ * codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+ MPI_IOCLOGINFO_FC_INIT_BASE = 0x20000000,
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN = 0x20000004, /* Bad Rx Frame, overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER = 0x20000005, /* Other errors caught by IOC which require retries */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD = 0x20000006, /* Main processor could not initialize sub-processor */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN = 0x20000007, /* Scatter Gather overrun */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS = 0x20000008, /* Receiver detected context mismatch via invalid header */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE = 0x2000000A, /* Link failure occurred */
+ MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT = 0x2000000B, /* Transmitter timeout error */
+
+ MPI_IOCLOGINFO_FC_TARGET_BASE = 0x21000000,
+ MPI_IOCLOGINFO_FC_TARGET_NO_PDISC = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+ MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN = 0x21000002, /* not sent because we are not logged in to the remote node */
+ MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA = 0x21000005, /* Data In, Auto Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA = 0x21000009, /* Data In, No Response, missing data frames */
+ MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP = 0x2100000a, /* Manual Response not sent due to a LIP */
+ MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3 = 0x2100000b, /* not sent because remote node does not support Class 3 */
+ MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID = 0x2100000c, /* not sent because login to remote node not validated */
+ MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND = 0x2100000e, /* cleared from the outbound queue after a logout */
+ MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN = 0x2100000f, /* cleared waiting for data after a logout */
+
+ MPI_IOCLOGINFO_FC_LAN_BASE = 0x22000000,
+ MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING = 0x22000001, /* Transaction Context Sgl Missing */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE = 0x22000002, /* Transaction Context found before an EOB */
+ MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET = 0x22000003, /* Transaction Context value has reserved bits set */
+ MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG = 0x22000004, /* Invalid SGL Flags */
+
+ MPI_IOCLOGINFO_FC_MSG_BASE = 0x23000000,
+
+ MPI_IOCLOGINFO_FC_LINK_BASE = 0x24000000,
+ MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT = 0x24000001, /* Loop initialization timed out */
+ MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED = 0x24000002, /* Another system controller already initialized the loop */
+ MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+ MPI_IOCLOGINFO_FC_LINK_CRC_ERROR = 0x24000004, /* CRC check detected error on received frame */
+
+ MPI_IOCLOGINFO_FC_CTX_BASE = 0x25000000,
+
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
+ MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET = 0x26ffffff,
+
+ MPI_IOCLOGINFO_FC_STATE_CHANGE = 0x27000000 /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644
index 000000000000..9259d1ad6e6e
--- /dev/null
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ * *
+ * Copyright 2003 LSI Logic Corporation. All rights reserved. *
+ * *
+ * This file is confidential and a trade secret of LSI Logic. The *
+ * receipt of or possession of this file does not convey any rights to *
+ * reproduce or disclose its contents or to manufacture, use, or sell *
+ * anything it may describe, in whole, or in part, without the specific *
+ * written consent of LSI Logic Corporation. *
+ * *
+ ***************************************************************************
+ *
+ * Name: iopiIocLogInfo.h
+ * Title: SAS Firmware IOP Interface IOC Log Info Definitions
+ * Programmer: Guy Kendall
+ * Creation Date: September 24, 2003
+ *
+ * Version History
+ * ---------------
+ *
+ * Last Updated
+ * -------------
+ * Version %version: 22 %
+ * Date Updated %date_modified: %
+ * Programmer %created_by: nperucca %
+ *
+ * Date Who Description
+ * -------- --- -------------------------------------------------------
+ * 09/24/03 GWK Initial version
+ *
+ *
+ * Description
+ * ------------
+ * This include file contains SAS firmware interface IOC Log Info codes
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef IOPI_IOCLOGINFO_H_INCLUDED
+#define IOPI_IOCLOGINFO_H_INCLUDED
+
+
+/****************************************************************************/
+/* IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF */
+/* Format: */
+/* Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3) */
+/* Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR */
+/* Bits 23-16: LOGINFO_CODE */
+/* Bits 15-0: LOGINFO_CODE Specific */
+/****************************************************************************/
+
+/****************************************************************************/
+/* IOC_LOGINFO_ORIGINATOR defines */
+/****************************************************************************/
+#define IOC_LOGINFO_ORIGINATOR_IOP (0x00000000)
+#define IOC_LOGINFO_ORIGINATOR_PL (0x01000000)
+#define IOC_LOGINFO_ORIGINATOR_IR (0x02000000)
+
+/****************************************************************************/
+/* LOGINFO_CODE defines */
+/****************************************************************************/
+#define IOC_LOGINFO_CODE_MASK (0x00FF0000)
+#define IOC_LOGINFO_CODE_SHIFT (16)
+
+/****************************************************************************/
+/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP */
+/****************************************************************************/
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2 (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT (0x00030700) /* Default Page not found */
+#define IOP_LOGINFO_CODE_TASK_TERMINATED (0x00050000)
+
+
+/****************************************************************************/
+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
+/****************************************************************************/
+#define PL_LOGINFO_CODE_OPEN_FAILURE (0x00010000)
+#define PL_LOGINFO_CODE_INVALID_SGL (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00100000)
+#define PL_LOGINFO_CODE_RESET (0x00110000)
+#define PL_LOGINFO_CODE_ABORT (0x00120000)
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED (0x00140000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE (0x00000100)
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
+
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200001) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR (0x00200002) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL (0x00200004) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED (0x00200005) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM (0x00200006) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT (0x00200007) /* SGPIO not present/enabled */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1 (0x00200105) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2 (0x00200106) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP (0x00200107) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+
+
+/****************************************************************************/
+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR */
+/****************************************************************************/
+#define IR_LOGINFO_CODE_UNUSED1 (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2 (0x00020000)
+
+/****************************************************************************/
+/* Defines for convienence */
+/****************************************************************************/
+#define IOC_LOGINFO_PREFIX_IOP ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
+#define IOC_LOGINFO_PREFIX_PL ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
+#define IOC_LOGINFO_PREFIX_IR ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
+
+#endif /* end of file */
+
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 230fa69b5353..70514867bddf 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -6,7 +6,7 @@
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.01
+ * mpi_sas.h Version: 01.05.02
*
* Version History
* ---------------
@@ -14,6 +14,9 @@
* Date Version Description
* -------- -------- ------------------------------------------------------
* 08-19-04 01.05.01 Original release.
+ * 08-30-05 01.05.02 Added DeviceInfo bit for SEP.
+ * Added PrimFlags and Primitive field to SAS IO Unit
+ * Control request, and added a new operation code.
* --------------------------------------------------------------------------
*/
@@ -51,6 +54,7 @@
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
* data and SAS IO Unit Configuration pages.
*/
+#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)
#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
@@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
U8 TargetID; /* 0Ch */
U8 Bus; /* 0Dh */
U8 PhyNum; /* 0Eh */
- U8 Reserved4; /* 0Fh */
- U32 Reserved5; /* 10h */
+ U8 PrimFlags; /* 0Fh */
+ U32 Primitive; /* 10h */
U64 SASAddress; /* 14h */
- U32 Reserved6; /* 1Ch */
+ U32 Reserved4; /* 1Ch */
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
/* values for the Operation field */
-#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
-#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
-#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
-#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
+#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
+#define MPI_SAS_OP_MAP_CURRENT (0x09)
+#define MPI_SAS_OP_SEND_PRIMITIVE (0x0A)
+
+/* values for the PrimFlags field */
+#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
+#define MPI_SAS_PRIMFLAGS_TRIPLE (0x02)
+#define MPI_SAS_PRIMFLAGS_REDUNDANT (0x01)
/* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 4262a22adc22..d890b2b8a93e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -148,7 +148,6 @@ static int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
static int GetLanConfigPages(MPT_ADAPTER *ioc);
-static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
static int GetIoUnitPage2(MPT_ADAPTER *ioc);
int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
@@ -313,13 +312,13 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa)
u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo);
if (ioc->bus_type == FC)
mpt_fc_log_info(ioc, log_info);
- else if (ioc->bus_type == SCSI)
+ else if (ioc->bus_type == SPI)
mpt_sp_log_info(ioc, log_info);
else if (ioc->bus_type == SAS)
mpt_sas_log_info(ioc, log_info);
}
if (ioc_stat & MPI_IOCSTATUS_MASK) {
- if (ioc->bus_type == SCSI &&
+ if (ioc->bus_type == SPI &&
cb_idx != mpt_stm_index &&
cb_idx != mpt_lan_index)
mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf);
@@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
dprintk((KERN_INFO MYNAM
": Not using 64 bit consistent mask\n"));
- ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+ ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
if (ioc == NULL) {
printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
return -ENOMEM;
}
- memset(ioc, 0, sizeof(MPT_ADAPTER));
ioc->alloc_total = sizeof(MPT_ADAPTER);
ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */
ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->pcidev = pdev;
ioc->diagPending = 0;
spin_lock_init(&ioc->diagLock);
+ spin_lock_init(&ioc->fc_rescan_work_lock);
+ spin_lock_init(&ioc->fc_rport_lock);
spin_lock_init(&ioc->initializing_hba_lock);
/* Initialize the event logging.
@@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
*/
INIT_LIST_HEAD(&ioc->configQ);
+ /* Initialize the fc rport list head.
+ */
+ INIT_LIST_HEAD(&ioc->fc_rports);
+
/* Find lookup slot. */
INIT_LIST_HEAD(&ioc->list);
ioc->id = mpt_ids++;
@@ -1374,9 +1378,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+ ioc->prod_name = "LSIFC949E";
+ ioc->bus_type = FC;
+ }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
- ioc->bus_type = SCSI;
+ ioc->bus_type = SPI;
/* 1030 Chip Fix. Disable Split transactions
* for PCIX. Set MOST bits to zero if Rev < C0( = 8).
*/
@@ -1389,7 +1397,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
ioc->prod_name = "LSI53C1035";
- ioc->bus_type = SCSI;
+ ioc->bus_type = SPI;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) {
ioc->prod_name = "LSISAS1064";
@@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev)
pci_enable_device(pdev);
/* enable interrupts */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
/* F/W not running */
@@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
ioc->alt_ioc->name));
- CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (ret == 0) {
/* Enable! (reply interrupt) */
- CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+ CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
ioc->active = 1;
}
@@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
/* (re)Enable alt-IOC! (reply interrupt) */
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));
+ CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
ioc->alt_ioc->active = 1;
}
@@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
* (FCPortPage0_t stuff)
*/
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- (void) GetFcPortPage0(ioc, ii);
+ (void) mptbase_GetFcPortPage0(ioc, ii);
}
if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -3042,7 +3050,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag)
/* Clear the internal flash bad bit - autoincrementing register,
* so must do two writes.
*/
- if (ioc->bus_type == SCSI) {
+ if (ioc->bus_type == SPI) {
/*
* 1030 and 1035 H/W errata, workaround to access
* the ClearFlashBadSignatureBit
@@ -3152,7 +3160,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
int cnt,cntdn;
dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
- if (ioc->bus_type == SCSI) {
+ if (ioc->bus_type == SPI) {
/* Always issue a Msg Unit Reset first. This will clear some
* SCSI bus hang conditions.
*/
@@ -3580,7 +3588,7 @@ initChainBuffers(MPT_ADAPTER *ioc)
dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
ioc->name, numSGE, num_sge, num_chain));
- if (ioc->bus_type == SCSI)
+ if (ioc->bus_type == SPI)
num_chain *= MPT_SCSI_CAN_QUEUE;
else
num_chain *= MPT_FC_CAN_QUEUE;
@@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * GetFcPortPage0 - Fetch FCPort config Page0.
+ * mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
* @ioc: Pointer to MPT_ADAPTER structure
* @portnum: IOC Port number
*
@@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
* -EAGAIN if no msg frames currently available
* -EFAULT for non-successful reply or no reply (timeout)
*/
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
{
ConfigPageHeader_t hdr;
CONFIGPARMS cfg;
@@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
int data_sz;
int copy_sz;
int rc;
+ int count = 400;
+
/* Get FCPort Page 0 header */
hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
rc = -ENOMEM;
ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
if (ppage0_alloc) {
+
+ try_again:
memset((u8 *)ppage0_alloc, 0, data_sz);
cfg.physAddr = page0_dma;
cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+ /*
+ * if still doing discovery,
+ * hang loose a while until finished
+ */
+ if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+ if (count-- > 0) {
+ msleep_interruptible(100);
+ goto try_again;
+ }
+ printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+ " complete.\n",
+ ioc->name);
+ }
}
pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
EXPORT_SYMBOL(mptbase_sas_persist_operation);
EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index bac8eb4186d2..47053ac65068 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.03.04"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.04"
+#define MPT_LINUX_VERSION_COMMON "3.03.06"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.06"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -321,7 +321,7 @@ typedef struct _SYSIF_REGS
* Dynamic Multi-Pathing specific stuff...
*/
-/* VirtDevice negoFlags field */
+/* VirtTarget negoFlags field */
#define MPT_TARGET_NO_NEGO_WIDE 0x01
#define MPT_TARGET_NO_NEGO_SYNC 0x02
#define MPT_TARGET_NO_NEGO_QAS 0x04
@@ -330,8 +330,7 @@ typedef struct _SYSIF_REGS
/*
* VirtDevice - FC LUN device or SCSI target device
*/
-typedef struct _VirtDevice {
- struct scsi_device *device;
+typedef struct _VirtTarget {
u8 tflags;
u8 ioc_id;
u8 target_id;
@@ -342,21 +341,18 @@ typedef struct _VirtDevice {
u8 negoFlags; /* bit field, see above */
u8 raidVolume; /* set, if RAID Volume */
u8 type; /* byte 0 of Inquiry data */
- u8 cflags; /* controller flags */
- u8 rsvd1raid;
- u16 fc_phys_lun;
- u16 fc_xlat_lun;
u32 num_luns;
u32 luns[8]; /* Max LUNs is 256 */
- u8 pad[4];
u8 inq_data[8];
- /* IEEE Registered Extended Identifier
- obtained via INQUIRY VPD page 0x83 */
- /* NOTE: Do not separate uniq_prepad and uniq_data
- as they are treateed as a single entity in the code */
- u8 uniq_prepad[8];
- u8 uniq_data[20];
- u8 pad2[4];
+} VirtTarget;
+
+typedef struct _VirtDevice {
+ VirtTarget *vtarget;
+ u8 ioc_id;
+ u8 bus_id;
+ u8 target_id;
+ u8 configured_lun;
+ u32 lun;
} VirtDevice;
/*
@@ -417,7 +413,7 @@ typedef struct _MPT_IOCTL {
u8 status; /* current command status */
u8 reset; /* 1 if bus reset allowed */
u8 target; /* target for reset */
- struct semaphore sem_ioc;
+ struct mutex ioctl_mutex;
} MPT_IOCTL;
#define MPT_SAS_MGMT_STATUS_RF_VALID 0x02 /* The Reply Frame is VALID */
@@ -425,7 +421,7 @@ typedef struct _MPT_IOCTL {
#define MPT_SAS_MGMT_STATUS_TM_FAILED 0x40 /* User TM request failed */
typedef struct _MPT_SAS_MGMT {
- struct semaphore mutex;
+ struct mutex mutex;
struct completion done;
u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
u8 status; /* current command status */
@@ -503,6 +499,22 @@ typedef struct _RaidCfgData {
int isRaid; /* bit field, 1 if RAID */
}RaidCfgData;
+#define MPT_RPORT_INFO_FLAGS_REGISTERED 0x01 /* rport registered */
+#define MPT_RPORT_INFO_FLAGS_MISSING 0x02 /* missing from DevPage0 scan */
+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04 /* target mapped in vdev */
+
+/*
+ * data allocated for each fc rport device
+ */
+struct mptfc_rport_info
+{
+ struct list_head list;
+ struct fc_rport *rport;
+ VirtDevice *vdev;
+ FCDevicePage0_t pg0;
+ u8 flags;
+};
+
/*
* Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
*/
@@ -616,7 +628,16 @@ typedef struct _MPT_ADAPTER
struct list_head list;
struct net_device *netdev;
struct list_head sas_topology;
+ struct mutex sas_topology_mutex;
MPT_SAS_MGMT sas_mgmt;
+ int num_ports;
+
+ struct list_head fc_rports;
+ spinlock_t fc_rport_lock; /* list and ri flags */
+ spinlock_t fc_rescan_work_lock;
+ int fc_rescan_work_count;
+ struct work_struct fc_rescan_work;
+
} MPT_ADAPTER;
/*
@@ -903,7 +924,7 @@ typedef struct _MPT_LOCAL_REPLY {
typedef enum {
FC,
- SCSI,
+ SPI,
SAS
} BUS_TYPE;
@@ -912,7 +933,7 @@ typedef struct _MPT_SCSI_HOST {
int port;
u32 pad0;
struct scsi_cmnd **ScsiLookup;
- VirtDevice **Targets;
+ VirtTarget **Targets;
MPT_LOCAL_REPLY *pLocal; /* used for internal commands */
struct timer_list timer;
/* Pool of memory for holding SCpnts before doing
@@ -1003,6 +1024,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
/*
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 602138f8544d..bdf709987982 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
if (nonblock) {
- if (down_trylock(&ioc->ioctl->sem_ioc))
+ if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
rc = -EAGAIN;
} else {
- if (down_interruptible(&ioc->ioctl->sem_ioc))
+ if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
rc = -ERESTARTSYS;
}
dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
else
ret = -EINVAL;
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -1245,7 +1245,7 @@ mptctl_gettargetinfo (unsigned long arg)
MPT_ADAPTER *ioc;
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
- VirtDevice *vdev;
+ VirtTarget *vdev;
char *pmem;
int *pdata;
IOCPage2_t *pIoc2;
@@ -1822,7 +1822,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
case MPI_FUNCTION_SCSI_IO_REQUEST:
if (ioc->sh) {
SCSIIORequest_t *pScsiReq = (SCSIIORequest_t *) mf;
- VirtDevice *pTarget = NULL;
+ VirtTarget *pTarget = NULL;
MPT_SCSI_HOST *hd = NULL;
int qtag = MPI_SCSIIO_CONTROL_UNTAGGED;
int scsidir = 0;
@@ -2585,8 +2585,6 @@ static struct miscdevice mptctl_miscdev = {
#ifdef CONFIG_COMPAT
-#include <linux/ioctl32.h>
-
static int
compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
@@ -2621,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2675,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
*/
ret = mptctl_do_mpt_command (karg, &uarg->MF);
- up(&iocp->ioctl->sem_ioc);
+ mutex_unlock(&iocp->ioctl->ioctl_mutex);
return ret;
}
@@ -2745,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(mem, 0, sz);
ioc->ioctl = (MPT_IOCTL *) mem;
ioc->ioctl->ioc = ioc;
- sema_init(&ioc->ioctl->sem_ioc, 1);
+ mutex_init(&ioc->ioctl->ioctl_mutex);
return 0;
out_fail:
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index a628be9bbbad..b102c7666d0e 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -55,12 +55,14 @@
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
+#include <linux/sort.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
#include "mptbase.h"
#include "mptscsih.h"
@@ -79,18 +81,36 @@ static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+#define MPTFC_DEV_LOSS_TMO (60)
+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; /* reasonable default */
+module_param(mptfc_dev_loss_tmo, int, 0);
+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
+ " transport to wait for an rport to "
+ " return following a device loss event."
+ " Default=60.");
+
static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
+int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *));
+
+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
+static void __devexit mptfc_remove(struct pci_dev *pdev);
+
static struct scsi_host_template mptfc_driver_template = {
+ .module = THIS_MODULE,
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
.name = "MPT FC Host",
.info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
- .slave_alloc = mptscsih_slave_alloc,
+ .queuecommand = mptfc_qcmd,
+ .target_alloc = mptscsih_target_alloc,
+ .slave_alloc = mptfc_slave_alloc,
.slave_configure = mptscsih_slave_configure,
+ .target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
@@ -125,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = {
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+ PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static struct scsi_transport_template *mptfc_transport_template = NULL;
+
+struct fc_function_template mptfc_transport_functions = {
+ .dd_fcrport_size = 8,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_port_id = 1,
+ .show_rport_supported_classes = 1,
+ .show_starget_node_name = 1,
+ .show_starget_port_name = 1,
+ .show_starget_port_id = 1,
+ .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
+ .show_rport_dev_loss_tmo = 1,
+
+};
+
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected. Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse. This value can be set via
+ * lsiutil.
+ */
+static void
+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+ if (timeout > 0)
+ rport->dev_loss_tmo = timeout;
+ else
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+}
+
+static int
+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
+{
+ FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
+ FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
+
+ if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
+ if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
+ return 0;
+ if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
+ return -1;
+ return 1;
+ }
+ if ((*aa)->CurrentBus < (*bb)->CurrentBus)
+ return -1;
+ return 1;
+}
+
+static int
+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
+ void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
+{
+ ConfigPageHeader_t hdr;
+ CONFIGPARMS cfg;
+ FCDevicePage0_t *ppage0_alloc, *fc;
+ dma_addr_t page0_dma;
+ int data_sz;
+ int ii;
+
+ FCDevicePage0_t *p0_array=NULL, *p_p0;
+ FCDevicePage0_t **pp0_array=NULL, **p_pp0;
+
+ int rc = -ENOMEM;
+ U32 port_id = 0xffffff;
+ int num_targ = 0;
+ int max_bus = ioc->facts.MaxBuses;
+ int max_targ = ioc->facts.MaxDevices;
+
+ if (max_bus == 0 || max_targ == 0)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
+ p_p0 = p0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!p0_array)
+ goto out;
+
+ data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
+ p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
+ if (!pp0_array)
+ goto out;
+
+ do {
+ /* Get FC Device Page 0 header */
+ hdr.PageVersion = 0;
+ hdr.PageLength = 0;
+ hdr.PageNumber = 0;
+ hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
+ cfg.cfghdr.hdr = &hdr;
+ cfg.physAddr = -1;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+ cfg.dir = 0;
+ cfg.pageAddr = port_id;
+ cfg.timeout = 0;
+
+ if ((rc = mpt_config(ioc, &cfg)) != 0)
+ break;
+
+ if (hdr.PageLength <= 0)
+ break;
+
+ data_sz = hdr.PageLength * 4;
+ ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
+ &page0_dma);
+ rc = -ENOMEM;
+ if (!ppage0_alloc)
+ break;
+
+ cfg.physAddr = page0_dma;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+ if ((rc = mpt_config(ioc, &cfg)) == 0) {
+ ppage0_alloc->PortIdentifier =
+ le32_to_cpu(ppage0_alloc->PortIdentifier);
+
+ ppage0_alloc->WWNN.Low =
+ le32_to_cpu(ppage0_alloc->WWNN.Low);
+
+ ppage0_alloc->WWNN.High =
+ le32_to_cpu(ppage0_alloc->WWNN.High);
+
+ ppage0_alloc->WWPN.Low =
+ le32_to_cpu(ppage0_alloc->WWPN.Low);
+
+ ppage0_alloc->WWPN.High =
+ le32_to_cpu(ppage0_alloc->WWPN.High);
+
+ ppage0_alloc->BBCredit =
+ le16_to_cpu(ppage0_alloc->BBCredit);
+
+ ppage0_alloc->MaxRxFrameSize =
+ le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
+
+ port_id = ppage0_alloc->PortIdentifier;
+ num_targ++;
+ *p_p0 = *ppage0_alloc; /* save data */
+ *p_pp0++ = p_p0++; /* save addr */
+ }
+ pci_free_consistent(ioc->pcidev, data_sz,
+ (u8 *) ppage0_alloc, page0_dma);
+ if (rc != 0)
+ break;
+
+ } while (port_id <= 0xff0000);
+
+ if (num_targ) {
+ /* sort array */
+ if (num_targ > 1)
+ sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
+ mptfc_FcDevPage0_cmp_func, NULL);
+ /* call caller's func for each targ */
+ for (ii = 0; ii < num_targ; ii++) {
+ fc = *(pp0_array+ii);
+ func(ioc, ioc_port, fc);
+ }
+ }
+
+ out:
+ if (pp0_array)
+ kfree(pp0_array);
+ if (p0_array)
+ kfree(p0_array);
+ return rc;
+}
+
+static int
+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
+{
+ /* not currently usable */
+ if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
+ MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
+ return -1;
+
+ if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
+ return -1;
+
+ if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
+ return -1;
+
+ /*
+ * board data structure already normalized to platform endianness
+ * shifted to avoid unaligned access on 64 bit architecture
+ */
+ rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
+ rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
+ rid->port_id = pg0->PortIdentifier;
+ rid->roles = FC_RPORT_ROLE_UNKNOWN;
+ rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+ rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+ return 0;
+}
+
+static void
+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
+{
+ struct fc_rport_identifiers rport_ids;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ int match = 0;
+ u64 port_name;
+ unsigned long flags;
+
+ if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
+ return;
+
+ /* scan list looking for a match */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+ if (port_name == rport_ids.port_name) { /* match */
+ list_move_tail(&ri->list, &ioc->fc_rports);
+ match = 1;
+ break;
+ }
+ }
+ if (!match) { /* allocate one */
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
+ if (!ri)
+ return;
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_add_tail(&ri->list, &ioc->fc_rports);
+ }
+
+ ri->pg0 = *pg0; /* add/update pg0 data */
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+
+ if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+ spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+ rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ if (rport) {
+ if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
+ ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = NULL;
+ ri->rport = rport;
+ *((struct mptfc_rport_info **)rport->dd_data) = ri;
+ }
+ rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+ /*
+ * if already mapped, remap here. If not mapped,
+ * slave_alloc will allocate vdev and map
+ */
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
+ ri->vdev->target_id = ri->pg0.CurrentTargetID;
+ ri->vdev->bus_id = ri->pg0.CurrentBus;
+ ri->vdev->vtarget->target_id = ri->vdev->target_id;
+ ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+ }
+ #ifdef MPT_DEBUG
+ printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+ "rport tid %d, tmo %d\n",
+ ioc->sh->host_no,
+ pg0->PortIdentifier,
+ pg0->WWNN,
+ pg0->WWPN,
+ pg0->CurrentTargetID,
+ ri->rport->scsi_target_id,
+ ri->rport->dev_loss_tmo);
+ #endif
+ } else {
+ list_del(&ri->list);
+ kfree(ri);
+ ri = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+}
+
/*
- * mptfc_probe - Installs scsi devices per bus.
- * @pdev: Pointer to pci_dev structure
- *
- * Returns 0 for success, non-zero for failure.
- *
+ * OS entry point to allow host driver to alloc memory
+ * for each scsi device. Called once per device the bus scan.
+ * Return non-zero if allocation fails.
+ * Init memory once per LUN.
*/
+int
+mptfc_slave_alloc(struct scsi_device *sdev)
+{
+ MPT_SCSI_HOST *hd;
+ VirtTarget *vtarget;
+ VirtDevice *vdev;
+ struct scsi_target *starget;
+ struct fc_rport *rport;
+ struct mptfc_rport_info *ri;
+ unsigned long flags;
+
+
+ rport = starget_to_rport(scsi_target(sdev));
+
+ if (!rport || fc_remote_port_chkready(rport))
+ return -ENXIO;
+
+ hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+
+ vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ if (!vdev) {
+ printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+ hd->ioc->name, sizeof(VirtDevice));
+ return -ENOMEM;
+ }
+ memset(vdev, 0, sizeof(VirtDevice));
+
+ spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
+
+ if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+ kfree(vdev);
+ return -ENODEV;
+ }
+
+ sdev->hostdata = vdev;
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ if (vtarget->num_luns == 0) {
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+ MPT_TARGET_FLAGS_VALID_INQUIRY;
+ hd->Targets[sdev->id] = vtarget;
+ }
+
+ vtarget->target_id = vdev->target_id;
+ vtarget->bus_id = vdev->bus_id;
+
+ vdev->vtarget = vtarget;
+ vdev->ioc_id = hd->ioc->id;
+ vdev->lun = sdev->lun;
+ vdev->target_id = ri->pg0.CurrentTargetID;
+ vdev->bus_id = ri->pg0.CurrentBus;
+
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+ ri->vdev = vdev;
+
+ spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+
+ vtarget->num_luns++;
+
+#ifdef MPT_DEBUG
+ printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+ "CurrentTargetID %d, %x %llx %llx\n",
+ sdev->host->host_no,
+ vtarget->num_luns,
+ sdev->id, ri->pg0.CurrentTargetID,
+ ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
+#endif
+
+ return 0;
+}
+
+static int
+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+ struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+ int err;
+
+ err = fc_remote_port_chkready(rport);
+ if (unlikely(err)) {
+ SCpnt->result = err;
+ done(SCpnt);
+ return 0;
+ }
+ return mptscsih_qcmd(SCpnt,done);
+}
+
+static void
+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
+{
+ unsigned class = 0, cos = 0;
+
+ /* don't know what to do as only one scsi (fc) host was allocated */
+ if (portnum != 0)
+ return;
+
+ class = ioc->fc_port_page0[portnum].SupportedServiceClass;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
+ cos |= FC_COS_CLASS1;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
+ cos |= FC_COS_CLASS2;
+ if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
+ cos |= FC_COS_CLASS3;
+
+ fc_host_node_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
+
+ fc_host_port_name(ioc->sh) =
+ (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
+ | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
+
+ fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
+
+ fc_host_supported_classes(ioc->sh) = cos;
+
+ fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
+}
+
+static void
+mptfc_rescan_devices(void *arg)
+{
+ MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+ int ii;
+ int work_to_do;
+ unsigned long flags;
+ struct mptfc_rport_info *ri;
+
+ do {
+ /* start by tagging all ports as missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+ ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * now rescan devices known to adapter,
+ * will reregister existing rports
+ */
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ (void) mptbase_GetFcPortPage0(ioc, ii);
+ mptfc_init_host_attr(ioc,ii); /* refresh */
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+ }
+
+ /* delete devices still missing */
+ spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+ list_for_each_entry(ri, &ioc->fc_rports, list) {
+ /* if newly missing, delete it */
+ if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING))
+ == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+ MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+ ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+ MPT_RPORT_INFO_FLAGS_MISSING);
+ fc_remote_port_delete(ri->rport);
+ /*
+ * remote port not really deleted 'cause
+ * binding is by WWPN and driver only
+ * registers FCP_TARGETs
+ */
+ #ifdef MPT_DEBUG
+ printk ("mptfc_rescan.%d: %llx deleted\n",
+ ioc->sh->host_no, ri->pg0.WWPN);
+ #endif
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+ /*
+ * allow multiple passes as target state
+ * might have changed during scan
+ */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ if (ioc->fc_rescan_work_count > 2) /* only need one more */
+ ioc->fc_rescan_work_count = 2;
+ work_to_do = --ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ } while (work_to_do);
+}
+
static int
mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -145,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
-
+
if ((r = mpt_attach(pdev,id)) != 0)
return r;
-
+
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptfcDoneCtx;
ioc->TaskCtx = mptfcTaskCtx;
@@ -167,13 +645,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptfc_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptfc_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
@@ -189,7 +669,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
- return 0;
+ return -ENODEV;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -198,9 +678,12 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
- return -1;
+ error = -1;
+ goto out_mptfc_probe;
}
+ INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+
spin_lock_irqsave(&ioc->FreeQlock, flags);
/* Attach the SCSI Host to the IOC structure
@@ -262,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
- goto mptfc_probe_failed;
+ goto out_mptfc_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* Allocate memory for the device structures.
* A non-Null pointer at an offset
* indicates a device exists.
* max_id = 1 + maximum id (hosts.h)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
- goto mptfc_probe_failed;
+ goto out_mptfc_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtDevice **) mem;
-
- dprintk((KERN_INFO
- " Targets @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -326,17 +800,22 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
+ sh->transportt = mptfc_transport_template;
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
- goto mptfc_probe_failed;
+ goto out_mptfc_probe;
+ }
+
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ mptfc_init_host_attr(ioc,ii);
+ mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
}
- scsi_scan_host(sh);
return 0;
-mptfc_probe_failed:
+out_mptfc_probe:
mptscsih_remove(pdev);
return error;
@@ -346,7 +825,7 @@ static struct pci_driver mptfc_driver = {
.name = "mptfc",
.id_table = mptfc_pci_table,
.probe = mptfc_probe,
- .remove = __devexit_p(mptscsih_remove),
+ .remove = __devexit_p(mptfc_remove),
.shutdown = mptscsih_shutdown,
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
@@ -364,9 +843,20 @@ static struct pci_driver mptfc_driver = {
static int __init
mptfc_init(void)
{
+ int error;
show_mptmod_ver(my_NAME, my_VERSION);
+ /* sanity check module parameter */
+ if (mptfc_dev_loss_tmo == 0)
+ mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
+
+ mptfc_transport_template =
+ fc_attach_transport(&mptfc_transport_functions);
+
+ if (!mptfc_transport_template)
+ return -ENODEV;
+
mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -381,7 +871,33 @@ mptfc_init(void)
": Registered for IOC reset notifications\n"));
}
- return pci_register_driver(&mptfc_driver);
+ error = pci_register_driver(&mptfc_driver);
+ if (error) {
+ fc_release_transport(mptfc_transport_template);
+ }
+
+ return error;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptfc_remove - Removed fc infrastructure for devices
+ * @pdev: Pointer to pci_dev structure
+ *
+ */
+static void __devexit mptfc_remove(struct pci_dev *pdev)
+{
+ MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+ struct mptfc_rport_info *p, *n;
+
+ fc_remove_host(ioc->sh);
+
+ list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
+
+ mptscsih_remove(pdev);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -394,7 +910,8 @@ static void __exit
mptfc_exit(void)
{
pci_unregister_driver(&mptfc_driver);
-
+ fc_release_transport(mptfc_transport_template);
+
mpt_reset_deregister(mptfcDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 014085d8ec85..73f59528212a 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev)
goto out;
priv->mpt_txfidx_tail = -1;
- priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+ priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->SendCtl == NULL)
goto out_mpt_txfidx;
- for (i = 0; i < priv->tx_max_out; i++) {
- memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->tx_max_out; i++)
priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
- }
dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
@@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev)
goto out_SendCtl;
priv->mpt_rxfidx_tail = -1;
- priv->RcvCtl = kmalloc(priv->max_buckets_out *
- sizeof(struct BufferControl),
+ priv->RcvCtl = kcalloc(priv->max_buckets_out,
+ sizeof(struct BufferControl),
GFP_KERNEL);
if (priv->RcvCtl == NULL)
goto out_mpt_rxfidx;
- for (i = 0; i < priv->max_buckets_out; i++) {
- memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+ for (i = 0; i < priv->max_buckets_out; i++)
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
- }
/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
/**/ for (i = 0; i < priv->tx_max_out; i++)
@@ -848,7 +844,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static inline void
+static void
mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
/*
* @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue
@@ -870,7 +866,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static inline int
+static int
mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb)
{
struct mpt_lan_priv *priv = dev->priv;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index e0a8bb8ba7d8..5a06d8d8694e 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
- * Copyright (c) 2005 Dell
+ * Copyright (c) 2005-2006 Dell
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -86,6 +86,24 @@ static int mptsasInternalCtx = -1; /* Used only for internal commands */
static int mptsasMgmtCtx = -1;
+enum mptsas_hotplug_action {
+ MPTSAS_ADD_DEVICE,
+ MPTSAS_DEL_DEVICE,
+};
+
+struct mptsas_hotplug_event {
+ struct work_struct work;
+ MPT_ADAPTER *ioc;
+ enum mptsas_hotplug_action event_type;
+ u64 sas_address;
+ u32 channel;
+ u32 id;
+ u32 device_info;
+ u16 handle;
+ u16 parent_handle;
+ u8 phy_id;
+};
+
/*
* SAS topology structures
*
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
u8 phy_id; /* phy number of parent device */
u8 port_id; /* sas physical port this device
is assoc'd with */
- u8 target; /* logical target id of this device */
- u8 bus; /* logical bus number of this device */
+ u8 id; /* logical target id of this device */
+ u8 channel; /* logical bus number of this device */
u64 sas_address; /* WWN of this device,
SATA is assigned by HBA,expander */
u32 device_info; /* bitfield detailed info about this device */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
u8 programmed_link_rate; /* programmed max/min phy link rate */
struct mptsas_devinfo identify; /* point to phy device info */
struct mptsas_devinfo attached; /* point to attached device info */
+ struct sas_phy *phy;
struct sas_rphy *rphy;
};
@@ -228,63 +247,120 @@ static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
* implement ->target_alloc.
*/
static int
-mptsas_slave_alloc(struct scsi_device *device)
+mptsas_slave_alloc(struct scsi_device *sdev)
{
- struct Scsi_Host *host = device->host;
+ struct Scsi_Host *host = sdev->host;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
struct sas_rphy *rphy;
struct mptsas_portinfo *p;
+ VirtTarget *vtarget;
VirtDevice *vdev;
- uint target = device->id;
+ struct scsi_target *starget;
int i;
- if ((vdev = hd->Targets[target]) != NULL)
- goto out;
-
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
}
-
- memset(vdev, 0, sizeof(VirtDevice));
- vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
vdev->ioc_id = hd->ioc->id;
+ sdev->hostdata = vdev;
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ vdev->vtarget = vtarget;
+ if (vtarget->num_luns == 0) {
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
+ hd->Targets[sdev->id] = vtarget;
+ }
- rphy = dev_to_rphy(device->sdev_target->dev.parent);
+ /*
+ RAID volumes placed beyond the last expected port.
+ */
+ if (sdev->channel == hd->ioc->num_ports) {
+ vdev->target_id = sdev->id;
+ vdev->bus_id = 0;
+ vdev->lun = 0;
+ goto out;
+ }
+
+ rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+ mutex_lock(&hd->ioc->sas_topology_mutex);
list_for_each_entry(p, &hd->ioc->sas_topology, list) {
for (i = 0; i < p->num_phys; i++) {
if (p->phy_info[i].attached.sas_address ==
rphy->identify.sas_address) {
vdev->target_id =
- p->phy_info[i].attached.target;
- vdev->bus_id = p->phy_info[i].attached.bus;
- hd->Targets[device->id] = vdev;
+ p->phy_info[i].attached.id;
+ vdev->bus_id = p->phy_info[i].attached.channel;
+ vdev->lun = sdev->lun;
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
goto out;
}
}
}
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
printk("No matching SAS device found!!\n");
kfree(vdev);
return -ENODEV;
out:
- vdev->num_luns++;
- device->hostdata = vdev;
+ vtarget->ioc_id = vdev->ioc_id;
+ vtarget->target_id = vdev->target_id;
+ vtarget->bus_id = vdev->bus_id;
+ vtarget->num_luns++;
return 0;
}
+static void
+mptsas_slave_destroy(struct scsi_device *sdev)
+{
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ struct sas_rphy *rphy;
+ struct mptsas_portinfo *p;
+ int i;
+
+ /*
+ * Handle hotplug removal case.
+ * We need to clear out attached data structure.
+ */
+ rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+
+ mutex_lock(&hd->ioc->sas_topology_mutex);
+ list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+ for (i = 0; i < p->num_phys; i++) {
+ if (p->phy_info[i].attached.sas_address ==
+ rphy->identify.sas_address) {
+ memset(&p->phy_info[i].attached, 0,
+ sizeof(struct mptsas_devinfo));
+ p->phy_info[i].rphy = NULL;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ mutex_unlock(&hd->ioc->sas_topology_mutex);
+ /*
+ * TODO: Issue target reset to flush firmware outstanding commands.
+ */
+ mptscsih_slave_destroy(sdev);
+}
+
static struct scsi_host_template mptsas_driver_template = {
+ .module = THIS_MODULE,
.proc_name = "mptsas",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
+ .target_alloc = mptscsih_target_alloc,
.slave_alloc = mptsas_slave_alloc,
.slave_configure = mptscsih_slave_configure,
- .slave_destroy = mptscsih_slave_destroy,
+ .target_destroy = mptscsih_target_destroy,
+ .slave_destroy = mptsas_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
@@ -390,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
return -ENXIO;
- if (down_interruptible(&ioc->sas_mgmt.mutex))
+ if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
goto out;
mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -441,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
error = 0;
out_unlock:
- up(&ioc->sas_mgmt.mutex);
+ mutex_unlock(&ioc->sas_mgmt.mutex);
out:
return error;
}
@@ -640,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
device_info->handle = le16_to_cpu(buffer->DevHandle);
device_info->phy_id = buffer->PhyNum;
device_info->port_id = buffer->PhysicalPort;
- device_info->target = buffer->TargetID;
- device_info->bus = buffer->Bus;
+ device_info->id = buffer->TargetID;
+ device_info->channel = buffer->Bus;
memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
device_info->sas_address = le64_to_cpu(sas_address);
device_info->device_info =
@@ -849,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
static int mptsas_probe_one_phy(struct device *dev,
struct mptsas_phyinfo *phy_info, int index, int local)
{
- struct sas_phy *port;
+ struct sas_phy *phy;
int error;
- port = sas_phy_alloc(dev, index);
- if (!port)
+ phy = sas_phy_alloc(dev, index);
+ if (!phy)
return -ENOMEM;
- port->port_identifier = phy_info->port_id;
- mptsas_parse_device_info(&port->identify, &phy_info->identify);
+ phy->port_identifier = phy_info->port_id;
+ mptsas_parse_device_info(&phy->identify, &phy_info->identify);
/*
* Set Negotiated link rate.
*/
switch (phy_info->negotiated_link_rate) {
case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
- port->negotiated_linkrate = SAS_PHY_DISABLED;
+ phy->negotiated_linkrate = SAS_PHY_DISABLED;
break;
case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
- port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+ phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
break;
case MPI_SAS_IOUNIT0_RATE_1_5:
- port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_IOUNIT0_RATE_3_0:
- port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
default:
- port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+ phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
break;
}
@@ -887,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
- port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
- port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -902,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev,
switch (phy_info->programmed_link_rate &
MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
- port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
- port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -916,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev,
*/
switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
- port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
- port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+ phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
@@ -931,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev,
switch (phy_info->programmed_link_rate &
MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
- port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+ phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
break;
case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
- port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+ phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
break;
default:
break;
}
if (local)
- port->local_attached = 1;
+ phy->local_attached = 1;
- error = sas_phy_add(port);
+ error = sas_phy_add(phy);
if (error) {
- sas_phy_free(port);
+ sas_phy_free(phy);
return error;
}
+ phy_info->phy = phy;
if (phy_info->attached.handle) {
struct sas_rphy *rphy;
- rphy = sas_rphy_alloc(port);
+ rphy = sas_rphy_alloc(phy);
if (!rphy)
return 0; /* non-fatal: an rphy can be added later */
@@ -976,16 +1053,18 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
u32 handle = 0xFFFF;
int error = -ENOMEM, i;
- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
if (!port_info)
goto out;
- memset(port_info, 0, sizeof(*port_info));
error = mptsas_sas_io_unit_pg0(ioc, port_info);
if (error)
goto out_free_port_info;
+ ioc->num_ports = port_info->num_phys;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ mutex_unlock(&ioc->sas_topology_mutex);
for (i = 0; i < port_info->num_phys; i++) {
mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
@@ -1026,10 +1105,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
struct mptsas_portinfo *port_info, *p;
int error = -ENOMEM, i, j;
- port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+ port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
if (!port_info)
goto out;
- memset(port_info, 0, sizeof(*port_info));
error = mptsas_sas_expander_pg0(ioc, port_info,
(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
@@ -1039,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
*handle = port_info->handle;
+ mutex_lock(&ioc->sas_topology_mutex);
list_add_tail(&port_info->list, &ioc->sas_topology);
+ mutex_unlock(&ioc->sas_topology_mutex);
+
for (i = 0; i < port_info->num_phys; i++) {
struct device *parent;
@@ -1071,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
* HBA phys.
*/
parent = &ioc->sh->shost_gendev;
+ mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry(p, &ioc->sas_topology, list) {
for (j = 0; j < p->num_phys; j++) {
if (port_info->phy_info[i].identify.handle ==
@@ -1078,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
parent = &p->phy_info[j].rphy->dev;
}
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptsas_probe_one_phy(parent, &port_info->phy_info[i],
*index, 0);
@@ -1103,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
;
}
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_devinfo device_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i, error;
+
+ /*
+ * Retrieve the parent sas_address
+ */
+ error = mptsas_sas_device_pg0(ioc, &device_info,
+ (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+ MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+ parent_handle);
+ if (error) {
+ printk("mptsas: failed to retrieve device page\n");
+ return NULL;
+ }
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].identify.sas_address ==
+ device_info.sas_address &&
+ port_info->phy_info[i].phy_id == phy_id) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+ struct mptsas_portinfo *port_info;
+ struct mptsas_phyinfo *phy_info = NULL;
+ int i;
+
+ /*
+ * The phy_info structures are never deallocated during lifetime of
+ * a host, so the code below is safe without additional refcounting.
+ */
+ mutex_lock(&ioc->sas_topology_mutex);
+ list_for_each_entry(port_info, &ioc->sas_topology, list) {
+ for (i = 0; i < port_info->num_phys; i++) {
+ if (port_info->phy_info[i].attached.handle == handle) {
+ phy_info = &port_info->phy_info[i];
+ break;
+ }
+ }
+ }
+ mutex_unlock(&ioc->sas_topology_mutex);
+
+ return phy_info;
+}
+
+static void
+mptsas_hotplug_work(void *arg)
+{
+ struct mptsas_hotplug_event *ev = arg;
+ MPT_ADAPTER *ioc = ev->ioc;
+ struct mptsas_phyinfo *phy_info;
+ struct sas_rphy *rphy;
+ char *ds = NULL;
+
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+ ds = "ssp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "stp";
+ if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "sata";
+
+ switch (ev->event_type) {
+ case MPTSAS_DEL_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "removing %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+ if (!phy_info) {
+ printk("mptsas: remove event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ sas_rphy_delete(phy_info->rphy);
+ phy_info->rphy = NULL;
+ }
+ break;
+ case MPTSAS_ADD_DEVICE:
+ printk(MYIOC_s_INFO_FMT
+ "attaching %s device, channel %d, id %d, phy %d\n",
+ ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+ phy_info = mptsas_find_phyinfo_by_parent(ioc,
+ ev->parent_handle, ev->phy_id);
+ if (!phy_info) {
+ printk("mptsas: add event for non-existant PHY.\n");
+ break;
+ }
+
+ if (phy_info->rphy) {
+ printk("mptsas: trying to add existing device.\n");
+ break;
+ }
+
+ /* fill attached info */
+ phy_info->attached.handle = ev->handle;
+ phy_info->attached.phy_id = ev->phy_id;
+ phy_info->attached.port_id = phy_info->identify.port_id;
+ phy_info->attached.id = ev->id;
+ phy_info->attached.channel = ev->channel;
+ phy_info->attached.sas_address = ev->sas_address;
+ phy_info->attached.device_info = ev->device_info;
+
+ rphy = sas_rphy_alloc(phy_info->phy);
+ if (!rphy)
+ break; /* non-fatal: an rphy can be added later */
+
+ mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+ if (sas_rphy_add(rphy)) {
+ sas_rphy_free(rphy);
+ break;
+ }
+
+ phy_info->rphy = rphy;
+ break;
+ }
+
+ kfree(ev);
+}
+
+static void
+mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+ EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+ struct mptsas_hotplug_event *ev;
+ u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+ __le64 sas_address;
+
+ if ((device_info &
+ (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+ MPI_SAS_DEVICE_INFO_STP_TARGET |
+ MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+ return;
+
+ if ((sas_event_data->ReasonCode &
+ (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
+ MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
+ return;
+
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ printk(KERN_WARNING "mptsas: lost hotplug event\n");
+ return;
+ }
+
+
+ INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+ ev->ioc = ioc;
+ ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+ ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+ ev->channel = sas_event_data->Bus;
+ ev->id = sas_event_data->TargetID;
+ ev->phy_id = sas_event_data->PhyNum;
+ memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
+ ev->sas_address = le64_to_cpu(sas_address);
+ ev->device_info = device_info;
+
+ if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+ ev->event_type = MPTSAS_ADD_DEVICE;
+ else
+ ev->event_type = MPTSAS_DEL_DEVICE;
+
+ schedule_work(&ev->work);
+}
+
+static int
+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+{
+ u8 event = le32_to_cpu(reply->Event) & 0xFF;
+
+ if (!ioc->sh)
+ return 1;
+
+ switch (event) {
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ mptscsih_send_sas_event(ioc,
+ (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+ return 1; /* currently means nothing really */
+
+ default:
+ return mptscsih_event_process(ioc, reply);
+ }
+}
+
static int
mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -1110,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -1133,13 +1420,15 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptsas_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptsas_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
@@ -1163,7 +1452,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
- return -1;
+ error = -1;
+ goto out_mptsas_probe;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -1192,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sh->unique_id = ioc->id;
INIT_LIST_HEAD(&ioc->sas_topology);
- init_MUTEX(&ioc->sas_mgmt.mutex);
+ mutex_init(&ioc->sas_topology_mutex);
+
+ mutex_init(&ioc->sas_mgmt.mutex);
init_completion(&ioc->sas_mgmt.done);
/* Verify that we won't exceed the maximum
@@ -1233,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
- goto mptsas_probe_failed;
+ goto out_mptsas_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* Allocate memory for the device structures.
* A non-Null pointer at an offset
* indicates a device exists.
* max_id = 1 + maximum id (hosts.h)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
- goto mptsas_probe_failed;
+ goto out_mptsas_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtDevice **) mem;
-
- dprintk((KERN_INFO
- " Targets @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -1308,14 +1591,28 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
- goto mptsas_probe_failed;
+ goto out_mptsas_probe;
}
mptsas_scan_sas_topology(ioc);
+ /*
+ Reporting RAID volumes.
+ */
+ if (!ioc->raid_data.pIocPg2)
+ return 0;
+ if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+ return 0;
+ for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
+ scsi_add_device(sh,
+ ioc->num_ports,
+ ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
+ 0);
+ }
+
return 0;
-mptsas_probe_failed:
+out_mptsas_probe:
mptscsih_remove(pdev);
return error;
@@ -1328,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
sas_remove_host(ioc->sh);
+ mutex_lock(&ioc->sas_topology_mutex);
list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
list_del(&p->list);
kfree(p);
}
+ mutex_unlock(&ioc->sas_topology_mutex);
mptscsih_remove(pdev);
}
@@ -1382,7 +1681,7 @@ mptsas_init(void)
mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
- if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+ if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index b7b9846ff3fd..cdac5578fdf2 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -150,28 +150,29 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 tar
int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
-static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
-static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
+static void mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen);
+static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *vtarget, char byte56);
static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
-static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
+static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
-static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
+static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice);
+static void mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget);
+static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
static struct work_struct mptscsih_persistTask;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io);
static void mptscsih_domainValidation(void *hd);
-static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id);
static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id);
static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id);
+static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc);
#endif
void mptscsih_remove(struct pci_dev *);
@@ -627,7 +628,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n"
"IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n"
"resid=%d bufflen=%d xfer_cnt=%d\n",
- ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+ ioc->id, sc->device->id, sc->device->lun,
status, scsi_state, scsi_status, sc->resid,
sc->request_bufflen, xfer_cnt));
@@ -641,7 +642,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
pScsiReply->ResponseInfo) {
printk(KERN_NOTICE "ha=%d id=%d lun=%d: "
"FCP_ResponseInfo=%08xh\n",
- ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
+ ioc->id, sc->device->id, sc->device->lun,
le32_to_cpu(pScsiReply->ResponseInfo));
}
@@ -677,8 +678,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->result = DID_RESET << 16;
/* GEM Workaround. */
- if (ioc->bus_type == SCSI)
- mptscsih_no_negotiate(hd, sc->device->id);
+ if (ioc->bus_type == SPI)
+ mptscsih_no_negotiate(hd, sc);
break;
case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */
@@ -892,16 +893,16 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
* when a lun is disable by mid-layer.
* Do NOT access the referenced scsi_cmnd structure or
* members. Will cause either a paging or NULL ptr error.
- * @hd: Pointer to a SCSI HOST structure
- * @target: target id
- * @lun: lun
+ * (BUT, BUT, BUT, the code does reference it! - mdr)
+ * @hd: Pointer to a SCSI HOST structure
+ * @vdevice: per device private data
*
* Returns: None.
*
* Called from slave_destroy.
*/
static void
-mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
+mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
{
SCSIIORequest_t *mf = NULL;
int ii;
@@ -909,7 +910,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
struct scsi_cmnd *sc;
dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n",
- target, lun, max));
+ vdevice->target_id, vdevice->lun, max));
for (ii=0; ii < max; ii++) {
if ((sc = hd->ScsiLookup[ii]) != NULL) {
@@ -919,7 +920,7 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
dsprintk(( "search_running: found (sc=%p, mf = %p) target %d, lun %d \n",
hd->ScsiLookup[ii], mf, mf->TargetID, mf->LUN[1]));
- if ((mf->TargetID != ((u8)target)) || (mf->LUN[1] != ((u8) lun)))
+ if ((mf->TargetID != ((u8)vdevice->target_id)) || (mf->LUN[1] != ((u8) vdevice->lun)))
continue;
/* Cleanup
@@ -993,8 +994,10 @@ mptscsih_remove(struct pci_dev *pdev)
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct Scsi_Host *host = ioc->sh;
MPT_SCSI_HOST *hd;
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
int count;
unsigned long flags;
+#endif
int sz1;
if(!host) {
@@ -1075,11 +1078,6 @@ mptscsih_shutdown(struct pci_dev *pdev)
hd = (MPT_SCSI_HOST *)host->hostdata;
- /* Flush the cache of this adapter
- */
- if(hd != NULL)
- mptscsih_synchronize_cache(hd, 0);
-
}
#ifdef CONFIG_PM
@@ -1286,7 +1284,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
MPT_SCSI_HOST *hd;
MPT_FRAME_HDR *mf;
SCSIIORequest_t *pScsiReq;
- VirtDevice *pTarget = SCpnt->device->hostdata;
+ VirtDevice *vdev = SCpnt->device->hostdata;
int lun;
u32 datalen;
u32 scsictl;
@@ -1341,8 +1339,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Default to untagged. Once a target structure has been allocated,
* use the Inquiry data to determine if device supports tagged.
*/
- if (pTarget
- && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+ if (vdev
+ && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
&& (SCpnt->device->tagged_supported)) {
scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
} else {
@@ -1351,8 +1349,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Use the above information to set up the message frame
*/
- pScsiReq->TargetID = (u8) pTarget->target_id;
- pScsiReq->Bus = pTarget->bus_id;
+ pScsiReq->TargetID = (u8) vdev->target_id;
+ pScsiReq->Bus = vdev->bus_id;
pScsiReq->ChainOffset = 0;
pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST;
pScsiReq->CDBLength = SCpnt->cmd_len;
@@ -1403,8 +1401,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
SCpnt->host_scribble = NULL;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
- if (hd->ioc->bus_type == SCSI) {
- int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id];
+ if (hd->ioc->bus_type == SPI) {
+ int dvStatus = hd->ioc->spi_data.dvStatus[vdev->target_id];
int issueCmd = 1;
if (dvStatus || hd->ioc->spi_data.forceDv) {
@@ -1437,7 +1435,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/* Set the DV flags.
*/
if (dvStatus & MPT_SCSICFG_DV_NOT_DONE)
- mptscsih_set_dvflags(hd, pScsiReq);
+ mptscsih_set_dvflags(hd, SCpnt);
if (!issueCmd)
goto fail;
@@ -1741,6 +1739,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
u32 ctx2abort;
int scpnt_idx;
int retval;
+ VirtDevice *vdev;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -1790,8 +1789,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
hd->abortSCpnt = SCpnt;
+ vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
- SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
+ vdev->bus_id, vdev->target_id, vdev->lun,
ctx2abort, 2 /* 2 second timeout */);
printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n",
@@ -1822,6 +1822,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
int retval;
+ VirtDevice *vdev;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -1839,8 +1840,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
hd->ioc->name, SCpnt);
scsi_print_command(SCpnt);
+ vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
- SCpnt->device->channel, SCpnt->device->id,
+ vdev->bus_id, vdev->target_id,
0, 0, 5 /* 5 second timeout */);
printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n",
@@ -1871,6 +1873,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
int retval;
+ VirtDevice *vdev;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -1888,8 +1891,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
if (hd->timeouts < -1)
hd->timeouts++;
+ vdev = SCpnt->device->hostdata;
retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
- SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */);
+ vdev->bus_id, 0, 0, 0, 5 /* 5 second timeout */);
printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n",
hd->ioc->name,
@@ -2151,51 +2155,70 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* OS entry point to allow host driver to alloc memory
+ * for each scsi target. Called once per device the bus scan.
+ * Return non-zero if allocation fails.
+ */
+int
+mptscsih_target_alloc(struct scsi_target *starget)
+{
+ VirtTarget *vtarget;
+
+ vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
+ if (!vtarget)
+ return -ENOMEM;
+ starget->hostdata = vtarget;
+ return 0;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * OS entry point to allow host driver to alloc memory
* for each scsi device. Called once per device the bus scan.
* Return non-zero if allocation fails.
- * Init memory once per id (not LUN).
*/
int
-mptscsih_slave_alloc(struct scsi_device *device)
+mptscsih_slave_alloc(struct scsi_device *sdev)
{
- struct Scsi_Host *host = device->host;
+ struct Scsi_Host *host = sdev->host;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ VirtTarget *vtarget;
VirtDevice *vdev;
- uint target = device->id;
-
- if (hd == NULL)
- return -ENODEV;
+ struct scsi_target *starget;
- if ((vdev = hd->Targets[target]) != NULL)
- goto out;
-
- vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+ vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
if (!vdev) {
printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
hd->ioc->name, sizeof(VirtDevice));
return -ENOMEM;
}
- memset(vdev, 0, sizeof(VirtDevice));
- vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
vdev->ioc_id = hd->ioc->id;
- vdev->target_id = device->id;
- vdev->bus_id = device->channel;
- vdev->raidVolume = 0;
- hd->Targets[device->id] = vdev;
- if (hd->ioc->bus_type == SCSI) {
- if (hd->ioc->raid_data.isRaid & (1 << device->id)) {
- vdev->raidVolume = 1;
- ddvtprintk((KERN_INFO
- "RAID Volume @ id %d\n", device->id));
+ vdev->target_id = sdev->id;
+ vdev->bus_id = sdev->channel;
+ vdev->lun = sdev->lun;
+ sdev->hostdata = vdev;
+
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ vdev->vtarget = vtarget;
+
+ if (vtarget->num_luns == 0) {
+ hd->Targets[sdev->id] = vtarget;
+ vtarget->ioc_id = hd->ioc->id;
+ vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
+ vtarget->target_id = sdev->id;
+ vtarget->bus_id = sdev->channel;
+ if (hd->ioc->bus_type == SPI) {
+ if (hd->ioc->raid_data.isRaid & (1 << sdev->id)) {
+ vtarget->raidVolume = 1;
+ ddvtprintk((KERN_INFO
+ "RAID Volume @ id %d\n", sdev->id));
+ }
+ } else {
+ vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
}
- } else {
- vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
}
-
- out:
- vdev->num_luns++;
- device->hostdata = vdev;
+ vtarget->num_luns++;
return 0;
}
@@ -2204,40 +2227,52 @@ mptscsih_slave_alloc(struct scsi_device *device)
* Called if no device present or device being unloaded
*/
void
-mptscsih_slave_destroy(struct scsi_device *device)
+mptscsih_target_destroy(struct scsi_target *starget)
{
- struct Scsi_Host *host = device->host;
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
- VirtDevice *vdev;
- uint target = device->id;
- uint lun = device->lun;
-
- if (hd == NULL)
- return;
-
- mptscsih_search_running_cmds(hd, target, lun);
-
- vdev = hd->Targets[target];
- vdev->luns[0] &= ~(1 << lun);
- if (--vdev->num_luns)
- return;
-
- kfree(hd->Targets[target]);
- hd->Targets[target] = NULL;
-
- if (hd->ioc->bus_type == SCSI) {
- if (mptscsih_is_phys_disk(hd->ioc, target)) {
- hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
- } else {
- hd->ioc->spi_data.dvStatus[target] =
- MPT_SCSICFG_NEGOTIATE;
+ if (starget->hostdata)
+ kfree(starget->hostdata);
+ starget->hostdata = NULL;
+}
- if (!hd->negoNvram) {
- hd->ioc->spi_data.dvStatus[target] |=
- MPT_SCSICFG_DV_NOT_DONE;
+/*
+ * OS entry point to allow for host driver to free allocated memory
+ * Called if no device present or device being unloaded
+ */
+void
+mptscsih_slave_destroy(struct scsi_device *sdev)
+{
+ struct Scsi_Host *host = sdev->host;
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+ VirtTarget *vtarget;
+ VirtDevice *vdevice;
+ struct scsi_target *starget;
+
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ vdevice = sdev->hostdata;
+
+ mptscsih_search_running_cmds(hd, vdevice);
+ vtarget->luns[0] &= ~(1 << vdevice->lun);
+ vtarget->num_luns--;
+ if (vtarget->num_luns == 0) {
+ mptscsih_negotiate_to_asyn_narrow(hd, vtarget);
+ if (hd->ioc->bus_type == SPI) {
+ if (mptscsih_is_phys_disk(hd->ioc, vtarget->target_id)) {
+ hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
+ } else {
+ hd->ioc->spi_data.dvStatus[vtarget->target_id] =
+ MPT_SCSICFG_NEGOTIATE;
+ if (!hd->negoNvram) {
+ hd->ioc->spi_data.dvStatus[vtarget->target_id] |=
+ MPT_SCSICFG_DV_NOT_DONE;
+ }
}
}
+ hd->Targets[sdev->id] = NULL;
}
+ mptscsih_synchronize_cache(hd, vdevice);
+ kfree(vdevice);
+ sdev->hostdata = NULL;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2251,22 +2286,21 @@ mptscsih_slave_destroy(struct scsi_device *device)
int
mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
- MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
- VirtDevice *pTarget;
- int max_depth;
- int tagged;
-
- if (hd == NULL)
- return 0;
- if (!(pTarget = hd->Targets[sdev->id]))
- return 0;
-
- if (hd->ioc->bus_type == SCSI) {
- if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
- if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+ MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+ VirtTarget *vtarget;
+ struct scsi_target *starget;
+ int max_depth;
+ int tagged;
+
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+
+ if (hd->ioc->bus_type == SPI) {
+ if (vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+ if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES))
max_depth = 1;
- else if (((pTarget->inq_data[0] & 0x1f) == 0x00) &&
- (pTarget->minSyncFactor <= MPT_ULTRA160 ))
+ else if (((vtarget->inq_data[0] & 0x1f) == 0x00) &&
+ (vtarget->minSyncFactor <= MPT_ULTRA160 ))
max_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
else
max_depth = MPT_SCSI_CMD_PER_DEV_LOW;
@@ -2295,64 +2329,58 @@ mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
* Return non-zero if fails.
*/
int
-mptscsih_slave_configure(struct scsi_device *device)
+mptscsih_slave_configure(struct scsi_device *sdev)
{
- struct Scsi_Host *sh = device->host;
- VirtDevice *pTarget;
+ struct Scsi_Host *sh = sdev->host;
+ VirtTarget *vtarget;
+ VirtDevice *vdevice;
+ struct scsi_target *starget;
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata;
+ int indexed_lun, lun_index;
- if ((hd == NULL) || (hd->Targets == NULL)) {
- return 0;
- }
+ starget = scsi_target(sdev);
+ vtarget = starget->hostdata;
+ vdevice = sdev->hostdata;
dsprintk((MYIOC_s_INFO_FMT
"device @ %p, id=%d, LUN=%d, channel=%d\n",
- hd->ioc->name, device, device->id, device->lun, device->channel));
- dsprintk((MYIOC_s_INFO_FMT
- "sdtr %d wdtr %d ppr %d inq length=%d\n",
- hd->ioc->name, device->sdtr, device->wdtr,
- device->ppr, device->inquiry_len));
-
- if (device->id > sh->max_id) {
+ hd->ioc->name, sdev, sdev->id, sdev->lun, sdev->channel));
+ if (hd->ioc->bus_type == SPI)
+ dsprintk((MYIOC_s_INFO_FMT
+ "sdtr %d wdtr %d ppr %d inq length=%d\n",
+ hd->ioc->name, sdev->sdtr, sdev->wdtr,
+ sdev->ppr, sdev->inquiry_len));
+
+ if (sdev->id > sh->max_id) {
/* error case, should never happen */
- scsi_adjust_queue_depth(device, 0, 1);
- goto slave_configure_exit;
- }
-
- pTarget = hd->Targets[device->id];
-
- 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
- * "scsi add-single-device" command is executed
- * 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,
- MPT_SCSI_CMD_PER_DEV_HIGH);
+ scsi_adjust_queue_depth(sdev, 0, 1);
goto slave_configure_exit;
}
- mptscsih_initTarget(hd, device->channel, device->id, device->lun,
- device->inquiry, device->inquiry_len );
- mptscsih_change_queue_depth(device, MPT_SCSI_CMD_PER_DEV_HIGH);
+ vdevice->configured_lun=1;
+ lun_index = (vdevice->lun >> 5); /* 32 luns per lun_index */
+ indexed_lun = (vdevice->lun % 32);
+ vtarget->luns[lun_index] |= (1 << indexed_lun);
+ mptscsih_initTarget(hd, vtarget, sdev->lun, sdev->inquiry,
+ sdev->inquiry_len );
+ mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH);
dsprintk((MYIOC_s_INFO_FMT
"Queue depth=%d, tflags=%x\n",
- hd->ioc->name, device->queue_depth, pTarget->tflags));
+ hd->ioc->name, sdev->queue_depth, vtarget->tflags));
- dsprintk((MYIOC_s_INFO_FMT
- "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
- hd->ioc->name, pTarget->negoFlags, pTarget->maxOffset, pTarget->minSyncFactor));
+ if (hd->ioc->bus_type == SPI)
+ dsprintk((MYIOC_s_INFO_FMT
+ "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n",
+ hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset,
+ vtarget->minSyncFactor));
slave_configure_exit:
dsprintk((MYIOC_s_INFO_FMT
"tagged %d, simple %d, ordered %d\n",
- hd->ioc->name,device->tagged_supported, device->simple_tags,
- device->ordered_tags));
+ hd->ioc->name,sdev->tagged_supported, sdev->simple_tags,
+ sdev->ordered_tags));
return 0;
}
@@ -2370,16 +2398,14 @@ slave_configure_exit:
static void
mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
{
- VirtDevice *target;
+ VirtDevice *vdev;
SCSIIORequest_t *pReq;
u32 sense_count = le32_to_cpu(pScsiReply->SenseCount);
- int index;
/* Get target structure
*/
pReq = (SCSIIORequest_t *) mf;
- index = (int) pReq->TargetID;
- target = hd->Targets[index];
+ vdev = sc->device->hostdata;
if (sense_count) {
u8 *sense_data;
@@ -2393,7 +2419,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
/* Log SMART data (asc = 0x5D, non-IM case only) if required.
*/
if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) {
- if ((sense_data[12] == 0x5D) && (target->raidVolume == 0)) {
+ if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) {
int idx;
MPT_ADAPTER *ioc = hd->ioc;
@@ -2403,7 +2429,7 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR
ioc->events[idx].data[0] = (pReq->LUN[1] << 24) ||
(MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA << 16) ||
- (pReq->Bus << 8) || pReq->TargetID;
+ (sc->device->channel << 8) || sc->device->id;
ioc->events[idx].data[1] = (sense_data[13] << 8) || sense_data[12];
@@ -2503,9 +2529,9 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
/* 2. Chain Buffer initialization
*/
- /* 4. Renegotiate to all devices, if SCSI
+ /* 4. Renegotiate to all devices, if SPI
*/
- if (ioc->bus_type == SCSI) {
+ if (ioc->bus_type == SPI) {
dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
}
@@ -2532,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
hd->cmdPtr = NULL;
}
- /* 7. Set flag to force DV and re-read IOC Page 3
+ /* 7. SPI: Set flag to force DV and re-read IOC Page 3
*/
- if (ioc->bus_type == SCSI) {
+ if (ioc->bus_type == SPI) {
ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
ddvtprintk(("Set reload IOC Pg3 Flag\n"));
}
+ /* 7. FC: Rescan for blocked rports which might have returned.
+ */
+ else if (ioc->bus_type == FC) {
+ int work_count;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ }
dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
}
@@ -2562,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
MPT_SCSI_HOST *hd;
u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+ int work_count;
+ unsigned long flags;
devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
ioc->name, event));
@@ -2576,18 +2616,25 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
break;
case MPI_EVENT_IOC_BUS_RESET: /* 04 */
case MPI_EVENT_EXT_BUS_RESET: /* 05 */
- if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1))
+ if (hd && (ioc->bus_type == SPI) && (hd->soft_resets < -1))
hd->soft_resets++;
break;
case MPI_EVENT_LOGOUT: /* 09 */
/* FIXME! */
break;
+ case MPI_EVENT_RESCAN: /* 06 */
+ spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+ work_count = ++ioc->fc_rescan_work_count;
+ spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+ if (work_count == 1)
+ schedule_work(&ioc->fc_rescan_work);
+ break;
+
/*
* CHECKME! Don't think we need to do
* anything for these, but...
*/
- case MPI_EVENT_RESCAN: /* 06 */
case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */
case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */
/*
@@ -2597,11 +2644,11 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
case MPI_EVENT_INTEGRATED_RAID: /* 0B */
{
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
pMpiEventDataRaid_t pRaidEventData =
(pMpiEventDataRaid_t) pEvReply->Data;
-#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* Domain Validation Needed */
- if (ioc->bus_type == SCSI &&
+ if (ioc->bus_type == SPI &&
pRaidEventData->ReasonCode ==
MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED)
mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum);
@@ -2632,8 +2679,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
/*
* mptscsih_initTarget - Target, LUN alloc/free functionality.
* @hd: Pointer to MPT_SCSI_HOST structure
- * @bus_id: Bus number (?)
- * @target_id: SCSI target id
+ * @vtarget: per target private data
* @lun: SCSI LUN id
* @data: Pointer to data
* @dlen: Number of INQUIRY bytes
@@ -2646,15 +2692,14 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
*
*/
static void
-mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen)
+mptscsih_initTarget(MPT_SCSI_HOST *hd, VirtTarget *vtarget, u8 lun, char *data, int dlen)
{
- int indexed_lun, lun_index;
- VirtDevice *vdev;
SpiCfgData *pSpi;
char data_56;
+ int inq_len;
dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
- hd->ioc->name, bus_id, target_id, lun, hd));
+ hd->ioc->name, vtarget->bus_id, vtarget->target_id, lun, hd));
/*
* If the peripheral qualifier filter is enabled then if the target reports a 0x1
@@ -2674,75 +2719,68 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
if (data[0] & 0xe0)
return;
- if ((vdev = hd->Targets[target_id]) == NULL) {
+ if (vtarget == NULL)
return;
- }
- lun_index = (lun >> 5); /* 32 luns per lun_index */
- indexed_lun = (lun % 32);
- vdev->luns[lun_index] |= (1 << indexed_lun);
-
- if (hd->ioc->bus_type == SCSI) {
- if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
- /* Treat all Processors as SAF-TE if
- * command line option is set */
- vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
- mptscsih_writeIOCPage4(hd, target_id, bus_id);
- }else if ((data[0] == TYPE_PROCESSOR) &&
- !(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
- if ( dlen > 49 ) {
- vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
- if ( data[44] == 'S' &&
- data[45] == 'A' &&
- data[46] == 'F' &&
- data[47] == '-' &&
- data[48] == 'T' &&
- data[49] == 'E' ) {
- vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
- mptscsih_writeIOCPage4(hd, target_id, bus_id);
- }
+ if (data)
+ vtarget->type = data[0];
+
+ if (hd->ioc->bus_type != SPI)
+ return;
+
+ if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+ /* Treat all Processors as SAF-TE if
+ * command line option is set */
+ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+ mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
+ }else if ((data[0] == TYPE_PROCESSOR) &&
+ !(vtarget->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
+ if ( dlen > 49 ) {
+ vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+ if ( data[44] == 'S' &&
+ data[45] == 'A' &&
+ data[46] == 'F' &&
+ data[47] == '-' &&
+ data[48] == 'T' &&
+ data[49] == 'E' ) {
+ vtarget->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+ mptscsih_writeIOCPage4(hd, vtarget->target_id, vtarget->bus_id);
}
}
- if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
- if ( dlen > 8 ) {
- memcpy (vdev->inq_data, data, 8);
- } else {
- memcpy (vdev->inq_data, data, dlen);
- }
+ }
+ if (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+ inq_len = dlen < 8 ? dlen : 8;
+ memcpy (vtarget->inq_data, data, inq_len);
+ /* If have not done DV, set the DV flag.
+ */
+ pSpi = &hd->ioc->spi_data;
+ if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
+ if (pSpi->dvStatus[vtarget->target_id] & MPT_SCSICFG_DV_NOT_DONE)
+ pSpi->dvStatus[vtarget->target_id] |= MPT_SCSICFG_NEED_DV;
+ }
+ vtarget->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
- /* If have not done DV, set the DV flag.
+ data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
+ if (dlen > 56) {
+ if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+ /* Update the target capabilities
*/
- pSpi = &hd->ioc->spi_data;
- if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
- if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
- pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
+ data_56 = data[56];
+ vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
}
-
- vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-
- data_56 = 0x0F; /* Default to full capabilities if Inq data length is < 57 */
- if (dlen > 56) {
- if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
- /* Update the target capabilities
- */
- data_56 = data[56];
- vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
- }
- }
- mptscsih_setTargetNegoParms(hd, vdev, data_56);
- } else {
- /* Initial Inquiry may not request enough data bytes to
- * obtain byte 57. DV will; if target doesn't return
- * at least 57 bytes, data[56] will be zero. */
- if (dlen > 56) {
- if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
- /* Update the target capabilities
- */
- data_56 = data[56];
- vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
- mptscsih_setTargetNegoParms(hd, vdev, data_56);
- }
+ }
+ mptscsih_setTargetNegoParms(hd, vtarget, data_56);
+ } else {
+ /* Initial Inquiry may not request enough data bytes to
+ * obtain byte 57. DV will; if target doesn't return
+ * at least 57 bytes, data[56] will be zero. */
+ if (dlen > 56) {
+ if ( (!(vtarget->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+ /* Update the target capabilities
+ */
+ data_56 = data[56];
+ vtarget->tflags |= MPT_TARGET_FLAGS_VALID_56;
+ mptscsih_setTargetNegoParms(hd, vtarget, data_56);
}
}
}
@@ -2755,12 +2793,12 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
*
*/
static void
-mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, char byte56)
{
SpiCfgData *pspi_data = &hd->ioc->spi_data;
int id = (int) target->target_id;
int nvram;
- VirtDevice *vdev;
+ VirtTarget *vtarget;
int ii;
u8 width = MPT_NARROW;
u8 factor = MPT_ASYNC;
@@ -2905,9 +2943,9 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
for (ii = 0; ii < id; ii++) {
- if ( (vdev = hd->Targets[ii]) ) {
- vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
- mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
+ if ( (vtarget = hd->Targets[ii]) ) {
+ vtarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+ mptscsih_writeSDP1(hd, 0, ii, vtarget->negoFlags);
}
}
}
@@ -2926,105 +2964,17 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
- * Else set the NEED_DV flag after Read Capacity Issued (disks)
- * or Mode Sense (cdroms).
- *
- * Tapes, initTarget will set this flag on completion of Inquiry command.
- * Called only if DV_NOT_DONE flag is set
- */
-static void
-mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- u8 cmd;
- SpiCfgData *pSpi;
-
- ddvtprintk((MYIOC_s_NOTE_FMT
- " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
- hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
-
- if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
- return;
-
- cmd = pReq->CDB[0];
-
- if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
- pSpi = &ioc->spi_data;
- if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) {
- /* Set NEED_DV for all hidden disks
- */
- Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
-
- while (numPDisk) {
- pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
- pPDisk++;
- numPDisk--;
- }
- }
- pSpi->dvStatus[pReq->TargetID] |= MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for visible disk id %d\n", pReq->TargetID));
- }
-}
-
-/* mptscsih_raid_set_dv_flags()
- *
- * New or replaced disk. Set DV flag and schedule DV.
- */
-static void
-mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
-{
- MPT_ADAPTER *ioc = hd->ioc;
- SpiCfgData *pSpi = &ioc->spi_data;
- Ioc3PhysDisk_t *pPDisk;
- int numPDisk;
-
- if (hd->negoNvram != 0)
- return;
-
- ddvtprintk(("DV requested for phys disk id %d\n", id));
- if (ioc->raid_data.pIocPg3) {
- pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
- numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
- while (numPDisk) {
- if (id == pPDisk->PhysDiskNum) {
- pSpi->dvStatus[pPDisk->PhysDiskID] =
- (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
- pSpi->forceDv = MPT_SCSICFG_NEED_DV;
- ddvtprintk(("NEED_DV set for phys disk id %d\n",
- pPDisk->PhysDiskID));
- break;
- }
- pPDisk++;
- numPDisk--;
- }
-
- if (numPDisk == 0) {
- /* The physical disk that needs DV was not found
- * in the stored IOC Page 3. The driver must reload
- * this page. DV routine will set the NEED_DV flag for
- * all phys disks that have DV_NOT_DONE set.
- */
- pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
- ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
- }
- }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* If no Target, bus reset on 1st I/O. Set the flag to
* prevent any future negotiations to this device.
*/
static void
-mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+mptscsih_no_negotiate(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
{
+ VirtDevice *vdev;
- if ((hd->Targets) && (hd->Targets[target_id] == NULL))
- hd->ioc->spi_data.dvStatus[target_id] |= MPT_SCSICFG_BLK_NEGO;
-
+ if ((vdev = sc->device->hostdata) != NULL)
+ hd->ioc->spi_data.dvStatus[vdev->target_id] |= MPT_SCSICFG_BLK_NEGO;
return;
}
@@ -3100,7 +3050,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
MPT_ADAPTER *ioc = hd->ioc;
Config_t *pReq;
SCSIDevicePage1_t *pData;
- VirtDevice *pTarget=NULL;
+ VirtTarget *vtarget=NULL;
MPT_FRAME_HDR *mf;
dma_addr_t dataDma;
u16 req_idx;
@@ -3180,11 +3130,11 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
/* If id is not a raid volume, get the updated
* transmission settings from the target structure.
*/
- if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
- width = pTarget->maxWidth;
- factor = pTarget->minSyncFactor;
- offset = pTarget->maxOffset;
- negoFlags = pTarget->negoFlags;
+ if (hd->Targets && (vtarget = hd->Targets[id]) && !vtarget->raidVolume) {
+ width = vtarget->maxWidth;
+ factor = vtarget->minSyncFactor;
+ offset = vtarget->maxOffset;
+ negoFlags = vtarget->negoFlags;
}
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
@@ -3904,149 +3854,137 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
- * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
- * @hd: Pointer to MPT_SCSI_HOST structure
- * @portnum: IOC port number
+ * mptscsih_negotiate_to_asyn_narrow - Restore devices to default state
+ * @hd: Pointer to a SCSI HOST structure
+ * @vtarget: per device private data
*
* Uses the ISR, but with special processing.
* MUST be single-threaded.
*
- * Return: 0 on completion
*/
-static int
-mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
+static void
+mptscsih_negotiate_to_asyn_narrow(MPT_SCSI_HOST *hd, VirtTarget *vtarget)
{
MPT_ADAPTER *ioc= hd->ioc;
- VirtDevice *pTarget;
- SCSIDevicePage1_t *pcfg1Data = NULL;
- INTERNAL_CMD iocmd;
+ SCSIDevicePage1_t *pcfg1Data;
CONFIGPARMS cfg;
- dma_addr_t cfg1_dma_addr = -1;
- ConfigPageHeader_t header1;
- int bus = 0;
- int id = 0;
- int lun;
- int indexed_lun, lun_index;
- int hostId = ioc->pfacts[portnum].PortSCSIID;
- int max_id;
- int requested, configuration, data;
- int doConfig = 0;
+ dma_addr_t cfg1_dma_addr;
+ ConfigPageHeader_t header;
+ int id;
+ int requested, configuration, data,i;
u8 flags, factor;
- max_id = ioc->sh->max_id - 1;
-
- /* Following parameters will not change
- * in this routine.
- */
- iocmd.cmd = SYNCHRONIZE_CACHE;
- iocmd.flags = 0;
- iocmd.physDiskNum = -1;
- iocmd.data = NULL;
- iocmd.data_dma = -1;
- iocmd.size = 0;
- iocmd.rsvd = iocmd.rsvd2 = 0;
-
- /* No SCSI hosts
- */
- if (hd->Targets == NULL)
- return 0;
-
- /* Skip the host
- */
- if (id == hostId)
- id++;
-
- /* Write SDP1 for all SCSI devices
- * Alloc memory and set up config buffer
- */
- if (ioc->bus_type == SCSI) {
- if (ioc->spi_data.sdp1length > 0) {
- pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
- ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
-
- if (pcfg1Data != NULL) {
- doConfig = 1;
- header1.PageVersion = ioc->spi_data.sdp1version;
- header1.PageLength = ioc->spi_data.sdp1length;
- header1.PageNumber = 1;
- header1.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
- cfg.cfghdr.hdr = &header1;
- cfg.physAddr = cfg1_dma_addr;
- cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
- cfg.dir = 1;
- cfg.timeout = 0;
- }
- }
- }
+ if (ioc->bus_type != SPI)
+ return;
- /* loop through all devices on this port
- */
- while (bus < MPT_MAX_BUS) {
- iocmd.bus = bus;
- iocmd.id = id;
- pTarget = hd->Targets[(int)id];
+ if (!ioc->spi_data.sdp1length)
+ return;
- if (doConfig) {
+ pcfg1Data = (SCSIDevicePage1_t *)pci_alloc_consistent(ioc->pcidev,
+ ioc->spi_data.sdp1length * 4, &cfg1_dma_addr);
- /* Set the negotiation flags */
- if (pTarget && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
- flags = pTarget->negoFlags;
- } else {
- flags = hd->ioc->spi_data.noQas;
- if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
- data = hd->ioc->spi_data.nvram[id];
+ if (pcfg1Data == NULL)
+ return;
- if (data & MPT_NVRAM_WIDE_DISABLE)
- flags |= MPT_TARGET_NO_NEGO_WIDE;
+ header.PageVersion = ioc->spi_data.sdp1version;
+ header.PageLength = ioc->spi_data.sdp1length;
+ header.PageNumber = 1;
+ header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;
+ cfg.cfghdr.hdr = &header;
+ cfg.physAddr = cfg1_dma_addr;
+ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ cfg.dir = 1;
+ cfg.timeout = 0;
- factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
- if ((factor == 0) || (factor == MPT_ASYNC))
- flags |= MPT_TARGET_NO_NEGO_SYNC;
- }
+ if (vtarget->raidVolume && ioc->raid_data.pIocPg3) {
+ for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+ id = ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID;
+ flags = hd->ioc->spi_data.noQas;
+ if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+ data = hd->ioc->spi_data.nvram[id];
+ if (data & MPT_NVRAM_WIDE_DISABLE)
+ flags |= MPT_TARGET_NO_NEGO_WIDE;
+ factor = (data & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT;
+ if ((factor == 0) || (factor == MPT_ASYNC))
+ flags |= MPT_TARGET_NO_NEGO_SYNC;
}
-
- /* Force to async, narrow */
mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
- &configuration, flags);
+ &configuration, flags);
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 = cpu_to_le32(requested);
pcfg1Data->Reserved = 0;
pcfg1Data->Configuration = cpu_to_le32(configuration);
- cfg.pageAddr = (bus<<8) | id;
+ cfg.pageAddr = (vtarget->bus_id<<8) | id;
mpt_config(hd->ioc, &cfg);
}
+ } else {
+ flags = vtarget->negoFlags;
+ mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
+ &configuration, flags);
+ dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+ "offset=0 negoFlags=%x request=%x config=%x\n",
+ vtarget->target_id, flags, requested, configuration));
+ pcfg1Data->RequestedParameters = cpu_to_le32(requested);
+ pcfg1Data->Reserved = 0;
+ pcfg1Data->Configuration = cpu_to_le32(configuration);
+ cfg.pageAddr = (vtarget->bus_id<<8) | vtarget->target_id;
+ mpt_config(hd->ioc, &cfg);
+ }
- /* If target Ptr NULL or if this target is NOT a disk, skip.
- */
- if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){
- for (lun=0; lun <= MPT_LAST_LUN; lun++) {
- /* If LUN present, issue the command
- */
- lun_index = (lun >> 5); /* 32 luns per lun_index */
- indexed_lun = (lun % 32);
- if (pTarget->luns[lun_index] & (1<<indexed_lun)) {
- iocmd.lun = lun;
- (void) mptscsih_do_cmd(hd, &iocmd);
- }
- }
- }
+ if (pcfg1Data)
+ pci_free_consistent(ioc->pcidev, header.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+}
- /* get next relevant device */
- id++;
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks.
+ * @hd: Pointer to a SCSI HOST structure
+ * @vtarget: per device private data
+ * @lun: lun
+ *
+ * Uses the ISR, but with special processing.
+ * MUST be single-threaded.
+ *
+ */
+static void
+mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
+{
+ INTERNAL_CMD iocmd;
- if (id == hostId)
- id++;
+ /* Following parameters will not change
+ * in this routine.
+ */
+ iocmd.cmd = SYNCHRONIZE_CACHE;
+ iocmd.flags = 0;
+ iocmd.physDiskNum = -1;
+ iocmd.data = NULL;
+ iocmd.data_dma = -1;
+ iocmd.size = 0;
+ iocmd.rsvd = iocmd.rsvd2 = 0;
+ iocmd.bus = vdevice->bus_id;
+ iocmd.id = vdevice->target_id;
+ iocmd.lun = (u8)vdevice->lun;
- if (id > max_id) {
- id = 0;
- bus++;
- }
- }
+ if ((vdevice->vtarget->type & TYPE_DISK) &&
+ (vdevice->configured_lun))
+ mptscsih_do_cmd(hd, &iocmd);
+}
+
+/* Search IOC page 3 to determine if this is hidden physical disk
+ */
+static int
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+{
+ int i;
- if (pcfg1Data) {
- pci_free_consistent(ioc->pcidev, header1.PageLength * 4, pcfg1Data, cfg1_dma_addr);
+ if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
+ return 0;
+
+ for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
+ if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
+ return 1;
}
return 0;
@@ -4101,8 +4039,8 @@ mptscsih_domainValidation(void *arg)
msleep(250);
- /* DV only to SCSI adapters */
- if (ioc->bus_type != SCSI)
+ /* DV only to SPI adapters */
+ if (ioc->bus_type != SPI)
continue;
/* Make sure everything looks ok */
@@ -4205,32 +4143,12 @@ mptscsih_domainValidation(void *arg)
return;
}
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
-static int
-mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
-{
- int i;
-
- if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3)
- return 0;
-
- for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) {
- if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID)
- return 1;
- }
-
- return 0;
-}
-
/* Write SDP1 if no QAS has been enabled
*/
static void
mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
{
- VirtDevice *pTarget;
+ VirtTarget *vtarget;
int ii;
if (hd->Targets == NULL)
@@ -4243,11 +4161,11 @@ mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0)
continue;
- pTarget = hd->Targets[ii];
+ vtarget = hd->Targets[ii];
- if ((pTarget != NULL) && (!pTarget->raidVolume)) {
- if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
- pTarget->negoFlags |= hd->ioc->spi_data.noQas;
+ if ((vtarget != NULL) && (!vtarget->raidVolume)) {
+ if ((vtarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
+ vtarget->negoFlags |= hd->ioc->spi_data.noQas;
dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
mptscsih_writeSDP1(hd, 0, ii, 0);
}
@@ -4287,7 +4205,7 @@ static int
mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
{
MPT_ADAPTER *ioc = hd->ioc;
- VirtDevice *pTarget;
+ VirtTarget *vtarget;
SCSIDevicePage1_t *pcfg1Data;
SCSIDevicePage0_t *pcfg0Data;
u8 *pbuf1;
@@ -4358,12 +4276,12 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
iocmd.physDiskNum = -1;
iocmd.rsvd = iocmd.rsvd2 = 0;
- pTarget = hd->Targets[id];
+ vtarget = hd->Targets[id];
/* Use tagged commands if possible.
*/
- if (pTarget) {
- if (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)
+ if (vtarget) {
+ if (vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
iocmd.flags |= MPT_ICFLAG_TAGGED_CMD;
else {
if (hd->ioc->facts.FWVersion.Word < 0x01000600)
@@ -4579,7 +4497,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
/* Reset the size for disks
*/
inq0 = (*pbuf1) & 0x1F;
- if ((inq0 == 0) && pTarget && !pTarget->raidVolume) {
+ if ((inq0 == 0) && vtarget && !vtarget->raidVolume) {
sz = 0x40;
iocmd.size = sz;
}
@@ -4589,8 +4507,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
*/
if (inq0 == TYPE_PROCESSOR) {
mptscsih_initTarget(hd,
- bus,
- id,
+ vtarget,
lun,
pbuf1,
sz);
@@ -4604,22 +4521,22 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
goto target_done;
if (sz == 0x40) {
- if ((pTarget->maxWidth == 1) && (pTarget->maxOffset) && (nfactor < 0x0A)
- && (pTarget->minSyncFactor > 0x09)) {
+ if ((vtarget->maxWidth == 1) && (vtarget->maxOffset) && (nfactor < 0x0A)
+ && (vtarget->minSyncFactor > 0x09)) {
if ((pbuf1[56] & 0x04) == 0)
;
else if ((pbuf1[56] & 0x01) == 1) {
- pTarget->minSyncFactor =
+ vtarget->minSyncFactor =
nfactor > MPT_ULTRA320 ? nfactor : MPT_ULTRA320;
} else {
- pTarget->minSyncFactor =
+ vtarget->minSyncFactor =
nfactor > MPT_ULTRA160 ? nfactor : MPT_ULTRA160;
}
- dv.max.factor = pTarget->minSyncFactor;
+ dv.max.factor = vtarget->minSyncFactor;
if ((pbuf1[56] & 0x02) == 0) {
- pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+ vtarget->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",
@@ -4702,8 +4619,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
"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,
- bus,
- id,
+ vtarget,
lun,
pbuf1,
sz);
@@ -5204,7 +5120,7 @@ target_done:
static void
mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
{
- VirtDevice *pTarget;
+ VirtTarget *vtarget;
SCSIDevicePage0_t *pPage0;
SCSIDevicePage1_t *pPage1;
int val = 0, data, configuration;
@@ -5224,11 +5140,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
* already throttled back.
*/
negoFlags = hd->ioc->spi_data.noQas;
- if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) {
- width = pTarget->maxWidth;
- offset = pTarget->maxOffset;
- factor = pTarget->minSyncFactor;
- negoFlags |= pTarget->negoFlags;
+ if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume) {
+ width = vtarget->maxWidth;
+ offset = vtarget->maxOffset;
+ factor = vtarget->minSyncFactor;
+ negoFlags |= vtarget->negoFlags;
} else {
if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) {
data = hd->ioc->spi_data.nvram[id];
@@ -5430,11 +5346,11 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
* or overwrite nvram (phys disks only).
*/
- if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume ) {
- pTarget->maxWidth = dv->now.width;
- pTarget->maxOffset = dv->now.offset;
- pTarget->minSyncFactor = dv->now.factor;
- pTarget->negoFlags = dv->now.flags;
+ if ((hd->Targets)&&((vtarget = hd->Targets[(int)id]) != NULL) && !vtarget->raidVolume ) {
+ vtarget->maxWidth = dv->now.width;
+ vtarget->maxOffset = dv->now.offset;
+ vtarget->minSyncFactor = dv->now.factor;
+ vtarget->negoFlags = dv->now.flags;
} else {
/* Preserv all flags, use
* read-modify-write algorithm
@@ -5588,6 +5504,94 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width)
break;
}
}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/* If DV disabled (negoNvram set to USE_NVARM) or if not LUN 0, return.
+ * Else set the NEED_DV flag after Read Capacity Issued (disks)
+ * or Mode Sense (cdroms).
+ *
+ * Tapes, initTarget will set this flag on completion of Inquiry command.
+ * Called only if DV_NOT_DONE flag is set
+ */
+static void
+mptscsih_set_dvflags(MPT_SCSI_HOST *hd, struct scsi_cmnd *sc)
+{
+ MPT_ADAPTER *ioc = hd->ioc;
+ u8 cmd;
+ SpiCfgData *pSpi;
+
+ ddvtprintk((MYIOC_s_NOTE_FMT
+ " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
+ hd->ioc->name, sc->device->id, sc->device->lun , hd->negoNvram, sc->cmnd[0]));
+
+ if ((sc->device->lun != 0) || (hd->negoNvram != 0))
+ return;
+
+ cmd = sc->cmnd[0];
+
+ if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
+ pSpi = &ioc->spi_data;
+ if ((ioc->raid_data.isRaid & (1 << sc->device->id)) && ioc->raid_data.pIocPg3) {
+ /* Set NEED_DV for all hidden disks
+ */
+ Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+
+ while (numPDisk) {
+ pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV;
+ ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID));
+ pPDisk++;
+ numPDisk--;
+ }
+ }
+ pSpi->dvStatus[sc->device->id] |= MPT_SCSICFG_NEED_DV;
+ ddvtprintk(("NEED_DV set for visible disk id %d\n", sc->device->id));
+ }
+}
+
+/* mptscsih_raid_set_dv_flags()
+ *
+ * New or replaced disk. Set DV flag and schedule DV.
+ */
+static void
+mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id)
+{
+ MPT_ADAPTER *ioc = hd->ioc;
+ SpiCfgData *pSpi = &ioc->spi_data;
+ Ioc3PhysDisk_t *pPDisk;
+ int numPDisk;
+
+ if (hd->negoNvram != 0)
+ return;
+
+ ddvtprintk(("DV requested for phys disk id %d\n", id));
+ if (ioc->raid_data.pIocPg3) {
+ pPDisk = ioc->raid_data.pIocPg3->PhysDisk;
+ numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks;
+ while (numPDisk) {
+ if (id == pPDisk->PhysDiskNum) {
+ pSpi->dvStatus[pPDisk->PhysDiskID] =
+ (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE);
+ pSpi->forceDv = MPT_SCSICFG_NEED_DV;
+ ddvtprintk(("NEED_DV set for phys disk id %d\n",
+ pPDisk->PhysDiskID));
+ break;
+ }
+ pPDisk++;
+ numPDisk--;
+ }
+
+ if (numPDisk == 0) {
+ /* The physical disk that needs DV was not found
+ * in the stored IOC Page 3. The driver must reload
+ * this page. DV routine will set the NEED_DV flag for
+ * all phys disks that have DV_NOT_DONE set.
+ */
+ pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
+ ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id));
+ }
+ }
+}
#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
EXPORT_SYMBOL(mptscsih_remove);
@@ -5599,7 +5603,9 @@ EXPORT_SYMBOL(mptscsih_resume);
EXPORT_SYMBOL(mptscsih_proc_info);
EXPORT_SYMBOL(mptscsih_info);
EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_target_alloc);
EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_target_destroy);
EXPORT_SYMBOL(mptscsih_slave_destroy);
EXPORT_SYMBOL(mptscsih_slave_configure);
EXPORT_SYMBOL(mptscsih_abort);
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 971fda4b8b57..d3cba12f4bd9 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -91,7 +91,9 @@ extern int mptscsih_resume(struct pci_dev *pdev);
extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
+extern int mptscsih_target_alloc(struct scsi_target *starget);
extern int mptscsih_slave_alloc(struct scsi_device *device);
+extern void mptscsih_target_destroy(struct scsi_target *starget);
extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 5c0e307d1d5d..7dce29277cb7 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -103,13 +103,16 @@ static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
static struct scsi_host_template mptspi_driver_template = {
+ .module = THIS_MODULE,
.proc_name = "mptspi",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
+ .target_alloc = mptscsih_target_alloc,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
+ .target_destroy = mptscsih_target_destroy,
.slave_destroy = mptscsih_slave_destroy,
.change_queue_depth = mptscsih_change_queue_depth,
.eh_abort_handler = mptscsih_abort,
@@ -155,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
- int sz, ii;
+ int ii;
int numSGE = 0;
int scale;
int ioc_cap;
- u8 *mem;
int error=0;
int r;
@@ -177,13 +179,15 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptspi_probe;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
- return -ENODEV;
+ error = -ENODEV;
+ goto out_mptspi_probe;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
@@ -208,7 +212,8 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
- return -1;
+ error = -1;
+ goto out_mptspi_probe;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
@@ -282,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+ if (!hd->ScsiLookup) {
error = -ENOMEM;
- goto mptspi_probe_failed;
+ goto out_mptspi_probe;
}
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+ ioc->name, hd->ScsiLookup));
/* Allocate memory for the device structures.
* A non-Null pointer at an offset
* indicates a device exists.
* max_id = 1 + maximum id (hosts.h)
*/
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
+ hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+ if (!hd->Targets) {
error = -ENOMEM;
- goto mptspi_probe_failed;
+ goto out_mptspi_probe;
}
- memset(mem, 0, sz);
- hd->Targets = (VirtDevice **) mem;
-
- dprintk((KERN_INFO
- " Targets @ %p, sz=%d\n", hd->Targets, sz));
+ dprintk((KERN_INFO " vdev @ %p\n", hd->Targets));
/* Clear the TM flags
*/
@@ -385,13 +381,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
- goto mptspi_probe_failed;
+ goto out_mptspi_probe;
}
scsi_scan_host(sh);
return 0;
-mptspi_probe_failed:
+out_mptspi_probe:
mptscsih_remove(pdev);
return error;
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 43a942a29c2e..fef677103880 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,6 +24,18 @@ config I2O
If unsure, say N.
+config I2O_LCT_NOTIFY_ON_CHANGES
+ bool "Enable LCT notification"
+ depends on I2O
+ default y
+ ---help---
+ Only say N here if you have a I2O controller from SUN. The SUN
+ firmware doesn't support LCT notification on changes. If this option
+ is enabled on such a controller the driver will hang up in a endless
+ loop. On all other controllers say Y.
+
+ If unsure, say Y.
+
config I2O_EXT_ADAPTEC
bool "Enable Adaptec extensions"
depends on I2O
diff --git a/drivers/message/i2o/README.ioctl b/drivers/message/i2o/README.ioctl
index 73dd084c0e98..65c0c47aeb79 100644
--- a/drivers/message/i2o/README.ioctl
+++ b/drivers/message/i2o/README.ioctl
@@ -185,7 +185,7 @@ VII. Getting Parameters
ENOMEM Kernel memory allocation error
A return value of 0 does not mean that the value was actually
- properly retreived. The user should check the result list
+ properly retrieved. The user should check the result list
to determine the specific status of the transaction.
VIII. Downloading Software
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
index 151b228e1cb3..ac06f10c54ec 100644
--- a/drivers/message/i2o/bus-osm.c
+++ b/drivers/message/i2o/bus-osm.c
@@ -17,7 +17,7 @@
#include <linux/i2o.h>
#define OSM_NAME "bus-osm"
-#define OSM_VERSION "$Rev$"
+#define OSM_VERSION "1.317"
#define OSM_DESCRIPTION "I2O Bus Adapter OSM"
static struct i2o_driver i2o_bus_driver;
@@ -39,18 +39,18 @@ static struct i2o_class_id i2o_bus_class_id[] = {
*/
static int i2o_bus_scan(struct i2o_device *dev)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
return -ETIMEDOUT;
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.
+ tid);
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
};
/**
@@ -59,8 +59,9 @@ static int i2o_bus_scan(struct i2o_device *dev)
*
* Returns count.
*/
-static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
- size_t count)
+static ssize_t i2o_bus_store_scan(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2o_device *i2o_dev = to_i2o_device(d);
int rc;
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
index 10432f665201..3bba7aa82e58 100644
--- a/drivers/message/i2o/config-osm.c
+++ b/drivers/message/i2o/config-osm.c
@@ -22,7 +22,7 @@
#include <asm/uaccess.h>
#define OSM_NAME "config-osm"
-#define OSM_VERSION "1.248"
+#define OSM_VERSION "1.323"
#define OSM_DESCRIPTION "I2O Configuration OSM"
/* access mode user rw */
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
index 9eefedb16211..90628562851e 100644
--- a/drivers/message/i2o/core.h
+++ b/drivers/message/i2o/core.h
@@ -14,8 +14,6 @@
*/
/* Exec-OSM */
-extern struct bus_type i2o_bus_type;
-
extern struct i2o_driver i2o_exec_driver;
extern int i2o_exec_lct_get(struct i2o_controller *);
@@ -23,6 +21,8 @@ extern int __init i2o_exec_init(void);
extern void __exit i2o_exec_exit(void);
/* driver */
+extern struct bus_type i2o_bus_type;
+
extern int i2o_driver_dispatch(struct i2o_controller *, u32);
extern int __init i2o_driver_init(void);
@@ -33,19 +33,27 @@ extern int __init i2o_pci_init(void);
extern void __exit i2o_pci_exit(void);
/* device */
+extern struct device_attribute i2o_device_attrs[];
+
extern void i2o_device_remove(struct i2o_device *);
extern int i2o_device_parse_lct(struct i2o_controller *);
/* IOP */
extern struct i2o_controller *i2o_iop_alloc(void);
-extern void i2o_iop_free(struct i2o_controller *);
+
+/**
+ * i2o_iop_free - Free the i2o_controller struct
+ * @c: I2O controller to free
+ */
+static inline void i2o_iop_free(struct i2o_controller *c)
+{
+ i2o_pool_free(&c->in_msg);
+ kfree(c);
+}
extern int i2o_iop_add(struct i2o_controller *);
extern void i2o_iop_remove(struct i2o_controller *);
-/* config */
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
-
/* control registers relative to c->base */
#define I2O_IRQ_STATUS 0x30
#define I2O_IRQ_MASK 0x34
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 8eb50cdb8ae1..ee183053fa23 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -35,18 +35,18 @@
static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
u32 type)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]);
- writel(type, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid);
+ msg->body[0] = cpu_to_le32(type);
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
}
/**
@@ -123,7 +123,6 @@ int i2o_device_claim_release(struct i2o_device *dev)
return rc;
}
-
/**
* i2o_device_release - release the memory for a I2O device
* @dev: I2O device which should be released
@@ -140,10 +139,10 @@ static void i2o_device_release(struct device *dev)
kfree(i2o_dev);
}
-
/**
- * i2o_device_class_show_class_id - Displays class id of I2O device
- * @cd: class device of which the class id should be displayed
+ * i2o_device_show_class_id - Displays class id of I2O device
+ * @dev: device of which the class id should be displayed
+ * @attr: pointer to device attribute
* @buf: buffer into which the class id should be printed
*
* Returns the number of bytes which are printed into the buffer.
@@ -159,15 +158,15 @@ static ssize_t i2o_device_show_class_id(struct device *dev,
}
/**
- * i2o_device_class_show_tid - Displays TID of I2O device
- * @cd: class device of which the TID should be displayed
- * @buf: buffer into which the class id should be printed
+ * i2o_device_show_tid - Displays TID of I2O device
+ * @dev: device of which the TID should be displayed
+ * @attr: pointer to device attribute
+ * @buf: buffer into which the TID should be printed
*
* Returns the number of bytes which are printed into the buffer.
*/
static ssize_t i2o_device_show_tid(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr, char *buf)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
@@ -175,6 +174,7 @@ static ssize_t i2o_device_show_tid(struct device *dev,
return strlen(buf) + 1;
}
+/* I2O device attributes */
struct device_attribute i2o_device_attrs[] = {
__ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL),
__ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL),
@@ -193,12 +193,10 @@ static struct i2o_device *i2o_device_alloc(void)
{
struct i2o_device *dev;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
- memset(dev, 0, sizeof(*dev));
-
INIT_LIST_HEAD(&dev->list);
init_MUTEX(&dev->lock);
@@ -209,66 +207,6 @@ static struct i2o_device *i2o_device_alloc(void)
}
/**
- * i2o_setup_sysfs_links - Adds attributes to the I2O device
- * @cd: I2O class device which is added to the I2O device class
- *
- * This function get called when a I2O device is added to the class. It
- * creates the attributes for each device and creates user/parent symlink
- * if necessary.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev)
-{
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_device *tmp;
-
- /* create user entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && tmp != i2o_dev)
- sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "user");
-
- /* create user entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid &&
- tmp != i2o_dev)
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
-
- /* create parent entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && tmp != i2o_dev)
- sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "parent");
-
- /* create parent entries refering to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid &&
- tmp != i2o_dev)
- sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
-}
-
-static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
-{
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_device *tmp;
-
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
-
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- }
-}
-
-
-
-/**
* i2o_device_add - allocate a new I2O device and add it to the IOP
* @iop: I2O controller where the device is on
* @entry: LCT entry of the I2O device
@@ -282,33 +220,57 @@ static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev)
static struct i2o_device *i2o_device_add(struct i2o_controller *c,
i2o_lct_entry * entry)
{
- struct i2o_device *dev;
+ struct i2o_device *i2o_dev, *tmp;
- dev = i2o_device_alloc();
- if (IS_ERR(dev)) {
+ i2o_dev = i2o_device_alloc();
+ if (IS_ERR(i2o_dev)) {
printk(KERN_ERR "i2o: unable to allocate i2o device\n");
- return dev;
+ return i2o_dev;
}
- dev->lct_data = *entry;
- dev->iop = c;
+ i2o_dev->lct_data = *entry;
- snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
- dev->lct_data.tid);
+ snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
+ i2o_dev->lct_data.tid);
- dev->device.parent = &c->device;
+ i2o_dev->iop = c;
+ i2o_dev->device.parent = &c->device;
- device_register(&dev->device);
+ device_register(&i2o_dev->device);
- list_add_tail(&dev->list, &c->devices);
+ list_add_tail(&i2o_dev->list, &c->devices);
- i2o_setup_sysfs_links(dev);
+ /* create user entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
+ if (tmp && (tmp != i2o_dev))
+ sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+ "user");
- i2o_driver_notify_device_add_all(dev);
+ /* create user entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "user");
- pr_debug("i2o: device %s added\n", dev->device.bus_id);
+ /* create parent entries for this device */
+ tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
+ if (tmp && (tmp != i2o_dev))
+ sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
+ "parent");
- return dev;
+ /* create parent entries refering to this device */
+ list_for_each_entry(tmp, &c->devices, list)
+ if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
+ sysfs_create_link(&tmp->device.kobj,
+ &i2o_dev->device.kobj, "parent");
+
+ i2o_driver_notify_device_add_all(i2o_dev);
+
+ pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id);
+
+ return i2o_dev;
}
/**
@@ -321,9 +283,22 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c,
*/
void i2o_device_remove(struct i2o_device *i2o_dev)
{
+ struct i2o_device *tmp;
+ struct i2o_controller *c = i2o_dev->iop;
+
i2o_driver_notify_device_remove_all(i2o_dev);
- i2o_remove_sysfs_links(i2o_dev);
+
+ sysfs_remove_link(&i2o_dev->device.kobj, "parent");
+ sysfs_remove_link(&i2o_dev->device.kobj, "user");
+
+ list_for_each_entry(tmp, &c->devices, list) {
+ if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "parent");
+ if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ sysfs_remove_link(&tmp->device.kobj, "user");
+ }
list_del(&i2o_dev->list);
+
device_unregister(&i2o_dev->device);
}
@@ -341,56 +316,83 @@ int i2o_device_parse_lct(struct i2o_controller *c)
{
struct i2o_device *dev, *tmp;
i2o_lct *lct;
- int i;
- int max;
+ u32 *dlct = c->dlct.virt;
+ int max = 0, i = 0;
+ u16 table_size;
+ u32 buf;
down(&c->lct_lock);
kfree(c->lct);
- lct = c->dlct.virt;
+ buf = le32_to_cpu(*dlct++);
+ table_size = buf & 0xffff;
- c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL);
- if (!c->lct) {
+ lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
+ if (!lct) {
up(&c->lct_lock);
return -ENOMEM;
}
- if (lct->table_size * 4 > c->dlct.len) {
- memcpy(c->lct, c->dlct.virt, c->dlct.len);
- up(&c->lct_lock);
- return -EAGAIN;
- }
+ lct->lct_ver = buf >> 28;
+ lct->boot_tid = buf >> 16 & 0xfff;
+ lct->table_size = table_size;
+ lct->change_ind = le32_to_cpu(*dlct++);
+ lct->iop_flags = le32_to_cpu(*dlct++);
- memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
-
- lct = c->lct;
-
- max = (lct->table_size - 3) / 9;
+ table_size -= 3;
pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max,
lct->table_size);
- /* remove devices, which are not in the LCT anymore */
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ while (table_size > 0) {
+ i2o_lct_entry *entry = &lct->lct_entry[max];
int found = 0;
- for (i = 0; i < max; i++) {
- if (lct->lct_entry[i].tid == dev->lct_data.tid) {
+ buf = le32_to_cpu(*dlct++);
+ entry->entry_size = buf & 0xffff;
+ entry->tid = buf >> 16 & 0xfff;
+
+ entry->change_ind = le32_to_cpu(*dlct++);
+ entry->device_flags = le32_to_cpu(*dlct++);
+
+ buf = le32_to_cpu(*dlct++);
+ entry->class_id = buf & 0xfff;
+ entry->version = buf >> 12 & 0xf;
+ entry->vendor_id = buf >> 16;
+
+ entry->sub_class = le32_to_cpu(*dlct++);
+
+ buf = le32_to_cpu(*dlct++);
+ entry->user_tid = buf & 0xfff;
+ entry->parent_tid = buf >> 12 & 0xfff;
+ entry->bios_info = buf >> 24;
+
+ memcpy(&entry->identity_tag, dlct, 8);
+ dlct += 2;
+
+ entry->event_capabilities = le32_to_cpu(*dlct++);
+
+ /* add new devices, which are new in the LCT */
+ list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ if (entry->tid == dev->lct_data.tid) {
found = 1;
break;
}
}
if (!found)
- i2o_device_remove(dev);
+ i2o_device_add(c, entry);
+
+ table_size -= 9;
+ max++;
}
- /* add new devices, which are new in the LCT */
- for (i = 0; i < max; i++) {
+ /* remove devices, which are not in the LCT anymore */
+ list_for_each_entry_safe(dev, tmp, &c->devices, list) {
int found = 0;
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
+ for (i = 0; i < max; i++) {
if (lct->lct_entry[i].tid == dev->lct_data.tid) {
found = 1;
break;
@@ -398,14 +400,14 @@ int i2o_device_parse_lct(struct i2o_controller *c)
}
if (!found)
- i2o_device_add(c, &lct->lct_entry[i]);
+ i2o_device_remove(dev);
}
+
up(&c->lct_lock);
return 0;
}
-
/*
* Run time support routines
*/
@@ -419,13 +421,9 @@ int i2o_device_parse_lct(struct i2o_controller *c)
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
*/
int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen)
+ int oplen, void *reslist, int reslen)
{
- struct i2o_message __iomem *msg;
- u32 m;
- u32 *res32 = (u32 *) reslist;
- u32 *restmp = (u32 *) reslist;
- int len = 0;
+ struct i2o_message *msg;
int i = 0;
int rc;
struct i2o_dma res;
@@ -437,26 +435,27 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL))
return -ENOMEM;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY) {
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg)) {
i2o_dma_free(dev, &res);
- return -ETIMEDOUT;
+ return PTR_ERR(msg);
}
i = 0;
- writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid,
- &msg->u.head[1]);
- writel(0, &msg->body[i++]);
- writel(0x4C000000 | oplen, &msg->body[i++]); /* OperationList */
- memcpy_toio(&msg->body[i], oplist, oplen);
+ msg->u.head[1] =
+ cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid);
+ msg->body[i++] = cpu_to_le32(0x00000000);
+ msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */
+ memcpy(&msg->body[i], oplist, oplen);
i += (oplen / 4 + (oplen % 4 ? 1 : 0));
- writel(0xD0000000 | res.len, &msg->body[i++]); /* ResultList */
- writel(res.phys, &msg->body[i++]);
+ msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */
+ msg->body[i++] = cpu_to_le32(res.phys);
- writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
- SGL_OFFSET_5, &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
+ SGL_OFFSET_5);
- rc = i2o_msg_post_wait_mem(c, m, 10, &res);
+ rc = i2o_msg_post_wait_mem(c, msg, 10, &res);
/* This only looks like a memory leak - don't "fix" it. */
if (rc == -ETIMEDOUT)
@@ -465,36 +464,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
memcpy(reslist, res.virt, res.len);
i2o_dma_free(dev, &res);
- /* Query failed */
- if (rc)
- return rc;
- /*
- * Calculate number of bytes of Result LIST
- * We need to loop through each Result BLOCK and grab the length
- */
- restmp = res32 + 1;
- len = 1;
- for (i = 0; i < (res32[0] & 0X0000FFFF); i++) {
- if (restmp[0] & 0x00FF0000) { /* BlockStatus != SUCCESS */
- printk(KERN_WARNING
- "%s - Error:\n ErrorInfoSize = 0x%02x, "
- "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
- (cmd ==
- I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" :
- "PARAMS_GET", res32[1] >> 24,
- (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF);
-
- /*
- * If this is the only request,than we return an error
- */
- if ((res32[0] & 0x0000FFFF) == 1) {
- return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */
- }
- }
- len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */
- restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */
- }
- return (len << 2); /* bytes used by result list */
+ return rc;
}
/*
@@ -503,28 +473,25 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
void *buf, int buflen)
{
- u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
+ u32 opblk[] = { cpu_to_le32(0x00000001),
+ cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET),
+ cpu_to_le32((s16) field << 16 | 0x00000001)
+ };
u8 *resblk; /* 8 bytes for header */
- int size;
-
- if (field == -1) /* whole group */
- opblk[4] = -1;
+ int rc;
resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
if (!resblk)
return -ENOMEM;
- size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- sizeof(opblk), resblk, buflen + 8);
+ rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
+ sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */
kfree(resblk);
- if (size > buflen)
- return buflen;
-
- return size;
+ return rc;
}
/*
@@ -534,12 +501,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
* else return specific fields
* ibuf contains fieldindexes
*
- * if oper == I2O_PARAMS_LIST_GET, get from specific rows
- * if fieldcount == -1 return all fields
+ * if oper == I2O_PARAMS_LIST_GET, get from specific rows
+ * if fieldcount == -1 return all fields
* ibuf contains rowcount, keyvalues
- * else return specific fields
+ * else return specific fields
* fieldcount is # of fieldindexes
- * ibuf contains fieldindexes, rowcount, keyvalues
+ * ibuf contains fieldindexes, rowcount, keyvalues
*
* You could also use directly function i2o_issue_params().
*/
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 0fb9c4e2ad4c..64130227574f 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -61,12 +61,10 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv)
};
/* I2O bus type */
-extern struct device_attribute i2o_device_attrs[];
-
struct bus_type i2o_bus_type = {
.name = "i2o",
.match = i2o_bus_match,
- .dev_attrs = i2o_device_attrs,
+ .dev_attrs = i2o_device_attrs
};
/**
@@ -219,14 +217,14 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
/* cut of header from message size (in 32-bit words) */
size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
- evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
+ evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
if (!evt)
return -ENOMEM;
evt->size = size;
evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
evt->event_indicator = le32_to_cpu(msg->body[0]);
- memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
+ memcpy(&evt->data, &msg->body[1], size * 4);
list_for_each_entry_safe(dev, tmp, &c->devices, list)
if (dev->lct_data.tid == tid) {
@@ -349,12 +347,10 @@ int __init i2o_driver_init(void)
osm_info("max drivers = %d\n", i2o_max_drivers);
i2o_drivers =
- kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+ kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
if (!i2o_drivers)
return -ENOMEM;
- memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers));
-
rc = bus_register(&i2o_bus_type);
if (rc < 0)
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 9c339a2505b0..9bb9859f6dfe 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -33,7 +33,7 @@
#include <linux/workqueue.h>
#include <linux/string.h>
#include <linux/slab.h>
-#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
+#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
#include <asm/param.h> /* HZ */
#include "core.h"
@@ -75,11 +75,9 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
{
struct i2o_exec_wait *wait;
- wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+ wait = kzalloc(sizeof(*wait), GFP_KERNEL);
if (!wait)
- return ERR_PTR(-ENOMEM);
-
- memset(wait, 0, sizeof(*wait));
+ return NULL;
INIT_LIST_HEAD(&wait->list);
@@ -114,13 +112,12 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
* Returns 0 on success, negative error code on timeout or positive error
* code from reply.
*/
-int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
- timeout, struct i2o_dma *dma)
+int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
+ unsigned long timeout, struct i2o_dma *dma)
{
DECLARE_WAIT_QUEUE_HEAD(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
- struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
int rc = 0;
wait = i2o_exec_wait_alloc();
@@ -138,15 +135,15 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* We will only use transaction contexts >= 0x80000000 for POST WAIT,
* so we could find a POST WAIT reply easier in the reply handler.
*/
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
wait->tcntxt = tcntxt++;
- writel(wait->tcntxt, &msg->u.s.tcntxt);
+ msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
/*
* Post the message to the controller. At some point later it will
* return. If we time out before it returns then complete will be zero.
*/
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
if (!wait->complete) {
wait->wq = &wq;
@@ -266,13 +263,14 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
*
* Returns number of bytes printed into buffer.
*/
-static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_vendor_id(struct device *d,
+ struct device_attribute *attr, char *buf)
{
struct i2o_device *dev = to_i2o_device(d);
u16 id;
- if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
- sprintf(buf, "0x%04x", id);
+ if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
+ sprintf(buf, "0x%04x", le16_to_cpu(id));
return strlen(buf) + 1;
}
@@ -286,13 +284,15 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute
*
* Returns number of bytes printed into buffer.
*/
-static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
+static ssize_t i2o_exec_show_product_id(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
{
struct i2o_device *dev = to_i2o_device(d);
u16 id;
- if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
- sprintf(buf, "0x%04x", id);
+ if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
+ sprintf(buf, "0x%04x", le16_to_cpu(id));
return strlen(buf) + 1;
}
@@ -362,7 +362,9 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
if (i2o_device_parse_lct(c) != -EAGAIN)
change_ind = c->lct->change_ind + 1;
+#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
i2o_exec_lct_notify(c, change_ind);
+#endif
};
/**
@@ -385,23 +387,22 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
u32 context;
if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
+ struct i2o_message __iomem *pmsg;
+ u32 pm;
+
/*
* If Fail bit is set we must take the transaction context of
* the preserved message to find the right request again.
*/
- struct i2o_message __iomem *pmsg;
- u32 pm;
pm = le32_to_cpu(msg->body[3]);
-
pmsg = i2o_msg_in_to_virt(c, pm);
+ context = readl(&pmsg->u.s.tcntxt);
i2o_report_status(KERN_INFO, "i2o_core", msg);
- context = readl(&pmsg->u.s.tcntxt);
-
/* Release the preserved msg */
- i2o_msg_nop(c, pm);
+ i2o_msg_nop_mfa(c, pm);
} else
context = le32_to_cpu(msg->u.s.tcntxt);
@@ -462,25 +463,26 @@ static void i2o_exec_event(struct i2o_event *evt)
*/
int i2o_exec_lct_get(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int i = 0;
int rc = -EAGAIN;
for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0xffffffff, &msg->body[0]);
- writel(0x00000000, &msg->body[1]);
- writel(0xd0000000 | c->dlct.len, &msg->body[2]);
- writel(c->dlct.phys, &msg->body[3]);
-
- rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] =
+ cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->body[0] = cpu_to_le32(0xffffffff);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+ msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+ rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET);
if (rc < 0)
break;
@@ -506,29 +508,29 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
{
i2o_status_block *sb = c->status_block.virt;
struct device *dev;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
dev = &c->pdev->dev;
- if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL))
+ if (i2o_dma_realloc
+ (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL))
return -ENOMEM;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); /* FIXME */
- writel(0xffffffff, &msg->body[0]);
- writel(change_ind, &msg->body[1]);
- writel(0xd0000000 | c->dlct.len, &msg->body[2]);
- writel(c->dlct.phys, &msg->body[3]);
-
- i2o_msg_post(c, m);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0xffffffff);
+ msg->body[1] = cpu_to_le32(change_ind);
+ msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
+ msg->body[3] = cpu_to_le32(c->dlct.phys);
+
+ i2o_msg_post(c, msg);
return 0;
};
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index f283b5bafdd3..b09fb6307153 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -59,10 +59,12 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
+#include <scsi/scsi.h>
+
#include "i2o_block.h"
#define OSM_NAME "block-osm"
-#define OSM_VERSION "1.287"
+#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O Block Device OSM"
static struct i2o_driver i2o_block_driver;
@@ -130,20 +132,20 @@ static int i2o_block_remove(struct device *dev)
*/
static int i2o_block_device_flush(struct i2o_device *dev)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(60 << 16, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(60 << 16);
osm_debug("Flushing...\n");
- return i2o_msg_post_wait(dev->iop, m, 60);
+ return i2o_msg_post_wait(dev->iop, msg, 60);
};
/**
@@ -181,21 +183,21 @@ static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
*/
static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
-
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(-1, &msg->body[0]);
- writel(0, &msg->body[1]);
+ struct i2o_message *msg;
+
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(-1);
+ msg->body[1] = cpu_to_le32(0x00000000);
osm_debug("Mounting...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -210,20 +212,20 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
*/
static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg) == I2O_QUEUE_EMPTY)
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(-1, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(-1);
osm_debug("Locking...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -238,20 +240,20 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
*/
static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
- &msg->u.head[1]);
- writel(media_id, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(media_id);
osm_debug("Unlocking...\n");
- return i2o_msg_post_wait(dev->iop, m, 2);
+ return i2o_msg_post_wait(dev->iop, msg, 2);
};
/**
@@ -267,21 +269,21 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
{
struct i2o_device *i2o_dev = dev->i2o_dev;
struct i2o_controller *c = i2o_dev->iop;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int rc;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
- tid, &msg->u.head[1]);
- writel(op << 24, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->
+ lct_data.tid);
+ msg->body[0] = cpu_to_le32(op << 24);
osm_debug("Power...\n");
- rc = i2o_msg_post_wait(c, m, 60);
+ rc = i2o_msg_post_wait(c, msg, 60);
if (!rc)
dev->power = op;
@@ -331,7 +333,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
*/
static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
struct i2o_block_request *ireq,
- u32 __iomem ** mptr)
+ u32 ** mptr)
{
int nents;
enum dma_data_direction direction;
@@ -466,7 +468,7 @@ static void i2o_block_end_request(struct request *req, int uptodate,
spin_lock_irqsave(q->queue_lock, flags);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
if (likely(dev)) {
dev->open_queue_depth--;
@@ -660,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file)
return 0;
}
+static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ i2o_block_biosparam(get_capacity(bdev->bd_disk),
+ &geo->cylinders, &geo->heads, &geo->sectors);
+ return 0;
+}
+
/**
* i2o_block_ioctl - Issue device specific ioctl calls.
* @cmd: ioctl command
@@ -674,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct i2o_block_device *dev = disk->private_data;
- void __user *argp = (void __user *)arg;
/* Anyone capable of this syscall can do *real bad* things */
@@ -682,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file,
return -EPERM;
switch (cmd) {
- case HDIO_GETGEO:
- {
- struct hd_geometry g;
- i2o_block_biosparam(get_capacity(disk),
- &g.cylinders, &g.heads, &g.sectors);
- g.start = get_start_sect(inode->i_bdev);
- return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
- }
-
case BLKI2OGRSTRAT:
return put_user(dev->rcache, (int __user *)arg);
case BLKI2OGWSTRAT:
@@ -745,10 +744,9 @@ static int i2o_block_transfer(struct request *req)
struct i2o_block_device *dev = req->rq_disk->private_data;
struct i2o_controller *c;
int tid = dev->i2o_dev->lct_data.tid;
- struct i2o_message __iomem *msg;
- u32 __iomem *mptr;
+ struct i2o_message *msg;
+ u32 *mptr;
struct i2o_block_request *ireq = req->special;
- u32 m;
u32 tcntxt;
u32 sgl_offset = SGL_OFFSET_8;
u32 ctl_flags = 0x00000000;
@@ -763,9 +761,9 @@ static int i2o_block_transfer(struct request *req)
c = dev->i2o_dev->iop;
- m = i2o_msg_get(c, &msg);
- if (m == I2O_QUEUE_EMPTY) {
- rc = -EBUSY;
+ msg = i2o_msg_get(c);
+ if (IS_ERR(msg)) {
+ rc = PTR_ERR(msg);
goto exit;
}
@@ -775,8 +773,8 @@ static int i2o_block_transfer(struct request *req)
goto nop_msg;
}
- writel(i2o_block_driver.context, &msg->u.s.icntxt);
- writel(tcntxt, &msg->u.s.tcntxt);
+ msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(tcntxt);
mptr = &msg->body[0];
@@ -834,11 +832,11 @@ static int i2o_block_transfer(struct request *req)
sgl_offset = SGL_OFFSET_12;
- writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid);
- writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
- writel(tid, mptr++);
+ *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+ *mptr++ = cpu_to_le32(tid);
/*
* ENABLE_DISCONNECT
@@ -846,29 +844,31 @@ static int i2o_block_transfer(struct request *req)
* RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
*/
if (rq_data_dir(req) == READ) {
- cmd[0] = 0x28;
+ cmd[0] = READ_10;
scsi_flags = 0x60a0000a;
} else {
- cmd[0] = 0x2A;
+ cmd[0] = WRITE_10;
scsi_flags = 0xa0a0000a;
}
- writel(scsi_flags, mptr++);
+ *mptr++ = cpu_to_le32(scsi_flags);
*((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
*((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
- memcpy_toio(mptr, cmd, 10);
+ memcpy(mptr, cmd, 10);
mptr += 4;
- writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+ *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
} else
#endif
{
- writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
- writel(ctl_flags, mptr++);
- writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
- writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
- writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
+ msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+ *mptr++ = cpu_to_le32(ctl_flags);
+ *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT);
+ *mptr++ =
+ cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT));
+ *mptr++ =
+ cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT));
}
if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
@@ -876,13 +876,13 @@ static int i2o_block_transfer(struct request *req)
goto context_remove;
}
- writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
- sgl_offset, &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
list_add_tail(&ireq->queue, &dev->open_queue);
dev->open_queue_depth++;
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
@@ -890,7 +890,7 @@ static int i2o_block_transfer(struct request *req)
i2o_cntxt_list_remove(c, req);
nop_msg:
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
exit:
return rc;
@@ -959,6 +959,7 @@ static struct block_device_operations i2o_block_fops = {
.open = i2o_block_open,
.release = i2o_block_release,
.ioctl = i2o_block_ioctl,
+ .getgeo = i2o_block_getgeo,
.media_changed = i2o_block_media_changed
};
@@ -978,13 +979,12 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
struct request_queue *queue;
int rc;
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
osm_err("Insufficient memory to allocate I2O Block disk.\n");
rc = -ENOMEM;
goto exit;
}
- memset(dev, 0, sizeof(*dev));
INIT_LIST_HEAD(&dev->open_queue);
spin_lock_init(&dev->lock);
@@ -1049,8 +1049,8 @@ static int i2o_block_probe(struct device *dev)
int rc;
u64 size;
u32 blocksize;
- u32 flags, status;
u16 body_size = 4;
+ u16 power;
unsigned short max_sectors;
#ifdef CONFIG_I2O_EXT_ADAPTEC
@@ -1108,22 +1108,20 @@ static int i2o_block_probe(struct device *dev)
* Ask for the current media data. If that isn't supported
* then we ask for the device capacity data
*/
- if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
- i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
- blk_queue_hardsect_size(queue, blocksize);
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
+ !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+ blk_queue_hardsect_size(queue, le32_to_cpu(blocksize));
} else
osm_warn("unable to get blocksize of %s\n", gd->disk_name);
- if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
- i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
- set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
+ if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
+ !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+ set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT);
} else
osm_warn("could not get size of %s\n", gd->disk_name);
- if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
- i2o_blk_dev->power = 0;
- i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
- i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
+ i2o_blk_dev->power = power;
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 3c3a7abebb1b..89daf67b764d 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -36,12 +36,12 @@
#include <asm/uaccess.h>
-#include "core.h"
-
#define SG_TABLESIZE 30
-static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
- unsigned long arg);
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
+static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
static spinlock_t i2o_config_lock;
@@ -230,8 +230,7 @@ static int i2o_cfg_swdl(unsigned long arg)
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
@@ -257,31 +256,34 @@ static int i2o_cfg_swdl(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
__copy_from_user(buffer.virt, kxfer.buf, fragsize);
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
- (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer.
+ sw_type) << 16) |
+ (((u32) maxfrag) << 8) | (((u32) curfrag)));
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != -ETIMEDOUT)
i2o_dma_free(&c->pdev->dev, &buffer);
@@ -302,8 +304,7 @@ static int i2o_cfg_swul(unsigned long arg)
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
unsigned char maxfrag = 0, curfrag = 1;
struct i2o_dma buffer;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int status = 0, swlen = 0, fragsize = 8192;
struct i2o_controller *c;
int ret = 0;
@@ -330,30 +331,30 @@ static int i2o_cfg_swul(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
- writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.
- sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
- writel(0xD0000000 | fragsize, &msg->body[3]);
- writel(buffer.phys, &msg->body[4]);
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.
+ sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
+ msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
+ msg->body[4] = cpu_to_le32(buffer.phys);
osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+ status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
if (status != I2O_POST_WAIT_OK) {
if (status != -ETIMEDOUT)
@@ -380,8 +381,7 @@ static int i2o_cfg_swdel(unsigned long arg)
struct i2o_controller *c;
struct i2o_sw_xfer kxfer;
struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int swlen;
int token;
@@ -395,21 +395,21 @@ static int i2o_cfg_swdel(unsigned long arg)
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
- &msg->body[0]);
- writel(swlen, &msg->body[1]);
- writel(kxfer.sw_id, &msg->body[2]);
+ msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
+ msg->body[0] =
+ cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16);
+ msg->body[1] = cpu_to_le32(swlen);
+ msg->body[2] = cpu_to_le32(kxfer.sw_id);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
osm_info("swdel failed, DetailedStatus = %d\n", token);
@@ -423,25 +423,24 @@ static int i2o_cfg_validate(unsigned long arg)
{
int token;
int iop = (int)arg;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
struct i2o_controller *c;
c = i2o_find_iop(iop);
if (!c)
return -ENXIO;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(0);
- token = i2o_msg_post_wait(c, m, 10);
+ token = i2o_msg_post_wait(c, msg, 10);
if (token != I2O_POST_WAIT_OK) {
osm_info("Can't validate configuration, ErrorStatus = %d\n",
@@ -454,8 +453,7 @@ static int i2o_cfg_validate(unsigned long arg)
static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
struct i2o_evt_id kdesc;
struct i2o_controller *c;
@@ -474,18 +472,19 @@ static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
if (!d)
return -ENODEV;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -EBUSY;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
- &msg->u.head[1]);
- writel(i2o_config_driver.context, &msg->u.head[2]);
- writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
- writel(kdesc.evt_mask, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 |
+ kdesc.tid);
+ msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
+ msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data));
+ msg->body[0] = cpu_to_le32(kdesc.evt_mask);
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
}
@@ -537,7 +536,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
u32 sg_index = 0;
i2o_status_block *sb;
struct i2o_message *msg;
- u32 m;
unsigned int iop;
cmd = (struct i2o_cmd_passthru32 __user *)arg;
@@ -553,7 +551,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
@@ -585,19 +583,15 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
@@ -631,7 +625,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
goto cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[sg_index++]);
+ p = &(sg_list[sg_index]);
/* Allocate memory for the transfer */
if (i2o_dma_alloc
(&c->pdev->dev, p, sg_size,
@@ -642,6 +636,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
rcode = -ENOMEM;
goto sg_list_cleanup;
}
+ sg_index++;
/* Copy in the user's SG buffer if necessary */
if (sg[i].
flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
@@ -662,9 +657,11 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
+ }
if (sg_offset) {
u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
@@ -714,6 +711,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -731,7 +729,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
}
}
- sg_list_cleanup:
for (i = 0; i < sg_index; i++)
i2o_dma_free(&c->pdev->dev, &sg_list[i]);
@@ -780,8 +777,7 @@ static int i2o_cfg_passthru(unsigned long arg)
u32 i = 0;
void *p = NULL;
i2o_status_block *sb;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned int iop;
if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
@@ -793,7 +789,7 @@ static int i2o_cfg_passthru(unsigned long arg)
return -ENXIO;
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
sb = c->status_block.virt;
@@ -820,19 +816,15 @@ static int i2o_cfg_passthru(unsigned long arg)
reply_size >>= 16;
reply_size <<= 2;
- reply = kmalloc(reply_size, GFP_KERNEL);
+ reply = kzalloc(reply_size, GFP_KERNEL);
if (!reply) {
printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
c->name);
return -ENOMEM;
}
- memset(reply, 0, reply_size);
sg_offset = (msg->u.head[0] >> 4) & 0x0f;
- writel(i2o_config_driver.context, &msg->u.s.icntxt);
- writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
-
memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
if (sg_offset) {
struct sg_simple_element *sg;
@@ -894,9 +886,11 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
- rcode = i2o_msg_post_wait(c, m, 60);
- if (rcode)
+ rcode = i2o_msg_post_wait(c, msg, 60);
+ if (rcode) {
+ reply[4] = ((u32) rcode) << 24;
goto sg_list_cleanup;
+ }
if (sg_offset) {
u32 msg[128];
@@ -946,6 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
+ sg_list_cleanup:
/* Copy back the reply to user space */
if (reply_size) {
// we wrote our own values for context - now restore the user supplied ones
@@ -962,7 +957,6 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
- sg_list_cleanup:
for (i = 0; i < sg_index; i++)
kfree(sg_list[i]);
diff --git a/drivers/message/i2o/i2o_lan.h b/drivers/message/i2o/i2o_lan.h
index 561d63304d7e..6502b817df58 100644
--- a/drivers/message/i2o/i2o_lan.h
+++ b/drivers/message/i2o/i2o_lan.h
@@ -103,14 +103,14 @@
#define I2O_LAN_DSC_SUSPENDED 0x11
struct i2o_packet_info {
- u32 offset : 24;
- u32 flags : 8;
- u32 len : 24;
- u32 status : 8;
+ u32 offset:24;
+ u32 flags:8;
+ u32 len:24;
+ u32 status:8;
};
struct i2o_bucket_descriptor {
- u32 context; /* FIXME: 64bit support */
+ u32 context; /* FIXME: 64bit support */
struct i2o_packet_info packet_info[1];
};
@@ -127,14 +127,14 @@ struct i2o_lan_local {
u8 unit;
struct i2o_device *i2o_dev;
- struct fddi_statistics stats; /* see also struct net_device_stats */
- unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
- atomic_t buckets_out; /* nbr of unused buckets on DDM */
- atomic_t tx_out; /* outstanding TXes */
- u8 tx_count; /* packets in one TX message frame */
- u16 tx_max_out; /* DDM's Tx queue len */
- u8 sgl_max; /* max SGLs in one message frame */
- u32 m; /* IOP address of the batch msg frame */
+ struct fddi_statistics stats; /* see also struct net_device_stats */
+ unsigned short (*type_trans) (struct sk_buff *, struct net_device *);
+ atomic_t buckets_out; /* nbr of unused buckets on DDM */
+ atomic_t tx_out; /* outstanding TXes */
+ u8 tx_count; /* packets in one TX message frame */
+ u16 tx_max_out; /* DDM's Tx queue len */
+ u8 sgl_max; /* max SGLs in one message frame */
+ u32 m; /* IOP address of the batch msg frame */
struct work_struct i2o_batch_send_task;
int send_active;
@@ -144,16 +144,16 @@ struct i2o_lan_local {
spinlock_t tx_lock;
- u32 max_size_mc_table; /* max number of multicast addresses */
+ u32 max_size_mc_table; /* max number of multicast addresses */
/* LAN OSM configurable parameters are here: */
- u16 max_buckets_out; /* max nbr of buckets to send to DDM */
- u16 bucket_thresh; /* send more when this many used */
+ u16 max_buckets_out; /* max nbr of buckets to send to DDM */
+ u16 bucket_thresh; /* send more when this many used */
u16 rx_copybreak;
- u8 tx_batch_mode; /* Set when using batch mode sends */
- u32 i2o_event_mask; /* To turn on interesting event flags */
+ u8 tx_batch_mode; /* Set when using batch mode sends */
+ u32 i2o_event_mask; /* To turn on interesting event flags */
};
-#endif /* _I2O_LAN_H */
+#endif /* _I2O_LAN_H */
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index d559a1758363..2a0c42b8cda5 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
*/
#define OSM_NAME "proc-osm"
-#define OSM_VERSION "1.145"
+#define OSM_VERSION "1.316"
#define OSM_DESCRIPTION "I2O ProcFS OSM"
#define I2O_MAX_MODULES 4
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 9f1744c3933b..f9e5a23697a1 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -70,7 +70,7 @@
#include <scsi/sg_request.h>
#define OSM_NAME "scsi-osm"
-#define OSM_VERSION "1.282"
+#define OSM_VERSION "1.316"
#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM"
static struct i2o_driver i2o_scsi_driver;
@@ -113,7 +113,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
list_for_each_entry(i2o_dev, &c->devices, list)
if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* SCSI bus */
max_channel++;
}
@@ -146,7 +146,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
i = 0;
list_for_each_entry(i2o_dev, &c->devices, list)
if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* only SCSI bus */
i2o_shost->channel[i++] = i2o_dev;
@@ -238,13 +238,15 @@ static int i2o_scsi_probe(struct device *dev)
u8 type;
struct i2o_device *d = i2o_shost->channel[0];
- if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
+ if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1)
&& (type == 0x01)) /* SCSI bus */
- if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
+ if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
channel = 0;
if (i2o_dev->lct_data.class_id ==
I2O_CLASS_RANDOM_BLOCK_STORAGE)
- lun = i2o_shost->lun++;
+ lun =
+ cpu_to_le64(i2o_shost->
+ lun++);
else
lun = 0;
}
@@ -253,10 +255,10 @@ static int i2o_scsi_probe(struct device *dev)
break;
case I2O_CLASS_SCSI_PERIPHERAL:
- if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4))
return -EFAULT;
- if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8))
return -EFAULT;
parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
@@ -281,20 +283,22 @@ static int i2o_scsi_probe(struct device *dev)
return -EFAULT;
}
- if (id >= scsi_host->max_id) {
- osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
- scsi_host->max_id);
+ if (le32_to_cpu(id) >= scsi_host->max_id) {
+ osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)",
+ le32_to_cpu(id), scsi_host->max_id);
return -EFAULT;
}
- if (lun >= scsi_host->max_lun) {
- osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
- (unsigned int)lun, scsi_host->max_lun);
+ if (le64_to_cpu(lun) >= scsi_host->max_lun) {
+ osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)",
+ (long unsigned int)le64_to_cpu(lun),
+ scsi_host->max_lun);
return -EFAULT;
}
scsi_dev =
- __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+ __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id),
+ le64_to_cpu(lun), i2o_dev);
if (IS_ERR(scsi_dev)) {
osm_warn("can not add SCSI device %03x\n",
@@ -305,8 +309,9 @@ static int i2o_scsi_probe(struct device *dev)
sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
"scsi");
- osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
- i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+ osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n",
+ i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
+ (long unsigned int)le64_to_cpu(lun));
return 0;
};
@@ -510,8 +515,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
struct i2o_controller *c;
struct i2o_device *i2o_dev;
int tid;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
/*
* ENABLE_DISCONNECT
* SIMPLE_TAG
@@ -519,7 +523,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
u32 scsi_flags = 0x20a00000;
u32 sgl_offset;
- u32 __iomem *mptr;
+ u32 *mptr;
u32 cmd = I2O_CMD_SCSI_EXEC << 24;
int rc = 0;
@@ -576,8 +580,8 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
* throw it back to the scsi layer
*/
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY) {
+ msg = i2o_msg_get(c);
+ if (IS_ERR(msg)) {
rc = SCSI_MLQUEUE_HOST_BUSY;
goto exit;
}
@@ -617,16 +621,16 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
if (sgl_offset == SGL_OFFSET_10)
sgl_offset = SGL_OFFSET_12;
cmd = I2O_CMD_PRIVATE << 24;
- writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
- writel(adpt_flags | tid, mptr++);
+ *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
+ *mptr++ = cpu_to_le32(adpt_flags | tid);
}
#endif
- writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
- writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
+ msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
+ msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context);
/* We want the SCSI control block back */
- writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);
+ msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt));
/* LSI_920_PCI_QUIRK
*
@@ -649,15 +653,15 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
*/
- writel(scsi_flags | SCpnt->cmd_len, mptr++);
+ *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len);
/* Write SCSI command into the message - always 16 byte block */
- memcpy_toio(mptr, SCpnt->cmnd, 16);
+ memcpy(mptr, SCpnt->cmnd, 16);
mptr += 4;
if (sgl_offset != SGL_OFFSET_0) {
/* write size of data addressed by SGL */
- writel(SCpnt->request_bufflen, mptr++);
+ *mptr++ = cpu_to_le32(SCpnt->request_bufflen);
/* Now fill in the SGList and command */
if (SCpnt->use_sg) {
@@ -676,11 +680,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
/* Stick the headers on */
- writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
- &msg->u.head[0]);
+ msg->u.head[0] =
+ cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
/* Queue the message */
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
osm_debug("Issued %ld\n", SCpnt->serial_number);
@@ -688,7 +692,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
nomem:
rc = -ENOMEM;
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
exit:
return rc;
@@ -709,8 +713,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
{
struct i2o_device *i2o_dev;
struct i2o_controller *c;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int tid;
int status = FAILED;
@@ -720,16 +723,16 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
c = i2o_dev->iop;
tid = i2o_dev->lct_data.tid;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
return SCSI_MLQUEUE_HOST_BUSY;
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
- writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
+ msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
- if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT))
+ if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
status = SUCCESS;
return status;
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 4eb53258842e..492167446936 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -32,7 +32,7 @@
#include "core.h"
#define OSM_NAME "i2o"
-#define OSM_VERSION "1.288"
+#define OSM_VERSION "1.325"
#define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */
@@ -47,27 +47,6 @@ static struct i2o_dma i2o_systab;
static int i2o_hrt_get(struct i2o_controller *c);
/**
- * i2o_msg_nop - Returns a message which is not used
- * @c: I2O controller from which the message was created
- * @m: message which should be returned
- *
- * If you fetch a message via i2o_msg_get, and can't use it, you must
- * return the message with this function. Otherwise the message frame
- * is lost.
- */
-void i2o_msg_nop(struct i2o_controller *c, u32 m)
-{
- struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
-
- writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0, &msg->u.head[2]);
- writel(0, &msg->u.head[3]);
- i2o_msg_post(c, m);
-};
-
-/**
* i2o_msg_get_wait - obtain an I2O message from the IOP
* @c: I2O controller
* @msg: pointer to a I2O message pointer
@@ -81,22 +60,21 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
* address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
-u32 i2o_msg_get_wait(struct i2o_controller *c,
- struct i2o_message __iomem ** msg, int wait)
+struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait)
{
unsigned long timeout = jiffies + wait * HZ;
- u32 m;
+ struct i2o_message *msg;
- while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
+ while (IS_ERR(msg = i2o_msg_get(c))) {
if (time_after(jiffies, timeout)) {
osm_debug("%s: Timeout waiting for message frame.\n",
c->name);
- return I2O_QUEUE_EMPTY;
+ return ERR_PTR(-ETIMEDOUT);
}
schedule_timeout_uninterruptible(1);
}
- return m;
+ return msg;
};
#if BITS_PER_LONG == 64
@@ -301,8 +279,7 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
*/
static int i2o_iop_quiesce(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
int rc;
@@ -313,16 +290,17 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
(sb->iop_state != ADAPTER_STATE_OPERATIONAL))
return 0;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/* Long timeout needed for quiesce if lots of devices */
- if ((rc = i2o_msg_post_wait(c, m, 240)))
+ if ((rc = i2o_msg_post_wait(c, msg, 240)))
osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Quiesced.\n", c->name);
@@ -342,8 +320,7 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
*/
static int i2o_iop_enable(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
int rc;
@@ -353,16 +330,17 @@ static int i2o_iop_enable(struct i2o_controller *c)
if (sb->iop_state != ADAPTER_STATE_READY)
return -EINVAL;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/* How long of a timeout do we need? */
- if ((rc = i2o_msg_post_wait(c, m, 240)))
+ if ((rc = i2o_msg_post_wait(c, msg, 240)))
osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Enabled.\n", c->name);
@@ -413,22 +391,22 @@ static inline void i2o_iop_enable_all(void)
*/
static int i2o_iop_clear(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
int rc;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
- writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
- if ((rc = i2o_msg_post_wait(c, m, 30)))
+ if ((rc = i2o_msg_post_wait(c, msg, 30)))
osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
else
osm_debug("%s: Cleared.\n", c->name);
@@ -446,13 +424,13 @@ static int i2o_iop_clear(struct i2o_controller *c)
* Clear and (re)initialize IOP's outbound queue and post the message
* frames to the IOP.
*
- * Returns 0 on success or a negative errno code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
{
- volatile u8 *status = c->status.virt;
u32 m;
- struct i2o_message __iomem *msg;
+ volatile u8 *status = c->status.virt;
+ struct i2o_message *msg;
ulong timeout;
int i;
@@ -460,23 +438,24 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
memset(c->status.virt, 0, 4);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0x00000000, &msg->u.s.tcntxt);
- writel(PAGE_SIZE, &msg->body[0]);
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(PAGE_SIZE);
/* Outbound msg frame size in words and Initcode */
- writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
- writel(0xd0000004, &msg->body[2]);
- writel(i2o_dma_low(c->status.phys), &msg->body[3]);
- writel(i2o_dma_high(c->status.phys), &msg->body[4]);
+ msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80);
+ msg->body[2] = cpu_to_le32(0xd0000004);
+ msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys));
+ msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys));
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
while (*status <= I2O_CMD_IN_PROGRESS) {
@@ -511,34 +490,34 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
static int i2o_iop_reset(struct i2o_controller *c)
{
volatile u8 *status = c->status.virt;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
unsigned long timeout;
i2o_status_block *sb = c->status_block.virt;
int rc = 0;
osm_debug("%s: Resetting controller\n", c->name);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
memset(c->status_block.virt, 0, 8);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
- writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context
- writel(0, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(i2o_dma_low(c->status.phys), &msg->body[2]);
- writel(i2o_dma_high(c->status.phys), &msg->body[3]);
+ msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0x00000000);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys));
+ msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys));
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
/* Wait for a reply */
timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
@@ -567,18 +546,15 @@ static int i2o_iop_reset(struct i2o_controller *c)
osm_debug("%s: Reset in progress, waiting for reboot...\n",
c->name);
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
- while (m == I2O_QUEUE_EMPTY) {
+ while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) {
if (time_after(jiffies, timeout)) {
osm_err("%s: IOP reset timeout.\n", c->name);
- rc = -ETIMEDOUT;
+ rc = PTR_ERR(msg);
goto exit;
}
schedule_timeout_uninterruptible(1);
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
}
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
/* from here all quiesce commands are safe */
c->no_quiesce = 0;
@@ -686,8 +662,7 @@ static int i2o_iop_activate(struct i2o_controller *c)
*/
static int i2o_iop_systab_set(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
i2o_status_block *sb = c->status_block.virt;
struct device *dev = &c->pdev->dev;
struct resource *root;
@@ -735,41 +710,38 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
}
}
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
PCI_DMA_TODEVICE);
if (!i2o_systab.phys) {
- i2o_msg_nop(c, m);
+ i2o_msg_nop(c, msg);
return -ENOMEM;
}
- writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
+ msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
/*
* Provide three SGL-elements:
* System table (SysTab), Private memory space declaration and
* Private i/o space declaration
- *
- * FIXME: is this still true?
- * Nasty one here. We can't use dma_alloc_coherent to send the
- * same table to everyone. We have to go remap it for them all
*/
- writel(c->unit + 2, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(0x54000000 | i2o_systab.len, &msg->body[2]);
- writel(i2o_systab.phys, &msg->body[3]);
- writel(0x54000000 | sb->current_mem_size, &msg->body[4]);
- writel(sb->current_mem_base, &msg->body[5]);
- writel(0xd4000000 | sb->current_io_size, &msg->body[6]);
- writel(sb->current_io_base, &msg->body[6]);
+ msg->body[0] = cpu_to_le32(c->unit + 2);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len);
+ msg->body[3] = cpu_to_le32(i2o_systab.phys);
+ msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size);
+ msg->body[5] = cpu_to_le32(sb->current_mem_base);
+ msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size);
+ msg->body[6] = cpu_to_le32(sb->current_io_base);
- rc = i2o_msg_post_wait(c, m, 120);
+ rc = i2o_msg_post_wait(c, msg, 120);
dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
PCI_DMA_TODEVICE);
@@ -780,8 +752,6 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
else
osm_debug("%s: SysTab set.\n", c->name);
- i2o_status_get(c); // Entered READY state
-
return rc;
}
@@ -791,7 +761,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
*
* Send the system table and enable the I2O controller.
*
- * Returns 0 on success or negativer error code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_iop_online(struct i2o_controller *c)
{
@@ -830,7 +800,6 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
- class_device_unregister(c->classdev);
device_del(&c->device);
/* Ask the IOP to switch to RESET state */
@@ -869,12 +838,11 @@ static int i2o_systab_build(void)
i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
sizeof(struct i2o_sys_tbl_entry);
- systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
+ systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL);
if (!systab) {
osm_err("unable to allocate memory for System Table\n");
return -ENOMEM;
}
- memset(systab, 0, i2o_systab.len);
systab->version = I2OVERSION;
systab->change_ind = change_ind + 1;
@@ -952,30 +920,30 @@ static int i2o_parse_hrt(struct i2o_controller *c)
*/
int i2o_status_get(struct i2o_controller *c)
{
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
volatile u8 *status_block;
unsigned long timeout;
status_block = (u8 *) c->status_block.virt;
memset(c->status_block.virt, 0, sizeof(i2o_status_block));
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context
- writel(0, &msg->body[0]);
- writel(0, &msg->body[1]);
- writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
- writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
- writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */
+ msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
+ msg->u.s.tcntxt = cpu_to_le32(0x00000000);
+ msg->body[0] = cpu_to_le32(0x00000000);
+ msg->body[1] = cpu_to_le32(0x00000000);
+ msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys));
+ msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys));
+ msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
/* Wait for a reply */
timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
@@ -1002,7 +970,7 @@ int i2o_status_get(struct i2o_controller *c)
* The HRT contains information about possible hidden devices but is
* mostly useless to us.
*
- * Returns 0 on success or negativer error code on failure.
+ * Returns 0 on success or negative error code on failure.
*/
static int i2o_hrt_get(struct i2o_controller *c)
{
@@ -1013,20 +981,20 @@ static int i2o_hrt_get(struct i2o_controller *c)
struct device *dev = &c->pdev->dev;
for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]);
- writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(0xd0000000 | c->hrt.len, &msg->body[0]);
- writel(c->hrt.phys, &msg->body[1]);
+ msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 |
+ ADAPTER_TID);
+ msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len);
+ msg->body[1] = cpu_to_le32(c->hrt.phys);
- rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
+ rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt);
if (rc < 0) {
osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
@@ -1051,15 +1019,6 @@ static int i2o_hrt_get(struct i2o_controller *c)
}
/**
- * i2o_iop_free - Free the i2o_controller struct
- * @c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
- kfree(c);
-};
-
-/**
* i2o_iop_release - release the memory for a I2O controller
* @dev: I2O controller which should be released
*
@@ -1073,14 +1032,11 @@ static void i2o_iop_release(struct device *dev)
i2o_iop_free(c);
};
-/* I2O controller class */
-static struct class *i2o_controller_class;
-
/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
*
* Allocate the necessary memory for a i2o_controller struct and
- * initialize the lists.
+ * initialize the lists and message mempool.
*
* Returns a pointer to the I2O controller or a negative error code on
* failure.
@@ -1089,20 +1045,29 @@ struct i2o_controller *i2o_iop_alloc(void)
{
static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */
struct i2o_controller *c;
+ char poolname[32];
- c = kmalloc(sizeof(*c), GFP_KERNEL);
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
osm_err("i2o: Insufficient memory to allocate a I2O controller."
"\n");
return ERR_PTR(-ENOMEM);
}
- memset(c, 0, sizeof(*c));
+
+ c->unit = unit++;
+ sprintf(c->name, "iop%d", c->unit);
+
+ snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
+ if (i2o_pool_alloc
+ (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
+ I2O_MSG_INPOOL_MIN)) {
+ kfree(c);
+ return ERR_PTR(-ENOMEM);
+ };
INIT_LIST_HEAD(&c->devices);
spin_lock_init(&c->lock);
init_MUTEX(&c->lct_lock);
- c->unit = unit++;
- sprintf(c->name, "iop%d", c->unit);
device_initialize(&c->device);
@@ -1137,36 +1102,29 @@ int i2o_iop_add(struct i2o_controller *c)
goto iop_reset;
}
- c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0),
- &c->device, "iop%d", c->unit);
- if (IS_ERR(c->classdev)) {
- osm_err("%s: could not add controller class\n", c->name);
- goto device_del;
- }
-
osm_info("%s: Activating I2O controller...\n", c->name);
osm_info("%s: This may take a few minutes if there are many devices\n",
c->name);
if ((rc = i2o_iop_activate(c))) {
osm_err("%s: could not activate controller\n", c->name);
- goto class_del;
+ goto device_del;
}
osm_debug("%s: building sys table...\n", c->name);
if ((rc = i2o_systab_build()))
- goto class_del;
+ goto device_del;
osm_debug("%s: online controller...\n", c->name);
if ((rc = i2o_iop_online(c)))
- goto class_del;
+ goto device_del;
osm_debug("%s: getting LCT...\n", c->name);
if ((rc = i2o_exec_lct_get(c)))
- goto class_del;
+ goto device_del;
list_add(&c->list, &i2o_controllers);
@@ -1176,9 +1134,6 @@ int i2o_iop_add(struct i2o_controller *c)
return 0;
- class_del:
- class_device_unregister(c->classdev);
-
device_del:
device_del(&c->device);
@@ -1199,28 +1154,27 @@ int i2o_iop_add(struct i2o_controller *c)
* is waited for, or expected. If you do not want further notifications,
* call the i2o_event_register again with a evt_mask of 0.
*
- * Returns 0 on success or -ETIMEDOUT if no message could be fetched for
- * sending the request.
+ * Returns 0 on success or negative error code on failure.
*/
int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
int tcntxt, u32 evt_mask)
{
struct i2o_controller *c = dev->iop;
- struct i2o_message __iomem *msg;
- u32 m;
+ struct i2o_message *msg;
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
+ msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
- writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
- writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data.
- tid, &msg->u.head[1]);
- writel(drv->context, &msg->u.s.icntxt);
- writel(tcntxt, &msg->u.s.tcntxt);
- writel(evt_mask, &msg->body[0]);
+ msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
+ msg->u.head[1] =
+ cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->
+ lct_data.tid);
+ msg->u.s.icntxt = cpu_to_le32(drv->context);
+ msg->u.s.tcntxt = cpu_to_le32(tcntxt);
+ msg->body[0] = cpu_to_le32(evt_mask);
- i2o_msg_post(c, m);
+ i2o_msg_post(c, msg);
return 0;
};
@@ -1239,14 +1193,8 @@ static int __init i2o_iop_init(void)
printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
- i2o_controller_class = class_create(THIS_MODULE, "i2o_controller");
- if (IS_ERR(i2o_controller_class)) {
- osm_err("can't register class i2o_controller\n");
- goto exit;
- }
-
if ((rc = i2o_driver_init()))
- goto class_exit;
+ goto exit;
if ((rc = i2o_exec_init()))
goto driver_exit;
@@ -1262,9 +1210,6 @@ static int __init i2o_iop_init(void)
driver_exit:
i2o_driver_exit();
- class_exit:
- class_destroy(i2o_controller_class);
-
exit:
return rc;
}
@@ -1279,7 +1224,6 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit();
i2o_exec_exit();
i2o_driver_exit();
- class_destroy(i2o_controller_class);
};
module_init(i2o_iop_init);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index ee7075fa1ec3..d698d7709c31 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -88,11 +88,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
struct device *dev = &pdev->dev;
int i;
- if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
- printk(KERN_ERR "%s: device already claimed\n", c->name);
- return -ENODEV;
- }
-
for (i = 0; i < 6; i++) {
/* Skip I/O spaces */
if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
return rc;
}
+ if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+ printk(KERN_ERR "i2o: device already claimed\n");
+ return -ENODEV;
+ }
+
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
pci_name(pdev));
@@ -339,7 +339,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
pci_name(pdev));
c->pdev = pdev;
- c->device.parent = get_device(&pdev->dev);
+ c->device.parent = &pdev->dev;
/* Cards that fall apart if you hit them with large I/O loads... */
if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -410,8 +410,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_iop_add(c)))
goto uninstall;
- get_device(&c->device);
-
if (i960)
pci_write_config_word(i960, 0x42, 0x03ff);
@@ -424,7 +422,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
i2o_pci_free(c);
free_controller:
- put_device(c->device.parent);
i2o_iop_free(c);
disable:
@@ -454,7 +451,6 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
printk(KERN_INFO "%s: Controller removed.\n", c->name);
- put_device(c->device.parent);
put_device(&c->device);
};
@@ -483,4 +479,5 @@ void __exit i2o_pci_exit(void)
{
pci_unregister_driver(&i2o_pci_driver);
};
+
MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 55ba23075c90..75f401d52fda 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev)
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
+ .probe = mcp_bus_probe,
+ .remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
.resume = mcp_bus_resume,
};
@@ -227,8 +229,6 @@ 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);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index e335d54c4659..aff83f966803 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -24,14 +24,14 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/mutex.h>
#include <asm/dma.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
#include "ucb1x00.h"
-static DECLARE_MUTEX(ucb1x00_sem);
+static DEFINE_MUTEX(ucb1x00_mutex);
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
@@ -507,14 +507,14 @@ static int ucb1x00_probe(struct mcp *mcp)
goto err_free;
}
- ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb);
+ ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING,
+ "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);
@@ -522,12 +522,12 @@ static int ucb1x00_probe(struct mcp *mcp)
goto err_irq;
INIT_LIST_HEAD(&ucb->devs);
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_add(&ucb->node, &ucb1x00_devices);
list_for_each_entry(drv, &ucb1x00_drivers, node) {
ucb1x00_add_dev(ucb, drv);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
goto out;
err_irq:
@@ -545,13 +545,13 @@ static void ucb1x00_remove(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct list_head *l, *n;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
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);
+ mutex_unlock(&ucb1x00_mutex);
free_irq(ucb->irq, ucb);
class_device_unregister(&ucb->cdev);
@@ -562,12 +562,12 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv)
struct ucb1x00 *ucb;
INIT_LIST_HEAD(&drv->devs);
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_add(&drv->node, &ucb1x00_drivers);
list_for_each_entry(ucb, &ucb1x00_devices, node) {
ucb1x00_add_dev(ucb, drv);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
@@ -575,13 +575,13 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
{
struct list_head *n, *l;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
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);
+ mutex_unlock(&ucb1x00_mutex);
}
static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
@@ -589,12 +589,12 @@ 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);
+ mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->suspend)
dev->drv->suspend(dev, state);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
@@ -603,12 +603,12 @@ static int ucb1x00_resume(struct mcp *mcp)
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;
- down(&ucb1x00_sem);
+ mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
if (dev->drv->resume)
dev->drv->resume(dev);
}
- up(&ucb1x00_sem);
+ mutex_unlock(&ucb1x00_mutex);
return 0;
}
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 551061c2eadf..79fd062ccb34 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -32,7 +32,6 @@
#include <linux/suspend.h>
#include <linux/slab.h>
#include <linux/kthread.h>
-#include <linux/delay.h>
#include <asm/dma.h>
#include <asm/semaphore.h>
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index d7e20a34f88d..1cef2387fa65 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -141,8 +141,8 @@ struct reverse_heartbeat {
};
struct ibmasm_remote {
- struct input_dev keybd_dev;
- struct input_dev mouse_dev;
+ struct input_dev *keybd_dev;
+ struct input_dev *mouse_dev;
};
struct service_processor {
@@ -157,7 +157,7 @@ struct service_processor {
char dirname[IBMASM_NAME_SIZE];
char devname[IBMASM_NAME_SIZE];
unsigned int number;
- struct ibmasm_remote *remote;
+ struct ibmasm_remote remote;
int serial_line;
struct device *dev;
};
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index d3c48d23ee51..0f9e3aa34d07 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -203,9 +203,9 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
print_input(&input);
if (input.type == INPUT_TYPE_MOUSE) {
- send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+ send_mouse_event(sp->remote.mouse_dev, regs, &input);
} else if (input.type == INPUT_TYPE_KEYBOARD) {
- send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+ send_keyboard_event(sp->remote.keybd_dev, regs, &input);
} else
break;
@@ -217,56 +217,71 @@ void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
int ibmasm_init_remote_input_dev(struct service_processor *sp)
{
/* set up the mouse input device */
- struct ibmasm_remote *remote;
+ struct input_dev *mouse_dev, *keybd_dev;
struct pci_dev *pdev = to_pci_dev(sp->dev);
+ int error = -ENOMEM;
int i;
- sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
- if (!remote)
- return -ENOMEM;
+ sp->remote.mouse_dev = mouse_dev = input_allocate_device();
+ sp->remote.keybd_dev = keybd_dev = input_allocate_device();
- memset(remote, 0, sizeof(*remote));
+ if (!mouse_dev || !keybd_dev)
+ goto err_free_devices;
- remote->mouse_dev.private = remote;
- init_input_dev(&remote->mouse_dev);
- remote->mouse_dev.id.vendor = pdev->vendor;
- remote->mouse_dev.id.product = pdev->device;
- remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+ mouse_dev->id.bustype = BUS_PCI;
+ mouse_dev->id.vendor = pdev->vendor;
+ mouse_dev->id.product = pdev->device;
+ mouse_dev->id.version = 1;
+ mouse_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ mouse_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
- remote->mouse_dev.name = remote_mouse_name;
- input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
- input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
+ set_bit(BTN_TOUCH, mouse_dev->keybit);
+ mouse_dev->name = remote_mouse_name;
+ input_set_abs_params(mouse_dev, ABS_X, 0, xmax, 0, 0);
+ input_set_abs_params(mouse_dev, ABS_Y, 0, ymax, 0, 0);
- remote->keybd_dev.private = remote;
- init_input_dev(&remote->keybd_dev);
- remote->keybd_dev.id.vendor = pdev->vendor;
- remote->keybd_dev.id.product = pdev->device;
- remote->keybd_dev.evbit[0] = BIT(EV_KEY);
- remote->keybd_dev.name = remote_keybd_name;
+ mouse_dev->id.bustype = BUS_PCI;
+ keybd_dev->id.vendor = pdev->vendor;
+ keybd_dev->id.product = pdev->device;
+ mouse_dev->id.version = 2;
+ keybd_dev->evbit[0] = BIT(EV_KEY);
+ keybd_dev->name = remote_keybd_name;
- for (i=0; i<XLATE_SIZE; i++) {
+ for (i = 0; i < XLATE_SIZE; i++) {
if (xlate_high[i])
- set_bit(xlate_high[i], remote->keybd_dev.keybit);
+ set_bit(xlate_high[i], keybd_dev->keybit);
if (xlate[i])
- set_bit(xlate[i], remote->keybd_dev.keybit);
+ set_bit(xlate[i], keybd_dev->keybit);
}
- input_register_device(&remote->mouse_dev);
- input_register_device(&remote->keybd_dev);
+ error = input_register_device(mouse_dev);
+ if (error)
+ goto err_free_devices;
+
+ error = input_register_device(keybd_dev);
+ if (error)
+ goto err_unregister_mouse_dev;
+
enable_mouse_interrupts(sp);
printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
return 0;
+
+ err_unregister_mouse_dev:
+ input_unregister_device(mouse_dev);
+ mouse_dev = NULL; /* so we don't try to free it again below */
+ err_free_devices:
+ input_free_device(mouse_dev);
+ input_free_device(keybd_dev);
+
+ return error;
}
void ibmasm_free_remote_input_dev(struct service_processor *sp)
{
disable_mouse_interrupts(sp);
- input_unregister_device(&sp->remote->keybd_dev);
- input_unregister_device(&sp->remote->mouse_dev);
- kfree(sp->remote);
+ input_unregister_device(sp->remote.mouse_dev);
+ input_unregister_device(sp->remote.keybd_dev);
}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index eb41391e06e9..bfca5c176e88 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -495,6 +495,7 @@ static void mmc_decode_cid(struct mmc_card *card)
case 2: /* MMC v2.0 - v2.2 */
case 3: /* MMC v3.1 - v3.3 */
+ case 4: /* MMC v4 */
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);
@@ -550,6 +551,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
} else {
/*
* We only understand CSD structure v1.1 and v1.2.
@@ -579,6 +585,11 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->capacity = (1 + m) << (e + 2);
csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+ csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+ csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+ csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
}
}
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index abcf19116d70..5b014c370e80 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -28,6 +28,7 @@
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/mutex.h>
#include <linux/mmc/card.h>
#include <linux/mmc/protocol.h>
@@ -54,41 +55,36 @@ struct mmc_blk_data {
unsigned int usage;
unsigned int block_bits;
+ unsigned int read_only;
};
-static DECLARE_MUTEX(open_lock);
+static DEFINE_MUTEX(open_lock);
static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
struct mmc_blk_data *md;
- down(&open_lock);
+ mutex_lock(&open_lock);
md = disk->private_data;
if (md && md->usage == 0)
md = NULL;
if (md)
md->usage++;
- up(&open_lock);
+ mutex_unlock(&open_lock);
return md;
}
static void mmc_blk_put(struct mmc_blk_data *md)
{
- down(&open_lock);
+ mutex_lock(&open_lock);
md->usage--;
if (md->usage == 0) {
put_disk(md->disk);
mmc_cleanup_queue(&md->queue);
kfree(md);
}
- up(&open_lock);
-}
-
-static inline int mmc_blk_readonly(struct mmc_card *card)
-{
- return mmc_card_readonly(card) ||
- !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+ mutex_unlock(&open_lock);
}
static int mmc_blk_open(struct inode *inode, struct file *filp)
@@ -102,8 +98,7 @@ static int mmc_blk_open(struct inode *inode, struct file *filp)
check_disk_change(inode->i_bdev);
ret = 0;
- if ((filp->f_mode & FMODE_WRITE) &&
- mmc_blk_readonly(md->queue.card))
+ if ((filp->f_mode & FMODE_WRITE) && md->read_only)
ret = -EROFS;
}
@@ -119,31 +114,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp)
}
static int
-mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct block_device *bdev = inode->i_bdev;
-
- if (cmd == HDIO_GETGEO) {
- struct hd_geometry geo;
-
- memset(&geo, 0, sizeof(struct hd_geometry));
-
- geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
- geo.heads = 4;
- geo.sectors = 16;
- geo.start = get_start_sect(bdev);
-
- return copy_to_user((void __user *)arg, &geo, sizeof(geo))
- ? -EFAULT : 0;
- }
-
- return -ENOTTY;
+ geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
+ geo->heads = 4;
+ geo->sectors = 16;
+ return 0;
}
static struct block_device_operations mmc_bdops = {
.open = mmc_blk_open,
.release = mmc_blk_release,
- .ioctl = mmc_blk_ioctl,
+ .getgeo = mmc_blk_getgeo,
.owner = THIS_MODULE,
};
@@ -206,7 +188,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.data.flags |= MMC_DATA_WRITE;
brq.data.blocks = 1;
}
- brq.mrq.stop = brq.data.blocks > 1 ? &brq.stop : NULL;
+
+ if (brq.data.blocks > 1) {
+ brq.data.flags |= MMC_DATA_MULTI;
+ brq.mrq.stop = &brq.stop;
+ } else {
+ brq.mrq.stop = NULL;
+ }
brq.data.sg = mq->sg;
brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
@@ -263,7 +251,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
*/
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 1);
}
spin_unlock_irq(&md->lock);
} while (ret);
@@ -289,7 +277,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
add_disk_randomness(req->rq_disk);
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
spin_unlock_irq(&md->lock);
return 0;
@@ -299,6 +287,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
static unsigned long dev_use[MMC_NUM_MINORS/(8*sizeof(unsigned long))];
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+ return mmc_card_readonly(card) ||
+ !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
{
struct mmc_blk_data *md;
@@ -310,64 +304,121 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
__set_bit(devidx, dev_use);
md = kmalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
- if (md) {
- memset(md, 0, sizeof(struct mmc_blk_data));
+ if (!md) {
+ ret = -ENOMEM;
+ goto out;
+ }
- md->disk = alloc_disk(1 << MMC_SHIFT);
- if (md->disk == NULL) {
- kfree(md);
- md = ERR_PTR(-ENOMEM);
- goto out;
- }
+ memset(md, 0, sizeof(struct mmc_blk_data));
- spin_lock_init(&md->lock);
- md->usage = 1;
+ /*
+ * Set the read-only status based on the supported commands
+ * and the write protect switch.
+ */
+ md->read_only = mmc_blk_readonly(card);
- ret = mmc_init_queue(&md->queue, card, &md->lock);
- if (ret) {
- put_disk(md->disk);
- kfree(md);
- md = ERR_PTR(ret);
- goto out;
+ /*
+ * Figure out a workable block size. MMC cards have:
+ * - two block sizes, one for read and one for write.
+ * - may support partial reads and/or writes
+ * (allows block sizes smaller than specified)
+ */
+ md->block_bits = card->csd.read_blkbits;
+ if (card->csd.write_blkbits != card->csd.read_blkbits) {
+ if (card->csd.write_blkbits < card->csd.read_blkbits &&
+ card->csd.read_partial) {
+ /*
+ * write block size is smaller than read block
+ * size, but we support partial reads, so choose
+ * the smaller write block size.
+ */
+ md->block_bits = card->csd.write_blkbits;
+ } else if (card->csd.write_blkbits > card->csd.read_blkbits &&
+ card->csd.write_partial) {
+ /*
+ * read block size is smaller than write block
+ * size, but we support partial writes. Use read
+ * block size.
+ */
+ } else {
+ /*
+ * We don't support this configuration for writes.
+ */
+ printk(KERN_ERR "%s: unable to select block size for "
+ "writing (rb%u wb%u rp%u wp%u)\n",
+ md->disk->disk_name,
+ 1 << card->csd.read_blkbits,
+ 1 << card->csd.write_blkbits,
+ card->csd.read_partial,
+ card->csd.write_partial);
+ md->read_only = 1;
}
- md->queue.prep_fn = mmc_blk_prep_rq;
- md->queue.issue_fn = mmc_blk_issue_rq;
- md->queue.data = md;
+ }
- md->disk->major = major;
- md->disk->first_minor = devidx << MMC_SHIFT;
- md->disk->fops = &mmc_bdops;
- md->disk->private_data = md;
- md->disk->queue = md->queue.queue;
- md->disk->driverfs_dev = &card->dev;
+ /*
+ * Refuse to allow block sizes smaller than 512 bytes.
+ */
+ if (md->block_bits < 9) {
+ printk(KERN_ERR "%s: unable to support block size %u\n",
+ mmc_card_id(card), 1 << md->block_bits);
+ ret = -EINVAL;
+ goto err_kfree;
+ }
- /*
- * As discussed on lkml, GENHD_FL_REMOVABLE should:
- *
- * - be set for removable media with permanent block devices
- * - be unset for removable block devices with permanent media
- *
- * Since MMC block devices clearly fall under the second
- * case, we do not set GENHD_FL_REMOVABLE. Userspace
- * should use the block device creation/destruction hotplug
- * messages to tell when the card is present.
- */
+ md->disk = alloc_disk(1 << MMC_SHIFT);
+ if (md->disk == NULL) {
+ ret = -ENOMEM;
+ goto err_kfree;
+ }
- sprintf(md->disk->disk_name, "mmcblk%d", devidx);
- sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+ spin_lock_init(&md->lock);
+ md->usage = 1;
- md->block_bits = card->csd.read_blkbits;
+ ret = mmc_init_queue(&md->queue, card, &md->lock);
+ if (ret)
+ goto err_putdisk;
- blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+ md->queue.prep_fn = mmc_blk_prep_rq;
+ md->queue.issue_fn = mmc_blk_issue_rq;
+ md->queue.data = md;
- /*
- * The CSD capacity field is in units of read_blkbits.
- * set_capacity takes units of 512 bytes.
- */
- set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
- }
- out:
+ md->disk->major = major;
+ md->disk->first_minor = devidx << MMC_SHIFT;
+ md->disk->fops = &mmc_bdops;
+ md->disk->private_data = md;
+ md->disk->queue = md->queue.queue;
+ md->disk->driverfs_dev = &card->dev;
+
+ /*
+ * As discussed on lkml, GENHD_FL_REMOVABLE should:
+ *
+ * - be set for removable media with permanent block devices
+ * - be unset for removable block devices with permanent media
+ *
+ * Since MMC block devices clearly fall under the second
+ * case, we do not set GENHD_FL_REMOVABLE. Userspace
+ * should use the block device creation/destruction hotplug
+ * messages to tell when the card is present.
+ */
+
+ sprintf(md->disk->disk_name, "mmcblk%d", devidx);
+ sprintf(md->disk->devfs_name, "mmc/blk%d", devidx);
+
+ blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits);
+
+ /*
+ * The CSD capacity field is in units of read_blkbits.
+ * set_capacity takes units of 512 bytes.
+ */
+ set_capacity(md->disk, card->csd.capacity << (card->csd.read_blkbits - 9));
return md;
+
+ err_putdisk:
+ put_disk(md->disk);
+ err_kfree:
+ kfree(md);
+ out:
+ return ERR_PTR(ret);
}
static int
@@ -403,12 +454,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
- if (card->csd.read_blkbits < 9) {
- printk(KERN_WARNING "%s: read blocksize too small (%u)\n",
- mmc_card_id(card), 1 << card->csd.read_blkbits);
- return -ENODEV;
- }
-
md = mmc_blk_alloc(card);
if (IS_ERR(md))
return PTR_ERR(md);
@@ -417,9 +462,10 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- printk(KERN_INFO "%s: %s %s %luKiB %s\n",
+ printk(KERN_INFO "%s: %s %s %lluKiB %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
- get_capacity(md->disk) >> 1, mmc_blk_readonly(card)?"(ro)":"");
+ (unsigned long long)(get_capacity(md->disk) >> 1),
+ md->read_only ? "(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 3f4a66ca9555..a2a35fd946ee 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -80,7 +80,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
}
static int
-mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
int buf_size)
{
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev)
return ret;
}
-static struct bus_type mmc_bus_type = {
- .name = "mmc",
- .dev_attrs = mmc_dev_attrs,
- .match = mmc_bus_match,
- .hotplug = mmc_bus_hotplug,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
-};
-
-
-static int mmc_drv_probe(struct device *dev)
+static int mmc_bus_probe(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev)
return drv->probe(card);
}
-static int mmc_drv_remove(struct device *dev)
+static int mmc_bus_remove(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
@@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev)
return 0;
}
+static struct bus_type mmc_bus_type = {
+ .name = "mmc",
+ .dev_attrs = mmc_dev_attrs,
+ .match = mmc_bus_match,
+ .uevent = mmc_bus_uevent,
+ .probe = mmc_bus_probe,
+ .remove = mmc_bus_remove,
+ .suspend = mmc_bus_suspend,
+ .resume = mmc_bus_resume,
+};
/**
* mmc_register_driver - register a media driver
@@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev)
int mmc_register_driver(struct mmc_driver *drv)
{
drv->drv.bus = &mmc_bus_type;
- drv->drv.probe = mmc_drv_probe;
- drv->drv.remove = mmc_drv_remove;
return driver_register(&drv->drv);
}
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index 166c9b0ad04e..634ef53e85a5 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -19,13 +19,14 @@
#include <linux/highmem.h>
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
+#include <linux/amba/bus.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
#include <asm/mach/mmc.h>
#include "mmci.h"
@@ -157,6 +158,13 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
data->error = MMC_ERR_FIFO;
status |= MCI_DATAEND;
+
+ /*
+ * We hit an error condition. Ensure that any data
+ * partially written to a page is properly coherent.
+ */
+ if (host->sg_len && data->flags & MMC_DATA_READ)
+ flush_dcache_page(host->sg_ptr->page);
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
@@ -292,7 +300,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
/*
* Unmap the buffer.
*/
- mmci_kunmap_atomic(host, &flags);
+ mmci_kunmap_atomic(host, buffer, &flags);
host->sg_off += len;
host->size -= len;
@@ -301,6 +309,13 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id, struct pt_regs *regs)
if (remain)
break;
+ /*
+ * If we were reading, and we have completed this
+ * page, ensure that the data cache is coherent.
+ */
+ if (status & MCI_RXACTIVE)
+ flush_dcache_page(host->sg_ptr->page);
+
if (!mmci_next_sg(host))
break;
@@ -479,13 +494,9 @@ static int mmci_probe(struct amba_device *dev, void *id)
goto host_free;
}
- ret = clk_use(host->clk);
- if (ret)
- goto clk_free;
-
ret = clk_enable(host->clk);
if (ret)
- goto clk_unuse;
+ goto clk_free;
host->plat = plat;
host->mclk = clk_get_rate(host->clk);
@@ -558,8 +569,6 @@ static int mmci_probe(struct amba_device *dev, void *id)
iounmap(host->base);
clk_disable:
clk_disable(host->clk);
- clk_unuse:
- clk_unuse(host->clk);
clk_free:
clk_put(host->clk);
host_free:
@@ -594,7 +603,6 @@ static int mmci_remove(struct amba_device *dev)
iounmap(host->base);
clk_disable(host->clk);
- clk_unuse(host->clk);
clk_put(host->clk);
mmc_free_host(mmc);
diff --git a/drivers/mmc/mmci.h b/drivers/mmc/mmci.h
index 4589bbd68192..6d7eadc9a678 100644
--- a/drivers/mmc/mmci.h
+++ b/drivers/mmc/mmci.h
@@ -172,8 +172,8 @@ static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flag
return kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
}
-static inline void mmci_kunmap_atomic(struct mmci_host *host, unsigned long *flags)
+static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
{
- kunmap_atomic(host->sg_ptr->page, KM_BIO_SRC_IRQ);
+ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
local_irq_restore(*flags);
}
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index c7eb7c269081..f25757625361 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -90,7 +90,7 @@ static int dma = 2;
* Basic functions
*/
-static inline void wbsd_unlock_config(struct wbsd_host* host)
+static inline void wbsd_unlock_config(struct wbsd_host *host)
{
BUG_ON(host->config == 0);
@@ -98,14 +98,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
outb(host->unlock_code, host->config);
}
-static inline void wbsd_lock_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)
+static inline void wbsd_write_config(struct wbsd_host *host, u8 reg, u8 value)
{
BUG_ON(host->config == 0);
@@ -113,7 +113,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
outb(value, host->config + 1);
}
-static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
+static inline u8 wbsd_read_config(struct wbsd_host *host, u8 reg)
{
BUG_ON(host->config == 0);
@@ -121,13 +121,13 @@ static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
return inb(host->config + 1);
}
-static inline void wbsd_write_index(struct wbsd_host* host, u8 index, u8 value)
+static inline void wbsd_write_index(struct wbsd_host *host, u8 index, u8 value)
{
outb(index, host->base + WBSD_IDXR);
outb(value, host->base + WBSD_DATAR);
}
-static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
+static inline u8 wbsd_read_index(struct wbsd_host *host, u8 index)
{
outb(index, host->base + WBSD_IDXR);
return inb(host->base + WBSD_DATAR);
@@ -137,7 +137,7 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
* Common routines
*/
-static void wbsd_init_device(struct wbsd_host* host)
+static void wbsd_init_device(struct wbsd_host *host)
{
u8 setup, ier;
@@ -197,7 +197,7 @@ static void wbsd_init_device(struct wbsd_host* host)
inb(host->base + WBSD_ISR);
}
-static void wbsd_reset(struct wbsd_host* host)
+static void wbsd_reset(struct wbsd_host *host)
{
u8 setup;
@@ -211,14 +211,13 @@ static void wbsd_reset(struct wbsd_host* host)
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
}
-static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
+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)
- {
+ if (host->dma >= 0) {
/*
* Release ISA DMA controller.
*/
@@ -247,7 +246,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
* Scatter/gather functions
*/
-static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_init_sg(struct wbsd_host *host, struct mmc_data *data)
{
/*
* Get info. about SG list from data structure.
@@ -259,7 +258,7 @@ static inline void wbsd_init_sg(struct wbsd_host* host, struct mmc_data* data)
host->remain = host->cur_sg->length;
}
-static inline int wbsd_next_sg(struct wbsd_host* host)
+static inline int wbsd_next_sg(struct wbsd_host *host)
{
/*
* Skip to next SG entry.
@@ -270,33 +269,32 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
/*
* Any entries left?
*/
- if (host->num_sg > 0)
- {
- host->offset = 0;
- host->remain = host->cur_sg->length;
- }
+ if (host->num_sg > 0) {
+ host->offset = 0;
+ host->remain = host->cur_sg->length;
+ }
return host->num_sg;
}
-static inline char* wbsd_kmap_sg(struct wbsd_host* host)
+static inline char *wbsd_kmap_sg(struct wbsd_host *host)
{
host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) +
host->cur_sg->offset;
return host->mapped_sg;
}
-static inline void wbsd_kunmap_sg(struct wbsd_host* host)
+static inline void wbsd_kunmap_sg(struct wbsd_host *host)
{
kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
}
-static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
- struct scatterlist* sg;
- char* dmabuf = host->dma_buffer;
- char* sgbuf;
+ struct scatterlist *sg;
+ char *dmabuf = host->dma_buffer;
+ char *sgbuf;
size = host->size;
@@ -308,8 +306,7 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
* be the entire list though so make sure that
* we do not transfer too much.
*/
- for (i = 0;i < len;i++)
- {
+ for (i = 0; i < len; i++) {
sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
if (size < sg[i].length)
memcpy(dmabuf, sgbuf, size);
@@ -337,12 +334,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
host->size -= size;
}
-static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
+static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
- struct scatterlist* sg;
- char* dmabuf = host->dma_buffer;
- char* sgbuf;
+ struct scatterlist *sg;
+ char *dmabuf = host->dma_buffer;
+ char *sgbuf;
size = host->size;
@@ -354,8 +351,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
* be the entire list though so make sure that
* we do not transfer too much.
*/
- for (i = 0;i < len;i++)
- {
+ for (i = 0; i < len; i++) {
sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
if (size < sg[i].length)
memcpy(sgbuf, dmabuf, size);
@@ -387,46 +383,38 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
* Command handling
*/
-static inline void wbsd_get_short_reply(struct wbsd_host* host,
- struct mmc_command* cmd)
+static inline void wbsd_get_short_reply(struct wbsd_host *host,
+ struct mmc_command *cmd)
{
/*
* Correct response type?
*/
- if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT)
- {
+ if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_SHORT) {
cmd->error = MMC_ERR_INVALID;
return;
}
- cmd->resp[0] =
- wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
- cmd->resp[0] |=
- wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
- cmd->resp[1] =
- wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
+ cmd->resp[0] = wbsd_read_index(host, WBSD_IDX_RESP12) << 24;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP13) << 16;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP14) << 8;
+ cmd->resp[0] |= wbsd_read_index(host, WBSD_IDX_RESP15) << 0;
+ cmd->resp[1] = wbsd_read_index(host, WBSD_IDX_RESP16) << 24;
}
-static inline void wbsd_get_long_reply(struct wbsd_host* host,
- struct mmc_command* cmd)
+static inline void wbsd_get_long_reply(struct wbsd_host *host,
+ struct mmc_command *cmd)
{
int i;
/*
* Correct response type?
*/
- if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG)
- {
+ if (wbsd_read_index(host, WBSD_IDX_RSPLEN) != WBSD_RSP_LONG) {
cmd->error = MMC_ERR_INVALID;
return;
}
- for (i = 0;i < 4;i++)
- {
+ for (i = 0; i < 4; i++) {
cmd->resp[i] =
wbsd_read_index(host, WBSD_IDX_RESP1 + i * 4) << 24;
cmd->resp[i] |=
@@ -438,7 +426,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
}
}
-static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
+static void wbsd_send_command(struct wbsd_host *host, struct mmc_command *cmd)
{
int i;
u8 status, isr;
@@ -456,7 +444,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Send the command (CRC calculated by host).
*/
outb(cmd->opcode, host->base + WBSD_CMDR);
- for (i = 3;i >= 0;i--)
+ for (i = 3; i >= 0; i--)
outb((cmd->arg >> (i * 8)) & 0xff, host->base + WBSD_CMDR);
cmd->error = MMC_ERR_NONE;
@@ -471,8 +459,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
/*
* Do we expect a reply?
*/
- if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE)
- {
+ if ((cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
/*
* Read back status.
*/
@@ -488,8 +475,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
else if ((cmd->flags & MMC_RSP_CRC) && (isr & WBSD_INT_CRC))
cmd->error = MMC_ERR_BADCRC;
/* All ok */
- else
- {
+ else {
if ((cmd->flags & MMC_RSP_MASK) == MMC_RSP_SHORT)
wbsd_get_short_reply(host, cmd);
else
@@ -504,10 +490,10 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Data functions
*/
-static void wbsd_empty_fifo(struct wbsd_host* host)
+static void wbsd_empty_fifo(struct wbsd_host *host)
{
- struct mmc_data* data = host->mrq->cmd->data;
- char* buffer;
+ struct mmc_data *data = host->mrq->cmd->data;
+ char *buffer;
int i, fsr, fifo;
/*
@@ -522,8 +508,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* Drain the fifo. This has a tendency to loop longer
* than the FIFO length (usually one block).
*/
- while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY))
- {
+ while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_EMPTY)) {
/*
* The size field in the FSR is broken so we have to
* do some guessing.
@@ -535,8 +520,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
else
fifo = 1;
- for (i = 0;i < fifo;i++)
- {
+ for (i = 0; i < fifo; i++) {
*buffer = inb(host->base + WBSD_DFR);
buffer++;
host->offset++;
@@ -547,8 +531,7 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* Transfer done?
*/
- if (data->bytes_xfered == host->size)
- {
+ if (data->bytes_xfered == host->size) {
wbsd_kunmap_sg(host);
return;
}
@@ -556,15 +539,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* End of scatter list entry?
*/
- if (host->remain == 0)
- {
+ if (host->remain == 0) {
wbsd_kunmap_sg(host);
/*
* Get next entry. Check if last.
*/
- if (!wbsd_next_sg(host))
- {
+ if (!wbsd_next_sg(host)) {
/*
* We should never reach this point.
* It means that we're trying to
@@ -594,10 +575,10 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
tasklet_schedule(&host->fifo_tasklet);
}
-static void wbsd_fill_fifo(struct wbsd_host* host)
+static void wbsd_fill_fifo(struct wbsd_host *host)
{
- struct mmc_data* data = host->mrq->cmd->data;
- char* buffer;
+ struct mmc_data *data = host->mrq->cmd->data;
+ char *buffer;
int i, fsr, fifo;
/*
@@ -613,8 +594,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* Fill the fifo. This has a tendency to loop longer
* than the FIFO length (usually one block).
*/
- while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL))
- {
+ while (!((fsr = inb(host->base + WBSD_FSR)) & WBSD_FIFO_FULL)) {
/*
* The size field in the FSR is broken so we have to
* do some guessing.
@@ -626,8 +606,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
else
fifo = 15;
- for (i = 16;i > fifo;i--)
- {
+ for (i = 16; i > fifo; i--) {
outb(*buffer, host->base + WBSD_DFR);
buffer++;
host->offset++;
@@ -638,8 +617,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* Transfer done?
*/
- if (data->bytes_xfered == host->size)
- {
+ if (data->bytes_xfered == host->size) {
wbsd_kunmap_sg(host);
return;
}
@@ -647,15 +625,13 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* End of scatter list entry?
*/
- if (host->remain == 0)
- {
+ if (host->remain == 0) {
wbsd_kunmap_sg(host);
/*
* Get next entry. Check if last.
*/
- if (!wbsd_next_sg(host))
- {
+ if (!wbsd_next_sg(host)) {
/*
* We should never reach this point.
* It means that we're trying to
@@ -684,7 +660,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
tasklet_schedule(&host->fifo_tasklet);
}
-static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
+static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data)
{
u16 blksize;
u8 setup;
@@ -706,8 +682,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
*/
if (data->timeout_ns > 127000000)
wbsd_write_index(host, WBSD_IDX_TAAC, 127);
- else
- wbsd_write_index(host, WBSD_IDX_TAAC, data->timeout_ns/1000000);
+ 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);
@@ -722,23 +700,18 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Space for CRC must be included in the size.
* Two bytes are needed for each data line.
*/
- if (host->bus_width == MMC_BUS_WIDTH_1)
- {
+ 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)
- {
+ } 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_PBSMSB,
+ ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH);
wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF);
- }
- else
- {
+ } else {
data->error = MMC_ERR_INVALID;
return;
}
@@ -755,14 +728,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
/*
* DMA transfer?
*/
- if (host->dma >= 0)
- {
+ if (host->dma >= 0) {
/*
* The buffer for DMA is only 64 kB.
*/
BUG_ON(host->size > 0x10000);
- if (host->size > 0x10000)
- {
+ if (host->size > 0x10000) {
data->error = MMC_ERR_INVALID;
return;
}
@@ -794,9 +765,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Enable DMA on the host.
*/
wbsd_write_index(host, WBSD_IDX_DMA, WBSD_DMA_ENABLE);
- }
- else
- {
+ } else {
/*
* This flag is used to keep printk
* output to a minimum.
@@ -817,13 +786,10 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* Set up FIFO threshold levels (and fill
* buffer if doing a write).
*/
- if (data->flags & MMC_DATA_READ)
- {
+ if (data->flags & MMC_DATA_READ) {
wbsd_write_index(host, WBSD_IDX_FIFOEN,
WBSD_FIFOEN_FULL | 8);
- }
- else
- {
+ } else {
wbsd_write_index(host, WBSD_IDX_FIFOEN,
WBSD_FIFOEN_EMPTY | 8);
wbsd_fill_fifo(host);
@@ -833,7 +799,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data->error = MMC_ERR_NONE;
}
-static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
+static void wbsd_finish_data(struct wbsd_host *host, struct mmc_data *data)
{
unsigned long dmaflags;
int count;
@@ -851,16 +817,14 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Wait for the controller to leave data
* transfer state.
*/
- do
- {
+ do {
status = wbsd_read_index(host, WBSD_IDX_STATUS);
} while (status & (WBSD_BLOCK_READ | WBSD_BLOCK_WRITE));
/*
* DMA transfer?
*/
- if (host->dma >= 0)
- {
+ if (host->dma >= 0) {
/*
* Disable DMA on the host.
*/
@@ -878,16 +842,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
/*
* Any leftover data?
*/
- if (count)
- {
+ if (count) {
printk(KERN_ERR "%s: Incomplete DMA transfer. "
"%d bytes left.\n",
mmc_hostname(host->mmc), count);
data->error = MMC_ERR_FAILED;
- }
- else
- {
+ } else {
/*
* Transfer data from DMA buffer to
* SG list.
@@ -910,10 +871,10 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* *
\*****************************************************************************/
-static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
+static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
- struct wbsd_host* host = mmc_priv(mmc);
- struct mmc_command* cmd;
+ struct wbsd_host *host = mmc_priv(mmc);
+ struct mmc_command *cmd;
/*
* Disable tasklets to avoid a deadlock.
@@ -930,8 +891,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
* If there is no card in the slot then
* timeout immediatly.
*/
- if (!(host->flags & WBSD_FCARD_PRESENT))
- {
+ if (!(host->flags & WBSD_FCARD_PRESENT)) {
cmd->error = MMC_ERR_TIMEOUT;
goto done;
}
@@ -939,8 +899,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
/*
* Does the request include data?
*/
- if (cmd->data)
- {
+ if (cmd->data) {
wbsd_prepare_data(host, cmd->data);
if (cmd->data->error != MMC_ERR_NONE)
@@ -954,8 +913,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
* will be finished after the data has
* transfered.
*/
- if (cmd->data && (cmd->error == MMC_ERR_NONE))
- {
+ if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
/*
* Dirty fix for hardware bug.
*/
@@ -973,14 +931,14 @@ done:
spin_unlock_bh(&host->lock);
}
-static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
+static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
- struct wbsd_host* host = mmc_priv(mmc);
+ struct wbsd_host *host = mmc_priv(mmc);
u8 clk, setup, pwr;
DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
- ios->vdd, ios->bus_width);
+ ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
+ ios->vdd, ios->bus_width);
spin_lock_bh(&host->lock);
@@ -1004,8 +962,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
* Only write to the clock register when
* there is an actual change.
*/
- if (clk != host->clk)
- {
+ if (clk != host->clk) {
wbsd_write_index(host, WBSD_IDX_CLK, clk);
host->clk = clk;
}
@@ -1013,8 +970,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
/*
* Power up card.
*/
- if (ios->power_mode != MMC_POWER_OFF)
- {
+ if (ios->power_mode != MMC_POWER_OFF) {
pwr = inb(host->base + WBSD_CSR);
pwr &= ~WBSD_POWER_N;
outb(pwr, host->base + WBSD_CSR);
@@ -1026,23 +982,19 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
* that needs to be disabled.
*/
setup = wbsd_read_index(host, WBSD_IDX_SETUP);
- if (ios->chip_select == MMC_CS_HIGH)
- {
+ 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
- {
- if (setup & WBSD_DAT3_H)
- {
+ } else {
+ if (setup & WBSD_DAT3_H) {
setup &= ~WBSD_DAT3_H;
/*
* We cannot resume card detection immediatly
* because of capacitance and delays in the chip.
*/
- mod_timer(&host->ignore_timer, jiffies + HZ/100);
+ mod_timer(&host->ignore_timer, jiffies + HZ / 100);
}
}
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
@@ -1056,9 +1008,9 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
spin_unlock_bh(&host->lock);
}
-static int wbsd_get_ro(struct mmc_host* mmc)
+static int wbsd_get_ro(struct mmc_host *mmc)
{
- struct wbsd_host* host = mmc_priv(mmc);
+ struct wbsd_host *host = mmc_priv(mmc);
u8 csr;
spin_lock_bh(&host->lock);
@@ -1096,7 +1048,7 @@ static struct mmc_host_ops wbsd_ops = {
static void wbsd_reset_ignore(unsigned long data)
{
- struct wbsd_host *host = (struct wbsd_host*)data;
+ struct wbsd_host *host = (struct wbsd_host *)data;
BUG_ON(host == NULL);
@@ -1119,7 +1071,7 @@ static void wbsd_reset_ignore(unsigned long data)
* Tasklets
*/
-static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
+static inline struct mmc_data *wbsd_get_data(struct wbsd_host *host)
{
WARN_ON(!host->mrq);
if (!host->mrq)
@@ -1138,14 +1090,13 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
static void wbsd_tasklet_card(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
+ struct wbsd_host *host = (struct wbsd_host *)param;
u8 csr;
int delay = -1;
spin_lock(&host->lock);
- if (host->flags & WBSD_FIGNORE_DETECT)
- {
+ if (host->flags & WBSD_FIGNORE_DETECT) {
spin_unlock(&host->lock);
return;
}
@@ -1153,23 +1104,18 @@ static void wbsd_tasklet_card(unsigned long param)
csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff);
- if (csr & WBSD_CARDPRESENT)
- {
- if (!(host->flags & WBSD_FCARD_PRESENT))
- {
+ if (csr & WBSD_CARDPRESENT) {
+ if (!(host->flags & WBSD_FCARD_PRESENT)) {
DBG("Card inserted\n");
host->flags |= WBSD_FCARD_PRESENT;
delay = 500;
}
- }
- else if (host->flags & WBSD_FCARD_PRESENT)
- {
+ } else if (host->flags & WBSD_FCARD_PRESENT) {
DBG("Card removed\n");
host->flags &= ~WBSD_FCARD_PRESENT;
- if (host->mrq)
- {
+ if (host->mrq) {
printk(KERN_ERR "%s: Card removed during transfer!\n",
mmc_hostname(host->mmc));
wbsd_reset(host);
@@ -1193,8 +1139,8 @@ static void wbsd_tasklet_card(unsigned long param)
static void wbsd_tasklet_fifo(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1213,8 +1159,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
/*
* Done?
*/
- if (host->size == data->bytes_xfered)
- {
+ if (host->size == data->bytes_xfered) {
wbsd_write_index(host, WBSD_IDX_FIFOEN, 0);
tasklet_schedule(&host->finish_tasklet);
}
@@ -1225,8 +1170,8 @@ end:
static void wbsd_tasklet_crc(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1249,8 +1194,8 @@ end:
static void wbsd_tasklet_timeout(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1273,8 +1218,8 @@ end:
static void wbsd_tasklet_finish(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ struct wbsd_host *host = (struct wbsd_host *)param;
+ struct mmc_data *data;
spin_lock(&host->lock);
@@ -1294,14 +1239,13 @@ end:
static void wbsd_tasklet_block(unsigned long param)
{
- struct wbsd_host* host = (struct wbsd_host*)param;
- struct mmc_data* data;
+ 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) !=
- WBSD_CRC_OK)
- {
+ WBSD_CRC_OK) {
data = wbsd_get_data(host);
if (!data)
goto end;
@@ -1323,7 +1267,7 @@ end:
static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct wbsd_host* host = dev_id;
+ struct wbsd_host *host = dev_id;
int isr;
isr = inb(host->base + WBSD_ISR);
@@ -1365,10 +1309,10 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
* Allocate/free MMC structure.
*/
-static int __devinit wbsd_alloc_mmc(struct device* dev)
+static int __devinit wbsd_alloc_mmc(struct device *dev)
{
- struct mmc_host* mmc;
- struct wbsd_host* host;
+ struct mmc_host *mmc;
+ struct wbsd_host *host;
/*
* Allocate MMC structure.
@@ -1388,7 +1332,7 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc->ops = &wbsd_ops;
mmc->f_min = 375000;
mmc->f_max = 24000000;
- mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
mmc->caps = MMC_CAP_4_BIT_DATA;
spin_lock_init(&host->lock);
@@ -1424,10 +1368,10 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
return 0;
}
-static void __devexit wbsd_free_mmc(struct device* dev)
+static void __devexit wbsd_free_mmc(struct device *dev)
{
- struct mmc_host* mmc;
- struct wbsd_host* host;
+ struct mmc_host *mmc;
+ struct wbsd_host *host;
mmc = dev_get_drvdata(dev);
if (!mmc)
@@ -1447,7 +1391,7 @@ static void __devexit wbsd_free_mmc(struct device* dev)
* Scan for known chip id:s
*/
-static int __devinit wbsd_scan(struct wbsd_host* host)
+static int __devinit wbsd_scan(struct wbsd_host *host)
{
int i, j, k;
int id;
@@ -1456,13 +1400,11 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Iterate through all ports, all codes to
* find hardware that is in our known list.
*/
- for (i = 0;i < sizeof(config_ports)/sizeof(int);i++)
- {
+ for (i = 0; i < ARRAY_SIZE(config_ports); i++) {
if (!request_region(config_ports[i], 2, DRIVER_NAME))
continue;
- for (j = 0;j < sizeof(unlock_codes)/sizeof(int);j++)
- {
+ for (j = 0; j < ARRAY_SIZE(unlock_codes); j++) {
id = 0xFFFF;
host->config = config_ports[i];
@@ -1478,18 +1420,15 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
wbsd_lock_config(host);
- for (k = 0;k < sizeof(valid_ids)/sizeof(int);k++)
- {
- if (id == valid_ids[k])
- {
+ for (k = 0; k < ARRAY_SIZE(valid_ids); k++) {
+ if (id == valid_ids[k]) {
host->chip_id = id;
return 0;
}
}
- if (id != 0xFFFF)
- {
+ if (id != 0xFFFF) {
DBG("Unknown hardware (id %x) found at %x\n",
id, config_ports[i]);
}
@@ -1508,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
* Allocate/free io port ranges
*/
-static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
+static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
{
if (io & 0x7)
return -EINVAL;
@@ -1521,7 +1460,7 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
return 0;
}
-static void __devexit wbsd_release_regions(struct wbsd_host* host)
+static void __devexit wbsd_release_regions(struct wbsd_host *host)
{
if (host->base)
release_region(host->base, 8);
@@ -1538,7 +1477,7 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
* Allocate/free DMA port and buffer
*/
-static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
+static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
{
if (dma < 0)
return;
@@ -1582,8 +1521,8 @@ kfree:
*/
BUG_ON(1);
- dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
- DMA_BIDIRECTIONAL);
+ 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);
@@ -1597,11 +1536,12 @@ err:
"Falling back on FIFO.\n", dma);
}
-static void __devexit wbsd_release_dma(struct wbsd_host* host)
+static void __devexit wbsd_release_dma(struct wbsd_host *host)
{
- if (host->dma_addr)
- dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
- DMA_BIDIRECTIONAL);
+ if (host->dma_addr) {
+ dma_unmap_single(host->mmc->dev, host->dma_addr,
+ WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+ }
kfree(host->dma_buffer);
if (host->dma >= 0)
free_dma(host->dma);
@@ -1615,7 +1555,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
* Allocate/free IRQ.
*/
-static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
+static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq)
{
int ret;
@@ -1632,17 +1572,23 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
/*
* Set up tasklets.
*/
- tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host);
- tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host);
- tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
- 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);
+ tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
+ (unsigned long)host);
+ tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
+ (unsigned long)host);
+ tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
+ (unsigned long)host);
+ 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;
}
-static void __devexit wbsd_release_irq(struct wbsd_host* host)
+static void __devexit wbsd_release_irq(struct wbsd_host *host)
{
if (!host->irq)
return;
@@ -1663,7 +1609,7 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
* Allocate all resources for the host.
*/
-static int __devinit wbsd_request_resources(struct wbsd_host* host,
+static int __devinit wbsd_request_resources(struct wbsd_host *host,
int base, int irq, int dma)
{
int ret;
@@ -1694,7 +1640,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Release all resources for the host.
*/
-static void __devexit wbsd_release_resources(struct wbsd_host* host)
+static void __devexit wbsd_release_resources(struct wbsd_host *host)
{
wbsd_release_dma(host);
wbsd_release_irq(host);
@@ -1705,7 +1651,7 @@ static void __devexit wbsd_release_resources(struct wbsd_host* host)
* Configure the resources the chip should use.
*/
-static void wbsd_chip_config(struct wbsd_host* host)
+static void wbsd_chip_config(struct wbsd_host *host)
{
wbsd_unlock_config(host);
@@ -1749,7 +1695,7 @@ static void wbsd_chip_config(struct wbsd_host* host)
* Check that configured resources are correct.
*/
-static int wbsd_chip_validate(struct wbsd_host* host)
+static int wbsd_chip_validate(struct wbsd_host *host)
{
int base, irq, dma;
@@ -1789,7 +1735,7 @@ static int wbsd_chip_validate(struct wbsd_host* host)
* Powers down the SD function
*/
-static void wbsd_chip_poweroff(struct wbsd_host* host)
+static void wbsd_chip_poweroff(struct wbsd_host *host)
{
wbsd_unlock_config(host);
@@ -1805,11 +1751,11 @@ static void wbsd_chip_poweroff(struct wbsd_host* host)
* *
\*****************************************************************************/
-static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
+static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma,
int pnp)
{
- struct wbsd_host* host = NULL;
- struct mmc_host* mmc = NULL;
+ struct wbsd_host *host = NULL;
+ struct mmc_host *mmc = NULL;
int ret;
ret = wbsd_alloc_mmc(dev);
@@ -1823,16 +1769,12 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Scan for hardware.
*/
ret = wbsd_scan(host);
- if (ret)
- {
- if (pnp && (ret == -ENODEV))
- {
+ if (ret) {
+ if (pnp && (ret == -ENODEV)) {
printk(KERN_WARNING DRIVER_NAME
": Unable to confirm device presence. You may "
"experience lock-ups.\n");
- }
- else
- {
+ } else {
wbsd_free_mmc(dev);
return ret;
}
@@ -1842,8 +1784,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Request resources.
*/
ret = wbsd_request_resources(host, io, irq, dma);
- if (ret)
- {
+ if (ret) {
wbsd_release_resources(host);
wbsd_free_mmc(dev);
return ret;
@@ -1852,18 +1793,15 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
/*
* See if chip needs to be configured.
*/
- if (pnp)
- {
- if ((host->config != 0) && !wbsd_chip_validate(host))
- {
+ if (pnp) {
+ if ((host->config != 0) && !wbsd_chip_validate(host)) {
printk(KERN_WARNING DRIVER_NAME
": PnP active but chip not configured! "
"You probably have a buggy BIOS. "
"Configuring chip manually.\n");
wbsd_chip_config(host);
}
- }
- else
+ } else
wbsd_chip_config(host);
/*
@@ -1871,8 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Not tested.
*/
#ifdef CONFIG_PM
- if (host->config)
- {
+ if (host->config) {
wbsd_unlock_config(host);
wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
wbsd_lock_config(host);
@@ -1905,10 +1842,10 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return 0;
}
-static void __devexit wbsd_shutdown(struct device* dev, int pnp)
+static void __devexit wbsd_shutdown(struct device *dev, int pnp)
{
- struct mmc_host* mmc = dev_get_drvdata(dev);
- struct wbsd_host* host;
+ struct mmc_host *mmc = dev_get_drvdata(dev);
+ struct wbsd_host *host;
if (!mmc)
return;
@@ -1932,12 +1869,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
* Non-PnP
*/
-static int __devinit wbsd_probe(struct platform_device* dev)
+static int __devinit wbsd_probe(struct platform_device *dev)
{
return wbsd_init(&dev->dev, io, irq, dma, 0);
}
-static int __devexit wbsd_remove(struct platform_device* dev)
+static int __devexit wbsd_remove(struct platform_device *dev)
{
wbsd_shutdown(&dev->dev, 0);
@@ -1951,7 +1888,7 @@ static int __devexit wbsd_remove(struct platform_device* dev)
#ifdef CONFIG_PNP
static int __devinit
-wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
+wbsd_pnp_probe(struct pnp_dev *pnpdev, const struct pnp_device_id *dev_id)
{
int io, irq, dma;
@@ -1970,7 +1907,7 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
}
-static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
+static void __devexit wbsd_pnp_remove(struct pnp_dev *dev)
{
wbsd_shutdown(&dev->dev, 1);
}
@@ -1983,37 +1920,54 @@ static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
#ifdef CONFIG_PM
-static int wbsd_suspend(struct platform_device *dev, pm_message_t state)
+static int wbsd_suspend(struct wbsd_host *host, pm_message_t state)
+{
+ BUG_ON(host == NULL);
+
+ return mmc_suspend_host(host->mmc, state);
+}
+
+static int wbsd_resume(struct wbsd_host *host)
+{
+ BUG_ON(host == NULL);
+
+ wbsd_init_device(host);
+
+ return mmc_resume_host(host->mmc);
+}
+
+static int wbsd_platform_suspend(struct platform_device *dev,
+ pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct wbsd_host *host;
int ret;
- if (!mmc)
+ if (mmc == NULL)
return 0;
- DBG("Suspending...\n");
-
- ret = mmc_suspend_host(mmc, state);
- if (!ret)
- return ret;
+ DBGF("Suspending...\n");
host = mmc_priv(mmc);
+ ret = wbsd_suspend(host, state);
+ if (ret)
+ return ret;
+
wbsd_chip_poweroff(host);
return 0;
}
-static int wbsd_resume(struct platform_device *dev)
+static int wbsd_platform_resume(struct platform_device *dev)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
struct wbsd_host *host;
- if (!mmc)
+ if (mmc == NULL)
return 0;
- DBG("Resuming...\n");
+ DBGF("Resuming...\n");
host = mmc_priv(mmc);
@@ -2024,15 +1978,68 @@ static int wbsd_resume(struct platform_device *dev)
*/
mdelay(5);
- wbsd_init_device(host);
+ return wbsd_resume(host);
+}
+
+#ifdef CONFIG_PNP
+
+static int wbsd_pnp_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+{
+ struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+ struct wbsd_host *host;
+
+ if (mmc == NULL)
+ return 0;
+
+ DBGF("Suspending...\n");
+
+ host = mmc_priv(mmc);
+
+ return wbsd_suspend(host, state);
+}
+
+static int wbsd_pnp_resume(struct pnp_dev *pnp_dev)
+{
+ struct mmc_host *mmc = dev_get_drvdata(&pnp_dev->dev);
+ struct wbsd_host *host;
+
+ if (mmc == NULL)
+ return 0;
+
+ DBGF("Resuming...\n");
+
+ host = mmc_priv(mmc);
+
+ /*
+ * See if chip needs to be configured.
+ */
+ if (host->config != 0) {
+ if (!wbsd_chip_validate(host)) {
+ printk(KERN_WARNING DRIVER_NAME
+ ": PnP active but chip not configured! "
+ "You probably have a buggy BIOS. "
+ "Configuring chip manually.\n");
+ wbsd_chip_config(host);
+ }
+ }
- return mmc_resume_host(mmc);
+ /*
+ * Allow device to initialise itself properly.
+ */
+ mdelay(5);
+
+ return wbsd_resume(host);
}
+#endif /* CONFIG_PNP */
+
#else /* CONFIG_PM */
-#define wbsd_suspend NULL
-#define wbsd_resume NULL
+#define wbsd_platform_suspend NULL
+#define wbsd_platform_resume NULL
+
+#define wbsd_pnp_suspend NULL
+#define wbsd_pnp_resume NULL
#endif /* CONFIG_PM */
@@ -2042,8 +2049,8 @@ static struct platform_driver wbsd_driver = {
.probe = wbsd_probe,
.remove = __devexit_p(wbsd_remove),
- .suspend = wbsd_suspend,
- .resume = wbsd_resume,
+ .suspend = wbsd_platform_suspend,
+ .resume = wbsd_platform_resume,
.driver = {
.name = DRIVER_NAME,
},
@@ -2056,6 +2063,9 @@ static struct pnp_driver wbsd_pnp_driver = {
.id_table = pnp_dev_table,
.probe = wbsd_pnp_probe,
.remove = __devexit_p(wbsd_pnp_remove),
+
+ .suspend = wbsd_pnp_suspend,
+ .resume = wbsd_pnp_resume,
};
#endif /* CONFIG_PNP */
@@ -2075,25 +2085,30 @@ static int __init wbsd_drv_init(void)
#ifdef CONFIG_PNP
- if (!nopnp)
- {
+ if (!nopnp) {
result = pnp_register_driver(&wbsd_pnp_driver);
if (result < 0)
return result;
}
-
#endif /* CONFIG_PNP */
- if (nopnp)
- {
+ if (nopnp) {
result = platform_driver_register(&wbsd_driver);
if (result < 0)
return result;
- wbsd_device = platform_device_register_simple(DRIVER_NAME, -1,
- NULL, 0);
- if (IS_ERR(wbsd_device))
- return PTR_ERR(wbsd_device);
+ wbsd_device = platform_device_alloc(DRIVER_NAME, -1);
+ if (!wbsd_device) {
+ platform_driver_unregister(&wbsd_driver);
+ return -ENOMEM;
+ }
+
+ result = platform_device_add(wbsd_device);
+ if (result) {
+ platform_device_put(wbsd_device);
+ platform_driver_unregister(&wbsd_driver);
+ return result;
+ }
}
return 0;
@@ -2108,8 +2123,7 @@ static void __exit wbsd_drv_exit(void)
#endif /* CONFIG_PNP */
- if (nopnp)
- {
+ if (nopnp) {
platform_device_unregister(wbsd_device);
platform_driver_unregister(&wbsd_driver);
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index eafa23f5cbd6..effa0d7a73ac 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -31,6 +31,7 @@ config MTD_JEDECPROBE
config MTD_GEN_PROBE
tristate
+ select OBSOLETE_INTERMODULE
config MTD_CFI_ADV_OPTIONS
bool "Flash chip driver advanced configuration options"
@@ -259,7 +260,7 @@ config MTD_ABSENT
with this driver will return -ENODEV upon access.
config MTD_OBSOLETE_CHIPS
- depends on MTD && BROKEN
+ depends on MTD
bool "Older (theoretically obsoleted now) drivers for non-CFI chips"
help
This option does not enable any code directly, but will allow you to
@@ -272,7 +273,7 @@ config MTD_OBSOLETE_CHIPS
config MTD_AMDSTD
tristate "AMD compatible flash chip support (non-CFI)"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
This option enables support for flash chips using AMD-compatible
commands, including some which are not CFI-compatible and hence
@@ -290,7 +291,7 @@ config MTD_SHARP
config MTD_JEDEC
tristate "JEDEC device support"
- depends on MTD && MTD_OBSOLETE_CHIPS
+ depends on MTD && MTD_OBSOLETE_CHIPS && BROKEN
help
Enable older older JEDEC flash interface devices for self
programming flash. It is commonly used in older AMD chips. It is
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 9a2aa4033c6a..dd628cb51e31 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -47,6 +47,22 @@ config MTD_MS02NV
accelerator. Say Y here if you have a DECstation 5000/2x0 or a
DECsystem 5900 equipped with such a module.
+config MTD_DATAFLASH
+ tristate "Support for AT45xxx DataFlash"
+ depends on MTD && SPI_MASTER && EXPERIMENTAL
+ help
+ This enables access to AT45xxx DataFlash chips, using SPI.
+ Sometimes DataFlash chips are packaged inside MMC-format
+ cards; at this writing, the MMC stack won't handle those.
+
+config MTD_M25P80
+ tristate "Support for M25 SPI Flash"
+ depends on MTD && SPI_MASTER && EXPERIMENTAL
+ help
+ This enables access to ST M25P80 and similar SPI flash chips,
+ used for program and data storage. Set up your spi devices
+ with the right board-specific platform data.
+
config MTD_SLRAM
tristate "Uncached system RAM"
depends on MTD
@@ -202,6 +218,7 @@ config MTD_DOC2001PLUS
config MTD_DOCPROBE
tristate
select MTD_DOCECC
+ select OBSOLETE_INTERMODULE
config MTD_DOCECC
tristate
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index e38db348057d..7c5ed2178380 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -23,3 +23,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
+obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
+obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index be5e88b3888d..e4345cf744a2 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -138,7 +138,7 @@ static inline int DoC_WaitReady(struct DiskOnChip *doc)
bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command,
+static int DoC_Command(struct DiskOnChip *doc, unsigned char command,
unsigned char xtraflags)
{
void __iomem *docptr = doc->virtadr;
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index fcb28a6fd89f..681a9c73a2a3 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -103,7 +103,7 @@ static inline int DoC_WaitReady(void __iomem * docptr)
with the internal pipeline. Each of 4 delay cycles (read from the NOP register) is
required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */
-static inline void DoC_Command(void __iomem * docptr, unsigned char command,
+static void DoC_Command(void __iomem * docptr, unsigned char command,
unsigned char xtraflags)
{
/* Assert the CLE (Command Latch Enable) line to the flash chip */
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 0595cc7324b2..5f57f29efee4 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -118,7 +118,7 @@ static inline void DoC_CheckASIC(void __iomem * docptr)
/* DoC_Command: Send a flash command to the flash chip through the Flash
* command register. Need 2 Write Pipeline Terminates to complete send.
*/
-static inline void DoC_Command(void __iomem * docptr, unsigned char command,
+static void DoC_Command(void __iomem * docptr, unsigned char command,
unsigned char xtraflags)
{
WriteDOC(command, docptr, Mplus_FlashCmd);
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
new file mode 100644
index 000000000000..d5f24089be71
--- /dev/null
+++ b/drivers/mtd/devices/m25p80.c
@@ -0,0 +1,582 @@
+/*
+ * MTD SPI driver for ST M25Pxx flash chips
+ *
+ * Author: Mike Lavender, mike@steroidmicros.com
+ *
+ * Copyright (c) 2005, Intec Automation Inc.
+ *
+ * Some parts are based on lart.c by Abraham Van Der Merwe
+ *
+ * Cleaned up and generalized based on mtd_dataflash.c
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <asm/semaphore.h>
+
+
+/* NOTE: AT 25F and SST 25LF series are very similar,
+ * but commands for sector erase and chip id differ...
+ */
+
+#define FLASH_PAGESIZE 256
+
+/* Flash opcodes. */
+#define OPCODE_WREN 6 /* Write enable */
+#define OPCODE_RDSR 5 /* Read status register */
+#define OPCODE_READ 3 /* Read data bytes */
+#define OPCODE_PP 2 /* Page program */
+#define OPCODE_SE 0xd8 /* Sector erase */
+#define OPCODE_RES 0xab /* Read Electronic Signature */
+#define OPCODE_RDID 0x9f /* Read JEDEC ID */
+
+/* Status Register bits. */
+#define SR_WIP 1 /* Write in progress */
+#define SR_WEL 2 /* Write enable latch */
+#define SR_BP0 4 /* Block protect 0 */
+#define SR_BP1 8 /* Block protect 1 */
+#define SR_BP2 0x10 /* Block protect 2 */
+#define SR_SRWD 0x80 /* SR write protect */
+
+/* Define max times to check status register before we give up. */
+#define MAX_READY_WAIT_COUNT 100000
+
+
+#ifdef CONFIG_MTD_PARTITIONS
+#define mtd_has_partitions() (1)
+#else
+#define mtd_has_partitions() (0)
+#endif
+
+/****************************************************************************/
+
+struct m25p {
+ struct spi_device *spi;
+ struct semaphore lock;
+ struct mtd_info mtd;
+ unsigned partitioned;
+ u8 command[4];
+};
+
+static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct m25p, mtd);
+}
+
+/****************************************************************************/
+
+/*
+ * Internal helper functions
+ */
+
+/*
+ * Read the status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_sr(struct m25p *flash)
+{
+ ssize_t retval;
+ u8 code = OPCODE_RDSR;
+ u8 val;
+
+ retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
+
+ if (retval < 0) {
+ dev_err(&flash->spi->dev, "error %d reading SR\n",
+ (int) retval);
+ return retval;
+ }
+
+ return val;
+}
+
+
+/*
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static inline int write_enable(struct m25p *flash)
+{
+ u8 code = OPCODE_WREN;
+
+ return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+
+/*
+ * Service routine to read status register until ready, or timeout occurs.
+ * Returns non-zero if error.
+ */
+static int wait_till_ready(struct m25p *flash)
+{
+ int count;
+ int sr;
+
+ /* one chip guarantees max 5 msec wait here after page writes,
+ * but potentially three seconds (!) after page erase.
+ */
+ for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
+ if ((sr = read_sr(flash)) < 0)
+ break;
+ else if (!(sr & SR_WIP))
+ return 0;
+
+ /* REVISIT sometimes sleeping would be best */
+ }
+
+ return 1;
+}
+
+
+/*
+ * Erase one sector of flash memory at offset ``offset'' which is any
+ * address within the sector which should be erased.
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int erase_sector(struct m25p *flash, u32 offset)
+{
+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
+ __FUNCTION__, offset);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+ return 1;
+
+ /* Send write enable, then erase commands. */
+ write_enable(flash);
+
+ /* Set up command buffer. */
+ flash->command[0] = OPCODE_SE;
+ flash->command[1] = offset >> 16;
+ flash->command[2] = offset >> 8;
+ flash->command[3] = offset;
+
+ spi_write(flash->spi, flash->command, sizeof(flash->command));
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+ * MTD implementation
+ */
+
+/*
+ * Erase an address range on the flash chip. The address range may extend
+ * one or more erase sectors. Return an error is there is a problem erasing.
+ */
+static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ u32 addr,len;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "at",
+ (u32)instr->addr, instr->len);
+
+ /* sanity checks */
+ if (instr->addr + instr->len > flash->mtd.size)
+ return -EINVAL;
+ if ((instr->addr % mtd->erasesize) != 0
+ || (instr->len % mtd->erasesize) != 0) {
+ return -EINVAL;
+ }
+
+ addr = instr->addr;
+ len = instr->len;
+
+ down(&flash->lock);
+
+ /* now erase those sectors */
+ while (len) {
+ if (erase_sector(flash, addr)) {
+ instr->state = MTD_ERASE_FAILED;
+ up(&flash->lock);
+ return -EIO;
+ }
+
+ addr += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
+
+ up(&flash->lock);
+
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+/*
+ * Read an address range from the flash chip. The address range
+ * may be any size provided it is within the physical boundaries.
+ */
+static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "from",
+ (u32)from, len);
+
+ /* sanity checks */
+ if (!len)
+ return 0;
+
+ if (from + len > flash->mtd.size)
+ return -EINVAL;
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+ t[0].len = sizeof(flash->command);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].rx_buf = buf;
+ t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ /* Byte count starts at zero. */
+ if (retlen)
+ *retlen = 0;
+
+ down(&flash->lock);
+
+ /* Wait till previous write/erase is done. */
+ if (wait_till_ready(flash)) {
+ /* REVISIT status return?? */
+ up(&flash->lock);
+ return 1;
+ }
+
+ /* NOTE: OPCODE_FAST_READ (if available) is faster... */
+
+ /* Set up the write data buffer. */
+ flash->command[0] = OPCODE_READ;
+ flash->command[1] = from >> 16;
+ flash->command[2] = from >> 8;
+ flash->command[3] = from;
+
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+
+ up(&flash->lock);
+
+ return 0;
+}
+
+/*
+ * Write an address range to the flash chip. Data must be written in
+ * FLASH_PAGESIZE chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ */
+static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct m25p *flash = mtd_to_m25p(mtd);
+ u32 page_offset, page_size;
+ struct spi_transfer t[2];
+ struct spi_message m;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ flash->spi->dev.bus_id, __FUNCTION__, "to",
+ (u32)to, len);
+
+ if (retlen)
+ *retlen = 0;
+
+ /* sanity checks */
+ if (!len)
+ return(0);
+
+ if (to + len > flash->mtd.size)
+ return -EINVAL;
+
+ spi_message_init(&m);
+ memset(t, 0, (sizeof t));
+
+ t[0].tx_buf = flash->command;
+ t[0].len = sizeof(flash->command);
+ spi_message_add_tail(&t[0], &m);
+
+ t[1].tx_buf = buf;
+ spi_message_add_tail(&t[1], &m);
+
+ down(&flash->lock);
+
+ /* Wait until finished previous write command. */
+ if (wait_till_ready(flash))
+ return 1;
+
+ write_enable(flash);
+
+ /* Set up the opcode in the write buffer. */
+ flash->command[0] = OPCODE_PP;
+ flash->command[1] = to >> 16;
+ flash->command[2] = to >> 8;
+ flash->command[3] = to;
+
+ /* what page do we start with? */
+ page_offset = to % FLASH_PAGESIZE;
+
+ /* do all the bytes fit onto one page? */
+ if (page_offset + len <= FLASH_PAGESIZE) {
+ t[1].len = len;
+
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+ } else {
+ u32 i;
+
+ /* the size of data remaining on the first page */
+ page_size = FLASH_PAGESIZE - page_offset;
+
+ t[1].len = page_size;
+ spi_sync(flash->spi, &m);
+
+ *retlen = m.actual_length - sizeof(flash->command);
+
+ /* write everything in PAGESIZE chunks */
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+ if (page_size > FLASH_PAGESIZE)
+ page_size = FLASH_PAGESIZE;
+
+ /* write the next page to flash */
+ flash->command[1] = (to + i) >> 16;
+ flash->command[2] = (to + i) >> 8;
+ flash->command[3] = (to + i);
+
+ t[1].tx_buf = buf + i;
+ t[1].len = page_size;
+
+ wait_till_ready(flash);
+
+ write_enable(flash);
+
+ spi_sync(flash->spi, &m);
+
+ if (retlen)
+ *retlen += m.actual_length
+ - sizeof(flash->command);
+ }
+ }
+
+ up(&flash->lock);
+
+ return 0;
+}
+
+
+/****************************************************************************/
+
+/*
+ * SPI device driver setup and teardown
+ */
+
+struct flash_info {
+ char *name;
+ u8 id;
+ u16 jedec_id;
+ unsigned sector_size;
+ unsigned n_sectors;
+};
+
+static struct flash_info __devinitdata m25p_data [] = {
+ /* REVISIT: fill in JEDEC ids, for parts that have them */
+ { "m25p05", 0x05, 0x0000, 32 * 1024, 2 },
+ { "m25p10", 0x10, 0x0000, 32 * 1024, 4 },
+ { "m25p20", 0x11, 0x0000, 64 * 1024, 4 },
+ { "m25p40", 0x12, 0x0000, 64 * 1024, 8 },
+ { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
+ { "m25p16", 0x14, 0x0000, 64 * 1024, 32 },
+ { "m25p32", 0x15, 0x0000, 64 * 1024, 64 },
+ { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
+};
+
+/*
+ * board specific setup should have ensured the SPI clock used here
+ * matches what the READ command supports, at least until this driver
+ * understands FAST_READ (for clocks over 25 MHz).
+ */
+static int __devinit m25p_probe(struct spi_device *spi)
+{
+ struct flash_platform_data *data;
+ struct m25p *flash;
+ struct flash_info *info;
+ unsigned i;
+
+ /* Platform data helps sort out which chip type we have, as
+ * well as how this board partitions it.
+ */
+ data = spi->dev.platform_data;
+ if (!data || !data->type) {
+ /* FIXME some chips can identify themselves with RES
+ * or JEDEC get-id commands. Try them ...
+ */
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
+ flash->spi->dev.bus_id);
+ return -ENODEV;
+ }
+
+ for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
+ if (strcmp(data->type, info->name) == 0)
+ break;
+ }
+ if (i == ARRAY_SIZE(m25p_data)) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
+ flash->spi->dev.bus_id, data->type);
+ return -ENODEV;
+ }
+
+ flash = kzalloc(sizeof *flash, SLAB_KERNEL);
+ if (!flash)
+ return -ENOMEM;
+
+ flash->spi = spi;
+ init_MUTEX(&flash->lock);
+ dev_set_drvdata(&spi->dev, flash);
+
+ if (data->name)
+ flash->mtd.name = data->name;
+ else
+ flash->mtd.name = spi->dev.bus_id;
+
+ flash->mtd.type = MTD_NORFLASH;
+ flash->mtd.flags = MTD_CAP_NORFLASH;
+ flash->mtd.size = info->sector_size * info->n_sectors;
+ flash->mtd.erasesize = info->sector_size;
+ flash->mtd.erase = m25p80_erase;
+ flash->mtd.read = m25p80_read;
+ flash->mtd.write = m25p80_write;
+
+ dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
+ flash->mtd.size / 1024);
+
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "mtd .name = %s, .size = 0x%.8x (%uM) "
+ ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
+ flash->mtd.name,
+ flash->mtd.size, flash->mtd.size / (1024*1024),
+ flash->mtd.erasesize, flash->mtd.erasesize / 1024,
+ flash->mtd.numeraseregions);
+
+ if (flash->mtd.numeraseregions)
+ for (i = 0; i < flash->mtd.numeraseregions; i++)
+ DEBUG(MTD_DEBUG_LEVEL2,
+ "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
+ ".erasesize = 0x%.8x (%uK), "
+ ".numblocks = %d }\n",
+ i, flash->mtd.eraseregions[i].offset,
+ flash->mtd.eraseregions[i].erasesize,
+ flash->mtd.eraseregions[i].erasesize / 1024,
+ flash->mtd.eraseregions[i].numblocks);
+
+
+ /* partitions should match sector boundaries; and it may be good to
+ * use readonly partitions for writeprotected sectors (BP2..BP0).
+ */
+ if (mtd_has_partitions()) {
+ struct mtd_partition *parts = NULL;
+ int nr_parts = 0;
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL, };
+
+ nr_parts = parse_mtd_partitions(&flash->mtd,
+ part_probes, &parts, 0);
+#endif
+
+ if (nr_parts <= 0 && data && data->parts) {
+ parts = data->parts;
+ nr_parts = data->nr_parts;
+ }
+
+ if (nr_parts > 0) {
+ for (i = 0; i < data->nr_parts; i++) {
+ DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
+ "{.name = %s, .offset = 0x%.8x, "
+ ".size = 0x%.8x (%uK) }\n",
+ i, data->parts[i].name,
+ data->parts[i].offset,
+ data->parts[i].size,
+ data->parts[i].size / 1024);
+ }
+ flash->partitioned = 1;
+ return add_mtd_partitions(&flash->mtd, parts, nr_parts);
+ }
+ } else if (data->nr_parts)
+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+ data->nr_parts, data->name);
+
+ return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
+}
+
+
+static int __devexit m25p_remove(struct spi_device *spi)
+{
+ struct m25p *flash = dev_get_drvdata(&spi->dev);
+ int status;
+
+ /* Clean up MTD stuff. */
+ if (mtd_has_partitions() && flash->partitioned)
+ status = del_mtd_partitions(&flash->mtd);
+ else
+ status = del_mtd_device(&flash->mtd);
+ if (status == 0)
+ kfree(flash);
+ return 0;
+}
+
+
+static struct spi_driver m25p80_driver = {
+ .driver = {
+ .name = "m25p80",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = m25p_probe,
+ .remove = __devexit_p(m25p_remove),
+};
+
+
+static int m25p80_init(void)
+{
+ return spi_register_driver(&m25p80_driver);
+}
+
+
+static void m25p80_exit(void)
+{
+ spi_unregister_driver(&m25p80_driver);
+}
+
+
+module_init(m25p80_init);
+module_exit(m25p80_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mike Lavender");
+MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
new file mode 100644
index 000000000000..155737e7483f
--- /dev/null
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -0,0 +1,629 @@
+/*
+ * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
+ *
+ * Largely derived from at91_dataflash.c:
+ * Copyright (C) 2003-2005 SAN People (Pty) Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+*/
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+
+/*
+ * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in
+ * each chip, which may be used for double buffered I/O; but this driver
+ * doesn't (yet) use these for any kind of i/o overlap or prefetching.
+ *
+ * Sometimes DataFlash is packaged in MMC-format cards, although the
+ * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash
+ * protocols during enumeration.
+ */
+
+#define CONFIG_DATAFLASH_WRITE_VERIFY
+
+/* reads can bypass the buffers */
+#define OP_READ_CONTINUOUS 0xE8
+#define OP_READ_PAGE 0xD2
+
+/* group B requests can run even while status reports "busy" */
+#define OP_READ_STATUS 0xD7 /* group B */
+
+/* move data between host and buffer */
+#define OP_READ_BUFFER1 0xD4 /* group B */
+#define OP_READ_BUFFER2 0xD6 /* group B */
+#define OP_WRITE_BUFFER1 0x84 /* group B */
+#define OP_WRITE_BUFFER2 0x87 /* group B */
+
+/* erasing flash */
+#define OP_ERASE_PAGE 0x81
+#define OP_ERASE_BLOCK 0x50
+
+/* move data between buffer and flash */
+#define OP_TRANSFER_BUF1 0x53
+#define OP_TRANSFER_BUF2 0x55
+#define OP_MREAD_BUFFER1 0xD4
+#define OP_MREAD_BUFFER2 0xD6
+#define OP_MWERASE_BUFFER1 0x83
+#define OP_MWERASE_BUFFER2 0x86
+#define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */
+#define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */
+
+/* write to buffer, then write-erase to flash */
+#define OP_PROGRAM_VIA_BUF1 0x82
+#define OP_PROGRAM_VIA_BUF2 0x85
+
+/* compare buffer to flash */
+#define OP_COMPARE_BUF1 0x60
+#define OP_COMPARE_BUF2 0x61
+
+/* read flash to buffer, then write-erase to flash */
+#define OP_REWRITE_VIA_BUF1 0x58
+#define OP_REWRITE_VIA_BUF2 0x59
+
+/* newer chips report JEDEC manufacturer and device IDs; chip
+ * serial number and OTP bits; and per-sector writeprotect.
+ */
+#define OP_READ_ID 0x9F
+#define OP_READ_SECURITY 0x77
+#define OP_WRITE_SECURITY 0x9A /* OTP bits */
+
+
+struct dataflash {
+ u8 command[4];
+ char name[24];
+
+ unsigned partitioned:1;
+
+ unsigned short page_offset; /* offset in flash address */
+ unsigned int page_size; /* of bytes per page */
+
+ struct semaphore lock;
+ struct spi_device *spi;
+
+ struct mtd_info mtd;
+};
+
+#ifdef CONFIG_MTD_PARTITIONS
+#define mtd_has_partitions() (1)
+#else
+#define mtd_has_partitions() (0)
+#endif
+
+/* ......................................................................... */
+
+/*
+ * Return the status of the DataFlash device.
+ */
+static inline int dataflash_status(struct spi_device *spi)
+{
+ /* NOTE: at45db321c over 25 MHz wants to write
+ * a dummy byte after the opcode...
+ */
+ return spi_w8r8(spi, OP_READ_STATUS);
+}
+
+/*
+ * Poll the DataFlash device until it is READY.
+ * This usually takes 5-20 msec or so; more for sector erase.
+ */
+static int dataflash_waitready(struct spi_device *spi)
+{
+ int status;
+
+ for (;;) {
+ status = dataflash_status(spi);
+ if (status < 0) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+ spi->dev.bus_id, status);
+ status = 0;
+ }
+
+ if (status & (1 << 7)) /* RDY/nBSY */
+ return status;
+
+ msleep(3);
+ }
+}
+
+/* ......................................................................... */
+
+/*
+ * Erase pages of flash.
+ */
+static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_device *spi = priv->spi;
+ struct spi_transfer x = { .tx_dma = 0, };
+ struct spi_message msg;
+ unsigned blocksize = priv->page_size << 3;
+ u8 *command;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
+ spi->dev.bus_id,
+ instr->addr, instr->len);
+
+ /* Sanity checks */
+ if ((instr->addr + instr->len) > mtd->size
+ || (instr->len % priv->page_size) != 0
+ || (instr->addr % priv->page_size) != 0)
+ return -EINVAL;
+
+ spi_message_init(&msg);
+
+ x.tx_buf = command = priv->command;
+ x.len = 4;
+ spi_message_add_tail(&x, &msg);
+
+ down(&priv->lock);
+ while (instr->len > 0) {
+ unsigned int pageaddr;
+ int status;
+ int do_block;
+
+ /* Calculate flash page address; use block erase (for speed) if
+ * we're at a block boundary and need to erase the whole block.
+ */
+ pageaddr = instr->addr / priv->page_size;
+ do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize;
+ pageaddr = pageaddr << priv->page_offset;
+
+ command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE;
+ command[1] = (u8)(pageaddr >> 16);
+ command[2] = (u8)(pageaddr >> 8);
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
+ do_block ? "block" : "page",
+ command[0], command[1], command[2], command[3],
+ pageaddr);
+
+ status = spi_sync(spi, &msg);
+ (void) dataflash_waitready(spi);
+
+ if (status < 0) {
+ printk(KERN_ERR "%s: erase %x, err %d\n",
+ spi->dev.bus_id, pageaddr, status);
+ /* REVISIT: can retry instr->retries times; or
+ * giveup and instr->fail_addr = instr->addr;
+ */
+ continue;
+ }
+
+ if (do_block) {
+ instr->addr += blocksize;
+ instr->len -= blocksize;
+ } else {
+ instr->addr += priv->page_size;
+ instr->len -= priv->page_size;
+ }
+ }
+ up(&priv->lock);
+
+ /* Inform MTD subsystem that erase is complete */
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+/*
+ * Read from the DataFlash device.
+ * from : Start offset in flash device
+ * len : Amount to read
+ * retlen : About of data actually read
+ * buf : Buffer containing the data
+ */
+static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_transfer x[2] = { { .tx_dma = 0, }, };
+ struct spi_message msg;
+ unsigned int addr;
+ u8 *command;
+ int status;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
+ priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len));
+
+ *retlen = 0;
+
+ /* Sanity checks */
+ if (!len)
+ return 0;
+ if (from + len > mtd->size)
+ return -EINVAL;
+
+ /* Calculate flash page/byte address */
+ addr = (((unsigned)from / priv->page_size) << priv->page_offset)
+ + ((unsigned)from % priv->page_size);
+
+ command = priv->command;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ spi_message_init(&msg);
+
+ x[0].tx_buf = command;
+ x[0].len = 8;
+ spi_message_add_tail(&x[0], &msg);
+
+ x[1].rx_buf = buf;
+ x[1].len = len;
+ spi_message_add_tail(&x[1], &msg);
+
+ down(&priv->lock);
+
+ /* Continuous read, max clock = f(car) which may be less than
+ * the peak rate available. Some chips support commands with
+ * fewer "don't care" bytes. Both buffers stay unchanged.
+ */
+ command[0] = OP_READ_CONTINUOUS;
+ command[1] = (u8)(addr >> 16);
+ command[2] = (u8)(addr >> 8);
+ command[3] = (u8)(addr >> 0);
+ /* plus 4 "don't care" bytes */
+
+ status = spi_sync(priv->spi, &msg);
+ up(&priv->lock);
+
+ if (status >= 0) {
+ *retlen = msg.actual_length - 8;
+ status = 0;
+ } else
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+ priv->spi->dev.bus_id,
+ (unsigned)from, (unsigned)(from + len),
+ status);
+ return status;
+}
+
+/*
+ * Write to the DataFlash device.
+ * to : Start offset in flash device
+ * len : Amount to write
+ * retlen : Amount of data actually written
+ * buf : Buffer containing the data
+ */
+static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct dataflash *priv = (struct dataflash *)mtd->priv;
+ struct spi_device *spi = priv->spi;
+ struct spi_transfer x[2] = { { .tx_dma = 0, }, };
+ struct spi_message msg;
+ unsigned int pageaddr, addr, offset, writelen;
+ size_t remaining = len;
+ u_char *writebuf = (u_char *) buf;
+ int status = -EINVAL;
+ u8 *command;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
+ spi->dev.bus_id, (unsigned)to, (unsigned)(to + len));
+
+ *retlen = 0;
+
+ /* Sanity checks */
+ if (!len)
+ return 0;
+ if ((to + len) > mtd->size)
+ return -EINVAL;
+
+ spi_message_init(&msg);
+
+ x[0].tx_buf = command = priv->command;
+ x[0].len = 4;
+ spi_message_add_tail(&x[0], &msg);
+
+ pageaddr = ((unsigned)to / priv->page_size);
+ offset = ((unsigned)to % priv->page_size);
+ if (offset + len > priv->page_size)
+ writelen = priv->page_size - offset;
+ else
+ writelen = len;
+
+ down(&priv->lock);
+ while (remaining > 0) {
+ DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+ pageaddr, offset, writelen);
+
+ /* REVISIT:
+ * (a) each page in a sector must be rewritten at least
+ * once every 10K sibling erase/program operations.
+ * (b) for pages that are already erased, we could
+ * use WRITE+MWRITE not PROGRAM for ~30% speedup.
+ * (c) WRITE to buffer could be done while waiting for
+ * a previous MWRITE/MWERASE to complete ...
+ * (d) error handling here seems to be mostly missing.
+ *
+ * Two persistent bits per page, plus a per-sector counter,
+ * could support (a) and (b) ... we might consider using
+ * the second half of sector zero, which is just one block,
+ * to track that state. (On AT91, that sector should also
+ * support boot-from-DataFlash.)
+ */
+
+ addr = pageaddr << priv->page_offset;
+
+ /* (1) Maybe transfer partial page to Buffer1 */
+ if (writelen != priv->page_size) {
+ command[0] = OP_TRANSFER_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ status = spi_sync(spi, &msg);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
+ spi->dev.bus_id, addr, status);
+
+ (void) dataflash_waitready(priv->spi);
+ }
+
+ /* (2) Program full page via Buffer1 */
+ addr += offset;
+ command[0] = OP_PROGRAM_VIA_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = (addr & 0x000000FF);
+
+ DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ x[1].tx_buf = writebuf;
+ x[1].len = writelen;
+ spi_message_add_tail(x + 1, &msg);
+ status = spi_sync(spi, &msg);
+ spi_transfer_del(x + 1);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
+ spi->dev.bus_id, addr, writelen, status);
+
+ (void) dataflash_waitready(priv->spi);
+
+
+#ifdef CONFIG_DATAFLASH_WRITE_VERIFY
+
+ /* (3) Compare to Buffer1 */
+ addr = pageaddr << priv->page_offset;
+ command[0] = OP_COMPARE_BUF1;
+ command[1] = (addr & 0x00FF0000) >> 16;
+ command[2] = (addr & 0x0000FF00) >> 8;
+ command[3] = 0;
+
+ DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
+ command[0], command[1], command[2], command[3]);
+
+ status = spi_sync(spi, &msg);
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
+ spi->dev.bus_id, addr, status);
+
+ status = dataflash_waitready(priv->spi);
+
+ /* Check result of the compare operation */
+ if ((status & (1 << 6)) == 1) {
+ printk(KERN_ERR "%s: compare page %u, err %d\n",
+ spi->dev.bus_id, pageaddr, status);
+ remaining = 0;
+ status = -EIO;
+ break;
+ } else
+ status = 0;
+
+#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */
+
+ remaining = remaining - writelen;
+ pageaddr++;
+ offset = 0;
+ writebuf += writelen;
+ *retlen += writelen;
+
+ if (remaining > priv->page_size)
+ writelen = priv->page_size;
+ else
+ writelen = remaining;
+ }
+ up(&priv->lock);
+
+ return status;
+}
+
+/* ......................................................................... */
+
+/*
+ * Register DataFlash device with MTD subsystem.
+ */
+static int __devinit
+add_dataflash(struct spi_device *spi, char *name,
+ int nr_pages, int pagesize, int pageoffset)
+{
+ struct dataflash *priv;
+ struct mtd_info *device;
+ struct flash_platform_data *pdata = spi->dev.platform_data;
+
+ priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ init_MUTEX(&priv->lock);
+ priv->spi = spi;
+ priv->page_size = pagesize;
+ priv->page_offset = pageoffset;
+
+ /* name must be usable with cmdlinepart */
+ sprintf(priv->name, "spi%d.%d-%s",
+ spi->master->bus_num, spi->chip_select,
+ name);
+
+ device = &priv->mtd;
+ device->name = (pdata && pdata->name) ? pdata->name : priv->name;
+ device->size = nr_pages * pagesize;
+ device->erasesize = pagesize;
+ device->owner = THIS_MODULE;
+ device->type = MTD_DATAFLASH;
+ device->flags = MTD_CAP_NORFLASH;
+ device->erase = dataflash_erase;
+ device->read = dataflash_read;
+ device->write = dataflash_write;
+ device->priv = priv;
+
+ dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024);
+ dev_set_drvdata(&spi->dev, priv);
+
+ if (mtd_has_partitions()) {
+ struct mtd_partition *parts;
+ int nr_parts = 0;
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_probes[] = { "cmdlinepart", NULL, };
+
+ nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0);
+#endif
+
+ if (nr_parts <= 0 && pdata && pdata->parts) {
+ parts = pdata->parts;
+ nr_parts = pdata->nr_parts;
+ }
+
+ if (nr_parts > 0) {
+ priv->partitioned = 1;
+ return add_mtd_partitions(device, parts, nr_parts);
+ }
+ } else if (pdata && pdata->nr_parts)
+ dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
+ pdata->nr_parts, device->name);
+
+ return add_mtd_device(device) == 1 ? -ENODEV : 0;
+}
+
+/*
+ * Detect and initialize DataFlash device:
+ *
+ * Device Density ID code #Pages PageSize Offset
+ * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9
+ * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9
+ * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9
+ * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9
+ * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10
+ * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10
+ * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11
+ * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11
+ */
+static int __devinit dataflash_probe(struct spi_device *spi)
+{
+ int status;
+
+ status = dataflash_status(spi);
+ if (status <= 0 || status == 0xff) {
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
+ spi->dev.bus_id, status);
+ if (status == 0xff)
+ status = -ENODEV;
+ return status;
+ }
+
+ /* if there's a device there, assume it's dataflash.
+ * board setup should have set spi->max_speed_max to
+ * match f(car) for continuous reads, mode 0 or 3.
+ */
+ switch (status & 0x3c) {
+ case 0x0c: /* 0 0 1 1 x x */
+ status = add_dataflash(spi, "AT45DB011B", 512, 264, 9);
+ break;
+ case 0x14: /* 0 1 0 1 x x */
+ status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9);
+ break;
+ case 0x1c: /* 0 1 1 1 x x */
+ status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9);
+ break;
+ case 0x24: /* 1 0 0 1 x x */
+ status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9);
+ break;
+ case 0x2c: /* 1 0 1 1 x x */
+ status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10);
+ break;
+ case 0x34: /* 1 1 0 1 x x */
+ status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10);
+ break;
+ case 0x38: /* 1 1 1 x x x */
+ case 0x3c:
+ status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11);
+ break;
+ /* obsolete AT45DB1282 not (yet?) supported */
+ default:
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
+ spi->dev.bus_id, status & 0x3c);
+ status = -ENODEV;
+ }
+
+ if (status < 0)
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
+ spi->dev.bus_id, status);
+
+ return status;
+}
+
+static int __devexit dataflash_remove(struct spi_device *spi)
+{
+ struct dataflash *flash = dev_get_drvdata(&spi->dev);
+ int status;
+
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
+
+ if (mtd_has_partitions() && flash->partitioned)
+ status = del_mtd_partitions(&flash->mtd);
+ else
+ status = del_mtd_device(&flash->mtd);
+ if (status == 0)
+ kfree(flash);
+ return status;
+}
+
+static struct spi_driver dataflash_driver = {
+ .driver = {
+ .name = "mtd_dataflash",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+
+ .probe = dataflash_probe,
+ .remove = __devexit_p(dataflash_remove),
+
+ /* FIXME: investigate suspend and resume... */
+};
+
+static int __init dataflash_init(void)
+{
+ return spi_register_driver(&dataflash_driver);
+}
+module_init(dataflash_init);
+
+static void __exit dataflash_exit(void)
+{
+ spi_unregister_driver(&dataflash_driver);
+}
+module_exit(dataflash_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrew Victor, David Brownell");
+MODULE_DESCRIPTION("MTD DataFlash driver");
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b9b77cf39a18..7abd7fee0dda 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -473,14 +473,6 @@ config MTD_IXP2000
IXDP425 and Coyote. If you have an IXP2000 based board and
would like to use the flash chips on it, say 'Y'.
-config MTD_EPXA10DB
- tristate "CFI Flash device mapped on Epxa10db"
- depends on MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
- help
- This enables support for the flash devices on the Altera
- Excalibur XA10 Development Board. If you are building a kernel
- for on of these boards then you should say 'Y' otherwise say 'N'.
-
config MTD_FORTUNET
tristate "CFI Flash device mapped on the FortuNet board"
depends on MTD_CFI && MTD_PARTITIONS && SA1100_FORTUNET
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 2f7e254912f0..ab71f172eb77 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o
obj-$(CONFIG_MTD_DC21285) += dc21285.o
obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o
-obj-$(CONFIG_MTD_EPXA10DB) += epxa10db-flash.o
obj-$(CONFIG_MTD_IQ80310) += iq80310.o
obj-$(CONFIG_MTD_L440GX) += l440gx.o
obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o
diff --git a/drivers/mtd/maps/epxa10db-flash.c b/drivers/mtd/maps/epxa10db-flash.c
deleted file mode 100644
index 265b079fe934..000000000000
--- a/drivers/mtd/maps/epxa10db-flash.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Flash memory access on EPXA based devices
- *
- * (C) 2000 Nicolas Pitre <nico@cam.org>
- * Copyright (C) 2001 Altera Corporation
- * Copyright (C) 2001 Red Hat, Inc.
- *
- * $Id: epxa10db-flash.c,v 1.15 2005/11/07 11:14:27 gleixner Exp $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public 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/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/io.h>
-#include <asm/hardware.h>
-
-#ifdef CONFIG_EPXA10DB
-#define BOARD_NAME "EPXA10DB"
-#else
-#define BOARD_NAME "EPXA1DB"
-#endif
-
-static int nr_parts = 0;
-static struct mtd_partition *parts;
-
-static struct mtd_info *mymtd;
-
-static int epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts);
-
-
-static struct map_info epxa_map = {
- .name = "EPXA flash",
- .size = FLASH_SIZE,
- .bankwidth = 2,
- .phys = FLASH_START,
-};
-
-static const char *probes[] = { "RedBoot", "afs", NULL };
-
-static int __init epxa_mtd_init(void)
-{
- int i;
-
- printk(KERN_NOTICE "%s flash device: 0x%x at 0x%x\n", BOARD_NAME, FLASH_SIZE, FLASH_START);
-
- epxa_map.virt = ioremap(FLASH_START, FLASH_SIZE);
- if (!epxa_map.virt) {
- printk("Failed to ioremap %s flash\n",BOARD_NAME);
- return -EIO;
- }
- simple_map_init(&epxa_map);
-
- mymtd = do_map_probe("cfi_probe", &epxa_map);
- if (!mymtd) {
- iounmap((void *)epxa_map.virt);
- return -ENXIO;
- }
-
- mymtd->owner = THIS_MODULE;
-
- /* Unlock the flash device. */
- if(mymtd->unlock){
- for (i=0; i<mymtd->numeraseregions;i++){
- int j;
- for(j=0;j<mymtd->eraseregions[i].numblocks;j++){
- mymtd->unlock(mymtd,mymtd->eraseregions[i].offset + j * mymtd->eraseregions[i].erasesize,mymtd->eraseregions[i].erasesize);
- }
- }
- }
-
-#ifdef CONFIG_MTD_PARTITIONS
- nr_parts = parse_mtd_partitions(mymtd, probes, &parts, 0);
-
- if (nr_parts > 0) {
- add_mtd_partitions(mymtd, parts, nr_parts);
- return 0;
- }
-#endif
- /* No recognised partitioning schemes found - use defaults */
- nr_parts = epxa_default_partitions(mymtd, &parts);
- if (nr_parts > 0) {
- add_mtd_partitions(mymtd, parts, nr_parts);
- return 0;
- }
-
- /* If all else fails... */
- add_mtd_device(mymtd);
- return 0;
-}
-
-static void __exit epxa_mtd_cleanup(void)
-{
- if (mymtd) {
- if (nr_parts)
- del_mtd_partitions(mymtd);
- else
- del_mtd_device(mymtd);
- map_destroy(mymtd);
- }
- if (epxa_map.virt) {
- iounmap((void *)epxa_map.virt);
- epxa_map.virt = 0;
- }
-}
-
-
-/*
- * This will do for now, once we decide which bootldr we're finally
- * going to use then we'll remove this function and do it properly
- *
- * Partions are currently (as offsets from base of flash):
- * 0x00000000 - 0x003FFFFF - bootloader (!)
- * 0x00400000 - 0x00FFFFFF - Flashdisk
- */
-
-static int __init epxa_default_partitions(struct mtd_info *master, struct mtd_partition **pparts)
-{
- struct mtd_partition *parts;
- int ret, i;
- int npartitions = 0;
- char *names;
- const char *name = "jffs";
-
- printk("Using default partitions for %s\n",BOARD_NAME);
- npartitions=1;
- parts = kmalloc(npartitions*sizeof(*parts)+strlen(name), GFP_KERNEL);
- memzero(parts,npartitions*sizeof(*parts)+strlen(name));
- if (!parts) {
- ret = -ENOMEM;
- goto out;
- }
- i=0;
- names = (char *)&parts[npartitions];
- parts[i].name = names;
- names += strlen(name) + 1;
- strcpy(parts[i].name, name);
-
-#ifdef CONFIG_EPXA10DB
- parts[i].size = FLASH_SIZE-0x00400000;
- parts[i].offset = 0x00400000;
-#else
- parts[i].size = FLASH_SIZE-0x00180000;
- parts[i].offset = 0x00180000;
-#endif
-
- out:
- *pparts = parts;
- return npartitions;
-}
-
-
-module_init(epxa_mtd_init);
-module_exit(epxa_mtd_cleanup);
-
-MODULE_AUTHOR("Clive Davies");
-MODULE_DESCRIPTION("Altera epxa mtd flash map");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index af24216a0626..f0f8916da7ad 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -66,9 +66,6 @@ struct pcmciamtd_dev {
};
-static dev_info_t dev_info = "pcmciamtd";
-static dev_link_t *dev_list;
-
/* Module parameters */
/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
@@ -691,55 +688,21 @@ static void pcmciamtd_config(dev_link_t *link)
}
-/* The card status event handler. Mostly, this schedules other
- * stuff to run after an event is received. A CARD_REMOVAL event
- * also sets some flags to discourage the driver from trying
- * to talk to the card any more.
- */
+static int pcmciamtd_suspend(struct pcmcia_device *dev)
+{
+ DEBUG(2, "EVENT_PM_RESUME");
+
+ /* get_lock(link); */
+
+ return 0;
+}
-static int pcmciamtd_event(event_t event, int priority,
- event_callback_args_t *args)
+static int pcmciamtd_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
-
- DEBUG(1, "event=0x%06x", event);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- DEBUG(2, "EVENT_CARD_REMOVAL");
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- struct pcmciamtd_dev *dev = link->priv;
- if(dev->mtd_info) {
- del_mtd_device(dev->mtd_info);
- info("mtd%d: Removed", dev->mtd_info->index);
- }
- pcmciamtd_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- DEBUG(2, "EVENT_CARD_INSERTION");
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcmciamtd_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- DEBUG(2, "EVENT_PM_SUSPEND");
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- DEBUG(2, "EVENT_RESET_PHYSICAL");
- /* get_lock(link); */
- break;
- case CS_EVENT_PM_RESUME:
- DEBUG(2, "EVENT_PM_RESUME");
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- DEBUG(2, "EVENT_CARD_RESET");
- /* free_lock(link); */
- break;
- default:
- DEBUG(2, "Unknown event %d", event);
- }
+ DEBUG(2, "EVENT_PM_SUSPEND");
+
+ /* free_lock(link); */
+
return 0;
}
@@ -750,23 +713,21 @@ static int pcmciamtd_event(event_t event, int priority,
* when the device is released.
*/
-static void pcmciamtd_detach(dev_link_t *link)
+static void pcmciamtd_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
+
DEBUG(3, "link=0x%p", link);
if(link->state & DEV_CONFIG) {
- pcmciamtd_release(link);
- }
+ struct pcmciamtd_dev *dev = link->priv;
+ if(dev->mtd_info) {
+ del_mtd_device(dev->mtd_info);
+ info("mtd%d: Removed", dev->mtd_info->index);
+ }
- if (link->handle) {
- int ret;
- DEBUG(2, "Deregistering with card services");
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
+ pcmciamtd_release(link);
}
-
- link->state |= DEV_STALE_LINK;
}
@@ -775,16 +736,14 @@ static void pcmciamtd_detach(dev_link_t *link)
* with Card Services.
*/
-static dev_link_t *pcmciamtd_attach(void)
+static int pcmciamtd_attach(struct pcmcia_device *p_dev)
{
struct pcmciamtd_dev *dev;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
/* Create new memory card device */
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) return NULL;
+ if (!dev) return -ENOMEM;
DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev));
@@ -794,22 +753,14 @@ static dev_link_t *pcmciamtd_attach(void)
link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY;
- link->next = dev_list;
- dev_list = link;
-
- /* Register with Card Services */
- client_reg.dev_info = &dev_info;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
- DEBUG(2, "Calling RegisterClient");
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if (ret != 0) {
- cs_error(link->handle, RegisterClient, ret);
- pcmciamtd_detach(link);
- return NULL;
- }
- DEBUG(2, "link = %p", link);
- return link;
+ link->next = NULL;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ pcmciamtd_config(link);
+
+ return 0;
}
static struct pcmcia_device_id pcmciamtd_ids[] = {
@@ -843,11 +794,12 @@ static struct pcmcia_driver pcmciamtd_driver = {
.drv = {
.name = "pcmciamtd"
},
- .attach = pcmciamtd_attach,
- .event = pcmciamtd_event,
- .detach = pcmciamtd_detach,
+ .probe = pcmciamtd_attach,
+ .remove = pcmciamtd_detach,
.owner = THIS_MODULE,
.id_table = pcmciamtd_ids,
+ .suspend = pcmciamtd_suspend,
+ .resume = pcmciamtd_resume,
};
@@ -875,7 +827,6 @@ static void __exit exit_pcmciamtd(void)
{
DEBUG(1, DRIVER_DESC " unloading");
pcmcia_unregister_driver(&pcmciamtd_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_pcmciamtd);
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 339cb1218eaa..7f3ff500b68e 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f)
return ret;
}
+static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data;
+
+ if (dev->tr->getgeo)
+ return dev->tr->getgeo(dev, geo);
+ return -ENOTTY;
+}
static int blktrans_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
return tr->flush(dev);
/* The core code did the work, we had nothing to do. */
return 0;
-
- case HDIO_GETGEO:
- if (tr->getgeo) {
- struct hd_geometry g;
- int ret;
-
- memset(&g, 0, sizeof(g));
- ret = tr->getgeo(dev, &g);
- if (ret)
- return ret;
-
- g.start = get_start_sect(inode->i_bdev);
- if (copy_to_user((void __user *)arg, &g, sizeof(g)))
- return -EFAULT;
- return 0;
- } /* else */
default:
return -ENOTTY;
}
@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = {
.open = blktrans_open,
.release = blktrans_release,
.ioctl = blktrans_ioctl,
+ .getgeo = blktrans_getgeo,
};
int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index 9c5945d6df88..201e1362da14 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -43,7 +43,7 @@ static int nand_width = 1; /* default x8*/
/*
* Define partitions for flash device
*/
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "NAND FS 0",
.offset = 0,
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 21d4e8f4b7af..ec5e45e4e4ef 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1506,7 +1506,7 @@ static inline int __init doc2001plus_init(struct mtd_info *mtd)
return 1;
}
-static inline int __init doc_probe(unsigned long physadr)
+static int __init doc_probe(unsigned long physadr)
{
unsigned char ChipID;
struct mtd_info *mtd;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 3a5841c9d950..4129c03dfd90 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -96,7 +96,7 @@ static struct mtd_info *rtc_from4_mtd = NULL;
*/
static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "Renesas flash partition 1",
.offset = 0,
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index d209214b1318..5b55599739f3 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -53,6 +53,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/clk.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -60,7 +61,6 @@
#include <linux/mtd/partitions.h>
#include <asm/io.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-nand.h>
#include <asm/arch/nand.h>
@@ -460,7 +460,6 @@ static int s3c2410_nand_remove(struct platform_device *pdev)
if (info->clk != NULL && !IS_ERR(info->clk)) {
clk_disable(info->clk);
- clk_unuse(info->clk);
clk_put(info->clk);
}
@@ -598,7 +597,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
goto exit_error;
}
- clk_use(info->clk);
clk_enable(info->clk);
/* allocate and map the resource */
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 32541cbb0103..9cf1ce718ec1 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -67,7 +67,7 @@ module_param(spia_peddr, int, 0);
/*
* Define partitions for flash device
*/
-const static struct mtd_partition partition_info[] = {
+static const struct mtd_partition partition_info[] = {
{
.name = "SPIA flash partition 1",
.offset = 0,
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 45c077d0f063..af06a80f44de 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index 20ce212638fc..a3e00a4635a5 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -18,6 +18,7 @@
#include <linux/mtd/blktrans.h>
#include <linux/mtd/mtd.h>
#include <linux/vmalloc.h>
+#include <linux/slab.h>
#include <linux/jiffies.h>
#include <asm/types.h>
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 5c5eebdb6914..dcc98afa65d7 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -148,14 +148,6 @@ el2_pio_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: el2_close() handles free_irq */
- release_region(dev->base_addr, EL2_IO_EXTENT);
- if (ei_status.mem)
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init el2_probe(int unit)
{
@@ -726,6 +718,14 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: el2_close() handles free_irq */
+ release_region(dev->base_addr, EL2_IO_EXTENT);
+ if (ei_status.mem)
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/3c527.h b/drivers/net/3c527.h
index c10f009ce9b6..53b5b071df08 100644
--- a/drivers/net/3c527.h
+++ b/drivers/net/3c527.h
@@ -32,43 +32,43 @@
struct mc32_mailbox
{
- u16 mbox __attribute((packed));
- u16 data[1] __attribute((packed));
-};
+ u16 mbox;
+ u16 data[1];
+} __attribute((packed));
struct skb_header
{
- u8 status __attribute((packed));
- u8 control __attribute((packed));
- u16 next __attribute((packed)); /* Do not change! */
- u16 length __attribute((packed));
- u32 data __attribute((packed));
-};
+ u8 status;
+ u8 control;
+ u16 next; /* Do not change! */
+ u16 length;
+ u32 data;
+} __attribute((packed));
struct mc32_stats
{
/* RX Errors */
- u32 rx_crc_errors __attribute((packed));
- u32 rx_alignment_errors __attribute((packed));
- u32 rx_overrun_errors __attribute((packed));
- u32 rx_tooshort_errors __attribute((packed));
- u32 rx_toolong_errors __attribute((packed));
- u32 rx_outofresource_errors __attribute((packed));
+ u32 rx_crc_errors;
+ u32 rx_alignment_errors;
+ u32 rx_overrun_errors;
+ u32 rx_tooshort_errors;
+ u32 rx_toolong_errors;
+ u32 rx_outofresource_errors;
- u32 rx_discarded __attribute((packed)); /* via card pattern match filter */
+ u32 rx_discarded; /* via card pattern match filter */
/* TX Errors */
- u32 tx_max_collisions __attribute((packed));
- u32 tx_carrier_errors __attribute((packed));
- u32 tx_underrun_errors __attribute((packed));
- u32 tx_cts_errors __attribute((packed));
- u32 tx_timeout_errors __attribute((packed)) ;
+ u32 tx_max_collisions;
+ u32 tx_carrier_errors;
+ u32 tx_underrun_errors;
+ u32 tx_cts_errors;
+ u32 tx_timeout_errors;
/* various cruft */
- u32 dataA[6] __attribute((packed));
- u16 dataB[5] __attribute((packed));
- u32 dataC[14] __attribute((packed));
-};
+ u32 dataA[6];
+ u16 dataB[5];
+ u32 dataC[14];
+} __attribute((packed));
#define STATUS_MASK 0x0F
#define COMPLETED (1<<7)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 30bee11c48bd..adfba44dac5a 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -505,7 +505,7 @@ enum chip_flags {
#define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)
/* directly indexed by chip_t, above */
-const static struct {
+static const struct {
const char *name;
u32 version; /* from RTL8139C/RTL8139D docs */
u32 flags;
@@ -586,16 +586,16 @@ struct rtl8139_private {
dma_addr_t tx_bufs_dma;
signed char phys[4]; /* MII device addresses. */
char twistie, twist_row, twist_col; /* Twister tune state. */
- unsigned int default_port:4; /* Last dev->if_port value. */
+ unsigned int default_port : 4; /* Last dev->if_port value. */
+ unsigned int have_thread : 1;
spinlock_t lock;
spinlock_t rx_lock;
chip_t chipset;
- pid_t thr_pid;
- wait_queue_head_t thr_wait;
- struct completion thr_exited;
u32 rx_config;
struct rtl_extra_stats xstats;
- int time_to_die;
+
+ struct work_struct thread;
+
struct mii_if_info mii;
unsigned int regs_len;
unsigned long fifo_copy_timeout;
@@ -620,7 +620,7 @@ static int rtl8139_open (struct net_device *dev);
static int mdio_read (struct net_device *dev, int phy_id, int location);
static void mdio_write (struct net_device *dev, int phy_id, int location,
int val);
-static void rtl8139_start_thread(struct net_device *dev);
+static void rtl8139_start_thread(struct rtl8139_private *tp);
static void rtl8139_tx_timeout (struct net_device *dev);
static void rtl8139_init_ring (struct net_device *dev);
static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -637,6 +637,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev);
static void rtl8139_set_rx_mode (struct net_device *dev);
static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
+static void rtl8139_thread (void *_data);
static struct ethtool_ops rtl8139_ethtool_ops;
/* write MMIO register, with flush */
@@ -1007,8 +1008,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
(debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));
spin_lock_init (&tp->lock);
spin_lock_init (&tp->rx_lock);
- init_waitqueue_head (&tp->thr_wait);
- init_completion (&tp->thr_exited);
+ INIT_WORK(&tp->thread, rtl8139_thread, dev);
tp->mii.dev = dev;
tp->mii.mdio_read = mdio_read;
tp->mii.mdio_write = mdio_write;
@@ -1345,7 +1345,7 @@ static int rtl8139_open (struct net_device *dev)
dev->irq, RTL_R8 (MediaStatus),
tp->mii.full_duplex ? "full" : "half");
- rtl8139_start_thread(dev);
+ rtl8139_start_thread(tp);
return 0;
}
@@ -1594,55 +1594,43 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
RTL_R8 (Config1));
}
-static int rtl8139_thread (void *data)
+static void rtl8139_thread (void *_data)
{
- struct net_device *dev = data;
+ struct net_device *dev = _data;
struct rtl8139_private *tp = netdev_priv(dev);
- unsigned long timeout;
-
- daemonize("%s", dev->name);
- allow_signal(SIGTERM);
-
- while (1) {
- timeout = next_tick;
- do {
- timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
- /* make swsusp happy with our thread */
- try_to_freeze();
- } while (!signal_pending (current) && (timeout > 0));
-
- if (signal_pending (current)) {
- flush_signals(current);
- }
+ unsigned long thr_delay;
- if (tp->time_to_die)
- break;
-
- if (rtnl_lock_interruptible ())
- break;
+ if (rtnl_shlock_nowait() == 0) {
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
rtnl_unlock ();
+
+ thr_delay = next_tick;
+ } else {
+ /* unlikely race. mitigate with fast poll. */
+ thr_delay = HZ / 2;
}
- complete_and_exit (&tp->thr_exited, 0);
+ schedule_delayed_work(&tp->thread, thr_delay);
}
-static void rtl8139_start_thread(struct net_device *dev)
+static void rtl8139_start_thread(struct rtl8139_private *tp)
{
- struct rtl8139_private *tp = netdev_priv(dev);
-
- tp->thr_pid = -1;
tp->twistie = 0;
- tp->time_to_die = 0;
if (tp->chipset == CH_8139_K)
tp->twistie = 1;
else if (tp->drv_flags & HAS_LNK_CHNG)
return;
- tp->thr_pid = kernel_thread(rtl8139_thread, dev, CLONE_FS|CLONE_FILES);
- if (tp->thr_pid < 0) {
- printk (KERN_WARNING "%s: unable to start kernel thread\n",
- dev->name);
+ tp->have_thread = 1;
+
+ schedule_delayed_work(&tp->thread, next_tick);
+}
+
+static void rtl8139_stop_thread(struct rtl8139_private *tp)
+{
+ if (tp->have_thread) {
+ cancel_rearming_delayed_work(&tp->thread);
+ tp->have_thread = 0;
}
}
@@ -2224,22 +2212,12 @@ static int rtl8139_close (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- int ret = 0;
unsigned long flags;
netif_stop_queue (dev);
- if (tp->thr_pid >= 0) {
- tp->time_to_die = 1;
- wmb();
- ret = kill_proc (tp->thr_pid, SIGTERM, 1);
- if (ret) {
- printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
- return ret;
- }
- wait_for_completion (&tp->thr_exited);
- }
-
+ rtl8139_stop_thread(tp);
+
if (netif_msg_ifdown(tp))
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
dev->name, RTL_R16 (IntrStatus));
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ebd7313d7fc1..626508afe1b1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -7,6 +7,7 @@ menu "Network device support"
config NETDEVICES
depends on NET
+ default y if UML
bool "Network device support"
---help---
You can say N here if you don't intend to connect your Linux box to
@@ -27,6 +28,19 @@ config NETDEVICES
# that for each of the symbols.
if NETDEVICES
+config IFB
+ tristate "Intermediate Functional Block support"
+ depends on NET_CLS_ACT
+ ---help---
+ This is an intermidiate driver that allows sharing of
+ resources.
+ To compile this driver as a module, choose M here: the module
+ will be called ifb. If you want to use more than one ifb
+ device at a time, you need to compile this driver as a module.
+ Instead of 'ifb', the devices will then be called 'ifb0',
+ 'ifb1' etc.
+ Look at the iproute2 documentation directory for usage etc
+
config DUMMY
tristate "Dummy net driver support"
---help---
@@ -129,7 +143,7 @@ config NET_SB1000
If you don't have this card, of course say N.
- source "drivers/net/arcnet/Kconfig"
+source "drivers/net/arcnet/Kconfig"
source "drivers/net/phy/Kconfig"
@@ -844,7 +858,7 @@ config SMC9194
config DM9000
tristate "DM9000 support"
- depends on ARM && NET_ETHERNET
+ depends on (ARM || MIPS) && NET_ETHERNET
select CRC32
select MII
---help---
@@ -1374,7 +1388,7 @@ config FORCEDETH
config CS89x0
tristate "CS89x0 support"
- depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105
+ depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
@@ -1384,7 +1398,7 @@ config CS89x0
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module will be
- called cs89x.
+ called cs89x0.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
@@ -1791,7 +1805,7 @@ config 68360_ENET
config FEC
bool "FEC ethernet controller (of ColdFire CPUs)"
- depends on M523x || M527x || M5272 || M528x
+ depends on M523x || M527x || M5272 || M528x || M520x
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire processors.
@@ -1901,6 +1915,17 @@ config E1000_NAPI
If in doubt, say N.
+config E1000_DISABLE_PACKET_SPLIT
+ bool "Disable Packet Split for PCI express adapters"
+ depends on E1000
+ help
+ Say Y here if you want to use the legacy receive path for PCI express
+ hadware.
+
+ If in doubt, say N.
+
+source "drivers/net/ixp2000/Kconfig"
+
config MYRI_SBUS
tristate "MyriCOM Gigabit Ethernet support"
depends on SBUS
@@ -2008,7 +2033,18 @@ config SKGE
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
-
+
+
+config SKY2
+ tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ ---help---
+ This driver support the Marvell Yukon 2 Gigabit Ethernet adapter.
+
+ To compile this driver as a module, choose M here: the module
+ will be called sky2. This is recommended.
+
config SK98LIN
tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
depends on PCI
@@ -2120,7 +2156,7 @@ config BNX2
config SPIDER_NET
tristate "Spider Gigabit Ethernet driver"
- depends on PCI && PPC_BPA
+ depends on PCI && PPC_CELL
help
This driver supports the Gigabit Ethernet chips present on the
Cell Processor-Based Blades from IBM.
@@ -2650,10 +2686,6 @@ config SHAPER
Class-Based Queueing (CBQ) scheduling support which you get if you
say Y to "QoS and/or fair queueing" above.
- To set up and configure shaper devices, you need the shapecfg
- program, available from <ftp://shadow.cabi.net/pub/Linux/> in the
- shaper package.
-
To compile this driver as a module, choose M here: the module
will be called shaper. If unsure, say N.
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 4cffd34442aa..00e72b12fb92 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -13,7 +13,10 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
-gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o
+gianfar_driver-objs := gianfar.o \
+ gianfar_ethtool.o \
+ gianfar_mii.o \
+ gianfar_sysfs.o
#
# link order important here
@@ -59,6 +62,7 @@ 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_SKY2) += sky2.o
obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
@@ -121,6 +125,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y)
endif
obj-$(CONFIG_DUMMY) += dummy.o
+obj-$(CONFIG_IFB) += ifb.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
obj-$(CONFIG_LANCE) += lance.o
@@ -202,6 +207,7 @@ obj-$(CONFIG_NET_TULIP) += tulip/
obj-$(CONFIG_HAMRADIO) += hamradio/
obj-$(CONFIG_IRDA) += irda/
obj-$(CONFIG_ETRAX_ETHERNET) += cris/
+obj-$(CONFIG_ENP2611_MSF_NET) += ixp2000/
obj-$(CONFIG_NETCONSOLE) += netconsole.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 8a0af5453e21..7952dc6d77e3 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -123,14 +123,6 @@ static int __init do_ac3200_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* Someday free_irq may be in ac_close_card() */
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, AC_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init ac3200_probe(int unit)
{
@@ -406,6 +398,14 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* Someday free_irq may be in ac_close_card() */
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, AC_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 470364deded0..625184b65e38 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -31,16 +31,3 @@ config ARM_ETHERH
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
-
-config ARM_ETHER00
- tristate "Altera Ether00 support"
- depends on NET_ETHERNET && ARM && ARCH_CAMELOT
- help
- This is the driver for Altera's ether00 ethernet mac IP core. Say
- Y here if you want to build support for this into the kernel. It
- is also available as a module (say M here) that can be inserted/
- removed from the kernel at the same time as the PLD is configured.
- If this driver is running on an epxa10 development board then it
- will generate a suitable hw address based on the board serial
- number (MTD support is required for this). Otherwise you will
- need to set a suitable hw address using ifconfig.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index b0d706834d89..bc263edf06a7 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -4,7 +4,6 @@
#
obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
-obj-$(CONFIG_ARM_ETHER00) += ether00.o
obj-$(CONFIG_ARM_ETHERH) += etherh.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 877891a29aaa..53e3afc1b7b7 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -668,9 +668,8 @@ static void __init am79c961_banner(void)
printk(KERN_INFO "%s", version);
}
-static int __init am79c961_probe(struct device *_dev)
+static int __init am79c961_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(_dev);
struct resource *res;
struct net_device *dev;
struct dev_priv *priv;
@@ -758,15 +757,16 @@ out:
return ret;
}
-static struct device_driver am79c961_driver = {
- .name = "am79c961",
- .bus = &platform_bus_type,
+static struct platform_driver am79c961_driver = {
.probe = am79c961_probe,
+ .driver = {
+ .name = "am79c961",
+ },
};
static int __init am79c961_init(void)
{
- return driver_register(&am79c961_driver);
+ return platform_driver_register(&am79c961_driver);
}
__initcall(am79c961_init);
diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c
deleted file mode 100644
index 4f1f4e31bda5..000000000000
--- a/drivers/net/arm/ether00.c
+++ /dev/null
@@ -1,1017 +0,0 @@
-/*
- * drivers/net/ether00.c
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* includes */
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/tqueue.h>
-#include <linux/mtd/mtd.h>
-#include <linux/pld/pld_hotswap.h>
-#include <asm/arch/excalibur.h>
-#include <asm/arch/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-#include <asm/arch/ether00.h>
-#include <asm/arch/tdkphy.h>
-
-
-MODULE_AUTHOR("Clive Davies");
-MODULE_DESCRIPTION("Altera Ether00 IP core driver");
-MODULE_LICENSE("GPL");
-
-#define PKT_BUF_SZ 1540 /* Size of each rx buffer */
-#define ETH_NR 4 /* Number of MACs this driver supports */
-
-#define DEBUG(x)
-
-#define __dma_va(x) (unsigned int)((unsigned int)priv->dma_data+(((unsigned int)(x))&(EXC_SPSRAM_BLOCK0_SIZE-1)))
-#define __dma_pa(x) (unsigned int)(EXC_SPSRAM_BLOCK0_BASE+(((unsigned int)(x))-(unsigned int)priv->dma_data))
-
-#define ETHER00_BASE 0
-#define ETHER00_TYPE
-#define ETHER00_NAME "ether00"
-#define MAC_REG_SIZE 0x400 /* size of MAC register area */
-
-
-
-/* typedefs */
-
-/* The definition of the driver control structure */
-
-#define RX_NUM_BUFF 10
-#define RX_NUM_FDESC 10
-#define TX_NUM_FDESC 10
-
-struct tx_fda_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct rx_fda_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct rx_blist_ent{
- FDA_DESC fd;
- BUF_DESC bd;
- BUF_DESC pad;
-};
-struct net_priv
-{
- struct net_device_stats stats;
- struct sk_buff* skb;
- void* dma_data;
- struct rx_blist_ent* rx_blist_vp;
- struct rx_fda_ent* rx_fda_ptr;
- struct tx_fda_ent* tx_fdalist_vp;
- struct tq_struct tq_memupdate;
- unsigned char memupdate_scheduled;
- unsigned char rx_disabled;
- unsigned char queue_stopped;
- spinlock_t rx_lock;
-};
-
-static const char vendor_id[2]={0x07,0xed};
-
-#ifdef ETHER00_DEBUG
-
-/* Dump (most) registers for debugging puposes */
-
-static void dump_regs(struct net_device *dev){
- struct net_priv* priv=dev->priv;
- unsigned int* i;
-
- printk("\n RX free descriptor area:\n");
-
- for(i=(unsigned int*)priv->rx_fda_ptr;
- i<((unsigned int*)(priv->rx_fda_ptr+RX_NUM_FDESC));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\n RX buffer list:\n");
-
- for(i=(unsigned int*)priv->rx_blist_vp;
- i<((unsigned int*)(priv->rx_blist_vp+RX_NUM_BUFF));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\n TX frame descriptor list:\n");
-
- for(i=(unsigned int*)priv->tx_fdalist_vp;
- i<((unsigned int*)(priv->tx_fdalist_vp+TX_NUM_FDESC));){
- printk("%#8x %#8x %#8x %#8x\n",*i,*(i+1),*(i+2),*(i+3));
- i+=4;
- }
-
- printk("\ndma ctl=%#x\n",readw(ETHER_DMA_CTL(dev->base_addr)));
- printk("txfrmptr=%#x\n",readw(ETHER_TXFRMPTR(dev->base_addr)));
- printk("txthrsh=%#x\n",readw(ETHER_TXTHRSH(dev->base_addr)));
- printk("txpollctr=%#x\n",readw(ETHER_TXPOLLCTR(dev->base_addr)));
- printk("blfrmptr=%#x\n",readw(ETHER_BLFRMPTR(dev->base_addr)));
- printk("rxfragsize=%#x\n",readw(ETHER_RXFRAGSIZE(dev->base_addr)));
- printk("tx_int_en=%#x\n",readw(ETHER_INT_EN(dev->base_addr)));
- printk("fda_bas=%#x\n",readw(ETHER_FDA_BAS(dev->base_addr)));
- printk("fda_lim=%#x\n",readw(ETHER_FDA_LIM(dev->base_addr)));
- printk("int_src=%#x\n",readw(ETHER_INT_SRC(dev->base_addr)));
- printk("pausecnt=%#x\n",readw(ETHER_PAUSECNT(dev->base_addr)));
- printk("rempaucnt=%#x\n",readw(ETHER_REMPAUCNT(dev->base_addr)));
- printk("txconfrmstat=%#x\n",readw(ETHER_TXCONFRMSTAT(dev->base_addr)));
- printk("mac_ctl=%#x\n",readw(ETHER_MAC_CTL(dev->base_addr)));
- printk("arc_ctl=%#x\n",readw(ETHER_ARC_CTL(dev->base_addr)));
- printk("tx_ctl=%#x\n",readw(ETHER_TX_CTL(dev->base_addr)));
-}
-#endif /* ETHER00_DEBUG */
-
-
-static int ether00_write_phy(struct net_device *dev, short address, short value)
-{
- volatile int count = 1024;
- writew(value,ETHER_MD_DATA(dev->base_addr));
- writew( ETHER_MD_CA_BUSY_MSK |
- ETHER_MD_CA_WR_MSK |
- (address & ETHER_MD_CA_ADDR_MSK),
- ETHER_MD_CA(dev->base_addr));
-
- /* Wait for the command to complete */
- while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){
- count--;
- }
- if (!count){
- printk("Write to phy failed, addr=%#x, data=%#x\n",address, value);
- return -EIO;
- }
- return 0;
-}
-
-static int ether00_read_phy(struct net_device *dev, short address)
-{
- volatile int count = 1024;
- writew( ETHER_MD_CA_BUSY_MSK |
- (address & ETHER_MD_CA_ADDR_MSK),
- ETHER_MD_CA(dev->base_addr));
-
- /* Wait for the command to complete */
- while((readw(ETHER_MD_CA(dev->base_addr)) & ETHER_MD_CA_BUSY_MSK)&&count){
- count--;
- }
- if (!count){
- printk(KERN_WARNING "Read from phy timed out\n");
- return -EIO;
- }
- return readw(ETHER_MD_DATA(dev->base_addr));
-}
-
-static void ether00_phy_int(int irq_num, void* dev_id, struct pt_regs* regs)
-{
- struct net_device* dev=dev_id;
- int irq_status;
-
- irq_status=ether00_read_phy(dev, PHY_IRQ_CONTROL);
-
- if(irq_status & PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK){
- /*
- * Autonegotiation complete on epxa10db. The mac doesn't
- * twig if we're in full duplex so we need to check the
- * phy status register and configure the mac accordingly
- */
- if(ether00_read_phy(dev, PHY_STATUS)&(PHY_STATUS_10T_F_MSK|PHY_STATUS_100_X_F_MSK)){
- int tmp;
- tmp=readl(ETHER_MAC_CTL(dev->base_addr));
- writel(tmp|ETHER_MAC_CTL_FULLDUP_MSK,ETHER_MAC_CTL(dev->base_addr));
- }
- }
-
- if(irq_status&PHY_IRQ_CONTROL_LS_CHG_INT_MSK){
-
- if(ether00_read_phy(dev, PHY_STATUS)& PHY_STATUS_LINK_MSK){
- /* Link is up */
- netif_carrier_on(dev);
- //printk("Carrier on\n");
- }else{
- netif_carrier_off(dev);
- //printk("Carrier off\n");
-
- }
- }
-
-}
-
-static void setup_blist_entry(struct sk_buff* skb,struct rx_blist_ent* blist_ent_ptr){
- /* Make the buffer consistent with the cache as the mac is going to write
- * directly into it*/
- blist_ent_ptr->fd.FDSystem=(unsigned int)skb;
- blist_ent_ptr->bd.BuffData=(char*)__pa(skb->data);
- consistent_sync(skb->data,PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
- /* align IP on 16 Byte (DMA_CTL set to skip 2 bytes) */
- skb_reserve(skb,2);
- blist_ent_ptr->bd.BuffLength=PKT_BUF_SZ-2;
- blist_ent_ptr->fd.FDLength=1;
- blist_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK;
- blist_ent_ptr->bd.BDCtl=BDCTL_COWNSBD_MSK;
-}
-
-
-static int ether00_mem_init(struct net_device* dev)
-{
- struct net_priv* priv=dev->priv;
- struct tx_fda_ent *tx_fd_ptr,*tx_end_ptr;
- struct rx_blist_ent* blist_ent_ptr;
- int i;
-
- /*
- * Grab a block of on chip SRAM to contain the control stuctures for
- * the ethernet MAC. This uncached becuase it needs to be accesses by both
- * bus masters (cpu + mac). However, it shouldn't matter too much in terms
- * of speed as its on chip memory
- */
- priv->dma_data=ioremap_nocache(EXC_SPSRAM_BLOCK0_BASE,EXC_SPSRAM_BLOCK0_SIZE );
- if (!priv->dma_data)
- return -ENOMEM;
-
- priv->rx_fda_ptr=(struct rx_fda_ent*)priv->dma_data;
- /*
- * Now share it out amongst the Frame descriptors and the buffer list
- */
- priv->rx_blist_vp=(struct rx_blist_ent*)((unsigned int)priv->dma_data+RX_NUM_FDESC*sizeof(struct rx_fda_ent));
-
- /*
- *Initalise the FDA list
- */
- /* set ownership to the controller */
- memset(priv->rx_fda_ptr,0x80,RX_NUM_FDESC*sizeof(struct rx_fda_ent));
-
- /*
- *Initialise the buffer list
- */
- blist_ent_ptr=priv->rx_blist_vp;
- i=0;
- while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){
- struct sk_buff *skb;
- blist_ent_ptr->fd.FDLength=1;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
- blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(blist_ent_ptr+1);
- blist_ent_ptr->bd.BDStat=i++;
- blist_ent_ptr++;
- }
- else
- {
- printk("Failed to initalise buffer list\n");
- }
-
- }
- blist_ent_ptr--;
- blist_ent_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->rx_blist_vp);
-
- priv->tx_fdalist_vp=(struct tx_fda_ent*)(priv->rx_blist_vp+RX_NUM_BUFF);
-
- /* Initialise the buffers to be a circular list. The mac will then go poll
- * the list until it finds a frame ready to transmit */
- tx_end_ptr=priv->tx_fdalist_vp+TX_NUM_FDESC;
- for(tx_fd_ptr=priv->tx_fdalist_vp;tx_fd_ptr<tx_end_ptr;tx_fd_ptr++){
- tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa((tx_fd_ptr+1));
- tx_fd_ptr->fd.FDCtl=1;
- tx_fd_ptr->fd.FDStat=0;
- tx_fd_ptr->fd.FDLength=1;
-
- }
- /* Change the last FDNext pointer to make a circular list */
- tx_fd_ptr--;
- tx_fd_ptr->fd.FDNext=(FDA_DESC*)__dma_pa(priv->tx_fdalist_vp);
-
- /* Point the device at the chain of Rx and Tx Buffers */
- writel((unsigned int)__dma_pa(priv->rx_fda_ptr),ETHER_FDA_BAS(dev->base_addr));
- writel((RX_NUM_FDESC-1)*sizeof(struct rx_fda_ent),ETHER_FDA_LIM(dev->base_addr));
- writel((unsigned int)__dma_pa(priv->rx_blist_vp),ETHER_BLFRMPTR(dev->base_addr));
-
- writel((unsigned int)__dma_pa(priv->tx_fdalist_vp),ETHER_TXFRMPTR(dev->base_addr));
-
- return 0;
-}
-
-
-void ether00_mem_update(void* dev_id)
-{
- struct net_device* dev=dev_id;
- struct net_priv* priv=dev->priv;
- struct sk_buff* skb;
- struct tx_fda_ent *fda_ptr=priv->tx_fdalist_vp;
- struct rx_blist_ent* blist_ent_ptr;
- unsigned long flags;
-
- priv->tq_memupdate.sync=0;
- //priv->tq_memupdate.list=
- priv->memupdate_scheduled=0;
-
- /* Transmit interrupt */
- while(fda_ptr<(priv->tx_fdalist_vp+TX_NUM_FDESC)){
- if(!(FDCTL_COWNSFD_MSK&fda_ptr->fd.FDCtl) && (ETHER_TX_STAT_COMP_MSK&fda_ptr->fd.FDStat)){
- priv->stats.tx_packets++;
- priv->stats.tx_bytes+=fda_ptr->bd.BuffLength;
- skb=(struct sk_buff*)fda_ptr->fd.FDSystem;
- //printk("%d:txcln:fda=%#x skb=%#x\n",jiffies,fda_ptr,skb);
- dev_kfree_skb(skb);
- fda_ptr->fd.FDSystem=0;
- fda_ptr->fd.FDStat=0;
- fda_ptr->fd.FDCtl=0;
- }
- fda_ptr++;
- }
- /* Fill in any missing buffers from the received queue */
- spin_lock_irqsave(&priv->rx_lock,flags);
- blist_ent_ptr=priv->rx_blist_vp;
- while(blist_ent_ptr<(priv->rx_blist_vp+RX_NUM_BUFF)){
- /* fd.FDSystem of 0 indicates we failed to allocate the buffer in the ISR */
- if(!blist_ent_ptr->fd.FDSystem){
- struct sk_buff *skb;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- blist_ent_ptr->fd.FDSystem=(unsigned int)skb;
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
- }
- else
- {
- break;
- }
- }
- blist_ent_ptr++;
- }
- spin_unlock_irqrestore(&priv->rx_lock,flags);
- if(priv->queue_stopped){
- //printk("%d:cln:start q\n",jiffies);
- netif_start_queue(dev);
- }
- if(priv->rx_disabled){
- //printk("%d:enable_irq\n",jiffies);
- priv->rx_disabled=0;
- writel(ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr));
-
- }
-}
-
-
-static void ether00_int( int irq_num, void* dev_id, struct pt_regs* regs)
-{
- struct net_device* dev=dev_id;
- struct net_priv* priv=dev->priv;
-
- unsigned int interruptValue;
-
- interruptValue=readl(ETHER_INT_SRC(dev->base_addr));
-
- //printk("INT_SRC=%x\n",interruptValue);
-
- if(!(readl(ETHER_INT_SRC(dev->base_addr)) & ETHER_INT_SRC_IRQ_MSK))
- {
- return; /* Interrupt wasn't caused by us!! */
- }
-
- if(readl(ETHER_INT_SRC(dev->base_addr))&
- (ETHER_INT_SRC_INTMACRX_MSK |
- ETHER_INT_SRC_FDAEX_MSK |
- ETHER_INT_SRC_BLEX_MSK)) {
- struct rx_blist_ent* blist_ent_ptr;
- struct rx_fda_ent* fda_ent_ptr;
- struct sk_buff* skb;
-
- fda_ent_ptr=priv->rx_fda_ptr;
- spin_lock(&priv->rx_lock);
- while(fda_ent_ptr<(priv->rx_fda_ptr+RX_NUM_FDESC)){
- int result;
-
- if(!(fda_ent_ptr->fd.FDCtl&FDCTL_COWNSFD_MSK))
- {
- /* This frame is ready for processing */
- /*find the corresponding buffer in the bufferlist */
- blist_ent_ptr=priv->rx_blist_vp+fda_ent_ptr->bd.BDStat;
- skb=(struct sk_buff*)blist_ent_ptr->fd.FDSystem;
-
- /* Pass this skb up the stack */
- skb->dev=dev;
- skb_put(skb,fda_ent_ptr->fd.FDLength);
- skb->protocol=eth_type_trans(skb,dev);
- skb->ip_summed=CHECKSUM_UNNECESSARY;
- result=netif_rx(skb);
- /* Update statistics */
- priv->stats.rx_packets++;
- priv->stats.rx_bytes+=fda_ent_ptr->fd.FDLength;
-
- /* Free the FDA entry */
- fda_ent_ptr->bd.BDStat=0xff;
- fda_ent_ptr->fd.FDCtl=FDCTL_COWNSFD_MSK;
-
- /* Allocate a new skb and point the bd entry to it */
- blist_ent_ptr->fd.FDSystem=0;
- skb=dev_alloc_skb(PKT_BUF_SZ);
- //printk("allocskb=%#x\n",skb);
- if(skb){
- setup_blist_entry(skb,blist_ent_ptr);
-
- }
- else if(!priv->memupdate_scheduled){
- int tmp;
- /* There are no buffers at the moment, so schedule */
- /* the background task to sort this out */
- schedule_task(&priv->tq_memupdate);
- priv->memupdate_scheduled=1;
- printk(KERN_DEBUG "%s:No buffers",dev->name);
- /* If this interrupt was due to a lack of buffers then
- * we'd better stop the receiver too */
- if(interruptValue&ETHER_INT_SRC_BLEX_MSK){
- priv->rx_disabled=1;
- tmp=readl(ETHER_INT_SRC(dev->base_addr));
- writel(tmp&~ETHER_RX_CTL_RXEN_MSK,ETHER_RX_CTL(dev->base_addr));
- printk(KERN_DEBUG "%s:Halting rx",dev->name);
- }
-
- }
-
- }
- fda_ent_ptr++;
- }
- spin_unlock(&priv->rx_lock);
-
- /* Clear the interrupts */
- writel(ETHER_INT_SRC_INTMACRX_MSK | ETHER_INT_SRC_FDAEX_MSK
- | ETHER_INT_SRC_BLEX_MSK,ETHER_INT_SRC(dev->base_addr));
-
- }
-
- if(readl(ETHER_INT_SRC(dev->base_addr))&ETHER_INT_SRC_INTMACTX_MSK){
-
- if(!priv->memupdate_scheduled){
- schedule_task(&priv->tq_memupdate);
- priv->memupdate_scheduled=1;
- }
- /* Clear the interrupt */
- writel(ETHER_INT_SRC_INTMACTX_MSK,ETHER_INT_SRC(dev->base_addr));
- }
-
- if (readl(ETHER_INT_SRC(dev->base_addr)) & (ETHER_INT_SRC_SWINT_MSK|
- ETHER_INT_SRC_INTEARNOT_MSK|
- ETHER_INT_SRC_INTLINK_MSK|
- ETHER_INT_SRC_INTEXBD_MSK|
- ETHER_INT_SRC_INTTXCTLCMP_MSK))
- {
- /*
- * Not using any of these so they shouldn't happen
- *
- * In the cased of INTEXBD - if you allocate more
- * than 28 decsriptors you may need to think about this
- */
- printk("Not using this interrupt\n");
- }
-
- if (readl(ETHER_INT_SRC(dev->base_addr)) &
- (ETHER_INT_SRC_INTSBUS_MSK |
- ETHER_INT_SRC_INTNRABT_MSK
- |ETHER_INT_SRC_DMPARERR_MSK))
- {
- /*
- * Hardware errors, we can either ignore them and hope they go away
- *or reset the device, I'll try the first for now to see if they happen
- */
- printk("Hardware error\n");
- }
-}
-
-static void ether00_setup_ethernet_address(struct net_device* dev)
-{
- int tmp;
-
- dev->addr_len=6;
- writew(0,ETHER_ARC_ADR(dev->base_addr));
- writel((dev->dev_addr[0]<<24) |
- (dev->dev_addr[1]<<16) |
- (dev->dev_addr[2]<<8) |
- dev->dev_addr[3],
- ETHER_ARC_DATA(dev->base_addr));
-
- writew(4,ETHER_ARC_ADR(dev->base_addr));
- tmp=readl(ETHER_ARC_DATA(dev->base_addr));
- tmp&=0xffff;
- tmp|=(dev->dev_addr[4]<<24) | (dev->dev_addr[5]<<16);
- writel(tmp, ETHER_ARC_DATA(dev->base_addr));
- /* Enable this entry in the ARC */
-
- writel(1,ETHER_ARC_ENA(dev->base_addr));
-
- return;
-}
-
-
-static void ether00_reset(struct net_device *dev)
-{
- /* reset the controller */
- writew(ETHER_MAC_CTL_RESET_MSK,ETHER_MAC_CTL(dev->base_addr));
-
- /*
- * Make sure we're not going to send anything
- */
-
- writew(ETHER_TX_CTL_TXHALT_MSK,ETHER_TX_CTL(dev->base_addr));
-
- /*
- * Make sure we're not going to receive anything
- */
- writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));
-
- /*
- * Disable Interrupts for now, and set the burst size to 8 bytes
- */
-
- writel(ETHER_DMA_CTL_INTMASK_MSK |
- ((8 << ETHER_DMA_CTL_DMBURST_OFST) & ETHER_DMA_CTL_DMBURST_MSK)
- |(2<<ETHER_DMA_CTL_RXALIGN_OFST),
- ETHER_DMA_CTL(dev->base_addr));
-
-
- /*
- * Set TxThrsh - start transmitting a packet after 1514
- * bytes or when a packet is complete, whichever comes first
- */
- writew(1514,ETHER_TXTHRSH(dev->base_addr));
-
- /*
- * Set TxPollCtr. Each cycle is
- * 61.44 microseconds with a 33 MHz bus
- */
- writew(1,ETHER_TXPOLLCTR(dev->base_addr));
-
- /*
- * Set Rx_Ctl - Turn off reception and let RxData turn it
- * on later
- */
- writew(ETHER_RX_CTL_RXHALT_MSK,ETHER_RX_CTL(dev->base_addr));
-
-}
-
-
-static void ether00_set_multicast(struct net_device* dev)
-{
- int count=dev->mc_count;
-
- /* Set promiscuous mode if it's asked for. */
-
- if (dev->flags&IFF_PROMISC){
-
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_BROADACC_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_STATIONACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
-
- /*
- * Get all multicast packets if required, or if there are too
- * many addresses to fit in hardware
- */
- if (dev->flags & IFF_ALLMULTI){
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_BROADACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
- if (dev->mc_count > (ETHER_ARC_SIZE - 1)){
-
- printk(KERN_WARNING "Too many multicast addresses for hardware to filter - receiving all multicast packets\n");
- writew( ETHER_ARC_CTL_COMPEN_MSK |
- ETHER_ARC_CTL_GROUPACC_MSK |
- ETHER_ARC_CTL_BROADACC_MSK,
- ETHER_ARC_CTL(dev->base_addr));
- return;
- }
-
- if(dev->mc_count){
- struct dev_mc_list *mc_list_ent=dev->mc_list;
- unsigned int temp,i;
- DEBUG(printk("mc_count=%d mc_list=%#x\n",dev-> mc_count, dev->mc_list));
- DEBUG(printk("mc addr=%02#x%02x%02x%02x%02x%02x\n",
- mc_list_ent->dmi_addr[5],
- mc_list_ent->dmi_addr[4],
- mc_list_ent->dmi_addr[3],
- mc_list_ent->dmi_addr[2],
- mc_list_ent->dmi_addr[1],
- mc_list_ent->dmi_addr[0]);)
-
- /*
- * The first 6 bytes are the MAC address, so
- * don't change them!
- */
- writew(4,ETHER_ARC_ADR(dev->base_addr));
- temp=readl(ETHER_ARC_DATA(dev->base_addr));
- temp&=0xffff0000;
-
- /* Disable the current multicast stuff */
- writel(1,ETHER_ARC_ENA(dev->base_addr));
-
- for(;;){
- temp|=mc_list_ent->dmi_addr[1] |
- mc_list_ent->dmi_addr[0]<<8;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writew(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[5]|
- mc_list_ent->dmi_addr[4]<<8 |
- mc_list_ent->dmi_addr[3]<<16 |
- mc_list_ent->dmi_addr[2]<<24;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- count--;
- if(!mc_list_ent->next || !count){
- break;
- }
- DEBUG(printk("mc_list_next=%#x\n",mc_list_ent->next);)
- mc_list_ent=mc_list_ent->next;
-
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writel(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[3]|
- mc_list_ent->dmi_addr[2]<<8 |
- mc_list_ent->dmi_addr[1]<<16 |
- mc_list_ent->dmi_addr[0]<<24;
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- i=readl(ETHER_ARC_ADR(dev->base_addr));
- writel(i+4,ETHER_ARC_ADR(dev->base_addr));
-
- temp=mc_list_ent->dmi_addr[4]<<16 |
- mc_list_ent->dmi_addr[5]<<24;
-
- writel(temp,ETHER_ARC_DATA(dev->base_addr));
-
- count--;
- if(!mc_list_ent->next || !count){
- break;
- }
- mc_list_ent=mc_list_ent->next;
- }
-
-
- if(count)
- printk(KERN_WARNING "Multicast list size error\n");
-
-
- writew( ETHER_ARC_CTL_BROADACC_MSK|
- ETHER_ARC_CTL_COMPEN_MSK,
- ETHER_ARC_CTL(dev->base_addr));
-
- }
-
- /* enable the active ARC enties */
- writew((1<<(count+2))-1,ETHER_ARC_ENA(dev->base_addr));
-}
-
-
-static int ether00_open(struct net_device* dev)
-{
- int result,tmp;
- struct net_priv* priv;
-
- if (!is_valid_ether_addr(dev->dev_addr))
- return -EINVAL;
-
- /* Install interrupt handlers */
- result=request_irq(dev->irq,ether00_int,0,"ether00",dev);
- if(result)
- goto open_err1;
-
- result=request_irq(2,ether00_phy_int,0,"ether00_phy",dev);
- if(result)
- goto open_err2;
-
- ether00_reset(dev);
- result=ether00_mem_init(dev);
- if(result)
- goto open_err3;
-
-
- ether00_setup_ethernet_address(dev);
-
- ether00_set_multicast(dev);
-
- result=ether00_write_phy(dev,PHY_CONTROL, PHY_CONTROL_ANEGEN_MSK | PHY_CONTROL_RANEG_MSK);
- if(result)
- goto open_err4;
- result=ether00_write_phy(dev,PHY_IRQ_CONTROL, PHY_IRQ_CONTROL_LS_CHG_IE_MSK |
- PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK);
- if(result)
- goto open_err4;
-
- /* Start the device enable interrupts */
- writew(ETHER_RX_CTL_RXEN_MSK
-// | ETHER_RX_CTL_STRIPCRC_MSK
- | ETHER_RX_CTL_ENGOOD_MSK
- | ETHER_RX_CTL_ENRXPAR_MSK| ETHER_RX_CTL_ENLONGERR_MSK
- | ETHER_RX_CTL_ENOVER_MSK| ETHER_RX_CTL_ENCRCERR_MSK,
- ETHER_RX_CTL(dev->base_addr));
-
- writew(ETHER_TX_CTL_TXEN_MSK|
- ETHER_TX_CTL_ENEXDEFER_MSK|
- ETHER_TX_CTL_ENLCARR_MSK|
- ETHER_TX_CTL_ENEXCOLL_MSK|
- ETHER_TX_CTL_ENLATECOLL_MSK|
- ETHER_TX_CTL_ENTXPAR_MSK|
- ETHER_TX_CTL_ENCOMP_MSK,
- ETHER_TX_CTL(dev->base_addr));
-
- tmp=readl(ETHER_DMA_CTL(dev->base_addr));
- writel(tmp&~ETHER_DMA_CTL_INTMASK_MSK,ETHER_DMA_CTL(dev->base_addr));
-
- return 0;
-
- open_err4:
- ether00_reset(dev);
- open_err3:
- free_irq(2,dev);
- open_err2:
- free_irq(dev->irq,dev);
- open_err1:
- return result;
-
-}
-
-
-static int ether00_tx(struct sk_buff* skb, struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- struct tx_fda_ent *fda_ptr;
- int i;
-
-
- /*
- * Find an empty slot in which to stick the frame
- */
- fda_ptr=(struct tx_fda_ent*)__dma_va(readl(ETHER_TXFRMPTR(dev->base_addr)));
- i=0;
- while(i<TX_NUM_FDESC){
- if (fda_ptr->fd.FDStat||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){
- fda_ptr =(struct tx_fda_ent*) __dma_va((struct tx_fda_ent*)fda_ptr->fd.FDNext);
- }
- else {
- break;
- }
- i++;
- }
-
- /* Write the skb data from the cache*/
- consistent_sync(skb->data,skb->len,PCI_DMA_TODEVICE);
- fda_ptr->bd.BuffData=(char*)__pa(skb->data);
- fda_ptr->bd.BuffLength=(unsigned short)skb->len;
- /* Save the pointer to the skb for freeing later */
- fda_ptr->fd.FDSystem=(unsigned int)skb;
- fda_ptr->fd.FDStat=0;
- /* Pass ownership of the buffers to the controller */
- fda_ptr->fd.FDCtl=1;
- fda_ptr->fd.FDCtl|=FDCTL_COWNSFD_MSK;
-
- /* If the next buffer in the list is full, stop the queue */
- fda_ptr=(struct tx_fda_ent*)__dma_va(fda_ptr->fd.FDNext);
- if ((fda_ptr->fd.FDStat)||(fda_ptr->fd.FDCtl & FDCTL_COWNSFD_MSK)){
- netif_stop_queue(dev);
- priv->queue_stopped=1;
- }
-
- return 0;
-}
-
-static struct net_device_stats *ether00_stats(struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- return &priv->stats;
-}
-
-
-static int ether00_stop(struct net_device* dev)
-{
- struct net_priv *priv=dev->priv;
- int tmp;
-
- /* Stop/disable the device. */
- tmp=readw(ETHER_RX_CTL(dev->base_addr));
- tmp&=~(ETHER_RX_CTL_RXEN_MSK | ETHER_RX_CTL_ENGOOD_MSK);
- tmp|=ETHER_RX_CTL_RXHALT_MSK;
- writew(tmp,ETHER_RX_CTL(dev->base_addr));
-
- tmp=readl(ETHER_TX_CTL(dev->base_addr));
- tmp&=~ETHER_TX_CTL_TXEN_MSK;
- tmp|=ETHER_TX_CTL_TXHALT_MSK;
- writel(tmp,ETHER_TX_CTL(dev->base_addr));
-
- /* Free up system resources */
- free_irq(dev->irq,dev);
- free_irq(2,dev);
- iounmap(priv->dma_data);
-
- return 0;
-}
-
-
-static void ether00_get_ethernet_address(struct net_device* dev)
-{
- struct mtd_info *mymtd=NULL;
- int i;
- size_t retlen;
-
- /*
- * For the Epxa10 dev board (camelot), the ethernet MAC
- * address is of the form 00:aa:aa:00:xx:xx where
- * 00:aa:aa is the Altera vendor ID and xx:xx is the
- * last 2 bytes of the board serial number, as programmed
- * into the OTP area of the flash device on EBI1. If this
- * isn't an expa10 dev board, or there's no mtd support to
- * read the serial number from flash then we'll force the
- * use to set their own mac address using ifconfig.
- */
-
-#ifdef CONFIG_ARCH_CAMELOT
-#ifdef CONFIG_MTD
- /* get the mtd_info structure for the first mtd device*/
- for(i=0;i<MAX_MTD_DEVICES;i++){
- mymtd=get_mtd_device(NULL,i);
- if(!mymtd||!strcmp(mymtd->name,"EPXA10DB flash"))
- break;
- }
-
- if(!mymtd || !mymtd->read_user_prot_reg){
- printk(KERN_WARNING "%s: Failed to read MAC address from flash\n",dev->name);
- }else{
- mymtd->read_user_prot_reg(mymtd,2,1,&retlen,&dev->dev_addr[5]);
- mymtd->read_user_prot_reg(mymtd,3,1,&retlen,&dev->dev_addr[4]);
- dev->dev_addr[3]=0;
- dev->dev_addr[2]=vendor_id[1];
- dev->dev_addr[1]=vendor_id[0];
- dev->dev_addr[0]=0;
- }
-#else
- printk(KERN_WARNING "%s: MTD support required to read MAC address from EPXA10 dev board\n", dev->name);
-#endif
-#endif
-
- if (!is_valid_ether_addr(dev->dev_addr))
- printk("%s: Invalid ethernet MAC address. Please set using "
- "ifconfig\n", dev->name);
-
-}
-
-/*
- * Keep a mapping of dev_info addresses -> port lines to use when
- * removing ports dev==NULL indicates unused entry
- */
-
-
-static struct net_device* dev_list[ETH_NR];
-
-static int ether00_add_device(struct pldhs_dev_info* dev_info,void* dev_ps_data)
-{
- struct net_device *dev;
- struct net_priv *priv;
- void *map_addr;
- int result;
- int i;
-
- i=0;
- while(dev_list[i] && i < ETH_NR)
- i++;
-
- if(i==ETH_NR){
- printk(KERN_WARNING "ether00: Maximum number of ports reached\n");
- return 0;
- }
-
-
- if (!request_mem_region(dev_info->base_addr, MAC_REG_SIZE, "ether00"))
- return -EBUSY;
-
- dev = alloc_etherdev(sizeof(struct net_priv));
- if(!dev) {
- result = -ENOMEM;
- goto out_release;
- }
- priv = dev->priv;
-
- priv->tq_memupdate.routine=ether00_mem_update;
- priv->tq_memupdate.data=(void*) dev;
-
- spin_lock_init(&priv->rx_lock);
-
- map_addr=ioremap_nocache(dev_info->base_addr,SZ_4K);
- if(!map_addr){
- result = -ENOMEM;
- out_kfree;
- }
-
- dev->open=ether00_open;
- dev->stop=ether00_stop;
- dev->set_multicast_list=ether00_set_multicast;
- dev->hard_start_xmit=ether00_tx;
- dev->get_stats=ether00_stats;
-
- ether00_get_ethernet_address(dev);
-
- SET_MODULE_OWNER(dev);
-
- dev->base_addr=(unsigned int)map_addr;
- dev->irq=dev_info->irq;
- dev->features=NETIF_F_DYNALLOC | NETIF_F_HW_CSUM;
-
- result=register_netdev(dev);
- if(result){
- printk("Ether00: Error %i registering driver\n",result);
- goto out_unmap;
- }
- printk("registered ether00 device at %#x\n",dev_info->base_addr);
-
- dev_list[i]=dev;
-
- return result;
-
- out_unmap:
- iounmap(map_addr);
- out_kfree:
- free_netdev(dev);
- out_release:
- release_mem_region(dev_info->base_addr, MAC_REG_SIZE);
- return result;
-}
-
-
-static int ether00_remove_devices(void)
-{
- int i;
-
- for(i=0;i<ETH_NR;i++){
- if(dev_list[i]){
- netif_device_detach(dev_list[i]);
- unregister_netdev(dev_list[i]);
- iounmap((void*)dev_list[i]->base_addr);
- release_mem_region(dev_list[i]->base_addr, MAC_REG_SIZE);
- free_netdev(dev_list[i]);
- dev_list[i]=0;
- }
- }
- return 0;
-}
-
-static struct pld_hotswap_ops ether00_pldhs_ops={
- .name = ETHER00_NAME,
- .add_device = ether00_add_device,
- .remove_devices = ether00_remove_devices,
-};
-
-
-static void __exit ether00_cleanup_module(void)
-{
- int result;
- result=ether00_remove_devices();
- if(result)
- printk(KERN_WARNING "ether00: failed to remove all devices\n");
-
- pldhs_unregister_driver(ETHER00_NAME);
-}
-module_exit(ether00_cleanup_module);
-
-
-static int __init ether00_mod_init(void)
-{
- printk("mod init\n");
- return pldhs_register_driver(&ether00_pldhs_ops);
-
-}
-
-module_init(ether00_mod_init);
-
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 1cc53abc3a39..f1d5b1027ff7 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -69,7 +69,6 @@
#include <asm/system.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 942a2819576c..6a93b666eb72 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -50,7 +50,6 @@
#include <asm/system.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include "../8390.h"
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 7aa49b974dc5..df9d6e80c4f2 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2136,7 +2136,7 @@ static int __init b44_init(void)
/* Setup paramaters for syncing RX/TX DMA descriptors */
dma_desc_align_mask = ~(dma_desc_align_size - 1);
- dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
+ dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
return pci_module_init(&b44_driver);
}
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index cf50384b469e..5cdae2bc055a 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -4,5 +4,5 @@
obj-$(CONFIG_BONDING) += bonding.o
-bonding-objs := bond_main.o bond_3ad.o bond_alb.o
+bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index d2f34d5a8083..f3f5825469d6 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -18,38 +18,6 @@
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
- *
- * Changes:
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Amir Noam <amir.noam at intel dot com>
- * - Added support for lacp_rate module param.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Based on discussion on mailing list, changed locking scheme
- * to use lock/unlock or lock_bh/unlock_bh appropriately instead
- * of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
- * hidden bugs and solves system hangs that occurred due to the fact
- * that holding lock_irqsave doesn't prevent softirqs from running.
- * This also increases total throughput since interrupts are not
- * blocked on each transmitted packets or monitor timeout.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Renamed bond_3ad_link_status_changed() to
- * bond_3ad_handle_link_change() for compatibility with TLB.
- *
- * 2003/05/20 - Amir Noam <amir.noam at intel dot com>
- * - Fix long fail over time when releasing last slave of an active
- * aggregator - send LACPDU on unbind of slave to tell partner this
- * port is no longer aggregatable.
- *
- * 2003/06/25 - Tsippy Mendelson <tsippy.mendelson at intel dot com>
- * - Send LACPDU as highest priority packet to further fix the above
- * problem on very high Tx traffic load where packets may get dropped
- * by the slave.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Code cleanup and style changes
*/
//#define BONDING_DEBUG 1
@@ -1198,10 +1166,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// detect loopback situation
if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
// INFO_RECEIVED_LOOPBACK_FRAMES
- printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
- port->slave->dev->name);
- printk(KERN_ERR "Check the configuration to verify that all Adapters "
- "are connected to 802.3ad compliant switch ports\n");
+ printk(KERN_ERR DRV_NAME ": %s: An illegal loopback occurred on "
+ "adapter (%s). Check the configuration to verify that all "
+ "Adapters are connected to 802.3ad compliant switch ports\n",
+ port->slave->dev->master->name, port->slave->dev->name);
__release_rx_machine_lock(port);
return;
}
@@ -1378,8 +1346,9 @@ static void ad_port_selection_logic(struct port *port)
}
}
if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
- printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: Port %d (on %s) was "
"related to aggregator %d but was not on its port list\n",
+ port->slave->dev->master->name,
port->actor_port_number, port->slave->dev->name,
port->aggregator->aggregator_identifier);
}
@@ -1450,7 +1419,8 @@ static void ad_port_selection_logic(struct port *port)
dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
} else {
- printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
+ printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n",
+ port->slave->dev->master->name,
port->actor_port_number, port->slave->dev->name);
}
}
@@ -1582,8 +1552,9 @@ static void ad_agg_selection_logic(struct aggregator *aggregator)
// check if any partner replys
if (best_aggregator->is_individual) {
- printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
- "for any adapters in the bond\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from "
+ "the link partner for any adapters in the bond\n",
+ best_aggregator->slave->dev->master->name);
}
// check if there are more than one aggregator
@@ -1915,7 +1886,8 @@ int bond_3ad_bind_slave(struct slave *slave)
struct aggregator *aggregator;
if (bond == NULL) {
- printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
+ printk(KERN_ERR DRV_NAME ": %s: The slave %s is not attached to its bond\n",
+ slave->dev->master->name, slave->dev->name);
return -1;
}
@@ -1990,7 +1962,9 @@ void bond_3ad_unbind_slave(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: Trying to "
+ "unbind an uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2021,7 +1995,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
- printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ aggregator->slave->dev->master->name);
// select new active aggregator
select_new_active_agg = 1;
}
@@ -2051,15 +2026,17 @@ void bond_3ad_unbind_slave(struct slave *slave)
ad_agg_selection_logic(__get_first_agg(port));
}
} else {
- printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
- "and could not find a new aggregator for its ports\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: unbinding aggregator, "
+ "and could not find a new aggregator for its ports\n",
+ slave->dev->master->name);
}
} else { // in case that the only port related to this aggregator is the one we want to remove
select_new_active_agg = aggregator->is_active;
// clear the aggregator
ad_clear_agg(aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO "Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2085,7 +2062,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
// clear the aggregator
ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
- printk(KERN_INFO "Removing an active aggregator\n");
+ printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
+ slave->dev->master->name);
// select new active aggregator
ad_agg_selection_logic(__get_first_agg(port));
}
@@ -2131,7 +2109,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
// select the active aggregator for the bond
if ((port = __get_first_port(bond))) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: bond's first port is "
+ "uninitialized\n", bond->dev->name);
goto re_arm;
}
@@ -2143,7 +2122,8 @@ void bond_3ad_state_machine_handler(struct bonding *bond)
// for each port run the state machines
for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: Found an uninitialized "
+ "port\n", bond->dev->name);
goto re_arm;
}
@@ -2184,7 +2164,8 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
port = &(SLAVE_AD_INFO(slave).port);
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: port of slave %s is "
+ "uninitialized\n", slave->dev->name, slave->dev->master->name);
return;
}
@@ -2230,8 +2211,9 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: speed "
+ "changed for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2257,8 +2239,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: duplex changed "
+ "for uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2285,8 +2268,9 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
// if slave is null, the whole port is not initialized
if (!port->slave) {
- printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
- slave->dev->name);
+ printk(KERN_WARNING DRV_NAME ": Warning: %s: link status changed for "
+ "uninitialized port on %s\n",
+ slave->dev->master->name, slave->dev->name);
return;
}
@@ -2363,7 +2347,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
}
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
- printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
+ printk(KERN_DEBUG DRV_NAME ": %s: Error: "
+ "bond_3ad_get_active_agg_info failed\n", dev->name);
goto out;
}
@@ -2372,7 +2357,9 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
if (slaves_in_agg == 0) {
/*the aggregator is empty*/
- printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
+ printk(KERN_DEBUG DRV_NAME ": %s: Error: active "
+ "aggregator is empty\n",
+ dev->name);
goto out;
}
@@ -2390,7 +2377,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
}
if (slave_agg_no >= 0) {
- printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+ printk(KERN_ERR DRV_NAME ": %s: Error: Couldn't find a slave to tx on "
+ "for aggregator ID %d\n", dev->name, agg_id);
goto out;
}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 673a30af5660..5ee2cef5b037 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -18,19 +18,6 @@
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
- *
- * Changes:
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Amir Noam <amir.noam at intel dot com>
- * - Added support for lacp_rate module param.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Renamed bond_3ad_link_status_changed() to
- * bond_3ad_handle_link_change() for compatibility with TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Code cleanup and style changes
*/
#ifndef __BOND_3AD_H__
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index f8fce3961197..f2a63186ae05 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -18,25 +18,6 @@
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
- *
- * Changes:
- *
- * 2003/06/25 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Fixed signed/unsigned calculation errors that caused load sharing
- * to collapse to one slave under very heavy UDP Tx stress.
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- * - Add support for setting bond's MAC address with special
- * handling required for ALB/TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Code cleanup and style changes
- *
- * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
- * - Fixed: Cannot remove and re-enslave the original active slave.
- *
- * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Add capability to tag self generated packets in ALB/TLB modes.
*/
//#define BONDING_DEBUG 1
@@ -188,9 +169,9 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
index = next_index;
}
- _unlock_tx_hashtbl(bond);
-
tlb_init_slave(slave);
+
+ _unlock_tx_hashtbl(bond);
}
/* Must be called before starting the monitor timer */
@@ -198,20 +179,21 @@ static int tlb_initialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
int size = TLB_HASH_TABLE_SIZE * sizeof(struct tlb_client_info);
+ struct tlb_client_info *new_hashtbl;
int i;
spin_lock_init(&(bond_info->tx_hashtbl_lock));
- _lock_tx_hashtbl(bond);
-
- bond_info->tx_hashtbl = kmalloc(size, GFP_KERNEL);
- if (!bond_info->tx_hashtbl) {
+ new_hashtbl = kmalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: Failed to allocate TLB hash table\n",
+ ": %s: Error: Failed to allocate TLB hash table\n",
bond->dev->name);
- _unlock_tx_hashtbl(bond);
return -1;
}
+ _lock_tx_hashtbl(bond);
+
+ bond_info->tx_hashtbl = new_hashtbl;
memset(bond_info->tx_hashtbl, 0, size);
@@ -513,7 +495,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
client_info->mac_dst);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to create an ARP packet\n");
+ ": %s: Error: failed to create an ARP packet\n",
+ client_info->slave->dev->master->name);
continue;
}
@@ -523,7 +506,8 @@ static void rlb_update_client(struct rlb_client_info *client_info)
skb = vlan_put_tag(skb, client_info->vlan_id);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to insert VLAN tag\n");
+ ": %s: Error: failed to insert VLAN tag\n",
+ client_info->slave->dev->master->name);
continue;
}
}
@@ -606,8 +590,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, u32 src_ip)
if (!client_info->slave) {
printk(KERN_ERR DRV_NAME
- ": Error: found a client with no channel in "
- "the client's hash table\n");
+ ": %s: Error: found a client with no channel in "
+ "the client's hash table\n",
+ bond->dev->name);
continue;
}
/*update all clients using this src_ip, that are not assigned
@@ -797,21 +782,22 @@ static int rlb_initialize(struct bonding *bond)
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct packet_type *pk_type = &(BOND_ALB_INFO(bond).rlb_pkt_type);
+ struct rlb_client_info *new_hashtbl;
int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
int i;
spin_lock_init(&(bond_info->rx_hashtbl_lock));
- _lock_rx_hashtbl(bond);
-
- bond_info->rx_hashtbl = kmalloc(size, GFP_KERNEL);
- if (!bond_info->rx_hashtbl) {
+ new_hashtbl = kmalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: Failed to allocate RLB hash table\n",
+ ": %s: Error: Failed to allocate RLB hash table\n",
bond->dev->name);
- _unlock_rx_hashtbl(bond);
return -1;
}
+ _lock_rx_hashtbl(bond);
+
+ bond_info->rx_hashtbl = new_hashtbl;
bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
@@ -927,7 +913,8 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
skb = vlan_put_tag(skb, vlan->vlan_id);
if (!skb) {
printk(KERN_ERR DRV_NAME
- ": Error: failed to insert VLAN tag\n");
+ ": %s: Error: failed to insert VLAN tag\n",
+ bond->dev->name);
continue;
}
}
@@ -956,11 +943,11 @@ static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
s_addr.sa_family = dev->type;
if (dev_set_mac_address(dev, &s_addr)) {
printk(KERN_ERR DRV_NAME
- ": Error: dev_set_mac_address of dev %s failed! ALB "
+ ": %s: Error: dev_set_mac_address of dev %s failed! ALB "
"mode requires that the base driver support setting "
"the hw address also when the network device's "
"interface is open\n",
- dev->name);
+ dev->master->name, dev->name);
return -EOPNOTSUPP;
}
return 0;
@@ -1153,16 +1140,16 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
bond->alb_info.rlb_enabled);
printk(KERN_WARNING DRV_NAME
- ": Warning: the hw address of slave %s is in use by "
+ ": %s: Warning: the hw address of slave %s is in use by "
"the bond; giving it the hw address of %s\n",
- slave->dev->name, free_mac_slave->dev->name);
+ bond->dev->name, slave->dev->name, free_mac_slave->dev->name);
} else if (has_bond_addr) {
printk(KERN_ERR DRV_NAME
- ": Error: the hw address of slave %s is in use by the "
+ ": %s: Error: the hw address of slave %s is in use by the "
"bond; couldn't find a slave with a free hw address to "
"give it (this should not have happened)\n",
- slave->dev->name);
+ bond->dev->name, slave->dev->name);
return -EFAULT;
}
@@ -1250,6 +1237,8 @@ int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
tlb_deinitialize(bond);
return res;
}
+ } else {
+ bond->alb_info.rlb_enabled = 0;
}
return 0;
@@ -1409,7 +1398,7 @@ void bond_alb_monitor(struct bonding *bond)
read_lock(&bond->curr_slave_lock);
bond_for_each_slave(bond, slave, i) {
- alb_send_learning_packets(slave,slave->dev->dev_addr);
+ alb_send_learning_packets(slave, slave->dev->dev_addr);
}
read_unlock(&bond->curr_slave_lock);
diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
index e4091cd8d654..28f2a2fd1b5a 100644
--- a/drivers/net/bonding/bond_alb.h
+++ b/drivers/net/bonding/bond_alb.h
@@ -18,15 +18,6 @@
* The full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
- *
- * Changes:
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- * - Add support for setting bond's MAC address with special
- * handling required for ALB/TLB.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Code cleanup and style changes
*/
#ifndef __BOND_ALB_H__
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94cec3cf2a13..2582d98ef5c3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -29,466 +29,6 @@
* b: if a hw mac address already is there, eth0's hw mac address
* will then be set from bond0.
*
- * v0.1 - first working version.
- * v0.2 - changed stats to be calculated by summing slaves stats.
- *
- * Changes:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- * - fix leaks on failure at bond_init
- *
- * 2000/09/30 - Willy Tarreau <willy at meta-x.org>
- * - added trivial code to release a slave device.
- * - fixed security bug (CAP_NET_ADMIN not checked)
- * - implemented MII link monitoring to disable dead links :
- * All MII capable slaves are checked every <miimon> milliseconds
- * (100 ms seems good). This value can be changed by passing it to
- * insmod. A value of zero disables the monitoring (default).
- * - fixed an infinite loop in bond_xmit_roundrobin() when there's no
- * good slave.
- * - made the code hopefully SMP safe
- *
- * 2000/10/03 - Willy Tarreau <willy at meta-x.org>
- * - optimized slave lists based on relevant suggestions from Thomas Davis
- * - implemented active-backup method to obtain HA with two switches:
- * stay as long as possible on the same active interface, while we
- * also monitor the backup one (MII link status) because we want to know
- * if we are able to switch at any time. ( pass "mode=1" to insmod )
- * - lots of stress testings because we need it to be more robust than the
- * wires ! :->
- *
- * 2000/10/09 - Willy Tarreau <willy at meta-x.org>
- * - added up and down delays after link state change.
- * - optimized the slaves chaining so that when we run forward, we never
- * repass through the bond itself, but we can find it by searching
- * backwards. Renders the deletion more difficult, but accelerates the
- * scan.
- * - smarter enslaving and releasing.
- * - finer and more robust SMP locking
- *
- * 2000/10/17 - Willy Tarreau <willy at meta-x.org>
- * - fixed two potential SMP race conditions
- *
- * 2000/10/18 - Willy Tarreau <willy at meta-x.org>
- * - small fixes to the monitoring FSM in case of zero delays
- * 2000/11/01 - Willy Tarreau <willy at meta-x.org>
- * - fixed first slave not automatically used in trunk mode.
- * 2000/11/10 : spelling of "EtherChannel" corrected.
- * 2000/11/13 : fixed a race condition in case of concurrent accesses to ioctl().
- * 2000/12/16 : fixed improper usage of rtnl_exlock_nowait().
- *
- * 2001/1/3 - Chad N. Tindel <ctindel at ieee dot org>
- * - The bonding driver now simulates MII status monitoring, just like
- * a normal network device. It will show that the link is down iff
- * every slave in the bond shows that their links are down. If at least
- * one slave is up, the bond's MII status will appear as up.
- *
- * 2001/2/7 - Chad N. Tindel <ctindel at ieee dot org>
- * - Applications can now query the bond from user space to get
- * information which may be useful. They do this by calling
- * the BOND_INFO_QUERY ioctl. Once the app knows how many slaves
- * are in the bond, it can call the BOND_SLAVE_INFO_QUERY ioctl to
- * get slave specific information (# link failures, etc). See
- * <linux/if_bonding.h> for more details. The structs of interest
- * are ifbond and ifslave.
- *
- * 2001/4/5 - Chad N. Tindel <ctindel at ieee dot org>
- * - Ported to 2.4 Kernel
- *
- * 2001/5/2 - Jeffrey E. Mast <jeff at mastfamily dot com>
- * - When a device is detached from a bond, the slave device is no longer
- * left thinking that is has a master.
- *
- * 2001/5/16 - Jeffrey E. Mast <jeff at mastfamily dot com>
- * - memset did not appropriately initialized the bond rw_locks. Used
- * rwlock_init to initialize to unlocked state to prevent deadlock when
- * first attempting a lock
- * - Called SET_MODULE_OWNER for bond device
- *
- * 2001/5/17 - Tim Anderson <tsa at mvista.com>
- * - 2 paths for releasing for slave release; 1 through ioctl
- * and 2) through close. Both paths need to release the same way.
- * - the free slave in bond release is changing slave status before
- * the free. The netdev_set_master() is intended to change slave state
- * so it should not be done as part of the release process.
- * - Simple rule for slave state at release: only the active in A/B and
- * only one in the trunked case.
- *
- * 2001/6/01 - Tim Anderson <tsa at mvista.com>
- * - Now call dev_close when releasing a slave so it doesn't screw up
- * out routing table.
- *
- * 2001/6/01 - Chad N. Tindel <ctindel at ieee dot org>
- * - Added /proc support for getting bond and slave information.
- * Information is in /proc/net/<bond device>/info.
- * - Changed the locking when calling bond_close to prevent deadlock.
- *
- * 2001/8/05 - Janice Girouard <girouard at us.ibm.com>
- * - correct problem where refcnt of slave is not incremented in bond_ioctl
- * so the system hangs when halting.
- * - correct locking problem when unable to malloc in bond_enslave.
- * - adding bond_xmit_xor logic.
- * - adding multiple bond device support.
- *
- * 2001/8/13 - Erik Habbinga <erik_habbinga at hp dot com>
- * - correct locking problem with rtnl_exlock_nowait
- *
- * 2001/8/23 - Janice Girouard <girouard at us.ibm.com>
- * - bzero initial dev_bonds, to correct oops
- * - convert SIOCDEVPRIVATE to new MII ioctl calls
- *
- * 2001/9/13 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- * - Add the BOND_CHANGE_ACTIVE ioctl implementation
- *
- * 2001/9/14 - Mark Huth <mhuth at mvista dot com>
- * - Change MII_LINK_READY to not check for end of auto-negotiation,
- * but only for an up link.
- *
- * 2001/9/20 - Chad N. Tindel <ctindel at ieee dot org>
- * - Add the device field to bonding_t. Previously the net_device
- * corresponding to a bond wasn't available from the bonding_t
- * structure.
- *
- * 2001/9/25 - Janice Girouard <girouard at us.ibm.com>
- * - add arp_monitor for active backup mode
- *
- * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
- * - Various memory leak fixes
- *
- * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
- * - Don't take rtnl lock in bond_mii_monitor as it deadlocks under
- * certain hotswap conditions.
- * Note: this same change may be required in bond_arp_monitor ???
- * - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr
- * - Handle hot swap ethernet interface deregistration events to remove
- * kernel oops following hot swap of enslaved interface
- *
- * 2002/1/2 - Chad N. Tindel <ctindel at ieee dot org>
- * - Restore original slave flags at release time.
- *
- * 2002/02/18 - Erik Habbinga <erik_habbinga at hp dot com>
- * - bond_release(): calling kfree on our_slave after call to
- * bond_restore_slave_flags, not before
- * - bond_enslave(): saving slave flags into original_flags before
- * call to netdev_set_master, so the IFF_SLAVE flag doesn't end
- * up in original_flags
- *
- * 2002/04/05 - Mark Smith <mark.smith at comdev dot cc> and
- * Steve Mead <steve.mead at comdev dot cc>
- * - Port Gleb Natapov's multicast support patchs from 2.4.12
- * to 2.4.18 adding support for multicast.
- *
- * 2002/06/10 - Tony Cureington <tony.cureington * hp_com>
- * - corrected uninitialized pointer (ifr.ifr_data) in bond_check_dev_link;
- * actually changed function to use MIIPHY, then MIIREG, and finally
- * ETHTOOL to determine the link status
- * - fixed bad ifr_data pointer assignments in bond_ioctl
- * - corrected mode 1 being reported as active-backup in bond_get_info;
- * also added text to distinguish type of load balancing (rr or xor)
- * - change arp_ip_target module param from "1-12s" (array of 12 ptrs)
- * to "s" (a single ptr)
- *
- * 2002/08/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Removed acquisition of xmit_lock in set_multicast_list; caused
- * deadlock on SMP (lock is held by caller).
- * - Revamped SIOCGMIIPHY, SIOCGMIIREG portion of bond_check_dev_link().
- *
- * 2002/09/18 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Fixed up bond_check_dev_link() (and callers): removed some magic
- * numbers, banished local MII_ defines, wrapped ioctl calls to
- * prevent EFAULT errors
- *
- * 2002/9/30 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - make sure the ip target matches the arp_target before saving the
- * hw address.
- *
- * 2002/9/30 - Dan Eisner <eisner at 2robots dot com>
- * - make sure my_ip is set before taking down the link, since
- * not all switches respond if the source ip is not set.
- *
- * 2002/10/8 - Janice Girouard <girouard at us dot ibm dot com>
- * - read in the local ip address when enslaving a device
- * - add primary support
- * - make sure 2*arp_interval has passed when a new device
- * is brought on-line before taking it down.
- *
- * 2002/09/11 - Philippe De Muyter <phdm at macqel dot be>
- * - Added bond_xmit_broadcast logic.
- * - Added bond_mode() support function.
- *
- * 2002/10/26 - Laurent Deniel <laurent.deniel at free.fr>
- * - allow to register multicast addresses only on active slave
- * (useful in active-backup mode)
- * - add multicast module parameter
- * - fix deletion of multicast groups after unloading module
- *
- * 2002/11/06 - Kameshwara Rayaprolu <kameshwara.rao * wipro_com>
- * - Changes to prevent panic from closing the device twice; if we close
- * the device in bond_release, we must set the original_flags to down
- * so it won't be closed again by the network layer.
- *
- * 2002/11/07 - Tony Cureington <tony.cureington * hp_com>
- * - Fix arp_target_hw_addr memory leak
- * - Created activebackup_arp_monitor function to handle arp monitoring
- * in active backup mode - the bond_arp_monitor had several problems...
- * such as allowing slaves to tx arps sequentially without any delay
- * for a response
- * - Renamed bond_arp_monitor to loadbalance_arp_monitor and re-wrote
- * this function to just handle arp monitoring in load-balancing mode;
- * it is a lot more compact now
- * - Changes to ensure one and only one slave transmits in active-backup
- * mode
- * - Robustesize parameters; warn users about bad combinations of
- * parameters; also if miimon is specified and a network driver does
- * not support MII or ETHTOOL, inform the user of this
- * - Changes to support link_failure_count when in arp monitoring mode
- * - Fix up/down delay reported in /proc
- * - Added version; log version; make version available from "modinfo -d"
- * - Fixed problem in bond_check_dev_link - if the first IOCTL (SIOCGMIIPH)
- * failed, the ETHTOOL ioctl never got a chance
- *
- * 2002/11/16 - Laurent Deniel <laurent.deniel at free.fr>
- * - fix multicast handling in activebackup_arp_monitor
- * - remove one unnecessary and confusing curr_active_slave == slave test
- * in activebackup_arp_monitor
- *
- * 2002/11/17 - Laurent Deniel <laurent.deniel at free.fr>
- * - fix bond_slave_info_query when slave_id = num_slaves
- *
- * 2002/11/19 - Janice Girouard <girouard at us dot ibm dot com>
- * - correct ifr_data reference. Update ifr_data reference
- * to mii_ioctl_data struct values to avoid confusion.
- *
- * 2002/11/22 - Bert Barbe <bert.barbe at oracle dot com>
- * - Add support for multiple arp_ip_target
- *
- * 2002/12/13 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Changed to allow text strings for mode and multicast, e.g.,
- * insmod bonding mode=active-backup. The numbers still work.
- * One change: an invalid choice will cause module load failure,
- * rather than the previous behavior of just picking one.
- * - Minor cleanups; got rid of dup ctype stuff, atoi function
- *
- * 2003/02/07 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Added use_carrier module parameter that causes miimon to
- * use netif_carrier_ok() test instead of MII/ETHTOOL ioctls.
- * - Minor cleanups; consolidated ioctl calls to one function.
- *
- * 2003/02/07 - Tony Cureington <tony.cureington * hp_com>
- * - Fix bond_mii_monitor() logic error that could result in
- * bonding round-robin mode ignoring links after failover/recovery
- *
- * 2003/03/17 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by
- * Shmulik dot Hen at intel.com.
- * - Based on discussion on mailing list, changed use of
- * update_slave_cnt(), created wrapper functions for adding/removing
- * slaves, changed bond_xmit_xor() to check slave_cnt instead of
- * checking slave and slave->dev (which only worked by accident).
- * - Misc code cleanup: get arp_send() prototype from header file,
- * add max_bonds to bonding.txt.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Make sure only bond_attach_slave() and bond_detach_slave() can
- * manipulate the slave list, including slave_cnt, even when in
- * bond_release_all().
- * - Fixed hang in bond_release() with traffic running:
- * netdev_set_master() must not be called from within the bond lock.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Fixed hang in bond_enslave() with traffic running:
- * netdev_set_master() must not be called from within the bond lock.
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>
- * - Added support for getting slave's speed and duplex via ethtool.
- * Needed for 802.3ad and other future modes.
- *
- * 2003/03/18 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Enable support of modes that need to use the unique mac address of
- * each slave.
- * * bond_enslave(): Moved setting the slave's mac address, and
- * openning it, from the application to the driver. This breaks
- * backward comaptibility with old versions of ifenslave that open
- * the slave before enalsving it !!!.
- * * bond_release(): The driver also takes care of closing the slave
- * and restoring its original mac address.
- * - Removed the code that restores all base driver's flags.
- * Flags are automatically restored once all undo stages are done
- * properly.
- * - Block possibility of enslaving before the master is up. This
- * prevents putting the system in an unstable state.
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
- * Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Added support for IEEE 802.3ad Dynamic link aggregation mode.
- *
- * 2003/05/01 - Amir Noam <amir.noam at intel dot com>
- * - Added ABI version control to restore compatibility between
- * new/old ifenslave and new/old bonding.
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Fixed bug in bond_release_all(): save old value of curr_active_slave
- * before setting it to NULL.
- * - Changed driver versioning scheme to include version number instead
- * of release date (that is already in another field). There are 3
- * fields X.Y.Z where:
- * X - Major version - big behavior changes
- * Y - Minor version - addition of features
- * Z - Extra version - minor changes and bug fixes
- * The current version is 1.0.0 as a base line.
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Amir Noam <amir.noam at intel dot com>
- * - Added support for lacp_rate module param.
- * - Code beautification and style changes (mainly in comments).
- * new version - 1.0.1
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Based on discussion on mailing list, changed locking scheme
- * to use lock/unlock or lock_bh/unlock_bh appropriately instead
- * of lock_irqsave/unlock_irqrestore. The new scheme helps exposing
- * hidden bugs and solves system hangs that occurred due to the fact
- * that holding lock_irqsave doesn't prevent softirqs from running.
- * This also increases total throughput since interrupts are not
- * blocked on each transmitted packets or monitor timeout.
- * new version - 2.0.0
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Added support for Transmit load balancing mode.
- * - Concentrate all assignments of curr_active_slave to a single point
- * so specific modes can take actions when the primary adapter is
- * changed.
- * - Take the updelay parameter into consideration during bond_enslave
- * since some adapters loose their link during setting the device.
- * - Renamed bond_3ad_link_status_changed() to
- * bond_3ad_handle_link_change() for compatibility with TLB.
- * new version - 2.1.0
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com>
- * - Added support for Adaptive load balancing mode which is
- * equivalent to Transmit load balancing + Receive load balancing.
- * new version - 2.2.0
- *
- * 2003/05/15 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Applied fix to activebackup_arp_monitor posted to bonding-devel
- * by Tony Cureington <tony.cureington * hp_com>. Fixes ARP
- * monitor endless failover bug. Version to 2.2.10
- *
- * 2003/05/20 - Amir Noam <amir.noam at intel dot com>
- * - Fixed bug in ABI version control - Don't commit to a specific
- * ABI version if receiving unsupported ioctl commands.
- *
- * 2003/05/22 - Jay Vosburgh <fubar at us dot ibm dot com>
- * - Fix ifenslave -c causing bond to loose existing routes;
- * added bond_set_mac_address() that doesn't require the
- * bond to be down.
- * - In conjunction with fix for ifenslave -c, in
- * bond_change_active(), changing to the already active slave
- * is no longer an error (it successfully does nothing).
- *
- * 2003/06/30 - Amir Noam <amir.noam at intel dot com>
- * - Fixed bond_change_active() for ALB/TLB modes.
- * Version to 2.2.14.
- *
- * 2003/07/29 - Amir Noam <amir.noam at intel dot com>
- * - Fixed ARP monitoring bug.
- * Version to 2.2.15.
- *
- * 2003/07/31 - Willy Tarreau <willy at ods dot org>
- * - Fixed kernel panic when using ARP monitoring without
- * setting bond's IP address.
- * Version to 2.2.16.
- *
- * 2003/08/06 - Amir Noam <amir.noam at intel dot com>
- * - Back port from 2.6: use alloc_netdev(); fix /proc handling;
- * made stats a part of bond struct so no need to allocate
- * and free it separately; use standard list operations instead
- * of pre-allocated array of bonds.
- * Version to 2.3.0.
- *
- * 2003/08/07 - Jay Vosburgh <fubar at us dot ibm dot com>,
- * Amir Noam <amir.noam at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Propagating master's settings: Distinguish between modes that
- * use a primary slave from those that don't, and propagate settings
- * accordingly; Consolidate change_active opeartions and add
- * reselect_active and find_best opeartions; Decouple promiscuous
- * handling from the multicast mode setting; Add support for changing
- * HW address and MTU with proper unwind; Consolidate procfs code,
- * add CHANGENAME handler; Enhance netdev notification handling.
- * Version to 2.4.0.
- *
- * 2003/09/15 - Stephen Hemminger <shemminger at osdl dot org>,
- * Amir Noam <amir.noam at intel dot com>
- * - Convert /proc to seq_file interface.
- * Change /proc/net/bondX/info to /proc/net/bonding/bondX.
- * Set version to 2.4.1.
- *
- * 2003/11/20 - Amir Noam <amir.noam at intel dot com>
- * - Fix /proc creation/destruction.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Massive cleanup - Set version to 2.5.0
- * Code changes:
- * o Consolidate format of prints and debug prints.
- * o Remove bonding_t/slave_t typedefs and consolidate all casts.
- * o Remove dead code and unnecessary checks.
- * o Consolidate starting/stopping timers.
- * o Consolidate handling of primary module param throughout the code.
- * o Removed multicast module param support - all settings are done
- * according to mode.
- * o Slave list iteration - bond is no longer part of the list,
- * added cyclic list iteration macros.
- * o Consolidate error handling in all xmit functions.
- * Style changes:
- * o Consolidate function naming and declarations.
- * o Consolidate function params and local variables names.
- * o Consolidate return values.
- * o Consolidate curly braces.
- * o Consolidate conditionals format.
- * o Change struct member names and types.
- * o Chomp trailing spaces, remove empty lines, fix indentations.
- * o Re-organize code according to context.
- *
- * 2003/12/30 - Amir Noam <amir.noam at intel dot com>
- * - Fixed: Cannot remove and re-enslave the original active slave.
- * - Fixed: Releasing the original active slave causes mac address
- * duplication.
- * - Add support for slaves that use ethtool_ops.
- * Set version to 2.5.3.
- *
- * 2004/01/05 - Amir Noam <amir.noam at intel dot com>
- * - Save bonding parameters per bond instead of using the global values.
- * Set version to 2.5.4.
- *
- * 2004/01/14 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Enhance VLAN support:
- * * Add support for VLAN hardware acceleration capable slaves.
- * * Add capability to tag self generated packets in ALB/TLB modes.
- * Set version to 2.6.0.
- * 2004/10/29 - Mitch Williams <mitch.a.williams at intel dot com>
- * - Fixed bug when unloading module while using 802.3ad. If
- * spinlock debugging is turned on, this causes a stack dump.
- * Solution is to move call to dev_remove_pack outside of the
- * spinlock.
- * Set version to 2.6.1.
- * 2005/06/05 - Jay Vosburgh <fubar@us.ibm.com>
- * - Support for generating gratuitous ARPs in active-backup mode.
- * Includes support for VLAN tagging all bonding-generated ARPs
- * as needed. Set version to 2.6.2.
- * 2005/06/08 - Jason Gabler <jygabler at lbl dot gov>
- * - alternate hashing policy support for mode 2
- * * Added kernel parameter "xmit_hash_policy" to allow the selection
- * of different hashing policies for mode 2. The original mode 2
- * policy is the default, now found in xmit_hash_policy_layer2().
- * * Added xmit_hash_policy_layer34()
- * - Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4.
- * Set version to 2.6.3.
- * 2005/09/26 - Jay Vosburgh <fubar@us.ibm.com>
- * - Removed backwards compatibility for old ifenslaves. Version 2.6.4.
*/
//#define BONDING_DEBUG 1
@@ -557,6 +97,7 @@ static char *lacp_rate = NULL;
static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+struct bond_params bonding_defaults;
module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
@@ -565,17 +106,24 @@ MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
module_param(updelay, int, 0);
MODULE_PARM_DESC(updelay, "Delay before considering link up, in milliseconds");
module_param(downdelay, int, 0);
-MODULE_PARM_DESC(downdelay, "Delay before considering link down, in milliseconds");
+MODULE_PARM_DESC(downdelay, "Delay before considering link down, "
+ "in milliseconds");
module_param(use_carrier, int, 0);
-MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)");
+MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; "
+ "0 for off, 1 for on (default)");
module_param(mode, charp, 0);
-MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor");
+MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
+ "1 for active-backup, 2 for balance-xor, "
+ "3 for broadcast, 4 for 802.3ad, 5 for balance-tlb, "
+ "6 for balance-alb");
module_param(primary, charp, 0);
MODULE_PARM_DESC(primary, "Primary network device to use");
module_param(lacp_rate, charp, 0);
-MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
+ "(slow/fast)");
module_param(xmit_hash_policy, charp, 0);
-MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4");
+MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
+ ", 1 for layer 3+4");
module_param(arp_interval, int, 0);
MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
module_param_array(arp_ip_target, charp, NULL, 0);
@@ -586,30 +134,27 @@ MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
static const char *version =
DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
-static LIST_HEAD(bond_dev_list);
+LIST_HEAD(bond_dev_list);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *bond_proc_dir = NULL;
#endif
+extern struct rw_semaphore bonding_rwsem;
static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
static int lacp_fast = 0;
-struct bond_parm_tbl {
- char *modename;
- int mode;
-};
-static struct bond_parm_tbl bond_lacp_tbl[] = {
+struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
{ "fast", AD_LACP_FAST},
{ NULL, -1},
};
-static struct bond_parm_tbl bond_mode_tbl[] = {
+struct bond_parm_tbl bond_mode_tbl[] = {
{ "balance-rr", BOND_MODE_ROUNDROBIN},
{ "active-backup", BOND_MODE_ACTIVEBACKUP},
{ "balance-xor", BOND_MODE_XOR},
@@ -620,7 +165,7 @@ static struct bond_parm_tbl bond_mode_tbl[] = {
{ NULL, -1},
};
-static struct bond_parm_tbl xmit_hashtype_tbl[] = {
+struct bond_parm_tbl xmit_hashtype_tbl[] = {
{ "layer2", BOND_XMIT_POLICY_LAYER2},
{ "layer3+4", BOND_XMIT_POLICY_LAYER34},
{ NULL, -1},
@@ -628,12 +173,11 @@ static struct bond_parm_tbl xmit_hashtype_tbl[] = {
/*-------------------------- Forward declarations ---------------------------*/
-static inline void bond_set_mode_ops(struct bonding *bond, int mode);
static void bond_send_gratuitous_arp(struct bonding *bond);
/*---------------------------- General routines -----------------------------*/
-static const char *bond_mode_name(int mode)
+const char *bond_mode_name(int mode)
{
switch (mode) {
case BOND_MODE_ROUNDROBIN :
@@ -910,7 +454,7 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
res = bond_add_vlan(bond, vid);
if (res) {
printk(KERN_ERR DRV_NAME
- ": %s: Failed to add vlan id %d\n",
+ ": %s: Error: Failed to add vlan id %d\n",
bond_dev->name, vid);
}
}
@@ -944,7 +488,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
res = bond_del_vlan(bond, vid);
if (res) {
printk(KERN_ERR DRV_NAME
- ": %s: Failed to remove vlan id %d\n",
+ ": %s: Error: Failed to remove vlan id %d\n",
bond_dev->name, vid);
}
}
@@ -1449,7 +993,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
{
struct slave *old_active = bond->curr_active_slave;
@@ -1523,7 +1067,7 @@ static void bond_change_active_slave(struct bonding *bond, struct slave *new_act
*
* Warning: Caller must hold curr_slave_lock for writing.
*/
-static void bond_select_active_slave(struct bonding *bond)
+void bond_select_active_slave(struct bonding *bond)
{
struct slave *best_slave;
@@ -1591,7 +1135,7 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
/*---------------------------------- IOCTL ----------------------------------*/
-static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
{
dprintk("bond_dev=%p\n", bond_dev);
dprintk("slave_dev=%p\n", slave_dev);
@@ -1631,7 +1175,7 @@ static int bond_compute_features(struct bonding *bond)
}
/* enslave device <slave> to bond device <master> */
-static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *new_slave = NULL;
@@ -1644,8 +1188,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
slave_dev->do_ioctl == NULL) {
printk(KERN_WARNING DRV_NAME
- ": Warning : no link monitoring support for %s\n",
- slave_dev->name);
+ ": %s: Warning: no link monitoring support for %s\n",
+ bond_dev->name, slave_dev->name);
}
/* bond must be initialized by bond_open() before enslaving */
@@ -1666,17 +1210,17 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
if (!list_empty(&bond->vlan_list)) {
printk(KERN_ERR DRV_NAME
- ": Error: cannot enslave VLAN "
+ ": %s: Error: cannot enslave VLAN "
"challenged slave %s on VLAN enabled "
- "bond %s\n", slave_dev->name,
+ "bond %s\n", bond_dev->name, slave_dev->name,
bond_dev->name);
return -EPERM;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: enslaved VLAN challenged "
+ ": %s: Warning: enslaved VLAN challenged "
"slave %s. Adding VLANs will be blocked as "
"long as %s is part of bond %s\n",
- slave_dev->name, slave_dev->name,
+ bond_dev->name, slave_dev->name, slave_dev->name,
bond_dev->name);
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
}
@@ -1706,12 +1250,11 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
if (slave_dev->set_mac_address == NULL) {
printk(KERN_ERR DRV_NAME
- ": Error: The slave device you specified does "
- "not support setting the MAC address.\n");
- printk(KERN_ERR
- "Your kernel likely does not support slave devices.\n");
-
- res = -EOPNOTSUPP;
+ ": %s: Error: The slave device you specified does "
+ "not support setting the MAC address. "
+ "Your kernel likely does not support slave "
+ "devices.\n", bond_dev->name);
+ res = -EOPNOTSUPP;
goto err_undo_flags;
}
@@ -1827,21 +1370,21 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
* the messages for netif_carrier.
*/
printk(KERN_WARNING DRV_NAME
- ": Warning: MII and ETHTOOL support not "
+ ": %s: Warning: MII and ETHTOOL support not "
"available for interface %s, and "
"arp_interval/arp_ip_target module parameters "
"not specified, thus bonding will not detect "
"link failures! see bonding.txt for details.\n",
- slave_dev->name);
+ bond_dev->name, slave_dev->name);
} else if (link_reporting == -1) {
/* unable get link status using mii/ethtool */
printk(KERN_WARNING DRV_NAME
- ": Warning: can't get link status from "
+ ": %s: Warning: can't get link status from "
"interface %s; the network driver associated "
"with this interface does not support MII or "
"ETHTOOL link status reporting, thus miimon "
"has no effect on this interface.\n",
- slave_dev->name);
+ bond_dev->name, slave_dev->name);
}
}
@@ -1868,15 +1411,15 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
if (bond_update_speed_duplex(new_slave) &&
(new_slave->link != BOND_LINK_DOWN)) {
printk(KERN_WARNING DRV_NAME
- ": Warning: failed to get speed and duplex from %s, "
+ ": %s: Warning: failed to get speed and duplex from %s, "
"assumed to be 100Mb/sec and Full.\n",
- new_slave->dev->name);
+ bond_dev->name, new_slave->dev->name);
if (bond->params.mode == BOND_MODE_8023AD) {
- printk(KERN_WARNING
- "Operation of 802.3ad mode requires ETHTOOL "
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: Operation of 802.3ad mode requires ETHTOOL "
"support in base driver for proper aggregator "
- "selection.\n");
+ "selection.\n", bond_dev->name);
}
}
@@ -1958,6 +1501,10 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
write_unlock_bh(&bond->lock);
+ res = bond_create_slave_symlinks(bond_dev, slave_dev);
+ if (res)
+ goto err_unset_master;
+
printk(KERN_INFO DRV_NAME
": %s: enslaving %s as a%s interface with a%s link.\n",
bond_dev->name, slave_dev->name,
@@ -1999,7 +1546,7 @@ err_undo_flags:
* for Bonded connections:
* The first up interface should be left on and all others downed.
*/
-static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2010,7 +1557,7 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
if (!(slave_dev->flags & IFF_SLAVE) ||
(slave_dev->master != bond_dev)) {
printk(KERN_ERR DRV_NAME
- ": Error: %s: cannot release %s.\n",
+ ": %s: Error: cannot release %s.\n",
bond_dev->name, slave_dev->name);
return -EINVAL;
}
@@ -2031,11 +1578,12 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
ETH_ALEN);
if (!mac_addr_differ && (bond->slave_cnt > 1)) {
printk(KERN_WARNING DRV_NAME
- ": Warning: the permanent HWaddr of %s "
+ ": %s: Warning: the permanent HWaddr of %s "
"- %02X:%02X:%02X:%02X:%02X:%02X - is "
"still in use by %s. Set the HWaddr of "
"%s to a different address to avoid "
"conflicts.\n",
+ bond_dev->name,
slave_dev->name,
slave->perm_hwaddr[0],
slave->perm_hwaddr[1],
@@ -2111,24 +1659,28 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: clearing HW address of %s while it "
+ ": %s: Warning: clearing HW address of %s while it "
"still has VLANs.\n",
- bond_dev->name);
+ bond_dev->name, bond_dev->name);
printk(KERN_WARNING DRV_NAME
- ": When re-adding slaves, make sure the bond's "
- "HW address matches its VLANs'.\n");
+ ": %s: When re-adding slaves, make sure the bond's "
+ "HW address matches its VLANs'.\n",
+ bond_dev->name);
}
} else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
!bond_has_challenged_slaves(bond)) {
printk(KERN_INFO DRV_NAME
- ": last VLAN challenged slave %s "
+ ": %s: last VLAN challenged slave %s "
"left bond %s. VLAN blocking is removed\n",
- slave_dev->name, bond_dev->name);
+ bond_dev->name, slave_dev->name, bond_dev->name);
bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED;
}
write_unlock_bh(&bond->lock);
+ /* must do this from outside any spinlocks */
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
+
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2220,6 +1772,7 @@ static int bond_release_all(struct net_device *bond_dev)
*/
write_unlock_bh(&bond->lock);
+ bond_destroy_slave_symlinks(bond_dev, slave_dev);
bond_del_vlans_from_slave(bond, slave_dev);
/* If the mode USES_PRIMARY, then we should only remove its
@@ -2274,12 +1827,13 @@ static int bond_release_all(struct net_device *bond_dev)
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
} else {
printk(KERN_WARNING DRV_NAME
- ": Warning: clearing HW address of %s while it "
+ ": %s: Warning: clearing HW address of %s while it "
"still has VLANs.\n",
- bond_dev->name);
+ bond_dev->name, bond_dev->name);
printk(KERN_WARNING DRV_NAME
- ": When re-adding slaves, make sure the bond's "
- "HW address matches its VLANs'.\n");
+ ": %s: When re-adding slaves, make sure the bond's "
+ "HW address matches its VLANs'.\n",
+ bond_dev->name);
}
printk(KERN_INFO DRV_NAME
@@ -2397,7 +1951,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
/*-------------------------------- Monitoring -------------------------------*/
/* this function is called regularly to monitor each slave's link. */
-static void bond_mii_monitor(struct net_device *bond_dev)
+void bond_mii_monitor(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2596,8 +2150,11 @@ static void bond_mii_monitor(struct net_device *bond_dev)
break;
default:
/* Should not happen */
- printk(KERN_ERR "bonding: Error: %s Illegal value (link=%d)\n",
- slave->dev->name, slave->link);
+ printk(KERN_ERR DRV_NAME
+ ": %s: Error: %s Illegal value (link=%d)\n",
+ bond_dev->name,
+ slave->dev->name,
+ slave->link);
goto out;
} /* end of switch (slave->link) */
@@ -2721,7 +2278,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
struct flowi fl;
struct rtable *rt;
- for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+ for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+ if (!targets[i])
+ continue;
dprintk("basa: target %x\n", targets[i]);
if (list_empty(&bond->vlan_list)) {
dprintk("basa: empty vlan: arp_send\n");
@@ -2825,7 +2384,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
* arp is transmitted to generate traffic. see activebackup_arp_monitor for
* arp monitoring in active backup mode.
*/
-static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
+void bond_loadbalance_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave, *oldcurrent;
@@ -2963,7 +2522,7 @@ out:
* may have received.
* see loadbalance_arp_monitor for arp monitoring in load balancing mode
*/
-static void bond_activebackup_arp_mon(struct net_device *bond_dev)
+void bond_activebackup_arp_mon(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
struct slave *slave;
@@ -3249,6 +2808,8 @@ static void bond_info_show_master(struct seq_file *seq)
{
struct bonding *bond = seq->private;
struct slave *curr;
+ int i;
+ u32 target;
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
@@ -3257,10 +2818,17 @@ static void bond_info_show_master(struct seq_file *seq)
seq_printf(seq, "Bonding Mode: %s\n",
bond_mode_name(bond->params.mode));
+ if (bond->params.mode == BOND_MODE_XOR ||
+ bond->params.mode == BOND_MODE_8023AD) {
+ seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
+ xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+ bond->params.xmit_policy);
+ }
+
if (USES_PRIMARY(bond->params.mode)) {
seq_printf(seq, "Primary Slave: %s\n",
- (bond->params.primary[0]) ?
- bond->params.primary : "None");
+ (bond->primary_slave) ?
+ bond->primary_slave->dev->name : "None");
seq_printf(seq, "Currently Active Slave: %s\n",
(curr) ? curr->dev->name : "None");
@@ -3273,6 +2841,27 @@ static void bond_info_show_master(struct seq_file *seq)
seq_printf(seq, "Down Delay (ms): %d\n",
bond->params.downdelay * bond->params.miimon);
+
+ /* ARP information */
+ if(bond->params.arp_interval > 0) {
+ int printed=0;
+ seq_printf(seq, "ARP Polling Interval (ms): %d\n",
+ bond->params.arp_interval);
+
+ seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
+
+ for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) {
+ if (!bond->params.arp_targets[i])
+ continue;
+ if (printed)
+ seq_printf(seq, ",");
+ target = ntohl(bond->params.arp_targets[i]);
+ seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target));
+ printed = 1;
+ }
+ seq_printf(seq, "\n");
+ }
+
if (bond->params.mode == BOND_MODE_8023AD) {
struct ad_info ad_info;
@@ -3478,7 +3067,10 @@ static int bond_event_changename(struct bonding *bond)
bond_remove_proc_entry(bond);
bond_create_proc_entry(bond);
#endif
-
+ down_write(&(bonding_rwsem));
+ bond_destroy_sysfs_entry(bond);
+ bond_create_sysfs_entry(bond);
+ up_write(&(bonding_rwsem));
return NOTIFY_DONE;
}
@@ -3955,6 +3547,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
return -EPERM;
}
+ down_write(&(bonding_rwsem));
slave_dev = dev_get_by_name(ifr->ifr_slave);
dprintk("slave_dev=%p: \n", slave_dev);
@@ -3987,6 +3580,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
dev_put(slave_dev);
}
+ up_write(&(bonding_rwsem));
return res;
}
@@ -4071,6 +3665,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
bond_for_each_slave(bond, slave, i) {
dprintk("s %p s->p %p c_m %p\n", slave,
slave->prev, slave->dev->change_mtu);
+
res = dev_set_mtu(slave->dev, new_mtu);
if (res) {
@@ -4397,8 +3992,9 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
if (!skb2) {
printk(KERN_ERR DRV_NAME
- ": Error: bond_xmit_broadcast(): "
- "skb_clone() failed\n");
+ ": %s: Error: bond_xmit_broadcast(): "
+ "skb_clone() failed\n",
+ bond_dev->name);
continue;
}
@@ -4431,7 +4027,7 @@ out:
/*
* set bond mode specific net device operations
*/
-static inline void bond_set_mode_ops(struct bonding *bond, int mode)
+void bond_set_mode_ops(struct bonding *bond, int mode)
{
struct net_device *bond_dev = bond->dev;
@@ -4467,7 +4063,8 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
default:
/* Should never happen, mode already checked */
printk(KERN_ERR DRV_NAME
- ": Error: Unknown bonding mode %d\n",
+ ": %s: Error: Unknown bonding mode %d\n",
+ bond_dev->name,
mode);
break;
}
@@ -4491,7 +4088,7 @@ static struct ethtool_ops bond_ethtool_ops = {
* Does not allocate but creates a /proc entry.
* Allowed to fail.
*/
-static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
+static int bond_init(struct net_device *bond_dev, struct bond_params *params)
{
struct bonding *bond = bond_dev->priv;
@@ -4565,7 +4162,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
/* De-initialize device specific data.
* Caller must hold rtnl_lock.
*/
-static inline void bond_deinit(struct net_device *bond_dev)
+void bond_deinit(struct net_device *bond_dev)
{
struct bonding *bond = bond_dev->priv;
@@ -4601,7 +4198,7 @@ static void bond_free_all(void)
* Convert string input module parms. Accept either the
* number of the mode or its string name.
*/
-static inline int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
{
int i;
@@ -4670,7 +4267,7 @@ static int bond_check_params(struct bond_params *params)
if (max_bonds < 1 || max_bonds > INT_MAX) {
printk(KERN_WARNING DRV_NAME
": Warning: max_bonds (%d) not in range %d-%d, so it "
- "was reset to BOND_DEFAULT_MAX_BONDS (%d)",
+ "was reset to BOND_DEFAULT_MAX_BONDS (%d)\n",
max_bonds, 1, INT_MAX, BOND_DEFAULT_MAX_BONDS);
max_bonds = BOND_DEFAULT_MAX_BONDS;
}
@@ -4881,81 +4478,96 @@ static int bond_check_params(struct bond_params *params)
return 0;
}
+/* Create a new bond based on the specified name and bonding parameters.
+ * Caller must NOT hold rtnl_lock; we need to release it here before we
+ * set up our sysfs entries.
+ */
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
+{
+ struct net_device *bond_dev;
+ int res;
+
+ rtnl_lock();
+ bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup);
+ if (!bond_dev) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: eek! can't alloc netdev!\n",
+ name);
+ res = -ENOMEM;
+ goto out_rtnl;
+ }
+
+ /* bond_init() must be called after dev_alloc_name() (for the
+ * /proc files), but before register_netdevice(), because we
+ * need to set function pointers.
+ */
+
+ res = bond_init(bond_dev, params);
+ if (res < 0) {
+ goto out_netdev;
+ }
+
+ SET_MODULE_OWNER(bond_dev);
+
+ res = register_netdevice(bond_dev);
+ if (res < 0) {
+ goto out_bond;
+ }
+ if (newbond)
+ *newbond = bond_dev->priv;
+
+ rtnl_unlock(); /* allows sysfs registration of net device */
+ res = bond_create_sysfs_entry(bond_dev->priv);
+ goto done;
+out_bond:
+ bond_deinit(bond_dev);
+out_netdev:
+ free_netdev(bond_dev);
+out_rtnl:
+ rtnl_unlock();
+done:
+ return res;
+}
+
static int __init bonding_init(void)
{
- struct bond_params params;
int i;
int res;
+ char new_bond_name[8]; /* Enough room for 999 bonds at init. */
printk(KERN_INFO "%s", version);
- res = bond_check_params(&params);
+ res = bond_check_params(&bonding_defaults);
if (res) {
- return res;
+ goto out;
}
- rtnl_lock();
-
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
-
for (i = 0; i < max_bonds; i++) {
- struct net_device *bond_dev;
-
- bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
- if (!bond_dev) {
- res = -ENOMEM;
- goto out_err;
- }
-
- res = dev_alloc_name(bond_dev, "bond%d");
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- /* bond_init() must be called after dev_alloc_name() (for the
- * /proc files), but before register_netdevice(), because we
- * need to set function pointers.
- */
- res = bond_init(bond_dev, &params);
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- SET_MODULE_OWNER(bond_dev);
-
- res = register_netdevice(bond_dev);
- if (res < 0) {
- bond_deinit(bond_dev);
- free_netdev(bond_dev);
- goto out_err;
- }
+ sprintf(new_bond_name, "bond%d",i);
+ res = bond_create(new_bond_name,&bonding_defaults, NULL);
+ if (res)
+ goto err;
}
- rtnl_unlock();
+ res = bond_create_sysfs();
+ if (res)
+ goto err;
+
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
- return 0;
-
-out_err:
- /*
- * rtnl_unlock() will run netdev_run_todo(), putting the
- * thus-far-registered bonding devices into a state which
- * unregigister_netdevice() will accept
- */
- rtnl_unlock();
+ goto out;
+err:
rtnl_lock();
-
- /* free and unregister all bonds that were successfully added */
bond_free_all();
-
+ bond_destroy_sysfs();
rtnl_unlock();
-
+out:
return res;
+
}
static void __exit bonding_exit(void)
@@ -4965,6 +4577,7 @@ static void __exit bonding_exit(void)
rtnl_lock();
bond_free_all();
+ bond_destroy_sysfs();
rtnl_unlock();
}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
new file mode 100644
index 000000000000..32d13da43a0b
--- /dev/null
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -0,0 +1,1358 @@
+
+/*
+ * Copyright(c) 2004-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 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.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/in.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
+#include <linux/rtnetlink.h>
+
+/* #define BONDING_DEBUG 1 */
+#include "bonding.h"
+#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
+#define to_net_dev(class) container_of(class, struct net_device, class_dev)
+#define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv))
+
+/*---------------------------- Declarations -------------------------------*/
+
+
+extern struct list_head bond_dev_list;
+extern struct bond_params bonding_defaults;
+extern struct bond_parm_tbl bond_mode_tbl[];
+extern struct bond_parm_tbl bond_lacp_tbl[];
+extern struct bond_parm_tbl xmit_hashtype_tbl[];
+
+static int expected_refcount = -1;
+static struct class *netdev_class;
+/*--------------------------- Data Structures -----------------------------*/
+
+/* Bonding sysfs lock. Why can't we just use the subsytem lock?
+ * Because kobject_register tries to acquire the subsystem lock. If
+ * we already hold the lock (which we would if the user was creating
+ * a new bond through the sysfs interface), we deadlock.
+ * This lock is only needed when deleting a bond - we need to make sure
+ * that we don't collide with an ongoing ioctl.
+ */
+
+struct rw_semaphore bonding_rwsem;
+
+
+
+
+/*------------------------------ Functions --------------------------------*/
+
+/*
+ * "show" function for the bond_masters attribute.
+ * The class parameter is ignored.
+ */
+static ssize_t bonding_show_bonds(struct class *cls, char *buffer)
+{
+ int res = 0;
+ struct bonding *bond;
+
+ down_read(&(bonding_rwsem));
+
+ list_for_each_entry(bond, &bond_dev_list, bond_list) {
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ /* not enough space for another interface name */
+ if ((PAGE_SIZE - res) > 10)
+ res = PAGE_SIZE - 10;
+ res += sprintf(buffer + res, "++more++");
+ break;
+ }
+ res += sprintf(buffer + res, "%s ",
+ bond->dev->name);
+ }
+ res += sprintf(buffer + res, "\n");
+ res++;
+ up_read(&(bonding_rwsem));
+ return res;
+}
+
+/*
+ * "store" function for the bond_masters attribute. This is what
+ * creates and deletes entire bonds.
+ *
+ * The class parameter is ignored.
+ *
+ */
+
+static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t count)
+{
+ char command[IFNAMSIZ + 1] = {0, };
+ char *ifname;
+ int res = count;
+ struct bonding *bond;
+ struct bonding *nxt;
+
+ down_write(&(bonding_rwsem));
+ sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
+ ifname = command + 1;
+ if ((strlen(command) <= 1) ||
+ !dev_valid_name(ifname))
+ goto err_no_cmd;
+
+ if (command[0] == '+') {
+
+ /* Check to see if the bond already exists. */
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+ if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+ printk(KERN_ERR DRV_NAME
+ ": cannot add bond %s; it already exists\n",
+ ifname);
+ res = -EPERM;
+ goto out;
+ }
+
+ printk(KERN_INFO DRV_NAME
+ ": %s is being created...\n", ifname);
+ if (bond_create(ifname, &bonding_defaults, &bond)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s interface already exists. Bond creation failed.\n",
+ ifname);
+ res = -EPERM;
+ }
+ goto out;
+ }
+
+ if (command[0] == '-') {
+ list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+ if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) {
+ rtnl_lock();
+ /* check the ref count on the bond's kobject.
+ * If it's > expected, then there's a file open,
+ * and we have to fail.
+ */
+ if (atomic_read(&bond->dev->class_dev.kobj.kref.refcount)
+ > expected_refcount){
+ rtnl_unlock();
+ printk(KERN_INFO DRV_NAME
+ ": Unable remove bond %s due to open references.\n",
+ ifname);
+ res = -EPERM;
+ goto out;
+ }
+ printk(KERN_INFO DRV_NAME
+ ": %s is being deleted...\n",
+ bond->dev->name);
+ unregister_netdevice(bond->dev);
+ bond_deinit(bond->dev);
+ bond_destroy_sysfs_entry(bond);
+ rtnl_unlock();
+ goto out;
+ }
+
+ printk(KERN_ERR DRV_NAME
+ ": unable to delete non-existent bond %s\n", ifname);
+ res = -ENODEV;
+ goto out;
+ }
+
+err_no_cmd:
+ printk(KERN_ERR DRV_NAME
+ ": no command found in bonding_masters. Use +ifname or -ifname.\n");
+ res = -EPERM;
+
+ /* Always return either count or an error. If you return 0, you'll
+ * get called forever, which is bad.
+ */
+out:
+ up_write(&(bonding_rwsem));
+ return res;
+}
+/* class attribute for bond_masters file. This ends up in /sys/class/net */
+static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
+ bonding_show_bonds, bonding_store_bonds);
+
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+ int ret = 0;
+
+ /* first, create a link from the slave back to the master */
+ ret = sysfs_create_link(&(slave->class_dev.kobj), &(master->class_dev.kobj),
+ "master");
+ if (ret)
+ return ret;
+ /* next, create a link from the master to the slave */
+ sprintf(linkname,"slave_%s",slave->name);
+ ret = sysfs_create_link(&(master->class_dev.kobj), &(slave->class_dev.kobj),
+ linkname);
+ return ret;
+
+}
+
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave)
+{
+ char linkname[IFNAMSIZ+7];
+
+ sysfs_remove_link(&(slave->class_dev.kobj), "master");
+ sprintf(linkname,"slave_%s",slave->name);
+ sysfs_remove_link(&(master->class_dev.kobj), linkname);
+}
+
+
+/*
+ * Show the slaves in the current bond.
+ */
+static ssize_t bonding_show_slaves(struct class_device *cd, char *buf)
+{
+ struct slave *slave;
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, i) {
+ if (res > (PAGE_SIZE - IFNAMSIZ)) {
+ /* not enough space for another interface name */
+ if ((PAGE_SIZE - res) > 10)
+ res = PAGE_SIZE - 10;
+ res += sprintf(buf + res, "++more++");
+ break;
+ }
+ res += sprintf(buf + res, "%s ", slave->dev->name);
+ }
+ read_unlock_bh(&bond->lock);
+ res += sprintf(buf + res, "\n");
+ res++;
+ return res;
+}
+
+/*
+ * Set the slaves in the current bond. The bond interface must be
+ * up for this to succeed.
+ * This function is largely the same flow as bonding_update_bonds().
+ */
+static ssize_t bonding_store_slaves(struct class_device *cd, const char *buffer, size_t count)
+{
+ char command[IFNAMSIZ + 1] = { 0, };
+ char *ifname;
+ int i, res, found, ret = count;
+ struct slave *slave;
+ struct net_device *dev = 0;
+ struct bonding *bond = to_bond(cd);
+
+ /* Quick sanity check -- is the bond interface up? */
+ if (!(bond->dev->flags & IFF_UP)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update slaves because interface is down.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /* Note: We can't hold bond->lock here, as bond_create grabs it. */
+
+ sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
+ ifname = command + 1;
+ if ((strlen(command) <= 1) ||
+ !dev_valid_name(ifname))
+ goto err_no_cmd;
+
+ if (command[0] == '+') {
+
+ /* Got a slave name in ifname. Is it already in the list? */
+ found = 0;
+ read_lock_bh(&bond->lock);
+ bond_for_each_slave(bond, slave, i)
+ if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Interface %s is already enslaved!\n",
+ bond->dev->name, ifname);
+ ret = -EPERM;
+ read_unlock_bh(&bond->lock);
+ goto out;
+ }
+
+ read_unlock_bh(&bond->lock);
+ printk(KERN_INFO DRV_NAME ": %s: Adding slave %s.\n",
+ bond->dev->name, ifname);
+ dev = dev_get_by_name(ifname);
+ if (!dev) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Interface %s does not exist!\n",
+ bond->dev->name, ifname);
+ ret = -EPERM;
+ goto out;
+ }
+ else
+ dev_put(dev);
+
+ if (dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Error: Unable to enslave %s "
+ "because it is already up.\n",
+ bond->dev->name, dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+ /* If this is the first slave, then we need to set
+ the master's hardware address to be the same as the
+ slave's. */
+ if (!(*((u32 *) & (bond->dev->dev_addr[0])))) {
+ memcpy(bond->dev->dev_addr, dev->dev_addr,
+ dev->addr_len);
+ }
+
+ /* Set the slave's MTU to match the bond */
+ if (dev->mtu != bond->dev->mtu) {
+ if (dev->change_mtu) {
+ res = dev->change_mtu(dev,
+ bond->dev->mtu);
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ } else {
+ dev->mtu = bond->dev->mtu;
+ }
+ }
+ rtnl_lock();
+ res = bond_enslave(bond->dev, dev);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ }
+ goto out;
+ }
+
+ if (command[0] == '-') {
+ dev = NULL;
+ bond_for_each_slave(bond, slave, i)
+ if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
+ dev = slave->dev;
+ break;
+ }
+ if (dev) {
+ printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n",
+ bond->dev->name, dev->name);
+ rtnl_lock();
+ res = bond_release(bond->dev, dev);
+ rtnl_unlock();
+ if (res) {
+ ret = res;
+ goto out;
+ }
+ /* set the slave MTU to the default */
+ if (dev->change_mtu) {
+ dev->change_mtu(dev, 1500);
+ } else {
+ dev->mtu = 1500;
+ }
+ }
+ else {
+ printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n",
+ ifname, bond->dev->name);
+ ret = -ENODEV;
+ }
+ goto out;
+ }
+
+err_no_cmd:
+ printk(KERN_ERR DRV_NAME ": no command found in slaves file for bond %s. Use +ifname or -ifname.\n", bond->dev->name);
+ ret = -EPERM;
+
+out:
+ return ret;
+}
+
+static CLASS_DEVICE_ATTR(slaves, S_IRUGO | S_IWUSR, bonding_show_slaves, bonding_store_slaves);
+
+/*
+ * Show and set the bonding mode. The bond interface must be down to
+ * change the mode.
+ */
+static ssize_t bonding_show_mode(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%s %d\n",
+ bond_mode_tbl[bond->params.mode].modename,
+ bond->params.mode) + 1;
+}
+
+static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": unable to update mode of %s because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_mode_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid mode value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.mode = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n",
+ bond->dev->name, bond_mode_tbl[new_value].modename, new_value);
+ }
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, bonding_show_mode, bonding_store_mode);
+
+/*
+ * Show and set the bonding transmit hash method. The bond interface must be down to
+ * change the xmit hash policy.
+ */
+static ssize_t bonding_show_xmit_hash(struct class_device *cd, char *buf)
+{
+ int count;
+ struct bonding *bond = to_bond(cd);
+
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ // Not Applicable
+ count = sprintf(buf, "NA\n") + 1;
+ } else {
+ count = sprintf(buf, "%s %d\n",
+ xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+ bond->params.xmit_policy) + 1;
+ }
+
+ return count;
+}
+
+static ssize_t bonding_store_xmit_hash(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Interface is up. Unable to update xmit policy.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if ((bond->params.mode != BOND_MODE_XOR) &&
+ (bond->params.mode != BOND_MODE_8023AD)) {
+ printk(KERN_ERR DRV_NAME
+ "%s: Transmit hash policy is irrelevant in this mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, xmit_hashtype_tbl);
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid xmit hash policy value %.*s.\n",
+ bond->dev->name,
+ (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.xmit_policy = new_value;
+ bond_set_mode_ops(bond, bond->params.mode);
+ printk(KERN_INFO DRV_NAME ": %s: setting xmit hash policy to %s (%d).\n",
+ bond->dev->name, xmit_hashtype_tbl[new_value].modename, new_value);
+ }
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
+
+/*
+ * Show and set the arp timer interval. There are two tricky bits
+ * here. First, if ARP monitoring is activated, then we must disable
+ * MII monitoring. Second, if the ARP timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_arp_interval(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%d\n", bond->params.arp_interval) + 1;
+}
+
+static ssize_t bonding_store_arp_interval(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no arp_interval value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+ bond->dev->name, new_value, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting ARP monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.arp_interval = new_value;
+ if (bond->params.miimon) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring cannot be used with MII monitoring. "
+ "%s Disabling MII monitoring.\n",
+ bond->dev->name, bond->dev->name);
+ bond->params.miimon = 0;
+ /* Kill MII timer, else it brings bond's link down */
+ if (bond->arp_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill MII timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->mii_timer);
+ }
+ }
+ if (!bond->params.arp_targets[0]) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: ARP monitoring has been set up, "
+ "but no ARP targets have been specified.\n",
+ bond->dev->name);
+ }
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the ARP timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->arp_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->arp_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->arp_timer);
+ bond->arp_timer.expires = jiffies + 1;
+ bond->arp_timer.data =
+ (unsigned long) bond->dev;
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+ bond->arp_timer.function =
+ (void *)
+ &bond_activebackup_arp_mon;
+ } else {
+ bond->arp_timer.function =
+ (void *)
+ &bond_loadbalance_arp_mon;
+ }
+ add_timer(&bond->arp_timer);
+ }
+ }
+
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR , bonding_show_arp_interval, bonding_store_arp_interval);
+
+/*
+ * Show and set the arp targets.
+ */
+static ssize_t bonding_show_arp_targets(struct class_device *cd, char *buf)
+{
+ int i, res = 0;
+ struct bonding *bond = to_bond(cd);
+
+ for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
+ if (bond->params.arp_targets[i])
+ res += sprintf(buf + res, "%u.%u.%u.%u ",
+ NIPQUAD(bond->params.arp_targets[i]));
+ }
+ if (res)
+ res--; /* eat the leftover space */
+ res += sprintf(buf + res, "\n");
+ res++;
+ return res;
+}
+
+static ssize_t bonding_store_arp_targets(struct class_device *cd, const char *buf, size_t count)
+{
+ u32 newtarget;
+ int i = 0, done = 0, ret = count;
+ struct bonding *bond = to_bond(cd);
+ u32 *targets;
+
+ targets = bond->params.arp_targets;
+ newtarget = in_aton(buf + 1);
+ /* look for adds */
+ if (buf[0] == '+') {
+ if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ ret = -EINVAL;
+ goto out;
+ }
+ /* look for an empty slot to put the target in, and check for dupes */
+ for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+ if (targets[i] == newtarget) { /* duplicate */
+ printk(KERN_ERR DRV_NAME
+ ": %s: ARP target %u.%u.%u.%u is already present\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ if (done)
+ targets[i] = 0;
+ ret = -EINVAL;
+ goto out;
+ }
+ if (targets[i] == 0 && !done) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: adding ARP target %d.%d.%d.%d.\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ done = 1;
+ targets[i] = newtarget;
+ }
+ }
+ if (!done) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: ARP target table is full!\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ }
+ else if (buf[0] == '-') {
+ if ((newtarget == 0) || (newtarget == INADDR_BROADCAST)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+ if (targets[i] == newtarget) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: removing ARP target %d.%d.%d.%d.\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ targets[i] = 0;
+ done = 1;
+ }
+ }
+ if (!done) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n",
+ bond->dev->name, NIPQUAD(newtarget));
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+ else {
+ printk(KERN_ERR DRV_NAME ": no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
+
+/*
+ * Show and set the up and down delays. These must be multiples of the
+ * MII monitoring value, and are stored internally as the multiplier.
+ * Thus, we must translate to MS for the real world.
+ */
+static ssize_t bonding_show_downdelay(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%d\n", bond->params.downdelay * bond->params.miimon) + 1;
+}
+
+static ssize_t bonding_store_downdelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set down delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no down delay value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: down delay (%d) is not a multiple "
+ "of miimon (%d), delay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.downdelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting down delay to %d.\n",
+ bond->dev->name, bond->params.downdelay * bond->params.miimon);
+
+ }
+
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR , bonding_show_downdelay, bonding_store_downdelay);
+
+static ssize_t bonding_show_updelay(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%d\n", bond->params.updelay * bond->params.miimon) + 1;
+
+}
+
+static ssize_t bonding_store_updelay(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (!(bond->params.miimon)) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to set up delay as MII monitoring is disabled\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no up delay value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid down delay value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ if ((new_value % bond->params.miimon) != 0) {
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Warning: up delay (%d) is not a multiple "
+ "of miimon (%d), updelay rounded to %d ms\n",
+ bond->dev->name, new_value, bond->params.miimon,
+ (new_value / bond->params.miimon) *
+ bond->params.miimon);
+ }
+ bond->params.updelay = new_value / bond->params.miimon;
+ printk(KERN_INFO DRV_NAME ": %s: Setting up delay to %d.\n",
+ bond->dev->name, bond->params.updelay * bond->params.miimon);
+
+ }
+
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR , bonding_show_updelay, bonding_store_updelay);
+
+/*
+ * Show and set the LACP interval. Interface must be down, and the mode
+ * must be set to 802.3ad mode.
+ */
+static ssize_t bonding_show_lacp(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%s %d\n",
+ bond_lacp_tbl[bond->params.lacp_fast].modename,
+ bond->params.lacp_fast) + 1;
+}
+
+static ssize_t bonding_store_lacp(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because interface is up.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (bond->params.mode != BOND_MODE_8023AD) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update LACP rate because bond is not in 802.3ad mode.\n",
+ bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm((char *)buf, bond_lacp_tbl);
+
+ if ((new_value == 1) || (new_value == 0)) {
+ bond->params.lacp_fast = new_value;
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting LACP rate to %s (%d).\n",
+ bond->dev->name, bond_lacp_tbl[new_value].modename, new_value);
+ } else {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid LACP rate value %.*s.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ }
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+
+/*
+ * Show and set the MII monitor interval. There are two tricky bits
+ * here. First, if MII monitoring is activated, then we must disable
+ * ARP monitoring. Second, if the timer isn't running, we must
+ * start it.
+ */
+static ssize_t bonding_show_miimon(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%d\n", bond->params.miimon) + 1;
+}
+
+static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no miimon value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (new_value < 0) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid miimon value %d not in range %d-%d; rejected.\n",
+ bond->dev->name, new_value, 1, INT_MAX);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting MII monitoring interval to %d.\n",
+ bond->dev->name, new_value);
+ bond->params.miimon = new_value;
+ if(bond->params.updelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating updelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.updelay * bond->params.miimon);
+ if(bond->params.downdelay)
+ printk(KERN_INFO DRV_NAME
+ ": %s: Note: Updating downdelay (to %d) "
+ "since it is a multiple of the miimon value.\n",
+ bond->dev->name,
+ bond->params.downdelay * bond->params.miimon);
+ if (bond->params.arp_interval) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: MII monitoring cannot be used with "
+ "ARP monitoring. Disabling ARP monitoring...\n",
+ bond->dev->name);
+ bond->params.arp_interval = 0;
+ /* Kill ARP timer, else it brings bond's link down */
+ if (bond->mii_timer.function) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Kill ARP timer, else it brings bond's link down...\n",
+ bond->dev->name);
+ del_timer_sync(&bond->arp_timer);
+ }
+ }
+
+ if (bond->dev->flags & IFF_UP) {
+ /* If the interface is up, we may need to fire off
+ * the MII timer. If the interface is down, the
+ * timer will get fired off when the open function
+ * is called.
+ */
+ if (bond->mii_timer.function) {
+ /* The timer's already set up, so fire it off */
+ mod_timer(&bond->mii_timer, jiffies + 1);
+ } else {
+ /* Set up the timer. */
+ init_timer(&bond->mii_timer);
+ bond->mii_timer.expires = jiffies + 1;
+ bond->mii_timer.data =
+ (unsigned long) bond->dev;
+ bond->mii_timer.function =
+ (void *) &bond_mii_monitor;
+ add_timer(&bond->mii_timer);
+ }
+ }
+ }
+out:
+ return ret;
+}
+static CLASS_DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, bonding_show_miimon, bonding_store_miimon);
+
+/*
+ * Show and set the primary slave. The store function is much
+ * simpler than bonding_store_slaves function because it only needs to
+ * handle one interface name.
+ * The bond must be a mode that supports a primary for this be
+ * set.
+ */
+static ssize_t bonding_show_primary(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->primary_slave)
+ count = sprintf(buf, "%s\n", bond->primary_slave->dev->name) + 1;
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+
+static ssize_t bonding_store_primary(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct bonding *bond = to_bond(cd);
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set primary slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as primary slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond->primary_slave = slave;
+ bond_select_active_slave(bond);
+ goto out;
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting primary slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as primary slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ return count;
+}
+static CLASS_DEVICE_ATTR(primary, S_IRUGO | S_IWUSR, bonding_show_primary, bonding_store_primary);
+
+/*
+ * Show and set the use_carrier flag.
+ */
+static ssize_t bonding_show_carrier(struct class_device *cd, char *buf)
+{
+ struct bonding *bond = to_bond(cd);
+
+ return sprintf(buf, "%d\n", bond->params.use_carrier) + 1;
+}
+
+static ssize_t bonding_store_carrier(struct class_device *cd, const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(cd);
+
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no use_carrier value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if ((new_value == 0) || (new_value == 1)) {
+ bond->params.use_carrier = new_value;
+ printk(KERN_INFO DRV_NAME ": %s: Setting use_carrier to %d.\n",
+ bond->dev->name, new_value);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Ignoring invalid use_carrier value %d.\n",
+ bond->dev->name, new_value);
+ }
+out:
+ return count;
+}
+static CLASS_DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR, bonding_show_carrier, bonding_store_carrier);
+
+
+/*
+ * Show and set currently active_slave.
+ */
+static ssize_t bonding_show_active_slave(struct class_device *cd, char *buf)
+{
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+ int count;
+
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ if (USES_PRIMARY(bond->params.mode) && curr)
+ count = sprintf(buf, "%s\n", curr->dev->name) + 1;
+ else
+ count = sprintf(buf, "\n") + 1;
+ return count;
+}
+
+static ssize_t bonding_store_active_slave(struct class_device *cd, const char *buf, size_t count)
+{
+ int i;
+ struct slave *slave;
+ struct slave *old_active = NULL;
+ struct slave *new_active = NULL;
+ struct bonding *bond = to_bond(cd);
+
+ write_lock_bh(&bond->lock);
+ if (!USES_PRIMARY(bond->params.mode)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to change active slave; %s is in mode %d\n",
+ bond->dev->name, bond->dev->name, bond->params.mode);
+ } else {
+ bond_for_each_slave(bond, slave, i) {
+ if (strnicmp
+ (slave->dev->name, buf,
+ strlen(slave->dev->name)) == 0) {
+ old_active = bond->curr_active_slave;
+ new_active = slave;
+ if (new_active && (new_active == old_active)) {
+ /* do nothing */
+ printk(KERN_INFO DRV_NAME
+ ": %s: %s is already the current active slave.\n",
+ bond->dev->name, slave->dev->name);
+ goto out;
+ }
+ else {
+ if ((new_active) &&
+ (old_active) &&
+ (new_active->link == BOND_LINK_UP) &&
+ IS_UP(new_active->dev)) {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting %s as active slave.\n",
+ bond->dev->name, slave->dev->name);
+ bond_change_active_slave(bond, new_active);
+ }
+ else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Could not set %s as active slave; "
+ "either %s is down or the link is down.\n",
+ bond->dev->name, slave->dev->name,
+ slave->dev->name);
+ }
+ goto out;
+ }
+ }
+ }
+
+ /* if we got here, then we didn't match the name of any slave */
+
+ if (strlen(buf) == 0 || buf[0] == '\n') {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting active slave to None.\n",
+ bond->dev->name);
+ bond->primary_slave = 0;
+ bond_select_active_slave(bond);
+ } else {
+ printk(KERN_INFO DRV_NAME
+ ": %s: Unable to set %.*s as active slave as it is not a slave.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ }
+ }
+out:
+ write_unlock_bh(&bond->lock);
+ return count;
+
+}
+static CLASS_DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, bonding_show_active_slave, bonding_store_active_slave);
+
+
+/*
+ * Show link status of the bond interface.
+ */
+static ssize_t bonding_show_mii_status(struct class_device *cd, char *buf)
+{
+ struct slave *curr;
+ struct bonding *bond = to_bond(cd);
+
+ read_lock(&bond->curr_slave_lock);
+ curr = bond->curr_active_slave;
+ read_unlock(&bond->curr_slave_lock);
+
+ return sprintf(buf, "%s\n", (curr) ? "up" : "down") + 1;
+}
+static CLASS_DEVICE_ATTR(mii_status, S_IRUGO, bonding_show_mii_status, NULL);
+
+
+/*
+ * Show current 802.3ad aggregator ID.
+ */
+static ssize_t bonding_show_ad_aggregator(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.aggregator_id) + 1;
+ }
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_aggregator, S_IRUGO, bonding_show_ad_aggregator, NULL);
+
+
+/*
+ * Show number of active 802.3ad ports.
+ */
+static ssize_t bonding_show_ad_num_ports(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0: ad_info.ports) + 1;
+ }
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_num_ports, S_IRUGO, bonding_show_ad_num_ports, NULL);
+
+
+/*
+ * Show current 802.3ad actor key.
+ */
+static ssize_t bonding_show_ad_actor_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.actor_key) + 1;
+ }
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_actor_key, S_IRUGO, bonding_show_ad_actor_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner key.
+ */
+static ssize_t bonding_show_ad_partner_key(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ count = sprintf(buf, "%d\n", (bond_3ad_get_active_agg_info(bond, &ad_info)) ? 0 : ad_info.partner_key) + 1;
+ }
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_key, S_IRUGO, bonding_show_ad_partner_key, NULL);
+
+
+/*
+ * Show current 802.3ad partner mac.
+ */
+static ssize_t bonding_show_ad_partner_mac(struct class_device *cd, char *buf)
+{
+ int count = 0;
+ struct bonding *bond = to_bond(cd);
+
+ if (bond->params.mode == BOND_MODE_8023AD) {
+ struct ad_info ad_info;
+ if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
+ count = sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ad_info.partner_system[0],
+ ad_info.partner_system[1],
+ ad_info.partner_system[2],
+ ad_info.partner_system[3],
+ ad_info.partner_system[4],
+ ad_info.partner_system[5]) + 1;
+ }
+ }
+ else
+ count = sprintf(buf, "\n") + 1;
+
+ return count;
+}
+static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
+
+
+
+static struct attribute *per_bond_attrs[] = {
+ &class_device_attr_slaves.attr,
+ &class_device_attr_mode.attr,
+ &class_device_attr_arp_interval.attr,
+ &class_device_attr_arp_ip_target.attr,
+ &class_device_attr_downdelay.attr,
+ &class_device_attr_updelay.attr,
+ &class_device_attr_lacp_rate.attr,
+ &class_device_attr_xmit_hash_policy.attr,
+ &class_device_attr_miimon.attr,
+ &class_device_attr_primary.attr,
+ &class_device_attr_use_carrier.attr,
+ &class_device_attr_active_slave.attr,
+ &class_device_attr_mii_status.attr,
+ &class_device_attr_ad_aggregator.attr,
+ &class_device_attr_ad_num_ports.attr,
+ &class_device_attr_ad_actor_key.attr,
+ &class_device_attr_ad_partner_key.attr,
+ &class_device_attr_ad_partner_mac.attr,
+ NULL,
+};
+
+static struct attribute_group bonding_group = {
+ .name = "bonding",
+ .attrs = per_bond_attrs,
+};
+
+/*
+ * Initialize sysfs. This sets up the bonding_masters file in
+ * /sys/class/net.
+ */
+int bond_create_sysfs(void)
+{
+ int ret = 0;
+ struct bonding *firstbond;
+
+ init_rwsem(&bonding_rwsem);
+
+ /* get the netdev class pointer */
+ firstbond = container_of(bond_dev_list.next, struct bonding, bond_list);
+ if (!firstbond)
+ return -ENODEV;
+
+ netdev_class = firstbond->dev->class_dev.class;
+ if (!netdev_class)
+ return -ENODEV;
+
+ ret = class_create_file(netdev_class, &class_attr_bonding_masters);
+
+ return ret;
+
+}
+
+/*
+ * Remove /sys/class/net/bonding_masters.
+ */
+void bond_destroy_sysfs(void)
+{
+ if (netdev_class)
+ class_remove_file(netdev_class, &class_attr_bonding_masters);
+}
+
+/*
+ * Initialize sysfs for each bond. This sets up and registers
+ * the 'bondctl' directory for each individual bond under /sys/class/net.
+ */
+int bond_create_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+ int err;
+
+ err = sysfs_create_group(&(dev->class_dev.kobj), &bonding_group);
+ if (err) {
+ printk(KERN_EMERG "eek! didn't create group!\n");
+ }
+
+ if (expected_refcount < 1)
+ expected_refcount = atomic_read(&bond->dev->class_dev.kobj.kref.refcount);
+
+ return err;
+}
+/*
+ * Remove sysfs entries for each bond.
+ */
+void bond_destroy_sysfs_entry(struct bonding *bond)
+{
+ struct net_device *dev = bond->dev;
+
+ sysfs_remove_group(&(dev->class_dev.kobj), &bonding_group);
+}
+
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 1433e91db0f7..3dd78d048c3e 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -10,25 +10,6 @@
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
- *
- * 2003/03/18 - Amir Noam <amir.noam at intel dot com>,
- * Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Shmulik Hen <shmulik.hen at intel dot com>
- * - Added support for IEEE 802.3ad Dynamic link aggregation mode.
- *
- * 2003/05/01 - Tsippy Mendelson <tsippy.mendelson at intel dot com> and
- * Amir Noam <amir.noam at intel dot com>
- * - Code beautification and style changes (mainly in comments).
- *
- * 2003/05/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Added support for Transmit load balancing mode.
- *
- * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
- * - Code cleanup and style changes
- *
- * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov>
- * - added "xmit_policy" kernel parameter for alternate hashing policy
- * support for mode 2
*/
#ifndef _LINUX_BONDING_H
@@ -37,11 +18,12 @@
#include <linux/timer.h>
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
+#include <linux/kobject.h>
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "2.6.5"
-#define DRV_RELDATE "November 4, 2005"
+#define DRV_VERSION "3.0.1"
+#define DRV_RELDATE "January 9, 2006"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -152,6 +134,11 @@ struct bond_params {
u32 arp_targets[BOND_MAX_ARP_TARGETS];
};
+struct bond_parm_tbl {
+ char *modename;
+ int mode;
+};
+
struct vlan_entry {
struct list_head vlan_list;
u32 vlan_ip;
@@ -159,7 +146,7 @@ struct vlan_entry {
};
struct slave {
- struct net_device *dev; /* first - usefull for panic debug */
+ struct net_device *dev; /* first - useful for panic debug */
struct slave *next;
struct slave *prev;
s16 delay;
@@ -185,7 +172,7 @@ struct slave {
* beforehand.
*/
struct bonding {
- struct net_device *dev; /* first - usefull for panic debug */
+ struct net_device *dev; /* first - useful for panic debug */
struct slave *first_slave;
struct slave *curr_active_slave;
struct slave *current_arp_slave;
@@ -218,7 +205,7 @@ struct bonding {
*
* Caller must hold bond lock for read
*/
-extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
{
struct slave *slave = NULL;
int i;
@@ -232,7 +219,7 @@ extern inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n
return slave;
}
-extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
+static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
{
if (!slave || !slave->dev->master) {
return NULL;
@@ -241,13 +228,13 @@ extern inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
return (struct bonding *)slave->dev->master->priv;
}
-extern inline void bond_set_slave_inactive_flags(struct slave *slave)
+static inline void bond_set_slave_inactive_flags(struct slave *slave)
{
slave->state = BOND_STATE_BACKUP;
slave->dev->flags |= IFF_NOARP;
}
-extern inline void bond_set_slave_active_flags(struct slave *slave)
+static inline void bond_set_slave_active_flags(struct slave *slave)
{
slave->state = BOND_STATE_ACTIVE;
slave->dev->flags &= ~IFF_NOARP;
@@ -255,6 +242,25 @@ extern inline void bond_set_slave_active_flags(struct slave *slave)
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
+void bond_deinit(struct net_device *bond_dev);
+int bond_create_sysfs(void);
+void bond_destroy_sysfs(void);
+void bond_destroy_sysfs_entry(struct bonding *bond);
+int bond_create_sysfs_entry(struct bonding *bond);
+int bond_create_slave_symlinks(struct net_device *master, struct net_device *slave);
+void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
+void bond_mii_monitor(struct net_device *bond_dev);
+void bond_loadbalance_arp_mon(struct net_device *bond_dev);
+void bond_activebackup_arp_mon(struct net_device *bond_dev);
+void bond_set_mode_ops(struct bonding *bond, int mode);
+int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
+const char *bond_mode_name(int mode);
+void bond_select_active_slave(struct bonding *bond);
+void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
#endif /* _LINUX_BONDING_H */
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 1f7ca453bb4a..6e295fce5c6f 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -335,6 +335,30 @@ static inline void cas_mask_intr(struct cas *cp)
cas_disable_irq(cp, i);
}
+static inline void cas_buffer_init(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_set((atomic_t *)&page->lru.next, 1);
+}
+
+static inline int cas_buffer_count(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ return atomic_read((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_inc(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_inc((atomic_t *)&page->lru.next);
+}
+
+static inline void cas_buffer_dec(cas_page_t *cp)
+{
+ struct page *page = cp->buffer;
+ atomic_dec((atomic_t *)&page->lru.next);
+}
+
static void cas_enable_irq(struct cas *cp, const int ring)
{
if (ring == 0) { /* all but TX_DONE */
@@ -472,6 +496,7 @@ static int cas_page_free(struct cas *cp, cas_page_t *page)
{
pci_unmap_page(cp->pdev, page->dma_addr, cp->page_size,
PCI_DMA_FROMDEVICE);
+ cas_buffer_dec(page);
__free_pages(page->buffer, cp->page_order);
kfree(page);
return 0;
@@ -501,6 +526,7 @@ static cas_page_t *cas_page_alloc(struct cas *cp, const gfp_t flags)
page->buffer = alloc_pages(flags, cp->page_order);
if (!page->buffer)
goto page_err;
+ cas_buffer_init(page);
page->dma_addr = pci_map_page(cp->pdev, page->buffer, 0,
cp->page_size, PCI_DMA_FROMDEVICE);
return page;
@@ -579,7 +605,7 @@ static void cas_spare_recover(struct cas *cp, const gfp_t flags)
list_for_each_safe(elem, tmp, &list) {
cas_page_t *page = list_entry(elem, cas_page_t, list);
- if (page_count(page->buffer) > 1)
+ if (cas_buffer_count(page) > 1)
continue;
list_del(elem);
@@ -1347,7 +1373,7 @@ static inline cas_page_t *cas_page_spare(struct cas *cp, const int index)
cas_page_t *page = cp->rx_pages[1][index];
cas_page_t *new;
- if (page_count(page->buffer) == 1)
+ if (cas_buffer_count(page) == 1)
return page;
new = cas_page_dequeue(cp);
@@ -1367,7 +1393,7 @@ static cas_page_t *cas_page_swap(struct cas *cp, const int ring,
cas_page_t **page1 = cp->rx_pages[1];
/* swap if buffer is in use */
- if (page_count(page0[index]->buffer) > 1) {
+ if (cas_buffer_count(page0[index]) > 1) {
cas_page_t *new = cas_page_spare(cp, index);
if (new) {
page1[index] = page0[index];
@@ -1925,8 +1951,8 @@ static void cas_tx(struct net_device *dev, struct cas *cp,
u64 compwb = le64_to_cpu(cp->init_block->tx_compwb);
#endif
if (netif_msg_intr(cp))
- printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %lx\n",
- cp->dev->name, status, compwb);
+ printk(KERN_DEBUG "%s: tx interrupt, status: 0x%x, %llx\n",
+ cp->dev->name, status, (unsigned long long)compwb);
/* process all the rings */
for (ring = 0; ring < N_TX_RINGS; ring++) {
#ifdef USE_TX_COMPWB
@@ -2039,6 +2065,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
skb->len += hlen - swivel;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = off;
frag->size = hlen - swivel;
@@ -2063,6 +2090,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc,
frag++;
get_page(page->buffer);
+ cas_buffer_inc(page);
frag->page = page->buffer;
frag->page_offset = 0;
frag->size = hlen;
@@ -2225,7 +2253,7 @@ static int cas_post_rxds_ringN(struct cas *cp, int ring, int num)
released = 0;
while (entry != last) {
/* make a new buffer if it's still in use */
- if (page_count(page[entry]->buffer) > 1) {
+ if (cas_buffer_count(page[entry]) > 1) {
cas_page_t *new = cas_page_dequeue(cp);
if (!new) {
/* let the timer know that we need to
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 53b41d99b00b..2c5b849b7ba4 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1332,8 +1332,8 @@ intr_handler_t t1_select_intr_handler(adapter_t *adapter)
*
* This runs with softirqs disabled.
*/
-unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
- unsigned int qid, struct net_device *dev)
+static 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];
@@ -1352,9 +1352,10 @@ unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
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 (!netif_queue_stopped(dev))
+ CH_ERR("%s: Tx ring full while queue awake!\n",
+ adapter->name);
+ return NETDEV_TX_BUSY;
}
if (unlikely(credits - count < q->stop_thres)) {
sge->stats.cmdQ_full[3]++;
@@ -1389,7 +1390,7 @@ unsigned int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter,
writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL);
}
}
- return 0;
+ return NETDEV_TX_OK;
}
#define MK_ETH_TYPE_MSS(type, mss) (((mss) & 0x3FFF) | ((type) << 14))
@@ -1449,7 +1450,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb->len < ETH_HLEN ||
skb->len > dev->mtu + eth_hdr_len(skb->data))) {
dev_kfree_skb_any(skb);
- return NET_XMIT_SUCCESS;
+ return NETDEV_TX_OK;
}
/*
@@ -1467,7 +1468,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb = skb_realloc_headroom(skb, sizeof(*cpl));
dev_kfree_skb_any(orig_skb);
if (!skb)
- return -ENOMEM;
+ return NETDEV_TX_OK;
}
if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
@@ -1475,7 +1476,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->nh.iph->protocol == IPPROTO_UDP)
if (unlikely(skb_checksum_help(skb, 0))) {
dev_kfree_skb_any(skb);
- return -ENOMEM;
+ return NETDEV_TX_OK;
}
/* Hmmm, assuming to catch the gratious arp... and we'll use
diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h
index 434b25586851..6d0d24a6364f 100644
--- a/drivers/net/chelsio/sge.h
+++ b/drivers/net/chelsio/sge.h
@@ -89,8 +89,6 @@ 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 *);
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index a6078ad9b654..ef54ebeb29b8 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -87,6 +87,15 @@
Deepak Saxena : dsaxena@plexity.net
: Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
+ Dmitry Pervushin : dpervushin@ru.mvista.com
+ : PNX010X platform support
+
+ Deepak Saxena : dsaxena@plexity.net
+ : Intel IXDP2351 platform support
+
+ Dmitry Pervushin : dpervushin@ru.mvista.com
+ : PNX010X platform support
+
*/
/* Always include 'config.h' first in case the user wants to turn on
@@ -100,7 +109,7 @@
* Note that even if DMA is turned off we still support the 'dma' and 'use_dma'
* module options so we don't break any startup scripts.
*/
-#ifndef CONFIG_ARCH_IXDP2X01
+#ifndef CONFIG_ISA_DMA_API
#define ALLOW_DMA 0
#else
#define ALLOW_DMA 1
@@ -171,11 +180,15 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0};
static unsigned int netcard_portlist[] __initdata =
{ 0x0300, 0};
static unsigned int cs8900_irq_map[] = {1,0,0,0};
+#elif defined(CONFIG_MACH_IXDP2351)
+static unsigned int netcard_portlist[] __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
+#include <asm/irq.h>
#elif defined(CONFIG_ARCH_IXDP2X01)
#include <asm/irq.h>
static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
-#elif defined(CONFIG_ARCH_PNX0105)
+#elif defined(CONFIG_ARCH_PNX010X)
#include <asm/irq.h>
#include <asm/arch/gpio.h>
#define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */
@@ -338,30 +351,96 @@ out:
}
#endif
-static int
-readreg(struct net_device *dev, int portno)
+#if defined(CONFIG_MACH_IXDP2351)
+static u16
+readword(unsigned long base_addr, int portno)
{
- outw(portno, dev->base_addr + ADD_PORT);
- return inw(dev->base_addr + DATA_PORT);
+ return __raw_readw(base_addr + (portno << 1));
}
static void
-writereg(struct net_device *dev, int portno, int value)
+writeword(unsigned long base_addr, int portno, u16 value)
{
- outw(portno, dev->base_addr + ADD_PORT);
- outw(value, dev->base_addr + DATA_PORT);
+ __raw_writew(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_IXDP2X01)
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return __raw_readl(base_addr + (portno << 1));
}
-static int
-readword(struct net_device *dev, int portno)
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ __raw_writel(value, base_addr + (portno << 1));
+}
+#elif defined(CONFIG_ARCH_PNX010X)
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return inw(base_addr + (portno << 1));
+}
+
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ outw(value, base_addr + (portno << 1));
+}
+#else
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return inw(base_addr + portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno, u16 value)
+{
+ outw(value, base_addr + portno);
+}
+#endif
+
+static void
+readwords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u16 tmp16;
+
+ tmp16 = readword(base_addr, portno);
+ *buf8++ = (u8)tmp16;
+ *buf8++ = (u8)(tmp16 >> 8);
+ } while (--length);
+}
+
+static void
+writewords(unsigned long base_addr, int portno, void *buf, int length)
+{
+ u8 *buf8 = (u8 *)buf;
+
+ do {
+ u16 tmp16;
+
+ tmp16 = *buf8++;
+ tmp16 |= (*buf8++) << 8;
+ writeword(base_addr, portno, tmp16);
+ } while (--length);
+}
+
+static u16
+readreg(struct net_device *dev, u16 regno)
{
- return inw(dev->base_addr + portno);
+ writeword(dev->base_addr, ADD_PORT, regno);
+ return readword(dev->base_addr, DATA_PORT);
}
static void
-writeword(struct net_device *dev, int portno, int value)
+writereg(struct net_device *dev, u16 regno, u16 value)
{
- outw(value, dev->base_addr + portno);
+ writeword(dev->base_addr, ADD_PORT, regno);
+ writeword(dev->base_addr, DATA_PORT, value);
}
static int __init
@@ -456,7 +535,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
#endif
}
-#ifdef CONFIG_ARCH_PNX0105
+#ifdef CONFIG_ARCH_PNX010X
initialize_ebi();
/* Map GPIO registers for the pins connected to the CS8900a. */
@@ -491,8 +570,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
#ifdef CONFIG_SH_HICOSH4
/* truely reset the chip */
- outw(0x0114, ioaddr + ADD_PORT);
- outw(0x0040, ioaddr + DATA_PORT);
+ writeword(ioaddr, ADD_PORT, 0x0114);
+ writeword(ioaddr, DATA_PORT, 0x0040);
#endif
/* if they give us an odd I/O address, then do ONE write to
@@ -503,24 +582,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
if (net_debug > 1)
printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr);
if ((ioaddr & 2) != 2)
- if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) {
+ if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) {
printk(KERN_ERR "%s: bad signature 0x%x\n",
- dev->name, inw((ioaddr & ~3)+ ADD_PORT));
+ dev->name, readword(ioaddr & ~3, ADD_PORT));
retval = -ENODEV;
goto out2;
}
}
- printk(KERN_DEBUG "PP_addr at %x: 0x%x\n",
- ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT));
+ printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n",
+ ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT));
ioaddr &= ~3;
- outw(PP_ChipID, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_ChipID);
- tmp = inw(ioaddr + DATA_PORT);
+ tmp = readword(ioaddr, DATA_PORT);
if (tmp != CHIP_EISA_ID_SIG) {
- printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!="
+ printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!="
CHIP_EISA_ID_SIG_STR "\n",
- dev->name, ioaddr + DATA_PORT, tmp);
+ dev->name, ioaddr, DATA_PORT, tmp);
retval = -ENODEV;
goto out2;
}
@@ -724,7 +803,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
} else {
i = lp->isa_config & INT_NO_MASK;
if (lp->chip_type == CS8900) {
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
+#if defined(CONFIG_MACH_IXDP2351) || defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X)
i = cs8900_irq_map[0];
#else
/* Translate the IRQ using the IRQ mapping table. */
@@ -790,7 +869,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
goto out3;
return 0;
out3:
- outw(PP_ChipID, dev->base_addr + ADD_PORT);
+ writeword(dev->base_addr, ADD_PORT, PP_ChipID);
out2:
release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
out1:
@@ -956,7 +1035,7 @@ skip_this_frame:
void __init reset_chip(struct net_device *dev)
{
-#ifndef CONFIG_ARCH_IXDP2X01
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
struct net_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
#endif
@@ -967,14 +1046,14 @@ void __init reset_chip(struct net_device *dev)
/* wait 30 ms */
msleep(30);
-#ifndef CONFIG_ARCH_IXDP2X01
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
if (lp->chip_type != CS8900) {
/* Hardware problem requires PNP registers to be reconfigured after a reset */
- outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
outb(dev->irq, ioaddr + DATA_PORT);
outb(0, ioaddr + DATA_PORT + 1);
- outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT);
+ writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB);
outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1);
}
@@ -1104,8 +1183,8 @@ send_test_pkt(struct net_device *dev)
memcpy(test_packet, dev->dev_addr, ETH_ALEN);
memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
- writeword(dev, TX_CMD_PORT, TX_AFTER_ALL);
- writeword(dev, TX_LEN_PORT, ETH_ZLEN);
+ writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL);
+ writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN);
/* Test to see if the chip has allocated memory for the packet */
while (jiffies - timenow < 5)
@@ -1115,7 +1194,7 @@ send_test_pkt(struct net_device *dev)
return 0; /* this shouldn't happen */
/* Write the contents of the packet */
- outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
+ writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
if (net_debug > 1) printk("Sending test packet ");
/* wait a couple of jiffies for packet to be received */
@@ -1200,7 +1279,7 @@ net_open(struct net_device *dev)
int i;
int ret;
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
if (dev->irq < 2) {
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
@@ -1231,7 +1310,7 @@ net_open(struct net_device *dev)
else
#endif
{
-#if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105)
+#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X)
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
@@ -1316,7 +1395,7 @@ net_open(struct net_device *dev)
case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
}
-#ifdef CONFIG_ARCH_PNX0105
+#ifdef CONFIG_ARCH_PNX010X
result = A_CNF_10B_T;
#endif
if (!result) {
@@ -1457,8 +1536,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
/* initiate a transmit sequence */
- writeword(dev, TX_CMD_PORT, lp->send_cmd);
- writeword(dev, TX_LEN_PORT, skb->len);
+ writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd);
+ writeword(dev->base_addr, TX_LEN_PORT, skb->len);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
@@ -1472,7 +1551,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
return 1;
}
/* Write the contents of the packet */
- outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
+ writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
spin_unlock_irq(&lp->lock);
lp->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
@@ -1512,7 +1591,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
course, if you're on a slow machine, and packets are arriving
faster than you can read them off, you're screwed. Hasta la
vista, baby! */
- while ((status = readword(dev, ISQ_PORT))) {
+ while ((status = readword(dev->base_addr, ISQ_PORT))) {
if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
handled = 1;
switch(status & ISQ_EVENT_MASK) {
@@ -1606,8 +1685,8 @@ net_rx(struct net_device *dev)
int status, length;
int ioaddr = dev->base_addr;
- status = inw(ioaddr + RX_FRAME_PORT);
- length = inw(ioaddr + RX_FRAME_PORT);
+ status = readword(ioaddr, RX_FRAME_PORT);
+ length = readword(ioaddr, RX_FRAME_PORT);
if ((status & RX_OK) == 0) {
count_rx_errors(status, lp);
@@ -1626,9 +1705,9 @@ net_rx(struct net_device *dev)
skb_reserve(skb, 2); /* longword align L3 header */
skb->dev = dev;
- insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
+ readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1);
if (length & 1)
- skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
+ skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT);
if (net_debug > 3) {
printk( "%s: received %d byte packet of type %x\n",
@@ -1901,7 +1980,7 @@ void
cleanup_module(void)
{
unregister_netdev(dev_cs89x0);
- outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT);
+ writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
free_netdev(dev_cs89x0);
}
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index decea264f121..bd954aaa636f 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -16,13 +16,6 @@
#include <linux/config.h>
-#if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105)
-/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
-#define CS89x0_PORT(reg) ((reg) * 2)
-#else
-#define CS89x0_PORT(reg) (reg)
-#endif
-
#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
/* offset 2h -> Model/Product Number */
/* offset 3h -> Chip Revision Number */
@@ -332,16 +325,16 @@
#define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */
#define PKT_START PP_TxFrame /* Start of packet RAM */
-#define RX_FRAME_PORT CS89x0_PORT(0x0000)
+#define RX_FRAME_PORT 0x0000
#define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT CS89x0_PORT(0x0004)
+#define TX_CMD_PORT 0x0004
#define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */
#define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */
#define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */
-#define TX_LEN_PORT CS89x0_PORT(0x0006)
-#define ISQ_PORT CS89x0_PORT(0x0008)
-#define ADD_PORT CS89x0_PORT(0x000A)
-#define DATA_PORT CS89x0_PORT(0x000C)
+#define TX_LEN_PORT 0x0006
+#define ISQ_PORT 0x0008
+#define ADD_PORT 0x000A
+#define DATA_PORT 0x000C
#define EEPROM_WRITE_EN 0x00F0
#define EEPROM_WRITE_DIS 0x0000
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 22cd04556707..bf1fd2b98bf8 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,25 +1,25 @@
/*******************************************************************************
-
+
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
- Software Foundation; either version 2 of the License, or (at your option)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the 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
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 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
+ 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:
Linux NICS <linux.nics@intel.com>
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
@@ -132,6 +132,10 @@
* TODO:
* o several entry points race with dev->close
* o check for tx-no-resources/stop Q races with tx clean/wake Q
+ *
+ * FIXES:
+ * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com>
+ * - Stratus87247: protect MDI control register manipulations
*/
#include <linux/config.h>
@@ -156,7 +160,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.4.14-k4"DRV_EXT
+#define DRV_VERSION "3.5.10-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 ": "
@@ -316,7 +320,7 @@ enum cuc_dump {
cuc_dump_complete = 0x0000A005,
cuc_dump_reset_complete = 0x0000A007,
};
-
+
enum port {
software_reset = 0x0000,
selftest = 0x0001,
@@ -578,6 +582,7 @@ struct nic {
u16 leds;
u16 eeprom_wc;
u16 eeprom[256];
+ spinlock_t mdio_lock;
};
static inline void e100_write_flush(struct nic *nic)
@@ -587,7 +592,7 @@ static inline void e100_write_flush(struct nic *nic)
(void)readb(&nic->csr->scb.status);
}
-static inline void e100_enable_irq(struct nic *nic)
+static void e100_enable_irq(struct nic *nic)
{
unsigned long flags;
@@ -597,7 +602,7 @@ static inline void e100_enable_irq(struct nic *nic)
e100_write_flush(nic);
}
-static inline void e100_disable_irq(struct nic *nic)
+static void e100_disable_irq(struct nic *nic)
{
unsigned long flags;
@@ -710,10 +715,10 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
writeb(ctrl, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
-
+
/* Eeprom drives a dummy zero to EEDO after receiving
* complete address. Use this to adjust addr_len. */
ctrl = readb(&nic->csr->eeprom_ctrl_lo);
@@ -721,7 +726,7 @@ static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
*addr_len -= (i - 16);
i = 17;
}
-
+
data = (data << 1) | (ctrl & eedo ? 1 : 0);
}
@@ -786,7 +791,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)
+static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
unsigned int i;
@@ -817,7 +822,7 @@ err_unlock:
return err;
}
-static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
+static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
{
struct cb *cb;
@@ -876,15 +881,35 @@ static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
{
u32 data_out = 0;
unsigned int i;
+ unsigned long flags;
+
+ /*
+ * Stratus87247: we shouldn't be writing the MDI control
+ * register until the Ready bit shows True. Also, since
+ * manipulation of the MDI control registers is a multi-step
+ * procedure it should be done under lock.
+ */
+ spin_lock_irqsave(&nic->mdio_lock, flags);
+ for (i = 100; i; --i) {
+ if (readl(&nic->csr->mdi_ctrl) & mdi_ready)
+ break;
+ udelay(20);
+ }
+ if (unlikely(!i)) {
+ printk("e100.mdio_ctrl(%s) won't go Ready\n",
+ nic->netdev->name );
+ spin_unlock_irqrestore(&nic->mdio_lock, flags);
+ return 0; /* No way to indicate timeout error */
+ }
writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl);
- for(i = 0; i < 100; i++) {
+ for (i = 0; i < 100; i++) {
udelay(20);
- if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
+ if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready)
break;
}
-
+ spin_unlock_irqrestore(&nic->mdio_lock, flags);
DPRINTK(HW, DEBUG,
"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out);
@@ -1145,7 +1170,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
}
-static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
/* *INDENT-OFF* */
static struct {
@@ -1188,13 +1213,13 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* driver can change the algorithm.
*
* INTDELAY - This loads the dead-man timer with its inital value.
-* When this timer expires the interrupt is asserted, and the
+* When this timer expires the interrupt is asserted, and the
* timer is reset each time a new packet is received. (see
* BUNDLEMAX below to set the limit on number of chained packets)
* The current default is 0x600 or 1536. Experiments show that
* the value should probably stay within the 0x200 - 0x1000.
*
-* BUNDLEMAX -
+* BUNDLEMAX -
* This sets the maximum number of frames that will be bundled. In
* some situations, such as the TCP windowing algorithm, it may be
* better to limit the growth of the bundle size than let it go as
@@ -1204,7 +1229,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* an interrupt for every frame received. If you do not want to put
* a limit on the bundle size, set this value to xFFFF.
*
-* BUNDLESMALL -
+* BUNDLESMALL -
* This contains a bit-mask describing the minimum size frame that
* will be bundled. The default masks the lower 7 bits, which means
* that any frame less than 128 bytes in length will not be bundled,
@@ -1219,7 +1244,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
*
* The current default is 0xFF80, which masks out the lower 7 bits.
* This means that any frame which is x7F (127) bytes or smaller
-* will cause an immediate interrupt. Because this value must be a
+* will cause an immediate interrupt. Because this value must be a
* bit mask, there are only a few valid values that can be used. To
* turn this feature off, the driver can write the value xFFFF to the
* lower word of this instruction (in the same way that the other
@@ -1228,7 +1253,7 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
* standard Ethernet frames are <= 2047 bytes in length.
*************************************************************************/
-/* if you wish to disable the ucode functionality, while maintaining the
+/* if you wish to disable the ucode functionality, while maintaining the
* workarounds it provides, set the following defines to:
* BUNDLESMALL 0
* BUNDLEMAX 1
@@ -1259,12 +1284,46 @@ static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
for (i = 0; i < UCODE_SIZE; i++)
cb->u.ucode[i] = cpu_to_le32(ucode[i]);
- cb->command = cpu_to_le16(cb_ucode);
+ cb->command = cpu_to_le16(cb_ucode | cb_el);
return;
}
noloaducode:
- cb->command = cpu_to_le16(cb_nop);
+ cb->command = cpu_to_le16(cb_nop | cb_el);
+}
+
+static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
+ void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+{
+ int err = 0, counter = 50;
+ struct cb *cb = nic->cb_to_clean;
+
+ if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
+ DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
+
+ /* must restart cuc */
+ nic->cuc_cmd = cuc_start;
+
+ /* wait for completion */
+ e100_write_flush(nic);
+ udelay(10);
+
+ /* wait for possibly (ouch) 500ms */
+ while (!(cb->status & cpu_to_le16(cb_complete))) {
+ msleep(10);
+ if (!--counter) break;
+ }
+
+ /* ack any interupts, something could have been set */
+ writeb(~0, &nic->csr->scb.stat_ack);
+
+ /* if the command failed, or is not OK, notify and return */
+ if (!counter || !(cb->status & cpu_to_le16(cb_ok))) {
+ DPRINTK(PROBE,ERR, "ucode load failed\n");
+ err = -EPERM;
+ }
+
+ return err;
}
static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
@@ -1332,13 +1391,13 @@ static int e100_phy_init(struct nic *nic)
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
}
- if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+ if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
/* enable/disable MDI/MDI-X auto-switching.
MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
- (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
- !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
+ (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
+ !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
else
mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
@@ -1363,7 +1422,7 @@ static int e100_hw_init(struct nic *nic)
return err;
if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
return err;
- if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+ if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
return err;
if((err = e100_exec_cb(nic, NULL, e100_configure)))
return err;
@@ -1468,7 +1527,7 @@ static void e100_update_stats(struct nic *nic)
}
}
-
+
if(e100_exec_cmd(nic, cuc_dump_reset, 0))
DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
@@ -1517,10 +1576,10 @@ static void e100_watchdog(unsigned long data)
mii_check_link(&nic->mii);
/* Software generated interrupt to recover from (rare) Rx
- * allocation failure.
- * Unfortunately have to use a spinlock to not re-enable interrupts
- * accidentally, due to hardware that shares a register between the
- * interrupt mask bit and the SW Interrupt generation bit */
+ * allocation failure.
+ * Unfortunately have to use a spinlock to not re-enable interrupts
+ * accidentally, due to hardware that shares a register between the
+ * interrupt mask bit and the SW Interrupt generation bit */
spin_lock_irq(&nic->cmd_lock);
writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
spin_unlock_irq(&nic->cmd_lock);
@@ -1542,7 +1601,7 @@ static void e100_watchdog(unsigned long data)
mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD);
}
-static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = nic->tx_command;
@@ -1592,7 +1651,7 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return 0;
}
-static inline int e100_tx_clean(struct nic *nic)
+static int e100_tx_clean(struct nic *nic)
{
struct cb *cb;
int tx_cleaned = 0;
@@ -1703,7 +1762,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
}
#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
-static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
+static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
{
if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
return -ENOMEM;
@@ -1737,7 +1796,7 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
return 0;
}
-static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
+static int e100_rx_indicate(struct nic *nic, struct rx *rx,
unsigned int *work_done, unsigned int work_to_do)
{
struct sk_buff *skb = rx->skb;
@@ -1797,7 +1856,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
return 0;
}
-static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
+static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do)
{
struct rx *rx;
@@ -1805,7 +1864,7 @@ static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
struct rx *rx_to_start = NULL;
/* are we already rnr? then pay attention!!! this ensures that
- * the state machine progression never allows a start with a
+ * the state machine progression never allows a start with a
* partially cleaned list, avoiding a race between hardware
* and rx_to_clean when in NAPI mode */
if(RU_SUSPENDED == nic->ru_running)
@@ -2041,7 +2100,7 @@ static void e100_tx_timeout(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
- /* Reset outside of interrupt context, to avoid request_irq
+ /* Reset outside of interrupt context, to avoid request_irq
* in interrupt context */
schedule_work(&nic->tx_timeout_task);
}
@@ -2288,7 +2347,7 @@ static int e100_set_ringparam(struct net_device *netdev,
struct param_range *rfds = &nic->params.rfds;
struct param_range *cbs = &nic->params.cbs;
- if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
if(netif_running(netdev))
@@ -2562,6 +2621,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
/* locks must be initialized before calling hw_reset */
spin_lock_init(&nic->cb_lock);
spin_lock_init(&nic->cmd_lock);
+ spin_lock_init(&nic->mdio_lock);
/* Reset the device before pci_set_master() in case device is in some
* funky state and has an interrupt pending - hint: we don't have the
@@ -2605,7 +2665,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->flags |= wol_magic;
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
+ err = pci_enable_wake(pdev, 0, 0);
+ if (err)
+ DPRINTK(PROBE, ERR, "Error clearing wake event\n");
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
@@ -2656,6 +2718,7 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
if(netif_running(netdev))
e100_down(nic);
@@ -2663,9 +2726,14 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_detach(netdev);
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ nic->flags & (wol_magic | e100_asf(nic)));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error %d setting power state\n", retval);
return 0;
}
@@ -2674,11 +2742,16 @@ static int e100_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
- pci_set_power_state(pdev, PCI_D0);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error waking adapter\n");
pci_restore_state(pdev);
/* ack any pending wake events, disable PME */
- pci_enable_wake(pdev, 0, 0);
+ retval = pci_enable_wake(pdev, 0, 0);
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error clearing wake events\n");
if(e100_hw_init(nic))
DPRINTK(HW, ERR, "e100_hw_init failed\n");
@@ -2695,12 +2768,15 @@ static void e100_shutdown(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
+ int retval;
#ifdef CONFIG_PM
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
#else
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+ retval = pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
#endif
+ if (retval)
+ DPRINTK(PROBE,ERR, "Error enabling wake\n");
}
@@ -2713,7 +2789,7 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
- .shutdown = e100_shutdown,
+ .shutdown = e100_shutdown,
};
static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 3f653a93e1bc..27c77306193b 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -72,10 +72,6 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
-#ifdef CONFIG_E1000_MQ
-#include <linux/cpu.h>
-#include <linux/smp.h>
-#endif
#define BAR_0 0
#define BAR_1 1
@@ -87,6 +83,10 @@
struct e1000_adapter;
#include "e1000_hw.h"
+#ifdef CONFIG_E1000_MQ
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#endif
#ifdef DBG
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
@@ -169,6 +169,13 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
+#ifdef CONFIG_E1000_MQ
+struct e1000_queue_stats {
+ uint64_t packets;
+ uint64_t bytes;
+};
+#endif
+
struct e1000_ps_page { struct page *ps_page[PS_PAGE_BUFFERS]; };
struct e1000_ps_page_dma { uint64_t ps_page_dma[PS_PAGE_BUFFERS]; };
@@ -188,11 +195,15 @@ struct e1000_tx_ring {
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
- struct e1000_buffer previous_buffer_info;
spinlock_t tx_lock;
uint16_t tdh;
uint16_t tdt;
- uint64_t pkt;
+
+ boolean_t last_tx_tso;
+
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats tx_stats;
+#endif
};
struct e1000_rx_ring {
@@ -214,9 +225,17 @@ struct e1000_rx_ring {
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *rx_skb_top;
+ struct sk_buff *rx_skb_prev;
+
+ /* cpu for rx queue */
+ int cpu;
+
uint16_t rdh;
uint16_t rdt;
- uint64_t pkt;
+#ifdef CONFIG_E1000_MQ
+ struct e1000_queue_stats rx_stats;
+#endif
};
#define E1000_DESC_UNUSED(R) \
@@ -249,6 +268,9 @@ struct e1000_adapter {
uint16_t link_speed;
uint16_t link_duplex;
spinlock_t stats_lock;
+#ifdef CONFIG_E1000_NAPI
+ spinlock_t tx_queue_lock;
+#endif
atomic_t irq_sem;
struct work_struct tx_timeout_task;
struct work_struct watchdog_task;
@@ -262,6 +284,7 @@ struct e1000_adapter {
#ifdef CONFIG_E1000_MQ
struct e1000_tx_ring **cpu_tx_ring; /* per-cpu */
#endif
+ unsigned long tx_queue_len;
uint32_t txd_cmd;
uint32_t tx_int_delay;
uint32_t tx_abs_int_delay;
@@ -269,9 +292,11 @@ struct e1000_adapter {
uint64_t gotcl_old;
uint64_t tpt_old;
uint64_t colc_old;
+ uint32_t tx_timeout_count;
uint32_t tx_fifo_head;
uint32_t tx_head_addr;
uint32_t tx_fifo_size;
+ uint8_t tx_timeout_factor;
atomic_t tx_fifo_stall;
boolean_t pcix_82544;
boolean_t detect_tx_hung;
@@ -279,14 +304,15 @@ struct e1000_adapter {
/* RX */
#ifdef CONFIG_E1000_NAPI
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring,
- int *work_done, int work_to_do);
+ struct e1000_rx_ring *rx_ring,
+ int *work_done, int work_to_do);
#else
boolean_t (*clean_rx) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring);
#endif
void (*alloc_rx_buf) (struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
#ifdef CONFIG_E1000_NAPI
struct net_device *polling_netdev; /* One per active queue */
@@ -294,13 +320,15 @@ struct e1000_adapter {
#ifdef CONFIG_E1000_MQ
struct net_device **cpu_netdev; /* per-cpu */
struct call_async_data_struct rx_sched_call_data;
- int cpu_for_queue[4];
+ cpumask_t cpumask;
#endif
- int num_queues;
+ int num_tx_queues;
+ int num_rx_queues;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
uint64_t rx_hdr_split;
+ uint32_t alloc_rx_buff_failed;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
@@ -328,6 +356,7 @@ struct e1000_adapter {
struct e1000_rx_ring test_rx_ring;
+ u32 *config_space;
int msg_enable;
#ifdef CONFIG_PCI_MSI
boolean_t have_msi;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 8eae8ba27e84..5cedc81786e3 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -80,6 +80,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "tx_deferred_ok", E1000_STAT(stats.dc) },
{ "tx_single_coll_ok", E1000_STAT(stats.scc) },
{ "tx_multi_coll_ok", E1000_STAT(stats.mcc) },
+ { "tx_timeout_count", E1000_STAT(tx_timeout_count) },
{ "rx_long_length_errors", E1000_STAT(stats.roc) },
{ "rx_short_length_errors", E1000_STAT(stats.ruc) },
{ "rx_align_errors", E1000_STAT(stats.algnerrc) },
@@ -93,9 +94,20 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
{ "rx_header_split", E1000_STAT(rx_hdr_split) },
+ { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) },
};
-#define E1000_STATS_LEN \
+
+#ifdef CONFIG_E1000_MQ
+#define E1000_QUEUE_STATS_LEN \
+ (((struct e1000_adapter *)netdev->priv)->num_tx_queues + \
+ ((struct e1000_adapter *)netdev->priv)->num_rx_queues) \
+ * (sizeof(struct e1000_queue_stats) / sizeof(uint64_t))
+#else
+#define E1000_QUEUE_STATS_LEN 0
+#endif
+#define E1000_GLOBAL_STATS_LEN \
sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
+#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN)
static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)", "Eeprom test (offline)",
"Interrupt test (offline)", "Loopback test (offline)",
@@ -109,7 +121,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
ecmd->supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
@@ -121,7 +133,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_TP;
- if(hw->autoneg == 1) {
+ if (hw->autoneg == 1) {
ecmd->advertising |= ADVERTISED_Autoneg;
/* the e1000 autoneg seems to match ethtool nicely */
@@ -132,7 +144,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
ecmd->phy_address = hw->phy_addr;
- if(hw->mac_type == e1000_82543)
+ if (hw->mac_type == e1000_82543)
ecmd->transceiver = XCVR_EXTERNAL;
else
ecmd->transceiver = XCVR_INTERNAL;
@@ -148,13 +160,13 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
- if(hw->mac_type >= e1000_82545)
+ if (hw->mac_type >= e1000_82545)
ecmd->transceiver = XCVR_INTERNAL;
else
ecmd->transceiver = XCVR_EXTERNAL;
}
- if(netif_carrier_ok(adapter->netdev)) {
+ if (netif_carrier_ok(adapter->netdev)) {
e1000_get_speed_and_duplex(hw, &adapter->link_speed,
&adapter->link_duplex);
@@ -163,7 +175,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
* and HALF_DUPLEX != DUPLEX_HALF */
- if(adapter->link_duplex == FULL_DUPLEX)
+ if (adapter->link_duplex == FULL_DUPLEX)
ecmd->duplex = DUPLEX_FULL;
else
ecmd->duplex = DUPLEX_HALF;
@@ -183,13 +195,21 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- if(ecmd->autoneg == AUTONEG_ENABLE) {
+ /* When SoL/IDER sessions are active, autoneg/speed/duplex
+ * cannot be changed */
+ if (e1000_check_phy_reset_block(hw)) {
+ DPRINTK(DRV, ERR, "Cannot change link characteristics "
+ "when SoL/IDER is active.\n");
+ return -EINVAL;
+ }
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
hw->autoneg = 1;
- if(hw->media_type == e1000_media_type_fiber)
+ if (hw->media_type == e1000_media_type_fiber)
hw->autoneg_advertised = ADVERTISED_1000baseT_Full |
ADVERTISED_FIBRE |
ADVERTISED_Autoneg;
- else
+ else
hw->autoneg_advertised = ADVERTISED_10baseT_Half |
ADVERTISED_10baseT_Full |
ADVERTISED_100baseT_Half |
@@ -199,12 +219,12 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
ADVERTISED_TP;
ecmd->advertising = hw->autoneg_advertised;
} else
- if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
+ if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
return -EINVAL;
/* reset the link */
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_reset(adapter);
e1000_up(adapter);
@@ -221,14 +241,14 @@ e1000_get_pauseparam(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- pause->autoneg =
+ pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
-
- if(hw->fc == e1000_fc_rx_pause)
+
+ if (hw->fc == e1000_fc_rx_pause)
pause->rx_pause = 1;
- else if(hw->fc == e1000_fc_tx_pause)
+ else if (hw->fc == e1000_fc_tx_pause)
pause->tx_pause = 1;
- else if(hw->fc == e1000_fc_full) {
+ else if (hw->fc == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
@@ -240,31 +260,30 @@ e1000_set_pauseparam(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
-
+
adapter->fc_autoneg = pause->autoneg;
- if(pause->rx_pause && pause->tx_pause)
+ if (pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_full;
- else if(pause->rx_pause && !pause->tx_pause)
+ else if (pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_rx_pause;
- else if(!pause->rx_pause && pause->tx_pause)
+ else if (!pause->rx_pause && pause->tx_pause)
hw->fc = e1000_fc_tx_pause;
- else if(!pause->rx_pause && !pause->tx_pause)
+ else if (!pause->rx_pause && !pause->tx_pause)
hw->fc = e1000_fc_none;
hw->original_fc = hw->fc;
- if(adapter->fc_autoneg == AUTONEG_ENABLE) {
- if(netif_running(adapter->netdev)) {
+ if (adapter->fc_autoneg == AUTONEG_ENABLE) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
- }
- else
+ } else
return ((hw->media_type == e1000_media_type_fiber) ?
e1000_setup_link(hw) : e1000_force_mac_fc(hw));
-
+
return 0;
}
@@ -281,14 +300,14 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
struct e1000_adapter *adapter = netdev_priv(netdev);
adapter->rx_csum = data;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
e1000_reset(adapter);
return 0;
}
-
+
static uint32_t
e1000_get_tx_csum(struct net_device *netdev)
{
@@ -300,7 +319,7 @@ e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(adapter->hw.mac_type < e1000_82543) {
+ if (adapter->hw.mac_type < e1000_82543) {
if (!data)
return -EINVAL;
return 0;
@@ -319,8 +338,8 @@ static int
e1000_set_tso(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if((adapter->hw.mac_type < e1000_82544) ||
- (adapter->hw.mac_type == e1000_82547))
+ if ((adapter->hw.mac_type < e1000_82544) ||
+ (adapter->hw.mac_type == e1000_82547))
return data ? -EINVAL : 0;
if (data)
@@ -328,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, uint32_t data)
else
netdev->features &= ~NETIF_F_TSO;
return 0;
-}
+}
#endif /* NETIF_F_TSO */
static uint32_t
@@ -345,7 +364,7 @@ e1000_set_msglevel(struct net_device *netdev, uint32_t data)
adapter->msg_enable = data;
}
-static int
+static int
e1000_get_regs_len(struct net_device *netdev)
{
#define E1000_REGS_LEN 32
@@ -381,7 +400,7 @@ e1000_get_regs(struct net_device *netdev,
regs_buff[11] = E1000_READ_REG(hw, TIDV);
regs_buff[12] = adapter->hw.phy_type; /* PHY type (IGP=1, M88=0) */
- if(hw->phy_type == e1000_phy_igp) {
+ if (hw->phy_type == e1000_phy_igp) {
e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT,
IGP01E1000_PHY_AGC_A);
e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A &
@@ -435,7 +454,7 @@ e1000_get_regs(struct net_device *netdev,
e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */
regs_buff[25] = regs_buff[24]; /* phy remote receiver status */
- if(hw->mac_type >= e1000_82540 &&
+ if (hw->mac_type >= e1000_82540 &&
hw->media_type == e1000_media_type_copper) {
regs_buff[26] = E1000_READ_REG(hw, MANC);
}
@@ -459,7 +478,7 @@ e1000_get_eeprom(struct net_device *netdev,
int ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EINVAL;
eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -469,16 +488,16 @@ e1000_get_eeprom(struct net_device *netdev,
eeprom_buff = kmalloc(sizeof(uint16_t) *
(last_word - first_word + 1), GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
- if(hw->eeprom.type == e1000_eeprom_spi)
+ if (hw->eeprom.type == e1000_eeprom_spi)
ret_val = e1000_read_eeprom(hw, first_word,
last_word - first_word + 1,
eeprom_buff);
else {
for (i = 0; i < last_word - first_word + 1; i++)
- if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
+ if ((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
&eeprom_buff[i])))
break;
}
@@ -505,10 +524,10 @@ e1000_set_eeprom(struct net_device *netdev,
int max_len, first_word, last_word, ret_val = 0;
uint16_t i;
- if(eeprom->len == 0)
+ if (eeprom->len == 0)
return -EOPNOTSUPP;
- if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
+ if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
return -EFAULT;
max_len = hw->eeprom.word_size * 2;
@@ -516,19 +535,19 @@ e1000_set_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_buff = kmalloc(max_len, GFP_KERNEL);
- if(!eeprom_buff)
+ if (!eeprom_buff)
return -ENOMEM;
ptr = (void *)eeprom_buff;
- if(eeprom->offset & 1) {
+ if (eeprom->offset & 1) {
/* need read/modify/write of first changed EEPROM word */
/* only the second byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, first_word, 1,
&eeprom_buff[0]);
ptr++;
}
- if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+ if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
/* need read/modify/write of last changed EEPROM word */
/* only the first byte of the word is being modified */
ret_val = e1000_read_eeprom(hw, last_word, 1,
@@ -547,9 +566,9 @@ e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_write_eeprom(hw, first_word,
last_word - first_word + 1, eeprom_buff);
- /* Update the checksum over the first part of the EEPROM if needed
+ /* Update the checksum over the first part of the EEPROM if needed
* and flush shadow RAM for 82573 conrollers */
- if((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
+ if ((ret_val == 0) && ((first_word <= EEPROM_CHECKSUM_REG) ||
(hw->mac_type == e1000_82573)))
e1000_update_eeprom_checksum(hw);
@@ -562,10 +581,29 @@ e1000_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ char firmware_version[32];
+ uint16_t eeprom_data;
strncpy(drvinfo->driver, e1000_driver_name, 32);
strncpy(drvinfo->version, e1000_driver_version, 32);
- strncpy(drvinfo->fw_version, "N/A", 32);
+
+ /* EEPROM image version # is reported as firmware version # for
+ * 8257{1|2|3} controllers */
+ e1000_read_eeprom(&adapter->hw, 5, 1, &eeprom_data);
+ switch (adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ case e1000_82573:
+ sprintf(firmware_version, "%d.%d-%d",
+ (eeprom_data & 0xF000) >> 12,
+ (eeprom_data & 0x0FF0) >> 4,
+ eeprom_data & 0x000F);
+ break;
+ default:
+ sprintf(firmware_version, "N/A");
+ }
+
+ strncpy(drvinfo->fw_version, firmware_version, 32);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
drvinfo->n_stats = E1000_STATS_LEN;
drvinfo->testinfo_len = E1000_TEST_LEN;
@@ -594,7 +632,7 @@ e1000_get_ringparam(struct net_device *netdev,
ring->rx_jumbo_pending = 0;
}
-static int
+static int
e1000_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
@@ -604,8 +642,8 @@ e1000_set_ringparam(struct net_device *netdev,
struct e1000_rx_ring *rxdr, *rx_old, *rx_new;
int i, err, tx_ring_size, rx_ring_size;
- tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
- rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+ tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
+ rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
if (netif_running(adapter->netdev))
e1000_down(adapter);
@@ -631,25 +669,25 @@ e1000_set_ringparam(struct net_device *netdev,
txdr = adapter->tx_ring;
rxdr = adapter->rx_ring;
- if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_RXD : E1000_MAX_82544_RXD));
- E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE);
txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
E1000_MAX_TXD : E1000_MAX_82544_TXD));
- E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+ E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE);
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
txdr[i].count = txdr->count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
rxdr[i].count = rxdr->count;
- }
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
/* Try to get new resources before deleting old */
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
@@ -669,7 +707,7 @@ e1000_set_ringparam(struct net_device *netdev,
kfree(rx_old);
adapter->rx_ring = rx_new;
adapter->tx_ring = tx_new;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
return err;
}
@@ -688,10 +726,10 @@ err_setup_rx:
uint32_t pat, value; \
uint32_t test[] = \
{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \
- for(pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
+ for (pat = 0; pat < sizeof(test)/sizeof(test[0]); pat++) { \
E1000_WRITE_REG(&adapter->hw, R, (test[pat] & W)); \
value = E1000_READ_REG(&adapter->hw, R); \
- if(value != (test[pat] & W & M)) { \
+ if (value != (test[pat] & W & M)) { \
DPRINTK(DRV, ERR, "pattern test reg %04X failed: got " \
"0x%08X expected 0x%08X\n", \
E1000_##R, value, (test[pat] & W & M)); \
@@ -707,7 +745,7 @@ err_setup_rx:
uint32_t value; \
E1000_WRITE_REG(&adapter->hw, R, W & M); \
value = E1000_READ_REG(&adapter->hw, R); \
- if((W & M) != (value & M)) { \
+ if ((W & M) != (value & M)) { \
DPRINTK(DRV, ERR, "set/check reg %04X test failed: got 0x%08X "\
"expected 0x%08X\n", E1000_##R, (value & M), (W & M)); \
*data = (adapter->hw.mac_type < e1000_82543) ? \
@@ -743,7 +781,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
value = (E1000_READ_REG(&adapter->hw, STATUS) & toggle);
E1000_WRITE_REG(&adapter->hw, STATUS, toggle);
after = E1000_READ_REG(&adapter->hw, STATUS) & toggle;
- if(value != after) {
+ if (value != after) {
DPRINTK(DRV, ERR, "failed STATUS register test got: "
"0x%08X expected: 0x%08X\n", after, value);
*data = 1;
@@ -771,7 +809,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0x003FFFFB);
REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000);
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
REG_SET_AND_CHECK(RCTL, 0x06DFB3FE, 0xFFFFFFFF);
REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
@@ -779,7 +817,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF);
REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF);
- for(i = 0; i < E1000_RAR_ENTRIES; i++) {
+ for (i = 0; i < E1000_RAR_ENTRIES; i++) {
REG_PATTERN_TEST(RA + ((i << 1) << 2), 0xFFFFFFFF,
0xFFFFFFFF);
REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF,
@@ -795,7 +833,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data)
}
- for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ for (i = 0; i < E1000_MC_TBL_SIZE; i++)
REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
*data = 0;
@@ -811,8 +849,8 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Read and add up the contents of the EEPROM */
- for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
- if((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
+ for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
+ if ((e1000_read_eeprom(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1;
break;
}
@@ -820,7 +858,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data)
}
/* If Checksum is not Correct return error else test passed */
- if((checksum != (uint16_t) EEPROM_SUM) && !(*data))
+ if ((checksum != (uint16_t) EEPROM_SUM) && !(*data))
*data = 2;
return *data;
@@ -849,9 +887,9 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 0;
/* Hook up test interrupt handler just for this test */
- if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ if (!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
shared_int = FALSE;
- } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ } else if (request_irq(irq, &e1000_test_intr, SA_SHIRQ,
netdev->name, netdev)){
*data = 1;
return -1;
@@ -862,12 +900,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
msec_delay(10);
/* Test each interrupt */
- for(; i < 10; i++) {
+ for (; i < 10; i++) {
/* Interrupt to test */
mask = 1 << i;
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the interrupt to be reported in
* the cause register and then force the same
* interrupt and see if one gets posted. If
@@ -878,8 +916,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, IMC, mask);
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
-
- if(adapter->test_icr & mask) {
+
+ if (adapter->test_icr & mask) {
*data = 3;
break;
}
@@ -896,12 +934,12 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, mask);
msec_delay(10);
- if(!(adapter->test_icr & mask)) {
+ if (!(adapter->test_icr & mask)) {
*data = 4;
break;
}
- if(!shared_int) {
+ if (!shared_int) {
/* Disable the other interrupts to be reported in
* the cause register and then force the other
* interrupts and see if any get posted. If
@@ -913,7 +951,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
msec_delay(10);
- if(adapter->test_icr) {
+ if (adapter->test_icr) {
*data = 5;
break;
}
@@ -938,35 +976,42 @@ e1000_free_desc_rings(struct e1000_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
int i;
- if(txdr->desc && txdr->buffer_info) {
- for(i = 0; i < txdr->count; i++) {
- if(txdr->buffer_info[i].dma)
+ if (txdr->desc && txdr->buffer_info) {
+ for (i = 0; i < txdr->count; i++) {
+ if (txdr->buffer_info[i].dma)
pci_unmap_single(pdev, txdr->buffer_info[i].dma,
txdr->buffer_info[i].length,
PCI_DMA_TODEVICE);
- if(txdr->buffer_info[i].skb)
+ if (txdr->buffer_info[i].skb)
dev_kfree_skb(txdr->buffer_info[i].skb);
}
}
- if(rxdr->desc && rxdr->buffer_info) {
- for(i = 0; i < rxdr->count; i++) {
- if(rxdr->buffer_info[i].dma)
+ if (rxdr->desc && rxdr->buffer_info) {
+ for (i = 0; i < rxdr->count; i++) {
+ if (rxdr->buffer_info[i].dma)
pci_unmap_single(pdev, rxdr->buffer_info[i].dma,
rxdr->buffer_info[i].length,
PCI_DMA_FROMDEVICE);
- if(rxdr->buffer_info[i].skb)
+ if (rxdr->buffer_info[i].skb)
dev_kfree_skb(rxdr->buffer_info[i].skb);
}
}
- if(txdr->desc)
+ if (txdr->desc) {
pci_free_consistent(pdev, txdr->size, txdr->desc, txdr->dma);
- if(rxdr->desc)
+ txdr->desc = NULL;
+ }
+ if (rxdr->desc) {
pci_free_consistent(pdev, rxdr->size, rxdr->desc, rxdr->dma);
+ rxdr->desc = NULL;
+ }
kfree(txdr->buffer_info);
+ txdr->buffer_info = NULL;
kfree(rxdr->buffer_info);
+ rxdr->buffer_info = NULL;
+
return;
}
@@ -981,11 +1026,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Tx descriptor ring and Tx buffers */
- if(!txdr->count)
- txdr->count = E1000_DEFAULT_TXD;
+ if (!txdr->count)
+ txdr->count = E1000_DEFAULT_TXD;
size = txdr->count * sizeof(struct e1000_buffer);
- if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 1;
goto err_nomem;
}
@@ -993,7 +1038,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
E1000_ROUNDUP(txdr->size, 4096);
- if(!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
+ if (!(txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma))) {
ret_val = 2;
goto err_nomem;
}
@@ -1012,12 +1057,12 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT |
E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT);
- for(i = 0; i < txdr->count; i++) {
+ for (i = 0; i < txdr->count; i++) {
struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i);
struct sk_buff *skb;
unsigned int size = 1024;
- if(!(skb = alloc_skb(size, GFP_KERNEL))) {
+ if (!(skb = alloc_skb(size, GFP_KERNEL))) {
ret_val = 3;
goto err_nomem;
}
@@ -1037,18 +1082,18 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Rx descriptor ring and Rx buffers */
- if(!rxdr->count)
- rxdr->count = E1000_DEFAULT_RXD;
+ if (!rxdr->count)
+ rxdr->count = E1000_DEFAULT_RXD;
size = rxdr->count * sizeof(struct e1000_buffer);
- if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
+ if (!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
ret_val = 4;
goto err_nomem;
}
memset(rxdr->buffer_info, 0, size);
rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
- if(!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
+ if (!(rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma))) {
ret_val = 5;
goto err_nomem;
}
@@ -1068,11 +1113,11 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- for(i = 0; i < rxdr->count; i++) {
+ for (i = 0; i < rxdr->count; i++) {
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+ if (!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
GFP_KERNEL))) {
ret_val = 6;
goto err_nomem;
@@ -1181,15 +1226,15 @@ e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter)
/* Check Phy Configuration */
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
- if(phy_reg != 0x4100)
+ if (phy_reg != 0x4100)
return 9;
e1000_read_phy_reg(&adapter->hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg);
- if(phy_reg != 0x0070)
+ if (phy_reg != 0x0070)
return 10;
e1000_read_phy_reg(&adapter->hw, 29, &phy_reg);
- if(phy_reg != 0x001A)
+ if (phy_reg != 0x001A)
return 11;
return 0;
@@ -1203,7 +1248,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
adapter->hw.autoneg = FALSE;
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
e1000_write_phy_reg(&adapter->hw,
M88E1000_PHY_SPEC_CTRL, 0x0808);
@@ -1223,14 +1268,14 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */
E1000_CTRL_FD); /* Force Duplex to FULL */
- if(adapter->hw.media_type == e1000_media_type_copper &&
+ if (adapter->hw.media_type == e1000_media_type_copper &&
adapter->hw.phy_type == e1000_phy_m88) {
ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
} else {
/* Set the ILOS bit on the fiber Nic is half
* duplex link is detected. */
stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
- if((stat_reg & E1000_STATUS_FD) == 0)
+ if ((stat_reg & E1000_STATUS_FD) == 0)
ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
}
@@ -1239,7 +1284,7 @@ e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
/* Disable the receiver on the PHY so when a cable is plugged in, the
* PHY does not begin to autoneg when a cable is reconnected to the NIC.
*/
- if(adapter->hw.phy_type == e1000_phy_m88)
+ if (adapter->hw.phy_type == e1000_phy_m88)
e1000_phy_disable_receiver(adapter);
udelay(500);
@@ -1255,14 +1300,14 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
switch (adapter->hw.mac_type) {
case e1000_82543:
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
/* Attempt to setup Loopback mode on Non-integrated PHY.
* Some PHY registers get corrupted at random, so
* attempt this 10 times.
*/
- while(e1000_nonintegrated_phy_loopback(adapter) &&
+ while (e1000_nonintegrated_phy_loopback(adapter) &&
count++ < 10);
- if(count < 11)
+ if (count < 11)
return 0;
}
break;
@@ -1300,22 +1345,33 @@ e1000_set_phy_loopback(struct e1000_adapter *adapter)
static int
e1000_setup_loopback_test(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
uint32_t rctl;
- if(adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) {
- if(adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546 ||
- adapter->hw.mac_type == e1000_82545_rev_3 ||
- adapter->hw.mac_type == e1000_82546_rev_3)
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
+ switch (hw->mac_type) {
+ case e1000_82545:
+ case e1000_82546:
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
return e1000_set_phy_loopback(adapter);
- else {
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ break;
+ case e1000_82571:
+ case e1000_82572:
+#define E1000_SERDES_LB_ON 0x410
+ e1000_set_phy_loopback(adapter);
+ E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_ON);
+ msec_delay(10);
+ return 0;
+ break;
+ default:
+ rctl = E1000_READ_REG(hw, RCTL);
rctl |= E1000_RCTL_LBM_TCVR;
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
return 0;
}
- } else if(adapter->hw.media_type == e1000_media_type_copper)
+ } else if (hw->media_type == e1000_media_type_copper)
return e1000_set_phy_loopback(adapter);
return 7;
@@ -1324,27 +1380,38 @@ e1000_setup_loopback_test(struct e1000_adapter *adapter)
static void
e1000_loopback_cleanup(struct e1000_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
uint32_t rctl;
uint16_t phy_reg;
- rctl = E1000_READ_REG(&adapter->hw, RCTL);
+ rctl = E1000_READ_REG(hw, RCTL);
rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ E1000_WRITE_REG(hw, RCTL, rctl);
- if(adapter->hw.media_type == e1000_media_type_copper ||
- ((adapter->hw.media_type == e1000_media_type_fiber ||
- adapter->hw.media_type == e1000_media_type_internal_serdes) &&
- (adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546 ||
- adapter->hw.mac_type == e1000_82545_rev_3 ||
- adapter->hw.mac_type == e1000_82546_rev_3))) {
- adapter->hw.autoneg = TRUE;
- e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg);
- if(phy_reg & MII_CR_LOOPBACK) {
+ switch (hw->mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes) {
+#define E1000_SERDES_LB_OFF 0x400
+ E1000_WRITE_REG(hw, SCTL, E1000_SERDES_LB_OFF);
+ msec_delay(10);
+ break;
+ }
+ /* Fall Through */
+ case e1000_82545:
+ case e1000_82546:
+ case e1000_82545_rev_3:
+ case e1000_82546_rev_3:
+ default:
+ hw->autoneg = TRUE;
+ e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
+ if (phy_reg & MII_CR_LOOPBACK) {
phy_reg &= ~MII_CR_LOOPBACK;
- e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_reg);
- e1000_phy_reset(&adapter->hw);
+ e1000_write_phy_reg(hw, PHY_CTRL, phy_reg);
+ e1000_phy_reset(hw);
}
+ break;
}
}
@@ -1352,7 +1419,7 @@ static void
e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
memset(skb->data, 0xFF, frame_size);
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
+ frame_size &= ~1;
memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
@@ -1361,9 +1428,9 @@ e1000_create_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
static int
e1000_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
{
- frame_size = (frame_size % 2) ? (frame_size - 1) : frame_size;
- if(*(skb->data + 3) == 0xFF) {
- if((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
+ frame_size &= ~1;
+ if (*(skb->data + 3) == 0xFF) {
+ if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
(*(skb->data + frame_size / 2 + 12) == 0xAF)) {
return 0;
}
@@ -1382,53 +1449,53 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
- /* Calculate the loop count based on the largest descriptor ring
+ /* Calculate the loop count based on the largest descriptor ring
* The idea is to wrap the largest ring a number of times using 64
* send/receive pairs during each loop
*/
- if(rxdr->count <= txdr->count)
+ if (rxdr->count <= txdr->count)
lc = ((txdr->count / 64) * 2) + 1;
else
lc = ((rxdr->count / 64) * 2) + 1;
k = l = 0;
- for(j = 0; j <= lc; j++) { /* loop count loop */
- for(i = 0; i < 64; i++) { /* send the packets */
- e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
+ for (j = 0; j <= lc; j++) { /* loop count loop */
+ for (i = 0; i < 64; i++) { /* send the packets */
+ e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
1024);
- pci_dma_sync_single_for_device(pdev,
+ pci_dma_sync_single_for_device(pdev,
txdr->buffer_info[k].dma,
txdr->buffer_info[k].length,
PCI_DMA_TODEVICE);
- if(unlikely(++k == txdr->count)) k = 0;
+ if (unlikely(++k == txdr->count)) k = 0;
}
E1000_WRITE_REG(&adapter->hw, TDT, k);
msec_delay(200);
time = jiffies; /* set the start time for the receive */
good_cnt = 0;
do { /* receive the sent packets */
- pci_dma_sync_single_for_cpu(pdev,
+ pci_dma_sync_single_for_cpu(pdev,
rxdr->buffer_info[l].dma,
rxdr->buffer_info[l].length,
PCI_DMA_FROMDEVICE);
-
+
ret_val = e1000_check_lbtest_frame(
rxdr->buffer_info[l].skb,
1024);
- if(!ret_val)
+ if (!ret_val)
good_cnt++;
- if(unlikely(++l == rxdr->count)) l = 0;
- /* time + 20 msecs (200 msecs on 2.4) is more than
- * enough time to complete the receives, if it's
+ if (unlikely(++l == rxdr->count)) l = 0;
+ /* time + 20 msecs (200 msecs on 2.4) is more than
+ * enough time to complete the receives, if it's
* exceeded, break and error off
*/
} while (good_cnt < 64 && jiffies < (time + 20));
- if(good_cnt != 64) {
+ if (good_cnt != 64) {
ret_val = 13; /* ret_val is the same as mis-compare */
- break;
+ break;
}
- if(jiffies >= (time + 2)) {
+ if (jiffies >= (time + 2)) {
ret_val = 14; /* error code for time out error */
break;
}
@@ -1439,12 +1506,25 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
static int
e1000_loopback_test(struct e1000_adapter *adapter, uint64_t *data)
{
- if((*data = e1000_setup_desc_rings(adapter))) goto err_loopback;
- if((*data = e1000_setup_loopback_test(adapter))) goto err_loopback;
+ /* PHY loopback cannot be performed if SoL/IDER
+ * sessions are active */
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(DRV, ERR, "Cannot do PHY loopback test "
+ "when SoL/IDER is active.\n");
+ *data = 0;
+ goto out;
+ }
+
+ if ((*data = e1000_setup_desc_rings(adapter)))
+ goto out;
+ if ((*data = e1000_setup_loopback_test(adapter)))
+ goto err_loopback;
*data = e1000_run_loopback_test(adapter);
e1000_loopback_cleanup(adapter);
- e1000_free_desc_rings(adapter);
+
err_loopback:
+ e1000_free_desc_rings(adapter);
+out:
return *data;
}
@@ -1468,17 +1548,17 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
*data = 1;
} else {
e1000_check_for_link(&adapter->hw);
- if(adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ if (adapter->hw.autoneg) /* if auto_neg is set wait for it */
msec_delay(4000);
- if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
+ if (!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
*data = 1;
}
}
return *data;
}
-static int
+static int
e1000_diag_test_count(struct net_device *netdev)
{
return E1000_TEST_LEN;
@@ -1491,7 +1571,7 @@ e1000_diag_test(struct net_device *netdev,
struct e1000_adapter *adapter = netdev_priv(netdev);
boolean_t if_running = netif_running(netdev);
- if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
+ if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
/* Offline tests */
/* save speed, duplex, autoneg settings */
@@ -1501,27 +1581,27 @@ e1000_diag_test(struct net_device *netdev,
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
- if(if_running)
+ if (if_running)
e1000_down(adapter);
else
e1000_reset(adapter);
- if(e1000_reg_test(adapter, &data[0]))
+ if (e1000_reg_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_eeprom_test(adapter, &data[1]))
+ if (e1000_eeprom_test(adapter, &data[1]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_intr_test(adapter, &data[2]))
+ if (e1000_intr_test(adapter, &data[2]))
eth_test->flags |= ETH_TEST_FL_FAILED;
e1000_reset(adapter);
- if(e1000_loopback_test(adapter, &data[3]))
+ if (e1000_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* restore speed, duplex, autoneg settings */
@@ -1530,11 +1610,11 @@ e1000_diag_test(struct net_device *netdev,
adapter->hw.autoneg = autoneg;
e1000_reset(adapter);
- if(if_running)
+ if (if_running)
e1000_up(adapter);
} else {
/* Online tests */
- if(e1000_link_test(adapter, &data[4]))
+ if (e1000_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
/* Offline tests aren't run; pass by default */
@@ -1552,7 +1632,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1566,8 +1646,9 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
wol->supported = 0;
wol->wolopts = 0;
return;
@@ -1579,13 +1660,13 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
WAKE_BCAST | WAKE_MAGIC;
wol->wolopts = 0;
- if(adapter->wol & E1000_WUFC_EX)
+ if (adapter->wol & E1000_WUFC_EX)
wol->wolopts |= WAKE_UCAST;
- if(adapter->wol & E1000_WUFC_MC)
+ if (adapter->wol & E1000_WUFC_MC)
wol->wolopts |= WAKE_MCAST;
- if(adapter->wol & E1000_WUFC_BC)
+ if (adapter->wol & E1000_WUFC_BC)
wol->wolopts |= WAKE_BCAST;
- if(adapter->wol & E1000_WUFC_MAG)
+ if (adapter->wol & E1000_WUFC_MAG)
wol->wolopts |= WAKE_MAGIC;
return;
}
@@ -1597,7 +1678,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- switch(adapter->hw.device_id) {
+ switch (adapter->hw.device_id) {
case E1000_DEV_ID_82542:
case E1000_DEV_ID_82543GC_FIBER:
case E1000_DEV_ID_82543GC_COPPER:
@@ -1609,24 +1690,25 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
case E1000_DEV_ID_82546EB_FIBER:
case E1000_DEV_ID_82546GB_FIBER:
+ case E1000_DEV_ID_82571EB_FIBER:
/* Wake events only supported on port A for dual fiber */
- if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+ if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
return wol->wolopts ? -EOPNOTSUPP : 0;
/* Fall Through */
default:
- if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+ if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
return -EOPNOTSUPP;
adapter->wol = 0;
- if(wol->wolopts & WAKE_UCAST)
+ if (wol->wolopts & WAKE_UCAST)
adapter->wol |= E1000_WUFC_EX;
- if(wol->wolopts & WAKE_MCAST)
+ if (wol->wolopts & WAKE_MCAST)
adapter->wol |= E1000_WUFC_MC;
- if(wol->wolopts & WAKE_BCAST)
+ if (wol->wolopts & WAKE_BCAST)
adapter->wol |= E1000_WUFC_BC;
- if(wol->wolopts & WAKE_MAGIC)
+ if (wol->wolopts & WAKE_MAGIC)
adapter->wol |= E1000_WUFC_MAG;
}
@@ -1644,7 +1726,7 @@ e1000_led_blink_callback(unsigned long data)
{
struct e1000_adapter *adapter = (struct e1000_adapter *) data;
- if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
+ if (test_and_change_bit(E1000_LED_ON, &adapter->led_status))
e1000_led_off(&adapter->hw);
else
e1000_led_on(&adapter->hw);
@@ -1657,11 +1739,11 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+ if (!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
- if(adapter->hw.mac_type < e1000_82571) {
- if(!adapter->blink_timer.function) {
+ if (adapter->hw.mac_type < e1000_82571) {
+ if (!adapter->blink_timer.function) {
init_timer(&adapter->blink_timer);
adapter->blink_timer.function = e1000_led_blink_callback;
adapter->blink_timer.data = (unsigned long) adapter;
@@ -1670,13 +1752,21 @@ e1000_phys_id(struct net_device *netdev, uint32_t data)
mod_timer(&adapter->blink_timer, jiffies);
msleep_interruptible(data * 1000);
del_timer_sync(&adapter->blink_timer);
- }
- else {
- E1000_WRITE_REG(&adapter->hw, LEDCTL, (E1000_LEDCTL_LED2_BLINK_RATE |
- E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
- (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
- (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
+ } else if (adapter->hw.mac_type < e1000_82573) {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED0_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED1_MODE_SHIFT)));
+ msleep_interruptible(data * 1000);
+ } else {
+ E1000_WRITE_REG(&adapter->hw, LEDCTL,
+ (E1000_LEDCTL_LED2_BLINK_RATE |
+ E1000_LEDCTL_LED1_BLINK | E1000_LEDCTL_LED2_BLINK |
+ (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED2_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LINK_ACTIVITY << E1000_LEDCTL_LED1_MODE_SHIFT) |
+ (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT)));
msleep_interruptible(data * 1000);
}
@@ -1691,50 +1781,89 @@ static int
e1000_nway_reset(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
return 0;
}
-static int
+static int
e1000_get_stats_count(struct net_device *netdev)
{
return E1000_STATS_LEN;
}
-static void
-e1000_get_ethtool_stats(struct net_device *netdev,
+static void
+e1000_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, uint64_t *data)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+#ifdef CONFIG_E1000_MQ
+ uint64_t *queue_stat;
+ int stat_count = sizeof(struct e1000_queue_stats) / sizeof(uint64_t);
+ int j, k;
+#endif
int i;
e1000_update_stats(adapter);
- for(i = 0; i < E1000_STATS_LEN; i++) {
- char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
- data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;
+ data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
}
+#ifdef CONFIG_E1000_MQ
+ for (j = 0; j < adapter->num_tx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->tx_ring[j].tx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ queue_stat = (uint64_t *)&adapter->rx_ring[j].rx_stats;
+ for (k = 0; k < stat_count; k++)
+ data[i + k] = queue_stat[k];
+ i += k;
+ }
+#endif
+/* BUG_ON(i != E1000_STATS_LEN); */
}
-static void
+static void
e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
{
+#ifdef CONFIG_E1000_MQ
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+#endif
+ uint8_t *p = data;
int i;
- switch(stringset) {
+ switch (stringset) {
case ETH_SS_TEST:
- memcpy(data, *e1000_gstrings_test,
+ memcpy(data, *e1000_gstrings_test,
E1000_TEST_LEN*ETH_GSTRING_LEN);
break;
case ETH_SS_STATS:
- for (i=0; i < E1000_STATS_LEN; i++) {
- memcpy(data + i * ETH_GSTRING_LEN,
- e1000_gstrings_stats[i].stat_string,
- ETH_GSTRING_LEN);
+ for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+ memcpy(p, e1000_gstrings_stats[i].stat_string,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ }
+#ifdef CONFIG_E1000_MQ
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ sprintf(p, "tx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
}
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ sprintf(p, "rx_queue_%u_packets", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_queue_%u_bytes", i);
+ p += ETH_GSTRING_LEN;
+ }
+#endif
+/* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */
break;
}
}
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index a267c5235fc0..beeec0fbbeac 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -318,6 +318,8 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -563,11 +565,13 @@ e1000_reset_hw(struct e1000_hw *hw)
msec_delay(20);
break;
case e1000_82573:
- udelay(10);
- ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
- ctrl_ext |= E1000_CTRL_EXT_EE_RST;
- E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
- E1000_WRITE_FLUSH(hw);
+ if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+ udelay(10);
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+ }
/* fall through */
case e1000_82571:
case e1000_82572:
@@ -637,6 +641,7 @@ e1000_init_hw(struct e1000_hw *hw)
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
uint32_t mta_size;
+ uint32_t ctrl_ext;
DEBUGFUNC("e1000_init_hw");
@@ -733,7 +738,6 @@ e1000_init_hw(struct e1000_hw *hw)
break;
case e1000_82571:
case e1000_82572:
- ctrl |= (1 << 22);
case e1000_82573:
ctrl |= E1000_TXDCTL_COUNT_DESC;
break;
@@ -773,6 +777,15 @@ e1000_init_hw(struct e1000_hw *hw)
*/
e1000_clear_hw_cntrs(hw);
+ if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
+ hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Relaxed ordering must be disabled to avoid a parity
+ * error crash in a PCI slot. */
+ ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ }
+
return ret_val;
}
@@ -836,6 +849,11 @@ e1000_setup_link(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_link");
+ /* In the case of the phy reset being blocked, we already have a link.
+ * We do not have to set it up again. */
+ if (e1000_check_phy_reset_block(hw))
+ return E1000_SUCCESS;
+
/* Read and store word 0x0F of the EEPROM. This word contains bits
* that determine the hardware's default PAUSE (flow control) mode,
* a bit that determines whether the HW defaults to enabling or
@@ -844,19 +862,27 @@ e1000_setup_link(struct e1000_hw *hw)
* control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM.
*/
- if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
- DEBUGOUT("EEPROM Read Error\n");
- return -E1000_ERR_EEPROM;
- }
-
- if(hw->fc == e1000_fc_default) {
- if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
- hw->fc = e1000_fc_none;
- else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
- EEPROM_WORD0F_ASM_DIR)
- hw->fc = e1000_fc_tx_pause;
- else
+ if (hw->fc == e1000_fc_default) {
+ switch (hw->mac_type) {
+ case e1000_82573:
hw->fc = e1000_fc_full;
+ break;
+ default:
+ ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+ 1, &eeprom_data);
+ if (ret_val) {
+ DEBUGOUT("EEPROM Read Error\n");
+ return -E1000_ERR_EEPROM;
+ }
+ if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
+ hw->fc = e1000_fc_none;
+ else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
+ EEPROM_WORD0F_ASM_DIR)
+ hw->fc = e1000_fc_tx_pause;
+ else
+ hw->fc = e1000_fc_full;
+ break;
+ }
}
/* We want to save off the original Flow Control configuration just
@@ -1574,10 +1600,10 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if(ret_val)
+ return ret_val;
/* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
@@ -1919,14 +1945,19 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw)
void
e1000_config_collision_dist(struct e1000_hw *hw)
{
- uint32_t tctl;
+ uint32_t tctl, coll_dist;
DEBUGFUNC("e1000_config_collision_dist");
+ if (hw->mac_type < e1000_82543)
+ coll_dist = E1000_COLLISION_DISTANCE_82542;
+ else
+ coll_dist = E1000_COLLISION_DISTANCE;
+
tctl = E1000_READ_REG(hw, TCTL);
tctl &= ~E1000_TCTL_COLD;
- tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+ tctl |= coll_dist << E1000_COLD_SHIFT;
E1000_WRITE_REG(hw, TCTL, tctl);
E1000_WRITE_FLUSH(hw);
@@ -2962,13 +2993,24 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
if(hw->mac_type > e1000_82543) {
/* Read the device control register and assert the E1000_CTRL_PHY_RST
* bit. Then, take it out of reset.
+ * For pre-e1000_82571 hardware, we delay for 10ms between the assert
+ * and deassert. For e1000_82571 hardware and later, we instead delay
+ * for 10ms after the deassertion.
*/
ctrl = E1000_READ_REG(hw, CTRL);
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
E1000_WRITE_FLUSH(hw);
- msec_delay(10);
+
+ if (hw->mac_type < e1000_82571)
+ msec_delay(10);
+ else
+ udelay(100);
+
E1000_WRITE_REG(hw, CTRL, ctrl);
E1000_WRITE_FLUSH(hw);
+
+ if (hw->mac_type >= e1000_82571)
+ msec_delay(10);
} else {
/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
* bit to put the PHY into reset. Then, take it out of reset.
@@ -3862,17 +3904,19 @@ e1000_read_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* FLASH reads without acquiring the semaphore are safe in 82573-based
- * controllers.
- */
- if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
- (hw->mac_type != e1000_82573)) {
- /* Prepare the EEPROM for reading */
- if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe */
+ if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
+ hw->eeprom.use_eerd == FALSE) {
+ switch (hw->mac_type) {
+ default:
+ /* Prepare the EEPROM for reading */
+ if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ break;
+ }
}
- if(eeprom->use_eerd == TRUE) {
+ if (eeprom->use_eerd == TRUE) {
ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
(hw->mac_type != e1000_82573))
@@ -4379,7 +4423,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
}
- /* If STM opcode located in bits 15:8 of flop, reset firmware */
+ /* If STM opcode located in bits 15:8 of flop, reset firmware */
if ((flop & 0xFF00) == E1000_STM_OPCODE) {
E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
}
@@ -4387,7 +4431,7 @@ e1000_commit_shadow_ram(struct e1000_hw *hw)
/* Perform the flash update */
E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
- for (i=0; i < attempts; i++) {
+ for (i=0; i < attempts; i++) {
eecd = E1000_READ_REG(hw, EECD);
if ((eecd & E1000_EECD_FLUPD) == 0) {
break;
@@ -4460,6 +4504,7 @@ e1000_read_mac_addr(struct e1000_hw * hw)
hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF);
hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8);
}
+
switch (hw->mac_type) {
default:
break;
@@ -5278,11 +5323,15 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
- case e1000_82571:
case e1000_82572:
case e1000_82573:
hw->bus_type = e1000_bus_type_pci_express;
hw->bus_speed = e1000_bus_speed_2500;
+ hw->bus_width = e1000_bus_width_pciex_1;
+ break;
+ case e1000_82571:
+ hw->bus_type = e1000_bus_type_pci_express;
+ hw->bus_speed = e1000_bus_speed_2500;
hw->bus_width = e1000_bus_width_pciex_4;
break;
default:
@@ -6650,6 +6699,12 @@ e1000_get_auto_rd_done(struct e1000_hw *hw)
break;
}
+ /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+ * Need to wait for PHY configuration completion before accessing NVM
+ * and PHY. */
+ if (hw->mac_type == e1000_82573)
+ msec_delay(25);
+
return E1000_SUCCESS;
}
@@ -6691,6 +6746,12 @@ e1000_get_phy_cfg_done(struct e1000_hw *hw)
break;
}
+ /* PHY configuration from NVM just starts after EECD_AUTO_RD sets to high.
+ * Need to wait for PHY configuration completion before accessing NVM
+ * and PHY. */
+ if (hw->mac_type == e1000_82573)
+ msec_delay(25);
+
return E1000_SUCCESS;
}
@@ -6780,7 +6841,8 @@ int32_t
e1000_check_phy_reset_block(struct e1000_hw *hw)
{
uint32_t manc = 0;
- if(hw->mac_type > e1000_82547_rev_2)
+
+ if (hw->mac_type > e1000_82547_rev_2)
manc = E1000_READ_REG(hw, MANC);
return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
E1000_BLK_PHY_RESET : E1000_SUCCESS;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 76ce12809a11..f1219dd9dbac 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -123,6 +123,7 @@ typedef enum {
e1000_bus_width_32,
e1000_bus_width_64,
e1000_bus_width_pciex_1,
+ e1000_bus_width_pciex_2,
e1000_bus_width_pciex_4,
e1000_bus_width_reserved
} e1000_bus_width;
@@ -149,6 +150,7 @@ typedef enum {
e1000_igp_cable_length_90 = 90,
e1000_igp_cable_length_100 = 100,
e1000_igp_cable_length_110 = 110,
+ e1000_igp_cable_length_115 = 115,
e1000_igp_cable_length_120 = 120,
e1000_igp_cable_length_130 = 130,
e1000_igp_cable_length_140 = 140,
@@ -375,6 +377,7 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
+void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -399,7 +402,9 @@ void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
/* Port I/O is only supported on 82544 and newer */
uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
+uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
void e1000_release_software_semaphore(struct e1000_hw *hw);
@@ -437,6 +442,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82546GB_FIBER 0x107A
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define E1000_DEV_ID_82547EI 0x1019
#define E1000_DEV_ID_82571EB_COPPER 0x105E
#define E1000_DEV_ID_82571EB_FIBER 0x105F
@@ -447,6 +453,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#define E1000_DEV_ID_82573E 0x108B
#define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
#define NODE_ADDRESS_SIZE 6
@@ -895,14 +902,14 @@ struct e1000_ffvt_entry {
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
-#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
-#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
-#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
-#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
-#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
-#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
-#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
-#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
@@ -1457,6 +1464,7 @@ struct e1000_hw {
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_EECD_SECVAL_SHIFT 22
#define E1000_STM_OPCODE 0xDB00
#define E1000_HICR_FW_RESET 0xC0
@@ -1494,6 +1502,7 @@ struct e1000_hw {
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
+#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
@@ -1755,7 +1764,6 @@ struct e1000_hw {
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
still to be processed. */
-
/* Transmit Configuration Word */
#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */
@@ -1951,7 +1959,23 @@ struct e1000_host_command_info {
#define E1000_MDALIGN 4096
-#define E1000_GCR_BEM32 0x00400000
+/* PCI-Ex registers */
+
+/* PCI-Ex Control Register */
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+
+#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000
/* Function Active and Power State to MNG */
#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
@@ -2075,7 +2099,10 @@ struct e1000_host_command_info {
/* Collision related configuration parameters */
#define E1000_COLLISION_THRESHOLD 15
#define E1000_CT_SHIFT 4
-#define E1000_COLLISION_DISTANCE 64
+/* Collision distance is a 0-based value that applies to
+ * half-duplex-capable hardware only. */
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLLISION_DISTANCE_82542 64
#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE
#define E1000_COLD_SHIFT 12
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index e0ae248b4313..31e332935e5a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -29,11 +29,71 @@
#include "e1000.h"
/* Change Log
- * 6.0.58 4/20/05
- * o Accepted ethtool cleanup patch from Stephen Hemminger
- * 6.0.44+ 2/15/05
- * o applied Anton's patch to resolve tx hang in hardware
- * o Applied Andrew Mortons patch - e1000 stops working after resume
+ * 6.3.9 12/16/2005
+ * o incorporate fix for recycled skbs from IBM LTC
+ * 6.3.7 11/18/2005
+ * o Honor eeprom setting for enabling/disabling Wake On Lan
+ * 6.3.5 11/17/2005
+ * o Fix memory leak in rx ring handling for PCI Express adapters
+ * 6.3.4 11/8/05
+ * o Patch from Jesper Juhl to remove redundant NULL checks for kfree
+ * 6.3.2 9/20/05
+ * o Render logic that sets/resets DRV_LOAD as inline functions to
+ * avoid code replication. If f/w is AMT then set DRV_LOAD only when
+ * network interface is open.
+ * o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
+ * o Adjust PBA partioning for Jumbo frames using MTU size and not
+ * rx_buffer_len
+ * 6.3.1 9/19/05
+ * o Use adapter->tx_timeout_factor in Tx Hung Detect logic
+ (e1000_clean_tx_irq)
+ * o Support for 8086:10B5 device (Quad Port)
+ * 6.2.14 9/15/05
+ * o In AMT enabled configurations, set/reset DRV_LOAD bit on interface
+ * open/close
+ * 6.2.13 9/14/05
+ * o Invoke e1000_check_mng_mode only for 8257x controllers since it
+ * accesses the FWSM that is not supported in other controllers
+ * 6.2.12 9/9/05
+ * o Add support for device id E1000_DEV_ID_82546GB_QUAD_COPPER
+ * o set RCTL:SECRC only for controllers newer than 82543.
+ * o When the n/w interface comes down reset DRV_LOAD bit to notify f/w.
+ * This code was moved from e1000_remove to e1000_close
+ * 6.2.10 9/6/05
+ * o Fix error in updating RDT in el1000_alloc_rx_buffers[_ps] -- one off.
+ * o Enable fc by default on 82573 controllers (do not read eeprom)
+ * o Fix rx_errors statistic not to include missed_packet_count
+ * o Fix rx_dropped statistic not to include missed_packet_count
+ (Padraig Brady)
+ * 6.2.9 8/30/05
+ * o Remove call to update statistics from the controller ib e1000_get_stats
+ * 6.2.8 8/30/05
+ * o Improved algorithm for rx buffer allocation/rdt update
+ * o Flow control watermarks relative to rx PBA size
+ * o Simplified 'Tx Hung' detect logic
+ * 6.2.7 8/17/05
+ * o Report rx buffer allocation failures and tx timeout counts in stats
+ * 6.2.6 8/16/05
+ * o Implement workaround for controller erratum -- linear non-tso packet
+ * following a TSO gets written back prematurely
+ * 6.2.5 8/15/05
+ * o Set netdev->tx_queue_len based on link speed/duplex settings.
+ * o Fix net_stats.rx_fifo_errors <p@draigBrady.com>
+ * o Do not power off PHY if SoL/IDER session is active
+ * 6.2.4 8/10/05
+ * o Fix loopback test setup/cleanup for 82571/3 controllers
+ * o Fix parsing of outgoing packets (e1000_transfer_dhcp_info) to treat
+ * all packets as raw
+ * o Prevent operations that will cause the PHY to be reset if SoL/IDER
+ * sessions are active and log a message
+ * 6.2.2 7/21/05
+ * o used fixed size descriptors for all MTU sizes, reduces memory load
+ * 6.1.2 4/13/05
+ * o Fixed ethtool diagnostics
+ * o Enabled flow control to take default eeprom settings
+ * o Added stats_lock around e1000_read_phy_reg commands to avoid concurrent
+ * calls, one from mii_ioctl and other from within update_stats while
+ * processing MIIREG ioctl.
*/
char e1000_driver_name[] = "e1000";
@@ -43,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "6.1.16-k2"DRIVERNAPI
+#define DRV_VERSION "6.3.9-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -97,7 +157,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x108A),
INTEL_E1000_ETHERNET_DEVICE(0x108B),
INTEL_E1000_ETHERNET_DEVICE(0x108C),
+ INTEL_E1000_ETHERNET_DEVICE(0x1099),
INTEL_E1000_ETHERNET_DEVICE(0x109A),
+ INTEL_E1000_ETHERNET_DEVICE(0x10B5),
/* required last entry */
{0,}
};
@@ -171,9 +233,11 @@ static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring);
#endif
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring);
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -291,7 +355,7 @@ e1000_irq_disable(struct e1000_adapter *adapter)
static inline void
e1000_irq_enable(struct e1000_adapter *adapter)
{
- if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
E1000_WRITE_FLUSH(&adapter->hw);
}
@@ -303,23 +367,91 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter)
struct net_device *netdev = adapter->netdev;
uint16_t vid = adapter->hw.mng_cookie.vlan_id;
uint16_t old_vid = adapter->mng_vlan_id;
- if(adapter->vlgrp) {
- if(!adapter->vlgrp->vlan_devices[vid]) {
- if(adapter->hw.mng_cookie.status &
+ if (adapter->vlgrp) {
+ if (!adapter->vlgrp->vlan_devices[vid]) {
+ if (adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
e1000_vlan_rx_add_vid(netdev, vid);
adapter->mng_vlan_id = vid;
} else
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
-
- if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
- (vid != old_vid) &&
+
+ if ((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
!adapter->vlgrp->vlan_devices[old_vid])
e1000_vlan_rx_kill_vid(netdev, old_vid);
}
}
}
-
+
+/**
+ * e1000_release_hw_control - release control of the h/w to f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that the
+ * driver is no longer loaded. For AMT version (only with 82573) i
+ * of the f/w this means that the netowrk i/f is closed.
+ *
+ **/
+
+static inline void
+e1000_release_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+
+ /* Let firmware taken over control of h/w */
+ switch (adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
+ break;
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ default:
+ break;
+ }
+}
+
+/**
+ * e1000_get_hw_control - get control of the h/w from f/w
+ * @adapter: address of board private structure
+ *
+ * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
+ * of the f/w this means that the netowrk i/f is open.
+ *
+ **/
+
+static inline void
+e1000_get_hw_control(struct e1000_adapter *adapter)
+{
+ uint32_t ctrl_ext;
+ uint32_t swsm;
+ /* Let firmware know the driver has taken over */
+ switch (adapter->hw.mac_type) {
+ case e1000_82571:
+ case e1000_82572:
+ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
+ E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+ break;
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
@@ -329,10 +461,10 @@ e1000_up(struct e1000_adapter *adapter)
/* hardware has been reset, we need to reload some things */
/* Reset the PHY if it was previously powered down */
- if(adapter->hw.media_type == e1000_media_type_copper) {
+ if (adapter->hw.media_type == e1000_media_type_copper) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
e1000_phy_reset(&adapter->hw);
}
@@ -343,20 +475,26 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- for (i = 0; i < adapter->num_queues; i++)
- adapter->alloc_rx_buf(adapter, &adapter->rx_ring[i]);
+ /* call E1000_DESC_UNUSED which always leaves
+ * at least 1 descriptor unused to make sure
+ * next_to_use != next_to_clean */
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ struct e1000_rx_ring *ring = &adapter->rx_ring[i];
+ adapter->alloc_rx_buf(adapter, ring,
+ E1000_DESC_UNUSED(ring));
+ }
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
adapter->have_msi = TRUE;
- if((err = pci_enable_msi(adapter->pdev))) {
+ if ((err = pci_enable_msi(adapter->pdev))) {
DPRINTK(PROBE, ERR,
"Unable to allocate MSI interrupt Error: %d\n", err);
adapter->have_msi = FALSE;
}
}
#endif
- if((err = request_irq(adapter->pdev->irq, &e1000_intr,
+ if ((err = request_irq(adapter->pdev->irq, &e1000_intr,
SA_SHIRQ | SA_SAMPLE_RANDOM,
netdev->name, netdev))) {
DPRINTK(PROBE, ERR,
@@ -364,6 +502,12 @@ e1000_up(struct e1000_adapter *adapter)
return err;
}
+#ifdef CONFIG_E1000_MQ
+ e1000_setup_queue_mapping(adapter);
+#endif
+
+ adapter->tx_queue_len = netdev->tx_queue_len;
+
mod_timer(&adapter->watchdog_timer, jiffies);
#ifdef CONFIG_E1000_NAPI
@@ -378,6 +522,8 @@ void
e1000_down(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
+ boolean_t mng_mode_enabled = (adapter->hw.mac_type >= e1000_82571) &&
+ e1000_check_mng_mode(&adapter->hw);
e1000_irq_disable(adapter);
#ifdef CONFIG_E1000_MQ
@@ -385,7 +531,7 @@ e1000_down(struct e1000_adapter *adapter)
#endif
free_irq(adapter->pdev->irq, netdev);
#ifdef CONFIG_PCI_MSI
- if(adapter->hw.mac_type > e1000_82547_rev_2 &&
+ if (adapter->hw.mac_type > e1000_82547_rev_2 &&
adapter->have_msi == TRUE)
pci_disable_msi(adapter->pdev);
#endif
@@ -396,6 +542,7 @@ e1000_down(struct e1000_adapter *adapter)
#ifdef CONFIG_E1000_NAPI
netif_poll_disable(netdev);
#endif
+ netdev->tx_queue_len = adapter->tx_queue_len;
adapter->link_speed = 0;
adapter->link_duplex = 0;
netif_carrier_off(netdev);
@@ -405,12 +552,16 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_all_tx_rings(adapter);
e1000_clean_all_rx_rings(adapter);
- /* If WoL is not enabled and management mode is not IAMT
- * Power down the PHY so no link is implied when interface is down */
- if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ /* Power down the PHY so no link is implied when interface is down *
+ * The PHY cannot be powered down if any of the following is TRUE *
+ * (a) WoL is enabled
+ * (b) AMT is active
+ * (c) SoL/IDER session is active */
+ if (!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper &&
- !e1000_check_mng_mode(&adapter->hw) &&
- !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN) &&
+ !mng_mode_enabled &&
+ !e1000_check_phy_reset_block(&adapter->hw)) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
@@ -422,10 +573,8 @@ e1000_down(struct e1000_adapter *adapter)
void
e1000_reset(struct e1000_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
uint32_t pba, manc;
uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
- uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
@@ -448,19 +597,12 @@ e1000_reset(struct e1000_adapter *adapter)
break;
}
- if((adapter->hw.mac_type != e1000_82573) &&
- (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+ if ((adapter->hw.mac_type != e1000_82573) &&
+ (adapter->netdev->mtu > E1000_RXBUFFER_8192))
pba -= 8; /* allocate more FIFO for Tx */
- /* send an XOFF when there is enough space in the
- * Rx FIFO to hold one extra full size Rx packet
- */
- fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE +
- ETHERNET_FCS_SIZE + 1;
- fc_low_water_mark = fc_high_water_mark + 8;
- }
- if(adapter->hw.mac_type == e1000_82547) {
+ if (adapter->hw.mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
@@ -471,19 +613,21 @@ e1000_reset(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* flow control settings */
- adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_high_water_mark;
- adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
- fc_low_water_mark;
+ /* Set the FC high water mark to 90% of the FIFO size.
+ * Required to clear last 3 LSB */
+ fc_high_water_mark = ((pba * 9216)/10) & 0xFFF8;
+
+ adapter->hw.fc_high_water = fc_high_water_mark;
+ adapter->hw.fc_low_water = fc_high_water_mark - 8;
adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
adapter->hw.fc_send_xon = 1;
adapter->hw.fc = adapter->hw.original_fc;
/* Allow time for pending master requests to run */
e1000_reset_hw(&adapter->hw);
- if(adapter->hw.mac_type >= e1000_82544)
+ if (adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
- if(e1000_init_hw(&adapter->hw))
+ if (e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
e1000_update_mng_vlan(adapter);
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@ -517,33 +661,31 @@ e1000_probe(struct pci_dev *pdev,
struct net_device *netdev;
struct e1000_adapter *adapter;
unsigned long mmio_start, mmio_len;
- uint32_t ctrl_ext;
- uint32_t swsm;
static int cards_found = 0;
int i, err, pci_using_dac;
uint16_t eeprom_data;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
- if((err = pci_enable_device(pdev)))
+ if ((err = pci_enable_device(pdev)))
return err;
- if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
pci_using_dac = 1;
} else {
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
E1000_ERR("No usable DMA configuration, aborting\n");
return err;
}
pci_using_dac = 0;
}
- if((err = pci_request_regions(pdev, e1000_driver_name)))
+ if ((err = pci_request_regions(pdev, e1000_driver_name)))
return err;
pci_set_master(pdev);
netdev = alloc_etherdev(sizeof(struct e1000_adapter));
- if(!netdev) {
+ if (!netdev) {
err = -ENOMEM;
goto err_alloc_etherdev;
}
@@ -562,15 +704,15 @@ e1000_probe(struct pci_dev *pdev,
mmio_len = pci_resource_len(pdev, BAR_0);
adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
- if(!adapter->hw.hw_addr) {
+ if (!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
}
- for(i = BAR_1; i <= BAR_5; i++) {
- if(pci_resource_len(pdev, i) == 0)
+ for (i = BAR_1; i <= BAR_5; i++) {
+ if (pci_resource_len(pdev, i) == 0)
continue;
- if(pci_resource_flags(pdev, i) & IORESOURCE_IO) {
+ if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
adapter->hw.io_base = pci_resource_start(pdev, i);
break;
}
@@ -607,13 +749,13 @@ e1000_probe(struct pci_dev *pdev,
/* setup the private structure */
- if((err = e1000_sw_init(adapter)))
+ if ((err = e1000_sw_init(adapter)))
goto err_sw_init;
- if((err = e1000_check_phy_reset_block(&adapter->hw)))
+ if ((err = e1000_check_phy_reset_block(&adapter->hw)))
DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
- if(adapter->hw.mac_type >= e1000_82543) {
+ if (adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
NETIF_F_HW_VLAN_TX |
@@ -622,16 +764,16 @@ e1000_probe(struct pci_dev *pdev,
}
#ifdef NETIF_F_TSO
- if((adapter->hw.mac_type >= e1000_82544) &&
+ if ((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
#ifdef NETIF_F_TSO_IPV6
- if(adapter->hw.mac_type > e1000_82547_rev_2)
+ if (adapter->hw.mac_type > e1000_82547_rev_2)
netdev->features |= NETIF_F_TSO_IPV6;
#endif
#endif
- if(pci_using_dac)
+ if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
/* hard_start_xmit is safe against parallel locking */
@@ -639,14 +781,14 @@ e1000_probe(struct pci_dev *pdev,
adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
- /* before reading the EEPROM, reset the controller to
+ /* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
-
+
e1000_reset_hw(&adapter->hw);
/* make sure the EEPROM is good */
- if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
+ if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
err = -EIO;
goto err_eeprom;
@@ -654,12 +796,12 @@ e1000_probe(struct pci_dev *pdev,
/* copy the MAC address out of the EEPROM */
- if(e1000_read_mac_addr(&adapter->hw))
+ if (e1000_read_mac_addr(&adapter->hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
- if(!is_valid_ether_addr(netdev->perm_addr)) {
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
@@ -699,7 +841,7 @@ e1000_probe(struct pci_dev *pdev,
* enable the ACPI Magic Packet filter
*/
- switch(adapter->hw.mac_type) {
+ switch (adapter->hw.mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
case e1000_82543:
@@ -711,8 +853,8 @@ e1000_probe(struct pci_dev *pdev,
break;
case e1000_82546:
case e1000_82546_rev_3:
- if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
- && (adapter->hw.media_type == e1000_media_type_copper)) {
+ case e1000_82571:
+ if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1){
e1000_read_eeprom(&adapter->hw,
EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
break;
@@ -723,31 +865,42 @@ e1000_probe(struct pci_dev *pdev,
EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
break;
}
- if(eeprom_data & eeprom_apme_mask)
+ if (eeprom_data & eeprom_apme_mask)
adapter->wol |= E1000_WUFC_MAG;
+ /* print bus type/speed/width info */
+ {
+ struct e1000_hw *hw = &adapter->hw;
+ DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ",
+ ((hw->bus_type == e1000_bus_type_pcix) ? "-X" :
+ (hw->bus_type == e1000_bus_type_pci_express ? " Express":"")),
+ ((hw->bus_speed == e1000_bus_speed_2500) ? "2.5Gb/s" :
+ (hw->bus_speed == e1000_bus_speed_133) ? "133MHz" :
+ (hw->bus_speed == e1000_bus_speed_120) ? "120MHz" :
+ (hw->bus_speed == e1000_bus_speed_100) ? "100MHz" :
+ (hw->bus_speed == e1000_bus_speed_66) ? "66MHz" : "33MHz"),
+ ((hw->bus_width == e1000_bus_width_64) ? "64-bit" :
+ (hw->bus_width == e1000_bus_width_pciex_4) ? "Width x4" :
+ (hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
+ "32-bit"));
+ }
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", netdev->dev_addr[i], i == 5 ? '\n' : ':');
+
/* reset the hardware with the new settings */
e1000_reset(adapter);
- /* Let firmware know the driver has taken over */
- switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
- case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
strcpy(netdev->name, "eth%d");
- if((err = register_netdev(netdev)))
+ if ((err = register_netdev(netdev)))
goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -781,47 +934,33 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t ctrl_ext;
- uint32_t manc, swsm;
+ uint32_t manc;
#ifdef CONFIG_E1000_NAPI
int i;
#endif
flush_scheduled_work();
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
}
- switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
- case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
-
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
unregister_netdev(netdev);
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
__dev_put(&adapter->polling_netdev[i]);
#endif
- if(!e1000_check_phy_reset_block(&adapter->hw))
+ if (!e1000_check_phy_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
kfree(adapter->tx_ring);
@@ -880,19 +1019,19 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* identify the MAC */
- if(e1000_set_mac_type(hw)) {
+ if (e1000_set_mac_type(hw)) {
DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
return -EIO;
}
/* initialize eeprom parameters */
- if(e1000_init_eeprom_params(hw)) {
+ if (e1000_init_eeprom_params(hw)) {
E1000_ERR("EEPROM initialization failed\n");
return -EIO;
}
- switch(hw->mac_type) {
+ switch (hw->mac_type) {
default:
break;
case e1000_82541:
@@ -911,7 +1050,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* Copper options */
- if(hw->media_type == e1000_media_type_copper) {
+ if (hw->media_type == e1000_media_type_copper) {
hw->mdix = AUTO_ALL_MODES;
hw->disable_polarity_correction = FALSE;
hw->master_slave = E1000_MASTER_SLAVE;
@@ -922,15 +1061,34 @@ e1000_sw_init(struct e1000_adapter *adapter)
switch (hw->mac_type) {
case e1000_82571:
case e1000_82572:
- adapter->num_queues = 2;
+ /* These controllers support 2 tx queues, but with a single
+ * qdisc implementation, multiple tx queues aren't quite as
+ * interesting. If we can find a logical way of mapping
+ * flows to a queue, then perhaps we can up the num_tx_queue
+ * count back to its default. Until then, we run the risk of
+ * terrible performance due to SACK overload. */
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 2;
break;
default:
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
break;
}
- adapter->num_queues = min(adapter->num_queues, num_online_cpus());
+ adapter->num_rx_queues = min(adapter->num_rx_queues, num_online_cpus());
+ adapter->num_tx_queues = min(adapter->num_tx_queues, num_online_cpus());
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Rx Queue count = %u %s\n",
+ adapter->num_rx_queues,
+ ((adapter->num_rx_queues == 1)
+ ? ((num_online_cpus() > 1)
+ ? "(due to unsupported feature in current adapter)"
+ : "(due to unsupported system configuration)")
+ : ""));
+ DPRINTK(DRV, INFO, "Multiqueue Enabled: Tx Queue count = %u\n",
+ adapter->num_tx_queues);
#else
- adapter->num_queues = 1;
+ adapter->num_tx_queues = 1;
+ adapter->num_rx_queues = 1;
#endif
if (e1000_alloc_queues(adapter)) {
@@ -939,17 +1097,14 @@ e1000_sw_init(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_NAPI
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
adapter->polling_netdev[i].priv = adapter;
adapter->polling_netdev[i].poll = &e1000_clean;
adapter->polling_netdev[i].weight = 64;
dev_hold(&adapter->polling_netdev[i]);
set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
}
-#endif
-
-#ifdef CONFIG_E1000_MQ
- e1000_setup_queue_mapping(adapter);
+ spin_lock_init(&adapter->tx_queue_lock);
#endif
atomic_set(&adapter->irq_sem, 1);
@@ -972,13 +1127,13 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
{
int size;
- size = sizeof(struct e1000_tx_ring) * adapter->num_queues;
+ size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
adapter->tx_ring = kmalloc(size, GFP_KERNEL);
if (!adapter->tx_ring)
return -ENOMEM;
memset(adapter->tx_ring, 0, size);
- size = sizeof(struct e1000_rx_ring) * adapter->num_queues;
+ size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
adapter->rx_ring = kmalloc(size, GFP_KERNEL);
if (!adapter->rx_ring) {
kfree(adapter->tx_ring);
@@ -987,7 +1142,7 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->rx_ring, 0, size);
#ifdef CONFIG_E1000_NAPI
- size = sizeof(struct net_device) * adapter->num_queues;
+ size = sizeof(struct net_device) * adapter->num_rx_queues;
adapter->polling_netdev = kmalloc(size, GFP_KERNEL);
if (!adapter->polling_netdev) {
kfree(adapter->tx_ring);
@@ -997,6 +1152,14 @@ e1000_alloc_queues(struct e1000_adapter *adapter)
memset(adapter->polling_netdev, 0, size);
#endif
+#ifdef CONFIG_E1000_MQ
+ adapter->rx_sched_call_data.func = e1000_rx_schedule;
+ adapter->rx_sched_call_data.info = adapter->netdev;
+
+ adapter->cpu_netdev = alloc_percpu(struct net_device *);
+ adapter->cpu_tx_ring = alloc_percpu(struct e1000_tx_ring *);
+#endif
+
return E1000_SUCCESS;
}
@@ -1016,14 +1179,15 @@ e1000_setup_queue_mapping(struct e1000_adapter *adapter)
lock_cpu_hotplug();
i = 0;
for_each_online_cpu(cpu) {
- *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_queues];
+ *per_cpu_ptr(adapter->cpu_tx_ring, cpu) = &adapter->tx_ring[i % adapter->num_tx_queues];
/* This is incomplete because we'd like to assign separate
* physical cpus to these netdev polling structures and
* avoid saturating a subset of cpus.
*/
- if (i < adapter->num_queues) {
+ if (i < adapter->num_rx_queues) {
*per_cpu_ptr(adapter->cpu_netdev, cpu) = &adapter->polling_netdev[i];
- adapter->cpu_for_queue[i] = cpu;
+ adapter->rx_ring[i].cpu = cpu;
+ cpu_set(cpu, adapter->cpumask);
} else
*per_cpu_ptr(adapter->cpu_netdev, cpu) = NULL;
@@ -1062,14 +1226,20 @@ e1000_open(struct net_device *netdev)
if ((err = e1000_setup_all_rx_resources(adapter)))
goto err_setup_rx;
- if((err = e1000_up(adapter)))
+ if ((err = e1000_up(adapter)))
goto err_up;
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_update_mng_vlan(adapter);
}
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now open */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
+
return E1000_SUCCESS;
err_up:
@@ -1104,10 +1274,17 @@ e1000_close(struct net_device *netdev)
e1000_free_all_tx_resources(adapter);
e1000_free_all_rx_resources(adapter);
- if((adapter->hw.mng_cookie.status &
+ if ((adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
}
+
+ /* If AMT is enabled, let the firmware know that the network
+ * interface is now closed */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ e1000_check_mng_mode(&adapter->hw))
+ e1000_release_hw_control(adapter);
+
return 0;
}
@@ -1152,13 +1329,12 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_buffer) * txdr->count;
txdr->buffer_info = vmalloc_node(size, pcibus_to_node(pdev->bus));
- if(!txdr->buffer_info) {
+ if (!txdr->buffer_info) {
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
- memset(&txdr->previous_buffer_info, 0, sizeof(struct e1000_buffer));
/* round up to nearest 4K */
@@ -1166,7 +1342,7 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter,
E1000_ROUNDUP(txdr->size, 4096);
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
+ if (!txdr->desc) {
setup_tx_desc_die:
vfree(txdr->buffer_info);
DPRINTK(PROBE, ERR,
@@ -1182,8 +1358,8 @@ setup_tx_desc_die:
"at %p\n", txdr->size, txdr->desc);
/* Try again, without freeing the previous */
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- if(!txdr->desc) {
/* Failed allocation, critical failure */
+ if (!txdr->desc) {
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
goto setup_tx_desc_die;
}
@@ -1229,7 +1405,7 @@ e1000_setup_all_tx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_tx_queues; i++) {
err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1254,10 +1430,11 @@ e1000_configure_tx(struct e1000_adapter *adapter)
uint64_t tdba;
struct e1000_hw *hw = &adapter->hw;
uint32_t tdlen, tctl, tipg, tarc;
+ uint32_t ipgr1, ipgr2;
/* Setup the HW Tx Head and Tail descriptor pointers */
- switch (adapter->num_queues) {
+ switch (adapter->num_tx_queues) {
case 2:
tdba = adapter->tx_ring[1].dma;
tdlen = adapter->tx_ring[1].count *
@@ -1287,22 +1464,26 @@ e1000_configure_tx(struct e1000_adapter *adapter)
/* Set the default values for the Tx Inter Packet Gap timer */
+ if (hw->media_type == e1000_media_type_fiber ||
+ hw->media_type == e1000_media_type_internal_serdes)
+ tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
+ else
+ tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
+
switch (hw->mac_type) {
case e1000_82542_rev2_0:
case e1000_82542_rev2_1:
tipg = DEFAULT_82542_TIPG_IPGT;
- tipg |= DEFAULT_82542_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+ ipgr1 = DEFAULT_82542_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82542_TIPG_IPGR2;
break;
default:
- if (hw->media_type == e1000_media_type_fiber ||
- hw->media_type == e1000_media_type_internal_serdes)
- tipg = DEFAULT_82543_TIPG_IPGT_FIBER;
- else
- tipg = DEFAULT_82543_TIPG_IPGT_COPPER;
- tipg |= DEFAULT_82543_TIPG_IPGR1 << E1000_TIPG_IPGR1_SHIFT;
- tipg |= DEFAULT_82543_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT;
+ ipgr1 = DEFAULT_82543_TIPG_IPGR1;
+ ipgr2 = DEFAULT_82543_TIPG_IPGR2;
+ break;
}
+ tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
+ tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
E1000_WRITE_REG(hw, TIPG, tipg);
/* Set the Tx Interrupt Delay register */
@@ -1378,7 +1559,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page) * rxdr->count;
rxdr->ps_page = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page) {
+ if (!rxdr->ps_page) {
vfree(rxdr->buffer_info);
DPRINTK(PROBE, ERR,
"Unable to allocate memory for the receive descriptor ring\n");
@@ -1388,7 +1569,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
- if(!rxdr->ps_page_dma) {
+ if (!rxdr->ps_page_dma) {
vfree(rxdr->buffer_info);
kfree(rxdr->ps_page);
DPRINTK(PROBE, ERR,
@@ -1397,7 +1578,7 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter,
}
memset(rxdr->ps_page_dma, 0, size);
- if(adapter->hw.mac_type <= e1000_82547_rev_2)
+ if (adapter->hw.mac_type <= e1000_82547_rev_2)
desc_len = sizeof(struct e1000_rx_desc);
else
desc_len = sizeof(union e1000_rx_desc_packet_split);
@@ -1454,6 +1635,8 @@ setup_rx_desc_die:
rxdr->next_to_clean = 0;
rxdr->next_to_use = 0;
+ rxdr->rx_skb_top = NULL;
+ rxdr->rx_skb_prev = NULL;
return 0;
}
@@ -1475,7 +1658,7 @@ e1000_setup_all_rx_resources(struct e1000_adapter *adapter)
{
int i, err = 0;
- for (i = 0; i < adapter->num_queues; i++) {
+ for (i = 0; i < adapter->num_rx_queues; i++) {
err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]);
if (err) {
DPRINTK(PROBE, ERR,
@@ -1498,7 +1681,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
{
uint32_t rctl, rfctl;
uint32_t psrctl = 0;
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
uint32_t pages = 0;
#endif
@@ -1510,7 +1693,10 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT);
- if(adapter->hw.tbi_compatibility_on == 1)
+ if (adapter->hw.mac_type > e1000_82543)
+ rctl |= E1000_RCTL_SECRC;
+
+ if (adapter->hw.tbi_compatibility_on == 1)
rctl |= E1000_RCTL_SBP;
else
rctl &= ~E1000_RCTL_SBP;
@@ -1521,32 +1707,17 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
- if(adapter->hw.mac_type >= e1000_82571) {
+ if (adapter->hw.mac_type >= e1000_82571) {
/* We can now specify buffers in 1K increments.
* BSIZE and BSEX are ignored in this case. */
rctl |= adapter->rx_buffer_len << 0x11;
} else {
rctl &= ~E1000_RCTL_SZ_4096;
- rctl |= E1000_RCTL_BSEX;
- switch (adapter->rx_buffer_len) {
- case E1000_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case E1000_RXBUFFER_4096:
- rctl |= E1000_RCTL_SZ_4096;
- break;
- case E1000_RXBUFFER_8192:
- rctl |= E1000_RCTL_SZ_8192;
- break;
- case E1000_RXBUFFER_16384:
- rctl |= E1000_RCTL_SZ_16384;
- break;
- }
+ rctl &= ~E1000_RCTL_BSEX;
+ rctl |= E1000_RCTL_SZ_2048;
}
-#ifdef CONFIG_E1000_PACKET_SPLIT
+#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
/* 82571 and greater support packet-split where the protocol
* header is placed in skb->data and the packet data is
* placed in pages hanging off of skb_shinfo(skb)->nr_frags.
@@ -1570,7 +1741,7 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
-
+
psrctl |= adapter->rx_ps_bsize0 >>
E1000_PSRCTL_BSIZE0_SHIFT;
@@ -1632,22 +1803,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
if (hw->mac_type >= e1000_82540) {
E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay);
- if(adapter->itr > 1)
+ if (adapter->itr > 1)
E1000_WRITE_REG(hw, ITR,
1000000000 / (adapter->itr * 256));
}
if (hw->mac_type >= e1000_82571) {
- /* Reset delay timers after every interrupt */
ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ /* Reset delay timers after every interrupt */
ctrl_ext |= E1000_CTRL_EXT_CANC;
+#ifdef CONFIG_E1000_NAPI
+ /* Auto-Mask interrupts upon ICR read. */
+ ctrl_ext |= E1000_CTRL_EXT_IAME;
+#endif
E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_REG(hw, IAM, ~0);
E1000_WRITE_FLUSH(hw);
}
/* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring */
- switch (adapter->num_queues) {
+ switch (adapter->num_rx_queues) {
#ifdef CONFIG_E1000_MQ
case 2:
rdba = adapter->rx_ring[1].dma;
@@ -1674,7 +1850,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
}
#ifdef CONFIG_E1000_MQ
- if (adapter->num_queues > 1) {
+ if (adapter->num_rx_queues > 1) {
uint32_t random[10];
get_random_bytes(&random[0], 40);
@@ -1684,7 +1860,7 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(hw, RSSIM, 0);
}
- switch (adapter->num_queues) {
+ switch (adapter->num_rx_queues) {
case 2:
default:
reta = 0x00800080;
@@ -1716,13 +1892,13 @@ e1000_configure_rx(struct e1000_adapter *adapter)
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
if (hw->mac_type >= e1000_82543) {
rxcsum = E1000_READ_REG(hw, RXCSUM);
- if(adapter->rx_csum == TRUE) {
+ if (adapter->rx_csum == TRUE) {
rxcsum |= E1000_RXCSUM_TUOFL;
/* Enable 82571 IPv4 payload checksum for UDP fragments
* Must be used in conjunction with packet-split. */
- if ((hw->mac_type >= e1000_82571) &&
- (adapter->rx_ps_pages)) {
+ if ((hw->mac_type >= e1000_82571) &&
+ (adapter->rx_ps_pages)) {
rxcsum |= E1000_RXCSUM_IPPCSE;
}
} else {
@@ -1776,7 +1952,7 @@ e1000_free_all_tx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
}
@@ -1784,17 +1960,15 @@ static inline void
e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- if(buffer_info->dma) {
+ if (buffer_info->dma) {
pci_unmap_page(adapter->pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_TODEVICE);
- buffer_info->dma = 0;
}
- if(buffer_info->skb) {
+ if (buffer_info->skb)
dev_kfree_skb_any(buffer_info->skb);
- buffer_info->skb = NULL;
- }
+ memset(buffer_info, 0, sizeof(struct e1000_buffer));
}
/**
@@ -1813,12 +1987,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
/* Free all the Tx ring sk_buffs */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
- }
-
- for(i = 0; i < tx_ring->count; i++) {
+ for (i = 0; i < tx_ring->count; i++) {
buffer_info = &tx_ring->buffer_info[i];
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
}
@@ -1832,6 +2001,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter,
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
+ tx_ring->last_tx_tso = 0;
writel(0, adapter->hw.hw_addr + tx_ring->tdh);
writel(0, adapter->hw.hw_addr + tx_ring->tdt);
@@ -1847,7 +2017,7 @@ e1000_clean_all_tx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]);
}
@@ -1891,7 +2061,7 @@ e1000_free_all_rx_resources(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_free_rx_resources(adapter, &adapter->rx_ring[i]);
}
@@ -1913,12 +2083,9 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
unsigned int i, j;
/* Free all the Rx ring sk_buffs */
-
- for(i = 0; i < rx_ring->count; i++) {
+ for (i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
- if(buffer_info->skb) {
- ps_page = &rx_ring->ps_page[i];
- ps_page_dma = &rx_ring->ps_page_dma[i];
+ if (buffer_info->skb) {
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
@@ -1926,19 +2093,30 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter,
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
-
- for(j = 0; j < adapter->rx_ps_pages; j++) {
- if(!ps_page->ps_page[j]) break;
- pci_unmap_single(pdev,
- ps_page_dma->ps_page_dma[j],
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
- ps_page_dma->ps_page_dma[j] = 0;
- put_page(ps_page->ps_page[j]);
- ps_page->ps_page[j] = NULL;
- }
}
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!ps_page->ps_page[j]) break;
+ pci_unmap_page(pdev,
+ ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ put_page(ps_page->ps_page[j]);
+ ps_page->ps_page[j] = NULL;
+ }
+ }
+
+ /* there also may be some cached data in our adapter */
+ if (rx_ring->rx_skb_top) {
+ dev_kfree_skb(rx_ring->rx_skb_top);
+
+ /* rx_skb_prev will be wiped out by rx_skb_top */
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
}
+
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
size = sizeof(struct e1000_ps_page) * rx_ring->count;
@@ -1967,7 +2145,7 @@ e1000_clean_all_rx_rings(struct e1000_adapter *adapter)
{
int i;
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]);
}
@@ -1988,7 +2166,7 @@ e1000_enter_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_clean_all_rx_rings(adapter);
}
@@ -2004,12 +2182,14 @@ e1000_leave_82542_rst(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
mdelay(5);
- if(adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
+ if (adapter->hw.pci_cmd_word & PCI_COMMAND_INVALIDATE)
e1000_pci_set_mwi(&adapter->hw);
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
+ /* No need to loop, because 82542 supports only 1 queue */
+ struct e1000_rx_ring *ring = &adapter->rx_ring[0];
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter, &adapter->rx_ring[0]);
+ adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring));
}
}
@@ -2027,12 +2207,12 @@ e1000_set_mac(struct net_device *netdev, void *p)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
- if(!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -2046,17 +2226,17 @@ e1000_set_mac(struct net_device *netdev, void *p)
/* activate the work around */
adapter->hw.laa_is_present = 1;
- /* Hold a copy of the LAA in RAR[14] This is done so that
- * between the time RAR[0] gets clobbered and the time it
- * gets fixed (in e1000_watchdog), the actual LAA is in one
+ /* Hold a copy of the LAA in RAR[14] This is done so that
+ * between the time RAR[0] gets clobbered and the time it
+ * gets fixed (in e1000_watchdog), the actual LAA is in one
* of the RARs and no incoming packets directed to this port
- * are dropped. Eventaully the LAA will be in RAR[0] and
+ * are dropped. Eventaully the LAA will be in RAR[0] and
* RAR[14] */
- e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
+ e1000_rar_set(&adapter->hw, adapter->hw.mac_addr,
E1000_RAR_ENTRIES - 1);
}
- if(adapter->hw.mac_type == e1000_82542_rev2_0)
+ if (adapter->hw.mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
return 0;
@@ -2090,9 +2270,9 @@ e1000_set_multi(struct net_device *netdev)
rctl = E1000_READ_REG(hw, RCTL);
- if(netdev->flags & IFF_PROMISC) {
+ if (netdev->flags & IFF_PROMISC) {
rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
- } else if(netdev->flags & IFF_ALLMULTI) {
+ } else if (netdev->flags & IFF_ALLMULTI) {
rctl |= E1000_RCTL_MPE;
rctl &= ~E1000_RCTL_UPE;
} else {
@@ -2103,7 +2283,7 @@ e1000_set_multi(struct net_device *netdev)
/* 82542 2.0 needs to be in reset to write receive address registers */
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_enter_82542_rst(adapter);
/* load the first 14 multicast address into the exact filters 1-14
@@ -2113,7 +2293,7 @@ e1000_set_multi(struct net_device *netdev)
*/
mc_ptr = netdev->mc_list;
- for(i = 1; i < rar_entries; i++) {
+ for (i = 1; i < rar_entries; i++) {
if (mc_ptr) {
e1000_rar_set(hw, mc_ptr->dmi_addr, i);
mc_ptr = mc_ptr->next;
@@ -2125,17 +2305,17 @@ e1000_set_multi(struct net_device *netdev)
/* clear the old settings from the multicast hash table */
- for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
+ for (i = 0; i < E1000_NUM_MTA_REGISTERS; i++)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* load any remaining addresses into the hash table */
- for(; mc_ptr; mc_ptr = mc_ptr->next) {
+ for (; mc_ptr; mc_ptr = mc_ptr->next) {
hash_value = e1000_hash_mc_addr(hw, mc_ptr->dmi_addr);
e1000_mta_set(hw, hash_value);
}
- if(hw->mac_type == e1000_82542_rev2_0)
+ if (hw->mac_type == e1000_82542_rev2_0)
e1000_leave_82542_rst(adapter);
}
@@ -2161,8 +2341,8 @@ e1000_82547_tx_fifo_stall(unsigned long data)
struct net_device *netdev = adapter->netdev;
uint32_t tctl;
- if(atomic_read(&adapter->tx_fifo_stall)) {
- if((E1000_READ_REG(&adapter->hw, TDT) ==
+ if (atomic_read(&adapter->tx_fifo_stall)) {
+ if ((E1000_READ_REG(&adapter->hw, TDT) ==
E1000_READ_REG(&adapter->hw, TDH)) &&
(E1000_READ_REG(&adapter->hw, TDFT) ==
E1000_READ_REG(&adapter->hw, TDFH)) &&
@@ -2208,24 +2388,24 @@ static void
e1000_watchdog_task(struct e1000_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_ring *txdr = &adapter->tx_ring[0];
+ struct e1000_tx_ring *txdr = adapter->tx_ring;
uint32_t link;
e1000_check_for_link(&adapter->hw);
if (adapter->hw.mac_type == e1000_82573) {
e1000_enable_tx_pkt_filtering(&adapter->hw);
- if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
e1000_update_mng_vlan(adapter);
- }
+ }
- if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
+ if ((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
link = !adapter->hw.serdes_link_down;
else
link = E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU;
- if(link) {
- if(!netif_carrier_ok(netdev)) {
+ if (link) {
+ if (!netif_carrier_ok(netdev)) {
e1000_get_speed_and_duplex(&adapter->hw,
&adapter->link_speed,
&adapter->link_duplex);
@@ -2235,13 +2415,28 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
adapter->link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex");
+ /* tweak tx_queue_len according to speed/duplex */
+ netdev->tx_queue_len = adapter->tx_queue_len;
+ adapter->tx_timeout_factor = 1;
+ if (adapter->link_duplex == HALF_DUPLEX) {
+ switch (adapter->link_speed) {
+ case SPEED_10:
+ netdev->tx_queue_len = 10;
+ adapter->tx_timeout_factor = 8;
+ break;
+ case SPEED_100:
+ netdev->tx_queue_len = 100;
+ break;
+ }
+ }
+
netif_carrier_on(netdev);
netif_wake_queue(netdev);
mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
adapter->smartspeed = 0;
}
} else {
- if(netif_carrier_ok(netdev)) {
+ if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
DPRINTK(LINK, INFO, "NIC Link is Down\n");
@@ -2267,7 +2462,10 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
e1000_update_adaptive(&adapter->hw);
- if (adapter->num_queues == 1 && !netif_carrier_ok(netdev)) {
+#ifdef CONFIG_E1000_MQ
+ txdr = *per_cpu_ptr(adapter->cpu_tx_ring, smp_processor_id());
+#endif
+ if (!netif_carrier_ok(netdev)) {
if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
/* We've lost link, so the controller stops DMA,
* but we've got queued Tx work that's never going
@@ -2278,12 +2476,12 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
}
/* Dynamic mode for Interrupt Throttle Rate (ITR) */
- if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
+ if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) {
/* Symmetric Tx/Rx gets a reduced ITR=2000; Total
* asymmetrical Tx or Rx gets ITR=8000; everyone
* else is between 2000-8000. */
uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000;
- uint32_t dif = (adapter->gotcl > adapter->gorcl ?
+ uint32_t dif = (adapter->gotcl > adapter->gorcl ?
adapter->gotcl - adapter->gorcl :
adapter->gorcl - adapter->gotcl) / 10000;
uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000;
@@ -2296,7 +2494,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
/* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = TRUE;
- /* With 82571 controllers, LAA may be overwritten due to controller
+ /* With 82571 controllers, LAA may be overwritten due to controller
* reset from the other port. Set the appropriate LAA in RAR[0] */
if (adapter->hw.mac_type == e1000_82571 && adapter->hw.laa_is_present)
e1000_rar_set(&adapter->hw, adapter->hw.mac_addr, 0);
@@ -2318,13 +2516,14 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
{
#ifdef NETIF_F_TSO
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint32_t cmd_length = 0;
uint16_t ipcse = 0, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
- if(skb_shinfo(skb)->tso_size) {
+ if (skb_shinfo(skb)->tso_size) {
if (skb_header_cloned(skb)) {
err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (err)
@@ -2333,7 +2532,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
- if(skb->protocol == ntohs(ETH_P_IP)) {
+ if (skb->protocol == ntohs(ETH_P_IP)) {
skb->nh.iph->tot_len = 0;
skb->nh.iph->check = 0;
skb->h.th->check =
@@ -2345,7 +2544,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
cmd_length = E1000_TXD_CMD_IP;
ipcse = skb->h.raw - skb->data - 1;
#ifdef NETIF_F_TSO_IPV6
- } else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+ } else if (skb->protocol == ntohs(ETH_P_IPV6)) {
skb->nh.ipv6h->payload_len = 0;
skb->h.th->check =
~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -2367,6 +2566,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
+ buffer_info = &tx_ring->buffer_info[i];
context_desc->lower_setup.ip_fields.ipcss = ipcss;
context_desc->lower_setup.ip_fields.ipcso = ipcso;
@@ -2378,14 +2578,16 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
context_desc->cmd_and_length = cpu_to_le32(cmd_length);
+ buffer_info->time_stamp = jiffies;
+
if (++i == tx_ring->count) i = 0;
tx_ring->next_to_use = i;
- return 1;
+ return TRUE;
}
#endif
- return 0;
+ return FALSE;
}
static inline boolean_t
@@ -2393,13 +2595,15 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
struct sk_buff *skb)
{
struct e1000_context_desc *context_desc;
+ struct e1000_buffer *buffer_info;
unsigned int i;
uint8_t css;
- if(likely(skb->ip_summed == CHECKSUM_HW)) {
+ if (likely(skb->ip_summed == CHECKSUM_HW)) {
css = skb->h.raw - skb->data;
i = tx_ring->next_to_use;
+ buffer_info = &tx_ring->buffer_info[i];
context_desc = E1000_CONTEXT_DESC(*tx_ring, i);
context_desc->upper_setup.tcp_fields.tucss = css;
@@ -2408,6 +2612,8 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
context_desc->tcp_seg_setup.data = 0;
context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
+ buffer_info->time_stamp = jiffies;
+
if (unlikely(++i == tx_ring->count)) i = 0;
tx_ring->next_to_use = i;
@@ -2433,13 +2639,23 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
i = tx_ring->next_to_use;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
+ /* Workaround for Controller erratum --
+ * descriptor for non-tso packet in a linear SKB that follows a
+ * tso gets written back prematurely before the data is fully
+ * DMAd to the controller */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+ !skb_shinfo(skb)->tso_size) {
+ tx_ring->last_tx_tso = 0;
+ size -= 4;
+ }
+
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && !nr_frags && size == len && size > 8))
+ if (unlikely(mss && !nr_frags && size == len && size > 8))
size -= 4;
#endif
/* work-around for errata 10 and it applies
@@ -2447,13 +2663,13 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
* The fix is to make sure that the first descriptor of a
* packet is smaller than 2048 - 16 - 16 (or 2016) bytes
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(size > 2015) && count == 0))
size = 2015;
-
+
/* Workaround for potential 82544 hang in PCI-X. Avoid
* terminating buffers within evenly-aligned dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(skb->data + offset + size - 1) & 4) &&
size > 4))
size -= 4;
@@ -2469,29 +2685,29 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- for(f = 0; f < nr_frags; f++) {
+ for (f = 0; f < nr_frags; f++) {
struct skb_frag_struct *frag;
frag = &skb_shinfo(skb)->frags[f];
len = frag->size;
offset = frag->page_offset;
- while(len) {
+ while (len) {
buffer_info = &tx_ring->buffer_info[i];
size = min(len, max_per_txd);
#ifdef NETIF_F_TSO
/* Workaround for premature desc write-backs
* in TSO mode. Append 4-byte sentinel desc */
- if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
+ if (unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
size -= 4;
#endif
/* Workaround for potential 82544 hang in PCI-X.
* Avoid terminating buffers within evenly-aligned
* dwords. */
- if(unlikely(adapter->pcix_82544 &&
+ if (unlikely(adapter->pcix_82544 &&
!((unsigned long)(frag->page+offset+size-1) & 4) &&
size > 4))
size -= 4;
@@ -2508,7 +2724,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
len -= size;
offset += size;
count++;
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
}
@@ -2528,35 +2744,35 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
unsigned int i;
- if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_TSO)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
- if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+ if (likely(tx_flags & E1000_TX_FLAGS_IPV4))
txd_upper |= E1000_TXD_POPTS_IXSM << 8;
}
- if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
+ if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
txd_upper |= E1000_TXD_POPTS_TXSM << 8;
}
- if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
+ if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
txd_lower |= E1000_TXD_CMD_VLE;
txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
}
i = tx_ring->next_to_use;
- while(count--) {
+ while (count--) {
buffer_info = &tx_ring->buffer_info[i];
tx_desc = E1000_TX_DESC(*tx_ring, i);
tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
tx_desc->lower.data =
cpu_to_le32(txd_lower | buffer_info->length);
tx_desc->upper.data = cpu_to_le32(txd_upper);
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -2591,20 +2807,20 @@ e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR);
- if(adapter->link_duplex != HALF_DUPLEX)
+ if (adapter->link_duplex != HALF_DUPLEX)
goto no_fifo_stall_required;
- if(atomic_read(&adapter->tx_fifo_stall))
+ if (atomic_read(&adapter->tx_fifo_stall))
return 1;
- if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
+ if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) {
atomic_set(&adapter->tx_fifo_stall, 1);
return 1;
}
no_fifo_stall_required:
adapter->tx_fifo_head += skb_fifo_len;
- if(adapter->tx_fifo_head >= adapter->tx_fifo_size)
+ if (adapter->tx_fifo_head >= adapter->tx_fifo_size)
adapter->tx_fifo_head -= adapter->tx_fifo_size;
return 0;
}
@@ -2615,27 +2831,27 @@ e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
{
struct e1000_hw *hw = &adapter->hw;
uint16_t length, offset;
- if(vlan_tx_tag_present(skb)) {
- if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ if (vlan_tx_tag_present(skb)) {
+ if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
( adapter->hw.mng_cookie.status &
E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
return 0;
}
- if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ if ((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
struct ethhdr *eth = (struct ethhdr *) skb->data;
- if((htons(ETH_P_IP) == eth->h_proto)) {
- const struct iphdr *ip =
+ if ((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
(struct iphdr *)((uint8_t *)skb->data+14);
- if(IPPROTO_UDP == ip->protocol) {
- struct udphdr *udp =
- (struct udphdr *)((uint8_t *)ip +
+ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+ (struct udphdr *)((uint8_t *)ip +
(ip->ihl << 2));
- if(ntohs(udp->dest) == 67) {
+ if (ntohs(udp->dest) == 67) {
offset = (uint8_t *)udp + 8 - skb->data;
length = skb->len - offset;
return e1000_mng_write_dhcp_info(hw,
- (uint8_t *)udp + 8,
+ (uint8_t *)udp + 8,
length);
}
}
@@ -2658,7 +2874,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
unsigned int nr_frags = 0;
unsigned int mss = 0;
int count = 0;
- int tso;
+ int tso;
unsigned int f;
len -= skb->data_len;
@@ -2681,59 +2897,65 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
* 4 = ceil(buffer len/mss). To make sure we don't
* overrun the FIFO, adjust the max buffer len if mss
* drops. */
- if(mss) {
+ if (mss) {
+ uint8_t hdr_len;
max_per_txd = min(mss << 2, max_per_txd);
max_txd_pwr = fls(max_per_txd) - 1;
+
+ /* TSO Workaround for 82571/2 Controllers -- if skb->data
+ * points to just header, pull a few bytes of payload from
+ * frags into skb->data */
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+ if (skb->data_len && (hdr_len == (skb->len - skb->data_len)) &&
+ (adapter->hw.mac_type == e1000_82571 ||
+ adapter->hw.mac_type == e1000_82572)) {
+ unsigned int pull_size;
+ pull_size = min((unsigned int)4, skb->data_len);
+ if (!__pskb_pull_tail(skb, pull_size)) {
+ printk(KERN_ERR "__pskb_pull_tail failed.\n");
+ dev_kfree_skb_any(skb);
+ return -EFAULT;
+ }
+ len = skb->len - skb->data_len;
+ }
}
- if((mss) || (skb->ip_summed == CHECKSUM_HW))
+ /* reserve a descriptor for the offload context */
+ if ((mss) || (skb->ip_summed == CHECKSUM_HW))
count++;
count++;
#else
- if(skb->ip_summed == CHECKSUM_HW)
+ if (skb->ip_summed == CHECKSUM_HW)
+ count++;
+#endif
+
+#ifdef NETIF_F_TSO
+ /* Controller Erratum workaround */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+ !skb_shinfo(skb)->tso_size)
count++;
#endif
+
count += TXD_USE_COUNT(len, max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count++;
- /* work-around for errata 10 and it applies to all controllers
+ /* work-around for errata 10 and it applies to all controllers
* in PCI-X mode, so add one more descriptor to the count
*/
- if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ if (unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
(len > 2015)))
count++;
nr_frags = skb_shinfo(skb)->nr_frags;
- for(f = 0; f < nr_frags; f++)
+ for (f = 0; f < nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
max_txd_pwr);
- if(adapter->pcix_82544)
+ if (adapter->pcix_82544)
count += nr_frags;
-#ifdef NETIF_F_TSO
- /* TSO Workaround for 82571/2 Controllers -- if skb->data
- * points to just header, pull a few bytes of payload from
- * frags into skb->data */
- if (skb_shinfo(skb)->tso_size) {
- uint8_t hdr_len;
- hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
- if (skb->data_len && (hdr_len < (skb->len - skb->data_len)) &&
- (adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572)) {
- unsigned int pull_size;
- pull_size = min((unsigned int)4, skb->data_len);
- if (!__pskb_pull_tail(skb, pull_size)) {
- printk(KERN_ERR "__pskb_pull_tail failed.\n");
- dev_kfree_skb_any(skb);
- return -EFAULT;
- }
- }
- }
-#endif
-
- if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
+ if (adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
e1000_transfer_dhcp_info(adapter, skb);
local_irq_save(flags);
@@ -2751,8 +2973,8 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
- if(unlikely(adapter->hw.mac_type == e1000_82547)) {
- if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
+ if (unlikely(adapter->hw.mac_type == e1000_82547)) {
+ if (unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
netif_stop_queue(netdev);
mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
@@ -2760,13 +2982,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
}
- if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
+ if (unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
tx_flags |= E1000_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
}
first = tx_ring->next_to_use;
-
+
tso = e1000_tso(adapter, tx_ring, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
@@ -2774,9 +2996,10 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
- if (likely(tso))
+ if (likely(tso)) {
+ tx_ring->last_tx_tso = 1;
tx_flags |= E1000_TX_FLAGS_TSO;
- else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+ } else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
/* Old method was to assume IPv4 packet by default if TSO was enabled.
@@ -2818,6 +3041,7 @@ e1000_tx_timeout_task(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ adapter->tx_timeout_count++;
e1000_down(adapter);
e1000_up(adapter);
}
@@ -2835,7 +3059,7 @@ e1000_get_stats(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- e1000_update_stats(adapter);
+ /* only return the current stats */
return &adapter->net_stats;
}
@@ -2853,56 +3077,57 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
struct e1000_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
- if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
- (max_frame > MAX_JUMBO_FRAME_SIZE)) {
- DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
- return -EINVAL;
- }
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
- /* might want this to be bigger enum check... */
- /* 82571 controllers limit jumbo frame size to 10500 bytes */
- if ((adapter->hw.mac_type == e1000_82571 ||
- adapter->hw.mac_type == e1000_82572) &&
- max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
- DPRINTK(PROBE, ERR, "MTU > 9216 bytes not supported "
- "on 82571 and 82572 controllers.\n");
+ if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
+ (max_frame > MAX_JUMBO_FRAME_SIZE)) {
+ DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
return -EINVAL;
}
- if(adapter->hw.mac_type == e1000_82573 &&
- max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
- "on 82573\n");
- return -EINVAL;
- }
-
- if(adapter->hw.mac_type > e1000_82547_rev_2) {
- adapter->rx_buffer_len = max_frame;
- E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
- } else {
- if(unlikely((adapter->hw.mac_type < e1000_82543) &&
- (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
- "on 82542\n");
+ /* Adapter-specific max frame size limits. */
+ switch (adapter->hw.mac_type) {
+ case e1000_82542_rev2_0:
+ case e1000_82542_rev2_1:
+ case e1000_82573:
+ if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
return -EINVAL;
-
- } else {
- if(max_frame <= E1000_RXBUFFER_2048) {
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
- } else if(max_frame <= E1000_RXBUFFER_4096) {
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
- } else if(max_frame <= E1000_RXBUFFER_8192) {
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
- } else if(max_frame <= E1000_RXBUFFER_16384) {
- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
- }
}
+ break;
+ case e1000_82571:
+ case e1000_82572:
+#define MAX_STD_JUMBO_FRAME_SIZE 9234
+ if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "MTU > 9216 not supported.\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */
+ break;
}
+ /* since the driver code now supports splitting a packet across
+ * multiple descriptors, most of the fifo related limitations on
+ * jumbo frame traffic have gone away.
+ * simply use 2k descriptors for everything.
+ *
+ * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+ * means we reserve 2 more, this pushes us to allocate from the next
+ * larger slab size
+ * i.e. RXBUFFER_2048 --> size-4096 slab */
+
+ /* recent hardware supports 1KB granularity */
+ if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->rx_buffer_len =
+ ((max_frame < E1000_RXBUFFER_2048) ?
+ max_frame : E1000_RXBUFFER_2048);
+ E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
+ } else
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+
netdev->mtu = new_mtu;
- if(netif_running(netdev)) {
+ if (netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
@@ -2989,7 +3214,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
hw->collision_delta = E1000_READ_REG(hw, COLC);
adapter->stats.colc += hw->collision_delta;
- if(hw->mac_type >= e1000_82543) {
+ if (hw->mac_type >= e1000_82543) {
adapter->stats.algnerrc += E1000_READ_REG(hw, ALGNERRC);
adapter->stats.rxerrc += E1000_READ_REG(hw, RXERRC);
adapter->stats.tncrs += E1000_READ_REG(hw, TNCRS);
@@ -2997,7 +3222,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
- if(hw->mac_type > e1000_82547_rev_2) {
+ if (hw->mac_type > e1000_82547_rev_2) {
adapter->stats.iac += E1000_READ_REG(hw, IAC);
adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
@@ -3022,12 +3247,11 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
- adapter->stats.rlec + adapter->stats.mpc +
- adapter->stats.cexterr;
+ adapter->stats.rlec + adapter->stats.cexterr;
+ adapter->net_stats.rx_dropped = 0;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
- adapter->net_stats.rx_fifo_errors = adapter->stats.mpc;
adapter->net_stats.rx_missed_errors = adapter->stats.mpc;
/* Tx Errors */
@@ -3042,14 +3266,14 @@ e1000_update_stats(struct e1000_adapter *adapter)
/* Phy Stats */
- if(hw->media_type == e1000_media_type_copper) {
- if((adapter->link_speed == SPEED_1000) &&
+ if (hw->media_type == e1000_media_type_copper) {
+ if ((adapter->link_speed == SPEED_1000) &&
(!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) {
phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
adapter->phy_stats.idle_errors += phy_tmp;
}
- if((hw->mac_type <= e1000_82546) &&
+ if ((hw->mac_type <= e1000_82546) &&
(hw->phy_type == e1000_phy_m88) &&
!e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp))
adapter->phy_stats.receive_errors += phy_tmp;
@@ -3095,32 +3319,44 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
uint32_t icr = E1000_READ_REG(hw, ICR);
-#if defined(CONFIG_E1000_NAPI) && defined(CONFIG_E1000_MQ) || !defined(CONFIG_E1000_NAPI)
+#ifndef CONFIG_E1000_NAPI
int i;
+#else
+ /* Interrupt Auto-Mask...upon reading ICR,
+ * interrupts are masked. No need for the
+ * IMC write, but it does mean we should
+ * account for it ASAP. */
+ if (likely(hw->mac_type >= e1000_82571))
+ atomic_inc(&adapter->irq_sem);
#endif
- if(unlikely(!icr))
+ if (unlikely(!icr)) {
+#ifdef CONFIG_E1000_NAPI
+ if (hw->mac_type >= e1000_82571)
+ e1000_irq_enable(adapter);
+#endif
return IRQ_NONE; /* Not our interrupt */
+ }
- if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
+ if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
hw->get_link_status = 1;
mod_timer(&adapter->watchdog_timer, jiffies);
}
#ifdef CONFIG_E1000_NAPI
- atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(hw, IMC, ~0);
- E1000_WRITE_FLUSH(hw);
+ if (unlikely(hw->mac_type < e1000_82571)) {
+ atomic_inc(&adapter->irq_sem);
+ E1000_WRITE_REG(hw, IMC, ~0);
+ E1000_WRITE_FLUSH(hw);
+ }
#ifdef CONFIG_E1000_MQ
if (atomic_read(&adapter->rx_sched_call_data.count) == 0) {
- cpu_set(adapter->cpu_for_queue[0],
- adapter->rx_sched_call_data.cpumask);
- for (i = 1; i < adapter->num_queues; i++) {
- cpu_set(adapter->cpu_for_queue[i],
- adapter->rx_sched_call_data.cpumask);
- atomic_inc(&adapter->irq_sem);
- }
- atomic_set(&adapter->rx_sched_call_data.count, i);
+ /* We must setup the cpumask once count == 0 since
+ * each cpu bit is cleared when the work is done. */
+ adapter->rx_sched_call_data.cpumask = adapter->cpumask;
+ atomic_add(adapter->num_rx_queues - 1, &adapter->irq_sem);
+ atomic_set(&adapter->rx_sched_call_data.count,
+ adapter->num_rx_queues);
smp_call_async_mask(&adapter->rx_sched_call_data);
} else {
printk("call_data.count == %u\n", atomic_read(&adapter->rx_sched_call_data.count));
@@ -3134,26 +3370,26 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
#else /* if !CONFIG_E1000_NAPI */
/* Writing IMC and IMS is needed for 82547.
- Due to Hub Link bus being occupied, an interrupt
- de-assertion message is not able to be sent.
- When an interrupt assertion message is generated later,
- two messages are re-ordered and sent out.
- That causes APIC to think 82547 is in de-assertion
- state, while 82547 is in assertion state, resulting
- in dead lock. Writing IMC forces 82547 into
- de-assertion state.
- */
- if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){
+ * Due to Hub Link bus being occupied, an interrupt
+ * de-assertion message is not able to be sent.
+ * When an interrupt assertion message is generated later,
+ * two messages are re-ordered and sent out.
+ * That causes APIC to think 82547 is in de-assertion
+ * state, while 82547 is in assertion state, resulting
+ * in dead lock. Writing IMC forces 82547 into
+ * de-assertion state.
+ */
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) {
atomic_inc(&adapter->irq_sem);
E1000_WRITE_REG(hw, IMC, ~0);
}
- for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
+ for (i = 0; i < E1000_MAX_INTR; i++)
+ if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) &
!e1000_clean_tx_irq(adapter, adapter->tx_ring)))
break;
- if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
+ if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
e1000_irq_enable(adapter);
#endif /* CONFIG_E1000_NAPI */
@@ -3172,7 +3408,7 @@ e1000_clean(struct net_device *poll_dev, int *budget)
{
struct e1000_adapter *adapter;
int work_to_do = min(*budget, poll_dev->quota);
- int tx_cleaned, i = 0, work_done = 0;
+ int tx_cleaned = 0, i = 0, work_done = 0;
/* Must NOT use netdev_priv macro here. */
adapter = poll_dev->priv;
@@ -3183,19 +3419,31 @@ e1000_clean(struct net_device *poll_dev, int *budget)
while (poll_dev != &adapter->polling_netdev[i]) {
i++;
- if (unlikely(i == adapter->num_queues))
+ if (unlikely(i == adapter->num_rx_queues))
BUG();
}
- tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+ if (likely(adapter->num_tx_queues == 1)) {
+ /* e1000_clean is called per-cpu. This lock protects
+ * tx_ring[0] from being cleaned by multiple cpus
+ * simultaneously. A failure obtaining the lock means
+ * tx_ring[0] is currently being cleaned anyway. */
+ if (spin_trylock(&adapter->tx_queue_lock)) {
+ tx_cleaned = e1000_clean_tx_irq(adapter,
+ &adapter->tx_ring[0]);
+ spin_unlock(&adapter->tx_queue_lock);
+ }
+ } else
+ tx_cleaned = e1000_clean_tx_irq(adapter, &adapter->tx_ring[i]);
+
adapter->clean_rx(adapter, &adapter->rx_ring[i],
&work_done, work_to_do);
*budget -= work_done;
poll_dev->quota -= work_done;
-
+
/* If no Tx and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done == 0)) ||
+ if ((!tx_cleaned && (work_done == 0)) ||
!netif_running(adapter->netdev)) {
quit_polling:
netif_rx_complete(poll_dev);
@@ -3227,47 +3475,24 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while (eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
- /* Premature writeback of Tx descriptors clear (free buffers
- * and unmap pci_mapping) previous_buffer_info */
- if (likely(tx_ring->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
- &tx_ring->previous_buffer_info);
- }
-
- for(cleaned = FALSE; !cleaned; ) {
+ for (cleaned = FALSE; !cleaned; ) {
tx_desc = E1000_TX_DESC(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
-#ifdef NETIF_F_TSO
- if (!(netdev->features & NETIF_F_TSO)) {
-#endif
- e1000_unmap_and_free_tx_resource(adapter,
- buffer_info);
-#ifdef NETIF_F_TSO
- } else {
- if (cleaned) {
- memcpy(&tx_ring->previous_buffer_info,
- buffer_info,
- sizeof(struct e1000_buffer));
- memset(buffer_info, 0,
- sizeof(struct e1000_buffer));
- } else {
- e1000_unmap_and_free_tx_resource(
- adapter, buffer_info);
- }
- }
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.bytes += buffer_info->length;
#endif
+ e1000_unmap_and_free_tx_resource(adapter, buffer_info);
+ memset(tx_desc, 0, sizeof(struct e1000_tx_desc));
- tx_desc->buffer_addr = 0;
- tx_desc->lower.data = 0;
- tx_desc->upper.data = 0;
-
- if(unlikely(++i == tx_ring->count)) i = 0;
+ if (unlikely(++i == tx_ring->count)) i = 0;
}
- tx_ring->pkt++;
-
+#ifdef CONFIG_E1000_MQ
+ tx_ring->tx_stats.packets++;
+#endif
+
eop = tx_ring->buffer_info[i].next_to_watch;
eop_desc = E1000_TX_DESC(*tx_ring, eop);
}
@@ -3276,7 +3501,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
spin_lock(&tx_ring->tx_lock);
- if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+ if (unlikely(cleaned && netif_queue_stopped(netdev) &&
netif_carrier_ok(netdev)))
netif_wake_queue(netdev);
@@ -3286,44 +3511,37 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter,
/* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = FALSE;
- if (tx_ring->buffer_info[i].dma &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+ if (tx_ring->buffer_info[eop].dma &&
+ time_after(jiffies, tx_ring->buffer_info[eop].time_stamp +
+ adapter->tx_timeout_factor * HZ)
&& !(E1000_READ_REG(&adapter->hw, STATUS) &
- E1000_STATUS_TXOFF)) {
+ E1000_STATUS_TXOFF)) {
/* detected Tx unit hang */
- i = tx_ring->next_to_clean;
- eop = tx_ring->buffer_info[i].next_to_watch;
- eop_desc = E1000_TX_DESC(*tx_ring, eop);
DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+ " Tx Queue <%lu>\n"
" TDH <%x>\n"
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
"buffer_info[next_to_clean]\n"
- " dma <%llx>\n"
" time_stamp <%lx>\n"
" next_to_watch <%x>\n"
" jiffies <%lx>\n"
" next_to_watch.status <%x>\n",
+ (unsigned long)((tx_ring - adapter->tx_ring) /
+ sizeof(struct e1000_tx_ring)),
readl(adapter->hw.hw_addr + tx_ring->tdh),
readl(adapter->hw.hw_addr + tx_ring->tdt),
tx_ring->next_to_use,
- i,
- (unsigned long long)tx_ring->buffer_info[i].dma,
- tx_ring->buffer_info[i].time_stamp,
+ tx_ring->next_to_clean,
+ tx_ring->buffer_info[eop].time_stamp,
eop,
jiffies,
eop_desc->upper.fields.status);
netif_stop_queue(netdev);
}
}
-#ifdef NETIF_F_TSO
- if (unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
- time_after(jiffies, tx_ring->previous_buffer_info.time_stamp + HZ)))
- e1000_unmap_and_free_tx_resource(
- adapter, &tx_ring->previous_buffer_info);
-#endif
return cleaned;
}
@@ -3345,21 +3563,21 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
skb->ip_summed = CHECKSUM_NONE;
/* 82543 or newer only */
- if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
+ if (unlikely(adapter->hw.mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
- if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+ if (unlikely(status & E1000_RXD_STAT_IXSM)) return;
/* TCP/UDP checksum error bit is set */
- if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
+ if (unlikely(errors & E1000_RXD_ERR_TCPE)) {
/* let the stack verify checksum errors */
adapter->hw_csum_err++;
return;
}
/* TCP/UDP Checksum has not been calculated */
- if(adapter->hw.mac_type <= e1000_82547_rev_2) {
- if(!(status & E1000_RXD_STAT_TCPCS))
+ if (adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if (!(status & E1000_RXD_STAT_TCPCS))
return;
} else {
- if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+ if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
return;
}
/* It must be a TCP or UDP packet with a valid checksum */
@@ -3395,46 +3613,87 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_rx_desc *rx_desc;
- struct e1000_buffer *buffer_info;
- struct sk_buff *skb;
+ struct e1000_rx_desc *rx_desc, *next_rxd;
+ struct e1000_buffer *buffer_info, *next_buffer;
unsigned long flags;
uint32_t length;
uint8_t last_byte;
unsigned int i;
- boolean_t cleaned = FALSE;
+ int cleaned_count = 0;
+ boolean_t cleaned = FALSE, multi_descriptor = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC(*rx_ring, i);
+ buffer_info = &rx_ring->buffer_info[i];
- while(rx_desc->status & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (rx_desc->status & E1000_RXD_STAT_DD) {
+ struct sk_buff *skb, *next_skb;
+ u8 status;
#ifdef CONFIG_E1000_NAPI
- if(*work_done >= work_to_do)
+ if (*work_done >= work_to_do)
break;
(*work_done)++;
#endif
- cleaned = TRUE;
+ status = rx_desc->status;
+ skb = buffer_info->skb;
+ buffer_info->skb = NULL;
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+
+ cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
length = le16_to_cpu(rx_desc->length);
- if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
- /* All receives must fit into a single buffer */
- E1000_DBG("%s: Receive packet consumed multiple"
- " buffers\n", netdev->name);
- dev_kfree_skb_irq(skb);
+ skb_put(skb, length);
+
+ if (!(status & E1000_RXD_STAT_EOP)) {
+ if (!rx_ring->rx_skb_top) {
+ rx_ring->rx_skb_top = skb;
+ rx_ring->rx_skb_top->len = length;
+ rx_ring->rx_skb_prev = skb;
+ } else {
+ if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else {
+ skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb;
+ }
+ rx_ring->rx_skb_prev = skb;
+ rx_ring->rx_skb_top->data_len += length;
+ }
goto next_desc;
+ } else {
+ if (rx_ring->rx_skb_top) {
+ if (skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list) {
+ rx_ring->rx_skb_prev->next = skb;
+ skb->prev = rx_ring->rx_skb_prev;
+ } else
+ skb_shinfo(rx_ring->rx_skb_top)
+ ->frag_list = skb;
+
+ rx_ring->rx_skb_top->data_len += length;
+ rx_ring->rx_skb_top->len +=
+ rx_ring->rx_skb_top->data_len;
+
+ skb = rx_ring->rx_skb_top;
+ multi_descriptor = TRUE;
+ rx_ring->rx_skb_top = NULL;
+ rx_ring->rx_skb_prev = NULL;
+ }
}
- if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
last_byte = *(skb->data + length - 1);
- if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
+ if (TBI_ACCEPT(&adapter->hw, status,
rx_desc->errors, length, last_byte)) {
spin_lock_irqsave(&adapter->stats_lock, flags);
e1000_tbi_adjust_stats(&adapter->hw,
@@ -3449,18 +3708,41 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
}
- /* Good Receive */
- skb_put(skb, length - ETHERNET_FCS_SIZE);
+ /* code added for copybreak, this should improve
+ * performance for small packets with large amounts
+ * of reassembly being done in the stack */
+#define E1000_CB_LENGTH 256
+ if ((length < E1000_CB_LENGTH) &&
+ !rx_ring->rx_skb_top &&
+ /* or maybe (status & E1000_RXD_STAT_EOP) && */
+ !multi_descriptor) {
+ struct sk_buff *new_skb =
+ dev_alloc_skb(length + NET_IP_ALIGN);
+ if (new_skb) {
+ skb_reserve(new_skb, NET_IP_ALIGN);
+ new_skb->dev = netdev;
+ memcpy(new_skb->data - NET_IP_ALIGN,
+ skb->data - NET_IP_ALIGN,
+ length + NET_IP_ALIGN);
+ /* save the skb in buffer_info as good */
+ buffer_info->skb = skb;
+ skb = new_skb;
+ skb_put(skb, length);
+ }
+ }
+
+ /* end copybreak code */
/* Receive Checksum Offload */
e1000_rx_checksum(adapter,
- (uint32_t)(rx_desc->status) |
+ (uint32_t)(status) |
((uint32_t)(rx_desc->errors) << 24),
rx_desc->csum, skb);
+
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3468,8 +3750,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp &&
- (rx_desc->status & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp &&
+ (status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3478,17 +3760,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->status = 0;
- buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3508,52 +3801,59 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
struct e1000_rx_ring *rx_ring)
#endif
{
- union e1000_rx_desc_packet_split *rx_desc;
+ union e1000_rx_desc_packet_split *rx_desc, *next_rxd;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- struct e1000_buffer *buffer_info;
+ struct e1000_buffer *buffer_info, *next_buffer;
struct e1000_ps_page *ps_page;
struct e1000_ps_page_dma *ps_page_dma;
- struct sk_buff *skb;
+ struct sk_buff *skb, *next_skb;
unsigned int i, j;
uint32_t length, staterr;
+ int cleaned_count = 0;
boolean_t cleaned = FALSE;
i = rx_ring->next_to_clean;
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+ buffer_info = &rx_ring->buffer_info[i];
- while(staterr & E1000_RXD_STAT_DD) {
- buffer_info = &rx_ring->buffer_info[i];
+ while (staterr & E1000_RXD_STAT_DD) {
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
#ifdef CONFIG_E1000_NAPI
- if(unlikely(*work_done >= work_to_do))
+ if (unlikely(*work_done >= work_to_do))
break;
(*work_done)++;
#endif
+ skb = buffer_info->skb;
+
+ if (++i == rx_ring->count) i = 0;
+ next_rxd = E1000_RX_DESC_PS(*rx_ring, i);
+ next_buffer = &rx_ring->buffer_info[i];
+ next_skb = next_buffer->skb;
+
cleaned = TRUE;
+ cleaned_count++;
pci_unmap_single(pdev, buffer_info->dma,
buffer_info->length,
PCI_DMA_FROMDEVICE);
- skb = buffer_info->skb;
-
- if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+ if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
E1000_DBG("%s: Packet Split buffers didn't pick up"
" the full packet\n", netdev->name);
dev_kfree_skb_irq(skb);
goto next_desc;
}
- if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ if (unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
dev_kfree_skb_irq(skb);
goto next_desc;
}
length = le16_to_cpu(rx_desc->wb.middle.length0);
- if(unlikely(!length)) {
+ if (unlikely(!length)) {
E1000_DBG("%s: Last part of the packet spanning"
" multiple descriptors\n", netdev->name);
dev_kfree_skb_irq(skb);
@@ -3563,8 +3863,8 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
/* Good Receive */
skb_put(skb, length);
- for(j = 0; j < adapter->rx_ps_pages; j++) {
- if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+ for (j = 0; j < adapter->rx_ps_pages; j++) {
+ if (!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
break;
pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
@@ -3584,15 +3884,11 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
- if(likely(rx_desc->wb.upper.header_status &
- E1000_RXDPS_HDRSTAT_HDRSP)) {
+ if (likely(rx_desc->wb.upper.header_status &
+ E1000_RXDPS_HDRSTAT_HDRSP))
adapter->rx_hdr_split++;
-#ifdef HAVE_RX_ZERO_COPY
- skb_shinfo(skb)->zero_copy = TRUE;
-#endif
- }
#ifdef CONFIG_E1000_NAPI
- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3600,7 +3896,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
#else /* CONFIG_E1000_NAPI */
- if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ if (unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->wb.middle.vlan) &
E1000_RXD_SPC_VLAN_MASK);
@@ -3609,18 +3905,31 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
}
#endif /* CONFIG_E1000_NAPI */
netdev->last_rx = jiffies;
- rx_ring->pkt++;
+#ifdef CONFIG_E1000_MQ
+ rx_ring->rx_stats.packets++;
+ rx_ring->rx_stats.bytes += length;
+#endif
next_desc:
rx_desc->wb.middle.status_error &= ~0xFF;
buffer_info->skb = NULL;
- if(unlikely(++i == rx_ring->count)) i = 0;
- rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ /* return some buffers to hardware, one at a time is too slow */
+ if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) {
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
+ cleaned_count = 0;
+ }
+
+ rx_desc = next_rxd;
+ buffer_info = next_buffer;
+
staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
}
rx_ring->next_to_clean = i;
- adapter->alloc_rx_buf(adapter, rx_ring);
+
+ cleaned_count = E1000_DESC_UNUSED(rx_ring);
+ if (cleaned_count)
+ adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count);
return cleaned;
}
@@ -3632,7 +3941,8 @@ next_desc:
static void
e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3645,11 +3955,18 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
- while(!buffer_info->skb) {
- skb = dev_alloc_skb(bufsz);
+ while (cleaned_count--) {
+ if (!(skb = buffer_info->skb))
+ skb = dev_alloc_skb(bufsz);
+ else {
+ skb_trim(skb, 0);
+ goto map_skb;
+ }
+
- if(unlikely(!skb)) {
+ if (unlikely(!skb)) {
/* Better luck next round */
+ adapter->alloc_rx_buff_failed++;
break;
}
@@ -3686,6 +4003,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
buffer_info->skb = skb;
buffer_info->length = adapter->rx_buffer_len;
+map_skb:
buffer_info->dma = pci_map_single(pdev,
skb->data,
adapter->rx_buffer_len,
@@ -3711,20 +4029,23 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
rx_desc = E1000_RX_DESC(*rx_ring, i);
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- writel(i, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count))
+ i = 0;
buffer_info = &rx_ring->buffer_info[i];
}
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0))
+ i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ writel(i, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3734,7 +4055,8 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
static void
e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
- struct e1000_rx_ring *rx_ring)
+ struct e1000_rx_ring *rx_ring,
+ int cleaned_count)
{
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -3750,16 +4072,18 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
- while(!buffer_info->skb) {
+ while (cleaned_count--) {
rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
- for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ for (j = 0; j < PS_PAGE_BUFFERS; j++) {
if (j < adapter->rx_ps_pages) {
if (likely(!ps_page->ps_page[j])) {
ps_page->ps_page[j] =
alloc_page(GFP_ATOMIC);
- if (unlikely(!ps_page->ps_page[j]))
+ if (unlikely(!ps_page->ps_page[j])) {
+ adapter->alloc_rx_buff_failed++;
goto no_buffers;
+ }
ps_page_dma->ps_page_dma[j] =
pci_map_page(pdev,
ps_page->ps_page[j],
@@ -3767,7 +4091,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
PCI_DMA_FROMDEVICE);
}
/* Refresh the desc even if buffer_addrs didn't
- * change because each write-back erases
+ * change because each write-back erases
* this info.
*/
rx_desc->read.buffer_addr[j+1] =
@@ -3778,8 +4102,10 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
- if(unlikely(!skb))
+ if (unlikely(!skb)) {
+ adapter->alloc_rx_buff_failed++;
break;
+ }
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
@@ -3797,27 +4123,28 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter,
rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
- if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
- /* Force memory writes to complete before letting h/w
- * know there are new descriptors to fetch. (Only
- * applicable for weak-ordered memory model archs,
- * such as IA-64). */
- wmb();
- /* Hardware increments by 16 bytes, but packet split
- * descriptors are 32 bytes...so we increment tail
- * twice as much.
- */
- writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
- }
-
- if(unlikely(++i == rx_ring->count)) i = 0;
+ if (unlikely(++i == rx_ring->count)) i = 0;
buffer_info = &rx_ring->buffer_info[i];
ps_page = &rx_ring->ps_page[i];
ps_page_dma = &rx_ring->ps_page_dma[i];
}
no_buffers:
- rx_ring->next_to_use = i;
+ if (likely(rx_ring->next_to_use != i)) {
+ rx_ring->next_to_use = i;
+ if (unlikely(i-- == 0)) i = (rx_ring->count - 1);
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ /* Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+ writel(i<<1, adapter->hw.hw_addr + rx_ring->rdt);
+ }
}
/**
@@ -3831,24 +4158,24 @@ e1000_smartspeed(struct e1000_adapter *adapter)
uint16_t phy_status;
uint16_t phy_ctrl;
- if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
+ if ((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg ||
!(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL))
return;
- if(adapter->smartspeed == 0) {
+ if (adapter->smartspeed == 0) {
/* If Master/Slave config fault is asserted twice,
* we assume back-to-back */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status);
- if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
+ if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return;
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
- if(phy_ctrl & CR_1000T_MS_ENABLE) {
+ if (phy_ctrl & CR_1000T_MS_ENABLE) {
phy_ctrl &= ~CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL,
phy_ctrl);
adapter->smartspeed++;
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL,
&phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
@@ -3858,12 +4185,12 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
return;
- } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
+ } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) {
/* If still no link, perhaps using 2/3 pair cable */
e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl);
phy_ctrl |= CR_1000T_MS_ENABLE;
e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl);
- if(!e1000_phy_setup_autoneg(&adapter->hw) &&
+ if (!e1000_phy_setup_autoneg(&adapter->hw) &&
!e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) {
phy_ctrl |= (MII_CR_AUTO_NEG_EN |
MII_CR_RESTART_AUTO_NEG);
@@ -3871,7 +4198,7 @@ e1000_smartspeed(struct e1000_adapter *adapter)
}
}
/* Restart process after E1000_SMARTSPEED_MAX iterations */
- if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
+ if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX)
adapter->smartspeed = 0;
}
@@ -3912,7 +4239,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
uint16_t spddplx;
unsigned long flags;
- if(adapter->hw.media_type != e1000_media_type_copper)
+ if (adapter->hw.media_type != e1000_media_type_copper)
return -EOPNOTSUPP;
switch (cmd) {
@@ -3920,10 +4247,10 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
data->phy_id = adapter->hw.phy_addr;
break;
case SIOCGMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
&data->val_out)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
@@ -3931,23 +4258,23 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
break;
case SIOCSMIIREG:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if(data->reg_num & ~(0x1F))
+ if (data->reg_num & ~(0x1F))
return -EFAULT;
mii_reg = data->val_in;
spin_lock_irqsave(&adapter->stats_lock, flags);
- if(e1000_write_phy_reg(&adapter->hw, data->reg_num,
+ if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
mii_reg)) {
spin_unlock_irqrestore(&adapter->stats_lock, flags);
return -EIO;
}
- if(adapter->hw.phy_type == e1000_phy_m88) {
+ if (adapter->hw.phy_type == e1000_phy_m88) {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(mii_reg & MII_CR_AUTO_NEG_EN) {
+ if (mii_reg & MII_CR_AUTO_NEG_EN) {
adapter->hw.autoneg = 1;
adapter->hw.autoneg_advertised = 0x2F;
} else {
@@ -3962,14 +4289,14 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
HALF_DUPLEX;
retval = e1000_set_spd_dplx(adapter,
spddplx);
- if(retval) {
+ if (retval) {
spin_unlock_irqrestore(
- &adapter->stats_lock,
+ &adapter->stats_lock,
flags);
return retval;
}
}
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -3977,7 +4304,7 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
break;
case M88E1000_PHY_SPEC_CTRL:
case M88E1000_EXT_PHY_SPEC_CTRL:
- if(e1000_phy_reset(&adapter->hw)) {
+ if (e1000_phy_reset(&adapter->hw)) {
spin_unlock_irqrestore(
&adapter->stats_lock, flags);
return -EIO;
@@ -3987,9 +4314,9 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
} else {
switch (data->reg_num) {
case PHY_CTRL:
- if(mii_reg & MII_CR_POWER_DOWN)
+ if (mii_reg & MII_CR_POWER_DOWN)
break;
- if(netif_running(adapter->netdev)) {
+ if (netif_running(adapter->netdev)) {
e1000_down(adapter);
e1000_up(adapter);
} else
@@ -4011,7 +4338,7 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
struct e1000_adapter *adapter = hw->back;
int ret_val = pci_set_mwi(adapter->pdev);
- if(ret_val)
+ if (ret_val)
DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
@@ -4060,7 +4387,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
e1000_irq_disable(adapter);
adapter->vlgrp = grp;
- if(grp) {
+ if (grp) {
/* enable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
ctrl |= E1000_CTRL_VME;
@@ -4082,7 +4409,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
- if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+ if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
}
@@ -4096,9 +4423,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
uint32_t vfta, index;
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
@@ -4115,15 +4443,19 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
e1000_irq_disable(adapter);
- if(adapter->vlgrp)
+ if (adapter->vlgrp)
adapter->vlgrp->vlan_devices[vid] = NULL;
e1000_irq_enable(adapter);
- if((adapter->hw.mng_cookie.status &
- E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
- (vid == adapter->mng_vlan_id))
+ if ((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id)) {
+ /* release control to f/w */
+ e1000_release_hw_control(adapter);
return;
+ }
+
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -4136,10 +4468,10 @@ e1000_restore_vlan(struct e1000_adapter *adapter)
{
e1000_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if(adapter->vlgrp) {
+ if (adapter->vlgrp) {
uint16_t vid;
- for(vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if(!adapter->vlgrp->vlan_devices[vid])
+ for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
+ if (!adapter->vlgrp->vlan_devices[vid])
continue;
e1000_vlan_rx_add_vid(adapter->netdev, vid);
}
@@ -4152,13 +4484,13 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
adapter->hw.autoneg = 0;
/* Fiber NICs only allow 1000 gbps Full duplex */
- if((adapter->hw.media_type == e1000_media_type_fiber) &&
+ if ((adapter->hw.media_type == e1000_media_type_fiber) &&
spddplx != (SPEED_1000 + DUPLEX_FULL)) {
DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
}
- switch(spddplx) {
+ switch (spddplx) {
case SPEED_10 + DUPLEX_HALF:
adapter->hw.forced_speed_duplex = e1000_10_half;
break;
@@ -4184,35 +4516,92 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
}
#ifdef CONFIG_PM
+/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
+ * space versus the 64 bytes that pci_[save|restore]_state handle
+ */
+#define PCIE_CONFIG_SPACE_LEN 256
+#define PCI_CONFIG_SPACE_LEN 64
+static int
+e1000_pci_save_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+
+ WARN_ON(adapter->config_space != NULL);
+
+ adapter->config_space = kmalloc(size, GFP_KERNEL);
+ if (!adapter->config_space) {
+ DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
+ return -ENOMEM;
+ }
+ for (i = 0; i < (size / 4); i++)
+ pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
+ return 0;
+}
+
+static void
+e1000_pci_restore_state(struct e1000_adapter *adapter)
+{
+ struct pci_dev *dev = adapter->pdev;
+ int size;
+ int i;
+ if (adapter->config_space == NULL)
+ return;
+ if (adapter->hw.mac_type >= e1000_82571)
+ size = PCIE_CONFIG_SPACE_LEN;
+ else
+ size = PCI_CONFIG_SPACE_LEN;
+ for (i = 0; i < (size / 4); i++)
+ pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
+ kfree(adapter->config_space);
+ adapter->config_space = NULL;
+ return;
+}
+#endif /* CONFIG_PM */
+
static int
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);
- uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
+ uint32_t ctrl, ctrl_ext, rctl, manc, status;
uint32_t wufc = adapter->wol;
+ int retval = 0;
netif_device_detach(netdev);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_down(adapter);
+#ifdef CONFIG_PM
+ /* implement our own version of pci_save_state(pdev) because pci
+ * express adapters have larger 256 byte config spaces */
+ retval = e1000_pci_save_state(adapter);
+ if (retval)
+ return retval;
+#endif
+
status = E1000_READ_REG(&adapter->hw, STATUS);
- if(status & E1000_STATUS_LU)
+ if (status & E1000_STATUS_LU)
wufc &= ~E1000_WUFC_LNKC;
- if(wufc) {
+ if (wufc) {
e1000_setup_rctl(adapter);
e1000_set_multi(netdev);
/* turn on all-multi mode if wake on multicast is enabled */
- if(adapter->wol & E1000_WUFC_MC) {
+ if (adapter->wol & E1000_WUFC_MC) {
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
- if(adapter->hw.mac_type >= e1000_82540) {
+ if (adapter->hw.mac_type >= e1000_82540) {
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
/* advertise wake from D3Cold */
#define E1000_CTRL_ADVD3WUC 0x00100000
@@ -4223,7 +4612,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
}
- if(adapter->hw.media_type == e1000_media_type_fiber ||
+ if (adapter->hw.media_type == e1000_media_type_fiber ||
adapter->hw.media_type == e1000_media_type_internal_serdes) {
/* keep the laser running in D3 */
ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
@@ -4236,96 +4625,96 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
} else {
E1000_WRITE_REG(&adapter->hw, WUC, 0);
E1000_WRITE_REG(&adapter->hw, WUFC, 0);
- pci_enable_wake(pdev, 3, 0);
- pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
- pci_save_state(pdev);
-
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
- if(manc & E1000_MANC_SMBUS_EN) {
+ if (manc & E1000_MANC_SMBUS_EN) {
manc |= E1000_MANC_ARP_EN;
E1000_WRITE_REG(&adapter->hw, MANC, manc);
- pci_enable_wake(pdev, 3, 1);
- pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
+ retval = pci_enable_wake(pdev, PCI_D3hot, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
}
}
- switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
- break;
- case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm & ~E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* Release control of h/w to f/w. If f/w is AMT enabled, this
+ * would have already happened in close and is redundant. */
+ e1000_release_hw_control(adapter);
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
return 0;
}
+#ifdef CONFIG_PM
static int
e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
- uint32_t manc, ret_val, swsm;
- uint32_t ctrl_ext;
+ int retval;
+ uint32_t manc, ret_val;
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
+ retval = pci_set_power_state(pdev, PCI_D0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error in setting power state\n");
+ e1000_pci_restore_state(adapter);
ret_val = pci_enable_device(pdev);
pci_set_master(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ retval = pci_enable_wake(pdev, PCI_D3hot, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
+ retval = pci_enable_wake(pdev, PCI_D3cold, 0);
+ if (retval)
+ DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
e1000_reset(adapter);
E1000_WRITE_REG(&adapter->hw, WUS, ~0);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e1000_up(adapter);
netif_device_attach(netdev);
- if(adapter->hw.mac_type >= e1000_82540 &&
+ if (adapter->hw.mac_type >= e1000_82540 &&
adapter->hw.media_type == e1000_media_type_copper) {
manc = E1000_READ_REG(&adapter->hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
- switch(adapter->hw.mac_type) {
- case e1000_82571:
- case e1000_82572:
- ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
- E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
- ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
- break;
- case e1000_82573:
- swsm = E1000_READ_REG(&adapter->hw, SWSM);
- E1000_WRITE_REG(&adapter->hw, SWSM,
- swsm | E1000_SWSM_DRV_LOAD);
- break;
- default:
- break;
- }
+ /* If the controller is 82573 and f/w is AMT, do not set
+ * DRV_LOAD until the interface is up. For all other cases,
+ * let the f/w know that the h/w is now under the control
+ * of the driver. */
+ if (adapter->hw.mac_type != e1000_82573 ||
+ !e1000_check_mng_mode(&adapter->hw))
+ e1000_get_hw_control(adapter);
return 0;
}
@@ -4343,6 +4732,9 @@ e1000_netpoll(struct net_device *netdev)
disable_irq(adapter->pdev->irq);
e1000_intr(adapter->pdev->irq, netdev, NULL);
e1000_clean_tx_irq(adapter, adapter->tx_ring);
+#ifndef CONFIG_E1000_NAPI
+ adapter->clean_rx(adapter, adapter->rx_ring);
+#endif
enable_irq(adapter->pdev->irq);
}
#endif
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index aac64de61437..9790db974dc1 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -47,7 +47,7 @@
BUG(); \
} else { \
msleep(x); \
- } } while(0)
+ } } while (0)
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 38695d5b4637..3768d83cd577 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -177,7 +177,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
*
* Valid Range: 100-100000 (0=off, 1=dynamic)
*
- * Default Value: 1
+ * Default Value: 8000
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
@@ -227,7 +227,7 @@ static int __devinit
e1000_validate_option(int *value, struct e1000_option *opt,
struct e1000_adapter *adapter)
{
- if(*value == OPTION_UNSET) {
+ if (*value == OPTION_UNSET) {
*value = opt->def;
return 0;
}
@@ -244,7 +244,7 @@ e1000_validate_option(int *value, struct e1000_option *opt,
}
break;
case range_option:
- if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
DPRINTK(PROBE, INFO,
"%s set to %i\n", opt->name, *value);
return 0;
@@ -254,10 +254,10 @@ e1000_validate_option(int *value, struct e1000_option *opt,
int i;
struct e1000_opt_list *ent;
- for(i = 0; i < opt->arg.l.nr; i++) {
+ for (i = 0; i < opt->arg.l.nr; i++) {
ent = &opt->arg.l.p[i];
- if(*value == ent->i) {
- if(ent->str[0] != '\0')
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
DPRINTK(PROBE, INFO, "%s\n", ent->str);
return 0;
}
@@ -291,7 +291,7 @@ void __devinit
e1000_check_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(bd >= E1000_MAX_NIC) {
+ if (bd >= E1000_MAX_NIC) {
DPRINTK(PROBE, NOTICE,
"Warning: no configuration for board #%i\n", bd);
DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
@@ -315,12 +315,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxDescriptors > bd) {
tx_ring->count = TxDescriptors[bd];
e1000_validate_option(&tx_ring->count, &opt, adapter);
- E1000_ROUNDUP(tx_ring->count,
+ E1000_ROUNDUP(tx_ring->count,
REQ_TX_DESCRIPTOR_MULTIPLE);
} else {
tx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_tx_queues; i++)
tx_ring[i].count = tx_ring->count;
}
{ /* Receive Descriptor Count */
@@ -341,12 +341,12 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxDescriptors > bd) {
rx_ring->count = RxDescriptors[bd];
e1000_validate_option(&rx_ring->count, &opt, adapter);
- E1000_ROUNDUP(rx_ring->count,
+ E1000_ROUNDUP(rx_ring->count,
REQ_RX_DESCRIPTOR_MULTIPLE);
} else {
rx_ring->count = opt.def;
}
- for (i = 0; i < adapter->num_queues; i++)
+ for (i = 0; i < adapter->num_rx_queues; i++)
rx_ring[i].count = rx_ring->count;
}
{ /* Checksum Offload Enable/Disable */
@@ -388,7 +388,7 @@ e1000_check_options(struct e1000_adapter *adapter)
e1000_validate_option(&fc, &opt, adapter);
adapter->hw.fc = adapter->hw.original_fc = fc;
} else {
- adapter->hw.fc = opt.def;
+ adapter->hw.fc = adapter->hw.original_fc = opt.def;
}
}
{ /* Transmit Interrupt Delay */
@@ -403,7 +403,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxIntDelay > bd) {
adapter->tx_int_delay = TxIntDelay[bd];
- e1000_validate_option(&adapter->tx_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_int_delay, &opt,
adapter);
} else {
adapter->tx_int_delay = opt.def;
@@ -421,7 +421,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_TxAbsIntDelay > bd) {
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
- e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
adapter);
} else {
adapter->tx_abs_int_delay = opt.def;
@@ -439,7 +439,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxIntDelay > bd) {
adapter->rx_int_delay = RxIntDelay[bd];
- e1000_validate_option(&adapter->rx_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_int_delay, &opt,
adapter);
} else {
adapter->rx_int_delay = opt.def;
@@ -457,7 +457,7 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_RxAbsIntDelay > bd) {
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
- e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
+ e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
adapter);
} else {
adapter->rx_abs_int_delay = opt.def;
@@ -475,17 +475,17 @@ e1000_check_options(struct e1000_adapter *adapter)
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- switch(adapter->itr) {
+ switch (adapter->itr) {
case 0:
- DPRINTK(PROBE, INFO, "%s turned off\n",
+ DPRINTK(PROBE, INFO, "%s turned off\n",
opt.name);
break;
case 1:
- DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
+ DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
break;
default:
- e1000_validate_option(&adapter->itr, &opt,
+ e1000_validate_option(&adapter->itr, &opt,
adapter);
break;
}
@@ -494,7 +494,7 @@ e1000_check_options(struct e1000_adapter *adapter)
}
}
- switch(adapter->hw.media_type) {
+ switch (adapter->hw.media_type) {
case e1000_media_type_fiber:
case e1000_media_type_internal_serdes:
e1000_check_fiber_options(adapter);
@@ -518,17 +518,17 @@ static void __devinit
e1000_check_fiber_options(struct e1000_adapter *adapter)
{
int bd = adapter->bd_number;
- if(num_Speed > bd) {
+ if (num_Speed > bd) {
DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
"parameter ignored\n");
}
- if(num_Duplex > bd) {
+ if (num_Duplex > bd) {
DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
"parameter ignored\n");
}
- if((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
+ if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
"not valid for fiber adapters, "
"parameter ignored\n");
@@ -545,7 +545,7 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
static void __devinit
e1000_check_copper_options(struct e1000_adapter *adapter)
{
- int speed, dplx;
+ int speed, dplx, an;
int bd = adapter->bd_number;
{ /* Speed */
@@ -584,6 +584,12 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = dplx_list }}
};
+ if (e1000_check_phy_reset_block(&adapter->hw)) {
+ DPRINTK(PROBE, INFO,
+ "Link active due to SoL/IDER Session. "
+ "Speed/Duplex/AutoNeg parameter ignored.\n");
+ return;
+ }
if (num_Duplex > bd) {
dplx = Duplex[bd];
e1000_validate_option(&dplx, &opt, adapter);
@@ -592,7 +598,7 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
}
}
- if((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
+ if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
DPRINTK(PROBE, INFO,
"AutoNeg specified along with Speed or Duplex, "
"parameter ignored\n");
@@ -641,15 +647,19 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
.p = an_list }}
};
- int an = AutoNeg[bd];
- e1000_validate_option(&an, &opt, adapter);
+ if (num_AutoNeg > bd) {
+ an = AutoNeg[bd];
+ e1000_validate_option(&an, &opt, adapter);
+ } else {
+ an = opt.def;
+ }
adapter->hw.autoneg_advertised = an;
}
switch (speed + dplx) {
case 0:
adapter->hw.autoneg = adapter->fc_autoneg = 1;
- if((num_Speed > bd) && (speed != 0 || dplx != 0))
+ if ((num_Speed > bd) && (speed != 0 || dplx != 0))
DPRINTK(PROBE, INFO,
"Speed and duplex autonegotiation enabled\n");
break;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index f5a4dd7d8564..e5c5cd2a2712 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -140,13 +140,6 @@ static int __init do_e2100_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: e21_close() handles free_irq */
- iounmap(ei_status.mem);
- release_region(dev->base_addr, E21_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init e2100_probe(int unit)
{
@@ -463,6 +456,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: e21_close() handles free_irq */
+ iounmap(ei_status.mem);
+ release_region(dev->base_addr, E21_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 50f8e23bb9e5..6b0ab1eac3fb 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -155,13 +155,6 @@ static int __init do_es_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, ES_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init es_probe(int unit)
{
@@ -456,6 +449,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, ES_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index c39344adecce..3682ec61e8a8 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -101,6 +101,7 @@
* 0.46: 20 Oct 2005: Add irq optimization modes.
* 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
* 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
+ * 0.49: 10 Dec 2005: Fix tso for large buffers.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -112,7 +113,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.48"
+#define FORCEDETH_VERSION "0.49"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -349,6 +350,8 @@ typedef union _ring_type {
#define NV_TX2_VALID (1<<31)
#define NV_TX2_TSO (1<<28)
#define NV_TX2_TSO_SHIFT 14
+#define NV_TX2_TSO_MAX_SHIFT 14
+#define NV_TX2_TSO_MAX_SIZE (1<<NV_TX2_TSO_MAX_SHIFT)
#define NV_TX2_CHECKSUM_L3 (1<<27)
#define NV_TX2_CHECKSUM_L4 (1<<26)
@@ -408,15 +411,15 @@ typedef union _ring_type {
#define NV_WATCHDOG_TIMEO (5*HZ)
#define RX_RING 128
-#define TX_RING 64
+#define TX_RING 256
/*
* If your nic mysteriously hangs then try to reduce the limits
* to 1/0: It might be required to set NV_TX_LASTPACKET in the
* last valid ring entry. But this would be impossible to
* implement - probably a disassembly error.
*/
-#define TX_LIMIT_STOP 63
-#define TX_LIMIT_START 62
+#define TX_LIMIT_STOP 255
+#define TX_LIMIT_START 254
/* rx/tx mac addr + type + vlan + align + slack*/
#define NV_RX_HEADERS (64)
@@ -535,6 +538,7 @@ struct fe_priv {
unsigned int next_tx, nic_tx;
struct sk_buff *tx_skbuff[TX_RING];
dma_addr_t tx_dma[TX_RING];
+ unsigned int tx_dma_len[TX_RING];
u32 tx_flags;
};
@@ -935,6 +939,7 @@ static void nv_init_tx(struct net_device *dev)
else
np->tx_ring.ex[i].FlagLen = 0;
np->tx_skbuff[i] = NULL;
+ np->tx_dma[i] = 0;
}
}
@@ -945,30 +950,27 @@ static int nv_init_ring(struct net_device *dev)
return nv_alloc_rx(dev);
}
-static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
+static int nv_release_txskb(struct net_device *dev, unsigned int skbnr)
{
struct fe_priv *np = netdev_priv(dev);
- struct sk_buff *skb = np->tx_skbuff[skbnr];
- unsigned int j, entry, fragments;
-
- dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
- dev->name, skbnr, np->tx_skbuff[skbnr]);
-
- entry = skbnr;
- if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
- for (j = fragments; j >= 1; j--) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
- pci_unmap_page(np->pci_dev, np->tx_dma[entry],
- frag->size,
- PCI_DMA_TODEVICE);
- entry = (entry - 1) % TX_RING;
- }
+
+ dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d\n",
+ dev->name, skbnr);
+
+ if (np->tx_dma[skbnr]) {
+ pci_unmap_page(np->pci_dev, np->tx_dma[skbnr],
+ np->tx_dma_len[skbnr],
+ PCI_DMA_TODEVICE);
+ np->tx_dma[skbnr] = 0;
+ }
+
+ if (np->tx_skbuff[skbnr]) {
+ dev_kfree_skb_irq(np->tx_skbuff[skbnr]);
+ np->tx_skbuff[skbnr] = NULL;
+ return 1;
+ } else {
+ return 0;
}
- pci_unmap_single(np->pci_dev, np->tx_dma[entry],
- skb->len - skb->data_len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(skb);
- np->tx_skbuff[skbnr] = NULL;
}
static void nv_drain_tx(struct net_device *dev)
@@ -981,10 +983,8 @@ static void nv_drain_tx(struct net_device *dev)
np->tx_ring.orig[i].FlagLen = 0;
else
np->tx_ring.ex[i].FlagLen = 0;
- if (np->tx_skbuff[i]) {
- nv_release_txskb(dev, i);
+ if (nv_release_txskb(dev, i))
np->stats.tx_dropped++;
- }
}
}
@@ -1021,68 +1021,105 @@ static void drain_ring(struct net_device *dev)
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
+ u32 tx_flags = 0;
u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
unsigned int fragments = skb_shinfo(skb)->nr_frags;
- unsigned int nr = (np->next_tx + fragments) % TX_RING;
+ unsigned int nr = (np->next_tx - 1) % TX_RING;
+ unsigned int start_nr = np->next_tx % TX_RING;
unsigned int i;
+ u32 offset = 0;
+ u32 bcnt;
+ u32 size = skb->len-skb->data_len;
+ u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+
+ /* add fragments to entries count */
+ for (i = 0; i < fragments; i++) {
+ entries += (skb_shinfo(skb)->frags[i].size >> NV_TX2_TSO_MAX_SHIFT) +
+ ((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
+ }
spin_lock_irq(&np->lock);
- if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
+ if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) {
spin_unlock_irq(&np->lock);
netif_stop_queue(dev);
return NETDEV_TX_BUSY;
}
- np->tx_skbuff[nr] = skb;
-
- if (fragments) {
- dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
- /* setup descriptors in reverse order */
- for (i = fragments; i >= 1; i--) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
- np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
- PCI_DMA_TODEVICE);
+ /* setup the header buffer */
+ do {
+ bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+ nr = (nr + 1) % TX_RING;
+
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
+ PCI_DMA_TODEVICE);
+ np->tx_dma_len[nr] = bcnt;
+
+ 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]);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+ } 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;
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+ }
+ tx_flags = np->tx_flags;
+ offset += bcnt;
+ size -= bcnt;
+ } while(size);
+
+ /* setup the fragments */
+ for (i = 0; i < fragments; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ u32 size = frag->size;
+ offset = 0;
+
+ do {
+ bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
+ nr = (nr + 1) % TX_RING;
+
+ np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
+ PCI_DMA_TODEVICE);
+ np->tx_dma_len[nr] = bcnt;
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]);
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
} 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;
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
}
-
- nr = (nr - 1) % TX_RING;
+ offset += bcnt;
+ size -= bcnt;
+ } while (size);
+ }
- if (np->desc_ver == DESC_VER_1)
- tx_flags_extra &= ~NV_TX_LASTPACKET;
- else
- tx_flags_extra &= ~NV_TX2_LASTPACKET;
- }
+ /* set last fragment flag */
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+ np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+ } else {
+ np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
}
+ np->tx_skbuff[nr] = skb;
+
#ifdef NETIF_F_TSO
if (skb_shinfo(skb)->tso_size)
- tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
+ tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
else
#endif
- tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+ tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
- PCI_DMA_TODEVICE);
-
+ /* set tx flags */
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]);
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
} 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;
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
+ np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
}
- dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
- dev->name, np->next_tx, tx_flags_extra);
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
+ dev->name, np->next_tx, entries, tx_flags_extra);
{
int j;
for (j=0; j<64; j++) {
@@ -1093,7 +1130,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
dprintk("\n");
}
- np->next_tx += 1 + fragments;
+ np->next_tx += entries;
dev->trans_start = jiffies;
spin_unlock_irq(&np->lock);
@@ -1140,7 +1177,6 @@ static void nv_tx_done(struct net_device *dev)
np->stats.tx_packets++;
np->stats.tx_bytes += skb->len;
}
- nv_release_txskb(dev, i);
}
} else {
if (Flags & NV_TX2_LASTPACKET) {
@@ -1156,9 +1192,9 @@ static void nv_tx_done(struct net_device *dev)
np->stats.tx_packets++;
np->stats.tx_bytes += skb->len;
}
- nv_release_txskb(dev, i);
}
}
+ nv_release_txskb(dev, i);
np->nic_tx++;
}
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
@@ -2456,7 +2492,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
#ifdef NETIF_F_TSO
- /* disabled dev->features |= NETIF_F_TSO; */
+ dev->features |= NETIF_F_TSO;
#endif
}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0f030b73cbb3..0c18dbd67d3b 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -2,7 +2,8 @@
* drivers/net/gianfar.c
*
* Gianfar Ethernet Driver
- * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560
+ * This driver is designed for the non-CPM ethernet controllers
+ * on the 85xx and 83xx family of integrated processors
* Based on 8260_io/fcc_enet.c
*
* Author: Andy Fleming
@@ -22,8 +23,6 @@
* B-V +1.62
*
* Theory of operation
- * This driver is designed for the non-CPM ethernet controllers
- * on the 85xx and 83xx family of integrated processors
*
* The driver is initialized through platform_device. Structures which
* define the configuration needed by the board are defined in a
@@ -85,6 +84,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <linux/in.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -110,7 +110,7 @@
#endif
const char gfar_driver_name[] = "Gianfar Ethernet";
-const char gfar_driver_version[] = "1.2";
+const char gfar_driver_version[] = "1.3";
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -139,6 +139,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
+void gfar_halt(struct net_device *dev);
+void gfar_start(struct net_device *dev);
+static void gfar_clear_exact_match(struct net_device *dev);
+static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
extern struct ethtool_ops gfar_ethtool_ops;
@@ -146,12 +150,10 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL");
-int gfar_uses_fcb(struct gfar_private *priv)
+/* Returns 1 if incoming frames use an FCB */
+static inline int gfar_uses_fcb(struct gfar_private *priv)
{
- if (priv->vlan_enable || priv->rx_csum_enable)
- return 1;
- else
- return 0;
+ return (priv->vlan_enable || priv->rx_csum_enable);
}
/* Set up the ethernet device structure, private data,
@@ -320,15 +322,10 @@ static int gfar_probe(struct platform_device *pdev)
else
priv->padding = 0;
- dev->hard_header_len += priv->padding;
-
if (dev->features & NETIF_F_IP_CSUM)
dev->hard_header_len += GMAC_FCB_LEN;
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
-#ifdef CONFIG_GFAR_BUFSTASH
- priv->rx_stash_size = STASH_LENGTH;
-#endif
priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
@@ -350,6 +347,9 @@ static int gfar_probe(struct platform_device *pdev)
goto register_fail;
}
+ /* Create all the sysfs files */
+ gfar_init_sysfs(dev);
+
/* Print out the device info */
printk(KERN_INFO DEVICE_NAME, dev->name);
for (idx = 0; idx < 6; idx++)
@@ -357,8 +357,7 @@ static int gfar_probe(struct platform_device *pdev)
printk("\n");
/* Even more device info helps when determining which kernel */
- /* provided which set of benchmarks. Since this is global for all */
- /* devices, we only print it once */
+ /* provided which set of benchmarks. */
#ifdef CONFIG_GFAR_NAPI
printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name);
#else
@@ -400,12 +399,15 @@ static int init_phy(struct net_device *dev)
priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
SUPPORTED_1000baseT_Full : 0;
struct phy_device *phydev;
+ char phy_id[BUS_ID_SIZE];
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0);
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
+
+ phydev = phy_connect(dev, phy_id, &adjust_link, 0);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -463,19 +465,9 @@ static void init_registers(struct net_device *dev)
/* Initialize the max receive buffer length */
gfar_write(&priv->regs->mrblr, priv->rx_buffer_size);
-#ifdef CONFIG_GFAR_BUFSTASH
- /* If we are stashing buffers, we need to set the
- * extraction length to the size of the buffer */
- gfar_write(&priv->regs->attreli, priv->rx_stash_size << 16);
-#endif
-
/* Initialize the Minimum Frame Length Register */
gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS);
- /* Setup Attributes so that snooping is on for rx */
- gfar_write(&priv->regs->attr, ATTR_INIT_SETTINGS);
- gfar_write(&priv->regs->attreli, ATTRELI_INIT_SETTINGS);
-
/* Assign the TBI an address which won't conflict with the PHYs */
gfar_write(&priv->regs->tbipa, TBIPA_VALUE);
}
@@ -577,8 +569,7 @@ static void free_skb_resources(struct gfar_private *priv)
for (i = 0; i < priv->rx_ring_size; i++) {
if (priv->rx_skbuff[i]) {
dma_unmap_single(NULL, rxbdp->bufPtr,
- priv->rx_buffer_size
- + RXBUF_ALIGNMENT,
+ priv->rx_buffer_size,
DMA_FROM_DEVICE);
dev_kfree_skb_any(priv->rx_skbuff[i]);
@@ -636,6 +627,7 @@ int startup_gfar(struct net_device *dev)
struct gfar *regs = priv->regs;
int err = 0;
u32 rctrl = 0;
+ u32 attrs = 0;
gfar_write(&regs->imask, IMASK_INIT_CLEAR);
@@ -795,18 +787,50 @@ int startup_gfar(struct net_device *dev)
if (priv->rx_csum_enable)
rctrl |= RCTRL_CHECKSUMMING;
- if (priv->extended_hash)
+ if (priv->extended_hash) {
rctrl |= RCTRL_EXTHASH;
+ gfar_clear_exact_match(dev);
+ rctrl |= RCTRL_EMEN;
+ }
+
if (priv->vlan_enable)
rctrl |= RCTRL_VLAN;
+ if (priv->padding) {
+ rctrl &= ~RCTRL_PAL_MASK;
+ rctrl |= RCTRL_PADDING(priv->padding);
+ }
+
/* Init rctrl based on our settings */
gfar_write(&priv->regs->rctrl, rctrl);
if (dev->features & NETIF_F_IP_CSUM)
gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
+ /* Set the extraction length and index */
+ attrs = ATTRELI_EL(priv->rx_stash_size) |
+ ATTRELI_EI(priv->rx_stash_index);
+
+ gfar_write(&priv->regs->attreli, attrs);
+
+ /* Start with defaults, and add stashing or locking
+ * depending on the approprate variables */
+ attrs = ATTR_INIT_SETTINGS;
+
+ if (priv->bd_stash_en)
+ attrs |= ATTR_BDSTASH;
+
+ if (priv->rx_stash_size != 0)
+ attrs |= ATTR_BUFSTASH;
+
+ gfar_write(&priv->regs->attr, attrs);
+
+ gfar_write(&priv->regs->fifo_tx_thr, priv->fifo_threshold);
+ gfar_write(&priv->regs->fifo_tx_starve, priv->fifo_starve);
+ gfar_write(&priv->regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
+
+ /* Start the controller */
gfar_start(dev);
return 0;
@@ -851,34 +875,32 @@ static int gfar_enet_open(struct net_device *dev)
return err;
}
-static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
+static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
{
struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
memset(fcb, 0, GMAC_FCB_LEN);
- /* Flag the bd so the controller looks for the FCB */
- bdp->status |= TXBD_TOE;
-
return fcb;
}
static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
{
- int len;
+ u8 flags = 0;
/* If we're here, it's a IP packet with a TCP or UDP
* payload. We set it to checksum, using a pseudo-header
* we provide
*/
- fcb->ip = 1;
- fcb->tup = 1;
- fcb->ctu = 1;
- fcb->nph = 1;
+ flags = TXFCB_DEFAULT;
- /* Notify the controller what the protocol is */
- if (skb->nh.iph->protocol == IPPROTO_UDP)
- fcb->udp = 1;
+ /* Tell the controller what the protocol is */
+ /* And provide the already calculated phcs */
+ if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ flags |= TXFCB_UDP;
+ fcb->phcs = skb->h.uh->check;
+ } else
+ fcb->phcs = skb->h.th->check;
/* l3os is the distance between the start of the
* frame (skb->data) and the start of the IP hdr.
@@ -887,17 +909,12 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN);
fcb->l4os = (u16)(skb->h.raw - skb->nh.raw);
- len = skb->nh.iph->tot_len - fcb->l4os;
-
- /* Provide the pseudoheader csum */
- fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr,
- skb->nh.iph->daddr, len,
- skb->nh.iph->protocol, 0);
+ fcb->flags = flags;
}
-void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
+void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
{
- fcb->vln = 1;
+ fcb->flags |= TXFCB_VLN;
fcb->vlctl = vlan_tx_tag_get(skb);
}
@@ -908,6 +925,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
struct txfcb *fcb = NULL;
struct txbd8 *txbdp;
+ u16 status;
/* Update transmit stats */
priv->stats.tx_bytes += skb->len;
@@ -919,19 +937,22 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
txbdp = priv->cur_tx;
/* Clear all but the WRAP status flags */
- txbdp->status &= TXBD_WRAP;
+ status = txbdp->status & TXBD_WRAP;
/* Set up checksumming */
- if ((dev->features & NETIF_F_IP_CSUM)
- && (CHECKSUM_HW == skb->ip_summed)) {
+ if (likely((dev->features & NETIF_F_IP_CSUM)
+ && (CHECKSUM_HW == skb->ip_summed))) {
fcb = gfar_add_fcb(skb, txbdp);
+ status |= TXBD_TOE;
gfar_tx_checksum(skb, fcb);
}
if (priv->vlan_enable &&
unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
- if (NULL == fcb)
+ if (unlikely(NULL == fcb)) {
fcb = gfar_add_fcb(skb, txbdp);
+ status |= TXBD_TOE;
+ }
gfar_tx_vlan(skb, fcb);
}
@@ -949,14 +970,16 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
(priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
/* Flag the BD as interrupt-causing */
- txbdp->status |= TXBD_INTERRUPT;
+ status |= TXBD_INTERRUPT;
/* Flag the BD as ready to go, last in frame, and */
/* in need of CRC */
- txbdp->status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
+ status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
dev->trans_start = jiffies;
+ txbdp->status = status;
+
/* If this was the last BD in the ring, the next one */
/* is at the beginning of the ring */
if (txbdp->status & TXBD_WRAP)
@@ -1010,21 +1033,7 @@ static struct net_device_stats * gfar_get_stats(struct net_device *dev)
/* Changes the mac address if the controller is not running. */
int gfar_set_mac_address(struct net_device *dev)
{
- struct gfar_private *priv = netdev_priv(dev);
- int i;
- char tmpbuf[MAC_ADDR_LEN];
- u32 tempval;
-
- /* Now copy it into the mac registers backwards, cuz */
- /* little endian is silly */
- for (i = 0; i < MAC_ADDR_LEN; i++)
- tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->dev_addr[i];
-
- gfar_write(&priv->regs->macstnaddr1, *((u32 *) (tmpbuf)));
-
- tempval = *((u32 *) (tmpbuf + 4));
-
- gfar_write(&priv->regs->macstnaddr2, tempval);
+ gfar_set_mac_for_addr(dev, 0, dev->dev_addr);
return 0;
}
@@ -1110,7 +1119,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
INCREMENTAL_BUFFER_SIZE;
/* Only stop and start the controller if it isn't already
- * stopped */
+ * stopped, and we changed something */
if ((oldsize != tempsize) && (dev->flags & IFF_UP))
stop_gfar(dev);
@@ -1220,6 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs)
struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
{
+ unsigned int alignamount;
struct gfar_private *priv = netdev_priv(dev);
struct sk_buff *skb = NULL;
unsigned int timeout = SKB_ALLOC_TIMEOUT;
@@ -1231,18 +1241,18 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp)
if (NULL == skb)
return NULL;
+ alignamount = RXBUF_ALIGNMENT -
+ (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1));
+
/* We need the data buffer to be aligned properly. We will reserve
* as many bytes as needed to align the data properly
*/
- skb_reserve(skb,
- RXBUF_ALIGNMENT -
- (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)));
+ skb_reserve(skb, alignamount);
skb->dev = dev;
bdp->bufPtr = dma_map_single(NULL, skb->data,
- priv->rx_buffer_size + RXBUF_ALIGNMENT,
- DMA_FROM_DEVICE);
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
bdp->length = 0;
@@ -1350,7 +1360,7 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
/* If valid headers were found, and valid sums
* were verified, then we tell the kernel that no
* checksumming is necessary. Otherwise, it is */
- if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu)
+ if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
@@ -1401,7 +1411,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
skb->protocol = eth_type_trans(skb, dev);
/* Send the packet up the stack */
- if (unlikely(priv->vlgrp && fcb->vln))
+ if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl);
else
ret = RECEIVE(skb);
@@ -1620,6 +1630,7 @@ static void adjust_link(struct net_device *dev)
spin_lock_irqsave(&priv->lock, flags);
if (phydev->link) {
u32 tempval = gfar_read(&regs->maccfg2);
+ u32 ecntrl = gfar_read(&regs->ecntrl);
/* Now we make sure that we can be in full duplex mode.
* If not, we operate in half-duplex mode. */
@@ -1644,6 +1655,13 @@ static void adjust_link(struct net_device *dev)
case 10:
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_MII);
+
+ /* Reduced mode distinguishes
+ * between 10 and 100 */
+ if (phydev->speed == SPEED_100)
+ ecntrl |= ECNTRL_R100;
+ else
+ ecntrl &= ~(ECNTRL_R100);
break;
default:
if (netif_msg_link(priv))
@@ -1657,6 +1675,7 @@ static void adjust_link(struct net_device *dev)
}
gfar_write(&regs->maccfg2, tempval);
+ gfar_write(&regs->ecntrl, ecntrl);
if (!priv->oldlink) {
new_state = 1;
@@ -1721,6 +1740,9 @@ static void gfar_set_multi(struct net_device *dev)
gfar_write(&regs->gaddr6, 0xffffffff);
gfar_write(&regs->gaddr7, 0xffffffff);
} else {
+ int em_num;
+ int idx;
+
/* zero out the hash */
gfar_write(&regs->igaddr0, 0x0);
gfar_write(&regs->igaddr1, 0x0);
@@ -1739,18 +1761,47 @@ static void gfar_set_multi(struct net_device *dev)
gfar_write(&regs->gaddr6, 0x0);
gfar_write(&regs->gaddr7, 0x0);
+ /* If we have extended hash tables, we need to
+ * clear the exact match registers to prepare for
+ * setting them */
+ if (priv->extended_hash) {
+ em_num = GFAR_EM_NUM + 1;
+ gfar_clear_exact_match(dev);
+ idx = 1;
+ } else {
+ idx = 0;
+ em_num = 0;
+ }
+
if(dev->mc_count == 0)
return;
/* Parse the list, and set the appropriate bits */
for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
- gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
+ if (idx < em_num) {
+ gfar_set_mac_for_addr(dev, idx,
+ mc_ptr->dmi_addr);
+ idx++;
+ } else
+ gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr);
}
}
return;
}
+
+/* Clears each of the exact match registers to zero, so they
+ * don't interfere with normal reception */
+static void gfar_clear_exact_match(struct net_device *dev)
+{
+ int idx;
+ u8 zero_arr[MAC_ADDR_LEN] = {0,0,0,0,0,0};
+
+ for(idx = 1;idx < GFAR_EM_NUM + 1;idx++)
+ gfar_set_mac_for_addr(dev, idx, (u8 *)zero_arr);
+}
+
/* Set the appropriate hash bit for the given addr */
/* The algorithm works like so:
* 1) Take the Destination Address (ie the multicast address), and
@@ -1781,6 +1832,32 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr)
return;
}
+
+/* There are multiple MAC Address register pairs on some controllers
+ * This function sets the numth pair to a given address
+ */
+static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ int idx;
+ char tmpbuf[MAC_ADDR_LEN];
+ u32 tempval;
+ u32 *macptr = &priv->regs->macstnaddr1;
+
+ macptr += num*2;
+
+ /* Now copy it into the mac registers backwards, cuz */
+ /* little endian is silly */
+ for (idx = 0; idx < MAC_ADDR_LEN; idx++)
+ tmpbuf[MAC_ADDR_LEN - 1 - idx] = addr[idx];
+
+ gfar_write(macptr, *((u32 *) (tmpbuf)));
+
+ tempval = *((u32 *) (tmpbuf + 4));
+
+ gfar_write(macptr+1, tempval);
+}
+
/* GFAR error interrupt handler */
static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs)
{
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 5065ba82cb76..cb9d66ac3ab9 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -90,12 +90,26 @@ extern const char gfar_driver_version[];
#define GFAR_RX_MAX_RING_SIZE 256
#define GFAR_TX_MAX_RING_SIZE 256
+#define GFAR_MAX_FIFO_THRESHOLD 511
+#define GFAR_MAX_FIFO_STARVE 511
+#define GFAR_MAX_FIFO_STARVE_OFF 511
+
#define DEFAULT_RX_BUFFER_SIZE 1536
#define TX_RING_MOD_MASK(size) (size-1)
#define RX_RING_MOD_MASK(size) (size-1)
#define JUMBO_BUFFER_SIZE 9728
#define JUMBO_FRAME_SIZE 9600
+#define DEFAULT_FIFO_TX_THR 0x100
+#define DEFAULT_FIFO_TX_STARVE 0x40
+#define DEFAULT_FIFO_TX_STARVE_OFF 0x80
+#define DEFAULT_BD_STASH 1
+#define DEFAULT_STASH_LENGTH 64
+#define DEFAULT_STASH_INDEX 0
+
+/* The number of Exact Match registers */
+#define GFAR_EM_NUM 15
+
/* Latency of interface clock in nanoseconds */
/* Interface clock latency , in this case, means the
* time described by a value of 1 in the interrupt
@@ -112,11 +126,11 @@ extern const char gfar_driver_version[];
#define DEFAULT_TX_COALESCE 1
#define DEFAULT_TXCOUNT 16
-#define DEFAULT_TXTIME 400
+#define DEFAULT_TXTIME 4
#define DEFAULT_RX_COALESCE 1
#define DEFAULT_RXCOUNT 16
-#define DEFAULT_RXTIME 400
+#define DEFAULT_RXTIME 4
#define TBIPA_VALUE 0x1f
#define MIIMCFG_INIT_VALUE 0x00000007
@@ -147,6 +161,7 @@ extern const char gfar_driver_version[];
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
+#define ECNTRL_R100 0x00000008
#define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE
@@ -181,10 +196,12 @@ extern const char gfar_driver_version[];
#define RCTRL_PRSDEP_MASK 0x000000c0
#define RCTRL_PRSDEP_INIT 0x000000c0
#define RCTRL_PROM 0x00000008
+#define RCTRL_EMEN 0x00000002
#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \
| RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
#define RCTRL_EXTHASH (RCTRL_GHTX)
#define RCTRL_VLAN (RCTRL_PRSDEP_INIT)
+#define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK)
#define RSTAT_CLEAR_RHALT 0x00800000
@@ -251,28 +268,26 @@ extern const char gfar_driver_version[];
IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
| IMASK_PERR)
+/* Fifo management */
+#define FIFO_TX_THR_MASK 0x01ff
+#define FIFO_TX_STARVE_MASK 0x01ff
+#define FIFO_TX_STARVE_OFF_MASK 0x01ff
/* Attribute fields */
/* This enables rx snooping for buffers and descriptors */
-#ifdef CONFIG_GFAR_BDSTASH
#define ATTR_BDSTASH 0x00000800
-#else
-#define ATTR_BDSTASH 0x00000000
-#endif
-#ifdef CONFIG_GFAR_BUFSTASH
#define ATTR_BUFSTASH 0x00004000
-#define STASH_LENGTH 64
-#else
-#define ATTR_BUFSTASH 0x00000000
-#endif
#define ATTR_SNOOPING 0x000000c0
-#define ATTR_INIT_SETTINGS (ATTR_SNOOPING \
- | ATTR_BDSTASH | ATTR_BUFSTASH)
+#define ATTR_INIT_SETTINGS ATTR_SNOOPING
#define ATTRELI_INIT_SETTINGS 0x0
+#define ATTRELI_EL_MASK 0x3fff0000
+#define ATTRELI_EL(x) (x << 16)
+#define ATTRELI_EI_MASK 0x00003fff
+#define ATTRELI_EI(x) (x)
/* TxBD status field bits */
@@ -328,6 +343,7 @@ extern const char gfar_driver_version[];
#define RXFCB_CTU 0x0400
#define RXFCB_EIP 0x0200
#define RXFCB_ETU 0x0100
+#define RXFCB_CSUM_MASK 0x0f00
#define RXFCB_PERR_MASK 0x000c
#define RXFCB_PERR_BADL3 0x0008
@@ -339,14 +355,7 @@ struct txbd8
};
struct txfcb {
- u8 vln:1,
- ip:1,
- ip6:1,
- tup:1,
- udp:1,
- cip:1,
- ctu:1,
- nph:1;
+ u8 flags;
u8 reserved;
u8 l4os; /* Level 4 Header Offset */
u8 l3os; /* Level 3 Header Offset */
@@ -362,14 +371,7 @@ struct rxbd8
};
struct rxfcb {
- u16 vln:1,
- ip:1,
- ip6:1,
- tup:1,
- cip:1,
- ctu:1,
- eip:1,
- etu:1;
+ u16 flags;
u8 rq; /* Receive Queue index */
u8 pro; /* Layer 4 Protocol */
u16 reserved;
@@ -688,12 +690,17 @@ struct gfar_private {
spinlock_t lock;
unsigned int rx_buffer_size;
unsigned int rx_stash_size;
+ unsigned int rx_stash_index;
unsigned int tx_ring_size;
unsigned int rx_ring_size;
+ unsigned int fifo_threshold;
+ unsigned int fifo_starve;
+ unsigned int fifo_starve_off;
unsigned char vlan_enable:1,
rx_csum_enable:1,
- extended_hash:1;
+ extended_hash:1,
+ bd_stash_en:1;
unsigned short padding;
struct vlan_group *vlgrp;
/* Info structure initialized by board setup code */
@@ -711,14 +718,14 @@ struct gfar_private {
uint32_t msg_enable;
};
-extern inline u32 gfar_read(volatile unsigned *addr)
+static inline u32 gfar_read(volatile unsigned *addr)
{
u32 val;
val = in_be32(addr);
return val;
}
-extern inline void gfar_write(volatile unsigned *addr, u32 val)
+static inline void gfar_write(volatile unsigned *addr, u32 val)
{
out_be32(addr, val);
}
@@ -731,6 +738,6 @@ extern void stop_gfar(struct net_device *dev);
extern void gfar_halt(struct net_device *dev);
extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
int enable, u32 regnum, u32 read);
-void gfar_setup_stashing(struct net_device *dev);
+void gfar_init_sysfs(struct net_device *dev);
#endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index cfa3cd7c91a0..765e810620fe 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -125,7 +125,7 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = {
static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
{
struct gfar_private *priv = netdev_priv(dev);
-
+
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
else
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 04a462c2a5b7..74e52fcbf806 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -128,6 +128,7 @@ int gfar_mdio_probe(struct device *dev)
struct gianfar_mdio_data *pdata;
struct gfar_mii *regs;
struct mii_bus *new_bus;
+ struct resource *r;
int err = 0;
if (NULL == dev)
@@ -151,8 +152,10 @@ int gfar_mdio_probe(struct device *dev)
return -ENODEV;
}
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
/* Set the PHY base address */
- regs = (struct gfar_mii *) ioremap(pdata->paddr,
+ regs = (struct gfar_mii *) ioremap(r->start,
sizeof (struct gfar_mii));
if (NULL == regs) {
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
index e85eb216fb5b..d527cf2f9c1d 100644
--- a/drivers/net/gianfar_mii.h
+++ b/drivers/net/gianfar_mii.h
@@ -24,6 +24,7 @@
#define MII_READ_COMMAND 0x00000001
#define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \
+ | SUPPORTED_10baseT_Full \
| SUPPORTED_100baseT_Half \
| SUPPORTED_100baseT_Full \
| SUPPORTED_Autoneg \
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c
new file mode 100644
index 000000000000..51ef181b1368
--- /dev/null
+++ b/drivers/net/gianfar_sysfs.c
@@ -0,0 +1,311 @@
+/*
+ * drivers/net/gianfar_sysfs.c
+ *
+ * Gianfar Ethernet Driver
+ * This driver is designed for the non-CPM ethernet controllers
+ * on the 85xx and 83xx family of integrated processors
+ * Based on 8260_io/fcc_enet.c
+ *
+ * Author: Andy Fleming
+ * Maintainer: Kumar Gala (galak@kernel.crashing.org)
+ *
+ * Copyright (c) 2002-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.
+ *
+ * Sysfs file creation and management
+ */
+
+#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/init.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+
+#include <asm/uaccess.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include "gianfar.h"
+
+#define GFAR_ATTR(_name) \
+static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \
+static ssize_t gfar_set_##_name(struct class_device *cdev, \
+ const char *buf, size_t count); \
+static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name)
+
+#define GFAR_CREATE_FILE(_dev, _name) \
+ class_device_create_file(&_dev->class_dev, &class_device_attr_##_name)
+
+GFAR_ATTR(bd_stash);
+GFAR_ATTR(rx_stash_size);
+GFAR_ATTR(rx_stash_index);
+GFAR_ATTR(fifo_threshold);
+GFAR_ATTR(fifo_starve);
+GFAR_ATTR(fifo_starve_off);
+
+#define to_net_dev(cd) container_of(cd, struct net_device, class_dev)
+
+static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off");
+}
+
+static ssize_t gfar_set_bd_stash(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ int new_setting = 0;
+ u32 temp;
+ unsigned long flags;
+
+ /* Find out the new setting */
+ if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1))
+ new_setting = 1;
+ else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1))
+ new_setting = 0;
+ else
+ return count;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* Set the new stashing value */
+ priv->bd_stash_en = new_setting;
+
+ temp = gfar_read(&priv->regs->attr);
+
+ if (new_setting)
+ temp |= ATTR_BDSTASH;
+ else
+ temp &= ~(ATTR_BDSTASH);
+
+ gfar_write(&priv->regs->attr, temp);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%d\n", priv->rx_stash_size);
+}
+
+static ssize_t gfar_set_rx_stash_size(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned int length = simple_strtoul(buf, NULL, 0);
+ u32 temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (length > priv->rx_buffer_size)
+ return count;
+
+ if (length == priv->rx_stash_size)
+ return count;
+
+ priv->rx_stash_size = length;
+
+ temp = gfar_read(&priv->regs->attreli);
+ temp &= ~ATTRELI_EL_MASK;
+ temp |= ATTRELI_EL(length);
+ gfar_write(&priv->regs->attreli, temp);
+
+ /* Turn stashing on/off as appropriate */
+ temp = gfar_read(&priv->regs->attr);
+
+ if (length)
+ temp |= ATTR_BUFSTASH;
+ else
+ temp &= ~(ATTR_BUFSTASH);
+
+ gfar_write(&priv->regs->attr, temp);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+
+/* Stashing will only be enabled when rx_stash_size != 0 */
+static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%d\n", priv->rx_stash_index);
+}
+
+static ssize_t gfar_set_rx_stash_index(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned short index = simple_strtoul(buf, NULL, 0);
+ u32 temp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (index > priv->rx_stash_size)
+ return count;
+
+ if (index == priv->rx_stash_index)
+ return count;
+
+ priv->rx_stash_index = index;
+
+ temp = gfar_read(&priv->regs->attreli);
+ temp &= ~ATTRELI_EI_MASK;
+ temp |= ATTRELI_EI(index);
+ gfar_write(&priv->regs->attreli, flags);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%d\n", priv->fifo_threshold);
+}
+
+static ssize_t gfar_set_fifo_threshold(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned int length = simple_strtoul(buf, NULL, 0);
+ u32 temp;
+ unsigned long flags;
+
+ if (length > GFAR_MAX_FIFO_THRESHOLD)
+ return count;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->fifo_threshold = length;
+
+ temp = gfar_read(&priv->regs->fifo_tx_thr);
+ temp &= ~FIFO_TX_THR_MASK;
+ temp |= length;
+ gfar_write(&priv->regs->fifo_tx_thr, temp);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%d\n", priv->fifo_starve);
+}
+
+
+static ssize_t gfar_set_fifo_starve(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned int num = simple_strtoul(buf, NULL, 0);
+ u32 temp;
+ unsigned long flags;
+
+ if (num > GFAR_MAX_FIFO_STARVE)
+ return count;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->fifo_starve = num;
+
+ temp = gfar_read(&priv->regs->fifo_tx_starve);
+ temp &= ~FIFO_TX_STARVE_MASK;
+ temp |= num;
+ gfar_write(&priv->regs->fifo_tx_starve, temp);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+
+ return sprintf(buf, "%d\n", priv->fifo_starve_off);
+}
+
+static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev,
+ const char *buf, size_t count)
+{
+ struct net_device *dev = to_net_dev(cdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned int num = simple_strtoul(buf, NULL, 0);
+ u32 temp;
+ unsigned long flags;
+
+ if (num > GFAR_MAX_FIFO_STARVE_OFF)
+ return count;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->fifo_starve_off = num;
+
+ temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff);
+ temp &= ~FIFO_TX_STARVE_OFF_MASK;
+ temp |= num;
+ gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+void gfar_init_sysfs(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ /* Initialize the default values */
+ priv->rx_stash_size = DEFAULT_STASH_LENGTH;
+ priv->rx_stash_index = DEFAULT_STASH_INDEX;
+ priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
+ priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
+ priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
+ priv->bd_stash_en = DEFAULT_BD_STASH;
+
+ /* Create our sysfs files */
+ GFAR_CREATE_FILE(dev, bd_stash);
+ GFAR_CREATE_FILE(dev, rx_stash_size);
+ GFAR_CREATE_FILE(dev, rx_stash_index);
+ GFAR_CREATE_FILE(dev, fifo_threshold);
+ GFAR_CREATE_FILE(dev, fifo_starve);
+ GFAR_CREATE_FILE(dev, fifo_starve_off);
+
+}
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 90999867a32c..102c1f0b90da 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -456,11 +456,6 @@ out:
/* ----------------------------------------------------------------------- */
-static int sixpack_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -671,6 +666,7 @@ static int sixpack_open(struct tty_struct *tty)
/* Done. We have linked the TTY line to a channel. */
tty->disc_data = sp;
+ tty->receive_room = 65536;
/* Now we're ready to register. */
if (register_netdev(dev))
@@ -802,7 +798,6 @@ static struct tty_ldisc sp_ldisc = {
.close = sixpack_close,
.ioctl = sixpack_ioctl,
.receive_buf = sixpack_receive_buf,
- .receive_room = sixpack_receive_room,
.write_wakeup = sixpack_write_wakeup,
};
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 3e9accf137e7..dc5e9d59deed 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -515,6 +515,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
count = kiss_esc(p, (unsigned char *)ax->xbuff, len);
}
}
+ spin_unlock_bh(&ax->buflock);
set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
@@ -752,6 +753,7 @@ static int mkiss_open(struct tty_struct *tty)
ax->tty = tty;
tty->disc_data = ax;
+ tty->receive_room = 65535;
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -939,11 +941,6 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
tty->driver->unthrottle(tty);
}
-static int mkiss_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
@@ -982,7 +979,6 @@ static struct tty_ldisc ax_ldisc = {
.close = mkiss_close,
.ioctl = mkiss_ioctl,
.receive_buf = mkiss_receive_buf,
- .receive_room = mkiss_receive_room,
.write_wakeup = mkiss_write_wakeup
};
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 0abf5dd08b4c..74e167e7dea7 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -138,12 +138,6 @@ static int __init do_hpp_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: hpp_close() handles free_irq */
- release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init hp_plus_probe(int unit)
{
@@ -473,6 +467,12 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: hpp_close() handles free_irq */
+ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 59cf841b14ab..cf9fb3698a6b 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -102,12 +102,6 @@ static int __init do_hp_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init hp_probe(int unit)
{
@@ -444,6 +438,12 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index e92c17f6931c..55c7ed608391 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -276,7 +276,7 @@ static void hp100_RegisterDump(struct net_device *dev);
* Convert an address in a kernel buffer to a bus/phys/dma address.
* This work *only* for memory fragments part of lp->page_vaddr,
* because it was properly DMA allocated via pci_alloc_consistent(),
- * so we just need to "retreive" the original mapping to bus/phys/dma
+ * so we just need to "retrieve" the original mapping to bus/phys/dma
* address - Jean II */
static inline dma_addr_t virt_to_whatever(struct net_device *dev, u32 * ptr)
{
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c
index 08703d6f934c..d8410634bcaf 100644
--- a/drivers/net/hplance.c
+++ b/drivers/net/hplance.c
@@ -150,7 +150,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
lp->lance.name = (char*)d->name; /* discards const, shut up gcc */
lp->lance.base = va;
lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
- lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */
+ lp->lance.lance_init_block = NULL; /* LANCE addr of same RAM */
lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */
lp->lance.irq = d->ipl;
lp->lance.writerap = hplance_writerap;
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 644edbff4f94..c2dae6092c4c 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -110,6 +110,7 @@ struct emac_regs {
#define EMAC_MR1_TFS_2K 0x00080000
#define EMAC_MR1_TR0_MULT 0x00008000
#define EMAC_MR1_JPSM 0x00000000
+#define EMAC_MR1_MWSW_001 0x00000000
#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR0_MULT)
#else
#define EMAC_MR1_RFS_4K 0x00180000
@@ -130,7 +131,7 @@ struct emac_regs {
(freq) <= 83 ? EMAC_MR1_OBCI_83 : \
(freq) <= 100 ? EMAC_MR1_OBCI_100 : EMAC_MR1_OBCI_100P)
#define EMAC_MR1_BASE(opb) (EMAC_MR1_TFS_2K | EMAC_MR1_TR | \
- EMAC_MR1_MWSW_001 | EMAC_MR1_OBCI(opb))
+ EMAC_MR1_OBCI(opb))
#endif
/* EMACx_TMR0 */
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 1da8a66f91e1..591c5864ffb1 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -408,7 +408,7 @@ static int emac_configure(struct ocp_enet_private *dev)
/* Mode register */
r = EMAC_MR1_BASE(emac_opb_mhz()) | EMAC_MR1_VLE | EMAC_MR1_IST;
if (dev->phy.duplex == DUPLEX_FULL)
- r |= EMAC_MR1_FDE;
+ r |= EMAC_MR1_FDE | EMAC_MR1_MWSW_001;
dev->stop_timeout = STOP_TIMEOUT_10;
switch (dev->phy.speed) {
case SPEED_1000:
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
new file mode 100644
index 000000000000..1b699259b4ec
--- /dev/null
+++ b/drivers/net/ifb.c
@@ -0,0 +1,294 @@
+/* drivers/net/ifb.c:
+
+ The purpose of this driver is to provide a device that allows
+ for sharing of resources:
+
+ 1) qdiscs/policies that are per device as opposed to system wide.
+ ifb allows for a device which can be redirected to thus providing
+ an impression of sharing.
+
+ 2) Allows for queueing incoming traffic for shaping instead of
+ dropping.
+
+ The original concept is based on what is known as the IMQ
+ driver initially written by Martin Devera, later rewritten
+ by Patrick McHardy and then maintained by Andre Correa.
+
+ You need the tc action mirror or redirect to feed this device
+ packets.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the 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: Jamal Hadi Salim (2005)
+
+*/
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <net/pkt_sched.h>
+
+#define TX_TIMEOUT (2*HZ)
+
+#define TX_Q_LIMIT 32
+struct ifb_private {
+ struct net_device_stats stats;
+ struct tasklet_struct ifb_tasklet;
+ int tasklet_pending;
+ /* mostly debug stats leave in for now */
+ unsigned long st_task_enter; /* tasklet entered */
+ unsigned long st_txq_refl_try; /* transmit queue refill attempt */
+ unsigned long st_rxq_enter; /* receive queue entered */
+ unsigned long st_rx2tx_tran; /* receive to trasmit transfers */
+ unsigned long st_rxq_notenter; /*receiveQ not entered, resched */
+ unsigned long st_rx_frm_egr; /* received from egress path */
+ unsigned long st_rx_frm_ing; /* received from ingress path */
+ unsigned long st_rxq_check;
+ unsigned long st_rxq_rsch;
+ struct sk_buff_head rq;
+ struct sk_buff_head tq;
+};
+
+static int numifbs = 1;
+
+static void ri_tasklet(unsigned long dev);
+static int ifb_xmit(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *ifb_get_stats(struct net_device *dev);
+static int ifb_open(struct net_device *dev);
+static int ifb_close(struct net_device *dev);
+
+static void ri_tasklet(unsigned long dev)
+{
+
+ struct net_device *_dev = (struct net_device *)dev;
+ struct ifb_private *dp = netdev_priv(_dev);
+ struct net_device_stats *stats = &dp->stats;
+ struct sk_buff *skb;
+
+ dp->st_task_enter++;
+ if ((skb = skb_peek(&dp->tq)) == NULL) {
+ dp->st_txq_refl_try++;
+ if (spin_trylock(&_dev->xmit_lock)) {
+ dp->st_rxq_enter++;
+ while ((skb = skb_dequeue(&dp->rq)) != NULL) {
+ skb_queue_tail(&dp->tq, skb);
+ dp->st_rx2tx_tran++;
+ }
+ spin_unlock(&_dev->xmit_lock);
+ } else {
+ /* reschedule */
+ dp->st_rxq_notenter++;
+ goto resched;
+ }
+ }
+
+ while ((skb = skb_dequeue(&dp->tq)) != NULL) {
+ u32 from = G_TC_FROM(skb->tc_verd);
+
+ skb->tc_verd = 0;
+ skb->tc_verd = SET_TC_NCLS(skb->tc_verd);
+ stats->tx_packets++;
+ stats->tx_bytes +=skb->len;
+ if (from & AT_EGRESS) {
+ dp->st_rx_frm_egr++;
+ dev_queue_xmit(skb);
+ } else if (from & AT_INGRESS) {
+
+ dp->st_rx_frm_ing++;
+ netif_rx(skb);
+ } else {
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+ }
+ }
+
+ if (spin_trylock(&_dev->xmit_lock)) {
+ dp->st_rxq_check++;
+ if ((skb = skb_peek(&dp->rq)) == NULL) {
+ dp->tasklet_pending = 0;
+ if (netif_queue_stopped(_dev))
+ netif_wake_queue(_dev);
+ } else {
+ dp->st_rxq_rsch++;
+ spin_unlock(&_dev->xmit_lock);
+ goto resched;
+ }
+ spin_unlock(&_dev->xmit_lock);
+ } else {
+resched:
+ dp->tasklet_pending = 1;
+ tasklet_schedule(&dp->ifb_tasklet);
+ }
+
+}
+
+static void __init ifb_setup(struct net_device *dev)
+{
+ /* Initialize the device structure. */
+ dev->get_stats = ifb_get_stats;
+ dev->hard_start_xmit = ifb_xmit;
+ dev->open = &ifb_open;
+ dev->stop = &ifb_close;
+
+ /* Fill in device structure with ethernet-generic values. */
+ ether_setup(dev);
+ dev->tx_queue_len = TX_Q_LIMIT;
+ dev->change_mtu = NULL;
+ dev->flags |= IFF_NOARP;
+ dev->flags &= ~IFF_MULTICAST;
+ SET_MODULE_OWNER(dev);
+ random_ether_addr(dev->dev_addr);
+}
+
+static int ifb_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ struct net_device_stats *stats = &dp->stats;
+ int ret = 0;
+ u32 from = G_TC_FROM(skb->tc_verd);
+
+ stats->tx_packets++;
+ stats->tx_bytes+=skb->len;
+
+ if (!from || !skb->input_dev) {
+dropped:
+ dev_kfree_skb(skb);
+ stats->rx_dropped++;
+ return ret;
+ } else {
+ /*
+ * note we could be going
+ * ingress -> egress or
+ * egress -> ingress
+ */
+ skb->dev = skb->input_dev;
+ skb->input_dev = dev;
+ if (from & AT_INGRESS) {
+ skb_pull(skb, skb->dev->hard_header_len);
+ } else {
+ if (!(from & AT_EGRESS)) {
+ goto dropped;
+ }
+ }
+ }
+
+ if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) {
+ netif_stop_queue(dev);
+ }
+
+ dev->trans_start = jiffies;
+ skb_queue_tail(&dp->rq, skb);
+ if (!dp->tasklet_pending) {
+ dp->tasklet_pending = 1;
+ tasklet_schedule(&dp->ifb_tasklet);
+ }
+
+ return ret;
+}
+
+static struct net_device_stats *ifb_get_stats(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+ struct net_device_stats *stats = &dp->stats;
+
+ pr_debug("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n",
+ dp->st_task_enter, dp->st_txq_refl_try, dp->st_rxq_enter,
+ dp->st_rx2tx_tran dp->st_rxq_notenter, dp->st_rx_frm_egr,
+ dp->st_rx_frm_ing, dp->st_rxq_check, dp->st_rxq_rsch );
+
+ return stats;
+}
+
+static struct net_device **ifbs;
+
+/* Number of ifb devices to be set up by this module. */
+module_param(numifbs, int, 0);
+MODULE_PARM_DESC(numifbs, "Number of ifb devices");
+
+static int ifb_close(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+
+ tasklet_kill(&dp->ifb_tasklet);
+ netif_stop_queue(dev);
+ skb_queue_purge(&dp->rq);
+ skb_queue_purge(&dp->tq);
+ return 0;
+}
+
+static int ifb_open(struct net_device *dev)
+{
+ struct ifb_private *dp = netdev_priv(dev);
+
+ tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev);
+ skb_queue_head_init(&dp->rq);
+ skb_queue_head_init(&dp->tq);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int __init ifb_init_one(int index)
+{
+ struct net_device *dev_ifb;
+ int err;
+
+ dev_ifb = alloc_netdev(sizeof(struct ifb_private),
+ "ifb%d", ifb_setup);
+
+ if (!dev_ifb)
+ return -ENOMEM;
+
+ if ((err = register_netdev(dev_ifb))) {
+ free_netdev(dev_ifb);
+ dev_ifb = NULL;
+ } else {
+ ifbs[index] = dev_ifb;
+ }
+
+ return err;
+}
+
+static void ifb_free_one(int index)
+{
+ unregister_netdev(ifbs[index]);
+ free_netdev(ifbs[index]);
+}
+
+static int __init ifb_init_module(void)
+{
+ int i, err = 0;
+ ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
+ if (!ifbs)
+ return -ENOMEM;
+ for (i = 0; i < numifbs && !err; i++)
+ err = ifb_init_one(i);
+ if (err) {
+ while (--i >= 0)
+ ifb_free_one(i);
+ }
+
+ return err;
+}
+
+static void __exit ifb_cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < numifbs; i++)
+ ifb_free_one(i);
+ kfree(ifbs);
+}
+
+module_init(ifb_init_module);
+module_exit(ifb_cleanup_module);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamal Hadi Salim");
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index d54156f11e61..7a081346f079 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -1,4 +1,3 @@
-
menu "Infrared-port device drivers"
depends on IRDA!=n
@@ -156,7 +155,7 @@ comment "Old Serial dongle support"
config DONGLE_OLD
bool "Old Serial dongle support"
- depends on (IRTTY_OLD || IRPORT_SIR) && BROKEN_ON_SMP
+ depends on IRPORT_SIR && BROKEN_ON_SMP
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index e7a8b7f7f5dd..72cbfdc9cfcc 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -45,4 +45,4 @@ obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
# The SIR helper module
-sir-dev-objs := sir_core.o sir_dev.o sir_dongle.o sir_kthread.o
+sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index c22c0517883c..fa176ffb4ad5 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1539,7 +1539,6 @@ static void irda_usb_disconnect(struct usb_interface *intf)
* USB device callbacks
*/
static struct usb_driver irda_driver = {
- .owner = THIS_MODULE,
.name = "irda-usb",
.probe = irda_usb_probe,
.disconnect = irda_usb_disconnect,
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 3d016a498e1d..6070195b87bd 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -285,19 +285,6 @@ static void irport_start(struct irport_cb *self)
}
/*
- * Function irport_probe (void)
- *
- * Start IO port
- *
- */
-int irport_probe(int iobase)
-{
- IRDA_DEBUG(4, "%s(), iobase=%#x\n", __FUNCTION__, iobase);
-
- return 0;
-}
-
-/*
* Function irport_get_fcr (speed)
*
* Compute value of fcr
@@ -382,7 +369,7 @@ static void irport_change_speed(void *priv, __u32 speed)
* we cannot use schedule_timeout() when we are in interrupt context
*
*/
-int __irport_change_speed(struct irda_task *task)
+static int __irport_change_speed(struct irda_task *task)
{
struct irport_cb *self;
__u32 speed = (__u32) task->param;
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index b8d112348ba4..101750bf210f 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -289,22 +289,6 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
}
/*
- * Function irtty_receive_room (tty)
- *
- * Used by the TTY to find out how much data we can receive at a time
- *
-*/
-static int irtty_receive_room(struct tty_struct *tty)
-{
- struct sirtty_cb *priv = tty->disc_data;
-
- IRDA_ASSERT(priv != NULL, return 0;);
- IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
-
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
-/*
* Function irtty_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
@@ -534,6 +518,7 @@ static int irtty_open(struct tty_struct *tty)
dev->priv = priv;
tty->disc_data = priv;
+ tty->receive_room = 65536;
up(&irtty_sem);
@@ -605,7 +590,6 @@ static struct tty_ldisc irda_ldisc = {
.ioctl = irtty_ioctl,
.poll = NULL,
.receive_buf = irtty_receive_buf,
- .receive_room = irtty_receive_room,
.write_wakeup = irtty_write_wakeup,
.owner = THIS_MODULE,
};
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index f0b8bc3637e5..f69fb4cec76f 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -133,8 +133,6 @@ extern int sirdev_put_dongle(struct sir_dev *self);
extern void sirdev_enable_rx(struct sir_dev *dev);
extern int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
-extern int __init irda_thread_create(void);
-extern void __exit irda_thread_join(void);
/* inline helpers */
diff --git a/drivers/net/irda/sir_core.c b/drivers/net/irda/sir_core.c
deleted file mode 100644
index a49f910c835b..000000000000
--- a/drivers/net/irda/sir_core.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*********************************************************************
- *
- * sir_core.c: module core for irda-sir abstraction layer
- *
- * Copyright (c) 2002 Martin Diehl
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <net/irda/irda.h>
-
-#include "sir-dev.h"
-
-/***************************************************************************/
-
-MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
-MODULE_DESCRIPTION("IrDA SIR core");
-MODULE_LICENSE("GPL");
-
-/***************************************************************************/
-
-EXPORT_SYMBOL(irda_register_dongle);
-EXPORT_SYMBOL(irda_unregister_dongle);
-
-EXPORT_SYMBOL(sirdev_get_instance);
-EXPORT_SYMBOL(sirdev_put_instance);
-
-EXPORT_SYMBOL(sirdev_set_dongle);
-EXPORT_SYMBOL(sirdev_write_complete);
-EXPORT_SYMBOL(sirdev_receive);
-
-EXPORT_SYMBOL(sirdev_raw_write);
-EXPORT_SYMBOL(sirdev_raw_read);
-EXPORT_SYMBOL(sirdev_set_dtr_rts);
-
-static int __init sir_core_init(void)
-{
- return irda_thread_create();
-}
-
-static void __exit sir_core_exit(void)
-{
- irda_thread_join();
-}
-
-module_init(sir_core_init);
-module_exit(sir_core_exit);
-
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index df22b8b532e7..ea7c9464d46a 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -60,6 +60,7 @@ int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type)
up(&dev->fsm.sem);
return err;
}
+EXPORT_SYMBOL(sirdev_set_dongle);
/* used by dongle drivers for dongle programming */
@@ -94,6 +95,7 @@ int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len)
spin_unlock_irqrestore(&dev->tx_lock, flags);
return ret;
}
+EXPORT_SYMBOL(sirdev_raw_write);
/* seems some dongle drivers may need this */
@@ -116,6 +118,7 @@ int sirdev_raw_read(struct sir_dev *dev, char *buf, int len)
return count;
}
+EXPORT_SYMBOL(sirdev_raw_read);
int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
@@ -124,7 +127,8 @@ int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
ret = dev->drv->set_dtr_rts(dev, dtr, rts);
return ret;
}
-
+EXPORT_SYMBOL(sirdev_set_dtr_rts);
+
/**********************************************************************/
/* called from client driver - likely with bh-context - to indicate
@@ -227,6 +231,7 @@ void sirdev_write_complete(struct sir_dev *dev)
done:
spin_unlock_irqrestore(&dev->tx_lock, flags);
}
+EXPORT_SYMBOL(sirdev_write_complete);
/* called from client driver - likely with bh-context - to give us
* some more received bytes. We put them into the rx-buffer,
@@ -279,6 +284,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
return 0;
}
+EXPORT_SYMBOL(sirdev_receive);
/**********************************************************************/
@@ -641,6 +647,7 @@ out_freenetdev:
out:
return NULL;
}
+EXPORT_SYMBOL(sirdev_get_instance);
int sirdev_put_instance(struct sir_dev *dev)
{
@@ -673,4 +680,5 @@ int sirdev_put_instance(struct sir_dev *dev)
return 0;
}
+EXPORT_SYMBOL(sirdev_put_instance);
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c
index c5b76746e72b..8d225921ae7b 100644
--- a/drivers/net/irda/sir_dongle.c
+++ b/drivers/net/irda/sir_dongle.c
@@ -50,6 +50,7 @@ int irda_register_dongle(struct dongle_driver *new)
up(&dongle_list_lock);
return 0;
}
+EXPORT_SYMBOL(irda_register_dongle);
int irda_unregister_dongle(struct dongle_driver *drv)
{
@@ -58,6 +59,7 @@ int irda_unregister_dongle(struct dongle_driver *drv)
up(&dongle_list_lock);
return 0;
}
+EXPORT_SYMBOL(irda_unregister_dongle);
int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
{
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index c65054364bca..e3904d6bfecd 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -466,7 +466,7 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
return 0;
}
-int __init irda_thread_create(void)
+static int __init irda_thread_create(void)
{
struct completion startup;
int pid;
@@ -488,7 +488,7 @@ int __init irda_thread_create(void)
return 0;
}
-void __exit irda_thread_join(void)
+static void __exit irda_thread_join(void)
{
if (irda_rq_queue.thread) {
flush_irda_queue();
@@ -499,3 +499,10 @@ void __exit irda_thread_join(void)
}
}
+module_init(irda_thread_create);
+module_exit(irda_thread_join);
+
+MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
+MODULE_DESCRIPTION("IrDA SIR core");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 3961a754e920..31867e4b891b 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -1152,7 +1152,6 @@ static int stir_resume(struct usb_interface *intf)
* USB device callbacks
*/
static struct usb_driver irda_driver = {
- .owner = THIS_MODULE,
.name = "stir4200",
.probe = stir_probe,
.disconnect = stir_disconnect,
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 741aecc655df..a82a4ba8de4f 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -577,8 +577,8 @@ struct ring_descr_hw {
struct {
u8 addr_res[3];
volatile u8 status; /* descriptor status */
- } rd_s __attribute__((packed));
- } rd_u __attribute((packed));
+ } __attribute__((packed)) rd_s;
+ } __attribute((packed)) rd_u;
} __attribute__ ((packed));
#define rd_addr rd_u.addr
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 77eadf84cb2c..f0f04be989d6 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -590,9 +590,9 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs)
{
struct veth_lpevent *veth_event = (struct veth_lpevent *)event;
- if (event->xFlags.xFunction == HvLpEvent_Function_Ack)
+ if (hvlpevent_is_ack(event))
veth_handle_ack(veth_event);
- else if (event->xFlags.xFunction == HvLpEvent_Function_Int)
+ else
veth_handle_int(veth_event);
}
diff --git a/drivers/net/ixp2000/Kconfig b/drivers/net/ixp2000/Kconfig
new file mode 100644
index 000000000000..2fec2415651f
--- /dev/null
+++ b/drivers/net/ixp2000/Kconfig
@@ -0,0 +1,6 @@
+config ENP2611_MSF_NET
+ tristate "Radisys ENP2611 MSF network interface support"
+ depends on ARCH_ENP2611
+ help
+ This is a driver for the MSF network interface unit in
+ the IXP2400 on the Radisys ENP2611 platform.
diff --git a/drivers/net/ixp2000/Makefile b/drivers/net/ixp2000/Makefile
new file mode 100644
index 000000000000..fd38351ceaa7
--- /dev/null
+++ b/drivers/net/ixp2000/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ENP2611_MSF_NET) += enp2611_mod.o
+
+enp2611_mod-objs := caleb.o enp2611.o ixp2400-msf.o ixpdev.o pm3386.o
diff --git a/drivers/net/ixp2000/caleb.c b/drivers/net/ixp2000/caleb.c
new file mode 100644
index 000000000000..3595e107df22
--- /dev/null
+++ b/drivers/net/ixp2000/caleb.c
@@ -0,0 +1,137 @@
+/*
+ * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/delay.h>
+#include <asm/io.h>
+#include "caleb.h"
+
+#define CALEB_IDLO 0x00
+#define CALEB_IDHI 0x01
+#define CALEB_RID 0x02
+#define CALEB_RESET 0x03
+#define CALEB_INTREN0 0x04
+#define CALEB_INTREN1 0x05
+#define CALEB_INTRSTAT0 0x06
+#define CALEB_INTRSTAT1 0x07
+#define CALEB_PORTEN 0x08
+#define CALEB_BURST 0x09
+#define CALEB_PORTPAUS 0x0A
+#define CALEB_PORTPAUSD 0x0B
+#define CALEB_PHY0RX 0x10
+#define CALEB_PHY1RX 0x11
+#define CALEB_PHY0TX 0x12
+#define CALEB_PHY1TX 0x13
+#define CALEB_IXPRX_HI_CNTR 0x15
+#define CALEB_PHY0RX_HI_CNTR 0x16
+#define CALEB_PHY1RX_HI_CNTR 0x17
+#define CALEB_IXPRX_CNTR 0x18
+#define CALEB_PHY0RX_CNTR 0x19
+#define CALEB_PHY1RX_CNTR 0x1A
+#define CALEB_IXPTX_CNTR 0x1B
+#define CALEB_PHY0TX_CNTR 0x1C
+#define CALEB_PHY1TX_CNTR 0x1D
+#define CALEB_DEBUG0 0x1E
+#define CALEB_DEBUG1 0x1F
+
+
+static u8 caleb_reg_read(int reg)
+{
+ u8 value;
+
+ value = *((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg));
+
+// printk(KERN_INFO "caleb_reg_read(%d) = %.2x\n", reg, value);
+
+ return value;
+}
+
+static void caleb_reg_write(int reg, u8 value)
+{
+ u8 dummy;
+
+// printk(KERN_INFO "caleb_reg_write(%d, %.2x)\n", reg, value);
+
+ *((volatile u8 *)(ENP2611_CALEB_VIRT_BASE + reg)) = value;
+
+ dummy = *((volatile u8 *)ENP2611_CALEB_VIRT_BASE);
+ __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
+}
+
+
+void caleb_reset(void)
+{
+ /*
+ * Perform a chip reset.
+ */
+ caleb_reg_write(CALEB_RESET, 0x02);
+ udelay(1);
+
+ /*
+ * Enable all interrupt sources. This is needed to get
+ * meaningful results out of the status bits (register 6
+ * and 7.)
+ */
+ caleb_reg_write(CALEB_INTREN0, 0xff);
+ caleb_reg_write(CALEB_INTREN1, 0x07);
+
+ /*
+ * Set RX and TX FIFO thresholds to 1.5kb.
+ */
+ caleb_reg_write(CALEB_PHY0RX, 0x11);
+ caleb_reg_write(CALEB_PHY1RX, 0x11);
+ caleb_reg_write(CALEB_PHY0TX, 0x11);
+ caleb_reg_write(CALEB_PHY1TX, 0x11);
+
+ /*
+ * Program SPI-3 burst size.
+ */
+ caleb_reg_write(CALEB_BURST, 0); // 64-byte RBUF mpackets
+// caleb_reg_write(CALEB_BURST, 1); // 128-byte RBUF mpackets
+// caleb_reg_write(CALEB_BURST, 2); // 256-byte RBUF mpackets
+}
+
+void caleb_enable_rx(int port)
+{
+ u8 temp;
+
+ temp = caleb_reg_read(CALEB_PORTEN);
+ temp |= 1 << port;
+ caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_disable_rx(int port)
+{
+ u8 temp;
+
+ temp = caleb_reg_read(CALEB_PORTEN);
+ temp &= ~(1 << port);
+ caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_enable_tx(int port)
+{
+ u8 temp;
+
+ temp = caleb_reg_read(CALEB_PORTEN);
+ temp |= 1 << (port + 4);
+ caleb_reg_write(CALEB_PORTEN, temp);
+}
+
+void caleb_disable_tx(int port)
+{
+ u8 temp;
+
+ temp = caleb_reg_read(CALEB_PORTEN);
+ temp &= ~(1 << (port + 4));
+ caleb_reg_write(CALEB_PORTEN, temp);
+}
diff --git a/drivers/net/ixp2000/caleb.h b/drivers/net/ixp2000/caleb.h
new file mode 100644
index 000000000000..e93a1ef5b8a3
--- /dev/null
+++ b/drivers/net/ixp2000/caleb.h
@@ -0,0 +1,22 @@
+/*
+ * Helper functions for the SPI-3 bridge FPGA on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __CALEB_H
+#define __CALEB_H
+
+void caleb_reset(void);
+void caleb_enable_rx(int port);
+void caleb_disable_rx(int port);
+void caleb_enable_tx(int port);
+void caleb_disable_tx(int port);
+
+
+#endif
diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c
new file mode 100644
index 000000000000..d82651a97bae
--- /dev/null
+++ b/drivers/net/ixp2000/enp2611.c
@@ -0,0 +1,245 @@
+/*
+ * IXP2400 MSF network device driver for the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <asm/arch/uengine.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include "ixpdev.h"
+#include "caleb.h"
+#include "ixp2400-msf.h"
+#include "pm3386.h"
+
+/***********************************************************************
+ * The Radisys ENP2611 is a PCI form factor board with three SFP GBIC
+ * slots, connected via two PMC/Sierra 3386s and an SPI-3 bridge FPGA
+ * to the IXP2400.
+ *
+ * +-------------+
+ * SFP GBIC #0 ---+ | +---------+
+ * | PM3386 #0 +-------+ |
+ * SFP GBIC #1 ---+ | | "Caleb" | +---------+
+ * +-------------+ | | | |
+ * | SPI-3 +---------+ IXP2400 |
+ * +-------------+ | bridge | | |
+ * SFP GBIC #2 ---+ | | FPGA | +---------+
+ * | PM3386 #1 +-------+ |
+ * | | +---------+
+ * +-------------+
+ * ^ ^ ^
+ * | 1.25Gbaud | 104MHz | 104MHz
+ * | SERDES ea. | SPI-3 ea. | SPI-3
+ *
+ ***********************************************************************/
+static struct ixp2400_msf_parameters enp2611_msf_parameters =
+{
+ .rx_mode = IXP2400_RX_MODE_UTOPIA_POS |
+ IXP2400_RX_MODE_1x32 |
+ IXP2400_RX_MODE_MPHY |
+ IXP2400_RX_MODE_MPHY_32 |
+ IXP2400_RX_MODE_MPHY_POLLED_STATUS |
+ IXP2400_RX_MODE_MPHY_LEVEL3 |
+ IXP2400_RX_MODE_RBUF_SIZE_64,
+
+ .rxclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
+
+ .rx_poll_ports = 3,
+
+ .rx_channel_mode = {
+ IXP2400_PORT_RX_MODE_MASTER |
+ IXP2400_PORT_RX_MODE_POS_PHY |
+ IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+ IXP2400_PORT_RX_MODE_ODD_PARITY |
+ IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_RX_MODE_MASTER |
+ IXP2400_PORT_RX_MODE_POS_PHY |
+ IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+ IXP2400_PORT_RX_MODE_ODD_PARITY |
+ IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_RX_MODE_MASTER |
+ IXP2400_PORT_RX_MODE_POS_PHY |
+ IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+ IXP2400_PORT_RX_MODE_ODD_PARITY |
+ IXP2400_PORT_RX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_RX_MODE_MASTER |
+ IXP2400_PORT_RX_MODE_POS_PHY |
+ IXP2400_PORT_RX_MODE_POS_PHY_L3 |
+ IXP2400_PORT_RX_MODE_ODD_PARITY |
+ IXP2400_PORT_RX_MODE_2_CYCLE_DECODE
+ },
+
+ .tx_mode = IXP2400_TX_MODE_UTOPIA_POS |
+ IXP2400_TX_MODE_1x32 |
+ IXP2400_TX_MODE_MPHY |
+ IXP2400_TX_MODE_MPHY_32 |
+ IXP2400_TX_MODE_MPHY_POLLED_STATUS |
+ IXP2400_TX_MODE_MPHY_LEVEL3 |
+ IXP2400_TX_MODE_TBUF_SIZE_64,
+
+ .txclk01_multiplier = IXP2400_PLL_MULTIPLIER_16,
+
+ .tx_poll_ports = 3,
+
+ .tx_channel_mode = {
+ IXP2400_PORT_TX_MODE_MASTER |
+ IXP2400_PORT_TX_MODE_POS_PHY |
+ IXP2400_PORT_TX_MODE_ODD_PARITY |
+ IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_TX_MODE_MASTER |
+ IXP2400_PORT_TX_MODE_POS_PHY |
+ IXP2400_PORT_TX_MODE_ODD_PARITY |
+ IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_TX_MODE_MASTER |
+ IXP2400_PORT_TX_MODE_POS_PHY |
+ IXP2400_PORT_TX_MODE_ODD_PARITY |
+ IXP2400_PORT_TX_MODE_2_CYCLE_DECODE,
+
+ IXP2400_PORT_TX_MODE_MASTER |
+ IXP2400_PORT_TX_MODE_POS_PHY |
+ IXP2400_PORT_TX_MODE_ODD_PARITY |
+ IXP2400_PORT_TX_MODE_2_CYCLE_DECODE
+ }
+};
+
+struct enp2611_ixpdev_priv
+{
+ struct ixpdev_priv ixpdev_priv;
+ struct net_device_stats stats;
+};
+
+static struct net_device *nds[3];
+static struct timer_list link_check_timer;
+
+static struct net_device_stats *enp2611_get_stats(struct net_device *dev)
+{
+ struct enp2611_ixpdev_priv *ip = netdev_priv(dev);
+
+ pm3386_get_stats(ip->ixpdev_priv.channel, &(ip->stats));
+
+ return &(ip->stats);
+}
+
+/* @@@ Poll the SFP moddef0 line too. */
+/* @@@ Try to use the pm3386 DOOL interrupt as well. */
+static void enp2611_check_link_status(unsigned long __dummy)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ struct net_device *dev;
+ int status;
+
+ dev = nds[i];
+
+ status = pm3386_is_link_up(i);
+ if (status && !netif_carrier_ok(dev)) {
+ /* @@@ Should report autonegotiation status. */
+ printk(KERN_INFO "%s: NIC Link is Up\n", dev->name);
+
+ pm3386_enable_tx(i);
+ caleb_enable_tx(i);
+ netif_carrier_on(dev);
+ } else if (!status && netif_carrier_ok(dev)) {
+ printk(KERN_INFO "%s: NIC Link is Down\n", dev->name);
+
+ netif_carrier_off(dev);
+ caleb_disable_tx(i);
+ pm3386_disable_tx(i);
+ }
+ }
+
+ link_check_timer.expires = jiffies + HZ / 10;
+ add_timer(&link_check_timer);
+}
+
+static void enp2611_set_port_admin_status(int port, int up)
+{
+ if (up) {
+ caleb_enable_rx(port);
+
+ pm3386_set_carrier(port, 1);
+ pm3386_enable_rx(port);
+ } else {
+ caleb_disable_tx(port);
+ pm3386_disable_tx(port);
+ /* @@@ Flush out pending packets. */
+ pm3386_set_carrier(port, 0);
+
+ pm3386_disable_rx(port);
+ caleb_disable_rx(port);
+ }
+}
+
+static int __init enp2611_init_module(void)
+{
+ int i;
+
+ if (!machine_is_enp2611())
+ return -ENODEV;
+
+ caleb_reset();
+ pm3386_reset();
+
+ for (i = 0; i < 3; i++) {
+ nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv));
+ if (nds[i] == NULL) {
+ while (--i >= 0)
+ free_netdev(nds[i]);
+ return -ENOMEM;
+ }
+
+ SET_MODULE_OWNER(nds[i]);
+ nds[i]->get_stats = enp2611_get_stats;
+ pm3386_init_port(i);
+ pm3386_get_mac(i, nds[i]->dev_addr);
+ }
+
+ ixp2400_msf_init(&enp2611_msf_parameters);
+
+ if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) {
+ for (i = 0; i < 3; i++)
+ free_netdev(nds[i]);
+ return -EINVAL;
+ }
+
+ init_timer(&link_check_timer);
+ link_check_timer.function = enp2611_check_link_status;
+ link_check_timer.expires = jiffies;
+ add_timer(&link_check_timer);
+
+ return 0;
+}
+
+static void __exit enp2611_cleanup_module(void)
+{
+ int i;
+
+ del_timer_sync(&link_check_timer);
+
+ ixpdev_deinit();
+ for (i = 0; i < 3; i++)
+ free_netdev(nds[i]);
+}
+
+module_init(enp2611_init_module);
+module_exit(enp2611_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ixp2000/ixp2400-msf.c b/drivers/net/ixp2000/ixp2400-msf.c
new file mode 100644
index 000000000000..48a3a891d3a4
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400-msf.c
@@ -0,0 +1,213 @@
+/*
+ * Generic library functions for the MSF (Media and Switch Fabric) unit
+ * found on the Intel IXP2400 network processor.
+ *
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/hardware.h>
+#include <asm/arch/ixp2000-regs.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include "ixp2400-msf.h"
+
+/*
+ * This is the Intel recommended PLL init procedure as described on
+ * page 340 of the IXP2400/IXP2800 Programmer's Reference Manual.
+ */
+static void ixp2400_pll_init(struct ixp2400_msf_parameters *mp)
+{
+ int rx_dual_clock;
+ int tx_dual_clock;
+ u32 value;
+
+ /*
+ * If the RX mode is not 1x32, we have to enable both RX PLLs
+ * (#0 and #1.) The same thing for the TX direction.
+ */
+ rx_dual_clock = !!(mp->rx_mode & IXP2400_RX_MODE_WIDTH_MASK);
+ tx_dual_clock = !!(mp->tx_mode & IXP2400_TX_MODE_WIDTH_MASK);
+
+ /*
+ * Read initial value.
+ */
+ value = ixp2000_reg_read(IXP2000_MSF_CLK_CNTRL);
+
+ /*
+ * Put PLLs in powerdown and bypass mode.
+ */
+ value |= 0x0000f0f0;
+ ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+ /*
+ * Set single or dual clock mode bits.
+ */
+ value &= ~0x03000000;
+ value |= (rx_dual_clock << 24) | (tx_dual_clock << 25);
+
+ /*
+ * Set multipliers.
+ */
+ value &= ~0x00ff0000;
+ value |= mp->rxclk01_multiplier << 16;
+ value |= mp->rxclk23_multiplier << 18;
+ value |= mp->txclk01_multiplier << 20;
+ value |= mp->txclk23_multiplier << 22;
+
+ /*
+ * And write value.
+ */
+ ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+ /*
+ * Disable PLL bypass mode.
+ */
+ value &= ~(0x00005000 | rx_dual_clock << 13 | tx_dual_clock << 15);
+ ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+ /*
+ * Turn on PLLs.
+ */
+ value &= ~(0x00000050 | rx_dual_clock << 5 | tx_dual_clock << 7);
+ ixp2000_reg_write(IXP2000_MSF_CLK_CNTRL, value);
+
+ /*
+ * Wait for PLLs to lock. There are lock status bits, but IXP2400
+ * erratum #65 says that these lock bits should not be relied upon
+ * as they might not accurately reflect the true state of the PLLs.
+ */
+ udelay(100);
+}
+
+/*
+ * Needed according to p480 of Programmer's Reference Manual.
+ */
+static void ixp2400_msf_free_rbuf_entries(struct ixp2400_msf_parameters *mp)
+{
+ int size_bits;
+ int i;
+
+ /*
+ * Work around IXP2400 erratum #69 (silent RBUF-to-DRAM transfer
+ * corruption) in the Intel-recommended way: do not add the RBUF
+ * elements susceptible to corruption to the freelist.
+ */
+ size_bits = mp->rx_mode & IXP2400_RX_MODE_RBUF_SIZE_MASK;
+ if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_64) {
+ for (i = 1; i < 128; i++) {
+ if (i == 9 || i == 18 || i == 27)
+ continue;
+ ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+ }
+ } else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_128) {
+ for (i = 1; i < 64; i++) {
+ if (i == 4 || i == 9 || i == 13)
+ continue;
+ ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+ }
+ } else if (size_bits == IXP2400_RX_MODE_RBUF_SIZE_256) {
+ for (i = 1; i < 32; i++) {
+ if (i == 2 || i == 4 || i == 6)
+ continue;
+ ixp2000_reg_write(IXP2000_MSF_RBUF_ELEMENT_DONE, i);
+ }
+ }
+}
+
+static u32 ixp2400_msf_valid_channels(u32 reg)
+{
+ u32 channels;
+
+ channels = 0;
+ switch (reg & IXP2400_RX_MODE_WIDTH_MASK) {
+ case IXP2400_RX_MODE_1x32:
+ channels = 0x1;
+ if (reg & IXP2400_RX_MODE_MPHY &&
+ !(reg & IXP2400_RX_MODE_MPHY_32))
+ channels = 0xf;
+ break;
+
+ case IXP2400_RX_MODE_2x16:
+ channels = 0x5;
+ break;
+
+ case IXP2400_RX_MODE_4x8:
+ channels = 0xf;
+ break;
+
+ case IXP2400_RX_MODE_1x16_2x8:
+ channels = 0xd;
+ break;
+ }
+
+ return channels;
+}
+
+static void ixp2400_msf_enable_rx(struct ixp2400_msf_parameters *mp)
+{
+ u32 value;
+
+ value = ixp2000_reg_read(IXP2000_MSF_RX_CONTROL) & 0x0fffffff;
+ value |= ixp2400_msf_valid_channels(mp->rx_mode) << 28;
+ ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, value);
+}
+
+static void ixp2400_msf_enable_tx(struct ixp2400_msf_parameters *mp)
+{
+ u32 value;
+
+ value = ixp2000_reg_read(IXP2000_MSF_TX_CONTROL) & 0x0fffffff;
+ value |= ixp2400_msf_valid_channels(mp->tx_mode) << 28;
+ ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, value);
+}
+
+
+void ixp2400_msf_init(struct ixp2400_msf_parameters *mp)
+{
+ u32 value;
+ int i;
+
+ /*
+ * Init the RX/TX PLLs based on the passed parameter block.
+ */
+ ixp2400_pll_init(mp);
+
+ /*
+ * Reset MSF. Bit 7 in IXP_RESET_0 resets the MSF.
+ */
+ value = ixp2000_reg_read(IXP2000_RESET0);
+ ixp2000_reg_write(IXP2000_RESET0, value | 0x80);
+ ixp2000_reg_write(IXP2000_RESET0, value & ~0x80);
+
+ /*
+ * Initialise the RX section.
+ */
+ ixp2000_reg_write(IXP2000_MSF_RX_MPHY_POLL_LIMIT, mp->rx_poll_ports - 1);
+ ixp2000_reg_write(IXP2000_MSF_RX_CONTROL, mp->rx_mode);
+ for (i = 0; i < 4; i++) {
+ ixp2000_reg_write(IXP2000_MSF_RX_UP_CONTROL_0 + i,
+ mp->rx_channel_mode[i]);
+ }
+ ixp2400_msf_free_rbuf_entries(mp);
+ ixp2400_msf_enable_rx(mp);
+
+ /*
+ * Initialise the TX section.
+ */
+ ixp2000_reg_write(IXP2000_MSF_TX_MPHY_POLL_LIMIT, mp->tx_poll_ports - 1);
+ ixp2000_reg_write(IXP2000_MSF_TX_CONTROL, mp->tx_mode);
+ for (i = 0; i < 4; i++) {
+ ixp2000_reg_write(IXP2000_MSF_TX_UP_CONTROL_0 + i,
+ mp->tx_channel_mode[i]);
+ }
+ ixp2400_msf_enable_tx(mp);
+}
diff --git a/drivers/net/ixp2000/ixp2400-msf.h b/drivers/net/ixp2000/ixp2400-msf.h
new file mode 100644
index 000000000000..3ac1af2771da
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400-msf.h
@@ -0,0 +1,115 @@
+/*
+ * Generic library functions for the MSF (Media and Switch Fabric) unit
+ * found on the Intel IXP2400 network processor.
+ *
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ */
+
+#ifndef __IXP2400_MSF_H
+#define __IXP2400_MSF_H
+
+struct ixp2400_msf_parameters
+{
+ u32 rx_mode;
+ unsigned rxclk01_multiplier:2;
+ unsigned rxclk23_multiplier:2;
+ unsigned rx_poll_ports:6;
+ u32 rx_channel_mode[4];
+
+ u32 tx_mode;
+ unsigned txclk01_multiplier:2;
+ unsigned txclk23_multiplier:2;
+ unsigned tx_poll_ports:6;
+ u32 tx_channel_mode[4];
+};
+
+void ixp2400_msf_init(struct ixp2400_msf_parameters *mp);
+
+#define IXP2400_PLL_MULTIPLIER_48 0x00
+#define IXP2400_PLL_MULTIPLIER_24 0x01
+#define IXP2400_PLL_MULTIPLIER_16 0x02
+#define IXP2400_PLL_MULTIPLIER_12 0x03
+
+#define IXP2400_RX_MODE_CSIX 0x00400000
+#define IXP2400_RX_MODE_UTOPIA_POS 0x00000000
+#define IXP2400_RX_MODE_WIDTH_MASK 0x00300000
+#define IXP2400_RX_MODE_1x16_2x8 0x00300000
+#define IXP2400_RX_MODE_4x8 0x00200000
+#define IXP2400_RX_MODE_2x16 0x00100000
+#define IXP2400_RX_MODE_1x32 0x00000000
+#define IXP2400_RX_MODE_MPHY 0x00080000
+#define IXP2400_RX_MODE_SPHY 0x00000000
+#define IXP2400_RX_MODE_MPHY_32 0x00040000
+#define IXP2400_RX_MODE_MPHY_4 0x00000000
+#define IXP2400_RX_MODE_MPHY_POLLED_STATUS 0x00020000
+#define IXP2400_RX_MODE_MPHY_DIRECT_STATUS 0x00000000
+#define IXP2400_RX_MODE_CBUS_FULL_DUPLEX 0x00010000
+#define IXP2400_RX_MODE_CBUS_SIMPLEX 0x00000000
+#define IXP2400_RX_MODE_MPHY_LEVEL2 0x00004000
+#define IXP2400_RX_MODE_MPHY_LEVEL3 0x00000000
+#define IXP2400_RX_MODE_CBUS_8BIT 0x00002000
+#define IXP2400_RX_MODE_CBUS_4BIT 0x00000000
+#define IXP2400_RX_MODE_CSIX_SINGLE_FREELIST 0x00000200
+#define IXP2400_RX_MODE_CSIX_SPLIT_FREELISTS 0x00000000
+#define IXP2400_RX_MODE_RBUF_SIZE_MASK 0x0000000c
+#define IXP2400_RX_MODE_RBUF_SIZE_256 0x00000008
+#define IXP2400_RX_MODE_RBUF_SIZE_128 0x00000004
+#define IXP2400_RX_MODE_RBUF_SIZE_64 0x00000000
+
+#define IXP2400_PORT_RX_MODE_SLAVE 0x00000040
+#define IXP2400_PORT_RX_MODE_MASTER 0x00000000
+#define IXP2400_PORT_RX_MODE_POS_PHY_L3 0x00000020
+#define IXP2400_PORT_RX_MODE_POS_PHY_L2 0x00000000
+#define IXP2400_PORT_RX_MODE_POS_PHY 0x00000010
+#define IXP2400_PORT_RX_MODE_UTOPIA 0x00000000
+#define IXP2400_PORT_RX_MODE_EVEN_PARITY 0x0000000c
+#define IXP2400_PORT_RX_MODE_ODD_PARITY 0x00000008
+#define IXP2400_PORT_RX_MODE_NO_PARITY 0x00000000
+#define IXP2400_PORT_RX_MODE_UTOPIA_BIG_CELLS 0x00000002
+#define IXP2400_PORT_RX_MODE_UTOPIA_NORMAL_CELLS 0x00000000
+#define IXP2400_PORT_RX_MODE_2_CYCLE_DECODE 0x00000001
+#define IXP2400_PORT_RX_MODE_1_CYCLE_DECODE 0x00000000
+
+#define IXP2400_TX_MODE_CSIX 0x00400000
+#define IXP2400_TX_MODE_UTOPIA_POS 0x00000000
+#define IXP2400_TX_MODE_WIDTH_MASK 0x00300000
+#define IXP2400_TX_MODE_1x16_2x8 0x00300000
+#define IXP2400_TX_MODE_4x8 0x00200000
+#define IXP2400_TX_MODE_2x16 0x00100000
+#define IXP2400_TX_MODE_1x32 0x00000000
+#define IXP2400_TX_MODE_MPHY 0x00080000
+#define IXP2400_TX_MODE_SPHY 0x00000000
+#define IXP2400_TX_MODE_MPHY_32 0x00040000
+#define IXP2400_TX_MODE_MPHY_4 0x00000000
+#define IXP2400_TX_MODE_MPHY_POLLED_STATUS 0x00020000
+#define IXP2400_TX_MODE_MPHY_DIRECT_STATUS 0x00000000
+#define IXP2400_TX_MODE_CBUS_FULL_DUPLEX 0x00010000
+#define IXP2400_TX_MODE_CBUS_SIMPLEX 0x00000000
+#define IXP2400_TX_MODE_MPHY_LEVEL2 0x00004000
+#define IXP2400_TX_MODE_MPHY_LEVEL3 0x00000000
+#define IXP2400_TX_MODE_CBUS_8BIT 0x00002000
+#define IXP2400_TX_MODE_CBUS_4BIT 0x00000000
+#define IXP2400_TX_MODE_TBUF_SIZE_MASK 0x0000000c
+#define IXP2400_TX_MODE_TBUF_SIZE_256 0x00000008
+#define IXP2400_TX_MODE_TBUF_SIZE_128 0x00000004
+#define IXP2400_TX_MODE_TBUF_SIZE_64 0x00000000
+
+#define IXP2400_PORT_TX_MODE_SLAVE 0x00000040
+#define IXP2400_PORT_TX_MODE_MASTER 0x00000000
+#define IXP2400_PORT_TX_MODE_POS_PHY 0x00000010
+#define IXP2400_PORT_TX_MODE_UTOPIA 0x00000000
+#define IXP2400_PORT_TX_MODE_EVEN_PARITY 0x0000000c
+#define IXP2400_PORT_TX_MODE_ODD_PARITY 0x00000008
+#define IXP2400_PORT_TX_MODE_NO_PARITY 0x00000000
+#define IXP2400_PORT_TX_MODE_UTOPIA_BIG_CELLS 0x00000002
+#define IXP2400_PORT_TX_MODE_2_CYCLE_DECODE 0x00000001
+#define IXP2400_PORT_TX_MODE_1_CYCLE_DECODE 0x00000000
+
+
+#endif
diff --git a/drivers/net/ixp2000/ixp2400_rx.uc b/drivers/net/ixp2000/ixp2400_rx.uc
new file mode 100644
index 000000000000..42a73e357afa
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_rx.uc
@@ -0,0 +1,408 @@
+/*
+ * RX ucode for the Intel IXP2400 in POS-PHY mode.
+ * Copyright (C) 2004, 2005 Lennert Buytenhek
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Assumptions made in this code:
+ * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
+ * only one full element list is used. This includes, for example,
+ * 1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
+ * is not an exhaustive list.)
+ * - The RBUF uses 64-byte mpackets.
+ * - RX descriptors reside in SRAM, and have the following format:
+ * struct rx_desc
+ * {
+ * // to uengine
+ * u32 buf_phys_addr;
+ * u32 buf_length;
+ *
+ * // from uengine
+ * u32 channel;
+ * u32 pkt_length;
+ * };
+ * - Packet data resides in DRAM.
+ * - Packet buffer addresses are 8-byte aligned.
+ * - Scratch ring 0 is rx_pending.
+ * - Scratch ring 1 is rx_done, and has status condition 'full'.
+ * - The host triggers rx_done flush and rx_pending refill on seeing INTA.
+ * - This code is run on all eight threads of the microengine it runs on.
+ *
+ * Local memory is used for per-channel RX state.
+ */
+
+#define RX_THREAD_FREELIST_0 0x0030
+#define RBUF_ELEMENT_DONE 0x0044
+
+#define CHANNEL_FLAGS *l$index0[0]
+#define CHANNEL_FLAG_RECEIVING 1
+#define PACKET_LENGTH *l$index0[1]
+#define PACKET_CHECKSUM *l$index0[2]
+#define BUFFER_HANDLE *l$index0[3]
+#define BUFFER_START *l$index0[4]
+#define BUFFER_LENGTH *l$index0[5]
+
+#define CHANNEL_STATE_SIZE 24 // in bytes
+#define CHANNEL_STATE_SHIFT 5 // ceil(log2(state size))
+
+
+ .sig volatile sig1
+ .sig volatile sig2
+ .sig volatile sig3
+
+ .sig mpacket_arrived
+ .reg add_to_rx_freelist
+ .reg read $rsw0, $rsw1
+ .xfer_order $rsw0 $rsw1
+
+ .reg zero
+
+ /*
+ * Initialise add_to_rx_freelist.
+ */
+ .begin
+ .reg temp
+ .reg temp2
+
+ immed[add_to_rx_freelist, RX_THREAD_FREELIST_0]
+ immed_w1[add_to_rx_freelist, (&$rsw0 | (&mpacket_arrived << 12))]
+
+ local_csr_rd[ACTIVE_CTX_STS]
+ immed[temp, 0]
+ alu[temp2, temp, and, 0x1f]
+ alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<20]
+ alu[temp2, temp, and, 0x80]
+ alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<18]
+ .end
+
+ immed[zero, 0]
+
+ /*
+ * Skip context 0 initialisation?
+ */
+ .begin
+ br!=ctx[0, mpacket_receive_loop#]
+ .end
+
+ /*
+ * Initialise local memory.
+ */
+ .begin
+ .reg addr
+ .reg temp
+
+ immed[temp, 0]
+ init_local_mem_loop#:
+ alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]
+ local_csr_wr[ACTIVE_LM_ADDR_0, addr]
+ nop
+ nop
+ nop
+
+ immed[CHANNEL_FLAGS, 0]
+
+ alu[temp, temp, +, 1]
+ alu[--, temp, and, 0x20]
+ beq[init_local_mem_loop#]
+ .end
+
+ /*
+ * Initialise signal pipeline.
+ */
+ .begin
+ local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
+ .set_sig sig1
+
+ local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
+ .set_sig sig2
+
+ local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
+ .set_sig sig3
+ .end
+
+mpacket_receive_loop#:
+ /*
+ * Synchronise and wait for mpacket.
+ */
+ .begin
+ ctx_arb[sig1]
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
+
+ msf[fast_wr, --, add_to_rx_freelist, 0]
+ .set_sig mpacket_arrived
+ ctx_arb[mpacket_arrived]
+ .set $rsw0 $rsw1
+ .end
+
+ /*
+ * We halt if we see {inbparerr,parerr,null,soperror}.
+ */
+ .begin
+ alu_shf[--, 0x1b, and, $rsw0, >>8]
+ bne[abort_rswerr#]
+ .end
+
+ /*
+ * Point local memory pointer to this channel's state area.
+ */
+ .begin
+ .reg chanaddr
+
+ alu[chanaddr, $rsw0, and, 0x1f]
+ alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]
+ local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]
+ nop
+ nop
+ nop
+ .end
+
+ /*
+ * Check whether we received a SOP mpacket while we were already
+ * working on a packet, or a non-SOP mpacket while there was no
+ * packet pending. (SOP == RECEIVING -> abort) If everything's
+ * okay, update the RECEIVING flag to reflect our new state.
+ */
+ .begin
+ .reg temp
+ .reg eop
+
+ #if CHANNEL_FLAG_RECEIVING != 1
+ #error CHANNEL_FLAG_RECEIVING is not 1
+ #endif
+
+ alu_shf[temp, 1, and, $rsw0, >>15]
+ alu[temp, temp, xor, CHANNEL_FLAGS]
+ alu[--, temp, and, CHANNEL_FLAG_RECEIVING]
+ beq[abort_proterr#]
+
+ alu_shf[eop, 1, and, $rsw0, >>14]
+ alu[CHANNEL_FLAGS, temp, xor, eop]
+ .end
+
+ /*
+ * Copy the mpacket into the right spot, and in case of EOP,
+ * write back the descriptor and pass the packet on.
+ */
+ .begin
+ .reg buffer_offset
+ .reg _packet_length
+ .reg _packet_checksum
+ .reg _buffer_handle
+ .reg _buffer_start
+ .reg _buffer_length
+
+ /*
+ * Determine buffer_offset, _packet_length and
+ * _packet_checksum.
+ */
+ .begin
+ .reg temp
+
+ alu[--, 1, and, $rsw0, >>15]
+ beq[not_sop#]
+
+ immed[PACKET_LENGTH, 0]
+ immed[PACKET_CHECKSUM, 0]
+
+ not_sop#:
+ alu[buffer_offset, --, b, PACKET_LENGTH]
+ alu_shf[temp, 0xff, and, $rsw0, >>16]
+ alu[_packet_length, buffer_offset, +, temp]
+ alu[PACKET_LENGTH, --, b, _packet_length]
+
+ immed[temp, 0xffff]
+ alu[temp, $rsw1, and, temp]
+ alu[_packet_checksum, PACKET_CHECKSUM, +, temp]
+ alu[PACKET_CHECKSUM, --, b, _packet_checksum]
+ .end
+
+ /*
+ * Allocate buffer in case of SOP.
+ */
+ .begin
+ .reg temp
+
+ alu[temp, 1, and, $rsw0, >>15]
+ beq[skip_buffer_alloc#]
+
+ .begin
+ .sig zzz
+ .reg read $stemp $stemp2
+ .xfer_order $stemp $stemp2
+
+ rx_nobufs#:
+ scratch[get, $stemp, zero, 0, 1], ctx_swap[zzz]
+ alu[_buffer_handle, --, b, $stemp]
+ beq[rx_nobufs#]
+
+ sram[read, $stemp, _buffer_handle, 0, 2],
+ ctx_swap[zzz]
+ alu[_buffer_start, --, b, $stemp]
+ alu[_buffer_length, --, b, $stemp2]
+ .end
+
+ skip_buffer_alloc#:
+ .end
+
+ /*
+ * Resynchronise.
+ */
+ .begin
+ ctx_arb[sig2]
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
+ .end
+
+ /*
+ * Synchronise buffer state.
+ */
+ .begin
+ .reg temp
+
+ alu[temp, 1, and, $rsw0, >>15]
+ beq[copy_from_local_mem#]
+
+ alu[BUFFER_HANDLE, --, b, _buffer_handle]
+ alu[BUFFER_START, --, b, _buffer_start]
+ alu[BUFFER_LENGTH, --, b, _buffer_length]
+ br[sync_state_done#]
+
+ copy_from_local_mem#:
+ alu[_buffer_handle, --, b, BUFFER_HANDLE]
+ alu[_buffer_start, --, b, BUFFER_START]
+ alu[_buffer_length, --, b, BUFFER_LENGTH]
+
+ sync_state_done#:
+ .end
+
+#if 0
+ /*
+ * Debug buffer state management.
+ */
+ .begin
+ .reg temp
+
+ alu[temp, 1, and, $rsw0, >>14]
+ beq[no_poison#]
+ immed[BUFFER_HANDLE, 0xdead]
+ immed[BUFFER_START, 0xdead]
+ immed[BUFFER_LENGTH, 0xdead]
+ no_poison#:
+
+ immed[temp, 0xdead]
+ alu[--, _buffer_handle, -, temp]
+ beq[state_corrupted#]
+ alu[--, _buffer_start, -, temp]
+ beq[state_corrupted#]
+ alu[--, _buffer_length, -, temp]
+ beq[state_corrupted#]
+ .end
+#endif
+
+ /*
+ * Check buffer length.
+ */
+ .begin
+ alu[--, _buffer_length, -, _packet_length]
+ blo[buffer_overflow#]
+ .end
+
+ /*
+ * Copy the mpacket and give back the RBUF element.
+ */
+ .begin
+ .reg element
+ .reg xfer_size
+ .reg temp
+ .sig copy_sig
+
+ alu_shf[element, 0x7f, and, $rsw0, >>24]
+ alu_shf[xfer_size, 0xff, and, $rsw0, >>16]
+
+ alu[xfer_size, xfer_size, -, 1]
+ alu_shf[xfer_size, 0x10, or, xfer_size, >>3]
+ alu_shf[temp, 0x10, or, xfer_size, <<21]
+ alu_shf[temp, temp, or, element, <<11]
+ alu_shf[--, temp, or, 1, <<18]
+
+ dram[rbuf_rd, --, _buffer_start, buffer_offset, max_8],
+ indirect_ref, sig_done[copy_sig]
+ ctx_arb[copy_sig]
+
+ alu[temp, RBUF_ELEMENT_DONE, or, element, <<16]
+ msf[fast_wr, --, temp, 0]
+ .end
+
+ /*
+ * If EOP, write back the packet descriptor.
+ */
+ .begin
+ .reg write $stemp $stemp2
+ .xfer_order $stemp $stemp2
+ .sig zzz
+
+ alu_shf[--, 1, and, $rsw0, >>14]
+ beq[no_writeback#]
+
+ alu[$stemp, $rsw0, and, 0x1f]
+ alu[$stemp2, --, b, _packet_length]
+ sram[write, $stemp, _buffer_handle, 8, 2], ctx_swap[zzz]
+
+ no_writeback#:
+ .end
+
+ /*
+ * Resynchronise.
+ */
+ .begin
+ ctx_arb[sig3]
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
+ .end
+
+ /*
+ * If EOP, put the buffer back onto the scratch ring.
+ */
+ .begin
+ .reg write $stemp
+ .sig zzz
+
+ br_inp_state[SCR_Ring1_Status, rx_done_ring_overflow#]
+
+ alu_shf[--, 1, and, $rsw0, >>14]
+ beq[mpacket_receive_loop#]
+
+ alu[--, 1, and, $rsw0, >>10]
+ bne[rxerr#]
+
+ alu[$stemp, --, b, _buffer_handle]
+ scratch[put, $stemp, zero, 4, 1], ctx_swap[zzz]
+ cap[fast_wr, 0, XSCALE_INT_A]
+ br[mpacket_receive_loop#]
+
+ rxerr#:
+ alu[$stemp, --, b, _buffer_handle]
+ scratch[put, $stemp, zero, 0, 1], ctx_swap[zzz]
+ br[mpacket_receive_loop#]
+ .end
+ .end
+
+
+abort_rswerr#:
+ halt
+
+abort_proterr#:
+ halt
+
+state_corrupted#:
+ halt
+
+buffer_overflow#:
+ halt
+
+rx_done_ring_overflow#:
+ halt
+
+
diff --git a/drivers/net/ixp2000/ixp2400_rx.ucode b/drivers/net/ixp2000/ixp2400_rx.ucode
new file mode 100644
index 000000000000..e8aee2f81aad
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_rx.ucode
@@ -0,0 +1,130 @@
+static struct ixp2000_uengine_code ixp2400_rx =
+{
+ .cpu_model_bitmask = 0x000003fe,
+ .cpu_min_revision = 0,
+ .cpu_max_revision = 255,
+
+ .uengine_parameters = IXP2000_UENGINE_8_CONTEXTS |
+ IXP2000_UENGINE_PRN_UPDATE_EVERY |
+ IXP2000_UENGINE_NN_FROM_PREVIOUS |
+ IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
+ IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
+ IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
+
+ .initial_reg_values = (struct ixp2000_reg_value []) {
+ { -1, -1 }
+ },
+
+ .num_insns = 109,
+ .insns = (u8 []) {
+ 0xf0, 0x00, 0x0c, 0xc0, 0x05,
+ 0xf4, 0x44, 0x0c, 0x00, 0x05,
+ 0xfc, 0x04, 0x4c, 0x00, 0x00,
+ 0xf0, 0x00, 0x00, 0x3b, 0x00,
+ 0xb4, 0x40, 0xf0, 0x3b, 0x1f,
+ 0x8a, 0xc0, 0x50, 0x3e, 0x05,
+ 0xb4, 0x40, 0xf0, 0x3b, 0x80,
+ 0x9a, 0xe0, 0x00, 0x3e, 0x05,
+ 0xf0, 0x00, 0x00, 0x07, 0x00,
+ 0xd8, 0x05, 0xc0, 0x00, 0x11,
+ 0xf0, 0x00, 0x00, 0x0f, 0x00,
+ 0x91, 0xb0, 0x20, 0x0e, 0x00,
+ 0xfc, 0x06, 0x60, 0x0b, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0xf0, 0x00, 0x0c, 0x02, 0x00,
+ 0xb0, 0xc0, 0x30, 0x0f, 0x01,
+ 0xa4, 0x70, 0x00, 0x0f, 0x20,
+ 0xd8, 0x02, 0xc0, 0x01, 0x00,
+ 0xfc, 0x10, 0xac, 0x23, 0x08,
+ 0xfc, 0x10, 0xac, 0x43, 0x10,
+ 0xfc, 0x10, 0xac, 0x63, 0x18,
+ 0xe0, 0x00, 0x00, 0x00, 0x02,
+ 0xfc, 0x10, 0xae, 0x23, 0x88,
+ 0x3d, 0x00, 0x04, 0x03, 0x20,
+ 0xe0, 0x00, 0x00, 0x00, 0x10,
+ 0x84, 0x82, 0x02, 0x01, 0x3b,
+ 0xd8, 0x1a, 0x00, 0x01, 0x01,
+ 0xb4, 0x00, 0x8c, 0x7d, 0x80,
+ 0x91, 0xb0, 0x80, 0x22, 0x00,
+ 0xfc, 0x06, 0x60, 0x23, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0xf0, 0x00, 0x0c, 0x03, 0x00,
+ 0x94, 0xf0, 0x92, 0x01, 0x21,
+ 0xac, 0x40, 0x60, 0x26, 0x00,
+ 0xa4, 0x30, 0x0c, 0x04, 0x06,
+ 0xd8, 0x1a, 0x40, 0x01, 0x00,
+ 0x94, 0xe0, 0xa2, 0x01, 0x21,
+ 0xac, 0x20, 0x00, 0x28, 0x06,
+ 0x84, 0xf2, 0x02, 0x01, 0x21,
+ 0xd8, 0x0b, 0x40, 0x01, 0x00,
+ 0xf0, 0x00, 0x0c, 0x02, 0x01,
+ 0xf0, 0x00, 0x0c, 0x02, 0x02,
+ 0xa0, 0x00, 0x08, 0x04, 0x00,
+ 0x95, 0x00, 0xc6, 0x01, 0xff,
+ 0xa0, 0x80, 0x10, 0x30, 0x00,
+ 0xa0, 0x60, 0x1c, 0x00, 0x01,
+ 0xf0, 0x0f, 0xf0, 0x33, 0xff,
+ 0xb4, 0x00, 0xc0, 0x31, 0x81,
+ 0xb0, 0x80, 0xb0, 0x32, 0x02,
+ 0xa0, 0x20, 0x20, 0x2c, 0x00,
+ 0x94, 0xf0, 0xd2, 0x01, 0x21,
+ 0xd8, 0x0f, 0x40, 0x01, 0x00,
+ 0x19, 0x40, 0x10, 0x04, 0x20,
+ 0xa0, 0x00, 0x26, 0x04, 0x00,
+ 0xd8, 0x0d, 0xc0, 0x01, 0x00,
+ 0x00, 0x42, 0x10, 0x80, 0x02,
+ 0xb0, 0x00, 0x46, 0x04, 0x00,
+ 0xb0, 0x00, 0x56, 0x08, 0x00,
+ 0xe0, 0x00, 0x00, 0x00, 0x04,
+ 0xfc, 0x10, 0xae, 0x43, 0x90,
+ 0x84, 0xf0, 0x32, 0x01, 0x21,
+ 0xd8, 0x11, 0x40, 0x01, 0x00,
+ 0xa0, 0x60, 0x3c, 0x00, 0x02,
+ 0xa0, 0x20, 0x40, 0x10, 0x00,
+ 0xa0, 0x20, 0x50, 0x14, 0x00,
+ 0xd8, 0x12, 0x00, 0x00, 0x18,
+ 0xa0, 0x00, 0x28, 0x0c, 0x00,
+ 0xb0, 0x00, 0x48, 0x10, 0x00,
+ 0xb0, 0x00, 0x58, 0x14, 0x00,
+ 0xaa, 0xf0, 0x00, 0x14, 0x01,
+ 0xd8, 0x1a, 0xc0, 0x01, 0x05,
+ 0x85, 0x80, 0x42, 0x01, 0xff,
+ 0x95, 0x00, 0x66, 0x01, 0xff,
+ 0xba, 0xc0, 0x60, 0x1b, 0x01,
+ 0x9a, 0x30, 0x60, 0x19, 0x30,
+ 0x9a, 0xb0, 0x70, 0x1a, 0x30,
+ 0x9b, 0x50, 0x78, 0x1e, 0x04,
+ 0x8a, 0xe2, 0x08, 0x1e, 0x21,
+ 0x6a, 0x4e, 0x00, 0x13, 0x00,
+ 0xe0, 0x00, 0x00, 0x00, 0x30,
+ 0x9b, 0x00, 0x7a, 0x92, 0x04,
+ 0x3d, 0x00, 0x04, 0x1f, 0x20,
+ 0x84, 0xe2, 0x02, 0x01, 0x21,
+ 0xd8, 0x16, 0x80, 0x01, 0x00,
+ 0xa4, 0x18, 0x0c, 0x7d, 0x80,
+ 0xa0, 0x58, 0x1c, 0x00, 0x01,
+ 0x01, 0x42, 0x00, 0xa0, 0x02,
+ 0xe0, 0x00, 0x00, 0x00, 0x08,
+ 0xfc, 0x10, 0xae, 0x63, 0x98,
+ 0xd8, 0x1b, 0x00, 0xc2, 0x14,
+ 0x84, 0xe2, 0x02, 0x01, 0x21,
+ 0xd8, 0x05, 0xc0, 0x01, 0x00,
+ 0x84, 0xa2, 0x02, 0x01, 0x21,
+ 0xd8, 0x19, 0x40, 0x01, 0x01,
+ 0xa0, 0x58, 0x0c, 0x00, 0x02,
+ 0x1a, 0x40, 0x00, 0x04, 0x24,
+ 0x33, 0x00, 0x01, 0x2f, 0x20,
+ 0xd8, 0x05, 0xc0, 0x00, 0x18,
+ 0xa0, 0x58, 0x0c, 0x00, 0x02,
+ 0x1a, 0x40, 0x00, 0x04, 0x20,
+ 0xd8, 0x05, 0xc0, 0x00, 0x18,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ }
+};
diff --git a/drivers/net/ixp2000/ixp2400_tx.uc b/drivers/net/ixp2000/ixp2400_tx.uc
new file mode 100644
index 000000000000..d090d1884fb7
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_tx.uc
@@ -0,0 +1,272 @@
+/*
+ * TX ucode for the Intel IXP2400 in POS-PHY mode.
+ * Copyright (C) 2004, 2005 Lennert Buytenhek
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Assumptions made in this code:
+ * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
+ * only one TBUF partition is used. This includes, for example,
+ * 1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
+ * is not an exhaustive list.)
+ * - The TBUF uses 64-byte mpackets.
+ * - TX descriptors reside in SRAM, and have the following format:
+ * struct tx_desc
+ * {
+ * // to uengine
+ * u32 buf_phys_addr;
+ * u32 pkt_length;
+ * u32 channel;
+ * };
+ * - Packet data resides in DRAM.
+ * - Packet buffer addresses are 8-byte aligned.
+ * - Scratch ring 2 is tx_pending.
+ * - Scratch ring 3 is tx_done, and has status condition 'full'.
+ * - This code is run on all eight threads of the microengine it runs on.
+ */
+
+#define TX_SEQUENCE_0 0x0060
+#define TBUF_CTRL 0x1800
+
+#define PARTITION_SIZE 128
+#define PARTITION_THRESH 96
+
+
+ .sig volatile sig1
+ .sig volatile sig2
+ .sig volatile sig3
+
+ .reg @old_tx_seq_0
+ .reg @mpkts_in_flight
+ .reg @next_tbuf_mpacket
+
+ .reg @buffer_handle
+ .reg @buffer_start
+ .reg @packet_length
+ .reg @channel
+ .reg @packet_offset
+
+ .reg zero
+
+ immed[zero, 0]
+
+ /*
+ * Skip context 0 initialisation?
+ */
+ .begin
+ br!=ctx[0, mpacket_tx_loop#]
+ .end
+
+ /*
+ * Wait until all pending TBUF elements have been transmitted.
+ */
+ .begin
+ .reg read $tx
+ .sig zzz
+
+ loop_empty#:
+ msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
+ alu_shf[--, --, b, $tx, >>31]
+ beq[loop_empty#]
+
+ alu[@old_tx_seq_0, --, b, $tx]
+ .end
+
+ immed[@mpkts_in_flight, 0]
+ alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]
+
+ immed[@buffer_handle, 0]
+
+ /*
+ * Initialise signal pipeline.
+ */
+ .begin
+ local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
+ .set_sig sig1
+
+ local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
+ .set_sig sig2
+
+ local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
+ .set_sig sig3
+ .end
+
+mpacket_tx_loop#:
+ .begin
+ .reg tbuf_element_index
+ .reg buffer_handle
+ .reg sop_eop
+ .reg packet_data
+ .reg channel
+ .reg mpacket_size
+
+ /*
+ * If there is no packet currently being transmitted,
+ * dequeue the next TX descriptor, and fetch the buffer
+ * address, packet length and destination channel number.
+ */
+ .begin
+ .reg read $stemp $stemp2 $stemp3
+ .xfer_order $stemp $stemp2 $stemp3
+ .sig zzz
+
+ ctx_arb[sig1]
+
+ alu[--, --, b, @buffer_handle]
+ bne[already_got_packet#]
+
+ tx_nobufs#:
+ scratch[get, $stemp, zero, 8, 1], ctx_swap[zzz]
+ alu[@buffer_handle, --, b, $stemp]
+ beq[tx_nobufs#]
+
+ sram[read, $stemp, $stemp, 0, 3], ctx_swap[zzz]
+ alu[@buffer_start, --, b, $stemp]
+ alu[@packet_length, --, b, $stemp2]
+ beq[zero_byte_packet#]
+ alu[@channel, --, b, $stemp3]
+ immed[@packet_offset, 0]
+
+ already_got_packet#:
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
+ .end
+
+ /*
+ * Determine tbuf element index, SOP/EOP flags, mpacket
+ * offset and mpacket size and cache buffer_handle and
+ * channel number.
+ */
+ .begin
+ alu[tbuf_element_index, --, b, @next_tbuf_mpacket]
+ alu[@next_tbuf_mpacket, @next_tbuf_mpacket, +, 1]
+ alu[@next_tbuf_mpacket, @next_tbuf_mpacket, and,
+ (PARTITION_SIZE - 1)]
+
+ alu[buffer_handle, --, b, @buffer_handle]
+ immed[@buffer_handle, 0]
+
+ immed[sop_eop, 1]
+
+ alu[packet_data, --, b, @packet_offset]
+ bne[no_sop#]
+ alu[sop_eop, sop_eop, or, 2]
+ no_sop#:
+ alu[packet_data, packet_data, +, @buffer_start]
+
+ alu[channel, --, b, @channel]
+
+ alu[mpacket_size, @packet_length, -, @packet_offset]
+ alu[--, 64, -, mpacket_size]
+ bhs[eop#]
+ alu[@buffer_handle, --, b, buffer_handle]
+ immed[mpacket_size, 64]
+ alu[sop_eop, sop_eop, and, 2]
+ eop#:
+
+ alu[@packet_offset, @packet_offset, +, mpacket_size]
+ .end
+
+ /*
+ * Wait until there's enough space in the TBUF.
+ */
+ .begin
+ .reg read $tx
+ .reg temp
+ .sig zzz
+
+ ctx_arb[sig2]
+
+ br[test_space#]
+
+ loop_space#:
+ msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
+
+ alu[temp, $tx, -, @old_tx_seq_0]
+ alu[temp, temp, and, 0xff]
+ alu[@mpkts_in_flight, @mpkts_in_flight, -, temp]
+
+ alu[@old_tx_seq_0, --, b, $tx]
+
+ test_space#:
+ alu[--, PARTITION_THRESH, -, @mpkts_in_flight]
+ blo[loop_space#]
+
+ alu[@mpkts_in_flight, @mpkts_in_flight, +, 1]
+
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
+ .end
+
+ /*
+ * Copy the packet data to the TBUF.
+ */
+ .begin
+ .reg temp
+ .sig copy_sig
+
+ alu[temp, mpacket_size, -, 1]
+ alu_shf[temp, 0x10, or, temp, >>3]
+ alu_shf[temp, 0x10, or, temp, <<21]
+ alu_shf[temp, temp, or, tbuf_element_index, <<11]
+ alu_shf[--, temp, or, 1, <<18]
+
+ dram[tbuf_wr, --, packet_data, 0, max_8],
+ indirect_ref, sig_done[copy_sig]
+ ctx_arb[copy_sig]
+ .end
+
+ /*
+ * Mark TBUF element as ready-to-be-transmitted.
+ */
+ .begin
+ .reg write $tsw $tsw2
+ .xfer_order $tsw $tsw2
+ .reg temp
+ .sig zzz
+
+ alu_shf[temp, channel, or, mpacket_size, <<24]
+ alu_shf[$tsw, temp, or, sop_eop, <<8]
+ immed[$tsw2, 0]
+
+ immed[temp, TBUF_CTRL]
+ alu_shf[temp, temp, or, tbuf_element_index, <<3]
+ msf[write, $tsw, temp, 0, 2], ctx_swap[zzz]
+ .end
+
+ /*
+ * Resynchronise.
+ */
+ .begin
+ ctx_arb[sig3]
+ local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
+ .end
+
+ /*
+ * If this was an EOP mpacket, recycle the TX buffer
+ * and signal the host.
+ */
+ .begin
+ .reg write $stemp
+ .sig zzz
+
+ alu[--, sop_eop, and, 1]
+ beq[mpacket_tx_loop#]
+
+ tx_done_ring_full#:
+ br_inp_state[SCR_Ring3_Status, tx_done_ring_full#]
+
+ alu[$stemp, --, b, buffer_handle]
+ scratch[put, $stemp, zero, 12, 1], ctx_swap[zzz]
+ cap[fast_wr, 0, XSCALE_INT_A]
+ br[mpacket_tx_loop#]
+ .end
+ .end
+
+
+zero_byte_packet#:
+ halt
+
+
diff --git a/drivers/net/ixp2000/ixp2400_tx.ucode b/drivers/net/ixp2000/ixp2400_tx.ucode
new file mode 100644
index 000000000000..a433e24b0a51
--- /dev/null
+++ b/drivers/net/ixp2000/ixp2400_tx.ucode
@@ -0,0 +1,98 @@
+static struct ixp2000_uengine_code ixp2400_tx =
+{
+ .cpu_model_bitmask = 0x000003fe,
+ .cpu_min_revision = 0,
+ .cpu_max_revision = 255,
+
+ .uengine_parameters = IXP2000_UENGINE_8_CONTEXTS |
+ IXP2000_UENGINE_PRN_UPDATE_EVERY |
+ IXP2000_UENGINE_NN_FROM_PREVIOUS |
+ IXP2000_UENGINE_ASSERT_EMPTY_AT_0 |
+ IXP2000_UENGINE_LM_ADDR1_PER_CONTEXT |
+ IXP2000_UENGINE_LM_ADDR0_PER_CONTEXT,
+
+ .initial_reg_values = (struct ixp2000_reg_value []) {
+ { -1, -1 }
+ },
+
+ .num_insns = 77,
+ .insns = (u8 []) {
+ 0xf0, 0x00, 0x00, 0x07, 0x00,
+ 0xd8, 0x03, 0x00, 0x00, 0x11,
+ 0x3c, 0x40, 0x00, 0x04, 0xe0,
+ 0x81, 0xf2, 0x02, 0x01, 0x00,
+ 0xd8, 0x00, 0x80, 0x01, 0x00,
+ 0xb0, 0x08, 0x06, 0x00, 0x00,
+ 0xf0, 0x00, 0x0c, 0x00, 0x80,
+ 0xb4, 0x49, 0x02, 0x03, 0x7f,
+ 0xf0, 0x00, 0x02, 0x83, 0x00,
+ 0xfc, 0x10, 0xac, 0x23, 0x08,
+ 0xfc, 0x10, 0xac, 0x43, 0x10,
+ 0xfc, 0x10, 0xac, 0x63, 0x18,
+ 0xe0, 0x00, 0x00, 0x00, 0x02,
+ 0xa0, 0x30, 0x02, 0x80, 0x00,
+ 0xd8, 0x06, 0x00, 0x01, 0x01,
+ 0x19, 0x40, 0x00, 0x04, 0x28,
+ 0xb0, 0x0a, 0x06, 0x00, 0x00,
+ 0xd8, 0x03, 0xc0, 0x01, 0x00,
+ 0x00, 0x44, 0x00, 0x80, 0x80,
+ 0xa0, 0x09, 0x06, 0x00, 0x00,
+ 0xb0, 0x0b, 0x06, 0x04, 0x00,
+ 0xd8, 0x13, 0x00, 0x01, 0x00,
+ 0xb0, 0x0c, 0x06, 0x08, 0x00,
+ 0xf0, 0x00, 0x0c, 0x00, 0xa0,
+ 0xfc, 0x10, 0xae, 0x23, 0x88,
+ 0xa0, 0x00, 0x12, 0x40, 0x00,
+ 0xb0, 0xc9, 0x02, 0x43, 0x01,
+ 0xb4, 0x49, 0x02, 0x43, 0x7f,
+ 0xb0, 0x00, 0x22, 0x80, 0x00,
+ 0xf0, 0x00, 0x02, 0x83, 0x00,
+ 0xf0, 0x00, 0x0c, 0x04, 0x02,
+ 0xb0, 0x40, 0x6c, 0x00, 0xa0,
+ 0xd8, 0x08, 0x80, 0x01, 0x01,
+ 0xaa, 0x00, 0x2c, 0x08, 0x02,
+ 0xa0, 0xc0, 0x30, 0x18, 0x90,
+ 0xa0, 0x00, 0x43, 0x00, 0x00,
+ 0xba, 0xc0, 0x32, 0xc0, 0xa0,
+ 0xaa, 0xb0, 0x00, 0x0f, 0x40,
+ 0xd8, 0x0a, 0x80, 0x01, 0x04,
+ 0xb0, 0x0a, 0x00, 0x08, 0x00,
+ 0xf0, 0x00, 0x00, 0x0f, 0x40,
+ 0xa4, 0x00, 0x2c, 0x08, 0x02,
+ 0xa0, 0x8a, 0x00, 0x0c, 0xa0,
+ 0xe0, 0x00, 0x00, 0x00, 0x04,
+ 0xd8, 0x0c, 0x80, 0x00, 0x18,
+ 0x3c, 0x40, 0x00, 0x04, 0xe0,
+ 0xba, 0x80, 0x42, 0x01, 0x80,
+ 0xb4, 0x40, 0x40, 0x13, 0xff,
+ 0xaa, 0x88, 0x00, 0x10, 0x80,
+ 0xb0, 0x08, 0x06, 0x00, 0x00,
+ 0xaa, 0xf0, 0x0d, 0x80, 0x80,
+ 0xd8, 0x0b, 0x40, 0x01, 0x05,
+ 0xa0, 0x88, 0x0c, 0x04, 0x80,
+ 0xfc, 0x10, 0xae, 0x43, 0x90,
+ 0xba, 0xc0, 0x50, 0x0f, 0x01,
+ 0x9a, 0x30, 0x50, 0x15, 0x30,
+ 0x9a, 0xb0, 0x50, 0x16, 0x30,
+ 0x9b, 0x50, 0x58, 0x16, 0x01,
+ 0x8a, 0xe2, 0x08, 0x16, 0x21,
+ 0x6b, 0x4e, 0x00, 0x83, 0x03,
+ 0xe0, 0x00, 0x00, 0x00, 0x30,
+ 0x9a, 0x80, 0x70, 0x0e, 0x04,
+ 0x8b, 0x88, 0x08, 0x1e, 0x02,
+ 0xf0, 0x00, 0x0c, 0x01, 0x81,
+ 0xf0, 0x01, 0x80, 0x1f, 0x00,
+ 0x9b, 0xd0, 0x78, 0x1e, 0x01,
+ 0x3d, 0x42, 0x00, 0x1c, 0x20,
+ 0xe0, 0x00, 0x00, 0x00, 0x08,
+ 0xfc, 0x10, 0xae, 0x63, 0x98,
+ 0xa4, 0x30, 0x0c, 0x04, 0x02,
+ 0xd8, 0x03, 0x00, 0x01, 0x00,
+ 0xd8, 0x11, 0xc1, 0x42, 0x14,
+ 0xa0, 0x18, 0x00, 0x08, 0x00,
+ 0x1a, 0x40, 0x00, 0x04, 0x2c,
+ 0x33, 0x00, 0x01, 0x2f, 0x20,
+ 0xd8, 0x03, 0x00, 0x00, 0x18,
+ 0xe0, 0x00, 0x02, 0x00, 0x00,
+ }
+};
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
new file mode 100644
index 000000000000..09f03f493bea
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -0,0 +1,421 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <asm/arch/uengine.h>
+#include <asm/mach-types.h>
+#include <asm/io.h>
+#include "ixp2400_rx.ucode"
+#include "ixp2400_tx.ucode"
+#include "ixpdev_priv.h"
+#include "ixpdev.h"
+
+#define DRV_MODULE_VERSION "0.2"
+
+static int nds_count;
+static struct net_device **nds;
+static int nds_open;
+static void (*set_port_admin_status)(int port, int up);
+
+static struct ixpdev_rx_desc * const rx_desc =
+ (struct ixpdev_rx_desc *)(IXP2000_SRAM0_VIRT_BASE + RX_BUF_DESC_BASE);
+static struct ixpdev_tx_desc * const tx_desc =
+ (struct ixpdev_tx_desc *)(IXP2000_SRAM0_VIRT_BASE + TX_BUF_DESC_BASE);
+static int tx_pointer;
+
+
+static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ixpdev_priv *ip = netdev_priv(dev);
+ struct ixpdev_tx_desc *desc;
+ int entry;
+
+ if (unlikely(skb->len > PAGE_SIZE)) {
+ /* @@@ Count drops. */
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ entry = tx_pointer;
+ tx_pointer = (tx_pointer + 1) % TX_BUF_COUNT;
+
+ desc = tx_desc + entry;
+ desc->pkt_length = skb->len;
+ desc->channel = ip->channel;
+
+ skb_copy_and_csum_dev(skb, phys_to_virt(desc->buf_addr));
+ dev_kfree_skb(skb);
+
+ ixp2000_reg_write(RING_TX_PENDING,
+ TX_BUF_DESC_BASE + (entry * sizeof(struct ixpdev_tx_desc)));
+
+ dev->trans_start = jiffies;
+
+ local_irq_disable();
+ ip->tx_queue_entries++;
+ if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
+ netif_stop_queue(dev);
+ local_irq_enable();
+
+ return 0;
+}
+
+
+static int ixpdev_rx(struct net_device *dev, int *budget)
+{
+ while (*budget > 0) {
+ struct ixpdev_rx_desc *desc;
+ struct sk_buff *skb;
+ void *buf;
+ u32 _desc;
+
+ _desc = ixp2000_reg_read(RING_RX_DONE);
+ if (_desc == 0)
+ return 0;
+
+ desc = rx_desc +
+ ((_desc - RX_BUF_DESC_BASE) / sizeof(struct ixpdev_rx_desc));
+ buf = phys_to_virt(desc->buf_addr);
+
+ if (desc->pkt_length < 4 || desc->pkt_length > PAGE_SIZE) {
+ printk(KERN_ERR "ixp2000: rx err, length %d\n",
+ desc->pkt_length);
+ goto err;
+ }
+
+ if (desc->channel < 0 || desc->channel >= nds_count) {
+ printk(KERN_ERR "ixp2000: rx err, channel %d\n",
+ desc->channel);
+ goto err;
+ }
+
+ /* @@@ Make FCS stripping configurable. */
+ desc->pkt_length -= 4;
+
+ if (unlikely(!netif_running(nds[desc->channel])))
+ goto err;
+
+ skb = dev_alloc_skb(desc->pkt_length + 2);
+ if (likely(skb != NULL)) {
+ skb->dev = nds[desc->channel];
+ skb_reserve(skb, 2);
+ eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+ skb_put(skb, desc->pkt_length);
+ skb->protocol = eth_type_trans(skb, skb->dev);
+
+ skb->dev->last_rx = jiffies;
+
+ netif_receive_skb(skb);
+ }
+
+err:
+ ixp2000_reg_write(RING_RX_PENDING, _desc);
+ dev->quota--;
+ (*budget)--;
+ }
+
+ return 1;
+}
+
+/* dev always points to nds[0]. */
+static int ixpdev_poll(struct net_device *dev, int *budget)
+{
+ /* @@@ Have to stop polling when nds[0] is administratively
+ * downed while we are polling. */
+ do {
+ ixp2000_reg_write(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0x00ff);
+
+ if (ixpdev_rx(dev, budget))
+ return 1;
+ } while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
+
+ netif_rx_complete(dev);
+ ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
+
+ return 0;
+}
+
+static void ixpdev_tx_complete(void)
+{
+ int channel;
+ u32 wake;
+
+ wake = 0;
+ while (1) {
+ struct ixpdev_priv *ip;
+ u32 desc;
+ int entry;
+
+ desc = ixp2000_reg_read(RING_TX_DONE);
+ if (desc == 0)
+ break;
+
+ /* @@@ Check whether entries come back in order. */
+ entry = (desc - TX_BUF_DESC_BASE) / sizeof(struct ixpdev_tx_desc);
+ channel = tx_desc[entry].channel;
+
+ if (channel < 0 || channel >= nds_count) {
+ printk(KERN_ERR "ixp2000: txcomp channel index "
+ "out of bounds (%d, %.8i, %d)\n",
+ channel, (unsigned int)desc, entry);
+ continue;
+ }
+
+ ip = netdev_priv(nds[channel]);
+ if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
+ wake |= 1 << channel;
+ ip->tx_queue_entries--;
+ }
+
+ for (channel = 0; wake != 0; channel++) {
+ if (wake & (1 << channel)) {
+ netif_wake_queue(nds[channel]);
+ wake &= ~(1 << channel);
+ }
+ }
+}
+
+static irqreturn_t ixpdev_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ u32 status;
+
+ status = ixp2000_reg_read(IXP2000_IRQ_THD_STATUS_A_0);
+ if (status == 0)
+ return IRQ_NONE;
+
+ /*
+ * Any of the eight receive units signaled RX?
+ */
+ if (status & 0x00ff) {
+ ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
+ if (likely(__netif_rx_schedule_prep(nds[0]))) {
+ __netif_rx_schedule(nds[0]);
+ } else {
+ printk(KERN_CRIT "ixp2000: irq while polling!!\n");
+ }
+ }
+
+ /*
+ * Any of the eight transmit units signaled TXdone?
+ */
+ if (status & 0xff00) {
+ ixp2000_reg_wrb(IXP2000_IRQ_THD_RAW_STATUS_A_0, 0xff00);
+ ixpdev_tx_complete();
+ }
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ixpdev_poll_controller(struct net_device *dev)
+{
+ disable_irq(IRQ_IXP2000_THDA0);
+ ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+ enable_irq(IRQ_IXP2000_THDA0);
+}
+#endif
+
+static int ixpdev_open(struct net_device *dev)
+{
+ struct ixpdev_priv *ip = netdev_priv(dev);
+ int err;
+
+ if (!nds_open++) {
+ err = request_irq(IRQ_IXP2000_THDA0, ixpdev_interrupt,
+ SA_SHIRQ, "ixp2000_eth", nds);
+ if (err) {
+ nds_open--;
+ return err;
+ }
+
+ ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0xffff);
+ }
+
+ set_port_admin_status(ip->channel, 1);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int ixpdev_close(struct net_device *dev)
+{
+ struct ixpdev_priv *ip = netdev_priv(dev);
+
+ netif_stop_queue(dev);
+ set_port_admin_status(ip->channel, 0);
+
+ if (!--nds_open) {
+ ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0xffff);
+ free_irq(IRQ_IXP2000_THDA0, nds);
+ }
+
+ return 0;
+}
+
+struct net_device *ixpdev_alloc(int channel, int sizeof_priv)
+{
+ struct net_device *dev;
+ struct ixpdev_priv *ip;
+
+ dev = alloc_etherdev(sizeof_priv);
+ if (dev == NULL)
+ return NULL;
+
+ dev->hard_start_xmit = ixpdev_xmit;
+ dev->poll = ixpdev_poll;
+ dev->open = ixpdev_open;
+ dev->stop = ixpdev_close;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = ixpdev_poll_controller;
+#endif
+
+ dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ dev->weight = 64;
+
+ ip = netdev_priv(dev);
+ ip->channel = channel;
+ ip->tx_queue_entries = 0;
+
+ return dev;
+}
+
+int ixpdev_init(int __nds_count, struct net_device **__nds,
+ void (*__set_port_admin_status)(int port, int up))
+{
+ int i;
+ int err;
+
+ if (RX_BUF_COUNT > 192 || TX_BUF_COUNT > 192) {
+ static void __too_many_rx_or_tx_buffers(void);
+ __too_many_rx_or_tx_buffers();
+ }
+
+ printk(KERN_INFO "IXP2000 MSF ethernet driver %s\n", DRV_MODULE_VERSION);
+
+ nds_count = __nds_count;
+ nds = __nds;
+ set_port_admin_status = __set_port_admin_status;
+
+ for (i = 0; i < RX_BUF_COUNT; i++) {
+ void *buf;
+
+ buf = (void *)get_zeroed_page(GFP_KERNEL);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ while (--i >= 0)
+ free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+ goto err_out;
+ }
+ rx_desc[i].buf_addr = virt_to_phys(buf);
+ rx_desc[i].buf_length = PAGE_SIZE;
+ }
+
+ /* @@@ Maybe we shouldn't be preallocating TX buffers. */
+ for (i = 0; i < TX_BUF_COUNT; i++) {
+ void *buf;
+
+ buf = (void *)get_zeroed_page(GFP_KERNEL);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ while (--i >= 0)
+ free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+ goto err_free_rx;
+ }
+ tx_desc[i].buf_addr = virt_to_phys(buf);
+ }
+
+ /* 256 entries, ring status set means 'empty', base address 0x0000. */
+ ixp2000_reg_write(RING_RX_PENDING_BASE, 0x44000000);
+ ixp2000_reg_write(RING_RX_PENDING_HEAD, 0x00000000);
+ ixp2000_reg_write(RING_RX_PENDING_TAIL, 0x00000000);
+
+ /* 256 entries, ring status set means 'full', base address 0x0400. */
+ ixp2000_reg_write(RING_RX_DONE_BASE, 0x40000400);
+ ixp2000_reg_write(RING_RX_DONE_HEAD, 0x00000000);
+ ixp2000_reg_write(RING_RX_DONE_TAIL, 0x00000000);
+
+ for (i = 0; i < RX_BUF_COUNT; i++) {
+ ixp2000_reg_write(RING_RX_PENDING,
+ RX_BUF_DESC_BASE + (i * sizeof(struct ixpdev_rx_desc)));
+ }
+
+ ixp2000_uengine_load(0, &ixp2400_rx);
+ ixp2000_uengine_start_contexts(0, 0xff);
+
+ /* 256 entries, ring status set means 'empty', base address 0x0800. */
+ ixp2000_reg_write(RING_TX_PENDING_BASE, 0x44000800);
+ ixp2000_reg_write(RING_TX_PENDING_HEAD, 0x00000000);
+ ixp2000_reg_write(RING_TX_PENDING_TAIL, 0x00000000);
+
+ /* 256 entries, ring status set means 'full', base address 0x0c00. */
+ ixp2000_reg_write(RING_TX_DONE_BASE, 0x40000c00);
+ ixp2000_reg_write(RING_TX_DONE_HEAD, 0x00000000);
+ ixp2000_reg_write(RING_TX_DONE_TAIL, 0x00000000);
+
+ ixp2000_uengine_load(1, &ixp2400_tx);
+ ixp2000_uengine_start_contexts(1, 0xff);
+
+ for (i = 0; i < nds_count; i++) {
+ err = register_netdev(nds[i]);
+ if (err) {
+ while (--i >= 0)
+ unregister_netdev(nds[i]);
+ goto err_free_tx;
+ }
+ }
+
+ for (i = 0; i < nds_count; i++) {
+ printk(KERN_INFO "%s: IXP2000 MSF ethernet (port %d), "
+ "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", nds[i]->name, i,
+ nds[i]->dev_addr[0], nds[i]->dev_addr[1],
+ nds[i]->dev_addr[2], nds[i]->dev_addr[3],
+ nds[i]->dev_addr[4], nds[i]->dev_addr[5]);
+ }
+
+ return 0;
+
+err_free_tx:
+ for (i = 0; i < TX_BUF_COUNT; i++)
+ free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+
+err_free_rx:
+ for (i = 0; i < RX_BUF_COUNT; i++)
+ free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+
+err_out:
+ return err;
+}
+
+void ixpdev_deinit(void)
+{
+ int i;
+
+ /* @@@ Flush out pending packets. */
+
+ for (i = 0; i < nds_count; i++)
+ unregister_netdev(nds[i]);
+
+ ixp2000_uengine_stop_contexts(1, 0xff);
+ ixp2000_uengine_stop_contexts(0, 0xff);
+ ixp2000_uengine_reset(0x3);
+
+ for (i = 0; i < TX_BUF_COUNT; i++)
+ free_page((unsigned long)phys_to_virt(tx_desc[i].buf_addr));
+
+ for (i = 0; i < RX_BUF_COUNT; i++)
+ free_page((unsigned long)phys_to_virt(rx_desc[i].buf_addr));
+}
diff --git a/drivers/net/ixp2000/ixpdev.h b/drivers/net/ixp2000/ixpdev.h
new file mode 100644
index 000000000000..bd686cb63058
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev.h
@@ -0,0 +1,27 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __IXPDEV_H
+#define __IXPDEV_H
+
+struct ixpdev_priv
+{
+ int channel;
+ int tx_queue_entries;
+};
+
+struct net_device *ixpdev_alloc(int channel, int sizeof_priv);
+int ixpdev_init(int num_ports, struct net_device **nds,
+ void (*set_port_admin_status)(int port, int up));
+void ixpdev_deinit(void);
+
+
+#endif
diff --git a/drivers/net/ixp2000/ixpdev_priv.h b/drivers/net/ixp2000/ixpdev_priv.h
new file mode 100644
index 000000000000..86aa08ea0c33
--- /dev/null
+++ b/drivers/net/ixp2000/ixpdev_priv.h
@@ -0,0 +1,57 @@
+/*
+ * IXP2000 MSF network device driver
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __IXPDEV_PRIV_H
+#define __IXPDEV_PRIV_H
+
+#define RX_BUF_DESC_BASE 0x00001000
+#define RX_BUF_COUNT ((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_rx_desc)))
+#define TX_BUF_DESC_BASE 0x00002000
+#define TX_BUF_COUNT ((3 * PAGE_SIZE) / (4 * sizeof(struct ixpdev_tx_desc)))
+#define TX_BUF_COUNT_PER_CHAN (TX_BUF_COUNT / 4)
+
+#define RING_RX_PENDING ((u32 *)IXP2000_SCRATCH_RING_VIRT_BASE)
+#define RING_RX_DONE ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 4))
+#define RING_TX_PENDING ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 8))
+#define RING_TX_DONE ((u32 *)(IXP2000_SCRATCH_RING_VIRT_BASE + 12))
+
+#define SCRATCH_REG(x) ((u32 *)(IXP2000_GLOBAL_REG_VIRT_BASE | 0x0800 | (x)))
+#define RING_RX_PENDING_BASE SCRATCH_REG(0x00)
+#define RING_RX_PENDING_HEAD SCRATCH_REG(0x04)
+#define RING_RX_PENDING_TAIL SCRATCH_REG(0x08)
+#define RING_RX_DONE_BASE SCRATCH_REG(0x10)
+#define RING_RX_DONE_HEAD SCRATCH_REG(0x14)
+#define RING_RX_DONE_TAIL SCRATCH_REG(0x18)
+#define RING_TX_PENDING_BASE SCRATCH_REG(0x20)
+#define RING_TX_PENDING_HEAD SCRATCH_REG(0x24)
+#define RING_TX_PENDING_TAIL SCRATCH_REG(0x28)
+#define RING_TX_DONE_BASE SCRATCH_REG(0x30)
+#define RING_TX_DONE_HEAD SCRATCH_REG(0x34)
+#define RING_TX_DONE_TAIL SCRATCH_REG(0x38)
+
+struct ixpdev_rx_desc
+{
+ u32 buf_addr;
+ u32 buf_length;
+ u32 channel;
+ u32 pkt_length;
+};
+
+struct ixpdev_tx_desc
+{
+ u32 buf_addr;
+ u32 pkt_length;
+ u32 channel;
+ u32 unused;
+};
+
+
+#endif
diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ixp2000/pm3386.c
new file mode 100644
index 000000000000..5c7ab7564053
--- /dev/null
+++ b/drivers/net/ixp2000/pm3386.c
@@ -0,0 +1,334 @@
+/*
+ * Helper functions for the PM3386s on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/delay.h>
+#include <linux/netdevice.h>
+#include <asm/io.h>
+#include "pm3386.h"
+
+/*
+ * Read from register 'reg' of PM3386 device 'pm'.
+ */
+static u16 pm3386_reg_read(int pm, int reg)
+{
+ void *_reg;
+ u16 value;
+
+ _reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
+ if (pm == 1)
+ _reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
+
+ value = *((volatile u16 *)(_reg + (reg << 1)));
+
+// printk(KERN_INFO "pm3386_reg_read(%d, %.3x) = %.8x\n", pm, reg, value);
+
+ return value;
+}
+
+/*
+ * Write to register 'reg' of PM3386 device 'pm', and perform
+ * a readback from the identification register.
+ */
+static void pm3386_reg_write(int pm, int reg, u16 value)
+{
+ void *_reg;
+ u16 dummy;
+
+// printk(KERN_INFO "pm3386_reg_write(%d, %.3x, %.8x)\n", pm, reg, value);
+
+ _reg = (void *)ENP2611_PM3386_0_VIRT_BASE;
+ if (pm == 1)
+ _reg = (void *)ENP2611_PM3386_1_VIRT_BASE;
+
+ *((volatile u16 *)(_reg + (reg << 1))) = value;
+
+ dummy = *((volatile u16 *)_reg);
+ __asm__ __volatile__("mov %0, %0" : "+r" (dummy));
+}
+
+/*
+ * Read from port 'port' register 'reg', where the registers
+ * for the different ports are 'spacing' registers apart.
+ */
+static u16 pm3386_port_reg_read(int port, int _reg, int spacing)
+{
+ int reg;
+
+ reg = _reg;
+ if (port & 1)
+ reg += spacing;
+
+ return pm3386_reg_read(port >> 1, reg);
+}
+
+/*
+ * Write to port 'port' register 'reg', where the registers
+ * for the different ports are 'spacing' registers apart.
+ */
+static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value)
+{
+ int reg;
+
+ reg = _reg;
+ if (port & 1)
+ reg += spacing;
+
+ pm3386_reg_write(port >> 1, reg, value);
+}
+
+
+void pm3386_reset(void)
+{
+ u8 mac[3][6];
+
+ /* Save programmed MAC addresses. */
+ pm3386_get_mac(0, mac[0]);
+ pm3386_get_mac(1, mac[1]);
+ pm3386_get_mac(2, mac[2]);
+
+ /* Assert analog and digital reset. */
+ pm3386_reg_write(0, 0x002, 0x0060);
+ pm3386_reg_write(1, 0x002, 0x0060);
+ mdelay(1);
+
+ /* Deassert analog reset. */
+ pm3386_reg_write(0, 0x002, 0x0062);
+ pm3386_reg_write(1, 0x002, 0x0062);
+ mdelay(10);
+
+ /* Deassert digital reset. */
+ pm3386_reg_write(0, 0x002, 0x0063);
+ pm3386_reg_write(1, 0x002, 0x0063);
+ mdelay(10);
+
+ /* Restore programmed MAC addresses. */
+ pm3386_set_mac(0, mac[0]);
+ pm3386_set_mac(1, mac[1]);
+ pm3386_set_mac(2, mac[2]);
+
+ /* Disable carrier on all ports. */
+ pm3386_set_carrier(0, 0);
+ pm3386_set_carrier(1, 0);
+ pm3386_set_carrier(2, 0);
+}
+
+static u16 swaph(u16 x)
+{
+ return ((x << 8) | (x >> 8)) & 0xffff;
+}
+
+void pm3386_init_port(int port)
+{
+ int pm = port >> 1;
+
+ /*
+ * Work around ENP2611 bootloader programming MAC address
+ * in reverse.
+ */
+ if (pm3386_port_reg_read(port, 0x30a, 0x100) == 0x0000 &&
+ (pm3386_port_reg_read(port, 0x309, 0x100) & 0xff00) == 0x5000) {
+ u16 temp[3];
+
+ temp[0] = pm3386_port_reg_read(port, 0x308, 0x100);
+ temp[1] = pm3386_port_reg_read(port, 0x309, 0x100);
+ temp[2] = pm3386_port_reg_read(port, 0x30a, 0x100);
+ pm3386_port_reg_write(port, 0x308, 0x100, swaph(temp[2]));
+ pm3386_port_reg_write(port, 0x309, 0x100, swaph(temp[1]));
+ pm3386_port_reg_write(port, 0x30a, 0x100, swaph(temp[0]));
+ }
+
+ /*
+ * Initialise narrowbanding mode. See application note 2010486
+ * for more information. (@@@ We also need to issue a reset
+ * when ROOL or DOOL are detected.)
+ */
+ pm3386_port_reg_write(port, 0x708, 0x10, 0xd055);
+ udelay(500);
+ pm3386_port_reg_write(port, 0x708, 0x10, 0x5055);
+
+ /*
+ * SPI-3 ingress block. Set 64 bytes SPI-3 burst size
+ * towards SPI-3 bridge.
+ */
+ pm3386_port_reg_write(port, 0x122, 0x20, 0x0002);
+
+ /*
+ * Enable ingress protocol checking, and soft reset the
+ * SPI-3 ingress block.
+ */
+ pm3386_reg_write(pm, 0x103, 0x0003);
+ while (!(pm3386_reg_read(pm, 0x103) & 0x80))
+ ;
+
+ /*
+ * SPI-3 egress block. Gather 12288 bytes of the current
+ * packet in the TX fifo before initiating transmit on the
+ * SERDES interface. (Prevents TX underflows.)
+ */
+ pm3386_port_reg_write(port, 0x221, 0x20, 0x0007);
+
+ /*
+ * Enforce odd parity from the SPI-3 bridge, and soft reset
+ * the SPI-3 egress block.
+ */
+ pm3386_reg_write(pm, 0x203, 0x000d & ~(4 << (port & 1)));
+ while ((pm3386_reg_read(pm, 0x203) & 0x000c) != 0x000c)
+ ;
+
+ /*
+ * EGMAC block. Set this channels to reject long preambles,
+ * not send or transmit PAUSE frames, enable preamble checking,
+ * disable frame length checking, enable FCS appending, enable
+ * TX frame padding.
+ */
+ pm3386_port_reg_write(port, 0x302, 0x100, 0x0113);
+
+ /*
+ * Soft reset the EGMAC block.
+ */
+ pm3386_port_reg_write(port, 0x301, 0x100, 0x8000);
+ pm3386_port_reg_write(port, 0x301, 0x100, 0x0000);
+
+ /*
+ * Auto-sense autonegotiation status.
+ */
+ pm3386_port_reg_write(port, 0x306, 0x100, 0x0100);
+
+ /*
+ * Allow reception of jumbo frames.
+ */
+ pm3386_port_reg_write(port, 0x310, 0x100, 9018);
+
+ /*
+ * Allow transmission of jumbo frames.
+ */
+ pm3386_port_reg_write(port, 0x336, 0x100, 9018);
+
+ /* @@@ Should set 0x337/0x437 (RX forwarding threshold.) */
+
+ /*
+ * Set autonegotiation parameters to 'no PAUSE, full duplex.'
+ */
+ pm3386_port_reg_write(port, 0x31c, 0x100, 0x0020);
+
+ /*
+ * Enable and restart autonegotiation.
+ */
+ pm3386_port_reg_write(port, 0x318, 0x100, 0x0003);
+ pm3386_port_reg_write(port, 0x318, 0x100, 0x0002);
+}
+
+void pm3386_get_mac(int port, u8 *mac)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x308, 0x100);
+ mac[0] = temp & 0xff;
+ mac[1] = (temp >> 8) & 0xff;
+
+ temp = pm3386_port_reg_read(port, 0x309, 0x100);
+ mac[2] = temp & 0xff;
+ mac[3] = (temp >> 8) & 0xff;
+
+ temp = pm3386_port_reg_read(port, 0x30a, 0x100);
+ mac[4] = temp & 0xff;
+ mac[5] = (temp >> 8) & 0xff;
+}
+
+void pm3386_set_mac(int port, u8 *mac)
+{
+ pm3386_port_reg_write(port, 0x308, 0x100, (mac[1] << 8) | mac[0]);
+ pm3386_port_reg_write(port, 0x309, 0x100, (mac[3] << 8) | mac[2]);
+ pm3386_port_reg_write(port, 0x30a, 0x100, (mac[5] << 8) | mac[4]);
+}
+
+static u32 pm3386_get_stat(int port, u16 base)
+{
+ u32 value;
+
+ value = pm3386_port_reg_read(port, base, 0x100);
+ value |= pm3386_port_reg_read(port, base + 1, 0x100) << 16;
+
+ return value;
+}
+
+void pm3386_get_stats(int port, struct net_device_stats *stats)
+{
+ /*
+ * Snapshot statistics counters.
+ */
+ pm3386_port_reg_write(port, 0x500, 0x100, 0x0001);
+ while (pm3386_port_reg_read(port, 0x500, 0x100) & 0x0001)
+ ;
+
+ memset(stats, 0, sizeof(*stats));
+
+ stats->rx_packets = pm3386_get_stat(port, 0x510);
+ stats->tx_packets = pm3386_get_stat(port, 0x590);
+ stats->rx_bytes = pm3386_get_stat(port, 0x514);
+ stats->tx_bytes = pm3386_get_stat(port, 0x594);
+ /* @@@ Add other stats. */
+}
+
+void pm3386_set_carrier(int port, int state)
+{
+ pm3386_port_reg_write(port, 0x703, 0x10, state ? 0x1001 : 0x0000);
+}
+
+int pm3386_is_link_up(int port)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x31a, 0x100);
+ temp = pm3386_port_reg_read(port, 0x31a, 0x100);
+
+ return !!(temp & 0x0002);
+}
+
+void pm3386_enable_rx(int port)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x303, 0x100);
+ temp |= 0x1000;
+ pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_disable_rx(int port)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x303, 0x100);
+ temp &= 0xefff;
+ pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_enable_tx(int port)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x303, 0x100);
+ temp |= 0x4000;
+ pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+void pm3386_disable_tx(int port)
+{
+ u16 temp;
+
+ temp = pm3386_port_reg_read(port, 0x303, 0x100);
+ temp &= 0xbfff;
+ pm3386_port_reg_write(port, 0x303, 0x100, temp);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ixp2000/pm3386.h
new file mode 100644
index 000000000000..fe92bb056ac4
--- /dev/null
+++ b/drivers/net/ixp2000/pm3386.h
@@ -0,0 +1,28 @@
+/*
+ * Helper functions for the PM3386s on the Radisys ENP2611
+ * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Dedicated to Marija Kulikova.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __PM3386_H
+#define __PM3386_H
+
+void pm3386_reset(void);
+void pm3386_init_port(int port);
+void pm3386_get_mac(int port, u8 *mac);
+void pm3386_set_mac(int port, u8 *mac);
+void pm3386_get_stats(int port, struct net_device_stats *stats);
+void pm3386_set_carrier(int port, int state);
+int pm3386_is_link_up(int port);
+void pm3386_enable_rx(int port);
+void pm3386_disable_rx(int port);
+void pm3386_enable_tx(int port);
+void pm3386_disable_tx(int port);
+
+
+#endif
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 1d75ca0bb939..d1d714faa6ce 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -309,17 +309,6 @@ static void lance_tx_timeout (struct net_device *dev);
-static void cleanup_card(struct net_device *dev)
-{
- struct lance_private *lp = dev->priv;
- if (dev->dma != 4)
- free_dma(dev->dma);
- release_region(dev->base_addr, LANCE_TOTAL_SIZE);
- kfree(lp->tx_bounce_buffs);
- kfree((void*)lp->rx_buffs);
- kfree(lp);
-}
-
#ifdef MODULE
#define MAX_CARDS 8 /* Max number of interfaces (cards) per module */
@@ -367,6 +356,17 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ struct lance_private *lp = dev->priv;
+ if (dev->dma != 4)
+ free_dma(dev->dma);
+ release_region(dev->base_addr, LANCE_TOTAL_SIZE);
+ kfree(lp->tx_bounce_buffs);
+ kfree((void*)lp->rx_buffs);
+ kfree(lp);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 309d254842cf..646e89fc3562 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -145,13 +145,6 @@ static int __init do_lne390_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, LNE390_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init lne390_probe(int unit)
{
@@ -440,6 +433,13 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, LNE390_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index d8c99f038fa0..06cb460361a8 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -559,55 +559,52 @@ static void mac8390_no_reset(struct net_device *dev)
/* directly from daynaport.c by Alan Cox */
static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
{
- volatile unsigned short *ptr;
- unsigned short *target=to;
+ volatile unsigned char *ptr;
+ unsigned char *target=to;
from<<=1; /* word, skip overhead */
- ptr=(unsigned short *)(dev->mem_start+from);
+ ptr=(unsigned char *)(dev->mem_start+from);
/* Leading byte? */
if (from&2) {
- *((char *)target)++ = *(((char *)ptr++)-1);
+ *target++ = ptr[-1];
+ ptr += 2;
count--;
}
while(count>=2)
{
- *target++=*ptr++; /* Copy and */
- ptr++; /* skip cruft */
+ *(unsigned short *)target = *(unsigned short volatile *)ptr;
+ ptr += 4; /* skip cruft */
+ target += 2;
count-=2;
}
/* Trailing byte? */
if(count)
- {
- /* Big endian */
- unsigned short v=*ptr;
- *((char *)target)=v>>8;
- }
+ *target = *ptr;
}
static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
{
volatile unsigned short *ptr;
- const unsigned short *src=from;
+ const unsigned char *src=from;
to<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+to);
/* Leading byte? */
if (to&2) { /* avoid a byte write (stomps on other data) */
- ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
+ ptr[-1] = (ptr[-1]&0xFF00)|*src++;
ptr++;
count--;
}
while(count>=2)
{
- *ptr++=*src++; /* Copy and */
+ *ptr++=*(unsigned short *)src; /* Copy and */
ptr++; /* skip cruft */
+ src += 2;
count-=2;
}
/* Trailing byte? */
if(count)
{
- /* Big endian */
- unsigned short v=*src;
/* card doesn't like byte writes */
- *ptr=(*ptr&0x00FF)|(v&0xFF00);
+ *ptr=(*ptr&0x00FF)|(*src << 8);
}
}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 3cb9b3fe0cf1..40ae36b20c9d 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -6,7 +6,7 @@
* Copyright (C) 2002 rabeeh@galileo.co.il
*
* Copyright (C) 2003 PMC-Sierra, Inc.,
- * written by Manish Lachwani (lachwani@pmc-sierra.com)
+ * written by Manish Lachwani
*
* Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
*
@@ -35,6 +35,8 @@
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/bitops.h>
#include <linux/delay.h>
@@ -55,13 +57,15 @@
/* Constants */
#define VLAN_HLEN 4
#define FCS_LEN 4
-#define WRAP NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define DMA_ALIGN 8 /* hw requires 8-byte alignment */
+#define HW_IP_ALIGN 2 /* hw aligns IP header */
+#define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
#define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7)
-#define INT_CAUSE_UNMASK_ALL 0x0007ffff
-#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff
-#define INT_CAUSE_MASK_ALL 0x00000000
-#define INT_CAUSE_MASK_ALL_EXT 0x00000000
+#define INT_UNMASK_ALL 0x0007ffff
+#define INT_UNMASK_ALL_EXT 0x0011ffff
+#define INT_MASK_ALL 0x00000000
+#define INT_MASK_ALL_EXT 0x00000000
#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL
#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT
@@ -78,8 +82,9 @@
static int eth_port_link_is_up(unsigned int eth_port_num);
static void eth_port_uc_addr_get(struct net_device *dev,
unsigned char *MacAddr);
-static int mv643xx_eth_real_open(struct net_device *);
-static int mv643xx_eth_real_stop(struct net_device *);
+static void eth_port_set_multicast_list(struct net_device *);
+static int mv643xx_eth_open(struct net_device *);
+static int mv643xx_eth_stop(struct net_device *);
static int mv643xx_eth_change_mtu(struct net_device *, int);
static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
static void eth_port_init_mac_tables(unsigned int eth_port_num);
@@ -124,15 +129,8 @@ static inline void mv_write(int offset, u32 data)
*/
static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&mp->lock, flags);
-
- if ((new_mtu > 9500) || (new_mtu < 64)) {
- spin_unlock_irqrestore(&mp->lock, flags);
+ if ((new_mtu > 9500) || (new_mtu < 64))
return -EINVAL;
- }
dev->mtu = new_mtu;
/*
@@ -142,17 +140,13 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
* to memory is full, which might fail the open function.
*/
if (netif_running(dev)) {
- if (mv643xx_eth_real_stop(dev))
- printk(KERN_ERR
- "%s: Fatal error on stopping device\n",
- dev->name);
- if (mv643xx_eth_real_open(dev))
+ mv643xx_eth_stop(dev);
+ if (mv643xx_eth_open(dev))
printk(KERN_ERR
"%s: Fatal error on opening device\n",
dev->name);
}
- spin_unlock_irqrestore(&mp->lock, flags);
return 0;
}
@@ -170,15 +164,19 @@ static void mv643xx_eth_rx_task(void *data)
struct mv643xx_private *mp = netdev_priv(dev);
struct pkt_info pkt_info;
struct sk_buff *skb;
+ int unaligned;
if (test_and_set_bit(0, &mp->rx_task_busy))
panic("%s: Error in test_set_bit / clear_bit", dev->name);
while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
- skb = dev_alloc_skb(RX_SKB_SIZE);
+ skb = dev_alloc_skb(RX_SKB_SIZE + DMA_ALIGN);
if (!skb)
break;
mp->rx_ring_skbs++;
+ unaligned = (u32)skb->data & (DMA_ALIGN - 1);
+ if (unaligned)
+ skb_reserve(skb, DMA_ALIGN - unaligned);
pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
pkt_info.byte_cnt = RX_SKB_SIZE;
pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
@@ -189,7 +187,7 @@ static void mv643xx_eth_rx_task(void *data)
"%s: Error allocating RX Ring\n", dev->name);
break;
}
- skb_reserve(skb, 2);
+ skb_reserve(skb, HW_IP_ALIGN);
}
clear_bit(0, &mp->rx_task_busy);
/*
@@ -207,7 +205,7 @@ static void mv643xx_eth_rx_task(void *data)
else {
/* Return interrupts */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
- INT_CAUSE_UNMASK_ALL);
+ INT_UNMASK_ALL);
}
#endif
}
@@ -267,6 +265,8 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config);
+
+ eth_port_set_multicast_list(dev);
}
/*
@@ -342,8 +342,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
if (!(eth_int_cause_ext & (BIT0 | BIT8)))
return released;
- spin_lock(&mp->lock);
-
/* Check only queue 0 */
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
if (pkt_info.cmd_sts & BIT0) {
@@ -351,31 +349,21 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev,
stats->tx_errors++;
}
- /*
- * If return_info is different than 0, release the skb.
- * The case where return_info is not 0 is only in case
- * when transmitted a scatter/gather packet, where only
- * last skb releases the whole chain.
- */
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info) {
dev_kfree_skb_irq(pkt_info.return_info);
released = 0;
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
+ }
}
- spin_unlock(&mp->lock);
-
return released;
}
@@ -482,12 +470,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
/* Read interrupt cause registers */
eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL;
+ INT_UNMASK_ALL;
if (eth_int_cause & BIT1)
eth_int_cause_ext = mv_read(
MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
- INT_CAUSE_UNMASK_ALL_EXT;
+ INT_UNMASK_ALL_EXT;
#ifdef MV643XX_NAPI
if (!(eth_int_cause & 0x0007fffd)) {
@@ -512,9 +500,10 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
} else {
if (netif_rx_schedule_prep(dev)) {
/* Mask all the interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
- (port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+ INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
__netif_rx_schedule(dev);
}
#else
@@ -527,9 +516,12 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
* with skb's.
*/
#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
- /* Unmask all interrupts on ethernet port */
+ /* Mask all interrupts on ethernet port */
mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_MASK_ALL);
+ INT_MASK_ALL);
+ /* wait for previous write to take effect */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
queue_task(&mp->rx_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -636,56 +628,6 @@ static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
}
/*
- * mv643xx_eth_open
- *
- * This function is called when openning the network device. The function
- * should initialize all the hardware, initialize cyclic Rx/Tx
- * descriptors chain and buffers and allocate an IRQ to the network
- * device.
- *
- * Input : a pointer to the network device structure
- *
- * Output : zero of success , nonzero if fails.
- */
-
-static int mv643xx_eth_open(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
- unsigned int port_num = mp->port_num;
- int err;
-
- spin_lock_irq(&mp->lock);
-
- err = request_irq(dev->irq, mv643xx_eth_int_handler,
- SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
-
- if (err) {
- printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
- port_num);
- err = -EAGAIN;
- goto out;
- }
-
- if (mv643xx_eth_real_open(dev)) {
- printk("%s: Error opening interface\n", dev->name);
- err = -EBUSY;
- goto out_free;
- }
-
- spin_unlock_irq(&mp->lock);
-
- return 0;
-
-out_free:
- free_irq(dev->irq, dev);
-
-out:
- spin_unlock_irq(&mp->lock);
-
- return err;
-}
-
-/*
* ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
*
* DESCRIPTION:
@@ -777,28 +719,37 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
mp->port_tx_queue_command |= 1;
}
-/* Helper function for mv643xx_eth_open */
-static int mv643xx_eth_real_open(struct net_device *dev)
+/*
+ * mv643xx_eth_open
+ *
+ * This function is called when openning the network device. The function
+ * should initialize all the hardware, initialize cyclic Rx/Tx
+ * descriptors chain and buffers and allocate an IRQ to the network
+ * device.
+ *
+ * Input : a pointer to the network device structure
+ *
+ * Output : zero of success , nonzero if fails.
+ */
+
+static int mv643xx_eth_open(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int size;
+ int err;
+
+ err = request_irq(dev->irq, mv643xx_eth_int_handler,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ if (err) {
+ printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+ port_num);
+ return -EAGAIN;
+ }
/* Stop RX Queues */
mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
- /* Clear the ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Unmask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL);
-
- /* Unmask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
- INT_CAUSE_UNMASK_ALL_EXT);
-
/* Set the MAC Address */
memcpy(mp->port_mac_addr, dev->dev_addr, 6);
@@ -818,14 +769,15 @@ static int mv643xx_eth_real_open(struct net_device *dev)
GFP_KERNEL);
if (!mp->rx_skb) {
printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_irq;
}
mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
GFP_KERNEL);
if (!mp->tx_skb) {
printk(KERN_ERR "%s: Cannot allocate Tx skb ring\n", dev->name);
- kfree(mp->rx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_rx_skb;
}
/* Allocate TX ring */
@@ -845,9 +797,8 @@ static int mv643xx_eth_real_open(struct net_device *dev)
if (!mp->p_tx_desc_area) {
printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
dev->name, size);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
BUG_ON((u32) mp->p_tx_desc_area & 0xf); /* check 16-byte alignment */
memset((void *)mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
@@ -874,13 +825,12 @@ static int mv643xx_eth_real_open(struct net_device *dev)
printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
dev->name);
if (mp->rx_sram_size)
- iounmap(mp->p_rx_desc_area);
+ iounmap(mp->p_tx_desc_area);
else
dma_free_coherent(NULL, mp->tx_desc_area_size,
mp->p_tx_desc_area, mp->tx_desc_dma);
- kfree(mp->rx_skb);
- kfree(mp->tx_skb);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto out_free_tx_skb;
}
memset((void *)mp->p_rx_desc_area, 0, size);
@@ -900,9 +850,26 @@ static int mv643xx_eth_real_open(struct net_device *dev)
mp->tx_int_coal =
eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
- netif_start_queue(dev);
+ /* Clear any pending ethernet port interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+ mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+
+ /* Unmask phy and link status changes interrupts */
+ mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+ INT_UNMASK_ALL_EXT);
+ /* Unmask RX buffer and TX end interrupt */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
return 0;
+
+out_free_tx_skb:
+ kfree(mp->tx_skb);
+out_free_rx_skb:
+ kfree(mp->rx_skb);
+out_free_irq:
+ free_irq(dev->irq, dev);
+
+ return err;
}
static void mv643xx_eth_free_tx_rings(struct net_device *dev)
@@ -910,14 +877,17 @@ static void mv643xx_eth_free_tx_rings(struct net_device *dev)
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
unsigned int curr;
+ struct sk_buff *skb;
/* Stop Tx Queues */
mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
/* Free outstanding skb's on TX rings */
for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
- if (mp->tx_skb[curr]) {
- dev_kfree_skb(mp->tx_skb[curr]);
+ skb = mp->tx_skb[curr];
+ if (skb) {
+ mp->tx_ring_skbs -= skb_shinfo(skb)->nr_frags;
+ dev_kfree_skb(skb);
mp->tx_ring_skbs--;
}
}
@@ -973,44 +943,32 @@ static void mv643xx_eth_free_rx_rings(struct net_device *dev)
* Output : zero if success , nonzero if fails
*/
-/* Helper function for mv643xx_eth_stop */
-
-static int mv643xx_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
{
struct mv643xx_private *mp = netdev_priv(dev);
unsigned int port_num = mp->port_num;
+ /* Mask all interrupts on ethernet port */
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
+
+#ifdef MV643XX_NAPI
+ netif_poll_disable(dev);
+#endif
netif_carrier_off(dev);
netif_stop_queue(dev);
- mv643xx_eth_free_tx_rings(dev);
- mv643xx_eth_free_rx_rings(dev);
-
eth_port_reset(mp->port_num);
- /* Disable ethernet port interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
- mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
-
- /* Mask RX buffer and TX end interrupt */
- mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
-
- /* Mask phy and link status changes interrupts */
- mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
-
- return 0;
-}
-
-static int mv643xx_eth_stop(struct net_device *dev)
-{
- struct mv643xx_private *mp = netdev_priv(dev);
-
- spin_lock_irq(&mp->lock);
+ mv643xx_eth_free_tx_rings(dev);
+ mv643xx_eth_free_rx_rings(dev);
- mv643xx_eth_real_stop(dev);
+#ifdef MV643XX_NAPI
+ netif_poll_enable(dev);
+#endif
free_irq(dev->irq, dev);
- spin_unlock_irq(&mp->lock);
return 0;
}
@@ -1022,20 +980,17 @@ static void mv643xx_tx(struct net_device *dev)
struct pkt_info pkt_info;
while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
- if (pkt_info.return_info) {
- if (skb_shinfo(pkt_info.return_info)->nr_frags)
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
- else
- dma_unmap_single(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt,
- DMA_TO_DEVICE);
+ if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC)
+ dma_unmap_single(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ else
+ dma_unmap_page(NULL, pkt_info.buf_ptr,
+ pkt_info.byte_cnt,
+ DMA_TO_DEVICE);
+ if (pkt_info.return_info)
dev_kfree_skb_irq(pkt_info.return_info);
- } else
- dma_unmap_page(NULL, pkt_info.buf_ptr,
- pkt_info.byte_cnt, DMA_TO_DEVICE);
}
if (netif_queue_stopped(dev) &&
@@ -1053,14 +1008,11 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
struct mv643xx_private *mp = netdev_priv(dev);
int done = 1, orig_budget, work_done;
unsigned int port_num = mp->port_num;
- unsigned long flags;
#ifdef MV643XX_TX_FAST_REFILL
if (++mp->tx_clean_threshold > 5) {
- spin_lock_irqsave(&mp->lock, flags);
mv643xx_tx(dev);
mp->tx_clean_threshold = 0;
- spin_unlock_irqrestore(&mp->lock, flags);
}
#endif
@@ -1078,21 +1030,36 @@ static int mv643xx_poll(struct net_device *dev, int *budget)
}
if (done) {
- spin_lock_irqsave(&mp->lock, flags);
- __netif_rx_complete(dev);
+ netif_rx_complete(dev);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
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);
+ INT_UNMASK_ALL);
}
return done ? 0 : 1;
}
#endif
+/* Hardware can't handle unaligned fragments smaller than 9 bytes.
+ * This helper function detects that case.
+ */
+
+static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
+{
+ unsigned int frag;
+ skb_frag_t *fragp;
+
+ for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+ fragp = &skb_shinfo(skb)->frags[frag];
+ if (fragp->size <= 8 && fragp->page_offset & 0x7)
+ return 1;
+
+ }
+ return 0;
+}
+
+
/*
* mv643xx_eth_start_xmit
*
@@ -1136,12 +1103,19 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 1;
}
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ if (has_tiny_unaligned_frags(skb)) {
+ if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+ stats->tx_dropped++;
+ printk(KERN_DEBUG "%s: failed to linearize tiny "
+ "unaligned fragment\n", dev->name);
+ return 1;
+ }
+ }
+
spin_lock_irqsave(&mp->lock, flags);
- /* Update packet info data structure -- DMA owned, first last */
-#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
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 |
@@ -1150,7 +1124,6 @@ linear:
5 << ETH_TX_IHL_SHIFT;
pkt_info.l4i_chk = 0;
} else {
-
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC |
@@ -1158,14 +1131,16 @@ linear:
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) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP) ) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1183,26 +1158,6 @@ linear:
} else {
unsigned int frag;
- /* Since hardware can't handle unaligned fragments smaller
- * than 9 bytes, if we find any, we linearize the skb
- * and start again. When I've seen it, it's always been
- * the first frag (probably near the end of the page),
- * but we check all frags to be safe.
- */
- for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *fragp;
-
- fragp = &skb_shinfo(skb)->frags[frag];
- if (fragp->size <= 8 && fragp->page_offset & 0x7) {
- skb_linearize(skb, GFP_ATOMIC);
- printk(KERN_DEBUG "%s: unaligned tiny fragment"
- "%d of %d, fixed\n",
- dev->name, frag,
- skb_shinfo(skb)->nr_frags);
- goto linear;
- }
- }
-
/* first frag which is skb header */
pkt_info.byte_cnt = skb_headlen(skb);
pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
@@ -1221,14 +1176,16 @@ linear:
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) {
+ if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_UDP)) {
pkt_info.cmd_sts |= ETH_UDP_FRAME;
pkt_info.l4i_chk = skb->h.uh->check;
- } else if (skb->nh.iph->protocol == IPPROTO_TCP)
+ } else if ((skb->protocol == ETH_P_IP) &&
+ (skb->nh.iph->protocol == IPPROTO_TCP))
pkt_info.l4i_chk = skb->h.th->check;
else {
printk(KERN_ERR
- "%s: chksum proto != TCP or UDP\n",
+ "%s: chksum proto != IPv4 TCP or UDP\n",
dev->name);
spin_unlock_irqrestore(&mp->lock, flags);
return 1;
@@ -1288,6 +1245,8 @@ linear:
}
}
#else
+ spin_lock_irqsave(&mp->lock, flags);
+
pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
ETH_TX_LAST_DESC;
pkt_info.l4i_chk = 0;
@@ -1340,39 +1299,18 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
}
#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);
+ int port_num = mp->port_num;
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_MASK_ALL);
+ /* wait for previous write to complete */
+ mv_read(MV643XX_ETH_INTERRUPT_MASK_REG(port_num));
- mv643xx_disable_irq(mp);
mv643xx_eth_int_handler(netdev->irq, netdev, NULL);
- mv643xx_enable_irq(mp);
+
+ mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), INT_UNMASK_ALL);
}
#endif
@@ -1441,7 +1379,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
* Zero copy can only work if we use Discovery II memory. Else, we will
* have to map the buffers to ISA memory which is only 16 MB
*/
- dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
#endif
@@ -2054,6 +1992,196 @@ static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
}
/*
+ * The entries in each table are indexed by a hash of a packet's MAC
+ * address. One bit in each entry determines whether the packet is
+ * accepted. There are 4 entries (each 8 bits wide) in each register
+ * of the table. The bits in each entry are defined as follows:
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue (ETH_Q0=0)
+ * 7-4 Reserved = 0;
+ */
+static void eth_port_set_filter_table_entry(int table, unsigned char entry)
+{
+ unsigned int table_reg;
+ unsigned int tbl_offset;
+ unsigned int reg_offset;
+
+ tbl_offset = (entry / 4) * 4; /* Register offset of DA table entry */
+ reg_offset = entry % 4; /* Entry offset within the register */
+
+ /* Set "accepts frame bit" at specified table entry */
+ table_reg = mv_read(table + tbl_offset);
+ table_reg |= 0x01 << (8 * reg_offset);
+ mv_write(table + tbl_offset, table_reg);
+}
+
+/*
+ * eth_port_mc_addr - Multicast address settings.
+ *
+ * The MV device supports multicast using two tables:
+ * 1) Special Multicast Table for MAC addresses of the form
+ * 0x01-00-5E-00-00-XX (where XX is between 0x00 and 0x_FF).
+ * The MAC DA[7:0] bits are used as a pointer to the Special Multicast
+ * Table entries in the DA-Filter table.
+ * 2) Other Multicast Table for multicast of another type. A CRC-8bit
+ * is used as an index to the Other Multicast Table entries in the
+ * DA-Filter table. This function calculates the CRC-8bit value.
+ * In either case, eth_port_set_filter_table_entry() is then called
+ * to set to set the actual table entry.
+ */
+static void eth_port_mc_addr(unsigned int eth_port_num, unsigned char *p_addr)
+{
+ unsigned int mac_h;
+ unsigned int mac_l;
+ unsigned char crc_result = 0;
+ int table;
+ int mac_array[48];
+ int crc[8];
+ int i;
+
+ if ((p_addr[0] == 0x01) && (p_addr[1] == 0x00) &&
+ (p_addr[2] == 0x5E) && (p_addr[3] == 0x00) && (p_addr[4] == 0x00)) {
+ table = MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num);
+ eth_port_set_filter_table_entry(table, p_addr[5]);
+ return;
+ }
+
+ /* Calculate CRC-8 out of the given address */
+ mac_h = (p_addr[0] << 8) | (p_addr[1]);
+ mac_l = (p_addr[2] << 24) | (p_addr[3] << 16) |
+ (p_addr[4] << 8) | (p_addr[5] << 0);
+
+ for (i = 0; i < 32; i++)
+ mac_array[i] = (mac_l >> i) & 0x1;
+ for (i = 32; i < 48; i++)
+ mac_array[i] = (mac_h >> (i - 32)) & 0x1;
+
+ crc[0] = mac_array[45] ^ mac_array[43] ^ mac_array[40] ^ mac_array[39] ^
+ mac_array[35] ^ mac_array[34] ^ mac_array[31] ^ mac_array[30] ^
+ mac_array[28] ^ mac_array[23] ^ mac_array[21] ^ mac_array[19] ^
+ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^ mac_array[12] ^
+ mac_array[8] ^ mac_array[7] ^ mac_array[6] ^ mac_array[0];
+
+ crc[1] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[41] ^ mac_array[39] ^ mac_array[36] ^ mac_array[34] ^
+ mac_array[32] ^ mac_array[30] ^ mac_array[29] ^ mac_array[28] ^
+ mac_array[24] ^ mac_array[23] ^ mac_array[22] ^ mac_array[21] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[17] ^ mac_array[16] ^
+ mac_array[15] ^ mac_array[14] ^ mac_array[13] ^ mac_array[12] ^
+ mac_array[9] ^ mac_array[6] ^ mac_array[1] ^ mac_array[0];
+
+ crc[2] = mac_array[47] ^ mac_array[46] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[42] ^ mac_array[39] ^ mac_array[37] ^ mac_array[34] ^
+ mac_array[33] ^ mac_array[29] ^ mac_array[28] ^ mac_array[25] ^
+ mac_array[24] ^ mac_array[22] ^ mac_array[17] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^
+ mac_array[6] ^ mac_array[2] ^ mac_array[1] ^ mac_array[0];
+
+ crc[3] = mac_array[47] ^ mac_array[45] ^ mac_array[44] ^ mac_array[43] ^
+ mac_array[40] ^ mac_array[38] ^ mac_array[35] ^ mac_array[34] ^
+ mac_array[30] ^ mac_array[29] ^ mac_array[26] ^ mac_array[25] ^
+ mac_array[23] ^ mac_array[18] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[7] ^
+ mac_array[3] ^ mac_array[2] ^ mac_array[1];
+
+ crc[4] = mac_array[46] ^ mac_array[45] ^ mac_array[44] ^ mac_array[41] ^
+ mac_array[39] ^ mac_array[36] ^ mac_array[35] ^ mac_array[31] ^
+ mac_array[30] ^ mac_array[27] ^ mac_array[26] ^ mac_array[24] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[15] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[8] ^ mac_array[4] ^
+ mac_array[3] ^ mac_array[2];
+
+ crc[5] = mac_array[47] ^ mac_array[46] ^ mac_array[45] ^ mac_array[42] ^
+ mac_array[40] ^ mac_array[37] ^ mac_array[36] ^ mac_array[32] ^
+ mac_array[31] ^ mac_array[28] ^ mac_array[27] ^ mac_array[25] ^
+ mac_array[20] ^ mac_array[18] ^ mac_array[16] ^ mac_array[15] ^
+ mac_array[13] ^ mac_array[11] ^ mac_array[9] ^ mac_array[5] ^
+ mac_array[4] ^ mac_array[3];
+
+ crc[6] = mac_array[47] ^ mac_array[46] ^ mac_array[43] ^ mac_array[41] ^
+ mac_array[38] ^ mac_array[37] ^ mac_array[33] ^ mac_array[32] ^
+ mac_array[29] ^ mac_array[28] ^ mac_array[26] ^ mac_array[21] ^
+ mac_array[19] ^ mac_array[17] ^ mac_array[16] ^ mac_array[14] ^
+ mac_array[12] ^ mac_array[10] ^ mac_array[6] ^ mac_array[5] ^
+ mac_array[4];
+
+ crc[7] = mac_array[47] ^ mac_array[44] ^ mac_array[42] ^ mac_array[39] ^
+ mac_array[38] ^ mac_array[34] ^ mac_array[33] ^ mac_array[30] ^
+ mac_array[29] ^ mac_array[27] ^ mac_array[22] ^ mac_array[20] ^
+ mac_array[18] ^ mac_array[17] ^ mac_array[15] ^ mac_array[13] ^
+ mac_array[11] ^ mac_array[7] ^ mac_array[6] ^ mac_array[5];
+
+ for (i = 0; i < 8; i++)
+ crc_result = crc_result | (crc[i] << i);
+
+ table = MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num);
+ eth_port_set_filter_table_entry(table, crc_result);
+}
+
+/*
+ * Set the entire multicast list based on dev->mc_list.
+ */
+static void eth_port_set_multicast_list(struct net_device *dev)
+{
+
+ struct dev_mc_list *mc_list;
+ int i;
+ int table_index;
+ struct mv643xx_private *mp = netdev_priv(dev);
+ unsigned int eth_port_num = mp->port_num;
+
+ /* If the device is in promiscuous mode or in all multicast mode,
+ * we will fully populate both multicast tables with accept.
+ * This is guaranteed to yield a match on all multicast addresses...
+ */
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI)) {
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Set all entries in DA filter special multicast
+ * table (Ex_dFSMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+
+ /* Set all entries in DA filter other multicast
+ * table (Ex_dFOMT)
+ * Set for ETH_Q0 for now
+ * Bits
+ * 0 Accept=1, Drop=0
+ * 3-1 Queue ETH_Q0=0
+ * 7-4 Reserved = 0;
+ */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(eth_port_num) + table_index, 0x01010101);
+ }
+ return;
+ }
+
+ /* We will clear out multicast tables every time we get the list.
+ * Then add the entire new list...
+ */
+ for (table_index = 0; table_index <= 0xFC; table_index += 4) {
+ /* Clear DA filter special multicast table (Ex_dFSMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+
+ /* Clear DA filter other multicast table (Ex_dFOMT) */
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
+ }
+
+ /* Get pointer to net_device multicast list and add each one... */
+ for (i = 0, mc_list = dev->mc_list;
+ (i < 256) && (mc_list != NULL) && (i < dev->mc_count);
+ i++, mc_list = mc_list->next)
+ if (mc_list->dmi_addrlen == 6)
+ eth_port_mc_addr(eth_port_num, mc_list->dmi_addr);
+}
+
+/*
* eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
*
* DESCRIPTION:
@@ -2080,11 +2208,11 @@ static void eth_port_init_mac_tables(unsigned int eth_port_num)
for (table_index = 0; table_index <= 0xFC; table_index += 4) {
/* Clear DA filter special multicast table (Ex_dFSMT) */
- mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
/* Clear DA filter other multicast table (Ex_dFOMT) */
- mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
- (eth_port_num) + table_index), 0);
+ mv_write(MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+ (eth_port_num) + table_index, 0);
}
}
@@ -2489,6 +2617,7 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
struct eth_tx_desc *current_descriptor;
struct eth_tx_desc *first_descriptor;
u32 command;
+ unsigned long flags;
/* Do not process Tx ring in case of Tx ring resource error */
if (mp->tx_resource_err)
@@ -2505,6 +2634,8 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
return ETH_ERROR;
}
+ spin_lock_irqsave(&mp->lock, flags);
+
mp->tx_ring_skbs++;
BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
@@ -2554,11 +2685,15 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
mp->tx_resource_err = 1;
mp->tx_curr_desc_q = tx_first_desc;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_QUEUE_LAST_RESOURCE;
}
mp->tx_curr_desc_q = tx_next_desc;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
#else
@@ -2569,11 +2704,14 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
int tx_desc_used;
struct eth_tx_desc *current_descriptor;
unsigned int command_status;
+ unsigned long flags;
/* Do not process Tx ring in case of Tx ring resource error */
if (mp->tx_resource_err)
return ETH_QUEUE_FULL;
+ spin_lock_irqsave(&mp->lock, flags);
+
mp->tx_ring_skbs++;
BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size);
@@ -2604,9 +2742,12 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
/* Check for ring index overlap in the Tx desc ring */
if (tx_desc_curr == tx_desc_used) {
mp->tx_resource_err = 1;
+
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_QUEUE_LAST_RESOURCE;
}
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_OK;
}
#endif
@@ -2629,23 +2770,27 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
* Tx ring 'first' and 'used' indexes are updated.
*
* RETURN:
- * ETH_ERROR in case the routine can not access Tx desc ring.
- * ETH_RETRY in case there is transmission in process.
- * ETH_END_OF_JOB if the routine has nothing to release.
- * ETH_OK otherwise.
+ * ETH_OK on success
+ * ETH_ERROR otherwise.
*
*/
static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
struct pkt_info *p_pkt_info)
{
int tx_desc_used;
+ int tx_busy_desc;
+ struct eth_tx_desc *p_tx_desc_used;
+ unsigned int command_status;
+ unsigned long flags;
+ int err = ETH_OK;
+
+ spin_lock_irqsave(&mp->lock, flags);
+
#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
- int tx_busy_desc = mp->tx_first_desc_q;
+ tx_busy_desc = mp->tx_first_desc_q;
#else
- int tx_busy_desc = mp->tx_curr_desc_q;
+ tx_busy_desc = mp->tx_curr_desc_q;
#endif
- struct eth_tx_desc *p_tx_desc_used;
- unsigned int command_status;
/* Get the Tx Desc ring indexes */
tx_desc_used = mp->tx_used_desc_q;
@@ -2653,22 +2798,30 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
/* Sanity check */
- if (p_tx_desc_used == NULL)
- return ETH_ERROR;
+ if (p_tx_desc_used == NULL) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Stop release. About to overlap the current available Tx descriptor */
- if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err)
- return ETH_END_OF_JOB;
+ if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err) {
+ err = ETH_ERROR;
+ goto out;
+ }
command_status = p_tx_desc_used->cmd_sts;
/* Still transmitting... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
- return ETH_RETRY;
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ err = ETH_ERROR;
+ goto out;
+ }
/* Pass the packet information to the caller */
p_pkt_info->cmd_sts = command_status;
p_pkt_info->return_info = mp->tx_skb[tx_desc_used];
+ p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr;
+ p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt;
mp->tx_skb[tx_desc_used] = NULL;
/* Update the next descriptor to release. */
@@ -2680,7 +2833,10 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
BUG_ON(mp->tx_ring_skbs == 0);
mp->tx_ring_skbs--;
- return ETH_OK;
+out:
+ spin_unlock_irqrestore(&mp->lock, flags);
+
+ return err;
}
/*
@@ -2712,11 +2868,14 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
volatile struct eth_rx_desc *p_rx_desc;
unsigned int command_status;
+ unsigned long flags;
/* Do not process Rx ring in case of Rx ring resource error */
if (mp->rx_resource_err)
return ETH_QUEUE_FULL;
+ spin_lock_irqsave(&mp->lock, flags);
+
/* Get the Rx Desc ring 'curr and 'used' indexes */
rx_curr_desc = mp->rx_curr_desc_q;
rx_used_desc = mp->rx_used_desc_q;
@@ -2728,8 +2887,10 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
rmb();
/* Nothing to receive... */
- if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
+ if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) {
+ spin_unlock_irqrestore(&mp->lock, flags);
return ETH_END_OF_JOB;
+ }
p_pkt_info->byte_cnt = (p_rx_desc->byte_cnt) - RX_BUF_OFFSET;
p_pkt_info->cmd_sts = command_status;
@@ -2749,6 +2910,8 @@ static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
if (rx_next_curr_desc == rx_used_desc)
mp->rx_resource_err = 1;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
@@ -2777,6 +2940,9 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
{
int used_rx_desc; /* Where to return Rx resource */
volatile struct eth_rx_desc *p_used_rx_desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mp->lock, flags);
/* Get 'used' Rx descriptor */
used_rx_desc = mp->rx_used_desc_q;
@@ -2800,6 +2966,8 @@ static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
/* Any Rx return cancels the Rx resource error status */
mp->rx_resource_err = 0;
+ spin_unlock_irqrestore(&mp->lock, flags);
+
return ETH_OK;
}
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 0de8fdd2aa86..94f782d51f0f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -212,15 +212,6 @@ static int __init do_ne_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init ne_probe(int unit)
{
@@ -859,6 +850,15 @@ int init_module(void)
return -ENODEV;
}
+static void cleanup_card(struct net_device *dev)
+{
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ if (idev)
+ pnp_device_detach(idev);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 6d62ada85de6..e6df375a1d4b 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -278,14 +278,6 @@ static int __init do_ne2_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- mca_mark_as_unused(ei_status.priv);
- mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
#ifndef MODULE
struct net_device * __init ne2_probe(int unit)
{
@@ -812,6 +804,14 @@ int init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ mca_mark_as_unused(ei_status.priv);
+ mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
void cleanup_module(void)
{
int this_dev;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index f857ae94d261..b0c3b6ab6263 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -115,6 +115,7 @@
#include <linux/ethtool.h>
#include <linux/timer.h>
#include <linux/if_vlan.h>
+#include <linux/rtnetlink.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index a1ac4bd1696e..a7bb54df75a8 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -415,7 +415,7 @@ typedef enum {
/* directly indexed by chip_t, above */
-const static struct {
+static const struct {
const char *name;
u8 version; /* from RTL8139C docs */
u32 RxConfigMask; /* should clear the bits supported by this chip */
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 71fd41122c91..48774efeec71 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -227,8 +227,6 @@ static char mii_preamble_required = 0;
static void tc574_config(dev_link_t *link);
static void tc574_release(dev_link_t *link);
-static int tc574_event(event_t event, int priority,
- event_callback_args_t *args);
static void mdio_sync(kio_addr_t ioaddr, int bits);
static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
@@ -250,12 +248,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct ethtool_ops netdev_ethtool_ops;
static void set_rx_mode(struct net_device *dev);
-static dev_info_t dev_info = "3c574_cs";
-
-static dev_link_t *tc574_attach(void);
-static void tc574_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void tc574_detach(struct pcmcia_device *p_dev);
/*
tc574_attach() creates an "instance" of the driver, allocating
@@ -263,20 +256,18 @@ static dev_link_t *dev_list;
with Card Services.
*/
-static dev_link_t *tc574_attach(void)
+static int tc574_attach(struct pcmcia_device *p_dev)
{
struct el3_private *lp;
- client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
- int ret;
DEBUG(0, "3c574_attach()\n");
/* Create the PC card device object. */
dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
lp = netdev_priv(dev);
link = &lp->link;
link->priv = dev;
@@ -307,20 +298,13 @@ static dev_link_t *tc574_attach(void)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- tc574_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ tc574_config(link);
+
+ return 0;
} /* tc574_attach */
/*
@@ -332,30 +316,19 @@ static dev_link_t *tc574_attach(void)
*/
-static void tc574_detach(dev_link_t *link)
+static void tc574_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
DEBUG(0, "3c574_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
if (link->dev)
unregister_netdev(dev);
if (link->state & DEV_CONFIG)
tc574_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
free_netdev(dev);
} /* tc574_detach */
@@ -547,56 +520,37 @@ static void tc574_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-*/
-
-static int tc574_event(event_t event, int priority,
- event_callback_args_t *args)
+static int tc574_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- DEBUG(1, "3c574_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc574_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- 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) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc574_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
+
+static int tc574_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ tc574_reset(dev);
+ netif_device_attach(dev);
}
- break;
}
+
return 0;
-} /* tc574_event */
+}
static void dump_status(struct net_device *dev)
{
@@ -1292,10 +1246,11 @@ static struct pcmcia_driver tc574_driver = {
.drv = {
.name = "3c574_cs",
},
- .attach = tc574_attach,
- .event = tc574_event,
- .detach = tc574_detach,
+ .probe = tc574_attach,
+ .remove = tc574_detach,
.id_table = tc574_ids,
+ .suspend = tc574_suspend,
+ .resume = tc574_resume,
};
static int __init init_tc574(void)
@@ -1306,7 +1261,6 @@ static int __init init_tc574(void)
static void __exit exit_tc574(void)
{
pcmcia_unregister_driver(&tc574_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_tc574);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index d83fdd8c1943..1c3c9c666f74 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -143,8 +143,6 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
static void tc589_config(dev_link_t *link);
static void tc589_release(dev_link_t *link);
-static int tc589_event(event_t event, int priority,
- event_callback_args_t *args);
static u16 read_eeprom(kio_addr_t ioaddr, int index);
static void tc589_reset(struct net_device *dev);
@@ -161,12 +159,7 @@ static void el3_tx_timeout(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops;
-static dev_info_t dev_info = "3c589_cs";
-
-static dev_link_t *tc589_attach(void);
-static void tc589_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void tc589_detach(struct pcmcia_device *p_dev);
/*======================================================================
@@ -176,20 +169,18 @@ static dev_link_t *dev_list;
======================================================================*/
-static dev_link_t *tc589_attach(void)
+static int tc589_attach(struct pcmcia_device *p_dev)
{
struct el3_private *lp;
- client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
- int ret;
DEBUG(0, "3c589_attach()\n");
-
+
/* Create new ethernet device */
dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
lp = netdev_priv(dev);
link = &lp->link;
link->priv = dev;
@@ -206,7 +197,7 @@ static dev_link_t *tc589_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
-
+
/* The EL3-specific entries in the device structure. */
SET_MODULE_OWNER(dev);
dev->hard_start_xmit = &el3_start_xmit;
@@ -221,20 +212,13 @@ static dev_link_t *tc589_attach(void)
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- tc589_detach(link);
- return NULL;
- }
-
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ tc589_config(link);
+
+ return 0;
} /* tc589_attach */
/*======================================================================
@@ -246,30 +230,19 @@ static dev_link_t *tc589_attach(void)
======================================================================*/
-static void tc589_detach(dev_link_t *link)
+static void tc589_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
-
+
DEBUG(0, "3c589_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->dev)
unregister_netdev(dev);
if (link->state & DEV_CONFIG)
tc589_release(link);
-
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
+
free_netdev(dev);
} /* tc589_detach */
@@ -421,58 +394,37 @@ static void tc589_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
-======================================================================*/
-
-static int tc589_event(event_t event, int priority,
- event_callback_args_t *args)
+static int tc589_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
-
- DEBUG(1, "3c589_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- tc589_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+ return 0;
+}
+
+static int tc589_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- tc589_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ tc589_reset(dev);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* tc589_event */
+
+ return 0;
+}
/*====================================================================*/
@@ -1067,10 +1019,11 @@ static struct pcmcia_driver tc589_driver = {
.drv = {
.name = "3c589_cs",
},
- .attach = tc589_attach,
- .event = tc589_event,
- .detach = tc589_detach,
+ .probe = tc589_attach,
+ .remove = tc589_detach,
.id_table = tc589_ids,
+ .suspend = tc589_suspend,
+ .resume = tc589_resume,
};
static int __init init_tc589(void)
@@ -1081,7 +1034,6 @@ static int __init init_tc589(void)
static void __exit exit_tc589(void)
{
pcmcia_unregister_driver(&tc589_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_tc589);
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 8bb4e85689ea..01ddfc8cce3f 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -87,8 +87,6 @@ static char *version =
static void axnet_config(dev_link_t *link);
static void axnet_release(dev_link_t *link);
-static int axnet_event(event_t event, int priority,
- event_callback_args_t *args);
static int axnet_open(struct net_device *dev);
static int axnet_close(struct net_device *dev);
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -107,11 +105,7 @@ static void block_input(struct net_device *dev, int count,
static void block_output(struct net_device *dev, int count,
const u_char *buf, const int start_page);
-static dev_link_t *axnet_attach(void);
-static void axnet_detach(dev_link_t *);
-
-static dev_info_t dev_info = "axnet_cs";
-static dev_link_t *dev_list;
+static void axnet_detach(struct pcmcia_device *p_dev);
static void axdev_setup(struct net_device *dev);
static void AX88190_init(struct net_device *dev, int startp);
@@ -147,13 +141,11 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static dev_link_t *axnet_attach(void)
+static int axnet_attach(struct pcmcia_device *p_dev)
{
axnet_dev_t *info;
dev_link_t *link;
struct net_device *dev;
- client_reg_t client_reg;
- int ret;
DEBUG(0, "axnet_attach()\n");
@@ -161,7 +153,7 @@ static dev_link_t *axnet_attach(void)
"eth%d", axdev_setup);
if (!dev)
- return NULL;
+ return -ENOMEM;
info = PRIV(dev);
link = &info->link;
@@ -176,20 +168,13 @@ static dev_link_t *axnet_attach(void)
dev->do_ioctl = &axnet_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- /* Register with Card Services */
- 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);
- axnet_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ axnet_config(link);
+
+ return 0;
} /* axnet_attach */
/*======================================================================
@@ -201,30 +186,19 @@ static dev_link_t *axnet_attach(void)
======================================================================*/
-static void axnet_detach(dev_link_t *link)
+static void axnet_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
DEBUG(0, "axnet_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
if (link->dev)
unregister_netdev(dev);
if (link->state & DEV_CONFIG)
axnet_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
free_netdev(dev);
} /* axnet_detach */
@@ -490,59 +464,39 @@ static void axnet_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
-======================================================================*/
-
-static int axnet_event(event_t event, int priority,
- event_callback_args_t *args)
+static int axnet_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- DEBUG(2, "axnet_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- axnet_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+ return 0;
+}
+
+static int axnet_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- axnet_reset_8390(dev);
- AX88190_init(dev, 1);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ axnet_reset_8390(dev);
+ AX88190_init(dev, 1);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* axnet_event */
+
+ return 0;
+}
+
/*======================================================================
@@ -616,7 +570,7 @@ static int axnet_open(struct net_device *dev)
link->open++;
- request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
+ request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, "axnet_cs", dev);
info->link_status = 0x00;
init_timer(&info->watchdog);
@@ -877,10 +831,11 @@ static struct pcmcia_driver axnet_cs_driver = {
.drv = {
.name = "axnet_cs",
},
- .attach = axnet_attach,
- .event = axnet_event,
- .detach = axnet_detach,
+ .probe = axnet_attach,
+ .remove = axnet_detach,
.id_table = axnet_ids,
+ .suspend = axnet_suspend,
+ .resume = axnet_resume,
};
static int __init init_axnet_cs(void)
@@ -891,7 +846,6 @@ static int __init init_axnet_cs(void)
static void __exit exit_axnet_cs(void)
{
pcmcia_unregister_driver(&axnet_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_axnet_cs);
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index b9355d9498a3..2827a48ea37c 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL");
static void com20020_config(dev_link_t *link);
static void com20020_release(dev_link_t *link);
-static int com20020_event(event_t event, int priority,
- event_callback_args_t *args);
-static dev_info_t dev_info = "com20020_cs";
-
-static dev_link_t *com20020_attach(void);
-static void com20020_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void com20020_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
@@ -145,21 +138,19 @@ typedef struct com20020_dev_t {
======================================================================*/
-static dev_link_t *com20020_attach(void)
+static int com20020_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
com20020_dev_t *info;
struct net_device *dev;
- int ret;
struct arcnet_local *lp;
-
+
DEBUG(0, "com20020_attach()\n");
/* Create new network device */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
- return NULL;
+ return -ENOMEM;
info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
if (!info)
@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
-
link->irq.Instance = info->dev = dev;
link->priv = info;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- com20020_detach(link);
- return NULL;
- }
+ link->state |= DEV_PRESENT;
+ com20020_config(link);
- return link;
+ return 0;
fail_alloc_dev:
kfree(info);
fail_alloc_info:
kfree(link);
- return NULL;
+ return -ENOMEM;
} /* com20020_attach */
/*======================================================================
@@ -226,29 +206,21 @@ fail_alloc_info:
======================================================================*/
-static void com20020_detach(dev_link_t *link)
+static void com20020_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct com20020_dev_t *info = link->priv;
- dev_link_t **linkp;
- struct net_device *dev;
-
+ struct net_device *dev = info->dev;
+
DEBUG(1,"detach...\n");
DEBUG(0, "com20020_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
- dev = info->dev;
-
if (link->dev) {
DEBUG(1,"unregister...\n");
unregister_netdev(dev);
-
+
/*
* this is necessary because we register our IRQ separately
* from card services.
@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link)
if (link->state & DEV_CONFIG)
com20020_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
/* Unlink device structure, free bits */
DEBUG(1,"unlinking...\n");
- *linkp = link->next;
if (link->priv)
{
dev = info->dev;
@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link)
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
}
-/*======================================================================
+static int com20020_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ com20020_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if (link->open) {
+ netif_device_detach(dev);
+ }
+ pcmcia_release_configuration(link->handle);
+ }
-======================================================================*/
+ return 0;
+}
-static int com20020_event(event_t event, int priority,
- event_callback_args_t *args)
+static int com20020_resume(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- com20020_dev_t *info = link->priv;
- struct net_device *dev = info->dev;
+ dev_link_t *link = dev_to_instance(p_dev);
+ com20020_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- DEBUG(1, "com20020_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT;
- com20020_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- }
- pcmcia_release_configuration(link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
+ link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- int ioaddr = dev->base_addr;
- struct arcnet_local *lp = dev->priv;
- ARCRESET;
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ int ioaddr = dev->base_addr;
+ struct arcnet_local *lp = dev->priv;
+ ARCRESET;
+ }
}
- break;
- }
- return 0;
-} /* com20020_event */
+
+ return 0;
+}
static struct pcmcia_device_id com20020_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = {
.drv = {
.name = "com20020_cs",
},
- .attach = com20020_attach,
- .event = com20020_event,
- .detach = com20020_detach,
+ .probe = com20020_attach,
+ .remove = com20020_detach,
.id_table = com20020_ids,
+ .suspend = com20020_suspend,
+ .resume = com20020_resume,
};
static int __init init_com20020_cs(void)
@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void)
static void __exit exit_com20020_cs(void)
{
pcmcia_unregister_driver(&com20020_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_com20020_cs);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 356f50909222..28fe2fb4d6c0 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -88,10 +88,7 @@ static void fmvj18x_config(dev_link_t *link);
static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
static int fmvj18x_setup_mfc(dev_link_t *link);
static void fmvj18x_release(dev_link_t *link);
-static int fmvj18x_event(event_t event, int priority,
- event_callback_args_t *args);
-static dev_link_t *fmvj18x_attach(void);
-static void fmvj18x_detach(dev_link_t *);
+static void fmvj18x_detach(struct pcmcia_device *p_dev);
/*
LAN controller(MBH86960A) specific routines
@@ -108,9 +105,6 @@ static void set_rx_mode(struct net_device *dev);
static void fjn_tx_timeout(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops;
-static dev_info_t dev_info = "fmvj18x_cs";
-static dev_link_t *dev_list;
-
/*
card type
*/
@@ -234,20 +228,18 @@ typedef struct local_info_t {
#define BANK_1U 0x24 /* bank 1 (CONFIG_1) */
#define BANK_2U 0x28 /* bank 2 (CONFIG_1) */
-static dev_link_t *fmvj18x_attach(void)
+static int fmvj18x_attach(struct pcmcia_device *p_dev)
{
local_info_t *lp;
dev_link_t *link;
struct net_device *dev;
- client_reg_t client_reg;
- int ret;
-
+
DEBUG(0, "fmvj18x_attach()\n");
/* Make up a FMVJ18x specific data structure */
dev = alloc_etherdev(sizeof(local_info_t));
if (!dev)
- return NULL;
+ return -ENOMEM;
lp = netdev_priv(dev);
link = &lp->link;
link->priv = dev;
@@ -262,7 +254,7 @@ static dev_link_t *fmvj18x_attach(void)
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &fjn_interrupt;
link->irq.Instance = dev;
-
+
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
@@ -281,37 +273,24 @@ static dev_link_t *fmvj18x_attach(void)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- fmvj18x_detach(link);
- return NULL;
- }
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ fmvj18x_config(link);
+
+ return 0;
} /* fmvj18x_attach */
/*====================================================================*/
-static void fmvj18x_detach(dev_link_t *link)
+static void fmvj18x_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
-
+
DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->dev)
unregister_netdev(dev);
@@ -319,12 +298,6 @@ static void fmvj18x_detach(dev_link_t *link)
if (link->state & DEV_CONFIG)
fmvj18x_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free pieces */
- *linkp = link->next;
free_netdev(dev);
} /* fmvj18x_detach */
@@ -713,51 +686,40 @@ static void fmvj18x_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*====================================================================*/
-
-static int fmvj18x_event(event_t event, int priority,
- event_callback_args_t *args)
+static int fmvj18x_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fmvj18x_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+
+ return 0;
+}
+
+static int fmvj18x_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- fjn_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ fjn_reset(dev);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* fmvj18x_event */
+
+ return 0;
+}
+
+/*====================================================================*/
static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
@@ -789,10 +751,11 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
.drv = {
.name = "fmvj18x_cs",
},
- .attach = fmvj18x_attach,
- .event = fmvj18x_event,
- .detach = fmvj18x_detach,
+ .probe = fmvj18x_attach,
+ .remove = fmvj18x_detach,
.id_table = fmvj18x_ids,
+ .suspend = fmvj18x_suspend,
+ .resume = fmvj18x_resume,
};
static int __init init_fmvj18x_cs(void)
@@ -803,7 +766,6 @@ static int __init init_fmvj18x_cs(void)
static void __exit exit_fmvj18x_cs(void)
{
pcmcia_unregister_driver(&fmvj18x_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_fmvj18x_cs);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b6c140eb9799..b9c7e39576f5 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -108,15 +108,7 @@ MODULE_LICENSE("GPL");
static void ibmtr_config(dev_link_t *link);
static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
static void ibmtr_release(dev_link_t *link);
-static int ibmtr_event(event_t event, int priority,
- event_callback_args_t *args);
-
-static dev_info_t dev_info = "ibmtr_cs";
-
-static dev_link_t *ibmtr_attach(void);
-static void ibmtr_detach(dev_link_t *);
-
-static dev_link_t *dev_list;
+static void ibmtr_detach(struct pcmcia_device *p_dev);
/*====================================================================*/
@@ -146,25 +138,23 @@ static struct ethtool_ops netdev_ethtool_ops = {
======================================================================*/
-static dev_link_t *ibmtr_attach(void)
+static int ibmtr_attach(struct pcmcia_device *p_dev)
{
ibmtr_dev_t *info;
dev_link_t *link;
struct net_device *dev;
- client_reg_t client_reg;
- int ret;
DEBUG(0, "ibmtr_attach()\n");
/* Create new token-ring device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return NULL;
+ if (!info) return -ENOMEM;
memset(info,0,sizeof(*info));
dev = alloc_trdev(sizeof(struct tok_info));
- if (!dev) {
- kfree(info);
- return NULL;
- }
+ if (!dev) {
+ kfree(info);
+ return -ENOMEM;
+ }
link = &info->link;
link->priv = info;
@@ -185,25 +175,13 @@ static dev_link_t *ibmtr_attach(void)
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- goto out_detach;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
-out:
- return link;
+ link->state |= DEV_PRESENT;
+ ibmtr_config(link);
-out_detach:
- ibmtr_detach(link);
- link = NULL;
- goto out;
+ return 0;
} /* ibmtr_attach */
/*======================================================================
@@ -215,22 +193,14 @@ out_detach:
======================================================================*/
-static void ibmtr_detach(dev_link_t *link)
+static void ibmtr_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct ibmtr_dev_t *info = link->priv;
- dev_link_t **linkp;
- struct net_device *dev;
+ struct net_device *dev = info->dev;
DEBUG(0, "ibmtr_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
- dev = info->dev;
-
if (link->dev)
unregister_netdev(dev);
@@ -241,13 +211,8 @@ static void ibmtr_detach(dev_link_t *link)
if (link->state & DEV_CONFIG)
ibmtr_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
free_netdev(dev);
- kfree(info);
+ kfree(info);
} /* ibmtr_detach */
/*======================================================================
@@ -401,63 +366,40 @@ static void ibmtr_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*======================================================================
+static int ibmtr_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ ibmtr_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
+ }
-======================================================================*/
+ return 0;
+}
-static int ibmtr_event(event_t event, int priority,
- event_callback_args_t *args)
+static int ibmtr_resume(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- ibmtr_dev_t *info = link->priv;
- struct net_device *dev = info->dev;
+ dev_link_t *link = dev_to_instance(p_dev);
+ ibmtr_dev_t *info = link->priv;
+ struct net_device *dev = info->dev;
- DEBUG(1, "ibmtr_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- /* set flag to bypass normal interrupt code */
- struct tok_info *priv = netdev_priv(dev);
- priv->sram_phys |= 1;
- netif_device_detach(dev);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT;
- ibmtr_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
+ link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ ibmtr_probe(dev); /* really? */
+ netif_device_attach(dev);
+ }
}
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ibmtr_probe(dev); /* really? */
- netif_device_attach(dev);
- }
- }
- break;
- }
- return 0;
-} /* ibmtr_event */
+
+ return 0;
+}
+
/*====================================================================*/
@@ -514,10 +456,11 @@ static struct pcmcia_driver ibmtr_cs_driver = {
.drv = {
.name = "ibmtr_cs",
},
- .attach = ibmtr_attach,
- .event = ibmtr_event,
- .detach = ibmtr_detach,
+ .probe = ibmtr_attach,
+ .remove = ibmtr_detach,
.id_table = ibmtr_ids,
+ .suspend = ibmtr_suspend,
+ .resume = ibmtr_resume,
};
static int __init init_ibmtr_cs(void)
@@ -528,7 +471,6 @@ static int __init init_ibmtr_cs(void)
static void __exit exit_ibmtr_cs(void)
{
pcmcia_unregister_driver(&ibmtr_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_ibmtr_cs);
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 980d7e5d66cb..4a232254a497 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -388,9 +388,6 @@ static char *version =
DRV_NAME " " DRV_VERSION " (Roger C. Pao)";
#endif
-static dev_info_t dev_info="nmclan_cs";
-static dev_link_t *dev_list;
-
static char *if_names[]={
"Auto", "10baseT", "BNC",
};
@@ -422,8 +419,6 @@ Function Prototypes
static void nmclan_config(dev_link_t *link);
static void nmclan_release(dev_link_t *link);
-static int nmclan_event(event_t event, int priority,
- event_callback_args_t *args);
static void nmclan_reset(struct net_device *dev);
static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -439,8 +434,7 @@ static void set_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops;
-static dev_link_t *nmclan_attach(void);
-static void nmclan_detach(dev_link_t *);
+static void nmclan_detach(struct pcmcia_device *p_dev);
/* ----------------------------------------------------------------------------
nmclan_attach
@@ -449,13 +443,11 @@ nmclan_attach
Services.
---------------------------------------------------------------------------- */
-static dev_link_t *nmclan_attach(void)
+static int nmclan_attach(struct pcmcia_device *p_dev)
{
mace_private *lp;
dev_link_t *link;
struct net_device *dev;
- client_reg_t client_reg;
- int ret;
DEBUG(0, "nmclan_attach()\n");
DEBUG(1, "%s\n", rcsid);
@@ -463,7 +455,7 @@ static dev_link_t *nmclan_attach(void)
/* Create new ethernet device */
dev = alloc_etherdev(sizeof(mace_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
lp = netdev_priv(dev);
link = &lp->link;
link->priv = dev;
@@ -497,20 +489,13 @@ static dev_link_t *nmclan_attach(void)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- nmclan_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ nmclan_config(link);
- return link;
+ return 0;
} /* nmclan_attach */
/* ----------------------------------------------------------------------------
@@ -521,30 +506,19 @@ nmclan_detach
when the device is released.
---------------------------------------------------------------------------- */
-static void nmclan_detach(dev_link_t *link)
+static void nmclan_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
DEBUG(0, "nmclan_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
if (link->dev)
unregister_netdev(dev);
if (link->state & DEV_CONFIG)
nmclan_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
free_netdev(dev);
} /* nmclan_detach */
@@ -801,59 +775,39 @@ static void nmclan_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/* ----------------------------------------------------------------------------
-nmclan_event
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
----------------------------------------------------------------------------- */
-static int nmclan_event(event_t event, int priority,
- event_callback_args_t *args)
+static int nmclan_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
+ }
- DEBUG(1, "nmclan_event(0x%06x)\n", event);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nmclan_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- 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) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- nmclan_reset(dev);
- netif_device_attach(dev);
+ return 0;
+}
+
+static int nmclan_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ nmclan_reset(dev);
+ netif_device_attach(dev);
+ }
}
- }
- break;
- case CS_EVENT_RESET_REQUEST:
- return 1;
- break;
- }
- return 0;
-} /* nmclan_event */
+
+ return 0;
+}
+
/* ----------------------------------------------------------------------------
nmclan_reset
@@ -1681,10 +1635,11 @@ static struct pcmcia_driver nmclan_cs_driver = {
.drv = {
.name = "nmclan_cs",
},
- .attach = nmclan_attach,
- .event = nmclan_event,
- .detach = nmclan_detach,
+ .probe = nmclan_attach,
+ .remove = nmclan_detach,
.id_table = nmclan_ids,
+ .suspend = nmclan_suspend,
+ .resume = nmclan_resume,
};
static int __init init_nmclan_cs(void)
@@ -1695,7 +1650,6 @@ static int __init init_nmclan_cs(void)
static void __exit exit_nmclan_cs(void)
{
pcmcia_unregister_driver(&nmclan_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_nmclan_cs);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 818c185d6438..d85b758f3efa 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -105,8 +105,6 @@ module_param_array(hw_addr, int, NULL, 0);
static void mii_phy_probe(struct net_device *dev);
static void pcnet_config(dev_link_t *link);
static void pcnet_release(dev_link_t *link);
-static int pcnet_event(event_t event, int priority,
- event_callback_args_t *args);
static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev);
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -120,11 +118,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
static int setup_dma_config(dev_link_t *link, int start_pg,
int stop_pg);
-static dev_link_t *pcnet_attach(void);
-static void pcnet_detach(dev_link_t *);
+static void pcnet_detach(struct pcmcia_device *p_dev);
static dev_info_t dev_info = "pcnet_cs";
-static dev_link_t *dev_list;
/*====================================================================*/
@@ -244,19 +240,17 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/
-static dev_link_t *pcnet_attach(void)
+static int pcnet_probe(struct pcmcia_device *p_dev)
{
pcnet_dev_t *info;
dev_link_t *link;
struct net_device *dev;
- client_reg_t client_reg;
- int ret;
DEBUG(0, "pcnet_attach()\n");
/* Create new ethernet device */
dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
- if (!dev) return NULL;
+ if (!dev) return -ENOMEM;
info = PRIV(dev);
link = &info->link;
link->priv = dev;
@@ -271,20 +265,13 @@ static dev_link_t *pcnet_attach(void)
dev->stop = &pcnet_close;
dev->set_config = &set_config;
- /* Register with Card Services */
- 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);
- pcnet_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ pcnet_config(link);
+
+ return 0;
} /* pcnet_attach */
/*======================================================================
@@ -296,31 +283,20 @@ static dev_link_t *pcnet_attach(void)
======================================================================*/
-static void pcnet_detach(dev_link_t *link)
+static void pcnet_detach(struct pcmcia_device *p_dev)
{
- struct net_device *dev = link->priv;
- dev_link_t **linkp;
-
- DEBUG(0, "pcnet_detach(0x%p)\n", link);
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
+ DEBUG(0, "pcnet_detach(0x%p)\n", link);
- if (link->dev)
- unregister_netdev(dev);
+ if (link->dev)
+ unregister_netdev(dev);
- if (link->state & DEV_CONFIG)
- pcnet_release(link);
-
- if (link->handle)
- pcmcia_deregister_client(link->handle);
+ if (link->state & DEV_CONFIG)
+ pcnet_release(link);
- /* Unlink device structure, free bits */
- *linkp = link->next;
- free_netdev(dev);
+ free_netdev(dev);
} /* pcnet_detach */
/*======================================================================
@@ -780,50 +756,39 @@ static void pcnet_release(dev_link_t *link)
======================================================================*/
-static int pcnet_event(event_t event, int priority,
- event_callback_args_t *args)
+static int pcnet_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- DEBUG(2, "pcnet_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- pcnet_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+ return 0;
+}
+
+static int pcnet_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- pcnet_reset_8390(dev);
- NS8390_init(dev, 1);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ pcnet_reset_8390(dev);
+ NS8390_init(dev, 1);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* pcnet_event */
+
+ return 0;
+}
+
/*======================================================================
@@ -1844,11 +1809,12 @@ static struct pcmcia_driver pcnet_driver = {
.drv = {
.name = "pcnet_cs",
},
- .attach = pcnet_attach,
- .event = pcnet_event,
- .detach = pcnet_detach,
+ .probe = pcnet_probe,
+ .remove = pcnet_detach,
.owner = THIS_MODULE,
.id_table = pcnet_ids,
+ .suspend = pcnet_suspend,
+ .resume = pcnet_resume,
};
static int __init init_pcnet_cs(void)
@@ -1860,7 +1826,6 @@ static void __exit exit_pcnet_cs(void)
{
DEBUG(0, "pcnet_cs: unloading\n");
pcmcia_unregister_driver(&pcnet_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_pcnet_cs);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index c7cca842e5ee..0122415dfeef 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -102,10 +102,6 @@ static const char *version =
currently have room for another Tx packet. */
#define MEMORY_WAIT_TIME 8
-static dev_info_t dev_info = "smc91c92_cs";
-
-static dev_link_t *dev_list;
-
struct smc_private {
dev_link_t link;
spinlock_t lock;
@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
/*====================================================================*/
-static dev_link_t *smc91c92_attach(void);
-static void smc91c92_detach(dev_link_t *);
+static void smc91c92_detach(struct pcmcia_device *p_dev);
static void smc91c92_config(dev_link_t *link);
static void smc91c92_release(dev_link_t *link);
-static int smc91c92_event(event_t event, int priority,
- event_callback_args_t *args);
static int smc_open(struct net_device *dev);
static int smc_close(struct net_device *dev);
@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops;
======================================================================*/
-static dev_link_t *smc91c92_attach(void)
+static int smc91c92_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
struct smc_private *smc;
dev_link_t *link;
struct net_device *dev;
- int ret;
DEBUG(0, "smc91c92_attach()\n");
/* Create new ethernet device */
dev = alloc_etherdev(sizeof(struct smc_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
smc = netdev_priv(dev);
link = &smc->link;
link->priv = dev;
@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void)
smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- smc91c92_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ smc91c92_config(link);
- return link;
+ return 0;
} /* smc91c92_attach */
/*======================================================================
@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void)
======================================================================*/
-static void smc91c92_detach(dev_link_t *link)
+static void smc91c92_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
if (link->dev)
unregister_netdev(dev);
if (link->state & DEV_CONFIG)
smc91c92_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
free_netdev(dev);
} /* smc91c92_detach */
@@ -895,6 +868,62 @@ free_cfg_mem:
return rc;
}
+static int smc91c92_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
+
+static int smc91c92_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+ struct smc_private *smc = netdev_priv(dev);
+ int i;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ if ((smc->manfid == MANFID_MEGAHERTZ) &&
+ (smc->cardid == PRODID_MEGAHERTZ_EM3288))
+ mhz_3288_power(link);
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (smc->manfid == MANFID_MOTOROLA)
+ mot_config(link);
+ if ((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid != PRODID_OSITECH_SEVEN)) {
+ /* Power up the card and enable interrupts */
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
+ set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
+ }
+ if (((smc->manfid == MANFID_OSITECH) &&
+ (smc->cardid == PRODID_OSITECH_SEVEN)) ||
+ ((smc->manfid == MANFID_PSION) &&
+ (smc->cardid == PRODID_PSION_NET100))) {
+ /* Download the Seven of Diamonds firmware */
+ for (i = 0; i < sizeof(__Xilinx7OD); i++) {
+ outb(__Xilinx7OD[i], link->io.BasePort1+2);
+ udelay(50);
+ }
+ }
+ if (link->open) {
+ smc_reset(dev);
+ netif_device_attach(dev);
+ }
+ }
+
+ return 0;
+}
+
+
/*======================================================================
This verifies that the chip is some SMC91cXX variant, and returns
@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link)
}
if (width) {
- event_callback_args_t args;
printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
- args.client_data = link;
- smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args);
+ smc91c92_suspend(link->handle);
pcmcia_release_io(link->handle, &link->io);
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
pcmcia_request_io(link->handle, &link->io);
- smc91c92_event(CS_EVENT_CARD_RESET, 0, &args);
+ smc91c92_resume(link->handle);
return check_sig(link);
}
return -ENODEV;
@@ -1172,82 +1199,6 @@ static void smc91c92_release(dev_link_t *link)
/*======================================================================
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
-======================================================================*/
-
-static int smc91c92_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 smc_private *smc = netdev_priv(dev);
- int i;
-
- DEBUG(1, "smc91c92_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- smc91c92_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- 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) {
- if ((smc->manfid == MANFID_MEGAHERTZ) &&
- (smc->cardid == PRODID_MEGAHERTZ_EM3288))
- mhz_3288_power(link);
- pcmcia_request_configuration(link->handle, &link->conf);
- if (smc->manfid == MANFID_MOTOROLA)
- mot_config(link);
- if ((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid != PRODID_OSITECH_SEVEN)) {
- /* Power up the card and enable interrupts */
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
- set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
- }
- if (((smc->manfid == MANFID_OSITECH) &&
- (smc->cardid == PRODID_OSITECH_SEVEN)) ||
- ((smc->manfid == MANFID_PSION) &&
- (smc->cardid == PRODID_PSION_NET100))) {
- /* Download the Seven of Diamonds firmware */
- for (i = 0; i < sizeof(__Xilinx7OD); i++) {
- outb(__Xilinx7OD[i], link->io.BasePort1+2);
- udelay(50);
- }
- }
- if (link->open) {
- smc_reset(dev);
- netif_device_attach(dev);
- }
- }
- break;
- }
- return 0;
-} /* smc91c92_event */
-
-/*======================================================================
-
MII interface support for SMC91cXX based cards
======================================================================*/
@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = {
.drv = {
.name = "smc91c92_cs",
},
- .attach = smc91c92_attach,
- .event = smc91c92_event,
- .detach = smc91c92_detach,
+ .probe = smc91c92_attach,
+ .remove = smc91c92_detach,
.id_table = smc91c92_ids,
+ .suspend = smc91c92_suspend,
+ .resume = smc91c92_resume,
};
static int __init init_smc91c92_cs(void)
@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void)
static void __exit exit_smc91c92_cs(void)
{
pcmcia_unregister_driver(&smc91c92_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_smc91c92_cs);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index ce143f08638a..593d8adee891 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -292,8 +292,6 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
static int has_ce2_string(dev_link_t * link);
static void xirc2ps_config(dev_link_t * link);
static void xirc2ps_release(dev_link_t * link);
-static int xirc2ps_event(event_t event, int priority,
- event_callback_args_t * args);
/****************
* The attach() and detach() entry points are used to create and destroy
@@ -301,8 +299,7 @@ static int xirc2ps_event(event_t event, int priority,
* needed to manage one actual PCMCIA card.
*/
-static dev_link_t *xirc2ps_attach(void);
-static void xirc2ps_detach(dev_link_t *);
+static void xirc2ps_detach(struct pcmcia_device *p_dev);
/****************
* You'll also need to prototype all the functions that will actually
@@ -313,14 +310,6 @@ static void xirc2ps_detach(dev_link_t *);
static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-/*
- * 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 = "xirc2ps_cs";
-
/****************
* A linked list of "instances" of the device. Each actual
* PCMCIA card corresponds to one device instance, and is described
@@ -331,15 +320,7 @@ static dev_info_t dev_info = "xirc2ps_cs";
* device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list;
-
/****************
- * A dev_link_t structure has fields for most things that are needed
- * to keep track of a socket, but there will usually be some device
- * specific information that also needs to be kept track of. The
- * 'priv' pointer in a dev_link_t structure can be used to point to
- * a device-specific private data structure, like this.
- *
* A driver needs to provide a dev_node_t structure for each device
* on a card. In some cases, there is only one device per card (for
* example, ethernet cards, modems). In other cases, there may be
@@ -571,21 +552,19 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
* card insertion event.
*/
-static dev_link_t *
-xirc2ps_attach(void)
+static int
+xirc2ps_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
local_info_t *local;
- int err;
DEBUG(0, "attach()\n");
/* Allocate the device structure */
dev = alloc_etherdev(sizeof(local_info_t));
if (!dev)
- return NULL;
+ return -ENOMEM;
local = netdev_priv(dev);
link = &local->link;
link->priv = dev;
@@ -614,19 +593,13 @@ xirc2ps_attach(void)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
- /* Register with Card Services */
- 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;
- if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
- cs_error(link->handle, RegisterClient, err);
- xirc2ps_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ xirc2ps_config(link);
- return link;
+ return 0;
} /* xirc2ps_attach */
/****************
@@ -637,40 +610,19 @@ xirc2ps_attach(void)
*/
static void
-xirc2ps_detach(dev_link_t * link)
+xirc2ps_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- dev_link_t **linkp;
DEBUG(0, "detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (!*linkp) {
- DEBUG(0, "detach(0x%p): dev_link lost\n", link);
- return;
- }
-
if (link->dev)
unregister_netdev(dev);
- /*
- * If the device is currently configured and active, we won't
- * actually delete it yet. Instead, it is marked so that when
- * the release() function is called, that will trigger a proper
- * detach().
- */
if (link->state & DEV_CONFIG)
xirc2ps_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free it */
- *linkp = link->next;
free_netdev(dev);
} /* xirc2ps_detach */
@@ -1157,67 +1109,41 @@ xirc2ps_release(dev_link_t *link)
/*====================================================================*/
-/****************
- * The card status event handler. Mostly, this schedules other
- * stuff to run after an event is received. A CARD_REMOVAL event
- * also sets some flags to discourage the net drivers from trying
- * to talk to the card any more.
- *
- * When a CARD_REMOVAL event is received, we immediately set a flag
- * to block future accesses to this device. All the functions that
- * actually access the device should check this flag to make sure
- * the card is still present.
- */
-static int
-xirc2ps_event(event_t event, int priority,
- event_callback_args_t * args)
+static int xirc2ps_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
-
- DEBUG(0, "event(%d)\n", (int)event);
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- switch (event) {
- case CS_EVENT_REGISTRATION_COMPLETE:
- DEBUG(0, "registration complete\n");
- break;
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- netif_device_detach(dev);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- xirc2ps_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open) {
- netif_device_detach(dev);
- do_powerdown(dev);
- }
- pcmcia_release_configuration(link->handle);
+ if (link->open) {
+ netif_device_detach(dev);
+ do_powerdown(dev);
+ }
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+ return 0;
+}
+
+static int xirc2ps_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- do_reset(dev,1);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ do_reset(dev,1);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* xirc2ps_event */
+
+ return 0;
+}
+
/*====================================================================*/
@@ -1672,7 +1598,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch(cmd) {
case SIOCGMIIPHY: /* Get the address of the PHY in use. */
data[0] = 0; /* we have only this address */
- /* fall trough */
+ /* fall through */
case SIOCGMIIREG: /* Read the specified MII register. */
data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
break;
@@ -2009,10 +1935,11 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
.drv = {
.name = "xirc2ps_cs",
},
- .attach = xirc2ps_attach,
- .event = xirc2ps_event,
- .detach = xirc2ps_detach,
+ .probe = xirc2ps_attach,
+ .remove = xirc2ps_detach,
.id_table = xirc2ps_ids,
+ .suspend = xirc2ps_suspend,
+ .resume = xirc2ps_resume,
};
static int __init
@@ -2025,7 +1952,6 @@ static void __exit
exit_xirc2ps_cs(void)
{
pcmcia_unregister_driver(&xirc2ps_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_xirc2ps_cs);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index c782a6329805..fa39b944bc46 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -6,7 +6,7 @@ menu "PHY device support"
config PHYLIB
tristate "PHY Device support and infrastructure"
- depends on NET_ETHERNET && (BROKEN || !ARCH_S390)
+ depends on NET_ETHERNET && (BROKEN || !S390)
help
Ethernet controllers are usually attached to PHY
devices. This option provides infrastructure for
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 02940c0fef68..459443b572ce 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -81,7 +81,7 @@ int mdiobus_register(struct mii_bus *bus)
phydev->dev.parent = bus->dev;
phydev->dev.bus = &mdio_bus_type;
- sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
+ snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i);
phydev->bus = bus;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index b8686e47f899..1474b7c5ac0b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -42,7 +42,7 @@
*/
void phy_print_status(struct phy_device *phydev)
{
- pr_info("%s: Link is %s", phydev->dev.bus_id,
+ pr_info("PHY: %s - Link is %s", phydev->dev.bus_id,
phydev->link ? "Up" : "Down");
if (phydev->link)
printk(" - %d/%s", phydev->speed,
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 1bd22cd40c75..87ee3271b17d 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -98,7 +98,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/delay.h>
-#include <linux/lp.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -106,7 +105,6 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n"
#include <linux/skbuff.h>
#include <linux/if_plip.h>
#include <linux/workqueue.h>
-#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/parport.h>
#include <linux/bitops.h>
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 400f652282d7..aa6540b39466 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -189,7 +189,7 @@ ppp_asynctty_open(struct tty_struct *tty)
goto out_free;
tty->disc_data = ap;
-
+ tty->receive_room = 65536;
return 0;
out_free:
@@ -343,12 +343,6 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
return 0;
}
-static int
-ppp_asynctty_room(struct tty_struct *tty)
-{
- return 65535;
-}
-
/*
* This can now be called from hard interrupt level as well
* as soft interrupt level or mainline.
@@ -398,7 +392,6 @@ static struct tty_ldisc ppp_ldisc = {
.write = ppp_asynctty_write,
.ioctl = ppp_asynctty_ioctl,
.poll = ppp_asynctty_poll,
- .receive_room = ppp_asynctty_room,
.receive_buf = ppp_asynctty_receive,
.write_wakeup = ppp_asynctty_wakeup,
};
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 4d51c0c8023d..33cb8254e79d 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -237,7 +237,7 @@ ppp_sync_open(struct tty_struct *tty)
goto out_free;
tty->disc_data = ap;
-
+ tty->receive_room = 65536;
return 0;
out_free:
@@ -384,12 +384,6 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
return 0;
}
-static int
-ppp_sync_room(struct tty_struct *tty)
-{
- return 65535;
-}
-
/*
* This can now be called from hard interrupt level as well
* as soft interrupt level or mainline.
@@ -439,7 +433,6 @@ static struct tty_ldisc ppp_sync_ldisc = {
.write = ppp_sync_write,
.ioctl = ppp_synctty_ioctl,
.poll = ppp_sync_poll,
- .receive_room = ppp_sync_room,
.receive_buf = ppp_sync_receive,
.write_wakeup = ppp_sync_wakeup,
};
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index a842ecc60a34..9369f811075d 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -85,7 +85,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
-static struct proto_ops pppoe_ops;
+static const struct proto_ops pppoe_ops;
static DEFINE_RWLOCK(pppoe_hash_lock);
static struct ppp_channel_ops pppoe_chan_ops;
@@ -383,8 +383,6 @@ static int pppoe_rcv(struct sk_buff *skb,
{
struct pppoe_hdr *ph;
struct pppox_sock *po;
- struct sock *sk;
- int ret;
if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
goto drop;
@@ -395,24 +393,8 @@ static int pppoe_rcv(struct sk_buff *skb,
ph = (struct pppoe_hdr *) skb->nh.raw;
po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
- if (!po)
- goto drop;
-
- sk = sk_pppox(po);
- bh_lock_sock(sk);
-
- /* Socket state is unknown, must put skb into backlog. */
- if (sock_owned_by_user(sk) != 0) {
- sk_add_backlog(sk, skb);
- ret = NET_RX_SUCCESS;
- } else {
- ret = pppoe_rcv_core(sk, skb);
- }
-
- bh_unlock_sock(sk);
- sock_put(sk);
-
- return ret;
+ if (po != NULL)
+ return sk_receive_skb(sk_pppox(po), skb);
drop:
kfree_skb(skb);
out:
@@ -1081,9 +1063,7 @@ static int __init pppoe_proc_init(void)
static inline int pppoe_proc_init(void) { return 0; }
#endif /* CONFIG_PROC_FS */
-/* ->ioctl are set at pppox_create */
-
-static struct proto_ops pppoe_ops = {
+static const struct proto_ops pppoe_ops = {
.family = AF_PPPOX,
.owner = THIS_MODULE,
.release = pppoe_release,
@@ -1099,7 +1079,8 @@ static struct proto_ops pppoe_ops = {
.getsockopt = sock_no_getsockopt,
.sendmsg = pppoe_sendmsg,
.recvmsg = pppoe_recvmsg,
- .mmap = sock_no_mmap
+ .mmap = sock_no_mmap,
+ .ioctl = pppox_ioctl,
};
static struct pppox_proto pppoe_proto = {
diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c
index 0c1e114527fb..9315046b3f55 100644
--- a/drivers/net/pppox.c
+++ b/drivers/net/pppox.c
@@ -68,8 +68,7 @@ EXPORT_SYMBOL(register_pppox_proto);
EXPORT_SYMBOL(unregister_pppox_proto);
EXPORT_SYMBOL(pppox_unbind_sock);
-static int pppox_ioctl(struct socket* sock, unsigned int cmd,
- unsigned long arg)
+int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
struct pppox_sock *po = pppox_sk(sk);
@@ -105,6 +104,7 @@ static int pppox_ioctl(struct socket* sock, unsigned int cmd,
return rc;
}
+EXPORT_SYMBOL(pppox_ioctl);
static int pppox_create(struct socket *sock, int protocol)
{
@@ -119,11 +119,7 @@ static int pppox_create(struct socket *sock, int protocol)
goto out;
rc = pppox_protos[protocol]->create(sock);
- if (!rc) {
- /* We get to set the ioctl handler. */
- /* For everything else, pppox is just a shell. */
- sock->ops->ioctl = pppox_ioctl;
- }
+
module_put(pppox_protos[protocol]->owner);
out:
return rc;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 14a76f7cf900..2e1bed153c39 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -170,7 +170,7 @@ enum phy_version {
#define _R(NAME,MAC,MASK) \
{ .name = NAME, .mac_version = MAC, .RxConfigMask = MASK }
-const static struct {
+static const struct {
const char *name;
u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 669dd52c412a..89c46787676c 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -66,7 +66,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "Version 2.0.9.3"
+#define DRV_VERSION "Version 2.0.9.4"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -412,7 +412,7 @@ static int init_shared_mem(struct s2io_nic *nic)
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;
+ mac_control->fifos[i].max_txds = MAX_SKB_FRAGS + 2;
for (j = 0; j < page_num; j++) {
int k = 0;
@@ -459,6 +459,10 @@ static int init_shared_mem(struct s2io_nic *nic)
}
}
+ nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
+ if (!nic->ufo_in_band_v)
+ return -ENOMEM;
+
/* Allocation and initialization of RXDs in Rings */
size = 0;
for (i = 0; i < config->rx_ring_num; i++) {
@@ -731,6 +735,8 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_control->stats_mem,
mac_control->stats_mem_phy);
}
+ if (nic->ufo_in_band_v)
+ kfree(nic->ufo_in_band_v);
}
/**
@@ -2003,6 +2009,49 @@ static int start_nic(struct s2io_nic *nic)
return SUCCESS;
}
+/**
+ * s2io_txdl_getskb - Get the skb from txdl, unmap and return skb
+ */
+static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, int get_off)
+{
+ nic_t *nic = fifo_data->nic;
+ struct sk_buff *skb;
+ TxD_t *txds;
+ u16 j, frg_cnt;
+
+ txds = txdlp;
+ if (txds->Host_Control == (u64)(long)nic->ufo_in_band_v) {
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txds->Buffer_Pointer, sizeof(u64),
+ PCI_DMA_TODEVICE);
+ txds++;
+ }
+
+ skb = (struct sk_buff *) ((unsigned long)
+ txds->Host_Control);
+ if (!skb) {
+ memset(txdlp, 0, (sizeof(TxD_t) * fifo_data->max_txds));
+ return NULL;
+ }
+ pci_unmap_single(nic->pdev, (dma_addr_t)
+ txds->Buffer_Pointer,
+ skb->len - skb->data_len,
+ PCI_DMA_TODEVICE);
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ if (frg_cnt) {
+ txds++;
+ for (j = 0; j < frg_cnt; j++, txds++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[j];
+ if (!txds->Buffer_Pointer)
+ break;
+ pci_unmap_page(nic->pdev, (dma_addr_t)
+ txds->Buffer_Pointer,
+ frag->size, PCI_DMA_TODEVICE);
+ }
+ }
+ txdlp->Host_Control = 0;
+ return(skb);
+}
/**
* free_tx_buffers - Free all queued Tx buffers
@@ -2020,7 +2069,7 @@ static void free_tx_buffers(struct s2io_nic *nic)
int i, j;
mac_info_t *mac_control;
struct config_param *config;
- int cnt = 0, frg_cnt;
+ int cnt = 0;
mac_control = &nic->mac_control;
config = &nic->config;
@@ -2029,38 +2078,11 @@ static void free_tx_buffers(struct s2io_nic *nic)
for (j = 0; j < config->tx_cfg[i].fifo_len - 1; 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) *
- 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;
+ skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
+ if (skb) {
+ dev_kfree_skb(skb);
+ cnt++;
}
- dev_kfree_skb(skb);
- memset(txdp, 0, sizeof(TxD_t) * config->max_txds);
- cnt++;
}
DBG_PRINT(INTR_DBG,
"%s:forcibly freeing %d skbs on FIFO%d\n",
@@ -2661,7 +2683,6 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
tx_curr_get_info_t get_info, put_info;
struct sk_buff *skb;
TxD_t *txdlp;
- u16 j, frg_cnt;
get_info = fifo_data->tx_curr_get_info;
put_info = fifo_data->tx_curr_put_info;
@@ -2684,8 +2705,7 @@ to loss of link\n");
}
}
- skb = (struct sk_buff *) ((unsigned long)
- txdlp->Host_Control);
+ skb = s2io_txdl_getskb(fifo_data, txdlp, get_info.offset);
if (skb == NULL) {
DBG_PRINT(ERR_DBG, "%s: Null skb ",
__FUNCTION__);
@@ -2693,34 +2713,6 @@ to loss of link\n");
return;
}
- 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);
- }
- 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);
@@ -3331,7 +3323,7 @@ failed\n", dev->name);
s2io_msix_fifo_handle, 0, sp->desc1,
sp->s2io_entries[i].arg);
DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
- sp->msix_info[i].addr);
+ (unsigned long long)sp->msix_info[i].addr);
} else {
sprintf(sp->desc2, "%s:MSI-X-%d-RX",
dev->name, i);
@@ -3339,7 +3331,7 @@ failed\n", dev->name);
s2io_msix_ring_handle, 0, sp->desc2,
sp->s2io_entries[i].arg);
DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
- sp->msix_info[i].addr);
+ (unsigned long long)sp->msix_info[i].addr);
}
if (err) {
DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
@@ -3527,6 +3519,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
+ txdp->Control_1 = 0;
+ txdp->Control_2 = 0;
#ifdef NETIF_F_TSO
mss = skb_shinfo(skb)->tso_size;
if (mss) {
@@ -3534,19 +3528,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
}
#endif
-
- frg_cnt = skb_shinfo(skb)->nr_frags;
- frg_len = skb->len - skb->data_len;
-
- 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 |
TXD_TX_CKO_UDP_EN);
}
-
+ txdp->Control_1 |= TXD_GATHER_CODE_FIRST;
+ txdp->Control_1 |= TXD_LIST_OWN_XENA;
txdp->Control_2 |= config->tx_intr_type;
if (sp->vlgrp && vlan_tx_tag_present(skb)) {
@@ -3554,10 +3542,40 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
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;
+ frg_len = skb->len - skb->data_len;
+ if (skb_shinfo(skb)->ufo_size) {
+ int ufo_size;
+
+ ufo_size = skb_shinfo(skb)->ufo_size;
+ ufo_size &= ~7;
+ txdp->Control_1 |= TXD_UFO_EN;
+ txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+ txdp->Control_1 |= TXD_BUFFER0_SIZE(8);
+#ifdef __BIG_ENDIAN
+ sp->ufo_in_band_v[put_off] =
+ (u64)skb_shinfo(skb)->ip6_frag_id;
+#else
+ sp->ufo_in_band_v[put_off] =
+ (u64)skb_shinfo(skb)->ip6_frag_id << 32;
+#endif
+ txdp->Host_Control = (unsigned long)sp->ufo_in_band_v;
+ txdp->Buffer_Pointer = pci_map_single(sp->pdev,
+ sp->ufo_in_band_v,
+ sizeof(u64), PCI_DMA_TODEVICE);
+ txdp++;
+ txdp->Control_1 = 0;
+ txdp->Control_2 = 0;
+ }
+
+ txdp->Buffer_Pointer = pci_map_single
+ (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
+ txdp->Host_Control = (unsigned long) skb;
+ txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
+ if (skb_shinfo(skb)->ufo_size)
+ txdp->Control_1 |= TXD_UFO_EN;
+
+ frg_cnt = skb_shinfo(skb)->nr_frags;
/* For fragmented SKB. */
for (i = 0; i < frg_cnt; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
@@ -3569,9 +3587,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
(sp->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
txdp->Control_1 |= TXD_BUFFER0_SIZE(frag->size);
+ if (skb_shinfo(skb)->ufo_size)
+ txdp->Control_1 |= TXD_UFO_EN;
}
txdp->Control_1 |= TXD_GATHER_CODE_LAST;
+ if (skb_shinfo(skb)->ufo_size)
+ frg_cnt++; /* as Txd0 was used for inband header */
+
tx_fifo = mac_control->tx_FIFO_start[queue];
val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;
writeq(val64, &tx_fifo->TxDL_Pointer);
@@ -3583,6 +3606,8 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
if (mss)
val64 |= TX_FIFO_SPECIAL_FUNC;
#endif
+ if (skb_shinfo(skb)->ufo_size)
+ val64 |= TX_FIFO_SPECIAL_FUNC;
writeq(val64, &tx_fifo->List_Control);
mmiowb();
@@ -4721,7 +4746,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
fail = 1;
if (ret_data != 0x012345) {
- DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x4F0. "
+ "Data written %llx Data read %llx\n",
+ dev->name, (unsigned long long)0x12345,
+ (unsigned long long)ret_data);
fail = 1;
}
@@ -4740,7 +4768,10 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)
fail = 1;
if (ret_data != 0x012345) {
- DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. Data written %llx Data read %llx\n", dev->name, (u64)0x12345, ret_data);
+ DBG_PRINT(ERR_DBG, "%s: eeprom test error at offset 0x7F0. "
+ "Data written %llx Data read %llx\n",
+ dev->name, (unsigned long long)0x12345,
+ (unsigned long long)ret_data);
fail = 1;
}
@@ -5190,6 +5221,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
#endif
+ .get_ufo = ethtool_op_get_ufo,
+ .set_ufo = ethtool_op_set_ufo,
.self_test_count = s2io_ethtool_self_test_count,
.self_test = s2io_ethtool_test,
.get_strings = s2io_ethtool_get_strings,
@@ -5941,7 +5974,8 @@ Defaulting to INTA\n");
break;
}
}
- config->max_txds = MAX_SKB_FRAGS + 1;
+ /* + 2 because one Txd for skb->data and one Txd for UFO */
+ config->max_txds = MAX_SKB_FRAGS + 2;
/* Rx side parameters. */
if (rx_ring_sz[0] == 0)
@@ -6035,6 +6069,10 @@ Defaulting to INTA\n");
#ifdef NETIF_F_TSO
dev->features |= NETIF_F_TSO;
#endif
+ if (sp->device_type & XFRAME_II_DEVICE) {
+ dev->features |= NETIF_F_UFO;
+ dev->features |= NETIF_F_HW_CSUM;
+ }
dev->tx_timeout = &s2io_tx_watchdog;
dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 419aad7f10e7..852a6a899d07 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -393,7 +393,9 @@ typedef struct _TxD {
#define TXD_GATHER_CODE_LAST BIT(23)
#define TXD_TCP_LSO_EN BIT(30)
#define TXD_UDP_COF_EN BIT(31)
+#define TXD_UFO_EN BIT(31) | BIT(30)
#define TXD_TCP_LSO_MSS(val) vBIT(val,34,14)
+#define TXD_UFO_MSS(val) vBIT(val,34,14)
#define TXD_BUFFER0_SIZE(val) vBIT(val,48,16)
u64 Control_2;
@@ -789,6 +791,7 @@ struct s2io_nic {
spinlock_t rx_lock;
atomic_t isr_cnt;
+ u64 *ufo_in_band_v;
};
#define RESET_ERROR 1;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index d6388e1533f0..76139478c3df 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -94,7 +94,7 @@ static inline int card_wait_for_busy_clear(const int ioaddr[],
const char* name);
static inline int card_wait_for_ready(const int ioaddr[], const char* name,
unsigned char in[]);
-static inline int card_send_command(const int ioaddr[], const char* name,
+static int card_send_command(const int ioaddr[], const char* name,
const unsigned char out[], unsigned char in[]);
/* SB1000 hardware routines to be used during frame rx interrupt */
@@ -309,7 +309,7 @@ card_wait_for_ready(const int ioaddr[], const char* name, unsigned char in[])
}
/* Card Send Command (cannot be used during an interrupt) */
-static inline int
+static int
card_send_command(const int ioaddr[], const char* name,
const unsigned char out[], unsigned char in[])
{
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 478791e09bf7..b420182eec4b 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -329,7 +329,7 @@ static struct mii_chip_info {
{ NULL, }
};
-const static struct {
+static const struct {
const char *name;
} sis_chip_info[] = {
{ "SiS 190 PCI Fast Ethernet adapter" },
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 1d4d88680db1..3d95fa20cd88 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1,6 +1,6 @@
/* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
Copyright 1999 Silicon Integrated System Corporation
- Revision: 1.08.08 Jan. 22 2005
+ Revision: 1.08.09 Sep. 19 2005
Modified from the driver which is originally written by Donald Becker.
@@ -17,6 +17,7 @@
SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
preliminary Rev. 1.0 Jan. 18, 1998
+ Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
Rev 1.08.07 Nov. 2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
@@ -76,7 +77,7 @@
#include "sis900.h"
#define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005"
+#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"
static char version[] __devinitdata =
KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -538,6 +539,11 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
printk("%2.2x:", (u8)net_dev->dev_addr[i]);
printk("%2.2x.\n", net_dev->dev_addr[i]);
+ /* Detect Wake on Lan support */
+ ret = inl(CFGPMC & PMESP);
+ if (netif_msg_probe(sis_priv) && (ret & PME_D3C) == 0)
+ printk(KERN_INFO "%s: Wake on LAN only available from suspend to RAM.", net_dev->name);
+
return 0;
err_unmap_rx:
@@ -2015,6 +2021,67 @@ static int sis900_nway_reset(struct net_device *net_dev)
return mii_nway_restart(&sis_priv->mii_info);
}
+/**
+ * sis900_set_wol - Set up Wake on Lan registers
+ * @net_dev: the net device to probe
+ * @wol: container for info passed to the driver
+ *
+ * Process ethtool command "wol" to setup wake on lan features.
+ * SiS900 supports sending WoL events if a correct packet is received,
+ * but there is no simple way to filter them to only a subset (broadcast,
+ * multicast, unicast or arp).
+ */
+
+static int sis900_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ long pmctrl_addr = net_dev->base_addr + pmctrl;
+ u32 cfgpmcsr = 0, pmctrl_bits = 0;
+
+ if (wol->wolopts == 0) {
+ pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
+ cfgpmcsr |= ~PME_EN;
+ pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
+ outl(pmctrl_bits, pmctrl_addr);
+ if (netif_msg_wol(sis_priv))
+ printk(KERN_DEBUG "%s: Wake on LAN disabled\n", net_dev->name);
+ return 0;
+ }
+
+ if (wol->wolopts & (WAKE_MAGICSECURE | WAKE_UCAST | WAKE_MCAST
+ | WAKE_BCAST | WAKE_ARP))
+ return -EINVAL;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ pmctrl_bits |= MAGICPKT;
+ if (wol->wolopts & WAKE_PHY)
+ pmctrl_bits |= LINKON;
+
+ outl(pmctrl_bits, pmctrl_addr);
+
+ pci_read_config_dword(sis_priv->pci_dev, CFGPMCSR, &cfgpmcsr);
+ cfgpmcsr |= PME_EN;
+ pci_write_config_dword(sis_priv->pci_dev, CFGPMCSR, cfgpmcsr);
+ if (netif_msg_wol(sis_priv))
+ printk(KERN_DEBUG "%s: Wake on LAN enabled\n", net_dev->name);
+
+ return 0;
+}
+
+static void sis900_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ long pmctrl_addr = net_dev->base_addr + pmctrl;
+ u32 pmctrl_bits;
+
+ pmctrl_bits = inl(pmctrl_addr);
+ if (pmctrl_bits & MAGICPKT)
+ wol->wolopts |= WAKE_MAGIC;
+ if (pmctrl_bits & LINKON)
+ wol->wolopts |= WAKE_PHY;
+
+ wol->supported = (WAKE_PHY | WAKE_MAGIC);
+}
+
static struct ethtool_ops sis900_ethtool_ops = {
.get_drvinfo = sis900_get_drvinfo,
.get_msglevel = sis900_get_msglevel,
@@ -2023,6 +2090,8 @@ static struct ethtool_ops sis900_ethtool_ops = {
.get_settings = sis900_get_settings,
.set_settings = sis900_set_settings,
.nway_reset = sis900_nway_reset,
+ .get_wol = sis900_get_wol,
+ .set_wol = sis900_set_wol
};
/**
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index de3c06735d15..4233ea55670f 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -33,6 +33,7 @@ enum sis900_registers {
rxcfg=0x34, //Receive Configuration Register
flctrl=0x38, //Flow Control Register
rxlen=0x3c, //Receive Packet Length Register
+ cfgpmcsr=0x44, //Configuration Power Management Control/Status Register
rfcr=0x48, //Receive Filter Control Register
rfdr=0x4C, //Receive Filter Data Register
pmctrl=0xB0, //Power Management Control Register
@@ -140,6 +141,50 @@ enum sis96x_eeprom_command {
EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
};
+/* PCI Registers */
+enum sis900_pci_registers {
+ CFGPMC = 0x40,
+ CFGPMCSR = 0x44
+};
+
+/* Power management capabilities bits */
+enum sis900_cfgpmc_register_bits {
+ PMVER = 0x00070000,
+ DSI = 0x00100000,
+ PMESP = 0xf8000000
+};
+
+enum sis900_pmesp_bits {
+ PME_D0 = 0x1,
+ PME_D1 = 0x2,
+ PME_D2 = 0x4,
+ PME_D3H = 0x8,
+ PME_D3C = 0x10
+};
+
+/* Power management control/status bits */
+enum sis900_cfgpmcsr_register_bits {
+ PMESTS = 0x00004000,
+ PME_EN = 0x00000100, // Power management enable
+ PWR_STA = 0x00000003 // Current power state
+};
+
+/* Wake-on-LAN support. */
+enum sis900_power_management_control_register_bits {
+ LINKLOSS = 0x00000001,
+ LINKON = 0x00000002,
+ MAGICPKT = 0x00000400,
+ ALGORITHM = 0x00000800,
+ FRM1EN = 0x00100000,
+ FRM2EN = 0x00200000,
+ FRM3EN = 0x00400000,
+ FRM1ACS = 0x01000000,
+ FRM2ACS = 0x02000000,
+ FRM3ACS = 0x04000000,
+ WAKEALL = 0x40000000,
+ GATECLK = 0x80000000
+};
+
/* Management Data I/O (mdio) frame */
#define MIIread 0x6000
#define MIIwrite 0x5002
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
index 7653d6e33aa2..afd900d5d730 100644
--- a/drivers/net/sk98lin/Makefile
+++ b/drivers/net/sk98lin/Makefile
@@ -26,8 +26,7 @@ sk98lin-objs := \
skrlmt.o \
sktimer.o \
skvpd.o \
- skxmac2.o \
- skproc.o
+ skxmac2.o
# DBGDEF = \
# -DDEBUG
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index 2dc5728e3ef6..778d9e618ebd 100644
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -60,7 +60,6 @@ extern SK_U64 SkOsGetTime(SK_AC*);
extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
@@ -268,8 +267,6 @@ typedef struct s_DevNet DEV_NET;
struct s_DevNet {
int PortNr;
int NetNr;
- int Mtu;
- int Up;
SK_AC *pAC;
};
@@ -298,6 +295,7 @@ struct s_RxPort {
RXD *pRxdRingTail; /* Tail of Rx rings */
RXD *pRxdRingPrev; /* descriptor given to BMU previously */
int RxdRingFree; /* # of free entrys */
+ int RxCsum; /* use receive checksum hardware */
spinlock_t RxDesRingLock; /* serialize descriptor accesses */
int RxFillLimit; /* limit for buffers in ring */
SK_IOC HwAddr; /* bmu registers address */
@@ -390,12 +388,10 @@ struct s_AC {
SK_IOC IoBase; /* register set of adapter */
int BoardLevel; /* level of active hw init (0-2) */
- char DeviceStr[80]; /* adapter string from vpd */
+
SK_U32 AllocFlag; /* flag allocation of resources */
struct pci_dev *PciDev; /* for access to pci config space */
- SK_U32 PciDevId; /* pci device id */
struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
- char Name[30]; /* driver name */
int RxBufSize; /* length of receive buffers */
struct net_device_stats stats; /* linux 'netstat -i' statistics */
@@ -430,7 +426,6 @@ struct s_AC {
DIM_INFO DynIrqModInfo; /* all data related to DIM */
/* Only for tests */
- int PortUp;
int PortDown;
int ChipsetType; /* Chipset family type
* 0 == Genesis family support
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
index bdc1a5eaaae9..daa9a8d154fc 100644
--- a/drivers/net/sk98lin/h/skvpd.h
+++ b/drivers/net/sk98lin/h/skvpd.h
@@ -130,14 +130,12 @@ typedef struct s_vpd_key {
#ifndef VPD_DO_IO
#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_OUT32(pAC,IoC,Addr,Val) (void)SkPciWriteCfgDWord(pAC,Addr,Val)
#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal)
#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
#else /* VPD_DO_IO */
#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val)
#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
@@ -155,12 +153,6 @@ typedef struct s_vpd_key {
else \
SK_OUT16(pAC,PCI_C(Addr),Val); \
}
-#define VPD_OUT32(pAC,Ioc,Addr,Val) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciWriteCfgDWord(pAC,Addr,Val); \
- else \
- SK_OUT32(pAC,PCI_C(Addr),Val); \
- }
#define VPD_IN8(pAC,Ioc,Addr,pVal) { \
if ((pAC)->DgT.DgUseCfgCycle) \
SkPciReadCfgByte(pAC,Addr,pVal); \
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
index 0fddf61047b4..07c1b4c8699d 100644
--- a/drivers/net/sk98lin/skdim.c
+++ b/drivers/net/sk98lin/skdim.c
@@ -180,7 +180,7 @@ SkDimModerate(SK_AC *pAC) {
/*
** The number of interrupts per sec is the same as expected.
** Evalulate the descriptor-ratio. If it has changed, a resize
- ** in the moderation timer might be usefull
+ ** in the moderation timer might be useful
*/
if (M_DIMINFO.AutoSizing) {
ResizeDimTimerDuration(pAC);
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
index b71769ae4603..4265ed91a9c4 100644
--- a/drivers/net/sk98lin/skethtool.c
+++ b/drivers/net/sk98lin/skethtool.c
@@ -539,6 +539,48 @@ static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *ep
return ret ? -EIO : 0;
}
+/* Only Yukon supports checksum offload. */
+static int setScatterGather(struct net_device *dev, u32 data)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+ return -EOPNOTSUPP;
+ return ethtool_op_set_sg(dev, data);
+}
+
+static int setTxCsum(struct net_device *dev, u32 data)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+ return -EOPNOTSUPP;
+
+ return ethtool_op_set_tx_csum(dev, data);
+}
+
+static u32 getRxCsum(struct net_device *dev)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+
+ return pAC->RxPort[pNet->PortNr].RxCsum;
+}
+
+static int setRxCsum(struct net_device *dev, u32 data)
+{
+ DEV_NET *pNet = netdev_priv(dev);
+ SK_AC *pAC = pNet->pAC;
+
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
+ return -EOPNOTSUPP;
+
+ pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
+ return 0;
+}
+
struct ethtool_ops SkGeEthtoolOps = {
.get_settings = getSettings,
.set_settings = setSettings,
@@ -551,4 +593,10 @@ struct ethtool_ops SkGeEthtoolOps = {
.set_pauseparam = setPauseParams,
.get_link = ethtool_op_get_link,
.get_perm_addr = ethtool_op_get_perm_addr,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = setScatterGather,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = setTxCsum,
+ .get_rx_csum = getRxCsum,
+ .set_rx_csum = setRxCsum,
};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index ae7343934758..a5f2b1ee0752 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -107,10 +107,10 @@
#include "h/skversion.h"
+#include <linux/in.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
#include <linux/dma-mapping.h>
#include <linux/ip.h>
@@ -206,7 +206,6 @@ static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
static void GetConfiguration(SK_AC*);
-static void ProductStr(SK_AC*);
static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
static void FillRxRing(SK_AC*, RX_PORT*);
@@ -235,28 +234,6 @@ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
* Extern Function Prototypes
*
******************************************************************************/
-static const char SKRootName[] = "net/sk98lin";
-static struct proc_dir_entry *pSkRootDir;
-extern struct file_operations sk_proc_fops;
-
-static inline void SkGeProcCreate(struct net_device *dev)
-{
- struct proc_dir_entry *pe;
-
- if (pSkRootDir &&
- (pe = create_proc_entry(dev->name, S_IRUGO, pSkRootDir))) {
- pe->proc_fops = &sk_proc_fops;
- pe->data = dev;
- pe->owner = THIS_MODULE;
- }
-}
-
-static inline void SkGeProcRemove(struct net_device *dev)
-{
- if (pSkRootDir)
- remove_proc_entry(dev->name, pSkRootDir);
-}
-
extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
extern void SkDimDisplayModerationSettings(SK_AC *pAC);
extern void SkDimStartModerationTimer(SK_AC *pAC);
@@ -279,31 +256,48 @@ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
/*****************************************************************************
*
+ * SkPciWriteCfgDWord - write a 32 bit value to pci config space
+ *
+ * Description:
+ * This routine writes a 32 bit value to the pci configuration
+ * space.
+ *
+ * Returns:
+ * 0 - indicate everything worked ok.
+ * != 0 - error indication
+ */
+static inline int SkPciWriteCfgDWord(
+SK_AC *pAC, /* Adapter Control structure pointer */
+int PciAddr, /* PCI register address */
+SK_U32 Val) /* pointer to store the read value */
+{
+ pci_write_config_dword(pAC->PciDev, PciAddr, Val);
+ return(0);
+} /* SkPciWriteCfgDWord */
+
+/*****************************************************************************
+ *
* SkGeInitPCI - Init the PCI resources
*
* Description:
* This function initialize the PCI resources and IO
*
- * Returns: N/A
- *
+ * Returns:
+ * 0 - indicate everything worked ok.
+ * != 0 - error indication
*/
-int SkGeInitPCI(SK_AC *pAC)
+static __devinit int SkGeInitPCI(SK_AC *pAC)
{
struct SK_NET_DEVICE *dev = pAC->dev[0];
struct pci_dev *pdev = pAC->PciDev;
int retval;
- if (pci_enable_device(pdev) != 0) {
- return 1;
- }
-
dev->mem_start = pci_resource_start (pdev, 0);
pci_set_master(pdev);
- if (pci_request_regions(pdev, pAC->Name) != 0) {
- retval = 2;
- goto out_disable;
- }
+ retval = pci_request_regions(pdev, "sk98lin");
+ if (retval)
+ goto out;
#ifdef SK_BIG_ENDIAN
/*
@@ -322,9 +316,8 @@ int SkGeInitPCI(SK_AC *pAC)
* Remap the regs into kernel space.
*/
pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
-
- if (!pAC->IoBase){
- retval = 3;
+ if (!pAC->IoBase) {
+ retval = -EIO;
goto out_release;
}
@@ -332,8 +325,7 @@ int SkGeInitPCI(SK_AC *pAC)
out_release:
pci_release_regions(pdev);
- out_disable:
- pci_disable_device(pdev);
+ out:
return retval;
}
@@ -494,7 +486,7 @@ module_param_array(AutoSizing, charp, NULL, 0);
* 0, if everything is ok
* !=0, on error
*/
-static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
+static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
short i;
unsigned long Flags;
@@ -531,7 +523,7 @@ SK_BOOL DualNet;
if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
printk("HWInit (0) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return(-EAGAIN);
+ return -EIO;
}
SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
@@ -553,7 +545,7 @@ SK_BOOL DualNet;
if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
printk("sk98lin: HWInit (1) failed.\n");
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return(-EAGAIN);
+ return -EIO;
}
SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
@@ -578,27 +570,27 @@ SK_BOOL DualNet;
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
if (pAC->GIni.GIMacsFound == 2) {
- Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+ Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
} else if (pAC->GIni.GIMacsFound == 1) {
Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
- pAC->Name, dev);
+ "sk98lin", dev);
} else {
printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
pAC->GIni.GIMacsFound);
- return -EAGAIN;
+ return -EIO;
}
if (Ret) {
printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
dev->irq);
- return -EAGAIN;
+ return Ret;
}
pAC->AllocFlag |= SK_ALLOC_IRQ;
/* Alloc memory for this board (Mem for RxD/TxD) : */
if(!BoardAllocMem(pAC)) {
printk("No memory for descriptor rings.\n");
- return(-EAGAIN);
+ return -ENOMEM;
}
BoardInitMem(pAC);
@@ -614,7 +606,7 @@ SK_BOOL DualNet;
DualNet)) {
BoardFreeMem(pAC);
printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
- return(-EAGAIN);
+ return -EIO;
}
return (0);
@@ -635,8 +627,7 @@ SK_BOOL DualNet;
* SK_TRUE, if all memory could be allocated
* SK_FALSE, if not
*/
-static SK_BOOL BoardAllocMem(
-SK_AC *pAC)
+static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC)
{
caddr_t pDescrMem; /* pointer to descriptor memory area */
size_t AllocLength; /* length of complete descriptor area */
@@ -729,8 +720,7 @@ size_t AllocLength; /* length of complete descriptor area */
*
* Returns: N/A
*/
-static void BoardInitMem(
-SK_AC *pAC) /* pointer to adapter context */
+static __devinit void BoardInitMem(SK_AC *pAC)
{
int i; /* loop counter */
int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/
@@ -1265,7 +1255,6 @@ struct SK_NET_DEVICE *dev)
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
pAC->MaxPorts++;
- pNet->Up = 1;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
@@ -1395,7 +1384,6 @@ struct SK_NET_DEVICE *dev)
sizeof(SK_PNMI_STRUCT_DATA));
pAC->MaxPorts--;
- pNet->Up = 0;
return (0);
} /* SkGeClose */
@@ -2175,7 +2163,6 @@ rx_start:
pMsg->ip_summed = CHECKSUM_NONE;
#endif
-
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
ForRlmt = SK_RLMT_RX_PROTOCOL;
#if 0
@@ -2550,7 +2537,7 @@ unsigned long Flags;
static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
{
DEV_NET *pNet;
-DEV_NET *pOtherNet;
+struct net_device *pOtherDev;
SK_AC *pAC;
unsigned long Flags;
int i;
@@ -2580,11 +2567,11 @@ SK_EVPARA EvPara;
}
#endif
- pNet->Mtu = NewMtu;
- pOtherNet = netdev_priv(pAC->dev[1 - pNet->NetNr]);
- if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
- return(0);
- }
+ pOtherDev = pAC->dev[1 - pNet->NetNr];
+
+ if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
+ && (NewMtu <= 1500))
+ return 0;
pAC->RxBufSize = NewMtu + 32;
dev->mtu = NewMtu;
@@ -2746,7 +2733,8 @@ SK_EVPARA EvPara;
EvPara.Para32[1] = -1;
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- if (pOtherNet->Up) {
+ if (netif_running(pOtherDev)) {
+ DEV_NET *pOtherNet = netdev_priv(pOtherDev);
EvPara.Para32[0] = pOtherNet->PortNr;
SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
}
@@ -2820,7 +2808,7 @@ unsigned long Flags; /* for spin lock */
pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
- if (pNet->Mtu <= 1500) {
+ if (dev->mtu <= 1500) {
pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
} else {
pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
@@ -2863,7 +2851,7 @@ unsigned long Flags; /* for spin lock */
* Description:
* This function is called if an ioctl is issued on the device.
* There are three subfunction for reading, writing and test-writing
- * the private MIB data structure (usefull for SysKonnect-internal tools).
+ * the private MIB data structure (useful for SysKonnect-internal tools).
*
* Returns:
* 0, if everything is ok
@@ -3771,25 +3759,21 @@ int Capabilities[3][3] =
*
* Returns: N/A
*/
-static void ProductStr(
-SK_AC *pAC /* pointer to adapter context */
+static inline int ProductStr(
+ SK_AC *pAC, /* pointer to adapter context */
+ char *DeviceStr, /* result string */
+ int StrLen /* length of the string */
)
{
-int StrLen = 80; /* length of the string, defined in SK_AC */
char Keyword[] = VPD_NAME; /* vpd productname identifier */
int ReturnCode; /* return code from vpd_read */
unsigned long Flags;
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr,
- &StrLen);
+ ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- if (ReturnCode != 0) {
- /* there was an error reading the vpd data */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
- ("Error reading VPD data: %d\n", ReturnCode));
- pAC->DeviceStr[0] = '\0';
- }
+
+ return ReturnCode;
} /* ProductStr */
/*****************************************************************************
@@ -3992,28 +3976,6 @@ SK_U8 *pVal) /* pointer to store the read value */
/*****************************************************************************
*
- * SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- * This routine writes a 32 bit value to the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciWriteCfgDWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U32 Val) /* pointer to store the read value */
-{
- pci_write_config_dword(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgDWord */
-
-
-/*****************************************************************************
- *
* SkPciWriteCfgWord - write a 16 bit value to pci config space
*
* Description:
@@ -4150,6 +4112,7 @@ SK_BOOL DualNet;
Flags);
break;
case SK_DRV_NET_UP: /* SK_U32 PortIdx */
+ { struct net_device *dev = pAC->dev[Param.Para32[0]];
/* action list 5 */
FromPort = Param.Para32[0];
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4233,22 +4196,12 @@ SK_BOOL DualNet;
printk(" irq moderation: disabled\n");
-#ifdef SK_ZEROCOPY
- if (pAC->ChipsetType)
-#ifdef USE_SK_TX_CHECKSUM
- printk(" scatter-gather: enabled\n");
-#else
- printk(" tx-checksum: disabled\n");
-#endif
- else
- printk(" scatter-gather: disabled\n");
-#else
- printk(" scatter-gather: disabled\n");
-#endif
-
-#ifndef USE_SK_RX_CHECKSUM
- printk(" rx-checksum: disabled\n");
-#endif
+ printk(" scatter-gather: %s\n",
+ (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
+ printk(" tx-checksum: %s\n",
+ (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
+ printk(" rx-checksum: %s\n",
+ pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
} else {
DoPrintInterfaceChange = SK_TRUE;
@@ -4263,9 +4216,9 @@ SK_BOOL DualNet;
}
/* Inform the world that link protocol is up. */
- netif_carrier_on(pAC->dev[Param.Para32[0]]);
-
+ netif_carrier_on(dev);
break;
+ }
case SK_DRV_NET_DOWN: /* SK_U32 Reason */
/* action list 7 */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4479,7 +4432,7 @@ SK_AC *pAc) /* pointer to adapter context */
pAC->DiagModeActive = DIAG_ACTIVE;
if (pAC->BoardLevel > SK_INIT_DATA) {
- if (pNet->Up) {
+ if (netif_running(pAC->dev[0])) {
pAC->WasIfUp[0] = SK_TRUE;
pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
DoPrintInterfaceChange = SK_FALSE;
@@ -4489,7 +4442,7 @@ SK_AC *pAc) /* pointer to adapter context */
}
if (pNet != netdev_priv(pAC->dev[1])) {
pNet = netdev_priv(pAC->dev[1]);
- if (pNet->Up) {
+ if (netif_running(pAC->dev[1])) {
pAC->WasIfUp[1] = SK_TRUE;
pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
DoPrintInterfaceChange = SK_FALSE;
@@ -4815,42 +4768,56 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
struct net_device *dev = NULL;
static int boards_found = 0;
int error = -ENODEV;
+ int using_dac = 0;
+ char DeviceStr[80];
if (pci_enable_device(pdev))
goto out;
/* Configure DMA attributes. */
- if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
- pci_set_dma_mask(pdev, DMA_32BIT_MASK))
- goto out_disable_device;
-
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ using_dac = 1;
+ error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (error < 0) {
+ printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto out_disable_device;
+ }
+ } else {
+ error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (error) {
+ printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto out_disable_device;
+ }
+ }
- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
- printk(KERN_ERR "Unable to allocate etherdev "
+ error = -ENOMEM;
+ dev = alloc_etherdev(sizeof(DEV_NET));
+ if (!dev) {
+ printk(KERN_ERR "sk98lin: unable to allocate etherdev "
"structure!\n");
goto out_disable_device;
}
pNet = netdev_priv(dev);
- pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+ pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
if (!pNet->pAC) {
- printk(KERN_ERR "Unable to allocate adapter "
+ printk(KERN_ERR "sk98lin: unable to allocate adapter "
"structure!\n");
goto out_free_netdev;
}
- memset(pNet->pAC, 0, sizeof(SK_AC));
pAC = pNet->pAC;
pAC->PciDev = pdev;
- pAC->PciDevId = pdev->device;
+
pAC->dev[0] = dev;
pAC->dev[1] = dev;
- sprintf(pAC->Name, "SysKonnect SK-98xx");
pAC->CheckQueue = SK_FALSE;
- pNet->Mtu = 1500;
- pNet->Up = 0;
dev->irq = pdev->irq;
+
error = SkGeInitPCI(pAC);
if (error) {
printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
@@ -4872,30 +4839,44 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
+ /* Use only if yukon hardware */
if (pAC->ChipsetType) {
- /* Use only if yukon hardware */
- /* SK and ZEROCOPY - fly baby... */
- dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
- }
+#ifdef USE_SK_TX_CHECKSUM
+ dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+ dev->features |= NETIF_F_SG;
#endif
+#ifdef USE_SK_RX_CHECKSUM
+ pAC->RxPort[0].RxCsum = 1;
#endif
+ }
+
+ if (using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
pAC->Index = boards_found++;
- if (SkGeBoardInit(dev, pAC))
+ error = SkGeBoardInit(dev, pAC);
+ if (error)
goto out_free_netdev;
+ /* Read Adapter name from VPD */
+ if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
+ error = -EIO;
+ printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
+ goto out_free_resources;
+ }
+
/* Register net device */
- if (register_netdev(dev)) {
+ error = register_netdev(dev);
+ if (error) {
printk(KERN_ERR "sk98lin: Could not register device.\n");
goto out_free_resources;
}
/* Print adapter specific string from vpd */
- ProductStr(pAC);
- printk("%s: %s\n", dev->name, pAC->DeviceStr);
+ printk("%s: %s\n", dev->name, DeviceStr);
/* Print configuration settings */
printk(" PrefPort:%c RlmtMode:%s\n",
@@ -4911,28 +4892,26 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- SkGeProcCreate(dev);
-
pNet->PortNr = 0;
pNet->NetNr = 0;
boards_found++;
+ pci_set_drvdata(pdev, dev);
+
/* More then one port found */
if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
- printk(KERN_ERR "Unable to allocate etherdev "
+ dev = alloc_etherdev(sizeof(DEV_NET));
+ if (!dev) {
+ printk(KERN_ERR "sk98lin: unable to allocate etherdev "
"structure!\n");
- goto out;
+ goto single_port;
}
- pAC->dev[1] = dev;
pNet = netdev_priv(dev);
pNet->PortNr = 1;
pNet->NetNr = 1;
pNet->pAC = pAC;
- pNet->Mtu = 1500;
- pNet->Up = 0;
dev->open = &SkGeOpen;
dev->stop = &SkGeClose;
@@ -4945,30 +4924,40 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
if (pAC->ChipsetType) {
- /* SG and ZEROCOPY - fly baby... */
- dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
- }
+#ifdef USE_SK_TX_CHECKSUM
+ dev->features |= NETIF_F_IP_CSUM;
+#endif
+#ifdef SK_ZEROCOPY
+ dev->features |= NETIF_F_SG;
#endif
+#ifdef USE_SK_RX_CHECKSUM
+ pAC->RxPort[1].RxCsum = 1;
#endif
+ }
+
+ if (using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
- if (register_netdev(dev)) {
- printk(KERN_ERR "sk98lin: Could not register device for seconf port.\n");
+ error = register_netdev(dev);
+ if (error) {
+ printk(KERN_ERR "sk98lin: Could not register device"
+ " for second port. (%d)\n", error);
free_netdev(dev);
- pAC->dev[1] = pAC->dev[0];
- } else {
- SkGeProcCreate(dev);
- memcpy(&dev->dev_addr,
- &pAC->Addr.Net[1].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- printk("%s: %s\n", dev->name, pAC->DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+ goto single_port;
}
+
+ pAC->dev[1] = dev;
+ memcpy(&dev->dev_addr,
+ &pAC->Addr.Net[1].CurrentMacAddress, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ printk("%s: %s\n", dev->name, DeviceStr);
+ printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
}
+single_port:
+
/* Save the hardware revision */
pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
(pAC->GIni.GIPciHwRev & 0x0F);
@@ -4980,7 +4969,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
- pci_set_drvdata(pdev, dev);
return 0;
out_free_resources:
@@ -5000,10 +4988,7 @@ static void __devexit skge_remove_one(struct pci_dev *pdev)
SK_AC *pAC = pNet->pAC;
struct net_device *otherdev = pAC->dev[1];
- SkGeProcRemove(dev);
unregister_netdev(dev);
- if (otherdev != dev)
- SkGeProcRemove(otherdev);
SkGeYellowLED(pAC, pAC->IoBase, 0);
@@ -5088,9 +5073,9 @@ static int skge_resume(struct pci_dev *pdev)
pci_enable_device(pdev);
pci_set_master(pdev);
if (pAC->GIni.GIMacsFound == 2)
- ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+ ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev);
else
- ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev);
+ ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, "sk98lin", dev);
if (ret) {
printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
pAC->AllocFlag &= ~SK_ALLOC_IRQ;
@@ -5148,23 +5133,12 @@ static struct pci_driver skge_driver = {
static int __init skge_init(void)
{
- int error;
-
- pSkRootDir = proc_mkdir(SKRootName, NULL);
- if (pSkRootDir)
- pSkRootDir->owner = THIS_MODULE;
-
- error = pci_register_driver(&skge_driver);
- if (error)
- remove_proc_entry(SKRootName, NULL);
- return error;
+ return pci_module_init(&skge_driver);
}
static void __exit skge_exit(void)
{
pci_unregister_driver(&skge_driver);
- remove_proc_entry(SKRootName, NULL);
-
}
module_init(skge_init);
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
index 58e1a5be913f..a386172107e8 100644
--- a/drivers/net/sk98lin/skgepnmi.c
+++ b/drivers/net/sk98lin/skgepnmi.c
@@ -611,7 +611,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* If the instance -1 is passed, an array of values is supposed and
* all instances of the OID will be set.
*
@@ -654,7 +654,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* If the instance -1 is passed, an array of values is supposed and
* all instances of the OID will be set.
*
@@ -870,7 +870,7 @@ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
* Description:
* Calls a general sub-function for all this set stuff. The preset does
* the same as a set, but returns just before finally setting the
- * new value. This is usefull to check if a set might be successfull.
+ * new value. This is useful to check if a set might be successfull.
* The sub-function runs through the IdTable, checks which OIDs are able
* to set, and calls the handler function of the OID to perform the
* preset. The return value of the function will also be stored in
@@ -6473,7 +6473,7 @@ unsigned int PhysPortIndex) /* Physical port index */
*
* Description:
* The COMMON module only tells us if the mode is half or full duplex.
- * But in the decade of auto sensing it is usefull for the user to
+ * But in the decade of auto sensing it is useful for the user to
* know if the mode was negotiated or forced. Therefore we have a
* look to the mode, which was last used by the negotiation process.
*
diff --git a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c
deleted file mode 100644
index 5cece25c034e..000000000000
--- a/drivers/net/sk98lin/skproc.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/******************************************************************************
- *
- * Name: skproc.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.11 $
- * Date: $Date: 2003/12/11 16:03:57 $
- * Purpose: Funktions to display statictic data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Created 22-Nov-2000
- * Author: Mirko Lindner (mlindner@syskonnect.de)
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-static int sk_seq_show(struct seq_file *seq, void *v);
-static int sk_proc_open(struct inode *inode, struct file *file);
-
-struct file_operations sk_proc_fops = {
- .owner = THIS_MODULE,
- .open = sk_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-
-/*****************************************************************************
- *
- * sk_seq_show - show proc information of a particular adapter
- *
- * Description:
- * This function fills the proc entry with statistic data about
- * the ethernet device. It invokes the generic sk_gen_browse() to
- * print out all items one per one.
- *
- * Returns: 0
- *
- */
-static int sk_seq_show(struct seq_file *seq, void *v)
-{
- struct net_device *dev = seq->private;
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
- unsigned long Flags;
- unsigned int Size;
- char sens_msg[50];
- int t;
- int i;
-
- /* NetIndex in GetStruct is now required, zero is only dummy */
- for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
- if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
- t--;
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- Size = SK_PNMI_STRUCT_SIZE;
-#ifdef SK_DIAG_SUPPORT
- if (pAC->BoardLevel == SK_INIT_DATA) {
- SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA));
- if (pAC->DiagModeActive == DIAG_NOTACTIVE) {
- pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
- }
- } else {
- SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1);
- }
-#else
- SkPnmiGetStruct(pAC, pAC->IoBase,
- pPnmiStruct, &Size, t-1);
-#endif
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- if (pAC->dev[t-1] == dev) {
- SK_PNMI_STAT *pPnmiStat = &pPnmiStruct->Stat[0];
-
- seq_printf(seq, "\nDetailed statistic for device %s\n",
- pAC->dev[t-1]->name);
- seq_printf(seq, "=======================================\n");
-
- /* Board statistics */
- seq_printf(seq, "\nBoard statistics\n\n");
- seq_printf(seq, "Active Port %c\n",
- 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
- Net[t-1].PrefPort]->PortNumber);
- seq_printf(seq, "Preferred Port %c\n",
- 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
- Net[t-1].PrefPort]->PortNumber);
-
- seq_printf(seq, "Bus speed (MHz) %d\n",
- pPnmiStruct->BusSpeed);
-
- seq_printf(seq, "Bus width (Bit) %d\n",
- pPnmiStruct->BusWidth);
- seq_printf(seq, "Driver version %s\n",
- VER_STRING);
- seq_printf(seq, "Hardware revision v%d.%d\n",
- (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
- pAC->GIni.GIPciHwRev & 0x0F);
-
- /* Print sensor informations */
- for (i=0; i < pAC->I2c.MaxSens; i ++) {
- /* Check type */
- switch (pAC->I2c.SenTable[i].SenType) {
- case 1:
- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
- strcat(sens_msg, " (C)");
- seq_printf(seq, "%-25s %d.%02d\n",
- sens_msg,
- pAC->I2c.SenTable[i].SenValue / 10,
- pAC->I2c.SenTable[i].SenValue % 10);
-
- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
- strcat(sens_msg, " (F)");
- seq_printf(seq, "%-25s %d.%02d\n",
- sens_msg,
- ((((pAC->I2c.SenTable[i].SenValue)
- *10)*9)/5 + 3200)/100,
- ((((pAC->I2c.SenTable[i].SenValue)
- *10)*9)/5 + 3200) % 10);
- break;
- case 2:
- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
- strcat(sens_msg, " (V)");
- seq_printf(seq, "%-25s %d.%03d\n",
- sens_msg,
- pAC->I2c.SenTable[i].SenValue / 1000,
- pAC->I2c.SenTable[i].SenValue % 1000);
- break;
- case 3:
- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
- strcat(sens_msg, " (rpm)");
- seq_printf(seq, "%-25s %d\n",
- sens_msg,
- pAC->I2c.SenTable[i].SenValue);
- break;
- default:
- break;
- }
- }
-
- /*Receive statistics */
- seq_printf(seq, "\nReceive statistics\n\n");
-
- seq_printf(seq, "Received bytes %Lu\n",
- (unsigned long long) pPnmiStat->StatRxOctetsOkCts);
- seq_printf(seq, "Received packets %Lu\n",
- (unsigned long long) pPnmiStat->StatRxOkCts);
-#if 0
- if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
- pAC->HWRevision < 12) {
- pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
- pPnmiStat->StatRxShortsCts;
- pPnmiStat->StatRxShortsCts = 0;
- }
-#endif
- if (dev->mtu > 1500)
- pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
- pPnmiStat->StatRxTooLongCts;
-
- seq_printf(seq, "Receive errors %Lu\n",
- (unsigned long long) pPnmiStruct->InErrorsCts);
- seq_printf(seq, "Receive dropped %Lu\n",
- (unsigned long long) pPnmiStruct->RxNoBufCts);
- seq_printf(seq, "Received multicast %Lu\n",
- (unsigned long long) pPnmiStat->StatRxMulticastOkCts);
- seq_printf(seq, "Receive error types\n");
- seq_printf(seq, " length %Lu\n",
- (unsigned long long) pPnmiStat->StatRxRuntCts);
- seq_printf(seq, " buffer overflow %Lu\n",
- (unsigned long long) pPnmiStat->StatRxFifoOverflowCts);
- seq_printf(seq, " bad crc %Lu\n",
- (unsigned long long) pPnmiStat->StatRxFcsCts);
- seq_printf(seq, " framing %Lu\n",
- (unsigned long long) pPnmiStat->StatRxFramingCts);
- seq_printf(seq, " missed frames %Lu\n",
- (unsigned long long) pPnmiStat->StatRxMissedCts);
-
- if (dev->mtu > 1500)
- pPnmiStat->StatRxTooLongCts = 0;
-
- seq_printf(seq, " too long %Lu\n",
- (unsigned long long) pPnmiStat->StatRxTooLongCts);
- seq_printf(seq, " carrier extension %Lu\n",
- (unsigned long long) pPnmiStat->StatRxCextCts);
- seq_printf(seq, " too short %Lu\n",
- (unsigned long long) pPnmiStat->StatRxShortsCts);
- seq_printf(seq, " symbol %Lu\n",
- (unsigned long long) pPnmiStat->StatRxSymbolCts);
- seq_printf(seq, " LLC MAC size %Lu\n",
- (unsigned long long) pPnmiStat->StatRxIRLengthCts);
- seq_printf(seq, " carrier event %Lu\n",
- (unsigned long long) pPnmiStat->StatRxCarrierCts);
- seq_printf(seq, " jabber %Lu\n",
- (unsigned long long) pPnmiStat->StatRxJabberCts);
-
-
- /*Transmit statistics */
- seq_printf(seq, "\nTransmit statistics\n\n");
-
- seq_printf(seq, "Transmited bytes %Lu\n",
- (unsigned long long) pPnmiStat->StatTxOctetsOkCts);
- seq_printf(seq, "Transmited packets %Lu\n",
- (unsigned long long) pPnmiStat->StatTxOkCts);
- seq_printf(seq, "Transmit errors %Lu\n",
- (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
- seq_printf(seq, "Transmit dropped %Lu\n",
- (unsigned long long) pPnmiStruct->TxNoBufCts);
- seq_printf(seq, "Transmit collisions %Lu\n",
- (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
- seq_printf(seq, "Transmit error types\n");
- seq_printf(seq, " excessive collision %ld\n",
- pAC->stats.tx_aborted_errors);
- seq_printf(seq, " carrier %Lu\n",
- (unsigned long long) pPnmiStat->StatTxCarrierCts);
- seq_printf(seq, " fifo underrun %Lu\n",
- (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts);
- seq_printf(seq, " heartbeat %Lu\n",
- (unsigned long long) pPnmiStat->StatTxCarrierCts);
- seq_printf(seq, " window %ld\n",
- pAC->stats.tx_window_errors);
-
- }
- }
- return 0;
-}
-
-/*****************************************************************************
- *
- * sk_proc_open - register the show function when proc is open'ed
- *
- * Description:
- * This function is called whenever a sk98lin proc file is queried.
- *
- * Returns: the return value of single_open()
- *
- */
-static int sk_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, sk_seq_show, PDE(inode)->data);
-}
-
-/*******************************************************************************
- *
- * End of file
- *
- ******************************************************************************/
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 00d683063c01..bf55a4cfb3d2 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -25,6 +25,7 @@
*/
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -43,7 +44,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.2"
+#define DRV_VERSION "1.3"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -88,15 +89,14 @@ MODULE_DEVICE_TABLE(pci, skge_id_table);
static int skge_up(struct net_device *dev);
static int skge_down(struct net_device *dev);
+static void skge_phy_reset(struct skge_port *skge);
static void skge_tx_clean(struct skge_port *skge);
static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
static void genesis_get_stats(struct skge_port *skge, u64 *data);
static void yukon_get_stats(struct skge_port *skge, u64 *data);
static void yukon_init(struct skge_hw *hw, int port);
-static void yukon_reset(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
-static void genesis_reset(struct skge_hw *hw, int port);
static void genesis_link_up(struct skge_port *skge);
/* Avoid conditionals by using array */
@@ -276,10 +276,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
skge->autoneg = ecmd->autoneg;
skge->advertising = ecmd->advertising;
- if (netif_running(dev)) {
- skge_down(dev);
- skge_up(dev);
- }
+ if (netif_running(dev))
+ skge_phy_reset(skge);
+
return (0);
}
@@ -399,6 +398,7 @@ static int skge_set_ring_param(struct net_device *dev,
struct ethtool_ringparam *p)
{
struct skge_port *skge = netdev_priv(dev);
+ int err;
if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE)
@@ -409,7 +409,9 @@ static int skge_set_ring_param(struct net_device *dev,
if (netif_running(dev)) {
skge_down(dev);
- skge_up(dev);
+ err = skge_up(dev);
+ if (err)
+ dev_close(dev);
}
return 0;
@@ -430,21 +432,11 @@ static void skge_set_msglevel(struct net_device *netdev, u32 value)
static int skge_nway_reset(struct net_device *dev)
{
struct skge_port *skge = netdev_priv(dev);
- struct skge_hw *hw = skge->hw;
- int port = skge->port;
if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev))
return -EINVAL;
- spin_lock_bh(&hw->phy_lock);
- if (hw->chip_id == CHIP_ID_GENESIS) {
- genesis_reset(hw, port);
- genesis_mac_init(hw, port);
- } else {
- yukon_reset(hw, port);
- yukon_init(hw, port);
- }
- spin_unlock_bh(&hw->phy_lock);
+ skge_phy_reset(skge);
return 0;
}
@@ -516,10 +508,8 @@ static int skge_set_pauseparam(struct net_device *dev,
else
skge->flow_control = FLOW_MODE_NONE;
- if (netif_running(dev)) {
- skge_down(dev);
- skge_up(dev);
- }
+ if (netif_running(dev))
+ skge_phy_reset(skge);
return 0;
}
@@ -2019,6 +2009,25 @@ static void yukon_phy_intr(struct skge_port *skge)
/* XXX restart autonegotiation? */
}
+static void skge_phy_reset(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ netif_stop_queue(skge->netdev);
+ netif_carrier_off(skge->netdev);
+
+ spin_lock_bh(&hw->phy_lock);
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ genesis_reset(hw, port);
+ genesis_mac_init(hw, port);
+ } else {
+ yukon_reset(hw, port);
+ yukon_init(hw, port);
+ }
+ spin_unlock_bh(&hw->phy_lock);
+}
+
/* Basic MII support */
static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
@@ -2187,6 +2196,7 @@ static int skge_up(struct net_device *dev)
kfree(skge->rx_ring.start);
free_pci_mem:
pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+ skge->mem = NULL;
return err;
}
@@ -2197,6 +2207,9 @@ static int skge_down(struct net_device *dev)
struct skge_hw *hw = skge->hw;
int port = skge->port;
+ if (skge->mem == NULL)
+ return 0;
+
if (netif_msg_ifdown(skge))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
@@ -2253,6 +2266,7 @@ static int skge_down(struct net_device *dev)
kfree(skge->rx_ring.start);
kfree(skge->tx_ring.start);
pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+ skge->mem = NULL;
return 0;
}
@@ -2413,18 +2427,23 @@ static void skge_tx_timeout(struct net_device *dev)
static int skge_change_mtu(struct net_device *dev, int new_mtu)
{
- int err = 0;
- int running = netif_running(dev);
+ int err;
if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
+ if (!netif_running(dev)) {
+ dev->mtu = new_mtu;
+ return 0;
+ }
+
+ skge_down(dev);
- if (running)
- skge_down(dev);
dev->mtu = new_mtu;
- if (running)
- skge_up(dev);
+
+ err = skge_up(dev);
+ if (err)
+ dev_close(dev);
return err;
}
@@ -3224,12 +3243,22 @@ static int __devinit skge_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
using_dac = 1;
- else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
- printk(KERN_ERR PFX "%s no usable DMA configuration\n",
- pci_name(pdev));
- goto err_out_free_regions;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
}
#ifdef __BIG_ENDIAN
@@ -3398,8 +3427,8 @@ static int skge_resume(struct pci_dev *pdev)
struct net_device *dev = hw->dev[i];
if (dev) {
netif_device_attach(dev);
- if (netif_running(dev))
- skge_up(dev);
+ if (netif_running(dev) && skge_up(dev))
+ dev_close(dev);
}
}
return 0;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index ee123c15f545..2efdacc290e5 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -475,18 +475,6 @@ enum {
Q_T2 = 0x40, /* 32 bit Test Register 2 */
Q_T3 = 0x44, /* 32 bit Test Register 3 */
-/* Yukon-2 */
- Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
- Q_WM = 0x40, /* 16 bit FIFO Watermark */
- Q_AL = 0x42, /* 8 bit FIFO Alignment */
- Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
- Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */
- Q_RP = 0x48, /* 8 bit FIFO Read Pointer */
- Q_RL = 0x4a, /* 8 bit FIFO Read Level */
- Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */
- Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */
- Q_WL = 0x4e, /* 8 bit FIFO Write Level */
- Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
@@ -675,22 +663,16 @@ enum {
LED_OFF = 1<<0, /* switch LED off */
};
-/* Receive GMAC FIFO (YUKON and Yukon-2) */
+/* Receive GMAC FIFO (YUKON) */
enum {
RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */
RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */
RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */
RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */
RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */
- RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */
-
- RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */
RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */
-
RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */
-
RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */
-
RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */
};
@@ -855,48 +837,6 @@ enum {
GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */
};
-/* Status BMU Registers (Yukon-2 only)*/
-enum {
- STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */
- STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */
- /* 0x0e85 - 0x0e86: reserved */
- STAT_LIST_ADDR_LO = 0x0e88,/* 32 bit Status List Start Addr (low) */
- STAT_LIST_ADDR_HI = 0x0e8c,/* 32 bit Status List Start Addr (high) */
- STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */
- STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */
- STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */
- STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */
- STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */
- STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */
-
-/* FIFO Control/Status Registers (Yukon-2 only)*/
- STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */
- STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */
- STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */
- STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */
- STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */
- STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */
- STAT_FIFO_ISR_WM = 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */
-
-/* Level and ISR Timer Registers (Yukon-2 only)*/
- STAT_LEV_TIMER_INI = 0x0eb0,/* 32 bit Level Timer Init. Value Reg */
- STAT_LEV_TIMER_CNT = 0x0eb4,/* 32 bit Level Timer Counter Reg */
- STAT_LEV_TIMER_CTRL = 0x0eb8,/* 8 bit Level Timer Control Reg */
- STAT_LEV_TIMER_TEST = 0x0eb9,/* 8 bit Level Timer Test Reg */
- STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */
- STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */
- STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */
- STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */
- STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */
- STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */
- STAT_ISR_TIMER_CTRL = 0x0ed8,/* 8 bit ISR Timer Control Reg */
- STAT_ISR_TIMER_TEST = 0x0ed9,/* 8 bit ISR Timer Test Reg */
-
- ST_LAST_IDX_MASK = 0x007f,/* Last Index Mask */
- ST_TXRP_IDX_MASK = 0x0fff,/* Tx Report Index Mask */
- ST_TXTH_IDX_MASK = 0x0fff,/* Tx Threshold Index Mask */
- ST_WM_IDX_MASK = 0x3f,/* FIFO Watermark Index Mask */
-};
enum {
LINKLED_OFF = 0x01,
@@ -923,8 +863,6 @@ enum {
WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */
WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */
WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */
- WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */
- WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */
WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */
/* WOL Pattern Length Registers (YUKON only) */
@@ -1641,15 +1579,6 @@ enum {
PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */
};
-/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
-/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/
-enum {
- PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */
- PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */
- PHY_M_MAC_MD_COPPER = 5,/* Copper only */
- PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */
-};
-#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK)
/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
enum {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
new file mode 100644
index 000000000000..f8b973a04b65
--- /dev/null
+++ b/drivers/net/sky2.c
@@ -0,0 +1,3315 @@
+/*
+ * New driver for Marvell Yukon 2 chipset.
+ * Based on earlier sk98lin, and skge driver.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.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.
+ */
+
+/*
+ * TOTEST
+ * - speed setting
+ * - suspend/resume
+ */
+
+#include <linux/config.h>
+#include <linux/crc32.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/if_vlan.h>
+#include <linux/prefetch.h>
+#include <linux/mii.h>
+
+#include <asm/irq.h>
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define SKY2_VLAN_TAG_USED 1
+#endif
+
+#include "sky2.h"
+
+#define DRV_NAME "sky2"
+#define DRV_VERSION "0.13"
+#define PFX DRV_NAME " "
+
+/*
+ * The Yukon II chipset takes 64 bit command blocks (called list elements)
+ * that are organized into three (receive, transmit, status) different rings
+ * similar to Tigon3. A transmit can require several elements;
+ * a receive requires one (or two if using 64 bit dma).
+ */
+
+#define is_ec_a1(hw) \
+ unlikely((hw)->chip_id == CHIP_ID_YUKON_EC && \
+ (hw)->chip_rev == CHIP_REV_YU_EC_A1)
+
+#define RX_LE_SIZE 512
+#define RX_LE_BYTES (RX_LE_SIZE*sizeof(struct sky2_rx_le))
+#define RX_MAX_PENDING (RX_LE_SIZE/2 - 2)
+#define RX_DEF_PENDING RX_MAX_PENDING
+#define RX_SKB_ALIGN 8
+
+#define TX_RING_SIZE 512
+#define TX_DEF_PENDING (TX_RING_SIZE - 1)
+#define TX_MIN_PENDING 64
+#define MAX_SKB_TX_LE (4 + 2*MAX_SKB_FRAGS)
+
+#define STATUS_RING_SIZE 2048 /* 2 ports * (TX + 2*RX) */
+#define STATUS_LE_BYTES (STATUS_RING_SIZE*sizeof(struct sky2_status_le))
+#define ETH_JUMBO_MTU 9000
+#define TX_WATCHDOG (5 * HZ)
+#define NAPI_WEIGHT 64
+#define PHY_RETRIES 1000
+
+static const u32 default_msg =
+ NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+ | NETIF_MSG_TIMER | NETIF_MSG_TX_ERR | NETIF_MSG_RX_ERR
+ | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+
+static int debug = -1; /* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static int copybreak __read_mostly = 256;
+module_param(copybreak, int, 0);
+MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+
+static const struct pci_device_id sky2_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
+ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sky2_id_table);
+
+/* Avoid conditionals by using array */
+static const unsigned txqaddr[] = { Q_XA1, Q_XA2 };
+static const unsigned rxqaddr[] = { Q_R1, Q_R2 };
+
+/* This driver supports yukon2 chipset only */
+static const char *yukon2_name[] = {
+ "XL", /* 0xb3 */
+ "EC Ultra", /* 0xb4 */
+ "UNKNOWN", /* 0xb5 */
+ "EC", /* 0xb6 */
+ "FE", /* 0xb7 */
+};
+
+/* Access to external PHY */
+static int gm_phy_write(struct sky2_hw *hw, unsigned port, u16 reg, u16 val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_DATA, val);
+ gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(PHY_ADDR_MARV) | GM_SMI_CT_REG_AD(reg));
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ return 0;
+ udelay(1);
+ }
+
+ printk(KERN_WARNING PFX "%s: phy write timeout\n", hw->dev[port]->name);
+ return -ETIMEDOUT;
+}
+
+static int __gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg, u16 *val)
+{
+ int i;
+
+ gma_write16(hw, port, GM_SMI_CTRL, GM_SMI_CT_PHY_AD(PHY_ADDR_MARV)
+ | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) {
+ *val = gma_read16(hw, port, GM_SMI_DATA);
+ return 0;
+ }
+
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
+{
+ u16 v;
+
+ if (__gm_phy_read(hw, port, reg, &v) != 0)
+ printk(KERN_WARNING PFX "%s: phy read timeout\n", hw->dev[port]->name);
+ return v;
+}
+
+static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
+{
+ u16 power_control;
+ u32 reg1;
+ int vaux;
+ int ret = 0;
+
+ pr_debug("sky2_set_power_state %d\n", state);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+
+ pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_PMC, &power_control);
+ vaux = (sky2_read8(hw, B0_CTST) & Y2_VAUX_AVAIL) &&
+ (power_control & PCI_PM_CAP_PME_D3cold);
+
+ pci_read_config_word(hw->pdev, hw->pm_cap + PCI_PM_CTRL, &power_control);
+
+ power_control |= PCI_PM_CTRL_PME_STATUS;
+ power_control &= ~(PCI_PM_CTRL_STATE_MASK);
+
+ switch (state) {
+ case PCI_D0:
+ /* switch power to VCC (WA for VAUX problem) */
+ sky2_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+
+ /* disable Core Clock Division, */
+ sky2_write32(hw, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+ else
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+
+ /* Turn off phy power saving */
+ pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+ reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+
+ /* looks like this XL is back asswards .. */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) {
+ reg1 |= PCI_Y2_PHY1_COMA;
+ if (hw->ports > 1)
+ reg1 |= PCI_Y2_PHY2_COMA;
+ }
+ pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+ break;
+
+ case PCI_D3hot:
+ case PCI_D3cold:
+ /* Turn on phy power saving */
+ pci_read_config_dword(hw->pdev, PCI_DEV_REG1, &reg1);
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+ else
+ reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
+ pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg1);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+ sky2_write8(hw, B2_Y2_CLK_GATE, 0);
+ else
+ /* enable bits are inverted */
+ sky2_write8(hw, B2_Y2_CLK_GATE,
+ Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
+ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
+ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+
+ /* switch power to VAUX */
+ if (vaux && state != PCI_D3cold)
+ sky2_write8(hw, B0_POWER_CTRL,
+ (PC_VAUX_ENA | PC_VCC_ENA |
+ PC_VAUX_ON | PC_VCC_OFF));
+ break;
+ default:
+ printk(KERN_ERR PFX "Unknown power state %d\n", state);
+ ret = -1;
+ }
+
+ pci_write_config_byte(hw->pdev, hw->pm_cap + PCI_PM_CTRL, power_control);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ return ret;
+}
+
+static void sky2_phy_reset(struct sky2_hw *hw, unsigned port)
+{
+ u16 reg;
+
+ /* disable all GMAC IRQ's */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ /* disable PHY IRQs */
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+ gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA;
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
+{
+ struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ u16 ctrl, ct1000, adv, pg, ledctrl, ledover;
+
+ if (sky2->autoneg == AUTONEG_ENABLE && hw->chip_id != CHIP_ID_YUKON_XL) {
+ u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+ ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+ PHY_M_EC_MAC_S_MSK);
+ ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC)
+ ectrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
+ else
+ ectrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ }
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ if (hw->copper) {
+ if (hw->chip_id == CHIP_ID_YUKON_FE) {
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
+ } else {
+ /* disable energy detect */
+ ctrl &= ~PHY_M_PC_EN_DET_MSK;
+
+ /* enable automatic crossover */
+ ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
+
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ hw->chip_id == CHIP_ID_YUKON_XL) {
+ ctrl &= ~PHY_M_PC_DSC_MSK;
+ ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
+ }
+ }
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+ } else {
+ /* workaround for deviation #4.88 (CRC errors) */
+ /* disable Automatic Crossover */
+
+ ctrl &= ~PHY_M_PC_MDIX_MSK;
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2);
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl &= ~PHY_M_MAC_MD_MSK;
+ ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* select page 1 to access Fiber registers */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1);
+ }
+ }
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL);
+ if (sky2->autoneg == AUTONEG_DISABLE)
+ ctrl &= ~PHY_CT_ANE;
+ else
+ ctrl |= PHY_CT_ANE;
+
+ ctrl |= PHY_CT_RESET;
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ ctrl = 0;
+ ct1000 = 0;
+ adv = PHY_AN_CSMA;
+
+ if (sky2->autoneg == AUTONEG_ENABLE) {
+ if (hw->copper) {
+ if (sky2->advertising & ADVERTISED_1000baseT_Full)
+ ct1000 |= PHY_M_1000C_AFD;
+ if (sky2->advertising & ADVERTISED_1000baseT_Half)
+ ct1000 |= PHY_M_1000C_AHD;
+ if (sky2->advertising & ADVERTISED_100baseT_Full)
+ adv |= PHY_M_AN_100_FD;
+ if (sky2->advertising & ADVERTISED_100baseT_Half)
+ adv |= PHY_M_AN_100_HD;
+ if (sky2->advertising & ADVERTISED_10baseT_Full)
+ adv |= PHY_M_AN_10_FD;
+ if (sky2->advertising & ADVERTISED_10baseT_Half)
+ adv |= PHY_M_AN_10_HD;
+ } else /* special defines for FIBER (88E1011S only) */
+ adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+
+ /* Set Flow-control capabilities */
+ if (sky2->tx_pause && sky2->rx_pause)
+ adv |= PHY_AN_PAUSE_CAP; /* symmetric */
+ else if (sky2->rx_pause && !sky2->tx_pause)
+ adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP;
+ else if (!sky2->rx_pause && sky2->tx_pause)
+ adv |= PHY_AN_PAUSE_ASYM; /* local */
+
+ /* Restart Auto-negotiation */
+ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* forced speed/duplex settings */
+ ct1000 = PHY_M_1000C_MSE;
+
+ if (sky2->duplex == DUPLEX_FULL)
+ ctrl |= PHY_CT_DUP_MD;
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ ctrl |= PHY_CT_SP1000;
+ break;
+ case SPEED_100:
+ ctrl |= PHY_CT_SP100;
+ break;
+ }
+
+ ctrl |= PHY_CT_RESET;
+ }
+
+ if (hw->chip_id != CHIP_ID_YUKON_FE)
+ gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* Setup Phy LED's */
+ ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+ ledover = 0;
+
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_FE:
+ /* on 88E3082 these bits are at 11..9 (shifted left) */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+ ctrl = gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR);
+
+ /* delete ACT LED control bits */
+ ctrl &= ~PHY_M_FELP_LED1_MSK;
+ /* change ACT LED control to blink mode */
+ ctrl |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL);
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
+ case CHIP_ID_YUKON_XL:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ /* select page 3 to access LED control register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+
+ /* set LED Function Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
+ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
+ PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
+
+ /* set Polarity Control register */
+ gm_phy_write(hw, port, PHY_MARV_PHY_STAT,
+ (PHY_M_POLC_LS1_P_MIX(4) |
+ PHY_M_POLC_IS0_P_MIX(4) |
+ PHY_M_POLC_LOS_CTRL(2) |
+ PHY_M_POLC_INIT_CTRL(2) |
+ PHY_M_POLC_STA1_CTRL(2) |
+ PHY_M_POLC_STA0_CTRL(2)));
+
+ /* restore page register */
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ default:
+ /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+ /* turn off the Rx LED (LED_RX) */
+ ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+ }
+
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+ if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+ /* Enable phy interrupt on auto-negotiation complete (or link up) */
+ if (sky2->autoneg == AUTONEG_ENABLE)
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ else
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+}
+
+/* Force a renegotiation */
+static void sky2_phy_reinit(struct sky2_port *sky2)
+{
+ down(&sky2->phy_sema);
+ sky2_phy_init(sky2->hw, sky2->port);
+ up(&sky2->phy_sema);
+}
+
+static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
+{
+ struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
+ u16 reg;
+ int i;
+ const u8 *addr = hw->dev[port]->dev_addr;
+
+ sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ sky2_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR|GPC_ENA_PAUSE);
+
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0 && port == 1) {
+ /* WA DEV_472 -- looks like crossed wires on port 2 */
+ /* clear GMAC 1 Control reset */
+ sky2_write8(hw, SK_REG(0, GMAC_CTRL), GMC_RST_CLR);
+ do {
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_SET);
+ sky2_write8(hw, SK_REG(1, GMAC_CTRL), GMC_RST_CLR);
+ } while (gm_phy_read(hw, 1, PHY_MARV_ID0) != PHY_MARV_ID0_VAL ||
+ gm_phy_read(hw, 1, PHY_MARV_ID1) != PHY_MARV_ID1_Y2 ||
+ gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0);
+ }
+
+ if (sky2->autoneg == AUTONEG_DISABLE) {
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg |= GM_GPCR_AU_ALL_DIS;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_read16(hw, port, GM_GP_CTRL);
+
+ switch (sky2->speed) {
+ case SPEED_1000:
+ reg |= GM_GPCR_SPEED_1000;
+ /* fallthru */
+ case SPEED_100:
+ reg |= GM_GPCR_SPEED_100;
+ }
+
+ if (sky2->duplex == DUPLEX_FULL)
+ reg |= GM_GPCR_DUP_FULL;
+ } else
+ reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+
+ if (!sky2->tx_pause && !sky2->rx_pause) {
+ sky2_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ reg |=
+ GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ } else if (sky2->tx_pause && !sky2->rx_pause) {
+ /* disable Rx flow-control */
+ reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ }
+
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ down(&sky2->phy_sema);
+ sky2_phy_init(hw, port);
+ up(&sky2->phy_sema);
+
+ /* MIB clear */
+ reg = gma_read16(hw, port, GM_PHY_ADDR);
+ gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+ for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+ gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i);
+ gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+ /* transmit control */
+ gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+ /* receive control reg: unicast + multicast + no FCS */
+ gma_write16(hw, port, GM_RX_CTRL,
+ GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+ /* transmit flow control */
+ gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+ /* transmit parameter */
+ gma_write16(hw, port, GM_TX_PARAM,
+ TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+ TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+ TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) |
+ TX_BACK_OFF_LIM(TX_BOF_LIM_DEF));
+
+ /* serial mode register */
+ reg = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ if (hw->dev[port]->mtu > ETH_DATA_LEN)
+ reg |= GM_SMOD_JUMBO_ENA;
+
+ gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ /* virtual address for data */
+ gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+ /* physical address: used for pause frames */
+ gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+
+ /* ignore counter overflows */
+ gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+ /* Configure Rx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ sky2_write16(hw, SK_REG(port, RX_GMF_CTRL_T),
+ GMF_RX_CTRL_DEF);
+
+ /* Flush Rx MAC FIFO on any flow control or error */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
+
+ /* Set threshold to 0xa (64 bytes)
+ * ASF disabled so no need to do WA dev #4.30
+ */
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+
+ /* Configure Tx MAC FIFO */
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+ sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
+ sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
+ if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 0x180);
+ /* Disable Store & Forward mode for TX */
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
+ }
+ }
+
+}
+
+/* Assign Ram Buffer allocation.
+ * start and end are in units of 4k bytes
+ * ram registers are in units of 64bit words
+ */
+static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk)
+{
+ u32 start, end;
+
+ start = startk * 4096/8;
+ end = (endk * 4096/8) - 1;
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+ sky2_write32(hw, RB_ADDR(q, RB_START), start);
+ sky2_write32(hw, RB_ADDR(q, RB_END), end);
+ sky2_write32(hw, RB_ADDR(q, RB_WP), start);
+ sky2_write32(hw, RB_ADDR(q, RB_RP), start);
+
+ if (q == Q_R1 || q == Q_R2) {
+ u32 space = (endk - startk) * 4096/8;
+ u32 tp = space - space/4;
+
+ /* On receive queue's set the thresholds
+ * give receiver priority when > 3/4 full
+ * send pause when down to 2K
+ */
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
+
+ tp = space - 2048/8;
+ sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
+ sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 1K on Yukon
+ */
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
+
+ sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+ sky2_read8(hw, RB_ADDR(q, RB_CTRL));
+}
+
+/* Setup Bus Memory Interface */
+static void sky2_qset(struct sky2_hw *hw, u16 q)
+{
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_RESET);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_OPER_INIT);
+ sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_FIFO_OP_ON);
+ sky2_write32(hw, Q_ADDR(q, Q_WM), BMU_WM_DEFAULT);
+}
+
+/* Setup prefetch unit registers. This is the interface between
+ * hardware and driver list elements
+ */
+static void sky2_prefetch_init(struct sky2_hw *hw, u32 qaddr,
+ u64 addr, u32 last)
+{
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_RST_CLR);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_HI), addr >> 32);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_ADDR_LO), (u32) addr);
+ sky2_write16(hw, Y2_QADDR(qaddr, PREF_UNIT_LAST_IDX), last);
+ sky2_write32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL), PREF_UNIT_OP_ON);
+
+ sky2_read32(hw, Y2_QADDR(qaddr, PREF_UNIT_CTRL));
+}
+
+static inline struct sky2_tx_le *get_tx_le(struct sky2_port *sky2)
+{
+ struct sky2_tx_le *le = sky2->tx_le + sky2->tx_prod;
+
+ sky2->tx_prod = (sky2->tx_prod + 1) % TX_RING_SIZE;
+ return le;
+}
+
+/*
+ * This is a workaround code taken from SysKonnect sk98lin driver
+ * to deal with chip bug on Yukon EC rev 0 in the wraparound case.
+ */
+static void sky2_put_idx(struct sky2_hw *hw, unsigned q,
+ u16 idx, u16 *last, u16 size)
+{
+ wmb();
+ if (is_ec_a1(hw) && idx < *last) {
+ u16 hwget = sky2_read16(hw, Y2_QADDR(q, PREF_UNIT_GET_IDX));
+
+ if (hwget == 0) {
+ /* Start prefetching again */
+ sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 0xe0);
+ goto setnew;
+ }
+
+ if (hwget == size - 1) {
+ /* set watermark to one list element */
+ sky2_write8(hw, Y2_QADDR(q, PREF_UNIT_FIFO_WM), 8);
+
+ /* set put index to first list element */
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), 0);
+ } else /* have hardware go to end of list */
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX),
+ size - 1);
+ } else {
+setnew:
+ sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
+ }
+ *last = idx;
+ mmiowb();
+}
+
+
+static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
+{
+ struct sky2_rx_le *le = sky2->rx_le + sky2->rx_put;
+ sky2->rx_put = (sky2->rx_put + 1) % RX_LE_SIZE;
+ return le;
+}
+
+/* Return high part of DMA address (could be 32 or 64 bit) */
+static inline u32 high32(dma_addr_t a)
+{
+ return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
+}
+
+/* Build description to hardware about buffer */
+static void sky2_rx_add(struct sky2_port *sky2, dma_addr_t map)
+{
+ struct sky2_rx_le *le;
+ u32 hi = high32(map);
+ u16 len = sky2->rx_bufsize;
+
+ if (sky2->rx_addr64 != hi) {
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32(hi);
+ le->ctrl = 0;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ sky2->rx_addr64 = high32(map + len);
+ }
+
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32((u32) map);
+ le->length = cpu_to_le16(len);
+ le->ctrl = 0;
+ le->opcode = OP_PACKET | HW_OWNER;
+}
+
+
+/* Tell chip where to start receive checksum.
+ * Actually has two checksums, but set both same to avoid possible byte
+ * order problems.
+ */
+static void rx_set_checksum(struct sky2_port *sky2)
+{
+ struct sky2_rx_le *le;
+
+ le = sky2_next_rx(sky2);
+ le->addr = (ETH_HLEN << 16) | ETH_HLEN;
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+
+}
+
+/*
+ * The RX Stop command will not work for Yukon-2 if the BMU does not
+ * reach the end of packet and since we can't make sure that we have
+ * incoming data, we must reset the BMU while it is not doing a DMA
+ * transfer. Since it is possible that the RX path is still active,
+ * the RX RAM buffer will be stopped first, so any possible incoming
+ * data will not trigger a DMA. After the RAM buffer is stopped, the
+ * BMU is polled until any DMA in progress is ended and only then it
+ * will be reset.
+ */
+static void sky2_rx_stop(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned rxq = rxqaddr[sky2->port];
+ int i;
+
+ /* disable the RAM Buffer receive queue */
+ sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_DIS_OP_MD);
+
+ for (i = 0; i < 0xffff; i++)
+ if (sky2_read8(hw, RB_ADDR(rxq, Q_RSL))
+ == sky2_read8(hw, RB_ADDR(rxq, Q_RL)))
+ goto stopped;
+
+ printk(KERN_WARNING PFX "%s: receiver stop failed\n",
+ sky2->netdev->name);
+stopped:
+ sky2_write32(hw, Q_ADDR(rxq, Q_CSR), BMU_RST_SET | BMU_FIFO_RST);
+
+ /* reset the Rx prefetch unit */
+ sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+}
+
+/* Clean out receive buffer area, assumes receiver hardware stopped */
+static void sky2_rx_clean(struct sky2_port *sky2)
+{
+ unsigned i;
+
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+ for (i = 0; i < sky2->rx_pending; i++) {
+ struct ring_info *re = sky2->rx_ring + i;
+
+ if (re->skb) {
+ pci_unmap_single(sky2->hw->pdev,
+ re->mapaddr, sky2->rx_bufsize,
+ PCI_DMA_FROMDEVICE);
+ kfree_skb(re->skb);
+ re->skb = NULL;
+ }
+ }
+}
+
+/* Basic MII support */
+static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct mii_ioctl_data *data = if_mii(ifr);
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ int err = -EOPNOTSUPP;
+
+ if (!netif_running(dev))
+ return -ENODEV; /* Phy still in reset */
+
+ switch(cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = PHY_ADDR_MARV;
+
+ /* fallthru */
+ case SIOCGMIIREG: {
+ u16 val = 0;
+
+ down(&sky2->phy_sema);
+ err = __gm_phy_read(hw, sky2->port, data->reg_num & 0x1f, &val);
+ up(&sky2->phy_sema);
+
+ data->val_out = val;
+ break;
+ }
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ down(&sky2->phy_sema);
+ err = gm_phy_write(hw, sky2->port, data->reg_num & 0x1f,
+ data->val_in);
+ up(&sky2->phy_sema);
+ break;
+ }
+ return err;
+}
+
+#ifdef SKY2_VLAN_TAG_USED
+static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u16 port = sky2->port;
+
+ spin_lock_bh(&sky2->tx_lock);
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
+ sky2->vlgrp = grp;
+
+ spin_unlock_bh(&sky2->tx_lock);
+}
+
+static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ u16 port = sky2->port;
+
+ spin_lock_bh(&sky2->tx_lock);
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
+ if (sky2->vlgrp)
+ sky2->vlgrp->vlan_devices[vid] = NULL;
+
+ spin_unlock_bh(&sky2->tx_lock);
+}
+#endif
+
+/*
+ * It appears the hardware has a bug in the FIFO logic that
+ * cause it to hang if the FIFO gets overrun and the receive buffer
+ * is not aligned. ALso alloc_skb() won't align properly if slab
+ * debugging is enabled.
+ */
+static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+ if (likely(skb)) {
+ unsigned long p = (unsigned long) skb->data;
+ skb_reserve(skb,
+ ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p);
+ }
+
+ return skb;
+}
+
+/*
+ * Allocate and setup receiver buffer pool.
+ * In case of 64 bit dma, there are 2X as many list elements
+ * available as ring entries
+ * and need to reserve one list element so we don't wrap around.
+ */
+static int sky2_rx_start(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned rxq = rxqaddr[sky2->port];
+ int i;
+
+ sky2->rx_put = sky2->rx_next = 0;
+ sky2_qset(hw, rxq);
+ sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
+
+ rx_set_checksum(sky2);
+ for (i = 0; i < sky2->rx_pending; i++) {
+ struct ring_info *re = sky2->rx_ring + i;
+
+ re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
+ if (!re->skb)
+ goto nomem;
+
+ re->mapaddr = pci_map_single(hw->pdev, re->skb->data,
+ sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+ sky2_rx_add(sky2, re->mapaddr);
+ }
+
+ /* Tell chip about available buffers */
+ sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put);
+ sky2->rx_last_put = sky2_read16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX));
+ return 0;
+nomem:
+ sky2_rx_clean(sky2);
+ return -ENOMEM;
+}
+
+/* Bring up network interface. */
+static int sky2_up(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u32 ramsize, rxspace;
+ int err = -ENOMEM;
+
+ if (netif_msg_ifup(sky2))
+ printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+
+ /* must be power of 2 */
+ sky2->tx_le = pci_alloc_consistent(hw->pdev,
+ TX_RING_SIZE *
+ sizeof(struct sky2_tx_le),
+ &sky2->tx_le_map);
+ if (!sky2->tx_le)
+ goto err_out;
+
+ sky2->tx_ring = kcalloc(TX_RING_SIZE, sizeof(struct tx_ring_info),
+ GFP_KERNEL);
+ if (!sky2->tx_ring)
+ goto err_out;
+ sky2->tx_prod = sky2->tx_cons = 0;
+
+ sky2->rx_le = pci_alloc_consistent(hw->pdev, RX_LE_BYTES,
+ &sky2->rx_le_map);
+ if (!sky2->rx_le)
+ goto err_out;
+ memset(sky2->rx_le, 0, RX_LE_BYTES);
+
+ sky2->rx_ring = kcalloc(sky2->rx_pending, sizeof(struct ring_info),
+ GFP_KERNEL);
+ if (!sky2->rx_ring)
+ goto err_out;
+
+ sky2_mac_init(hw, port);
+
+ /* Determine available ram buffer space (in 4K blocks).
+ * Note: not sure about the FE setting below yet
+ */
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ ramsize = 4;
+ else
+ ramsize = sky2_read8(hw, B2_E_0);
+
+ /* Give transmitter one third (rounded up) */
+ rxspace = ramsize - (ramsize + 2) / 3;
+
+ sky2_ramset(hw, rxqaddr[port], 0, rxspace);
+ sky2_ramset(hw, txqaddr[port], rxspace, ramsize);
+
+ /* Make sure SyncQ is disabled */
+ sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL),
+ RB_RST_SET);
+
+ sky2_qset(hw, txqaddr[port]);
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+ sky2_write16(hw, Q_ADDR(txqaddr[port], Q_AL), 0x1a0);
+
+
+ sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map,
+ TX_RING_SIZE - 1);
+
+ err = sky2_rx_start(sky2);
+ if (err)
+ goto err_out;
+
+ /* Enable interrupts from phy/mac for port */
+ hw->intr_mask |= (port == 0) ? Y2_IS_PORT_1 : Y2_IS_PORT_2;
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ return 0;
+
+err_out:
+ if (sky2->rx_le) {
+ pci_free_consistent(hw->pdev, RX_LE_BYTES,
+ sky2->rx_le, sky2->rx_le_map);
+ sky2->rx_le = NULL;
+ }
+ if (sky2->tx_le) {
+ pci_free_consistent(hw->pdev,
+ TX_RING_SIZE * sizeof(struct sky2_tx_le),
+ sky2->tx_le, sky2->tx_le_map);
+ sky2->tx_le = NULL;
+ }
+ kfree(sky2->tx_ring);
+ kfree(sky2->rx_ring);
+
+ sky2->tx_ring = NULL;
+ sky2->rx_ring = NULL;
+ return err;
+}
+
+/* Modular subtraction in ring */
+static inline int tx_dist(unsigned tail, unsigned head)
+{
+ return (head - tail) % TX_RING_SIZE;
+}
+
+/* Number of list elements available for next tx */
+static inline int tx_avail(const struct sky2_port *sky2)
+{
+ return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod);
+}
+
+/* Estimate of number of transmit list elements required */
+static unsigned tx_le_req(const struct sk_buff *skb)
+{
+ unsigned count;
+
+ count = sizeof(dma_addr_t) / sizeof(u32);
+ count += skb_shinfo(skb)->nr_frags * count;
+
+ if (skb_shinfo(skb)->tso_size)
+ ++count;
+
+ if (skb->ip_summed == CHECKSUM_HW)
+ ++count;
+
+ return count;
+}
+
+/*
+ * Put one packet in ring for transmit.
+ * A single packet can generate multiple list elements, and
+ * the number of ring elements will probably be less than the number
+ * of list elements used.
+ *
+ * No BH disabling for tx_lock here (like tg3)
+ */
+static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ struct sky2_tx_le *le = NULL;
+ struct tx_ring_info *re;
+ unsigned i, len;
+ dma_addr_t mapping;
+ u32 addr64;
+ u16 mss;
+ u8 ctrl;
+
+ /* No BH disabling for tx_lock here. We are running in BH disabled
+ * context and TX reclaim runs via poll inside of a software
+ * interrupt, and no related locks in IRQ processing.
+ */
+ if (!spin_trylock(&sky2->tx_lock))
+ return NETDEV_TX_LOCKED;
+
+ if (unlikely(tx_avail(sky2) < tx_le_req(skb))) {
+ /* There is a known but harmless race with lockless tx
+ * and netif_stop_queue.
+ */
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+ if (net_ratelimit())
+ printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+ dev->name);
+ }
+ spin_unlock(&sky2->tx_lock);
+
+ return NETDEV_TX_BUSY;
+ }
+
+ if (unlikely(netif_msg_tx_queued(sky2)))
+ printk(KERN_DEBUG "%s: tx queued, slot %u, len %d\n",
+ dev->name, sky2->tx_prod, skb->len);
+
+ len = skb_headlen(skb);
+ mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ addr64 = high32(mapping);
+
+ re = sky2->tx_ring + sky2->tx_prod;
+
+ /* Send high bits if changed or crosses boundary */
+ if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+ le = get_tx_le(sky2);
+ le->tx.addr = cpu_to_le32(addr64);
+ le->ctrl = 0;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ sky2->tx_addr64 = high32(mapping + len);
+ }
+
+ /* Check for TCP Segmentation Offload */
+ mss = skb_shinfo(skb)->tso_size;
+ if (mss != 0) {
+ /* just drop the packet if non-linear expansion fails */
+ if (skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+ dev_kfree_skb_any(skb);
+ goto out_unlock;
+ }
+
+ mss += ((skb->h.th->doff - 5) * 4); /* TCP options */
+ mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
+ mss += ETH_HLEN;
+ }
+
+ if (mss != sky2->tx_last_mss) {
+ le = get_tx_le(sky2);
+ le->tx.tso.size = cpu_to_le16(mss);
+ le->tx.tso.rsvd = 0;
+ le->opcode = OP_LRGLEN | HW_OWNER;
+ le->ctrl = 0;
+ sky2->tx_last_mss = mss;
+ }
+
+ ctrl = 0;
+#ifdef SKY2_VLAN_TAG_USED
+ /* Add VLAN tag, can piggyback on LRGLEN or ADDR64 */
+ if (sky2->vlgrp && vlan_tx_tag_present(skb)) {
+ if (!le) {
+ le = get_tx_le(sky2);
+ le->tx.addr = 0;
+ le->opcode = OP_VLAN|HW_OWNER;
+ le->ctrl = 0;
+ } else
+ le->opcode |= OP_VLAN;
+ le->length = cpu_to_be16(vlan_tx_tag_get(skb));
+ ctrl |= INS_VLAN;
+ }
+#endif
+
+ /* Handle TCP checksum offload */
+ if (skb->ip_summed == CHECKSUM_HW) {
+ u16 hdr = skb->h.raw - skb->data;
+ u16 offset = hdr + skb->csum;
+
+ ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+ if (skb->nh.iph->protocol == IPPROTO_UDP)
+ ctrl |= UDPTCP;
+
+ le = get_tx_le(sky2);
+ le->tx.csum.start = cpu_to_le16(hdr);
+ le->tx.csum.offset = cpu_to_le16(offset);
+ le->length = 0; /* initial checksum value */
+ le->ctrl = 1; /* one packet */
+ le->opcode = OP_TCPLISW | HW_OWNER;
+ }
+
+ le = get_tx_le(sky2);
+ le->tx.addr = cpu_to_le32((u32) mapping);
+ le->length = cpu_to_le16(len);
+ le->ctrl = ctrl;
+ le->opcode = mss ? (OP_LARGESEND | HW_OWNER) : (OP_PACKET | HW_OWNER);
+
+ /* Record the transmit mapping info */
+ re->skb = skb;
+ pci_unmap_addr_set(re, mapaddr, mapping);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ struct tx_ring_info *fre;
+
+ mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
+ addr64 = high32(mapping);
+ if (addr64 != sky2->tx_addr64) {
+ le = get_tx_le(sky2);
+ le->tx.addr = cpu_to_le32(addr64);
+ le->ctrl = 0;
+ le->opcode = OP_ADDR64 | HW_OWNER;
+ sky2->tx_addr64 = addr64;
+ }
+
+ le = get_tx_le(sky2);
+ le->tx.addr = cpu_to_le32((u32) mapping);
+ le->length = cpu_to_le16(frag->size);
+ le->ctrl = ctrl;
+ le->opcode = OP_BUFFER | HW_OWNER;
+
+ fre = sky2->tx_ring
+ + ((re - sky2->tx_ring) + i + 1) % TX_RING_SIZE;
+ pci_unmap_addr_set(fre, mapaddr, mapping);
+ }
+
+ re->idx = sky2->tx_prod;
+ le->ctrl |= EOP;
+
+ sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod,
+ &sky2->tx_last_put, TX_RING_SIZE);
+
+ if (tx_avail(sky2) <= MAX_SKB_TX_LE)
+ netif_stop_queue(dev);
+
+out_unlock:
+ spin_unlock(&sky2->tx_lock);
+
+ dev->trans_start = jiffies;
+ return NETDEV_TX_OK;
+}
+
+/*
+ * Free ring elements from starting at tx_cons until "done"
+ *
+ * NB: the hardware will tell us about partial completion of multi-part
+ * buffers; these are deferred until completion.
+ */
+static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
+{
+ struct net_device *dev = sky2->netdev;
+ struct pci_dev *pdev = sky2->hw->pdev;
+ u16 nxt, put;
+ unsigned i;
+
+ BUG_ON(done >= TX_RING_SIZE);
+
+ if (unlikely(netif_msg_tx_done(sky2)))
+ printk(KERN_DEBUG "%s: tx done, up to %u\n",
+ dev->name, done);
+
+ for (put = sky2->tx_cons; put != done; put = nxt) {
+ struct tx_ring_info *re = sky2->tx_ring + put;
+ struct sk_buff *skb = re->skb;
+
+ nxt = re->idx;
+ BUG_ON(nxt >= TX_RING_SIZE);
+ prefetch(sky2->tx_ring + nxt);
+
+ /* Check for partial status */
+ if (tx_dist(put, done) < tx_dist(put, nxt))
+ break;
+
+ skb = re->skb;
+ pci_unmap_single(pdev, pci_unmap_addr(re, mapaddr),
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ struct tx_ring_info *fre;
+ fre = sky2->tx_ring + (put + i + 1) % TX_RING_SIZE;
+ pci_unmap_page(pdev, pci_unmap_addr(fre, mapaddr),
+ skb_shinfo(skb)->frags[i].size,
+ PCI_DMA_TODEVICE);
+ }
+
+ dev_kfree_skb_any(skb);
+ }
+
+ sky2->tx_cons = put;
+ if (netif_queue_stopped(dev) && tx_avail(sky2) > MAX_SKB_TX_LE)
+ netif_wake_queue(dev);
+}
+
+/* Cleanup all untransmitted buffers, assume transmitter not running */
+static void sky2_tx_clean(struct sky2_port *sky2)
+{
+ spin_lock_bh(&sky2->tx_lock);
+ sky2_tx_complete(sky2, sky2->tx_prod);
+ spin_unlock_bh(&sky2->tx_lock);
+}
+
+/* Network shutdown */
+static int sky2_down(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 ctrl;
+
+ /* Never really got started! */
+ if (!sky2->tx_le)
+ return 0;
+
+ if (netif_msg_ifdown(sky2))
+ printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+
+ /* Stop more packets from being queued */
+ netif_stop_queue(dev);
+
+ /* Disable port IRQ */
+ local_irq_disable();
+ hw->intr_mask &= ~((sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ local_irq_enable();
+
+ flush_scheduled_work();
+
+ sky2_phy_reset(hw, port);
+
+ /* Stop transmitter */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
+ sky2_read32(hw, Q_ADDR(txqaddr[port], Q_CSR));
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+ RB_RST_SET | RB_DIS_OP_MD);
+
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ ctrl &= ~(GM_GPCR_TX_ENA | GM_GPCR_RX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+
+ sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+
+ /* Workaround shared GMAC reset */
+ if (!(hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0
+ && port == 0 && hw->dev[1] && netif_running(hw->dev[1])))
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+ /* Disable Force Sync bit and Enable Alloc bit */
+ sky2_write8(hw, SK_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ sky2_write32(hw, SK_REG(port, TXA_ITI_INI), 0L);
+ sky2_write32(hw, SK_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset the PCI FIFO of the async Tx queue */
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR),
+ BMU_RST_SET | BMU_FIFO_RST);
+
+ /* Reset the Tx prefetch units */
+ sky2_write32(hw, Y2_QADDR(txqaddr[port], PREF_UNIT_CTRL),
+ PREF_UNIT_RST_SET);
+
+ sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+ sky2_rx_stop(sky2);
+
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+
+ /* turn off LED's */
+ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+
+ synchronize_irq(hw->pdev->irq);
+
+ sky2_tx_clean(sky2);
+ sky2_rx_clean(sky2);
+
+ pci_free_consistent(hw->pdev, RX_LE_BYTES,
+ sky2->rx_le, sky2->rx_le_map);
+ kfree(sky2->rx_ring);
+
+ pci_free_consistent(hw->pdev,
+ TX_RING_SIZE * sizeof(struct sky2_tx_le),
+ sky2->tx_le, sky2->tx_le_map);
+ kfree(sky2->tx_ring);
+
+ sky2->tx_le = NULL;
+ sky2->rx_le = NULL;
+
+ sky2->rx_ring = NULL;
+ sky2->tx_ring = NULL;
+
+ return 0;
+}
+
+static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
+{
+ if (!hw->copper)
+ return SPEED_1000;
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+
+ switch (aux & PHY_M_PS_SPEED_MSK) {
+ case PHY_M_PS_SPEED_1000:
+ return SPEED_1000;
+ case PHY_M_PS_SPEED_100:
+ return SPEED_100;
+ default:
+ return SPEED_10;
+ }
+}
+
+static void sky2_link_up(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ /* Enable Transmit FIFO Underrun */
+ sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE)
+ reg |= GM_GPCR_DUP_FULL;
+
+ /* enable Rx/Tx */
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_read16(hw, port, GM_GP_CTRL);
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+
+ netif_carrier_on(sky2->netdev);
+ netif_wake_queue(sky2->netdev);
+
+ /* Turn on link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG),
+ LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
+
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
+ PHY_M_LEDC_INIT_CTRL(sky2->speed ==
+ SPEED_10 ? 7 : 0) |
+ PHY_M_LEDC_STA1_CTRL(sky2->speed ==
+ SPEED_100 ? 7 : 0) |
+ PHY_M_LEDC_STA0_CTRL(sky2->speed ==
+ SPEED_1000 ? 7 : 0));
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ }
+
+ if (netif_msg_link(sky2))
+ printk(KERN_INFO PFX
+ "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
+ sky2->netdev->name, sky2->speed,
+ sky2->duplex == DUPLEX_FULL ? "full" : "half",
+ (sky2->tx_pause && sky2->rx_pause) ? "both" :
+ sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none");
+}
+
+static void sky2_link_down(struct sky2_port *sky2)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 reg;
+
+ gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+
+ reg = gma_read16(hw, port, GM_GP_CTRL);
+ reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+ gma_write16(hw, port, GM_GP_CTRL, reg);
+ gma_read16(hw, port, GM_GP_CTRL); /* PCI post */
+
+ if (sky2->rx_pause && !sky2->tx_pause) {
+ /* restore Asymmetric Pause bit */
+ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+ gm_phy_read(hw, port, PHY_MARV_AUNE_ADV)
+ | PHY_M_AN_ASP);
+ }
+
+ netif_carrier_off(sky2->netdev);
+ netif_stop_queue(sky2->netdev);
+
+ /* Turn on link LED */
+ sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
+
+ if (netif_msg_link(sky2))
+ printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name);
+ sky2_phy_init(hw, port);
+}
+
+static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 lpa;
+
+ lpa = gm_phy_read(hw, port, PHY_MARV_AUNE_LP);
+
+ if (lpa & PHY_M_AN_RF) {
+ printk(KERN_ERR PFX "%s: remote fault", sky2->netdev->name);
+ return -1;
+ }
+
+ if (hw->chip_id != CHIP_ID_YUKON_FE &&
+ gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) {
+ printk(KERN_ERR PFX "%s: master/slave fault",
+ sky2->netdev->name);
+ return -1;
+ }
+
+ if (!(aux & PHY_M_PS_SPDUP_RES)) {
+ printk(KERN_ERR PFX "%s: speed/duplex mismatch",
+ sky2->netdev->name);
+ return -1;
+ }
+
+ sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ sky2->speed = sky2_phy_speed(hw, aux);
+
+ /* Pause bits are offset (9..8) */
+ if (hw->chip_id == CHIP_ID_YUKON_XL)
+ aux >>= 6;
+
+ sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0;
+ sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0;
+
+ if ((sky2->tx_pause || sky2->rx_pause)
+ && !(sky2->speed < SPEED_1000 && sky2->duplex == DUPLEX_HALF))
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ else
+ sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+
+ return 0;
+}
+
+/*
+ * Interrupt from PHY are handled outside of interrupt context
+ * because accessing phy registers requires spin wait which might
+ * cause excess interrupt latency.
+ */
+static void sky2_phy_task(void *arg)
+{
+ struct sky2_port *sky2 = arg;
+ struct sky2_hw *hw = sky2->hw;
+ u16 istatus, phystat;
+
+ down(&sky2->phy_sema);
+ istatus = gm_phy_read(hw, sky2->port, PHY_MARV_INT_STAT);
+ phystat = gm_phy_read(hw, sky2->port, PHY_MARV_PHY_STAT);
+
+ if (netif_msg_intr(sky2))
+ printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
+ sky2->netdev->name, istatus, phystat);
+
+ if (istatus & PHY_M_IS_AN_COMPL) {
+ if (sky2_autoneg_done(sky2, phystat) == 0)
+ sky2_link_up(sky2);
+ goto out;
+ }
+
+ if (istatus & PHY_M_IS_LSP_CHANGE)
+ sky2->speed = sky2_phy_speed(hw, phystat);
+
+ if (istatus & PHY_M_IS_DUP_CHANGE)
+ sky2->duplex =
+ (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+
+ if (istatus & PHY_M_IS_LST_CHANGE) {
+ if (phystat & PHY_M_PS_LINK_UP)
+ sky2_link_up(sky2);
+ else
+ sky2_link_down(sky2);
+ }
+out:
+ up(&sky2->phy_sema);
+
+ local_irq_disable();
+ hw->intr_mask |= (sky2->port == 0) ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2;
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ local_irq_enable();
+}
+
+
+/* Transmit timeout is only called if we are running, carries is up
+ * and tx queue is full (stopped).
+ */
+static void sky2_tx_timeout(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned txq = txqaddr[sky2->port];
+ u16 ridx;
+
+ /* Maybe we just missed an status interrupt */
+ spin_lock(&sky2->tx_lock);
+ ridx = sky2_read16(hw,
+ sky2->port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX);
+ sky2_tx_complete(sky2, ridx);
+ spin_unlock(&sky2->tx_lock);
+
+ if (!netif_queue_stopped(dev)) {
+ if (net_ratelimit())
+ pr_info(PFX "transmit interrupt missed? recovered\n");
+ return;
+ }
+
+ if (netif_msg_timer(sky2))
+ printk(KERN_ERR PFX "%s: tx timeout\n", dev->name);
+
+ sky2_write32(hw, Q_ADDR(txq, Q_CSR), BMU_STOP);
+ sky2_write32(hw, Y2_QADDR(txq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
+
+ sky2_tx_clean(sky2);
+
+ sky2_qset(hw, txq);
+ sky2_prefetch_init(hw, txq, sky2->tx_le_map, TX_RING_SIZE - 1);
+}
+
+
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+/* Want receive buffer size to be multiple of 64 bits, and incl room for vlan */
+static inline unsigned sky2_buf_size(int mtu)
+{
+ return roundup(mtu + ETH_HLEN + 4, 8);
+}
+
+static int sky2_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ int err;
+ u16 ctl, mode;
+
+ if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+ return -EINVAL;
+
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U && new_mtu > ETH_DATA_LEN)
+ return -EINVAL;
+
+ if (!netif_running(dev)) {
+ dev->mtu = new_mtu;
+ return 0;
+ }
+
+ sky2_write32(hw, B0_IMSK, 0);
+
+ dev->trans_start = jiffies; /* prevent tx timeout */
+ netif_stop_queue(dev);
+ netif_poll_disable(hw->dev[0]);
+
+ ctl = gma_read16(hw, sky2->port, GM_GP_CTRL);
+ gma_write16(hw, sky2->port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
+ sky2_rx_stop(sky2);
+ sky2_rx_clean(sky2);
+
+ dev->mtu = new_mtu;
+ sky2->rx_bufsize = sky2_buf_size(new_mtu);
+ mode = DATA_BLIND_VAL(DATA_BLIND_DEF) |
+ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+
+ if (dev->mtu > ETH_DATA_LEN)
+ mode |= GM_SMOD_JUMBO_ENA;
+
+ gma_write16(hw, sky2->port, GM_SERIAL_MODE, mode);
+
+ sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD);
+
+ err = sky2_rx_start(sky2);
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+ if (err)
+ dev_close(dev);
+ else {
+ gma_write16(hw, sky2->port, GM_GP_CTRL, ctl);
+
+ netif_poll_enable(hw->dev[0]);
+ netif_wake_queue(dev);
+ }
+
+ return err;
+}
+
+/*
+ * Receive one packet.
+ * For small packets or errors, just reuse existing skb.
+ * For larger packets, get new buffer.
+ */
+static struct sk_buff *sky2_receive(struct sky2_port *sky2,
+ u16 length, u32 status)
+{
+ struct ring_info *re = sky2->rx_ring + sky2->rx_next;
+ struct sk_buff *skb = NULL;
+
+ if (unlikely(netif_msg_rx_status(sky2)))
+ printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
+ sky2->netdev->name, sky2->rx_next, status, length);
+
+ sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
+ prefetch(sky2->rx_ring + sky2->rx_next);
+
+ if (status & GMR_FS_ANY_ERR)
+ goto error;
+
+ if (!(status & GMR_FS_RX_OK))
+ goto resubmit;
+
+ if ((status >> 16) != length || length > sky2->rx_bufsize)
+ goto oversize;
+
+ if (length < copybreak) {
+ skb = alloc_skb(length + 2, GFP_ATOMIC);
+ if (!skb)
+ goto resubmit;
+
+ skb_reserve(skb, 2);
+ pci_dma_sync_single_for_cpu(sky2->hw->pdev, re->mapaddr,
+ length, PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, re->skb->data, length);
+ skb->ip_summed = re->skb->ip_summed;
+ skb->csum = re->skb->csum;
+ pci_dma_sync_single_for_device(sky2->hw->pdev, re->mapaddr,
+ length, PCI_DMA_FROMDEVICE);
+ } else {
+ struct sk_buff *nskb;
+
+ nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
+ if (!nskb)
+ goto resubmit;
+
+ skb = re->skb;
+ re->skb = nskb;
+ pci_unmap_single(sky2->hw->pdev, re->mapaddr,
+ sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+ prefetch(skb->data);
+
+ re->mapaddr = pci_map_single(sky2->hw->pdev, nskb->data,
+ sky2->rx_bufsize, PCI_DMA_FROMDEVICE);
+ }
+
+ skb_put(skb, length);
+resubmit:
+ re->skb->ip_summed = CHECKSUM_NONE;
+ sky2_rx_add(sky2, re->mapaddr);
+
+ /* Tell receiver about new buffers. */
+ sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put,
+ &sky2->rx_last_put, RX_LE_SIZE);
+
+ return skb;
+
+oversize:
+ ++sky2->net_stats.rx_over_errors;
+ goto resubmit;
+
+error:
+ ++sky2->net_stats.rx_errors;
+
+ if (netif_msg_rx_err(sky2) && net_ratelimit())
+ printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
+ sky2->netdev->name, status, length);
+
+ if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE))
+ sky2->net_stats.rx_length_errors++;
+ if (status & GMR_FS_FRAGMENT)
+ sky2->net_stats.rx_frame_errors++;
+ if (status & GMR_FS_CRC_ERR)
+ sky2->net_stats.rx_crc_errors++;
+ if (status & GMR_FS_RX_FF_OV)
+ sky2->net_stats.rx_fifo_errors++;
+
+ goto resubmit;
+}
+
+/*
+ * Check for transmit complete
+ */
+#define TX_NO_STATUS 0xffff
+
+static void sky2_tx_check(struct sky2_hw *hw, int port, u16 last)
+{
+ if (last != TX_NO_STATUS) {
+ struct net_device *dev = hw->dev[port];
+ if (dev && netif_running(dev)) {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ spin_lock(&sky2->tx_lock);
+ sky2_tx_complete(sky2, last);
+ spin_unlock(&sky2->tx_lock);
+ }
+ }
+}
+
+/*
+ * Both ports share the same status interrupt, therefore there is only
+ * one poll routine.
+ */
+static int sky2_poll(struct net_device *dev0, int *budget)
+{
+ struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
+ unsigned int to_do = min(dev0->quota, *budget);
+ unsigned int work_done = 0;
+ u16 hwidx;
+ u16 tx_done[2] = { TX_NO_STATUS, TX_NO_STATUS };
+
+ hwidx = sky2_read16(hw, STAT_PUT_IDX);
+ BUG_ON(hwidx >= STATUS_RING_SIZE);
+ rmb();
+
+ while (hwidx != hw->st_idx) {
+ struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ struct net_device *dev;
+ struct sky2_port *sky2;
+ struct sk_buff *skb;
+ u32 status;
+ u16 length;
+
+ le = hw->st_le + hw->st_idx;
+ hw->st_idx = (hw->st_idx + 1) % STATUS_RING_SIZE;
+ prefetch(hw->st_le + hw->st_idx);
+
+ BUG_ON(le->link >= 2);
+ dev = hw->dev[le->link];
+ if (dev == NULL || !netif_running(dev))
+ continue;
+
+ sky2 = netdev_priv(dev);
+ status = le32_to_cpu(le->status);
+ length = le16_to_cpu(le->length);
+
+ switch (le->opcode & ~HW_OWNER) {
+ case OP_RXSTAT:
+ skb = sky2_receive(sky2, length, status);
+ if (!skb)
+ break;
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ dev->last_rx = jiffies;
+
+#ifdef SKY2_VLAN_TAG_USED
+ if (sky2->vlgrp && (status & GMR_FS_VLAN)) {
+ vlan_hwaccel_receive_skb(skb,
+ sky2->vlgrp,
+ be16_to_cpu(sky2->rx_tag));
+ } else
+#endif
+ netif_receive_skb(skb);
+
+ if (++work_done >= to_do)
+ goto exit_loop;
+ break;
+
+#ifdef SKY2_VLAN_TAG_USED
+ case OP_RXVLAN:
+ sky2->rx_tag = length;
+ break;
+
+ case OP_RXCHKSVLAN:
+ sky2->rx_tag = length;
+ /* fall through */
+#endif
+ case OP_RXCHKS:
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = le16_to_cpu(status);
+ break;
+
+ case OP_TXINDEXLE:
+ /* TX index reports status for both ports */
+ tx_done[0] = status & 0xffff;
+ tx_done[1] = ((status >> 24) & 0xff)
+ | (u16)(length & 0xf) << 8;
+ break;
+
+ default:
+ if (net_ratelimit())
+ printk(KERN_WARNING PFX
+ "unknown status opcode 0x%x\n", le->opcode);
+ break;
+ }
+ }
+
+exit_loop:
+ sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
+ sky2_tx_check(hw, 0, tx_done[0]);
+ sky2_tx_check(hw, 1, tx_done[1]);
+
+ if (sky2_read16(hw, STAT_PUT_IDX) == hw->st_idx) {
+ /* need to restart TX timer */
+ if (is_ec_a1(hw)) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+
+ netif_rx_complete(dev0);
+ hw->intr_mask |= Y2_IS_STAT_BMU;
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ return 0;
+ } else {
+ *budget -= work_done;
+ dev0->quota -= work_done;
+ return 1;
+ }
+}
+
+static void sky2_hw_error(struct sky2_hw *hw, unsigned port, u32 status)
+{
+ struct net_device *dev = hw->dev[port];
+
+ if (net_ratelimit())
+ printk(KERN_INFO PFX "%s: hw error interrupt status 0x%x\n",
+ dev->name, status);
+
+ if (status & Y2_IS_PAR_RD1) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data read parity error\n",
+ dev->name);
+ /* Clear IRQ */
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_RD_PERR);
+ }
+
+ if (status & Y2_IS_PAR_WR1) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: ram data write parity error\n",
+ dev->name);
+
+ sky2_write16(hw, RAM_BUFFER(port, B3_RI_CTRL), RI_CLR_WR_PERR);
+ }
+
+ if (status & Y2_IS_PAR_MAC1) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: MAC parity error\n", dev->name);
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
+ }
+
+ if (status & Y2_IS_PAR_RX1) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: RX parity error\n", dev->name);
+ sky2_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), BMU_CLR_IRQ_PAR);
+ }
+
+ if (status & Y2_IS_TCP_TXA1) {
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: TCP segmentation error\n",
+ dev->name);
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_CLR_IRQ_TCP);
+ }
+}
+
+static void sky2_hw_intr(struct sky2_hw *hw)
+{
+ u32 status = sky2_read32(hw, B0_HWE_ISRC);
+
+ if (status & Y2_IS_TIST_OV)
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
+ u16 pci_err;
+
+ pci_read_config_word(hw->pdev, PCI_STATUS, &pci_err);
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci hw error (0x%x)\n",
+ pci_name(hw->pdev), pci_err);
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_write_config_word(hw->pdev, PCI_STATUS,
+ pci_err | PCI_STATUS_ERROR_BITS);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ }
+
+ if (status & Y2_IS_PCI_EXP) {
+ /* PCI-Express uncorrectable Error occurred */
+ u32 pex_err;
+
+ pci_read_config_dword(hw->pdev, PEX_UNC_ERR_STAT, &pex_err);
+
+ if (net_ratelimit())
+ printk(KERN_ERR PFX "%s: pci express error (0x%x)\n",
+ pci_name(hw->pdev), pex_err);
+
+ /* clear the interrupt */
+ sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+ 0xffffffffUL);
+ sky2_write32(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ if (pex_err & PEX_FATAL_ERRORS) {
+ u32 hwmsk = sky2_read32(hw, B0_HWE_IMSK);
+ hwmsk &= ~Y2_IS_PCI_EXP;
+ sky2_write32(hw, B0_HWE_IMSK, hwmsk);
+ }
+ }
+
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 0, status);
+ status >>= 8;
+ if (status & Y2_HWE_L1_MASK)
+ sky2_hw_error(hw, 1, status);
+}
+
+static void sky2_mac_intr(struct sky2_hw *hw, unsigned port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u8 status = sky2_read8(hw, SK_REG(port, GMAC_IRQ_SRC));
+
+ if (netif_msg_intr(sky2))
+ printk(KERN_INFO PFX "%s: mac interrupt status 0x%x\n",
+ dev->name, status);
+
+ if (status & GM_IS_RX_FF_OR) {
+ ++sky2->net_stats.rx_fifo_errors;
+ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO);
+ }
+
+ if (status & GM_IS_TX_FF_UR) {
+ ++sky2->net_stats.tx_fifo_errors;
+ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU);
+ }
+}
+
+static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
+{
+ struct net_device *dev = hw->dev[port];
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ hw->intr_mask &= ~(port == 0 ? Y2_IS_IRQ_PHY1 : Y2_IS_IRQ_PHY2);
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+ schedule_work(&sky2->phy_task);
+}
+
+static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct sky2_hw *hw = dev_id;
+ struct net_device *dev0 = hw->dev[0];
+ u32 status;
+
+ status = sky2_read32(hw, B0_Y2_SP_ISRC2);
+ if (status == 0 || status == ~0)
+ return IRQ_NONE;
+
+ if (status & Y2_IS_HW_ERR)
+ sky2_hw_intr(hw);
+
+ /* Do NAPI for Rx and Tx status */
+ if (status & Y2_IS_STAT_BMU) {
+ hw->intr_mask &= ~Y2_IS_STAT_BMU;
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+ if (likely(__netif_rx_schedule_prep(dev0))) {
+ prefetch(&hw->st_le[hw->st_idx]);
+ __netif_rx_schedule(dev0);
+ }
+ }
+
+ if (status & Y2_IS_IRQ_PHY1)
+ sky2_phy_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_PHY2)
+ sky2_phy_intr(hw, 1);
+
+ if (status & Y2_IS_IRQ_MAC1)
+ sky2_mac_intr(hw, 0);
+
+ if (status & Y2_IS_IRQ_MAC2)
+ sky2_mac_intr(hw, 1);
+
+ sky2_write32(hw, B0_Y2_SP_ICR, 2);
+
+ sky2_read32(hw, B0_IMSK);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void sky2_netpoll(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL);
+}
+#endif
+
+/* Chip internal frequency for clock calculations */
+static inline u32 sky2_mhz(const struct sky2_hw *hw)
+{
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_EC:
+ case CHIP_ID_YUKON_EC_U:
+ return 125; /* 125 Mhz */
+ case CHIP_ID_YUKON_FE:
+ return 100; /* 100 Mhz */
+ default: /* YUKON_XL */
+ return 156; /* 156 Mhz */
+ }
+}
+
+static inline u32 sky2_us2clk(const struct sky2_hw *hw, u32 us)
+{
+ return sky2_mhz(hw) * us;
+}
+
+static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
+{
+ return clk / sky2_mhz(hw);
+}
+
+
+static int sky2_reset(struct sky2_hw *hw)
+{
+ u32 ctst;
+ u16 status;
+ u8 t8, pmd_type;
+ int i;
+
+ ctst = sky2_read32(hw, B0_CTST);
+
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+ hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
+ if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+ printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
+ pci_name(hw->pdev), hw->chip_id);
+ return -EOPNOTSUPP;
+ }
+
+ /* ring for status responses */
+ hw->st_le = pci_alloc_consistent(hw->pdev, STATUS_LE_BYTES,
+ &hw->st_dma);
+ if (!hw->st_le)
+ return -ENOMEM;
+
+ /* disable ASF */
+ if (hw->chip_id <= CHIP_ID_YUKON_EC) {
+ sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
+ sky2_write16(hw, B0_CTST, Y2_ASF_DISABLE);
+ }
+
+ /* do a SW reset */
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_write8(hw, B0_CTST, CS_RST_CLR);
+
+ /* clear PCI errors, if any */
+ pci_read_config_word(hw->pdev, PCI_STATUS, &status);
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ pci_write_config_word(hw->pdev, PCI_STATUS,
+ status | PCI_STATUS_ERROR_BITS);
+
+ sky2_write8(hw, B0_CTST, CS_MRST_CLR);
+
+ /* clear any PEX errors */
+ if (is_pciex(hw)) {
+ u16 lstat;
+ pci_write_config_dword(hw->pdev, PEX_UNC_ERR_STAT,
+ 0xffffffffUL);
+ pci_read_config_word(hw->pdev, PEX_LNK_STAT, &lstat);
+ }
+
+ pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ hw->copper = !(pmd_type == 'L' || pmd_type == 'S');
+
+ hw->ports = 1;
+ t8 = sky2_read8(hw, B2_Y2_HW_RES);
+ if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
+ if (!(sky2_read8(hw, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC))
+ ++hw->ports;
+ }
+ hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+ sky2_set_power_state(hw, PCI_D0);
+
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+ }
+
+ sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ /* Clear I2C IRQ noise */
+ sky2_write32(hw, B2_I2C_IRQ, 1);
+
+ /* turn off hardware timer (unused) */
+ sky2_write8(hw, B2_TI_CTRL, TIM_STOP);
+ sky2_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+
+ sky2_write8(hw, B0_Y2LED, LED_STAT_ON);
+
+ /* Turn off descriptor polling */
+ sky2_write32(hw, B28_DPT_CTRL, DPT_STOP);
+
+ /* Turn off receive timestamp */
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_STOP);
+ sky2_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < hw->ports; i++)
+ sky2_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+ /* Initialize ram interface */
+ for (i = 0; i < hw->ports; i++) {
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_CTRL), RI_RST_CLR);
+
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
+ sky2_write8(hw, RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
+ }
+
+ sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK);
+
+ for (i = 0; i < hw->ports; i++)
+ sky2_phy_reset(hw, i);
+
+ memset(hw->st_le, 0, STATUS_LE_BYTES);
+ hw->st_idx = 0;
+
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_SET);
+ sky2_write32(hw, STAT_CTRL, SC_STAT_RST_CLR);
+
+ sky2_write32(hw, STAT_LIST_ADDR_LO, hw->st_dma);
+ sky2_write32(hw, STAT_LIST_ADDR_HI, (u64) hw->st_dma >> 32);
+
+ /* Set the list last index */
+ sky2_write16(hw, STAT_LAST_IDX, STATUS_RING_SIZE - 1);
+
+ /* These status setup values are copied from SysKonnect's driver */
+ if (is_ec_a1(hw)) {
+ /* WA for dev. #4.3 */
+ sky2_write16(hw, STAT_TX_IDX_TH, 0xfff); /* Tx Threshold */
+
+ /* set Status-FIFO watermark */
+ sky2_write8(hw, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */
+
+ /* set Status-FIFO ISR watermark */
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */
+ sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 10000));
+ } else {
+ sky2_write16(hw, STAT_TX_IDX_TH, 10);
+ sky2_write8(hw, STAT_FIFO_WM, 16);
+
+ /* set Status-FIFO ISR watermark */
+ if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev == 0)
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 4);
+ else
+ sky2_write8(hw, STAT_FIFO_ISR_WM, 16);
+
+ sky2_write32(hw, STAT_TX_TIMER_INI, sky2_us2clk(hw, 1000));
+ sky2_write32(hw, STAT_LEV_TIMER_INI, sky2_us2clk(hw, 100));
+ sky2_write32(hw, STAT_ISR_TIMER_INI, sky2_us2clk(hw, 20));
+ }
+
+ /* enable status unit */
+ sky2_write32(hw, STAT_CTRL, SC_STAT_OP_ON);
+
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+
+ return 0;
+}
+
+static u32 sky2_supported_modes(const struct sky2_hw *hw)
+{
+ u32 modes;
+ if (hw->copper) {
+ modes = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_Autoneg | SUPPORTED_TP;
+
+ if (hw->chip_id != CHIP_ID_YUKON_FE)
+ modes |= SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full;
+ } else
+ modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
+ | SUPPORTED_Autoneg;
+ return modes;
+}
+
+static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->supported = sky2_supported_modes(hw);
+ ecmd->phy_address = PHY_ADDR_MARV;
+ if (hw->copper) {
+ ecmd->supported = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full
+ | SUPPORTED_Autoneg | SUPPORTED_TP;
+ ecmd->port = PORT_TP;
+ } else
+ ecmd->port = PORT_FIBRE;
+
+ ecmd->advertising = sky2->advertising;
+ ecmd->autoneg = sky2->autoneg;
+ ecmd->speed = sky2->speed;
+ ecmd->duplex = sky2->duplex;
+ return 0;
+}
+
+static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ const struct sky2_hw *hw = sky2->hw;
+ u32 supported = sky2_supported_modes(hw);
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ ecmd->advertising = supported;
+ sky2->duplex = -1;
+ sky2->speed = -1;
+ } else {
+ u32 setting;
+
+ switch (ecmd->speed) {
+ case SPEED_1000:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_1000baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_1000baseT_Half;
+ else
+ return -EINVAL;
+ break;
+ case SPEED_100:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_100baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_100baseT_Half;
+ else
+ return -EINVAL;
+ break;
+
+ case SPEED_10:
+ if (ecmd->duplex == DUPLEX_FULL)
+ setting = SUPPORTED_10baseT_Full;
+ else if (ecmd->duplex == DUPLEX_HALF)
+ setting = SUPPORTED_10baseT_Half;
+ else
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((setting & supported) == 0)
+ return -EINVAL;
+
+ sky2->speed = ecmd->speed;
+ sky2->duplex = ecmd->duplex;
+ }
+
+ sky2->autoneg = ecmd->autoneg;
+ sky2->advertising = ecmd->advertising;
+
+ if (netif_running(dev))
+ sky2_phy_reinit(sky2);
+
+ return 0;
+}
+
+static void sky2_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, pci_name(sky2->hw->pdev));
+}
+
+static const struct sky2_stat {
+ char name[ETH_GSTRING_LEN];
+ u16 offset;
+} sky2_stats[] = {
+ { "tx_bytes", GM_TXO_OK_HI },
+ { "rx_bytes", GM_RXO_OK_HI },
+ { "tx_broadcast", GM_TXF_BC_OK },
+ { "rx_broadcast", GM_RXF_BC_OK },
+ { "tx_multicast", GM_TXF_MC_OK },
+ { "rx_multicast", GM_RXF_MC_OK },
+ { "tx_unicast", GM_TXF_UC_OK },
+ { "rx_unicast", GM_RXF_UC_OK },
+ { "tx_mac_pause", GM_TXF_MPAUSE },
+ { "rx_mac_pause", GM_RXF_MPAUSE },
+ { "collisions", GM_TXF_SNG_COL },
+ { "late_collision",GM_TXF_LAT_COL },
+ { "aborted", GM_TXF_ABO_COL },
+ { "multi_collisions", GM_TXF_MUL_COL },
+ { "fifo_underrun", GM_TXE_FIFO_UR },
+ { "fifo_overflow", GM_RXE_FIFO_OV },
+ { "rx_toolong", GM_RXF_LNG_ERR },
+ { "rx_jabber", GM_RXF_JAB_PKT },
+ { "rx_runt", GM_RXE_FRAG },
+ { "rx_too_long", GM_RXF_LNG_ERR },
+ { "rx_fcs_error", GM_RXF_FCS_ERR },
+};
+
+static u32 sky2_get_rx_csum(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ return sky2->rx_csum;
+}
+
+static int sky2_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2->rx_csum = data;
+
+ sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+
+ return 0;
+}
+
+static u32 sky2_get_msglevel(struct net_device *netdev)
+{
+ struct sky2_port *sky2 = netdev_priv(netdev);
+ return sky2->msg_enable;
+}
+
+static int sky2_nway_reset(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (sky2->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ sky2_phy_reinit(sky2);
+
+ return 0;
+}
+
+static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count)
+{
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ int i;
+
+ data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32
+ | (u64) gma_read32(hw, port, GM_TXO_OK_LO);
+ data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32
+ | (u64) gma_read32(hw, port, GM_RXO_OK_LO);
+
+ for (i = 2; i < count; i++)
+ data[i] = (u64) gma_read32(hw, port, sky2_stats[i].offset);
+}
+
+static void sky2_set_msglevel(struct net_device *netdev, u32 value)
+{
+ struct sky2_port *sky2 = netdev_priv(netdev);
+ sky2->msg_enable = value;
+}
+
+static int sky2_get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(sky2_stats);
+}
+
+static void sky2_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 * data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ sky2_phy_stats(sky2, data, ARRAY_SIZE(sky2_stats));
+}
+
+static void sky2_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+ int i;
+
+ switch (stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(sky2_stats); i++)
+ memcpy(data + i * ETH_GSTRING_LEN,
+ sky2_stats[i].name, ETH_GSTRING_LEN);
+ break;
+ }
+}
+
+/* Use hardware MIB variables for critical path statistics and
+ * transmit feedback not reported at interrupt.
+ * Other errors are accounted for in interrupt handler.
+ */
+static struct net_device_stats *sky2_get_stats(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u64 data[13];
+
+ sky2_phy_stats(sky2, data, ARRAY_SIZE(data));
+
+ sky2->net_stats.tx_bytes = data[0];
+ sky2->net_stats.rx_bytes = data[1];
+ sky2->net_stats.tx_packets = data[2] + data[4] + data[6];
+ sky2->net_stats.rx_packets = data[3] + data[5] + data[7];
+ sky2->net_stats.multicast = data[5] + data[7];
+ sky2->net_stats.collisions = data[10];
+ sky2->net_stats.tx_aborted_errors = data[12];
+
+ return &sky2->net_stats;
+}
+
+static int sky2_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
+ dev->dev_addr, ETH_ALEN);
+ memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
+ dev->dev_addr, ETH_ALEN);
+
+ if (netif_running(dev))
+ sky2_phy_reinit(sky2);
+
+ return 0;
+}
+
+static void sky2_set_multicast(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ struct dev_mc_list *list = dev->mc_list;
+ u16 reg;
+ u8 filter[8];
+
+ memset(filter, 0, sizeof(filter));
+
+ reg = gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA;
+
+ if (dev->flags & IFF_PROMISC) /* promiscuous */
+ reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+ else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */
+ memset(filter, 0xff, sizeof(filter));
+ else if (dev->mc_count == 0) /* no multicast */
+ reg &= ~GM_RXCR_MCF_ENA;
+ else {
+ int i;
+ reg |= GM_RXCR_MCF_ENA;
+
+ for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
+ u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
+ filter[bit / 8] |= 1 << (bit % 8);
+ }
+ }
+
+ gma_write16(hw, port, GM_MC_ADDR_H1,
+ (u16) filter[0] | ((u16) filter[1] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H2,
+ (u16) filter[2] | ((u16) filter[3] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H3,
+ (u16) filter[4] | ((u16) filter[5] << 8));
+ gma_write16(hw, port, GM_MC_ADDR_H4,
+ (u16) filter[6] | ((u16) filter[7] << 8));
+
+ gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+/* Can have one global because blinking is controlled by
+ * ethtool and that is always under RTNL mutex
+ */
+static void sky2_led(struct sky2_hw *hw, unsigned port, int on)
+{
+ u16 pg;
+
+ switch (hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL,
+ on ? (PHY_M_LEDC_LOS_CTRL(1) |
+ PHY_M_LEDC_INIT_CTRL(7) |
+ PHY_M_LEDC_STA1_CTRL(7) |
+ PHY_M_LEDC_STA0_CTRL(7))
+ : 0);
+
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ break;
+
+ default:
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ on ? PHY_M_LED_MO_DUP(MO_LED_ON) |
+ PHY_M_LED_MO_10(MO_LED_ON) |
+ PHY_M_LED_MO_100(MO_LED_ON) |
+ PHY_M_LED_MO_1000(MO_LED_ON) |
+ PHY_M_LED_MO_RX(MO_LED_ON)
+ : PHY_M_LED_MO_DUP(MO_LED_OFF) |
+ PHY_M_LED_MO_10(MO_LED_OFF) |
+ PHY_M_LED_MO_100(MO_LED_OFF) |
+ PHY_M_LED_MO_1000(MO_LED_OFF) |
+ PHY_M_LED_MO_RX(MO_LED_OFF));
+
+ }
+}
+
+/* blink LED's for finding board */
+static int sky2_phys_id(struct net_device *dev, u32 data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ u16 ledctrl, ledover = 0;
+ long ms;
+ int interrupted;
+ int onoff = 1;
+
+ if (!data || data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))
+ ms = jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT);
+ else
+ ms = data * 1000;
+
+ /* save initial values */
+ down(&sky2->phy_sema);
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+ ledctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ } else {
+ ledctrl = gm_phy_read(hw, port, PHY_MARV_LED_CTRL);
+ ledover = gm_phy_read(hw, port, PHY_MARV_LED_OVER);
+ }
+
+ interrupted = 0;
+ while (!interrupted && ms > 0) {
+ sky2_led(hw, port, onoff);
+ onoff = !onoff;
+
+ up(&sky2->phy_sema);
+ interrupted = msleep_interruptible(250);
+ down(&sky2->phy_sema);
+
+ ms -= 250;
+ }
+
+ /* resume regularly scheduled programming */
+ if (hw->chip_id == CHIP_ID_YUKON_XL) {
+ u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 3);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ledctrl);
+ gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+ } else {
+ gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+ gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+ }
+ up(&sky2->phy_sema);
+
+ return 0;
+}
+
+static void sky2_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ ecmd->tx_pause = sky2->tx_pause;
+ ecmd->rx_pause = sky2->rx_pause;
+ ecmd->autoneg = sky2->autoneg;
+}
+
+static int sky2_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int err = 0;
+
+ sky2->autoneg = ecmd->autoneg;
+ sky2->tx_pause = ecmd->tx_pause != 0;
+ sky2->rx_pause = ecmd->rx_pause != 0;
+
+ sky2_phy_reinit(sky2);
+
+ return err;
+}
+
+#ifdef CONFIG_PM
+static void sky2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = sky2->wol ? WAKE_MAGIC : 0;
+}
+
+static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ if (wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+ return -EOPNOTSUPP;
+
+ sky2->wol = wol->wolopts == WAKE_MAGIC;
+
+ if (sky2->wol) {
+ memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN);
+
+ sky2_write16(hw, WOL_CTRL_STAT,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT |
+ WOL_CTL_ENA_MAGIC_PKT_UNIT);
+ } else
+ sky2_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT);
+
+ return 0;
+}
+#endif
+
+static int sky2_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_STOP)
+ ecmd->tx_coalesce_usecs = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_TX_TIMER_INI);
+ ecmd->tx_coalesce_usecs = sky2_clk2us(hw, clks);
+ }
+ ecmd->tx_max_coalesced_frames = sky2_read16(hw, STAT_TX_IDX_TH);
+
+ if (sky2_read8(hw, STAT_LEV_TIMER_CTRL) == TIM_STOP)
+ ecmd->rx_coalesce_usecs = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_LEV_TIMER_INI);
+ ecmd->rx_coalesce_usecs = sky2_clk2us(hw, clks);
+ }
+ ecmd->rx_max_coalesced_frames = sky2_read8(hw, STAT_FIFO_WM);
+
+ if (sky2_read8(hw, STAT_ISR_TIMER_CTRL) == TIM_STOP)
+ ecmd->rx_coalesce_usecs_irq = 0;
+ else {
+ u32 clks = sky2_read32(hw, STAT_ISR_TIMER_INI);
+ ecmd->rx_coalesce_usecs_irq = sky2_clk2us(hw, clks);
+ }
+
+ ecmd->rx_max_coalesced_frames_irq = sky2_read8(hw, STAT_FIFO_ISR_WM);
+
+ return 0;
+}
+
+/* Note: this affect both ports */
+static int sky2_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ const u32 tmin = sky2_clk2us(hw, 1);
+ const u32 tmax = 5000;
+
+ if (ecmd->tx_coalesce_usecs != 0 &&
+ (ecmd->tx_coalesce_usecs < tmin || ecmd->tx_coalesce_usecs > tmax))
+ return -EINVAL;
+
+ if (ecmd->rx_coalesce_usecs != 0 &&
+ (ecmd->rx_coalesce_usecs < tmin || ecmd->rx_coalesce_usecs > tmax))
+ return -EINVAL;
+
+ if (ecmd->rx_coalesce_usecs_irq != 0 &&
+ (ecmd->rx_coalesce_usecs_irq < tmin || ecmd->rx_coalesce_usecs_irq > tmax))
+ return -EINVAL;
+
+ if (ecmd->tx_max_coalesced_frames > 0xffff)
+ return -EINVAL;
+ if (ecmd->rx_max_coalesced_frames > 0xff)
+ return -EINVAL;
+ if (ecmd->rx_max_coalesced_frames_irq > 0xff)
+ return -EINVAL;
+
+ if (ecmd->tx_coalesce_usecs == 0)
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_TX_TIMER_INI,
+ sky2_us2clk(hw, ecmd->tx_coalesce_usecs));
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+ }
+ sky2_write16(hw, STAT_TX_IDX_TH, ecmd->tx_max_coalesced_frames);
+
+ if (ecmd->rx_coalesce_usecs == 0)
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_LEV_TIMER_INI,
+ sky2_us2clk(hw, ecmd->rx_coalesce_usecs));
+ sky2_write8(hw, STAT_LEV_TIMER_CTRL, TIM_START);
+ }
+ sky2_write8(hw, STAT_FIFO_WM, ecmd->rx_max_coalesced_frames);
+
+ if (ecmd->rx_coalesce_usecs_irq == 0)
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_STOP);
+ else {
+ sky2_write32(hw, STAT_TX_TIMER_INI,
+ sky2_us2clk(hw, ecmd->rx_coalesce_usecs_irq));
+ sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START);
+ }
+ sky2_write8(hw, STAT_FIFO_ISR_WM, ecmd->rx_max_coalesced_frames_irq);
+ return 0;
+}
+
+static void sky2_get_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ ering->rx_max_pending = RX_MAX_PENDING;
+ ering->rx_mini_max_pending = 0;
+ ering->rx_jumbo_max_pending = 0;
+ ering->tx_max_pending = TX_RING_SIZE - 1;
+
+ ering->rx_pending = sky2->rx_pending;
+ ering->rx_mini_pending = 0;
+ ering->rx_jumbo_pending = 0;
+ ering->tx_pending = sky2->tx_pending;
+}
+
+static int sky2_set_ringparam(struct net_device *dev,
+ struct ethtool_ringparam *ering)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int err = 0;
+
+ if (ering->rx_pending > RX_MAX_PENDING ||
+ ering->rx_pending < 8 ||
+ ering->tx_pending < MAX_SKB_TX_LE ||
+ ering->tx_pending > TX_RING_SIZE - 1)
+ return -EINVAL;
+
+ if (netif_running(dev))
+ sky2_down(dev);
+
+ sky2->rx_pending = ering->rx_pending;
+ sky2->tx_pending = ering->tx_pending;
+
+ if (netif_running(dev)) {
+ err = sky2_up(dev);
+ if (err)
+ dev_close(dev);
+ else
+ sky2_set_multicast(dev);
+ }
+
+ return err;
+}
+
+static int sky2_get_regs_len(struct net_device *dev)
+{
+ return 0x4000;
+}
+
+/*
+ * Returns copy of control register region
+ * Note: access to the RAM address register set will cause timeouts.
+ */
+static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ const void __iomem *io = sky2->hw->regs;
+
+ BUG_ON(regs->len < B3_RI_WTO_R1);
+ regs->version = 1;
+ memset(p, 0, regs->len);
+
+ memcpy_fromio(p, io, B3_RAM_ADDR);
+
+ memcpy_fromio(p + B3_RI_WTO_R1,
+ io + B3_RI_WTO_R1,
+ regs->len - B3_RI_WTO_R1);
+}
+
+static struct ethtool_ops sky2_ethtool_ops = {
+ .get_settings = sky2_get_settings,
+ .set_settings = sky2_set_settings,
+ .get_drvinfo = sky2_get_drvinfo,
+ .get_msglevel = sky2_get_msglevel,
+ .set_msglevel = sky2_set_msglevel,
+ .nway_reset = sky2_nway_reset,
+ .get_regs_len = sky2_get_regs_len,
+ .get_regs = sky2_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+ .get_rx_csum = sky2_get_rx_csum,
+ .set_rx_csum = sky2_set_rx_csum,
+ .get_strings = sky2_get_strings,
+ .get_coalesce = sky2_get_coalesce,
+ .set_coalesce = sky2_set_coalesce,
+ .get_ringparam = sky2_get_ringparam,
+ .set_ringparam = sky2_set_ringparam,
+ .get_pauseparam = sky2_get_pauseparam,
+ .set_pauseparam = sky2_set_pauseparam,
+#ifdef CONFIG_PM
+ .get_wol = sky2_get_wol,
+ .set_wol = sky2_set_wol,
+#endif
+ .phys_id = sky2_phys_id,
+ .get_stats_count = sky2_get_stats_count,
+ .get_ethtool_stats = sky2_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+/* Initialize network device */
+static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
+ unsigned port, int highmem)
+{
+ struct sky2_port *sky2;
+ struct net_device *dev = alloc_etherdev(sizeof(*sky2));
+
+ if (!dev) {
+ printk(KERN_ERR "sky2 etherdev alloc failed");
+ return NULL;
+ }
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &hw->pdev->dev);
+ dev->irq = hw->pdev->irq;
+ dev->open = sky2_up;
+ dev->stop = sky2_down;
+ dev->do_ioctl = sky2_ioctl;
+ dev->hard_start_xmit = sky2_xmit_frame;
+ dev->get_stats = sky2_get_stats;
+ dev->set_multicast_list = sky2_set_multicast;
+ dev->set_mac_address = sky2_set_mac_address;
+ dev->change_mtu = sky2_change_mtu;
+ SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
+ dev->tx_timeout = sky2_tx_timeout;
+ dev->watchdog_timeo = TX_WATCHDOG;
+ if (port == 0)
+ dev->poll = sky2_poll;
+ dev->weight = NAPI_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = sky2_netpoll;
+#endif
+
+ sky2 = netdev_priv(dev);
+ sky2->netdev = dev;
+ sky2->hw = hw;
+ sky2->msg_enable = netif_msg_init(debug, default_msg);
+
+ spin_lock_init(&sky2->tx_lock);
+ /* Auto speed and flow control */
+ sky2->autoneg = AUTONEG_ENABLE;
+ sky2->tx_pause = 1;
+ sky2->rx_pause = 1;
+ sky2->duplex = -1;
+ sky2->speed = -1;
+ sky2->advertising = sky2_supported_modes(hw);
+
+ /* Receive checksum disabled for Yukon XL
+ * because of observed problems with incorrect
+ * values when multiple packets are received in one interrupt
+ */
+ sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
+
+ INIT_WORK(&sky2->phy_task, sky2_phy_task, sky2);
+ init_MUTEX(&sky2->phy_sema);
+ sky2->tx_pending = TX_DEF_PENDING;
+ sky2->rx_pending = is_ec_a1(hw) ? 8 : RX_DEF_PENDING;
+ sky2->rx_bufsize = sky2_buf_size(ETH_DATA_LEN);
+
+ hw->dev[port] = dev;
+
+ sky2->port = port;
+
+ dev->features |= NETIF_F_LLTX;
+ if (hw->chip_id != CHIP_ID_YUKON_EC_U)
+ dev->features |= NETIF_F_TSO;
+ if (highmem)
+ dev->features |= NETIF_F_HIGHDMA;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+
+#ifdef SKY2_VLAN_TAG_USED
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+ dev->vlan_rx_register = sky2_vlan_rx_register;
+ dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid;
+#endif
+
+ /* read the mac address */
+ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ /* device is off until link detection */
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ return dev;
+}
+
+static void __devinit sky2_show_addr(struct net_device *dev)
+{
+ const struct sky2_port *sky2 = netdev_priv(dev);
+
+ if (netif_msg_probe(sky2))
+ printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+}
+
+static int __devinit sky2_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *dev, *dev1 = NULL;
+ struct sky2_hw *hw;
+ int err, pm_cap, using_dac = 0;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+ pci_name(pdev));
+ goto err_out;
+ }
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+ pci_name(pdev));
+ goto err_out;
+ }
+
+ pci_set_master(pdev);
+
+ /* Find power-management capability. */
+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (pm_cap == 0) {
+ printk(KERN_ERR PFX "Cannot find PowerManagement capability, "
+ "aborting.\n");
+ err = -EIO;
+ goto err_out_free_regions;
+ }
+
+ if (sizeof(dma_addr_t) > sizeof(u32) &&
+ !(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
+ using_dac = 1;
+ err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ if (err < 0) {
+ printk(KERN_ERR PFX "%s unable to obtain 64 bit DMA "
+ "for consistent allocations\n", pci_name(pdev));
+ goto err_out_free_regions;
+ }
+
+ } else {
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
+ }
+
+#ifdef __BIG_ENDIAN
+ /* byte swap descriptors in hardware */
+ {
+ u32 reg;
+
+ pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+ reg |= PCI_REV_DESC;
+ pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+ }
+#endif
+
+ err = -ENOMEM;
+ hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+ if (!hw) {
+ printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
+
+ hw->pdev = pdev;
+
+ hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+ if (!hw->regs) {
+ printk(KERN_ERR PFX "%s: cannot map device registers\n",
+ pci_name(pdev));
+ goto err_out_free_hw;
+ }
+ hw->pm_cap = pm_cap;
+
+ err = sky2_reset(hw);
+ if (err)
+ goto err_out_iounmap;
+
+ printk(KERN_INFO PFX "v%s addr 0x%lx irq %d Yukon-%s (0x%x) rev %d\n",
+ DRV_VERSION, pci_resource_start(pdev, 0), pdev->irq,
+ yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
+ hw->chip_id, hw->chip_rev);
+
+ dev = sky2_init_netdev(hw, 0, using_dac);
+ if (!dev)
+ goto err_out_free_pci;
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "%s: cannot register net device\n",
+ pci_name(pdev));
+ goto err_out_free_netdev;
+ }
+
+ sky2_show_addr(dev);
+
+ if (hw->ports > 1 && (dev1 = sky2_init_netdev(hw, 1, using_dac))) {
+ if (register_netdev(dev1) == 0)
+ sky2_show_addr(dev1);
+ else {
+ /* Failure to register second port need not be fatal */
+ printk(KERN_WARNING PFX
+ "register of second port failed\n");
+ hw->dev[1] = NULL;
+ free_netdev(dev1);
+ }
+ }
+
+ err = request_irq(pdev->irq, sky2_intr, SA_SHIRQ, DRV_NAME, hw);
+ if (err) {
+ printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+ pci_name(pdev), pdev->irq);
+ goto err_out_unregister;
+ }
+
+ hw->intr_mask = Y2_IS_BASE;
+ sky2_write32(hw, B0_IMSK, hw->intr_mask);
+
+ pci_set_drvdata(pdev, hw);
+
+ return 0;
+
+err_out_unregister:
+ if (dev1) {
+ unregister_netdev(dev1);
+ free_netdev(dev1);
+ }
+ unregister_netdev(dev);
+err_out_free_netdev:
+ free_netdev(dev);
+err_out_free_pci:
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ pci_free_consistent(hw->pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
+err_out_iounmap:
+ iounmap(hw->regs);
+err_out_free_hw:
+ kfree(hw);
+err_out_free_regions:
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+err_out:
+ return err;
+}
+
+static void __devexit sky2_remove(struct pci_dev *pdev)
+{
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ struct net_device *dev0, *dev1;
+
+ if (!hw)
+ return;
+
+ dev0 = hw->dev[0];
+ dev1 = hw->dev[1];
+ if (dev1)
+ unregister_netdev(dev1);
+ unregister_netdev(dev0);
+
+ sky2_write32(hw, B0_IMSK, 0);
+ sky2_set_power_state(hw, PCI_D3hot);
+ sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
+ sky2_write8(hw, B0_CTST, CS_RST_SET);
+ sky2_read8(hw, B0_CTST);
+
+ free_irq(pdev->irq, hw);
+ pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ if (dev1)
+ free_netdev(dev1);
+ free_netdev(dev0);
+ iounmap(hw->regs);
+ kfree(hw);
+
+ pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ struct net_device *dev = hw->dev[i];
+
+ if (dev) {
+ if (!netif_running(dev))
+ continue;
+
+ sky2_down(dev);
+ netif_device_detach(dev);
+ }
+ }
+
+ return sky2_set_power_state(hw, pci_choose_state(pdev, state));
+}
+
+static int sky2_resume(struct pci_dev *pdev)
+{
+ struct sky2_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ sky2_set_power_state(hw, PCI_D0);
+
+ sky2_reset(hw);
+
+ for (i = 0; i < 2; i++) {
+ struct net_device *dev = hw->dev[i];
+ if (dev) {
+ if (netif_running(dev)) {
+ netif_device_attach(dev);
+ if (sky2_up(dev))
+ dev_close(dev);
+ }
+ }
+ }
+ return 0;
+}
+#endif
+
+static struct pci_driver sky2_driver = {
+ .name = DRV_NAME,
+ .id_table = sky2_id_table,
+ .probe = sky2_probe,
+ .remove = __devexit_p(sky2_remove),
+#ifdef CONFIG_PM
+ .suspend = sky2_suspend,
+ .resume = sky2_resume,
+#endif
+};
+
+static int __init sky2_init_module(void)
+{
+ return pci_register_driver(&sky2_driver);
+}
+
+static void __exit sky2_cleanup_module(void)
+{
+ pci_unregister_driver(&sky2_driver);
+}
+
+module_init(sky2_init_module);
+module_exit(sky2_cleanup_module);
+
+MODULE_DESCRIPTION("Marvell Yukon 2 Gigabit Ethernet driver");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
new file mode 100644
index 000000000000..95518921001c
--- /dev/null
+++ b/drivers/net/sky2.h
@@ -0,0 +1,1922 @@
+/*
+ * Definitions for the new Marvell Yukon 2 driver.
+ */
+#ifndef _SKY2_H
+#define _SKY2_H
+
+/* PCI config registers */
+#define PCI_DEV_REG1 0x40
+#define PCI_DEV_REG2 0x44
+#define PCI_DEV_STATUS 0x7c
+#define PCI_OS_PCI_X (1<<26)
+
+#define PEX_LNK_STAT 0xf2
+#define PEX_UNC_ERR_STAT 0x104
+#define PEX_DEV_CTRL 0xe8
+
+/* Yukon-2 */
+enum pci_dev_reg_1 {
+ PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
+ PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
+ PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
+ PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
+ PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
+ PCI_Y2_PHY1_POWD = 1<<26, /* Set PHY 1 to Power Down (YUKON-2) */
+};
+
+enum pci_dev_reg_2 {
+ PCI_VPD_WR_THR = 0xffL<<24, /* Bit 31..24: VPD Write Threshold */
+ PCI_DEV_SEL = 0x7fL<<17, /* Bit 23..17: EEPROM Device Select */
+ PCI_VPD_ROM_SZ = 7L<<14, /* Bit 16..14: VPD ROM Size */
+
+ PCI_PATCH_DIR = 0xfL<<8, /* Bit 11.. 8: Ext Patches dir 3..0 */
+ PCI_EXT_PATCHS = 0xfL<<4, /* Bit 7.. 4: Extended Patches 3..0 */
+ PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */
+ PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */
+
+ PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
+};
+
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+ PCI_STATUS_SIG_SYSTEM_ERROR | \
+ PCI_STATUS_REC_MASTER_ABORT | \
+ PCI_STATUS_REC_TARGET_ABORT | \
+ PCI_STATUS_PARITY)
+
+enum pex_dev_ctrl {
+ PEX_DC_MAX_RRS_MSK = 7<<12, /* Bit 14..12: Max. Read Request Size */
+ PEX_DC_EN_NO_SNOOP = 1<<11,/* Enable No Snoop */
+ PEX_DC_EN_AUX_POW = 1<<10,/* Enable AUX Power */
+ PEX_DC_EN_PHANTOM = 1<<9, /* Enable Phantom Functions */
+ PEX_DC_EN_EXT_TAG = 1<<8, /* Enable Extended Tag Field */
+ PEX_DC_MAX_PLS_MSK = 7<<5, /* Bit 7.. 5: Max. Payload Size Mask */
+ PEX_DC_EN_REL_ORD = 1<<4, /* Enable Relaxed Ordering */
+ PEX_DC_EN_UNS_RQ_RP = 1<<3, /* Enable Unsupported Request Reporting */
+ PEX_DC_EN_FAT_ER_RP = 1<<2, /* Enable Fatal Error Reporting */
+ PEX_DC_EN_NFA_ER_RP = 1<<1, /* Enable Non-Fatal Error Reporting */
+ PEX_DC_EN_COR_ER_RP = 1<<0, /* Enable Correctable Error Reporting */
+};
+#define PEX_DC_MAX_RD_RQ_SIZE(x) (((x)<<12) & PEX_DC_MAX_RRS_MSK)
+
+/* PEX_UNC_ERR_STAT PEX Uncorrectable Errors Status Register (Yukon-2) */
+enum pex_err {
+ PEX_UNSUP_REQ = 1<<20, /* Unsupported Request Error */
+
+ PEX_MALFOR_TLP = 1<<18, /* Malformed TLP */
+
+ PEX_UNEXP_COMP = 1<<16, /* Unexpected Completion */
+
+ PEX_COMP_TO = 1<<14, /* Completion Timeout */
+ PEX_FLOW_CTRL_P = 1<<13, /* Flow Control Protocol Error */
+ PEX_POIS_TLP = 1<<12, /* Poisoned TLP */
+
+ PEX_DATA_LINK_P = 1<<4, /* Data Link Protocol Error */
+ PEX_FATAL_ERRORS= (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P),
+};
+
+
+enum csr_regs {
+ B0_RAP = 0x0000,
+ B0_CTST = 0x0004,
+ B0_Y2LED = 0x0005,
+ B0_POWER_CTRL = 0x0007,
+ B0_ISRC = 0x0008,
+ B0_IMSK = 0x000c,
+ B0_HWE_ISRC = 0x0010,
+ B0_HWE_IMSK = 0x0014,
+
+ /* Special ISR registers (Yukon-2 only) */
+ B0_Y2_SP_ISRC2 = 0x001c,
+ B0_Y2_SP_ISRC3 = 0x0020,
+ B0_Y2_SP_EISR = 0x0024,
+ B0_Y2_SP_LISR = 0x0028,
+ B0_Y2_SP_ICR = 0x002c,
+
+ B2_MAC_1 = 0x0100,
+ B2_MAC_2 = 0x0108,
+ B2_MAC_3 = 0x0110,
+ B2_CONN_TYP = 0x0118,
+ B2_PMD_TYP = 0x0119,
+ B2_MAC_CFG = 0x011a,
+ B2_CHIP_ID = 0x011b,
+ B2_E_0 = 0x011c,
+
+ B2_Y2_CLK_GATE = 0x011d,
+ B2_Y2_HW_RES = 0x011e,
+ B2_E_3 = 0x011f,
+ B2_Y2_CLK_CTRL = 0x0120,
+
+ B2_TI_INI = 0x0130,
+ B2_TI_VAL = 0x0134,
+ B2_TI_CTRL = 0x0138,
+ B2_TI_TEST = 0x0139,
+
+ B2_TST_CTRL1 = 0x0158,
+ B2_TST_CTRL2 = 0x0159,
+ B2_GP_IO = 0x015c,
+
+ B2_I2C_CTRL = 0x0160,
+ B2_I2C_DATA = 0x0164,
+ B2_I2C_IRQ = 0x0168,
+ B2_I2C_SW = 0x016c,
+
+ B3_RAM_ADDR = 0x0180,
+ B3_RAM_DATA_LO = 0x0184,
+ B3_RAM_DATA_HI = 0x0188,
+
+/* RAM Interface Registers */
+/* Yukon-2: use RAM_BUFFER() to access the RAM buffer */
+/*
+ * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+ * not usable in SW. Please notice these are NOT real timeouts, these are
+ * the number of qWords transferred continuously.
+ */
+#define RAM_BUFFER(port, reg) (reg | (port <<6))
+
+ B3_RI_WTO_R1 = 0x0190,
+ B3_RI_WTO_XA1 = 0x0191,
+ B3_RI_WTO_XS1 = 0x0192,
+ B3_RI_RTO_R1 = 0x0193,
+ B3_RI_RTO_XA1 = 0x0194,
+ B3_RI_RTO_XS1 = 0x0195,
+ B3_RI_WTO_R2 = 0x0196,
+ B3_RI_WTO_XA2 = 0x0197,
+ B3_RI_WTO_XS2 = 0x0198,
+ B3_RI_RTO_R2 = 0x0199,
+ B3_RI_RTO_XA2 = 0x019a,
+ B3_RI_RTO_XS2 = 0x019b,
+ B3_RI_TO_VAL = 0x019c,
+ B3_RI_CTRL = 0x01a0,
+ B3_RI_TEST = 0x01a2,
+ B3_MA_TOINI_RX1 = 0x01b0,
+ B3_MA_TOINI_RX2 = 0x01b1,
+ B3_MA_TOINI_TX1 = 0x01b2,
+ B3_MA_TOINI_TX2 = 0x01b3,
+ B3_MA_TOVAL_RX1 = 0x01b4,
+ B3_MA_TOVAL_RX2 = 0x01b5,
+ B3_MA_TOVAL_TX1 = 0x01b6,
+ B3_MA_TOVAL_TX2 = 0x01b7,
+ B3_MA_TO_CTRL = 0x01b8,
+ B3_MA_TO_TEST = 0x01ba,
+ B3_MA_RCINI_RX1 = 0x01c0,
+ B3_MA_RCINI_RX2 = 0x01c1,
+ B3_MA_RCINI_TX1 = 0x01c2,
+ B3_MA_RCINI_TX2 = 0x01c3,
+ B3_MA_RCVAL_RX1 = 0x01c4,
+ B3_MA_RCVAL_RX2 = 0x01c5,
+ B3_MA_RCVAL_TX1 = 0x01c6,
+ B3_MA_RCVAL_TX2 = 0x01c7,
+ B3_MA_RC_CTRL = 0x01c8,
+ B3_MA_RC_TEST = 0x01ca,
+ B3_PA_TOINI_RX1 = 0x01d0,
+ B3_PA_TOINI_RX2 = 0x01d4,
+ B3_PA_TOINI_TX1 = 0x01d8,
+ B3_PA_TOINI_TX2 = 0x01dc,
+ B3_PA_TOVAL_RX1 = 0x01e0,
+ B3_PA_TOVAL_RX2 = 0x01e4,
+ B3_PA_TOVAL_TX1 = 0x01e8,
+ B3_PA_TOVAL_TX2 = 0x01ec,
+ B3_PA_CTRL = 0x01f0,
+ B3_PA_TEST = 0x01f2,
+
+ Y2_CFG_SPC = 0x1c00,
+};
+
+/* B0_CTST 16 bit Control/Status register */
+enum {
+ Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */
+ Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */
+ Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */
+ Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */
+ Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */
+ Y2_CLK_RUN_DIS = 1<<10,/* CLK_RUN Disable (YUKON-2 only) */
+ Y2_LED_STAT_ON = 1<<9, /* Status LED On (YUKON-2 only) */
+ Y2_LED_STAT_OFF = 1<<8, /* Status LED Off (YUKON-2 only) */
+
+ CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */
+ CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */
+ CS_STOP_DONE = 1<<5, /* Stop Master is finished */
+ CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */
+ CS_MRST_CLR = 1<<3, /* Clear Master reset */
+ CS_MRST_SET = 1<<2, /* Set Master reset */
+ CS_RST_CLR = 1<<1, /* Clear Software reset */
+ CS_RST_SET = 1, /* Set Software reset */
+};
+
+/* B0_LED 8 Bit LED register */
+enum {
+/* Bit 7.. 2: reserved */
+ LED_STAT_ON = 1<<1, /* Status LED on */
+ LED_STAT_OFF = 1, /* Status LED off */
+};
+
+/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+enum {
+ PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */
+ PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */
+ PC_VCC_ENA = 1<<5, /* Switch VCC Enable */
+ PC_VCC_DIS = 1<<4, /* Switch VCC Disable */
+ PC_VAUX_ON = 1<<3, /* Switch VAUX On */
+ PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */
+ PC_VCC_ON = 1<<1, /* Switch VCC On */
+ PC_VCC_OFF = 1<<0, /* Switch VCC Off */
+};
+
+/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
+
+/* B0_Y2_SP_ISRC2 32 bit Special Interrupt Source Reg 2 */
+/* B0_Y2_SP_ISRC3 32 bit Special Interrupt Source Reg 3 */
+/* B0_Y2_SP_EISR 32 bit Enter ISR Reg */
+/* B0_Y2_SP_LISR 32 bit Leave ISR Reg */
+enum {
+ Y2_IS_HW_ERR = 1<<31, /* Interrupt HW Error */
+ Y2_IS_STAT_BMU = 1<<30, /* Status BMU Interrupt */
+ Y2_IS_ASF = 1<<29, /* ASF subsystem Interrupt */
+
+ Y2_IS_POLL_CHK = 1<<27, /* Check IRQ from polling unit */
+ Y2_IS_TWSI_RDY = 1<<26, /* IRQ on end of TWSI Tx */
+ Y2_IS_IRQ_SW = 1<<25, /* SW forced IRQ */
+ Y2_IS_TIMINT = 1<<24, /* IRQ from Timer */
+
+ Y2_IS_IRQ_PHY2 = 1<<12, /* Interrupt from PHY 2 */
+ Y2_IS_IRQ_MAC2 = 1<<11, /* Interrupt from MAC 2 */
+ Y2_IS_CHK_RX2 = 1<<10, /* Descriptor error Rx 2 */
+ Y2_IS_CHK_TXS2 = 1<<9, /* Descriptor error TXS 2 */
+ Y2_IS_CHK_TXA2 = 1<<8, /* Descriptor error TXA 2 */
+
+ Y2_IS_IRQ_PHY1 = 1<<4, /* Interrupt from PHY 1 */
+ Y2_IS_IRQ_MAC1 = 1<<3, /* Interrupt from MAC 1 */
+ Y2_IS_CHK_RX1 = 1<<2, /* Descriptor error Rx 1 */
+ Y2_IS_CHK_TXS1 = 1<<1, /* Descriptor error TXS 1 */
+ Y2_IS_CHK_TXA1 = 1<<0, /* Descriptor error TXA 1 */
+
+ Y2_IS_BASE = Y2_IS_HW_ERR | Y2_IS_STAT_BMU |
+ Y2_IS_POLL_CHK | Y2_IS_TWSI_RDY |
+ Y2_IS_IRQ_SW | Y2_IS_TIMINT,
+ Y2_IS_PORT_1 = Y2_IS_IRQ_PHY1 | Y2_IS_IRQ_MAC1 |
+ Y2_IS_CHK_RX1 | Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXS1,
+ Y2_IS_PORT_2 = Y2_IS_IRQ_PHY2 | Y2_IS_IRQ_MAC2 |
+ Y2_IS_CHK_RX2 | Y2_IS_CHK_TXA2 | Y2_IS_CHK_TXS2,
+};
+
+/* 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 */
+ IS_IRQ_STAT = 1<<10, /* IRQ status exception */
+ IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */
+ IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */
+ IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */
+ IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */
+ IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */
+ IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */
+ IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */
+ 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 */
+};
+
+/* Hardware error interrupt mask for Yukon 2 */
+enum {
+ Y2_IS_TIST_OV = 1<<29,/* Time Stamp Timer overflow interrupt */
+ Y2_IS_SENSOR = 1<<28, /* Sensor interrupt */
+ Y2_IS_MST_ERR = 1<<27, /* Master error interrupt */
+ Y2_IS_IRQ_STAT = 1<<26, /* Status exception interrupt */
+ Y2_IS_PCI_EXP = 1<<25, /* PCI-Express interrupt */
+ Y2_IS_PCI_NEXP = 1<<24, /* PCI-Express error similar to PCI error */
+ /* Link 2 */
+ Y2_IS_PAR_RD2 = 1<<13, /* Read RAM parity error interrupt */
+ Y2_IS_PAR_WR2 = 1<<12, /* Write RAM parity error interrupt */
+ Y2_IS_PAR_MAC2 = 1<<11, /* MAC hardware fault interrupt */
+ Y2_IS_PAR_RX2 = 1<<10, /* Parity Error Rx Queue 2 */
+ Y2_IS_TCP_TXS2 = 1<<9, /* TCP length mismatch sync Tx queue IRQ */
+ Y2_IS_TCP_TXA2 = 1<<8, /* TCP length mismatch async Tx queue IRQ */
+ /* Link 1 */
+ Y2_IS_PAR_RD1 = 1<<5, /* Read RAM parity error interrupt */
+ Y2_IS_PAR_WR1 = 1<<4, /* Write RAM parity error interrupt */
+ Y2_IS_PAR_MAC1 = 1<<3, /* MAC hardware fault interrupt */
+ Y2_IS_PAR_RX1 = 1<<2, /* Parity Error Rx Queue 1 */
+ Y2_IS_TCP_TXS1 = 1<<1, /* TCP length mismatch sync Tx queue IRQ */
+ Y2_IS_TCP_TXA1 = 1<<0, /* TCP length mismatch async Tx queue IRQ */
+
+ Y2_HWE_L1_MASK = Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |
+ Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1,
+ Y2_HWE_L2_MASK = Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |
+ Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2,
+
+ Y2_HWE_ALL_MASK = Y2_IS_TIST_OV | Y2_IS_MST_ERR | Y2_IS_IRQ_STAT |
+ Y2_IS_PCI_EXP |
+ Y2_HWE_L1_MASK | Y2_HWE_L2_MASK,
+};
+
+/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
+enum {
+ DPT_START = 1<<1,
+ DPT_STOP = 1<<0,
+};
+
+/* B2_TST_CTRL1 8 bit Test Control Register 1 */
+enum {
+ TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+ TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+ TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+ TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+ TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */
+ TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */
+ TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */
+ TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
+enum {
+ CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
+ /* Bit 3.. 2: reserved */
+ CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */
+ CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/* B2_CHIP_ID 8 bit Chip Identification Number */
+enum {
+ CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */
+ CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */
+ CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+ CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */
+ CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */
+ CHIP_ID_YUKON_EC_U = 0xb4, /* Chip ID for YUKON-2 EC Ultra */
+ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */
+ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */
+
+ CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
+ CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
+ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
+};
+
+/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
+enum {
+ Y2_STATUS_LNK2_INAC = 1<<7, /* Status Link 2 inactive (0 = active) */
+ Y2_CLK_GAT_LNK2_DIS = 1<<6, /* Disable clock gating Link 2 */
+ Y2_COR_CLK_LNK2_DIS = 1<<5, /* Disable Core clock Link 2 */
+ Y2_PCI_CLK_LNK2_DIS = 1<<4, /* Disable PCI clock Link 2 */
+ Y2_STATUS_LNK1_INAC = 1<<3, /* Status Link 1 inactive (0 = active) */
+ Y2_CLK_GAT_LNK1_DIS = 1<<2, /* Disable clock gating Link 1 */
+ Y2_COR_CLK_LNK1_DIS = 1<<1, /* Disable Core clock Link 1 */
+ Y2_PCI_CLK_LNK1_DIS = 1<<0, /* Disable PCI clock Link 1 */
+};
+
+/* B2_Y2_HW_RES 8 bit HW Resources (Yukon-2 only) */
+enum {
+ CFG_LED_MODE_MSK = 7<<2, /* Bit 4.. 2: LED Mode Mask */
+ CFG_LINK_2_AVAIL = 1<<1, /* Link 2 available */
+ CFG_LINK_1_AVAIL = 1<<0, /* Link 1 available */
+};
+#define CFG_LED_MODE(x) (((x) & CFG_LED_MODE_MSK) >> 2)
+#define CFG_DUAL_MAC_MSK (CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL)
+
+
+/* B2_Y2_CLK_CTRL 32 bit Clock Frequency Control Register (Yukon-2/EC) */
+enum {
+ Y2_CLK_DIV_VAL_MSK = 0xff<<16,/* Bit 23..16: Clock Divisor Value */
+#define Y2_CLK_DIV_VAL(x) (((x)<<16) & Y2_CLK_DIV_VAL_MSK)
+ Y2_CLK_DIV_VAL2_MSK = 7<<21, /* Bit 23..21: Clock Divisor Value */
+ Y2_CLK_SELECT2_MSK = 0x1f<<16,/* Bit 20..16: Clock Select */
+#define Y2_CLK_DIV_VAL_2(x) (((x)<<21) & Y2_CLK_DIV_VAL2_MSK)
+#define Y2_CLK_SEL_VAL_2(x) (((x)<<16) & Y2_CLK_SELECT2_MSK)
+ Y2_CLK_DIV_ENA = 1<<1, /* Enable Core Clock Division */
+ Y2_CLK_DIV_DIS = 1<<0, /* Disable Core Clock Division */
+};
+
+/* B2_TI_CTRL 8 bit Timer control */
+/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
+enum {
+ TIM_START = 1<<2, /* Start Timer */
+ TIM_STOP = 1<<1, /* Stop Timer */
+ TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */
+};
+
+/* B2_TI_TEST 8 Bit Timer Test */
+/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
+/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
+enum {
+ TIM_T_ON = 1<<2, /* Test mode on */
+ TIM_T_OFF = 1<<1, /* Test mode off */
+ TIM_T_STEP = 1<<0, /* Test step */
+};
+
+/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+ /* Bit 31..19: reserved */
+#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+/* RAM Interface Registers */
+
+/* B3_RI_CTRL 16 bit RAM Interface Control Register */
+enum {
+ RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */
+ RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/
+
+ RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */
+ RI_RST_SET = 1<<0, /* Set RAM Interface Reset */
+};
+
+#define SK_RI_TO_53 36 /* RAM interface timeout */
+
+
+/* Port related registers FIFO, and Arbiter */
+#define SK_REG(port,reg) (((port)<<7)+(reg))
+
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
+/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
+/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
+/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */
+
+/* TXA_CTRL 8 bit Tx Arbiter Control Register */
+enum {
+ TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */
+ TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */
+ TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */
+ TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */
+ TXA_START_RC = 1<<3, /* Start sync Rate Control */
+ TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */
+ TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */
+ TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */
+};
+
+/*
+ * Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */
+enum {
+ TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/
+ TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */
+ TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */
+ TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */
+ TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
+ TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
+ TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */
+};
+
+
+enum {
+ B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
+ B7_CFG_SPC = 0x0380,/* copy of the Configuration register */
+ B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */
+ B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */
+ B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */
+ B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */
+ B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */
+ B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */
+ B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+ B8_Q_REGS = 0x0400, /* base of Queue registers */
+ Q_D = 0x00, /* 8*32 bit Current Descriptor */
+ Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
+ Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
+ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
+ Q_BC = 0x30, /* 32 bit Current Byte Counter */
+ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
+ Q_F = 0x38, /* 32 bit Flag Register */
+ Q_T1 = 0x3c, /* 32 bit Test Register 1 */
+ Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
+ Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
+ Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
+ Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
+ Q_T2 = 0x40, /* 32 bit Test Register 2 */
+ Q_T3 = 0x44, /* 32 bit Test Register 3 */
+
+/* Yukon-2 */
+ Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
+ Q_WM = 0x40, /* 16 bit FIFO Watermark */
+ Q_AL = 0x42, /* 8 bit FIFO Alignment */
+ Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
+ Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */
+ Q_RP = 0x48, /* 8 bit FIFO Read Pointer */
+ Q_RL = 0x4a, /* 8 bit FIFO Read Level */
+ Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */
+ Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */
+ Q_WL = 0x4e, /* 8 bit FIFO Write Level */
+ Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+enum {
+ Y2_B8_PREF_REGS = 0x0450,
+
+ PREF_UNIT_CTRL = 0x00, /* 32 bit Control register */
+ PREF_UNIT_LAST_IDX = 0x04, /* 16 bit Last Index */
+ PREF_UNIT_ADDR_LO = 0x08, /* 32 bit List start addr, low part */
+ PREF_UNIT_ADDR_HI = 0x0c, /* 32 bit List start addr, high part*/
+ PREF_UNIT_GET_IDX = 0x10, /* 16 bit Get Index */
+ PREF_UNIT_PUT_IDX = 0x14, /* 16 bit Put Index */
+ PREF_UNIT_FIFO_WP = 0x20, /* 8 bit FIFO write pointer */
+ PREF_UNIT_FIFO_RP = 0x24, /* 8 bit FIFO read pointer */
+ PREF_UNIT_FIFO_WM = 0x28, /* 8 bit FIFO watermark */
+ PREF_UNIT_FIFO_LEV = 0x2c, /* 8 bit FIFO level */
+
+ PREF_UNIT_MASK_IDX = 0x0fff,
+};
+#define Y2_QADDR(q,reg) (Y2_B8_PREF_REGS + (q) + (reg))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+ RB_START = 0x00,/* 32 bit RAM Buffer Start Address */
+ RB_END = 0x04,/* 32 bit RAM Buffer End Address */
+ RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */
+ RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */
+ RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */
+ RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */
+ RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */
+ RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */
+ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+ RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */
+ RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */
+ RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */
+ RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */
+ RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+ Q_R1 = 0x0000, /* Receive Queue 1 */
+ Q_R2 = 0x0080, /* Receive Queue 2 */
+ Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */
+ Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */
+ Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */
+ Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */
+};
+
+/* Different PHY Types */
+enum {
+ PHY_ADDR_MARV = 0,
+};
+
+#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+
+
+enum {
+ LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */
+ LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */
+ LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */
+ LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */
+
+ LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */
+
+/* Receive GMAC FIFO (YUKON and Yukon-2) */
+
+ RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */
+ RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+ RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */
+ RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */
+ RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */
+ RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */
+ RX_GMF_UP_THR = 0x0c58,/* 8 bit Rx Upper Pause Thr (Yukon-EC_U) */
+ RX_GMF_LP_THR = 0x0c5a,/* 8 bit Rx Lower Pause Thr (Yukon-EC_U) */
+ RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */
+ RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */
+
+ RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */
+
+ RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */
+
+ RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */
+};
+
+
+/* Q_BC 32 bit Current Byte Counter */
+
+/* BMU Control Status Registers */
+/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
+/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
+/* Q_CSR 32 bit BMU Control/Status Register */
+
+/* Rx BMU Control / Status Registers (Yukon-2) */
+enum {
+ BMU_IDLE = 1<<31, /* BMU Idle State */
+ BMU_RX_TCP_PKT = 1<<30, /* Rx TCP Packet (when RSS Hash enabled) */
+ BMU_RX_IP_PKT = 1<<29, /* Rx IP Packet (when RSS Hash enabled) */
+
+ BMU_ENA_RX_RSS_HASH = 1<<15, /* Enable Rx RSS Hash */
+ BMU_DIS_RX_RSS_HASH = 1<<14, /* Disable Rx RSS Hash */
+ BMU_ENA_RX_CHKSUM = 1<<13, /* Enable Rx TCP/IP Checksum Check */
+ BMU_DIS_RX_CHKSUM = 1<<12, /* Disable Rx TCP/IP Checksum Check */
+ BMU_CLR_IRQ_PAR = 1<<11, /* Clear IRQ on Parity errors (Rx) */
+ BMU_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment. error (Tx) */
+ BMU_CLR_IRQ_CHK = 1<<10, /* Clear IRQ Check */
+ BMU_STOP = 1<<9, /* Stop Rx/Tx Queue */
+ BMU_START = 1<<8, /* Start Rx/Tx Queue */
+ BMU_FIFO_OP_ON = 1<<7, /* FIFO Operational On */
+ BMU_FIFO_OP_OFF = 1<<6, /* FIFO Operational Off */
+ BMU_FIFO_ENA = 1<<5, /* Enable FIFO */
+ BMU_FIFO_RST = 1<<4, /* Reset FIFO */
+ BMU_OP_ON = 1<<3, /* BMU Operational On */
+ BMU_OP_OFF = 1<<2, /* BMU Operational Off */
+ BMU_RST_CLR = 1<<1, /* Clear BMU Reset (Enable) */
+ BMU_RST_SET = 1<<0, /* Set BMU Reset */
+
+ BMU_CLR_RESET = BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR,
+ BMU_OPER_INIT = BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START |
+ BMU_FIFO_ENA | BMU_OP_ON,
+
+ BMU_WM_DEFAULT = 0x600,
+};
+
+/* Tx BMU Control / Status Registers (Yukon-2) */
+ /* Bit 31: same as for Rx */
+enum {
+ BMU_TX_IPIDINCR_ON = 1<<13, /* Enable IP ID Increment */
+ BMU_TX_IPIDINCR_OFF = 1<<12, /* Disable IP ID Increment */
+ BMU_TX_CLR_IRQ_TCP = 1<<11, /* Clear IRQ on TCP segment length mismatch */
+};
+
+/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
+/* PREF_UNIT_CTRL 32 bit Prefetch Control register */
+enum {
+ PREF_UNIT_OP_ON = 1<<3, /* prefetch unit operational */
+ PREF_UNIT_OP_OFF = 1<<2, /* prefetch unit not operational */
+ PREF_UNIT_RST_CLR = 1<<1, /* Clear Prefetch Unit Reset */
+ PREF_UNIT_RST_SET = 1<<0, /* Set Prefetch Unit Reset */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/* RB_START 32 bit RAM Buffer Start Address */
+/* RB_END 32 bit RAM Buffer End Address */
+/* RB_WP 32 bit RAM Buffer Write Pointer */
+/* RB_RP 32 bit RAM Buffer Read Pointer */
+/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
+/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
+/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
+/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
+/* RB_PC 32 bit RAM Buffer Packet Counter */
+/* RB_LEV 32 bit RAM Buffer Level Register */
+
+#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+/* RB_TST2 8 bit RAM Buffer Test Register 2 */
+/* RB_TST1 8 bit RAM Buffer Test Register 1 */
+
+/* RB_CTRL 8 bit RAM Buffer Control Register */
+enum {
+ RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */
+ RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */
+ RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */
+ RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */
+};
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+ TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */
+ TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+ TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */
+
+ TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */
+ TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+ TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */
+
+ TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */
+ TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */
+ TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */
+};
+
+/* Descriptor Poll Timer Registers */
+enum {
+ B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */
+ B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */
+ B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */
+
+ B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */
+};
+
+/* Time Stamp Timer Registers (YUKON only) */
+enum {
+ GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */
+ GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */
+ GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */
+};
+
+/* Polling Unit Registers (Yukon-2 only) */
+enum {
+ POLL_CTRL = 0x0e20, /* 32 bit Polling Unit Control Reg */
+ POLL_LAST_IDX = 0x0e24,/* 16 bit Polling Unit List Last Index */
+
+ POLL_LIST_ADDR_LO= 0x0e28,/* 32 bit Poll. List Start Addr (low) */
+ POLL_LIST_ADDR_HI= 0x0e2c,/* 32 bit Poll. List Start Addr (high) */
+};
+
+/* ASF Subsystem Registers (Yukon-2 only) */
+enum {
+ B28_Y2_SMB_CONFIG = 0x0e40,/* 32 bit ASF SMBus Config Register */
+ B28_Y2_SMB_CSD_REG = 0x0e44,/* 32 bit ASF SMB Control/Status/Data */
+ B28_Y2_ASF_IRQ_V_BASE=0x0e60,/* 32 bit ASF IRQ Vector Base */
+
+ B28_Y2_ASF_STAT_CMD= 0x0e68,/* 32 bit ASF Status and Command Reg */
+ B28_Y2_ASF_HOST_COM= 0x0e6c,/* 32 bit ASF Host Communication Reg */
+ B28_Y2_DATA_REG_1 = 0x0e70,/* 32 bit ASF/Host Data Register 1 */
+ B28_Y2_DATA_REG_2 = 0x0e74,/* 32 bit ASF/Host Data Register 2 */
+ B28_Y2_DATA_REG_3 = 0x0e78,/* 32 bit ASF/Host Data Register 3 */
+ B28_Y2_DATA_REG_4 = 0x0e7c,/* 32 bit ASF/Host Data Register 4 */
+};
+
+/* Status BMU Registers (Yukon-2 only)*/
+enum {
+ STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */
+ STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */
+
+ STAT_LIST_ADDR_LO= 0x0e88,/* 32 bit Status List Start Addr (low) */
+ STAT_LIST_ADDR_HI= 0x0e8c,/* 32 bit Status List Start Addr (high) */
+ STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */
+ STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */
+ STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */
+ STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */
+ STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */
+ STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */
+
+/* FIFO Control/Status Registers (Yukon-2 only)*/
+ STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */
+ STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */
+ STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */
+ STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */
+ STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */
+ STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */
+ STAT_FIFO_ISR_WM= 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */
+
+/* Level and ISR Timer Registers (Yukon-2 only)*/
+ STAT_LEV_TIMER_INI= 0x0eb0,/* 32 bit Level Timer Init. Value Reg */
+ STAT_LEV_TIMER_CNT= 0x0eb4,/* 32 bit Level Timer Counter Reg */
+ STAT_LEV_TIMER_CTRL= 0x0eb8,/* 8 bit Level Timer Control Reg */
+ STAT_LEV_TIMER_TEST= 0x0eb9,/* 8 bit Level Timer Test Reg */
+ STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */
+ STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */
+ STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */
+ STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */
+ STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */
+ STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */
+ STAT_ISR_TIMER_CTRL= 0x0ed8,/* 8 bit ISR Timer Control Reg */
+ STAT_ISR_TIMER_TEST= 0x0ed9,/* 8 bit ISR Timer Test Reg */
+};
+
+enum {
+ LINKLED_OFF = 0x01,
+ LINKLED_ON = 0x02,
+ LINKLED_LINKSYNC_OFF = 0x04,
+ LINKLED_LINKSYNC_ON = 0x08,
+ LINKLED_BLINK_OFF = 0x10,
+ LINKLED_BLINK_ON = 0x20,
+};
+
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+ GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */
+ GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */
+ GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */
+ GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */
+ GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+ WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */
+
+ WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */
+ WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */
+ WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */
+ WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */
+ WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */
+ WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */
+ WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+ WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */
+ WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+
+ WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */
+ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */
+};
+
+enum {
+ WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */
+ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */
+};
+
+enum {
+ BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */
+ BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+ PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Marvel-specific registers */
+ PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */
+ PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */
+ PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */
+ PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
+ PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */
+ PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */
+ PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */
+ PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */
+ PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */
+ PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */
+ PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+ PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */
+ PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */
+ PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */
+ PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+ PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */
+ PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */
+ PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */
+ PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */
+ PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */
+};
+
+enum {
+ PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */
+ PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */
+ PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */
+ PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */
+ PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */
+ PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */
+ PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */
+ PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */
+ PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */
+ PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */
+};
+
+enum {
+ PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+ PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */
+ PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */
+};
+
+enum {
+ PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */
+
+ PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */
+ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */
+ PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */
+ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */
+ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */
+ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */
+ PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */
+};
+
+enum {
+ PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */
+ PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */
+ PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */
+};
+
+/* different Marvell PHY Ids */
+enum {
+ PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+
+ PHY_BCOM_ID1_A1 = 0x6041,
+ PHY_BCOM_ID1_B2 = 0x6043,
+ PHY_BCOM_ID1_C0 = 0x6044,
+ PHY_BCOM_ID1_C5 = 0x6047,
+
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+};
+
+/* Advertisement register bits */
+enum {
+ PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */
+
+ PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */
+ PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */
+ PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */
+ PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */
+ PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */
+ PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */
+ PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */
+ PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */
+ PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+ PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA,
+ PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL |
+ PHY_AN_100HALF | PHY_AN_100FULL,
+};
+
+/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
+ PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
+ /* Bit 9..8: reserved */
+ PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+};
+
+/** Marvell-Specific */
+enum {
+ PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */
+ PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */
+ PHY_M_AN_RF = 1<<13, /* Remote Fault */
+
+ PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */
+ PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */
+ PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */
+ PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */
+ PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */
+ PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */
+ PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */
+ PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+ PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */
+ PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */
+ PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */
+ PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+ PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */
+ PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */
+ PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */
+ PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */
+};
+
+/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */
+ PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */
+ PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */
+ PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */
+ PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */
+};
+
+/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+enum {
+ PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+ PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+ PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */
+ PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */
+ PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */
+ PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */
+ PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */
+ PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */
+ PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */
+ PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */
+ PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */
+ PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */
+};
+
+enum {
+ PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */
+ PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK)
+
+enum {
+ PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
+ PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */
+ PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+ PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */
+ PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */
+ PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */
+ PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */
+
+ PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */
+ PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+ PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */
+ PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */
+};
+
+/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+enum {
+ PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */
+ PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */
+ PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */
+ PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */
+ PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */
+ PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */
+ PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */
+ PHY_M_PS_LINK_UP = 1<<10, /* Link Up */
+ PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */
+ PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */
+ PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */
+ PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */
+ PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */
+ PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */
+ PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */
+ PHY_M_PS_JABBER = 1<<0, /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */
+ PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+ PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */
+ PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */
+ PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */
+ PHY_M_IS_AN_PR = 1<<12, /* Page Received */
+ PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */
+ PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */
+ PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */
+ PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */
+ PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */
+ PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */
+ PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */
+ PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */
+
+ PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */
+ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */
+ PHY_M_IS_JABBER = 1<<0, /* Jabber */
+
+ PHY_M_DEF_MSK = PHY_M_IS_LSP_CHANGE | PHY_M_IS_LST_CHANGE
+ | PHY_M_IS_FIFO_ERROR,
+ PHY_M_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL,
+};
+
+
+/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+enum {
+ PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+ PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+ PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+ PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */
+ /* (88E1111 only) */
+ PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */
+ /* !!! Errata in spec. (1 = disable) */
+ PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/
+ PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */
+ PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+ PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */
+ PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */
+ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x) ((x)<<10 & PHY_M_EC_M_DSC_MSK)
+ /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x) ((x)<<8 & PHY_M_EC_S_DSC_MSK)
+ /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_DSC_2(x) ((x)<<9 & PHY_M_EC_M_DSC_MSK2)
+ /* 000=1x; 001=2x; 010=3x; 011=4x */
+#define PHY_M_EC_MAC_S(x) ((x)<<4 & PHY_M_EC_MAC_S_MSK)
+ /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+enum {
+ PHY_M_PC_DIS_LINK_Pa = 1<<15,/* Disable Link Pulses */
+ PHY_M_PC_DSC_MSK = 7<<12,/* Bit 14..12: Downshift Counter */
+ PHY_M_PC_DOWN_S_ENA = 1<<11,/* Downshift Enable */
+};
+/* !!! Errata in spec. (1 = disable) */
+
+#define PHY_M_PC_DSC(x) (((x)<<12) & PHY_M_PC_DSC_MSK)
+ /* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+ MAC_TX_CLK_0_MHZ = 2,
+ MAC_TX_CLK_2_5_MHZ = 6,
+ MAC_TX_CLK_25_MHZ = 7,
+};
+
+/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+enum {
+ PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */
+ PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+ PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */
+ PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+ PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */
+ /* (88E1111 only) */
+};
+
+enum {
+ PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */
+ /* (88E1011 only) */
+ PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */
+ PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+ PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */
+ PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */
+ PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK)
+
+/***** PHY_MARV_PHY_STAT (page 3)16 bit r/w Polarity Control Reg. *****/
+enum {
+ PHY_M_POLC_LS1M_MSK = 0xf<<12, /* Bit 15..12: LOS,STAT1 Mix % Mask */
+ PHY_M_POLC_IS0M_MSK = 0xf<<8, /* Bit 11.. 8: INIT,STAT0 Mix % Mask */
+ PHY_M_POLC_LOS_MSK = 0x3<<6, /* Bit 7.. 6: LOS Pol. Ctrl. Mask */
+ PHY_M_POLC_INIT_MSK = 0x3<<4, /* Bit 5.. 4: INIT Pol. Ctrl. Mask */
+ PHY_M_POLC_STA1_MSK = 0x3<<2, /* Bit 3.. 2: STAT1 Pol. Ctrl. Mask */
+ PHY_M_POLC_STA0_MSK = 0x3, /* Bit 1.. 0: STAT0 Pol. Ctrl. Mask */
+};
+
+#define PHY_M_POLC_LS1_P_MIX(x) (((x)<<12) & PHY_M_POLC_LS1M_MSK)
+#define PHY_M_POLC_IS0_P_MIX(x) (((x)<<8) & PHY_M_POLC_IS0M_MSK)
+#define PHY_M_POLC_LOS_CTRL(x) (((x)<<6) & PHY_M_POLC_LOS_MSK)
+#define PHY_M_POLC_INIT_CTRL(x) (((x)<<4) & PHY_M_POLC_INIT_MSK)
+#define PHY_M_POLC_STA1_CTRL(x) (((x)<<2) & PHY_M_POLC_STA1_MSK)
+#define PHY_M_POLC_STA0_CTRL(x) (((x)<<0) & PHY_M_POLC_STA0_MSK)
+
+enum {
+ PULS_NO_STR = 0,/* no pulse stretching */
+ PULS_21MS = 1,/* 21 ms to 42 ms */
+ PULS_42MS = 2,/* 42 ms to 84 ms */
+ PULS_84MS = 3,/* 84 ms to 170 ms */
+ PULS_170MS = 4,/* 170 ms to 340 ms */
+ PULS_340MS = 5,/* 340 ms to 670 ms */
+ PULS_670MS = 6,/* 670 ms to 1.3 s */
+ PULS_1300MS = 7,/* 1.3 s to 2.7 s */
+};
+
+#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+ BLINK_42MS = 0,/* 42 ms */
+ BLINK_84MS = 1,/* 84 ms */
+ BLINK_170MS = 2,/* 170 ms */
+ BLINK_340MS = 3,/* 340 ms */
+ BLINK_670MS = 4,/* 670 ms */
+};
+
+/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */
+ /* Bit 13..12: reserved */
+#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */
+#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */
+#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */
+#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */
+#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */
+#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */
+
+enum {
+ MO_LED_NORM = 0,
+ MO_LED_BLINK = 1,
+ MO_LED_OFF = 2,
+ MO_LED_ON = 3,
+};
+
+/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+enum {
+ PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */
+ PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */
+ PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */
+ PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */
+ PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */
+};
+
+/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+enum {
+ PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+ PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */
+ PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */
+ PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */
+ PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */
+ PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */
+ PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */
+ /* (88E1111 only) */
+
+ PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */
+ PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */
+ PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/
+ /* Bit 15..12: reserved (used internally) */
+enum {
+ PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */
+ PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */
+ PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+ LED_PAR_CTRL_COLX = 0x00,
+ LED_PAR_CTRL_ERROR = 0x01,
+ LED_PAR_CTRL_DUPLEX = 0x02,
+ LED_PAR_CTRL_DP_COL = 0x03,
+ LED_PAR_CTRL_SPEED = 0x04,
+ LED_PAR_CTRL_LINK = 0x05,
+ LED_PAR_CTRL_TX = 0x06,
+ LED_PAR_CTRL_RX = 0x07,
+ LED_PAR_CTRL_ACT = 0x08,
+ LED_PAR_CTRL_LNK_RX = 0x09,
+ LED_PAR_CTRL_LNK_AC = 0x0a,
+ LED_PAR_CTRL_ACT_BL = 0x0b,
+ LED_PAR_CTRL_TX_BL = 0x0c,
+ LED_PAR_CTRL_RX_BL = 0x0d,
+ LED_PAR_CTRL_COL_BL = 0x0e,
+ LED_PAR_CTRL_INACT = 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/
+enum {
+ PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */
+ PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */
+ PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/
+enum {
+ PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */
+ PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */
+ PHY_M_MAC_MD_COPPER = 5,/* Copper only */
+ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */
+};
+#define PHY_M_MAC_MODE_SEL(x) (((x)<<7) & PHY_M_MAC_MD_MSK)
+
+/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
+enum {
+ PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+ PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+ PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */
+ PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers */
+/* Port Registers */
+enum {
+ GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */
+ GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */
+ GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */
+ GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */
+ GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */
+ GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */
+ GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */
+/* Source Address Registers */
+ GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */
+ GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */
+ GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */
+ GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */
+ GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */
+ GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+ GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */
+ GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */
+ GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */
+ GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+ GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */
+ GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */
+ GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+ GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */
+ GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */
+ GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+ GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */
+ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */
+ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
+};
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word (32 bit r/o)
+ */
+enum {
+ GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */
+ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */
+ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */
+ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */
+ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */
+ /* GM_MIB_CNT_BASE + 40: reserved */
+ GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */
+ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */
+ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */
+ GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */
+ GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */
+ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */
+ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */
+ GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */
+ GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */
+ GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */
+ GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */
+ GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */
+ GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */
+ GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */
+ GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */
+ /* GM_MIB_CNT_BASE + 168: reserved */
+ GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */
+ /* GM_MIB_CNT_BASE + 184: reserved */
+ GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */
+ GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */
+ GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */
+ GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */
+ GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */
+ GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */
+ GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */
+ GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */
+ GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */
+ GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */
+ GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */
+ GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */
+ GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */
+
+ GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */
+ GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */
+ GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */
+ GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */
+ GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */
+ GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+enum {
+ GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */
+ GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */
+ GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */
+ GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */
+ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */
+ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */
+ GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */
+ GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */
+
+ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */
+ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+ GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */
+ GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */
+ GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */
+};
+
+/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+enum {
+ GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */
+ GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */
+ GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */
+ GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */
+ GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */
+ GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */
+ GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */
+ GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */
+ GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */
+ GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */
+ GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */
+ GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */
+ GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */
+ GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */
+ GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+
+/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+enum {
+ GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
+ GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
+ GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
+ GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */
+};
+
+#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF 0x04
+
+/* GM_RX_CTRL 16 bit r/w Receive Control Register */
+enum {
+ GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */
+ GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */
+ GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */
+ GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */
+};
+
+/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+enum {
+ GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */
+ GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */
+ GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */
+ GM_TXPA_BO_LIM_MSK = 0x0f, /* Bit 3.. 0: Backoff Limit Mask */
+
+ TX_JAM_LEN_DEF = 0x03,
+ TX_JAM_IPG_DEF = 0x0b,
+ TX_IPG_JAM_DEF = 0x1c,
+ TX_BOF_LIM_DEF = 0x04,
+};
+
+#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK)
+#define TX_BACK_OFF_LIM(x) ((x) & GM_TXPA_BO_LIM_MSK)
+
+
+/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+enum {
+ GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */
+ GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */
+ GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */
+ GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */
+ GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+};
+
+#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF 0x04
+
+#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF 0x1e
+
+/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+enum {
+ GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */
+ GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */
+ GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/
+ GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */
+ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */
+};
+
+#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+enum {
+ GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */
+ GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */
+};
+
+/* Receive Frame Status Encoding */
+enum {
+ GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_VLAN = 1<<13, /* VLAN Packet */
+ GMR_FS_JABBER = 1<<12, /* Jabber Packet */
+ GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */
+ GMR_FS_MC = 1<<10, /* Multicast Packet */
+ GMR_FS_BC = 1<<9, /* Broadcast Packet */
+ GMR_FS_RX_OK = 1<<8, /* Receive OK (Good Packet) */
+ GMR_FS_GOOD_FC = 1<<7, /* Good Flow-Control Packet */
+ GMR_FS_BAD_FC = 1<<6, /* Bad Flow-Control Packet */
+ GMR_FS_MII_ERR = 1<<5, /* MII Error */
+ GMR_FS_LONG_ERR = 1<<4, /* Too Long Packet */
+ GMR_FS_FRAGMENT = 1<<3, /* Fragment */
+
+ GMR_FS_CRC_ERR = 1<<1, /* CRC Error */
+ GMR_FS_RX_FF_OV = 1<<0, /* Rx FIFO Overflow */
+
+ GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR |
+ GMR_FS_FRAGMENT | GMR_FS_LONG_ERR |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+ GMR_FS_UN_SIZE | GMR_FS_JABBER,
+};
+
+/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+enum {
+ RX_TRUNC_ON = 1<<27, /* enable packet truncation */
+ RX_TRUNC_OFF = 1<<26, /* disable packet truncation */
+ RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
+ RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
+
+ GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
+ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
+ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
+
+ GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */
+ GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */
+ GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */
+ GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */
+ GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */
+ GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */
+ GMF_CLI_RX_C = 1<<4, /* Clear IRQ Rx Frame Complete */
+
+ GMF_OPER_ON = 1<<3, /* Operational Mode On */
+ GMF_OPER_OFF = 1<<2, /* Operational Mode Off */
+ GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */
+ GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */
+
+ RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */
+
+ GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON,
+};
+
+
+/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+enum {
+ TX_STFW_DIS = 1<<31,/* Disable Store & Forward (Yukon-EC Ultra) */
+ TX_STFW_ENA = 1<<30,/* Enable Store & Forward (Yukon-EC Ultra) */
+
+ TX_VLAN_TAG_ON = 1<<25,/* enable VLAN tagging */
+ TX_VLAN_TAG_OFF = 1<<24,/* disable VLAN tagging */
+
+ GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */
+ GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */
+ GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */
+
+ GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */
+ GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */
+ GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */
+};
+
+/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+ GMT_ST_START = 1<<2, /* Start Time Stamp Timer */
+ GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */
+ GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */
+};
+
+/* B28_Y2_ASF_STAT_CMD 32 bit ASF Status and Command Reg */
+enum {
+ Y2_ASF_OS_PRES = 1<<4, /* ASF operation system present */
+ Y2_ASF_RESET = 1<<3, /* ASF system in reset state */
+ Y2_ASF_RUNNING = 1<<2, /* ASF system operational */
+ Y2_ASF_CLR_HSTI = 1<<1, /* Clear ASF IRQ */
+ Y2_ASF_IRQ = 1<<0, /* Issue an IRQ to ASF system */
+
+ Y2_ASF_UC_STATE = 3<<2, /* ASF uC State */
+ Y2_ASF_CLK_HALT = 0, /* ASF system clock stopped */
+};
+
+/* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */
+enum {
+ Y2_ASF_CLR_ASFI = 1<<1, /* Clear host IRQ */
+ Y2_ASF_HOST_IRQ = 1<<0, /* Issue an IRQ to HOST system */
+};
+
+/* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */
+enum {
+ SC_STAT_CLR_IRQ = 1<<4, /* Status Burst IRQ clear */
+ SC_STAT_OP_ON = 1<<3, /* Operational Mode On */
+ SC_STAT_OP_OFF = 1<<2, /* Operational Mode Off */
+ SC_STAT_RST_CLR = 1<<1, /* Clear Status Unit Reset (Enable) */
+ SC_STAT_RST_SET = 1<<0, /* Set Status Unit Reset */
+};
+
+/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+enum {
+ GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
+ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
+ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
+ GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */
+ GMC_PAUSE_ON = 1<<3, /* Pause On */
+ GMC_PAUSE_OFF = 1<<2, /* Pause Off */
+ GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */
+ GMC_RST_SET = 1<<0, /* Set GMAC Reset */
+};
+
+/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+enum {
+ GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
+ GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */
+ GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */
+ GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */
+ GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */
+ GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */
+ GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */
+ GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */
+ GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */
+ GPC_ANEG_0 = 1<<19, /* ANEG[0] */
+ GPC_ENA_XC = 1<<18, /* Enable MDI crossover */
+ GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */
+ GPC_ANEG_3 = 1<<16, /* ANEG[3] */
+ GPC_ANEG_2 = 1<<15, /* ANEG[2] */
+ GPC_ANEG_1 = 1<<14, /* ANEG[1] */
+ GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */
+ GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */
+ GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */
+ GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */
+ GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */
+ GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */
+ /* Bits 7..2: reserved */
+ GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */
+ GPC_RST_SET = 1<<0, /* Set GPHY Reset */
+};
+
+/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+enum {
+ GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */
+ GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */
+ GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */
+ GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */
+ GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
+ GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
+
+#define GMAC_DEF_MSK GM_IS_TX_FF_UR
+
+/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+ /* Bits 15.. 2: reserved */
+ GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */
+ GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */
+
+
+/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
+ WOL_CTL_LINK_CHG_OCC = 1<<15,
+ WOL_CTL_MAGIC_PKT_OCC = 1<<14,
+ WOL_CTL_PATTERN_OCC = 1<<13,
+ WOL_CTL_CLEAR_RESULT = 1<<12,
+ WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11,
+ WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9,
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8,
+ WOL_CTL_ENA_PME_ON_PATTERN = 1<<7,
+ WOL_CTL_DIS_PME_ON_PATTERN = 1<<6,
+ WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5,
+ WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4,
+ WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3,
+ WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2,
+ WOL_CTL_ENA_PATTERN_UNIT = 1<<1,
+ WOL_CTL_DIS_PATTERN_UNIT = 1<<0,
+};
+
+#define WOL_CTL_DEFAULT \
+ (WOL_CTL_DIS_PME_ON_LINK_CHG | \
+ WOL_CTL_DIS_PME_ON_PATTERN | \
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
+ WOL_CTL_DIS_LINK_CHG_UNIT | \
+ WOL_CTL_DIS_PATTERN_UNIT | \
+ WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x) (1 << (x))
+
+
+/* Control flags */
+enum {
+ UDPTCP = 1<<0,
+ CALSUM = 1<<1,
+ WR_SUM = 1<<2,
+ INIT_SUM= 1<<3,
+ LOCK_SUM= 1<<4,
+ INS_VLAN= 1<<5,
+ FRC_STAT= 1<<6,
+ EOP = 1<<7,
+};
+
+enum {
+ HW_OWNER = 1<<7,
+ OP_TCPWRITE = 0x11,
+ OP_TCPSTART = 0x12,
+ OP_TCPINIT = 0x14,
+ OP_TCPLCK = 0x18,
+ OP_TCPCHKSUM = OP_TCPSTART,
+ OP_TCPIS = OP_TCPINIT | OP_TCPSTART,
+ OP_TCPLW = OP_TCPLCK | OP_TCPWRITE,
+ OP_TCPLSW = OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE,
+ OP_TCPLISW = OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE,
+
+ OP_ADDR64 = 0x21,
+ OP_VLAN = 0x22,
+ OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
+ OP_LRGLEN = 0x24,
+ OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
+ OP_BUFFER = 0x40,
+ OP_PACKET = 0x41,
+ OP_LARGESEND = 0x43,
+
+/* YUKON-2 STATUS opcodes defines */
+ OP_RXSTAT = 0x60,
+ OP_RXTIMESTAMP = 0x61,
+ OP_RXVLAN = 0x62,
+ OP_RXCHKS = 0x64,
+ OP_RXCHKSVLAN = OP_RXCHKS | OP_RXVLAN,
+ OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
+ OP_RSS_HASH = 0x65,
+ OP_TXINDEXLE = 0x68,
+};
+
+/* Yukon 2 hardware interface
+ * Not tested on big endian
+ */
+struct sky2_tx_le {
+ union {
+ __le32 addr;
+ struct {
+ __le16 offset;
+ __le16 start;
+ } csum __attribute((packed));
+ struct {
+ __le16 size;
+ __le16 rsvd;
+ } tso __attribute((packed));
+ } tx;
+ __le16 length; /* also vlan tag or checksum start */
+ u8 ctrl;
+ u8 opcode;
+} __attribute((packed));
+
+struct sky2_rx_le {
+ __le32 addr;
+ __le16 length;
+ u8 ctrl;
+ u8 opcode;
+} __attribute((packed));;
+
+struct sky2_status_le {
+ __le32 status; /* also checksum */
+ __le16 length; /* also vlan tag */
+ u8 link;
+ u8 opcode;
+} __attribute((packed));
+
+struct tx_ring_info {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(mapaddr);
+ u16 idx;
+};
+
+struct ring_info {
+ struct sk_buff *skb;
+ dma_addr_t mapaddr;
+};
+
+struct sky2_port {
+ struct sky2_hw *hw;
+ struct net_device *netdev;
+ unsigned port;
+ u32 msg_enable;
+
+ spinlock_t tx_lock ____cacheline_aligned_in_smp;
+ struct tx_ring_info *tx_ring;
+ struct sky2_tx_le *tx_le;
+ u16 tx_cons; /* next le to check */
+ u16 tx_prod; /* next le to use */
+ u32 tx_addr64;
+ u16 tx_pending;
+ u16 tx_last_put;
+ u16 tx_last_mss;
+
+ struct ring_info *rx_ring ____cacheline_aligned_in_smp;
+ struct sky2_rx_le *rx_le;
+ u32 rx_addr64;
+ u16 rx_next; /* next re to check */
+ u16 rx_put; /* next le index to use */
+ u16 rx_pending;
+ u16 rx_last_put;
+ u16 rx_bufsize;
+#ifdef SKY2_VLAN_TAG_USED
+ u16 rx_tag;
+ struct vlan_group *vlgrp;
+#endif
+
+ dma_addr_t rx_le_map;
+ dma_addr_t tx_le_map;
+ u32 advertising; /* ADVERTISED_ bits */
+ u16 speed; /* SPEED_1000, SPEED_100, ... */
+ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
+ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
+ u8 rx_pause;
+ u8 tx_pause;
+ u8 rx_csum;
+ u8 wol;
+
+ struct net_device_stats net_stats;
+
+ struct work_struct phy_task;
+ struct semaphore phy_sema;
+};
+
+struct sky2_hw {
+ void __iomem *regs;
+ struct pci_dev *pdev;
+ u32 intr_mask;
+ struct net_device *dev[2];
+
+ int pm_cap;
+ u8 chip_id;
+ u8 chip_rev;
+ u8 copper;
+ u8 ports;
+
+ struct sky2_status_le *st_le;
+ u32 st_idx;
+ dma_addr_t st_dma;
+};
+
+/* Register accessor for memory mapped device */
+static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg)
+{
+ return readl(hw->regs + reg);
+}
+
+static inline u16 sky2_read16(const struct sky2_hw *hw, unsigned reg)
+{
+ return readw(hw->regs + reg);
+}
+
+static inline u8 sky2_read8(const struct sky2_hw *hw, unsigned reg)
+{
+ return readb(hw->regs + reg);
+}
+
+/* This should probably go away, bus based tweeks suck */
+static inline int is_pciex(const struct sky2_hw *hw)
+{
+ u32 status;
+ pci_read_config_dword(hw->pdev, PCI_DEV_STATUS, &status);
+ return (status & PCI_OS_PCI_X) == 0;
+}
+
+static inline void sky2_write32(const struct sky2_hw *hw, unsigned reg, u32 val)
+{
+ writel(val, hw->regs + reg);
+}
+
+static inline void sky2_write16(const struct sky2_hw *hw, unsigned reg, u16 val)
+{
+ writew(val, hw->regs + reg);
+}
+
+static inline void sky2_write8(const struct sky2_hw *hw, unsigned reg, u8 val)
+{
+ writeb(val, hw->regs + reg);
+}
+
+/* Yukon PHY related registers */
+#define SK_GMAC_REG(port,reg) \
+ (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg))
+#define GM_PHY_RETRIES 100
+
+static inline u16 gma_read16(const struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+ return sky2_read16(hw, SK_GMAC_REG(port,reg));
+}
+
+static inline u32 gma_read32(struct sky2_hw *hw, unsigned port, unsigned reg)
+{
+ unsigned base = SK_GMAC_REG(port, reg);
+ return (u32) sky2_read16(hw, base)
+ | (u32) sky2_read16(hw, base+4) << 16;
+}
+
+static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v)
+{
+ sky2_write16(hw, SK_GMAC_REG(port,r), v);
+}
+
+static inline void gma_set_addr(struct sky2_hw *hw, unsigned port, unsigned reg,
+ const u8 *addr)
+{
+ gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8));
+ gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8));
+ gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8));
+}
+#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 404ea4297e32..b2e18d28850d 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -651,11 +651,6 @@ static void sl_setup(struct net_device *dev)
******************************************/
-static int slip_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -869,10 +864,6 @@ static int slip_open(struct tty_struct *tty)
sl->line = tty_devnum(tty);
sl->pid = current->pid;
- /* FIXME: already done before we were called - seems this can go */
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
-
if (!test_bit(SLF_INUSE, &sl->flags)) {
/* Perform the low-level SLIP initialization. */
if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -897,6 +888,7 @@ static int slip_open(struct tty_struct *tty)
/* Done. We have linked the TTY line to a channel. */
rtnl_unlock();
+ tty->receive_room = 65536; /* We don't flow control */
return sl->dev->base_addr;
err_free_bufs:
@@ -1329,7 +1321,6 @@ static struct tty_ldisc sl_ldisc = {
.close = slip_close,
.ioctl = slip_ioctl,
.receive_buf = slip_receive_buf,
- .receive_room = slip_receive_room,
.write_wakeup = slip_write_wakeup,
};
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index ba8593ac3f8a..3db30cd0625e 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -168,18 +168,6 @@ static int __init do_ultra_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- /* NB: ultra_close_card() does free_irq */
-#ifdef __ISAPNP__
- struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
- if (idev)
- pnp_device_detach(idev);
-#endif
- release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init ultra_probe(int unit)
{
@@ -594,6 +582,18 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ /* NB: ultra_close_card() does free_irq */
+#ifdef __ISAPNP__
+ struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+ if (idev)
+ pnp_device_detach(idev);
+#endif
+ release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 28bf2e69eb5e..7ec08127c9d6 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -88,7 +88,6 @@ static const char version[] =
#include <linux/skbuff.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include "smc91x.h"
@@ -2007,12 +2006,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
}
/* Grab the IRQ */
- retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
+ retval = request_irq(dev->irq, &smc_interrupt, SMC_IRQ_FLAGS, dev->name, dev);
if (retval)
goto err_out;
- set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE);
-
#ifdef SMC_USE_PXA_DMA
{
int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 5c2824be4ee6..e0efd1964e72 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -90,7 +90,7 @@
__l--; \
} \
} while (0)
-#define set_irq_type(irq, type)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_SA1100_PLEB)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -109,7 +109,7 @@
#define SMC_outw(v, a, r) writew(v, (a) + (r))
#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
-#define set_irq_type(irq, type) do {} while (0)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_SA1100_ASSABET)
@@ -185,11 +185,11 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#include <asm/mach-types.h>
#include <asm/arch/cpu.h>
-#define SMC_IRQ_TRIGGER_TYPE (( \
+#define SMC_IRQ_FLAGS (( \
machine_is_omap_h2() \
|| machine_is_omap_h3() \
|| (machine_is_omap_innovator() && !cpu_is_omap1510()) \
- ) ? IRQT_FALLING : IRQT_RISING)
+ ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING)
#elif defined(CONFIG_SH_SH4202_MICRODEV)
@@ -209,7 +209,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l)
#define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l)
-#define set_irq_type(irq, type) do {} while(0)
+#define SMC_IRQ_FLAGS (0)
#elif defined(CONFIG_ISA)
@@ -237,7 +237,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l)
-#define set_irq_type(irq, type) do {} while(0)
+#define SMC_IRQ_FLAGS (0)
#define RPC_LSA_DEFAULT RPC_LED_TX_RX
#define RPC_LSB_DEFAULT RPC_LED_100_10
@@ -319,7 +319,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
au_writew(*_p++ , _a); \
} while(0)
-#define set_irq_type(irq, type) do {} while (0)
+#define SMC_IRQ_FLAGS (0)
#else
@@ -342,8 +342,8 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#endif
-#ifndef SMC_IRQ_TRIGGER_TYPE
-#define SMC_IRQ_TRIGGER_TYPE IRQT_RISING
+#ifndef SMC_IRQ_FLAGS
+#define SMC_IRQ_FLAGS SA_TRIGGER_RISING
#endif
#ifdef SMC_USE_PXA_DMA
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 0d765f1733b5..1f5975a61e1f 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -22,7 +22,6 @@
*/
#include <linux/config.h>
-
#include <linux/compiler.h>
#include <linux/crc32.h>
#include <linux/delay.h>
@@ -30,6 +29,7 @@
#include <linux/ethtool.h>
#include <linux/firmware.h>
#include <linux/if_vlan.h>
+#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ip.h>
@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/tcp.h>
#include <linux/types.h>
+#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <asm/bitops.h>
@@ -108,42 +109,6 @@ spider_net_write_reg(struct spider_net_card *card, u32 reg, u32 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
@@ -199,60 +164,33 @@ spider_net_read_phy(struct net_device *netdev, int mii_id, int reg)
}
/**
- * 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
+ * spider_net_rx_irq_off - switch off rx irq on this spider card
* @card: device structure
*
- * switches off tx irq by masking them out in the GHIINTnMSK register
+ * switches off rx irq by masking them out in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_off(struct spider_net_card *card)
+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_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE & (~SPIDER_NET_RXINT);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
- * spider_net_tx_irq_on - switch on tx irq on this spider card
+ * spider_net_rx_irq_on - switch on rx irq on this spider card
* @card: device structure
*
- * switches on tx irq by enabling them in the GHIINTnMSK register
+ * switches on rx irq by enabling them in the GHIINTnMSK register
*/
static void
-spider_net_tx_irq_on(struct spider_net_card *card)
+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_TXINT;
- spider_net_write_reg_sync(card, SPIDER_NET_GHIINT0MSK, regvalue);
- spin_unlock_irqrestore(&card->intmask_lock, flags);
+ regvalue = SPIDER_NET_INT0_MASK_VALUE | SPIDER_NET_RXINT;
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, regvalue);
}
/**
@@ -326,9 +264,8 @@ 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) */
@@ -349,7 +286,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
{
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;
@@ -357,7 +293,6 @@ spider_net_set_descr_status(struct spider_net_descr *descr,
cmd_status |= ((u32)status)<<SPIDER_NET_DESCR_IND_PROC_SHIFT;
/* and write it back */
descr->dmac_cmd_status = cmd_status;
- wmb();
}
/**
@@ -398,8 +333,9 @@ spider_net_init_chain(struct spider_net_card *card,
{
int i;
struct spider_net_descr *descr;
+ dma_addr_t buf;
- spin_lock_init(&card->chain_lock);
+ atomic_set(&card->rx_chain_refill,0);
descr = start_descr;
memset(descr, 0, sizeof(*descr) * no);
@@ -408,14 +344,14 @@ spider_net_init_chain(struct spider_net_card *card,
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);
+ buf = pci_map_single(card->pdev, descr,
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
- if (descr->bus_addr == DMA_ERROR_CODE)
+ if (buf == DMA_ERROR_CODE)
goto iommu_error;
+ descr->bus_addr = buf;
descr->next = descr + 1;
descr->prev = descr - 1;
@@ -439,7 +375,8 @@ iommu_error:
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);
+ SPIDER_NET_DESCR_SIZE,
+ PCI_DMA_BIDIRECTIONAL);
return -ENOMEM;
}
@@ -459,7 +396,7 @@ spider_net_free_rx_chain_contents(struct spider_net_card *card)
if (descr->skb) {
dev_kfree_skb(descr->skb);
pci_unmap_single(card->pdev, descr->buf_addr,
- SPIDER_NET_MAX_MTU,
+ SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
}
descr = descr->next;
@@ -480,12 +417,13 @@ static int
spider_net_prepare_rx_descr(struct spider_net_card *card,
struct spider_net_descr *descr)
{
+ dma_addr_t buf;
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) &
+ bufsize = (SPIDER_NET_MAX_FRAME + SPIDER_NET_RXBUF_ALIGN - 1) &
(~(SPIDER_NET_RXBUF_ALIGN - 1));
/* and we need to have it 128 byte aligned, therefore we allocate a
@@ -493,10 +431,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
/* 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");
+ if (netif_msg_rx_err(card) && net_ratelimit())
+ pr_err("Not enough memory to allocate rx buffer\n");
return -ENOMEM;
}
descr->buf_size = bufsize;
@@ -510,12 +446,12 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
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) {
+ buf = pci_map_single(card->pdev, descr->skb->data,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ descr->buf_addr = buf;
+ if (buf == DMA_ERROR_CODE) {
dev_kfree_skb_any(descr->skb);
- if (netif_msg_rx_err(card))
+ if (netif_msg_rx_err(card) && net_ratelimit())
pr_err("Could not iommu-map rx buffer\n");
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
} else {
@@ -526,10 +462,10 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
}
/**
- * spider_net_enable_rxctails - sets RX dmac chain tail addresses
+ * spider_net_enable_rxchtails - sets RX dmac chain tail addresses
* @card: card structure
*
- * spider_net_enable_rxctails sets the RX DMAC chain tail adresses in the
+ * spider_net_enable_rxchtails sets the RX DMAC chain tail adresses in the
* chip by writing to the appropriate register. DMA is enabled in
* spider_net_enable_rxdmac.
*/
@@ -551,6 +487,7 @@ spider_net_enable_rxchtails(struct spider_net_card *card)
static void
spider_net_enable_rxdmac(struct spider_net_card *card)
{
+ wmb();
spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
SPIDER_NET_DMA_RX_VALUE);
}
@@ -559,32 +496,28 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
* 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.
+ * refills descriptors in the rx chain: 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);
+ /* one context doing the refill (and a second context seeing that
+ * and omitting it) is ok. If called by NAPI, we'll be called again
+ * as spider_net_decode_one_descr is called several times. If some
+ * interrupt calls us, the NAPI is about to clean up anyway. */
+ if (atomic_inc_return(&card->rx_chain_refill) == 1)
+ while (spider_net_get_descr_status(chain->head) ==
+ SPIDER_NET_DESCR_NOT_IN_USE) {
+ if (spider_net_prepare_rx_descr(card, chain->head))
+ break;
+ chain->head = chain->head->next;
+ }
- /* could be optimized, only do that, if we know the DMA processing
- * has terminated */
- if (count)
- spider_net_enable_rxdmac(card);
+ atomic_dec(&card->rx_chain_refill);
}
/**
@@ -613,6 +546,7 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card)
/* this will allocate the rest of the rx buffers; if not, it's
* business as usual later on */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
return 0;
error:
@@ -649,24 +583,30 @@ spider_net_release_tx_descr(struct spider_net_card *card,
* @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)
+ * returns 0 if the tx ring is empty, otherwise 1.
+ *
+ * spider_net_release_tx_chain releases the tx descriptors that spider has
+ * finished with (if non-brutal) or simply release tx descriptors (if brutal).
+ * If some other context is calling this function, we return 1 so that we're
+ * scheduled again (if we were scheduled) and will not loose initiative.
*/
-static void
+static int
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);
+ if (atomic_inc_return(&card->tx_chain_release) != 1) {
+ atomic_dec(&card->tx_chain_release);
+ return 1;
+ }
- /* 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;
+ if (!brutal)
+ goto out;
/* fallthrough, if we release the descriptors
* brutally (then we don't care about
* SPIDER_NET_DESCR_CARDOWNED) */
@@ -693,25 +633,30 @@ again:
tx_chain->tail = tx_chain->tail->next;
}
out:
+ atomic_dec(&card->tx_chain_release);
+
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;
- }
- }
+ if (status == SPIDER_NET_DESCR_CARDOWNED)
+ return 1;
+ return 0;
+}
+/**
+ * spider_net_cleanup_tx_ring - cleans up the TX ring
+ * @card: card structure
+ *
+ * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
+ * interrupts to cleanup our TX ring) and returns sent packets to the stack
+ * by freeing them
+ */
+static void
+spider_net_cleanup_tx_ring(struct spider_net_card *card)
+{
+ if ( (spider_net_release_tx_chain(card, 0)) &&
+ (card->netdev->flags & IFF_UP) ) {
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
+ }
}
/**
@@ -726,16 +671,22 @@ out:
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;
+ char addr_for_crc[ETH_ALEN] = { 0, };
+ int i, bit;
- crc = crc32_be(~0, addr, netdev->addr_len);
+ for (i = 0; i < ETH_ALEN * 8; i++) {
+ bit = (addr[i / 8] >> (i % 8)) & 1;
+ addr_for_crc[ETH_ALEN - 1 - i / 8] += bit << (7 - (i % 8));
+ }
+
+ crc = crc32_be(~0, addr_for_crc, netdev->addr_len);
hash = (crc >> 27);
hash <<= 3;
hash |= crc & 7;
+ hash &= 0xff;
return hash;
}
@@ -821,9 +772,11 @@ spider_net_stop(struct net_device *netdev)
{
struct spider_net_card *card = netdev_priv(netdev);
+ tasklet_kill(&card->rxram_full_tl);
netif_poll_disable(netdev);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+ del_timer_sync(&card->tx_timer);
/* disable/mask all interrupts */
spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
@@ -872,13 +825,15 @@ spider_net_get_next_tx_descr(struct spider_net_card *card)
* @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.
+ * depending on hardware checksum settings.
*/
static void
spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
struct sk_buff *skb)
{
+ /* make sure the other fields in the descriptor are written */
+ wmb();
+
if (skb->ip_summed != CHECKSUM_HW) {
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_NOCS;
return;
@@ -887,14 +842,13 @@ spider_net_set_txdescr_cmdstat(struct spider_net_descr *descr,
/* is packet ip?
* if yes: tcp? udp? */
if (skb->protocol == htons(ETH_P_IP)) {
- if (skb->nh.iph->protocol == IPPROTO_TCP) {
+ if (skb->nh.iph->protocol == IPPROTO_TCP)
descr->dmac_cmd_status = SPIDER_NET_DMAC_CMDSTAT_TCPCS;
- } else if (skb->nh.iph->protocol == IPPROTO_UDP) {
+ 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 */
+ 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;
- }
}
}
@@ -914,23 +868,22 @@ 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))
+ dma_addr_t buf;
+
+ buf = pci_map_single(card->pdev, skb->data,
+ skb->len, PCI_DMA_BIDIRECTIONAL);
+ if (buf == DMA_ERROR_CODE) {
+ if (netif_msg_tx_err(card) && net_ratelimit())
pr_err("could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
return -ENOMEM;
}
+ descr->buf_addr = buf;
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;
@@ -972,17 +925,12 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
struct spider_net_descr *descr;
int result;
- descr = spider_net_get_next_tx_descr(card);
+ spider_net_release_tx_chain(card, 0);
- if (!descr) {
- netif_stop_queue(netdev);
+ descr = spider_net_get_next_tx_descr(card);
- descr = spider_net_get_next_tx_descr(card);
- if (!descr)
- goto error;
- else
- netif_start_queue(netdev);
- }
+ if (!descr)
+ goto error;
result = spider_net_prepare_tx_descr(card, descr, skb);
if (result)
@@ -990,19 +938,25 @@ spider_net_xmit(struct sk_buff *skb, struct net_device *netdev)
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);
+ SPIDER_NET_DESCR_CARDOWNED) {
+ /* make sure the current descriptor is in memory. Then
+ * kicking it on again makes sense, if the previous is not
+ * card-owned anymore. Check the previous descriptor twice
+ * to omit an mb() in heavy traffic cases */
+ mb();
+ if (spider_net_get_descr_status(descr->prev) !=
+ SPIDER_NET_DESCR_CARDOWNED)
+ spider_net_kick_tx_dma(card, descr);
+ }
+
+ mod_timer(&card->tx_timer, jiffies + SPIDER_NET_TX_TIMER);
return NETDEV_TX_OK;
error:
card->netdev_stats.tx_dropped++;
- return NETDEV_TX_LOCKED;
+ return NETDEV_TX_BUSY;
}
/**
@@ -1027,6 +981,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
* spider_net_pass_skb_up - takes an skb from a descriptor and passes it on
* @descr: descriptor to process
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* returns 1 on success, 0 if no packet was passed to the stack
*
@@ -1035,7 +990,7 @@ spider_net_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
*/
static int
spider_net_pass_skb_up(struct spider_net_descr *descr,
- struct spider_net_card *card)
+ struct spider_net_card *card, int napi)
{
struct sk_buff *skb;
struct net_device *netdev;
@@ -1046,22 +1001,20 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
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,
+ /* unmap descriptor */
+ pci_unmap_single(card->pdev, descr->buf_addr, SPIDER_NET_MAX_FRAME,
PCI_DMA_BIDIRECTIONAL);
/* the cases we'll throw away the packet immediately */
- if (data_error & SPIDER_NET_DESTROY_RX_FLAGS)
+ if (data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
+ if (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);
return 0;
+ }
+ skb = descr->skb;
skb->dev = netdev;
skb_put(skb, descr->valid_size);
@@ -1073,14 +1026,14 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
/* checksum offload */
if (card->options.rx_csum) {
- if ( (data_status & SPIDER_NET_DATA_STATUS_CHK_MASK) &&
- (!(data_error & SPIDER_NET_DATA_ERROR_CHK_MASK)) )
+ if ( ( (data_status & SPIDER_NET_DATA_STATUS_CKSUM_MASK) ==
+ SPIDER_NET_DATA_STATUS_CKSUM_MASK) &&
+ !(data_error & SPIDER_NET_DATA_ERR_CKSUM_MASK))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
- } else {
+ } else
skb->ip_summed = CHECKSUM_NONE;
- }
if (data_status & SPIDER_NET_VLAN_PACKET) {
/* further enhancements: HW-accel VLAN
@@ -1089,7 +1042,10 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/* pass skb up to stack */
- netif_receive_skb(skb);
+ if (napi)
+ netif_receive_skb(skb);
+ else
+ netif_rx_ni(skb);
/* update netdevice statistics */
card->netdev_stats.rx_packets++;
@@ -1099,16 +1055,18 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
}
/**
- * spider_net_decode_descr - processes an rx descriptor
+ * spider_net_decode_one_descr - processes an rx descriptor
* @card: card structure
+ * @napi: whether caller is in NAPI context
*
* 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
+ * the packet up to the stack. This function is called in softirq
+ * context, e.g. either bottom half from interrupt or NAPI polling context
*/
static int
-spider_net_decode_one_descr(struct spider_net_card *card)
+spider_net_decode_one_descr(struct spider_net_card *card, int napi)
{
enum spider_net_descr_status status;
struct spider_net_descr *descr;
@@ -1122,17 +1080,19 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if (status == SPIDER_NET_DESCR_CARDOWNED) {
/* nothing in the descriptor yet */
- return 0;
+ result=0;
+ goto out;
}
if (status == SPIDER_NET_DESCR_NOT_IN_USE) {
- /* not initialized yet, I bet chain->tail == chain->head
- * and the ring is empty */
+ /* not initialized yet, the ring must be empty */
spider_net_refill_rx_chain(card);
- return 0;
+ spider_net_enable_rxdmac(card);
+ result=0;
+ goto out;
}
- /* descriptor definitively used -- move on head */
+ /* descriptor definitively used -- move on tail */
chain->tail = descr->next;
result = 0;
@@ -1143,6 +1103,9 @@ spider_net_decode_one_descr(struct spider_net_card *card)
pr_err("%s: dropping RX descriptor with state %d\n",
card->netdev->name, status);
card->netdev_stats.rx_dropped++;
+ pci_unmap_single(card->pdev, descr->buf_addr,
+ SPIDER_NET_MAX_FRAME, PCI_DMA_BIDIRECTIONAL);
+ dev_kfree_skb_irq(descr->skb);
goto refill;
}
@@ -1155,12 +1118,13 @@ spider_net_decode_one_descr(struct spider_net_card *card)
}
/* ok, we've got a packet in descr */
- result = spider_net_pass_skb_up(descr, card);
+ result = spider_net_pass_skb_up(descr, card, napi);
refill:
spider_net_set_descr_status(descr, SPIDER_NET_DESCR_NOT_IN_USE);
/* change the descriptor state: */
- spider_net_refill_rx_chain(card);
-
+ if (!napi)
+ spider_net_refill_rx_chain(card);
+out:
return result;
}
@@ -1186,7 +1150,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
- if (spider_net_decode_one_descr(card)) {
+ if (spider_net_decode_one_descr(card, 1)) {
packets_done++;
packets_to_do--;
} else {
@@ -1198,6 +1162,7 @@ spider_net_poll(struct net_device *netdev, int *budget)
netdev->quota -= packets_done;
*budget -= packets_done;
+ spider_net_refill_rx_chain(card);
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
@@ -1342,6 +1307,24 @@ spider_net_enable_txdmac(struct spider_net_card *card)
}
/**
+ * spider_net_handle_rxram_full - cleans up RX ring upon RX RAM full interrupt
+ * @card: card structure
+ *
+ * spider_net_handle_rxram_full empties the RX ring so that spider can put
+ * more packets in it and empty its RX RAM. This is called in bottom half
+ * context
+ */
+static void
+spider_net_handle_rxram_full(struct spider_net_card *card)
+{
+ while (spider_net_decode_one_descr(card, 0))
+ ;
+ spider_net_enable_rxchtails(card);
+ spider_net_enable_rxdmac(card);
+ netif_rx_schedule(card->netdev);
+}
+
+/**
* spider_net_handle_error_irq - handles errors raised by an interrupt
* @card: card structure
* @status_reg: interrupt status register 0 (GHIINT0STS)
@@ -1449,17 +1432,21 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
switch (i)
{
case SPIDER_NET_GTMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
pr_err("Spider TX RAM full\n");
show_error = 0;
break;
+ case SPIDER_NET_GRFDFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFCFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFBFLLINT: /* fallthrough */
+ case SPIDER_NET_GRFAFLLINT: /* fallthrough */
case SPIDER_NET_GRMFLLINT:
- if (netif_msg_intr(card))
+ if (netif_msg_intr(card) && net_ratelimit())
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);
+ "might be discarded!\n");
+ spider_net_rx_irq_off(card);
+ tasklet_schedule(&card->rxram_full_tl);
+ show_error = 0;
break;
/* case SPIDER_NET_GTMSHTINT: problem, print a message */
@@ -1467,10 +1454,6 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
/* 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 */
@@ -1482,6 +1465,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
"restarting DMAC %c.\n",
'D'+i-SPIDER_NET_GDDDCEINT);
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1492,6 +1476,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDAINVDINT:
/* could happen when rx chain is full */
spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
show_error = 0;
break;
@@ -1580,17 +1565,13 @@ spider_net_interrupt(int irq, void *ptr, struct pt_regs *regs)
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);
+ if (status_reg & SPIDER_NET_ERRINT )
+ spider_net_handle_error_irq(card, status_reg);
/* clear interrupt sources */
spider_net_write_reg(card, SPIDER_NET_GHIINT0STS, status_reg);
@@ -1831,34 +1812,40 @@ spider_net_setup_phy(struct spider_net_card *card)
/**
* spider_net_download_firmware - loads firmware into the adapter
* @card: card structure
- * @firmware: firmware pointer
+ * @firmware_ptr: pointer to firmware data
*
- * spider_net_download_firmware loads the firmware opened by
- * spider_net_init_firmware into the adapter.
+ * spider_net_download_firmware loads the firmware data into the
+ * adapter. It assumes the length etc. to be allright.
*/
-static void
+static int
spider_net_download_firmware(struct spider_net_card *card,
- const struct firmware *firmware)
+ u8 *firmware_ptr)
{
int sequencer, i;
- u32 *fw_ptr = (u32 *)firmware->data;
+ u32 *fw_ptr = (u32 *)firmware_ptr;
/* stop sequencers */
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_STOP_SEQ_VALUE);
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card,
SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, *fw_ptr);
fw_ptr++;
}
}
+ if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
+ return -EIO;
+
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_RUN_SEQ_VALUE);
+
+ return 0;
}
/**
@@ -1890,31 +1877,53 @@ spider_net_download_firmware(struct spider_net_card *card,
static int
spider_net_init_firmware(struct spider_net_card *card)
{
- const struct firmware *firmware;
- int err = -EIO;
+ struct firmware *firmware = NULL;
+ struct device_node *dn;
+ u8 *fw_prop = NULL;
+ int err = -ENOENT;
+ int fw_size;
+
+ if (request_firmware((const struct firmware **)&firmware,
+ SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
+ if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "filesystem. Looking in host firmware...\n");
+ goto try_host_fw;
+ }
+ err = spider_net_download_firmware(card, firmware->data);
- 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;
- }
+ release_firmware(firmware);
+ if (err)
+ goto try_host_fw;
- 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;
+ goto done;
}
- spider_net_download_firmware(card, firmware);
+try_host_fw:
+ dn = pci_device_to_OF_node(card->pdev);
+ if (!dn)
+ goto out_err;
- err = 0;
-out:
- release_firmware(firmware);
+ fw_prop = (u8 *)get_property(dn, "firmware", &fw_size);
+ if (!fw_prop)
+ goto out_err;
+
+ if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
+ netif_msg_probe(card) ) {
+ pr_err("Incorrect size of spidernet firmware in " \
+ "host firmware\n");
+ goto done;
+ }
+ err = spider_net_download_firmware(card, fw_prop);
+
+done:
+ return err;
+out_err:
+ if (netif_msg_probe(card))
+ pr_err("Couldn't find spidernet firmware in filesystem " \
+ "or host firmware\n");
return err;
}
@@ -1934,10 +1943,11 @@ spider_net_workaround_rxramfull(struct spider_net_card *card)
SPIDER_NET_CKRCTRL_RUN_VALUE);
/* empty sequencer data */
- for (sequencer = 0; sequencer < 6; sequencer++) {
+ for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
+ sequencer++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
- for (i = 0; i < SPIDER_NET_FIRMWARE_LEN; i++) {
+ for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, 0x0);
}
@@ -2061,7 +2071,15 @@ spider_net_setup_netdev(struct spider_net_card *card)
SET_NETDEV_DEV(netdev, &card->pdev->dev);
pci_set_drvdata(card->pdev, netdev);
- spin_lock_init(&card->intmask_lock);
+
+ atomic_set(&card->tx_chain_release,0);
+ card->rxram_full_tl.data = (unsigned long) card;
+ card->rxram_full_tl.func =
+ (void (*)(unsigned long)) spider_net_handle_rxram_full;
+ init_timer(&card->tx_timer);
+ card->tx_timer.function =
+ (void (*)(unsigned long)) spider_net_cleanup_tx_ring;
+ card->tx_timer.data = (unsigned long) card;
netdev->irq = card->pdev->irq;
card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 22b2f2347351..5922b529a048 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -33,25 +33,32 @@ extern struct ethtool_ops spider_net_ethtool_ops;
extern char spider_net_driver_name[];
-#define SPIDER_NET_MAX_MTU 2308
+#define SPIDER_NET_MAX_FRAME 2312
+#define SPIDER_NET_MAX_MTU 2294
#define SPIDER_NET_MIN_MTU 64
#define SPIDER_NET_RXBUF_ALIGN 128
-#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_RX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_RX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_RX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_RX_DESCRIPTORS_MAX 512
-#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 64
+#define SPIDER_NET_TX_DESCRIPTORS_DEFAULT 256
#define SPIDER_NET_TX_DESCRIPTORS_MIN 16
-#define SPIDER_NET_TX_DESCRIPTORS_MAX 256
+#define SPIDER_NET_TX_DESCRIPTORS_MAX 512
+
+#define SPIDER_NET_TX_TIMER 20
#define SPIDER_NET_RX_CSUM_DEFAULT 1
-#define SPIDER_NET_WATCHDOG_TIMEOUT 5*HZ
-#define SPIDER_NET_NAPI_WEIGHT 64
+#define SPIDER_NET_WATCHDOG_TIMEOUT 50*HZ
+#define SPIDER_NET_NAPI_WEIGHT 64
-#define SPIDER_NET_FIRMWARE_LEN 1024
+#define SPIDER_NET_FIRMWARE_SEQS 6
+#define SPIDER_NET_FIRMWARE_SEQWORDS 1024
+#define SPIDER_NET_FIRMWARE_LEN (SPIDER_NET_FIRMWARE_SEQS * \
+ SPIDER_NET_FIRMWARE_SEQWORDS * \
+ sizeof(u32))
#define SPIDER_NET_FIRMWARE_NAME "spider_fw.bin"
/** spider_net SMMIO registers */
@@ -142,14 +149,12 @@ extern char spider_net_driver_name[];
/** 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
+/** interrupt mask registers */
+#define SPIDER_NET_INT0_MASK_VALUE 0x3f7fe2c7
+#define SPIDER_NET_INT1_MASK_VALUE 0xffff7ff7
/* no MAC aborts -> auto retransmission */
-#define SPIDER_NET_INT2_MASK_VALUE 0xfffffff1
+#define SPIDER_NET_INT2_MASK_VALUE 0xffef7ff1
-/* 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 */
@@ -168,7 +173,7 @@ extern char spider_net_driver_name[];
#if 0
#define SPIDER_NET_WOL_VALUE 0x00000000
#endif
-#define SPIDER_NET_IPSECINIT_VALUE 0x00f000f8
+#define SPIDER_NET_IPSECINIT_VALUE 0x6f716f71
/* pause frames: automatic, no upper retransmission count */
/* outside loopback mode: ETOMOD signal dont matter, not connected */
@@ -318,6 +323,10 @@ enum spider_net_int2_status {
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) | \
(1 << SPIDER_NET_GRMFLLINT) )
+#define SPIDER_NET_ERRINT ( 0xffffffff & \
+ (~SPIDER_NET_TXINT) & \
+ (~SPIDER_NET_RXINT) )
+
#define SPIDER_NET_GPREXEC 0x80000000
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
@@ -358,9 +367,6 @@ enum spider_net_int2_status {
/* 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 */
@@ -373,9 +379,9 @@ enum spider_net_descr_status {
struct spider_net_descr {
/* as defined by the hardware */
- dma_addr_t buf_addr;
+ u32 buf_addr;
u32 buf_size;
- dma_addr_t next_descr_addr;
+ u32 next_descr_addr;
u32 dmac_cmd_status;
u32 result_size;
u32 valid_size; /* all zeroes for tx */
@@ -384,7 +390,7 @@ struct spider_net_descr {
/* used in the driver */
struct sk_buff *skb;
- dma_addr_t bus_addr;
+ u32 bus_addr;
struct spider_net_descr *next;
struct spider_net_descr *prev;
} __attribute__((aligned(32)));
@@ -396,21 +402,21 @@ struct spider_net_descr_chain {
};
/* 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_RX_IPCHK 29
+#define SPIDER_NET_RX_TCPCHK 28
#define SPIDER_NET_VLAN_PACKET 21
+#define SPIDER_NET_DATA_STATUS_CKSUM_MASK ( (1 << SPIDER_NET_RX_IPCHK) | \
+ (1 << SPIDER_NET_RX_TCPCHK) )
/* 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)
+#define SPIDER_NET_RX_IPCHKERR 27
+#define SPIDER_NET_RX_RXTCPCHKERR 28
+
+#define SPIDER_NET_DATA_ERR_CKSUM_MASK (1 << SPIDER_NET_RX_IPCHKERR)
-/* the cases we don't pass the packet to the stack */
-#define SPIDER_NET_DESTROY_RX_FLAGS 0x70138000
+/* the cases we don't pass the packet to the stack.
+ * 701b8000 would be correct, but every packets gets that flag */
+#define SPIDER_NET_DESTROY_RX_FLAGS 0x700b8000
#define SPIDER_NET_DESCR_SIZE 32
@@ -445,13 +451,16 @@ struct spider_net_card {
struct spider_net_descr_chain tx_chain;
struct spider_net_descr_chain rx_chain;
- spinlock_t chain_lock;
+ atomic_t rx_chain_refill;
+ atomic_t tx_chain_release;
struct net_device_stats netdev_stats;
struct spider_net_options options;
spinlock_t intmask_lock;
+ struct tasklet_struct rxram_full_tl;
+ struct timer_list tx_timer;
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index d42e60ba74ce..a5bb0b7633af 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -113,6 +113,23 @@ spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
return 0;
}
+static uint32_t
+spider_net_ethtool_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+ if (data)
+ netdev->features |= NETIF_F_HW_CSUM;
+ else
+ netdev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
+
struct ethtool_ops spider_net_ethtool_ops = {
.get_settings = spider_net_ethtool_get_settings,
.get_drvinfo = spider_net_ethtool_get_drvinfo,
@@ -122,5 +139,7 @@ struct ethtool_ops spider_net_ethtool_ops = {
.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,
+ .get_tx_csum = spider_net_ethtool_get_tx_csum,
+ .set_tx_csum = spider_net_ethtool_set_tx_csum,
};
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 5c8fcd40ef4d..01bdb2334058 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -389,7 +389,7 @@ static int __init lance_probe( struct net_device *dev)
dev->stop = &lance_close;
dev->get_stats = &lance_get_stats;
dev->set_multicast_list = &set_multicast_list;
- dev->set_mac_address = 0;
+ dev->set_mac_address = NULL;
// KLUDGE -- REMOVE ME
set_bit(__LINK_STATE_PRESENT, &dev->state);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2fc9893d69e1..f2d1dafde087 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -24,6 +24,7 @@
#include <linux/compiler.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/pci.h>
@@ -68,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.47"
-#define DRV_MODULE_RELDATE "Dec 28, 2005"
+#define DRV_MODULE_VERSION "3.48"
+#define DRV_MODULE_RELDATE "Jan 16, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -1324,10 +1325,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
tw32(0x7d00, val);
if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
- tg3_nvram_lock(tp);
+ int err;
+
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
}
}
@@ -3650,7 +3653,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
TXD_FLAG_CPU_POST_DMA);
skb->nh.iph->check = 0;
- skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
+ skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
skb->h.th->check = 0;
base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
@@ -4192,14 +4195,19 @@ static int tg3_nvram_lock(struct tg3 *tp)
if (tp->tg3_flags & TG3_FLAG_NVRAM) {
int i;
- tw32(NVRAM_SWARB, SWARB_REQ_SET1);
- for (i = 0; i < 8000; i++) {
- if (tr32(NVRAM_SWARB) & SWARB_GNT1)
- break;
- udelay(20);
+ if (tp->nvram_lock_cnt == 0) {
+ tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+ for (i = 0; i < 8000; i++) {
+ if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+ break;
+ udelay(20);
+ }
+ if (i == 8000) {
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
+ return -ENODEV;
+ }
}
- if (i == 8000)
- return -ENODEV;
+ tp->nvram_lock_cnt++;
}
return 0;
}
@@ -4207,8 +4215,12 @@ static int tg3_nvram_lock(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_nvram_unlock(struct tg3 *tp)
{
- if (tp->tg3_flags & TG3_FLAG_NVRAM)
- tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ if (tp->tg3_flags & TG3_FLAG_NVRAM) {
+ if (tp->nvram_lock_cnt > 0)
+ tp->nvram_lock_cnt--;
+ if (tp->nvram_lock_cnt == 0)
+ tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+ }
}
/* tp->lock is held. */
@@ -4319,8 +4331,13 @@ static int tg3_chip_reset(struct tg3 *tp)
void (*write_op)(struct tg3 *, u32, u32);
int i;
- if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
+ if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
tg3_nvram_lock(tp);
+ /* No matching tg3_nvram_unlock() after this because
+ * chip reset below will undo the nvram lock.
+ */
+ tp->nvram_lock_cnt = 0;
+ }
/*
* We must avoid the readl() that normally takes place.
@@ -4716,6 +4733,10 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
(offset == RX_CPU_BASE ? "RX" : "TX"));
return -ENODEV;
}
+
+ /* Clear firmware's nvram arbitration. */
+ if (tp->tg3_flags & TG3_FLAG_NVRAM)
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
return 0;
}
@@ -4735,7 +4756,7 @@ struct fw_info {
static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base,
int cpu_scratch_size, struct fw_info *info)
{
- int err, i;
+ int err, lock_err, i;
void (*write_op)(struct tg3 *, u32, u32);
if (cpu_base == TX_CPU_BASE &&
@@ -4754,9 +4775,10 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
/* It is possible that bootcode is still loading at this point.
* Get the nvram lock first before halting the cpu.
*/
- tg3_nvram_lock(tp);
+ lock_err = tg3_nvram_lock(tp);
err = tg3_halt_cpu(tp, cpu_base);
- tg3_nvram_unlock(tp);
+ if (!lock_err)
+ tg3_nvram_unlock(tp);
if (err)
goto out;
@@ -8181,7 +8203,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
data[1] = 1;
}
if (etest->flags & ETH_TEST_FL_OFFLINE) {
- int irq_sync = 0;
+ int err, irq_sync = 0;
if (netif_running(dev)) {
tg3_netif_stop(tp);
@@ -8191,11 +8213,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
tg3_full_lock(tp, irq_sync);
tg3_halt(tp, RESET_KIND_SUSPEND, 1);
- tg3_nvram_lock(tp);
+ err = tg3_nvram_lock(tp);
tg3_halt_cpu(tp, RX_CPU_BASE);
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
tg3_halt_cpu(tp, TX_CPU_BASE);
- tg3_nvram_unlock(tp);
+ if (!err)
+ tg3_nvram_unlock(tp);
if (tg3_test_registers(tp) != 0) {
etest->flags |= ETH_TEST_FL_FAILED;
@@ -8587,7 +8610,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
tp->tg3_flags |= TG3_FLAG_NVRAM;
- tg3_nvram_lock(tp);
+ if (tg3_nvram_lock(tp)) {
+ printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, "
+ "tg3_nvram_init failed.\n", tp->dev->name);
+ return;
+ }
tg3_enable_nvram_access(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
@@ -8685,7 +8712,9 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
if (offset > NVRAM_ADDR_MSK)
return -EINVAL;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
@@ -8784,10 +8813,6 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
offset = offset + (pagesize - page_off);
- /* Nvram lock released by tg3_nvram_read() above,
- * so need to get it again.
- */
- tg3_nvram_lock(tp);
tg3_enable_nvram_access(tp);
/*
@@ -8924,7 +8949,9 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
else {
u32 grc_mode;
- tg3_nvram_lock(tp);
+ ret = tg3_nvram_lock(tp);
+ if (ret)
+ return ret;
tg3_enable_nvram_access(tp);
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 890e1635996b..e8243305f0e8 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2275,6 +2275,7 @@ struct tg3 {
dma_addr_t stats_mapping;
struct work_struct reset_task;
+ int nvram_lock_cnt;
u32 nvram_size;
u32 nvram_pagesize;
u32 nvram_jedecnum;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 942fae0f2130..c2506b56a186 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -2865,11 +2865,11 @@ void TLan_PhyMonitor( struct net_device *dev )
* for this device.
* phy The address of the PHY to be queried.
* reg The register whose contents are to be
- * retreived.
+ * retrieved.
* val A pointer to a variable to store the
* retrieved value.
*
- * This function uses the TLAN's MII bus to retreive the contents
+ * This function uses the TLAN's MII bus to retrieve the contents
* of a given register on a PHY. It sends the appropriate info
* and then reads the 16-bit register value from the MII bus via
* the TLAN SIO register.
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 125ed00e95a5..c67c91251d04 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1564,7 +1564,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
dev->dev_addr, 6);
}
#endif
-#if defined(__i386__) /* Patch up x86 BIOS bug. */
+#if defined(__i386__) || defined(__x86_64__) /* Patch up x86 BIOS bug. */
if (last_irq)
irq = last_irq;
#endif
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 1a4316336256..983981666800 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -1689,9 +1689,9 @@ 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_param(debug, int, 0644);
+module_param(mode, int, 0);
+module_param(cr6set, int, 0);
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");
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 82c6b757d306..c2d5907dc8e0 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -791,7 +791,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
#endif
if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) {
- dev->features |= NETIF_F_HW_CSUM;
+ dev->features |= NETIF_F_IP_CSUM;
}
ret = register_netdev(dev);
diff --git a/drivers/net/wan/.gitignore b/drivers/net/wan/.gitignore
new file mode 100644
index 000000000000..dae3ea6bb18c
--- /dev/null
+++ b/drivers/net/wan/.gitignore
@@ -0,0 +1 @@
+wanxlfw.inc
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 2b948ea397d5..40926d779161 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -641,7 +641,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
spin_lock_irqsave(&sc->lmc_lock, flags);
if(sc->check != 0xBEAFCAFE){
- printk("LMC: Corrupt net_device stuct, breaking out\n");
+ printk("LMC: Corrupt net_device struct, breaking out\n");
spin_unlock_irqrestore(&sc->lmc_lock, flags);
return;
}
diff --git a/drivers/net/wan/lmc/lmc_prot.h b/drivers/net/wan/lmc/lmc_prot.h
deleted file mode 100644
index f3b1df9e2cdb..000000000000
--- a/drivers/net/wan/lmc/lmc_prot.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _LMC_PROTO_H_
-#define _LMC_PROTO_H_
-
-void lmc_proto_init(lmc_softc_t * const)
-void lmc_proto_attach(lmc_softc_t *sc const)
-void lmc_proto_detach(lmc_softc *sc const)
-void lmc_proto_reopen(lmc_softc_t *sc const)
-int lmc_proto_ioctl(lmc_softc_t *sc const, struct ifreq *ifr, int cmd)
-void lmc_proto_open(lmc_softc_t *sc const)
-void lmc_proto_close(lmc_softc_t *sc const)
-unsigned short lmc_proto_type(lmc_softc_t *sc const, struct skbuff *skb)
-
-
-#endif
-
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 52f26b9c69d2..931cbdf6d791 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -689,7 +689,7 @@ static void cpc_tty_rx_work(void * data)
}
}
cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
- kfree(buf);
+ kfree((void *)buf);
buf = cpc_tty->buf_rx.first;
flg_rx = 1;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 036adc4f8ba7..22e794071cf4 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -329,9 +329,9 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr)
struct _dlci_stat
{
- short dlci __attribute__((packed));
- char flags __attribute__((packed));
-};
+ short dlci;
+ char flags;
+} __attribute__((packed));
struct _frad_stat
{
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index bdf672c48182..9c3ccc669143 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -515,11 +515,6 @@ static int x25_asy_close(struct net_device *dev)
return 0;
}
-static int x25_asy_receive_room(struct tty_struct *tty)
-{
- return 65536; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* Handle the 'receiver data ready' interrupt.
* This function is called by the 'tty_io' module in the kernel when
@@ -573,6 +568,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
sl->tty = tty;
tty->disc_data = sl;
+ tty->receive_room = 65536;
if (tty->driver->flush_buffer) {
tty->driver->flush_buffer(tty);
}
@@ -779,7 +775,6 @@ static struct tty_ldisc x25_ldisc = {
.close = x25_asy_close_tty,
.ioctl = x25_asy_ioctl,
.receive_buf = x25_asy_receive_buf,
- .receive_room = x25_asy_receive_room,
.write_wakeup = x25_asy_write_wakeup,
};
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index b03feae459fc..7caa8dc88a58 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -127,13 +127,6 @@ static int __init do_wd_probe(struct net_device *dev)
return -ENODEV;
}
-static void cleanup_card(struct net_device *dev)
-{
- free_irq(dev->irq, dev);
- release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
- iounmap(ei_status.mem);
-}
-
#ifndef MODULE
struct net_device * __init wd_probe(int unit)
{
@@ -538,6 +531,13 @@ init_module(void)
return -ENXIO;
}
+static void cleanup_card(struct net_device *dev)
+{
+ free_irq(dev->irq, dev);
+ release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
+ iounmap(ei_status.mem);
+}
+
void
cleanup_module(void)
{
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 00e55165b760..233a4f608084 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -24,10 +24,6 @@ config NET_RADIO
the tools from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
- Some user-level drivers for scarab devices which don't require
- special kernel support are available from
- <ftp://shadow.cabi.net/pub/Linux/>.
-
# Note : the cards are obsolete (can't buy them anymore), but the drivers
# are not, as people are still using them...
comment "Obsolete Wireless cards support (pre-802.11)"
@@ -160,7 +156,7 @@ config IPW2100
<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),
+ inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/modules.txt>. The module
will be called ipw2100.ko.
@@ -173,7 +169,7 @@ config IPW2100_MONITOR
promiscuous mode via the Wireless Tool's Monitor mode. While in this
mode, no packets can be sent.
-config IPW_DEBUG
+config IPW2100_DEBUG
bool "Enable full debugging output in IPW2100 module."
depends on IPW2100
---help---
@@ -192,7 +188,7 @@ config IPW_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
- depends on IEEE80211 && PCI
+ depends on NET_RADIO && IEEE80211 && PCI
select FW_LOADER
---help---
A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
@@ -213,11 +209,11 @@ config IPW2200
<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),
+ inserted in and removed 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
+config IPW2200_DEBUG
bool "Enable full debugging output in IPW2200 module."
depends on IPW2200
---help---
@@ -243,7 +239,7 @@ config IPW_DEBUG
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
- depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
+ depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN)
---help---
This is the standard Linux driver to support Cisco/Aironet ISA and
PCI 802.11 wireless cards.
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7a92b1cbd6aa..a4c7ae94614d 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4037,7 +4037,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
Cmd cmd;
Resp rsp;
- if (test_bit(FLAG_ENABLED, &ai->flags))
+ if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
printk(KERN_ERR
"%s: MAC should be disabled (rid=%04x)\n",
__FUNCTION__, rid);
@@ -5093,9 +5093,9 @@ static int set_wep_key(struct airo_info *ai, u16 index,
printk(KERN_INFO "Setting key %d\n", index);
}
- disable_MAC(ai, lock);
+ if (perm) disable_MAC(ai, lock);
writeWepKeyRid(ai, &wkr, perm, lock);
- enable_MAC(ai, &rsp, lock);
+ if (perm) enable_MAC(ai, &rsp, lock);
return 0;
}
@@ -5668,13 +5668,13 @@ static int airo_set_freq(struct net_device *dev,
int channel = fwrq->m;
/* We should do a better check than that,
* based on the card capability !!! */
- if((channel < 1) || (channel > 16)) {
+ if((channel < 1) || (channel > 14)) {
printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
rc = -EINVAL;
} else {
readConfigRid(local, 1);
/* Yes ! We can set it !!! */
- local->config.channelSet = (u16)(channel - 1);
+ local->config.channelSet = (u16) channel;
set_bit (FLAG_COMMIT, &local->flags);
}
}
@@ -5692,6 +5692,7 @@ static int airo_get_freq(struct net_device *dev,
{
struct airo_info *local = dev->priv;
StatusRid status_rid; /* Card status info */
+ int ch;
readConfigRid(local, 1);
if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
@@ -5699,16 +5700,14 @@ static int airo_get_freq(struct net_device *dev,
else
readStatusRid(local, &status_rid, 1);
-#ifdef WEXT_USECHANNELS
- fwrq->m = ((int)status_rid.channel) + 1;
- fwrq->e = 0;
-#else
- {
- int f = (int)status_rid.channel;
- fwrq->m = frequency_list[f] * 100000;
+ ch = (int)status_rid.channel;
+ if((ch > 0) && (ch < 15)) {
+ fwrq->m = frequency_list[ch - 1] * 100000;
fwrq->e = 1;
+ } else {
+ fwrq->m = ch;
+ fwrq->e = 0;
}
-#endif
return 0;
}
@@ -5783,7 +5782,7 @@ static int airo_get_essid(struct net_device *dev,
/* If none, we may want to get the one that was set */
/* Push it out ! */
- dwrq->length = status_rid.SSIDlen + 1;
+ dwrq->length = status_rid.SSIDlen;
dwrq->flags = 1; /* active */
return 0;
@@ -6170,6 +6169,8 @@ static int airo_set_encode(struct net_device *dev,
{
struct airo_info *local = dev->priv;
CapabilityRid cap_rid; /* Card capability info */
+ int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+ u16 currentAuthType = local->config.authType;
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
@@ -6212,7 +6213,7 @@ static int airo_set_encode(struct net_device *dev,
/* Copy the key in the driver */
memcpy(key.key, extra, dwrq->length);
/* Send the key to the card */
- set_wep_key(local, index, key.key, key.len, 1, 1);
+ set_wep_key(local, index, key.key, key.len, perm, 1);
}
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
@@ -6220,13 +6221,12 @@ static int airo_set_encode(struct net_device *dev,
if((index == current_index) && (key.len > 0) &&
(local->config.authType == AUTH_OPEN)) {
local->config.authType = AUTH_ENCRYPT;
- set_bit (FLAG_COMMIT, &local->flags);
}
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
- set_wep_key(local, index, NULL, 0, 1, 1);
+ set_wep_key(local, index, NULL, 0, perm, 1);
} else
/* Don't complain if only change the mode */
if(!dwrq->flags & IW_ENCODE_MODE) {
@@ -6241,7 +6241,7 @@ static int airo_set_encode(struct net_device *dev,
if(dwrq->flags & IW_ENCODE_OPEN)
local->config.authType = AUTH_ENCRYPT; // Only Wep
/* Commit the changes to flags if needed */
- if(dwrq->flags & IW_ENCODE_MODE)
+ if (local->config.authType != currentAuthType)
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
}
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index e328547599dc..a496460ce224 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -82,8 +82,6 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
static void airo_config(dev_link_t *link);
static void airo_release(dev_link_t *link);
-static int airo_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -91,8 +89,7 @@ static int airo_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *airo_attach(void);
-static void airo_detach(dev_link_t *);
+static void airo_detach(struct pcmcia_device *p_dev);
/*
You'll also need to prototype all the functions that will actually
@@ -102,14 +99,6 @@ static void airo_detach(dev_link_t *);
*/
/*
- 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 = "airo_cs";
-
-/*
A linked list of "instances" of the aironet device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
@@ -119,15 +108,7 @@ static dev_info_t dev_info = "airo_cs";
device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list = NULL;
-
/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -160,20 +141,18 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *airo_attach(void)
+static int airo_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
-
+
DEBUG(0, "airo_attach()\n");
/* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) {
printk(KERN_ERR "airo_cs: no memory for new device\n");
- return NULL;
+ return -ENOMEM;
}
/* Interrupt setup */
@@ -197,24 +176,17 @@ static dev_link_t *airo_attach(void)
if (!local) {
printk(KERN_ERR "airo_cs: no memory for new device\n");
kfree (link);
- return NULL;
+ return -ENOMEM;
}
link->priv = local;
-
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- airo_detach(link);
- return NULL;
- }
-
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ airo_config(link);
+
+ return 0;
} /* airo_attach */
/*======================================================================
@@ -226,37 +198,22 @@ static dev_link_t *airo_attach(void)
======================================================================*/
-static void airo_detach(dev_link_t *link)
+static void airo_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
-
+ dev_link_t *link = dev_to_instance(p_dev);
+
DEBUG(0, "airo_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
-
+
if (link->state & DEV_CONFIG)
airo_release(link);
-
+
if ( ((local_info_t*)link->priv)->eth_dev ) {
stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
}
- ((local_info_t*)link->priv)->eth_dev = NULL;
-
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
-
-
- /* Unlink device structure, free pieces */
- *linkp = link->next;
+ ((local_info_t*)link->priv)->eth_dev = NULL;
+
kfree(link->priv);
kfree(link);
-
} /* airo_detach */
/*======================================================================
@@ -492,60 +449,34 @@ static void airo_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received.
+static int airo_suspend(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ local_info_t *local = link->priv;
- When a CARD_REMOVAL event is received, we immediately set a
- private flag to block future accesses to this device. All the
- functions that actually access the device should check this flag
- to make sure the card is still present.
-
- ======================================================================*/
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(local->eth_dev);
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
-static int airo_event(event_t event, int priority,
- event_callback_args_t *args)
+static int airo_resume(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
-
- DEBUG(1, "airo_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- airo_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- airo_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- 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) {
- pcmcia_request_configuration(link->handle, &link->conf);
- reset_airo_card(local->eth_dev);
- netif_device_attach(local->eth_dev);
- }
- break;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ reset_airo_card(local->eth_dev);
+ netif_device_attach(local->eth_dev);
}
+
return 0;
-} /* airo_event */
+}
static struct pcmcia_device_id airo_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
@@ -561,10 +492,11 @@ static struct pcmcia_driver airo_driver = {
.drv = {
.name = "airo_cs",
},
- .attach = airo_attach,
- .event = airo_event,
- .detach = airo_detach,
+ .probe = airo_attach,
+ .remove = airo_detach,
.id_table = airo_ids,
+ .suspend = airo_suspend,
+ .resume = airo_resume,
};
static int airo_cs_init(void)
@@ -575,7 +507,6 @@ static int airo_cs_init(void)
static void airo_cs_cleanup(void)
{
pcmcia_unregister_driver(&airo_driver);
- BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 5e53c5258a33..98a76f10a0f7 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -5,9 +5,9 @@
Copyright 2000-2001 ATMEL Corporation.
Copyright 2003-2004 Simon Kelley.
- This code was developed from version 2.1.1 of the Atmel drivers,
- released by Atmel corp. under the GPL in December 2002. It also
- includes code from the Linux aironet drivers (C) Benjamin Reed,
+ This code was developed from version 2.1.1 of the Atmel drivers,
+ released by Atmel corp. under the GPL in December 2002. It also
+ includes code from the Linux aironet drivers (C) Benjamin Reed,
and the Linux PCMCIA package, (C) David Hinds and the Linux wireless
extensions, (C) Jean Tourrilhes.
@@ -31,7 +31,7 @@
along with Atmel wireless lan drivers; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- For all queries about this code, please contact the current author,
+ For all queries about this code, please contact the current author,
Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
Credit is due to HP UK and Cambridge Online Systems Ltd for supplying
@@ -79,13 +79,13 @@ MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.")
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards");
-/* The name of the firmware file to be loaded
+/* The name of the firmware file to be loaded
over-rides any automatic selection */
static char *firmware = NULL;
module_param(firmware, charp, 0);
/* table of firmware file names */
-static struct {
+static struct {
AtmelFWType fw_type;
const char *fw_file;
const char *fw_file_ext;
@@ -104,17 +104,17 @@ static struct {
#define MAX_SSID_LENGTH 32
#define MGMT_JIFFIES (256 * HZ / 100)
-#define MAX_BSS_ENTRIES 64
+#define MAX_BSS_ENTRIES 64
/* registers */
-#define GCR 0x00 // (SIR0) General Configuration Register
-#define BSR 0x02 // (SIR1) Bank Switching Select Register
+#define GCR 0x00 // (SIR0) General Configuration Register
+#define BSR 0x02 // (SIR1) Bank Switching Select Register
#define AR 0x04
#define DR 0x08
-#define MR1 0x12 // Mirror Register 1
-#define MR2 0x14 // Mirror Register 2
-#define MR3 0x16 // Mirror Register 3
-#define MR4 0x18 // Mirror Register 4
+#define MR1 0x12 // Mirror Register 1
+#define MR2 0x14 // Mirror Register 2
+#define MR3 0x16 // Mirror Register 3
+#define MR4 0x18 // Mirror Register 4
#define GPR1 0x0c
#define GPR2 0x0e
@@ -123,9 +123,9 @@ static struct {
// Constants for the GCR register.
//
#define GCR_REMAP 0x0400 // Remap internal SRAM to 0
-#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset)
+#define GCR_SWRES 0x0080 // BIU reset (ARM and PAI are NOT reset)
#define GCR_CORES 0x0060 // Core Reset (ARM and PAI are reset)
-#define GCR_ENINT 0x0002 // Enable Interrupts
+#define GCR_ENINT 0x0002 // Enable Interrupts
#define GCR_ACKINT 0x0008 // Acknowledge Interrupts
#define BSS_SRAM 0x0200 // AMBA module selection --> SRAM
@@ -190,7 +190,7 @@ struct rx_desc {
u32 Next;
u16 MsduPos;
u16 MsduSize;
-
+
u8 State;
u8 Status;
u8 Rate;
@@ -199,7 +199,6 @@ struct rx_desc {
u8 PreambleType;
u16 Duration;
u32 RxTime;
-
};
#define RX_DESC_FLAG_VALID 0x80
@@ -218,16 +217,15 @@ struct rx_desc {
#define RX_DESC_DURATION_OFFSET 14
#define RX_DESC_RX_TIME_OFFSET 16
-
struct tx_desc {
u32 NextDescriptor;
u16 TxStartOfFrame;
u16 TxLength;
-
+
u8 TxState;
u8 TxStatus;
u8 RetryCount;
-
+
u8 TxRate;
u8 KeyIndex;
@@ -238,10 +236,8 @@ struct tx_desc {
u8 Reserved;
u8 PacketType;
u16 HostTxLength;
-
};
-
#define TX_DESC_NEXT_OFFSET 0
#define TX_DESC_POS_OFFSET 4
#define TX_DESC_SIZE_OFFSET 6
@@ -255,8 +251,6 @@ struct tx_desc {
#define TX_DESC_PACKET_TYPE_OFFSET 17
#define TX_DESC_HOST_LENGTH_OFFSET 18
-
-
///////////////////////////////////////////////////////
// Host-MAC interface
///////////////////////////////////////////////////////
@@ -266,7 +260,6 @@ struct tx_desc {
#define TX_FIRM_OWN 0x80
#define TX_DONE 0x40
-
#define TX_ERROR 0x01
#define TX_PACKET_TYPE_DATA 0x01
@@ -280,8 +273,7 @@ struct tx_desc {
#define ISR_COMMAND_COMPLETE 0x10 // command completed
#define ISR_OUT_OF_RANGE 0x20 // command completed
#define ISR_IBSS_MERGE 0x40 // (4.1.2.30): IBSS merge
-#define ISR_GENERIC_IRQ 0x80
-
+#define ISR_GENERIC_IRQ 0x80
#define Local_Mib_Type 0x01
#define Mac_Address_Mib_Type 0x02
@@ -317,7 +309,6 @@ struct tx_desc {
#define LOCAL_MIB_PREAMBLE_TYPE 9
#define MAC_ADDR_MIB_MAC_ADDR_POS 0
-
#define CMD_Set_MIB_Vars 0x01
#define CMD_Get_MIB_Vars 0x02
#define CMD_Scan 0x03
@@ -338,7 +329,6 @@ struct tx_desc {
#define CMD_STATUS_HOST_ERROR 0xFF
#define CMD_STATUS_BUSY 0xFE
-
#define CMD_BLOCK_COMMAND_OFFSET 0
#define CMD_BLOCK_STATUS_OFFSET 1
#define CMD_BLOCK_PARAMETERS_OFFSET 4
@@ -347,15 +337,15 @@ struct tx_desc {
#define MGMT_FRAME_BODY_OFFSET 24
#define MAX_AUTHENTICATION_RETRIES 3
-#define MAX_ASSOCIATION_RETRIES 3
+#define MAX_ASSOCIATION_RETRIES 3
#define AUTHENTICATION_RESPONSE_TIME_OUT 1000
#define MAX_WIRELESS_BODY 2316 /* mtu is 2312, CRC is 4 */
#define LOOP_RETRY_LIMIT 500000
-#define ACTIVE_MODE 1
-#define PS_MODE 2
+#define ACTIVE_MODE 1
+#define PS_MODE 2
#define MAX_ENCRYPTION_KEYS 4
#define MAX_ENCRYPTION_KEY_SIZE 40
@@ -377,7 +367,7 @@ struct tx_desc {
#define REG_DOMAIN_MKK1 0x41 //Channel 1-14 Japan(MKK1)
#define REG_DOMAIN_ISRAEL 0x50 //Channel 3-9 ISRAEL
-#define BSS_TYPE_AD_HOC 1
+#define BSS_TYPE_AD_HOC 1
#define BSS_TYPE_INFRASTRUCTURE 2
#define SCAN_TYPE_ACTIVE 0
@@ -389,7 +379,7 @@ struct tx_desc {
#define DATA_FRAME_WS_HEADER_SIZE 30
-/* promiscuous mode control */
+/* promiscuous mode control */
#define PROM_MODE_OFF 0x0
#define PROM_MODE_UNKNOWN 0x1
#define PROM_MODE_CRC_FAILED 0x2
@@ -398,8 +388,7 @@ struct tx_desc {
#define PROM_MODE_CTRL 0x10
#define PROM_MODE_BAD_PROTOCOL 0x20
-
-#define IFACE_INT_STATUS_OFFSET 0
+#define IFACE_INT_STATUS_OFFSET 0
#define IFACE_INT_MASK_OFFSET 1
#define IFACE_LOCKOUT_HOST_OFFSET 2
#define IFACE_LOCKOUT_MAC_OFFSET 3
@@ -407,7 +396,7 @@ struct tx_desc {
#define IFACE_MAC_STAT_OFFSET 30
#define IFACE_GENERIC_INT_TYPE_OFFSET 32
-#define CIPHER_SUITE_NONE 0
+#define CIPHER_SUITE_NONE 0
#define CIPHER_SUITE_WEP_64 1
#define CIPHER_SUITE_TKIP 2
#define CIPHER_SUITE_AES 3
@@ -419,11 +408,11 @@ struct tx_desc {
//
//
-// FuncCtrl field:
+// FuncCtrl field:
//
#define FUNC_CTRL_TxENABLE 0x10
#define FUNC_CTRL_RxENABLE 0x20
-#define FUNC_CTRL_INIT_COMPLETE 0x01
+#define FUNC_CTRL_INIT_COMPLETE 0x01
/* A stub firmware image which reads the MAC address from NVRAM on the card.
For copyright information and source see the end of this file. */
@@ -486,10 +475,10 @@ struct atmel_private {
struct net_device_stats stats; // device stats
spinlock_t irqlock, timerlock; // spinlocks
enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type;
- enum {
- CARD_TYPE_PARALLEL_FLASH,
+ enum {
+ CARD_TYPE_PARALLEL_FLASH,
CARD_TYPE_SPI_FLASH,
- CARD_TYPE_EEPROM
+ CARD_TYPE_EEPROM
} card_type;
int do_rx_crc; /* If we need to CRC incoming packets */
int probe_crc; /* set if we don't yet know */
@@ -497,18 +486,18 @@ struct atmel_private {
u16 rx_desc_head;
u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous;
u16 tx_free_mem, tx_buff_head, tx_buff_tail;
-
+
u16 frag_seq, frag_len, frag_no;
- u8 frag_source[6];
-
+ u8 frag_source[6];
+
u8 wep_is_on, default_key, exclude_unencrypted, encryption_level;
u8 group_cipher_suite, pairwise_cipher_suite;
u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
- int wep_key_len[MAX_ENCRYPTION_KEYS];
+ int wep_key_len[MAX_ENCRYPTION_KEYS];
int use_wpa, radio_on_broken; /* firmware dependent stuff. */
u16 host_info_base;
- struct host_info_struct {
+ struct host_info_struct {
/* NB this is matched to the hardware, don't change. */
u8 volatile int_status;
u8 volatile int_mask;
@@ -524,20 +513,20 @@ struct atmel_private {
u16 rx_buff_size;
u16 rx_desc_pos;
u16 rx_desc_count;
-
+
u16 build_version;
- u16 command_pos;
-
+ u16 command_pos;
+
u16 major_version;
u16 minor_version;
-
+
u16 func_ctrl;
u16 mac_status;
u16 generic_IRQ_type;
u8 reserved[2];
} host_info;
- enum {
+ enum {
STATION_STATE_SCANNING,
STATION_STATE_JOINNING,
STATION_STATE_AUTHENTICATING,
@@ -547,7 +536,7 @@ struct atmel_private {
STATION_STATE_DOWN,
STATION_STATE_MGMT_ERROR
} station_state;
-
+
int operating_mode, power_mode;
time_t last_qual;
int beacons_this_sec;
@@ -560,18 +549,18 @@ struct atmel_private {
int long_retry, short_retry;
int preamble;
int default_beacon_period, beacon_period, listen_interval;
- int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
+ int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum;
int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt;
enum {
SITE_SURVEY_IDLE,
SITE_SURVEY_IN_PROGRESS,
- SITE_SURVEY_COMPLETED
+ SITE_SURVEY_COMPLETED
} site_survey_state;
time_t last_survey;
int station_was_associated, station_is_associated;
int fast_scan;
-
+
struct bss_info {
int channel;
int SSIDsize;
@@ -584,13 +573,12 @@ struct atmel_private {
u8 SSID[MAX_SSID_LENGTH];
} BSSinfo[MAX_BSS_ENTRIES];
int BSS_list_entries, current_BSS;
- int connect_to_any_BSS;
+ int connect_to_any_BSS;
int SSID_size, new_SSID_size;
u8 CurrentBSSID[6], BSSID[6];
u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH];
u64 last_beacon_timestamp;
u8 rx_buf[MAX_WIRELESS_BODY];
-
};
static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
@@ -598,39 +586,49 @@ static u8 atmel_basic_rates[4] = {0x82,0x84,0x0b,0x16};
static const struct {
int reg_domain;
int min, max;
- char *name;
+ char *name;
} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" },
{ REG_DOMAIN_DOC, 1, 11, "Canada" },
{ REG_DOMAIN_ETSI, 1, 13, "Europe" },
{ REG_DOMAIN_SPAIN, 10, 11, "Spain" },
- { REG_DOMAIN_FRANCE, 10, 13, "France" },
+ { REG_DOMAIN_FRANCE, 10, 13, "France" },
{ REG_DOMAIN_MKK, 14, 14, "MKK" },
{ REG_DOMAIN_MKK1, 1, 14, "MKK1" },
{ REG_DOMAIN_ISRAEL, 3, 9, "Israel"} };
static void build_wpa_mib(struct atmel_private *priv);
static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len);
-static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len);
+static void atmel_copy_to_card(struct net_device *dev, u16 dest,
+ unsigned char *src, u16 len);
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
+ u16 src, u16 len);
static void atmel_set_gcr(struct net_device *dev, u16 mask);
static void atmel_clear_gcr(struct net_device *dev, u16 mask);
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 ieee80211_hdr_4addr *header,
+static void atmel_management_frame(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *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 ieee80211_hdr_4addr *header,
+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 ieee80211_hdr_4addr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
-static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data);
-static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data);
-static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
-static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len);
+static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index,
+ u8 data);
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
+ u16 data);
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
+ u8 *data, int data_len);
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
+ u8 *data, int data_len);
static void atmel_scan(struct atmel_private *priv, int specific_ssid);
static void atmel_join_bss(struct atmel_private *priv, int bss_index);
static void atmel_smooth_qual(struct atmel_private *priv);
@@ -650,12 +648,12 @@ static inline u16 atmel_co(struct atmel_private *priv, u16 offset)
return priv->host_info.command_pos + offset;
}
-static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
+static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc)
{
return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset;
}
-static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
+static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc)
{
return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset;
}
@@ -682,25 +680,25 @@ static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data)
static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos)
{
- atmel_writeAR(priv->dev, pos);
+ atmel_writeAR(priv->dev, pos);
return atmel_read8(priv->dev, DR);
}
static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data)
{
- atmel_writeAR(priv->dev, pos);
+ atmel_writeAR(priv->dev, pos);
atmel_write8(priv->dev, DR, data);
}
static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos)
{
- atmel_writeAR(priv->dev, pos);
+ atmel_writeAR(priv->dev, pos);
return atmel_read16(priv->dev, DR);
}
static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data)
{
- atmel_writeAR(priv->dev, pos);
+ atmel_writeAR(priv->dev, pos);
atmel_write16(priv->dev, DR, data);
}
@@ -710,11 +708,10 @@ static void tx_done_irq(struct atmel_private *priv)
{
int i;
- for (i = 0;
+ for (i = 0;
atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE &&
i < priv->host_info.tx_desc_count;
i++) {
-
u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head));
u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head));
u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head));
@@ -728,16 +725,16 @@ static void tx_done_irq(struct atmel_private *priv)
priv->tx_buff_head = 0;
else
priv->tx_buff_head += msdu_size;
-
+
if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1))
- priv->tx_desc_head++ ;
+ priv->tx_desc_head++ ;
else
priv->tx_desc_head = 0;
-
+
if (type == TX_PACKET_TYPE_DATA) {
if (status == TX_STATUS_SUCCESS)
priv->stats.tx_packets++;
- else
+ else
priv->stats.tx_errors++;
netif_wake_queue(priv->dev);
}
@@ -748,21 +745,22 @@ static u16 find_tx_buff(struct atmel_private *priv, u16 len)
{
u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail;
- if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
+ if (priv->tx_desc_free == 3 || priv->tx_free_mem < len)
return 0;
-
+
if (bottom_free >= len)
return priv->host_info.tx_buff_pos + priv->tx_buff_tail;
-
+
if (priv->tx_free_mem - bottom_free >= len) {
priv->tx_buff_tail = 0;
return priv->host_info.tx_buff_pos;
}
-
+
return 0;
}
-static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 len, u16 buff, u8 type)
+static void tx_update_descriptor(struct atmel_private *priv, int is_bcast,
+ u16 len, u16 buff, u8 type)
{
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len);
@@ -775,8 +773,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
int cipher_type, cipher_length;
if (is_bcast) {
cipher_type = priv->group_cipher_suite;
- if (cipher_type == CIPHER_SUITE_WEP_64 ||
- cipher_type == CIPHER_SUITE_WEP_128 )
+ if (cipher_type == CIPHER_SUITE_WEP_64 ||
+ cipher_type == CIPHER_SUITE_WEP_128)
cipher_length = 8;
else if (cipher_type == CIPHER_SUITE_TKIP)
cipher_length = 12;
@@ -790,8 +788,8 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
}
} else {
cipher_type = priv->pairwise_cipher_suite;
- if (cipher_type == CIPHER_SUITE_WEP_64 ||
- cipher_type == CIPHER_SUITE_WEP_128 )
+ if (cipher_type == CIPHER_SUITE_WEP_64 ||
+ cipher_type == CIPHER_SUITE_WEP_128)
cipher_length = 8;
else if (cipher_type == CIPHER_SUITE_TKIP)
cipher_length = 12;
@@ -804,9 +802,9 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
cipher_length = 0;
}
}
-
+
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail),
- cipher_type);
+ cipher_type);
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail),
cipher_length);
}
@@ -815,46 +813,46 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, u16 l
if (priv->tx_desc_previous != priv->tx_desc_tail)
atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0);
priv->tx_desc_previous = priv->tx_desc_tail;
- if (priv->tx_desc_tail < (priv->host_info.tx_desc_count -1 ))
+ if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1))
priv->tx_desc_tail++;
else
priv->tx_desc_tail = 0;
priv->tx_desc_free--;
priv->tx_free_mem -= len;
-
}
-static int start_tx (struct sk_buff *skb, struct net_device *dev)
+static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
struct ieee80211_hdr_4addr 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};
-
- if (priv->card && priv->present_callback &&
+
+ if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card)) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
-
+
if (priv->station_state != STATION_STATE_READY) {
priv->stats.tx_errors++;
dev_kfree_skb(skb);
return 0;
}
-
+
/* first ensure the timer func cannot run */
- spin_lock_bh(&priv->timerlock);
+ spin_lock_bh(&priv->timerlock);
/* then stop the hardware ISR */
- spin_lock_irqsave(&priv->irqlock, flags);
+ spin_lock_irqsave(&priv->irqlock, flags);
/* nb doing the above in the opposite order will deadlock */
-
+
/* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the
- 12 first bytes (containing DA/SA) and put them in the appropriate fields of
- the Wireless Header. Thus the packet length is then the initial + 18 (+30-12) */
-
+ 12 first bytes (containing DA/SA) and put them in the appropriate
+ fields of the Wireless Header. Thus the packet length is then the
+ initial + 18 (+30-12) */
+
if (!(buff = find_tx_buff(priv, len + 18))) {
priv->stats.tx_dropped++;
spin_unlock_irqrestore(&priv->irqlock, flags);
@@ -862,7 +860,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
return 1;
}
-
+
frame_ctl = IEEE80211_FTYPE_DATA;
header.duration_id = 0;
header.seq_ctl = 0;
@@ -878,7 +876,7 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
memcpy(&header.addr2, dev->dev_addr, 6);
memcpy(&header.addr3, skb->data, 6);
}
-
+
if (priv->use_wpa)
memcpy(&header.addr4, SNAP_RFC1024, 6);
@@ -888,27 +886,27 @@ static int start_tx (struct sk_buff *skb, struct net_device *dev)
/* Copy the packet sans its 802.3 header addresses which have been replaced */
atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12);
priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE;
-
+
/* low bit of first byte of destination tells us if broadcast */
tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA);
dev->trans_start = jiffies;
priv->stats.tx_bytes += len;
-
+
spin_unlock_irqrestore(&priv->irqlock, flags);
spin_unlock_bh(&priv->timerlock);
dev_kfree_skb(skb);
-
- return 0;
+
+ return 0;
}
-static void atmel_transmit_management_frame(struct atmel_private *priv,
+static void atmel_transmit_management_frame(struct atmel_private *priv,
struct ieee80211_hdr_4addr *header,
u8 *body, int body_len)
{
u16 buff;
- int len = MGMT_FRAME_BODY_OFFSET + body_len;
-
- if (!(buff = find_tx_buff(priv, len)))
+ int len = MGMT_FRAME_BODY_OFFSET + body_len;
+
+ if (!(buff = find_tx_buff(priv, len)))
return;
atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET);
@@ -916,24 +914,25 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
priv->tx_buff_tail += len;
tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT);
}
-
-static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
+
+static void fast_rx_path(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
- u8 mac4[6];
- struct sk_buff *skb;
+ u8 mac4[6];
+ struct sk_buff *skb;
unsigned char *skbp;
-
+
/* get the final, mac 4 header field, this tells us encapsulation */
atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6);
msdu_size -= 6;
-
+
if (priv->do_rx_crc) {
crc = crc32_le(crc, mac4, 6);
msdu_size -= 4;
}
-
+
if (!(skb = dev_alloc_skb(msdu_size + 14))) {
priv->stats.rx_dropped++;
return;
@@ -942,7 +941,7 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
skb_reserve(skb, 2);
skbp = skb_put(skb, msdu_size + 12);
atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size);
-
+
if (priv->do_rx_crc) {
u32 netcrc;
crc = crc32_le(crc, skbp + 12, msdu_size);
@@ -953,24 +952,25 @@ static void fast_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
return;
}
}
-
+
memcpy(skbp, header->addr1, 6); /* destination address */
- if (le16_to_cpu(header->frame_ctl) & IEEE80211_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 */
-
- priv->dev->last_rx=jiffies;
+
+ priv->dev->last_rx = jiffies;
skb->dev = priv->dev;
skb->protocol = eth_type_trans(skb, priv->dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
priv->stats.rx_bytes += 12 + msdu_size;
priv->stats.rx_packets++;
}
/* Test to see if the packet in card memory at packet_loc has a valid CRC
- It doesn't matter that this is slow: it is only used to proble the first few packets. */
+ It doesn't matter that this is slow: it is only used to proble the first few
+ packets. */
static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
{
int i = msdu_size - 4;
@@ -980,7 +980,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
return 0;
atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4);
-
+
atmel_writeAR(priv->dev, packet_loc);
while (i--) {
u8 octet = atmel_read8(priv->dev, DR);
@@ -990,20 +990,22 @@ 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 ieee80211_hdr_4addr *header,
- u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, u8 frag_no, int more_frags)
+static void frag_rx_path(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *header,
+ u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
+ u8 frag_no, int more_frags)
{
- u8 mac4[6];
+ u8 mac4[6];
u8 source[6];
struct sk_buff *skb;
- if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
memcpy(source, header->addr3, 6);
else
- memcpy(source, header->addr2, 6);
-
+ memcpy(source, header->addr2, 6);
+
rx_packet_loc += 24; /* skip header */
-
+
if (priv->do_rx_crc)
msdu_size -= 4;
@@ -1012,16 +1014,16 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
msdu_size -= 6;
rx_packet_loc += 6;
- if (priv->do_rx_crc)
+ if (priv->do_rx_crc)
crc = crc32_le(crc, mac4, 6);
-
+
priv->frag_seq = seq_no;
priv->frag_no = 1;
priv->frag_len = msdu_size;
- memcpy(priv->frag_source, source, 6);
+ memcpy(priv->frag_source, source, 6);
memcpy(&priv->rx_buf[6], source, 6);
memcpy(priv->rx_buf, header->addr1, 6);
-
+
atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size);
if (priv->do_rx_crc) {
@@ -1033,17 +1035,17 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
memset(priv->frag_source, 0xff, 6);
}
}
-
+
} else if (priv->frag_no == frag_no &&
priv->frag_seq == seq_no &&
memcmp(priv->frag_source, source, 6) == 0) {
-
- atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
+
+ atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len],
rx_packet_loc, msdu_size);
if (priv->do_rx_crc) {
u32 netcrc;
- crc = crc32_le(crc,
- &priv->rx_buf[12 + priv->frag_len],
+ crc = crc32_le(crc,
+ &priv->rx_buf[12 + priv->frag_len],
msdu_size);
atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4);
if ((crc ^ 0xffffffff) != netcrc) {
@@ -1052,7 +1054,7 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
more_frags = 1; /* don't send broken assembly */
}
}
-
+
priv->frag_len += msdu_size;
priv->frag_no++;
@@ -1062,60 +1064,60 @@ static void frag_rx_path(struct atmel_private *priv, struct ieee80211_hdr_4addr
priv->stats.rx_dropped++;
} else {
skb_reserve(skb, 2);
- memcpy(skb_put(skb, priv->frag_len + 12),
+ memcpy(skb_put(skb, priv->frag_len + 12),
priv->rx_buf,
priv->frag_len + 12);
priv->dev->last_rx = jiffies;
skb->dev = priv->dev;
skb->protocol = eth_type_trans(skb, priv->dev);
- skb->ip_summed = CHECKSUM_NONE;
+ skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
priv->stats.rx_bytes += priv->frag_len + 12;
priv->stats.rx_packets++;
}
}
-
} else
priv->wstats.discard.fragment++;
}
-
+
static void rx_done_irq(struct atmel_private *priv)
{
int i;
struct ieee80211_hdr_4addr header;
-
- for (i = 0;
+
+ for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
i < priv->host_info.rx_desc_count;
i++) {
-
+
u16 msdu_size, rx_packet_loc, frame_ctl, seq_control;
u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head));
u32 crc = 0xffffffff;
-
+
if (status != RX_STATUS_SUCCESS) {
if (status == 0xc1) /* determined by experiment */
priv->wstats.discard.nwid++;
else
- priv->stats.rx_errors++;
+ priv->stats.rx_errors++;
goto next;
}
msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head));
rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head));
-
+
if (msdu_size < 30) {
- priv->stats.rx_errors++;
+ priv->stats.rx_errors++;
goto next;
}
-
+
/* Get header as far as end of seq_ctl */
atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
frame_ctl = le16_to_cpu(header.frame_ctl);
seq_control = le16_to_cpu(header.seq_ctl);
- /* 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 */
+ /* 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 & IEEE80211_FCTL_PROTECTED)) {
priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size);
@@ -1130,34 +1132,33 @@ static void rx_done_irq(struct atmel_private *priv)
priv->probe_crc = 0;
}
}
-
+
/* don't CRC header when WEP in use */
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 & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
-
+ if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
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 ) {
+
+ if (!more_fragments && packet_fragment_no == 0) {
fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc);
} else {
frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc,
packet_sequence_no, packet_fragment_no, more_fragments);
}
}
-
+
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);
-
+
/* we use the same buffer for frag reassembly and control packets */
memset(priv->frag_source, 0xff, 6);
-
+
if (priv->do_rx_crc) {
/* last 4 octets is crc */
msdu_size -= 4;
@@ -1170,18 +1171,18 @@ static void rx_done_irq(struct atmel_private *priv)
atmel_management_frame(priv, &header, msdu_size,
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head)));
- }
+ }
- next:
+next:
/* release descriptor */
- atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
-
+ atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED);
+
if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1))
- priv->rx_desc_head++;
+ priv->rx_desc_head++;
else
priv->rx_desc_head = 0;
}
-}
+}
static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1189,7 +1190,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
struct atmel_private *priv = netdev_priv(dev);
u8 isr;
int i = -1;
- static u8 irq_order[] = {
+ static u8 irq_order[] = {
ISR_OUT_OF_RANGE,
ISR_RxCOMPLETE,
ISR_TxCOMPLETE,
@@ -1199,20 +1200,19 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
ISR_IBSS_MERGE,
ISR_GENERIC_IRQ
};
-
- if (priv->card && priv->present_callback &&
+ if (priv->card && priv->present_callback &&
!(*priv->present_callback)(priv->card))
return IRQ_HANDLED;
/* In this state upper-level code assumes it can mess with
the card unhampered by interrupts which may change register state.
Note that even though the card shouldn't generate interrupts
- the inturrupt line may be shared. This allows card setup
+ the inturrupt line may be shared. This allows card setup
to go on without disabling interrupts for a long time. */
if (priv->station_state == STATION_STATE_DOWN)
return IRQ_NONE;
-
+
atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */
while (1) {
@@ -1221,36 +1221,36 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
-
+
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-
+
if (!isr) {
atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */
return i == -1 ? IRQ_NONE : IRQ_HANDLED;
}
-
+
atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */
-
+
for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++)
if (isr & irq_order[i])
break;
-
+
if (!atmel_lock_mac(priv)) {
/* failed to contact card */
printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name);
return IRQ_HANDLED;
}
-
+
isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET));
isr ^= irq_order[i];
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr);
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
-
+
switch (irq_order[i]) {
-
- case ISR_OUT_OF_RANGE:
- if (priv->operating_mode == IW_MODE_INFRA &&
+
+ case ISR_OUT_OF_RANGE:
+ if (priv->operating_mode == IW_MODE_INFRA &&
priv->station_state == STATION_STATE_READY) {
priv->station_is_associated = 0;
atmel_scan(priv, 1);
@@ -1261,24 +1261,24 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
priv->wstats.discard.misc++;
/* fall through */
case ISR_RxCOMPLETE:
- rx_done_irq(priv);
+ rx_done_irq(priv);
break;
-
+
case ISR_TxCOMPLETE:
- tx_done_irq(priv);
+ tx_done_irq(priv);
break;
-
+
case ISR_FATAL_ERROR:
printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name);
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
break;
-
- case ISR_COMMAND_COMPLETE:
+
+ case ISR_COMMAND_COMPLETE:
atmel_command_irq(priv);
break;
case ISR_IBSS_MERGE:
- atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
+ atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
priv->CurrentBSSID, 6);
/* The WPA stuff cares about the current AP address */
if (priv->use_wpa)
@@ -1288,24 +1288,23 @@ static irqreturn_t service_interrupt(int irq, void *dev_id, struct pt_regs *regs
printk(KERN_INFO "%s: Generic_irq received.\n", dev->name);
break;
}
- }
+ }
}
-
-static struct net_device_stats *atmel_get_stats (struct net_device *dev)
+static struct net_device_stats *atmel_get_stats(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
return &priv->stats;
}
-static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
+static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
- /* update the link quality here in case we are seeing no beacons
+ /* update the link quality here in case we are seeing no beacons
at all to drive the process */
atmel_smooth_qual(priv);
-
+
priv->wstats.status = priv->station_state;
if (priv->operating_mode == IW_MODE_INFRA) {
@@ -1328,8 +1327,8 @@ static struct iw_statistics *atmel_get_wireless_stats (struct net_device *dev)
| IW_QUAL_NOISE_INVALID;
priv->wstats.miss.beacon = 0;
}
-
- return (&priv->wstats);
+
+ return &priv->wstats;
}
static int atmel_change_mtu(struct net_device *dev, int new_mtu)
@@ -1343,21 +1342,21 @@ static int atmel_change_mtu(struct net_device *dev, int new_mtu)
static int atmel_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
-
+
memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
return atmel_open(dev);
}
EXPORT_SYMBOL(atmel_open);
-int atmel_open (struct net_device *dev)
+int atmel_open(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
int i, channel;
/* any scheduled timer is no longer needed and might screw things up.. */
del_timer_sync(&priv->management_timer);
-
+
/* Interrupts will not touch the card once in this state... */
priv->station_state = STATION_STATE_DOWN;
@@ -1377,7 +1376,7 @@ int atmel_open (struct net_device *dev)
priv->site_survey_state = SITE_SURVEY_IDLE;
priv->station_is_associated = 0;
- if (!reset_atmel_card(dev))
+ if (!reset_atmel_card(dev))
return -EAGAIN;
if (priv->config_reg_domain) {
@@ -1391,26 +1390,37 @@ int atmel_open (struct net_device *dev)
if (i == sizeof(channel_table)/sizeof(channel_table[0])) {
priv->reg_domain = REG_DOMAIN_MKK1;
printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name);
- }
+ }
}
-
+
if ((channel = atmel_validate_channel(priv, priv->channel)))
priv->channel = channel;
- /* this moves station_state on.... */
- atmel_scan(priv, 1);
+ /* this moves station_state on.... */
+ atmel_scan(priv, 1);
atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */
return 0;
}
-static int atmel_close (struct net_device *dev)
+static int atmel_close(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
-
+
+ /* Send event to userspace that we are disassociating */
+ if (priv->station_state == STATION_STATE_READY) {
+ union iwreq_data wrqu;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+ }
+
atmel_enter_state(priv, STATION_STATE_DOWN);
-
- if (priv->bus_type == BUS_TYPE_PCCARD)
+
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
return 0;
@@ -1438,43 +1448,46 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
int i;
char *p = buf;
char *s, *r, *c;
-
- p += sprintf(p, "Driver version:\t\t%d.%d\n", DRIVER_MAJOR, DRIVER_MINOR);
-
+
+ p += sprintf(p, "Driver version:\t\t%d.%d\n",
+ DRIVER_MAJOR, DRIVER_MINOR);
+
if (priv->station_state != STATION_STATE_DOWN) {
- p += sprintf(p, "Firmware version:\t%d.%d build %d\nFirmware location:\t",
+ p += sprintf(p, "Firmware version:\t%d.%d build %d\n"
+ "Firmware location:\t",
priv->host_info.major_version,
priv->host_info.minor_version,
priv->host_info.build_version);
-
- if (priv->card_type != CARD_TYPE_EEPROM)
+
+ if (priv->card_type != CARD_TYPE_EEPROM)
p += sprintf(p, "on card\n");
- else if (priv->firmware)
- p += sprintf(p, "%s loaded by host\n", priv->firmware_id);
+ else if (priv->firmware)
+ p += sprintf(p, "%s loaded by host\n",
+ priv->firmware_id);
else
- p += sprintf(p, "%s loaded by hotplug\n", priv->firmware_id);
-
- switch(priv->card_type) {
+ p += sprintf(p, "%s loaded by hotplug\n",
+ priv->firmware_id);
+
+ switch (priv->card_type) {
case CARD_TYPE_PARALLEL_FLASH: c = "Parallel flash"; break;
case CARD_TYPE_SPI_FLASH: c = "SPI flash\n"; break;
case CARD_TYPE_EEPROM: c = "EEPROM"; break;
default: c = "<unknown>";
}
-
r = "<unknown>";
for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++)
if (priv->reg_domain == channel_table[i].reg_domain)
r = channel_table[i].name;
-
+
p += sprintf(p, "MAC memory type:\t%s\n", c);
p += sprintf(p, "Regulatory domain:\t%s\n", r);
- p += sprintf(p, "Host CRC checking:\t%s\n",
+ p += sprintf(p, "Host CRC checking:\t%s\n",
priv->do_rx_crc ? "On" : "Off");
p += sprintf(p, "WPA-capable firmware:\t%s\n",
priv->use_wpa ? "Yes" : "No");
}
-
+
switch(priv->station_state) {
case STATION_STATE_SCANNING: s = "Scanning"; break;
case STATION_STATE_JOINNING: s = "Joining"; break;
@@ -1486,9 +1499,9 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv)
case STATION_STATE_DOWN: s = "Down"; break;
default: s = "<unknown>";
}
-
+
p += sprintf(p, "Current state:\t\t%s\n", s);
- return p - buf;
+ return p - buf;
}
static int atmel_read_proc(char *page, char **start, off_t off,
@@ -1504,9 +1517,12 @@ static int atmel_read_proc(char *page, char **start, off_t off,
return len;
}
-struct net_device *init_atmel_card( unsigned short irq, unsigned long port, const AtmelFWType fw_type,
- struct device *sys_dev, int (*card_present)(void *), void *card)
+struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
+ const AtmelFWType fw_type,
+ struct device *sys_dev,
+ int (*card_present)(void *), void *card)
{
+ struct proc_dir_entry *ent;
struct net_device *dev;
struct atmel_private *priv;
int rc;
@@ -1514,11 +1530,11 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
/* Create the network device object. */
dev = alloc_etherdev(sizeof(*priv));
if (!dev) {
- printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
+ printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n");
return NULL;
}
if (dev_alloc_name(dev, dev->name) < 0) {
- printk(KERN_ERR "atmel: Couldn't get name!\n");
+ printk(KERN_ERR "atmel: Couldn't get name!\n");
goto err_out_free;
}
@@ -1550,7 +1566,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
memset(priv->BSSID, 0, 6);
priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */
priv->station_was_associated = 0;
-
+
priv->last_survey = jiffies;
priv->preamble = LONG_PREAMBLE;
priv->operating_mode = IW_MODE_INFRA;
@@ -1586,7 +1602,7 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
spin_lock_init(&priv->timerlock);
priv->management_timer.function = atmel_management_timer;
priv->management_timer.data = (unsigned long) dev;
-
+
dev->open = atmel_open;
dev->stop = atmel_close;
dev->change_mtu = atmel_change_mtu;
@@ -1597,44 +1613,46 @@ struct net_device *init_atmel_card( unsigned short irq, unsigned long port, cons
dev->do_ioctl = atmel_ioctl;
dev->irq = irq;
dev->base_addr = port;
-
+
SET_NETDEV_DEV(dev, sys_dev);
-
+
if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
- printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
+ printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc);
goto err_out_free;
}
- if (!request_region(dev->base_addr, 32,
+ if (!request_region(dev->base_addr, 32,
priv->bus_type == BUS_TYPE_PCCARD ? "atmel_cs" : "atmel_pci")) {
goto err_out_irq;
}
-
+
if (register_netdev(dev))
goto err_out_res;
-
+
if (!probe_atmel_card(dev)){
unregister_netdev(dev);
goto err_out_res;
}
-
+
netif_carrier_off(dev);
-
- create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
-
+
+ ent = create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv);
+ if (!ent)
+ printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
+
printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dev->name, DRIVER_MAJOR, DRIVER_MINOR,
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
-
+
SET_MODULE_OWNER(dev);
return dev;
-
- err_out_res:
+
+err_out_res:
release_region( dev->base_addr, 32);
- err_out_irq:
+err_out_irq:
free_irq(dev->irq, dev);
- err_out_free:
+err_out_free:
free_netdev(dev);
return NULL;
}
@@ -1644,12 +1662,12 @@ EXPORT_SYMBOL(init_atmel_card);
void stop_atmel_card(struct net_device *dev)
{
struct atmel_private *priv = netdev_priv(dev);
-
+
/* put a brick on it... */
- if (priv->bus_type == BUS_TYPE_PCCARD)
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
-
+
del_timer_sync(&priv->management_timer);
unregister_netdev(dev);
remove_proc_entry("driver/atmel", NULL);
@@ -1675,13 +1693,13 @@ static int atmel_set_essid(struct net_device *dev,
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
priv->connect_to_any_BSS = 0;
-
+
/* Check the size of the string */
if (dwrq->length > MAX_SSID_LENGTH + 1)
- return -E2BIG ;
+ return -E2BIG;
if (index != 0)
return -EINVAL;
-
+
memcpy(priv->new_SSID, extra, dwrq->length - 1);
priv->new_SSID_size = dwrq->length - 1;
}
@@ -1700,13 +1718,13 @@ static int atmel_get_essid(struct net_device *dev,
if (priv->new_SSID_size != 0) {
memcpy(extra, priv->new_SSID, priv->new_SSID_size);
extra[priv->new_SSID_size] = '\0';
- dwrq->length = priv->new_SSID_size + 1;
+ dwrq->length = priv->new_SSID_size;
} else {
memcpy(extra, priv->SSID, priv->SSID_size);
extra[priv->SSID_size] = '\0';
- dwrq->length = priv->SSID_size + 1;
+ dwrq->length = priv->SSID_size;
}
-
+
dwrq->flags = !priv->connect_to_any_BSS; /* active */
return 0;
@@ -1768,33 +1786,33 @@ static int atmel_set_encode(struct net_device *dev,
/* WE specify that if a valid key is set, encryption
* should be enabled (user may turn it off later)
* This is also how "iwconfig ethX key on" works */
- if (index == current_index &&
+ if (index == current_index &&
priv->wep_key_len[index] > 0) {
priv->wep_is_on = 1;
priv->exclude_unencrypted = 1;
if (priv->wep_key_len[index] > 5) {
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
priv->encryption_level = 2;
} else {
- priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
priv->encryption_level = 1;
}
}
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
- if ( index>=0 && index < 4 ) {
+ if (index >= 0 && index < 4) {
priv->default_key = index;
} else
/* Don't complain if only change the mode */
- if(!dwrq->flags & IW_ENCODE_MODE) {
+ if (!dwrq->flags & IW_ENCODE_MODE) {
return -EINVAL;
}
}
/* Read the flags */
- if(dwrq->flags & IW_ENCODE_DISABLED) {
+ if (dwrq->flags & IW_ENCODE_DISABLED) {
priv->wep_is_on = 0;
- priv->encryption_level = 0;
+ priv->encryption_level = 0;
priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
} else {
priv->wep_is_on = 1;
@@ -1806,15 +1824,14 @@ static int atmel_set_encode(struct net_device *dev,
priv->encryption_level = 1;
}
}
- if(dwrq->flags & IW_ENCODE_RESTRICTED)
+ if (dwrq->flags & IW_ENCODE_RESTRICTED)
priv->exclude_unencrypted = 1;
- if(dwrq->flags & IW_ENCODE_OPEN)
+ if(dwrq->flags & IW_ENCODE_OPEN)
priv->exclude_unencrypted = 0;
-
+
return -EINPROGRESS; /* Call commit handler */
}
-
static int atmel_get_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
@@ -1822,7 +1839,7 @@ static int atmel_get_encode(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
+
if (!priv->wep_is_on)
dwrq->flags = IW_ENCODE_DISABLED;
else {
@@ -1843,10 +1860,185 @@ static int atmel_get_encode(struct net_device *dev,
memset(extra, 0, 16);
memcpy(extra, priv->wep_keys[index], dwrq->length);
}
+
+ return 0;
+}
+
+static int atmel_set_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, key_len;
+
+ /* Determine and validate the key index */
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = priv->default_key;
+
+ if ((encoding->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ priv->wep_is_on = 0;
+ priv->encryption_level = 0;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_NONE;
+ }
+
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
+ priv->default_key = idx;
+
+ /* Set the requested key */
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_NONE:
+ break;
+ case IW_ENCODE_ALG_WEP:
+ if (ext->key_len > 5) {
+ priv->wep_key_len[idx] = 13;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128;
+ priv->encryption_level = 2;
+ } else if (ext->key_len > 0) {
+ priv->wep_key_len[idx] = 5;
+ priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64;
+ priv->encryption_level = 1;
+ } else {
+ return -EINVAL;
+ }
+ priv->wep_is_on = 1;
+ memset(priv->wep_keys[idx], 0, 13);
+ key_len = min ((int)ext->key_len, priv->wep_key_len[idx]);
+ memcpy(priv->wep_keys[idx], ext->key, key_len);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return -EINPROGRESS;
+}
+
+static int atmel_get_encodeext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int idx, max_key_len;
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = priv->default_key;
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+ if (!priv->wep_is_on) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ encoding->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (priv->encryption_level > 0)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else
+ return -EINVAL;
+
+ ext->key_len = priv->wep_key_len[idx];
+ memcpy(ext->key, priv->wep_keys[idx], ext->key_len);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ }
+
+ return 0;
+}
+
+static int atmel_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_param *param = &wrqu->param;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ case IW_AUTH_PRIVACY_INVOKED:
+ /*
+ * atmel does not use these parameters
+ */
+ break;
+
+ case IW_AUTH_DROP_UNENCRYPTED:
+ priv->exclude_unencrypted = param->value ? 1 : 0;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG: {
+ if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+ priv->exclude_unencrypted = 1;
+ } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ priv->exclude_unencrypted = 0;
+ } else
+ return -EINVAL;
+ break;
+ }
+
+ case IW_AUTH_WPA_ENABLED:
+ /* Silently accept disable of WPA */
+ if (param->value > 0)
+ return -EOPNOTSUPP;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+ return -EINPROGRESS;
+}
+
+static int atmel_get_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct atmel_private *priv = netdev_priv(dev);
+ struct iw_param *param = &wrqu->param;
+
+ switch (param->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_DROP_UNENCRYPTED:
+ param->value = priv->exclude_unencrypted;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (priv->exclude_unencrypted == 1)
+ param->value = IW_AUTH_ALG_SHARED_KEY;
+ else
+ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ param->value = 0;
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
return 0;
}
+
static int atmel_get_name(struct net_device *dev,
struct iw_request_info *info,
char *cwrq,
@@ -1862,17 +2054,17 @@ static int atmel_set_rate(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
-
+
if (vwrq->fixed == 0) {
priv->tx_rate = 3;
priv->auto_tx_rate = 1;
} else {
priv->auto_tx_rate = 0;
-
+
/* Which type of value ? */
- if((vwrq->value < 4) && (vwrq->value >= 0)) {
+ if ((vwrq->value < 4) && (vwrq->value >= 0)) {
/* Setting by rate index */
- priv->tx_rate = vwrq->value;
+ priv->tx_rate = vwrq->value;
} else {
/* Setting by frequency value */
switch (vwrq->value) {
@@ -1899,7 +2091,7 @@ static int atmel_set_mode(struct net_device *dev,
return -EINVAL;
priv->operating_mode = *uwrq;
- return -EINPROGRESS;
+ return -EINPROGRESS;
}
static int atmel_get_mode(struct net_device *dev,
@@ -1908,7 +2100,7 @@ static int atmel_get_mode(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
-
+
*uwrq = priv->operating_mode;
return 0;
}
@@ -1962,9 +2154,9 @@ static int atmel_set_retry(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
-
- if(!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
- if(vwrq->flags & IW_RETRY_MAX)
+
+ if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
+ if (vwrq->flags & IW_RETRY_MAX)
priv->long_retry = vwrq->value;
else if (vwrq->flags & IW_RETRY_MIN)
priv->short_retry = vwrq->value;
@@ -1973,9 +2165,9 @@ static int atmel_set_retry(struct net_device *dev,
priv->long_retry = vwrq->value;
priv->short_retry = vwrq->value;
}
- return -EINPROGRESS;
+ return -EINPROGRESS;
}
-
+
return -EINVAL;
}
@@ -1989,13 +2181,13 @@ static int atmel_get_retry(struct net_device *dev,
vwrq->disabled = 0; /* Can't be disabled */
/* Note : by default, display the min retry number */
- if((vwrq->flags & IW_RETRY_MAX)) {
+ if (vwrq->flags & IW_RETRY_MAX) {
vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
vwrq->value = priv->long_retry;
} else {
vwrq->flags = IW_RETRY_LIMIT;
vwrq->value = priv->short_retry;
- if(priv->long_retry != priv->short_retry)
+ if (priv->long_retry != priv->short_retry)
vwrq->flags |= IW_RETRY_MIN;
}
@@ -2010,13 +2202,13 @@ static int atmel_set_rts(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
int rthr = vwrq->value;
- if(vwrq->disabled)
+ if (vwrq->disabled)
rthr = 2347;
- if((rthr < 0) || (rthr > 2347)) {
+ if ((rthr < 0) || (rthr > 2347)) {
return -EINVAL;
}
priv->rts_threshold = rthr;
-
+
return -EINPROGRESS; /* Call commit handler */
}
@@ -2026,7 +2218,7 @@ static int atmel_get_rts(struct net_device *dev,
char *extra)
{
struct atmel_private *priv = netdev_priv(dev);
-
+
vwrq->value = priv->rts_threshold;
vwrq->disabled = (vwrq->value >= 2347);
vwrq->fixed = 1;
@@ -2042,14 +2234,14 @@ static int atmel_set_frag(struct net_device *dev,
struct atmel_private *priv = netdev_priv(dev);
int fthr = vwrq->value;
- if(vwrq->disabled)
+ if (vwrq->disabled)
fthr = 2346;
- if((fthr < 256) || (fthr > 2346)) {
+ if ((fthr < 256) || (fthr > 2346)) {
return -EINVAL;
}
fthr &= ~0x1; /* Get an even value - is it really needed ??? */
priv->frag_threshold = fthr;
-
+
return -EINPROGRESS; /* Call commit handler */
}
@@ -2077,21 +2269,21 @@ static int atmel_set_freq(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int rc = -EINPROGRESS; /* Call commit handler */
-
+
/* If setting by frequency, convert to a channel */
- if((fwrq->e == 1) &&
- (fwrq->m >= (int) 241200000) &&
- (fwrq->m <= (int) 248700000)) {
+ if ((fwrq->e == 1) &&
+ (fwrq->m >= (int) 241200000) &&
+ (fwrq->m <= (int) 248700000)) {
int f = fwrq->m / 100000;
int c = 0;
- while((c < 14) && (f != frequency_list[c]))
+ while ((c < 14) && (f != frequency_list[c]))
c++;
/* Hack to fall through... */
fwrq->e = 0;
fwrq->m = c + 1;
}
/* Setting by channel number */
- if((fwrq->m > 1000) || (fwrq->e > 0))
+ if ((fwrq->m > 1000) || (fwrq->e > 0))
rc = -EOPNOTSUPP;
else {
int channel = fwrq->m;
@@ -2099,7 +2291,7 @@ static int atmel_set_freq(struct net_device *dev,
priv->channel = channel;
} else {
rc = -EINVAL;
- }
+ }
}
return rc;
}
@@ -2130,7 +2322,7 @@ static int atmel_set_scan(struct net_device *dev,
* This is not an error, while the device perform scanning,
* traffic doesn't flow, so it's a perfect DoS...
* Jean II */
-
+
if (priv->station_state == STATION_STATE_DOWN)
return -EAGAIN;
@@ -2142,15 +2334,15 @@ static int atmel_set_scan(struct net_device *dev,
/* Initiate a scan command */
if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS)
return -EBUSY;
-
+
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
-
+
priv->site_survey_state = SITE_SURVEY_IN_PROGRESS;
priv->fast_scan = 0;
atmel_scan(priv, 0);
spin_unlock_irqrestore(&priv->irqlock, flags);
-
+
return 0;
}
@@ -2163,11 +2355,11 @@ static int atmel_get_scan(struct net_device *dev,
int i;
char *current_ev = extra;
struct iw_event iwe;
-
+
if (priv->site_survey_state != SITE_SURVEY_COMPLETED)
return -EAGAIN;
-
- for(i=0; i<priv->BSS_list_entries; i++) {
+
+ for (i = 0; i < priv->BSS_list_entries; i++) {
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6);
@@ -2179,16 +2371,16 @@ static int atmel_get_scan(struct net_device *dev,
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID);
-
+
iwe.cmd = SIOCGIWMODE;
iwe.u.mode = priv->BSSinfo[i].BSStype;
current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN);
-
+
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = priv->BSSinfo[i].channel;
iwe.u.freq.e = 0;
current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN);
-
+
iwe.cmd = SIOCGIWENCODE;
if (priv->BSSinfo[i].UsingWEP)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
@@ -2196,13 +2388,12 @@ static int atmel_get_scan(struct net_device *dev,
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL);
-
}
/* Length of data */
dwrq->length = (current_ev - extra);
- dwrq->flags = 0;
-
+ dwrq->flags = 0;
+
return 0;
}
@@ -2213,7 +2404,7 @@ static int atmel_get_range(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
struct iw_range *range = (struct iw_range *) extra;
- int k,i,j;
+ int k, i, j;
dwrq->length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
@@ -2226,14 +2417,14 @@ static int atmel_get_range(struct net_device *dev,
break;
}
if (range->num_channels != 0) {
- for(k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
+ for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) {
range->freq[k].i = i; /* List index */
- range->freq[k].m = frequency_list[i-1] * 100000;
+ range->freq[k].m = frequency_list[i - 1] * 100000;
range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
}
range->num_frequency = k;
}
-
+
range->max_qual.qual = 100;
range->max_qual.level = 100;
range->max_qual.noise = 0;
@@ -2261,11 +2452,11 @@ static int atmel_get_range(struct net_device *dev,
range->encoding_size[1] = 13;
range->num_encoding_sizes = 2;
range->max_encoding_tokens = 4;
-
+
range->pmp_flags = IW_POWER_ON;
range->pmt_flags = IW_POWER_ON;
range->pm_capa = 0;
-
+
range->we_version_source = WIRELESS_EXT;
range->we_version_compiled = WIRELESS_EXT;
range->retry_capa = IW_RETRY_LIMIT ;
@@ -2284,21 +2475,23 @@ static int atmel_set_wap(struct net_device *dev,
{
struct atmel_private *priv = netdev_priv(dev);
int i;
- static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 };
+ static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned long flags;
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
-
- if (memcmp(bcast, awrq->sa_data, 6) == 0) {
+
+ if (!memcmp(any, awrq->sa_data, 6) ||
+ !memcmp(off, awrq->sa_data, 6)) {
del_timer_sync(&priv->management_timer);
spin_lock_irqsave(&priv->irqlock, flags);
atmel_scan(priv, 1);
spin_unlock_irqrestore(&priv->irqlock, flags);
return 0;
}
-
- for(i=0; i<priv->BSS_list_entries; i++) {
+
+ for (i = 0; i < priv->BSS_list_entries; i++) {
if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) {
if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) {
return -EINVAL;
@@ -2313,10 +2506,10 @@ static int atmel_set_wap(struct net_device *dev,
}
}
}
-
+
return -EINVAL;
}
-
+
static int atmel_config_commit(struct net_device *dev,
struct iw_request_info *info, /* NULL */
void *zwrq, /* NULL */
@@ -2325,18 +2518,18 @@ static int atmel_config_commit(struct net_device *dev,
return atmel_open(dev);
}
-static const iw_handler atmel_handler[] =
+static const iw_handler atmel_handler[] =
{
(iw_handler) atmel_config_commit, /* SIOCSIWCOMMIT */
- (iw_handler) atmel_get_name, /* SIOCGIWNAME */
+ (iw_handler) atmel_get_name, /* SIOCGIWNAME */
(iw_handler) NULL, /* SIOCSIWNWID */
(iw_handler) NULL, /* SIOCGIWNWID */
(iw_handler) atmel_set_freq, /* SIOCSIWFREQ */
(iw_handler) atmel_get_freq, /* SIOCGIWFREQ */
(iw_handler) atmel_set_mode, /* SIOCSIWMODE */
(iw_handler) atmel_get_mode, /* SIOCGIWMODE */
- (iw_handler) NULL, /* SIOCSIWSENS */
- (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWRANGE */
(iw_handler) atmel_get_range, /* SIOCGIWRANGE */
(iw_handler) NULL, /* SIOCSIWPRIV */
@@ -2350,13 +2543,13 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_set_wap, /* SIOCSIWAP */
(iw_handler) atmel_get_wap, /* SIOCGIWAP */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* SIOCGIWAPLIST */
+ (iw_handler) NULL, /* SIOCGIWAPLIST */
(iw_handler) atmel_set_scan, /* SIOCSIWSCAN */
(iw_handler) atmel_get_scan, /* SIOCGIWSCAN */
(iw_handler) atmel_set_essid, /* SIOCSIWESSID */
(iw_handler) atmel_get_essid, /* SIOCGIWESSID */
- (iw_handler) NULL, /* SIOCSIWNICKN */
- (iw_handler) NULL, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) NULL, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) atmel_set_rate, /* SIOCSIWRATE */
@@ -2365,49 +2558,70 @@ static const iw_handler atmel_handler[] =
(iw_handler) atmel_get_rts, /* SIOCGIWRTS */
(iw_handler) atmel_set_frag, /* SIOCSIWFRAG */
(iw_handler) atmel_get_frag, /* SIOCGIWFRAG */
- (iw_handler) NULL, /* SIOCSIWTXPOW */
- (iw_handler) NULL, /* SIOCGIWTXPOW */
+ (iw_handler) NULL, /* SIOCSIWTXPOW */
+ (iw_handler) NULL, /* SIOCGIWTXPOW */
(iw_handler) atmel_set_retry, /* SIOCSIWRETRY */
(iw_handler) atmel_get_retry, /* SIOCGIWRETRY */
(iw_handler) atmel_set_encode, /* SIOCSIWENCODE */
(iw_handler) atmel_get_encode, /* SIOCGIWENCODE */
(iw_handler) atmel_set_power, /* SIOCSIWPOWER */
(iw_handler) atmel_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* SIOCSIWGENIE */
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+ (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */
+ (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
};
-
-static const iw_handler atmel_private_handler[] =
+static const iw_handler atmel_private_handler[] =
{
NULL, /* SIOCIWFIRSTPRIV */
};
typedef struct atmel_priv_ioctl {
char id[32];
- unsigned char __user *data;
- unsigned short len;
+ unsigned char __user *data;
+ unsigned short len;
} atmel_priv_ioctl;
-
-#define ATMELFWL SIOCIWFIRSTPRIV
-#define ATMELIDIFC ATMELFWL + 1
-#define ATMELRD ATMELFWL + 2
-#define ATMELMAGIC 0x51807
+#define ATMELFWL SIOCIWFIRSTPRIV
+#define ATMELIDIFC ATMELFWL + 1
+#define ATMELRD ATMELFWL + 2
+#define ATMELMAGIC 0x51807
#define REGDOMAINSZ 20
static const struct iw_priv_args atmel_private_args[] = {
-/*{ cmd, set_args, get_args, name } */
- { ATMELFWL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (atmel_priv_ioctl), IW_PRIV_TYPE_NONE, "atmelfwl" },
- { ATMELIDIFC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "atmelidifc" },
- { ATMELRD, IW_PRIV_TYPE_CHAR | REGDOMAINSZ, IW_PRIV_TYPE_NONE, "regdomain" },
+ {
+ .cmd = ATMELFWL,
+ .set_args = IW_PRIV_TYPE_BYTE
+ | IW_PRIV_SIZE_FIXED
+ | sizeof (atmel_priv_ioctl),
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "atmelfwl"
+ }, {
+ .cmd = ATMELIDIFC,
+ .set_args = IW_PRIV_TYPE_NONE,
+ .get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ .name = "atmelidifc"
+ }, {
+ .cmd = ATMELRD,
+ .set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ,
+ .get_args = IW_PRIV_TYPE_NONE,
+ .name = "regdomain"
+ },
};
-static const struct iw_handler_def atmel_handler_def =
+static const struct iw_handler_def atmel_handler_def =
{
.num_standard = sizeof(atmel_handler)/sizeof(iw_handler),
- .num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
- .num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
+ .num_private = sizeof(atmel_private_handler)/sizeof(iw_handler),
+ .num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args),
.standard = (iw_handler *) atmel_handler,
- .private = (iw_handler *) atmel_private_handler,
+ .private = (iw_handler *) atmel_private_handler,
.private_args = (struct iw_priv_args *) atmel_private_args,
.get_wireless_stats = atmel_get_wireless_stats
};
@@ -2419,13 +2633,13 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
atmel_priv_ioctl com;
struct iwreq *wrq = (struct iwreq *) rq;
unsigned char *new_firmware;
- char domain[REGDOMAINSZ+1];
+ char domain[REGDOMAINSZ + 1];
switch (cmd) {
case ATMELIDIFC:
- wrq->u.param.value = ATMELMAGIC;
+ wrq->u.param.value = ATMELMAGIC;
break;
-
+
case ATMELFWL:
if (copy_from_user(&com, rq->ifr_data, sizeof(com))) {
rc = -EFAULT;
@@ -2449,7 +2663,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
kfree(priv->firmware);
-
+
priv->firmware = new_firmware;
priv->firmware_length = com.len;
strncpy(priv->firmware_id, com.id, 31);
@@ -2461,7 +2675,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = -EFAULT;
break;
}
-
+
if (!capable(CAP_NET_ADMIN)) {
rc = -EPERM;
break;
@@ -2484,15 +2698,15 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = 0;
}
}
-
+
if (rc == 0 && priv->station_state != STATION_STATE_DOWN)
rc = atmel_open(dev);
break;
-
+
default:
rc = -EOPNOTSUPP;
}
-
+
return rc;
}
@@ -2503,17 +2717,17 @@ struct auth_body {
u8 el_id;
u8 chall_text_len;
u8 chall_text[253];
-};
+};
static void atmel_enter_state(struct atmel_private *priv, int new_state)
{
int old_state = priv->station_state;
-
+
if (new_state == old_state)
return;
-
+
priv->station_state = new_state;
-
+
if (new_state == STATION_STATE_READY) {
netif_start_queue(priv->dev);
netif_carrier_on(priv->dev);
@@ -2540,7 +2754,7 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
u8 options;
u8 SSID_size;
} cmd;
-
+
memset(cmd.BSSID, 0xff, 6);
if (priv->fast_scan) {
@@ -2554,17 +2768,17 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
cmd.min_channel_time = cpu_to_le16(10);
cmd.max_channel_time = cpu_to_le16(120);
}
-
+
cmd.options = 0;
-
+
if (!specific_ssid)
cmd.options |= SCAN_OPTIONS_SITE_SURVEY;
-
- cmd.channel = (priv->channel & 0x7f);
+
+ cmd.channel = (priv->channel & 0x7f);
cmd.scan_type = SCAN_TYPE_ACTIVE;
- cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
+ cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ?
BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE);
-
+
atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd));
/* This must come after all hardware access to avoid being messed up
@@ -2591,16 +2805,15 @@ static void join(struct atmel_private *priv, int type)
cmd.BSS_type = type;
cmd.timeout = cpu_to_le16(2000);
- atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
+ atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd));
}
-
static void start(struct atmel_private *priv, int type)
{
struct {
u8 BSSID[6];
u8 SSID[MAX_SSID_LENGTH];
- u8 BSS_type;
+ u8 BSS_type;
u8 channel;
u8 SSID_size;
u8 reserved[3];
@@ -2612,13 +2825,14 @@ static void start(struct atmel_private *priv, int type)
cmd.BSS_type = type;
cmd.channel = (priv->channel & 0x7f);
- atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
+ atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd));
}
-static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 channel)
+static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
+ u8 channel)
{
int rejoin = 0;
- int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+ int new = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
SHORT_PREAMBLE : LONG_PREAMBLE;
if (priv->preamble != new) {
@@ -2626,48 +2840,48 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability, u8 c
rejoin = 1;
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new);
}
-
+
if (priv->channel != channel) {
priv->channel = channel;
rejoin = 1;
atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel);
}
-
+
if (rejoin) {
priv->station_is_associated = 0;
atmel_enter_state(priv, STATION_STATE_JOINNING);
-
+
if (priv->operating_mode == IW_MODE_INFRA)
join(priv, BSS_TYPE_INFRASTRUCTURE);
- else
+ else
join(priv, BSS_TYPE_AD_HOC);
- }
+ }
}
-
-static void send_authentication_request(struct atmel_private *priv, u16 system, u8 *challenge, int challenge_len)
+static void send_authentication_request(struct atmel_private *priv, u16 system,
+ u8 *challenge, int challenge_len)
{
struct ieee80211_hdr_4addr header;
struct auth_body auth;
-
- header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
- header.duration_id = cpu_to_le16(0x8000);
+
+ 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);
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
-
- if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
+
+ if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
/* no WEP for authentication frames with TrSeqNo 1 */
header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-
- auth.alg = cpu_to_le16(system);
+
+ auth.alg = cpu_to_le16(system);
auth.status = 0;
auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum);
- priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
+ priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1;
priv->CurrentAuthentTransactionSeqNum += 2;
-
+
if (challenge_len != 0) {
auth.el_id = 16; /* challenge_text */
auth.chall_text_len = challenge_len;
@@ -2685,7 +2899,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
struct ieee80211_hdr_4addr header;
struct ass_req_format {
u16 capability;
- u16 listen_interval;
+ u16 listen_interval;
u8 ap[6]; /* nothing after here directly accessible */
u8 ssid_el_id;
u8 ssid_len;
@@ -2694,15 +2908,15 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
u8 sup_rates_len;
u8 rates[4];
} body;
-
- header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+
+ 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;
- memcpy(header.addr1, priv->CurrentBSSID, 6);
+ memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr2, priv->dev->dev_addr, 6);
- memcpy(header.addr3, priv->CurrentBSSID, 6);
+ memcpy(header.addr3, priv->CurrentBSSID, 6);
body.capability = cpu_to_le16(C80211_MGMT_CAPABILITY_ESS);
if (priv->wep_is_on)
@@ -2711,18 +2925,18 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
body.capability |= cpu_to_le16(C80211_MGMT_CAPABILITY_ShortPreamble);
body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
-
+
/* current AP address - only in reassoc frame */
if (is_reassoc) {
- memcpy(body.ap, priv->CurrentBSSID, 6);
+ memcpy(body.ap, priv->CurrentBSSID, 6);
ssid_el_p = (u8 *)&body.ssid_el_id;
bodysize = 18 + priv->SSID_size;
} else {
ssid_el_p = (u8 *)&body.ap[0];
bodysize = 12 + priv->SSID_size;
}
-
- ssid_el_p[0]= C80211_MGMT_ElementID_SSID;
+
+ ssid_el_p[0] = C80211_MGMT_ElementID_SSID;
ssid_el_p[1] = priv->SSID_size;
memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
ssid_el_p[2 + priv->SSID_size] = C80211_MGMT_ElementID_SupportedRates;
@@ -2732,7 +2946,8 @@ 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 ieee80211_hdr_4addr *header)
+static int is_frame_from_current_bss(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *header)
{
if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
@@ -2745,29 +2960,29 @@ static int retrieve_bss(struct atmel_private *priv)
int i;
int max_rssi = -128;
int max_index = -1;
-
+
if (priv->BSS_list_entries == 0)
return -1;
-
+
if (priv->connect_to_any_BSS) {
- /* Select a BSS with the max-RSSI but of the same type and of the same WEP mode
- and that it is not marked as 'bad' (i.e. we had previously failed to connect to
- this BSS with the settings that we currently use) */
+ /* Select a BSS with the max-RSSI but of the same type and of
+ the same WEP mode and that it is not marked as 'bad' (i.e.
+ we had previously failed to connect to this BSS with the
+ settings that we currently use) */
priv->current_BSS = 0;
- for(i=0; i<priv->BSS_list_entries; i++) {
+ for (i = 0; i < priv->BSS_list_entries; i++) {
if (priv->operating_mode == priv->BSSinfo[i].BSStype &&
- ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
+ ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) ||
(priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) &&
!(priv->BSSinfo[i].channel & 0x80)) {
max_rssi = priv->BSSinfo[i].RSSI;
priv->current_BSS = max_index = i;
}
-
}
return max_index;
}
-
- for(i=0; i<priv->BSS_list_entries; i++) {
+
+ for (i = 0; i < priv->BSS_list_entries; i++) {
if (priv->SSID_size == priv->BSSinfo[i].SSIDsize &&
memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 &&
priv->operating_mode == priv->BSSinfo[i].BSStype &&
@@ -2781,19 +2996,19 @@ static int retrieve_bss(struct atmel_private *priv)
return max_index;
}
-
-static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
- u16 capability, u16 beacon_period, u8 channel, u8 rssi,
- u8 ssid_len, u8 *ssid, int is_beacon)
+static void store_bss_info(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *header, u16 capability,
+ u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
+ u8 *ssid, int is_beacon)
{
u8 *bss = capability & C80211_MGMT_CAPABILITY_ESS ? header->addr2 : header->addr3;
int i, index;
-
- for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
- if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
+
+ for (index = -1, i = 0; i < priv->BSS_list_entries; i++)
+ if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0)
index = i;
- /* If we process a probe and an entry from this BSS exists
+ /* If we process a probe and an entry from this BSS exists
we will update the BSS entry with the info from this BSS.
If we process a beacon we will only update RSSI */
@@ -2820,8 +3035,8 @@ static void store_bss_info(struct atmel_private *priv, struct ieee80211_hdr_4add
priv->BSSinfo[index].BSStype = IW_MODE_ADHOC;
else if (capability & C80211_MGMT_CAPABILITY_ESS)
priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
-
- priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
+
+ priv->BSSinfo[index].preamble = capability & C80211_MGMT_CAPABILITY_ShortPreamble ?
SHORT_PREAMBLE : LONG_PREAMBLE;
}
@@ -2831,8 +3046,8 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
u16 status = le16_to_cpu(auth->status);
u16 trans_seq_no = le16_to_cpu(auth->trans_seq);
u16 system = le16_to_cpu(auth->alg);
-
- if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
+
+ if (status == C80211_MGMT_SC_Success && !priv->wep_is_on) {
/* no WEP */
if (priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -2842,20 +3057,20 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
send_association_request(priv, 0);
return;
- }
+ }
}
-
- if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
+
+ if (status == C80211_MGMT_SC_Success && priv->wep_is_on) {
/* WEP */
if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum)
return;
-
+
if (trans_seq_no == 0x0002 &&
auth->el_id == C80211_MGMT_ElementID_ChallengeText) {
send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
return;
}
-
+
if (trans_seq_no == 0x0004) {
if(priv->station_was_associated) {
atmel_enter_state(priv, STATION_STATE_REASSOCIATING);
@@ -2865,10 +3080,10 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
atmel_enter_state(priv, STATION_STATE_ASSOCIATING);
send_association_request(priv, 0);
return;
- }
+ }
}
- }
-
+ }
+
if (status == C80211_MGMT_SC_AuthAlgNotSupported) {
/* Do opensystem first, then try sharedkey */
if (system == C80211_MGMT_AAN_OPENSYSTEM) {
@@ -2876,17 +3091,16 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
} else if (priv->connect_to_any_BSS) {
int bss_index;
-
+
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-
+
if ((bss_index = retrieve_bss(priv)) != -1) {
atmel_join_bss(priv, bss_index);
return;
}
}
}
-
-
+
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
@@ -2902,38 +3116,54 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
u8 length;
u8 rates[4];
} *ass_resp = (struct ass_resp_format *)priv->rx_buf;
-
- u16 status = le16_to_cpu(ass_resp->status);
+
+ u16 status = le16_to_cpu(ass_resp->status);
u16 ass_id = le16_to_cpu(ass_resp->ass_id);
- u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
-
+ u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length;
+
+ union iwreq_data wrqu;
+
if (frame_len < 8 + rates_len)
return;
-
+
if (status == C80211_MGMT_SC_Success) {
if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE)
priv->AssociationRequestRetryCnt = 0;
else
priv->ReAssociationRequestRetryCnt = 0;
-
- atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
- atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
+
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff);
+ atmel_set_mib(priv, Phy_Mib_Type,
+ PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len);
if (priv->power_mode == 0) {
priv->listen_interval = 1;
- atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
- atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
} else {
priv->listen_interval = 2;
- atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, PS_MODE);
- atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_PS_MODE_POS, PS_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2);
}
-
+
priv->station_is_associated = 1;
priv->station_was_associated = 1;
atmel_enter_state(priv, STATION_STATE_READY);
+
+ /* Send association event to userspace */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN);
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+
return;
}
-
+
if (subtype == C80211_SUBTYPE_MGMT_ASS_RESPONSE &&
status != C80211_MGMT_SC_AssDeniedBSSRate &&
status != C80211_MGMT_SC_SupportCapabilities &&
@@ -2943,7 +3173,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
send_association_request(priv, 0);
return;
}
-
+
if (subtype == C80211_SUBTYPE_MGMT_REASS_RESPONSE &&
status != C80211_MGMT_SC_AssDeniedBSSRate &&
status != C80211_MGMT_SC_SupportCapabilities &&
@@ -2953,17 +3183,16 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
send_association_request(priv, 1);
return;
}
-
+
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
-
- if(priv->connect_to_any_BSS) {
+
+ if (priv->connect_to_any_BSS) {
int bss_index;
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-
- if ((bss_index = retrieve_bss(priv)) != -1)
+
+ if ((bss_index = retrieve_bss(priv)) != -1)
atmel_join_bss(priv, bss_index);
-
}
}
@@ -2977,7 +3206,7 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
/* The WPA stuff cares about the current AP address */
if (priv->use_wpa)
build_wpa_mib(priv);
-
+
/* When switching to AdHoc turn OFF Power Save if needed */
if (bss->BSStype == IW_MODE_ADHOC &&
@@ -2985,25 +3214,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
priv->power_mode) {
priv->power_mode = 0;
priv->listen_interval = 1;
- atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
- atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
+ atmel_set_mib8(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
+ atmel_set_mib16(priv, Mac_Mgmt_Mib_Type,
+ MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
}
-
+
priv->operating_mode = bss->BSStype;
- priv->channel = bss->channel & 0x7f;
+ priv->channel = bss->channel & 0x7f;
priv->beacon_period = bss->beacon_period;
-
+
if (priv->preamble != bss->preamble) {
priv->preamble = bss->preamble;
- atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
+ atmel_set_mib8(priv, Local_Mib_Type,
+ LOCAL_MIB_PREAMBLE_TYPE, bss->preamble);
}
-
+
if (!priv->wep_is_on && bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
return;
}
-
+
if (priv->wep_is_on && !bss->UsingWEP) {
atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
priv->station_is_associated = 0;
@@ -3011,30 +3243,28 @@ void atmel_join_bss(struct atmel_private *priv, int bss_index)
}
atmel_enter_state(priv, STATION_STATE_JOINNING);
-
+
if (priv->operating_mode == IW_MODE_INFRA)
join(priv, BSS_TYPE_INFRASTRUCTURE);
- else
+ else
join(priv, BSS_TYPE_AD_HOC);
}
-
static void restart_search(struct atmel_private *priv)
{
int bss_index;
-
+
if (!priv->connect_to_any_BSS) {
atmel_scan(priv, 1);
} else {
priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80;
-
- if ((bss_index = retrieve_bss(priv)) != -1)
+
+ if ((bss_index = retrieve_bss(priv)) != -1)
atmel_join_bss(priv, bss_index);
else
atmel_scan(priv, 0);
-
- }
-}
+ }
+}
static void smooth_rssi(struct atmel_private *priv, u8 rssi)
{
@@ -3050,21 +3280,21 @@ static void smooth_rssi(struct atmel_private *priv, u8 rssi)
}
rssi = rssi * 100 / max_rssi;
- if((rssi + old) % 2)
- priv->wstats.qual.level = ((rssi + old)/2) + 1;
+ if ((rssi + old) % 2)
+ priv->wstats.qual.level = (rssi + old) / 2 + 1;
else
- priv->wstats.qual.level = ((rssi + old)/2);
+ priv->wstats.qual.level = (rssi + old) / 2;
priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
}
static void atmel_smooth_qual(struct atmel_private *priv)
{
- unsigned long time_diff = (jiffies - priv->last_qual)/HZ;
+ unsigned long time_diff = (jiffies - priv->last_qual) / HZ;
while (time_diff--) {
priv->last_qual += HZ;
- priv->wstats.qual.qual = priv->wstats.qual.qual/2;
- priv->wstats.qual.qual +=
+ priv->wstats.qual.qual = priv->wstats.qual.qual / 2;
+ priv->wstats.qual.qual +=
priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
priv->beacons_this_sec = 0;
}
@@ -3073,15 +3303,17 @@ static void atmel_smooth_qual(struct atmel_private *priv)
}
/* deals with incoming managment frames. */
-static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_hdr_4addr *header,
- u16 frame_len, u8 rssi)
+static void atmel_management_frame(struct atmel_private *priv,
+ struct ieee80211_hdr_4addr *header,
+ u16 frame_len, u8 rssi)
{
u16 subtype;
-
- switch (subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE) {
- case C80211_SUBTYPE_MGMT_BEACON :
+
+ subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
+ switch (subtype) {
+ case C80211_SUBTYPE_MGMT_BEACON:
case C80211_SUBTYPE_MGMT_ProbeResponse:
-
+
/* beacon frame has multiple variable-length fields -
never let an engineer loose with a data structure design. */
{
@@ -3099,7 +3331,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
u8 ds_length;
/* ds here */
} *beacon = (struct beacon_format *)priv->rx_buf;
-
+
u8 channel, rates_length, ssid_length;
u64 timestamp = le64_to_cpu(beacon->timestamp);
u16 beacon_interval = le16_to_cpu(beacon->interval);
@@ -3107,7 +3339,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
u8 *beaconp = priv->rx_buf;
ssid_length = beacon->ssid_length;
/* this blows chunks. */
- if (frame_len < 14 || frame_len < ssid_length + 15)
+ if (frame_len < 14 || frame_len < ssid_length + 15)
return;
rates_length = beaconp[beacon->ssid_length + 15];
if (frame_len < ssid_length + rates_length + 18)
@@ -3115,10 +3347,10 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
if (ssid_length > MAX_SSID_LENGTH)
return;
channel = beaconp[ssid_length + rates_length + 18];
-
+
if (priv->station_state == STATION_STATE_READY) {
smooth_rssi(priv, rssi);
- if (is_frame_from_current_bss(priv, header)) {
+ if (is_frame_from_current_bss(priv, header)) {
priv->beacons_this_sec++;
atmel_smooth_qual(priv);
if (priv->last_beacon_timestamp) {
@@ -3132,41 +3364,43 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
handle_beacon_probe(priv, capability, channel);
}
}
-
- if (priv->station_state == STATION_STATE_SCANNING )
- store_bss_info(priv, header, capability, beacon_interval, channel,
- rssi, ssid_length, &beacon->rates_el_id,
- subtype == C80211_SUBTYPE_MGMT_BEACON) ;
+
+ if (priv->station_state == STATION_STATE_SCANNING)
+ store_bss_info(priv, header, capability,
+ beacon_interval, channel, rssi,
+ ssid_length,
+ &beacon->rates_el_id,
+ subtype == C80211_SUBTYPE_MGMT_BEACON);
}
break;
-
+
case C80211_SUBTYPE_MGMT_Authentication:
if (priv->station_state == STATION_STATE_AUTHENTICATING)
authenticate(priv, frame_len);
-
+
break;
-
+
case C80211_SUBTYPE_MGMT_ASS_RESPONSE:
case C80211_SUBTYPE_MGMT_REASS_RESPONSE:
-
- if (priv->station_state == STATION_STATE_ASSOCIATING ||
+
+ if (priv->station_state == STATION_STATE_ASSOCIATING ||
priv->station_state == STATION_STATE_REASSOCIATING)
associate(priv, frame_len, subtype);
-
+
break;
case C80211_SUBTYPE_MGMT_DISASSOSIATION:
- if (priv->station_is_associated &&
- priv->operating_mode == IW_MODE_INFRA &&
+ if (priv->station_is_associated &&
+ priv->operating_mode == IW_MODE_INFRA &&
is_frame_from_current_bss(priv, header)) {
priv->station_was_associated = 0;
priv->station_is_associated = 0;
-
+
atmel_enter_state(priv, STATION_STATE_JOINNING);
join(priv, BSS_TYPE_INFRASTRUCTURE);
}
-
+
break;
case C80211_SUBTYPE_MGMT_Deauthentication:
@@ -3177,7 +3411,7 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
atmel_enter_state(priv, STATION_STATE_JOINNING);
join(priv, BSS_TYPE_INFRASTRUCTURE);
}
-
+
break;
}
}
@@ -3185,76 +3419,73 @@ static void atmel_management_frame(struct atmel_private *priv, struct ieee80211_
/* run when timer expires */
static void atmel_management_timer(u_long a)
{
- struct net_device *dev = (struct net_device *) a;
- struct atmel_private *priv = netdev_priv(dev);
- unsigned long flags;
-
- /* Check if the card has been yanked. */
- if (priv->card && priv->present_callback &&
- !(*priv->present_callback)(priv->card))
- return;
-
- spin_lock_irqsave(&priv->irqlock, flags);
-
- switch (priv->station_state) {
-
- case STATION_STATE_AUTHENTICATING:
- if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
- atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
- priv->station_is_associated = 0;
- priv->AuthenticationRequestRetryCnt = 0;
- restart_search(priv);
- } else {
- priv->AuthenticationRequestRetryCnt++;
- priv->CurrentAuthentTransactionSeqNum = 0x0001;
- mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
- send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
- }
-
- break;
+ struct net_device *dev = (struct net_device *) a;
+ struct atmel_private *priv = netdev_priv(dev);
+ unsigned long flags;
- case STATION_STATE_ASSOCIATING:
- if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
- atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
- priv->station_is_associated = 0;
- priv->AssociationRequestRetryCnt = 0;
- restart_search(priv);
- } else {
- priv->AssociationRequestRetryCnt++;
- mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
- send_association_request(priv, 0);
- }
+ /* Check if the card has been yanked. */
+ if (priv->card && priv->present_callback &&
+ !(*priv->present_callback)(priv->card))
+ return;
- break;
-
- case STATION_STATE_REASSOCIATING:
- if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
- atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
- priv->station_is_associated = 0;
- priv->ReAssociationRequestRetryCnt = 0;
- restart_search(priv);
- } else {
- priv->ReAssociationRequestRetryCnt++;
- mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
- send_association_request(priv, 1);
- }
+ spin_lock_irqsave(&priv->irqlock, flags);
+
+ switch (priv->station_state) {
+ case STATION_STATE_AUTHENTICATING:
+ if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->AuthenticationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->AuthenticationRequestRetryCnt++;
+ priv->CurrentAuthentTransactionSeqNum = 0x0001;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_authentication_request(priv, C80211_MGMT_AAN_OPENSYSTEM, NULL, 0);
+ }
break;
-
- default:
+
+ case STATION_STATE_ASSOCIATING:
+ if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->AssociationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->AssociationRequestRetryCnt++;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_association_request(priv, 0);
+ }
break;
- }
-
- spin_unlock_irqrestore(&priv->irqlock, flags);
+
+ case STATION_STATE_REASSOCIATING:
+ if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) {
+ atmel_enter_state(priv, STATION_STATE_MGMT_ERROR);
+ priv->station_is_associated = 0;
+ priv->ReAssociationRequestRetryCnt = 0;
+ restart_search(priv);
+ } else {
+ priv->ReAssociationRequestRetryCnt++;
+ mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
+ send_association_request(priv, 1);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ spin_unlock_irqrestore(&priv->irqlock, flags);
}
-
+
static void atmel_command_irq(struct atmel_private *priv)
{
u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET));
int fast_scan;
-
- if (status == CMD_STATUS_IDLE ||
+
+ if (status == CMD_STATUS_IDLE ||
status == CMD_STATUS_IN_PROGRESS)
return;
@@ -3266,20 +3497,20 @@ static void atmel_command_irq(struct atmel_private *priv)
atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS,
(u8 *)priv->CurrentBSSID, 6);
atmel_enter_state(priv, STATION_STATE_READY);
- }
+ }
break;
-
+
case CMD_Scan:
fast_scan = priv->fast_scan;
priv->fast_scan = 0;
-
+
if (status != CMD_STATUS_COMPLETE) {
atmel_scan(priv, 1);
} else {
int bss_index = retrieve_bss(priv);
if (bss_index != -1) {
atmel_join_bss(priv, bss_index);
- } else if (priv->operating_mode == IW_MODE_ADHOC &&
+ } else if (priv->operating_mode == IW_MODE_ADHOC &&
priv->SSID_size != 0) {
start(priv, BSS_TYPE_AD_HOC);
} else {
@@ -3289,16 +3520,16 @@ static void atmel_command_irq(struct atmel_private *priv)
priv->site_survey_state = SITE_SURVEY_COMPLETED;
}
break;
-
+
case CMD_SiteSurvey:
priv->fast_scan = 0;
-
+
if (status != CMD_STATUS_COMPLETE)
return;
-
+
priv->site_survey_state = SITE_SURVEY_COMPLETED;
if (priv->station_is_associated) {
- atmel_enter_state(priv, STATION_STATE_READY);
+ atmel_enter_state(priv, STATION_STATE_READY);
} else {
atmel_scan(priv, 1);
}
@@ -3312,16 +3543,15 @@ static void atmel_command_irq(struct atmel_private *priv)
} else {
priv->AuthenticationRequestRetryCnt = 0;
atmel_enter_state(priv, STATION_STATE_AUTHENTICATING);
-
+
mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES);
priv->CurrentAuthentTransactionSeqNum = 0x0001;
send_authentication_request(priv, C80211_MGMT_AAN_SHAREDKEY, NULL, 0);
}
return;
}
-
+
atmel_scan(priv, 1);
-
}
}
@@ -3333,20 +3563,20 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
if (priv->card_type == CARD_TYPE_SPI_FLASH)
atmel_set_gcr(priv->dev, GCR_REMAP);
-
+
/* wake up on-board processor */
atmel_clear_gcr(priv->dev, 0x0040);
atmel_write16(priv->dev, BSR, BSS_SRAM);
-
+
if (priv->card_type == CARD_TYPE_SPI_FLASH)
mdelay(100);
/* and wait for it */
- for (i = LOOP_RETRY_LIMIT; i; i--) {
+ for (i = LOOP_RETRY_LIMIT; i; i--) {
mr1 = atmel_read16(priv->dev, MR1);
mr3 = atmel_read16(priv->dev, MR3);
-
- if (mr3 & MAC_BOOT_COMPLETE)
+
+ if (mr3 & MAC_BOOT_COMPLETE)
break;
if (mr1 & MAC_BOOT_COMPLETE &&
priv->bus_type == BUS_TYPE_PCCARD)
@@ -3357,35 +3587,36 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name);
return 0;
}
-
+
if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) {
printk(KERN_ALERT "%s: card missing.\n", priv->dev->name);
return 0;
}
-
- /* now check for completion of MAC initialization through
- the FunCtrl field of the IFACE, poll MR1 to detect completion of
- MAC initialization, check completion status, set interrupt mask,
- enables interrupts and calls Tx and Rx initialization functions */
-
+
+ /* now check for completion of MAC initialization through
+ the FunCtrl field of the IFACE, poll MR1 to detect completion of
+ MAC initialization, check completion status, set interrupt mask,
+ enables interrupts and calls Tx and Rx initialization functions */
+
atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE);
-
- for (i = LOOP_RETRY_LIMIT; i; i--) {
+
+ for (i = LOOP_RETRY_LIMIT; i; i--) {
mr1 = atmel_read16(priv->dev, MR1);
mr3 = atmel_read16(priv->dev, MR3);
-
- if (mr3 & MAC_INIT_COMPLETE)
+
+ if (mr3 & MAC_INIT_COMPLETE)
break;
if (mr1 & MAC_INIT_COMPLETE &&
priv->bus_type == BUS_TYPE_PCCARD)
break;
}
-
+
if (i == 0) {
- printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name);
+ printk(KERN_ALERT "%s: MAC failed to initialise.\n",
+ priv->dev->name);
return 0;
}
-
+
/* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */
if ((mr3 & MAC_INIT_COMPLETE) &&
!(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) {
@@ -3398,9 +3629,9 @@ static int atmel_wakeup_firmware(struct atmel_private *priv)
return 0;
}
- atmel_copy_to_host(priv->dev, (unsigned char *)iface,
+ atmel_copy_to_host(priv->dev, (unsigned char *)iface,
priv->host_info_base, sizeof(*iface));
-
+
iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos);
iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size);
iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos);
@@ -3424,16 +3655,16 @@ static int probe_atmel_card(struct net_device *dev)
{
int rc = 0;
struct atmel_private *priv = netdev_priv(dev);
-
+
/* reset pccard */
- if (priv->bus_type == BUS_TYPE_PCCARD)
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
-
+
atmel_write16(dev, GCR, 0x0040);
mdelay(500);
-
+
if (atmel_read16(dev, MR2) == 0) {
- /* No stored firmware so load a small stub which just
+ /* No stored firmware so load a small stub which just
tells us the MAC address */
int i;
priv->card_type = CARD_TYPE_EEPROM;
@@ -3442,7 +3673,7 @@ static int probe_atmel_card(struct net_device *dev)
atmel_set_gcr(dev, GCR_REMAP);
atmel_clear_gcr(priv->dev, 0x0040);
atmel_write16(dev, BSR, BSS_SRAM);
- for (i = LOOP_RETRY_LIMIT; i; i--)
+ for (i = LOOP_RETRY_LIMIT; i; i--)
if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE)
break;
if (i == 0) {
@@ -3451,7 +3682,7 @@ static int probe_atmel_card(struct net_device *dev)
atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6);
/* got address, now squash it again until the network
interface is opened */
- if (priv->bus_type == BUS_TYPE_PCCARD)
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
rc = 1;
@@ -3459,7 +3690,7 @@ static int probe_atmel_card(struct net_device *dev)
} else if (atmel_read16(dev, MR4) == 0) {
/* Mac address easy in this case. */
priv->card_type = CARD_TYPE_PARALLEL_FLASH;
- atmel_write16(dev, BSR, 1);
+ atmel_write16(dev, BSR, 1);
atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6);
atmel_write16(dev, BSR, 0x200);
rc = 1;
@@ -3469,16 +3700,16 @@ static int probe_atmel_card(struct net_device *dev)
priv->card_type = CARD_TYPE_SPI_FLASH;
if (atmel_wakeup_firmware(priv)) {
atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6);
-
+
/* got address, now squash it again until the network
interface is opened */
- if (priv->bus_type == BUS_TYPE_PCCARD)
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(dev, GCR, 0x0060);
atmel_write16(dev, GCR, 0x0040);
rc = 1;
}
}
-
+
if (rc) {
if (dev->dev_addr[0] == 0xFF) {
u8 default_mac[] = {0x00,0x04, 0x25, 0x00, 0x00, 0x00};
@@ -3486,27 +3717,27 @@ static int probe_atmel_card(struct net_device *dev)
memcpy(dev->dev_addr, default_mac, 6);
}
}
-
+
return rc;
}
-static void build_wep_mib(struct atmel_private *priv)
/* Move the encyption information on the MIB structure.
This routine is for the pre-WPA firmware: later firmware has
a different format MIB and a different routine. */
+static void build_wep_mib(struct atmel_private *priv)
{
struct { /* NB this is matched to the hardware, don't change. */
- u8 wep_is_on;
+ u8 wep_is_on;
u8 default_key; /* 0..3 */
u8 reserved;
u8 exclude_unencrypted;
-
+
u32 WEPICV_error_count;
u32 WEP_excluded_count;
-
+
u8 wep_keys[MAX_ENCRYPTION_KEYS][13];
- u8 encryption_level; /* 0, 1, 2 */
- u8 reserved2[3];
+ u8 encryption_level; /* 0, 1, 2 */
+ u8 reserved2[3];
} mib;
int i;
@@ -3515,54 +3746,55 @@ static void build_wep_mib(struct atmel_private *priv)
if (priv->wep_key_len[priv->default_key] > 5)
mib.encryption_level = 2;
else
- mib.encryption_level = 1;
+ mib.encryption_level = 1;
} else {
mib.encryption_level = 0;
}
mib.default_key = priv->default_key;
mib.exclude_unencrypted = priv->exclude_unencrypted;
-
- for(i = 0; i < MAX_ENCRYPTION_KEYS; i++)
+
+ for (i = 0; i < MAX_ENCRYPTION_KEYS; i++)
memcpy(mib.wep_keys[i], priv->wep_keys[i], 13);
-
+
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
}
static void build_wpa_mib(struct atmel_private *priv)
{
- /* This is for the later (WPA enabled) firmware. */
+ /* This is for the later (WPA enabled) firmware. */
struct { /* NB this is matched to the hardware, don't change. */
u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE];
u8 receiver_address[6];
- u8 wep_is_on;
+ u8 wep_is_on;
u8 default_key; /* 0..3 */
u8 group_key;
u8 exclude_unencrypted;
u8 encryption_type;
u8 reserved;
-
+
u32 WEPICV_error_count;
u32 WEP_excluded_count;
-
+
u8 key_RSC[4][8];
} mib;
-
+
int i;
mib.wep_is_on = priv->wep_is_on;
mib.exclude_unencrypted = priv->exclude_unencrypted;
memcpy(mib.receiver_address, priv->CurrentBSSID, 6);
-
+
/* zero all the keys before adding in valid ones. */
memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value));
-
+
if (priv->wep_is_on) {
- /* There's a comment in the Atmel code to the effect that this is only valid
- when still using WEP, it may need to be set to something to use WPA */
+ /* There's a comment in the Atmel code to the effect that this
+ is only valid when still using WEP, it may need to be set to
+ something to use WPA */
memset(mib.key_RSC, 0, sizeof(mib.key_RSC));
-
+
mib.default_key = mib.group_key = 255;
for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) {
if (priv->wep_key_len[i] > 0) {
@@ -3570,12 +3802,12 @@ static void build_wpa_mib(struct atmel_private *priv)
if (i == priv->default_key) {
mib.default_key = i;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7;
- mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
+ mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite;
} else {
mib.group_key = i;
priv->group_cipher_suite = priv->pairwise_cipher_suite;
mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1;
- mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
+ mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite;
}
}
}
@@ -3583,47 +3815,48 @@ static void build_wpa_mib(struct atmel_private *priv)
mib.default_key = mib.group_key != 255 ? mib.group_key : 0;
if (mib.group_key == 255)
mib.group_key = mib.default_key;
-
+
}
-
+
atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib));
}
-
-static int reset_atmel_card(struct net_device *dev)
+
+static int reset_atmel_card(struct net_device *dev)
{
/* do everything necessary to wake up the hardware, including
waiting for the lightning strike and throwing the knife switch....
- set all the Mib values which matter in the card to match
+ set all the Mib values which matter in the card to match
their settings in the atmel_private structure. Some of these
can be altered on the fly, but many (WEP, infrastucture or ad-hoc)
can only be changed by tearing down the world and coming back through
here.
- This routine is also responsible for initialising some
- hardware-specific fields in the atmel_private structure,
+ This routine is also responsible for initialising some
+ hardware-specific fields in the atmel_private structure,
including a copy of the firmware's hostinfo stucture
which is the route into the rest of the firmare datastructures. */
struct atmel_private *priv = netdev_priv(dev);
u8 configuration;
-
+ int old_state = priv->station_state;
+
/* data to add to the firmware names, in priority order
this implemenents firmware versioning */
-
+
static char *firmware_modifier[] = {
"-wpa",
"",
NULL
};
-
+
/* reset pccard */
- if (priv->bus_type == BUS_TYPE_PCCARD)
+ if (priv->bus_type == BUS_TYPE_PCCARD)
atmel_write16(priv->dev, GCR, 0x0060);
-
+
/* stop card , disable interrupts */
atmel_write16(priv->dev, GCR, 0x0040);
-
+
if (priv->card_type == CARD_TYPE_EEPROM) {
/* copy in firmware if needed */
const struct firmware *fw_entry = NULL;
@@ -3636,13 +3869,13 @@ static int reset_atmel_card(struct net_device *dev)
"%s: card type is unknown: assuming at76c502 firmware is OK.\n",
dev->name);
printk(KERN_INFO
- "%s: if not, use the firmware= module parameter.\n",
+ "%s: if not, use the firmware= module parameter.\n",
dev->name);
strcpy(priv->firmware_id, "atmel_at76c502.bin");
}
if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) {
- printk(KERN_ALERT
- "%s: firmware %s is missing, cannot continue.\n",
+ printk(KERN_ALERT
+ "%s: firmware %s is missing, cannot continue.\n",
dev->name, priv->firmware_id);
return 0;
}
@@ -3654,7 +3887,7 @@ static int reset_atmel_card(struct net_device *dev)
while (fw_table[fw_index].fw_type != priv->firmware_type
&& fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
fw_index++;
-
+
/* construct the actual firmware file name */
if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
int i;
@@ -3669,24 +3902,24 @@ static int reset_atmel_card(struct net_device *dev)
}
}
if (!success) {
- printk(KERN_ALERT
- "%s: firmware %s is missing, cannot start.\n",
+ printk(KERN_ALERT
+ "%s: firmware %s is missing, cannot start.\n",
dev->name, priv->firmware_id);
priv->firmware_id[0] = '\0';
- return 0;
+ return 0;
}
}
-
+
fw = fw_entry->data;
len = fw_entry->size;
}
-
+
if (len <= 0x6000) {
atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, len);
atmel_set_gcr(priv->dev, GCR_REMAP);
} else {
- /* Remap */
+ /* Remap */
atmel_set_gcr(priv->dev, GCR_REMAP);
atmel_write16(priv->dev, BSR, BSS_IRAM);
atmel_copy_to_card(priv->dev, 0, fw, 0x6000);
@@ -3708,45 +3941,45 @@ static int reset_atmel_card(struct net_device *dev)
the 3com broken-ness filter. */
priv->use_wpa = (priv->host_info.major_version == 4);
priv->radio_on_broken = (priv->host_info.major_version == 5);
-
+
/* unmask all irq sources */
atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff);
-
+
/* int Tx system and enable Tx */
atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0);
atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0);
atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0);
- priv->tx_desc_free = priv->host_info.tx_desc_count;
- priv->tx_desc_head = 0;
- priv->tx_desc_tail = 0;
+ priv->tx_desc_free = priv->host_info.tx_desc_count;
+ priv->tx_desc_head = 0;
+ priv->tx_desc_tail = 0;
priv->tx_desc_previous = 0;
priv->tx_free_mem = priv->host_info.tx_buff_size;
- priv->tx_buff_head = 0;
- priv->tx_buff_tail = 0;
-
- configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
- atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
+ priv->tx_buff_head = 0;
+ priv->tx_buff_tail = 0;
+
+ configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_TxENABLE);
/* init Rx system and enable */
priv->rx_desc_head = 0;
-
- configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
- atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
+
+ configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET));
+ atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET),
configuration | FUNC_CTRL_RxENABLE);
-
+
if (!priv->radio_on_broken) {
- if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
+ if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) ==
CMD_STATUS_REJECTED_RADIO_OFF) {
- printk(KERN_INFO
+ printk(KERN_INFO
"%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n",
dev->name);
return 0;
}
}
-
+
/* set up enough MIB values to run. */
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate);
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_TX_PROMISCUOUS_POS, PROM_MODE_OFF);
@@ -3755,7 +3988,7 @@ static int reset_atmel_card(struct net_device *dev)
atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry);
atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry);
atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble);
- atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
+ atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS,
priv->dev->dev_addr, 6);
atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE);
atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1);
@@ -3766,42 +3999,55 @@ static int reset_atmel_card(struct net_device *dev)
build_wpa_mib(priv);
else
build_wep_mib(priv);
-
+
+ if (old_state == STATION_STATE_READY)
+ {
+ union iwreq_data wrqu;
+
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+ }
+
return 1;
}
-static void atmel_send_command(struct atmel_private *priv, int command, void *cmd, int cmd_size)
+static void atmel_send_command(struct atmel_private *priv, int command,
+ void *cmd, int cmd_size)
{
if (cmd)
- atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
+ atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET),
cmd, cmd_size);
-
+
atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command);
atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0);
}
-
-static int atmel_send_command_wait(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)
{
int i, status;
-
+
atmel_send_command(priv, command, cmd, cmd_size);
-
+
for (i = 5000; i; i--) {
status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET));
- if (status != CMD_STATUS_IDLE &&
+ if (status != CMD_STATUS_IDLE &&
status != CMD_STATUS_IN_PROGRESS)
break;
udelay(20);
}
-
+
if (i == 0) {
printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name);
status = CMD_STATUS_HOST_ERROR;
- } else {
+ } else {
if (command != CMD_EnableRadio)
status = CMD_STATUS_COMPLETE;
}
-
+
return status;
}
@@ -3827,7 +4073,8 @@ static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 dat
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1);
}
-static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 data)
+static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index,
+ u16 data)
{
struct get_set_mib m;
m.type = type;
@@ -3839,7 +4086,8 @@ static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, u16 d
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2);
}
-static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index,
+ u8 *data, int data_len)
{
struct get_set_mib m;
m.type = type;
@@ -3848,23 +4096,24 @@ static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, u8 *dat
if (data_len > MIB_MAX_DATA_BYTES)
printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
-
+
memcpy(m.data, data, data_len);
atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
}
-static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, u8 *data, int data_len)
+static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index,
+ u8 *data, int data_len)
{
struct get_set_mib m;
m.type = type;
m.size = data_len;
m.index = index;
-
+
if (data_len > MIB_MAX_DATA_BYTES)
printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name);
-
+
atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len);
- atmel_copy_to_host(priv->dev, data,
+ atmel_copy_to_host(priv->dev, data,
atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len);
}
@@ -3873,11 +4122,12 @@ static void atmel_writeAR(struct net_device *dev, u16 data)
int i;
outw(data, dev->base_addr + AR);
/* Address register appears to need some convincing..... */
- for (i = 0; data != inw(dev->base_addr + AR) && i<10; i++)
+ for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++)
outw(data, dev->base_addr + AR);
}
-static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *src, u16 len)
+static void atmel_copy_to_card(struct net_device *dev, u16 dest,
+ unsigned char *src, u16 len)
{
int i;
atmel_writeAR(dev, dest);
@@ -3894,7 +4144,8 @@ static void atmel_copy_to_card(struct net_device *dev, u16 dest, unsigned char *
atmel_write8(dev, DR, *src);
}
-static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, u16 src, u16 len)
+static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest,
+ u16 src, u16 len)
{
int i;
atmel_writeAR(dev, src);
@@ -3930,22 +4181,24 @@ static int atmel_lock_mac(struct atmel_private *priv)
break;
udelay(20);
}
-
- if (!i) return 0; /* timed out */
-
+
+ if (!i)
+ return 0; /* timed out */
+
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1);
if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) {
atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0);
- if (!j--) return 0; /* timed out */
+ if (!j--)
+ return 0; /* timed out */
goto retry;
}
-
+
return 1;
}
static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
{
- atmel_writeAR(priv->dev, pos);
+ atmel_writeAR(priv->dev, pos);
atmel_write16(priv->dev, DR, data); /* card is little-endian */
atmel_write16(priv->dev, DR, data >> 16);
}
@@ -4017,9 +4270,9 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
serial output, since SO is normally high. But it
does cause 8 clock cycles and thus 8 bits to be
clocked in to the chip. See Atmel's SPI
- controller (e.g. AT91M55800) timing and 4K
+ controller (e.g. AT91M55800) timing and 4K
SPI EEPROM manuals */
-
+
.set NVRAM_SCRATCH, 0x02000100 /* arbitrary area for scratchpad memory */
.set NVRAM_IMAGE, 0x02000200
.set NVRAM_LENGTH, 0x0200
@@ -4032,24 +4285,24 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data)
.set MR4, 0xC
RESET_VECTOR:
b RESET_HANDLER
-UNDEF_VECTOR:
+UNDEF_VECTOR:
b HALT1
-SWI_VECTOR:
+SWI_VECTOR:
b HALT1
-IABORT_VECTOR:
+IABORT_VECTOR:
b HALT1
-DABORT_VECTOR:
-RESERVED_VECTOR:
+DABORT_VECTOR:
+RESERVED_VECTOR:
b HALT1
-IRQ_VECTOR:
+IRQ_VECTOR:
b HALT1
-FIQ_VECTOR:
+FIQ_VECTOR:
b HALT1
HALT1: b HALT1
RESET_HANDLER:
mov r0, #CPSR_INITIAL
msr CPSR_c, r0 /* This is probably unnecessary */
-
+
/* I'm guessing this is initializing clock generator electronics for SPI */
ldr r0, =SPI_CGEN_BASE
mov r1, #0
@@ -4061,7 +4314,7 @@ RESET_HANDLER:
str r1, [r0, #28]
mov r1, #1
str r1, [r0, #8]
-
+
ldr r0, =MRBASE
mov r1, #0
strh r1, [r0, #MR1]
@@ -4094,7 +4347,7 @@ GET_WHOLE_NVRAM:
ldmia sp!, {lr}
bx lr
.endfunc
-
+
.func Get_MAC_Addr, GET_MAC_ADDR
GET_MAC_ADDR:
stmdb sp!, {lr}
@@ -4110,13 +4363,13 @@ GET_MAC_ADDR:
.func Delay9, DELAY9
DELAY9:
adds r0, r0, r0, LSL #3 /* r0 = r0 * 9 */
-DELAYLOOP:
+DELAYLOOP:
beq DELAY9_done
subs r0, r0, #1
b DELAYLOOP
-DELAY9_done:
+DELAY9_done:
bx lr
-.endfunc
+.endfunc
.func SP_Init, SP_INIT
SP_INIT:
@@ -4145,26 +4398,26 @@ SP_INIT:
ldr r0, [r0, #SP_RDR]
bx lr
.endfunc
-.func NVRAM_Init, NVRAM_INIT
+.func NVRAM_Init, NVRAM_INIT
NVRAM_INIT:
ldr r1, =SP_BASE
ldr r0, [r1, #SP_RDR]
mov r0, #NVRAM_CMD_RDSR
str r0, [r1, #SP_TDR]
-SP_loop1:
+SP_loop1:
ldr r0, [r1, #SP_SR]
tst r0, #SP_TDRE
beq SP_loop1
mov r0, #SPI_8CLOCKS
- str r0, [r1, #SP_TDR]
-SP_loop2:
+ str r0, [r1, #SP_TDR]
+SP_loop2:
ldr r0, [r1, #SP_SR]
tst r0, #SP_TDRE
beq SP_loop2
ldr r0, [r1, #SP_RDR]
-SP_loop3:
+SP_loop3:
ldr r0, [r1, #SP_SR]
tst r0, #SP_RDRF
beq SP_loop3
@@ -4173,7 +4426,7 @@ SP_loop3:
and r0, r0, #255
bx lr
.endfunc
-
+
.func NVRAM_Xfer, NVRAM_XFER
/* r0 = dest address */
/* r1 = not used */
@@ -4185,11 +4438,11 @@ NVRAM_XFER:
mov r4, r3 /* save r3 (length) */
mov r0, r2, LSR #5 /* SPI memories put A8 in the command field */
and r0, r0, #8
- add r0, r0, #NVRAM_CMD_READ
+ add r0, r0, #NVRAM_CMD_READ
ldr r1, =NVRAM_SCRATCH
strb r0, [r1, #0] /* save command in NVRAM_SCRATCH[0] */
strb r2, [r1, #1] /* save low byte of source address in NVRAM_SCRATCH[1] */
-_local1:
+_local1:
bl NVRAM_INIT
tst r0, #NVRAM_SR_RDY
bne _local1
@@ -4211,7 +4464,7 @@ NVRAM_XFER2:
cmp r0, #0
bls _local2
ldr r5, =NVRAM_SCRATCH
-_local4:
+_local4:
ldrb r6, [r5, r3]
str r6, [r4, #SP_TDR]
_local3:
@@ -4225,7 +4478,7 @@ _local2:
mov r3, #SPI_8CLOCKS
str r3, [r4, #SP_TDR]
ldr r0, [r4, #SP_RDR]
-_local5:
+_local5:
ldr r0, [r4, #SP_SR]
tst r0, #SP_RDRF
beq _local5
@@ -4233,12 +4486,12 @@ _local5:
mov r0, #0
cmp r2, #0 /* r2 is # of bytes to copy in */
bls _local6
-_local7:
+_local7:
ldr r5, [r4, #SP_SR]
tst r5, #SP_TDRE
beq _local7
str r3, [r4, #SP_TDR] /* r3 has SPI_8CLOCKS */
-_local8:
+_local8:
ldr r5, [r4, #SP_SR]
tst r5, #SP_RDRF
beq _local8
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 17d1fd90f832..d6f4a5a3e55a 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -93,8 +93,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
static void atmel_config(dev_link_t *link);
static void atmel_release(dev_link_t *link);
-static int atmel_event(event_t event, int priority,
- event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
@@ -102,8 +100,7 @@ static int atmel_event(event_t event, int priority,
needed to manage one actual PCMCIA card.
*/
-static dev_link_t *atmel_attach(void);
-static void atmel_detach(dev_link_t *);
+static void atmel_detach(struct pcmcia_device *p_dev);
/*
You'll also need to prototype all the functions that will actually
@@ -113,14 +110,6 @@ static void atmel_detach(dev_link_t *);
*/
/*
- 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 = "atmel_cs";
-
-/*
A linked list of "instances" of the atmelnet device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
@@ -130,15 +119,7 @@ static dev_info_t dev_info = "atmel_cs";
device numbers are used to derive the corresponding array index.
*/
-static dev_link_t *dev_list = NULL;
-
/*
- A dev_link_t structure has fields for most things that are needed
- to keep track of a socket, but there will usually be some device
- specific information that also needs to be kept track of. The
- 'priv' pointer in a dev_link_t structure can be used to point to
- a device-specific private data structure, like this.
-
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
@@ -171,27 +152,25 @@ typedef struct local_info_t {
======================================================================*/
-static dev_link_t *atmel_attach(void)
+static int atmel_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
- int ret;
-
+
DEBUG(0, "atmel_attach()\n");
/* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) {
printk(KERN_ERR "atmel_cs: no memory for new device\n");
- return NULL;
+ return -ENOMEM;
}
-
+
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL;
-
+
/*
General socket configuration defaults can go here. In this
client, we assume very little, and rely on the CIS for almost
@@ -202,30 +181,23 @@ static dev_link_t *atmel_attach(void)
link->conf.Attributes = 0;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
-
+
/* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) {
printk(KERN_ERR "atmel_cs: no memory for new device\n");
kfree (link);
- return NULL;
+ return -ENOMEM;
}
link->priv = local;
-
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- atmel_detach(link);
- return NULL;
- }
-
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ atmel_config(link);
+
+ return 0;
} /* atmel_attach */
/*======================================================================
@@ -237,27 +209,15 @@ static dev_link_t *atmel_attach(void)
======================================================================*/
-static void atmel_detach(dev_link_t *link)
+static void atmel_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
-
+ dev_link_t *link = dev_to_instance(p_dev);
+
DEBUG(0, "atmel_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
atmel_release(link);
-
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
- /* Unlink device structure, free pieces */
- *linkp = link->next;
kfree(link->priv);
kfree(link);
}
@@ -477,60 +437,34 @@ static void atmel_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received.
+static int atmel_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ local_info_t *local = link->priv;
- When a CARD_REMOVAL event is received, we immediately set a
- private flag to block future accesses to this device. All the
- functions that actually access the device should check this flag
- to make sure the card is still present.
-
- ======================================================================*/
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ netif_device_detach(local->eth_dev);
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
-static int atmel_event(event_t event, int priority,
- event_callback_args_t *args)
+static int atmel_resume(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
-
- DEBUG(1, "atmel_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- atmel_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- atmel_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- netif_device_detach(local->eth_dev);
- 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) {
- pcmcia_request_configuration(link->handle, &link->conf);
- atmel_open(local->eth_dev);
- netif_device_attach(local->eth_dev);
- }
- break;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ atmel_open(local->eth_dev);
+ netif_device_attach(local->eth_dev);
}
+
return 0;
-} /* atmel_event */
+}
/*====================================================================*/
/* We use the driver_info field to store the correct firmware type for a card. */
@@ -581,10 +515,11 @@ static struct pcmcia_driver atmel_driver = {
.drv = {
.name = "atmel_cs",
},
- .attach = atmel_attach,
- .event = atmel_event,
- .detach = atmel_detach,
+ .probe = atmel_attach,
+ .remove = atmel_detach,
.id_table = atmel_ids,
+ .suspend = atmel_suspend,
+ .resume = atmel_resume,
};
static int atmel_cs_init(void)
@@ -595,7 +530,6 @@ static int atmel_cs_init(void)
static void atmel_cs_cleanup(void)
{
pcmcia_unregister_driver(&atmel_driver);
- BUG_ON(dev_list != NULL);
}
/*
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 56f41c714d38..c8f6286dd35f 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -26,11 +26,25 @@ config HOSTAP_FIRMWARE
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.
+ download. This option by itself only enables downloading to the
+ volatile memory, i.e. the card RAM. This option is required to
+ support cards that don't have firmware in flash, such as D-Link
+ DWL-520 rev E and D-Link DWL-650 rev P.
- Firmware image downloading needs user space tool, prism2_srec. It is
- available from http://hostap.epitest.fi/.
+ Firmware image downloading needs a user space tool, prism2_srec.
+ It is available from http://hostap.epitest.fi/.
+
+config HOSTAP_FIRMWARE_NVRAM
+ bool "Support for non-volatile firmware download"
+ depends on HOSTAP_FIRMWARE
+ ---help---
+ Allow Host AP driver to write firmware images to the non-volatile
+ card memory, i.e. flash memory that survives power cycling.
+ Enable this option if you want to be able to change card firmware
+ permanently.
+
+ Firmware image downloading needs a 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"
diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile
index fc62235bfc24..b8e41a702c00 100644
--- a/drivers/net/wireless/hostap/Makefile
+++ b/drivers/net/wireless/hostap/Makefile
@@ -1,3 +1,5 @@
+hostap-y := hostap_80211_rx.o hostap_80211_tx.o hostap_ap.o hostap_info.o \
+ hostap_ioctl.o hostap_main.o hostap_proc.o
obj-$(CONFIG_HOSTAP) += hostap.o
obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index 5fac89b8ce3a..5e63765219fe 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -1,6 +1,15 @@
#ifndef HOSTAP_H
#define HOSTAP_H
+#include <linux/ethtool.h>
+
+#include "hostap_wlan.h"
+#include "hostap_ap.h"
+
+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]))
+
/* hostap.c */
extern struct proc_dir_entry *hostap_proc;
@@ -40,6 +49,26 @@ 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);
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked);
+int prism2_wds_del(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked, int do_not_remove);
+
+
+/* hostap_ap.c */
+
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac);
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
+void ap_control_kickall(struct ap_data *ap);
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt);
+int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
+ struct iw_quality qual[], int buf_size,
+ int aplist);
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer);
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param);
/* hostap_proc.c */
@@ -54,4 +83,12 @@ void hostap_info_init(local_info_t *local);
void hostap_info_process(local_info_t *local, struct sk_buff *skb);
+/* hostap_ioctl.c */
+
+extern const struct iw_handler_def hostap_iw_handler_def;
+extern struct ethtool_ops prism2_ethtool_ops;
+
+int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+
+
#endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index bf506f50d722..1fc72fe511e9 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_80211_H
#define HOSTAP_80211_H
+#include <linux/types.h>
+#include <net/ieee80211_crypt.h>
+
struct hostap_ieee80211_mgmt {
u16 frame_control;
u16 duration;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index ffac50899454..7e04dc94b3bc 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,7 +1,18 @@
#include <linux/etherdevice.h>
+#include <net/ieee80211_crypt.h>
#include "hostap_80211.h"
#include "hostap.h"
+#include "hostap_ap.h"
+
+/* 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) */
void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats)
@@ -435,7 +446,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
}
-static inline int
+static int
hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
struct hostap_80211_rx_status *rx_stats, u16 type,
u16 stype)
@@ -499,7 +510,7 @@ hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ) */
-static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
+static struct net_device *prism2_rx_get_wds(local_info_t *local,
u8 *addr)
{
struct hostap_interface *iface = NULL;
@@ -519,7 +530,7 @@ static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
}
-static inline int
+static int
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
u16 fc, struct net_device **wds)
{
@@ -615,7 +626,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
/* Called only as a tasklet (software IRQ) */
-static inline int
+static int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
struct ieee80211_crypt_data *crypt)
{
@@ -654,7 +665,7 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ) */
-static inline int
+static int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
int keyidx, struct ieee80211_crypt_data *crypt)
{
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 9d24f8a38ac5..4a85e63906f1 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -1,3 +1,18 @@
+#include "hostap_80211.h"
+#include "hostap_common.h"
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
+/* 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) */
+
void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
struct ieee80211_hdr_4addr *hdr;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 9da94ab7f05f..753a1de6664b 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -16,6 +16,14 @@
* (8802.11: 5.5)
*/
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
+
static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL,
DEF_INTS };
module_param_array(other_ap_policy, int, NULL, 0444);
@@ -360,8 +368,7 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
}
-static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct mac_entry *entry;
@@ -380,8 +387,7 @@ static int ap_control_add_mac(struct mac_restrictions *mac_restrictions,
}
-static int ap_control_del_mac(struct mac_restrictions *mac_restrictions,
- u8 *mac)
+int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
{
struct list_head *ptr;
struct mac_entry *entry;
@@ -433,7 +439,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
}
-static void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
+void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
{
struct list_head *ptr, *n;
struct mac_entry *entry;
@@ -454,8 +460,7 @@ 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)
+int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac)
{
struct sta_info *sta;
u16 resp;
@@ -486,7 +491,7 @@ static int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev,
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
-static void ap_control_kickall(struct ap_data *ap)
+void ap_control_kickall(struct ap_data *ap)
{
struct list_head *ptr, *n;
struct sta_info *sta;
@@ -2321,9 +2326,9 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
}
-static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
- struct iw_quality qual[], int buf_size,
- int aplist)
+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;
@@ -2363,7 +2368,7 @@ static int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
/* 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)
+int prism2_ap_translate_scan(struct net_device *dev, char *buffer)
{
struct hostap_interface *iface;
local_info_t *local;
@@ -2608,8 +2613,7 @@ static int prism2_hostapd_sta_clear_stats(struct ap_data *ap,
}
-static int prism2_hostapd(struct ap_data *ap,
- struct prism2_hostapd_param *param)
+int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param)
{
switch (param->cmd) {
case PRISM2_HOSTAPD_FLUSH:
@@ -3207,8 +3211,8 @@ void hostap_update_rates(local_info_t *local)
}
-static void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt)
+void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
+ struct ieee80211_crypt_data ***crypt)
{
struct sta_info *sta;
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 6d00df69c2e3..2fa2452b6b07 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -1,6 +1,8 @@
#ifndef HOSTAP_AP_H
#define HOSTAP_AP_H
+#include "hostap_80211.h"
+
/* AP data structures for STAs */
/* maximum number of frames to buffer per STA */
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 6f4fa9dc308f..01624005d808 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -1,6 +1,9 @@
#ifndef HOSTAP_COMMON_H
#define HOSTAP_COMMON_H
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
#define BIT(x) (1 << (x))
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 7ed3425d08c1..c090a5aebb58 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -21,15 +21,10 @@
#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 */
+/* Allow kernel configuration to enable non-volatile download support. */
+#ifdef CONFIG_HOSTAP_FIRMWARE_NVRAM
+#define PRISM2_NON_VOLATILE_DOWNLOAD
+#endif
/* Save low-level I/O for debugging. This should not be enabled in normal use.
*/
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 2643976a6677..8bc0b528548f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -25,7 +25,6 @@
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 "
@@ -203,10 +202,9 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
-static void prism2_detach(dev_link_t *link);
+static void prism2_detach(struct pcmcia_device *p_dev);
static void prism2_release(u_long arg);
-static int prism2_event(event_t event, int priority,
- event_callback_args_t *args);
+static int prism2_config(dev_link_t *link);
static int prism2_pccard_card_present(local_info_t *local)
@@ -503,15 +501,13 @@ static struct prism2_helper_functions prism2_pccard_funcs =
/* allocate local data and register with CardServices
* initialize dev_link structure, but do not configure the card yet */
-static dev_link_t *prism2_attach(void)
+static int prism2_attach(struct pcmcia_device *p_dev)
{
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
if (link == NULL)
- return NULL;
+ return -ENOMEM;
memset(link, 0, sizeof(dev_link_t));
@@ -519,50 +515,27 @@ static dev_link_t *prism2_attach(void)
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;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ if (prism2_config(link))
+ PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
+
+ return 0;
}
-static void prism2_detach(dev_link_t *link)
+static void prism2_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
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 hostap_cs_priv *hw_priv;
@@ -846,84 +819,58 @@ static void prism2_release(u_long arg)
PDEBUG(DEBUG_FLOW, "release - done\n");
}
-
-static int prism2_event(event_t event, int priority,
- event_callback_args_t *args)
+static int hostap_cs_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
+
+ link->state |= DEV_SUSPEND;
+
if (link->state & DEV_CONFIG) {
struct hostap_interface *iface = netdev_priv(dev);
if (iface && iface->local)
dev_open = iface->local->num_dev_open > 0;
- }
-
- 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) {
+ if (dev_open) {
netif_stop_queue(dev);
netif_device_detach(dev);
- prism2_release((u_long) link);
}
- break;
+ prism2_suspend(dev);
+ pcmcia_release_configuration(link->handle);
+ }
- 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 (dev_open) {
- netif_stop_queue(dev);
- netif_device_detach(dev);
- }
- prism2_suspend(dev);
- pcmcia_release_configuration(link->handle);
- }
- break;
+ return 0;
+}
- 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, dev_open ? 0 : 1);
- if (dev_open) {
- netif_device_attach(dev);
- netif_start_queue(dev);
- }
- }
- break;
+static int hostap_cs_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = (struct net_device *) link->priv;
+ int dev_open = 0;
- default:
- PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
- dev_info, event);
- break;
+ PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ struct hostap_interface *iface = netdev_priv(dev);
+ if (iface && iface->local)
+ dev_open = iface->local->num_dev_open > 0;
+
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ prism2_hw_shutdown(dev, 1);
+ prism2_hw_config(dev, dev_open ? 0 : 1);
+ if (dev_open) {
+ netif_device_attach(dev);
+ netif_start_queue(dev);
+ }
}
+
return 0;
}
-
static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300),
@@ -982,11 +929,12 @@ static struct pcmcia_driver hostap_driver = {
.drv = {
.name = "hostap_cs",
},
- .attach = prism2_attach,
- .detach = prism2_detach,
+ .probe = prism2_attach,
+ .remove = prism2_detach,
.owner = THIS_MODULE,
- .event = prism2_event,
.id_table = hostap_cs_ids,
+ .suspend = hostap_cs_suspend,
+ .resume = hostap_cs_resume,
};
static int __init init_prism2_pccard(void)
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index abfae7fedebc..b1f142d9e232 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -253,7 +253,7 @@ static void prism2_clear_cmd_queue(local_info_t *local)
* @dev: pointer to net_device
* @entry: Prism2 command queue entry to be issued
*/
-static inline int hfa384x_cmd_issue(struct net_device *dev,
+static int hfa384x_cmd_issue(struct net_device *dev,
struct hostap_cmd_queue *entry)
{
struct hostap_interface *iface;
@@ -743,7 +743,7 @@ static void prism2_cmd_ev(struct net_device *dev)
}
-static inline int hfa384x_wait_offset(struct net_device *dev, u16 o_off)
+static 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;
@@ -1904,7 +1904,7 @@ fail:
* 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)
+static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg)
{
#ifdef EXTRA_FID_READ_TESTS
u16 val, val2, val3;
@@ -2581,7 +2581,7 @@ static void prism2_ev_tick(struct net_device *dev)
/* Called only from hardware IRQ */
-static inline void prism2_check_magic(local_info_t *local)
+static 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
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 5aa998fdf1c4..50f72d831cf4 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -1,5 +1,8 @@
/* Host AP driver Info Frame processing (part of hostap.o module) */
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
/* Called only as a tasklet (software IRQ) */
static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf,
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 2617d70bcda9..f3e0ce1ee037 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1,11 +1,13 @@
/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */
-#ifdef in_atomic
-/* Get kernel_locked() for in_atomic() */
+#include <linux/types.h>
#include <linux/smp_lock.h>
-#endif
#include <linux/ethtool.h>
+#include <net/ieee80211_crypt.h>
+#include "hostap_wlan.h"
+#include "hostap.h"
+#include "hostap_ap.h"
static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
{
@@ -3910,7 +3912,7 @@ static void prism2_get_drvinfo(struct net_device *dev,
local->sta_fw_ver & 0xff);
}
-static struct ethtool_ops prism2_ethtool_ops = {
+struct ethtool_ops prism2_ethtool_ops = {
.get_drvinfo = prism2_get_drvinfo
};
@@ -3985,7 +3987,7 @@ static const iw_handler prism2_private_handler[] =
(iw_handler) prism2_ioctl_priv_readmif, /* 3 */
};
-static const struct iw_handler_def hostap_iw_handler_def =
+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),
diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap_main.c
index 3d2ea61033be..8dd4c4446a64 100644
--- a/drivers/net/wireless/hostap/hostap.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -24,6 +24,7 @@
#include <linux/kmod.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
+#include <linux/etherdevice.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
#include <net/ieee80211_crypt.h>
@@ -47,57 +48,6 @@ MODULE_VERSION(PRISM2_VERSION);
#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,
@@ -196,8 +146,8 @@ static inline int prism2_wds_special_addr(u8 *addr)
}
-static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
- int rtnl_locked)
+int prism2_wds_add(local_info_t *local, u8 *remote_addr,
+ int rtnl_locked)
{
struct net_device *dev;
struct list_head *ptr;
@@ -258,8 +208,8 @@ static int prism2_wds_add(local_info_t *local, u8 *remote_addr,
}
-static int prism2_wds_del(local_info_t *local, u8 *remote_addr,
- int rtnl_locked, int do_not_remove)
+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;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index a0a4cbd4937a..d1d8ce022e63 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -1,5 +1,12 @@
/* /proc routines for Host AP driver */
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <net/ieee80211_crypt.h>
+
+#include "hostap_wlan.h"
+#include "hostap.h"
+
#define PROC_LIMIT (PAGE_SIZE - 80)
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index cfd801559492..87a54aa6f4dd 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -1,6 +1,10 @@
#ifndef HOSTAP_WLAN_H
#define HOSTAP_WLAN_H
+#include <linux/wireless.h>
+#include <linux/netdevice.h>
+#include <net/iw_handler.h>
+
#include "hostap_config.h"
#include "hostap_common.h"
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 77d2a21d4cd0..8bf02763b5c7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -175,7 +175,7 @@ that only one external action is invoked at a time.
#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation"
/* Debugging stuff */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
#define CONFIG_IPW2100_RX_DEBUG /* Reception debugging */
#endif
@@ -208,7 +208,7 @@ MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
static u32 ipw2100_debug_level = IPW_DL_NONE;
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
#define IPW_DEBUG(level, message...) \
do { \
if (ipw2100_debug_level & (level)) { \
@@ -219,9 +219,9 @@ do { \
} while (0)
#else
#define IPW_DEBUG(level, message...) do {} while (0)
-#endif /* CONFIG_IPW_DEBUG */
+#endif /* CONFIG_IPW2100_DEBUG */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
static const char *command_types[] = {
"undefined",
"unused", /* HOST_ATTENTION */
@@ -411,7 +411,7 @@ 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,
+static void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
const u8 * buf)
{
u32 aligned_addr;
@@ -449,7 +449,7 @@ static inline void write_nic_memory(struct net_device *dev, u32 addr, u32 len,
*buf);
}
-static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
+static void read_nic_memory(struct net_device *dev, u32 addr, u32 len,
u8 * buf)
{
u32 aligned_addr;
@@ -657,7 +657,7 @@ static void printk_buf(int level, const u8 * data, u32 len)
#define MAX_RESET_BACKOFF 10
-static inline void schedule_reset(struct ipw2100_priv *priv)
+static void schedule_reset(struct ipw2100_priv *priv)
{
unsigned long now = get_seconds();
@@ -1130,7 +1130,7 @@ static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv)
write_register(priv->net_dev, IPW_REG_GPIO, reg);
}
-static inline int rf_kill_active(struct ipw2100_priv *priv)
+static int rf_kill_active(struct ipw2100_priv *priv)
{
#define MAX_RF_KILL_CHECKS 5
#define RF_KILL_CHECK_DELAY 40
@@ -2081,7 +2081,7 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
priv->status &= ~STATUS_SCANNING;
}
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
#define IPW2100_HANDLER(v, f) { v, f, # v }
struct ipw2100_status_indicator {
int status;
@@ -2094,7 +2094,7 @@ struct ipw2100_status_indicator {
int status;
void (*cb) (struct ipw2100_priv * priv, u32 status);
};
-#endif /* CONFIG_IPW_DEBUG */
+#endif /* CONFIG_IPW2100_DEBUG */
static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status)
{
@@ -2149,7 +2149,7 @@ static void isr_status_change(struct ipw2100_priv *priv, int status)
static void isr_rx_complete_command(struct ipw2100_priv *priv,
struct ipw2100_cmd_header *cmd)
{
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
if (cmd->host_command_reg < ARRAY_SIZE(command_types)) {
IPW_DEBUG_HC("Command completed '%s (%d)'\n",
command_types[cmd->host_command_reg],
@@ -2167,7 +2167,7 @@ static void isr_rx_complete_command(struct ipw2100_priv *priv,
wake_up_interruptible(&priv->wait_command_queue);
}
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
static const char *frame_types[] = {
"COMMAND_STATUS_VAL",
"STATUS_CHANGE_VAL",
@@ -2177,7 +2177,7 @@ static const char *frame_types[] = {
};
#endif
-static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,
+static int ipw2100_alloc_skb(struct ipw2100_priv *priv,
struct ipw2100_rx_packet *packet)
{
packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx));
@@ -2201,7 +2201,7 @@ static inline int ipw2100_alloc_skb(struct ipw2100_priv *priv,
#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)
+static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
{
int i;
if (priv->snapshot[0])
@@ -2221,7 +2221,7 @@ static inline int ipw2100_snapshot_alloc(struct ipw2100_priv *priv)
return 1;
}
-static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
+static void ipw2100_snapshot_free(struct ipw2100_priv *priv)
{
int i;
if (!priv->snapshot[0])
@@ -2231,7 +2231,7 @@ static inline void ipw2100_snapshot_free(struct ipw2100_priv *priv)
priv->snapshot[0] = NULL;
}
-static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
+static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
size_t len, int mode)
{
u32 i, j;
@@ -2288,9 +2288,9 @@ static inline u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf,
static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH];
#endif
-static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
+static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
{
-#ifdef CONFIG_IPW_DEBUG_C3
+#ifdef CONFIG_IPW2100_DEBUG_C3
struct ipw2100_status *status = &priv->status_queue.drv[i];
u32 match, reg;
int j;
@@ -2312,7 +2312,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
}
#endif
-#ifdef CONFIG_IPW_DEBUG_C3
+#ifdef CONFIG_IPW2100_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);
@@ -2346,7 +2346,7 @@ static inline void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i)
schedule_reset(priv);
}
-static inline void isr_rx(struct ipw2100_priv *priv, int i,
+static void isr_rx(struct ipw2100_priv *priv, int i,
struct ieee80211_rx_stats *stats)
{
struct ipw2100_status *status = &priv->status_queue.drv[i];
@@ -2425,7 +2425,7 @@ static inline void isr_rx(struct ipw2100_priv *priv, int i,
priv->rx_queue.drv[i].host_addr = packet->dma_addr;
}
-static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
+static 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;
@@ -2481,7 +2481,7 @@ static inline int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
* The WRITE index is cached in the variable 'priv->rx_queue.next'.
*
*/
-static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
+static void __ipw2100_rx_process(struct ipw2100_priv *priv)
{
struct ipw2100_bd_queue *rxq = &priv->rx_queue;
struct ipw2100_status_queue *sq = &priv->status_queue;
@@ -2634,7 +2634,7 @@ static inline void __ipw2100_rx_process(struct ipw2100_priv *priv)
* for use by future command and data packets.
*
*/
-static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
+static int __ipw2100_tx_process(struct ipw2100_priv *priv)
{
struct ipw2100_bd_queue *txq = &priv->tx_queue;
struct ipw2100_bd *tbd;
@@ -2716,7 +2716,7 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
list_del(element);
DEC_STAT(&priv->fw_pend_stat);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
{
int i = txq->oldest;
IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i,
@@ -2782,7 +2782,7 @@ static inline int __ipw2100_tx_process(struct ipw2100_priv *priv)
"something else: ids %d=%d.\n",
priv->net_dev->name, txq->oldest, packet->index);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_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",
@@ -2975,7 +2975,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
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
+#ifdef CONFIG_IPW2100_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);
@@ -3827,7 +3827,7 @@ static ssize_t show_stats(struct device *d, struct device_attribute *attr,
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
+#ifdef CONFIG_IPW2100_DEBUG
out += sprintf(out, "packet mismatch image: %s\n",
priv->snapshot[0] ? "YES" : "NO");
#endif
@@ -3982,7 +3982,7 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
static ssize_t show_debug_level(struct device_driver *d, char *buf)
{
return sprintf(buf, "0x%08X\n", ipw2100_debug_level);
@@ -4011,7 +4011,7 @@ static ssize_t store_debug_level(struct device_driver *d,
static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level,
store_debug_level);
-#endif /* CONFIG_IPW_DEBUG */
+#endif /* CONFIG_IPW2100_DEBUG */
static ssize_t show_fatal_error(struct device *d,
struct device_attribute *attr, char *buf)
@@ -4937,7 +4937,7 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid,
};
int err;
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_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],
@@ -5735,70 +5735,6 @@ static struct net_device_stats *ipw2100_stats(struct net_device *dev)
return &priv->ieee->stats;
}
-#if WIRELESS_EXT < 18
-/* Support for wpa_supplicant before WE-18, deprecated. */
-
-/* following definitions must match definitions in driver_ipw.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 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct {
- u32 command;
- u32 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_ipw.c code */
-#endif /* WIRELESS_EXT < 18 */
-
static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
@@ -5807,11 +5743,6 @@ static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value)
return 0;
}
-#if WIRELESS_EXT < 18
-#define IW_AUTH_ALG_OPEN_SYSTEM 0x1
-#define IW_AUTH_ALG_SHARED_KEY 0x2
-#endif
-
static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value)
{
@@ -5855,360 +5786,6 @@ void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv,
ipw2100_set_wpa_ie(priv, &frame, 0);
}
-#if WIRELESS_EXT < 18
-static int ipw2100_wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct ipw2100_priv *priv = ieee80211_priv(dev);
- struct ieee80211_crypt_data *crypt;
- unsigned long flags;
- int ret = 0;
-
- switch (name) {
- case IPW2100_PARAM_WPA_ENABLED:
- ret = ipw2100_wpa_enable(priv, value);
- break;
-
- case IPW2100_PARAM_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
- break;
-
- flags = crypt->ops->get_flags(crypt->priv);
-
- if (value)
- flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
- else
- flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-
- crypt->ops->set_flags(flags, crypt->priv);
-
- break;
-
- case IPW2100_PARAM_DROP_UNENCRYPTED:{
- /* See IW_AUTH_DROP_UNENCRYPTED handling for details */
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- priv->ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (priv->ieee->set_security)
- priv->ieee->set_security(priv->ieee->dev, &sec);
- 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;
-}
-
-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;
- }
-
- sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- sec.encrypt = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_LEVEL;
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- sec.encrypt = 1;
-
- 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 = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- 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;
-}
-
-static int ipw2100_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- 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;
- }
-
- return -EOPNOTSUPP;
-}
-#endif /* WIRELESS_EXT < 18 */
-
static void ipw_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
@@ -6337,9 +5914,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
dev->open = ipw2100_open;
dev->stop = ipw2100_close;
dev->init = ipw2100_net_init;
-#if WIRELESS_EXT < 18
- dev->do_ioctl = ipw2100_ioctl;
-#endif
dev->get_stats = ipw2100_stats;
dev->ethtool_ops = &ipw2100_ethtool_ops;
dev->tx_timeout = ipw2100_tx_timeout;
@@ -6858,7 +6432,7 @@ static int __init ipw2100_init(void)
ret = pci_module_init(&ipw2100_pci_driver);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
ipw2100_debug_level = debug;
driver_create_file(&ipw2100_pci_driver.driver,
&driver_attr_debug_level);
@@ -6873,7 +6447,7 @@ static int __init ipw2100_init(void)
static void __exit ipw2100_exit(void)
{
/* FIXME: IPG: check that we have no instances of the devices open */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
driver_remove_file(&ipw2100_pci_driver.driver,
&driver_attr_debug_level);
#endif
@@ -7153,7 +6727,7 @@ static int ipw2100_wx_get_range(struct net_device *dev,
/* Set the Wireless Extension versions */
range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
+ range->we_version_source = 18;
// range->retry_capa; /* What retry options are supported */
// range->retry_flags; /* How to decode max/min retry limit */
@@ -7184,6 +6758,9 @@ static int ipw2100_wx_get_range(struct net_device *dev,
IW_EVENT_CAPA_MASK(SIOCGIWAP));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+
IPW_DEBUG_WX("GET Range\n");
return 0;
@@ -7852,7 +7429,6 @@ static int ipw2100_wx_get_power(struct net_device *dev,
return 0;
}
-#if WIRELESS_EXT > 17
/*
* WE-18 WPA support
*/
@@ -8114,7 +7690,6 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
}
return 0;
}
-#endif /* WIRELESS_EXT > 17 */
/*
*
@@ -8347,11 +7922,7 @@ static iw_handler ipw2100_wx_handlers[] = {
NULL, /* SIOCWIWTHRSPY */
ipw2100_wx_set_wap, /* SIOCSIWAP */
ipw2100_wx_get_wap, /* SIOCGIWAP */
-#if WIRELESS_EXT > 17
ipw2100_wx_set_mlme, /* SIOCSIWMLME */
-#else
- NULL, /* -- hole -- */
-#endif
NULL, /* SIOCGIWAPLIST -- deprecated */
ipw2100_wx_set_scan, /* SIOCSIWSCAN */
ipw2100_wx_get_scan, /* SIOCGIWSCAN */
@@ -8375,7 +7946,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_get_encode, /* SIOCGIWENCODE */
ipw2100_wx_set_power, /* SIOCSIWPOWER */
ipw2100_wx_get_power, /* SIOCGIWPOWER */
-#if WIRELESS_EXT > 17
NULL, /* -- hole -- */
NULL, /* -- hole -- */
ipw2100_wx_set_genie, /* SIOCSIWGENIE */
@@ -8385,7 +7955,6 @@ static iw_handler ipw2100_wx_handlers[] = {
ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */
ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */
NULL, /* SIOCSIWPMKSA */
-#endif
};
#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV
@@ -8558,7 +8127,7 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev)
quality = min(beacon_qual, min(tx_qual, rssi_qual));
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2100_DEBUG
if (beacon_qual == quality)
IPW_DEBUG_WX("Quality clamped by Missed Beacons\n");
else if (tx_qual == quality)
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h
index 7c65b10bb164..f6c51441fa87 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2100.h
@@ -73,7 +73,7 @@ struct ipw2100_rx_packet;
* 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
+ * CONFIG_IPW2100_DEBUG defined in your kernel configuration
*
*/
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 5e7c7e944c9d..4c28e332ecc3 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -462,7 +462,7 @@ static inline void ipw_disable_interrupts(struct ipw_priv *priv)
ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL);
}
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
static char *ipw_error_desc(u32 val)
{
switch (val) {
@@ -813,7 +813,7 @@ static void ipw_bg_led_link_off(void *data)
up(&priv->sem);
}
-static inline void __ipw_led_activity_on(struct ipw_priv *priv)
+static void __ipw_led_activity_on(struct ipw_priv *priv)
{
u32 led;
@@ -1235,7 +1235,7 @@ static ssize_t store_scan_age(struct device *d, struct device_attribute *attr,
const char *buf, size_t count)
{
struct ipw_priv *priv = dev_get_drvdata(d);
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
struct net_device *dev = priv->net_dev;
#endif
char buffer[] = "00000000";
@@ -1508,7 +1508,7 @@ static ssize_t store_direct_dword(struct device *d,
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)
+static int rf_kill_active(struct ipw_priv *priv)
{
if (0 == (ipw_read32(priv, 0x30) & 0x10000))
priv->status |= STATUS_RF_KILL_HW;
@@ -1754,7 +1754,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
IPW_ERROR("Firmware error detected. Restarting.\n");
if (priv->error) {
IPW_ERROR("Sysfs 'error' log already exists.\n");
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
if (ipw_debug_level & IPW_DL_FW_ERRORS) {
struct ipw_fw_error *error =
ipw_alloc_error_log(priv);
@@ -1770,7 +1770,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
else
IPW_ERROR("Error allocating sysfs 'error' "
"log.\n");
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
if (ipw_debug_level & IPW_DL_FW_ERRORS)
ipw_dump_error_log(priv, priv->error);
#endif
@@ -2359,7 +2359,7 @@ static inline void eeprom_write_reg(struct ipw_priv *p, u32 data)
}
/* perform a chip select operation */
-static inline void eeprom_cs(struct ipw_priv *priv)
+static void eeprom_cs(struct ipw_priv *priv)
{
eeprom_write_reg(priv, 0);
eeprom_write_reg(priv, EEPROM_BIT_CS);
@@ -2368,7 +2368,7 @@ static inline void eeprom_cs(struct ipw_priv *priv)
}
/* perform a chip select operation */
-static inline void eeprom_disable_cs(struct ipw_priv *priv)
+static void eeprom_disable_cs(struct ipw_priv *priv)
{
eeprom_write_reg(priv, EEPROM_BIT_CS);
eeprom_write_reg(priv, 0);
@@ -2475,7 +2475,7 @@ static void ipw_eeprom_init_sram(struct ipw_priv *priv)
IPW_DEBUG_TRACE("<<\n");
}
-static inline void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
+static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count)
{
count >>= 2;
if (!count)
@@ -2772,7 +2772,7 @@ 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,
+static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask,
int timeout)
{
int i = 0;
@@ -3150,7 +3150,7 @@ static int ipw_get_fw(struct ipw_priv *priv,
#define IPW_RX_BUF_SIZE (3000)
-static inline void ipw_rx_queue_reset(struct ipw_priv *priv,
+static void ipw_rx_queue_reset(struct ipw_priv *priv,
struct ipw_rx_queue *rxq)
{
unsigned long flags;
@@ -3608,7 +3608,7 @@ static void ipw_tx_queue_free(struct ipw_priv *priv)
ipw_queue_tx_free(priv, &priv->txq[3]);
}
-static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
+static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
{
/* First 3 bytes are manufacturer */
bssid[0] = priv->mac_addr[0];
@@ -3622,7 +3622,7 @@ static inline void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid)
bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */
}
-static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
+static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
{
struct ipw_station_entry entry;
int i;
@@ -3655,7 +3655,7 @@ static inline u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
return i;
}
-static inline u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
+static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
{
int i;
@@ -3778,7 +3778,7 @@ static const struct ipw_status_code ipw_status_codes[] = {
{0x2E, "Cipher suite is rejected per security policy"},
};
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
static const char *ipw_get_status_code(u16 status)
{
int i;
@@ -3794,7 +3794,7 @@ static void inline average_init(struct average *avg)
memset(avg, 0, sizeof(*avg));
}
-static void inline average_add(struct average *avg, s16 val)
+static void average_add(struct average *avg, s16 val)
{
avg->sum -= avg->entries[avg->pos];
avg->sum += val;
@@ -3805,7 +3805,7 @@ static void inline average_add(struct average *avg, s16 val)
}
}
-static s16 inline average_value(struct average *avg)
+static s16 average_value(struct average *avg)
{
if (!unlikely(avg->init)) {
if (avg->pos)
@@ -3847,7 +3847,7 @@ static void ipw_reset_stats(struct ipw_priv *priv)
}
-static inline u32 ipw_get_max_rate(struct ipw_priv *priv)
+static u32 ipw_get_max_rate(struct ipw_priv *priv)
{
u32 i = 0x80000000;
u32 mask = priv->rates_mask;
@@ -4087,7 +4087,7 @@ static void ipw_bg_gather_stats(void *data)
* roaming_threshold -> disassociate_threshold, scan and roam for better signal.
* Above disassociate threshold, give up and stop scanning.
* Roaming is disabled if disassociate_threshold <= roaming_threshold */
-static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
+static void ipw_handle_missed_beacon(struct ipw_priv *priv,
int missed_count)
{
priv->notif_missed_beacons = missed_count;
@@ -4157,7 +4157,7 @@ static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
* Handle host notification packet.
* Called from interrupt routine
*/
-static inline void ipw_rx_notification(struct ipw_priv *priv,
+static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
notif->size = le16_to_cpu(notif->size);
@@ -4250,7 +4250,7 @@ static inline void ipw_rx_notification(struct ipw_priv *priv,
if (priv->
status & (STATUS_ASSOCIATED |
STATUS_AUTH)) {
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
struct notif_authenticate *auth
= &notif->u.auth;
IPW_DEBUG(IPW_DL_NOTIF |
@@ -4944,12 +4944,11 @@ 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);
+ rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
if (unlikely(!rxq)) {
IPW_ERROR("memory allocation failed\n");
return NULL;
}
- memset(rxq, 0, sizeof(*rxq));
spin_lock_init(&rxq->lock);
INIT_LIST_HEAD(&rxq->rx_free);
INIT_LIST_HEAD(&rxq->rx_used);
@@ -5096,7 +5095,7 @@ static int ipw_compatible_rates(struct ipw_priv *priv,
return 1;
}
-static inline void ipw_copy_rates(struct ipw_supported_rates *dest,
+static void ipw_copy_rates(struct ipw_supported_rates *dest,
const struct ipw_supported_rates *src)
{
u8 i;
@@ -5828,7 +5827,7 @@ static void ipw_bg_adhoc_check(void *data)
up(&priv->sem);
}
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
static void ipw_debug_config(struct ipw_priv *priv)
{
IPW_DEBUG_INFO("Scan completed, no valid APs matched "
@@ -5857,7 +5856,7 @@ static void ipw_debug_config(struct ipw_priv *priv)
#define ipw_debug_config(x) do {} while (0)
#endif
-static inline void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
+static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
{
/* TODO: Verify that this works... */
struct ipw_fixed_rate fr = {
@@ -7456,8 +7455,7 @@ static void ipw_handle_data_packet(struct ipw_priv *priv,
/* HW decrypt will not clear the WEP bit, MIC, PN, etc. */
hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data;
if (priv->ieee->iw_mode != IW_MODE_MONITOR &&
- ((is_multicast_ether_addr(hdr->addr1) ||
- is_broadcast_ether_addr(hdr->addr1)) ?
+ (is_multicast_ether_addr(hdr->addr1) ?
!priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt))
ipw_rebuild_decrypted_skb(priv, rxb->skb);
@@ -7636,7 +7634,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
}
#endif
-static inline int is_network_packet(struct ipw_priv *priv,
+static int is_network_packet(struct ipw_priv *priv,
struct ieee80211_hdr_4addr *header)
{
/* Filter incoming packets to determine if they are targetted toward
@@ -7648,8 +7646,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
return 0;
/* {broad,multi}cast packets to our BSSID go through */
- if (is_multicast_ether_addr(header->addr1) ||
- is_broadcast_ether_addr(header->addr1))
+ if (is_multicast_ether_addr(header->addr1))
return !memcmp(header->addr3, priv->bssid, ETH_ALEN);
/* packets to our adapter go through */
@@ -7662,8 +7659,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
return 0;
/* {broad,multi}cast packets to our BSS go through */
- if (is_multicast_ether_addr(header->addr1) ||
- is_broadcast_ether_addr(header->addr1))
+ if (is_multicast_ether_addr(header->addr1))
return !memcmp(header->addr2, priv->bssid, ETH_ALEN);
/* packets to our adapter go through */
@@ -7676,7 +7672,7 @@ static inline int is_network_packet(struct ipw_priv *priv,
#define IPW_PACKET_RETRY_TIME HZ
-static inline int is_duplicate_packet(struct ipw_priv *priv,
+static int is_duplicate_packet(struct ipw_priv *priv,
struct ieee80211_hdr_4addr *header)
{
u16 sc = le16_to_cpu(header->seq_ctl);
@@ -7815,7 +7811,7 @@ static void ipw_rx(struct ipw_priv *priv)
while (i != r) {
rxb = priv->rxq->queue[i];
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
if (unlikely(rxb == NULL)) {
printk(KERN_CRIT "Queue not allocated!\n");
break;
@@ -8940,14 +8936,12 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
IPW_DEBUG_HC("starting request direct scan!\n");
if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) {
- err = wait_event_interruptible(priv->wait_state,
- !(priv->
- status & (STATUS_SCANNING |
- STATUS_SCAN_ABORTING)));
- if (err) {
- IPW_DEBUG_HC("aborting direct scan");
- goto done;
- }
+ /* We should not sleep here; otherwise we will block most
+ * of the system (for instance, we hold rtnl_lock when we
+ * get here).
+ */
+ err = -EAGAIN;
+ goto done;
}
memset(&scan, 0, sizeof(scan));
@@ -9585,7 +9579,7 @@ static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev)
/* net device stuff */
-static inline void init_sys_config(struct ipw_sys_config *sys_config)
+static 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 */
@@ -9631,7 +9625,7 @@ modify to send one tfd per fragment instead of using chunking. otherwise
we need to heavily modify the ieee80211_skb_to_txb.
*/
-static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
+static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
int pri)
{
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
@@ -9657,8 +9651,7 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
hdr_len = IEEE80211_3ADDR_LEN;
- unicast = !(is_multicast_ether_addr(hdr->addr1) ||
- is_broadcast_ether_addr(hdr->addr1));
+ unicast = !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);
@@ -9673,8 +9666,7 @@ static inline int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
case IW_MODE_INFRA:
default:
- unicast = !(is_multicast_ether_addr(hdr->addr3) ||
- is_broadcast_ether_addr(hdr->addr3));
+ unicast = !is_multicast_ether_addr(hdr->addr3);
hdr_len = IEEE80211_3ADDR_LEN;
id = 0;
break;
@@ -10956,7 +10948,7 @@ static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->net_dev = net_dev;
priv->pci_dev = pdev;
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_DEBUG
ipw_debug_level = debug;
#endif
spin_lock_init(&priv->lock);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 1c98db0652c9..e65620a4d79e 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -1301,14 +1301,14 @@ struct ipw_priv {
/* debug macros */
-#ifdef CONFIG_IPW_DEBUG
+#ifdef CONFIG_IPW2200_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 */
+#endif /* CONFIG_IPW2200_DEBUG */
/*
* To use the debug system;
@@ -1332,7 +1332,7 @@ do { if (ipw_debug_level & (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
+ * CONFIG_IPW2200_DEBUG defined in your kernel configuration
*
*/
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 92793b958e32..bf6271ee387a 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -166,8 +166,6 @@ static char *version =
#define DEBUG(n, args...)
#endif
-static dev_info_t dev_info = "netwave_cs";
-
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
@@ -195,12 +193,9 @@ module_param(mem_speed, int, 0);
/* PCMCIA (Card Services) related functions */
static void netwave_release(dev_link_t *link); /* Card removal */
-static int netwave_event(event_t event, int priority,
- event_callback_args_t *args);
static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card
insertion */
-static dev_link_t *netwave_attach(void); /* Create instance */
-static void netwave_detach(dev_link_t *); /* Destroy instance */
+static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */
/* Hardware configuration */
static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
@@ -228,17 +223,6 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/*
- A linked list of "instances" of the skeleton device. Each actual
- PCMCIA card corresponds to one device instance, and is described
- by one dev_link_t structure (defined in ds.h).
-
- You may not want to use a linked list for this -- for example, the
- memory card driver uses an array of dev_link_t pointers, where minor
- device numbers are used to derive the corresponding array index.
-*/
-static dev_link_t *dev_list;
-
-/*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
@@ -394,20 +378,18 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
* configure the card at this point -- we wait until we receive a
* card insertion event.
*/
-static dev_link_t *netwave_attach(void)
+static int netwave_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
struct net_device *dev;
netwave_private *priv;
- int ret;
-
+
DEBUG(0, "netwave_attach()\n");
-
+
/* Initialize the dev_link_t structure */
dev = alloc_etherdev(sizeof(netwave_private));
if (!dev)
- return NULL;
+ return -ENOMEM;
priv = netdev_priv(dev);
link = &priv->link;
link->priv = dev;
@@ -449,21 +431,14 @@ static dev_link_t *netwave_attach(void)
dev->open = &netwave_open;
dev->stop = &netwave_close;
link->irq.Instance = dev;
-
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- netwave_detach(link);
- return NULL;
- }
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ netwave_pcmcia_config( link);
+
+ return 0;
} /* netwave_attach */
/*
@@ -474,42 +449,20 @@ static dev_link_t *netwave_attach(void)
* structures are freed. Otherwise, the structures will be freed
* when the device is released.
*/
-static void netwave_detach(dev_link_t *link)
+static void netwave_detach(struct pcmcia_device *p_dev)
{
- struct net_device *dev = link->priv;
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
- DEBUG(0, "netwave_detach(0x%p)\n", link);
-
- /*
- If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
- if (link->state & DEV_CONFIG)
- netwave_release(link);
-
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- {
- DEBUG(1, "netwave_cs: detach fail, '%s' not in list\n",
- link->dev->dev_name);
- return;
- }
-
- /* Unlink device structure, free pieces */
- *linkp = link->next;
- if (link->dev)
- unregister_netdev(dev);
- free_netdev(dev);
-
+ DEBUG(0, "netwave_detach(0x%p)\n", link);
+
+ if (link->state & DEV_CONFIG)
+ netwave_release(link);
+
+ if (link->dev)
+ unregister_netdev(dev);
+
+ free_netdev(dev);
} /* netwave_detach */
/*
@@ -935,69 +888,38 @@ static void netwave_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/*
- * Function netwave_event (event, priority, args)
- *
- * The card status event handler. Mostly, this schedules other
- * stuff to run after an event is received. A CARD_REMOVAL event
- * also sets some flags to discourage the net drivers from trying
- * to talk to the card any more.
- *
- * When a CARD_REMOVAL event is received, we immediately set a flag
- * to block future accesses to this device. All the functions that
- * actually access the device should check this flag to make sure
- * the card is still present.
- *
- */
-static int netwave_event(event_t event, int priority,
- event_callback_args_t *args)
+static int netwave_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
-
- DEBUG(1, "netwave_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_REGISTRATION_COMPLETE:
- DEBUG(0, "netwave_cs: registration complete\n");
- break;
-
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- netif_device_detach(dev);
- netwave_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- netwave_pcmcia_config( link);
- break;
- case CS_EVENT_PM_SUSPEND:
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ if (link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
+
+ return 0;
+}
+
+static int netwave_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- netwave_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ netwave_reset(dev);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
-} /* netwave_event */
+
+ return 0;
+}
+
/*
* Function netwave_doreset (ioBase, ramBase)
@@ -1491,10 +1413,11 @@ static struct pcmcia_driver netwave_driver = {
.drv = {
.name = "netwave_cs",
},
- .attach = netwave_attach,
- .event = netwave_event,
- .detach = netwave_detach,
+ .probe = netwave_attach,
+ .remove = netwave_detach,
.id_table = netwave_ids,
+ .suspend = netwave_suspend,
+ .resume = netwave_resume,
};
static int __init init_netwave_cs(void)
@@ -1505,7 +1428,6 @@ static int __init init_netwave_cs(void)
static void __exit exit_netwave_cs(void)
{
pcmcia_unregister_driver(&netwave_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_netwave_cs);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index dc1128a00971..b664708481cc 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -43,17 +43,6 @@ 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 */
/********************************************************************/
@@ -69,19 +58,14 @@ struct orinoco_pccard {
unsigned long hard_reset_in_progress;
};
-/*
- * 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 */
/********************************************************************/
+static void orinoco_cs_config(dev_link_t *link);
static void orinoco_cs_release(dev_link_t *link);
-static void orinoco_cs_detach(dev_link_t *link);
+static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/
/* Device methods */
@@ -119,19 +103,17 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
* 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 *
-orinoco_cs_attach(void)
+static int
+orinoco_cs_attach(struct pcmcia_device *p_dev)
{
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), orinoco_cs_hard_reset);
if (! dev)
- return NULL;
+ return -ENOMEM;
priv = netdev_priv(dev);
card = priv->card;
@@ -154,22 +136,15 @@ orinoco_cs_attach(void)
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);
- orinoco_cs_detach(link);
- return NULL;
- }
+ link->next = NULL;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ orinoco_cs_config(link);
- return link;
+ return 0;
} /* orinoco_cs_attach */
/*
@@ -178,27 +153,14 @@ orinoco_cs_attach(void)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void orinoco_cs_detach(dev_link_t *link)
+static void orinoco_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
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)
orinoco_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",
@@ -465,106 +427,82 @@ orinoco_cs_release(dev_link_t *link)
ioport_unmap(priv->hw.iobase);
} /* orinoco_cs_release */
-/*
- * The card status event handler. Mostly, this schedules other stuff
- * to run after an event is received.
- */
-static int
-orinoco_cs_event(event_t event, int priority,
- event_callback_args_t * args)
+static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- unsigned long flags;
-
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ /* This is probably racy, but I can't think of
+ a better way, short of rewriting the PCMCIA
+ layer to not suck :-( */
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
spin_lock_irqsave(&priv->lock, flags);
+
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
+
netif_device_detach(dev);
priv->hw_unavailable++;
+
spin_unlock_irqrestore(&priv->lock, flags);
}
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- orinoco_cs_config(link);
- break;
+ pcmcia_release_configuration(link->handle);
+ }
- 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 :-( */
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- spin_lock_irqsave(&priv->lock, flags);
-
- err = __orinoco_down(dev);
- if (err)
- printk(KERN_WARNING "%s: %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);
+ return 0;
+}
+
+static int orinoco_cs_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_pccard *card = priv->card;
+ int err = 0;
+ unsigned long flags;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ /* FIXME: should we double check that this is
+ * the same card as we had before */
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ if (! test_bit(0, &card->hard_reset_in_progress)) {
+ err = orinoco_reinit_firmware(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ dev->name, err);
+ return -EIO;
}
- pcmcia_release_configuration(link->handle);
- }
- break;
+ spin_lock_irqsave(&priv->lock, flags);
+
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
- 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);
-
- if (! test_bit(0, &card->hard_reset_in_progress)) {
- err = orinoco_reinit_firmware(dev);
- if (err) {
- printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ if (priv->open && ! priv->hw_unavailable) {
+ err = __orinoco_up(dev);
+ if (err)
+ printk(KERN_ERR "%s: Error %d restarting card\n",
dev->name, err);
- break;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- netif_device_attach(dev);
- priv->hw_unavailable--;
-
- if (priv->open && ! priv->hw_unavailable) {
- err = __orinoco_up(dev);
- if (err)
- printk(KERN_ERR "%s: Error %d restarting card\n",
- dev->name, err);
-
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
}
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
- break;
}
- return err;
-} /* orinoco_cs_event */
+ return 0;
+}
+
/********************************************************************/
/* Module initialization */
@@ -665,10 +603,11 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .attach = orinoco_cs_attach,
- .detach = orinoco_cs_detach,
- .event = orinoco_cs_event,
+ .probe = orinoco_cs_attach,
+ .remove = orinoco_cs_detach,
.id_table = orinoco_cs_ids,
+ .suspend = orinoco_cs_suspend,
+ .resume = orinoco_cs_resume,
};
static int __init
@@ -683,7 +622,6 @@ static void __exit
exit_orinoco_cs(void)
{
pcmcia_unregister_driver(&orinoco_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_orinoco_cs);
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 135a156db25d..c5cd61c7f927 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -748,7 +748,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
if (essid->length) {
dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */
/* if it is to big, trunk it */
- dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length + 1);
+ dwrq->length = min(IW_ESSID_MAX_SIZE, essid->length);
} else {
dwrq->flags = 0;
dwrq->length = 0;
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index 33d64d2ee53f..a8261d8454dd 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -177,7 +177,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
#endif
newskb->dev = skb->dev;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
skb = newskb;
}
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 70fd6fd8feb9..7880d8c31aad 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -92,9 +92,7 @@ module_param(pc_debug, int, 0);
/** Prototypes based on PCMCIA skeleton driver *******************************/
static void ray_config(dev_link_t *link);
static void ray_release(dev_link_t *link);
-static int ray_event(event_t event, int priority, event_callback_args_t *args);
-static dev_link_t *ray_attach(void);
-static void ray_detach(dev_link_t *);
+static void ray_detach(struct pcmcia_device *p_dev);
/***** Prototypes indicated by device structure ******************************/
static int ray_dev_close(struct net_device *dev);
@@ -192,12 +190,6 @@ static int bc;
static char *phy_addr = NULL;
-/* 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 = "ray_cs";
-
/* A linked list of "instances" of the ray device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
@@ -314,12 +306,10 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
configure the card at this point -- we wait until we receive a
card insertion event.
=============================================================================*/
-static dev_link_t *ray_attach(void)
+static int ray_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
ray_dev_t *local;
- int ret;
struct net_device *dev;
DEBUG(1, "ray_attach()\n");
@@ -328,7 +318,7 @@ static dev_link_t *ray_attach(void)
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
- return NULL;
+ return -ENOMEM;
/* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t));
@@ -387,30 +377,19 @@ static dev_link_t *ray_attach(void)
dev->stop = &ray_dev_close;
netif_stop_queue(dev);
- /* Register with Card Services */
- 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;
+ init_timer(&local->timer);
- DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n");
+ link->handle = p_dev;
+ p_dev->instance = link;
- init_timer(&local->timer);
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ ray_config(link);
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if (ret != 0) {
- printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
- cs_error(link->handle, RegisterClient, ret);
- ray_detach(link);
- return NULL;
- }
- DEBUG(2,"ray_cs ray_attach ending\n");
- return link;
+ return 0;
fail_alloc_dev:
kfree(link);
- return NULL;
+ return -ENOMEM;
} /* ray_attach */
/*=============================================================================
This deletes a driver "instance". The device is de-registered
@@ -418,9 +397,12 @@ fail_alloc_dev:
structures are freed. Otherwise, the structures will be freed
when the device is released.
=============================================================================*/
-static void ray_detach(dev_link_t *link)
+static void ray_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp;
+ struct net_device *dev;
+ ray_dev_t *local;
DEBUG(1, "ray_detach(0x%p)\n", link);
@@ -430,22 +412,18 @@ static void ray_detach(dev_link_t *link)
if (*linkp == NULL)
return;
- /* If the device is currently configured and active, we won't
- actually delete it yet. Instead, it is marked so that when
- the release() function is called, that will trigger a proper
- detach().
- */
- if (link->state & DEV_CONFIG)
- ray_release(link);
+ dev = link->priv;
+
+ if (link->state & DEV_CONFIG) {
+ ray_release(link);
+
+ local = (ray_dev_t *)dev->priv;
+ del_timer(&local->timer);
+ }
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
/* Unlink device structure, free pieces */
*linkp = link->next;
if (link->priv) {
- struct net_device *dev = link->priv;
if (link->dev) unregister_netdev(dev);
free_netdev(dev);
}
@@ -891,65 +869,40 @@ static void ray_release(dev_link_t *link)
DEBUG(2,"ray_release ending\n");
}
-/*=============================================================================
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
-=============================================================================*/
-static int ray_event(event_t event, int priority,
- event_callback_args_t *args)
+static int ray_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
- struct net_device *dev = link->priv;
- ray_dev_t *local = (ray_dev_t *)dev->priv;
- DEBUG(1, "ray_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- netif_device_detach(dev);
- if (link->state & DEV_CONFIG) {
- ray_release(link);
- del_timer(&local->timer);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ray_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
+ if (link->open)
+ netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
+ pcmcia_release_configuration(link->handle);
}
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
+
+
+ return 0;
+}
+
+static int ray_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- ray_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ ray_reset(dev);
+ netif_device_attach(dev);
+ }
}
- break;
- }
- return 0;
- DEBUG(2,"ray_event ending\n");
-} /* ray_event */
+
+ return 0;
+}
+
/*===========================================================================*/
int ray_dev_init(struct net_device *dev)
{
@@ -1303,7 +1256,7 @@ static int ray_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Push it out ! */
- dwrq->length = strlen(extra) + 1;
+ dwrq->length = strlen(extra);
dwrq->flags = 1; /* active */
return 0;
@@ -2945,10 +2898,11 @@ static struct pcmcia_driver ray_driver = {
.drv = {
.name = "ray_cs",
},
- .attach = ray_attach,
- .event = ray_event,
- .detach = ray_detach,
+ .probe = ray_attach,
+ .remove = ray_detach,
.id_table = ray_ids,
+ .suspend = ray_suspend,
+ .resume = ray_resume,
};
static int __init init_ray_cs(void)
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index b1bbc8e8e91f..fee4be1ce810 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -57,17 +57,6 @@ 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 */
/********************************************************************/
@@ -78,19 +67,12 @@ struct orinoco_pccard {
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 */
/********************************************************************/
+static void spectrum_cs_config(dev_link_t *link);
static void spectrum_cs_release(dev_link_t *link);
-static void spectrum_cs_detach(dev_link_t *link);
/********************************************************************/
/* Firmware downloader */
@@ -601,19 +583,17 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
* 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)
+static int
+spectrum_cs_attach(struct pcmcia_device *p_dev)
{
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;
+ return -ENOMEM;
priv = netdev_priv(dev);
card = priv->card;
@@ -635,23 +615,13 @@ spectrum_cs_attach(void)
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;
+ link->handle = p_dev;
+ p_dev->instance = link;
- client_reg.dev_info = &dev_info;
- client_reg.Version = 0x0210; /* FIXME: what does this mean? */
- client_reg.event_callback_args.client_data = link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ spectrum_cs_config(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;
+ return 0;
} /* spectrum_cs_attach */
/*
@@ -660,27 +630,14 @@ spectrum_cs_attach(void)
* are freed. Otherwise, the structures will be freed when the device
* is released.
*/
-static void spectrum_cs_detach(dev_link_t *link)
+static void spectrum_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
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",
@@ -948,82 +905,56 @@ spectrum_cs_release(dev_link_t *link)
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)
+spectrum_cs_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
- int err = 0;
unsigned long flags;
+ int err = 0;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- unsigned long flags;
+ link->state |= DEV_SUSPEND;
+ /* Mark the device as stopped, to block IO until later */
+ if (link->state & DEV_CONFIG) {
+ spin_lock_irqsave(&priv->lock, flags);
- spin_lock_irqsave(&priv->lock, flags);
- netif_device_detach(dev);
- priv->hw_unavailable++;
- spin_unlock_irqrestore(&priv->lock, flags);
- }
- break;
+ err = __orinoco_down(dev);
+ if (err)
+ printk(KERN_WARNING "%s: Error %d downing interface\n",
+ dev->name, err);
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- spectrum_cs_config(link);
- break;
+ netif_device_detach(dev);
+ priv->hw_unavailable++;
- 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;
+ spin_unlock_irqrestore(&priv->lock, flags);
- 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;
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
+
+static int
+spectrum_cs_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+ struct orinoco_private *priv = netdev_priv(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ /* FIXME: should we double check that this is
+ * the same card as we had before */
+ pcmcia_request_configuration(link->handle, &link->conf);
+ netif_device_attach(dev);
+ priv->hw_unavailable--;
+ schedule_work(&priv->reset_work);
}
+ return 0;
+}
- return err;
-} /* spectrum_cs_event */
/********************************************************************/
/* Module initialization */
@@ -1048,9 +979,10 @@ static struct pcmcia_driver orinoco_driver = {
.drv = {
.name = DRIVER_NAME,
},
- .attach = spectrum_cs_attach,
- .detach = spectrum_cs_detach,
- .event = spectrum_cs_event,
+ .probe = spectrum_cs_attach,
+ .remove = spectrum_cs_detach,
+ .suspend = spectrum_cs_suspend,
+ .resume = spectrum_cs_resume,
.id_table = spectrum_cs_ids,
};
@@ -1066,7 +998,6 @@ static void __exit
exit_spectrum_cs(void)
{
pcmcia_unregister_driver(&orinoco_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_spectrum_cs);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index d25264ba0c0e..18baacfc5a2c 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1675,11 +1675,6 @@ static int strip_rebuild_header(struct sk_buff *skb)
/************************************************************************/
/* Receiving routines */
-static int strip_receive_room(struct tty_struct *tty)
-{
- return 0x10000; /* We can handle an infinite amount of data. :-) */
-}
-
/*
* This function parses the response to the ATS300? command,
* extracting the radio version and serial number.
@@ -2424,7 +2419,7 @@ static struct net_device_stats *strip_get_stats(struct net_device *dev)
/*
* Here's the order things happen:
* When the user runs "slattach -p strip ..."
- * 1. The TTY module calls strip_open
+ * 1. The TTY module calls strip_open;;
* 2. strip_open calls strip_alloc
* 3. strip_alloc calls register_netdev
* 4. register_netdev calls strip_dev_init
@@ -2652,6 +2647,8 @@ static int strip_open(struct tty_struct *tty)
strip_info->tty = tty;
tty->disc_data = strip_info;
+ tty->receive_room = 65536;
+
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
@@ -2762,7 +2759,6 @@ static struct tty_ldisc strip_ldisc = {
.close = strip_close,
.ioctl = strip_ioctl,
.receive_buf = strip_receive_buf,
- .receive_room = strip_receive_room,
.write_wakeup = strip_write_some_more,
};
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index b0d8b5b03152..ff192e96268a 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -102,7 +102,7 @@ static inline void hacr_write(unsigned long ioaddr, u16 hacr)
* Write to card's Host Adapter Command Register. Include a delay for
* those times when it is needed.
*/
-static inline void hacr_write_slow(unsigned long ioaddr, u16 hacr)
+static void hacr_write_slow(unsigned long ioaddr, u16 hacr)
{
hacr_write(ioaddr, hacr);
/* delay might only be needed sometimes */
@@ -242,7 +242,7 @@ static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */
* The Windows drivers don't use the CRC, but the AP and the PtP tool
* depend on it.
*/
-static inline u16 psa_crc(u8 * psa, /* The PSA */
+static u16 psa_crc(u8 * psa, /* The PSA */
int size)
{ /* Number of short for CRC */
int byte_cnt; /* Loop on the PSA */
@@ -310,7 +310,7 @@ static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u
/*
* Write 1 byte to the MMC.
*/
-static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
+static void mmc_out(unsigned long ioaddr, u16 o, u8 d)
{
int count = 0;
@@ -326,7 +326,7 @@ static inline void mmc_out(unsigned long ioaddr, u16 o, u8 d)
* Routine to write bytes to the Modem Management Controller.
* We start at the end because it is the way it should be!
*/
-static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
+static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
{
o += n;
b += n;
@@ -340,7 +340,7 @@ static inline void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n)
* Read a byte from the MMC.
* Optimised version for 1 byte, avoid using memory.
*/
-static inline u8 mmc_in(unsigned long ioaddr, u16 o)
+static u8 mmc_in(unsigned long ioaddr, u16 o)
{
int count = 0;
@@ -587,7 +587,7 @@ static void wv_ack(struct net_device * dev)
* Set channel attention bit and busy wait until command has
* completed, then acknowledge completion of the command.
*/
-static inline int wv_synchronous_cmd(struct net_device * dev, const char *str)
+static int wv_synchronous_cmd(struct net_device * dev, const char *str)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -633,7 +633,7 @@ static inline int wv_synchronous_cmd(struct net_device * dev, const char *str)
* Configuration commands completion interrupt.
* Check if done, and if OK.
*/
-static inline int
+static int
wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp)
{
unsigned short mcs_addr;
@@ -843,7 +843,7 @@ if (lp->tx_n_in_use > 0)
* wavelan_interrupt is not an option), so you may experience
* delays sometimes.
*/
-static inline void wv_82586_reconfig(struct net_device * dev)
+static void wv_82586_reconfig(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long flags;
@@ -1281,7 +1281,7 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */
* This is the information which is displayed by the driver at startup.
* There are lots of flags for configuring it to your liking.
*/
-static inline void wv_init_info(struct net_device * dev)
+static void wv_init_info(struct net_device * dev)
{
short ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -1502,7 +1502,7 @@ static int wavelan_set_mac_address(struct net_device * dev, void *addr)
* It's a bit complicated and you don't really want to look into it.
* (called in wavelan_ioctl)
*/
-static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
+static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */
iw_freq * frequency)
{
const int BAND_NUM = 10; /* Number of bands */
@@ -1677,7 +1677,7 @@ static inline int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card
/*
* Give the list of available frequencies.
*/
-static inline int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
+static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */
iw_freq * list, /* List of frequencies to fill */
int max)
{ /* Maximum number of frequencies */
@@ -2489,7 +2489,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
* Note: if any errors occur, the packet is "dropped on the floor".
* (called by wv_packet_rcv())
*/
-static inline void
+static void
wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
{
net_local *lp = (net_local *) dev->priv;
@@ -2585,7 +2585,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
* (called in wavelan_interrupt()).
* Note : the spinlock is already grabbed for us.
*/
-static inline void wv_receive(struct net_device * dev)
+static void wv_receive(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -2768,7 +2768,7 @@ static inline void wv_receive(struct net_device * dev)
*
* (called in wavelan_packet_xmit())
*/
-static inline int wv_packet_write(struct net_device * dev, void *buf, short length)
+static int wv_packet_write(struct net_device * dev, void *buf, short length)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -2964,7 +2964,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
* Routine to initialize the Modem Management Controller.
* (called by wv_hw_reset())
*/
-static inline int wv_mmc_init(struct net_device * dev)
+static int wv_mmc_init(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv;
@@ -3136,7 +3136,7 @@ static inline int wv_mmc_init(struct net_device * dev)
* Start the receive unit.
* (called by wv_hw_reset())
*/
-static inline int wv_ru_start(struct net_device * dev)
+static int wv_ru_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3228,7 +3228,7 @@ static inline int wv_ru_start(struct net_device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int wv_cu_start(struct net_device * dev)
+static int wv_cu_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3329,7 +3329,7 @@ static inline int wv_cu_start(struct net_device * dev)
*
* (called by wv_hw_reset())
*/
-static inline int wv_82586_start(struct net_device * dev)
+static int wv_82586_start(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
@@ -3641,7 +3641,7 @@ static void wv_82586_config(struct net_device * dev)
* WaveLAN controller (i82586).
* (called by wavelan_close())
*/
-static inline void wv_82586_stop(struct net_device * dev)
+static void wv_82586_stop(struct net_device * dev)
{
net_local *lp = (net_local *) dev->priv;
unsigned long ioaddr = dev->base_addr;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index c822cad3333f..cf373625fc70 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -2280,7 +2280,7 @@ static int wavelan_get_essid(struct net_device *dev,
extra[IW_ESSID_MAX_SIZE] = '\0';
/* Set the length */
- wrqu->data.length = strlen(extra) + 1;
+ wrqu->data.length = strlen(extra);
return 0;
}
@@ -4594,14 +4594,12 @@ wavelan_close(struct net_device * dev)
* configure the card at this point -- we wait until we receive a
* card insertion event.
*/
-static dev_link_t *
-wavelan_attach(void)
+static int
+wavelan_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg; /* Register with cardmgr */
dev_link_t * link; /* Info for cardmgr */
struct net_device * dev; /* Interface generic data */
net_local * lp; /* Interface specific data */
- int ret;
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_attach()\n");
@@ -4609,7 +4607,7 @@ wavelan_attach(void)
/* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- if (!link) return NULL;
+ if (!link) return -ENOMEM;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 8;
@@ -4627,14 +4625,13 @@ wavelan_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
/* Chain drivers */
- link->next = dev_list;
- dev_list = link;
+ link->next = NULL;
/* Allocate the generic data structure */
dev = alloc_etherdev(sizeof(net_local));
if (!dev) {
kfree(link);
- return NULL;
+ return -ENOMEM;
}
link->priv = link->irq.Instance = dev;
@@ -4679,28 +4676,21 @@ wavelan_attach(void)
/* Other specific data */
dev->mtu = WAVELAN_MTU;
- /* Register with Card Services */
- client_reg.dev_info = &dev_info;
- client_reg.Version = 0x0210;
- client_reg.event_callback_args.client_data = link;
+ link->handle = p_dev;
+ p_dev->instance = link;
-#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "wavelan_attach(): almost done, calling pcmcia_register_client\n");
-#endif
-
- ret = pcmcia_register_client(&link->handle, &client_reg);
- if(ret != 0)
- {
- cs_error(link->handle, RegisterClient, ret);
- wavelan_detach(link);
- return NULL;
- }
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ if(wv_pcmcia_config(link) &&
+ wv_hw_config(dev))
+ wv_init_info(dev);
+ else
+ dev->irq = 0;
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_attach()\n");
#endif
- return link;
+ return 0;
}
/*------------------------------------------------------------------*/
@@ -4711,8 +4701,10 @@ wavelan_attach(void)
* is released.
*/
static void
-wavelan_detach(dev_link_t * link)
+wavelan_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
+
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
#endif
@@ -4729,31 +4721,6 @@ wavelan_detach(dev_link_t * link)
wv_pcmcia_release(link);
}
- /* Break the link with Card Services */
- if(link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Remove the interface data from the linked list */
- if(dev_list == link)
- dev_list = link->next;
- else
- {
- dev_link_t * prev = dev_list;
-
- while((prev != (dev_link_t *) NULL) && (prev->next != link))
- prev = prev->next;
-
- if(prev == (dev_link_t *) NULL)
- {
-#ifdef DEBUG_CONFIG_ERRORS
- printk(KERN_WARNING "wavelan_detach : Attempting to remove a nonexistent device.\n");
-#endif
- return;
- }
-
- prev->next = link->next;
- }
-
/* Free pieces */
if(link->priv)
{
@@ -4775,65 +4742,11 @@ wavelan_detach(dev_link_t * link)
#endif
}
-/*------------------------------------------------------------------*/
-/*
- * The card status event handler. Mostly, this schedules other stuff
- * to run after an event is received. A CARD_REMOVAL event also sets
- * some flags to discourage the net drivers from trying to talk to the
- * card any more.
- */
-static int
-wavelan_event(event_t event, /* The event received */
- int priority,
- event_callback_args_t * args)
+static int wavelan_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t * link = (dev_link_t *) args->client_data;
- struct net_device * dev = (struct net_device *) link->priv;
-
-#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "->wavelan_event(): %s\n",
- ((event == CS_EVENT_REGISTRATION_COMPLETE)?"registration complete" :
- ((event == CS_EVENT_CARD_REMOVAL) ? "card removal" :
- ((event == CS_EVENT_CARD_INSERTION) ? "card insertion" :
- ((event == CS_EVENT_PM_SUSPEND) ? "pm suspend" :
- ((event == CS_EVENT_RESET_PHYSICAL) ? "physical reset" :
- ((event == CS_EVENT_PM_RESUME) ? "pm resume" :
- ((event == CS_EVENT_CARD_RESET) ? "card reset" :
- "unknown"))))))));
-#endif
-
- switch(event)
- {
- case CS_EVENT_REGISTRATION_COMPLETE:
-#ifdef DEBUG_CONFIG_INFO
- printk(KERN_DEBUG "wavelan_cs: registration complete\n");
-#endif
- break;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device * dev = (struct net_device *) link->priv;
- case CS_EVENT_CARD_REMOVAL:
- /* Oups ! The card is no more there */
- link->state &= ~DEV_PRESENT;
- if(link->state & DEV_CONFIG)
- {
- /* Accept no more transmissions */
- netif_device_detach(dev);
-
- /* Release the card */
- wv_pcmcia_release(link);
- }
- break;
-
- case CS_EVENT_CARD_INSERTION:
- /* Reset and configure the card */
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- if(wv_pcmcia_config(link) &&
- wv_hw_config(dev))
- wv_init_info(dev);
- else
- dev->irq = 0;
- break;
-
- case CS_EVENT_PM_SUSPEND:
/* NB: wavelan_close will be called, but too late, so we are
* obliged to close nicely the wavelan here. David, could you
* close the device before suspending them ? And, by the way,
@@ -4848,38 +4761,37 @@ wavelan_event(event_t event, /* The event received */
/* The card is now suspended */
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
+
if(link->state & DEV_CONFIG)
- {
- if(link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
- break;
+ {
+ if(link->open)
+ netif_device_detach(dev);
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
+
+static int wavelan_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device * dev = (struct net_device *) link->priv;
- case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if(link->state & DEV_CONFIG)
- {
- pcmcia_request_configuration(link->handle, &link->conf);
- if(link->open) /* If RESET -> True, If RESUME -> False ? */
- {
- wv_hw_reset(dev);
- netif_device_attach(dev);
- }
- }
- break;
- }
+ {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if(link->open) /* If RESET -> True, If RESUME -> False ? */
+ {
+ wv_hw_reset(dev);
+ netif_device_attach(dev);
+ }
+ }
-#ifdef DEBUG_CALLBACK_TRACE
- printk(KERN_DEBUG "<-wavelan_event()\n");
-#endif
- return 0;
+ return 0;
}
+
static struct pcmcia_device_id wavelan_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975),
PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06),
@@ -4894,10 +4806,11 @@ static struct pcmcia_driver wavelan_driver = {
.drv = {
.name = "wavelan_cs",
},
- .attach = wavelan_attach,
- .event = wavelan_event,
- .detach = wavelan_detach,
+ .probe = wavelan_attach,
+ .remove = wavelan_detach,
.id_table = wavelan_ids,
+ .suspend = wavelan_suspend,
+ .resume = wavelan_resume,
};
static int __init
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 724a715089c9..f2d597568151 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -754,20 +754,11 @@ static void
static int
wavelan_open(struct net_device *), /* Open the device */
wavelan_close(struct net_device *); /* Close the device */
-static dev_link_t *
- wavelan_attach(void); /* Create a new device */
static void
- wavelan_detach(dev_link_t *); /* Destroy a removed device */
-static int
- wavelan_event(event_t, /* Manage pcmcia events */
- int,
- event_callback_args_t *);
+ wavelan_detach(struct pcmcia_device *p_dev); /* Destroy a removed device */
/**************************** VARIABLES ****************************/
-static dev_info_t dev_info = "wavelan_cs";
-static dev_link_t *dev_list = NULL; /* Linked list of devices */
-
/*
* Parameters that can be set with 'insmod'
* The exact syntax is 'insmod wavelan_cs.o <var>=<value>'
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 978fdc606781..48e10b0c7e74 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -105,7 +105,6 @@ module_param(pc_debug, int, 0);
*/
static void wl3501_config(dev_link_t *link);
static void wl3501_release(dev_link_t *link);
-static int wl3501_event(event_t event, int pri, event_callback_args_t *args);
/*
* The dev_info variable is the "key" that is used to match up this
@@ -1498,9 +1497,11 @@ static struct ethtool_ops ops = {
* Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released.
*/
-static void wl3501_detach(dev_link_t *link)
+static void wl3501_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp;
+ struct net_device *dev = link->priv;
/* Locate device structure */
for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
@@ -1514,16 +1515,12 @@ static void wl3501_detach(dev_link_t *link)
* function is called, that will trigger a proper detach(). */
if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
- printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' "
- "still locked\n", link->dev->dev_name);
-#endif
- goto out;
- }
+ while (link->open > 0)
+ wl3501_close(dev);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
+ netif_device_detach(dev);
+ wl3501_release(link);
+ }
/* Unlink device structure, free pieces */
*linkp = link->next;
@@ -1956,18 +1953,16 @@ static const struct iw_handler_def wl3501_handler_def = {
* The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event.
*/
-static dev_link_t *wl3501_attach(void)
+static int wl3501_attach(struct pcmcia_device *p_dev)
{
- 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 */
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
- goto out;
+ return -ENOMEM;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 16;
@@ -2003,24 +1998,17 @@ static dev_link_t *wl3501_attach(void)
netif_stop_queue(dev);
link->priv = link->irq.Instance = dev;
- /* Register with Card Services */
- link->next = wl3501_dev_list;
- wl3501_dev_list = link;
- client_reg.dev_info = &wl3501_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_error(link->handle, RegisterClient, ret);
- wl3501_detach(link);
- link = NULL;
- }
-out:
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ wl3501_config(link);
+
+ return 0;
out_link:
kfree(link);
link = NULL;
- goto out;
+ return -ENOMEM;
}
#define CS_CHECK(fn, ret) \
@@ -2173,67 +2161,41 @@ static void wl3501_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-/**
- * wl3501_event - The card status event handler
- * @event - event
- * @pri - priority
- * @args - arguments for this event
- *
- * The card status event handler. Mostly, this schedules other stuff to run
- * after an event is received. A CARD_REMOVAL event also sets some flags to
- * discourage the net drivers from trying to talk to the card any more.
- *
- * When a CARD_REMOVAL event is received, we immediately set a flag to block
- * future accesses to this device. All the functions that actually access the
- * device should check this flag to make sure the card is still present.
- */
-static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
+static int wl3501_suspend(struct pcmcia_device *p_dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- while (link->open > 0)
- wl3501_close(dev);
+ link->state |= DEV_SUSPEND;
+
+ wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
+ if (link->state & DEV_CONFIG) {
+ if (link->open)
netif_device_detach(dev);
- wl3501_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- wl3501_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG) {
- if (link->open)
- netif_device_detach(dev);
- pcmcia_release_configuration(link->handle);
- }
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- if (link->open) {
- wl3501_reset(dev);
- netif_device_attach(dev);
- }
+ pcmcia_release_configuration(link->handle);
+ }
+
+ return 0;
+}
+
+static int wl3501_resume(struct pcmcia_device *p_dev)
+{
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct net_device *dev = link->priv;
+
+ wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (link->open) {
+ wl3501_reset(dev);
+ netif_device_attach(dev);
}
- break;
}
+
return 0;
}
+
static struct pcmcia_device_id wl3501_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001),
PCMCIA_DEVICE_NULL
@@ -2245,10 +2207,11 @@ static struct pcmcia_driver wl3501_driver = {
.drv = {
.name = "wl3501_cs",
},
- .attach = wl3501_attach,
- .event = wl3501_event,
- .detach = wl3501_detach,
+ .probe = wl3501_attach,
+ .remove = wl3501_detach,
.id_table = wl3501_ids,
+ .suspend = wl3501_suspend,
+ .resume = wl3501_resume,
};
static int __init wl3501_init_module(void)
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 531b07313141..b2e8e49c8659 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -43,13 +43,16 @@ static void process_task_mortuary(void);
* list for processing. Only after two full buffer syncs
* does the task eventually get freed, because by then
* we are sure we will not reference it again.
+ * Can be invoked from softirq via RCU callback due to
+ * call_rcu() of the task struct, hence the _irqsave.
*/
static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
{
+ unsigned long flags;
struct task_struct * task = data;
- spin_lock(&task_mortuary);
+ spin_lock_irqsave(&task_mortuary, flags);
list_add(&task->tasks, &dying_tasks);
- spin_unlock(&task_mortuary);
+ spin_unlock_irqrestore(&task_mortuary, flags);
return NOTIFY_OK;
}
@@ -431,25 +434,22 @@ static void increment_tail(struct oprofile_cpu_buffer * b)
*/
static void process_task_mortuary(void)
{
- struct list_head * pos;
- struct list_head * pos2;
+ unsigned long flags;
+ LIST_HEAD(local_dead_tasks);
struct task_struct * task;
+ struct task_struct * ttask;
- spin_lock(&task_mortuary);
+ spin_lock_irqsave(&task_mortuary, flags);
- list_for_each_safe(pos, pos2, &dead_tasks) {
- task = list_entry(pos, struct task_struct, tasks);
- list_del(&task->tasks);
- free_task(task);
- }
+ list_splice_init(&dead_tasks, &local_dead_tasks);
+ list_splice_init(&dying_tasks, &dead_tasks);
- list_for_each_safe(pos, pos2, &dying_tasks) {
- task = list_entry(pos, struct task_struct, tasks);
+ spin_unlock_irqrestore(&task_mortuary, flags);
+
+ list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) {
list_del(&task->tasks);
- list_add_tail(&task->tasks, &dead_tasks);
+ free_task(task);
}
-
- spin_unlock(&task_mortuary);
}
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 026f671ea558..78193e4bbdb5 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -52,7 +52,8 @@ int alloc_cpu_buffers(void)
for_each_online_cpu(i) {
struct oprofile_cpu_buffer * b = &cpu_buffer[i];
- b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size);
+ b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size,
+ cpu_to_node(i));
if (!b->buffer)
goto fail;
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 166bca790133..b80318f03420 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/oprofile.h>
#include <linux/sched.h>
+#include <linux/capability.h>
#include <linux/dcookies.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 5ab75334c579..216d1d859326 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -83,7 +83,8 @@
** bus number for each dino.
*/
-#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_card_dino(id) ((id)->hw_type == HPHW_A_DMA)
+#define is_cujo(id) ((id)->hversion == 0x682)
#define DINO_IAR0 0x004
#define DINO_IODC_ADDR 0x008
@@ -124,6 +125,7 @@
#define DINO_IRQS 11 /* bits 0-10 are architected */
#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
+#define DINO_LOCAL_IRQS (DINO_IRQS+1)
#define DINO_MASK_IRQ(x) (1<<(x))
@@ -146,7 +148,7 @@ struct dino_device
unsigned long txn_addr; /* EIR addr to generate interrupt */
u32 txn_data; /* EIR data assign to each dino */
u32 imr; /* IRQ's which are enabled */
- int global_irq[12]; /* map IMR bit to global irq */
+ int global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
#ifdef DINO_DEBUG
unsigned int dino_irr0; /* save most recent IRQ line stat */
#endif
@@ -297,7 +299,7 @@ struct pci_port_ops dino_port_ops = {
static void dino_disable_irq(unsigned int irq)
{
struct dino_device *dino_dev = irq_desc[irq].handler_data;
- int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -309,7 +311,7 @@ static void dino_disable_irq(unsigned int irq)
static void dino_enable_irq(unsigned int irq)
{
struct dino_device *dino_dev = irq_desc[irq].handler_data;
- int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, irq);
+ int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
u32 tmp;
DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq);
@@ -435,6 +437,21 @@ static void dino_choose_irq(struct parisc_device *dev, void *ctrl)
dino_assign_irq(dino, irq, &dev->irq);
}
+
+/*
+ * Cirrus 6832 Cardbus reports wrong irq on RDI Tadpole PARISC Laptop (deller@gmx.de)
+ * (the irqs are off-by-one, not sure yet if this is a cirrus, dino-hardware or dino-driver problem...)
+ */
+static void __devinit quirk_cirrus_cardbus(struct pci_dev *dev)
+{
+ u8 new_irq = dev->irq - 1;
+ printk(KERN_INFO "PCI: Cirrus Cardbus IRQ fixup for %s, from %d to %d\n",
+ pci_name(dev), dev->irq, new_irq);
+ dev->irq = new_irq;
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
+
+
static void __init
dino_bios_init(void)
{
@@ -666,7 +683,6 @@ dino_fixup_bus(struct pci_bus *bus)
printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
#endif
} else {
-
/* Adjust INT_LINE for that busses region */
dino_assign_irq(dino_dev, dev->irq, &dev->irq);
}
@@ -872,7 +888,7 @@ static int __init dino_common_init(struct parisc_device *dev,
/* allocate I/O Port resource region */
res = &dino_dev->hba.io_space;
- if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) {
+ if (!is_cujo(&dev->id)) {
res->name = "Dino I/O Port";
} else {
res->name = "Cujo I/O Port";
@@ -927,7 +943,7 @@ static int __init dino_probe(struct parisc_device *dev)
if (is_card_dino(&dev->id)) {
version = "3.x (card mode)";
} else {
- if(dev->id.hversion == 0x680) {
+ if (!is_cujo(&dev->id)) {
if (dev->id.hversion_rev < 4) {
version = dino_vers[dev->id.hversion_rev];
}
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 6362bf99eff6..3d94d86c1c9f 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -57,7 +57,7 @@
static DEFINE_SPINLOCK(eisa_irq_lock);
-void __iomem *eisa_eeprom_addr;
+void __iomem *eisa_eeprom_addr __read_mostly;
/* We can only have one EISA adapter in the system because neither
* implementation can be flexed.
@@ -141,7 +141,7 @@ static int slave_mask;
* in the furure.
*/
/* irq 13,8,2,1,0 must be edge */
-static unsigned int eisa_irq_level; /* default to edge triggered */
+static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered */
/* called by free irq */
diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
index 3a1b4826e5c1..e13aafa70bf5 100644
--- a/drivers/parisc/eisa_eeprom.c
+++ b/drivers/parisc/eisa_eeprom.c
@@ -48,7 +48,7 @@ static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
}
static ssize_t eisa_eeprom_read(struct file * file,
- char *buf, size_t count, loff_t *ppos )
+ char __user *buf, size_t count, loff_t *ppos )
{
unsigned char *tmp;
ssize_t ret;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index a8c20396ffbe..2b3ba1dcf332 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -150,7 +150,7 @@ void __init lasi_led_init(unsigned long lasi_hpa)
*
*/
-static unsigned long lasi_power_off_hpa;
+static unsigned long lasi_power_off_hpa __read_mostly;
static void lasi_power_off(void)
{
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 5e495dcbc58a..cbae8c8963fa 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -167,7 +167,7 @@
/* non-postable I/O port space, densely packed */
#define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL)
-static void __iomem *astro_iop_base;
+static void __iomem *astro_iop_base __read_mostly;
#define ELROY_HVERS 0x782
#define MERCURY_HVERS 0x783
@@ -695,11 +695,71 @@ lba_claim_dev_resources(struct pci_dev *dev)
}
}
}
+
+
+/*
+ * truncate_pat_collision: Deal with overlaps or outright collisions
+ * between PAT PDC reported ranges.
+ *
+ * Broken PA8800 firmware will report lmmio range that
+ * overlaps with CPU HPA. Just truncate the lmmio range.
+ *
+ * BEWARE: conflicts with this lmmio range may be an
+ * elmmio range which is pointing down another rope.
+ *
+ * FIXME: only deals with one collision per range...theoretically we
+ * could have several. Supporting more than one collision will get messy.
+ */
+static unsigned long
+truncate_pat_collision(struct resource *root, struct resource *new)
+{
+ unsigned long start = new->start;
+ unsigned long end = new->end;
+ struct resource *tmp = root->child;
+
+ if (end <= start || start < root->start || !tmp)
+ return 0;
+
+ /* find first overlap */
+ while (tmp && tmp->end < start)
+ tmp = tmp->sibling;
+
+ /* no entries overlap */
+ if (!tmp) return 0;
+
+ /* found one that starts behind the new one
+ ** Don't need to do anything.
+ */
+ if (tmp->start >= end) return 0;
+
+ if (tmp->start <= start) {
+ /* "front" of new one overlaps */
+ new->start = tmp->end + 1;
+
+ if (tmp->end >= end) {
+ /* AACCKK! totally overlaps! drop this range. */
+ return 1;
+ }
+ }
+
+ if (tmp->end < end ) {
+ /* "end" of new one overlaps */
+ new->end = tmp->start - 1;
+ }
+
+ printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
+ "to [%lx,%lx]\n",
+ start, end,
+ new->start, new->end );
+
+ return 0; /* truncation successful */
+}
+
#else
-#define lba_claim_dev_resources(dev)
+#define lba_claim_dev_resources(dev) do { } while (0)
+#define truncate_pat_collision(r,n) (0)
#endif
-
/*
** The algorithm is generic code.
** But it needs to access local data structures to get the IRQ base.
@@ -747,6 +807,9 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&ioport_resource, 2);
BUG();
}
+ /* advertize Host bridge resources to PCI bus */
+ bus->resource[0] = &(ldev->hba.io_space);
+ i = 1;
if (ldev->hba.elmmio_space.start) {
err = request_resource(&iomem_resource,
@@ -760,23 +823,35 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */
/* BUG(); */
- }
+ } else
+ bus->resource[i++] = &(ldev->hba.elmmio_space);
}
- err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
- if (err < 0) {
- /* FIXME overlaps with elmmio will fail here.
- * Need to prune (or disable) the distributed range.
- *
- * BEWARE: conflicts with this lmmio range may be
- * elmmio range which is pointing down another rope.
- */
-
- printk("FAILED: lba_fixup_bus() request for "
+
+ /* Overlaps with elmmio can (and should) fail here.
+ * We will prune (or ignore) the distributed range.
+ *
+ * FIXME: SBA code should register all elmmio ranges first.
+ * that would take care of elmmio ranges routed
+ * to a different rope (already discovered) from
+ * getting registered *after* LBA code has already
+ * registered it's distributed lmmio range.
+ */
+ if (truncate_pat_collision(&iomem_resource,
+ &(ldev->hba.lmmio_space))) {
+
+ printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+ ldev->hba.lmmio_space.start,
+ ldev->hba.lmmio_space.end);
+ } else {
+ err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
+ if (err < 0) {
+ printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
"lmmio_space [%lx/%lx]\n",
ldev->hba.lmmio_space.start,
ldev->hba.lmmio_space.end);
- /* lba_dump_res(&iomem_resource, 2); */
+ } else
+ bus->resource[i++] = &(ldev->hba.lmmio_space);
}
#ifdef CONFIG_64BIT
@@ -791,18 +866,10 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&iomem_resource, 2);
BUG();
}
+ bus->resource[i++] = &(ldev->hba.gmmio_space);
}
#endif
- /* advertize Host bridge resources to PCI bus */
- bus->resource[0] = &(ldev->hba.io_space);
- bus->resource[1] = &(ldev->hba.lmmio_space);
- i=2;
- if (ldev->hba.elmmio_space.start)
- bus->resource[i++] = &(ldev->hba.elmmio_space);
- if (ldev->hba.gmmio_space.start)
- bus->resource[i++] = &(ldev->hba.gmmio_space);
-
}
list_for_each(ln, &bus->devices) {
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 95bd07b8b61b..3627a2d7f79f 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -3,7 +3,7 @@
*
* (c) Copyright 2000 Red Hat Software
* (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
- * (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
+ * (c) Copyright 2001-2005 Helge Deller <deller@gmx.de>
* (c) Copyright 2001 Randolph Chung <tausq@debian.org>
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/ioport.h>
#include <linux/utsname.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
@@ -56,13 +57,13 @@
relatively large amount of CPU time, some of the calculations can be
turned off with the following variables (controlled via procfs) */
-static int led_type = -1;
+static int led_type __read_mostly = -1;
static unsigned char lastleds; /* LED state from most recent update */
-static unsigned int led_heartbeat = 1;
-static unsigned int led_diskio = 1;
-static unsigned int led_lanrxtx = 1;
-static char lcd_text[32];
-static char lcd_text_default[32];
+static unsigned int led_heartbeat __read_mostly = 1;
+static unsigned int led_diskio __read_mostly = 1;
+static unsigned int led_lanrxtx __read_mostly = 1;
+static char lcd_text[32] __read_mostly;
+static char lcd_text_default[32] __read_mostly;
static struct workqueue_struct *led_wq;
@@ -108,7 +109,7 @@ struct pdc_chassis_lcd_info_ret_block {
/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's
* HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */
static struct pdc_chassis_lcd_info_ret_block
-lcd_info __attribute__((aligned(8))) =
+lcd_info __attribute__((aligned(8))) __read_mostly =
{
.model = DISPLAY_MODEL_LCD,
.lcd_width = 16,
@@ -144,7 +145,7 @@ static int start_task(void)
device_initcall(start_task);
/* ptr to LCD/LED-specific function */
-static void (*led_func_ptr) (unsigned char);
+static void (*led_func_ptr) (unsigned char) __read_mostly;
#ifdef CONFIG_PROC_FS
static int led_proc_read(char *page, char **start, off_t off, int count,
@@ -347,7 +348,7 @@ static void led_LCD_driver(unsigned char leds)
**
** led_get_net_activity()
**
- ** calculate if there was TX- or RX-troughput on the network interfaces
+ ** calculate if there was TX- or RX-throughput on the network interfaces
** (analog to dev_get_info() from net/core/dev.c)
**
*/
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 273a74179720..42a3c54e8e6c 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -42,9 +42,9 @@
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/sched.h> /* for capable() */
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/sysfs.h>
#include <linux/kobject.h>
@@ -56,7 +56,7 @@
#include <asm/uaccess.h>
#include <asm/hardware.h>
-#define PDCS_VERSION "0.09"
+#define PDCS_VERSION "0.10"
#define PDCS_ADDR_PPRI 0x00
#define PDCS_ADDR_OSID 0x40
@@ -70,7 +70,7 @@ MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
MODULE_LICENSE("GPL");
MODULE_VERSION(PDCS_VERSION);
-static unsigned long pdcs_size = 0;
+static unsigned long pdcs_size __read_mostly;
/* This struct defines what we need to deal with a parisc pdc path entry */
struct pdcspath_entry {
@@ -194,7 +194,8 @@ pdcspath_store(struct pdcspath_entry *entry)
return -EIO;
}
- entry->ready = 1;
+ /* kobject is already registered */
+ entry->ready = 2;
DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
@@ -653,15 +654,21 @@ pdcs_register_pathentries(void)
{
unsigned short i;
struct pdcspath_entry *entry;
+ int err;
for (i = 0; (entry = pdcspath_entries[i]); i++) {
if (pdcspath_fetch(entry) < 0)
continue;
- kobject_set_name(&entry->kobj, "%s", entry->name);
+ if ((err = kobject_set_name(&entry->kobj, "%s", entry->name)))
+ return err;
kobj_set_kset_s(entry, paths_subsys);
- kobject_register(&entry->kobj);
-
+ if ((err = kobject_register(&entry->kobj)))
+ return err;
+
+ /* kobject is now registered */
+ entry->ready = 2;
+
if (!entry->dev)
continue;
@@ -675,14 +682,14 @@ pdcs_register_pathentries(void)
/**
* pdcs_unregister_pathentries - Routine called when unregistering the module.
*/
-static inline void __exit
+static inline void
pdcs_unregister_pathentries(void)
{
unsigned short i;
struct pdcspath_entry *entry;
for (i = 0; (entry = pdcspath_entries[i]); i++)
- if (entry->ready)
+ if (entry->ready >= 2)
kobject_unregister(&entry->kobj);
}
@@ -704,7 +711,7 @@ pdc_stable_init(void)
/* For now we'll register the pdc subsys within this driver */
if ((rc = firmware_register(&pdc_subsys)))
- return rc;
+ goto fail_firmreg;
/* Don't forget the info entry */
for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
@@ -713,12 +720,25 @@ pdc_stable_init(void)
/* register the paths subsys as a subsystem of pdc subsys */
kset_set_kset_s(&paths_subsys, pdc_subsys);
- subsystem_register(&paths_subsys);
+ if ((rc= subsystem_register(&paths_subsys)))
+ goto fail_subsysreg;
/* now we create all "files" for the paths subsys */
- pdcs_register_pathentries();
+ if ((rc = pdcs_register_pathentries()))
+ goto fail_pdcsreg;
+
+ return rc;
- return 0;
+fail_pdcsreg:
+ pdcs_unregister_pathentries();
+ subsystem_unregister(&paths_subsys);
+
+fail_subsysreg:
+ firmware_unregister(&pdc_subsys);
+
+fail_firmreg:
+ printk(KERN_INFO "PDC Stable Storage bailing out\n");
+ return rc;
}
static void __exit
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index ff75e9296df9..54b2b7f20b96 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -2,7 +2,7 @@
* linux/arch/parisc/kernel/power.c
* HP PARISC soft power switch support driver
*
- * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2005 Helge Deller <deller@gmx.de>
* All rights reserved.
*
*
@@ -102,7 +102,7 @@ static DECLARE_WORK(poweroff_work, deferred_poweroff, NULL);
static void poweroff(void)
{
- static int powering_off;
+ static int powering_off __read_mostly;
if (powering_off)
return;
@@ -113,7 +113,7 @@ static void poweroff(void)
/* local time-counter for shutdown */
-static int shutdown_timer;
+static int shutdown_timer __read_mostly;
/* check, give feedback and start shutdown after one second */
static void process_shutdown(void)
@@ -139,7 +139,7 @@ static void process_shutdown(void)
DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
/* soft power switch enabled/disabled */
-int pwrsw_enabled = 1;
+int pwrsw_enabled __read_mostly = 1;
/*
* On gecko style machines (e.g. 712/xx and 715/xx)
@@ -149,7 +149,7 @@ int pwrsw_enabled = 1;
*/
static void gecko_tasklet_func(unsigned long unused)
{
- if (!pwrsw_enabled)
+ if (unlikely(!pwrsw_enabled))
return;
if (__getDIAG(25) & 0x80000000) {
@@ -173,7 +173,7 @@ static void polling_tasklet_func(unsigned long soft_power_reg)
{
unsigned long current_status;
- if (!pwrsw_enabled)
+ if (unlikely(!pwrsw_enabled))
return;
current_status = gsc_readl(soft_power_reg);
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 725a14119f2a..f605dea57224 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -34,7 +34,7 @@ config PARPORT
config PARPORT_PC
tristate "PC-style hardware"
- depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R
+ depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
@@ -77,7 +77,7 @@ config PARPORT_PC_SUPERIO
config PARPORT_PC_PCMCIA
tristate "Support for PCMCIA management for PC-style ports"
- depends on PARPORT!=n && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA)
+ depends on PCMCIA && PARPORT_PC
help
Say Y here if you need PCMCIA support for your PC-style parallel
ports. If unsure, say N.
@@ -121,6 +121,7 @@ config PARPORT_GSC
tristate
default GSC
depends on PARPORT
+ select PARPORT_NOT_PC
config PARPORT_SUNBPP
tristate "Sparc hardware (EXPERIMENTAL)"
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 075c7eb5c85d..9ee67321b630 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -144,9 +144,9 @@ again:
add_dev (numdevs++, port, -1);
/* Find out the legacy device's IEEE 1284 device ID. */
- deviceid = kmalloc (1000, GFP_KERNEL);
+ deviceid = kmalloc (1024, GFP_KERNEL);
if (deviceid) {
- if (parport_device_id (numdevs - 1, deviceid, 1000) > 2)
+ if (parport_device_id (numdevs - 1, deviceid, 1024) > 2)
detected++;
kfree (deviceid);
@@ -252,7 +252,7 @@ struct pardevice *parport_open (int devnum, const char *name,
selected = port->daisy;
parport_release (dev);
- if (selected != port->daisy) {
+ if (selected != daisy) {
/* No corresponding device. */
parport_unregister_device (dev);
return NULL;
@@ -344,9 +344,9 @@ static int cpp_daisy (struct parport *port, int cmd)
PARPORT_CONTROL_STROBE,
PARPORT_CONTROL_STROBE);
udelay (1);
+ s = parport_read_status (port);
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
udelay (1);
- s = parport_read_status (port);
parport_write_data (port, 0xff); udelay (2);
return s;
@@ -395,15 +395,15 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
case IEEE1284_MODE_EPP:
case IEEE1284_MODE_EPPSL:
case IEEE1284_MODE_EPPSWE:
- return (cpp_daisy (port, 0x20 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0x20 + daisy) &
+ PARPORT_STATUS_ERROR);
// For these modes we should switch to ECP mode:
case IEEE1284_MODE_ECP:
case IEEE1284_MODE_ECPRLE:
case IEEE1284_MODE_ECPSWE:
- return (cpp_daisy (port, 0xd0 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0xd0 + daisy) &
+ PARPORT_STATUS_ERROR);
// Nothing was told for BECP in Daisy chain specification.
// May be it's wise to use ECP?
@@ -413,8 +413,8 @@ int parport_daisy_select (struct parport *port, int daisy, int mode)
case IEEE1284_MODE_BYTE:
case IEEE1284_MODE_COMPAT:
default:
- return (cpp_daisy (port, 0xe0 + daisy) &
- PARPORT_STATUS_ERROR);
+ return !(cpp_daisy (port, 0xe0 + daisy) &
+ PARPORT_STATUS_ERROR);
}
}
@@ -436,7 +436,7 @@ static int select_port (struct parport *port)
static int assign_addrs (struct parport *port)
{
- unsigned char s, last_dev;
+ unsigned char s;
unsigned char daisy;
int thisdev = numdevs;
int detected;
@@ -472,10 +472,13 @@ static int assign_addrs (struct parport *port)
}
parport_write_data (port, 0x78); udelay (2);
- last_dev = 0; /* We've just been speaking to a device, so we
- know there must be at least _one_ out there. */
+ s = parport_read_status (port);
- for (daisy = 0; daisy < 4; daisy++) {
+ for (daisy = 0;
+ (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
+ == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
+ && daisy < 4;
+ ++daisy) {
parport_write_data (port, daisy);
udelay (2);
parport_frob_control (port,
@@ -485,14 +488,18 @@ static int assign_addrs (struct parport *port)
parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
udelay (1);
- if (last_dev)
- /* No more devices. */
- break;
+ add_dev (numdevs++, port, daisy);
- last_dev = !(parport_read_status (port)
- & PARPORT_STATUS_BUSY);
+ /* See if this device thought it was the last in the
+ * chain. */
+ if (!(s & PARPORT_STATUS_BUSY))
+ break;
- add_dev (numdevs++, port, daisy);
+ /* We are seeing pass through status now. We see
+ last_dev from next device or if last_dev does not
+ work status lines from some non-daisy chain
+ device. */
+ s = parport_read_status (port);
}
parport_write_data (port, 0xff); udelay (2);
@@ -501,11 +508,11 @@ static int assign_addrs (struct parport *port)
detected);
/* Ask the new devices to introduce themselves. */
- deviceid = kmalloc (1000, GFP_KERNEL);
+ deviceid = kmalloc (1024, GFP_KERNEL);
if (!deviceid) return 0;
for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
- parport_device_id (thisdev, deviceid, 1000);
+ parport_device_id (thisdev, deviceid, 1024);
kfree (deviceid);
return detected;
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
index ce1e2aad8b10..d6c77658231e 100644
--- a/drivers/parport/ieee1284_ops.c
+++ b/drivers/parport/ieee1284_ops.c
@@ -165,17 +165,7 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
/* Does the error line indicate end of data? */
if (((i & 1) == 0) &&
(parport_read_status(port) & PARPORT_STATUS_ERROR)) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DPRINTK (KERN_DEBUG
- "%s: No more nibble data (%d bytes)\n",
- port->name, i/2);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ goto end_of_data;
}
/* Event 7: Set nAutoFd low. */
@@ -225,18 +215,25 @@ size_t parport_ieee1284_read_nibble (struct parport *port,
byte = nibble;
}
- i /= 2; /* i is now in bytes */
-
if (i == len) {
/* Read the last nibble without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ DPRINTK (KERN_DEBUG
+ "%s: No more nibble data (%d bytes)\n",
+ port->name, i/2);
+
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
- return i;
+ return i/2;
#endif /* IEEE1284 support */
}
@@ -256,17 +253,7 @@ size_t parport_ieee1284_read_byte (struct parport *port,
/* Data available? */
if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
- port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
- DPRINTK (KERN_DEBUG
- "%s: No more byte data (%Zd bytes)\n",
- port->name, count);
-
- /* Go to reverse idle phase. */
- parport_frob_control (port,
- PARPORT_CONTROL_AUTOFD,
- PARPORT_CONTROL_AUTOFD);
- port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
- break;
+ goto end_of_data;
}
/* Event 14: Place data bus in high impedance state. */
@@ -318,11 +305,20 @@ size_t parport_ieee1284_read_byte (struct parport *port,
if (count == len) {
/* Read the last byte without checking data avail. */
- port = port->physport;
- if (parport_read_status (port) & PARPORT_STATUS_ERROR)
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+ if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+ end_of_data:
+ DPRINTK (KERN_DEBUG
+ "%s: No more byte data (%Zd bytes)\n",
+ port->name, count);
+
+ /* Go to reverse idle phase. */
+ parport_frob_control (port,
+ PARPORT_CONTROL_AUTOFD,
+ PARPORT_CONTROL_AUTOFD);
+ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+ }
else
- port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+ port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
}
return count;
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 24e6aacddb74..158d92563259 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -87,15 +87,9 @@ typedef struct parport_info_t {
struct parport *port;
} parport_info_t;
-static dev_link_t *parport_attach(void);
-static void parport_detach(dev_link_t *);
+static void parport_detach(struct pcmcia_device *p_dev);
static void parport_config(dev_link_t *link);
static void parport_cs_release(dev_link_t *);
-static int parport_event(event_t event, int priority,
- event_callback_args_t *args);
-
-static dev_info_t dev_info = "parport_cs";
-static dev_link_t *dev_list = NULL;
/*======================================================================
@@ -105,18 +99,16 @@ static dev_link_t *dev_list = NULL;
======================================================================*/
-static dev_link_t *parport_attach(void)
+static int parport_attach(struct pcmcia_device *p_dev)
{
parport_info_t *info;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
-
+
DEBUG(0, "parport_attach()\n");
/* Create new parport device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return NULL;
+ if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info;
@@ -127,21 +119,14 @@ static dev_link_t *parport_attach(void)
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
-
- /* Register with Card Services */
- 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);
- parport_detach(link);
- return NULL;
- }
-
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ parport_config(link);
+
+ return 0;
} /* parport_attach */
/*======================================================================
@@ -153,32 +138,16 @@ static dev_link_t *parport_attach(void)
======================================================================*/
-static void parport_detach(dev_link_t *link)
+static void parport_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
- int ret;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "parport_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
if (link->state & DEV_CONFIG)
parport_cs_release(link);
-
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink, free device structure */
- *linkp = link->next;
+
kfree(link->priv);
-
} /* parport_detach */
/*======================================================================
@@ -325,47 +294,27 @@ void parport_cs_release(dev_link_t *link)
} /* parport_cs_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received.
-
-======================================================================*/
-
-int parport_event(event_t event, int priority,
- event_callback_args_t *args)
+static int parport_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
- DEBUG(1, "parport_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- parport_cs_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- parport_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int parport_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
- return 0;
-} /* parport_event */
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ return 0;
+}
static struct pcmcia_device_id parport_ids[] = {
PCMCIA_DEVICE_FUNC_ID(3),
@@ -379,11 +328,11 @@ static struct pcmcia_driver parport_cs_driver = {
.drv = {
.name = "parport_cs",
},
- .attach = parport_attach,
- .event = parport_event,
- .detach = parport_detach,
+ .probe = parport_attach,
+ .remove = parport_detach,
.id_table = parport_ids,
-
+ .suspend = parport_suspend,
+ .resume = parport_resume,
};
static int __init init_parport_cs(void)
@@ -394,7 +343,6 @@ static int __init init_parport_cs(void)
static void __exit exit_parport_cs(void)
{
pcmcia_unregister_driver(&parport_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_parport_cs);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index c6493ad7c0c8..9302b8fd7461 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1169,7 +1169,7 @@ dump_parport_state ("fwd idle", port);
/* GCC is not inlining extern inline function later overwriten to non-inline,
so we use outlined_ variants here. */
-static struct parport_operations parport_pc_ops =
+static const struct parport_operations parport_pc_ops =
{
.write_data = parport_pc_write_data,
.read_data = parport_pc_read_data,
@@ -1211,10 +1211,11 @@ static struct parport_operations parport_pc_ops =
static void __devinit show_parconfig_smsc37c669(int io, int key)
{
int cr1,cr4,cra,cr23,cr26,cr27,i=0;
- static const char *modes[]={ "SPP and Bidirectional (PS/2)",
- "EPP and SPP",
- "ECP",
- "ECP and EPP" };
+ static const char *const modes[]={
+ "SPP and Bidirectional (PS/2)",
+ "EPP and SPP",
+ "ECP",
+ "ECP and EPP" };
outb(key,io);
outb(key,io);
@@ -1288,7 +1289,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key)
static void __devinit show_parconfig_winbond(int io, int key)
{
int cr30,cr60,cr61,cr70,cr74,crf0,i=0;
- static const char *modes[] = {
+ static const char *const modes[] = {
"Standard (SPP) and Bidirectional(PS/2)", /* 0 */
"EPP-1.9 and SPP",
"ECP",
@@ -1297,7 +1298,9 @@ static void __devinit show_parconfig_winbond(int io, int key)
"EPP-1.7 and SPP", /* 5 */
"undefined!",
"ECP and EPP-1.7" };
- static char *irqtypes[] = { "pulsed low, high-Z", "follows nACK" };
+ static char *const irqtypes[] = {
+ "pulsed low, high-Z",
+ "follows nACK" };
/* The registers are called compatible-PnP because the
register layout is modelled after ISA-PnP, the access
@@ -2368,8 +2371,10 @@ void parport_pc_unregister_port (struct parport *p)
spin_lock(&ports_lock);
list_del_init(&priv->list);
spin_unlock(&ports_lock);
+#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA)
if (p->dma != PARPORT_DMA_NONE)
free_dma(p->dma);
+#endif
if (p->irq != PARPORT_IRQ_NONE)
free_irq(p->irq, p);
release_region(p->base, 3);
@@ -2377,14 +2382,12 @@ void parport_pc_unregister_port (struct parport *p)
release_region(p->base + 3, p->size - 3);
if (p->modes & PARPORT_MODE_ECP)
release_region(p->base_hi, 3);
-#ifdef CONFIG_PARPORT_PC_FIFO
-#ifdef HAS_DMA
+#if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA)
if (priv->dma_buf)
pci_free_consistent(priv->dev, PAGE_SIZE,
priv->dma_buf,
priv->dma_handle);
#endif
-#endif
kfree (p->private_data);
parport_put_port(p);
kfree (ops); /* hope no-one cached it */
@@ -2396,7 +2399,8 @@ EXPORT_SYMBOL (parport_pc_unregister_port);
/* ITE support maintained by Rich Liu <richliu@poorman.org> */
static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
- int autodma, struct parport_pc_via_data *via)
+ int autodma,
+ const struct parport_pc_via_data *via)
{
short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
struct resource *base_res;
@@ -2524,7 +2528,8 @@ static struct parport_pc_via_data via_8231_data __devinitdata = {
};
static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq,
- int autodma, struct parport_pc_via_data *via)
+ int autodma,
+ const struct parport_pc_via_data *via)
{
u8 tmp, tmp2, siofunc;
u8 ppcontrol = 0;
@@ -2694,8 +2699,9 @@ enum parport_pc_sio_types {
/* each element directly indexed from enum list, above */
static struct parport_pc_superio {
- int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via);
- struct parport_pc_via_data *via;
+ int (*probe) (struct pci_dev *pdev, int autoirq, int autodma,
+ const struct parport_pc_via_data *via);
+ const struct parport_pc_via_data *via;
} parport_pc_superio_info[] __devinitdata = {
{ sio_via_probe, &via_686a_data, },
{ sio_via_probe, &via_8231_data, },
@@ -2828,7 +2834,7 @@ static struct parport_pc_pci {
/* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
};
-static struct pci_device_id parport_pc_pci_tbl[] = {
+static const struct pci_device_id parport_pc_pci_tbl[] = {
/* Super-IO onboard chips */
{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
{ 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 },
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index d3dad0aac7cb..76dd077e3184 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -464,7 +464,7 @@ static struct pci_driver parport_serial_pci_driver = {
static int __init parport_serial_init (void)
{
- return pci_module_init (&parport_serial_pci_driver);
+ return pci_register_driver (&parport_serial_pci_driver);
}
static void __exit parport_serial_exit (void)
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index 4b48b31ec235..b62aee8de3cb 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -11,9 +11,9 @@
#include <linux/string.h>
#include <asm/uaccess.h>
-static struct {
- char *token;
- char *descr;
+static const struct {
+ const char *token;
+ const char *descr;
} classes[] = {
{ "", "Legacy device" },
{ "PRINTER", "Printer" },
@@ -128,8 +128,131 @@ static void parse_data(struct parport *port, int device, char *str)
kfree(txt);
}
+/* Read up to count-1 bytes of device id. Terminate buffer with
+ * '\0'. Buffer begins with two Device ID length bytes as given by
+ * device. */
+static ssize_t parport_read_device_id (struct parport *port, char *buffer,
+ size_t count)
+{
+ unsigned char length[2];
+ unsigned lelen, belen;
+ size_t idlens[4];
+ unsigned numidlens;
+ unsigned current_idlen;
+ ssize_t retval;
+ size_t len;
+
+ /* First two bytes are MSB,LSB of inclusive length. */
+ retval = parport_read (port, length, 2);
+
+ if (retval < 0)
+ return retval;
+ if (retval != 2)
+ return -EIO;
+
+ if (count < 2)
+ return 0;
+ memcpy(buffer, length, 2);
+ len = 2;
+
+ /* Some devices wrongly send LE length, and some send it two
+ * bytes short. Construct a sorted array of lengths to try. */
+ belen = (length[0] << 8) + length[1];
+ lelen = (length[1] << 8) + length[0];
+ idlens[0] = min(belen, lelen);
+ idlens[1] = idlens[0]+2;
+ if (belen != lelen) {
+ int off = 2;
+ /* Don't try lenghts of 0x100 and 0x200 as 1 and 2 */
+ if (idlens[0] <= 2)
+ off = 0;
+ idlens[off] = max(belen, lelen);
+ idlens[off+1] = idlens[off]+2;
+ numidlens = off+2;
+ }
+ else {
+ /* Some devices don't truly implement Device ID, but
+ * just return constant nibble forever. This catches
+ * also those cases. */
+ if (idlens[0] == 0 || idlens[0] > 0xFFF) {
+ printk (KERN_DEBUG "%s: reported broken Device ID"
+ " length of %#zX bytes\n",
+ port->name, idlens[0]);
+ return -EIO;
+ }
+ numidlens = 2;
+ }
+
+ /* Try to respect the given ID length despite all the bugs in
+ * the ID length. Read according to shortest possible ID
+ * first. */
+ for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) {
+ size_t idlen = idlens[current_idlen];
+ if (idlen+1 >= count)
+ break;
+
+ retval = parport_read (port, buffer+len, idlen-len);
+
+ if (retval < 0)
+ return retval;
+ len += retval;
+
+ if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) {
+ if (belen != len) {
+ printk (KERN_DEBUG "%s: Device ID was %d bytes"
+ " while device told it would be %d"
+ " bytes\n",
+ port->name, len, belen);
+ }
+ goto done;
+ }
+
+ /* This might end reading the Device ID too
+ * soon. Hopefully the needed fields were already in
+ * the first 256 bytes or so that we must have read so
+ * far. */
+ if (buffer[len-1] == ';') {
+ printk (KERN_DEBUG "%s: Device ID reading stopped"
+ " before device told data not available. "
+ "Current idlen %d of %d, len bytes %02X %02X\n",
+ port->name, current_idlen, numidlens,
+ length[0], length[1]);
+ goto done;
+ }
+ }
+ if (current_idlen < numidlens) {
+ /* Buffer not large enough, read to end of buffer. */
+ size_t idlen, len2;
+ if (len+1 < count) {
+ retval = parport_read (port, buffer+len, count-len-1);
+ if (retval < 0)
+ return retval;
+ len += retval;
+ }
+ /* Read the whole ID since some devices would not
+ * otherwise give back the Device ID from beginning
+ * next time when asked. */
+ idlen = idlens[current_idlen];
+ len2 = len;
+ while(len2 < idlen && retval > 0) {
+ char tmp[4];
+ retval = parport_read (port, tmp,
+ min(sizeof tmp, idlen-len2));
+ if (retval < 0)
+ return retval;
+ len2 += retval;
+ }
+ }
+ /* In addition, there are broken devices out there that don't
+ even finish off with a semi-colon. We do not need to care
+ about those at this time. */
+ done:
+ buffer[len] = '\0';
+ return len;
+}
+
/* Get Std 1284 Device ID. */
-ssize_t parport_device_id (int devnum, char *buffer, size_t len)
+ssize_t parport_device_id (int devnum, char *buffer, size_t count)
{
ssize_t retval = -ENXIO;
struct pardevice *dev = parport_open (devnum, "Device ID probe",
@@ -139,76 +262,20 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t len)
parport_claim_or_block (dev);
- /* Negotiate to compatibility mode, and then to device ID mode.
- * (This is in case we are already in device ID mode.) */
+ /* Negotiate to compatibility mode, and then to device ID
+ * mode. (This so that we start form beginning of device ID if
+ * already in device ID mode.) */
parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
retval = parport_negotiate (dev->port,
IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
if (!retval) {
- int idlen;
- unsigned char length[2];
-
- /* First two bytes are MSB,LSB of inclusive length. */
- retval = parport_read (dev->port, length, 2);
-
- if (retval != 2) goto end_id;
-
- idlen = (length[0] << 8) + length[1] - 2;
- /*
- * Check if the caller-allocated buffer is large enough
- * otherwise bail out or there will be an at least off by one.
- */
- if (idlen + 1 < len)
- len = idlen;
- else {
- retval = -EINVAL;
- goto out;
- }
- retval = parport_read (dev->port, buffer, len);
-
- if (retval != len)
- printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n",
- dev->port->name, retval,
- len);
-
- /* Some printer manufacturers mistakenly believe that
- the length field is supposed to be _exclusive_.
- In addition, there are broken devices out there
- that don't even finish off with a semi-colon. */
- if (buffer[len - 1] != ';') {
- ssize_t diff;
- diff = parport_read (dev->port, buffer + len, 2);
- retval += diff;
-
- if (diff)
- printk (KERN_DEBUG
- "%s: device reported incorrect "
- "length field (%d, should be %Zd)\n",
- dev->port->name, idlen, retval);
- else {
- /* One semi-colon short of a device ID. */
- buffer[len++] = ';';
- printk (KERN_DEBUG "%s: faking semi-colon\n",
- dev->port->name);
-
- /* If we get here, I don't think we
- need to worry about the possible
- standard violation of having read
- more than we were told to. The
- device is non-compliant anyhow. */
- }
- }
-
- end_id:
- buffer[len] = '\0';
+ retval = parport_read_device_id (dev->port, buffer, count);
parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
+ if (retval > 2)
+ parse_data (dev->port, dev->daisy, buffer+2);
}
- if (retval > 2)
- parse_data (dev->port, dev->daisy, buffer);
-
-out:
parport_release (dev);
parport_close (dev);
return retval;
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 9cb3ab156b09..ea62bed6bc83 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -1002,6 +1002,7 @@ EXPORT_SYMBOL(parport_register_driver);
EXPORT_SYMBOL(parport_unregister_driver);
EXPORT_SYMBOL(parport_register_device);
EXPORT_SYMBOL(parport_unregister_device);
+EXPORT_SYMBOL(parport_get_port);
EXPORT_SYMBOL(parport_put_port);
EXPORT_SYMBOL(parport_find_number);
EXPORT_SYMBOL(parport_find_base);
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index e1743be31909..1c97e7dd130b 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -3,8 +3,8 @@
#include <linux/module.h>
#include "pci.h"
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct pci_dev *pdev;
int i = 0;
@@ -17,34 +17,34 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
if (!pdev)
return -ENODEV;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_CLASS=%04X", pdev->class))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_CLASS=%04X", pdev->class))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
- pdev->subsystem_device))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
+ pdev->subsystem_device))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PCI_SLOT_NAME=%s", pci_name(pdev)))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PCI_SLOT_NAME=%s", pci_name(pdev)))
return -ENOMEM;
- 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)))
+ if (add_uevent_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/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 8e21f6ab89a1..509a5b3ae998 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -794,12 +794,14 @@ static int enable_device(struct acpiphp_slot *slot)
if (PCI_SLOT(dev->devfn) != slot->device)
continue;
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
+ if (pass && dev->subordinate)
+ pci_bus_size_bridges(dev->subordinate);
+ }
}
}
- pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
pci_enable_bridges(bus);
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index 092491e25ef2..cb88404c89fe 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -317,6 +317,7 @@ struct controller {
u16 vendor_id;
struct work_struct int_task_event;
wait_queue_head_t queue; /* sleep & wake process */
+ struct dentry *dentry; /* debugfs dentry */
};
struct irq_mapping {
@@ -399,8 +400,11 @@ struct resource_lists {
#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
-/* sysfs functions for the hotplug controller info */
-extern void cpqhp_create_ctrl_files (struct controller *ctrl);
+/* debugfs functions for the hotplug controller info */
+extern void cpqhp_initialize_debugfs (void);
+extern void cpqhp_shutdown_debugfs (void);
+extern void cpqhp_create_debugfs_files (struct controller *ctrl);
+extern void cpqhp_remove_debugfs_files (struct controller *ctrl);
/* controller functions */
extern void cpqhp_pushbutton_thread (unsigned long event_pointer);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 9aed8efe6a11..b3659ffccac9 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -327,7 +327,9 @@ static int ctrl_slot_setup(struct controller *ctrl,
void __iomem *smbios_start,
void __iomem *smbios_table)
{
- struct slot *new_slot;
+ struct slot *slot;
+ struct hotplug_slot *hotplug_slot;
+ struct hotplug_slot_info *hotplug_slot_info;
u8 number_of_slots;
u8 slot_device;
u8 slot_number;
@@ -345,93 +347,105 @@ static int ctrl_slot_setup(struct controller *ctrl,
slot_number = ctrl->first_slot;
while (number_of_slots) {
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
- if (!new_slot)
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
goto error;
- memset(new_slot, 0, sizeof(struct slot));
- new_slot->hotplug_slot = kmalloc(sizeof(*(new_slot->hotplug_slot)),
+ memset(slot, 0, sizeof(struct slot));
+ slot->hotplug_slot = kmalloc(sizeof(*(slot->hotplug_slot)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot)
+ if (!slot->hotplug_slot)
goto error_slot;
- memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+ hotplug_slot = slot->hotplug_slot;
+ memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
- new_slot->hotplug_slot->info =
- kmalloc(sizeof(*(new_slot->hotplug_slot->info)),
+ hotplug_slot->info =
+ kmalloc(sizeof(*(hotplug_slot->info)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot->info)
+ if (!hotplug_slot->info)
goto error_hpslot;
- memset(new_slot->hotplug_slot->info, 0,
+ hotplug_slot_info = hotplug_slot->info;
+ memset(hotplug_slot_info, 0,
sizeof(struct hotplug_slot_info));
- new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
- if (!new_slot->hotplug_slot->name)
+ hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+
+ if (!hotplug_slot->name)
goto error_info;
- new_slot->ctrl = ctrl;
- new_slot->bus = ctrl->bus;
- new_slot->device = slot_device;
- new_slot->number = slot_number;
- dbg("slot->number = %d\n",new_slot->number);
+ slot->ctrl = ctrl;
+ slot->bus = ctrl->bus;
+ slot->device = slot_device;
+ slot->number = slot_number;
+ dbg("slot->number = %d\n", slot->number);
slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9,
slot_entry);
- while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {
+ while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) !=
+ slot->number)) {
slot_entry = get_SMBIOS_entry(smbios_start,
smbios_table, 9, slot_entry);
}
- new_slot->p_sm_slot = slot_entry;
+ slot->p_sm_slot = slot_entry;
- init_timer(&new_slot->task_event);
- new_slot->task_event.expires = jiffies + 5 * HZ;
- new_slot->task_event.function = cpqhp_pushbutton_thread;
+ init_timer(&slot->task_event);
+ slot->task_event.expires = jiffies + 5 * HZ;
+ slot->task_event.function = cpqhp_pushbutton_thread;
//FIXME: these capabilities aren't used but if they are
// they need to be correctly implemented
- new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
- new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
+ slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;
+ slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;
- if (is_slot64bit(new_slot))
- new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
- if (is_slot66mhz(new_slot))
- new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
+ if (is_slot64bit(slot))
+ slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
+ if (is_slot66mhz(slot))
+ slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
if (ctrl->speed == PCI_SPEED_66MHz)
- new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
+ slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
- ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
+ ctrl_slot =
+ slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);
// Check presence
- new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
+ slot->capabilities |=
+ ((((~tempdword) >> 23) |
+ ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;
// Check the switch state
- new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
+ slot->capabilities |=
+ ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;
// Check the slot enable
- new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
+ slot->capabilities |=
+ ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
/* register this slot with the hotplug pci core */
- new_slot->hotplug_slot->release = &release_slot;
- new_slot->hotplug_slot->private = new_slot;
- make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
- new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
+ hotplug_slot->release = &release_slot;
+ hotplug_slot->private = slot;
+ make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
+ hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
- new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);
- new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);
- new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);
- new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);
+ hotplug_slot_info->power_status = get_slot_enabled(ctrl, slot);
+ hotplug_slot_info->attention_status =
+ cpq_get_attention_status(ctrl, slot);
+ hotplug_slot_info->latch_status =
+ cpq_get_latch_status(ctrl, slot);
+ hotplug_slot_info->adapter_status =
+ get_presence_status(ctrl, slot);
- dbg ("registering bus %d, dev %d, number %d, "
+ dbg("registering bus %d, dev %d, number %d, "
"ctrl->slot_device_offset %d, slot %d\n",
- new_slot->bus, new_slot->device,
- new_slot->number, ctrl->slot_device_offset,
+ slot->bus, slot->device,
+ slot->number, ctrl->slot_device_offset,
slot_number);
- result = pci_hp_register (new_slot->hotplug_slot);
+ result = pci_hp_register(hotplug_slot);
if (result) {
- err ("pci_hp_register failed with error %d\n", result);
+ err("pci_hp_register failed with error %d\n", result);
goto error_name;
}
- new_slot->next = ctrl->slot;
- ctrl->slot = new_slot;
+ slot->next = ctrl->slot;
+ ctrl->slot = slot;
number_of_slots--;
slot_device++;
@@ -439,15 +453,14 @@ static int ctrl_slot_setup(struct controller *ctrl,
}
return 0;
-
error_name:
- kfree(new_slot->hotplug_slot->name);
+ kfree(hotplug_slot->name);
error_info:
- kfree(new_slot->hotplug_slot->info);
+ kfree(hotplug_slot_info);
error_hpslot:
- kfree(new_slot->hotplug_slot);
+ kfree(hotplug_slot);
error_slot:
- kfree(new_slot);
+ kfree(slot);
error:
return result;
}
@@ -466,6 +479,8 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
old_slot = next_slot;
}
+ cpqhp_remove_debugfs_files(ctrl);
+
//Free IRQ associated with hot plug device
free_irq(ctrl->interrupt, ctrl);
//Unmap the memory
@@ -1262,7 +1277,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
// Done with exclusive hardware access
up(&ctrl->crit_sect);
- cpqhp_create_ctrl_files(ctrl);
+ cpqhp_create_debugfs_files(ctrl);
return 0;
@@ -1502,6 +1517,7 @@ static int __init cpqhpc_init(void)
cpqhp_debug = debug;
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ cpqhp_initialize_debugfs();
result = pci_register_driver(&cpqhpc_driver);
dbg("pci_register_driver = %d\n", result);
return result;
@@ -1515,6 +1531,7 @@ static void __exit cpqhpc_cleanup(void)
dbg("pci_unregister_driver\n");
pci_unregister_driver(&cpqhpc_driver);
+ cpqhp_shutdown_debugfs();
}
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 10a5a7674a8a..771ed34b1819 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -2630,29 +2630,15 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
hold_mem_node = NULL;
}
- /* If we have prefetchable memory resources copy them and
- * fill in the bridge's memory range registers. Otherwise,
- * fill in the range registers with values that disable them. */
- if (p_mem_node) {
- memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
- p_mem_node->next = NULL;
-
- /* set Pre Mem base and Limit registers */
- temp_word = p_mem_node->base >> 16;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
+ memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
+ p_mem_node->next = NULL;
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
+ /* set Pre Mem base and Limit registers */
+ temp_word = p_mem_node->base >> 16;
+ rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
- kfree(hold_p_mem_node);
- hold_p_mem_node = NULL;
- }
+ temp_word = (p_mem_node->base + p_mem_node->length - 1) >> 16;
+ rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
/* Adjust this to compensate for extra adjustment in first loop */
irqs.barber_pole--;
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 4c11048ad51b..bbfeed767ff1 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -33,22 +33,15 @@
#include <linux/proc_fs.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
+#include <linux/debugfs.h>
#include "cpqphp.h"
-
-/* A few routines that create sysfs entries for the hot plug controller */
-
-static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
+static int show_ctrl (struct controller *ctrl, char *buf)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
- char * out = buf;
+ char *out = buf;
int index;
struct pci_resource *res;
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
-
out += sprintf(buf, "Free resources: memory\n");
index = 11;
res = ctrl->mem_head;
@@ -80,22 +73,16 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
return out - buf;
}
-static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
+static int show_dev (struct controller *ctrl, char *buf)
{
- struct pci_dev *pci_dev;
- struct controller *ctrl;
char * out = buf;
int index;
struct pci_resource *res;
struct pci_func *new_slot;
struct slot *slot;
- pci_dev = container_of (dev, struct pci_dev, dev);
- ctrl = pci_get_drvdata(pci_dev);
-
- slot=ctrl->slot;
+ slot = ctrl->slot;
while (slot) {
new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
@@ -134,10 +121,117 @@ static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char
return out - buf;
}
-static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL);
-void cpqhp_create_ctrl_files (struct controller *ctrl)
+static int spew_debug_info(struct controller *ctrl, char *data, int size)
{
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
- device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev);
+ int used;
+
+ used = size - show_ctrl(ctrl, data);
+ used = (size - used) - show_dev(ctrl, &data[used]);
+ return used;
+}
+
+struct ctrl_dbg {
+ int size;
+ char *data;
+ struct controller *ctrl;
+};
+
+#define MAX_OUTPUT (4*PAGE_SIZE)
+
+static int open(struct inode *inode, struct file *file)
+{
+ struct controller *ctrl = inode->u.generic_ip;
+ struct ctrl_dbg *dbg;
+ int retval = -ENOMEM;
+
+ lock_kernel();
+ dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
+ if (!dbg)
+ goto exit;
+ dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
+ if (!dbg->data) {
+ kfree(dbg);
+ goto exit;
+ }
+ dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT);
+ file->private_data = dbg;
+ retval = 0;
+exit:
+ unlock_kernel();
+ return retval;
+}
+
+static loff_t lseek(struct file *file, loff_t off, int whence)
+{
+ struct ctrl_dbg *dbg;
+ loff_t new = -1;
+
+ lock_kernel();
+ dbg = file->private_data;
+
+ switch (whence) {
+ case 0:
+ new = off;
+ break;
+ case 1:
+ new = file->f_pos + off;
+ break;
+ }
+ if (new < 0 || new > dbg->size) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ unlock_kernel();
+ return (file->f_pos = new);
}
+
+static ssize_t read(struct file *file, char __user *buf,
+ size_t nbytes, loff_t *ppos)
+{
+ struct ctrl_dbg *dbg = file->private_data;
+ return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size);
+}
+
+static int release(struct inode *inode, struct file *file)
+{
+ struct ctrl_dbg *dbg = file->private_data;
+
+ kfree(dbg->data);
+ kfree(dbg);
+ return 0;
+}
+
+static struct file_operations debug_ops = {
+ .owner = THIS_MODULE,
+ .open = open,
+ .llseek = lseek,
+ .read = read,
+ .release = release,
+};
+
+static struct dentry *root;
+
+void cpqhp_initialize_debugfs(void)
+{
+ if (!root)
+ root = debugfs_create_dir("cpqhp", NULL);
+}
+
+void cpqhp_shutdown_debugfs(void)
+{
+ debugfs_remove(root);
+}
+
+void cpqhp_create_debugfs_files(struct controller *ctrl)
+{
+ ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops);
+}
+
+void cpqhp_remove_debugfs_files(struct controller *ctrl)
+{
+ if (ctrl->dentry)
+ debugfs_remove(ctrl->dentry);
+ ctrl->dentry = NULL;
+}
+
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index b1ba429e0a2d..155133fe5c12 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -969,7 +969,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
debug ("io 32\n");
need_io_upper = TRUE;
}
- if ((io_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+ if ((pfmem_base & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
debug ("pfmem 64\n");
need_pfmem_upper = TRUE;
}
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 6a61b9f286e1..0aac6a61337d 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -32,6 +32,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/sched.h> /* signal_pending() */
#include <linux/pcieport_if.h>
#include "pci_hotplug.h"
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 8df704860348..4fb569018a24 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -103,7 +103,10 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
static int init_slots(struct controller *ctrl)
{
- struct slot *new_slot;
+ struct slot *slot;
+ struct hpc_ops *hpc_ops;
+ struct hotplug_slot *hotplug_slot;
+ struct hotplug_slot_info *hotplug_slot_info;
u8 number_of_slots;
u8 slot_device;
u32 slot_number;
@@ -114,59 +117,66 @@ static int init_slots(struct controller *ctrl)
slot_number = ctrl->first_slot;
while (number_of_slots) {
- new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);
- if (!new_slot)
+ slot = kmalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot)
goto error;
- memset(new_slot, 0, sizeof(struct slot));
- new_slot->hotplug_slot =
- kmalloc(sizeof(*(new_slot->hotplug_slot)),
+ memset(slot, 0, sizeof(struct slot));
+ slot->hotplug_slot =
+ kmalloc(sizeof(*(slot->hotplug_slot)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot)
+ if (!slot->hotplug_slot)
goto error_slot;
- memset(new_slot->hotplug_slot, 0, sizeof(struct hotplug_slot));
+ hotplug_slot = slot->hotplug_slot;
+ memset(hotplug_slot, 0, sizeof(struct hotplug_slot));
- new_slot->hotplug_slot->info =
- kmalloc(sizeof(*(new_slot->hotplug_slot->info)),
+ hotplug_slot->info =
+ kmalloc(sizeof(*(hotplug_slot->info)),
GFP_KERNEL);
- if (!new_slot->hotplug_slot->info)
+ if (!hotplug_slot->info)
goto error_hpslot;
- memset(new_slot->hotplug_slot->info, 0,
+ hotplug_slot_info = hotplug_slot->info;
+ memset(hotplug_slot_info, 0,
sizeof(struct hotplug_slot_info));
- new_slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE,
- GFP_KERNEL);
- if (!new_slot->hotplug_slot->name)
+ hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL);
+ if (!hotplug_slot->name)
goto error_info;
- new_slot->ctrl = ctrl;
- new_slot->bus = ctrl->slot_bus;
- new_slot->device = slot_device;
- new_slot->hpc_ops = ctrl->hpc_ops;
+ slot->ctrl = ctrl;
+ slot->bus = ctrl->slot_bus;
+ slot->device = slot_device;
+ slot->hpc_ops = hpc_ops = ctrl->hpc_ops;
- new_slot->number = ctrl->first_slot;
- new_slot->hp_slot = slot_device - ctrl->slot_device_offset;
+ slot->number = ctrl->first_slot;
+ slot->hp_slot = slot_device - ctrl->slot_device_offset;
/* register this slot with the hotplug pci core */
- new_slot->hotplug_slot->private = new_slot;
- new_slot->hotplug_slot->release = &release_slot;
- make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);
- new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops;
-
- new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status));
- new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status));
- new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status));
- new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status));
-
- dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n",
- new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset);
- result = pci_hp_register (new_slot->hotplug_slot);
+ hotplug_slot->private = slot;
+ hotplug_slot->release = &release_slot;
+ make_slot_name(hotplug_slot->name, SLOT_NAME_SIZE, slot);
+ hotplug_slot->ops = &pciehp_hotplug_slot_ops;
+
+ hpc_ops->get_power_status(slot,
+ &(hotplug_slot_info->power_status));
+ hpc_ops->get_attention_status(slot,
+ &(hotplug_slot_info->attention_status));
+ hpc_ops->get_latch_status(slot,
+ &(hotplug_slot_info->latch_status));
+ hpc_ops->get_adapter_status(slot,
+ &(hotplug_slot_info->adapter_status));
+
+ dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
+ "slot_device_offset=%x\n",
+ slot->bus, slot->device, slot->hp_slot, slot->number,
+ ctrl->slot_device_offset);
+ result = pci_hp_register(hotplug_slot);
if (result) {
err ("pci_hp_register failed with error %d\n", result);
goto error_name;
}
- new_slot->next = ctrl->slot;
- ctrl->slot = new_slot;
+ slot->next = ctrl->slot;
+ ctrl->slot = slot;
number_of_slots--;
slot_device++;
@@ -176,13 +186,13 @@ static int init_slots(struct controller *ctrl)
return 0;
error_name:
- kfree(new_slot->hotplug_slot->name);
+ kfree(hotplug_slot->name);
error_info:
- kfree(new_slot->hotplug_slot->info);
+ kfree(hotplug_slot_info);
error_hpslot:
- kfree(new_slot->hotplug_slot);
+ kfree(hotplug_slot);
error_slot:
- kfree(new_slot);
+ kfree(slot);
error:
return result;
}
@@ -502,7 +512,7 @@ static void __exit unload_pciehpd(void)
}
-int hpdriver_context = 0;
+static int hpdriver_context = 0;
static void pciehp_remove (struct pcie_device *device)
{
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0b8b26beb163..77e530321de2 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -30,6 +30,9 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/signal.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
@@ -784,8 +787,13 @@ static int hpc_power_on_slot(struct slot * slot)
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
+ /* Enable detection that we turned off at slot power-off time */
if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ slot_cmd = slot_cmd |
+ PWR_FAULT_DETECT_ENABLE |
+ MRL_DETECT_ENABLE |
+ PRSN_DETECT_ENABLE |
+ HP_INTR_ENABLE;
retval = pcie_write_cmd(slot, slot_cmd);
@@ -830,8 +838,18 @@ static int hpc_power_off_slot(struct slot * slot)
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
+ /*
+ * If we get MRL or presence detect interrupts now, the isr
+ * will notice the sticky power-fault bit too and issue power
+ * indicator change commands. This will lead to an endless loop
+ * of command completions, since the power-fault bit remains on
+ * till the slot is powered on again.
+ */
if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ slot_cmd = (slot_cmd &
+ ~PWR_FAULT_DETECT_ENABLE &
+ ~MRL_DETECT_ENABLE &
+ ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
retval = pcie_write_cmd(slot, slot_cmd);
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 647673a7d224..4017fb03a0b8 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -34,6 +34,31 @@
#include "../pci.h"
#include "pciehp.h"
+static int pciehp_add_bridge(struct pci_dev *dev)
+{
+ struct pci_bus *parent = dev->bus;
+ int pass, busnr, start = parent->secondary;
+ int end = parent->subordinate;
+
+ for (busnr = start; busnr <= end; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(parent), busnr))
+ break;
+ }
+ if (busnr-- > end) {
+ err("No bus number available for hot-added bridge %s\n",
+ pci_name(dev));
+ return -1;
+ }
+ for (pass = 0; pass < 2; pass++)
+ busnr = pci_scan_bridge(parent, dev, busnr, pass);
+ if (!dev->subordinate)
+ return -1;
+ pci_bus_size_bridges(dev->subordinate);
+ pci_bus_assign_resources(parent);
+ pci_enable_bridges(parent);
+ pci_bus_add_devices(parent);
+ return 0;
+}
int pciehp_configure_device(struct slot *p_slot)
{
@@ -55,8 +80,8 @@ int pciehp_configure_device(struct slot *p_slot)
}
for (fn = 0; fn < 8; fn++) {
- if (!(dev = pci_find_slot(p_slot->bus,
- PCI_DEVFN(p_slot->device, fn))))
+ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
+ if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot hot-add display device %s\n",
@@ -65,27 +90,7 @@ int pciehp_configure_device(struct slot *p_slot)
}
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
- /* Find an unused bus number for the new bridge */
- struct pci_bus *child;
- unsigned char busnr, start = parent->secondary;
- unsigned char end = parent->subordinate;
- for (busnr = start; busnr <= end; busnr++) {
- if (!pci_find_bus(pci_domain_nr(parent),
- busnr))
- break;
- }
- if (busnr >= end) {
- err("No free bus for hot-added bridge\n");
- continue;
- }
- child = pci_add_new_bus(parent, dev, busnr);
- if (!child) {
- err("Cannot add new bus for %s\n",
- pci_name(dev));
- continue;
- }
- child->subordinate = pci_do_scan_bus(child);
- pci_bus_size_bridges(child);
+ pciehp_add_bridge(dev);
}
/* TBD: program firmware provided _HPP values */
/* program_fw_provided_values(dev); */
@@ -93,7 +98,6 @@ int pciehp_configure_device(struct slot *p_slot)
pci_bus_assign_resources(parent);
pci_bus_add_devices(parent);
- pci_enable_bridges(parent);
return 0;
}
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index ae244e218620..2bdb30f68bf8 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -174,7 +174,9 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
acpi_status status;
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
struct pci_dev *pdev = dev;
+ struct pci_bus *parent;
u8 *path_name;
+
/*
* Per PCI firmware specification, we should run the ACPI _OSC
* method to get control of hotplug hardware before using it.
@@ -190,17 +192,18 @@ int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
*/
if (!pdev || !pdev->bus->parent)
break;
+ parent = pdev->bus->parent;
dbg("Could not find %s in acpi namespace, trying parent\n",
pci_name(pdev));
- if (!pdev->bus->parent->self)
+ if (!parent->self)
/* Parent must be a host bridge */
handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(pdev->bus->parent),
- pdev->bus->parent->number);
+ pci_domain_nr(parent),
+ parent->number);
else
handle = DEVICE_ACPI_HANDLE(
- &(pdev->bus->parent->self->dev));
- pdev = pdev->bus->parent->self;
+ &(parent->self->dev));
+ pdev = parent->self;
}
while (handle) {
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index cc03609f45d0..7d93dbaf628d 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -112,28 +112,6 @@ static struct slot *find_slot(struct device_node *dn)
return NULL;
}
-static void rpadlpar_claim_one_bus(struct pci_bus *b)
-{
- struct list_head *ld;
- struct pci_bus *child_bus;
-
- for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
- struct pci_dev *dev = pci_dev_b(ld);
- int i;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *r = &dev->resource[i];
-
- if (r->parent || !r->start || !r->flags)
- continue;
- rpaphp_claim_resource(dev, i);
- }
- }
-
- list_for_each_entry(child_bus, &b->children, node)
- rpadlpar_claim_one_bus(child_bus);
-}
-
static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
struct device_node *dev_dn)
{
@@ -154,7 +132,8 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
struct pci_controller *phb = pdn->phb;
struct pci_dev *dev = NULL;
- rpaphp_eeh_init_nodes(dn);
+ eeh_add_device_tree_early(dn);
+
/* Add EADS device to PHB bus, adding new entry to bus->devices */
dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
if (!dev) {
@@ -170,7 +149,7 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
rpaphp_init_new_devs(dev->subordinate);
/* Claim new bus resources */
- rpadlpar_claim_one_bus(dev->bus);
+ pcibios_claim_one_bus(dev->bus);
/* ioremap() for child bus, which may or may not succeed */
(void) remap_bus_range(dev->bus);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 4b35097b3d9f..396b54b0c847 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -62,28 +62,6 @@ struct pci_bus *rpaphp_find_pci_bus(struct device_node *dn)
}
EXPORT_SYMBOL_GPL(rpaphp_find_pci_bus);
-int rpaphp_claim_resource(struct pci_dev *dev, int resource)
-{
- struct resource *res = &dev->resource[resource];
- struct resource *root = pci_find_parent_resource(dev, res);
- char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
- int err = -EINVAL;
-
- if (root != NULL) {
- err = request_resource(root, res);
- }
-
- if (err) {
- err("PCI: %s region %d of %s %s [%lx:%lx]\n",
- root ? "Address space collision on" :
- "No parent found for",
- resource, dtype, pci_name(dev), res->start, res->end);
- }
- return err;
-}
-
-EXPORT_SYMBOL_GPL(rpaphp_claim_resource);
-
static int rpaphp_get_sensor_state(struct slot *slot, int *state)
{
int rc;
@@ -177,7 +155,7 @@ void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
if (r->parent || !r->start || !r->flags)
continue;
- rpaphp_claim_resource(dev, i);
+ pci_claim_resource(dev, i);
}
}
}
@@ -287,18 +265,6 @@ rpaphp_pci_config_slot(struct pci_bus *bus)
return dev;
}
-void rpaphp_eeh_init_nodes(struct device_node *dn)
-{
- struct device_node *sib;
-
- for (sib = dn->child; sib; sib = sib->sibling)
- rpaphp_eeh_init_nodes(sib);
- eeh_add_device_early(dn);
- return;
-
-}
-EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes);
-
static void print_slot_pci_funcs(struct pci_bus *bus)
{
struct device_node *dn;
@@ -324,7 +290,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus)
if (!dn)
goto exit;
- rpaphp_eeh_init_nodes(dn);
+ eeh_add_device_tree_early(dn);
dev = rpaphp_pci_config_slot(bus);
if (!dev) {
err("%s: can't find any devices.\n", __FUNCTION__);
@@ -370,13 +336,14 @@ EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
static int setup_pci_hotplug_slot_info(struct slot *slot)
{
+ struct hotplug_slot_info *hotplug_slot_info = slot->hotplug_slot->info;
+
dbg("%s Initilize the PCI slot's hotplug->info structure ...\n",
__FUNCTION__);
- rpaphp_get_power_status(slot, &slot->hotplug_slot->info->power_status);
+ rpaphp_get_power_status(slot, &hotplug_slot_info->power_status);
rpaphp_get_pci_adapter_status(slot, 1,
- &slot->hotplug_slot->info->
- adapter_status);
- if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
+ &hotplug_slot_info->adapter_status);
+ if (hotplug_slot_info->adapter_status == NOT_VALID) {
err("%s: NOT_VALID: skip dn->full_name=%s\n",
__FUNCTION__, slot->dn->full_name);
return -EINVAL;
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 08ad26a0cae7..ce0e9b6ce833 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -98,6 +98,10 @@ struct controller {
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
+ u32 cap_offset;
+ unsigned long mmio_base;
+ unsigned long mmio_size;
+ volatile int cmd_busy;
};
struct hotplug_params {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 63628e01dd43..a2b3f0010cec 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -65,6 +65,7 @@ static int get_power_status (struct hotplug_slot *slot, u8 *value);
static int get_attention_status (struct hotplug_slot *slot, u8 *value);
static int get_latch_status (struct hotplug_slot *slot, u8 *value);
static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
+static int get_address (struct hotplug_slot *slot, u32 *value);
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
@@ -77,6 +78,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
.get_attention_status = get_attention_status,
.get_latch_status = get_latch_status,
.get_adapter_status = get_adapter_status,
+ .get_address = get_address,
.get_max_bus_speed = get_max_bus_speed,
.get_cur_bus_speed = get_cur_bus_speed,
};
@@ -314,6 +316,18 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
+static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
+{
+ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
+ struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+ dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+ *value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+ return 0;
+}
+
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
@@ -377,8 +391,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_ctrl;
}
- ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
-
pci_set_drvdata(pdev, ctrl);
ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 58619359ad08..25ccb0e47593 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -248,7 +248,6 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
@@ -330,9 +329,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return -1;
}
-
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
if (rc) {
@@ -352,7 +348,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
@@ -367,7 +362,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
@@ -494,7 +488,6 @@ static int board_added(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
@@ -532,9 +525,6 @@ static int board_added(struct slot *p_slot)
p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -552,8 +542,6 @@ err_exit:
up(&ctrl->crit_sect);
return rc;
}
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
if (rc) {
@@ -603,8 +591,6 @@ static int remove_board(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
rc = p_slot->hpc_ops->check_cmd_status(ctrl);
if (rc) {
@@ -621,8 +607,6 @@ static int remove_board(struct slot *p_slot)
up(&ctrl->crit_sect);
return rc;
}
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -676,9 +660,6 @@ static void shpchp_pushbutton_thread (unsigned long slot)
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (p_slot->ctrl);
-
/* Done with exclusive hardware access */
up(&p_slot->ctrl->crit_sect);
}
@@ -790,14 +771,9 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
break;
@@ -806,12 +782,8 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -845,14 +817,9 @@ static void interrupt_event_handler(struct controller *ctrl)
/* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
-
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
@@ -870,12 +837,8 @@ static void interrupt_event_handler(struct controller *ctrl)
down(&ctrl->crit_sect);
p_slot->hpc_ops->set_attention_status(p_slot, 1);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->green_led_off(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 9987a6fd65b8..b4226ff3a854 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -275,6 +275,25 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
return;
}
+static inline int shpc_wait_cmd(struct controller *ctrl)
+{
+ int retval = 0;
+ unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000;
+ unsigned long timeout = msecs_to_jiffies(timeout_msec);
+ int rc = wait_event_interruptible_timeout(ctrl->queue,
+ !ctrl->cmd_busy, timeout);
+ if (!rc) {
+ retval = -EIO;
+ err("Command not completed in %d msec\n", timeout_msec);
+ } else if (rc < 0) {
+ retval = -EINTR;
+ info("Command was interrupted by a signal\n");
+ }
+ ctrl->cmd_busy = 0;
+
+ return retval;
+}
+
static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
{
struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
@@ -314,8 +333,14 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
/* To make sure the Controller Busy bit is 0 before we send out the
* command.
*/
+ slot->ctrl->cmd_busy = 1;
writew(temp_word, php_ctlr->creg + CMD);
+ /*
+ * Wait for command completion.
+ */
+ retval = shpc_wait_cmd(slot->ctrl);
+
DBG_LEAVE_ROUTINE
return retval;
}
@@ -604,7 +629,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
if (pi == 2) {
- *mode = (sec_bus_status & 0x0100) >> 7;
+ *mode = (sec_bus_status & 0x0100) >> 8;
} else {
retval = -1;
}
@@ -791,7 +816,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
}
if (php_ctlr->pci_dev) {
iounmap(php_ctlr->creg);
- release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
php_ctlr->pci_dev = NULL;
}
@@ -1058,12 +1083,13 @@ static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
if (intr_loc & 0x0001) {
/*
* Command Complete Interrupt Pending
- * RO only - clear by writing 0 to the Command Completion
+ * RO only - clear by writing 1 to the Command Completion
* Detect bit in Controller SERR-INT register
*/
temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
- temp_dword &= 0xfffeffff;
+ temp_dword &= 0xfffdffff;
writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+ ctrl->cmd_busy = 0;
wake_up_interruptible(&ctrl->queue);
}
@@ -1121,7 +1147,6 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
int retval = 0;
u8 pi;
u32 slot_avail1, slot_avail2;
- int slot_num;
DBG_ENTER_ROUTINE
@@ -1140,39 +1165,39 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
if (pi == 2) {
- if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 )
+ if (slot_avail2 & SLOT_133MHZ_PCIX_533)
bus_speed = PCIX_133MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 )
+ else if (slot_avail2 & SLOT_100MHZ_PCIX_533)
bus_speed = PCIX_100MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ_PCIX_533)
bus_speed = PCIX_66MHZ_533;
- else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 )
+ else if (slot_avail2 & SLOT_133MHZ_PCIX_266)
bus_speed = PCIX_133MHZ_266;
- else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 )
+ else if (slot_avail2 & SLOT_100MHZ_PCIX_266)
bus_speed = PCIX_100MHZ_266;
- else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ_PCIX_266)
bus_speed = PCIX_66MHZ_266;
- else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 )
+ else if (slot_avail1 & SLOT_133MHZ_PCIX)
bus_speed = PCIX_133MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 )
+ else if (slot_avail1 & SLOT_100MHZ_PCIX)
bus_speed = PCIX_100MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 )
+ else if (slot_avail1 & SLOT_66MHZ_PCIX)
bus_speed = PCIX_66MHZ;
- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ)
bus_speed = PCI_66MHZ;
- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+ else if (slot_avail1 & SLOT_33MHZ)
bus_speed = PCI_33MHZ;
else bus_speed = PCI_SPEED_UNKNOWN;
} else {
- if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 )
+ if (slot_avail1 & SLOT_133MHZ_PCIX)
bus_speed = PCIX_133MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 )
+ else if (slot_avail1 & SLOT_100MHZ_PCIX)
bus_speed = PCIX_100MHZ;
- else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 )
+ else if (slot_avail1 & SLOT_66MHZ_PCIX)
bus_speed = PCIX_66MHZ;
- else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 )
+ else if (slot_avail2 & SLOT_66MHZ)
bus_speed = PCI_66MHZ;
- else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 )
+ else if (slot_avail1 & SLOT_33MHZ)
bus_speed = PCI_33MHZ;
else bus_speed = PCI_SPEED_UNKNOWN;
}
@@ -1321,19 +1346,34 @@ static struct hpc_ops shpchp_hpc_ops = {
.check_cmd_status = hpc_check_cmd_status,
};
+inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
+ u32 *value)
+{
+ int rc;
+ u32 cap_offset = ctrl->cap_offset;
+ struct pci_dev *pdev = ctrl->pci_dev;
+
+ rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
+ if (rc)
+ return rc;
+ return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
+}
+
int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
- int rc;
+ int rc, num_slots = 0;
u8 hp_slot;
static int first = 1;
- u32 shpc_cap_offset, shpc_base_offset;
+ u32 shpc_base_offset;
u32 tempdword, slot_reg;
u8 i;
DBG_ENTER_ROUTINE
+ ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
+
spin_lock_init(&list_lock);
php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);
@@ -1348,41 +1388,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
- shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */
+ /* amd shpc driver doesn't use Base Offset; assume 0 */
+ ctrl->mmio_base = pci_resource_start(pdev, 0);
+ ctrl->mmio_size = pci_resource_len(pdev, 0);
} else {
- if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
- err("%s : shpc_cap_offset == 0\n", __FUNCTION__);
+ ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
+ if (!ctrl->cap_offset) {
+ err("%s : cap_offset == 0\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset);
-
- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET);
+ dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
+
+ rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
if (rc) {
- err("%s : pci_word_config_byte failed\n", __FUNCTION__);
+ err("%s: cannot read base_offset\n", __FUNCTION__);
goto abort_free_ctlr;
}
-
- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset);
+
+ rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
if (rc) {
- err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+ err("%s: cannot read slot config\n", __FUNCTION__);
goto abort_free_ctlr;
}
+ num_slots = tempdword & SLOT_NUM;
+ dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
- for (i = 0; i <= 14; i++) {
- rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i);
- if (rc) {
- err("%s : pci_word_config_byte failed\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword);
+ for (i = 0; i < 9 + num_slots; i++) {
+ rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
if (rc) {
- err("%s : pci_read_config_dword failed\n", __FUNCTION__);
+ err("%s: cannot read creg (index = %d)\n",
+ __FUNCTION__, i);
goto abort_free_ctlr;
}
dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
tempdword);
}
+
+ ctrl->mmio_base =
+ pci_resource_start(pdev, 0) + shpc_base_offset;
+ ctrl->mmio_size = 0x24 + 0x4 * num_slots;
}
if (first) {
@@ -1396,16 +1440,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if (pci_enable_device(pdev))
goto abort_free_ctlr;
- if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) {
+ if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
err("%s: cannot reserve MMIO region\n", __FUNCTION__);
goto abort_free_ctlr;
}
- php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+ php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
if (!php_ctlr->creg) {
- err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0),
- pci_resource_start(pdev, 0) + shpc_base_offset);
- release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
+ err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
+ ctrl->mmio_size, ctrl->mmio_base);
+ release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
goto abort_free_ctlr;
}
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 38009bc0fd5d..19e1a5e1e30b 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -89,10 +89,11 @@ int shpchp_configure_device(struct slot *p_slot)
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn;
- dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
err("Device %s already exists at %x:%x, cannot hot-add\n",
pci_name(dev), p_slot->bus, p_slot->device);
+ pci_dev_put(dev);
return -EINVAL;
}
@@ -103,12 +104,13 @@ int shpchp_configure_device(struct slot *p_slot)
}
for (fn = 0; fn < 8; fn++) {
- if (!(dev = pci_find_slot(p_slot->bus,
- PCI_DEVFN(p_slot->device, fn))))
+ dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
+ if (!dev)
continue;
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot hot-add display device %s\n",
pci_name(dev));
+ pci_dev_put(dev);
continue;
}
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
@@ -124,18 +126,21 @@ int shpchp_configure_device(struct slot *p_slot)
}
if (busnr >= end) {
err("No free bus for hot-added bridge\n");
+ pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
err("Cannot add new bus for %s\n",
pci_name(dev));
+ pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
program_fw_provided_values(dev);
+ pci_dev_put(dev);
}
pci_bus_assign_resources(parent);
@@ -149,17 +154,19 @@ int shpchp_unconfigure_device(struct slot *p_slot)
int rc = 0;
int j;
u8 bctl = 0;
-
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus, p_slot->device);
for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(p_slot->bus,
+ struct pci_dev* temp = pci_get_slot(parent,
(p_slot->device << 3) | j);
if (!temp)
continue;
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
err("Cannot remove display device %s\n",
pci_name(temp));
+ pci_dev_put(temp);
continue;
}
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
@@ -167,10 +174,12 @@ int shpchp_unconfigure_device(struct slot *p_slot)
if (bctl & PCI_BRIDGE_CTL_VGA) {
err("Cannot remove display device %s\n",
pci_name(temp));
+ pci_dev_put(temp);
continue;
}
}
pci_remove_bus_device(temp);
+ pci_dev_put(temp);
}
return rc;
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a9046d4b8af3..0aa14c92b570 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &pci_bus_type;
- drv->driver.probe = pci_device_probe;
- drv->driver.remove = pci_device_remove;
/* FIXME, once all of the existing PCI drivers have been fixed to set
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
@@ -502,8 +500,8 @@ void pci_dev_put(struct pci_dev *dev)
}
#ifndef CONFIG_HOTPLUG
-int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
return -ENODEV;
}
@@ -512,7 +510,9 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
struct bus_type pci_bus_type = {
.name = "pci",
.match = pci_bus_match,
- .hotplug = pci_hotplug,
+ .uevent = pci_uevent,
+ .probe = pci_device_probe,
+ .remove = pci_device_remove,
.suspend = pci_device_suspend,
.resume = pci_device_resume,
.dev_attrs = pci_dev_attrs,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8e287a828d5d..d2a633efa10a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -19,6 +19,7 @@
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
+#if 0
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
@@ -63,6 +64,8 @@ pci_max_busnr(void)
return max;
}
+#endif /* 0 */
+
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
{
u8 id;
@@ -587,7 +590,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
{
u8 pin;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ pin = dev->pin;
if (!pin)
return -1;
pin--;
@@ -917,8 +920,6 @@ EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_enable_device_bars);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_disable_device);
-EXPORT_SYMBOL(pci_max_busnr);
-EXPORT_SYMBOL(pci_bus_max_busnr);
EXPORT_SYMBOL(pci_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 6527b36c9a61..a6dfee2f6d2b 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -1,7 +1,7 @@
/* Functions internal to the PCI core code */
-extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size);
+extern int pci_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
@@ -26,20 +26,15 @@ extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *dev);
extern int pci_proc_detach_device(struct pci_dev *dev);
-extern int pci_proc_attach_bus(struct pci_bus *bus);
extern int pci_proc_detach_bus(struct pci_bus *bus);
#else
static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; }
static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; }
-static inline int pci_proc_attach_bus(struct pci_bus *bus) { return 0; }
static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif
/* Functions for PCI Hotplug drivers to use */
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);
-extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
extern void pci_remove_legacy_files(struct pci_bus *bus);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 467a4ceccf10..e4e5f1e8d816 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -238,8 +238,8 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
device->driver = NULL;
device->driver_data = NULL;
device->release = release_pcie_device; /* callback to free pcie dev */
- sprintf(&device->bus_id[0], "pcie%02x",
- get_descriptor_id(port_type, service_type));
+ snprintf(device->bus_id, sizeof(device->bus_id), "%s:pcie%02x",
+ pci_name(parent), get_descriptor_id(port_type, service_type));
device->parent = &parent->dev;
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index fce2cb2112d8..adfad4fd6a13 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -264,8 +264,10 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (base <= limit) {
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
- res->start = base;
- res->end = limit + 0xfff;
+ if (!res->start)
+ res->start = base;
+ if (!res->end)
+ res->end = limit + 0xfff;
}
res = child->resource[1];
@@ -431,7 +433,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
{
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
- u32 buses, i;
+ u32 buses, i, j = 0;
u16 bctl;
pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
@@ -541,10 +543,29 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
* as cards with a PCI-to-PCI bridge can be
* inserted later.
*/
- for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)
+ for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) {
+ struct pci_bus *parent = bus;
if (pci_find_bus(pci_domain_nr(bus),
max+i+1))
break;
+ while (parent->parent) {
+ if ((!pcibios_assign_all_busses()) &&
+ (parent->subordinate > max) &&
+ (parent->subordinate <= max+i)) {
+ j = 1;
+ }
+ parent = parent->parent;
+ }
+ if (j) {
+ /*
+ * Often, there are two cardbus bridges
+ * -- try to leave one valid bus number
+ * for each one.
+ */
+ i /= 2;
+ break;
+ }
+ }
max += i;
pci_fixup_parent_subordinate_busnr(child, max);
}
@@ -559,6 +580,22 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
+ while (bus->parent) {
+ if ((child->subordinate > bus->subordinate) ||
+ (child->number > bus->subordinate) ||
+ (child->number < bus->number) ||
+ (child->subordinate < bus->number)) {
+ printk(KERN_WARNING "PCI: Bus #%02x (-#%02x) may be "
+ "hidden behind%s bridge #%02x (-#%02x)%s\n",
+ child->number, child->subordinate,
+ bus->self->transparent ? " transparent" : " ",
+ bus->number, bus->subordinate,
+ pcibios_assign_all_busses() ? " " :
+ " (try 'pci=assign-busses')");
+ }
+ bus = bus->parent;
+ }
+
return max;
}
@@ -571,6 +608,7 @@ static void pci_read_irq(struct pci_dev *dev)
unsigned char irq;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
+ dev->pin = irq;
if (irq)
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
dev->irq = irq;
@@ -624,6 +662,7 @@ static int pci_setup_device(struct pci_dev * dev)
/* The PCI-to-PCI bridge spec requires that subtractive
decoding (i.e. transparent) bridge must have programming
interface code of 0x01. */
+ pci_read_irq(dev);
dev->transparent = ((dev->class & 0xff) == 1);
pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
break;
@@ -678,7 +717,7 @@ static void pci_release_dev(struct device *dev)
* reading the dword at 0x100 which must either be 0 or a valid extended
* capability header.
*/
-static int pci_cfg_space_size(struct pci_dev *dev)
+int pci_cfg_space_size(struct pci_dev *dev)
{
int pos;
u32 status;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9eb465727fce..92a885760832 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -25,7 +25,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
loff_t new = -1;
struct inode *inode = file->f_dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
switch (whence) {
case 0:
new = off;
@@ -41,7 +41,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
new = -EINVAL;
else
file->f_pos = new;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return new;
}
@@ -431,6 +431,7 @@ int pci_proc_detach_device(struct pci_dev *dev)
return 0;
}
+#if 0
int pci_proc_attach_bus(struct pci_bus* bus)
{
struct proc_dir_entry *de = bus->procdir;
@@ -447,6 +448,7 @@ int pci_proc_attach_bus(struct pci_bus* bus)
}
return 0;
}
+#endif /* 0 */
int pci_proc_detach_bus(struct pci_bus* bus)
{
@@ -612,7 +614,6 @@ __initcall(pci_proc_init);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_proc_attach_device);
-EXPORT_SYMBOL(pci_proc_attach_bus);
EXPORT_SYMBOL(pci_proc_detach_bus);
#endif
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 3a4f49f4effb..dda6099903c1 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1098,6 +1098,23 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic );
#endif
+enum ide_combined_type { COMBINED = 0, IDE = 1, LIBATA = 2 };
+/* Defaults to combined */
+static enum ide_combined_type combined_mode;
+
+static int __init combined_setup(char *str)
+{
+ if (!strncmp(str, "ide", 3))
+ combined_mode = IDE;
+ else if (!strncmp(str, "libata", 6))
+ combined_mode = LIBATA;
+ else /* "combined" or anything else defaults to old behavior */
+ combined_mode = COMBINED;
+
+ return 1;
+}
+__setup("combined_mode=", combined_setup);
+
#ifdef CONFIG_SCSI_SATA_INTEL_COMBINED
static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
{
@@ -1125,6 +1142,9 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
case 0x27c4:
ich = 7;
break;
+ case 0x2828: /* ICH8M */
+ ich = 8;
+ break;
default:
/* we do not handle this PCI device */
return;
@@ -1144,7 +1164,7 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
else
return; /* not in combined mode */
} else {
- WARN_ON((ich != 6) && (ich != 7));
+ WARN_ON((ich != 6) && (ich != 7) && (ich != 8));
tmp &= 0x3; /* interesting bits 1:0 */
if (tmp & (1 << 0))
comb = (1 << 2); /* PATA port 0, SATA port 1 */
@@ -1164,6 +1184,19 @@ static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
if (prog & comb)
return;
+ /* Don't reserve any so the IDE driver can get them (but only if
+ * combined_mode=ide).
+ */
+ if (combined_mode == IDE)
+ return;
+
+ /* Grab them both for libata if combined_mode=libata. */
+ if (combined_mode == LIBATA) {
+ request_region(0x1f0, 8, "libata"); /* port 0 */
+ request_region(0x170, 8, "libata"); /* port 1 */
+ return;
+ }
+
/* SATA port is in legacy mode. Reserve port so that
* IDE driver does not attempt to use it. If request_region
* fails, it will be obvious at boot time, so we don't bother
@@ -1312,6 +1345,32 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
pci_do_fixups(dev, start, end);
}
+/* Enable 1k I/O space granularity on the Intel P64H2 */
+static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
+{
+ u16 en1k;
+ u8 io_base_lo, io_limit_lo;
+ unsigned long base, limit;
+ struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
+
+ pci_read_config_word(dev, 0x40, &en1k);
+
+ if (en1k & 0x200) {
+ printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n");
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+ pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+ base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
+ limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
+
+ if (base <= limit) {
+ res->start = base;
+ res->end = limit + 0x3ff;
+ }
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
+
EXPORT_SYMBOL(pcie_mch_quirk);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_fixup_device);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 27a294b6965d..1a6bf9de166f 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -48,6 +48,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
* in question is not being used by a driver.
* Returns 0 on success.
*/
+#if 0
int pci_remove_device_safe(struct pci_dev *dev)
{
if (pci_dev_driver(dev))
@@ -55,7 +56,7 @@ int pci_remove_device_safe(struct pci_dev *dev)
pci_destroy_dev(dev);
return 0;
}
-EXPORT_SYMBOL(pci_remove_device_safe);
+#endif /* 0 */
void pci_remove_bus(struct pci_bus *pci_bus)
{
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 309eb557f9a3..1f4ad0e7836e 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -116,6 +116,31 @@ config YENTA
If unsure, say Y.
+config YENTA_O2
+ default y
+ bool "Special initialization for O2Micro bridges" if EMBEDDED
+ depends on YENTA
+
+config YENTA_RICOH
+ default y
+ bool "Special initialization for Ricoh bridges" if EMBEDDED
+ depends on YENTA
+
+config YENTA_TI
+ default y
+ bool "Special initialization for TI and EnE bridges" if EMBEDDED
+ depends on YENTA
+
+config YENTA_ENE_TUNE
+ default y
+ bool "Auto-tune EnE bridges for CB cards" if EMBEDDED
+ depends on YENTA_TI && CARDBUS
+
+config YENTA_TOSHIBA
+ default y
+ bool "Special initialization for Toshiba ToPIC bridges" if EMBEDDED
+ depends on YENTA
+
config PD6729
tristate "Cirrus PD6729 compatible bridge support"
depends on PCMCIA && PCI
@@ -157,7 +182,7 @@ config TCIC
config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support"
depends on PCMCIA && PPC && 8xx
- select PCCARD_NONSTATIC
+ select PCCARD_IODYN
help
Say Y here to include support for PowerPC 8xx series PCMCIA
controller.
@@ -200,7 +225,7 @@ config PCMCIA_PXA2XX
config PCMCIA_PROBE
bool
- default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
+ default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
config M32R_PCC
bool "M32R PCMCIA I/F"
@@ -241,6 +266,9 @@ config OMAP_CF
config PCCARD_NONSTATIC
tristate
+config PCCARD_IODYN
+ bool
+
endif # PCCARD
endmenu
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index 87302c548c24..971a35281649 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -241,23 +241,6 @@ au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
return 0;
}
-/* au1x00_pcmcia_get_socket()
- * Implements the get_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_GetSocket in Card Services). Not a very
- * exciting routine.
- *
- * Returns: 0
- */
-static int
-au1x00_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
-
- debug("for sock %u\n", skt->nr);
- *state = skt->cs_state;
- return 0;
-}
-
/* au1x00_pcmcia_set_socket()
* Implements the set_socket() operation for the in-kernel PCMCIA
* service (formerly SS_SetSocket in Card Services). We more or
@@ -352,7 +335,6 @@ static struct pccard_operations au1x00_pcmcia_operations = {
.init = au1x00_pcmcia_sock_init,
.suspend = au1x00_pcmcia_suspend,
.get_status = au1x00_pcmcia_get_status,
- .get_socket = au1x00_pcmcia_get_socket,
.set_socket = au1x00_pcmcia_set_socket,
.set_io_map = au1x00_pcmcia_set_io_map,
.set_mem_map = au1x00_pcmcia_set_mem_map,
@@ -372,13 +354,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
struct skt_dev_info *sinfo;
int ret, i;
- sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
+ sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
if (!sinfo) {
ret = -ENOMEM;
goto out;
}
- memset(sinfo, 0, sizeof(struct skt_dev_info));
sinfo->nskt = nr;
/*
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 2dc3e611a9a3..120fa8da6392 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -60,9 +60,9 @@ static const u_int exponent[] = {
/* Parameters that can be set with 'insmod' */
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
-
-INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
+/* 16-bit CIS? */
+static int cis_width;
+module_param(cis_width, int, 0444);
void release_cis_mem(struct pcmcia_socket *s)
{
@@ -463,7 +463,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
/* Get indirect link from the MFC tuple */
read_cis_cache(s, LINK_SPACE(tuple->Flags),
tuple->LinkOffset, 5, link);
- ofs = le32_to_cpu(*(u_int *)(link+1));
+ ofs = le32_to_cpu(*(__le32 *)(link+1));
SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
/* Move to the next indirect link */
tuple->LinkOffset += 5;
@@ -671,8 +671,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
if (tuple->TupleDataLen < 5)
return CS_BAD_TUPLE;
p = (u_char *)tuple->TupleData;
- csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
- csum->len = le16_to_cpu(*(u_short *)(p + 2));
+ csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2;
+ csum->len = le16_to_cpu(*(__le16 *)(p + 2));
csum->sum = *(p+4);
return CS_SUCCESS;
}
@@ -683,7 +683,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
{
if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE;
- link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
+ link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData);
return CS_SUCCESS;
}
@@ -702,7 +702,7 @@ static int parse_longlink_mfc(tuple_t *tuple,
return CS_BAD_TUPLE;
for (i = 0; i < link->nfn; i++) {
link->fn[i].space = *p; p++;
- link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
+ link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4;
}
return CS_SUCCESS;
}
@@ -789,10 +789,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
{
- u_short *p;
+ __le16 *p;
if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE;
- p = (u_short *)tuple->TupleData;
+ p = (__le16 *)tuple->TupleData;
m->manf = le16_to_cpu(p[0]);
m->card = le16_to_cpu(p[1]);
return CS_SUCCESS;
@@ -1093,7 +1093,7 @@ static int parse_cftable_entry(tuple_t *tuple,
break;
case 0x20:
entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+ entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
entry->mem.win[0].card_addr = 0;
entry->mem.win[0].host_addr = 0;
p += 2;
@@ -1101,9 +1101,9 @@ static int parse_cftable_entry(tuple_t *tuple,
break;
case 0x40:
entry->mem.nwin = 1;
- entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
+ entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
entry->mem.win[0].card_addr =
- le16_to_cpu(*(u_short *)(p+2)) << 8;
+ le16_to_cpu(*(__le16 *)(p+2)) << 8;
entry->mem.win[0].host_addr = 0;
p += 4;
if (p > q) return CS_BAD_TUPLE;
@@ -1140,7 +1140,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
p = (u_char *)tuple->TupleData;
bar->attr = *p;
p += 2;
- bar->size = le32_to_cpu(*(u_int *)p);
+ bar->size = le32_to_cpu(*(__le32 *)p);
return CS_SUCCESS;
}
@@ -1153,7 +1153,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
return CS_BAD_TUPLE;
config->last_idx = *(++p);
p++;
- config->base = le32_to_cpu(*(u_int *)p);
+ config->base = le32_to_cpu(*(__le32 *)p);
config->subtuples = tuple->TupleDataLen - 6;
return CS_SUCCESS;
}
@@ -1269,7 +1269,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
v2->vers = p[0];
v2->comply = p[1];
- v2->dindex = le16_to_cpu(*(u_short *)(p+2));
+ v2->dindex = le16_to_cpu(*(__le16 *)(p+2));
v2->vspec8 = p[6];
v2->vspec9 = p[7];
v2->nhdr = p[8];
@@ -1310,8 +1310,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
fmt->type = p[0];
fmt->edc = p[1];
- fmt->offset = le32_to_cpu(*(u_int *)(p+2));
- fmt->length = le32_to_cpu(*(u_int *)(p+6));
+ fmt->offset = le32_to_cpu(*(__le32 *)(p+2));
+ fmt->length = le32_to_cpu(*(__le32 *)(p+6));
return CS_SUCCESS;
}
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index a30aa74304a2..613f2f1fbfdd 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -309,41 +309,6 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
}
EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
-
-/**
- * socket_setup() and shutdown_socket() are called by the main event
- * handler when card insertion and removal events are received.
- * socket_setup() turns on socket power and resets the socket, in two stages.
- * shutdown_socket() unconfigures a socket and turns off socket power.
- */
-static void shutdown_socket(struct pcmcia_socket *s)
-{
- cs_dbg(s, 1, "shutdown_socket\n");
-
- /* Blank out the socket state */
- s->socket = dead_socket;
- s->ops->init(s);
- s->ops->set_socket(s, &s->socket);
- s->irq.AssignedIRQ = s->irq.Config = 0;
- s->lock_count = 0;
- destroy_cis_cache(s);
-#ifdef CONFIG_CARDBUS
- cb_free(s);
-#endif
- s->functions = 0;
- kfree(s->config);
- s->config = NULL;
-
- {
- int status;
- s->ops->get_status(s, &status);
- if (status & SS_POWERON) {
- printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
- }
- }
-} /* shutdown_socket */
-
-
/**
* The central event handler. Send_event() sends an event to the
* 16-bit subsystem, which then calls the relevant device drivers.
@@ -383,17 +348,6 @@ static void socket_remove_drivers(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
}
-static void socket_shutdown(struct pcmcia_socket *skt)
-{
- cs_dbg(skt, 4, "shutdown\n");
-
- socket_remove_drivers(skt);
- skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
- msleep(shutdown_delay * 10);
- skt->state &= SOCKET_INUSE;
- shutdown_socket(skt);
-}
-
static int socket_reset(struct pcmcia_socket *skt)
{
int status, i;
@@ -424,6 +378,45 @@ static int socket_reset(struct pcmcia_socket *skt)
return CS_GENERAL_FAILURE;
}
+/**
+ * socket_setup() and socket_shutdown() are called by the main event handler
+ * when card insertion and removal events are received.
+ * socket_setup() turns on socket power and resets the socket, in two stages.
+ * socket_shutdown() unconfigures a socket and turns off socket power.
+ */
+static void socket_shutdown(struct pcmcia_socket *s)
+{
+ int status;
+
+ cs_dbg(s, 4, "shutdown\n");
+
+ socket_remove_drivers(s);
+ s->state &= SOCKET_INUSE | SOCKET_PRESENT;
+ msleep(shutdown_delay * 10);
+ s->state &= SOCKET_INUSE;
+
+ /* Blank out the socket state */
+ s->socket = dead_socket;
+ s->ops->init(s);
+ s->ops->set_socket(s, &s->socket);
+ s->irq.AssignedIRQ = s->irq.Config = 0;
+ s->lock_count = 0;
+ destroy_cis_cache(s);
+#ifdef CONFIG_CARDBUS
+ cb_free(s);
+#endif
+ s->functions = 0;
+ kfree(s->config);
+ s->config = NULL;
+
+ s->ops->get_status(s, &status);
+ if (status & SS_POWERON) {
+ printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
+ }
+
+ cs_socket_put(s);
+}
+
static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
{
int status, i;
@@ -529,7 +522,6 @@ static int socket_insert(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else {
socket_shutdown(skt);
- cs_socket_put(skt);
}
return ret;
@@ -593,7 +585,6 @@ static int socket_resume(struct pcmcia_socket *skt)
}
} else {
socket_shutdown(skt);
- cs_socket_put(skt);
}
skt->state &= ~SOCKET_SUSPEND;
@@ -605,7 +596,6 @@ static void socket_remove(struct pcmcia_socket *skt)
{
printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
socket_shutdown(skt);
- cs_socket_put(skt);
}
/*
@@ -780,8 +770,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
if (ret == 0) {
send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
- if (socket_reset(skt) == CS_SUCCESS)
+ if (skt->callback)
+ skt->callback->suspend(skt);
+ if (socket_reset(skt) == CS_SUCCESS) {
send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
+ if (skt->callback)
+ skt->callback->resume(skt);
+ }
}
ret = CS_SUCCESS;
@@ -812,6 +807,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
ret = CS_UNSUPPORTED_FUNCTION;
break;
}
+ if (skt->callback) {
+ ret = skt->callback->suspend(skt);
+ if (ret)
+ break;
+ }
ret = socket_suspend(skt);
} while (0);
up(&skt->skt_sem);
@@ -838,6 +838,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
break;
}
ret = socket_resume(skt);
+ if (!ret && skt->callback)
+ skt->callback->resume(skt);
} while (0);
up(&skt->skt_sem);
@@ -901,14 +903,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
EXPORT_SYMBOL(pcmcia_insert_card);
-static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
{
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
int i = 0, length = 0;
- if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
- &length, "SOCKET_NO=%u", s->sock))
+ if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "SOCKET_NO=%u", s->sock))
return -ENOMEM;
envp[i] = NULL;
@@ -927,7 +929,7 @@ static void pcmcia_release_socket_class(struct class *data)
struct class pcmcia_socket_class = {
.name = "pcmcia_socket",
- .hotplug = pcmcia_socket_hotplug,
+ .uevent = pcmcia_socket_uevent,
.release = pcmcia_release_socket,
.class_release = pcmcia_release_socket_class,
};
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 55867bc7f199..7b37eba35bf1 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socket *s);
int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
/* In rsrc_mgr */
-void pcmcia_validate_mem(struct pcmcia_socket *s);
+int pcmcia_validate_mem(struct pcmcia_socket *s);
struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
struct pcmcia_socket *s);
int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
@@ -143,6 +143,8 @@ struct pcmcia_callback{
struct module *owner;
int (*event) (struct pcmcia_socket *s, event_t event, int priority);
void (*requery) (struct pcmcia_socket *s);
+ int (*suspend) (struct pcmcia_socket *s);
+ int (*resume) (struct pcmcia_socket *s);
};
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 7f8219f3fd9e..0a424a4e8187 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -57,8 +57,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
spinlock_t pcmcia_dev_list_lock;
-static int unbind_request(struct pcmcia_socket *s);
-
/*====================================================================*/
/* code which was in cs.c before */
@@ -205,7 +203,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
unsigned int i;
u32 hash;
- if (!p_drv->attach || !p_drv->event || !p_drv->detach)
+ if (!p_drv->probe || !p_drv->remove)
printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
"function\n", p_drv->drv.name);
@@ -266,12 +264,10 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
if (fw->size >= CISTPL_MAX_CIS_SIZE)
goto release;
- cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
+ cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis)
goto release;
- memset(cis, 0, sizeof(cisdump_t));
-
cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size);
@@ -315,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
/* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
- driver->drv.probe = pcmcia_device_probe;
- driver->drv.remove = pcmcia_device_remove;
return driver_register(&driver->drv);
}
@@ -363,6 +357,7 @@ static int pcmcia_device_probe(struct device * dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
+ struct pcmcia_socket *s;
int ret = 0;
dev = get_device(dev);
@@ -371,25 +366,38 @@ static int pcmcia_device_probe(struct device * dev)
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
+ s = p_dev->socket;
- if (!try_module_get(p_drv->owner)) {
+ if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
ret = -EINVAL;
goto put_dev;
}
- if (p_drv->attach) {
- p_dev->instance = p_drv->attach();
- if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) {
- printk(KERN_NOTICE "ds: unable to create instance "
- "of '%s'!\n", p_drv->drv.name);
- ret = -EINVAL;
+ p_dev->state &= ~CLIENT_UNBOUND;
+
+ /* set up the device configuration, if it hasn't been done before */
+ if (!s->functions) {
+ cistpl_longlink_mfc_t mfc;
+ if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
+ &mfc) == CS_SUCCESS)
+ s->functions = mfc.nfn;
+ else
+ s->functions = 1;
+ s->config = kzalloc(sizeof(config_t) * s->functions,
+ GFP_KERNEL);
+ if (!s->config) {
+ ret = -ENOMEM;
+ goto put_module;
}
}
+ ret = p_drv->probe(p_dev);
+
+ put_module:
if (ret)
module_put(p_drv->owner);
put_dev:
- if ((ret) || !(p_drv->attach))
+ if (ret)
put_device(dev);
return (ret);
}
@@ -399,24 +407,66 @@ static int pcmcia_device_remove(struct device * dev)
{
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
+ int i;
/* detach the "instance" */
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
+ if (!p_drv)
+ return 0;
- if (p_drv) {
- if ((p_drv->detach) && (p_dev->instance)) {
- p_drv->detach(p_dev->instance);
- /* from pcmcia_probe_device */
- put_device(&p_dev->dev);
- }
- module_put(p_drv->owner);
- }
+ if (p_drv->remove)
+ p_drv->remove(p_dev);
+
+ /* check for proper unloading */
+ if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+ printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
+ p_drv->drv.name);
+
+ for (i = 0; i < MAX_WIN; i++)
+ if (p_dev->state & CLIENT_WIN_REQ(i))
+ printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
+ p_drv->drv.name);
+
+ /* references from pcmcia_probe_device */
+ p_dev->state = CLIENT_UNBOUND;
+ pcmcia_put_dev(p_dev);
+ module_put(p_drv->owner);
return 0;
}
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s)
+{
+ struct pcmcia_device *p_dev;
+ unsigned long flags;
+
+ ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+ s->device_count = 0;
+
+ for (;;) {
+ /* unregister all pcmcia_devices registered with this socket*/
+ spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+ if (list_empty(&s->devices_list)) {
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+ return;
+ }
+ p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+ list_del(&p_dev->socket_device_list);
+ p_dev->state |= CLIENT_STALE;
+ spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+ device_unregister(&p_dev->dev);
+ }
+
+ return;
+} /* unbind_request */
+
/*
* pcmcia_device_query -- determine information about a pcmcia device
@@ -517,10 +567,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (s->device_count == 2)
goto err_put;
- p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
+ p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
if (!p_dev)
goto err_put;
- memset(p_dev, 0, sizeof(struct pcmcia_device));
p_dev->socket = s;
p_dev->device_no = (s->device_count++);
@@ -583,7 +632,9 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
if (!(s->resource_setup_done))
return -EAGAIN; /* try again, but later... */
- pcmcia_validate_mem(s);
+ if (pcmcia_validate_mem(s))
+ return -EAGAIN; /* try again, but later... */
+
ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
if (ret || !cisinfo.Chains) {
ds_dbg(0, "invalid CIS or invalid resources\n");
@@ -779,8 +830,8 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
#ifdef CONFIG_HOTPLUG
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct pcmcia_device *p_dev;
int i, length = 0;
@@ -800,31 +851,31 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
i = 0;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "SOCKET_NO=%u",
- p_dev->socket->sock))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "SOCKET_NO=%u",
+ p_dev->socket->sock))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "DEVICE_NO=%02X",
- p_dev->device_no))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEVICE_NO=%02X",
+ p_dev->device_no))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
- "pa%08Xpb%08Xpc%08Xpd%08X",
- p_dev->has_manf_id ? p_dev->manf_id : 0,
- p_dev->has_card_id ? p_dev->card_id : 0,
- p_dev->has_func_id ? p_dev->func_id : 0,
- p_dev->func,
- p_dev->device_no,
- hash[0],
- hash[1],
- hash[2],
- hash[3]))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
+ "pa%08Xpb%08Xpc%08Xpd%08X",
+ p_dev->has_manf_id ? p_dev->manf_id : 0,
+ p_dev->has_card_id ? p_dev->card_id : 0,
+ p_dev->has_func_id ? p_dev->func_id : 0,
+ p_dev->func,
+ p_dev->device_no,
+ hash[0],
+ hash[1],
+ hash[2],
+ hash[3]))
return -ENOMEM;
envp[i] = NULL;
@@ -834,7 +885,7 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
#else
-static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
+static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -867,6 +918,37 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);
+
+static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+ if (p_dev->dev.power.power_state.event != PM_EVENT_ON)
+ return sprintf(buf, "off\n");
+ else
+ return sprintf(buf, "on\n");
+}
+
+static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ int ret = 0;
+
+ if (!count)
+ return -EINVAL;
+
+ if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) &&
+ (!strncmp(buf, "off", 3)))
+ ret = dpm_runtime_suspend(dev, PMSG_SUSPEND);
+ else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) &&
+ (!strncmp(buf, "on", 2)))
+ dpm_runtime_resume(dev);
+
+ return ret ? ret : count;
+}
+
+
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -892,8 +974,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- if (!count)
- return -EINVAL;
+
+ if (!count)
+ return -EINVAL;
down(&p_dev->socket->skt_sem);
p_dev->allow_func_id_match = 1;
@@ -906,6 +989,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev,
static struct device_attribute pcmcia_dev_attrs[] = {
__ATTR(function, 0444, func_show, NULL),
+ __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state),
__ATTR_RO(func_id),
__ATTR_RO(manf_id),
__ATTR_RO(card_id),
@@ -918,55 +1002,84 @@ static struct device_attribute pcmcia_dev_attrs[] = {
__ATTR_NULL,
};
+/* PM support, also needed for reset */
-/*======================================================================
+static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
+{
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+ struct pcmcia_driver *p_drv = NULL;
- The card status event handler.
-
-======================================================================*/
+ if (dev->driver)
+ p_drv = to_pcmcia_drv(dev->driver);
-struct send_event_data {
- struct pcmcia_socket *skt;
- event_t event;
- int priority;
-};
+ if (p_drv && p_drv->suspend)
+ return p_drv->suspend(p_dev);
-static int send_event_callback(struct device *dev, void * _data)
+ return 0;
+}
+
+
+static int pcmcia_dev_resume(struct device * dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- struct pcmcia_driver *p_drv;
- struct send_event_data *data = _data;
+ struct pcmcia_driver *p_drv = NULL;
- /* we get called for all sockets, but may only pass the event
- * for drivers _on the affected socket_ */
- if (p_dev->socket != data->skt)
- return 0;
+ if (dev->driver)
+ p_drv = to_pcmcia_drv(dev->driver);
- p_drv = to_pcmcia_drv(p_dev->dev.driver);
- if (!p_drv)
+ if (p_drv && p_drv->resume)
+ return p_drv->resume(p_dev);
+
+ return 0;
+}
+
+
+static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
+{
+ struct pcmcia_socket *skt = _data;
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+ if (p_dev->socket != skt)
return 0;
- if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
+ return dpm_runtime_suspend(dev, PMSG_SUSPEND);
+}
+
+static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
+{
+ struct pcmcia_socket *skt = _data;
+ struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+
+ if (p_dev->socket != skt)
return 0;
- if (p_drv->event)
- return p_drv->event(data->event, data->priority,
- &p_dev->event_callback_args);
+ dpm_runtime_resume(dev);
+
+ return 0;
+}
+static int pcmcia_bus_resume(struct pcmcia_socket *skt)
+{
+ bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
return 0;
}
-static int send_event(struct pcmcia_socket *s, event_t event, int priority)
+static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
- struct send_event_data private;
+ if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
+ pcmcia_bus_suspend_callback)) {
+ pcmcia_bus_resume(skt);
+ return -EIO;
+ }
+ return 0;
+}
- private.skt = s;
- private.event = event;
- private.priority = priority;
- return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
-} /* send_event */
+/*======================================================================
+ The card status event handler.
+
+======================================================================*/
/* Normally, the event is passed to individual drivers after
* informing userspace. Only for CS_EVENT_CARD_REMOVAL this
@@ -976,20 +1089,17 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{
struct pcmcia_socket *s = pcmcia_get_socket(skt);
- int ret = 0;
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
event, priority, skt);
-
- switch (event) {
+ switch (event) {
case CS_EVENT_CARD_REMOVAL:
s->pcmcia_state.present = 0;
- send_event(skt, event, priority);
- unbind_request(skt);
+ pcmcia_card_remove(skt);
handle_event(skt, event);
break;
-
+
case CS_EVENT_CARD_INSERTION:
s->pcmcia_state.present = 1;
pcmcia_card_add(skt);
@@ -997,12 +1107,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
break;
case CS_EVENT_EJECTION_REQUEST:
- ret = send_event(skt, event, priority);
break;
+ case CS_EVENT_PM_SUSPEND:
+ case CS_EVENT_PM_RESUME:
+ case CS_EVENT_RESET_PHYSICAL:
+ case CS_EVENT_CARD_RESET:
default:
handle_event(skt, event);
- send_event(skt, event, priority);
break;
}
@@ -1012,152 +1124,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
} /* ds_event */
-
-int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req)
-{
- struct pcmcia_socket *s = NULL;
- struct pcmcia_device *p_dev = NULL;
- struct pcmcia_driver *p_drv = NULL;
-
- /* Look for unbound client with matching dev_info */
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
- unsigned long flags;
-
- if (s->state & SOCKET_CARDBUS)
- continue;
-
- s = pcmcia_get_socket(s);
- if (!s)
- continue;
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
- p_dev = pcmcia_get_dev(p_dev);
- if (!p_dev)
- continue;
- if (!(p_dev->state & CLIENT_UNBOUND) ||
- (!p_dev->dev.driver)) {
- pcmcia_put_dev(p_dev);
- continue;
- }
- p_drv = to_pcmcia_drv(p_dev->dev.driver);
- if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- goto found;
- }
- pcmcia_put_dev(p_dev);
- }
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- pcmcia_put_socket(s);
- }
- found:
- up_read(&pcmcia_socket_list_rwsem);
- if (!p_dev)
- return -ENODEV;
-
- pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */
-
- *handle = p_dev;
- p_dev->state &= ~CLIENT_UNBOUND;
- p_dev->event_callback_args = req->event_callback_args;
- p_dev->event_callback_args.client_handle = p_dev;
-
-
- if (!s->functions) {
- cistpl_longlink_mfc_t mfc;
- if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc)
- == CS_SUCCESS)
- s->functions = mfc.nfn;
- else
- s->functions = 1;
- s->config = kmalloc(sizeof(config_t) * s->functions,
- GFP_KERNEL);
- if (!s->config)
- goto out_no_resource;
- memset(s->config, 0, sizeof(config_t) * s->functions);
- }
-
- ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
- p_dev, p_dev->dev.bus_id);
-
- if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
- if (p_drv->event)
- p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW,
- &p_dev->event_callback_args);
-
- }
-
- return CS_SUCCESS;
-
- out_no_resource:
- pcmcia_put_dev(p_dev);
- return CS_OUT_OF_RESOURCE;
-} /* register_client */
-EXPORT_SYMBOL(pcmcia_register_client);
-
-
-/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
- * drivers have been called with EVENT_CARD_REMOVAL before.
- */
-static int unbind_request(struct pcmcia_socket *s)
-{
- struct pcmcia_device *p_dev;
- unsigned long flags;
-
- ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
- s->device_count = 0;
-
- for (;;) {
- /* unregister all pcmcia_devices registered with this socket*/
- spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
- if (list_empty(&s->devices_list)) {
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- return 0;
- }
- p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
- list_del(&p_dev->socket_device_list);
- p_dev->state |= CLIENT_STALE;
- spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
- device_unregister(&p_dev->dev);
- }
-
- return 0;
-} /* unbind_request */
-
-int pcmcia_deregister_client(struct pcmcia_device *p_dev)
-{
- struct pcmcia_socket *s;
- int i;
-
- s = p_dev->socket;
- ds_dbg(1, "deregister_client(%p)\n", p_dev);
-
- if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
- goto warn_out;
- for (i = 0; i < MAX_WIN; i++)
- if (p_dev->state & CLIENT_WIN_REQ(i))
- goto warn_out;
-
- if (p_dev->state & CLIENT_STALE) {
- p_dev->state &= ~CLIENT_STALE;
- pcmcia_put_dev(p_dev);
- } else {
- p_dev->state = CLIENT_UNBOUND;
- }
-
- return CS_SUCCESS;
- warn_out:
- printk(KERN_WARNING "ds: deregister_client was called too early.\n");
- return CS_IN_USE;
-} /* deregister_client */
-EXPORT_SYMBOL(pcmcia_deregister_client);
-
static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE,
.event = ds_event,
.requery = pcmcia_bus_rescan,
+ .suspend = pcmcia_bus_suspend,
+ .resume = pcmcia_bus_resume,
};
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
@@ -1223,9 +1195,13 @@ static struct class_interface pcmcia_bus_interface = {
struct bus_type pcmcia_bus_type = {
.name = "pcmcia",
- .hotplug = pcmcia_bus_hotplug,
+ .uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match,
.dev_attrs = pcmcia_dev_attrs,
+ .probe = pcmcia_device_probe,
+ .remove = pcmcia_device_remove,
+ .suspend = pcmcia_dev_suspend,
+ .resume = pcmcia_dev_resume,
};
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index 561706ba4499..b39435bbfaeb 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -417,18 +417,6 @@ static int hs_get_status(struct pcmcia_socket *s, u_int *value)
/*============================================================*/
-static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
-
- DPRINTK("hs_get_socket(%d)\n", sock);
-
- *state = sp->state;
- return 0;
-}
-
-/*============================================================*/
-
static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
@@ -749,7 +737,6 @@ static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
static struct pccard_operations hs_operations = {
.init = hs_init,
.get_status = hs_get_status,
- .get_socket = hs_get_socket,
.set_socket = hs_set_socket,
.set_io_map = hs_set_io_map,
.set_mem_map = hs_set_mem_map,
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index f3fdc748659d..7979c85df3dc 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -66,7 +66,6 @@ static struct pci_driver i82092aa_pci_drv = {
static struct pccard_operations i82092aa_operations = {
.init = i82092aa_init,
.get_status = i82092aa_get_status,
- .get_socket = i82092aa_get_socket,
.set_socket = i82092aa_set_socket,
.set_io_map = i82092aa_set_io_map,
.set_mem_map = i82092aa_set_mem_map,
@@ -482,78 +481,6 @@ static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
}
-static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state)
-{
- unsigned int sock = container_of(socket, struct socket_info, socket)->number;
- unsigned char reg,vcc,vpp;
-
- enter("i82092aa_get_socket");
- state->flags = 0;
- state->Vcc = 0;
- state->Vpp = 0;
- state->io_irq = 0;
- state->csc_mask = 0;
-
- /* First the power status of the socket */
- reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
-
- if (reg & I365_PWR_AUTO)
- state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */
-
- if (reg & I365_PWR_OUT)
- state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
-
- vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
-
- if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
- state->Vcc = 50;
-
- if (vpp == I365_VPP1_5V)
- state->Vpp = 50;
- if (vpp == I365_VPP1_12V)
- state->Vpp = 120;
-
- }
-
- if ((reg & I365_VCC_3V)==I365_VCC_3V)
- state->Vcc = 33;
-
-
- /* Now the IO card, RESET flags and IO interrupt */
-
- reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
-
- if ((reg & I365_PC_RESET)==0)
- state->flags |= SS_RESET;
- if (reg & I365_PC_IOCARD)
- state->flags |= SS_IOCARD; /* This is an IO card */
-
- /* Set the IRQ number */
- if (sockets[sock].dev!=NULL)
- state->io_irq = sockets[sock].dev->irq;
-
- /* Card status change */
- reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
-
- if (reg & I365_CSC_DETECT)
- state->csc_mask |= SS_DETECT; /* Card detect is enabled */
-
- if (state->flags & SS_IOCARD) {/* IO Cards behave different */
- if (reg & I365_CSC_STSCHG)
- state->csc_mask |= SS_STSCHG;
- } else {
- if (reg & I365_CSC_BVD1)
- state->csc_mask |= SS_BATDEAD;
- if (reg & I365_CSC_BVD2)
- state->csc_mask |= SS_BATWARN;
- if (reg & I365_CSC_READY)
- state->csc_mask |= SS_READY;
- }
-
- leave("i82092aa_get_socket");
- return 0;
-}
-
static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state)
{
unsigned int sock = container_of(socket, struct socket_info, socket)->number;
diff --git a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h
index b98cac7bda9f..9c14599d0673 100644
--- a/drivers/pcmcia/i82092aa.h
+++ b/drivers/pcmcia/i82092aa.h
@@ -29,7 +29,6 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
-static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 4d56bc9926d6..35a92d1e4945 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -940,78 +940,6 @@ static int i365_get_status(u_short sock, u_int *value)
/*====================================================================*/
-static int i365_get_socket(u_short sock, socket_state_t *state)
-{
- struct i82365_socket *t = &socket[sock];
- u_char reg, vcc, vpp;
-
- reg = i365_get(sock, I365_POWER);
- state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
- state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
- vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
- state->Vcc = state->Vpp = 0;
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
- if (reg & I365_VCC_5V) state->Vcc = 33;
- if (vpp == I365_VPP1_5V) state->Vpp = 33;
- } 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 if (t->flags & IS_VG_PWR) {
- if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
- if (reg & I365_VCC_5V) state->Vcc = 33;
- if (vpp == I365_VPP1_5V) state->Vpp = 33;
- } 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 if (t->flags & IS_DF_PWR) {
- if (vcc == I365_VCC_3V) state->Vcc = 33;
- if (vcc == I365_VCC_5V) state->Vcc = 50;
- if (vpp == I365_VPP1_5V) state->Vpp = 50;
- 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;
- }
- }
-
- /* IO card, RESET flags, IO interrupt */
- reg = i365_get(sock, I365_INTCTL);
- state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
- if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
- state->io_irq = reg & I365_IRQ_MASK;
-
- /* speaker control */
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
- state->flags |= SS_SPKR_ENA;
- }
-
- /* Card status change mask */
- reg = i365_get(sock, I365_CSCINT);
- state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
- if (state->flags & SS_IOCARD)
- state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
- else {
- state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
- state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
- state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
- }
-
- debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-} /* i365_get_socket */
-
-/*====================================================================*/
-
static int i365_set_socket(u_short sock, socket_state_t *state)
{
struct i82365_socket *t = &socket[sock];
@@ -1265,16 +1193,6 @@ static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(i365_get_status(sock, value));
}
-static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
-
- if (socket[sock].flags & IS_ALIVE)
- return -EINVAL;
-
- LOCKED(i365_get_socket(sock, state));
-}
-
static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
@@ -1324,7 +1242,6 @@ static int pcic_init(struct pcmcia_socket *s)
static struct pccard_operations pcic_operations = {
.init = pcic_init,
.get_status = pcic_get_status,
- .get_socket = pcic_get_socket,
.set_socket = pcic_set_socket,
.set_io_map = pcic_set_io_map,
.set_mem_map = pcic_set_mem_map,
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 078579ae6359..071cf485e1a3 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -480,25 +480,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
/*====================================================================*/
-static int _pcc_get_socket(u_short sock, socket_state_t *state)
-{
-// pcc_socket_t *t = &socket[sock];
-
- state->flags = 0;
- state->csc_mask = SS_DETECT;
- state->csc_mask |= SS_READY;
- state->io_irq = 0;
- state->Vcc = 33; /* 3.3V fixed */
- state->Vpp = 33;
-
- debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-} /* _get_socket */
-
-/*====================================================================*/
-
static int _pcc_set_socket(u_short sock, socket_state_t *state)
{
debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
@@ -667,18 +648,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(_pcc_get_status(sock, value));
}
-static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
-
- if (socket[sock].flags & IS_ALIVE) {
- debug(3, "m32r_cfc: pcc_get_socket: sock(%d) -EINVAL\n", sock);
- return -EINVAL;
- }
- debug(3, "m32r_cfc: pcc_get_socket: sock(%d)\n", sock);
- LOCKED(_pcc_get_socket(sock, state));
-}
-
static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@@ -724,7 +693,6 @@ static int pcc_init(struct pcmcia_socket *s)
static struct pccard_operations pcc_operations = {
.init = pcc_init,
.get_status = pcc_get_status,
- .get_socket = pcc_get_socket,
.set_socket = pcc_set_socket,
.set_io_map = pcc_set_io_map,
.set_mem_map = pcc_set_mem_map,
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 356a6fb416a1..70d5f0748d55 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -429,16 +429,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
/*====================================================================*/
-static int _pcc_get_socket(u_short sock, socket_state_t *state)
-{
- debug(3, "m32r-pcc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-} /* _get_socket */
-
-/*====================================================================*/
-
static int _pcc_set_socket(u_short sock, socket_state_t *state)
{
u_long reg = 0;
@@ -641,15 +631,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(_pcc_get_status(sock, value));
}
-static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
-
- if (socket[sock].flags & IS_ALIVE)
- return -EINVAL;
- LOCKED(_pcc_get_socket(sock, state));
-}
-
static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@@ -687,7 +668,6 @@ static int pcc_init(struct pcmcia_socket *s)
static struct pccard_operations pcc_operations = {
.init = pcc_init,
.get_status = pcc_get_status,
- .get_socket = pcc_get_socket,
.set_socket = pcc_set_socket,
.set_io_map = pcc_set_io_map,
.set_mem_map = pcc_set_mem_map,
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 6d9f71cfcb34..0e07d9535116 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -9,6 +9,9 @@
* <oliver.kurth@cyclades.de>
* Further fixes, v2.6 kernel port
* <marcelo.tosatti@cyclades.com>
+ *
+ * Some fixes, additions (C) 2005 Montavista Software, Inc.
+ * <vbordug@ru.mvista.com>
*
* "The ExCA standard specifies that socket controllers should provide
* two IO and five memory windows per socket, which can be independently
@@ -97,6 +100,11 @@ MODULE_LICENSE("Dual MPL/GPL");
#endif
#endif
+#if defined(CONFIG_MPC885ADS)
+#define CONFIG_PCMCIA_SLOT_A
+#define PCMCIA_GLITCHY_CD
+#endif
+
/* Cyclades ACS uses both slots */
#ifdef CONFIG_PRxK
#define CONFIG_PCMCIA_SLOT_A
@@ -374,10 +382,10 @@ static int voltage_set(int slot, int vcc, int vpp)
}
/* first, turn off all power */
- out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+ out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
/* enable new powersettings */
- out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | reg);
+ out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | reg);
return 0;
}
@@ -386,12 +394,89 @@ static int voltage_set(int slot, int vcc, int vpp)
static void hardware_enable(int slot)
{
- out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~BCSR1_PCCEN);
+ out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
}
static void hardware_disable(int slot)
{
- out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | BCSR1_PCCEN);
+ out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | BCSR1_PCCEN);
+}
+
+#endif
+
+/* MPC885ADS Boards */
+
+#if defined(CONFIG_MPC885ADS)
+
+#define PCMCIA_BOARD_MSG "MPC885ADS"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+ u32 reg = 0;
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ switch(vcc) {
+ case 0:
+ break;
+ case 33:
+ reg |= BCSR1_PCCVCC0;
+ break;
+ case 50:
+ reg |= BCSR1_PCCVCC1;
+ break;
+ default:
+ return 1;
+ }
+
+ switch(vpp) {
+ case 0:
+ break;
+ case 33:
+ case 50:
+ if(vcc == vpp)
+ reg |= BCSR1_PCCVPP1;
+ else
+ return 1;
+ break;
+ case 120:
+ if ((vcc == 33) || (vcc == 50))
+ reg |= BCSR1_PCCVPP0;
+ else
+ return 1;
+ default:
+ return 1;
+ }
+
+ /* first, turn off all power */
+ out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
+
+ /* enable new powersettings */
+ out_be32(bcsr_io, in_be32(bcsr_io) | reg);
+
+ iounmap(bcsr_io);
+ return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static void hardware_enable(int slot)
+{
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+ out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
+ iounmap(bcsr_io);
+}
+
+static void hardware_disable(int slot)
+{
+ unsigned *bcsr_io;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+ out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN);
+ iounmap(bcsr_io);
}
#endif
@@ -440,10 +525,10 @@ static int voltage_set(int slot, int vcc, int vpp)
}
/* first, turn off all power */
- out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
+ out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
/* enable new powersettings */
- out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) | reg);
+ out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) | reg);
return 0;
}
@@ -823,17 +908,6 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0;
}
-static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- int lsock = container_of(sock, struct socket_info, socket)->slot;
- *state = socket[lsock].state; /* copy the whole structure */
-
- dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-}
-
static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
int lsock = container_of(sock, struct socket_info, socket)->slot;
@@ -1023,8 +1097,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
if(io->flags & MAP_WRPROT)
reg |= M8XX_PCMCIA_POR_WRPROT;
- /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/
- if(io->flags & MAP_16BIT)
+ if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
reg |= M8XX_PCMCIA_POR_16BIT;
if(io->flags & MAP_ACTIVE)
@@ -1169,7 +1242,6 @@ static struct pccard_operations m8xx_services = {
.init = m8xx_sock_init,
.suspend = m8xx_suspend,
.get_status = m8xx_get_status,
- .get_socket = m8xx_get_socket,
.set_socket = m8xx_set_socket,
.set_io_map = m8xx_set_io_map,
.set_mem_map = m8xx_set_mem_map,
@@ -1244,7 +1316,7 @@ static int __init m8xx_init(void)
socket[i].socket.io_offset = 0;
socket[i].socket.pci_irq = i ? 7 : 9;
socket[i].socket.ops = &m8xx_services;
- socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+ socket[i].socket.resource_ops = &pccard_iodyn_ops;
socket[i].socket.cb_dev = NULL;
socket[i].socket.dev.dev = &m8xx_device.dev;
}
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 20642f0e7bfe..f2789afb22b2 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -304,75 +304,6 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
}
-static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct pd6729_socket *socket
- = container_of(sock, struct pd6729_socket, socket);
- unsigned char reg, vcc, vpp;
-
- state->flags = 0;
- state->Vcc = 0;
- state->Vpp = 0;
- state->io_irq = 0;
- state->csc_mask = 0;
-
- /* First the power status of the socket */
- reg = indirect_read(socket, I365_POWER);
-
- if (reg & I365_PWR_AUTO)
- state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */
-
- if (reg & I365_PWR_OUT)
- state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
-
- vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
-
- if (reg & I365_VCC_5V) {
- state->Vcc = (indirect_read(socket, PD67_MISC_CTL_1) &
- PD67_MC1_VCC_3V) ? 33 : 50;
-
- if (vpp == I365_VPP1_5V) {
- if (state->Vcc == 50)
- state->Vpp = 50;
- else
- state->Vpp = 33;
- }
- if (vpp == I365_VPP1_12V)
- state->Vpp = 120;
- }
-
- /* Now the IO card, RESET flags and IO interrupt */
- reg = indirect_read(socket, I365_INTCTL);
-
- if ((reg & I365_PC_RESET) == 0)
- state->flags |= SS_RESET;
- if (reg & I365_PC_IOCARD)
- state->flags |= SS_IOCARD; /* This is an IO card */
-
- /* Set the IRQ number */
- state->io_irq = socket->card_irq;
-
- /* Card status change */
- reg = indirect_read(socket, I365_CSCINT);
-
- if (reg & I365_CSC_DETECT)
- state->csc_mask |= SS_DETECT; /* Card detect is enabled */
-
- if (state->flags & SS_IOCARD) {/* IO Cards behave different */
- if (reg & I365_CSC_STSCHG)
- state->csc_mask |= SS_STSCHG;
- } else {
- if (reg & I365_CSC_BVD1)
- state->csc_mask |= SS_BATDEAD;
- if (reg & I365_CSC_BVD2)
- state->csc_mask |= SS_BATWARN;
- if (reg & I365_CSC_READY)
- state->csc_mask |= SS_READY;
- }
-
- return 0;
-}
-
static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct pd6729_socket *socket
@@ -640,7 +571,6 @@ static int pd6729_init(struct pcmcia_socket *sock)
static struct pccard_operations pd6729_operations = {
.init = pd6729_init,
.get_status = pd6729_get_status,
- .get_socket = pd6729_get_socket,
.set_socket = pd6729_set_socket,
.set_io_map = pd6729_set_io_map,
.set_mem_map = pd6729_set_mem_map,
@@ -704,13 +634,11 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
char configbyte;
struct pd6729_socket *socket;
- socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
+ socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
GFP_KERNEL);
if (!socket)
return -ENOMEM;
- memset(socket, 0, sizeof(struct pd6729_socket) * MAX_SOCKETS);
-
if ((ret = pci_enable_device(dev)))
goto err_out_free_mem;
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index 5209d8c7764f..fda06941e730 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -171,28 +171,22 @@ static int __init mst_pcmcia_init(void)
{
int ret;
- mst_pcmcia_device = kmalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL);
+ mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
if (!mst_pcmcia_device)
return -ENOMEM;
- memset(mst_pcmcia_device, 0, sizeof(*mst_pcmcia_device));
- mst_pcmcia_device->name = "pxa2xx-pcmcia";
+
mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
- ret = platform_device_register(mst_pcmcia_device);
+ ret = platform_device_add(mst_pcmcia_device);
+
if (ret)
- kfree(mst_pcmcia_device);
+ platform_device_put(mst_pcmcia_device);
return ret;
}
static void __exit mst_pcmcia_exit(void)
{
- /*
- * This call is supposed to free our mst_pcmcia_device.
- * Unfortunately platform_device don't have a free method, and
- * we can't assume it's free of any reference at this point so we
- * can't free it either.
- */
platform_device_unregister(mst_pcmcia_device);
}
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index 56c58831e80e..fd3647368955 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -36,9 +36,18 @@
struct scoop_pcmcia_config *platform_scoop_config;
#define SCOOP_DEV platform_scoop_config->devs
-static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev)
+static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
{
+ struct scoop_pcmcia_dev *scoopdev = &SCOOP_DEV[skt->nr];
+
reset_scoop(scoopdev->dev);
+
+ /* Shared power controls need to be handled carefully */
+ if (platform_scoop_config->power_ctrl)
+ platform_scoop_config->power_ctrl(scoopdev->dev, 0x0000, skt->nr);
+ else
+ write_scoop_reg(scoopdev->dev, SCOOP_CPR, 0x0000);
+
scoopdev->keep_vs = NO_KEEP_VS;
scoopdev->keep_rd = 0;
}
@@ -208,26 +217,17 @@ 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_DEV[skt->nr]);
+ sharpsl_pcmcia_init_reset(skt);
/* Enable interrupt */
write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_IMR, 0x00C0);
write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_MCR, 0x0101);
SCOOP_DEV[skt->nr].keep_vs = NO_KEEP_VS;
-
- if (machine_is_collie())
- /* We need to disable SS_OUTPUT_ENA here. */
- write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080);
}
static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
{
- /* CF_BUS_OFF */
- sharpsl_pcmcia_init_reset(&SCOOP_DEV[skt->nr]);
-
- if (machine_is_collie())
- /* We need to disable SS_OUTPUT_ENA here. */
- write_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR, read_scoop_reg(SCOOP_DEV[skt->nr].dev, SCOOP_CPR) & ~0x0080);
+ sharpsl_pcmcia_init_reset(skt);
}
static struct pcmcia_low_level sharpsl_pcmcia_ops = {
@@ -263,31 +263,25 @@ static int __init sharpsl_pcmcia_init(void)
{
int ret;
- sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs;
- sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
+ sharpsl_pcmcia_ops.nr = platform_scoop_config->num_devs;
+ sharpsl_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
+
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=platform_scoop_config->devs[0].dev;
+ sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev;
+
+ ret = platform_device_add(sharpsl_pcmcia_device);
- ret = platform_device_register(sharpsl_pcmcia_device);
if (ret)
- kfree(sharpsl_pcmcia_device);
+ platform_device_put(sharpsl_pcmcia_device);
return ret;
}
static void __exit sharpsl_pcmcia_exit(void)
{
- /*
- * This call is supposed to free our sharpsl_pcmcia_device.
- * Unfortunately platform_device don't have a free method, and
- * we can't assume it's free of any reference at this point so we
- * can't free it either.
- */
platform_device_unregister(sharpsl_pcmcia_device);
}
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 0668384ebc8b..514609369836 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
}
EXPORT_SYMBOL(pcmcia_adjust_resource_info);
-void pcmcia_validate_mem(struct pcmcia_socket *s)
+int pcmcia_validate_mem(struct pcmcia_socket *s)
{
if (s->resource_ops->validate_mem)
- s->resource_ops->validate_mem(s);
+ return s->resource_ops->validate_mem(s);
+ /* if there is no callback, we can assume that everything is OK */
+ return 0;
}
EXPORT_SYMBOL(pcmcia_validate_mem);
@@ -164,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = {
.exit = NULL,
};
EXPORT_SYMBOL(pccard_static_ops);
+
+
+#ifdef CONFIG_PCCARD_IODYN
+
+static struct resource *
+make_resource(unsigned long b, unsigned long n, int flags, char *name)
+{
+ struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
+
+ if (res) {
+ res->name = name;
+ res->start = b;
+ res->end = b + n - 1;
+ res->flags = flags;
+ }
+ return res;
+}
+
+struct pcmcia_align_data {
+ unsigned long mask;
+ unsigned long offset;
+};
+
+static void pcmcia_align(void *align_data, struct resource *res,
+ unsigned long size, unsigned long align)
+{
+ struct pcmcia_align_data *data = align_data;
+ unsigned long start;
+
+ start = (res->start & ~data->mask) + data->offset;
+ if (start < res->start)
+ start += data->mask + 1;
+ res->start = start;
+
+#ifdef CONFIG_X86
+ if (res->flags & IORESOURCE_IO) {
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+#endif
+
+#ifdef CONFIG_M68K
+ if (res->flags & IORESOURCE_IO) {
+ if ((res->start + size - 1) >= 1024)
+ res->start = res->end;
+ }
+#endif
+}
+
+
+static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
+ unsigned long r_end, struct pcmcia_socket *s)
+{
+ return adjust_resource(res, r_start, r_end - r_start + 1);
+}
+
+
+static struct resource *iodyn_find_io_region(unsigned long base, int num,
+ unsigned long align, struct pcmcia_socket *s)
+{
+ struct resource *res = make_resource(0, num, IORESOURCE_IO,
+ s->dev.class_id);
+ struct pcmcia_align_data data;
+ unsigned long min = base;
+ int ret;
+
+ if (align == 0)
+ align = 0x10000;
+
+ data.mask = align - 1;
+ data.offset = base & data.mask;
+
+#ifdef CONFIG_PCI
+ if (s->cb_dev) {
+ ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
+ min, 0, pcmcia_align, &data);
+ } else
+#endif
+ ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
+ 1, pcmcia_align, &data);
+
+ if (ret != 0) {
+ kfree(res);
+ res = NULL;
+ }
+ return res;
+}
+
+struct pccard_resource_ops pccard_iodyn_ops = {
+ .validate_mem = NULL,
+ .adjust_io_region = iodyn_adjust_io_region,
+ .find_io = iodyn_find_io_region,
+ .find_mem = NULL,
+ .adjust_resource = NULL,
+ .init = static_init,
+ .exit = NULL,
+};
+EXPORT_SYMBOL(pccard_iodyn_ops);
+
+#endif /* CONFIG_PCCARD_IODYN */
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 00960a379b9c..5301ac60358f 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -75,10 +75,9 @@ static DECLARE_MUTEX(rsrc_sem);
static struct resource *
make_resource(unsigned long b, unsigned long n, int flags, 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 = b;
res->end = b + n - 1;
@@ -200,12 +199,11 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
base, base+num-1);
/* First, what does a floating port look like? */
- b = kmalloc(256, GFP_KERNEL);
+ b = kzalloc(256, GFP_KERNEL);
if (!b) {
printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
return;
}
- memset(b, 0, 256);
for (i = base, most = 0; i < base+num; i += 8) {
res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
if (!res)
@@ -407,69 +405,79 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
{
- struct socket_data *s_data = s->resource_data;
- u_long ok;
- if (m == &s_data->mem_db)
- return 0;
- ok = inv_probe(m->next, s);
- if (ok) {
- if (m->base >= 0x100000)
- sub_interval(&s_data->mem_db, m->base, m->num);
- return ok;
- }
- if (m->base < 0x100000)
- return 0;
- return do_mem_probe(m->base, m->num, s);
+ struct socket_data *s_data = s->resource_data;
+ u_long ok;
+ if (m == &s_data->mem_db)
+ return 0;
+ ok = inv_probe(m->next, s);
+ if (ok) {
+ if (m->base >= 0x100000)
+ sub_interval(&s_data->mem_db, m->base, m->num);
+ return ok;
+ }
+ if (m->base < 0x100000)
+ return 0;
+ return do_mem_probe(m->base, m->num, s);
}
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
- struct resource_map *m, mm;
- static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
- u_long b, i, ok = 0;
- struct socket_data *s_data = s->resource_data;
+ struct resource_map *m, mm;
+ static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
+ unsigned long b, i, ok = 0;
+ struct socket_data *s_data = s->resource_data;
- /* We do up to four passes through the list */
- if (probe_mask & MEM_PROBE_HIGH) {
- if (inv_probe(s_data->mem_db.next, s) > 0)
- return;
- printk(KERN_NOTICE "cs: warning: no high memory space "
- "available!\n");
- }
- if ((probe_mask & MEM_PROBE_LOW) == 0)
- return;
- for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
- mm = *m;
- /* Only probe < 1 MB */
- if (mm.base >= 0x100000) continue;
- if ((mm.base | mm.num) & 0xffff) {
- ok += do_mem_probe(mm.base, mm.num, s);
- continue;
+ /* We do up to four passes through the list */
+ if (probe_mask & MEM_PROBE_HIGH) {
+ if (inv_probe(s_data->mem_db.next, s) > 0)
+ return 0;
+ printk(KERN_NOTICE "cs: warning: no high memory space "
+ "available!\n");
+ return -ENODEV;
}
- /* Special probe for 64K-aligned block */
- for (i = 0; i < 4; i++) {
- b = order[i] << 12;
- if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
- if (ok >= mem_limit)
- sub_interval(&s_data->mem_db, b, 0x10000);
- else
- ok += do_mem_probe(b, 0x10000, s);
- }
+
+ for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
+ mm = *m;
+ /* Only probe < 1 MB */
+ if (mm.base >= 0x100000)
+ continue;
+ if ((mm.base | mm.num) & 0xffff) {
+ ok += do_mem_probe(mm.base, mm.num, s);
+ continue;
+ }
+ /* Special probe for 64K-aligned block */
+ for (i = 0; i < 4; i++) {
+ b = order[i] << 12;
+ if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
+ if (ok >= mem_limit)
+ sub_interval(&s_data->mem_db, b, 0x10000);
+ else
+ ok += do_mem_probe(b, 0x10000, s);
+ }
+ }
}
- }
+
+ if (ok > 0)
+ return 0;
+
+ return -ENODEV;
}
#else /* CONFIG_PCMCIA_PROBE */
-static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
+static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
struct resource_map *m, mm;
struct socket_data *s_data = s->resource_data;
+ unsigned long ok = 0;
for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
mm = *m;
- do_mem_probe(mm.base, mm.num, s);
+ ok += do_mem_probe(mm.base, mm.num, s);
}
+ if (ok > 0)
+ return 0;
+ return -ENODEV;
}
#endif /* CONFIG_PCMCIA_PROBE */
@@ -478,27 +486,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
/*
* Locking note: Must be called with skt_sem held!
*/
-static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
+static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{
struct socket_data *s_data = s->resource_data;
- if (probe_mem) {
- unsigned int probe_mask;
+ unsigned int probe_mask = MEM_PROBE_LOW;
+ int ret = 0;
- down(&rsrc_sem);
+ if (!probe_mem)
+ return 0;
- probe_mask = MEM_PROBE_LOW;
- if (s->features & SS_CAP_PAGE_REGS)
- probe_mask = MEM_PROBE_HIGH;
+ down(&rsrc_sem);
- if (probe_mask & ~s_data->rsrc_mem_probe) {
+ if (s->features & SS_CAP_PAGE_REGS)
+ probe_mask = MEM_PROBE_HIGH;
+
+ if (probe_mask & ~s_data->rsrc_mem_probe) {
+ if (s->state & SOCKET_PRESENT)
+ ret = validate_mem(s, probe_mask);
+ if (!ret)
s_data->rsrc_mem_probe |= probe_mask;
+ }
- if (s->state & SOCKET_PRESENT)
- validate_mem(s, probe_mask);
- }
+ up(&rsrc_sem);
- up(&rsrc_sem);
- }
+ return ret;
}
struct pcmcia_align_data {
@@ -837,10 +848,9 @@ static int nonstatic_init(struct pcmcia_socket *s)
{
struct socket_data *data;
- data = kmalloc(sizeof(struct socket_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- memset(data, 0, sizeof(struct socket_data));
data->mem_db.next = &data->mem_db;
data->io_db.next = &data->io_db;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 9e7ccd8a4321..ea7d9ca160b2 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -297,25 +297,6 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
/*
- * Implements the get_socket() operation for the in-kernel PCMCIA
- * service (formerly SS_GetSocket in Card Services). Not a very
- * exciting routine.
- *
- * Returns: 0
- */
-static int
-soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
-
- debug(skt, 2, "\n");
-
- *state = skt->cs_state;
-
- return 0;
-}
-
-/*
* Implements the set_socket() operation for the in-kernel PCMCIA
* service (formerly SS_SetSocket in Card Services). We more or
* less punt all of this work and let the kernel handle the details
@@ -528,7 +509,6 @@ static struct pccard_operations soc_common_pcmcia_operations = {
.init = soc_common_pcmcia_sock_init,
.suspend = soc_common_pcmcia_suspend,
.get_status = soc_common_pcmcia_get_status,
- .get_socket = soc_common_pcmcia_get_socket,
.set_socket = soc_common_pcmcia_set_socket,
.set_io_map = soc_common_pcmcia_set_io_map,
.set_mem_map = soc_common_pcmcia_set_mem_map,
@@ -665,13 +645,12 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
down(&soc_pcmcia_sockets_lock);
- sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
+ sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
if (!sinfo) {
ret = -ENOMEM;
goto out;
}
- memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr));
sinfo->nskt = nr;
/*
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 4a3150a7854c..5ab1cdef7c48 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -42,35 +42,28 @@
static ssize_t pccard_show_type(struct class_device *dev, char *buf)
{
- int val;
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- s->ops->get_status(s, &val);
- if (val & SS_CARDBUS)
+ if (s->state & SOCKET_CARDBUS)
return sprintf(buf, "32-bit\n");
- if (val & SS_DETECT)
- return sprintf(buf, "16-bit\n");
- return sprintf(buf, "invalid\n");
+ return sprintf(buf, "16-bit\n");
}
-static CLASS_DEVICE_ATTR(card_type, 0400, pccard_show_type, NULL);
+static CLASS_DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
{
- int val;
struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- s->ops->get_status(s, &val);
- if (val & SS_3VCARD)
- return sprintf(buf, "3.3V\n");
- if (val & SS_XVCARD)
- return sprintf(buf, "X.XV\n");
- return sprintf(buf, "5.0V\n");
+ if (s->socket.Vcc)
+ return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10,
+ s->socket.Vcc % 10);
+ return sprintf(buf, "X.XV\n");
}
-static CLASS_DEVICE_ATTR(card_voltage, 0400, pccard_show_voltage, NULL);
+static CLASS_DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
{
@@ -79,7 +72,7 @@ static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
}
-static CLASS_DEVICE_ATTR(card_vpp, 0400, pccard_show_vpp, NULL);
+static CLASS_DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
{
@@ -88,7 +81,7 @@ static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
}
-static CLASS_DEVICE_ATTR(card_vcc, 0400, pccard_show_vcc, NULL);
+static CLASS_DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
@@ -105,6 +98,30 @@ static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, si
}
static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert);
+
+static ssize_t pccard_show_card_pm_state(struct class_device *dev, char *buf)
+{
+ struct pcmcia_socket *s = to_socket(dev);
+ return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on");
+}
+
+static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *buf, size_t count)
+{
+ ssize_t ret = -EINVAL;
+ struct pcmcia_socket *s = to_socket(dev);
+
+ if (!count)
+ return -EINVAL;
+
+ if (!(s->state & SOCKET_SUSPEND) && !strncmp(buf, "off", 3))
+ ret = pcmcia_suspend_card(s);
+ else if ((s->state & SOCKET_SUSPEND) && !strncmp(buf, "on", 2))
+ ret = pcmcia_resume_card(s);
+
+ return ret ? -ENODEV : count;
+}
+static CLASS_DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state);
+
static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count)
{
ssize_t ret;
@@ -292,10 +309,9 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL);
+ cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis)
return -ENOMEM;
- memset(cis, 0, sizeof(cisdump_t));
cis->Length = count + 1;
memcpy(cis->Data, buf, count);
@@ -328,6 +344,7 @@ static struct class_device_attribute *pccard_socket_attributes[] = {
&class_device_attr_card_vpp,
&class_device_attr_card_vcc,
&class_device_attr_card_insert,
+ &class_device_attr_card_pm_state,
&class_device_attr_card_eject,
&class_device_attr_card_irq_mask,
&class_device_attr_available_resources_setup_done,
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index e31263864377..73bad1d5cb23 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -181,13 +181,6 @@ static void tcic_setl(u_char reg, u_int data)
outw(data >> 16, tcic_base+reg+2);
}
-static u_char tcic_aux_getb(u_short reg)
-{
- u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
- tcic_setb(TCIC_MODE, mode);
- return tcic_getb(TCIC_AUX);
-}
-
static void tcic_aux_setb(u_short reg, u_char data)
{
u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
@@ -641,59 +634,6 @@ static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value);
return 0;
} /* tcic_get_status */
-
-/*====================================================================*/
-
-static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
- u_char reg;
- u_short scf1, scf2;
-
- tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
- | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
- scf1 = tcic_getw(TCIC_DATA);
- state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
- state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
- state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
- if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
- state->flags |= SS_OUTPUT_ENA;
- state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
- if (state->io_irq == 1) state->io_irq = 11;
-
- reg = tcic_getb(TCIC_PWR);
- state->Vcc = state->Vpp = 0;
- if (reg & TCIC_PWR_VCC(psock)) {
- if (reg & TCIC_PWR_VPP(psock))
- state->Vcc = 50;
- else
- state->Vcc = state->Vpp = 50;
- } else {
- if (reg & TCIC_PWR_VPP(psock)) {
- state->Vcc = 50;
- state->Vpp = 120;
- }
- }
- reg = tcic_aux_getb(TCIC_AUX_ILOCK);
- state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
-
- /* Card status change interrupt mask */
- tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
- scf2 = tcic_getw(TCIC_DATA);
- state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
- if (state->flags & SS_IOCARD) {
- state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
- } else {
- state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
- state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
- state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
- }
-
- debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", psock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-} /* tcic_get_socket */
/*====================================================================*/
@@ -874,7 +814,6 @@ static int tcic_init(struct pcmcia_socket *s)
static struct pccard_operations tcic_operations = {
.init = tcic_init,
.get_status = tcic_get_status,
- .get_socket = tcic_get_socket,
.set_socket = tcic_set_socket,
.set_io_map = tcic_set_io_map,
.set_mem_map = tcic_set_mem_map,
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index 539b5cd1a598..d5b4ff74462e 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -873,7 +873,7 @@ static int ti1250_override(struct yenta_socket *socket)
* Some fixup code to make everybody happy (TM).
*/
-#ifdef CONFIG_CARDBUS
+#ifdef CONFIG_YENTA_ENE_TUNE
/**
* set/clear various test bits:
* Defaults to clear the bit.
@@ -937,7 +937,7 @@ static int ene_override(struct yenta_socket *socket)
}
#else
# define ene_override ti1250_override
-#endif
+#endif /* !CONFIG_YENTA_ENE_TUNE */
#endif /* _LINUX_TI113X_H */
diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c
index 38a028c725d4..0574efd7828a 100644
--- a/drivers/pcmcia/vrc4171_card.c
+++ b/drivers/pcmcia/vrc4171_card.c
@@ -1,7 +1,7 @@
/*
* vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
*
- * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
#include "i82365.h"
MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_LICENSE("GPL");
#define CARD_MAX_SLOTS 2
@@ -301,75 +301,6 @@ static int pccard_get_status(struct pcmcia_socket *sock, u_int *value)
return 0;
}
-static inline u_char get_Vcc_value(uint8_t voltage)
-{
- switch (voltage) {
- case VCC_STATUS_3V:
- return 33;
- case VCC_STATUS_5V:
- return 50;
- default:
- break;
- }
-
- return 0;
-}
-
-static inline u_char get_Vpp_value(uint8_t power, u_char Vcc)
-{
- if ((power & 0x03) == 0x01 || (power & 0x03) == 0x02)
- return Vcc;
-
- return 0;
-}
-
-static int pccard_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- unsigned int slot;
- uint8_t power, voltage, control, cscint;
-
- if (sock == NULL || sock->sock >= CARD_MAX_SLOTS || state == NULL)
- return -EINVAL;
-
- slot = sock->sock;
-
- power = exca_read_byte(slot, I365_POWER);
- voltage = exca_read_byte(slot, CARD_VOLTAGE_SELECT);
-
- state->Vcc = get_Vcc_value(voltage);
- state->Vpp = get_Vpp_value(power, state->Vcc);
-
- state->flags = 0;
- if (power & POWER_ENABLE)
- state->flags |= SS_PWR_AUTO;
- if (power & I365_PWR_OUT)
- state->flags |= SS_OUTPUT_ENA;
-
- control = exca_read_byte(slot, I365_INTCTL);
- if (control & I365_PC_IOCARD)
- state->flags |= SS_IOCARD;
- if (!(control & I365_PC_RESET))
- state->flags |= SS_RESET;
-
- cscint = exca_read_byte(slot, I365_CSCINT);
- state->csc_mask = 0;
- if (state->flags & SS_IOCARD) {
- if (cscint & I365_CSC_STSCHG)
- state->flags |= SS_STSCHG;
- } else {
- if (cscint & I365_CSC_BVD1)
- state->csc_mask |= SS_BATDEAD;
- if (cscint & I365_CSC_BVD2)
- state->csc_mask |= SS_BATWARN;
- }
- if (cscint & I365_CSC_READY)
- state->csc_mask |= SS_READY;
- if (cscint & I365_CSC_DETECT)
- state->csc_mask |= SS_DETECT;
-
- return 0;
-}
-
static inline uint8_t set_Vcc_value(u_char Vcc)
{
switch (Vcc) {
@@ -551,7 +482,6 @@ static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
static struct pccard_operations vrc4171_pccard_operations = {
.init = pccard_init,
.get_status = pccard_get_status,
- .get_socket = pccard_get_socket,
.set_socket = pccard_set_socket,
.set_io_map = pccard_set_io_map,
.set_mem_map = pccard_set_mem_map,
diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c
index db91259dc50e..57f38dba0a48 100644
--- a/drivers/pcmcia/vrc4173_cardu.c
+++ b/drivers/pcmcia/vrc4173_cardu.c
@@ -6,7 +6,7 @@
* NEC VRC4173 CARDU driver for Socket Services
* (This device doesn't support CardBus. it is supporting only 16bit PC Card.)
*
- * Copyright 2002,2003 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -41,7 +41,7 @@
#include "vrc4173_cardu.h"
MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_LICENSE("GPL");
static int vrc4173_cardu_slots;
@@ -198,48 +198,6 @@ static int cardu_get_status(unsigned int sock, u_int *value)
return 0;
}
-static inline u_char get_Vcc_value(uint8_t val)
-{
- switch (val & VCC_MASK) {
- case VCC_3V:
- return 33;
- case VCC_5V:
- return 50;
- }
-
- return 0;
-}
-
-static inline u_char get_Vpp_value(uint8_t val)
-{
- switch (val & VPP_MASK) {
- case VPP_12V:
- return 120;
- case VPP_VCC:
- return get_Vcc_value(val);
- }
-
- return 0;
-}
-
-static int cardu_get_socket(unsigned int sock, socket_state_t *state)
-{
- vrc4173_socket_t *socket = &cardu_sockets[sock];
- uint8_t val;
-
- val = exca_readb(socket, PWR_CNT);
- state->Vcc = get_Vcc_value(val);
- state->Vpp = get_Vpp_value(val);
- state->flags = 0;
- if (val & CARD_OUT_EN) state->flags |= SS_OUTPUT_ENA;
-
- val = exca_readb(socket, INT_GEN_CNT);
- if (!(val & CARD_REST0)) state->flags |= SS_RESET;
- if (val & CARD_TYPE_IO) state->flags |= SS_IOCARD;
-
- return 0;
-}
-
static inline uint8_t set_Vcc_value(u_char Vcc)
{
switch (Vcc) {
@@ -431,7 +389,6 @@ static struct pccard_operations cardu_operations = {
.register_callback = cardu_register_callback,
.inquire_socket = cardu_inquire_socket,
.get_status = cardu_get_status,
- .get_socket = cardu_get_socket,
.set_socket = cardu_set_socket,
.get_io_map = cardu_get_io_map,
.set_io_map = cardu_set_io_map,
@@ -604,7 +561,7 @@ static int __devinit vrc4173_cardu_init(void)
{
vrc4173_cardu_slots = 0;
- return pci_module_init(&vrc4173_cardu_driver);
+ return pci_register_driver(&vrc4173_cardu_driver);
}
static void __devexit vrc4173_cardu_exit(void)
diff --git a/drivers/pcmcia/vrc4173_cardu.h b/drivers/pcmcia/vrc4173_cardu.h
index 113726f7cf92..7d77c74120c1 100644
--- a/drivers/pcmcia/vrc4173_cardu.h
+++ b/drivers/pcmcia/vrc4173_cardu.h
@@ -5,7 +5,7 @@
* BRIEF MODULE DESCRIPTION
* Include file for NEC VRC4173 CARDU.
*
- * Copyright 2002 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index ec6ab65f0872..4145eb83b9b6 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -49,7 +49,13 @@ MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only
#define to_cycles(ns) ((ns)/120)
#define to_ns(cycles) ((cycles)*120)
+/**
+ * yenta PCI irq probing.
+ * currently only used in the TI/EnE initialization code
+ */
+#ifdef CONFIG_YENTA_TI
static int yenta_probe_cb_irq(struct yenta_socket *socket);
+#endif
static unsigned int override_bios;
@@ -224,95 +230,6 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0;
}
-static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
-{
- 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;
-
- 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;
- }
- }
-}
-
-static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
-{
- struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
- u8 reg;
- u32 control;
-
- control = cb_readl(socket, CB_SOCKET_CONTROL);
-
- yenta_get_power(socket, state);
- state->io_irq = socket->io_irq;
-
- if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
- u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL);
- if (bridge & CB_BRIDGE_CRST)
- state->flags |= SS_RESET;
- return 0;
- }
-
- /* 16-bit card state.. */
- reg = exca_readb(socket, I365_POWER);
- state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
- state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
-
- reg = exca_readb(socket, I365_INTCTL);
- state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
- state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
-
- reg = exca_readb(socket, I365_CSCINT);
- state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
- if (state->flags & SS_IOCARD) {
- state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
- } else {
- state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
- state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
- state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
- }
-
- return 0;
-}
-
static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
{
/* some birdges require to use the ExCA registers to power 16bit cards */
@@ -531,6 +448,9 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
csc = exca_readb(socket, I365_CSC);
+ if (!(cb_event || csc))
+ return IRQ_NONE;
+
events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@@ -544,10 +464,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events)
pcmcia_parse_events(&socket->socket, events);
- if (cb_event || csc)
- return IRQ_HANDLED;
-
- return IRQ_NONE;
+ return IRQ_HANDLED;
}
static void yenta_interrupt_wrapper(unsigned long data)
@@ -828,17 +745,24 @@ static struct pccard_operations yenta_socket_operations = {
.init = yenta_sock_init,
.suspend = yenta_sock_suspend,
.get_status = yenta_get_status,
- .get_socket = yenta_get_socket,
.set_socket = yenta_set_socket,
.set_io_map = yenta_set_io_map,
.set_mem_map = yenta_set_mem_map,
};
+#ifdef CONFIG_YENTA_TI
#include "ti113x.h"
+#endif
+#ifdef CONFIG_YENTA_RICOH
#include "ricoh.h"
+#endif
+#ifdef CONFIG_YENTA_TOSHIBA
#include "topic.h"
+#endif
+#ifdef CONFIG_YENTA_O2
#include "o2micro.h"
+#endif
enum {
CARDBUS_TYPE_DEFAULT = -1,
@@ -858,6 +782,7 @@ enum {
* initialization sequences etc details. List them here..
*/
static struct cardbus_type cardbus_type[] = {
+#ifdef CONFIG_YENTA_TI
[CARDBUS_TYPE_TI] = {
.override = ti_override,
.save_state = ti_save_state,
@@ -882,27 +807,36 @@ static struct cardbus_type cardbus_type[] = {
.restore_state = ti_restore_state,
.sock_init = ti_init,
},
+#endif
+#ifdef CONFIG_YENTA_RICOH
[CARDBUS_TYPE_RICOH] = {
.override = ricoh_override,
.save_state = ricoh_save_state,
.restore_state = ricoh_restore_state,
},
+#endif
+#ifdef CONFIG_YENTA_TOSHIBA
[CARDBUS_TYPE_TOPIC95] = {
.override = topic95_override,
},
[CARDBUS_TYPE_TOPIC97] = {
.override = topic97_override,
},
+#endif
+#ifdef CONFIG_YENTA_O2
[CARDBUS_TYPE_O2MICRO] = {
.override = o2micro_override,
.restore_state = o2micro_restore_state,
},
+#endif
+#ifdef CONFIG_YENTA_TI
[CARDBUS_TYPE_ENE] = {
.override = ene_override,
.save_state = ti_save_state,
.restore_state = ti_restore_state,
.sock_init = ti_init,
},
+#endif
};
@@ -948,6 +882,12 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
}
+/**
+ * yenta PCI irq probing.
+ * currently only used in the TI/EnE initialization code
+ */
+#ifdef CONFIG_YENTA_TI
+
/* interrupt handler, only used during probing */
static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1000,6 +940,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
return (int) socket->probe_status;
}
+#endif /* CONFIG_YENTA_TI */
/*
@@ -1078,10 +1019,9 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
return -ENODEV;
}
- socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
+ socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket)
return -ENOMEM;
- memset(socket, 0, sizeof(*socket));
/* prepare pcmcia_socket */
socket->socket.ops = &yenta_socket_operations;
@@ -1263,6 +1203,7 @@ static struct pci_device_id yenta_table [] = {
* advanced overrides instead. (I can't get the
* data sheets for these devices. --rmk)
*/
+#ifdef CONFIG_YENTA_TI
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X),
@@ -1305,18 +1246,25 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
+#endif /* CONFIG_YENTA_TI */
+#ifdef CONFIG_YENTA_RICOH
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
+#endif
+#ifdef CONFIG_YENTA_TOSHIBA
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),
+#endif
+#ifdef CONFIG_YENTA_O2
CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO),
+#endif
/* match any cardbus bridge */
CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT),
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index bd7c966ea2d7..0ecbe4edbec1 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -69,6 +69,7 @@ static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv)
return 0;
clink->card = card;
clink->driver = drv;
+ clink->pm_state = PMSG_ON;
if (drv->probe) {
if (drv->probe(clink, id)>=0)
return 1;
@@ -333,6 +334,28 @@ void pnp_release_card_device(struct pnp_dev * dev)
up_write(&dev->dev.bus->subsys.rwsem);
}
+/*
+ * suspend/resume callbacks
+ */
+static int card_suspend(struct pnp_dev *dev, pm_message_t state)
+{
+ struct pnp_card_link *link = dev->card_link;
+ if (link->pm_state.event == state.event)
+ return 0;
+ link->pm_state = state;
+ return link->driver->suspend(link, state);
+}
+
+static int card_resume(struct pnp_dev *dev)
+{
+ struct pnp_card_link *link = dev->card_link;
+ if (link->pm_state.event == PM_EVENT_ON)
+ return 0;
+ link->pm_state = PMSG_ON;
+ link->driver->resume(link);
+ return 0;
+}
+
/**
* pnp_register_card_driver - registers a PnP card driver with the PnP Layer
* @drv: pointer to the driver to register
@@ -348,6 +371,8 @@ int pnp_register_card_driver(struct pnp_card_driver * drv)
drv->link.flags = drv->flags;
drv->link.probe = NULL;
drv->link.remove = &card_remove_first;
+ drv->link.suspend = drv->suspend ? card_suspend : NULL;
+ drv->link.resume = drv->resume ? card_resume : NULL;
spin_lock(&pnp_lock);
list_add_tail(&drv->global_list, &pnp_card_drivers);
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d3ccce706ab4..7cafacdd12b0 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -146,10 +146,59 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}
+static int pnp_bus_suspend(struct device *dev, pm_message_t state)
+{
+ struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+ struct pnp_driver * pnp_drv = pnp_dev->driver;
+ int error;
+
+ if (!pnp_drv)
+ return 0;
+
+ if (pnp_drv->suspend) {
+ error = pnp_drv->suspend(pnp_dev, state);
+ if (error)
+ return error;
+ }
+
+ if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) &&
+ pnp_can_disable(pnp_dev)) {
+ error = pnp_stop_dev(pnp_dev);
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+static int pnp_bus_resume(struct device *dev)
+{
+ struct pnp_dev * pnp_dev = to_pnp_dev(dev);
+ struct pnp_driver * pnp_drv = pnp_dev->driver;
+ int error;
+
+ if (!pnp_drv)
+ return 0;
+
+ if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
+ error = pnp_start_dev(pnp_dev);
+ if (error)
+ return error;
+ }
+
+ if (pnp_drv->resume)
+ return pnp_drv->resume(pnp_dev);
+
+ return 0;
+}
struct bus_type pnp_bus_type = {
.name = "pnp",
.match = pnp_bus_match,
+ .probe = pnp_device_probe,
+ .remove = pnp_device_remove,
+ .suspend = pnp_bus_suspend,
+ .resume = pnp_bus_resume,
};
@@ -168,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv)
drv->driver.name = drv->name;
drv->driver.bus = &pnp_bus_type;
- drv->driver.probe = pnp_device_probe;
- drv->driver.remove = pnp_device_remove;
count = driver_register(&drv->driver);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 261668618b2d..c4256aa32bcb 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -470,6 +470,53 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
}
/**
+ * pnp_start_dev - low-level start of the PnP device
+ * @dev: pointer to the desired device
+ *
+ * assumes that resources have alread been allocated
+ */
+
+int pnp_start_dev(struct pnp_dev *dev)
+{
+ if (!pnp_can_write(dev)) {
+ pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+ return -EINVAL;
+ }
+
+ if (dev->protocol->set(dev, &dev->res)<0) {
+ pnp_err("Failed to activate device %s.", dev->dev.bus_id);
+ return -EIO;
+ }
+
+ pnp_info("Device %s activated.", dev->dev.bus_id);
+
+ return 0;
+}
+
+/**
+ * pnp_stop_dev - low-level disable of the PnP device
+ * @dev: pointer to the desired device
+ *
+ * does not free resources
+ */
+
+int pnp_stop_dev(struct pnp_dev *dev)
+{
+ if (!pnp_can_disable(dev)) {
+ pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+ return -EINVAL;
+ }
+ if (dev->protocol->disable(dev)<0) {
+ pnp_err("Failed to disable device %s.", dev->dev.bus_id);
+ return -EIO;
+ }
+
+ pnp_info("Device %s disabled.", dev->dev.bus_id);
+
+ return 0;
+}
+
+/**
* pnp_activate_dev - activates a PnP device for use
* @dev: pointer to the desired device
*
@@ -477,6 +524,8 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
*/
int pnp_activate_dev(struct pnp_dev *dev)
{
+ int error;
+
if (!dev)
return -EINVAL;
if (dev->active) {
@@ -487,18 +536,11 @@ int pnp_activate_dev(struct pnp_dev *dev)
if (pnp_auto_config_dev(dev))
return -EBUSY;
- if (!pnp_can_write(dev)) {
- pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
- return -EINVAL;
- }
-
- if (dev->protocol->set(dev, &dev->res)<0) {
- pnp_err("Failed to activate device %s.", dev->dev.bus_id);
- return -EIO;
- }
+ error = pnp_start_dev(dev);
+ if (error)
+ return error;
dev->active = 1;
- pnp_info("Device %s activated.", dev->dev.bus_id);
return 1;
}
@@ -511,23 +553,19 @@ int pnp_activate_dev(struct pnp_dev *dev)
*/
int pnp_disable_dev(struct pnp_dev *dev)
{
+ int error;
+
if (!dev)
return -EINVAL;
if (!dev->active) {
return 0; /* the device is already disabled */
}
- if (!pnp_can_disable(dev)) {
- pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
- return -EINVAL;
- }
- if (dev->protocol->disable(dev)<0) {
- pnp_err("Failed to disable device %s.", dev->dev.bus_id);
- return -EIO;
- }
+ error = pnp_stop_dev(dev);
+ if (error)
+ return error;
dev->active = 0;
- pnp_info("Device %s disabled.", dev->dev.bus_id);
/* release the resources so that other devices can use them */
down(&pnp_res_mutex);
@@ -558,6 +596,8 @@ EXPORT_SYMBOL(pnp_manual_config_dev);
#if 0
EXPORT_SYMBOL(pnp_auto_config_dev);
#endif
+EXPORT_SYMBOL(pnp_start_dev);
+EXPORT_SYMBOL(pnp_stop_dev);
EXPORT_SYMBOL(pnp_activate_dev);
EXPORT_SYMBOL(pnp_disable_dev);
EXPORT_SYMBOL(pnp_resource_change);
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 6b7583f497d0..a1f0b0ba2bfe 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -31,15 +31,6 @@ static struct {
} pnp_bios_callpoint;
-/* The PnP BIOS entries in the GDT */
-#define PNP_GDT (GDT_ENTRY_PNPBIOS_BASE * 8)
-
-#define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */
-#define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */
-#define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */
-#define PNP_TS1 (PNP_GDT+0x18) /* transfer data segment */
-#define PNP_TS2 (PNP_GDT+0x20) /* another data segment */
-
/*
* These are some opcodes for a "static asmlinkage"
* As this code is *not* executed inside the linux kernel segment, but in a
@@ -67,16 +58,11 @@ __asm__(
".previous \n"
);
-#define Q_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
-} while(0)
-
#define Q2_SET_SEL(cpu, selname, address, size) \
do { \
-set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \
-set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
+struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \
+set_base(gdt[(selname) >> 3], (u32)(address)); \
+set_limit(gdt[(selname) >> 3], size); \
} while(0)
static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
@@ -115,8 +101,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
return PNP_FUNCTION_NOT_SUPPORTED;
cpu = get_cpu();
- save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8];
- per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc;
+ save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8];
+ get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc;
/* On some boxes IRQ's during PnP BIOS calls are deadly. */
spin_lock_irqsave(&pnp_bios_lock, flags);
@@ -158,7 +144,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
);
spin_unlock_irqrestore(&pnp_bios_lock, flags);
- per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40;
+ get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
put_cpu();
/* If we get here and this is set then the PnP BIOS faulted on us. */
@@ -290,12 +276,15 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
+ u16 tmp_nodenum;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot && pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
+ tmp_nodenum = *nodenum;
status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
- nodenum, sizeof(char), data, 65536);
+ &tmp_nodenum, sizeof(tmp_nodenum), data, 65536);
+ *nodenum = tmp_nodenum;
return status;
}
@@ -535,10 +524,12 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header)
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
- for(i=0; i < NR_CPUS; i++)
- {
- Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
- Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024);
- Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024);
- }
+ for (i = 0; i < NR_CPUS; i++) {
+ struct desc_struct *gdt = get_cpu_gdt_table(i);
+ if (!gdt)
+ continue;
+ set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc);
+ set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg));
+ set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg));
+ }
}
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index f49674f07949..b154b3f52cbe 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -56,7 +56,6 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/slab.h>
-#include <linux/kobject_uevent.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/dmi.h>
@@ -106,8 +105,6 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
char *argv [3], **envp, *buf, *scratch;
int i = 0, value;
- if (!hotplug_path [0])
- return -ENOENT;
if (!current->fs->root) {
return -EAGAIN;
}
@@ -119,8 +116,9 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
return -ENOMEM;
}
- /* only one standardized param to hotplug command: type */
- argv [0] = hotplug_path;
+ /* FIXME: if there are actual users of this, it should be integrated into
+ * the driver core and use the usual infrastructure like sysfs and uevents */
+ argv [0] = "/sbin/pnpbios";
argv [1] = "dock";
argv [2] = NULL;
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index dc749609699a..5480119ff9d3 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv)
/* initialize common driver fields */
rdrv->driver.name = rdrv->name;
rdrv->driver.bus = &rio_bus_type;
- rdrv->driver.probe = rio_device_probe;
- rdrv->driver.remove = rio_device_remove;
/* register with core */
return driver_register(&rdrv->driver);
@@ -204,7 +202,9 @@ static struct device rio_bus = {
struct bus_type rio_bus_type = {
.name = "rapidio",
.match = rio_match_bus,
- .dev_attrs = rio_dev_attrs
+ .dev_attrs = rio_dev_attrs,
+ .probe = rio_device_probe,
+ .remove = rio_device_remove,
};
/**
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 4f7ed4bd3be9..94e30fe4b8f3 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -24,6 +24,8 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
#include "rio.h"
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 30a11436e241..bef9316e95df 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -15,6 +15,7 @@
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/stat.h>
+#include <linux/sched.h> /* for capable() */
#include "rio.h"
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 3ca1011ceaac..5e382470faa2 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -23,6 +23,7 @@
#include <linux/rio_regs.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/slab.h>
#include "rio.h"
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index c99a2fe92fb0..9803c9352d78 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -2,7 +2,7 @@
# Makefile for the S/390 specific device drivers
#
-obj-y += s390mach.o sysinfo.o
+obj-y += s390mach.o sysinfo.o s390_rdev.o
obj-y += cio/ block/ char/ crypto/ net/ scsi/
drivers-y += drivers/s390/built-in.o
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index 6e7d7b06421d..6f50cc9323d9 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -1,11 +1,11 @@
-if ARCH_S390
+if S390
comment "S/390 block device drivers"
- depends on ARCH_S390
+ depends on S390
config BLK_DEV_XPRAM
tristate "XPRAM disk support"
- depends on ARCH_S390
+ depends on S390
help
Select this option if you want to use your expanded storage on S/390
or zSeries as a disk. This is useful as a _fast_ swap device if you
@@ -49,7 +49,7 @@ config DASD_FBA
config DASD_DIAG
tristate "Support for DIAG access to Disks"
- depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL)
+ depends on DASD && ( 64BIT = '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 7008d32433bf..ef4c687e7c01 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.167 $
+ * $Revision: 1.172 $
*/
#include <linux/config.h>
@@ -18,6 +18,7 @@
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
#include <asm/ccwdev.h>
#include <asm/ebcdic.h>
@@ -604,7 +605,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize,
void
dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
{
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
struct ccw1 *ccw;
/* Clear any idals used for the request. */
@@ -1035,7 +1036,7 @@ dasd_end_request(struct request *req, int uptodate)
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
add_disk_randomness(req->rq_disk);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
/*
@@ -1224,6 +1225,12 @@ __dasd_start_head(struct dasd_device * device)
if (list_empty(&device->ccw_queue))
return;
cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
+ /* check FAILFAST */
+ if (device->stopped & ~DASD_STOPPED_PENDING &&
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) {
+ cqr->status = DASD_CQR_FAILED;
+ dasd_schedule_bh(device);
+ }
if ((cqr->status == DASD_CQR_QUEUED) &&
(!device->stopped)) {
/* try to start the first I/O that can be started */
@@ -1323,7 +1330,7 @@ void
dasd_schedule_bh(struct dasd_device * device)
{
/* Protect against rescheduling. */
- if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled))
+ if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0)
return;
dasd_get_device(device);
tasklet_hi_schedule(&device->tasklet);
@@ -1628,7 +1635,7 @@ dasd_setup_queue(struct dasd_device * device)
blk_queue_max_hw_segments(device->request_queue, -1L);
blk_queue_max_segment_size(device->request_queue, -1L);
blk_queue_segment_boundary(device->request_queue, -1L);
- blk_queue_ordered(device->request_queue, 1);
+ blk_queue_ordered(device->request_queue, QUEUE_ORDERED_TAG, NULL);
}
/*
@@ -1717,12 +1724,35 @@ dasd_release(struct inode *inp, struct file *filp)
return 0;
}
+/*
+ * Return disk geometry.
+ */
+static int
+dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct dasd_device *device;
+
+ device = bdev->bd_disk->private_data;
+ if (!device)
+ return -ENODEV;
+
+ if (!device->discipline ||
+ !device->discipline->fill_geometry)
+ return -EINVAL;
+
+ device->discipline->fill_geometry(device, geo);
+ geo->start = get_start_sect(bdev) >> device->s2b_shift;
+ return 0;
+}
+
struct block_device_operations
dasd_device_operations = {
.owner = THIS_MODULE,
.open = dasd_open,
.release = dasd_release,
.ioctl = dasd_ioctl,
+ .compat_ioctl = dasd_compat_ioctl,
+ .getgeo = dasd_getgeo,
};
@@ -1750,8 +1780,10 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use
*/
-/* initial attempt at a probe function. this can be simplified once
- * the other detection code is gone */
+/*
+ * Initial attempt at a probe function. this can be simplified once
+ * the other detection code is gone.
+ */
int
dasd_generic_probe (struct ccw_device *cdev,
struct dasd_discipline *discipline)
@@ -1770,8 +1802,10 @@ dasd_generic_probe (struct ccw_device *cdev,
return ret;
}
-/* this will one day be called from a global not_oper handler.
- * It is also used by driver_unregister during module unload */
+/*
+ * This will one day be called from a global not_oper handler.
+ * It is also used by driver_unregister during module unload.
+ */
void
dasd_generic_remove (struct ccw_device *cdev)
{
@@ -1798,9 +1832,11 @@ dasd_generic_remove (struct ccw_device *cdev)
dasd_delete_device(device);
}
-/* activate a device. This is called from dasd_{eckd,fba}_probe() when either
+/*
+ * Activate a device. This is called from dasd_{eckd,fba}_probe() when either
* the device is detected for the first time and is supposed to be used
- * or the user has started activation through sysfs */
+ * or the user has started activation through sysfs.
+ */
int
dasd_generic_set_online (struct ccw_device *cdev,
struct dasd_discipline *discipline)
@@ -1917,7 +1953,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
if (cqr->status == DASD_CQR_IN_IO)
cqr->status = DASD_CQR_FAILED;
device->stopped |= DASD_STOPPED_DC_EIO;
- dasd_schedule_bh(device);
} else {
list_for_each_entry(cqr, &device->ccw_queue, list)
if (cqr->status == DASD_CQR_IN_IO) {
@@ -1927,6 +1962,7 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
device->stopped |= DASD_STOPPED_DC_WAIT;
dasd_set_timer(device, 0);
}
+ dasd_schedule_bh(device);
ret = 1;
break;
case CIO_OPER:
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index ab8754e566bc..ba80fdea7ebf 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.51 $
+ * $Revision: 1.53 $
*/
#include <linux/config.h>
@@ -25,6 +25,7 @@
#include <asm/io.h>
#include <asm/s390_ext.h>
#include <asm/todclk.h>
+#include <asm/vtoc.h>
#include "dasd_int.h"
#include "dasd_diag.h"
@@ -74,7 +75,7 @@ dia250(void *iob, int cmd)
int rc;
__asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
" lghi %0,3\n"
" lgr 0,%3\n"
" diag 0,%2,0x250\n"
@@ -329,7 +330,7 @@ dasd_diag_check_device(struct dasd_device *device)
struct dasd_diag_private *private;
struct dasd_diag_characteristics *rdc_data;
struct dasd_diag_bio bio;
- struct dasd_diag_cms_label *label;
+ struct vtoc_cms_label *label;
blocknum_t end_block;
unsigned int sb, bsize;
int rc;
@@ -380,7 +381,7 @@ dasd_diag_check_device(struct dasd_device *device)
mdsk_term_io(device);
/* figure out blocksize of device */
- label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
+ label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
if (label == NULL) {
DEV_MESSAGE(KERN_WARNING, device, "%s",
"No memory to allocate initialization request");
@@ -548,6 +549,8 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
}
cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = DIAG_TIMEOUT;
cqr->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index df31484d73a7..a4f80bd735f1 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.8 $
+ * $Revision: 1.9 $
*/
#define MDSK_WRITE_REQ 0x01
@@ -44,29 +44,8 @@ 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
+
+#ifdef CONFIG_64BIT
#define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT
typedef u64 blocknum_t;
@@ -107,7 +86,7 @@ struct dasd_diag_rw_io {
struct dasd_diag_bio *bio_list;
u8 spare4[8];
} __attribute__ ((packed, aligned(8)));
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define DASD_DIAG_FLAGA_DEFAULT 0x0
typedef u32 blocknum_t;
@@ -146,4 +125,4 @@ struct dasd_diag_rw_io {
u32 interrupt_params;
u8 spare3[20];
} __attribute__ ((packed, aligned(8)));
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 811060e10c00..96eb48258580 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.71 $
+ * $Revision: 1.74 $
*/
#include <linux/config.h>
@@ -1041,7 +1041,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
/* Eckd can only do full blocks. */
return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
if (idal_is_needed (page_address(bv->bv_page),
bv->bv_len))
cidaw += bv->bv_len >> (device->s2b_shift + 9);
@@ -1136,6 +1136,8 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
cqr->lpm = private->path_data.ppm;
@@ -1252,6 +1254,7 @@ dasd_eckd_release(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1296,6 +1299,7 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
@@ -1339,6 +1343,7 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args)
cqr->cpaddr->cda = (__u32)(addr_t) cqr->data;
cqr->device = device;
clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->retries = 0;
cqr->expires = 2 * HZ;
cqr->buildclk = get_clock();
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 28cb4613b7f5..8ec75dc08e2c 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -4,7 +4,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.40 $
+ * $Revision: 1.41 $
*/
#include <linux/config.h>
@@ -271,7 +271,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
/* Fba can only do full blocks. */
return ERR_PTR(-EINVAL);
count += bv->bv_len >> (device->s2b_shift + 9);
-#if defined(CONFIG_ARCH_S390X)
+#if defined(CONFIG_64BIT)
if (idal_is_needed (page_address(bv->bv_page),
bv->bv_len))
cidaw += bv->bv_len / blksize;
@@ -352,6 +352,8 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req)
recid++;
}
}
+ if (req->flags & REQ_FAILFAST)
+ set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->device = device;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */
cqr->retries = 32;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 9fab04f3056d..e4b401500b01 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.65 $
+ * $Revision: 1.68 $
*/
#ifndef DASD_INT_H
@@ -208,6 +208,7 @@ struct dasd_ccw_req {
/* per dasd_ccw_req flags */
#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
+#define DASD_CQR_FLAGS_FAILFAST 1 /* FAILFAST */
/* Signature for error recovery functions. */
typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
@@ -526,6 +527,7 @@ void dasd_ioctl_exit(void);
int dasd_ioctl_no_register(struct module *, int, dasd_ioctl_fn_t);
int dasd_ioctl_no_unregister(struct module *, int, dasd_ioctl_fn_t);
int dasd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+long dasd_compat_ioctl(struct file *, unsigned int, unsigned long);
/* externals in dasd_proc.c */
int dasd_proc_init(void);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 789595b3fa09..9396fcacb8f8 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.47 $
+ * $Revision: 1.50 $
*
* i/o controls for the dasd driver.
*/
@@ -118,6 +118,18 @@ dasd_ioctl(struct inode *inp, struct file *filp,
return -EINVAL;
}
+long
+dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int rval;
+
+ lock_kernel();
+ rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return (rval == -EINVAL) ? -ENOIOCTLCMD : rval;
+}
+
static int
dasd_ioctl_api_version(struct block_device *bdev, int no, long args)
{
@@ -352,6 +364,9 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args)
if (device == NULL)
return -ENODEV;
+ if (dasd_profile_level == DASD_PROFILE_OFF)
+ return -EIO;
+
if (copy_to_user((long __user *) args, (long *) &device->profile,
sizeof (struct dasd_profile_info_t)))
return -EFAULT;
@@ -483,33 +498,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args)
}
/*
- * Return disk geometry.
- */
-static int
-dasd_ioctl_getgeo(struct block_device *bdev, int no, long args)
-{
- struct hd_geometry geo = { 0, };
- struct dasd_device *device;
-
- device = bdev->bd_disk->private_data;
- if (device == NULL)
- return -ENODEV;
-
- if (device == NULL || device->discipline == NULL ||
- device->discipline->fill_geometry == NULL)
- return -EINVAL;
-
- geo = (struct hd_geometry) {};
- device->discipline->fill_geometry(device, &geo);
- geo.start = get_start_sect(bdev) >> device->s2b_shift;
- if (copy_to_user((struct hd_geometry __user *) args, &geo,
- sizeof (struct hd_geometry)))
- return -EFAULT;
-
- return 0;
-}
-
-/*
* List of static ioctls.
*/
static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
@@ -525,7 +513,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
{ BIODASDPRRST, dasd_ioctl_reset_profile },
{ BLKROSET, dasd_ioctl_set_ro },
{ DASDAPIVER, dasd_ioctl_api_version },
- { HDIO_GETGEO, dasd_ioctl_getgeo },
{ -1, NULL }
};
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 4fde41188996..2e727f49ad19 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -15,7 +15,7 @@
#include <asm/io.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
-#include <asm/ccwdev.h> // for s390_root_dev_(un)register()
+#include <asm/s390_rdev.h>
//#define DCSSBLK_DEBUG /* Debug messages on/off */
#define DCSSBLK_NAME "dcssblk"
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index d428c909b8a0..54ecd548c318 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -160,7 +160,7 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,1b\n"
@@ -208,7 +208,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 0b,1b\n"
@@ -328,31 +328,27 @@ fail:
return 0;
}
-static int xpram_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
- struct hd_geometry __user *geo;
unsigned long size;
- if (cmd != HDIO_GETGEO)
- return -EINVAL;
+
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 64 (32k): tell we have 16 sectors, 4 heads,
* whatever cylinders. Tell also that data starts at sector. 4.
*/
- geo = (struct hd_geometry __user *) arg;
size = (xpram_pages * 8) & ~0x3f;
- put_user(size >> 6, &geo->cylinders);
- put_user(4, &geo->heads);
- put_user(16, &geo->sectors);
- put_user(4, &geo->start);
+ geo->cylinders = size >> 6;
+ geo->heads = 4;
+ geo->sectors = 16;
+ geo->start = 4;
return 0;
}
static struct block_device_operations xpram_devops =
{
.owner = THIS_MODULE,
- .ioctl = xpram_ioctl,
+ .getgeo = xpram_getgeo,
};
/*
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 75419cf9d353..1f060914cfa4 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/vt_kern.h>
#include <linux/init.h>
#include <linux/console.h>
@@ -432,8 +433,6 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
if (count > slen)
count = slen;
} else
- if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
- count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
EBCASC(raw->inbuf, count);
cchar = ctrlchar_handle(raw->inbuf, count, tty);
switch (cchar & CTRLCHAR_MASK) {
@@ -441,28 +440,20 @@ raw3215_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
break;
case CTRLCHAR_CTRL:
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = cchar;
+ tty_insert_flip_char(tty, cchar, TTY_NORMAL);
tty_flip_buffer_push(raw->tty);
break;
case CTRLCHAR_NONE:
- memcpy(tty->flip.char_buf_ptr,
- raw->inbuf, count);
if (count < 2 ||
- (strncmp(raw->inbuf+count-2, "^n", 2) &&
- strncmp(raw->inbuf+count-2, "\252n", 2)) ) {
- /* don't add the auto \n */
- tty->flip.char_buf_ptr[count] = '\n';
- memset(tty->flip.flag_buf_ptr,
- TTY_NORMAL, count + 1);
+ (strncmp(raw->inbuf+count-2, "\252n", 2) &&
+ strncmp(raw->inbuf+count-2, "^n", 2)) ) {
+ /* add the auto \n */
+ raw->inbuf[count] = '\n';
count++;
} else
- count-=2;
- tty->flip.char_buf_ptr += count;
- tty->flip.flag_buf_ptr += count;
- tty->flip.count += count;
+ count -= 2;
+ tty_insert_flip_string(tty, raw->inbuf, count);
tty_flip_buffer_push(raw->tty);
break;
}
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index 735a7fcdeff5..5f6fa4c67843 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -319,9 +319,8 @@ fs3270_write(struct file *filp, const char *data, size_t count, loff_t *off)
/*
* process ioctl commands for the tube driver
*/
-static int
-fs3270_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
+static long
+fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct fs3270 *fp;
struct raw3270_iocb iocb;
@@ -331,6 +330,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
if (!fp)
return -ENODEV;
rc = 0;
+ lock_kernel();
switch (cmd) {
case TUBICMD:
fp->read_command = arg;
@@ -356,6 +356,7 @@ fs3270_ioctl(struct inode *inode, struct file *filp,
rc = -EFAULT;
break;
}
+ unlock_kernel();
return rc;
}
@@ -491,12 +492,13 @@ fs3270_close(struct inode *inode, struct file *filp)
}
static struct file_operations fs3270_fops = {
- .owner = THIS_MODULE, /* owner */
- .read = fs3270_read, /* read */
- .write = fs3270_write, /* write */
- .ioctl = fs3270_ioctl, /* ioctl */
- .open = fs3270_open, /* open */
- .release = fs3270_close, /* release */
+ .owner = THIS_MODULE, /* owner */
+ .read = fs3270_read, /* read */
+ .write = fs3270_write, /* write */
+ .unlocked_ioctl = fs3270_ioctl, /* ioctl */
+ .compat_ioctl = fs3270_ioctl, /* ioctl */
+ .open = fs3270_open, /* open */
+ .release = fs3270_close, /* release */
};
/*
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c
index 5a6cef2dfa13..80f7f31310e6 100644
--- a/drivers/s390/char/sclp_cpi.c
+++ b/drivers/s390/char/sclp_cpi.c
@@ -204,7 +204,7 @@ cpi_module_init(void)
printk(KERN_WARNING "cpi: no control program identification "
"support\n");
sclp_unregister(&sclp_cpi_event);
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
}
req = cpi_prepare_req();
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 83f75774df60..56fa69168898 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -32,7 +32,7 @@ do_load_quiesce_psw(void * __unused)
psw_t quiesce_psw;
int cpu;
- if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1)
signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter stopped state */
for_each_online_cpu(cpu) {
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index a20d7c89341d..6cbf067f1a8f 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -13,6 +13,7 @@
#include <linux/kmod.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/slab.h>
@@ -496,25 +497,19 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
case CTRLCHAR_SYSRQ:
break;
case CTRLCHAR_CTRL:
- sclp_tty->flip.count++;
- *sclp_tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *sclp_tty->flip.char_buf_ptr++ = cchar;
+ tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
tty_flip_buffer_push(sclp_tty);
break;
case CTRLCHAR_NONE:
/* send (normal) input to line discipline */
- memcpy(sclp_tty->flip.char_buf_ptr, buf, count);
if (count < 2 ||
- (strncmp ((const char *) buf + count - 2, "^n", 2) &&
- strncmp ((const char *) buf + count - 2, "\0252n", 2))) {
- sclp_tty->flip.char_buf_ptr[count] = '\n';
- count++;
+ (strncmp((const char *) buf + count - 2, "^n", 2) &&
+ strncmp((const char *) buf + count - 2, "\252n", 2))) {
+ /* add the auto \n */
+ tty_insert_flip_string(sclp_tty, buf, count);
+ tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
} else
- count -= 2;
- memset(sclp_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
- sclp_tty->flip.char_buf_ptr += count;
- sclp_tty->flip.flag_buf_ptr += count;
- sclp_tty->flip.count += count;
+ tty_insert_flip_string(sclp_tty, buf, count - 2);
tty_flip_buffer_push(sclp_tty);
break;
}
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 06bd85824d7b..9e02625c82cf 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/mm.h>
@@ -482,16 +483,7 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
/* Send input to line discipline */
buffer++;
count--;
- /* Prevent buffer overrun by discarding input. Note that
- * because buffer_push works asynchronously, we cannot wait
- * for the buffer to be emptied. */
- if (count + sclp_vt220_tty->flip.count > TTY_FLIPBUF_SIZE)
- count = TTY_FLIPBUF_SIZE - sclp_vt220_tty->flip.count;
- memcpy(sclp_vt220_tty->flip.char_buf_ptr, buffer, count);
- memset(sclp_vt220_tty->flip.flag_buf_ptr, TTY_NORMAL, count);
- sclp_vt220_tty->flip.char_buf_ptr += count;
- sclp_vt220_tty->flip.flag_buf_ptr += count;
- sclp_vt220_tty->flip.count += count;
+ tty_insert_flip_string(sclp_vt220_tty, buffer, count);
tty_flip_buffer_push(sclp_vt220_tty);
break;
}
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c
index 1efc9f21229e..5ced2725d6c7 100644
--- a/drivers/s390/char/tape_block.c
+++ b/drivers/s390/char/tape_block.c
@@ -65,7 +65,7 @@ static void
tapeblock_trigger_requeue(struct tape_device *device)
{
/* Protect against rescheduling. */
- if (atomic_compare_and_swap(0, 1, &device->blk_data.requeue_scheduled))
+ if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0)
return;
schedule_work(&device->blk_data.requeue_task);
}
@@ -78,7 +78,7 @@ tapeblock_end_request(struct request *req, int uptodate)
{
if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
BUG();
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
}
static void
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 86262a13f7c6..5ce7ca38ace0 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -37,6 +37,8 @@ static int tapechar_open(struct inode *,struct file *);
static int tapechar_release(struct inode *,struct file *);
static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
+static long tapechar_compat_ioctl(struct file *, unsigned int,
+ unsigned long);
static struct file_operations tape_fops =
{
@@ -44,6 +46,7 @@ static struct file_operations tape_fops =
.read = tapechar_read,
.write = tapechar_write,
.ioctl = tapechar_ioctl,
+ .compat_ioctl = tapechar_compat_ioctl,
.open = tapechar_open,
.release = tapechar_release,
};
@@ -463,6 +466,23 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
return device->discipline->ioctl_fn(device, no, data);
}
+static long
+tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+ struct tape_device *device = filp->private_data;
+ int rval = -ENOIOCTLCMD;
+
+ if (device->discipline->ioctl_fn) {
+ lock_kernel();
+ rval = device->discipline->ioctl_fn(device, no, data);
+ unlock_kernel();
+ if (rval == -EINVAL)
+ rval = -ENOIOCTLCMD;
+ }
+
+ return rval;
+}
+
/*
* Initialize character device frontend.
*/
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c
index 5473c23fcb52..5acc0ace3d7d 100644
--- a/drivers/s390/char/vmwatchdog.c
+++ b/drivers/s390/char/vmwatchdog.c
@@ -66,7 +66,7 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout,
__cmdl = len;
err = 0;
asm volatile (
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
"diag %2,%4,0x288\n"
"1: \n"
".section .fixup,\"ax\"\n"
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index 83e6a060668e..cd2cc28e16a7 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -2,12 +2,12 @@
* drivers/s390/cio/airq.c
* S/390 common I/O routines -- support for adapter interruptions
*
- * $Revision: 1.12 $
+ * $Revision: 1.15 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index a1c52a682191..72f27c151c09 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.35 $
+ * $Revision: 1.42 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
@@ -15,6 +15,7 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/ctype.h>
#include <linux/device.h>
@@ -34,10 +35,10 @@
* These can be single devices or ranges of devices
*/
-/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
+/* 65536 bits for each set to indicate if a devno is blacklisted or not */
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \
(8*sizeof(long)))
-static unsigned long bl_dev[__BL_DEV_WORDS];
+static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS];
typedef enum {add, free} range_action;
/*
@@ -45,21 +46,23 @@ typedef enum {add, free} range_action;
* (Un-)blacklist the devices from-to
*/
static inline void
-blacklist_range (range_action action, unsigned int from, unsigned int to)
+blacklist_range (range_action action, unsigned int from, unsigned int to,
+ unsigned int ssid)
{
if (!to)
to = from;
- if (from > to || to > __MAX_SUBCHANNELS) {
+ if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) {
printk (KERN_WARNING "Invalid blacklist range "
- "0x%04x to 0x%04x, skipping\n", from, to);
+ "0.%x.%04x to 0.%x.%04x, skipping\n",
+ ssid, from, ssid, to);
return;
}
for (; from <= to; from++) {
if (action == add)
- set_bit (from, bl_dev);
+ set_bit (from, bl_dev[ssid]);
else
- clear_bit (from, bl_dev);
+ clear_bit (from, bl_dev[ssid]);
}
}
@@ -69,7 +72,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to)
* Shamelessly grabbed from dasd_devmap.c.
*/
static inline int
-blacklist_busid(char **str, int *id0, int *id1, int *devno)
+blacklist_busid(char **str, int *id0, int *ssid, int *devno)
{
int val, old_style;
char *sav;
@@ -86,7 +89,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
goto confused;
val = simple_strtoul(*str, str, 16);
if (old_style || (*str)[0] != '.') {
- *id0 = *id1 = 0;
+ *id0 = *ssid = 0;
if (val < 0 || val > 0xffff)
goto confused;
*devno = val;
@@ -105,7 +108,7 @@ blacklist_busid(char **str, int *id0, int *id1, int *devno)
val = simple_strtoul(*str, str, 16);
if (val < 0 || val > 0xff || (*str)++[0] != '.')
goto confused;
- *id1 = val;
+ *ssid = val;
if (!isxdigit((*str)[0])) /* We require at least one hex digit */
goto confused;
val = simple_strtoul(*str, str, 16);
@@ -125,7 +128,7 @@ confused:
static inline int
blacklist_parse_parameters (char *str, range_action action)
{
- unsigned int from, to, from_id0, to_id0, from_id1, to_id1;
+ unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
while (*str != 0 && *str != '\n') {
range_action ra = action;
@@ -142,23 +145,25 @@ blacklist_parse_parameters (char *str, range_action action)
*/
if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 ||
strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) {
- from = 0;
- to = __MAX_SUBCHANNELS;
+ int j;
+
str += 3;
+ for (j=0; j <= __MAX_SSID; j++)
+ blacklist_range(ra, 0, __MAX_SUBCHANNEL, j);
} else {
int rc;
rc = blacklist_busid(&str, &from_id0,
- &from_id1, &from);
+ &from_ssid, &from);
if (rc)
continue;
to = from;
to_id0 = from_id0;
- to_id1 = from_id1;
+ to_ssid = from_ssid;
if (*str == '-') {
str++;
rc = blacklist_busid(&str, &to_id0,
- &to_id1, &to);
+ &to_ssid, &to);
if (rc)
continue;
}
@@ -168,18 +173,19 @@ blacklist_parse_parameters (char *str, range_action action)
strsep(&str, ",\n"));
continue;
}
- if ((from_id0 != to_id0) || (from_id1 != to_id1)) {
+ if ((from_id0 != to_id0) ||
+ (from_ssid != to_ssid)) {
printk(KERN_WARNING "invalid cio_ignore range "
"%x.%x.%04x-%x.%x.%04x\n",
- from_id0, from_id1, from,
- to_id0, to_id1, to);
+ from_id0, from_ssid, from,
+ to_id0, to_ssid, to);
continue;
}
+ pr_debug("blacklist_setup: adding range "
+ "from %x.%x.%04x to %x.%x.%04x\n",
+ from_id0, from_ssid, from, to_id0, to_ssid, to);
+ blacklist_range (ra, from, to, to_ssid);
}
- /* FIXME: ignoring id0 and id1 here. */
- pr_debug("blacklist_setup: adding range "
- "from 0.0.%04x to 0.0.%04x\n", from, to);
- blacklist_range (ra, from, to);
}
return 1;
}
@@ -213,12 +219,33 @@ __setup ("cio_ignore=", blacklist_setup);
* Used by validate_subchannel()
*/
int
-is_blacklisted (int devno)
+is_blacklisted (int ssid, int devno)
{
- return test_bit (devno, bl_dev);
+ return test_bit (devno, bl_dev[ssid]);
}
#ifdef CONFIG_PROC_FS
+static int
+__s390_redo_validation(struct subchannel_id schid, void *data)
+{
+ int ret;
+ struct subchannel *sch;
+
+ sch = get_subchannel_by_schid(schid);
+ if (sch) {
+ /* Already known. */
+ put_device(&sch->dev);
+ return 0;
+ }
+ ret = css_probe_device(schid);
+ if (ret == -ENXIO)
+ return ret; /* We're through. */
+ if (ret == -ENOMEM)
+ /* Stop validation for now. Bad, but no need for a panic. */
+ return ret;
+ return 0;
+}
+
/*
* Function: s390_redo_validation
* Look for no longer blacklisted devices
@@ -226,29 +253,9 @@ is_blacklisted (int devno)
static inline void
s390_redo_validation (void)
{
- unsigned int irq;
-
CIO_TRACE_EVENT (0, "redoval");
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int ret;
- struct subchannel *sch;
-
- sch = get_subchannel_by_schid(irq);
- if (sch) {
- /* Already known. */
- put_device(&sch->dev);
- continue;
- }
- ret = css_probe_device(irq);
- if (ret == -ENXIO)
- break; /* We're through. */
- if (ret == -ENOMEM)
- /*
- * Stop validation for now. Bad, but no need for a
- * panic.
- */
- break;
- }
+
+ for_each_subchannel(__s390_redo_validation, NULL);
}
/*
@@ -278,41 +285,90 @@ blacklist_parse_proc_parameters (char *buf)
s390_redo_validation ();
}
-/* FIXME: These should be real bus ids and not home-grown ones! */
-static int cio_ignore_read (char *page, char **start, off_t off,
- int count, int *eof, void *data)
+/* Iterator struct for all devices. */
+struct ccwdev_iter {
+ int devno;
+ int ssid;
+ int in_range;
+};
+
+static void *
+cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset)
{
- const unsigned int entry_size = 18; /* "0.0.ABCD-0.0.EFGH\n" */
- long devno;
- int len;
-
- len = 0;
- for (devno = off; /* abuse the page variable
- * as counter, see fs/proc/generic.c */
- devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
- if (!test_bit(devno, bl_dev))
- continue;
- len += sprintf(page + len, "0.0.%04lx", devno);
- if (test_bit(devno + 1, bl_dev)) { /* print range */
- while (++devno < __MAX_SUBCHANNELS)
- if (!test_bit(devno, bl_dev))
- break;
- len += sprintf(page + len, "-0.0.%04lx", --devno);
- }
- len += sprintf(page + len, "\n");
- }
+ struct ccwdev_iter *iter;
+
+ if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+ return NULL;
+ iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL);
+ if (!iter)
+ return ERR_PTR(-ENOMEM);
+ iter->ssid = *offset / (__MAX_SUBCHANNEL + 1);
+ iter->devno = *offset % (__MAX_SUBCHANNEL + 1);
+ return iter;
+}
+
+static void
+cio_ignore_proc_seq_stop(struct seq_file *s, void *it)
+{
+ if (!IS_ERR(it))
+ kfree(it);
+}
+
+static void *
+cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
+{
+ struct ccwdev_iter *iter;
+
+ if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+ return NULL;
+ iter = it;
+ if (iter->devno == __MAX_SUBCHANNEL) {
+ iter->devno = 0;
+ iter->ssid++;
+ if (iter->ssid > __MAX_SSID)
+ return NULL;
+ } else
+ iter->devno++;
+ (*offset)++;
+ return iter;
+}
- if (devno < __MAX_SUBCHANNELS)
- *eof = 1;
- *start = (char *) (devno - off); /* number of checked entries */
- return len;
+static int
+cio_ignore_proc_seq_show(struct seq_file *s, void *it)
+{
+ struct ccwdev_iter *iter;
+
+ iter = it;
+ if (!is_blacklisted(iter->ssid, iter->devno))
+ /* Not blacklisted, nothing to output. */
+ return 0;
+ if (!iter->in_range) {
+ /* First device in range. */
+ if ((iter->devno == __MAX_SUBCHANNEL) ||
+ !is_blacklisted(iter->ssid, iter->devno + 1))
+ /* Singular device. */
+ return seq_printf(s, "0.%x.%04x\n",
+ iter->ssid, iter->devno);
+ iter->in_range = 1;
+ return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno);
+ }
+ if ((iter->devno == __MAX_SUBCHANNEL) ||
+ !is_blacklisted(iter->ssid, iter->devno + 1)) {
+ /* Last device in range. */
+ iter->in_range = 0;
+ return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno);
+ }
+ return 0;
}
-static int cio_ignore_write(struct file *file, const char __user *user_buf,
- unsigned long user_len, void *data)
+static ssize_t
+cio_ignore_write(struct file *file, const char __user *user_buf,
+ size_t user_len, loff_t *offset)
{
char *buf;
+ if (*offset)
+ return -EINVAL;
if (user_len > 65536)
user_len = 65536;
buf = vmalloc (user_len + 1); /* maybe better use the stack? */
@@ -330,6 +386,27 @@ static int cio_ignore_write(struct file *file, const char __user *user_buf,
return user_len;
}
+static struct seq_operations cio_ignore_proc_seq_ops = {
+ .start = cio_ignore_proc_seq_start,
+ .stop = cio_ignore_proc_seq_stop,
+ .next = cio_ignore_proc_seq_next,
+ .show = cio_ignore_proc_seq_show,
+};
+
+static int
+cio_ignore_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &cio_ignore_proc_seq_ops);
+}
+
+static struct file_operations cio_ignore_proc_fops = {
+ .open = cio_ignore_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+ .write = cio_ignore_write,
+};
+
static int
cio_ignore_proc_init (void)
{
@@ -340,8 +417,7 @@ cio_ignore_proc_init (void)
if (!entry)
return 0;
- entry->read_proc = cio_ignore_read;
- entry->write_proc = cio_ignore_write;
+ entry->proc_fops = &cio_ignore_proc_fops;
return 1;
}
diff --git a/drivers/s390/cio/blacklist.h b/drivers/s390/cio/blacklist.h
index fb42cafbe57c..95e25c1df922 100644
--- a/drivers/s390/cio/blacklist.h
+++ b/drivers/s390/cio/blacklist.h
@@ -1,6 +1,6 @@
#ifndef S390_BLACKLIST_H
#define S390_BLACKLIST_H
-extern int is_blacklisted (int devno);
+extern int is_blacklisted (int ssid, int devno);
#endif
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index e7bd7f37f080..6c077ad71edc 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.32 $
+ * $Revision: 1.35 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/errno.h>
@@ -45,18 +45,14 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
return 0;
}
static int
-ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
+ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
int buffer_size)
{
/* TODO */
return 0;
}
-static struct bus_type ccwgroup_bus_type = {
- .name = "ccwgroup",
- .match = ccwgroup_bus_match,
- .hotplug = ccwgroup_hotplug,
-};
+static struct bus_type ccwgroup_bus_type;
static inline void
__ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
@@ -263,7 +259,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
struct ccwgroup_driver *gdrv;
int ret;
- if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
if (gdev->state == CCWGROUP_ONLINE) {
ret = 0;
@@ -289,7 +285,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
struct ccwgroup_driver *gdrv;
int ret;
- if (atomic_compare_and_swap(0, 1, &gdev->onoff))
+ if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0)
return -EAGAIN;
if (gdev->state == CCWGROUP_OFFLINE) {
ret = 0;
@@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev)
return 0;
}
+static struct bus_type ccwgroup_bus_type = {
+ .name = "ccwgroup",
+ .match = ccwgroup_bus_match,
+ .uevent = ccwgroup_uevent,
+ .probe = ccwgroup_probe,
+ .remove = ccwgroup_remove,
+};
+
int
ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
{
@@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
cdriver->driver = (struct device_driver) {
.bus = &ccwgroup_bus_type,
.name = cdriver->name,
- .probe = ccwgroup_probe,
- .remove = ccwgroup_remove,
};
return driver_register(&cdriver->driver);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index fa3c23b80e3a..2cbb724791a8 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/chsc.c
* S/390 common I/O routines -- channel subsystem call
- * $Revision: 1.120 $
+ * $Revision: 1.128 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
*/
@@ -24,8 +24,6 @@
#include "ioasm.h"
#include "chsc.h"
-static struct channel_path *chps[NR_CHPIDS];
-
static void *sei_page;
static int new_channel_path(int chpid);
@@ -33,13 +31,13 @@ static int new_channel_path(int chpid);
static inline void
set_chp_logically_online(int chp, int onoff)
{
- chps[chp]->state = onoff;
+ css[0]->chps[chp]->state = onoff;
}
static int
get_chp_status(int chp)
{
- return (chps[chp] ? chps[chp]->state : -ENODEV);
+ return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV);
}
void
@@ -77,7 +75,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
struct {
struct chsc_header request;
- u16 reserved1;
+ u16 reserved1a:10;
+ u16 ssid:2;
+ u16 reserved1b:4;
u16 f_sch; /* first subchannel */
u16 reserved2;
u16 l_sch; /* last subchannel */
@@ -104,8 +104,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
.code = 0x0004,
};
- ssd_area->f_sch = sch->irq;
- ssd_area->l_sch = sch->irq;
+ ssd_area->ssid = sch->schid.ssid;
+ ssd_area->f_sch = sch->schid.sch_no;
+ ssd_area->l_sch = sch->schid.sch_no;
ccode = chsc(ssd_area);
if (ccode > 0) {
@@ -147,7 +148,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
*/
if (ssd_area->st > 3) { /* uhm, that looks strange... */
CIO_CRW_EVENT(0, "Strange subchannel type %d"
- " for sch %04x\n", ssd_area->st, sch->irq);
+ " for sch 0.%x.%04x\n", ssd_area->st,
+ sch->schid.ssid, sch->schid.sch_no);
/*
* There may have been a new subchannel type defined in the
* time since this code was written; since we don't know which
@@ -156,8 +158,9 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
return 0;
} else {
const char *type[4] = {"I/O", "chsc", "message", "ADM"};
- CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n",
- sch->irq, type[ssd_area->st]);
+ CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n",
+ sch->schid.ssid, sch->schid.sch_no,
+ type[ssd_area->st]);
sch->ssd_info.valid = 1;
sch->ssd_info.type = ssd_area->st;
@@ -218,13 +221,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
int j;
int mask;
struct subchannel *sch;
- __u8 *chpid;
+ struct channel_path *chpid;
struct schib schib;
sch = to_subchannel(dev);
chpid = data;
for (j = 0; j < 8; j++)
- if (sch->schib.pmcw.chpid[j] == *chpid)
+ if (sch->schib.pmcw.chpid[j] == chpid->id)
break;
if (j >= 8)
return 0;
@@ -232,7 +235,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
mask = 0x80 >> j;
spin_lock(&sch->lock);
- stsch(sch->irq, &schib);
+ stsch(sch->schid, &schib);
if (!schib.pmcw.dnv)
goto out_unreg;
memcpy(&sch->schib, &schib, sizeof(struct schib));
@@ -284,7 +287,7 @@ out_unlock:
out_unreg:
spin_unlock(&sch->lock);
sch->lpm = 0;
- if (css_enqueue_subchannel_slow(sch->irq)) {
+ if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -295,23 +298,30 @@ static inline void
s390_set_chpid_offline( __u8 chpid)
{
char dbf_txt[15];
+ struct device *dev;
sprintf(dbf_txt, "chpr%x", chpid);
CIO_TRACE_EVENT(2, dbf_txt);
if (get_chp_status(chpid) <= 0)
return;
-
- bus_for_each_dev(&css_bus_type, NULL, &chpid,
+ dev = get_device(&css[0]->chps[chpid]->dev);
+ bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev),
s390_subchannel_remove_chpid);
if (need_rescan || css_slow_subchannels_exist())
queue_work(slow_path_wq, &slow_path_work);
+ put_device(dev);
}
+struct res_acc_data {
+ struct channel_path *chp;
+ u32 fla_mask;
+ u16 fla;
+};
+
static int
-s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
- struct subchannel *sch)
+s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch)
{
int found;
int chp;
@@ -323,8 +333,9 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
* check if chpid is in information updated by ssd
*/
if (sch->ssd_info.valid &&
- sch->ssd_info.chpid[chp] == chpid &&
- (sch->ssd_info.fla[chp] & fla_mask) == fla) {
+ sch->ssd_info.chpid[chp] == res_data->chp->id &&
+ (sch->ssd_info.fla[chp] & res_data->fla_mask)
+ == res_data->fla) {
found = 1;
break;
}
@@ -337,24 +348,87 @@ s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask,
* new path information and eventually check for logically
* offline chpids.
*/
- ccode = stsch(sch->irq, &sch->schib);
+ ccode = stsch(sch->schid, &sch->schib);
if (ccode > 0)
return 0;
return 0x80 >> chp;
}
+static inline int
+s390_process_res_acc_new_sch(struct subchannel_id schid)
+{
+ struct schib schib;
+ int ret;
+ /*
+ * We don't know the device yet, but since a path
+ * may be available now to the device we'll have
+ * to do recognition again.
+ * Since we don't have any idea about which chpid
+ * that beast may be on we'll have to do a stsch
+ * on all devices, grr...
+ */
+ if (stsch_err(schid, &schib))
+ /* We're through */
+ return need_rescan ? -EAGAIN : -ENXIO;
+
+ /* Put it on the slow path. */
+ ret = css_enqueue_subchannel_slow(schid);
+ if (ret) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
static int
-s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
+__s390_process_res_acc(struct subchannel_id schid, void *data)
{
+ int chp_mask, old_lpm;
+ struct res_acc_data *res_data;
struct subchannel *sch;
- int irq, rc;
+
+ res_data = (struct res_acc_data *)data;
+ sch = get_subchannel_by_schid(schid);
+ if (!sch)
+ /* Check if a subchannel is newly available. */
+ return s390_process_res_acc_new_sch(schid);
+
+ spin_lock_irq(&sch->lock);
+
+ chp_mask = s390_process_res_acc_sch(res_data, sch);
+
+ if (chp_mask == 0) {
+ spin_unlock_irq(&sch->lock);
+ return 0;
+ }
+ old_lpm = sch->lpm;
+ sch->lpm = ((sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom)
+ | chp_mask) & sch->opm;
+ if (!old_lpm && sch->lpm)
+ device_trigger_reprobe(sch);
+ else if (sch->driver && sch->driver->verify)
+ sch->driver->verify(&sch->dev);
+
+ spin_unlock_irq(&sch->lock);
+ put_device(&sch->dev);
+ return (res_data->fla_mask == 0xffff) ? -ENODEV : 0;
+}
+
+
+static int
+s390_process_res_acc (struct res_acc_data *res_data)
+{
+ int rc;
char dbf_txt[15];
- sprintf(dbf_txt, "accpr%x", chpid);
+ sprintf(dbf_txt, "accpr%x", res_data->chp->id);
CIO_TRACE_EVENT( 2, dbf_txt);
- if (fla != 0) {
- sprintf(dbf_txt, "fla%x", fla);
+ if (res_data->fla != 0) {
+ sprintf(dbf_txt, "fla%x", res_data->fla);
CIO_TRACE_EVENT( 2, dbf_txt);
}
@@ -365,70 +439,11 @@ s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask)
* The more information we have (info), the less scanning
* will we have to do.
*/
-
- if (!get_chp_status(chpid))
- return 0; /* no need to do the rest */
-
- rc = 0;
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int chp_mask, old_lpm;
-
- sch = get_subchannel_by_schid(irq);
- if (!sch) {
- struct schib schib;
- int ret;
- /*
- * We don't know the device yet, but since a path
- * may be available now to the device we'll have
- * to do recognition again.
- * Since we don't have any idea about which chpid
- * that beast may be on we'll have to do a stsch
- * on all devices, grr...
- */
- if (stsch(irq, &schib)) {
- /* We're through */
- if (need_rescan)
- rc = -EAGAIN;
- break;
- }
- if (need_rescan) {
- rc = -EAGAIN;
- continue;
- }
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- rc = -EAGAIN;
- continue;
- }
-
- spin_lock_irq(&sch->lock);
-
- chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch);
-
- if (chp_mask == 0) {
-
- spin_unlock_irq(&sch->lock);
- continue;
- }
- old_lpm = sch->lpm;
- sch->lpm = ((sch->schib.pmcw.pim &
- sch->schib.pmcw.pam &
- sch->schib.pmcw.pom)
- | chp_mask) & sch->opm;
- if (!old_lpm && sch->lpm)
- device_trigger_reprobe(sch);
- else if (sch->driver && sch->driver->verify)
- sch->driver->verify(&sch->dev);
-
- spin_unlock_irq(&sch->lock);
- put_device(&sch->dev);
- if (fla_mask == 0xffff)
- break;
- }
+ rc = for_each_subchannel(__s390_process_res_acc, res_data);
+ if (css_slow_subchannels_exist())
+ rc = -EAGAIN;
+ else if (rc != -EAGAIN)
+ rc = 0;
return rc;
}
@@ -466,6 +481,7 @@ int
chsc_process_crw(void)
{
int chpid, ret;
+ struct res_acc_data res_data;
struct {
struct chsc_header request;
u32 reserved1;
@@ -499,8 +515,9 @@ chsc_process_crw(void)
ret = 0;
do {
int ccode, status;
+ struct device *dev;
memset(sei_area, 0, sizeof(*sei_area));
-
+ memset(&res_data, 0, sizeof(struct res_acc_data));
sei_area->request = (struct chsc_header) {
.length = 0x0010,
.code = 0x000e,
@@ -573,26 +590,25 @@ chsc_process_crw(void)
if (status < 0)
new_channel_path(sei_area->rsid);
else if (!status)
- return 0;
- if ((sei_area->vf & 0x80) == 0) {
- pr_debug("chpid: %x\n", sei_area->rsid);
- ret = s390_process_res_acc(sei_area->rsid,
- 0, 0);
- } else if ((sei_area->vf & 0xc0) == 0x80) {
- pr_debug("chpid: %x link addr: %x\n",
- sei_area->rsid, sei_area->fla);
- ret = s390_process_res_acc(sei_area->rsid,
- sei_area->fla,
- 0xff00);
- } else if ((sei_area->vf & 0xc0) == 0xc0) {
- pr_debug("chpid: %x full link addr: %x\n",
- sei_area->rsid, sei_area->fla);
- ret = s390_process_res_acc(sei_area->rsid,
- sei_area->fla,
- 0xffff);
+ break;
+ dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
+ res_data.chp = to_channelpath(dev);
+ pr_debug("chpid: %x", sei_area->rsid);
+ if ((sei_area->vf & 0xc0) != 0) {
+ res_data.fla = sei_area->fla;
+ if ((sei_area->vf & 0xc0) == 0xc0) {
+ pr_debug(" full link addr: %x",
+ sei_area->fla);
+ res_data.fla_mask = 0xffff;
+ } else {
+ pr_debug(" link addr: %x",
+ sei_area->fla);
+ res_data.fla_mask = 0xff00;
+ }
}
- pr_debug("\n");
-
+ ret = s390_process_res_acc(&res_data);
+ pr_debug("\n\n");
+ put_device(dev);
break;
default: /* other stuff */
@@ -604,12 +620,72 @@ chsc_process_crw(void)
return ret;
}
+static inline int
+__chp_add_new_sch(struct subchannel_id schid)
+{
+ struct schib schib;
+ int ret;
+
+ if (stsch(schid, &schib))
+ /* We're through */
+ return need_rescan ? -EAGAIN : -ENXIO;
+
+ /* Put it on the slow path. */
+ ret = css_enqueue_subchannel_slow(schid);
+ if (ret) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+
static int
-chp_add(int chpid)
+__chp_add(struct subchannel_id schid, void *data)
{
+ int i;
+ struct channel_path *chp;
struct subchannel *sch;
- int irq, ret, rc;
+
+ chp = (struct channel_path *)data;
+ sch = get_subchannel_by_schid(schid);
+ if (!sch)
+ /* Check if the subchannel is now available. */
+ return __chp_add_new_sch(schid);
+ spin_lock(&sch->lock);
+ for (i=0; i<8; i++)
+ if (sch->schib.pmcw.chpid[i] == chp->id) {
+ if (stsch(sch->schid, &sch->schib) != 0) {
+ /* Endgame. */
+ spin_unlock(&sch->lock);
+ return -ENXIO;
+ }
+ break;
+ }
+ if (i==8) {
+ spin_unlock(&sch->lock);
+ return 0;
+ }
+ sch->lpm = ((sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom)
+ | 0x80 >> i) & sch->opm;
+
+ if (sch->driver && sch->driver->verify)
+ sch->driver->verify(&sch->dev);
+
+ spin_unlock(&sch->lock);
+ put_device(&sch->dev);
+ return 0;
+}
+
+static int
+chp_add(int chpid)
+{
+ int rc;
char dbf_txt[15];
+ struct device *dev;
if (!get_chp_status(chpid))
return 0; /* no need to do the rest */
@@ -617,59 +693,13 @@ chp_add(int chpid)
sprintf(dbf_txt, "cadd%x", chpid);
CIO_TRACE_EVENT(2, dbf_txt);
- rc = 0;
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- int i;
-
- sch = get_subchannel_by_schid(irq);
- if (!sch) {
- struct schib schib;
-
- if (stsch(irq, &schib)) {
- /* We're through */
- if (need_rescan)
- rc = -EAGAIN;
- break;
- }
- if (need_rescan) {
- rc = -EAGAIN;
- continue;
- }
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- rc = -EAGAIN;
- continue;
- }
-
- spin_lock(&sch->lock);
- for (i=0; i<8; i++)
- if (sch->schib.pmcw.chpid[i] == chpid) {
- if (stsch(sch->irq, &sch->schib) != 0) {
- /* Endgame. */
- spin_unlock(&sch->lock);
- return rc;
- }
- break;
- }
- if (i==8) {
- spin_unlock(&sch->lock);
- return rc;
- }
- sch->lpm = ((sch->schib.pmcw.pim &
- sch->schib.pmcw.pam &
- sch->schib.pmcw.pom)
- | 0x80 >> i) & sch->opm;
-
- if (sch->driver && sch->driver->verify)
- sch->driver->verify(&sch->dev);
-
- spin_unlock(&sch->lock);
- put_device(&sch->dev);
- }
+ dev = get_device(&css[0]->chps[chpid]->dev);
+ rc = for_each_subchannel(__chp_add, to_channelpath(dev));
+ if (css_slow_subchannels_exist())
+ rc = -EAGAIN;
+ if (rc != -EAGAIN)
+ rc = 0;
+ put_device(dev);
return rc;
}
@@ -702,7 +732,7 @@ __check_for_io_and_kill(struct subchannel *sch, int index)
if (!device_is_online(sch))
/* cio could be doing I/O. */
return 0;
- cc = stsch(sch->irq, &sch->schib);
+ cc = stsch(sch->schid, &sch->schib);
if (cc)
return 0;
if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) {
@@ -743,7 +773,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
* just varied off path. Then kill it.
*/
if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) {
- if (css_enqueue_subchannel_slow(sch->irq)) {
+ if (css_enqueue_subchannel_slow(sch->schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -781,6 +811,29 @@ s390_subchannel_vary_chpid_on(struct device *dev, void *data)
return 0;
}
+static int
+__s390_vary_chpid_on(struct subchannel_id schid, void *data)
+{
+ struct schib schib;
+ struct subchannel *sch;
+
+ sch = get_subchannel_by_schid(schid);
+ if (sch) {
+ put_device(&sch->dev);
+ return 0;
+ }
+ if (stsch_err(schid, &schib))
+ /* We're through */
+ return -ENXIO;
+ /* Put it on the slow path. */
+ if (css_enqueue_subchannel_slow(schid)) {
+ css_clear_subchannel_slow_list();
+ need_rescan = 1;
+ return -EAGAIN;
+ }
+ return 0;
+}
+
/*
* Function: s390_vary_chpid
* Varies the specified chpid online or offline
@@ -789,8 +842,7 @@ static int
s390_vary_chpid( __u8 chpid, int on)
{
char dbf_text[15];
- int status, irq, ret;
- struct subchannel *sch;
+ int status;
sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid);
CIO_TRACE_EVENT( 2, dbf_text);
@@ -815,30 +867,9 @@ s390_vary_chpid( __u8 chpid, int on)
bus_for_each_dev(&css_bus_type, NULL, &chpid, on ?
s390_subchannel_vary_chpid_on :
s390_subchannel_vary_chpid_off);
- if (!on)
- goto out;
- /* Scan for new devices on varied on path. */
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- struct schib schib;
-
- if (need_rescan)
- break;
- sch = get_subchannel_by_schid(irq);
- if (sch) {
- put_device(&sch->dev);
- continue;
- }
- if (stsch(irq, &schib))
- /* We're through */
- break;
- /* Put it on the slow path. */
- ret = css_enqueue_subchannel_slow(irq);
- if (ret) {
- css_clear_subchannel_slow_list();
- need_rescan = 1;
- }
- }
-out:
+ if (on)
+ /* Scan for new devices on varied on path. */
+ for_each_subchannel(__s390_vary_chpid_on, NULL);
if (need_rescan || css_slow_subchannels_exist())
queue_work(slow_path_wq, &slow_path_work);
return 0;
@@ -995,7 +1026,7 @@ new_channel_path(int chpid)
chp->id = chpid;
chp->state = 1;
chp->dev = (struct device) {
- .parent = &css_bus_device,
+ .parent = &css[0]->device,
.release = chp_release,
};
snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
@@ -1017,7 +1048,7 @@ new_channel_path(int chpid)
device_unregister(&chp->dev);
goto out_free;
} else
- chps[chpid] = chp;
+ css[0]->chps[chpid] = chp;
return ret;
out_free:
kfree(chp);
@@ -1030,7 +1061,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no)
struct channel_path *chp;
struct channel_path_desc *desc;
- chp = chps[sch->schib.pmcw.chpid[chp_no]];
+ chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]];
if (!chp)
return NULL;
desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
@@ -1051,6 +1082,54 @@ chsc_alloc_sei_area(void)
return (sei_page ? 0 : -ENOMEM);
}
+int __init
+chsc_enable_facility(int operation_code)
+{
+ int ret;
+ struct {
+ struct chsc_header request;
+ u8 reserved1:4;
+ u8 format:4;
+ u8 reserved2;
+ u16 operation_code;
+ u32 reserved3;
+ u32 reserved4;
+ u32 operation_data_area[252];
+ struct chsc_header response;
+ u32 reserved5:4;
+ u32 format2:4;
+ u32 reserved6:24;
+ } *sda_area;
+
+ sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
+ if (!sda_area)
+ return -ENOMEM;
+ sda_area->request = (struct chsc_header) {
+ .length = 0x0400,
+ .code = 0x0031,
+ };
+ sda_area->operation_code = operation_code;
+
+ ret = chsc(sda_area);
+ if (ret > 0) {
+ ret = (ret == 3) ? -ENODEV : -EBUSY;
+ goto out;
+ }
+ switch (sda_area->response.code) {
+ case 0x0003: /* invalid request block */
+ case 0x0007:
+ ret = -EINVAL;
+ break;
+ case 0x0004: /* command not provided */
+ case 0x0101: /* facility not provided */
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ out:
+ free_page((unsigned long)sda_area);
+ return ret;
+}
+
subsys_initcall(chsc_alloc_sei_area);
struct css_general_char css_general_characteristics;
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index be20da49d147..44e4b4bb1c5a 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -1,12 +1,12 @@
#ifndef S390_CHSC_H
#define S390_CHSC_H
-#define NR_CHPIDS 256
-
#define CHSC_SEI_ACC_CHPID 1
#define CHSC_SEI_ACC_LINKADDR 2
#define CHSC_SEI_ACC_FULLLINKADDR 3
+#define CHSC_SDA_OC_MSS 0x2
+
struct chsc_header {
u16 length;
u16 code;
@@ -43,7 +43,9 @@ struct css_general_char {
u32 ext_mb : 1; /* bit 48 */
u32 : 7;
u32 aif_tdd : 1; /* bit 56 */
- u32 : 10;
+ u32 : 1;
+ u32 qebsm : 1; /* bit 58 */
+ u32 : 8;
u32 aif_osa : 1; /* bit 67 */
u32 : 28;
}__attribute__((packed));
@@ -63,4 +65,9 @@ extern int chsc_determine_css_characteristics(void);
extern int css_characteristics_avail;
extern void *chsc_get_chp_desc(struct subchannel*, int);
+
+extern int chsc_enable_facility(int);
+
+#define to_channelpath(dev) container_of(dev, struct channel_path, dev)
+
#endif
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 185bc73c3ecd..6223b06d27d5 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.135 $
+ * $Revision: 1.140 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Ingo Adlung (adlung@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Arnd Bergmann (arndb@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
@@ -135,7 +135,7 @@ cio_tpi(void)
return 0;
irb = (struct irb *) __LC_IRB;
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->irq, irb) != 0)
+ if (tsch (tpi_info->schid, irb) != 0)
/* Not status pending or not operational. */
return 1;
sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
@@ -163,10 +163,11 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
else
sch->lpm = 0;
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
CIO_MSG_EVENT(0, "cio_start: 'not oper' status for "
- "subchannel %04x!\n", sch->irq);
+ "subchannel 0.%x.%04x!\n", sch->schid.ssid,
+ sch->schid.sch_no);
sprintf(dbf_text, "no%s", sch->dev.bus_id);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib));
@@ -194,7 +195,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
sch->orb.spnd = sch->options.suspend;
sch->orb.ssic = sch->options.suspend && sch->options.inter;
sch->orb.lpm = (lpm != 0) ? (lpm & sch->opm) : sch->lpm;
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
/*
* for 64 bit we always support 64 bit IDAWs with 4k page size only
*/
@@ -204,7 +205,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
sch->orb.key = key >> 4;
/* issue "Start Subchannel" */
sch->orb.cpa = (__u32) __pa (cpa);
- ccode = ssch (sch->irq, &sch->orb);
+ ccode = ssch (sch->schid, &sch->orb);
/* process condition code */
sprintf (dbf_txt, "ccode:%d", ccode);
@@ -243,7 +244,7 @@ cio_resume (struct subchannel *sch)
CIO_TRACE_EVENT (4, "resIO");
CIO_TRACE_EVENT (4, sch->dev.bus_id);
- ccode = rsch (sch->irq);
+ ccode = rsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (4, dbf_txt);
@@ -283,7 +284,7 @@ cio_halt(struct subchannel *sch)
/*
* Issue "Halt subchannel" and process condition code
*/
- ccode = hsch (sch->irq);
+ ccode = hsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -318,7 +319,7 @@ cio_clear(struct subchannel *sch)
/*
* Issue "Clear subchannel" and process condition code
*/
- ccode = csch (sch->irq);
+ ccode = csch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -351,7 +352,7 @@ cio_cancel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "cancelIO");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = xsch (sch->irq);
+ ccode = xsch (sch->schid);
sprintf (dbf_txt, "ccode:%d", ccode);
CIO_TRACE_EVENT (2, dbf_txt);
@@ -359,7 +360,7 @@ cio_cancel (struct subchannel *sch)
switch (ccode) {
case 0: /* success */
/* Update information in scsw. */
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
return 0;
case 1: /* status pending */
return -EBUSY;
@@ -381,7 +382,7 @@ cio_modify (struct subchannel *sch)
ret = 0;
for (retry = 0; retry < 5; retry++) {
- ccode = msch_err (sch->irq, &sch->schib);
+ ccode = msch_err (sch->schid, &sch->schib);
if (ccode < 0) /* -EIO if msch gets a program check. */
return ccode;
switch (ccode) {
@@ -414,7 +415,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
CIO_TRACE_EVENT (2, "ensch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = stsch (sch->irq, &sch->schib);
+ ccode = stsch (sch->schid, &sch->schib);
if (ccode)
return -ENODEV;
@@ -432,13 +433,13 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
*/
sch->schib.pmcw.csense = 0;
if (ret == 0) {
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
if (sch->schib.pmcw.ena)
break;
}
if (ret == -EBUSY) {
struct irb irb;
- if (tsch(sch->irq, &irb) != 0)
+ if (tsch(sch->schid, &irb) != 0)
break;
}
}
@@ -461,7 +462,7 @@ cio_disable_subchannel (struct subchannel *sch)
CIO_TRACE_EVENT (2, "dissch");
CIO_TRACE_EVENT (2, sch->dev.bus_id);
- ccode = stsch (sch->irq, &sch->schib);
+ ccode = stsch (sch->schid, &sch->schib);
if (ccode == 3) /* Not operational. */
return -ENODEV;
@@ -485,7 +486,7 @@ cio_disable_subchannel (struct subchannel *sch)
*/
break;
if (ret == 0) {
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
if (!sch->schib.pmcw.ena)
break;
}
@@ -508,12 +509,12 @@ cio_disable_subchannel (struct subchannel *sch)
* -ENODEV for subchannels with invalid device number or blacklisted devices
*/
int
-cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
+cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
{
char dbf_txt[15];
int ccode;
- sprintf (dbf_txt, "valsch%x", irq);
+ sprintf (dbf_txt, "valsch%x", schid.sch_no);
CIO_TRACE_EVENT (4, dbf_txt);
/* Nuke all fields. */
@@ -522,17 +523,20 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
spin_lock_init(&sch->lock);
/* Set a name for the subchannel */
- snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", irq);
+ snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid,
+ schid.sch_no);
/*
* The first subchannel that is not-operational (ccode==3)
* indicates that there aren't any more devices available.
+ * If stsch gets an exception, it means the current subchannel set
+ * is not valid.
*/
- sch->irq = irq;
- ccode = stsch (irq, &sch->schib);
+ ccode = stsch_err (schid, &sch->schib);
if (ccode)
- return -ENXIO;
+ return (ccode == 3) ? -ENXIO : ccode;
+ sch->schid = schid;
/* Copy subchannel type from path management control word. */
sch->st = sch->schib.pmcw.st;
@@ -541,9 +545,9 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
*/
if (sch->st != 0) {
CIO_DEBUG(KERN_INFO, 0,
- "Subchannel %04X reports "
+ "Subchannel 0.%x.%04x reports "
"non-I/O subchannel type %04X\n",
- sch->irq, sch->st);
+ sch->schid.ssid, sch->schid.sch_no, sch->st);
/* We stop here for non-io subchannels. */
return sch->st;
}
@@ -554,26 +558,29 @@ cio_validate_subchannel (struct subchannel *sch, unsigned int irq)
return -ENODEV;
/* Devno is valid. */
- if (is_blacklisted (sch->schib.pmcw.dev)) {
+ if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) {
/*
* This device must not be known to Linux. So we simply
* say that there is no device and return ENODEV.
*/
CIO_MSG_EVENT(0, "Blacklisted device detected "
- "at devno %04X\n", sch->schib.pmcw.dev);
+ "at devno %04X, subchannel set %x\n",
+ sch->schib.pmcw.dev, sch->schid.ssid);
return -ENODEV;
}
sch->opm = 0xff;
- chsc_validate_chpids(sch);
+ if (!cio_is_console(sch->schid))
+ chsc_validate_chpids(sch);
sch->lpm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom &
sch->opm;
CIO_DEBUG(KERN_INFO, 0,
- "Detected device %04X on subchannel %04X"
+ "Detected device %04x on subchannel 0.%x.%04X"
" - PIM = %02X, PAM = %02X, POM = %02X\n",
- sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim,
+ sch->schib.pmcw.dev, sch->schid.ssid,
+ sch->schid.sch_no, sch->schib.pmcw.pim,
sch->schib.pmcw.pam, sch->schib.pmcw.pom);
/*
@@ -632,7 +639,7 @@ do_IRQ (struct pt_regs *regs)
if (sch)
spin_lock(&sch->lock);
/* Store interrupt response block to lowcore. */
- if (tsch (tpi_info->irq, irb) == 0 && sch) {
+ if (tsch (tpi_info->schid, irb) == 0 && sch) {
/* Keep subchannel information word up to date. */
memcpy (&sch->schib.scsw, &irb->scsw,
sizeof (irb->scsw));
@@ -691,28 +698,36 @@ wait_cons_dev (void)
}
static int
-cio_console_irq(void)
+cio_test_for_console(struct subchannel_id schid, void *data)
{
- int irq;
+ if (stsch_err(schid, &console_subchannel.schib) != 0)
+ return -ENXIO;
+ if (console_subchannel.schib.pmcw.dnv &&
+ console_subchannel.schib.pmcw.dev ==
+ console_devno) {
+ console_irq = schid.sch_no;
+ return 1; /* found */
+ }
+ return 0;
+}
+
+
+static int
+cio_get_console_sch_no(void)
+{
+ struct subchannel_id schid;
+ init_subchannel_id(&schid);
if (console_irq != -1) {
/* VM provided us with the irq number of the console. */
- if (stsch(console_irq, &console_subchannel.schib) != 0 ||
+ schid.sch_no = console_irq;
+ if (stsch(schid, &console_subchannel.schib) != 0 ||
!console_subchannel.schib.pmcw.dnv)
return -1;
console_devno = console_subchannel.schib.pmcw.dev;
} else if (console_devno != -1) {
/* At least the console device number is known. */
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- if (stsch(irq, &console_subchannel.schib) != 0)
- break;
- if (console_subchannel.schib.pmcw.dnv &&
- console_subchannel.schib.pmcw.dev ==
- console_devno) {
- console_irq = irq;
- break;
- }
- }
+ for_each_subchannel(cio_test_for_console, NULL);
if (console_irq == -1)
return -1;
} else {
@@ -728,17 +743,20 @@ cio_console_irq(void)
struct subchannel *
cio_probe_console(void)
{
- int irq, ret;
+ int sch_no, ret;
+ struct subchannel_id schid;
if (xchg(&console_subchannel_in_use, 1) != 0)
return ERR_PTR(-EBUSY);
- irq = cio_console_irq();
- if (irq == -1) {
+ sch_no = cio_get_console_sch_no();
+ if (sch_no == -1) {
console_subchannel_in_use = 0;
return ERR_PTR(-ENODEV);
}
memset(&console_subchannel, 0, sizeof(struct subchannel));
- ret = cio_validate_subchannel(&console_subchannel, irq);
+ init_subchannel_id(&schid);
+ schid.sch_no = sch_no;
+ ret = cio_validate_subchannel(&console_subchannel, schid);
if (ret) {
console_subchannel_in_use = 0;
return ERR_PTR(-ENODEV);
@@ -770,11 +788,11 @@ cio_release_console(void)
/* Bah... hack to catch console special sausages. */
int
-cio_is_console(int irq)
+cio_is_console(struct subchannel_id schid)
{
if (!console_subchannel_in_use)
return 0;
- return (irq == console_subchannel.irq);
+ return schid_equal(&schid, &console_subchannel.schid);
}
struct subchannel *
@@ -787,7 +805,7 @@ cio_get_console_subchannel(void)
#endif
static inline int
-__disable_subchannel_easy(unsigned int schid, struct schib *schib)
+__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
{
int retry, cc;
@@ -805,7 +823,7 @@ __disable_subchannel_easy(unsigned int schid, struct schib *schib)
}
static inline int
-__clear_subchannel_easy(unsigned int schid)
+__clear_subchannel_easy(struct subchannel_id schid)
{
int retry;
@@ -815,8 +833,8 @@ __clear_subchannel_easy(unsigned int schid)
struct tpi_info ti;
if (tpi(&ti)) {
- tsch(ti.irq, (struct irb *)__LC_IRB);
- if (ti.irq == schid)
+ tsch(ti.schid, (struct irb *)__LC_IRB);
+ if (schid_equal(&ti.schid, &schid))
return 0;
}
udelay(100);
@@ -825,31 +843,33 @@ __clear_subchannel_easy(unsigned int schid)
}
extern void do_reipl(unsigned long devno);
+static int
+__shutdown_subchannel_easy(struct subchannel_id schid, void *data)
+{
+ struct schib schib;
+
+ if (stsch_err(schid, &schib))
+ return -ENXIO;
+ if (!schib.pmcw.ena)
+ return 0;
+ switch(__disable_subchannel_easy(schid, &schib)) {
+ case 0:
+ case -ENODEV:
+ break;
+ default: /* -EBUSY */
+ if (__clear_subchannel_easy(schid))
+ break; /* give up... */
+ stsch(schid, &schib);
+ __disable_subchannel_easy(schid, &schib);
+ }
+ return 0;
+}
-/* Clear all subchannels. */
void
clear_all_subchannels(void)
{
- unsigned int schid;
-
local_irq_disable();
- for (schid=0;schid<=highest_subchannel;schid++) {
- struct schib schib;
- if (stsch(schid, &schib))
- break; /* break out of the loop */
- if (!schib.pmcw.ena)
- continue;
- switch(__disable_subchannel_easy(schid, &schib)) {
- case 0:
- case -ENODEV:
- break;
- default: /* -EBUSY */
- if (__clear_subchannel_easy(schid))
- break; /* give up... jump out of switch */
- stsch(schid, &schib);
- __disable_subchannel_easy(schid, &schib);
- }
- }
+ for_each_subchannel(__shutdown_subchannel_easy, NULL);
}
/* Make sure all subchannels are quiet before we re-ipl an lpar. */
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index c50a9da420a9..0ca987344e07 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -1,6 +1,8 @@
#ifndef S390_CIO_H
#define S390_CIO_H
+#include "schid.h"
+
/*
* where we put the ssd info
*/
@@ -83,7 +85,7 @@ struct orb {
/* subchannel data structure used by I/O subroutines */
struct subchannel {
- unsigned int irq; /* aka. subchannel number */
+ struct subchannel_id schid;
spinlock_t lock; /* subchannel lock */
enum {
@@ -114,7 +116,7 @@ struct subchannel {
#define to_subchannel(n) container_of(n, struct subchannel, dev)
-extern int cio_validate_subchannel (struct subchannel *, unsigned int);
+extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
extern int cio_enable_subchannel (struct subchannel *, unsigned int);
extern int cio_disable_subchannel (struct subchannel *);
extern int cio_cancel (struct subchannel *);
@@ -127,14 +129,15 @@ extern int cio_cancel (struct subchannel *);
extern int cio_set_options (struct subchannel *, int);
extern int cio_get_options (struct subchannel *);
extern int cio_modify (struct subchannel *);
+
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
extern struct subchannel *cio_probe_console(void);
extern void cio_release_console(void);
-extern int cio_is_console(int irq);
+extern int cio_is_console(struct subchannel_id);
extern struct subchannel *cio_get_console_subchannel(void);
#else
-#define cio_is_console(irq) 0
+#define cio_is_console(schid) 0
#define cio_get_console_subchannel() NULL
#endif
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index b978f7fe8327..0b03714e696a 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $)
*
* Linux on zSeries Channel Measurement Facility support
*
@@ -178,7 +178,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
/* msch can silently fail, so do it again if necessary */
for (retry = 0; retry < 3; retry++) {
/* prepare schib */
- stsch(sch->irq, schib);
+ stsch(sch->schid, schib);
schib->pmcw.mme = mme;
schib->pmcw.mbfc = mbfc;
/* address can be either a block address or a block index */
@@ -188,7 +188,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
schib->pmcw.mbi = address;
/* try to submit it */
- switch(ret = msch_err(sch->irq, schib)) {
+ switch(ret = msch_err(sch->schid, schib)) {
case 0:
break;
case 1:
@@ -202,7 +202,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address)
ret = -EINVAL;
break;
}
- stsch(sch->irq, schib); /* restore the schib */
+ stsch(sch->schid, schib); /* restore the schib */
if (ret)
break;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 555119cacc27..516108779f60 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/css.c
* driver for channel subsystem
- * $Revision: 1.85 $
+ * $Revision: 1.96 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/module.h>
#include <linux/init.h>
@@ -21,19 +21,35 @@
#include "ioasm.h"
#include "chsc.h"
-unsigned int highest_subchannel;
int need_rescan = 0;
int css_init_done = 0;
+static int max_ssid = 0;
+
+struct channel_subsystem *css[__MAX_CSSID + 1];
-struct pgid global_pgid;
int css_characteristics_avail = 0;
-struct device css_bus_device = {
- .bus_id = "css0",
-};
+inline int
+for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
+{
+ struct subchannel_id schid;
+ int ret;
+
+ init_subchannel_id(&schid);
+ ret = -ENODEV;
+ do {
+ do {
+ ret = fn(schid, data);
+ if (ret)
+ break;
+ } while (schid.sch_no++ < __MAX_SUBCHANNEL);
+ schid.sch_no = 0;
+ } while (schid.ssid++ < max_ssid);
+ return ret;
+}
static struct subchannel *
-css_alloc_subchannel(int irq)
+css_alloc_subchannel(struct subchannel_id schid)
{
struct subchannel *sch;
int ret;
@@ -41,13 +57,11 @@ css_alloc_subchannel(int irq)
sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
if (sch == NULL)
return ERR_PTR(-ENOMEM);
- ret = cio_validate_subchannel (sch, irq);
+ ret = cio_validate_subchannel (sch, schid);
if (ret < 0) {
kfree(sch);
return ERR_PTR(ret);
}
- if (irq > highest_subchannel)
- highest_subchannel = irq;
if (sch->st != SUBCHANNEL_TYPE_IO) {
/* For now we ignore all non-io subchannels. */
@@ -87,7 +101,7 @@ css_subchannel_release(struct device *dev)
struct subchannel *sch;
sch = to_subchannel(dev);
- if (!cio_is_console(sch->irq))
+ if (!cio_is_console(sch->schid))
kfree(sch);
}
@@ -99,7 +113,7 @@ css_register_subchannel(struct subchannel *sch)
int ret;
/* Initialize the subchannel structure */
- sch->dev.parent = &css_bus_device;
+ sch->dev.parent = &css[0]->device;
sch->dev.bus = &css_bus_type;
sch->dev.release = &css_subchannel_release;
@@ -114,12 +128,12 @@ css_register_subchannel(struct subchannel *sch)
}
int
-css_probe_device(int irq)
+css_probe_device(struct subchannel_id schid)
{
int ret;
struct subchannel *sch;
- sch = css_alloc_subchannel(irq);
+ sch = css_alloc_subchannel(schid);
if (IS_ERR(sch))
return PTR_ERR(sch);
ret = css_register_subchannel(sch);
@@ -132,26 +146,26 @@ static int
check_subchannel(struct device * dev, void * data)
{
struct subchannel *sch;
- int irq = (unsigned long)data;
+ struct subchannel_id *schid = data;
sch = to_subchannel(dev);
- return (sch->irq == irq);
+ return schid_equal(&sch->schid, schid);
}
struct subchannel *
-get_subchannel_by_schid(int irq)
+get_subchannel_by_schid(struct subchannel_id schid)
{
struct device *dev;
dev = bus_find_device(&css_bus_type, NULL,
- (void *)(unsigned long)irq, check_subchannel);
+ (void *)&schid, check_subchannel);
return dev ? to_subchannel(dev) : NULL;
}
static inline int
-css_get_subchannel_status(struct subchannel *sch, int schid)
+css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid)
{
struct schib schib;
int cc;
@@ -170,13 +184,13 @@ css_get_subchannel_status(struct subchannel *sch, int schid)
}
static int
-css_evaluate_subchannel(int irq, int slow)
+css_evaluate_subchannel(struct subchannel_id schid, int slow)
{
int event, ret, disc;
struct subchannel *sch;
unsigned long flags;
- sch = get_subchannel_by_schid(irq);
+ sch = get_subchannel_by_schid(schid);
disc = sch ? device_is_disconnected(sch) : 0;
if (disc && slow) {
if (sch)
@@ -194,9 +208,10 @@ css_evaluate_subchannel(int irq, int slow)
put_device(&sch->dev);
return -EAGAIN; /* Will be done on the slow path. */
}
- event = css_get_subchannel_status(sch, irq);
- CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n",
- irq, event, sch?(disc?"disconnected":"normal"):"unknown",
+ event = css_get_subchannel_status(sch, schid);
+ CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n",
+ schid.ssid, schid.sch_no, event,
+ sch?(disc?"disconnected":"normal"):"unknown",
slow?"slow":"fast");
switch (event) {
case CIO_NO_PATH:
@@ -253,7 +268,7 @@ css_evaluate_subchannel(int irq, int slow)
sch->schib.pmcw.intparm = 0;
cio_modify(sch);
put_device(&sch->dev);
- ret = css_probe_device(irq);
+ ret = css_probe_device(schid);
} else {
/*
* We can't immediately deregister the disconnected
@@ -272,7 +287,7 @@ css_evaluate_subchannel(int irq, int slow)
device_trigger_reprobe(sch);
spin_unlock_irqrestore(&sch->lock, flags);
}
- ret = sch ? 0 : css_probe_device(irq);
+ ret = sch ? 0 : css_probe_device(schid);
break;
default:
BUG();
@@ -281,28 +296,15 @@ css_evaluate_subchannel(int irq, int slow)
return ret;
}
-static void
-css_rescan_devices(void)
+static int
+css_rescan_devices(struct subchannel_id schid, void *data)
{
- int irq, ret;
-
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- ret = css_evaluate_subchannel(irq, 1);
- /* No more memory. It doesn't make sense to continue. No
- * panic because this can happen in midflight and just
- * because we can't use a new device is no reason to crash
- * the system. */
- if (ret == -ENOMEM)
- break;
- /* -ENXIO indicates that there are no more subchannels. */
- if (ret == -ENXIO)
- break;
- }
+ return css_evaluate_subchannel(schid, 1);
}
struct slow_subchannel {
struct list_head slow_list;
- unsigned long schid;
+ struct subchannel_id schid;
};
static LIST_HEAD(slow_subchannels_head);
@@ -315,7 +317,7 @@ css_trigger_slow_path(void)
if (need_rescan) {
need_rescan = 0;
- css_rescan_devices();
+ for_each_subchannel(css_rescan_devices, NULL);
return;
}
@@ -354,23 +356,31 @@ css_reiterate_subchannels(void)
* Called from the machine check handler for subchannel report words.
*/
int
-css_process_crw(int irq)
+css_process_crw(int rsid1, int rsid2)
{
int ret;
+ struct subchannel_id mchk_schid;
- CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
+ CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n",
+ rsid1, rsid2);
if (need_rescan)
/* We need to iterate all subchannels anyway. */
return -EAGAIN;
+
+ init_subchannel_id(&mchk_schid);
+ mchk_schid.sch_no = rsid1;
+ if (rsid2 != 0)
+ mchk_schid.ssid = (rsid2 >> 8) & 3;
+
/*
* Since we are always presented with IPI in the CRW, we have to
* use stsch() to find out if the subchannel in question has come
* or gone.
*/
- ret = css_evaluate_subchannel(irq, 0);
+ ret = css_evaluate_subchannel(mchk_schid, 0);
if (ret == -EAGAIN) {
- if (css_enqueue_subchannel_slow(irq)) {
+ if (css_enqueue_subchannel_slow(mchk_schid)) {
css_clear_subchannel_slow_list();
need_rescan = 1;
}
@@ -378,22 +388,83 @@ css_process_crw(int irq)
return ret;
}
-static void __init
-css_generate_pgid(void)
+static int __init
+__init_channel_subsystem(struct subchannel_id schid, void *data)
{
- /* Let's build our path group ID here. */
- if (css_characteristics_avail && css_general_characteristics.mcss)
- global_pgid.cpu_addr = 0x8000;
+ struct subchannel *sch;
+ int ret;
+
+ if (cio_is_console(schid))
+ sch = cio_get_console_subchannel();
else {
+ sch = css_alloc_subchannel(schid);
+ if (IS_ERR(sch))
+ ret = PTR_ERR(sch);
+ else
+ ret = 0;
+ switch (ret) {
+ case 0:
+ break;
+ case -ENOMEM:
+ panic("Out of memory in init_channel_subsystem\n");
+ /* -ENXIO: no more subchannels. */
+ case -ENXIO:
+ return ret;
+ default:
+ return 0;
+ }
+ }
+ /*
+ * We register ALL valid subchannels in ioinfo, even those
+ * that have been present before init_channel_subsystem.
+ * These subchannels can't have been registered yet (kmalloc
+ * not working) so we do it now. This is true e.g. for the
+ * console subchannel.
+ */
+ css_register_subchannel(sch);
+ return 0;
+}
+
+static void __init
+css_generate_pgid(struct channel_subsystem *css, u32 tod_high)
+{
+ if (css_characteristics_avail && css_general_characteristics.mcss) {
+ css->global_pgid.pgid_high.ext_cssid.version = 0x80;
+ css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid;
+ } else {
#ifdef CONFIG_SMP
- global_pgid.cpu_addr = hard_smp_processor_id();
+ css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id();
#else
- global_pgid.cpu_addr = 0;
+ css->global_pgid.pgid_high.cpu_addr = 0;
#endif
}
- global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
- global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
- global_pgid.tod_high = (__u32) (get_clock() >> 32);
+ css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident;
+ css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine;
+ css->global_pgid.tod_high = tod_high;
+
+}
+
+static void
+channel_subsystem_release(struct device *dev)
+{
+ struct channel_subsystem *css;
+
+ css = to_css(dev);
+ kfree(css);
+}
+
+static inline void __init
+setup_css(int nr)
+{
+ u32 tod_high;
+
+ memset(css[nr], 0, sizeof(struct channel_subsystem));
+ css[nr]->valid = 1;
+ css[nr]->cssid = nr;
+ sprintf(css[nr]->device.bus_id, "css%x", nr);
+ css[nr]->device.release = channel_subsystem_release;
+ tod_high = (u32) (get_clock() >> 32);
+ css_generate_pgid(css[nr], tod_high);
}
/*
@@ -404,53 +475,50 @@ css_generate_pgid(void)
static int __init
init_channel_subsystem (void)
{
- int ret, irq;
+ int ret, i;
if (chsc_determine_css_characteristics() == 0)
css_characteristics_avail = 1;
- css_generate_pgid();
-
if ((ret = bus_register(&css_bus_type)))
goto out;
- if ((ret = device_register (&css_bus_device)))
- goto out_bus;
+ /* Try to enable MSS. */
+ ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
+ switch (ret) {
+ case 0: /* Success. */
+ max_ssid = __MAX_SSID;
+ break;
+ case -ENOMEM:
+ goto out_bus;
+ default:
+ max_ssid = 0;
+ }
+ /* Setup css structure. */
+ for (i = 0; i <= __MAX_CSSID; i++) {
+ css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL);
+ if (!css[i]) {
+ ret = -ENOMEM;
+ goto out_unregister;
+ }
+ setup_css(i);
+ ret = device_register(&css[i]->device);
+ if (ret)
+ goto out_free;
+ }
css_init_done = 1;
ctl_set_bit(6, 28);
- for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
- struct subchannel *sch;
-
- if (cio_is_console(irq))
- sch = cio_get_console_subchannel();
- else {
- sch = css_alloc_subchannel(irq);
- if (IS_ERR(sch))
- ret = PTR_ERR(sch);
- else
- ret = 0;
- if (ret == -ENOMEM)
- panic("Out of memory in "
- "init_channel_subsystem\n");
- /* -ENXIO: no more subchannels. */
- if (ret == -ENXIO)
- break;
- if (ret)
- continue;
- }
- /*
- * We register ALL valid subchannels in ioinfo, even those
- * that have been present before init_channel_subsystem.
- * These subchannels can't have been registered yet (kmalloc
- * not working) so we do it now. This is true e.g. for the
- * console subchannel.
- */
- css_register_subchannel(sch);
- }
+ for_each_subchannel(__init_channel_subsystem, NULL);
return 0;
-
+out_free:
+ kfree(css[i]);
+out_unregister:
+ while (i > 0) {
+ i--;
+ device_unregister(&css[i]->device);
+ }
out_bus:
bus_unregister(&css_bus_type);
out:
@@ -474,54 +542,47 @@ css_bus_match (struct device *dev, struct device_driver *drv)
return 0;
}
-struct bus_type css_bus_type = {
- .name = "css",
- .match = &css_bus_match,
-};
-
-subsys_initcall(init_channel_subsystem);
-
-/*
- * Register root devices for some drivers. The release function must not be
- * in the device drivers, so we do it here.
- */
-static void
-s390_root_dev_release(struct device *dev)
+static int
+css_probe (struct device *dev)
{
- kfree(dev);
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ sch->driver = container_of (dev->driver, struct css_driver, drv);
+ return (sch->driver->probe ? sch->driver->probe(sch) : 0);
}
-struct device *
-s390_root_dev_register(const char *name)
+static int
+css_remove (struct device *dev)
{
- struct device *dev;
- int ret;
+ struct subchannel *sch;
- if (!strlen(name))
- return ERR_PTR(-EINVAL);
- dev = kmalloc(sizeof(struct device), GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
- memset(dev, 0, sizeof(struct device));
- strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
- dev->release = s390_root_dev_release;
- ret = device_register(dev);
- if (ret) {
- kfree(dev);
- return ERR_PTR(ret);
- }
- return dev;
+ sch = to_subchannel(dev);
+ return (sch->driver->remove ? sch->driver->remove(sch) : 0);
}
-void
-s390_root_dev_unregister(struct device *dev)
+static void
+css_shutdown (struct device *dev)
{
- if (dev)
- device_unregister(dev);
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ if (sch->driver->shutdown)
+ sch->driver->shutdown(sch);
}
+struct bus_type css_bus_type = {
+ .name = "css",
+ .match = css_bus_match,
+ .probe = css_probe,
+ .remove = css_remove,
+ .shutdown = css_shutdown,
+};
+
+subsys_initcall(init_channel_subsystem);
+
int
-css_enqueue_subchannel_slow(unsigned long schid)
+css_enqueue_subchannel_slow(struct subchannel_id schid)
{
struct slow_subchannel *new_slow_sch;
unsigned long flags;
@@ -564,6 +625,4 @@ css_slow_subchannels_exist(void)
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(css_bus_type);
-EXPORT_SYMBOL(s390_root_dev_register);
-EXPORT_SYMBOL(s390_root_dev_unregister);
EXPORT_SYMBOL_GPL(css_characteristics_avail);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 2004a6c49388..b6375861cb37 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -6,6 +6,8 @@
#include <asm/cio.h>
+#include "schid.h"
+
/*
* path grouping stuff
*/
@@ -33,19 +35,25 @@ struct path_state {
__u8 resvd : 3; /* reserved */
} __attribute__ ((packed));
+struct extended_cssid {
+ u8 version;
+ u8 cssid;
+} __attribute__ ((packed));
+
struct pgid {
union {
__u8 fc; /* SPID function code */
struct path_state ps; /* SNID path state */
} inf;
- __u32 cpu_addr : 16; /* CPU address */
+ union {
+ __u32 cpu_addr : 16; /* CPU address */
+ struct extended_cssid ext_cssid;
+ } pgid_high;
__u32 cpu_id : 24; /* CPU identification */
__u32 cpu_model : 16; /* CPU model */
__u32 tod_high; /* high word TOD clock */
} __attribute__ ((packed));
-extern struct pgid global_pgid;
-
#define MAX_CIWS 8
/*
@@ -68,7 +76,8 @@ struct ccw_device_private {
atomic_t onoff;
unsigned long registered;
__u16 devno; /* device number */
- __u16 irq; /* subchannel number */
+ __u16 sch_no; /* subchannel number */
+ __u8 ssid; /* subchannel set id */
__u8 imask; /* lpm mask for SNID/SID/SPGID */
int iretry; /* retry counter SNID/SID/SPGID */
struct {
@@ -106,6 +115,7 @@ struct ccw_device_private {
* Currently, we only care about I/O subchannels (type 0), these
* have a ccw_device connected to them.
*/
+struct subchannel;
struct css_driver {
unsigned int subchannel_type;
struct device_driver drv;
@@ -113,6 +123,9 @@ struct css_driver {
int (*notify)(struct device *, int);
void (*verify)(struct device *);
void (*termination)(struct device *);
+ int (*probe)(struct subchannel *);
+ int (*remove)(struct subchannel *);
+ void (*shutdown)(struct subchannel *);
};
/*
@@ -121,15 +134,27 @@ struct css_driver {
extern struct bus_type css_bus_type;
extern struct css_driver io_subchannel_driver;
-int css_probe_device(int irq);
-extern struct subchannel * get_subchannel_by_schid(int irq);
-extern unsigned int highest_subchannel;
+extern int css_probe_device(struct subchannel_id);
+extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
-
-#define __MAX_SUBCHANNELS 65536
+extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
+
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
+#define __MAX_CHPID 255
+#define __MAX_CSSID 0
+
+struct channel_subsystem {
+ u8 cssid;
+ int valid;
+ struct channel_path *chps[__MAX_CHPID + 1];
+ struct device device;
+ struct pgid global_pgid;
+};
+#define to_css(dev) container_of(dev, struct channel_subsystem, device)
extern struct bus_type css_bus_type;
-extern struct device css_bus_device;
+extern struct channel_subsystem *css[];
/* Some helper functions for disconnected state. */
int device_is_disconnected(struct subchannel *);
@@ -144,7 +169,7 @@ void device_set_waiting(struct subchannel *);
void device_kill_pending_timer(struct subchannel *);
/* Helper functions to build lists for the slow path. */
-int css_enqueue_subchannel_slow(unsigned long schid);
+extern int css_enqueue_subchannel_slow(struct subchannel_id schid);
void css_walk_subchannel_slow_list(void (*fn)(unsigned long));
void css_clear_subchannel_slow_list(void);
int css_slow_subchannels_exist(void);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 811c9d150637..a67e7e60e330 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
- * $Revision: 1.131 $
+ * $Revision: 1.140 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
#include <linux/config.h>
@@ -59,7 +59,7 @@ ccw_bus_match (struct device * dev, struct device_driver * drv)
* Heavily modeled on pci and usb hotplug.
*/
static int
-ccw_hotplug (struct device *dev, char **envp, int num_envp,
+ccw_uevent (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct ccw_device *cdev = to_ccwdev(dev);
@@ -107,33 +107,29 @@ ccw_hotplug (struct device *dev, char **envp, int num_envp,
return 0;
}
-struct bus_type ccw_bus_type = {
- .name = "ccw",
- .match = &ccw_bus_match,
- .hotplug = &ccw_hotplug,
-};
+struct bus_type ccw_bus_type;
-static int io_subchannel_probe (struct device *);
-static int io_subchannel_remove (struct device *);
+static int io_subchannel_probe (struct subchannel *);
+static int io_subchannel_remove (struct subchannel *);
void io_subchannel_irq (struct device *);
static int io_subchannel_notify(struct device *, int);
static void io_subchannel_verify(struct device *);
static void io_subchannel_ioterm(struct device *);
-static void io_subchannel_shutdown(struct device *);
+static void io_subchannel_shutdown(struct subchannel *);
struct css_driver io_subchannel_driver = {
.subchannel_type = SUBCHANNEL_TYPE_IO,
.drv = {
.name = "io_subchannel",
.bus = &css_bus_type,
- .probe = &io_subchannel_probe,
- .remove = &io_subchannel_remove,
- .shutdown = &io_subchannel_shutdown,
},
.irq = io_subchannel_irq,
.notify = io_subchannel_notify,
.verify = io_subchannel_verify,
.termination = io_subchannel_ioterm,
+ .probe = io_subchannel_probe,
+ .remove = io_subchannel_remove,
+ .shutdown = io_subchannel_shutdown,
};
struct workqueue_struct *ccw_device_work;
@@ -374,7 +370,7 @@ online_store (struct device *dev, struct device_attribute *attr, const char *buf
int i, force, ret;
char *tmp;
- if (atomic_compare_and_swap(0, 1, &cdev->private->onoff))
+ if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
return -EAGAIN;
if (cdev->drv && !try_module_get(cdev->drv->owner)) {
@@ -535,7 +531,8 @@ ccw_device_register(struct ccw_device *cdev)
}
struct match_data {
- unsigned int devno;
+ unsigned int devno;
+ unsigned int ssid;
struct ccw_device * sibling;
};
@@ -548,6 +545,7 @@ match_devno(struct device * dev, void * data)
cdev = to_ccwdev(dev);
if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
(cdev->private->devno == d->devno) &&
+ (cdev->private->ssid == d->ssid) &&
(cdev != d->sibling)) {
cdev->private->state = DEV_STATE_NOT_OPER;
return 1;
@@ -556,11 +554,13 @@ match_devno(struct device * dev, void * data)
}
static struct ccw_device *
-get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
+get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid,
+ struct ccw_device *sibling)
{
struct device *dev;
struct match_data data = {
- .devno = devno,
+ .devno = devno,
+ .ssid = ssid,
.sibling = sibling,
};
@@ -616,13 +616,13 @@ ccw_device_do_unreg_rereg(void *data)
need_rename = 1;
other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev,
- cdev);
+ sch->schid.ssid, cdev);
if (other_cdev) {
struct subchannel *other_sch;
other_sch = to_subchannel(other_cdev->dev.parent);
if (get_device(&other_sch->dev)) {
- stsch(other_sch->irq, &other_sch->schib);
+ stsch(other_sch->schid, &other_sch->schib);
if (other_sch->schib.pmcw.dnv) {
other_sch->schib.pmcw.intparm = 0;
cio_modify(other_sch);
@@ -639,8 +639,8 @@ ccw_device_do_unreg_rereg(void *data)
if (test_and_clear_bit(1, &cdev->private->registered))
device_del(&cdev->dev);
if (need_rename)
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
- sch->schib.pmcw.dev);
+ snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
PREPARE_WORK(&cdev->private->kick_work,
ccw_device_add_changed, (void *)cdev);
queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -769,18 +769,20 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
sch->dev.driver_data = cdev;
sch->driver = &io_subchannel_driver;
cdev->ccwlock = &sch->lock;
+
/* Init private data. */
priv = cdev->private;
priv->devno = sch->schib.pmcw.dev;
- priv->irq = sch->irq;
+ priv->ssid = sch->schid.ssid;
+ priv->sch_no = sch->schid.sch_no;
priv->state = DEV_STATE_NOT_OPER;
INIT_LIST_HEAD(&priv->cmb_list);
init_waitqueue_head(&priv->wait_q);
init_timer(&priv->timer);
/* Set an initial name for the device. */
- snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
- sch->schib.pmcw.dev);
+ snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x",
+ sch->schid.ssid, sch->schib.pmcw.dev);
/* Increase counter of devices currently in recognition. */
atomic_inc(&ccw_device_init_count);
@@ -797,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
}
static int
-io_subchannel_probe (struct device *pdev)
+io_subchannel_probe (struct subchannel *sch)
{
- struct subchannel *sch;
struct ccw_device *cdev;
int rc;
unsigned long flags;
- sch = to_subchannel(pdev);
if (sch->dev.driver_data) {
/*
* This subchannel already has an associated ccw_device.
@@ -840,7 +840,7 @@ io_subchannel_probe (struct device *pdev)
memset(cdev->private, 0, sizeof(struct ccw_device_private));
atomic_set(&cdev->private->onoff, 0);
cdev->dev = (struct device) {
- .parent = pdev,
+ .parent = &sch->dev,
.release = ccw_device_release,
};
INIT_LIST_HEAD(&cdev->private->kick_work.entry);
@@ -853,7 +853,7 @@ io_subchannel_probe (struct device *pdev)
return -ENODEV;
}
- rc = io_subchannel_recog(cdev, to_subchannel(pdev));
+ rc = io_subchannel_recog(cdev, sch);
if (rc) {
spin_lock_irqsave(&sch->lock, flags);
sch->dev.driver_data = NULL;
@@ -877,17 +877,17 @@ ccw_device_unregister(void *data)
}
static int
-io_subchannel_remove (struct device *dev)
+io_subchannel_remove (struct subchannel *sch)
{
struct ccw_device *cdev;
unsigned long flags;
- if (!dev->driver_data)
+ if (!sch->dev.driver_data)
return 0;
- cdev = dev->driver_data;
+ cdev = sch->dev.driver_data;
/* Set ccw device to not operational and drop reference. */
spin_lock_irqsave(cdev->ccwlock, flags);
- dev->driver_data = NULL;
+ sch->dev.driver_data = NULL;
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
/*
@@ -942,16 +942,14 @@ io_subchannel_ioterm(struct device *dev)
}
static void
-io_subchannel_shutdown(struct device *dev)
+io_subchannel_shutdown(struct subchannel *sch)
{
- struct subchannel *sch;
struct ccw_device *cdev;
int ret;
- sch = to_subchannel(dev);
- cdev = dev->driver_data;
+ cdev = sch->dev.driver_data;
- if (cio_is_console(sch->irq))
+ if (cio_is_console(sch->schid))
return;
if (!sch->schib.pmcw.ena)
/* Nothing to do. */
@@ -986,10 +984,6 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch)
cdev->dev = (struct device) {
.parent = &sch->dev,
};
- /* Initialize the subchannel structure */
- sch->dev.parent = &css_bus_device;
- sch->dev.bus = &css_bus_type;
-
rc = io_subchannel_recog(cdev, sch);
if (rc)
return rc;
@@ -1127,6 +1121,14 @@ ccw_device_remove (struct device *dev)
return 0;
}
+struct bus_type ccw_bus_type = {
+ .name = "ccw",
+ .match = ccw_bus_match,
+ .uevent = ccw_uevent,
+ .probe = ccw_device_probe,
+ .remove = ccw_device_remove,
+};
+
int
ccw_driver_register (struct ccw_driver *cdriver)
{
@@ -1134,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver)
drv->bus = &ccw_bus_type;
drv->name = cdriver->name;
- drv->probe = ccw_device_probe;
- drv->remove = ccw_device_remove;
return driver_register(drv);
}
@@ -1146,6 +1146,16 @@ ccw_driver_unregister (struct ccw_driver *cdriver)
driver_unregister(&cdriver->driver);
}
+/* Helper func for qdio. */
+struct subchannel_id
+ccw_device_get_subchannel_id(struct ccw_device *cdev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(cdev->dev.parent);
+ return sch->schid;
+}
+
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(ccw_device_set_online);
EXPORT_SYMBOL(ccw_device_set_offline);
@@ -1155,3 +1165,4 @@ EXPORT_SYMBOL(get_ccwdev_by_busid);
EXPORT_SYMBOL(ccw_bus_type);
EXPORT_SYMBOL(ccw_device_work);
EXPORT_SYMBOL(ccw_device_notify_work);
+EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index a3aa056d7245..11587ebb7289 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -110,6 +110,7 @@ int ccw_device_stlck(struct ccw_device *);
/* qdio needs this. */
void ccw_device_set_timeout(struct ccw_device *, int);
+extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
void retry_set_schib(struct ccw_device *cdev);
#endif
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c1c89f4fd4e3..b302779e7cff 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
@@ -133,7 +133,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
int ret;
sch = to_subchannel(cdev->dev.parent);
- ret = stsch(sch->irq, &sch->schib);
+ ret = stsch(sch->schid, &sch->schib);
if (ret || !sch->schib.pmcw.dnv)
return -ENODEV;
if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0)
@@ -231,7 +231,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
* through ssch() and the path information is up to date.
*/
old_lpm = sch->lpm;
- stsch(sch->irq, &sch->schib);
+ stsch(sch->schid, &sch->schib);
sch->lpm = sch->schib.pmcw.pim &
sch->schib.pmcw.pam &
sch->schib.pmcw.pom &
@@ -257,8 +257,9 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
switch (state) {
case DEV_STATE_NOT_OPER:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : unknown device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ "SenseID : unknown device %04x on subchannel "
+ "0.%x.%04x\n", cdev->private->devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
case DEV_STATE_OFFLINE:
if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) {
@@ -282,16 +283,18 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
return;
}
/* Issue device info message. */
- CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: "
+ CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: "
"CU Type/Mod = %04X/%02X, Dev Type/Mod = "
- "%04X/%02X\n", cdev->private->devno,
+ "%04X/%02X\n",
+ cdev->private->ssid, cdev->private->devno,
cdev->id.cu_type, cdev->id.cu_model,
cdev->id.dev_type, cdev->id.dev_model);
break;
case DEV_STATE_BOXED:
CIO_DEBUG(KERN_WARNING, 2,
- "SenseID : boxed device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ "SenseID : boxed device %04x on subchannel "
+ "0.%x.%04x\n", cdev->private->devno,
+ sch->schid.ssid, sch->schid.sch_no);
break;
}
cdev->private->state = state;
@@ -359,7 +362,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
if (state == DEV_STATE_BOXED)
CIO_DEBUG(KERN_WARNING, 2,
"Boxed device %04x on subchannel %04x\n",
- cdev->private->devno, sch->irq);
+ cdev->private->devno, sch->schid.sch_no);
if (cdev->private->flags.donotify) {
cdev->private->flags.donotify = 0;
@@ -592,7 +595,7 @@ ccw_device_offline(struct ccw_device *cdev)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- if (stsch(sch->irq, &sch->schib) || !sch->schib.pmcw.dnv)
+ if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv)
return -ENODEV;
if (cdev->private->state != DEV_STATE_ONLINE) {
if (sch->schib.scsw.actl != 0)
@@ -711,7 +714,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
* Since we might not just be coming from an interrupt from the
* subchannel we have to update the schib.
*/
- stsch(sch->irq, &sch->schib);
+ stsch(sch->schid, &sch->schib);
if (sch->schib.scsw.actl != 0 ||
(cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
@@ -923,7 +926,7 @@ ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* Iff device is idle, reset timeout. */
sch = to_subchannel(cdev->dev.parent);
- if (!stsch(sch->irq, &sch->schib))
+ if (!stsch(sch->schid, &sch->schib))
if (sch->schib.scsw.actl == 0)
ccw_device_set_timeout(cdev, 0);
/* Call the handler. */
@@ -1035,7 +1038,7 @@ device_trigger_reprobe(struct subchannel *sch)
return;
/* Update some values. */
- if (stsch(sch->irq, &sch->schib))
+ if (stsch(sch->schid, &sch->schib))
return;
/*
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 0e68fb511dc9..e60b2d8103b8 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Sense ID functions.
@@ -27,7 +27,7 @@
/*
* diag210 is used under VM to get information about a virtual device
*/
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
int
diag210(struct diag210 * addr)
{
@@ -256,16 +256,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
* sense id information. So, for intervention required,
* we use the "whack it until it talks" strategy...
*/
- CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x "
- "reports cmd reject\n",
- cdev->private->devno, sch->irq);
+ CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel "
+ "0.%x.%04x reports cmd reject\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EOPNOTSUPP;
}
if (irb->esw.esw0.erw.cons) {
- CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, "
+ CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, "
"lpum %02X, cnt %02d, sns :"
" %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->devno,
+ cdev->private->ssid, cdev->private->devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -277,16 +278,17 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
if (irb->scsw.cc == 3) {
if ((sch->orb.lpm &
sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0)
- CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on"
- " subchannel %04x is 'not operational'\n",
- sch->orb.lpm, cdev->private->devno,
- sch->irq);
+ CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x "
+ "on subchannel 0.%x.%04x is "
+ "'not operational'\n", sch->orb.lpm,
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EACCES;
}
/* Hmm, whatever happened, try again. */
CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
- "subchannel %04x returns status %02X%02X\n",
- cdev->private->devno, sch->irq,
+ "subchannel 0.%x.%04x returns status %02X%02X\n",
+ cdev->private->devno, sch->schid.ssid, sch->schid.sch_no,
irb->scsw.dstat, irb->scsw.cstat);
return -EAGAIN;
}
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 85a3026e6900..8b0218949b62 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -1,12 +1,12 @@
/*
* drivers/s390/cio/device_ops.c
*
- * $Revision: 1.57 $
+ * $Revision: 1.61 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- * Cornelia Huck (cohuck@de.ibm.com)
+ * Cornelia Huck (cornelia.huck@de.ibm.com)
*/
#include <linux/config.h>
#include <linux/module.h>
@@ -570,7 +570,7 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
int
_ccw_device_get_subchannel_number(struct ccw_device *cdev)
{
- return cdev->private->irq;
+ return cdev->private->sch_no;
}
int
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 0adac8a67331..d2a5b04d7cba 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Path Group ID functions.
@@ -22,6 +22,7 @@
#include "cio_debug.h"
#include "css.h"
#include "device.h"
+#include "ioasm.h"
/*
* Start Sense Path Group ID helper function. Used in ccw_device_recog
@@ -56,10 +57,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev)
if (ret != -EACCES)
return ret;
CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not "
+ "0.%x.%04x, lpm %02X, became 'not "
"operational'\n",
- cdev->private->devno, sch->irq,
- cdev->private->imask);
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
}
cdev->private->imask >>= 1;
@@ -105,10 +106,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
return -EOPNOTSUPP;
}
if (irb->esw.esw0.erw.cons) {
- CIO_MSG_EVENT(2, "SNID - device %04x, unit check, "
+ CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, "
"lpum %02X, cnt %02d, sns : "
"%02X%02X%02X%02X %02X%02X%02X%02X ...\n",
- cdev->private->devno,
+ cdev->private->ssid, cdev->private->devno,
irb->esw.esw0.sublog.lpum,
irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
@@ -118,15 +119,17 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev)
return -EAGAIN;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq, sch->orb.lpm);
+ CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x,"
+ " lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, sch->orb.lpm);
return -EACCES;
}
if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) {
- CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x "
+ CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x "
"is reserved by someone else\n",
- cdev->private->devno, sch->irq);
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no);
return -EUSERS;
}
return 0;
@@ -162,7 +165,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event)
/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
case 0: /* Sense Path Group ID successful. */
if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
- memcpy(&cdev->private->pgid, &global_pgid,
+ memcpy(&cdev->private->pgid, &css[0]->global_pgid,
sizeof(struct pgid));
ccw_device_sense_pgid_done(cdev, 0);
break;
@@ -235,8 +238,9 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func)
sch->lpm &= ~cdev->private->imask;
sch->vpm &= ~cdev->private->imask;
CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq, cdev->private->imask);
+ "0.%x.%04x, lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
return ret;
}
@@ -258,8 +262,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
if (irb->ecw[0] & SNS0_CMD_REJECT)
return -EOPNOTSUPP;
/* Hmm, whatever happened, try again. */
- CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, "
+ CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, "
+ "cnt %02d, "
"sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+ cdev->private->ssid,
cdev->private->devno, irb->esw.esw0.erw.scnt,
irb->ecw[0], irb->ecw[1],
irb->ecw[2], irb->ecw[3],
@@ -268,10 +274,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev)
return -EAGAIN;
}
if (irb->scsw.cc == 3) {
- CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel "
- "%04x, lpm %02X, became 'not operational'\n",
- cdev->private->devno, sch->irq,
- cdev->private->imask);
+ CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x,"
+ " lpm %02X, became 'not operational'\n",
+ cdev->private->devno, sch->schid.ssid,
+ sch->schid.sch_no, cdev->private->imask);
return -EACCES;
}
return 0;
@@ -364,8 +370,22 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event)
void
ccw_device_verify_start(struct ccw_device *cdev)
{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
cdev->private->flags.pgid_single = 0;
cdev->private->iretry = 5;
+ /*
+ * Update sch->lpm with current values to catch paths becoming
+ * available again.
+ */
+ if (stsch(sch->schid, &sch->schib)) {
+ ccw_device_verify_done(cdev, -ENODEV);
+ return;
+ }
+ sch->lpm = sch->schib.pmcw.pim &
+ sch->schib.pmcw.pam &
+ sch->schib.pmcw.pom &
+ sch->opm;
__ccw_device_verify_start(cdev);
}
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 12a24d4331a2..dad4dd9887c9 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
- * Author(s): Cornelia Huck(cohuck@de.ibm.com)
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Status accumulation and basic sense functions.
@@ -36,15 +36,16 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check "
"received"
- " ... device %04X on subchannel %04X, dev_stat "
+ " ... device %04x on subchannel 0.%x.%04x, dev_stat "
": %02X sch_stat : %02X\n",
- cdev->private->devno, cdev->private->irq,
+ cdev->private->devno, cdev->private->ssid,
+ cdev->private->sch_no,
irb->scsw.dstat, irb->scsw.cstat);
if (irb->scsw.cc != 3) {
char dbf_text[15];
- sprintf(dbf_text, "chk%x", cdev->private->irq);
+ sprintf(dbf_text, "chk%x", cdev->private->sch_no);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, irb, sizeof (struct irb));
}
@@ -59,10 +60,11 @@ ccw_device_path_notoper(struct ccw_device *cdev)
struct subchannel *sch;
sch = to_subchannel(cdev->dev.parent);
- stsch (sch->irq, &sch->schib);
+ stsch (sch->schid, &sch->schib);
- CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are "
- "not operational \n", __FUNCTION__, sch->irq,
+ CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are "
+ "not operational \n", __FUNCTION__,
+ sch->schid.ssid, sch->schid.sch_no,
sch->schib.pmcw.pnom);
sch->lpm &= ~sch->schib.pmcw.pnom;
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index 45480a2bc4c0..95a9462f9a91 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -1,12 +1,13 @@
#ifndef S390_CIO_IOASM_H
#define S390_CIO_IOASM_H
+#include "schid.h"
+
/*
* TPI info structure
*/
struct tpi_info {
- __u32 reserved1 : 16; /* reserved 0x00000001 */
- __u32 irq : 16; /* aka. subchannel number */
+ struct subchannel_id schid;
__u32 intparm; /* interruption parameter */
__u32 adapter_IO : 1;
__u32 reserved2 : 1;
@@ -21,7 +22,8 @@ struct tpi_info {
* Some S390 specific IO instructions as inline
*/
-static inline int stsch(int irq, volatile struct schib *addr)
+static inline int stsch(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -31,12 +33,42 @@ static inline int stsch(int irq, volatile struct schib *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
+ : "cc", "1" );
+ return ccode;
+}
+
+static inline int stsch_err(struct subchannel_id schid,
+ volatile struct schib *addr)
+{
+ int ccode;
+
+ __asm__ __volatile__(
+ " lhi %0,%3\n"
+ " lr 1,%1\n"
+ " stsch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+#ifdef CONFIG_64BIT
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,1b\n"
+ ".previous"
+#else
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 0b,1b\n"
+ ".previous"
+#endif
+ : "=&d" (ccode)
+ : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int msch(int irq, volatile struct schib *addr)
+static inline int msch(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -46,12 +78,13 @@ static inline int msch(int irq, volatile struct schib *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int msch_err(int irq, volatile struct schib *addr)
+static inline int msch_err(struct subchannel_id schid,
+ volatile struct schib *addr)
{
int ccode;
@@ -62,7 +95,7 @@ static inline int msch_err(int irq, volatile struct schib *addr)
"0: ipm %0\n"
" srl %0,28\n"
"1:\n"
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
".section __ex_table,\"a\"\n"
" .align 8\n"
" .quad 0b,1b\n"
@@ -74,12 +107,13 @@ static inline int msch_err(int irq, volatile struct schib *addr)
".previous"
#endif
: "=&d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr), "K" (-EIO)
+ : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int tsch(int irq, volatile struct irb *addr)
+static inline int tsch(struct subchannel_id schid,
+ volatile struct irb *addr)
{
int ccode;
@@ -89,7 +123,7 @@ static inline int tsch(int irq, volatile struct irb *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
@@ -103,12 +137,13 @@ static inline int tpi( volatile struct tpi_info *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "a" (addr)
+ : "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int ssch(int irq, volatile struct orb *addr)
+static inline int ssch(struct subchannel_id schid,
+ volatile struct orb *addr)
{
int ccode;
@@ -118,12 +153,12 @@ static inline int ssch(int irq, volatile struct orb *addr)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L), "a" (addr)
+ : "d" (schid), "a" (addr), "m" (*addr)
: "cc", "1" );
return ccode;
}
-static inline int rsch(int irq)
+static inline int rsch(struct subchannel_id schid)
{
int ccode;
@@ -133,12 +168,12 @@ static inline int rsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int csch(int irq)
+static inline int csch(struct subchannel_id schid)
{
int ccode;
@@ -148,12 +183,12 @@ static inline int csch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int hsch(int irq)
+static inline int hsch(struct subchannel_id schid)
{
int ccode;
@@ -163,12 +198,12 @@ static inline int hsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
-static inline int xsch(int irq)
+static inline int xsch(struct subchannel_id schid)
{
int ccode;
@@ -178,21 +213,22 @@ static inline int xsch(int irq)
" ipm %0\n"
" srl %0,28"
: "=d" (ccode)
- : "d" (irq | 0x10000L)
+ : "d" (schid)
: "cc", "1" );
return ccode;
}
static inline int chsc(void *chsc_area)
{
+ typedef struct { char _[4096]; } addr_type;
int cc;
__asm__ __volatile__ (
- ".insn rre,0xb25f0000,%1,0 \n\t"
+ ".insn rre,0xb25f0000,%2,0 \n\t"
"ipm %0 \n\t"
"srl %0,28 \n\t"
- : "=d" (cc)
- : "d" (chsc_area)
+ : "=d" (cc), "=m" (*(addr_type *) chsc_area)
+ : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
: "cc" );
return cc;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index eb39218b925e..77be2c39bfe4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -7,7 +7,7 @@
*
* Copyright 2000,2002 IBM Corporation
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
- * 2.6 cio integration by Cornelia Huck <cohuck@de.ibm.com>
+ * 2.6 cio integration by Cornelia Huck <cornelia.huck@de.ibm.com>
*
* Restriction: only 63 iqdio subchannels would have its own indicator,
* after that, subsequent subchannels share one indicator
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.108 $"
+#define VERSION_QDIO_C "$Revision: 1.117 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -76,6 +76,7 @@ static struct qdio_perf_stats perf_stats;
#endif /* QDIO_PERFORMANCE_STATS */
static int hydra_thinints;
+static int is_passthrough = 0;
static int omit_svs;
static int indicator_used[INDICATORS_PER_CACHELINE];
@@ -136,12 +137,126 @@ qdio_release_q(struct qdio_q *q)
atomic_dec(&q->use_count);
}
-static volatile inline void
-qdio_set_slsb(volatile char *slsb, unsigned char value)
+/*check ccq */
+static inline int
+qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
+{
+ char dbf_text[15];
+
+ if (ccq == 0 || ccq == 32 || ccq == 96)
+ return 0;
+ if (ccq == 97)
+ return 1;
+ /*notify devices immediately*/
+ sprintf(dbf_text,"%d", ccq);
+ QDIO_DBF_TEXT2(1,trace,dbf_text);
+ return -EIO;
+}
+/* EQBS: extract buffer states */
+static inline int
+qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
+ unsigned int *start, unsigned int *cnt)
+{
+ struct qdio_irq *irq;
+ unsigned int tmp_cnt, q_no, ccq;
+ int rc ;
+ char dbf_text[15];
+
+ ccq = 0;
+ tmp_cnt = *cnt;
+ irq = (struct qdio_irq*)q->irq_ptr;
+ q_no = q->q_no;
+ if(!q->is_input_q)
+ q_no += irq->no_input_qs;
+ ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt);
+ rc = qdio_check_ccq(q, ccq);
+ if (rc < 0) {
+ QDIO_DBF_TEXT2(1,trace,"eqberr");
+ sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no);
+ QDIO_DBF_TEXT2(1,trace,dbf_text);
+ q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+ QDIO_STATUS_LOOK_FOR_ERROR,
+ 0, 0, 0, -1, -1, q->int_parm);
+ return 0;
+ }
+ return (tmp_cnt - *cnt);
+}
+
+/* SQBS: set buffer states */
+static inline int
+qdio_do_sqbs(struct qdio_q *q, unsigned char state,
+ unsigned int *start, unsigned int *cnt)
{
- xchg((char*)slsb,value);
+ struct qdio_irq *irq;
+ unsigned int tmp_cnt, q_no, ccq;
+ int rc;
+ char dbf_text[15];
+
+ ccq = 0;
+ tmp_cnt = *cnt;
+ irq = (struct qdio_irq*)q->irq_ptr;
+ q_no = q->q_no;
+ if(!q->is_input_q)
+ q_no += irq->no_input_qs;
+ ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt);
+ rc = qdio_check_ccq(q, ccq);
+ if (rc < 0) {
+ QDIO_DBF_TEXT3(1,trace,"sqberr");
+ sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION|
+ QDIO_STATUS_LOOK_FOR_ERROR,
+ 0, 0, 0, -1, -1, q->int_parm);
+ return 0;
+ }
+ return (tmp_cnt - *cnt);
}
+static inline int
+qdio_set_slsb(struct qdio_q *q, unsigned int *bufno,
+ unsigned char state, unsigned int *count)
+{
+ volatile char *slsb;
+ struct qdio_irq *irq;
+
+ irq = (struct qdio_irq*)q->irq_ptr;
+ if (!irq->is_qebsm) {
+ slsb = (char *)&q->slsb.acc.val[(*bufno)];
+ xchg(slsb, state);
+ return 1;
+ }
+ return qdio_do_sqbs(q, state, bufno, count);
+}
+
+#ifdef CONFIG_QDIO_DEBUG
+static inline void
+qdio_trace_slsb(struct qdio_q *q)
+{
+ if (q->queue_type==QDIO_TRACE_QTYPE) {
+ if (q->is_input_q)
+ QDIO_DBF_HEX2(0,slsb_in,&q->slsb,
+ QDIO_MAX_BUFFERS_PER_Q);
+ else
+ QDIO_DBF_HEX2(0,slsb_out,&q->slsb,
+ QDIO_MAX_BUFFERS_PER_Q);
+ }
+}
+#endif
+
+static inline int
+set_slsb(struct qdio_q *q, unsigned int *bufno,
+ unsigned char state, unsigned int *count)
+{
+ int rc;
+#ifdef CONFIG_QDIO_DEBUG
+ qdio_trace_slsb(q);
+#endif
+ rc = qdio_set_slsb(q, bufno, state, count);
+#ifdef CONFIG_QDIO_DEBUG
+ qdio_trace_slsb(q);
+#endif
+ return rc;
+}
static inline int
qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
unsigned int gpr3)
@@ -155,7 +270,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2,
perf_stats.siga_syncs++;
#endif /* QDIO_PERFORMANCE_STATS */
- cc = do_siga_sync(q->irq, gpr2, gpr3);
+ cc = do_siga_sync(q->schid, gpr2, gpr3);
if (cc)
QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
@@ -170,6 +285,23 @@ qdio_siga_sync_q(struct qdio_q *q)
return qdio_siga_sync(q, q->mask, 0);
}
+static int
+__do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
+{
+ struct qdio_irq *irq;
+ unsigned int fc = 0;
+ unsigned long schid;
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (!irq->is_qebsm)
+ schid = *((u32 *)&q->schid);
+ else {
+ schid = irq->sch_token;
+ fc |= 0x80;
+ }
+ return do_siga_output(schid, q->mask, busy_bit, fc);
+}
+
/*
* returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
* an access exception
@@ -189,7 +321,7 @@ qdio_siga_output(struct qdio_q *q)
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
for (;;) {
- cc = do_siga_output(q->irq, q->mask, &busy_bit);
+ cc = __do_siga_output(q, &busy_bit);
//QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit);
if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) {
if (!start_time)
@@ -221,7 +353,7 @@ qdio_siga_input(struct qdio_q *q)
perf_stats.siga_ins++;
#endif /* QDIO_PERFORMANCE_STATS */
- cc = do_siga_input(q->irq, q->mask);
+ cc = do_siga_input(q->schid, q->mask);
if (cc)
QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*));
@@ -230,7 +362,7 @@ qdio_siga_input(struct qdio_q *q)
}
/* locked by the locks in qdio_activate and qdio_cleanup */
-static __u32 volatile *
+static __u32 *
qdio_get_indicator(void)
{
int i;
@@ -258,7 +390,7 @@ qdio_put_indicator(__u32 *addr)
atomic_dec(&spare_indicator_usecount);
}
-static inline volatile void
+static inline void
tiqdio_clear_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"clrsummb");
@@ -267,7 +399,7 @@ tiqdio_clear_summary_bit(__u32 *location)
xchg(location,0);
}
-static inline volatile void
+static inline void
tiqdio_set_summary_bit(__u32 *location)
{
QDIO_DBF_TEXT5(0,trace,"setsummb");
@@ -336,7 +468,9 @@ static inline int
qdio_stop_polling(struct qdio_q *q)
{
#ifdef QDIO_USE_PROCESSING_STATE
- int gsf;
+ unsigned int tmp, gsf, count = 1;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
if (!atomic_swap(&q->polling,0))
return 1;
@@ -348,17 +482,22 @@ qdio_stop_polling(struct qdio_q *q)
if (!q->is_input_q)
return 1;
- gsf=GET_SAVED_FRONTIER(q);
- set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)&
- (QDIO_MAX_BUFFERS_PER_Q-1)],
- SLSB_P_INPUT_NOT_INIT);
+ tmp = gsf = GET_SAVED_FRONTIER(q);
+ tmp = ((tmp + QDIO_MAX_BUFFERS_PER_Q-1) & (QDIO_MAX_BUFFERS_PER_Q-1) );
+ set_slsb(q, &tmp, SLSB_P_INPUT_NOT_INIT, &count);
+
/*
* we don't issue this SYNC_MEMORY, as we trust Rick T and
* moreover will not use the PROCESSING state under VM, so
* q->polling was 0 anyway
*/
/*SYNC_MEMORY;*/
- if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED)
+ if (irq->is_qebsm) {
+ count = 1;
+ qdio_do_eqbs(q, &state, &gsf, &count);
+ } else
+ state = q->slsb.acc.val[gsf];
+ if (state != SLSB_P_INPUT_PRIMED)
return 1;
/*
* set our summary bit again, as otherwise there is a
@@ -431,18 +570,136 @@ tiqdio_clear_global_summary(void)
/************************* OUTBOUND ROUTINES *******************************/
+static int
+qdio_qebsm_get_outbound_buffer_frontier(struct qdio_q *q)
+{
+ struct qdio_irq *irq;
+ unsigned char state;
+ unsigned int cnt, count, ftc;
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if ((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis))
+ SYNC_MEMORY;
+
+ ftc = q->first_to_check;
+ count = qdio_min(atomic_read(&q->number_of_buffers_used),
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ if (count == 0)
+ return q->first_to_check;
+ cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+ if (cnt == 0)
+ return q->first_to_check;
+ switch (state) {
+ case SLSB_P_OUTPUT_ERROR:
+ QDIO_DBF_TEXT3(0,trace,"outperr");
+ atomic_sub(cnt , &q->number_of_buffers_used);
+ if (q->qdio_error)
+ q->error_status_flags |=
+ QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+ q->qdio_error = SLSB_P_OUTPUT_ERROR;
+ q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+ q->first_to_check = ftc;
+ break;
+ case SLSB_P_OUTPUT_EMPTY:
+ QDIO_DBF_TEXT5(0,trace,"outpempt");
+ atomic_sub(cnt, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_CU_OUTPUT_PRIMED:
+ /* all buffers primed */
+ QDIO_DBF_TEXT5(0,trace,"outpprim");
+ break;
+ default:
+ break;
+ }
+ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+ return q->first_to_check;
+}
+
+static int
+qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q)
+{
+ struct qdio_irq *irq;
+ unsigned char state;
+ int tmp, ftc, count, cnt;
+ char dbf_text[15];
+
+
+ irq = (struct qdio_irq *) q->irq_ptr;
+ ftc = q->first_to_check;
+ count = qdio_min(atomic_read(&q->number_of_buffers_used),
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ if (count == 0)
+ return q->first_to_check;
+ cnt = qdio_do_eqbs(q, &state, &ftc, &count);
+ if (cnt == 0)
+ return q->first_to_check;
+ switch (state) {
+ case SLSB_P_INPUT_ERROR :
+#ifdef CONFIG_QDIO_DEBUG
+ QDIO_DBF_TEXT3(1,trace,"inperr");
+ sprintf(dbf_text,"%2x,%2x",ftc,count);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+#endif /* CONFIG_QDIO_DEBUG */
+ if (q->qdio_error)
+ q->error_status_flags |=
+ QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR;
+ q->qdio_error = SLSB_P_INPUT_ERROR;
+ q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR;
+ atomic_sub(cnt, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_P_INPUT_PRIMED :
+ QDIO_DBF_TEXT3(0,trace,"inptprim");
+ sprintf(dbf_text,"%2x,%2x",ftc,count);
+ QDIO_DBF_TEXT3(1,trace,dbf_text);
+ tmp = 0;
+ ftc = q->first_to_check;
+#ifdef QDIO_USE_PROCESSING_STATE
+ if (cnt > 1) {
+ cnt -= 1;
+ tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+ if (!tmp)
+ break;
+ }
+ cnt = 1;
+ tmp += set_slsb(q, &ftc,
+ SLSB_P_INPUT_PROCESSING, &cnt);
+ atomic_set(&q->polling, 1);
+#else
+ tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt);
+#endif
+ atomic_sub(tmp, &q->number_of_buffers_used);
+ q->first_to_check = ftc;
+ break;
+ case SLSB_CU_INPUT_EMPTY:
+ case SLSB_P_INPUT_NOT_INIT:
+ case SLSB_P_INPUT_PROCESSING:
+ QDIO_DBF_TEXT5(0,trace,"inpnipro");
+ break;
+ default:
+ break;
+ }
+ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
+ return q->first_to_check;
+}
static inline int
qdio_get_outbound_buffer_frontier(struct qdio_q *q)
{
- int f,f_mod_no;
- volatile char *slsb;
- int first_not_to_check;
+ struct qdio_irq *irq;
+ volatile char *slsb;
+ unsigned int count = 1;
+ int first_not_to_check, f, f_mod_no;
char dbf_text[15];
QDIO_DBF_TEXT4(0,trace,"getobfro");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (irq->is_qebsm)
+ return qdio_qebsm_get_outbound_buffer_frontier(q);
+
slsb=&q->slsb.acc.val[0];
f_mod_no=f=q->first_to_check;
/*
@@ -484,7 +741,7 @@ check_next:
QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
/* kind of process the buffer */
- set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_OUTPUT_NOT_INIT, &count);
/*
* we increment the frontier, as this buffer
@@ -597,48 +854,48 @@ qdio_kick_outbound_q(struct qdio_q *q)
result=qdio_siga_output(q);
- switch (result) {
- case 0:
- /* went smooth this time, reset timestamp */
+ switch (result) {
+ case 0:
+ /* went smooth this time, reset timestamp */
#ifdef CONFIG_QDIO_DEBUG
- QDIO_DBF_TEXT3(0,trace,"cc2reslv");
- sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
- atomic_read(&q->busy_siga_counter));
- QDIO_DBF_TEXT3(0,trace,dbf_text);
+ QDIO_DBF_TEXT3(0,trace,"cc2reslv");
+ sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+ atomic_read(&q->busy_siga_counter));
+ QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
- q->timing.busy_start=0;
+ q->timing.busy_start=0;
+ break;
+ case (2|QDIO_SIGA_ERROR_B_BIT_SET):
+ /* cc=2 and busy bit: */
+ atomic_inc(&q->busy_siga_counter);
+
+ /* if the last siga was successful, save
+ * timestamp here */
+ if (!q->timing.busy_start)
+ q->timing.busy_start=NOW;
+
+ /* if we're in time, don't touch error_status_flags
+ * and siga_error */
+ if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
+ qdio_mark_q(q);
break;
- case (2|QDIO_SIGA_ERROR_B_BIT_SET):
- /* cc=2 and busy bit: */
- atomic_inc(&q->busy_siga_counter);
-
- /* if the last siga was successful, save
- * timestamp here */
- if (!q->timing.busy_start)
- q->timing.busy_start=NOW;
-
- /* if we're in time, don't touch error_status_flags
- * and siga_error */
- if (NOW-q->timing.busy_start<QDIO_BUSY_BIT_GIVE_UP) {
- qdio_mark_q(q);
- break;
- }
- QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
+ }
+ QDIO_DBF_TEXT2(0,trace,"cc2REPRT");
#ifdef CONFIG_QDIO_DEBUG
- sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no,
- atomic_read(&q->busy_siga_counter));
- QDIO_DBF_TEXT3(0,trace,dbf_text);
+ sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no,
+ atomic_read(&q->busy_siga_counter));
+ QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
- /* else fallthrough and report error */
- default:
- /* for plain cc=1, 2 or 3: */
- if (q->siga_error)
- q->error_status_flags|=
- QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+ /* else fallthrough and report error */
+ default:
+ /* for plain cc=1, 2 or 3: */
+ if (q->siga_error)
q->error_status_flags|=
- QDIO_STATUS_LOOK_FOR_ERROR;
- q->siga_error=result;
- }
+ QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR;
+ q->error_status_flags|=
+ QDIO_STATUS_LOOK_FOR_ERROR;
+ q->siga_error=result;
+ }
}
static inline void
@@ -743,8 +1000,10 @@ qdio_outbound_processing(struct qdio_q *q)
static inline int
qdio_get_inbound_buffer_frontier(struct qdio_q *q)
{
+ struct qdio_irq *irq;
int f,f_mod_no;
volatile char *slsb;
+ unsigned int count = 1;
int first_not_to_check;
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
@@ -756,6 +1015,10 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,"getibfro");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
+ irq = (struct qdio_irq *) q->irq_ptr;
+ if (irq->is_qebsm)
+ return qdio_qebsm_get_inbound_buffer_frontier(q);
+
slsb=&q->slsb.acc.val[0];
f_mod_no=f=q->first_to_check;
/*
@@ -792,19 +1055,19 @@ check_next:
* kill VM in terms of CP overhead
*/
if (q->siga_sync) {
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
} else {
/* set the previous buffer to NOT_INIT. The current
* buffer will be set to PROCESSING at the end of
* this function to avoid further interrupts. */
if (last_position>=0)
- set_slsb(&slsb[last_position],
- SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &last_position,
+ SLSB_P_INPUT_NOT_INIT, &count);
atomic_set(&q->polling,1);
last_position=f_mod_no;
}
#else /* QDIO_USE_PROCESSING_STATE */
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
#endif /* QDIO_USE_PROCESSING_STATE */
/*
* not needed, as the inbound queue will be synced on the next
@@ -829,7 +1092,7 @@ check_next:
QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256);
/* kind of process the buffer */
- set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT);
+ set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count);
if (q->qdio_error)
q->error_status_flags|=
@@ -857,7 +1120,7 @@ out:
#ifdef QDIO_USE_PROCESSING_STATE
if (last_position>=0)
- set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING);
+ set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count);
#endif /* QDIO_USE_PROCESSING_STATE */
QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int));
@@ -902,6 +1165,10 @@ static inline int
tiqdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+ unsigned int start_buf, count;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
#endif
@@ -927,8 +1194,13 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
if (!q->siga_sync)
/* we'll check for more primed buffers in qeth_stop_polling */
return 0;
-
- if (q->slsb.acc.val[q->first_to_check]!=SLSB_P_INPUT_PRIMED)
+ if (irq->is_qebsm) {
+ count = 1;
+ start_buf = q->first_to_check;
+ qdio_do_eqbs(q, &state, &start_buf, &count);
+ } else
+ state = q->slsb.acc.val[q->first_to_check];
+ if (state != SLSB_P_INPUT_PRIMED)
/*
* nothing more to do, if next buffer is not PRIMED.
* note that we did a SYNC_MEMORY before, that there
@@ -955,6 +1227,10 @@ static inline int
qdio_is_inbound_q_done(struct qdio_q *q)
{
int no_used;
+ unsigned int start_buf, count;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[15];
#endif
@@ -973,8 +1249,13 @@ qdio_is_inbound_q_done(struct qdio_q *q)
QDIO_DBF_TEXT4(0,trace,dbf_text);
return 1;
}
-
- if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) {
+ if (irq->is_qebsm) {
+ count = 1;
+ start_buf = q->first_to_check;
+ qdio_do_eqbs(q, &state, &start_buf, &count);
+ } else
+ state = q->slsb.acc.val[q->first_to_check];
+ if (state == SLSB_P_INPUT_PRIMED) {
/* we got something to do */
QDIO_DBF_TEXT4(0,trace,"inqisntA");
QDIO_DBF_HEX4(0,trace,&q,sizeof(void*));
@@ -1456,7 +1737,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
void *ptr;
int available;
- sprintf(dbf_text,"qfqs%4x",cdev->private->irq);
+ sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
for (i=0;i<no_input_qs;i++) {
q=irq_ptr->input_qs[i];
@@ -1476,7 +1757,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->queue_type=q_format;
q->int_parm=int_parm;
- q->irq=irq_ptr->irq;
+ q->schid = irq_ptr->schid;
q->irq_ptr = irq_ptr;
q->cdev = cdev;
q->mask=1<<(31-i);
@@ -1523,11 +1804,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
/* fill in slsb */
- for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
- set_slsb(&q->slsb.acc.val[j],
- SLSB_P_INPUT_NOT_INIT);
-/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
- }
+ if (!irq_ptr->is_qebsm) {
+ unsigned int count = 1;
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+ set_slsb(q, &j, SLSB_P_INPUT_NOT_INIT, &count);
+ }
}
for (i=0;i<no_output_qs;i++) {
@@ -1549,7 +1830,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
q->queue_type=q_format;
q->int_parm=int_parm;
q->is_input_q=0;
- q->irq=irq_ptr->irq;
+ q->schid = irq_ptr->schid;
q->cdev = cdev;
q->irq_ptr = irq_ptr;
q->mask=1<<(31-i);
@@ -1584,11 +1865,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev,
QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*));
/* fill in slsb */
- for (j=0;j<QDIO_MAX_BUFFERS_PER_Q;j++) {
- set_slsb(&q->slsb.acc.val[j],
- SLSB_P_OUTPUT_NOT_INIT);
-/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/
- }
+ if (!irq_ptr->is_qebsm) {
+ unsigned int count = 1;
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
+ set_slsb(q, &j, SLSB_P_OUTPUT_NOT_INIT, &count);
+ }
}
}
@@ -1656,7 +1937,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
char dbf_text[15];
QDIO_DBF_TEXT5(0,trace,"newstate");
- sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state);
+ sprintf(dbf_text,"%4x%4x",irq_ptr->schid.sch_no,state);
QDIO_DBF_TEXT5(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
@@ -1669,12 +1950,12 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
}
static inline void
-qdio_irq_check_sense(int irq, struct irb *irb)
+qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
{
char dbf_text[15];
if (irb->esw.esw0.erw.cons) {
- sprintf(dbf_text,"sens%4x",irq);
+ sprintf(dbf_text,"sens%4x",schid.sch_no);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN);
@@ -1785,21 +2066,22 @@ qdio_timeout_handler(struct ccw_device *cdev)
switch (irq_ptr->state) {
case QDIO_IRQ_STATE_INACTIVE:
- QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n",
- irq_ptr->irq);
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1,setup,"eq:timeo");
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
break;
case QDIO_IRQ_STATE_CLEANUP:
- QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n",
- irq_ptr->irq);
+ QDIO_PRINT_INFO("Did not get interrupt on cleanup, "
+ "irq=0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
break;
case QDIO_IRQ_STATE_ESTABLISHED:
case QDIO_IRQ_STATE_ACTIVE:
/* I/O has been terminated by common I/O layer. */
- QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n",
- irq_ptr->irq);
+ QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1, trace, "cio:term");
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED);
if (get_device(&cdev->dev)) {
@@ -1862,7 +2144,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
}
}
- qdio_irq_check_sense(irq_ptr->irq, irb);
+ qdio_irq_check_sense(irq_ptr->schid, irb);
#ifdef CONFIG_QDIO_DEBUG
sprintf(dbf_text, "state:%d", irq_ptr->state);
@@ -1905,7 +2187,7 @@ int
qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
unsigned int queue_number)
{
- int cc;
+ int cc = 0;
struct qdio_q *q;
struct qdio_irq *irq_ptr;
void *ptr;
@@ -1918,7 +2200,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
return -ENODEV;
#ifdef CONFIG_QDIO_DEBUG
- *((int*)(&dbf_text[4])) = irq_ptr->irq;
+ *((int*)(&dbf_text[4])) = irq_ptr->schid.sch_no;
QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN);
*((int*)(&dbf_text[0]))=flags;
*((int*)(&dbf_text[4]))=queue_number;
@@ -1929,12 +2211,14 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
q=irq_ptr->input_qs[queue_number];
if (!q)
return -EINVAL;
- cc = do_siga_sync(q->irq, 0, q->mask);
+ if (!(irq_ptr->is_qebsm))
+ cc = do_siga_sync(q->schid, 0, q->mask);
} else if (flags&QDIO_FLAG_SYNC_OUTPUT) {
q=irq_ptr->output_qs[queue_number];
if (!q)
return -EINVAL;
- cc = do_siga_sync(q->irq, q->mask, 0);
+ if (!(irq_ptr->is_qebsm))
+ cc = do_siga_sync(q->schid, q->mask, 0);
} else
return -EINVAL;
@@ -1945,15 +2229,54 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
return cc;
}
-static unsigned char
-qdio_check_siga_needs(int sch)
+static inline void
+qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
+ unsigned long token)
+{
+ struct qdio_q *q;
+ int i;
+ unsigned int count, start_buf;
+ char dbf_text[15];
+
+ /*check if QEBSM is disabled */
+ if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) {
+ irq_ptr->is_qebsm = 0;
+ irq_ptr->sch_token = 0;
+ irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+ QDIO_DBF_TEXT0(0,setup,"noV=V");
+ return;
+ }
+ irq_ptr->sch_token = token;
+ /*input queue*/
+ for (i = 0; i < irq_ptr->no_input_qs;i++) {
+ q = irq_ptr->input_qs[i];
+ count = QDIO_MAX_BUFFERS_PER_Q;
+ start_buf = 0;
+ set_slsb(q, &start_buf, SLSB_P_INPUT_NOT_INIT, &count);
+ }
+ sprintf(dbf_text,"V=V:%2x",irq_ptr->is_qebsm);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+ sprintf(dbf_text,"%8lx",irq_ptr->sch_token);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+ /*output queue*/
+ for (i = 0; i < irq_ptr->no_output_qs; i++) {
+ q = irq_ptr->output_qs[i];
+ count = QDIO_MAX_BUFFERS_PER_Q;
+ start_buf = 0;
+ set_slsb(q, &start_buf, SLSB_P_OUTPUT_NOT_INIT, &count);
+ }
+}
+
+static void
+qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
{
int result;
unsigned char qdioac;
-
struct {
struct chsc_header request;
- u16 reserved1;
+ u16 reserved1:10;
+ u16 ssid:2;
+ u16 fmt:4;
u16 first_sch;
u16 reserved2;
u16 last_sch;
@@ -1964,67 +2287,83 @@ qdio_check_siga_needs(int sch)
u8 reserved5;
u16 sch;
u8 qfmt;
- u8 reserved6;
- u8 qdioac;
+ u8 parm;
+ u8 qdioac1;
u8 sch_class;
u8 reserved7;
u8 icnt;
u8 reserved8;
u8 ocnt;
+ u8 reserved9;
+ u8 mbccnt;
+ u16 qdioac2;
+ u64 sch_token;
} *ssqd_area;
+ QDIO_DBF_TEXT0(0,setup,"getssqd");
+ qdioac = 0;
ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!ssqd_area) {
QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
- "SIGAs for sch x%x.\n", sch);
- return CHSC_FLAG_SIGA_INPUT_NECESSARY ||
- CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
- CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
+ irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
+ CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
+ CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
+ irq_ptr->sch_token = 0;
+ irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM;
+ return;
}
+
ssqd_area->request = (struct chsc_header) {
.length = 0x0010,
.code = 0x0024,
};
-
- ssqd_area->first_sch = sch;
- ssqd_area->last_sch = sch;
-
- result=chsc(ssqd_area);
+ ssqd_area->first_sch = irq_ptr->schid.sch_no;
+ ssqd_area->last_sch = irq_ptr->schid.sch_no;
+ ssqd_area->ssid = irq_ptr->schid.ssid;
+ result = chsc(ssqd_area);
if (result) {
QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \
- "SIGAs for sch x%x.\n",
- result,sch);
+ "SIGAs for sch 0.%x.%x.\n", result,
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
goto out;
}
if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) {
QDIO_PRINT_WARN("response upon checking SIGA needs " \
- "is 0x%x. Using all SIGAs for sch x%x.\n",
- ssqd_area->response.code, sch);
+ "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n",
+ ssqd_area->response.code,
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY ||
CHSC_FLAG_SIGA_OUTPUT_NECESSARY ||
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */
+ irq_ptr->is_qebsm = 0;
goto out;
}
if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) ||
!(ssqd_area->flags & CHSC_FLAG_VALIDITY) ||
- (ssqd_area->sch != sch)) {
- QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \
- "using all SIGAs.\n",sch);
+ (ssqd_area->sch != irq_ptr->schid.sch_no)) {
+ QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \
+ "using all SIGAs.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY |
CHSC_FLAG_SIGA_OUTPUT_NECESSARY |
CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */
+ irq_ptr->is_qebsm = 0;
goto out;
}
-
- qdioac = ssqd_area->qdioac;
+ qdioac = ssqd_area->qdioac1;
out:
+ qdio_check_subchannel_qebsm(irq_ptr, qdioac,
+ ssqd_area->sch_token);
free_page ((unsigned long) ssqd_area);
- return qdioac;
+ irq_ptr->qdioac = qdioac;
}
static unsigned int
@@ -2055,6 +2394,13 @@ tiqdio_check_chsc_availability(void)
sprintf(dbf_text,"hydrati%1x", hydra_thinints);
QDIO_DBF_TEXT0(0,setup,dbf_text);
+#ifdef CONFIG_64BIT
+ /* Check for QEBSM support in general (bit 58). */
+ is_passthrough = css_general_characteristics.qebsm;
+#endif
+ sprintf(dbf_text,"cssQBS:%1x", is_passthrough);
+ QDIO_DBF_TEXT0(0,setup,dbf_text);
+
/* Check for aif time delay disablement fac (bit 56). If installed,
* omit svs even under lpar (good point by rick again) */
omit_svs = css_general_characteristics.aif_tdd;
@@ -2091,7 +2437,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
/* set to 0x10000000 to enable
* time delay disablement facility */
u32 reserved5;
- u32 subsystem_id;
+ struct subchannel_id schid;
u32 reserved6[1004];
struct chsc_header response;
u32 reserved7;
@@ -2113,7 +2459,8 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scssc_area) {
QDIO_PRINT_WARN("No memory for setting indicators on " \
- "subchannel x%x.\n", irq_ptr->irq);
+ "subchannel 0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
return -ENOMEM;
}
scssc_area->request = (struct chsc_header) {
@@ -2127,7 +2474,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
scssc_area->ks = QDIO_STORAGE_KEY;
scssc_area->kc = QDIO_STORAGE_KEY;
scssc_area->isc = TIQDIO_THININT_ISC;
- scssc_area->subsystem_id = (1<<16) + irq_ptr->irq;
+ scssc_area->schid = irq_ptr->schid;
/* enables the time delay disablement facility. Don't care
* whether it is really there (i.e. we haven't checked for
* it) */
@@ -2137,12 +2484,11 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
QDIO_PRINT_WARN("Time delay disablement facility " \
"not available\n");
-
-
result = chsc(scssc_area);
if (result) {
- QDIO_PRINT_WARN("could not set indicators on irq x%x, " \
- "cc=%i.\n",irq_ptr->irq,result);
+ QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \
+ "cc=%i.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result);
result = -EIO;
goto out;
}
@@ -2198,7 +2544,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!scsscf_area) {
QDIO_PRINT_WARN("No memory for setting delay target on " \
- "subchannel x%x.\n", irq_ptr->irq);
+ "subchannel 0.%x.%x.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
return -ENOMEM;
}
scsscf_area->request = (struct chsc_header) {
@@ -2210,8 +2557,10 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
result=chsc(scsscf_area);
if (result) {
- QDIO_PRINT_WARN("could not set delay target on irq x%x, " \
- "cc=%i. Continuing.\n",irq_ptr->irq,result);
+ QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \
+ "cc=%i. Continuing.\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result);
result = -EIO;
goto out;
}
@@ -2245,7 +2594,7 @@ qdio_cleanup(struct ccw_device *cdev, int how)
if (!irq_ptr)
return -ENODEV;
- sprintf(dbf_text,"qcln%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qcln%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2272,7 +2621,7 @@ qdio_shutdown(struct ccw_device *cdev, int how)
down(&irq_ptr->setting_up_sema);
- sprintf(dbf_text,"qsqs%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qsqs%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2378,7 +2727,7 @@ qdio_free(struct ccw_device *cdev)
down(&irq_ptr->setting_up_sema);
- sprintf(dbf_text,"qfqs%4x",irq_ptr->irq);
+ sprintf(dbf_text,"qfqs%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT1(0,trace,dbf_text);
QDIO_DBF_TEXT0(0,setup,dbf_text);
@@ -2526,13 +2875,14 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
irq_ptr = cdev->private->qdio_data;
if (cstat || (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END))) {
- sprintf(dbf_text,"ick1%4x",irq_ptr->irq);
+ sprintf(dbf_text,"ick1%4x",irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(1,trace,dbf_text);
QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int));
QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int));
QDIO_PRINT_ERR("received check condition on establish " \
- "queues on irq 0x%x (cs=x%x, ds=x%x).\n",
- irq_ptr->irq,cstat,dstat);
+ "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ cstat,dstat);
qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR);
}
@@ -2540,9 +2890,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
QDIO_DBF_TEXT2(1,setup,"eq:no de");
QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
- QDIO_PRINT_ERR("establish queues on irq %04x: didn't get "
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get "
"device end: dstat=%02x, cstat=%02x\n",
- irq_ptr->irq, dstat, cstat);
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ dstat, cstat);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
return 1;
}
@@ -2551,10 +2902,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
QDIO_DBF_TEXT2(1,setup,"eq:badio");
QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat));
QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat));
- QDIO_PRINT_ERR("establish queues on irq %04x: got "
+ QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got "
"the following devstat: dstat=%02x, "
- "cstat=%02x\n",
- irq_ptr->irq, dstat, cstat);
+ "cstat=%02x\n", irq_ptr->schid.ssid,
+ irq_ptr->schid.sch_no, dstat, cstat);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
return 1;
}
@@ -2569,7 +2920,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat)
irq_ptr = cdev->private->qdio_data;
- sprintf(dbf_text,"qehi%4x",cdev->private->irq);
+ sprintf(dbf_text,"qehi%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2588,7 +2939,7 @@ qdio_initialize(struct qdio_initialize *init_data)
int rc;
char dbf_text[15];
- sprintf(dbf_text,"qini%4x",init_data->cdev->private->irq);
+ sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2609,7 +2960,7 @@ qdio_allocate(struct qdio_initialize *init_data)
struct qdio_irq *irq_ptr;
char dbf_text[15];
- sprintf(dbf_text,"qalc%4x",init_data->cdev->private->irq);
+ sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) ||
@@ -2682,7 +3033,7 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
irq_ptr->int_parm=init_data->int_parm;
- irq_ptr->irq = init_data->cdev->private->irq;
+ irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev);
irq_ptr->no_input_qs=init_data->no_input_qs;
irq_ptr->no_output_qs=init_data->no_output_qs;
@@ -2698,11 +3049,12 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
QDIO_DBF_TEXT2(0,setup,dbf_text);
if (irq_ptr->is_thinint_irq) {
- irq_ptr->dev_st_chg_ind=qdio_get_indicator();
+ irq_ptr->dev_st_chg_ind = qdio_get_indicator();
QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*));
if (!irq_ptr->dev_st_chg_ind) {
QDIO_PRINT_WARN("no indicator location available " \
- "for irq 0x%x\n",irq_ptr->irq);
+ "for irq 0.%x.%x\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no);
qdio_release_irq_memory(irq_ptr);
return -ENOBUFS;
}
@@ -2747,6 +3099,10 @@ int qdio_fill_irq(struct qdio_initialize *init_data)
irq_ptr->qdr->qkey=QDIO_STORAGE_KEY;
/* fill in qib */
+ irq_ptr->is_qebsm = is_passthrough;
+ if (irq_ptr->is_qebsm)
+ irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM;
+
irq_ptr->qib.qfmt=init_data->q_format;
if (init_data->no_input_qs)
irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib);
@@ -2829,7 +3185,7 @@ qdio_establish(struct qdio_initialize *init_data)
tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET);
}
- sprintf(dbf_text,"qest%4x",cdev->private->irq);
+ sprintf(dbf_text,"qest%4x",cdev->private->sch_no);
QDIO_DBF_TEXT0(0,setup,dbf_text);
QDIO_DBF_TEXT0(0,trace,dbf_text);
@@ -2855,9 +3211,10 @@ qdio_establish(struct qdio_initialize *init_data)
sprintf(dbf_text,"eq:io%4x",result);
QDIO_DBF_TEXT2(1,setup,dbf_text);
}
- QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \
- "returned %i, next try returned %i\n",
- irq_ptr->irq,result,result2);
+ QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \
+ "returned %i, next try returned %i\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result, result2);
result=result2;
if (result)
ccw_device_set_timeout(cdev, 0);
@@ -2884,7 +3241,7 @@ qdio_establish(struct qdio_initialize *init_data)
return -EIO;
}
- irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq);
+ qdio_get_ssqd_information(irq_ptr);
/* if this gets set once, we're running under VM and can omit SVSes */
if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY)
omit_svs=1;
@@ -2930,7 +3287,7 @@ qdio_activate(struct ccw_device *cdev, int flags)
goto out;
}
- sprintf(dbf_text,"qact%4x", irq_ptr->irq);
+ sprintf(dbf_text,"qact%4x", irq_ptr->schid.sch_no);
QDIO_DBF_TEXT2(0,setup,dbf_text);
QDIO_DBF_TEXT2(0,trace,dbf_text);
@@ -2955,9 +3312,10 @@ qdio_activate(struct ccw_device *cdev, int flags)
sprintf(dbf_text,"aq:io%4x",result);
QDIO_DBF_TEXT2(1,setup,dbf_text);
}
- QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \
- "returned %i, next try returned %i\n",
- irq_ptr->irq,result,result2);
+ QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \
+ "returned %i, next try returned %i\n",
+ irq_ptr->schid.ssid, irq_ptr->schid.sch_no,
+ result, result2);
result=result2;
}
@@ -3015,30 +3373,40 @@ static inline void
qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+ qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+ if (irq->is_qebsm) {
+ while (count)
+ set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
+ return;
+ }
for (;;) {
- set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY);
+ set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count);
count--;
if (!count) break;
- qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+ qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
}
-
- /* not necessary, as the queues are synced during the SIGA read */
- /*SYNC_MEMORY;*/
}
static inline void
qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
unsigned int count, struct qdio_buffer *buffers)
{
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
+
+ qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1);
+ if (irq->is_qebsm) {
+ while (count)
+ set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
+ return;
+ }
+
for (;;) {
- set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED);
+ set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count);
count--;
if (!count) break;
- qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1);
+ qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1);
}
-
- /* SIGA write will sync the queues */
- /*SYNC_MEMORY;*/
}
static inline void
@@ -3083,6 +3451,9 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
struct qdio_buffer *buffers)
{
int used_elements;
+ unsigned int cnt, start_buf;
+ unsigned char state = 0;
+ struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr;
/* This is the outbound handling of queues */
#ifdef QDIO_PERFORMANCE_STATS
@@ -3115,9 +3486,15 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
* SYNC_MEMORY :-/ ), we try to
* fast-requeue buffers
*/
- if (q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
- &(QDIO_MAX_BUFFERS_PER_Q-1)]!=
- SLSB_CU_OUTPUT_PRIMED) {
+ if (irq->is_qebsm) {
+ cnt = 1;
+ start_buf = ((qidx+QDIO_MAX_BUFFERS_PER_Q-1) &
+ (QDIO_MAX_BUFFERS_PER_Q-1));
+ qdio_do_eqbs(q, &state, &start_buf, &cnt);
+ } else
+ state = q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1)
+ &(QDIO_MAX_BUFFERS_PER_Q-1) ];
+ if (state != SLSB_CU_OUTPUT_PRIMED) {
qdio_kick_outbound_q(q);
} else {
QDIO_DBF_TEXT3(0,trace, "fast-req");
@@ -3150,7 +3527,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags,
#ifdef CONFIG_QDIO_DEBUG
char dbf_text[20];
- sprintf(dbf_text,"doQD%04x",cdev->private->irq);
+ sprintf(dbf_text,"doQD%04x",cdev->private->sch_no);
QDIO_DBF_TEXT3(0,trace,dbf_text);
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 328e31cc6854..fa385e761fe1 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,14 +3,15 @@
#include <asm/page.h>
-#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
+#include "schid.h"
+
+#define VERSION_CIO_QDIO_H "$Revision: 1.40 $"
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_VERBOSE_LEVEL 9
#else /* CONFIG_QDIO_DEBUG */
#define QDIO_VERBOSE_LEVEL 5
#endif /* CONFIG_QDIO_DEBUG */
-
#define QDIO_USE_PROCESSING_STATE
#ifdef CONFIG_QDIO_PERF_STATS
@@ -265,12 +266,64 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
/*
* Some instructions as assembly
*/
+
+static inline int
+do_sqbs(unsigned long sch, unsigned char state, int queue,
+ unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+ register unsigned long _ccq asm ("0") = *count;
+ register unsigned long _sch asm ("1") = sch;
+ unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+
+ asm volatile (
+ " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t"
+ : "+d" (_ccq), "+d" (_queuestart)
+ : "d" ((unsigned long)state), "d" (_sch)
+ : "memory", "cc"
+ );
+ *count = _ccq & 0xff;
+ *start = _queuestart & 0xff;
+
+ return (_ccq >> 32) & 0xff;
+#else
+ return 0;
+#endif
+}
+
+static inline int
+do_eqbs(unsigned long sch, unsigned char *state, int queue,
+ unsigned int *start, unsigned int *count)
+{
+#ifdef CONFIG_64BIT
+ register unsigned long _ccq asm ("0") = *count;
+ register unsigned long _sch asm ("1") = sch;
+ unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+ unsigned long _state = 0;
+
+ asm volatile (
+ " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t"
+ : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+ : "d" (_sch)
+ : "memory", "cc"
+ );
+ *count = _ccq & 0xff;
+ *start = _queuestart & 0xff;
+ *state = _state & 0xff;
+
+ return (_ccq >> 32) & 0xff;
+#else
+ return 0;
+#endif
+}
+
+
static inline int
-do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
+do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2)
{
int cc;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,2 \n\t"
"lr 1,%1 \n\t"
@@ -280,10 +333,10 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+ : "d" (schid), "d" (mask1), "d" (mask2)
: "cc", "0", "1", "2", "3"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 0,2 \n\t"
"llgfr 1,%1 \n\t"
@@ -293,19 +346,19 @@ do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
+ : "d" (schid), "d" (mask1), "d" (mask2)
: "cc", "0", "1", "2", "3"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return cc;
}
static inline int
-do_siga_input(unsigned int irq, unsigned int mask)
+do_siga_input(struct subchannel_id schid, unsigned int mask)
{
int cc;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,1 \n\t"
"lr 1,%1 \n\t"
@@ -314,10 +367,10 @@ do_siga_input(unsigned int irq, unsigned int mask)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask)
+ : "d" (schid), "d" (mask)
: "cc", "0", "1", "2", "memory"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 0,1 \n\t"
"llgfr 1,%1 \n\t"
@@ -326,21 +379,22 @@ do_siga_input(unsigned int irq, unsigned int mask)
"ipm %0 \n\t"
"srl %0,28 \n\t"
: "=d" (cc)
- : "d" (0x10000|irq), "d" (mask)
+ : "d" (schid), "d" (mask)
: "cc", "0", "1", "2", "memory"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return cc;
}
static inline int
-do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
+do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb,
+ unsigned int fc)
{
int cc;
__u32 busy_bit;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 0,0 \n\t"
"lr 1,%2 \n\t"
@@ -366,14 +420,14 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
".long 0b,2b \n\t"
".previous \n\t"
: "=d" (cc), "=d" (busy_bit)
- : "d" (0x10000|irq), "d" (mask),
+ : "d" (schid), "d" (mask),
"i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
: "cc", "0", "1", "2", "memory"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
- "lghi 0,0 \n\t"
- "llgfr 1,%2 \n\t"
+ "llgfr 0,%5 \n\t"
+ "lgr 1,%2 \n\t"
"llgfr 2,%3 \n\t"
"siga 0 \n\t"
"0:"
@@ -391,11 +445,11 @@ do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
".quad 0b,1b \n\t"
".previous \n\t"
: "=d" (cc), "=d" (busy_bit)
- : "d" (0x10000|irq), "d" (mask),
- "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
+ : "d" (schid), "d" (mask),
+ "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc)
: "cc", "0", "1", "2", "memory"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
(*bb) = busy_bit;
return cc;
@@ -407,21 +461,21 @@ do_clear_global_summary(void)
unsigned long time;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
asm volatile (
"lhi 1,3 \n\t"
".insn rre,0xb2650000,2,0 \n\t"
"lr %0,3 \n\t"
: "=d" (time) : : "cc", "1", "2", "3"
);
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
asm volatile (
"lghi 1,3 \n\t"
".insn rre,0xb2650000,2,0 \n\t"
"lgr %0,3 \n\t"
: "=d" (time) : : "cc", "1", "2", "3"
);
-#endif /* CONFIG_ARCH_S390X */
+#endif /* CONFIG_64BIT */
return time;
}
@@ -488,42 +542,21 @@ struct qdio_perf_stats {
#define MY_MODULE_STRING(x) #x
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
#define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x)
-#else /* CONFIG_ARCH_S390X */
+#else /* CONFIG_64BIT */
#define QDIO_GET_ADDR(x) ((__u32)(long)x)
-#endif /* CONFIG_ARCH_S390X */
-
-#ifdef CONFIG_QDIO_DEBUG
-#define set_slsb(x,y) \
- if(q->queue_type==QDIO_TRACE_QTYPE) { \
- if(q->is_input_q) { \
- QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } else { \
- QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } \
- } \
- qdio_set_slsb(x,y); \
- if(q->queue_type==QDIO_TRACE_QTYPE) { \
- if(q->is_input_q) { \
- QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } else { \
- QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
- } \
- }
-#else /* CONFIG_QDIO_DEBUG */
-#define set_slsb(x,y) qdio_set_slsb(x,y)
-#endif /* CONFIG_QDIO_DEBUG */
+#endif /* CONFIG_64BIT */
struct qdio_q {
volatile struct slsb slsb;
char unused[QDIO_MAX_BUFFERS_PER_Q];
- __u32 * volatile dev_st_chg_ind;
+ __u32 * dev_st_chg_ind;
int is_input_q;
- int irq;
+ struct subchannel_id schid;
struct ccw_device *cdev;
unsigned int is_iqdio_q;
@@ -568,6 +601,7 @@ struct qdio_q {
struct tasklet_struct tasklet;
#endif /* QDIO_USE_TIMERS_FOR_POLLING */
+
enum qdio_irq_states state;
/* used to store the error condition during a data transfer */
@@ -617,13 +651,17 @@ struct qdio_irq {
__u32 * volatile dev_st_chg_ind;
unsigned long int_parm;
- int irq;
+ struct subchannel_id schid;
unsigned int is_iqdio_irq;
unsigned int is_thinint_irq;
unsigned int hydra_gives_outbound_pcis;
unsigned int sync_done_on_outb_pcis;
+ /* QEBSM facility */
+ unsigned int is_qebsm;
+ unsigned long sch_token;
+
enum qdio_irq_states state;
unsigned int no_input_qs;
diff --git a/drivers/s390/cio/schid.h b/drivers/s390/cio/schid.h
new file mode 100644
index 000000000000..54328fec5ade
--- /dev/null
+++ b/drivers/s390/cio/schid.h
@@ -0,0 +1,26 @@
+#ifndef S390_SCHID_H
+#define S390_SCHID_H
+
+struct subchannel_id {
+ __u32 reserved:13;
+ __u32 ssid:2;
+ __u32 one:1;
+ __u32 sch_no:16;
+} __attribute__ ((packed,aligned(4)));
+
+
+/* Helper function for sane state of pre-allocated subchannel_id. */
+static inline void
+init_subchannel_id(struct subchannel_id *schid)
+{
+ memset(schid, 0, sizeof(struct subchannel_id));
+ schid->one = 1;
+}
+
+static inline int
+schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)
+{
+ return !memcmp(schid1, schid2, sizeof(struct subchannel_id));
+}
+
+#endif /* S390_SCHID_H */
diff --git a/drivers/s390/crypto/z90common.h b/drivers/s390/crypto/z90common.h
index e319e78b5ea2..f87c785f2039 100644
--- a/drivers/s390/crypto/z90common.h
+++ b/drivers/s390/crypto/z90common.h
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90common.h
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -91,12 +91,13 @@ enum hdstat {
#define TSQ_FATAL_ERROR 34
#define RSQ_FATAL_ERROR 35
-#define Z90CRYPT_NUM_TYPES 5
+#define Z90CRYPT_NUM_TYPES 6
#define PCICA 0
#define PCICC 1
#define PCIXCC_MCL2 2
#define PCIXCC_MCL3 3
#define CEX2C 4
+#define CEX2A 5
#define NILDEV -1
#define ANYDEV -1
#define PCIXCC_UNK -2
@@ -105,7 +106,7 @@ enum hdevice_type {
PCICC_HW = 3,
PCICA_HW = 4,
PCIXCC_HW = 5,
- OTHER_HW = 6,
+ CEX2A_HW = 6,
CEX2C_HW = 7
};
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 0a3bb5a10dd4..3a18443fdfa7 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90crypt.h
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -29,11 +29,11 @@
#include <linux/ioctl.h>
-#define VERSION_Z90CRYPT_H "$Revision: 1.11 $"
+#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
#define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support
+#define z90crypt_VARIANT 3 // 3 = CEX2A support
/**
* struct ica_rsa_modexpo
@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt {
* Z90STAT_CEX2CCOUNT
* Return an integer count of all CEX2Cs.
*
+ * Z90STAT_CEX2ACOUNT
+ * Return an integer count of all CEX2As.
+ *
* Z90STAT_REQUESTQ_COUNT
* Return an integer count of the number of entries waiting to be
* sent to a device.
@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt {
* 0x03: PCIXCC_MCL2
* 0x04: PCIXCC_MCL3
* 0x05: CEX2C
+ * 0x06: CEX2A
* 0x0d: device is disabled via the proc filesystem
*
* Z90STAT_QDEPTH_MASK
@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt {
#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
diff --git a/drivers/s390/crypto/z90hardware.c b/drivers/s390/crypto/z90hardware.c
index c215e0889736..d7f7494a0cbe 100644
--- a/drivers/s390/crypto/z90hardware.c
+++ b/drivers/s390/crypto/z90hardware.c
@@ -1,9 +1,9 @@
/*
* linux/drivers/s390/crypto/z90hardware.c
*
- * z90crypt 1.3.2
+ * z90crypt 1.3.3
*
- * Copyright (C) 2001, 2004 IBM Corporation
+ * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com)
*
@@ -648,6 +648,87 @@ static struct cca_public_sec static_cca_pub_sec = {
#define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724
+struct type50_hdr {
+ u8 reserved1;
+ u8 msg_type_code;
+ u16 msg_len;
+ u8 reserved2;
+ u8 ignored;
+ u16 reserved3;
+};
+
+#define TYPE50_TYPE_CODE 0x50
+
+#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg))
+#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg))
+#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg))
+#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg))
+
+#define TYPE50_MEB1_FMT 0x0001
+#define TYPE50_MEB2_FMT 0x0002
+#define TYPE50_CRB1_FMT 0x0011
+#define TYPE50_CRB2_FMT 0x0012
+
+struct type50_meb1_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 exponent[128];
+ u8 modulus[128];
+ u8 message[128];
+};
+
+struct type50_meb2_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 exponent[256];
+ u8 modulus[256];
+ u8 message[256];
+};
+
+struct type50_crb1_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 p[64];
+ u8 q[64];
+ u8 dp[64];
+ u8 dq[64];
+ u8 u[64];
+ u8 message[128];
+};
+
+struct type50_crb2_msg {
+ struct type50_hdr header;
+ u16 keyblock_type;
+ u8 reserved[6];
+ u8 p[128];
+ u8 q[128];
+ u8 dp[128];
+ u8 dq[128];
+ u8 u[128];
+ u8 message[256];
+};
+
+union type50_msg {
+ struct type50_meb1_msg meb1;
+ struct type50_meb2_msg meb2;
+ struct type50_crb1_msg crb1;
+ struct type50_crb2_msg crb2;
+};
+
+struct type80_hdr {
+ u8 reserved1;
+ u8 type;
+ u16 len;
+ u8 code;
+ u8 reserved2[3];
+ u8 reserved3[8];
+};
+
+#define TYPE80_RSP_CODE 0x80
+
struct error_hdr {
unsigned char reserved1;
unsigned char type;
@@ -657,6 +738,7 @@ struct error_hdr {
};
#define TYPE82_RSP_CODE 0x82
+#define TYPE88_RSP_CODE 0x88
#define REP82_ERROR_MACHINE_FAILURE 0x10
#define REP82_ERROR_PREEMPT_FAILURE 0x12
@@ -679,6 +761,22 @@ struct error_hdr {
#define REP82_ERROR_PACKET_TRUNCATED 0xA0
#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
+#define REP88_ERROR_MODULE_FAILURE 0x10
+#define REP88_ERROR_MODULE_TIMEOUT 0x11
+#define REP88_ERROR_MODULE_NOTINIT 0x13
+#define REP88_ERROR_MODULE_NOTAVAIL 0x14
+#define REP88_ERROR_MODULE_DISABLED 0x15
+#define REP88_ERROR_MODULE_IN_DIAGN 0x17
+#define REP88_ERROR_FASTPATH_DISABLD 0x19
+#define REP88_ERROR_MESSAGE_TYPE 0x20
+#define REP88_ERROR_MESSAGE_MALFORMD 0x22
+#define REP88_ERROR_MESSAGE_LENGTH 0x23
+#define REP88_ERROR_RESERVED_FIELD 0x24
+#define REP88_ERROR_KEY_TYPE 0x34
+#define REP88_ERROR_INVALID_KEY 0x82
+#define REP88_ERROR_OPERAND 0x84
+#define REP88_ERROR_OPERAND_EVEN_MOD 0x85
+
#define CALLER_HEADER 12
static inline int
@@ -687,7 +785,7 @@ testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%4 \n"
" slgr 1,1 \n"
" lgr 2,1 \n"
@@ -757,7 +855,7 @@ resetq(int q_nr, struct ap_status_word *stat_p)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%2 \n"
" lghi 1,1 \n"
" sll 1,24 \n"
@@ -823,7 +921,7 @@ sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat)
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" lgr 6,%3 \n"
" llgfr 7,%2 \n"
" llgt 0,0(6) \n"
@@ -902,7 +1000,7 @@ rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id,
int ccode;
asm volatile
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
(" llgfr 0,%2 \n"
" lgr 3,%4 \n"
" lgr 6,%3 \n"
@@ -1029,10 +1127,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
stat = HD_ONLINE;
*q_depth = t_depth + 1;
switch (t_dev_type) {
- case OTHER_HW:
- stat = HD_NOT_THERE;
- *dev_type = NILDEV;
- break;
case PCICA_HW:
*dev_type = PCICA;
break;
@@ -1045,6 +1139,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
case CEX2C_HW:
*dev_type = CEX2C;
break;
+ case CEX2A_HW:
+ *dev_type = CEX2A;
+ break;
default:
*dev_type = NILDEV;
break;
@@ -2029,6 +2126,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
return 0;
}
+static int
+ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
+ union type50_msg *z90cMsg_p)
+{
+ int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
+ unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
+ union type50_msg *tmp_type50_msg;
+
+ mod_len = icaMex_p->inputdatalength;
+
+ msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) +
+ CALLER_HEADER;
+
+ memset(z90cMsg_p, 0, msg_size);
+
+ tmp_type50_msg = (union type50_msg *)
+ ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+ tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE;
+
+ if (mod_len <= 128) {
+ tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN;
+ tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT;
+ mod_tgt = tmp_type50_msg->meb1.modulus;
+ mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus);
+ exp_tgt = tmp_type50_msg->meb1.exponent;
+ exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent);
+ inp_tgt = tmp_type50_msg->meb1.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->meb1.message);
+ } else {
+ tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN;
+ tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT;
+ mod_tgt = tmp_type50_msg->meb2.modulus;
+ mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus);
+ exp_tgt = tmp_type50_msg->meb2.exponent;
+ exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent);
+ inp_tgt = tmp_type50_msg->meb2.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->meb2.message);
+ }
+
+ mod_tgt += (mod_tgt_len - mod_len);
+ if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(mod_tgt, mod_len))
+ return SEN_USER_ERROR;
+ exp_tgt += (exp_tgt_len - mod_len);
+ if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(exp_tgt, mod_len))
+ return SEN_USER_ERROR;
+ inp_tgt += (inp_tgt_len - mod_len);
+ if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(inp_tgt, mod_len))
+ return SEN_USER_ERROR;
+
+ *z90cMsg_l_p = msg_size - CALLER_HEADER;
+
+ return 0;
+}
+
+static int
+ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
+ int *z90cMsg_l_p, union type50_msg *z90cMsg_p)
+{
+ int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
+ dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset;
+ unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt,
+ temp[8];
+ union type50_msg *tmp_type50_msg;
+
+ mod_len = icaMsg_p->inputdatalength;
+ short_len = mod_len / 2;
+ long_len = mod_len / 2 + 8;
+ long_offset = 0;
+
+ if (long_len > 128) {
+ memset(temp, 0x00, sizeof(temp));
+ if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128))
+ return SEN_RELEASED;
+ if (!is_empty(temp, 8))
+ return SEN_NOT_AVAIL;
+ long_offset = long_len - 128;
+ long_len = 128;
+ }
+
+ tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) +
+ CALLER_HEADER;
+
+ memset(z90cMsg_p, 0, tmp_size);
+
+ tmp_type50_msg = (union type50_msg *)
+ ((unsigned char *) z90cMsg_p + CALLER_HEADER);
+
+ tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE;
+ if (long_len <= 64) {
+ tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN;
+ tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT;
+ p_tgt = tmp_type50_msg->crb1.p;
+ p_tgt_len = sizeof(tmp_type50_msg->crb1.p);
+ q_tgt = tmp_type50_msg->crb1.q;
+ q_tgt_len = sizeof(tmp_type50_msg->crb1.q);
+ dp_tgt = tmp_type50_msg->crb1.dp;
+ dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp);
+ dq_tgt = tmp_type50_msg->crb1.dq;
+ dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq);
+ u_tgt = tmp_type50_msg->crb1.u;
+ u_tgt_len = sizeof(tmp_type50_msg->crb1.u);
+ inp_tgt = tmp_type50_msg->crb1.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->crb1.message);
+ } else {
+ tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN;
+ tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT;
+ p_tgt = tmp_type50_msg->crb2.p;
+ p_tgt_len = sizeof(tmp_type50_msg->crb2.p);
+ q_tgt = tmp_type50_msg->crb2.q;
+ q_tgt_len = sizeof(tmp_type50_msg->crb2.q);
+ dp_tgt = tmp_type50_msg->crb2.dp;
+ dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp);
+ dq_tgt = tmp_type50_msg->crb2.dq;
+ dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq);
+ u_tgt = tmp_type50_msg->crb2.u;
+ u_tgt_len = sizeof(tmp_type50_msg->crb2.u);
+ inp_tgt = tmp_type50_msg->crb2.message;
+ inp_tgt_len = sizeof(tmp_type50_msg->crb2.message);
+ }
+
+ p_tgt += (p_tgt_len - long_len);
+ if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(p_tgt, long_len))
+ return SEN_USER_ERROR;
+ q_tgt += (q_tgt_len - short_len);
+ if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
+ return SEN_RELEASED;
+ if (is_empty(q_tgt, short_len))
+ return SEN_USER_ERROR;
+ dp_tgt += (dp_tgt_len - long_len);
+ if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(dp_tgt, long_len))
+ return SEN_USER_ERROR;
+ dq_tgt += (dq_tgt_len - short_len);
+ if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
+ return SEN_RELEASED;
+ if (is_empty(dq_tgt, short_len))
+ return SEN_USER_ERROR;
+ u_tgt += (u_tgt_len - long_len);
+ if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len))
+ return SEN_RELEASED;
+ if (is_empty(u_tgt, long_len))
+ return SEN_USER_ERROR;
+ inp_tgt += (inp_tgt_len - mod_len);
+ if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
+ return SEN_RELEASED;
+ if (is_empty(inp_tgt, mod_len))
+ return SEN_USER_ERROR;
+
+ *z90cMsg_l_p = tmp_size - CALLER_HEADER;
+
+ return 0;
+}
+
int
convert_request(unsigned char *buffer, int func, unsigned short function,
int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
@@ -2071,6 +2339,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
cdx, msg_l_p, (struct type6_msg *) msg_p,
dev_type);
}
+ if (dev_type == CEX2A) {
+ if (func == ICARSACRT)
+ return ICACRT_msg_to_type50CRT_msg(
+ (struct ica_rsa_modexpo_crt *) buffer,
+ msg_l_p, (union type50_msg *) msg_p);
+ else
+ return ICAMEX_msg_to_type50MEX_msg(
+ (struct ica_rsa_modexpo *) buffer,
+ msg_l_p, (union type50_msg *) msg_p);
+ }
return 0;
}
@@ -2081,8 +2359,8 @@ unset_ext_bitlens(void)
{
if (!ext_bitlens_msg_count) {
PRINTK("Unable to use coprocessors for extended bitlengths. "
- "Using PCICAs (if present) for extended bitlengths. "
- "This is not an error.\n");
+ "Using PCICAs/CEX2As (if present) for extended "
+ "bitlengths. This is not an error.\n");
ext_bitlens_msg_count++;
}
ext_bitlens = 0;
@@ -2094,6 +2372,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
{
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
struct error_hdr *errh_p = (struct error_hdr *) response;
+ struct type80_hdr *t80h_p = (struct type80_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;
@@ -2108,6 +2387,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_l = 0;
switch (errh_p->type) {
case TYPE82_RSP_CODE:
+ case TYPE88_RSP_CODE:
reply_code = errh_p->reply_code;
src_p = (unsigned char *)errh_p;
PRINTK("Hardware error: Type %02X Message Header: "
@@ -2116,6 +2396,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
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;
+ case TYPE80_RSP_CODE:
+ src_l = icaMsg_p->outputdatalength;
+ src_p = response + (int)t80h_p->len - src_l;
+ break;
case TYPE84_RSP_CODE:
src_l = icaMsg_p->outputdatalength;
src_p = response + (int)t84h_p->len - src_l;
@@ -2202,6 +2486,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (reply_code)
switch (reply_code) {
case REP82_ERROR_OPERAND_INVALID:
+ case REP88_ERROR_MESSAGE_MALFORMD:
return REC_OPERAND_INV;
case REP82_ERROR_OPERAND_SIZE:
return REC_OPERAND_SIZE;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 4010f2bb85af..2f54d033d7cf 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -30,11 +30,9 @@
#include <linux/delay.h> // mdelay
#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>
#include <linux/proc_fs.h>
#include <linux/syscalls.h>
#include "z90crypt.h"
@@ -229,7 +227,7 @@ struct device_x {
*/
struct device {
int dev_type; // PCICA, PCICC, PCIXCC_MCL2,
- // PCIXCC_MCL3, CEX2C
+ // PCIXCC_MCL3, CEX2C, CEX2A
enum devstat dev_stat; // current device status
int dev_self_x; // Index in array
int disabled; // Set when device is in error
@@ -296,26 +294,30 @@ struct caller {
/**
* Function prototypes from z90hardware.c
*/
-enum hdstat query_online(int, int, int, int *, int *);
-enum devstat reset_device(int, int, int);
-enum devstat send_to_AP(int, int, int, unsigned char *);
-enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *);
-int convert_request(unsigned char *, int, short, int, int, int *,
- unsigned char *);
-int convert_response(unsigned char *, unsigned char *, int *, unsigned char *);
+enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
+ int *dev_type);
+enum devstat reset_device(int deviceNr, int cdx, int resetNr);
+enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
+enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
+ unsigned char *resp, unsigned char *psmid);
+int convert_request(unsigned char *buffer, int func, unsigned short function,
+ int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
+int convert_response(unsigned char *response, unsigned char *buffer,
+ int *respbufflen_p, unsigned char *resp_buff);
/**
* Low level function prototypes
*/
-static int create_z90crypt(int *);
-static int refresh_z90crypt(int *);
-static int find_crypto_devices(struct status *);
-static int create_crypto_device(int);
-static int destroy_crypto_device(int);
+static int create_z90crypt(int *cdx_p);
+static int refresh_z90crypt(int *cdx_p);
+static int find_crypto_devices(struct status *deviceMask);
+static int create_crypto_device(int index);
+static int destroy_crypto_device(int index);
static void destroy_z90crypt(void);
-static int refresh_index_array(struct status *, struct device_x *);
-static int probe_device_type(struct device *);
-static int probe_PCIXCC_type(struct device *);
+static int refresh_index_array(struct status *status_str,
+ struct device_x *index_array);
+static int probe_device_type(struct device *devPtr);
+static int probe_PCIXCC_type(struct device *devPtr);
/**
* proc fs definitions
@@ -426,7 +428,7 @@ static struct miscdevice z90crypt_misc_device = {
MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
"and Jochen Roehrig");
MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
- "Copyright 2001, 2004 IBM Corporation");
+ "Copyright 2001, 2005 IBM Corporation");
MODULE_LICENSE("GPL");
module_param(domain, int, 0);
MODULE_PARM_DESC(domain, "domain index for device");
@@ -861,6 +863,12 @@ get_status_CEX2Ccount(void)
}
static inline int
+get_status_CEX2Acount(void)
+{
+ return z90crypt.hdware_info->type_mask[CEX2A].st_count;
+}
+
+static inline int
get_status_requestq_count(void)
{
return requestq_count;
@@ -1009,11 +1017,13 @@ static inline int
select_device_type(int *dev_type_p, int bytelength)
{
static int count = 0;
- int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use;
+ int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
+ index_to_use;
struct status *stat;
if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
(*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
- (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV))
+ (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
+ (*dev_type_p != ANYDEV))
return -1;
if (*dev_type_p != ANYDEV) {
stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
@@ -1023,7 +1033,13 @@ select_device_type(int *dev_type_p, int bytelength)
return -1;
}
- /* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */
+ /**
+ * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
+ * speed.
+ *
+ * PCICA and CEX2A do NOT co-exist, so it would be either one or the
+ * other present.
+ */
stat = &z90crypt.hdware_info->type_mask[PCICA];
PCICA_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
@@ -1033,29 +1049,38 @@ select_device_type(int *dev_type_p, int bytelength)
stat = &z90crypt.hdware_info->type_mask[CEX2C];
CEX2C_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
- if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) {
+ stat = &z90crypt.hdware_info->type_mask[CEX2A];
+ CEX2A_avail = stat->st_count -
+ (stat->disabled_count + stat->user_disabled_count);
+ if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
/**
- * bitlength is a factor, PCICA is the most capable, even with
- * the new MCL for PCIXCC.
+ * bitlength is a factor, PCICA or CEX2A are the most capable,
+ * even with the new MCL for PCIXCC.
*/
if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
- if (!PCICA_avail)
- return -1;
- else {
+ if (PCICA_avail) {
*dev_type_p = PCICA;
return 0;
}
+ if (CEX2A_avail) {
+ *dev_type_p = CEX2A;
+ return 0;
+ }
+ return -1;
}
index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
- CEX2C_avail);
+ CEX2C_avail + CEX2A_avail);
if (index_to_use < PCICA_avail)
*dev_type_p = PCICA;
else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
*dev_type_p = PCIXCC_MCL3;
- else
+ else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
+ CEX2C_avail))
*dev_type_p = CEX2C;
+ else
+ *dev_type_p = CEX2A;
count++;
return 0;
}
@@ -1360,7 +1385,7 @@ build_caller(struct work_element *we_p, short function)
if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
- (we_p->devtype != CEX2C))
+ (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
return SEN_NOT_AVAIL;
memcpy(caller_p->caller_id, we_p->caller_id,
@@ -1429,7 +1454,8 @@ get_crypto_request_buffer(struct work_element *we_p)
if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
- (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) {
+ (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
+ (we_p->devtype != ANYDEV)) {
PRINTK("invalid device type\n");
return SEN_USER_ERROR;
}
@@ -1504,8 +1530,9 @@ get_crypto_request_buffer(struct work_element *we_p)
function = PCI_FUNC_KEY_ENCRYPT;
switch (we_p->devtype) {
- /* PCICA does everything with a simple RSA mod-expo operation */
+ /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
case PCICA:
+ case CEX2A:
function = PCI_FUNC_KEY_ENCRYPT;
break;
/**
@@ -1663,7 +1690,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
* trigger a fallback to software.
*/
case -EINVAL:
- if (we_p->devtype != PCICA)
+ if ((we_p->devtype != PCICA) &&
+ (we_p->devtype != CEX2A))
rv = -EGETBUFF;
break;
case -ETIMEOUT:
@@ -1780,6 +1808,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ret = -EFAULT;
break;
+ case Z90STAT_CEX2ACOUNT:
+ tempstat = get_status_CEX2Acount();
+ if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
+ ret = -EFAULT;
+ break;
+
case Z90STAT_REQUESTQ_COUNT:
tempstat = get_status_requestq_count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
@@ -2020,6 +2054,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
get_status_PCIXCCMCL3count());
len += sprintf(resp_buff+len, "CEX2C count: %d\n",
get_status_CEX2Ccount());
+ len += sprintf(resp_buff+len, "CEX2A count: %d\n",
+ get_status_CEX2Acount());
len += sprintf(resp_buff+len, "requestq count: %d\n",
get_status_requestq_count());
len += sprintf(resp_buff+len, "pendingq count: %d\n",
@@ -2027,8 +2063,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
get_status_totalopen_count());
len += sprinthx(
- "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), "
- "4: PCIXCC (MCL3), 5: CEX2C",
+ "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
+ "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
resp_buff+len,
get_status_status_mask(workarea),
Z90CRYPT_NUM_APS);
@@ -2141,6 +2177,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
case '3': // PCIXCC_MCL2
case '4': // PCIXCC_MCL3
case '5': // CEX2C
+ case '6': // CEX2A
j++;
break;
case 'd':
@@ -3008,7 +3045,9 @@ create_crypto_device(int index)
z90crypt.hdware_info->device_type_array[index] = 4;
else if (deviceType == CEX2C)
z90crypt.hdware_info->device_type_array[index] = 5;
- else
+ else if (deviceType == CEX2A)
+ z90crypt.hdware_info->device_type_array[index] = 6;
+ else // No idea how this would happen.
z90crypt.hdware_info->device_type_array[index] = -1;
}
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index a7efc394515e..548854754921 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -1,5 +1,5 @@
menu "S/390 network device drivers"
- depends on NETDEVICES && ARCH_S390
+ depends on NETDEVICES && S390
config LCS
tristate "Lan Channel Station Interface"
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 6b63d21612ec..e70af7f39946 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -1603,7 +1603,7 @@ dumpit(char* buf, int len)
__u32 ct, sw, rm, dup;
char *ptr, *rptr;
char tbuf[82], tdup[82];
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
char addr[22];
#else
char addr[12];
@@ -1619,7 +1619,7 @@ dumpit(char* buf, int len)
dup = 0;
for ( ct=0; ct < len; ct++, ptr++, rptr++ ) {
if (sw == 0) {
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
sprintf(addr, "%16.16lX",(unsigned long)rptr);
#else
sprintf(addr, "%8.8X",(__u32)rptr);
@@ -1634,7 +1634,7 @@ dumpit(char* buf, int len)
if (sw == 8) {
strcat(bhex, " ");
}
-#if (CONFIG_ARCH_S390X)
+#if (CONFIG_64BIT)
sprintf(tbuf,"%2.2lX", (unsigned long)*ptr);
#else
sprintf(tbuf,"%2.2X", (__u32)*ptr);
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 0db4f57a6a95..1901feef07d9 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
+ * $Id: ctcmain.c,v 1.79 2006/01/11 11:32:18 cohuck Exp $
*
* CTC / ESCON network driver
*
@@ -8,7 +8,7 @@
* Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
* Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
*
* Documentation used:
* - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -37,7 +37,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.79 $
*
*/
#undef DEBUG
@@ -248,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.78 $";
+ char vbuf[] = "$Revision: 1.79 $";
char *version = vbuf;
if (printed)
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 968f2c113efe..93d1725eb79b 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -101,25 +102,17 @@ static spinlock_t ctc_tty_lock;
static int
ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
{
- int c;
int len;
struct tty_struct *tty;
DBF_TEXT(trace, 5, __FUNCTION__);
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- c = TTY_FLIPBUF_SIZE - tty->flip.count;
len = skb->len;
- if (c >= len) {
- memcpy(tty->flip.char_buf_ptr, skb->data, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty_flip_buffer_push(tty);
- kfree_skb(skb);
- return 1;
- }
+ tty_insert_flip_string(tty, skb->data, len);
+ tty_flip_buffer_push(tty);
+ kfree_skb(skb);
+ return 1;
}
}
return 0;
@@ -138,19 +131,12 @@ ctc_tty_readmodem(ctc_tty_info *info)
DBF_TEXT(trace, 5, __FUNCTION__);
if ((tty = info->tty)) {
if (info->mcr & UART_MCR_RTS) {
- int c = TTY_FLIPBUF_SIZE - tty->flip.count;
struct sk_buff *skb;
- if ((c > 0) && (skb = skb_dequeue(&info->rx_queue))) {
+ if ((skb = skb_dequeue(&info->rx_queue))) {
int len = skb->len;
- if (len > c)
- len = c;
- memcpy(tty->flip.char_buf_ptr, skb->data, len);
+ tty_insert_flip_string(tty, skb->data, len);
skb_pull(skb, len);
- memset(tty->flip.flag_buf_ptr, 0, len);
- tty->flip.count += len;
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
tty_flip_buffer_push(tty);
if (skb->len > 0)
skb_queue_head(&info->rx_queue, skb);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 0075894c71db..2014fb7a4881 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,11 +1,11 @@
/*
- * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
+ * $Id: cu3088.c,v 1.38 2006/01/12 14:33:09 cohuck Exp $
*
* CTC / LCS ccw_device driver
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Arnd Bergmann <arndb@de.ibm.com>
- * Cornelia Huck <cohuck@de.ibm.com>
+ * Cornelia Huck <cornelia.huck@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
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/err.h>
+#include <asm/s390_rdev.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index df7647c3c100..ea8177392564 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
+ * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $
*
* IUCV network driver
*
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $
*
*/
@@ -54,7 +54,7 @@
#include <asm/s390_ext.h>
#include <asm/ebcdic.h>
#include <asm/smp.h>
-#include <asm/ccwdev.h> //for root device stuff
+#include <asm/s390_rdev.h>
/* FLAGS:
* All flags are defined in the field IPFLAGS1 of each function
@@ -355,7 +355,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.45 $";
+ char vbuf[] = "$Revision: 1.47 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
@@ -477,7 +477,7 @@ grab_param(void)
ptr++;
if (ptr >= iucv_param_pool + PARAM_POOL_SIZE)
ptr = iucv_param_pool;
- } while (atomic_compare_and_swap(0, 1, &ptr->in_use));
+ } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0);
hint = ptr - iucv_param_pool;
memset(&ptr->param, 0, sizeof(ptr->param));
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 69425a7a6e98..ac4c4b83fe17 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,12 +1,13 @@
/*
- * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
+ * $Id: netiucv.c,v 1.69 2006/01/12 14:33:09 cohuck Exp $
*
* IUCV network driver
*
* Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
*
- * Driverfs integration and all bugs therein by Cornelia Huck(cohuck@de.ibm.com)
+ * Sysfs integration and all bugs therein by Cornelia Huck
+ * (cornelia.huck@de.ibm.com)
*
* Documentation used:
* the source of the original IUCV driver by:
@@ -30,7 +31,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.69 $
*
*/
@@ -2076,7 +2077,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.66 $";
+ char vbuf[] = "$Revision: 1.69 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index f8f55cc468ba..97f927c01a82 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -65,6 +65,7 @@
#include <asm/timex.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
+#include <asm/s390_rdev.h>
#include "qeth.h"
#include "qeth_mpc.h"
@@ -1396,7 +1397,7 @@ qeth_idx_activate_get_answer(struct qeth_channel *channel,
channel->ccw.cda = (__u32) __pa(iob->data);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(setup, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
@@ -1463,7 +1464,7 @@ qeth_idx_activate_channel(struct qeth_channel *channel,
memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&channel->irq_pending) == 0);
+ atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(setup, 6, "noirqpnd");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev,
@@ -1616,7 +1617,7 @@ qeth_issue_next_read(struct qeth_card *card)
}
qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->read.irq_pending) == 0);
+ atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0);
QETH_DBF_TEXT(trace, 6, "noirqpnd");
rc = ccw_device_start(card->read.ccwdev, &card->read.ccw,
(addr_t) iob, 0, 0);
@@ -1882,7 +1883,7 @@ qeth_send_control_data(struct qeth_card *card, int len,
spin_unlock_irqrestore(&card->lock, flags);
QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN);
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob);
if (IS_IPA(iob->data))
timer.expires = jiffies + QETH_IPA_TIMEOUT;
@@ -1924,7 +1925,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len,
QETH_DBF_TEXT(trace, 5, "osndctrd");
wait_event(card->wait_q,
- atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0);
+ atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
qeth_prepare_control_data(card, len, iob);
QETH_DBF_TEXT(trace, 6, "osnoirqp");
spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
@@ -4236,9 +4237,8 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
QETH_DBF_TEXT(trace, 6, "dosndpfa");
/* spin until we get the queue ... */
- while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
- QETH_OUT_Q_LOCKED,
- &queue->state));
+ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
/* ... now we've got the queue */
index = queue->next_buf_to_fill;
buffer = &queue->bufs[queue->next_buf_to_fill];
@@ -4292,9 +4292,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
QETH_DBF_TEXT(trace, 6, "dosndpkt");
/* spin until we get the queue ... */
- while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
- QETH_OUT_Q_LOCKED,
- &queue->state));
+ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED,
+ QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED);
start_index = queue->next_buf_to_fill;
buffer = &queue->bufs[queue->next_buf_to_fill];
/*
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
new file mode 100644
index 000000000000..206518c7d332
--- /dev/null
+++ b/drivers/s390/s390_rdev.c
@@ -0,0 +1,53 @@
+/*
+ * drivers/s390/s390_rdev.c
+ * s390 root device
+ * $Revision: 1.4 $
+ *
+ * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
+ * IBM Corporation
+ * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
+ * Carsten Otte (cotte@de.ibm.com)
+ */
+
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <asm/s390_rdev.h>
+
+static void
+s390_root_dev_release(struct device *dev)
+{
+ kfree(dev);
+}
+
+struct device *
+s390_root_dev_register(const char *name)
+{
+ struct device *dev;
+ int ret;
+
+ if (!strlen(name))
+ return ERR_PTR(-EINVAL);
+ dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+ memset(dev, 0, sizeof(struct device));
+ strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
+ dev->release = s390_root_dev_release;
+ ret = device_register(dev);
+ if (ret) {
+ kfree(dev);
+ return ERR_PTR(ret);
+ }
+ return dev;
+}
+
+void
+s390_root_dev_unregister(struct device *dev)
+{
+ if (dev)
+ device_unregister(dev);
+}
+
+EXPORT_SYMBOL(s390_root_dev_register);
+EXPORT_SYMBOL(s390_root_dev_unregister);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4191fd9d4d11..3bf466603512 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -23,7 +23,7 @@
static struct semaphore m_sem;
-extern int css_process_crw(int);
+extern int css_process_crw(int, int);
extern int chsc_process_crw(void);
extern int chp_process_crw(int, int);
extern void css_reiterate_subchannels(void);
@@ -49,9 +49,10 @@ s390_handle_damage(char *msg)
static int
s390_collect_crw_info(void *param)
{
- struct crw crw;
+ struct crw crw[2];
int ccode, ret, slow;
struct semaphore *sem;
+ unsigned int chain;
sem = (struct semaphore *)param;
/* Set a nice name. */
@@ -59,25 +60,50 @@ s390_collect_crw_info(void *param)
repeat:
down_interruptible(sem);
slow = 0;
+ chain = 0;
while (1) {
- ccode = stcrw(&crw);
+ if (unlikely(chain > 1)) {
+ struct crw tmp_crw;
+
+ printk(KERN_WARNING"%s: Code does not support more "
+ "than two chained crws; please report to "
+ "linux390@de.ibm.com!\n", __FUNCTION__);
+ ccode = stcrw(&tmp_crw);
+ printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
+ "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
+ __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
+ tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
+ tmp_crw.erc, tmp_crw.rsid);
+ printk(KERN_WARNING"%s: This was crw number %x in the "
+ "chain\n", __FUNCTION__, chain);
+ if (ccode != 0)
+ break;
+ chain = tmp_crw.chn ? chain + 1 : 0;
+ continue;
+ }
+ ccode = stcrw(&crw[chain]);
if (ccode != 0)
break;
DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
"chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
- crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc,
- crw.erc, crw.rsid);
+ crw[chain].slct, crw[chain].oflw, crw[chain].chn,
+ crw[chain].rsc, crw[chain].anc, crw[chain].erc,
+ crw[chain].rsid);
/* Check for overflows. */
- if (crw.oflw) {
+ if (crw[chain].oflw) {
pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
css_reiterate_subchannels();
+ chain = 0;
slow = 1;
continue;
}
- switch (crw.rsc) {
+ switch (crw[chain].rsc) {
case CRW_RSC_SCH:
- pr_debug("source is subchannel %04X\n", crw.rsid);
- ret = css_process_crw (crw.rsid);
+ if (crw[0].chn && !chain)
+ break;
+ pr_debug("source is subchannel %04X\n", crw[0].rsid);
+ ret = css_process_crw (crw[0].rsid,
+ chain ? crw[1].rsid : 0);
if (ret == -EAGAIN)
slow = 1;
break;
@@ -85,18 +111,18 @@ repeat:
pr_debug("source is monitoring facility\n");
break;
case CRW_RSC_CPATH:
- pr_debug("source is channel path %02X\n", crw.rsid);
- switch (crw.erc) {
+ pr_debug("source is channel path %02X\n", crw[0].rsid);
+ switch (crw[0].erc) {
case CRW_ERC_IPARM: /* Path has come. */
- ret = chp_process_crw(crw.rsid, 1);
+ ret = chp_process_crw(crw[0].rsid, 1);
break;
case CRW_ERC_PERRI: /* Path has gone. */
case CRW_ERC_PERRN:
- ret = chp_process_crw(crw.rsid, 0);
+ ret = chp_process_crw(crw[0].rsid, 0);
break;
default:
pr_debug("Don't know how to handle erc=%x\n",
- crw.erc);
+ crw[0].erc);
ret = 0;
}
if (ret == -EAGAIN)
@@ -115,6 +141,8 @@ repeat:
pr_debug("unknown source\n");
break;
}
+ /* chain is always 0 or 1 here. */
+ chain = crw[chain].chn ? chain + 1 : 0;
}
if (slow)
queue_work(slow_path_wq, &slow_path_work);
@@ -218,7 +246,7 @@ s390_revalidate_registers(struct mci *mci)
*/
kill_task = 1;
-#ifndef __s390x__
+#ifndef CONFIG_64BIT
asm volatile("ld 0,0(%0)\n"
"ld 2,8(%0)\n"
"ld 4,16(%0)\n"
@@ -227,7 +255,7 @@ s390_revalidate_registers(struct mci *mci)
#endif
if (MACHINE_HAS_IEEE) {
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
fpt_save_area = &S390_lowcore.floating_pt_save_area;
fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
#else
@@ -286,7 +314,7 @@ s390_revalidate_registers(struct mci *mci)
*/
s390_handle_damage("invalid control registers.");
else
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
asm volatile("lctlg 0,15,0(%0)"
: : "a" (&S390_lowcore.cregs_save_area));
#else
@@ -299,7 +327,7 @@ s390_revalidate_registers(struct mci *mci)
* can't write something sensible into that register.
*/
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
/*
* See if we can revalidate the TOD programmable register with its
* old contents (should be zero) otherwise set it to zero.
@@ -356,7 +384,7 @@ s390_do_machine_check(struct pt_regs *regs)
if (mci->b) {
/* Processing backup -> verify if we can survive this */
u64 z_mcic, o_mcic, t_mcic;
-#ifdef __s390x__
+#ifdef CONFIG_64BIT
z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 5e84c5aa7779..167fef39d8a7 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_free_low_mem_buffers(adapter);
/* free memory of adapter data structure and queues */
zfcp_qdio_free_queues(adapter);
+ kfree(adapter->fc_stats);
+ kfree(adapter->stats_reset_data);
ZFCP_LOG_TRACE("freeing adapter structure\n");
kfree(adapter);
out:
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index d81b737d68cc..9bb511083a26 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -921,7 +921,6 @@ struct zfcp_adapter {
u32 physical_s_id; /* local FC port ID */
struct ccw_device *ccw_device; /* S/390 ccw device */
u8 fc_service_class;
- u32 fc_topology; /* FC topology */
u32 hydra_version; /* Hydra version */
u32 fsf_lic_version;
u32 adapter_features; /* FCP channel features */
@@ -978,6 +977,9 @@ struct zfcp_adapter {
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
struct qdio_initialize qdio_init_data; /* for qdio_establish */
struct device generic_services; /* directory for WKA ports */
+ struct fc_host_statistics *fc_stats;
+ struct fsf_qtcb_bottom_port *stats_reset_data;
+ unsigned long stats_reset;
};
/*
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index ee7314d8c2da..c065cb836c97 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
case ZFCP_ERP_STEP_UNINITIALIZED:
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
case ZFCP_ERP_STEP_PORT_CLOSING:
- if (adapter->fc_topology == FSF_TOPO_P2P) {
+ if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
if (port->wwpn != adapter->peer_wwpn) {
ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
"on adapter %s.\nPeer WWPN "
@@ -3403,7 +3403,7 @@ zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
/**
* zfcp_erp_action_cleanup
*
- * Register unit with scsi stack if appropiate and fix reference counts.
+ * Register unit with scsi stack if appropriate and fix reference counts.
* Note: Temporary units are not registered with scsi stack.
*/
static void
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 59587951c847..cbfab09899c8 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
| ZFCP_STATUS_COMMON_ERP_FAILED);
break;
+ case FSF_STATUS_READ_NOTIFICATION_LOST:
+ ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
+ "adapter %s%s%s%s%s%s%s%s%s\n",
+ zfcp_get_busid_by_adapter(adapter),
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_INCOMING_ELS) ?
+ ", incoming ELS" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_SENSE_DATA) ?
+ ", sense data" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_LINK_STATUS) ?
+ ", link status change" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_PORT_CLOSED) ?
+ ", port close" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
+ ", bit error exception" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED) ?
+ ", ACT update" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_HARDENED) ?
+ ", ACT hardening" : "",
+ (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
+ ", adapter feature change" : "");
+
+ if (status_buffer->status_subtype &
+ FSF_STATUS_READ_SUB_ACT_UPDATED)
+ zfcp_erp_adapter_access_changed(adapter);
+ break;
+
case FSF_STATUS_READ_CFDC_UPDATED:
ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
@@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
erp_action->fsf_req->qtcb->bottom.config.feature_selection =
FSF_FEATURE_CFDC |
FSF_FEATURE_LUN_SHARING |
+ FSF_FEATURE_NOTIFICATION_LOST |
FSF_FEATURE_UPDATE_ALERT;
/* start QDIO request for this FSF request */
@@ -2008,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
fc_host_speed(shost) = bottom->fc_link_speed;
fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
- adapter->fc_topology = bottom->fc_topology;
adapter->hydra_version = bottom->adapter_type;
- if (adapter->physical_wwpn == 0)
- adapter->physical_wwpn = fc_host_port_name(shost);
- if (adapter->physical_s_id == 0)
- adapter->physical_s_id = fc_host_port_id(shost);
+ if (fc_host_permanent_port_name(shost) == -1)
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
+ if (bottom->fc_topology == FSF_TOPO_P2P) {
+ adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
+ adapter->peer_wwpn = bottom->plogi_payload.wwpn;
+ adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+ fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+ } else if (bottom->fc_topology == FSF_TOPO_FABRIC)
+ fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+ else if (bottom->fc_topology == FSF_TOPO_AL)
+ fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+ else
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
} else {
fc_host_node_name(shost) = 0;
fc_host_port_name(shost) = 0;
fc_host_port_id(shost) = 0;
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
- adapter->fc_topology = 0;
+ fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
adapter->hydra_version = 0;
}
- if (adapter->fc_topology == FSF_TOPO_P2P) {
- adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
- adapter->peer_wwpn = bottom->plogi_payload.wwpn;
- adapter->peer_wwnn = bottom->plogi_payload.wwnn;
- }
-
if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
adapter->hardware_version = bottom->hardware_version;
memcpy(fc_host_serial_number(shost), bottom->serial_number,
@@ -2097,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
return -EIO;
- switch (adapter->fc_topology) {
- case FSF_TOPO_P2P:
+ switch (fc_host_port_type(adapter->scsi_host)) {
+ case FC_PORTTYPE_PTP:
ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
"configuration detected at adapter %s\n"
"Peer WWNN 0x%016llx, "
@@ -2111,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"top-p-to-p");
break;
- case FSF_TOPO_AL:
+ case FC_PORTTYPE_NLPORT:
ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
"topology detected at adapter %s "
"unsupported, shutting down adapter\n",
@@ -2120,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"top-al");
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
- case FSF_TOPO_FABRIC:
+ case FC_PORTTYPE_NPORT:
ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
zfcp_get_busid_by_adapter(adapter));
@@ -2133,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"of a type known to the zfcp "
"driver, shutting down adapter\n",
zfcp_get_busid_by_adapter(adapter));
- adapter->fc_topology = FSF_TOPO_ERROR;
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"unknown-topo");
zfcp_erp_adapter_shutdown(adapter, 0);
@@ -2293,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
if (data)
memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
- if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
- adapter->physical_wwpn = bottom->wwpn;
- adapter->physical_s_id = bottom->fc_port_id;
- } else {
- adapter->physical_wwpn = fc_host_port_name(shost);
- adapter->physical_s_id = fc_host_port_id(shost);
- }
+ if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+ fc_host_permanent_port_name(shost) = bottom->wwpn;
+ else
+ fc_host_permanent_port_name(shost) =
+ fc_host_port_name(shost);
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+ fc_host_supported_speeds(shost) = bottom->supported_speed;
break;
case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 48719f055952..e734415cae6d 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -166,6 +166,7 @@
#define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004
#define FSF_STATUS_READ_LINK_DOWN 0x00000005
#define FSF_STATUS_READ_LINK_UP 0x00000006
+#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009
#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A
#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B
#define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C
@@ -179,6 +180,16 @@
#define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001
#define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002
+/* status subtypes for unsolicited status notification lost */
+#define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001
+#define FSF_STATUS_READ_SUB_SENSE_DATA 0x00000002
+#define FSF_STATUS_READ_SUB_LINK_STATUS 0x00000004
+#define FSF_STATUS_READ_SUB_PORT_CLOSED 0x00000008
+#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD 0x00000010
+#define FSF_STATUS_READ_SUB_ACT_UPDATED 0x00000020
+#define FSF_STATUS_READ_SUB_ACT_HARDENED 0x00000040
+#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
+
/* status subtypes for CFDC */
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002
#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
@@ -188,7 +199,6 @@
#define FSF_TOPO_P2P 0x00000001
#define FSF_TOPO_FABRIC 0x00000002
#define FSF_TOPO_AL 0x00000003
-#define FSF_TOPO_FABRIC_VIRT 0x00000004
/* data direction for FCP commands */
#define FSF_DATADIR_WRITE 0x00000001
@@ -211,6 +221,7 @@
/* channel features */
#define FSF_FEATURE_CFDC 0x00000002
#define FSF_FEATURE_LUN_SHARING 0x00000004
+#define FSF_FEATURE_NOTIFICATION_LOST 0x00000008
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 66608d13a634..3c2cbcccbf54 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8,
static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
scsi_lun_t);
-static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
- scsi_id_t);
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
@@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
return retval;
}
-static struct zfcp_port *
-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 (port->rport && (id == port->rport->scsi_target_id))
- return port;
- }
- return (struct zfcp_port *) NULL;
-}
-
/**
* zfcp_scsi_eh_abort_handler - abort the specified SCSI command
* @scpnt: pointer to scsi_cmnd to be aborted
@@ -731,70 +717,164 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
/*
* Support functions for FC transport class
*/
-static void
-zfcp_get_port_id(struct scsi_target *starget)
+static struct fc_host_statistics*
+zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ struct fc_host_statistics *fc_stats;
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_port_id(starget) = port->d_id;
- else
- fc_starget_port_id(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ if (!adapter->fc_stats) {
+ fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
+ if (!fc_stats)
+ return NULL;
+ adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
+ }
+ memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
+ return adapter->fc_stats;
}
static void
-zfcp_get_port_name(struct scsi_target *starget)
+zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data,
+ struct fsf_qtcb_bottom_port *old)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
+ old->seconds_since_last_reset;
+ fc_stats->tx_frames = data->tx_frames - old->tx_frames;
+ fc_stats->tx_words = data->tx_words - old->tx_words;
+ fc_stats->rx_frames = data->rx_frames - old->rx_frames;
+ fc_stats->rx_words = data->rx_words - old->rx_words;
+ fc_stats->lip_count = data->lip - old->lip;
+ fc_stats->nos_count = data->nos - old->nos;
+ fc_stats->error_frames = data->error_frames - old->error_frames;
+ fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
+ fc_stats->link_failure_count = data->link_failure - old->link_failure;
+ fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
+ fc_stats->loss_of_signal_count = data->loss_of_signal -
+ old->loss_of_signal;
+ fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
+ old->psp_error_counts;
+ fc_stats->invalid_tx_word_count = data->invalid_tx_words -
+ old->invalid_tx_words;
+ fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
+ fc_stats->fcp_input_requests = data->input_requests -
+ old->input_requests;
+ fc_stats->fcp_output_requests = data->output_requests -
+ old->output_requests;
+ fc_stats->fcp_control_requests = data->control_requests -
+ old->control_requests;
+ fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
+ fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
+}
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_port_name(starget) = port->wwpn;
- else
- fc_starget_port_name(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+static void
+zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data)
+{
+ fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
+ fc_stats->tx_frames = data->tx_frames;
+ fc_stats->tx_words = data->tx_words;
+ fc_stats->rx_frames = data->rx_frames;
+ fc_stats->rx_words = data->rx_words;
+ fc_stats->lip_count = data->lip;
+ fc_stats->nos_count = data->nos;
+ fc_stats->error_frames = data->error_frames;
+ fc_stats->dumped_frames = data->dumped_frames;
+ fc_stats->link_failure_count = data->link_failure;
+ fc_stats->loss_of_sync_count = data->loss_of_sync;
+ fc_stats->loss_of_signal_count = data->loss_of_signal;
+ fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
+ fc_stats->invalid_tx_word_count = data->invalid_tx_words;
+ fc_stats->invalid_crc_count = data->invalid_crcs;
+ fc_stats->fcp_input_requests = data->input_requests;
+ fc_stats->fcp_output_requests = data->output_requests;
+ fc_stats->fcp_control_requests = data->control_requests;
+ fc_stats->fcp_input_megabytes = data->input_mb;
+ fc_stats->fcp_output_megabytes = data->output_mb;
+}
+
+/**
+ * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
+ *
+ * assumption: scsi_transport_fc synchronizes calls of
+ * get_fc_host_stats and reset_fc_host_stats
+ * (XXX to be checked otherwise introduce locking)
+ */
+static struct fc_host_statistics *
+zfcp_get_fc_host_stats(struct Scsi_Host *shost)
+{
+ struct zfcp_adapter *adapter;
+ struct fc_host_statistics *fc_stats;
+ struct fsf_qtcb_bottom_port *data;
+ int ret;
+
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ fc_stats = zfcp_init_fc_host_stats(adapter);
+ if (!fc_stats)
+ return NULL;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+ memset(data, 0, sizeof(*data));
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret) {
+ kfree(data);
+ return NULL; /* XXX return zeroed fc_stats? */
+ }
+
+ if (adapter->stats_reset &&
+ ((jiffies/HZ - adapter->stats_reset) <
+ data->seconds_since_last_reset)) {
+ zfcp_adjust_fc_host_stats(fc_stats, data,
+ adapter->stats_reset_data);
+ } else
+ zfcp_set_fc_host_stats(fc_stats, data);
+
+ kfree(data);
+ return fc_stats;
}
static void
-zfcp_get_node_name(struct scsi_target *starget)
+zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
- struct zfcp_port *port;
- unsigned long flags;
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_port *data, *old_data;
+ int ret;
- read_lock_irqsave(&zfcp_data.config_lock, flags);
- port = zfcp_port_lookup(adapter, starget->channel, starget->id);
- if (port)
- fc_starget_node_name(starget) = port->wwnn;
- else
- fc_starget_node_name(starget) = -1;
- read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+ memset(data, 0, sizeof(*data));
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret == 0) {
+ adapter->stats_reset = jiffies/HZ;
+ old_data = adapter->stats_reset_data;
+ adapter->stats_reset_data = data; /* finally freed in
+ adater_dequeue */
+ kfree(old_data);
+ }
}
struct fc_function_template zfcp_transport_functions = {
- .get_starget_port_id = zfcp_get_port_id,
- .get_starget_port_name = zfcp_get_port_name,
- .get_starget_node_name = zfcp_get_node_name,
.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_permanent_port_name = 1,
.show_host_supported_classes = 1,
+ .show_host_supported_speeds = 1,
.show_host_maxframe_size = 1,
.show_host_serial_number = 1,
+ .get_fc_host_stats = zfcp_get_fc_host_stats,
+ .reset_fc_host_stats = zfcp_reset_fc_host_stats,
+ /* no functions registered for following dynamic attributes but
+ directly set by LLDD */
+ .show_host_port_type = 1,
.show_host_speed = 1,
.show_host_port_id = 1,
};
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 0cd435280e7d..9f262250043a 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -33,14 +33,6 @@
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
-static const char fc_topologies[5][25] = {
- "<error>",
- "point-to-point",
- "fabric",
- "arbitrated loop",
- "fabric (virt. adapter)"
-};
-
/**
* ZFCP_DEFINE_ADAPTER_ATTR
* @_name: name of show attribute
@@ -69,12 +61,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
- fc_topologies[adapter->fc_topology]);
ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
adapter->hardware_version);
-ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
@@ -259,9 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_physical_s_id.attr,
&dev_attr_card_version.attr,
&dev_attr_lic_version.attr,
- &dev_attr_fc_service_class.attr,
- &dev_attr_fc_topology.attr,
- &dev_attr_scsi_host_no.attr,
&dev_attr_status.attr,
&dev_attr_hardware_version.attr,
NULL
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index c55e82d91deb..3924eb38805c 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_
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(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
@@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = {
&dev_attr_failed.attr,
&dev_attr_in_recovery.attr,
&dev_attr_status.attr,
- &dev_attr_wwnn.attr,
- &dev_attr_d_id.attr,
&dev_attr_access_denied.attr,
NULL
};
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 0556642c9e1d..2f50815f65c7 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_
static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
-ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
zfcp_sysfs_unit_failed_store);
static struct attribute *zfcp_unit_attrs[] = {
- &dev_attr_scsi_lun.attr,
&dev_attr_failed.attr,
&dev_attr_in_recovery.attr,
&dev_attr_status.attr,
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 87c2db1bd4f5..66da840c9316 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -106,7 +106,7 @@ static inline int stsi (void *sysinfo,
{
int cc, retv;
-#ifndef CONFIG_ARCH_S390X
+#ifndef CONFIG_64BIT
__asm__ __volatile__ ( "lr\t0,%2\n"
"\tlr\t1,%3\n"
"\tstsi\t0(%4)\n"
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index 92e6c5639dd3..015db40ad8a4 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = {
/* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/
static unsigned char * tmp_buf = NULL;
-static DECLARE_MUTEX(tmp_buf_sem);
DECLARE_TASK_QUEUE(tq_aurora);
diff --git a/drivers/scsi/.gitignore b/drivers/scsi/.gitignore
new file mode 100644
index 000000000000..b385af314356
--- /dev/null
+++ b/drivers/scsi/.gitignore
@@ -0,0 +1,3 @@
+53c700_d.h
+53c7xx_d.h
+53c7xx_u.h
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 3ff74f472249..31c497542272 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -73,6 +73,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
void __user *argp = (void __user *)arg;
/* Only let one of these through at a time */
- if (down_interruptible(&tw_dev->ioctl_sem)) {
+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
retval = TW_IOCTL_ERROR_OS_EINTR;
goto out;
}
@@ -852,7 +853,7 @@ out3:
/* Now free ioctl buf memory */
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
out2:
- up(&tw_dev->ioctl_sem);
+ mutex_unlock(&tw_dev->ioctl_lock);
out:
return retval;
} /* End twa_chrdev_ioctl() */
@@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev)
tw_dev->error_sequence_id = 1;
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- init_MUTEX(&tw_dev->ioctl_sem);
+ mutex_init(&tw_dev->ioctl_lock);
init_waitqueue_head(&tw_dev->ioctl_wqueue);
retval = 0;
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 46f22cdc8298..1b16d57f0314 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension {
u32 ioctl_msec;
int chrdev_request_id;
wait_queue_head_t ioctl_wqueue;
- struct semaphore ioctl_sem;
+ struct mutex ioctl_lock;
char aen_clobber;
unsigned short working_srl;
unsigned short working_branch;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 283f6d25892b..25f678d0780b 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -203,6 +203,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/time.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
/* Only let one of these through at a time */
- if (down_interruptible(&tw_dev->ioctl_sem))
+ if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
return -EINTR;
/* First copy down the buffer length */
@@ -1029,7 +1030,7 @@ out2:
/* Now free ioctl buf memory */
dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
out:
- up(&tw_dev->ioctl_sem);
+ mutex_unlock(&tw_dev->ioctl_lock);
return retval;
} /* End tw_chrdev_ioctl() */
@@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
tw_dev->pending_tail = TW_Q_START;
tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
- init_MUTEX(&tw_dev->ioctl_sem);
+ mutex_init(&tw_dev->ioctl_lock);
init_waitqueue_head(&tw_dev->ioctl_wqueue);
return 0;
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 4f81fc39ec57..31fe5ea15920 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension {
u32 max_sector_count;
u32 aen_count;
struct Scsi_Host *host;
- struct semaphore ioctl_sem;
+ struct mutex ioctl_lock;
unsigned short aen_queue[TW_Q_LENGTH];
unsigned char aen_head;
unsigned char aen_tail;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index e7ad269041a4..4ce7438608ec 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -857,7 +857,7 @@ process_extended_message(struct Scsi_Host *host,
printk(KERN_INFO "scsi%d (%d:%d): Unexpected message %s: ",
host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
- scsi_print_msg(hostdata->msgin);
+ spi_print_msg(hostdata->msgin);
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
@@ -887,7 +887,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
#ifdef NCR_700_DEBUG
printk("scsi%d (%d:%d): message %s: ", host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
- scsi_print_msg(hostdata->msgin);
+ spi_print_msg(hostdata->msgin);
printk("\n");
#endif
@@ -939,7 +939,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
host->host_no, pun, lun,
NCR_700_phase[(dsps & 0xf00) >> 8]);
- scsi_print_msg(hostdata->msgin);
+ spi_print_msg(hostdata->msgin);
printk("\n");
/* just reject it */
hostdata->msgout[0] = A_REJECT_MSG;
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index 362d78483d09..a8c83bb03630 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -238,21 +238,23 @@ struct NCR_700_Host_Parameters {
#ifdef CONFIG_53C700_LE_ON_BE
#define bE (hostdata->force_le_on_be ? 0 : 3)
#define bSWAP (hostdata->force_le_on_be)
-/* This is terrible, but there's no raw version of ioread32. That means
- * that on a be board we swap twice (once in ioread32 and once again to
- * get the value correct) */
-#define bS_to_io(x) ((hostdata->force_le_on_be) ? (x) : cpu_to_le32(x))
+#define bEBus (!hostdata->force_le_on_be)
#elif defined(__BIG_ENDIAN)
#define bE 3
#define bSWAP 0
-#define bS_to_io(x) (x)
#elif defined(__LITTLE_ENDIAN)
#define bE 0
#define bSWAP 0
-#define bS_to_io(x) (x)
#else
#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined, did you include byteorder.h?"
#endif
+#ifndef bEBus
+#ifdef CONFIG_53C700_BE_BUS
+#define bEBus 1
+#else
+#define bEBus 0
+#endif
+#endif
#define bS_to_cpu(x) (bSWAP ? le32_to_cpu(x) : (x))
#define bS_to_host(x) (bSWAP ? cpu_to_le32(x) : (x))
@@ -466,14 +468,15 @@ NCR_700_readl(struct Scsi_Host *host, __u32 reg)
{
const struct NCR_700_Host_Parameters *hostdata
= (struct NCR_700_Host_Parameters *)host->hostdata[0];
- __u32 value = ioread32(hostdata->base + reg);
+ __u32 value = bEBus ? ioread32be(hostdata->base + reg) :
+ ioread32(hostdata->base + reg);
#if 1
/* sanity check the register */
if((reg & 0x3) != 0)
BUG();
#endif
- return bS_to_io(value);
+ return value;
}
static inline void
@@ -497,7 +500,8 @@ NCR_700_writel(__u32 value, struct Scsi_Host *host, __u32 reg)
BUG();
#endif
- iowrite32(bS_to_io(value), hostdata->base + reg);
+ bEBus ? iowrite32be(value, hostdata->base + reg):
+ iowrite32(value, hostdata->base + reg);
}
#endif
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 9cb5dd48383f..7894b8ea84bd 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -282,6 +282,7 @@
#include "scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
#include "53c7xx.h"
#include <linux/stat.h>
#include <linux/stddef.h>
@@ -1724,7 +1725,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
printk ("scsi%d : status ", host->host_no);
scsi_print_status (status);
printk ("\nscsi%d : message ", host->host_no);
- scsi_print_msg (&msg);
+ spi_print_msg(&msg);
printk ("\n");
} else if (hostdata->test_completed == 3) {
printk("scsi%d : test 2 no connection with target %d\n",
@@ -2313,7 +2314,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct
printk ("scsi%d : received message", host->host_no);
if (c)
printk (" from target %d lun %d ", c->device->id, c->device->lun);
- scsi_print_msg ((unsigned char *) hostdata->msg_buf);
+ spi_print_msg((unsigned char *) hostdata->msg_buf);
printk("\n");
}
@@ -5540,7 +5541,7 @@ print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
i > 0 && !check_address ((unsigned long) ptr, 1);
ptr += len, i -= len) {
printk(" ");
- len = scsi_print_msg (ptr);
+ len = spi_print_msg(ptr);
printk("\n");
if (!len)
break;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 9d6040bfa064..1c459343292b 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void)
HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
HostAdapter->Bus = ProbeInfo->Bus;
HostAdapter->Device = ProbeInfo->Device;
+ HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
/*
@@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void)
scsi_host_put(Host);
} else {
BusLogic_InitializeHostStructure(HostAdapter, Host);
- scsi_add_host(Host, NULL);
+ scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
scsi_scan_host(Host);
BusLogicHostAdapterCount++;
}
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 5beed4f6d985..8d64f0bed628 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -149,7 +149,7 @@ typedef SCCBMGR_INFO * PSCCBMGR_INFO;
#define PCI_BUS_CARD 0x03
#define VESA_BUS_CARD 0x04
-/* SCCB struc used for both SCCB and UCB manager compiles!
+/* SCCB struct used for both SCCB and UCB manager compiles!
* The UCB Manager treats the SCCB as it's 'native hardware structure'
*/
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 20dd85a77813..3c606cf8c8ca 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -336,6 +336,7 @@ config SCSI_ACARD
config SCSI_AHA152X
tristate "Adaptec AHA152X/2825 support"
depends on ISA && SCSI && !64BIT
+ select SCSI_SPI_ATTRS
---help---
This is a driver for the AHA-1510, AHA-1520, AHA-1522, and AHA-2825
SCSI host adapters. It also works for the AVA-1505, but the IRQ etc.
@@ -623,6 +624,7 @@ config SCSI_OMIT_FLASHPOINT
config SCSI_DMX3191D
tristate "DMX3191D SCSI support"
depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
help
This is support for Domex DMX3191D SCSI Host Adapters.
@@ -632,6 +634,7 @@ config SCSI_DMX3191D
config SCSI_DTC3280
tristate "DTC3180/3280 SCSI support"
depends on ISA && SCSI
+ select SCSI_SPI_ATTRS
help
This is support for DTC 3180/3280 SCSI Host Adapters. Please read
the SCSI-HOWTO, available from
@@ -752,6 +755,7 @@ config SCSI_GDTH
config SCSI_GENERIC_NCR5380
tristate "Generic NCR5380/53c400 SCSI PIO support"
depends on ISA && SCSI
+ select SCSI_SPI_ATTRS
---help---
This is a driver for the old NCR 53c80 series of SCSI controllers
on boards using PIO. Most boards such as the Trantor T130 fit this
@@ -771,6 +775,7 @@ config SCSI_GENERIC_NCR5380
config SCSI_GENERIC_NCR5380_MMIO
tristate "Generic NCR5380/53c400 SCSI MMIO support"
depends on ISA && SCSI
+ select SCSI_SPI_ATTRS
---help---
This is a driver for the old NCR 53c80 series of SCSI controllers
on boards using memory mapped I/O.
@@ -909,7 +914,7 @@ config SCSI_INIA100
config SCSI_PPA
tristate "IOMEGA parallel port (ppa - older drives)"
- depends on SCSI && PARPORT
+ depends on SCSI && PARPORT_PC
---help---
This driver supports older versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -936,7 +941,7 @@ config SCSI_PPA
config SCSI_IMM
tristate "IOMEGA parallel port (imm - newer drives)"
- depends on SCSI && PARPORT
+ depends on SCSI && PARPORT_PC
---help---
This driver supports newer versions of IOMEGA's parallel port ZIP
drive (a 100 MB removable media device).
@@ -963,7 +968,7 @@ config SCSI_IMM
config SCSI_IZIP_EPP16
bool "ppa/imm option - Use slow (but safe) EPP-16"
- depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+ depends on SCSI_PPA || SCSI_IMM
---help---
EPP (Enhanced Parallel Port) is a standard for parallel ports which
allows them to act as expansion buses that can handle up to 64
@@ -978,7 +983,7 @@ config SCSI_IZIP_EPP16
config SCSI_IZIP_SLOW_CTR
bool "ppa/imm option - Assume slow parport control register"
- depends on PARPORT && (SCSI_PPA || SCSI_IMM)
+ depends on SCSI_PPA || SCSI_IMM
help
Some parallel ports are known to have excessive delays between
changing the parallel port control register and good data being
@@ -1254,6 +1259,7 @@ config SCSI_MCA_53C9X
config SCSI_PAS16
tristate "PAS16 SCSI support"
depends on ISA && SCSI
+ select SCSI_SPI_ATTRS
---help---
This is support for a SCSI host adapter. It is explained in section
3.10 of the SCSI-HOWTO, available from
@@ -1423,6 +1429,7 @@ config SCSI_DC390T
config SCSI_T128
tristate "Trantor T128/T128F/T228 SCSI support"
depends on ISA && SCSI
+ select SCSI_SPI_ATTRS
---help---
This is support for a SCSI host adapter. It is explained in section
3.11 of the SCSI-HOWTO, available from
@@ -1681,6 +1688,7 @@ config OKTAGON_SCSI
config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI && BROKEN
+ select SCSI_SPI_ATTRS
---help---
If you have an Atari with built-in NCR5380 SCSI controller (TT,
Falcon, ...) say Y to get it supported. Of course also, if you have
@@ -1722,6 +1730,7 @@ config TT_DMA_EMUL
config MAC_SCSI
bool "Macintosh NCR5380 SCSI"
depends on MAC && SCSI=y
+ select SCSI_SPI_ATTRS
help
This is the NCR 5380 SCSI controller included on most of the 68030
based Macintoshes. If you have one of these say Y and read the
@@ -1743,6 +1752,7 @@ config SCSI_MAC_ESP
config MVME147_SCSI
bool "WD33C93 SCSI driver for MVME147"
depends on MVME147 && SCSI=y
+ select SCSI_SPI_ATTRS
help
Support for the on-board SCSI controller on the Motorola MVME147
single-board computer.
@@ -1750,6 +1760,7 @@ config MVME147_SCSI
config MVME16x_SCSI
bool "NCR53C710 SCSI driver for MVME16x"
depends on MVME16x && SCSI && BROKEN
+ select SCSI_SPI_ATTRS
help
The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710
SCSI controller chip. Almost everyone using one of these boards
@@ -1758,6 +1769,7 @@ config MVME16x_SCSI
config BVME6000_SCSI
bool "NCR53C710 SCSI driver for BVME6000"
depends on BVME6000 && SCSI && BROKEN
+ select SCSI_SPI_ATTRS
help
The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710
SCSI controller chip. Almost everyone using one of these boards
@@ -1774,6 +1786,7 @@ config SCSI_NCR53C7xx_FAST
config SUN3_SCSI
tristate "Sun3 NCR5380 SCSI"
depends on SUN3 && SCSI && BROKEN
+ select SCSI_SPI_ATTRS
help
This option will enable support for the OBIO (onboard io) NCR5380
SCSI controller found in the Sun 3/50 and 3/60, as well as for
@@ -1802,7 +1815,7 @@ config SCSI_SUNESP
config ZFCP
tristate "FCP host bus adapter driver for IBM eServer zSeries"
- depends on ARCH_S390 && QDIO && SCSI
+ depends on S390 && QDIO && SCSI
select SCSI_FC_ATTRS
help
If you want to access SCSI devices attached to your IBM eServer
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index f062ea0f813a..320e765fa0cd 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o
obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o
obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o
obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o
-obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp.o oktagon_io.o
+obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o
obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o
@@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o qlogicfas.o
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogicfas408.o
obj-$(CONFIG_SCSI_QLOGIC_FC) += qlogicfc.o
obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o
-obj-$(CONFIG_SCSI_QLA2XXX) += qla2xxx/
+obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/
obj-$(CONFIG_SCSI_LPFC) += lpfc/
obj-$(CONFIG_SCSI_PAS16) += pas16.o
obj-$(CONFIG_SCSI_SEAGATE) += seagate.o
@@ -164,6 +164,7 @@ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
zalon7xx-objs := zalon.o ncr53c8xx.o
NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o
libata-objs := libata-core.o libata-scsi.o
+oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o
# Files generated that shall be removed upon make clean
clean-files := 53c7xx_d.h 53c700_d.h \
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index cba9655d0f14..9f0ddbe6dc76 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -87,6 +87,7 @@
* the high level code.
*/
#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
#ifndef NDEBUG
#define NDEBUG 0
@@ -2377,7 +2378,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
* 3..length+1 arguments
*
* Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.
+ * byte, since spi_print_msg() wants the whole thing.
*/
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
@@ -2424,7 +2425,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
default:
if (!tmp) {
printk("scsi%d: rejecting message ", instance->host_no);
- scsi_print_msg(extended_msg);
+ spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
scmd_printk(KERN_INFO, cmd,
@@ -2560,7 +2561,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
if (!(msg[0] & 0x80)) {
printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no);
- scsi_print_msg(msg);
+ spi_print_msg(msg);
abort = 1;
} else {
/* Accept message by clearing ACK */
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 640590bd014a..c7dd0154d012 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -1799,6 +1799,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
*/
int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */
int fifocnt = 0;
+ unsigned char *p = phys_to_virt((unsigned long)SCptr->SCp.ptr);
oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK;
@@ -1860,7 +1861,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
/* read fifo */
for(j=0;j<fifocnt;j++)
- SCptr->SCp.ptr[i++] = esp_read(eregs->esp_fdata);
+ p[i++] = esp_read(eregs->esp_fdata);
ESPDATA(("(%d) ", i));
@@ -1882,7 +1883,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
/* fill fifo */
for(j=0;j<this_count;j++)
- esp_write(eregs->esp_fdata, SCptr->SCp.ptr[i++]);
+ esp_write(eregs->esp_fdata, p[i++]);
/* how many left if this goes out ?? */
hmuch -= this_count;
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
deleted file mode 100644
index 4193865d419c..000000000000
--- a/drivers/scsi/aacraid/README
+++ /dev/null
@@ -1,74 +0,0 @@
-AACRAID Driver for Linux (take two)
-
-Introduction
--------------------------
-The aacraid driver adds support for Adaptec (http://www.adaptec.com)
-RAID controllers. This is a major rewrite from the original
-Adaptec supplied driver. It has signficantly cleaned up both the code
-and the running binary size (the module is less than half the size of
-the original).
-
-Supported Cards/Chipsets
--------------------------
- Adaptec 2020S
- Adaptec 2025S
- Adaptec 2120S
- Adaptec 2130S
- Adaptec 2200S
- Adaptec 2230S
- Adaptec 2240S
- Adaptec 2410SA
- Adaptec 2610SA
- Adaptec 2810SA
- Adaptec 21610SA
- Adaptec 3230S
- Adaptec 3240S
- Adaptec 4000SAS
- Adaptec 4005SAS
- Adaptec 4800SAS
- Adaptec 4805SAS
- Adaptec 5400S
- Dell PERC 2 Quad Channel
- Dell PERC 2/Si
- Dell PERC 3/Si
- Dell PERC 3/Di
- Dell CERC 2
- HP NetRAID-4M
- Legend S220
- Legend S230
- IBM ServeRAID 8i
- ICP 9014R0
- ICP 9024R0
- ICP 9047MA
- ICP 9087MA
- ICP 9085LI
- ICP 5085AU
-
-People
--------------------------
-Alan Cox <alan@redhat.com>
-Christoph Hellwig <hch@infradead.org> (updates for new-style PCI probing and SCSI host registration,
- small cleanups/fixes)
-Matt Domsch <matt_domsch@dell.com> (revision ioctl, adapter messages)
-Deanna Bonds (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
- added new ioctls, changed scsi interface to use new error handler,
- increased the number of fibs and outstanding commands to a container)
-
- (fixed 64bit and 64G memory model, changed confusing naming convention
- where fibs that go to the hardware are consistently called hw_fibs and
- not just fibs like the name of the driver tracking structure)
-Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
-
-Original Driver
--------------------------
-Adaptec Unix OEM Product Group
-
-Mailing List
--------------------------
-linux-scsi@vger.kernel.org (Interested parties troll here)
-Also note this is very different to Brian's original driver
-so don't expect him to support it.
-Adaptec does support this driver. Contact either tech support or Mark Salyzyn.
-
-Original by Brian Boerner February 2001
-Rewritten by Alan Cox, November 2001
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 30fd8d6e3f31..66dbb6d2c506 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -532,6 +532,13 @@ struct aac_driver_ident
#define AAC_QUIRK_MASTER 0x0008
/*
+ * Some adapter firmware perform poorly when it must split up scatter gathers
+ * in order to deal with the limits of the underlying CHIM. This limit in this
+ * class of adapters is 17 scatter gather elements.
+ */
+#define AAC_QUIRK_17SG 0x0010
+
+/*
* The adapter interface specs all queues to be located in the same
* physically contigous block. The host structure that defines the
* commuication queues will assume they are each a separate physically
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index ef623bd965f5..4fe79cd7c957 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
if (size < le16_to_cpu(kfib->header.SenderSize))
size = le16_to_cpu(kfib->header.SenderSize);
if (size > dev->max_fib_size) {
+ if (size > 2048) {
+ retval = -EINVAL;
+ goto cleanup;
+ }
/* Highjack the hw_fib */
hw_fib = fibptr->hw_fib;
hw_fib_pa = fibptr->hw_fib_pa;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 3cb68af90456..0bf5f9a943e8 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -46,7 +46,6 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
-#include <linux/ioctl32.h>
#include <linux/delay.h>
#include <linux/smp_lock.h>
#include <asm/semaphore.h>
@@ -201,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = {
{ 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) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
- { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
- { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+ { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2026ZCR ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2610SA ", 1 }, /* SATA 6Ch (Bearcat) */
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2240S ", 1 }, /* ASR-2240S (SabreExpress) */
@@ -575,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev,
struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
int len;
- len = snprintf(buf, PAGE_SIZE, "%s\n",
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+ char * cp = dev->supplement_adapter_info.AdapterTypeText;
+ while (*cp && *cp != ' ')
+ ++cp;
+ while (*cp == ' ')
+ ++cp;
+ len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
+ } else
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
aac_drivers[dev->cardtype].model);
return len;
}
@@ -586,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
int len;
- len = snprintf(buf, PAGE_SIZE, "%s\n",
+ if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+ char * cp = dev->supplement_adapter_info.AdapterTypeText;
+ while (*cp && *cp != ' ')
+ ++cp;
+ len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+ (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
+ dev->supplement_adapter_info.AdapterTypeText);
+ } else
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
aac_drivers[dev->cardtype].vname);
return len;
}
@@ -838,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
= (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
}
+ if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
+ (aac->scsi_host_ptr->sg_tablesize > 17)) {
+ aac->scsi_host_ptr->sg_tablesize = 17;
+ aac->scsi_host_ptr->max_sectors
+ = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
+
/*
* Firware printf works only with older firmware.
*/
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 9df23b654cec..cb2ee25f213f 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -259,6 +259,7 @@
#include "scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
#include "aha152x.h"
@@ -1845,7 +1846,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
#if defined(AHA152X_DEBUG)
if (HOSTDATA(shpnt)->debug & debug_msgi) {
printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0));
- scsi_print_msg(&MSGI(0));
+ spi_print_msg(&MSGI(0));
printk("\n");
}
#endif
@@ -1933,7 +1934,7 @@ static void msgi_run(struct Scsi_Host *shpnt)
break;
printk(INFO_LEAD, CMDINFO(CURRENT_SC));
- scsi_print_msg(&MSGI(0));
+ spi_print_msg(&MSGI(0));
printk("\n");
ticks = (MSGI(3) * 4 + 49) / 50;
@@ -2031,7 +2032,7 @@ static void msgo_init(struct Scsi_Host *shpnt)
int i;
printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC));
- for (i=0; i<MSGOLEN; i+=scsi_print_msg(&MSGO(i)), printk(" "))
+ for (i=0; i<MSGOLEN; i+=spi_print_msg(&MSGO(i)), printk(" "))
;
printk(")\n");
}
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 83467a05dc8e..19bd346951dd 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -214,7 +214,6 @@ static struct scsi_host_template ahci_sht = {
.dma_boundary = AHCI_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations ahci_ops = {
@@ -243,7 +242,7 @@ static const struct ata_port_operations ahci_ops = {
.port_stop = ahci_port_stop,
};
-static struct ata_port_info ahci_port_info[] = {
+static const struct ata_port_info ahci_port_info[] = {
/* board_ahci */
{
.sht = &ahci_sht,
@@ -277,6 +276,16 @@ static const struct pci_device_id ahci_pci_tbl[] = {
board_ahci }, /* ESB2 */
{ PCI_VENDOR_ID_INTEL, 0x27c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH7-M DH */
+ { PCI_VENDOR_ID_INTEL, 0x2821, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2822, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2824, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8 */
+ { PCI_VENDOR_ID_INTEL, 0x2829, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
+ { PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_ahci }, /* ICH8M */
{ } /* terminate list */
};
@@ -643,7 +652,8 @@ static void ahci_eng_timeout(struct ata_port *ap)
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
- ata_qc_complete(qc, AC_ERR_OTHER);
+ qc->err_mask |= AC_ERR_OTHER;
+ ata_qc_complete(qc);
}
spin_unlock_irqrestore(&host_set->lock, flags);
@@ -664,7 +674,8 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
ci = readl(port_mmio + PORT_CMD_ISSUE);
if (likely((ci & 0x1) == 0)) {
if (qc) {
- ata_qc_complete(qc, 0);
+ assert(qc->err_mask == 0);
+ ata_qc_complete(qc);
qc = NULL;
}
}
@@ -681,8 +692,10 @@ static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
/* command processing has stopped due to error; restart */
ahci_restart_port(ap, status);
- if (qc)
- ata_qc_complete(qc, err_mask);
+ if (qc) {
+ qc->err_mask |= AC_ERR_OTHER;
+ ata_qc_complete(qc);
+ }
}
return 1;
diff --git a/drivers/scsi/aic7xxx/.gitignore b/drivers/scsi/aic7xxx/.gitignore
new file mode 100644
index 000000000000..b8ee24d5748a
--- /dev/null
+++ b/drivers/scsi/aic7xxx/.gitignore
@@ -0,0 +1,6 @@
+aic79xx_reg.h
+aic79xx_reg_print.c
+aic79xx_seq.h
+aic7xxx_reg.h
+aic7xxx_reg_print.c
+aic7xxx_seq.h
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index ac8de03c9fa2..6c2c395554ff 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE
config AIC7XXX_RESET_DELAY_MS
int "Initial bus reset delay in milli-seconds"
depends on SCSI_AIC7XXX
- default "15000"
+ default "5000"
---help---
The number of milliseconds to delay after an initial bus reset.
The bus settle delay following all error recovery actions is
dictated by the SCSI layer and is not affected by this value.
- Default: 15000 (15 seconds)
+ Default: 5000 (5 seconds)
config AIC7XXX_PROBE_EISA_VL
bool "Probe for EISA and VL AIC7XXX Adapters"
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index 653fb0b42aea..2cfdbef447db 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.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/aic79xx.h#95 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
*
* $FreeBSD$
*/
@@ -75,8 +75,7 @@ struct scb_platform_data;
#define INITIATOR_WILDCARD (~0)
#define SCB_LIST_NULL 0xFF00
#define SCB_LIST_NULL_LE (ahd_htole16(SCB_LIST_NULL))
-#define QOUTFIFO_ENTRY_VALID 0x8000
-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
+#define QOUTFIFO_ENTRY_VALID 0x80
#define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
#define SCSIID_TARGET(ahd, scsiid) \
@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
typedef void ahd_callback_t (void *);
+struct ahd_completion
+{
+ uint16_t tag;
+ uint8_t sg_status;
+ uint8_t valid_tag;
+};
+
struct ahd_softc {
bus_space_tag_t tags[2];
bus_space_handle_t bshs[2];
@@ -1062,6 +1068,7 @@ struct ahd_softc {
struct scb_data scb_data;
struct hardware_scb *next_queued_hscb;
+ struct map_node *next_queued_hscb_map;
/*
* SCBs that have been sent to the controller
@@ -1140,16 +1147,23 @@ struct ahd_softc {
ahd_flag flags;
struct seeprom_config *seep_config;
- /* Values to store in the SEQCTL register for pause and unpause */
- uint8_t unpause;
- uint8_t pause;
-
/* Command Queues */
+ struct ahd_completion *qoutfifo;
uint16_t qoutfifonext;
uint16_t qoutfifonext_valid_tag;
uint16_t qinfifonext;
uint16_t qinfifo[AHD_SCB_MAX];
- uint16_t *qoutfifo;
+
+ /*
+ * Our qfreeze count. The sequencer compares
+ * this value with its own counter to determine
+ * whether to allow selections to occur.
+ */
+ uint16_t qfreeze_cnt;
+
+ /* Values to store in the SEQCTL register for pause and unpause */
+ uint8_t unpause;
+ uint8_t pause;
/* Critical Section Data */
struct cs *critical_sections;
@@ -1197,8 +1211,7 @@ struct ahd_softc {
*/
bus_dma_tag_t parent_dmat;
bus_dma_tag_t shared_data_dmat;
- bus_dmamap_t shared_data_dmamap;
- dma_addr_t shared_data_busaddr;
+ struct map_node shared_data_map;
/* Information saved through suspend/resume cycles */
struct ahd_suspend_state suspend_state;
@@ -1296,9 +1309,9 @@ struct ahd_devinfo {
};
/****************************** PCI Structures ********************************/
-#define AHD_PCI_IOADDR0 PCIR_MAPS /* I/O BAR*/
-#define AHD_PCI_MEMADDR (PCIR_MAPS + 4) /* Memory BAR */
-#define AHD_PCI_IOADDR1 (PCIR_MAPS + 12)/* Second I/O BAR */
+#define AHD_PCI_IOADDR0 PCIR_BAR(0) /* I/O BAR*/
+#define AHD_PCI_MEMADDR PCIR_BAR(1) /* Memory BAR */
+#define AHD_PCI_IOADDR1 PCIR_BAR(3) /* Second I/O BAR */
typedef int (ahd_device_setup_t)(struct ahd_softc *);
diff --git a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg
index cca58edc8648..3a3204703b15 100644
--- a/drivers/scsi/aic7xxx/aic79xx.reg
+++ b/drivers/scsi/aic7xxx/aic79xx.reg
@@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
mvi MODE_PTR, MK_MODE(src, dst); \
}
-#define TOGGLE_DFF_MODE \
- if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
- call toggle_dff_mode_work_around; \
- } else { \
- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); \
- }
-
#define RESTORE_MODE(mode) \
if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) { \
mov mode call set_mode_work_around; \
@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
/*
* LQ Packet In
- * The last LQ Packet received
+ * The last LQ Packet recieved
*/
register LQIN {
address 0x020
@@ -3542,10 +3535,34 @@ scratch_ram {
COMPLETE_DMA_SCB_HEAD {
size 2
}
- /* Counting semaphore to prevent new select-outs */
+ /*
+ * tail of list of SCBs that have
+ * completed but need to be uploaded
+ * to the host prior to being completed.
+ */
+ COMPLETE_DMA_SCB_TAIL {
+ size 2
+ }
+ /*
+ * head of list of SCBs that have
+ * been uploaded to the host, but cannot
+ * be completed until the QFREEZE is in
+ * full effect (i.e. no selections pending).
+ */
+ COMPLETE_ON_QFREEZE_HEAD {
+ size 2
+ }
+ /*
+ * Counting semaphore to prevent new select-outs
+ * The queue is frozen so long as the sequencer
+ * and kernel freeze counts differ.
+ */
QFREEZE_COUNT {
size 2
}
+ KERNEL_QFREEZE_COUNT {
+ size 2
+ }
/*
* Mode to restore on legacy idle loop exit.
*/
@@ -3625,6 +3642,17 @@ scratch_ram {
size 1
}
/*
+ * Kernel and sequencer offsets into the queue of
+ * incoming target mode command descriptors. The
+ * queue is full when the KERNEL_TQINPOS == TQINPOS.
+ */
+ KERNEL_TQINPOS {
+ size 1
+ }
+ TQINPOS {
+ size 1
+ }
+ /*
* Base address of our shared data with the kernel driver in host
* memory. This includes the qoutfifo and target mode
* incoming command queue.
@@ -3639,17 +3667,6 @@ scratch_ram {
QOUTFIFO_NEXT_ADDR {
size 4
}
- /*
- * Kernel and sequencer offsets into the queue of
- * incoming target mode command descriptors. The
- * queue is full when the KERNEL_TQINPOS == TQINPOS.
- */
- KERNEL_TQINPOS {
- size 1
- }
- TQINPOS {
- size 1
- }
ARG_1 {
size 1
mask SEND_MSG 0x80
@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
const SG_SIZEOF download
const PKT_OVERRUN_BUFOFFSET download
const SCB_TRANSFER_SIZE download
+const CACHELINE_MASK download
/*
* BIOS SCB offsets
diff --git a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq
index 65339bc1ca99..bef1f9d369b6 100644
--- a/drivers/scsi/aic7xxx/aic79xx.seq
+++ b/drivers/scsi/aic7xxx/aic79xx.seq
@@ -40,7 +40,7 @@
* $FreeBSD$
*/
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
PATCH_ARG_LIST = "struct ahd_softc *ahd"
PREFIX = "ahd_"
@@ -68,13 +68,47 @@ no_error_set:
}
SET_MODE(M_SCSI, M_SCSI)
test SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
- test SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
+ test SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;
+ /*
+ * If the kernel has caught up with us, thaw the queue.
+ */
+ mov A, KERNEL_QFREEZE_COUNT;
+ cmp QFREEZE_COUNT, A jne check_frozen_completions;
+ mov A, KERNEL_QFREEZE_COUNT[1];
+ cmp QFREEZE_COUNT[1], A jne check_frozen_completions;
+ and SEQ_FLAGS2, ~SELECTOUT_QFROZEN;
+ jmp check_waiting_list;
+check_frozen_completions:
+ test SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;
+BEGIN_CRITICAL;
+ /*
+ * If we have completions stalled waiting for the qfreeze
+ * to take effect, move them over to the complete_scb list
+ * now that no selections are pending.
+ */
+ cmp COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;
+ /*
+ * Find the end of the qfreeze list. The first element has
+ * to be treated specially.
+ */
+ bmov SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;
+ /*
+ * Now the normal loop.
+ */
+ bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;
+join_lists:
+ bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+ bmov COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;
+ mvi COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;
+ jmp idle_loop_checkbus;
+check_waiting_list:
cmp WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
/*
* ENSELO is cleared by a SELDO, so we must test for SELDO
* one last time.
*/
-BEGIN_CRITICAL;
test SSTAT0, SELDO jnz select_out;
END_CRITICAL;
call start_selection;
@@ -90,6 +124,13 @@ idle_loop_check_nonpackreq:
test SSTAT2, NONPACKREQ jz . + 2;
call unexpected_nonpkt_phase_find_ctxt;
if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on so
+ * long as one of our data FIFOs is active.
+ */
and A, FIFO0FREE|FIFO1FREE, DFFSTAT;
cmp A, FIFO0FREE|FIFO1FREE jne . + 3;
and SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -101,9 +142,9 @@ idle_loop_check_nonpackreq:
call idle_loop_cchan;
jmp idle_loop;
-BEGIN_CRITICAL;
idle_loop_gsfifo:
SET_MODE(M_SCSI, M_SCSI)
+BEGIN_CRITICAL;
idle_loop_gsfifo_in_scsi_mode:
test LQISTAT2, LQIGSAVAIL jz return;
/*
@@ -152,11 +193,15 @@ END_CRITICAL;
idle_loop_service_fifos:
SET_MODE(M_DFF0, M_DFF0)
+BEGIN_CRITICAL;
test LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
call longjmp;
+END_CRITICAL;
idle_loop_next_fifo:
SET_MODE(M_DFF1, M_DFF1)
+BEGIN_CRITICAL;
test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+END_CRITICAL;
return:
ret;
@@ -170,7 +215,6 @@ BEGIN_CRITICAL;
test CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
test CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
test CCSCBCTL, CCSCBDONE jz return;
-END_CRITICAL;
/* FALLTHROUGH */
scbdma_tohost_done:
test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -180,26 +224,18 @@ scbdma_tohost_done:
* bad SCSI status (currently only for underruns), we
* queue the SCB for normal completion. Otherwise, we
* wait until any select-out activity has halted, and
- * then notify the host so that the transaction can be
- * dealt with.
+ * then queue the completion.
*/
- test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
and CCSCBCTL, ~(CCARREN|CCSCBEN);
bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+ cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;
+ mvi COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;
+ test SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
+ bmov SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;
+ bmov COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;
+scbdma_queue_completion:
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
-scbdma_notify_host:
- SET_MODE(M_SCSI, M_SCSI)
- test SCSISEQ0, ENSELO jnz return;
- test SSTAT0, (SELDO|SELINGO) jnz return;
- SET_MODE(M_CCHAN, M_CCHAN)
- /*
- * Remove SCB and notify host.
- */
- and CCSCBCTL, ~(CCARREN|CCSCBEN);
- bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
- SET_SEQINTCODE(BAD_SCB_STATUS)
- ret;
fill_qoutfifo_dmadone:
and CCSCBCTL, ~(CCARREN|CCSCBEN);
call qoutfifo_updated;
@@ -208,6 +244,7 @@ fill_qoutfifo_dmadone:
test QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
bmov QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
xor QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+END_CRITICAL;
qoutfifo_updated:
/*
@@ -324,14 +361,15 @@ fill_qoutfifo:
* Keep track of the SCBs we are dmaing just
* in case the DMA fails or is aborted.
*/
- mov A, QOUTFIFO_ENTRY_VALID_TAG;
bmov COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
mvi CCSCBCTL, CCSCBRESET;
bmov SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
+ mov A, QOUTFIFO_NEXT_ADDR;
bmov SCBPTR, COMPLETE_SCB_HEAD, 2;
fill_qoutfifo_loop:
- mov CCSCBRAM, SCBPTR;
- or CCSCBRAM, A, SCBPTR[1];
+ bmov CCSCBRAM, SCBPTR, 2;
+ mov CCSCBRAM, SCB_SGPTR[0];
+ mov CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;
mov NONE, SDSCB_QOFF;
inc INT_COALESCING_CMDCOUNT;
add CMDS_PENDING, -1;
@@ -339,6 +377,18 @@ fill_qoutfifo_loop:
cmp SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
cmp CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
test QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
+ /*
+ * Don't cross an ADB or Cachline boundary when DMA'ing
+ * completion entries. In PCI mode, at least in 32/33
+ * configurations, the SCB DMA engine may lose its place
+ * in the data-stream should the target force a retry on
+ * something other than an 8byte aligned boundary. In
+ * PCI-X mode, we do this to avoid split transactions since
+ * many chipsets seem to be unable to format proper split
+ * completions to continue the data transfer.
+ */
+ add SINDEX, A, CCSCBADDR;
+ test SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;
bmov SCBPTR, SCB_NEXT_COMPLETE, 2;
jmp fill_qoutfifo_loop;
fill_qoutfifo_done:
@@ -354,7 +404,6 @@ dma_complete_scb:
bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
bmov SCBHADDR, SCB_BUSADDR, 4;
mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
-END_CRITICAL;
/*
* Either post or fetch an SCB from host memory. The caller
@@ -371,9 +420,19 @@ dma_scb:
mvi SCBHCNT, SCB_TRANSFER_SIZE;
mov CCSCBCTL, SINDEX ret;
-BEGIN_CRITICAL;
setjmp:
- bmov LONGJMP_ADDR, STACK, 2 ret;
+ /*
+ * At least on the A, a return in the same
+ * instruction as the bmov results in a return
+ * to the caller, not to the new address at the
+ * top of the stack. Since we want the latter
+ * (we use setjmp to register a handler from an
+ * interrupt context but not invoke that handler
+ * until we return to our idle loop), use a
+ * separate ret instruction.
+ */
+ bmov LONGJMP_ADDR, STACK, 2;
+ ret;
setjmp_inline:
bmov LONGJMP_ADDR, STACK, 2;
longjmp:
@@ -392,11 +451,6 @@ set_mode_work_around:
mvi SEQINTCTL, INTVEC1DSL;
mov MODE_PTR, SINDEX;
clr SEQINTCTL ret;
-
-toggle_dff_mode_work_around:
- mvi SEQINTCTL, INTVEC1DSL;
- xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
- clr SEQINTCTL ret;
}
@@ -490,6 +544,21 @@ allocate_fifo1:
SET_SRC_MODE M_SCSI;
SET_DST_MODE M_SCSI;
select_in:
+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on from
+ * the point of selection until our idle
+ * loop determines that neither of our FIFOs
+ * are busy. This handles the non-packetized
+ * case nicely as we will not return to the
+ * idle loop until the busfree at the end of
+ * each transaction.
+ */
+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;
+ }
if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
/*
* Test to ensure that the bus has not
@@ -528,6 +597,21 @@ SET_SRC_MODE M_SCSI;
SET_DST_MODE M_SCSI;
select_out:
BEGIN_CRITICAL;
+ if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+ /*
+ * On Rev A. hardware, the busy LED is only
+ * turned on automaically during selections
+ * and re-selections. Make the LED status
+ * more useful by forcing it to be on from
+ * the point of re-selection until our idle
+ * loop determines that neither of our FIFOs
+ * are busy. This handles the non-packetized
+ * case nicely as we will not return to the
+ * idle loop until the busfree at the end of
+ * each transaction.
+ */
+ or SBLKCTL, DIAGLEDEN|DIAGLEDON;
+ }
/* Clear out all SCBs that have been successfully sent. */
if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
/*
@@ -1000,15 +1084,9 @@ not_found_ITloop:
/*
* We received a "command complete" message. Put the SCB on the complete
* queue and trigger a completion interrupt via the idle loop. Before doing
- * so, check to see if there
- * is a residual or the status byte is something other than STATUS_GOOD (0).
- * In either of these conditions, we upload the SCB back to the host so it can
- * process this information. In the case of a non zero status byte, we
- * additionally interrupt the kernel driver synchronously, allowing it to
- * decide if sense should be retrieved. If the kernel driver wishes to request
- * sense, it will fill the kernel SCB with a request sense command, requeue
- * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting
- * RETURN_1 to SEND_SENSE.
+ * so, check to see if there is a residual or the status byte is something
+ * other than STATUS_GOOD (0). In either of these conditions, we upload the
+ * SCB back to the host so it can process this information.
*/
mesgin_complete:
@@ -1053,6 +1131,7 @@ complete_nomsg:
call queue_scb_completion;
jmp await_busfree;
+BEGIN_CRITICAL;
freeze_queue:
/* Cancel any pending select-out. */
test SSTAT0, SELDO|SELINGO jnz . + 2;
@@ -1063,6 +1142,7 @@ freeze_queue:
adc QFREEZE_COUNT[1], A;
or SEQ_FLAGS2, SELECTOUT_QFROZEN;
mov A, ACCUM_SAVE ret;
+END_CRITICAL;
/*
* Complete the current FIFO's SCB if data for this same
@@ -1085,8 +1165,10 @@ queue_scb_completion:
test SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
test SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
complete:
+BEGIN_CRITICAL;
bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+END_CRITICAL;
bad_status:
cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
call freeze_queue;
@@ -1097,9 +1179,18 @@ upload_scb:
* it on the host.
*/
bmov SCB_TAG, SCBPTR, 2;
- bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
+BEGIN_CRITICAL;
+ or SCB_SGPTR, SG_STATUS_VALID;
+ mvi SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;
+ cmp COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;
bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
- or SCB_SGPTR, SG_STATUS_VALID ret;
+ bmov COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;
+add_dma_scb_tail:
+ bmov REG0, SCBPTR, 2;
+ bmov SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;
+ bmov SCB_NEXT_COMPLETE, REG0, 2;
+ bmov COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;
+END_CRITICAL;
/*
* Is it a disconnect message? Set a flag in the SCB to remind us
@@ -1146,8 +1237,18 @@ SET_DST_MODE M_DFF1;
await_busfree_clrchn:
mvi DFFSXFRCTL, CLRCHN;
await_busfree_not_m_dff:
- call clear_target_state;
+ /* clear target specific flags */
+ mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
test SSTAT1,REQINIT|BUSFREE jz .;
+ /*
+ * We only set BUSFREE status once either a new
+ * phase has been detected or we are really
+ * BUSFREE. This allows the driver to know
+ * that we are active on the bus even though
+ * no identified transaction exists should a
+ * timeout occur while awaiting busfree.
+ */
+ mvi LASTPHASE, P_BUSFREE;
test SSTAT1, BUSFREE jnz idle_loop;
SET_SEQINTCODE(MISSED_BUSFREE)
@@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo:
call allocate_fifo;
jmp mesgin_done;
-clear_target_state:
- mvi LASTPHASE, P_BUSFREE;
- /* clear target specific flags */
- mvi SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
-
phase_lock:
if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
/*
@@ -1298,6 +1394,47 @@ service_fifo:
test CCSGCTL, CCSGENACK jnz return;
/*
+ * Should the other FIFO get the S/G cache first? If
+ * both FIFOs have been allocated since we last checked
+ * any FIFO, it is important that we service a FIFO
+ * that is not actively on the bus first. This guarantees
+ * that a FIFO will be freed to handle snapshot requests for
+ * any FIFO that is still on the bus. Chips with RTI do not
+ * perform snapshots, so don't bother with this test there.
+ */
+ if ((ahd->features & AHD_RTI) == 0) {
+ /*
+ * If we're not still receiving SCSI data,
+ * it is safe to allocate the S/G cache to
+ * this FIFO.
+ */
+ test DFCNTRL, SCSIEN jz idle_sgfetch_start;
+
+ /*
+ * Switch to the other FIFO. Non-RTI chips
+ * also have the "set mode" bug, so we must
+ * disable interrupts during the switch.
+ */
+ mvi SEQINTCTL, INTVEC1DSL;
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+
+ /*
+ * If the other FIFO needs loading, then it
+ * must not have claimed the S/G cache yet
+ * (SG_CACHE_AVAIL would have been cleared in
+ * the orginal FIFO mode and we test this above).
+ * Return to the idle loop so we can process the
+ * FIFO not currently on the bus first.
+ */
+ test SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;
+ clr SEQINTCTL ret;
+idle_sgfetch_okay:
+ xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+ clr SEQINTCTL;
+ }
+
+idle_sgfetch_start:
+ /*
* We fetch a "cacheline aligned" and sized amount of data
* so we don't end up referencing a non-existant page.
* Cacheline aligned is in quotes because the kernel will
@@ -1308,7 +1445,7 @@ service_fifo:
mvi SGHCNT, SG_PREFETCH_CNT;
if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
/*
- * Need two instruction between "touches" of SGHADDR.
+ * Need two instructions between "touches" of SGHADDR.
*/
nop;
}
@@ -1658,7 +1795,7 @@ export seq_isr:
* savepointer in the current FIFO. We do this so that
* a pending CTXTDONE or SAVEPTR is visible in the active
* FIFO. This status is the only way we can detect if we
- * have lost the race (e.g. host paused us) and our attepts
+ * have lost the race (e.g. host paused us) and our attempts
* to disable the channel occurred after all REQs were
* already seen and acked (REQINIT never comes true).
*/
@@ -1667,7 +1804,7 @@ export seq_isr:
test DFCNTRL, DIRECTION jz interrupt_return;
and DFCNTRL, ~SCSIEN;
snapshot_wait_data_valid:
- test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+ test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
test SSTAT1, REQINIT jz snapshot_wait_data_valid;
snapshot_data_valid:
or DFCNTRL, SCSIEN;
@@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status:
dec SCB_FIFO_USE_COUNT;
test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
mvi DFFSXFRCTL, CLRCHN ret;
-END_CRITICAL;
/*
* LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1843,7 +1979,6 @@ END_CRITICAL;
* Check for overrun and see if we can complete this command.
*/
pkt_last_seg_done:
-BEGIN_CRITICAL;
/*
* Mark transfer as completed.
*/
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 4e8f00df978d..db8f5ce99ee3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_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/aic79xx.c#202 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
*/
#ifdef __linux__
@@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd)
ahd_outb(ahd, SCSISEQ1,
ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+ /*
+ * Clear any pending sequencer interrupt. It is no
+ * longer relevant since we're resetting the Program
+ * Counter.
+ */
+ ahd_outb(ahd, CLRINT, CLRSEQINT);
+
ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
ahd_unpause(ahd);
}
@@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
saved_modes = ahd_save_modes(ahd);
/*
- * Complete any SCBs that just finished being
- * DMA'ed into the qoutfifo.
- */
- ahd_run_qoutfifo(ahd);
-
- /*
- * Flush the good status FIFO for compelted packetized commands.
+ * Flush the good status FIFO for completed packetized commands.
*/
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
saved_scbptr = ahd_get_scbptr(ahd);
@@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
u_int fifo_mode;
u_int i;
- scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
- | ahd_inb(ahd, GSFIFO);
+ scbid = ahd_inw(ahd, GSFIFO);
scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) {
printf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -401,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
* the host before completing the command.
*/
fifo_mode = 0;
+rescan_fifos:
for (i = 0; i < 2; i++) {
/* Toggle to the other mode. */
fifo_mode ^= 1;
ahd_set_modes(ahd, fifo_mode, fifo_mode);
+
if (ahd_scb_active_in_fifo(ahd, scb) == 0)
continue;
ahd_run_data_fifo(ahd, scb);
/*
- * Clearing this transaction in this FIFO may
- * cause a CFG4DATA for this same transaction
- * to assert in the other FIFO. Make sure we
- * loop one more time and check the other FIFO.
+ * Running this FIFO may cause a CFG4DATA for
+ * this same transaction to assert in the other
+ * FIFO or a new snapshot SAVEPTRS interrupt
+ * in this FIFO. Even running a FIFO may not
+ * clear the transaction if we are still waiting
+ * for data to drain to the host. We must loop
+ * until the transaction is not active in either
+ * FIFO just to be sure. Reset our loop counter
+ * so we will visit both FIFOs again before
+ * declaring this transaction finished. We
+ * also delay a bit so that status has a chance
+ * to change before we look at this FIFO again.
*/
- i = 0;
+ ahd_delay(200);
+ goto rescan_fifos;
}
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
ahd_set_scbptr(ahd, scbid);
@@ -429,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
/*
* The transfer completed with a residual.
* Place this SCB on the complete DMA list
- * so that we Update our in-core copy of the
+ * so that we update our in-core copy of the
* SCB before completing the command.
*/
ahd_outb(ahd, SCB_SCSI_STATUS, 0);
ahd_outb(ahd, SCB_SGPTR,
ahd_inb_scbram(ahd, SCB_SGPTR)
| SG_STATUS_VALID);
- ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+ ahd_outw(ahd, SCB_TAG, scbid);
+ ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
- ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
- if (SCBID_IS_NULL(comp_head))
- ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
- SCB_GET_TAG(scb));
+ if (SCBID_IS_NULL(comp_head)) {
+ ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+ } else {
+ u_int tail;
+
+ tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
+ ahd_set_scbptr(ahd, tail);
+ ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+ ahd_set_scbptr(ahd, scbid);
+ }
} else
ahd_complete_scb(ahd, scb);
}
@@ -465,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
break;
ahd_delay(200);
}
- if ((ccscbctl & CCSCBDIR) != 0)
+ /*
+ * We leave the sequencer to cleanup in the case of DMA's to
+ * update the qoutfifo. In all other cases (DMA's to the
+ * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
+ * we disable the DMA engine so that the sequencer will not
+ * attempt to handle the DMA completion.
+ */
+ if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
+ /*
+ * Complete any SCBs that just finished
+ * being DMA'ed into the qoutfifo.
+ */
+ ahd_run_qoutfifo(ahd);
+
saved_scbptr = ahd_get_scbptr(ahd);
/*
* Manually update/complete any completed SCBs that are waiting to be
@@ -494,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
scbid = next_scbid;
}
ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+
+ scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+ while (!SCBID_IS_NULL(scbid)) {
+
+ ahd_set_scbptr(ahd, scbid);
+ next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+ scb = ahd_lookup_scb(ahd, scbid);
+ if (scb == NULL) {
+ printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
+ ahd_name(ahd), scbid);
+ continue;
+ }
+
+ ahd_complete_scb(ahd, scb);
+ scbid = next_scbid;
+ }
+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
while (!SCBID_IS_NULL(scbid)) {
@@ -558,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
{
u_int seqintsrc;
- while (1) {
- seqintsrc = ahd_inb(ahd, SEQINTSRC);
- if ((seqintsrc & CFG4DATA) != 0) {
- uint32_t datacnt;
- uint32_t sgptr;
-
- /*
- * Clear full residual flag.
- */
- sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
- ahd_outb(ahd, SCB_SGPTR, sgptr);
+ seqintsrc = ahd_inb(ahd, SEQINTSRC);
+ if ((seqintsrc & CFG4DATA) != 0) {
+ uint32_t datacnt;
+ uint32_t sgptr;
- /*
- * Load datacnt and address.
- */
- datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
- if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
- sgptr |= LAST_SEG;
- ahd_outb(ahd, SG_STATE, 0);
- } else
- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
- ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
- ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
- ahd_outb(ahd, SG_CACHE_PRE, sgptr);
- ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+ /*
+ * Clear full residual flag.
+ */
+ sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+ ahd_outb(ahd, SCB_SGPTR, sgptr);
- /*
- * Initialize Residual Fields.
- */
- ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+ /*
+ * Load datacnt and address.
+ */
+ datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+ if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+ sgptr |= LAST_SEG;
+ ahd_outb(ahd, SG_STATE, 0);
+ } else
+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+ ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+ ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+ ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+ ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
- /*
- * Mark the SCB as having a FIFO in use.
- */
- ahd_outb(ahd, SCB_FIFO_USE_COUNT,
- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+ /*
+ * Initialize Residual Fields.
+ */
+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
- /*
- * Install a "fake" handler for this FIFO.
- */
- ahd_outw(ahd, LONGJMP_ADDR, 0);
+ /*
+ * Mark the SCB as having a FIFO in use.
+ */
+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
- /*
- * Notify the hardware that we have satisfied
- * this sequencer interrupt.
- */
- ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
- } else if ((seqintsrc & SAVEPTRS) != 0) {
- uint32_t sgptr;
- uint32_t resid;
+ /*
+ * Install a "fake" handler for this FIFO.
+ */
+ ahd_outw(ahd, LONGJMP_ADDR, 0);
- if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
- /*
- * Snapshot Save Pointers. Clear
- * the snapshot and continue.
- */
- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
- continue;
- }
+ /*
+ * Notify the hardware that we have satisfied
+ * this sequencer interrupt.
+ */
+ ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+ } else if ((seqintsrc & SAVEPTRS) != 0) {
+ uint32_t sgptr;
+ uint32_t resid;
+ if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
/*
- * Disable S/G fetch so the DMA engine
- * is available to future users.
+ * Snapshot Save Pointers. All that
+ * is necessary to clear the snapshot
+ * is a CLRCHN.
*/
- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
- ahd_outb(ahd, CCSGCTL, 0);
- ahd_outb(ahd, SG_STATE, 0);
+ goto clrchn;
+ }
- /*
- * Flush the data FIFO. Strickly only
- * necessary for Rev A parts.
- */
- ahd_outb(ahd, DFCNTRL,
- ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+ /*
+ * Disable S/G fetch so the DMA engine
+ * is available to future users.
+ */
+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+ ahd_outb(ahd, CCSGCTL, 0);
+ ahd_outb(ahd, SG_STATE, 0);
- /*
- * Calculate residual.
- */
- sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
- resid = ahd_inl(ahd, SHCNT);
- resid |=
- ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
- ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
- /*
- * Must back up to the correct S/G element.
- * Typically this just means resetting our
- * low byte to the offset in the SG_CACHE,
- * but if we wrapped, we have to correct
- * the other bytes of the sgptr too.
- */
- if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
- && (sgptr & 0x80) == 0)
- sgptr -= 0x100;
- sgptr &= ~0xFF;
- sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
- & SG_ADDR_MASK;
- ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
- ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
- } else if ((resid & AHD_SG_LEN_MASK) == 0) {
- ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
- sgptr | SG_LIST_NULL);
- }
- /*
- * Save Pointers.
- */
- ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
- ahd_outl(ahd, SCB_DATACNT, resid);
- ahd_outl(ahd, SCB_SGPTR, sgptr);
- ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
- ahd_outb(ahd, SEQIMODE,
- ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
- /*
- * If the data is to the SCSI bus, we are
- * done, otherwise wait for FIFOEMP.
- */
- if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
- break;
- } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
- uint32_t sgptr;
- uint64_t data_addr;
- uint32_t data_len;
- u_int dfcntrl;
+ /*
+ * Flush the data FIFO. Strickly only
+ * necessary for Rev A parts.
+ */
+ ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+ /*
+ * Calculate residual.
+ */
+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+ resid = ahd_inl(ahd, SHCNT);
+ resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+ ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
/*
- * Disable S/G fetch so the DMA engine
- * is available to future users.
+ * Must back up to the correct S/G element.
+ * Typically this just means resetting our
+ * low byte to the offset in the SG_CACHE,
+ * but if we wrapped, we have to correct
+ * the other bytes of the sgptr too.
*/
- if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
- ahd_outb(ahd, CCSGCTL, 0);
- ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
- }
+ if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+ && (sgptr & 0x80) == 0)
+ sgptr -= 0x100;
+ sgptr &= ~0xFF;
+ sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+ & SG_ADDR_MASK;
+ ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+ ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+ } else if ((resid & AHD_SG_LEN_MASK) == 0) {
+ ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+ sgptr | SG_LIST_NULL);
+ }
+ /*
+ * Save Pointers.
+ */
+ ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+ ahd_outl(ahd, SCB_DATACNT, resid);
+ ahd_outl(ahd, SCB_SGPTR, sgptr);
+ ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+ ahd_outb(ahd, SEQIMODE,
+ ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+ /*
+ * If the data is to the SCSI bus, we are
+ * done, otherwise wait for FIFOEMP.
+ */
+ if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+ goto clrchn;
+ } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+ uint32_t sgptr;
+ uint64_t data_addr;
+ uint32_t data_len;
+ u_int dfcntrl;
- /*
- * Wait for the DMA engine to notice that the
- * host transfer is enabled and that there is
- * space in the S/G FIFO for new segments before
- * loading more segments.
- */
- if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
- continue;
- if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
- continue;
+ /*
+ * Disable S/G fetch so the DMA engine
+ * is available to future users. We won't
+ * be using the DMA engine to load segments.
+ */
+ if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+ ahd_outb(ahd, CCSGCTL, 0);
+ ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+ }
+
+ /*
+ * Wait for the DMA engine to notice that the
+ * host transfer is enabled and that there is
+ * space in the S/G FIFO for new segments before
+ * loading more segments.
+ */
+ if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
+ && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
/*
* Determine the offset of the next S/G
@@ -748,7 +794,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
* Advertise the segment to the hardware.
*/
dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
- if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+ if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
/*
* Use SCSIENWRDIS so that SCSIEN
* is never modified by this
@@ -757,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
dfcntrl |= SCSIENWRDIS;
}
ahd_outb(ahd, DFCNTRL, dfcntrl);
- } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
- & LAST_SEG_DONE) != 0) {
-
- /*
- * Transfer completed to the end of SG list
- * and has flushed to the host.
- */
- ahd_outb(ahd, SCB_SGPTR,
- ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
- break;
- } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
- break;
}
- ahd_delay(200);
+ } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
+
+ /*
+ * Transfer completed to the end of SG list
+ * and has flushed to the host.
+ */
+ ahd_outb(ahd, SCB_SGPTR,
+ ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+ goto clrchn;
+ } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+clrchn:
+ /*
+ * Clear any handler for this FIFO, decrement
+ * the FIFO use count for the SCB, and release
+ * the FIFO.
+ */
+ ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+ ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+ ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+ ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
}
- /*
- * Clear any handler for this FIFO, decrement
- * the FIFO use count for the SCB, and release
- * the FIFO.
- */
- ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
- ahd_outb(ahd, SCB_FIFO_USE_COUNT,
- ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
- ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
}
+/*
+ * Look for entries in the QoutFIFO that have completed.
+ * The valid_tag completion field indicates the validity
+ * of the entry - the valid value toggles each time through
+ * the queue. We use the sg_status field in the completion
+ * entry to avoid referencing the hscb if the completion
+ * occurred with no errors and no residual. sg_status is
+ * a copy of the first byte (little endian) of the sgptr
+ * hscb field.
+ */
void
ahd_run_qoutfifo(struct ahd_softc *ahd)
{
+ struct ahd_completion *completion;
struct scb *scb;
u_int scb_index;
@@ -793,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
panic("ahd_run_qoutfifo recursion");
ahd->flags |= AHD_RUNNING_QOUTFIFO;
ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
- while ((ahd->qoutfifo[ahd->qoutfifonext]
- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {
+ for (;;) {
+ completion = &ahd->qoutfifo[ahd->qoutfifonext];
- scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
- & ~QOUTFIFO_ENTRY_VALID_LE);
+ if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
+ break;
+
+ scb_index = ahd_le16toh(completion->tag);
scb = ahd_lookup_scb(ahd, scb_index);
if (scb == NULL) {
printf("%s: WARNING no command for scb %d "
@@ -805,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
ahd_name(ahd), scb_index,
ahd->qoutfifonext);
ahd_dump_card_state(ahd);
- } else
- ahd_complete_scb(ahd, scb);
+ } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
+ ahd_handle_scb_status(ahd, scb);
+ } else {
+ ahd_done(ahd, scb);
+ }
ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
if (ahd->qoutfifonext == 0)
- ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;
+ ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
}
ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
}
@@ -876,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), seqintcode);
#endif
switch (seqintcode) {
- case BAD_SCB_STATUS:
- {
- struct scb *scb;
- u_int scbid;
- int cmds_pending;
-
- scbid = ahd_get_scbptr(ahd);
- scb = ahd_lookup_scb(ahd, scbid);
- if (scb != NULL) {
- ahd_complete_scb(ahd, scb);
- } else {
- printf("%s: WARNING no command for scb %d "
- "(bad status)\n", ahd_name(ahd), scbid);
- ahd_dump_card_state(ahd);
- }
- cmds_pending = ahd_inw(ahd, CMDS_PENDING);
- if (cmds_pending > 0)
- ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
- break;
- }
case ENTERING_NONPACK:
{
struct scb *scb;
@@ -1060,7 +1100,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_outb(ahd, SAVED_LUN, 0);
ahd_outb(ahd, SEQ_FLAGS, 0);
ahd_assert_atn(ahd);
- scb->flags &= ~(SCB_PACKETIZED);
+ scb->flags &= ~SCB_PACKETIZED;
scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
ahd_freeze_devq(ahd, scb);
ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
@@ -1503,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
&& (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
scb = NULL;
- /* Make sure the sequencer is in a safe location. */
- ahd_clear_critical_section(ahd);
-
if ((status0 & IOERR) != 0) {
u_int now_lvd;
@@ -1521,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
ahd_setup_iocell_workaround(ahd);
ahd_unpause(ahd);
} else if ((status0 & OVERRUN) != 0) {
+
printf("%s: SCSI offset overrun detected. Resetting bus.\n",
ahd_name(ahd));
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
} else if ((status & SCSIRSTI) != 0) {
+
printf("%s: Someone reset channel A\n", ahd_name(ahd));
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
} else if ((status & SCSIPERR) != 0) {
+
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
ahd_handle_transmission_error(ahd);
} else if (lqostat0 != 0) {
+
printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
ahd_outb(ahd, CLRLQOINT0, lqostat0);
- if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
+ if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
ahd_outb(ahd, CLRLQOINT1, 0);
- }
} else if ((status & SELTO) != 0) {
u_int scbid;
/* Stop the selection */
ahd_outb(ahd, SCSISEQ0, 0);
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
/* No more pending messages */
ahd_clear_msg_state(ahd);
@@ -1573,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
scbid);
}
#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.
- */
ahd_scb_devinfo(ahd, &devinfo, scb);
- ahd_force_renegotiation(ahd, &devinfo);
ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
ahd_freeze_devq(ahd, 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.
+ */
+ ahd_handle_devreset(ahd, &devinfo,
+ CAM_LUN_WILDCARD,
+ CAM_SEL_TIMEOUT,
+ "Selection Timeout",
+ /*verbose_level*/1);
}
ahd_outb(ahd, CLRINT, CLRSCSIINT);
ahd_iocell_first_selection(ahd);
ahd_unpause(ahd);
} else if ((status0 & (SELDI|SELDO)) != 0) {
+
ahd_iocell_first_selection(ahd);
ahd_unpause(ahd);
} else if (status3 != 0) {
@@ -1598,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), status3);
ahd_outb(ahd, CLRSINT3, status3);
} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
+
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
ahd_handle_lqiphase_error(ahd, lqistat1);
} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
/*
@@ -1622,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
*/
ahd_outb(ahd, SCSISEQ0, 0);
+ /* Make sure the sequencer is in a safe location. */
+ ahd_clear_critical_section(ahd);
+
/*
* Determine what we were up to at the time of
* the busfree.
@@ -1659,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
clear_fifo = 0;
packetized = (lqostat1 & LQOBUSFREE) != 0;
if (!packetized
- && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)
+ && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
+ && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
+ && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
+ || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
+ /*
+ * Assume packetized if we are not
+ * on the bus in a non-packetized
+ * capacity and any pending selection
+ * was a packetized selection.
+ */
packetized = 1;
break;
}
@@ -2310,8 +2375,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
"PRGMCNT == 0x%x\n",
ahd_lookup_phase_entry(lastphase)->phasemsg,
aborted,
- ahd_inb(ahd, PRGMCNT)
- | (ahd_inb(ahd, PRGMCNT+1) << 8));
+ ahd_inw(ahd, PRGMCNT));
ahd_dump_card_state(ahd);
}
/* Always restart the sequencer. */
@@ -2474,8 +2538,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
u_int i;
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- seqaddr = ahd_inb(ahd, CURADDR)
- | (ahd_inb(ahd, CURADDR+1) << 8);
+ seqaddr = ahd_inw(ahd, CURADDR);
cs = ahd->critical_sections;
for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -3196,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
- && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {
+ && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
+ && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
/*
* Slow down our CRC interval to be
- * compatible with devices that can't
- * handle a CRC at full speed.
+ * compatible with non-packetized
+ * U160 devices that can't handle a
+ * CRC at full speed.
*/
con_opts |= ENSLOWCRC;
}
+
+ if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
+ /*
+ * On H2A4, revert to a slower slewrate
+ * on non-paced transfers.
+ */
+ iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
+ ~AHD_SLEWRATE_MASK;
+ }
}
ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -3292,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
* Force the sequencer to reinitialize the selection for
* the command at the head of the execution queue if it
* has already been setup. The negotiation changes may
- * effect whether we select-out with ATN.
+ * effect whether we select-out with ATN. It is only
+ * safe to clear ENSELO when the bus is not free and no
+ * selection is in progres or completed.
*/
saved_modes = ahd_save_modes(ahd);
ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
+ if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
+ && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
+ ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
saved_scbptr = ahd_get_scbptr(ahd);
/* Ensure that the hscbs down on the card match the new information */
for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
@@ -4909,10 +4987,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
* Determine initial values for data_addr and data_cnt
* for resuming the data phase.
*/
- sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)
- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
- | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
- | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
+ sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
sgptr &= SG_PTR_MASK;
resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4930,10 +5005,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
dataptr = ahd_le64toh(sg->addr)
+ (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
- resid;
- ahd_outb(ahd, HADDR + 7, dataptr >> 56);
- ahd_outb(ahd, HADDR + 6, dataptr >> 48);
- ahd_outb(ahd, HADDR + 5, dataptr >> 40);
- ahd_outb(ahd, HADDR + 4, dataptr >> 32);
+ ahd_outl(ahd, HADDR + 4, dataptr >> 32);
} else {
struct ahd_dma_seg *sg;
@@ -4948,10 +5020,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
ahd_outb(ahd, HADDR + 4,
(ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
}
- ahd_outb(ahd, HADDR + 3, dataptr >> 24);
- ahd_outb(ahd, HADDR + 2, dataptr >> 16);
- ahd_outb(ahd, HADDR + 1, dataptr >> 8);
- ahd_outb(ahd, HADDR, dataptr);
+ ahd_outl(ahd, HADDR, dataptr);
ahd_outb(ahd, HCNT + 2, resid >> 16);
ahd_outb(ahd, HCNT + 1, resid >> 8);
ahd_outb(ahd, HCNT, resid);
@@ -5011,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
AHD_TRANS_CUR, /*paused*/TRUE);
ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
- /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE);
+ /*ppr_options*/0, AHD_TRANS_CUR,
+ /*paused*/TRUE);
- ahd_send_async(ahd, devinfo->channel, devinfo->target,
- lun, AC_SENT_BDR, NULL);
+ if (status != CAM_SEL_TIMEOUT)
+ ahd_send_async(ahd, devinfo->channel, devinfo->target,
+ CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
- if (message != NULL
- && (verbose_level <= bootverbose))
+ if (message != NULL && bootverbose)
printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
message, devinfo->channel, devinfo->target, found);
}
@@ -5203,13 +5273,13 @@ ahd_free(struct ahd_softc *ahd)
/* FALLTHROUGH */
case 4:
ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
/* FALLTHROUGH */
case 3:
ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap);
+ ahd->shared_data_map.dmamap);
/* FALLTHROUGH */
case 2:
ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
@@ -5975,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
newcount = MIN(newcount, scb_data->sgs_left);
newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
- scb_data->sense_left -= newcount;
- scb_data->scbs_left -= newcount;
- scb_data->sgs_left -= newcount;
for (i = 0; i < newcount; i++) {
- u_int col_tag;
-
struct scb_platform_data *pdata;
+ u_int col_tag;
#ifndef __linux__
int error;
#endif
+
next_scb = (struct scb *)malloc(sizeof(*next_scb),
M_DEVBUF, M_NOWAIT);
if (next_scb == NULL)
@@ -6041,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
sense_data += AHD_SENSE_BUFSIZE;
sense_busaddr += AHD_SENSE_BUFSIZE;
scb_data->numscbs++;
+ scb_data->sense_left--;
+ scb_data->scbs_left--;
+ scb_data->sgs_left--;
}
}
@@ -6088,7 +6158,6 @@ static const char *termstat_strings[] = {
int
ahd_init(struct ahd_softc *ahd)
{
- uint8_t *base_vaddr;
uint8_t *next_vaddr;
dma_addr_t next_baddr;
size_t driver_data_size;
@@ -6156,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd)
* for the target mode role, we must additionally provide space for
* the incoming target command fifo.
*/
- driver_data_size = AHD_SCB_MAX * sizeof(uint16_t)
+ driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
+ sizeof(struct hardware_scb);
if ((ahd->features & AHD_TARGETMODE) != 0)
driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6178,20 +6247,23 @@ ahd_init(struct ahd_softc *ahd)
/* Allocation of driver data */
if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
- (void **)&base_vaddr,
- BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {
+ (void **)&ahd->shared_data_map.vaddr,
+ BUS_DMA_NOWAIT,
+ &ahd->shared_data_map.dmamap) != 0) {
return (ENOMEM);
}
ahd->init_level++;
/* And permanently map it in */
- ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- base_vaddr, driver_data_size, ahd_dmamap_cb,
- &ahd->shared_data_busaddr, /*flags*/0);
- ahd->qoutfifo = (uint16_t *)base_vaddr;
+ ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ ahd->shared_data_map.vaddr, driver_data_size,
+ ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
+ /*flags*/0);
+ ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
- next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);
+ next_baddr = ahd->shared_data_map.physaddr
+ + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
if ((ahd->features & AHD_TARGETMODE) != 0) {
ahd->targetcmds = (struct target_cmd *)next_vaddr;
next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6212,6 +6284,7 @@ ahd_init(struct ahd_softc *ahd)
* specially from the DMA safe memory chunk used for the QOUTFIFO.
*/
ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
+ ahd->next_queued_hscb_map = &ahd->shared_data_map;
ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
ahd->init_level++;
@@ -6517,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd)
/* All of our queues are empty */
ahd->qoutfifonext = 0;
- ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE;
- ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8);
+ ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
+ ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
for (i = 0; i < AHD_QOUT_SIZE; i++)
- ahd->qoutfifo[i] = 0;
+ ahd->qoutfifo[i].valid_tag = 0;
ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
ahd->qinfifonext = 0;
@@ -6553,24 +6626,22 @@ ahd_chip_init(struct ahd_softc *ahd)
ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+ ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
/*
* The Freeze Count is 0.
*/
+ ahd->qfreeze_cnt = 0;
ahd_outw(ahd, QFREEZE_COUNT, 0);
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
/*
* Tell the sequencer where it can find our arrays in memory.
*/
- busaddr = ahd->shared_data_busaddr;
- ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
+ busaddr = ahd->shared_data_map.physaddr;
+ ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
+ ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
/*
* Setup the allowed SCSI Sequences based on operational mode.
@@ -6619,10 +6690,7 @@ ahd_chip_init(struct ahd_softc *ahd)
* Tell the sequencer which SCB will be the next one it receives.
*/
busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
/*
* Default to coalescing disabled.
@@ -6926,43 +6994,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
{
u_int intstat;
u_int maxloops;
- u_int qfreeze_cnt;
maxloops = 1000;
ahd->flags |= AHD_ALL_INTERRUPTS;
ahd_pause(ahd);
/*
- * Increment the QFreeze Count so that the sequencer
- * will not start new selections. We do this only
+ * Freeze the outgoing selections. We do this only
* until we are safely paused without further selections
* pending.
*/
- ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1);
+ ahd->qfreeze_cnt--;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
do {
- struct scb *waiting_scb;
ahd_unpause(ahd);
+ /*
+ * Give the sequencer some time to service
+ * any active selections.
+ */
+ ahd_delay(500);
+
ahd_intr(ahd);
ahd_pause(ahd);
- ahd_clear_critical_section(ahd);
intstat = ahd_inb(ahd, INTSTAT);
- ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
- if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
- ahd_outb(ahd, SCSISEQ0,
- ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
- /*
- * In the non-packetized case, the sequencer (for Rev A),
- * relies on ENSELO remaining set after SELDO. The hardware
- * auto-clears ENSELO in the packetized case.
- */
- waiting_scb = ahd_lookup_scb(ahd,
- ahd_inw(ahd, WAITING_TID_HEAD));
- if (waiting_scb != NULL
- && (waiting_scb->flags & SCB_PACKETIZED) == 0
- && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)
- ahd_outb(ahd, SCSISEQ0,
- ahd_inb(ahd, SCSISEQ0) | ENSELO);
+ if ((intstat & INT_PEND) == 0) {
+ ahd_clear_critical_section(ahd);
+ intstat = ahd_inb(ahd, INTSTAT);
+ }
} while (--maxloops
&& (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
&& ((intstat & INT_PEND) != 0
@@ -6973,17 +7032,8 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
printf("Infinite interrupt loop, INTSTAT = %x",
ahd_inb(ahd, INTSTAT));
}
- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
- if (qfreeze_cnt == 0) {
- printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n",
- ahd_name(ahd));
- } else {
- qfreeze_cnt--;
- }
- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
- if (qfreeze_cnt == 0)
- ahd_outb(ahd, SEQ_FLAGS2,
- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+ ahd->qfreeze_cnt++;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
ahd_flush_qoutfifo(ahd);
@@ -7155,10 +7205,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
uint32_t busaddr;
busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
} else {
prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
ahd_sync_scb(ahd, prev_scb,
@@ -7265,10 +7312,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
*/
ahd->qinfifonext = qinstart;
busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
- ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+ ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
while (qinpos != qintail) {
scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
@@ -7330,6 +7374,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
* appropriate, traverse the SCBs of each "their id"
* looking for matches.
*/
+ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
savedscbptr = ahd_get_scbptr(ahd);
tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
tid_prev = SCB_LIST_NULL;
@@ -7399,7 +7444,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
u_int prev;
int found;
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
found = 0;
prev = SCB_LIST_NULL;
next = *list_head;
@@ -7466,7 +7511,7 @@ static void
ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
u_int tid_cur, u_int tid_next)
{
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
if (SCBID_IS_NULL(tid_cur)) {
@@ -7506,7 +7551,7 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
{
u_int tail_offset;
- AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
+ AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
if (!SCBID_IS_NULL(prev)) {
ahd_set_scbptr(ahd, prev);
ahd_outw(ahd, SCB_NEXT, next);
@@ -7739,7 +7784,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
*/
ahd_clear_msg_state(ahd);
ahd_outb(ahd, SIMODE1,
- ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE));
+ ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
if (initiate_reset)
ahd_reset_current_bus(ahd);
@@ -7910,30 +7955,35 @@ ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
void
ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
{
- struct hardware_scb *hscb;
- u_int qfreeze_cnt;
+ struct hardware_scb *hscb;
+ int paused;
/*
* The sequencer freezes its select-out queue
* anytime a SCSI status error occurs. We must
- * handle the error and decrement the QFREEZE count
- * to allow the sequencer to continue.
+ * handle the error and increment our qfreeze count
+ * to allow the sequencer to continue. We don't
+ * bother clearing critical sections here since all
+ * operations are on data structures that the sequencer
+ * is not touching once the queue is frozen.
*/
hscb = scb->hscb;
+ if (ahd_is_paused(ahd)) {
+ paused = 1;
+ } else {
+ paused = 0;
+ ahd_pause(ahd);
+ }
+
/* Freeze the queue until the client sees the error. */
ahd_freeze_devq(ahd, scb);
ahd_freeze_scb(scb);
- qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT);
- if (qfreeze_cnt == 0) {
- printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd));
- } else {
- qfreeze_cnt--;
- ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt);
- }
- if (qfreeze_cnt == 0)
- ahd_outb(ahd, SEQ_FLAGS2,
- ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN);
+ ahd->qfreeze_cnt++;
+ ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
+
+ if (paused == 0)
+ ahd_unpause(ahd);
/* Don't want to clobber the original sense code */
if ((scb->flags & SCB_SENSE) != 0) {
@@ -8317,8 +8367,7 @@ ahd_dumpseq(struct ahd_softc* ahd)
max_prog = 2048;
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
- ahd_outb(ahd, PRGMCNT, 0);
- ahd_outb(ahd, PRGMCNT+1, 0);
+ ahd_outw(ahd, PRGMCNT, 0);
for (i = 0; i < max_prog; i++) {
uint8_t ins_bytes[4];
@@ -8347,13 +8396,14 @@ ahd_loadseq(struct ahd_softc *ahd)
u_int sg_prefetch_cnt_limit;
u_int sg_prefetch_align;
u_int sg_size;
+ u_int cacheline_mask;
uint8_t download_consts[DOWNLOAD_CONST_COUNT];
if (bootverbose)
printf("%s: Downloading Sequencer Program...",
ahd_name(ahd));
-#if DOWNLOAD_CONST_COUNT != 7
+#if DOWNLOAD_CONST_COUNT != 8
#error "Download Const Mismatch"
#endif
/*
@@ -8389,6 +8439,9 @@ ahd_loadseq(struct ahd_softc *ahd)
/* Round down to the nearest power of 2. */
while (powerof2(sg_prefetch_align) == 0)
sg_prefetch_align--;
+
+ cacheline_mask = sg_prefetch_align - 1;
+
/*
* If the cacheline boundary is greater than half our prefetch RAM
* we risk not being able to fetch even a single complete S/G
@@ -8429,12 +8482,12 @@ ahd_loadseq(struct ahd_softc *ahd)
download_consts[PKT_OVERRUN_BUFOFFSET] =
(ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
+ download_consts[CACHELINE_MASK] = cacheline_mask;
cur_patch = patches;
downloaded = 0;
skip_addr = 0;
ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
- ahd_outb(ahd, PRGMCNT, 0);
- ahd_outb(ahd, PRGMCNT+1, 0);
+ ahd_outw(ahd, PRGMCNT, 0);
for (i = 0; i < sizeof(seqprog)/4; i++) {
if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
@@ -8727,7 +8780,7 @@ ahd_dump_card_state(struct ahd_softc *ahd)
printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
"%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
ahd_name(ahd),
- ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8),
+ ahd_inw(ahd, CURADDR),
ahd_build_mode_state(ahd, ahd->saved_src_mode,
ahd->saved_dst_mode));
if (paused)
@@ -8843,6 +8896,15 @@ ahd_dump_card_state(struct ahd_softc *ahd)
scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
}
printf("\n");
+ printf("Sequencer On QFreeze and Complete list: ");
+ scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+ i = 0;
+ while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
+ ahd_set_scbptr(ahd, scb_index);
+ printf("%d ", scb_index);
+ scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+ }
+ printf("\n");
ahd_set_scbptr(ahd, saved_scb_index);
dffstat = ahd_inb(ahd, DFFSTAT);
for (i = 0; i < 2; i++) {
@@ -9077,7 +9139,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd)
{
int cnt;
- cnt = 20;
+ cnt = 5000;
while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
ahd_delay(5);
@@ -9423,13 +9485,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
if ((ahd->features & AHD_MULTI_TID) != 0) {
u_int targid_mask;
- targid_mask = ahd_inb(ahd, TARGID)
- | (ahd_inb(ahd, TARGID + 1) << 8);
-
+ targid_mask = ahd_inw(ahd, TARGID);
targid_mask |= target_mask;
- ahd_outb(ahd, TARGID, targid_mask);
- ahd_outb(ahd, TARGID+1, (targid_mask >> 8));
-
+ ahd_outw(ahd, TARGID, targid_mask);
ahd_update_scsiid(ahd, targid_mask);
} else {
u_int our_id;
@@ -9543,14 +9601,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
if (ahd->features & AHD_MULTI_TID) {
u_int targid_mask;
- targid_mask = ahd_inb(ahd, TARGID)
- | (ahd_inb(ahd, TARGID + 1)
- << 8);
-
+ targid_mask = ahd_inw(ahd, TARGID);
targid_mask &= ~target_mask;
- ahd_outb(ahd, TARGID, targid_mask);
- ahd_outb(ahd, TARGID+1,
- (targid_mask >> 8));
+ ahd_outw(ahd, TARGID, targid_mask);
ahd_update_scsiid(ahd, targid_mask);
}
}
@@ -9651,7 +9704,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
cmd->cmd_valid = 0;
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
sizeof(struct target_cmd),
BUS_DMASYNC_PREREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index d80bc5161fb1..91c4f7f484b1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.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/aic79xx_inline.h#51 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#58 $
*
* $FreeBSD$
*/
@@ -522,12 +522,21 @@ do { \
static __inline uint16_t
ahd_inw(struct ahd_softc *ahd, u_int port)
{
+ /*
+ * Read high byte first as some registers increment
+ * or have other side effects when the low byte is
+ * read.
+ */
return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
}
static __inline void
ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
{
+ /*
+ * Write low byte first to accomodate registers
+ * such as PRGMCNT where the order maters.
+ */
ahd_outb(ahd, port, value & 0xFF);
ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
}
@@ -684,7 +693,7 @@ ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
* Razor #528
*/
value = ahd_inb(ahd, offset);
- if ((ahd->flags & AHD_PCIX_SCBRAM_RD_BUG) != 0)
+ if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
ahd_inb(ahd, MODE_PTR);
return (value);
}
@@ -727,7 +736,8 @@ ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
static __inline void
ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
{
- struct hardware_scb *q_hscb;
+ struct hardware_scb *q_hscb;
+ struct map_node *q_hscb_map;
uint32_t saved_hscb_busaddr;
/*
@@ -743,6 +753,7 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
* locate the correct SCB by SCB_TAG.
*/
q_hscb = ahd->next_queued_hscb;
+ q_hscb_map = ahd->next_queued_hscb_map;
saved_hscb_busaddr = q_hscb->hscb_busaddr;
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
q_hscb->hscb_busaddr = saved_hscb_busaddr;
@@ -750,7 +761,9 @@ ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
/* Now swap HSCB pointers. */
ahd->next_queued_hscb = scb->hscb;
+ ahd->next_queued_hscb_map = scb->hscb_map;
scb->hscb = q_hscb;
+ scb->hscb_map = q_hscb_map;
/* Now define the mapping from tag to SCB in the scbindex */
ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
@@ -824,8 +837,9 @@ static __inline int ahd_intr(struct ahd_softc *ahd);
static __inline void
ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
{
- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- /*offset*/0, /*len*/AHC_SCB_MAX * sizeof(uint16_t), op);
+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ /*offset*/0,
+ /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
}
static __inline void
@@ -834,7 +848,7 @@ ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, 0),
sizeof(struct target_cmd) * AHD_TMODE_CMDS,
op);
@@ -854,17 +868,17 @@ ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
u_int retval;
retval = 0;
- ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
- /*offset*/ahd->qoutfifonext, /*len*/2,
- BUS_DMASYNC_POSTREAD);
- if ((ahd->qoutfifo[ahd->qoutfifonext]
- & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag)
+ ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+ /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
+ /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
+ if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
+ == ahd->qoutfifonext_valid_tag)
retval |= AHD_RUN_QOUTFIFO;
#ifdef AHD_TARGET_MODE
if ((ahd->flags & AHD_TARGETROLE) != 0
&& (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
ahd_dmamap_sync(ahd, ahd->shared_data_dmat,
- ahd->shared_data_dmamap,
+ ahd->shared_data_map.dmamap,
ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
/*len*/sizeof(struct target_cmd),
BUS_DMASYNC_POSTREAD);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 6aab9dacdeea..2567e29960bd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1064,6 +1064,7 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
struct Scsi_Host *host;
char *new_name;
u_long s;
+ int retval;
template->name = ahd->description;
host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
@@ -1096,9 +1097,15 @@ ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *templa
host->transportt = ahd_linux_transport_template;
- scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */
+ retval = scsi_add_host(host, &ahd->dev_softc->dev);
+ if (retval) {
+ printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
+ scsi_host_put(host);
+ return retval;
+ }
+
scsi_scan_host(host);
- return (0);
+ return 0;
}
uint64_t
@@ -1461,6 +1468,30 @@ ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
if ((tstate->auto_negotiate & mask) != 0) {
scb->flags |= SCB_AUTO_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
+ } else if (cmd->cmnd[0] == INQUIRY
+ && (tinfo->curr.offset != 0
+ || tinfo->curr.width != MSG_EXT_WDTR_BUS_8_BIT
+ || tinfo->curr.ppr_options != 0)
+ && (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)==0) {
+ /*
+ * The SCSI spec requires inquiry
+ * commands to complete without
+ * reporting unit attention conditions.
+ * Because of this, an inquiry command
+ * that occurs just after a device is
+ * reset will result in a data phase
+ * with mismatched negotiated rates.
+ * The core already forces a renegotiation
+ * for reset events that are visible to
+ * our controller or that we initiate,
+ * but a third party device reset or a
+ * hot-plug insertion can still cause this
+ * issue. Therefore, we force a re-negotiation
+ * for every inquiry command unless we
+ * are async.
+ */
+ scb->flags |= SCB_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
}
if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
@@ -2051,6 +2082,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
int paused;
int wait;
int disconnected;
+ int found;
ahd_mode_state saved_modes;
unsigned long flags;
@@ -2169,7 +2201,8 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
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) {
+ if (disconnected && ((last_phase != P_BUSFREE) ||
+ (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0)) {
struct scb *bus_scb;
bus_scb = ahd_lookup_scb(ahd, active_scbptr);
@@ -2187,28 +2220,41 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
* 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
+ if (SCB_GET_TAG(pending_scb) == active_scbptr
|| (flag == SCB_DEVICE_RESET
- && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {
+ && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd))) {
/*
* 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;
+ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_DEVICE_RESET;
ahd_outb(ahd, MSG_OUT, HOST_MSG);
ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
- scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
+ scmd_printk(KERN_INFO, cmd, "BDR message in message buffer\n");
wait = TRUE;
+ } else if (last_phase != P_BUSFREE
+ && ahd_inb(ahd, SCSIPHASE) == 0) {
+ /*
+ * SCB is not identified, there
+ * is no pending REQ, and the sequencer
+ * has not seen a busfree. Looks like
+ * a stuck connection waiting to
+ * go busfree. Reset the bus.
+ */
+ found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
+ /*Initiate Reset*/TRUE);
+ printf("%s: Issued Channel %c Bus Reset. "
+ "%d SCBs aborted\n", ahd_name(ahd),
+ cmd->device->channel + 'A', found);
} 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;
+ pending_scb->flags |= SCB_RECOVERY_SCB|flag;
ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
pending_scb->hscb->cdb_len = 0;
pending_scb->hscb->task_attribute = 0;
@@ -2289,16 +2335,17 @@ done:
timer.expires = jiffies + (5 * HZ);
timer.function = ahd_linux_sem_timeout;
add_timer(&timer);
- printf("Recovery code sleeping\n");
+ printf("%s: Recovery code sleeping\n", ahd_name(ahd));
down(&ahd->platform_data->eh_sem);
- printf("Recovery code awake\n");
+ printf("%s: Recovery code awake\n", ahd_name(ahd));
ret = del_timer_sync(&timer);
if (ret == 0) {
- printf("Timer Expired\n");
+ printf("%s: Timer Expired (active %d)\n",
+ ahd_name(ahd), dev->active);
retval = FAILED;
}
}
- ahd_unlock(ahd, &flags);
+ ahd_unlock(ahd, &flags);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index bc44222d6cc3..cb74fccc8100 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -252,7 +252,7 @@ ahd_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#define AIC79XX_DRIVER_VERSION "1.3.11"
+#define AIC79XX_DRIVER_VERSION "3.0"
/*************************** Device Data Structures ***************************/
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 2131db60018a..196a6344b037 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -38,9 +38,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#77 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#89 $
*/
#ifdef __linux__
@@ -114,6 +112,13 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
"Adaptec 29320ALP Ultra320 SCSI adapter",
ahd_aic7901_setup
},
+ /* aic7901A based controllers */
+ {
+ ID_AHA_29320LP,
+ ID_ALL_MASK,
+ "Adaptec 29320LP Ultra320 SCSI adapter",
+ ahd_aic7901A_setup
+ },
/* aic7902 based controllers */
{
ID_AHA_29320,
@@ -128,12 +133,6 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
ahd_aic7902_setup
},
{
- ID_AHA_29320LP,
- ID_ALL_MASK,
- "Adaptec 29320LP Ultra320 SCSI adapter",
- ahd_aic7901A_setup
- },
- {
ID_AHA_39320,
ID_ALL_MASK,
"Adaptec 39320 Ultra320 SCSI adapter",
@@ -146,6 +145,12 @@ struct ahd_pci_identity ahd_pci_ident_table [] =
ahd_aic7902_setup
},
{
+ ID_AHA_39320_B_DELL,
+ ID_ALL_MASK,
+ "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
+ ahd_aic7902_setup
+ },
+ {
ID_AHA_39320A,
ID_ALL_MASK,
"Adaptec 39320A Ultra320 SCSI adapter",
@@ -668,6 +673,7 @@ ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
* Now set the termination based on what we found.
*/
sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
+ ahd->flags &= ~AHD_TERM_ENB_A;
if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
ahd->flags |= AHD_TERM_ENB_A;
sxfrctl1 |= STPWEN;
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h
index b5cfeabdfecf..da45153668c7 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.h
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.h
@@ -53,14 +53,15 @@
#define ID_AHA_29320ALP 0x8017900500449005ull
#define ID_AIC7901A 0x801E9005FFFF9005ull
-#define ID_AHA_29320 0x8012900500429005ull
-#define ID_AHA_29320B 0x8013900500439005ull
#define ID_AHA_29320LP 0x8014900500449005ull
#define ID_AIC7902 0x801F9005FFFF9005ull
#define ID_AIC7902_B 0x801D9005FFFF9005ull
#define ID_AHA_39320 0x8010900500409005ull
+#define ID_AHA_29320 0x8012900500429005ull
+#define ID_AHA_29320B 0x8013900500439005ull
#define ID_AHA_39320_B 0x8015900500409005ull
+#define ID_AHA_39320_B_DELL 0x8015900501681028ull
#define ID_AHA_39320A 0x8016900500409005ull
#define ID_AHA_39320D 0x8011900500419005ull
#define ID_AHA_39320D_B 0x801C900500419005ull
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
index c01ac39090d9..8763b158856b 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
@@ -2,8 +2,8 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
*/
typedef int (ahd_reg_print_t)(u_int, u_int *, u_int);
typedef struct ahd_reg_parse_entry {
@@ -83,17 +83,17 @@ ahd_reg_print_t ahd_hs_mailbox_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrseqintstat_print;
+ahd_reg_print_t ahd_seqintstat_print;
#else
-#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
+#define ahd_seqintstat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_seqintstat_print;
+ahd_reg_print_t ahd_clrseqintstat_print;
#else
-#define ahd_seqintstat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
+#define ahd_clrseqintstat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CLRSEQINTSTAT", 0x0c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -412,17 +412,17 @@ ahd_reg_print_t ahd_sxfrctl0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_businitid_print;
+ahd_reg_print_t ahd_dlcount_print;
#else
-#define ahd_businitid_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
+#define ahd_dlcount_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dlcount_print;
+ahd_reg_print_t ahd_businitid_print;
#else
-#define ahd_dlcount_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DLCOUNT", 0x3c, regvalue, cur_col, wrap)
+#define ahd_businitid_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BUSINITID", 0x3c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -517,13 +517,6 @@ ahd_reg_print_t ahd_selid_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sblkctl_print;
-#else
-#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_optionmode_print;
#else
#define ahd_optionmode_print(regvalue, cur_col, wrap) \
@@ -531,10 +524,10 @@ ahd_reg_print_t ahd_optionmode_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sstat0_print;
+ahd_reg_print_t ahd_sblkctl_print;
#else
-#define ahd_sstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#define ahd_sblkctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SBLKCTL", 0x4a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -545,6 +538,13 @@ ahd_reg_print_t ahd_clrsint0_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sstat0_print;
+#else
+#define ahd_sstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SSTAT0", 0x4b, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_simode0_print;
#else
#define ahd_simode0_print(regvalue, cur_col, wrap) \
@@ -573,17 +573,17 @@ ahd_reg_print_t ahd_sstat2_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_clrsint2_print;
+ahd_reg_print_t ahd_simode2_print;
#else
-#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_simode2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_simode2_print;
+ahd_reg_print_t ahd_clrsint2_print;
#else
-#define ahd_simode2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SIMODE2", 0x4d, regvalue, cur_col, wrap)
+#define ahd_clrsint2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CLRSINT2", 0x4d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -685,13 +685,6 @@ ahd_reg_print_t ahd_clrsint3_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode0_print;
-#else
-#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat0_print;
#else
#define ahd_lqostat0_print(regvalue, cur_col, wrap) \
@@ -706,6 +699,20 @@ ahd_reg_print_t ahd_clrlqoint0_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode0_print;
+#else
+#define ahd_lqomode0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "LQOMODE0", 0x54, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_lqomode1_print;
+#else
+#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat1_print;
#else
#define ahd_lqostat1_print(regvalue, cur_col, wrap) \
@@ -720,13 +727,6 @@ ahd_reg_print_t ahd_clrlqoint1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_lqomode1_print;
-#else
-#define ahd_lqomode1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LQOMODE1", 0x55, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lqostat2_print;
#else
#define ahd_lqostat2_print(regvalue, cur_col, wrap) \
@@ -909,17 +909,17 @@ ahd_reg_print_t ahd_annexcol_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_scschkn_print;
+ahd_reg_print_t ahd_annexdat_print;
#else
-#define ahd_scschkn_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
+#define ahd_annexdat_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_annexdat_print;
+ahd_reg_print_t ahd_scschkn_print;
#else
-#define ahd_annexdat_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ANNEXDAT", 0x66, regvalue, cur_col, wrap)
+#define ahd_scschkn_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SCSCHKN", 0x66, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1000,17 +1000,17 @@ ahd_reg_print_t ahd_pll400ctl1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_pll400cnt0_print;
+ahd_reg_print_t ahd_unfairness_print;
#else
-#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
+#define ahd_unfairness_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_unfairness_print;
+ahd_reg_print_t ahd_pll400cnt0_print;
#else
-#define ahd_unfairness_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "UNFAIRNESS", 0x6e, regvalue, cur_col, wrap)
+#define ahd_pll400cnt0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "PLL400CNT0", 0x6e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1056,13 +1056,6 @@ ahd_reg_print_t ahd_hodmaen_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghaddr_print;
-#else
-#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scbhaddr_print;
#else
#define ahd_scbhaddr_print(regvalue, cur_col, wrap) \
@@ -1070,10 +1063,10 @@ ahd_reg_print_t ahd_scbhaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sghcnt_print;
+ahd_reg_print_t ahd_sghaddr_print;
#else
-#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#define ahd_sghaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHADDR", 0x7c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1084,6 +1077,13 @@ ahd_reg_print_t ahd_scbhcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_sghcnt_print;
+#else
+#define ahd_sghcnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGHCNT", 0x84, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dff_thrsh_print;
#else
#define ahd_dff_thrsh_print(regvalue, cur_col, wrap) \
@@ -1154,13 +1154,6 @@ ahd_reg_print_t ahd_nsenable_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg1_print;
-#else
-#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmcrxmsg1_print;
#else
#define ahd_cmcrxmsg1_print(regvalue, cur_col, wrap) \
@@ -1168,17 +1161,17 @@ ahd_reg_print_t ahd_cmcrxmsg1_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchrxmsg2_print;
+ahd_reg_print_t ahd_dchrxmsg1_print;
#else
-#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
+#define ahd_dchrxmsg1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHRXMSG1", 0x91, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg2_print;
+ahd_reg_print_t ahd_dchrxmsg2_print;
#else
-#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+#define ahd_dchrxmsg2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHRXMSG2", 0x92, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1196,6 +1189,13 @@ ahd_reg_print_t ahd_ost_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg2_print;
+#else
+#define ahd_ovlyrxmsg2_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYRXMSG2", 0x92, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dchrxmsg3_print;
#else
#define ahd_dchrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1203,6 +1203,13 @@ ahd_reg_print_t ahd_dchrxmsg3_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_ovlyrxmsg3_print;
+#else
+#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmcrxmsg3_print;
#else
#define ahd_cmcrxmsg3_print(regvalue, cur_col, wrap) \
@@ -1217,13 +1224,6 @@ ahd_reg_print_t ahd_pcixctl_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyrxmsg3_print;
-#else
-#define ahd_ovlyrxmsg3_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYRXMSG3", 0x93, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_ovlyseqbcnt_print;
#else
#define ahd_ovlyseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1231,13 +1231,6 @@ ahd_reg_print_t ahd_ovlyseqbcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcseqbcnt_print;
-#else
-#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dchseqbcnt_print;
#else
#define ahd_dchseqbcnt_print(regvalue, cur_col, wrap) \
@@ -1245,17 +1238,17 @@ ahd_reg_print_t ahd_dchseqbcnt_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_cmcspltstat0_print;
+ahd_reg_print_t ahd_cmcseqbcnt_print;
#else
-#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+#define ahd_cmcseqbcnt_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CMCSEQBCNT", 0x94, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ovlyspltstat0_print;
+ahd_reg_print_t ahd_cmcspltstat0_print;
#else
-#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
+#define ahd_cmcspltstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CMCSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1266,10 +1259,10 @@ ahd_reg_print_t ahd_dchspltstat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dchspltstat1_print;
+ahd_reg_print_t ahd_ovlyspltstat0_print;
#else
-#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#define ahd_ovlyspltstat0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "OVLYSPLTSTAT0", 0x96, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1287,6 +1280,13 @@ ahd_reg_print_t ahd_ovlyspltstat1_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dchspltstat1_print;
+#else
+#define ahd_dchspltstat1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DCHSPLTSTAT1", 0x97, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_sgrxmsg0_print;
#else
#define ahd_sgrxmsg0_print(regvalue, cur_col, wrap) \
@@ -1378,17 +1378,17 @@ ahd_reg_print_t ahd_sgspltstat0_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sfunct_print;
+ahd_reg_print_t ahd_sgspltstat1_print;
#else
-#define ahd_sfunct_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
+#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_sgspltstat1_print;
+ahd_reg_print_t ahd_sfunct_print;
#else
-#define ahd_sgspltstat1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SGSPLTSTAT1", 0x9f, regvalue, cur_col, wrap)
+#define ahd_sfunct_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SFUNCT", 0x9f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1504,17 +1504,17 @@ ahd_reg_print_t ahd_ccsgaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbaddr_print;
+ahd_reg_print_t ahd_ccscbadr_bk_print;
#else
-#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
+#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbadr_bk_print;
+ahd_reg_print_t ahd_ccscbaddr_print;
#else
-#define ahd_ccscbadr_bk_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBADR_BK", 0xac, regvalue, cur_col, wrap)
+#define ahd_ccscbaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBADDR", 0xac, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1525,17 +1525,17 @@ ahd_reg_print_t ahd_cmc_rambist_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccsgctl_print;
+ahd_reg_print_t ahd_ccscbctl_print;
#else
-#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
+#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_ccscbctl_print;
+ahd_reg_print_t ahd_ccsgctl_print;
#else
-#define ahd_ccscbctl_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CCSCBCTL", 0xad, regvalue, cur_col, wrap)
+#define ahd_ccsgctl_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CCSGCTL", 0xad, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1707,13 +1707,6 @@ ahd_reg_print_t ahd_wrtbiascalc_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfptrs_print;
-#else
-#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_rcvrbiascalc_print;
#else
#define ahd_rcvrbiascalc_print(regvalue, cur_col, wrap) \
@@ -1721,10 +1714,10 @@ ahd_reg_print_t ahd_rcvrbiascalc_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_dfbkptr_print;
+ahd_reg_print_t ahd_dfptrs_print;
#else
-#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#define ahd_dfptrs_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DFPTRS", 0xc8, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1735,6 +1728,13 @@ ahd_reg_print_t ahd_skewcalc_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_dfbkptr_print;
+#else
+#define ahd_dfbkptr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "DFBKPTR", 0xc9, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dfdbctl_print;
#else
#define ahd_dfdbctl_print(regvalue, cur_col, wrap) \
@@ -1826,17 +1826,17 @@ ahd_reg_print_t ahd_dindex_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr1_print;
+ahd_reg_print_t ahd_brkaddr0_print;
#else
-#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
+#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_brkaddr0_print;
+ahd_reg_print_t ahd_brkaddr1_print;
#else
-#define ahd_brkaddr0_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "BRKADDR0", 0xe6, regvalue, cur_col, wrap)
+#define ahd_brkaddr1_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "BRKADDR1", 0xe6, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1889,13 +1889,6 @@ ahd_reg_print_t ahd_stack_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_curaddr_print;
-#else
-#define ahd_curaddr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
-#endif
-
-#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_intvec1_addr_print;
#else
#define ahd_intvec1_addr_print(regvalue, cur_col, wrap) \
@@ -1903,10 +1896,10 @@ ahd_reg_print_t ahd_intvec1_addr_print;
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_intvec2_addr_print;
+ahd_reg_print_t ahd_curaddr_print;
#else
-#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#define ahd_curaddr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "CURADDR", 0xf4, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -1917,6 +1910,13 @@ ahd_reg_print_t ahd_lastaddr_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_intvec2_addr_print;
+#else
+#define ahd_intvec2_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "INTVEC2_ADDR", 0xf6, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_longjmp_addr_print;
#else
#define ahd_longjmp_addr_print(regvalue, cur_col, wrap) \
@@ -1994,192 +1994,213 @@ ahd_reg_print_t ahd_complete_dma_scb_head_print;
#endif
#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_dma_scb_tail_print;
+#else
+#define ahd_complete_dma_scb_tail_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL", 0x12e, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_complete_on_qfreeze_head_print;
+#else
+#define ahd_complete_on_qfreeze_head_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD", 0x130, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_qfreeze_count_print;
#else
#define ahd_qfreeze_count_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x12e, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "QFREEZE_COUNT", 0x132, regvalue, cur_col, wrap)
+#endif
+
+#if AIC_DEBUG_REGISTERS
+ahd_reg_print_t ahd_kernel_qfreeze_count_print;
+#else
+#define ahd_kernel_qfreeze_count_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT", 0x134, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_mode_print;
#else
#define ahd_saved_mode_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_MODE", 0x130, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_MODE", 0x136, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_msg_out_print;
#else
#define ahd_msg_out_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "MSG_OUT", 0x131, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "MSG_OUT", 0x137, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_dmaparams_print;
#else
#define ahd_dmaparams_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "DMAPARAMS", 0x132, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "DMAPARAMS", 0x138, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seq_flags_print;
#else
#define ahd_seq_flags_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x133, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SEQ_FLAGS", 0x139, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_scsiid_print;
#else
#define ahd_saved_scsiid_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x134, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_SCSIID", 0x13a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_saved_lun_print;
#else
#define ahd_saved_lun_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SAVED_LUN", 0x135, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SAVED_LUN", 0x13b, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_lastphase_print;
#else
#define ahd_lastphase_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LASTPHASE", 0x136, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LASTPHASE", 0x13c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_qoutfifo_entry_valid_tag_print;
#else
#define ahd_qoutfifo_entry_valid_tag_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x137, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG", 0x13d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_shared_data_addr_print;
+ahd_reg_print_t ahd_kernel_tqinpos_print;
#else
-#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x138, regvalue, cur_col, wrap)
+#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x13e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_qoutfifo_next_addr_print;
+ahd_reg_print_t ahd_tqinpos_print;
#else
-#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x13c, regvalue, cur_col, wrap)
+#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "TQINPOS", 0x13f, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_kernel_tqinpos_print;
+ahd_reg_print_t ahd_shared_data_addr_print;
#else
-#define ahd_kernel_tqinpos_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "KERNEL_TQINPOS", 0x140, regvalue, cur_col, wrap)
+#define ahd_shared_data_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "SHARED_DATA_ADDR", 0x140, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
-ahd_reg_print_t ahd_tqinpos_print;
+ahd_reg_print_t ahd_qoutfifo_next_addr_print;
#else
-#define ahd_tqinpos_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "TQINPOS", 0x141, regvalue, cur_col, wrap)
+#define ahd_qoutfifo_next_addr_print(regvalue, cur_col, wrap) \
+ ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR", 0x144, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_arg_1_print;
#else
#define ahd_arg_1_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_1", 0x142, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ARG_1", 0x148, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_arg_2_print;
#else
#define ahd_arg_2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ARG_2", 0x143, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ARG_2", 0x149, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_last_msg_print;
#else
#define ahd_last_msg_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LAST_MSG", 0x144, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LAST_MSG", 0x14a, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_scsiseq_template_print;
#else
#define ahd_scsiseq_template_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x145, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SCSISEQ_TEMPLATE", 0x14b, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_initiator_tag_print;
#else
#define ahd_initiator_tag_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x146, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INITIATOR_TAG", 0x14c, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_seq_flags2_print;
#else
#define ahd_seq_flags2_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x147, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "SEQ_FLAGS2", 0x14d, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_allocfifo_scbptr_print;
#else
#define ahd_allocfifo_scbptr_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x148, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR", 0x14e, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_timer_print;
#else
#define ahd_int_coalescing_timer_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x14a, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_TIMER", 0x150, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_maxcmds_print;
#else
#define ahd_int_coalescing_maxcmds_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x14c, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS", 0x152, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_mincmds_print;
#else
#define ahd_int_coalescing_mincmds_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x14d, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS", 0x153, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmds_pending_print;
#else
#define ahd_cmds_pending_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMDS_PENDING", 0x14e, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "CMDS_PENDING", 0x154, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_int_coalescing_cmdcount_print;
#else
#define ahd_int_coalescing_cmdcount_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x150, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT", 0x156, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_local_hs_mailbox_print;
#else
#define ahd_local_hs_mailbox_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x151, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX", 0x157, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
ahd_reg_print_t ahd_cmdsize_table_print;
#else
#define ahd_cmdsize_table_print(regvalue, cur_col, wrap) \
- ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x152, regvalue, cur_col, wrap)
+ ahd_print_register(NULL, 0, "CMDSIZE_TABLE", 0x158, regvalue, cur_col, wrap)
#endif
#if AIC_DEBUG_REGISTERS
@@ -2434,13 +2455,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define HOST_TQINPOS 0x80
#define ENINT_COALESCE 0x40
-#define CLRSEQINTSTAT 0x0c
-#define CLRSEQ_SWTMRTO 0x10
-#define CLRSEQ_SEQINT 0x08
-#define CLRSEQ_SCSIINT 0x04
-#define CLRSEQ_PCIINT 0x02
-#define CLRSEQ_SPLTINT 0x01
-
#define SEQINTSTAT 0x0c
#define SEQ_SWTMRTO 0x10
#define SEQ_SEQINT 0x08
@@ -2448,6 +2462,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEQ_PCIINT 0x02
#define SEQ_SPLTINT 0x01
+#define CLRSEQINTSTAT 0x0c
+#define CLRSEQ_SWTMRTO 0x10
+#define CLRSEQ_SEQINT 0x08
+#define CLRSEQ_SCSIINT 0x04
+#define CLRSEQ_PCIINT 0x02
+#define CLRSEQ_SPLTINT 0x01
+
#define SWTIMER 0x0e
#define SNSCB_QOFF 0x10
@@ -2623,10 +2644,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define BIOSCANCELEN 0x10
#define SPIOEN 0x08
-#define BUSINITID 0x3c
-
#define DLCOUNT 0x3c
+#define BUSINITID 0x3c
+
#define SXFRCTL1 0x3d
#define BITBUCKET 0x80
#define ENSACHK 0x40
@@ -2693,13 +2714,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SELID_MASK 0xf0
#define ONEBIT 0x08
-#define SBLKCTL 0x4a
-#define DIAGLEDEN 0x80
-#define DIAGLEDON 0x40
-#define ENAB40 0x08
-#define ENAB20 0x04
-#define SELWIDE 0x02
-
#define OPTIONMODE 0x4a
#define OPTIONMODE_DEFAULTS 0x02
#define BIOSCANCTL 0x80
@@ -2709,15 +2723,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENDGFORMCHK 0x04
#define AUTO_MSGOUT_DE 0x02
-#define SSTAT0 0x4b
-#define TARGET 0x80
-#define SELDO 0x40
-#define SELDI 0x20
-#define SELINGO 0x10
-#define IOERR 0x08
-#define OVERRUN 0x04
-#define SPIORDY 0x02
-#define ARBDO 0x01
+#define SBLKCTL 0x4a
+#define DIAGLEDEN 0x80
+#define DIAGLEDON 0x40
+#define ENAB40 0x08
+#define ENAB20 0x04
+#define SELWIDE 0x02
#define CLRSINT0 0x4b
#define CLRSELDO 0x40
@@ -2728,6 +2739,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRSPIORDY 0x02
#define CLRARBDO 0x01
+#define SSTAT0 0x4b
+#define TARGET 0x80
+#define SELDO 0x40
+#define SELDI 0x20
+#define SELINGO 0x10
+#define IOERR 0x08
+#define OVERRUN 0x04
+#define SPIORDY 0x02
+#define ARBDO 0x01
+
#define SIMODE0 0x4b
#define ENSELDO 0x40
#define ENSELDI 0x20
@@ -2768,17 +2789,17 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define BUSFREE_DFF0 0x80
#define BUSFREE_LQO 0x40
+#define SIMODE2 0x4d
+#define ENWIDE_RES 0x04
+#define ENSDONE 0x02
+#define ENDMADONE 0x01
+
#define CLRSINT2 0x4d
#define CLRNONPACKREQ 0x20
#define CLRWIDE_RES 0x04
#define CLRSDONE 0x02
#define CLRDMADONE 0x01
-#define SIMODE2 0x4d
-#define ENWIDE_RES 0x04
-#define ENSDONE 0x02
-#define ENDMADONE 0x01
-
#define PERRDIAG 0x4e
#define HIZERO 0x80
#define HIPERR 0x40
@@ -2871,13 +2892,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRNTRAMPERR 0x02
#define CLROSRAMPERR 0x01
-#define LQOMODE0 0x54
-#define ENLQOTARGSCBPERR 0x10
-#define ENLQOSTOPT2 0x08
-#define ENLQOATNLQ 0x04
-#define ENLQOATNPKT 0x02
-#define ENLQOTCRC 0x01
-
#define LQOSTAT0 0x54
#define LQOTARGSCBPERR 0x10
#define LQOSTOPT2 0x08
@@ -2892,6 +2906,20 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRLQOATNPKT 0x02
#define CLRLQOTCRC 0x01
+#define LQOMODE0 0x54
+#define ENLQOTARGSCBPERR 0x10
+#define ENLQOSTOPT2 0x08
+#define ENLQOATNLQ 0x04
+#define ENLQOATNPKT 0x02
+#define ENLQOTCRC 0x01
+
+#define LQOMODE1 0x55
+#define ENLQOINITSCBPERR 0x10
+#define ENLQOSTOPI2 0x08
+#define ENLQOBADQAS 0x04
+#define ENLQOBUSFREE 0x02
+#define ENLQOPHACHGINPKT 0x01
+
#define LQOSTAT1 0x55
#define LQOINITSCBPERR 0x10
#define LQOSTOPI2 0x08
@@ -2906,13 +2934,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CLRLQOBUSFREE 0x02
#define CLRLQOPHACHGINPKT 0x01
-#define LQOMODE1 0x55
-#define ENLQOINITSCBPERR 0x10
-#define ENLQOSTOPI2 0x08
-#define ENLQOBADQAS 0x04
-#define ENLQOBUSFREE 0x02
-#define ENLQOPHACHGINPKT 0x01
-
#define LQOSTAT2 0x56
#define LQOPKT 0xe0
#define LQOWAITFIFO 0x10
@@ -3028,6 +3049,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ANNEXCOL 0x65
+#define ANNEXDAT 0x66
+
#define SCSCHKN 0x66
#define STSELSKIDDIS 0x40
#define CURRFIFODEF 0x20
@@ -3037,8 +3060,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SHVALIDSTDIS 0x02
#define LSTSGCLRDIS 0x01
-#define ANNEXDAT 0x66
-
#define IOWNID 0x67
#define PLL960CTL0 0x68
@@ -3071,10 +3092,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define PLL_CNTCLR 0x40
#define PLL_RST 0x01
-#define PLL400CNT0 0x6e
-
#define UNFAIRNESS 0x6e
+#define PLL400CNT0 0x6e
+
#define HADDR 0x70
#define PLLDELAY 0x70
@@ -3088,14 +3109,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define HODMAEN 0x7a
-#define SGHADDR 0x7c
-
#define SCBHADDR 0x7c
-#define SGHCNT 0x84
+#define SGHADDR 0x7c
#define SCBHCNT 0x84
+#define SGHCNT 0x84
+
#define DFF_THRSH 0x88
#define WR_DFTHRSH 0x70
#define RD_DFTHRSH 0x07
@@ -3113,8 +3134,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define RD_DFTHRSH_63 0x03
#define RD_DFTHRSH_50 0x02
#define RD_DFTHRSH_25 0x01
-#define WR_DFTHRSH_MIN 0x00
#define RD_DFTHRSH_MIN 0x00
+#define WR_DFTHRSH_MIN 0x00
#define ROMADDR 0x8a
@@ -3150,20 +3171,22 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DCH1NSEN 0x02
#define DCH0NSEN 0x01
-#define DCHRXMSG1 0x91
-
#define CMCRXMSG1 0x91
-#define DCHRXMSG2 0x92
+#define DCHRXMSG1 0x91
-#define OVLYRXMSG2 0x92
+#define DCHRXMSG2 0x92
#define CMCRXMSG2 0x92
#define OST 0x92
+#define OVLYRXMSG2 0x92
+
#define DCHRXMSG3 0x93
+#define OVLYRXMSG3 0x93
+
#define CMCRXMSG3 0x93
#define PCIXCTL 0x93
@@ -3175,26 +3198,24 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define TSCSERREN 0x02
#define CMPABCDIS 0x01
-#define OVLYRXMSG3 0x93
-
#define OVLYSEQBCNT 0x94
-#define CMCSEQBCNT 0x94
-
#define DCHSEQBCNT 0x94
-#define CMCSPLTSTAT0 0x96
+#define CMCSEQBCNT 0x94
-#define OVLYSPLTSTAT0 0x96
+#define CMCSPLTSTAT0 0x96
#define DCHSPLTSTAT0 0x96
-#define DCHSPLTSTAT1 0x97
+#define OVLYSPLTSTAT0 0x96
#define CMCSPLTSTAT1 0x97
#define OVLYSPLTSTAT1 0x97
+#define DCHSPLTSTAT1 0x97
+
#define SGRXMSG0 0x98
#define CDNUM 0xf8
#define CFNUM 0x07
@@ -3244,13 +3265,13 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define RXSCEMSG 0x02
#define RXSPLTRSP 0x01
+#define SGSPLTSTAT1 0x9f
+#define RXDATABUCKET 0x01
+
#define SFUNCT 0x9f
#define TEST_GROUP 0xf0
#define TEST_NUM 0x0f
-#define SGSPLTSTAT1 0x9f
-#define RXDATABUCKET 0x01
-
#define DF0PCISTAT 0xa0
#define REG0 0xa0
@@ -3299,10 +3320,10 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CCSGADDR 0xac
-#define CCSCBADDR 0xac
-
#define CCSCBADR_BK 0xac
+#define CCSCBADDR 0xac
+
#define CMC_RAMBIST 0xad
#define SG_ELEMENT_SIZE 0x80
#define SCBRAMBIST_FAIL 0x40
@@ -3311,14 +3332,6 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CMC_BUFFER_BIST_FAIL 0x02
#define CMC_BUFFER_BIST_EN 0x01
-#define CCSGCTL 0xad
-#define CCSGEN 0x0c
-#define CCSGDONE 0x80
-#define SG_CACHE_AVAIL 0x10
-#define CCSGENACK 0x08
-#define SG_FETCH_REQ 0x02
-#define CCSGRESET 0x01
-
#define CCSCBCTL 0xad
#define CCSCBDONE 0x80
#define ARRDONE 0x40
@@ -3327,6 +3340,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CCSCBDIR 0x04
#define CCSCBRESET 0x01
+#define CCSGCTL 0xad
+#define CCSGEN 0x0c
+#define CCSGDONE 0x80
+#define SG_CACHE_AVAIL 0x10
+#define CCSGENACK 0x08
+#define SG_FETCH_REQ 0x02
+#define CCSGRESET 0x01
+
#define CCSGRAM 0xb0
#define FLEXADR 0xb0
@@ -3356,8 +3377,8 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SEEDAT 0xbc
#define SEECTL 0xbe
-#define SEEOP_EWEN 0x40
#define SEEOP_WALL 0x40
+#define SEEOP_EWEN 0x40
#define SEEOP_EWDS 0x40
#define SEEOPCODE 0x70
#define SEERST 0x02
@@ -3414,14 +3435,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define WRTBIASCALC 0xc7
-#define DFPTRS 0xc8
-
#define RCVRBIASCALC 0xc8
-#define DFBKPTR 0xc9
+#define DFPTRS 0xc8
#define SKEWCALC 0xc9
+#define DFBKPTR 0xc9
+
#define DFDBCTL 0xcb
#define DFF_CIO_WR_RDY 0x20
#define DFF_CIO_RD_RDY 0x10
@@ -3475,11 +3496,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define DINDEX 0xe4
+#define BRKADDR0 0xe6
+
#define BRKADDR1 0xe6
#define BRKDIS 0x80
-#define BRKADDR0 0xe6
-
#define ALLONES 0xe8
#define ALLZEROS 0xea
@@ -3494,14 +3515,14 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define STACK 0xf2
-#define CURADDR 0xf4
-
#define INTVEC1_ADDR 0xf4
-#define INTVEC2_ADDR 0xf6
+#define CURADDR 0xf4
#define LASTADDR 0xf6
+#define INTVEC2_ADDR 0xf6
+
#define LONGJMP_ADDR 0xf8
#define ACCUM_SAVE 0xfa
@@ -3524,25 +3545,31 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define COMPLETE_DMA_SCB_HEAD 0x12c
-#define QFREEZE_COUNT 0x12e
+#define COMPLETE_DMA_SCB_TAIL 0x12e
+
+#define COMPLETE_ON_QFREEZE_HEAD 0x130
+
+#define QFREEZE_COUNT 0x132
-#define SAVED_MODE 0x130
+#define KERNEL_QFREEZE_COUNT 0x134
-#define MSG_OUT 0x131
+#define SAVED_MODE 0x136
-#define DMAPARAMS 0x132
+#define MSG_OUT 0x137
+
+#define DMAPARAMS 0x138
#define PRELOADEN 0x80
#define WIDEODD 0x40
#define SCSIEN 0x20
#define SDMAEN 0x10
#define SDMAENACK 0x10
-#define HDMAENACK 0x08
#define HDMAEN 0x08
+#define HDMAENACK 0x08
#define DIRECTION 0x04
#define FIFOFLUSH 0x02
#define FIFORESET 0x01
-#define SEQ_FLAGS 0x133
+#define SEQ_FLAGS 0x139
#define NOT_IDENTIFIED 0x80
#define NO_CDB_SENT 0x40
#define TARGET_CMD_IS_TAGGED 0x40
@@ -3553,11 +3580,11 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SPHASE_PENDING 0x02
#define NO_DISCONNECT 0x01
-#define SAVED_SCSIID 0x134
+#define SAVED_SCSIID 0x13a
-#define SAVED_LUN 0x135
+#define SAVED_LUN 0x13b
-#define LASTPHASE 0x136
+#define LASTPHASE 0x13c
#define PHASE_MASK 0xe0
#define CDI 0x80
#define IOI 0x40
@@ -3572,18 +3599,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define P_DATAOUT_DT 0x20
#define P_DATAOUT 0x00
-#define QOUTFIFO_ENTRY_VALID_TAG 0x137
+#define QOUTFIFO_ENTRY_VALID_TAG 0x13d
-#define SHARED_DATA_ADDR 0x138
+#define KERNEL_TQINPOS 0x13e
-#define QOUTFIFO_NEXT_ADDR 0x13c
+#define TQINPOS 0x13f
-#define KERNEL_TQINPOS 0x140
+#define SHARED_DATA_ADDR 0x140
-#define TQINPOS 0x141
+#define QOUTFIFO_NEXT_ADDR 0x144
-#define ARG_1 0x142
-#define RETURN_1 0x142
+#define ARG_1 0x148
+#define RETURN_1 0x148
#define SEND_MSG 0x80
#define SEND_SENSE 0x40
#define SEND_REJ 0x20
@@ -3593,12 +3620,12 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define CONT_MSG_LOOP_READ 0x03
#define CONT_MSG_LOOP_TARG 0x02
-#define ARG_2 0x143
-#define RETURN_2 0x143
+#define ARG_2 0x149
+#define RETURN_2 0x149
-#define LAST_MSG 0x144
+#define LAST_MSG 0x14a
-#define SCSISEQ_TEMPLATE 0x145
+#define SCSISEQ_TEMPLATE 0x14b
#define MANUALCTL 0x40
#define ENSELI 0x20
#define ENRSELI 0x10
@@ -3606,27 +3633,27 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define ENAUTOATNP 0x02
#define ALTSTIM 0x01
-#define INITIATOR_TAG 0x146
+#define INITIATOR_TAG 0x14c
-#define SEQ_FLAGS2 0x147
+#define SEQ_FLAGS2 0x14d
#define SELECTOUT_QFROZEN 0x04
#define TARGET_MSG_PENDING 0x02
-#define ALLOCFIFO_SCBPTR 0x148
+#define ALLOCFIFO_SCBPTR 0x14e
-#define INT_COALESCING_TIMER 0x14a
+#define INT_COALESCING_TIMER 0x150
-#define INT_COALESCING_MAXCMDS 0x14c
+#define INT_COALESCING_MAXCMDS 0x152
-#define INT_COALESCING_MINCMDS 0x14d
+#define INT_COALESCING_MINCMDS 0x153
-#define CMDS_PENDING 0x14e
+#define CMDS_PENDING 0x154
-#define INT_COALESCING_CMDCOUNT 0x150
+#define INT_COALESCING_CMDCOUNT 0x156
-#define LOCAL_HS_MAILBOX 0x151
+#define LOCAL_HS_MAILBOX 0x157
-#define CMDSIZE_TABLE 0x152
+#define CMDSIZE_TABLE 0x158
#define SCB_BASE 0x180
@@ -3701,6 +3728,16 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SCB_DISCONNECTED_LISTS 0x1b8
+#define AHD_TIMER_MAX_US 0x18ffe7
+#define AHD_TIMER_MAX_TICKS 0xffff
+#define AHD_SENSE_BUFSIZE 0x100
+#define BUS_8_BIT 0x00
+#define TARGET_CMD_CMPLT 0xfe
+#define SEEOP_WRAL_ADDR 0x40
+#define AHD_AMPLITUDE_DEF 0x07
+#define AHD_PRECOMP_CUTBACK_37 0x07
+#define AHD_PRECOMP_SHIFT 0x00
+#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
#define AHD_TIMER_US_PER_TICK 0x19
#define SCB_TRANSFER_SIZE_FULL_LUN 0x38
#define STATUS_QUEUE_FULL 0x28
@@ -3724,28 +3761,18 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define B_CURRFIFO_0 0x02
#define LUNLEN_SINGLE_LEVEL_LUN 0x0f
#define NVRAM_SCB_OFFSET 0x2c
-#define AHD_TIMER_MAX_US 0x18ffe7
-#define AHD_TIMER_MAX_TICKS 0xffff
#define STATUS_PKT_SENSE 0xff
#define CMD_GROUP_CODE_SHIFT 0x05
-#define AHD_SENSE_BUFSIZE 0x100
#define MAX_OFFSET_PACED_BUG 0x7f
-#define BUS_8_BIT 0x00
#define STIMESEL_BUG_ADJ 0x08
#define STIMESEL_MIN 0x18
#define STIMESEL_SHIFT 0x03
#define CCSGRAM_MAXSEGS 0x10
#define INVALID_ADDR 0x80
-#define TARGET_CMD_CMPLT 0xfe
-#define SEEOP_WRAL_ADDR 0x40
#define SEEOP_ERAL_ADDR 0x80
-#define AHD_AMPLITUDE_DEF 0x07
#define AHD_SLEWRATE_DEF_REVB 0x08
-#define AHD_PRECOMP_CUTBACK_37 0x07
#define AHD_PRECOMP_CUTBACK_17 0x04
-#define AHD_PRECOMP_SHIFT 0x00
#define AHD_PRECOMP_MASK 0x07
-#define AHD_ANNEXCOL_PRECOMP_SLEW 0x04
#define SRC_MODE_SHIFT 0x00
#define PKT_OVERRUN_BUFSIZE 0x200
#define SCB_TRANSFER_SIZE_1BYTE_LUN 0x30
@@ -3761,6 +3788,7 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
/* Downloaded Constant Definitions */
+#define CACHELINE_MASK 0x07
#define SCB_TRANSFER_SIZE 0x06
#define PKT_OVERRUN_BUFOFFSET 0x05
#define SG_SIZEOF 0x04
@@ -3768,9 +3796,9 @@ ahd_reg_print_t ahd_scb_disconnected_lists_print;
#define SG_PREFETCH_ALIGN_MASK 0x02
#define SG_PREFETCH_CNT_LIMIT 0x01
#define SG_PREFETCH_CNT 0x00
-#define DOWNLOAD_CONST_COUNT 0x07
+#define DOWNLOAD_CONST_COUNT 0x08
/* Exported Labels */
-#define LABEL_seq_isr 0x269
-#define LABEL_timer_isr 0x265
+#define LABEL_seq_isr 0x285
+#define LABEL_timer_isr 0x281
diff --git a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
index 3098a757e3d7..a4137c985376 100644
--- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_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/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#118 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#75 $
*/
#include "aic79xx_osm.h"
@@ -172,21 +172,6 @@ ahd_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0b, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
- { "CLRSEQ_SPLTINT", 0x01, 0x01 },
- { "CLRSEQ_PCIINT", 0x02, 0x02 },
- { "CLRSEQ_SCSIINT", 0x04, 0x04 },
- { "CLRSEQ_SEQINT", 0x08, 0x08 },
- { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
-};
-
-int
-ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
- 0x0c, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t SEQINTSTAT_parse_table[] = {
{ "SEQ_SPLTINT", 0x01, 0x01 },
{ "SEQ_PCIINT", 0x02, 0x02 },
@@ -202,6 +187,21 @@ ahd_seqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x0c, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t CLRSEQINTSTAT_parse_table[] = {
+ { "CLRSEQ_SPLTINT", 0x01, 0x01 },
+ { "CLRSEQ_PCIINT", 0x02, 0x02 },
+ { "CLRSEQ_SCSIINT", 0x04, 0x04 },
+ { "CLRSEQ_SEQINT", 0x08, 0x08 },
+ { "CLRSEQ_SWTMRTO", 0x10, 0x10 }
+};
+
+int
+ahd_clrseqintstat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(CLRSEQINTSTAT_parse_table, 5, "CLRSEQINTSTAT",
+ 0x0c, regvalue, cur_col, wrap));
+}
+
int
ahd_swtimer_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -670,16 +670,16 @@ ahd_sxfrctl0_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "BUSINITID",
+ return (ahd_print_register(NULL, 0, "DLCOUNT",
0x3c, regvalue, cur_col, wrap));
}
int
-ahd_dlcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_businitid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DLCOUNT",
+ return (ahd_print_register(NULL, 0, "BUSINITID",
0x3c, regvalue, cur_col, wrap));
}
@@ -859,21 +859,6 @@ ahd_selid_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x49, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
- { "SELWIDE", 0x02, 0x02 },
- { "ENAB20", 0x04, 0x04 },
- { "ENAB40", 0x08, 0x08 },
- { "DIAGLEDON", 0x40, 0x40 },
- { "DIAGLEDEN", 0x80, 0x80 }
-};
-
-int
-ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
- 0x4a, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t OPTIONMODE_parse_table[] = {
{ "AUTO_MSGOUT_DE", 0x02, 0x02 },
{ "ENDGFORMCHK", 0x04, 0x04 },
@@ -891,22 +876,19 @@ ahd_optionmode_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4a, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
- { "ARBDO", 0x01, 0x01 },
- { "SPIORDY", 0x02, 0x02 },
- { "OVERRUN", 0x04, 0x04 },
- { "IOERR", 0x08, 0x08 },
- { "SELINGO", 0x10, 0x10 },
- { "SELDI", 0x20, 0x20 },
- { "SELDO", 0x40, 0x40 },
- { "TARGET", 0x80, 0x80 }
+static ahd_reg_parse_entry_t SBLKCTL_parse_table[] = {
+ { "SELWIDE", 0x02, 0x02 },
+ { "ENAB20", 0x04, 0x04 },
+ { "ENAB40", 0x08, 0x08 },
+ { "DIAGLEDON", 0x40, 0x40 },
+ { "DIAGLEDEN", 0x80, 0x80 }
};
int
-ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sblkctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
- 0x4b, regvalue, cur_col, wrap));
+ return (ahd_print_register(SBLKCTL_parse_table, 5, "SBLKCTL",
+ 0x4a, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t CLRSINT0_parse_table[] = {
@@ -926,6 +908,24 @@ ahd_clrsint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4b, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t SSTAT0_parse_table[] = {
+ { "ARBDO", 0x01, 0x01 },
+ { "SPIORDY", 0x02, 0x02 },
+ { "OVERRUN", 0x04, 0x04 },
+ { "IOERR", 0x08, 0x08 },
+ { "SELINGO", 0x10, 0x10 },
+ { "SELDI", 0x20, 0x20 },
+ { "SELDO", 0x40, 0x40 },
+ { "TARGET", 0x80, 0x80 }
+};
+
+int
+ahd_sstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(SSTAT0_parse_table, 8, "SSTAT0",
+ 0x4b, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t SIMODE0_parse_table[] = {
{ "ENARBDO", 0x01, 0x01 },
{ "ENSPIORDY", 0x02, 0x02 },
@@ -998,30 +998,30 @@ ahd_sstat2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x4d, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
- { "CLRDMADONE", 0x01, 0x01 },
- { "CLRSDONE", 0x02, 0x02 },
- { "CLRWIDE_RES", 0x04, 0x04 },
- { "CLRNONPACKREQ", 0x20, 0x20 }
+static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
+ { "ENDMADONE", 0x01, 0x01 },
+ { "ENSDONE", 0x02, 0x02 },
+ { "ENWIDE_RES", 0x04, 0x04 }
};
int
-ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
+ return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
0x4d, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SIMODE2_parse_table[] = {
- { "ENDMADONE", 0x01, 0x01 },
- { "ENSDONE", 0x02, 0x02 },
- { "ENWIDE_RES", 0x04, 0x04 }
+static ahd_reg_parse_entry_t CLRSINT2_parse_table[] = {
+ { "CLRDMADONE", 0x01, 0x01 },
+ { "CLRSDONE", 0x02, 0x02 },
+ { "CLRWIDE_RES", 0x04, 0x04 },
+ { "CLRNONPACKREQ", 0x20, 0x20 }
};
int
-ahd_simode2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_clrsint2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SIMODE2_parse_table, 3, "SIMODE2",
+ return (ahd_print_register(CLRSINT2_parse_table, 4, "CLRSINT2",
0x4d, regvalue, cur_col, wrap));
}
@@ -1220,21 +1220,6 @@ ahd_clrsint3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x53, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
- { "ENLQOTCRC", 0x01, 0x01 },
- { "ENLQOATNPKT", 0x02, 0x02 },
- { "ENLQOATNLQ", 0x04, 0x04 },
- { "ENLQOSTOPT2", 0x08, 0x08 },
- { "ENLQOTARGSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
- 0x54, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t LQOSTAT0_parse_table[] = {
{ "LQOTCRC", 0x01, 0x01 },
{ "LQOATNPKT", 0x02, 0x02 },
@@ -1265,6 +1250,36 @@ ahd_clrlqoint0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x54, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t LQOMODE0_parse_table[] = {
+ { "ENLQOTCRC", 0x01, 0x01 },
+ { "ENLQOATNPKT", 0x02, 0x02 },
+ { "ENLQOATNLQ", 0x04, 0x04 },
+ { "ENLQOSTOPT2", 0x08, 0x08 },
+ { "ENLQOTARGSCBPERR", 0x10, 0x10 }
+};
+
+int
+ahd_lqomode0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(LQOMODE0_parse_table, 5, "LQOMODE0",
+ 0x54, regvalue, cur_col, wrap));
+}
+
+static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
+ { "ENLQOPHACHGINPKT", 0x01, 0x01 },
+ { "ENLQOBUSFREE", 0x02, 0x02 },
+ { "ENLQOBADQAS", 0x04, 0x04 },
+ { "ENLQOSTOPI2", 0x08, 0x08 },
+ { "ENLQOINITSCBPERR", 0x10, 0x10 }
+};
+
+int
+ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
+ 0x55, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t LQOSTAT1_parse_table[] = {
{ "LQOPHACHGINPKT", 0x01, 0x01 },
{ "LQOBUSFREE", 0x02, 0x02 },
@@ -1295,21 +1310,6 @@ ahd_clrlqoint1_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x55, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t LQOMODE1_parse_table[] = {
- { "ENLQOPHACHGINPKT", 0x01, 0x01 },
- { "ENLQOBUSFREE", 0x02, 0x02 },
- { "ENLQOBADQAS", 0x04, 0x04 },
- { "ENLQOSTOPI2", 0x08, 0x08 },
- { "ENLQOINITSCBPERR", 0x10, 0x10 }
-};
-
-int
-ahd_lqomode1_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(LQOMODE1_parse_table, 5, "LQOMODE1",
- 0x55, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t LQOSTAT2_parse_table[] = {
{ "LQOSTOP0", 0x01, 0x01 },
{ "LQOPHACHGOUTPKT", 0x02, 0x02 },
@@ -1594,6 +1594,13 @@ ahd_annexcol_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x65, regvalue, cur_col, wrap));
}
+int
+ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "ANNEXDAT",
+ 0x66, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t SCSCHKN_parse_table[] = {
{ "LSTSGCLRDIS", 0x01, 0x01 },
{ "SHVALIDSTDIS", 0x02, 0x02 },
@@ -1612,13 +1619,6 @@ ahd_scschkn_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_annexdat_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "ANNEXDAT",
- 0x66, regvalue, cur_col, wrap));
-}
-
-int
ahd_iownid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "IOWNID",
@@ -1728,16 +1728,16 @@ ahd_pll400ctl1_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "PLL400CNT0",
+ return (ahd_print_register(NULL, 0, "UNFAIRNESS",
0x6e, regvalue, cur_col, wrap));
}
int
-ahd_unfairness_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_pll400cnt0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "UNFAIRNESS",
+ return (ahd_print_register(NULL, 0, "PLL400CNT0",
0x6e, regvalue, cur_col, wrap));
}
@@ -1788,30 +1788,30 @@ ahd_hodmaen_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SGHADDR",
+ return (ahd_print_register(NULL, 0, "SCBHADDR",
0x7c, regvalue, cur_col, wrap));
}
int
-ahd_scbhaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SCBHADDR",
+ return (ahd_print_register(NULL, 0, "SGHADDR",
0x7c, regvalue, cur_col, wrap));
}
int
-ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SGHCNT",
+ return (ahd_print_register(NULL, 0, "SCBHCNT",
0x84, regvalue, cur_col, wrap));
}
int
-ahd_scbhcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sghcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SCBHCNT",
+ return (ahd_print_register(NULL, 0, "SGHCNT",
0x84, regvalue, cur_col, wrap));
}
@@ -1950,25 +1950,25 @@ ahd_nsenable_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x91, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
+static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
{ "CBNUM", 0xff, 0xff }
};
int
-ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
+ return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
0x91, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CMCRXMSG1_parse_table[] = {
+static ahd_reg_parse_entry_t DCHRXMSG1_parse_table[] = {
{ "CBNUM", 0xff, 0xff }
};
int
-ahd_cmcrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchrxmsg1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CMCRXMSG1_parse_table, 1, "CMCRXMSG1",
+ return (ahd_print_register(DCHRXMSG1_parse_table, 1, "DCHRXMSG1",
0x91, regvalue, cur_col, wrap));
}
@@ -1983,17 +1983,6 @@ ahd_dchrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
- { "MINDEX", 0xff, 0xff }
-};
-
-int
-ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
- 0x92, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t CMCRXMSG2_parse_table[] = {
{ "MINDEX", 0xff, 0xff }
};
@@ -2012,6 +2001,17 @@ ahd_ost_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x92, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t OVLYRXMSG2_parse_table[] = {
+ { "MINDEX", 0xff, 0xff }
+};
+
+int
+ahd_ovlyrxmsg2_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(OVLYRXMSG2_parse_table, 1, "OVLYRXMSG2",
+ 0x92, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t DCHRXMSG3_parse_table[] = {
{ "MCLASS", 0x0f, 0x0f }
};
@@ -2023,6 +2023,17 @@ ahd_dchrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x93, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
+ { "MCLASS", 0x0f, 0x0f }
+};
+
+int
+ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
+ 0x93, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t CMCRXMSG3_parse_table[] = {
{ "MCLASS", 0x0f, 0x0f }
};
@@ -2051,17 +2062,6 @@ ahd_pcixctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x93, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYRXMSG3_parse_table[] = {
- { "MCLASS", 0x0f, 0x0f }
-};
-
-int
-ahd_ovlyrxmsg3_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(OVLYRXMSG3_parse_table, 1, "OVLYRXMSG3",
- 0x93, regvalue, cur_col, wrap));
-}
-
int
ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -2070,16 +2070,16 @@ ahd_ovlyseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
+ return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
0x94, regvalue, cur_col, wrap));
}
int
-ahd_dchseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcseqbcnt_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DCHSEQBCNT",
+ return (ahd_print_register(NULL, 0, "CMCSEQBCNT",
0x94, regvalue, cur_col, wrap));
}
@@ -2101,7 +2101,7 @@ ahd_cmcspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
+static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
{ "RXSPLTRSP", 0x01, 0x01 },
{ "RXSCEMSG", 0x02, 0x02 },
{ "RXOVRUN", 0x04, 0x04 },
@@ -2113,13 +2113,13 @@ static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
};
int
-ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
+ return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
+static ahd_reg_parse_entry_t OVLYSPLTSTAT0_parse_table[] = {
{ "RXSPLTRSP", 0x01, 0x01 },
{ "RXSCEMSG", 0x02, 0x02 },
{ "RXOVRUN", 0x04, 0x04 },
@@ -2131,42 +2131,42 @@ static ahd_reg_parse_entry_t DCHSPLTSTAT0_parse_table[] = {
};
int
-ahd_dchspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ovlyspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHSPLTSTAT0_parse_table, 8, "DCHSPLTSTAT0",
+ return (ahd_print_register(OVLYSPLTSTAT0_parse_table, 8, "OVLYSPLTSTAT0",
0x96, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
+ return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CMCSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_cmcspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(CMCSPLTSTAT1_parse_table, 1, "CMCSPLTSTAT1",
+ return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t OVLYSPLTSTAT1_parse_table[] = {
+static ahd_reg_parse_entry_t DCHSPLTSTAT1_parse_table[] = {
{ "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_ovlyspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dchspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(OVLYSPLTSTAT1_parse_table, 1, "OVLYSPLTSTAT1",
+ return (ahd_print_register(DCHSPLTSTAT1_parse_table, 1, "DCHSPLTSTAT1",
0x97, regvalue, cur_col, wrap));
}
@@ -2320,26 +2320,26 @@ ahd_sgspltstat0_print(u_int regvalue, u_int *cur_col, u_int wrap)
0x9e, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
- { "TEST_NUM", 0x0f, 0x0f },
- { "TEST_GROUP", 0xf0, 0xf0 }
+static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
+ { "RXDATABUCKET", 0x01, 0x01 }
};
int
-ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
+ return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
0x9f, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t SGSPLTSTAT1_parse_table[] = {
- { "RXDATABUCKET", 0x01, 0x01 }
+static ahd_reg_parse_entry_t SFUNCT_parse_table[] = {
+ { "TEST_NUM", 0x0f, 0x0f },
+ { "TEST_GROUP", 0xf0, 0xf0 }
};
int
-ahd_sgspltstat1_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_sfunct_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(SGSPLTSTAT1_parse_table, 1, "SGSPLTSTAT1",
+ return (ahd_print_register(SFUNCT_parse_table, 2, "SFUNCT",
0x9f, regvalue, cur_col, wrap));
}
@@ -2537,16 +2537,16 @@ ahd_ccsgaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CCSCBADDR",
+ return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
0xac, regvalue, cur_col, wrap));
}
int
-ahd_ccscbadr_bk_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_ccscbaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CCSCBADR_BK",
+ return (ahd_print_register(NULL, 0, "CCSCBADDR",
0xac, regvalue, cur_col, wrap));
}
@@ -2566,22 +2566,6 @@ ahd_cmc_rambist_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xad, regvalue, cur_col, wrap));
}
-static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
- { "CCSGRESET", 0x01, 0x01 },
- { "SG_FETCH_REQ", 0x02, 0x02 },
- { "CCSGENACK", 0x08, 0x08 },
- { "SG_CACHE_AVAIL", 0x10, 0x10 },
- { "CCSGDONE", 0x80, 0x80 },
- { "CCSGEN", 0x0c, 0x0c }
-};
-
-int
-ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
- 0xad, regvalue, cur_col, wrap));
-}
-
static ahd_reg_parse_entry_t CCSCBCTL_parse_table[] = {
{ "CCSCBRESET", 0x01, 0x01 },
{ "CCSCBDIR", 0x04, 0x04 },
@@ -2598,6 +2582,22 @@ ahd_ccscbctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xad, regvalue, cur_col, wrap));
}
+static ahd_reg_parse_entry_t CCSGCTL_parse_table[] = {
+ { "CCSGRESET", 0x01, 0x01 },
+ { "SG_FETCH_REQ", 0x02, 0x02 },
+ { "CCSGENACK", 0x08, 0x08 },
+ { "SG_CACHE_AVAIL", 0x10, 0x10 },
+ { "CCSGDONE", 0x80, 0x80 },
+ { "CCSGEN", 0x0c, 0x0c }
+};
+
+int
+ahd_ccsgctl_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(CCSGCTL_parse_table, 6, "CCSGCTL",
+ 0xad, regvalue, cur_col, wrap));
+}
+
int
ahd_ccsgram_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
@@ -2841,30 +2841,30 @@ ahd_wrtbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DFPTRS",
+ return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
0xc8, regvalue, cur_col, wrap));
}
int
-ahd_rcvrbiascalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dfptrs_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "RCVRBIASCALC",
+ return (ahd_print_register(NULL, 0, "DFPTRS",
0xc8, regvalue, cur_col, wrap));
}
int
-ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "DFBKPTR",
+ return (ahd_print_register(NULL, 0, "SKEWCALC",
0xc9, regvalue, cur_col, wrap));
}
int
-ahd_skewcalc_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_dfbkptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SKEWCALC",
+ return (ahd_print_register(NULL, 0, "DFBKPTR",
0xc9, regvalue, cur_col, wrap));
}
@@ -3001,6 +3001,13 @@ ahd_dindex_print(u_int regvalue, u_int *cur_col, u_int wrap)
0xe4, regvalue, cur_col, wrap));
}
+int
+ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "BRKADDR0",
+ 0xe6, regvalue, cur_col, wrap));
+}
+
static ahd_reg_parse_entry_t BRKADDR1_parse_table[] = {
{ "BRKDIS", 0x80, 0x80 }
};
@@ -3013,13 +3020,6 @@ ahd_brkaddr1_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_brkaddr0_print(u_int regvalue, u_int *cur_col, u_int wrap)
-{
- return (ahd_print_register(NULL, 0, "BRKADDR0",
- 0xe6, regvalue, cur_col, wrap));
-}
-
-int
ahd_allones_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ALLONES",
@@ -3069,30 +3069,30 @@ ahd_stack_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
-ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "CURADDR",
+ return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
0xf4, regvalue, cur_col, wrap));
}
int
-ahd_intvec1_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_curaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "INTVEC1_ADDR",
+ return (ahd_print_register(NULL, 0, "CURADDR",
0xf4, regvalue, cur_col, wrap));
}
int
-ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
+ return (ahd_print_register(NULL, 0, "LASTADDR",
0xf6, regvalue, cur_col, wrap));
}
int
-ahd_lastaddr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_intvec2_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "LASTADDR",
+ return (ahd_print_register(NULL, 0, "INTVEC2_ADDR",
0xf6, regvalue, cur_col, wrap));
}
@@ -3174,24 +3174,45 @@ ahd_complete_dma_scb_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
}
int
+ahd_complete_dma_scb_tail_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "COMPLETE_DMA_SCB_TAIL",
+ 0x12e, regvalue, cur_col, wrap));
+}
+
+int
+ahd_complete_on_qfreeze_head_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "COMPLETE_ON_QFREEZE_HEAD",
+ 0x130, regvalue, cur_col, wrap));
+}
+
+int
ahd_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "QFREEZE_COUNT",
- 0x12e, regvalue, cur_col, wrap));
+ 0x132, regvalue, cur_col, wrap));
+}
+
+int
+ahd_kernel_qfreeze_count_print(u_int regvalue, u_int *cur_col, u_int wrap)
+{
+ return (ahd_print_register(NULL, 0, "KERNEL_QFREEZE_COUNT",
+ 0x134, regvalue, cur_col, wrap));
}
int
ahd_saved_mode_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_MODE",
- 0x130, regvalue, cur_col, wrap));
+ 0x136, regvalue, cur_col, wrap));
}
int
ahd_msg_out_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "MSG_OUT",
- 0x131, regvalue, cur_col, wrap));
+ 0x137, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t DMAPARAMS_parse_table[] = {
@@ -3211,7 +3232,7 @@ int
ahd_dmaparams_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(DMAPARAMS_parse_table, 10, "DMAPARAMS",
- 0x132, regvalue, cur_col, wrap));
+ 0x138, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SEQ_FLAGS_parse_table[] = {
@@ -3230,21 +3251,21 @@ int
ahd_seq_flags_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQ_FLAGS_parse_table, 9, "SEQ_FLAGS",
- 0x133, regvalue, cur_col, wrap));
+ 0x139, regvalue, cur_col, wrap));
}
int
ahd_saved_scsiid_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_SCSIID",
- 0x134, regvalue, cur_col, wrap));
+ 0x13a, regvalue, cur_col, wrap));
}
int
ahd_saved_lun_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "SAVED_LUN",
- 0x135, regvalue, cur_col, wrap));
+ 0x13b, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t LASTPHASE_parse_table[] = {
@@ -3267,42 +3288,42 @@ int
ahd_lastphase_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(LASTPHASE_parse_table, 13, "LASTPHASE",
- 0x136, regvalue, cur_col, wrap));
+ 0x13c, regvalue, cur_col, wrap));
}
int
ahd_qoutfifo_entry_valid_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "QOUTFIFO_ENTRY_VALID_TAG",
- 0x137, regvalue, cur_col, wrap));
+ 0x13d, regvalue, cur_col, wrap));
}
int
-ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
- 0x138, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
+ 0x13e, regvalue, cur_col, wrap));
}
int
-ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
- 0x13c, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "TQINPOS",
+ 0x13f, regvalue, cur_col, wrap));
}
int
-ahd_kernel_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_shared_data_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "KERNEL_TQINPOS",
+ return (ahd_print_register(NULL, 0, "SHARED_DATA_ADDR",
0x140, regvalue, cur_col, wrap));
}
int
-ahd_tqinpos_print(u_int regvalue, u_int *cur_col, u_int wrap)
+ahd_qoutfifo_next_addr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
- return (ahd_print_register(NULL, 0, "TQINPOS",
- 0x141, regvalue, cur_col, wrap));
+ return (ahd_print_register(NULL, 0, "QOUTFIFO_NEXT_ADDR",
+ 0x144, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t ARG_1_parse_table[] = {
@@ -3320,21 +3341,21 @@ int
ahd_arg_1_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(ARG_1_parse_table, 8, "ARG_1",
- 0x142, regvalue, cur_col, wrap));
+ 0x148, regvalue, cur_col, wrap));
}
int
ahd_arg_2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ARG_2",
- 0x143, regvalue, cur_col, wrap));
+ 0x149, regvalue, cur_col, wrap));
}
int
ahd_last_msg_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LAST_MSG",
- 0x144, regvalue, cur_col, wrap));
+ 0x14a, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SCSISEQ_TEMPLATE_parse_table[] = {
@@ -3350,14 +3371,14 @@ int
ahd_scsiseq_template_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SCSISEQ_TEMPLATE_parse_table, 6, "SCSISEQ_TEMPLATE",
- 0x145, regvalue, cur_col, wrap));
+ 0x14b, regvalue, cur_col, wrap));
}
int
ahd_initiator_tag_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INITIATOR_TAG",
- 0x146, regvalue, cur_col, wrap));
+ 0x14c, regvalue, cur_col, wrap));
}
static ahd_reg_parse_entry_t SEQ_FLAGS2_parse_table[] = {
@@ -3369,63 +3390,63 @@ int
ahd_seq_flags2_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(SEQ_FLAGS2_parse_table, 2, "SEQ_FLAGS2",
- 0x147, regvalue, cur_col, wrap));
+ 0x14d, regvalue, cur_col, wrap));
}
int
ahd_allocfifo_scbptr_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "ALLOCFIFO_SCBPTR",
- 0x148, regvalue, cur_col, wrap));
+ 0x14e, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_timer_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_TIMER",
- 0x14a, regvalue, cur_col, wrap));
+ 0x150, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_maxcmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_MAXCMDS",
- 0x14c, regvalue, cur_col, wrap));
+ 0x152, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_mincmds_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_MINCMDS",
- 0x14d, regvalue, cur_col, wrap));
+ 0x153, regvalue, cur_col, wrap));
}
int
ahd_cmds_pending_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "CMDS_PENDING",
- 0x14e, regvalue, cur_col, wrap));
+ 0x154, regvalue, cur_col, wrap));
}
int
ahd_int_coalescing_cmdcount_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "INT_COALESCING_CMDCOUNT",
- 0x150, regvalue, cur_col, wrap));
+ 0x156, regvalue, cur_col, wrap));
}
int
ahd_local_hs_mailbox_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "LOCAL_HS_MAILBOX",
- 0x151, regvalue, cur_col, wrap));
+ 0x157, regvalue, cur_col, wrap));
}
int
ahd_cmdsize_table_print(u_int regvalue, u_int *cur_col, u_int wrap)
{
return (ahd_print_register(NULL, 0, "CMDSIZE_TABLE",
- 0x152, regvalue, cur_col, wrap));
+ 0x158, regvalue, cur_col, wrap));
}
int
diff --git a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
index 77c471f934e0..b1e5365be230 100644
--- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
+++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
@@ -2,215 +2,228 @@
* DO NOT EDIT - This file is automatically generated
* from the following source files:
*
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#94 $
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $
*/
static uint8_t seqprog[] = {
0xff, 0x02, 0x06, 0x78,
- 0x00, 0xea, 0x50, 0x59,
+ 0x00, 0xea, 0x64, 0x59,
0x01, 0xea, 0x04, 0x30,
0xff, 0x04, 0x0c, 0x78,
- 0x19, 0xea, 0x50, 0x59,
+ 0x19, 0xea, 0x64, 0x59,
0x19, 0xea, 0x04, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x60, 0x3a, 0x1a, 0x68,
- 0x04, 0x47, 0x1b, 0x68,
- 0xff, 0x21, 0x1b, 0x70,
- 0x40, 0x4b, 0x92, 0x69,
- 0x00, 0xe2, 0x54, 0x59,
- 0x40, 0x4b, 0x92, 0x69,
- 0x20, 0x4b, 0x82, 0x69,
- 0xfc, 0x42, 0x24, 0x78,
- 0x10, 0x40, 0x24, 0x78,
- 0x00, 0xe2, 0xc4, 0x5d,
- 0x20, 0x4d, 0x28, 0x78,
- 0x00, 0xe2, 0xc4, 0x5d,
+ 0x60, 0x3a, 0x3a, 0x68,
+ 0x04, 0x4d, 0x35, 0x78,
+ 0x01, 0x34, 0xc1, 0x31,
+ 0x00, 0x32, 0x21, 0x60,
+ 0x01, 0x35, 0xc1, 0x31,
+ 0x00, 0x33, 0x21, 0x60,
+ 0xfb, 0x4d, 0x9b, 0x0a,
+ 0x00, 0xe2, 0x34, 0x40,
+ 0x50, 0x4b, 0x3a, 0x68,
+ 0xff, 0x31, 0x3b, 0x70,
+ 0x02, 0x30, 0x51, 0x31,
+ 0xff, 0x8d, 0x2d, 0x70,
+ 0x02, 0x8c, 0x51, 0x31,
+ 0xff, 0x8d, 0x29, 0x60,
+ 0x02, 0x28, 0x19, 0x33,
+ 0x02, 0x30, 0x51, 0x32,
+ 0xff, 0xea, 0x62, 0x02,
+ 0x00, 0xe2, 0x3a, 0x40,
+ 0xff, 0x21, 0x3b, 0x70,
+ 0x40, 0x4b, 0xaa, 0x69,
+ 0x00, 0xe2, 0x68, 0x59,
+ 0x40, 0x4b, 0xaa, 0x69,
+ 0x20, 0x4b, 0x96, 0x69,
+ 0xfc, 0x42, 0x44, 0x78,
+ 0x10, 0x40, 0x44, 0x78,
+ 0x00, 0xe2, 0xfc, 0x5d,
+ 0x20, 0x4d, 0x48, 0x78,
+ 0x00, 0xe2, 0xfc, 0x5d,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x30, 0x60,
+ 0x30, 0xe0, 0x50, 0x60,
0x7f, 0x4a, 0x94, 0x08,
- 0x00, 0xe2, 0x32, 0x40,
+ 0x00, 0xe2, 0x52, 0x40,
0xc0, 0x4a, 0x94, 0x00,
- 0x00, 0xe2, 0x3e, 0x58,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0xe2, 0x66, 0x58,
+ 0x00, 0xe2, 0x5e, 0x58,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0xe2, 0x86, 0x58,
0x00, 0xe2, 0x06, 0x40,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x01, 0x52, 0x64, 0x78,
+ 0x01, 0x52, 0x84, 0x78,
0x02, 0x58, 0x50, 0x31,
0xff, 0xea, 0x10, 0x0b,
- 0xff, 0x97, 0x4f, 0x78,
- 0x50, 0x4b, 0x4a, 0x68,
+ 0xff, 0x97, 0x6f, 0x78,
+ 0x50, 0x4b, 0x6a, 0x68,
0xbf, 0x3a, 0x74, 0x08,
- 0x14, 0xea, 0x50, 0x59,
+ 0x14, 0xea, 0x64, 0x59,
0x14, 0xea, 0x04, 0x00,
0x08, 0x92, 0x25, 0x03,
- 0xff, 0x90, 0x3f, 0x68,
- 0x00, 0xe2, 0x56, 0x5b,
- 0x00, 0xe2, 0x3e, 0x40,
- 0x00, 0xea, 0x44, 0x59,
+ 0xff, 0x90, 0x5f, 0x68,
+ 0x00, 0xe2, 0x76, 0x5b,
+ 0x00, 0xe2, 0x5e, 0x40,
+ 0x00, 0xea, 0x5e, 0x59,
0x01, 0xea, 0x00, 0x30,
- 0x80, 0xf9, 0x5e, 0x68,
- 0x00, 0xe2, 0x42, 0x59,
- 0x11, 0xea, 0x44, 0x59,
+ 0x80, 0xf9, 0x7e, 0x68,
+ 0x00, 0xe2, 0x5c, 0x59,
+ 0x11, 0xea, 0x5e, 0x59,
0x11, 0xea, 0x00, 0x00,
- 0x80, 0xf9, 0x42, 0x79,
+ 0x80, 0xf9, 0x5c, 0x79,
0xff, 0xea, 0xd4, 0x0d,
- 0x22, 0xea, 0x44, 0x59,
+ 0x22, 0xea, 0x5e, 0x59,
0x22, 0xea, 0x00, 0x00,
- 0x10, 0x16, 0x70, 0x78,
- 0x01, 0x0b, 0xa2, 0x32,
+ 0x10, 0x16, 0x90, 0x78,
0x10, 0x16, 0x2c, 0x00,
- 0x18, 0xad, 0x00, 0x79,
- 0x04, 0xad, 0xca, 0x68,
- 0x80, 0xad, 0x64, 0x78,
- 0x10, 0xad, 0x98, 0x78,
- 0xff, 0x88, 0x83, 0x68,
+ 0x01, 0x0b, 0xae, 0x32,
+ 0x18, 0xad, 0x12, 0x79,
+ 0x04, 0xad, 0xdc, 0x68,
+ 0x80, 0xad, 0x84, 0x78,
+ 0x10, 0xad, 0xaa, 0x78,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0x8c, 0x59, 0x32,
+ 0xff, 0x8d, 0xa1, 0x60,
+ 0xff, 0xea, 0x5e, 0x02,
+ 0xff, 0x88, 0xa7, 0x78,
+ 0x02, 0x30, 0x19, 0x33,
+ 0x02, 0xa8, 0x60, 0x36,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
- 0x33, 0xea, 0x44, 0x59,
- 0x33, 0xea, 0x00, 0x00,
- 0x40, 0x3a, 0x64, 0x68,
- 0x50, 0x4b, 0x64, 0x68,
- 0x22, 0xea, 0x44, 0x59,
- 0x22, 0xea, 0x00, 0x00,
- 0xe7, 0xad, 0x5a, 0x09,
- 0x02, 0x8c, 0x59, 0x32,
- 0x1a, 0xea, 0x50, 0x59,
- 0x1a, 0xea, 0x04, 0x00,
- 0xff, 0xea, 0xd4, 0x0d,
0xe7, 0xad, 0x5a, 0x09,
- 0x00, 0xe2, 0xa6, 0x58,
+ 0x00, 0xe2, 0xb8, 0x58,
0xff, 0xea, 0x56, 0x02,
- 0x04, 0x7c, 0x78, 0x32,
- 0x20, 0x16, 0x64, 0x78,
- 0x04, 0x38, 0x79, 0x32,
- 0x80, 0x37, 0x6f, 0x16,
- 0xff, 0x2d, 0xb5, 0x60,
- 0xff, 0x29, 0xb5, 0x60,
- 0x40, 0x51, 0xc5, 0x78,
- 0xff, 0x4f, 0xb5, 0x68,
- 0xff, 0x4d, 0xc1, 0x19,
- 0x00, 0x4e, 0xd5, 0x19,
- 0x00, 0xe2, 0xc4, 0x50,
- 0x01, 0x4c, 0xc1, 0x31,
- 0x00, 0x50, 0xd5, 0x19,
- 0x00, 0xe2, 0xc4, 0x48,
- 0x80, 0x18, 0x64, 0x78,
- 0x02, 0x4a, 0x1d, 0x30,
+ 0x04, 0x7c, 0x88, 0x32,
+ 0x20, 0x16, 0x84, 0x78,
+ 0x04, 0x40, 0x89, 0x32,
+ 0x80, 0x3d, 0x7b, 0x16,
+ 0xff, 0x2d, 0xc7, 0x60,
+ 0xff, 0x29, 0xc7, 0x60,
+ 0x40, 0x57, 0xd7, 0x78,
+ 0xff, 0x55, 0xc7, 0x68,
+ 0xff, 0x53, 0xc1, 0x19,
+ 0x00, 0x54, 0xd5, 0x19,
+ 0x00, 0xe2, 0xd6, 0x50,
+ 0x01, 0x52, 0xc1, 0x31,
+ 0x00, 0x56, 0xd5, 0x19,
+ 0x00, 0xe2, 0xd6, 0x48,
+ 0x80, 0x18, 0x84, 0x78,
+ 0x02, 0x50, 0x1d, 0x30,
0x10, 0xea, 0x18, 0x00,
0x60, 0x18, 0x30, 0x00,
0x7f, 0x18, 0x30, 0x0c,
0x02, 0xea, 0x02, 0x00,
- 0xff, 0xea, 0xa0, 0x0a,
+ 0xff, 0xea, 0xac, 0x0a,
0x80, 0x18, 0x30, 0x04,
- 0x40, 0xad, 0x64, 0x78,
+ 0x40, 0xad, 0x84, 0x78,
0xe7, 0xad, 0x5a, 0x09,
0x02, 0xa8, 0x40, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x01, 0x4e, 0x9d, 0x1a,
- 0x00, 0x4f, 0x9f, 0x22,
+ 0x01, 0x54, 0xa9, 0x1a,
+ 0x00, 0x55, 0xab, 0x22,
0x01, 0x94, 0x6d, 0x33,
- 0x01, 0xea, 0x20, 0x33,
+ 0xff, 0xea, 0x20, 0x0b,
0x04, 0xac, 0x49, 0x32,
0xff, 0xea, 0x5a, 0x03,
0xff, 0xea, 0x5e, 0x03,
0x01, 0x10, 0xd4, 0x31,
- 0x10, 0x92, 0xf5, 0x68,
+ 0x10, 0x92, 0x07, 0x69,
0x3d, 0x93, 0xc5, 0x29,
0xfe, 0xe2, 0xc4, 0x09,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x50, 0x31,
0x02, 0xa0, 0xda, 0x31,
- 0xff, 0xa9, 0xf4, 0x70,
+ 0xff, 0xa9, 0x06, 0x71,
0x02, 0xa0, 0x58, 0x37,
- 0xff, 0x21, 0xfd, 0x70,
+ 0xff, 0x21, 0x0f, 0x71,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x36,
0x02, 0xa0, 0x40, 0x32,
0x02, 0xa0, 0x44, 0x36,
- 0x04, 0x47, 0x05, 0x69,
- 0x40, 0x16, 0x30, 0x69,
- 0xff, 0x2d, 0x35, 0x61,
- 0xff, 0x29, 0x65, 0x70,
- 0x01, 0x37, 0xc1, 0x31,
+ 0x04, 0x4d, 0x17, 0x69,
+ 0x40, 0x16, 0x48, 0x69,
+ 0xff, 0x2d, 0x4d, 0x61,
+ 0xff, 0x29, 0x85, 0x70,
0x02, 0x28, 0x55, 0x32,
0x01, 0xea, 0x5a, 0x01,
- 0x04, 0x3c, 0xf9, 0x30,
+ 0x04, 0x44, 0xf9, 0x30,
+ 0x01, 0x44, 0xc1, 0x31,
0x02, 0x28, 0x51, 0x31,
- 0x01, 0xa8, 0x60, 0x31,
- 0x00, 0xa9, 0x60, 0x01,
+ 0x02, 0xa8, 0x60, 0x31,
+ 0x01, 0xa4, 0x61, 0x31,
+ 0x01, 0x3d, 0x61, 0x31,
0x01, 0x14, 0xd4, 0x31,
- 0x01, 0x50, 0xa1, 0x1a,
- 0xff, 0x4e, 0x9d, 0x1a,
- 0xff, 0x4f, 0x9f, 0x22,
- 0xff, 0x8d, 0x29, 0x71,
- 0x80, 0xac, 0x28, 0x71,
- 0x20, 0x16, 0x28, 0x69,
+ 0x01, 0x56, 0xad, 0x1a,
+ 0xff, 0x54, 0xa9, 0x1a,
+ 0xff, 0x55, 0xab, 0x22,
+ 0xff, 0x8d, 0x41, 0x71,
+ 0x80, 0xac, 0x40, 0x71,
+ 0x20, 0x16, 0x40, 0x69,
+ 0x00, 0xac, 0xc4, 0x19,
+ 0x07, 0xe2, 0x40, 0xf9,
0x02, 0x8c, 0x51, 0x31,
- 0x00, 0xe2, 0x12, 0x41,
+ 0x00, 0xe2, 0x24, 0x41,
0x01, 0xac, 0x08, 0x31,
0x09, 0xea, 0x5a, 0x01,
0x02, 0x8c, 0x51, 0x32,
0xff, 0xea, 0x1a, 0x07,
0x04, 0x24, 0xf9, 0x30,
- 0x1d, 0xea, 0x3a, 0x41,
+ 0x1d, 0xea, 0x52, 0x41,
0x02, 0x2c, 0x51, 0x31,
0x04, 0xa8, 0xf9, 0x30,
- 0x19, 0xea, 0x3a, 0x41,
+ 0x19, 0xea, 0x52, 0x41,
0x06, 0xea, 0x08, 0x81,
0x01, 0xe2, 0x5a, 0x35,
- 0x02, 0xf2, 0xf0, 0x35,
+ 0x02, 0xf2, 0xf0, 0x31,
+ 0xff, 0xea, 0xd4, 0x0d,
0x02, 0xf2, 0xf0, 0x31,
0x02, 0xf8, 0xe4, 0x35,
0x80, 0xea, 0xb2, 0x01,
0x01, 0xe2, 0x00, 0x30,
0xff, 0xea, 0xb2, 0x0d,
- 0x80, 0xea, 0xb2, 0x01,
- 0x11, 0x00, 0x00, 0x10,
- 0xff, 0xea, 0xb2, 0x0d,
0x01, 0xe2, 0x04, 0x30,
0x01, 0xea, 0x04, 0x34,
0x02, 0x20, 0xbd, 0x30,
0x02, 0x20, 0xb9, 0x30,
0x02, 0x20, 0x51, 0x31,
0x4c, 0x93, 0xd7, 0x28,
- 0x10, 0x92, 0x63, 0x79,
+ 0x10, 0x92, 0x77, 0x79,
0x01, 0x6b, 0xc0, 0x30,
0x02, 0x64, 0xc8, 0x00,
0x40, 0x3a, 0x74, 0x04,
- 0x00, 0xe2, 0x56, 0x58,
- 0x33, 0xea, 0x44, 0x59,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x64, 0x61,
- 0x20, 0x3f, 0x7a, 0x69,
- 0x10, 0x3f, 0x64, 0x79,
+ 0x30, 0xe0, 0x78, 0x61,
+ 0x20, 0x3f, 0x8e, 0x69,
+ 0x10, 0x3f, 0x78, 0x79,
0x02, 0xea, 0x7e, 0x00,
- 0x00, 0xea, 0x44, 0x59,
+ 0x00, 0xea, 0x5e, 0x59,
0x01, 0xea, 0x00, 0x30,
- 0x02, 0x48, 0x51, 0x35,
+ 0x02, 0x4e, 0x51, 0x35,
0x01, 0xea, 0x7e, 0x00,
- 0x11, 0xea, 0x44, 0x59,
+ 0x11, 0xea, 0x5e, 0x59,
0x11, 0xea, 0x00, 0x00,
- 0x02, 0x48, 0x51, 0x35,
+ 0x02, 0x4e, 0x51, 0x35,
+ 0xc0, 0x4a, 0x94, 0x00,
+ 0x04, 0x41, 0x9c, 0x79,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
0x08, 0x3c, 0x78, 0x00,
- 0xf0, 0x49, 0x68, 0x0a,
+ 0xf0, 0x49, 0x74, 0x0a,
0x0f, 0x67, 0xc0, 0x09,
- 0x00, 0x34, 0x69, 0x02,
+ 0x00, 0x3a, 0x75, 0x02,
0x20, 0xea, 0x96, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x40, 0x3a, 0xae, 0x69,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0xc0, 0x4a, 0x94, 0x00,
+ 0x40, 0x3a, 0xc8, 0x69,
0x02, 0x55, 0x06, 0x68,
- 0x02, 0x56, 0xae, 0x69,
- 0xff, 0x5b, 0xae, 0x61,
+ 0x02, 0x56, 0xc8, 0x69,
+ 0xff, 0x5b, 0xc8, 0x61,
0x02, 0x20, 0x51, 0x31,
0x80, 0xea, 0xb2, 0x01,
0x44, 0xea, 0x00, 0x00,
@@ -218,237 +231,246 @@ static uint8_t seqprog[] = {
0x33, 0xea, 0x00, 0x00,
0xff, 0xea, 0xb2, 0x09,
0xff, 0xe0, 0xc0, 0x19,
- 0xff, 0xe0, 0xb0, 0x79,
+ 0xff, 0xe0, 0xca, 0x79,
0x02, 0xac, 0x51, 0x31,
- 0x00, 0xe2, 0xa6, 0x41,
+ 0x00, 0xe2, 0xc0, 0x41,
0x02, 0x5e, 0x50, 0x31,
0x02, 0xa8, 0xb8, 0x30,
0x02, 0x5c, 0x50, 0x31,
- 0xff, 0xad, 0xc1, 0x71,
+ 0xff, 0xad, 0xdb, 0x71,
0x02, 0xac, 0x41, 0x31,
0x02, 0x22, 0x51, 0x31,
0x02, 0xa0, 0x5c, 0x33,
0x02, 0xa0, 0x44, 0x32,
- 0x00, 0xe2, 0xca, 0x41,
- 0x10, 0x92, 0xcb, 0x69,
+ 0x00, 0xe2, 0xe4, 0x41,
+ 0x10, 0x92, 0xe5, 0x69,
0x3d, 0x93, 0xc9, 0x29,
0x01, 0xe4, 0xc8, 0x01,
0x01, 0xea, 0xca, 0x01,
0xff, 0xea, 0xda, 0x01,
0x02, 0x20, 0x51, 0x31,
0x02, 0xae, 0x41, 0x32,
- 0xff, 0x21, 0xd3, 0x61,
+ 0xff, 0x21, 0xed, 0x61,
0xff, 0xea, 0x46, 0x02,
0x02, 0x5c, 0x50, 0x31,
0x40, 0xea, 0x96, 0x00,
- 0x02, 0x56, 0xcc, 0x6d,
- 0x01, 0x55, 0xcc, 0x6d,
- 0x10, 0x92, 0xdf, 0x79,
- 0x10, 0x40, 0xe8, 0x69,
- 0x01, 0x56, 0xe8, 0x79,
+ 0x02, 0x56, 0x04, 0x6e,
+ 0x01, 0x55, 0x04, 0x6e,
+ 0x10, 0x92, 0xf9, 0x79,
+ 0x10, 0x40, 0x02, 0x6a,
+ 0x01, 0x56, 0x02, 0x7a,
0xff, 0x97, 0x07, 0x78,
- 0x13, 0xea, 0x50, 0x59,
+ 0x13, 0xea, 0x64, 0x59,
0x13, 0xea, 0x04, 0x00,
0x00, 0xe2, 0x06, 0x40,
0xbf, 0x3a, 0x74, 0x08,
+ 0x04, 0x41, 0x08, 0x7a,
0x08, 0xea, 0x98, 0x00,
0x08, 0x57, 0xae, 0x00,
- 0x01, 0x93, 0x69, 0x32,
- 0x01, 0x94, 0x6b, 0x32,
- 0x40, 0xea, 0x66, 0x02,
+ 0x01, 0x93, 0x75, 0x32,
+ 0x01, 0x94, 0x77, 0x32,
+ 0x40, 0xea, 0x72, 0x02,
0x08, 0x3c, 0x78, 0x00,
- 0x80, 0xea, 0x62, 0x02,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x01, 0x36, 0xc1, 0x31,
- 0x9f, 0xe0, 0x4c, 0x7c,
- 0x80, 0xe0, 0x0c, 0x72,
- 0xa0, 0xe0, 0x44, 0x72,
- 0xc0, 0xe0, 0x3a, 0x72,
- 0xe0, 0xe0, 0x74, 0x72,
- 0x01, 0xea, 0x50, 0x59,
+ 0x80, 0xea, 0x6e, 0x02,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x01, 0x3c, 0xc1, 0x31,
+ 0x9f, 0xe0, 0x84, 0x7c,
+ 0x80, 0xe0, 0x28, 0x72,
+ 0xa0, 0xe0, 0x64, 0x72,
+ 0xc0, 0xe0, 0x5a, 0x72,
+ 0xe0, 0xe0, 0x94, 0x72,
+ 0x01, 0xea, 0x64, 0x59,
0x01, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x80, 0x33, 0x13, 0x7a,
- 0x03, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x80, 0x39, 0x2f, 0x7a,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0xee, 0x00, 0x1a, 0x6a,
+ 0xee, 0x00, 0x36, 0x6a,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x02, 0xa8, 0x90, 0x32,
- 0x00, 0xe2, 0x6a, 0x59,
+ 0x02, 0xa8, 0x9c, 0x32,
+ 0x00, 0xe2, 0x7e, 0x59,
0xef, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x2a, 0x52,
+ 0x00, 0xe2, 0x46, 0x52,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x30, 0x42,
+ 0x00, 0xe2, 0x4c, 0x42,
0x01, 0x96, 0xd1, 0x30,
0x10, 0x80, 0x89, 0x31,
0x20, 0xea, 0x32, 0x00,
- 0xbf, 0x33, 0x67, 0x0a,
- 0x20, 0x19, 0x32, 0x6a,
- 0x02, 0x4d, 0xf8, 0x69,
- 0x40, 0x33, 0x67, 0x02,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x80, 0x33, 0xb5, 0x6a,
+ 0xbf, 0x39, 0x73, 0x0a,
+ 0x10, 0x4c, 0x56, 0x6a,
+ 0x20, 0x19, 0x4e, 0x6a,
+ 0x20, 0x19, 0x52, 0x6a,
+ 0x02, 0x4d, 0x14, 0x6a,
+ 0x40, 0x39, 0x73, 0x02,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x80, 0x39, 0xd5, 0x6a,
0x01, 0x44, 0x10, 0x33,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0xf8, 0x41,
+ 0x00, 0xe2, 0x14, 0x42,
0x10, 0xea, 0x80, 0x00,
- 0x01, 0x31, 0xc5, 0x31,
- 0x80, 0xe2, 0x60, 0x62,
- 0x10, 0x92, 0x85, 0x6a,
+ 0x01, 0x37, 0xc5, 0x31,
+ 0x80, 0xe2, 0x80, 0x62,
+ 0x10, 0x92, 0xa5, 0x6a,
0xc0, 0x94, 0xc5, 0x01,
- 0x40, 0x92, 0x51, 0x6a,
+ 0x40, 0x92, 0x71, 0x6a,
0xbf, 0xe2, 0xc4, 0x09,
- 0x20, 0x92, 0x65, 0x7a,
+ 0x20, 0x92, 0x85, 0x7a,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x6d, 0x62,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x8d, 0x62,
0x23, 0x92, 0x89, 0x08,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x6d, 0x62,
- 0x00, 0xa8, 0x64, 0x42,
- 0xff, 0xe2, 0x64, 0x62,
- 0x00, 0xe2, 0x84, 0x42,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x8d, 0x62,
+ 0x00, 0xa8, 0x84, 0x42,
+ 0xff, 0xe2, 0x84, 0x62,
+ 0x00, 0xe2, 0xa4, 0x42,
0x40, 0xea, 0x98, 0x00,
0x01, 0xe2, 0x88, 0x30,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0xa0, 0x36, 0x43, 0x72,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0xa0, 0x3c, 0x63, 0x72,
0x40, 0xea, 0x98, 0x00,
- 0x01, 0x31, 0x89, 0x32,
- 0x08, 0xea, 0x62, 0x02,
- 0x00, 0xe2, 0xf8, 0x41,
- 0xe0, 0xea, 0xd4, 0x5b,
- 0x80, 0xe0, 0xc0, 0x6a,
- 0x04, 0xe0, 0x66, 0x73,
- 0x02, 0xe0, 0x96, 0x73,
- 0x00, 0xea, 0x1e, 0x73,
- 0x03, 0xe0, 0xa6, 0x73,
- 0x23, 0xe0, 0x96, 0x72,
- 0x08, 0xe0, 0xbc, 0x72,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x07, 0xea, 0x50, 0x59,
+ 0x01, 0x37, 0x95, 0x32,
+ 0x08, 0xea, 0x6e, 0x02,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0xe0, 0xea, 0xfe, 0x5b,
+ 0x80, 0xe0, 0xe0, 0x6a,
+ 0x04, 0xe0, 0x92, 0x73,
+ 0x02, 0xe0, 0xc4, 0x73,
+ 0x00, 0xea, 0x3e, 0x73,
+ 0x03, 0xe0, 0xd4, 0x73,
+ 0x23, 0xe0, 0xb6, 0x72,
+ 0x08, 0xe0, 0xdc, 0x72,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x07, 0xea, 0x64, 0x59,
0x07, 0xea, 0x04, 0x00,
- 0x08, 0x42, 0xf9, 0x71,
- 0x04, 0x42, 0x93, 0x62,
- 0x01, 0x43, 0x89, 0x30,
- 0x00, 0xe2, 0x84, 0x42,
+ 0x08, 0x48, 0x15, 0x72,
+ 0x04, 0x48, 0xb3, 0x62,
+ 0x01, 0x49, 0x89, 0x30,
+ 0x00, 0xe2, 0xa4, 0x42,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0x84, 0x42,
- 0x01, 0x00, 0x60, 0x32,
- 0x33, 0xea, 0x44, 0x59,
+ 0x00, 0xe2, 0xa4, 0x42,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x4c, 0x34, 0xc1, 0x28,
+ 0x4c, 0x3a, 0xc1, 0x28,
0x01, 0x64, 0xc0, 0x31,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x01, 0xe0, 0xba, 0x7a,
- 0xa0, 0xea, 0xca, 0x5b,
- 0x01, 0xa0, 0xba, 0x62,
- 0x01, 0x84, 0xaf, 0x7a,
- 0x01, 0x95, 0xbd, 0x6a,
- 0x05, 0xea, 0x50, 0x59,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x01, 0xe0, 0xda, 0x7a,
+ 0xa0, 0xea, 0xf4, 0x5b,
+ 0x01, 0xa0, 0xda, 0x62,
+ 0x01, 0x84, 0xcf, 0x7a,
+ 0x01, 0x95, 0xdd, 0x6a,
+ 0x05, 0xea, 0x64, 0x59,
0x05, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x03, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x07, 0xea, 0xdc, 0x5b,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x07, 0xea, 0x06, 0x5c,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x3f, 0xe0, 0x6a, 0x0a,
- 0xc0, 0x34, 0xc1, 0x09,
- 0x00, 0x35, 0x51, 0x01,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x3f, 0xe0, 0x76, 0x0a,
+ 0xc0, 0x3a, 0xc1, 0x09,
+ 0x00, 0x3b, 0x51, 0x01,
0xff, 0xea, 0x52, 0x09,
- 0x30, 0x34, 0xc5, 0x09,
+ 0x30, 0x3a, 0xc5, 0x09,
0x3d, 0xe2, 0xc4, 0x29,
0xb8, 0xe2, 0xc4, 0x19,
0x01, 0xea, 0xc6, 0x01,
0x02, 0xe2, 0xc8, 0x31,
0x02, 0xec, 0x40, 0x31,
- 0xff, 0xa1, 0xdc, 0x72,
+ 0xff, 0xa1, 0xfc, 0x72,
0x02, 0xe8, 0xda, 0x31,
0x02, 0xa0, 0x50, 0x31,
- 0x00, 0xe2, 0xfe, 0x42,
- 0x80, 0x33, 0x67, 0x02,
+ 0x00, 0xe2, 0x1e, 0x43,
+ 0x80, 0x39, 0x73, 0x02,
0x01, 0x44, 0xd4, 0x31,
- 0x00, 0xe2, 0xb8, 0x5b,
- 0x01, 0x33, 0x67, 0x02,
- 0xe0, 0x36, 0x19, 0x63,
- 0x02, 0x33, 0x67, 0x02,
- 0x20, 0x46, 0x12, 0x63,
+ 0x00, 0xe2, 0xe2, 0x5b,
+ 0x01, 0x39, 0x73, 0x02,
+ 0xe0, 0x3c, 0x39, 0x63,
+ 0x02, 0x39, 0x73, 0x02,
+ 0x20, 0x46, 0x32, 0x63,
0xff, 0xea, 0x52, 0x09,
- 0xa8, 0xea, 0xca, 0x5b,
- 0x04, 0x92, 0xf9, 0x7a,
- 0x01, 0x34, 0xc1, 0x31,
- 0x00, 0x93, 0xf9, 0x62,
- 0x01, 0x35, 0xc1, 0x31,
- 0x00, 0x94, 0x03, 0x73,
+ 0xa8, 0xea, 0xf4, 0x5b,
+ 0x04, 0x92, 0x19, 0x7b,
+ 0x01, 0x3a, 0xc1, 0x31,
+ 0x00, 0x93, 0x19, 0x63,
+ 0x01, 0x3b, 0xc1, 0x31,
+ 0x00, 0x94, 0x23, 0x73,
0x01, 0xa9, 0x52, 0x11,
- 0xff, 0xa9, 0xee, 0x6a,
- 0x00, 0xe2, 0x12, 0x43,
- 0x10, 0x33, 0x67, 0x02,
- 0x04, 0x92, 0x13, 0x7b,
+ 0xff, 0xa9, 0x0e, 0x6b,
+ 0x00, 0xe2, 0x32, 0x43,
+ 0x10, 0x39, 0x73, 0x02,
+ 0x04, 0x92, 0x33, 0x7b,
0xfb, 0x92, 0x25, 0x0b,
- 0xff, 0xea, 0x66, 0x0a,
- 0x01, 0xa4, 0x0d, 0x6b,
- 0x02, 0xa8, 0x90, 0x32,
- 0x00, 0xe2, 0x6a, 0x59,
- 0x10, 0x92, 0xbd, 0x7a,
- 0xff, 0xea, 0xdc, 0x5b,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x04, 0xea, 0x50, 0x59,
+ 0xff, 0xea, 0x72, 0x0a,
+ 0x01, 0xa4, 0x2d, 0x6b,
+ 0x02, 0xa8, 0x9c, 0x32,
+ 0x00, 0xe2, 0x7e, 0x59,
+ 0x10, 0x92, 0xdd, 0x7a,
+ 0xff, 0xea, 0x06, 0x5c,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x04, 0xea, 0x64, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x04, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0x04, 0xea, 0x64, 0x59,
0x04, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x08, 0x92, 0xb5, 0x7a,
- 0xc0, 0x33, 0x29, 0x7b,
- 0x80, 0x33, 0xb5, 0x6a,
- 0xff, 0x88, 0x29, 0x6b,
- 0x40, 0x33, 0xb5, 0x6a,
- 0x10, 0x92, 0x2f, 0x7b,
- 0x0a, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x08, 0x92, 0xd5, 0x7a,
+ 0xc0, 0x39, 0x49, 0x7b,
+ 0x80, 0x39, 0xd5, 0x6a,
+ 0xff, 0x88, 0x49, 0x6b,
+ 0x40, 0x39, 0xd5, 0x6a,
+ 0x10, 0x92, 0x4f, 0x7b,
+ 0x0a, 0xea, 0x64, 0x59,
0x0a, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x4e, 0x5b,
- 0x00, 0xe2, 0x82, 0x43,
- 0x50, 0x4b, 0x36, 0x6b,
+ 0x00, 0xe2, 0x6e, 0x5b,
+ 0x00, 0xe2, 0xae, 0x43,
+ 0x50, 0x4b, 0x56, 0x6b,
0xbf, 0x3a, 0x74, 0x08,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x01, 0x2e, 0x5d, 0x1a,
- 0x00, 0x2f, 0x5f, 0x22,
- 0x04, 0x47, 0x8f, 0x02,
+ 0x01, 0x32, 0x65, 0x1a,
+ 0x00, 0x33, 0x67, 0x22,
+ 0x04, 0x4d, 0x9b, 0x02,
0x01, 0xfa, 0xc0, 0x35,
- 0x02, 0xa8, 0x84, 0x32,
+ 0x02, 0xa8, 0x90, 0x32,
0x02, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x02, 0x42, 0x51, 0x31,
- 0xff, 0x90, 0x65, 0x68,
- 0xff, 0x88, 0x5b, 0x6b,
- 0x01, 0xa4, 0x57, 0x6b,
- 0x02, 0xa4, 0x5f, 0x6b,
- 0x01, 0x84, 0x5f, 0x7b,
+ 0x02, 0x48, 0x51, 0x31,
+ 0xff, 0x90, 0x85, 0x68,
+ 0xff, 0x88, 0x7b, 0x6b,
+ 0x01, 0xa4, 0x77, 0x6b,
+ 0x02, 0xa4, 0x7f, 0x6b,
+ 0x01, 0x84, 0x7f, 0x7b,
0x02, 0x28, 0x19, 0x33,
0x02, 0xa8, 0x50, 0x36,
- 0xff, 0x88, 0x5f, 0x73,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0xff, 0x88, 0x7f, 0x73,
+ 0x00, 0xe2, 0x52, 0x5b,
0x02, 0xa8, 0x20, 0x33,
- 0x02, 0x2c, 0x19, 0x33,
+ 0x04, 0xa4, 0x49, 0x03,
+ 0xff, 0xea, 0x1a, 0x03,
+ 0xff, 0x2d, 0x8b, 0x63,
0x02, 0xa8, 0x58, 0x32,
- 0x04, 0xa4, 0x49, 0x07,
- 0xc0, 0x33, 0xb5, 0x6a,
+ 0x02, 0xa8, 0x5c, 0x36,
+ 0x02, 0xa8, 0x40, 0x31,
+ 0x02, 0x2e, 0x51, 0x31,
+ 0x02, 0xa0, 0x18, 0x33,
+ 0x02, 0xa0, 0x5c, 0x36,
+ 0xc0, 0x39, 0xd5, 0x6a,
0x04, 0x92, 0x25, 0x03,
- 0x20, 0x92, 0x83, 0x6b,
+ 0x20, 0x92, 0xaf, 0x6b,
0x02, 0xa8, 0x40, 0x31,
- 0xc0, 0x34, 0xc1, 0x09,
- 0x00, 0x35, 0x51, 0x01,
+ 0xc0, 0x3a, 0xc1, 0x09,
+ 0x00, 0x3b, 0x51, 0x01,
0xff, 0xea, 0x52, 0x09,
- 0x30, 0x34, 0xc5, 0x09,
+ 0x30, 0x3a, 0xc5, 0x09,
0x3d, 0xe2, 0xc4, 0x29,
0xb8, 0xe2, 0xc4, 0x19,
0x01, 0xea, 0xc6, 0x01,
@@ -458,69 +480,75 @@ static uint8_t seqprog[] = {
0xf7, 0x57, 0xae, 0x08,
0x08, 0xea, 0x98, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0xee, 0x00, 0x8c, 0x6b,
+ 0xee, 0x00, 0xb8, 0x6b,
0x02, 0xea, 0xb4, 0x00,
- 0x00, 0xe2, 0xb4, 0x5b,
- 0x09, 0x4c, 0x8e, 0x7b,
+ 0xc0, 0xea, 0x72, 0x02,
+ 0x09, 0x4c, 0xba, 0x7b,
+ 0x01, 0xea, 0x78, 0x02,
0x08, 0x4c, 0x06, 0x68,
- 0x0b, 0xea, 0x50, 0x59,
+ 0x0b, 0xea, 0x64, 0x59,
0x0b, 0xea, 0x04, 0x00,
0x01, 0x44, 0xd4, 0x31,
- 0x20, 0x33, 0xf9, 0x79,
- 0x00, 0xe2, 0x9e, 0x5b,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x01, 0x84, 0xa3, 0x7b,
+ 0x20, 0x39, 0x15, 0x7a,
+ 0x00, 0xe2, 0xcc, 0x5b,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x01, 0x84, 0xd1, 0x7b,
0x01, 0xa4, 0x49, 0x07,
0x08, 0x60, 0x30, 0x33,
0x08, 0x80, 0x41, 0x37,
- 0xdf, 0x33, 0x67, 0x0a,
- 0xee, 0x00, 0xb0, 0x6b,
+ 0xdf, 0x39, 0x73, 0x0a,
+ 0xee, 0x00, 0xde, 0x6b,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
- 0x00, 0xe2, 0x6a, 0x59,
- 0x00, 0xe2, 0xbc, 0x42,
- 0x01, 0xea, 0x6c, 0x02,
- 0xc0, 0xea, 0x66, 0x06,
- 0xff, 0x42, 0xc4, 0x6b,
- 0x01, 0x41, 0xb8, 0x6b,
- 0x02, 0x41, 0xb8, 0x7b,
- 0xff, 0x42, 0xc4, 0x6b,
- 0x01, 0x41, 0xb8, 0x6b,
- 0x02, 0x41, 0xb8, 0x7b,
- 0xff, 0x42, 0xc4, 0x7b,
- 0x04, 0x4c, 0xb8, 0x6b,
- 0xe0, 0x41, 0x6c, 0x0e,
+ 0x00, 0xe2, 0x7e, 0x59,
+ 0x00, 0xe2, 0xdc, 0x42,
+ 0xff, 0x42, 0xee, 0x6b,
+ 0x01, 0x41, 0xe2, 0x6b,
+ 0x02, 0x41, 0xe2, 0x7b,
+ 0xff, 0x42, 0xee, 0x6b,
+ 0x01, 0x41, 0xe2, 0x6b,
+ 0x02, 0x41, 0xe2, 0x7b,
+ 0xff, 0x42, 0xee, 0x7b,
+ 0x04, 0x4c, 0xe2, 0x6b,
+ 0xe0, 0x41, 0x78, 0x0e,
0x01, 0x44, 0xd4, 0x31,
- 0xff, 0x42, 0xcc, 0x7b,
- 0x04, 0x4c, 0xcc, 0x6b,
- 0xe0, 0x41, 0x6c, 0x0a,
- 0xe0, 0x36, 0xf9, 0x61,
+ 0xff, 0x42, 0xf6, 0x7b,
+ 0x04, 0x4c, 0xf6, 0x6b,
+ 0xe0, 0x41, 0x78, 0x0a,
+ 0xe0, 0x3c, 0x15, 0x62,
0xff, 0xea, 0xca, 0x09,
0x01, 0xe2, 0xc8, 0x31,
0x01, 0x46, 0xda, 0x35,
0x01, 0x44, 0xd4, 0x35,
0x10, 0xea, 0x80, 0x00,
- 0x01, 0xe2, 0x62, 0x36,
- 0x04, 0xa6, 0xe4, 0x7b,
+ 0x01, 0xe2, 0x6e, 0x36,
+ 0x04, 0xa6, 0x0e, 0x7c,
0xff, 0xea, 0x5a, 0x09,
0xff, 0xea, 0x4c, 0x0d,
- 0x01, 0xa6, 0x02, 0x6c,
- 0x10, 0xad, 0x64, 0x78,
- 0x80, 0xad, 0xfa, 0x6b,
- 0x08, 0xad, 0x64, 0x68,
+ 0x01, 0xa6, 0x3a, 0x6c,
+ 0x10, 0xad, 0x84, 0x78,
+ 0x80, 0xad, 0x32, 0x6c,
+ 0x08, 0xad, 0x84, 0x68,
+ 0x20, 0x19, 0x26, 0x7c,
+ 0x80, 0xea, 0xb2, 0x01,
+ 0x11, 0x00, 0x00, 0x10,
+ 0x02, 0xa6, 0x22, 0x7c,
+ 0xff, 0xea, 0xb2, 0x0d,
+ 0x11, 0x00, 0x00, 0x10,
+ 0xff, 0xea, 0xb2, 0x09,
0x04, 0x84, 0xf9, 0x30,
0x00, 0xea, 0x08, 0x81,
0xff, 0xea, 0xd4, 0x09,
0x02, 0x84, 0xf9, 0x88,
0x0d, 0xea, 0x5a, 0x01,
0x04, 0xa6, 0x4c, 0x05,
- 0x04, 0xa6, 0x64, 0x78,
+ 0x04, 0xa6, 0x84, 0x78,
0xff, 0xea, 0x5a, 0x09,
0x03, 0x84, 0x59, 0x89,
0x03, 0xea, 0x4c, 0x01,
- 0x80, 0x1a, 0x64, 0x78,
- 0x08, 0x19, 0x64, 0x78,
+ 0x80, 0x1a, 0x84, 0x78,
+ 0x08, 0x19, 0x84, 0x78,
0x08, 0xb0, 0xe0, 0x30,
0x04, 0xb0, 0xe0, 0x30,
0x03, 0xb0, 0xf0, 0x30,
@@ -533,259 +561,259 @@ static uint8_t seqprog[] = {
0x00, 0x86, 0x0d, 0x23,
0x00, 0x87, 0x0f, 0x23,
0x01, 0x84, 0xc5, 0x31,
- 0x80, 0x83, 0x25, 0x7c,
+ 0x80, 0x83, 0x5d, 0x7c,
0x02, 0xe2, 0xc4, 0x01,
0xff, 0xea, 0x4c, 0x09,
0x01, 0xe2, 0x36, 0x30,
0xc8, 0x19, 0x32, 0x00,
0x88, 0x19, 0x32, 0x00,
0x01, 0xac, 0xd4, 0x99,
- 0x00, 0xe2, 0x64, 0x50,
+ 0x00, 0xe2, 0x84, 0x50,
0xfe, 0xa6, 0x4c, 0x0d,
0x0b, 0x98, 0xe1, 0x30,
0xfd, 0xa4, 0x49, 0x09,
- 0x80, 0xa3, 0x39, 0x7c,
+ 0x80, 0xa3, 0x71, 0x7c,
0x02, 0xa4, 0x48, 0x01,
0x01, 0xa4, 0x36, 0x30,
0xa8, 0xea, 0x32, 0x00,
0xfd, 0xa4, 0x49, 0x0b,
0x05, 0xa3, 0x07, 0x33,
- 0x80, 0x83, 0x45, 0x6c,
+ 0x80, 0x83, 0x7d, 0x6c,
0x02, 0xea, 0x4c, 0x05,
0xff, 0xea, 0x4c, 0x0d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x02, 0xa6, 0xe6, 0x6b,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x02, 0xa6, 0x10, 0x6c,
0x80, 0xf9, 0xf2, 0x05,
- 0xc0, 0x33, 0x53, 0x7c,
- 0x03, 0xea, 0x50, 0x59,
+ 0xc0, 0x39, 0x8b, 0x7c,
+ 0x03, 0xea, 0x64, 0x59,
0x03, 0xea, 0x04, 0x00,
- 0x20, 0x33, 0x77, 0x7c,
- 0x01, 0x84, 0x5d, 0x6c,
- 0x06, 0xea, 0x50, 0x59,
+ 0x20, 0x39, 0xaf, 0x7c,
+ 0x01, 0x84, 0x95, 0x6c,
+ 0x06, 0xea, 0x64, 0x59,
0x06, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x7a, 0x44,
- 0x01, 0x00, 0x60, 0x32,
- 0xee, 0x00, 0x66, 0x6c,
+ 0x00, 0xe2, 0xb2, 0x44,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0xee, 0x00, 0x9e, 0x6c,
0x05, 0xea, 0xb4, 0x00,
- 0x33, 0xea, 0x44, 0x59,
+ 0x33, 0xea, 0x5e, 0x59,
0x33, 0xea, 0x00, 0x00,
0x80, 0x3d, 0x7a, 0x00,
- 0xfc, 0x42, 0x68, 0x7c,
+ 0xfc, 0x42, 0xa0, 0x7c,
0x7f, 0x3d, 0x7a, 0x08,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x09, 0xea, 0x50, 0x59,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x09, 0xea, 0x64, 0x59,
0x09, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x01, 0xa4, 0x5d, 0x6c,
- 0x00, 0xe2, 0x30, 0x5c,
- 0x20, 0x33, 0x67, 0x02,
- 0x01, 0x00, 0x60, 0x32,
- 0x02, 0xa6, 0x82, 0x7c,
- 0x00, 0xe2, 0x46, 0x5c,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0xe2, 0x66, 0x58,
- 0x00, 0xe2, 0x3a, 0x58,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x20, 0x19, 0x82, 0x6c,
- 0x00, 0xe2, 0xb2, 0x5c,
- 0x04, 0x19, 0x9c, 0x6c,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x01, 0xa4, 0x95, 0x6c,
+ 0x00, 0xe2, 0x68, 0x5c,
+ 0x20, 0x39, 0x73, 0x02,
+ 0x01, 0x00, 0x6c, 0x32,
+ 0x02, 0xa6, 0xba, 0x7c,
+ 0x00, 0xe2, 0x7e, 0x5c,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0xe2, 0x86, 0x58,
+ 0x00, 0xe2, 0x5a, 0x58,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x20, 0x19, 0xba, 0x6c,
+ 0x00, 0xe2, 0xea, 0x5c,
+ 0x04, 0x19, 0xd4, 0x6c,
0x02, 0x19, 0x32, 0x00,
- 0x01, 0x84, 0x9d, 0x7c,
- 0x01, 0x1b, 0x96, 0x7c,
- 0x01, 0x1a, 0x9c, 0x6c,
- 0x00, 0xe2, 0x4c, 0x44,
- 0x80, 0x4b, 0xa2, 0x6c,
- 0x01, 0x4c, 0x9e, 0x7c,
- 0x03, 0x42, 0x4c, 0x6c,
- 0x00, 0xe2, 0xe0, 0x5b,
+ 0x01, 0x84, 0xd5, 0x7c,
+ 0x01, 0x1b, 0xce, 0x7c,
+ 0x01, 0x1a, 0xd4, 0x6c,
+ 0x00, 0xe2, 0x84, 0x44,
+ 0x80, 0x4b, 0xda, 0x6c,
+ 0x01, 0x4c, 0xd6, 0x7c,
+ 0x03, 0x42, 0x84, 0x6c,
+ 0x00, 0xe2, 0x0a, 0x5c,
0x80, 0xf9, 0xf2, 0x01,
- 0x04, 0x33, 0xf9, 0x79,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x08, 0x5d, 0xba, 0x6c,
- 0x00, 0xe2, 0x56, 0x58,
- 0x00, 0x30, 0x45, 0x59,
- 0x01, 0x30, 0x01, 0x30,
- 0x02, 0x1b, 0xaa, 0x7c,
- 0x08, 0x5d, 0xb8, 0x7c,
+ 0x04, 0x39, 0x15, 0x7a,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x08, 0x5d, 0xf2, 0x6c,
+ 0x00, 0xe2, 0x76, 0x58,
+ 0x00, 0x36, 0x5f, 0x59,
+ 0x01, 0x36, 0x01, 0x30,
+ 0x02, 0x1b, 0xe2, 0x7c,
+ 0x08, 0x5d, 0xf0, 0x7c,
0x03, 0x68, 0x00, 0x37,
0x01, 0x84, 0x09, 0x07,
- 0x80, 0x1b, 0xc4, 0x7c,
- 0x80, 0x84, 0xc5, 0x6c,
+ 0x80, 0x1b, 0xfc, 0x7c,
+ 0x80, 0x84, 0xfd, 0x6c,
0xff, 0x85, 0x0b, 0x1b,
0xff, 0x86, 0x0d, 0x23,
0xff, 0x87, 0x0f, 0x23,
0xf8, 0x1b, 0x08, 0x0b,
0xff, 0xea, 0x06, 0x0b,
0x03, 0x68, 0x00, 0x37,
- 0x00, 0xe2, 0xc4, 0x58,
+ 0x00, 0xe2, 0xd6, 0x58,
0x10, 0xea, 0x18, 0x00,
0xf9, 0xd9, 0xb2, 0x0d,
0x01, 0xd9, 0xb2, 0x05,
0x01, 0x52, 0x48, 0x31,
- 0x20, 0xa4, 0xee, 0x7c,
- 0x20, 0x5b, 0xee, 0x7c,
- 0x80, 0xf9, 0xfc, 0x7c,
+ 0x20, 0xa4, 0x26, 0x7d,
+ 0x20, 0x5b, 0x26, 0x7d,
+ 0x80, 0xf9, 0x34, 0x7d,
0x02, 0xea, 0xb4, 0x00,
0x11, 0x00, 0x00, 0x10,
- 0x04, 0x19, 0x08, 0x7d,
+ 0x04, 0x19, 0x40, 0x7d,
0xdf, 0x19, 0x32, 0x08,
- 0x60, 0x5b, 0xe6, 0x6c,
- 0x01, 0x4c, 0xe2, 0x7c,
+ 0x60, 0x5b, 0x40, 0x6d,
+ 0x01, 0x4c, 0x1a, 0x7d,
0x20, 0x19, 0x32, 0x00,
0x01, 0xd9, 0xb2, 0x05,
0x02, 0xea, 0xb4, 0x00,
0x01, 0xd9, 0xb2, 0x05,
- 0x10, 0x5b, 0x00, 0x6d,
- 0x08, 0x5b, 0x0a, 0x6d,
- 0x20, 0x5b, 0xfa, 0x6c,
- 0x02, 0x5b, 0x2a, 0x6d,
- 0x0e, 0xea, 0x50, 0x59,
+ 0x10, 0x5b, 0x38, 0x6d,
+ 0x08, 0x5b, 0x42, 0x6d,
+ 0x20, 0x5b, 0x32, 0x6d,
+ 0x02, 0x5b, 0x62, 0x6d,
+ 0x0e, 0xea, 0x64, 0x59,
0x0e, 0xea, 0x04, 0x00,
- 0x80, 0xf9, 0xea, 0x6c,
+ 0x80, 0xf9, 0x22, 0x6d,
0xdf, 0x5c, 0xb8, 0x08,
0x01, 0xd9, 0xb2, 0x05,
- 0x01, 0xa4, 0xe5, 0x6d,
- 0x00, 0xe2, 0x30, 0x5c,
- 0x00, 0xe2, 0x34, 0x5d,
+ 0x01, 0xa4, 0x1d, 0x6e,
+ 0x00, 0xe2, 0x68, 0x5c,
+ 0x00, 0xe2, 0x6c, 0x5d,
0x01, 0x90, 0x21, 0x1b,
0x01, 0xd9, 0xb2, 0x05,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0x00, 0xe2, 0x52, 0x5b,
0xf3, 0x96, 0xd5, 0x19,
- 0x00, 0xe2, 0x18, 0x55,
- 0x80, 0x96, 0x19, 0x6d,
- 0x0f, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x50, 0x55,
+ 0x80, 0x96, 0x51, 0x6d,
+ 0x0f, 0xea, 0x64, 0x59,
0x0f, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x20, 0x45,
+ 0x00, 0xe2, 0x58, 0x45,
0x04, 0x8c, 0xe1, 0x30,
0x01, 0xea, 0xf2, 0x00,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0xff, 0x97, 0x27, 0x7d,
- 0x14, 0xea, 0x50, 0x59,
+ 0xff, 0x97, 0x5f, 0x7d,
+ 0x14, 0xea, 0x64, 0x59,
0x14, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x96, 0x5d,
+ 0x00, 0xe2, 0xce, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
0x09, 0x80, 0xe1, 0x30,
0x02, 0xea, 0x36, 0x00,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x8e, 0x5d,
+ 0x00, 0xe2, 0xc6, 0x5d,
0x01, 0xd9, 0xb2, 0x05,
- 0x02, 0xa6, 0x44, 0x7d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x20, 0x5b, 0x52, 0x6d,
- 0xfc, 0x42, 0x3e, 0x7d,
- 0x10, 0x40, 0x40, 0x6d,
- 0x20, 0x4d, 0x42, 0x7d,
- 0x08, 0x5d, 0x52, 0x6d,
- 0x02, 0xa6, 0xe6, 0x6b,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x20, 0x5b, 0x52, 0x6d,
- 0x01, 0x1b, 0x72, 0x6d,
- 0xfc, 0x42, 0x4e, 0x7d,
- 0x10, 0x40, 0x50, 0x6d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x08, 0x5d, 0x64, 0x78,
+ 0x02, 0xa6, 0x7c, 0x7d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x20, 0x5b, 0x8a, 0x6d,
+ 0xfc, 0x42, 0x76, 0x7d,
+ 0x10, 0x40, 0x78, 0x6d,
+ 0x20, 0x4d, 0x7a, 0x7d,
+ 0x08, 0x5d, 0x8a, 0x6d,
+ 0x02, 0xa6, 0x10, 0x6c,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x20, 0x5b, 0x8a, 0x6d,
+ 0x01, 0x1b, 0xaa, 0x6d,
+ 0xfc, 0x42, 0x86, 0x7d,
+ 0x10, 0x40, 0x88, 0x6d,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x08, 0x5d, 0x84, 0x78,
0x02, 0x19, 0x32, 0x00,
0x01, 0x5b, 0x40, 0x31,
- 0x00, 0xe2, 0xb2, 0x5c,
- 0x00, 0xe2, 0x9e, 0x5b,
+ 0x00, 0xe2, 0xea, 0x5c,
+ 0x00, 0xe2, 0xcc, 0x5b,
0x20, 0xea, 0xb6, 0x00,
- 0x00, 0xe2, 0xe0, 0x5b,
+ 0x00, 0xe2, 0x0a, 0x5c,
0x20, 0x5c, 0xb8, 0x00,
- 0x04, 0x19, 0x68, 0x6d,
- 0x01, 0x1a, 0x68, 0x6d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1a, 0x64, 0x78,
+ 0x04, 0x19, 0xa0, 0x6d,
+ 0x01, 0x1a, 0xa0, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
- 0x20, 0xa0, 0xcc, 0x7d,
+ 0x20, 0xa0, 0x04, 0x7e,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
0x01, 0xa4, 0x49, 0x03,
- 0x40, 0x5b, 0x82, 0x6d,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x40, 0x5b, 0x82, 0x6d,
- 0x04, 0x5d, 0xe6, 0x7d,
- 0x01, 0x1a, 0xe6, 0x7d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x40, 0x5b, 0xcc, 0x7d,
- 0x04, 0x5d, 0xe6, 0x7d,
- 0x01, 0x1a, 0xe6, 0x7d,
+ 0x40, 0x5b, 0xba, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x40, 0x5b, 0xba, 0x6d,
+ 0x04, 0x5d, 0x1e, 0x7e,
+ 0x01, 0x1a, 0x1e, 0x7e,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x40, 0x5b, 0x04, 0x7e,
+ 0x04, 0x5d, 0x1e, 0x7e,
+ 0x01, 0x1a, 0x1e, 0x7e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1b, 0x64, 0x78,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1b, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0x02, 0xea, 0xb4, 0x04,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x01, 0x1b, 0xaa, 0x6d,
- 0x40, 0x5b, 0xb8, 0x7d,
- 0x01, 0x1b, 0xaa, 0x6d,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x01, 0x1b, 0xe2, 0x6d,
+ 0x40, 0x5b, 0xf0, 0x7d,
+ 0x01, 0x1b, 0xe2, 0x6d,
0x02, 0x19, 0x32, 0x00,
- 0x01, 0x1a, 0x64, 0x78,
+ 0x01, 0x1a, 0x84, 0x78,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0xea, 0x10, 0x03,
0x08, 0x92, 0x25, 0x03,
- 0x00, 0xe2, 0x42, 0x43,
- 0x01, 0x1a, 0xb4, 0x7d,
- 0x40, 0x5b, 0xb0, 0x7d,
- 0x01, 0x1a, 0x9e, 0x6d,
- 0xfc, 0x42, 0x64, 0x78,
- 0x01, 0x1a, 0xb8, 0x6d,
- 0x10, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x62, 0x43,
+ 0x01, 0x1a, 0xec, 0x7d,
+ 0x40, 0x5b, 0xe8, 0x7d,
+ 0x01, 0x1a, 0xd6, 0x6d,
+ 0xfc, 0x42, 0x84, 0x78,
+ 0x01, 0x1a, 0xf0, 0x6d,
+ 0x10, 0xea, 0x64, 0x59,
0x10, 0xea, 0x04, 0x00,
- 0xfc, 0x42, 0x64, 0x78,
- 0x10, 0x40, 0xbe, 0x6d,
- 0x20, 0x4d, 0x64, 0x78,
- 0x40, 0x5b, 0x9e, 0x6d,
- 0x01, 0x1a, 0x64, 0x78,
+ 0xfc, 0x42, 0x84, 0x78,
+ 0x10, 0x40, 0xf6, 0x6d,
+ 0x20, 0x4d, 0x84, 0x78,
+ 0x40, 0x5b, 0xd6, 0x6d,
+ 0x01, 0x1a, 0x84, 0x78,
0x01, 0x90, 0x21, 0x1b,
0x30, 0x3f, 0xc0, 0x09,
- 0x30, 0xe0, 0x64, 0x60,
- 0x40, 0x4b, 0x64, 0x68,
+ 0x30, 0xe0, 0x84, 0x60,
+ 0x40, 0x4b, 0x84, 0x68,
0xff, 0xea, 0x52, 0x01,
- 0xee, 0x00, 0xd2, 0x6d,
+ 0xee, 0x00, 0x0c, 0x6e,
0x80, 0xf9, 0xf2, 0x01,
0xff, 0x90, 0x21, 0x1b,
0x02, 0xea, 0xb4, 0x00,
0x20, 0xea, 0x9a, 0x00,
- 0xf3, 0x42, 0xde, 0x6d,
- 0x12, 0xea, 0x50, 0x59,
+ 0xf3, 0x42, 0x16, 0x6e,
+ 0x12, 0xea, 0x64, 0x59,
0x12, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
- 0x0d, 0xea, 0x50, 0x59,
+ 0x00, 0xe2, 0x14, 0x42,
+ 0x0d, 0xea, 0x64, 0x59,
0x0d, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0xf8, 0x41,
+ 0x00, 0xe2, 0x14, 0x42,
0x01, 0x90, 0x21, 0x1b,
- 0x11, 0xea, 0x50, 0x59,
+ 0x11, 0xea, 0x64, 0x59,
0x11, 0xea, 0x04, 0x00,
- 0x00, 0xe2, 0x32, 0x5b,
+ 0x00, 0xe2, 0x52, 0x5b,
0x08, 0x5a, 0xb4, 0x00,
- 0x00, 0xe2, 0x0c, 0x5e,
+ 0x00, 0xe2, 0x44, 0x5e,
0xa8, 0xea, 0x32, 0x00,
- 0x00, 0xe2, 0x3e, 0x59,
- 0x80, 0x1a, 0xfa, 0x7d,
- 0x00, 0xe2, 0x0c, 0x5e,
+ 0x00, 0xe2, 0x56, 0x59,
+ 0x80, 0x1a, 0x32, 0x7e,
+ 0x00, 0xe2, 0x44, 0x5e,
0x80, 0x19, 0x32, 0x00,
- 0x40, 0x5b, 0x00, 0x6e,
- 0x08, 0x5a, 0x00, 0x7e,
- 0x20, 0x4d, 0x64, 0x78,
+ 0x40, 0x5b, 0x38, 0x6e,
+ 0x08, 0x5a, 0x38, 0x7e,
+ 0x20, 0x4d, 0x84, 0x78,
0x02, 0x84, 0x09, 0x03,
- 0x40, 0x5b, 0xcc, 0x7d,
+ 0x40, 0x5b, 0x04, 0x7e,
0xff, 0x90, 0x21, 0x1b,
0x80, 0xf9, 0xf2, 0x01,
- 0x08, 0x92, 0x43, 0x6b,
+ 0x08, 0x92, 0x63, 0x6b,
0x02, 0xea, 0xb4, 0x04,
- 0x01, 0x38, 0xe1, 0x30,
- 0x05, 0x39, 0xe3, 0x98,
+ 0x01, 0x40, 0xe1, 0x30,
+ 0x05, 0x41, 0xe3, 0x98,
0x01, 0xe0, 0xf4, 0x31,
0xff, 0xea, 0xc0, 0x09,
- 0x00, 0x3a, 0xe5, 0x20,
- 0x00, 0x3b, 0xe7, 0x20,
+ 0x00, 0x42, 0xe5, 0x20,
+ 0x00, 0x43, 0xe7, 0x20,
0x01, 0xfa, 0xc0, 0x31,
0x04, 0xea, 0xe8, 0x30,
0xff, 0xea, 0xf0, 0x08,
@@ -794,12 +822,20 @@ static uint8_t seqprog[] = {
};
typedef int ahd_patch_func_t (struct ahd_softc *ahd);
+static ahd_patch_func_t ahd_patch23_func;
+
+static int
+ahd_patch23_func(struct ahd_softc *ahd)
+{
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+}
+
static ahd_patch_func_t ahd_patch22_func;
static int
ahd_patch22_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0);
+ return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
}
static ahd_patch_func_t ahd_patch21_func;
@@ -807,7 +843,7 @@ static ahd_patch_func_t ahd_patch21_func;
static int
ahd_patch21_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) == 0);
+ return ((ahd->flags & AHD_INITIATORROLE) != 0);
}
static ahd_patch_func_t ahd_patch20_func;
@@ -815,7 +851,7 @@ static ahd_patch_func_t ahd_patch20_func;
static int
ahd_patch20_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_RTI) == 0);
+ return ((ahd->flags & AHD_TARGETROLE) != 0);
}
static ahd_patch_func_t ahd_patch19_func;
@@ -823,7 +859,7 @@ static ahd_patch_func_t ahd_patch19_func;
static int
ahd_patch19_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_INITIATORROLE) != 0);
+ return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
}
static ahd_patch_func_t ahd_patch18_func;
@@ -831,7 +867,7 @@ static ahd_patch_func_t ahd_patch18_func;
static int
ahd_patch18_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_TARGETROLE) != 0);
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
}
static ahd_patch_func_t ahd_patch17_func;
@@ -839,7 +875,7 @@ static ahd_patch_func_t ahd_patch17_func;
static int
ahd_patch17_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0);
+ return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch16_func;
@@ -847,7 +883,7 @@ static ahd_patch_func_t ahd_patch16_func;
static int
ahd_patch16_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0);
+ return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
}
static ahd_patch_func_t ahd_patch15_func;
@@ -855,7 +891,7 @@ static ahd_patch_func_t ahd_patch15_func;
static int
ahd_patch15_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_39BIT_ADDRESSING) != 0);
+ return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
}
static ahd_patch_func_t ahd_patch14_func;
@@ -863,7 +899,7 @@ static ahd_patch_func_t ahd_patch14_func;
static int
ahd_patch14_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_64BIT_ADDRESSING) != 0);
+ return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
}
static ahd_patch_func_t ahd_patch13_func;
@@ -871,7 +907,7 @@ static ahd_patch_func_t ahd_patch13_func;
static int
ahd_patch13_func(struct ahd_softc *ahd)
{
- return ((ahd->features & AHD_NEW_DFCNTRL_OPTS) == 0);
+ return ((ahd->features & AHD_RTI) == 0);
}
static ahd_patch_func_t ahd_patch12_func;
@@ -879,7 +915,7 @@ static ahd_patch_func_t ahd_patch12_func;
static int
ahd_patch12_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0);
+ return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
}
static ahd_patch_func_t ahd_patch11_func;
@@ -887,7 +923,7 @@ static ahd_patch_func_t ahd_patch11_func;
static int
ahd_patch11_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0);
+ return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
}
static ahd_patch_func_t ahd_patch10_func;
@@ -895,7 +931,7 @@ static ahd_patch_func_t ahd_patch10_func;
static int
ahd_patch10_func(struct ahd_softc *ahd)
{
- return ((ahd->bugs & AHD_BUSFREEREV_BUG) == 0);
+ return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
}
static ahd_patch_func_t ahd_patch9_func;
@@ -903,7 +939,7 @@ static ahd_patch_func_t ahd_patch9_func;
static int
ahd_patch9_func(struct ahd_softc *ahd)
{
- return ((ahd->flags & AHD_SEQUENCER_DEBUG) != 0);
+ return ((ahd->features & AHD_FAST_CDB_DELIVERY) != 0);
}
static ahd_patch_func_t ahd_patch8_func;
@@ -992,147 +1028,149 @@ static struct patch {
{ ahd_patch0_func, 5, 1, 1 },
{ ahd_patch2_func, 6, 1, 2 },
{ ahd_patch0_func, 7, 1, 1 },
- { ahd_patch3_func, 20, 5, 1 },
- { ahd_patch2_func, 29, 1, 2 },
- { ahd_patch0_func, 30, 1, 1 },
- { ahd_patch1_func, 37, 1, 2 },
- { ahd_patch0_func, 38, 1, 1 },
- { ahd_patch2_func, 43, 1, 2 },
- { ahd_patch0_func, 44, 1, 1 },
- { ahd_patch2_func, 47, 1, 2 },
- { ahd_patch0_func, 48, 1, 1 },
- { ahd_patch2_func, 51, 1, 2 },
- { ahd_patch0_func, 52, 1, 1 },
- { ahd_patch2_func, 65, 1, 2 },
- { ahd_patch0_func, 66, 1, 1 },
- { ahd_patch2_func, 69, 1, 2 },
- { ahd_patch0_func, 70, 1, 1 },
- { ahd_patch1_func, 73, 1, 2 },
- { ahd_patch0_func, 74, 1, 1 },
- { ahd_patch4_func, 107, 1, 1 },
- { ahd_patch2_func, 162, 6, 1 },
- { ahd_patch1_func, 168, 2, 1 },
- { ahd_patch5_func, 170, 1, 1 },
- { ahd_patch2_func, 179, 1, 2 },
- { ahd_patch0_func, 180, 1, 1 },
- { ahd_patch6_func, 181, 2, 2 },
- { ahd_patch0_func, 183, 6, 3 },
- { ahd_patch2_func, 186, 1, 2 },
- { ahd_patch0_func, 187, 1, 1 },
- { ahd_patch2_func, 190, 1, 2 },
- { ahd_patch0_func, 191, 1, 1 },
- { ahd_patch7_func, 193, 2, 1 },
- { ahd_patch5_func, 201, 16, 2 },
- { ahd_patch0_func, 217, 1, 1 },
- { ahd_patch8_func, 237, 2, 1 },
- { ahd_patch1_func, 241, 1, 2 },
- { ahd_patch0_func, 242, 1, 1 },
- { ahd_patch7_func, 245, 2, 1 },
- { ahd_patch1_func, 259, 1, 2 },
- { ahd_patch0_func, 260, 1, 1 },
- { ahd_patch1_func, 263, 1, 2 },
- { ahd_patch0_func, 264, 1, 1 },
- { ahd_patch2_func, 267, 1, 2 },
- { ahd_patch0_func, 268, 1, 1 },
- { ahd_patch1_func, 323, 1, 2 },
- { ahd_patch0_func, 324, 1, 1 },
- { ahd_patch2_func, 332, 1, 2 },
- { ahd_patch0_func, 333, 1, 1 },
- { ahd_patch2_func, 336, 1, 2 },
- { ahd_patch0_func, 337, 1, 1 },
- { ahd_patch1_func, 343, 1, 2 },
- { ahd_patch0_func, 344, 1, 1 },
- { ahd_patch1_func, 346, 1, 2 },
- { ahd_patch0_func, 347, 1, 1 },
- { ahd_patch9_func, 366, 1, 1 },
- { ahd_patch9_func, 369, 1, 1 },
- { ahd_patch9_func, 371, 1, 1 },
- { ahd_patch9_func, 383, 1, 1 },
- { ahd_patch1_func, 393, 1, 2 },
- { ahd_patch0_func, 394, 1, 1 },
- { ahd_patch1_func, 396, 1, 2 },
- { ahd_patch0_func, 397, 1, 1 },
- { ahd_patch1_func, 405, 1, 2 },
- { ahd_patch0_func, 406, 1, 1 },
- { ahd_patch2_func, 419, 1, 2 },
- { ahd_patch0_func, 420, 1, 1 },
- { ahd_patch10_func, 450, 1, 1 },
- { ahd_patch1_func, 457, 1, 2 },
- { ahd_patch0_func, 458, 1, 1 },
- { ahd_patch2_func, 470, 1, 2 },
- { ahd_patch0_func, 471, 1, 1 },
- { ahd_patch11_func, 476, 6, 2 },
- { ahd_patch0_func, 482, 1, 1 },
- { ahd_patch12_func, 505, 1, 1 },
- { ahd_patch13_func, 514, 1, 1 },
- { ahd_patch14_func, 515, 1, 2 },
- { ahd_patch0_func, 516, 1, 1 },
- { ahd_patch15_func, 519, 1, 1 },
- { ahd_patch14_func, 520, 1, 1 },
- { ahd_patch16_func, 531, 1, 2 },
- { ahd_patch0_func, 532, 1, 1 },
- { ahd_patch1_func, 551, 1, 2 },
- { ahd_patch0_func, 552, 1, 1 },
- { ahd_patch1_func, 555, 1, 2 },
- { ahd_patch0_func, 556, 1, 1 },
- { ahd_patch2_func, 561, 1, 2 },
- { ahd_patch0_func, 562, 1, 1 },
- { ahd_patch2_func, 566, 1, 2 },
- { ahd_patch0_func, 567, 1, 1 },
- { ahd_patch1_func, 568, 1, 2 },
- { ahd_patch0_func, 569, 1, 1 },
- { ahd_patch2_func, 580, 1, 2 },
- { ahd_patch0_func, 581, 1, 1 },
- { ahd_patch17_func, 585, 1, 1 },
- { ahd_patch18_func, 590, 1, 1 },
- { ahd_patch19_func, 591, 2, 1 },
- { ahd_patch18_func, 595, 1, 2 },
- { ahd_patch0_func, 596, 1, 1 },
- { ahd_patch2_func, 599, 1, 2 },
- { ahd_patch0_func, 600, 1, 1 },
- { ahd_patch2_func, 615, 1, 2 },
- { ahd_patch0_func, 616, 1, 1 },
- { ahd_patch20_func, 617, 14, 1 },
- { ahd_patch1_func, 635, 1, 2 },
- { ahd_patch0_func, 636, 1, 1 },
- { ahd_patch20_func, 637, 1, 1 },
- { ahd_patch1_func, 649, 1, 2 },
- { ahd_patch0_func, 650, 1, 1 },
- { ahd_patch1_func, 657, 1, 2 },
- { ahd_patch0_func, 658, 1, 1 },
- { ahd_patch17_func, 681, 1, 1 },
- { ahd_patch17_func, 719, 1, 1 },
- { ahd_patch1_func, 730, 1, 2 },
- { ahd_patch0_func, 731, 1, 1 },
- { ahd_patch1_func, 748, 1, 2 },
- { ahd_patch0_func, 749, 1, 1 },
- { ahd_patch1_func, 751, 1, 2 },
- { ahd_patch0_func, 752, 1, 1 },
- { ahd_patch1_func, 755, 1, 2 },
- { ahd_patch0_func, 756, 1, 1 },
- { ahd_patch21_func, 758, 1, 2 },
- { ahd_patch0_func, 759, 2, 1 },
- { ahd_patch22_func, 762, 4, 2 },
- { ahd_patch0_func, 766, 1, 1 },
- { ahd_patch22_func, 774, 11, 1 }
+ { ahd_patch3_func, 36, 5, 1 },
+ { ahd_patch2_func, 45, 1, 2 },
+ { ahd_patch0_func, 46, 1, 1 },
+ { ahd_patch1_func, 53, 1, 2 },
+ { ahd_patch0_func, 54, 1, 1 },
+ { ahd_patch2_func, 59, 1, 2 },
+ { ahd_patch0_func, 60, 1, 1 },
+ { ahd_patch2_func, 63, 1, 2 },
+ { ahd_patch0_func, 64, 1, 1 },
+ { ahd_patch2_func, 67, 1, 2 },
+ { ahd_patch0_func, 68, 1, 1 },
+ { ahd_patch4_func, 116, 1, 1 },
+ { ahd_patch2_func, 175, 3, 1 },
+ { ahd_patch1_func, 178, 2, 1 },
+ { ahd_patch5_func, 180, 1, 1 },
+ { ahd_patch2_func, 189, 1, 2 },
+ { ahd_patch0_func, 190, 1, 1 },
+ { ahd_patch6_func, 191, 2, 2 },
+ { ahd_patch0_func, 193, 6, 3 },
+ { ahd_patch2_func, 196, 1, 2 },
+ { ahd_patch0_func, 197, 1, 1 },
+ { ahd_patch2_func, 200, 1, 2 },
+ { ahd_patch0_func, 201, 1, 1 },
+ { ahd_patch3_func, 203, 1, 1 },
+ { ahd_patch7_func, 204, 3, 1 },
+ { ahd_patch3_func, 213, 1, 1 },
+ { ahd_patch5_func, 214, 16, 2 },
+ { ahd_patch0_func, 230, 1, 1 },
+ { ahd_patch8_func, 250, 2, 1 },
+ { ahd_patch1_func, 254, 1, 2 },
+ { ahd_patch0_func, 255, 1, 1 },
+ { ahd_patch7_func, 258, 3, 1 },
+ { ahd_patch1_func, 273, 1, 2 },
+ { ahd_patch0_func, 274, 1, 1 },
+ { ahd_patch1_func, 277, 1, 2 },
+ { ahd_patch0_func, 278, 1, 1 },
+ { ahd_patch2_func, 281, 1, 2 },
+ { ahd_patch0_func, 282, 1, 1 },
+ { ahd_patch9_func, 295, 2, 2 },
+ { ahd_patch0_func, 297, 1, 1 },
+ { ahd_patch1_func, 339, 1, 2 },
+ { ahd_patch0_func, 340, 1, 1 },
+ { ahd_patch2_func, 348, 1, 2 },
+ { ahd_patch0_func, 349, 1, 1 },
+ { ahd_patch2_func, 352, 1, 2 },
+ { ahd_patch0_func, 353, 1, 1 },
+ { ahd_patch1_func, 359, 1, 2 },
+ { ahd_patch0_func, 360, 1, 1 },
+ { ahd_patch1_func, 362, 1, 2 },
+ { ahd_patch0_func, 363, 1, 1 },
+ { ahd_patch10_func, 382, 1, 1 },
+ { ahd_patch10_func, 385, 1, 1 },
+ { ahd_patch10_func, 387, 1, 1 },
+ { ahd_patch10_func, 399, 1, 1 },
+ { ahd_patch1_func, 409, 1, 2 },
+ { ahd_patch0_func, 410, 1, 1 },
+ { ahd_patch1_func, 412, 1, 2 },
+ { ahd_patch0_func, 413, 1, 1 },
+ { ahd_patch1_func, 421, 1, 2 },
+ { ahd_patch0_func, 422, 1, 1 },
+ { ahd_patch2_func, 435, 1, 2 },
+ { ahd_patch0_func, 436, 1, 1 },
+ { ahd_patch11_func, 472, 1, 1 },
+ { ahd_patch1_func, 480, 1, 2 },
+ { ahd_patch0_func, 481, 1, 1 },
+ { ahd_patch2_func, 493, 1, 2 },
+ { ahd_patch0_func, 494, 1, 1 },
+ { ahd_patch12_func, 497, 6, 2 },
+ { ahd_patch0_func, 503, 1, 1 },
+ { ahd_patch13_func, 524, 7, 1 },
+ { ahd_patch14_func, 533, 1, 1 },
+ { ahd_patch15_func, 542, 1, 1 },
+ { ahd_patch16_func, 543, 1, 2 },
+ { ahd_patch0_func, 544, 1, 1 },
+ { ahd_patch17_func, 547, 1, 1 },
+ { ahd_patch16_func, 548, 1, 1 },
+ { ahd_patch18_func, 559, 1, 2 },
+ { ahd_patch0_func, 560, 1, 1 },
+ { ahd_patch1_func, 579, 1, 2 },
+ { ahd_patch0_func, 580, 1, 1 },
+ { ahd_patch1_func, 583, 1, 2 },
+ { ahd_patch0_func, 584, 1, 1 },
+ { ahd_patch2_func, 589, 1, 2 },
+ { ahd_patch0_func, 590, 1, 1 },
+ { ahd_patch2_func, 594, 1, 2 },
+ { ahd_patch0_func, 595, 1, 1 },
+ { ahd_patch1_func, 596, 1, 2 },
+ { ahd_patch0_func, 597, 1, 1 },
+ { ahd_patch2_func, 608, 1, 2 },
+ { ahd_patch0_func, 609, 1, 1 },
+ { ahd_patch19_func, 613, 1, 1 },
+ { ahd_patch20_func, 618, 1, 1 },
+ { ahd_patch21_func, 619, 2, 1 },
+ { ahd_patch20_func, 623, 1, 2 },
+ { ahd_patch0_func, 624, 1, 1 },
+ { ahd_patch2_func, 627, 1, 2 },
+ { ahd_patch0_func, 628, 1, 1 },
+ { ahd_patch2_func, 643, 1, 2 },
+ { ahd_patch0_func, 644, 1, 1 },
+ { ahd_patch13_func, 645, 14, 1 },
+ { ahd_patch1_func, 663, 1, 2 },
+ { ahd_patch0_func, 664, 1, 1 },
+ { ahd_patch13_func, 665, 1, 1 },
+ { ahd_patch1_func, 677, 1, 2 },
+ { ahd_patch0_func, 678, 1, 1 },
+ { ahd_patch1_func, 685, 1, 2 },
+ { ahd_patch0_func, 686, 1, 1 },
+ { ahd_patch19_func, 709, 1, 1 },
+ { ahd_patch19_func, 747, 1, 1 },
+ { ahd_patch1_func, 758, 1, 2 },
+ { ahd_patch0_func, 759, 1, 1 },
+ { ahd_patch1_func, 776, 1, 2 },
+ { ahd_patch0_func, 777, 1, 1 },
+ { ahd_patch1_func, 779, 1, 2 },
+ { ahd_patch0_func, 780, 1, 1 },
+ { ahd_patch1_func, 783, 1, 2 },
+ { ahd_patch0_func, 784, 1, 1 },
+ { ahd_patch22_func, 786, 1, 2 },
+ { ahd_patch0_func, 787, 2, 1 },
+ { ahd_patch23_func, 790, 4, 2 },
+ { ahd_patch0_func, 794, 1, 1 },
+ { ahd_patch23_func, 802, 11, 1 }
};
static struct cs {
uint16_t begin;
uint16_t end;
} critical_sections[] = {
- { 11, 12 },
- { 13, 14 },
- { 29, 42 },
- { 56, 59 },
- { 101, 128 },
- { 129, 157 },
- { 159, 162 },
- { 170, 178 },
- { 201, 250 },
- { 681, 697 },
- { 697, 711 },
- { 721, 725 }
+ { 17, 28 },
+ { 29, 30 },
+ { 47, 58 },
+ { 61, 63 },
+ { 65, 66 },
+ { 72, 92 },
+ { 110, 137 },
+ { 138, 175 },
+ { 180, 188 },
+ { 213, 264 },
+ { 425, 433 },
+ { 443, 445 },
+ { 448, 457 },
+ { 709, 739 },
+ { 749, 753 }
};
static const int num_critical_sections = sizeof(critical_sections)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index d866213f42b8..051970efba68 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -375,7 +375,7 @@ static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
struct scsi_cmnd *cmd);
static void ahc_linux_sem_timeout(u_long arg);
static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
-static void ahc_linux_release_simq(u_long arg);
+static void ahc_linux_release_simq(struct ahc_softc *ahc);
static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
@@ -1061,10 +1061,11 @@ uint32_t aic7xxx_verbose;
int
ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
{
- char buf[80];
- struct Scsi_Host *host;
+ char buf[80];
+ struct Scsi_Host *host;
char *new_name;
- u_long s;
+ u_long s;
+ int retval;
template->name = ahc->description;
host = scsi_host_alloc(template, sizeof(struct ahc_softc *));
@@ -1072,7 +1073,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
return (ENOMEM);
*((struct ahc_softc **)host->hostdata) = ahc;
- ahc_lock(ahc, &s);
ahc->platform_data->host = host;
host->can_queue = AHC_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -1083,7 +1083,9 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->max_lun = AHC_NUM_LUNS;
host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;
host->sg_tablesize = AHC_NSEG;
+ ahc_lock(ahc, &s);
ahc_set_unit(ahc, ahc_linux_unit++);
+ ahc_unlock(ahc, &s);
sprintf(buf, "scsi%d", host->host_no);
new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (new_name != NULL) {
@@ -1093,13 +1095,19 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
host->unique_id = ahc->unit;
ahc_linux_initialize_scsi_bus(ahc);
ahc_intr_enable(ahc, TRUE);
- ahc_unlock(ahc, &s);
host->transportt = ahc_linux_transport_template;
- scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
+ retval = scsi_add_host(host,
+ (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
+ if (retval) {
+ printk(KERN_WARNING "aic7xxx: scsi_add_host failed\n");
+ scsi_host_put(host);
+ return retval;
+ }
+
scsi_scan_host(host);
- return (0);
+ return 0;
}
/*
@@ -1112,10 +1120,13 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
{
int i;
int numtarg;
+ unsigned long s;
i = 0;
numtarg = 0;
+ ahc_lock(ahc, &s);
+
if (aic7xxx_no_reset != 0)
ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);
@@ -1162,16 +1173,12 @@ ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc)
ahc_update_neg_request(ahc, &devinfo, tstate,
tinfo, AHC_NEG_ALWAYS);
}
+ ahc_unlock(ahc, &s);
/* Give the bus some time to recover */
if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {
ahc_linux_freeze_simq(ahc);
- init_timer(&ahc->platform_data->reset_timer);
- ahc->platform_data->reset_timer.data = (u_long)ahc;
- ahc->platform_data->reset_timer.expires =
- jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;
- ahc->platform_data->reset_timer.function =
- ahc_linux_release_simq;
- add_timer(&ahc->platform_data->reset_timer);
+ msleep(AIC7XXX_RESET_DELAY);
+ ahc_linux_release_simq(ahc);
}
}
@@ -2051,6 +2058,9 @@ ahc_linux_sem_timeout(u_long arg)
static void
ahc_linux_freeze_simq(struct ahc_softc *ahc)
{
+ unsigned long s;
+
+ ahc_lock(ahc, &s);
ahc->platform_data->qfrozen++;
if (ahc->platform_data->qfrozen == 1) {
scsi_block_requests(ahc->platform_data->host);
@@ -2060,17 +2070,15 @@ ahc_linux_freeze_simq(struct ahc_softc *ahc)
CAM_LUN_WILDCARD, SCB_LIST_NULL,
ROLE_INITIATOR, CAM_REQUEUE_REQ);
}
+ ahc_unlock(ahc, &s);
}
static void
-ahc_linux_release_simq(u_long arg)
+ahc_linux_release_simq(struct ahc_softc *ahc)
{
- struct ahc_softc *ahc;
u_long s;
int unblock_reqs;
- ahc = (struct ahc_softc *)arg;
-
unblock_reqs = 0;
ahc_lock(ahc, &s);
if (ahc->platform_data->qfrozen > 0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index f2a95447142c..e0edacae895f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -223,9 +223,6 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
*/
#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op)
-/************************** Timer DataStructures ******************************/
-typedef struct timer_list ahc_timer_t;
-
/********************************** Includes **********************************/
#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT
#define AIC_DEBUG_REGISTERS 1
@@ -235,30 +232,9 @@ typedef struct timer_list ahc_timer_t;
#include "aic7xxx.h"
/***************************** Timer Facilities *******************************/
-#define ahc_timer_init init_timer
-#define ahc_timer_stop del_timer_sync
-typedef void ahc_linux_callback_t (u_long);
-static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec,
- ahc_callback_t *func, void *arg);
-static __inline void ahc_scb_timer_reset(struct scb *scb, u_int usec);
-
-static __inline void
-ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg)
-{
- struct ahc_softc *ahc;
-
- ahc = (struct ahc_softc *)arg;
- del_timer(timer);
- timer->data = (u_long)arg;
- timer->expires = jiffies + (usec * HZ)/1000000;
- timer->function = (ahc_linux_callback_t*)func;
- add_timer(timer);
-}
-
static __inline void
ahc_scb_timer_reset(struct scb *scb, u_int usec)
{
- mod_timer(&scb->io_ctx->eh_timeout, jiffies + (usec * HZ)/1000000);
}
/***************************** SMP support ************************************/
@@ -393,7 +369,6 @@ struct ahc_platform_data {
spinlock_t spin_lock;
u_int qfrozen;
- struct timer_list reset_timer;
struct semaphore eh_sem;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index b3b2e2237eb3..5f586140e057 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -39,9 +39,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_pci.c#69 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
*/
#ifdef __linux__
@@ -393,6 +391,12 @@ struct ahc_pci_identity ahc_pci_ident_table [] =
"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
ahc_aic7892_setup
},
+ {
+ ID_AHA_2915_30LP,
+ ID_ALL_MASK,
+ "Adaptec 2915/30LP Ultra160 SCSI adapter",
+ ahc_aic7892_setup
+ },
/* aic7895 based controllers */
{
ID_AHA_2940U_DUAL,
@@ -1193,9 +1197,19 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
* use for this test.
*/
hcntrl = ahc_inb(ahc, HCNTRL);
+
if (hcntrl == 0xFF)
goto fail;
+ if ((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;
+ }
+
/*
* Next create a situation where write combining
* or read prefetching could be initiated by the
@@ -1307,6 +1321,10 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
sd.sd_chip = C56_66;
}
ahc_release_seeprom(&sd);
+
+ /* Remember the SEEPROM type for later */
+ if (sd.sd_chip == C56_66)
+ ahc->flags |= AHC_LARGE_SEEPROM;
}
if (!have_seeprom) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.h b/drivers/scsi/aic7xxx/aic7xxx_pci.h
index be27fcb20346..263f85da405e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.h
@@ -105,6 +105,7 @@
#define ID_AHA_29160C 0x0080900562209005ull
#define ID_AHA_29160B 0x00809005E2209005ull
#define ID_AHA_19160B 0x0081900562A19005ull
+#define ID_AHA_2915_30LP 0x0082900502109005ull
#define ID_AIC7896 0x005F9005FFFF9005ull
#define ID_AIC7896_ARO 0x00539005FFFF9005ull
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 33d56c344944..770f1647e4d6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -1290,7 +1290,7 @@ static void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);
*
***************************************************************************/
-static inline unsigned char
+static unsigned char
aic_inb(struct aic7xxx_host *p, long port)
{
#ifdef MMAPIO
@@ -1309,7 +1309,7 @@ aic_inb(struct aic7xxx_host *p, long port)
#endif
}
-static inline void
+static void
aic_outb(struct aic7xxx_host *p, unsigned char val, long port)
{
#ifdef MMAPIO
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
index 13f23043c8a3..06d7601cdf56 100644
--- a/drivers/scsi/arm/Kconfig
+++ b/drivers/scsi/arm/Kconfig
@@ -4,6 +4,7 @@
config SCSI_ACORNSCSI_3
tristate "Acorn SCSI card (aka30) support"
depends on ARCH_ACORN && SCSI && BROKEN
+ select SCSI_SPI_ATTRS
help
This enables support for the Acorn SCSI card (aka30). If you have an
Acorn system with one of these, say Y. If unsure, say N.
diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c
index b7b20c689c24..dda5a5f79c53 100644
--- a/drivers/scsi/arm/acornscsi.c
+++ b/drivers/scsi/arm/acornscsi.c
@@ -146,12 +146,12 @@
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/ecard.h>
#include "../scsi.h"
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
#include "acornscsi.h"
#include "msgqueue.h"
#include "scsi.h"
@@ -1370,7 +1370,7 @@ void acornscsi_sendmessage(AS_Host *host)
host->scsi.last_message = msg->msg[0];
#if (DEBUG & DEBUG_MESSAGES)
- scsi_print_msg(msg->msg);
+ spi_print_msg(msg->msg);
#endif
break;
@@ -1392,7 +1392,7 @@ void acornscsi_sendmessage(AS_Host *host)
while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
unsigned int i;
#if (DEBUG & DEBUG_MESSAGES)
- scsi_print_msg(msg);
+ spi_print_msg(msg);
#endif
i = 0;
if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000))
@@ -1488,7 +1488,7 @@ void acornscsi_message(AS_Host *host)
#if (DEBUG & DEBUG_MESSAGES)
printk("scsi%d.%c: message in: ",
host->host->host_no, acornscsi_target(host));
- scsi_print_msg(message);
+ spi_print_msg(message);
printk("\n");
#endif
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 804125e35fc3..a28940156703 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -33,7 +33,6 @@
#include <asm/dma.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/ecard.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 81e266be26d0..e6c9491dc5c0 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -13,7 +13,6 @@
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/system.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 3a7a46b0dc41..583d2d8c8335 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -31,7 +31,6 @@
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include "../scsi.h"
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 4d1e8f52c924..3ffec7efc9d5 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -35,7 +35,6 @@
#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/pgtable.h>
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 3333d7b39139..3113bdcedb13 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -22,7 +22,6 @@
#include <asm/dma.h>
#include <asm/ecard.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include "../scsi.h"
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 333d69dd84ef..fc3ca051ceed 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -37,6 +37,49 @@
*
* Hardware documentation available at http://developer.intel.com/
*
+ * Documentation
+ * Publically available from Intel web site. Errata documentation
+ * is also publically available. As an aide to anyone hacking on this
+ * driver the list of errata that are relevant is below.going back to
+ * PIIX4. Older device documentation is now a bit tricky to find.
+ *
+ * The chipsets all follow very much the same design. The orginal Triton
+ * series chipsets do _not_ support independant device timings, but this
+ * is fixed in Triton II. With the odd mobile exception the chips then
+ * change little except in gaining more modes until SATA arrives. This
+ * driver supports only the chips with independant timing (that is those
+ * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
+ * for the early chip drivers.
+ *
+ * Errata of note:
+ *
+ * Unfixable
+ * PIIX4 errata #9 - Only on ultra obscure hw
+ * ICH3 errata #13 - Not observed to affect real hw
+ * by Intel
+ *
+ * Things we must deal with
+ * PIIX4 errata #10 - BM IDE hang with non UDMA
+ * (must stop/start dma to recover)
+ * 440MX errata #15 - As PIIX4 errata #10
+ * PIIX4 errata #15 - Must not read control registers
+ * during a PIO transfer
+ * 440MX errata #13 - As PIIX4 errata #15
+ * ICH2 errata #21 - DMA mode 0 doesn't work right
+ * ICH0/1 errata #55 - As ICH2 errata #21
+ * ICH2 spec c #9 - Extra operations needed to handle
+ * drive hotswap [NOT YET SUPPORTED]
+ * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary
+ * and must be dword aligned
+ * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3
+ *
+ * Should have been BIOS fixed:
+ * 450NX: errata #19 - DMA hangs on old 450NX
+ * 450NX: errata #20 - DMA hangs on old 450NX
+ * 450NX: errata #25 - Corruption with DMA on old 450NX
+ * ICH3 errata #15 - IDE deadlock under high load
+ * (BIOS must set dev 31 fn 0 bit 23)
+ * ICH3 errata #18 - Don't use native mode
*/
#include <linux/kernel.h>
@@ -78,9 +121,7 @@ enum {
ich5_sata = 1,
piix4_pata = 2,
ich6_sata = 3,
- ich6_sata_rm = 4,
- ich7_sata = 5,
- esb2_sata = 6,
+ ich6_sata_ahci = 4,
PIIX_AHCI_DEVICE = 6,
};
@@ -111,11 +152,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
- { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
- { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
- { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
- { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_sata },
- { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_sata },
+ { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
+ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
{ } /* terminate list */
};
@@ -125,6 +169,8 @@ static struct pci_driver piix_pci_driver = {
.id_table = piix_pci_tbl,
.probe = piix_init_one,
.remove = ata_pci_remove_one,
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
};
static struct scsi_host_template piix_sht = {
@@ -144,7 +190,8 @@ static struct scsi_host_template piix_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
+ .resume = ata_scsi_device_resume,
+ .suspend = ata_scsi_device_suspend,
};
static const struct ata_port_operations piix_pata_ops = {
@@ -258,31 +305,7 @@ static struct ata_port_info piix_port_info[] = {
.port_ops = &piix_sata_ops,
},
- /* ich6_sata_rm */
- {
- .sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
- PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
- ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
- .port_ops = &piix_sata_ops,
- },
-
- /* ich7_sata */
- {
- .sht = &piix_sht,
- .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
- PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
- ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
- .pio_mask = 0x1f, /* pio0-4 */
- .mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
- .port_ops = &piix_sata_ops,
- },
-
- /* esb2_sata */
+ /* ich6_sata_ahci */
{
.sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
@@ -603,6 +626,40 @@ static int piix_disable_ahci(struct pci_dev *pdev)
}
/**
+ * piix_check_450nx_errata - Check for problem 450NX setup
+ *
+ * Check for the present of 450NX errata #19 and errata #25. If
+ * they are found return an error code so we can turn off DMA
+ */
+
+static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+{
+ struct pci_dev *pdev = NULL;
+ u16 cfg;
+ u8 rev;
+ int no_piix_dma = 0;
+
+ while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
+ {
+ /* Look for 450NX PXB. Check for problem configurations
+ A PCI quirk checks bit 6 already */
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ pci_read_config_word(pdev, 0x41, &cfg);
+ /* Only on the original revision: IDE DMA can hang */
+ if(rev == 0x00)
+ no_piix_dma = 1;
+ /* On all revisions below 5 PXB bus lock must be disabled for IDE */
+ else if(cfg & (1<<14) && rev < 5)
+ no_piix_dma = 2;
+ }
+ if(no_piix_dma)
+ dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
+ if(no_piix_dma == 2)
+ dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
+ return no_piix_dma;
+}
+
+/**
* piix_init_one - Register PIIX ATA PCI device with kernel services
* @pdev: PCI device to register
* @ent: Entry in piix_pci_tbl matching with @pdev
@@ -676,7 +733,15 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
"combined mode detected (p=%u, s=%u)\n",
pata_chan, sata_chan);
}
-
+ if (piix_check_450nx_errata(pdev)) {
+ /* This writes into the master table but it does not
+ really matter for this errata as we will apply it to
+ all the PIIX devices on the board */
+ port_info[0]->mwdma_mask = 0;
+ port_info[0]->udma_mask = 0;
+ port_info[1]->mwdma_mask = 0;
+ port_info[1]->udma_mask = 0;
+ }
return ata_pci_init_one(pdev, port_info, 2);
}
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 2ae31ceb32a8..57295bcea3e7 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -74,6 +74,7 @@
* the high level code.
*/
#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
#if (NDEBUG & NDEBUG_LISTS)
#define LIST(x,y) \
@@ -2355,7 +2356,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
* 3..length+1 arguments
*
* Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.
+ * byte, since spi_print_msg() wants the whole thing.
*/
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
@@ -2408,7 +2409,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
default:
if (!tmp) {
printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
- scsi_print_msg (extended_msg);
+ spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
printk(KERN_DEBUG "scsi%d: rejecting unknown "
@@ -2541,7 +2542,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
if (!(msg[0] & 0x80)) {
printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
- scsi_print_msg(msg);
+ spi_print_msg(msg);
do_abort(instance);
return;
}
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
index 763e409a1ff3..3867ac2de4c2 100644
--- a/drivers/scsi/blz1230.c
+++ b/drivers/scsi/blz1230.c
@@ -224,7 +224,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void dma_dump_state(struct NCR_ESP *esp)
{
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -298,7 +298,7 @@ static int dma_irq_p(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
index d72d05fffdfa..4ebe69e32756 100644
--- a/drivers/scsi/blz2060.c
+++ b/drivers/scsi/blz2060.c
@@ -190,7 +190,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static void dma_dump_state(struct NCR_ESP *esp)
{
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -251,7 +251,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index ccbbae2bf478..c3f27285db1b 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -20,9 +20,9 @@
#include <linux/interrupt.h>
#include <linux/blkdev.h>
#include <linux/completion.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
#include <linux/chio.h> /* here are all the ioctls */
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -75,7 +75,7 @@ static int vendor_counts[CH_TYPES-4];
module_param_array(vendor_firsts, int, NULL, 0444);
module_param_array(vendor_counts, int, NULL, 0444);
-static char *vendor_labels[CH_TYPES-4] = {
+static const char * vendor_labels[CH_TYPES-4] = {
"v0", "v1", "v2", "v3"
};
// module_param_string_array(vendor_labels, NULL, 0444);
@@ -112,7 +112,7 @@ typedef struct {
u_int counts[CH_TYPES];
u_int unit_attention;
u_int voltags;
- struct semaphore lock;
+ struct mutex lock;
} scsi_changer;
static LIST_HEAD(ch_devlist);
@@ -140,7 +140,7 @@ static struct file_operations changer_fops =
#endif
};
-static struct {
+static const struct {
unsigned char sense;
unsigned char asc;
unsigned char ascq;
@@ -566,7 +566,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
u_char data[16];
unsigned int i;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
for (i = 0; i < ch->counts[type]; i++) {
if (0 != ch_read_element_status
(ch, ch->firsts[type]+i,data)) {
@@ -583,7 +583,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest)
if (0 != retval)
break;
}
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -688,11 +688,11 @@ static int ch_ioctl(struct inode * inode, struct file * file,
dprintk("CHIOPOSITION: invalid parameter\n");
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_position(ch,0,
ch->firsts[pos.cp_type] + pos.cp_unit,
pos.cp_flags & CP_INVERT);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -709,12 +709,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_move(ch,0,
ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
ch->firsts[mv.cm_totype] + mv.cm_tounit,
mv.cm_flags & CM_INVERT);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -732,14 +732,14 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_exchange
(ch,0,
ch->firsts[mv.ce_srctype] + mv.ce_srcunit,
ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -773,7 +773,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
if (!buffer)
return -ENOMEM;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
voltag_retry:
memset(cmd,0,sizeof(cmd));
@@ -824,7 +824,7 @@ static int ch_ioctl(struct inode * inode, struct file * file,
goto voltag_retry;
}
kfree(buffer);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
if (copy_to_user(argp, &cge, sizeof (cge)))
return -EFAULT;
@@ -833,9 +833,9 @@ static int ch_ioctl(struct inode * inode, struct file * file,
case CHIOINITELEM:
{
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_init_elem(ch);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -852,12 +852,12 @@ static int ch_ioctl(struct inode * inode, struct file * file,
return -EBADSLT;
}
elem = ch->firsts[csv.csv_type] + csv.csv_unit;
- down(&ch->lock);
+ mutex_lock(&ch->lock);
retval = ch_set_voltag(ch, elem,
csv.csv_flags & CSV_AVOLTAG,
csv.csv_flags & CSV_CLEARTAG,
csv.csv_voltag);
- up(&ch->lock);
+ mutex_unlock(&ch->lock);
return retval;
}
@@ -930,7 +930,7 @@ static int ch_probe(struct device *dev)
memset(ch,0,sizeof(*ch));
ch->minor = ch_devcount;
sprintf(ch->name,"ch%d",ch->minor);
- init_MUTEX(&ch->lock);
+ mutex_init(&ch->lock);
ch->device = sd;
ch_readconfig(ch);
if (init)
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 09bc81557b6e..30a335349cee 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1065,7 +1065,7 @@ struct error_info2 {
const char * fmt;
};
-static struct error_info2 additional2[] =
+static const struct error_info2 additional2[] =
{
{0x40,0x00,0x7f,"Ram failure (%x)"},
{0x40,0x80,0xff,"Diagnostic failure on component (%x)"},
@@ -1077,7 +1077,7 @@ static struct error_info2 additional2[] =
};
/* description of the sense key values */
-static const char *snstext[] = {
+static const char * const snstext[] = {
"No Sense", /* 0: There is no sense information */
"Recovered Error", /* 1: The last command completed successfully
but used error correction */
@@ -1278,114 +1278,6 @@ void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
}
EXPORT_SYMBOL(scsi_print_req_sense);
-#ifdef CONFIG_SCSI_CONSTANTS
-static const char *one_byte_msgs[] = {
-/* 0x00 */ "Command Complete", NULL, "Save Pointers",
-/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error",
-/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
-/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
-/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue",
-/* 0x0f */ "Initiate Recovery", "Release Recovery"
-};
-#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs) / sizeof (const char *))
-
-static const char *two_byte_msgs[] = {
-/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag"
-/* 0x23 */ "Ignore Wide Residue"
-};
-#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs) / sizeof (const char *))
-
-static const char *extended_msgs[] = {
-/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
-/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request"
-};
-#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs) / sizeof (const char *))
-
-
-int scsi_print_msg (const unsigned char *msg)
-{
- int len = 0, i;
- if (msg[0] == EXTENDED_MESSAGE) {
- len = 3 + msg[1];
- if (msg[2] < NO_EXTENDED_MSGS)
- printk ("%s ", extended_msgs[msg[2]]);
- else
- printk ("Extended Message, reserved code (0x%02x) ",
- (int) msg[2]);
- switch (msg[2]) {
- case EXTENDED_MODIFY_DATA_POINTER:
- printk("pointer = %d", (int) (msg[3] << 24) |
- (msg[4] << 16) | (msg[5] << 8) | msg[6]);
- break;
- case EXTENDED_SDTR:
- printk("period = %d ns, offset = %d",
- (int) msg[3] * 4, (int) msg[4]);
- break;
- case EXTENDED_WDTR:
- printk("width = 2^%d bytes", msg[3]);
- break;
- default:
- for (i = 2; i < len; ++i)
- printk("%02x ", msg[i]);
- }
- /* Identify */
- } else if (msg[0] & 0x80) {
- printk("Identify disconnect %sallowed %s %d ",
- (msg[0] & 0x40) ? "" : "not ",
- (msg[0] & 0x20) ? "target routine" : "lun",
- msg[0] & 0x7);
- len = 1;
- /* Normal One byte */
- } else if (msg[0] < 0x1f) {
- if (msg[0] < NO_ONE_BYTE_MSGS)
- printk(one_byte_msgs[msg[0]]);
- else
- printk("reserved (%02x) ", msg[0]);
- len = 1;
- /* Two byte */
- } else if (msg[0] <= 0x2f) {
- if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS)
- printk("%s %02x ", two_byte_msgs[msg[0] - 0x20],
- msg[1]);
- else
- printk("reserved two byte (%02x %02x) ",
- msg[0], msg[1]);
- len = 2;
- } else
- printk("reserved");
- return len;
-}
-EXPORT_SYMBOL(scsi_print_msg);
-
-#else /* ifndef CONFIG_SCSI_CONSTANTS */
-
-int scsi_print_msg (const unsigned char *msg)
-{
- int len = 0, i;
-
- if (msg[0] == EXTENDED_MESSAGE) {
- len = 3 + msg[1];
- for (i = 0; i < len; ++i)
- printk("%02x ", msg[i]);
- /* Identify */
- } else if (msg[0] & 0x80) {
- printk("%02x ", msg[0]);
- len = 1;
- /* Normal One byte */
- } else if (msg[0] < 0x1f) {
- printk("%02x ", msg[0]);
- len = 1;
- /* Two byte */
- } else if (msg[0] <= 0x2f) {
- printk("%02x %02x", msg[0], msg[1]);
- len = 2;
- } else
- printk("%02x ", msg[0]);
- return len;
-}
-EXPORT_SYMBOL(scsi_print_msg);
-#endif /* ! CONFIG_SCSI_CONSTANTS */
-
void scsi_print_command(struct scsi_cmnd *cmd)
{
/* Assume appended output (i.e. not at start of line) */
@@ -1397,7 +1289,7 @@ EXPORT_SYMBOL(scsi_print_command);
#ifdef CONFIG_SCSI_CONSTANTS
-static const char * hostbyte_table[]={
+static const char * const hostbyte_table[]={
"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
"DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
@@ -1422,12 +1314,12 @@ void scsi_print_hostbyte(int scsiresult)
#ifdef CONFIG_SCSI_CONSTANTS
-static const char * driverbyte_table[]={
+static const char * const driverbyte_table[]={
"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", "DRIVER_ERROR",
"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
#define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *))
-static const char * driversuggest_table[]={"SUGGEST_OK",
+static const char * const driversuggest_table[]={"SUGGEST_OK",
"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
#define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *))
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
index f9b940e56430..a4a4fac5c0a1 100644
--- a/drivers/scsi/cyberstorm.c
+++ b/drivers/scsi/cyberstorm.c
@@ -223,7 +223,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct cyber_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -322,7 +322,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
index a3caabfd7557..3a803d73bc5f 100644
--- a/drivers/scsi/cyberstormII.c
+++ b/drivers/scsi/cyberstormII.c
@@ -200,7 +200,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct cyberII_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -259,7 +259,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 6252b9ddc01e..6e6b293dcb28 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver");
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/ioport.h>
+#include <linux/mutex.h>
#include <asm/processor.h> /* for boot_cpu_data */
#include <asm/pgtable.h>
@@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = {
*============================================================================
*/
-static DECLARE_MUTEX(adpt_configuration_lock);
+static DEFINE_MUTEX(adpt_configuration_lock);
static struct i2o_sys_tbl *sys_tbl = NULL;
static int sys_tbl_ind = 0;
@@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Host *host, char *buffer, char **start, of
*/
// Find HBA (host bus adapter) we are looking for
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->host == host) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if (pHba == NULL) {
return 0;
}
@@ -898,6 +899,12 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
if(pci_enable_device(pDev)) {
return -EINVAL;
}
+
+ if (pci_request_regions(pDev, "dpt_i2o")) {
+ PERROR("dpti: adpt_config_hba: pci request region failed\n");
+ return -EINVAL;
+ }
+
pci_set_master(pDev);
if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) &&
pci_set_dma_mask(pDev, 0xffffffffULL))
@@ -923,10 +930,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
raptorFlag = TRUE;
}
- if (pci_request_regions(pDev, "dpt_i2o")) {
- PERROR("dpti: adpt_config_hba: pci request region failed\n");
- return -EINVAL;
- }
base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size);
if (!base_addr_virt) {
pci_release_regions(pDev);
@@ -958,7 +961,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
}
memset(pHba, 0, sizeof(adpt_hba));
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
if(hba_chain != NULL){
for(p = hba_chain; p->next; p = p->next);
@@ -971,7 +974,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
sprintf(pHba->name, "dpti%d", hba_count);
hba_count++;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
pHba->pDev = pDev;
pHba->base_addr_phys = base_addr0_phys;
@@ -1027,7 +1030,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
struct adpt_device* pNext;
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
// scsi_unregister calls our adpt_release which
// does a quiese
if(pHba->host){
@@ -1046,7 +1049,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
}
hba_count--;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
iounmap(pHba->base_addr_virt);
pci_release_regions(pHba->pDev);
@@ -1549,7 +1552,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
{
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
d->controller=pHba;
d->owner=NULL;
d->next=pHba->devices;
@@ -1560,7 +1563,7 @@ static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d)
pHba->devices=d;
*d->dev_name = 0;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return 0;
}
@@ -1575,24 +1578,24 @@ static int adpt_open(struct inode *inode, struct file *file)
if (minor >= hba_count) {
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
if (pHba == NULL) {
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return -ENXIO;
}
// if(pHba->in_use){
- // up(&adpt_configuration_lock);
+ // mutex_unlock(&adpt_configuration_lock);
// return -EBUSY;
// }
pHba->in_use = 1;
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
return 0;
}
@@ -1606,13 +1609,13 @@ static int adpt_close(struct inode *inode, struct file *file)
if (minor >= hba_count) {
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if (pHba == NULL) {
return -ENXIO;
}
@@ -1910,13 +1913,13 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
if (minor >= DPTI_MAX_HBA){
return -ENXIO;
}
- down(&adpt_configuration_lock);
+ mutex_lock(&adpt_configuration_lock);
for (pHba = hba_chain; pHba; pHba = pHba->next) {
if (pHba->unit == minor) {
break; /* found adapter */
}
}
- up(&adpt_configuration_lock);
+ mutex_unlock(&adpt_configuration_lock);
if(pHba == NULL){
return -ENXIO;
}
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
index ccee68b52f7e..8ae9c406a83b 100644
--- a/drivers/scsi/fastlane.c
+++ b/drivers/scsi/fastlane.c
@@ -268,7 +268,7 @@ static void dma_dump_state(struct NCR_ESP *esp)
esp->esp_id, ((struct fastlane_dma_registers *)
(esp->dregs))->cond_reg));
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
- custom.intreqr, custom.intenar));
+ amiga_custom.intreqr, amiga_custom.intenar));
}
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
@@ -368,7 +368,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index a6deb016584c..bd3ffdf6c800 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -328,7 +328,7 @@
* hdr_channel:x x - number of virtual bus for host drives
* shared_access:Y disable driver reserve/release protocol to
* access a shared resource from several nodes,
- * appropiate controller firmware required
+ * appropriate controller firmware required
* shared_access:N enable driver reserve/release protocol
* probe_eisa_isa:Y scan for EISA/ISA controllers
* probe_eisa_isa:N do not scan for EISA/ISA controllers
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5b9c2c5a7f0e..588107923499 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -156,16 +156,16 @@ EXPORT_SYMBOL(scsi_host_set_state);
void scsi_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_CANCEL))
if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
spin_unlock_irqrestore(shost->host_lock, flags);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
return;
}
spin_unlock_irqrestore(shost->host_lock, flags);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
scsi_forget_host(shost);
scsi_proc_host_rm(shost);
@@ -320,7 +320,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
INIT_LIST_HEAD(&shost->starved_list);
init_waitqueue_head(&shost->host_wait);
- init_MUTEX(&shost->scan_mutex);
+ mutex_init(&shost->scan_mutex);
shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */
shost->dma_channel = 0xff;
@@ -347,17 +347,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->cmd_per_lun = sht->cmd_per_lun;
shost->unchecked_isa_dma = sht->unchecked_isa_dma;
shost->use_clustering = sht->use_clustering;
- shost->ordered_flush = sht->ordered_flush;
shost->ordered_tag = sht->ordered_tag;
- /*
- * hosts/devices that do queueing must support ordered tags
- */
- if (shost->can_queue > 1 && shost->ordered_flush) {
- printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
- shost->ordered_flush = 0;
- }
-
if (sht->max_host_blocked)
shost->max_host_blocked = sht->max_host_blocked;
else
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 4cb1f3ed9100..3c688ef54660 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -1046,7 +1046,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
/* kill current request */
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
if (req->flags & REQ_SENSE)
kfree(scsi->pc->buffer);
kfree(scsi->pc);
@@ -1056,7 +1056,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
/* now nuke the drive queue */
while ((req = elv_next_request(drive->queue))) {
blkdev_dequeue_request(req);
- end_that_request_last(req);
+ end_that_request_last(req, 0);
}
HWGROUP(drive)->rq = NULL;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fa2cb3582cfa..27acf78cf8d8 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2132,7 +2132,7 @@ restart:
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE, NULL);
+ kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
LEAVE;
}
@@ -5887,7 +5887,12 @@ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
dev_dbg(&ioa_cfg->pdev->dev, "ioa_cfg adx: 0x%p\n", ioa_cfg);
- _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa, IPR_SHUTDOWN_NONE);
+ if (ioa_cfg->needs_hard_reset) {
+ ioa_cfg->needs_hard_reset = 0;
+ ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
+ } else
+ _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_enable_ioa,
+ IPR_SHUTDOWN_NONE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
@@ -6264,6 +6269,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
unsigned long ipr_regs_pci;
void __iomem *ipr_regs;
u32 rc = PCIBIOS_SUCCESSFUL;
+ volatile u32 mask, uproc;
ENTER;
@@ -6356,6 +6362,15 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto cleanup_nomem;
}
+ /*
+ * If HRRQ updated interrupt is not masked, or reset alert is set,
+ * the card is in an unknown state and needs a hard reset
+ */
+ mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
+ uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
+ if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
+ ioa_cfg->needs_hard_reset = 1;
+
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 6bec673c925c..b639332131f1 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.1.0"
-#define IPR_DRIVER_DATE "(October 31, 2005)"
+#define IPR_DRIVER_VERSION "2.1.1"
+#define IPR_DRIVER_DATE "(November 15, 2005)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
@@ -922,6 +922,7 @@ struct ipr_ioa_cfg {
u8 dump_taken:1;
u8 allow_cmds:1;
u8 allow_ml_add_del:1;
+ u8 needs_hard_reset:1;
enum ipr_cache_state cache_state;
u16 type; /* CCIN of the card */
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 3882d48a42bf..e5e1ca44e1ee 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1319,6 +1319,9 @@ ips_slave_configure(struct scsi_device * SDptr)
min = ha->max_cmds - 1;
scsi_adjust_queue_depth(SDptr, MSG_ORDERED_TAG, min);
}
+
+ SDptr->skip_ms_page_8 = 1;
+ SDptr->skip_ms_page_3f = 1;
return 0;
}
#endif
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 3d8009f55342..780bfcc67096 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/kfifo.h>
#include <linux/scatterlist.h>
+#include <linux/mutex.h>
#include <net/tcp.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -49,7 +50,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
"Alex Aizman <itn780@yahoo.com>");
MODULE_DESCRIPTION("iSCSI/TCP data-path");
MODULE_LICENSE("GPL");
-MODULE_VERSION("0:4.409");
+MODULE_VERSION("0:4.445");
/* #define DEBUG_TCP */
/* #define DEBUG_SCSI */
#define DEBUG_ASSERT
@@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
{
sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
ibuf->sent = 0;
+ ibuf->use_sendmsg = 0;
}
static inline void
iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
{
- ibuf->sg.page = (void*)vbuf;
- ibuf->sg.offset = (unsigned int)-1;
+ ibuf->sg.page = virt_to_page(vbuf);
+ ibuf->sg.offset = offset_in_page(vbuf);
ibuf->sg.length = size;
ibuf->sent = 0;
-}
-
-static inline void*
-iscsi_buf_iov_base(struct iscsi_buf *ibuf)
-{
- return (char*)ibuf->sg.page + ibuf->sent;
+ ibuf->use_sendmsg = 1;
}
static inline void
iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg)
{
+ ibuf->sg.page = sg->page;
+ ibuf->sg.offset = sg->offset;
+ ibuf->sg.length = sg->length;
/*
* Fastpath: sg element fits into single page
*/
- if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) {
- ibuf->sg.page = sg->page;
- ibuf->sg.offset = sg->offset;
- ibuf->sg.length = sg->length;
- } else
- iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length);
+ if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page))
+ ibuf->use_sendmsg = 0;
+ else
+ ibuf->use_sendmsg = 1;
ibuf->sent = 0;
}
@@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
struct scsi_cmnd *sc = ctask->sc;
conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
- if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+ if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
int res_count = be32_to_cpu(rhdr->residual_count);
if (res_count > 0 &&
@@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
} else
sc->result = (DID_BAD_TARGET << 16) |
rhdr->cmd_status;
- } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
- else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) {
+ } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) {
sc->resid = be32_to_cpu(rhdr->residual_count);
sc->result = (DID_OK << 16) | rhdr->cmd_status;
} else
@@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
- schedule_work(&conn->xmitwork);
+ scsi_queue_work(session->host, &conn->xmitwork);
conn->r2t_pdus_cnt++;
spin_unlock(&session->lock);
@@ -581,10 +577,16 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
conn->in.ahslen);
+ if (cdgst != rdgst) {
+ printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
+ "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
+ cdgst);
+ return ISCSI_ERR_HDR_DGST;
+ }
}
/* save opcode for later */
- conn->in.opcode = hdr->opcode;
+ conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
/* verify itt (itt encoding: age+cid+itt) */
if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
@@ -610,13 +612,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
conn->in.ahslen, conn->in.datalen);
if (conn->in.itt < session->cmds_max) {
- if (conn->hdrdgst_en && cdgst != rdgst) {
- printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
- "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
- cdgst);
- return ISCSI_ERR_HDR_DGST;
- }
-
ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
if (!ctask->sc) {
@@ -642,9 +637,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
switch(conn->in.opcode) {
case ISCSI_OP_SCSI_CMD_RSP:
BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
- if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE)
- rc = iscsi_cmd_rsp(conn, ctask);
- else if (!conn->in.datalen)
+ if (!conn->in.datalen)
rc = iscsi_cmd_rsp(conn, ctask);
else
/*
@@ -666,8 +659,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
break;
case ISCSI_OP_R2T:
BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
- if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE &&
- ctask->sc->sc_data_direction == DMA_TO_DEVICE)
+ if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
rc = iscsi_r2t_rsp(conn, ctask);
else
rc = ISCSI_ERR_PROTO;
@@ -690,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
switch(conn->in.opcode) {
case ISCSI_OP_LOGIN_RSP:
case ISCSI_OP_TEXT_RSP:
- case ISCSI_OP_LOGOUT_RSP:
+ case ISCSI_OP_LOGOUT_RSP:
rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (rc)
@@ -731,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
}
spin_unlock(&session->lock);
break;
- case ISCSI_OP_NOOP_IN:
+ case ISCSI_OP_NOOP_IN:
if (hdr->ttt != ISCSI_RESERVED_TAG) {
rc = ISCSI_ERR_PROTO;
break;
}
- rc = iscsi_check_assign_cmdsn(session,
+ rc = iscsi_check_assign_cmdsn(session,
(struct iscsi_nopin*)hdr);
if (rc)
break;
@@ -771,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
rc = iscsi_recv_pdu(iscsi_handle(conn),
hdr, NULL, 0);
- } else
+ } else
rc = ISCSI_ERR_PROTO;
break;
case ISCSI_OP_REJECT:
@@ -906,11 +898,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
crypto_digest_update(conn->data_rx_tfm, &temp, 1);
}
+static void
+iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
+{
+ struct scatterlist tmp;
+
+ sg_init_one(&tmp, buf, len);
+ crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
+}
+
static int iscsi_scsi_data_in(struct iscsi_conn *conn)
{
struct iscsi_cmd_task *ctask = conn->in.ctask;
struct scsi_cmnd *sc = ctask->sc;
- struct scatterlist tmp, *sg;
+ struct scatterlist *sg;
int i, offset, rc = 0;
BUG_ON((void*)ctask != sc->SCp.ptr);
@@ -924,10 +925,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
sc->request_bufflen, ctask->data_offset);
if (rc == -EAGAIN)
return rc;
- if (conn->datadgst_en) {
- sg_init_one(&tmp, sc->request_buffer, i);
- crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
- }
+ if (conn->datadgst_en)
+ iscsi_recv_digest_update(conn, sc->request_buffer, i);
rc = 0;
goto done;
}
@@ -1021,6 +1020,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
conn->in.hdr = &conn->hdr;
conn->senselen = (conn->data[0] << 8) | conn->data[1];
rc = iscsi_cmd_rsp(conn, conn->in.ctask);
+ if (!rc && conn->datadgst_en)
+ iscsi_recv_digest_update(conn, conn->data,
+ conn->in.datalen);
}
break;
case ISCSI_OP_TEXT_RSP:
@@ -1045,6 +1047,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
conn->data, conn->in.datalen);
+ if (!rc && conn->datadgst_en &&
+ conn->in.opcode != ISCSI_OP_LOGIN_RSP)
+ iscsi_recv_digest_update(conn, conn->data,
+ conn->in.datalen);
+
if (mtask && conn->login_mtask != mtask) {
spin_lock(&session->lock);
__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
@@ -1053,6 +1060,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
}
}
break;
+ case ISCSI_OP_ASYNC_EVENT:
+ case ISCSI_OP_REJECT:
default:
BUG_ON(1);
}
@@ -1114,8 +1123,7 @@ more:
*/
rc = iscsi_hdr_recv(conn);
if (!rc && conn->in.datalen) {
- if (conn->datadgst_en &&
- conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
+ if (conn->datadgst_en) {
BUG_ON(!conn->data_rx_tfm);
crypto_digest_init(conn->data_rx_tfm);
}
@@ -1127,26 +1135,24 @@ more:
}
if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+ uint32_t recv_digest;
debug_tcp("extra data_recv offset %d copy %d\n",
conn->in.offset, conn->in.copy);
- if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
- uint32_t recv_digest;
- skb_copy_bits(conn->in.skb, conn->in.offset,
- &recv_digest, 4);
- conn->in.offset += 4;
- conn->in.copy -= 4;
- if (recv_digest != conn->in.datadgst) {
- debug_tcp("iscsi_tcp: data digest error!"
- "0x%x != 0x%x\n", recv_digest,
- conn->in.datadgst);
- iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
- return 0;
- } else {
- debug_tcp("iscsi_tcp: data digest match!"
- "0x%x == 0x%x\n", recv_digest,
- conn->in.datadgst);
- conn->in_progress = IN_PROGRESS_WAIT_HEADER;
- }
+ skb_copy_bits(conn->in.skb, conn->in.offset,
+ &recv_digest, 4);
+ conn->in.offset += 4;
+ conn->in.copy -= 4;
+ if (recv_digest != conn->in.datadgst) {
+ debug_tcp("iscsi_tcp: data digest error!"
+ "0x%x != 0x%x\n", recv_digest,
+ conn->in.datadgst);
+ iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
+ return 0;
+ } else {
+ debug_tcp("iscsi_tcp: data digest match!"
+ "0x%x == 0x%x\n", recv_digest,
+ conn->in.datadgst);
+ conn->in_progress = IN_PROGRESS_WAIT_HEADER;
}
}
@@ -1167,8 +1173,7 @@ more:
}
conn->in.copy -= conn->in.padding;
conn->in.offset += conn->in.padding;
- if (conn->datadgst_en &&
- conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
+ if (conn->datadgst_en) {
if (conn->in.padding) {
debug_tcp("padding -> %d\n", conn->in.padding);
memset(pad, 0, conn->in.padding);
@@ -1237,8 +1242,9 @@ iscsi_tcp_state_change(struct sock *sk)
conn = (struct iscsi_conn*)sk->sk_user_data;
session = conn->session;
- if (sk->sk_state == TCP_CLOSE_WAIT ||
- sk->sk_state == TCP_CLOSE) {
+ if ((sk->sk_state == TCP_CLOSE_WAIT ||
+ sk->sk_state == TCP_CLOSE) &&
+ !atomic_read(&sk->sk_rmem_alloc)) {
debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
}
@@ -1261,7 +1267,7 @@ iscsi_write_space(struct sock *sk)
conn->old_write_space(sk);
debug_tcp("iscsi_write_space: cid %d\n", conn->id);
clear_bit(SUSPEND_BIT, &conn->suspend_tx);
- schedule_work(&conn->xmitwork);
+ scsi_queue_work(conn->session->host, &conn->xmitwork);
}
static void
@@ -1302,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
* @buf: buffer to write from
* @size: actual size to write
* @flags: socket's flags
- *
- * Notes:
- * depending on buffer will use tcp_sendpage() or tcp_sendmsg().
- * buf->sg.offset == -1 tells us that buffer is non S/G and forces
- * to use tcp_sendmsg().
*/
static inline int
-iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
+iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
{
- int res;
-
- if ((int)buf->sg.offset >= 0) {
- int offset = buf->sg.offset + buf->sent;
-
- /* tcp_sendpage */
- res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags);
- } else {
- struct msghdr msg;
-
- buf->iov.iov_base = iscsi_buf_iov_base(buf);
- buf->iov.iov_len = size;
-
- memset(&msg, 0, sizeof(struct msghdr));
-
- /* tcp_sendmsg */
- res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size);
- }
+ struct socket *sk = conn->sock;
+ int offset = buf->sg.offset + buf->sent;
- return res;
+ /*
+ * if we got use_sg=0 or are sending something we kmallocd
+ * then we did not have to do kmap (kmap returns page_address)
+ *
+ * if we got use_sg > 0, but had to drop down, we do not
+ * set clustering so this should only happen for that
+ * slab case.
+ */
+ if (buf->use_sendmsg)
+ return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+ else
+ return conn->sendpage(sk, buf->sg.page, offset, size, flags);
}
/**
@@ -1345,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags)
static inline int
iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
{
- struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */
int res, size;
@@ -1354,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
if (buf->sent + size != buf->sg.length || datalen)
flags |= MSG_MORE;
- res = iscsi_send(sk, buf, size, flags);
+ res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
if (res >= 0) {
conn->txdata_octets += res;
@@ -1385,7 +1380,6 @@ static inline int
iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
int *count, int *sent)
{
- struct socket *sk = conn->sock;
int flags = 0; /* MSG_DONTWAIT; */
int res, size;
@@ -1396,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
if (buf->sent + size != buf->sg.length || *count != size)
flags |= MSG_MORE;
- res = iscsi_send(sk, buf, size, flags);
+ res = iscsi_send(conn, buf, size, flags);
debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
size, buf->sent, *count, *sent, res);
if (res >= 0) {
@@ -1424,20 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
ctask->digest_count = 4;
}
-static inline void
-iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf)
-{
- struct scatterlist sg;
-
- if (buf->sg.offset != -1)
- crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1);
- else {
- sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length);
- crypto_digest_update(conn->data_tx_tfm, &sg, 1);
- }
-}
-
-static inline int
+static int
iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
struct iscsi_buf *buf, uint32_t *digest, int final)
{
@@ -1670,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
zero_data(ctask->hdr.dlength);
}
- iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
+ iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
sizeof(struct iscsi_hdr));
conn->scsicmd_pdus_cnt++;
}
@@ -1736,7 +1717,7 @@ static inline int
handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
ctask->xmstate &= ~XMSTATE_R_HDR;
- if (conn->hdrdgst_en)
+ if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
BUG_ON(ctask->xmstate != XMSTATE_IDLE);
@@ -1750,7 +1731,7 @@ static inline int
handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
ctask->xmstate &= ~XMSTATE_W_HDR;
- if (conn->hdrdgst_en)
+ if (conn->hdrdgst_en)
iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
ctask->xmstate |= XMSTATE_W_HDR;
@@ -1799,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
return -EAGAIN;
}
if (conn->datadgst_en)
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm,
+ &ctask->sendbuf.sg, 1);
if (!ctask->imm_count)
break;
@@ -1884,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
* so pass it
*/
if (conn->datadgst_en && ctask->sent - start > 0)
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm,
+ &ctask->sendbuf.sg, 1);
if (!ctask->data_count)
break;
@@ -1962,7 +1945,7 @@ solicit_again:
BUG_ON(r2t->data_count < 0);
if (conn->datadgst_en)
- iscsi_buf_data_digest_update(conn, &r2t->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
if (r2t->data_count) {
BUG_ON(ctask->sc->use_sg == 0);
@@ -2044,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
}
if (conn->datadgst_en) {
- iscsi_buf_data_digest_update(conn, &ctask->sendbuf);
+ crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
/* imm data? */
if (!dtask) {
if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
@@ -2138,7 +2121,7 @@ unsolicit_head_again:
solicit_head_again:
r2t = ctask->r2t;
if (conn->hdrdgst_en)
- iscsi_hdr_digest(conn, &r2t->headbuf,
+ iscsi_hdr_digest(conn, &r2t->headbuf,
(u8*)r2t->dtask->hdrext);
if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
ctask->xmstate &= ~XMSTATE_SOL_DATA;
@@ -2290,10 +2273,10 @@ iscsi_xmitworker(void *data)
/*
* serialize Xmit worker on a per-connection basis.
*/
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
if (iscsi_data_xmit(conn))
- schedule_work(&conn->xmitwork);
- up(&conn->xmitsema);
+ scsi_queue_work(conn->session->host, &conn->xmitwork);
+ mutex_unlock(&conn->xmitmutex);
}
#define FAILURE_BAD_HOST 1
@@ -2357,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
spin_unlock(&session->lock);
- if (!in_interrupt() && !down_trylock(&conn->xmitsema)) {
- spin_unlock_irq(host->host_lock);
- if (iscsi_data_xmit(conn))
- schedule_work(&conn->xmitwork);
- up(&conn->xmitsema);
- spin_lock_irq(host->host_lock);
- } else
- schedule_work(&conn->xmitwork);
-
+ scsi_queue_work(host, &conn->xmitwork);
return 0;
reject:
@@ -2389,6 +2364,15 @@ fault:
}
static int
+iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+{
+ if (depth > ISCSI_MAX_CMD_PER_LUN)
+ depth = ISCSI_MAX_CMD_PER_LUN;
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+ return sdev->queue_depth;
+}
+
+static int
iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
{
int i;
@@ -2443,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items)
kfree(items);
}
-static iscsi_connh_t
-iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
+static struct iscsi_cls_conn *
+iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx)
{
- struct iscsi_session *session = iscsi_ptr(sessionh);
- struct iscsi_conn *conn = NULL;
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+ struct iscsi_conn *conn;
+ struct iscsi_cls_conn *cls_conn;
- conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
- if (conn == NULL)
- goto conn_alloc_fail;
- memset(conn, 0, sizeof(struct iscsi_conn));
+ cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata),
+ conn_idx);
+ if (!cls_conn)
+ return NULL;
+ conn = cls_conn->dd_data;
+ memset(conn, 0, sizeof(struct iscsi_conn));
conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
conn->in_progress = IN_PROGRESS_WAIT_HEADER;
conn->id = conn_idx;
@@ -2512,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx)
goto max_recv_dlenght_alloc_fail;
init_timer(&conn->tmabort_timer);
- init_MUTEX(&conn->xmitsema);
+ mutex_init(&conn->xmitmutex);
init_waitqueue_head(&conn->ehwait);
- return iscsi_handle(conn);
+ return cls_conn;
max_recv_dlenght_alloc_fail:
spin_lock_bh(&session->lock);
@@ -2531,18 +2518,18 @@ immqueue_alloc_fail:
writequeue_alloc_fail:
kfifo_free(conn->xmitqueue);
xmitqueue_alloc_fail:
- kfree(conn);
-conn_alloc_fail:
- return iscsi_handle(NULL);
+ iscsi_destroy_conn(cls_conn);
+ return NULL;
}
static void
-iscsi_conn_destroy(iscsi_connh_t connh)
+iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
+ struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
+ unsigned long flags;
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
set_bit(SUSPEND_BIT, &conn->suspend_tx);
if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
struct sock *sk = conn->sock->sk;
@@ -2573,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh)
}
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
/*
* Block until all in-progress commands for this connection
* time out or fail.
*/
for (;;) {
- spin_lock_bh(&conn->lock);
+ spin_lock_irqsave(session->host->host_lock, flags);
if (!session->host->host_busy) { /* OK for ERL == 0 */
- spin_unlock_bh(&conn->lock);
+ spin_unlock_irqrestore(session->host->host_lock, flags);
break;
}
- spin_unlock_bh(&conn->lock);
+ spin_unlock_irqrestore(session->host->host_lock, flags);
msleep_interruptible(500);
printk("conn_destroy(): host_busy %d host_failed %d\n",
session->host->host_busy, session->host->host_failed);
@@ -2633,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh)
kfifo_free(conn->writequeue);
kfifo_free(conn->immqueue);
kfifo_free(conn->mgmtqueue);
- kfree(conn);
+
+ iscsi_destroy_conn(cls_conn);
}
static int
@@ -2694,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh,
*/
iscsi_conn_set_callbacks(conn);
+ conn->sendpage = conn->sock->ops->sendpage;
+
/*
* set receive state machine into initial state
*/
@@ -2777,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
set_bit(SUSPEND_BIT, &conn->suspend_rx);
write_unlock_bh(&sk->sk_callback_lock);
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
spin_lock_irqsave(session->host->host_lock, flags);
spin_lock(&session->lock);
@@ -2853,10 +2843,13 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
* in hdr_extract() and will be re-negotiated at
* set_param() time.
*/
- if (flag == STOP_CONN_RECOVER)
+ if (flag == STOP_CONN_RECOVER) {
conn->hdr_size = sizeof(struct iscsi_hdr);
+ conn->hdrdgst_en = 0;
+ conn->datadgst_en = 0;
+ }
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
}
static int
@@ -2941,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
else
__kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
- schedule_work(&conn->xmitwork);
-
+ scsi_queue_work(session->host, &conn->xmitwork);
return 0;
}
@@ -3007,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
* 1) connection-level failure;
* 2) recovery due protocol error;
*/
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
spin_lock_bh(&session->lock);
if (session->state != ISCSI_STATE_LOGGED_IN) {
if (session->state == ISCSI_STATE_TERMINATE) {
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto failed;
}
spin_unlock_bh(&session->lock);
@@ -3030,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
* 2) session was re-open during time out of ctask.
*/
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto success;
}
conn->tmabort_state = TMABORT_INITIAL;
@@ -3085,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
conn->tmabort_state == TMABORT_SUCCESS) {
conn->tmabort_state = TMABORT_INITIAL;
spin_unlock_bh(&session->lock);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
goto success;
}
conn->tmabort_state = TMABORT_INITIAL;
@@ -3094,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc)
spin_unlock_bh(&session->lock);
}
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
/*
@@ -3160,7 +3152,7 @@ failed:
exit:
del_timer_sync(&conn->tmabort_timer);
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
if (conn->sock) {
struct sock *sk = conn->sock->sk;
@@ -3168,7 +3160,7 @@ exit:
iscsi_ctask_cleanup(conn, ctask);
write_unlock_bh(&sk->sk_callback_lock);
}
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
return rc;
}
@@ -3247,28 +3239,35 @@ iscsi_r2tpool_free(struct iscsi_session *session)
static struct scsi_host_template iscsi_sht = {
.name = "iSCSI Initiator over TCP/IP, v."
ISCSI_VERSION_STR,
- .queuecommand = iscsi_queuecommand,
+ .queuecommand = iscsi_queuecommand,
+ .change_queue_depth = iscsi_change_queue_depth,
.can_queue = ISCSI_XMIT_CMDS_MAX - 1,
.sg_tablesize = ISCSI_SG_TABLESIZE,
- .cmd_per_lun = ISCSI_CMD_PER_LUN,
- .eh_abort_handler = iscsi_eh_abort,
- .eh_host_reset_handler = iscsi_eh_host_reset,
- .use_clustering = DISABLE_CLUSTERING,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+ .eh_abort_handler = iscsi_eh_abort,
+ .eh_host_reset_handler = iscsi_eh_host_reset,
+ .use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_tcp",
.this_id = -1,
};
-static iscsi_sessionh_t
-iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
+static struct iscsi_transport iscsi_tcp_transport;
+
+static struct Scsi_Host *
+iscsi_session_create(struct scsi_transport_template *scsit,
+ uint32_t initial_cmdsn)
{
- int cmd_i;
+ struct Scsi_Host *shost;
struct iscsi_session *session;
+ int cmd_i;
- session = iscsi_hostdata(host->hostdata);
- memset(session, 0, sizeof(struct iscsi_session));
+ shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
+ if (!shost)
+ return NULL;
- session->host = host;
- session->id = host->host_no;
+ session = iscsi_hostdata(shost->hostdata);
+ memset(session, 0, sizeof(struct iscsi_session));
+ session->host = shost;
session->state = ISCSI_STATE_LOGGED_IN;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = ISCSI_XMIT_CMDS_MAX;
@@ -3312,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host)
if (iscsi_r2tpool_alloc(session))
goto r2tpool_alloc_fail;
- return iscsi_handle(session);
+ return shost;
r2tpool_alloc_fail:
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
@@ -3322,15 +3321,15 @@ immdata_alloc_fail:
mgmtpool_alloc_fail:
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
cmdpool_alloc_fail:
- return iscsi_handle(NULL);
+ return NULL;
}
static void
-iscsi_session_destroy(iscsi_sessionh_t sessionh)
+iscsi_session_destroy(struct Scsi_Host *shost)
{
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
int cmd_i;
struct iscsi_data_task *dtask, *n;
- struct iscsi_session *session = iscsi_ptr(sessionh);
for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
@@ -3346,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh)
iscsi_r2tpool_free(session);
iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+
+ iscsi_transport_destroy_session(shost);
}
static int
@@ -3444,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
if (conn->data_rx_tfm)
crypto_free_tfm(conn->data_rx_tfm);
}
+ conn->sendpage = conn->datadgst_en ?
+ sock_no_sendpage : conn->sock->ops->sendpage;
break;
case ISCSI_PARAM_INITIAL_R2T_EN:
session->initial_r2t_en = value;
@@ -3492,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param,
}
static int
-iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
- uint32_t *value)
+iscsi_session_get_param(struct Scsi_Host *shost,
+ enum iscsi_param param, uint32_t *value)
{
- struct iscsi_conn *conn = iscsi_ptr(connh);
- struct iscsi_session *session = conn->session;
+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
switch(param) {
- case ISCSI_PARAM_MAX_RECV_DLENGTH:
- *value = conn->max_recv_dlength;
- break;
- case ISCSI_PARAM_MAX_XMIT_DLENGTH:
- *value = conn->max_xmit_dlength;
- break;
- case ISCSI_PARAM_HDRDGST_EN:
- *value = conn->hdrdgst_en;
- break;
- case ISCSI_PARAM_DATADGST_EN:
- *value = conn->datadgst_en;
- break;
case ISCSI_PARAM_INITIAL_R2T_EN:
*value = session->initial_r2t_en;
break;
@@ -3548,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param,
return 0;
}
+static int
+iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value)
+{
+ struct iscsi_conn *conn = data;
+
+ switch(param) {
+ case ISCSI_PARAM_MAX_RECV_DLENGTH:
+ *value = conn->max_recv_dlength;
+ break;
+ case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+ *value = conn->max_xmit_dlength;
+ break;
+ case ISCSI_PARAM_HDRDGST_EN:
+ *value = conn->hdrdgst_en;
+ break;
+ case ISCSI_PARAM_DATADGST_EN:
+ *value = conn->datadgst_en;
+ break;
+ default:
+ return ISCSI_ERR_PARAM_NOT_FOUND;
+ }
+
+ return 0;
+}
+
static void
iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats)
{
@@ -3578,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data,
struct iscsi_conn *conn = iscsi_ptr(connh);
int rc;
- down(&conn->xmitsema);
+ mutex_lock(&conn->xmitmutex);
rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
- up(&conn->xmitsema);
+ mutex_unlock(&conn->xmitmutex);
return rc;
}
@@ -3592,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = {
| CAP_DATADGST,
.host_template = &iscsi_sht,
.hostdata_size = sizeof(struct iscsi_session),
+ .conndata_size = sizeof(struct iscsi_conn),
.max_conn = 1,
.max_cmd_len = ISCSI_TCP_MAX_CMD_LEN,
.create_session = iscsi_session_create,
@@ -3600,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = {
.bind_conn = iscsi_conn_bind,
.destroy_conn = iscsi_conn_destroy,
.set_param = iscsi_conn_set_param,
- .get_param = iscsi_conn_get_param,
+ .get_conn_param = iscsi_conn_get_param,
+ .get_session_param = iscsi_session_get_param,
.start_conn = iscsi_conn_start,
.stop_conn = iscsi_conn_stop,
.send_pdu = iscsi_conn_send_pdu,
@@ -3610,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = {
static int __init
iscsi_tcp_init(void)
{
- int error;
-
if (iscsi_max_lun < 1) {
printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
return -EINVAL;
@@ -3624,11 +3639,10 @@ iscsi_tcp_init(void)
if (!taskcache)
return -ENOMEM;
- error = iscsi_register_transport(&iscsi_tcp_transport);
- if (error)
+ if (!iscsi_register_transport(&iscsi_tcp_transport))
kmem_cache_destroy(taskcache);
- return error;
+ return 0;
}
static void __exit
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index d23ae68fae0d..f95e61b76f70 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -71,7 +71,8 @@
#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */
#define ISCSI_MGMT_ITT_OFFSET 0xa00
#define ISCSI_SG_TABLESIZE SG_ALL
-#define ISCSI_CMD_PER_LUN 128
+#define ISCSI_DEF_CMD_PER_LUN 32
+#define ISCSI_MAX_CMD_PER_LUN 128
#define ISCSI_TCP_MAX_CMD_LEN 16
#define ITT_MASK (0xfff)
@@ -157,7 +158,7 @@ struct iscsi_conn {
struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */
struct kfifo *xmitqueue; /* data-path cmd queue */
struct work_struct xmitwork; /* per-conn. xmit workqueue */
- struct semaphore xmitsema; /* serializes connection xmit,
+ struct mutex xmitmutex; /* serializes connection xmit,
* access to kfifos: *
* xmitqueue, writequeue, *
* immqueue, mgmtqueue */
@@ -190,6 +191,8 @@ struct iscsi_conn {
uint32_t sendpage_failures_cnt;
uint32_t discontiguous_hdr_cnt;
uint32_t eh_abort_cnt;
+
+ ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
};
struct iscsi_session {
@@ -239,8 +242,8 @@ struct iscsi_session {
struct iscsi_buf {
struct scatterlist sg;
- struct kvec iov;
unsigned int sent;
+ char use_sendmsg;
};
struct iscsi_data_task {
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index d0a0fdbd0fc4..46c4cdbaee86 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
ATA_CMD_WRITE_MULTI,
ATA_CMD_READ_MULTI_EXT,
ATA_CMD_WRITE_MULTI_EXT,
+ 0,
+ 0,
+ 0,
+ ATA_CMD_WRITE_MULTI_FUA_EXT,
/* pio */
ATA_CMD_PIO_READ,
ATA_CMD_PIO_WRITE,
ATA_CMD_PIO_READ_EXT,
ATA_CMD_PIO_WRITE_EXT,
+ 0,
+ 0,
+ 0,
+ 0,
/* dma */
ATA_CMD_READ,
ATA_CMD_WRITE,
ATA_CMD_READ_EXT,
- ATA_CMD_WRITE_EXT
+ ATA_CMD_WRITE_EXT,
+ 0,
+ 0,
+ 0,
+ ATA_CMD_WRITE_FUA_EXT
};
/**
@@ -584,28 +596,39 @@ static const u8 ata_rw_cmds[] = {
* LOCKING:
* caller.
*/
-void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
{
struct ata_taskfile *tf = &qc->tf;
struct ata_device *dev = qc->dev;
+ u8 cmd;
- int index, lba48, write;
+ int index, fua, lba48, write;
+ fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
if (dev->flags & ATA_DFLAG_PIO) {
tf->protocol = ATA_PROT_PIO;
+ index = dev->multi_count ? 0 : 8;
+ } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) {
+ /* Unable to use DMA due to host limitation */
+ tf->protocol = ATA_PROT_PIO;
index = dev->multi_count ? 0 : 4;
} else {
tf->protocol = ATA_PROT_DMA;
- index = 8;
+ index = 16;
}
- tf->command = ata_rw_cmds[index + lba48 + write];
+ cmd = ata_rw_cmds[index + fua + lba48 + write];
+ if (cmd) {
+ tf->command = cmd;
+ return 0;
+ }
+ return -1;
}
-static const char * xfer_mode_str[] = {
+static const char * const xfer_mode_str[] = {
"UDMA/16",
"UDMA/25",
"UDMA/33",
@@ -1032,42 +1055,154 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
{
u16 modes;
- /* Usual case. Word 53 indicates word 88 is valid */
- if (adev->id[ATA_ID_FIELD_VALID] & (1 << 2)) {
+ /* Usual case. Word 53 indicates word 64 is valid */
+ if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) {
modes = adev->id[ATA_ID_PIO_MODES] & 0x03;
modes <<= 3;
modes |= 0x7;
return modes;
}
- /* If word 88 isn't valid then Word 51 holds the PIO timing number
- for the maximum. Turn it into a mask and return it */
- modes = (2 << (adev->id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ;
+ /* If word 64 isn't valid then Word 51 high byte holds the PIO timing
+ number for the maximum. Turn it into a mask and return it */
+ modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ;
return modes;
+ /* But wait.. there's more. Design your standards by committee and
+ you too can get a free iordy field to process. However its the
+ speeds not the modes that are supported... Note drivers using the
+ timing API will get this right anyway */
}
-static int ata_qc_wait_err(struct ata_queued_cmd *qc,
- struct completion *wait)
+struct ata_exec_internal_arg {
+ unsigned int err_mask;
+ struct ata_taskfile *tf;
+ struct completion *waiting;
+};
+
+int ata_qc_complete_internal(struct ata_queued_cmd *qc)
{
- int rc = 0;
+ struct ata_exec_internal_arg *arg = qc->private_data;
+ struct completion *waiting = arg->waiting;
- if (wait_for_completion_timeout(wait, 30 * HZ) < 1) {
- /* timeout handling */
- unsigned int err_mask = ac_err_mask(ata_chk_status(qc->ap));
+ if (!(qc->err_mask & ~AC_ERR_DEV))
+ qc->ap->ops->tf_read(qc->ap, arg->tf);
+ arg->err_mask = qc->err_mask;
+ arg->waiting = NULL;
+ complete(waiting);
- if (!err_mask) {
- printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n",
- qc->ap->id, qc->tf.command);
- } else {
- printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n",
- qc->ap->id, qc->tf.command);
- rc = -EIO;
+ return 0;
+}
+
+/**
+ * ata_exec_internal - execute libata internal command
+ * @ap: Port to which the command is sent
+ * @dev: Device to which the command is sent
+ * @tf: Taskfile registers for the command and the result
+ * @dma_dir: Data tranfer direction of the command
+ * @buf: Data buffer of the command
+ * @buflen: Length of data buffer
+ *
+ * Executes libata internal command with timeout. @tf contains
+ * command on entry and result on return. Timeout and error
+ * conditions are reported via return value. No recovery action
+ * is taken after a command times out. It's caller's duty to
+ * clean up after timeout.
+ *
+ * LOCKING:
+ * None. Should be called with kernel context, might sleep.
+ */
+
+static unsigned
+ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
+ struct ata_taskfile *tf,
+ int dma_dir, void *buf, unsigned int buflen)
+{
+ u8 command = tf->command;
+ struct ata_queued_cmd *qc;
+ DECLARE_COMPLETION(wait);
+ unsigned long flags;
+ struct ata_exec_internal_arg arg;
+
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+
+ qc = ata_qc_new_init(ap, dev);
+ BUG_ON(qc == NULL);
+
+ qc->tf = *tf;
+ qc->dma_dir = dma_dir;
+ if (dma_dir != DMA_NONE) {
+ ata_sg_init_one(qc, buf, buflen);
+ qc->nsect = buflen / ATA_SECT_SIZE;
+ }
+
+ arg.waiting = &wait;
+ arg.tf = tf;
+ qc->private_data = &arg;
+ qc->complete_fn = ata_qc_complete_internal;
+
+ if (ata_qc_issue(qc))
+ goto issue_fail;
+
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+ if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+ spin_lock_irqsave(&ap->host_set->lock, flags);
+
+ /* We're racing with irq here. If we lose, the
+ * following test prevents us from completing the qc
+ * again. If completion irq occurs after here but
+ * before the caller cleans up, it will result in a
+ * spurious interrupt. We can live with that.
+ */
+ if (arg.waiting) {
+ qc->err_mask = AC_ERR_OTHER;
+ ata_qc_complete(qc);
+ printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
+ ap->id, command);
}
- ata_qc_complete(qc, err_mask);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
- return rc;
+ return arg.err_mask;
+
+ issue_fail:
+ ata_qc_free(qc);
+ spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ return AC_ERR_OTHER;
+}
+
+/**
+ * ata_pio_need_iordy - check if iordy needed
+ * @adev: ATA device
+ *
+ * Check if the current speed of the device requires IORDY. Used
+ * by various controllers for chip configuration.
+ */
+
+unsigned int ata_pio_need_iordy(const struct ata_device *adev)
+{
+ int pio;
+ int speed = adev->pio_mode - XFER_PIO_0;
+
+ if (speed < 2)
+ return 0;
+ if (speed > 2)
+ return 1;
+
+ /* If we have no drive specific rule, then PIO 2 is non IORDY */
+
+ if (adev->id[ATA_ID_FIELD_VALID] & 2) { /* EIDE */
+ pio = adev->id[ATA_ID_EIDE_PIO];
+ /* Is the speed faster than the drive allows non IORDY ? */
+ if (pio) {
+ /* This is cycle times not frequency - watch the logic! */
+ if (pio > 240) /* PIO2 is 240nS per cycle */
+ return 1;
+ return 0;
+ }
+ }
+ return 0;
}
/**
@@ -1099,9 +1234,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
u16 tmp;
unsigned long xfer_modes;
unsigned int using_edd;
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- unsigned long flags;
+ struct ata_taskfile tf;
+ unsigned int err_mask;
int rc;
if (!ata_dev_present(dev)) {
@@ -1122,40 +1256,26 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
-
- ata_sg_init_one(qc, dev->id, sizeof(dev->id));
- qc->dma_dir = DMA_FROM_DEVICE;
- qc->tf.protocol = ATA_PROT_PIO;
- qc->nsect = 1;
-
retry:
+ ata_tf_init(ap, &tf, device);
+
if (dev->class == ATA_DEV_ATA) {
- qc->tf.command = ATA_CMD_ID_ATA;
+ tf.command = ATA_CMD_ID_ATA;
DPRINTK("do ATA identify\n");
} else {
- qc->tf.command = ATA_CMD_ID_ATAPI;
+ tf.command = ATA_CMD_ID_ATAPI;
DPRINTK("do ATAPI identify\n");
}
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ tf.protocol = ATA_PROT_PIO;
- if (rc)
- goto err_out;
- else
- ata_qc_wait_err(qc, &wait);
+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+ dev->id, sizeof(dev->id));
- spin_lock_irqsave(&ap->host_set->lock, flags);
- ap->ops->tf_read(ap, &qc->tf);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ if (err_mask) {
+ if (err_mask & ~AC_ERR_DEV)
+ goto err_out;
- if (qc->tf.command & ATA_ERR) {
/*
* arg! EDD works for all test cases, but seems to return
* the ATA signature for some ATAPI devices. Until the
@@ -1168,13 +1288,9 @@ retry:
* to have this problem.
*/
if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
- u8 err = qc->tf.feature;
+ u8 err = tf.feature;
if (err & ATA_ABORTED) {
dev->class = ATA_DEV_ATAPI;
- qc->cursg = 0;
- qc->cursg_ofs = 0;
- qc->cursect = 0;
- qc->nsect = 1;
goto retry;
}
}
@@ -1340,7 +1456,7 @@ void ata_dev_config(struct ata_port *ap, unsigned int i)
ap->udma_mask &= ATA_UDMA5;
ap->host->max_sectors = ATA_MAX_SECTORS;
ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
- ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+ ap->device[i].flags |= ATA_DFLAG_LOCK_SECTORS;
}
if (ap->ops->dev_config)
@@ -1444,11 +1560,23 @@ void __sata_phy_reset(struct ata_port *ap)
} while (time_before(jiffies, timeout));
/* TODO: phy layer with polling, timeouts, etc. */
- if (sata_dev_present(ap))
+ sstatus = scr_read(ap, SCR_STATUS);
+ if (sata_dev_present(ap)) {
+ const char *speed;
+ u32 tmp;
+
+ tmp = (sstatus >> 4) & 0xf;
+ if (tmp & (1 << 0))
+ speed = "1.5";
+ else if (tmp & (1 << 1))
+ speed = "3.0";
+ else
+ speed = "<unknown>";
+ printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+ ap->id, speed, sstatus);
ata_port_probe(ap);
- else {
- sstatus = scr_read(ap, SCR_STATUS);
- printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+ } else {
+ printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
ap->id, sstatus);
ata_port_disable(ap);
}
@@ -1660,7 +1788,7 @@ static const struct {
{ ATA_SHIFT_PIO, XFER_PIO_0 },
};
-static inline u8 base_from_shift(unsigned int shift)
+static u8 base_from_shift(unsigned int shift)
{
int i;
@@ -2071,7 +2199,7 @@ static void ata_pr_blacklisted(const struct ata_port *ap,
ap->id, dev->devno);
}
-static const char * ata_dma_blacklist [] = {
+static const char * const ata_dma_blacklist [] = {
"WDC AC11000H",
"WDC AC22100H",
"WDC AC32500H",
@@ -2266,34 +2394,23 @@ static int ata_choose_xfer_mode(const struct ata_port *ap,
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
{
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- int rc;
- unsigned long flags;
+ struct ata_taskfile tf;
/* set up set-features taskfile */
DPRINTK("set features - xfer mode\n");
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
-
- qc->tf.command = ATA_CMD_SET_FEATURES;
- qc->tf.feature = SETFEATURES_XFER;
- qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- qc->tf.protocol = ATA_PROT_NODATA;
- qc->tf.nsect = dev->xfer_mode;
-
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ ata_tf_init(ap, &tf, dev->devno);
+ tf.command = ATA_CMD_SET_FEATURES;
+ tf.feature = SETFEATURES_XFER;
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_NODATA;
+ tf.nsect = dev->xfer_mode;
- if (rc)
+ if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+ printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+ ap->id);
ata_port_disable(ap);
- else
- ata_qc_wait_err(qc, &wait);
+ }
DPRINTK("EXIT\n");
}
@@ -2308,41 +2425,25 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
{
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- unsigned long flags;
- int rc;
-
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
+ struct ata_taskfile tf;
- ata_sg_init_one(qc, dev->id, sizeof(dev->id));
- qc->dma_dir = DMA_FROM_DEVICE;
+ ata_tf_init(ap, &tf, dev->devno);
if (dev->class == ATA_DEV_ATA) {
- qc->tf.command = ATA_CMD_ID_ATA;
+ tf.command = ATA_CMD_ID_ATA;
DPRINTK("do ATA identify\n");
} else {
- qc->tf.command = ATA_CMD_ID_ATAPI;
+ tf.command = ATA_CMD_ID_ATAPI;
DPRINTK("do ATAPI identify\n");
}
- qc->tf.flags |= ATA_TFLAG_DEVICE;
- qc->tf.protocol = ATA_PROT_PIO;
- qc->nsect = 1;
-
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ tf.flags |= ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_PIO;
- if (rc)
+ if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+ dev->id, sizeof(dev->id)))
goto err_out;
- ata_qc_wait_err(qc, &wait);
-
swap_buf_le16(dev->id, ATA_ID_WORDS);
ata_dump_id(dev);
@@ -2351,6 +2452,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
return;
err_out:
+ printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
ata_port_disable(ap);
}
@@ -2364,10 +2466,7 @@ err_out:
static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
{
- DECLARE_COMPLETION(wait);
- struct ata_queued_cmd *qc;
- int rc;
- unsigned long flags;
+ struct ata_taskfile tf;
u16 sectors = dev->id[6];
u16 heads = dev->id[3];
@@ -2378,26 +2477,18 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
/* set up init dev params taskfile */
DPRINTK("init dev params \n");
- qc = ata_qc_new_init(ap, dev);
- BUG_ON(qc == NULL);
-
- qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
- qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- qc->tf.protocol = ATA_PROT_NODATA;
- qc->tf.nsect = sectors;
- qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
- qc->waiting = &wait;
- qc->complete_fn = ata_qc_complete_noop;
-
- spin_lock_irqsave(&ap->host_set->lock, flags);
- rc = ata_qc_issue(qc);
- spin_unlock_irqrestore(&ap->host_set->lock, flags);
+ ata_tf_init(ap, &tf, dev->devno);
+ tf.command = ATA_CMD_INIT_DEV_PARAMS;
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_NODATA;
+ tf.nsect = sectors;
+ tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
- if (rc)
+ if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+ printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
+ ap->id);
ata_port_disable(ap);
- else
- ata_qc_wait_err(qc, &wait);
+ }
DPRINTK("EXIT\n");
}
@@ -2765,7 +2856,7 @@ skip_map:
* None. (grabs host lock)
*/
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned long flags;
@@ -2773,7 +2864,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
spin_lock_irqsave(&ap->host_set->lock, flags);
ap->flags &= ~ATA_FLAG_NOINTR;
ata_irq_on(ap);
- ata_qc_complete(qc, err_mask);
+ ata_qc_complete(qc);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
@@ -2790,10 +2881,14 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
static unsigned long ata_pio_poll(struct ata_port *ap)
{
+ struct ata_queued_cmd *qc;
u8 status;
unsigned int poll_state = HSM_ST_UNKNOWN;
unsigned int reg_state = HSM_ST_UNKNOWN;
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ assert(qc != NULL);
+
switch (ap->hsm_task_state) {
case HSM_ST:
case HSM_ST_POLL:
@@ -2813,6 +2908,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
status = ata_chk_status(ap);
if (status & ATA_BUSY) {
if (time_after(jiffies, ap->pio_task_timeout)) {
+ qc->err_mask |= AC_ERR_ATA_BUS;
ap->hsm_task_state = HSM_ST_TMOUT;
return 0;
}
@@ -2847,29 +2943,31 @@ static int ata_pio_complete (struct ata_port *ap)
* msecs, then chk-status again. If still busy, fall back to
* HSM_ST_POLL state.
*/
- drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
- if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+ drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+ if (drv_stat & ATA_BUSY) {
msleep(2);
- drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
- if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+ drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+ if (drv_stat & ATA_BUSY) {
ap->hsm_task_state = HSM_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
return 0;
}
}
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ assert(qc != NULL);
+
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
+ qc->err_mask |= __ac_err_mask(drv_stat);
ap->hsm_task_state = HSM_ST_ERR;
return 0;
}
- qc = ata_qc_from_tag(ap, ap->active_tag);
- assert(qc != NULL);
-
ap->hsm_task_state = HSM_ST_IDLE;
- ata_poll_qc_complete(qc, 0);
+ assert(qc->err_mask == 0);
+ ata_poll_qc_complete(qc);
/* another command may start at this point */
@@ -2999,10 +3097,21 @@ static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
unsigned int buflen, int do_write)
{
- if (ap->flags & ATA_FLAG_MMIO)
- ata_mmio_data_xfer(ap, buf, buflen, do_write);
- else
- ata_pio_data_xfer(ap, buf, buflen, do_write);
+ /* Make the crap hardware pay the costs not the good stuff */
+ if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
+ unsigned long flags;
+ local_irq_save(flags);
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ local_irq_restore(flags);
+ } else {
+ if (ap->flags & ATA_FLAG_MMIO)
+ ata_mmio_data_xfer(ap, buf, buflen, do_write);
+ else
+ ata_pio_data_xfer(ap, buf, buflen, do_write);
+ }
}
/**
@@ -3177,6 +3286,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
err_out:
printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
ap->id, dev->devno);
+ qc->err_mask |= AC_ERR_ATA_BUS;
ap->hsm_task_state = HSM_ST_ERR;
}
@@ -3215,8 +3325,16 @@ static void ata_pio_block(struct ata_port *ap)
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
+ /* check error */
+ if (status & (ATA_ERR | ATA_DF)) {
+ qc->err_mask |= AC_ERR_DEV;
+ ap->hsm_task_state = HSM_ST_ERR;
+ return;
+ }
+
+ /* transfer data if any */
if (is_atapi_taskfile(&qc->tf)) {
- /* no more data to transfer or unsupported ATAPI command */
+ /* DRQ=0 means no more data to transfer */
if ((status & ATA_DRQ) == 0) {
ap->hsm_task_state = HSM_ST_LAST;
return;
@@ -3226,6 +3344,7 @@ static void ata_pio_block(struct ata_port *ap)
} else {
/* handle BSY=0, DRQ=0 as error */
if ((status & ATA_DRQ) == 0) {
+ qc->err_mask |= AC_ERR_ATA_BUS;
ap->hsm_task_state = HSM_ST_ERR;
return;
}
@@ -3243,9 +3362,14 @@ static void ata_pio_error(struct ata_port *ap)
qc = ata_qc_from_tag(ap, ap->active_tag);
assert(qc != NULL);
+ /* make sure qc->err_mask is available to
+ * know what's wrong and recover
+ */
+ assert(qc->err_mask);
+
ap->hsm_task_state = HSM_ST_IDLE;
- ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
+ ata_poll_qc_complete(qc);
}
static void ata_pio_task(void *_data)
@@ -3347,7 +3471,8 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
ap->id, qc->tf.command, drv_stat, host_stat);
/* complete taskfile transaction */
- ata_qc_complete(qc, ac_err_mask(drv_stat));
+ qc->err_mask |= ac_err_mask(drv_stat);
+ ata_qc_complete(qc);
break;
}
@@ -3446,15 +3571,10 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
return qc;
}
-int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
-{
- return 0;
-}
-
static void __ata_qc_complete(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- unsigned int tag, do_clear = 0;
+ unsigned int tag;
qc->flags = 0;
tag = qc->tag;
@@ -3462,17 +3582,8 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
if (tag == ap->active_tag)
ap->active_tag = ATA_TAG_POISON;
qc->tag = ATA_TAG_POISON;
- do_clear = 1;
- }
-
- if (qc->waiting) {
- struct completion *waiting = qc->waiting;
- qc->waiting = NULL;
- complete(waiting);
- }
-
- if (likely(do_clear))
clear_bit(tag, &ap->qactive);
+ }
}
/**
@@ -3488,7 +3599,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
void ata_qc_free(struct ata_queued_cmd *qc)
{
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
- assert(qc->waiting == NULL); /* nothing should be waiting */
__ata_qc_complete(qc);
}
@@ -3505,7 +3615,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
* spin_lock_irqsave(host_set lock)
*/
-void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_qc_complete(struct ata_queued_cmd *qc)
{
int rc;
@@ -3522,7 +3632,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
qc->flags &= ~ATA_QCFLAG_ACTIVE;
/* call completion callback */
- rc = qc->complete_fn(qc, err_mask);
+ rc = qc->complete_fn(qc);
/* if callback indicates not to complete command (non-zero),
* return immediately
@@ -3960,7 +4070,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
ap->ops->irq_clear(ap);
/* complete taskfile transaction */
- ata_qc_complete(qc, ac_err_mask(status));
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
break;
default:
@@ -4054,13 +4165,17 @@ static void atapi_packet_task(void *_data)
/* sleep-wait for BSY to clear */
DPRINTK("busy wait\n");
- if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
- goto err_out_status;
+ if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+ qc->err_mask |= AC_ERR_ATA_BUS;
+ goto err_out;
+ }
/* make sure DRQ is set */
status = ata_chk_status(ap);
- if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
+ if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+ qc->err_mask |= AC_ERR_ATA_BUS;
goto err_out;
+ }
/* send SCSI cdb */
DPRINTK("send cdb\n");
@@ -4092,10 +4207,8 @@ static void atapi_packet_task(void *_data)
return;
-err_out_status:
- status = ata_chk_status(ap);
err_out:
- ata_poll_qc_complete(qc, __ac_err_mask(status));
+ ata_poll_qc_complete(qc);
}
@@ -4112,6 +4225,96 @@ err_out:
* Inherited from caller.
*/
+/*
+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
+ * without filling any other registers
+ */
+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
+ u8 cmd)
+{
+ struct ata_taskfile tf;
+ int err;
+
+ ata_tf_init(ap, &tf, dev->devno);
+
+ tf.command = cmd;
+ tf.flags |= ATA_TFLAG_DEVICE;
+ tf.protocol = ATA_PROT_NODATA;
+
+ err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+ if (err)
+ printk(KERN_ERR "%s: ata command failed: %d\n",
+ __FUNCTION__, err);
+
+ return err;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+ u8 cmd;
+
+ if (!ata_try_flush_cache(dev))
+ return 0;
+
+ if (ata_id_has_flush_ext(dev->id))
+ cmd = ATA_CMD_FLUSH_EXT;
+ else
+ cmd = ATA_CMD_FLUSH;
+
+ return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+ return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+ return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ * ata_device_resume - wakeup a previously suspended devices
+ *
+ * Kick the drive back into action, by sending it an idle immediate
+ * command and making sure its transfer mode matches between drive
+ * and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+ if (ap->flags & ATA_FLAG_SUSPENDED) {
+ ap->flags &= ~ATA_FLAG_SUSPENDED;
+ ata_set_mode(ap);
+ }
+ if (!ata_dev_present(dev))
+ return 0;
+ if (dev->class == ATA_DEV_ATA)
+ ata_start_drive(ap, dev);
+
+ return 0;
+}
+
+/**
+ * ata_device_suspend - prepare a device for suspend
+ *
+ * Flush the cache on the drive, if appropriate, then issue a
+ * standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+ if (!ata_dev_present(dev))
+ return 0;
+ if (dev->class == ATA_DEV_ATA)
+ ata_flush_cache(ap, dev);
+
+ ata_standby_drive(ap, dev);
+ ap->flags |= ATA_FLAG_SUSPENDED;
+ return 0;
+}
+
int ata_port_start (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
@@ -4860,6 +5063,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
return (tmp == bits->val) ? 1 : 0;
}
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+ return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_device(pdev);
+ pci_set_master(pdev);
+ return 0;
+}
#endif /* CONFIG_PCI */
@@ -4954,6 +5174,7 @@ EXPORT_SYMBOL_GPL(ata_dev_id_string);
EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
EXPORT_SYMBOL_GPL(ata_timing_compute);
EXPORT_SYMBOL_GPL(ata_timing_merge);
@@ -4963,4 +5184,11 @@ 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);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
#endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_device_suspend);
+EXPORT_SYMBOL_GPL(ata_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 2282c04fee46..cfbceb504718 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -396,6 +396,22 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf)
}
}
+int ata_scsi_device_resume(struct scsi_device *sdev)
+{
+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+ struct ata_device *dev = &ap->device[sdev->id];
+
+ return ata_device_resume(ap, dev);
+}
+
+int ata_scsi_device_suspend(struct scsi_device *sdev)
+{
+ struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+ struct ata_device *dev = &ap->device[sdev->id];
+
+ return ata_device_suspend(ap, dev);
+}
+
/**
* ata_to_sense_error - convert ATA error to SCSI error
* @id: ATA device number
@@ -418,7 +434,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
int i;
/* Based on the 3ware driver translation table */
- static unsigned char sense_table[][4] = {
+ static const unsigned char sense_table[][4] = {
/* BBD|ECC|ID|MAR */
{0xd1, ABORTED_COMMAND, 0x00, 0x00}, // Device busy Aborted command
/* BBD|ECC|ID */
@@ -449,7 +465,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
{0x80, MEDIUM_ERROR, 0x11, 0x04}, // Block marked bad Medium error, unrecovered read error
{0xFF, 0xFF, 0xFF, 0xFF}, // END mark
};
- static unsigned char stat_table[][4] = {
+ static const unsigned char stat_table[][4] = {
/* Must be first because BUSY means no other bits valid */
{0x80, ABORTED_COMMAND, 0x47, 0x00}, // Busy, fake parity for now
{0x20, HARDWARE_ERROR, 0x00, 0x00}, // Device fault
@@ -1080,11 +1096,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
scsicmd[0] == WRITE_16)
tf->flags |= ATA_TFLAG_WRITE;
- /* Calculate the SCSI LBA and transfer length. */
+ /* Calculate the SCSI LBA, transfer length and FUA. */
switch (scsicmd[0]) {
case READ_10:
case WRITE_10:
scsi_10_lba_len(scsicmd, &block, &n_block);
+ if (unlikely(scsicmd[1] & (1 << 3)))
+ tf->flags |= ATA_TFLAG_FUA;
break;
case READ_6:
case WRITE_6:
@@ -1099,6 +1117,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
case READ_16:
case WRITE_16:
scsi_16_lba_len(scsicmd, &block, &n_block);
+ if (unlikely(scsicmd[1] & (1 << 3)))
+ tf->flags |= ATA_TFLAG_FUA;
break;
default:
DPRINTK("no-byte command\n");
@@ -1142,7 +1162,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
tf->device |= (block >> 24) & 0xf;
}
- ata_rwcmd_protocol(qc);
+ if (unlikely(ata_rwcmd_protocol(qc) < 0))
+ goto invalid_fld;
qc->nsect = n_block;
tf->nsect = n_block & 0xff;
@@ -1160,7 +1181,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
if ((block >> 28) || (n_block > 256))
goto out_of_range;
- ata_rwcmd_protocol(qc);
+ if (unlikely(ata_rwcmd_protocol(qc) < 0))
+ goto invalid_fld;
/* Convert LBA to CHS */
track = (u32)block / dev->sectors;
@@ -1203,12 +1225,11 @@ nothing_to_do:
return 1;
}
-static int ata_scsi_qc_complete(struct ata_queued_cmd *qc,
- unsigned int err_mask)
+static int ata_scsi_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
u8 *cdb = cmd->cmnd;
- int need_sense = (err_mask != 0);
+ int need_sense = (qc->err_mask != 0);
/* For ATA pass thru (SAT) commands, generate a sense block if
* user mandated it or if there's an error. Note that if we
@@ -1532,7 +1553,7 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
return 0;
}
-static const char *inq_83_str = "Linux ATA-SCSI simulator";
+static const char * const inq_83_str = "Linux ATA-SCSI simulator";
/**
* ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
@@ -1696,6 +1717,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
+ struct ata_device *dev = args->dev;
u8 *scsicmd = args->cmd->cmnd, *p, *last;
const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */
@@ -1704,6 +1726,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
};
u8 pg, spg;
unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+ u8 dpofua;
VPRINTK("ENTER\n");
@@ -1772,9 +1795,17 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
if (minlen < 1)
return 0;
+
+ dpofua = 0;
+ if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+ (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
+ dpofua = 1 << 4;
+
if (six_byte) {
output_len--;
rbuf[0] = output_len;
+ if (minlen > 2)
+ rbuf[2] |= dpofua;
if (ebd) {
if (minlen > 3)
rbuf[3] = sizeof(sat_blk_desc);
@@ -1787,6 +1818,8 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
rbuf[0] = output_len >> 8;
if (minlen > 1)
rbuf[1] = output_len;
+ if (minlen > 3)
+ rbuf[3] |= dpofua;
if (ebd) {
if (minlen > 7)
rbuf[7] = sizeof(sat_blk_desc);
@@ -1955,9 +1988,9 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
done(cmd);
}
-static int atapi_sense_complete(struct ata_queued_cmd *qc,unsigned int err_mask)
+static int atapi_sense_complete(struct ata_queued_cmd *qc)
{
- if (err_mask && ((err_mask & AC_ERR_DEV) == 0))
+ if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
/* FIXME: not quite right; we don't want the
* translation of taskfile registers into
* a sense descriptors, since that's only
@@ -2015,15 +2048,18 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
qc->complete_fn = atapi_sense_complete;
- if (ata_qc_issue(qc))
- ata_qc_complete(qc, AC_ERR_OTHER);
+ if (ata_qc_issue(qc)) {
+ qc->err_mask |= AC_ERR_OTHER;
+ ata_qc_complete(qc);
+ }
DPRINTK("EXIT\n");
}
-static int atapi_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+static int atapi_qc_complete(struct ata_queued_cmd *qc)
{
struct scsi_cmnd *cmd = qc->scsicmd;
+ unsigned int err_mask = qc->err_mask;
VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
@@ -2444,7 +2480,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
if (xlat_func)
ata_scsi_translate(ap, dev, cmd, done, xlat_func);
else
- ata_scsi_simulate(dev->id, cmd, done);
+ ata_scsi_simulate(ap, dev, cmd, done);
} else
ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
@@ -2467,14 +2503,16 @@ out_unlock:
* spin_lock_irqsave(host_set lock)
*/
-void ata_scsi_simulate(u16 *id,
+void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *))
{
struct ata_scsi_args args;
const u8 *scsicmd = cmd->cmnd;
- args.id = id;
+ args.ap = ap;
+ args.dev = dev;
+ args.id = dev->id;
args.cmd = cmd;
args.done = done;
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 8ebaa694d18e..e03ce48b7b4b 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -32,6 +32,8 @@
#define DRV_VERSION "1.20" /* must be exactly four chars */
struct ata_scsi_args {
+ struct ata_port *ap;
+ struct ata_device *dev;
u16 *id;
struct scsi_cmnd *cmd;
void (*done)(struct scsi_cmnd *);
@@ -39,10 +41,9 @@ struct ata_scsi_args {
/* libata-core.c */
extern int atapi_enabled;
-extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
-extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 3062b39fbdb9..38ffa8d6e629 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -29,9 +29,10 @@ struct lpfc_sli2_slim;
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
-#define LPFC_CMD_PER_LUN 30 /* max outstanding cmds per lun */
+#define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */
#define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
+#define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */
/* Define macros for 64 bit support */
#define putPaddrLow(addr) ((uint32_t) (0xffffffff & (u64)(addr)))
@@ -45,6 +46,11 @@ struct lpfc_sli2_slim;
#define MAX_HBAEVT 32
+enum lpfc_polling_flags {
+ ENABLE_FCP_RING_POLLING = 0x1,
+ DISABLE_FCP_RING_INT = 0x2
+};
+
/* Provide DMA memory definitions the driver uses per port instance. */
struct lpfc_dmabuf {
struct list_head list;
@@ -167,6 +173,7 @@ struct lpfc_hba {
dma_addr_t slim2p_mapping;
uint16_t pci_cfg_value;
+ struct semaphore hba_can_block;
uint32_t hba_state;
#define LPFC_INIT_START 1 /* Initial state after board reset */
@@ -286,6 +293,8 @@ struct lpfc_hba {
uint32_t cfg_fcp_bind_method;
uint32_t cfg_discovery_threads;
uint32_t cfg_max_luns;
+ uint32_t cfg_poll;
+ uint32_t cfg_poll_tmo;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
@@ -337,7 +346,9 @@ struct lpfc_hba {
#define VPD_PORT 0x8 /* valid vpd port data */
#define VPD_MASK 0xf /* mask for any vpd data */
+ struct timer_list fcp_poll_timer;
struct timer_list els_tmofunc;
+
/*
* stat counters
*/
@@ -348,6 +359,7 @@ struct lpfc_hba {
struct lpfc_sysfs_mbox sysfs_mbox;
/* fastpath list. */
+ spinlock_t scsi_buf_list_lock;
struct list_head lpfc_scsi_buf_list;
uint32_t total_scsi_bufs;
struct list_head lpfc_iocb_list;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 89e8222bc7cc..5625a8c2a8fd 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -278,6 +278,71 @@ lpfc_board_online_store(struct class_device *cdev, const char *buf,
return -EIO;
}
+static ssize_t
+lpfc_poll_show(struct class_device *cdev, char *buf)
+{
+ struct Scsi_Host *host = class_to_shost(cdev);
+ struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
+
+ return snprintf(buf, PAGE_SIZE, "%#x\n", phba->cfg_poll);
+}
+
+static ssize_t
+lpfc_poll_store(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct Scsi_Host *host = class_to_shost(cdev);
+ struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata[0];
+ uint32_t creg_val;
+ uint32_t old_val;
+ int val=0;
+
+ if (!isdigit(buf[0]))
+ return -EINVAL;
+
+ if (sscanf(buf, "%i", &val) != 1)
+ return -EINVAL;
+
+ if ((val & 0x3) != val)
+ return -EINVAL;
+
+ spin_lock_irq(phba->host->host_lock);
+
+ old_val = phba->cfg_poll;
+
+ if (val & ENABLE_FCP_RING_POLLING) {
+ if ((val & DISABLE_FCP_RING_INT) &&
+ !(old_val & DISABLE_FCP_RING_INT)) {
+ creg_val = readl(phba->HCregaddr);
+ creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+ writel(creg_val, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+
+ lpfc_poll_start_timer(phba);
+ }
+ } else if (val != 0x0) {
+ spin_unlock_irq(phba->host->host_lock);
+ return -EINVAL;
+ }
+
+ if (!(val & DISABLE_FCP_RING_INT) &&
+ (old_val & DISABLE_FCP_RING_INT))
+ {
+ spin_unlock_irq(phba->host->host_lock);
+ del_timer(&phba->fcp_poll_timer);
+ spin_lock_irq(phba->host->host_lock);
+ creg_val = readl(phba->HCregaddr);
+ creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
+ writel(creg_val, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+ }
+
+ phba->cfg_poll = val;
+
+ spin_unlock_irq(phba->host->host_lock);
+
+ return strlen(buf);
+}
#define lpfc_param_show(attr) \
static ssize_t \
@@ -416,6 +481,15 @@ static CLASS_DEVICE_ATTR(management_version, S_IRUGO, management_version_show,
static CLASS_DEVICE_ATTR(board_online, S_IRUGO | S_IWUSR,
lpfc_board_online_show, lpfc_board_online_store);
+static int lpfc_poll = 0;
+module_param(lpfc_poll, int, 0);
+MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
+ " 0 - none,"
+ " 1 - poll with interrupts enabled"
+ " 3 - poll and disable FCP ring interrupts");
+
+static CLASS_DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
+ lpfc_poll_show, lpfc_poll_store);
/*
# lpfc_log_verbose: Only turn this flag on if you are willing to risk being
@@ -523,10 +597,10 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
# cr_delay is set to 0.
*/
-LPFC_ATTR(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
+LPFC_ATTR_RW(cr_delay, 0, 0, 63, "A count of milliseconds after which an"
"interrupt response is generated");
-LPFC_ATTR(cr_count, 1, 1, 255, "A count of I/O completions after which an"
+LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an"
"interrupt response is generated");
/*
@@ -553,6 +627,13 @@ LPFC_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands"
LPFC_ATTR_R(max_luns, 256, 1, 32768,
"Maximum number of LUNs per target driver will support");
+/*
+# lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring.
+# Value range is [1,255], default value is 10.
+*/
+LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
+ "Milliseconds driver will wait between polling FCP ring");
+
struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_info,
&class_device_attr_serialnum,
@@ -575,11 +656,15 @@ struct class_device_attribute *lpfc_host_attrs[] = {
&class_device_attr_lpfc_topology,
&class_device_attr_lpfc_scan_down,
&class_device_attr_lpfc_link_speed,
+ &class_device_attr_lpfc_cr_delay,
+ &class_device_attr_lpfc_cr_count,
&class_device_attr_lpfc_fdmi_on,
&class_device_attr_lpfc_max_luns,
&class_device_attr_nport_evt_cnt,
&class_device_attr_management_version,
&class_device_attr_board_online,
+ &class_device_attr_lpfc_poll,
+ &class_device_attr_lpfc_poll_tmo,
NULL,
};
@@ -1292,6 +1377,9 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_fdmi_on_init(phba, lpfc_fdmi_on);
lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
lpfc_max_luns_init(phba, lpfc_max_luns);
+ lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
+
+ phba->cfg_poll = lpfc_poll;
/*
* The total number of segments is the configuration value plus 2
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index d527d05a607f..f1e708946e66 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -143,6 +143,9 @@ LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
int lpfc_mem_alloc(struct lpfc_hba *);
void lpfc_mem_free(struct lpfc_hba *);
+void lpfc_poll_timeout(unsigned long ptr);
+void lpfc_poll_start_timer(struct lpfc_hba * phba);
+void lpfc_sli_poll_fcp_ring(struct lpfc_hba * hba);
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 084e7628ce17..ed6c81660e03 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -73,6 +73,8 @@ struct lpfc_nodelist {
struct lpfc_hba *nlp_phba;
struct lpfc_work_evt nodev_timeout_evt;
struct lpfc_work_evt els_retry_evt;
+ unsigned long last_ramp_up_time; /* jiffy of last ramp up */
+ unsigned long last_q_full_time; /* jiffy of last queue full */
};
/* Defines for nlp_flag (uint32) */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index bcc29ec126dc..20f1a0713db2 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -720,6 +720,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+ (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
}
@@ -869,6 +870,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+ (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
goto out;
}
@@ -1054,6 +1056,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+ (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
}
@@ -1205,6 +1208,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+ (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
(irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
goto out;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 259eeb161b82..a1f751e79405 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1017,12 +1017,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rport_ids.port_id = ndlp->nlp_DID;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
- if (ndlp->nlp_type & NLP_FCP_TARGET)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
- if (ndlp->nlp_type & NLP_FCP_INITIATOR)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
- scsi_block_requests(phba->host);
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
if (!rport) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
@@ -1039,7 +1034,16 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
}
rdata = rport->dd_data;
rdata->pnode = ndlp;
- scsi_unblock_requests(phba->host);
+
+ if (ndlp->nlp_type & NLP_FCP_TARGET)
+ rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ if (ndlp->nlp_type & NLP_FCP_INITIATOR)
+ rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+
+ if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
+ fc_remote_port_rolechg(rport, rport_ids.roles);
+
return;
}
@@ -1053,9 +1057,7 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
ndlp->rport = NULL;
rdata->pnode = NULL;
- scsi_block_requests(phba->host);
fc_remote_port_delete(rport);
- scsi_unblock_requests(phba->host);
return;
}
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 86c41981188b..1ea565e0561f 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -266,9 +266,11 @@ struct lpfc_name {
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 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 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
@@ -278,7 +280,8 @@ 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 IEEEextLsb; /* FC Word 0, bit 16:23, IEEE
+ extended Lsb */
uint8_t IEEE[6]; /* FC IEEE address */
} s;
uint8_t wwn[8];
@@ -1024,23 +1027,38 @@ typedef struct {
/* Start FireFly Register definitions */
#define PCI_VENDOR_ID_EMULEX 0x10df
#define PCI_DEVICE_ID_FIREFLY 0x1ae5
-#define PCI_DEVICE_ID_SUPERFLY 0xf700
-#define PCI_DEVICE_ID_DRAGONFLY 0xf800
#define PCI_DEVICE_ID_RFLY 0xf095
#define PCI_DEVICE_ID_PFLY 0xf098
+#define PCI_DEVICE_ID_LP101 0xf0a1
#define PCI_DEVICE_ID_TFLY 0xf0a5
+#define PCI_DEVICE_ID_BSMB 0xf0d1
+#define PCI_DEVICE_ID_BMID 0xf0d5
+#define PCI_DEVICE_ID_ZSMB 0xf0e1
+#define PCI_DEVICE_ID_ZMID 0xf0e5
+#define PCI_DEVICE_ID_NEPTUNE 0xf0f5
+#define PCI_DEVICE_ID_NEPTUNE_SCSP 0xf0f6
+#define PCI_DEVICE_ID_NEPTUNE_DCSP 0xf0f7
+#define PCI_DEVICE_ID_SUPERFLY 0xf700
+#define PCI_DEVICE_ID_DRAGONFLY 0xf800
#define PCI_DEVICE_ID_CENTAUR 0xf900
#define PCI_DEVICE_ID_PEGASUS 0xf980
#define PCI_DEVICE_ID_THOR 0xfa00
#define PCI_DEVICE_ID_VIPER 0xfb00
+#define PCI_DEVICE_ID_LP10000S 0xfc00
+#define PCI_DEVICE_ID_LP11000S 0xfc10
+#define PCI_DEVICE_ID_LPE11000S 0xfc20
#define PCI_DEVICE_ID_HELIOS 0xfd00
-#define PCI_DEVICE_ID_BMID 0xf0d5
-#define PCI_DEVICE_ID_BSMB 0xf0d1
+#define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11
+#define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12
#define PCI_DEVICE_ID_ZEPHYR 0xfe00
-#define PCI_DEVICE_ID_ZMID 0xf0e5
-#define PCI_DEVICE_ID_ZSMB 0xf0e1
-#define PCI_DEVICE_ID_LP101 0xf0a1
-#define PCI_DEVICE_ID_LP10000S 0xfc00
+#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
+#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
+
+#define PCI_SUBSYSTEM_ID_LP11000S 0xfc11
+#define PCI_SUBSYSTEM_ID_LP11002S 0xfc12
+#define PCI_SUBSYSTEM_ID_LPE11000S 0xfc21
+#define PCI_SUBSYSTEM_ID_LPE11002S 0xfc22
+#define PCI_SUBSYSTEM_ID_LPE11010S 0xfc2A
#define JEDEC_ID_ADDRESS 0x0080001c
#define FIREFLY_JEDEC_ID 0x1ACC
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 07498118359d..b7a603a45328 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -126,34 +126,26 @@ lpfc_config_port_prep(struct lpfc_hba * phba)
return -ERESTART;
}
- /* The HBA's current state is provided by the ProgType and rr fields.
- * Read and check the value of these fields before continuing to config
- * this port.
+ /*
+ * The value of rr must be 1 since the driver set the cv field to 1.
+ * This setting requires the FW to set all revision fields.
*/
- if (mb->un.varRdRev.rr == 0 || mb->un.varRdRev.un.b.ProgType != 2) {
- /* Old firmware */
+ if (mb->un.varRdRev.rr == 0) {
vp->rev.rBit = 0;
- lpfc_printf_log(phba,
- KERN_ERR,
- LOG_INIT,
- "%d:0440 Adapter failed to init, mbxCmd x%x "
- "READ_REV detected outdated firmware"
- "Data: x%x\n",
- phba->brd_no,
- mb->mbxCommand, 0);
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "%d:0440 Adapter failed to init, READ_REV has "
+ "missing revision information.\n",
+ phba->brd_no);
mempool_free(pmb, phba->mbox_mem_pool);
return -ERESTART;
- } else {
- vp->rev.rBit = 1;
- vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
- memcpy(vp->rev.sli1FwName,
- (char*)mb->un.varRdRev.sli1FwName, 16);
- vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
- memcpy(vp->rev.sli2FwName,
- (char *)mb->un.varRdRev.sli2FwName, 16);
}
/* Save information as VPD data */
+ vp->rev.rBit = 1;
+ vp->rev.sli1FwRev = mb->un.varRdRev.sli1FwRev;
+ memcpy(vp->rev.sli1FwName, (char*) mb->un.varRdRev.sli1FwName, 16);
+ vp->rev.sli2FwRev = mb->un.varRdRev.sli2FwRev;
+ memcpy(vp->rev.sli2FwName, (char *) mb->un.varRdRev.sli2FwName, 16);
vp->rev.biuRev = mb->un.varRdRev.biuRev;
vp->rev.smRev = mb->un.varRdRev.smRev;
vp->rev.smFwRev = mb->un.varRdRev.un.smFwRev;
@@ -378,6 +370,10 @@ lpfc_config_port_post(struct lpfc_hba * phba)
if (psli->num_rings > 3)
status |= HC_R3INT_ENA;
+ if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) &&
+ (phba->cfg_poll & DISABLE_FCP_RING_INT))
+ status &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
spin_unlock_irq(phba->host->host_lock);
@@ -571,6 +567,8 @@ lpfc_handle_latt(struct lpfc_hba * phba)
rc = -EIO;
+ /* Cleanup any outstanding ELS commands */
+ lpfc_els_flush_cmd(phba);
psli->slistat.link_event++;
lpfc_read_la(phba, pmb, mp);
@@ -765,96 +763,139 @@ static void
lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
{
lpfc_vpd_t *vp;
- uint32_t id;
- uint8_t hdrtype;
- char str[16];
+ uint16_t dev_id = phba->pcidev->device;
+ uint16_t dev_subid = phba->pcidev->subsystem_device;
+ uint8_t hdrtype = phba->pcidev->hdr_type;
+ char *model_str = "";
vp = &phba->vpd;
- pci_read_config_dword(phba->pcidev, PCI_VENDOR_ID, &id);
- pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
- switch ((id >> 16) & 0xffff) {
+ switch (dev_id) {
case PCI_DEVICE_ID_FIREFLY:
- strcpy(str, "LP6000 1");
+ model_str = "LP6000 1Gb PCI";
break;
case PCI_DEVICE_ID_SUPERFLY:
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
- strcpy(str, "LP7000 1");
+ model_str = "LP7000 1Gb PCI";
else
- strcpy(str, "LP7000E 1");
+ model_str = "LP7000E 1Gb PCI";
break;
case PCI_DEVICE_ID_DRAGONFLY:
- strcpy(str, "LP8000 1");
+ model_str = "LP8000 1Gb PCI";
break;
case PCI_DEVICE_ID_CENTAUR:
if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
- strcpy(str, "LP9002 2");
+ model_str = "LP9002 2Gb PCI";
else
- strcpy(str, "LP9000 1");
+ model_str = "LP9000 1Gb PCI";
break;
case PCI_DEVICE_ID_RFLY:
- strcpy(str, "LP952 2");
+ model_str = "LP952 2Gb PCI";
break;
case PCI_DEVICE_ID_PEGASUS:
- strcpy(str, "LP9802 2");
+ model_str = "LP9802 2Gb PCI-X";
break;
case PCI_DEVICE_ID_THOR:
if (hdrtype == 0x80)
- strcpy(str, "LP10000DC 2");
+ model_str = "LP10000DC 2Gb 2-port PCI-X";
else
- strcpy(str, "LP10000 2");
+ model_str = "LP10000 2Gb PCI-X";
break;
case PCI_DEVICE_ID_VIPER:
- strcpy(str, "LPX1000 10");
+ model_str = "LPX1000 10Gb PCI-X";
break;
case PCI_DEVICE_ID_PFLY:
- strcpy(str, "LP982 2");
+ model_str = "LP982 2Gb PCI-X";
break;
case PCI_DEVICE_ID_TFLY:
if (hdrtype == 0x80)
- strcpy(str, "LP1050DC 2");
+ model_str = "LP1050DC 2Gb 2-port PCI-X";
else
- strcpy(str, "LP1050 2");
+ model_str = "LP1050 2Gb PCI-X";
break;
case PCI_DEVICE_ID_HELIOS:
if (hdrtype == 0x80)
- strcpy(str, "LP11002 4");
+ model_str = "LP11002 4Gb 2-port PCI-X2";
+ else
+ model_str = "LP11000 4Gb PCI-X2";
+ break;
+ case PCI_DEVICE_ID_HELIOS_SCSP:
+ model_str = "LP11000-SP 4Gb PCI-X2";
+ break;
+ case PCI_DEVICE_ID_HELIOS_DCSP:
+ model_str = "LP11002-SP 4Gb 2-port PCI-X2";
+ break;
+ case PCI_DEVICE_ID_NEPTUNE:
+ if (hdrtype == 0x80)
+ model_str = "LPe1002 4Gb 2-port";
else
- strcpy(str, "LP11000 4");
+ model_str = "LPe1000 4Gb PCIe";
+ break;
+ case PCI_DEVICE_ID_NEPTUNE_SCSP:
+ model_str = "LPe1000-SP 4Gb PCIe";
+ break;
+ case PCI_DEVICE_ID_NEPTUNE_DCSP:
+ model_str = "LPe1002-SP 4Gb 2-port PCIe";
break;
case PCI_DEVICE_ID_BMID:
- strcpy(str, "LP1150 4");
+ model_str = "LP1150 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_BSMB:
- strcpy(str, "LP111 4");
+ model_str = "LP111 4Gb PCI-X2";
break;
case PCI_DEVICE_ID_ZEPHYR:
if (hdrtype == 0x80)
- strcpy(str, "LPe11002 4");
+ model_str = "LPe11002 4Gb 2-port PCIe";
else
- strcpy(str, "LPe11000 4");
+ model_str = "LPe11000 4Gb PCIe";
+ break;
+ case PCI_DEVICE_ID_ZEPHYR_SCSP:
+ model_str = "LPe11000-SP 4Gb PCIe";
+ break;
+ case PCI_DEVICE_ID_ZEPHYR_DCSP:
+ model_str = "LPe11002-SP 4Gb 2-port PCIe";
break;
case PCI_DEVICE_ID_ZMID:
- strcpy(str, "LPe1150 4");
+ model_str = "LPe1150 4Gb PCIe";
break;
case PCI_DEVICE_ID_ZSMB:
- strcpy(str, "LPe111 4");
+ model_str = "LPe111 4Gb PCIe";
break;
case PCI_DEVICE_ID_LP101:
- strcpy(str, "LP101 2");
+ model_str = "LP101 2Gb PCI-X";
break;
case PCI_DEVICE_ID_LP10000S:
- strcpy(str, "LP10000-S 2");
+ model_str = "LP10000-S 2Gb PCI";
+ break;
+ case PCI_DEVICE_ID_LP11000S:
+ case PCI_DEVICE_ID_LPE11000S:
+ switch (dev_subid) {
+ case PCI_SUBSYSTEM_ID_LP11000S:
+ model_str = "LP11002-S 4Gb PCI-X2";
+ break;
+ case PCI_SUBSYSTEM_ID_LP11002S:
+ model_str = "LP11000-S 4Gb 2-port PCI-X2";
+ break;
+ case PCI_SUBSYSTEM_ID_LPE11000S:
+ model_str = "LPe11002-S 4Gb PCIe";
+ break;
+ case PCI_SUBSYSTEM_ID_LPE11002S:
+ model_str = "LPe11002-S 4Gb 2-port PCIe";
+ break;
+ case PCI_SUBSYSTEM_ID_LPE11010S:
+ model_str = "LPe11010-S 4Gb 10-port PCIe";
+ break;
+ default:
+ break;
+ }
break;
default:
- memset(str, 0, 16);
break;
}
if (mdp)
- sscanf(str, "%s", mdp);
+ sscanf(model_str, "%s", mdp);
if (descp)
- sprintf(descp, "Emulex LightPulse %s Gigabit PCI Fibre "
- "Channel Adapter", str);
+ sprintf(descp, "Emulex %s Fibre Channel Adapter", model_str);
}
/**************************************************/
@@ -1196,6 +1237,7 @@ lpfc_stop_timer(struct lpfc_hba * phba)
}
}
+ del_timer_sync(&phba->fcp_poll_timer);
del_timer_sync(&phba->fc_estabtmo);
del_timer_sync(&phba->fc_disctmo);
del_timer_sync(&phba->fc_fdmitmo);
@@ -1351,7 +1393,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
goto out_put_host;
host->unique_id = phba->brd_no;
-
+ init_MUTEX(&phba->hba_can_block);
INIT_LIST_HEAD(&phba->ctrspbuflist);
INIT_LIST_HEAD(&phba->rnidrspbuflist);
INIT_LIST_HEAD(&phba->freebufList);
@@ -1375,6 +1417,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
psli->mbox_tmo.function = lpfc_mbox_timeout;
psli->mbox_tmo.data = (unsigned long)phba;
+ init_timer(&phba->fcp_poll_timer);
+ phba->fcp_poll_timer.function = lpfc_poll_timeout;
+ phba->fcp_poll_timer.data = (unsigned long)phba;
+
/*
* Get all the module params for configuring this host and then
* establish the host parameters.
@@ -1489,6 +1535,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
host->max_cmd_len = 16;
/* Initialize the list of scsi buffers used by driver for scsi IO. */
+ spin_lock_init(&phba->scsi_buf_list_lock);
INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list);
host->transportt = lpfc_transport_template;
@@ -1520,6 +1567,12 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
if (error)
goto out_free_irq;
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+ spin_lock_irq(phba->host->host_lock);
+ lpfc_poll_start_timer(phba);
+ spin_unlock_irq(phba->host->host_lock);
+ }
+
/*
* set fixed host attributes
* Must done after lpfc_sli_hba_setup()
@@ -1679,14 +1732,28 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
+ PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
@@ -1697,6 +1764,10 @@ static struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
+ PCI_ANY_ID, PCI_ANY_ID, },
{ 0 }
};
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 507a6af56f42..fbead786031f 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -55,55 +55,76 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
return (1);
}
-
int
lpfc_check_sparm(struct lpfc_hba * phba,
struct lpfc_nodelist * ndlp, struct serv_parm * sp,
uint32_t class)
{
volatile struct serv_parm *hsp = &phba->fc_sparam;
- /* First check for supported version */
-
- /* Next check for class validity */
+ uint16_t hsp_value, ssp_value = 0;
+
+ /*
+ * The receive data field size and buffer-to-buffer receive data field
+ * size entries are 16 bits but are represented as two 8-bit fields in
+ * the driver data structure to account for rsvd bits and other control
+ * bits. Reconstruct and compare the fields as a 16-bit values before
+ * correcting the byte values.
+ */
if (sp->cls1.classValid) {
-
- if (sp->cls1.rcvDataSizeMsb > hsp->cls1.rcvDataSizeMsb)
- sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
- if (sp->cls1.rcvDataSizeLsb > hsp->cls1.rcvDataSizeLsb)
+ hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
+ hsp->cls1.rcvDataSizeLsb;
+ ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
+ sp->cls1.rcvDataSizeLsb;
+ if (ssp_value > hsp_value) {
sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
+ sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
+ }
} else if (class == CLASS1) {
- return (0);
+ return 0;
}
if (sp->cls2.classValid) {
-
- if (sp->cls2.rcvDataSizeMsb > hsp->cls2.rcvDataSizeMsb)
- sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
- if (sp->cls2.rcvDataSizeLsb > hsp->cls2.rcvDataSizeLsb)
+ hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
+ hsp->cls2.rcvDataSizeLsb;
+ ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
+ sp->cls2.rcvDataSizeLsb;
+ if (ssp_value > hsp_value) {
sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
+ sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
+ }
} else if (class == CLASS2) {
- return (0);
+ return 0;
}
if (sp->cls3.classValid) {
-
- if (sp->cls3.rcvDataSizeMsb > hsp->cls3.rcvDataSizeMsb)
- sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
- if (sp->cls3.rcvDataSizeLsb > hsp->cls3.rcvDataSizeLsb)
+ hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
+ hsp->cls3.rcvDataSizeLsb;
+ ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
+ sp->cls3.rcvDataSizeLsb;
+ if (ssp_value > hsp_value) {
sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
+ sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
+ }
} else if (class == CLASS3) {
- return (0);
+ return 0;
}
- if (sp->cmn.bbRcvSizeMsb > hsp->cmn.bbRcvSizeMsb)
- sp->cmn.bbRcvSizeMsb = hsp->cmn.bbRcvSizeMsb;
- if (sp->cmn.bbRcvSizeLsb > hsp->cmn.bbRcvSizeLsb)
+ /*
+ * Preserve the upper four bits of the MSB from the PLOGI response.
+ * These bits contain the Buffer-to-Buffer State Change Number
+ * from the target and need to be passed to the FW.
+ */
+ hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
+ ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
+ if (ssp_value > hsp_value) {
sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
+ sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
+ (hsp->cmn.bbRcvSizeMsb & 0x0F);
+ }
- /* If check is good, copy wwpn wwnn into ndlp */
memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
- return (1);
+ return 1;
}
static void *
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c63275e66e2e..dafabeefc5b3 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -41,6 +41,20 @@
#define LPFC_ABORT_WAIT 2
+static inline void
+lpfc_block_requests(struct lpfc_hba * phba)
+{
+ down(&phba->hba_can_block);
+ scsi_block_requests(phba->host);
+}
+
+static inline void
+lpfc_unblock_requests(struct lpfc_hba * phba)
+{
+ scsi_unblock_requests(phba->host);
+ up(&phba->hba_can_block);
+}
+
/*
* This routine allocates a scsi buffer, which contains all the necessary
* information needed to initiate a SCSI I/O. The non-DMAable buffer region
@@ -136,19 +150,23 @@ lpfc_new_scsi_buf(struct lpfc_hba * phba)
return psb;
}
-struct lpfc_scsi_buf*
-lpfc_sli_get_scsi_buf(struct lpfc_hba * phba)
+static struct lpfc_scsi_buf*
+lpfc_get_scsi_buf(struct lpfc_hba * phba)
{
struct lpfc_scsi_buf * lpfc_cmd = NULL;
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+ unsigned long iflag = 0;
+ spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
return lpfc_cmd;
}
static void
lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
{
+ unsigned long iflag = 0;
/*
* There are only two special cases to consider. (1) the scsi command
* requested scatter-gather usage or (2) the scsi command allocated
@@ -166,8 +184,10 @@ lpfc_release_scsi_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
}
}
+ spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
psb->pCmd = NULL;
list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
}
static int
@@ -389,7 +409,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
- unsigned long iflag;
+ int result;
+ struct scsi_device *sdev, *tmp_sdev;
+ int depth = 0;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
@@ -441,11 +463,64 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
*lp, *(lp + 3), cmd->retries, cmd->resid);
}
+ result = cmd->result;
+ sdev = cmd->device;
cmd->scsi_done(cmd);
- spin_lock_irqsave(phba->host->host_lock, iflag);
+ if (!result &&
+ ((jiffies - pnode->last_ramp_up_time) >
+ LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+ ((jiffies - pnode->last_q_full_time) >
+ LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
+ (phba->cfg_lun_queue_depth > sdev->queue_depth)) {
+ shost_for_each_device(tmp_sdev, sdev->host) {
+ if (phba->cfg_lun_queue_depth > tmp_sdev->queue_depth) {
+ if (tmp_sdev->id != sdev->id)
+ continue;
+ if (tmp_sdev->ordered_tags)
+ scsi_adjust_queue_depth(tmp_sdev,
+ MSG_ORDERED_TAG,
+ tmp_sdev->queue_depth+1);
+ else
+ scsi_adjust_queue_depth(tmp_sdev,
+ MSG_SIMPLE_TAG,
+ tmp_sdev->queue_depth+1);
+
+ pnode->last_ramp_up_time = jiffies;
+ }
+ }
+ }
+
+ /*
+ * Check for queue full. If the lun is reporting queue full, then
+ * back off the lun queue depth to prevent target overloads.
+ */
+ if (result == SAM_STAT_TASK_SET_FULL) {
+ pnode->last_q_full_time = jiffies;
+
+ shost_for_each_device(tmp_sdev, sdev->host) {
+ if (tmp_sdev->id != sdev->id)
+ continue;
+ depth = scsi_track_queue_full(tmp_sdev,
+ tmp_sdev->queue_depth - 1);
+ }
+ /*
+ * The queue depth cannot be lowered any more.
+ * Modify the returned error code to store
+ * the final depth value set by
+ * scsi_track_queue_full.
+ */
+ if (depth == -1)
+ depth = sdev->host->cmd_per_lun;
+
+ if (depth) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
+ "%d:0711 detected queue full - lun queue depth "
+ " adjusted to %d.\n", phba->brd_no, depth);
+ }
+ }
+
lpfc_release_scsi_buf(phba, lpfc_cmd);
- spin_unlock_irqrestore(phba->host->host_lock, iflag);
}
static void
@@ -693,6 +768,37 @@ lpfc_info(struct Scsi_Host *host)
return lpfcinfobuf;
}
+static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
+{
+ unsigned long poll_tmo_expires =
+ (jiffies + msecs_to_jiffies(phba->cfg_poll_tmo));
+
+ if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt)
+ mod_timer(&phba->fcp_poll_timer,
+ poll_tmo_expires);
+}
+
+void lpfc_poll_start_timer(struct lpfc_hba * phba)
+{
+ lpfc_poll_rearm_timer(phba);
+}
+
+void lpfc_poll_timeout(unsigned long ptr)
+{
+ struct lpfc_hba *phba = (struct lpfc_hba *)ptr;
+ unsigned long iflag;
+
+ spin_lock_irqsave(phba->host->host_lock, iflag);
+
+ if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+ lpfc_sli_poll_fcp_ring (phba);
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+ lpfc_poll_rearm_timer(phba);
+ }
+
+ spin_unlock_irqrestore(phba->host->host_lock, iflag);
+}
+
static int
lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
{
@@ -719,10 +825,11 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
goto out_fail_command;
}
- lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+ lpfc_cmd = lpfc_get_scsi_buf (phba);
if (lpfc_cmd == NULL) {
- printk(KERN_WARNING "%s: No buffer available - list empty, "
- "total count %d\n", __FUNCTION__, phba->total_scsi_bufs);
+ lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+ "%d:0707 driver's buffer pool is empty, "
+ "IO busied\n", phba->brd_no);
goto out_host_busy;
}
@@ -746,11 +853,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
if (err)
goto out_host_busy_free_buf;
+
+ if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+ lpfc_sli_poll_fcp_ring(phba);
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+ lpfc_poll_rearm_timer(phba);
+ }
+
return 0;
out_host_busy_free_buf:
lpfc_release_scsi_buf(phba, lpfc_cmd);
- cmnd->host_scribble = NULL;
out_host_busy:
return SCSI_MLQUEUE_HOST_BUSY;
@@ -759,11 +872,12 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
return 0;
}
+
static int
-__lpfc_abort_handler(struct scsi_cmnd *cmnd)
+lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
- struct lpfc_hba *phba =
- (struct lpfc_hba *)cmnd->device->host->hostdata[0];
+ struct Scsi_Host *shost = cmnd->device->host;
+ struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
struct lpfc_sli_ring *pring = &phba->sli.ring[phba->sli.fcp_ring];
struct lpfc_iocbq *iocb;
struct lpfc_iocbq *abtsiocb;
@@ -772,6 +886,8 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
unsigned int loop_count = 0;
int ret = SUCCESS;
+ lpfc_block_requests(phba);
+ spin_lock_irq(shost->host_lock);
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
BUG_ON(!lpfc_cmd);
@@ -821,9 +937,15 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
goto out;
}
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+ lpfc_sli_poll_fcp_ring (phba);
+
/* Wait for abort to complete */
while (lpfc_cmd->pCmd == cmnd)
{
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+ lpfc_sli_poll_fcp_ring (phba);
+
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
@@ -844,26 +966,19 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
out:
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
- "%d:0749 SCSI layer issued abort device: ret %#x, "
- "ID %d, LUN %d, snum %#lx\n",
+ "%d:0749 SCSI Layer I/O Abort Request "
+ "Status x%x ID %d LUN %d snum %#lx\n",
phba->brd_no, ret, cmnd->device->id,
cmnd->device->lun, cmnd->serial_number);
- return ret;
-}
+ spin_unlock_irq(shost->host_lock);
+ lpfc_unblock_requests(phba);
-static int
-lpfc_abort_handler(struct scsi_cmnd *cmnd)
-{
- int rc;
- spin_lock_irq(cmnd->device->host->host_lock);
- rc = __lpfc_abort_handler(cmnd);
- spin_unlock_irq(cmnd->device->host->host_lock);
- return rc;
+ return ret;
}
static int
-__lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -871,9 +986,12 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
struct lpfc_iocbq *iocbq, *iocbqrsp;
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *pnode = rdata->pnode;
+ uint32_t cmd_result = 0, cmd_status = 0;
int ret = FAILED;
int cnt, loopcnt;
+ lpfc_block_requests(phba);
+ spin_lock_irq(shost->host_lock);
/*
* If target is not in a MAPPED state, delay the reset until
* target is rediscovered or nodev timeout expires.
@@ -891,7 +1009,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
break;
}
- lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+ lpfc_cmd = lpfc_get_scsi_buf (phba);
if (lpfc_cmd == NULL)
goto out;
@@ -916,26 +1034,28 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (ret == IOCB_SUCCESS)
ret = SUCCESS;
- lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
- lpfc_cmd->status = iocbqrsp->iocb.ulpStatus;
- if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT)
- if (lpfc_cmd->result & IOERR_DRVR_MASK)
- lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
+
+ cmd_result = iocbqrsp->iocb.un.ulpWord[4];
+ cmd_status = iocbqrsp->iocb.ulpStatus;
+
+ lpfc_sli_release_iocbq(phba, iocbqrsp);
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
/*
- * All outstanding txcmplq I/Os should have been aborted by the target.
+ * All outstanding txcmplq I/Os should have been aborted by the device.
* Unfortunately, some targets do not abide by this forcing the driver
* to double check.
*/
- lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
- cmnd->device->id, cmnd->device->lun, 0,
- LPFC_CTX_LUN);
-
+ cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+ cmnd->device->id, cmnd->device->lun,
+ LPFC_CTX_LUN);
+ if (cnt)
+ lpfc_sli_abort_iocb(phba,
+ &phba->sli.ring[phba->sli.fcp_ring],
+ cmnd->device->id, cmnd->device->lun,
+ 0, LPFC_CTX_LUN);
loopcnt = 0;
- while((cnt = lpfc_sli_sum_iocb(phba,
- &phba->sli.ring[phba->sli.fcp_ring],
- cmnd->device->id, cmnd->device->lun,
- LPFC_CTX_LUN))) {
+ while(cnt) {
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
@@ -943,6 +1063,11 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (++loopcnt
> (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
break;
+
+ cnt = lpfc_sli_sum_iocb(phba,
+ &phba->sli.ring[phba->sli.fcp_ring],
+ cmnd->device->id, cmnd->device->lun,
+ LPFC_CTX_LUN);
}
if (cnt) {
@@ -952,35 +1077,21 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
ret = FAILED;
}
- lpfc_sli_release_iocbq(phba, iocbqrsp);
-
out_free_scsi_buf:
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
"Data: x%x x%x x%x\n",
- phba->brd_no, lpfc_cmd->pCmd->device->id,
- lpfc_cmd->pCmd->device->lun, ret, lpfc_cmd->status,
- lpfc_cmd->result);
- lpfc_release_scsi_buf(phba, lpfc_cmd);
+ phba->brd_no, cmnd->device->id,cmnd->device->lun,
+ ret, cmd_status, cmd_result);
+
out:
+ spin_unlock_irq(shost->host_lock);
+ lpfc_unblock_requests(phba);
return ret;
}
static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
-{
- int rc;
- spin_lock_irq(cmnd->device->host->host_lock);
- rc = __lpfc_reset_lun_handler(cmnd);
- spin_unlock_irq(cmnd->device->host->host_lock);
- return rc;
-}
-
-/*
- * Note: midlayer calls this function with the host_lock held
- */
-static int
-__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -991,7 +1102,10 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
unsigned int midlayer_id = 0;
struct lpfc_scsi_buf * lpfc_cmd;
- lpfc_cmd = lpfc_sli_get_scsi_buf (phba);
+ lpfc_block_requests(phba);
+ spin_lock_irq(shost->host_lock);
+
+ lpfc_cmd = lpfc_get_scsi_buf(phba);
if (lpfc_cmd == NULL)
goto out;
@@ -1022,18 +1136,31 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
lpfc_cmd->pCmd->device->hostdata = ndlp->rport->dd_data;
ret = lpfc_scsi_tgt_reset(lpfc_cmd, phba);
if (ret != SUCCESS) {
- lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0713 Bus Reset on target %d failed\n",
phba->brd_no, i);
err_count++;
}
}
+ if (err_count == 0)
+ ret = SUCCESS;
+
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+
+ /*
+ * All outstanding txcmplq I/Os should have been aborted by
+ * the targets. Unfortunately, some targets do not abide by
+ * this forcing the driver to double check.
+ */
cmnd->device->id = midlayer_id;
+ cnt = lpfc_sli_sum_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+ 0, 0, LPFC_CTX_HOST);
+ if (cnt)
+ lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring],
+ 0, 0, 0, LPFC_CTX_HOST);
loopcnt = 0;
- while((cnt = lpfc_sli_sum_iocb(phba,
- &phba->sli.ring[phba->sli.fcp_ring],
- 0, 0, LPFC_CTX_HOST))) {
+ while(cnt) {
spin_unlock_irq(phba->host->host_lock);
schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
@@ -1041,45 +1168,31 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
if (++loopcnt
> (2 * phba->cfg_nodev_tmo)/LPFC_RESET_WAIT)
break;
+
+ cnt = lpfc_sli_sum_iocb(phba,
+ &phba->sli.ring[phba->sli.fcp_ring],
+ 0, 0, LPFC_CTX_HOST);
}
if (cnt) {
- /* flush all outstanding commands on the host */
- i = lpfc_sli_abort_iocb(phba,
- &phba->sli.ring[phba->sli.fcp_ring], 0, 0, 0,
- LPFC_CTX_HOST);
-
- lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
+ lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
"%d:0715 Bus Reset I/O flush failure: cnt x%x left x%x\n",
phba->brd_no, cnt, i);
- }
-
- if (cnt == 0)
- ret = SUCCESS;
- else
ret = FAILED;
+ }
- lpfc_release_scsi_buf(phba, lpfc_cmd);
lpfc_printf_log(phba,
KERN_ERR,
LOG_FCP,
"%d:0714 SCSI layer issued Bus Reset Data: x%x\n",
phba->brd_no, ret);
out:
+ spin_unlock_irq(shost->host_lock);
+ lpfc_unblock_requests(phba);
return ret;
}
static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
-{
- int rc;
- spin_lock_irq(cmnd->device->host->host_lock);
- rc = __lpfc_reset_bus_handler(cmnd);
- spin_unlock_irq(cmnd->device->host->host_lock);
- return rc;
-}
-
-static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
@@ -1127,10 +1240,10 @@ lpfc_slave_alloc(struct scsi_device *sdev)
break;
}
- spin_lock_irqsave(phba->host->host_lock, flags);
+ spin_lock_irqsave(&phba->scsi_buf_list_lock, flags);
phba->total_scsi_bufs++;
list_add_tail(&scsi_buf->list, &phba->lpfc_scsi_buf_list);
- spin_unlock_irqrestore(phba->host->host_lock, flags);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_lock, flags);
}
return 0;
}
@@ -1154,6 +1267,12 @@ lpfc_slave_configure(struct scsi_device *sdev)
*/
rport->dev_loss_tmo = phba->cfg_nodev_tmo + 5;
+ if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
+ lpfc_sli_poll_fcp_ring(phba);
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT)
+ lpfc_poll_rearm_timer(phba);
+ }
+
return 0;
}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e2c08c5d83fb..7b785ade8b07 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -886,6 +886,182 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
return rc;
}
+static void lpfc_sli_rsp_pointers_error(struct lpfc_hba * phba,
+ struct lpfc_sli_ring * pring)
+{
+ struct lpfc_pgp *pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+ /*
+ * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+ * rsp ring <portRspMax>
+ */
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "%d:0312 Ring %d handler: portRspPut %d "
+ "is bigger then rsp ring %d\n",
+ phba->brd_no, pring->ringno,
+ le32_to_cpu(pgp->rspPutInx),
+ pring->numRiocb);
+
+ phba->hba_state = LPFC_HBA_ERROR;
+
+ /*
+ * All error attention handlers are posted to
+ * worker thread
+ */
+ phba->work_ha |= HA_ERATT;
+ phba->work_hs = HS_FFER3;
+ if (phba->work_wait)
+ wake_up(phba->work_wait);
+
+ return;
+}
+
+void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba)
+{
+ struct lpfc_sli * psli = &phba->sli;
+ struct lpfc_sli_ring * pring = &psli->ring[LPFC_FCP_RING];
+ IOCB_t *irsp = NULL;
+ IOCB_t *entry = NULL;
+ struct lpfc_iocbq *cmdiocbq = NULL;
+ struct lpfc_iocbq rspiocbq;
+ struct lpfc_pgp *pgp;
+ uint32_t status;
+ uint32_t portRspPut, portRspMax;
+ int type;
+ uint32_t rsp_cmpl = 0;
+ void __iomem *to_slim;
+ uint32_t ha_copy;
+
+ pring->stats.iocb_event++;
+
+ /* The driver assumes SLI-2 mode */
+ pgp = &phba->slim2p->mbx.us.s2.port[pring->ringno];
+
+ /*
+ * The next available response entry should never exceed the maximum
+ * entries. If it does, treat it as an adapter hardware error.
+ */
+ portRspMax = pring->numRiocb;
+ portRspPut = le32_to_cpu(pgp->rspPutInx);
+ if (unlikely(portRspPut >= portRspMax)) {
+ lpfc_sli_rsp_pointers_error(phba, pring);
+ return;
+ }
+
+ rmb();
+ while (pring->rspidx != portRspPut) {
+
+ entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+
+ if (++pring->rspidx >= portRspMax)
+ pring->rspidx = 0;
+
+ lpfc_sli_pcimem_bcopy((uint32_t *) entry,
+ (uint32_t *) &rspiocbq.iocb,
+ sizeof (IOCB_t));
+ irsp = &rspiocbq.iocb;
+ type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
+ pring->stats.iocb_rsp++;
+ rsp_cmpl++;
+
+ if (unlikely(irsp->ulpStatus)) {
+ /* Rsp ring <ringno> error: IOCB */
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "%d:0326 Rsp Ring %d error: IOCB Data: "
+ "x%x x%x x%x x%x x%x x%x x%x x%x\n",
+ phba->brd_no, pring->ringno,
+ irsp->un.ulpWord[0],
+ irsp->un.ulpWord[1],
+ irsp->un.ulpWord[2],
+ irsp->un.ulpWord[3],
+ irsp->un.ulpWord[4],
+ irsp->un.ulpWord[5],
+ *(((uint32_t *) irsp) + 6),
+ *(((uint32_t *) irsp) + 7));
+ }
+
+ switch (type) {
+ case LPFC_ABORT_IOCB:
+ case LPFC_SOL_IOCB:
+ /*
+ * Idle exchange closed via ABTS from port. No iocb
+ * resources need to be recovered.
+ */
+ if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
+ printk(KERN_INFO "%s: IOCB cmd 0x%x processed."
+ " Skipping completion\n", __FUNCTION__,
+ irsp->ulpCommand);
+ break;
+ }
+
+ cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
+ &rspiocbq);
+ if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
+ (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+ &rspiocbq);
+ }
+ break;
+ default:
+ if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
+ char adaptermsg[LPFC_MAX_ADPTMSG];
+ memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
+ memcpy(&adaptermsg[0], (uint8_t *) irsp,
+ MAX_MSG_DATA);
+ dev_warn(&((phba->pcidev)->dev), "lpfc%d: %s",
+ phba->brd_no, adaptermsg);
+ } else {
+ /* Unknown IOCB command */
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "%d:0321 Unknown IOCB command "
+ "Data: x%x, x%x x%x x%x x%x\n",
+ phba->brd_no, type,
+ irsp->ulpCommand,
+ irsp->ulpStatus,
+ irsp->ulpIoTag,
+ irsp->ulpContext);
+ }
+ break;
+ }
+
+ /*
+ * The response IOCB has been processed. Update the ring
+ * pointer in SLIM. If the port response put pointer has not
+ * been updated, sync the pgp->rspPutInx and fetch the new port
+ * response put pointer.
+ */
+ to_slim = phba->MBslimaddr +
+ (SLIMOFF + (pring->ringno * 2) + 1) * 4;
+ writeb(pring->rspidx, to_slim);
+
+ if (pring->rspidx == portRspPut)
+ portRspPut = le32_to_cpu(pgp->rspPutInx);
+ }
+
+ ha_copy = readl(phba->HAregaddr);
+ ha_copy >>= (LPFC_FCP_RING * 4);
+
+ if ((rsp_cmpl > 0) && (ha_copy & HA_R0RE_REQ)) {
+ pring->stats.iocb_rsp_full++;
+ status = ((CA_R0ATT | CA_R0RE_RSP) << (LPFC_FCP_RING * 4));
+ writel(status, phba->CAregaddr);
+ readl(phba->CAregaddr);
+ }
+ if ((ha_copy & HA_R0CE_RSP) &&
+ (pring->flag & LPFC_CALL_RING_AVAILABLE)) {
+ pring->flag &= ~LPFC_CALL_RING_AVAILABLE;
+ pring->stats.iocb_cmd_empty++;
+
+ /* Force update of the local copy of cmdGetInx */
+ pring->local_getidx = le32_to_cpu(pgp->cmdGetInx);
+ lpfc_sli_resume_iocb(phba, pring);
+
+ if ((pring->lpfc_sli_cmd_available))
+ (pring->lpfc_sli_cmd_available) (phba, pring);
+
+ }
+
+ return;
+}
+
/*
* This routine presumes LPFC_FCP_RING handling and doesn't bother
* to check it explicitly.
@@ -917,24 +1093,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
portRspMax = pring->numRiocb;
portRspPut = le32_to_cpu(pgp->rspPutInx);
if (unlikely(portRspPut >= portRspMax)) {
- /*
- * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
- * rsp ring <portRspMax>
- */
- lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "%d:0312 Ring %d handler: portRspPut %d "
- "is bigger then rsp ring %d\n",
- phba->brd_no, pring->ringno, portRspPut,
- portRspMax);
-
- phba->hba_state = LPFC_HBA_ERROR;
-
- /* All error attention handlers are posted to worker thread */
- phba->work_ha |= HA_ERATT;
- phba->work_hs = HS_FFER3;
- if (phba->work_wait)
- wake_up(phba->work_wait);
-
+ lpfc_sli_rsp_pointers_error(phba, pring);
spin_unlock_irqrestore(phba->host->host_lock, iflag);
return 1;
}
@@ -947,6 +1106,10 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
* network byte order and pci byte orders are different.
*/
entry = IOCB_ENTRY(pring->rspringaddr, pring->rspidx);
+
+ if (++pring->rspidx >= portRspMax)
+ pring->rspidx = 0;
+
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
(uint32_t *) &rspiocbq.iocb,
sizeof (IOCB_t));
@@ -1020,9 +1183,6 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
* been updated, sync the pgp->rspPutInx and fetch the new port
* response put pointer.
*/
- if (++pring->rspidx >= portRspMax)
- pring->rspidx = 0;
-
to_slim = phba->MBslimaddr +
(SLIMOFF + (pring->ringno * 2) + 1) * 4;
writel(pring->rspidx, to_slim);
@@ -2615,6 +2775,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
DECLARE_WAIT_QUEUE_HEAD(done_q);
long timeleft, timeout_req = 0;
int retval = IOCB_SUCCESS;
+ uint32_t creg_val;
/*
* If the caller has provided a response iocbq buffer, then context2
@@ -2630,6 +2791,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
piocb->context_un.wait_queue = &done_q;
piocb->iocb_flag &= ~LPFC_IO_WAKE;
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+ creg_val = readl(phba->HCregaddr);
+ creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
+ writel(creg_val, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+ }
+
retval = lpfc_sli_issue_iocb(phba, pring, piocb, 0);
if (retval == IOCB_SUCCESS) {
timeout_req = timeout * HZ;
@@ -2663,6 +2831,13 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
retval = IOCB_ERROR;
}
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+ creg_val = readl(phba->HCregaddr);
+ creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+ writel(creg_val, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+ }
+
if (prspiocbq)
piocb->context2 = NULL;
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 4f0466fbd5f2..fa681a934ffe 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.1.0"
+#define LPFC_DRIVER_VERSION "8.1.1"
#define LPFC_DRIVER_NAME "lpfc"
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 932dcf0366eb..311a4122bd70 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -432,11 +432,12 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
struct Scsi_Host *host;
void *dma_cmd_space;
unsigned char *clkprop;
- int proplen;
+ int proplen, rc = -ENODEV;
if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
- printk(KERN_ERR "mac53c94: expected 2 addrs and intrs (got %d/%d)\n",
- node->n_addrs, node->n_intrs);
+ printk(KERN_ERR "mac53c94: expected 2 addrs and intrs"
+ " (got %d/%d)\n",
+ macio_resource_count(mdev), macio_irq_count(mdev));
return -ENODEV;
}
@@ -448,6 +449,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state));
if (host == NULL) {
printk(KERN_ERR "mac53c94: couldn't register host");
+ rc = -ENOMEM;
goto out_release;
}
@@ -486,6 +488,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
if (dma_cmd_space == 0) {
printk(KERN_ERR "mac53c94: couldn't allocate dma "
"command space for %s\n", node->full_name);
+ rc = -ENOMEM;
goto out_free;
}
state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space);
@@ -495,18 +498,21 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
mac53c94_init(state);
- if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94", state)) {
+ if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94",state)) {
printk(KERN_ERR "mac53C94: can't get irq %d for %s\n",
state->intr, node->full_name);
goto out_free_dma;
}
- /* XXX FIXME: handle failure */
- scsi_add_host(host, &mdev->ofdev.dev);
- scsi_scan_host(host);
+ rc = scsi_add_host(host, &mdev->ofdev.dev);
+ if (rc != 0)
+ goto out_release_irq;
+ scsi_scan_host(host);
return 0;
+ out_release_irq:
+ free_irq(state->intr, state);
out_free_dma:
kfree(state->dma_cmd_space);
out_free:
@@ -518,7 +524,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
out_release:
macio_release_resources(mdev);
- return -ENODEV;
+ return rc;
}
static int mac53c94_remove(struct macio_dev *mdev)
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 578143e93a6f..d101a8a6f4e8 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -2,7 +2,7 @@
*
* Linux MegaRAID device driver
*
- * Copyright © 2002 LSI Logic Corporation.
+ * Copyright (c) 2002 LSI Logic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,7 +17,8 @@
* Copyright (c) 2003 Christoph Hellwig <hch@lst.de>
* - new-style, hotplug-aware pci probing and scsi registration
*
- * Version : v2.00.3 (Feb 19, 2003) - Atul Mukker <Atul.Mukker@lsil.com>
+ * Version : v2.00.4 Mon Nov 14 14:02:43 EST 2005 - Seokmann Ju
+ * <Seokmann.Ju@lsil.com>
*
* Description: Linux device driver for LSI Logic MegaRAID controller
*
@@ -51,10 +52,10 @@
#include "megaraid.h"
-#define MEGARAID_MODULE_VERSION "2.00.3"
+#define MEGARAID_MODULE_VERSION "2.00.4"
-MODULE_AUTHOR ("LSI Logic Corporation");
-MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
+MODULE_AUTHOR ("sju@lsil.com");
+MODULE_DESCRIPTION ("LSI Logic MegaRAID legacy driver");
MODULE_LICENSE ("GPL");
MODULE_VERSION(MEGARAID_MODULE_VERSION);
@@ -4478,7 +4479,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
* serialized. This is so because we want to reserve maximum number of
* available command ids for the I/O commands.
*/
- down(&adapter->int_mtx);
+ mutex_lock(&adapter->int_mtx);
scb = &adapter->int_scb;
memset(scb, 0, sizeof(scb_t));
@@ -4526,7 +4527,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru)
mc->cmd, mc->opcode, mc->subopcode, scmd->result);
}
- up(&adapter->int_mtx);
+ mutex_unlock(&adapter->int_mtx);
return rval;
}
@@ -4553,7 +4554,7 @@ mega_internal_done(Scsi_Cmnd *scmd)
static struct scsi_host_template megaraid_template = {
.module = THIS_MODULE,
.name = "MegaRAID",
- .proc_name = "megaraid",
+ .proc_name = "megaraid_legacy",
.info = megaraid_info,
.queuecommand = megaraid_queue,
.bios_param = megaraid_biosparam,
@@ -4865,7 +4866,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->has_64bit_addr = 0;
}
- init_MUTEX(&adapter->int_mtx);
+ mutex_init(&adapter->int_mtx);
init_completion(&adapter->int_waitq);
adapter->this_id = DEFAULT_INITIATOR_ID;
@@ -5037,22 +5038,12 @@ megaraid_shutdown(struct pci_dev *pdev)
}
static struct pci_device_id megaraid_pci_tbl[] = {
- {PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DISCOVERY,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_PERC4_DI,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
- {PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_PERC4_QC_VERDE,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, BOARD_64BIT},
{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_AMI_MEGARAID3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, megaraid_pci_tbl);
@@ -5095,7 +5086,7 @@ static int __init megaraid_init(void)
* First argument (major) to register_chrdev implies a dynamic
* major number allocation.
*/
- major = register_chrdev(0, "megadev", &megadev_fops);
+ major = register_chrdev(0, "megadev_legacy", &megadev_fops);
if (!major) {
printk(KERN_WARNING
"megaraid: failed to register char device\n");
@@ -5109,7 +5100,7 @@ static void __exit megaraid_exit(void)
/*
* Unregister the character device interface to the driver.
*/
- unregister_chrdev(major, "megadev");
+ unregister_chrdev(major, "megadev_legacy");
pci_unregister_driver(&megaraid_pci_driver);
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
index 6f9078025748..4b3e0d6e5afa 100644
--- a/drivers/scsi/megaraid.h
+++ b/drivers/scsi/megaraid.h
@@ -2,7 +2,7 @@
#define __MEGARAID_H__
#include <linux/spinlock.h>
-
+#include <linux/mutex.h>
#define MEGARAID_VERSION \
"v2.00.3 (Release Date: Wed Feb 19 08:51:30 EST 2003)\n"
@@ -889,7 +889,7 @@ typedef struct {
scb_t int_scb;
Scsi_Cmnd int_scmd;
- struct semaphore int_mtx; /* To synchronize the internal
+ struct mutex int_mtx; /* To synchronize the internal
commands */
struct completion int_waitq; /* wait queue for internal
cmds */
diff --git a/drivers/scsi/megaraid/Kconfig.megaraid b/drivers/scsi/megaraid/Kconfig.megaraid
index 7363e12663ac..17419e30ffc8 100644
--- a/drivers/scsi/megaraid/Kconfig.megaraid
+++ b/drivers/scsi/megaraid/Kconfig.megaraid
@@ -64,7 +64,6 @@ config MEGARAID_MAILBOX
To compile this driver as a module, choose M here: the
module will be called megaraid_mbox
-if MEGARAID_NEWGEN=n
config MEGARAID_LEGACY
tristate "LSI Logic Legacy MegaRAID Driver"
depends on PCI && SCSI
@@ -75,7 +74,6 @@ config MEGARAID_LEGACY
To compile this driver as a module, choose M here: the
module will be called megaraid
-endif
config MEGARAID_SAS
tristate "LSI Logic MegaRAID SAS RAID Module"
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 4b5d420d2f4d..bf9f7f7ba354 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,12 +10,13 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_mbox.c
- * Version : v2.20.4.6 (Mar 07 2005)
+ * Version : v2.20.4.7 (Nov 14 2005)
*
* Authors:
* Atul Mukker <Atul.Mukker@lsil.com>
* Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
* Manoj Jose <Manoj.Jose@lsil.com>
+ * Seokmann Ju <Seokmann.Ju@lsil.com>
*
* List of supported controllers
*
@@ -136,7 +137,7 @@ static int wait_till_fw_empty(adapter_t *);
-MODULE_AUTHOR("LSI Logic Corporation");
+MODULE_AUTHOR("sju@lsil.com");
MODULE_DESCRIPTION("LSI Logic MegaRAID Mailbox Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(MEGARAID_VERSION);
@@ -278,68 +279,14 @@ static struct pci_device_id pci_id_table_g[] = {
{
PCI_VENDOR_ID_AMI,
PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC3_QC,
- },
- {
- PCI_VENDOR_ID_AMI,
- PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC3_DC,
- },
- {
- PCI_VENDOR_ID_AMI,
- PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC3_SC,
- },
- {
- PCI_VENDOR_ID_AMI,
- PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_VENDOR_ID_AMI,
- PCI_SUBSYS_ID_PERC3_SC,
- },
- {
- PCI_VENDOR_ID_AMI,
- PCI_DEVICE_ID_AMI_MEGARAID3,
- PCI_VENDOR_ID_AMI,
- PCI_SUBSYS_ID_PERC3_DC,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_0,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_1,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_1,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_2,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_2,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SATA_150_4,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SATA_150_4,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SATA_150_6,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SATA_150_6,
+ PCI_DEVICE_ID_AMI_MEGARAID3,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
@@ -347,18 +294,6 @@ static struct pci_device_id pci_id_table_g[] = {
PCI_ANY_ID,
PCI_ANY_ID,
},
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCS16,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCS16,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
- },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, pci_id_table_g);
@@ -1331,7 +1266,7 @@ megaraid_mbox_teardown_dma_pools(adapter_t *adapter)
* return the scb from the head of the free list. NULL if there are none
* available
**/
-static inline scb_t *
+static scb_t *
megaraid_alloc_scb(adapter_t *adapter, struct scsi_cmnd *scp)
{
struct list_head *head = &adapter->kscb_pool;
@@ -1394,7 +1329,7 @@ megaraid_dealloc_scb(adapter_t *adapter, scb_t *scb)
*
* prepare the scatter-gather list
*/
-static inline int
+static int
megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
{
struct scatterlist *sgl;
@@ -1467,7 +1402,7 @@ megaraid_mbox_mksgl(adapter_t *adapter, scb_t *scb)
*
* post the command to the controller if mailbox is availble.
*/
-static inline int
+static int
mbox_post_cmd(adapter_t *adapter, scb_t *scb)
{
mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2135,7 +2070,7 @@ megaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,
*
* Returns: 1 if the interrupt is valid, 0 otherwise
*/
-static inline int
+static int
megaraid_ack_sequence(adapter_t *adapter)
{
mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
@@ -2273,7 +2208,7 @@ megaraid_isr(int irq, void *devp, struct pt_regs *regs)
*
* DMA sync if required.
*/
-static inline void
+static void
megaraid_mbox_sync_scb(adapter_t *adapter, scb_t *scb)
{
mbox_ccb_t *ccb;
@@ -2985,6 +2920,7 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[])
for (i = 0; i < 0xFFFFF; i++) {
if (mbox->numstatus != 0xFF) break;
+ rmb();
}
if (i == 0xFFFFF) {
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 644b91bdb028..882fb1a0b575 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
#include "megaraid_ioctl.h"
-#define MEGARAID_VERSION "2.20.4.6"
-#define MEGARAID_EXT_VERSION "(Release Date: Mon Mar 07 12:27:22 EST 2005)"
+#define MEGARAID_VERSION "2.20.4.7"
+#define MEGARAID_EXT_VERSION "(Release Date: Mon Nov 14 12:27:22 EST 2005)"
/*
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index eb8c390a0fa3..3d9e67d6849d 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -22,7 +22,6 @@
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <linux/list.h>
-#include <linux/ioctl32.h>
#include "mbox_defs.h"
#include "megaraid_ioctl.h"
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3c32e69afcd9..511ed52a5807 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -35,6 +35,7 @@
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/compat.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, megasas_pci_table);
static int megasas_mgmt_majorno;
static struct megasas_mgmt_info megasas_mgmt_info;
static struct fasync_struct *megasas_async_queue;
-static DECLARE_MUTEX(megasas_async_queue_mutex);
+static DEFINE_MUTEX(megasas_async_queue_mutex);
/**
* megasas_get_cmd - Get a command from the free pool
@@ -80,7 +81,7 @@ static DECLARE_MUTEX(megasas_async_queue_mutex);
*
* Returns a free command from the pool
*/
-static inline struct megasas_cmd *megasas_get_cmd(struct megasas_instance
+static struct megasas_cmd *megasas_get_cmd(struct megasas_instance
*instance)
{
unsigned long flags;
@@ -262,7 +263,7 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance,
* If successful, this function returns the number of SG elements. Otherwise,
* it returnes -1.
*/
-static inline int
+static int
megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
union megasas_sgl *mfi_sgl)
{
@@ -310,7 +311,7 @@ megasas_make_sgl32(struct megasas_instance *instance, struct scsi_cmnd *scp,
* If successful, this function returns the number of SG elements. Otherwise,
* it returnes -1.
*/
-static inline int
+static int
megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
union megasas_sgl *mfi_sgl)
{
@@ -359,7 +360,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
* This function prepares CDB commands. These are typcially pass-through
* commands to the devices.
*/
-static inline int
+static int
megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
struct megasas_cmd *cmd)
{
@@ -440,7 +441,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp,
*
* Frames (and accompanying SGLs) for regular SCSI IOs use this function.
*/
-static inline int
+static int
megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
struct megasas_cmd *cmd)
{
@@ -562,7 +563,7 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp,
* @scp: SCSI command
* @frame_count: [OUT] Number of frames used to prepare this command
*/
-static inline struct megasas_cmd *megasas_build_cmd(struct megasas_instance
+static struct megasas_cmd *megasas_build_cmd(struct megasas_instance
*instance,
struct scsi_cmnd *scp,
int *frame_count)
@@ -913,7 +914,7 @@ megasas_complete_abort(struct megasas_instance *instance,
* @instance: Adapter soft state
* @cmd: Completed command
*/
-static inline void
+static void
megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
{
dma_addr_t buf_h;
@@ -957,7 +958,7 @@ megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
* an alternate status (as in the case of aborted
* commands)
*/
-static inline void
+static void
megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
u8 alt_status)
{
@@ -1104,7 +1105,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
* SCSI mid-layer instead of the status
* returned by the FW
*/
-static inline int
+static int
megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
{
u32 status;
@@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode)
{
int rc;
- down(&megasas_async_queue_mutex);
+ mutex_lock(&megasas_async_queue_mutex);
rc = fasync_helper(fd, filep, mode, &megasas_async_queue);
- up(&megasas_async_queue_mutex);
+ mutex_unlock(&megasas_async_queue_mutex);
if (rc >= 0) {
/* For sanity check when we get ioctl */
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index bdccf73cf9fe..d6d2125f9044 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1869,7 +1869,8 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs"
- " (got %d,%d)\n", mesh->n_addrs, mesh->n_intrs);
+ " (got %d,%d)\n", macio_resource_count(mdev),
+ macio_irq_count(mdev));
return -ENODEV;
}
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 243470936fab..32350707b940 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -131,7 +131,739 @@
#define NAME53C "ncr53c"
#define NAME53C8XX "ncr53c8xx"
-#include "sym53c8xx_comm.h"
+
+/*==========================================================
+**
+** Debugging tags
+**
+**==========================================================
+*/
+
+#define DEBUG_ALLOC (0x0001)
+#define DEBUG_PHASE (0x0002)
+#define DEBUG_QUEUE (0x0008)
+#define DEBUG_RESULT (0x0010)
+#define DEBUG_POINTER (0x0020)
+#define DEBUG_SCRIPT (0x0040)
+#define DEBUG_TINY (0x0080)
+#define DEBUG_TIMING (0x0100)
+#define DEBUG_NEGO (0x0200)
+#define DEBUG_TAGS (0x0400)
+#define DEBUG_SCATTER (0x0800)
+#define DEBUG_IC (0x1000)
+
+/*
+** Enable/Disable debug messages.
+** Can be changed at runtime too.
+*/
+
+#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
+static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
+ #define DEBUG_FLAGS ncr_debug
+#else
+ #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
+#endif
+
+static inline struct list_head *ncr_list_pop(struct list_head *head)
+{
+ if (!list_empty(head)) {
+ struct list_head *elem = head->next;
+
+ list_del(elem);
+ return elem;
+ }
+
+ return NULL;
+}
+
+/*==========================================================
+**
+** Simple power of two buddy-like allocator.
+**
+** This simple code is not intended to be fast, but to
+** provide power of 2 aligned memory allocations.
+** Since the SCRIPTS processor only supplies 8 bit
+** arithmetic, this allocator allows simple and fast
+** address calculations from the SCRIPTS code.
+** In addition, cache line alignment is guaranteed for
+** power of 2 cache line size.
+** Enhanced in linux-2.3.44 to provide a memory pool
+** per pcidev to support dynamic dma mapping. (I would
+** have preferred a real bus astraction, btw).
+**
+**==========================================================
+*/
+
+#define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */
+#if PAGE_SIZE >= 8192
+#define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum */
+#else
+#define MEMO_PAGE_ORDER 1 /* 2 PAGES maximum */
+#endif
+#define MEMO_FREE_UNUSED /* Free unused pages immediately */
+#define MEMO_WARN 1
+#define MEMO_GFP_FLAGS GFP_ATOMIC
+#define MEMO_CLUSTER_SHIFT (PAGE_SHIFT+MEMO_PAGE_ORDER)
+#define MEMO_CLUSTER_SIZE (1UL << MEMO_CLUSTER_SHIFT)
+#define MEMO_CLUSTER_MASK (MEMO_CLUSTER_SIZE-1)
+
+typedef u_long m_addr_t; /* Enough bits to bit-hack addresses */
+typedef struct device *m_bush_t; /* Something that addresses DMAable */
+
+typedef struct m_link { /* Link between free memory chunks */
+ struct m_link *next;
+} m_link_s;
+
+typedef struct m_vtob { /* Virtual to Bus address translation */
+ struct m_vtob *next;
+ m_addr_t vaddr;
+ m_addr_t baddr;
+} m_vtob_s;
+#define VTOB_HASH_SHIFT 5
+#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
+#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
+#define VTOB_HASH_CODE(m) \
+ ((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
+
+typedef struct m_pool { /* Memory pool of a given kind */
+ m_bush_t bush;
+ m_addr_t (*getp)(struct m_pool *);
+ void (*freep)(struct m_pool *, m_addr_t);
+ int nump;
+ m_vtob_s *(vtob[VTOB_HASH_SIZE]);
+ struct m_pool *next;
+ struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
+} m_pool_s;
+
+static void *___m_alloc(m_pool_s *mp, int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ int j;
+ m_addr_t a;
+ m_link_s *h = mp->h;
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return NULL;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ j = i;
+ while (!h[j].next) {
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ h[j].next = (m_link_s *)mp->getp(mp);
+ if (h[j].next)
+ h[j].next->next = NULL;
+ break;
+ }
+ ++j;
+ s <<= 1;
+ }
+ a = (m_addr_t) h[j].next;
+ if (a) {
+ h[j].next = h[j].next->next;
+ while (j > i) {
+ j -= 1;
+ s >>= 1;
+ h[j].next = (m_link_s *) (a+s);
+ h[j].next->next = NULL;
+ }
+ }
+#ifdef DEBUG
+ printk("___m_alloc(%d) = %p\n", size, (void *) a);
+#endif
+ return (void *) a;
+}
+
+static void ___m_free(m_pool_s *mp, void *ptr, int size)
+{
+ int i = 0;
+ int s = (1 << MEMO_SHIFT);
+ m_link_s *q;
+ m_addr_t a, b;
+ m_link_s *h = mp->h;
+
+#ifdef DEBUG
+ printk("___m_free(%p, %d)\n", ptr, size);
+#endif
+
+ if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
+ return;
+
+ while (size > s) {
+ s <<= 1;
+ ++i;
+ }
+
+ a = (m_addr_t) ptr;
+
+ while (1) {
+#ifdef MEMO_FREE_UNUSED
+ if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
+ mp->freep(mp, a);
+ break;
+ }
+#endif
+ b = a ^ s;
+ q = &h[i];
+ while (q->next && q->next != (m_link_s *) b) {
+ q = q->next;
+ }
+ if (!q->next) {
+ ((m_link_s *) a)->next = h[i].next;
+ h[i].next = (m_link_s *) a;
+ break;
+ }
+ q->next = q->next->next;
+ a = a & b;
+ s <<= 1;
+ ++i;
+ }
+}
+
+static DEFINE_SPINLOCK(ncr53c8xx_lock);
+
+static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
+{
+ void *p;
+
+ p = ___m_alloc(mp, size);
+
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("new %-10s[%4d] @%p.\n", name, size, p);
+
+ if (p)
+ memset(p, 0, size);
+ else if (uflags & MEMO_WARN)
+ printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
+
+ return p;
+}
+
+#define __m_calloc(mp, s, n) __m_calloc2(mp, s, n, MEMO_WARN)
+
+static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
+{
+ if (DEBUG_FLAGS & DEBUG_ALLOC)
+ printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
+
+ ___m_free(mp, ptr, size);
+
+}
+
+/*
+ * With pci bus iommu support, we use a default pool of unmapped memory
+ * for memory we donnot need to DMA from/to and one pool per pcidev for
+ * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
+ */
+
+static m_addr_t ___mp0_getp(m_pool_s *mp)
+{
+ m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
+ if (m)
+ ++mp->nump;
+ return m;
+}
+
+static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
+{
+ free_pages(m, MEMO_PAGE_ORDER);
+ --mp->nump;
+}
+
+static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
+
+/*
+ * DMAable pools.
+ */
+
+/*
+ * With pci bus iommu support, we maintain one pool per pcidev and a
+ * hashed reverse table for virtual to bus physical address translations.
+ */
+static m_addr_t ___dma_getp(m_pool_s *mp)
+{
+ m_addr_t vp;
+ m_vtob_s *vbp;
+
+ vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
+ if (vbp) {
+ dma_addr_t daddr;
+ vp = (m_addr_t) dma_alloc_coherent(mp->bush,
+ PAGE_SIZE<<MEMO_PAGE_ORDER,
+ &daddr, GFP_ATOMIC);
+ if (vp) {
+ int hc = VTOB_HASH_CODE(vp);
+ vbp->vaddr = vp;
+ vbp->baddr = daddr;
+ vbp->next = mp->vtob[hc];
+ mp->vtob[hc] = vbp;
+ ++mp->nump;
+ return vp;
+ }
+ }
+ if (vbp)
+ __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
+ return 0;
+}
+
+static void ___dma_freep(m_pool_s *mp, m_addr_t m)
+{
+ m_vtob_s **vbpp, *vbp;
+ int hc = VTOB_HASH_CODE(m);
+
+ vbpp = &mp->vtob[hc];
+ while (*vbpp && (*vbpp)->vaddr != m)
+ vbpp = &(*vbpp)->next;
+ if (*vbpp) {
+ vbp = *vbpp;
+ *vbpp = (*vbpp)->next;
+ dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
+ (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
+ __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
+ --mp->nump;
+ }
+}
+
+static inline m_pool_s *___get_dma_pool(m_bush_t bush)
+{
+ m_pool_s *mp;
+ for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
+ return mp;
+}
+
+static m_pool_s *___cre_dma_pool(m_bush_t bush)
+{
+ m_pool_s *mp;
+ mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
+ if (mp) {
+ memset(mp, 0, sizeof(*mp));
+ mp->bush = bush;
+ mp->getp = ___dma_getp;
+ mp->freep = ___dma_freep;
+ mp->next = mp0.next;
+ mp0.next = mp;
+ }
+ return mp;
+}
+
+static void ___del_dma_pool(m_pool_s *p)
+{
+ struct m_pool **pp = &mp0.next;
+
+ while (*pp && *pp != p)
+ pp = &(*pp)->next;
+ if (*pp) {
+ *pp = (*pp)->next;
+ __m_free(&mp0, p, sizeof(*p), "MPOOL");
+ }
+}
+
+static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
+{
+ u_long flags;
+ struct m_pool *mp;
+ void *m = NULL;
+
+ spin_lock_irqsave(&ncr53c8xx_lock, flags);
+ mp = ___get_dma_pool(bush);
+ if (!mp)
+ mp = ___cre_dma_pool(bush);
+ if (mp)
+ m = __m_calloc(mp, size, name);
+ if (mp && !mp->nump)
+ ___del_dma_pool(mp);
+ spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+
+ return m;
+}
+
+static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
+{
+ u_long flags;
+ struct m_pool *mp;
+
+ spin_lock_irqsave(&ncr53c8xx_lock, flags);
+ mp = ___get_dma_pool(bush);
+ if (mp)
+ __m_free(mp, m, size, name);
+ if (mp && !mp->nump)
+ ___del_dma_pool(mp);
+ spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+}
+
+static m_addr_t __vtobus(m_bush_t bush, void *m)
+{
+ u_long flags;
+ m_pool_s *mp;
+ int hc = VTOB_HASH_CODE(m);
+ m_vtob_s *vp = NULL;
+ m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
+
+ spin_lock_irqsave(&ncr53c8xx_lock, flags);
+ mp = ___get_dma_pool(bush);
+ if (mp) {
+ vp = mp->vtob[hc];
+ while (vp && (m_addr_t) vp->vaddr != a)
+ vp = vp->next;
+ }
+ spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
+ return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
+}
+
+#define _m_calloc_dma(np, s, n) __m_calloc_dma(np->dev, s, n)
+#define _m_free_dma(np, p, s, n) __m_free_dma(np->dev, p, s, n)
+#define m_calloc_dma(s, n) _m_calloc_dma(np, s, n)
+#define m_free_dma(p, s, n) _m_free_dma(np, p, s, n)
+#define _vtobus(np, p) __vtobus(np->dev, p)
+#define vtobus(p) _vtobus(np, p)
+
+/*
+ * Deal with DMA mapping/unmapping.
+ */
+
+/* To keep track of the dma mapping (sg/single) that has been set */
+#define __data_mapped SCp.phase
+#define __data_mapping SCp.have_data_in
+
+static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+ switch(cmd->__data_mapped) {
+ case 2:
+ dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
+ cmd->sc_data_direction);
+ break;
+ case 1:
+ dma_unmap_single(dev, cmd->__data_mapping,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
+ break;
+ }
+ cmd->__data_mapped = 0;
+}
+
+static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+ dma_addr_t mapping;
+
+ if (cmd->request_bufflen == 0)
+ return 0;
+
+ mapping = dma_map_single(dev, cmd->request_buffer,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
+ cmd->__data_mapped = 1;
+ cmd->__data_mapping = mapping;
+
+ return mapping;
+}
+
+static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
+{
+ int use_sg;
+
+ if (cmd->use_sg == 0)
+ return 0;
+
+ use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
+ cmd->sc_data_direction);
+ cmd->__data_mapped = 2;
+ cmd->__data_mapping = use_sg;
+
+ return use_sg;
+}
+
+#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
+#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
+#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
+
+/*==========================================================
+**
+** Driver setup.
+**
+** This structure is initialized from linux config
+** options. It can be overridden at boot-up by the boot
+** command line.
+**
+**==========================================================
+*/
+static struct ncr_driver_setup
+ driver_setup = SCSI_NCR_DRIVER_SETUP;
+
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+static struct ncr_driver_setup
+ driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
+#endif
+
+#define initverbose (driver_setup.verbose)
+#define bootverbose (np->verbose)
+
+
+/*===================================================================
+**
+** Driver setup from the boot command line
+**
+**===================================================================
+*/
+
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+#define OPT_TAGS 1
+#define OPT_MASTER_PARITY 2
+#define OPT_SCSI_PARITY 3
+#define OPT_DISCONNECTION 4
+#define OPT_SPECIAL_FEATURES 5
+#define OPT_UNUSED_1 6
+#define OPT_FORCE_SYNC_NEGO 7
+#define OPT_REVERSE_PROBE 8
+#define OPT_DEFAULT_SYNC 9
+#define OPT_VERBOSE 10
+#define OPT_DEBUG 11
+#define OPT_BURST_MAX 12
+#define OPT_LED_PIN 13
+#define OPT_MAX_WIDE 14
+#define OPT_SETTLE_DELAY 15
+#define OPT_DIFF_SUPPORT 16
+#define OPT_IRQM 17
+#define OPT_PCI_FIX_UP 18
+#define OPT_BUS_CHECK 19
+#define OPT_OPTIMIZE 20
+#define OPT_RECOVERY 21
+#define OPT_SAFE_SETUP 22
+#define OPT_USE_NVRAM 23
+#define OPT_EXCLUDE 24
+#define OPT_HOST_ID 25
+
+#ifdef SCSI_NCR_IARB_SUPPORT
+#define OPT_IARB 26
+#endif
+
+static char setup_token[] __initdata =
+ "tags:" "mpar:"
+ "spar:" "disc:"
+ "specf:" "ultra:"
+ "fsn:" "revprob:"
+ "sync:" "verb:"
+ "debug:" "burst:"
+ "led:" "wide:"
+ "settle:" "diff:"
+ "irqm:" "pcifix:"
+ "buschk:" "optim:"
+ "recovery:"
+ "safe:" "nvram:"
+ "excl:" "hostid:"
+#ifdef SCSI_NCR_IARB_SUPPORT
+ "iarb:"
+#endif
+ ; /* DONNOT REMOVE THIS ';' */
+
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+static int __init get_setup_token(char *p)
+{
+ char *cur = setup_token;
+ char *pc;
+ int i = 0;
+
+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ ++pc;
+ ++i;
+ if (!strncmp(p, cur, pc - cur))
+ return i;
+ cur = pc;
+ }
+ return 0;
+}
+
+
+static int __init sym53c8xx__setup(char *str)
+{
+#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+ char *cur = str;
+ char *pc, *pv;
+ int i, val, c;
+ int xi = 0;
+
+ while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
+ char *pe;
+
+ val = 0;
+ pv = pc;
+ c = *++pv;
+
+ if (c == 'n')
+ val = 0;
+ else if (c == 'y')
+ val = 1;
+ else
+ val = (int) simple_strtoul(pv, &pe, 0);
+
+ switch (get_setup_token(cur)) {
+ case OPT_TAGS:
+ driver_setup.default_tags = val;
+ if (pe && *pe == '/') {
+ i = 0;
+ while (*pe && *pe != ARG_SEP &&
+ i < sizeof(driver_setup.tag_ctrl)-1) {
+ driver_setup.tag_ctrl[i++] = *pe++;
+ }
+ driver_setup.tag_ctrl[i] = '\0';
+ }
+ break;
+ case OPT_MASTER_PARITY:
+ driver_setup.master_parity = val;
+ break;
+ case OPT_SCSI_PARITY:
+ driver_setup.scsi_parity = val;
+ break;
+ case OPT_DISCONNECTION:
+ driver_setup.disconnection = val;
+ break;
+ case OPT_SPECIAL_FEATURES:
+ driver_setup.special_features = val;
+ break;
+ case OPT_FORCE_SYNC_NEGO:
+ driver_setup.force_sync_nego = val;
+ break;
+ case OPT_REVERSE_PROBE:
+ driver_setup.reverse_probe = val;
+ break;
+ case OPT_DEFAULT_SYNC:
+ driver_setup.default_sync = val;
+ break;
+ case OPT_VERBOSE:
+ driver_setup.verbose = val;
+ break;
+ case OPT_DEBUG:
+ driver_setup.debug = val;
+ break;
+ case OPT_BURST_MAX:
+ driver_setup.burst_max = val;
+ break;
+ case OPT_LED_PIN:
+ driver_setup.led_pin = val;
+ break;
+ case OPT_MAX_WIDE:
+ driver_setup.max_wide = val? 1:0;
+ break;
+ case OPT_SETTLE_DELAY:
+ driver_setup.settle_delay = val;
+ break;
+ case OPT_DIFF_SUPPORT:
+ driver_setup.diff_support = val;
+ break;
+ case OPT_IRQM:
+ driver_setup.irqm = val;
+ break;
+ case OPT_PCI_FIX_UP:
+ driver_setup.pci_fix_up = val;
+ break;
+ case OPT_BUS_CHECK:
+ driver_setup.bus_check = val;
+ break;
+ case OPT_OPTIMIZE:
+ driver_setup.optimize = val;
+ break;
+ case OPT_RECOVERY:
+ driver_setup.recovery = val;
+ break;
+ case OPT_USE_NVRAM:
+ driver_setup.use_nvram = val;
+ break;
+ case OPT_SAFE_SETUP:
+ memcpy(&driver_setup, &driver_safe_setup,
+ sizeof(driver_setup));
+ break;
+ case OPT_EXCLUDE:
+ if (xi < SCSI_NCR_MAX_EXCLUDES)
+ driver_setup.excludes[xi++] = val;
+ break;
+ case OPT_HOST_ID:
+ driver_setup.host_id = val;
+ break;
+#ifdef SCSI_NCR_IARB_SUPPORT
+ case OPT_IARB:
+ driver_setup.iarb = val;
+ break;
+#endif
+ default:
+ printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
+ break;
+ }
+
+ if ((cur = strchr(cur, ARG_SEP)) != NULL)
+ ++cur;
+ }
+#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
+ return 1;
+}
+
+/*===================================================================
+**
+** Get device queue depth from boot command line.
+**
+**===================================================================
+*/
+#define DEF_DEPTH (driver_setup.default_tags)
+#define ALL_TARGETS -2
+#define NO_TARGET -1
+#define ALL_LUNS -2
+#define NO_LUN -1
+
+static int device_queue_depth(int unit, int target, int lun)
+{
+ int c, h, t, u, v;
+ char *p = driver_setup.tag_ctrl;
+ char *ep;
+
+ h = -1;
+ t = NO_TARGET;
+ u = NO_LUN;
+ while ((c = *p++) != 0) {
+ v = simple_strtoul(p, &ep, 0);
+ switch(c) {
+ case '/':
+ ++h;
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ case 't':
+ if (t != target)
+ t = (target == v) ? v : NO_TARGET;
+ u = ALL_LUNS;
+ break;
+ case 'u':
+ if (u != lun)
+ u = (lun == v) ? v : NO_LUN;
+ break;
+ case 'q':
+ if (h == unit &&
+ (t == ALL_TARGETS || t == target) &&
+ (u == ALL_LUNS || u == lun))
+ return v;
+ break;
+ case '-':
+ t = ALL_TARGETS;
+ u = ALL_LUNS;
+ break;
+ default:
+ break;
+ }
+ p = ep;
+ }
+ return DEF_DEPTH;
+}
/*==========================================================
@@ -2971,21 +3703,10 @@ struct host_data {
static void ncr_print_msg(struct ccb *cp, char *label, u_char *msg)
{
- int i;
PRINT_ADDR(cp->cmd, "%s: ", label);
- printk ("%x",*msg);
- if (*msg == M_EXTENDED) {
- for (i = 1; i < 8; i++) {
- if (i - 1 > msg[1])
- break;
- printk ("-%x",msg[i]);
- }
- } else if ((*msg & 0xf0) == 0x20) {
- printk ("-%x",msg[1]);
- }
-
- printk(".\n");
+ spi_print_msg(msg);
+ printk("\n");
}
/*==========================================================
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index 05c7b83cef09..6a7bef2e6118 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -2,6 +2,7 @@
** Device driver for the PCI-SCSI NCR538XX controller family.
**
** Copyright (C) 1994 Wolfgang Stanglmeier
+** Copyright (C) 1998-2001 Gerard Roudier <groudier@free.fr>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@@ -36,15 +37,1275 @@
** And has been ported to NetBSD by
** Charles M. Hannum <mycroft@gnu.ai.mit.edu>
**
+** NVRAM detection and reading.
+** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
+**
+** Added support for MIPS big endian systems.
+** Carsten Langgaard, carstenl@mips.com
+** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+**
+** Added support for HP PARISC big endian systems.
+** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+**
*******************************************************************************
*/
#ifndef NCR53C8XX_H
#define NCR53C8XX_H
+#include <linux/config.h>
#include <scsi/scsi_host.h>
-#include "sym53c8xx_defs.h"
+/*
+** If you want a driver as small as possible, do not define the
+** following options.
+*/
+#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
+#define SCSI_NCR_DEBUG_INFO_SUPPORT
+
+/*
+** To disable integrity checking, do not define the
+** following option.
+*/
+#ifdef CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK
+# define SCSI_NCR_ENABLE_INTEGRITY_CHECK
+#endif
+
+/* ---------------------------------------------------------------------
+** Take into account kernel configured parameters.
+** Most of these options can be overridden at startup by a command line.
+** ---------------------------------------------------------------------
+*/
+
+/*
+ * For Ultra2 and Ultra3 SCSI support option, use special features.
+ *
+ * Value (default) means:
+ * bit 0 : all features enabled, except:
+ * bit 1 : PCI Write And Invalidate.
+ * bit 2 : Data Phase Mismatch handling from SCRIPTS.
+ *
+ * Use boot options ncr53c8xx=specf:1 if you want all chip features to be
+ * enabled by the driver.
+ */
+#define SCSI_NCR_SETUP_SPECIAL_FEATURES (3)
+
+#define SCSI_NCR_MAX_SYNC (80)
+
+/*
+ * Allow tags from 2 to 256, default 8
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
+#define SCSI_NCR_MAX_TAGS (2)
+#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 256
+#define SCSI_NCR_MAX_TAGS (256)
+#else
+#define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
+#endif
+#else
+#define SCSI_NCR_MAX_TAGS (8)
+#endif
+
+/*
+ * Allow tagged command queuing support if configured with default number
+ * of tags set to max (see above).
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
+#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
+#define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS
+#else
+#define SCSI_NCR_SETUP_DEFAULT_TAGS (0)
+#endif
+
+/*
+ * Immediate arbitration
+ */
+#if defined(CONFIG_SCSI_NCR53C8XX_IARB)
+#define SCSI_NCR_IARB_SUPPORT
+#endif
+
+/*
+ * Sync transfer frequency at startup.
+ * Allow from 5Mhz to 80Mhz default 20 Mhz.
+ */
+#ifndef CONFIG_SCSI_NCR53C8XX_SYNC
+#define CONFIG_SCSI_NCR53C8XX_SYNC (20)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
+#undef CONFIG_SCSI_NCR53C8XX_SYNC
+#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC
+#endif
+
+#if CONFIG_SCSI_NCR53C8XX_SYNC == 0
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (255)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 5
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (50)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 20
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC))
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (11)
+#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 40
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (10)
+#else
+#define SCSI_NCR_SETUP_DEFAULT_SYNC (9)
+#endif
+
+/*
+ * Disallow disconnections at boot-up
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
+#define SCSI_NCR_SETUP_DISCONNECTION (0)
+#else
+#define SCSI_NCR_SETUP_DISCONNECTION (1)
+#endif
+
+/*
+ * Force synchronous negotiation for all targets
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (1)
+#else
+#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (0)
+#endif
+
+/*
+ * Disable master parity checking (flawed hardwares need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
+#define SCSI_NCR_SETUP_MASTER_PARITY (0)
+#else
+#define SCSI_NCR_SETUP_MASTER_PARITY (1)
+#endif
+
+/*
+ * Disable scsi parity checking (flawed devices may need that)
+ */
+#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
+#define SCSI_NCR_SETUP_SCSI_PARITY (0)
+#else
+#define SCSI_NCR_SETUP_SCSI_PARITY (1)
+#endif
+
+/*
+ * Settle time after reset at boot-up
+ */
+#define SCSI_NCR_SETUP_SETTLE_TIME (2)
+
+/*
+** Bridge quirks work-around option defaulted to 1.
+*/
+#ifndef SCSI_NCR_PCIQ_WORK_AROUND_OPT
+#define SCSI_NCR_PCIQ_WORK_AROUND_OPT 1
+#endif
+
+/*
+** Work-around common bridge misbehaviour.
+**
+** - Do not flush posted writes in the opposite
+** direction on read.
+** - May reorder DMA writes to memory.
+**
+** This option should not affect performances
+** significantly, so it is the default.
+*/
+#if SCSI_NCR_PCIQ_WORK_AROUND_OPT == 1
+#define SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
+#define SCSI_NCR_PCIQ_MAY_REORDER_WRITES
+#define SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
+
+/*
+** Same as option 1, but also deal with
+** misconfigured interrupts.
+**
+** - Edge triggerred instead of level sensitive.
+** - No interrupt line connected.
+** - IRQ number misconfigured.
+**
+** If no interrupt is delivered, the driver will
+** catch the interrupt conditions 10 times per
+** second. No need to say that this option is
+** not recommended.
+*/
+#elif SCSI_NCR_PCIQ_WORK_AROUND_OPT == 2
+#define SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
+#define SCSI_NCR_PCIQ_MAY_REORDER_WRITES
+#define SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
+#define SCSI_NCR_PCIQ_BROKEN_INTR
+
+/*
+** Some bridge designers decided to flush
+** everything prior to deliver the interrupt.
+** This option tries to deal with such a
+** behaviour.
+*/
+#elif SCSI_NCR_PCIQ_WORK_AROUND_OPT == 3
+#define SCSI_NCR_PCIQ_SYNC_ON_INTR
+#endif
+
+/*
+** Other parameters not configurable with "make config"
+** Avoid to change these constants, unless you know what you are doing.
+*/
+
+#define SCSI_NCR_ALWAYS_SIMPLE_TAG
+#define SCSI_NCR_MAX_SCATTER (127)
+#define SCSI_NCR_MAX_TARGET (16)
+
+/*
+** Compute some desirable value for CAN_QUEUE
+** and CMD_PER_LUN.
+** The driver will use lower values if these
+** ones appear to be too large.
+*/
+#define SCSI_NCR_CAN_QUEUE (8*SCSI_NCR_MAX_TAGS + 2*SCSI_NCR_MAX_TARGET)
+#define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS)
+
+#define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER)
+#define SCSI_NCR_TIMER_INTERVAL (HZ)
+
+#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
+#define SCSI_NCR_MAX_LUN (16)
+#else
+#define SCSI_NCR_MAX_LUN (1)
+#endif
+
+/*
+ * IO functions definition for big/little endian CPU support.
+ * For now, the NCR is only supported in little endian addressing mode,
+ */
+
+#ifdef __BIG_ENDIAN
+
+#define inw_l2b inw
+#define inl_l2b inl
+#define outw_b2l outw
+#define outl_b2l outl
+
+#define readb_raw readb
+#define writeb_raw writeb
+
+#if defined(SCSI_NCR_BIG_ENDIAN)
+#define readw_l2b __raw_readw
+#define readl_l2b __raw_readl
+#define writew_b2l __raw_writew
+#define writel_b2l __raw_writel
+#define readw_raw __raw_readw
+#define readl_raw __raw_readl
+#define writew_raw __raw_writew
+#define writel_raw __raw_writel
+#else /* Other big-endian */
+#define readw_l2b readw
+#define readl_l2b readl
+#define writew_b2l writew
+#define writel_b2l writel
+#define readw_raw readw
+#define readl_raw readl
+#define writew_raw writew
+#define writel_raw writel
+#endif
+
+#else /* little endian */
+
+#define inw_raw inw
+#define inl_raw inl
+#define outw_raw outw
+#define outl_raw outl
+
+#define readb_raw readb
+#define readw_raw readw
+#define readl_raw readl
+#define writeb_raw writeb
+#define writew_raw writew
+#define writel_raw writel
+
+#endif
+
+#if !defined(__hppa__) && !defined(__mips__)
+#ifdef SCSI_NCR_BIG_ENDIAN
+#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
+#endif
+#endif
+
+#define MEMORY_BARRIER() mb()
+
+
+/*
+ * If the NCR uses big endian addressing mode over the
+ * PCI, actual io register addresses for byte and word
+ * accesses must be changed according to lane routing.
+ * Btw, ncr_offb() and ncr_offw() macros only apply to
+ * constants and so donnot generate bloated code.
+ */
+
+#if defined(SCSI_NCR_BIG_ENDIAN)
+
+#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
+#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
+
+#else
+
+#define ncr_offb(o) (o)
+#define ncr_offw(o) (o)
+
+#endif
+
+/*
+ * If the CPU and the NCR use same endian-ness addressing,
+ * no byte reordering is needed for script patching.
+ * Macro cpu_to_scr() is to be used for script patching.
+ * Macro scr_to_cpu() is to be used for getting a DWORD
+ * from the script.
+ */
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_le32(dw)
+#define scr_to_cpu(dw) le32_to_cpu(dw)
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define cpu_to_scr(dw) cpu_to_be32(dw)
+#define scr_to_cpu(dw) be32_to_cpu(dw)
+
+#else
+
+#define cpu_to_scr(dw) (dw)
+#define scr_to_cpu(dw) (dw)
+
+#endif
+
+/*
+ * Access to the controller chip.
+ *
+ * If the CPU and the NCR use same endian-ness addressing,
+ * no byte reordering is needed for accessing chip io
+ * registers. Functions suffixed by '_raw' are assumed
+ * to access the chip over the PCI without doing byte
+ * reordering. Functions suffixed by '_l2b' are
+ * assumed to perform little-endian to big-endian byte
+ * reordering, those suffixed by '_b2l' blah, blah,
+ * blah, ...
+ */
+
+/*
+ * MEMORY mapped IO input / output
+ */
+
+#define INB_OFF(o) readb_raw((char __iomem *)np->reg + ncr_offb(o))
+#define OUTB_OFF(o, val) writeb_raw((val), (char __iomem *)np->reg + ncr_offb(o))
+
+#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_l2b((char __iomem *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_l2b((char __iomem *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_b2l((val), (char __iomem *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_b2l((val), (char __iomem *)np->reg + (o))
+
+#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
+
+#define INW_OFF(o) readw_b2l((char __iomem *)np->reg + ncr_offw(o))
+#define INL_OFF(o) readl_b2l((char __iomem *)np->reg + (o))
+
+#define OUTW_OFF(o, val) writew_l2b((val), (char __iomem *)np->reg + ncr_offw(o))
+#define OUTL_OFF(o, val) writel_l2b((val), (char __iomem *)np->reg + (o))
+
+#else
+
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
+/* Only 8 or 32 bit transfers allowed */
+#define INW_OFF(o) (readb((char __iomem *)np->reg + ncr_offw(o)) << 8 | readb((char __iomem *)np->reg + ncr_offw(o) + 1))
+#else
+#define INW_OFF(o) readw_raw((char __iomem *)np->reg + ncr_offw(o))
+#endif
+#define INL_OFF(o) readl_raw((char __iomem *)np->reg + (o))
+
+#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
+/* Only 8 or 32 bit transfers allowed */
+#define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char __iomem *)np->reg + ncr_offw(o)); writeb((char)(val), (char __iomem *)np->reg + ncr_offw(o) + 1); } while (0)
+#else
+#define OUTW_OFF(o, val) writew_raw((val), (char __iomem *)np->reg + ncr_offw(o))
+#endif
+#define OUTL_OFF(o, val) writel_raw((val), (char __iomem *)np->reg + (o))
+
+#endif
+
+#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
+#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
+#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
+
+#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
+#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
+
+/*
+ * Set bit field ON, OFF
+ */
+
+#define OUTONB(r, m) OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
+#define OUTONW(r, m) OUTW(r, INW(r) | (m))
+#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
+#define OUTONL(r, m) OUTL(r, INL(r) | (m))
+#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
+
+/*
+ * We normally want the chip to have a consistent view
+ * of driver internal data structures when we restart it.
+ * Thus these macros.
+ */
+#define OUTL_DSP(v) \
+ do { \
+ MEMORY_BARRIER(); \
+ OUTL (nc_dsp, (v)); \
+ } while (0)
+
+#define OUTONB_STD() \
+ do { \
+ MEMORY_BARRIER(); \
+ OUTONB (nc_dcntl, (STD|NOCOM)); \
+ } while (0)
+
+
+/*
+** NCR53C8XX devices features table.
+*/
+struct ncr_chip {
+ unsigned short revision_id;
+ unsigned char burst_max; /* log-base-2 of max burst */
+ unsigned char offset_max;
+ unsigned char nr_divisor;
+ unsigned int features;
+#define FE_LED0 (1<<0)
+#define FE_WIDE (1<<1) /* Wide data transfers */
+#define FE_ULTRA (1<<2) /* Ultra speed 20Mtrans/sec */
+#define FE_DBLR (1<<4) /* Clock doubler present */
+#define FE_QUAD (1<<5) /* Clock quadrupler present */
+#define FE_ERL (1<<6) /* Enable read line */
+#define FE_CLSE (1<<7) /* Cache line size enable */
+#define FE_WRIE (1<<8) /* Write & Invalidate enable */
+#define FE_ERMP (1<<9) /* Enable read multiple */
+#define FE_BOF (1<<10) /* Burst opcode fetch */
+#define FE_DFS (1<<11) /* DMA fifo size */
+#define FE_PFEN (1<<12) /* Prefetch enable */
+#define FE_LDSTR (1<<13) /* Load/Store supported */
+#define FE_RAM (1<<14) /* On chip RAM present */
+#define FE_VARCLK (1<<15) /* SCSI clock may vary */
+#define FE_RAM8K (1<<16) /* On chip RAM sized 8Kb */
+#define FE_64BIT (1<<17) /* Have a 64-bit PCI interface */
+#define FE_IO256 (1<<18) /* Requires full 256 bytes in PCI space */
+#define FE_NOPM (1<<19) /* Scripts handles phase mismatch */
+#define FE_LEDC (1<<20) /* Hardware control of LED */
+#define FE_DIFF (1<<21) /* Support Differential SCSI */
+#define FE_66MHZ (1<<23) /* 66MHz PCI Support */
+#define FE_DAC (1<<24) /* Support DAC cycles (64 bit addressing) */
+#define FE_ISTAT1 (1<<25) /* Have ISTAT1, MBOX0, MBOX1 registers */
+#define FE_DAC_IN_USE (1<<26) /* Platform does DAC cycles */
+#define FE_EHP (1<<27) /* 720: Even host parity */
+#define FE_MUX (1<<28) /* 720: Multiplexed bus */
+#define FE_EA (1<<29) /* 720: Enable Ack */
+
+#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
+#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_DBLR|FE_QUAD|F_CLK80)
+#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
+};
+
+
+/*
+** Driver setup structure.
+**
+** This structure is initialized from linux config options.
+** It can be overridden at boot-up by the boot command line.
+*/
+#define SCSI_NCR_MAX_EXCLUDES 8
+struct ncr_driver_setup {
+ u8 master_parity;
+ u8 scsi_parity;
+ u8 disconnection;
+ u8 special_features;
+ u8 force_sync_nego;
+ u8 reverse_probe;
+ u8 pci_fix_up;
+ u8 use_nvram;
+ u8 verbose;
+ u8 default_tags;
+ u16 default_sync;
+ u16 debug;
+ u8 burst_max;
+ u8 led_pin;
+ u8 max_wide;
+ u8 settle_delay;
+ u8 diff_support;
+ u8 irqm;
+ u8 bus_check;
+ u8 optimize;
+ u8 recovery;
+ u8 host_id;
+ u16 iarb;
+ u32 excludes[SCSI_NCR_MAX_EXCLUDES];
+ char tag_ctrl[100];
+};
+
+/*
+** Initial setup.
+** Can be overriden at startup by a command line.
+*/
+#define SCSI_NCR_DRIVER_SETUP \
+{ \
+ SCSI_NCR_SETUP_MASTER_PARITY, \
+ SCSI_NCR_SETUP_SCSI_PARITY, \
+ SCSI_NCR_SETUP_DISCONNECTION, \
+ SCSI_NCR_SETUP_SPECIAL_FEATURES, \
+ SCSI_NCR_SETUP_FORCE_SYNC_NEGO, \
+ 0, \
+ 0, \
+ 1, \
+ 0, \
+ SCSI_NCR_SETUP_DEFAULT_TAGS, \
+ SCSI_NCR_SETUP_DEFAULT_SYNC, \
+ 0x00, \
+ 7, \
+ 0, \
+ 1, \
+ SCSI_NCR_SETUP_SETTLE_TIME, \
+ 0, \
+ 0, \
+ 1, \
+ 0, \
+ 0, \
+ 255, \
+ 0x00 \
+}
+
+/*
+** Boot fail safe setup.
+** Override initial setup from boot command line:
+** ncr53c8xx=safe:y
+*/
+#define SCSI_NCR_DRIVER_SAFE_SETUP \
+{ \
+ 0, \
+ 1, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ 1, \
+ 2, \
+ 0, \
+ 255, \
+ 0x00, \
+ 255, \
+ 0, \
+ 0, \
+ 10, \
+ 1, \
+ 1, \
+ 1, \
+ 0, \
+ 0, \
+ 255 \
+}
+
+/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
+
+/*-----------------------------------------------------------------
+**
+** The ncr 53c810 register structure.
+**
+**-----------------------------------------------------------------
+*/
+
+struct ncr_reg {
+/*00*/ u8 nc_scntl0; /* full arb., ena parity, par->ATN */
+
+/*01*/ u8 nc_scntl1; /* no reset */
+ #define ISCON 0x10 /* connected to scsi */
+ #define CRST 0x08 /* force reset */
+ #define IARB 0x02 /* immediate arbitration */
+
+/*02*/ u8 nc_scntl2; /* no disconnect expected */
+ #define SDU 0x80 /* cmd: disconnect will raise error */
+ #define CHM 0x40 /* sta: chained mode */
+ #define WSS 0x08 /* sta: wide scsi send [W]*/
+ #define WSR 0x01 /* sta: wide scsi received [W]*/
+
+/*03*/ u8 nc_scntl3; /* cnf system clock dependent */
+ #define EWS 0x08 /* cmd: enable wide scsi [W]*/
+ #define ULTRA 0x80 /* cmd: ULTRA enable */
+ /* bits 0-2, 7 rsvd for C1010 */
+
+/*04*/ u8 nc_scid; /* cnf host adapter scsi address */
+ #define RRE 0x40 /* r/w:e enable response to resel. */
+ #define SRE 0x20 /* r/w:e enable response to select */
+
+/*05*/ u8 nc_sxfer; /* ### Sync speed and count */
+ /* bits 6-7 rsvd for C1010 */
+
+/*06*/ u8 nc_sdid; /* ### Destination-ID */
+
+/*07*/ u8 nc_gpreg; /* ??? IO-Pins */
+
+/*08*/ u8 nc_sfbr; /* ### First byte in phase */
+
+/*09*/ u8 nc_socl;
+ #define CREQ 0x80 /* r/w: SCSI-REQ */
+ #define CACK 0x40 /* r/w: SCSI-ACK */
+ #define CBSY 0x20 /* r/w: SCSI-BSY */
+ #define CSEL 0x10 /* r/w: SCSI-SEL */
+ #define CATN 0x08 /* r/w: SCSI-ATN */
+ #define CMSG 0x04 /* r/w: SCSI-MSG */
+ #define CC_D 0x02 /* r/w: SCSI-C_D */
+ #define CI_O 0x01 /* r/w: SCSI-I_O */
+
+/*0a*/ u8 nc_ssid;
+
+/*0b*/ u8 nc_sbcl;
+
+/*0c*/ u8 nc_dstat;
+ #define DFE 0x80 /* sta: dma fifo empty */
+ #define MDPE 0x40 /* int: master data parity error */
+ #define BF 0x20 /* int: script: bus fault */
+ #define ABRT 0x10 /* int: script: command aborted */
+ #define SSI 0x08 /* int: script: single step */
+ #define SIR 0x04 /* int: script: interrupt instruct. */
+ #define IID 0x01 /* int: script: illegal instruct. */
+
+/*0d*/ u8 nc_sstat0;
+ #define ILF 0x80 /* sta: data in SIDL register lsb */
+ #define ORF 0x40 /* sta: data in SODR register lsb */
+ #define OLF 0x20 /* sta: data in SODL register lsb */
+ #define AIP 0x10 /* sta: arbitration in progress */
+ #define LOA 0x08 /* sta: arbitration lost */
+ #define WOA 0x04 /* sta: arbitration won */
+ #define IRST 0x02 /* sta: scsi reset signal */
+ #define SDP 0x01 /* sta: scsi parity signal */
+
+/*0e*/ u8 nc_sstat1;
+ #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
+
+/*0f*/ u8 nc_sstat2;
+ #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
+ #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
+ #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
+ #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
+ #define LDSC 0x02 /* sta: disconnect & reconnect */
+
+/*10*/ u8 nc_dsa; /* --> Base page */
+/*11*/ u8 nc_dsa1;
+/*12*/ u8 nc_dsa2;
+/*13*/ u8 nc_dsa3;
+
+/*14*/ u8 nc_istat; /* --> Main Command and status */
+ #define CABRT 0x80 /* cmd: abort current operation */
+ #define SRST 0x40 /* mod: reset chip */
+ #define SIGP 0x20 /* r/w: message from host to ncr */
+ #define SEM 0x10 /* r/w: message between host + ncr */
+ #define CON 0x08 /* sta: connected to scsi */
+ #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
+ #define SIP 0x02 /* sta: scsi-interrupt */
+ #define DIP 0x01 /* sta: host/script interrupt */
+
+/*15*/ u8 nc_istat1; /* 896 and later cores only */
+ #define FLSH 0x04 /* sta: chip is flushing */
+ #define SRUN 0x02 /* sta: scripts are running */
+ #define SIRQD 0x01 /* r/w: disable INT pin */
+
+/*16*/ u8 nc_mbox0; /* 896 and later cores only */
+/*17*/ u8 nc_mbox1; /* 896 and later cores only */
+
+/*18*/ u8 nc_ctest0;
+ #define EHP 0x04 /* 720 even host parity */
+/*19*/ u8 nc_ctest1;
+
+/*1a*/ u8 nc_ctest2;
+ #define CSIGP 0x40
+ /* bits 0-2,7 rsvd for C1010 */
+
+/*1b*/ u8 nc_ctest3;
+ #define FLF 0x08 /* cmd: flush dma fifo */
+ #define CLF 0x04 /* cmd: clear dma fifo */
+ #define FM 0x02 /* mod: fetch pin mode */
+ #define WRIE 0x01 /* mod: write and invalidate enable */
+ /* bits 4-7 rsvd for C1010 */
+
+/*1c*/ u32 nc_temp; /* ### Temporary stack */
+
+/*20*/ u8 nc_dfifo;
+/*21*/ u8 nc_ctest4;
+ #define MUX 0x80 /* 720 host bus multiplex mode */
+ #define BDIS 0x80 /* mod: burst disable */
+ #define MPEE 0x08 /* mod: master parity error enable */
+
+/*22*/ u8 nc_ctest5;
+ #define DFS 0x20 /* mod: dma fifo size */
+ /* bits 0-1, 3-7 rsvd for C1010 */
+/*23*/ u8 nc_ctest6;
+
+/*24*/ u32 nc_dbc; /* ### Byte count and command */
+/*28*/ u32 nc_dnad; /* ### Next command register */
+/*2c*/ u32 nc_dsp; /* --> Script Pointer */
+/*30*/ u32 nc_dsps; /* --> Script pointer save/opcode#2 */
+
+/*34*/ u8 nc_scratcha; /* Temporary register a */
+/*35*/ u8 nc_scratcha1;
+/*36*/ u8 nc_scratcha2;
+/*37*/ u8 nc_scratcha3;
+
+/*38*/ u8 nc_dmode;
+ #define BL_2 0x80 /* mod: burst length shift value +2 */
+ #define BL_1 0x40 /* mod: burst length shift value +1 */
+ #define ERL 0x08 /* mod: enable read line */
+ #define ERMP 0x04 /* mod: enable read multiple */
+ #define BOF 0x02 /* mod: burst op code fetch */
+
+/*39*/ u8 nc_dien;
+/*3a*/ u8 nc_sbr;
+
+/*3b*/ u8 nc_dcntl; /* --> Script execution control */
+ #define CLSE 0x80 /* mod: cache line size enable */
+ #define PFF 0x40 /* cmd: pre-fetch flush */
+ #define PFEN 0x20 /* mod: pre-fetch enable */
+ #define EA 0x20 /* mod: 720 enable-ack */
+ #define SSM 0x10 /* mod: single step mode */
+ #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
+ #define STD 0x04 /* cmd: start dma mode */
+ #define IRQD 0x02 /* mod: irq disable */
+ #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
+ /* bits 0-1 rsvd for C1010 */
+
+/*3c*/ u32 nc_adder;
+
+/*40*/ u16 nc_sien; /* -->: interrupt enable */
+/*42*/ u16 nc_sist; /* <--: interrupt status */
+ #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+ #define STO 0x0400/* sta: timeout (select) */
+ #define GEN 0x0200/* sta: timeout (general) */
+ #define HTH 0x0100/* sta: timeout (handshake) */
+ #define MA 0x80 /* sta: phase mismatch */
+ #define CMP 0x40 /* sta: arbitration complete */
+ #define SEL 0x20 /* sta: selected by another device */
+ #define RSL 0x10 /* sta: reselected by another device*/
+ #define SGE 0x08 /* sta: gross error (over/underflow)*/
+ #define UDC 0x04 /* sta: unexpected disconnect */
+ #define RST 0x02 /* sta: scsi bus reset detected */
+ #define PAR 0x01 /* sta: scsi parity error */
+
+/*44*/ u8 nc_slpar;
+/*45*/ u8 nc_swide;
+/*46*/ u8 nc_macntl;
+/*47*/ u8 nc_gpcntl;
+/*48*/ u8 nc_stime0; /* cmd: timeout for select&handshake*/
+/*49*/ u8 nc_stime1; /* cmd: timeout user defined */
+/*4a*/ u16 nc_respid; /* sta: Reselect-IDs */
+
+/*4c*/ u8 nc_stest0;
+
+/*4d*/ u8 nc_stest1;
+ #define SCLK 0x80 /* Use the PCI clock as SCSI clock */
+ #define DBLEN 0x08 /* clock doubler running */
+ #define DBLSEL 0x04 /* clock doubler selected */
+
+
+/*4e*/ u8 nc_stest2;
+ #define ROF 0x40 /* reset scsi offset (after gross error!) */
+ #define DIF 0x20 /* 720 SCSI differential mode */
+ #define EXT 0x02 /* extended filtering */
+
+/*4f*/ u8 nc_stest3;
+ #define TE 0x80 /* c: tolerAnt enable */
+ #define HSC 0x20 /* c: Halt SCSI Clock */
+ #define CSF 0x02 /* c: clear scsi fifo */
+
+/*50*/ u16 nc_sidl; /* Lowlevel: latched from scsi data */
+/*52*/ u8 nc_stest4;
+ #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
+ #define SMODE_HVD 0x40 /* High Voltage Differential */
+ #define SMODE_SE 0x80 /* Single Ended */
+ #define SMODE_LVD 0xc0 /* Low Voltage Differential */
+ #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
+ /* bits 0-5 rsvd for C1010 */
+
+/*53*/ u8 nc_53_;
+/*54*/ u16 nc_sodl; /* Lowlevel: data out to scsi data */
+/*56*/ u8 nc_ccntl0; /* Chip Control 0 (896) */
+ #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
+ #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
+ #define ENNDJ 0x20 /* Enable Non Data PM Jump */
+ #define DISFC 0x10 /* Disable Auto FIFO Clear */
+ #define DILS 0x02 /* Disable Internal Load/Store */
+ #define DPR 0x01 /* Disable Pipe Req */
+
+/*57*/ u8 nc_ccntl1; /* Chip Control 1 (896) */
+ #define ZMOD 0x80 /* High Impedance Mode */
+ #define DIC 0x10 /* Disable Internal Cycles */
+ #define DDAC 0x08 /* Disable Dual Address Cycle */
+ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
+ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
+ #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
+
+/*58*/ u16 nc_sbdl; /* Lowlevel: data from scsi data */
+/*5a*/ u16 nc_5a_;
+
+/*5c*/ u8 nc_scr0; /* Working register B */
+/*5d*/ u8 nc_scr1; /* */
+/*5e*/ u8 nc_scr2; /* */
+/*5f*/ u8 nc_scr3; /* */
+
+/*60*/ u8 nc_scrx[64]; /* Working register C-R */
+/*a0*/ u32 nc_mmrs; /* Memory Move Read Selector */
+/*a4*/ u32 nc_mmws; /* Memory Move Write Selector */
+/*a8*/ u32 nc_sfs; /* Script Fetch Selector */
+/*ac*/ u32 nc_drs; /* DSA Relative Selector */
+/*b0*/ u32 nc_sbms; /* Static Block Move Selector */
+/*b4*/ u32 nc_dbms; /* Dynamic Block Move Selector */
+/*b8*/ u32 nc_dnad64; /* DMA Next Address 64 */
+/*bc*/ u16 nc_scntl4; /* C1010 only */
+ #define U3EN 0x80 /* Enable Ultra 3 */
+ #define AIPEN 0x40 /* Allow check upper byte lanes */
+ #define XCLKH_DT 0x08 /* Extra clock of data hold on DT
+ transfer edge */
+ #define XCLKH_ST 0x04 /* Extra clock of data hold on ST
+ transfer edge */
+
+/*be*/ u8 nc_aipcntl0; /* Epat Control 1 C1010 only */
+/*bf*/ u8 nc_aipcntl1; /* AIP Control C1010_66 Only */
+
+/*c0*/ u32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */
+/*c4*/ u32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */
+/*c8*/ u8 nc_rbc; /* Remaining Byte Count */
+/*c9*/ u8 nc_rbc1; /* */
+/*ca*/ u8 nc_rbc2; /* */
+/*cb*/ u8 nc_rbc3; /* */
+
+/*cc*/ u8 nc_ua; /* Updated Address */
+/*cd*/ u8 nc_ua1; /* */
+/*ce*/ u8 nc_ua2; /* */
+/*cf*/ u8 nc_ua3; /* */
+/*d0*/ u32 nc_esa; /* Entry Storage Address */
+/*d4*/ u8 nc_ia; /* Instruction Address */
+/*d5*/ u8 nc_ia1;
+/*d6*/ u8 nc_ia2;
+/*d7*/ u8 nc_ia3;
+/*d8*/ u32 nc_sbc; /* SCSI Byte Count (3 bytes only) */
+/*dc*/ u32 nc_csbc; /* Cumulative SCSI Byte Count */
+
+ /* Following for C1010 only */
+/*e0*/ u16 nc_crcpad; /* CRC Value */
+/*e2*/ u8 nc_crccntl0; /* CRC control register */
+ #define SNDCRC 0x10 /* Send CRC Request */
+/*e3*/ u8 nc_crccntl1; /* CRC control register */
+/*e4*/ u32 nc_crcdata; /* CRC data register */
+/*e8*/ u32 nc_e8_; /* rsvd */
+/*ec*/ u32 nc_ec_; /* rsvd */
+/*f0*/ u16 nc_dfbc; /* DMA FIFO byte count */
+
+};
+
+/*-----------------------------------------------------------
+**
+** Utility macros for the script.
+**
+**-----------------------------------------------------------
+*/
+
+#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
+#define REG(r) REGJ (nc_, r)
+
+typedef u32 ncrcmd;
+
+/*-----------------------------------------------------------
+**
+** SCSI phases
+**
+** DT phases illegal for ncr driver.
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_DATA_OUT 0x00000000
+#define SCR_DATA_IN 0x01000000
+#define SCR_COMMAND 0x02000000
+#define SCR_STATUS 0x03000000
+#define SCR_DT_DATA_OUT 0x04000000
+#define SCR_DT_DATA_IN 0x05000000
+#define SCR_MSG_OUT 0x06000000
+#define SCR_MSG_IN 0x07000000
+
+#define SCR_ILG_OUT 0x04000000
+#define SCR_ILG_IN 0x05000000
+
+/*-----------------------------------------------------------
+**
+** Data transfer via SCSI.
+**
+**-----------------------------------------------------------
+**
+** MOVE_ABS (LEN)
+** <<start address>>
+**
+** MOVE_IND (LEN)
+** <<dnad_offset>>
+**
+** MOVE_TBL
+** <<dnad_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define OPC_MOVE 0x08000000
+
+#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_TBL (0x10000000 | OPC_MOVE)
+
+#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
+#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
+#define SCR_CHMOV_TBL (0x10000000)
+
+struct scr_tblmove {
+ u32 size;
+ u32 addr;
+};
+
+/*-----------------------------------------------------------
+**
+** Selection
+**
+**-----------------------------------------------------------
+**
+** SEL_ABS | SCR_ID (0..15) [ | REL_JMP]
+** <<alternate_address>>
+**
+** SEL_TBL | << dnad_offset>> [ | REL_JMP]
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SEL_ABS 0x40000000
+#define SCR_SEL_ABS_ATN 0x41000000
+#define SCR_SEL_TBL 0x42000000
+#define SCR_SEL_TBL_ATN 0x43000000
+
+
+#ifdef SCSI_NCR_BIG_ENDIAN
+struct scr_tblsel {
+ u8 sel_scntl3;
+ u8 sel_id;
+ u8 sel_sxfer;
+ u8 sel_scntl4;
+};
+#else
+struct scr_tblsel {
+ u8 sel_scntl4;
+ u8 sel_sxfer;
+ u8 sel_id;
+ u8 sel_scntl3;
+};
+#endif
+
+#define SCR_JMP_REL 0x04000000
+#define SCR_ID(id) (((u32)(id)) << 16)
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** WAIT_DISC
+** dummy: <<alternate_address>>
+**
+** WAIT_RESEL
+** <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_WAIT_DISC 0x48000000
+#define SCR_WAIT_RESEL 0x50000000
+
+/*-----------------------------------------------------------
+**
+** Bit Set / Reset
+**
+**-----------------------------------------------------------
+**
+** SET (flags {|.. })
+**
+** CLR (flags {|.. })
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SET(f) (0x58000000 | (f))
+#define SCR_CLR(f) (0x60000000 | (f))
+
+#define SCR_CARRY 0x00000400
+#define SCR_TRG 0x00000200
+#define SCR_ACK 0x00000040
+#define SCR_ATN 0x00000008
+
+
+
+
+/*-----------------------------------------------------------
+**
+** Memory to memory move
+**
+**-----------------------------------------------------------
+**
+** COPY (bytecount)
+** << source_address >>
+** << destination_address >>
+**
+** SCR_COPY sets the NO FLUSH option by default.
+** SCR_COPY_F does not set this option.
+**
+** For chips which do not support this option,
+** ncr_copy_and_bind() will remove this bit.
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+**
+** Register move and binary operations
+**
+**-----------------------------------------------------------
+**
+** SFBR_REG (reg, op, data) reg = SFBR op data
+** << 0 >>
+**
+** REG_SFBR (reg, op, data) SFBR = reg op data
+** << 0 >>
+**
+** REG_REG (reg, op, data) reg = reg op data
+** << 0 >>
+**
+**-----------------------------------------------------------
+** On 810A, 860, 825A, 875, 895 and 896 chips the content
+** of SFBR register can be used as data (SCR_SFBR_DATA).
+** The 896 has additionnal IO registers starting at
+** offset 0x80. Bit 7 of register offset is stored in
+** bit 7 of the SCRIPTS instruction first DWORD.
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80))
+
+#define SCR_SFBR_REG(reg,op,data) \
+ (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+ (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+ (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define SCR_LOAD 0x00000000
+#define SCR_SHL 0x01000000
+#define SCR_OR 0x02000000
+#define SCR_XOR 0x03000000
+#define SCR_AND 0x04000000
+#define SCR_SHR 0x05000000
+#define SCR_ADD 0x06000000
+#define SCR_ADDC 0x07000000
+
+#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */
+
+/*-----------------------------------------------------------
+**
+** FROM_REG (reg) SFBR = reg
+** << 0 >>
+**
+** TO_REG (reg) reg = SFBR
+** << 0 >>
+**
+** LOAD_REG (reg, data) reg = <data>
+** << 0 >>
+**
+** LOAD_SFBR(data) SFBR = <data>
+** << 0 >>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_FROM_REG(reg) \
+ SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define SCR_TO_REG(reg) \
+ SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define SCR_LOAD_REG(reg,data) \
+ SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+ (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+**
+** LOAD from memory to register.
+** STORE from register to memory.
+**
+** Only supported by 810A, 860, 825A, 875, 895 and 896.
+**
+**-----------------------------------------------------------
+**
+** LOAD_ABS (LEN)
+** <<start address>>
+**
+** LOAD_REL (LEN) (DSA relative)
+** <<dsa_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2 0x02000000
+#define SCR_DSA_REL2 0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+ (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+ (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+**
+** Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** CALL [ | IFTRUE/IFFALSE ( ... ) ]
+** <<address>>
+**
+** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
+** <<distance>>
+**
+** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
+** <<dummy>>
+**
+** INT [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
+** <<ident>>
+**
+** Conditions:
+** WHEN (phase)
+** IF (phase)
+** CARRYSET
+** DATA (data, mask)
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_OP 0x80000000
+#define SCR_JUMP 0x80080000
+#define SCR_JUMP64 0x80480000
+#define SCR_JUMPR 0x80880000
+#define SCR_CALL 0x88080000
+#define SCR_CALLR 0x88880000
+#define SCR_RETURN 0x90080000
+#define SCR_INT 0x98080000
+#define SCR_INT_FLY 0x98180000
+
+#define IFFALSE(arg) (0x00080000 | (arg))
+#define IFTRUE(arg) (0x00000000 | (arg))
+
+#define WHEN(phase) (0x00030000 | (phase))
+#define IF(phase) (0x00020000 | (phase))
+
+#define DATA(D) (0x00040000 | ((D) & 0xff))
+#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET (0x00200000)
+
+/*-----------------------------------------------------------
+**
+** SCSI constants.
+**
+**-----------------------------------------------------------
+*/
+
+/*
+** Messages
+*/
+
+#define M_COMPLETE COMMAND_COMPLETE
+#define M_EXTENDED EXTENDED_MESSAGE
+#define M_SAVE_DP SAVE_POINTERS
+#define M_RESTORE_DP RESTORE_POINTERS
+#define M_DISCONNECT DISCONNECT
+#define M_ID_ERROR INITIATOR_ERROR
+#define M_ABORT ABORT_TASK_SET
+#define M_REJECT MESSAGE_REJECT
+#define M_NOOP NOP
+#define M_PARITY MSG_PARITY_ERROR
+#define M_LCOMPLETE LINKED_CMD_COMPLETE
+#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
+#define M_RESET TARGET_RESET
+#define M_ABORT_TAG ABORT_TASK
+#define M_CLEAR_QUEUE CLEAR_TASK_SET
+#define M_INIT_REC INITIATE_RECOVERY
+#define M_REL_REC RELEASE_RECOVERY
+#define M_TERMINATE (0x11)
+#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
+#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
+#define M_ORDERED_TAG ORDERED_QUEUE_TAG
+#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
+#define M_IDENTIFY (0x80)
+
+#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
+#define M_X_SYNC_REQ EXTENDED_SDTR
+#define M_X_WIDE_REQ EXTENDED_WDTR
+#define M_X_PPR_REQ EXTENDED_PPR
+
+/*
+** Status
+*/
+
+#define S_GOOD (0x00)
+#define S_CHECK_COND (0x02)
+#define S_COND_MET (0x04)
+#define S_BUSY (0x08)
+#define S_INT (0x10)
+#define S_INT_COND_MET (0x14)
+#define S_CONFLICT (0x18)
+#define S_TERMINATED (0x20)
+#define S_QUEUE_FULL (0x28)
+#define S_ILLEGAL (0xff)
+#define S_SENSE (0x80)
+
+/*
+ * End of ncrreg from FreeBSD
+ */
/*
Build a scatter/gather entry.
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
index 5d9c9ada814f..dee426f8c07b 100644
--- a/drivers/scsi/oktagon_esp.c
+++ b/drivers/scsi/oktagon_esp.c
@@ -490,7 +490,7 @@ static void dma_led_on(struct NCR_ESP *esp)
static int dma_ports_p(struct NCR_ESP *esp)
{
- return ((custom.intenar) & IF_PORTS);
+ return ((amiga_custom.intenar) & IF_PORTS);
}
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 7c5306499832..0c9edb7051f4 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -95,27 +95,21 @@ typedef struct scsi_info_t {
} scsi_info_t;
static void aha152x_release_cs(dev_link_t *link);
-static int aha152x_event(event_t event, int priority,
- event_callback_args_t *args);
-
-static dev_link_t *aha152x_attach(void);
-static void aha152x_detach(dev_link_t *);
+static void aha152x_detach(struct pcmcia_device *p_dev);
+static void aha152x_config_cs(dev_link_t *link);
static dev_link_t *dev_list;
-static dev_info_t dev_info = "aha152x_cs";
-static dev_link_t *aha152x_attach(void)
+static int aha152x_attach(struct pcmcia_device *p_dev)
{
scsi_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
DEBUG(0, "aha152x_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return NULL;
+ if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info;
@@ -129,26 +123,20 @@ static dev_link_t *aha152x_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- aha152x_detach(link);
- return NULL;
- }
-
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ aha152x_config_cs(link);
+
+ return 0;
} /* aha152x_attach */
/*====================================================================*/
-static void aha152x_detach(dev_link_t *link)
+static void aha152x_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp;
DEBUG(0, "aha152x_detach(0x%p)\n", link);
@@ -162,9 +150,6 @@ static void aha152x_detach(dev_link_t *link)
if (link->state & DEV_CONFIG)
aha152x_release_cs(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(link->priv);
@@ -272,44 +257,31 @@ static void aha152x_release_cs(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-static int aha152x_event(event_t event, int priority,
- event_callback_args_t *args)
+static int aha152x_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- scsi_info_t *info = link->priv;
-
- DEBUG(0, "aha152x_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- aha152x_release_cs(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- aha152x_config_cs(link);
- break;
- case CS_EVENT_PM_SUSPEND:
+ dev_link_t *link = dev_to_instance(dev);
+
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int aha152x_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ scsi_info_t *info = link->priv;
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- Scsi_Cmnd tmp;
- pcmcia_request_configuration(link->handle, &link->conf);
- tmp.device->host = info->host;
- aha152x_host_reset(&tmp);
+ Scsi_Cmnd tmp;
+ pcmcia_request_configuration(link->handle, &link->conf);
+ tmp.device->host = info->host;
+ aha152x_host_reset(&tmp);
}
- break;
- }
- return 0;
+
+ return 0;
}
static struct pcmcia_device_id aha152x_ids[] = {
@@ -327,10 +299,11 @@ static struct pcmcia_driver aha152x_cs_driver = {
.drv = {
.name = "aha152x_cs",
},
- .attach = aha152x_attach,
- .event = aha152x_event,
- .detach = aha152x_detach,
+ .probe = aha152x_attach,
+ .remove = aha152x_detach,
.id_table = aha152x_ids,
+ .suspend = aha152x_suspend,
+ .resume = aha152x_resume,
};
static int __init init_aha152x_cs(void)
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index db8f5cd85ffe..788c58d805f3 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -80,29 +80,19 @@ typedef struct scsi_info_t {
static void fdomain_release(dev_link_t *link);
-static int fdomain_event(event_t event, int priority,
- event_callback_args_t *args);
+static void fdomain_detach(struct pcmcia_device *p_dev);
+static void fdomain_config(dev_link_t *link);
-static dev_link_t *fdomain_attach(void);
-static void fdomain_detach(dev_link_t *);
-
-
-static dev_link_t *dev_list = NULL;
-
-static dev_info_t dev_info = "fdomain_cs";
-
-static dev_link_t *fdomain_attach(void)
+static int fdomain_attach(struct pcmcia_device *p_dev)
{
scsi_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
-
+
DEBUG(0, "fdomain_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info) return NULL;
+ if (!info) return -ENOMEM;
memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info;
link->io.NumPorts1 = 0x10;
@@ -115,46 +105,27 @@ static dev_link_t *fdomain_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- fdomain_detach(link);
- return NULL;
- }
-
- return link;
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ fdomain_config(link);
+
+ return 0;
} /* fdomain_attach */
/*====================================================================*/
-static void fdomain_detach(dev_link_t *link)
+static void fdomain_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
- DEBUG(0, "fdomain_detach(0x%p)\n", link);
-
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) break;
- if (*linkp == NULL)
- return;
+ DEBUG(0, "fdomain_detach(0x%p)\n", link);
- if (link->state & DEV_CONFIG)
- fdomain_release(link);
+ if (link->state & DEV_CONFIG)
+ fdomain_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
- kfree(link->priv);
-
+ kfree(link->priv);
} /* fdomain_detach */
/*====================================================================*/
@@ -256,43 +227,29 @@ static void fdomain_release(dev_link_t *link)
/*====================================================================*/
-static int fdomain_event(event_t event, int priority,
- event_callback_args_t *args)
+static int fdomain_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
- DEBUG(1, "fdomain_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- fdomain_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- fdomain_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int fdomain_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- fdomain_16x0_bus_reset(NULL);
+ pcmcia_request_configuration(link->handle, &link->conf);
+ fdomain_16x0_bus_reset(NULL);
}
- break;
- }
- return 0;
-} /* fdomain_event */
+ return 0;
+}
static struct pcmcia_device_id fdomain_ids[] = {
PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20),
@@ -307,10 +264,11 @@ static struct pcmcia_driver fdomain_cs_driver = {
.drv = {
.name = "fdomain_cs",
},
- .attach = fdomain_attach,
- .event = fdomain_event,
- .detach = fdomain_detach,
+ .probe = fdomain_attach,
+ .remove = fdomain_detach,
.id_table = fdomain_ids,
+ .suspend = fdomain_suspend,
+ .resume = fdomain_resume,
};
static int __init init_fdomain_cs(void)
@@ -321,7 +279,6 @@ static int __init init_fdomain_cs(void)
static void __exit exit_fdomain_cs(void)
{
pcmcia_unregister_driver(&fdomain_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_fdomain_cs);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 050ea13ff80b..9e3ab3fd5355 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -104,9 +104,6 @@ static struct scsi_host_template nsp_driver_template = {
#endif
};
-static dev_link_t *dev_list = NULL;
-static dev_info_t dev_info = {"nsp_cs"};
-
static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
@@ -1596,19 +1593,17 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
configure the card at this point -- we wait until we receive a
card insertion event.
======================================================================*/
-static dev_link_t *nsp_cs_attach(void)
+static int nsp_cs_attach(struct pcmcia_device *p_dev)
{
scsi_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
nsp_hw_data *data = &nsp_data_base;
nsp_dbg(NSP_DEBUG_INIT, "in");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (info == NULL) { return NULL; }
+ if (info == NULL) { return -ENOMEM; }
memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
@@ -1636,23 +1631,14 @@ static dev_link_t *nsp_cs_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
+ link->handle = p_dev;
+ p_dev->instance = link;
- /* Register with Card Services */
- 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);
- nsp_cs_detach(link);
- return NULL;
- }
-
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
- return link;
+ return 0;
} /* nsp_cs_attach */
@@ -1662,35 +1648,19 @@ static dev_link_t *nsp_cs_attach(void)
structures are freed. Otherwise, the structures will be freed
when the device is released.
======================================================================*/
-static void nsp_cs_detach(dev_link_t *link)
+static void nsp_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
- if (*linkp == link) {
- break;
- }
- }
- if (*linkp == NULL) {
- return;
- }
-
- if (link->state & DEV_CONFIG)
+ if (link->state & DEV_CONFIG) {
+ ((scsi_info_t *)link->priv)->stop = 1;
nsp_cs_release(link);
-
- /* Break the link with Card Services */
- if (link->handle) {
- pcmcia_deregister_client(link->handle);
}
- /* Unlink device structure, free bits */
- *linkp = link->next;
kfree(link->priv);
link->priv = NULL;
-
} /* nsp_cs_detach */
@@ -2021,99 +1991,58 @@ static void nsp_cs_release(dev_link_t *link)
#endif
} /* nsp_cs_release */
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the net drivers from trying
- to talk to the card any more.
-
- When a CARD_REMOVAL event is received, we immediately set a flag
- to block future accesses to this device. All the functions that
- actually access the device should check this flag to make sure
- the card is still present.
-
-======================================================================*/
-static int nsp_cs_event(event_t event,
- int priority,
- event_callback_args_t *args)
+static int nsp_cs_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
- nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event);
+ link->state |= DEV_SUSPEND;
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- nsp_dbg(NSP_DEBUG_INIT, "event: remove");
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- ((scsi_info_t *)link->priv)->stop = 1;
- nsp_cs_release(link);
- }
- break;
+ nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
- case CS_EVENT_CARD_INSERTION:
- nsp_dbg(NSP_DEBUG_INIT, "event: insert");
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
- info->bus = args->bus;
-#endif
- nsp_cs_config(link);
- break;
+ if (info->host != NULL) {
+ nsp_msg(KERN_INFO, "clear SDTR status");
- case CS_EVENT_PM_SUSPEND:
- nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- /* Mark the device as stopped, to block IO until later */
- nsp_dbg(NSP_DEBUG_INIT, "event: reset physical");
+ data = (nsp_hw_data *)info->host->hostdata;
- if (info->host != NULL) {
- nsp_msg(KERN_INFO, "clear SDTR status");
+ nsphw_init_sync(data);
+ }
- data = (nsp_hw_data *)info->host->hostdata;
+ info->stop = 1;
- nsphw_init_sync(data);
- }
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
- info->stop = 1;
- if (link->state & DEV_CONFIG) {
- pcmcia_release_configuration(link->handle);
- }
- break;
+ return 0;
+}
- case CS_EVENT_PM_RESUME:
- nsp_dbg(NSP_DEBUG_INIT, "event: resume");
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- nsp_dbg(NSP_DEBUG_INIT, "event: reset");
- if (link->state & DEV_CONFIG) {
- pcmcia_request_configuration(link->handle, &link->conf);
- }
- info->stop = 0;
+static int nsp_cs_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ scsi_info_t *info = link->priv;
+ nsp_hw_data *data;
- if (info->host != NULL) {
- nsp_msg(KERN_INFO, "reset host and bus");
+ nsp_dbg(NSP_DEBUG_INIT, "event: resume");
- data = (nsp_hw_data *)info->host->hostdata;
+ link->state &= ~DEV_SUSPEND;
- nsphw_init (data);
- nsp_bus_reset(data);
- }
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
- break;
+ info->stop = 0;
- default:
- nsp_dbg(NSP_DEBUG_INIT, "event: unknown");
- break;
+ if (info->host != NULL) {
+ nsp_msg(KERN_INFO, "reset host and bus");
+
+ data = (nsp_hw_data *)info->host->hostdata;
+
+ nsphw_init (data);
+ nsp_bus_reset(data);
}
- nsp_dbg(NSP_DEBUG_INIT, "end");
+
return 0;
-} /* nsp_cs_event */
+}
/*======================================================================*
* module entry point
@@ -2136,10 +2065,11 @@ static struct pcmcia_driver nsp_driver = {
.drv = {
.name = "nsp_cs",
},
- .attach = nsp_cs_attach,
- .event = nsp_cs_event,
- .detach = nsp_cs_detach,
+ .probe = nsp_cs_attach,
+ .remove = nsp_cs_detach,
.id_table = nsp_cs_ids,
+ .suspend = nsp_cs_suspend,
+ .resume = nsp_cs_resume,
};
#endif
@@ -2171,7 +2101,6 @@ static void __exit nsp_cs_exit(void)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
- BUG_ON(dev_list != NULL);
#else
unregister_pcmcia_driver(&dev_info);
/* XXX: this really needs to move into generic code.. */
diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h
index f8b943082717..b66b140a745e 100644
--- a/drivers/scsi/pcmcia/nsp_cs.h
+++ b/drivers/scsi/pcmcia/nsp_cs.h
@@ -296,11 +296,9 @@ typedef struct _nsp_hw_data {
*/
/* Card service functions */
-static dev_link_t *nsp_cs_attach (void);
-static void nsp_cs_detach (dev_link_t *link);
+static void nsp_cs_detach (struct pcmcia_device *p_dev);
static void nsp_cs_release(dev_link_t *link);
static void nsp_cs_config (dev_link_t *link);
-static int nsp_cs_event (event_t event, int priority, event_callback_args_t *args);
/* Linux SCSI subsystem specific functions */
static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index bb091a45a880..dce7e687fd4a 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -98,15 +98,8 @@ typedef struct scsi_info_t {
} scsi_info_t;
static void qlogic_release(dev_link_t *link);
-static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
-
-static dev_link_t *qlogic_attach(void);
-static void qlogic_detach(dev_link_t *);
-
-
-static dev_link_t *dev_list = NULL;
-
-static dev_info_t dev_info = "qlogic_cs";
+static void qlogic_detach(struct pcmcia_device *p_dev);
+static void qlogic_config(dev_link_t * link);
static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
dev_link_t *link, int qbase, int qlirq)
@@ -163,19 +156,17 @@ free_scsi_host:
err:
return NULL;
}
-static dev_link_t *qlogic_attach(void)
+static int qlogic_attach(struct pcmcia_device *p_dev)
{
scsi_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
DEBUG(0, "qlogic_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
@@ -189,45 +180,26 @@ static dev_link_t *qlogic_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- qlogic_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ qlogic_config(link);
+
+ return 0;
} /* qlogic_attach */
/*====================================================================*/
-static void qlogic_detach(dev_link_t * link)
+static void qlogic_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "qlogic_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp == NULL)
- return;
-
if (link->state & DEV_CONFIG)
qlogic_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
kfree(link->priv);
} /* qlogic_detach */
@@ -349,48 +321,39 @@ static void qlogic_release(dev_link_t *link)
/*====================================================================*/
-static int qlogic_event(event_t event, int priority, event_callback_args_t * args)
+static int qlogic_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
-
- DEBUG(1, "qlogic_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- qlogic_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- qlogic_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- 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) {
- scsi_info_t *info = link->priv;
- pcmcia_request_configuration(link->handle, &link->conf);
- if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /* Ugggglllyyyy!!! */
- qlogicfas408_bus_reset(NULL);
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int qlogic_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ scsi_info_t *info = link->priv;
+
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
- break;
+ /* Ugggglllyyyy!!! */
+ qlogicfas408_bus_reset(NULL);
}
+
return 0;
-} /* qlogic_event */
+}
static struct pcmcia_device_id qlogic_ids[] = {
PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6),
@@ -419,10 +382,11 @@ static struct pcmcia_driver qlogic_cs_driver = {
.drv = {
.name = "qlogic_cs",
},
- .attach = qlogic_attach,
- .event = qlogic_event,
- .detach = qlogic_detach,
+ .probe = qlogic_attach,
+ .remove = qlogic_detach,
.id_table = qlogic_ids,
+ .suspend = qlogic_suspend,
+ .resume = qlogic_resume,
};
static int __init init_qlogic_cs(void)
@@ -433,7 +397,6 @@ static int __init init_qlogic_cs(void)
static void __exit exit_qlogic_cs(void)
{
pcmcia_unregister_driver(&qlogic_cs_driver);
- BUG_ON(dev_list != NULL);
}
MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 98b64b2aa8ee..3a4dd6f5b81f 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -228,15 +228,6 @@ enum Phase {
/* ================================================================== */
-/*
-* Global (within this module) variables other than
-* sym53c500_driver_template (the scsi_host_template).
-*/
-static dev_link_t *dev_list;
-static dev_info_t dev_info = "sym53c500_cs";
-
-/* ================================================================== */
-
static void
chip_init(int io_port)
{
@@ -872,96 +863,70 @@ cs_failed:
return;
} /* SYM53C500_config */
-static int
-SYM53C500_event(event_t event, int priority, event_callback_args_t *args)
+static int sym53c500_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- struct scsi_info_t *info = link->priv;
+ dev_link_t *link = dev_to_instance(dev);
- DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- SYM53C500_release(link);
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- SYM53C500_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- 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) {
- pcmcia_request_configuration(link->handle, &link->conf);
- /* See earlier comment about manufacturer IDs. */
- if ((info->manf_id == MANFID_MACNICA) ||
- (info->manf_id == MANFID_PIONEER) ||
- (info->manf_id == 0x0098)) {
- outb(0x80, link->io.BasePort1 + 0xd);
- outb(0x24, link->io.BasePort1 + 0x9);
- outb(0x04, link->io.BasePort1 + 0xd);
- }
- /*
- * If things don't work after a "resume",
- * this is a good place to start looking.
- */
- SYM53C500_int_host_reset(link->io.BasePort1);
+ return 0;
+}
+
+static int sym53c500_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ struct scsi_info_t *info = link->priv;
+
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG) {
+ pcmcia_request_configuration(link->handle, &link->conf);
+
+ /* See earlier comment about manufacturer IDs. */
+ if ((info->manf_id == MANFID_MACNICA) ||
+ (info->manf_id == MANFID_PIONEER) ||
+ (info->manf_id == 0x0098)) {
+ outb(0x80, link->io.BasePort1 + 0xd);
+ outb(0x24, link->io.BasePort1 + 0x9);
+ outb(0x04, link->io.BasePort1 + 0xd);
}
- break;
+ /*
+ * If things don't work after a "resume",
+ * this is a good place to start looking.
+ */
+ SYM53C500_int_host_reset(link->io.BasePort1);
}
+
return 0;
-} /* SYM53C500_event */
+}
static void
-SYM53C500_detach(dev_link_t *link)
+SYM53C500_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp == NULL)
- return;
-
if (link->state & DEV_CONFIG)
SYM53C500_release(link);
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
- /* Unlink device structure, free bits. */
- *linkp = link->next;
kfree(link->priv);
link->priv = NULL;
} /* SYM53C500_detach */
-static dev_link_t *
-SYM53C500_attach(void)
+static int
+SYM53C500_attach(struct pcmcia_device *p_dev)
{
struct scsi_info_t *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
DEBUG(0, "SYM53C500_attach()\n");
/* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
@@ -975,20 +940,13 @@ SYM53C500_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- 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 != 0) {
- cs_error(link->handle, RegisterClient, ret);
- SYM53C500_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ SYM53C500_config(link);
- return link;
+ return 0;
} /* SYM53C500_attach */
MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@@ -1008,10 +966,11 @@ static struct pcmcia_driver sym53c500_cs_driver = {
.drv = {
.name = "sym53c500_cs",
},
- .attach = SYM53C500_attach,
- .event = SYM53C500_event,
- .detach = SYM53C500_detach,
+ .probe = SYM53C500_attach,
+ .remove = SYM53C500_detach,
.id_table = sym53c500_ids,
+ .suspend = sym53c500_suspend,
+ .resume = sym53c500_resume,
};
static int __init
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index f557f17ca00c..e8df0c9ec1e6 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -464,14 +464,12 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set)
continue;
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
- unsigned int err_mask = 0;
-
if ((status & (aPERR | aPSD | aUIRQ)))
- err_mask = AC_ERR_OTHER;
+ qc->err_mask |= AC_ERR_OTHER;
else if (pp->pkt[0] != cDONE)
- err_mask = AC_ERR_OTHER;
+ qc->err_mask |= AC_ERR_OTHER;
- ata_qc_complete(qc, err_mask);
+ ata_qc_complete(qc);
}
}
return handled;
@@ -501,7 +499,8 @@ static inline unsigned int adma_intr_mmio(struct ata_host_set *host_set)
/* complete taskfile transaction */
pp->state = adma_state_idle;
- ata_qc_complete(qc, ac_err_mask(status));
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
handled = 1;
}
}
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index c1c1c687bcbd..5758b2566d7f 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -1,55 +1,78 @@
-config SCSI_QLA2XXX
- tristate
- default (SCSI && PCI)
- depends on SCSI && PCI
+config SCSI_QLA_FC
+ tristate "QLogic QLA2XXX Fibre Channel Support"
+ depends on PCI && SCSI
+ select SCSI_FC_ATTRS
+ select FW_LOADER
+ ---help---
+ This qla2xxx driver supports all QLogic Fibre Channel
+ PCI and PCIe host adapters.
+
+ By default, firmware for the ISP parts will be loaded
+ via the Firmware Loader interface.
+
+ ISP Firmware Filename
+ ---------- -----------------
+ 21xx ql2100_fw.bin
+ 22xx ql2200_fw.bin
+ 2300, 2312 ql2300_fw.bin
+ 2322 ql2322_fw.bin
+ 6312, 6322 ql6312_fw.bin
+ 24xx ql2400_fw.bin
+
+ Upon request, the driver caches the firmware image until
+ the driver is unloaded.
+
+ Firmware images can be retrieved from:
+
+ ftp://ftp.qlogic.com/outgoing/linux/firmware/
+
+ NOTE: The original method of building firmware-loader
+ modules has been deprecated as the firmware-images will
+ be removed from the kernel sources.
+
+config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
+ bool " Use firmware-loader modules (DEPRECATED)"
+ depends on SCSI_QLA_FC
+ help
+ This option offers you the deprecated firmware-loader
+ modules that have been obsoleted by the usage of the
+ Firmware Loader interface in the qla2xxx driver.
config SCSI_QLA21XX
- tristate "QLogic ISP2100 host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP2100 firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 21xx (ISP2100) host adapter family.
config SCSI_QLA22XX
- tristate "QLogic ISP2200 host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP2200 firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 22xx (ISP2200) host adapter family.
config SCSI_QLA2300
- tristate "QLogic ISP2300 host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP2300 firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2300 (ISP2300 and ISP2312) host
adapter family.
config SCSI_QLA2322
- tristate "QLogic ISP2322 host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP2322 firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 2322 (ISP2322) host adapter family.
config SCSI_QLA6312
- tristate "QLogic ISP63xx host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP63xx firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 63xx (ISP6312 and ISP6322) host
adapter family.
config SCSI_QLA24XX
- tristate "QLogic ISP24xx host adapter family support"
- depends on SCSI_QLA2XXX
- select SCSI_FC_ATTRS
- select FW_LOADER
+ tristate " Build QLogic ISP24xx firmware-module"
+ depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
---help---
This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index b169687d08ff..d028bc50ccf7 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -3,15 +3,18 @@ EXTRA_CFLAGS += -DUNIQUE_FW_NAME
qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
+obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
+
qla2100-y := ql2100.o ql2100_fw.o
qla2200-y := ql2200.o ql2200_fw.o
qla2300-y := ql2300.o ql2300_fw.o
qla2322-y := ql2322.o ql2322_fw.o
qla6312-y := ql6312.o ql6312_fw.o
+qla2400-y := ql2400.o ql2400_fw.o
obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
obj-$(CONFIG_SCSI_QLA6312) += qla2xxx.o qla6312.o
-obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o
+obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o
diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c
new file mode 100644
index 000000000000..6c7165f47e29
--- /dev/null
+++ b/drivers/scsi/qla2xxx/ql2400.c
@@ -0,0 +1,111 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2005 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "qla_def.h"
+
+static char qla_driver_name[] = "qla2400";
+
+extern uint32_t fw2400_version_str[];
+extern uint32_t fw2400_addr01;
+extern uint32_t fw2400_code01[];
+extern uint32_t fw2400_length01;
+extern uint32_t fw2400_addr02;
+extern uint32_t fw2400_code02[];
+extern uint32_t fw2400_length02;
+
+static struct qla_fw_info qla_fw_tbl[] = {
+ {
+ .addressing = FW_INFO_ADDR_EXTENDED,
+ .fwcode = (unsigned short *)&fw2400_code01[0],
+ .fwlen = (unsigned short *)&fw2400_length01,
+ .lfwstart = (unsigned long *)&fw2400_addr01,
+ },
+ {
+ .addressing = FW_INFO_ADDR_EXTENDED,
+ .fwcode = (unsigned short *)&fw2400_code02[0],
+ .fwlen = (unsigned short *)&fw2400_length02,
+ .lfwstart = (unsigned long *)&fw2400_addr02,
+ },
+ { FW_INFO_ADDR_NOMORE, },
+};
+
+static struct qla_board_info qla_board_tbl[] = {
+ {
+ .drv_name = qla_driver_name,
+ .isp_name = "ISP2422",
+ .fw_info = qla_fw_tbl,
+ .fw_fname = "ql2400_fw.bin",
+ },
+ {
+ .drv_name = qla_driver_name,
+ .isp_name = "ISP2432",
+ .fw_info = qla_fw_tbl,
+ .fw_fname = "ql2400_fw.bin",
+ },
+};
+
+static struct pci_device_id qla24xx_pci_tbl[] = {
+ {
+ .vendor = PCI_VENDOR_ID_QLOGIC,
+ .device = PCI_DEVICE_ID_QLOGIC_ISP2422,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (unsigned long)&qla_board_tbl[0],
+ },
+ {
+ .vendor = PCI_VENDOR_ID_QLOGIC,
+ .device = PCI_DEVICE_ID_QLOGIC_ISP2432,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (unsigned long)&qla_board_tbl[1],
+ },
+ {0, 0},
+};
+MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);
+
+static int __devinit
+qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ return qla2x00_probe_one(pdev,
+ (struct qla_board_info *)id->driver_data);
+}
+
+static void __devexit
+qla24xx_remove_one(struct pci_dev *pdev)
+{
+ qla2x00_remove_one(pdev);
+}
+
+static struct pci_driver qla24xx_pci_driver = {
+ .name = "qla2400",
+ .id_table = qla24xx_pci_tbl,
+ .probe = qla24xx_probe_one,
+ .remove = __devexit_p(qla24xx_remove_one),
+};
+
+static int __init
+qla24xx_init(void)
+{
+ return pci_module_init(&qla24xx_pci_driver);
+}
+
+static void __exit
+qla24xx_exit(void)
+{
+ pci_unregister_driver(&qla24xx_pci_driver);
+}
+
+module_init(qla24xx_init);
+module_exit(qla24xx_exit);
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c
new file mode 100644
index 000000000000..5977795854f8
--- /dev/null
+++ b/drivers/scsi/qla2xxx/ql2400_fw.c
@@ -0,0 +1,12376 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c) 2003-2005 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include <linux/types.h>
+
+/*
+ * Firmware Version 4.00.16 (08:09 Oct 26, 2005)
+ */
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_version = 4*1024+0;
+#else
+uint32_t risc_code_version = 4*1024+0;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_version_str[] = {4, 0,16};
+#else
+uint32_t firmware_version[] = {4, 0,16};
+#endif
+
+#ifdef UNIQUE_FW_NAME
+#define fw2400_VERSION_STRING "4.00.16"
+#else
+#define FW_VERSION_STRING "4.00.16"
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_addr01 = 0x00100000 ;
+#else
+uint32_t risc_code_addr01 = 0x00100000 ;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_code01[] = {
+#else
+uint32_t risc_code01[] = {
+#endif
+ 0x0401f17c, 0x0010e000, 0x00100000, 0x0000ab4a,
+ 0x00000004, 0x00000000, 0x00000010, 0x00000002,
+ 0x00000003, 0x00000000, 0x20434f50, 0x59524947,
+ 0x48542032, 0x30303520, 0x514c4f47, 0x49432043,
+ 0x4f52504f, 0x52415449, 0x4f4e2020, 0x20495350,
+ 0x32347878, 0x20466972, 0x6d776172, 0x65202020,
+ 0x56657273, 0x696f6e20, 0x342e302e, 0x31362020,
+ 0x20202024, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x42001800, 0x0010014f, 0x42002000, 0x0010b8fe,
+ 0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800,
+ 0x54042000, 0x80102000, 0x80040800, 0x80081040,
+ 0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6,
+ 0x44002000, 0x80102000, 0x40100000, 0x44040000,
+ 0x80000000, 0x44080000, 0x80000000, 0x440c0000,
+ 0x80000000, 0x44100000, 0x80000000, 0x44140000,
+ 0x80000000, 0x44180000, 0x80000000, 0x441c0000,
+ 0x80000000, 0x44200000, 0x80000000, 0x44240000,
+ 0x80000000, 0x44280000, 0x80000000, 0x442c0000,
+ 0x80000000, 0x44300000, 0x80000000, 0x44340000,
+ 0x80000000, 0x44380000, 0x80000000, 0x443c0000,
+ 0x80000000, 0x44400000, 0x80000000, 0x44440000,
+ 0x80000000, 0x44480000, 0x80000000, 0x444c0000,
+ 0x80000000, 0x44500000, 0x80000000, 0x44540000,
+ 0x80000000, 0x44580000, 0x80000000, 0x445c0000,
+ 0x80000000, 0x44600000, 0x80000000, 0x44640000,
+ 0x80000000, 0x44680000, 0x80000000, 0x446c0000,
+ 0x80000000, 0x44700000, 0x80000000, 0x44740000,
+ 0x80000000, 0x44780000, 0x80000000, 0x447c0000,
+ 0x80000000, 0x44800000, 0x80000000, 0x44840000,
+ 0x80000000, 0x44880000, 0x80000000, 0x448c0000,
+ 0x80000000, 0x44900000, 0x80000000, 0x44940000,
+ 0x80000000, 0x44980000, 0x80000000, 0x449c0000,
+ 0x80000000, 0x44a00000, 0x80000000, 0x44a40000,
+ 0x80000000, 0x44a80000, 0x80000000, 0x44ac0000,
+ 0x80000000, 0x44b00000, 0x80000000, 0x44b40000,
+ 0x80000000, 0x44b80000, 0x80000000, 0x44bc0000,
+ 0x80000000, 0x44c00000, 0x80000000, 0x44c40000,
+ 0x80000000, 0x44c80000, 0x80000000, 0x44cc0000,
+ 0x80000000, 0x44d00000, 0x80000000, 0x44d80000,
+ 0x80000000, 0x44d40000, 0x80000000, 0x44dc0000,
+ 0x80000000, 0x44e00000, 0x80000000, 0x44e40000,
+ 0x80000000, 0x44e80000, 0x80000000, 0x44ec0000,
+ 0x80000000, 0x44f00000, 0x80000000, 0x44f40000,
+ 0x80000000, 0x44f80000, 0x80000000, 0x44fc0000,
+ 0x80000000, 0x45000000, 0x80000000, 0x45040000,
+ 0x80000000, 0x45080000, 0x80000000, 0x450c0000,
+ 0x80000000, 0x45100000, 0x80000000, 0x45140000,
+ 0x80000000, 0x45180000, 0x80000000, 0x451c0000,
+ 0x80000000, 0x45200000, 0x80000000, 0x45240000,
+ 0x80000000, 0x45280000, 0x80000000, 0x452c0000,
+ 0x80000000, 0x45300000, 0x80000000, 0x45340000,
+ 0x80000000, 0x45380000, 0x80000000, 0x453c0000,
+ 0x80000000, 0x45400000, 0x80000000, 0x45440000,
+ 0x80000000, 0x45480000, 0x80000000, 0x454c0000,
+ 0x80000000, 0x45500000, 0x80000000, 0x45540000,
+ 0x80000000, 0x45580000, 0x80000000, 0x455c0000,
+ 0x80000000, 0x45600000, 0x80000000, 0x45640000,
+ 0x80000000, 0x45680000, 0x80000000, 0x456c0000,
+ 0x80000000, 0x45700000, 0x80000000, 0x45740000,
+ 0x80000000, 0x45780000, 0x80000000, 0x457c0000,
+ 0x80000000, 0x45800000, 0x80000000, 0x45840000,
+ 0x80000000, 0x45880000, 0x80000000, 0x458c0000,
+ 0x80000000, 0x45900000, 0x80000000, 0x45940000,
+ 0x80000000, 0x45980000, 0x80000000, 0x459c0000,
+ 0x80000000, 0x45a00000, 0x80000000, 0x45a40000,
+ 0x80000000, 0x45a80000, 0x80000000, 0x45ac0000,
+ 0x80000000, 0x45b00000, 0x80000000, 0x45b40000,
+ 0x80000000, 0x45b80000, 0x80000000, 0x45bc0000,
+ 0x80000000, 0x45c00000, 0x80000000, 0x45c40000,
+ 0x80000000, 0x45c80000, 0x80000000, 0x45cc0000,
+ 0x80000000, 0x45d00000, 0x80000000, 0x45d40000,
+ 0x80000000, 0x45d80000, 0x80000000, 0x45dc0000,
+ 0x80000000, 0x45e00000, 0x80000000, 0x45e40000,
+ 0x80000000, 0x45e80000, 0x80000000, 0x45ec0000,
+ 0x80000000, 0x45f00000, 0x80000000, 0x45f40000,
+ 0x80000000, 0x45f80000, 0x80000000, 0x45fc0000,
+ 0x4a03c020, 0x00004000, 0x4a03c011, 0x40000010,
+ 0x04006000, 0x4203e000, 0x40000000, 0x59e00017,
+ 0x8c000508, 0x04000003, 0x4a03c017, 0x00000000,
+ 0x4203e000, 0x30000001, 0x0401f000, 0x0000bf00,
+ 0x00000080, 0x0000bfe0, 0x00000020, 0x0000ff00,
+ 0x00000080, 0x0000ffd0, 0x00000030, 0x00007100,
+ 0x00000010, 0x00007200, 0x00000008, 0x00007209,
+ 0x00000007, 0x00007300, 0x00000008, 0x00007309,
+ 0x00000007, 0x00007400, 0x00000008, 0x00007409,
+ 0x00000007, 0x00007600, 0x000000b0, 0x00007700,
+ 0x00000040, 0x00003000, 0x00000070, 0x00004000,
+ 0x000000c0, 0x00006000, 0x00000050, 0x00006100,
+ 0x00000010, 0x00006130, 0x00000010, 0x00006150,
+ 0x00000010, 0x00006170, 0x00000010, 0x00006190,
+ 0x00000010, 0x000061b0, 0x00000010, 0x00000000,
+ 0x42000000, 0x00000100, 0x4202f000, 0x00000000,
+ 0x42000800, 0x00021f00, 0x45780800, 0x80040800,
+ 0x80000040, 0x040207fd, 0x4203f000, 0x00021fff,
+ 0x40000000, 0x4203e000, 0x90000100, 0x40000000,
+ 0x0201f800, 0x001006fd, 0x42000000, 0x00001000,
+ 0x50000000, 0x82000480, 0x24320002, 0x04020015,
+ 0x42000800, 0x00000064, 0x80040840, 0x04000007,
+ 0x4a030000, 0x00000001, 0x40000000, 0x59800000,
+ 0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
+ 0x00007a17, 0x50040000, 0x8c00050e, 0x04020003,
+ 0x8400054e, 0x44000800, 0x4a030000, 0x00000000,
+ 0x4a03c020, 0x00000004, 0x4203e000, 0x6000000f,
+ 0x59e00023, 0x8c000500, 0x04020039, 0x42000000,
+ 0x00100001, 0x50000800, 0x82040c00, 0x00000004,
+ 0x58042003, 0x42001000, 0xffffffff, 0x0201f800,
+ 0x001006f4, 0x0402004e, 0x58042003, 0x42001000,
+ 0xffffffff, 0x0201f800, 0x001006f4, 0x04020048,
+ 0x58042003, 0x42001000, 0x00ffffff, 0x0201f800,
+ 0x001006f4, 0x04020042, 0x58042003, 0x42001000,
+ 0x00ffffff, 0x0201f800, 0x001006f4, 0x0402003c,
+ 0x42000000, 0x00100001, 0x5000a000, 0x8250a400,
+ 0x00000004, 0x4200a800, 0x00020000, 0x5850b003,
+ 0x0201f800, 0x0010ab17, 0x8250a400, 0x00000005,
+ 0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000,
+ 0x5850b003, 0x0201f800, 0x0010ab17, 0x4a0378e8,
+ 0x00000003, 0x4200a800, 0x00008000, 0x5850b003,
+ 0x0201f800, 0x0010ab17, 0x0401f02b, 0x42000800,
+ 0x00020000, 0x58042003, 0x42001000, 0xffffffff,
+ 0x0201f800, 0x001006f4, 0x04020019, 0x4a0370e8,
+ 0x00000003, 0x42000800, 0x0000c000, 0x58042003,
+ 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
+ 0x0201f800, 0x001006f4, 0x0402000d, 0x4a0378e8,
+ 0x00000003, 0x42000800, 0x00008000, 0x58042003,
+ 0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
+ 0x0201f800, 0x001006f4, 0x0400000b, 0x4a03c020,
+ 0x00004010, 0x4a03c011, 0x40100011, 0x04006000,
+ 0x4203e000, 0x40000000, 0x4203e000, 0x30000001,
+ 0x0401f000, 0x0201f800, 0x00100791, 0x42001000,
+ 0x0010ab4a, 0x40080000, 0x80140480, 0x82001d00,
+ 0xffffff00, 0x04020003, 0x40001800, 0x0401f003,
+ 0x42001800, 0x000000ff, 0x480bc840, 0x480fc842,
+ 0x04011000, 0x400c0000, 0x80081400, 0x40140000,
+ 0x80080580, 0x040207f0, 0x4817500d, 0x45782800,
+ 0x59c40000, 0x82000500, 0xffff0000, 0x80000120,
+ 0x82000580, 0x00002422, 0x04020005, 0x59a80005,
+ 0x8400054e, 0x48035005, 0x0401f008, 0x59e00003,
+ 0x82000500, 0x00030000, 0x04000004, 0x59a80005,
+ 0x84000554, 0x48035005, 0x42000800, 0x00000040,
+ 0x59a80005, 0x8c000514, 0x0402000e, 0x42000800,
+ 0x00001000, 0x82141480, 0x0017ffff, 0x04021009,
+ 0x80040902, 0x82141480, 0x0013ffff, 0x04021005,
+ 0x80040902, 0x82141480, 0x0011ffff, 0x04001b8d,
+ 0x4807500e, 0x42001000, 0x00000024, 0x0201f800,
+ 0x00106681, 0x82040c00, 0x0010d1c0, 0x4807500b,
+ 0x4a03c810, 0x00100000, 0x4a03c811, 0x0010ab4a,
+ 0x4a03c829, 0x00000004, 0x59e40001, 0x82000540,
+ 0x0003001d, 0x4803c801, 0x4a03c014, 0x001c001c,
+ 0x42001000, 0x0000001c, 0x0201f800, 0x001006e2,
+ 0x4202c000, 0x0010d1c0, 0x59aab00b, 0x59aaa00b,
+ 0x59aaa80b, 0x59aac80e, 0x49675069, 0x59a8000b,
+ 0x4803500c, 0x0401fbf5, 0x0201f800, 0x00107903,
+ 0x0201f800, 0x001007be, 0x0201f800, 0x00100807,
+ 0x0201f800, 0x00101a05, 0x0201f800, 0x00101354,
+ 0x0201f800, 0x00100969, 0x0201f800, 0x00101354,
+ 0x0201f800, 0x00100f4c, 0x0201f800, 0x001066c1,
+ 0x0401fb1a, 0x0201f800, 0x0010220e, 0x0201f800,
+ 0x001053bb, 0x0201f800, 0x00104c90, 0x0201f800,
+ 0x00106194, 0x0201f800, 0x00105f28, 0x0201f800,
+ 0x001013ed, 0x0201f800, 0x0010126f, 0x4203e000,
+ 0xf0000001, 0x42000000, 0x00001000, 0x50000000,
+ 0x82000480, 0x24220001, 0x04000016, 0x59e00002,
+ 0x8c00051e, 0x42000000, 0x7ffe00fe, 0x04020003,
+ 0x42000000, 0x7ffe01fe, 0x50000800, 0x48075058,
+ 0x80040920, 0x82040580, 0x0000013a, 0x04000004,
+ 0x82040580, 0x0000013b, 0x04020006, 0x59a80005,
+ 0x84000552, 0x48035005, 0x4a0378e4, 0x000c0000,
+ 0x4a03c018, 0x0000000f, 0x4203e000, 0x20000511,
+ 0x4203e000, 0x50010000, 0x4a03c020, 0x00000000,
+ 0x04027013, 0x59e00020, 0x82000580, 0x00000002,
+ 0x0402000f, 0x4a03c020, 0x00004000, 0x4a03c011,
+ 0x40000010, 0x04006000, 0x4203e000, 0x40000000,
+ 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
+ 0x00000000, 0x4203e000, 0x30000001, 0x4202d800,
+ 0x00000000, 0x4203e000, 0xb0600000, 0x59a80005,
+ 0x42000800, 0x00000002, 0x8c000512, 0x04020007,
+ 0x42000800, 0x0000000f, 0x8c000514, 0x04020003,
+ 0x42000800, 0x00000001, 0x4007f800, 0x59a80005,
+ 0x8c000514, 0x02020000, 0x00020004, 0x59e00003,
+ 0x82000500, 0x00030000, 0x82000580, 0x00000000,
+ 0x04020af8, 0x0201f000, 0x00020004, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x416c0000, 0x82000c80,
+ 0x00000008, 0x04021aef, 0x0c01f804, 0x5c03e000,
+ 0x0201f000, 0x00020008, 0x001002f7, 0x0010030a,
+ 0x001003d7, 0x001002f6, 0x00100452, 0x001002f6,
+ 0x001002f6, 0x00100593, 0x0401fae2, 0x42000800,
+ 0x0010b4a4, 0x5804001d, 0x4803c857, 0x8c000500,
+ 0x0400000d, 0x84000500, 0x4800081d, 0x4202d800,
+ 0x00000004, 0x0401fbd3, 0x49f3c857, 0x5c000800,
+ 0x5c000000, 0x82000540, 0x00003e00, 0x4c000000,
+ 0x4c040000, 0x1c01f000, 0x0401fbbd, 0x0201f800,
+ 0x0010513b, 0x04000009, 0x0201f800, 0x00105151,
+ 0x0402002e, 0x59c40006, 0x82000540, 0x000000c0,
+ 0x48038806, 0x0401f029, 0x0201f800, 0x001050a2,
+ 0x836c0580, 0x00000001, 0x040200bc, 0x59a80017,
+ 0x82000580, 0x00000009, 0x040200b8, 0x497b5010,
+ 0x4a038893, 0x00000001, 0x42001000, 0x000000f0,
+ 0x0201f800, 0x0010193d, 0x0201f800, 0x00105149,
+ 0x59c41006, 0x04020006, 0x82081540, 0x000000f1,
+ 0x82081500, 0xbbffffff, 0x0401f003, 0x82081540,
+ 0x440000f1, 0x480b8806, 0x0201f800, 0x0010609e,
+ 0x4a0378e4, 0x00002000, 0x42000000, 0x0010b83a,
+ 0x0201f800, 0x0010aa47, 0x42001000, 0x00008030,
+ 0x497b5013, 0x0401f035, 0x0201f800, 0x00103b38,
+ 0x59c400a4, 0x82000500, 0x0000000f, 0x82000480,
+ 0x00000007, 0x04021091, 0x0201f800, 0x0010609e,
+ 0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3,
+ 0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800,
+ 0x00104139, 0x0401f085, 0x59a80015, 0x84000546,
+ 0x48035015, 0x0201f800, 0x00105141, 0x59c41006,
+ 0x04020006, 0x82081540, 0x44000001, 0x82081500,
+ 0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1,
+ 0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff,
+ 0x4a0378e4, 0x00003000, 0x42000000, 0x0010b80c,
+ 0x0201f800, 0x0010aa47, 0x59a81010, 0x42000800,
+ 0x00000003, 0x0201f800, 0x00106c78, 0x42001000,
+ 0x00008010, 0x59a8180a, 0x0201f800, 0x00103a3e,
+ 0x0201f800, 0x00101815, 0x59a80805, 0x82040d00,
+ 0xffffffdf, 0x48075005, 0x0201f800, 0x0010483d,
+ 0x0201f800, 0x0010513b, 0x0400000a, 0x0201f800,
+ 0x0010413e, 0x04000007, 0x4a035013, 0x00000001,
+ 0x497b5021, 0x0201f800, 0x00103c80, 0x0401f04f,
+ 0x0201f800, 0x001048ec, 0x04000005, 0x59c41002,
+ 0x8408150c, 0x480b8802, 0x0401f012, 0x0201f800,
+ 0x0010513b, 0x04020006, 0x59a8001d, 0x80000540,
+ 0x02000800, 0x0010930f, 0x0401f00a, 0x0201f800,
+ 0x0010930f, 0x59a80026, 0x8c000506, 0x04020005,
+ 0x59a8001d, 0x80000540, 0x02020800, 0x00104245,
+ 0x497b5028, 0x497b5027, 0x497b5018, 0x0201f800,
+ 0x0010513b, 0x59a81026, 0x0402000a, 0x0201f800,
+ 0x0010162a, 0x80001580, 0x59a8002a, 0x82000500,
+ 0xffff0000, 0x80040d40, 0x4807502a, 0x0401f005,
+ 0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a,
+ 0x599c0017, 0x8c00050a, 0x04000002, 0x84081544,
+ 0x480b5026, 0x0201f800, 0x0010513b, 0x04000004,
+ 0x0201f800, 0x0010162a, 0x48078880, 0x42001000,
+ 0x00000005, 0x0201f800, 0x001070b0, 0x497b5028,
+ 0x497b501b, 0x4a03501c, 0x0000ffff, 0x4a0378e4,
+ 0x000000c0, 0x4202d800, 0x00000002, 0x0201f800,
+ 0x0010513b, 0x04000007, 0x59a80026, 0x82000500,
+ 0x0000000c, 0x82000580, 0x00000004, 0x04000003,
+ 0x0201f800, 0x00101e45, 0x1c01f000, 0x59a8001c,
+ 0x82000580, 0x0000ffff, 0x04000004, 0x0201f800,
+ 0x00101e45, 0x0401f074, 0x59a80026, 0x8c00050a,
+ 0x04020003, 0x8c000506, 0x0400001c, 0x8c000500,
+ 0x0400001a, 0x4a038802, 0x0000ffbf, 0x8c000502,
+ 0x04000016, 0x599c0018, 0x8c000516, 0x04020010,
+ 0x59a80027, 0x82000580, 0x0000ffff, 0x0400000c,
+ 0x0201f800, 0x00101f9a, 0x59a80026, 0x8c000504,
+ 0x0402005d, 0x42001000, 0x00000003, 0x417a5800,
+ 0x0201f800, 0x00101fbf, 0x0401f057, 0x59a80028,
+ 0x80000540, 0x04020054, 0x59a80026, 0x8c000508,
+ 0x04020005, 0x59a8001b, 0x80000540, 0x0402004e,
+ 0x0401f003, 0x8c000516, 0x0400004b, 0x0201f800,
+ 0x001048ec, 0x04020048, 0x599c0018, 0x8c000516,
+ 0x04020004, 0x0201f800, 0x00104c51, 0x04020042,
+ 0x599c0017, 0x8c00050a, 0x0400000d, 0x4200b000,
+ 0x000007f0, 0x417a8800, 0x0201f800, 0x00020245,
+ 0x04020004, 0x59340200, 0x8c00051a, 0x04020036,
+ 0x81468800, 0x8058b040, 0x040207f8, 0x4a038802,
+ 0x0000ffff, 0x42001800, 0x0010b4eb, 0x0401fb8c,
+ 0x42001800, 0x0010b4f8, 0x0401fb89, 0x59a80005,
+ 0x84000502, 0x48035005, 0x4a0378e4, 0x00000080,
+ 0x4202d800, 0x00000003, 0x4a03501c, 0x0000ffff,
+ 0x0401fa7f, 0x80000580, 0x0201f800, 0x00101590,
+ 0x599c0018, 0x8c000516, 0x04000004, 0x0201f800,
+ 0x00103b10, 0x0401f009, 0x42001800, 0x0000ffff,
+ 0x42002000, 0x00000006, 0x42003000, 0x00000000,
+ 0x0201f800, 0x00103aae, 0x0201f800, 0x00105151,
+ 0x0400000b, 0x59c40006, 0x0201f800, 0x0010513b,
+ 0x04000004, 0x82000500, 0xffffff0f, 0x0401f003,
+ 0x82000500, 0xfbffffff, 0x48038806, 0x0201f800,
+ 0x00106f36, 0x1c01f000, 0x4c040000, 0x4c080000,
+ 0x4c100000, 0x59a8003e, 0x82000c80, 0x00000004,
+ 0x04021980, 0x0c01f805, 0x5c002000, 0x5c001000,
+ 0x5c000800, 0x1c01f000, 0x00100462, 0x001004ea,
+ 0x00100516, 0x00100577, 0x42000000, 0x00000001,
+ 0x0201f800, 0x00101590, 0x0201f800, 0x0010609e,
+ 0x59c408a3, 0x82040d00, 0xfffffff7, 0x480788a3,
+ 0x0201f800, 0x00105141, 0x0400000e, 0x0201f800,
+ 0x00105151, 0x0400000b, 0x0201f800, 0x00105149,
+ 0x04020964, 0x59c400a3, 0x84000532, 0x84000570,
+ 0x480388a3, 0x4a038808, 0x00000008, 0x0401f010,
+ 0x59c400a3, 0x84000530, 0x82000500, 0xbf7fffff,
+ 0x480388a3, 0x42000800, 0x000000f8, 0x0201f800,
+ 0x00104200, 0x59c400a3, 0x82000540, 0x00018000,
+ 0x8400051c, 0x480388a3, 0x497b8808, 0x59c40006,
+ 0x82000500, 0xfbffff0e, 0x48038806, 0x497b2822,
+ 0x497b2823, 0x42000800, 0x000001f4, 0x42001000,
+ 0x00100591, 0x0201f800, 0x00105f83, 0x59c40805,
+ 0x42001000, 0x00000001, 0x0201f800, 0x0010193d,
+ 0x0201f800, 0x0010163b, 0x0402000a, 0x42000000,
+ 0x00000001, 0x0201f800, 0x0010188c, 0x42000000,
+ 0x00000001, 0x0201f800, 0x00101821, 0x0401f022,
+ 0x0201f800, 0x00101642, 0x04020008, 0x41780000,
+ 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+ 0x00101821, 0x0401f018, 0x0201f800, 0x00101649,
+ 0x0402000a, 0x42000000, 0x00000002, 0x0201f800,
+ 0x0010188c, 0x42000000, 0x00000002, 0x0201f800,
+ 0x00101821, 0x0401f00c, 0x0201f800, 0x00101650,
+ 0x04020918, 0x59a80049, 0x800001c0, 0x04000006,
+ 0x0201f800, 0x00101656, 0x4a03503e, 0x00000001,
+ 0x0401f021, 0x0201f800, 0x00101927, 0x4a03503e,
+ 0x00000001, 0x0201f800, 0x00105141, 0x0400000c,
+ 0x0201f800, 0x00105151, 0x04000009, 0x0201f800,
+ 0x00105149, 0x04020903, 0x4a035033, 0x00000001,
+ 0x0201f800, 0x001050a2, 0x0401f00f, 0x59c400a4,
+ 0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+ 0x04000003, 0x4a038805, 0x04000000, 0x59c400a3,
+ 0x82000540, 0x0001c000, 0x480388a3, 0x84000520,
+ 0x480388a3, 0x1c01f000, 0x0401f8a3, 0x04020004,
+ 0x4a03503e, 0x00000003, 0x0401f027, 0x0201f800,
+ 0x00101650, 0x04020011, 0x59a80049, 0x800001c0,
+ 0x0400000e, 0x0201f800, 0x00101656, 0x59a80048,
+ 0x8c00051e, 0x0400001c, 0x0201f800, 0x00105149,
+ 0x04020009, 0x4a035033, 0x00000001, 0x0201f800,
+ 0x001050a2, 0x0401f004, 0x0201f800, 0x001018d3,
+ 0x04020011, 0x0201f800, 0x00101815, 0x4a03503e,
+ 0x00000002, 0x497b5049, 0x59c400a3, 0x84000520,
+ 0x480388a3, 0x497b2822, 0x497b2823, 0x42000800,
+ 0x0000002d, 0x42001000, 0x00100591, 0x0201f800,
+ 0x00105f83, 0x1c01f000, 0x0401f877, 0x04020004,
+ 0x4a03503e, 0x00000003, 0x0401f05b, 0x4a038805,
+ 0x000000f0, 0x0201f800, 0x001018d3, 0x04020050,
+ 0x0201f800, 0x00105149, 0x04000044, 0x59c400a4,
+ 0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+ 0x04000020, 0x59c40005, 0x8c000534, 0x0402001d,
+ 0x59940022, 0x82000580, 0x00000001, 0x04020046,
+ 0x0201f800, 0x00105151, 0x04020043, 0x4a038805,
+ 0x000000f0, 0x0201f800, 0x00105196, 0x4a035032,
+ 0x0000aaaa, 0x4a035033, 0x00000000, 0x59c408a3,
+ 0x82040d40, 0x00000008, 0x480788a3, 0x4202d800,
+ 0x00000001, 0x4a03503e, 0x00000000, 0x4a038805,
+ 0x00000001, 0x497b2822, 0x497b2823, 0x0401f01f,
+ 0x0201f800, 0x00105151, 0x04020007, 0x59a80032,
+ 0x82000580, 0x0000aaaa, 0x04020003, 0x4a035010,
+ 0x00ffffff, 0x497b5032, 0x59c40006, 0x82000540,
+ 0x04000001, 0x48038806, 0x59a80805, 0x8c040d06,
+ 0x04020005, 0x59c408a3, 0x82040d40, 0x00000008,
+ 0x480788a3, 0x4202d800, 0x00000001, 0x4a03503e,
+ 0x00000000, 0x4a038805, 0x00000001, 0x497b2822,
+ 0x497b2823, 0x0401f010, 0x59c40005, 0x82000500,
+ 0x000000c0, 0x0400000c, 0x59c40006, 0x82000540,
+ 0x000000f1, 0x48038806, 0x0401f7ef, 0x0201f800,
+ 0x00101650, 0x04020004, 0x59a80049, 0x800001c0,
+ 0x040207a4, 0x497b8885, 0x1c01f000, 0x4803c856,
+ 0x42000000, 0x00000001, 0x0201f800, 0x00101590,
+ 0x4a03503e, 0x00000000, 0x0201f800, 0x00101650,
+ 0x0402000b, 0x59a80052, 0x800001c0, 0x04000004,
+ 0x80000040, 0x48035052, 0x04020005, 0x4a035052,
+ 0x0000000a, 0x4a035049, 0x00000001, 0x497b8885,
+ 0x0401f0ed, 0x59940022, 0x59940823, 0x80040540,
+ 0x1c01f000, 0x497b2823, 0x1c01f000, 0x4c080000,
+ 0x42001000, 0x000000f0, 0x0201f800, 0x0010193d,
+ 0x5c001000, 0x1c01f000, 0x4a03505c, 0x00000004,
+ 0x4a03505d, 0x00000000, 0x4a03505e, 0x00000010,
+ 0x4a03505f, 0x00000002, 0x4a035010, 0x00ffffff,
+ 0x0201f800, 0x0010930f, 0x4a03502a, 0x20200000,
+ 0x4a03502b, 0x88000200, 0x4a03502c, 0x00ff001f,
+ 0x4a03502d, 0x000007d0, 0x4a03502e, 0x80000000,
+ 0x4a03502f, 0x00000200, 0x4a035030, 0x00ff0000,
+ 0x4a035031, 0x00010000, 0x4a03503a, 0x514c4f47,
+ 0x4a03503b, 0x49432020, 0x1c01f000, 0x4d440000,
+ 0x417a8800, 0x41780800, 0x0201f800, 0x00020245,
+ 0x04020005, 0x0201f800, 0x001049e7, 0x04020002,
+ 0x80040800, 0x81468800, 0x83440580, 0x000007f0,
+ 0x040207f6, 0x5c028800, 0x1c01f000, 0x4803c857,
+ 0x5c000000, 0x4c000000, 0x4803c857, 0x0401f809,
+ 0x485fc857, 0x4203e000, 0x50000000, 0x5c000000,
+ 0x4d780000, 0x4200b800, 0x00008002, 0x0401f006,
+ 0x485fc857, 0x4203e000, 0x50000000, 0x4200b800,
+ 0x00008002, 0x04006000, 0x4c000000, 0x4c040000,
+ 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
+ 0x00000001, 0x04020005, 0x42000800, 0x00000000,
+ 0x0201f800, 0x00106c6c, 0x5c000800, 0x4807c025,
+ 0x80040920, 0x4807c026, 0x5c000000, 0x4803c023,
+ 0x80000120, 0x4803c024, 0x5c000000, 0x4803c857,
+ 0x4803c021, 0x80000120, 0x4803c022, 0x41f80000,
+ 0x4803c027, 0x80000120, 0x4803c028, 0x42000000,
+ 0x00001000, 0x50000000, 0x82000480, 0x24320001,
+ 0x4803c857, 0x0400104f, 0x42000800, 0x00000064,
+ 0x80040840, 0x04000007, 0x4a030000, 0x00000001,
+ 0x40000000, 0x59800000, 0x8c000500, 0x040007f9,
+ 0x04000042, 0x42000800, 0x0010c1a3, 0x46000800,
+ 0xfaceface, 0x80040800, 0x42001000, 0x00007a00,
+ 0x58080013, 0x44000800, 0x80040800, 0x58080019,
+ 0x44000800, 0x80040800, 0x5808001a, 0x44000800,
+ 0x80040800, 0x5808001b, 0x44000800, 0x80040800,
+ 0x5808001c, 0x44000800, 0x80040800, 0x5808001f,
+ 0x44000800, 0x80040800, 0x42001000, 0x00007a40,
+ 0x42001800, 0x0000000b, 0x50080000, 0x44000800,
+ 0x80081000, 0x80040800, 0x800c1840, 0x040207fb,
+ 0x42001800, 0x00000003, 0x42001000, 0x00007b00,
+ 0x480c1003, 0x58080005, 0x44000800, 0x80040800,
+ 0x800c1840, 0x040217fb, 0x42001000, 0x00007c00,
+ 0x58080002, 0x44000800, 0x80040800, 0x58080003,
+ 0x44000800, 0x80040800, 0x58080020, 0x44000800,
+ 0x80040800, 0x58080021, 0x44000800, 0x80040800,
+ 0x58080022, 0x44000800, 0x80040800, 0x58080023,
+ 0x44000800, 0x80040800, 0x4a030000, 0x00000000,
+ 0x485fc020, 0x905cb9c0, 0x825cbd40, 0x00000012,
+ 0x485fc011, 0x4203e000, 0x40000000, 0x4202d800,
+ 0x00000005, 0x59e00017, 0x8c000508, 0x04000003,
+ 0x4a03c017, 0x00000002, 0x4203e000, 0x30000001,
+ 0x0401f81a, 0x0401f7ff, 0x4a03c850, 0x0010c1bf,
+ 0x4a03c851, 0x0010d1be, 0x4a03c853, 0x00000800,
+ 0x4a03c855, 0x0001eb5a, 0x59e40001, 0x82000540,
+ 0x00003f00, 0x4803c801, 0x4a03b104, 0x70000002,
+ 0x4a03a804, 0x70000002, 0x4a03b004, 0x70000002,
+ 0x42000000, 0x0010b8ec, 0x49780001, 0x49780002,
+ 0x1c01f000, 0x1c01f000, 0x59a8006b, 0x8c000530,
+ 0x040207fe, 0x4c080000, 0x42001000, 0x00000004,
+ 0x0401f862, 0x5c001000, 0x4201d000, 0x00028b0a,
+ 0x0201f800, 0x0010608e, 0x4c080000, 0x42001000,
+ 0x00000008, 0x0401f859, 0x5c001000, 0x4201d000,
+ 0x00028b0a, 0x0201f800, 0x0010608e, 0x4c080000,
+ 0x42001000, 0x00000010, 0x0401f850, 0x5c001000,
+ 0x4201d000, 0x00028b0a, 0x0201f800, 0x0010608e,
+ 0x0401f7e2, 0x8c00050c, 0x59a8086b, 0x04020003,
+ 0x84040d30, 0x0401f006, 0x84040d70, 0x4807506b,
+ 0x42001000, 0x00000000, 0x0401f040, 0x4807506b,
+ 0x836c0500, 0x00000007, 0x0c01f001, 0x001006e1,
+ 0x001006c7, 0x001006c7, 0x001006af, 0x001006d4,
+ 0x001006c7, 0x001006c7, 0x001006d4, 0x59a80005,
+ 0x8c000514, 0x04020013, 0x59c40801, 0x82040d00,
+ 0x00018000, 0x82040580, 0x00010000, 0x0400000a,
+ 0x82040580, 0x00008000, 0x04000004, 0x42001000,
+ 0x42004000, 0x0401f006, 0x42001000, 0x22002000,
+ 0x0401f003, 0x42001000, 0x12001000, 0x0401f025,
+ 0x42001000, 0x00001004, 0x0401f022, 0x59a80005,
+ 0x8c000514, 0x04020008, 0x59a8006b, 0x8c000534,
+ 0x04020004, 0x42001000, 0x74057005, 0x0401f819,
+ 0x1c01f000, 0x42001000, 0x00002008, 0x0401f7fc,
+ 0x59a8006b, 0x8c000534, 0x0402000a, 0x59a80005,
+ 0x8c000514, 0x04000004, 0x42001000, 0x24052005,
+ 0x0401f00c, 0x42001000, 0x74057005, 0x0401f009,
+ 0x1c01f000, 0x1c01f000, 0x82081500, 0x0000001c,
+ 0x82081540, 0x001c0000, 0x480bc013, 0x1c01f000,
+ 0x59a8006b, 0x8c000530, 0x04000002, 0x84081570,
+ 0x480b506b, 0x8c000530, 0x04020005, 0x82081500,
+ 0x00007000, 0x80081114, 0x0401fff0, 0x1c01f000,
+ 0x41780000, 0x50041800, 0x800c0400, 0x80040800,
+ 0x80102040, 0x040207fc, 0x80080500, 0x80000540,
+ 0x1c01f000, 0x4202f000, 0x00000000, 0x41780000,
+ 0x41780800, 0x41781000, 0x41781800, 0x41782000,
+ 0x41782800, 0x41783000, 0x41783800, 0x41784000,
+ 0x41784800, 0x41785000, 0x41785800, 0x41786000,
+ 0x41786800, 0x41787000, 0x41787800, 0x41788000,
+ 0x41788800, 0x41789000, 0x41789800, 0x4178a000,
+ 0x4178a800, 0x4178b000, 0x4178b800, 0x4178c000,
+ 0x4178c800, 0x4178d000, 0x4178d800, 0x4178e000,
+ 0x4178e800, 0x4178f000, 0x4178f800, 0x41790000,
+ 0x41790800, 0x41791000, 0x41791800, 0x41792000,
+ 0x41792800, 0x41793000, 0x41793800, 0x41794000,
+ 0x41794800, 0x41795000, 0x41795800, 0x41796000,
+ 0x41796800, 0x41797000, 0x41797800, 0x41798000,
+ 0x41798800, 0x42019000, 0x0010b537, 0x42019800,
+ 0x0010b50e, 0x4179a000, 0x4179b000, 0x4179a800,
+ 0x4179b800, 0x4179c800, 0x4179c000, 0x4179d000,
+ 0x4179d800, 0x4179e000, 0x4179e800, 0x4179f000,
+ 0x4179f800, 0x417a0000, 0x417a0800, 0x417a1000,
+ 0x417a1800, 0x417a2000, 0x42022800, 0x00006100,
+ 0x417a3000, 0x417a3800, 0x417a4000, 0x417a4800,
+ 0x417a5000, 0x417a5800, 0x417a6000, 0x417a6800,
+ 0x417a7000, 0x417a7800, 0x417a8000, 0x417a8800,
+ 0x417a9000, 0x417a9800, 0x417ae800, 0x417af800,
+ 0x42030000, 0x00007c00, 0x42031000, 0x0010b806,
+ 0x42031800, 0x0000bf1d, 0x42032000, 0x0000bf32,
+ 0x42032800, 0x0010b7ce, 0x42033000, 0x0010b46e,
+ 0x42034000, 0x0010b4a4, 0x42033800, 0x0010b4c3,
+ 0x42034800, 0x0010b544, 0x42035000, 0x0010b400,
+ 0x42035800, 0x0010ac00, 0x42030800, 0x0010b505,
+ 0x417b6000, 0x42036800, 0x00006f00, 0x4203c800,
+ 0x00003000, 0x42037000, 0x0000ff00, 0x42037800,
+ 0x0000bf00, 0x42038000, 0x00007700, 0x42038800,
+ 0x00004000, 0x42039000, 0x00006000, 0x42039800,
+ 0x0010bedb, 0x4203a000, 0x00007600, 0x4203a800,
+ 0x00007400, 0x4203b000, 0x00007200, 0x4203b800,
+ 0x00007100, 0x4203c000, 0x00007000, 0x4203d000,
+ 0x00000000, 0x4203e800, 0x00101b95, 0x417bd800,
+ 0x1c01f000, 0x42000800, 0x00100000, 0x50040000,
+ 0x4c000000, 0x42000000, 0x0000aaaa, 0x44000800,
+ 0x42001800, 0x00005555, 0x41782000, 0x82102400,
+ 0x00010000, 0x40100000, 0x80042c00, 0x440c2800,
+ 0x42003000, 0x0000000a, 0x80183040, 0x040207ff,
+ 0x50140000, 0x800c0580, 0x04020004, 0x50040000,
+ 0x800c0580, 0x040207f2, 0x5c000000, 0x44000800,
+ 0x80142840, 0x4817c861, 0x1c01f000, 0x59a8081f,
+ 0x800409c0, 0x04020009, 0x49781c0c, 0x4a001a0c,
+ 0x00000200, 0x4a001804, 0x07000000, 0x59a80010,
+ 0x9c0001c0, 0x48001805, 0x0401fe01, 0x9c0409c0,
+ 0x48041806, 0x1c01f000, 0x59a8080c, 0x4006d000,
+ 0x4202b800, 0x00000001, 0x59a8180d, 0x480fc857,
+ 0x82041400, 0x00000014, 0x82082400, 0x00000014,
+ 0x40100000, 0x800c0480, 0x04001006, 0x44080800,
+ 0x40080800, 0x40101000, 0x815eb800, 0x0401f7f7,
+ 0x45780800, 0x495f5020, 0x1c01f000, 0x835c0480,
+ 0x00000020, 0x04001009, 0x496bc857, 0x815eb840,
+ 0x416a5800, 0x592ed000, 0x497a5800, 0x497a5801,
+ 0x812e59c0, 0x1c01f000, 0x42000000, 0x0010b853,
+ 0x0201f800, 0x0010aa47, 0x417a5800, 0x0401f7f9,
+ 0x815eb840, 0x04001008, 0x416a5800, 0x492fc857,
+ 0x592ed000, 0x497a5800, 0x497a5801, 0x812e59c0,
+ 0x1c01f000, 0x42000000, 0x0010b853, 0x0201f800,
+ 0x0010aa47, 0x417ab800, 0x417a5800, 0x0401f7f8,
+ 0x492fc857, 0x496a5800, 0x412ed000, 0x815eb800,
+ 0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+ 0x1c01f000, 0x492fc857, 0x812e59c0, 0x04000007,
+ 0x592c0001, 0x497a5801, 0x4c000000, 0x0401fff1,
+ 0x5c025800, 0x0401f7f9, 0x1c01f000, 0x4807c856,
+ 0x42007000, 0x0010b7f8, 0x4a007001, 0x00000000,
+ 0x59e00003, 0x82000540, 0x00008080, 0x4803c003,
+ 0x4a03b805, 0x90000001, 0x59dc0006, 0x4a03b805,
+ 0x70000000, 0x59dc0006, 0x4a03b805, 0x30000000,
+ 0x4200b000, 0x00000020, 0x497bb807, 0x8058b040,
+ 0x040207fe, 0x4a03b805, 0x30000000, 0x59dc0006,
+ 0x4a03b805, 0x60000001, 0x59dc0006, 0x4a03b805,
+ 0x70000001, 0x59dc0006, 0x4a03b805, 0x30000002,
+ 0x4200b000, 0x00000020, 0x497bb807, 0x8058b040,
+ 0x040207fe, 0x4a03b805, 0x30000000, 0x59dc0006,
+ 0x4a03b805, 0x60000001, 0x0401ffa1, 0x04000da5,
+ 0x42001000, 0x0010b7f6, 0x452c1000, 0x4a025801,
+ 0x00000001, 0x4a025802, 0x00000100, 0x4a025809,
+ 0x00107149, 0x497a580a, 0x497a580b, 0x497a580c,
+ 0x0401ff93, 0x04000d97, 0x42001000, 0x0010b7f7,
+ 0x452c1000, 0x4a025801, 0x00000000, 0x4a025802,
+ 0x00000100, 0x4a025809, 0x001011bc, 0x497a5803,
+ 0x497a5807, 0x497a5808, 0x497a580a, 0x59a80005,
+ 0x8c00050e, 0x04000006, 0x4a03b805, 0xe0000001,
+ 0x59dc0006, 0x8c000522, 0x040007fc, 0x1c01f000,
+ 0x4df00000, 0x4203e000, 0x50000000, 0x4c380000,
+ 0x40087000, 0x480bc857, 0x4a007002, 0x00000000,
+ 0x42007000, 0x0010b7f8, 0x82080400, 0x00000000,
+ 0x45780000, 0x58380005, 0x48087005, 0x80000540,
+ 0x04000005, 0x82000400, 0x00000000, 0x44080000,
+ 0x0401f003, 0x480bc857, 0x48087006, 0x58380001,
+ 0x80000540, 0x0400080c, 0x5c007000, 0x5c03e000,
+ 0x1c01f000, 0x4c380000, 0x42007000, 0x0010b7f8,
+ 0x58380001, 0x80000540, 0x04000803, 0x5c007000,
+ 0x1c01f000, 0x42007000, 0x0010b7f8, 0x58380001,
+ 0x82000580, 0x00000000, 0x04020012, 0x58380000,
+ 0x0c01f001, 0x0010088e, 0x0010088d, 0x0010088d,
+ 0x0010088d, 0x0010088d, 0x0010088d, 0x0010088d,
+ 0x0010088d, 0x0401fd4b, 0x58380808, 0x800409c0,
+ 0x04020024, 0x58380006, 0x80000540, 0x04020002,
+ 0x1c01f000, 0x4803c857, 0x48007002, 0x40006800,
+ 0x58340000, 0x80000540, 0x04020002, 0x48007005,
+ 0x48007006, 0x4a03b805, 0x20000000, 0x59dc0006,
+ 0x4a03b805, 0x30000000, 0x58340007, 0x4803b800,
+ 0x58340008, 0x4803b801, 0x58340004, 0x48007003,
+ 0x58340003, 0x48007004, 0x4803b803, 0x58340001,
+ 0x8c000500, 0x04000004, 0x4a007001, 0x00000001,
+ 0x0401f028, 0x4a007001, 0x00000002, 0x0401f03d,
+ 0x0201f800, 0x001093ea, 0x0201f800, 0x0010a69d,
+ 0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006,
+ 0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801,
+ 0x4a007003, 0x00000010, 0x480c7009, 0x42001000,
+ 0x00100875, 0x0201f800, 0x00105f9a, 0x58380008,
+ 0x82000400, 0x00000004, 0x48007004, 0x4803b803,
+ 0x4a007001, 0x00000007, 0x0401f022, 0x0201f800,
+ 0x00109402, 0x42000800, 0x00000001, 0x42001000,
+ 0x00100875, 0x0201f800, 0x00105f76, 0x0401f7ba,
+ 0x4c040000, 0x4c080000, 0x58380803, 0x42001000,
+ 0x00003fff, 0x82040480, 0x00003fff, 0x04021003,
+ 0x40041000, 0x80000580, 0x48007003, 0x800800c4,
+ 0x4803b802, 0x4a03b805, 0x30000002, 0x59dc0006,
+ 0x4a03b805, 0x70000001, 0x59dc0006, 0x4a03b805,
+ 0x10000000, 0x5c001000, 0x5c000800, 0x1c01f000,
+ 0x483bc857, 0x4c040000, 0x4c080000, 0x58380803,
+ 0x42001000, 0x00003fff, 0x82040480, 0x00003fff,
+ 0x04021003, 0x40041000, 0x80000580, 0x48007003,
+ 0x800800c4, 0x4803b802, 0x4a03b805, 0x10000002,
+ 0x5c001000, 0x5c000800, 0x1c01f000, 0x4c040000,
+ 0x4c380000, 0x42007000, 0x0010b7f8, 0x59dc0806,
+ 0x4807c857, 0x4a03b805, 0x20000000, 0x8c040d3e,
+ 0x04000007, 0x8c040d08, 0x04020cca, 0x58380001,
+ 0x82000500, 0x00000007, 0x0c01f804, 0x5c007000,
+ 0x5c000800, 0x1c01f000, 0x0010087d, 0x0010091e,
+ 0x0010092e, 0x001005d8, 0x001005d8, 0x001005d8,
+ 0x001005d8, 0x001011ea, 0x4807c856, 0x82040d00,
+ 0x43000f80, 0x04020009, 0x58380003, 0x80000540,
+ 0x0400001c, 0x59dc0000, 0x4803b800, 0x59dc0001,
+ 0x4803b801, 0x0401f7af, 0x58380802, 0x4a000802,
+ 0x00000200, 0x0401f01e, 0x4807c856, 0x82040d00,
+ 0x43000f80, 0x04020009, 0x58380003, 0x80000540,
+ 0x0400000c, 0x59dc0000, 0x4803b800, 0x59dc0001,
+ 0x4803b801, 0x0401f7b7, 0x58380002, 0x82000400,
+ 0x00000002, 0x46000000, 0x00000200, 0x0401f00c,
+ 0x4c340000, 0x58386802, 0x59dc0000, 0x4803c857,
+ 0x48006807, 0x59dc0001, 0x4803c857, 0x48006808,
+ 0x4a006802, 0x00000100, 0x5c006800, 0x4a007001,
+ 0x00000000, 0x4c300000, 0x58386002, 0x0401f80c,
+ 0x04000009, 0x58300009, 0x82000c80, 0x0010ab4a,
+ 0x04021c84, 0x82000c80, 0x00020000, 0x04001c81,
+ 0x0801f800, 0x5c006000, 0x0401f723, 0x4833c857,
+ 0x803061c0, 0x04000009, 0x59a8000c, 0x80300480,
+ 0x04001007, 0x59a8000d, 0x80300480, 0x04021004,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x80000580,
+ 0x1c01f000, 0x4803c856, 0x4dc00000, 0x42007000,
+ 0x0010b803, 0x4a007400, 0x00000000, 0x49787001,
+ 0x42038000, 0x00007720, 0x4a038006, 0x60000001,
+ 0x4a038009, 0xf4f60000, 0x42038000, 0x00007700,
+ 0x4a038006, 0x60000001, 0x4a038009, 0xf4f60000,
+ 0x4a03c822, 0x00000010, 0x4a0370e8, 0x00000000,
+ 0x0401f809, 0x4a0370e9, 0x00003a0f, 0x4a0370e8,
+ 0x00000000, 0x4a0370e8, 0x00000001, 0x5c038000,
+ 0x1c01f000, 0x4c5c0000, 0x4178b800, 0x0401f80a,
+ 0x5c00b800, 0x1c01f000, 0x4803c856, 0x4c5c0000,
+ 0x825cbd40, 0x00000001, 0x0401f803, 0x5c00b800,
+ 0x1c01f000, 0x4803c856, 0x4dc00000, 0x4c500000,
+ 0x4c580000, 0x4c540000, 0x4a0370e8, 0x00000000,
+ 0x805cb9c0, 0x04000009, 0x4a038807, 0x00000004,
+ 0x59b800ea, 0x8c000510, 0x04000004, 0x59b800e0,
+ 0x0401f87b, 0x0401f7fb, 0x42038000, 0x00007720,
+ 0x0201f800, 0x00100ec1, 0x59c00007, 0x4a038006,
+ 0x20000000, 0x59c00007, 0x4a038006, 0x8000000a,
+ 0x59c00007, 0x4a038006, 0x8000000b, 0x59c00007,
+ 0x4a038006, 0x40000001, 0x83c00580, 0x00007700,
+ 0x04000004, 0x42038000, 0x00007700, 0x0401f7ed,
+ 0x42038000, 0x00007720, 0x42000800, 0x00000800,
+ 0x59c00007, 0x8c00051e, 0x04000006, 0x4a038006,
+ 0x90000001, 0x80040840, 0x040207fa, 0x0401fc11,
+ 0x83c00580, 0x00007700, 0x04000004, 0x42038000,
+ 0x00007700, 0x0401f7f1, 0x805cb9c0, 0x0402001d,
+ 0x4200b000, 0x00000020, 0x83b8ac00, 0x00000020,
+ 0x0201f800, 0x0010ab20, 0x4a0370fb, 0x00000001,
+ 0x4a037020, 0x001010bd, 0x59a80039, 0x82000500,
+ 0x0000ffff, 0x48037021, 0x4a037035, 0x0010bddb,
+ 0x4a037030, 0x0010b410, 0x4a037031, 0x0010ac00,
+ 0x4a037032, 0x0010b519, 0x4a037036, 0x0010b524,
+ 0x59840002, 0x48037034, 0x4a037038, 0x001010b4,
+ 0x4a0370fb, 0x00000001, 0x4178a000, 0x4200b000,
+ 0x00000020, 0x83b8ac00, 0x00000000, 0x0201f800,
+ 0x0010ab20, 0x4200b000, 0x00000040, 0x83b8ac00,
+ 0x00000040, 0x0201f800, 0x0010ab20, 0x805cb9c0,
+ 0x04020004, 0x4a0370e4, 0xaaaaaaaa, 0x0401f003,
+ 0x4a0370e4, 0xa2aaaa82, 0x4a0370e5, 0xaaaaaaaa,
+ 0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb, 0x00000000,
+ 0x4a0370e6, 0xaaaaaaaa, 0x42038000, 0x00007720,
+ 0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e,
+ 0x02020800, 0x001005d8, 0x42038000, 0x00007700,
+ 0x4a038006, 0x90000000, 0x59c00007, 0x8c00051e,
+ 0x02020800, 0x001005d8, 0x5c00a800, 0x5c00b000,
+ 0x5c00a000, 0x5c038000, 0x1c01f000, 0x4d300000,
+ 0x4d380000, 0x40026000, 0x82000500, 0x7f000000,
+ 0x82000580, 0x00000003, 0x0402000f, 0x83326500,
+ 0x00ffffff, 0x59300203, 0x82000580, 0x00000004,
+ 0x04020009, 0x59300c06, 0x82040580, 0x00000009,
+ 0x04020005, 0x42027000, 0x00000047, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x5c026000, 0x1c01f000,
+ 0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000,
+ 0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000,
+ 0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000,
+ 0x4c640000, 0x4cc80000, 0x4ccc0000, 0x4cf00000,
+ 0x4cf40000, 0x4cf80000, 0x4cfc0000, 0x4d000000,
+ 0x4d040000, 0x0201f800, 0x00020015, 0x5c020800,
+ 0x5c020000, 0x5c01f800, 0x5c01f000, 0x5c01e800,
+ 0x5c01e000, 0x5c019800, 0x5c019000, 0x5c00c800,
+ 0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800,
+ 0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800,
+ 0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000,
+ 0x1c01f000, 0x493bc857, 0x0201f000, 0x00020044,
+ 0x83300500, 0x1f000000, 0x04000008, 0x81326580,
+ 0x80000130, 0x82000c80, 0x00000014, 0x02021800,
+ 0x001005d8, 0x0c01f013, 0x83300500, 0x000000ff,
+ 0x82000c80, 0x00000007, 0x02021800, 0x001005d8,
+ 0x0c01f025, 0x1c01f000, 0x82000d00, 0xc0000038,
+ 0x02020800, 0x001005d0, 0x0201f800, 0x001005d8,
+ 0x00000000, 0x00000048, 0x00000054, 0x00000053,
+ 0x00100a9b, 0x00100abf, 0x00100aba, 0x00100adf,
+ 0x00100aa6, 0x00100ab2, 0x00100a9b, 0x00100ada,
+ 0x00100b1a, 0x00100a9b, 0x00100a9b, 0x00100a9b,
+ 0x00100a9b, 0x00100b1d, 0x00100b23, 0x00100b34,
+ 0x00100b45, 0x00100a9b, 0x00100b4e, 0x00100b5a,
+ 0x00100a9b, 0x00100a9b, 0x00100a9b, 0x0201f800,
+ 0x001005d8, 0x00100aa4, 0x00100bff, 0x00100aec,
+ 0x00100b0f, 0x00100aa4, 0x00100aa4, 0x00100aa4,
+ 0x0201f800, 0x001005d8, 0x4803c856, 0x59300004,
+ 0x8c00053e, 0x04020005, 0x42027000, 0x00000055,
+ 0x0201f000, 0x000207a1, 0x0201f800, 0x00106f60,
+ 0x040007fa, 0x1c01f000, 0x4803c856, 0x0401f8a9,
+ 0x40002800, 0x41782000, 0x42027000, 0x00000056,
+ 0x0201f000, 0x000207a1, 0x4803c856, 0x42027000,
+ 0x00000057, 0x0201f000, 0x000207a1, 0x4803c856,
+ 0x59300007, 0x8c00051a, 0x04020010, 0x59325808,
+ 0x812e59c0, 0x04000014, 0x592c0408, 0x8c00051c,
+ 0x04020003, 0x4a026011, 0xffffffff, 0x59300004,
+ 0x8c00053e, 0x04020009, 0x42027000, 0x00000048,
+ 0x0201f000, 0x000207a1, 0x59325808, 0x4a025a06,
+ 0x00000007, 0x0401f7f4, 0x0201f800, 0x00106f60,
+ 0x040007f6, 0x1c01f000, 0x4803c856, 0x83300500,
+ 0x00ffffff, 0x0201f000, 0x001064d7, 0x1c01f000,
+ 0x4c040000, 0x59b808ea, 0x82040d00, 0x00000007,
+ 0x82040580, 0x00000003, 0x04000004, 0x42000000,
+ 0x60000000, 0x0401f8ab, 0x5c000800, 0x1c01f000,
+ 0x0401f8f9, 0x59325808, 0x812e59c0, 0x04000018,
+ 0x592c0204, 0x82000500, 0x000000ff, 0x82000d80,
+ 0x00000029, 0x04020012, 0x59300203, 0x82000580,
+ 0x00000003, 0x0400000b, 0x59300807, 0x84040d26,
+ 0x48066007, 0x0201f800, 0x00020086, 0x4a03900d,
+ 0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000,
+ 0x0201f800, 0x00106f60, 0x040007f4, 0x59880052,
+ 0x80000000, 0x48031052, 0x4a03900d, 0x00000040,
+ 0x42000000, 0xc0000000, 0x0401f05a, 0x42007800,
+ 0x0010bde2, 0x42002000, 0x00003000, 0x42003000,
+ 0x00000105, 0x0201f800, 0x00105e04, 0x4a0370e4,
+ 0x02000000, 0x1c01f000, 0x4933c857, 0x0201f000,
+ 0x0002077d, 0x41300800, 0x800409c0, 0x02020800,
+ 0x001005d8, 0x0201f800, 0x001005d0, 0x4933c857,
+ 0x813261c0, 0x02000800, 0x001005d8, 0x0401f835,
+ 0x40002800, 0x0201f800, 0x0010a99c, 0x0401f8ae,
+ 0x04000007, 0x59326809, 0x59340200, 0x8c00050e,
+ 0x59300414, 0x02020800, 0x001092ce, 0x1c01f000,
+ 0x4933c857, 0x813261c0, 0x02000800, 0x001005d8,
+ 0x0401f8a1, 0x0400000b, 0x59325808, 0x0201f800,
+ 0x00109037, 0x04000007, 0x592c0208, 0x8400054e,
+ 0x48025a08, 0x417a7800, 0x0201f800, 0x00108be3,
+ 0x1c01f000, 0x485fc857, 0x5c000000, 0x4d780000,
+ 0x4203e000, 0x50000000, 0x4200b800, 0x00008005,
+ 0x0201f000, 0x001005dd, 0x4933c857, 0x83300480,
+ 0x00000020, 0x02021800, 0x001005d8, 0x83300c00,
+ 0x0010b8cc, 0x50040000, 0x80000000, 0x04001002,
+ 0x44000800, 0x1c01f000, 0x4933c857, 0x0401f7f4,
+ 0x4807c856, 0x59b800ea, 0x8c000510, 0x040007fd,
+ 0x59b800e0, 0x4803c857, 0x1c01f000, 0x4803c856,
+ 0x42000000, 0x10000000, 0x41300800, 0x0401f02d,
+ 0x82000500, 0xf0000000, 0x82040d00, 0x0fffffff,
+ 0x80040d40, 0x4807c857, 0x59b800ea, 0x8c000516,
+ 0x04020003, 0x480770e1, 0x1c01f000, 0x8c000510,
+ 0x040007fa, 0x4c040000, 0x0401f809, 0x5c000800,
+ 0x82100480, 0x00000008, 0x040017f4, 0x4c040000,
+ 0x0401febc, 0x5c000800, 0x0401f7f0, 0x59b800e2,
+ 0x59b820e2, 0x80100580, 0x040207fd, 0x80102114,
+ 0x0401f006, 0x59b800e2, 0x59b820e2, 0x80100580,
+ 0x040207fd, 0x0401f001, 0x40101800, 0x800c190a,
+ 0x82100500, 0x0000001f, 0x820c1d00, 0x0000001f,
+ 0x800c2480, 0x82102500, 0x0000001f, 0x1c01f000,
+ 0x82000500, 0xf0000000, 0x82040d00, 0x0fffffff,
+ 0x80040d40, 0x4807c857, 0x42001000, 0x0010b804,
+ 0x50080000, 0x80000540, 0x04020005, 0x4a0370e5,
+ 0x00000003, 0x4a0370e4, 0x00000300, 0x80000000,
+ 0x44001000, 0x42001000, 0x00000400, 0x59b800ea,
+ 0x8c000510, 0x0400000c, 0x0401ffd5, 0x82100480,
+ 0x00000008, 0x04001007, 0x4c040000, 0x4c080000,
+ 0x0401fe88, 0x5c001000, 0x5c000800, 0x0401f020,
+ 0x59b800ea, 0x8c000516, 0x0402001d, 0x4a0370e4,
+ 0x00300000, 0x480770e1, 0x42001000, 0x0000ff00,
+ 0x80081040, 0x04000012, 0x59b808e4, 0x8c040d28,
+ 0x040207fc, 0x42001000, 0x0010b804, 0x50080000,
+ 0x80000040, 0x04020005, 0x4a0370e5, 0x00000002,
+ 0x4a0370e4, 0x00000200, 0x02001800, 0x001005d8,
+ 0x44001000, 0x8c040d2c, 0x1c01f000, 0x41f80000,
+ 0x50000000, 0x0201f800, 0x001005d8, 0x80081040,
+ 0x040207d3, 0x41f80000, 0x50000000, 0x0201f800,
+ 0x001005d8, 0x4d380000, 0x59300c06, 0x82040580,
+ 0x00000009, 0x04020006, 0x42027000, 0x00000047,
+ 0x0201f800, 0x000207a1, 0x80000580, 0x5c027000,
+ 0x1c01f000, 0x4c500000, 0x4a03900d, 0x00000001,
+ 0x59c8a020, 0x4a03900d, 0x00000002, 0x59c80820,
+ 0x8c50a52e, 0x04000002, 0x900409c0, 0x82040d00,
+ 0x0000ffff, 0x0201f800, 0x00105dd7, 0x02000800,
+ 0x001005d8, 0x4933c857, 0x8250a500, 0xff000000,
+ 0x82500580, 0x05000000, 0x04000003, 0x82000540,
+ 0x00000001, 0x5c00a000, 0x1c01f000, 0x0401ffe6,
+ 0x4933c857, 0x59300406, 0x82000580, 0x00000000,
+ 0x04000040, 0x59c82021, 0x4a03900d, 0x00000001,
+ 0x59c82821, 0x82142d00, 0x0000ffff, 0x59325808,
+ 0x812e59c0, 0x04000037, 0x59326809, 0x0201f800,
+ 0x001048d9, 0x02020800, 0x001092b6, 0x599c0019,
+ 0x8c00050c, 0x04020018, 0x0201f800, 0x001048d9,
+ 0x04020015, 0x59300811, 0x4807c857, 0x592c0408,
+ 0x8c00051c, 0x0402000e, 0x8400055c, 0x48025c08,
+ 0x592c0a04, 0x82040d00, 0x000000ff, 0x82040580,
+ 0x00000048, 0x04000004, 0x82040580, 0x00000018,
+ 0x04020003, 0x59300811, 0x48065803, 0x4a026011,
+ 0x7fffffff, 0x48166013, 0x0201f800, 0x001010dd,
+ 0x04020014, 0x0401f9fd, 0x40280000, 0x4802600d,
+ 0x04000005, 0x4832600b, 0x50200000, 0x4802600a,
+ 0x4822600c, 0x59300414, 0x8c00051c, 0x04020004,
+ 0x599c0019, 0x8c00050c, 0x0402086e, 0x4a03900d,
+ 0x00000040, 0x4a0370e5, 0x00000008, 0x1c01f000,
+ 0x59880052, 0x80000000, 0x48031052, 0x4a03900d,
+ 0x00000040, 0x42000000, 0xc0000000, 0x0401f71d,
+ 0x4cf80000, 0x58f40000, 0x8001f540, 0x0401f820,
+ 0x41781800, 0x0401f8e4, 0x04020014, 0x44140800,
+ 0x0401f82a, 0x04000011, 0x40043800, 0x42001800,
+ 0x00000001, 0x40142000, 0x0401f8db, 0x0402000b,
+ 0x801c3800, 0x501c0000, 0x44000800, 0x0401f810,
+ 0x801c0580, 0x04000004, 0x44103800, 0x801c3840,
+ 0x44143800, 0x0401f819, 0x5c01f000, 0x1c01f000,
+ 0x80f9f1c0, 0x04020003, 0x58f41202, 0x0401f003,
+ 0x42001000, 0x00000007, 0x1c01f000, 0x80f9f1c0,
+ 0x04020006, 0x58f40401, 0x82000480, 0x00000002,
+ 0x80f40400, 0x0401f005, 0x58f80401, 0x82000480,
+ 0x00000002, 0x80f80400, 0x50002800, 0x80000000,
+ 0x50002000, 0x1c01f000, 0x80f9f1c0, 0x04020008,
+ 0x58f40401, 0x82000480, 0x00000002, 0x02001800,
+ 0x001005d8, 0x4801ec01, 0x0401f00b, 0x58f80401,
+ 0x82000480, 0x00000002, 0x02001800, 0x001005d8,
+ 0x4801f401, 0x82000580, 0x00000002, 0x04020002,
+ 0x0401f809, 0x58f40202, 0x80000040, 0x4801ea02,
+ 0x02000800, 0x001005d8, 0x82000580, 0x00000001,
+ 0x1c01f000, 0x4d2c0000, 0x40fa5800, 0x0201f800,
+ 0x001007f4, 0x4979e800, 0x4179f000, 0x5c025800,
+ 0x1c01f000, 0x80f5e9c0, 0x04000009, 0x80f9f1c0,
+ 0x04020ff5, 0x4d2c0000, 0x40f65800, 0x0201f800,
+ 0x001007f4, 0x4179e800, 0x5c025800, 0x1c01f000,
+ 0x4cf40000, 0x59300807, 0x82040500, 0x00003100,
+ 0x04020032, 0x8c040d22, 0x04000032, 0x5930001f,
+ 0x8001ed40, 0x02000800, 0x001005d8, 0x82000580,
+ 0xffffffff, 0x04000029, 0x58f40201, 0x82000580,
+ 0x0000dcb3, 0x02020800, 0x001005d8, 0x58f40a02,
+ 0x82040500, 0x0000fffe, 0x04000003, 0x0401ff89,
+ 0x58f40a02, 0x82040480, 0x0000000f, 0x04021059,
+ 0x80040800, 0x4805ea02, 0x82040580, 0x00000008,
+ 0x0400005d, 0x82040480, 0x00000008, 0x0400100a,
+ 0x58f40000, 0x8001ed40, 0x02000800, 0x001005d8,
+ 0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800,
+ 0x001005d8, 0x58f40401, 0x82000c00, 0x00000002,
+ 0x4805ec01, 0x80f40400, 0x59300812, 0x44040000,
+ 0x80000000, 0x45780000, 0x5c01e800, 0x1c01f000,
+ 0x42001000, 0x00000400, 0x59b800e4, 0x8c000524,
+ 0x04020023, 0x4a0370e4, 0x00030000, 0x40000000,
+ 0x59b800e4, 0x8c000524, 0x0402001b, 0x59300807,
+ 0x84040d62, 0x48066007, 0x4a0370e4, 0x00020000,
+ 0x4d2c0000, 0x0201f800, 0x001007d3, 0x04000025,
+ 0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008,
+ 0x80001d40, 0x02000800, 0x001005d8, 0x580c080f,
+ 0x48065803, 0x59301811, 0x40040000, 0x800c0580,
+ 0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004,
+ 0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000,
+ 0x40000000, 0x80081040, 0x02000800, 0x001005d8,
+ 0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01,
+ 0x00000006, 0x497a5804, 0x400c0000, 0x80040480,
+ 0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9,
+ 0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3,
+ 0x4d2c0000, 0x58f65800, 0x0201f800, 0x001007f4,
+ 0x40f65800, 0x0201f800, 0x001007f4, 0x5c025800,
+ 0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x001007d3,
+ 0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01,
+ 0x00000002, 0x492de800, 0x412de800, 0x5c025800,
+ 0x0401f7a5, 0x0401ff33, 0x82f40400, 0x00000004,
+ 0x800c0400, 0x40000800, 0x50040000, 0x80100580,
+ 0x04000016, 0x82040c00, 0x00000002, 0x80081040,
+ 0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202,
+ 0x82081480, 0x00000007, 0x82f80400, 0x00000002,
+ 0x800c0400, 0x40000800, 0x50040000, 0x80100580,
+ 0x04000006, 0x82040c00, 0x00000002, 0x80081040,
+ 0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000,
+ 0x4001e800, 0x592c0a06, 0x800409c0, 0x0402001d,
+ 0x82f40580, 0xffffffff, 0x04000017, 0x58f40201,
+ 0x82000580, 0x0000dcb3, 0x02020800, 0x001005d8,
+ 0x58f40000, 0x8001f540, 0x04000006, 0x58f80201,
+ 0x82000580, 0x0000ddb9, 0x02020800, 0x001005d8,
+ 0x41783800, 0x0401f839, 0x04020006, 0x0401ff32,
+ 0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000,
+ 0x0401ff2d, 0x4a025a06, 0x00000011, 0x0401f7f9,
+ 0x82f40580, 0xffffffff, 0x04020f27, 0x0401f7f5,
+ 0x4cf40000, 0x4cf80000, 0x4001e800, 0x82040580,
+ 0x00000001, 0x0402001f, 0x82f40580, 0xffffffff,
+ 0x04000019, 0x58f40201, 0x82000580, 0x0000dcb3,
+ 0x02020800, 0x001005d8, 0x58f40000, 0x8001f540,
+ 0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9,
+ 0x02020800, 0x001005d8, 0x41783800, 0x0401f813,
+ 0x04020008, 0x0401ff0c, 0x42000800, 0x00000001,
+ 0x497a601f, 0x5c01f000, 0x5c01e800, 0x1c01f000,
+ 0x0401ff05, 0x42000800, 0x00000011, 0x0401f7f9,
+ 0x4c040000, 0x82f40580, 0xffffffff, 0x04020efe,
+ 0x5c000800, 0x0401f7f3, 0x4803c856, 0x401c2000,
+ 0x41781800, 0x0401ff8c, 0x0402002c, 0x58f42003,
+ 0x42001800, 0x00000001, 0x0401ff87, 0x04020027,
+ 0x0401feb8, 0x40082800, 0x82f40400, 0x00000004,
+ 0x40003000, 0x50182000, 0x40100000, 0x801c0580,
+ 0x04000005, 0x42001800, 0x00000001, 0x0401ff7a,
+ 0x0402001a, 0x82183400, 0x00000002, 0x80142840,
+ 0x040207f5, 0x80f9f1c0, 0x04000013, 0x58f42a02,
+ 0x82142c80, 0x00000007, 0x82f80400, 0x00000003,
+ 0x40003000, 0x50182000, 0x40100000, 0x801c0580,
+ 0x04000005, 0x42001800, 0x00000001, 0x0401ff66,
+ 0x04020006, 0x82183400, 0x00000002, 0x80142840,
+ 0x040207f5, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x0401f7fd, 0x0201f800, 0x001005d8, 0x58380207,
+ 0x8c000502, 0x040007fc, 0x50200000, 0x80387c00,
+ 0x583c2800, 0x583c2001, 0x58380404, 0x80001540,
+ 0x04020002, 0x58381407, 0x58c83401, 0x58380c08,
+ 0x59303807, 0x497a6012, 0x497a6013, 0x0201f000,
+ 0x000200be, 0x592c0408, 0x8c000502, 0x040007ea,
+ 0x592c0409, 0x80000540, 0x040007e7, 0x82000c80,
+ 0x00000002, 0x04001011, 0x58380001, 0x80007540,
+ 0x02000800, 0x001005d8, 0x58380204, 0x82000500,
+ 0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+ 0x40040000, 0x800409c0, 0x04000005, 0x82040c80,
+ 0x00000005, 0x040217f1, 0x80204400, 0x50200000,
+ 0x80387c00, 0x583c2800, 0x583c2001, 0x583c1002,
+ 0x592c0a07, 0x592c4c08, 0x592c300d, 0x59303807,
+ 0x497a6012, 0x497a6013, 0x4816600e, 0x4812600f,
+ 0x480a6010, 0x481a6011, 0x80040840, 0x4806600d,
+ 0x02000000, 0x000200c6, 0x80204000, 0x50201800,
+ 0x800c19c0, 0x0402000c, 0x58380001, 0x80007540,
+ 0x02000800, 0x001005d8, 0x58380204, 0x82000500,
+ 0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+ 0x50201800, 0x483a600b, 0x480e600a, 0x4822600c,
+ 0x0201f000, 0x000200c6, 0x4803c856, 0x592c0208,
+ 0x8c00051e, 0x04020017, 0x50200000, 0x80306c00,
+ 0x40240000, 0x0c01f001, 0x00100e46, 0x00100e46,
+ 0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e46,
+ 0x00100e46, 0x00100e46, 0x00100e4f, 0x00100e46,
+ 0x00100e4f, 0x00100e46, 0x00100e46, 0x00100e4f,
+ 0x00100e46, 0x00100e46, 0x0201f800, 0x001005d8,
+ 0x8400051e, 0x48025a08, 0x50200000, 0x80306c00,
+ 0x58343801, 0x481e600f, 0x0401f007, 0x58341802,
+ 0x58342800, 0x58343801, 0x480e6010, 0x4816600e,
+ 0x481e600f, 0x0401f246, 0x4933c857, 0x5931f808,
+ 0x59300a06, 0x800409c0, 0x04000005, 0x80040906,
+ 0x04020002, 0x80040800, 0x4805fc06, 0x4a026206,
+ 0x00000002, 0x592c0409, 0x82000500, 0x00000008,
+ 0x0400000b, 0x0401f834, 0x59300203, 0x82000580,
+ 0x00000004, 0x04020005, 0x42027000, 0x00000048,
+ 0x0201f800, 0x000207a1, 0x1c01f000, 0x4cfc0000,
+ 0x58fc0204, 0x82000500, 0x000000ff, 0x82000580,
+ 0x00000048, 0x0402000c, 0x58fc000b, 0x800001c0,
+ 0x04000009, 0x58fc0407, 0x800001c0, 0x04000006,
+ 0x58fc080b, 0x8c040d16, 0x04000017, 0x58fc0007,
+ 0x0401f00a, 0x58fc0408, 0x8c000512, 0x04020014,
+ 0x58fc0c09, 0x8c040d16, 0x04020003, 0x5c01f800,
+ 0x1c01f000, 0x58fc000a, 0x59300811, 0x80040580,
+ 0x04020009, 0x59300007, 0x84000500, 0x48026007,
+ 0x42027000, 0x00000048, 0x5c01f800, 0x0201f000,
+ 0x000207a1, 0x5c01f800, 0x1c01f000, 0x58fdf809,
+ 0x0401f7ec, 0x4933c857, 0x59b808ea, 0x82040d00,
+ 0x00000007, 0x82040580, 0x00000000, 0x0400001e,
+ 0x82040580, 0x00000003, 0x0400001b, 0x59300406,
+ 0x4c000000, 0x4a026406, 0x00000000, 0x42003000,
+ 0x00000041, 0x42000000, 0x50000000, 0x41300800,
+ 0x4c180000, 0x0401fce7, 0x5c003000, 0x0400000b,
+ 0x42000000, 0x0000001e, 0x80000040, 0x040207ff,
+ 0x80183040, 0x040207f4, 0x42000000, 0x40000000,
+ 0x41300800, 0x0401fcdb, 0x5c000000, 0x48026406,
+ 0x1c01f000, 0x59300007, 0x84000500, 0x48026007,
+ 0x0401f7fc, 0x59c00007, 0x4a038006, 0x30000000,
+ 0x40000000, 0x59c00007, 0x8c00050a, 0x040207fe,
+ 0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857,
+ 0x4dc00000, 0x4a0370e8, 0x00000000, 0x42038000,
+ 0x00007720, 0x0401fff0, 0x42038000, 0x00007700,
+ 0x0401ffed, 0x0201f800, 0x0010513b, 0x04020013,
+ 0x4a038891, 0x0000ffff, 0x497b8880, 0x497b8892,
+ 0x42001000, 0x00000190, 0x40000000, 0x40000000,
+ 0x80081040, 0x040207fd, 0x42000000, 0x0010b8a6,
+ 0x0201f800, 0x0010aa47, 0x0401f80e, 0x5c038000,
+ 0x0201f000, 0x00105258, 0x0401f82d, 0x42000000,
+ 0x0010b8a7, 0x0201f800, 0x0010aa47, 0x0401f805,
+ 0x48178892, 0x480b8880, 0x5c038000, 0x1c01f000,
+ 0x496fc857, 0x836c0580, 0x00000003, 0x0402000b,
+ 0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048,
+ 0x42001800, 0x0000ffff, 0x0201f800, 0x00103a3e,
+ 0x5c001800, 0x5c001000, 0x42000800, 0x0000003c,
+ 0x0201f800, 0x00101345, 0x59a8006c, 0x80000540,
+ 0x04000006, 0x59a8106d, 0x800811c0, 0x04000003,
+ 0x0201f800, 0x00101aaf, 0x4a038891, 0x0000ffff,
+ 0x4a03900d, 0x00000040, 0x0201f800, 0x0010098e,
+ 0x4a0370e8, 0x00000001, 0x1c01f000, 0x5c000000,
+ 0x4c000000, 0x4803c857, 0x59c41080, 0x497b8880,
+ 0x59c42892, 0x497b8892, 0x0201f800, 0x0010513b,
+ 0x04020002, 0x1c01f000, 0x42002000, 0x00000260,
+ 0x59c418a4, 0x820c1d00, 0x0000000f, 0x820c0580,
+ 0x00000000, 0x04000010, 0x59c41805, 0x820c1d00,
+ 0x00000001, 0x0402000e, 0x59c418a4, 0x820c1d00,
+ 0x0000000f, 0x820c0480, 0x00000007, 0x04001004,
+ 0x820c0480, 0x0000000c, 0x04001003, 0x80102040,
+ 0x040207ec, 0x497b8891, 0x1c01f000, 0x4c100000,
+ 0x42002000, 0x00000019, 0x46000000, 0x00000001,
+ 0x0201f800, 0x00101937, 0x50001800, 0x820c1d00,
+ 0x00000001, 0x04000005, 0x80102040, 0x040207f7,
+ 0x5c002000, 0x0401f7f0, 0x5c002000, 0x0401f7ec,
+ 0x4803c856, 0x1c01f000, 0x4d2c0000, 0x59325808,
+ 0x592c0a04, 0x4807c857, 0x82040d00, 0x000000ff,
+ 0x82040500, 0x0000000f, 0x0c01f001, 0x00100f67,
+ 0x00100f67, 0x00100f67, 0x00100f7f, 0x00100f67,
+ 0x00100f67, 0x00100f67, 0x00100f67, 0x00100f67,
+ 0x00100f7f, 0x00100f67, 0x00100f69, 0x00100f67,
+ 0x00100f67, 0x00100f67, 0x00100f67, 0x0201f800,
+ 0x001005d8, 0x82040580, 0x0000003b, 0x02020800,
+ 0x001005d8, 0x592c020a, 0x8c000500, 0x0400005f,
+ 0x592c1a07, 0x82040500, 0x0000000f, 0x82000400,
+ 0x001010bd, 0x50001000, 0x50080000, 0x59302013,
+ 0x4802600a, 0x492e600b, 0x480a600c, 0x480e600d,
+ 0x48126012, 0x5c025800, 0x1c01f000, 0x82040500,
+ 0x0000000f, 0x82000400, 0x001010bd, 0x50001000,
+ 0x50080000, 0x592c1a07, 0x4802600a, 0x492e600b,
+ 0x480a600c, 0x480e600d, 0x497a6012, 0x0401f7f2,
+ 0x8c040d00, 0x04020041, 0x82040d00, 0x00000080,
+ 0x0400003e, 0x0201f000, 0x000200cf, 0x59300013,
+ 0x59301012, 0x80080580, 0x0402000c, 0x42007800,
+ 0x80000005, 0x592c1208, 0x82080500, 0xffff7fff,
+ 0x48025a08, 0x8c08151e, 0x0402002d, 0x823c7d40,
+ 0x00000020, 0x0401f02a, 0x480bc857, 0x42000000,
+ 0x0010b851, 0x0201f800, 0x0010aa47, 0x59300414,
+ 0x4803c857, 0x8c000514, 0x04020007, 0x599c1819,
+ 0x8c0c1d12, 0x04020004, 0x820c1d40, 0x00000001,
+ 0x0401f01d, 0x59302013, 0x0401f92b, 0x0402001a,
+ 0x42007800, 0x80000005, 0x5930500d, 0x592c0208,
+ 0x4803c857, 0x8c00051e, 0x04020005, 0x823c7d40,
+ 0x00000020, 0x5930400c, 0x0401f004, 0x8400051e,
+ 0x48025a08, 0x0401f8da, 0x50201800, 0x480e600a,
+ 0x4832600b, 0x4822600c, 0x482a600d, 0x480fc857,
+ 0x4833c857, 0x4823c857, 0x482bc857, 0x80000580,
+ 0x483e6004, 0x1c01f000, 0x0201f800, 0x001005d8,
+ 0x4933c857, 0x4d2c0000, 0x59900004, 0x81300580,
+ 0x02020800, 0x001005d8, 0x0201f800, 0x00109037,
+ 0x02000800, 0x001005d8, 0x59325808, 0x4d3c0000,
+ 0x4d400000, 0x59300004, 0x4803c857, 0x4c000000,
+ 0x0201f800, 0x00106dc3, 0x0201f800, 0x00106b8a,
+ 0x5c000000, 0x8c000516, 0x04000010, 0x592c000f,
+ 0x4803c857, 0x48025807, 0x41780800, 0x42028000,
+ 0x00000002, 0x0201f800, 0x00104e70, 0x4a025c06,
+ 0x0000ffff, 0x0201f800, 0x000202da, 0x0201f800,
+ 0x00107911, 0x0401f015, 0x4a026203, 0x00000002,
+ 0x592c0208, 0x8400054e, 0x48025a08, 0x59300406,
+ 0x82000580, 0x00000006, 0x04020009, 0x811800ca,
+ 0x81c80c00, 0x58040939, 0x592c000d, 0x80040480,
+ 0x592c080f, 0x80040480, 0x4802580b, 0x417a7800,
+ 0x0201f800, 0x00108be3, 0x5c028000, 0x5c027800,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+ 0x59900004, 0x81300580, 0x02020800, 0x001005d8,
+ 0x0201f800, 0x00109037, 0x02000800, 0x001005d8,
+ 0x59325808, 0x592c0208, 0x84000540, 0x48025a08,
+ 0x0401f7bf, 0x491bc857, 0x49d3c857, 0x4dd00000,
+ 0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600,
+ 0x4a03a005, 0x80000002, 0x42000000, 0x00001000,
+ 0x50000000, 0x82000480, 0x24220001, 0x04020029,
+ 0x59d01006, 0x82080500, 0x00006000, 0x82000580,
+ 0x00006000, 0x0400002f, 0x82080500, 0x40008000,
+ 0x040007f8, 0x800409c0, 0x0402002a, 0x811a31c0,
+ 0x04000028, 0x42000000, 0x00001002, 0x50001000,
+ 0x46000000, 0x00000512, 0x42001800, 0x0000000a,
+ 0x59e00000, 0x8c00051a, 0x040207fc, 0x800c1840,
+ 0x040207fc, 0x42000000, 0x00001002, 0x46000000,
+ 0x00000514, 0x42001800, 0x0000000a, 0x59e00000,
+ 0x8c00053a, 0x040207fc, 0x800c1840, 0x040207fc,
+ 0x42000000, 0x00001002, 0x44080000, 0x0401f00d,
+ 0x59d01006, 0x82080500, 0x00006000, 0x82000580,
+ 0x00006000, 0x04000007, 0x8c08151e, 0x040007f9,
+ 0x59d01006, 0x82080500, 0x00006000, 0x040207f5,
+ 0x83d3a400, 0x00000020, 0x80040800, 0x82040480,
+ 0x00000005, 0x040017bf, 0x5c03a000, 0x1c01f000,
+ 0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800,
+ 0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005,
+ 0x80000001, 0x59d00006, 0x83d3a400, 0x00000020,
+ 0x80040800, 0x82040480, 0x00000005, 0x040017f8,
+ 0x5c03a000, 0x1c01f000, 0x59d00006, 0x8c00053e,
+ 0x0400001e, 0x59902804, 0x4817c857, 0x801429c0,
+ 0x04000013, 0x5990000a, 0x5990080b, 0x5990100c,
+ 0x5990180d, 0x4800280a, 0x4804280b, 0x4808280c,
+ 0x480c280d, 0x59d00000, 0x59d00801, 0x59d01002,
+ 0x59d01803, 0x59d02004, 0x4800280e, 0x4804280f,
+ 0x48082810, 0x480c2811, 0x48102812, 0x59900006,
+ 0x82000500, 0xffff0000, 0x48032006, 0x4a03a005,
+ 0x30000000, 0x59d00006, 0x1c01f000, 0x4803c856,
+ 0x80204000, 0x50200000, 0x80000540, 0x04000003,
+ 0x80285040, 0x1c01f000, 0x58300001, 0x80000540,
+ 0x0400000e, 0x4802600b, 0x40006000, 0x58300204,
+ 0x82000500, 0x0000000f, 0x82000400, 0x001010bd,
+ 0x50004000, 0x802041c0, 0x02000800, 0x001005d8,
+ 0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000,
+ 0x00000005, 0x00000008, 0x0000000b, 0x0000000e,
+ 0x00000011, 0x00000000, 0x00000000, 0x0000000b,
+ 0x00000000, 0x00000000, 0x00000000, 0x001010b8,
+ 0x001010b7, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x001010b8, 0x001010b7, 0x001010b4,
+ 0x001010b8, 0x001010b7, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x001010b8,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x001010b8, 0x001010b8, 0x001010b8,
+ 0x00000000, 0x001010b8, 0x00000000, 0x00000000,
+ 0x00000000, 0x4813c857, 0x492fc857, 0x4933c857,
+ 0x48126012, 0x592c5207, 0x802851c0, 0x0400004a,
+ 0x412c6000, 0x0401f84b, 0x04000009, 0x82240580,
+ 0x00000002, 0x04020003, 0x5830000d, 0x80102480,
+ 0x50200000, 0x80004540, 0x0400003f, 0x50200000,
+ 0x80000540, 0x0400000b, 0x80301400, 0x58080002,
+ 0x80102480, 0x0400101e, 0x801021c0, 0x04000009,
+ 0x80285040, 0x04000034, 0x80204000, 0x0401f7f4,
+ 0x58300001, 0x80006540, 0x0400002f, 0x0401f7e6,
+ 0x80285040, 0x0400002c, 0x80204000, 0x50200000,
+ 0x80000540, 0x0402000a, 0x58300001, 0x80006540,
+ 0x04000025, 0x58300204, 0x82004d00, 0x0000000f,
+ 0x82244400, 0x001010bd, 0x50204000, 0x592c0208,
+ 0x8400051e, 0x48025a08, 0x0401f013, 0x80102080,
+ 0x80102000, 0x48126010, 0x4813c857, 0x58080802,
+ 0x40100000, 0x80042480, 0x02001800, 0x001005d8,
+ 0x58080000, 0x58081801, 0x80102400, 0x4812600e,
+ 0x480e600f, 0x4813c857, 0x592c0208, 0x8400055e,
+ 0x48025a08, 0x4833c857, 0x4823c857, 0x482bc857,
+ 0x4832600b, 0x4822600c, 0x482a600d, 0x80000580,
+ 0x0401f003, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x58300204, 0x82004d00, 0x0000000f, 0x82244400,
+ 0x001010bd, 0x82000500, 0x000000ff, 0x82000580,
+ 0x00000029, 0x0402001b, 0x50204000, 0x592c0409,
+ 0x80000540, 0x02000800, 0x001005d8, 0x82000c80,
+ 0x00000002, 0x04001011, 0x58300001, 0x80006540,
+ 0x02000800, 0x001005d8, 0x58300204, 0x82000500,
+ 0x0000000f, 0x82000400, 0x001010bd, 0x50004000,
+ 0x40040000, 0x800409c0, 0x04000006, 0x82040c80,
+ 0x00000005, 0x040217f1, 0x80204400, 0x80000580,
+ 0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000,
+ 0x00100903, 0x1c01f000, 0x4c5c0000, 0x59e4b800,
+ 0x485fc857, 0x825c0500, 0x0000001f, 0x04000004,
+ 0x59e40862, 0x0201f800, 0x001005d8, 0x825c0500,
+ 0x000000e0, 0x02000800, 0x001005d8, 0x8c5cbd0e,
+ 0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a,
+ 0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856,
+ 0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000,
+ 0x42007800, 0x0010b8ec, 0x583c0001, 0x583c0802,
+ 0x80040540, 0x0400003f, 0x42000800, 0x0010b7f7,
+ 0x50065800, 0x592c0002, 0x82000580, 0x00000000,
+ 0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000,
+ 0x80040400, 0x59e40852, 0x4807c857, 0x80041480,
+ 0x04021008, 0x40001000, 0x480bc857, 0x4a007800,
+ 0x00000001, 0x0401f006, 0x4803c857, 0x0401f029,
+ 0x59e41050, 0x480bc857, 0x49787800, 0x480bc857,
+ 0x480fc857, 0x592c0003, 0x80000540, 0x04000006,
+ 0x80080580, 0x04020004, 0x592c0003, 0x4803c857,
+ 0x480bc857, 0x480a5803, 0x592c0007, 0x800001c0,
+ 0x04000007, 0x592c1007, 0x480bc857, 0x583c0003,
+ 0x4803c857, 0x80080480, 0x04001003, 0x583c1001,
+ 0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857,
+ 0x4a025801, 0x00000000, 0x4a025809, 0x001011bc,
+ 0x480a5807, 0x48065808, 0x59e40053, 0x48025804,
+ 0x412c1000, 0x492fc857, 0x0201f800, 0x00100858,
+ 0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000,
+ 0x42007800, 0x0010b7f7, 0x503c7800, 0x4a007802,
+ 0x00000100, 0x42007800, 0x0010b8ec, 0x583c0000,
+ 0x4803c857, 0x82000d80, 0x00000001, 0x04000004,
+ 0x80000000, 0x48007800, 0x0401f019, 0x49787800,
+ 0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806,
+ 0x800c0580, 0x04020002, 0x49787806, 0x583c0807,
+ 0x800409c0, 0x0400000e, 0x583c0008, 0x80000000,
+ 0x48007808, 0x80040580, 0x04020009, 0x49787808,
+ 0x583c2006, 0x42001800, 0x00000001, 0x42001000,
+ 0x00008028, 0x0201f800, 0x00103a3e, 0x1c01f000,
+ 0x4a03c800, 0x00000020, 0x0201f800, 0x0010aa40,
+ 0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001,
+ 0x00000000, 0x82040d00, 0x43000f80, 0x02020800,
+ 0x001005d8, 0x58380009, 0x4803c00f, 0x0201f800,
+ 0x00109402, 0x583a5808, 0x592c0000, 0x48007008,
+ 0x800001c0, 0x04020002, 0x49787007, 0x0201f800,
+ 0x001007f4, 0x5c025800, 0x0201f000, 0x0010087d,
+ 0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000,
+ 0x5830000a, 0x80025d40, 0x02000800, 0x001005d8,
+ 0x592e6008, 0x4c300000, 0x0201f800, 0x0010941a,
+ 0x5c006000, 0x02000800, 0x001005d8, 0x58300002,
+ 0x82000580, 0x00000100, 0x04020010, 0x5930780b,
+ 0x583c0001, 0x80000540, 0x0400000e, 0x4802600b,
+ 0x40007800, 0x82000400, 0x00000002, 0x48006003,
+ 0x583c0000, 0x48006004, 0x40301000, 0x0201f800,
+ 0x00100858, 0x0401f00c, 0x4a025a06, 0x00000002,
+ 0x4c300000, 0x0201f800, 0x000202da, 0x5c006000,
+ 0x40325800, 0x0201f800, 0x001007f4, 0x0201f800,
+ 0x0002077d, 0x5c026000, 0x5c025800, 0x5c007800,
+ 0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000,
+ 0x42007000, 0x0010b7f8, 0x58380801, 0x82040580,
+ 0x00000002, 0x04020011, 0x58386002, 0x5830000a,
+ 0x812c0580, 0x0402000d, 0x59e00004, 0x8c00050e,
+ 0x040007fe, 0x59dc0006, 0x4803c857, 0x4a03b805,
+ 0x20000000, 0x8c00053e, 0x040007f8, 0x4a007001,
+ 0x00000000, 0x0401f019, 0x58386006, 0x40305000,
+ 0x803061c0, 0x02000800, 0x001005d8, 0x5830000a,
+ 0x812c0580, 0x04000004, 0x40305000, 0x58306000,
+ 0x0401f7f8, 0x40280000, 0x80300580, 0x58300000,
+ 0x04000006, 0x48005000, 0x800001c0, 0x04020007,
+ 0x48287005, 0x0401f005, 0x800001c0, 0x04020002,
+ 0x48007005, 0x48007006, 0x40325800, 0x0201f800,
+ 0x001007f4, 0x42007000, 0x0010b7f8, 0x58380001,
+ 0x82000580, 0x00000000, 0x02000800, 0x0010087d,
+ 0x5c026000, 0x5c025800, 0x1c01f000, 0x4803c856,
+ 0x42000800, 0x0000003c, 0x48079000, 0x59c80000,
+ 0x80040500, 0x040207fe, 0x497b9005, 0x4a039035,
+ 0x00880200, 0x59a8000e, 0x800000e0, 0x4803900e,
+ 0x4a039011, 0x00000024, 0x4a03900f, 0x0010d1c0,
+ 0x4a039010, 0x0010d1c0, 0x4a039015, 0x0000007f,
+ 0x4a03900d, 0x00000040, 0x4a039000, 0x00001600,
+ 0x1c01f000, 0x59c80007, 0x8c000508, 0x040208b7,
+ 0x59c80800, 0x8c040d16, 0x04020004, 0x82000500,
+ 0x00000006, 0x0c01f005, 0x4807c857, 0x82000500,
+ 0x0000000e, 0x0c01f001, 0x001012a8, 0x001012a6,
+ 0x00105999, 0x001012a6, 0x001012aa, 0x001012a6,
+ 0x001012aa, 0x001012aa, 0x001012a6, 0x001012a6,
+ 0x001012a6, 0x001012a6, 0x001012aa, 0x001012a6,
+ 0x001012aa, 0x001012a6, 0x0201f800, 0x001005d8,
+ 0x4803c857, 0x1c01f000, 0x59c8080c, 0x4807c857,
+ 0x82040500, 0x00006000, 0x04000004, 0x0201f800,
+ 0x0010aa03, 0x0401f006, 0x82040500, 0x007f0000,
+ 0x04000006, 0x0201f800, 0x0010a9d5, 0x0201f800,
+ 0x00106eb3, 0x0401f02b, 0x82040500, 0x00000014,
+ 0x04000014, 0x0201f800, 0x0010aa32, 0x836c0580,
+ 0x00000003, 0x0400000d, 0x0201f800, 0x0010513b,
+ 0x04000004, 0x0201f800, 0x0010411d, 0x0401f007,
+ 0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
+ 0x0201f800, 0x001050a2, 0x0401f817, 0x0401f015,
+ 0x82040500, 0x00001c00, 0x04000005, 0x0201f800,
+ 0x0010aa11, 0x0401f810, 0x0401f00e, 0x82040500,
+ 0x00000140, 0x04000005, 0x0201f800, 0x0010aa24,
+ 0x0401f809, 0x0401f007, 0x82040500, 0x00008000,
+ 0x04000004, 0x0201f800, 0x0010a9fc, 0x0401f802,
+ 0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000,
+ 0x0201f800, 0x00100ec9, 0x5c002800, 0x5c002000,
+ 0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804,
+ 0x59a8002b, 0x82000500, 0xfffff000, 0x80040540,
+ 0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000,
+ 0x80040540, 0x4803502f, 0x48078882, 0x82041c00,
+ 0x0000000f, 0x800c1908, 0x820c1c00, 0x00000004,
+ 0x400c2000, 0x901029c0, 0x82040480, 0x000001e4,
+ 0x04021005, 0x42001000, 0x00000008, 0x801020c6,
+ 0x0401f031, 0x82040480, 0x00000230, 0x04021009,
+ 0x42001000, 0x00000007, 0x801000c2, 0x800000c2,
+ 0x80100400, 0x80100400, 0x80102400, 0x0401f026,
+ 0x82040480, 0x00000298, 0x04021008, 0x42001000,
+ 0x00000006, 0x801000c2, 0x800000c2, 0x80100400,
+ 0x80102400, 0x0401f01c, 0x82040480, 0x00000328,
+ 0x04021007, 0x42001000, 0x00000005, 0x801000c2,
+ 0x800000c2, 0x80102400, 0x0401f013, 0x82040480,
+ 0x00000404, 0x04021005, 0x42001000, 0x00000004,
+ 0x801020c4, 0x0401f00c, 0x82040480, 0x0000056c,
+ 0x04021006, 0x42001000, 0x00000003, 0x801000c2,
+ 0x80102400, 0x0401f004, 0x42001000, 0x00000002,
+ 0x801020c2, 0x82100480, 0x00000110, 0x80000080,
+ 0x80002000, 0x800800d0, 0x80140540, 0x80100540,
+ 0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800,
+ 0x001005d0, 0x82040d00, 0x0000007c, 0x48079000,
+ 0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04,
+ 0x04000003, 0x59c80035, 0x48039035, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
+ 0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001,
+ 0x497b8807, 0x59c40005, 0x48038805, 0x0201f800,
+ 0x00101815, 0x4201d000, 0x000001f4, 0x0201f800,
+ 0x0010608e, 0x497b880e, 0x4200b000, 0x000001f4,
+ 0x42000000, 0x00000001, 0x42000800, 0x00000014,
+ 0x0201f800, 0x00101944, 0x42000800, 0x00000014,
+ 0x0201f800, 0x0010193f, 0x8c040d00, 0x04000005,
+ 0x8058b040, 0x040207f3, 0x0201f800, 0x001005d8,
+ 0x4200b000, 0x00000032, 0x42000000, 0x00000001,
+ 0x42000800, 0x000000b4, 0x0201f800, 0x00101944,
+ 0x42000800, 0x000000b4, 0x0201f800, 0x0010193f,
+ 0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3,
+ 0x0201f800, 0x001005d8, 0x59c40005, 0x48038805,
+ 0x42000000, 0x00000089, 0x800008d0, 0x48075054,
+ 0x48075055, 0x48075056, 0x42000800, 0x000000e0,
+ 0x0201f800, 0x00101944, 0x42000800, 0x000000f4,
+ 0x0201f800, 0x0010193f, 0x82040500, 0xffffffd1,
+ 0x82000540, 0x00000002, 0x42000800, 0x000000f4,
+ 0x0201f800, 0x00101944, 0x42000800, 0x000000a0,
+ 0x0201f800, 0x0010193f, 0x82040540, 0x00000001,
+ 0x42000800, 0x000000a0, 0x0201f800, 0x00101944,
+ 0x42000800, 0x00000000, 0x0201f800, 0x0010193f,
+ 0x82040540, 0x00000001, 0x42000800, 0x00000000,
+ 0x0201f800, 0x00101944, 0x4201d000, 0x0001d4c0,
+ 0x0201f800, 0x0010608e, 0x0401fa2b, 0x4a0388a7,
+ 0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae,
+ 0x000061a8, 0x4a038801, 0x00032063, 0x4a038810,
+ 0x00410108, 0x4a038811, 0x00520608, 0x4a038812,
+ 0x00450320, 0x4a038813, 0x00440405, 0x4a03881c,
+ 0x004132e1, 0x4a038850, 0x80000108, 0x4a038860,
+ 0x00000008, 0x4a038870, 0x00000008, 0x4a038851,
+ 0x80000508, 0x4a038861, 0x00800000, 0x4a038871,
+ 0x00800000, 0x4a038852, 0x80000708, 0x4a038862,
+ 0x00800000, 0x4a038872, 0x00800000, 0x4a038853,
+ 0x80000608, 0x497b8863, 0x4a038873, 0x00800000,
+ 0x4a038882, 0x00000840, 0x4a0388a5, 0x0000001e,
+ 0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530,
+ 0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800,
+ 0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001,
+ 0x42000800, 0x00000040, 0x0201f800, 0x0010193f,
+ 0x82040500, 0xffffffaf, 0x82000540, 0x00000000,
+ 0x42000800, 0x00000040, 0x0201f800, 0x00101944,
+ 0x42000800, 0x000000f4, 0x0201f800, 0x0010193f,
+ 0x4c040000, 0x40040000, 0x84000548, 0x42000800,
+ 0x000000f4, 0x0201f800, 0x00101944, 0x42000800,
+ 0x00000000, 0x0201f800, 0x0010193f, 0x82040500,
+ 0xffffffc1, 0x82000540, 0x00000038, 0x42000800,
+ 0x00000000, 0x0201f800, 0x00101944, 0x5c000000,
+ 0x42000800, 0x000000f4, 0x0201f000, 0x00101944,
+ 0x59c40805, 0x4807c857, 0x59c40006, 0x80040d00,
+ 0x02000800, 0x001005d8, 0x82040500, 0x00e00800,
+ 0x04020004, 0x8c040d3e, 0x040208c4, 0x0401f007,
+ 0x82040500, 0x00800800, 0x02020800, 0x001005d0,
+ 0x0201f800, 0x001005d8, 0x4c5c0000, 0x4c600000,
+ 0x59c4b805, 0x485fc857, 0x59c40006, 0x8c000500,
+ 0x04000003, 0x8c5cbd00, 0x04020079, 0x0201f800,
+ 0x0010513b, 0x04000014, 0x59c40005, 0x82000500,
+ 0x000000c0, 0x04000036, 0x0201f800, 0x00105151,
+ 0x04020033, 0x4a038805, 0x04000000, 0x59c400a3,
+ 0x82000500, 0xbf203fff, 0x480388a3, 0x497b5049,
+ 0x4a038805, 0x000000c0, 0x0201f800, 0x00105065,
+ 0x0401f063, 0x8c5cbd34, 0x04020025, 0x59c40005,
+ 0x8c00050c, 0x04020012, 0x8c00050e, 0x04020013,
+ 0x8c00050a, 0x04020014, 0x8c000508, 0x0400000b,
+ 0x59a80017, 0x82000580, 0x00000009, 0x04020007,
+ 0x42000000, 0x0010b844, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00105318, 0x0401f04b, 0x4a035033,
+ 0x00000000, 0x0401f00b, 0x4a035033, 0x00000002,
+ 0x0401f008, 0x42000000, 0x0010b846, 0x0201f800,
+ 0x0010aa47, 0x0201f800, 0x001052c2, 0x0401f03e,
+ 0x0201f800, 0x00105378, 0x0401f03b, 0x8c5cbd34,
+ 0x04000037, 0x59c40005, 0x8c00053a, 0x04020005,
+ 0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+ 0x4a038805, 0x02000000, 0x0201f800, 0x0010513b,
+ 0x04020010, 0x4a038805, 0x04000000, 0x0201f800,
+ 0x00105149, 0x04020008, 0x4a035033, 0x00000001,
+ 0x4202d800, 0x00000001, 0x0201f800, 0x001050a2,
+ 0x0401f05b, 0x41780000, 0x0201f800, 0x00105113,
+ 0x0201f800, 0x001019fe, 0x4000c000, 0x0201f800,
+ 0x00101963, 0x836c1580, 0x00000004, 0x0402000d,
+ 0x8c5cbd00, 0x04020012, 0x59a81005, 0x8c081506,
+ 0x04020005, 0x59c410a3, 0x82081540, 0x00000008,
+ 0x480b88a3, 0x59c41006, 0x84081540, 0x480b8806,
+ 0x4a038805, 0x04000000, 0x4202d800, 0x00000001,
+ 0x497b5014, 0x0201f800, 0x00103b38, 0x8c5cbd3c,
+ 0x04020858, 0x8c5cbd00, 0x04000036, 0x42000000,
+ 0x0010b8ca, 0x0201f800, 0x0010aa47, 0x4a038805,
+ 0x00000001, 0x4200b000, 0x000003e8, 0x4201d000,
+ 0x00000064, 0x4c580000, 0x0201f800, 0x0010608e,
+ 0x0201f800, 0x001018d3, 0x5c00b000, 0x04000004,
+ 0x8058b040, 0x040207f6, 0x0401f004, 0x4a038805,
+ 0x00000001, 0x0401f01f, 0x59c40006, 0x84000500,
+ 0x48038806, 0x0201f800, 0x00106ede, 0x497b8880,
+ 0x0201f800, 0x0010a9c0, 0x59c4000d, 0x8c000500,
+ 0x02020800, 0x0010a9ce, 0x59c400a3, 0x82000500,
+ 0xfcf8ffff, 0x480388a3, 0x4a03504c, 0x00000002,
+ 0x4202d800, 0x00000004, 0x4a038805, 0x00000001,
+ 0x0201f800, 0x001006d4, 0x0401fb3b, 0x497b5052,
+ 0x4a035049, 0x00000001, 0x0201f800, 0x00100452,
+ 0x825cbd00, 0xbbfffffe, 0x485f8805, 0x5c00c000,
+ 0x5c00b800, 0x1c01f000, 0x59c41004, 0x480bc857,
+ 0x8c081500, 0x04000006, 0x4803c856, 0x497b2807,
+ 0x0201f800, 0x00106fa4, 0x0401f00a, 0x82080500,
+ 0x000001f0, 0x04000007, 0x4803c856, 0x417a3000,
+ 0x0201f800, 0x00106062, 0x0201f800, 0x00106fc6,
+ 0x4a038805, 0x80000000, 0x1c01f000, 0x59c408a3,
+ 0x4807c857, 0x84040d40, 0x480788a3, 0x1c01f000,
+ 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+ 0x4a038805, 0x40000000, 0x42000000, 0x0010b8c6,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x00106c55,
+ 0x59c41004, 0x8c081500, 0x04000054, 0x598e600d,
+ 0x497b2807, 0x813261c0, 0x04000032, 0x59300403,
+ 0x82000580, 0x00000032, 0x0402002e, 0x5930001c,
+ 0x48038833, 0x4a038807, 0x00018000, 0x4201d000,
+ 0x00000002, 0x0201f800, 0x0010608e, 0x497b8807,
+ 0x4201d000, 0x00000002, 0x0201f800, 0x0010608e,
+ 0x0201f800, 0x00106e21, 0x4201d000, 0x00007530,
+ 0x0201f800, 0x0010608e, 0x59c408a4, 0x82040d00,
+ 0x0000000f, 0x82040d80, 0x00000000, 0x04000005,
+ 0x42000000, 0x00200000, 0x0201f800, 0x00101949,
+ 0x0201f800, 0x00106bbf, 0x59300008, 0x80000540,
+ 0x02000800, 0x001005d8, 0x40025800, 0x4a025a04,
+ 0x00000103, 0x5931d821, 0x58ef400b, 0x58ec0009,
+ 0x0801f800, 0x0201f800, 0x0002077d, 0x0401f047,
+ 0x598c000f, 0x82001c80, 0x000000c8, 0x0402100f,
+ 0x80000000, 0x4803180f, 0x59c400a4, 0x82000500,
+ 0x0000000f, 0x82000580, 0x00000002, 0x04020004,
+ 0x42000000, 0x00200000, 0x0401fbf7, 0x0201f800,
+ 0x0010604d, 0x0401f035, 0x4933c857, 0x0201f800,
+ 0x00106e21, 0x813261c0, 0x04000030, 0x4a026203,
+ 0x00000001, 0x42027000, 0x00000027, 0x0201f800,
+ 0x000207a1, 0x0401f029, 0x8c081508, 0x04000027,
+ 0x417a3000, 0x0201f800, 0x001070d8, 0x42032000,
+ 0x0000bf32, 0x0201f800, 0x00106062, 0x59926004,
+ 0x813261c0, 0x04000012, 0x42001800, 0x000000c8,
+ 0x0201f800, 0x001070a4, 0x0402000d, 0x59c400a4,
+ 0x82000500, 0x0000000f, 0x82000580, 0x00000002,
+ 0x04020004, 0x42000000, 0x00200000, 0x0401fbce,
+ 0x0201f800, 0x00106052, 0x0401f00c, 0x4933c857,
+ 0x0201f800, 0x00106dc3, 0x813261c0, 0x04000007,
+ 0x42027000, 0x0000004f, 0x4a026203, 0x00000003,
+ 0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800,
+ 0x5c03a000, 0x5c032000, 0x0201f000, 0x00106c4b,
+ 0x4803c857, 0x59a80821, 0x48035021, 0x80041580,
+ 0x04000045, 0x800409c0, 0x04000023, 0x497b504c,
+ 0x42000000, 0x0010b80d, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x0010aaf9, 0x42001000, 0x00008011,
+ 0x59c40001, 0x82000500, 0x00018000, 0x82001d80,
+ 0x00000000, 0x04000009, 0x82001d80, 0x00008000,
+ 0x04000009, 0x82001d80, 0x00010000, 0x04000009,
+ 0x0201f800, 0x001005d8, 0x42001800, 0x00000000,
+ 0x0401f006, 0x42001800, 0x00000001, 0x0401f003,
+ 0x42001800, 0x00000003, 0x0201f800, 0x00103a3e,
+ 0x0401f021, 0x59a8084c, 0x800409c0, 0x04020007,
+ 0x59c4000d, 0x8c000520, 0x04000004, 0x42001800,
+ 0x00000003, 0x0401f002, 0x40041800, 0x0201f800,
+ 0x0010aadd, 0x42001000, 0x00008012, 0x0201f800,
+ 0x00103a3e, 0x0201f800, 0x001006d4, 0x0201f800,
+ 0x0010ab33, 0x0402000c, 0x0401f853, 0x4d400000,
+ 0x4d3c0000, 0x42028000, 0x00000028, 0x42027800,
+ 0x00000408, 0x0201f800, 0x00101fe5, 0x5c027800,
+ 0x5c028000, 0x1c01f000, 0x4803c857, 0x82000400,
+ 0x0010210e, 0x50000800, 0x82040d00, 0x000000ff,
+ 0x1c01f000, 0x4803c856, 0x4c580000, 0x4200b000,
+ 0x00000010, 0x497b88ac, 0x497b88ad, 0x8058b040,
+ 0x040207fe, 0x5c00b000, 0x1c01f000, 0x4807c857,
+ 0x48075010, 0x80041108, 0x4200b000, 0x00000010,
+ 0x497b88ac, 0x80000580, 0x800811c0, 0x04020006,
+ 0x82040500, 0x0000000f, 0x82000400, 0x0010ab38,
+ 0x50000000, 0x480388ad, 0x80081040, 0x8058b040,
+ 0x040207f5, 0x1c01f000, 0x59a80005, 0x04000003,
+ 0x84000546, 0x0401f002, 0x84000506, 0x48035005,
+ 0x4803c857, 0x1c01f000, 0x4803c857, 0x4c080000,
+ 0x4c040000, 0x4c000000, 0x59c40892, 0x4807c857,
+ 0x80041580, 0x04000010, 0x80041480, 0x04021007,
+ 0x80081080, 0x80081000, 0x4008b000, 0x42000000,
+ 0x00000201, 0x0401f004, 0x4008b000, 0x42000000,
+ 0x00000210, 0x48038886, 0x8058b040, 0x040207fe,
+ 0x497b8886, 0x5c000000, 0x5c000800, 0x5c001000,
+ 0x1c01f000, 0x4803c856, 0x0201f800, 0x00103b25,
+ 0x04000005, 0x42028000, 0x0000002e, 0x0201f000,
+ 0x0010a449, 0x1c01f000, 0x42000800, 0x00000002,
+ 0x59a80005, 0x8c000514, 0x0402000b, 0x59c80835,
+ 0x82040d00, 0x00001f00, 0x80040910, 0x80040800,
+ 0x59a8006c, 0x80000540, 0x04000003, 0x42000800,
+ 0x0000025a, 0x4807c857, 0x1c01f000, 0x4c000000,
+ 0x59a80053, 0x4803c857, 0x82000580, 0x00000000,
+ 0x5c000000, 0x1c01f000, 0x4c000000, 0x59a80053,
+ 0x4803c857, 0x82000580, 0x00000001, 0x5c000000,
+ 0x1c01f000, 0x4c000000, 0x59a80053, 0x4803c857,
+ 0x82000580, 0x00000003, 0x5c000000, 0x1c01f000,
+ 0x4c000000, 0x59a80053, 0x82000580, 0x00000002,
+ 0x5c000000, 0x1c01f000, 0x4c000000, 0x4c040000,
+ 0x4c080000, 0x4c380000, 0x59a80040, 0x82000c80,
+ 0x00000007, 0x02021800, 0x001005d8, 0x0c01f806,
+ 0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000,
+ 0x1c01f000, 0x0010166c, 0x0010167f, 0x00101693,
+ 0x00101695, 0x001016bc, 0x001016be, 0x001016c0,
+ 0x4803c856, 0x4a035042, 0x00000000, 0x42000000,
+ 0x00000002, 0x0401fa1b, 0x42000000, 0x00000002,
+ 0x0401f9ad, 0x0401fab2, 0x4803c856, 0x4a035040,
+ 0x00000006, 0x42000800, 0x0000001e, 0x42001000,
+ 0x001016c1, 0x0201f000, 0x0010606e, 0x497b5045,
+ 0x4a035050, 0x00000036, 0x4a03504f, 0x0000002a,
+ 0x4803c856, 0x4a035042, 0x00000001, 0x42000000,
+ 0x00000002, 0x0401f998, 0x4803c856, 0x4a035040,
+ 0x00000006, 0x42000800, 0x0000001e, 0x42001000,
+ 0x001016c1, 0x0201f000, 0x0010606e, 0x0201f800,
+ 0x001005d8, 0x4a035050, 0x00000036, 0x4803c856,
+ 0x4a035042, 0x00000003, 0x42000800, 0x00000000,
+ 0x0401faa3, 0x82040d00, 0x00000090, 0x82040580,
+ 0x00000090, 0x04000009, 0x82040580, 0x00000010,
+ 0x04000009, 0x82040580, 0x00000000, 0x04000008,
+ 0x0201f800, 0x001005d8, 0x42000000, 0x00000001,
+ 0x0401f005, 0x41780000, 0x0401f003, 0x42000000,
+ 0x00000002, 0x0401f970, 0x497b5046, 0x4803c856,
+ 0x4a035040, 0x00000006, 0x42000800, 0x0000001e,
+ 0x42001000, 0x001016c1, 0x0201f000, 0x0010606e,
+ 0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8,
+ 0x1c01f000, 0x4c000000, 0x4c040000, 0x4c080000,
+ 0x4c380000, 0x59a80042, 0x82000c80, 0x00000007,
+ 0x02021800, 0x001005d8, 0x0c01f806, 0x5c007000,
+ 0x5c001000, 0x5c000800, 0x5c000000, 0x1c01f000,
+ 0x001016d7, 0x001016f6, 0x0010174a, 0x00101761,
+ 0x00101778, 0x00101781, 0x00101783, 0x0401f9fc,
+ 0x0402001b, 0x59a81048, 0x42000800, 0x00000000,
+ 0x0401fa63, 0x82040d00, 0x00000090, 0x82040580,
+ 0x00000090, 0x04000009, 0x82040580, 0x00000010,
+ 0x04000008, 0x82040580, 0x00000000, 0x04000007,
+ 0x0201f800, 0x001005d8, 0x84081540, 0x0401f004,
+ 0x84081542, 0x0401f002, 0x84081544, 0x480b5048,
+ 0x4a035040, 0x00000001, 0x0401f003, 0x0401f8cb,
+ 0x0401ff82, 0x1c01f000, 0x0401f88f, 0x04000052,
+ 0x0401f9db, 0x0402002a, 0x42000800, 0x00000000,
+ 0x0401fa43, 0x82040d00, 0x00000090, 0x82040580,
+ 0x00000000, 0x04000044, 0x82040580, 0x00000010,
+ 0x04000006, 0x82040580, 0x00000090, 0x04000009,
+ 0x0201f800, 0x001005d8, 0x59c40801, 0x82040d00,
+ 0x00018000, 0x82040580, 0x00000000, 0x04000036,
+ 0x42000800, 0x00000000, 0x0401fa2d, 0x82040d00,
+ 0x00000090, 0x82040580, 0x00000010, 0x04000006,
+ 0x82040580, 0x00000090, 0x04000006, 0x02020800,
+ 0x001005d8, 0x59a80048, 0x84000542, 0x0401f003,
+ 0x59a80048, 0x84000540, 0x48035048, 0x59a80045,
+ 0x80000000, 0x48035045, 0x82000580, 0x00000005,
+ 0x04000003, 0x0401f861, 0x0401f01e, 0x497b5045,
+ 0x59c40801, 0x82040d00, 0x00018000, 0x82040580,
+ 0x00000000, 0x04000009, 0x82040580, 0x00008000,
+ 0x04000009, 0x82040580, 0x00010000, 0x04000008,
+ 0x0201f800, 0x001005d8, 0x42000000, 0x00000001,
+ 0x0401f005, 0x41780000, 0x0401f003, 0x42000000,
+ 0x00000002, 0x0401f94b, 0x4a035042, 0x00000002,
+ 0x0401f004, 0x4a035040, 0x00000003, 0x0401f002,
+ 0x0401ff42, 0x1c01f000, 0x0401f83b, 0x04000015,
+ 0x59a8004f, 0x80000040, 0x4803504f, 0x0401f984,
+ 0x04020005, 0x4a035040, 0x00000003, 0x497b5041,
+ 0x0401f00c, 0x59a8004f, 0x80000540, 0x04020003,
+ 0x0401f89e, 0x0401f002, 0x0401f84b, 0x0401f82f,
+ 0x497b5045, 0x4a035042, 0x00000001, 0x0401ff2b,
+ 0x1c01f000, 0x0401f824, 0x04000015, 0x0401f970,
+ 0x0402000f, 0x59a80046, 0x80000000, 0x48035046,
+ 0x82000580, 0x00000007, 0x0402000c, 0x4a035052,
+ 0x0000000a, 0x497b5049, 0x59a80048, 0x8400055e,
+ 0x48035048, 0x4803c857, 0x0401f005, 0x0401f817,
+ 0x4a035042, 0x00000004, 0x0401ff3d, 0x1c01f000,
+ 0x0401f80d, 0x04000007, 0x0401f959, 0x04020003,
+ 0x0401ff1b, 0x0401f003, 0x0401f80c, 0x0401ff34,
+ 0x1c01f000, 0x0201f800, 0x001005d8, 0x0201f800,
+ 0x001005d8, 0x59a80050, 0x80000040, 0x48035050,
+ 0x0400088d, 0x1c01f000, 0x4c040000, 0x42000800,
+ 0x00000000, 0x0401f9b2, 0x82040d00, 0x00000090,
+ 0x82040580, 0x00000090, 0x04000009, 0x82040580,
+ 0x00000010, 0x04000009, 0x82040580, 0x00000000,
+ 0x04000009, 0x0201f800, 0x001005d8, 0x42000000,
+ 0x00000002, 0x0401f005, 0x42000000, 0x00000001,
+ 0x0401f002, 0x41780000, 0x0401f8ea, 0x5c000800,
+ 0x1c01f000, 0x4c040000, 0x59c40801, 0x82040d00,
+ 0x00018000, 0x82040580, 0x00000000, 0x04000009,
+ 0x82040580, 0x00008000, 0x04000009, 0x82040580,
+ 0x00010000, 0x04000009, 0x0201f800, 0x001005d8,
+ 0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+ 0x00000001, 0x0401f002, 0x41780000, 0x0401f866,
+ 0x5c000800, 0x1c01f000, 0x4c040000, 0x59a80045,
+ 0x80000000, 0x48035045, 0x82000580, 0x00000005,
+ 0x04020018, 0x497b5045, 0x59c40801, 0x82040d00,
+ 0x00018000, 0x82040580, 0x00000000, 0x04000009,
+ 0x82040580, 0x00008000, 0x04000009, 0x82040580,
+ 0x00010000, 0x04000009, 0x0201f800, 0x001005d8,
+ 0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+ 0x00000001, 0x0401f002, 0x41780000, 0x0401f846,
+ 0x42000800, 0x00000000, 0x0401f961, 0x82040d00,
+ 0x00000090, 0x82040580, 0x00000090, 0x04000009,
+ 0x82040580, 0x00000010, 0x04000009, 0x82040580,
+ 0x00000000, 0x04000009, 0x0201f800, 0x001005d8,
+ 0x42000000, 0x00000002, 0x0401f005, 0x42000000,
+ 0x00000001, 0x0401f002, 0x41780000, 0x0401f899,
+ 0x5c000800, 0x1c01f000, 0x4c200000, 0x59a80048,
+ 0x82000500, 0x00007fff, 0x02000800, 0x001005d8,
+ 0x59a84047, 0x80204102, 0x02001800, 0x001005d8,
+ 0x48235047, 0x80204500, 0x040007fa, 0x8c000504,
+ 0x04020007, 0x8c000502, 0x04020008, 0x8c000500,
+ 0x04020008, 0x0201f800, 0x001005d8, 0x42000000,
+ 0x00000002, 0x0401f005, 0x41780000, 0x0401f003,
+ 0x42000000, 0x00000001, 0x0401f80f, 0x5c004000,
+ 0x1c01f000, 0x04011000, 0x4a03c840, 0x0010b440,
+ 0x4a03c842, 0x00000009, 0x40000000, 0x040117ff,
+ 0x4a035047, 0x00000004, 0x4a03503e, 0x00000000,
+ 0x1c01f000, 0x59a80858, 0x82040d80, 0x01391077,
+ 0x04020008, 0x59e00813, 0x8c040d00, 0x04000005,
+ 0x82000d80, 0x00000002, 0x04020002, 0x41780000,
+ 0x4c000000, 0x0401f9b1, 0x5c000000, 0x800001c0,
+ 0x04000040, 0x82000d80, 0x00000001, 0x0402001d,
+ 0x42000800, 0x000000a0, 0x0401f909, 0x82040540,
+ 0x00000004, 0x42000800, 0x000000a0, 0x0401f909,
+ 0x42000800, 0x000000c0, 0x0401f901, 0x82040540,
+ 0x00000020, 0x42000800, 0x000000c0, 0x0401f901,
+ 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+ 0x00000000, 0x48038801, 0x59a80054, 0x80000110,
+ 0x42000800, 0x000000e0, 0x0401f8f6, 0x0401f03c,
+ 0x82000d80, 0x00000002, 0x02020800, 0x001005d8,
+ 0x42000800, 0x000000a0, 0x0401f8e9, 0x82040500,
+ 0xfffffffb, 0x42000800, 0x000000a0, 0x0401f8e9,
+ 0x42000800, 0x000000c0, 0x0401f8e1, 0x82040500,
+ 0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8e1,
+ 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+ 0x00010000, 0x48038801, 0x59a80056, 0x80000110,
+ 0x42000800, 0x000000e0, 0x0401f8d6, 0x0401f01c,
+ 0x42000800, 0x000000a0, 0x0401f8cd, 0x82040540,
+ 0x00000004, 0x42000800, 0x000000a0, 0x0401f8cd,
+ 0x42000800, 0x000000c0, 0x0401f8c5, 0x82040500,
+ 0xffffffdf, 0x42000800, 0x000000c0, 0x0401f8c5,
+ 0x59c40001, 0x82000500, 0xfffe7fff, 0x82000540,
+ 0x00008000, 0x48038801, 0x59a80055, 0x80000110,
+ 0x42000800, 0x000000e0, 0x0401f8ba, 0x0401f163,
+ 0x4803c857, 0x59a80858, 0x82040d80, 0x01391077,
+ 0x04020008, 0x59e00813, 0x8c040d00, 0x04000005,
+ 0x82000d80, 0x00000002, 0x04020002, 0x41780000,
+ 0x4c000000, 0x0401f94d, 0x5c000000, 0x800001c0,
+ 0x04000026, 0x82000d80, 0x00000001, 0x04020010,
+ 0x59a8006c, 0x80000540, 0x04000004, 0x42001000,
+ 0x00000000, 0x0401fa0a, 0x42000800, 0x00000000,
+ 0x0401f897, 0x82040540, 0x00000090, 0x42000800,
+ 0x00000000, 0x0401f897, 0x0401f024, 0x82000d80,
+ 0x00000002, 0x02020800, 0x001005d8, 0x59a8006c,
+ 0x80000540, 0x04000004, 0x42001000, 0x00010000,
+ 0x0401f9f7, 0x42000800, 0x00000000, 0x0401f884,
+ 0x82040500, 0xffffff6f, 0x42000800, 0x00000000,
+ 0x0401f884, 0x0401f011, 0x59a8006c, 0x80000540,
+ 0x04000004, 0x42001000, 0x00008000, 0x0401f9e8,
+ 0x42000800, 0x00000000, 0x0401f875, 0x82040500,
+ 0xffffff6f, 0x82000540, 0x00000010, 0x42000800,
+ 0x00000000, 0x0401f873, 0x0401f124, 0x4c580000,
+ 0x4200b000, 0x00000014, 0x8058b040, 0x04000043,
+ 0x59c4000d, 0x8c000520, 0x040207fc, 0x0401f85c,
+ 0x59c4000d, 0x8c000520, 0x040207f8, 0x59c40808,
+ 0x84040d50, 0x48078808, 0x4200b000, 0x000000c8,
+ 0x8058b040, 0x040207ff, 0x4200b000, 0x00000014,
+ 0x8058b040, 0x04000031, 0x59c4000d, 0x8c000520,
+ 0x0402002e, 0x42000800, 0x00001000, 0x50040800,
+ 0x82040c80, 0x24220001, 0x04020003, 0x8c000504,
+ 0x040007f4, 0x0401f842, 0x59c4000d, 0x8c000520,
+ 0x04020022, 0x42000800, 0x00001000, 0x50040800,
+ 0x82040c80, 0x24220001, 0x04020003, 0x8c000504,
+ 0x040007e8, 0x4200b000, 0x0000000a, 0x8058b040,
+ 0x04000003, 0x0401f832, 0x0401f7fd, 0x4200b000,
+ 0x00000064, 0x59c4000d, 0x8c00051e, 0x0400000f,
+ 0x8058b040, 0x040207fc, 0x42000000, 0x00001000,
+ 0x50000000, 0x82000480, 0x24220001, 0x04020004,
+ 0x59c40808, 0x84040d10, 0x48078808, 0x80000580,
+ 0x4803c857, 0x0401f00c, 0x42000000, 0x00001000,
+ 0x50000000, 0x82000480, 0x24220001, 0x04020004,
+ 0x59c40808, 0x84040d10, 0x48078808, 0x82000540,
+ 0x00000001, 0x5c00b000, 0x1c01f000, 0x42000800,
+ 0x000000a0, 0x0401f816, 0x82040500, 0xfffffffe,
+ 0x42000800, 0x000000a0, 0x0401f816, 0x42000800,
+ 0x00000000, 0x0401f80e, 0x82040500, 0xfffffffe,
+ 0x42000800, 0x00000000, 0x0401f00e, 0x40000000,
+ 0x40000000, 0x40000000, 0x40000000, 0x40000000,
+ 0x1c01f000, 0x480b8805, 0x1c01f000, 0x4807880e,
+ 0x59c4080f, 0x82040d00, 0x000000ff, 0x1c01f000,
+ 0x900001c0, 0x80040d40, 0x84040d40, 0x4807880e,
+ 0x1c01f000, 0x82000d80, 0x00200000, 0x04000009,
+ 0x82000d80, 0x02000000, 0x04000006, 0x82000d80,
+ 0x01000000, 0x04000006, 0x59c408a3, 0x0401f006,
+ 0x59c408a3, 0x84040d30, 0x0401f003, 0x59c408a3,
+ 0x84040d32, 0x80040540, 0x480388a3, 0x480788a3,
+ 0x1c01f000, 0x59c400a3, 0x84000556, 0x480388a3,
+ 0x84000516, 0x480388a3, 0x1c01f000, 0x485fc857,
+ 0x4863c857, 0x4c640000, 0x4d3c0000, 0x4d400000,
+ 0x0201f800, 0x00106ede, 0x4863500a, 0x0201f800,
+ 0x0010ab33, 0x0402006c, 0x82600d00, 0x0000ff00,
+ 0x800409c0, 0x0400000c, 0x4200c800, 0x00000001,
+ 0x59a80010, 0x82000500, 0x000000ff, 0x80041110,
+ 0x80081580, 0x04000021, 0x82041580, 0x0000ff00,
+ 0x0400000a, 0x59c410a3, 0x82081500, 0x00008000,
+ 0x04000009, 0x59c410a7, 0x82081500, 0x0000ff00,
+ 0x82081580, 0x0000ff00, 0x4200c800, 0x00000000,
+ 0x04000012, 0x59a80005, 0x8c000502, 0x04020008,
+ 0x8c000500, 0x0402000d, 0x599c1017, 0x8c08151a,
+ 0x0400003e, 0x84000542, 0x48035005, 0x4200c800,
+ 0x00000002, 0x42028000, 0x00000004, 0x42027800,
+ 0x00000008, 0x0401f008, 0x59a80805, 0x84040d40,
+ 0x48075005, 0x42028000, 0x00000004, 0x42027800,
+ 0x00000400, 0x59a80006, 0x8c000502, 0x04020006,
+ 0x59a80805, 0x8c040d0a, 0x04020033, 0x84040d4a,
+ 0x48075005, 0x42000000, 0x0010b812, 0x0201f800,
+ 0x0010aa47, 0x59a8180a, 0x42001000, 0x00008013,
+ 0x0201f800, 0x00103a3e, 0x0201f800, 0x00103b25,
+ 0x04000015, 0x4d400000, 0x82600500, 0x000000ff,
+ 0x42028800, 0x0000ffff, 0x40643000, 0x42028000,
+ 0x0000000e, 0x0201f800, 0x0010a446, 0x42000800,
+ 0x00000001, 0x42001000, 0x00000100, 0x0201f800,
+ 0x0010618b, 0x5c028000, 0x599c0817, 0x8c040d0a,
+ 0x04020011, 0x493fc857, 0x4943c857, 0x0201f800,
+ 0x00101fe5, 0x0401f00c, 0x0201f800, 0x00103b25,
+ 0x04000009, 0x42028000, 0x0000000f, 0x42028800,
+ 0x0000ffff, 0x42003000, 0x00000000, 0x0201f800,
+ 0x0010a449, 0x497b8880, 0x5c028000, 0x5c027800,
+ 0x5c00c800, 0x1c01f000, 0x42000800, 0x000000a0,
+ 0x0401ff5f, 0x82040540, 0x00000002, 0x42000800,
+ 0x000000a0, 0x0401f75f, 0x42000800, 0x00000000,
+ 0x0401ff57, 0x82040540, 0x00000002, 0x42000800,
+ 0x00000000, 0x0401f757, 0x42000800, 0x000000a0,
+ 0x0401ff4f, 0x82040500, 0xfffffffd, 0x42000800,
+ 0x000000a0, 0x0401f74f, 0x42000800, 0x00000000,
+ 0x0401ff47, 0x82040500, 0xfffffffd, 0x42000800,
+ 0x00000000, 0x0401f747, 0x59c408a8, 0x0401ff38,
+ 0x0401ff37, 0x59c400a8, 0x80040d80, 0x040207fb,
+ 0x1c01f000, 0x4803c856, 0x4a038807, 0x00000001,
+ 0x497b8807, 0x59c40005, 0x48038805, 0x497b506c,
+ 0x497b506d, 0x41785800, 0x42006000, 0x00000001,
+ 0x42006800, 0x00000003, 0x0401f824, 0x0401f82f,
+ 0x40400000, 0x4803c857, 0x82408580, 0x00000000,
+ 0x0402001d, 0x41785800, 0x42006000, 0x0000001e,
+ 0x42006800, 0x00000014, 0x0401f818, 0x0401f823,
+ 0x40400000, 0x4803c857, 0x82408580, 0x00000800,
+ 0x04020011, 0x42005800, 0x00000001, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000014, 0x0401f80b,
+ 0x0401f816, 0x40400000, 0x4803c857, 0x82408580,
+ 0x0000ffff, 0x04020004, 0x4a03506c, 0x00000001,
+ 0x4803c856, 0x1c01f000, 0x41785000, 0x0401f812,
+ 0x0401f838, 0x40347000, 0x40340800, 0x0401f03d,
+ 0x42005000, 0x00000001, 0x0401f80b, 0x0401f831,
+ 0x40340800, 0x0401f037, 0x42005000, 0x00000002,
+ 0x0401f805, 0x0401f81d, 0x0401f835, 0x40048000,
+ 0x1c01f000, 0x0401f808, 0x0401f814, 0x40280800,
+ 0x0401f826, 0x402c0800, 0x0401f827, 0x40300800,
+ 0x0401f025, 0x42000800, 0x0000ffff, 0x42001000,
+ 0x00000001, 0x0401f829, 0x42001000, 0x00000010,
+ 0x0401f826, 0x42000800, 0x0000ffff, 0x42001000,
+ 0x00000010, 0x0401f021, 0x41780800, 0x42001000,
+ 0x00000002, 0x0401f01d, 0x0401f92e, 0x4a03d000,
+ 0x00050004, 0x0401f92b, 0x4a03d000, 0x00050005,
+ 0x0401f928, 0x4a03d000, 0x00050004, 0x42000800,
+ 0x00000001, 0x42001000, 0x00000001, 0x0401f00f,
+ 0x42000800, 0x00000002, 0x42001000, 0x00000002,
+ 0x0401f00a, 0x42001000, 0x00000005, 0x0401f007,
+ 0x42001000, 0x00000010, 0x0401f004, 0x42001000,
+ 0x00000010, 0x0401f01b, 0x0401f912, 0x82082c00,
+ 0x0010ab38, 0x50142800, 0x82081500, 0xffffffff,
+ 0x04000013, 0x0401f90b, 0x80081040, 0x80142902,
+ 0x40040000, 0x80140500, 0x04000007, 0x4a03d000,
+ 0x00070006, 0x0401f903, 0x4a03d000, 0x00070007,
+ 0x0401f006, 0x4a03d000, 0x00070004, 0x0401f8fd,
+ 0x4a03d000, 0x00070005, 0x0401f7ec, 0x1c01f000,
+ 0x41780800, 0x82082c00, 0x0010ab38, 0x50142800,
+ 0x82081500, 0xffffffff, 0x04000010, 0x0401f8f1,
+ 0x4a03d000, 0x00050001, 0x0401f8ee, 0x59e81800,
+ 0x80081040, 0x80142902, 0x8c0c1d06, 0x04000004,
+ 0x40140000, 0x80040d40, 0x0401f8e6, 0x4a03d000,
+ 0x00070000, 0x0401f7ef, 0x1c01f000, 0x480bc857,
+ 0x480b506d, 0x59c40001, 0x82000500, 0xffffefff,
+ 0x48038801, 0x41781800, 0x0401f8c4, 0x41785800,
+ 0x42006000, 0x0000001e, 0x42006800, 0x00000004,
+ 0x0401ff7a, 0x42006800, 0x0000003c, 0x0401ff7d,
+ 0x41785800, 0x42006000, 0x0000001e, 0x42006800,
+ 0x00000004, 0x0401ff71, 0x41786800, 0x0401ff75,
+ 0x41785800, 0x42006000, 0x0000001e, 0x41786800,
+ 0x0401ff6a, 0x42006800, 0x00000002, 0x0401ff6d,
+ 0x42006800, 0x00000001, 0x0401ff64, 0x42006800,
+ 0x000000f5, 0x0401ff67, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000004, 0x0401ff5b,
+ 0x42006800, 0x00000020, 0x0401ff5e, 0x59a8106d,
+ 0x0401f865, 0x42001800, 0x000200f5, 0x0401f897,
+ 0x59a8106d, 0x0401f879, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000004, 0x0401ff4b,
+ 0x41786800, 0x0401ff4f, 0x59c40001, 0x82000540,
+ 0x00001000, 0x48038801, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000015, 0x0401ff3f,
+ 0x0401ff4a, 0x40400000, 0x82000540, 0x00000002,
+ 0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+ 0x42006800, 0x00000015, 0x0401ff34, 0x5c000000,
+ 0x40006800, 0x0401ff37, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000015, 0x0401ff2b,
+ 0x0401ff36, 0x40400000, 0x82000500, 0x0000fffd,
+ 0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+ 0x42006800, 0x00000015, 0x0401ff20, 0x5c000000,
+ 0x40006800, 0x0401ff23, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000014, 0x0401ff17,
+ 0x0401ff22, 0x40400000, 0x82000540, 0x00000040,
+ 0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+ 0x42006800, 0x00000014, 0x0401ff0c, 0x5c000000,
+ 0x40006800, 0x0401ff0f, 0x41785800, 0x42006000,
+ 0x0000001e, 0x42006800, 0x00000014, 0x0401ff03,
+ 0x0401ff0e, 0x40400000, 0x82000500, 0x0000ffbf,
+ 0x4c000000, 0x41785800, 0x42006000, 0x0000001e,
+ 0x42006800, 0x00000014, 0x0401fef8, 0x5c000000,
+ 0x40006800, 0x0401fefb, 0x4a038886, 0x00002020,
+ 0x0401f04c, 0x480bc857, 0x82080580, 0x00010000,
+ 0x04020007, 0x82040d40, 0x00010000, 0x42001800,
+ 0x00000001, 0x0401f82d, 0x0401f00f, 0x82080580,
+ 0x00008000, 0x04000007, 0x82040d40, 0x00000000,
+ 0x42001800, 0x00900001, 0x0401f824, 0x0401f006,
+ 0x82040d40, 0x00008000, 0x42001800, 0x00100001,
+ 0x0401f81e, 0x1c01f000, 0x480bc857, 0x82080580,
+ 0x00010000, 0x04020008, 0x42001800, 0x000000a1,
+ 0x0401f816, 0x42001800, 0x000000c1, 0x0401f813,
+ 0x0401f011, 0x82080580, 0x00008000, 0x04000008,
+ 0x42001800, 0x000400a1, 0x0401f80c, 0x42001800,
+ 0x002000c1, 0x0401f809, 0x0401f007, 0x42001800,
+ 0x000400a1, 0x0401f805, 0x42001800, 0x000000c1,
+ 0x0401f802, 0x1c01f000, 0x480fc857, 0x41785800,
+ 0x42006000, 0x0000001e, 0x41786800, 0x0401feb7,
+ 0x400c6800, 0x80346960, 0x0401feba, 0x42006800,
+ 0x00000001, 0x0401feb1, 0x400c6800, 0x0401feb5,
+ 0x42006800, 0x00000003, 0x0401feac, 0x0401feb7,
+ 0x40400000, 0x8c000504, 0x040207fc, 0x1c01f000,
+ 0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+ 0x1c01f000, 0x00020103, 0x00101bd5, 0x00101bdb,
+ 0x00101be1, 0x00101be9, 0x00101bef, 0x00101bf7,
+ 0x00101bff, 0x00101c09, 0x00101c0f, 0x00101c17,
+ 0x00101c1f, 0x00101c29, 0x00101c31, 0x00101c3b,
+ 0x00101c45, 0x000200f8, 0x00101c51, 0x00101c59,
+ 0x00101c61, 0x00101c6b, 0x00101c73, 0x00101c7d,
+ 0x00101c87, 0x00101c93, 0x00101c9b, 0x00101ca5,
+ 0x00101caf, 0x00101cbb, 0x00101cc5, 0x00101cd1,
+ 0x00101cdd, 0x000200fd, 0x00101ceb, 0x00101cf3,
+ 0x00101cfb, 0x00101d05, 0x00101d0d, 0x00101d17,
+ 0x00101d21, 0x00101d2d, 0x00101d35, 0x00101d3f,
+ 0x00101d49, 0x00101d55, 0x00101d5f, 0x00101d6b,
+ 0x00101d77, 0x00101d85, 0x00101d8d, 0x00101d97,
+ 0x00101da1, 0x00101dad, 0x00101db7, 0x00101dc3,
+ 0x00101dcf, 0x00101ddd, 0x00101de7, 0x00101df3,
+ 0x00101dff, 0x00101e0d, 0x00101e19, 0x00101e27,
+ 0x00101e35, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00101418, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020729, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020015, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020015, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020015, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101155, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f800,
+ 0x00020104, 0x0201f000, 0x00020101, 0x4c000000,
+ 0x4df00000, 0x0201f800, 0x00101155, 0x0201f800,
+ 0x00101418, 0x0201f800, 0x00020729, 0x0201f800,
+ 0x00020015, 0x0201f800, 0x00101289, 0x0201f000,
+ 0x00020101, 0x4c000000, 0x4df00000, 0x0201f800,
+ 0x00101155, 0x0201f800, 0x00101418, 0x0201f800,
+ 0x00020729, 0x0201f800, 0x00020015, 0x0201f800,
+ 0x00101289, 0x0201f800, 0x00020104, 0x0201f000,
+ 0x00020101, 0x4c5c0000, 0x4c600000, 0x4178b800,
+ 0x0201f800, 0x001048ec, 0x040200fd, 0x59a8c026,
+ 0x0201f800, 0x0010513b, 0x04000003, 0x8c60c506,
+ 0x0400000e, 0x8c60c500, 0x04020004, 0x8c60c50e,
+ 0x040008f6, 0x0401f0f2, 0x0401fab4, 0x040200f0,
+ 0x0201f800, 0x0010513b, 0x04020004, 0x4a03501c,
+ 0x0000ffff, 0x0401f0ea, 0x8c60c504, 0x04000004,
+ 0x4a03501c, 0x0000ffff, 0x0401f0e5, 0x59a8c010,
+ 0x8260c500, 0x000000ff, 0x59a81013, 0x8c081500,
+ 0x0400005d, 0x8c081502, 0x0402005b, 0x59a8b81c,
+ 0x825c0d80, 0x0000ffff, 0x04020003, 0x4200b800,
+ 0x00000001, 0x805c1104, 0x82086400, 0x0010be21,
+ 0x50300800, 0x825c0500, 0x00000003, 0x0c01f001,
+ 0x00101e81, 0x00101e7c, 0x00101e80, 0x00101e7e,
+ 0x80040910, 0x0401f004, 0x80040930, 0x0401f002,
+ 0x80040920, 0x82040500, 0x000000ff, 0x82000d80,
+ 0x000000ff, 0x0400000f, 0x4c000000, 0x82000400,
+ 0x0010210e, 0x50000800, 0x80040910, 0x82040580,
+ 0x00000080, 0x5c000000, 0x04000030, 0x80600d80,
+ 0x0400002e, 0x80000540, 0x0400002c, 0x0401f00b,
+ 0x59a81005, 0x82081500, 0x00000003, 0x0402002b,
+ 0x59a81013, 0x84081542, 0x480b5013, 0x4a03501c,
+ 0x0000ffff, 0x0401f028, 0x4c000000, 0x59a80005,
+ 0x8c000514, 0x42001000, 0x00000010, 0x02020800,
+ 0x00104c6d, 0x5c000000, 0x0402001c, 0x417a8800,
+ 0x0201f800, 0x00105c9a, 0x04020016, 0x0201f800,
+ 0x001045e5, 0x04000006, 0x0201f800, 0x00104c62,
+ 0x0401f8b1, 0x0400000f, 0x0401f00c, 0x599c0019,
+ 0x8c00050e, 0x04020009, 0x0201f800, 0x001045a6,
+ 0x04020008, 0x0201f800, 0x00104c62, 0x0401f9e1,
+ 0x0401f8be, 0x04000003, 0x805cb800, 0x0401f7b2,
+ 0x485f501c, 0x0401f086, 0x4a03501c, 0x0000ffff,
+ 0x0401f083, 0x42003000, 0x0000007e, 0x59a8001c,
+ 0x82001580, 0x0000ffff, 0x04020005, 0x80000d80,
+ 0x4018b000, 0x4803c856, 0x0401f009, 0x8018b480,
+ 0x04001004, 0x40000800, 0x4803c856, 0x0401f004,
+ 0x4a03501c, 0x0000ffff, 0x0401f071, 0x4c040000,
+ 0x4c580000, 0x82040400, 0x0010210e, 0x50000000,
+ 0x82000500, 0x000000ff, 0x80604580, 0x0400005c,
+ 0x0201f800, 0x00105c9b, 0x04020061, 0x59a80005,
+ 0x8c000514, 0x42001000, 0x00000010, 0x02020800,
+ 0x00104c6d, 0x5c00b000, 0x5c000800, 0x040207d7,
+ 0x4c040000, 0x4c580000, 0x845cbd00, 0x0201f800,
+ 0x00020245, 0x04000008, 0x599c0019, 0x8c00050e,
+ 0x04020047, 0x0201f800, 0x001045ab, 0x0402004c,
+ 0x0401f002, 0x845cbd40, 0x0201f800, 0x00104c62,
+ 0x0201f800, 0x001049e7, 0x04020007, 0x59a80005,
+ 0x8c000502, 0x04000033, 0x59340200, 0x8c00050e,
+ 0x04020030, 0x59a81013, 0x8c081502, 0x04000025,
+ 0x0201f800, 0x00104a09, 0x04000031, 0x8c5cbd00,
+ 0x04020004, 0x0201f800, 0x001045ff, 0x0401f02c,
+ 0x0401f9cd, 0x0400002a, 0x42026000, 0x0010bde9,
+ 0x49366009, 0x497a6008, 0x417a7800, 0x0401f925,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00103b25, 0x0400001d, 0x41782800,
+ 0x42003000, 0x00000008, 0x4d400000, 0x4d440000,
+ 0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+ 0x0010a446, 0x5c028800, 0x5c028000, 0x0401f010,
+ 0x4937c857, 0x599c0019, 0x8c00050e, 0x0402000c,
+ 0x0401f96c, 0x0401f849, 0x04000011, 0x0401f008,
+ 0x59a80013, 0x8c000500, 0x04000003, 0x0401f9a6,
+ 0x04000003, 0x0401f828, 0x04000009, 0x5c00b000,
+ 0x5c000800, 0x80040800, 0x8058b040, 0x04020798,
+ 0x4a03501c, 0x0000ffff, 0x0401f005, 0x4937c857,
+ 0x5c00b000, 0x5c000800, 0x4807501c, 0x5c00c000,
+ 0x5c00b800, 0x1c01f000, 0x4803c856, 0x4a03501c,
+ 0x00000001, 0x42028800, 0x000007fe, 0x42003000,
+ 0x00fffffe, 0x0201f800, 0x001045a6, 0x0402000c,
+ 0x0401f948, 0x0401f825, 0x04000009, 0x59a80026,
+ 0x8400054e, 0x48035026, 0x0201f800, 0x0010930f,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x80000580,
+ 0x0401f7fe, 0x4937c857, 0x0201f800, 0x00107942,
+ 0x04000015, 0x49366009, 0x4a026406, 0x00000001,
+ 0x417a7800, 0x0201f800, 0x00104567, 0x59a8001b,
+ 0x80000000, 0x4803501b, 0x42027000, 0x00000004,
+ 0x599c0019, 0x8c00050e, 0x04000003, 0x42027000,
+ 0x00000000, 0x0201f800, 0x000207a1, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4937c857, 0x0201f800,
+ 0x00107942, 0x0400001c, 0x49366009, 0x59340403,
+ 0x82000580, 0x000007fe, 0x04000005, 0x4d3c0000,
+ 0x417a7800, 0x0401f8b7, 0x5c027800, 0x4a026406,
+ 0x00000001, 0x417a7800, 0x0201f800, 0x00104567,
+ 0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+ 0x59a8001b, 0x80000000, 0x4803501b, 0x42027000,
+ 0x00000002, 0x0201f800, 0x000207a1, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4803c856, 0x42028800,
+ 0x000007fc, 0x42003000, 0x00fffffc, 0x0201f800,
+ 0x001045a6, 0x04020005, 0x0401f805, 0x04000003,
+ 0x4a035027, 0x0000ffff, 0x1c01f000, 0x4937c857,
+ 0x0201f800, 0x00107942, 0x04000014, 0x49366009,
+ 0x4a026406, 0x00000001, 0x417a7800, 0x0201f800,
+ 0x00104567, 0x42000800, 0x00000003, 0x0201f800,
+ 0x00104571, 0x59a80028, 0x80000000, 0x48035028,
+ 0x42027000, 0x00000002, 0x0201f800, 0x000207a1,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x480bc857,
+ 0x492fc857, 0x4c5c0000, 0x4008b800, 0x42028800,
+ 0x000007fd, 0x42003000, 0x00fffffd, 0x0201f800,
+ 0x001045a6, 0x0402001a, 0x0201f800, 0x0002075a,
+ 0x04000017, 0x49366009, 0x5934000a, 0x84000544,
+ 0x4802680a, 0x812e59c0, 0x04000005, 0x592c0404,
+ 0x8c00051e, 0x04000002, 0x48ee6021, 0x492e6008,
+ 0x4a026406, 0x00000001, 0x485e601c, 0x42027000,
+ 0x00000022, 0x0201f800, 0x000207a1, 0x82000540,
+ 0x00000001, 0x5c00b800, 0x1c01f000, 0x80000580,
+ 0x0401f7fd, 0x5c000000, 0x4c000000, 0x4803c857,
+ 0x4943c857, 0x493fc857, 0x4d340000, 0x4d440000,
+ 0x4c580000, 0x4d2c0000, 0x4c5c0000, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x0201f800, 0x001069f1,
+ 0x0201f800, 0x00106aac, 0x0201f800, 0x00106737,
+ 0x0201f800, 0x0010848a, 0x5c03e000, 0x02000800,
+ 0x00106c4b, 0x4200b000, 0x000007f0, 0x417a8800,
+ 0x0201f800, 0x00020245, 0x0402001f, 0x8d3e7d14,
+ 0x04000005, 0x59340212, 0x82000500, 0x0000ff00,
+ 0x04000019, 0x8d3e7d06, 0x04000004, 0x59340200,
+ 0x8c00050e, 0x04020014, 0x8d3e7d18, 0x0400000f,
+ 0x5934b80f, 0x805cb9c0, 0x04000009, 0x49425a06,
+ 0x592cb800, 0x0201f800, 0x000202ce, 0x805cb9c0,
+ 0x040207fb, 0x497a680f, 0x497a6810, 0x4a026c00,
+ 0x00000707, 0x0401f004, 0x4937c857, 0x0201f800,
+ 0x001042b4, 0x81468800, 0x8058b040, 0x040207dd,
+ 0x8d3e7d02, 0x04000011, 0x497b501d, 0x42028800,
+ 0x000007f0, 0x4200b000, 0x00000010, 0x0201f800,
+ 0x00020245, 0x04020006, 0x4937c857, 0x4a026c00,
+ 0x00000707, 0x0201f800, 0x001042b4, 0x81468800,
+ 0x8058b040, 0x040207f6, 0x5c00b800, 0x5c025800,
+ 0x5c00b000, 0x5c028800, 0x5c026800, 0x1c01f000,
+ 0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857,
+ 0x493fc857, 0x4d340000, 0x4d400000, 0x4d440000,
+ 0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x59326809, 0x813669c0, 0x04000020,
+ 0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+ 0x00106a50, 0x0201f800, 0x00106ab4, 0x0201f800,
+ 0x001067fd, 0x0201f800, 0x0010a2ff, 0x4937c857,
+ 0x8d3e7d18, 0x04000010, 0x5934b80f, 0x805cb9c0,
+ 0x0400000a, 0x405e5800, 0x49425a06, 0x592cb800,
+ 0x0201f800, 0x000202ce, 0x805cb9c0, 0x040207fa,
+ 0x497a680f, 0x497a6810, 0x4a026c00, 0x00000707,
+ 0x0401f003, 0x0201f800, 0x001042b4, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x5c00b800, 0x5c025800,
+ 0x5c028800, 0x5c028000, 0x5c026800, 0x1c01f000,
+ 0x4933c857, 0x59a80026, 0x8c000508, 0x04020012,
+ 0x59305009, 0x482bc857, 0x836c0580, 0x00000002,
+ 0x0402000d, 0x0401f813, 0x0402000b, 0x58280403,
+ 0x82000580, 0x000007fc, 0x04000008, 0x59a8001b,
+ 0x80000040, 0x4803c857, 0x02001800, 0x001005d8,
+ 0x4803501b, 0x1c01f000, 0x59a80028, 0x80000040,
+ 0x4803c857, 0x040017fc, 0x48035028, 0x1c01f000,
+ 0x59300008, 0x800001c0, 0x04020009, 0x59300403,
+ 0x82000580, 0x00000001, 0x04020004, 0x82000540,
+ 0x00000001, 0x0401f002, 0x80000580, 0x1c01f000,
+ 0x4937c857, 0x59340200, 0x84000502, 0x48026a00,
+ 0x1c01f000, 0x4933c857, 0x493fc857, 0x4947c857,
+ 0x4d3c0000, 0x4d400000, 0x4d340000, 0x4d440000,
+ 0x4c580000, 0x0201f800, 0x00106c55, 0x4df00000,
+ 0x813e79c0, 0x04020004, 0x4200b000, 0x00000001,
+ 0x0401f004, 0x4200b000, 0x000007f0, 0x417a8800,
+ 0x41440000, 0x81ac0400, 0x50000000, 0x80026d40,
+ 0x04000019, 0x42027800, 0x00000001, 0x0201f800,
+ 0x001048f6, 0x42028000, 0x00000029, 0x417a7800,
+ 0x0201f800, 0x00106a50, 0x0201f800, 0x00106ab4,
+ 0x0201f800, 0x001067fd, 0x0201f800, 0x001049e7,
+ 0x04020005, 0x4937c857, 0x4a026c00, 0x00000404,
+ 0x0401f003, 0x0201f800, 0x00104a14, 0x0201f800,
+ 0x0010a2ff, 0x81468800, 0x8058b040, 0x040207e1,
+ 0x5c03e000, 0x02000800, 0x00106c4b, 0x5c00b000,
+ 0x5c028800, 0x5c026800, 0x5c028000, 0x5c027800,
+ 0x1c01f000, 0x4937c857, 0x4947c857, 0x4c5c0000,
+ 0x4c600000, 0x4c640000, 0x59a80013, 0x8c000500,
+ 0x0400001f, 0x599c0017, 0x8c00050a, 0x0402001c,
+ 0x5934ba02, 0x825cbd00, 0x000000ff, 0x485fc857,
+ 0x4178c000, 0x4178c800, 0x82600400, 0x0010be21,
+ 0x50002000, 0x8060c1c0, 0x04000008, 0x82100500,
+ 0x000000ff, 0x82002d80, 0x000000ff, 0x0400000c,
+ 0x805c0580, 0x0400000d, 0x80102110, 0x8064c800,
+ 0x82640580, 0x00000004, 0x040207f5, 0x8060c000,
+ 0x82600580, 0x00000020, 0x040207eb, 0x4813c857,
+ 0x82000540, 0x00000001, 0x5c00c800, 0x5c00c000,
+ 0x5c00b800, 0x1c01f000, 0x59a80026, 0x4803c857,
+ 0x8c000512, 0x1c01f000, 0x00007eef, 0x00007de8,
+ 0x00007ce4, 0x000080e2, 0x00007be1, 0x000080e0,
+ 0x000080dc, 0x000080da, 0x00007ad9, 0x000080d6,
+ 0x000080d5, 0x000080d4, 0x000080d3, 0x000080d2,
+ 0x000080d1, 0x000079ce, 0x000078cd, 0x000080cc,
+ 0x000080cb, 0x000080ca, 0x000080c9, 0x000080c7,
+ 0x000080c6, 0x000077c5, 0x000076c3, 0x000080bc,
+ 0x000080ba, 0x000075b9, 0x000080b6, 0x000074b5,
+ 0x000073b4, 0x000072b3, 0x000080b2, 0x000080b1,
+ 0x000080ae, 0x000071ad, 0x000080ac, 0x000070ab,
+ 0x00006faa, 0x00006ea9, 0x000080a7, 0x00006da6,
+ 0x00006ca5, 0x00006ba3, 0x00006a9f, 0x0000699e,
+ 0x0000689d, 0x0000809b, 0x00008098, 0x00006797,
+ 0x00006690, 0x0000658f, 0x00006488, 0x00006384,
+ 0x00006282, 0x00008081, 0x00008080, 0x0000617c,
+ 0x0000607a, 0x00008079, 0x00005f76, 0x00008075,
+ 0x00008074, 0x00008073, 0x00008072, 0x00008071,
+ 0x0000806e, 0x00005e6d, 0x0000806c, 0x00005d6b,
+ 0x00005c6a, 0x00005b69, 0x00008067, 0x00005a66,
+ 0x00005965, 0x00005863, 0x0000575c, 0x0000565a,
+ 0x00005559, 0x00008056, 0x00008055, 0x00005454,
+ 0x00005353, 0x00005252, 0x00005151, 0x0000504e,
+ 0x00004f4d, 0x0000804c, 0x0000804b, 0x00004e4a,
+ 0x00004d49, 0x00008047, 0x00004c46, 0x00008045,
+ 0x00008043, 0x0000803c, 0x0000803a, 0x00008039,
+ 0x00008036, 0x00004b35, 0x00008034, 0x00004a33,
+ 0x00004932, 0x00004831, 0x0000802e, 0x0000472d,
+ 0x0000462c, 0x0000452b, 0x0000442a, 0x00004329,
+ 0x00004227, 0x00008026, 0x00008025, 0x00004123,
+ 0x0000401f, 0x00003f1e, 0x00003e1d, 0x00003d1b,
+ 0x00003c18, 0x00008017, 0x00008010, 0x00003b0f,
+ 0x00003a08, 0x00008004, 0x00003902, 0x00008001,
+ 0x00008000, 0x00008000, 0x00003800, 0x00003700,
+ 0x00003600, 0x00008000, 0x00003500, 0x00008000,
+ 0x00008000, 0x00008000, 0x00003400, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00003300, 0x00003200, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00003100, 0x00003000, 0x00008000,
+ 0x00008000, 0x00002f00, 0x00008000, 0x00002e00,
+ 0x00002d00, 0x00002c00, 0x00008000, 0x00008000,
+ 0x00008000, 0x00002b00, 0x00008000, 0x00002a00,
+ 0x00002900, 0x00002800, 0x00008000, 0x00002700,
+ 0x00002600, 0x00002500, 0x00002400, 0x00002300,
+ 0x00002200, 0x00008000, 0x00008000, 0x00002100,
+ 0x00002000, 0x00001f00, 0x00001e00, 0x00001d00,
+ 0x00001c00, 0x00008000, 0x00008000, 0x00001b00,
+ 0x00001a00, 0x00008000, 0x00001900, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00001800, 0x00008000, 0x00001700,
+ 0x00001600, 0x00001500, 0x00008000, 0x00001400,
+ 0x00001300, 0x00001200, 0x00001100, 0x00001000,
+ 0x00000f00, 0x00008000, 0x00008000, 0x00000e00,
+ 0x00000d00, 0x00000c00, 0x00000b00, 0x00000a00,
+ 0x00000900, 0x00008000, 0x00008000, 0x00000800,
+ 0x00000700, 0x00008000, 0x00000600, 0x00008000,
+ 0x00008000, 0x00008000, 0x00000500, 0x00000400,
+ 0x00000300, 0x00008000, 0x00000200, 0x00008000,
+ 0x00008000, 0x00008000, 0x00000100, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00000000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00008000, 0x00008000, 0x00008000,
+ 0x00008000, 0x00008000, 0x0201f800, 0x001007d3,
+ 0x02000800, 0x001005d8, 0x492f4016, 0x1c01f000,
+ 0x83a0ac00, 0x00000006, 0x83a00580, 0x0010b4a4,
+ 0x0400000c, 0x492fc857, 0x812e59c0, 0x02000800,
+ 0x001005d8, 0x832ca400, 0x00000006, 0x4200b000,
+ 0x0000000d, 0x0201f800, 0x0010ab17, 0x0401f00f,
+ 0x4200b000, 0x00000010, 0x83e0a400, 0x00000020,
+ 0x50500000, 0x8050a000, 0x50500800, 0x900409c0,
+ 0x80040540, 0x4400a800, 0x8050a000, 0x8054a800,
+ 0x8058b040, 0x040207f7, 0x1c01f000, 0x59a00206,
+ 0x4803c857, 0x82000c80, 0x0000007f, 0x040210c9,
+ 0x59a80821, 0x0c01f001, 0x001022c0, 0x00102300,
+ 0x00102300, 0x0010234b, 0x0010236d, 0x00102300,
+ 0x001022c0, 0x0010238f, 0x001023a0, 0x00102300,
+ 0x00102300, 0x001023ad, 0x001023c5, 0x001023dd,
+ 0x00102300, 0x001023e7, 0x001023f4, 0x00102300,
+ 0x0010241d, 0x00102300, 0x0010247a, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102491, 0x00102300,
+ 0x001024e3, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x001024e8, 0x00102560, 0x00102300,
+ 0x00102567, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102569, 0x001025ea,
+ 0x00102727, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102736, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102753, 0x001027a6,
+ 0x00102802, 0x00102816, 0x00102835, 0x00102a70,
+ 0x00102dff, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00102300,
+ 0x00102300, 0x00102fb4, 0x00103028, 0x00102300,
+ 0x00102300, 0x00103094, 0x00102300, 0x00103126,
+ 0x001031d8, 0x00102300, 0x00102300, 0x0010320f,
+ 0x0010326b, 0x00102300, 0x001032bd, 0x00103419,
+ 0x00102300, 0x0010342d, 0x001034b8, 0x00102300,
+ 0x00102300, 0x00102300, 0x00102300, 0x00103522,
+ 0x00103526, 0x00103545, 0x00102300, 0x001035e7,
+ 0x00102300, 0x00102300, 0x00103615, 0x00102300,
+ 0x00103643, 0x00102300, 0x00102300, 0x001036aa,
+ 0x001037b7, 0x00103814, 0x00102300, 0x0010387a,
+ 0x00102300, 0x00102300, 0x001038d3, 0x00103936,
+ 0x00102300, 0x48efc857, 0x4031d800, 0x58ef400b,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x04000045,
+ 0x48efc857, 0x4a034206, 0x00004000, 0x0201f800,
+ 0x00103a15, 0x83a00580, 0x0010b4a4, 0x0400000d,
+ 0x58ee580a, 0x4d2c0000, 0x0401f856, 0x41a25800,
+ 0x0201f800, 0x001007f4, 0x40ee5800, 0x0201f800,
+ 0x001007f4, 0x5c025800, 0x0201f000, 0x000202da,
+ 0x04026007, 0x59a0001d, 0x84000542, 0x4803401d,
+ 0x4a01d809, 0x001022d4, 0x1c01f000, 0x59a00206,
+ 0x82000d80, 0x00004000, 0x04000006, 0x900001c0,
+ 0x82000540, 0x00000011, 0x4803c011, 0x0401f005,
+ 0x900001c0, 0x82000540, 0x00000010, 0x4803c011,
+ 0x0401f845, 0x59e00017, 0x8c000508, 0x0402000c,
+ 0x4203e000, 0x30000001, 0x4203e000, 0x40000000,
+ 0x40ee5800, 0x0201f800, 0x001007f4, 0x59a0001d,
+ 0x84000504, 0x4803401d, 0x1c01f000, 0x4a03c017,
+ 0x00000000, 0x59a00206, 0x82000d80, 0x00004000,
+ 0x040007f0, 0x4a03c017, 0x00000001, 0x0401f7ed,
+ 0x4803c856, 0x4a034206, 0x00004001, 0x0401f7c0,
+ 0x4803c856, 0x4a034206, 0x00004002, 0x0401f7bc,
+ 0x4803c856, 0x4a034206, 0x00004003, 0x0401f7b8,
+ 0x4803c856, 0x4a034206, 0x00004005, 0x0401f7b4,
+ 0x4803c856, 0x4a034206, 0x00004006, 0x0401f7b0,
+ 0x4803c856, 0x4a034206, 0x0000400b, 0x0401f7ac,
+ 0x4803c856, 0x4a034206, 0x0000400c, 0x0401f7a8,
+ 0x4803c856, 0x4a034206, 0x0000400c, 0x0401f7a4,
+ 0x48efc857, 0x58eca80a, 0x8054a9c0, 0x02000800,
+ 0x001005d8, 0x83a0a400, 0x00000006, 0x8254ac00,
+ 0x00000006, 0x4200b000, 0x0000000d, 0x0201f000,
+ 0x0010ab17, 0x59a00206, 0x4803c857, 0x59a00406,
+ 0x4803c857, 0x59a00207, 0x4803c857, 0x59a00407,
+ 0x4803c857, 0x59a00208, 0x4803c857, 0x59a00408,
+ 0x4803c857, 0x59a00209, 0x4803c857, 0x83e0ac00,
+ 0x00000020, 0x83a0a400, 0x00000006, 0x4200b000,
+ 0x00000010, 0x50500000, 0x4400a800, 0x8054a800,
+ 0x900001c0, 0x4400a800, 0x8054a800, 0x8050a000,
+ 0x8058b040, 0x040207f8, 0x1c01f000, 0x59a00406,
+ 0x800000c2, 0x59a00a07, 0x900409c0, 0x80040540,
+ 0x84000540, 0x59a00c07, 0x8c040d00, 0x04000018,
+ 0x59a80805, 0x8c040d0e, 0x040207ba, 0x42000800,
+ 0x00000064, 0x80040840, 0x04000007, 0x4a030000,
+ 0x00000001, 0x40000000, 0x59801000, 0x8c081500,
+ 0x040007f9, 0x04000005, 0x48030004, 0x4a030000,
+ 0x00000000, 0x0401f75b, 0x4a030000, 0x00000000,
+ 0x4a034406, 0x00000004, 0x040007a2, 0x4803880e,
+ 0x0401f754, 0x59a00406, 0x800000c2, 0x59a00c07,
+ 0x8c040d00, 0x0400001a, 0x59a80805, 0x8c040d0e,
+ 0x0402079c, 0x42000800, 0x00000064, 0x80040840,
+ 0x04000007, 0x4a030000, 0x00000001, 0x40000000,
+ 0x59801000, 0x8c081500, 0x040007f9, 0x04000007,
+ 0x48030004, 0x59800805, 0x48074406, 0x4a030000,
+ 0x00000000, 0x0401f73b, 0x4a030000, 0x00000000,
+ 0x4a034406, 0x00000004, 0x04000782, 0x4803880e,
+ 0x59c4080f, 0x48074406, 0x0401f732, 0x59a01c06,
+ 0x59a00207, 0x900c19c0, 0x800c1d40, 0x580c0803,
+ 0x80000580, 0x500c1000, 0x80080400, 0x800c1800,
+ 0x80040840, 0x040207fc, 0x48034406, 0x900001c0,
+ 0x48034207, 0x800001c0, 0x04000722, 0x0401f769,
+ 0x4a034406, 0x00000004, 0x4a034207, 0x00000000,
+ 0x4a034407, 0x00000010, 0x59a8000d, 0x48034208,
+ 0x900001c0, 0x48034408, 0x4a034209, 0x00000002,
+ 0x0401f714, 0x59a00407, 0x59a01207, 0x900811c0,
+ 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+ 0x800c1d40, 0x59a00a08, 0x59a00408, 0x900409c0,
+ 0x80040d40, 0x59a0020a, 0x82002480, 0x00000010,
+ 0x04001754, 0x59a02406, 0x900001c0, 0x80100540,
+ 0x59a8280d, 0x80142480, 0x0400174e, 0x0201f000,
+ 0x00103a25, 0x59a00407, 0x59a01207, 0x900811c0,
+ 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+ 0x800c1d40, 0x59a00a08, 0x59a00408, 0x900409c0,
+ 0x80040d40, 0x59a0020a, 0x82002480, 0x00000010,
+ 0x0400173c, 0x59a02406, 0x900001c0, 0x80100540,
+ 0x59a8280d, 0x80142480, 0x04001736, 0x0201f000,
+ 0x00103a28, 0x59a00a0a, 0x59a00406, 0x900409c0,
+ 0x80040d40, 0x59a01407, 0x59a00207, 0x900811c0,
+ 0x80081540, 0x44080800, 0x0401f6da, 0x59a00a0a,
+ 0x59a00406, 0x900409c0, 0x80040d40, 0x50040000,
+ 0x82000d00, 0x0000ffff, 0x48074207, 0x82000d00,
+ 0xffff0000, 0x900409c0, 0x48074407, 0x0401f6cd,
+ 0x59a00406, 0x8c000500, 0x04000020, 0x59a01207,
+ 0x59a01c07, 0x59a02208, 0x480b5054, 0x480f5055,
+ 0x48135056, 0x59c40801, 0x82040d00, 0x00018000,
+ 0x82040580, 0x00000000, 0x04000009, 0x82040580,
+ 0x00008000, 0x04000008, 0x82040580, 0x00010000,
+ 0x04000007, 0x0201f800, 0x001005d8, 0x40080000,
+ 0x0401f004, 0x400c0000, 0x0401f002, 0x40100000,
+ 0x80000110, 0x42000800, 0x000000e0, 0x0201f800,
+ 0x00101944, 0x0401f007, 0x59a81054, 0x59a81855,
+ 0x59a82056, 0x480b4207, 0x480f4407, 0x48134208,
+ 0x0401f6a4, 0x4d2c0000, 0x4d340000, 0x4d300000,
+ 0x4d440000, 0x59a28c06, 0x0201f800, 0x00020245,
+ 0x04000006, 0x5c028800, 0x5c026000, 0x5c026800,
+ 0x5c025800, 0x0401f6e7, 0x59a04407, 0x59a00207,
+ 0x900001c0, 0x80204540, 0x0401f81e, 0x04000009,
+ 0x4a034208, 0x00000001, 0x4a034406, 0x0000ffff,
+ 0x4a034207, 0x0000ffff, 0x497b4407, 0x0401f00b,
+ 0x0401f822, 0x0400000e, 0x4a034208, 0x00000002,
+ 0x59300402, 0x48034406, 0x59300202, 0x48034207,
+ 0x59300206, 0x48034407, 0x5c028800, 0x5c026000,
+ 0x5c026800, 0x5c025800, 0x0401f67a, 0x5c028800,
+ 0x5c026000, 0x5c026800, 0x5c025800, 0x0401f6c1,
+ 0x4937c856, 0x4823c856, 0x4d2c0000, 0x5934000f,
+ 0x80025d40, 0x04000007, 0x592c0005, 0x80200580,
+ 0x592c0000, 0x040207fb, 0x82000540, 0x00000001,
+ 0x5c025800, 0x1c01f000, 0x4823c857, 0x4d2c0000,
+ 0x4d300000, 0x42026000, 0x0010d1c0, 0x59300406,
+ 0x82000d80, 0x00000003, 0x04000004, 0x82000d80,
+ 0x00000006, 0x04020007, 0x59325808, 0x812e59c0,
+ 0x04000004, 0x592c0005, 0x80200580, 0x0400000a,
+ 0x83326400, 0x00000024, 0x41580000, 0x81300480,
+ 0x040017ef, 0x80000580, 0x5c026000, 0x5c025800,
+ 0x1c01f000, 0x82000540, 0x00000001, 0x5c026000,
+ 0x5c025800, 0x1c01f000, 0x83a00580, 0x0010b4a4,
+ 0x04020684, 0x59a80005, 0x8c00050e, 0x04020003,
+ 0x4a030000, 0x00000000, 0x4a034206, 0x00004000,
+ 0x4a03c011, 0x40000010, 0x0401fea7, 0x59e00017,
+ 0x8c000508, 0x04000003, 0x4a03c017, 0x00000000,
+ 0x4203e000, 0x30000001, 0x4203e000, 0x40000000,
+ 0x0401f000, 0x800409c0, 0x04000004, 0x4a034406,
+ 0x00000001, 0x0401f677, 0x836c0580, 0x00000003,
+ 0x04020010, 0x59a80010, 0x497b4406, 0x0201f800,
+ 0x0010513b, 0x0400000f, 0x82000d00, 0x00ffff00,
+ 0x0402000c, 0x82000c00, 0x0010210e, 0x50040800,
+ 0x80040910, 0x82041580, 0x00000080, 0x04020004,
+ 0x4a034406, 0x00000007, 0x0401f662, 0x48074406,
+ 0x82000d00, 0x0000ffff, 0x48074207, 0x80000120,
+ 0x48034407, 0x59a80026, 0x82001500, 0x00000100,
+ 0x480b4409, 0x8c000502, 0x0400001f, 0x8c000506,
+ 0x04000009, 0x82000d00, 0x0000000a, 0x82040d80,
+ 0x0000000a, 0x04020004, 0x4a034209, 0x00000001,
+ 0x0401f022, 0x8c00050a, 0x04000009, 0x82000d00,
+ 0x00000022, 0x82040d80, 0x00000022, 0x04020004,
+ 0x4a034209, 0x00000003, 0x0401f018, 0x8c000508,
+ 0x04000009, 0x82000d00, 0x00000012, 0x82040d80,
+ 0x00000012, 0x04020004, 0x4a034209, 0x00000002,
+ 0x0401f00e, 0x0201f800, 0x0010513b, 0x04020004,
+ 0x4a034209, 0x00000004, 0x0401f5e6, 0x8c000506,
+ 0x04000004, 0x4a034406, 0x00000005, 0x0401f62d,
+ 0x4a034209, 0x00000000, 0x0401f5de, 0x59a80037,
+ 0x48034407, 0x59a80038, 0x48034209, 0x0401f5d9,
+ 0x42007800, 0x0010b8ec, 0x59a00406, 0x4803c857,
+ 0x82000c80, 0x00000006, 0x04021622, 0x0c01f001,
+ 0x001024f6, 0x001024f7, 0x00102505, 0x00102518,
+ 0x00102539, 0x001024f6, 0x0401f61a, 0x836c0580,
+ 0x00000000, 0x04000613, 0x59a00a07, 0x59a00407,
+ 0x900001c0, 0x80040d40, 0x4807c857, 0x59a00a08,
+ 0x59a00408, 0x900001c0, 0x80040d40, 0x4807c857,
+ 0x0401f056, 0x836c0580, 0x00000000, 0x04000605,
+ 0x59a00407, 0x59a01207, 0x900001c0, 0x80081540,
+ 0x59a00408, 0x59a01a08, 0x900001c0, 0x800c1d40,
+ 0x42000000, 0x0010c1bf, 0x480fc857, 0x480bc857,
+ 0x42000800, 0x00001000, 0x0201f000, 0x00103a28,
+ 0x59a00a07, 0x59a00407, 0x900001c0, 0x80041d40,
+ 0x820c0c80, 0x0010ab4a, 0x040215f2, 0x820c0c80,
+ 0x00100000, 0x040015ef, 0x480fc857, 0x823c7c00,
+ 0x00000009, 0x503c0800, 0x800409c0, 0x04000006,
+ 0x823c0580, 0x0000000d, 0x040005e6, 0x803c7800,
+ 0x0401f7f9, 0x59e41001, 0x82080d00, 0xfffeffcf,
+ 0x4807c801, 0x440c7800, 0x46001800, 0x0201f800,
+ 0x800c1800, 0x46001800, 0x001005cb, 0x480bc801,
+ 0x0401f022, 0x59a01a07, 0x59a00407, 0x900001c0,
+ 0x800c1d40, 0x480c7801, 0x59a02208, 0x59a00408,
+ 0x900001c0, 0x80102540, 0x48107802, 0x59a00209,
+ 0x80000040, 0x040015cb, 0x48007806, 0x80000000,
+ 0x48007805, 0x42000800, 0x00004000, 0x40001000,
+ 0x0201f800, 0x00106681, 0x80000540, 0x04000003,
+ 0x49787801, 0x0401f5bf, 0x40040000, 0x800c1c00,
+ 0x040015bc, 0x480c7803, 0x48107804, 0x49787808,
+ 0x59a00409, 0x48007807, 0x59e40001, 0x4803c857,
+ 0x82000540, 0x00040000, 0x4803c801, 0x0401f561,
+ 0x59a80006, 0x48034406, 0x59a80007, 0x48034207,
+ 0x59a80008, 0x48034407, 0x0401f55a, 0x0201f800,
+ 0x001005d8, 0x4803c856, 0x4a03c013, 0x03800300,
+ 0x4a03c014, 0x03800380, 0x59a00c06, 0x82040580,
+ 0x000000a0, 0x04000004, 0x82040580, 0x000000a2,
+ 0x0402002b, 0x59a0140a, 0x82080480, 0x00000100,
+ 0x04021027, 0x59a0020b, 0x8c000500, 0x0402002e,
+ 0x59a00a0a, 0x800409c0, 0x04000021, 0x82040480,
+ 0x00000041, 0x0402101e, 0x82040c00, 0x00000003,
+ 0x82040d00, 0x000000fc, 0x80040904, 0x59a00407,
+ 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+ 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x0201f800,
+ 0x00103a00, 0x04020006, 0x4a034406, 0x00000002,
+ 0x4a03c014, 0x03800000, 0x0401f576, 0x832e5c00,
+ 0x00000004, 0x412c0000, 0x0201f800, 0x00103a25,
+ 0x4a01d809, 0x001025a2, 0x1c01f000, 0x4a03c014,
+ 0x03800000, 0x0401f56f, 0x4031d800, 0x58ef400b,
+ 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x0400055c, 0x59a00c06, 0x59a0140a, 0x59a0020b,
+ 0x8c000500, 0x04020031, 0x832e5c00, 0x00000004,
+ 0x41783800, 0x59a04a0a, 0x401c0000, 0x812c0400,
+ 0x50004000, 0x82201d00, 0x000000ff, 0x4c040000,
+ 0x0401f8ac, 0x5c000800, 0x0400002d, 0x80244840,
+ 0x04000028, 0x80081000, 0x82201d00, 0x0000ff00,
+ 0x800c1910, 0x4c040000, 0x0401f8a2, 0x5c000800,
+ 0x04000023, 0x80244840, 0x0400001e, 0x80081000,
+ 0x82201d00, 0x00ff0000, 0x800c1920, 0x4c040000,
+ 0x0401f898, 0x5c000800, 0x04000019, 0x80244840,
+ 0x04000014, 0x80081000, 0x82201d00, 0xff000000,
+ 0x800c1930, 0x4c040000, 0x0401f88e, 0x5c000800,
+ 0x0400000f, 0x80244840, 0x0400000a, 0x80081000,
+ 0x801c3800, 0x0401f7d5, 0x59a0020a, 0x82000500,
+ 0x000000ff, 0x40001800, 0x0401f882, 0x04000004,
+ 0x4a03c014, 0x03800000, 0x0401f4da, 0x4a03c014,
+ 0x03800000, 0x0401f523, 0x4803c856, 0x4a03c013,
+ 0x03800300, 0x4a03c014, 0x03800380, 0x59a00c06,
+ 0x82040580, 0x000000a0, 0x04000004, 0x82040580,
+ 0x000000a2, 0x0402006c, 0x59a0140a, 0x82080480,
+ 0x00000100, 0x04021068, 0x59a0020b, 0x8c000500,
+ 0x0402005c, 0x59a01a0a, 0x800c19c0, 0x04000062,
+ 0x820c0480, 0x00000041, 0x0402105f, 0x0201f800,
+ 0x00103a00, 0x04020006, 0x4a034406, 0x00000002,
+ 0x4a03c014, 0x03800000, 0x0401f502, 0x832e5c00,
+ 0x00000004, 0x41783800, 0x59a04a0a, 0x401c0000,
+ 0x812c0400, 0x40004000, 0x4c040000, 0x4c080000,
+ 0x0401f874, 0x5c001000, 0x5c000800, 0x04000047,
+ 0x44144000, 0x80244840, 0x0400002b, 0x80081000,
+ 0x4c040000, 0x4c080000, 0x0401f86a, 0x5c001000,
+ 0x5c000800, 0x0400003d, 0x50200000, 0x801428d0,
+ 0x80140540, 0x44004000, 0x80244840, 0x0400001e,
+ 0x80081000, 0x4c040000, 0x4c080000, 0x0401f85d,
+ 0x5c001000, 0x5c000800, 0x04000030, 0x50200000,
+ 0x801428e0, 0x80140540, 0x44004000, 0x80244840,
+ 0x04000011, 0x80081000, 0x4c040000, 0x4c080000,
+ 0x0401f850, 0x5c001000, 0x5c000800, 0x04000023,
+ 0x50200000, 0x801428f0, 0x80140540, 0x44004000,
+ 0x80244840, 0x04000004, 0x80081000, 0x801c3800,
+ 0x0401f7cb, 0x59a00a0a, 0x82040c00, 0x00000003,
+ 0x82040d00, 0x000000fc, 0x80040904, 0x59a00407,
+ 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+ 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x4a03c014,
+ 0x03800000, 0x412c0000, 0x0201f000, 0x00103a28,
+ 0x0401f830, 0x04000005, 0x48174406, 0x4a03c014,
+ 0x03800000, 0x0401f463, 0x4a03c014, 0x03800000,
+ 0x0401f4ac, 0x4a03c014, 0x03800000, 0x0401f4ad,
+ 0x0401f836, 0x04000010, 0x0401f862, 0x0402000f,
+ 0x40080800, 0x0401f85f, 0x0402000c, 0x400c0800,
+ 0x0401f85c, 0x04020009, 0x0401f84b, 0x42000000,
+ 0x00030d40, 0x80000040, 0x040207ff, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x0401f843, 0x80000580,
+ 0x0401f7fd, 0x0401f821, 0x0400000a, 0x82040d40,
+ 0x00000001, 0x0401f84b, 0x04020007, 0x0401f87e,
+ 0x0401f898, 0x0401f838, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x0401f834, 0x80000580, 0x0401f7fd,
+ 0x40041800, 0x0401f811, 0x0400000c, 0x0401f83d,
+ 0x0402000b, 0x40080800, 0x0401f83a, 0x04020008,
+ 0x400c0800, 0x0401ffe8, 0x04000004, 0x0401f826,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x0401f822,
+ 0x80000580, 0x0401f7fd, 0x4c040000, 0x42000800,
+ 0x00000064, 0x4a03c013, 0x03800300, 0x80040840,
+ 0x04000016, 0x59e00013, 0x82000500, 0x00000300,
+ 0x82000580, 0x00000300, 0x040207f7, 0x42000000,
+ 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
+ 0x01000000, 0x42000000, 0x00000064, 0x80000040,
+ 0x040207ff, 0x4a03c013, 0x02000000, 0x82000540,
+ 0x00000001, 0x0401f002, 0x80000580, 0x5c000800,
+ 0x1c01f000, 0x4a03c013, 0x01000000, 0x42000000,
+ 0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
+ 0x02000200, 0x42000000, 0x00000064, 0x80000040,
+ 0x040207ff, 0x4a03c013, 0x01000100, 0x1c01f000,
+ 0x42002000, 0x00000008, 0x82040500, 0x00000080,
+ 0x800000c2, 0x82000540, 0x01000000, 0x4803c013,
+ 0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+ 0x4a03c013, 0x02000200, 0x42000000, 0x00000064,
+ 0x80000040, 0x040207ff, 0x4a03c013, 0x02000000,
+ 0x800408c2, 0x80102040, 0x040207ec, 0x4a03c013,
+ 0x01000100, 0x42000000, 0x00000064, 0x80000040,
+ 0x040207ff, 0x4a03c013, 0x02000200, 0x42000000,
+ 0x00000064, 0x80000040, 0x040207ff, 0x59e00013,
+ 0x82000500, 0x00000100, 0x4a03c013, 0x02000000,
+ 0x4c040000, 0x42000800, 0x00000064, 0x59e00013,
+ 0x82000500, 0x00000100, 0x80040840, 0x04000003,
+ 0x80000540, 0x040207fa, 0x80000540, 0x5c000800,
+ 0x1c01f000, 0x4a03c013, 0x01000100, 0x42001000,
+ 0x00000008, 0x80000d80, 0x42000000, 0x00000064,
+ 0x80000040, 0x040207ff, 0x4a03c013, 0x02000200,
+ 0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+ 0x59e00013, 0x82000500, 0x00000100, 0x80000110,
+ 0x800408c2, 0x80040d40, 0x4a03c013, 0x02000000,
+ 0x80081040, 0x040207ed, 0x40042800, 0x1c01f000,
+ 0x4a03c013, 0x01000100, 0x42000000, 0x00000064,
+ 0x80000040, 0x040207ff, 0x4a03c013, 0x02000200,
+ 0x42000000, 0x00000064, 0x80000040, 0x040207ff,
+ 0x4a03c013, 0x02000000, 0x1c01f000, 0x59a00407,
+ 0x59a80837, 0x48035037, 0x48074407, 0x59a00a09,
+ 0x82040480, 0x00000014, 0x04021003, 0x42000800,
+ 0x000007d0, 0x59a80038, 0x48075038, 0x48034209,
+ 0x0201f000, 0x001022c0, 0x836c0580, 0x00000000,
+ 0x0400000e, 0x59a80006, 0x59a00c06, 0x80041580,
+ 0x82081500, 0x00000040, 0x02000000, 0x001022c0,
+ 0x80080580, 0x48035006, 0x0201f800, 0x00100699,
+ 0x0201f000, 0x001022c0, 0x59a00406, 0x59a80806,
+ 0x48035006, 0x80040d80, 0x8c040d0c, 0x02020800,
+ 0x00100699, 0x59a00207, 0x48035007, 0x59a00407,
+ 0x48035008, 0x0201f000, 0x001022c0, 0x800409c0,
+ 0x04000005, 0x4a034406, 0x00000001, 0x0201f000,
+ 0x0010230c, 0x0201f800, 0x0010513b, 0x04020005,
+ 0x4a034406, 0x00000016, 0x0201f000, 0x0010230c,
+ 0x836c0580, 0x00000003, 0x04000005, 0x4a034406,
+ 0x00000007, 0x0201f000, 0x0010230c, 0x59a00c06,
+ 0x82040500, 0xffffff00, 0x02020000, 0x00102310,
+ 0x82041580, 0x000000ff, 0x04020007, 0x59a80010,
+ 0x82000500, 0x000000ff, 0x82001540, 0x0000ff00,
+ 0x0401f011, 0x82040400, 0x0010210e, 0x50000000,
+ 0x80000110, 0x82000580, 0x00000080, 0x02000000,
+ 0x00102310, 0x59a80010, 0x82000500, 0x000000ff,
+ 0x80041580, 0x02000000, 0x00102310, 0x840409c0,
+ 0x80041540, 0x0201f800, 0x0002075a, 0x04020005,
+ 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+ 0x48ee6021, 0x480a621c, 0x4a02641c, 0x0000bc09,
+ 0x4a026406, 0x00000001, 0x0201f800, 0x00103a00,
+ 0x04020007, 0x0201f800, 0x0002077d, 0x4a034406,
+ 0x00000002, 0x0201f000, 0x0010230c, 0x497a5a04,
+ 0x497a5805, 0x4a025c04, 0x00008000, 0x4a01d809,
+ 0x001027f9, 0x492e6008, 0x42027000, 0x00000032,
+ 0x0201f000, 0x000207a1, 0x800409c0, 0x04000005,
+ 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+ 0x0201f800, 0x0010513b, 0x04020005, 0x4a034406,
+ 0x00000016, 0x0201f000, 0x0010230c, 0x836c0580,
+ 0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+ 0x0201f000, 0x0010230c, 0x59a00c06, 0x82040500,
+ 0xffffff00, 0x02020000, 0x00102310, 0x82041580,
+ 0x000000ff, 0x04020007, 0x59a80010, 0x82000500,
+ 0x000000ff, 0x82001540, 0x0000ff00, 0x0401f011,
+ 0x82040400, 0x0010210e, 0x50000000, 0x80000110,
+ 0x82000580, 0x00000080, 0x02000000, 0x00102310,
+ 0x59a80010, 0x82000500, 0x000000ff, 0x80041580,
+ 0x02000000, 0x00102310, 0x840409c0, 0x80041540,
+ 0x0201f800, 0x0002075a, 0x04020005, 0x4a034406,
+ 0x00000003, 0x0201f000, 0x0010230c, 0x48ee6021,
+ 0x480a621c, 0x4a02641c, 0x0000bc05, 0x4a026406,
+ 0x00000001, 0x0201f800, 0x00103a00, 0x04020007,
+ 0x0201f800, 0x0002077d, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x497a5a04, 0x497a5805,
+ 0x4a025c04, 0x00008000, 0x4a01d809, 0x001027f9,
+ 0x492e6008, 0x42027000, 0x00000032, 0x0201f000,
+ 0x000207a1, 0x592c0005, 0x82000580, 0x01000000,
+ 0x02020000, 0x001022c0, 0x4a034406, 0x00000004,
+ 0x0201f000, 0x0010230c, 0x497b4406, 0x497b4207,
+ 0x0201f800, 0x00103b25, 0x04000008, 0x59a80066,
+ 0x59a8086a, 0x80040480, 0x59a80867, 0x48074406,
+ 0x80041480, 0x480b4207, 0x49674407, 0x59a8000e,
+ 0x48034209, 0x495f4409, 0x59a80020, 0x4803420b,
+ 0x0201f000, 0x001022c0, 0x800409c0, 0x04000005,
+ 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+ 0x59a00406, 0x8c000500, 0x0402000f, 0x59a80069,
+ 0x81640480, 0x04001008, 0x59a8000b, 0x81500580,
+ 0x04000009, 0x59a8006a, 0x59a81066, 0x80080580,
+ 0x04000005, 0x4a034406, 0x00000018, 0x0201f000,
+ 0x0010230c, 0x82000540, 0x00000001, 0x0201f800,
+ 0x001015fe, 0x0201f800, 0x00103c80, 0x0201f000,
+ 0x001022c0, 0x4803c856, 0x800409c0, 0x02020000,
+ 0x00102314, 0x59a00406, 0x8c00051e, 0x04000008,
+ 0x4803c856, 0x59a0020b, 0x82000480, 0x00000800,
+ 0x04001015, 0x0201f000, 0x00102310, 0x4803c856,
+ 0x59a0020b, 0x599c0a01, 0x80040480, 0x04021003,
+ 0x0201f000, 0x00102310, 0x59a8000e, 0x81640580,
+ 0x04000009, 0x4a034406, 0x00000018, 0x0201f000,
+ 0x0010230c, 0x4a034406, 0x00000005, 0x0201f000,
+ 0x0010230c, 0x59a80026, 0x8c00050a, 0x040007fa,
+ 0x59a00406, 0x8c00051e, 0x04000036, 0x0201f800,
+ 0x0002075a, 0x040007f4, 0x0201f800, 0x00103a00,
+ 0x040007f1, 0x497a5a04, 0x59a00406, 0x4802620a,
+ 0x59a00209, 0x4802640a, 0x59a00409, 0x4802620b,
+ 0x59a0020d, 0x4802620c, 0x59a0040d, 0x4802640c,
+ 0x59a0020e, 0x4802620d, 0x59a0040e, 0x4802640d,
+ 0x59a00210, 0x4802620e, 0x59a00410, 0x4802640e,
+ 0x59a0020b, 0x82000500, 0x0000fffc, 0x80000104,
+ 0x4802640b, 0x0401f9d9, 0x040007d7, 0x48ee6021,
+ 0x58ee580d, 0x5930020e, 0x59301c0e, 0x900c19c0,
+ 0x800c1d40, 0x5930020c, 0x5930140c, 0x900811c0,
+ 0x80081540, 0x592c0a05, 0x832c0400, 0x00000006,
+ 0x0201f800, 0x00103a25, 0x4a01d809, 0x001029e5,
+ 0x4a034000, 0x00000001, 0x49334001, 0x1c01f000,
+ 0x0201f800, 0x00106c55, 0x0201f800, 0x00100ae0,
+ 0x0401f86d, 0x497b5057, 0x4201d000, 0x00002710,
+ 0x0201f800, 0x001060c6, 0x59c40880, 0x4c040000,
+ 0x59c408a3, 0x4c040000, 0x497b4002, 0x0401f876,
+ 0x0401f893, 0x4a03a005, 0x10000000, 0x0401f8b4,
+ 0x0401f901, 0x04000048, 0x59c80001, 0x800001c0,
+ 0x040007fc, 0x59c80018, 0x82000500, 0xf0000000,
+ 0x59c00808, 0x82040d00, 0x0fffffff, 0x80040540,
+ 0x48038008, 0x0201f800, 0x00100ec1, 0x59c00006,
+ 0x4a038006, 0x10000000, 0x59c00009, 0x82000d00,
+ 0x00e00000, 0x04020024, 0x4a03900d, 0x00000000,
+ 0x59c80020, 0x82000500, 0xff000000, 0x82000580,
+ 0x32000000, 0x0402001c, 0x4a03900d, 0x00000001,
+ 0x59c80020, 0x82000500, 0xff000000, 0x82000580,
+ 0xe1000000, 0x04020014, 0x4a03900d, 0x00000000,
+ 0x59c80020, 0x82000500, 0x00ffffff, 0x4a03900d,
+ 0x00000000, 0x59c80821, 0x82040d00, 0x00ffffff,
+ 0x80040580, 0x04020008, 0x59a80010, 0x80040580,
+ 0x04020005, 0x59c40005, 0x82000500, 0x000000f0,
+ 0x04000006, 0x4803c856, 0x0401f8d7, 0x4a035057,
+ 0x00000001, 0x0401f002, 0x0401f8e1, 0x42000000,
+ 0x00000064, 0x80000040, 0x02000800, 0x001005d8,
+ 0x59c00807, 0x82040d00, 0x0000000c, 0x040007fa,
+ 0x0401f003, 0x4a035057, 0x00000001, 0x0401f8da,
+ 0x0201f800, 0x00106f36, 0x0401f818, 0x4201d000,
+ 0x000186a0, 0x0201f800, 0x001060c6, 0x5c000800,
+ 0x480788a3, 0x5c000800, 0x48078880, 0x59a80057,
+ 0x800001c0, 0x02000000, 0x001022c0, 0x0201f000,
+ 0x00102318, 0x599c0201, 0x48035059, 0x41780800,
+ 0x42001000, 0x00003b10, 0x0201f800, 0x001066a0,
+ 0x480b505a, 0x1c01f000, 0x0201f800, 0x00106c4b,
+ 0x59b800ea, 0x82000500, 0x00000007, 0x82000580,
+ 0x00000003, 0x04020003, 0x4a0370e8, 0x00000001,
+ 0x1c01f000, 0x42038000, 0x00007700, 0x4a038006,
+ 0x30000000, 0x59c00007, 0x8c00050a, 0x040207fe,
+ 0x59c00006, 0x59a00209, 0x59a00c09, 0x900409c0,
+ 0x80040d40, 0x48078001, 0x59a0020e, 0x59a00c0e,
+ 0x900409c0, 0x80040d40, 0x48078000, 0x59a0020b,
+ 0x82000500, 0x0000fffc, 0x48038002, 0x48038003,
+ 0x48038005, 0x497b9009, 0x59e00003, 0x82000540,
+ 0x00008060, 0x4803c003, 0x1c01f000, 0x41780800,
+ 0x8007a0ca, 0x83d3a400, 0x00007600, 0x42000800,
+ 0x00000040, 0x0201f800, 0x00101345, 0x4a03a00a,
+ 0x00000001, 0x4a03a005, 0x20000000, 0x59d00006,
+ 0x4a03a005, 0x30000000, 0x59d00006, 0x8c00050a,
+ 0x040207fe, 0x59d00005, 0x59a00210, 0x59a00c10,
+ 0x900409c0, 0x80040d40, 0x4807a001, 0x59a0020d,
+ 0x59a00c0d, 0x900409c0, 0x80040d40, 0x4807a000,
+ 0x59a0020b, 0x82000500, 0x0000fffc, 0x4803a003,
+ 0x4803a002, 0x4803a008, 0x1c01f000, 0x59a00002,
+ 0x4803c857, 0x800001c0, 0x0402004a, 0x59a8005a,
+ 0x48038880, 0x59c400a3, 0x82000540, 0x00002008,
+ 0x8400053a, 0x480388a3, 0x59c40008, 0x8400054e,
+ 0x82000500, 0xffffffe1, 0x48038808, 0x59c80040,
+ 0x84000534, 0x48039040, 0x0401f902, 0x04020013,
+ 0x59a80010, 0x800000d0, 0x82000540, 0x00000011,
+ 0x48039120, 0x59a80010, 0x82000500, 0x00ffffff,
+ 0x82000540, 0x32000000, 0x48039121, 0x4a039123,
+ 0xe1290008, 0x59a80010, 0x82000500, 0x00ffffff,
+ 0x48039122, 0x0401f016, 0x59a80010, 0x82000500,
+ 0x000000ff, 0x900009c0, 0x840001c0, 0x80040540,
+ 0x82000540, 0x00000000, 0x48039120, 0x59a80010,
+ 0x82000500, 0x000000ff, 0x82000540, 0x01000000,
+ 0x48039121, 0x4a039123, 0x08210008, 0x59a80010,
+ 0x82000500, 0x000000ff, 0x48039122, 0x497b9124,
+ 0x59a80c5b, 0x80040800, 0x4807545b, 0x900409c0,
+ 0x82040540, 0x0000aaaa, 0x48039125, 0x497b9126,
+ 0x497b9127, 0x0401f8cf, 0x04020004, 0x4a039100,
+ 0x0000e980, 0x0401f003, 0x4a039100, 0x0000e9a0,
+ 0x1c01f000, 0x82000540, 0x00000001, 0x0402500d,
+ 0x4203e000, 0x80000000, 0x40e81000, 0x41780800,
+ 0x42000000, 0x00000064, 0x0201f800, 0x001066a0,
+ 0x59940024, 0x80080400, 0x48032824, 0x80000580,
+ 0x1c01f000, 0x4d900000, 0x4dd00000, 0x4da40000,
+ 0x4d140000, 0x417a3000, 0x0201f800, 0x001070d8,
+ 0x0201f800, 0x00106dc3, 0x5c022800, 0x5c034800,
+ 0x5c03a000, 0x5c032000, 0x1c01f000, 0x59c80007,
+ 0x8c000500, 0x04000003, 0x4a03900d, 0x00000030,
+ 0x1c01f000, 0x4a038805, 0x00020000, 0x42000800,
+ 0x0000003c, 0x0201f800, 0x00101345, 0x4a038891,
+ 0x0000ffff, 0x59c80035, 0x48039035, 0x4a03900d,
+ 0x00000040, 0x42038000, 0x00007700, 0x0201f800,
+ 0x00100ec1, 0x42038000, 0x00007720, 0x0201f800,
+ 0x00100ec1, 0x4a03a005, 0x20000000, 0x4a03a005,
+ 0x30000000, 0x59d00806, 0x8c040d0a, 0x040207fe,
+ 0x1c01f000, 0x4d300000, 0x4031d800, 0x58ef400b,
+ 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x5c026000, 0x02000000, 0x00102304, 0x4d300000,
+ 0x59a26001, 0x59a00000, 0x4000b000, 0x80000000,
+ 0x48034000, 0x592c0001, 0x80000540, 0x0400001e,
+ 0x40025800, 0x8058b040, 0x040207fb, 0x58ec1007,
+ 0x58ec1808, 0x592c0a05, 0x4d2c0000, 0x58ec000d,
+ 0x40025800, 0x592c0204, 0x5c025800, 0x82000580,
+ 0x00000103, 0x04000008, 0x832c0400, 0x00000006,
+ 0x0201f800, 0x00103a25, 0x4a01d809, 0x001029e5,
+ 0x0401f007, 0x832c0400, 0x00000006, 0x0201f800,
+ 0x00103a28, 0x4a01d809, 0x001029e5, 0x5c026000,
+ 0x1c01f000, 0x58ec000d, 0x40025800, 0x592c0204,
+ 0x82000580, 0x00000103, 0x04020006, 0x0201f800,
+ 0x0002077d, 0x5c026000, 0x0201f000, 0x001022c0,
+ 0x58ec000d, 0x40025800, 0x592c0404, 0x8400055e,
+ 0x48025c04, 0x42028800, 0x000007fd, 0x42003000,
+ 0x00fffffd, 0x0201f800, 0x001045a6, 0x04000003,
+ 0x80000580, 0x0401f004, 0x59a26001, 0x0201f800,
+ 0x0010937d, 0x5c026000, 0x02000000, 0x0010230c,
+ 0x4d300000, 0x4a01d809, 0x00102a38, 0x0401f7dc,
+ 0x592c0005, 0x82000580, 0x01000000, 0x02000000,
+ 0x00102318, 0x4d300000, 0x59a26001, 0x5930020b,
+ 0x59301c0a, 0x900001c0, 0x800c1d40, 0x5930040d,
+ 0x5930120d, 0x900001c0, 0x80081540, 0x592c0a05,
+ 0x832c0400, 0x00000006, 0x0201f800, 0x00103a28,
+ 0x4a01d809, 0x001029e5, 0x4a034000, 0x00000001,
+ 0x5c026000, 0x1c01f000, 0x4933c857, 0x4c300000,
+ 0x5930040b, 0x82000c80, 0x0000000e, 0x04001004,
+ 0x4a025a05, 0x0000000e, 0x0401f003, 0x48025a05,
+ 0x0401f00c, 0x800409c0, 0x0400000a, 0x4c040000,
+ 0x0201f800, 0x00103a00, 0x5c000800, 0x04000003,
+ 0x40040000, 0x0401f7f0, 0x80000580, 0x0401f003,
+ 0x82000540, 0x00000001, 0x5c006000, 0x1c01f000,
+ 0x59a00206, 0x82000580, 0x00000044, 0x1c01f000,
+ 0x4807c857, 0x800409c0, 0x0400000c, 0x0201f800,
+ 0x00101650, 0x04020009, 0x42000000, 0x00000002,
+ 0x0201f800, 0x0010188c, 0x42000000, 0x00000002,
+ 0x0201f800, 0x00101821, 0x59a00406, 0x82000500,
+ 0x00000007, 0x0c01f001, 0x00102a8c, 0x00102aa1,
+ 0x00102ab7, 0x00102a8a, 0x00102a8a, 0x00102a8a,
+ 0x00102a8a, 0x00102a8a, 0x0201f000, 0x00102310,
+ 0x42000800, 0x000000c0, 0x0201f800, 0x0010193f,
+ 0x82040540, 0x00000002, 0x42000800, 0x000000c0,
+ 0x0201f800, 0x00101944, 0x42000800, 0x00000000,
+ 0x0201f800, 0x0010193f, 0x82040540, 0x00000008,
+ 0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+ 0x0401f00b, 0x42000800, 0x000000c0, 0x0201f800,
+ 0x0010193f, 0x82040540, 0x00000001, 0x42000800,
+ 0x000000c0, 0x0201f800, 0x00101944, 0x59c80040,
+ 0x4c000000, 0x59a80010, 0x4c000000, 0x59c400a3,
+ 0x4c000000, 0x59c40008, 0x4c000000, 0x0401f911,
+ 0x04000021, 0x0201f800, 0x001005d8, 0x59a80821,
+ 0x800409c0, 0x02020000, 0x00102314, 0x0201f800,
+ 0x0010513b, 0x04020005, 0x4a034406, 0x00000016,
+ 0x0201f000, 0x0010230c, 0x836c0580, 0x00000003,
+ 0x02020000, 0x00102314, 0x59c408a4, 0x82040d00,
+ 0x0000000f, 0x82040580, 0x00000000, 0x02020000,
+ 0x00102314, 0x59c80040, 0x4c000000, 0x59a80010,
+ 0x4c000000, 0x59c400a3, 0x4c000000, 0x59c40008,
+ 0x4c000000, 0x59c40080, 0x4c000000, 0x59a0020f,
+ 0x59a0bc0f, 0x905cb9c0, 0x805cbd40, 0x41784800,
+ 0x41785000, 0x41785800, 0x41789000, 0x41789800,
+ 0x0401fe21, 0x0201f800, 0x00106c55, 0x0201f800,
+ 0x00100ae0, 0x4178c000, 0x497b4002, 0x0401f95c,
+ 0x0401f9aa, 0x59a0020c, 0x59a00c0c, 0x80040d40,
+ 0x04000002, 0x0401f9fb, 0x0401f9fa, 0x0401fe68,
+ 0x8060c1c0, 0x04020014, 0x0401fa98, 0x0401feb2,
+ 0x0402000e, 0x0201f800, 0x001018d3, 0x04020008,
+ 0x4a034406, 0x00000017, 0x0201f800, 0x0010230c,
+ 0x4203e000, 0x50000000, 0x0401f000, 0x42005800,
+ 0x0000aaaa, 0x0401f058, 0x59c80001, 0x800001c0,
+ 0x040007ee, 0x59c80801, 0x800409c0, 0x04000006,
+ 0x0401fa70, 0x40240000, 0x80280540, 0x802c0540,
+ 0x0402004d, 0x59a00002, 0x82000580, 0xfeedbeef,
+ 0x04000004, 0x42008800, 0x10000000, 0x0401f003,
+ 0x42008800, 0x10000004, 0x0401fa19, 0x4a034002,
+ 0xfeedbeef, 0x0401fa71, 0x0401fa97, 0x0401fea8,
+ 0x59c40005, 0x8c000534, 0x04000004, 0x42005800,
+ 0x0000bbbb, 0x0401f038, 0x0401fe83, 0x04020007,
+ 0x42005800, 0x0000cccc, 0x485f420f, 0x905cb9c0,
+ 0x485f440f, 0x0401f030, 0x59a0040c, 0x800001c0,
+ 0x0400000e, 0x59a26000, 0x5930000d, 0x800001c0,
+ 0x040207be, 0x59a26001, 0x5930080d, 0x800409c0,
+ 0x040207ba, 0x804891c0, 0x040207b8, 0x804c99c0,
+ 0x040207b6, 0x0401f87a, 0x805cb840, 0x04000005,
+ 0x40240000, 0x80280540, 0x802c0540, 0x0402001a,
+ 0x42000000, 0x00030d40, 0x80000040, 0x04020012,
+ 0x59c00007, 0x82000500, 0x000501c0, 0x0402000b,
+ 0x0201f800, 0x001018d3, 0x04020008, 0x4a034406,
+ 0x00000017, 0x0201f800, 0x0010230c, 0x4203e000,
+ 0x50000000, 0x0401f000, 0x42005800, 0x0000dddd,
+ 0x0401f005, 0x59c00807, 0x82040d00, 0x0000000c,
+ 0x040007ea, 0x0401fe5c, 0x59a0040c, 0x800001c0,
+ 0x04000002, 0x0401f856, 0x0401fe6b, 0x40240000,
+ 0x80280540, 0x802c0540, 0x04020003, 0x805cb9c0,
+ 0x04020781, 0x0201f800, 0x00106f36, 0x0401fda3,
+ 0x4201d000, 0x000186a0, 0x0201f800, 0x001060c6,
+ 0x5c000800, 0x48078880, 0x5c000800, 0x48078808,
+ 0x5c000800, 0x480788a3, 0x5c000800, 0x48075010,
+ 0x5c000800, 0x48079040, 0x0201f800, 0x00100969,
+ 0x59a00406, 0x82000500, 0x00000003, 0x82000580,
+ 0x00000002, 0x0400002c, 0x42000800, 0x000000c0,
+ 0x0201f800, 0x0010193f, 0x82040500, 0xfffffffc,
+ 0x42000800, 0x000000c0, 0x0201f800, 0x00101944,
+ 0x42000800, 0x00000000, 0x0201f800, 0x0010193f,
+ 0x82040500, 0xfffffff7, 0x42000800, 0x00000000,
+ 0x0201f800, 0x00101944, 0x42000800, 0x00000000,
+ 0x0201f800, 0x0010193f, 0x82040500, 0xfffffffb,
+ 0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+ 0x4a0388a7, 0x0000f7f7, 0x42006000, 0xbeffffff,
+ 0x42006800, 0x80018000, 0x0201f800, 0x0010427d,
+ 0x42006000, 0xfffeffff, 0x41786800, 0x0201f800,
+ 0x0010427d, 0x402c0000, 0x80280540, 0x80240540,
+ 0x02000000, 0x001022c0, 0x48274406, 0x482b4207,
+ 0x482f4407, 0x0201f000, 0x0010231c, 0x59a26000,
+ 0x813261c0, 0x0400000e, 0x59325808, 0x812e59c0,
+ 0x0400000b, 0x0201f800, 0x0002077d, 0x0201f800,
+ 0x001007fd, 0x59a26001, 0x59325808, 0x0201f800,
+ 0x0002077d, 0x0201f800, 0x001007fd, 0x1c01f000,
+ 0x42000800, 0x000000ef, 0x0201f800, 0x001015eb,
+ 0x59c400a3, 0x8400055a, 0x8400053a, 0x480388a3,
+ 0x0201f800, 0x0010163b, 0x0402000a, 0x42000000,
+ 0x00000001, 0x0201f800, 0x0010188c, 0x42000000,
+ 0x00000001, 0x0201f800, 0x00101821, 0x0401f013,
+ 0x0201f800, 0x00101642, 0x04020008, 0x41780000,
+ 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+ 0x00101821, 0x0401f009, 0x42000000, 0x00000002,
+ 0x0201f800, 0x0010188c, 0x42000000, 0x00000002,
+ 0x0201f800, 0x00101821, 0x42000800, 0x00000000,
+ 0x0201f800, 0x0010193f, 0x82040540, 0x00000004,
+ 0x42000800, 0x00000000, 0x0201f800, 0x00101944,
+ 0x4201d000, 0x00000014, 0x0201f800, 0x0010608e,
+ 0x59c40008, 0x8400054e, 0x82000500, 0xffffffe1,
+ 0x48038808, 0x4a0388a7, 0x0000f7f7, 0x42001000,
+ 0x04000001, 0x0201f800, 0x0010193d, 0x42006000,
+ 0xbe20bfff, 0x42006800, 0x80018000, 0x0201f800,
+ 0x0010427d, 0x42006000, 0xfffeffff, 0x41786800,
+ 0x0201f800, 0x0010427d, 0x4200b000, 0x00001388,
+ 0x4201d000, 0x00000014, 0x4c580000, 0x0201f800,
+ 0x0010608e, 0x0201f800, 0x001018d3, 0x5c00b000,
+ 0x04000004, 0x8058b040, 0x040207f6, 0x0401f025,
+ 0x59c40005, 0x8c000534, 0x04020007, 0x59c400a4,
+ 0x82000500, 0x0000000f, 0x82000580, 0x00000008,
+ 0x0402001c, 0x42006000, 0x00020000, 0x0201f800,
+ 0x00104282, 0x4201d000, 0x00000064, 0x0201f800,
+ 0x0010608e, 0x42006000, 0xfeffffff, 0x42006800,
+ 0x02000000, 0x0201f800, 0x0010427d, 0x42006000,
+ 0xfdffffff, 0x41786800, 0x0201f800, 0x0010427d,
+ 0x4a038805, 0x04000001, 0x59c400a4, 0x82000500,
+ 0x0000000f, 0x82000580, 0x00000000, 0x04000003,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856,
+ 0x42038000, 0x00007700, 0x0201f800, 0x00100ec1,
+ 0x59c00006, 0x59a0040c, 0x800001c0, 0x0400003f,
+ 0x59a03c0c, 0x59a00209, 0x59a01c09, 0x900c19c0,
+ 0x800c1d40, 0x59a0020e, 0x59a0240e, 0x901021c0,
+ 0x80102540, 0x59a0020b, 0x82000500, 0x0000fffc,
+ 0x59a0140b, 0x900811c0, 0x80081540, 0x480b8003,
+ 0x0201f800, 0x0002075a, 0x02000800, 0x001005d8,
+ 0x49334000, 0x0201f800, 0x001007e4, 0x4a025a04,
+ 0x00000018, 0x4a025805, 0x00abcdef, 0x492e6008,
+ 0x492e600b, 0x481e600d, 0x4a02600c, 0x00000004,
+ 0x832c0400, 0x00000011, 0x4802600a, 0x42001000,
+ 0x0000000c, 0x821c0d80, 0x00000001, 0x04000004,
+ 0x801c3840, 0x0401f963, 0x0401f004, 0x41783800,
+ 0x0401f960, 0x0401f011, 0x821c0c80, 0x00000005,
+ 0x04001005, 0x40043800, 0x42001000, 0x0000003c,
+ 0x0401f006, 0x80001580, 0x82081400, 0x0000000c,
+ 0x801c3840, 0x040207fd, 0x832c0400, 0x00000005,
+ 0x0401f950, 0x040207f1, 0x497b9009, 0x59e00003,
+ 0x82000540, 0x00008060, 0x4803c003, 0x4a038009,
+ 0x00e00000, 0x1c01f000, 0x4803c856, 0x41780800,
+ 0x8007a0ca, 0x83d3a400, 0x00007600, 0x42000800,
+ 0x00000040, 0x0201f800, 0x00101345, 0x4a03a00a,
+ 0x00000001, 0x4a03a005, 0x20000000, 0x59d00006,
+ 0x4a03a005, 0x30000000, 0x59d00006, 0x8c00050a,
+ 0x040207fe, 0x59d00005, 0x59a0020c, 0x800001c0,
+ 0x0400003f, 0x59a03a0c, 0x59a00210, 0x59a01c10,
+ 0x900c19c0, 0x800c1d40, 0x59a0020d, 0x59a0240d,
+ 0x901021c0, 0x80102540, 0x59a0120b, 0x82081500,
+ 0x0000fffc, 0x59a0040b, 0x900001c0, 0x80081540,
+ 0x480ba003, 0x0201f800, 0x0002075a, 0x02000800,
+ 0x001005d8, 0x49334001, 0x0201f800, 0x001007e4,
+ 0x4a025a04, 0x00000018, 0x4a025805, 0x00abcdef,
+ 0x492e6008, 0x492e600b, 0x481e600d, 0x4a02600c,
+ 0x00000004, 0x832c0400, 0x00000011, 0x4802600a,
+ 0x42001000, 0x0000000c, 0x821c0d80, 0x00000001,
+ 0x04000004, 0x801c3840, 0x0401f906, 0x0401f004,
+ 0x41783800, 0x0401f903, 0x0401f011, 0x821c0c80,
+ 0x00000005, 0x04001005, 0x40043800, 0x42001000,
+ 0x0000003c, 0x0401f006, 0x80001580, 0x82081400,
+ 0x0000000c, 0x801c3840, 0x040207fd, 0x832c0400,
+ 0x00000005, 0x0401f8f3, 0x040207f1, 0x1c01f000,
+ 0x4803c856, 0x59a0020c, 0x800001c0, 0x04000024,
+ 0x824c0580, 0x00000002, 0x04000040, 0x59a26001,
+ 0x5930380d, 0x801c39c0, 0x0400003c, 0x801c3840,
+ 0x481e600d, 0x5932580b, 0x5930080a, 0x50042000,
+ 0x58041801, 0x58041002, 0x82081500, 0xfffffffc,
+ 0x5930000c, 0x80000000, 0x82000d80, 0x00000005,
+ 0x04020009, 0x497a600c, 0x592e5801, 0x812e59c0,
+ 0x0400001a, 0x492e600b, 0x832c0c00, 0x00000005,
+ 0x0401f005, 0x4802600c, 0x5930080a, 0x82040c00,
+ 0x00000003, 0x4806600a, 0x0401f010, 0x59a0120b,
+ 0x82081500, 0x0000fffc, 0x59a0040b, 0x900001c0,
+ 0x80081540, 0x480ba003, 0x59a0020d, 0x59a0240d,
+ 0x901021c0, 0x80102540, 0x59a00210, 0x59a01c10,
+ 0x900c19c0, 0x800c1d40, 0x4201d000, 0x00003a98,
+ 0x0201f800, 0x001060c6, 0x480ba002, 0x59a80059,
+ 0x4803a008, 0x4813a000, 0x480fa001, 0x4a03a005,
+ 0x10000000, 0x02005800, 0x001005d8, 0x804c9800,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4847c857,
+ 0x59a0040c, 0x800001c0, 0x04000024, 0x82480580,
+ 0x00000002, 0x04000042, 0x59a26000, 0x5930380d,
+ 0x801c39c0, 0x0400003e, 0x801c3840, 0x481e600d,
+ 0x5932580b, 0x5930080a, 0x50042000, 0x58041801,
+ 0x58041002, 0x82081500, 0xfffffffc, 0x5930000c,
+ 0x80000000, 0x82000d80, 0x00000005, 0x04020009,
+ 0x497a600c, 0x592e5801, 0x812e59c0, 0x0400001d,
+ 0x492e600b, 0x832c0c00, 0x00000005, 0x0401f005,
+ 0x4802600c, 0x5930080a, 0x82040c00, 0x00000003,
+ 0x4806600a, 0x0401f013, 0x82440580, 0x10000000,
+ 0x0402001f, 0x59a0020e, 0x59a0240e, 0x901021c0,
+ 0x80102540, 0x59a00209, 0x59a01c09, 0x900c19c0,
+ 0x800c1d40, 0x59a0020b, 0x82000500, 0x0000fffc,
+ 0x59a0140b, 0x900811c0, 0x80081540, 0x480b8003,
+ 0x48138000, 0x480f8001, 0x480b8002, 0x59c80018,
+ 0x82000500, 0xf0000000, 0x59c02008, 0x82102500,
+ 0x0fffffff, 0x80100540, 0x48038008, 0x48478006,
+ 0x80489000, 0x8260c540, 0x00000001, 0x1c01f000,
+ 0x59c00009, 0x4803c857, 0x82000d00, 0x00e00000,
+ 0x0400000d, 0x485f420f, 0x905cb9c0, 0x485f440f,
+ 0x8c00052e, 0x04000002, 0x80285000, 0x8c00052c,
+ 0x04000002, 0x80244800, 0x8c00052a, 0x04000002,
+ 0x802c5800, 0x1c01f000, 0x59a0020c, 0x800001c0,
+ 0x04000024, 0x59d00806, 0x4807c857, 0x8c040d3e,
+ 0x04000020, 0x4a03a005, 0x20000000, 0x4a03a005,
+ 0x30000000, 0x59d00806, 0x8c040d0a, 0x040207fe,
+ 0x824c0480, 0x00000003, 0x02021800, 0x001005d8,
+ 0x404c0000, 0x0c01f001, 0x00102da1, 0x00102da3,
+ 0x00102da9, 0x0201f800, 0x001005d8, 0x80000040,
+ 0x40009800, 0x0401ff43, 0x0400000a, 0x0401ff41,
+ 0x0401f008, 0x80000040, 0x40009800, 0x59d00806,
+ 0x4807c857, 0x8c040d3e, 0x040207e3, 0x0401ff39,
+ 0x1c01f000, 0x59a0040c, 0x800001c0, 0x04000024,
+ 0x59c00807, 0x4807c857, 0x8c040d3e, 0x04000020,
+ 0x59c00807, 0x4a038006, 0x20000000, 0x82480480,
+ 0x00000003, 0x02021800, 0x001005d8, 0x40480000,
+ 0x0c01f001, 0x00102dc4, 0x00102dc6, 0x00102dce,
+ 0x0201f800, 0x001005d8, 0x80000040, 0x40009000,
+ 0x42008800, 0x10000004, 0x0401ff65, 0x0400000c,
+ 0x0401ff63, 0x0401f00a, 0x80000040, 0x40009000,
+ 0x59c00807, 0x4807c857, 0x8c040d3e, 0x040207e5,
+ 0x42008800, 0x10000004, 0x0401ff59, 0x1c01f000,
+ 0x492fc857, 0x4000a800, 0x4a03b805, 0x20000000,
+ 0x59dc0006, 0x4a03b805, 0x30000000, 0x4813b800,
+ 0x480fb801, 0x480bb802, 0x4857b803, 0x4a03b805,
+ 0x30000002, 0x59dc0006, 0x4a03b805, 0x70000001,
+ 0x59dc0006, 0x4a03b805, 0x10000000, 0x59dc0006,
+ 0x8c00053e, 0x040007fe, 0x4a03b805, 0x20000000,
+ 0x59dc0006, 0x59dc2000, 0x59dc1801, 0x801c39c0,
+ 0x0400000a, 0x4d2c0000, 0x0201f800, 0x001007e4,
+ 0x5c000800, 0x02000800, 0x001005d8, 0x4a025a04,
+ 0x0000000a, 0x492c0801, 0x1c01f000, 0x42006000,
+ 0x00102fb2, 0x0201f800, 0x00101345, 0x4a03902c,
+ 0x00200000, 0x4200b000, 0x000001f4, 0x59c8002c,
+ 0x8c00052c, 0x04000007, 0x8058b040, 0x040207fc,
+ 0x42000000, 0x00004003, 0x41781000, 0x0401f196,
+ 0x50301000, 0x41784800, 0x4a03902d, 0x00008000,
+ 0x4200b000, 0x000001f4, 0x59c8002c, 0x8c000534,
+ 0x04000007, 0x8058b040, 0x040207fc, 0x42000000,
+ 0x00004003, 0x41781000, 0x0401f187, 0x0401f8f8,
+ 0x80244800, 0x40240000, 0x82000580, 0x000003b1,
+ 0x040207fb, 0x0401f988, 0x41784800, 0x0401f920,
+ 0x80244800, 0x40240000, 0x82000580, 0x000003b1,
+ 0x040207fb, 0x80306000, 0x82300580, 0x00102fb4,
+ 0x040207e0, 0x59a80863, 0x800409c0, 0x04000007,
+ 0x42000000, 0x00004004, 0x42001000, 0x00000002,
+ 0x59a81862, 0x0401f16c, 0x42006000, 0x00102fb2,
+ 0x4a035064, 0x00000004, 0x50301000, 0x41784800,
+ 0x4a03902d, 0x00004000, 0x4200b000, 0x000001f4,
+ 0x59c8002c, 0x8c000532, 0x04000007, 0x8058b040,
+ 0x040207fc, 0x42000000, 0x00004003, 0x41781000,
+ 0x0401f159, 0x0401f8ca, 0x80244800, 0x40240000,
+ 0x82000580, 0x00000154, 0x040207fb, 0x0401f95a,
+ 0x41784800, 0x0401f8f2, 0x80244800, 0x40240000,
+ 0x82000580, 0x00000154, 0x040207fb, 0x80306000,
+ 0x82300580, 0x00102fb4, 0x040207e0, 0x59a80863,
+ 0x800409c0, 0x04000007, 0x42000000, 0x00004004,
+ 0x42001000, 0x00000004, 0x59a81862, 0x0401f13e,
+ 0x42006000, 0x00102fb2, 0x497b5064, 0x50301000,
+ 0x41784800, 0x4a03902d, 0x00001000, 0x4200b000,
+ 0x000001f4, 0x59c8002c, 0x8c00052e, 0x04000007,
+ 0x8058b040, 0x040207fc, 0x42000000, 0x00004003,
+ 0x41781000, 0x0401f12c, 0x0401f89d, 0x80244800,
+ 0x40240000, 0x82000580, 0x00000088, 0x040207fb,
+ 0x0401f92d, 0x41784800, 0x0401f8c5, 0x80244800,
+ 0x40240000, 0x82000580, 0x00000088, 0x040207fb,
+ 0x80306000, 0x82300580, 0x00102fb4, 0x040207e0,
+ 0x59a80863, 0x800409c0, 0x04000007, 0x42000000,
+ 0x00004004, 0x42001000, 0x00000001, 0x59a81862,
+ 0x0401f111, 0x42006000, 0x00102fb2, 0x50301000,
+ 0x41784800, 0x4a03902d, 0x00000800, 0x0401f87c,
+ 0x80244800, 0x40240000, 0x82000580, 0x00000018,
+ 0x040207fb, 0x0401f90c, 0x41784800, 0x0401f8a4,
+ 0x80244800, 0x40240000, 0x82000580, 0x00000018,
+ 0x040207fb, 0x80306000, 0x82300580, 0x00102fb4,
+ 0x040207eb, 0x59a80863, 0x800409c0, 0x04000007,
+ 0x42000000, 0x00004004, 0x42001000, 0x00000010,
+ 0x59a81862, 0x0401f0f0, 0x42006000, 0x00102fb2,
+ 0x50301000, 0x41784800, 0x4a03902d, 0x00000400,
+ 0x0401f85b, 0x80244800, 0x40240000, 0x82000580,
+ 0x00000088, 0x040207fb, 0x0401f8eb, 0x41784800,
+ 0x0401f883, 0x80244800, 0x40240000, 0x82000580,
+ 0x00000088, 0x040207fb, 0x80306000, 0x82300580,
+ 0x00102fb4, 0x040207eb, 0x59a80863, 0x800409c0,
+ 0x04000007, 0x42000000, 0x00004004, 0x42001000,
+ 0x00000008, 0x59a81862, 0x0401f0cf, 0x42006000,
+ 0x00102fb2, 0x50301000, 0x41784800, 0x4a03902d,
+ 0x00002000, 0x4200b000, 0x000001f4, 0x59c8002c,
+ 0x8c000530, 0x04000007, 0x8058b040, 0x040207fc,
+ 0x42000000, 0x00004003, 0x41781000, 0x0401f0be,
+ 0x59c8002c, 0x82000500, 0xffe0ffff, 0x82080d00,
+ 0x001f0000, 0x80040540, 0x4803902c, 0x0401f828,
+ 0x80244800, 0x40240000, 0x82000580, 0x00000110,
+ 0x040207fb, 0x0401f8b8, 0x41784800, 0x0401f850,
+ 0x59c80034, 0x82080d00, 0x001f0000, 0x82000500,
+ 0x001f0000, 0x80040580, 0x04000006, 0x59a80063,
+ 0x80000000, 0x48035063, 0x40240000, 0x48035062,
+ 0x80244800, 0x40240000, 0x82000580, 0x00000110,
+ 0x040207ef, 0x80306000, 0x82300580, 0x00102fb4,
+ 0x040207cd, 0x59a80863, 0x800409c0, 0x04000006,
+ 0x42000000, 0x00004004, 0x42001000, 0x00000020,
+ 0x59a81862, 0x0201f000, 0x001022c0, 0x59c8002c,
+ 0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff,
+ 0x80040540, 0x4803902c, 0x40080000, 0x48039028,
+ 0x48039029, 0x59a80064, 0x82000580, 0x00000004,
+ 0x04000004, 0x40080000, 0x4803902a, 0x4803902b,
+ 0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000,
+ 0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4,
+ 0x59c8002c, 0x82000500, 0x18000000, 0x04000007,
+ 0x8058b040, 0x040207fb, 0x42000000, 0x00004003,
+ 0x41781000, 0x0401f06c, 0x4a03902e, 0x00000001,
+ 0x4200b000, 0x000001f4, 0x59c8002e, 0x8c000500,
+ 0x04000006, 0x8058b040, 0x040207fc, 0x42000000,
+ 0x00004003, 0x0401f060, 0x1c01f000, 0x41783800,
+ 0x59c8082d, 0x82040d00, 0xfffffc00, 0x40240000,
+ 0x80040d40, 0x4807902d, 0x4200b000, 0x000001f4,
+ 0x59c8002c, 0x82000500, 0x18000000, 0x04000007,
+ 0x8058b040, 0x040207fb, 0x42000000, 0x00004003,
+ 0x41781000, 0x0401f04c, 0x59c80030, 0x59c80830,
+ 0x80040580, 0x040207fd, 0x40041800, 0x59c80031,
+ 0x59c80831, 0x80040580, 0x040207fd, 0x40042000,
+ 0x59c80032, 0x59c80832, 0x80040580, 0x040207fd,
+ 0x40042800, 0x59c80033, 0x59c80833, 0x80040580,
+ 0x040207fd, 0x40043000, 0x400c0000, 0x80080580,
+ 0x04000002, 0x801c3800, 0x40100000, 0x80080580,
+ 0x04000002, 0x801c3800, 0x59a80064, 0x82000580,
+ 0x00000004, 0x04000009, 0x40140000, 0x80080580,
+ 0x04000002, 0x801c3800, 0x40180000, 0x80080580,
+ 0x04000002, 0x801c3800, 0x59a80064, 0x82000580,
+ 0x00000004, 0x0400000d, 0x59c80034, 0x59c80834,
+ 0x80040580, 0x040207fd, 0x82040500, 0x0000ffff,
+ 0x82080d00, 0x0000ffff, 0x80040580, 0x0400000e,
+ 0x801c3800, 0x0401f00c, 0x59c80034, 0x59c80834,
+ 0x80040580, 0x040207fd, 0x82040500, 0x000000ff,
+ 0x82080d00, 0x000000ff, 0x80040580, 0x04000002,
+ 0x801c3800, 0x801c39c0, 0x04000006, 0x59a80063,
+ 0x801c0400, 0x48035063, 0x40240000, 0x48035062,
+ 0x1c01f000, 0x48034206, 0x48074406, 0x480b4207,
+ 0x480f4407, 0x48134208, 0x48174408, 0x0201f000,
+ 0x001022c3, 0x42000000, 0x00600000, 0x80000040,
+ 0x040207ff, 0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5,
+ 0x59a00c0a, 0x800409c0, 0x02000000, 0x00102310,
+ 0x82040480, 0x00000021, 0x02021000, 0x00102310,
+ 0x82040480, 0x00000011, 0x04001003, 0x42000800,
+ 0x00000010, 0x59a00208, 0x59a01407, 0x900811c0,
+ 0x80081540, 0x59a00207, 0x59a01c06, 0x900c19c0,
+ 0x800c1d40, 0x0201f800, 0x00103a00, 0x04000006,
+ 0x0201f800, 0x00103a25, 0x4a01d809, 0x00102fd5,
+ 0x1c01f000, 0x4a034406, 0x00000002, 0x0201f000,
+ 0x0010230c, 0x4031d800, 0x58ef400b, 0x58ec0002,
+ 0x82000580, 0x00000200, 0x02000000, 0x00102304,
+ 0x59a00c0a, 0x82040480, 0x00000011, 0x04001003,
+ 0x42000800, 0x00000010, 0x59a0040b, 0x59a0120b,
+ 0x900811c0, 0x80081540, 0x59a00209, 0x59a01c08,
+ 0x900c19c0, 0x800c1d40, 0x58ec0003, 0x0201f800,
+ 0x00103a28, 0x4a01d809, 0x00102ff0, 0x1c01f000,
+ 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x59a00c0a,
+ 0x82040480, 0x00000011, 0x02001000, 0x001022c0,
+ 0x82040c80, 0x00000010, 0x59a00208, 0x59a01407,
+ 0x900811c0, 0x80081540, 0x59a00207, 0x59a01c06,
+ 0x900c19c0, 0x800c1d40, 0x82081400, 0x00000040,
+ 0x58ec0003, 0x0201f800, 0x00103a25, 0x4a01d809,
+ 0x0010300e, 0x1c01f000, 0x4031d800, 0x58ef400b,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+ 0x00102304, 0x59a0040a, 0x82000c80, 0x00000010,
+ 0x59a0040b, 0x59a0120b, 0x900811c0, 0x80081540,
+ 0x59a00209, 0x59a01c08, 0x900c19c0, 0x800c1d40,
+ 0x82081400, 0x00000040, 0x58ec0003, 0x0201f800,
+ 0x00103a28, 0x4a01d809, 0x001022b9, 0x1c01f000,
+ 0x48efc857, 0x59a00207, 0x59a01407, 0x900001c0,
+ 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+ 0x800c1d40, 0x59a00406, 0x48034000, 0x480b4001,
+ 0x480f4002, 0x0201f800, 0x00103a00, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x42000800, 0x00000010, 0x0201f800, 0x00103a25,
+ 0x4a01d809, 0x00103043, 0x1c01f000, 0x4031d800,
+ 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x48efc857,
+ 0x49a3c857, 0x492fc857, 0x592c0a04, 0x80040910,
+ 0x04020005, 0x4a034406, 0x00000019, 0x0201f000,
+ 0x0010230c, 0x4805d80c, 0x0401f00a, 0x4031d800,
+ 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x02000000, 0x00102304, 0x48efc857, 0x49a3c857,
+ 0x48efc857, 0x49a3c857, 0x58ec000c, 0x80000040,
+ 0x04000012, 0x4801d80c, 0x0201f800, 0x00103a00,
+ 0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+ 0x0010230c, 0x42000800, 0x00000010, 0x58ec1007,
+ 0x58ec1808, 0x0201f800, 0x00103a25, 0x4a01d809,
+ 0x00103057, 0x1c01f000, 0x58ee580d, 0x48efc857,
+ 0x49a3c857, 0x492fc857, 0x492f3006, 0x592c0404,
+ 0x8400055e, 0x48025c04, 0x4a01d809, 0x00103081,
+ 0x1c01f000, 0x58ee580d, 0x48efc857, 0x49a3c857,
+ 0x492fc857, 0x592c0404, 0x8400051e, 0x48025c04,
+ 0x59a00000, 0x59a01001, 0x59a01802, 0x80081400,
+ 0x820c1c40, 0x00000000, 0x832c0400, 0x00000004,
+ 0x42000800, 0x00000010, 0x0201f000, 0x00103a28,
+ 0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
+ 0x0201f000, 0x0010230c, 0x836c0580, 0x00000003,
+ 0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
+ 0x0010230c, 0x59a0320b, 0x82183500, 0x000000ff,
+ 0x59a28c06, 0x0201f800, 0x00020245, 0x02020000,
+ 0x00102310, 0x83440580, 0x000007fd, 0x04000008,
+ 0x0201f800, 0x001049e7, 0x04000005, 0x4a034406,
+ 0x00000009, 0x0201f000, 0x0010230c, 0x0201f800,
+ 0x00103a00, 0x04020005, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x801831c0, 0x0400000a,
+ 0x412c0800, 0x0201f800, 0x00103a00, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x40065800, 0x4a025c04, 0x00008000, 0x497a5a04,
+ 0x0201f800, 0x00109100, 0x04020005, 0x4a034406,
+ 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+ 0x001030d2, 0x1c01f000, 0x592c0005, 0x82000580,
+ 0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+ 0x0201f000, 0x0010230c, 0x592c0406, 0x82002d00,
+ 0x0000ff00, 0x82000500, 0x000000ff, 0x80000904,
+ 0x80040800, 0x82040480, 0x00000006, 0x04001003,
+ 0x42000800, 0x00000005, 0x832ca400, 0x00000006,
+ 0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28,
+ 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
+ 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
+ 0x832c0400, 0x00000006, 0x4c140000, 0x0201f800,
+ 0x00103a28, 0x5c002800, 0x801429c0, 0x04000003,
+ 0x4a01d809, 0x001030ff, 0x1c01f000, 0x4031d800,
+ 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x592c0006, 0x82000500,
+ 0xff000000, 0x80000904, 0x800409c0, 0x02000000,
+ 0x00102304, 0x82040480, 0x0000000e, 0x04001003,
+ 0x42000800, 0x0000000d, 0x592e5801, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x832ca400, 0x00000005,
+ 0x4050a800, 0x4004b000, 0x0201f800, 0x0010ab28,
+ 0x58ec1007, 0x58ec1808, 0x832c0400, 0x00000005,
+ 0x0201f000, 0x00103a28, 0x0201f800, 0x00103a00,
+ 0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+ 0x0010230c, 0x59a00c06, 0x82040500, 0x0000ff00,
+ 0x840001c0, 0x82001480, 0x00000007, 0x02021000,
+ 0x00102310, 0x0c01f001, 0x0010313d, 0x00103144,
+ 0x0010314b, 0x0010314b, 0x0010314b, 0x0010314d,
+ 0x00103152, 0x42000800, 0x0000000d, 0x42003800,
+ 0x00103166, 0x4a034000, 0x0010b4eb, 0x0401f013,
+ 0x42000800, 0x0000000d, 0x42003800, 0x00103166,
+ 0x4a034000, 0x0010b4f8, 0x0401f00c, 0x0201f000,
+ 0x00102310, 0x42000800, 0x00000008, 0x42003800,
+ 0x00103179, 0x0401f005, 0x42000800, 0x00000004,
+ 0x42003800, 0x001031c3, 0x59a00207, 0x59a01407,
+ 0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09,
+ 0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005,
+ 0x4c1c0000, 0x0201f800, 0x00103a25, 0x5c003800,
+ 0x481dd809, 0x1c01f000, 0x4031d800, 0x58ef400b,
+ 0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x02000000, 0x00102304, 0x4a03501f, 0x00000001,
+ 0x4200b000, 0x0000000d, 0x59a0a800, 0x832ca400,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x0201f000,
+ 0x001022c0, 0x4031d800, 0x58ef400b, 0x58ee580d,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+ 0x00102304, 0x832ca400, 0x00000005, 0x50500000,
+ 0x82001500, 0x000c0016, 0x02020000, 0x00102310,
+ 0x82500c00, 0x00000003, 0x50040000, 0x82001500,
+ 0x00000001, 0x02020000, 0x00102310, 0x50500000,
+ 0x82001500, 0x00000028, 0x0400001d, 0x82081580,
+ 0x00000028, 0x02020000, 0x00102310, 0x80500800,
+ 0x50040000, 0x82001500, 0x00000013, 0x82081580,
+ 0x00000013, 0x02020000, 0x00102310, 0x80040800,
+ 0x50040000, 0x82001500, 0x00010000, 0x82081580,
+ 0x00010000, 0x02020000, 0x00102310, 0x836c0580,
+ 0x00000000, 0x04000012, 0x599c0019, 0x8c00050e,
+ 0x0402000f, 0x0201f000, 0x00102310, 0x80500800,
+ 0x50040000, 0x82001500, 0x00000013, 0x02020000,
+ 0x00102310, 0x80040800, 0x50040000, 0x82001500,
+ 0x00010000, 0x02020000, 0x00102310, 0x4200b000,
+ 0x00000008, 0x4200a800, 0x0010b4e3, 0x0201f800,
+ 0x0010ab17, 0x0201f000, 0x001022c0, 0x4031d800,
+ 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x4200b000,
+ 0x00000004, 0x4200a800, 0x0010b8fa, 0x832ca400,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x59a80005,
+ 0x84000550, 0x48035005, 0x0201f000, 0x001022c0,
+ 0x0201f800, 0x00103a00, 0x04020005, 0x4a034406,
+ 0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06,
+ 0x82040500, 0x0000ff00, 0x840001c0, 0x82001480,
+ 0x00000006, 0x02021000, 0x00102310, 0x0c01f001,
+ 0x001031ee, 0x001031f3, 0x001031f8, 0x001031f8,
+ 0x001031f8, 0x001031fa, 0x42000800, 0x0000000d,
+ 0x4200a000, 0x0010b4eb, 0x0401f00c, 0x42000800,
+ 0x0000000d, 0x4200a000, 0x0010b4f8, 0x0401f007,
+ 0x0201f000, 0x00102310, 0x42000800, 0x00000008,
+ 0x4200a000, 0x0010b4e3, 0x4004b000, 0x832cac00,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x59a00207,
+ 0x59a01407, 0x900001c0, 0x80081540, 0x59a00209,
+ 0x59a01c09, 0x900001c0, 0x800c1d40, 0x832c0400,
+ 0x00000005, 0x0201f000, 0x00103a28, 0x836c0580,
+ 0x00000000, 0x04020005, 0x4a034406, 0x00000007,
+ 0x0201f000, 0x0010230c, 0x59a00406, 0x800001c0,
+ 0x0400001a, 0x59a80005, 0x8c000514, 0x04000005,
+ 0x42000000, 0x00000001, 0x40000800, 0x0401f003,
+ 0x59a00207, 0x59a80853, 0x48035053, 0x0201f800,
+ 0x0010163b, 0x04000022, 0x0201f800, 0x00101642,
+ 0x0400001f, 0x0201f800, 0x00101649, 0x0400001c,
+ 0x0201f800, 0x00101650, 0x04000019, 0x48075053,
+ 0x0201f000, 0x00102310, 0x59c40801, 0x82040d00,
+ 0x00018000, 0x82040580, 0x00000000, 0x04020004,
+ 0x4a034406, 0x00000000, 0x0401f00d, 0x82040580,
+ 0x00008000, 0x04020004, 0x4a034406, 0x00000001,
+ 0x0401f007, 0x82040580, 0x00010000, 0x02020800,
+ 0x001005d8, 0x4a034406, 0x00000003, 0x59a00406,
+ 0x82000580, 0x00000002, 0x0402001f, 0x59c40006,
+ 0x84000500, 0x48038806, 0x0201f800, 0x00106ede,
+ 0x497b8880, 0x0201f800, 0x0010a9c0, 0x0201f800,
+ 0x0010a9ce, 0x42000000, 0x0010b8ca, 0x0201f800,
+ 0x0010aa47, 0x82000540, 0x00000001, 0x0201f800,
+ 0x0010518c, 0x4a038808, 0x00000000, 0x4202d800,
+ 0x00000004, 0x42001000, 0x00000001, 0x0201f800,
+ 0x0010193d, 0x4a035049, 0x00000001, 0x0201f800,
+ 0x001006d4, 0x0201f000, 0x001022c0, 0x800409c0,
+ 0x04000005, 0x4a034406, 0x00000001, 0x0201f000,
+ 0x0010230c, 0x836c0580, 0x00000003, 0x04000005,
+ 0x4a034406, 0x00000007, 0x0201f000, 0x0010230c,
+ 0x59a28c06, 0x59a0320b, 0x82183500, 0x000000ff,
+ 0x0201f800, 0x00020245, 0x02020000, 0x00102310,
+ 0x83440580, 0x000007fd, 0x04000008, 0x0201f800,
+ 0x001049e7, 0x04000005, 0x42000800, 0x00000009,
+ 0x0201f000, 0x0010230c, 0x0201f800, 0x00103a00,
+ 0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+ 0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000,
+ 0x0201f800, 0x00109115, 0x04020005, 0x4a034406,
+ 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+ 0x0010329e, 0x1c01f000, 0x592c0005, 0x82000d00,
+ 0x0000ffff, 0x82000500, 0xffff0000, 0x82000580,
+ 0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+ 0x0201f000, 0x0010230c, 0x80040904, 0x832ca400,
+ 0x00000005, 0x4050a800, 0x4004b000, 0x0201f800,
+ 0x0010ab28, 0x59a00207, 0x59a01407, 0x900001c0,
+ 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+ 0x800c1d40, 0x832c0400, 0x00000005, 0x0201f000,
+ 0x00103a28, 0x496fc857, 0x836c0580, 0x00000000,
+ 0x04000005, 0x4a034406, 0x0000001a, 0x0201f000,
+ 0x0010230c, 0x0201f800, 0x0010513b, 0x02020800,
+ 0x00104142, 0x42000800, 0x00000020, 0x59a00407,
+ 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+ 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x419c0000,
+ 0x49a3c857, 0x0201f800, 0x00103a25, 0x4a01d809,
+ 0x001032da, 0x1c01f000, 0x4833c857, 0x4031d800,
+ 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x02000000, 0x00102304, 0x599c0200, 0x800001c0,
+ 0x02000000, 0x00102310, 0x59a80005, 0x8c000512,
+ 0x04000004, 0x599c0019, 0x8400050c, 0x48033819,
+ 0x0201f800, 0x001097d7, 0x59a80005, 0x8c000514,
+ 0x04000004, 0x599c0017, 0x84000508, 0x48033817,
+ 0x0201f800, 0x00103b25, 0x04020004, 0x8c00050a,
+ 0x02020000, 0x00102310, 0x4803c857, 0x8c000504,
+ 0x04020004, 0x59c408a3, 0x84040d7a, 0x480788a3,
+ 0x8c000502, 0x04020004, 0x59c408a3, 0x84040d08,
+ 0x480788a3, 0x599c0c02, 0x8c000500, 0x04020004,
+ 0x8c000516, 0x04000012, 0x0401f001, 0x82041480,
+ 0x0000007f, 0x02021000, 0x00102310, 0x82041400,
+ 0x0010210e, 0x50081000, 0x82081500, 0x000000ff,
+ 0x8c000500, 0x04020006, 0x480b5010, 0x42000800,
+ 0x00000003, 0x0201f800, 0x00106c78, 0x599c0019,
+ 0x8c00050e, 0x0402000b, 0x59a80806, 0x8c040d14,
+ 0x04000008, 0x42000800, 0x0010b4e3, 0x50040800,
+ 0x82040d00, 0x00000028, 0x02020000, 0x00102310,
+ 0x82000500, 0x00000030, 0x04000003, 0x80000108,
+ 0x0401f003, 0x42000000, 0x00000002, 0x48039040,
+ 0x42000800, 0x00000002, 0x82000400, 0x00103415,
+ 0x50001000, 0x0201f800, 0x00106c78, 0x599c0201,
+ 0x82000c80, 0x00000100, 0x02001000, 0x00102310,
+ 0x82000c80, 0x00000841, 0x02021000, 0x00102310,
+ 0x82000500, 0x00000007, 0x02020000, 0x00102310,
+ 0x599c0401, 0x80000540, 0x02000000, 0x00102310,
+ 0x599c0409, 0x599c0c07, 0x80040c80, 0x02021000,
+ 0x00102310, 0x80000040, 0x02000000, 0x00102310,
+ 0x599c0209, 0x599c0a07, 0x80040c80, 0x02021000,
+ 0x00102310, 0x80000040, 0x02000000, 0x00102310,
+ 0x0201f800, 0x001053cd, 0x0201f800, 0x00104cb6,
+ 0x599c0201, 0x48035004, 0x0201f800, 0x001012ee,
+ 0x599c020a, 0x800001c0, 0x04000003, 0x4803504d,
+ 0x0401f003, 0x4a03504d, 0x000000c8, 0x0201f800,
+ 0x00103b25, 0x04000004, 0x0201f800, 0x001060df,
+ 0x417a5000, 0x836c0580, 0x00000000, 0x04020098,
+ 0x599c0003, 0x599c0804, 0x9c0001c0, 0x9c0409c0,
+ 0x48035002, 0x48075003, 0x599c1017, 0x8c08151c,
+ 0x04000006, 0x599c0005, 0x599c0806, 0x9c0001c0,
+ 0x9c0409c0, 0x0401f003, 0x82000500, 0xf0ffffff,
+ 0x48035000, 0x48075001, 0x42001000, 0x0010b4eb,
+ 0x48001000, 0x48041001, 0x42001000, 0x0010b4f8,
+ 0x48001000, 0x48041001, 0x59a80005, 0x8c000514,
+ 0x04020015, 0x599c1019, 0x82081500, 0x0000e000,
+ 0x82080580, 0x00000000, 0x0402000c, 0x4a035053,
+ 0x00000000, 0x42000000, 0x00000001, 0x0201f800,
+ 0x0010188c, 0x42000000, 0x00000001, 0x0201f800,
+ 0x00101821, 0x0401f02b, 0x82080580, 0x00002000,
+ 0x0402000a, 0x4a035053, 0x00000001, 0x41780000,
+ 0x0201f800, 0x0010188c, 0x41780000, 0x0201f800,
+ 0x00101821, 0x0401f01f, 0x82080580, 0x00004000,
+ 0x04020006, 0x4a035053, 0x00000002, 0x4a035049,
+ 0x00000001, 0x0401f017, 0x82080580, 0x00006000,
+ 0x02020000, 0x00102310, 0x59a80858, 0x82040d80,
+ 0x01391077, 0x04020005, 0x59e00813, 0x8c040d00,
+ 0x02020000, 0x00102310, 0x4a035053, 0x00000003,
+ 0x42000000, 0x00000002, 0x0201f800, 0x0010188c,
+ 0x42000000, 0x00000002, 0x0201f800, 0x00101821,
+ 0x599c0019, 0x8c000520, 0x0400000d, 0x42000000,
+ 0x00000004, 0x42000800, 0x00000040, 0x0201f800,
+ 0x00101944, 0x42000000, 0x00000010, 0x42000800,
+ 0x000000c0, 0x0201f800, 0x00101944, 0x4a035032,
+ 0x0000aaaa, 0x599c1018, 0x82081500, 0x00000030,
+ 0x59a8006c, 0x80000540, 0x0400000c, 0x82080580,
+ 0x00000000, 0x02000000, 0x00102310, 0x599c1018,
+ 0x82081500, 0xffffffcf, 0x82081540, 0x00000010,
+ 0x480b3818, 0x0401f010, 0x82080d80, 0x00000000,
+ 0x04000007, 0x82080d80, 0x00000010, 0x0400000a,
+ 0x82080d80, 0x00000020, 0x04020002, 0x48075032,
+ 0x0201f800, 0x00103aba, 0x04000008, 0x0201f800,
+ 0x001015fe, 0x0201f800, 0x0010162a, 0x59a8002a,
+ 0x80040540, 0x4803502a, 0x49f3c857, 0x42001000,
+ 0x00105065, 0x0201f800, 0x00105f90, 0x42001000,
+ 0x00105058, 0x0201f800, 0x00106084, 0x4a038805,
+ 0xffffffff, 0x4a03c014, 0x00400040, 0x4a03c013,
+ 0x00400000, 0x0201f800, 0x001048c7, 0x59a0001d,
+ 0x84000540, 0x4803401d, 0x49f3c857, 0x0201f000,
+ 0x001022c0, 0x00000018, 0x0000000c, 0x00000018,
+ 0x00000020, 0x836c0580, 0x00000000, 0x04020005,
+ 0x42000800, 0x00000007, 0x0201f000, 0x0010230c,
+ 0x42000800, 0x00000020, 0x59a00407, 0x59a01207,
+ 0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
+ 0x900c19c0, 0x800c1d40, 0x419c0000, 0x0201f000,
+ 0x00103a28, 0x800409c0, 0x04000005, 0x4a034406,
+ 0x00000001, 0x0201f000, 0x0010230c, 0x0201f800,
+ 0x0010513b, 0x04020005, 0x4a034406, 0x00000016,
+ 0x0201f000, 0x0010230c, 0x59a80013, 0x8c000500,
+ 0x04000011, 0x4a034406, 0x00000000, 0x42000800,
+ 0x00000020, 0x59a00407, 0x59a01207, 0x900811c0,
+ 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+ 0x800c1d40, 0x42000000, 0x0010be21, 0x0201f000,
+ 0x00103a28, 0x4a034406, 0x00000001, 0x4200b000,
+ 0x00000020, 0x4200a800, 0x0010be21, 0x4200a000,
+ 0xffffffff, 0x4450a800, 0x8054a800, 0x8058b040,
+ 0x040207fd, 0x4d440000, 0x4d340000, 0x42028800,
+ 0xffffffff, 0x42002000, 0xffffffff, 0x42003000,
+ 0x00000001, 0x42003800, 0x00000001, 0x42001800,
+ 0x0010be21, 0x59a81010, 0x82081500, 0x000000ff,
+ 0x40180000, 0x0c01f001, 0x0010346e, 0x00103471,
+ 0x00103475, 0x00103479, 0x82102500, 0xffffff00,
+ 0x0401f014, 0x82102500, 0xffff00ff, 0x840811c0,
+ 0x0401f010, 0x82102500, 0xff00ffff, 0x900811c0,
+ 0x0401f00c, 0x82102500, 0x00ffffff, 0x9c0801c0,
+ 0x80102540, 0x44101800, 0x42003000, 0xffffffff,
+ 0x42002000, 0xffffffff, 0x800c1800, 0x0401f003,
+ 0x40080000, 0x80102540, 0x81468800, 0x83442c80,
+ 0x0000007f, 0x04021014, 0x4c080000, 0x4c0c0000,
+ 0x4c180000, 0x4c1c0000, 0x0201f800, 0x00020245,
+ 0x5c003800, 0x5c003000, 0x5c001800, 0x5c001000,
+ 0x040207f2, 0x0201f800, 0x001049f3, 0x040207ef,
+ 0x80183000, 0x801c3800, 0x59341202, 0x40180000,
+ 0x0c01f7ce, 0x82100580, 0xffffffff, 0x04000002,
+ 0x44101800, 0x42001800, 0x0010be21, 0x500c0000,
+ 0x82000500, 0xffffff00, 0x801c0540, 0x44001800,
+ 0x5c026800, 0x5c028800, 0x42000800, 0x00000020,
+ 0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
+ 0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
+ 0x42000000, 0x0010be21, 0x0201f000, 0x00103a28,
+ 0x59a28c06, 0x59a0020b, 0x8c000500, 0x0400000e,
+ 0x59a01208, 0x59a00408, 0x82000500, 0x000000ff,
+ 0x900001c0, 0x80081540, 0x41784000, 0x0201f800,
+ 0x00104919, 0x04000008, 0x48034406, 0x0201f000,
+ 0x00102310, 0x0201f800, 0x00020245, 0x02020000,
+ 0x00102310, 0x0201f800, 0x00103a00, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x59a0020b, 0x8c000500, 0x04000005, 0x0201f800,
+ 0x001049f3, 0x02020000, 0x00103ac4, 0x59a0020b,
+ 0x8c000502, 0x04000019, 0x83440480, 0x000007f0,
+ 0x04021016, 0x0201f800, 0x001049fc, 0x04020013,
+ 0x497a5a04, 0x4a025c04, 0x00008000, 0x0201f800,
+ 0x001090e6, 0x04020005, 0x4a034406, 0x00000003,
+ 0x0201f000, 0x0010230c, 0x4a01d809, 0x001034f1,
+ 0x1c01f000, 0x59a28c06, 0x0201f800, 0x00020245,
+ 0x02020000, 0x00102310, 0x4200b000, 0x0000000a,
+ 0x4134a000, 0x832e5c00, 0x00000002, 0x412ca800,
+ 0x0201f800, 0x0010ab17, 0x832cac00, 0x00000006,
+ 0x4054a000, 0x4200b000, 0x00000004, 0x0201f800,
+ 0x0010ab28, 0x592c0802, 0x82040500, 0x00ff00ff,
+ 0x900001c0, 0x82041500, 0xff00ff00, 0x80080540,
+ 0x48025802, 0x592c0801, 0x82040500, 0x00ff00ff,
+ 0x900001c0, 0x82041500, 0xff00ff00, 0x80080540,
+ 0x48025801, 0x42000800, 0x0000000a, 0x59a00407,
+ 0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
+ 0x59a01a09, 0x900c19c0, 0x800c1d40, 0x412c0000,
+ 0x0201f000, 0x00103a28, 0x496fc857, 0x496f4406,
+ 0x0201f000, 0x001022c0, 0x59a28c06, 0x0201f800,
+ 0x00020245, 0x02020000, 0x00102310, 0x836c0580,
+ 0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+ 0x0201f000, 0x0010230c, 0x83340c00, 0x00000006,
+ 0x59a0020b, 0x8c000500, 0x04000003, 0x83340c00,
+ 0x00000008, 0x58040001, 0x48034409, 0x900001c0,
+ 0x48034209, 0x50040000, 0x48034407, 0x900001c0,
+ 0x48034207, 0x59340200, 0x48034406, 0x0201f000,
+ 0x001022c0, 0x800409c0, 0x04000005, 0x4a034406,
+ 0x00000001, 0x0201f000, 0x0010230c, 0x59a0220b,
+ 0x8c102500, 0x0402002e, 0x8c102506, 0x04020006,
+ 0x59a03208, 0x82180480, 0x00000003, 0x02021000,
+ 0x00102310, 0x59a28c06, 0x0201f800, 0x00020245,
+ 0x02020000, 0x00102310, 0x0201f800, 0x001049e7,
+ 0x04000005, 0x4a034406, 0x00000009, 0x0201f000,
+ 0x0010230c, 0x0201f800, 0x00103a00, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x59a0220b, 0x8c102506, 0x04000004, 0x59343002,
+ 0x82183500, 0x00ffffff, 0x497a5a04, 0x4a025c04,
+ 0x00008000, 0x0201f800, 0x001090a8, 0x04020005,
+ 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+ 0x4a01d809, 0x001035d1, 0x1c01f000, 0x59a28c06,
+ 0x0201f800, 0x00020245, 0x02020000, 0x00102310,
+ 0x0201f800, 0x001049e7, 0x04000005, 0x4a034406,
+ 0x00000009, 0x0201f000, 0x0010230c, 0x0201f800,
+ 0x00103a00, 0x04020005, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x497a5a04, 0x4a025c04,
+ 0x00008000, 0x0201f800, 0x00103a00, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x592e5800, 0x0201f800, 0x001090bd, 0x04020005,
+ 0x4a034406, 0x00000003, 0x0201f000, 0x0010230c,
+ 0x4a01d809, 0x001035a3, 0x1c01f000, 0x592c2805,
+ 0x82140d80, 0x01000000, 0x04020005, 0x4a034406,
+ 0x00000004, 0x0201f000, 0x0010230c, 0x42000800,
+ 0x00000008, 0x59a00207, 0x59a01407, 0x900001c0,
+ 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+ 0x800c1d40, 0x832c0400, 0x00000005, 0x0201f800,
+ 0x00103a28, 0x8c142d00, 0x04000003, 0x4a01d809,
+ 0x001035be, 0x1c01f000, 0x4031d800, 0x58ef400b,
+ 0x58ee580e, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x02000000, 0x00102304, 0x812e59c0, 0x02000800,
+ 0x001005d8, 0x42000800, 0x00000008, 0x832c0400,
+ 0x00000005, 0x58ec1007, 0x58ec1808, 0x0201f000,
+ 0x00103a28, 0x592c0005, 0x82000580, 0x01000000,
+ 0x04020005, 0x4a034406, 0x00000004, 0x0201f000,
+ 0x0010230c, 0x59a00207, 0x59a01407, 0x900001c0,
+ 0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
+ 0x800c1d40, 0x42000800, 0x00000006, 0x832c0400,
+ 0x00000006, 0x0201f000, 0x00103a28, 0x59a00a0a,
+ 0x800409c0, 0x02000000, 0x00102310, 0x82040480,
+ 0x000000e7, 0x04001003, 0x42000800, 0x000000e6,
+ 0x59a00207, 0x59a01407, 0x900001c0, 0x80081540,
+ 0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40,
+ 0x83880400, 0x00000000, 0x0201f800, 0x00103a28,
+ 0x4a01d809, 0x001035ff, 0x1c01f000, 0x4031d800,
+ 0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
+ 0x02000000, 0x00102304, 0x58ef400b, 0x59a0020b,
+ 0x8c000500, 0x04000008, 0x83880400, 0x00000000,
+ 0x4803c840, 0x4a03c842, 0x00000006, 0x04011000,
+ 0x497b8885, 0x4a034207, 0x000000e6, 0x0201f000,
+ 0x001022c0, 0x800409c0, 0x04000005, 0x4a034406,
+ 0x00000001, 0x0201f000, 0x0010230c, 0x0401fbe5,
+ 0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
+ 0x0010230c, 0x497a5a04, 0x4a025c04, 0x00008000,
+ 0x59a00406, 0x800001c0, 0x02000000, 0x00102310,
+ 0x82001580, 0x000000ff, 0x04000005, 0x82001480,
+ 0x00000004, 0x02021000, 0x00102310, 0x40001000,
+ 0x0201f800, 0x00101fbf, 0x04020005, 0x4a034406,
+ 0x00000003, 0x0201f000, 0x0010230c, 0x4a01d809,
+ 0x0010363a, 0x1c01f000, 0x592c0005, 0x82000580,
+ 0x01000000, 0x02020000, 0x001022c0, 0x4a034406,
+ 0x00000004, 0x0201f000, 0x0010230c, 0x59a01406,
+ 0x8c081508, 0x04020007, 0x800409c0, 0x04000005,
+ 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+ 0x59a01c07, 0x820c0480, 0x00001000, 0x02021000,
+ 0x00102310, 0x497b2804, 0x497b2805, 0x497b281c,
+ 0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822,
+ 0x497b2823, 0x80000580, 0x0201f800, 0x001015fe,
+ 0x59a80805, 0x8c081500, 0x04000004, 0x82040d40,
+ 0x00000011, 0x0401f004, 0x8c081506, 0x04000002,
+ 0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800,
+ 0x00000001, 0x82081500, 0x000000e0, 0x8008010a,
+ 0x0c020036, 0x0201f800, 0x0010513b, 0x04020009,
+ 0x4a035033, 0x00000001, 0x0201f800, 0x001050a2,
+ 0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb,
+ 0x497b5032, 0x0201f800, 0x00104142, 0x0201f800,
+ 0x00106c55, 0x0201f800, 0x00106ede, 0x0201f800,
+ 0x00106c4b, 0x59a00a07, 0x480788a7, 0x59c400a3,
+ 0x82000500, 0xfeffffff, 0x82000540, 0x80018000,
+ 0x40000800, 0x84040d20, 0x480388a3, 0x480788a3,
+ 0x497b504e, 0x42000800, 0x0000002d, 0x42001000,
+ 0x001041bc, 0x0201f800, 0x00105f69, 0x59a00407,
+ 0x800000c2, 0x800008c4, 0x8005d400, 0x42000000,
+ 0x0000ffff, 0x0201f800, 0x0010513b, 0x04000003,
+ 0x59a00207, 0x80000110, 0x0201f800, 0x00103afc,
+ 0x0201f000, 0x001022c0, 0x0010366d, 0x00103670,
+ 0x00103678, 0x00102310, 0x00103675, 0x00102310,
+ 0x00102310, 0x00102310, 0x836c0580, 0x00000003,
+ 0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
+ 0x0010230c, 0x59a03c06, 0x59a00407, 0x59a04a07,
+ 0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209,
+ 0x902851c0, 0x80285540, 0x0401fb46, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x417a8800, 0x41783000, 0x497b4001, 0x497b4004,
+ 0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04,
+ 0x04020078, 0x0201f800, 0x00020245, 0x0402002a,
+ 0x0201f800, 0x001049e7, 0x04000004, 0x0201f800,
+ 0x001048e3, 0x04020024, 0x8c1c3d00, 0x04000008,
+ 0x59340009, 0x44004000, 0x59340008, 0x80204000,
+ 0x44004000, 0x80204000, 0x0401f007, 0x59340007,
+ 0x44004000, 0x59340006, 0x80204000, 0x44004000,
+ 0x80204000, 0x83440580, 0x000007fe, 0x0400000d,
+ 0x83440580, 0x000007fc, 0x0400000a, 0x0201f800,
+ 0x001049f3, 0x04000003, 0x85468d5e, 0x0401f005,
+ 0x0201f800, 0x00104838, 0x04020002, 0x85468d5e,
+ 0x45444000, 0x85468d1e, 0x80204000, 0x82183400,
+ 0x00000003, 0x81468800, 0x83440480, 0x000007f0,
+ 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
+ 0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
+ 0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
+ 0x42028800, 0x000007fc, 0x82180580, 0x0000000f,
+ 0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006,
+ 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
+ 0x001022c0, 0x4a034004, 0x00000001, 0x49474000,
+ 0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
+ 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
+ 0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800,
+ 0x4000a000, 0x4018b000, 0x0201f800, 0x0010ab17,
+ 0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809,
+ 0x0010372a, 0x1c01f000, 0x4031d800, 0x58ef400b,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+ 0x00102304, 0x59a00004, 0x80000540, 0x04020008,
+ 0x59a28800, 0x59a04002, 0x59a03803, 0x41783000,
+ 0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801,
+ 0x800408c4, 0x48074406, 0x0201f000, 0x001022c0,
+ 0x0201f800, 0x00020245, 0x0402002f, 0x0201f800,
+ 0x001049e7, 0x04000004, 0x0201f800, 0x001048e3,
+ 0x04020029, 0x83440580, 0x000007fe, 0x04000011,
+ 0x83440580, 0x000007fc, 0x0400000e, 0x0201f800,
+ 0x001049f3, 0x04000005, 0x59340403, 0x8400055e,
+ 0x48026c03, 0x0401f007, 0x0201f800, 0x00104838,
+ 0x04020004, 0x59340403, 0x8400055e, 0x48026c03,
+ 0x4134a000, 0x4020a800, 0x4200b000, 0x00000006,
+ 0x0201f800, 0x0010ab17, 0x59340007, 0x4400a800,
+ 0x59340006, 0x4800a801, 0x59340009, 0x4800a802,
+ 0x59340008, 0x4800a803, 0x59340403, 0x8400051e,
+ 0x48026c03, 0x82204400, 0x0000000a, 0x82183400,
+ 0x0000000a, 0x81468800, 0x83440480, 0x000007f0,
+ 0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
+ 0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
+ 0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
+ 0x42028800, 0x000007fc, 0x82180580, 0x0000000a,
+ 0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006,
+ 0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
+ 0x001022c0, 0x4a034004, 0x00000001, 0x49474000,
+ 0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
+ 0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
+ 0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000,
+ 0x0201f800, 0x00100858, 0x4a01d809, 0x001037a1,
+ 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002,
+ 0x82000580, 0x00000200, 0x02000000, 0x00102304,
+ 0x59a00004, 0x80000540, 0x04020008, 0x59a28800,
+ 0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807,
+ 0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4,
+ 0x48074406, 0x0201f000, 0x001022c0, 0x42002800,
+ 0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07,
+ 0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0,
+ 0x82003480, 0x00000020, 0x02001000, 0x00102310,
+ 0x80140480, 0x02001000, 0x00102310, 0x82040500,
+ 0x000000ff, 0x82003480, 0x00000020, 0x02001000,
+ 0x00102310, 0x80140480, 0x02001000, 0x00102310,
+ 0x82080500, 0x0000ff00, 0x840001c0, 0x82003480,
+ 0x00000020, 0x02001000, 0x00102310, 0x80140480,
+ 0x02001000, 0x00102310, 0x82080500, 0x000000ff,
+ 0x82003480, 0x00000020, 0x02001000, 0x00102310,
+ 0x80140480, 0x02001000, 0x00102310, 0x820c0500,
+ 0x0000ff00, 0x840001c0, 0x82003480, 0x00000020,
+ 0x02001000, 0x00102310, 0x80140480, 0x02001000,
+ 0x00102310, 0x820c0500, 0x000000ff, 0x82003480,
+ 0x00000020, 0x02001000, 0x00102310, 0x80140480,
+ 0x02001000, 0x00102310, 0x82100500, 0x0000ff00,
+ 0x840001c0, 0x82003480, 0x00000020, 0x02001000,
+ 0x00102310, 0x80140480, 0x02001000, 0x00102310,
+ 0x82100500, 0x000000ff, 0x82003480, 0x00000020,
+ 0x02001000, 0x00102310, 0x80140480, 0x02001000,
+ 0x00102310, 0x900401c0, 0x80080d40, 0x900c01c0,
+ 0x80101d40, 0x83a83400, 0x0000003a, 0x44043000,
+ 0x80183000, 0x440c3000, 0x0201f000, 0x001022c0,
+ 0x0401f9ec, 0x04020005, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x42000800, 0x0000000c,
+ 0x0401f853, 0x4a01d809, 0x00103820, 0x1c01f000,
+ 0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002,
+ 0x82000580, 0x00000200, 0x02000000, 0x00102304,
+ 0x832ca400, 0x00000004, 0x4200b000, 0x0000000c,
+ 0x40c8a800, 0x0201f800, 0x0010ab17, 0x58c80200,
+ 0x80000540, 0x04000034, 0x58c80400, 0x82000500,
+ 0xfffffffb, 0x04020030, 0x58c80401, 0x80000540,
+ 0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a,
+ 0x58c80202, 0x82000480, 0x0000005c, 0x04001026,
+ 0x0201f800, 0x001063a3, 0x58c80c08, 0x58c80204,
+ 0x80040480, 0x04001020, 0x58c80204, 0x82000480,
+ 0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08,
+ 0x80040902, 0x80040480, 0x04001017, 0x58c80c08,
+ 0x0201f800, 0x001062f1, 0x0400001b, 0x0201f800,
+ 0x001061b9, 0x04020012, 0x4979940b, 0x59c408a3,
+ 0x82040d40, 0x00000002, 0x480788a3, 0x4a038830,
+ 0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202,
+ 0x48030804, 0x0201f800, 0x0010619b, 0x0201f000,
+ 0x001022c0, 0x0201f000, 0x00102310, 0x0201f800,
+ 0x001063f5, 0x0201f800, 0x00106402, 0x0201f800,
+ 0x001062e4, 0x0201f000, 0x0010230c, 0x4c000000,
+ 0x59a01207, 0x59a00407, 0x900811c0, 0x80081540,
+ 0x59a01a09, 0x59a00409, 0x900c19c0, 0x800c1d40,
+ 0x5c000000, 0x0401f1ac, 0x59840000, 0x82000580,
+ 0x00000000, 0x04000054, 0x59840002, 0x8c000504,
+ 0x04000051, 0x84000546, 0x48030802, 0x0201f800,
+ 0x001062e4, 0x59c408a3, 0x82040d00, 0xfffffffd,
+ 0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010ac00,
+ 0x505e6800, 0x813669c0, 0x04000008, 0x5936600e,
+ 0x813261c0, 0x04000005, 0x0201f800, 0x001062d5,
+ 0x02000800, 0x001064ad, 0x805cb800, 0x825c0580,
+ 0x0010b3f0, 0x040207f3, 0x59866003, 0x813261c0,
+ 0x0400000b, 0x59300406, 0x82000580, 0x00000009,
+ 0x02020800, 0x001005d8, 0x5930b800, 0x0201f800,
+ 0x001062c1, 0x405e6000, 0x0401f7f5, 0x497b0803,
+ 0x4200b800, 0x0010b51b, 0x505e6000, 0x813261c0,
+ 0x04000011, 0x59300406, 0x82000580, 0x00000009,
+ 0x0402000d, 0x59300203, 0x82000580, 0x00000004,
+ 0x04020009, 0x59326809, 0x813669c0, 0x02020800,
+ 0x001005d8, 0x0201f800, 0x00100e99, 0x0201f800,
+ 0x001062c1, 0x4578b800, 0x805cb800, 0x825c0580,
+ 0x0010b523, 0x040207e9, 0x42000800, 0x0010b519,
+ 0x49780801, 0x49780800, 0x59a80069, 0x82000400,
+ 0x00000007, 0x48035069, 0x0201f800, 0x001063f5,
+ 0x0201f800, 0x00106402, 0x5c00b800, 0x0201f800,
+ 0x001061b4, 0x0201f000, 0x001022c0, 0x836c0580,
+ 0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+ 0x0201f000, 0x0010230c, 0x59a00407, 0x59a02207,
+ 0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09,
+ 0x901429c0, 0x80142d40, 0x0401f91e, 0x04020005,
+ 0x4a034406, 0x00000002, 0x0201f000, 0x0010230c,
+ 0x417a8800, 0x41781800, 0x497b4001, 0x497b4003,
+ 0x832c3400, 0x00000004, 0x481b4002, 0x41440000,
+ 0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b,
+ 0x0201f800, 0x001049e7, 0x04020008, 0x59340002,
+ 0x48003000, 0x49443001, 0x82183400, 0x00000002,
+ 0x820c1c00, 0x00000002, 0x81468800, 0x83440480,
+ 0x00000800, 0x04000005, 0x820c0480, 0x00000010,
+ 0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006,
+ 0x59a00801, 0x80040902, 0x48074406, 0x0201f000,
+ 0x001022c0, 0x4a034003, 0x00000001, 0x49474000,
+ 0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000,
+ 0x4a001001, 0x00000000, 0x480c1004, 0x59a00002,
+ 0x48001003, 0x48101007, 0x48141008, 0x0201f800,
+ 0x00100858, 0x4a01d809, 0x00103920, 0x1c01f000,
+ 0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x59a00003,
+ 0x80000540, 0x04020008, 0x59a28800, 0x59a03002,
+ 0x41781800, 0x40ec1000, 0x58082007, 0x58082808,
+ 0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406,
+ 0x0201f000, 0x001022c0, 0x800409c0, 0x04000005,
+ 0x4a034406, 0x00000001, 0x0201f000, 0x0010230c,
+ 0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506,
+ 0x04020005, 0x4a034406, 0x00000016, 0x0201f000,
+ 0x0010230c, 0x0401f8bb, 0x04020005, 0x4a034406,
+ 0x00000002, 0x0201f000, 0x0010230c, 0x59a00c06,
+ 0x80040902, 0x59a00407, 0x59a01207, 0x900811c0,
+ 0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
+ 0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8ce,
+ 0x4a01d809, 0x0010395b, 0x1c01f000, 0x4031d800,
+ 0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
+ 0x00000200, 0x02000000, 0x00102304, 0x592c0009,
+ 0x0201f800, 0x00105c9a, 0x02000800, 0x001045a6,
+ 0x02020000, 0x00102310, 0x49474001, 0x481a6802,
+ 0x592c000a, 0x82001d80, 0x70000000, 0x04020007,
+ 0x0401f890, 0x04020011, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x82001d80, 0x72000000,
+ 0x02020000, 0x00102310, 0x0401f886, 0x04020885,
+ 0x04020884, 0x04020005, 0x4a034406, 0x00000002,
+ 0x0201f000, 0x0010230c, 0x58ee580d, 0x4a025c04,
+ 0x00008000, 0x497a5a04, 0x592c3208, 0x80183102,
+ 0x592c1801, 0x4a001805, 0x01000000, 0x0201f800,
+ 0x001090d1, 0x04020005, 0x4a034406, 0x00000003,
+ 0x0201f000, 0x0010230c, 0x4a01d809, 0x00103995,
+ 0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580,
+ 0x01000000, 0x04020005, 0x4a034406, 0x00000004,
+ 0x0201f000, 0x0010230c, 0x832c3c00, 0x00000005,
+ 0x401ca000, 0x401ca800, 0x5820280a, 0x4200b000,
+ 0x00000002, 0x82143580, 0x70000000, 0x04000003,
+ 0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab28,
+ 0x401c0000, 0x58201006, 0x58201807, 0x58202205,
+ 0x80102102, 0x82143580, 0x70000000, 0x04020008,
+ 0x82103480, 0x00000002, 0x02001000, 0x00102310,
+ 0x42000800, 0x00000002, 0x0401f06e, 0x82143580,
+ 0x72000000, 0x02020000, 0x00102310, 0x82103480,
+ 0x0000002a, 0x02001000, 0x00102310, 0x42000800,
+ 0x0000000f, 0x0401f863, 0x4a01d809, 0x001039c9,
+ 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+ 0x00102304, 0x592e5800, 0x832c0c00, 0x00000005,
+ 0x4004a000, 0x4004a800, 0x4200b000, 0x0000000f,
+ 0x0201f800, 0x0010ab28, 0x40ec1000, 0x4a001001,
+ 0x00000000, 0x4a001004, 0x0000000f, 0x48041003,
+ 0x0201f800, 0x00100858, 0x4a01d809, 0x001039e5,
+ 0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e,
+ 0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
+ 0x00102304, 0x832c0c00, 0x00000005, 0x4004a000,
+ 0x4004a800, 0x4200b000, 0x0000000c, 0x0201f800,
+ 0x0010ab28, 0x40ec1000, 0x4a001001, 0x00000000,
+ 0x4a001004, 0x0000000c, 0x48041003, 0x0201f800,
+ 0x00100858, 0x4a01d809, 0x001022b9, 0x1c01f000,
+ 0x0201f800, 0x001007e4, 0x04000010, 0x497a5800,
+ 0x58ec000d, 0x80000540, 0x04020004, 0x492dd80d,
+ 0x492dd80e, 0x0401f007, 0x58ec000e, 0x48025800,
+ 0x82000400, 0x00000001, 0x452c0000, 0x492dd80e,
+ 0x832c0400, 0x00000004, 0x492fc857, 0x4803c857,
+ 0x1c01f000, 0x4d2c0000, 0x48efc857, 0x58ec400d,
+ 0x4823c857, 0x802041c0, 0x04000007, 0x40225800,
+ 0x592c4001, 0x497a5801, 0x0201f800, 0x001007f4,
+ 0x0401f7f8, 0x4979d80d, 0x4979d80e, 0x5c025800,
+ 0x1c01f000, 0x42003000, 0x00000001, 0x0401f003,
+ 0x42003000, 0x00000000, 0x4803c857, 0x4807c857,
+ 0x480bc857, 0x480fc857, 0x481bc857, 0x48efc857,
+ 0x4819d801, 0x800409c0, 0x02000800, 0x001005d8,
+ 0x4805d804, 0x4801d803, 0x4809d807, 0x480dd808,
+ 0x40ec1000, 0x0201f800, 0x00100858, 0x4a01d809,
+ 0x001022b9, 0x1c01f000, 0x80002d80, 0x480bc857,
+ 0x480fc857, 0x4813c857, 0x4817c857, 0x4d2c0000,
+ 0x4da00000, 0x42034000, 0x0010b4a4, 0x59a00017,
+ 0x800001c0, 0x04020013, 0x04006012, 0x480bc020,
+ 0x480fc021, 0x4813c022, 0x4817c023, 0x900811c0,
+ 0x82081540, 0x00000012, 0x480bc011, 0x59e00017,
+ 0x8c000508, 0x04020004, 0x4203e000, 0x30000001,
+ 0x0401f053, 0x4a03c017, 0x00000002, 0x0401f7fb,
+ 0x4c040000, 0x4c1c0000, 0x80000800, 0x48074017,
+ 0x59a0381a, 0x481fc857, 0x801c39c0, 0x04020027,
+ 0x82000480, 0x0000000a, 0x04021010, 0x59a00018,
+ 0x80000000, 0x48034018, 0x59a00219, 0x82000400,
+ 0x00000002, 0x82000c80, 0x00000013, 0x48034219,
+ 0x04001003, 0x497b4219, 0x41780000, 0x59a03816,
+ 0x801c3c00, 0x0401f030, 0x4803c856, 0x0201f800,
+ 0x001007e4, 0x04000007, 0x492f401a, 0x492f401b,
+ 0x412c3800, 0x497b421c, 0x497a5813, 0x0401f026,
+ 0x59880051, 0x80000000, 0x48031051, 0x59a00017,
+ 0x80000040, 0x48034017, 0x59a00219, 0x59a03816,
+ 0x801c3c00, 0x0401f01c, 0x59a0021c, 0x82000400,
+ 0x00000002, 0x82000c80, 0x00000012, 0x04021004,
+ 0x4803421c, 0x801c3c00, 0x0401f013, 0x0201f800,
+ 0x001007e4, 0x0402000b, 0x59880051, 0x80000000,
+ 0x48031051, 0x59a00017, 0x80000040, 0x48034017,
+ 0x4803c856, 0x59a0021c, 0x801c3c00, 0x0401f006,
+ 0x492f401a, 0x492c3813, 0x412c3800, 0x497b421c,
+ 0x497a5813, 0x48083c00, 0x480c3a00, 0x48103c01,
+ 0x48143a01, 0x5c003800, 0x5c000800, 0x5c034000,
+ 0x5c025800, 0x1c01f000, 0x480fc857, 0x4813c857,
+ 0x481bc857, 0x42000000, 0x0010b813, 0x0201f800,
+ 0x0010aa47, 0x801800d0, 0x40002800, 0x42001000,
+ 0x00008014, 0x0401f786, 0x4c000000, 0x599c0017,
+ 0x8c000512, 0x5c000000, 0x1c01f000, 0x4c000000,
+ 0x599c0018, 0x8c00050e, 0x5c000000, 0x1c01f000,
+ 0x59a80821, 0x800409c0, 0x04000005, 0x4a034406,
+ 0x00000001, 0x0201f000, 0x0010230c, 0x836c0580,
+ 0x00000003, 0x04000005, 0x4a034406, 0x00000007,
+ 0x0201f000, 0x0010230c, 0x599c0017, 0x8c00050a,
+ 0x04000005, 0x4a034406, 0x00000008, 0x0201f000,
+ 0x0010230c, 0x59340405, 0x8c000508, 0x04020004,
+ 0x8c00050a, 0x02020000, 0x001034db, 0x497a5a04,
+ 0x497a5805, 0x4a025c04, 0x00008000, 0x0201f800,
+ 0x00109176, 0x04020005, 0x4a034406, 0x00000003,
+ 0x0201f000, 0x0010230c, 0x4a01d809, 0x00103aed,
+ 0x1c01f000, 0x592c0005, 0x82000580, 0x01000000,
+ 0x04020005, 0x4a034406, 0x00000004, 0x0201f000,
+ 0x0010230c, 0x59a28c06, 0x0201f800, 0x00020245,
+ 0x02020000, 0x00102310, 0x0201f000, 0x001034db,
+ 0x82001580, 0x0000ffff, 0x04000009, 0x0201f800,
+ 0x00105c9a, 0x02000800, 0x00020245, 0x0402000c,
+ 0x0201f800, 0x00105fae, 0x0401f009, 0x42028800,
+ 0x000007ef, 0x0201f800, 0x00020245, 0x02000800,
+ 0x00105fae, 0x81468840, 0x040217fb, 0x1c01f000,
+ 0x4803c856, 0x4c0c0000, 0x4d340000, 0x4d440000,
+ 0x42028800, 0x000007fe, 0x0201f800, 0x00020245,
+ 0x04020009, 0x5934180a, 0x820c1d00, 0x00000001,
+ 0x820c1d80, 0x00000001, 0x42001000, 0x0000801b,
+ 0x0401ff1e, 0x5c028800, 0x5c026800, 0x5c001800,
+ 0x1c01f000, 0x599c0017, 0x8c000508, 0x1c01f000,
+ 0x48efc857, 0x04011000, 0x48efc840, 0x4a03c842,
+ 0x00000011, 0x40000000, 0x040117ff, 0x4a01d80f,
+ 0xbeefbeef, 0x1c01f000, 0x497b4000, 0x497b4001,
+ 0x497b4002, 0x497b4003, 0x497b4004, 0x1c01f000,
+ 0x59c400a4, 0x4c580000, 0x4c500000, 0x4c540000,
+ 0x82000500, 0x0000000f, 0x82000480, 0x00000007,
+ 0x0400100a, 0x82006c80, 0x00000006, 0x02021800,
+ 0x001005d8, 0x0c01f807, 0x5c00a800, 0x5c00a000,
+ 0x5c00b000, 0x1c01f000, 0x0401f906, 0x0401f7fb,
+ 0x00103b51, 0x00103b57, 0x00103b7c, 0x00103b9e,
+ 0x00103c59, 0x59c40806, 0x8c040d00, 0x04020003,
+ 0x84040d40, 0x48078806, 0x1c01f000, 0x59c40005,
+ 0x8c000534, 0x02020000, 0x0010429e, 0x4a038805,
+ 0xffffffff, 0x42006000, 0x00020000, 0x0201f800,
+ 0x00104282, 0x59a80015, 0x82000500, 0xfffffffa,
+ 0x84000542, 0x48035015, 0x497b5026, 0x42000800,
+ 0x0010be21, 0x45780800, 0x497b5013, 0x42006000,
+ 0xffefffff, 0x42006800, 0x40000000, 0x0201f800,
+ 0x0010427d, 0x59c40006, 0x82000500, 0xffffff0f,
+ 0x48038806, 0x42000800, 0x00000010, 0x42001000,
+ 0x001041f3, 0x0201f800, 0x00105f83, 0x0401f001,
+ 0x42006000, 0xffffffff, 0x42006800, 0x00800000,
+ 0x0201f800, 0x0010427d, 0x4200b000, 0x000000c8,
+ 0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
+ 0x0000000a, 0x0400000f, 0x8058b040, 0x040207f9,
+ 0x497b5014, 0x42006000, 0xbf7fffff, 0x42006800,
+ 0x00018000, 0x0201f800, 0x0010427d, 0x42006000,
+ 0xfffeffff, 0x41786800, 0x0201f000, 0x0010427d,
+ 0x497b5014, 0x4a035012, 0x00000000, 0x80000580,
+ 0x0201f000, 0x00104289, 0x4a038805, 0xffffffff,
+ 0x59a80012, 0x82000c80, 0x00000004, 0x02021800,
+ 0x001005d8, 0x0c01f001, 0x00103ba9, 0x00103bd6,
+ 0x00103c4f, 0x4803c856, 0x59c400a3, 0x8400051e,
+ 0x480388a3, 0x4a035012, 0x00000001, 0x59c40008,
+ 0x8400054e, 0x48038808, 0x0201f800, 0x00104263,
+ 0x42007800, 0x0010b54c, 0x4a007806, 0x11010000,
+ 0x4200a000, 0x0010b402, 0x4200a800, 0x0010b553,
+ 0x4200b000, 0x00000002, 0x0201f800, 0x0010ab17,
+ 0x497b8802, 0x42000800, 0x00000003, 0x497b504a,
+ 0x0201f800, 0x0010416e, 0x4a03504a, 0x00000001,
+ 0x497b5016, 0x0201f800, 0x00104290, 0x42006000,
+ 0xffffffff, 0x42006800, 0x00080000, 0x0201f800,
+ 0x0010427d, 0x42006000, 0xfff7ffff, 0x41786800,
+ 0x0201f000, 0x0010427d, 0x59a80016, 0x497b5016,
+ 0x80002540, 0x04000066, 0x59c40004, 0x82000500,
+ 0x00000003, 0x04020071, 0x59a80815, 0x8c040d02,
+ 0x0400004b, 0x82100580, 0x0000000c, 0x0402004f,
+ 0x82100400, 0x00000018, 0x8000b104, 0x41cc1000,
+ 0x42001800, 0x0010b54c, 0x50080800, 0x500c0000,
+ 0x80040580, 0x0402001a, 0x80081000, 0x800c1800,
+ 0x8058b040, 0x040207f9, 0x0201f800, 0x00104290,
+ 0x42006000, 0xffffffff, 0x42006800, 0x00500000,
+ 0x0201f800, 0x0010427d, 0x4a035012, 0x00000002,
+ 0x4a035014, 0x00000002, 0x42000800, 0x000007d0,
+ 0x42001000, 0x00104148, 0x0201f800, 0x0010606e,
+ 0x0201f800, 0x00104263, 0x0401f048, 0x59cc0806,
+ 0x82040d80, 0x11010000, 0x04020028, 0x59cc0800,
+ 0x82040500, 0x00ffffff, 0x0400001a, 0x82000580,
+ 0x000000ef, 0x04020017, 0x59cc0801, 0x82040500,
+ 0x00ffffff, 0x82000580, 0x000000ef, 0x04020011,
+ 0x83cca400, 0x00000007, 0x4200a800, 0x0010b402,
+ 0x4200b000, 0x00000002, 0x50500800, 0x50540000,
+ 0x80040480, 0x04001007, 0x04020010, 0x8050a000,
+ 0x8054a800, 0x8058b040, 0x040207f8, 0x0401f00b,
+ 0x59a80015, 0x84000502, 0x48035015, 0x41cca000,
+ 0x4200a800, 0x0010b54c, 0x4200b000, 0x00000009,
+ 0x0201f800, 0x0010ab17, 0x0201f800, 0x00104290,
+ 0x42006000, 0xffffffff, 0x42006800, 0x00080000,
+ 0x0201f800, 0x0010427d, 0x42006000, 0xfff7ffff,
+ 0x41786800, 0x0201f800, 0x0010427d, 0x42006000,
+ 0xffffffff, 0x42006800, 0x00004000, 0x0201f800,
+ 0x0010427d, 0x59c40004, 0x82000500, 0x00000003,
+ 0x04020006, 0x497b5016, 0x42000800, 0x00000003,
+ 0x0201f000, 0x0010416e, 0x1c01f000, 0x1c01f000,
+ 0x59a80014, 0x82006d80, 0x0000000f, 0x04000005,
+ 0x82000580, 0x0000001b, 0x02020800, 0x00104139,
+ 0x1c01f000, 0x59a80015, 0x84000506, 0x48035015,
+ 0x497b504a, 0x59a80014, 0x82000c80, 0x0000001e,
+ 0x02021800, 0x001005d8, 0x0c01f001, 0x00103c97,
+ 0x00103cac, 0x00103cd5, 0x00103cf0, 0x00103d14,
+ 0x00103d45, 0x00103d68, 0x00103d9b, 0x00103dbe,
+ 0x00103de4, 0x00103e21, 0x00103e48, 0x00103e5f,
+ 0x00103e71, 0x00103e8a, 0x00103ea0, 0x00103ea5,
+ 0x00103ecd, 0x00103ef0, 0x00103f16, 0x00103f39,
+ 0x00103f6c, 0x00103fae, 0x00103fd8, 0x00103ff0,
+ 0x00104030, 0x00104049, 0x0010405c, 0x0010405d,
+ 0x4803c856, 0x4202d800, 0x00000007, 0x0201f800,
+ 0x0010513b, 0x04000007, 0x42006000, 0xffffffd7,
+ 0x41786800, 0x0201f800, 0x0010427d, 0x0401f00b,
+ 0x59c40006, 0x82000500, 0xffffff0f, 0x48038806,
+ 0x42001000, 0x000000f0, 0x0201f800, 0x0010193d,
+ 0x0201f800, 0x00105098, 0x1c01f000, 0x4803c856,
+ 0x42006000, 0xbf7fffff, 0x42006800, 0x00400000,
+ 0x0201f800, 0x0010427d, 0x4a035014, 0x00000001,
+ 0x42001000, 0x001041f3, 0x0201f800, 0x00105fa4,
+ 0x0201f800, 0x001041f8, 0x42000800, 0x000007d0,
+ 0x42001000, 0x00104148, 0x0201f000, 0x0010606e,
+ 0x59a80016, 0x82000580, 0x00000014, 0x04020025,
+ 0x4803c857, 0x42006000, 0xffbfffff, 0x41786800,
+ 0x0201f800, 0x0010427d, 0x59c40004, 0x82000500,
+ 0x00000003, 0x0402001b, 0x59cc1006, 0x82081580,
+ 0x11020000, 0x04020016, 0x59cc1007, 0x8c08153e,
+ 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008,
+ 0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47,
+ 0x59a80015, 0x84000544, 0x48035015, 0x42001000,
+ 0x00104148, 0x0201f800, 0x00105f90, 0x4a035014,
+ 0x00000010, 0x0401f9d4, 0x0401f002, 0x497b5016,
+ 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000003,
+ 0x42006000, 0xbf3fffff, 0x42006800, 0x00100000,
+ 0x0201f800, 0x0010427d, 0x42001000, 0x001041f3,
+ 0x0201f800, 0x00105fa4, 0x0201f800, 0x001041f8,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x42007800, 0x0010b552, 0x46007800, 0x11020000,
+ 0x42000800, 0x00000005, 0x0201f000, 0x0010416e,
+ 0x59a80016, 0x80000540, 0x04000021, 0x4803c857,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x59a80016, 0x82000580, 0x00000014, 0x04020016,
+ 0x59cc1006, 0x82081580, 0x11020000, 0x04020012,
+ 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
+ 0x8c000504, 0x04020008, 0x42000000, 0x0010b83f,
+ 0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544,
+ 0x48035015, 0x4a035014, 0x00000004, 0x0401f805,
+ 0x0401f003, 0x0201f800, 0x00104139, 0x1c01f000,
+ 0x4803c856, 0x4a035014, 0x00000005, 0x83cca400,
+ 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x42007800,
+ 0x0010b552, 0x46007800, 0x11030000, 0x0201f800,
+ 0x0010413e, 0x04020014, 0x59a80015, 0x8c000500,
+ 0x04020011, 0x59a80810, 0x82040580, 0x00ffffff,
+ 0x0400000d, 0x82040d00, 0x000000ff, 0x82040400,
+ 0x0010210e, 0x50000800, 0x80040910, 0x42001000,
+ 0x00000004, 0x0401fb9b, 0x0400000b, 0x0201f800,
+ 0x0010420d, 0x4200b000, 0x00000004, 0x83cca400,
+ 0x00000007, 0x4200a800, 0x0010b553, 0x0201f800,
+ 0x0010ab17, 0x42000800, 0x00000005, 0x0201f000,
+ 0x0010416e, 0x59a80016, 0x80000540, 0x04000020,
+ 0x4803c857, 0x42001000, 0x00104148, 0x0201f800,
+ 0x00105f90, 0x59a80016, 0x82000580, 0x00000014,
+ 0x04020016, 0x59cc1006, 0x82081580, 0x11030000,
+ 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
+ 0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+ 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+ 0x84000544, 0x48035015, 0x4a035014, 0x00000006,
+ 0x0401f804, 0x0401f002, 0x0401fbd3, 0x1c01f000,
+ 0x4803c856, 0x4a035014, 0x00000007, 0x83cca400,
+ 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x42007800,
+ 0x0010b552, 0x46007800, 0x11040000, 0x0401fbc7,
+ 0x04020020, 0x59a80015, 0x8c000500, 0x0402001d,
+ 0x599c0017, 0x8c000500, 0x0400001a, 0x599c1402,
+ 0x82080480, 0x0000007f, 0x02021800, 0x001005d8,
+ 0x4c080000, 0x82081400, 0x0010210e, 0x50081000,
+ 0x82081500, 0x000000ff, 0x480b5010, 0x42000800,
+ 0x00000003, 0x0201f800, 0x00106c78, 0x5c000800,
+ 0x42001000, 0x00000004, 0x0401fb3e, 0x04000005,
+ 0x0401fd2b, 0x04000003, 0x0201f800, 0x001015fe,
+ 0x42000800, 0x00000005, 0x0401f3d4, 0x59a80016,
+ 0x80000540, 0x04000020, 0x4803c857, 0x42001000,
+ 0x00104148, 0x0201f800, 0x00105f90, 0x59a80016,
+ 0x82000580, 0x00000014, 0x04020016, 0x59cc1006,
+ 0x82081580, 0x11040000, 0x04020012, 0x59cc1007,
+ 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
+ 0x04020008, 0x42000000, 0x0010b83f, 0x0201f800,
+ 0x0010aa47, 0x59a80015, 0x84000544, 0x48035015,
+ 0x4a035014, 0x00000008, 0x0401f804, 0x0401f002,
+ 0x0401fb7d, 0x1c01f000, 0x4803c856, 0x4a035014,
+ 0x00000009, 0x83cca400, 0x00000006, 0x4200a800,
+ 0x0010b552, 0x4200b000, 0x00000005, 0x0201f800,
+ 0x0010ab17, 0x42007800, 0x0010b552, 0x46007800,
+ 0x11050100, 0x0401fb71, 0x0402000a, 0x59a80015,
+ 0x8c000500, 0x04020007, 0x0401fa8c, 0x04020005,
+ 0x82000540, 0x00000001, 0x0201f800, 0x001015fe,
+ 0x42000800, 0x00000005, 0x0401fb94, 0x0401fb63,
+ 0x04020ea4, 0x4d3c0000, 0x42027800, 0x00000001,
+ 0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000,
+ 0x59a80016, 0x80000540, 0x0400003a, 0x4803c857,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x59a80016, 0x82000580, 0x00000014, 0x04020030,
+ 0x59cc1006, 0x82080500, 0x11050000, 0x82000580,
+ 0x11050000, 0x0402002a, 0x8c081510, 0x04000014,
+ 0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
+ 0x8c000504, 0x04020008, 0x42000000, 0x0010b83f,
+ 0x0201f800, 0x0010aa47, 0x59a80015, 0x84000544,
+ 0x48035015, 0x4a035013, 0x00000001, 0x4a035014,
+ 0x0000000a, 0x0401f818, 0x0401f016, 0x80000540,
+ 0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b,
+ 0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+ 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+ 0x84000544, 0x48035015, 0x497b5013, 0x4a035014,
+ 0x0000000e, 0x0401f86d, 0x0401f002, 0x0401fb1a,
+ 0x1c01f000, 0x4803c856, 0x4a035014, 0x0000000b,
+ 0x42001000, 0x0010b553, 0x4008a800, 0x4200b000,
+ 0x00000020, 0x4600a800, 0xffffffff, 0x8054a800,
+ 0x8058b040, 0x040207fc, 0x42007800, 0x0010b552,
+ 0x46007800, 0x11060000, 0x42001000, 0x0010b553,
+ 0x0401fb0a, 0x04000005, 0x50080000, 0x46001000,
+ 0x00ffffff, 0x0401f00c, 0x50080800, 0x82040d00,
+ 0x0000ffff, 0x59a80010, 0x82000500, 0x000000ff,
+ 0x82000540, 0x00000100, 0x800000e0, 0x80040d40,
+ 0x44041000, 0x42000800, 0x00000021, 0x0401f327,
+ 0x59a80016, 0x80000540, 0x04000014, 0x4803c857,
+ 0x59a80016, 0x42001000, 0x00104148, 0x0201f800,
+ 0x00105f90, 0x59a80016, 0x82000580, 0x00000084,
+ 0x04020009, 0x59cc1006, 0x82081580, 0x11060000,
+ 0x04020005, 0x4a035014, 0x0000000c, 0x0401f804,
+ 0x0401f002, 0x0401fadc, 0x1c01f000, 0x4803c856,
+ 0x4a035014, 0x0000000d, 0x83cca400, 0x00000006,
+ 0x4200a800, 0x0010b552, 0x4200b000, 0x00000021,
+ 0x0201f800, 0x0010ab17, 0x42007800, 0x0010b552,
+ 0x46007800, 0x11070000, 0x42000800, 0x00000021,
+ 0x0401f2fe, 0x59a80016, 0x80000540, 0x04000016,
+ 0x4803c857, 0x59a80016, 0x42001000, 0x00104148,
+ 0x0201f800, 0x00105f90, 0x82000580, 0x00000084,
+ 0x0402000c, 0x59cc1006, 0x82081580, 0x11070000,
+ 0x04020008, 0x4a035013, 0x00000001, 0x0401fa91,
+ 0x4a035014, 0x0000000e, 0x0401f804, 0x0401f002,
+ 0x0401fab1, 0x1c01f000, 0x4803c856, 0x82040d40,
+ 0x00000001, 0x0401fbfc, 0x4a035014, 0x0000000f,
+ 0x497b5016, 0x42006000, 0xffffffff, 0x42006800,
+ 0x00300000, 0x0401fbe8, 0x42006000, 0xffdfffff,
+ 0x41786800, 0x0401fbe4, 0x42000800, 0x000007d0,
+ 0x42001000, 0x00104148, 0x0201f000, 0x00105f69,
+ 0x4803c856, 0x59a80016, 0x80000540, 0x04020296,
+ 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000011,
+ 0x83cca400, 0x00000006, 0x4200a800, 0x0010b552,
+ 0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17,
+ 0x4200a800, 0x0010b552, 0x4600a800, 0x11020000,
+ 0x0401fa8a, 0x04020015, 0x59a80010, 0x82000d00,
+ 0xffff0000, 0x04000011, 0x82000500, 0x000000ff,
+ 0x0400000e, 0x82000c00, 0x0010210e, 0x50040800,
+ 0x80040910, 0x82040580, 0x0000007e, 0x04000007,
+ 0x82040580, 0x00000080, 0x04000004, 0x42001000,
+ 0x00000004, 0x0401fa07, 0x42000800, 0x00000005,
+ 0x0401f2a2, 0x59a80016, 0x80000540, 0x04000020,
+ 0x4803c857, 0x42001000, 0x00104148, 0x0201f800,
+ 0x00105f90, 0x59a80016, 0x82000580, 0x00000014,
+ 0x04020016, 0x59cc1006, 0x82081580, 0x11030000,
+ 0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
+ 0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+ 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+ 0x84000544, 0x48035015, 0x4a035014, 0x00000012,
+ 0x0401f804, 0x0401f002, 0x0401fa4b, 0x1c01f000,
+ 0x4803c856, 0x4a035014, 0x00000013, 0x83cca400,
+ 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x4200a800,
+ 0x0010b552, 0x4600a800, 0x11030000, 0x0401fa3f,
+ 0x04020013, 0x59a80015, 0x8c000500, 0x04020010,
+ 0x59a80810, 0x82040580, 0x00ffffff, 0x0400000c,
+ 0x82040d00, 0x000000ff, 0x82040400, 0x0010210e,
+ 0x50000800, 0x80040910, 0x42001000, 0x00000004,
+ 0x0401f9c0, 0x04000002, 0x0401fafb, 0x42000800,
+ 0x00000005, 0x0401f259, 0x59a80016, 0x80000540,
+ 0x04000020, 0x4803c857, 0x42001000, 0x00104148,
+ 0x0201f800, 0x00105f90, 0x59a80016, 0x82000580,
+ 0x00000014, 0x04020016, 0x59cc1006, 0x82081580,
+ 0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e,
+ 0x0400000b, 0x59a80015, 0x8c000504, 0x04020008,
+ 0x42000000, 0x0010b83f, 0x0201f800, 0x0010aa47,
+ 0x59a80015, 0x84000544, 0x48035015, 0x4a035014,
+ 0x00000014, 0x0401f804, 0x0401f002, 0x0401fa02,
+ 0x1c01f000, 0x4803c856, 0x4a035014, 0x00000015,
+ 0x83cca400, 0x00000006, 0x4200a800, 0x0010b552,
+ 0x4200b000, 0x00000005, 0x0201f800, 0x0010ab17,
+ 0x4200a800, 0x0010b552, 0x4600a800, 0x11040000,
+ 0x0401f9f6, 0x04020020, 0x59a80015, 0x8c000500,
+ 0x0402001d, 0x599c0017, 0x8c000500, 0x0400001a,
+ 0x599c1402, 0x82080480, 0x0000007f, 0x02021800,
+ 0x001005d8, 0x4c080000, 0x82081400, 0x0010210e,
+ 0x50081000, 0x82081500, 0x000000ff, 0x480b5010,
+ 0x42000800, 0x00000003, 0x0201f800, 0x00106c78,
+ 0x5c000800, 0x42001000, 0x00000004, 0x0401f96d,
+ 0x04000005, 0x0201f800, 0x00103abf, 0x02020800,
+ 0x001015fe, 0x42000800, 0x00000005, 0x0401f203,
+ 0x59a80016, 0x80000540, 0x0400003f, 0x4803c857,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x59a80016, 0x82000580, 0x00000014, 0x04020035,
+ 0x59cc1006, 0x82080500, 0x11050000, 0x82000580,
+ 0x11050000, 0x0402002f, 0x8c081510, 0x04000010,
+ 0x0401fb09, 0x59cc1007, 0x8c08153e, 0x0400000b,
+ 0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
+ 0x0010b83f, 0x0201f800, 0x0010aa47, 0x59a80015,
+ 0x84000544, 0x48035015, 0x0401f013, 0x59cc1007,
+ 0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
+ 0x04020008, 0x42000000, 0x0010b83f, 0x0201f800,
+ 0x0010aa47, 0x59a80015, 0x84000544, 0x48035015,
+ 0x82000540, 0x00000001, 0x0401faeb, 0x497b5013,
+ 0x0401f003, 0x4a035013, 0x00000001, 0x59cc1007,
+ 0x8c08153c, 0x04000003, 0x4a035026, 0x00000008,
+ 0x4a035014, 0x00000016, 0x0401f804, 0x0401f002,
+ 0x0401f98d, 0x1c01f000, 0x4803c856, 0x83cca400,
+ 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x4a035014,
+ 0x00000017, 0x59a80013, 0x8c000500, 0x04000006,
+ 0x42001000, 0x0010b552, 0x46001000, 0x11050100,
+ 0x0401f003, 0x4a035014, 0x0000001b, 0x0401f97b,
+ 0x0402000a, 0x59a80015, 0x8c000500, 0x04020007,
+ 0x0401f896, 0x04020005, 0x82000540, 0x00000001,
+ 0x0201f800, 0x001015fe, 0x42000800, 0x00000005,
+ 0x0401f99e, 0x4d3c0000, 0x42027800, 0x00000001,
+ 0x0201f800, 0x00109874, 0x5c027800, 0x1c01f000,
+ 0x59a80016, 0x80000540, 0x04000015, 0x4803c857,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x59a80016, 0x82000580, 0x00000084, 0x0402000b,
+ 0x59cc1006, 0x82081580, 0x11060000, 0x04020007,
+ 0x80000580, 0x0401faa0, 0x4a035014, 0x00000018,
+ 0x0401f804, 0x0401f002, 0x0401f94b, 0x1c01f000,
+ 0x4803c856, 0x4a035014, 0x00000019, 0x83cca400,
+ 0x00000006, 0x4200a800, 0x0010b552, 0x4200b000,
+ 0x00000021, 0x0201f800, 0x0010ab17, 0x42003800,
+ 0x0010b553, 0x0401f941, 0x04020018, 0x401c2800,
+ 0x50141000, 0x80080130, 0x80000000, 0x40001800,
+ 0x82081500, 0x00ffffff, 0x800000f0, 0x80080540,
+ 0x44002800, 0x59a80810, 0x82040d00, 0x000000ff,
+ 0x400c1000, 0x80081104, 0x82082400, 0x0010b553,
+ 0x50101000, 0x820c0500, 0x00000003, 0x0c01f806,
+ 0x80081540, 0x44082000, 0x42000800, 0x00000021,
+ 0x0401f156, 0x0010401d, 0x00104022, 0x00104027,
+ 0x0010402c, 0x800408f0, 0x40040000, 0x82081500,
+ 0x00ffffff, 0x1c01f000, 0x800408e0, 0x40040000,
+ 0x82081500, 0xff00ffff, 0x1c01f000, 0x800408d0,
+ 0x40040000, 0x82081500, 0xffff00ff, 0x1c01f000,
+ 0x40040000, 0x82081500, 0xffffff00, 0x1c01f000,
+ 0x59a80016, 0x80000540, 0x04000016, 0x4803c857,
+ 0x42001000, 0x00104148, 0x0201f800, 0x00105f90,
+ 0x59a80016, 0x82000580, 0x00000084, 0x0402000c,
+ 0x59cc1006, 0x82081580, 0x11070000, 0x04020008,
+ 0x4a035013, 0x00000001, 0x0401f8d2, 0x4a035014,
+ 0x0000001a, 0x0401f804, 0x0401f002, 0x0401f8f2,
+ 0x1c01f000, 0x82000540, 0x00000001, 0x0401fa3e,
+ 0x4a035014, 0x0000001b, 0x83cca400, 0x00000006,
+ 0x4200a800, 0x0010b552, 0x59a82016, 0x40100000,
+ 0x8000b104, 0x40580800, 0x5450a800, 0x8050a000,
+ 0x8054a800, 0x8058b040, 0x040207fc, 0x0401f113,
+ 0x1c01f000, 0x1c01f000, 0x4803c856, 0x42003000,
+ 0x00000004, 0x42004000, 0x0010b553, 0x599c2817,
+ 0x8c142d14, 0x0402001f, 0x42001000, 0x00000003,
+ 0x40200000, 0x80080400, 0x50000800, 0x82042580,
+ 0xffffffff, 0x04020005, 0x80081040, 0x80183040,
+ 0x040207f8, 0x0401f05e, 0x800811c0, 0x04020006,
+ 0x82042580, 0x3fffffff, 0x04000058, 0x82040d40,
+ 0xc0000000, 0x4200b000, 0x00000020, 0x42001800,
+ 0x00000001, 0x40042000, 0x80102102, 0x04021021,
+ 0x800c18c2, 0x8058b040, 0x040207fc, 0x0401f04b,
+ 0x41781000, 0x40200000, 0x80080400, 0x50000800,
+ 0x82042580, 0xffffffff, 0x04020005, 0x80081000,
+ 0x80183040, 0x040207f8, 0x0401f040, 0x800811c0,
+ 0x04020003, 0x82040d40, 0xc0000000, 0x4200b000,
+ 0x00000001, 0x42001800, 0x80000000, 0x40042000,
+ 0x801020c2, 0x04021007, 0x800c1902, 0x8058b000,
+ 0x82580480, 0x00000021, 0x040017fa, 0x0401f02f,
+ 0x40200000, 0x80082400, 0x50100000, 0x800c0540,
+ 0x44002000, 0x59a80015, 0x84000540, 0x48035015,
+ 0x40580000, 0x42002800, 0x00000020, 0x80142c80,
+ 0x40080000, 0x42003800, 0x00000003, 0x801c0480,
+ 0x800000ca, 0x80142d40, 0x82144c00, 0x0010210e,
+ 0x50242800, 0x82142d00, 0x000000ff, 0x48175010,
+ 0x4c040000, 0x40140800, 0x0201f800, 0x001015eb,
+ 0x5c000800, 0x40001800, 0x500c0000, 0x80100540,
+ 0x44001800, 0x59a80015, 0x84000540, 0x48035015,
+ 0x4200a800, 0x0010b553, 0x4020a000, 0x4200b000,
+ 0x00000004, 0x0201f800, 0x0010ab17, 0x82000540,
+ 0x00000001, 0x0401f002, 0x80000580, 0x1c01f000,
+ 0x4807c857, 0x480bc857, 0x4008b000, 0x83cca400,
+ 0x00000007, 0x4200a800, 0x0010b553, 0x40541000,
+ 0x0201f800, 0x0010ab17, 0x40041800, 0x41782000,
+ 0x42000000, 0x00000003, 0x820c1c80, 0x00000020,
+ 0x04001004, 0x80102000, 0x80000040, 0x0401f7fb,
+ 0x40041800, 0x801021c0, 0x04000005, 0x820c1c80,
+ 0x00000020, 0x80102040, 0x040207fd, 0x42002000,
+ 0x00000001, 0x800c19c0, 0x04000004, 0x801020c2,
+ 0x800c1840, 0x040207fe, 0x80083c00, 0x83cc2c00,
+ 0x00000007, 0x80142c00, 0x50140000, 0x80102d00,
+ 0x04020012, 0x80100540, 0x44003800, 0x82042400,
+ 0x0010210e, 0x50102800, 0x82142d00, 0x000000ff,
+ 0x48175010, 0x4c040000, 0x40140800, 0x0201f800,
+ 0x001015eb, 0x5c000800, 0x59a80015, 0x84000540,
+ 0x48035015, 0x80000580, 0x1c01f000, 0x4807c856,
+ 0x42001000, 0x00008017, 0x59a8184e, 0x0201f800,
+ 0x0010aa4f, 0x0201f800, 0x00103a3e, 0x1c01f000,
+ 0x4807c856, 0x4200b000, 0x00000020, 0x83cca400,
+ 0x00000007, 0x4200a800, 0x0010be21, 0x0201f000,
+ 0x0010ab28, 0x4807c856, 0x0201f800, 0x00106ede,
+ 0x42000800, 0x000000f7, 0x0401f8de, 0x497b2804,
+ 0x497b2805, 0x497b281c, 0x497b281d, 0x4202d800,
+ 0x00000001, 0x42006000, 0xbf7fffff, 0x42006800,
+ 0x00018000, 0x0401f950, 0x42006000, 0xfffeffff,
+ 0x41786800, 0x0401f94c, 0x497b504e, 0x42000800,
+ 0x0000002d, 0x42001000, 0x001041bc, 0x0201f000,
+ 0x00105f69, 0x4807c856, 0x0401ffe3, 0x497b5014,
+ 0x497b5016, 0x1c01f000, 0x4807c856, 0x59a80005,
+ 0x8c000506, 0x1c01f000, 0x4807c856, 0x42006000,
+ 0xffffffff, 0x42006800, 0x00000028, 0x0401f136,
+ 0x4807c856, 0x0401ffc2, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500,
+ 0x0000000f, 0x82000580, 0x00000002, 0x0402000a,
+ 0x42006000, 0xffffffff, 0x42006800, 0x00200000,
+ 0x0401f921, 0x42006000, 0xffdfffff, 0x41786800,
+ 0x0401f91d, 0x497b5014, 0x42000800, 0x000000f7,
+ 0x0401f89c, 0x59c400a3, 0x82000500, 0xbf20bfff,
+ 0x82000540, 0x0001c000, 0x480388a3, 0x84000520,
+ 0x480388a3, 0x1c01f000, 0x497b5016, 0x59b400f5,
+ 0x8c000500, 0x04020004, 0x82000540, 0x00000001,
+ 0x480368f5, 0x800400c4, 0x82000400, 0x00002000,
+ 0x4803910a, 0x59b400f6, 0x82000500, 0x00000018,
+ 0x040207fd, 0x4a0368f0, 0x0010b54b, 0x42000000,
+ 0x0010b552, 0x480368f1, 0x82040400, 0x0000dc00,
+ 0x480368f3, 0x59c400a4, 0x82000500, 0x0000000f,
+ 0x82000580, 0x00000008, 0x04020017, 0x4c5c0000,
+ 0x4c600000, 0x59c4b805, 0x8c5cbd3a, 0x04020005,
+ 0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+ 0x4a038805, 0x02000000, 0x0201f800, 0x001019fe,
+ 0x4000c000, 0x0201f800, 0x00101963, 0x4202d800,
+ 0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800,
+ 0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2,
+ 0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80,
+ 0x0000000b, 0x04020005, 0x59a80814, 0x82040d40,
+ 0x00002000, 0x0401f004, 0x59a80812, 0x82040d40,
+ 0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0,
+ 0x04020007, 0x42000800, 0x000007d0, 0x42001000,
+ 0x00104148, 0x0201f800, 0x0010606e, 0x1c01f000,
+ 0x4807c856, 0x0401ff4e, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x59c400a4, 0x82000500,
+ 0x0000000f, 0x82000580, 0x00000002, 0x0402000a,
+ 0x42006000, 0xffffffff, 0x42006800, 0x00200000,
+ 0x0401f8ad, 0x42006000, 0xffdfffff, 0x41786800,
+ 0x0401f8a9, 0x0201f800, 0x00105141, 0x04000014,
+ 0x0201f800, 0x00105151, 0x04020011, 0x4a035032,
+ 0x0000aaaa, 0x4c040000, 0x0201f800, 0x0010162a,
+ 0x59a8002a, 0x82000500, 0xffff0000, 0x80040540,
+ 0x4803502a, 0x5c000800, 0x4a035033, 0x00000000,
+ 0x0201f800, 0x001050a2, 0x0401f008, 0x4a03504c,
+ 0x00000005, 0x42000000, 0x00000001, 0x0201f800,
+ 0x00101590, 0x0401ff2c, 0x1c01f000, 0x0401f805,
+ 0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f086,
+ 0x0201f800, 0x00105151, 0x04020005, 0x59c40006,
+ 0x82000540, 0x000000f0, 0x48038806, 0x1c01f000,
+ 0x800408d0, 0x59a80015, 0x8c000506, 0x04000006,
+ 0x59a80010, 0x82000500, 0x000000ff, 0x80040540,
+ 0x0401f003, 0x82040540, 0x000000f7, 0x480388a7,
+ 0x1c01f000, 0x4807c856, 0x42000000, 0x0010b83b,
+ 0x0201f800, 0x0010aa47, 0x42003000, 0x00000005,
+ 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d,
+ 0x42027800, 0x00000002, 0x0401f038, 0x4807c856,
+ 0x42000000, 0x0010b86b, 0x0201f800, 0x0010aa47,
+ 0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000,
+ 0x42003000, 0x0000000f, 0x42027800, 0x00000002,
+ 0x0401f02a, 0x4807c856, 0x42000000, 0x0010b86a,
+ 0x0201f800, 0x0010aa47, 0x42003000, 0x00000003,
+ 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e,
+ 0x42027800, 0x00000202, 0x0401f01c, 0x4807c856,
+ 0x42000000, 0x0010b869, 0x0201f800, 0x0010aa47,
+ 0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000,
+ 0x42003000, 0x00000010, 0x42027800, 0x00000202,
+ 0x0401f00e, 0x4807c856, 0x42000000, 0x0010b83e,
+ 0x0201f800, 0x0010aa47, 0x42003000, 0x00000001,
+ 0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c,
+ 0x42027800, 0x00000202, 0x42001800, 0x0000ffff,
+ 0x42002000, 0x00000007, 0x0201f800, 0x00103aae,
+ 0x5c003000, 0x4d400000, 0x0201f800, 0x0010a95d,
+ 0x42028000, 0x0000002a, 0x0201f800, 0x00101fe5,
+ 0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856,
+ 0x04011000, 0x4a03c840, 0x0010b54b, 0x4a03c842,
+ 0x00000040, 0x40000000, 0x040117ff, 0x42007800,
+ 0x0010b54b, 0x46007800, 0x00000011, 0x803c7800,
+ 0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef,
+ 0x4a007802, 0x01380000, 0x4a007803, 0x00000000,
+ 0x4a007804, 0xffffffff, 0x4a007805, 0x00000000,
+ 0x1c01f000, 0x59c400a3, 0x80300500, 0x80340540,
+ 0x480388a3, 0x1c01f000, 0x4833c857, 0x59c400a3,
+ 0x80300540, 0x480388a3, 0x80300580, 0x480388a3,
+ 0x1c01f000, 0x4803c856, 0x04000004, 0x4a03504b,
+ 0x00000001, 0x0401f002, 0x497b504b, 0x1c01f000,
+ 0x4803c856, 0x59c80002, 0x80000540, 0x0400000a,
+ 0x80000040, 0x04000008, 0x4a039005, 0x00000140,
+ 0x42000000, 0x00000006, 0x80000040, 0x040207ff,
+ 0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000,
+ 0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005,
+ 0x42000000, 0x0010b818, 0x0201f800, 0x0010aa47,
+ 0x4a038805, 0x02000000, 0x0201f800, 0x001019fe,
+ 0x4000c000, 0x0201f800, 0x00101963, 0x4a038805,
+ 0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+ 0x497a6a00, 0x4937c857, 0x4a026c00, 0x00000707,
+ 0x497a6801, 0x497a6808, 0x497a6809, 0x497a6806,
+ 0x497a6807, 0x497a6c0b, 0x497a680c, 0x0201f800,
+ 0x00103b25, 0x04020006, 0x5934080f, 0x59340010,
+ 0x80040540, 0x02020800, 0x001005d8, 0x4a026a04,
+ 0x00000100, 0x497a6a03, 0x59340402, 0x82000500,
+ 0x000000ff, 0x48026c02, 0x497a6c04, 0x497a6a05,
+ 0x497a6c05, 0x497a6811, 0x4d2c0000, 0x5934000d,
+ 0x49466c03, 0x80025d40, 0x04000004, 0x0201f800,
+ 0x001007fd, 0x497a680d, 0x5c025800, 0x599c0401,
+ 0x48026a0b, 0x599c0208, 0x48026c12, 0x497a680a,
+ 0x0201f000, 0x00104c62, 0x42000000, 0x00000005,
+ 0x80000d80, 0x0401f02d, 0x0201f800, 0x00104a09,
+ 0x04020017, 0x59a80026, 0x8c00050a, 0x04020010,
+ 0x59340212, 0x82000500, 0x0000ff00, 0x4803c857,
+ 0x0400000b, 0x59340a00, 0x8c040d1e, 0x02000000,
+ 0x000201c4, 0x42000000, 0x00000029, 0x42000800,
+ 0x00001000, 0x492fc857, 0x0401f018, 0x492fc857,
+ 0x42000000, 0x00000028, 0x0401f012, 0x59a80805,
+ 0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004,
+ 0x42000000, 0x00000004, 0x0401f00a, 0x42000000,
+ 0x00000029, 0x59340a00, 0x8c040d1e, 0x04000005,
+ 0x492fc857, 0x42000800, 0x00001000, 0x0401f003,
+ 0x492fc857, 0x80000d80, 0x4803c857, 0x80028540,
+ 0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500,
+ 0x040207ec, 0x0201f800, 0x001049e7, 0x040207e4,
+ 0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000,
+ 0x000201c4, 0x0201f800, 0x001047eb, 0x040007bf,
+ 0x0201f000, 0x000201c8, 0x592c0206, 0x492fc857,
+ 0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a,
+ 0x00000030, 0x42026800, 0x0010b524, 0x0401f021,
+ 0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400,
+ 0x50000000, 0x80026d40, 0x04000038, 0x0201f800,
+ 0x001048e3, 0x04020038, 0x592c040a, 0x8c00050a,
+ 0x04020014, 0x592e6009, 0x83300480, 0x0010d1c0,
+ 0x0400103b, 0x41580000, 0x81300480, 0x04021038,
+ 0x59300c06, 0x82040580, 0x00000009, 0x04020037,
+ 0x4a025a06, 0x00000000, 0x497a5800, 0x59300008,
+ 0x80000540, 0x04020018, 0x492e6008, 0x0401f010,
+ 0x0201f800, 0x0002075a, 0x04000019, 0x592c0206,
+ 0x49366009, 0x492e6008, 0x4a026406, 0x00000009,
+ 0x497a6015, 0x49325809, 0x82000d80, 0x000007ff,
+ 0x04020003, 0x4a026015, 0x00008000, 0x42027000,
+ 0x00000043, 0x0201f800, 0x000207a1, 0x80000580,
+ 0x0401f020, 0x40000800, 0x58040000, 0x80000d40,
+ 0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000,
+ 0x0000002c, 0x0401f016, 0x42000000, 0x00000028,
+ 0x0401f013, 0x59a80805, 0x82040500, 0x00000003,
+ 0x04000004, 0x42000000, 0x00000004, 0x0401f00c,
+ 0x42000000, 0x00000029, 0x0401f009, 0x42000000,
+ 0x00000008, 0x0401f006, 0x82040580, 0x00000007,
+ 0x040207fb, 0x42000000, 0x00000005, 0x80000540,
+ 0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80,
+ 0x000007fc, 0x04000004, 0x83440480, 0x000007f0,
+ 0x04021014, 0x0201f800, 0x00020245, 0x04020011,
+ 0x0201f800, 0x001049f3, 0x04020011, 0x0201f800,
+ 0x0002075a, 0x0400001c, 0x49366009, 0x492e6008,
+ 0x4a026406, 0x0000000a, 0x42027000, 0x00000040,
+ 0x0201f800, 0x000207a1, 0x80000580, 0x0401f011,
+ 0x42000000, 0x00000028, 0x0401f00d, 0x0201f800,
+ 0x00104a09, 0x040007fb, 0x59a80805, 0x82040d00,
+ 0x00000003, 0x04000004, 0x42000000, 0x00000004,
+ 0x0401f003, 0x42000000, 0x00000029, 0x80000540,
+ 0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc,
+ 0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80,
+ 0x00000800, 0x42000000, 0x0000000a, 0x04021176,
+ 0x592c4207, 0x4823c857, 0x82200500, 0x0000000f,
+ 0x0c01f001, 0x001043d5, 0x0010445d, 0x001044a9,
+ 0x001044b4, 0x001044bf, 0x001043d1, 0x001043d1,
+ 0x001043d1, 0x001044cf, 0x00104513, 0x00104530,
+ 0x001043d1, 0x001043d1, 0x001043d1, 0x001043d1,
+ 0x001043d1, 0x4803c857, 0x42000000, 0x0000000c,
+ 0x0401f15d, 0x592c1008, 0x82081500, 0x00ffffff,
+ 0x59a80010, 0x80084d80, 0x42000000, 0x00000010,
+ 0x04000155, 0x0201f800, 0x00104919, 0x04000036,
+ 0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a,
+ 0x0201f800, 0x00105755, 0x59340405, 0x4c000000,
+ 0x0201f800, 0x001049e7, 0x5c000000, 0x04000004,
+ 0x8c20450a, 0x04000028, 0x80000580, 0x44002800,
+ 0x59340008, 0x48002802, 0x59340009, 0x48002801,
+ 0x59340006, 0x48002804, 0x59340007, 0x48002803,
+ 0x4200b000, 0x00000005, 0x0201f800, 0x0010955f,
+ 0x0401f166, 0x4803c857, 0x82004d80, 0x0000001a,
+ 0x04020003, 0x40101000, 0x0401f136, 0x4803c857,
+ 0x82004d80, 0x0000001b, 0x04020003, 0x40181000,
+ 0x0401f130, 0x4803c857, 0x82004d80, 0x0000001c,
+ 0x04000131, 0x82004d80, 0x00000019, 0x42000000,
+ 0x0000000a, 0x04000120, 0x42000000, 0x0000000a,
+ 0x04020137, 0x59a80005, 0x8c000514, 0x0400001b,
+ 0x0201f800, 0x001049e7, 0x04000018, 0x59340212,
+ 0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
+ 0x0402000c, 0x42001000, 0x00000008, 0x59a80026,
+ 0x8c000506, 0x04020009, 0x59340002, 0x82000500,
+ 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000007,
+ 0x0201f800, 0x00104c6d, 0x42000000, 0x0000001c,
+ 0x40181000, 0x04020107, 0x0201f800, 0x0002075a,
+ 0x04000111, 0x49366009, 0x492e6008, 0x4a026406,
+ 0x00000001, 0x8c20450a, 0x04000004, 0x592c0404,
+ 0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000,
+ 0x42027800, 0x00001000, 0x0201f800, 0x0010203c,
+ 0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b,
+ 0x599c0018, 0x8c000518, 0x04000008, 0x592c0009,
+ 0x82000500, 0x00000380, 0x5934080a, 0x80040d40,
+ 0x84040d54, 0x4806680a, 0x417a7800, 0x0401f914,
+ 0x42000800, 0x00000003, 0x0401f91b, 0x42027000,
+ 0x00000002, 0x0201f800, 0x000207a1, 0x80000580,
+ 0x0401f10a, 0x0201f800, 0x00020245, 0x040200ec,
+ 0x0201f800, 0x001049ed, 0x04000008, 0x0201f800,
+ 0x001049e7, 0x040200ec, 0x417a7800, 0x417a6000,
+ 0x0201f800, 0x001020a1, 0x59a80005, 0x8c000514,
+ 0x0400001b, 0x0201f800, 0x001049e7, 0x04000018,
+ 0x59340212, 0x82000500, 0x0000ff00, 0x42001000,
+ 0x00000010, 0x0402000c, 0x42001000, 0x00000008,
+ 0x59a80026, 0x8c000506, 0x04020009, 0x59340002,
+ 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+ 0x04000007, 0x0201f800, 0x00104c6d, 0x42000000,
+ 0x0000001c, 0x40181000, 0x040200b2, 0x0201f800,
+ 0x0002075a, 0x040000bc, 0x5934080a, 0x8c204512,
+ 0x0400000c, 0x599c0018, 0x8c000518, 0x04000009,
+ 0x592c0009, 0x82000500, 0x00000380, 0x82041500,
+ 0xfffffc7f, 0x80080d40, 0x84040d54, 0x0401f002,
+ 0x84040d14, 0x4806680a, 0x49366009, 0x492e6008,
+ 0x4a026406, 0x00000001, 0x417a7800, 0x0401f8c8,
+ 0x42000800, 0x00000005, 0x0401f8cf, 0x42027000,
+ 0x00000003, 0x0201f800, 0x000207a1, 0x80000580,
+ 0x0401f0be, 0x0201f800, 0x00020245, 0x040200a0,
+ 0x0201f800, 0x001049fc, 0x040200a3, 0x0201f800,
+ 0x00109517, 0x04000094, 0x80000580, 0x0401f0b3,
+ 0x0201f800, 0x00020245, 0x04020095, 0x0201f800,
+ 0x001049fc, 0x04020098, 0x0201f800, 0x001090e6,
+ 0x04000089, 0x80000580, 0x0401f0a8, 0x0201f800,
+ 0x00020245, 0x0402008a, 0x83444d80, 0x000007fe,
+ 0x42000000, 0x0000000a, 0x0402006b, 0x0201f800,
+ 0x001049e7, 0x04020088, 0x0201f800, 0x0010952f,
+ 0x04000079, 0x80000580, 0x0401f098, 0x82200500,
+ 0x00000070, 0x04020005, 0x8c20450e, 0x42000000,
+ 0x0000000c, 0x0402005c, 0x8c20450a, 0x0400000d,
+ 0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e,
+ 0x04020002, 0x853e7d56, 0x82200500, 0x000000a0,
+ 0x0201f800, 0x001049d3, 0x5c027800, 0x0401f07f,
+ 0x0201f800, 0x00020245, 0x04020065, 0x8c204508,
+ 0x04000010, 0x4d3c0000, 0x42027800, 0x00001000,
+ 0x8c20450e, 0x04020002, 0x853e7d56, 0x82200500,
+ 0x00000090, 0x0201f800, 0x001049bb, 0x5c027800,
+ 0x42000000, 0x0000000a, 0x0402003b, 0x0401f06b,
+ 0x836c0580, 0x00000003, 0x42000800, 0x00000007,
+ 0x0402000f, 0x0201f800, 0x001049f3, 0x04000007,
+ 0x4c000000, 0x0201f800, 0x00104a1f, 0x5c000000,
+ 0x0400004d, 0x0401f05d, 0x0201f800, 0x001094c5,
+ 0x04000007, 0x80000580, 0x0401f05c, 0x0201f800,
+ 0x00104a1f, 0x04000051, 0x0401f054, 0x0201f800,
+ 0x00104a1f, 0x04000034, 0x0401f050, 0x0201f800,
+ 0x00020245, 0x04020036, 0x836c0580, 0x00000003,
+ 0x04020040, 0x8c204508, 0x04000006, 0x417a7800,
+ 0x417a6000, 0x0201f800, 0x001020a1, 0x0401f043,
+ 0x0201f800, 0x001049ed, 0x04000008, 0x0201f800,
+ 0x001049e7, 0x0402002c, 0x417a7800, 0x417a6000,
+ 0x0201f800, 0x001020a1, 0x480bc856, 0x0201f800,
+ 0x00109332, 0x04000018, 0x80000580, 0x0401f037,
+ 0x0401f7e3, 0x480bc857, 0x42000800, 0x00000019,
+ 0x40001000, 0x4200b000, 0x00000002, 0x0401f00a,
+ 0x480bc857, 0x40000800, 0x4200b000, 0x00000002,
+ 0x0401f005, 0x480bc857, 0x40000800, 0x4200b000,
+ 0x00000001, 0x480bc857, 0x42028000, 0x00000031,
+ 0x0401f020, 0x480bc857, 0x42000800, 0x00000003,
+ 0x4200b000, 0x00000001, 0x0401f7f7, 0x480bc857,
+ 0x42000800, 0x0000000a, 0x4200b000, 0x00000001,
+ 0x0401f7f1, 0x480bc857, 0x42000800, 0x00000009,
+ 0x40001000, 0x4200b000, 0x00000002, 0x0401f7ea,
+ 0x480bc857, 0x42000800, 0x00000007, 0x4200b000,
+ 0x00000001, 0x0401f7e4, 0x480bc857, 0x4200b000,
+ 0x00000001, 0x0401f7e0, 0x80028580, 0x4178b000,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4937c857,
+ 0x59326809, 0x59341200, 0x813e79c0, 0x04000003,
+ 0x84081540, 0x0401f002, 0x84081500, 0x480a6a00,
+ 0x1c01f000, 0x59326809, 0x5c000000, 0x4c000000,
+ 0x4803c857, 0x4937c857, 0x82040580, 0x00000006,
+ 0x04020004, 0x42000000, 0x00000606, 0x0401f021,
+ 0x82040580, 0x00000004, 0x04020004, 0x42000000,
+ 0x00000404, 0x0401f01b, 0x82040580, 0x00000007,
+ 0x42000000, 0x00000707, 0x04000016, 0x82040580,
+ 0x00000003, 0x42000000, 0x00000703, 0x04000011,
+ 0x82040580, 0x00000005, 0x42000000, 0x00000405,
+ 0x0400000c, 0x82040580, 0x00000009, 0x42000000,
+ 0x00000409, 0x04000007, 0x82040580, 0x0000000b,
+ 0x42000000, 0x0000070b, 0x02020800, 0x001005d8,
+ 0x4803c857, 0x48026c00, 0x82040d80, 0x00000006,
+ 0x04020005, 0x59341404, 0x800811c0, 0x02000800,
+ 0x001005d8, 0x1c01f000, 0x5c000000, 0x4c000000,
+ 0x4803c857, 0x4947c857, 0x481bc857, 0x83440480,
+ 0x00000800, 0x04021034, 0x83441400, 0x0010ac00,
+ 0x50080000, 0x80026d40, 0x04020011, 0x4c180000,
+ 0x4d2c0000, 0x0201f800, 0x001007d3, 0x412e6800,
+ 0x5c025800, 0x5c003000, 0x04000027, 0x45341000,
+ 0x497a680d, 0x497a6810, 0x497a680f, 0x497a680e,
+ 0x4c180000, 0x0401fcf3, 0x5c003000, 0x59340a12,
+ 0x4c040000, 0x0201f800, 0x0010513b, 0x5c000800,
+ 0x04000009, 0x82180500, 0x00ffff00, 0x04000008,
+ 0x59a81010, 0x82081500, 0x00ffff00, 0x80080580,
+ 0x04000003, 0x80000580, 0x0401f004, 0x82180500,
+ 0x000000ff, 0x800000d0, 0x80040d80, 0x04000003,
+ 0x4803c857, 0x48026a12, 0x59340002, 0x80180580,
+ 0x04000003, 0x481bc857, 0x481a6802, 0x80000580,
+ 0x1c01f000, 0x4803c856, 0x82000540, 0x00000001,
+ 0x0401f7fc, 0x4947c857, 0x83440480, 0x00000800,
+ 0x04021011, 0x83441400, 0x0010ac00, 0x50080000,
+ 0x80026d40, 0x0400000b, 0x0401fbf9, 0x0402000a,
+ 0x59a80005, 0x8c000502, 0x04000004, 0x59340200,
+ 0x8c00050e, 0x04000004, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x80000580, 0x0401f7fe, 0x5c000000,
+ 0x4c000000, 0x4803c857, 0x4947c857, 0x4d2c0000,
+ 0x4d300000, 0x83440480, 0x00000800, 0x04021024,
+ 0x83441400, 0x0010ac00, 0x50080000, 0x80026d40,
+ 0x0400001b, 0x45781000, 0x5934000d, 0x80025d40,
+ 0x02020800, 0x001007fd, 0x59366011, 0x813261c0,
+ 0x0400000e, 0x4c640000, 0x5930c800, 0x59325808,
+ 0x0201f800, 0x00109037, 0x02020800, 0x001007fd,
+ 0x0201f800, 0x0002077d, 0x82666540, 0x00000000,
+ 0x040207f6, 0x5c00c800, 0x0201f800, 0x00104c62,
+ 0x41365800, 0x0201f800, 0x001007f5, 0x80000580,
+ 0x5c026000, 0x5c025800, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x0401f7fb, 0x4937c857, 0x4c580000,
+ 0x59cc0001, 0x82000500, 0x00ffffff, 0x48026802,
+ 0x497a6c01, 0x497a6a01, 0x59340200, 0x84000502,
+ 0x48026a00, 0x0201f800, 0x0010513b, 0x04020017,
+ 0x59340403, 0x82000580, 0x000007fe, 0x04000005,
+ 0x59a80026, 0x8c00050a, 0x04020010, 0x0401f008,
+ 0x59cc0408, 0x8c000518, 0x0400000c, 0x59cc0009,
+ 0x48035035, 0x59cc000a, 0x48035036, 0x59cc0207,
+ 0x80000540, 0x04020003, 0x42000000, 0x00000001,
+ 0x48038893, 0x4803501e, 0x59cc0a09, 0x82040d00,
+ 0x00000010, 0x59cc0408, 0x82000500, 0x00000020,
+ 0x04000002, 0x84040d40, 0x5934000a, 0x82000500,
+ 0xffffffee, 0x80040540, 0x4802680a, 0x83cca400,
+ 0x0000000b, 0x8334ac00, 0x00000006, 0x4200b000,
+ 0x00000002, 0x0201f800, 0x0010ab17, 0x83cca400,
+ 0x0000000d, 0x8334ac00, 0x00000008, 0x4200b000,
+ 0x00000002, 0x0201f800, 0x0010ab17, 0x59cc0a18,
+ 0x82040480, 0x00000800, 0x0402100c, 0x82040480,
+ 0x00000400, 0x04001004, 0x42000800, 0x00000400,
+ 0x0401f006, 0x82040480, 0x00000200, 0x04001003,
+ 0x42000800, 0x00000200, 0x48066a04, 0x59340403,
+ 0x82000580, 0x000007fe, 0x04020003, 0x59cc0a08,
+ 0x48066a04, 0x42000800, 0x00000004, 0x59cc1207,
+ 0x800811c0, 0x04000005, 0x82080480, 0x00000004,
+ 0x04021002, 0x40080800, 0x48066c04, 0x5c00b000,
+ 0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508,
+ 0x04000004, 0x84000556, 0x4803c857, 0x48035026,
+ 0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a,
+ 0x4803c857, 0x48026c05, 0x59341200, 0x599c0818,
+ 0x5934180a, 0x4807c857, 0x480bc857, 0x480fc857,
+ 0x59cc2006, 0x82102500, 0xff000000, 0x82102580,
+ 0x02000000, 0x04000007, 0x8c00050e, 0x04000009,
+ 0x8c0c1d14, 0x04000003, 0x8c0c1d0e, 0x04000005,
+ 0x8c040d18, 0x04000003, 0x8408154a, 0x0401f002,
+ 0x8408150a, 0x8c000510, 0x04000009, 0x8c0c1d14,
+ 0x04000003, 0x8c0c1d10, 0x04000005, 0x8c040d18,
+ 0x04000003, 0x8408154e, 0x0401f002, 0x8408150e,
+ 0x8c000512, 0x04000009, 0x8c0c1d14, 0x04000003,
+ 0x8c0c1d12, 0x04000005, 0x8c040d18, 0x04000003,
+ 0x8408155c, 0x0401f002, 0x8408151c, 0x480a6a00,
+ 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000,
+ 0x4c580000, 0x5934000d, 0x80025d40, 0x04000029,
+ 0x592c0003, 0x82000480, 0x00000008, 0x0400100b,
+ 0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9,
+ 0x0201f800, 0x001007e4, 0x04000037, 0x492fc857,
+ 0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004,
+ 0x4200b000, 0x00000008, 0x50040000, 0x82000580,
+ 0xffffffff, 0x04020006, 0x80041000, 0x50080000,
+ 0x82000580, 0xffffffff, 0x04000007, 0x82040c00,
+ 0x00000002, 0x8058b040, 0x040207f4, 0x0201f800,
+ 0x001005d8, 0x45480800, 0x454c1000, 0x592c1803,
+ 0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014,
+ 0x0201f800, 0x001007e4, 0x04000017, 0x492fc857,
+ 0x492e680d, 0x497a5802, 0x4a025803, 0x00000001,
+ 0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006,
+ 0x4200b000, 0x0000000e, 0x46000800, 0xffffffff,
+ 0x80040800, 0x8058b040, 0x040207fc, 0x82000540,
+ 0x00000001, 0x5c00b000, 0x5c025800, 0x5c00b800,
+ 0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856,
+ 0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40,
+ 0x0400001f, 0x592c0002, 0x80000540, 0x0402001f,
+ 0x412e7800, 0x0401f8ce, 0x0402001c, 0x46000800,
+ 0xffffffff, 0x46001000, 0xffffffff, 0x4813c857,
+ 0x480fc857, 0x580c0003, 0x82000c80, 0x00000002,
+ 0x04021014, 0x480fc857, 0x400c0000, 0x812c0580,
+ 0x04020004, 0x580c0001, 0x4802680d, 0x0401f003,
+ 0x580c0001, 0x48002001, 0x400e5800, 0x0201f800,
+ 0x001007f4, 0x82000540, 0x00000001, 0x5c025800,
+ 0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc,
+ 0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6,
+ 0x0201f800, 0x00020086, 0x59300007, 0x8400054e,
+ 0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff,
+ 0x820c0580, 0x00000048, 0x04000013, 0x0201f000,
+ 0x0002028e, 0x8c000500, 0x02020800, 0x000200e5,
+ 0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00,
+ 0x000000ff, 0x820c0580, 0x00000018, 0x02000000,
+ 0x0002028e, 0x820c0580, 0x00000048, 0x02020000,
+ 0x0002028e, 0x42000800, 0x80000804, 0x0201f800,
+ 0x00106721, 0x0201f000, 0x00020297, 0x4a025a06,
+ 0x00000008, 0x0201f000, 0x000202da, 0x4a025a06,
+ 0x00000029, 0x0201f000, 0x000202da, 0x4a025a06,
+ 0x0000002a, 0x0201f000, 0x000202da, 0x4a025a06,
+ 0x00000028, 0x0201f000, 0x000202da, 0x4943c857,
+ 0x4d440000, 0x4d340000, 0x4d2c0000, 0x4c580000,
+ 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
+ 0x00020245, 0x0402000d, 0x8d3e7d14, 0x04000005,
+ 0x59340212, 0x82000500, 0x0000ff00, 0x04000007,
+ 0x8d3e7d06, 0x04000004, 0x59340200, 0x8c00050e,
+ 0x04020002, 0x0401f813, 0x81468800, 0x8058b040,
+ 0x040207ef, 0x83440480, 0x00000800, 0x04021008,
+ 0x8d3e7d02, 0x04000006, 0x42028800, 0x000007f0,
+ 0x4200b000, 0x00000010, 0x0401f7e5, 0x5c00b000,
+ 0x5c025800, 0x5c026800, 0x5c028800, 0x1c01f000,
+ 0x4d2c0000, 0x41783000, 0x5936580f, 0x812e59c0,
+ 0x04000029, 0x592c0204, 0x82000500, 0x000000ff,
+ 0x82000580, 0x00000012, 0x04000020, 0x8d3e7d00,
+ 0x04000003, 0x0401f83c, 0x0402001c, 0x592c2000,
+ 0x497a5800, 0x801831c0, 0x04020009, 0x59340010,
+ 0x812c0580, 0x04020004, 0x497a680f, 0x497a6810,
+ 0x0401f008, 0x4812680f, 0x0401f006, 0x48103000,
+ 0x59340010, 0x812c0580, 0x04020002, 0x481a6810,
+ 0x4a025a04, 0x00000103, 0x49425a06, 0x497a5c09,
+ 0x0201f800, 0x001091c6, 0x0201f800, 0x000202da,
+ 0x40125800, 0x0401f7da, 0x412c3000, 0x592e5800,
+ 0x0401f7d7, 0x5c025800, 0x1c01f000, 0x4803c856,
+ 0x41781800, 0x5934000f, 0x80025d40, 0x04000010,
+ 0x592c0005, 0x80200580, 0x592c0000, 0x04000003,
+ 0x412c1800, 0x0401f7f9, 0x497a5800, 0x800c19c0,
+ 0x04000008, 0x48001800, 0x80000540, 0x04020004,
+ 0x480e6810, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x4802680f, 0x80000540, 0x040207fd, 0x497a6810,
+ 0x0401f7f9, 0x592c0008, 0x81480580, 0x04020003,
+ 0x592c0009, 0x814c0580, 0x1c01f000, 0x4803c856,
+ 0x4c580000, 0x413c1800, 0x400c2000, 0x593c0002,
+ 0x80000540, 0x04020018, 0x4200b000, 0x00000008,
+ 0x820c0c00, 0x00000004, 0x50040000, 0x81480580,
+ 0x04020005, 0x80041000, 0x50080000, 0x814c0580,
+ 0x0400000d, 0x82040c00, 0x00000002, 0x8058b040,
+ 0x040207f6, 0x400c2000, 0x580c0001, 0x80001d40,
+ 0x040207ee, 0x82000540, 0x00000001, 0x5c00b000,
+ 0x1c01f000, 0x80000580, 0x0401f7fd, 0x4937c857,
+ 0x4c580000, 0x4d2c0000, 0x5934000d, 0x80025d40,
+ 0x04020016, 0x0201f800, 0x001007e4, 0x04000010,
+ 0x492e680d, 0x4a025802, 0x00000001, 0x497a5803,
+ 0x832c0c00, 0x00000004, 0x4200b000, 0x00000010,
+ 0x46000800, 0xffffffff, 0x80040800, 0x8058b040,
+ 0x040207fc, 0x82000540, 0x00000001, 0x5c025800,
+ 0x5c00b000, 0x1c01f000, 0x4d2c0000, 0x592e5801,
+ 0x0201f800, 0x001007fd, 0x5c025800, 0x0401f7ea,
+ 0x4d2c0000, 0x5936580d, 0x812e59c0, 0x04000007,
+ 0x4937c857, 0x497a680d, 0x0201f800, 0x001007fd,
+ 0x82000540, 0x00000001, 0x5c025800, 0x1c01f000,
+ 0x59340405, 0x4937c857, 0x4803c857, 0x8c000508,
+ 0x1c01f000, 0x4803c856, 0x0201f800, 0x0010513b,
+ 0x04000011, 0x59a80815, 0x8c040d04, 0x0402000e,
+ 0x59a80826, 0x8c040d06, 0x0400000b, 0x83ac0400,
+ 0x000007fe, 0x50000000, 0x80026d40, 0x04000006,
+ 0x0401f9a7, 0x04020004, 0x59340200, 0x8400055a,
+ 0x48026a00, 0x599c0017, 0x8c000508, 0x04000015,
+ 0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
+ 0x00020245, 0x0402000c, 0x0401f999, 0x0402000a,
+ 0x59a80010, 0x59340802, 0x80040580, 0x82000500,
+ 0x00ffff00, 0x04020004, 0x59340200, 0x8400055a,
+ 0x48026a00, 0x81468800, 0x8058b040, 0x040207f0,
+ 0x0401f884, 0x04000003, 0x59a80836, 0x0401f006,
+ 0x599c0017, 0x8c000508, 0x04000007, 0x42000800,
+ 0x000007d0, 0x42001000, 0x00104876, 0x0201f800,
+ 0x0010606e, 0x1c01f000, 0x4803c856, 0x4d340000,
+ 0x4d440000, 0x4d3c0000, 0x4c580000, 0x42001000,
+ 0x00104876, 0x0201f800, 0x00105f90, 0x59a80826,
+ 0x8c040d06, 0x04000015, 0x0401f86a, 0x04000013,
+ 0x83ae6c00, 0x000007fe, 0x51366800, 0x59340200,
+ 0x8400051a, 0x48026a00, 0x599c0017, 0x8c000508,
+ 0x04000007, 0x42000800, 0x000007d0, 0x42001000,
+ 0x00104876, 0x0201f800, 0x0010606e, 0x0201f800,
+ 0x00101e45, 0x0401f027, 0x4200b000, 0x000007f0,
+ 0x80028d80, 0x0201f800, 0x00020245, 0x0402001e,
+ 0x59340200, 0x8c00051a, 0x0400001b, 0x59368c03,
+ 0x417a7800, 0x42028000, 0x00000029, 0x41783000,
+ 0x0201f800, 0x0010a446, 0x59340200, 0x84000558,
+ 0x8400051a, 0x48026a00, 0x4937c857, 0x4a026c00,
+ 0x00000707, 0x42028000, 0x00000029, 0x0201f800,
+ 0x00106ab4, 0x417a7800, 0x0201f800, 0x001067fd,
+ 0x80000d80, 0x0201f800, 0x0010a2ff, 0x0201f800,
+ 0x00106c4b, 0x81468800, 0x8058b040, 0x040207de,
+ 0x5c00b000, 0x5c027800, 0x5c028800, 0x5c026800,
+ 0x1c01f000, 0x4933c857, 0x59303809, 0x581c0200,
+ 0x8400051a, 0x48003a00, 0x1c01f000, 0x4803c856,
+ 0x42026800, 0x0010b524, 0x497a680e, 0x42028800,
+ 0x000007ff, 0x0201f800, 0x001042b4, 0x4937c857,
+ 0x4a026c00, 0x00000606, 0x4a026802, 0x00ffffff,
+ 0x4a026a04, 0x00000200, 0x4a026c04, 0x00000002,
+ 0x1c01f000, 0x59300009, 0x50000000, 0x4933c857,
+ 0x4803c857, 0x8c00050e, 0x1c01f000, 0x59300009,
+ 0x50000000, 0x8c00050a, 0x1c01f000, 0x4933c856,
+ 0x0401f90f, 0x04000006, 0x59340400, 0x82000d00,
+ 0x000000ff, 0x82041580, 0x00000005, 0x1c01f000,
+ 0x4d340000, 0x83ac0400, 0x000007fe, 0x50000000,
+ 0x80026d40, 0x04000003, 0x59340200, 0x8c00051a,
+ 0x5c026800, 0x1c01f000, 0x4937c857, 0x493fc857,
+ 0x59340403, 0x81ac0400, 0x50000000, 0x81340580,
+ 0x02020800, 0x001005d8, 0x59341200, 0x813e79c0,
+ 0x04000003, 0x8408155e, 0x0401f002, 0x8408151e,
+ 0x480a6a00, 0x1c01f000, 0x4937c857, 0x0201f800,
+ 0x0010210a, 0x04000006, 0x59a80835, 0x42001000,
+ 0x00104910, 0x0201f800, 0x0010606e, 0x1c01f000,
+ 0x4937c857, 0x42001000, 0x00104910, 0x0201f800,
+ 0x00105f90, 0x59a81026, 0x84081512, 0x480b5026,
+ 0x1c01f000, 0x4c380000, 0x4c340000, 0x4c240000,
+ 0x4c600000, 0x4008c000, 0x83440480, 0x00000800,
+ 0x04021045, 0x80002d80, 0x41442000, 0x83447400,
+ 0x0010ac00, 0x4200b000, 0x000007f0, 0x83444c80,
+ 0x000007f0, 0x04001003, 0x4200b000, 0x00000010,
+ 0x50380000, 0x80000540, 0x0402001e, 0x41440000,
+ 0x80100580, 0x04020043, 0x40102800, 0x82104c80,
+ 0x000007f0, 0x04001015, 0x82104d80, 0x000007fc,
+ 0x04020005, 0x82604d80, 0x00fffffc, 0x0402002a,
+ 0x0401f00e, 0x82104d80, 0x000007fd, 0x04020005,
+ 0x82604d80, 0x00fffffd, 0x04020023, 0x0401f007,
+ 0x82104d80, 0x000007ff, 0x0402001f, 0x82604d80,
+ 0x00ffffff, 0x0402001c, 0x84142d5e, 0x0401f029,
+ 0x40006800, 0x58343002, 0x82183500, 0x00ffffff,
+ 0x40180000, 0x80600580, 0x04020019, 0x40100000,
+ 0x81440580, 0x0402000a, 0x40366800, 0x8c204508,
+ 0x04000053, 0x0401ff8a, 0x04020051, 0x4947c857,
+ 0x42000000, 0x0000001d, 0x0401f04e, 0x4947c857,
+ 0x480bc857, 0x4823c857, 0x42000000, 0x0000001a,
+ 0x0401f048, 0x4947c857, 0x4863c857, 0x4813c857,
+ 0x42000000, 0x00000019, 0x0401f042, 0x40100000,
+ 0x81440580, 0x04020007, 0x58343002, 0x4947c857,
+ 0x481bc857, 0x42000000, 0x0000001b, 0x0401f039,
+ 0x80102000, 0x80387000, 0x83444c80, 0x000007f0,
+ 0x04001009, 0x82104d80, 0x00000800, 0x0402000c,
+ 0x42002000, 0x000007f0, 0x42007000, 0x0010b3f0,
+ 0x0401f007, 0x82104d80, 0x000007f0, 0x04020004,
+ 0x41782000, 0x42007000, 0x0010ac00, 0x8058b040,
+ 0x040207a4, 0x801429c0, 0x04020007, 0x0201f800,
+ 0x001005d8, 0x4947c857, 0x42000000, 0x0000000a,
+ 0x0401f01c, 0x4d2c0000, 0x4c180000, 0x40603000,
+ 0x0401fc12, 0x4947c857, 0x4937c857, 0x5c003000,
+ 0x5c025800, 0x040207f4, 0x497a6a12, 0x59a80026,
+ 0x8c00050a, 0x0402000d, 0x82600500, 0x00ffff00,
+ 0x04000006, 0x59a84810, 0x82244d00, 0x00ffff00,
+ 0x80240580, 0x04020005, 0x82600500, 0x000000ff,
+ 0x800000d0, 0x48026a12, 0x48626802, 0x80000580,
+ 0x80000540, 0x5c00c000, 0x5c004800, 0x5c006800,
+ 0x5c007000, 0x1c01f000, 0x5934000f, 0x5934140b,
+ 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
+ 0x02020800, 0x00020253, 0x1c01f000, 0x4803c857,
+ 0x4947c857, 0x4c300000, 0x82006500, 0x00000030,
+ 0x04000006, 0x4c000000, 0x0201f800, 0x0010942a,
+ 0x5c000000, 0x0402000b, 0x8c00050e, 0x04000006,
+ 0x0201f800, 0x00020245, 0x04020006, 0x4937c857,
+ 0x0401fc2f, 0x80000580, 0x5c006000, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x0401f7fc, 0x4803c857,
+ 0x4c580000, 0x4d440000, 0x40001000, 0x80000d80,
+ 0x4200b000, 0x000007f0, 0x4c040000, 0x40068800,
+ 0x4c080000, 0x40080000, 0x0401ffdd, 0x5c001000,
+ 0x5c000800, 0x80040800, 0x8058b040, 0x040207f7,
+ 0x5c028800, 0x5c00b000, 0x1c01f000, 0x4c5c0000,
+ 0x59340400, 0x8200bd80, 0x00000606, 0x5c00b800,
+ 0x1c01f000, 0x4c5c0000, 0x59340400, 0x8200bd80,
+ 0x00000404, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
+ 0x59340400, 0x8200bd80, 0x00000404, 0x04000003,
+ 0x8200bd80, 0x00000606, 0x5c00b800, 0x1c01f000,
+ 0x4c5c0000, 0x4c600000, 0x59340400, 0x8200bd00,
+ 0x0000ff00, 0x825cc580, 0x00000400, 0x04000003,
+ 0x825cc580, 0x00000600, 0x5c00c000, 0x5c00b800,
+ 0x1c01f000, 0x4c5c0000, 0x59340400, 0x82000500,
+ 0x000000ff, 0x8200bd80, 0x00000003, 0x04000003,
+ 0x8200bd80, 0x00000005, 0x5c00b800, 0x1c01f000,
+ 0x4c5c0000, 0x59340400, 0x82000500, 0x0000ff00,
+ 0x8400b9c0, 0x805c0580, 0x4937c857, 0x4803c857,
+ 0x48026c00, 0x5c00b800, 0x1c01f000, 0x4c040000,
+ 0x4c080000, 0x592c0207, 0x8c00050c, 0x0400000f,
+ 0x592e8c06, 0x82000500, 0x00000080, 0x84000548,
+ 0x4d3c0000, 0x42027800, 0x00001000, 0x0401ff90,
+ 0x5c027800, 0x82000540, 0x00000001, 0x5c001000,
+ 0x5c000800, 0x1c01f000, 0x80000580, 0x0401f7fc,
+ 0x592c040b, 0x82000500, 0x0000e000, 0x82000580,
+ 0x00006000, 0x04000019, 0x836c0580, 0x00000003,
+ 0x04000016, 0x836c0580, 0x00000002, 0x040200ff,
+ 0x59a80026, 0x82000d00, 0x00000038, 0x04020005,
+ 0x59a80832, 0x800409c0, 0x0400000c, 0x0401f0f7,
+ 0x82000d00, 0x00000003, 0x82040d80, 0x00000003,
+ 0x040200f2, 0x82000d00, 0x00000028, 0x04020003,
+ 0x8c00050c, 0x040000ed, 0x592c100a, 0x82080500,
+ 0xff000000, 0x040200ce, 0x59a80010, 0x80080580,
+ 0x040000c8, 0x592c0c0b, 0x82040d00, 0x0000e000,
+ 0x82040480, 0x00008000, 0x040210c8, 0x592e8c06,
+ 0x83440480, 0x00000800, 0x04001007, 0x83440580,
+ 0x0000ffff, 0x040200af, 0x800409c0, 0x040200f7,
+ 0x0401f0ac, 0x800409c0, 0x040200f4, 0x41784000,
+ 0x0401fead, 0x040200db, 0x42027000, 0x00000053,
+ 0x592c2409, 0x82100500, 0xffffff00, 0x040200aa,
+ 0x4813c857, 0x592c000c, 0x800001c0, 0x04000083,
+ 0x82100580, 0x00000004, 0x040000a0, 0x82100580,
+ 0x00000051, 0x0400009d, 0x82100580, 0x00000003,
+ 0x04000016, 0x82100580, 0x00000020, 0x0400004b,
+ 0x82100580, 0x00000024, 0x04000042, 0x82100580,
+ 0x00000021, 0x04000042, 0x82100580, 0x00000050,
+ 0x04000037, 0x82100580, 0x00000052, 0x04000031,
+ 0x82100580, 0x00000005, 0x0402006b, 0x42027000,
+ 0x00000001, 0x0401f01b, 0x42027000, 0x00000002,
+ 0x59a80005, 0x8c000514, 0x04000016, 0x0401ff4c,
+ 0x04000014, 0x59340212, 0x82000500, 0x0000ff00,
+ 0x42001000, 0x00000010, 0x0402000c, 0x59a80026,
+ 0x8c000506, 0x0402006f, 0x42001000, 0x00000008,
+ 0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
+ 0x00ff0000, 0x04000003, 0x0401f9bf, 0x04020065,
+ 0x0201f800, 0x0002075a, 0x0400007e, 0x4a026406,
+ 0x00000010, 0x49366009, 0x42000800, 0x00000003,
+ 0x83380580, 0x00000002, 0x04000003, 0x42000800,
+ 0x0000000b, 0x0201f800, 0x00104571, 0x0401f044,
+ 0x42027000, 0x00000000, 0x0401f003, 0x42027000,
+ 0x00000004, 0x0401ff37, 0x04020071, 0x0401f036,
+ 0x42027000, 0x00000033, 0x0401f006, 0x42027000,
+ 0x00000005, 0x0401f003, 0x42027000, 0x00000003,
+ 0x0401ff23, 0x04020066, 0x59a80005, 0x8c000514,
+ 0x04000016, 0x0401ff12, 0x04000014, 0x59340212,
+ 0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
+ 0x0402000c, 0x59a80026, 0x8c000506, 0x04020035,
+ 0x42001000, 0x00000008, 0x59340002, 0x82000500,
+ 0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003,
+ 0x0401f985, 0x0402002b, 0x0201f800, 0x0002075a,
+ 0x04000044, 0x4a026406, 0x00000010, 0x49366009,
+ 0x42000800, 0x00000005, 0x83380580, 0x00000003,
+ 0x04000003, 0x42000800, 0x00000009, 0x0201f800,
+ 0x00104571, 0x0401f00a, 0x82102580, 0x00000011,
+ 0x0402002d, 0x0201f800, 0x0002075a, 0x04000031,
+ 0x4a026406, 0x00000010, 0x49366009, 0x492e6008,
+ 0x49325808, 0x813669c0, 0x04000007, 0x592c0c0b,
+ 0x8c040d18, 0x04000004, 0x59340200, 0x84000514,
+ 0x48026a00, 0x0201f800, 0x000207a1, 0x80000580,
+ 0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd,
+ 0x42001000, 0x0000000a, 0x0401f015, 0x42001000,
+ 0x00000010, 0x0401f012, 0x42001000, 0x00000016,
+ 0x0401f00f, 0x42001000, 0x00000017, 0x0401f00c,
+ 0x42001000, 0x00000018, 0x0401f009, 0x42001000,
+ 0x0000001b, 0x0401f006, 0x42001000, 0x0000001e,
+ 0x0401f003, 0x42001000, 0x00000020, 0x42000800,
+ 0x00000019, 0x42028000, 0x00000031, 0x0401f7e2,
+ 0x42000800, 0x00000003, 0x0401f003, 0x42000800,
+ 0x0000000a, 0x41781000, 0x0401f7f7, 0x42000800,
+ 0x00000009, 0x59341400, 0x0401f7f3, 0x42028000,
+ 0x00000008, 0x0401f005, 0x42000800, 0x00000007,
+ 0x416c1000, 0x0401f7ec, 0x41780800, 0x41781000,
+ 0x0401f7cd, 0x42028000, 0x00000000, 0x0401f7fb,
+ 0x82004d80, 0x0000001d, 0x02000800, 0x001005d8,
+ 0x82004d80, 0x0000001a, 0x04020004, 0x40101000,
+ 0x40000800, 0x0401f7dc, 0x82004d80, 0x0000001b,
+ 0x04020003, 0x40181000, 0x0401f7fa, 0x82004d80,
+ 0x0000001c, 0x040007f7, 0x82004d80, 0x00000019,
+ 0x040007b8, 0x0401f7d6, 0x592e6008, 0x0201f800,
+ 0x0010941a, 0x040007b6, 0x59300c06, 0x82040580,
+ 0x00000011, 0x040207d6, 0x83440580, 0x0000ffff,
+ 0x04020005, 0x59326809, 0x813669c0, 0x0400000e,
+ 0x0401f7cf, 0x592c100a, 0x82081500, 0x00ffffff,
+ 0x41784000, 0x0401fda8, 0x040207d6, 0x59300009,
+ 0x800001c0, 0x04000003, 0x81340580, 0x040207c4,
+ 0x49366009, 0x592c0c0b, 0x82041500, 0x0000e000,
+ 0x82080580, 0x00006000, 0x04000009, 0x59300a03,
+ 0x82040580, 0x00000007, 0x040207b9, 0x492e6008,
+ 0x42027000, 0x00000054, 0x0401f77f, 0x0201f800,
+ 0x0010a8d4, 0x040007bc, 0x0401f7b1, 0x492fc857,
+ 0x59a80021, 0x800001c0, 0x04020073, 0x592e6008,
+ 0x4933c857, 0x0201f800, 0x0010941a, 0x04000041,
+ 0x59301406, 0x82080580, 0x00000005, 0x0402005b,
+ 0x59301203, 0x82080580, 0x00000007, 0x04020057,
+ 0x592e8c06, 0x83440480, 0x00000800, 0x04021032,
+ 0x41784000, 0x592c1009, 0x82081500, 0x00ffffff,
+ 0x0401fd75, 0x0402005f, 0x59300009, 0x800001c0,
+ 0x04000003, 0x81340580, 0x04020048, 0x4d300000,
+ 0x592e6013, 0x4933c857, 0x83300580, 0xffffffff,
+ 0x0400000d, 0x0201f800, 0x0010941a, 0x5c026000,
+ 0x04000029, 0x591c1406, 0x82080580, 0x00000006,
+ 0x04000046, 0x82080580, 0x00000011, 0x04000043,
+ 0x0401f002, 0x5c026000, 0x59a80010, 0x592c100a,
+ 0x82081500, 0x00ffffff, 0x80081580, 0x04020017,
+ 0x592c1009, 0x82081500, 0x00ffffff, 0x80081580,
+ 0x0400000f, 0x49366009, 0x492e6008, 0x42027000,
+ 0x00000092, 0x0201f800, 0x000207a1, 0x80000580,
+ 0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c,
+ 0x42001000, 0x00000010, 0x0401f009, 0x42001000,
+ 0x00000014, 0x0401f006, 0x42001000, 0x00000018,
+ 0x0401f003, 0x42001000, 0x0000003c, 0x492fc857,
+ 0x480bc857, 0x42000800, 0x00000019, 0x42028000,
+ 0x00000031, 0x82000540, 0x00000001, 0x0401f7e9,
+ 0x492fc857, 0x4803c857, 0x480bc857, 0x40000800,
+ 0x0401f7f7, 0x492fc857, 0x42000800, 0x0000000a,
+ 0x41781000, 0x0401f7f2, 0x4933c857, 0x59300406,
+ 0x4803c857, 0x59300203, 0x4803c857, 0x59300009,
+ 0x4803c857, 0x42028000, 0x00000008, 0x41780800,
+ 0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e,
+ 0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed,
+ 0x82004d80, 0x0000001d, 0x02000800, 0x001005d8,
+ 0x82004d80, 0x0000001a, 0x04020003, 0x40101000,
+ 0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003,
+ 0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c,
+ 0x040007d4, 0x82004d80, 0x00000019, 0x040007d1,
+ 0x0401f7d5, 0x59302009, 0x801021c0, 0x04000035,
+ 0x58101400, 0x82081d00, 0x000000ff, 0x59300c03,
+ 0x82040580, 0x00000008, 0x04000022, 0x82040580,
+ 0x0000000a, 0x04000017, 0x82040580, 0x0000000c,
+ 0x04000010, 0x82040580, 0x00000002, 0x04000019,
+ 0x82040580, 0x00000001, 0x04000012, 0x82040580,
+ 0x00000003, 0x0400000b, 0x82040580, 0x00000005,
+ 0x04000004, 0x82040580, 0x00000033, 0x04020019,
+ 0x820c0580, 0x00000009, 0x0400000d, 0x0401f015,
+ 0x820c0580, 0x00000005, 0x04000009, 0x0401f011,
+ 0x820c0580, 0x0000000b, 0x04000005, 0x0401f00d,
+ 0x820c0580, 0x00000003, 0x0402000a, 0x82081d00,
+ 0xffffff00, 0x840c01c0, 0x800c0540, 0x4813c857,
+ 0x480bc857, 0x4807c857, 0x4803c857, 0x48002400,
+ 0x1c01f000, 0x599c0017, 0x8c00050a, 0x04000003,
+ 0x80000580, 0x1c01f000, 0x59a80026, 0x82000500,
+ 0x00000028, 0x04000008, 0x42028800, 0x000007fd,
+ 0x0201f800, 0x00020245, 0x04020003, 0x5934000a,
+ 0x8c000504, 0x1c01f000, 0x4d300000, 0x5934000e,
+ 0x80026540, 0x04000006, 0x0201f800, 0x001062d5,
+ 0x02000800, 0x001064ad, 0x497a680e, 0x5c026000,
+ 0x1c01f000, 0x4d440000, 0x4d340000, 0x80000580,
+ 0x40001800, 0x40028800, 0x82080580, 0x00000008,
+ 0x04020003, 0x42001800, 0x00000001, 0x0201f800,
+ 0x00020245, 0x0402000a, 0x0401fd6d, 0x04020008,
+ 0x800c19c0, 0x04000004, 0x59340405, 0x8c000508,
+ 0x04000003, 0x80081040, 0x04000009, 0x81468800,
+ 0x83440480, 0x00000800, 0x040017f1, 0x80000580,
+ 0x5c026800, 0x5c028800, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x5c026800, 0x5c028800, 0x1c01f000,
+ 0x4a033020, 0x00000000, 0x497b3026, 0x497b3027,
+ 0x497b3028, 0x497b3029, 0x497b302b, 0x497b3021,
+ 0x4a03b104, 0x60000001, 0x1c01f000, 0x4803c856,
+ 0x599c0018, 0x497b3024, 0x497b3025, 0x82000500,
+ 0x0000000f, 0x82000d80, 0x00000005, 0x04000006,
+ 0x82000580, 0x00000006, 0x0400000d, 0x497b3022,
+ 0x1c01f000, 0x4a033022, 0x00000005, 0x599c0216,
+ 0x82000500, 0x0000ffff, 0x04020003, 0x42000000,
+ 0x00000002, 0x48033023, 0x1c01f000, 0x4a033022,
+ 0x00000006, 0x0401f7f6, 0x0401ffe5, 0x4a03c826,
+ 0x00000004, 0x599c0209, 0x80000540, 0x0400001f,
+ 0x599c0207, 0x80000540, 0x04000007, 0x800000cc,
+ 0x599c080d, 0x80040400, 0x4803b100, 0x497bb102,
+ 0x59d80101, 0x599c000d, 0x4803b100, 0x599c000e,
+ 0x4803b101, 0x599c0207, 0x80000540, 0x04020002,
+ 0x497bb102, 0x599c0a09, 0x82040540, 0x00400000,
+ 0x59980822, 0x4803b103, 0x4a03b109, 0x00000004,
+ 0x4a03b104, 0x10000001, 0x800409c0, 0x04020004,
+ 0x4a033020, 0x00000001, 0x1c01f000, 0x4a033020,
+ 0x00000002, 0x0401f7fd, 0x59980022, 0x4803c856,
+ 0x80000540, 0x02000000, 0x000202de, 0x0401f017,
+ 0x42034000, 0x0010b4a4, 0x59a1d81e, 0x80edd9c0,
+ 0x02000800, 0x001005d8, 0x58ec0009, 0x48efc857,
+ 0x49a3c857, 0x492fc857, 0x4803c857, 0x800001c0,
+ 0x08020000, 0x0201f800, 0x001005d8, 0x5931d821,
+ 0x58ef400b, 0x58ec0009, 0x800001c0, 0x08020000,
+ 0x0201f800, 0x001005d8, 0x497a5800, 0x59980026,
+ 0x80000540, 0x0402008c, 0x59d80105, 0x82000d00,
+ 0x00018780, 0x040201da, 0x80000106, 0x82000500,
+ 0x00000003, 0x0c01f001, 0x00104d0a, 0x00104d89,
+ 0x00104d22, 0x00104d50, 0x592c0001, 0x492fc857,
+ 0x492fb107, 0x80000d40, 0x04020007, 0x59940019,
+ 0x80000540, 0x04022003, 0x59980023, 0x48032819,
+ 0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001,
+ 0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40,
+ 0x040207f9, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x0401f7ee, 0x492fc857, 0x492fb107,
+ 0x592c0001, 0x80000d40, 0x04020012, 0x59da5908,
+ 0x835c0480, 0x00000020, 0x0400101c, 0x0402b01a,
+ 0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500,
+ 0x00018780, 0x040201aa, 0x59940019, 0x80000540,
+ 0x04022003, 0x59980023, 0x48032819, 0x1c01f000,
+ 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+ 0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9,
+ 0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+ 0x0401f7e3, 0x0400f009, 0x496a5800, 0x412ed000,
+ 0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x0401f7e0, 0x492fa807, 0x0401f7de,
+ 0x492fc857, 0x59d81108, 0x45681000, 0x400ad000,
+ 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540,
+ 0x00001200, 0x48039000, 0x0402d00c, 0x592c0001,
+ 0x492fc857, 0x492fb107, 0x80000d40, 0x0402001d,
+ 0x59940019, 0x80000540, 0x04022003, 0x59980023,
+ 0x48032819, 0x1c01f000, 0x59d80105, 0x82000500,
+ 0x00018780, 0x04020172, 0x42000000, 0x0010b855,
+ 0x0201f800, 0x0010aa47, 0x59980026, 0x59980828,
+ 0x80000000, 0x48033026, 0x492fc857, 0x800409c0,
+ 0x492f3028, 0x04000003, 0x492c0800, 0x0401f002,
+ 0x492f3029, 0x592c0001, 0x80000d40, 0x040007e5,
+ 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+ 0x815eb800, 0x412ed000, 0x80000d40, 0x040207f9,
+ 0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+ 0x0401f7d8, 0x59980026, 0x59980828, 0x80000000,
+ 0x48033026, 0x492fc857, 0x800409c0, 0x492f3028,
+ 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+ 0x592c0001, 0x80000d40, 0x04020027, 0x0402d00e,
+ 0x59980029, 0x80025d40, 0x0400000f, 0x59980026,
+ 0x80000040, 0x48033026, 0x04020002, 0x48033028,
+ 0x592c0000, 0x48033029, 0x492fc857, 0x492fb107,
+ 0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800,
+ 0x0010aa47, 0x0402e00a, 0x59da5908, 0x496a5800,
+ 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x59d80105,
+ 0x82000500, 0x00018780, 0x04020125, 0x59940019,
+ 0x80000540, 0x04022003, 0x59980023, 0x48032819,
+ 0x1c01f000, 0x497a5801, 0x40065800, 0x592c0001,
+ 0x496a5800, 0x815eb800, 0x412ed000, 0x80000d40,
+ 0x040207f9, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x0401f7ce, 0x592c0204, 0x4803c856,
+ 0x04000008, 0x42034000, 0x0010b4a4, 0x59a1d81e,
+ 0x80edd9c0, 0x02000800, 0x001005d8, 0x0401f003,
+ 0x5931d821, 0x58ef400b, 0x58ec0009, 0x800001c0,
+ 0x08020000, 0x0201f800, 0x001005d8, 0x497a5801,
+ 0x40065800, 0x592c0001, 0x496a5800, 0x412ed000,
+ 0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
+ 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+ 0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9,
+ 0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+ 0x0200e000, 0x000202fb, 0x0201f000, 0x00020302,
+ 0x5998002b, 0x84000540, 0x4803302b, 0x0201f000,
+ 0x0002035e, 0x42000000, 0x0010b855, 0x0201f800,
+ 0x0010aa47, 0x492fc857, 0x59980026, 0x59980828,
+ 0x80000000, 0x48033026, 0x800409c0, 0x492f3028,
+ 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+ 0x592c0001, 0x80000d40, 0x04020002, 0x1c01f000,
+ 0x497a5801, 0x40065800, 0x592c0001, 0x496a5800,
+ 0x412ed000, 0x815eb800, 0x80000d40, 0x040207f9,
+ 0x59c80000, 0x82000540, 0x00001200, 0x48039000,
+ 0x1c01f000, 0x59980026, 0x59980828, 0x80000000,
+ 0x48033026, 0x492fc857, 0x800409c0, 0x492f3028,
+ 0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
+ 0x592c0001, 0x80000d40, 0x04020039, 0x0402d00e,
+ 0x59980029, 0x80025d40, 0x0400000f, 0x59980026,
+ 0x80000040, 0x48033026, 0x04020002, 0x48033028,
+ 0x592c0000, 0x48033029, 0x492fc857, 0x492fb107,
+ 0x0400d7f4, 0x42000000, 0x0010b855, 0x0201f800,
+ 0x0010aa47, 0x0402e01d, 0x59da5908, 0x496a5800,
+ 0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x04006018,
+ 0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd,
+ 0x900001c0, 0x82000540, 0x00000013, 0x4803c011,
+ 0x5998002b, 0x84000500, 0x4803302b, 0x59e00017,
+ 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+ 0x4203e000, 0x30000001, 0x59d80105, 0x82000500,
+ 0x00018780, 0x0402007e, 0x1c01f000, 0x5998002b,
+ 0x84000540, 0x4803302b, 0x0401f7f8, 0x497a5801,
+ 0x40065800, 0x592c0001, 0x496a5800, 0x412ed000,
+ 0x815eb800, 0x80000d40, 0x040207f9, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x0401f7bc,
+ 0x5c000000, 0x4c000000, 0x4803c857, 0x492fc857,
+ 0x4943c857, 0x4807c857, 0x4a025a04, 0x00000103,
+ 0x49425a06, 0x48065a08, 0x4a025c06, 0x0000ffff,
+ 0x813261c0, 0x04000003, 0x59300402, 0x48025c06,
+ 0x832c0400, 0x00000009, 0x04011000, 0x4803c840,
+ 0x4a03c842, 0x0000000b, 0x04011000, 0x1c01f000,
+ 0x4df00000, 0x4203e000, 0x50000000, 0x599cb817,
+ 0x59940019, 0x80000540, 0x04002023, 0x0400000e,
+ 0x59980022, 0x82000580, 0x00000005, 0x0400001e,
+ 0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08,
+ 0x04000005, 0x59a8006a, 0x59a80866, 0x80040580,
+ 0x04020015, 0x8c5cbd08, 0x04020030, 0x59d8090b,
+ 0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e,
+ 0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040,
+ 0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
+ 0x00000002, 0x4203e000, 0x30000001, 0x4a032819,
+ 0xffff0000, 0x04026835, 0x04006003, 0x8c5cbd08,
+ 0x04020860, 0x59980029, 0x80025d40, 0x04000010,
+ 0x59d80105, 0x82000500, 0x00018780, 0x04020020,
+ 0x0402d00d, 0x59980026, 0x492fc857, 0x80000040,
+ 0x48033026, 0x592c0000, 0x492fb107, 0x48033029,
+ 0x04020003, 0x4803c856, 0x48033028, 0x5c03e000,
+ 0x1c01f000, 0x42000000, 0x0010b855, 0x0201f800,
+ 0x0010aa47, 0x0401f7fa, 0x59e0000f, 0x59e0080f,
+ 0x80040580, 0x040207fd, 0x59e00010, 0x59e01010,
+ 0x80081580, 0x040207fd, 0x40065000, 0x80041580,
+ 0x040007c7, 0x040067dc, 0x0401f7ca, 0x4803c857,
+ 0x485fc857, 0x8c00050e, 0x02020800, 0x001005d0,
+ 0x4203e000, 0x50000000, 0x4200b800, 0x00008004,
+ 0x0201f000, 0x001005dd, 0x5998002b, 0x8c000500,
+ 0x04000013, 0x84000500, 0x4803302b, 0x59d8010a,
+ 0x59d8090a, 0x80040580, 0x040207fd, 0x800408e0,
+ 0x82040d40, 0x00000013, 0x4807c011, 0x59e00017,
+ 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+ 0x4203e000, 0x30000001, 0x1c01f000, 0x0402e014,
+ 0x59da5908, 0x496a5800, 0x412ed000, 0x815eb800,
+ 0x0400e7fc, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x59d8090b, 0x59980024, 0x48073024,
+ 0x80040480, 0x04020004, 0x59940019, 0x80000540,
+ 0x04022003, 0x59980823, 0x48072819, 0x59d80105,
+ 0x82000500, 0x00018780, 0x040207c9, 0x1c01f000,
+ 0x59981025, 0x59e00010, 0x59e00810, 0x80041d80,
+ 0x040207fd, 0x80080580, 0x04000013, 0x48073025,
+ 0x59e0000f, 0x59e0100f, 0x80081d80, 0x040207fd,
+ 0x81280580, 0x04000008, 0x400a5000, 0x40080000,
+ 0x80040580, 0x04000003, 0x59980823, 0x48072819,
+ 0x1c01f000, 0x59940019, 0x80000540, 0x040227f8,
+ 0x0401f7fc, 0x59e0000f, 0x59e0100f, 0x80081d80,
+ 0x040207fd, 0x81280580, 0x040007f6, 0x400a5000,
+ 0x59940019, 0x80000540, 0x040027ed, 0x0401f7f1,
+ 0x59a80017, 0x82000c80, 0x0000000a, 0x02021800,
+ 0x001005d8, 0x0c01f809, 0x4a038805, 0x000000f0,
+ 0x59c400a3, 0x82000500, 0x02870000, 0x02020800,
+ 0x001005d8, 0x1c01f000, 0x00104fc5, 0x00104f51,
+ 0x00104f6c, 0x00104f95, 0x00104fb8, 0x00104ff2,
+ 0x00105004, 0x00104f6c, 0x00104fd6, 0x00104f50,
+ 0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9,
+ 0x0201f800, 0x001053ab, 0x59c40805, 0x8c040d0e,
+ 0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
+ 0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017,
+ 0x00000003, 0x0401f00a, 0x4a035017, 0x00000000,
+ 0x0401f007, 0x42000000, 0x0010b844, 0x0201f800,
+ 0x0010aa47, 0x4a035017, 0x00000002, 0x1c01f000,
+ 0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805,
+ 0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c,
+ 0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0,
+ 0x0402001c, 0x0201f800, 0x001053ab, 0x4a038808,
+ 0x00000080, 0x59c40002, 0x8400050c, 0x48038802,
+ 0x0401f9d9, 0x4d3c0000, 0x42027800, 0x00000001,
+ 0x0201f800, 0x00109874, 0x5c027800, 0x4a038808,
+ 0x00000080, 0x4a035017, 0x00000009, 0x0401f009,
+ 0x4a035017, 0x00000001, 0x0401f006, 0x4a035017,
+ 0x00000000, 0x0401f003, 0x4a035017, 0x00000003,
+ 0x1c01f000, 0x0401f8b7, 0x4a038808, 0x00000080,
+ 0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c,
+ 0x04020016, 0x8c040d0e, 0x04020011, 0x82040500,
+ 0x000000f0, 0x04020016, 0x59c40002, 0x8400050c,
+ 0x48038802, 0x0401f9b4, 0x4d3c0000, 0x42027800,
+ 0x00000001, 0x0201f800, 0x00109874, 0x5c027800,
+ 0x4a035017, 0x00000009, 0x0401f009, 0x4a035017,
+ 0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
+ 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+ 0x4a038808, 0x00000008, 0x59c40805, 0x8c040d0c,
+ 0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017,
+ 0x00000001, 0x0401f003, 0x4a035017, 0x00000000,
+ 0x1c01f000, 0x0401f8d3, 0x59c40805, 0x8c040d0c,
+ 0x0402000d, 0x4c040000, 0x0401f882, 0x5c000800,
+ 0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006,
+ 0x4a035017, 0x00000001, 0x0401f003, 0x4a035017,
+ 0x00000002, 0x1c01f000, 0x4a038808, 0x00000008,
+ 0x42001000, 0x00105058, 0x0201f800, 0x00106084,
+ 0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08,
+ 0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e,
+ 0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a,
+ 0x4a035017, 0x00000000, 0x0401f007, 0x42000000,
+ 0x0010b844, 0x0201f800, 0x0010aa47, 0x4a035017,
+ 0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859,
+ 0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
+ 0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017,
+ 0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
+ 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+ 0x4a038808, 0x00000004, 0x0401f846, 0x59c40805,
+ 0x8c040d0a, 0x04020010, 0x8c040d08, 0x0402000b,
+ 0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000c,
+ 0x4a035017, 0x00000001, 0x0401f009, 0x4a035017,
+ 0x00000000, 0x0401f006, 0x4a035017, 0x00000003,
+ 0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
+ 0x0401f91f, 0x02020800, 0x001005d8, 0x59a80805,
+ 0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005,
+ 0x4a038805, 0x00000010, 0x0201f800, 0x00101937,
+ 0x59c40005, 0x8c000508, 0x04000008, 0x4a038808,
+ 0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+ 0x00000001, 0x0401f01a, 0x59c40006, 0x84000548,
+ 0x48038806, 0x0401f016, 0x59a80017, 0x82000580,
+ 0x00000001, 0x0400000c, 0x59a80017, 0x82000580,
+ 0x00000005, 0x0402000c, 0x42000000, 0x0010b844,
+ 0x0201f800, 0x0010aa47, 0x4a035017, 0x00000008,
+ 0x0401f007, 0x42000000, 0x0010b844, 0x0201f800,
+ 0x0010aa47, 0x4a035017, 0x00000004, 0x1c01f000,
+ 0x4803c856, 0x4c040000, 0x4c080000, 0x42000800,
+ 0x00000064, 0x42001000, 0x00105058, 0x0201f800,
+ 0x00106079, 0x5c001000, 0x5c000800, 0x1c01f000,
+ 0x4803c856, 0x4c040000, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x0201f800, 0x00106e21, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x0401ffba, 0x5c000800,
+ 0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000,
+ 0x0201f800, 0x00106c55, 0x4df00000, 0x0201f800,
+ 0x00106e21, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x59c40006, 0x84000500, 0x48038806, 0x0201f800,
+ 0x00106ede, 0x497b8880, 0x0201f800, 0x0010a9c0,
+ 0x0201f800, 0x0010a9ce, 0x0201f800, 0x00101815,
+ 0x4a03504c, 0x00000004, 0x4202d800, 0x00000004,
+ 0x4a038805, 0x00000001, 0x42001000, 0x00105058,
+ 0x0201f800, 0x00106084, 0x0201f800, 0x001006d4,
+ 0x0401f8c1, 0x04000006, 0x42006000, 0xfeffffff,
+ 0x41786800, 0x0201f800, 0x0010427d, 0x0201f800,
+ 0x00100452, 0x42000000, 0x00000001, 0x0201f800,
+ 0x00101590, 0x5c001000, 0x5c000800, 0x1c01f000,
+ 0x59c40008, 0x8c000508, 0x04020007, 0x4a038808,
+ 0x00000010, 0x4201d000, 0x00001388, 0x0201f800,
+ 0x0010608e, 0x1c01f000, 0x4c040000, 0x59a80833,
+ 0x82040580, 0x00000000, 0x0400000b, 0x82040580,
+ 0x00000001, 0x0400000b, 0x82040580, 0x00000002,
+ 0x0400000b, 0x82040580, 0x00000003, 0x0400000b,
+ 0x0401f057, 0x4a035017, 0x00000000, 0x0401f009,
+ 0x4a035017, 0x00000004, 0x0401f006, 0x4a035017,
+ 0x00000001, 0x0401f003, 0x4a035017, 0x00000007,
+ 0x497b8880, 0x4a038893, 0x00000001, 0x41780000,
+ 0x0201f800, 0x00101606, 0x0201f800, 0x00106ede,
+ 0x836c0d80, 0x00000004, 0x04000008, 0x59c40006,
+ 0x82000500, 0xffffff0f, 0x82000540, 0x04000001,
+ 0x48038806, 0x0401f007, 0x59c40006, 0x82000500,
+ 0xffffff0f, 0x82000540, 0x04000000, 0x48038806,
+ 0x0401f875, 0x04020005, 0x59c40806, 0x82040d00,
+ 0xfbffff0f, 0x48078806, 0x4200b000, 0x00000005,
+ 0x59c40005, 0x8c000534, 0x04020033, 0x42006000,
+ 0xfc18ffff, 0x42006800, 0x01000000, 0x0201f800,
+ 0x0010427d, 0x0201f800, 0x00101937, 0x59c408a4,
+ 0x82040d00, 0x0000000f, 0x82040d80, 0x0000000c,
+ 0x0400000a, 0x42006000, 0xfeffffff, 0x42006800,
+ 0x02000000, 0x0201f800, 0x0010427d, 0x8058b040,
+ 0x040207e8, 0x0401f8a1, 0x0401f853, 0x04000006,
+ 0x42006000, 0xfeffffff, 0x41786800, 0x0201f800,
+ 0x0010427d, 0x836c0d80, 0x00000004, 0x04000006,
+ 0x59a8084d, 0x42001000, 0x00105065, 0x0201f800,
+ 0x0010606e, 0x4a035033, 0x00000004, 0x0401fe31,
+ 0x0401f841, 0x04020008, 0x59c408a4, 0x82040d00,
+ 0x0000000f, 0x82040580, 0x0000000c, 0x02020800,
+ 0x001005d8, 0x5c000800, 0x1c01f000, 0x4803c856,
+ 0x4c000000, 0x0201f800, 0x0010609e, 0x4a035010,
+ 0x00ffffff, 0x497b5032, 0x59a8002a, 0x82000500,
+ 0xffff0000, 0x4803502a, 0x497b8880, 0x497b8893,
+ 0x41780000, 0x0201f800, 0x00101606, 0x59c40001,
+ 0x82000500, 0xfffffcff, 0x48038801, 0x42006000,
+ 0xfc18ffff, 0x41786800, 0x0201f800, 0x0010427d,
+ 0x4a038808, 0x00000000, 0x5c000000, 0x800001c0,
+ 0x02020800, 0x0010411d, 0x4a038805, 0x040000f0,
+ 0x59c40006, 0x82000500, 0xffffffcf, 0x82000540,
+ 0x440000c1, 0x48038806, 0x1c01f000, 0x4c5c0000,
+ 0x59a8b832, 0x825cbd80, 0x0000aaaa, 0x5c00b800,
+ 0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+ 0x00000030, 0x825cbd80, 0x00000000, 0x5c00b800,
+ 0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+ 0x00000030, 0x825cbd80, 0x00000010, 0x5c00b800,
+ 0x1c01f000, 0x4c5c0000, 0x599cb818, 0x825cbd00,
+ 0x00000030, 0x825cbd80, 0x00000020, 0x5c00b800,
+ 0x1c01f000, 0x59a80005, 0x4803c857, 0x82000d00,
+ 0x00000013, 0x04000025, 0x599c1017, 0x4d3c0000,
+ 0x82000500, 0x00000011, 0x04000007, 0x42027800,
+ 0x00000400, 0x0201f800, 0x00103b25, 0x0402000a,
+ 0x0401f012, 0x42027800, 0x00000408, 0x0201f800,
+ 0x00103b25, 0x0400000d, 0x42003000, 0x00000003,
+ 0x0401f003, 0x42003000, 0x00000004, 0x42028000,
+ 0x0000000e, 0x0201f800, 0x0010a449, 0x599c1017,
+ 0x8c08150a, 0x04020007, 0x42028000, 0x00000004,
+ 0x0201f800, 0x00101fe5, 0x80000580, 0x0401f80d,
+ 0x5c027800, 0x0401f00a, 0x0201f800, 0x00103b25,
+ 0x04000007, 0x42028000, 0x0000000f, 0x42003000,
+ 0x00000001, 0x0201f800, 0x0010a449, 0x1c01f000,
+ 0x59a80005, 0x04000004, 0x82000540, 0x00000010,
+ 0x0401f003, 0x82000500, 0xffffffef, 0x48035005,
+ 0x4803c857, 0x1c01f000, 0x4803c856, 0x4c580000,
+ 0x42000000, 0x0010b8cb, 0x0201f800, 0x0010aa47,
+ 0x42000800, 0x0010c0f1, 0x59c40003, 0x44000800,
+ 0x59c40004, 0x48000801, 0x59c4000b, 0x48000802,
+ 0x59c4008e, 0x48000803, 0x59c4008f, 0x48000804,
+ 0x59c40090, 0x48000805, 0x59c40091, 0x48000806,
+ 0x59c40092, 0x48000807, 0x59c40093, 0x48000808,
+ 0x59c40099, 0x48000809, 0x59c4009e, 0x4800080a,
+ 0x59c400aa, 0x4800080b, 0x59c400af, 0x4800080c,
+ 0x59c400b2, 0x4800080d, 0x59c400b1, 0x4800080e,
+ 0x82040c00, 0x0000000f, 0x41c41800, 0x4200b000,
+ 0x00000030, 0x580c0050, 0x44000800, 0x80040800,
+ 0x800c1800, 0x8058b040, 0x040207fb, 0x41c41800,
+ 0x4200b000, 0x00000020, 0x580c0010, 0x44000800,
+ 0x80040800, 0x800c1800, 0x8058b040, 0x040207fb,
+ 0x497b8830, 0x4200b000, 0x00000040, 0x59c40031,
+ 0x44000800, 0x80040800, 0x8058b040, 0x040207fc,
+ 0x497b88ac, 0x4200b000, 0x00000010, 0x59c400ad,
+ 0x44000800, 0x80040800, 0x8058b040, 0x040207fc,
+ 0x59c41001, 0x4c080000, 0x8408150c, 0x480b8801,
+ 0x4a0370e4, 0x00000300, 0x4a0370e5, 0xb0000000,
+ 0x42000800, 0x00000800, 0x80040840, 0x02000800,
+ 0x001005d8, 0x59b800e5, 0x8c000538, 0x040207fb,
+ 0x4a0370e4, 0x00000200, 0x42006000, 0xffffffff,
+ 0x42006800, 0x80000000, 0x0201f800, 0x0010427d,
+ 0x4a038807, 0x00000001, 0x497b8807, 0x4a038808,
+ 0x00000010, 0x42006000, 0xfcf8ffff, 0x42006800,
+ 0x01000000, 0x0201f800, 0x0010427d, 0x5c001000,
+ 0x480b8801, 0x42000800, 0x0010c0f1, 0x50040000,
+ 0x48038803, 0x58040001, 0x48038804, 0x58040002,
+ 0x4803880b, 0x58040003, 0x4803888e, 0x58040004,
+ 0x4803888f, 0x58040005, 0x48038890, 0x58040006,
+ 0x48038891, 0x58040007, 0x48038892, 0x58040008,
+ 0x48038893, 0x58040009, 0x48038899, 0x5804000a,
+ 0x4803889e, 0x5804000b, 0x480388aa, 0x5804000c,
+ 0x480388af, 0x5804000d, 0x480388b2, 0x5804000e,
+ 0x480388b1, 0x82040c00, 0x0000000f, 0x41c41800,
+ 0x4200b000, 0x00000030, 0x50040000, 0x48001850,
+ 0x80040800, 0x800c1800, 0x8058b040, 0x040207fb,
+ 0x41c41800, 0x4200b000, 0x00000020, 0x50040000,
+ 0x48001810, 0x80040800, 0x800c1800, 0x8058b040,
+ 0x040207fb, 0x497b8830, 0x4200b000, 0x00000040,
+ 0x50040000, 0x48038831, 0x80040800, 0x8058b040,
+ 0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010,
+ 0x50040000, 0x480388ad, 0x80040800, 0x8058b040,
+ 0x040207fc, 0x497b8880, 0x41780000, 0x0201f800,
+ 0x00101606, 0x59c408a4, 0x82040d00, 0x0000000f,
+ 0x82040580, 0x0000000c, 0x02020800, 0x001005d8,
+ 0x4a038805, 0x04000000, 0x5c00b000, 0x1c01f000,
+ 0x4803c856, 0x4c580000, 0x4ce80000, 0x42000000,
+ 0x0010b845, 0x0201f800, 0x0010aa47, 0x59c41008,
+ 0x4c080000, 0x82080500, 0xffffff7f, 0x48038808,
+ 0x59c40004, 0x82000500, 0x00003e02, 0x04000005,
+ 0x4201d000, 0x00000014, 0x0201f800, 0x0010608e,
+ 0x59c40006, 0x82000500, 0xffffff0f, 0x48038806,
+ 0x4a038805, 0x00000010, 0x4a038808, 0x00000004,
+ 0x4200b000, 0x00000065, 0x59c40005, 0x8c000508,
+ 0x04020012, 0x4201d000, 0x000003e8, 0x0201f800,
+ 0x0010608e, 0x8058b040, 0x040207f8, 0x0201f800,
+ 0x00106ede, 0x4a038808, 0x00000008, 0x4a035033,
+ 0x00000001, 0x4202d800, 0x00000001, 0x82000540,
+ 0x00000001, 0x0401f030, 0x0201f800, 0x00100ae0,
+ 0x42000000, 0x0010b8a8, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00100ef4, 0x497b8880, 0x59a8002a,
+ 0x82000500, 0x0000ffff, 0x4c000000, 0x0201f800,
+ 0x00101606, 0x5c000000, 0x48038880, 0x4a038808,
+ 0x00000000, 0x4200b000, 0x00000065, 0x4a038805,
+ 0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+ 0x000000f0, 0x59c40005, 0x80040d00, 0x04000008,
+ 0x4201d000, 0x000003e8, 0x0201f800, 0x0010608e,
+ 0x8058b040, 0x040207f2, 0x0401f7d1, 0x59c40006,
+ 0x82000540, 0x000000f0, 0x48038806, 0x59a8001e,
+ 0x80000540, 0x04020002, 0x80000000, 0x48038893,
+ 0x80000580, 0x5c001000, 0x4df00000, 0x0201f800,
+ 0x0010195d, 0x5c03e000, 0x480b8808, 0x5c01d000,
+ 0x5c00b000, 0x1c01f000, 0x4803c856, 0x4c580000,
+ 0x4ce80000, 0x59c41008, 0x82080500, 0xffffff7f,
+ 0x48038808, 0x4c080000, 0x59c40004, 0x82000500,
+ 0x00003e02, 0x04000005, 0x4201d000, 0x00000014,
+ 0x0201f800, 0x0010608e, 0x0201f800, 0x00100ae0,
+ 0x42000000, 0x0010b8a9, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00100ef4, 0x4a038808, 0x00000002,
+ 0x80000580, 0x48038880, 0x48038893, 0x0201f800,
+ 0x00101606, 0x4200b000, 0x00000384, 0x4a038805,
+ 0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+ 0x000000f0, 0x59c40005, 0x80040d00, 0x04000015,
+ 0x82000500, 0x000000d0, 0x04020012, 0x4201d000,
+ 0x00000067, 0x0201f800, 0x0010608e, 0x8058b040,
+ 0x040207ef, 0x0201f800, 0x00106ede, 0x4a038808,
+ 0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+ 0x00000001, 0x82000540, 0x00000001, 0x0401f010,
+ 0x497b8880, 0x59a8001e, 0x80000540, 0x04020002,
+ 0x80000000, 0x48038893, 0x59a8002a, 0x82000500,
+ 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101606,
+ 0x5c000000, 0x48038880, 0x80000580, 0x5c001000,
+ 0x4df00000, 0x0201f800, 0x0010195d, 0x5c03e000,
+ 0x480b8808, 0x5c01d000, 0x5c00b000, 0x1c01f000,
+ 0x4803c856, 0x59c40004, 0x82000500, 0x00003e02,
+ 0x0400000a, 0x0201f800, 0x00106ede, 0x4a038808,
+ 0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
+ 0x00000001, 0x0401f052, 0x0201f800, 0x00100ae0,
+ 0x42000000, 0x0010b8aa, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00100ef4, 0x59c40006, 0x84000508,
+ 0x48038806, 0x4a038805, 0x00000010, 0x59a80805,
+ 0x84040d4c, 0x48075005, 0x42000800, 0x00000064,
+ 0x42001000, 0x00105058, 0x0201f800, 0x0010606e,
+ 0x4a038808, 0x00000000, 0x497b8880, 0x4a038805,
+ 0x000000f0, 0x0201f800, 0x00101937, 0x42000800,
+ 0x000000f0, 0x59c40005, 0x80040d00, 0x0400000e,
+ 0x82000500, 0x000000e0, 0x0402000b, 0x4201d000,
+ 0x000003e8, 0x0201f800, 0x0010608e, 0x0201f800,
+ 0x00105f48, 0x59940004, 0x80000540, 0x040207ec,
+ 0x0401f023, 0x4c080000, 0x42001000, 0x00105065,
+ 0x0201f800, 0x00105f90, 0x42001000, 0x00105058,
+ 0x0201f800, 0x00106084, 0x5c001000, 0x497b8880,
+ 0x59a8001e, 0x80000540, 0x04020002, 0x80000000,
+ 0x48038893, 0x59a8002a, 0x82000500, 0x0000ffff,
+ 0x4c000000, 0x0201f800, 0x00101606, 0x5c000000,
+ 0x48038880, 0x59a80805, 0x84040d0c, 0x48075005,
+ 0x59c40006, 0x84000548, 0x48038806, 0x0201f800,
+ 0x0010195d, 0x4a038808, 0x00000080, 0x1c01f000,
+ 0x4803c856, 0x4d400000, 0x4d3c0000, 0x0201f800,
+ 0x00106ede, 0x0201f800, 0x0010ab33, 0x04020025,
+ 0x599c1017, 0x59a80805, 0x8c040d00, 0x0402000c,
+ 0x8c08151a, 0x0400001f, 0x84040d42, 0x48075005,
+ 0x42028000, 0x00000004, 0x42027800, 0x0000000c,
+ 0x8c081508, 0x04020008, 0x0401f012, 0x42028000,
+ 0x00000004, 0x42027800, 0x00000004, 0x8c081508,
+ 0x0400000c, 0x4d400000, 0x42028000, 0x0000000e,
+ 0x42028800, 0x0000ffff, 0x0201f800, 0x0010a446,
+ 0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005,
+ 0x4943c857, 0x493fc857, 0x0201f800, 0x00101fe5,
+ 0x497b8880, 0x4202d800, 0x00000001, 0x0401fcfb,
+ 0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800,
+ 0x00100ae0, 0x42000000, 0x0010b8ab, 0x0201f800,
+ 0x0010aa47, 0x0201f800, 0x00100ef4, 0x42000000,
+ 0x00000001, 0x0201f800, 0x00101606, 0x4a038880,
+ 0x00000001, 0x0201f000, 0x0010195d, 0x4202e000,
+ 0x00000000, 0x4a033015, 0x00000001, 0x497b301d,
+ 0x497b3006, 0x4a03b004, 0x60000001, 0x59d80005,
+ 0x4a03b004, 0x90000001, 0x4a03a804, 0x60000001,
+ 0x59d40005, 0x4a03a804, 0x90000001, 0x0201f000,
+ 0x00105983, 0x4a03c825, 0x00000004, 0x4a03c827,
+ 0x00000004, 0x599c0409, 0x80000d40, 0x04000020,
+ 0x599c0407, 0x80000540, 0x04000007, 0x800000cc,
+ 0x599c100b, 0x80080400, 0x4803b000, 0x497bb002,
+ 0x59d80001, 0x599c000b, 0x4803b000, 0x599c000c,
+ 0x4803b001, 0x599c0407, 0x80000540, 0x04020002,
+ 0x497bb002, 0x599c0c09, 0x82040540, 0x00400000,
+ 0x4803b003, 0x4a03b009, 0x00000004, 0x4a03b004,
+ 0x10000001, 0x59e00803, 0x82040d00, 0xfffffeff,
+ 0x82040d40, 0x00008000, 0x4807c003, 0x599c040a,
+ 0x80000540, 0x04000020, 0x599c0408, 0x80000540,
+ 0x04000007, 0x800000cc, 0x599c100f, 0x80080400,
+ 0x4803a800, 0x497ba802, 0x59d40001, 0x599c000f,
+ 0x4803a800, 0x599c0010, 0x4803a801, 0x599c0408,
+ 0x80000540, 0x04020002, 0x497ba802, 0x599c0c0a,
+ 0x82040540, 0x00400000, 0x4803a803, 0x4a03a809,
+ 0x00000004, 0x4a03a804, 0x10000001, 0x59e00803,
+ 0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000,
+ 0x4807c003, 0x800409c0, 0x04000007, 0x4202e000,
+ 0x00000001, 0x0200b800, 0x00020551, 0x0200f000,
+ 0x00020566, 0x1c01f000, 0x0201f800, 0x001005d8,
+ 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
+ 0x59981005, 0x800811c0, 0x0400001e, 0x58080005,
+ 0x82000d00, 0x43018780, 0x02020000, 0x00105846,
+ 0x8c000508, 0x04000015, 0x580a5808, 0x592c0204,
+ 0x497a5800, 0x497a5801, 0x82000500, 0x000000ff,
+ 0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f,
+ 0x5c03e000, 0x83700580, 0x00000003, 0x040007e6,
+ 0x0200f800, 0x00020566, 0x0200b000, 0x00020551,
+ 0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9,
+ 0x0401f8de, 0x0401f7fd, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x001054a1, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105519, 0x00105491, 0x00105491, 0x001054a1,
+ 0x001054a1, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x492fc857, 0x42000000, 0x0010b85e,
+ 0x0201f800, 0x0010aa47, 0x42000000, 0x00000400,
+ 0x0401f019, 0x492fc857, 0x42000000, 0x0010b85d,
+ 0x0201f800, 0x0010aa47, 0x42000000, 0x00001000,
+ 0x0401f011, 0x492fc857, 0x42000000, 0x0010b85c,
+ 0x0201f800, 0x0010aa47, 0x42000000, 0x00002000,
+ 0x0401f009, 0x492fc857, 0x42000000, 0x0010b85f,
+ 0x0201f800, 0x0010aa47, 0x42000000, 0x00000800,
+ 0x0401f001, 0x4803c857, 0x4202e000, 0x00000001,
+ 0x592c0c04, 0x82040d00, 0xffff80ff, 0x80040540,
+ 0x48025c04, 0x0201f000, 0x000202da, 0x592c0204,
+ 0x492fc857, 0x80000110, 0x040007db, 0x80000040,
+ 0x04000025, 0x48033002, 0x492f3003, 0x492f3004,
+ 0x4a033008, 0x001054e5, 0x4202e000, 0x00000003,
+ 0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110,
+ 0x040007cd, 0x80000040, 0x04000033, 0x48033002,
+ 0x492f3003, 0x492f3004, 0x4a033008, 0x00105501,
+ 0x4202e000, 0x00000003, 0x1c01f000, 0x0201f800,
+ 0x0010ab33, 0x02020000, 0x000204d9, 0x42028000,
+ 0x00000028, 0x41780800, 0x417a6000, 0x0201f800,
+ 0x00104e70, 0x0201f800, 0x001091c6, 0x0201f000,
+ 0x000202da, 0x592c0a0a, 0x8c040d02, 0x04020016,
+ 0x59a80021, 0x492fc857, 0x80000540, 0x0402000f,
+ 0x592c0207, 0x80000540, 0x04000005, 0x0201f800,
+ 0x00104326, 0x04020004, 0x1c01f000, 0x42000000,
+ 0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06,
+ 0x0201f000, 0x000202da, 0x42000000, 0x00000028,
+ 0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000,
+ 0x0010665b, 0x592c0208, 0x492fc857, 0x82000c80,
+ 0x0000199a, 0x040217a4, 0x592c0408, 0x80000540,
+ 0x040207a1, 0x59a80821, 0x800409c0, 0x04020009,
+ 0x592c0207, 0x80000540, 0x0400079b, 0x497a5a06,
+ 0x0201f800, 0x00104385, 0x04020004, 0x1c01f000,
+ 0x42000000, 0x00000028, 0x48025a06, 0x0201f000,
+ 0x000202da, 0x59980804, 0x59980002, 0x48065800,
+ 0x492c0801, 0x492f3004, 0x80000040, 0x48033002,
+ 0x04000002, 0x1c01f000, 0x599a5803, 0x59980008,
+ 0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06,
+ 0x592c0406, 0x4803c856, 0x82000500, 0x000000ff,
+ 0x4200b800, 0x00000001, 0x82000d80, 0x00000001,
+ 0x04000015, 0x417a8800, 0x4200b800, 0x000007f0,
+ 0x82000d80, 0x00000002, 0x0400000f, 0x80000540,
+ 0x02020000, 0x000202da, 0x592e8a06, 0x0201f800,
+ 0x00020245, 0x02020000, 0x000202da, 0x592e9008,
+ 0x592e9809, 0x0201f800, 0x00104713, 0x0201f000,
+ 0x000202da, 0x59a80805, 0x84040d00, 0x48075005,
+ 0x0201f800, 0x00020245, 0x02000800, 0x0010482c,
+ 0x81468800, 0x805cb840, 0x040207fa, 0x0201f000,
+ 0x000202da, 0x592c0a08, 0x4807c857, 0x82040580,
+ 0x0000000e, 0x04000045, 0x82040580, 0x00000046,
+ 0x04000046, 0x82040580, 0x00000045, 0x04000020,
+ 0x82040580, 0x00000029, 0x04000010, 0x82040580,
+ 0x0000002a, 0x04000009, 0x82040580, 0x0000000f,
+ 0x040001fc, 0x82040580, 0x0000002e, 0x040001f9,
+ 0x4807c856, 0x0401f1f2, 0x59a80805, 0x84040d04,
+ 0x48075005, 0x0401f1f3, 0x592e8a06, 0x0201f800,
+ 0x00020245, 0x040201ef, 0x59340200, 0x84000518,
+ 0x48026a00, 0x592e6009, 0x4933c857, 0x83300580,
+ 0xffffffff, 0x0402002a, 0x0401f1e6, 0x592c1407,
+ 0x480bc857, 0x0201f800, 0x00109410, 0x411e6000,
+ 0x04020003, 0x4803c856, 0x0401f1d9, 0x592e3809,
+ 0x591c1414, 0x84081516, 0x84081554, 0x480a3c14,
+ 0x4a026403, 0x0000003a, 0x592c040b, 0x80000540,
+ 0x04000007, 0x4a026403, 0x0000003b, 0x592c020c,
+ 0x4802641a, 0x592c040c, 0x4802621a, 0x4a026203,
+ 0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+ 0x00020721, 0x0401f1c7, 0x59a80068, 0x84000510,
+ 0x48035068, 0x0401f1c3, 0x592c1207, 0x8c081500,
+ 0x040201c0, 0x592e8a06, 0x592e6009, 0x0201f800,
+ 0x0010941a, 0x04020003, 0x4803c856, 0x0401f1b4,
+ 0x59300c06, 0x82040580, 0x00000004, 0x04000003,
+ 0x4803c856, 0x0401f1ae, 0x59300a03, 0x82040580,
+ 0x00000007, 0x04000003, 0x4803c856, 0x0401f1a8,
+ 0x59300c03, 0x82040580, 0x00000001, 0x04000021,
+ 0x82040580, 0x00000003, 0x04000016, 0x82040580,
+ 0x00000006, 0x04000020, 0x82040580, 0x00000008,
+ 0x04000015, 0x82040580, 0x0000000a, 0x0400000a,
+ 0x82040580, 0x0000000c, 0x04000004, 0x82040580,
+ 0x0000002e, 0x04020018, 0x42000800, 0x00000009,
+ 0x0401f013, 0x42000800, 0x00000005, 0x0401f010,
+ 0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406,
+ 0x00000001, 0x42000800, 0x00000003, 0x0401f008,
+ 0x417a7800, 0x0201f800, 0x0010203c, 0x4a026406,
+ 0x00000001, 0x42000800, 0x0000000b, 0x0201f800,
+ 0x00104571, 0x4a026203, 0x00000001, 0x0201f800,
+ 0x0010672b, 0x0401f17b, 0x40000800, 0x58040000,
+ 0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000,
+ 0x492fc857, 0x59300c06, 0x82040580, 0x00000006,
+ 0x04020094, 0x0201f800, 0x001049e7, 0x04020005,
+ 0x59340200, 0x8c00051a, 0x02000000, 0x00020533,
+ 0x59340200, 0x8c00050e, 0x0400008a, 0x59300203,
+ 0x42027800, 0x00000001, 0x82000580, 0x00000007,
+ 0x02020000, 0x00020533, 0x4a026203, 0x00000002,
+ 0x0201f000, 0x00020533, 0x42028000, 0x00000002,
+ 0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800,
+ 0x0010a1d1, 0x5c025800, 0x59300c06, 0x4807c857,
+ 0x82040580, 0x00000007, 0x04020063, 0x492fc857,
+ 0x4a025a06, 0x00000001, 0x0201f000, 0x000202da,
+ 0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c,
+ 0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a,
+ 0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003,
+ 0x8c10251e, 0x04000064, 0x0201f800, 0x0002075a,
+ 0x0400006b, 0x592c240a, 0x49366009, 0x49325809,
+ 0x4a026406, 0x00000006, 0x4a026203, 0x00000007,
+ 0x0201f000, 0x0002052f, 0x592c0a0c, 0x5934000f,
+ 0x41784000, 0x80001540, 0x0400006d, 0x58080204,
+ 0x82000500, 0x000000ff, 0x82000580, 0x00000012,
+ 0x04020004, 0x5808020c, 0x80040580, 0x04000004,
+ 0x58080000, 0x40084000, 0x0401f7f3, 0x58080000,
+ 0x49781000, 0x802041c0, 0x04000006, 0x48004000,
+ 0x80000540, 0x04020007, 0x48226810, 0x0401f005,
+ 0x4802680f, 0x80000540, 0x04020002, 0x497a6810,
+ 0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002,
+ 0x0201f800, 0x000202da, 0x5c025800, 0x0401f7bc,
+ 0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206,
+ 0x82000580, 0x0000ffff, 0x04020012, 0x592e6009,
+ 0x83300580, 0xffffffff, 0x040007b1, 0x83300480,
+ 0x0010d1c0, 0x04001010, 0x59a8000b, 0x81300480,
+ 0x0402100d, 0x59300008, 0x800001c0, 0x04020005,
+ 0x59300203, 0x82000580, 0x00000007, 0x04000797,
+ 0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000,
+ 0x000202da, 0x492fc857, 0x4a025a06, 0x00000008,
+ 0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06,
+ 0x00000045, 0x0201f000, 0x000202da, 0x492fc857,
+ 0x4a025a06, 0x0000002a, 0x0201f000, 0x000202da,
+ 0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000,
+ 0x000202da, 0x492fc857, 0x4a025a06, 0x00000006,
+ 0x0201f000, 0x000202da, 0x492fc857, 0x4a025a06,
+ 0x0000000e, 0x0201f000, 0x000202da, 0x59340010,
+ 0x492e6810, 0x492fc857, 0x80000d40, 0x04000003,
+ 0x492c0800, 0x1c01f000, 0x5934040b, 0x492e680f,
+ 0x492fc857, 0x4803c857, 0x80000540, 0x04020003,
+ 0x4a026a03, 0x00000001, 0x1c01f000, 0x59a8000e,
+ 0x81640480, 0x0402176e, 0x42026000, 0x0010d1c0,
+ 0x59300009, 0x81340580, 0x04020004, 0x59300202,
+ 0x80040580, 0x04000759, 0x83326400, 0x00000024,
+ 0x41580000, 0x81300480, 0x040017f6, 0x0401f760,
+ 0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a,
+ 0x040215f1, 0x592c0204, 0x80000112, 0x040205de,
+ 0x592e8a06, 0x0201f800, 0x00020245, 0x04020059,
+ 0x0201f800, 0x001049e7, 0x04020059, 0x592e780a,
+ 0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021,
+ 0x80000540, 0x0402004f, 0x0201f800, 0x00104838,
+ 0x040005dd, 0x833c1d00, 0x0000001f, 0x040005da,
+ 0x592c0207, 0x82000c80, 0x00001000, 0x040215d6,
+ 0x800000c2, 0x800008c4, 0x8005d400, 0x592e9008,
+ 0x592e9809, 0x5934080d, 0x800409c0, 0x0402002e,
+ 0x833c1d00, 0x0000001f, 0x81780040, 0x80000000,
+ 0x800c1902, 0x040217fe, 0x040205c7, 0x0c01f001,
+ 0x001056e9, 0x001056ec, 0x001056f9, 0x001056fc,
+ 0x001056ff, 0x0201f800, 0x0010903e, 0x0401f01a,
+ 0x0201f800, 0x0010480b, 0x04000027, 0x80e9d1c0,
+ 0x02020800, 0x00105fae, 0x42028000, 0x00000005,
+ 0x417a9000, 0x417a9800, 0x0201f800, 0x0010904e,
+ 0x0401f00d, 0x42027000, 0x0000004d, 0x0401f006,
+ 0x42027000, 0x0000004e, 0x0401f003, 0x42027000,
+ 0x00000052, 0x0201f800, 0x001046c9, 0x02020800,
+ 0x0010907e, 0x04000010, 0x8d3e7d3e, 0x04020017,
+ 0x1c01f000, 0x58040002, 0x80000540, 0x04020007,
+ 0x4d3c0000, 0x40067800, 0x0201f800, 0x001047eb,
+ 0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030,
+ 0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a,
+ 0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06,
+ 0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06,
+ 0x00000000, 0x4a025a04, 0x00000103, 0x0201f000,
+ 0x000202da, 0x492fc857, 0x592c0204, 0x80000110,
+ 0x80000040, 0x04000002, 0x0401f56f, 0x592c0207,
+ 0x82000500, 0x000003ff, 0x48025a07, 0x8c000506,
+ 0x04000004, 0x82000500, 0x00000070, 0x04020004,
+ 0x59a80821, 0x800409c0, 0x04020018, 0x4a025a06,
+ 0x0000dead, 0x592c0408, 0x82000500, 0x0000f0ff,
+ 0x48025c08, 0x0201f800, 0x001043b4, 0x04020002,
+ 0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009,
+ 0x0201f800, 0x0010955f, 0x0401f80f, 0x44042800,
+ 0x82580580, 0x00000002, 0x04020002, 0x48082801,
+ 0x0201f000, 0x000202da, 0x42028000, 0x00000031,
+ 0x42000800, 0x00000001, 0x4200b000, 0x00000001,
+ 0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00,
+ 0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857,
+ 0x4a025a08, 0x00000006, 0x0201f000, 0x000202da,
+ 0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000,
+ 0x000202da, 0x492fc857, 0x592c040a, 0x82000500,
+ 0x00000003, 0x04000020, 0x0201f800, 0x0002075a,
+ 0x04000021, 0x592c0204, 0x492e6008, 0x82000500,
+ 0x000000ff, 0x82000580, 0x00000045, 0x0400000e,
+ 0x592c000b, 0x0201f800, 0x00105c9a, 0x02000800,
+ 0x00020245, 0x04020018, 0x42027000, 0x00000041,
+ 0x49366009, 0x4a026406, 0x00000001, 0x0201f000,
+ 0x000207a1, 0x59300015, 0x8400055e, 0x48026015,
+ 0x42026800, 0x0010b524, 0x42027000, 0x00000040,
+ 0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000,
+ 0x000202da, 0x4a025a06, 0x0000002c, 0x0201f000,
+ 0x000202da, 0x4a025a06, 0x00000028, 0x0201f800,
+ 0x000202da, 0x0201f000, 0x0002077d, 0x492fc857,
+ 0x0201f800, 0x001062e1, 0x0400000b, 0x592c0204,
+ 0x80000110, 0x80000040, 0x040204fb, 0x592c0c06,
+ 0x800409c0, 0x04000009, 0x42000000, 0x00000102,
+ 0x0401f003, 0x42000000, 0x00000104, 0x48025a06,
+ 0x0201f000, 0x000202da, 0x592c0c07, 0x800409c0,
+ 0x04000024, 0x82040480, 0x00000005, 0x04021021,
+ 0x4c040000, 0x80040800, 0x0201f800, 0x00106306,
+ 0x5c001000, 0x04020018, 0x832c0400, 0x00000008,
+ 0x4000a000, 0x0201f800, 0x0010632f, 0x04020012,
+ 0x592c1207, 0x82cc0580, 0x0010b50e, 0x04020009,
+ 0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500,
+ 0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001,
+ 0x42000000, 0x00000000, 0x48025a06, 0x0201f000,
+ 0x000202da, 0x42000000, 0x00000103, 0x0401f7fb,
+ 0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857,
+ 0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043,
+ 0x592c4007, 0x42026000, 0x0010d1c0, 0x41581800,
+ 0x400c0000, 0x81300480, 0x04021023, 0x59300203,
+ 0x82000580, 0x00000000, 0x04000007, 0x59300008,
+ 0x80000d40, 0x04000004, 0x58040005, 0x80200580,
+ 0x04000004, 0x83326400, 0x00000024, 0x0401f7f1,
+ 0x58040204, 0x82000500, 0x000000ff, 0x82000d80,
+ 0x00000053, 0x04000007, 0x82000d80, 0x00000048,
+ 0x04000004, 0x82000580, 0x00000018, 0x04020023,
+ 0x4d2c0000, 0x0201f800, 0x00108be3, 0x5c025800,
+ 0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000,
+ 0x000202da, 0x592e8a06, 0x83440480, 0x000007f0,
+ 0x04021016, 0x83440400, 0x0010ac00, 0x50000000,
+ 0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800,
+ 0x001047cb, 0x0400000c, 0x42028000, 0x00000005,
+ 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+ 0x001091cc, 0x0201f800, 0x000202da, 0x5c025800,
+ 0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031,
+ 0x0201f000, 0x000202da, 0x492fc857, 0x4d2c0000,
+ 0x0201f800, 0x001007e4, 0x04000016, 0x492fc857,
+ 0x412f4000, 0x0201f800, 0x001007e4, 0x0400000e,
+ 0x492fc857, 0x412dd800, 0x0201f800, 0x00103b28,
+ 0x0201f800, 0x00103b32, 0x49a1d80b, 0x5c025800,
+ 0x492dd80a, 0x0201f800, 0x00102214, 0x0201f000,
+ 0x00102233, 0x41a25800, 0x0201f800, 0x001007f4,
+ 0x5c025800, 0x4a025a06, 0x00004005, 0x4a025c06,
+ 0x00000002, 0x0201f000, 0x000202da, 0x4807c857,
+ 0x485fc857, 0x4200b800, 0x00000001, 0x5c000800,
+ 0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857,
+ 0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857,
+ 0x8c00050e, 0x02020800, 0x001005d0, 0x4203e000,
+ 0x50000000, 0x4200b800, 0x00008003, 0x0201f000,
+ 0x001005dd, 0x592c0204, 0x80000110, 0x80000040,
+ 0x04020441, 0x0201f800, 0x00104a34, 0x04020002,
+ 0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e,
+ 0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000,
+ 0x000202da, 0x592c0204, 0x80000110, 0x80000040,
+ 0x04020431, 0x0201f800, 0x00104b8b, 0x04020002,
+ 0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812,
+ 0x0201f000, 0x000202da, 0x592c0204, 0x80000110,
+ 0x04000425, 0x80000040, 0x0402000c, 0x4202e000,
+ 0x00000001, 0x592c020a, 0x8c000504, 0x02000000,
+ 0x000204d0, 0x592c0207, 0x82000c80, 0x00001001,
+ 0x04021429, 0x0401f009, 0x4202e000, 0x00000003,
+ 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008,
+ 0x000204d0, 0x1c01f000, 0x4202e000, 0x00000002,
+ 0x42000000, 0x0010beda, 0x50007000, 0x492c700b,
+ 0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812,
+ 0x48007007, 0x48047008, 0x592c1013, 0x82080500,
+ 0xffff0000, 0x04000003, 0x0201f800, 0x001005d8,
+ 0x4978700d, 0x82080480, 0x00000180, 0x4803c857,
+ 0x04001007, 0x4800700f, 0x4a007005, 0x00000180,
+ 0x4a007004, 0x00000060, 0x0401f005, 0x4978700f,
+ 0x48087005, 0x80081104, 0x48087004, 0x5838000a,
+ 0x48007003, 0x40381000, 0x0201f000, 0x00100858,
+ 0x0201f800, 0x001007d3, 0x04000003, 0x59980007,
+ 0x0801f000, 0x1c01f000, 0x40307000, 0x5838000b,
+ 0x80025d40, 0x0400001b, 0x58380002, 0x82000580,
+ 0x00000100, 0x0400001d, 0x4c380000, 0x592c0204,
+ 0x82000500, 0x000000ff, 0x82000580, 0x00000012,
+ 0x0400000b, 0x592c0208, 0x8400054e, 0x48025a08,
+ 0x4a025a06, 0x00000002, 0x4a025a04, 0x00000103,
+ 0x0201f800, 0x000202c1, 0x0401f005, 0x4a025a06,
+ 0x00000010, 0x0201f800, 0x000202da, 0x5c007000,
+ 0x4202e000, 0x00000001, 0x4a007002, 0x00000100,
+ 0x49787010, 0x1c01f000, 0x58380004, 0x82000480,
+ 0x00000003, 0x04000087, 0x58380010, 0x8c000500,
+ 0x04020019, 0x4200b000, 0x00000003, 0x832cac00,
+ 0x00000011, 0x5838000a, 0x5838100d, 0x8008a400,
+ 0x4c380000, 0x0201f800, 0x0010ab17, 0x5c007000,
+ 0x5838000d, 0x82000400, 0x00000003, 0x4800700d,
+ 0x4a007010, 0x00000001, 0x58380004, 0x82000480,
+ 0x00000003, 0x48007004, 0x82000580, 0x00000003,
+ 0x0400006c, 0x5838000e, 0x80001d40, 0x04020020,
+ 0x4c380000, 0x0201f800, 0x001007d3, 0x5c007000,
+ 0x04000010, 0x4a025a04, 0x0000010a, 0x42001800,
+ 0x00000005, 0x480c700e, 0x5838000c, 0x80000540,
+ 0x04020002, 0x5838000b, 0x40000800, 0x492c0801,
+ 0x492c700c, 0x42000800, 0x0000000f, 0x0401f011,
+ 0x4202e000, 0x00000008, 0x4a033007, 0x00105915,
+ 0x1c01f000, 0x4202e000, 0x00000002, 0x42000000,
+ 0x0010beda, 0x50007000, 0x0401f7e7, 0x583a580c,
+ 0x400c0000, 0x42000800, 0x00000014, 0x80040c80,
+ 0x58381004, 0x5838000f, 0x41783000, 0x80000540,
+ 0x04020005, 0x84183540, 0x82081480, 0x00000003,
+ 0x0400003c, 0x40080000, 0x80040480, 0x04001002,
+ 0x40080800, 0x4004b000, 0x412c0000, 0x800c0400,
+ 0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400,
+ 0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000,
+ 0x0201f800, 0x0010ab17, 0x5c007000, 0x5c001800,
+ 0x5c000800, 0x40040000, 0x58381004, 0x80080480,
+ 0x48007004, 0x82000580, 0x00000003, 0x04000002,
+ 0x84183500, 0x5c000000, 0x80041400, 0x82080480,
+ 0x00000060, 0x04020003, 0x84183542, 0x41781000,
+ 0x400c0000, 0x80041c00, 0x820c0480, 0x00000014,
+ 0x04020003, 0x84183544, 0x40001800, 0x40080800,
+ 0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001,
+ 0x00105960, 0x00105964, 0x00105962, 0x00105960,
+ 0x001058fc, 0x00105964, 0x00105962, 0x00105960,
+ 0x0201f800, 0x001005d8, 0x5838100f, 0x0401f739,
+ 0x5838080d, 0x82040400, 0x00000002, 0x5838100a,
+ 0x80080400, 0x50001000, 0x800811c0, 0x0402000f,
+ 0x4202e000, 0x00000001, 0x583a580b, 0x4978700b,
+ 0x49787010, 0x592c0204, 0x82000500, 0x000000ff,
+ 0x82000580, 0x00000012, 0x02000000, 0x00020507,
+ 0x0201f000, 0x000204d0, 0x5838000a, 0x80040c00,
+ 0x82381c00, 0x00000007, 0x54041800, 0x80040800,
+ 0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800,
+ 0x001007d3, 0x02000800, 0x001005d8, 0x4a02580a,
+ 0x0010be79, 0x42000800, 0x0010beda, 0x452c0800,
+ 0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e,
+ 0x497a580f, 0x4a025809, 0x001058b6, 0x497a5810,
+ 0x4a025802, 0x00000100, 0x4a025801, 0x00000001,
+ 0x1c01f000, 0x59c80007, 0x8c000502, 0x04000070,
+ 0x835c2c80, 0x00000005, 0x02001000, 0x00105f23,
+ 0x59c82817, 0x497b9005, 0x82140500, 0x00e00000,
+ 0x0402004f, 0x82140500, 0x000003ff, 0x82001c00,
+ 0x00000006, 0x41cc2000, 0x42003000, 0x00006080,
+ 0x820c0480, 0x00000040, 0x04001006, 0x42001000,
+ 0x00000040, 0x820c1c80, 0x00000040, 0x0401f003,
+ 0x400c1000, 0x41781800, 0x54182000, 0x80102000,
+ 0x80183000, 0x80081040, 0x040207fc, 0x800c19c0,
+ 0x04000005, 0x59c80005, 0x80000000, 0x48039005,
+ 0x0401f7ea, 0x82140500, 0x01f60000, 0x04020029,
+ 0x82140500, 0x0000f000, 0x0400000b, 0x82000c80,
+ 0x00002000, 0x0402100f, 0x82140500, 0x0e000000,
+ 0x80000132, 0x0c01f840, 0x4a039005, 0x00000140,
+ 0x1c01f000, 0x59cc0400, 0x82000500, 0x0000ff00,
+ 0x82000580, 0x00008100, 0x040007f4, 0x0401f01c,
+ 0x4817c857, 0x82140500, 0x000003ff, 0x04020007,
+ 0x59cc0400, 0x82000500, 0x0000ff00, 0x82000580,
+ 0x00008100, 0x04020012, 0x42000000, 0x0010b8bd,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x00105dfa,
+ 0x4803c856, 0x4a039005, 0x00000140, 0x0401f020,
+ 0x4817c857, 0x82140500, 0x00f60000, 0x04020004,
+ 0x0201f800, 0x00105e35, 0x040207d2, 0x0201f800,
+ 0x0010513b, 0x04000010, 0x59c400a4, 0x4803c857,
+ 0x82000500, 0x0000000f, 0x82000580, 0x0000000a,
+ 0x04020009, 0x497b5016, 0x59c400a3, 0x82000540,
+ 0x00080000, 0x480388a3, 0x82000500, 0xfff7ffff,
+ 0x480388a3, 0x4817c856, 0x0201f800, 0x0010a978,
+ 0x4a039005, 0x00000140, 0x0401f842, 0x4803c856,
+ 0x1c01f000, 0x00105a1d, 0x00105cf4, 0x00105a15,
+ 0x00105a15, 0x00105a15, 0x00105a15, 0x00105a15,
+ 0x00105a15, 0x4803c857, 0x42000000, 0x0010b85a,
+ 0x0201f800, 0x0010aa47, 0x4a039005, 0x00000140,
+ 0x1c01f000, 0x4817c857, 0x59cc0400, 0x4803c857,
+ 0x82000d00, 0x0000ff00, 0x82041500, 0x0000f000,
+ 0x840409c0, 0x82140500, 0x000003ff, 0x800018c4,
+ 0x8c142d14, 0x04000005, 0x59cc0002, 0x82000500,
+ 0x00000003, 0x800c1c80, 0x480f5016, 0x82080580,
+ 0x00002000, 0x04020011, 0x836c0580, 0x00000001,
+ 0x0402000c, 0x59cc0006, 0x82000500, 0xff000000,
+ 0x82000580, 0x11000000, 0x04020011, 0x0201f800,
+ 0x00103b38, 0x0201f800, 0x00105f48, 0x0401f00c,
+ 0x0401f81f, 0x0401f00a, 0x82080580, 0x00003000,
+ 0x04020003, 0x0401fa06, 0x0401f005, 0x82080580,
+ 0x00008000, 0x04020002, 0x0401fafc, 0x1c01f000,
+ 0x4817c857, 0x42000000, 0x0010b859, 0x0201f800,
+ 0x0010aa47, 0x836c0580, 0x00000003, 0x0402000b,
+ 0x4c080000, 0x4c0c0000, 0x42001000, 0x00008048,
+ 0x40141800, 0x80142120, 0x0201f800, 0x00103a3e,
+ 0x5c001800, 0x5c001000, 0x1c01f000, 0x4807c857,
+ 0x59cc0002, 0x82000500, 0xff000000, 0x82001580,
+ 0x01000000, 0x04000004, 0x82001580, 0x23000000,
+ 0x04020192, 0x82040580, 0x00000023, 0x0402003f,
+ 0x0401fb6a, 0x0400018d, 0x59300c06, 0x82040580,
+ 0x00000010, 0x04000013, 0x82040580, 0x00000011,
+ 0x04000010, 0x82040580, 0x00000001, 0x0400000d,
+ 0x82040580, 0x00000004, 0x0400000a, 0x82040580,
+ 0x00000008, 0x04000007, 0x82040580, 0x0000000a,
+ 0x04000004, 0x4933c857, 0x4807c857, 0x0401f177,
+ 0x59300004, 0x82000500, 0x80010000, 0x04000004,
+ 0x0201f800, 0x00106f60, 0x04020170, 0x59cc0a04,
+ 0x48066202, 0x59cc0006, 0x82000500, 0xffff0000,
+ 0x82000d80, 0x02000000, 0x04020005, 0x42027000,
+ 0x00000015, 0x0201f000, 0x000207a1, 0x82000d80,
+ 0x02140000, 0x040007fa, 0x82000d80, 0x02100000,
+ 0x040007f7, 0x82000d80, 0x02100000, 0x040007f4,
+ 0x82000d80, 0x01000000, 0x04020158, 0x59cc0006,
+ 0x82000500, 0x0000ffff, 0x04020154, 0x42027000,
+ 0x00000016, 0x0401f7ec, 0x82040580, 0x00000022,
+ 0x0402014e, 0x59a80806, 0x8c040d14, 0x04000011,
+ 0x0401f967, 0x0402000f, 0x0401f97d, 0x0400000d,
+ 0x42027000, 0x0000004c, 0x59cc0001, 0x82000500,
+ 0x00ffffff, 0x0201f800, 0x00105eec, 0x0400012a,
+ 0x42028800, 0x0000ffff, 0x417a6800, 0x0401f126,
+ 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
+ 0x03000000, 0x04020021, 0x59a80026, 0x8c000508,
+ 0x04000017, 0x8400054c, 0x48035026, 0x59cc0800,
+ 0x82040d00, 0x00ffffff, 0x48075010, 0x497b8830,
+ 0x84040d70, 0x48078832, 0x59c40802, 0x84040d4c,
+ 0x48078802, 0x59cc0007, 0x82000500, 0x0000ffff,
+ 0x48038893, 0x4803501e, 0x42000800, 0x00000003,
+ 0x59a81010, 0x0201f800, 0x00106c78, 0x59cc0006,
+ 0x82000500, 0x0000ffff, 0x04020118, 0x42027000,
+ 0x00000017, 0x0401f0d9, 0x82000d80, 0x04000000,
+ 0x04020011, 0x59cc0006, 0x82000500, 0x0000ffff,
+ 0x0402010e, 0x0201f800, 0x0010513b, 0x04000004,
+ 0x42027000, 0x0000001d, 0x0401f0cc, 0x59a80026,
+ 0x84000548, 0x48035026, 0x42027000, 0x00000030,
+ 0x0401f0c6, 0x82000d80, 0x05000000, 0x04020008,
+ 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200fb,
+ 0x42027000, 0x00000018, 0x0401f0bc, 0x82000d80,
+ 0x20100000, 0x04020004, 0x42027000, 0x00000019,
+ 0x0401f0b6, 0x82000d80, 0x21100000, 0x04020004,
+ 0x42027000, 0x0000001a, 0x0401f0b0, 0x82000d80,
+ 0x52000000, 0x04020008, 0x59cc0006, 0x82000500,
+ 0x0000ffff, 0x040200e5, 0x42027000, 0x0000001b,
+ 0x0401f0a6, 0x82000d80, 0x50000000, 0x04020008,
+ 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200db,
+ 0x42027000, 0x0000001c, 0x0401f09c, 0x82000d80,
+ 0x13000000, 0x04020004, 0x42027000, 0x00000034,
+ 0x0401f096, 0x82000d80, 0x12000000, 0x04020008,
+ 0x59cc0006, 0x82000500, 0x0000ffff, 0x040200cb,
+ 0x42027000, 0x00000024, 0x0401f08c, 0x82000d00,
+ 0xff000000, 0x82040d80, 0x24000000, 0x04020004,
+ 0x42027000, 0x0000002d, 0x0401f084, 0x82000d00,
+ 0xff000000, 0x82040d80, 0x53000000, 0x04020004,
+ 0x42027000, 0x0000002a, 0x0401f07c, 0x82000d80,
+ 0x0f000000, 0x04020004, 0x42027000, 0x00000020,
+ 0x0401f076, 0x82000d80, 0x61040000, 0x04020036,
+ 0x83cc1400, 0x00000006, 0x80080800, 0x50080000,
+ 0x82000500, 0x0000ffff, 0x82000480, 0x00000004,
+ 0x4c580000, 0x8000b104, 0x8058b1c0, 0x04000026,
+ 0x4c100000, 0x50041800, 0x820c1500, 0x03000000,
+ 0x80081130, 0x42000000, 0x0010b817, 0x82082580,
+ 0x00000000, 0x04020004, 0x42000000, 0x0010b814,
+ 0x0401f00c, 0x82082580, 0x00000001, 0x04020004,
+ 0x42000000, 0x0010b815, 0x0401f006, 0x82082580,
+ 0x00000002, 0x04020003, 0x42000000, 0x0010b816,
+ 0x0201f800, 0x0010aa47, 0x42001000, 0x00008015,
+ 0x820c2500, 0x0000ffff, 0x800c1920, 0x0201f800,
+ 0x00103a3e, 0x5c002000, 0x80040800, 0x8058b040,
+ 0x040207da, 0x5c00b000, 0x42027000, 0x00000023,
+ 0x0401f03e, 0x82000d80, 0x60000000, 0x04020004,
+ 0x42027000, 0x0000003f, 0x0401f038, 0x82000d80,
+ 0x54000000, 0x04020006, 0x0401fb12, 0x0402006f,
+ 0x42027000, 0x00000046, 0x0401f030, 0x82000d80,
+ 0x55000000, 0x04020009, 0x0401fb32, 0x04020004,
+ 0x42027000, 0x00000041, 0x0401f028, 0x42027000,
+ 0x00000042, 0x0401f025, 0x82000d80, 0x78000000,
+ 0x04020004, 0x42027000, 0x00000045, 0x0401f01f,
+ 0x82000d80, 0x10000000, 0x04020004, 0x42027000,
+ 0x0000004e, 0x0401f019, 0x82000d80, 0x63000000,
+ 0x04020004, 0x42027000, 0x0000004a, 0x0401f013,
+ 0x82000d00, 0xff000000, 0x82040d80, 0x56000000,
+ 0x04020004, 0x42027000, 0x0000004f, 0x0401f00b,
+ 0x82000d00, 0xff000000, 0x82040d80, 0x57000000,
+ 0x04020004, 0x42027000, 0x00000050, 0x0401f003,
+ 0x42027000, 0x0000001d, 0x59cc3800, 0x821c3d00,
+ 0x00ffffff, 0x821c0580, 0x00fffffe, 0x59cc0001,
+ 0x04020005, 0x40003000, 0x42028800, 0x000007fe,
+ 0x0401f003, 0x0401f8d1, 0x04020030, 0x0201f800,
+ 0x001045a6, 0x0402002d, 0x83380580, 0x00000046,
+ 0x04020004, 0x59a80010, 0x80180580, 0x04000027,
+ 0x59340200, 0x8c000514, 0x0400000f, 0x83380580,
+ 0x00000030, 0x0400000c, 0x83380580, 0x0000003f,
+ 0x04000009, 0x83380580, 0x00000034, 0x04000006,
+ 0x83380580, 0x00000024, 0x04000003, 0x42027000,
+ 0x0000004c, 0x0201f800, 0x0002075a, 0x04000018,
+ 0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04,
+ 0x48066202, 0x83380580, 0x0000004c, 0x04020009,
+ 0x4a026406, 0x00000011, 0x813669c0, 0x04020005,
+ 0x59cc0001, 0x82000500, 0x00ffffff, 0x4802601e,
+ 0x0201f000, 0x000207a1, 0x59880052, 0x4803c857,
+ 0x80000000, 0x48031052, 0x1c01f000, 0x42001000,
+ 0x00008049, 0x59cc1806, 0x800c1930, 0x0201f800,
+ 0x00103a3e, 0x0201f800, 0x00107942, 0x040007f3,
+ 0x49366009, 0x4a026406, 0x00000004, 0x59cc0c04,
+ 0x48066202, 0x4a026403, 0x00000009, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00002900, 0x4a026203,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x59a80026,
+ 0x4803c857, 0x8c000508, 0x04000010, 0x59cc0006,
+ 0x82000500, 0xff000000, 0x82000d80, 0x03000000,
+ 0x0400000c, 0x82000d80, 0x20000000, 0x04000009,
+ 0x82000d80, 0x05000000, 0x04000006, 0x82000d80,
+ 0x21000000, 0x04000003, 0x80000580, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x0401f7fd, 0x59cc2006,
+ 0x82102500, 0xff000000, 0x9c1021c0, 0x0401f807,
+ 0x820c1c00, 0x0010b4e3, 0x500c1800, 0x800c0500,
+ 0x4803c857, 0x1c01f000, 0x40100800, 0x41781800,
+ 0x82040480, 0x00000020, 0x04001004, 0x800c1800,
+ 0x40000800, 0x0401f7fb, 0x82040500, 0x0000000f,
+ 0x82000400, 0x0010ab38, 0x50000000, 0x8c040d08,
+ 0x04000002, 0x900001c0, 0x1c01f000, 0x4803c856,
+ 0x0401fac3, 0x0402000a, 0x0201f800, 0x0010210a,
+ 0x04020007, 0x59cc0002, 0x82000500, 0xff000000,
+ 0x82000d80, 0x08000000, 0x04000802, 0x1c01f000,
+ 0x4803c856, 0x59cc0400, 0x82000d00, 0x0000ff00,
+ 0x840409c0, 0x82040580, 0x00000033, 0x0402001f,
+ 0x0401f976, 0x04000038, 0x59cc0a04, 0x48066202,
+ 0x59cc0006, 0x4803c857, 0x82000500, 0xffff0000,
+ 0x82000d80, 0x02000000, 0x04020009, 0x59cc0006,
+ 0x82000500, 0x0000ffff, 0x0402002b, 0x42027000,
+ 0x00000015, 0x0201f000, 0x000207a1, 0x82000d80,
+ 0x01000000, 0x04020024, 0x59cc0006, 0x82000500,
+ 0x0000ffff, 0x04020020, 0x42027000, 0x00000016,
+ 0x0201f000, 0x000207a1, 0x82040580, 0x00000032,
+ 0x04020019, 0x59cc0006, 0x82000500, 0xffff0000,
+ 0x82000d80, 0x14000000, 0x04020013, 0x42027000,
+ 0x00000038, 0x59cc0001, 0x0401f810, 0x0402000e,
+ 0x0201f800, 0x001045a6, 0x0402000b, 0x0201f800,
+ 0x0002075a, 0x04000008, 0x49366009, 0x4a026406,
+ 0x00000004, 0x59cc0c04, 0x48066202, 0x0201f000,
+ 0x000207a1, 0x1c01f000, 0x4803c857, 0x4c580000,
+ 0x4c100000, 0x4c380000, 0x4c340000, 0x82003500,
+ 0x00ffffff, 0x82181500, 0x00ff0000, 0x82081580,
+ 0x00ff0000, 0x04020016, 0x82181480, 0x00fffffc,
+ 0x04001013, 0x82181580, 0x00fffffd, 0x04020004,
+ 0x42028800, 0x000007fd, 0x0401f040, 0x82181580,
+ 0x00fffffe, 0x04020004, 0x42028800, 0x000007fe,
+ 0x0401f03a, 0x82181580, 0x00fffffc, 0x04020004,
+ 0x42028800, 0x000007fc, 0x0401f034, 0x41781000,
+ 0x42002000, 0x00000000, 0x4200b000, 0x000007f0,
+ 0x41ac7000, 0x50380000, 0x80006d40, 0x04020005,
+ 0x800811c0, 0x0402001e, 0x8410155e, 0x0401f01c,
+ 0x58340212, 0x82000500, 0x0000ff00, 0x04000011,
+ 0x59a84010, 0x82204500, 0x00ffff00, 0x82180500,
+ 0x00ffff00, 0x04000002, 0x80200580, 0x58340002,
+ 0x0402000f, 0x82000500, 0x000000ff, 0x82184500,
+ 0x000000ff, 0x80204580, 0x04020009, 0x0401f006,
+ 0x58340002, 0x82000500, 0x00ffffff, 0x80184580,
+ 0x04020003, 0x40128800, 0x0401f00c, 0x80102000,
+ 0x80387000, 0x8058b040, 0x040207db, 0x800811c0,
+ 0x04020005, 0x481bc857, 0x82000540, 0x00000001,
+ 0x0401f003, 0x840a8d1e, 0x80000580, 0x5c006800,
+ 0x5c007000, 0x5c002000, 0x5c00b000, 0x1c01f000,
+ 0x59a80026, 0x8c00050e, 0x04000003, 0x8c000502,
+ 0x04000006, 0x59cc0c00, 0x80040910, 0x82040500,
+ 0x0000000f, 0x0c01f002, 0x1c01f000, 0x00105d0f,
+ 0x00105d0f, 0x00105d0f, 0x00105de5, 0x00105d0f,
+ 0x00105d11, 0x00105d29, 0x00105d2c, 0x00105d0f,
+ 0x00105d0f, 0x00105d0f, 0x00105d0f, 0x00105d0f,
+ 0x00105d0f, 0x00105d0f, 0x00105d0f, 0x4803c856,
+ 0x1c01f000, 0x0401f8c5, 0x04000014, 0x82140500,
+ 0x000003ff, 0x800000c4, 0x82000480, 0x00000008,
+ 0x0400100e, 0x59cc0001, 0x59326809, 0x59340802,
+ 0x80040580, 0x82000500, 0x00ffffff, 0x04020007,
+ 0x59cc0a04, 0x48066202, 0x42027000, 0x00000046,
+ 0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857,
+ 0x1c01f000, 0x59cc0004, 0x4803c857, 0x1c01f000,
+ 0x0401f8aa, 0x04000016, 0x82140500, 0x000003ff,
+ 0x800000c4, 0x82000480, 0x0000000c, 0x04001010,
+ 0x59cc0001, 0x82000500, 0x00ffffff, 0x59326809,
+ 0x59340802, 0x82040d00, 0x00ffffff, 0x80040580,
+ 0x04020007, 0x59cc0a04, 0x48066202, 0x42027000,
+ 0x00000045, 0x0201f000, 0x000207a1, 0x59cc0004,
+ 0x4803c857, 0x1c01f000, 0x4817c857, 0x0401f9c8,
+ 0x04020011, 0x0201f800, 0x0010210a, 0x0402000e,
+ 0x59cc0002, 0x82000500, 0xff000000, 0x82000580,
+ 0x00000000, 0x04020008, 0x82040500, 0x0000000f,
+ 0x82000c80, 0x00000006, 0x04021003, 0x4803c857,
+ 0x0c01f002, 0x1c01f000, 0x00105d60, 0x00105d64,
+ 0x00105d60, 0x00105d60, 0x00105db2, 0x00105dc3,
+ 0x4803c857, 0x59cc0004, 0x4803c857, 0x1c01f000,
+ 0x59cc0004, 0x4803c857, 0x59a80016, 0x800001c0,
+ 0x040207f8, 0x59cc0802, 0x8c040d2e, 0x0402001d,
+ 0x0201f800, 0x00107942, 0x02000800, 0x001005d8,
+ 0x59cc0001, 0x4803c857, 0x0401ff28, 0x0402000d,
+ 0x0201f800, 0x00020245, 0x0402000a, 0x4a026406,
+ 0x00000005, 0x49366009, 0x59cc0c04, 0x48066202,
+ 0x42027000, 0x00000088, 0x0201f000, 0x000207a1,
+ 0x42028800, 0x0000ffff, 0x417a6800, 0x59cc0001,
+ 0x82000500, 0x00ffffff, 0x4802601e, 0x0401f7f0,
+ 0x59cc0001, 0x4803c857, 0x0401ff10, 0x040207d5,
+ 0x0201f800, 0x001045a6, 0x040207d2, 0x59cc0005,
+ 0x8c000500, 0x04020004, 0x59340200, 0x8c00050e,
+ 0x040207cc, 0x0201f800, 0x001049f3, 0x0402000f,
+ 0x0401f83e, 0x040007c7, 0x0201f800, 0x0002075a,
+ 0x040007c4, 0x49366009, 0x4a026406, 0x00000002,
+ 0x59cc0c04, 0x48066202, 0x42027000, 0x00000088,
+ 0x0201f000, 0x000207a1, 0x0201f800, 0x0002075a,
+ 0x040007b8, 0x49366009, 0x4a026406, 0x00000004,
+ 0x59cc0c04, 0x48066202, 0x42027000, 0x00000001,
+ 0x0201f000, 0x000207a1, 0x59cc0004, 0x4803c857,
+ 0x59cc0802, 0x8c040d2e, 0x0400000b, 0x0401f81f,
+ 0x04000009, 0x0401f960, 0x04020007, 0x59cc0a04,
+ 0x48066202, 0x42027000, 0x00000089, 0x0201f000,
+ 0x000207a1, 0x4933c857, 0x1c01f000, 0x59cc0004,
+ 0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b,
+ 0x0401f80e, 0x04000009, 0x0401f94f, 0x04020007,
+ 0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a,
+ 0x0201f000, 0x000207a1, 0x4933c857, 0x1c01f000,
+ 0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e,
+ 0x59a81067, 0x80080400, 0x80040480, 0x04021008,
+ 0x40040000, 0x800000c4, 0x800408ca, 0x80040c00,
+ 0x82066400, 0x0010d1c0, 0x1c01f000, 0x80000580,
+ 0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010,
+ 0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500,
+ 0x00ffffff, 0x59326809, 0x59340802, 0x82040d00,
+ 0x00ffffff, 0x80040580, 0x04020005, 0x42027000,
+ 0x00000051, 0x0201f000, 0x000207a1, 0x59cc0004,
+ 0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000,
+ 0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000,
+ 0x41cc7800, 0x0401f803, 0x5c007800, 0x1c01f000,
+ 0x4803c856, 0x4c580000, 0x583c0400, 0x82000500,
+ 0x0000f000, 0x82000580, 0x0000c000, 0x04000024,
+ 0x0201f800, 0x0002075a, 0x04000021, 0x4c180000,
+ 0x583c0001, 0x0401fe89, 0x0402001f, 0x0201f800,
+ 0x001045a6, 0x0402001c, 0x49366009, 0x0201f800,
+ 0x001007e4, 0x04000018, 0x492e6017, 0x497a5800,
+ 0x497a5a04, 0x48125c04, 0x832cac00, 0x00000005,
+ 0x4200b000, 0x00000007, 0x403ca000, 0x0201f800,
+ 0x0010ab17, 0x5c003000, 0x481a641a, 0x4a026403,
+ 0x0000003e, 0x4a026406, 0x00000001, 0x4a026203,
+ 0x00000001, 0x0201f800, 0x0010672b, 0x5c00b000,
+ 0x1c01f000, 0x0201f800, 0x0002077d, 0x5c003000,
+ 0x0401f7fb, 0x4803c856, 0x59cc0400, 0x82000d00,
+ 0x0000ff00, 0x82040500, 0x0000f000, 0x840409c0,
+ 0x82000580, 0x00002000, 0x04020049, 0x82040580,
+ 0x00000022, 0x0402003a, 0x59c400a4, 0x82000500,
+ 0x0000000f, 0x82000c80, 0x00000007, 0x04001004,
+ 0x82000480, 0x0000000c, 0x0400103f, 0x59cc0006,
+ 0x82000500, 0xffff0000, 0x82000d80, 0x04000000,
+ 0x04000039, 0x82000d80, 0x60000000, 0x04000036,
+ 0x82000d80, 0x54000000, 0x04000033, 0x82000d80,
+ 0x03000000, 0x04020015, 0x59a80826, 0x8c040d02,
+ 0x0402002d, 0x8c040d08, 0x0402002b, 0x0201f800,
+ 0x001048ec, 0x0400002b, 0x59a8001d, 0x800000d0,
+ 0x59a80810, 0x82040d00, 0x000000ff, 0x80040540,
+ 0x59cc0800, 0x82040d00, 0x00ffffff, 0x80040580,
+ 0x0402001b, 0x0401f01c, 0x59c40802, 0x8c040d0c,
+ 0x04020017, 0x82000d80, 0x52000000, 0x040007ec,
+ 0x82000d80, 0x05000000, 0x040007e9, 0x82000d80,
+ 0x50000000, 0x040007e6, 0x0401f00d, 0x82040580,
+ 0x00000023, 0x0402000a, 0x0401ff58, 0x04000008,
+ 0x59300c03, 0x82040580, 0x00000002, 0x04000006,
+ 0x82040580, 0x00000051, 0x04000003, 0x80000580,
+ 0x0401f003, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
+ 0x03000000, 0x04000004, 0x82000d80, 0x52000000,
+ 0x040207f3, 0x59a80026, 0x82000500, 0x00000009,
+ 0x82000580, 0x00000008, 0x040007ef, 0x0401f7ec,
+ 0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016,
+ 0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807,
+ 0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00,
+ 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
+ 0x00000002, 0x83cc1400, 0x0000000d, 0x0201f800,
+ 0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a,
+ 0x4200b000, 0x00000002, 0x83a81c00, 0x00000000,
+ 0x83cc1400, 0x0000000f, 0x0201f800, 0x0010855a,
+ 0x04020005, 0x8c5cbd04, 0x04000003, 0x82000540,
+ 0x00000001, 0x5c00b000, 0x5c00b800, 0x1c01f000,
+ 0x4803c856, 0x4c5c0000, 0x4c580000, 0x59a80016,
+ 0x82000580, 0x0000004c, 0x0402001f, 0x59ccb807,
+ 0x9c5cb9c0, 0x825cbd00, 0x00000007, 0x8c5cbd00,
+ 0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
+ 0x00000002, 0x83cc1400, 0x00000009, 0x0201f800,
+ 0x0010855a, 0x04020010, 0x8c5cbd02, 0x0400000a,
+ 0x4200b000, 0x00000002, 0x83a81c00, 0x00000000,
+ 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+ 0x04020005, 0x8c5cbd04, 0x04000003, 0x82000540,
+ 0x00000001, 0x5c00b000, 0x5c00b800, 0x1c01f000,
+ 0x4803c857, 0x4c580000, 0x40003000, 0x42002000,
+ 0x000007f0, 0x4200b000, 0x00000010, 0x83ac7400,
+ 0x000007f0, 0x50380000, 0x80026d40, 0x04000006,
+ 0x59340002, 0x82000500, 0x00ffffff, 0x80180580,
+ 0x04000010, 0x80102000, 0x80387000, 0x8058b040,
+ 0x040207f5, 0x82100480, 0x00000800, 0x42002000,
+ 0x00000000, 0x4200b000, 0x000007f0, 0x41ac7000,
+ 0x040217ed, 0x82000540, 0x00000001, 0x0401f002,
+ 0x40128800, 0x5c00b000, 0x1c01f000, 0x59a80026,
+ 0x8c00050e, 0x04000004, 0x8c000502, 0x04000003,
+ 0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x0401f7fd, 0x59300c06, 0x82040580, 0x00000002,
+ 0x04000006, 0x82040580, 0x00000005, 0x04000003,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x59c80000,
+ 0x84000558, 0x84000512, 0x48039000, 0x1c01f000,
+ 0x4a03281a, 0x000003e8, 0x4a032802, 0x0010d1c0,
+ 0x4a032800, 0x00000000, 0x4a032808, 0x00107049,
+ 0x42000000, 0x00000005, 0x83947c00, 0x00000009,
+ 0x49787801, 0x4a007802, 0x00106fff, 0x823c7c00,
+ 0x00000003, 0x80000040, 0x040207fa, 0x4a032819,
+ 0xffff0000, 0x4201d000, 0x00000064, 0x0401f96e,
+ 0x4201d000, 0x000186a0, 0x0401f184, 0x00000000,
+ 0x00000003, 0x00000006, 0x00000009, 0x0000000c,
+ 0x4d300000, 0x4d2c0000, 0x4d340000, 0x4d400000,
+ 0x4cfc0000, 0x4d380000, 0x4d3c0000, 0x4d440000,
+ 0x4d4c0000, 0x4d480000, 0x4c5c0000, 0x4c600000,
+ 0x4c640000, 0x4cc80000, 0x4ccc0000, 0x0201f800,
+ 0x0002057b, 0x5c019800, 0x5c019000, 0x5c00c800,
+ 0x5c00c000, 0x5c00b800, 0x5c029000, 0x5c029800,
+ 0x5c028800, 0x5c027800, 0x5c027000, 0x5c01f800,
+ 0x5c028000, 0x5c026800, 0x5c025800, 0x5c026000,
+ 0x1c01f000, 0x59940004, 0x80000540, 0x0402000a,
+ 0x59940025, 0x80040400, 0x02001800, 0x001005d8,
+ 0x48032804, 0x480b2805, 0x4a032803, 0x0000000a,
+ 0x80000580, 0x1c01f000, 0x5994001f, 0x80000540,
+ 0x0402000a, 0x59940025, 0x80040400, 0x02001800,
+ 0x001005d8, 0x4803281f, 0x480b2820, 0x4a03281e,
+ 0x00000001, 0x80000580, 0x1c01f000, 0x59940022,
+ 0x80000540, 0x0402000a, 0x59940025, 0x80040400,
+ 0x02001800, 0x001005d8, 0x48032822, 0x480b2823,
+ 0x4a032821, 0x0000000a, 0x80000580, 0x1c01f000,
+ 0x4c000000, 0x59940005, 0x4803c857, 0x480bc857,
+ 0x80080580, 0x04020003, 0x497b2804, 0x497b2805,
+ 0x5c000000, 0x1c01f000, 0x4c000000, 0x59940020,
+ 0x4803c857, 0x480bc857, 0x80080580, 0x04020003,
+ 0x497b281f, 0x497b2820, 0x5c000000, 0x1c01f000,
+ 0x4c000000, 0x59940023, 0x4803c857, 0x480bc857,
+ 0x80080580, 0x04020003, 0x497b2822, 0x497b2823,
+ 0x5c000000, 0x1c01f000, 0x4937c857, 0x48ebc857,
+ 0x59340203, 0x80e80480, 0x04001002, 0x48ea6a03,
+ 0x1c01f000, 0x5c03e000, 0x1c01f000, 0x4d440000,
+ 0x42007800, 0x00000010, 0x59968801, 0x0201f800,
+ 0x00020245, 0x04020012, 0x59341a03, 0x800c1840,
+ 0x0400100f, 0x59940027, 0x800c0480, 0x04000003,
+ 0x48026a03, 0x0402100a, 0x5934000f, 0x497a6a03,
+ 0x80000540, 0x04000006, 0x4c3c0000, 0x5934140b,
+ 0x0201f800, 0x00020253, 0x5c007800, 0x81468800,
+ 0x83440480, 0x00000800, 0x04021007, 0x803c7840,
+ 0x040207e7, 0x49472801, 0x5c028800, 0x5c03e000,
+ 0x1c01f000, 0x4a032800, 0x00000002, 0x497b2801,
+ 0x0401f7fa, 0x42007800, 0x00000010, 0x59966002,
+ 0x59300205, 0x80000d40, 0x04000006, 0x59940027,
+ 0x80040480, 0x48026205, 0x0400102d, 0x0400002c,
+ 0x59300206, 0x80000d40, 0x04000014, 0x59b800e4,
+ 0x8c000524, 0x04020011, 0x4a0370e4, 0x00030000,
+ 0x40000000, 0x59b800e4, 0x8c000524, 0x04000004,
+ 0x4a0370e4, 0x00020000, 0x0401f008, 0x59940027,
+ 0x80040480, 0x48026206, 0x4a0370e4, 0x00020000,
+ 0x0400101c, 0x0400001b, 0x83326400, 0x00000024,
+ 0x49332802, 0x41540000, 0x81300480, 0x04021005,
+ 0x803c7840, 0x040207db, 0x5c03e000, 0x1c01f000,
+ 0x59940026, 0x48032827, 0x4a032802, 0x0010d1c0,
+ 0x497b2826, 0x80000540, 0x0400000f, 0x4a032800,
+ 0x00000001, 0x5c03e000, 0x1c01f000, 0x4c3c0000,
+ 0x0201f800, 0x001091db, 0x5c007800, 0x0401f7d1,
+ 0x4c3c0000, 0x0201f800, 0x00108d5d, 0x5c007800,
+ 0x0401f7e2, 0x4a032800, 0x00000000, 0x5c03e000,
+ 0x1c01f000, 0x59a8086b, 0x8c040d30, 0x04020029,
+ 0x8c040d32, 0x0400000f, 0x59a80069, 0x81640480,
+ 0x04001019, 0x59a8000b, 0x81500580, 0x04000005,
+ 0x59a8006a, 0x59a81066, 0x80080580, 0x04020012,
+ 0x900411c0, 0x82081500, 0x00007000, 0x0401f012,
+ 0x82040500, 0x0000001f, 0x04000016, 0x80040840,
+ 0x82040500, 0x0000001f, 0x04000003, 0x4807506b,
+ 0x0401f010, 0x900401c0, 0x82000500, 0x0000001f,
+ 0x80040d40, 0x900401c0, 0x80040580, 0x82001500,
+ 0x00007000, 0x82040500, 0xffff8fff, 0x80080540,
+ 0x4803506b, 0x80081114, 0x0201f800, 0x001006e2,
+ 0x1c01f000, 0x4a032807, 0x000007d0, 0x4a032806,
+ 0x0000000a, 0x1c01f000, 0x42000800, 0x000007d0,
+ 0x83180480, 0x00000005, 0x02021800, 0x001005d8,
+ 0x83947c00, 0x00000009, 0x83180400, 0x00105f43,
+ 0x50000000, 0x803c7c00, 0x48047801, 0x4a007800,
+ 0x0000000a, 0x1c01f000, 0x83180480, 0x00000005,
+ 0x02021800, 0x001005d8, 0x83947c00, 0x00000009,
+ 0x83180400, 0x00105f43, 0x50000000, 0x803c7c00,
+ 0x49787801, 0x1c01f000, 0x4807c857, 0x480bc857,
+ 0x59940025, 0x80040400, 0x02001800, 0x001005d8,
+ 0x48032804, 0x480b2805, 0x4a032803, 0x0000000a,
+ 0x1c01f000, 0x4807c857, 0x480bc857, 0x59940025,
+ 0x80040400, 0x02001800, 0x001005d8, 0x4803281c,
+ 0x480b281d, 0x4a03281b, 0x0000000a, 0x1c01f000,
+ 0x4c000000, 0x5994001d, 0x4803c857, 0x480bc857,
+ 0x80080580, 0x04020003, 0x4803281c, 0x4803281d,
+ 0x5c000000, 0x1c01f000, 0x80e9d1c0, 0x0400000e,
+ 0x0401f836, 0x04025000, 0x4203e000, 0x80000000,
+ 0x40e81000, 0x41780800, 0x42000000, 0x00000064,
+ 0x0201f800, 0x001066a0, 0x59940024, 0x80080400,
+ 0x48032824, 0x1c01f000, 0x42001000, 0x00105065,
+ 0x0401fef0, 0x42001000, 0x00105058, 0x0401ffe1,
+ 0x42001000, 0x00104148, 0x0401feea, 0x42001000,
+ 0x001041bc, 0x0401fee7, 0x42001000, 0x001041f3,
+ 0x0401f6f8, 0x4203e000, 0x70000000, 0x4203e000,
+ 0xb0300000, 0x41fc0000, 0x40ebf800, 0x80e80480,
+ 0x04001011, 0x04000004, 0x82000480, 0x00000003,
+ 0x0402100d, 0x42000000, 0x0000000f, 0x04004004,
+ 0x80000040, 0x040207fe, 0x0401f007, 0x4203e000,
+ 0x70000000, 0x42000000, 0x0010b87e, 0x0201f800,
+ 0x0010aa47, 0x1c01f000, 0x4203e000, 0x80000000,
+ 0x4203e000, 0xb0400000, 0x41fc0000, 0x40ebf800,
+ 0x80e80480, 0x04001011, 0x04000004, 0x82000480,
+ 0x00000003, 0x0402100d, 0x42000000, 0x0000000f,
+ 0x04005004, 0x80000040, 0x040207fe, 0x0401f007,
+ 0x4203e000, 0x80000000, 0x42000000, 0x0010b87f,
+ 0x0201f800, 0x0010aa47, 0x1c01f000, 0x59a8000e,
+ 0x82000480, 0x00000100, 0x599c0a02, 0x800409c0,
+ 0x04020002, 0x80040800, 0x80041480, 0x04001002,
+ 0x40000800, 0x48075067, 0x59a8100e, 0x40040000,
+ 0x800acc80, 0x4967500e, 0x49675069, 0x59aaa80b,
+ 0x41640800, 0x42001000, 0x00000024, 0x0201f800,
+ 0x00106681, 0x8206a400, 0x0010d1c0, 0x49535065,
+ 0x4152b000, 0x42006000, 0x0010be65, 0x4a006004,
+ 0x0000012c, 0x4a006005, 0xda10da10, 0x4a006008,
+ 0x00000011, 0x4a006009, 0x0010be65, 0x4a00600a,
+ 0x001010b8, 0x599c0014, 0x48006011, 0x599c0015,
+ 0x48006012, 0x42006000, 0x0010be41, 0x4a006203,
+ 0x00000008, 0x4a006406, 0x00000006, 0x4a006002,
+ 0xffff0000, 0x4a006008, 0x0010be65, 0x4a006014,
+ 0x0010be65, 0x599c0014, 0x48006015, 0x599c0015,
+ 0x48006016, 0x599c0413, 0x48006017, 0x49506018,
+ 0x49546019, 0x59a80067, 0x4800601a, 0x4a00601b,
+ 0x0010b465, 0x4a00601c, 0x0010b466, 0x4a00601d,
+ 0x0010b46a, 0x42000000, 0xb0000000, 0x42000800,
+ 0x0010be41, 0x0201f800, 0x00100b68, 0x1c01f000,
+ 0x82000d00, 0x000000c0, 0x04000004, 0x82040d80,
+ 0x000000c0, 0x04020055, 0x82000d00, 0x00002020,
+ 0x59300414, 0x84000512, 0x82040d80, 0x00002020,
+ 0x0400000b, 0x8c000514, 0x0402000f, 0x48026414,
+ 0x813e79c0, 0x02020000, 0x000206d0, 0x42027000,
+ 0x00000043, 0x0201f000, 0x000207a1, 0x59326809,
+ 0x59340a00, 0x8c040d0a, 0x040007f3, 0x84000552,
+ 0x0401f7f1, 0x84000514, 0x592c080d, 0x48066015,
+ 0x0401f7ef, 0x59326809, 0x59340a00, 0x8c040d0a,
+ 0x02000000, 0x000206e3, 0x59300c14, 0x84040d52,
+ 0x48066414, 0x0201f000, 0x000206e3, 0x0201f800,
+ 0x00020086, 0x813e79c0, 0x02020000, 0x000206d0,
+ 0x0201f000, 0x000206f1, 0x8c00051e, 0x02000000,
+ 0x000206fd, 0x82000d00, 0x00002020, 0x82040d80,
+ 0x00002020, 0x04000014, 0x82000500, 0x000000c0,
+ 0x82000d80, 0x00000080, 0x04000008, 0x813e79c0,
+ 0x02020000, 0x000206d0, 0x42027000, 0x00000041,
+ 0x0201f000, 0x000207a1, 0x813e79c0, 0x02020000,
+ 0x000206d0, 0x42027000, 0x00000043, 0x0201f000,
+ 0x000207a1, 0x59326809, 0x59340a00, 0x8c040d0a,
+ 0x040007ea, 0x59300c14, 0x84040d52, 0x48066414,
+ 0x0401f7e6, 0x492fc857, 0x42000800, 0x00000006,
+ 0x0201f000, 0x000206f8, 0x492fc857, 0x42000800,
+ 0x00000004, 0x0201f000, 0x000206f8, 0x4807c856,
+ 0x59a80068, 0x800409c0, 0x04000003, 0x80080540,
+ 0x0401f002, 0x80080500, 0x48035068, 0x1c01f000,
+ 0x4a030800, 0x00000000, 0x4a030802, 0x00000001,
+ 0x497b0803, 0x497b0804, 0x1c01f000, 0x59840002,
+ 0x8c000500, 0x04000004, 0x84000500, 0x4a030800,
+ 0x00000001, 0x84000544, 0x84000506, 0x48030802,
+ 0x82000d00, 0x0fffffff, 0x42000000, 0x90000000,
+ 0x0201f800, 0x00100b94, 0x59a80069, 0x82000480,
+ 0x00000007, 0x48035069, 0x80000580, 0x42000800,
+ 0x0010b519, 0x48000800, 0x48000801, 0x1c01f000,
+ 0x59a80069, 0x82000480, 0x00000007, 0x48035069,
+ 0x1c01f000, 0x83640480, 0x00000008, 0x0400101b,
+ 0x58c80a03, 0x80000580, 0x82000400, 0x00000008,
+ 0x80040840, 0x040207fd, 0x815c0480, 0x04001013,
+ 0x4200b000, 0x00000007, 0x0201f800, 0x0002075a,
+ 0x4a026203, 0x00000004, 0x4a026406, 0x00000009,
+ 0x4a026203, 0x00000004, 0x4a026007, 0x00000101,
+ 0x0401f809, 0x0401f880, 0x8058b040, 0x040207f3,
+ 0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x0401f7fd, 0x0201f800, 0x001007e4, 0x492e6008,
+ 0x58c80a03, 0x4a025a04, 0x0000002c, 0x497a5800,
+ 0x497a5801, 0x497a5c04, 0x497a5c06, 0x497a5805,
+ 0x4a025a08, 0x00000005, 0x4a025a07, 0x00000002,
+ 0x58c80201, 0x48025c04, 0x58c80202, 0x48025c07,
+ 0x58c80204, 0x48025c08, 0x4a02580d, 0x0000ffff,
+ 0x80040840, 0x0400000c, 0x412c2000, 0x0201f800,
+ 0x001007e4, 0x4a025a04, 0x0000000a, 0x497a5c04,
+ 0x48125800, 0x492c2001, 0x412c2000, 0x80040840,
+ 0x040207f7, 0x1c01f000, 0x4d7c0000, 0x4202f800,
+ 0x00000010, 0x4df00000, 0x4203e000, 0x50000000,
+ 0x59847803, 0x803c79c0, 0x0400001e, 0x4c5c0000,
+ 0x583cb808, 0x585c3408, 0x801831c0, 0x0400000b,
+ 0x0401f84a, 0x04000016, 0x42001000, 0x0010b519,
+ 0x0401f87f, 0x04000012, 0x0201f800, 0x001007d3,
+ 0x0400000f, 0x492cb805, 0x585c0005, 0x80000540,
+ 0x02000800, 0x001005d8, 0x0401f830, 0x585c5408,
+ 0x0401f80b, 0x5c00b800, 0x5c03e000, 0x817ef840,
+ 0x040207e1, 0x5c02f800, 0x1c01f000, 0x5c00b800,
+ 0x5c03e000, 0x5c02f800, 0x1c01f000, 0x4803c856,
+ 0x405c6000, 0x802851c0, 0x04000018, 0x585c0204,
+ 0x82000d00, 0x0000000f, 0x82040c00, 0x001010bd,
+ 0x50044000, 0x4cf00000, 0x4d000000, 0x4d040000,
+ 0x4021e000, 0x40320800, 0x59860004, 0x4c280000,
+ 0x0401f934, 0x5c005000, 0x40f04000, 0x41046000,
+ 0x0201f800, 0x0010109b, 0x040207f6, 0x5c020800,
+ 0x5c020000, 0x5c01e000, 0x58c80204, 0x4800bc08,
+ 0x0201f800, 0x00020086, 0x4a026007, 0x00000101,
+ 0x497a6009, 0x0401f055, 0x4803c856, 0x59840003,
+ 0x80026540, 0x04000003, 0x59300000, 0x48030803,
+ 0x1c01f000, 0x4803c856, 0x59840003, 0x48026000,
+ 0x49330803, 0x1c01f000, 0x58cc0805, 0x40180000,
+ 0x80040480, 0x0400100d, 0x82cc0580, 0x0010b50e,
+ 0x02020800, 0x001005d8, 0x58c80205, 0x80040480,
+ 0x0400101d, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x80003580, 0x0401f7fe, 0x82cc0580, 0x0010b50e,
+ 0x02020800, 0x001005d8, 0x58c80400, 0x8c000504,
+ 0x040007f8, 0x58c8040b, 0x8c00051e, 0x040007f5,
+ 0x8c000500, 0x040207f3, 0x84000540, 0x4801940b,
+ 0x42000000, 0x0010b839, 0x0201f800, 0x0010aa47,
+ 0x42001000, 0x00008026, 0x0201f800, 0x00103a3e,
+ 0x0401f7e8, 0x58c8040b, 0x8c00051e, 0x040007e2,
+ 0x8c000502, 0x040207e0, 0x84000542, 0x4801940b,
+ 0x42000000, 0x0010b838, 0x0201f800, 0x0010aa47,
+ 0x42001000, 0x00008025, 0x42001800, 0x00000000,
+ 0x0201f800, 0x00103a3e, 0x0401f7d3, 0x4803c856,
+ 0x58080000, 0x42001800, 0x00000007, 0x58080801,
+ 0x80040480, 0x04020004, 0x400c0000, 0x80000540,
+ 0x0401f005, 0x04001003, 0x800c0480, 0x0401f002,
+ 0x80000080, 0x1c01f000, 0x4803c856, 0x59300008,
+ 0x80000d40, 0x02000800, 0x001005d8, 0x58040005,
+ 0x80000540, 0x02000800, 0x001005d8, 0x59300007,
+ 0x82000500, 0x00000101, 0x82000580, 0x00000101,
+ 0x02020800, 0x001005d8, 0x42001000, 0x0010b519,
+ 0x58080801, 0x82040400, 0x0010b51b, 0x497a6414,
+ 0x4a026015, 0x0000ffff, 0x45300000, 0x80040800,
+ 0x82040480, 0x00000008, 0x04001002, 0x80000d80,
+ 0x48041001, 0x82040400, 0x0010b51b, 0x45780000,
+ 0x1c01f000, 0x4933c857, 0x59300808, 0x800409c0,
+ 0x02000800, 0x001005d8, 0x4d2c0000, 0x58065805,
+ 0x812e59c0, 0x02020800, 0x001007f4, 0x49780805,
+ 0x40065800, 0x0201f800, 0x001007fd, 0x5c025800,
+ 0x4d300000, 0x0201f800, 0x0002077d, 0x5c026000,
+ 0x1c01f000, 0x59300406, 0x82000580, 0x00000009,
+ 0x04020006, 0x59300007, 0x8c000510, 0x04000003,
+ 0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x59840802, 0x8c040d04, 0x1c01f000,
+ 0x4803c856, 0x59840802, 0x84040d04, 0x84040d40,
+ 0x4a030800, 0x00000000, 0x48070802, 0x82040d00,
+ 0x0fffffff, 0x42000000, 0x90000000, 0x0201f000,
+ 0x00100b94, 0x4807c857, 0x4805980a, 0x49799801,
+ 0x49799803, 0x49799806, 0x49799807, 0x49799808,
+ 0x49799805, 0x49799809, 0x0401f8c9, 0x0400000a,
+ 0x0401f8eb, 0x04000008, 0x48359800, 0x48359802,
+ 0x48359806, 0x4a019804, 0x00000001, 0x4a019807,
+ 0x00000005, 0x1c01f000, 0x4807c857, 0x58cc1007,
+ 0x40040000, 0x80080480, 0x04021020, 0x4c040000,
+ 0x4c080000, 0x0401f8da, 0x5c001000, 0x5c000800,
+ 0x0400001c, 0x58cc0006, 0x80006540, 0x0402000b,
+ 0x48359800, 0x48359802, 0x48359806, 0x49799801,
+ 0x49799803, 0x49786801, 0x49786800, 0x49799804,
+ 0x49799807, 0x0401f005, 0x48306801, 0x48346000,
+ 0x48359806, 0x49786800, 0x58cc0004, 0x58cc1007,
+ 0x80000000, 0x82081400, 0x00000005, 0x48019804,
+ 0x48099807, 0x0401f7df, 0x80000580, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x480bc857,
+ 0x4c500000, 0x4c540000, 0x4c580000, 0x40083000,
+ 0x58cc0801, 0x82040480, 0x00000005, 0x02021800,
+ 0x001005d8, 0x82040400, 0x00106418, 0x50000000,
+ 0x58cca800, 0x8054ac00, 0x42001800, 0x00000005,
+ 0x40040000, 0x800c0480, 0x80082480, 0x04021002,
+ 0x40080000, 0x8000b0c2, 0x8058b400, 0x5450a800,
+ 0x8050a000, 0x8054a800, 0x8058b040, 0x040207fc,
+ 0x40001000, 0x58cc2805, 0x58cc0807, 0x58cc2001,
+ 0x80142c00, 0x80040c80, 0x80102400, 0x48159805,
+ 0x48059807, 0x48119801, 0x82100580, 0x00000005,
+ 0x0400000c, 0x48119801, 0x40080000, 0x80181480,
+ 0x40083000, 0x04000003, 0x040217d6, 0x80000580,
+ 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x1c01f000,
+ 0x58cc0800, 0x800409c0, 0x02000800, 0x001005d8,
+ 0x58040800, 0x48059800, 0x41782000, 0x0401f7ee,
+ 0x0401f813, 0x50f00000, 0x81040400, 0x40001800,
+ 0x585c0204, 0x4803c857, 0x82000580, 0x0000002c,
+ 0x02020800, 0x001005d8, 0x58040202, 0x800000e0,
+ 0x81000540, 0x48001802, 0x58040000, 0x48001800,
+ 0x58040001, 0x48001801, 0x1c01f000, 0x4807c856,
+ 0x58cc0005, 0x80000040, 0x02001800, 0x001005d8,
+ 0x48019805, 0x58cc1003, 0x82080480, 0x00000005,
+ 0x02021800, 0x001005d8, 0x82080400, 0x00106418,
+ 0x50000000, 0x58cc0802, 0x80040c00, 0x80081000,
+ 0x82080480, 0x00000005, 0x0402000f, 0x58cc2002,
+ 0x58100000, 0x80006d40, 0x04000009, 0x4c340000,
+ 0x0401f858, 0x5c006800, 0x49786801, 0x48359802,
+ 0x58cc0004, 0x80000040, 0x48019804, 0x49799803,
+ 0x0401f002, 0x48099803, 0x1c01f000, 0x4807c856,
+ 0x41781800, 0x58c80201, 0x80000540, 0x04000002,
+ 0x800c1800, 0x58c80c01, 0x80040c80, 0x0400100a,
+ 0x04000009, 0x800c1800, 0x58c80202, 0x80041480,
+ 0x04001005, 0x04000004, 0x800c1800, 0x40080800,
+ 0x0401f7fb, 0x480d9204, 0x400c0000, 0x42002000,
+ 0x00000001, 0x80000040, 0x04000007, 0x04001006,
+ 0x80102000, 0x82000480, 0x00000005, 0x04000002,
+ 0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856,
+ 0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800,
+ 0x001005d8, 0x82002400, 0x00000005, 0x0201f800,
+ 0x001007d3, 0x04000012, 0x492d9809, 0x497a5800,
+ 0x497a5801, 0x0201f800, 0x001007d3, 0x0400000c,
+ 0x58cc0009, 0x48025800, 0x497a5801, 0x492d9809,
+ 0x82102480, 0x00000005, 0x040217f7, 0x82000540,
+ 0x00000001, 0x5c025800, 0x1c01f000, 0x58cc0009,
+ 0x80025d40, 0x040007fc, 0x592c2000, 0x0201f800,
+ 0x001007f4, 0x40100000, 0x0401f7fa, 0x58cc0009,
+ 0x48cfc857, 0x80006d40, 0x04000005, 0x50340000,
+ 0x48019809, 0x49786800, 0x49786801, 0x1c01f000,
+ 0x4813c857, 0x58cc0009, 0x48002000, 0x48119809,
+ 0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0009,
+ 0x80025d40, 0x04000007, 0x592c0000, 0x4c000000,
+ 0x0201f800, 0x001007f4, 0x5c000000, 0x0401f7f9,
+ 0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000,
+ 0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000,
+ 0x4c000000, 0x0201f800, 0x001007f4, 0x5c000000,
+ 0x0401f7f9, 0x49799800, 0x49799802, 0x49799801,
+ 0x49799803, 0x49799806, 0x49799807, 0x49799808,
+ 0x49799809, 0x4979980a, 0x5c025800, 0x1c01f000,
+ 0x00000003, 0x00000006, 0x00000009, 0x0000000c,
+ 0x0000000f, 0x00000012, 0x4803c856, 0x0401f857,
+ 0x4a00c204, 0x0000003c, 0x59301009, 0x82080580,
+ 0x0010b524, 0x04000013, 0x58080802, 0x82040d00,
+ 0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406,
+ 0x4a00c207, 0x00000003, 0x59300811, 0x585c0404,
+ 0x4978c206, 0x4804c407, 0x80000540, 0x0400000d,
+ 0x58600206, 0x84000540, 0x4800c206, 0x0401f009,
+ 0x585c080a, 0x82040d00, 0x00ffffff, 0x4804c005,
+ 0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef,
+ 0x82603c00, 0x00000008, 0x58605404, 0x40282000,
+ 0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f,
+ 0x82040c00, 0x001010bd, 0x50044000, 0x80004d80,
+ 0x50200000, 0x80307400, 0x58380402, 0x8c244d00,
+ 0x04020003, 0x48003a00, 0x0401f003, 0x48003c00,
+ 0x801c3800, 0x80244800, 0x80102040, 0x04000006,
+ 0x0201f800, 0x0010109b, 0x02000800, 0x001005d8,
+ 0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000,
+ 0x59300009, 0x80026d40, 0x02000800, 0x001005d8,
+ 0x59340401, 0x80000540, 0x0400000e, 0x59840000,
+ 0x80000540, 0x0400000b, 0x836c0580, 0x00000003,
+ 0x04020008, 0x59341c03, 0x42002000, 0x00000004,
+ 0x42003000, 0x00000004, 0x0201f800, 0x00103aae,
+ 0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580,
+ 0x58c80c01, 0x59300011, 0x80040c80, 0x48066011,
+ 0x58c80201, 0x80000540, 0x04000005, 0x80081000,
+ 0x80040c80, 0x04001007, 0x04000006, 0x58c80202,
+ 0x80081000, 0x80040c80, 0x04001002, 0x040207fd,
+ 0x4808bc08, 0x4808c404, 0x1c01f000, 0x4803c856,
+ 0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524,
+ 0x040207fc, 0x4a0370e5, 0x00030000, 0x40000000,
+ 0x40000000, 0x59b800e5, 0x8c000524, 0x040207f5,
+ 0x5934000e, 0x80006d40, 0x04000010, 0x81300580,
+ 0x04020004, 0x58340000, 0x4802680e, 0x0401f00a,
+ 0x40347800, 0x58340000, 0x80006d40, 0x02000800,
+ 0x001005d8, 0x81300580, 0x040207fa, 0x58340000,
+ 0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000,
+ 0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000,
+ 0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000,
+ 0x59b800e5, 0x8c000524, 0x04000005, 0x80040840,
+ 0x040207fa, 0x0201f800, 0x001005d8, 0x4a0370e5,
+ 0x00030000, 0x40000000, 0x40000000, 0x59b800e5,
+ 0x8c000524, 0x040207f1, 0x5934000e, 0x80026540,
+ 0x0400000e, 0x4933c857, 0x59300000, 0x4802680e,
+ 0x4a026203, 0x00000004, 0x497a6206, 0x497a6009,
+ 0x4a026007, 0x00000101, 0x59325808, 0x497a5c08,
+ 0x0401fd81, 0x0401f7f1, 0x4a0370e5, 0x00020000,
+ 0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856,
+ 0x4c000000, 0x0201f800, 0x00105c9a, 0x04020011,
+ 0x0201f800, 0x001045a6, 0x02020800, 0x001005d8,
+ 0x5c000000, 0x48026802, 0x0201f800, 0x0002075a,
+ 0x04000009, 0x49366009, 0x4a026406, 0x00000001,
+ 0x42027000, 0x00000001, 0x0201f000, 0x000207a1,
+ 0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+ 0x0c01f001, 0x00106503, 0x00106503, 0x00106503,
+ 0x00106505, 0x00106565, 0x00106503, 0x00106503,
+ 0x001065b7, 0x001065b8, 0x00106503, 0x00106503,
+ 0x00106503, 0x00106503, 0x00106503, 0x0201f800,
+ 0x001005d8, 0x493bc857, 0x83380480, 0x00000050,
+ 0x02021800, 0x001005d8, 0x83380480, 0x00000049,
+ 0x02001800, 0x001005d8, 0x0c01f001, 0x00106518,
+ 0x0010653a, 0x00106516, 0x00106516, 0x00106516,
+ 0x00106516, 0x00106549, 0x0201f800, 0x001005d8,
+ 0x4d2c0000, 0x59325808, 0x592c0206, 0x48025c06,
+ 0x4a025a06, 0x00000000, 0x4c5c0000, 0x592cbc0a,
+ 0x592c0000, 0x48026008, 0x0201f800, 0x00104cde,
+ 0x59300008, 0x80000540, 0x04000008, 0x4a026203,
+ 0x00000007, 0x42027000, 0x00000043, 0x5c00b800,
+ 0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006,
+ 0x4a026203, 0x00000007, 0x497a6206, 0x497a6008,
+ 0x0401f003, 0x0201f800, 0x0002077d, 0x5c00b800,
+ 0x5c025800, 0x1c01f000, 0x0201f800, 0x00106b8a,
+ 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+ 0x04000006, 0x4d400000, 0x42028000, 0x00000001,
+ 0x0401f8f8, 0x5c028000, 0x5c025800, 0x0201f000,
+ 0x0002077d, 0x0201f800, 0x00106b8a, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+ 0x42003000, 0x00000014, 0x0201f800, 0x0010a942,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+ 0x04000006, 0x4d400000, 0x42028000, 0x00000029,
+ 0x0401f8dc, 0x5c028000, 0x5c025800, 0x0201f000,
+ 0x0002077d, 0x493bc857, 0x497a6206, 0x83380480,
+ 0x00000054, 0x02021800, 0x001005d8, 0x83380480,
+ 0x00000047, 0x02001800, 0x001005d8, 0x0c01f001,
+ 0x001065b6, 0x0010657f, 0x0010657d, 0x0010657d,
+ 0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d,
+ 0x0010657d, 0x0010657d, 0x0010657d, 0x0010657d,
+ 0x00106583, 0x0201f800, 0x001005d8, 0x59300011,
+ 0x82000500, 0xffff0000, 0x04020034, 0x59840802,
+ 0x8c040d04, 0x04000025, 0x59300009, 0x80026d40,
+ 0x0400001f, 0x4c5c0000, 0x4c600000, 0x497a6206,
+ 0x5930b808, 0x585c0005, 0x8000c540, 0x02000800,
+ 0x001005d8, 0x0401fe8d, 0x40625800, 0x0201f800,
+ 0x00104cde, 0x4978b805, 0x0401fef5, 0x497a6009,
+ 0x585c3408, 0x0401fcbd, 0x0400000e, 0x42001000,
+ 0x0010b519, 0x0401fcf2, 0x0400000a, 0x0201f800,
+ 0x001007e4, 0x04000007, 0x492cb805, 0x585c5408,
+ 0x0401fc83, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+ 0x0401fca9, 0x0401f7fc, 0x8c040d06, 0x040207fc,
+ 0x59300009, 0x80026d40, 0x04000006, 0x5934000e,
+ 0x80000540, 0x02020800, 0x001005d8, 0x497a6009,
+ 0x0401fd0d, 0x0401f7f2, 0x0401f06f, 0x4803c856,
+ 0x4803c856, 0x83380580, 0x00000043, 0x02020800,
+ 0x001005d8, 0x4a026203, 0x00000003, 0x493a6403,
+ 0x59325808, 0x592c000f, 0x48026011, 0x497a6013,
+ 0x592c0406, 0x800000c2, 0x800010c4, 0x80081400,
+ 0x480a6206, 0x0201f800, 0x00100f4e, 0x42000800,
+ 0x80000060, 0x0401f154, 0x42000000, 0x0010b875,
+ 0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+ 0x82000d80, 0x00000003, 0x04000006, 0x82000d80,
+ 0x00000004, 0x04000045, 0x0201f800, 0x001005d8,
+ 0x0201f800, 0x00106c55, 0x59300004, 0x8c00053e,
+ 0x04020007, 0x0201f800, 0x00106b6c, 0x02020800,
+ 0x001005d8, 0x0201f000, 0x00106c4b, 0x0401f9c3,
+ 0x0201f800, 0x00106c4b, 0x59325808, 0x42028000,
+ 0x00000006, 0x0401f84b, 0x0201f000, 0x0002077d,
+ 0x4803c856, 0x59300203, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x82000d80, 0x00000003,
+ 0x04000006, 0x82000d80, 0x00000004, 0x04000023,
+ 0x0201f800, 0x001005d8, 0x4803c856, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x59300004, 0x8c00053e,
+ 0x04020006, 0x0201f800, 0x00106f60, 0x02020800,
+ 0x001005d8, 0x0401f010, 0x0201f800, 0x00108cd6,
+ 0x04020004, 0x0201f800, 0x00106e62, 0x0402000a,
+ 0x0401f99a, 0x02020800, 0x001005d8, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x80000580, 0x1c01f000, 0x4933c857, 0x0201f800,
+ 0x00100e99, 0x4933c857, 0x4c5c0000, 0x4d340000,
+ 0x497a6206, 0x5930b808, 0x59300009, 0x80026d40,
+ 0x04020e5f, 0x42001000, 0x0010b519, 0x0401fc60,
+ 0x04000009, 0x58c80204, 0x4800bc08, 0x41785000,
+ 0x0201f800, 0x00106227, 0x5c026800, 0x5c00b800,
+ 0x1c01f000, 0x4978bc08, 0x0401fc17, 0x0401f7fb,
+ 0x4803c856, 0x0201f800, 0x00109037, 0x0400000f,
+ 0x592c0000, 0x80000d40, 0x04000009, 0x497a5800,
+ 0x49425a06, 0x4c040000, 0x0201f800, 0x000202da,
+ 0x5c000800, 0x40065800, 0x0401f7f6, 0x49425a06,
+ 0x0201f800, 0x000202da, 0x1c01f000, 0x4933c857,
+ 0x59300c06, 0x82040580, 0x0000000e, 0x04000004,
+ 0x82040580, 0x00000009, 0x04020004, 0x0401ffe5,
+ 0x497a6008, 0x80000580, 0x1c01f000, 0x592e6009,
+ 0x83300480, 0x0010d1c0, 0x04001016, 0x41580000,
+ 0x81300480, 0x04021013, 0x40040000, 0x59300c06,
+ 0x80040580, 0x04020012, 0x59300a03, 0x82040580,
+ 0x00000007, 0x02020800, 0x001005d8, 0x59300008,
+ 0x80000540, 0x02020800, 0x001005d8, 0x0201f800,
+ 0x0002077d, 0x42000000, 0x00000000, 0x0401f009,
+ 0x42000000, 0x00000008, 0x0401f006, 0x82040580,
+ 0x00000007, 0x040207fb, 0x42000000, 0x00000005,
+ 0x592c0a06, 0x48065c06, 0x48025a06, 0x0201f000,
+ 0x000202da, 0x4c0c0000, 0x4c100000, 0x4c140000,
+ 0x4c180000, 0x80001d80, 0x80002580, 0x42003000,
+ 0x00000020, 0x82040500, 0x00000001, 0x04000003,
+ 0x40080000, 0x800c1c00, 0x400c2800, 0x800c1902,
+ 0x80102102, 0x82140500, 0x00000001, 0x04000003,
+ 0x82102540, 0x80000000, 0x80040902, 0x80183040,
+ 0x040207f1, 0x40100800, 0x400c0000, 0x5c003000,
+ 0x5c002800, 0x5c002000, 0x5c001800, 0x1c01f000,
+ 0x4c580000, 0x4200b000, 0x00000020, 0x80000540,
+ 0x04000018, 0x80041c80, 0x04021016, 0x800810c2,
+ 0x80040982, 0x04001006, 0x80041c80, 0x04021005,
+ 0x8058b040, 0x040207fa, 0x0401f006, 0x80041c80,
+ 0x400c0800, 0x80081000, 0x8058b040, 0x040207f4,
+ 0x4c000000, 0x41f00000, 0x82000500, 0xf7ffffff,
+ 0x4003e000, 0x5c000000, 0x5c00b000, 0x1c01f000,
+ 0x4c000000, 0x41f00000, 0x82000540, 0x08000000,
+ 0x0401f7f8, 0x4a0378e8, 0x00000000, 0x4a03c821,
+ 0x00000010, 0x4a03c823, 0x00000004, 0x0401f82c,
+ 0x4a0378e9, 0x00003a0d, 0x4a0378e8, 0x00000001,
+ 0x42000000, 0x00001000, 0x50000000, 0x82000480,
+ 0x24220001, 0x04000004, 0x59e00002, 0x84000548,
+ 0x4803c002, 0x42000800, 0x00000005, 0x4203a000,
+ 0x00007600, 0x42000000, 0x00001000, 0x50000000,
+ 0x82000480, 0x24320001, 0x04021003, 0x4a03a005,
+ 0xd0000001, 0x59d00006, 0x4a03a005, 0x90000001,
+ 0x83d3a400, 0x00000020, 0x80040840, 0x040207fa,
+ 0x59e00003, 0x82000500, 0xffffffe0, 0x82000540,
+ 0x00008000, 0x4803c003, 0x59c40006, 0x82000500,
+ 0xfffcffff, 0x48038806, 0x1c01f000, 0x4d900000,
+ 0x4d180000, 0x4a0378e7, 0xaaaaaaaa, 0x4a0378e6,
+ 0xaaaaaaaa, 0x4a0378e5, 0xaaaaaaaa, 0x4a0378e4,
+ 0xaaaaaaaa, 0x42000800, 0x0000bf00, 0x4a00081a,
+ 0x0010b7d4, 0x4a00081b, 0x001010bd, 0x4a00081c,
+ 0x001010cd, 0x4a031800, 0x00000000, 0x4a031801,
+ 0x0010b544, 0x4a031802, 0x0010b54b, 0x42000800,
+ 0x0010b7d7, 0x417a3000, 0x811b20c8, 0x83932400,
+ 0x0000bf32, 0x48072000, 0x4a032001, 0x00000000,
+ 0x83180400, 0x001070ea, 0x50000000, 0x48032002,
+ 0x82040c00, 0x00000003, 0x811a3000, 0x83180480,
+ 0x00000005, 0x040017f1, 0x5c023000, 0x5c032000,
+ 0x1c01f000, 0x48066004, 0x497a6000, 0x497a6001,
+ 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400,
+ 0xa0000000, 0x480378e1, 0x1c01f000, 0x4933c857,
+ 0x42000800, 0x80000040, 0x48066004, 0x497a6000,
+ 0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400,
+ 0x60000000, 0x480378e1, 0x1c01f000, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x4d300000, 0x4d340000,
+ 0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000,
+ 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+ 0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0,
+ 0x0400002c, 0x41302800, 0x4178c000, 0x59300000,
+ 0x4c000000, 0x59326809, 0x5930b801, 0x59300406,
+ 0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18,
+ 0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580,
+ 0x00000003, 0x04020004, 0x59340200, 0x8c00050e,
+ 0x04020008, 0x0401f92f, 0x4c0c0000, 0x4c140000,
+ 0x0401fb5f, 0x5c002800, 0x5c001800, 0x0401f005,
+ 0x41301800, 0x8060c1c0, 0x04020002, 0x400cc000,
+ 0x805cb9c0, 0x04000003, 0x405e6000, 0x0401f7e3,
+ 0x5c026000, 0x813261c0, 0x04000006, 0x8060c1c0,
+ 0x04000002, 0x40602800, 0x4178c000, 0x0401f7d8,
+ 0x417a3000, 0x0201f800, 0x001070d8, 0x59926004,
+ 0x813261c0, 0x04000023, 0x59326809, 0x4130c000,
+ 0x59300001, 0x8000bd40, 0x04000016, 0x40026000,
+ 0x40602800, 0x5930b801, 0x59300406, 0x82000d80,
+ 0x00000006, 0x0400000e, 0x8d3e7d06, 0x04000007,
+ 0x82000580, 0x00000003, 0x04020004, 0x59340200,
+ 0x8c00050e, 0x04020006, 0x0401f8dc, 0x4c140000,
+ 0x0401fb2f, 0x5c002800, 0x0401f002, 0x41302800,
+ 0x405e6000, 0x813261c0, 0x040207eb, 0x8060c1c0,
+ 0x04000004, 0x40626000, 0x4178c000, 0x0401f7e7,
+ 0x811a3000, 0x83180480, 0x00000005, 0x040017d6,
+ 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+ 0x5c00c000, 0x5c00b800, 0x5c023000, 0x5c025800,
+ 0x5c026800, 0x5c026000, 0x5c03e000, 0x02000800,
+ 0x00106c4b, 0x1c01f000, 0x4933c857, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x4d340000, 0x4d180000,
+ 0x4d900000, 0x42003000, 0x0000bf2e, 0x59326809,
+ 0x58182001, 0x40102800, 0x801021c0, 0x04000016,
+ 0x41300000, 0x80100580, 0x04000011, 0x58100009,
+ 0x81340580, 0x0402000b, 0x40101800, 0x58102001,
+ 0x41300000, 0x801021c0, 0x0400000b, 0x80100d80,
+ 0x04000007, 0x40101800, 0x58102001, 0x0401f7fa,
+ 0x40102800, 0x58102000, 0x0401f7ec, 0x0401f8bd,
+ 0x0401f01a, 0x42032000, 0x0000bf32, 0x417a3000,
+ 0x59902004, 0x40102800, 0x801021c0, 0x0400000b,
+ 0x58100009, 0x81340580, 0x04020008, 0x41300000,
+ 0x80100580, 0x0400000c, 0x40102800, 0x58102001,
+ 0x801021c0, 0x040207fa, 0x811a3000, 0x83180480,
+ 0x00000005, 0x0402100d, 0x83932400, 0x00000010,
+ 0x0401f7ec, 0x0401f881, 0x5c032000, 0x5c023000,
+ 0x5c026800, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x80000580, 0x1c01f000, 0x0401fb6f, 0x040007f7,
+ 0x5c032000, 0x5c023000, 0x5c026800, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x0201f800, 0x00106c55, 0x4df00000,
+ 0x4d300000, 0x4d340000, 0x4d180000, 0x4d2c0000,
+ 0x4c5c0000, 0x4c600000, 0x4d900000, 0x4dd00000,
+ 0x4da40000, 0x4d140000, 0x42003000, 0x0000bf2e,
+ 0x581a6001, 0x813261c0, 0x04000023, 0x41302800,
+ 0x5930b800, 0x59326809, 0x59340403, 0x81440580,
+ 0x04000006, 0x805cb9c0, 0x0400001b, 0x41302800,
+ 0x405e6000, 0x0401f7f7, 0x5930b801, 0x8d3e7d00,
+ 0x04000003, 0x0401fb67, 0x0402000e, 0x59300406,
+ 0x82000580, 0x00000006, 0x04020003, 0x8d3e7d18,
+ 0x04000008, 0x0401f867, 0x4c0c0000, 0x4c140000,
+ 0x0401fa97, 0x5c002800, 0x5c001800, 0x0401f002,
+ 0x41301800, 0x405e6000, 0x813261c0, 0x040207eb,
+ 0x0401f02d, 0x417a3000, 0x0201f800, 0x001070d8,
+ 0x59926004, 0x813261c0, 0x04000005, 0x59326809,
+ 0x59340403, 0x81440580, 0x04000006, 0x811a3000,
+ 0x83180480, 0x00000005, 0x040017f4, 0x0401f01e,
+ 0x4130c000, 0x59300001, 0x8000bd40, 0x04000012,
+ 0x40026000, 0x40602800, 0x5930b801, 0x8d3e7d00,
+ 0x04000003, 0x0401fb3b, 0x0402000a, 0x59300406,
+ 0x82000580, 0x00000006, 0x04000006, 0x0401f81b,
+ 0x4c140000, 0x0401fa6e, 0x5c002800, 0x0401f002,
+ 0x41302800, 0x405e6000, 0x813261c0, 0x040207ef,
+ 0x8060c1c0, 0x04000004, 0x40626000, 0x4178c000,
+ 0x0401f7eb, 0x5c022800, 0x5c034800, 0x5c03a000,
+ 0x5c032000, 0x5c00c000, 0x5c00b800, 0x5c025800,
+ 0x5c023000, 0x5c026800, 0x5c026000, 0x5c03e000,
+ 0x04000be3, 0x1c01f000, 0x0401fbc8, 0x59900004,
+ 0x81300580, 0x04020018, 0x4c140000, 0x0201f800,
+ 0x00106dc3, 0x0401fbb8, 0x5c002800, 0x59300001,
+ 0x800001c0, 0x04020003, 0x497a680c, 0x1c01f000,
+ 0x42003000, 0x0000bf2e, 0x497a6001, 0x58180801,
+ 0x800409c0, 0x04020004, 0x48003000, 0x48003001,
+ 0x1c01f000, 0x58180800, 0x48000800, 0x48003000,
+ 0x1c01f000, 0x59300001, 0x48002801, 0x800001c0,
+ 0x04020002, 0x4816680c, 0x497a6001, 0x1c01f000,
+ 0x0401fba6, 0x42003000, 0x0000bf2e, 0x58180001,
+ 0x81300580, 0x0402001c, 0x59300801, 0x800409c0,
+ 0x0400000e, 0x59300000, 0x800001c0, 0x04020005,
+ 0x48043001, 0x48043000, 0x497a6001, 0x1c01f000,
+ 0x59300000, 0x48000800, 0x48043001, 0x497a6000,
+ 0x497a6001, 0x1c01f000, 0x59300800, 0x800409c0,
+ 0x04020005, 0x49783001, 0x49783000, 0x497a680c,
+ 0x1c01f000, 0x48043001, 0x497a6000, 0x497a680c,
+ 0x1c01f000, 0x58180000, 0x81300580, 0x0402000c,
+ 0x59300001, 0x800001c0, 0x04020005, 0x48143000,
+ 0x49782800, 0x497a680c, 0x1c01f000, 0x48003000,
+ 0x48002800, 0x497a6001, 0x1c01f000, 0x59300000,
+ 0x800001c0, 0x04020008, 0x59300001, 0x48001801,
+ 0x800001c0, 0x04020002, 0x480e680c, 0x497a6001,
+ 0x1c01f000, 0x59300801, 0x800409c0, 0x04020006,
+ 0x59300800, 0x48042800, 0x497a6000, 0x497a680c,
+ 0x1c01f000, 0x59300000, 0x48000800, 0x48042800,
+ 0x497a6000, 0x497a6001, 0x1c01f000, 0x0401fb82,
+ 0x4df00000, 0x0401f839, 0x040208c4, 0x04020945,
+ 0x04020a89, 0x04020005, 0x5c03e000, 0x04000b70,
+ 0x80000580, 0x1c01f000, 0x5c03e000, 0x04000b6c,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4d2c0000,
+ 0x4d340000, 0x4d300000, 0x41783000, 0x598e6009,
+ 0x813261c0, 0x04000021, 0x59300406, 0x82000580,
+ 0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000a,
+ 0x0401f017, 0x82040580, 0x00000005, 0x04020006,
+ 0x8d3e7d16, 0x04000004, 0x59300420, 0x8c000500,
+ 0x0402000f, 0x0401fa4e, 0x59300000, 0x4c000000,
+ 0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7,
+ 0x04000005, 0x0401f867, 0x4c180000, 0x0401f9bc,
+ 0x5c003000, 0x5c026000, 0x0401f7e2, 0x41303000,
+ 0x59326000, 0x0401f7df, 0x5c026000, 0x5c026800,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+ 0x813261c0, 0x02000800, 0x001005d8, 0x41300000,
+ 0x598cb809, 0x41783000, 0x805cb9c0, 0x04000013,
+ 0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800,
+ 0x0401f7fa, 0x0401f84b, 0x598c000d, 0x81300580,
+ 0x02000800, 0x001070b9, 0x59300403, 0x82000580,
+ 0x00000042, 0x04020002, 0x497a6007, 0x80000580,
+ 0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x5c00b800, 0x1c01f000, 0x0401fb27, 0x4df00000,
+ 0x4d2c0000, 0x4d340000, 0x4d300000, 0x41783000,
+ 0x598e6009, 0x813261c0, 0x0400002c, 0x59300c06,
+ 0x82040580, 0x00000006, 0x04020004, 0x8d3e7d18,
+ 0x0402000a, 0x0401f022, 0x82040580, 0x00000005,
+ 0x04020006, 0x8d3e7d18, 0x04000004, 0x59300420,
+ 0x8c000500, 0x0402001a, 0x59326809, 0x59340403,
+ 0x81440580, 0x04020016, 0x8d3e7d00, 0x04000006,
+ 0x82040580, 0x00000003, 0x04020011, 0x0401fa35,
+ 0x0402000f, 0x0401f9f6, 0x59300000, 0x4c000000,
+ 0x8d3e7d06, 0x04000004, 0x0201f800, 0x001092d7,
+ 0x04000005, 0x0401f80f, 0x4c180000, 0x0401f964,
+ 0x5c003000, 0x5c026000, 0x0401f7d7, 0x41303000,
+ 0x59326000, 0x0401f7d4, 0x5c026000, 0x5c026800,
+ 0x5c025800, 0x5c03e000, 0x04000ae5, 0x1c01f000,
+ 0x59300800, 0x497a6000, 0x0401fac8, 0x801831c0,
+ 0x04020009, 0x598c0008, 0x81300580, 0x04020004,
+ 0x48031808, 0x48031809, 0x0401f008, 0x48071809,
+ 0x0401f006, 0x48043000, 0x598c0008, 0x81300580,
+ 0x04020002, 0x481b1808, 0x0401f2ca, 0x4d2c0000,
+ 0x4d300000, 0x4d340000, 0x41783000, 0x598e600b,
+ 0x813261c0, 0x04000013, 0x8d3e7d06, 0x04000005,
+ 0x59326809, 0x59340200, 0x8c00050e, 0x0402000a,
+ 0x0401f9bf, 0x59300000, 0x4c000000, 0x0401f853,
+ 0x4c180000, 0x0401f932, 0x5c003000, 0x5c026000,
+ 0x0401f7f0, 0x41303000, 0x59326000, 0x0401f7ed,
+ 0x0201f800, 0x00104773, 0x5c026800, 0x5c026000,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+ 0x813261c0, 0x02000800, 0x001005d8, 0x41300000,
+ 0x598cb80b, 0x41783000, 0x805cb9c0, 0x0400000f,
+ 0x805c0d80, 0x04000004, 0x405c3000, 0x5818b800,
+ 0x0401f7fa, 0x0401f835, 0x598c000d, 0x81300580,
+ 0x02000800, 0x001070b9, 0x497a6007, 0x80000580,
+ 0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x5c00b800, 0x1c01f000, 0x0401fa9f, 0x4df00000,
+ 0x4d340000, 0x4d300000, 0x4d2c0000, 0x0201f800,
+ 0x00020245, 0x02020800, 0x001005d8, 0x41783000,
+ 0x598e600b, 0x813261c0, 0x04000014, 0x59300009,
+ 0x81340580, 0x0402000e, 0x8d3e7d00, 0x04000003,
+ 0x0401f9bc, 0x0402000a, 0x0401f97d, 0x59300000,
+ 0x4c000000, 0x0401f811, 0x4c180000, 0x0401f8f0,
+ 0x5c003000, 0x5c026000, 0x0401f7ef, 0x41303000,
+ 0x59326000, 0x0401f7ec, 0x0201f800, 0x0010479c,
+ 0x5c025800, 0x5c026000, 0x5c026800, 0x5c03e000,
+ 0x04000a6f, 0x1c01f000, 0x59300800, 0x497a6000,
+ 0x0401fa52, 0x801831c0, 0x04020009, 0x598c000a,
+ 0x81300580, 0x04020004, 0x4803180a, 0x4803180b,
+ 0x0401f008, 0x4807180b, 0x0401f006, 0x48043000,
+ 0x598c000a, 0x81300580, 0x04020002, 0x481b180a,
+ 0x0401f254, 0x0401fa64, 0x4df00000, 0x4d300000,
+ 0x598e6005, 0x813261c0, 0x04000020, 0x59300000,
+ 0x4c000000, 0x59300c06, 0x82040580, 0x00000011,
+ 0x04020007, 0x833c0500, 0x00001800, 0x04000015,
+ 0x8d3e7d16, 0x04020013, 0x0401f009, 0x82040580,
+ 0x00000004, 0x04020006, 0x8d3e7d16, 0x04000004,
+ 0x59300420, 0x8c000500, 0x0402000a, 0x0201f800,
+ 0x0010914e, 0x02000800, 0x0010801c, 0x0201f800,
+ 0x00109326, 0x0201f800, 0x0002077d, 0x0401fa31,
+ 0x5c026000, 0x0401f7e0, 0x497b1805, 0x497b1804,
+ 0x5c026000, 0x5c03e000, 0x04000a31, 0x1c01f000,
+ 0x4933c857, 0x4c5c0000, 0x4c600000, 0x813261c0,
+ 0x02000800, 0x001005d8, 0x41300000, 0x598cb805,
+ 0x405cc000, 0x805cb9c0, 0x04000025, 0x805c0d80,
+ 0x04000004, 0x405cc000, 0x5860b800, 0x0401f7fa,
+ 0x598c000d, 0x81300580, 0x02000800, 0x001070b9,
+ 0x0401fa02, 0x598c0005, 0x805c0580, 0x04020009,
+ 0x585c0000, 0x48031805, 0x4978b800, 0x598c0004,
+ 0x805c0580, 0x0402000d, 0x497b1804, 0x0401f00b,
+ 0x598c0004, 0x805c0580, 0x04020005, 0x48631804,
+ 0x4978b800, 0x4978c000, 0x0401f004, 0x585c0000,
+ 0x4800c000, 0x4978b800, 0x0401f9fe, 0x80000580,
+ 0x5c00c000, 0x5c00b800, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+ 0x4933c857, 0x0401fa04, 0x4df00000, 0x4d2c0000,
+ 0x4d340000, 0x4d300000, 0x4c5c0000, 0x4178b800,
+ 0x8d3e7d18, 0x0400000d, 0x8d3e7d16, 0x0402000b,
+ 0x0201f800, 0x00109037, 0x04000008, 0x0201f800,
+ 0x00109597, 0x04020005, 0x592c0207, 0x492fc857,
+ 0x8200bd00, 0x0000000f, 0x41783000, 0x598e6005,
+ 0x813261c0, 0x04000029, 0x59326809, 0x813669c0,
+ 0x04000023, 0x59340403, 0x81440580, 0x04020020,
+ 0x59300c06, 0x82040580, 0x00000011, 0x0400001a,
+ 0x82040580, 0x00000004, 0x04020004, 0x59300420,
+ 0x8c000500, 0x04020016, 0x0201f800, 0x00109037,
+ 0x04000008, 0x0201f800, 0x00109597, 0x04020005,
+ 0x59300403, 0x82000580, 0x00000043, 0x0400000c,
+ 0x0401f8c3, 0x59300000, 0x4c000000, 0x0401f812,
+ 0x4c180000, 0x0401f836, 0x5c003000, 0x5c026000,
+ 0x0401f7dc, 0x805cb9c0, 0x040207ec, 0x41303000,
+ 0x59326000, 0x0401f7d7, 0x5c00b800, 0x5c026000,
+ 0x5c026800, 0x5c025800, 0x5c03e000, 0x040009b4,
+ 0x1c01f000, 0x59300800, 0x497a6000, 0x0401f997,
+ 0x801831c0, 0x04020009, 0x598c0004, 0x81300580,
+ 0x04020004, 0x48031804, 0x48031805, 0x0401f008,
+ 0x48071805, 0x0401f006, 0x48043000, 0x598c0004,
+ 0x81300580, 0x04020002, 0x481b1804, 0x0401f199,
+ 0x4943c857, 0x0401f9a8, 0x4df00000, 0x0401fe34,
+ 0x0401fecb, 0x5c03e000, 0x04000999, 0x1c01f000,
+ 0x4947c857, 0x0401f9a0, 0x4df00000, 0x4d3c0000,
+ 0x853e7d00, 0x0401fe75, 0x0401fefc, 0x5c027800,
+ 0x5c03e000, 0x0400098e, 0x1c01f000, 0x5c000000,
+ 0x4c000000, 0x4803c857, 0x4d340000, 0x4d2c0000,
+ 0x59326809, 0x59325808, 0x59300406, 0x82000c80,
+ 0x00000012, 0x02021800, 0x001005d8, 0x4933c857,
+ 0x4943c857, 0x493fc857, 0x4803c857, 0x0c01f804,
+ 0x5c025800, 0x5c026800, 0x1c01f000, 0x00106ae5,
+ 0x00106ae7, 0x00106af1, 0x00106b0b, 0x00106ae7,
+ 0x00106afb, 0x00106b23, 0x00106ae5, 0x00106ae5,
+ 0x00106b36, 0x00106b2d, 0x00106ae5, 0x00106ae5,
+ 0x00106ae5, 0x00106ae5, 0x00106ae5, 0x00106b3c,
+ 0x00106b3c, 0x0201f800, 0x001005d8, 0x0201f800,
+ 0x00109134, 0x02000800, 0x00102074, 0x0201f800,
+ 0x00109326, 0x0201f800, 0x0010801c, 0x0201f000,
+ 0x00107911, 0x812e59c0, 0x02020800, 0x001005d8,
+ 0x5930021d, 0x82000580, 0x00000003, 0x02000800,
+ 0x0010912a, 0x0201f000, 0x00107911, 0x0201f800,
+ 0x00109037, 0x02000000, 0x00107911, 0x592c1204,
+ 0x82081500, 0x000000ff, 0x82080580, 0x00000055,
+ 0x02020800, 0x001005d8, 0x49425a06, 0x0201f800,
+ 0x000202da, 0x0201f000, 0x00107911, 0x59300004,
+ 0x8400055c, 0x48026004, 0x59300007, 0x8c000500,
+ 0x02020800, 0x00100e99, 0x0201f800, 0x00109037,
+ 0x0400000d, 0x4a025a04, 0x00000103, 0x49425a06,
+ 0x497a5c09, 0x0201f800, 0x001091c6, 0x0201f800,
+ 0x0010a693, 0x0201f800, 0x000202da, 0x0201f800,
+ 0x0010912a, 0x0201f000, 0x00107911, 0x59300007,
+ 0x8c000500, 0x02020800, 0x00100e99, 0x0201f800,
+ 0x00109037, 0x02020800, 0x0010a3ef, 0x0201f000,
+ 0x00107911, 0x0201f800, 0x00109037, 0x04000005,
+ 0x49425a06, 0x497a5c09, 0x0201f800, 0x000202da,
+ 0x0201f000, 0x00107911, 0x0201f800, 0x00109037,
+ 0x02020800, 0x0010664f, 0x0201f000, 0x00107911,
+ 0x0201f800, 0x00109037, 0x04000004, 0x49425a06,
+ 0x0201f800, 0x000202da, 0x59325817, 0x0201f800,
+ 0x001007fd, 0x0201f000, 0x00107911, 0x598c000d,
+ 0x81300580, 0x04000003, 0x497a6007, 0x1c01f000,
+ 0x59c40004, 0x82000500, 0x0000000c, 0x04000005,
+ 0x4a038804, 0x0000000c, 0x497b2807, 0x0401f00a,
+ 0x0401facd, 0x59300403, 0x82000d80, 0x00000040,
+ 0x04000004, 0x82000580, 0x00000042, 0x04020002,
+ 0x497a6007, 0x0201f800, 0x001070b9, 0x80000580,
+ 0x1c01f000, 0x59300804, 0x8c040d3e, 0x04020004,
+ 0x82000540, 0x00000001, 0x0401f005, 0x4933c857,
+ 0x84040d3e, 0x48066004, 0x80000580, 0x1c01f000,
+ 0x59300804, 0x8c040d20, 0x04020004, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4933c857, 0x4d380000,
+ 0x59300804, 0x84040d20, 0x48066004, 0x42027000,
+ 0x00000049, 0x59300203, 0x82000580, 0x00000003,
+ 0x04000003, 0x42027000, 0x00000013, 0x0201f800,
+ 0x000207a1, 0x80000580, 0x5c027000, 0x1c01f000,
+ 0x59300017, 0x81480580, 0x04020003, 0x59300018,
+ 0x814c0580, 0x1c01f000, 0x4d2c0000, 0x4d300000,
+ 0x0401f8c9, 0x4df00000, 0x0201f800, 0x00106062,
+ 0x59900001, 0x82000500, 0x00000003, 0x0c01f001,
+ 0x00106bba, 0x00106b9a, 0x00106b98, 0x00106b98,
+ 0x0201f800, 0x001005d8, 0x59926004, 0x0401f88e,
+ 0x813261c0, 0x0400001d, 0x59300004, 0x8c000516,
+ 0x04000004, 0x59325808, 0x497a5808, 0x497a5809,
+ 0x0401f88e, 0x59300001, 0x800001c0, 0x0400000e,
+ 0x497a6001, 0x42003000, 0x0000bf2e, 0x58180801,
+ 0x800409c0, 0x04020004, 0x48003001, 0x48003000,
+ 0x0401f00a, 0x58180800, 0x48000800, 0x48003000,
+ 0x0401f006, 0x59300809, 0x800409c0, 0x02000800,
+ 0x001005d8, 0x4978080c, 0x5c03e000, 0x04000890,
+ 0x5c026000, 0x5c025800, 0x1c01f000, 0x4d300000,
+ 0x497b2807, 0x0401f894, 0x4df00000, 0x598c0000,
+ 0x82000500, 0x00000007, 0x4803c857, 0x0c01f001,
+ 0x00106bef, 0x00106bd2, 0x00106bdb, 0x00106bdf,
+ 0x00106bea, 0x00106bef, 0x00106bd0, 0x00106bd0,
+ 0x0201f800, 0x001005d8, 0x598c000d, 0x80026540,
+ 0x04000004, 0x0401f81e, 0x02020800, 0x001005d8,
+ 0x0201f800, 0x001070b9, 0x0401f015, 0x0401f827,
+ 0x0201f800, 0x001070b9, 0x0401f011, 0x598c000d,
+ 0x80026540, 0x0400000e, 0x0401f838, 0x04000004,
+ 0x0401f80f, 0x04000002, 0x0401f81c, 0x0201f800,
+ 0x001070b9, 0x0401f006, 0x0401f830, 0x02020800,
+ 0x001005d8, 0x0201f800, 0x001070b9, 0x5c03e000,
+ 0x0400085b, 0x5c026000, 0x1c01f000, 0x598c0009,
+ 0x81300580, 0x0402000c, 0x0401f84e, 0x0401f83b,
+ 0x59300000, 0x800001c0, 0x04000004, 0x48031809,
+ 0x497a6000, 0x0401f003, 0x497b1809, 0x497b1808,
+ 0x80000580, 0x1c01f000, 0x4d2c0000, 0x59300406,
+ 0x82000580, 0x00000003, 0x04020012, 0x598c000b,
+ 0x81300580, 0x0402000f, 0x0401f83a, 0x59325808,
+ 0x497a5808, 0x497a5809, 0x0401f824, 0x59300000,
+ 0x800001c0, 0x04000004, 0x4803180b, 0x497a6000,
+ 0x0401f003, 0x497b180a, 0x497b180b, 0x80000580,
+ 0x5c025800, 0x1c01f000, 0x598c0005, 0x81300580,
+ 0x0402000c, 0x0401f827, 0x0401f814, 0x59300000,
+ 0x800001c0, 0x04000004, 0x48031805, 0x497a6000,
+ 0x0401f003, 0x497b1805, 0x497b1804, 0x80000580,
+ 0x1c01f000, 0x4a032001, 0x00000000, 0x497b2004,
+ 0x497b2005, 0x59900006, 0x82000500, 0x0000ffff,
+ 0x48032006, 0x1c01f000, 0x4c040000, 0x59300004,
+ 0x82000500, 0x7ffeffff, 0x48026004, 0x59bc00e4,
+ 0x8c000514, 0x04000009, 0x42000800, 0x0000bf00,
+ 0x58040012, 0x81300580, 0x04020004, 0x49780812,
+ 0x4a0378e4, 0x00000800, 0x5c000800, 0x1c01f000,
+ 0x4803c856, 0x598c000c, 0x80000540, 0x04000003,
+ 0x80000040, 0x4803180c, 0x1c01f000, 0x59bc00ea,
+ 0x82000500, 0x00000007, 0x82000580, 0x00000003,
+ 0x04020004, 0x4803c856, 0x4a0378e8, 0x00000001,
+ 0x1c01f000, 0x59bc00ea, 0x82000500, 0x00000007,
+ 0x82000580, 0x00000001, 0x04020011, 0x4803c856,
+ 0x42000800, 0x00000000, 0x0401f80e, 0x42000800,
+ 0x00001000, 0x59bc00ea, 0x82000500, 0x00000007,
+ 0x82000580, 0x00000003, 0x04000005, 0x80040840,
+ 0x040207f9, 0x0201f800, 0x001005d8, 0x1c01f000,
+ 0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
+ 0x00000001, 0x02020800, 0x001005d8, 0x59bc00ea,
+ 0x8c000516, 0x040207fe, 0x480778e1, 0x1c01f000,
+ 0x59bc00ea, 0x8c000516, 0x040207fe, 0x480778e1,
+ 0x59bc00ea, 0x8c000516, 0x040207fe, 0x480b78e1,
+ 0x1c01f000, 0x82000d00, 0x80000018, 0x02020800,
+ 0x001005d0, 0x0201f800, 0x001005d8, 0x00106c97,
+ 0x00106d3b, 0x00106d55, 0x00106c97, 0x00106c99,
+ 0x00106cba, 0x00106cd9, 0x00106d0d, 0x00106c97,
+ 0x00106d39, 0x00106c97, 0x00106c97, 0x00106c97,
+ 0x00106c97, 0x00106c97, 0x00106c97, 0x0201f800,
+ 0x001005d8, 0x4d300000, 0x4d900000, 0x4dd00000,
+ 0x4da40000, 0x4d140000, 0x0201f800, 0x001070d8,
+ 0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0,
+ 0x59300004, 0x8c000520, 0x04000011, 0x82000500,
+ 0xfffefeff, 0x48026004, 0x4a026203, 0x00000003,
+ 0x0401ffa9, 0x0201f800, 0x00100fd0, 0x5c022800,
+ 0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000,
+ 0x4a0378e4, 0x00000008, 0x0401f795, 0x84000510,
+ 0x48026004, 0x0401f7f6, 0x4d300000, 0x4d900000,
+ 0x4dd00000, 0x4da40000, 0x4d140000, 0x0201f800,
+ 0x001070d8, 0x59bc00ea, 0x8c000510, 0x040007fe,
+ 0x59be60e0, 0x59300004, 0x8c000520, 0x0400000f,
+ 0x82000500, 0xfffefeff, 0x48026004, 0x0401ff8a,
+ 0x0201f800, 0x0010100e, 0x5c022800, 0x5c034800,
+ 0x5c03a000, 0x5c032000, 0x5c026000, 0x4a0378e4,
+ 0x00000008, 0x0401f776, 0x84000510, 0x48026004,
+ 0x0401f7f6, 0x4d300000, 0x4d2c0000, 0x4d340000,
+ 0x4da40000, 0x4cd00000, 0x59bc00ea, 0x8c000510,
+ 0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800,
+ 0x001005d8, 0x59300004, 0x8c000520, 0x0400001d,
+ 0x82000500, 0xfffefeff, 0x48026004, 0x59326809,
+ 0x42034800, 0x0010b544, 0x04011000, 0x4a03c840,
+ 0x0010b54b, 0x4a03c842, 0x00000012, 0x04011000,
+ 0x4a03c840, 0x0010b55d, 0x4a03c842, 0x000000ff,
+ 0x04011000, 0x4a03c840, 0x0010b65c, 0x4a03c842,
+ 0x000000ff, 0x0401fbf2, 0x5c01a000, 0x5c034800,
+ 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000,
+ 0x84000510, 0x48026004, 0x5c01a000, 0x5c034800,
+ 0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000,
+ 0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000,
+ 0x4cd00000, 0x4d900000, 0x4dd00000, 0x4da40000,
+ 0x4d140000, 0x0401fbc3, 0x59bc00ea, 0x8c000510,
+ 0x040007fe, 0x59be60e0, 0x813261c0, 0x02000800,
+ 0x001005d8, 0x59300004, 0x8c000520, 0x0400000f,
+ 0x82000500, 0xfffefeff, 0x48026004, 0x0201f800,
+ 0x0010783a, 0x5c022800, 0x5c034800, 0x5c03a000,
+ 0x5c032000, 0x5c01a000, 0x5c026800, 0x5c025800,
+ 0x5c026000, 0x1c01f000, 0x84000510, 0x48026004,
+ 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+ 0x5c01a000, 0x5c026800, 0x5c025800, 0x5c026000,
+ 0x1c01f000, 0x0201f800, 0x001005d8, 0x4d300000,
+ 0x4d380000, 0x42000000, 0x0010b8c4, 0x0201f800,
+ 0x0010aa47, 0x0401ff14, 0x598e600d, 0x59c40004,
+ 0x8c000506, 0x04000004, 0x0401f8db, 0x4a038804,
+ 0x00000008, 0x813261c0, 0x04000006, 0x0401fb87,
+ 0x42027000, 0x00000014, 0x0201f800, 0x000207a1,
+ 0x4a0378e4, 0x00000002, 0x5c027000, 0x5c026000,
+ 0x0401f6f7, 0x4d180000, 0x4d300000, 0x4d380000,
+ 0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
+ 0x0401fef9, 0x417a3000, 0x59c40804, 0x83180400,
+ 0x0010709f, 0x50000000, 0x80040500, 0x0400001b,
+ 0x42000000, 0x0010b8c5, 0x0201f800, 0x0010aa47,
+ 0x0401fb70, 0x59926004, 0x0401f859, 0x83180400,
+ 0x0010709f, 0x50000000, 0x48038804, 0x813261c0,
+ 0x0400000a, 0x59300004, 0x8c00050c, 0x04020003,
+ 0x4a026203, 0x00000003, 0x42027000, 0x0000004a,
+ 0x0201f800, 0x000207a1, 0x59c40004, 0x82000500,
+ 0x00f80000, 0x04000005, 0x811a3000, 0x83180480,
+ 0x00000005, 0x040017dd, 0x4a0378e4, 0x00000008,
+ 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+ 0x5c027000, 0x5c026000, 0x5c023000, 0x0401f6c0,
+ 0x4d2c0000, 0x4d340000, 0x59326809, 0x598c0800,
+ 0x82040580, 0x00000004, 0x04020004, 0x838c1400,
+ 0x00000005, 0x0401f00c, 0x82040580, 0x00000001,
+ 0x04020004, 0x838c1400, 0x00000009, 0x0401f006,
+ 0x82040580, 0x00000002, 0x04020022, 0x838c1400,
+ 0x0000000b, 0x41306800, 0x58340000, 0x80007d40,
+ 0x0400001c, 0x583c0009, 0x81340580, 0x04020006,
+ 0x403c6800, 0x583c0000, 0x80007d40, 0x040207fa,
+ 0x0401f014, 0x4933c857, 0x483fc857, 0x583c0000,
+ 0x48006800, 0x49307800, 0x443c1000, 0x80000580,
+ 0x4803180d, 0x4803180f, 0x598c0000, 0x82000580,
+ 0x00000003, 0x04000003, 0x4a031800, 0x00000000,
+ 0x80000580, 0x5c026800, 0x5c025800, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x0401f7fb, 0x491bc857,
+ 0x59c80840, 0x82040540, 0x00000010, 0x48039040,
+ 0x59c41008, 0x82080500, 0xffffff7f, 0x48038808,
+ 0x4c040000, 0x4c080000, 0x0401fabb, 0x04020007,
+ 0x0401fabf, 0x04000022, 0x48038804, 0x0201f800,
+ 0x0010107a, 0x0401f042, 0x4a038803, 0x00000008,
+ 0x59c40003, 0x82000500, 0x00000003, 0x040007fd,
+ 0x8c000502, 0x04020007, 0x0401fab1, 0x04000014,
+ 0x48038804, 0x0201f800, 0x0010107a, 0x0401f034,
+ 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
+ 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
+ 0xc0000000, 0x04000006, 0x59c400a3, 0x84000540,
+ 0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800,
+ 0x0010101d, 0x4a03a005, 0x30000000, 0x59d00006,
+ 0x4a03a005, 0x30000000, 0x59900006, 0x82000500,
+ 0xffff0000, 0x48032006, 0x59d00005, 0x8c000504,
+ 0x040207fe, 0x42000800, 0x00007600, 0x83180540,
+ 0x60000000, 0x480008a1, 0x811800dc, 0x59c80840,
+ 0x80040540, 0x48039040, 0x82000540, 0x00003000,
+ 0x48039040, 0x59c80040, 0x82000500, 0x00003000,
+ 0x040207fd, 0x0201f800, 0x00101068, 0x83180400,
+ 0x0010709f, 0x50000000, 0x48038804, 0x80000580,
+ 0x4df00000, 0x0201f800, 0x00106062, 0x5c03e000,
+ 0x5c001000, 0x5c000800, 0x480b8808, 0x48079040,
+ 0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540,
+ 0x00000010, 0x48039040, 0x59c41008, 0x82080500,
+ 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
+ 0x59c40004, 0x82000500, 0x00000003, 0x04020010,
+ 0x59c40004, 0x82000500, 0x0000000c, 0x04000005,
+ 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f025,
+ 0x59c80040, 0x8400056e, 0x48039040, 0x59c80040,
+ 0x8c00052e, 0x040207fe, 0x0401f01e, 0x4a038803,
+ 0x00000008, 0x59c40003, 0x82000500, 0x00000003,
+ 0x040007fd, 0x8c000502, 0x04020006, 0x59c40004,
+ 0x4a038804, 0x0000000c, 0x8c000504, 0x0401f011,
+ 0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
+ 0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
+ 0xc0000000, 0x04000007, 0x59c400a3, 0x84000540,
+ 0x480388a3, 0x4a038805, 0xc0000000, 0x80000580,
+ 0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808,
+ 0x48079040, 0x1c01f000, 0x4933c857, 0x4d900000,
+ 0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdee,
+ 0x4df00000, 0x0401fa6f, 0x59900004, 0x800001c0,
+ 0x04000011, 0x81300580, 0x0402000f, 0x59300004,
+ 0x84000520, 0x48026004, 0x0401ff51, 0x04020009,
+ 0x5c03e000, 0x04000dd6, 0x80000580, 0x5c022800,
+ 0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000,
+ 0x0401fd0e, 0x42027000, 0x00000049, 0x59300004,
+ 0x84000520, 0x48026004, 0x8c00050c, 0x02020800,
+ 0x000207a1, 0x5c03e000, 0x04000dc5, 0x82000540,
+ 0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000,
+ 0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fdc6,
+ 0x4df00000, 0x598c000d, 0x80026540, 0x04000012,
+ 0x59300004, 0x84000520, 0x48026004, 0x0401ff8a,
+ 0x04000017, 0x0401fd26, 0x42027000, 0x00000013,
+ 0x59300004, 0x8c00050c, 0x02020800, 0x000207a1,
+ 0x5c03e000, 0x04000daa, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9,
+ 0x836c1580, 0x00000004, 0x040007f6, 0x42001000,
+ 0x00104148, 0x0201f800, 0x00105f90, 0x5c03e000,
+ 0x04000d9b, 0x80000580, 0x1c01f000, 0x4d300000,
+ 0x4d180000, 0x4d3c0000, 0x0401fd9f, 0x4df00000,
+ 0x4a0378e4, 0x0000000f, 0x0401f9ff, 0x417a3000,
+ 0x59926004, 0x813261c0, 0x04000010, 0x417a7800,
+ 0x0201f800, 0x001048d9, 0x0400000a, 0x59300c06,
+ 0x82040580, 0x00000003, 0x04000004, 0x82040580,
+ 0x00000006, 0x04020003, 0x42027800, 0x00000002,
+ 0x0201f800, 0x00108be3, 0x811a3000, 0x83180480,
+ 0x00000005, 0x040017eb, 0x42000800, 0x00000040,
+ 0x0201f800, 0x00101345, 0x4a0378e4, 0x0000000a,
+ 0x5c03e000, 0x04000d72, 0x5c027800, 0x5c023000,
+ 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+ 0x0401fd75, 0x4df00000, 0x59c80840, 0x82040540,
+ 0x00000010, 0x48039040, 0x59c41008, 0x82080500,
+ 0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
+ 0x42001000, 0x00000003, 0x0401f9c2, 0x598e600d,
+ 0x813261c0, 0x04020f9d, 0x040009c7, 0x497b2807,
+ 0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808,
+ 0x84040d74, 0x48079040, 0x5c03e000, 0x04000d50,
+ 0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000,
+ 0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000,
+ 0x4d140000, 0x59c41004, 0x480bc857, 0x82080500,
+ 0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000,
+ 0x0201f800, 0x00106062, 0x5c001000, 0x82080500,
+ 0x00000210, 0x04020004, 0x811a3000, 0x80081102,
+ 0x0401f7f7, 0x0401f9c3, 0x59926004, 0x4933c857,
+ 0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a,
+ 0x02000800, 0x001005d8, 0x0401fea5, 0x04000009,
+ 0x0401fc6a, 0x42027000, 0x00000049, 0x59300004,
+ 0x8c00050c, 0x02020800, 0x000207a1, 0x0401f007,
+ 0x42027000, 0x0000004a, 0x4a026203, 0x00000003,
+ 0x0201f800, 0x000207a1, 0x5c022800, 0x5c034800,
+ 0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000,
+ 0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000,
+ 0x4d900000, 0x0401fd1c, 0x42001000, 0x00000000,
+ 0x598c0000, 0x82000580, 0x00000005, 0x04000971,
+ 0x417a3000, 0x811b20c8, 0x83932400, 0x0000bf32,
+ 0x59900001, 0x82000580, 0x00000001, 0x0402000d,
+ 0x42000800, 0x000007d0, 0x59926004, 0x59300011,
+ 0x82000500, 0xfff00000, 0x80000540, 0x04000003,
+ 0x42000800, 0x00001b58, 0x0201f800, 0x00106054,
+ 0x811a3000, 0x83180480, 0x00000005, 0x040017ea,
+ 0x59c81040, 0x84081534, 0x480b9040, 0x0401fcf0,
+ 0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000,
+ 0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000,
+ 0x4d140000, 0x4d380000, 0x0401fcef, 0x4df00000,
+ 0x59300004, 0x8c00053e, 0x04020007, 0x8c000520,
+ 0x04000025, 0x0201f800, 0x00106b6c, 0x04000022,
+ 0x0401f02a, 0x598c000d, 0x81300580, 0x04000011,
+ 0x0201f800, 0x00108cd6, 0x04020024, 0x0401f918,
+ 0x04000022, 0x48038804, 0x0401f95e, 0x0201f800,
+ 0x0010107a, 0x0401fc0d, 0x42027000, 0x00000049,
+ 0x59300004, 0x8c00050c, 0x0402000d, 0x0401f00e,
+ 0x59c40004, 0x8c000504, 0x04000014, 0x4a038804,
+ 0x00000004, 0x0401fc36, 0x42027000, 0x00000013,
+ 0x59300004, 0x8c00050c, 0x04000003, 0x0201f800,
+ 0x000207a1, 0x5c03e000, 0x04000cb9, 0x5c027000,
+ 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+ 0x80000580, 0x1c01f000, 0x5c03e000, 0x04000cb0,
+ 0x5c027000, 0x5c022800, 0x5c034800, 0x5c03a000,
+ 0x5c032000, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x497b2807, 0x0401fcb0, 0x59c400af, 0x800001c0,
+ 0x04020004, 0x0401fca2, 0x0201f000, 0x001014fb,
+ 0x598c000f, 0x82001480, 0x00000002, 0x04021007,
+ 0x80000000, 0x4803180f, 0x80000580, 0x0201f800,
+ 0x0010604d, 0x0400000e, 0x0401fed8, 0x0402000c,
+ 0x0401fdd4, 0x0400000a, 0x0201f800, 0x0010a9c7,
+ 0x0401f916, 0x4d380000, 0x42027000, 0x00000014,
+ 0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc88,
+ 0x0201f000, 0x001014fb, 0x4d900000, 0x4dd00000,
+ 0x4da40000, 0x4d140000, 0x4d300000, 0x0201f800,
+ 0x00106062, 0x0401fc88, 0x59c400af, 0x800001c0,
+ 0x04000027, 0x0401f907, 0x59926004, 0x4933c857,
+ 0x59300004, 0x8c000516, 0x0400000b, 0x0401fe8b,
+ 0x0402001f, 0x0201f800, 0x00106b8a, 0x0401fc70,
+ 0x42000800, 0x80000804, 0x0201f800, 0x00106721,
+ 0x0401f017, 0x42001800, 0x00007530, 0x0401f8c1,
+ 0x04020004, 0x0201f800, 0x00106052, 0x0401f010,
+ 0x0401fe7a, 0x0402000e, 0x0201f800, 0x0010a9c7,
+ 0x59300004, 0x8c00050c, 0x04020003, 0x4a026203,
+ 0x00000003, 0x4d380000, 0x42027000, 0x0000004a,
+ 0x0201f800, 0x000207a1, 0x5c027000, 0x0401fc54,
+ 0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000,
+ 0x5c032000, 0x0201f000, 0x001014fb, 0x4d900000,
+ 0x4dd00000, 0x4da40000, 0x4d140000, 0x4d300000,
+ 0x4d2c0000, 0x0401fc50, 0x0401f8d2, 0x59926004,
+ 0x4933c857, 0x0401f880, 0x04000016, 0x0201f800,
+ 0x00106062, 0x813261c0, 0x04000034, 0x59325808,
+ 0x812e59c0, 0x02000800, 0x001005d8, 0x0201f800,
+ 0x0010513b, 0x0402001d, 0x592c0208, 0x84000550,
+ 0x48025a08, 0x0201f800, 0x00105258, 0x04020027,
+ 0x592c0208, 0x84000510, 0x48025a08, 0x0401f023,
+ 0x0201f800, 0x00106052, 0x0401f020, 0x0201f800,
+ 0x0010a9c7, 0x0401fd9e, 0x592c0208, 0x84000550,
+ 0x48025a08, 0x4d380000, 0x42027000, 0x0000004a,
+ 0x4a026203, 0x00000003, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x0401f011, 0x59900006, 0x82000500,
+ 0xffff0000, 0x040207ee, 0x59c408af, 0x82040480,
+ 0x000003e8, 0x040217ea, 0x59900006, 0x82000400,
+ 0x00010000, 0x48032006, 0x0201f800, 0x00106052,
+ 0x0201f800, 0x0010411d, 0x5c025800, 0x5c026000,
+ 0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
+ 0x0401f403, 0x4d300000, 0x4d2c0000, 0x0401fc0a,
+ 0x598e600d, 0x4933c857, 0x59c41004, 0x8c081500,
+ 0x04000007, 0x0201f800, 0x0010513b, 0x04020007,
+ 0x0201f800, 0x00105258, 0x0402002f, 0x0201f800,
+ 0x0010604d, 0x0401f02c, 0x598c000f, 0x80000540,
+ 0x04020011, 0x59c408af, 0x82040480, 0x000003e8,
+ 0x0402100d, 0x598c080f, 0x80040800, 0x4807180f,
+ 0x0201f800, 0x0010604d, 0x42000000, 0x0010b852,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010411d,
+ 0x0401f019, 0x0401fdb4, 0x813261c0, 0x04020003,
+ 0x0401f849, 0x0401f014, 0x0201f800, 0x0010a9c7,
+ 0x59300406, 0x82000580, 0x00000003, 0x04020007,
+ 0x59325808, 0x812e59c0, 0x04000004, 0x592c0208,
+ 0x84000550, 0x48025a08, 0x0401f854, 0x4d380000,
+ 0x42027000, 0x00000014, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x5c025800, 0x5c026000, 0x0201f000,
+ 0x00106c4b, 0x59c40804, 0x83180400, 0x00107095,
+ 0x50000000, 0x80040500, 0x1c01f000, 0x59c40804,
+ 0x83180400, 0x0010709a, 0x50000000, 0x80040500,
+ 0x1c01f000, 0x00000210, 0x00000420, 0x00000840,
+ 0x00001080, 0x00002100, 0x00004000, 0x00008000,
+ 0x00010000, 0x00020000, 0x00040000, 0x00080000,
+ 0x00100000, 0x00200000, 0x00400000, 0x00800000,
+ 0x59900806, 0x80040120, 0x800c0480, 0x04021004,
+ 0x82000540, 0x00000001, 0x0401f005, 0x82040c00,
+ 0x00010000, 0x48072006, 0x80000580, 0x1c01f000,
+ 0x480bc857, 0x0201f800, 0x00106c55, 0x4df00000,
+ 0x480b1800, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x1c01f000, 0x4803c856, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x497b180d, 0x497b1803, 0x497b180e,
+ 0x497b180f, 0x497b1810, 0x598c0000, 0x82000580,
+ 0x00000003, 0x04000009, 0x836c0580, 0x00000002,
+ 0x04020004, 0x4a031800, 0x00000005, 0x0401f003,
+ 0x4a031800, 0x00000000, 0x5c03e000, 0x02000800,
+ 0x00106c4b, 0x1c01f000, 0x59300004, 0x8c00050c,
+ 0x04020003, 0x4a026203, 0x00000001, 0x1c01f000,
+ 0x83180480, 0x00000005, 0x02021800, 0x001005d8,
+ 0x491bc857, 0x811b20c8, 0x83932400, 0x0000bf32,
+ 0x811ba0ca, 0x83d3a400, 0x00007600, 0x83180400,
+ 0x001070ea, 0x50034800, 0x811a28c2, 0x83162c00,
+ 0x00006100, 0x1c01f000, 0x0010b75b, 0x0010b772,
+ 0x0010b789, 0x0010b7a0, 0x0010b7b7, 0x4933c857,
+ 0x59300406, 0x82000c80, 0x00000012, 0x04021016,
+ 0x4803c857, 0x04011000, 0x0c01f001, 0x00107109,
+ 0x00107198, 0x001074d1, 0x00107556, 0x00107198,
+ 0x001074d1, 0x00107556, 0x00107109, 0x00107198,
+ 0x00107109, 0x00107109, 0x00107109, 0x00107109,
+ 0x00107109, 0x00107109, 0x00107109, 0x0010710f,
+ 0x0010710f, 0x0201f800, 0x00106c55, 0x0201f800,
+ 0x00106bbf, 0x0201f000, 0x00106c4b, 0x42001000,
+ 0x0010b7f6, 0x50081000, 0x4930100c, 0x58080002,
+ 0x82000580, 0x00000100, 0x04020032, 0x59325808,
+ 0x812e59c0, 0x02000800, 0x001005d8, 0x59326809,
+ 0x813669c0, 0x04000019, 0x592c040b, 0x82000500,
+ 0x0000e000, 0x04000003, 0x0401fba8, 0x0401f002,
+ 0x0401fb98, 0x42001000, 0x0010b7f6, 0x50081000,
+ 0x4930100b, 0x492c100a, 0x82d00400, 0x00000006,
+ 0x48001003, 0x592c000d, 0x80000104, 0x48001004,
+ 0x592c000e, 0x48001007, 0x592c000f, 0x48001008,
+ 0x0201f000, 0x00100858, 0x42026800, 0x0010be0d,
+ 0x592c080a, 0x48066802, 0x82040500, 0x00ffff00,
+ 0x04000007, 0x497a6a12, 0x59a81010, 0x82081500,
+ 0x00ffff00, 0x80080580, 0x040207dc, 0x82040d00,
+ 0x000000ff, 0x800408d0, 0x48066a12, 0x0401f7d7,
+ 0x1c01f000, 0x4d2c0000, 0x4d300000, 0x4c580000,
+ 0x4c540000, 0x4c500000, 0x5832580a, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x58300002, 0x4a006002,
+ 0x00000100, 0x82000580, 0x00000100, 0x0402001c,
+ 0x5830000b, 0x5832600c, 0x81300580, 0x04020010,
+ 0x0401f828, 0x04020010, 0x592c080d, 0x80040904,
+ 0x4004b000, 0x4200a000, 0x0010b54b, 0x4050a800,
+ 0x0201f800, 0x0010ab28, 0x42001000, 0x0000dc00,
+ 0x0201f800, 0x001078bc, 0x0401f003, 0x0401f819,
+ 0x04000fa3, 0x5c00a000, 0x5c00a800, 0x5c00b000,
+ 0x5c026000, 0x5c025800, 0x1c01f000, 0x5830000b,
+ 0x5832600c, 0x81300580, 0x040207f5, 0x0401f80d,
+ 0x040207f5, 0x0201f800, 0x001068d3, 0x02020800,
+ 0x001005d8, 0x4a025a06, 0x00000002, 0x0201f800,
+ 0x000202da, 0x0201f800, 0x00107911, 0x0401f7ea,
+ 0x0201f800, 0x00106c55, 0x4df00000, 0x598c000d,
+ 0x81300580, 0x04020009, 0x598c0005, 0x81300580,
+ 0x04020006, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x80000580, 0x1c01f000, 0x5c03e000, 0x02000800,
+ 0x00106c4b, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x59300403, 0x82000c80, 0x00000056, 0x02021800,
+ 0x001005d8, 0x4803c857, 0x0c01f001, 0x00107302,
+ 0x0010731d, 0x0010732e, 0x00107431, 0x001073f1,
+ 0x001073f5, 0x00107406, 0x0010741a, 0x0010740f,
+ 0x0010741a, 0x00107455, 0x0010741a, 0x00107497,
+ 0x0010741a, 0x001074a5, 0x0010741a, 0x0010740f,
+ 0x0010741a, 0x001074a9, 0x001071f5, 0x001071f5,
+ 0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5,
+ 0x001071f5, 0x001071f5, 0x001071f5, 0x001071f5,
+ 0x001071f5, 0x00107574, 0x00107593, 0x0010759d,
+ 0x001071f5, 0x001075b3, 0x00107406, 0x001071f5,
+ 0x00107406, 0x0010741a, 0x001071f5, 0x0010732e,
+ 0x00107431, 0x001071f5, 0x00107603, 0x0010741a,
+ 0x001071f5, 0x00107613, 0x0010741a, 0x001071f5,
+ 0x0010740f, 0x001072f3, 0x001071f7, 0x001071f5,
+ 0x0010762a, 0x0010765d, 0x001076d7, 0x001071f5,
+ 0x001076e7, 0x00107404, 0x001076da, 0x001071f5,
+ 0x001075bf, 0x00107700, 0x001071f5, 0x00107735,
+ 0x00107788, 0x001071f5, 0x0010720c, 0x00107265,
+ 0x00107272, 0x001071f5, 0x00107406, 0x001071f5,
+ 0x001072b9, 0x001072c4, 0x001071f5, 0x001071f5,
+ 0x00107220, 0x00107245, 0x001077c7, 0x00107808,
+ 0x0010782e, 0x001071f5, 0x001071f5, 0x001071f5,
+ 0x001077fc, 0x0201f800, 0x001005d8, 0x0401fac5,
+ 0x59325808, 0x592c0009, 0x4801a006, 0x592c000a,
+ 0x4801a007, 0x592c000b, 0x4801a008, 0x592c000c,
+ 0x4801a009, 0x592c000d, 0x4801a00a, 0x4979a00b,
+ 0x592c0809, 0x82040d00, 0x00000fff, 0x80040904,
+ 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+ 0x4a026202, 0x0000ffff, 0x0401faae, 0x4d2c0000,
+ 0x4a01a006, 0x05000000, 0x59325808, 0x592c0009,
+ 0x4801a007, 0x592c000a, 0x4801a008, 0x592c000b,
+ 0x4801a009, 0x42000800, 0x00000004, 0x42001000,
+ 0x0000dc00, 0x5c025800, 0x0201f000, 0x001078bc,
+ 0x4c580000, 0x4c500000, 0x4c540000, 0x4d2c0000,
+ 0x0401fa98, 0x59325808, 0x5930040b, 0x800000c2,
+ 0x4200a800, 0x0010b54b, 0x592cb205, 0x832ca400,
+ 0x00000006, 0x0201f800, 0x0010ab17, 0x40580000,
+ 0x8054ac00, 0x592c0001, 0x80000540, 0x04000003,
+ 0x40025800, 0x0401f7f5, 0x4200a000, 0x0010b54b,
+ 0x4050a800, 0x5930b40b, 0x0201f800, 0x0010ab28,
+ 0x59300c0b, 0x42001000, 0x0000dc00, 0x5c025800,
+ 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000,
+ 0x001078bc, 0x4c580000, 0x4c500000, 0x4c540000,
+ 0x4d2c0000, 0x42034800, 0x0010b544, 0x0401fa7f,
+ 0x59325808, 0x4a025805, 0x02000000, 0x592c0802,
+ 0x82d0ac00, 0x00000006, 0x592cb011, 0x832ca400,
+ 0x00000005, 0x0201f800, 0x0010ab17, 0x40580000,
+ 0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40,
+ 0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800,
+ 0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000,
+ 0x001078bc, 0x0401fa57, 0x4a01a006, 0x78000000,
+ 0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207,
+ 0x42000800, 0x00000002, 0x42001000, 0x0000dc00,
+ 0x0201f000, 0x001078bc, 0x4c580000, 0x4c540000,
+ 0x4c500000, 0x0401fa55, 0x4a01a006, 0x02000000,
+ 0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009,
+ 0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b,
+ 0x5930001c, 0x82000d80, 0x0000e000, 0x04000016,
+ 0x82000d80, 0x0000df00, 0x04000006, 0x4a01a407,
+ 0x00000010, 0x42000800, 0x00000006, 0x0401f027,
+ 0x4a03c840, 0x0010b4eb, 0x4a03c842, 0x0000000d,
+ 0x42001800, 0x0010b4eb, 0x0201f800, 0x001007af,
+ 0x42000000, 0x0000df00, 0x4200a000, 0x0010b4eb,
+ 0x0401f00d, 0x4a03c840, 0x0010b4f8, 0x4a03c842,
+ 0x0000000d, 0x42001800, 0x0010b4f8, 0x0201f800,
+ 0x001007af, 0x42000000, 0x0000e000, 0x4200a000,
+ 0x0010b4f8, 0x82000540, 0x00000010, 0x4801a407,
+ 0x4a01a207, 0x00000034, 0x4200b000, 0x0000000d,
+ 0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010ab17,
+ 0x42000800, 0x00000013, 0x42001000, 0x0000dc00,
+ 0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000,
+ 0x001078bc, 0x0401fa03, 0x4a01a006, 0x63000028,
+ 0x5930001c, 0x4801a007, 0x42000800, 0x00000002,
+ 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+ 0x0401fa06, 0x41780000, 0x41780800, 0x42002000,
+ 0x00080000, 0x0c01f81b, 0x80000000, 0x80040800,
+ 0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00,
+ 0x04020008, 0x42002000, 0x00050000, 0x0c01f811,
+ 0x80000000, 0x80040800, 0x82081400, 0x00000004,
+ 0x82080540, 0x02000000, 0x4801a006, 0x800408e0,
+ 0x5930001c, 0x80040540, 0x4801a007, 0x80080904,
+ 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+ 0x001072e9, 0x001072eb, 0x001072ed, 0x001072ef,
+ 0x001072f1, 0x4811a008, 0x1c01f000, 0x4811a009,
+ 0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b,
+ 0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009,
+ 0x0010be0d, 0x59a80010, 0x82000500, 0x000000ff,
+ 0x800000d0, 0x42026800, 0x0010be0d, 0x48026a12,
+ 0x0401fa3b, 0x41780800, 0x42001000, 0x00005c00,
+ 0x0201f000, 0x001078bc, 0x0401f9ba, 0x4a01a006,
+ 0x52000000, 0x4979a007, 0x599c0017, 0x8c000500,
+ 0x04000005, 0x599c0402, 0x0201f800, 0x001015da,
+ 0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003,
+ 0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001,
+ 0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800,
+ 0x00000007, 0x42001000, 0x0000dc00, 0x0201f000,
+ 0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f99d,
+ 0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007,
+ 0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009,
+ 0x42000800, 0x00000004, 0x42001000, 0x0000dc00,
+ 0x0201f000, 0x001078bc, 0x4a026202, 0x0000ffff,
+ 0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x001048f6, 0x5c027800, 0x4a01a006, 0x03000000,
+ 0x59340403, 0x82000580, 0x000007fe, 0x0402006e,
+ 0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800,
+ 0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a,
+ 0x59c41002, 0x8408150c, 0x480b8802, 0x59a80026,
+ 0x8c000508, 0x04000010, 0x59a8002a, 0x4801a007,
+ 0x59a8002b, 0x82000500, 0xffff2000, 0x599c0818,
+ 0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008,
+ 0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a,
+ 0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800,
+ 0x0010513b, 0x04020009, 0x497b8880, 0x82000500,
+ 0x0000ffff, 0x4c000000, 0x0201f800, 0x00101606,
+ 0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800,
+ 0x0010513b, 0x04020004, 0x82000500, 0x37ffffff,
+ 0x0401f003, 0x82000500, 0x3fffffff, 0x599c0818,
+ 0x8c040d16, 0x04000002, 0x8400056a, 0x59a80805,
+ 0x8c040d10, 0x04000019, 0x59300c03, 0x82041580,
+ 0x00000051, 0x04000015, 0x82041580, 0x00000031,
+ 0x04000012, 0x4c580000, 0x4c500000, 0x4c540000,
+ 0x4200b000, 0x00000004, 0x4200a000, 0x0010b8fa,
+ 0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800,
+ 0x0010ab17, 0x5c000000, 0x5c00a800, 0x5c00a000,
+ 0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009,
+ 0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b,
+ 0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d,
+ 0x4805a00e, 0x4979a00f, 0x4979a010, 0x4979a011,
+ 0x4979a012, 0x4979a013, 0x4979a014, 0x4979a015,
+ 0x4979a016, 0x59a8002e, 0x84000576, 0x4801a017,
+ 0x59a8002f, 0x4801a018, 0x4979a019, 0x4979a01a,
+ 0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d,
+ 0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880,
+ 0x80040d80, 0x04000007, 0x497b8880, 0x4c000000,
+ 0x0201f800, 0x00101606, 0x5c000000, 0x48038880,
+ 0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000,
+ 0x59a8c82b, 0x0201f800, 0x00109037, 0x0400000d,
+ 0x0201f800, 0x00109597, 0x0402000a, 0x592c0207,
+ 0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff,
+ 0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40,
+ 0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c,
+ 0x4801a009, 0x59a8002d, 0x4801a00a, 0x59a80002,
+ 0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000,
+ 0x59a80801, 0x4801a00d, 0x4805a00e, 0x4979a00f,
+ 0x4979a010, 0x4979a011, 0x4979a012, 0x4979a013,
+ 0x4979a014, 0x4979a015, 0x4979a016, 0x59a8002e,
+ 0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030,
+ 0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800,
+ 0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000,
+ 0x001078bc, 0x0401f8cb, 0x4a01a006, 0x50000000,
+ 0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010,
+ 0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008,
+ 0x4979a009, 0x4979a00a, 0x42000800, 0x00000005,
+ 0x42001000, 0x0000dc00, 0x0201f000, 0x001078bc,
+ 0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006,
+ 0x02000000, 0x42000800, 0x00000001, 0x42001000,
+ 0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f8bb,
+ 0x4a01a006, 0x02000000, 0x59300403, 0x82000580,
+ 0x00000031, 0x04020794, 0x81a40800, 0x4a000801,
+ 0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006,
+ 0x01000000, 0x5930041a, 0x80000540, 0x04000003,
+ 0x4801a407, 0x0401f003, 0x4a01a407, 0x00000003,
+ 0x5930021a, 0x80000540, 0x04000003, 0x4801a207,
+ 0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800,
+ 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
+ 0x001078bc, 0x4a026202, 0x0000ffff, 0x0401f889,
+ 0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014,
+ 0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000,
+ 0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003,
+ 0x82000540, 0x00000020, 0x8c040d08, 0x04000003,
+ 0x82000540, 0x00000010, 0x82000540, 0x00000002,
+ 0x5934080a, 0x8c040d14, 0x04000005, 0x82040d00,
+ 0x00000380, 0x80040540, 0x0401f006, 0x599c0818,
+ 0x8c040d18, 0x04000003, 0x82000540, 0x00000380,
+ 0x0401f03c, 0x0401f875, 0x4a01a406, 0x00000210,
+ 0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800,
+ 0x5934000a, 0x8c000516, 0x04000014, 0x59340c05,
+ 0x82040500, 0x00000030, 0x04000013, 0x59340a05,
+ 0x82040500, 0x0000c000, 0x04020009, 0x8c040d1a,
+ 0x04000004, 0x4a01a207, 0x00002100, 0x0401f00c,
+ 0x4a01a207, 0x00000100, 0x0401f009, 0x4a01a207,
+ 0x00000400, 0x0401f006, 0x4a01a207, 0x00000700,
+ 0x0401f003, 0x4a01a207, 0x00000800, 0x80000580,
+ 0x599c0817, 0x8c040d0a, 0x04020003, 0x82000540,
+ 0x00000020, 0x8c040d08, 0x04000003, 0x82000540,
+ 0x00000010, 0x82000540, 0x00000002, 0x59340a00,
+ 0x8c040d0e, 0x0400000b, 0x84000550, 0x599c1017,
+ 0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002,
+ 0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552,
+ 0x4801a20a, 0x42000800, 0x00000005, 0x42001000,
+ 0x0000dc00, 0x0201f000, 0x001078bc, 0x0401f833,
+ 0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000,
+ 0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800,
+ 0x00000005, 0x42001000, 0x0000dc00, 0x0201f000,
+ 0x001078bc, 0x0401f825, 0x4a01a006, 0x02000000,
+ 0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006,
+ 0x01000000, 0x4a01a407, 0x0000000b, 0x42000800,
+ 0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
+ 0x001078bc, 0x42005000, 0x32000000, 0x42006000,
+ 0x08290000, 0x41786800, 0x41787800, 0x0401f3df,
+ 0x42005000, 0x22000000, 0x42006000, 0x01290000,
+ 0x41786800, 0x41787800, 0x0401f3d8, 0x42005000,
+ 0x33000000, 0x42006000, 0x08980000, 0x41786800,
+ 0x41787800, 0x0401f3d1, 0x42005000, 0x23000000,
+ 0x42006000, 0x01980000, 0x41786800, 0x41787800,
+ 0x0401f3ca, 0x59300403, 0x82000c80, 0x00000085,
+ 0x02001800, 0x001005d8, 0x82000c80, 0x00000093,
+ 0x02021800, 0x001005d8, 0x82000480, 0x00000085,
+ 0x0c01f001, 0x001074eb, 0x001074ed, 0x001074fb,
+ 0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb,
+ 0x001074eb, 0x001074eb, 0x001074eb, 0x001074eb,
+ 0x001074eb, 0x001074eb, 0x00107506, 0x0201f800,
+ 0x001005d8, 0x4933c857, 0x0401f850, 0x59300402,
+ 0x4801a407, 0x5930001c, 0x4801a207, 0x4979a408,
+ 0x4a01a208, 0x0000ffff, 0x42000800, 0x00000003,
+ 0x42001000, 0x0000dc00, 0x0401f3c2, 0x4933c857,
+ 0x0401f84e, 0x4a01a406, 0x00000003, 0x4a01a206,
+ 0x00000300, 0x42000800, 0x00000001, 0x42001000,
+ 0x0000dc00, 0x0401f3b7, 0x4d2c0000, 0x59325808,
+ 0x4933c857, 0x492fc857, 0x812e59c0, 0x02000800,
+ 0x001005d8, 0x59340a12, 0x82040d00, 0x0000ff00,
+ 0x592c000a, 0x82000500, 0x000000ff, 0x900001c0,
+ 0x80040540, 0x82000540, 0x00000011, 0x44034800,
+ 0x81a5a000, 0x42001000, 0x00000009, 0x42000800,
+ 0x00000003, 0x592c0009, 0x82000500, 0xff000000,
+ 0x82001d80, 0x84000000, 0x04000009, 0x82001d80,
+ 0x85000000, 0x02020800, 0x001005d8, 0x42001000,
+ 0x00000007, 0x42000800, 0x00000001, 0x832c1c00,
+ 0x00000009, 0x500c0000, 0x4401a000, 0x800c1800,
+ 0x80d1a000, 0x80081040, 0x040207fb, 0x42001000,
+ 0x0000dc00, 0x5c025800, 0x0401f386, 0x42005000,
+ 0x81000000, 0x42006000, 0x00090000, 0x41786800,
+ 0x41787800, 0x0401f35d, 0x42005000, 0x84000000,
+ 0x42006000, 0x00990000, 0x59300406, 0x82000580,
+ 0x00000005, 0x04000002, 0x8430652e, 0x41786800,
+ 0x41787800, 0x0401f351, 0x42005000, 0x85000000,
+ 0x42006000, 0x00990000, 0x59300406, 0x82000580,
+ 0x00000005, 0x04000002, 0x8430652e, 0x41786800,
+ 0x41787800, 0x0401f345, 0x59300403, 0x82000c80,
+ 0x00000053, 0x02021800, 0x001005d8, 0x82000480,
+ 0x0000004b, 0x02001800, 0x001005d8, 0x59326809,
+ 0x59368c03, 0x4803c857, 0x0c01f001, 0x001075da,
+ 0x001075e2, 0x001075ea, 0x001075f2, 0x0010756b,
+ 0x0010756b, 0x0010756b, 0x001075d2, 0x0201f800,
+ 0x001005d8, 0x42005000, 0x06000000, 0x42006000,
+ 0x08290000, 0x41786800, 0x41787800, 0x0401f327,
+ 0x4933c857, 0x0401ff47, 0x4a01a006, 0x12000000,
+ 0x59300406, 0x82000580, 0x00000004, 0x04020003,
+ 0x59340002, 0x0401f002, 0x59a80010, 0x82000500,
+ 0x00ffffff, 0x4801a007, 0x59300419, 0x4801a408,
+ 0x59300219, 0x4801a208, 0x4979a009, 0x4979a00a,
+ 0x4979a00b, 0x4979a00c, 0x4979a00d, 0x4979a00e,
+ 0x4979a00f, 0x4979a010, 0x42000800, 0x0000000b,
+ 0x42001000, 0x0000dc00, 0x0401f32a, 0x0401ff29,
+ 0x4a01a006, 0x0f000000, 0x5930001c, 0x4801a007,
+ 0x42000800, 0x00000002, 0x42001000, 0x0000dc00,
+ 0x0401f320, 0x0401ff2d, 0x4a01a006, 0x02000000,
+ 0x59c40085, 0x48031004, 0x59880000, 0x4801a007,
+ 0x59880001, 0x4801a008, 0x59880002, 0x4801a009,
+ 0x59880003, 0x4801a00a, 0x59880004, 0x4801a00b,
+ 0x59880005, 0x4801a00c, 0x42000800, 0x00000007,
+ 0x42001000, 0x0000dc00, 0x0401f30a, 0x4a026202,
+ 0x0000ffff, 0x0401ff07, 0x4a01a006, 0x62000000,
+ 0x5930001c, 0x4801a007, 0x42000800, 0x00000002,
+ 0x42001000, 0x0000dc00, 0x0401f2fe, 0x0401fefd,
+ 0x59300808, 0x4c500000, 0x4c540000, 0x4c580000,
+ 0x8204a400, 0x0000000a, 0x5930b01c, 0x82d0ac00,
+ 0x00000006, 0x0201f800, 0x0010ab17, 0x5930081c,
+ 0x42001000, 0x0000dc00, 0x5c00b000, 0x5c00a800,
+ 0x5c00a000, 0x0401f2eb, 0x0401ff9b, 0x59300017,
+ 0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+ 0x00001000, 0x0401f020, 0x0401ff93, 0x59300017,
+ 0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+ 0x00004000, 0x0401f018, 0x0401ff8b, 0x59300017,
+ 0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+ 0x00002000, 0x0401f010, 0x0401ff83, 0x59300017,
+ 0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+ 0x00000400, 0x0401f008, 0x0401ff7b, 0x59300017,
+ 0x4801a006, 0x59300018, 0x4801a007, 0x4a01a008,
+ 0x00000200, 0x4979a009, 0x4979a00a, 0x4979a00b,
+ 0x4979a00c, 0x4979a00d, 0x42000800, 0x00000008,
+ 0x42001000, 0x0000dc00, 0x0401f2ba, 0x0401fec7,
+ 0x4a01a006, 0x02000014, 0x4979a407, 0x4979a207,
+ 0x59a8003a, 0x4801a008, 0x59a8003b, 0x4801a009,
+ 0x4a01a00a, 0x00047878, 0x42000800, 0x00000005,
+ 0x42001000, 0x0000dc00, 0x0401f2aa, 0x0401feb7,
+ 0x4a01a006, 0x02140018, 0x4a01a407, 0x00000800,
+ 0x5930001c, 0x82000d00, 0xff000000, 0x900409c0,
+ 0x4805a207, 0x82000500, 0x00ffffff, 0x4801a00a,
+ 0x4979a408, 0x4979a208, 0x4979a409, 0x4979a209,
+ 0x4979a00b, 0x42000800, 0x00000006, 0x42001000,
+ 0x0000dc00, 0x0401f293, 0x4803c856, 0x4d380000,
+ 0x4d1c0000, 0x42027000, 0x00000035, 0x0201f800,
+ 0x001093ba, 0x0402001e, 0x0401fe8a, 0x4a01a006,
+ 0x13000000, 0x5932381e, 0x591c0019, 0x4801a005,
+ 0x591c0406, 0x82000580, 0x00000003, 0x04000007,
+ 0x59300809, 0x58040002, 0x82000500, 0x00ffffff,
+ 0x4801a007, 0x0401f003, 0x59a80010, 0x4801a007,
+ 0x59300419, 0x4801a408, 0x59300219, 0x4801a208,
+ 0x42000800, 0x00000003, 0x42001000, 0x0000dc00,
+ 0x5c023800, 0x5c027000, 0x0401f26e, 0x0201f800,
+ 0x00106c55, 0x598c000d, 0x81300580, 0x02020800,
+ 0x001005d8, 0x0201f800, 0x00106bbf, 0x0201f800,
+ 0x0002077d, 0x5c023800, 0x5c027000, 0x0201f000,
+ 0x00106c4b, 0x4803c856, 0x4d2c0000, 0x4d1c0000,
+ 0x5932381e, 0x811e39c0, 0x02000800, 0x001005d8,
+ 0x591c0c06, 0x82040580, 0x00000006, 0x0400000d,
+ 0x82040580, 0x00000003, 0x04000036, 0x4a026403,
+ 0x00000037, 0x4a02641a, 0x00000003, 0x4a02621a,
+ 0x00001700, 0x5c023800, 0x5c025800, 0x0401f064,
+ 0x0401f84b, 0x42001000, 0x40000000, 0x591c0203,
+ 0x591c0804, 0x8c040d3e, 0x04020023, 0x82000c80,
+ 0x0000000e, 0x0c001003, 0x0201f800, 0x001005d8,
+ 0x00107691, 0x0010769d, 0x00107693, 0x0010769d,
+ 0x00107699, 0x00107691, 0x00107691, 0x0010769d,
+ 0x0010769d, 0x00107691, 0x00107691, 0x00107691,
+ 0x00107691, 0x00107691, 0x0010769d, 0x00107691,
+ 0x0010769d, 0x0201f800, 0x001005d8, 0x591c0414,
+ 0x4803c857, 0x8c000518, 0x04000003, 0x8c000512,
+ 0x04000003, 0x80001580, 0x0401f003, 0x42001000,
+ 0x20000000, 0x591c0015, 0x4801a00a, 0x0401f018,
+ 0x0401f81f, 0x591e5808, 0x812e59c0, 0x02000800,
+ 0x001005d8, 0x592c100f, 0x591c0011, 0x80080480,
+ 0x4801a00a, 0x591c0203, 0x591c0804, 0x8c040d3e,
+ 0x04020007, 0x82000d80, 0x00000002, 0x04000007,
+ 0x82000d80, 0x00000004, 0x04000004, 0x42001000,
+ 0x40000000, 0x0401f002, 0x80001580, 0x4809a00b,
+ 0x42000800, 0x00000006, 0x42001000, 0x0000dc00,
+ 0x5c023800, 0x5c025800, 0x0401f1fe, 0x4803c856,
+ 0x0401fe0a, 0x4a01a006, 0x02000000, 0x59300c19,
+ 0x4805a407, 0x59300a19, 0x4805a207, 0x59a81010,
+ 0x59300809, 0x58041802, 0x820c1d00, 0x00ffffff,
+ 0x5930081e, 0x58040406, 0x82000580, 0x00000003,
+ 0x04020004, 0x4809a008, 0x480da009, 0x0401f003,
+ 0x480da008, 0x4809a009, 0x1c01f000, 0x4803c856,
+ 0x0401fdf2, 0x0401f003, 0x4803c856, 0x0401fde8,
+ 0x4a01a006, 0x01000000, 0x5930041a, 0x4801a407,
+ 0x5930021a, 0x4801a207, 0x42000800, 0x00000002,
+ 0x42001000, 0x0000dc00, 0x0401f1d6, 0x4803c856,
+ 0x4d1c0000, 0x0401fdcc, 0x4a01a006, 0x14000000,
+ 0x5932381e, 0x591c0019, 0x4801a005, 0x59300419,
+ 0x4801a407, 0x59300219, 0x4801a207, 0x59300015,
+ 0x4801a008, 0x59300216, 0x82000500, 0x000000ff,
+ 0x840001c0, 0x4801a409, 0x42000800, 0x00000004,
+ 0x42001000, 0x0000dc00, 0x5c023800, 0x0401f1bd,
+ 0x4803c856, 0x0401f80b, 0x5930041a, 0x900001c0,
+ 0x4801a005, 0x0401f9ec, 0x41780800, 0x42001000,
+ 0x00005c00, 0x0401f9b3, 0x0201f000, 0x0010604d,
+ 0x4803c856, 0x59300817, 0x82041c00, 0x00000005,
+ 0x46034800, 0x00000021, 0x58040404, 0x82000500,
+ 0x0000f000, 0x82000580, 0x00003000, 0x04000003,
+ 0x46034800, 0x00000041, 0x81a5a000, 0x580c0001,
+ 0x82000d00, 0x00ffffff, 0x82040d40, 0xc2000000,
+ 0x4805a000, 0x580c0800, 0x82041500, 0x00ffffff,
+ 0x82000500, 0xff000000, 0x80080540, 0x4801a001,
+ 0x580c0002, 0x82000580, 0x00c00000, 0x82000500,
+ 0x00fd0300, 0x4801a002, 0x580c0003, 0x4801a003,
+ 0x580c0404, 0x4801a404, 0x580c0204, 0x4801a204,
+ 0x1c01f000, 0x4803c856, 0x59a80026, 0x82000500,
+ 0x00000028, 0x04020009, 0x59a80026, 0x82000500,
+ 0x00000028, 0x04000003, 0x497a6a12, 0x0401f003,
+ 0x4a026a12, 0x0000ff00, 0x42005000, 0x22000000,
+ 0x42006000, 0x01380000, 0x41786800, 0x41787800,
+ 0x0401f952, 0x59301008, 0x4a01a006, 0x54000000,
+ 0x59a80010, 0x82000500, 0x00ffffff, 0x58080c0a,
+ 0x800408f0, 0x80040540, 0x4801a007, 0x5808000a,
+ 0x82000500, 0xff000000, 0x4801a008, 0x59a80002,
+ 0x4801a009, 0x59a80003, 0x4801a00a, 0x59a80000,
+ 0x4801a00b, 0x59a80001, 0x4801a00c, 0x5808000c,
+ 0x9c0001c0, 0x4801a00d, 0x5808000d, 0x9c0001c0,
+ 0x4801a00e, 0x5808000e, 0x9c0001c0, 0x4801a00f,
+ 0x5808000f, 0x9c0001c0, 0x4801a010, 0x58080010,
+ 0x9c0001c0, 0x4801a011, 0x58080011, 0x9c0001c0,
+ 0x4801a012, 0x58080012, 0x9c0001c0, 0x4801a013,
+ 0x58080013, 0x9c0001c0, 0x4801a014, 0x58080010,
+ 0x9c0001c0, 0x4801a015, 0x58080011, 0x9c0001c0,
+ 0x4801a016, 0x58080012, 0x9c0001c0, 0x4801a017,
+ 0x58080013, 0x9c0001c0, 0x4801a018, 0x42000800,
+ 0x00000013, 0x42001000, 0x0000dc00, 0x0401f135,
+ 0x4803c856, 0x42005000, 0x22000000, 0x42006000,
+ 0x01290000, 0x41786800, 0x41787800, 0x0401f90b,
+ 0x59301008, 0x4a01a006, 0x55000000, 0x5808000b,
+ 0x82000500, 0x00ffffff, 0x58080c0a, 0x800408f0,
+ 0x80040540, 0x4801a007, 0x5808080a, 0x82040d00,
+ 0xff000000, 0x59a80010, 0x82000500, 0x00ffffff,
+ 0x80040540, 0x4801a008, 0x5808000c, 0x9c0001c0,
+ 0x4801a009, 0x5808000d, 0x9c0001c0, 0x4801a00a,
+ 0x5808000e, 0x9c0001c0, 0x4801a00b, 0x5808000f,
+ 0x9c0001c0, 0x4801a00c, 0x59a80002, 0x4801a00d,
+ 0x59a80003, 0x4801a00e, 0x59a80000, 0x4801a00f,
+ 0x59a80001, 0x4801a010, 0x58080010, 0x4801a011,
+ 0x58080011, 0x4801a012, 0x58080012, 0x4801a013,
+ 0x58080013, 0x4801a014, 0x4979a015, 0x4979a016,
+ 0x4979a017, 0x4979a018, 0x42000800, 0x00000013,
+ 0x42001000, 0x0000dc00, 0x0401f0f6, 0x0401fd03,
+ 0x5930001c, 0x800001c0, 0x04000008, 0x4a01a006,
+ 0x01000000, 0x4a01a407, 0x00000003, 0x42000800,
+ 0x00000002, 0x0401f028, 0x4a01a006, 0x02000000,
+ 0x41780800, 0x836c0580, 0x00000004, 0x04020003,
+ 0x84040d42, 0x0401f00d, 0x0201f800, 0x0010513b,
+ 0x04020003, 0x84040d4a, 0x0401f002, 0x84040d48,
+ 0x59a80026, 0x8c000506, 0x04020003, 0x8c00050a,
+ 0x04000002, 0x84040d46, 0x4805a207, 0x59c40085,
+ 0x48031004, 0x4c580000, 0x4c500000, 0x4c540000,
+ 0x4200b000, 0x00000006, 0x8388a400, 0x00000000,
+ 0x82d0ac00, 0x00000008, 0x0201f800, 0x0010ab17,
+ 0x5c00a800, 0x5c00a000, 0x5c00b000, 0x42000800,
+ 0x00000008, 0x42001000, 0x0000dc00, 0x0401f0c1,
+ 0x0401fcc0, 0x4a01a006, 0x56000000, 0x59340006,
+ 0x4801a007, 0x59340007, 0x4801a008, 0x42000800,
+ 0x00000003, 0x42001000, 0x0000dc00, 0x0401f0b5,
+ 0x4803c856, 0x0401fcc1, 0x5930081c, 0x800409c0,
+ 0x0400000e, 0x82040580, 0x0000ffff, 0x04000004,
+ 0x82040480, 0x00000007, 0x04021008, 0x4a01a006,
+ 0x01000000, 0x4a01a407, 0x00000003, 0x42000800,
+ 0x00000002, 0x0401f012, 0x4a01a006, 0x0200001c,
+ 0x4a01a007, 0x00000001, 0x42001000, 0x0010b4f0,
+ 0x50080000, 0x9c0001c0, 0x4801a009, 0x59a80010,
+ 0x4801a00a, 0x59a80002, 0x59a80803, 0x4801a00b,
+ 0x4805a00c, 0x42000800, 0x00000007, 0x42001000,
+ 0x0000dc00, 0x0401f08f, 0x4d2c0000, 0x0401fc8d,
+ 0x59325808, 0x592c0008, 0x82000500, 0x00ffffff,
+ 0x4801a001, 0x4a01a006, 0x51000000, 0x5c025800,
+ 0x0201f000, 0x00107344, 0x4803c856, 0x59a80810,
+ 0x82040d00, 0x000000ff, 0x59325808, 0x59326809,
+ 0x59a83026, 0x8c18350a, 0x04020008, 0x8c00050e,
+ 0x04020006, 0x80001d80, 0x59a82010, 0x82102500,
+ 0x000000ff, 0x0401f001, 0x59300406, 0x4803c857,
+ 0x82000d80, 0x00000009, 0x04000006, 0x82000d80,
+ 0x0000000a, 0x0400002e, 0x0201f800, 0x001005d8,
+ 0x59300015, 0x8c00051e, 0x04020020, 0x42005000,
+ 0x04000000, 0x42006000, 0x05000000, 0x592c040a,
+ 0x82000500, 0x00000030, 0x800000e0, 0x80306540,
+ 0x5934000a, 0x8c000508, 0x04000002, 0x84306546,
+ 0x41786800, 0x41787800, 0x0401f831, 0x59300c14,
+ 0x80040000, 0x48026414, 0x40040000, 0x800000d0,
+ 0x82000540, 0x00000020, 0x4801a403, 0x83180d40,
+ 0x00000038, 0x42001000, 0x0000c920, 0x0401f860,
+ 0x0201f000, 0x00106052, 0x59a80026, 0x82000500,
+ 0x00000028, 0x04000003, 0x497a6a12, 0x0401f7dc,
+ 0x4a026a12, 0x0000ff00, 0x0401f7d9, 0x42005000,
+ 0x02000000, 0x42006000, 0x20290000, 0x41786800,
+ 0x41787800, 0x0401f812, 0x83180d40, 0x00000038,
+ 0x42001000, 0x0000c9a0, 0x0401f849, 0x42000800,
+ 0x000007d0, 0x59300011, 0x82000500, 0xfff00000,
+ 0x80000540, 0x04000003, 0x42000800, 0x00001b58,
+ 0x41781000, 0x0201f000, 0x00106054, 0x4201a000,
+ 0x00000000, 0x0401f003, 0x4201a000, 0x00000011,
+ 0x59340a12, 0x82040d00, 0x0000ff00, 0x59a80010,
+ 0x82000500, 0x000000ff, 0x900001c0, 0x80040540,
+ 0x80d00540, 0x44034800, 0x81a5a000, 0x59340002,
+ 0x82000500, 0x00ffffff, 0x80280540, 0x4801a000,
+ 0x59a80010, 0x4801a001, 0x4831a002, 0x82340540,
+ 0x00000000, 0x4801a003, 0x59300402, 0x4801a404,
+ 0x59300a02, 0x4805a204, 0x8c30652e, 0x04000003,
+ 0x4805a404, 0x4801a204, 0x483da005, 0x1c01f000,
+ 0x4803c856, 0x4c040000, 0x0401f822, 0x5c000800,
+ 0x40040000, 0x80081540, 0x800000c4, 0x82000540,
+ 0x00002000, 0x4803910a, 0x59b400f6, 0x82000500,
+ 0x00000018, 0x040207fd, 0x4a0368f0, 0x0010b544,
+ 0x4a0368f1, 0x0010b54b, 0x480b68f3, 0x4a0378e4,
+ 0x00008000, 0x0201f000, 0x0010604d, 0x4807c857,
+ 0x480a2800, 0x4c040000, 0x0401f80a, 0x5c000800,
+ 0x59b400f6, 0x8c00050a, 0x040207fe, 0x49a768f2,
+ 0x480768f4, 0x4a0378e4, 0x00008000, 0x1c01f000,
+ 0x4a0378e4, 0x0000c000, 0x59bc00e4, 0x8c000520,
+ 0x0400000c, 0x4a0378e4, 0x00008000, 0x42007000,
+ 0x000003e8, 0x59bc00e4, 0x8c000520, 0x040007f5,
+ 0x80387040, 0x02000800, 0x001005d8, 0x0401f7fa,
+ 0x1c01f000, 0x82000500, 0xffff0000, 0x82000580,
+ 0x01050000, 0x0402000d, 0x599c0818, 0x8c040d10,
+ 0x0400000a, 0x59a80807, 0x8c040d0a, 0x04000007,
+ 0x42001000, 0x0000804f, 0x41781800, 0x41782000,
+ 0x0201f800, 0x00103a3e, 0x1c01f000, 0x41781000,
+ 0x42026000, 0x0010d1c0, 0x59a8180e, 0x480a6402,
+ 0x4a026202, 0x0000ffff, 0x80081000, 0x800c1840,
+ 0x04000004, 0x83326400, 0x00000024, 0x0401f7f8,
+ 0x1c01f000, 0x4933c857, 0x59300203, 0x82000580,
+ 0x00000000, 0x0400002c, 0x59300406, 0x4803c857,
+ 0x82000d80, 0x00000004, 0x04000011, 0x82000d80,
+ 0x00000001, 0x0400000e, 0x82000d80, 0x00000003,
+ 0x04000006, 0x82000d80, 0x00000006, 0x04020011,
+ 0x0201f800, 0x0010a5df, 0x5930001c, 0x800001c0,
+ 0x02020800, 0x0010984e, 0x0401f00a, 0x5930081e,
+ 0x4807c857, 0x800409c0, 0x04000006, 0x5804001c,
+ 0x4803c857, 0x81300580, 0x04020002, 0x4978081c,
+ 0x497a6008, 0x4a026004, 0x00004000, 0x59a80037,
+ 0x82000c80, 0x00000051, 0x04001002, 0x80000102,
+ 0x48026206, 0x497a6205, 0x497a6009, 0x4a026406,
+ 0x00000007, 0x1c01f000, 0x8166c9c0, 0x0400001c,
+ 0x41626000, 0x41580000, 0x59300a03, 0x82040d80,
+ 0x00000000, 0x04000008, 0x83326400, 0x00000024,
+ 0x81300c80, 0x040017f9, 0x42026000, 0x0010d1c0,
+ 0x0401f7f6, 0x4933c857, 0x8166c840, 0x83300c00,
+ 0x00000024, 0x80040480, 0x04021006, 0x4006c000,
+ 0x4a026203, 0x00000008, 0x813261c0, 0x1c01f000,
+ 0x4202c000, 0x0010d1c0, 0x0401f7fa, 0x42000000,
+ 0x0010b854, 0x0201f800, 0x0010aa47, 0x4933c856,
+ 0x417a6000, 0x0401f7f5, 0x4933c857, 0x83380580,
+ 0x00000013, 0x0402000b, 0x59300004, 0x8c00053e,
+ 0x04000007, 0x0201f800, 0x00106c55, 0x0201f800,
+ 0x00106bbf, 0x0201f800, 0x00106c4b, 0x1c01f000,
+ 0x4933c857, 0x59880052, 0x80000000, 0x48031052,
+ 0x1c01f000, 0x4933c857, 0x59300203, 0x82003480,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x4d2c0000,
+ 0x0c01f803, 0x5c025800, 0x1c01f000, 0x00107991,
+ 0x00107efd, 0x0010804a, 0x00107991, 0x001080b0,
+ 0x00107af5, 0x00107991, 0x00107991, 0x00107e93,
+ 0x00107991, 0x00107991, 0x00107991, 0x00107991,
+ 0x00107991, 0x0201f800, 0x001005d8, 0x4933c857,
+ 0x59300203, 0x82003480, 0x0000000e, 0x02021800,
+ 0x001005d8, 0x0c01f001, 0x001079a8, 0x00108a3d,
+ 0x001079a8, 0x001079a8, 0x001079a8, 0x001079a8,
+ 0x001079a8, 0x001079a8, 0x001089e5, 0x00108a58,
+ 0x00108ac6, 0x00108a58, 0x00108ac6, 0x001079a8,
+ 0x0201f800, 0x001005d8, 0x0201f800, 0x001005d8,
+ 0x4933c857, 0x4d2c0000, 0x59325808, 0x59300203,
+ 0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001079c5,
+ 0x001079c5, 0x001079c5, 0x001079e1, 0x00107a2d,
+ 0x001079c5, 0x001079c5, 0x001079c5, 0x001079c7,
+ 0x001079c5, 0x001079c5, 0x001079c5, 0x001079c5,
+ 0x001079c5, 0x0201f800, 0x001005d8, 0x4933c857,
+ 0x83380580, 0x00000040, 0x02020800, 0x001005d8,
+ 0x4a026007, 0x00082000, 0x4a026203, 0x00000003,
+ 0x493a6403, 0x4a025c08, 0x00000001, 0x592c000d,
+ 0x48026011, 0x497a6013, 0x592c0208, 0x800000c2,
+ 0x800010c4, 0x80081400, 0x480a6206, 0x0201f800,
+ 0x00100f4e, 0x42000800, 0x80000060, 0x0201f000,
+ 0x00106721, 0x4933c857, 0x83380480, 0x00000050,
+ 0x02021800, 0x001005d8, 0x83380480, 0x00000049,
+ 0x02001800, 0x001005d8, 0x0c01f001, 0x001079f4,
+ 0x001079ff, 0x001079f2, 0x001079f2, 0x001079f2,
+ 0x001079f2, 0x00107a0a, 0x0201f800, 0x001005d8,
+ 0x4a026203, 0x00000004, 0x4a025c08, 0x00000002,
+ 0x592c0207, 0x48025c09, 0x592c0209, 0x48025a07,
+ 0x592c000c, 0x4802580d, 0x1c01f000, 0x0201f800,
+ 0x00106b8a, 0x0201f800, 0x00109037, 0x04000005,
+ 0x4a025a06, 0x00000006, 0x0201f800, 0x000202da,
+ 0x0201f000, 0x0002077d, 0x0201f800, 0x00106b8a,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x5c027800, 0x42003000, 0x00000014, 0x41782800,
+ 0x42002000, 0x00000002, 0x4d400000, 0x4d440000,
+ 0x59368c03, 0x42028000, 0x00000029, 0x0201f800,
+ 0x0010985e, 0x5c028800, 0x5c028000, 0x42000000,
+ 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+ 0x00109037, 0x02000000, 0x0002077d, 0x4a025a06,
+ 0x00000029, 0x0201f800, 0x000202da, 0x0201f000,
+ 0x0002077d, 0x4933c857, 0x83380580, 0x00000048,
+ 0x04000005, 0x83380580, 0x00000053, 0x02020800,
+ 0x001005d8, 0x592c0206, 0x82000580, 0x00000007,
+ 0x04000009, 0x59300011, 0x80000540, 0x04000006,
+ 0x592c080c, 0x80040480, 0x4802580c, 0x4a025a06,
+ 0x00000015, 0x592c0206, 0x80000540, 0x04020003,
+ 0x4a025a06, 0x00000000, 0x0201f800, 0x000202da,
+ 0x0201f000, 0x0002077d, 0x4933c857, 0x4d2c0000,
+ 0x4c500000, 0x4c540000, 0x4c580000, 0x0201f800,
+ 0x001007e4, 0x02000800, 0x001005d8, 0x497a5a06,
+ 0x59c80017, 0x82000500, 0x0000f000, 0x48025c07,
+ 0x59a80816, 0x82040c00, 0x00000018, 0x48065a07,
+ 0x412c7800, 0x4d2c0000, 0x41cca000, 0x42002800,
+ 0x00000001, 0x42001000, 0x0000002c, 0x82040480,
+ 0x0000002d, 0x04021006, 0x832cac00, 0x00000009,
+ 0x0201f800, 0x00108b96, 0x0401f02e, 0x40043000,
+ 0x42000800, 0x0000002c, 0x832cac00, 0x00000009,
+ 0x0201f800, 0x00108b96, 0x82183480, 0x0000002c,
+ 0x0201f800, 0x001007e4, 0x0400001a, 0x80142800,
+ 0x4a025804, 0x00000110, 0x492c7801, 0x82180c80,
+ 0x0000003d, 0x04021007, 0x40180800, 0x832cac00,
+ 0x00000005, 0x0201f800, 0x00108b96, 0x0401f015,
+ 0x82081400, 0x0000003c, 0x82183480, 0x0000003c,
+ 0x42000800, 0x0000003c, 0x412c7800, 0x832cac00,
+ 0x00000005, 0x0201f800, 0x00108b96, 0x0401f7e5,
+ 0x5c025800, 0x592c0206, 0x8400055e, 0x48025a06,
+ 0x592c0407, 0x80080540, 0x48025c07, 0x0401f002,
+ 0x5c025800, 0x813669c0, 0x04000003, 0x59343403,
+ 0x0401f003, 0x42003000, 0x0000ffff, 0x49325808,
+ 0x481a5c06, 0x82100580, 0x00000054, 0x04020002,
+ 0x491e5813, 0x841401c0, 0x80100540, 0x48025804,
+ 0x592c0001, 0x497a5801, 0x4c000000, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x812e59c0, 0x040207f9,
+ 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
+ 0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000,
+ 0x4c500000, 0x4c540000, 0x4c580000, 0x412cb800,
+ 0x592c040b, 0x8c000516, 0x04000003, 0x41cca000,
+ 0x0401f003, 0x83cca400, 0x00000006, 0x4008b000,
+ 0x41781000, 0x82580480, 0x00000012, 0x04001004,
+ 0x4200b000, 0x00000012, 0x40001000, 0x4c080000,
+ 0x4d2c0000, 0x0201f800, 0x001007e4, 0x04000023,
+ 0x5c001800, 0x492c1801, 0x485a5800, 0x832cac00,
+ 0x00000002, 0x0201f800, 0x0010ab28, 0x585c040b,
+ 0x8c000500, 0x0400000e, 0x832c1400, 0x00000002,
+ 0x8c000516, 0x04000003, 0x82081400, 0x00000006,
+ 0x46001000, 0x00000001, 0x80081000, 0x46001000,
+ 0x00000900, 0x84000500, 0x4800bc0b, 0x5c001000,
+ 0x800811c0, 0x040207da, 0x82000540, 0x00000001,
+ 0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
+ 0x5c00b800, 0x1c01f000, 0x5c025800, 0x5c001000,
+ 0x0401f7f8, 0x4933c857, 0x83380d80, 0x00000015,
+ 0x04020003, 0x0201f000, 0x0002077d, 0x83380d80,
+ 0x00000016, 0x02020800, 0x001005d8, 0x0201f000,
+ 0x0002077d, 0x4933c857, 0x4d2c0000, 0x4c500000,
+ 0x4c540000, 0x4c580000, 0x59325808, 0x83cca400,
+ 0x00000006, 0x59cc1806, 0x820c0580, 0x01000000,
+ 0x04020004, 0x4200b000, 0x00000002, 0x0401f00f,
+ 0x4200b000, 0x00000008, 0x832cac00, 0x00000005,
+ 0x0201f800, 0x0010ab17, 0x8c0c1d00, 0x0400000b,
+ 0x4200b000, 0x00000008, 0x592e5801, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x832cac00, 0x00000005,
+ 0x0201f800, 0x0010ab17, 0x0401f816, 0x5c00b000,
+ 0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000,
+ 0x4933c857, 0x4c500000, 0x4c540000, 0x4c580000,
+ 0x83cca400, 0x00000006, 0x5930a808, 0x8254ac00,
+ 0x00000005, 0x4200b000, 0x00000007, 0x0201f800,
+ 0x0010ab17, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+ 0x4933c857, 0x0201f800, 0x00109037, 0x02000000,
+ 0x0002077d, 0x4d2c0000, 0x0201f800, 0x00109597,
+ 0x0402000b, 0x41780800, 0x4d400000, 0x42028000,
+ 0x00000000, 0x0201f800, 0x0010943b, 0x5c028000,
+ 0x5c025800, 0x0201f000, 0x0002077d, 0x5931d821,
+ 0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103,
+ 0x58ec0009, 0x0801f800, 0x5c025800, 0x0201f000,
+ 0x0002077d, 0x4933c857, 0x59cc1806, 0x820c0580,
+ 0x02000000, 0x04020014, 0x4a026802, 0x00fffffd,
+ 0x5934000a, 0x84000504, 0x4802680a, 0x59300808,
+ 0x800409c0, 0x02000000, 0x0002077d, 0x4a000a04,
+ 0x00000103, 0x480c0805, 0x5931d821, 0x58ef400b,
+ 0x58ee580d, 0x58ec0009, 0x0801f800, 0x0201f000,
+ 0x0002077d, 0x42000000, 0x0010b86c, 0x0201f800,
+ 0x0010aa47, 0x4c0c0000, 0x0401f804, 0x5c001800,
+ 0x040207eb, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+ 0x59325808, 0x812e59c0, 0x04020009, 0x497a6206,
+ 0x497a6205, 0x4d380000, 0x42027000, 0x00000022,
+ 0x0401fb77, 0x5c027000, 0x80000580, 0x5c025800,
+ 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c500000,
+ 0x4c540000, 0x4c580000, 0x59325808, 0x592e5801,
+ 0x832cac00, 0x00000005, 0x83cca400, 0x00000006,
+ 0x59c80817, 0x82040d00, 0x000003ff, 0x82041480,
+ 0x0000000f, 0x0400101b, 0x4200b000, 0x0000000f,
+ 0x0201f800, 0x0010ab17, 0x592e5801, 0x832cac00,
+ 0x00000005, 0x82080c80, 0x0000000f, 0x0400100d,
+ 0x4200b000, 0x0000000f, 0x0201f800, 0x0010ab17,
+ 0x592e5801, 0x832cac00, 0x00000005, 0x82041480,
+ 0x0000000f, 0x04001007, 0x42001000, 0x0000000f,
+ 0x4008b000, 0x0201f800, 0x0010ab17, 0x0401f004,
+ 0x4004b000, 0x0201f800, 0x0010ab17, 0x5931d821,
+ 0x58ef400b, 0x58ee580d, 0x4a025a04, 0x00000103,
+ 0x592e5801, 0x58ec0009, 0x0801f800, 0x0201f800,
+ 0x0002077d, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x4d2c0000,
+ 0x4c500000, 0x4c540000, 0x4c580000, 0x59cc0006,
+ 0x82000d80, 0x01000000, 0x0400002c, 0x59cc0007,
+ 0x9000b1c0, 0x8258b500, 0x000000ff, 0x8058b104,
+ 0x8258b400, 0x00000002, 0x82580c80, 0x00000007,
+ 0x04001003, 0x4200b000, 0x00000006, 0x83cca400,
+ 0x00000006, 0x59301008, 0x800811c0, 0x02000800,
+ 0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800,
+ 0x0010ab17, 0x82000d00, 0xff000000, 0x800409c0,
+ 0x04000019, 0x8200b500, 0x000000ff, 0x8058b104,
+ 0x82580c80, 0x0000000e, 0x04001003, 0x4200b000,
+ 0x0000000d, 0x58081001, 0x800811c0, 0x02000800,
+ 0x001005d8, 0x8208ac00, 0x00000005, 0x0201f800,
+ 0x0010ab17, 0x0401f008, 0x59301008, 0x800811c0,
+ 0x02000800, 0x001005d8, 0x48001005, 0x59cc0007,
+ 0x48001006, 0x0401ff3b, 0x5c00b000, 0x5c00a800,
+ 0x5c00a000, 0x5c025800, 0x1c01f000, 0x4933c857,
+ 0x42000800, 0x00000000, 0x59cc0006, 0x82000580,
+ 0x02000000, 0x04000003, 0x42000800, 0x00000001,
+ 0x4d2c0000, 0x59325808, 0x812e59c0, 0x02000800,
+ 0x001005d8, 0x48065a06, 0x0201f800, 0x000202da,
+ 0x5c025800, 0x0201f000, 0x0002077d, 0x4933c857,
+ 0x4d2c0000, 0x4c500000, 0x4c540000, 0x4c580000,
+ 0x4200b000, 0x00000002, 0x59cc0806, 0x82040580,
+ 0x01000000, 0x04000004, 0x8204b500, 0x0000ffff,
+ 0x8058b104, 0x83cca400, 0x00000006, 0x59300008,
+ 0x8200ac00, 0x00000005, 0x0201f800, 0x0010ab17,
+ 0x0401ff0c, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x4803c857,
+ 0x4807c857, 0x480bc857, 0x480fc857, 0x4813c857,
+ 0x481bc857, 0x492fc857, 0x4d2c0000, 0x4c000000,
+ 0x0201f800, 0x001007d3, 0x5c000000, 0x0400000f,
+ 0x48025803, 0x5c000000, 0x4802580a, 0x4c000000,
+ 0x481a5801, 0x48125809, 0x48065804, 0x480a5807,
+ 0x480e5808, 0x412c1000, 0x0201f800, 0x00100858,
+ 0x82000540, 0x00000001, 0x5c025800, 0x1c01f000,
+ 0x4933c857, 0x4d1c0000, 0x59cc0001, 0x82000500,
+ 0x00ffffff, 0x59341002, 0x82081500, 0x00ffffff,
+ 0x80080580, 0x0402001f, 0x497a6205, 0x4d380000,
+ 0x42027000, 0x00000035, 0x0201f800, 0x001093ba,
+ 0x5c027000, 0x04020012, 0x591c001c, 0x800001c0,
+ 0x0400000f, 0x497a381c, 0x591c0414, 0x8c000502,
+ 0x02000800, 0x001005d8, 0x84000502, 0x48023c14,
+ 0x591c1406, 0x82080580, 0x00000003, 0x04000006,
+ 0x82080580, 0x00000006, 0x04000005, 0x0401fc9e,
+ 0x0401f004, 0x0401f805, 0x0401f002, 0x0401f8c0,
+ 0x5c023800, 0x1c01f000, 0x4d2c0000, 0x591e5808,
+ 0x4933c857, 0x491fc857, 0x493bc857, 0x492fc857,
+ 0x83380580, 0x00000015, 0x040000b3, 0x83380580,
+ 0x00000016, 0x040200ae, 0x4d300000, 0x411e6000,
+ 0x59cc0207, 0x4803c857, 0x82000d00, 0x0000ff00,
+ 0x82040580, 0x00001700, 0x04000004, 0x82040580,
+ 0x00000300, 0x0402005b, 0x591c0203, 0x4803c857,
+ 0x82000580, 0x0000000d, 0x0400003f, 0x812e59c0,
+ 0x0400009a, 0x591c0202, 0x4803c857, 0x82000580,
+ 0x0000ffff, 0x0402007e, 0x592c020a, 0x4803c857,
+ 0x82000500, 0x00000003, 0x82000580, 0x00000002,
+ 0x04020007, 0x592c080f, 0x591c0011, 0x4803c857,
+ 0x4807c857, 0x80040580, 0x04020071, 0x591c0414,
+ 0x4803c857, 0x8c000500, 0x0402006d, 0x41780800,
+ 0x591c1206, 0x42000000, 0x0000000a, 0x0201f800,
+ 0x001066a0, 0x592c0406, 0x4803c857, 0x800001c0,
+ 0x0400000c, 0x80080c80, 0x04001004, 0x02020800,
+ 0x001005d8, 0x80001040, 0x480a5c06, 0x800811c0,
+ 0x04020004, 0x0201f800, 0x00108d88, 0x0401f06b,
+ 0x0201f800, 0x0010912a, 0x591c0817, 0x591c0018,
+ 0x48065808, 0x48025809, 0x59300007, 0x8c000500,
+ 0x02020800, 0x00100e99, 0x497a3808, 0x0201f800,
+ 0x000201ba, 0x0402004a, 0x411e6000, 0x0401fc3e,
+ 0x0401f05a, 0x0401fc6d, 0x04000013, 0x49366009,
+ 0x4a026406, 0x00000003, 0x492e6008, 0x591c0817,
+ 0x591c1018, 0x48066017, 0x480a6018, 0x4d380000,
+ 0x591e7403, 0x4d300000, 0x411e6000, 0x0401fc2e,
+ 0x5c026000, 0x0201f800, 0x000207a1, 0x5c027000,
+ 0x0401f046, 0x59a80039, 0x48023a05, 0x0401f043,
+ 0x59cc0407, 0x82000580, 0x0000000b, 0x04020025,
+ 0x59340a00, 0x84040d0e, 0x48066a00, 0x592c0a04,
+ 0x82040d00, 0x000000ff, 0x82040d80, 0x00000014,
+ 0x04000003, 0x4a02621d, 0x00000003, 0x59300007,
+ 0x8c000500, 0x02020800, 0x00100e99, 0x4d400000,
+ 0x42028000, 0x00000003, 0x592c0a08, 0x0201f800,
+ 0x00104e70, 0x0201f800, 0x000202da, 0x5c028000,
+ 0x497a6008, 0x4a026403, 0x00000085, 0x4a026203,
+ 0x00000009, 0x4a026406, 0x00000002, 0x42000800,
+ 0x8000404b, 0x0201f800, 0x00020721, 0x0401f01b,
+ 0x59cc0207, 0x82000580, 0x00002a00, 0x04020004,
+ 0x59a80039, 0x48023a05, 0x0401f014, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x4a025a04, 0x00000103,
+ 0x591c0007, 0x8c000500, 0x02020800, 0x00100e99,
+ 0x591c0402, 0x48025c06, 0x4a025a06, 0x00000003,
+ 0x0201f800, 0x000202c1, 0x0201f800, 0x00107911,
+ 0x0201f800, 0x001049b2, 0x5c026000, 0x0201f800,
+ 0x0002077d, 0x0401f002, 0x5c026000, 0x5c025800,
+ 0x1c01f000, 0x0401f819, 0x0401f7fd, 0x4933c857,
+ 0x83380580, 0x00000015, 0x04020004, 0x59a80039,
+ 0x48023a05, 0x0401f00d, 0x83380580, 0x00000016,
+ 0x0402000d, 0x4d300000, 0x411e6000, 0x0201f800,
+ 0x0010a5df, 0x0201f800, 0x000206fd, 0x0201f800,
+ 0x0002077d, 0x5c026000, 0x497a381c, 0x0201f800,
+ 0x0002077d, 0x1c01f000, 0x591c0414, 0x84000540,
+ 0x48023c14, 0x59cc100b, 0x4933c857, 0x491fc857,
+ 0x492fc857, 0x4803c857, 0x480bc857, 0x8c08153c,
+ 0x04000006, 0x59a80039, 0x48023a05, 0x497a381c,
+ 0x0201f000, 0x0002077d, 0x4d300000, 0x411e6000,
+ 0x0201f800, 0x00108bd7, 0x5c026000, 0x591c0406,
+ 0x82000580, 0x00000000, 0x02000000, 0x0002077d,
+ 0x591c0403, 0x82000580, 0x00000050, 0x0402000d,
+ 0x4d300000, 0x411e6000, 0x4a026203, 0x00000001,
+ 0x42000800, 0x80000043, 0x0201f800, 0x00020721,
+ 0x5c026000, 0x497a381c, 0x0201f000, 0x0002077d,
+ 0x591c0203, 0x82000580, 0x0000000d, 0x04000014,
+ 0x812e59c0, 0x02000800, 0x001005d8, 0x591c0203,
+ 0x82000580, 0x00000004, 0x04020011, 0x592c020a,
+ 0x8c000502, 0x0400000e, 0x4a023812, 0x0fffffff,
+ 0x592c0208, 0x8400051e, 0x48025a08, 0x42000000,
+ 0x00000001, 0x48023a14, 0x0401f021, 0x42000000,
+ 0x00000007, 0x48023a14, 0x0401f01d, 0x592c020a,
+ 0x4803c857, 0x8c000500, 0x0402000b, 0x8c000502,
+ 0x040007f7, 0x591c0414, 0x8c00051c, 0x040207eb,
+ 0x591c0011, 0x4803c857, 0x800001c0, 0x040007f0,
+ 0x0401f7e6, 0x8c08153a, 0x040207ed, 0x59cc000a,
+ 0x592c180f, 0x4803c857, 0x480fc857, 0x800c0580,
+ 0x040007e7, 0x59cc000a, 0x4803c857, 0x48023816,
+ 0x42000000, 0x00000005, 0x48023a14, 0x0201f000,
+ 0x00109259, 0x4933c857, 0x4d1c0000, 0x59cc0001,
+ 0x59341002, 0x80080580, 0x82000500, 0x00ffffff,
+ 0x04020041, 0x59301419, 0x0201f800, 0x00109410,
+ 0x02000800, 0x001005d8, 0x591c1406, 0x82080580,
+ 0x00000007, 0x04000038, 0x82080580, 0x00000002,
+ 0x04000035, 0x82080580, 0x00000000, 0x04000032,
+ 0x591c0202, 0x82000d80, 0x0000ffff, 0x04000004,
+ 0x59301a19, 0x800c0580, 0x0402002b, 0x83380580,
+ 0x00000015, 0x04000026, 0x4d300000, 0x4d2c0000,
+ 0x411e6000, 0x59325808, 0x0201f800, 0x00109037,
+ 0x02000800, 0x001005d8, 0x592c0204, 0x82000500,
+ 0x000000ff, 0x82000580, 0x00000014, 0x04000003,
+ 0x4a02621d, 0x00000003, 0x42028000, 0x00000003,
+ 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x497a6008, 0x4a026403,
+ 0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+ 0x00000002, 0x42000800, 0x8000404b, 0x0201f800,
+ 0x00020721, 0x5c026000, 0x0401f003, 0x59a80039,
+ 0x48023a05, 0x497a381c, 0x0201f800, 0x0002077d,
+ 0x5c023800, 0x1c01f000, 0x4933c857, 0x4c580000,
+ 0x4d2c0000, 0x59325808, 0x83383580, 0x00000015,
+ 0x04000010, 0x59342200, 0x84102502, 0x48126a00,
+ 0x0201f800, 0x00109037, 0x04000066, 0x0201f800,
+ 0x00109597, 0x04020005, 0x4200b000, 0x00000002,
+ 0x0201f800, 0x0010957d, 0x0401fa0a, 0x0401f079,
+ 0x83cc1400, 0x00000008, 0x4200b000, 0x00000002,
+ 0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+ 0x04020015, 0x83cc1400, 0x0000000a, 0x4200b000,
+ 0x00000002, 0x83341c00, 0x00000008, 0x0201f800,
+ 0x0010855a, 0x0402000c, 0x0201f800, 0x00102074,
+ 0x59342200, 0x59cc1007, 0x800811c0, 0x04000003,
+ 0x480a6801, 0x84102542, 0x8410251a, 0x48126a00,
+ 0x0401f05f, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x59340200, 0x84000558,
+ 0x48026a00, 0x4d300000, 0x0201f800, 0x0002075a,
+ 0x02000800, 0x001005d8, 0x49366009, 0x497a6008,
+ 0x4a026406, 0x00000001, 0x4a026403, 0x00000001,
+ 0x42003000, 0x00000003, 0x0201f800, 0x0010a942,
+ 0x0201f800, 0x00103b25, 0x04000011, 0x41782800,
+ 0x42003000, 0x00000001, 0x4d400000, 0x42028000,
+ 0x00000029, 0x0201f800, 0x0010a43e, 0x5c028000,
+ 0x4a026406, 0x00000004, 0x4a026203, 0x00000007,
+ 0x4a026420, 0x00000001, 0x0401f009, 0x4a026203,
+ 0x00000001, 0x42000800, 0x0000000b, 0x0201f800,
+ 0x00104571, 0x0201f800, 0x0010672b, 0x5c026000,
+ 0x0201f800, 0x00109037, 0x04000022, 0x0201f800,
+ 0x00109597, 0x04020022, 0x0401f9ae, 0x0401f01d,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x59340200, 0x84000558, 0x48026a00, 0x42003000,
+ 0x00000003, 0x41782800, 0x42002000, 0x00000005,
+ 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+ 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+ 0x5c028000, 0x5c027800, 0x0201f800, 0x00102074,
+ 0x0201f800, 0x0002077d, 0x0401f002, 0x0401fca9,
+ 0x5c025800, 0x5c00b000, 0x1c01f000, 0x4933c857,
+ 0x41380000, 0x83383480, 0x00000056, 0x02021800,
+ 0x001005d8, 0x0c01f001, 0x00107ef7, 0x00107ef2,
+ 0x00107ef7, 0x00107ef7, 0x00107ef7, 0x00107ef7,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef7, 0x00107ef0, 0x00107ef7,
+ 0x00107ef7, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef7, 0x00107ef7, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+ 0x00107ef0, 0x00107ef0, 0x00107ef7, 0x00107ef7,
+ 0x00107ef0, 0x00107ef7, 0x00107ef7, 0x00107ef0,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+ 0x00107ef0, 0x00107ef0, 0x00107ef0, 0x00107ef7,
+ 0x0201f800, 0x001005d8, 0x4a026203, 0x00000001,
+ 0x493a6403, 0x0201f000, 0x0010672b, 0x4933c857,
+ 0x4a026203, 0x00000001, 0x493a6403, 0x0201f000,
+ 0x0010672b, 0x4933c857, 0x59300403, 0x82003480,
+ 0x00000056, 0x02021800, 0x001005d8, 0x83383580,
+ 0x00000013, 0x04000093, 0x83383580, 0x00000027,
+ 0x0402004b, 0x0201f800, 0x00106bbf, 0x0201f800,
+ 0x00109134, 0x0400000b, 0x0201f800, 0x0010914e,
+ 0x04000041, 0x59300403, 0x82000d80, 0x00000022,
+ 0x04020038, 0x0401fc61, 0x0400003a, 0x0401f03a,
+ 0x0201f800, 0x00102074, 0x42000800, 0x00000007,
+ 0x0201f800, 0x00104571, 0x0401f8fe, 0x4d440000,
+ 0x59368c03, 0x83440580, 0x000007fe, 0x04020008,
+ 0x59a81026, 0x84081540, 0x0201f800, 0x0010513b,
+ 0x04020002, 0x8408154a, 0x480b5026, 0x42028000,
+ 0x00000029, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x836c0580, 0x00000003,
+ 0x0400000c, 0x59326809, 0x59340008, 0x800001c0,
+ 0x04020008, 0x59368c03, 0x4933c857, 0x4937c857,
+ 0x4947c857, 0x0201f800, 0x001045fb, 0x0401f00c,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x42003000, 0x00000015, 0x41782800, 0x42002000,
+ 0x00000003, 0x0201f800, 0x0010985e, 0x5c028800,
+ 0x0201f800, 0x00109326, 0x0201f000, 0x0002077d,
+ 0x1c01f000, 0x0401f8cb, 0x0401f7fa, 0x83380580,
+ 0x00000014, 0x0400000b, 0x0201f800, 0x00106f60,
+ 0x02020000, 0x00107974, 0x59300203, 0x82000580,
+ 0x00000002, 0x040000ed, 0x0201f800, 0x001005d8,
+ 0x0201f800, 0x00106bbf, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x0010203c, 0x5c027800, 0x42003000,
+ 0x00000016, 0x41782800, 0x4d400000, 0x4d440000,
+ 0x59368c03, 0x42002000, 0x00000009, 0x42028000,
+ 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+ 0x5c028000, 0x42000000, 0x0010b864, 0x0201f800,
+ 0x0010aa47, 0x0201f800, 0x00109134, 0x0402000c,
+ 0x0201f800, 0x00102074, 0x0401f89e, 0x59340c03,
+ 0x82040580, 0x000007fe, 0x040207ca, 0x59a80826,
+ 0x84040d40, 0x48075026, 0x0401f7c6, 0x0201f800,
+ 0x0010914e, 0x04020003, 0x0401f892, 0x0401f7c1,
+ 0x59300403, 0x82000d80, 0x00000032, 0x04020004,
+ 0x0201f800, 0x0010230c, 0x0401f7ba, 0x59300403,
+ 0x82000d80, 0x00000022, 0x04000886, 0x0401f7b5,
+ 0x4803c857, 0x0c01f001, 0x00108016, 0x00108016,
+ 0x00108016, 0x00108016, 0x00108016, 0x00108016,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff9, 0x00108016, 0x00107ff0, 0x00108016,
+ 0x00108016, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00108016, 0x00108016,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00107ff0,
+ 0x00108007, 0x00108016, 0x00107ff0, 0x00108000,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108000,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+ 0x00108003, 0x00107ff0, 0x00107ff2, 0x00108016,
+ 0x00107ff0, 0x00108016, 0x00108016, 0x00107ff0,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+ 0x00107ff0, 0x00107ff0, 0x00107ff0, 0x00108016,
+ 0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808,
+ 0x0201f800, 0x000202da, 0x5c025800, 0x0201f000,
+ 0x0002077d, 0x4a026203, 0x00000005, 0x59a80039,
+ 0x48026205, 0x59a80037, 0x48026206, 0x1c01f000,
+ 0x5930081e, 0x49780a05, 0x0401f014, 0x0201f800,
+ 0x00109326, 0x0201f000, 0x0002077d, 0x0201f800,
+ 0x0010230c, 0x0201f800, 0x00106c55, 0x04000005,
+ 0x0201f800, 0x00106bbf, 0x0201f000, 0x0002077d,
+ 0x0201f800, 0x00106bbf, 0x0201f800, 0x0002077d,
+ 0x0201f000, 0x00106c4b, 0x4933c857, 0x4a026203,
+ 0x00000002, 0x59a80037, 0x48026206, 0x1c01f000,
+ 0x4933c857, 0x0201f800, 0x00109037, 0x0400002a,
+ 0x4d2c0000, 0x0201f800, 0x00109597, 0x0402000a,
+ 0x4d400000, 0x42028000, 0x00000031, 0x42000800,
+ 0x00000004, 0x0201f800, 0x0010943b, 0x5c028000,
+ 0x0401f01c, 0x59300c06, 0x82040580, 0x00000010,
+ 0x04000004, 0x82040580, 0x00000011, 0x0402000a,
+ 0x4a025a06, 0x00000031, 0x4a02580d, 0x00000004,
+ 0x4a02580e, 0x000000ff, 0x0201f800, 0x000202da,
+ 0x0401f00c, 0x592c0404, 0x8c00051e, 0x04000009,
+ 0x4a025a04, 0x00000103, 0x4a025805, 0x01000000,
+ 0x5931d821, 0x58ef400b, 0x58ec0009, 0x0801f800,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x59340400,
+ 0x82000500, 0x000000ff, 0x82003480, 0x0000000c,
+ 0x02021800, 0x001005d8, 0x59303403, 0x82180d80,
+ 0x0000004d, 0x02000000, 0x0010938b, 0x82180d80,
+ 0x00000033, 0x02000000, 0x00109349, 0x82180d80,
+ 0x00000028, 0x02000000, 0x0010918f, 0x82180d80,
+ 0x00000029, 0x02000000, 0x001091a3, 0x82180d80,
+ 0x0000001f, 0x02000000, 0x00107b28, 0x82180d80,
+ 0x00000055, 0x02000000, 0x00107b01, 0x82180d80,
+ 0x00000000, 0x04000591, 0x82180d80, 0x00000022,
+ 0x02000000, 0x00107b55, 0x82180d80, 0x00000035,
+ 0x02000000, 0x00107c50, 0x82180d80, 0x00000039,
+ 0x04000539, 0x82180d80, 0x0000003d, 0x02000000,
+ 0x00107b85, 0x82180d80, 0x00000044, 0x02000000,
+ 0x00107bc2, 0x82180d80, 0x00000049, 0x02000000,
+ 0x00107c17, 0x82180d80, 0x00000041, 0x02000000,
+ 0x00107c03, 0x82180d80, 0x00000043, 0x02000000,
+ 0x001094dc, 0x82180d80, 0x00000051, 0x02000000,
+ 0x00109542, 0x82180d80, 0x00000004, 0x04020003,
+ 0x42000000, 0x00000001, 0x83380d80, 0x00000015,
+ 0x04000006, 0x83380d80, 0x00000016, 0x02020000,
+ 0x00107974, 0x0401f20f, 0x4d2c0000, 0x4d3c0000,
+ 0x0c01f804, 0x5c027800, 0x5c025800, 0x1c01f000,
+ 0x001080b8, 0x001080bc, 0x001080b8, 0x00108131,
+ 0x001080b8, 0x00108226, 0x001082bf, 0x001080b8,
+ 0x001080b8, 0x00108288, 0x001080b8, 0x0010829a,
+ 0x4933c857, 0x497a6007, 0x59300808, 0x58040000,
+ 0x4a000a04, 0x00000103, 0x0201f000, 0x0002077d,
+ 0x4933c857, 0x40000000, 0x40000000, 0x1c01f000,
+ 0x4933c857, 0x59a80016, 0x82000580, 0x00000074,
+ 0x0402005c, 0x0201f800, 0x0010a2c8, 0x04020016,
+ 0x0401f85c, 0x0201f800, 0x00109037, 0x0400000c,
+ 0x0201f800, 0x00109597, 0x04020009, 0x41780800,
+ 0x4d400000, 0x42028000, 0x00000000, 0x0201f800,
+ 0x0010943b, 0x5c028000, 0x0401f003, 0x0201f800,
+ 0x00102074, 0x0201f800, 0x001048c1, 0x0201f000,
+ 0x0002077d, 0x0201f800, 0x00109037, 0x04000007,
+ 0x0201f800, 0x00109597, 0x04020004, 0x0401ff3d,
+ 0x0201f000, 0x0002077d, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x42000000, 0x0010b864, 0x0201f800,
+ 0x0010aa47, 0x59340200, 0x84000558, 0x48026a00,
+ 0x42003000, 0x00000003, 0x0201f800, 0x0010a942,
+ 0x4d300000, 0x0201f800, 0x0002075a, 0x02000800,
+ 0x001005d8, 0x49366009, 0x497a6008, 0x4a026406,
+ 0x00000001, 0x4a026403, 0x00000001, 0x0201f800,
+ 0x00103b25, 0x04000011, 0x4a026406, 0x00000004,
+ 0x4a026203, 0x00000007, 0x4a026420, 0x00000001,
+ 0x42003000, 0x00000001, 0x4d400000, 0x42028000,
+ 0x00000029, 0x41782800, 0x0201f800, 0x0010a43e,
+ 0x5c028000, 0x0401f009, 0x42000800, 0x0000000b,
+ 0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+ 0x0201f800, 0x0010672b, 0x5c026000, 0x0401ff05,
+ 0x0201f800, 0x00102074, 0x0201f000, 0x0002077d,
+ 0x0401ff00, 0x42000000, 0x00000001, 0x0401f0c7,
+ 0x4933c857, 0x59340200, 0x8c000500, 0x0400000d,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567,
+ 0x5c027800, 0x0201f800, 0x00103b25, 0x04000005,
+ 0x42000800, 0x00000006, 0x0201f800, 0x00104571,
+ 0x1c01f000, 0x4933c857, 0x59a80816, 0x82040580,
+ 0x00000074, 0x0400000e, 0x4807c857, 0x82040580,
+ 0x00000100, 0x040200a0, 0x59cc0408, 0x4803c857,
+ 0x8c000500, 0x0400009c, 0x59341403, 0x82080580,
+ 0x000007fe, 0x04000006, 0x0401f097, 0x59341403,
+ 0x82080580, 0x000007fe, 0x04020003, 0x0401fa9c,
+ 0x0401f04c, 0x0201f800, 0x0010462a, 0x59341403,
+ 0x82080580, 0x000007fc, 0x0402001f, 0x4a026802,
+ 0x00fffffc, 0x0201f800, 0x00109037, 0x04000012,
+ 0x0201f800, 0x00109597, 0x0402000f, 0x0401f8a9,
+ 0x41780800, 0x4d400000, 0x42028000, 0x00000000,
+ 0x0201f800, 0x0010943b, 0x5c028000, 0x42000800,
+ 0x00000004, 0x0201f800, 0x00104571, 0x0201f000,
+ 0x0002077d, 0x42000800, 0x00000004, 0x0201f800,
+ 0x00104571, 0x0201f800, 0x00102074, 0x0201f000,
+ 0x0002077d, 0x59a80005, 0x8c000514, 0x04000011,
+ 0x0201f800, 0x0010513b, 0x42001000, 0x00000010,
+ 0x04020009, 0x59340002, 0x82000500, 0x00ff0000,
+ 0x82000580, 0x00ff0000, 0x04000006, 0x42001000,
+ 0x00000008, 0x0201f800, 0x00104c6d, 0x0402005a,
+ 0x0201f800, 0x00109037, 0x0400005b, 0x0201f800,
+ 0x00109597, 0x04020005, 0x592c0404, 0x8c00051c,
+ 0x040207c9, 0x0401f877, 0x42000800, 0x00000005,
+ 0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+ 0x4a026403, 0x00000003, 0x0201f000, 0x0010672b,
+ 0x59cc0408, 0x8c000518, 0x04000010, 0x0201f800,
+ 0x001092e5, 0x0201f800, 0x0010513b, 0x04000004,
+ 0x59cc0408, 0x8c000516, 0x040207b3, 0x59a80026,
+ 0x8400054a, 0x48035026, 0x59a80010, 0x84000570,
+ 0x48038832, 0x0401f7ac, 0x42001000, 0x000000ef,
+ 0x480b5010, 0x497b8830, 0x84081570, 0x480b8832,
+ 0x59c40802, 0x84040d4c, 0x48078802, 0x0201f800,
+ 0x0010930f, 0x59a80026, 0x84000548, 0x48035026,
+ 0x0201f800, 0x0010a3da, 0x0402079b, 0x59a80026,
+ 0x8400054c, 0x48035026, 0x42000800, 0x00000006,
+ 0x0201f800, 0x00104571, 0x417a7800, 0x0201f800,
+ 0x00104567, 0x42000000, 0x000000e8, 0x0201f800,
+ 0x00105c9a, 0x02000800, 0x001045a6, 0x02020800,
+ 0x001005d8, 0x49366009, 0x59340200, 0x8400051a,
+ 0x48026a00, 0x42000800, 0x00000003, 0x0201f800,
+ 0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+ 0x00000001, 0x4a026403, 0x00000002, 0x0201f000,
+ 0x0010672b, 0x0401fe43, 0x42000000, 0x00000001,
+ 0x0401f00a, 0x599c0017, 0x8c00050a, 0x040007ab,
+ 0x42000800, 0x00000004, 0x0201f800, 0x00104571,
+ 0x0201f000, 0x0002077d, 0x4933c857, 0x80003540,
+ 0x04000005, 0x42000800, 0x00000007, 0x0201f800,
+ 0x00104571, 0x801831c0, 0x0402000e, 0x59302008,
+ 0x801021c0, 0x04000004, 0x58100404, 0x8c00051e,
+ 0x04020008, 0x59341c03, 0x42002000, 0x00000004,
+ 0x42003000, 0x00000012, 0x0201f800, 0x00103aae,
+ 0x0201f800, 0x00102074, 0x0201f000, 0x0002077d,
+ 0x4c5c0000, 0x4d2c0000, 0x59325808, 0x0201f800,
+ 0x00105755, 0x5c025800, 0x59cc0008, 0x48002805,
+ 0x59cc0009, 0x48002806, 0x49782807, 0x49782808,
+ 0x49782809, 0x4978280a, 0x59cc0013, 0x8c00053e,
+ 0x04000009, 0x59cc0414, 0x900001c0, 0x59ccbc15,
+ 0x805c0540, 0x48002807, 0x59cc0416, 0x900001c0,
+ 0x48002808, 0x59cc0017, 0x8c00053e, 0x04000009,
+ 0x59cc0418, 0x900001c0, 0x59ccbc19, 0x805c0540,
+ 0x48002809, 0x59cc041a, 0x900001c0, 0x4800280a,
+ 0x5c00b800, 0x1c01f000, 0x4933c857, 0x59a80016,
+ 0x82000580, 0x00000014, 0x04020048, 0x59a80005,
+ 0x8c000514, 0x04000015, 0x0201f800, 0x0010513b,
+ 0x42001000, 0x00000010, 0x04020009, 0x59340002,
+ 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+ 0x0400000a, 0x42001000, 0x00000008, 0x0201f800,
+ 0x00104c6d, 0x04000005, 0x59a80005, 0x84000556,
+ 0x48035005, 0x0401f031, 0x836c0580, 0x00000003,
+ 0x0402000b, 0x59300008, 0x80000540, 0x04020008,
+ 0x59341c03, 0x42002000, 0x00000006, 0x42003000,
+ 0x00000013, 0x0201f800, 0x00103aae, 0x0201f800,
+ 0x0010468d, 0x0401fecf, 0x0401fa1d, 0x0402001f,
+ 0x59340404, 0x80000540, 0x0400001c, 0x42000800,
+ 0x00000006, 0x0201f800, 0x00104571, 0x0201f800,
+ 0x00109037, 0x04000011, 0x0201f800, 0x00109597,
+ 0x0402000a, 0x41780800, 0x4d400000, 0x42028000,
+ 0x00000000, 0x0201f800, 0x0010943b, 0x5c028000,
+ 0x0201f000, 0x0002077d, 0x4a025a04, 0x00000103,
+ 0x4a025805, 0x02000000, 0x0201f800, 0x00102074,
+ 0x0201f000, 0x0002077d, 0x0201f800, 0x00104c19,
+ 0x0201f800, 0x00109037, 0x04000007, 0x0201f800,
+ 0x00109597, 0x04020004, 0x0401fda2, 0x0201f000,
+ 0x0002077d, 0x0401fd9f, 0x80000580, 0x59a80005,
+ 0x8c000516, 0x04000005, 0x84000516, 0x48035005,
+ 0x82000540, 0x00000001, 0x0401ff60, 0x1c01f000,
+ 0x4933c857, 0x59a80016, 0x82000580, 0x00000014,
+ 0x0402000b, 0x42000800, 0x0000000b, 0x0201f800,
+ 0x00104571, 0x4a026203, 0x00000001, 0x4a026403,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x42000000,
+ 0x00000001, 0x0401f74d, 0x4933c857, 0x40003000,
+ 0x59a80016, 0x82000580, 0x00000004, 0x0402000a,
+ 0x82183580, 0x0000000b, 0x04020005, 0x42000800,
+ 0x00000007, 0x0201f800, 0x00104571, 0x0201f000,
+ 0x0002077d, 0x42000000, 0x00000001, 0x0401f73b,
+ 0x4803c857, 0x4d2c0000, 0x4d3c0000, 0x0c01f804,
+ 0x5c027800, 0x5c025800, 0x1c01f000, 0x001080b8,
+ 0x001082ce, 0x001080b8, 0x00108323, 0x001080b8,
+ 0x00108391, 0x001082bf, 0x001080b8, 0x001080b8,
+ 0x001083b1, 0x001080b8, 0x001083c1, 0x4933c857,
+ 0x4d1c0000, 0x59301403, 0x82080580, 0x00000003,
+ 0x04000008, 0x82081580, 0x0000001e, 0x04020003,
+ 0x0201f800, 0x0002077d, 0x5c023800, 0x1c01f000,
+ 0x0401ff5a, 0x0401f7fd, 0x4933c857, 0x0201f800,
+ 0x00109037, 0x0400000b, 0x0201f800, 0x00109597,
+ 0x04020008, 0x4200b000, 0x00000002, 0x0201f800,
+ 0x0010957d, 0x0401fd43, 0x0201f000, 0x0002077d,
+ 0x0401f8f5, 0x04020030, 0x417a7800, 0x0201f800,
+ 0x00104567, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x59340200, 0x84000558, 0x48026a00, 0x4a026403,
+ 0x00000002, 0x42003000, 0x00000003, 0x0201f800,
+ 0x0010a942, 0x0201f800, 0x00103b25, 0x04000011,
+ 0x4d400000, 0x41782800, 0x42003000, 0x00000005,
+ 0x42028000, 0x00000029, 0x0201f800, 0x0010a43e,
+ 0x5c028000, 0x4a026203, 0x00000007, 0x4a026406,
+ 0x00000004, 0x4a026420, 0x00000001, 0x1c01f000,
+ 0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x0201f800, 0x0010672b,
+ 0x0401f7f7, 0x59cc0407, 0x82000580, 0x00000009,
+ 0x0402000a, 0x59340412, 0x82000500, 0x000000ff,
+ 0x0400000c, 0x80000040, 0x48026c12, 0x4a026206,
+ 0x0000000a, 0x0401f7ea, 0x59cc0207, 0x82000500,
+ 0x0000ff00, 0x82000580, 0x00001900, 0x040007c2,
+ 0x0401fcfc, 0x80000580, 0x0401f6c4, 0x4933c857,
+ 0x59a80032, 0x80000540, 0x04000015, 0x59340403,
+ 0x82000580, 0x000007fe, 0x04020011, 0x59a80010,
+ 0x80000000, 0x48035010, 0x417a7800, 0x0201f800,
+ 0x00104567, 0x42000800, 0x00000003, 0x0201f800,
+ 0x00104571, 0x4a026203, 0x00000001, 0x4a026403,
+ 0x00000002, 0x0201f000, 0x0010672b, 0x0201f800,
+ 0x00109037, 0x04000011, 0x0201f800, 0x00109597,
+ 0x0402000e, 0x4c580000, 0x4200b000, 0x00000002,
+ 0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fcd5,
+ 0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+ 0x0201f000, 0x0002077d, 0x0401fcce, 0x59cc3407,
+ 0x82183500, 0x000000ff, 0x82180580, 0x00000005,
+ 0x0400001c, 0x82180580, 0x0000000b, 0x04000016,
+ 0x59cc0207, 0x82000500, 0x0000ff00, 0x04020004,
+ 0x82180580, 0x00000009, 0x04000012, 0x82000580,
+ 0x00001900, 0x0402000c, 0x82180580, 0x00000009,
+ 0x0400000c, 0x42000800, 0x00000004, 0x0201f800,
+ 0x00104571, 0x0201f800, 0x00102074, 0x0201f000,
+ 0x0002077d, 0x42000000, 0x00000001, 0x0401f677,
+ 0x0201f800, 0x00109037, 0x59325808, 0x04000008,
+ 0x592c0204, 0x82000580, 0x00000139, 0x040007f6,
+ 0x592c0404, 0x8c00051e, 0x040207f3, 0x59340403,
+ 0x82000580, 0x000007fe, 0x04020007, 0x59a80026,
+ 0x84000540, 0x48035026, 0x0201f800, 0x00104229,
+ 0x0401f7e9, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x42003000, 0x00000005, 0x0201f800, 0x0010a942,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x0401f7dd, 0x4933c857, 0x0401f84d, 0x0402000b,
+ 0x42000800, 0x00000005, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000003,
+ 0x0201f000, 0x0010672b, 0x42000800, 0x00000004,
+ 0x0201f800, 0x00104571, 0x0201f800, 0x00109597,
+ 0x0402000a, 0x4c580000, 0x4200b000, 0x00000002,
+ 0x0201f800, 0x0010957d, 0x5c00b000, 0x0401fc71,
+ 0x0201f000, 0x0002077d, 0x0401fc6e, 0x80000580,
+ 0x0401f636, 0x4933c857, 0x0401f82d, 0x0402000b,
+ 0x42000800, 0x00000009, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000005,
+ 0x0201f000, 0x0010672b, 0x42000000, 0x00000001,
+ 0x0401f626, 0x4933c857, 0x0401f81d, 0x0402000b,
+ 0x42000800, 0x0000000b, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000001,
+ 0x0201f000, 0x0010672b, 0x42000000, 0x00000001,
+ 0x0401f616, 0x4933c857, 0x59cc0407, 0x82000580,
+ 0x00000003, 0x04020009, 0x59cc0207, 0x82000500,
+ 0x0000ff00, 0x82000d80, 0x00002a00, 0x04000003,
+ 0x82000d80, 0x00001e00, 0x1c01f000, 0x4933c857,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4933c857,
+ 0x4d400000, 0x4c580000, 0x59a80026, 0x82000540,
+ 0x00000003, 0x48035026, 0x0401f85c, 0x04000038,
+ 0x4d340000, 0x4d440000, 0x59a80026, 0x84000552,
+ 0x48035026, 0x0201f800, 0x00103b25, 0x0400000c,
+ 0x42028000, 0x0000002a, 0x42028800, 0x0000ffff,
+ 0x42003000, 0x00000002, 0x0201f800, 0x0010a446,
+ 0x59a80805, 0x84040d44, 0x48075005, 0x42028000,
+ 0x0000002a, 0x4d3c0000, 0x42027800, 0x00000204,
+ 0x0201f800, 0x00101fe5, 0x5c027800, 0x42000000,
+ 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+ 0x00101e45, 0x4200b000, 0x00000010, 0x42028800,
+ 0x000007f0, 0x4d2c0000, 0x83440580, 0x000007fe,
+ 0x04000003, 0x0201f800, 0x001045fb, 0x81468800,
+ 0x8058b040, 0x040207f9, 0x5c025800, 0x59cc0408,
+ 0x8c00051e, 0x04000004, 0x59a80026, 0x84000512,
+ 0x48035026, 0x5c028800, 0x5c026800, 0x0201f800,
+ 0x0010462a, 0x4a026802, 0x00fffffe, 0x59a80826,
+ 0x84040d50, 0x59cc0013, 0x8c00053e, 0x04000003,
+ 0x8c000536, 0x04000004, 0x59cc0017, 0x8c000536,
+ 0x04020002, 0x84040d10, 0x48075026, 0x59cc0800,
+ 0x82040d00, 0x00ffffff, 0x48075010, 0x80040110,
+ 0x4803501d, 0x48038881, 0x0201f800, 0x0010513b,
+ 0x04000007, 0x59cc0009, 0x48035035, 0x59cc000a,
+ 0x48035036, 0x0201f800, 0x001092e5, 0x5c00b000,
+ 0x5c028000, 0x1c01f000, 0x4933c857, 0x4c580000,
+ 0x59a80010, 0x82000500, 0x00ffff00, 0x04000022,
+ 0x59cc1000, 0x82081500, 0x00ffff00, 0x80080580,
+ 0x04000004, 0x42000000, 0x0010b83b, 0x0401f016,
+ 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+ 0x83341c00, 0x00000006, 0x0401f900, 0x04000004,
+ 0x42000000, 0x0010b83c, 0x0401f00b, 0x83cc1400,
+ 0x0000000d, 0x4200b000, 0x00000002, 0x83341c00,
+ 0x00000008, 0x0401f8f5, 0x04000007, 0x42000000,
+ 0x0010b83d, 0x0201f800, 0x0010aa47, 0x82000540,
+ 0x00000001, 0x5c00b000, 0x1c01f000, 0x4933c857,
+ 0x59cc0206, 0x82000580, 0x00000014, 0x04020016,
+ 0x59cc0407, 0x82000580, 0x00000800, 0x04020012,
+ 0x59cc0207, 0x8c00051a, 0x0400000d, 0x82000500,
+ 0x00000f00, 0x82000580, 0x00000100, 0x04020008,
+ 0x59cc020a, 0x8c000508, 0x04020003, 0x8c00050a,
+ 0x04000003, 0x80000580, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4933c857, 0x4943c857,
+ 0x493fc857, 0x4c5c0000, 0x4d300000, 0x4d340000,
+ 0x4d2c0000, 0x4d380000, 0x4130b800, 0x42026000,
+ 0x0010d1c0, 0x59a8000e, 0x81640480, 0x040210bd,
+ 0x8d3e7d12, 0x04000004, 0x405c0000, 0x81300580,
+ 0x040000b3, 0x59300406, 0x82000c80, 0x00000012,
+ 0x04021015, 0x59326809, 0x0c01f001, 0x0010854f,
+ 0x001084bc, 0x001084d3, 0x001084de, 0x001084b7,
+ 0x001084ce, 0x00108507, 0x0010854f, 0x001084b5,
+ 0x0010851b, 0x0010852a, 0x001084b5, 0x001084b5,
+ 0x001084b5, 0x001084b5, 0x0010854f, 0x00108540,
+ 0x00108538, 0x0201f800, 0x001005d8, 0x8d3e7d18,
+ 0x04000004, 0x59300420, 0x8c000500, 0x04020094,
+ 0x59300403, 0x82000580, 0x00000043, 0x04000090,
+ 0x0201f800, 0x00109134, 0x02000800, 0x00102074,
+ 0x0201f800, 0x0010914e, 0x02000800, 0x0010801c,
+ 0x8d3e7d06, 0x04000084, 0x0201f800, 0x001092d7,
+ 0x04000083, 0x0401f080, 0x8d3e7d16, 0x04000004,
+ 0x59300420, 0x8c000500, 0x0402007d, 0x59325808,
+ 0x0201f800, 0x00109037, 0x04000077, 0x49425a06,
+ 0x497a5c09, 0x0201f800, 0x000202da, 0x0201f800,
+ 0x0010912a, 0x0401f070, 0x813669c0, 0x02000800,
+ 0x001005d8, 0x8d3e7d06, 0x04000004, 0x59340200,
+ 0x8c00050e, 0x0402006a, 0x59300004, 0x8400055c,
+ 0x48026004, 0x59300203, 0x82000580, 0x00000004,
+ 0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+ 0x00109037, 0x0400005c, 0x4a025a04, 0x00000103,
+ 0x59300402, 0x48025c06, 0x592c0408, 0x8c000512,
+ 0x04000006, 0x4d2c0000, 0x592e5809, 0x0201f800,
+ 0x001007fd, 0x5c025800, 0x49425a06, 0x497a5c09,
+ 0x0201f800, 0x0010959c, 0x0201f800, 0x000202da,
+ 0x0201f800, 0x0010912a, 0x0401f047, 0x8c000518,
+ 0x04000047, 0x59300203, 0x82000580, 0x00000004,
+ 0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+ 0x00109037, 0x0400003c, 0x49425a06, 0x497a5c09,
+ 0x0201f800, 0x0010a693, 0x0201f800, 0x0010959c,
+ 0x0201f800, 0x000202da, 0x0401f033, 0x0201f800,
+ 0x001062d5, 0x04000032, 0x59300203, 0x82000580,
+ 0x00000004, 0x04020004, 0x0201f800, 0x00100e99,
+ 0x0401f02b, 0x42027000, 0x00000047, 0x0201f800,
+ 0x000207a1, 0x0401f026, 0x59300203, 0x82000580,
+ 0x00000004, 0x02000800, 0x00100e99, 0x59325808,
+ 0x0201f800, 0x00109037, 0x0400001b, 0x49425a06,
+ 0x497a5c09, 0x0201f800, 0x000202da, 0x0401f016,
+ 0x833c0500, 0x00001800, 0x04000015, 0x8d3e7d16,
+ 0x04020013, 0x59325817, 0x0201f800, 0x001007fd,
+ 0x59300203, 0x82000580, 0x00000004, 0x02000800,
+ 0x00100e99, 0x59325808, 0x0201f800, 0x00109037,
+ 0x04000005, 0x49425a06, 0x497a5c09, 0x0201f800,
+ 0x000202da, 0x0201f800, 0x00107911, 0x83326400,
+ 0x00000024, 0x41580000, 0x81300480, 0x04001742,
+ 0x5c027000, 0x5c025800, 0x5c026800, 0x5c026000,
+ 0x5c00b800, 0x1c01f000, 0x5c000000, 0x4c000000,
+ 0x4803c857, 0x480bc857, 0x480fc857, 0x485bc857,
+ 0x50080800, 0x500c0000, 0x80042580, 0x04020007,
+ 0x80081000, 0x800c1800, 0x8058b040, 0x040207f9,
+ 0x80000580, 0x1c01f000, 0x4803c857, 0x4807c857,
+ 0x480bc857, 0x480fc857, 0x80040480, 0x04001006,
+ 0x42000000, 0x00000001, 0x82040d40, 0x00000001,
+ 0x1c01f000, 0x41780000, 0x0401f7fc, 0x83380480,
+ 0x00000053, 0x02021800, 0x001005d8, 0x83380480,
+ 0x0000004b, 0x02001800, 0x001005d8, 0x0c01f001,
+ 0x0010858a, 0x0010858a, 0x0010858a, 0x0010858a,
+ 0x00108588, 0x00108588, 0x00108588, 0x0010858a,
+ 0x0201f800, 0x001005d8, 0x493bc857, 0x4a026203,
+ 0x0000000d, 0x493a6403, 0x42000800, 0x80000000,
+ 0x0201f000, 0x00020721, 0x83380580, 0x00000013,
+ 0x04020008, 0x59300403, 0x82000580, 0x00000050,
+ 0x02020800, 0x001005d8, 0x0201f000, 0x0002077d,
+ 0x4933c857, 0x83380580, 0x00000027, 0x04020030,
+ 0x4933c857, 0x0201f800, 0x00106bbf, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+ 0x492fc857, 0x0400000d, 0x4a025a04, 0x00000103,
+ 0x59300c02, 0x48065c06, 0x4a025a06, 0x00000029,
+ 0x497a5c09, 0x592c0c08, 0x84040d50, 0x48065c08,
+ 0x0201f800, 0x000202da, 0x5c025800, 0x42003000,
+ 0x00000015, 0x41782800, 0x42002000, 0x00000003,
+ 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+ 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+ 0x5c028000, 0x0201f000, 0x0002077d, 0x83380580,
+ 0x00000014, 0x0402000c, 0x59300403, 0x82000c80,
+ 0x00000053, 0x02021800, 0x001005d8, 0x82000480,
+ 0x00000040, 0x02001800, 0x001005d8, 0x4803c857,
+ 0x0c01f00e, 0x83380580, 0x00000053, 0x0400000a,
+ 0x83380580, 0x00000048, 0x02020800, 0x001005d8,
+ 0x59300403, 0x82000580, 0x00000050, 0x02020800,
+ 0x001005d8, 0x1c01f000, 0x001085ff, 0x001085fd,
+ 0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd,
+ 0x001085fd, 0x001085fd, 0x001085fd, 0x001085fd,
+ 0x001085fd, 0x00108616, 0x00108616, 0x00108616,
+ 0x00108616, 0x001085fd, 0x00108616, 0x001085fd,
+ 0x00108616, 0x0201f800, 0x001005d8, 0x4933c857,
+ 0x0201f800, 0x00106bbf, 0x0201f800, 0x00109037,
+ 0x02000000, 0x0002077d, 0x4d2c0000, 0x59325808,
+ 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06,
+ 0x4a025a06, 0x00000006, 0x497a5c09, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x0201f800, 0x0010912a,
+ 0x0201f000, 0x0002077d, 0x4933c857, 0x0201f800,
+ 0x00106bbf, 0x0201f000, 0x0002077d, 0x0201f800,
+ 0x001005d8, 0x5930001c, 0x800001c0, 0x02020800,
+ 0x0010984e, 0x59300004, 0x8c00053e, 0x04020029,
+ 0x59325808, 0x592c0c08, 0x59cc2a08, 0x82141d00,
+ 0x00000c00, 0x04000002, 0x59cc1809, 0x84040d58,
+ 0x48065c08, 0x82143500, 0x00000fff, 0x04020027,
+ 0x59340200, 0x8c00050e, 0x04020080, 0x0201f800,
+ 0x0002082b, 0x04020006, 0x4a025a06, 0x00000000,
+ 0x59300811, 0x800409c0, 0x0402094b, 0x4a025a04,
+ 0x00000103, 0x48065807, 0x480e580a, 0x48165c09,
+ 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+ 0x0201f800, 0x001049b2, 0x59cc0208, 0x8c000518,
+ 0x02020000, 0x001091d1, 0x0201f000, 0x0002077d,
+ 0x0201f800, 0x00106f60, 0x040007d6, 0x4d3c0000,
+ 0x42027800, 0x00000002, 0x0201f800, 0x00108be3,
+ 0x5c027800, 0x0401f7cf, 0x4817c857, 0x480fc857,
+ 0x82180500, 0x000000ff, 0x0400000e, 0x592c0204,
+ 0x82000500, 0x000000ff, 0x82000580, 0x00000048,
+ 0x04020008, 0x592c0407, 0x800001c0, 0x04000005,
+ 0x0201f800, 0x0010973f, 0x0201f000, 0x00109787,
+ 0x82180d00, 0x00000c00, 0x04000004, 0x59340200,
+ 0x8c00050e, 0x04020032, 0x4a025a06, 0x00000000,
+ 0x41782000, 0x8c183510, 0x04000007, 0x59cc000c,
+ 0x82000500, 0x000000ff, 0x04000002, 0x4803c857,
+ 0x59cc200b, 0x4812580c, 0x41780000, 0x8c183512,
+ 0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00,
+ 0x040007b8, 0x82041480, 0x0000001d, 0x04001006,
+ 0x592c0404, 0x8c00051e, 0x0400000e, 0x42000800,
+ 0x0000001c, 0x4c500000, 0x4c540000, 0x83cca400,
+ 0x0000000c, 0x832cac00, 0x0000000d, 0x0201f800,
+ 0x00108b9f, 0x5c00a800, 0x5c00a000, 0x0401f7a5,
+ 0x59300011, 0x59301402, 0x480a5c06, 0x48025807,
+ 0x480e580a, 0x48165c09, 0x0201f800, 0x00108b48,
+ 0x0201f800, 0x00108b84, 0x0401f7a6, 0x592c020a,
+ 0x8c000502, 0x040007cd, 0x592c0208, 0x8c00050e,
+ 0x040207ca, 0x59300011, 0x800c0d80, 0x040007c7,
+ 0x4803c857, 0x480fc857, 0x8c183514, 0x02000000,
+ 0x0010920f, 0x80000540, 0x040007c0, 0x4807c856,
+ 0x0201f000, 0x0010920f, 0x592c020a, 0x8c000502,
+ 0x04000782, 0x59300011, 0x800001c0, 0x0400077f,
+ 0x592c0208, 0x8c00050e, 0x0402077c, 0x0201f000,
+ 0x0010920f, 0x59cc2006, 0x59cc2807, 0x0401f035,
+ 0x0401f034, 0x1c01f000, 0x4933c857, 0x5930001c,
+ 0x800001c0, 0x02020800, 0x0010984e, 0x59325808,
+ 0x592c0c08, 0x41782800, 0x41781800, 0x84040d58,
+ 0x48065c08, 0x41783000, 0x59340200, 0x8c00050e,
+ 0x04020018, 0x0201f800, 0x0002082b, 0x04020007,
+ 0x4a025a06, 0x00000000, 0x59300811, 0x4807c857,
+ 0x800409c0, 0x040208ac, 0x4a025a04, 0x00000103,
+ 0x48065807, 0x480e580a, 0x48165c09, 0x4933c857,
+ 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+ 0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d,
+ 0x592c020a, 0x8c000502, 0x040007ea, 0x59300011,
+ 0x4803c857, 0x800001c0, 0x040007e6, 0x592c0208,
+ 0x8c00050e, 0x040207e3, 0x0201f000, 0x0010920f,
+ 0x5930001c, 0x800001c0, 0x4c100000, 0x4c140000,
+ 0x02020800, 0x0010984e, 0x5c002800, 0x5c002000,
+ 0x4a026203, 0x00000002, 0x4a026403, 0x00000043,
+ 0x59325808, 0x592c020a, 0x8c000502, 0x04020018,
+ 0x40100000, 0x592c080f, 0x80040c80, 0x40140000,
+ 0x80040480, 0x04001014, 0x48126013, 0x48166011,
+ 0x59300004, 0x8c00053e, 0x04020008, 0x497a6205,
+ 0x0201f800, 0x00100f93, 0x04020009, 0x59300804,
+ 0x0201f000, 0x00106721, 0x0201f800, 0x00106f60,
+ 0x040007f7, 0x0201f000, 0x00107974, 0x4933c857,
+ 0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7eb,
+ 0x83380480, 0x00000058, 0x04021005, 0x83380480,
+ 0x00000040, 0x04001002, 0x0c01f002, 0x1c01f000,
+ 0x00108740, 0x00108740, 0x00108740, 0x00108740,
+ 0x00108740, 0x00108740, 0x00108740, 0x00108740,
+ 0x00108740, 0x00108740, 0x00108742, 0x00108740,
+ 0x00108740, 0x00108740, 0x00108740, 0x0010874f,
+ 0x00108740, 0x00108740, 0x00108740, 0x00108740,
+ 0x0010877d, 0x00108740, 0x00108740, 0x00108740,
+ 0x0201f800, 0x001005d8, 0x4933c857, 0x0201f800,
+ 0x00106dc3, 0x4a026203, 0x00000002, 0x59a80039,
+ 0x48026205, 0x59300011, 0x59300815, 0x80040c80,
+ 0x48066015, 0x0201f000, 0x00106b8a, 0x4933c857,
+ 0x0201f800, 0x00106b8a, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x0010203c, 0x5c027800, 0x42000000,
+ 0x0010b864, 0x0201f800, 0x0010aa47, 0x0201f800,
+ 0x00109037, 0x04000010, 0x4d2c0000, 0x59325808,
+ 0x4a025a04, 0x00000103, 0x59300402, 0x48025c06,
+ 0x4a025a06, 0x00000029, 0x497a5c09, 0x592c0c08,
+ 0x84040d50, 0x48065c08, 0x0201f800, 0x000202da,
+ 0x5c025800, 0x42003000, 0x00000014, 0x41782800,
+ 0x4d400000, 0x4d440000, 0x59368c03, 0x42002000,
+ 0x00000002, 0x42028000, 0x00000029, 0x0201f800,
+ 0x0010985e, 0x5c028800, 0x5c028000, 0x0201f000,
+ 0x0002077d, 0x4933c857, 0x59300808, 0x49780c09,
+ 0x4978080a, 0x58041408, 0x84081558, 0x48080c08,
+ 0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020023,
+ 0x497a5a06, 0x5930001f, 0x80000540, 0x04000017,
+ 0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000,
+ 0x4c100000, 0x4c140000, 0x58f41003, 0x40040000,
+ 0x80081480, 0x5930001f, 0x4809e803, 0x0201f800,
+ 0x00100d56, 0x5c002800, 0x5c002000, 0x5c001800,
+ 0x5c001000, 0x5c000800, 0x592c0206, 0x80000540,
+ 0x04020009, 0x0401f005, 0x592c0408, 0x8c00051c,
+ 0x04000002, 0x592c0803, 0x4807c857, 0x4a025a06,
+ 0x00000015, 0x1c01f000, 0x5930001f, 0x80000540,
+ 0x04000009, 0x4a025a06, 0x00000011, 0x5930001f,
+ 0x4c040000, 0x0201f800, 0x00100d56, 0x5c000800,
+ 0x0401f7f5, 0x4807c856, 0x4a025a06, 0x00000007,
+ 0x1c01f000, 0x83380480, 0x00000058, 0x04021007,
+ 0x83380480, 0x00000040, 0x04001004, 0x4d2c0000,
+ 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001087db,
+ 0x001087db, 0x001087db, 0x001087db, 0x001087db,
+ 0x001087dd, 0x001087db, 0x001087db, 0x00108860,
+ 0x001087db, 0x001087db, 0x001087db, 0x001087db,
+ 0x001087db, 0x001087db, 0x001087db, 0x001087db,
+ 0x001087db, 0x001087db, 0x00108910, 0x00108939,
+ 0x00108918, 0x001087db, 0x00108945, 0x0201f800,
+ 0x001005d8, 0x5930001c, 0x800001c0, 0x02020800,
+ 0x0010984e, 0x59300007, 0x8c00050e, 0x0400007c,
+ 0x8c000500, 0x0400006e, 0x8c00051c, 0x04000009,
+ 0x84000500, 0x48026007, 0x59325808, 0x592c3c08,
+ 0x841c3d58, 0x481e5c08, 0x0201f000, 0x000207dd,
+ 0x59325808, 0x592c3c08, 0x841c3d58, 0x59300007,
+ 0x8c00051c, 0x040207f3, 0x481e5c08, 0x42000000,
+ 0x00000005, 0x40000000, 0x80000040, 0x040207fe,
+ 0x59300007, 0x8c00051c, 0x040207ea, 0x59cc0a08,
+ 0x592c0204, 0x82000500, 0x000000ff, 0x82000580,
+ 0x00000048, 0x0402000c, 0x497a580b, 0x82040500,
+ 0x000000ff, 0x04000008, 0x592c0407, 0x800001c0,
+ 0x04000005, 0x0201f800, 0x0010973f, 0x0201f000,
+ 0x00100e56, 0x48065c09, 0x41782000, 0x82040500,
+ 0x00000c00, 0x04000002, 0x59cc2009, 0x82043500,
+ 0x00000fff, 0x04020027, 0x481e5c08, 0x4a025a06,
+ 0x00000000, 0x801831c0, 0x02000000, 0x00100e56,
+ 0x41782000, 0x8c183510, 0x04000002, 0x59cc200b,
+ 0x4812580c, 0x41780000, 0x8c183512, 0x04000002,
+ 0x59cc000a, 0x4802580b, 0x80100c00, 0x02001800,
+ 0x001005d8, 0x02000000, 0x00100e56, 0x82041480,
+ 0x0000001d, 0x0402100c, 0x4c500000, 0x4c540000,
+ 0x83cca400, 0x0000000c, 0x832cac00, 0x0000000d,
+ 0x0401fb67, 0x5c00a800, 0x5c00a000, 0x0201f000,
+ 0x00100e56, 0x0401fb0b, 0x0201f000, 0x00100e56,
+ 0x412c7800, 0x0201f800, 0x001007e4, 0x02000800,
+ 0x001005d8, 0x492c7809, 0x841c3d52, 0x481c7c08,
+ 0x4a025a04, 0x00000103, 0x4812580a, 0x48065c09,
+ 0x583c0404, 0x583c1005, 0x583c2208, 0x48025c04,
+ 0x480a5805, 0x48125a08, 0x0401f7c8, 0x8c000524,
+ 0x04000794, 0x59325808, 0x4c000000, 0x592c0408,
+ 0x8c00051c, 0x5c000000, 0x04020003, 0x4a026011,
+ 0xffffffff, 0x84000524, 0x0401f78a, 0x1c01f000,
+ 0x59a80039, 0x48026205, 0x59325808, 0x4a026203,
+ 0x00000002, 0x592c2408, 0x59300807, 0x4933c857,
+ 0x4807c857, 0x592c0204, 0x82000500, 0x000000ff,
+ 0x82000580, 0x00000048, 0x04020004, 0x8c102500,
+ 0x02020000, 0x00109787, 0x4a025a06, 0x00000000,
+ 0x8c040d1e, 0x04000027, 0x41780800, 0x497a5c09,
+ 0x592c1c09, 0x59300011, 0x59341200, 0x497a6205,
+ 0x8c08150e, 0x0402006e, 0x4807c857, 0x4806580a,
+ 0x80000d40, 0x04020f04, 0x59300402, 0x48025c06,
+ 0x48065807, 0x4a025a04, 0x00000103, 0x4c040000,
+ 0x4c0c0000, 0x4c100000, 0x0201f800, 0x0010959c,
+ 0x5c002000, 0x5c001800, 0x5c000800, 0x8c102512,
+ 0x0402001a, 0x4c0c0000, 0x0201f800, 0x000202c1,
+ 0x0201f800, 0x001049b2, 0x5c001800, 0x8c0c1d18,
+ 0x02000000, 0x0002077d, 0x0201f000, 0x001091d1,
+ 0x4813c857, 0x8c102518, 0x0400004b, 0x41780800,
+ 0x592c1c09, 0x820c0580, 0x00001000, 0x040007d6,
+ 0x8c102512, 0x040007d4, 0x592c7809, 0x583c080a,
+ 0x583c1c09, 0x0401f7d0, 0x4807c857, 0x592c7809,
+ 0x59300402, 0x592c1404, 0x8c08151e, 0x0402000d,
+ 0x592c1206, 0x48007c06, 0x48047807, 0x48087a06,
+ 0x84102512, 0x48107c08, 0x4c0c0000, 0x0201f800,
+ 0x001007fd, 0x403e5800, 0x0401faca, 0x0401f7d9,
+ 0x48025c06, 0x48065807, 0x583c080c, 0x583c000b,
+ 0x80040c00, 0x82041480, 0x0000001d, 0x04001006,
+ 0x583c1001, 0x480a5801, 0x49787801, 0x42000800,
+ 0x0000001c, 0x82040c00, 0x00000014, 0x4c0c0000,
+ 0x4c500000, 0x4c540000, 0x823ca400, 0x00000008,
+ 0x832cac00, 0x00000008, 0x4c100000, 0x4c3c0000,
+ 0x0401facb, 0x5c007800, 0x5c002000, 0x5c00a800,
+ 0x5c00a000, 0x84102512, 0x48125c08, 0x403e5800,
+ 0x0201f800, 0x001007fd, 0x42034000, 0x0010b4a4,
+ 0x59a1d81e, 0x80edd9c0, 0x02000800, 0x001005d8,
+ 0x48efc857, 0x58ec0009, 0x4803c857, 0x0801f800,
+ 0x0401f7ac, 0x4933c857, 0x1c01f000, 0x59301414,
+ 0x480bc857, 0x8c08151c, 0x0402000e, 0x80000540,
+ 0x4803c857, 0x0400078d, 0x80042c80, 0x0402178b,
+ 0x8c081514, 0x04020005, 0x592c080f, 0x4807c857,
+ 0x80040480, 0x48026016, 0x8408155c, 0x480a6414,
+ 0x59301007, 0x8408151e, 0x480a6007, 0x4a025c09,
+ 0x00000001, 0x0201f800, 0x0010959c, 0x497a5c09,
+ 0x8c102512, 0x04000006, 0x4d2c0000, 0x403e5800,
+ 0x0201f800, 0x001007fd, 0x5c025800, 0x82102500,
+ 0xffffedff, 0x48125c08, 0x0201f000, 0x0010920f,
+ 0x59325808, 0x592c0408, 0x8c000518, 0x04000004,
+ 0x412df800, 0x0201f000, 0x00100e6f, 0x1c01f000,
+ 0x4933c857, 0x59325808, 0x497a5c09, 0x4a025a06,
+ 0x00000000, 0x4a025a04, 0x00000103, 0x59300811,
+ 0x4807c857, 0x800409c0, 0x0402000a, 0x48065807,
+ 0x59300c02, 0x48065c06, 0x0201f800, 0x000202c1,
+ 0x0201f800, 0x001049b2, 0x0201f000, 0x0002077d,
+ 0x59340200, 0x8c00050e, 0x04020005, 0x59300811,
+ 0x0401fe55, 0x48065807, 0x0401f7f2, 0x592c0208,
+ 0x8c00050e, 0x040207fa, 0x4933c857, 0x0201f000,
+ 0x0010920f, 0x4933c857, 0x59325808, 0x812e59c0,
+ 0x02000800, 0x001005d8, 0x592c020a, 0x8c000502,
+ 0x02000800, 0x001005d8, 0x4a026206, 0x00000002,
+ 0x1c01f000, 0x5930001c, 0x800001c0, 0x02020800,
+ 0x0010984e, 0x59300007, 0x4933c857, 0x4803c857,
+ 0x8c00050e, 0x04000037, 0x8c000500, 0x04000029,
+ 0x8c00051c, 0x0400000a, 0x84000500, 0x48026007,
+ 0x59325808, 0x592c3c08, 0x481fc857, 0x841c3d58,
+ 0x481e5c08, 0x0201f000, 0x000207dd, 0x59325808,
+ 0x592c3c08, 0x841c3d58, 0x59300007, 0x8c00051c,
+ 0x040207f2, 0x481e5c08, 0x42000000, 0x00000005,
+ 0x40000000, 0x80000040, 0x040207fe, 0x59300007,
+ 0x8c00051c, 0x040207e9, 0x592c0204, 0x82000500,
+ 0x000000ff, 0x82000580, 0x00000048, 0x04020003,
+ 0x497a580b, 0x0401f002, 0x497a5c09, 0x481e5c08,
+ 0x4a025a06, 0x00000000, 0x0201f000, 0x00100e56,
+ 0x8c000524, 0x040007d9, 0x59325808, 0x4c000000,
+ 0x592c0408, 0x8c00051c, 0x5c000000, 0x04020003,
+ 0x4a026011, 0xffffffff, 0x84000524, 0x0401f7cf,
+ 0x1c01f000, 0x4933c857, 0x41780800, 0x83380480,
+ 0x00000058, 0x0402100b, 0x83380480, 0x00000040,
+ 0x04001008, 0x4d2c0000, 0x59325808, 0x812e59c0,
+ 0x0c020806, 0x5c025800, 0x0201f000, 0x0002077d,
+ 0x493bc857, 0x1c01f000, 0x001089ae, 0x001089ae,
+ 0x001089ae, 0x001089ae, 0x001089ae, 0x001089b0,
+ 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+ 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+ 0x001089ae, 0x001089ae, 0x001089ae, 0x001089ae,
+ 0x001089ae, 0x001089ae, 0x001089b5, 0x001089ae,
+ 0x001089ae, 0x001089ae, 0x0201f800, 0x001005d8,
+ 0x59cc0a08, 0x497a5807, 0x4807c857, 0x82040d00,
+ 0x00000fff, 0x59300402, 0x48025c06, 0x4a025a04,
+ 0x00000103, 0x48065c09, 0x4a025a06, 0x00000000,
+ 0x800409c0, 0x02000000, 0x000202c1, 0x59cc0009,
+ 0x4802580a, 0x82042500, 0x00000100, 0x04000002,
+ 0x59cc200b, 0x4812580c, 0x82040500, 0x00000200,
+ 0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00,
+ 0x02001800, 0x001005d8, 0x02000000, 0x000202da,
+ 0x82041480, 0x0000001d, 0x04001006, 0x592c0404,
+ 0x8c00051e, 0x0400000e, 0x42000800, 0x0000001c,
+ 0x4c500000, 0x4c540000, 0x83cca400, 0x0000000c,
+ 0x832cac00, 0x0000000d, 0x0401f9c1, 0x5c00a800,
+ 0x5c00a000, 0x0201f000, 0x000202da, 0x0401f965,
+ 0x0401f1a0, 0x83380480, 0x00000093, 0x02021800,
+ 0x001005d8, 0x83380480, 0x00000085, 0x02001800,
+ 0x001005d8, 0x0c01f001, 0x001089fd, 0x001089fb,
+ 0x001089fb, 0x00108a04, 0x001089fb, 0x001089fb,
+ 0x001089fb, 0x001089fb, 0x001089fb, 0x001089fb,
+ 0x001089fb, 0x001089fb, 0x001089fb, 0x0201f800,
+ 0x001005d8, 0x4a026203, 0x00000001, 0x493a6403,
+ 0x42000800, 0x80000040, 0x0201f000, 0x00020721,
+ 0x4933c857, 0x59cc1204, 0x480a601c, 0x59cc1404,
+ 0x0201f800, 0x00109410, 0x0400001b, 0x591c0203,
+ 0x82000580, 0x00000000, 0x04000017, 0x591c0009,
+ 0x81340580, 0x04020014, 0x4d300000, 0x4d1c0000,
+ 0x411e6000, 0x0401f9c2, 0x5c023800, 0x5c026000,
+ 0x0400000b, 0x59cc0005, 0x8c000500, 0x04020003,
+ 0x0401f98c, 0x0401f003, 0x4a023a03, 0x00000002,
+ 0x4a026403, 0x00000086, 0x0401f005, 0x0401f9a6,
+ 0x040007f5, 0x4a026403, 0x00000087, 0x4a026203,
+ 0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+ 0x00020721, 0x59340200, 0x8c00050e, 0x0400000d,
+ 0x59cc1404, 0x0201f800, 0x00109410, 0x04000009,
+ 0x591c0414, 0x8c00051a, 0x04000006, 0x4d300000,
+ 0x411e6000, 0x0201f800, 0x0010921e, 0x5c026000,
+ 0x1c01f000, 0x83380580, 0x00000013, 0x0402000a,
+ 0x59300403, 0x82000d80, 0x00000086, 0x04000012,
+ 0x82000d80, 0x00000087, 0x02020800, 0x001005d8,
+ 0x0401f00d, 0x83380580, 0x00000027, 0x04000005,
+ 0x83380580, 0x00000014, 0x02020800, 0x001005d8,
+ 0x493bc857, 0x0201f800, 0x00106bbf, 0x0201f000,
+ 0x00107911, 0x4933c857, 0x0201f000, 0x00107911,
+ 0x83380580, 0x00000013, 0x04020005, 0x59300403,
+ 0x82000480, 0x00000085, 0x0c01f04d, 0x83380580,
+ 0x00000027, 0x04020041, 0x4933c857, 0x0201f800,
+ 0x00106bbf, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42003000, 0x00000015,
+ 0x41782800, 0x42002000, 0x00000003, 0x42028000,
+ 0x00000029, 0x4d400000, 0x4d440000, 0x59368c03,
+ 0x0201f800, 0x0010985e, 0x5c028800, 0x5c028000,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00109037, 0x0400000c, 0x4d2c0000,
+ 0x59325808, 0x4a025a04, 0x00000103, 0x59300402,
+ 0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x0201f800, 0x0010912a,
+ 0x0201f000, 0x0002077d, 0x83380580, 0x00000089,
+ 0x04000005, 0x83380580, 0x0000008a, 0x02020000,
+ 0x00107974, 0x0201f800, 0x00106f60, 0x02020000,
+ 0x00107974, 0x59300a03, 0x82040580, 0x0000000a,
+ 0x0400002a, 0x82040580, 0x0000000c, 0x04000027,
+ 0x0201f800, 0x001005d8, 0x83380580, 0x00000014,
+ 0x040207ea, 0x4933c857, 0x0201f800, 0x00106bbf,
+ 0x42028000, 0x00000006, 0x0401f7d2, 0x00108aba,
+ 0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8,
+ 0x00108ab8, 0x00108ac0, 0x00108ab8, 0x00108ab8,
+ 0x00108ab8, 0x00108ab8, 0x00108ab8, 0x00108ab8,
+ 0x0201f800, 0x001005d8, 0x4933c857, 0x59a80037,
+ 0x48026206, 0x4a026203, 0x0000000a, 0x1c01f000,
+ 0x4933c857, 0x59a80037, 0x48026206, 0x4a026203,
+ 0x0000000c, 0x1c01f000, 0x83380580, 0x00000089,
+ 0x04000008, 0x83380580, 0x0000008a, 0x04000032,
+ 0x4933c857, 0x493bc857, 0x0201f000, 0x00107974,
+ 0x4933c857, 0x59325808, 0x59300a1d, 0x82040580,
+ 0x00000003, 0x04020004, 0x0201f800, 0x001049b2,
+ 0x0401f00c, 0x5930021d, 0x82000580, 0x00000001,
+ 0x04020008, 0x59300c16, 0x82040580, 0x00000039,
+ 0x0400002c, 0x82040580, 0x00000035, 0x04000029,
+ 0x4c340000, 0x41306800, 0x0201f800, 0x0002075a,
+ 0x04000010, 0x4a026203, 0x00000001, 0x4a026403,
+ 0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07,
+ 0x48066219, 0x49366009, 0x4a026406, 0x00000001,
+ 0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+ 0x40366000, 0x0201f800, 0x0002077d, 0x5c006800,
+ 0x1c01f000, 0x4933c857, 0x5930021d, 0x82000580,
+ 0x00000001, 0x04020040, 0x59300c16, 0x82040580,
+ 0x00000035, 0x04000007, 0x82040580, 0x0000001e,
+ 0x04000004, 0x82040580, 0x00000039, 0x04020036,
+ 0x4933c857, 0x4c500000, 0x4d1c0000, 0x4130a000,
+ 0x40067000, 0x0201f800, 0x001093ba, 0x04020029,
+ 0x0201f800, 0x0002075a, 0x04000026, 0x491fc857,
+ 0x4933c857, 0x83380580, 0x00000035, 0x04000004,
+ 0x83380580, 0x00000039, 0x04020002, 0x4932381c,
+ 0x493a6403, 0x4a026203, 0x00000001, 0x4a026406,
+ 0x00000001, 0x58500809, 0x4807c857, 0x48066009,
+ 0x58500c15, 0x4807c857, 0x48066415, 0x58500a15,
+ 0x4807c857, 0x48066215, 0x58500a16, 0x4807c857,
+ 0x48066216, 0x58500c19, 0x4807c857, 0x48066419,
+ 0x58500a19, 0x4807c857, 0x48066219, 0x491e601e,
+ 0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+ 0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000,
+ 0x0002077d, 0x5930021d, 0x82000580, 0x00000003,
+ 0x02000800, 0x001049b2, 0x0201f000, 0x0002077d,
+ 0x4803c856, 0x4c500000, 0x4c540000, 0x412c7800,
+ 0x4c3c0000, 0x42002800, 0x00000001, 0x82040480,
+ 0x00000101, 0x04001003, 0x42000800, 0x00000100,
+ 0x40043000, 0x42000800, 0x0000001c, 0x83cca400,
+ 0x0000000c, 0x832cac00, 0x0000000d, 0x0401f844,
+ 0x82183480, 0x0000001c, 0x592e5801, 0x812e59c0,
+ 0x02020800, 0x001007fd, 0x0201f800, 0x001007e4,
+ 0x04000017, 0x80142800, 0x4a025a04, 0x00000110,
+ 0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d,
+ 0x04021006, 0x40180800, 0x832cac00, 0x00000005,
+ 0x0401f82f, 0x0401f00a, 0x82183480, 0x0000003c,
+ 0x42000800, 0x0000003c, 0x412c7800, 0x832cac00,
+ 0x00000005, 0x0401f826, 0x0401f7e8, 0x5c007800,
+ 0x841429c0, 0x82142d40, 0x00000003, 0x48147a04,
+ 0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000,
+ 0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000,
+ 0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006,
+ 0x497a5801, 0x0201f800, 0x000202da, 0x403e5800,
+ 0x0401f7f9, 0x5c007800, 0x0201f800, 0x000202da,
+ 0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000,
+ 0x82040c00, 0x00000003, 0x8004b104, 0x0201f800,
+ 0x0010ab17, 0x5c00b000, 0x1c01f000, 0x4803c856,
+ 0x4c580000, 0x82040c00, 0x00000003, 0x8004b104,
+ 0x0201f800, 0x0010ab17, 0x5c00b000, 0x1c01f000,
+ 0x591c0c06, 0x82040580, 0x00000003, 0x04000004,
+ 0x82040580, 0x00000002, 0x0402001a, 0x4d300000,
+ 0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800,
+ 0x00109037, 0x0400000f, 0x4d400000, 0x42028000,
+ 0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800,
+ 0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c,
+ 0x0201f800, 0x000202da, 0x0201f800, 0x0010912a,
+ 0x0201f800, 0x00107911, 0x5c025800, 0x5c026000,
+ 0x1c01f000, 0x59cc0005, 0x8c000500, 0x0402000b,
+ 0x591c0406, 0x82000580, 0x00000002, 0x04020007,
+ 0x591c0c03, 0x82040580, 0x00000085, 0x04000003,
+ 0x82040580, 0x0000008b, 0x1c01f000, 0x4933c857,
+ 0x4d3c0000, 0x42027800, 0x00000002, 0x59300406,
+ 0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+ 0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857,
+ 0x59300406, 0x82000c80, 0x00000012, 0x02021800,
+ 0x001005d8, 0x0c01f001, 0x00108c01, 0x00108bfe,
+ 0x00108bfe, 0x00108c29, 0x00108bfc, 0x00108bfe,
+ 0x00108c1a, 0x00108bfe, 0x00108bfc, 0x001065f4,
+ 0x00108bfe, 0x00108bfe, 0x00108bfe, 0x00108bfc,
+ 0x00108bfc, 0x00108bfc, 0x00108cf9, 0x00108bfe,
+ 0x0201f800, 0x001005d8, 0x4803c856, 0x80000580,
+ 0x1c01f000, 0x4803c856, 0x8d3e7d02, 0x04020016,
+ 0x0201f800, 0x00109037, 0x0400000f, 0x59325808,
+ 0x41780800, 0x4d400000, 0x42028000, 0x00000005,
+ 0x0201f800, 0x00104e70, 0x5c028000, 0x0201f800,
+ 0x0010959c, 0x0201f800, 0x001091cc, 0x0201f800,
+ 0x000202da, 0x0201f800, 0x00107911, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800,
+ 0x001048d9, 0x0402000c, 0x4d400000, 0x42028000,
+ 0x00000010, 0x0201f800, 0x0010a1d1, 0x4a026406,
+ 0x00000006, 0x4a026203, 0x00000007, 0x5c028000,
+ 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x0c01f001, 0x00108c43,
+ 0x00108cb0, 0x00108c5a, 0x00108cc3, 0x00108cab,
+ 0x00108c41, 0x00108c43, 0x00108c43, 0x00108c47,
+ 0x00108c43, 0x00108c43, 0x00108c43, 0x00108c43,
+ 0x00108c5a, 0x0201f800, 0x001005d8, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x0401f7b8, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x59300406, 0x82000580,
+ 0x00000003, 0x040207b4, 0x59300203, 0x82000580,
+ 0x0000000d, 0x040007b0, 0x8d3e7d02, 0x040207ae,
+ 0x4d340000, 0x59326809, 0x0201f800, 0x001049b2,
+ 0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c,
+ 0x48026004, 0x0201f800, 0x00106c4b, 0x59300406,
+ 0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02,
+ 0x04020041, 0x497a621d, 0x59300203, 0x82000580,
+ 0x0000000d, 0x04000003, 0x4a02621d, 0x00000003,
+ 0x0401fbcb, 0x04000024, 0x4d2c0000, 0x4d400000,
+ 0x59325808, 0x0201f800, 0x001091cc, 0x592c0408,
+ 0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512,
+ 0x48025c08, 0x592c0809, 0x40065800, 0x0201f800,
+ 0x001007fd, 0x5c025800, 0x4d400000, 0x42028000,
+ 0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004,
+ 0x42028000, 0x00000002, 0x0401f001, 0x0201f800,
+ 0x00104e70, 0x5c028000, 0x0201f800, 0x0010959c,
+ 0x0201f800, 0x000202da, 0x497a6008, 0x5c028000,
+ 0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000,
+ 0x59326809, 0x0201f800, 0x001049b2, 0x5c026800,
+ 0x0201f800, 0x00107911, 0x0401f00b, 0x4a026403,
+ 0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+ 0x00000002, 0x42000800, 0x8000404b, 0x0201f800,
+ 0x00020721, 0x5c03e000, 0x02020800, 0x00106c55,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x0201f800,
+ 0x00106c4b, 0x0201f800, 0x00100e99, 0x0401f7ab,
+ 0x598c000d, 0x81300580, 0x04020004, 0x0201f800,
+ 0x00106e8e, 0x0402001b, 0x0201f800, 0x001068d3,
+ 0x04020006, 0x59300c03, 0x82040580, 0x00000040,
+ 0x0400078b, 0x0401f79d, 0x0201f800, 0x00106b6c,
+ 0x04000010, 0x0201f800, 0x001005d8, 0x0401f813,
+ 0x04020004, 0x0201f800, 0x00106e62, 0x04020009,
+ 0x0201f800, 0x001067ae, 0x040207f4, 0x59300c03,
+ 0x82040580, 0x00000040, 0x04000779, 0x0401f78b,
+ 0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
+ 0x001005d8, 0x0c01f75e, 0x417a3000, 0x42032000,
+ 0x0000bf32, 0x59900004, 0x81300580, 0x04000009,
+ 0x83932400, 0x00000010, 0x811a3000, 0x83180480,
+ 0x00000005, 0x040017f8, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x59300004, 0x8c00053e, 0x04000010,
+ 0x8c00050c, 0x0402000e, 0x8c000516, 0x04020006,
+ 0x82000d00, 0x0000001f, 0x82040580, 0x00000005,
+ 0x04020004, 0x42000000, 0x00000003, 0x0401f005,
+ 0x42000000, 0x00000001, 0x0401f002, 0x59300203,
+ 0x1c01f000, 0x4933c857, 0x0201f800, 0x00106c55,
+ 0x4df00000, 0x59300203, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x0c01f001, 0x00108d13,
+ 0x00108d30, 0x00108d17, 0x00108d11, 0x00108d11,
+ 0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11,
+ 0x00108d11, 0x00108d11, 0x00108d11, 0x00108d11,
+ 0x00108d11, 0x0201f800, 0x001005d8, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x0401f6e8, 0x5c03e000,
+ 0x02000800, 0x00106c4b, 0x4d2c0000, 0x59325808,
+ 0x59300403, 0x82000580, 0x00000052, 0x02000800,
+ 0x00101231, 0x0401fb16, 0x02000800, 0x001005d8,
+ 0x4a025a06, 0x00000005, 0x0201f800, 0x000202da,
+ 0x0201f800, 0x00104c19, 0x0201f800, 0x00107911,
+ 0x5c025800, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x598c000d, 0x81300580, 0x0402001a, 0x59300004,
+ 0x8c000520, 0x04000004, 0x84000520, 0x48026004,
+ 0x0401f01a, 0x42001000, 0x0010b7f6, 0x50081000,
+ 0x58080002, 0x82000580, 0x00000100, 0x0400000a,
+ 0x5808000c, 0x81300580, 0x02020800, 0x001005d8,
+ 0x0201f800, 0x001068d3, 0x02020800, 0x001005d8,
+ 0x0401f7cf, 0x0201f800, 0x00106e8e, 0x0402000c,
+ 0x59300004, 0x8c000520, 0x04000004, 0x84000520,
+ 0x48026004, 0x0401f7c6, 0x0201f800, 0x001068d3,
+ 0x040007c3, 0x0201f800, 0x001005d8, 0x59300203,
+ 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857,
+ 0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+ 0x0c01f001, 0x00108d7c, 0x00108e41, 0x00108f79,
+ 0x00108d88, 0x00107911, 0x00108d7c, 0x0010a1c0,
+ 0x0002077d, 0x00108e41, 0x001065ce, 0x00108fda,
+ 0x00108d77, 0x00108d77, 0x00108d77, 0x00108d77,
+ 0x00108d77, 0x001096eb, 0x001096eb, 0x0201f800,
+ 0x001005d8, 0x0401fbd5, 0x02000000, 0x0010801c,
+ 0x1c01f000, 0x0201f800, 0x00106c55, 0x0201f800,
+ 0x00106bbf, 0x0201f800, 0x00106c4b, 0x0201f000,
+ 0x0002077d, 0x4a026206, 0x00000001, 0x1c01f000,
+ 0x42000000, 0x0010b872, 0x0201f800, 0x0010aa47,
+ 0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401faa8,
+ 0x04000007, 0x59325808, 0x592c0208, 0x8400054c,
+ 0x48025a08, 0x42028000, 0x00000006, 0x0201f800,
+ 0x00106c55, 0x0401ff4c, 0x4803c857, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f806,
+ 0x0201f800, 0x00106c4b, 0x5c028000, 0x5c025800,
+ 0x1c01f000, 0x00108e40, 0x00108db5, 0x00108dc3,
+ 0x00108de5, 0x00108e11, 0x00108db3, 0x00108d7c,
+ 0x00108d7c, 0x00108d7c, 0x00108db3, 0x00108db3,
+ 0x00108db3, 0x00108db3, 0x00108dc3, 0x0201f800,
+ 0x001005d8, 0x598c000d, 0x81300580, 0x04020004,
+ 0x0201f800, 0x00106e8e, 0x04020038, 0x0201f800,
+ 0x001068d3, 0x0400003b, 0x0201f800, 0x00106b6c,
+ 0x04000032, 0x0201f800, 0x001005d8, 0x497a621d,
+ 0x812e59c0, 0x02000800, 0x001005d8, 0x592c0204,
+ 0x82000500, 0x000000ff, 0x82000580, 0x00000014,
+ 0x04000003, 0x4a02621d, 0x00000003, 0x592c0a08,
+ 0x0201f800, 0x00104e70, 0x0201f800, 0x0010959c,
+ 0x0201f800, 0x000202da, 0x497a6008, 0x4a026403,
+ 0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+ 0x00000002, 0x4a026004, 0x8000404b, 0x0201f800,
+ 0x00106c4b, 0x42000800, 0x8000404b, 0x0201f000,
+ 0x00020721, 0x0401fef1, 0x04020004, 0x0201f800,
+ 0x00106e62, 0x04020009, 0x0201f800, 0x001067ae,
+ 0x040207d2, 0x59300c03, 0x82040580, 0x00000040,
+ 0x04000008, 0x0401f7d2, 0x59300203, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ae,
+ 0x0201f800, 0x00106c4b, 0x812e59c0, 0x04000013,
+ 0x592c0a08, 0x0201f800, 0x00104e70, 0x0201f800,
+ 0x0010959c, 0x0201f800, 0x000202da, 0x59300203,
+ 0x82000580, 0x0000000d, 0x04000008, 0x0201f800,
+ 0x00106c4b, 0x4d340000, 0x59326809, 0x0201f800,
+ 0x001049b2, 0x5c026800, 0x0201f800, 0x00107911,
+ 0x0401f030, 0x812e59c0, 0x02000800, 0x001005d8,
+ 0x0201f800, 0x0010940a, 0x04020004, 0x0201f800,
+ 0x00100e99, 0x0401f7aa, 0x0201f800, 0x00106c4b,
+ 0x592c0208, 0x8400050c, 0x48025a08, 0x592c0406,
+ 0x800000c2, 0x800008c4, 0x80040c00, 0x48066206,
+ 0x42000000, 0x10000000, 0x41300800, 0x0201f800,
+ 0x00100b94, 0x0400000d, 0x592c0208, 0x8c00051c,
+ 0x04020006, 0x8400055c, 0x48025a08, 0x4a026206,
+ 0x00000002, 0x0401f00f, 0x4d300000, 0x0201f800,
+ 0x001012e5, 0x5c026000, 0x59300203, 0x82000580,
+ 0x00000004, 0x04020007, 0x4d380000, 0x42027000,
+ 0x00000048, 0x0201f800, 0x000207a1, 0x5c027000,
+ 0x1c01f000, 0x42000000, 0x0010b86e, 0x0201f800,
+ 0x0010aa47, 0x59300203, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x4803c857, 0x0c01f001,
+ 0x00108e5a, 0x00108d85, 0x00108e5c, 0x00108e5a,
+ 0x00108e5c, 0x00108e5c, 0x00108d7d, 0x00108e5a,
+ 0x00108d79, 0x00108e5a, 0x00108e5a, 0x00108e5a,
+ 0x00108e5a, 0x00108e5a, 0x0201f800, 0x001005d8,
+ 0x4d340000, 0x4d2c0000, 0x59326809, 0x59340400,
+ 0x82000500, 0x000000ff, 0x82000c80, 0x0000000c,
+ 0x02021800, 0x001005d8, 0x59303403, 0x82180d80,
+ 0x00000004, 0x04020004, 0x42000000, 0x00000001,
+ 0x0401f006, 0x82180d80, 0x00000000, 0x04020003,
+ 0x42000000, 0x00000001, 0x4803c857, 0x0c01f804,
+ 0x5c025800, 0x5c026800, 0x1c01f000, 0x00108e83,
+ 0x00108f22, 0x00108e85, 0x00108eba, 0x00108e85,
+ 0x00108f3f, 0x00108e85, 0x00108e8f, 0x00108e83,
+ 0x00108f3f, 0x00108e83, 0x00108e9e, 0x0201f800,
+ 0x001005d8, 0x59300403, 0x82000d80, 0x00000016,
+ 0x0400002e, 0x82000d80, 0x00000004, 0x0400002b,
+ 0x82000d80, 0x00000002, 0x04000028, 0x0401fabf,
+ 0x04000079, 0x59300403, 0x82000d80, 0x00000022,
+ 0x040000ae, 0x82000d80, 0x00000039, 0x040000b3,
+ 0x82000d80, 0x00000035, 0x040000b0, 0x82000d80,
+ 0x0000001e, 0x0400001b, 0x0401f999, 0x04000007,
+ 0x0201f800, 0x00109597, 0x04020004, 0x0201f800,
+ 0x00104a14, 0x0401f011, 0x59300403, 0x82000d80,
+ 0x00000001, 0x04020004, 0x0201f800, 0x001049e7,
+ 0x0400000a, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010801c,
+ 0x0201f000, 0x00107911, 0x0401f97d, 0x04000004,
+ 0x0201f800, 0x00109597, 0x040000a9, 0x59300c03,
+ 0x82040580, 0x00000016, 0x04000056, 0x82040580,
+ 0x00000002, 0x04020034, 0x59a80026, 0x8c000502,
+ 0x04020013, 0x0201f800, 0x0010513b, 0x04020010,
+ 0x0201f800, 0x00105151, 0x04020006, 0x42000000,
+ 0x00000001, 0x0201f800, 0x00105113, 0x0401f094,
+ 0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
+ 0x0201f800, 0x001050a2, 0x0401f08d, 0x59340403,
+ 0x82000580, 0x000007fc, 0x04000008, 0x59a80026,
+ 0x8c00050a, 0x04020084, 0x59340212, 0x82000500,
+ 0x0000ff00, 0x04000082, 0x59340412, 0x82000500,
+ 0x000000ff, 0x04000010, 0x80000040, 0x48026c12,
+ 0x497a6008, 0x4a026406, 0x00000007, 0x4a026206,
+ 0x00000398, 0x497a6205, 0x0201f800, 0x0002075a,
+ 0x04000005, 0x49366009, 0x4a026406, 0x00000001,
+ 0x0401f020, 0x59300403, 0x82000d80, 0x00000002,
+ 0x0402000d, 0x59340403, 0x82000580, 0x000007fe,
+ 0x04020009, 0x59a80026, 0x84000540, 0x48035026,
+ 0x0201f800, 0x00104237, 0x0201f800, 0x0010801c,
+ 0x0401f00c, 0x0201f800, 0x0010801c, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x0010203c, 0x5c027800,
+ 0x42000000, 0x0010b864, 0x0201f800, 0x0010aa47,
+ 0x0201f800, 0x00102074, 0x0201f000, 0x00107911,
+ 0x42000800, 0x00000003, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000002,
+ 0x0201f000, 0x0010672b, 0x0401f915, 0x04020793,
+ 0x0201f800, 0x00102074, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x0010203c, 0x5c027800, 0x42000000,
+ 0x0010b864, 0x0201f800, 0x0010aa47, 0x42003000,
+ 0x00000018, 0x41782800, 0x42002000, 0x00000000,
+ 0x4d400000, 0x4d440000, 0x59368c03, 0x42028000,
+ 0x00000029, 0x0201f800, 0x0010985e, 0x5c028800,
+ 0x5c028000, 0x0201f000, 0x00107911, 0x0201f800,
+ 0x00104a14, 0x0401f7c8, 0x42000000, 0x0010b86d,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x00107b76,
+ 0x040207c1, 0x1c01f000, 0x4d380000, 0x59327403,
+ 0x0201f800, 0x001093ba, 0x5c027000, 0x02020000,
+ 0x0002077d, 0x836c0580, 0x00000003, 0x04000004,
+ 0x4a026206, 0x00000002, 0x1c01f000, 0x59300403,
+ 0x48026416, 0x4a02621d, 0x00000001, 0x4a026403,
+ 0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+ 0x00000002, 0x42000800, 0x8000004b, 0x0201f000,
+ 0x00020721, 0x0201f800, 0x00102074, 0x0201f800,
+ 0x0010801c, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x497a6008, 0x4a026406,
+ 0x00000007, 0x4a026206, 0x00000398, 0x497a6205,
+ 0x1c01f000, 0x42000000, 0x0010b870, 0x0201f800,
+ 0x0010aa47, 0x4d340000, 0x59326809, 0x59300203,
+ 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x4803c857, 0x0c01f803, 0x5c026800, 0x1c01f000,
+ 0x00108f96, 0x00108d85, 0x00108f96, 0x00108f96,
+ 0x00108f96, 0x00108f96, 0x00108f96, 0x00108f96,
+ 0x00108f96, 0x00108d85, 0x00108f98, 0x00108d85,
+ 0x00108fa0, 0x00108f96, 0x0201f800, 0x001005d8,
+ 0x4a026403, 0x0000008b, 0x4a026203, 0x0000000b,
+ 0x42000800, 0x8000404b, 0x0201f000, 0x00020721,
+ 0x59300a1d, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42003000, 0x00000011,
+ 0x0201f800, 0x0010a942, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x41306800, 0x0201f800,
+ 0x0002075a, 0x04000008, 0x49366009, 0x4d300000,
+ 0x40366000, 0x0201f800, 0x00107911, 0x5c026000,
+ 0x0401f002, 0x40366000, 0x497a6008, 0x4a026406,
+ 0x00000001, 0x4a026403, 0x00000001, 0x0201f800,
+ 0x00103b25, 0x04000011, 0x4a026406, 0x00000004,
+ 0x4a026203, 0x00000007, 0x4a026420, 0x00000001,
+ 0x42003000, 0x00000004, 0x4d400000, 0x42028000,
+ 0x00000029, 0x41782800, 0x0201f800, 0x0010a43e,
+ 0x5c028000, 0x1c01f000, 0x42000800, 0x0000000b,
+ 0x0201f800, 0x00104571, 0x4a026203, 0x00000001,
+ 0x0201f000, 0x0010672b, 0x42000000, 0x0010b876,
+ 0x0201f800, 0x0010aa47, 0x59300203, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x4803c857,
+ 0x0c01f001, 0x0010900b, 0x00108ff3, 0x00108ff7,
+ 0x0010900c, 0x00108ff5, 0x00108ff3, 0x00108ff3,
+ 0x00108ff3, 0x00108ff3, 0x00108ff3, 0x00108ff3,
+ 0x00108ff3, 0x00108ff3, 0x00108ff3, 0x0201f800,
+ 0x001005d8, 0x0201f800, 0x00100e99, 0x4d2c0000,
+ 0x59325808, 0x4a025a06, 0x00000006, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x497a6008, 0x4a02621d,
+ 0x0000000a, 0x4a026403, 0x00000085, 0x4a026203,
+ 0x00000009, 0x4a026406, 0x00000002, 0x42000800,
+ 0x8000404b, 0x0201f000, 0x00020721, 0x1c01f000,
+ 0x0201f800, 0x00106c55, 0x4df00000, 0x0401fcc7,
+ 0x04020004, 0x0201f800, 0x00106e62, 0x0402000c,
+ 0x0201f800, 0x001067ae, 0x04020005, 0x5c03e000,
+ 0x0201f800, 0x00106c4b, 0x0401f7dd, 0x0201f800,
+ 0x00106b6c, 0x02020800, 0x001005d8, 0x5c03e000,
+ 0x0201f800, 0x00106c4b, 0x59300203, 0x82000d80,
+ 0x00000003, 0x02000800, 0x001005d8, 0x82000c80,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f7ba,
+ 0x4803c856, 0x59a8000e, 0x59a80867, 0x80040400,
+ 0x80080480, 0x04021004, 0x82000540, 0x00000001,
+ 0x1c01f000, 0x80000580, 0x1c01f000, 0x4803c856,
+ 0x4c080000, 0x59301008, 0x82081500, 0xfff00000,
+ 0x5c001000, 0x1c01f000, 0x4803c856, 0x4d300000,
+ 0x0201f800, 0x0002075a, 0x0400000a, 0x0401f82f,
+ 0x4d380000, 0x42027000, 0x0000004b, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+ 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+ 0x0201f800, 0x00107942, 0x0400001b, 0x0401f81f,
+ 0x4d300000, 0x0201f800, 0x00106c55, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x00106ab4, 0x0201f800,
+ 0x001067fd, 0x5c027800, 0x0201f800, 0x0010a2ff,
+ 0x0201f800, 0x00106c4b, 0x5c026000, 0x8d3e7d3e,
+ 0x0402000b, 0x4d380000, 0x42027000, 0x0000004c,
+ 0x0201f800, 0x000207a1, 0x5c027000, 0x82000540,
+ 0x00000001, 0x5c026000, 0x1c01f000, 0x0201f800,
+ 0x0002077d, 0x0401f7fa, 0x592c0407, 0x494a6017,
+ 0x494e6018, 0x49366009, 0x492e6008, 0x4a026406,
+ 0x00000003, 0x800000c2, 0x800008c4, 0x80040400,
+ 0x48026206, 0x1c01f000, 0x493bc857, 0x4d300000,
+ 0x0201f800, 0x0002075a, 0x0400000d, 0x0401ffef,
+ 0x4d400000, 0x42028000, 0x00000005, 0x0401f80d,
+ 0x5c028000, 0x8d3e7d3e, 0x04020007, 0x0201f800,
+ 0x000207a1, 0x82000540, 0x00000001, 0x5c026000,
+ 0x1c01f000, 0x0201f800, 0x0002077d, 0x0401f7fa,
+ 0x4803c856, 0x0201f800, 0x00106c55, 0x4d3c0000,
+ 0x4d440000, 0x59368c03, 0x42027800, 0x00000001,
+ 0x0201f800, 0x001069b6, 0x0201f800, 0x0010692e,
+ 0x0201f800, 0x001067fd, 0x0201f800, 0x0010a2ff,
+ 0x5c028800, 0x5c027800, 0x0201f000, 0x00106c4b,
+ 0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a,
+ 0x0400000f, 0x481a601c, 0x48ee6021, 0x49366009,
+ 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+ 0x42027000, 0x0000001f, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+ 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+ 0x0002075a, 0x0400000e, 0x48ee6021, 0x49366009,
+ 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+ 0x42027000, 0x00000055, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+ 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+ 0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021,
+ 0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+ 0x4d380000, 0x42027000, 0x0000003d, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+ 0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
+ 0x0201f800, 0x00107942, 0x04000014, 0x49366009,
+ 0x492fc857, 0x4933c857, 0x592c0404, 0x8c00051e,
+ 0x04000003, 0x48efc857, 0x48ee6021, 0x4a026406,
+ 0x00000001, 0x492e6008, 0x4d380000, 0x42027000,
+ 0x00000000, 0x0201f800, 0x000207a1, 0x5c027000,
+ 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
+ 0x4803c856, 0x4d300000, 0x0201f800, 0x0002075a,
+ 0x0400000f, 0x48ee6021, 0x481a601c, 0x49366009,
+ 0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
+ 0x42027000, 0x00000044, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+ 0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
+ 0x0002075a, 0x0400000f, 0x481a601c, 0x48ee6021,
+ 0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+ 0x4d380000, 0x42027000, 0x00000049, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+ 0x5c026000, 0x1c01f000, 0x59300009, 0x80001540,
+ 0x02000800, 0x001005d8, 0x5808040b, 0x4803c856,
+ 0x80000040, 0x04001002, 0x4800140b, 0x1c01f000,
+ 0x4803c856, 0x59300403, 0x82000d80, 0x00000002,
+ 0x04000015, 0x82000d80, 0x00000003, 0x04000012,
+ 0x82000d80, 0x00000004, 0x0400000f, 0x82000d80,
+ 0x00000008, 0x0400000c, 0x82000d80, 0x0000000a,
+ 0x04000009, 0x599c0819, 0x8c040d0e, 0x04000004,
+ 0x82000d80, 0x00000000, 0x04000003, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4803c856, 0x4c000000,
+ 0x4d2c0000, 0x59300406, 0x82000580, 0x00000004,
+ 0x0400001d, 0x59300008, 0x80025d40, 0x800001c0,
+ 0x04000019, 0x0201f800, 0x00109597, 0x04000014,
+ 0x59300406, 0x82004580, 0x00000010, 0x04000010,
+ 0x82004580, 0x00000011, 0x0400000d, 0x82004580,
+ 0x00000003, 0x0400000c, 0x82004580, 0x00000002,
+ 0x04000009, 0x82004580, 0x0000000a, 0x04000006,
+ 0x592c0404, 0x8c00051e, 0x04000003, 0x80000580,
+ 0x0401f003, 0x82000540, 0x00000001, 0x5c025800,
+ 0x5c000000, 0x1c01f000, 0x4803c856, 0x4d300000,
+ 0x0201f800, 0x00107942, 0x04000013, 0x49366009,
+ 0x48ee6021, 0x4a026406, 0x00000001, 0x492e6008,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x5c027800, 0x4d380000, 0x42027000, 0x00000028,
+ 0x0201f800, 0x000207a1, 0x5c027000, 0x82000540,
+ 0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856,
+ 0x83380580, 0x00000015, 0x0402000d, 0x59a80016,
+ 0x82000580, 0x00000074, 0x04020009, 0x0201f800,
+ 0x0010462a, 0x4a026203, 0x00000001, 0x4a026403,
+ 0x00000029, 0x0201f000, 0x0010672b, 0x0201f800,
+ 0x0010801c, 0x0201f000, 0x0002077d, 0x4803c856,
+ 0x83380580, 0x00000016, 0x04020007, 0x42000800,
+ 0x00000004, 0x0201f800, 0x00104571, 0x0201f000,
+ 0x00107b38, 0x83380580, 0x00000015, 0x04020013,
+ 0x59a80016, 0x82000580, 0x00000014, 0x0402000f,
+ 0x0201f800, 0x0010468d, 0x0201f800, 0x0010846f,
+ 0x0402000a, 0x59340404, 0x80000540, 0x04000007,
+ 0x42000800, 0x00000006, 0x0201f800, 0x00104571,
+ 0x0201f000, 0x00107b38, 0x0201f800, 0x0010801c,
+ 0x0201f000, 0x0002077d, 0x4803c856, 0x592c0206,
+ 0x82000580, 0x00000005, 0x04000002, 0x1c01f000,
+ 0x4803c856, 0x592c0208, 0x8400054a, 0x48025a08,
+ 0x1c01f000, 0x497a6205, 0x497a6008, 0x4a026203,
+ 0x00000001, 0x4a026403, 0x00000050, 0x42000800,
+ 0x80000043, 0x0201f000, 0x00020721, 0x4933c857,
+ 0x4d340000, 0x59326809, 0x59340200, 0x8c00050e,
+ 0x04000006, 0x59300406, 0x82000c80, 0x00000012,
+ 0x04021004, 0x0c01f806, 0x5c026800, 0x1c01f000,
+ 0x0201f800, 0x00108d7c, 0x0401f7fc, 0x00108d7c,
+ 0x001091fd, 0x00109201, 0x00109204, 0x0010a49b,
+ 0x0010a4b8, 0x0010a4bc, 0x00108d7c, 0x00108d7c,
+ 0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c,
+ 0x00108d7c, 0x00108d7c, 0x00108d7c, 0x00108d7c,
+ 0x00108d7c, 0x4803c856, 0x40000000, 0x40000000,
+ 0x1c01f000, 0x40000000, 0x40000000, 0x1c01f000,
+ 0x5930001c, 0x4803c857, 0x59300414, 0x4933c857,
+ 0x4803c857, 0x8c000502, 0x04000005, 0x84000502,
+ 0x84000540, 0x48026414, 0x1c01f000, 0x42000000,
+ 0xd0000000, 0x41300800, 0x0201f800, 0x00100b94,
+ 0x0401f80a, 0x04020008, 0x59a80037, 0x82000400,
+ 0x0000000a, 0x48026205, 0x59300414, 0x84000542,
+ 0x48026414, 0x1c01f000, 0x4933c857, 0x4d340000,
+ 0x59326809, 0x59340200, 0x8c00050e, 0x02000800,
+ 0x001005d8, 0x5930001c, 0x80000540, 0x0402002f,
+ 0x59a80021, 0x80000540, 0x0402002a, 0x4d1c0000,
+ 0x41323800, 0x0201f800, 0x0002075a, 0x04000023,
+ 0x4932381c, 0x591c0414, 0x84000542, 0x48023c14,
+ 0x49366009, 0x591c0406, 0x82000580, 0x00000003,
+ 0x04000006, 0x591c0202, 0x48026419, 0x591c0402,
+ 0x48026219, 0x0401f005, 0x591c0202, 0x48026219,
+ 0x591c0402, 0x48026419, 0x491e601e, 0x4a026406,
+ 0x00000001, 0x4a026403, 0x00000035, 0x4a026203,
+ 0x00000001, 0x42000800, 0x80000040, 0x0201f800,
+ 0x00020721, 0x411e6000, 0x5c023800, 0x80000580,
+ 0x5c026800, 0x1c01f000, 0x411e6000, 0x5c023800,
+ 0x59a80039, 0x48026205, 0x82000540, 0x00000001,
+ 0x0401f7f8, 0x4933c857, 0x4d2c0000, 0x4932381c,
+ 0x4a026202, 0x0000ffff, 0x591e5808, 0x591c0007,
+ 0x8c00051e, 0x04000005, 0x8400051e, 0x48023807,
+ 0x497a5c09, 0x0401f014, 0x592c0408, 0x8c000518,
+ 0x04000011, 0x84000518, 0x48025c08, 0x4a025c09,
+ 0x00000001, 0x0401fb2f, 0x497a5c09, 0x592c0408,
+ 0x8c000512, 0x04000008, 0x4d2c0000, 0x84000512,
+ 0x48025c08, 0x592e5809, 0x0201f800, 0x001007fd,
+ 0x5c025800, 0x59a80039, 0x48026205, 0x591c0214,
+ 0x48026216, 0x82000d80, 0x00000001, 0x04000008,
+ 0x4a023a03, 0x00000002, 0x82000580, 0x00000005,
+ 0x04000008, 0x497a6015, 0x0401f01e, 0x591c0007,
+ 0x84000540, 0x48023807, 0x4a023a03, 0x00000004,
+ 0x591c0414, 0x4803c857, 0x8400051c, 0x84000554,
+ 0x48023c14, 0x592c000f, 0x40001000, 0x591c0816,
+ 0x80040480, 0x040217f0, 0x591c0016, 0x82000500,
+ 0xfffffffc, 0x48026015, 0x48023816, 0x591c0a14,
+ 0x4807c857, 0x82040d80, 0x00000005, 0x04020005,
+ 0x480bc857, 0x4803c857, 0x4a023812, 0xffffffff,
+ 0x591c0402, 0x48026419, 0x591c0202, 0x48026219,
+ 0x591e6809, 0x49366009, 0x4a026406, 0x00000001,
+ 0x4a026403, 0x00000039, 0x4a026203, 0x00000001,
+ 0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x59300414,
+ 0x8c000514, 0x04000015, 0x8c00051c, 0x04020012,
+ 0x59300016, 0x80100480, 0x04001006, 0x04000005,
+ 0x59300414, 0x84000514, 0x8400055c, 0x0401f009,
+ 0x48126016, 0x48126012, 0x40100000, 0x592c180f,
+ 0x800c0480, 0x48026011, 0x59300414, 0x84000514,
+ 0x48026414, 0x1c01f000, 0x4933c857, 0x8c00051c,
+ 0x04020006, 0x59300012, 0x48026016, 0x59300414,
+ 0x8400055c, 0x48026414, 0x1c01f000, 0x59300c03,
+ 0x4933c857, 0x4807c857, 0x82040480, 0x00000034,
+ 0x04001006, 0x82040480, 0x0000003c, 0x04021003,
+ 0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
+ 0x0401f7fd, 0x41780800, 0x59a81035, 0x42000000,
+ 0x00000032, 0x0201f800, 0x001066a0, 0x800811c0,
+ 0x04020003, 0x42001000, 0x00000014, 0x480b5037,
+ 0x59a81036, 0x480b502d, 0x41780800, 0x42000000,
+ 0x00000064, 0x0201f800, 0x001066a0, 0x800811c0,
+ 0x04020003, 0x42001000, 0x00000014, 0x480b5038,
+ 0x82081400, 0x0000000a, 0x480b5039, 0x42000800,
+ 0x00000001, 0x0201f800, 0x00106c78, 0x42000000,
+ 0x30000000, 0x40080800, 0x0201f800, 0x00100b68,
+ 0x42000800, 0x00000003, 0x59a81010, 0x0201f800,
+ 0x00106c78, 0x0201f000, 0x00104906, 0x4a035037,
+ 0x00000028, 0x4a035038, 0x00000014, 0x4a03502d,
+ 0x000007d0, 0x42001000, 0x0000001e, 0x480b5039,
+ 0x42000800, 0x00000001, 0x0201f800, 0x00106c78,
+ 0x42000000, 0x30000000, 0x40080800, 0x0201f800,
+ 0x00100b68, 0x42000800, 0x00000003, 0x59a81010,
+ 0x0201f000, 0x00106c78, 0x4933c857, 0x4d2c0000,
+ 0x59300403, 0x82000580, 0x0000003e, 0x04020005,
+ 0x59325817, 0x812e59c0, 0x02020800, 0x001007f4,
+ 0x5c025800, 0x1c01f000, 0x4937c857, 0x4d300000,
+ 0x0201f800, 0x0002075a, 0x04000011, 0x49366009,
+ 0x4a026406, 0x00000001, 0x492e6008, 0x42000800,
+ 0x00000009, 0x0201f800, 0x00104571, 0x4d380000,
+ 0x42027000, 0x00000033, 0x0201f800, 0x000207a1,
+ 0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
+ 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c580000,
+ 0x4d3c0000, 0x59325808, 0x83380580, 0x00000015,
+ 0x04020022, 0x59a8b016, 0x82580c80, 0x00000019,
+ 0x04001003, 0x4200b000, 0x00000018, 0x8058b104,
+ 0x0401fa07, 0x80000580, 0x0401fa17, 0x832cac00,
+ 0x00000009, 0x83cca400, 0x00000006, 0x0201f800,
+ 0x0010ab17, 0x42027800, 0x00000001, 0x592c100a,
+ 0x8c081518, 0x04020006, 0x59a80010, 0x592c100d,
+ 0x80080580, 0x04020006, 0x417a7800, 0x59301009,
+ 0x58081403, 0x0201f800, 0x001020a1, 0x0201f800,
+ 0x00107b38, 0x0401f008, 0x4200b000, 0x00000002,
+ 0x0401fa09, 0x0201f800, 0x0010801c, 0x0201f800,
+ 0x0002077d, 0x5c027800, 0x5c00b000, 0x5c025800,
+ 0x1c01f000, 0x4933c856, 0x49366009, 0x4a026406,
+ 0x00000001, 0x492e6008, 0x4d380000, 0x42027000,
+ 0x0000004d, 0x0201f800, 0x000207a1, 0x5c027000,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x4803c856,
+ 0x4d2c0000, 0x83380580, 0x00000015, 0x04020027,
+ 0x59a80816, 0x59325808, 0x5930040b, 0x800000c4,
+ 0x80040580, 0x04020021, 0x4c500000, 0x4c540000,
+ 0x4c580000, 0x83cca400, 0x00000006, 0x4050a800,
+ 0x5930b40b, 0x0201f800, 0x0010ab28, 0x83cca400,
+ 0x00000006, 0x592cb205, 0x832cac00, 0x00000006,
+ 0x0201f800, 0x0010ab17, 0x592e5801, 0x812e59c0,
+ 0x040207f9, 0x5931d821, 0x58ef400b, 0x58ee580d,
+ 0x4a025a04, 0x00000103, 0x58ec0009, 0x0801f800,
+ 0x59300402, 0x5c00b000, 0x5c00a800, 0x5c00a000,
+ 0x5c025800, 0x1c01f000, 0x0201f800, 0x0010801c,
+ 0x5c025800, 0x1c01f000, 0x4933c857, 0x83380580,
+ 0x00000035, 0x04000005, 0x59301419, 0x0401f851,
+ 0x04000027, 0x0401f006, 0x4d300000, 0x5932601e,
+ 0x0401f856, 0x5c026000, 0x04000020, 0x591c0c06,
+ 0x82040580, 0x00000003, 0x04000004, 0x82040580,
+ 0x00000006, 0x0402001c, 0x591c0c02, 0x59300419,
+ 0x80040580, 0x04000009, 0x59300219, 0x80040580,
+ 0x04020015, 0x591c0a02, 0x59300419, 0x80040580,
+ 0x04020011, 0x0401f009, 0x59300a19, 0x82040580,
+ 0x0000ffff, 0x04000005, 0x591c0202, 0x59300a19,
+ 0x80040580, 0x04020008, 0x591c0009, 0x59300809,
+ 0x80040580, 0x1c01f000, 0x417a3800, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x4803c856, 0x59b800e4,
+ 0x8c000538, 0x02020800, 0x001005d8, 0x42000800,
+ 0x0000012c, 0x4a0370e4, 0x20000000, 0x59b800e4,
+ 0x80040840, 0x02000800, 0x001005d8, 0x8c00053c,
+ 0x040207f9, 0x4a0370e4, 0x30000000, 0x40000000,
+ 0x40000000, 0x40000000, 0x59b800e4, 0x8c00053c,
+ 0x040207f1, 0x1c01f000, 0x4803c856, 0x4a0370e4,
+ 0x20000000, 0x40000000, 0x59b800e4, 0x8c000538,
+ 0x040207fb, 0x1c01f000, 0x59300807, 0x8c040d1e,
+ 0x592c0c08, 0x04020002, 0x8c040d18, 0x1c01f000,
+ 0x0401fc1c, 0x04000008, 0x42000800, 0x00000024,
+ 0x0201f800, 0x00106681, 0x82063c00, 0x0010d1c0,
+ 0x491fc857, 0x1c01f000, 0x83300480, 0x0010d1c0,
+ 0x0400100a, 0x59a8000b, 0x81300480, 0x04021007,
+ 0x59301402, 0x0401ffef, 0x04000007, 0x411c0000,
+ 0x81300580, 0x04000003, 0x81780500, 0x0401f002,
+ 0x81300540, 0x1c01f000, 0x4947c857, 0x4d300000,
+ 0x0201f800, 0x00020245, 0x0402000a, 0x42026000,
+ 0x0010bde9, 0x49366009, 0x492e6008, 0x0201f800,
+ 0x0010203c, 0x80000580, 0x5c026000, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x0401f7fc, 0x4933c857,
+ 0x0201f800, 0x00109037, 0x02000800, 0x001005d8,
+ 0x4d2c0000, 0x4d340000, 0x4d440000, 0x4c580000,
+ 0x59325808, 0x59326809, 0x49425a06, 0x0201f800,
+ 0x00105755, 0x592e8c06, 0x592c4207, 0x82200500,
+ 0x0000000f, 0x0c01f806, 0x5c00b000, 0x5c028800,
+ 0x5c026800, 0x5c025800, 0x1c01f000, 0x00109466,
+ 0x00109488, 0x0010948f, 0x00109493, 0x0010949c,
+ 0x00109463, 0x00109463, 0x00109463, 0x001094a0,
+ 0x001094ac, 0x001094ac, 0x00109463, 0x00109463,
+ 0x00109463, 0x00109463, 0x00109463, 0x4803c857,
+ 0x0201f800, 0x001005d8, 0x814281c0, 0x04020012,
+ 0x41785800, 0x592c0404, 0x8c00051c, 0x04020002,
+ 0x59345c05, 0x442c2800, 0x59340008, 0x48002802,
+ 0x59340009, 0x48002801, 0x59340006, 0x48002804,
+ 0x59340007, 0x48002803, 0x4200b000, 0x0000000b,
+ 0x0401f037, 0x592c0207, 0x8c00051e, 0x4200b000,
+ 0x00000002, 0x04020032, 0x8204b540, 0x00000000,
+ 0x0400002f, 0x44042800, 0x59326809, 0x59340400,
+ 0x48002801, 0x4200b000, 0x00000002, 0x0401f028,
+ 0x814281c0, 0x04020030, 0x59345c05, 0x442c2800,
+ 0x4200b000, 0x00000001, 0x0401f021, 0x8340b540,
+ 0x00000000, 0x0400001e, 0x0401f027, 0x814281c0,
+ 0x04020025, 0x59340200, 0x44002800, 0x59340001,
+ 0x48002801, 0x4200b000, 0x00000002, 0x0401f014,
+ 0x8340b540, 0x00000000, 0x0402001b, 0x0401f010,
+ 0x8340b540, 0x00000000, 0x0400000d, 0x0201f800,
+ 0x00104a1f, 0x04000014, 0x8c20450e, 0x04000002,
+ 0x497a6009, 0x4178b000, 0x497a5a06, 0x0401f004,
+ 0x8340b540, 0x00000000, 0x0402000b, 0x592c0404,
+ 0x8400051c, 0x48025c04, 0x592c0207, 0x8400051e,
+ 0x48025a07, 0x0401f8aa, 0x497a6008, 0x0201f000,
+ 0x000202da, 0x592c0207, 0x8c00051e, 0x4200b000,
+ 0x00000002, 0x040207f2, 0x8204b540, 0x00000000,
+ 0x040007ef, 0x44042800, 0x4200b000, 0x00000001,
+ 0x0401f7eb, 0x4937c857, 0x4d300000, 0x0201f800,
+ 0x0002075a, 0x04000011, 0x49366009, 0x4a026406,
+ 0x00000001, 0x492e6008, 0x42000800, 0x0000000b,
+ 0x0201f800, 0x00104571, 0x4d380000, 0x42027000,
+ 0x00000043, 0x0201f800, 0x000207a1, 0x5c027000,
+ 0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
+ 0x4937c857, 0x4d2c0000, 0x59325808, 0x83380580,
+ 0x00000015, 0x04020025, 0x59a80016, 0x82000580,
+ 0x00000004, 0x04020021, 0x59a80010, 0x592c1009,
+ 0x80080580, 0x04020010, 0x4d440000, 0x592e8c06,
+ 0x592c0207, 0x4803c856, 0x82000500, 0x00000080,
+ 0x84000548, 0x4d3c0000, 0x42027800, 0x00001000,
+ 0x0201f800, 0x001049bb, 0x5c027800, 0x5c028800,
+ 0x0401f004, 0x4803c856, 0x0201f800, 0x00104a1f,
+ 0x0201f800, 0x00109037, 0x04000017, 0x4d400000,
+ 0x42028000, 0x00000000, 0x41780800, 0x0401ff38,
+ 0x5c028000, 0x0401f00e, 0x0201f800, 0x00104a1f,
+ 0x040207f4, 0x0201f800, 0x00109037, 0x0400000a,
+ 0x4c580000, 0x4200b000, 0x00000002, 0x0401f86e,
+ 0x5c00b000, 0x0201f800, 0x0010801c, 0x0201f800,
+ 0x0002077d, 0x5c025800, 0x1c01f000, 0x4937c857,
+ 0x4d300000, 0x0201f800, 0x0002075a, 0x04000012,
+ 0x49366009, 0x4a026406, 0x00000001, 0x4d3c0000,
+ 0x4d380000, 0x417a7800, 0x0201f800, 0x00104567,
+ 0x492e6008, 0x42027000, 0x00000004, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x5c027800, 0x82000540,
+ 0x00000001, 0x5c026000, 0x1c01f000, 0x4937c857,
+ 0x4d300000, 0x0201f800, 0x00107942, 0x0400000d,
+ 0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
+ 0x4d380000, 0x42027000, 0x00000051, 0x0201f800,
+ 0x000207a1, 0x5c027000, 0x82000540, 0x00000001,
+ 0x5c026000, 0x1c01f000, 0x4933c857, 0x4c580000,
+ 0x59325808, 0x83383580, 0x00000015, 0x04020011,
+ 0x592c0008, 0x82000500, 0x00ffffff, 0x0402000a,
+ 0x0201f800, 0x00105755, 0x59cc0000, 0x82000500,
+ 0x00ffffff, 0x44002800, 0x4200b000, 0x00000001,
+ 0x0401f80b, 0x0201f800, 0x00107b38, 0x0401f006,
+ 0x4200b000, 0x00000002, 0x0401f823, 0x0201f800,
+ 0x0010801c, 0x5c00b000, 0x1c01f000, 0x492fc857,
+ 0x4c580000, 0x4c000000, 0x8058b1c0, 0x0400000b,
+ 0x82580500, 0xfffffff0, 0x02020800, 0x001005d8,
+ 0x8058b0d0, 0x592c0408, 0x82000500, 0xfffff0ff,
+ 0x80580540, 0x48025c08, 0x5c000000, 0x5c00b000,
+ 0x1c01f000, 0x492fc857, 0x4c000000, 0x4c040000,
+ 0x800000d8, 0x592c0c08, 0x82040d00, 0xffff0fff,
+ 0x80040540, 0x48025c08, 0x5c000800, 0x5c000000,
+ 0x1c01f000, 0x4933c857, 0x4d2c0000, 0x59325808,
+ 0x592c0207, 0x8400055e, 0x48025a07, 0x4c500000,
+ 0x4c540000, 0x4c580000, 0x0401ffd9, 0x0201f800,
+ 0x00105755, 0x46002800, 0x00000018, 0x80142800,
+ 0x8058b040, 0x83cca400, 0x00000007, 0x4014a800,
+ 0x0201f800, 0x0010ab17, 0x5c00b000, 0x5c00a800,
+ 0x5c00a000, 0x5c025800, 0x1c01f000, 0x59325808,
+ 0x592c0204, 0x82000580, 0x00000152, 0x1c01f000,
+ 0x5930001f, 0x80000540, 0x02020800, 0x00100d56,
+ 0x1c01f000, 0x4d2c0000, 0x59325808, 0x59300203,
+ 0x4933c857, 0x492fc857, 0x493bc857, 0x4803c857,
+ 0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x0c01f803, 0x5c025800, 0x1c01f000, 0x001095bd,
+ 0x001095c8, 0x00109603, 0x001095bd, 0x001095bd,
+ 0x001095bd, 0x001095bd, 0x001095bd, 0x001095bf,
+ 0x001095bd, 0x001095bd, 0x001095bd, 0x001095bd,
+ 0x001095bd, 0x0201f800, 0x001005d8, 0x83383480,
+ 0x00000056, 0x02021800, 0x001005d8, 0x493a6403,
+ 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+ 0x83380580, 0x00000013, 0x0402000f, 0x592c000c,
+ 0x800001c0, 0x04000006, 0x4a026203, 0x00000002,
+ 0x59a80037, 0x48026206, 0x1c01f000, 0x4a025a06,
+ 0x00000000, 0x0201f800, 0x000202da, 0x0201f000,
+ 0x0002077d, 0x83380580, 0x00000027, 0x0400001a,
+ 0x83380580, 0x00000014, 0x04000012, 0x83380580,
+ 0x00000015, 0x04000005, 0x83380580, 0x00000016,
+ 0x02020800, 0x001005d8, 0x0201f800, 0x00106f60,
+ 0x02020000, 0x00107974, 0x59300203, 0x82000580,
+ 0x00000002, 0x02020800, 0x001005d8, 0x0401f014,
+ 0x0201f800, 0x00106bbf, 0x4a02580e, 0x00000011,
+ 0x0401f005, 0x0201f800, 0x00106bbf, 0x4a02580e,
+ 0x00000010, 0x4a025a06, 0x00000031, 0x4a02580d,
+ 0x00000004, 0x0201f800, 0x000202da, 0x0201f800,
+ 0x00104c19, 0x0201f000, 0x00107911, 0x59341400,
+ 0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857,
+ 0x4807c857, 0x82040580, 0x00000053, 0x0400002e,
+ 0x82040580, 0x00000002, 0x04000016, 0x82040580,
+ 0x00000001, 0x04000017, 0x82040580, 0x00000003,
+ 0x0400001c, 0x82040580, 0x00000005, 0x0400001d,
+ 0x82040580, 0x00000033, 0x0400001a, 0x82040580,
+ 0x00000000, 0x0400001b, 0x82040580, 0x00000004,
+ 0x02020800, 0x001005d8, 0x0401f8a1, 0x0401f016,
+ 0x820c0580, 0x00000003, 0x0400084c, 0x0401f012,
+ 0x820c0580, 0x0000000b, 0x0402000f, 0x42000800,
+ 0x00000007, 0x0201f800, 0x00104571, 0x0401f00a,
+ 0x820c0580, 0x00000005, 0x04000864, 0x0401f006,
+ 0x820c0580, 0x00000009, 0x04000889, 0x0401f002,
+ 0x0401f893, 0x4a026403, 0x00000052, 0x59a81016,
+ 0x592c040b, 0x8c000500, 0x04000003, 0x42001000,
+ 0x00000008, 0x592c040b, 0x8c000516, 0x04000003,
+ 0x82081400, 0x00000018, 0x592c000c, 0x497a580d,
+ 0x497a580e, 0x80080c80, 0x04000009, 0x04001005,
+ 0x4a025a06, 0x00000007, 0x40001000, 0x0401f006,
+ 0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06,
+ 0x00000000, 0x480a580c, 0x82081400, 0x00000003,
+ 0x80081104, 0x0201f800, 0x00107ab5, 0x04000010,
+ 0x592c1001, 0x480a600b, 0x58080800, 0x82080400,
+ 0x00000002, 0x592c1011, 0x592c1812, 0x42003000,
+ 0x00000000, 0x42002000, 0x00101200, 0x0201f800,
+ 0x00107c32, 0x04000002, 0x1c01f000, 0x4a025a06,
+ 0x0000002c, 0x497a580c, 0x0201f800, 0x000202da,
+ 0x0201f000, 0x0002077d, 0x83380580, 0x00000015,
+ 0x0402000a, 0x59a80005, 0x8c000514, 0x0402000b,
+ 0x0201f800, 0x0010462a, 0x42000800, 0x00000004,
+ 0x0201f000, 0x00104571, 0x42000800, 0x00000007,
+ 0x0201f000, 0x00104571, 0x0201f800, 0x0010513b,
+ 0x42001000, 0x00000010, 0x04020009, 0x59340002,
+ 0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
+ 0x040007ec, 0x42001000, 0x00000008, 0x0201f800,
+ 0x00104c6d, 0x040007e7, 0x592c040b, 0x84000540,
+ 0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015,
+ 0x0402000f, 0x59a80005, 0x8c000514, 0x04020010,
+ 0x0201f800, 0x0010468d, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x00104567, 0x5c027800, 0x42000800,
+ 0x00000006, 0x0201f000, 0x00104571, 0x42000800,
+ 0x00000004, 0x0201f000, 0x00104571, 0x0201f800,
+ 0x0010513b, 0x42001000, 0x00000010, 0x04020009,
+ 0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
+ 0x00ff0000, 0x040007e7, 0x42001000, 0x00000008,
+ 0x0201f800, 0x00104c6d, 0x040007e2, 0x592c040b,
+ 0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800,
+ 0x00000004, 0x0201f000, 0x00104571, 0x83380580,
+ 0x00000015, 0x04020005, 0x0201f800, 0x0010a2c8,
+ 0x02000800, 0x001048c1, 0x1c01f000, 0x83380580,
+ 0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400,
+ 0x00000008, 0x4200b000, 0x00000002, 0x83341c00,
+ 0x00000006, 0x0201f800, 0x0010855a, 0x04020012,
+ 0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002,
+ 0x83341c00, 0x00000008, 0x0201f800, 0x0010855a,
+ 0x04020009, 0x59342200, 0x59cc1007, 0x800811c0,
+ 0x04000003, 0x480a6801, 0x84102542, 0x8410251a,
+ 0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000,
+ 0x0010b87b, 0x0201f800, 0x0010aa47, 0x0201f800,
+ 0x00106c55, 0x59300203, 0x4933c857, 0x4803c857,
+ 0x82000c80, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x0c01f803, 0x0201f000, 0x00106c4b, 0x0010970b,
+ 0x0010971a, 0x0010970c, 0x00109709, 0x00109709,
+ 0x00109709, 0x00109709, 0x00109709, 0x00109709,
+ 0x00109709, 0x00109709, 0x00109709, 0x00109709,
+ 0x00109709, 0x0201f800, 0x001005d8, 0x1c01f000,
+ 0x59300403, 0x82000580, 0x00000052, 0x02000000,
+ 0x00108d85, 0x0201f800, 0x00104c19, 0x59325808,
+ 0x4a025a06, 0x00000006, 0x0201f800, 0x000202da,
+ 0x0201f000, 0x00107911, 0x59301804, 0x840c0520,
+ 0x48026004, 0x598c000d, 0x81300580, 0x04020010,
+ 0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b7f6,
+ 0x50081000, 0x58080002, 0x82000580, 0x00000100,
+ 0x0400000e, 0x5808000c, 0x81300580, 0x02020800,
+ 0x001005d8, 0x4978100c, 0x0401f003, 0x8c0c1d20,
+ 0x040207dc, 0x0201f800, 0x001068d3, 0x040007d9,
+ 0x0201f800, 0x001005d8, 0x0201f800, 0x00106e8e,
+ 0x040007f9, 0x59300203, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x0c01f7bd, 0x4933c857,
+ 0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07,
+ 0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08,
+ 0x4806580b, 0x59c80817, 0x82040500, 0x000003ff,
+ 0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002,
+ 0x82000500, 0x00000003, 0x80081480, 0x82080480,
+ 0x000000f1, 0x02021800, 0x001005d8, 0x480a621a,
+ 0x412c0800, 0x0201f800, 0x001007d3, 0x02000800,
+ 0x001005d8, 0x492c0809, 0x58040408, 0x84000552,
+ 0x84000540, 0x48000c08, 0x82081400, 0x00000003,
+ 0x80081104, 0x83cca400, 0x00000006, 0x832cac00,
+ 0x00000004, 0x42000800, 0x00000010, 0x82080480,
+ 0x00000010, 0x04021003, 0x40080800, 0x80000580,
+ 0x4004b000, 0x4c000000, 0x0201f800, 0x0010ab28,
+ 0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000,
+ 0x4c000000, 0x0201f800, 0x001007d3, 0x02000800,
+ 0x001005d8, 0x492c1001, 0x832cac00, 0x00000004,
+ 0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000,
+ 0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857,
+ 0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a,
+ 0x48025a08, 0x59301011, 0x800811c0, 0x04020008,
+ 0x4a025a06, 0x00000000, 0x592c000b, 0x82000500,
+ 0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e,
+ 0x04000006, 0x4a025a06, 0x00000007, 0x80081080,
+ 0x80081000, 0x0401f003, 0x4a025a06, 0x00000015,
+ 0x480a5807, 0x42000000, 0x0010bed9, 0x50007000,
+ 0x5838000b, 0x80000540, 0x04020008, 0x4930700c,
+ 0x4930700b, 0x58380002, 0x82000580, 0x00000000,
+ 0x04020809, 0x0401f005, 0x82001400, 0x00000000,
+ 0x45301000, 0x4930700b, 0x5c007000, 0x5c025800,
+ 0x1c01f000, 0x4933c857, 0x592c0009, 0x40001000,
+ 0x4800700a, 0x82080400, 0x00000004, 0x48007003,
+ 0x592c000d, 0x592c100e, 0x48007007, 0x48087008,
+ 0x592c000a, 0x592c1208, 0x80080c80, 0x04001002,
+ 0x40001000, 0x82081400, 0x00000003, 0x80081104,
+ 0x82080480, 0x00000010, 0x04021003, 0x80000580,
+ 0x0401f003, 0x42001000, 0x00000010, 0x4800700d,
+ 0x48087004, 0x800810c4, 0x48087005, 0x40381000,
+ 0x0201f800, 0x00100858, 0x1c01f000, 0x4d2c0000,
+ 0x0201f800, 0x001007d3, 0x02000800, 0x001005d8,
+ 0x42000800, 0x0010bed9, 0x452c0800, 0x497a580b,
+ 0x497a580c, 0x497a580d, 0x4a025809, 0x001097ea,
+ 0x4a025802, 0x00000100, 0x4a025801, 0x00000000,
+ 0x5c025800, 0x1c01f000, 0x4833c857, 0x4d300000,
+ 0x4d2c0000, 0x4c5c0000, 0x4030b800, 0x585c000a,
+ 0x80025d40, 0x04020004, 0x585c000c, 0x4c000000,
+ 0x0401f044, 0x585c0002, 0x82000580, 0x00000100,
+ 0x04020022, 0x592c0801, 0x4c040000, 0x0201f800,
+ 0x001007f4, 0x5c000800, 0x800409c0, 0x0400001c,
+ 0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005,
+ 0x40065800, 0x0201f800, 0x001007fd, 0x0401f014,
+ 0x82080480, 0x00000010, 0x04021003, 0x80000580,
+ 0x0401f003, 0x42001000, 0x00000010, 0x4800b80d,
+ 0x4808b804, 0x800810c4, 0x4808b805, 0x82040400,
+ 0x00000004, 0x4800b803, 0x405c1000, 0x0201f800,
+ 0x00100858, 0x0401f025, 0x0401f828, 0x585c000c,
+ 0x80026540, 0x59300000, 0x80000d40, 0x04020002,
+ 0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000,
+ 0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103,
+ 0x59300402, 0x48025c06, 0x592c100b, 0x4c080000,
+ 0x0201f800, 0x000202c1, 0x0201f800, 0x0010912a,
+ 0x5c001000, 0x8c081518, 0x04000004, 0x0201f800,
+ 0x001091d1, 0x0401f003, 0x0201f800, 0x0002077d,
+ 0x405c7000, 0x5c000000, 0x80026540, 0x04000003,
+ 0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800,
+ 0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a,
+ 0x40025800, 0x0201f800, 0x001007fd, 0x5838000c,
+ 0x80026540, 0x59300008, 0x80025d40, 0x4a025a06,
+ 0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000,
+ 0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000,
+ 0x42027800, 0x00000005, 0x0401f83c, 0x5c027800,
+ 0x411e6000, 0x59300414, 0x84000502, 0x48026414,
+ 0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857,
+ 0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000,
+ 0x0201f800, 0x0010a942, 0x0201f800, 0x00103b25,
+ 0x04000008, 0x40602800, 0x405c3000, 0x0201f800,
+ 0x0010a446, 0x82000540, 0x00000001, 0x0401f002,
+ 0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000,
+ 0x4803c856, 0x4d300000, 0x42026000, 0x0010d1c0,
+ 0x59a8000e, 0x81640580, 0x04000016, 0x59300c06,
+ 0x82040580, 0x00000001, 0x04000009, 0x82040580,
+ 0x00000004, 0x04000006, 0x82040580, 0x00000010,
+ 0x02000800, 0x00108cf9, 0x0401f005, 0x4807c857,
+ 0x0201f800, 0x001092d7, 0x04020808, 0x83326400,
+ 0x00000024, 0x41580000, 0x81300480, 0x040017e9,
+ 0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403,
+ 0x4803c857, 0x0201f800, 0x00106c55, 0x4df00000,
+ 0x59300406, 0x4803c857, 0x82000d80, 0x00000002,
+ 0x04000018, 0x82000d80, 0x00000001, 0x04000009,
+ 0x82000d80, 0x00000004, 0x04000006, 0x4933c856,
+ 0x5c03e000, 0x02000800, 0x00106c4b, 0x0401f03c,
+ 0x59300203, 0x82000d80, 0x00000001, 0x04000018,
+ 0x82000d80, 0x00000002, 0x04000026, 0x82000d80,
+ 0x00000005, 0x04000023, 0x0201f800, 0x001005d8,
+ 0x59300203, 0x82000d80, 0x00000009, 0x0400000c,
+ 0x82000d80, 0x0000000b, 0x04000009, 0x82000d80,
+ 0x0000000a, 0x04000017, 0x82000d80, 0x0000000c,
+ 0x04000014, 0x0201f800, 0x001005d8, 0x598c000d,
+ 0x81300580, 0x04020004, 0x0201f800, 0x00106e8e,
+ 0x0402000c, 0x59300004, 0x4803c857, 0x8c000520,
+ 0x04000004, 0x84000520, 0x48026004, 0x0401f005,
+ 0x0201f800, 0x001068d3, 0x02020800, 0x001005d8,
+ 0x5c03e000, 0x02000800, 0x00106c4b, 0x59300406,
+ 0x82000d80, 0x00000002, 0x04000009, 0x0201f800,
+ 0x00104c19, 0x0201f800, 0x0010914e, 0x02000800,
+ 0x0010801c, 0x8d3e7d00, 0x04000003, 0x0201f000,
+ 0x00107911, 0x4a02621d, 0x00000001, 0x4a026403,
+ 0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
+ 0x00000002, 0x42000800, 0x8000004b, 0x0201f000,
+ 0x00020721, 0x4933c857, 0x59368c03, 0x4c180000,
+ 0x59300203, 0x82003480, 0x0000000e, 0x02021800,
+ 0x001005d8, 0x0c01f803, 0x5c003000, 0x1c01f000,
+ 0x0010990a, 0x00109dcf, 0x00109edb, 0x0010990a,
+ 0x0010990a, 0x0010990a, 0x0010990a, 0x0010990a,
+ 0x0010992d, 0x0010990a, 0x0010990a, 0x0010990a,
+ 0x0010990a, 0x0010990a, 0x0201f800, 0x001005d8,
+ 0x4933c857, 0x42028800, 0x0000ffff, 0x813669c0,
+ 0x04000002, 0x59368c03, 0x4c180000, 0x59300203,
+ 0x82003480, 0x0000000e, 0x02021800, 0x001005d8,
+ 0x0c01f803, 0x5c003000, 0x1c01f000, 0x00109929,
+ 0x0010a180, 0x00109929, 0x00109929, 0x00109929,
+ 0x00109929, 0x00109929, 0x0010a952, 0x0010a0ed,
+ 0x0010a52c, 0x0010a562, 0x0010a52c, 0x0010a562,
+ 0x00109929, 0x0201f800, 0x001005d8, 0x0201f800,
+ 0x001005d8, 0x83383480, 0x00000051, 0x02021800,
+ 0x001005d8, 0x41380000, 0x493bc857, 0x4d1c0000,
+ 0x4d400000, 0x0c01f804, 0x5c028000, 0x5c023800,
+ 0x1c01f000, 0x0010998a, 0x00109b69, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x00109b74, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+ 0x001099ac, 0x001099f5, 0x00109a0c, 0x00109a62,
+ 0x00109ac6, 0x00109b04, 0x00109b34, 0x0010998a,
+ 0x0010998a, 0x00109b7c, 0x0010998a, 0x0010998a,
+ 0x00109b8a, 0x00109b93, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x00109c15,
+ 0x0010998a, 0x0010998a, 0x00109a9a, 0x0010998a,
+ 0x0010998a, 0x00109bec, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x00109c23, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x00109c6c, 0x0010998a, 0x0010998a,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010998a,
+ 0x00109cb9, 0x0010998a, 0x00109ce5, 0x00109cf0,
+ 0x0010998a, 0x0010998a, 0x0010998c, 0x00109cfb,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x0010999b,
+ 0x0010998a, 0x0010998a, 0x0010998a, 0x00109d02,
+ 0x00109d0a, 0x00109d28, 0x0201f800, 0x001005d8,
+ 0x4933c857, 0x0201f800, 0x0010a592, 0x040203a4,
+ 0x0201f800, 0x0010210a, 0x040203a1, 0x59cc0407,
+ 0x4802601c, 0x4a026403, 0x00000045, 0x4a026203,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x4933c857,
+ 0x0201f800, 0x0010a592, 0x04020395, 0x0201f800,
+ 0x0010210a, 0x04020392, 0x0401fbce, 0x040201a0,
+ 0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a,
+ 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+ 0x4933c857, 0x0201f800, 0x0010210a, 0x04020009,
+ 0x0201f800, 0x001048ec, 0x04020006, 0x82000500,
+ 0x00000009, 0x82000580, 0x00000008, 0x04020008,
+ 0x4a026403, 0x00000009, 0x4a02641a, 0x00000009,
+ 0x4a02621a, 0x00000000, 0x0401f1b2, 0x0201f800,
+ 0x001048c1, 0x0201f800, 0x00104a09, 0x04000021,
+ 0x0201f800, 0x001049ed, 0x0400001e, 0x0201f800,
+ 0x0010a252, 0x04020025, 0x42028000, 0x00000029,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x5c027800, 0x0201f800, 0x0010462a, 0x836c0580,
+ 0x00000002, 0x04020004, 0x59a8001b, 0x80000000,
+ 0x4803501b, 0x4a026403, 0x00000008, 0x42003000,
+ 0x00000003, 0x0201f800, 0x00103b25, 0x04000191,
+ 0x4a026203, 0x00000007, 0x41782800, 0x0401f180,
+ 0x0201f800, 0x0010a3da, 0x040207e1, 0x4a026403,
+ 0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a,
+ 0x00001900, 0x0401f183, 0x4a026403, 0x00000009,
+ 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000f00,
+ 0x0401f17c, 0x4933c857, 0x0201f800, 0x0010210a,
+ 0x0402033b, 0x0201f800, 0x001048ec, 0x04020338,
+ 0x493a6403, 0x0201f800, 0x0010a22d, 0x04020006,
+ 0x42003000, 0x00000005, 0x4a026403, 0x00000006,
+ 0x0401f7d9, 0x4a026403, 0x00000007, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00000000, 0x0401f165,
+ 0x4933c857, 0x0201f800, 0x001048ec, 0x04020324,
+ 0x0201f800, 0x0010a592, 0x02000800, 0x0010210a,
+ 0x0402031f, 0x0201f800, 0x00104a09, 0x04020005,
+ 0x42027800, 0x00000001, 0x0201f800, 0x00104567,
+ 0x0201f800, 0x001049fc, 0x0402002b, 0x59cc0206,
+ 0x82003500, 0x00000003, 0x0402002e, 0x82003480,
+ 0x00000014, 0x0400102b, 0x5934300a, 0x84183516,
+ 0x82000580, 0x00000014, 0x04020002, 0x84183556,
+ 0x481a680a, 0x59cc0406, 0x82000500, 0x00000003,
+ 0x04020020, 0x0201f800, 0x0010a29f, 0x04020028,
+ 0x0201f800, 0x001049e7, 0x0402000c, 0x417a7800,
+ 0x0201f800, 0x001020a1, 0x42003000, 0x00000006,
+ 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b865,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x0010468d,
+ 0x4a026403, 0x0000000a, 0x42003000, 0x00000020,
+ 0x0401f795, 0x4a026403, 0x0000000b, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f121,
+ 0x42000000, 0x0010b860, 0x0201f800, 0x0010aa47,
+ 0x4a026403, 0x0000000b, 0x4a02641a, 0x00000007,
+ 0x4a02621a, 0x00000000, 0x0401f116, 0x4a026403,
+ 0x0000000b, 0x4a02641a, 0x00000003, 0x4a02621a,
+ 0x00000000, 0x0401f10f, 0x4933c857, 0x0201f800,
+ 0x001048ec, 0x040202ce, 0x0201f800, 0x0010a592,
+ 0x040202cb, 0x0201f800, 0x0010210a, 0x040202c8,
+ 0x59cc0206, 0x82003500, 0x00000003, 0x0402001d,
+ 0x82003480, 0x00000014, 0x0400101a, 0x59cc0406,
+ 0x82000500, 0x00000003, 0x04020016, 0x59340400,
+ 0x82000580, 0x00000707, 0x04000019, 0x417a7800,
+ 0x0201f800, 0x001020a1, 0x42003000, 0x0000000a,
+ 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b862,
+ 0x0201f800, 0x0010aa47, 0x4a026403, 0x0000000c,
+ 0x41782800, 0x42003000, 0x00000021, 0x0401f752,
+ 0x4a026403, 0x0000000d, 0x4a02641a, 0x00000007,
+ 0x4a02621a, 0x00000000, 0x0401f0de, 0x4a026403,
+ 0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a,
+ 0x00001e00, 0x0401f0d7, 0x4933c857, 0x0201f800,
+ 0x001048ec, 0x04020296, 0x0201f800, 0x0010a592,
+ 0x04020293, 0x0201f800, 0x0010210a, 0x04020290,
+ 0x0401facc, 0x0402001a, 0x493a6403, 0x4c5c0000,
+ 0x0401fad2, 0x0402000e, 0x4a026403, 0x0000002e,
+ 0x405c2800, 0x42003000, 0x00000024, 0x0201f800,
+ 0x00103b25, 0x0400000c, 0x4a026203, 0x00000007,
+ 0x405c2800, 0x5c00b800, 0x0401f0ad, 0x4a026403,
+ 0x0000000d, 0x4a02641a, 0x00000007, 0x4a02621a,
+ 0x00000000, 0x5c00b800, 0x0401f0b2, 0x4a026403,
+ 0x0000000d, 0x4a02641a, 0x00000009, 0x4a02621a,
+ 0x00001e00, 0x0401f0ab, 0x4933c857, 0x0201f800,
+ 0x001048ec, 0x040206ef, 0x59a80026, 0x82000500,
+ 0x00000009, 0x82000580, 0x00000008, 0x040006e9,
+ 0x0201f800, 0x001049fc, 0x0402002d, 0x0201f800,
+ 0x0010a2a7, 0x04020007, 0x4a026403, 0x0000000e,
+ 0x41782800, 0x42003000, 0x00000052, 0x0401f702,
+ 0x4933c857, 0x42003000, 0x00000003, 0x0201f800,
+ 0x0010a942, 0x4d3c0000, 0x417a7800, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x59340200, 0x84000558,
+ 0x48026a00, 0x42000800, 0x0000000b, 0x0201f800,
+ 0x00104571, 0x0201f800, 0x00103b25, 0x04000076,
+ 0x42003000, 0x00000007, 0x0401f062, 0x4933c857,
+ 0x4a026403, 0x0000000f, 0x4a02641a, 0x00000003,
+ 0x4a02621a, 0x00001e00, 0x0401f072, 0x59340400,
+ 0x82000580, 0x00000703, 0x040007f5, 0x0401f040,
+ 0x4933c857, 0x0201f800, 0x001048ec, 0x0402022c,
+ 0x59a80026, 0x82000500, 0x00000009, 0x82000580,
+ 0x00000008, 0x04000226, 0x0201f800, 0x001049f3,
+ 0x0402002f, 0x0201f800, 0x0010a2c8, 0x02000800,
+ 0x0010a252, 0x04020007, 0x4a026403, 0x00000010,
+ 0x41782800, 0x42003000, 0x00000050, 0x0401f6c2,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x5c027800, 0x42003000, 0x00000003, 0x0201f800,
+ 0x0010a942, 0x42000000, 0x0010b864, 0x0201f800,
+ 0x0010aa47, 0x59340200, 0x84000558, 0x48026a00,
+ 0x0401f7c5, 0x4a026403, 0x00000011, 0x4a02641a,
+ 0x00000003, 0x4a02621a, 0x00001e00, 0x0401f03d,
+ 0x4933c857, 0x0201f800, 0x0010210a, 0x02000800,
+ 0x0010a592, 0x040201fa, 0x0401fa36, 0x04020008,
+ 0x4a026403, 0x00000012, 0x0401f032, 0x59340400,
+ 0x82000580, 0x00000703, 0x040007eb, 0x4d3c0000,
+ 0x417a7800, 0x42028000, 0x00000029, 0x0201f800,
+ 0x0010203c, 0x5c027800, 0x42003000, 0x00000017,
+ 0x0201f800, 0x0010a942, 0x42000000, 0x0010b864,
+ 0x0201f800, 0x0010aa47, 0x0201f800, 0x00103b25,
+ 0x04000015, 0x42003000, 0x00000006, 0x41782800,
+ 0x42028000, 0x00000029, 0x4933c857, 0x4a026403,
+ 0x00000001, 0x4a026203, 0x00000007, 0x0201f800,
+ 0x0010a974, 0x0201f000, 0x0010a43e, 0x42028000,
+ 0x00000046, 0x0201f800, 0x0010a974, 0x0201f000,
+ 0x0010a43e, 0x4933c857, 0x4a026403, 0x00000001,
+ 0x42000800, 0x0000000b, 0x0201f800, 0x00104571,
+ 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+ 0x4933c857, 0x42000800, 0x00000009, 0x0201f800,
+ 0x00104571, 0x4a026403, 0x00000005, 0x0401f7f5,
+ 0x0201f800, 0x0010a592, 0x040201b5, 0x0201f800,
+ 0x0010210a, 0x040201b2, 0x0401f9ee, 0x040207c0,
+ 0x4a026403, 0x00000020, 0x4a026203, 0x00000001,
+ 0x0201f000, 0x0010672b, 0x0201f800, 0x0010210a,
+ 0x040201a7, 0x4a026403, 0x00000023, 0x4a026203,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+ 0x0010a592, 0x02000800, 0x0010210a, 0x0402019c,
+ 0x0401f9d8, 0x040207aa, 0x40300800, 0x59a81010,
+ 0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580,
+ 0x04000019, 0x59cc1408, 0x0201f800, 0x0010902c,
+ 0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800,
+ 0x00105dd7, 0x41323800, 0x5c026000, 0x04000026,
+ 0x591c0202, 0x82000580, 0x0000ffff, 0x04000005,
+ 0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e,
+ 0x591c0406, 0x82000580, 0x00000007, 0x0402001a,
+ 0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff,
+ 0x0400000c, 0x0201f800, 0x00109410, 0x04000012,
+ 0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e,
+ 0x591c0009, 0x81340580, 0x04000016, 0x0401f00a,
+ 0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a405,
+ 0x04020010, 0x59cc1208, 0x82080580, 0x0000ffff,
+ 0x04000019, 0x4a026403, 0x00000026, 0x4a02621a,
+ 0x00001700, 0x59cc1204, 0x82081580, 0x0000ffff,
+ 0x04020798, 0x4a026403, 0x00000025, 0x0401f795,
+ 0x591c0406, 0x82000580, 0x00000007, 0x040207f2,
+ 0x591c0403, 0x82000580, 0x00000024, 0x04020006,
+ 0x4d300000, 0x411e6000, 0x0201f800, 0x0002077d,
+ 0x5c026000, 0x4a026403, 0x00000025, 0x0401f785,
+ 0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001,
+ 0x0201f800, 0x00104567, 0x5c027800, 0x4c580000,
+ 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002,
+ 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+ 0x5c00b000, 0x04000004, 0x4a026403, 0x00000031,
+ 0x0401f770, 0x0201f800, 0x00107911, 0x0201f800,
+ 0x0010513b, 0x0402000f, 0x0201f800, 0x00105149,
+ 0x04020008, 0x4a035033, 0x00000001, 0x4202d800,
+ 0x00000001, 0x0201f800, 0x001050a2, 0x0401f005,
+ 0x42000000, 0x00000001, 0x0201f800, 0x00105113,
+ 0x1c01f000, 0x0201f800, 0x0010210a, 0x0402011c,
+ 0x0401f958, 0x0402072a, 0x493a6403, 0x0401f996,
+ 0x04020004, 0x4a026403, 0x0000002b, 0x0401f751,
+ 0x4a026403, 0x0000002c, 0x0401f74e, 0x4933c857,
+ 0x0201f800, 0x0010210a, 0x0402010d, 0x0201f800,
+ 0x001049e7, 0x04020740, 0x0201f800, 0x001048d9,
+ 0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208,
+ 0x48026219, 0x59cc0807, 0x59340002, 0x82000500,
+ 0x00ffffff, 0x80040580, 0x04000012, 0x59a80010,
+ 0x80040580, 0x04020021, 0x59cc1408, 0x0201f800,
+ 0x00109410, 0x04000023, 0x0201f800, 0x0010a4ca,
+ 0x04000020, 0x0201f800, 0x0010a921, 0x0400001d,
+ 0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6,
+ 0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009,
+ 0x0201f800, 0x00109410, 0x04000012, 0x591c0202,
+ 0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb,
+ 0x59cc1408, 0x41327800, 0x0201f800, 0x0010a405,
+ 0x04000008, 0x0401f7e5, 0x4803c856, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00001500, 0x0401f006,
+ 0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a,
+ 0x00001700, 0x4a026403, 0x00000037, 0x0401f0c6,
+ 0x4803c856, 0x4a026403, 0x00000012, 0x0401f0c2,
+ 0x4933c857, 0x0201f800, 0x0010210a, 0x040200c4,
+ 0x0201f800, 0x001049e7, 0x040206f7, 0x0201f800,
+ 0x001048d9, 0x0400003e, 0x59cc0407, 0x48026419,
+ 0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff,
+ 0x04000005, 0x0201f800, 0x00109410, 0x0400002c,
+ 0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800,
+ 0x0010a405, 0x04000026, 0x59cc0c07, 0x591c0202,
+ 0x80040580, 0x04020022, 0x4d300000, 0x411e6000,
+ 0x0201f800, 0x00108bd7, 0x5c026000, 0x59cc0c09,
+ 0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800,
+ 0x0010a921, 0x04000016, 0x82040580, 0x00000001,
+ 0x0400000a, 0x82040580, 0x00000005, 0x04000004,
+ 0x82040580, 0x00000007, 0x04020007, 0x591c0008,
+ 0x80000540, 0x04000004, 0x59cc2808, 0x0201f000,
+ 0x0010a4de, 0x4803c856, 0x4a02641a, 0x00000009,
+ 0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856,
+ 0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300,
+ 0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856,
+ 0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000,
+ 0x0401f7f8, 0x4c080000, 0x0201f800, 0x001048ec,
+ 0x04000026, 0x0201f800, 0x001048c1, 0x0201f800,
+ 0x0010a601, 0x0402001e, 0x59a80026, 0x82000540,
+ 0x00000003, 0x48035026, 0x59a8001d, 0x800000d0,
+ 0x59a80810, 0x82040d00, 0x000000ff, 0x80041540,
+ 0x480b5010, 0x42000800, 0x00000003, 0x0201f800,
+ 0x00106c78, 0x497b5028, 0x0201f800, 0x00103b25,
+ 0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a,
+ 0x0402000a, 0x0201f800, 0x0002077d, 0x0201f800,
+ 0x00101e45, 0x5c001000, 0x1c01f000, 0x0201f800,
+ 0x0010a623, 0x0401f7fc, 0x5c001000, 0x0201f000,
+ 0x0002077d, 0x0201f800, 0x0010210a, 0x0402004c,
+ 0x0201f800, 0x0010a628, 0x4a026403, 0x00000047,
+ 0x4a026203, 0x00000001, 0x0201f000, 0x0010672b,
+ 0x0201f800, 0x0010210a, 0x04020041, 0x0201f800,
+ 0x0010a628, 0x4a026403, 0x00000047, 0x4a026203,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+ 0x0010210a, 0x04020036, 0x0201f800, 0x0010a628,
+ 0x0201f000, 0x0002077d, 0x0401f834, 0x04000030,
+ 0x4a026403, 0x0000004e, 0x4a026203, 0x00000001,
+ 0x0201f000, 0x0010672b, 0x4a026403, 0x0000004f,
+ 0x497a601c, 0x59cc0a06, 0x82040d00, 0x000000ff,
+ 0x800409c0, 0x0400065f, 0x82040580, 0x00000001,
+ 0x04020005, 0x59cc0808, 0x59a80005, 0x80040580,
+ 0x04000658, 0x82040580, 0x00000002, 0x0402000a,
+ 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+ 0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+ 0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649,
+ 0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c,
+ 0x0401f644, 0x4a026203, 0x00000001, 0x42000800,
+ 0x80000040, 0x0201f000, 0x00020721, 0x4803c857,
+ 0x0201f000, 0x0002077d, 0x4d2c0000, 0x4c500000,
+ 0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80,
+ 0x00000829, 0x04021029, 0x0201f800, 0x001007d3,
+ 0x04000026, 0x492e6008, 0x59a80016, 0x80000104,
+ 0x48025802, 0x83cca400, 0x00000006, 0x82000c80,
+ 0x0000000b, 0x04001013, 0x4a025811, 0x0000000b,
+ 0x4200b000, 0x0000000b, 0x832c0400, 0x00000005,
+ 0x4000a800, 0x0201f800, 0x0010ab17, 0x412c7000,
+ 0x0201f800, 0x001007d3, 0x04000010, 0x492c7001,
+ 0x40040000, 0x800409c0, 0x04000009, 0x0401f7ec,
+ 0x48025811, 0x4000b000, 0x832c0400, 0x00000005,
+ 0x4000a800, 0x0201f800, 0x0010ab17, 0x82000540,
+ 0x00000001, 0x0401f006, 0x497b5016, 0x59325808,
+ 0x0201f800, 0x001007fd, 0x80000580, 0x5c00a800,
+ 0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000,
+ 0x4d340000, 0x59326809, 0x59343400, 0x4933c857,
+ 0x4937c857, 0x481bc857, 0x0201f800, 0x001049f3,
+ 0x5c026800, 0x1c01f000, 0x4933c857, 0x4c5c0000,
+ 0x4d3c0000, 0x0401f840, 0x0402002c, 0x59cc0207,
+ 0x82000d00, 0x0000ff00, 0x900411c0, 0x59cc000a,
+ 0x82000500, 0x00ffffff, 0x80081540, 0x480a601c,
+ 0x8c040d18, 0x0400000e, 0x42003000, 0x00000008,
+ 0x0201f800, 0x0010a932, 0x42000000, 0x0010b863,
+ 0x0201f800, 0x0010aa47, 0x4200b800, 0x00000002,
+ 0x42027800, 0x00000001, 0x0401f011, 0x4178b800,
+ 0x8c040d1a, 0x04000011, 0x59cc000a, 0x0201f800,
+ 0x00105c9a, 0x0402000d, 0x42003000, 0x00000009,
+ 0x0201f800, 0x0010a93a, 0x42000000, 0x0010b863,
+ 0x0201f800, 0x0010aa47, 0x417a7800, 0x0201f800,
+ 0x001020a1, 0x0401f004, 0x82000540, 0x00000001,
+ 0x0401f002, 0x80000580, 0x5c027800, 0x5c00b800,
+ 0x1c01f000, 0x4933c857, 0x59cc0206, 0x82000480,
+ 0x00000010, 0x04021006, 0x4a02621a, 0x00000000,
+ 0x82000540, 0x00000001, 0x0401f002, 0x80000580,
+ 0x1c01f000, 0x4933c857, 0x4a02621a, 0x00000000,
+ 0x59cc0407, 0x82000500, 0x0000ff00, 0x82000580,
+ 0x00000800, 0x04020009, 0x59cc0006, 0x82000500,
+ 0x00ff0000, 0x82000d80, 0x00140000, 0x04000003,
+ 0x82000d80, 0x00100000, 0x1c01f000, 0x4933c857,
+ 0x59300403, 0x82003480, 0x00000051, 0x02021800,
+ 0x001005d8, 0x83383580, 0x00000013, 0x04020003,
+ 0x4803c857, 0x0c01f012, 0x83383580, 0x00000027,
+ 0x04000005, 0x83383580, 0x00000014, 0x02020800,
+ 0x001005d8, 0x0201f800, 0x001048c1, 0x42000800,
+ 0x00000007, 0x0201f800, 0x00104571, 0x0201f800,
+ 0x00106bbf, 0x0201f000, 0x00107911, 0x00109e3c,
+ 0x00109e45, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e45, 0x00109e50, 0x00109ecd, 0x00109e95,
+ 0x00109ecd, 0x00109ead, 0x00109ecd, 0x00109ebe,
+ 0x00109ecd, 0x00109ec6, 0x00109ecd, 0x00109ec6,
+ 0x00109ecd, 0x00109ecd, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e45, 0x00109e3c, 0x00109ecd,
+ 0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109e3c,
+ 0x00109eca, 0x00109ecd, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e3c, 0x00109ecd, 0x00109ecd,
+ 0x00109e3c, 0x00109ec3, 0x00109ecd, 0x00109e3c,
+ 0x00109e4a, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109ec9, 0x00109ecd, 0x00109e3c,
+ 0x00109e3c, 0x00109ecd, 0x00109ecd, 0x00109e3c,
+ 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e3c, 0x00109e3c, 0x00109e3c,
+ 0x00109e3e, 0x00109e3c, 0x00109e3e, 0x00109e3c,
+ 0x00109e3c, 0x00109e3e, 0x00109e3c, 0x00109e3c,
+ 0x00109e3c, 0x00109e3e, 0x00109e3e, 0x00109e3e,
+ 0x0201f800, 0x001005d8, 0x4d2c0000, 0x59325808,
+ 0x0201f800, 0x001007fd, 0x5c025800, 0x0201f000,
+ 0x0002077d, 0x59a80037, 0x48026206, 0x4a026203,
+ 0x00000002, 0x1c01f000, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x00104567, 0x5c027800, 0x0401f07e,
+ 0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+ 0x59a80026, 0x8c000508, 0x04000012, 0x59326809,
+ 0x4c580000, 0x4200b000, 0x00000002, 0x83a81c00,
+ 0x00000002, 0x83341400, 0x00000006, 0x0201f800,
+ 0x0010855a, 0x80000540, 0x5c00b000, 0x0402006a,
+ 0x59340200, 0x8400051a, 0x48026a00, 0x0401f01b,
+ 0x599c0017, 0x8c00050a, 0x04020063, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x00104567, 0x5c027800,
+ 0x42000800, 0x00000007, 0x0201f800, 0x00104571,
+ 0x59340212, 0x82000500, 0x0000ff00, 0x04000056,
+ 0x599c0019, 0x8c00050e, 0x04020053, 0x416c0000,
+ 0x82000580, 0x00000002, 0x04020004, 0x59a8001b,
+ 0x80000000, 0x4803501b, 0x42000800, 0x00000003,
+ 0x0201f800, 0x00104571, 0x4a026406, 0x00000001,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000002,
+ 0x0201f800, 0x0010672b, 0x4ce80000, 0x4201d000,
+ 0x00000001, 0x0201f800, 0x00105fae, 0x5c01d000,
+ 0x1c01f000, 0x0201f800, 0x001049f3, 0x04000036,
+ 0x0201f800, 0x0010645e, 0x42000800, 0x00000004,
+ 0x0201f800, 0x00104571, 0x0201f800, 0x0010a96a,
+ 0x0402002d, 0x42000800, 0x00000005, 0x0201f800,
+ 0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+ 0x00000001, 0x4a026403, 0x00000003, 0x0201f000,
+ 0x0010672b, 0x42000800, 0x00000006, 0x0401f820,
+ 0x59303009, 0x599c0017, 0x8c00050a, 0x0402001a,
+ 0x59a80026, 0x8c000508, 0x04000017, 0x0201f800,
+ 0x001049e7, 0x04000014, 0x59a8001b, 0x80000000,
+ 0x4803501b, 0x0401f7c5, 0x42000800, 0x00000004,
+ 0x0201f800, 0x00104571, 0x0401f792, 0x42000800,
+ 0x00000004, 0x0401f006, 0x0201f800, 0x001048c1,
+ 0x0401f005, 0x0401f004, 0x0401f003, 0x0201f800,
+ 0x00104571, 0x0201f000, 0x0002077d, 0x4933c857,
+ 0x4807c857, 0x0201f800, 0x00104571, 0x4d3c0000,
+ 0x417a7800, 0x0201f800, 0x00104567, 0x5c027800,
+ 0x0201f800, 0x00102074, 0x1c01f000, 0x4933c857,
+ 0x59340400, 0x80000110, 0x82003480, 0x0000000c,
+ 0x02021800, 0x001005d8, 0x83383580, 0x00000015,
+ 0x04020002, 0x0c01f006, 0x83383580, 0x00000016,
+ 0x02020800, 0x001005d8, 0x0c01f00d, 0x001080b8,
+ 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+ 0x001080b8, 0x00109f30, 0x00109f03, 0x001080b8,
+ 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+ 0x001080b8, 0x001080b8, 0x001080b8, 0x001080b8,
+ 0x001080b8, 0x00109f30, 0x00109f37, 0x001080b8,
+ 0x001080b8, 0x001080b8, 0x001080b8, 0x4933c857,
+ 0x599c0017, 0x8c00050a, 0x0402001b, 0x813669c0,
+ 0x04000019, 0x59340212, 0x82000500, 0x0000ff00,
+ 0x04000015, 0x599c0019, 0x8c00050e, 0x04020012,
+ 0x4d3c0000, 0x417a7800, 0x0201f800, 0x00104567,
+ 0x5c027800, 0x42000800, 0x00000003, 0x0201f800,
+ 0x00104571, 0x4a026406, 0x00000001, 0x4a026203,
+ 0x00000001, 0x4a026403, 0x00000002, 0x0201f000,
+ 0x0010672b, 0x59cc0001, 0x0201f800, 0x00105c9a,
+ 0x0402000b, 0x0201f800, 0x00020245, 0x02020000,
+ 0x0002077d, 0x59345002, 0x0201f800, 0x001042b4,
+ 0x482a6802, 0x0201f000, 0x0002077d, 0x1c01f000,
+ 0x4933c857, 0x59303403, 0x82183580, 0x0000001e,
+ 0x02000000, 0x0002077d, 0x1c01f000, 0x4933c857,
+ 0x0201f800, 0x001083df, 0x02020000, 0x0002077d,
+ 0x4a026203, 0x00000001, 0x4a026403, 0x00000001,
+ 0x0201f000, 0x0010672b, 0x493bc857, 0x83380580,
+ 0x00000051, 0x0402000b, 0x0201f800, 0x00106f60,
+ 0x02020000, 0x00107974, 0x59300203, 0x82000580,
+ 0x00000002, 0x0400006d, 0x0201f800, 0x001005d8,
+ 0x83380580, 0x00000027, 0x04000014, 0x83380580,
+ 0x00000048, 0x04000006, 0x83380580, 0x00000014,
+ 0x0400000e, 0x02020800, 0x001005d8, 0x0201f800,
+ 0x00106f60, 0x02020000, 0x00107974, 0x59300203,
+ 0x82000580, 0x00000004, 0x02000000, 0x0002086e,
+ 0x0201f800, 0x001005d8, 0x59300403, 0x82000c80,
+ 0x00000044, 0x02021800, 0x001005d8, 0x82000480,
+ 0x00000040, 0x02001800, 0x001005d8, 0x40027000,
+ 0x4803c857, 0x0c01f001, 0x00109f76, 0x00109f78,
+ 0x00109f78, 0x00109f93, 0x0201f800, 0x001005d8,
+ 0x0201f800, 0x00106bbf, 0x59325808, 0x812e59c0,
+ 0x04000016, 0x832c0500, 0x00ff0000, 0x04000013,
+ 0x4a026203, 0x00000002, 0x59326809, 0x59340200,
+ 0x8c00050e, 0x0402000d, 0x42028000, 0x00000004,
+ 0x0201f800, 0x0010a3ef, 0x497a6008, 0x59300206,
+ 0x80000540, 0x04020003, 0x59a80038, 0x48026206,
+ 0x4a026203, 0x00000007, 0x1c01f000, 0x0201f800,
+ 0x00106bbf, 0x0201f800, 0x00109037, 0x02000000,
+ 0x00107911, 0x59325808, 0x0201f800, 0x001007f4,
+ 0x0201f000, 0x00107911, 0x0201f800, 0x001005d8,
+ 0x59325808, 0x592c040a, 0x8c000502, 0x04000007,
+ 0x4a026203, 0x00000007, 0x42027000, 0x00000043,
+ 0x0201f000, 0x000207a1, 0x4a026203, 0x00000004,
+ 0x1c01f000, 0x0201f800, 0x0010a597, 0x02000000,
+ 0x0002086c, 0x1c01f000, 0x4a026203, 0x00000001,
+ 0x4a026403, 0x00000041, 0x42027800, 0x80002042,
+ 0x0201f000, 0x00020721, 0x83380580, 0x00000051,
+ 0x04000006, 0x83380580, 0x00000041, 0x02020800,
+ 0x001005d8, 0x1c01f000, 0x0201f800, 0x000206fd,
+ 0x0201f800, 0x0010a5df, 0x0201f000, 0x0002077d,
+ 0x83380480, 0x00000050, 0x02021800, 0x001005d8,
+ 0x83380480, 0x00000049, 0x02001800, 0x001005d8,
+ 0x0c01f001, 0x00109fda, 0x00109ffb, 0x00109fd8,
+ 0x00109fd8, 0x00109fd8, 0x00109fd8, 0x00109ffb,
+ 0x0201f800, 0x001005d8, 0x59325808, 0x592c040a,
+ 0x8c00051e, 0x0400000d, 0x82000d00, 0x000000c0,
+ 0x82040d80, 0x00000080, 0x0400000d, 0x59300804,
+ 0x8c040d18, 0x0402000a, 0x42027000, 0x00000041,
+ 0x0201f000, 0x0002088d, 0x4a026203, 0x00000007,
+ 0x497a6206, 0x0201f000, 0x000206fd, 0x59325808,
+ 0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800,
+ 0x000206fd, 0x0201f000, 0x0002077d, 0x0201f800,
+ 0x0010a597, 0x040007fa, 0x1c01f000, 0x0201f800,
+ 0x00106b8a, 0x59325808, 0x59326809, 0x59340200,
+ 0x8c00050e, 0x0400000e, 0x592c040a, 0x82000500,
+ 0x000000c0, 0x82000580, 0x00000080, 0x04000005,
+ 0x592c000f, 0x59301815, 0x800c1c80, 0x480e6015,
+ 0x4a026203, 0x00000002, 0x0401f00d, 0x42028000,
+ 0x00000004, 0x0401fbde, 0x59300206, 0x80000540,
+ 0x04020004, 0x59a80038, 0x800000c2, 0x48026206,
+ 0x497a6008, 0x4a026203, 0x00000007, 0x1c01f000,
+ 0x4a026203, 0x00000007, 0x497a6206, 0x0201f000,
+ 0x000206fd, 0x4a026203, 0x00000007, 0x497a6206,
+ 0x0201f000, 0x000206f8, 0x59300414, 0x8c00051c,
+ 0x02020000, 0x0002087e, 0x59325808, 0x592c200f,
+ 0x40080000, 0x80102480, 0x59300015, 0x80102400,
+ 0x48126015, 0x0201f000, 0x0002087e, 0x8c040d0e,
+ 0x0402000a, 0x4a026203, 0x00000006, 0x0401f823,
+ 0x5930001f, 0x80000540, 0x02020800, 0x00100d7c,
+ 0x0201f000, 0x000206f8, 0x4a026203, 0x00000002,
+ 0x1c01f000, 0x42000800, 0x00000001, 0x0201f800,
+ 0x00100d7c, 0x82040580, 0x00000001, 0x02000000,
+ 0x00020885, 0x0401f7d8, 0x59300414, 0x8c00051c,
+ 0x04000006, 0x0201f800, 0x00100b63, 0x02000000,
+ 0x00020877, 0x1c01f000, 0x59300011, 0x80000540,
+ 0x04020005, 0x0201f800, 0x00100b63, 0x02000000,
+ 0x00020877, 0x1c01f000, 0x492fc857, 0x480bc857,
+ 0x8c08153e, 0x04000006, 0x80081080, 0x80081000,
+ 0x42000800, 0x00000009, 0x0401f003, 0x42000800,
+ 0x00000015, 0x480a580b, 0x1c01f000, 0x83380580,
+ 0x00000013, 0x04000005, 0x83380580, 0x00000014,
+ 0x02020800, 0x001005d8, 0x59300414, 0x8c000516,
+ 0x02000800, 0x001005d8, 0x1c01f000, 0x0201f800,
+ 0x001005d8, 0x59300008, 0x80000540, 0x02020800,
+ 0x001005d8, 0x1c01f000, 0x59300414, 0x8c000516,
+ 0x02000800, 0x001005d8, 0x1c01f000, 0x4a026203,
+ 0x00000004, 0x493a6403, 0x42000800, 0x80002001,
+ 0x0201f000, 0x00020721, 0x4a026203, 0x00000003,
+ 0x493a6403, 0x0201f800, 0x000200c9, 0x59325808,
+ 0x592c040a, 0x8c00051e, 0x04000012, 0x82000500,
+ 0x000000c0, 0x82000580, 0x00000080, 0x04000011,
+ 0x59300414, 0x8c000512, 0x0402000a, 0x8c000510,
+ 0x04020008, 0x592c040c, 0x80000540, 0x04020005,
+ 0x82080d40, 0x80003065, 0x0201f000, 0x00106721,
+ 0x82080d40, 0x80002065, 0x0201f000, 0x00106721,
+ 0x82080d40, 0x80002042, 0x0201f000, 0x00106721,
+ 0x4933c857, 0x493bc857, 0x83380480, 0x00000044,
+ 0x02021800, 0x001005d8, 0x83380480, 0x00000041,
+ 0x02001800, 0x001005d8, 0x0c01f001, 0x0010a0b6,
+ 0x0010a0c6, 0x0010a0db, 0x59325808, 0x592c040a,
+ 0x8c00051e, 0x0400001d, 0x82001d00, 0x000000c0,
+ 0x820c1d80, 0x000000c0, 0x04000018, 0x4a026203,
+ 0x00000001, 0x493a6403, 0x42000800, 0x80002042,
+ 0x0201f000, 0x00020721, 0x59325808, 0x592c040a,
+ 0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0,
+ 0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203,
+ 0x00000001, 0x493a6403, 0x42000800, 0x80002001,
+ 0x0201f000, 0x00020721, 0x497a6008, 0x497a6206,
+ 0x42028000, 0x00000004, 0x0401f315, 0x59325808,
+ 0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00,
+ 0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3,
+ 0x4a026203, 0x00000003, 0x493a6403, 0x0201f800,
+ 0x000200c9, 0x82080d40, 0x80002065, 0x0201f000,
+ 0x00106721, 0x4933c857, 0x493bc857, 0x83380580,
+ 0x00000085, 0x04000006, 0x83380580, 0x00000088,
+ 0x0400000a, 0x0201f800, 0x001005d8, 0x4a026203,
+ 0x00000009, 0x493a6403, 0x42000800, 0x8000004b,
+ 0x0201f000, 0x00020721, 0x4d1c0000, 0x813669c0,
+ 0x04000004, 0x0201f800, 0x0010a592, 0x04020044,
+ 0x59cc1404, 0x0401f846, 0x04000018, 0x591c0406,
+ 0x82000500, 0x0000001f, 0x82002580, 0x00000006,
+ 0x04000007, 0x82002580, 0x00000004, 0x0400002e,
+ 0x82002580, 0x00000011, 0x0402000c, 0x497a3a05,
+ 0x42002000, 0x00000054, 0x0201f800, 0x00107a4a,
+ 0x4a026203, 0x00000007, 0x493a6403, 0x0201f800,
+ 0x0010a974, 0x0401f02c, 0x0201f800, 0x00103b25,
+ 0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1,
+ 0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800,
+ 0x00105c9a, 0x0402001e, 0x0201f800, 0x001045a6,
+ 0x0402001b, 0x49366009, 0x4a026403, 0x00000087,
+ 0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003,
+ 0x4a026403, 0x00000086, 0x4a026203, 0x00000001,
+ 0x42000800, 0x80000040, 0x0201f800, 0x00020721,
+ 0x0401f00d, 0x591c0203, 0x82000580, 0x00000007,
+ 0x040207de, 0x4d300000, 0x411e6000, 0x0201f800,
+ 0x00107911, 0x5c026000, 0x0401f7d8, 0x0201f800,
+ 0x00107911, 0x5c023800, 0x1c01f000, 0x4933c857,
+ 0x480bc857, 0x42002800, 0x0010d1c0, 0x41300000,
+ 0x80140580, 0x04000017, 0x58140203, 0x82000580,
+ 0x00000000, 0x04000013, 0x58140202, 0x80080580,
+ 0x04020010, 0x58141c06, 0x820c0580, 0x00000005,
+ 0x0400000c, 0x820c0580, 0x00000009, 0x0400001d,
+ 0x59302009, 0x58140009, 0x800001c0, 0x0400000b,
+ 0x801021c0, 0x04000003, 0x80100580, 0x04000010,
+ 0x82142c00, 0x00000024, 0x41540000, 0x80140480,
+ 0x0402100e, 0x0401f7e2, 0x5814001e, 0x801021c0,
+ 0x04000005, 0x58102002, 0x82102500, 0x00ffffff,
+ 0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800,
+ 0x81300540, 0x0401f002, 0x80000580, 0x1c01f000,
+ 0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1,
+ 0x4933c857, 0x493bc857, 0x83380580, 0x00000013,
+ 0x0402000e, 0x59300403, 0x82000c80, 0x00000085,
+ 0x02001800, 0x001005d8, 0x82000c80, 0x00000093,
+ 0x02021800, 0x001005d8, 0x82000480, 0x00000085,
+ 0x4803c857, 0x0c01f018, 0x83380580, 0x00000027,
+ 0x04000005, 0x83380580, 0x00000014, 0x02020000,
+ 0x00107974, 0x0201f800, 0x00106bbf, 0x59325808,
+ 0x812e59c0, 0x02000000, 0x00107911, 0x4a025a06,
+ 0x00000031, 0x4a025811, 0x00000004, 0x4a025812,
+ 0x000000ff, 0x0201f800, 0x000202da, 0x0201f000,
+ 0x00107911, 0x0010a1b7, 0x0010a1be, 0x0010a1be,
+ 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7,
+ 0x0010a1b7, 0x0010a1b7, 0x0010a1b7, 0x0010a1b7,
+ 0x0010a1b7, 0x0010a1b7, 0x0010a1b9, 0x0201f800,
+ 0x001005d8, 0x59325808, 0x4a025a06, 0x00000000,
+ 0x0201f800, 0x000202da, 0x0201f000, 0x00107911,
+ 0x4933c857, 0x42000000, 0x0010b873, 0x0201f800,
+ 0x0010aa47, 0x0201f800, 0x0010a5df, 0x497a6205,
+ 0x42028000, 0x0000000b, 0x0401f807, 0x4a026406,
+ 0x00000006, 0x4a026203, 0x00000007, 0x497a6206,
+ 0x1c01f000, 0x4933c857, 0x4943c857, 0x59300406,
+ 0x82000580, 0x00000007, 0x04020002, 0x1c01f000,
+ 0x0201f800, 0x00106c55, 0x4df00000, 0x0201f800,
+ 0x00108ce5, 0x82000c80, 0x0000000e, 0x02021800,
+ 0x001005d8, 0x0c01f001, 0x0010a205, 0x0010a209,
+ 0x0010a1f0, 0x0010a217, 0x0010a22a, 0x0010a1f0,
+ 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0,
+ 0x0010a1f0, 0x0010a1f0, 0x0010a1f0, 0x0010a1f0,
+ 0x4d400000, 0x5930001f, 0x80000540, 0x04000005,
+ 0x41400800, 0x0201f800, 0x00100d7c, 0x40068000,
+ 0x4d2c0000, 0x59325808, 0x0201f800, 0x00109037,
+ 0x040209f3, 0x4c5c0000, 0x5930b809, 0x0201f800,
+ 0x00107911, 0x485e6009, 0x5c00b800, 0x5c025800,
+ 0x5c028000, 0x5c03e000, 0x02000000, 0x00106c4b,
+ 0x1c01f000, 0x598c000d, 0x81300580, 0x04020004,
+ 0x0201f800, 0x00106e8e, 0x04020016, 0x0201f800,
+ 0x001068d3, 0x040007df, 0x0201f800, 0x00106b6c,
+ 0x04000010, 0x0201f800, 0x001005d8, 0x0201f800,
+ 0x00108cd6, 0x04020004, 0x0201f800, 0x00106e62,
+ 0x04020008, 0x0201f800, 0x001067ae, 0x040007d1,
+ 0x0201f800, 0x00106b6c, 0x02020800, 0x001005d8,
+ 0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
+ 0x001005d8, 0x0c01f7b9, 0x0201f800, 0x00100e99,
+ 0x0401f7c4, 0x4933c857, 0x4d440000, 0x4d340000,
+ 0x59cc0007, 0x0201f800, 0x00105c9a, 0x02000800,
+ 0x00020245, 0x0402001a, 0x59300009, 0x4c000000,
+ 0x49366009, 0x42003000, 0x0000000b, 0x0201f800,
+ 0x0010a942, 0x42000000, 0x0010b861, 0x0201f800,
+ 0x0010aa47, 0x4d3c0000, 0x4d400000, 0x42028000,
+ 0x00000029, 0x417a7800, 0x0201f800, 0x0010203c,
+ 0x5c028000, 0x5c027800, 0x5c000000, 0x48026009,
+ 0x59cc0007, 0x48026802, 0x80000580, 0x5c026800,
+ 0x5c028800, 0x1c01f000, 0x4933c857, 0x4c040000,
+ 0x59a80016, 0x82000580, 0x00000074, 0x04020040,
+ 0x59cc0a08, 0x82040480, 0x00000100, 0x04001033,
+ 0x59cc0c08, 0x82040500, 0x00008000, 0x04000035,
+ 0x59a80032, 0x80000540, 0x04020009, 0x59301009,
+ 0x58080212, 0x82000500, 0x0000ff00, 0x04000004,
+ 0x82040500, 0x00000800, 0x0400002a, 0x59cc0c09,
+ 0x80040840, 0x04001024, 0x59a80826, 0x8c040d06,
+ 0x04000004, 0x59cc0c0f, 0x8c040d1e, 0x04020012,
+ 0x59cc0a17, 0x800409c0, 0x04020012, 0x59cc0a18,
+ 0x82040480, 0x00000100, 0x04001014, 0x59cc0c18,
+ 0x800409c0, 0x0402000e, 0x59cc0c19, 0x80040840,
+ 0x04001011, 0x59cc0c1a, 0x80040840, 0x04001011,
+ 0x0401f018, 0x4a02621a, 0x00000100, 0x0401f012,
+ 0x4a02621a, 0x00000300, 0x0401f00f, 0x4a02621a,
+ 0x00000500, 0x0401f00c, 0x4a02621a, 0x00000700,
+ 0x0401f009, 0x4a02621a, 0x00000900, 0x0401f006,
+ 0x4a02621a, 0x00000f00, 0x0401f003, 0x4a02621a,
+ 0x00002d00, 0x82000540, 0x00000001, 0x0401f002,
+ 0x80000580, 0x5c000800, 0x1c01f000, 0x59cc0407,
+ 0x4803c857, 0x82000580, 0x00000800, 0x04000003,
+ 0x4a02621a, 0x00000000, 0x1c01f000, 0x4933c857,
+ 0x4c040000, 0x4c080000, 0x4c0c0000, 0x4c580000,
+ 0x59cc000c, 0x0201f800, 0x00105c9a, 0x02000800,
+ 0x00020245, 0x04020012, 0x83cc1400, 0x00000008,
+ 0x4200b000, 0x00000002, 0x83341c00, 0x00000006,
+ 0x0201f800, 0x0010855a, 0x04020009, 0x83cc1400,
+ 0x0000000a, 0x4200b000, 0x00000002, 0x83341c00,
+ 0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000,
+ 0x5c001800, 0x5c001000, 0x5c000800, 0x1c01f000,
+ 0x4933c857, 0x4c000000, 0x4c040000, 0x4c080000,
+ 0x4c0c0000, 0x4c580000, 0x59cc0001, 0x0201f800,
+ 0x00105c9a, 0x02000800, 0x00020245, 0x04020014,
+ 0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
+ 0x83341c00, 0x00000006, 0x0201f800, 0x0010855a,
+ 0x0402000c, 0x83cc1400, 0x0000000d, 0x4200b000,
+ 0x00000002, 0x83341c00, 0x00000008, 0x0201f800,
+ 0x0010855a, 0x04000014, 0x4933c856, 0x4933c856,
+ 0x4933c857, 0x59340009, 0x4803c857, 0x5934000e,
+ 0x4803c857, 0x59340008, 0x4803c857, 0x5934000d,
+ 0x4803c857, 0x59340007, 0x4803c857, 0x5934000c,
+ 0x4803c857, 0x59340006, 0x4803c857, 0x5934000b,
+ 0x4803c857, 0x5c00b000, 0x5c001800, 0x5c001000,
+ 0x5c000800, 0x5c000000, 0x1c01f000, 0x4933c857,
+ 0x4947c857, 0x4943c857, 0x4c600000, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x4d2c0000, 0x4d300000,
+ 0x4d340000, 0x4130c000, 0x42026000, 0x0010d1c0,
+ 0x59a8000e, 0x8060c1c0, 0x04000005, 0x82601580,
+ 0x0010bde9, 0x04000002, 0x80000040, 0x81640480,
+ 0x040210be, 0x40600000, 0x81300580, 0x040000b6,
+ 0x0401f97a, 0x040200b4, 0x59326809, 0x59300406,
+ 0x82000c80, 0x00000012, 0x02021800, 0x001005d8,
+ 0x0c01f001, 0x0010a3cd, 0x0010a338, 0x0010a351,
+ 0x0010a35c, 0x0010a335, 0x0010a34c, 0x0010a387,
+ 0x0010a3cd, 0x0010a333, 0x0010a39a, 0x0010a3ae,
+ 0x0010a333, 0x0010a333, 0x0010a333, 0x0010a333,
+ 0x0010a3cd, 0x0010a3c4, 0x0010a3bc, 0x0201f800,
+ 0x001005d8, 0x59300420, 0x8c000500, 0x04020096,
+ 0x59300403, 0x82000580, 0x00000043, 0x04000092,
+ 0x0201f800, 0x00109134, 0x04000007, 0x0201f800,
+ 0x0010914e, 0x0402008a, 0x0201f800, 0x0010801c,
+ 0x0401f087, 0x0201f800, 0x00102074, 0x0201f800,
+ 0x0010914e, 0x02000800, 0x0010801c, 0x0401f080,
+ 0x8d3e7d18, 0x04000004, 0x59300420, 0x8c000500,
+ 0x0402007d, 0x59325808, 0x0201f800, 0x00109037,
+ 0x04000077, 0x49425a06, 0x497a5c09, 0x0201f800,
+ 0x000202da, 0x0201f800, 0x0010912a, 0x0401f070,
+ 0x8d3e7d00, 0x04000007, 0x59300017, 0x81480580,
+ 0x0402006d, 0x59300018, 0x814c0580, 0x0402006a,
+ 0x59300203, 0x82000580, 0x00000004, 0x02000800,
+ 0x00100e99, 0x59325808, 0x0201f800, 0x00109037,
+ 0x0400005f, 0x4a025a04, 0x00000103, 0x59300004,
+ 0x8400055c, 0x48026004, 0x592c0408, 0x8c000512,
+ 0x04000007, 0x4d2c0000, 0x592c0009, 0x40025800,
+ 0x0201f800, 0x001007fd, 0x5c025800, 0x49425a06,
+ 0x497a5c09, 0x0401fb16, 0x0201f800, 0x0010959c,
+ 0x0201f800, 0x001091c6, 0x0201f800, 0x000202da,
+ 0x0201f800, 0x0010912a, 0x0401f045, 0x8d3e7d18,
+ 0x04000045, 0x59300203, 0x82000580, 0x00000004,
+ 0x02000800, 0x00100e99, 0x59325808, 0x0201f800,
+ 0x00109037, 0x0400003a, 0x49425a06, 0x497a5c09,
+ 0x0401faff, 0x0201f800, 0x0010959c, 0x0201f800,
+ 0x000202da, 0x0401f032, 0x0201f800, 0x001062d5,
+ 0x04000031, 0x59300203, 0x82000580, 0x00000004,
+ 0x0400002d, 0x59300203, 0x82000580, 0x00000003,
+ 0x04020029, 0x0201f800, 0x00106b8a, 0x59325808,
+ 0x0201f800, 0x00109037, 0x04000021, 0x0201f800,
+ 0x000202da, 0x0401f01e, 0x59300203, 0x82000580,
+ 0x00000004, 0x02000800, 0x00100e99, 0x59325808,
+ 0x0201f800, 0x00109037, 0x04000015, 0x49425a06,
+ 0x497a5c09, 0x0201f800, 0x000202da, 0x0401f010,
+ 0x833c0500, 0x00001800, 0x0400000f, 0x8d3e7d16,
+ 0x0402000d, 0x59325817, 0x0201f800, 0x001007fd,
+ 0x59325808, 0x0201f800, 0x00109037, 0x04000004,
+ 0x49425a06, 0x0201f800, 0x000202da, 0x0201f800,
+ 0x00107911, 0x83326400, 0x00000024, 0x41580000,
+ 0x81300480, 0x0400173b, 0x5c026800, 0x5c026000,
+ 0x5c025800, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x5c00c000, 0x1c01f000, 0x5c000000, 0x4c000000,
+ 0x4803c857, 0x4d3c0000, 0x42027800, 0x00000001,
+ 0x0201f800, 0x00104567, 0x5c027800, 0x4c580000,
+ 0x4200b000, 0x00000002, 0x83a81c00, 0x00000002,
+ 0x83cc1400, 0x0000000b, 0x0201f800, 0x0010855a,
+ 0x5c00b000, 0x80000540, 0x1c01f000, 0x492fc857,
+ 0x4943c857, 0x59a8000c, 0x812c0480, 0x04001011,
+ 0x59a8000d, 0x812c0480, 0x0402100e, 0x592c0000,
+ 0x80005d40, 0x04000008, 0x497a5800, 0x49425a06,
+ 0x4c2c0000, 0x0201f800, 0x000202da, 0x5c025800,
+ 0x0401f7f7, 0x49425a06, 0x0201f000, 0x000202da,
+ 0x1c01f000, 0x493fc857, 0x4933c857, 0x480bc857,
+ 0x0201f800, 0x00103b25, 0x0400002e, 0x41502800,
+ 0x813e79c0, 0x04020006, 0x59a80066, 0x80000000,
+ 0x59a8086a, 0x80040580, 0x04000026, 0x41300000,
+ 0x80140580, 0x0400001a, 0x58140203, 0x82000580,
+ 0x00000000, 0x04000016, 0x58140202, 0x80080580,
+ 0x04020013, 0x58141c06, 0x820c0580, 0x00000005,
+ 0x0400000f, 0x820c0580, 0x00000009, 0x04000017,
+ 0x59300009, 0x58142009, 0x801021c0, 0x04020006,
+ 0x5814201e, 0x59301809, 0x580c0002, 0x82000500,
+ 0x00ffffff, 0x80100580, 0x04000007, 0x82142c00,
+ 0x00000024, 0x41540000, 0x80140480, 0x04021005,
+ 0x0401f7df, 0x40163800, 0x81300540, 0x0401f002,
+ 0x80000580, 0x1c01f000, 0x58141807, 0x8c0c1d10,
+ 0x040207f3, 0x0401f7e7, 0x42002000, 0x0000ffff,
+ 0x59301009, 0x800811c0, 0x04000002, 0x58082403,
+ 0x41301000, 0x0401f007, 0x41781000, 0x41442000,
+ 0x0401f004, 0x41781000, 0x42002000, 0x0000ffff,
+ 0x5c000000, 0x4c000000, 0x4803c857, 0x480bc857,
+ 0x4813c857, 0x492fc857, 0x4943c857, 0x4d2c0000,
+ 0x0201f800, 0x001007e4, 0x02000800, 0x001005d8,
+ 0x4a025a04, 0x0000010d, 0x800811c0, 0x04000017,
+ 0x83400580, 0x00000029, 0x04020010, 0x82180580,
+ 0x00000002, 0x0400000a, 0x82180580, 0x00000003,
+ 0x04000007, 0x82180580, 0x00000008, 0x04000004,
+ 0x82180580, 0x00000009, 0x04020004, 0x4a025809,
+ 0xffffffff, 0x0401f002, 0x480a5809, 0x58080202,
+ 0x48025c13, 0x0401f005, 0x4a025809, 0xffffffff,
+ 0x4a025c13, 0x0000ffff, 0x49425a08, 0x48125a06,
+ 0x82100580, 0x0000ffff, 0x0400000e, 0x4d440000,
+ 0x4d340000, 0x40128800, 0x0201f800, 0x00020245,
+ 0x02020800, 0x001005d8, 0x59340002, 0x82000500,
+ 0x00ffffff, 0x48025812, 0x5c026800, 0x5c028800,
+ 0x497a5800, 0x497a5c04, 0x83400580, 0x00000046,
+ 0x04020002, 0x48165a07, 0x481a5c08, 0x0401fbed,
+ 0x5c025800, 0x1c01f000, 0x59300809, 0x800409c0,
+ 0x04000004, 0x58040403, 0x81440580, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x0401f7fd, 0x4933c857,
+ 0x4c040000, 0x59300403, 0x82000d80, 0x0000001e,
+ 0x04020016, 0x800000d0, 0x59300a16, 0x82040d00,
+ 0x000000ff, 0x80040540, 0x4803c857, 0x48026416,
+ 0x4a026403, 0x00000085, 0x4a026203, 0x00000009,
+ 0x4a026406, 0x00000005, 0x4a02621d, 0x00000004,
+ 0x59a80038, 0x48026206, 0x42000800, 0x8000004b,
+ 0x0201f800, 0x00020721, 0x5c000800, 0x1c01f000,
+ 0x4933c857, 0x40000000, 0x40000000, 0x1c01f000,
+ 0x59300414, 0x4933c857, 0x4803c857, 0x8c000518,
+ 0x04000009, 0x8c000512, 0x02020000, 0x0010921e,
+ 0x0401f91b, 0x0201f800, 0x000206fd, 0x0201f800,
+ 0x0002077d, 0x1c01f000, 0x591c0406, 0x4803c857,
+ 0x82000c80, 0x00000009, 0x0402100b, 0x0c01f001,
+ 0x0010a4d9, 0x0010a4d9, 0x0010a4d9, 0x0010a4db,
+ 0x0010a4d9, 0x0010a4db, 0x0010a4db, 0x0010a4d9,
+ 0x0010a4db, 0x80000580, 0x1c01f000, 0x82000540,
+ 0x00000001, 0x1c01f000, 0x591c0406, 0x82000500,
+ 0x0000001f, 0x82000580, 0x00000006, 0x0400000e,
+ 0x4803c857, 0x4a026403, 0x0000003b, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00002a00, 0x4a026203,
+ 0x00000001, 0x42000800, 0x80000040, 0x0201f000,
+ 0x00020721, 0x4803c856, 0x4c040000, 0x4c140000,
+ 0x4d300000, 0x411e6000, 0x0401f8e9, 0x497a6205,
+ 0x59300414, 0x4803c857, 0x82000500, 0xffffadff,
+ 0x48026414, 0x497a6405, 0x5c026000, 0x0201f800,
+ 0x001007e4, 0x02000800, 0x001005d8, 0x5c002800,
+ 0x5c000800, 0x4a025a04, 0x0000010d, 0x497a5800,
+ 0x497a5c04, 0x4a025a08, 0x00000045, 0x491e5809,
+ 0x59300402, 0x48025c07, 0x59300419, 0x48025c0b,
+ 0x591c0414, 0x84000556, 0x48023c14, 0x591c1809,
+ 0x580c0403, 0x48025a06, 0x4816580a, 0x48065a0b,
+ 0x0401f99d, 0x4d400000, 0x42028000, 0x00000045,
+ 0x591c0202, 0x4c000000, 0x4d300000, 0x411e6000,
+ 0x0401fcb1, 0x5c026000, 0x5c000000, 0x48023a02,
+ 0x5c028000, 0x4a023c06, 0x00000006, 0x4a023a03,
+ 0x00000007, 0x497a3a06, 0x497a3a05, 0x1c01f000,
+ 0x4933c857, 0x83380580, 0x00000013, 0x0402000b,
+ 0x59300403, 0x4803c857, 0x82000d80, 0x00000085,
+ 0x0400002b, 0x82000d80, 0x0000008b, 0x04000028,
+ 0x0201f800, 0x001005d8, 0x83380580, 0x00000027,
+ 0x0402000c, 0x0201f800, 0x00106bbf, 0x4d2c0000,
+ 0x4d400000, 0x59325808, 0x42028000, 0x00000004,
+ 0x0401feab, 0x5c028000, 0x5c025800, 0x1c01f000,
+ 0x83380580, 0x00000014, 0x040007f3, 0x83380580,
+ 0x00000089, 0x04000005, 0x83380580, 0x0000008a,
+ 0x02020000, 0x00107974, 0x0201f800, 0x00106f60,
+ 0x02020000, 0x00107974, 0x59300a03, 0x82040580,
+ 0x0000000a, 0x04000009, 0x82040580, 0x0000000c,
+ 0x04000006, 0x0201f800, 0x001005d8, 0x4a026203,
+ 0x0000000a, 0x1c01f000, 0x83380480, 0x00000093,
+ 0x0402100c, 0x83380480, 0x00000085, 0x04001009,
+ 0x83380580, 0x00000089, 0x0400000a, 0x83380580,
+ 0x0000008a, 0x04000022, 0x0201f800, 0x001005d8,
+ 0x493bc857, 0x4933c857, 0x0201f000, 0x00107974,
+ 0x4933c857, 0x4c340000, 0x41306800, 0x0201f800,
+ 0x0002075a, 0x04000011, 0x4a026203, 0x00000001,
+ 0x4a026403, 0x0000001e, 0x59cc0c07, 0x48066419,
+ 0x59cc0a07, 0x48066219, 0x58340809, 0x48066009,
+ 0x4a026406, 0x00000004, 0x42000800, 0x80000040,
+ 0x0201f800, 0x00020721, 0x40366000, 0x0201f800,
+ 0x0002077d, 0x5c006800, 0x1c01f000, 0x4933c857,
+ 0x0201f000, 0x0002077d, 0x4933c857, 0x59300809,
+ 0x58040200, 0x8c00051a, 0x1c01f000, 0x0201f800,
+ 0x001048df, 0x0400001e, 0x4a026203, 0x00000002,
+ 0x59300414, 0x84000558, 0x48026414, 0x8c000512,
+ 0x04000004, 0x59a80039, 0x48026205, 0x0401f007,
+ 0x59a80839, 0x59a80037, 0x80040400, 0x82000400,
+ 0x0000000a, 0x48026205, 0x59300009, 0x82000c00,
+ 0x00000011, 0x50040000, 0x80000540, 0x04000004,
+ 0x82000c00, 0x00000000, 0x0401f7fb, 0x45300800,
+ 0x497a6000, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x82100500, 0xfffffeef, 0x04020020, 0x4d2c0000,
+ 0x4937c857, 0x59340811, 0x83341400, 0x00000011,
+ 0x800409c0, 0x0400000e, 0x40040000, 0x81300580,
+ 0x04000005, 0x58040800, 0x82041400, 0x00000000,
+ 0x0401f7f8, 0x59300800, 0x497a6000, 0x44041000,
+ 0x0201f800, 0x000206fd, 0x0401f002, 0x4933c857,
+ 0x592c0000, 0x80000540, 0x02020800, 0x001005d8,
+ 0x5c025800, 0x492e6008, 0x0201f800, 0x000206fd,
+ 0x0201f000, 0x0002077d, 0x492fc857, 0x4a025a06,
+ 0x00000006, 0x0201f000, 0x000202da, 0x4c340000,
+ 0x59300009, 0x800001c0, 0x04000010, 0x82006c00,
+ 0x00000011, 0x50340000, 0x80000540, 0x04000009,
+ 0x81300580, 0x04000005, 0x50340000, 0x82006c00,
+ 0x00000000, 0x0401f7f8, 0x59300000, 0x44006800,
+ 0x5c006800, 0x1c01f000, 0x59300c06, 0x82040580,
+ 0x00000005, 0x040007fb, 0x82040580, 0x00000011,
+ 0x040007f8, 0x82040580, 0x00000006, 0x040007f5,
+ 0x82040580, 0x00000001, 0x040007f2, 0x0201f800,
+ 0x001005d8, 0x4933c857, 0x4c080000, 0x4c0c0000,
+ 0x4c580000, 0x59a8101d, 0x59cc1807, 0x820c1d00,
+ 0x00ffffff, 0x800c0110, 0x80083580, 0x04020014,
+ 0x83cc1400, 0x00000008, 0x4200b000, 0x00000002,
+ 0x59300009, 0x82001c00, 0x00000006, 0x0201f800,
+ 0x0010855a, 0x0402000a, 0x83cc1400, 0x0000000a,
+ 0x4200b000, 0x00000002, 0x59300009, 0x82001c00,
+ 0x00000008, 0x0201f800, 0x0010855a, 0x5c00b000,
+ 0x5c001800, 0x5c001000, 0x1c01f000, 0x4933c856,
+ 0x0201f800, 0x0010421b, 0x0201f000, 0x00101e45,
+ 0x493bc857, 0x4d2c0000, 0x0201f800, 0x001007e4,
+ 0x02000800, 0x001005d8, 0x832cac00, 0x00000005,
+ 0x4c580000, 0x4c540000, 0x4200b000, 0x00000006,
+ 0x4578a800, 0x8054a800, 0x8058b040, 0x040207fd,
+ 0x83380580, 0x00000046, 0x04020004, 0x4a025a04,
+ 0x00000144, 0x0401f008, 0x4a025a04, 0x00000146,
+ 0x83380580, 0x00000041, 0x04000003, 0x4a025a06,
+ 0x00000001, 0x59cc0007, 0x82000500, 0xff000000,
+ 0x80000110, 0x59cc1008, 0x82081500, 0xff000000,
+ 0x80081540, 0x480a580a, 0x83380580, 0x00000046,
+ 0x04020006, 0x59cc0007, 0x82000500, 0x00ffffff,
+ 0x4802580b, 0x0401f005, 0x59cc0008, 0x82000500,
+ 0x00ffffff, 0x4802580b, 0x83380580, 0x00000046,
+ 0x04020004, 0x83cc1400, 0x00000009, 0x0401f003,
+ 0x83cc1400, 0x0000000d, 0x50080000, 0x9c0001c0,
+ 0x4802580c, 0x80081000, 0x50080000, 0x9c0001c0,
+ 0x4802580d, 0x83380580, 0x00000046, 0x04020008,
+ 0x59cc000b, 0x9c0001c0, 0x4802580e, 0x59cc000c,
+ 0x9c0001c0, 0x4802580f, 0x0401f007, 0x59cc000f,
+ 0x9c0001c0, 0x4802580e, 0x59cc0010, 0x9c0001c0,
+ 0x4802580f, 0x83380580, 0x00000046, 0x04020004,
+ 0x83cc1400, 0x00000011, 0x0401f003, 0x83cc1400,
+ 0x00000015, 0x412c3000, 0x82183400, 0x00000010,
+ 0x4200b000, 0x00000004, 0x50080000, 0x9c0001c0,
+ 0x44003000, 0x80081000, 0x80183000, 0x8058b040,
+ 0x040207fa, 0x5c00a800, 0x5c00b000, 0x0201f800,
+ 0x000202da, 0x5c025800, 0x1c01f000, 0x4933c857,
+ 0x492fc857, 0x59300809, 0x58040200, 0x8c00051e,
+ 0x04000004, 0x592c0208, 0x84000558, 0x48025a08,
+ 0x1c01f000, 0x59e0180f, 0x599c0413, 0x800c1000,
+ 0x80080580, 0x04020002, 0x41781000, 0x59e00010,
+ 0x59e00810, 0x80040d80, 0x040207fd, 0x80080580,
+ 0x0400000b, 0x4c080000, 0x599c0814, 0x599c1015,
+ 0x800c00cc, 0x80040c00, 0x82081440, 0x00000000,
+ 0x5c001800, 0x82000540, 0x00000001, 0x4803c857,
+ 0x1c01f000, 0x492fc857, 0x42007000, 0x0010b7f8,
+ 0x58380807, 0x800409c0, 0x04020005, 0x492c7008,
+ 0x492c7007, 0x0201f000, 0x00100875, 0x492c0800,
+ 0x492c7007, 0x1c01f000, 0x59300203, 0x4933c857,
+ 0x4937c857, 0x493bc857, 0x4803c857, 0x82003480,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001,
+ 0x0010a6da, 0x0010a82c, 0x0010a6da, 0x0010a6da,
+ 0x0010a6da, 0x0010a6da, 0x0010a6da, 0x0010a791,
+ 0x0010a6dc, 0x0010a6da, 0x0010a6da, 0x0010a6da,
+ 0x0010a6da, 0x0010a6da, 0x0201f800, 0x001005d8,
+ 0x83380580, 0x0000004c, 0x02020800, 0x001005d8,
+ 0x0201f800, 0x001048ec, 0x04020020, 0x59a80826,
+ 0x82040500, 0x00000009, 0x82000580, 0x00000008,
+ 0x0400001a, 0x8c040d12, 0x0400003d, 0x59cc0806,
+ 0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+ 0x0400001f, 0x82040580, 0x50000000, 0x04000005,
+ 0x82040580, 0x52000000, 0x02020000, 0x0002077d,
+ 0x813669c0, 0x04000006, 0x4d3c0000, 0x417a7800,
+ 0x0201f800, 0x0010203c, 0x5c027800, 0x4a026403,
+ 0x00000001, 0x0401f014, 0x59cc0806, 0x82040d00,
+ 0xff000000, 0x82040580, 0x03000000, 0x04000008,
+ 0x82040580, 0x50000000, 0x04000005, 0x82040580,
+ 0x52000000, 0x02020000, 0x0002077d, 0x4a026403,
+ 0x00000009, 0x4a02641a, 0x00000009, 0x4a02621a,
+ 0x00000000, 0x813669c0, 0x0402000b, 0x59cc0001,
+ 0x0201f800, 0x00105c9a, 0x02020000, 0x0002077d,
+ 0x0201f800, 0x001045a6, 0x02020000, 0x0002077d,
+ 0x49366009, 0x4a026406, 0x00000004, 0x4a026203,
+ 0x00000001, 0x0201f000, 0x0010672b, 0x0201f800,
+ 0x00103b25, 0x04000023, 0x59cc0806, 0x4807c857,
+ 0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+ 0x04000033, 0x82040580, 0x20000000, 0x04000041,
+ 0x82040580, 0x21000000, 0x04000052, 0x82040580,
+ 0x24000000, 0x0400004f, 0x82040580, 0x50000000,
+ 0x0400004c, 0x82040580, 0x52000000, 0x04000049,
+ 0x82040580, 0x05000000, 0x0402000d, 0x59cc0806,
+ 0x82040d00, 0xff000000, 0x9c0431c0, 0x42028000,
+ 0x00000046, 0x42002800, 0x00000001, 0x0401fcf3,
+ 0x0401f93c, 0x02000800, 0x001005d8, 0x42002000,
+ 0x00000051, 0x0201f800, 0x00107a4a, 0x59cc0000,
+ 0x82000500, 0x00ffffff, 0x82000580, 0x00ffffff,
+ 0x04000005, 0x4a026203, 0x00000007, 0x493a6403,
+ 0x1c01f000, 0x59325817, 0x812e59c0, 0x02020800,
+ 0x001007fd, 0x0201f000, 0x0002077d, 0x813669c0,
+ 0x040007df, 0x59340400, 0x82000500, 0x000000ff,
+ 0x82000580, 0x00000003, 0x040207d9, 0x0401fc6f,
+ 0x040207d7, 0x4a026403, 0x00000009, 0x4a02641a,
+ 0x0000000e, 0x4a02621a, 0x00001900, 0x0401f7a2,
+ 0x813669c0, 0x0400000c, 0x59340c00, 0x82040500,
+ 0x000000ff, 0x82000580, 0x00000009, 0x04000794,
+ 0x82040500, 0x0000ff00, 0x82000580, 0x00000700,
+ 0x040207c3, 0x4a026403, 0x00000009, 0x4a02641a,
+ 0x00000009, 0x4a02621a, 0x00001e00, 0x0401f78e,
+ 0x813669c0, 0x040007f8, 0x59340c00, 0x82040500,
+ 0x0000ff00, 0x82000580, 0x00000700, 0x040007f2,
+ 0x0401f7b3, 0x4d2c0000, 0x4c580000, 0x4c500000,
+ 0x4c540000, 0x41385000, 0x83380580, 0x00000054,
+ 0x02020800, 0x001005d8, 0x59325808, 0x592c0c0b,
+ 0x82040d00, 0x0000e000, 0x82040580, 0x00002000,
+ 0x04020076, 0x59300817, 0x800409c0, 0x04000014,
+ 0x58041404, 0x41cca800, 0x8204a400, 0x00000005,
+ 0x82080480, 0x00000010, 0x04021004, 0x4008b000,
+ 0x0401fb6b, 0x0401f00a, 0x40001000, 0x4200b000,
+ 0x0000000f, 0x0401fb66, 0x58040801, 0x800409c0,
+ 0x040207f2, 0x0201f800, 0x001005d8, 0x813669c0,
+ 0x0400005e, 0x59344c00, 0x592c0c09, 0x4807c857,
+ 0x4827c857, 0x82040d00, 0x000000ff, 0x82040580,
+ 0x00000003, 0x0400002a, 0x82040580, 0x00000005,
+ 0x04000032, 0x82040580, 0x00000020, 0x04000036,
+ 0x82040580, 0x00000052, 0x04000042, 0x82040580,
+ 0x00000050, 0x04000042, 0x82040580, 0x00000021,
+ 0x04000004, 0x82040580, 0x00000024, 0x04020043,
+ 0x82240500, 0x0000ff00, 0x82000580, 0x00000007,
+ 0x04000008, 0x42000800, 0x00000009, 0x0201f800,
+ 0x00104571, 0x42005000, 0x0000000c, 0x0401f037,
+ 0x4a025a06, 0x00000031, 0x4a02580d, 0x00000009,
+ 0x59340400, 0x4802580e, 0x0201f800, 0x000202da,
+ 0x0201f800, 0x00107911, 0x0401f03d, 0x0201f800,
+ 0x001042b4, 0x0201f800, 0x0010462a, 0x42000800,
+ 0x00000003, 0x0201f800, 0x00104571, 0x42005000,
+ 0x00000008, 0x0401f021, 0x59cc0007, 0x0201f800,
+ 0x00105eec, 0x0402001d, 0x0201f800, 0x001042b4,
+ 0x0401f01a, 0x82240500, 0x0000ff00, 0x82000580,
+ 0x00000007, 0x040007df, 0x82240500, 0x000000ff,
+ 0x82000580, 0x00000009, 0x040007da, 0x0201f800,
+ 0x0010468d, 0x42005000, 0x0000000a, 0x0401f00b,
+ 0x42005000, 0x0000000e, 0x0401f003, 0x42005000,
+ 0x00000010, 0x82240500, 0x0000ff00, 0x82000580,
+ 0x00000007, 0x040007cb, 0x482a6403, 0x4a026203,
+ 0x00000001, 0x592c000d, 0x48026011, 0x497a6013,
+ 0x59a80038, 0x48026206, 0x417a7800, 0x0201f800,
+ 0x0010672b, 0x59325817, 0x812e59c0, 0x04000004,
+ 0x0201f800, 0x001007fd, 0x497a6017, 0x5c00a800,
+ 0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000,
+ 0x4d2c0000, 0x59325808, 0x83380580, 0x00000013,
+ 0x04020029, 0x59300c03, 0x82040580, 0x00000054,
+ 0x0400001e, 0x82040580, 0x00000010, 0x04000018,
+ 0x82040580, 0x0000000e, 0x04000015, 0x82040580,
+ 0x00000008, 0x0400000d, 0x82040580, 0x0000000c,
+ 0x0400000a, 0x82040580, 0x0000000a, 0x02020800,
+ 0x001005d8, 0x42000800, 0x00000006, 0x0201f800,
+ 0x00104571, 0x0401f009, 0x42000800, 0x00000004,
+ 0x0201f800, 0x00104571, 0x0401f004, 0x59340200,
+ 0x8400051a, 0x48026a00, 0x4a025a06, 0x00000000,
+ 0x0201f800, 0x000202da, 0x0201f800, 0x0002077d,
+ 0x0401f022, 0x83380580, 0x00000027, 0x0400000e,
+ 0x83380580, 0x00000014, 0x02020800, 0x001005d8,
+ 0x0201f800, 0x00106bbf, 0x42028000, 0x00000031,
+ 0x42000800, 0x00000004, 0x42001000, 0x000000ff,
+ 0x0401f009, 0x0201f800, 0x00106bbf, 0x42028000,
+ 0x00000031, 0x42000800, 0x00000004, 0x42001000,
+ 0x00000010, 0x49425a06, 0x4806580d, 0x480a580e,
+ 0x0201f800, 0x000202da, 0x0201f800, 0x00104c19,
+ 0x0201f800, 0x00107911, 0x5c025800, 0x1c01f000,
+ 0x42007000, 0x0010b7f8, 0x58380807, 0x800409c0,
+ 0x04020005, 0x492c7008, 0x492c7007, 0x0201f000,
+ 0x00100875, 0x492c0800, 0x492c7007, 0x1c01f000,
+ 0x4d2c0000, 0x4c580000, 0x4c500000, 0x4c540000,
+ 0x4933c857, 0x4937c857, 0x59cc0806, 0x4807c857,
+ 0x82040d00, 0xff000000, 0x82040580, 0x03000000,
+ 0x0400000d, 0x82040580, 0x05000000, 0x0400000a,
+ 0x82040580, 0x21000000, 0x04000030, 0x82040580,
+ 0x24000000, 0x0400002d, 0x82040580, 0x20000000,
+ 0x0402002f, 0x0201f800, 0x001007e4, 0x0400002c,
+ 0x492fc857, 0x492e6017, 0x59a8b016, 0x8258b400,
+ 0x0000001b, 0x8258b500, 0xfffffffc, 0x8058b104,
+ 0x485a5c04, 0x412c7800, 0x41cca000, 0x82580480,
+ 0x00000010, 0x04021005, 0x832cac00, 0x00000005,
+ 0x0401fa63, 0x0401f015, 0x40580800, 0x4200b000,
+ 0x0000000f, 0x832cac00, 0x00000005, 0x0401fa5c,
+ 0x8204b480, 0x0000000f, 0x0201f800, 0x001007e4,
+ 0x04000004, 0x492c7801, 0x412c7800, 0x0401f7ec,
+ 0x59325817, 0x0201f800, 0x001007fd, 0x497a6017,
+ 0x80000580, 0x0401f006, 0x59340200, 0x84000554,
+ 0x48026a00, 0x82000540, 0x00000001, 0x5c00a800,
+ 0x5c00a000, 0x5c00b000, 0x5c025800, 0x1c01f000,
+ 0x4933c857, 0x492fc857, 0x4d2c0000, 0x59300a03,
+ 0x82040580, 0x00000007, 0x04000036, 0x82040580,
+ 0x00000001, 0x02020800, 0x001005d8, 0x0201f800,
+ 0x00106c55, 0x4df00000, 0x598c000d, 0x81300580,
+ 0x04020016, 0x59300004, 0x8c000520, 0x04000004,
+ 0x84000520, 0x48026004, 0x0401f016, 0x42001000,
+ 0x0010b7f6, 0x50081000, 0x58080002, 0x82000580,
+ 0x00000100, 0x04000006, 0x5808000c, 0x81300580,
+ 0x02020800, 0x001005d8, 0x0401f00a, 0x0201f800,
+ 0x00106e8e, 0x04020020, 0x59300004, 0x8c000520,
+ 0x04000004, 0x84000520, 0x48026004, 0x0401f003,
+ 0x0201f800, 0x001068d3, 0x5c03e000, 0x02000800,
+ 0x00106c4b, 0x0201f800, 0x00109037, 0x02000800,
+ 0x001005d8, 0x59325808, 0x4a025a06, 0x00000005,
+ 0x0201f800, 0x000202da, 0x0201f800, 0x00104c19,
+ 0x59325817, 0x812e59c0, 0x02020800, 0x001007fd,
+ 0x0201f800, 0x00107911, 0x80000580, 0x5c025800,
+ 0x1c01f000, 0x5c03e000, 0x02000800, 0x00106c4b,
+ 0x59300406, 0x82000580, 0x00000011, 0x040007b8,
+ 0x0401f7f7, 0x4c040000, 0x59340200, 0x4803c857,
+ 0x8c00051c, 0x04000009, 0x59cc0805, 0x591c0019,
+ 0x4803c857, 0x80040580, 0x04000004, 0x80000580,
+ 0x4803c856, 0x0401f003, 0x82000540, 0x00000001,
+ 0x5c000800, 0x1c01f000, 0x4c000000, 0x4c0c0000,
+ 0x4c100000, 0x42001800, 0x0000ffff, 0x42002000,
+ 0x00000004, 0x0401f010, 0x4c000000, 0x4c0c0000,
+ 0x4c100000, 0x59302009, 0x58101c03, 0x42002000,
+ 0x00000004, 0x0401f008, 0x4c000000, 0x4c0c0000,
+ 0x4c100000, 0x59302009, 0x58101c03, 0x42002000,
+ 0x00000007, 0x480fc857, 0x4813c857, 0x481bc857,
+ 0x0201f800, 0x00103aae, 0x5c002000, 0x5c001800,
+ 0x5c000000, 0x1c01f000, 0x83380580, 0x00000092,
+ 0x02020800, 0x001005d8, 0x42000800, 0x80000040,
+ 0x4a026203, 0x00000001, 0x493a6403, 0x0201f000,
+ 0x00020721, 0x4d400000, 0x0201f800, 0x00103b25,
+ 0x04000008, 0x59a80005, 0x84000544, 0x48035005,
+ 0x42028000, 0x0000002a, 0x0201f800, 0x0010a449,
+ 0x5c028000, 0x1c01f000, 0x59a80026, 0x8c000508,
+ 0x04000005, 0x599c0017, 0x8c00050a, 0x04020002,
+ 0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000,
+ 0x59300420, 0x84000540, 0x48026420, 0x1c01f000,
+ 0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a,
+ 0x04000004, 0x598800b8, 0x80000000, 0x480310b8,
+ 0x8c142d2e, 0x04000004, 0x598800b9, 0x80000000,
+ 0x480310b9, 0x8c142d2c, 0x04000013, 0x40140000,
+ 0x82000500, 0x00070000, 0x82000d80, 0x00030000,
+ 0x0400000d, 0x82000d80, 0x00040000, 0x0400000a,
+ 0x82000d80, 0x00050000, 0x04000007, 0x59880005,
+ 0x80000000, 0x48031005, 0x598800ba, 0x80000000,
+ 0x480310ba, 0x5c000800, 0x5c000000, 0x1c01f000,
+ 0x4817c857, 0x4c000000, 0x4c040000, 0x8c142d2a,
+ 0x04000004, 0x598800bb, 0x80000000, 0x480310bb,
+ 0x8c142d2e, 0x04000004, 0x598800bc, 0x80000000,
+ 0x480310bc, 0x8c142d2c, 0x04000013, 0x40140000,
+ 0x82000500, 0x00070000, 0x82000d80, 0x00030000,
+ 0x0400000d, 0x82000d80, 0x00040000, 0x0400000a,
+ 0x82000d80, 0x00050000, 0x04000007, 0x59880005,
+ 0x80000000, 0x48031005, 0x598800bd, 0x80000000,
+ 0x480310bd, 0x5c000800, 0x5c000000, 0x1c01f000,
+ 0x4c000000, 0x59880001, 0x80000000, 0x4803c857,
+ 0x48031001, 0x5c000000, 0x1c01f000, 0x4c000000,
+ 0x59880000, 0x80000000, 0x4803c857, 0x48031000,
+ 0x5c000000, 0x1c01f000, 0x4c000000, 0x59880002,
+ 0x80000000, 0x4803c857, 0x48031002, 0x5c000000,
+ 0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d2c,
+ 0x04000004, 0x598800a6, 0x80000000, 0x480310a6,
+ 0x8c040d2a, 0x04000004, 0x598800a7, 0x80000000,
+ 0x480310a7, 0x8c040d28, 0x04000004, 0x598800a8,
+ 0x80000000, 0x480310a8, 0x8c040d26, 0x04000004,
+ 0x598800a9, 0x80000000, 0x480310a9, 0x8c040d24,
+ 0x04000004, 0x598800aa, 0x80000000, 0x480310aa,
+ 0x8c040d22, 0x04000004, 0x598800ab, 0x80000000,
+ 0x480310ab, 0x8c040d20, 0x04000004, 0x598800ac,
+ 0x80000000, 0x480310ac, 0x5c000000, 0x1c01f000,
+ 0x4807c857, 0x4c000000, 0x598800ad, 0x80000000,
+ 0x480310ad, 0x5c000000, 0x1c01f000, 0x4807c857,
+ 0x4c000000, 0x8c040d1c, 0x04000004, 0x598800ae,
+ 0x80000000, 0x480310ae, 0x8c040d1a, 0x04000004,
+ 0x598800af, 0x80000000, 0x480310af, 0x5c000000,
+ 0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d18,
+ 0x04000004, 0x598800b0, 0x80000000, 0x480310b0,
+ 0x8c040d16, 0x04000004, 0x598800b1, 0x80000000,
+ 0x480310b1, 0x8c040d14, 0x04000004, 0x598800b2,
+ 0x80000000, 0x480310b2, 0x5c000000, 0x1c01f000,
+ 0x4807c857, 0x4c000000, 0x8c040d10, 0x04000004,
+ 0x598800b3, 0x80000000, 0x480310b3, 0x8c040d0c,
+ 0x04000004, 0x598800b4, 0x80000000, 0x480310b4,
+ 0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000,
+ 0x8c040d08, 0x04000004, 0x598800b5, 0x80000000,
+ 0x480310b5, 0x8c040d04, 0x04000004, 0x598800b6,
+ 0x80000000, 0x480310b6, 0x5c000000, 0x1c01f000,
+ 0x4807c856, 0x4c000000, 0x5988007f, 0x80000000,
+ 0x4803107f, 0x5c000000, 0x1c01f000, 0x4803c857,
+ 0x4c040000, 0x50000800, 0x80040800, 0x4807c857,
+ 0x44040000, 0x5c000800, 0x1c01f000, 0x480fc857,
+ 0x4c000000, 0x820c0580, 0x00000000, 0x04020004,
+ 0x42000000, 0x0010b819, 0x0401f014, 0x820c0580,
+ 0x00001001, 0x04020004, 0x42000000, 0x0010b81a,
+ 0x0401f00e, 0x820c0580, 0x00001002, 0x04020004,
+ 0x42000000, 0x0010b81b, 0x0401f008, 0x820c0c80,
+ 0x0000201c, 0x02021800, 0x001005d8, 0x820c0500,
+ 0x0000001f, 0x0c01f804, 0x0401ffdd, 0x5c000000,
+ 0x1c01f000, 0x0010aa89, 0x0010aa8c, 0x0010aa8f,
+ 0x0010aa92, 0x0010aa95, 0x0010aa98, 0x0010aa9b,
+ 0x0010aa9e, 0x0010aaa1, 0x0010aaa4, 0x0010aaa7,
+ 0x0010aaaa, 0x0010aaad, 0x0010aab0, 0x0010aab3,
+ 0x0010aab6, 0x0010aab9, 0x0010aabc, 0x0010aabf,
+ 0x0010aac2, 0x0010aac5, 0x0010aac8, 0x0010aacb,
+ 0x0010aace, 0x0010aad1, 0x0010aad4, 0x0010aad7,
+ 0x0010aada, 0x42000000, 0x0010b81c, 0x1c01f000,
+ 0x42000000, 0x0010b81d, 0x1c01f000, 0x42000000,
+ 0x0010b81e, 0x1c01f000, 0x42000000, 0x0010b81f,
+ 0x1c01f000, 0x42000000, 0x0010b820, 0x1c01f000,
+ 0x42000000, 0x0010b821, 0x1c01f000, 0x42000000,
+ 0x0010b822, 0x1c01f000, 0x42000000, 0x0010b823,
+ 0x1c01f000, 0x42000000, 0x0010b824, 0x1c01f000,
+ 0x42000000, 0x0010b825, 0x1c01f000, 0x42000000,
+ 0x0010b826, 0x1c01f000, 0x42000000, 0x0010b827,
+ 0x1c01f000, 0x42000000, 0x0010b828, 0x1c01f000,
+ 0x42000000, 0x0010b829, 0x1c01f000, 0x42000000,
+ 0x0010b82a, 0x1c01f000, 0x42000000, 0x0010b82b,
+ 0x1c01f000, 0x42000000, 0x0010b82c, 0x1c01f000,
+ 0x42000000, 0x0010b82d, 0x1c01f000, 0x42000000,
+ 0x0010b82e, 0x1c01f000, 0x42000000, 0x0010b82f,
+ 0x1c01f000, 0x42000000, 0x0010b830, 0x1c01f000,
+ 0x42000000, 0x0010b831, 0x1c01f000, 0x42000000,
+ 0x0010b832, 0x1c01f000, 0x42000000, 0x0010b833,
+ 0x1c01f000, 0x42000000, 0x0010b834, 0x1c01f000,
+ 0x42000000, 0x0010b835, 0x1c01f000, 0x42000000,
+ 0x0010b836, 0x1c01f000, 0x42000000, 0x0010b837,
+ 0x1c01f000, 0x480fc857, 0x4c000000, 0x820c0580,
+ 0x00000001, 0x04020004, 0x42000000, 0x0010b80e,
+ 0x0401f012, 0x820c0580, 0x00000002, 0x04020004,
+ 0x42000000, 0x0010b80f, 0x0401f00c, 0x820c0580,
+ 0x00000003, 0x04020004, 0x42000000, 0x0010b810,
+ 0x0401f006, 0x820c0580, 0x00000004, 0x04020004,
+ 0x42000000, 0x0010b811, 0x0401ff51, 0x5c000000,
+ 0x1c01f000, 0x4c000000, 0x59a80026, 0x4803c857,
+ 0x8c000502, 0x04000010, 0x8c000506, 0x04000004,
+ 0x42000000, 0x0010b841, 0x0401f012, 0x8c00050a,
+ 0x04000004, 0x42000000, 0x0010b840, 0x0401f00d,
+ 0x8c000508, 0x04000004, 0x42000000, 0x0010b843,
+ 0x0401f008, 0x0201f800, 0x0010513b, 0x04000006,
+ 0x8c000506, 0x04020004, 0x42000000, 0x0010b842,
+ 0x0401ff33, 0x5c000000, 0x1c01f000, 0x8058b1c0,
+ 0x02000800, 0x001005d8, 0x5450a800, 0x8050a000,
+ 0x8054a800, 0x8058b040, 0x040207fc, 0x1c01f000,
+ 0x8058b1c0, 0x02000800, 0x001005d8, 0x4450a800,
+ 0x8054a800, 0x8058b040, 0x040207fd, 0x1c01f000,
+ 0x8058b1c0, 0x02000800, 0x001005d8, 0x50500000,
+ 0x9c0001c0, 0x4400a800, 0x8050a000, 0x8054a800,
+ 0x8058b040, 0x040207fa, 0x1c01f000, 0x4c000000,
+ 0x59a80008, 0x8c00051c, 0x5c000000, 0x1c01f000,
+ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800,
+ 0x00001000, 0x00002000, 0x00004000, 0x00008000,
+ 0x00010000, 0xa5f2b3ac
+};
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_length01 = 0x0000ab4a ;
+#else
+uint32_t risc_code_length01 = 0x0000ab4a ;
+#endif
+
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_addr02 = 0x0010e000 ;
+#else
+uint32_t risc_code_addr02 = 0x0010e000 ;
+#endif
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_code02[] = {
+#else
+uint32_t risc_code02[] = {
+#endif
+ 0x00000000, 0x00000000, 0x0010e000, 0x000014ff,
+ 0x00000000, 0x00000000, 0x00020000, 0x000008c0,
+ 0x836c0580, 0x00000003, 0x02020000, 0x001002e3,
+ 0x42000000, 0x0010b4bb, 0x50000000, 0x800001c0,
+ 0x04020956, 0x0401f923, 0x0401fbe3, 0x0401fb5c,
+ 0x0201f800, 0x00020718, 0x0201f800, 0x0002057b,
+ 0x0401f7f0, 0x59b800ea, 0x82000d00, 0xf0000038,
+ 0x02020000, 0x00100a7a, 0x8c000510, 0x02000000,
+ 0x00100a79, 0x59ba60e0, 0x81300182, 0x0402104e,
+ 0x04002030, 0x8532653e, 0x59300406, 0x82000580,
+ 0x00000003, 0x04020028, 0x59300203, 0x82000580,
+ 0x00000004, 0x04020024, 0x59325808, 0x59300402,
+ 0x4a025a04, 0x00000103, 0x900001c0, 0x48025806,
+ 0x497a5807, 0x497a5c09, 0x5930001f, 0x80000540,
+ 0x02020800, 0x00100d56, 0x59300004, 0x8c00053e,
+ 0x04020010, 0x0401fa88, 0x59326809, 0x0201f800,
+ 0x0002077d, 0x5934000f, 0x5934140b, 0x80081040,
+ 0x04001002, 0x480a6c0b, 0x80000540, 0x04020a10,
+ 0x59b800ea, 0x8c000510, 0x040207d7, 0x1c01f000,
+ 0x0201f800, 0x00106f60, 0x040007ef, 0x0201f000,
+ 0x00100a65, 0x42027000, 0x00000055, 0x0401f027,
+ 0x83326500, 0x3fffffff, 0x59300406, 0x82000580,
+ 0x00000003, 0x04020015, 0x59325808, 0x59326809,
+ 0x59301402, 0x4a025a04, 0x00000103, 0x900811c0,
+ 0x480a5806, 0x497a5c09, 0x497a5807, 0x0401fa62,
+ 0x0201f800, 0x0002077d, 0x5934000f, 0x5934140b,
+ 0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
+ 0x040209eb, 0x0401f7db, 0x42027000, 0x00000054,
+ 0x0401f00a, 0x83300500, 0x60000000, 0x02000000,
+ 0x00100a68, 0x81326580, 0x8000013a, 0x82000400,
+ 0x00100a80, 0x50027000, 0x59300c06, 0x82040580,
+ 0x00000002, 0x02000000, 0x00100a65, 0x59300004,
+ 0x8c00053e, 0x04020004, 0x0201f800, 0x000207a1,
+ 0x0401f7c4, 0x0201f800, 0x00106f60, 0x040007fb,
+ 0x0201f000, 0x00100a65, 0x59325808, 0x412c7000,
+ 0x58380a04, 0x82040500, 0x0000000f, 0x82000c00,
+ 0x001010bd, 0x50044000, 0x0c01f001, 0x00100dd9,
+ 0x00100dd9, 0x0002009f, 0x00100dd9, 0x00100dd9,
+ 0x00100dd9, 0x00100dd9, 0x00100dd9, 0x000200af,
+ 0x00100ded, 0x00100dd9, 0x00100dd9, 0x00100ddb,
+ 0x00100dd9, 0x00100dd9, 0x00100dd9, 0x5838040a,
+ 0x8c000500, 0x02000800, 0x001005d8, 0x50200000,
+ 0x80387c00, 0x583c1002, 0x583c2800, 0x583c2001,
+ 0x58380a07, 0x5838300f, 0x59303807, 0x58384c08,
+ 0x5838000d, 0x48026012, 0x0401f010, 0x5838020a,
+ 0x8c000502, 0x02000000, 0x00100dd9, 0x50200000,
+ 0x80387c00, 0x583c2800, 0x583c2001, 0x583c1002,
+ 0x592c0a07, 0x592c4c08, 0x592c300f, 0x59303807,
+ 0x497a6012, 0x497a6013, 0x4816600e, 0x4812600f,
+ 0x480a6010, 0x481a6011, 0x80040840, 0x4806600d,
+ 0x02020000, 0x00100e1a, 0x841c3d40, 0x481e6007,
+ 0x1c01f000, 0x41787800, 0x59325808, 0x592c0c0a,
+ 0x8c040d02, 0x02000000, 0x00100f8c, 0x592c000d,
+ 0x592c100f, 0x592c0a04, 0x480a6011, 0x48026012,
+ 0x48026013, 0x412c3000, 0x82040500, 0x0000000f,
+ 0x82000400, 0x001010bd, 0x50003800, 0x501c0000,
+ 0x401c1000, 0x592c1a07, 0x4802600a, 0x481a600b,
+ 0x480a600c, 0x480e600d, 0x843c7d4a, 0x403c1000,
+ 0x1c01f000, 0x41787800, 0x497a6012, 0x592c0a04,
+ 0x412c3000, 0x592c1a07, 0x82040500, 0x0000000f,
+ 0x82000400, 0x001010bd, 0x50004000, 0x50200000,
+ 0x40201000, 0x4802600a, 0x481a600b, 0x480a600c,
+ 0x480e600d, 0x80000580, 0x483e6004, 0x1c01f000,
+ 0x4c000000, 0x4df00000, 0x0201f800, 0x00020729,
+ 0x0401f005, 0x4c000000, 0x4df00000, 0x0401ff16,
+ 0x0401f001, 0x5c03e000, 0x5c000000, 0x1801f000,
+ 0x4203e000, 0xb0100000, 0x41fc0000, 0x82000500,
+ 0x00000011, 0x0c01f001, 0x0002012a, 0x00020697,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0010115a, 0x0002012c,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0002012a, 0x0002012a,
+ 0x0002012a, 0x0002012a, 0x0201f800, 0x001005d8,
+ 0x0201f800, 0x00020697, 0x0201f000, 0x0010115a,
+ 0x42000000, 0x0010b4c1, 0x50000000, 0x8c000504,
+ 0x04000014, 0x42000000, 0x0010b4c1, 0x50000000,
+ 0x8c000502, 0x04020002, 0x1c01f000, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x42034000, 0x0010b4a4,
+ 0x59a0001d, 0x59a1d81e, 0x84000502, 0x4803401d,
+ 0x58ec0009, 0x0801f800, 0x5c03e000, 0x1c01f000,
+ 0x04027002, 0x04026002, 0x1c01f000, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x0201f800, 0x001007e4,
+ 0x04000010, 0x412dd800, 0x48efc857, 0x0201f800,
+ 0x00103b28, 0x42034000, 0x0010b4a4, 0x49a1d80b,
+ 0x48ef401e, 0x59a0001d, 0x84000544, 0x4803401d,
+ 0x0201f800, 0x00102214, 0x0201f800, 0x00102233,
+ 0x5c03e000, 0x1c01f000, 0x4da00000, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x04006051, 0x40001000,
+ 0x42034000, 0x0010b4a4, 0x59a01818, 0x800c19c0,
+ 0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800,
+ 0x001005d8, 0x59a0041c, 0x801c3c00, 0x0401f00c,
+ 0x59a00419, 0x82000400, 0x00000002, 0x48034419,
+ 0x82000c80, 0x00000013, 0x04001003, 0x497b4419,
+ 0x41780000, 0x59a03816, 0x801c3c00, 0x80081040,
+ 0x480b4017, 0x581c0200, 0x4803c021, 0x581c0401,
+ 0x4803c022, 0x581c0201, 0x4803c023, 0x581c0400,
+ 0x4803c020, 0x900001c0, 0x82000540, 0x00000012,
+ 0x4803c011, 0x59e00017, 0x8c000508, 0x04000003,
+ 0x4a03c017, 0x00000002, 0x4203e000, 0x30000001,
+ 0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018,
+ 0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c,
+ 0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b,
+ 0x0201f800, 0x001007f4, 0x5c025800, 0x497b401b,
+ 0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010,
+ 0x59a0041c, 0x82000400, 0x00000002, 0x82000c80,
+ 0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000,
+ 0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c,
+ 0x0201f800, 0x001007f4, 0x5c025800, 0x5c03e000,
+ 0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500,
+ 0x00000003, 0x02020000, 0x00104315, 0x59340400,
+ 0x82000580, 0x00000606, 0x02020000, 0x001042e6,
+ 0x5934000d, 0x80027d40, 0x02020000, 0x00104321,
+ 0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f,
+ 0x59341203, 0x80080540, 0x0402006f, 0x5934020b,
+ 0x5934140b, 0x80080480, 0x0402106b, 0x0201f800,
+ 0x0002075a, 0x04000064, 0x80081000, 0x592c0406,
+ 0x480a6c0b, 0x49366009, 0x492e6008, 0x4a026406,
+ 0x00000003, 0x4a026403, 0x00000040, 0x800000c2,
+ 0x800018c4, 0x800c0400, 0x48026206, 0x592c0808,
+ 0x592c1809, 0x592c020a, 0x48066017, 0x480e6018,
+ 0x8c000502, 0x04000030, 0x4a026203, 0x00000004,
+ 0x592c0207, 0x80000040, 0x04020020, 0x59a80005,
+ 0x8c000514, 0x42000000, 0x00000055, 0x04020003,
+ 0x42000000, 0x00000033, 0x80000040, 0x040207ff,
+ 0x592c0204, 0x82000500, 0x000000ff, 0x82000580,
+ 0x00000018, 0x04020011, 0x592c180f, 0x59300007,
+ 0x82000540, 0x00000091, 0x480e6011, 0x48026007,
+ 0x42000000, 0x80000004, 0x48026004, 0x59bc00ea,
+ 0x8c000516, 0x040207fe, 0x83300400, 0x20000000,
+ 0x480378e1, 0x1c01f000, 0x0401fe78, 0x59300007,
+ 0x8400054e, 0x48026007, 0x592c1a04, 0x820c1d00,
+ 0x000000ff, 0x820c0580, 0x00000048, 0x04000017,
+ 0x0401f7ec, 0x8c000500, 0x04020ecb, 0x4a026203,
+ 0x00000002, 0x59a80805, 0x82040500, 0x00000600,
+ 0x04020012, 0x42000000, 0x00000030, 0x80000040,
+ 0x040207ff, 0x592c1a04, 0x820c1d00, 0x000000ff,
+ 0x820c0580, 0x00000018, 0x040007da, 0x820c0580,
+ 0x00000048, 0x040207d7, 0x42000800, 0x80000804,
+ 0x0201f000, 0x00106721, 0x8c040d12, 0x42000000,
+ 0x00000010, 0x040207ee, 0x42000000, 0x00000051,
+ 0x0401f7eb, 0x800811c0, 0x04020003, 0x4a026a03,
+ 0x00000001, 0x59340010, 0x492e6810, 0x80000d40,
+ 0x04020003, 0x492e680f, 0x1c01f000, 0x492c0800,
+ 0x1c01f000, 0x83440c80, 0x00000800, 0x04021009,
+ 0x83440400, 0x0010ac00, 0x50000000, 0x80000540,
+ 0x04000004, 0x40026800, 0x80000580, 0x1c01f000,
+ 0x82000540, 0x00000001, 0x1c01f000, 0x59340203,
+ 0x80000540, 0x0402004b, 0x4d300000, 0x4d2c0000,
+ 0x5934000f, 0x80025d40, 0x04000044, 0x0201f800,
+ 0x0002075a, 0x0400003f, 0x592c0000, 0x4802680f,
+ 0x80000540, 0x04020002, 0x48026810, 0x592c2a04,
+ 0x80081000, 0x480a6c0b, 0x49366009, 0x492e6008,
+ 0x82142d00, 0x000000ff, 0x82140580, 0x00000012,
+ 0x04000035, 0x4a026406, 0x00000003, 0x4a026403,
+ 0x00000040, 0x592c0406, 0x800000c2, 0x800018c4,
+ 0x800c0400, 0x48026206, 0x592c0808, 0x592c1809,
+ 0x592c020a, 0x48066017, 0x480e6018, 0x8c000502,
+ 0x02000000, 0x0010474d, 0x4a026203, 0x00000004,
+ 0x592c0207, 0x80000040, 0x02020000, 0x00104740,
+ 0x82140580, 0x00000018, 0x02020000, 0x00104740,
+ 0x592c180f, 0x59300007, 0x82000540, 0x00000091,
+ 0x480e6011, 0x48026007, 0x42000000, 0x80000004,
+ 0x48026004, 0x59bc00ea, 0x8c000516, 0x040207fe,
+ 0x83300400, 0x20000000, 0x480378e1, 0x5934020b,
+ 0x5934140b, 0x80080480, 0x040017be, 0x0401f003,
+ 0x4a026a03, 0x00000001, 0x5c025800, 0x5c026000,
+ 0x1c01f000, 0x497a5800, 0x49325809, 0x4a026406,
+ 0x00000006, 0x4a026203, 0x00000007, 0x0401f802,
+ 0x0401f7ef, 0x59a80021, 0x800001c0, 0x02020000,
+ 0x0010476f, 0x59a80005, 0x8c000504, 0x02020000,
+ 0x0010476b, 0x59340200, 0x8c000518, 0x02020000,
+ 0x00104767, 0x592c0a0c, 0x48066202, 0x4a025a06,
+ 0x00000000, 0x8c000508, 0x02020000, 0x00104763,
+ 0x4d3c0000, 0x417a7800, 0x0401fbdf, 0x5c027800,
+ 0x1c01f000, 0x592c0404, 0x8c00051e, 0x02020000,
+ 0x00104ce4, 0x59980022, 0x80000540, 0x04000017,
+ 0x592c0a06, 0x592c0409, 0x80040540, 0x04020013,
+ 0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e,
+ 0x02020000, 0x00104cf3, 0x59980022, 0x80000540,
+ 0x0400000a, 0x82040580, 0x00000001, 0x04020007,
+ 0x0201f000, 0x00104cfa, 0x592c0404, 0x8c00051e,
+ 0x02020000, 0x00104dca, 0x59980026, 0x497a5800,
+ 0x80000540, 0x02020000, 0x00104e1d, 0x59d80105,
+ 0x82000d00, 0x00018780, 0x02020000, 0x00104edb,
+ 0x80000106, 0x82000500, 0x00000003, 0x0c01f001,
+ 0x000202f0, 0x00104e1d, 0x000202f6, 0x00020341,
+ 0x592c0001, 0x492fb107, 0x80000d40, 0x02020000,
+ 0x00104ddb, 0x1c01f000, 0x592c0001, 0x492fb107,
+ 0x80000d40, 0x02020000, 0x00104de8, 0x59da5908,
+ 0x835c0480, 0x00000020, 0x0400102c, 0x0402b034,
+ 0x492fb007, 0x0400e7fa, 0x59d80105, 0x82000500,
+ 0x00018780, 0x02020000, 0x00104edb, 0x0400601f,
+ 0x59d8010a, 0x59d8090a, 0x80040580, 0x040207fd,
+ 0x800408e0, 0x599c1017, 0x8c081508, 0x04020028,
+ 0x82040d40, 0x00000013, 0x5998002b, 0x4807c011,
+ 0x84000500, 0x4803302b, 0x59e00017, 0x8c000508,
+ 0x04020004, 0x4203e000, 0x30000001, 0x1c01f000,
+ 0x4a03c017, 0x00000003, 0x82040500, 0x000000ff,
+ 0x82000580, 0x0000001d, 0x040207f7, 0x4a03c017,
+ 0x0000000d, 0x0401f7f4, 0x5998082b, 0x84040d40,
+ 0x4807302b, 0x1c01f000, 0x496a5800, 0x412ed000,
+ 0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x0400e7ca, 0x0401f7d0, 0x0402f7f7,
+ 0x492fa807, 0x0400e7c6, 0x0401f7cc, 0x59e0000f,
+ 0x59e0100f, 0x80081580, 0x040207fd, 0x81281580,
+ 0x040007d4, 0x40025000, 0x82040d40, 0x0000001d,
+ 0x0401f7d2, 0x59d80908, 0x45680800, 0x4006d000,
+ 0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540,
+ 0x00001200, 0x48039000, 0x02006000, 0x00104df8,
+ 0x59d8010a, 0x59d8090a, 0x80040d80, 0x040207fd,
+ 0x900001c0, 0x82000540, 0x00000013, 0x4803c011,
+ 0x5998002b, 0x84000500, 0x4803302b, 0x59e00017,
+ 0x8c000508, 0x04000003, 0x4a03c017, 0x00000003,
+ 0x4203e000, 0x30000001, 0x59d80105, 0x82000500,
+ 0x00018780, 0x02020000, 0x00104edb, 0x0202d000,
+ 0x00104dfd, 0x592c0001, 0x492fb107, 0x80000d40,
+ 0x02020000, 0x00104e10, 0x1c01f000, 0x59980020,
+ 0x0c01f001, 0x00020370, 0x00020371, 0x00104e88,
+ 0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
+ 0x0402681e, 0x04006004, 0x599c0017, 0x8c000508,
+ 0x04020865, 0x59980029, 0x80025d40, 0x0400000a,
+ 0x0402d00b, 0x59980026, 0x80000040, 0x48033026,
+ 0x592c0000, 0x492fb107, 0x48033029, 0x04020002,
+ 0x48033028, 0x5c03e000, 0x1c01f000, 0x59d80105,
+ 0x82000500, 0x00018780, 0x02020000, 0x00104edb,
+ 0x42000000, 0x0010b855, 0x0201f800, 0x0010aa47,
+ 0x5c03e000, 0x1c01f000, 0x5998002b, 0x8c000500,
+ 0x0402003b, 0x0400e007, 0x59d80105, 0x82000500,
+ 0x00018780, 0x02020000, 0x00104edb, 0x1c01f000,
+ 0x59da5908, 0x835c0c80, 0x00000020, 0x04001003,
+ 0x0400b029, 0x0400f02b, 0x496a5800, 0x412ed000,
+ 0x815eb800, 0x59c80000, 0x82000540, 0x00001200,
+ 0x48039000, 0x0400e7f3, 0x59d8010a, 0x59d8090a,
+ 0x80040580, 0x040207fd, 0x800408e0, 0x599c1017,
+ 0x8c081508, 0x04020022, 0x82040d40, 0x00000013,
+ 0x4807c011, 0x59e00017, 0x8c000508, 0x0400000a,
+ 0x4a03c017, 0x00000003, 0x82040500, 0x000000ff,
+ 0x82000580, 0x0000001d, 0x04020003, 0x4a03c017,
+ 0x0000000d, 0x4203e000, 0x30000001, 0x59d80105,
+ 0x82000500, 0x00018780, 0x02020000, 0x00104edb,
+ 0x1c01f000, 0x492fb007, 0x0400e7d2, 0x0401f7df,
+ 0x492fa807, 0x0400e7cf, 0x0401f7dc, 0x84000500,
+ 0x4803302b, 0x0400e7cb, 0x0401f7d8, 0x59e0000f,
+ 0x59e0100f, 0x80081580, 0x040207fd, 0x81281580,
+ 0x040007da, 0x40025000, 0x82040d40, 0x0000001d,
+ 0x0401f7d8, 0x59e0000f, 0x59e0100f, 0x80080d80,
+ 0x040207fd, 0x81280580, 0x04020002, 0x1c01f000,
+ 0x400a5000, 0x900811c0, 0x82081540, 0x0000001c,
+ 0x480bc011, 0x59e00017, 0x8c000508, 0x04000003,
+ 0x4a03c017, 0x0000000c, 0x4203e000, 0x30000001,
+ 0x1c01f000, 0x41700000, 0x0c01f001, 0x00105420,
+ 0x000203fc, 0x00105420, 0x00105421, 0x0010541e,
+ 0x0010541e, 0x0010541e, 0x0010541e, 0x001058b0,
+ 0x04010037, 0x59980006, 0x80000540, 0x0402003c,
+ 0x0402c01c, 0x4202f800, 0x00000010, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x49db3005, 0x59da5808,
+ 0x592c0204, 0x497a5800, 0x497a5801, 0x82000500,
+ 0x000000ff, 0x82000c80, 0x00000079, 0x04021036,
+ 0x0c01f839, 0x5c03e000, 0x817ef840, 0x04000009,
+ 0x836c0580, 0x00000003, 0x04020006, 0x83700580,
+ 0x00000001, 0x04020010, 0x0401001b, 0x0400c7e8,
+ 0x0400f94a, 0x0400b134, 0x59d40005, 0x82000500,
+ 0x43018780, 0x02020000, 0x0010583f, 0x59d80005,
+ 0x82000500, 0x43018780, 0x02020000, 0x00105846,
+ 0x1c01f000, 0x83700580, 0x00000003, 0x02000800,
+ 0x00105421, 0x83700580, 0x00000001, 0x040207ed,
+ 0x04010005, 0x0400c7d2, 0x0401f7ea, 0x4202f800,
+ 0x00000010, 0x4df00000, 0x4203e000, 0x50000000,
+ 0x49d73005, 0x59d65808, 0x0401f7ce, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x40025800, 0x592c0204,
+ 0x497b3005, 0x497b3006, 0x4202f800, 0x00000010,
+ 0x0401f7c7, 0x0201f800, 0x00105491, 0x5c03e000,
+ 0x0401f7d4, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105527, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x001054a1,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105551,
+ 0x00105491, 0x00105491, 0x00105491, 0x000204ef,
+ 0x00105491, 0x001056b4, 0x00105491, 0x00105491,
+ 0x00105491, 0x000204c2, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x001054c9, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x001057d3, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x0010581e, 0x00105491,
+ 0x001054bb, 0x00105491, 0x00105797, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105765, 0x00105491,
+ 0x00105765, 0x00105872, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105725,
+ 0x00105855, 0x00105491, 0x00105865, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x00105491, 0x00105491,
+ 0x00105491, 0x00105491, 0x592c0204, 0x80000110,
+ 0x02000000, 0x00105499, 0x80000040, 0x04000009,
+ 0x48033002, 0x492f3003, 0x492f3004, 0x4a033008,
+ 0x000204d0, 0x4202e000, 0x00000003, 0x1c01f000,
+ 0x592c0406, 0x82000c80, 0x0000199a, 0x02021000,
+ 0x001054a9, 0x59a80021, 0x80000540, 0x02020000,
+ 0x001054d7, 0x592e8a06, 0x83440c80, 0x000007f0,
+ 0x02021000, 0x001054a9, 0x83440400, 0x0010ac00,
+ 0x50000000, 0x80026d40, 0x02000000, 0x001054db,
+ 0x59340002, 0x592c0810, 0x80040580, 0x82000500,
+ 0x00ffffff, 0x02020000, 0x001054a9, 0x0401fccf,
+ 0x02020000, 0x001054de, 0x1c01f000, 0x592c0204,
+ 0x80000110, 0x02000000, 0x00105499, 0x80000040,
+ 0x0402000b, 0x592c040a, 0x8c000504, 0x04000010,
+ 0x592c0207, 0x82000c80, 0x00001001, 0x02021000,
+ 0x001054a9, 0x0201f000, 0x0010588a, 0x48033002,
+ 0x492f3003, 0x492f3004, 0x4a033008, 0x00020507,
+ 0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406,
+ 0x82000c80, 0x0000199a, 0x02021000, 0x001054a9,
+ 0x592e8a06, 0x417a7800, 0x0401fd37, 0x02020000,
+ 0x00105658, 0x59340002, 0x592c0808, 0x80040580,
+ 0x82000500, 0x00ffffff, 0x02020000, 0x001054a9,
+ 0x497a5808, 0x592e6009, 0x83300580, 0xffffffff,
+ 0x02000000, 0x00105618, 0x83300480, 0x0010d1c0,
+ 0x02001000, 0x00105675, 0x59a8000b, 0x81300480,
+ 0x02021000, 0x00105675, 0x592c240a, 0x49366009,
+ 0x8c10251c, 0x02020000, 0x00105606, 0x59a80068,
+ 0x8c000510, 0x02020000, 0x0010568e, 0x59a80821,
+ 0x800409c0, 0x02020000, 0x001055ec, 0x59a80805,
+ 0x8c040d04, 0x02020000, 0x0010567f, 0x59340200,
+ 0x8c000518, 0x02020000, 0x00105670, 0x59300c06,
+ 0x82040580, 0x00000006, 0x02020000, 0x00105610,
+ 0x59300414, 0x8c000516, 0x02020000, 0x0010567a,
+ 0x8c102508, 0x02020000, 0x0010a5b8, 0x59300808,
+ 0x4a025a06, 0x00000000, 0x800409c0, 0x02020000,
+ 0x001055e7, 0x592c0a0c, 0x48066202, 0x492e6008,
+ 0x0401f14d, 0x4df00000, 0x4203e000, 0x50000000,
+ 0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d,
+ 0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007,
+ 0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005,
+ 0x82000500, 0x43018780, 0x02020000, 0x00105846,
+ 0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000,
+ 0x50000000, 0x0402f00b, 0x835c0480, 0x00000020,
+ 0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000,
+ 0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7,
+ 0x59d40005, 0x82000500, 0x43018780, 0x02020000,
+ 0x0010583f, 0x5c03e000, 0x1c01f000, 0x4df00000,
+ 0x4203e000, 0x50000000, 0x59940024, 0x80000540,
+ 0x04000112, 0x4c000000, 0x42000000, 0x00001000,
+ 0x50000000, 0x82000480, 0x24320001, 0x04020015,
+ 0x42000800, 0x00000064, 0x80040840, 0x04000007,
+ 0x4a030000, 0x00000001, 0x40000000, 0x59800000,
+ 0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
+ 0x00007a01, 0x50040000, 0x8c000510, 0x04000003,
+ 0x84000510, 0x44000800, 0x4a030000, 0x00000000,
+ 0x59e00002, 0x8c00051e, 0x0402001b, 0x42000000,
+ 0x00001000, 0x50000000, 0x82000480, 0x24320002,
+ 0x04020015, 0x42000800, 0x00000064, 0x80040840,
+ 0x04000007, 0x4a030000, 0x00000001, 0x40000000,
+ 0x59800000, 0x8c000500, 0x040007f9, 0x04000008,
+ 0x42000800, 0x00007a17, 0x50040000, 0x8c00050e,
+ 0x04020003, 0x8400054e, 0x44000800, 0x4a030000,
+ 0x00000000, 0x5c000000, 0x5994781a, 0x48032825,
+ 0x803c0480, 0x04001004, 0x04000003, 0x4803281a,
+ 0x0401f022, 0x41787800, 0x803c7800, 0x82000400,
+ 0x000003e8, 0x040027fd, 0x4803281a, 0x59a80024,
+ 0x803c1400, 0x480b5024, 0x803c0040, 0x04000002,
+ 0x483fc857, 0x59e40852, 0x59a80025, 0x80040580,
+ 0x04000004, 0x480bc857, 0x59e40052, 0x48035025,
+ 0x59940026, 0x803c0400, 0x48032826, 0x0201f800,
+ 0x00106021, 0x59940000, 0x82000580, 0x00000000,
+ 0x04020006, 0x59940026, 0x48032827, 0x497b2826,
+ 0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007,
+ 0x80000d40, 0x0400001d, 0x59941006, 0x59940025,
+ 0x80081c80, 0x04001004, 0x04000003, 0x480f2806,
+ 0x0401f016, 0x80040840, 0x48072807, 0x82040580,
+ 0x000003e8, 0x04020007, 0x4c040000, 0x4c0c0000,
+ 0x59940008, 0x0801f800, 0x5c001800, 0x5c000800,
+ 0x800409c0, 0x04020004, 0x59940008, 0x0801f800,
+ 0x0401f006, 0x400c0000, 0x820c1c00, 0x0000000a,
+ 0x040027ed, 0x480f2806, 0x5c001800, 0x4d180000,
+ 0x59c40008, 0x8c000534, 0x04020025, 0x417a3000,
+ 0x83947c00, 0x00000009, 0x583c0001, 0x80000d40,
+ 0x04020008, 0x823c7c00, 0x00000003, 0x811a3000,
+ 0x83180580, 0x00000005, 0x040207f8, 0x0401f018,
+ 0x583c1000, 0x59940025, 0x80080480, 0x04001005,
+ 0x04000004, 0x48007800, 0x80000040, 0x04021010,
+ 0x80040840, 0x48047801, 0x04000008, 0x82000400,
+ 0x0000000a, 0x48007800, 0x040027fa, 0x82040500,
+ 0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000,
+ 0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000,
+ 0x59940019, 0x80001540, 0x04000008, 0x04002007,
+ 0x59940025, 0x80080480, 0x497b2819, 0x04001003,
+ 0x04000002, 0x48032819, 0x59940004, 0x80000d40,
+ 0x0400002a, 0x4c040000, 0x5994001c, 0x80000d40,
+ 0x04000013, 0x5994101b, 0x59940025, 0x80080480,
+ 0x04001005, 0x04000004, 0x4803281b, 0x80000040,
+ 0x0402100b, 0x80040840, 0x4807281c, 0x04020004,
+ 0x5994001d, 0x0801f800, 0x0401f005, 0x82000400,
+ 0x0000000a, 0x4803281b, 0x040027f7, 0x5c000800,
+ 0x59941003, 0x59940025, 0x80080480, 0x04001005,
+ 0x04000004, 0x48032803, 0x80000040, 0x0402100b,
+ 0x80040840, 0x48072804, 0x04020004, 0x59940005,
+ 0x0801f800, 0x0401f005, 0x82000400, 0x0000000a,
+ 0x48032803, 0x040027f7, 0x5994001f, 0x80000d40,
+ 0x04000013, 0x5994101e, 0x59940025, 0x80080480,
+ 0x04001005, 0x04000004, 0x4803281e, 0x80000040,
+ 0x0402100b, 0x80040840, 0x4807281f, 0x04020004,
+ 0x59940020, 0x0801f800, 0x0401f005, 0x82000400,
+ 0x00000001, 0x4803281e, 0x040027f7, 0x59940022,
+ 0x80000d40, 0x04000013, 0x59941021, 0x59940025,
+ 0x80080480, 0x04001005, 0x04000004, 0x48032821,
+ 0x80000040, 0x0402100b, 0x80040840, 0x48072822,
+ 0x04020004, 0x59940023, 0x0801f800, 0x0401f005,
+ 0x82000400, 0x0000000a, 0x48032821, 0x040027f7,
+ 0x59940824, 0x59940025, 0x80040480, 0x02001800,
+ 0x001005d8, 0x48032824, 0x59940000, 0x0c01f001,
+ 0x00105fb5, 0x00105fb7, 0x00105fdd, 0x59940024,
+ 0x80000000, 0x48032824, 0x4203e000, 0x70000000,
+ 0x1c01f000, 0x592c0406, 0x800000c2, 0x800008c4,
+ 0x80040c00, 0x592c040a, 0x48066206, 0x82000d00,
+ 0x00000003, 0x02000000, 0x0010615e, 0x8c000500,
+ 0x04020029, 0x8c00051e, 0x02000000, 0x00106139,
+ 0x82000d00, 0x000000c0, 0x02020000, 0x0010612f,
+ 0x82000d00, 0x00002020, 0x02020000, 0x0010612c,
+ 0x813e79c0, 0x02020000, 0x0010612c, 0x592c0c0c,
+ 0x800409c0, 0x02020000, 0x0010612c, 0x59300a03,
+ 0x82040d80, 0x00000007, 0x02020000, 0x0010612c,
+ 0x4a026203, 0x00000003, 0x4a026403, 0x00000043,
+ 0x0201f800, 0x000200c9, 0x82080d40, 0x80003465,
+ 0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516,
+ 0x040207fe, 0x83300400, 0xa0000000, 0x480378e1,
+ 0x1c01f000, 0x8c000502, 0x02020000, 0x00106181,
+ 0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0,
+ 0x04000005, 0x82040d80, 0x000000c0, 0x02020000,
+ 0x00106186, 0x82000d00, 0x00002020, 0x82040d80,
+ 0x00002020, 0x02000000, 0x0010614d, 0x592c0207,
+ 0x80000040, 0x02020000, 0x00106157, 0x592c180d,
+ 0x800c19c0, 0x02020000, 0x00106157, 0x592c180f,
+ 0x59300007, 0x82000540, 0x00000011, 0x480e6011,
+ 0x48026007, 0x4a026203, 0x00000004, 0x4a026403,
+ 0x00000042, 0x42000800, 0x80002001, 0x0401f02a,
+ 0x5c000000, 0x4c000000, 0x4803c857, 0x4807c857,
+ 0x0401f003, 0x42000800, 0x00000001, 0x59325808,
+ 0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000,
+ 0x48065a06, 0x48026008, 0x592c040a, 0x8c000510,
+ 0x04020008, 0x0201f800, 0x000202ce, 0x417a7800,
+ 0x59300008, 0x80025d40, 0x0402078f, 0x1c01f000,
+ 0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000,
+ 0x82000540, 0x00001200, 0x48039000, 0x0401f7f4,
+ 0x59840000, 0x80000540, 0x04020002, 0x1c01f000,
+ 0x59840003, 0x80000540, 0x02020000, 0x001061fe,
+ 0x1c01f000, 0x48066004, 0x59bc00ea, 0x8c000516,
+ 0x040207fe, 0x83300400, 0x40000000, 0x480378e1,
+ 0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018,
+ 0x02020000, 0x00106c81, 0x8c000510, 0x0400002a,
+ 0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a,
+ 0x80080108, 0x820a3500, 0x0000000f, 0x4803c857,
+ 0x1201f000, 0x00106c87, 0x84000510, 0x48026004,
+ 0x0401f016, 0x840a653e, 0x59300004, 0x8c000520,
+ 0x040007fa, 0x82000500, 0xfffefeff, 0x48026004,
+ 0x8c08153e, 0x04020005, 0x42027000, 0x00000013,
+ 0x0401f859, 0x0401f009, 0x59300004, 0x8c000514,
+ 0x04000003, 0x0401ffb0, 0x0401f02f, 0x42027000,
+ 0x00000049, 0x0401f850, 0x59bc00ea, 0x82001500,
+ 0xb0000018, 0x02020000, 0x00106c81, 0x8c000510,
+ 0x040207d8, 0x1c01f000, 0x83640480, 0x00000010,
+ 0x0400101a, 0x41626000, 0x41580000, 0x59300a03,
+ 0x82040d80, 0x00000000, 0x04000008, 0x83326400,
+ 0x00000024, 0x81300c80, 0x040017f9, 0x42026000,
+ 0x0010d1c0, 0x0401f7f6, 0x8166c840, 0x83300c00,
+ 0x00000024, 0x80040480, 0x04021005, 0x4006c000,
+ 0x4a026203, 0x00000008, 0x1c01f000, 0x837ac540,
+ 0x0010d1c0, 0x0401f7fb, 0x42000000, 0x0010b854,
+ 0x0201f800, 0x0010aa47, 0x4967c857, 0x80026580,
+ 0x1c01f000, 0x83300480, 0x0010d1c0, 0x02001800,
+ 0x001005d8, 0x41580000, 0x81300480, 0x0402100c,
+ 0x04011000, 0x457a6000, 0x4a026202, 0x0000ffff,
+ 0x83300400, 0x00000003, 0x4803c840, 0x4a03c842,
+ 0x00000021, 0x8166c800, 0x1c01f000, 0x41540000,
+ 0x81300480, 0x02021800, 0x001005d8, 0x04011000,
+ 0x457a6000, 0x4a026202, 0x0000ffff, 0x83300400,
+ 0x00000003, 0x4803c840, 0x4a03c842, 0x00000021,
+ 0x59a80066, 0x49335065, 0x80000000, 0x48035066,
+ 0x1c01f000, 0x4d340000, 0x59326809, 0x59300406,
+ 0x82000500, 0x0000001f, 0x0c01f803, 0x5c026800,
+ 0x1c01f000, 0x00107966, 0x00107979, 0x00107993,
+ 0x000207c9, 0x001098f1, 0x0010990c, 0x0002083e,
+ 0x00107966, 0x00107979, 0x001064ee, 0x001079ac,
+ 0x00107966, 0x00107966, 0x00107966, 0x00107966,
+ 0x00107966, 0x001095a1, 0x0010a6c2, 0x00107966,
+ 0x00107966, 0x00107966, 0x00107966, 0x00107966,
+ 0x00107966, 0x00107966, 0x00107966, 0x00107966,
+ 0x00107966, 0x00107966, 0x00107966, 0x00107966,
+ 0x00107966, 0x59300203, 0x82000c80, 0x0000000e,
+ 0x02021800, 0x001005d8, 0x0c01f001, 0x001079aa,
+ 0x00108592, 0x000207dd, 0x00108720, 0x001087b9,
+ 0x001079aa, 0x001079aa, 0x001079aa, 0x00108577,
+ 0x001079aa, 0x001079aa, 0x001079aa, 0x001079aa,
+ 0x00108985, 0x83380480, 0x00000058, 0x04021007,
+ 0x83380480, 0x00000040, 0x04001004, 0x4d2c0000,
+ 0x0c01f803, 0x5c025800, 0x1c01f000, 0x0010861b,
+ 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+ 0x0010861d, 0x001086bd, 0x0010861b, 0x0010861b,
+ 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+ 0x0010861b, 0x0010861b, 0x0010861b, 0x0010861b,
+ 0x0010861b, 0x0010861b, 0x001086c1, 0x000207ff,
+ 0x0010861b, 0x001086c0, 0x001086c2, 0x59325808,
+ 0x59300811, 0x59301402, 0x59340200, 0x8c00050e,
+ 0x0402001c, 0x0401f826, 0x04000005, 0x4a025a04,
+ 0x00000103, 0x497a5c09, 0x0401f009, 0x4a025a04,
+ 0x00000103, 0x4a025a06, 0x00000000, 0x497a5c09,
+ 0x800409c0, 0x02020800, 0x00108785, 0x48065807,
+ 0x480a5c06, 0x0201f800, 0x000202c1, 0x5934000f,
+ 0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b,
+ 0x80000540, 0x02020800, 0x00020253, 0x0401f75e,
+ 0x592c020a, 0x8c000502, 0x040007e9, 0x800409c0,
+ 0x040007e7, 0x592c0208, 0x8c00050e, 0x040207e4,
+ 0x4933c857, 0x0201f000, 0x0010920f, 0x592c020a,
+ 0x8c000500, 0x04000010, 0x59300015, 0x592c380f,
+ 0x801c3c80, 0x0400000c, 0x4a025a06, 0x00000015,
+ 0x8c1c3d3e, 0x04000005, 0x4a025a06, 0x00000007,
+ 0x801c3880, 0x801c3800, 0x481fc857, 0x821c0d40,
+ 0x00000000, 0x1c01f000, 0x59300203, 0x82003480,
+ 0x0000000e, 0x02021800, 0x001005d8, 0x0c01f001,
+ 0x0010992b, 0x00020852, 0x00109fba, 0x00109fc8,
+ 0x0002086e, 0x0010992b, 0x0010a0a8, 0x0002088d,
+ 0x0010992b, 0x0010992b, 0x0010992b, 0x0010992b,
+ 0x0010992b, 0x0010992b, 0x83380580, 0x00000013,
+ 0x02020000, 0x00109f42, 0x59300403, 0x82027480,
+ 0x00000044, 0x02021800, 0x001005d8, 0x82000480,
+ 0x00000040, 0x02001800, 0x001005d8, 0x0c01f001,
+ 0x00109f9e, 0x00020864, 0x00109fa0, 0x00109fb2,
+ 0x59325808, 0x832c0500, 0x00ff0000, 0x04000005,
+ 0x592c0c0a, 0x8c040d1a, 0x02020000, 0x00109fad,
+ 0x0401fe91, 0x0401f710, 0x83380580, 0x00000048,
+ 0x04000007, 0x83380580, 0x00000053, 0x02000000,
+ 0x0010a04a, 0x0201f800, 0x001005d8, 0x5930001f,
+ 0x59301011, 0x59300809, 0x58040a00, 0x8c040d0e,
+ 0x02020000, 0x0010a026, 0x800811c0, 0x02020000,
+ 0x0010a033, 0x5930001f, 0x80000540, 0x02020000,
+ 0x0010a041, 0x59325808, 0x592c040a, 0x8c00051e,
+ 0x02000000, 0x0010a01c, 0x42027000, 0x00000041,
+ 0x0401f001, 0x83380480, 0x00000054, 0x02021800,
+ 0x001005d8, 0x83380480, 0x00000040, 0x02001000,
+ 0x0010a067, 0x0c01f001, 0x0010a073, 0x000208aa,
+ 0x0010a07f, 0x0010a086, 0x0010a073, 0x0010a073,
+ 0x0010a073, 0x0010a073, 0x0010a075, 0x0010a07a,
+ 0x0010a07a, 0x0010a073, 0x0010a073, 0x0010a073,
+ 0x0010a073, 0x0010a07a, 0x0010a073, 0x0010a07a,
+ 0x0010a073, 0x0010a075, 0x4a026203, 0x00000001,
+ 0x493a6403, 0x42000800, 0x80002042, 0x0401f672,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x14aa62b1,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000005,
+ 0xfffffffb, 0x02800004, 0x00000000, 0x0000c000,
+ 0x0000071d, 0x073fca5a, 0x0705a5a5, 0x01928009,
+ 0x070ff0e1, 0x03800006, 0x04958010, 0x05308000,
+ 0x05008000, 0x0600902f, 0x04a004dc, 0x0202f051,
+ 0x042e4020, 0x018f021b, 0x033e5000, 0x03020000,
+ 0x078d0018, 0x0493041a, 0x0092041c, 0x038a0305,
+ 0x078b0303, 0x048e8010, 0x0678aae5, 0x06000001,
+ 0x07818174, 0x040010e6, 0x0448e0e6, 0x04818010,
+ 0x002fb008, 0x0448e0e6, 0x04818010, 0x060ff0e6,
+ 0x00580401, 0x054880ff, 0x04818010, 0x022a5001,
+ 0x030430d4, 0x06780043, 0x030e0000, 0x030450ff,
+ 0x06780043, 0x03019000, 0x058185c6, 0x027c0045,
+ 0x03020000, 0x06810037, 0x027c0045, 0x03040000,
+ 0x068100c7, 0x027c0045, 0x03080000, 0x0781061e,
+ 0x04908037, 0x029105c4, 0x010410a6, 0x0379ff41,
+ 0x037fffff, 0x072d6000, 0x07601241, 0x050f80ff,
+ 0x032fa009, 0x05600400, 0x050f80ff, 0x056c04ff,
+ 0x068105dc, 0x073fa009, 0x06000001, 0x0279ff02,
+ 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff,
+ 0x045c0402, 0x048185dc, 0x060ff0d0, 0x0179feff,
+ 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x078105be,
+ 0x05600e41, 0x050f80ff, 0x032fa069, 0x07480000,
+ 0x068105d0, 0x06780043, 0x070000f0, 0x0781005f,
+ 0x037c00ff, 0x06000010, 0x0781005f, 0x038005cc,
+ 0x0379ff00, 0x070fffff, 0x06780043, 0x07f00000,
+ 0x075a0000, 0x020ef001, 0x028605ce, 0x05484000,
+ 0x02a1819e, 0x062d6001, 0x002fb001, 0x070ff069,
+ 0x01868072, 0x060ff079, 0x055c0441, 0x06810010,
+ 0x012fb000, 0x060560fb, 0x03800078, 0x060ff079,
+ 0x02868198, 0x070ff069, 0x055c0441, 0x06810010,
+ 0x060560fb, 0x0400d0d0, 0x062d6002, 0x0648300d,
+ 0x06810086, 0x070ff0d1, 0x062d6001, 0x045c040b,
+ 0x06810089, 0x05488000, 0x04818086, 0x072e500c,
+ 0x00208001, 0x05a004e1, 0x02800010, 0x062d6001,
+ 0x07f00000, 0x07f00000, 0x070ff0d1, 0x0179feff,
+ 0x070000ff, 0x055c040c, 0x058180bb, 0x0007b001,
+ 0x03079041, 0x0307a000, 0x06600a79, 0x050f80ff,
+ 0x053fa80a, 0x06000010, 0x072d5003, 0x078d0096,
+ 0x0307c003, 0x0007d004, 0x0107e005, 0x0307f006,
+ 0x02080007, 0x00081008, 0x01082009, 0x0308300a,
+ 0x0008400b, 0x0308500c, 0x068d00a1, 0x0678007a,
+ 0x07f00000, 0x010880ff, 0x03386000, 0x03010000,
+ 0x072e6300, 0x020ef07f, 0x02860010, 0x070ff07d,
+ 0x0450047c, 0x050f80ff, 0x002fa819, 0x068d00ae,
+ 0x02080001, 0x00081002, 0x0448807a, 0x068100b5,
+ 0x0379ff03, 0x070000ff, 0x01082003, 0x068d00b6,
+ 0x02386004, 0x03010000, 0x072e6c00, 0x02800010,
+ 0x06780043, 0x070000f0, 0x078105d7, 0x050020ff,
+ 0x027c0002, 0x06000010, 0x078100c3, 0x038005d7,
+ 0x0700c0d1, 0x0379ff0c, 0x070000ff, 0x0380008e,
+ 0x0204a051, 0x06780043, 0x070000f0, 0x037c00ff,
+ 0x06000010, 0x0781816a, 0x072d6000, 0x019485c0,
+ 0x050fb056, 0x044880e6, 0x04818010, 0x060ff0d0,
+ 0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff,
+ 0x078105be, 0x05a00212, 0x0349c0e4, 0x0781811d,
+ 0x070ff093, 0x050010ff, 0x070ff093, 0x045c0401,
+ 0x058180db, 0x02046092, 0x04002046, 0x04600202,
+ 0x00540401, 0x048280e6, 0x04500425, 0x070060ff,
+ 0x0730ffff, 0x0700000f, 0x0742000f, 0x05810190,
+ 0x07a005a6, 0x0648a002, 0x048180e9, 0x00047089,
+ 0x070ff047, 0x045c0443, 0x077800ff, 0x07f00000,
+ 0x0781818e, 0x07780047, 0x0500e000, 0x048185ad,
+ 0x070ff006, 0x01860117, 0x0179fe47, 0x0700000f,
+ 0x010480ff, 0x056c7048, 0x06818102, 0x007a0d4a,
+ 0x04003801, 0x0220f001, 0x0180010f, 0x07608e48,
+ 0x034a60ff, 0x0700f0ff, 0x074b88ff, 0x037000ff,
+ 0x07000600, 0x05500448, 0x074d00ff, 0x045a044a,
+ 0x0304a0ff, 0x070ff00f, 0x01540406, 0x05820117,
+ 0x04950120, 0x05a001bd, 0x02868123, 0x0134bfff,
+ 0x070fffff, 0x0104102e, 0x050fd041, 0x00800126,
+ 0x0595011d, 0x05a001bd, 0x0186011d, 0x0202f00e,
+ 0x052e4030, 0x040fd02f, 0x070fc0ff, 0x05a00218,
+ 0x02800010, 0x0400e02f, 0x042e4020, 0x0202f051,
+ 0x0004100e, 0x0004b00e, 0x050fd041, 0x024a6c46,
+ 0x04500423, 0x050070ff, 0x03620024, 0x050080ff,
+ 0x04004046, 0x0700500f, 0x03206000, 0x05601048,
+ 0x0700a0ff, 0x0700900a, 0x070ff005, 0x04500446,
+ 0x00540425, 0x04820157, 0x05601622, 0x050f80ff,
+ 0x063fa032, 0x06000002, 0x03203000, 0x01204000,
+ 0x03205000, 0x0120b000, 0x0320c000, 0x07601441,
+ 0x050f80ff, 0x043fa852, 0x06000001, 0x070ff056,
+ 0x056c02ff, 0x050fb0ff, 0x070560ff, 0x03079041,
+ 0x05600e41, 0x050f80ff, 0x073fa011, 0x0600003d,
+ 0x06780043, 0x07f00000, 0x065a007a, 0x010880ff,
+ 0x04a001b6, 0x058d0150, 0x0208a04a, 0x0108b04b,
+ 0x02386001, 0x03010000, 0x072e6300, 0x028000a8,
+ 0x0500d00a, 0x05500405, 0x014a68ff, 0x070090ff,
+ 0x0154040a, 0x0700c0ff, 0x0600a023, 0x0500b024,
+ 0x02206001, 0x05601622, 0x050f80ff, 0x063fa04a,
+ 0x06000002, 0x05601022, 0x050f80ff, 0x043fa819,
+ 0x06000001, 0x0600a00d, 0x0180013c, 0x06780043,
+ 0x070000f0, 0x050010ff, 0x027c0001, 0x07000030,
+ 0x078105b4, 0x027c0001, 0x06000020, 0x078105b4,
+ 0x038005cc, 0x054880ff, 0x06810010, 0x070ff056,
+ 0x050fb0ff, 0x044880e5, 0x0581017d, 0x044880e6,
+ 0x04818010, 0x00800183, 0x056c02ff, 0x050fb0ff,
+ 0x070560ff, 0x072e5300, 0x044880e6, 0x04818010,
+ 0x072d5003, 0x06780043, 0x07f00000, 0x010880ff,
+ 0x058d0187, 0x03386005, 0x03010000, 0x033e6000,
+ 0x0700000c, 0x052e5200, 0x02800010, 0x0120918e,
+ 0x018004e4, 0x01209190, 0x018004e4, 0x00209192,
+ 0x018004e4, 0x03209000, 0x018004e4, 0x01209196,
+ 0x018004e4, 0x00209198, 0x018004e4, 0x02493075,
+ 0x06810510, 0x0120919a, 0x018004e4, 0x06601e01,
+ 0x050f80ff, 0x063fa029, 0x06000008, 0x02015010,
+ 0x02016051, 0x00017051, 0x00011051, 0x05601a41,
+ 0x050f80ff, 0x053fa83a, 0x06000008, 0x05600e41,
+ 0x050f80ff, 0x01464000, 0x032fa00a, 0x07006011,
+ 0x05007012, 0x04008013, 0x07009014, 0x0600a015,
+ 0x0400b016, 0x0700c017, 0x07c00000, 0x072d5003,
+ 0x06601479, 0x050f80ff, 0x048d01b9, 0x063fa051,
+ 0x0600003e, 0x07c00000, 0x06005051, 0x0400e02c,
+ 0x0660060e, 0x050f80ff, 0x032fa009, 0x0379ff00,
+ 0x070000ff, 0x076c0000, 0x058101dd, 0x0660480e,
+ 0x0500e0ff, 0x034000ff, 0x01540427, 0x0582020a,
+ 0x03400005, 0x070ff005, 0x055c0428, 0x0481020e,
+ 0x01680e05, 0x056c0405, 0x068181bf, 0x040f8029,
+ 0x053fa809, 0x07000024, 0x06600649, 0x050f80ff,
+ 0x032fa009, 0x0379ff00, 0x070000ff, 0x076c0000,
+ 0x068181bf, 0x0400e049, 0x0340002d, 0x050f802b,
+ 0x053fa80a, 0x06000016, 0x0660480e, 0x0302c0ff,
+ 0x034000ff, 0x01540427, 0x0582020c, 0x072d6000,
+ 0x0460040e, 0x050f80ff, 0x0104e0d1, 0x0379ff4e,
+ 0x0700ffff, 0x062d6002, 0x032fa009, 0x0004d0d0,
+ 0x074b004d, 0x07780000, 0x07ffff00, 0x055a044d,
+ 0x070000ff, 0x00201008, 0x04002051, 0x06003051,
+ 0x05304000, 0x07000060, 0x03205009, 0x07006022,
+ 0x0460040e, 0x050f80ff, 0x032fa03a, 0x06603c0e,
+ 0x050f80ff, 0x073fa00a, 0x07000027, 0x050010d1,
+ 0x0460320e, 0x050f80ff, 0x012fa80a, 0x060ff00e,
+ 0x055c042e, 0x04810210, 0x07c00000, 0x0400e026,
+ 0x008001cb, 0x0202c026, 0x008001e6, 0x0500e02e,
+ 0x008001e6, 0x0400e051, 0x01800209, 0x0349c0e4,
+ 0x04810215, 0x07c00000, 0x013e4000, 0x070c0000,
+ 0x07c00000, 0x013e4000, 0x03080000, 0x07c00000,
+ 0x009702f4, 0x022a5002, 0x0790821d, 0x00910291,
+ 0x030400a6, 0x0678aae5, 0x06000001, 0x00a1860e,
+ 0x06600c40, 0x050f80ff, 0x032fa021, 0x074b0000,
+ 0x076c0600, 0x07818293, 0x05600403, 0x050f80ff,
+ 0x073fa009, 0x06000002, 0x0279ff04, 0x0700ffff,
+ 0x010440d7, 0x0179fe44, 0x0700ffff, 0x045c0404,
+ 0x07818295, 0x0349f044, 0x0681829e, 0x02495001,
+ 0x06818297, 0x060ff079, 0x045c0440, 0x0781823c,
+ 0x0644f07a, 0x002fb008, 0x060ff079, 0x045c0440,
+ 0x07818241, 0x0644f07a, 0x002fb008, 0x0648f001,
+ 0x07818288, 0x04600e40, 0x050f80ff, 0x06480001,
+ 0x04810257, 0x0448e001, 0x04810273, 0x02460001,
+ 0x0644f001, 0x012fa80a, 0x04008040, 0x05a004ee,
+ 0x0286828c, 0x05a004d8, 0x062da001, 0x013e4000,
+ 0x06000080, 0x06930013, 0x02920013, 0x02800010,
+ 0x0644f001, 0x012fa80a, 0x020ef002, 0x00860275,
+ 0x04600840, 0x050f80ff, 0x053fa809, 0x06000002,
+ 0x05780105, 0x00800440, 0x017c0105, 0x05000400,
+ 0x06818275, 0x06601e02, 0x050f80ff, 0x053fa809,
+ 0x06000002, 0x04602a40, 0x050f80ff, 0x070ff005,
+ 0x053fa809, 0x06000002, 0x055c0405, 0x06818275,
+ 0x04008040, 0x0045e008, 0x05a004d8, 0x00800251,
+ 0x0644f001, 0x012fa80a, 0x050020d8, 0x04600440,
+ 0x050f80ff, 0x073fa00a, 0x06000001, 0x06480001,
+ 0x07818281, 0x05308000, 0x03040000, 0x06009040,
+ 0x04a004dc, 0x00800251, 0x06a0060e, 0x054b0800,
+ 0x056a0700, 0x06600c40, 0x050f80ff, 0x032fa00a,
+ 0x00800251, 0x013e4000, 0x06000080, 0x01209288,
+ 0x018004e4, 0x06009008, 0x05308000, 0x05004000,
+ 0x04a004dc, 0x00800251, 0x02209002, 0x008002e5,
+ 0x03209000, 0x008002e5, 0x02209004, 0x008002e5,
+ 0x04a002fd, 0x062da001, 0x05308000, 0x05002000,
+ 0x06009040, 0x04a004dc, 0x02800013, 0x013e4000,
+ 0x06000080, 0x02495001, 0x078182db, 0x04600840,
+ 0x050f80ff, 0x053fa809, 0x06000001, 0x0721f000,
+ 0x0349f003, 0x058102aa, 0x0245f01f, 0x06000002,
+ 0x018602db, 0x07601400, 0x050f80ff, 0x012fa809,
+ 0x06480001, 0x058102db, 0x06602440, 0x050f80ff,
+ 0x012fa809, 0x020ef001, 0x038682db, 0x019b02db,
+ 0x050020d8, 0x062da001, 0x06303002, 0x05000430,
+ 0x04600440, 0x050f80ff, 0x073fa012, 0x06000001,
+ 0x028f82bf, 0x050040d8, 0x062da001, 0x07601e00,
+ 0x050f80ff, 0x073fa009, 0x06000001, 0x060ff004,
+ 0x00540402, 0x048202d9, 0x06005051, 0x06006051,
+ 0x06602240, 0x050f80ff, 0x063fa01a, 0x06000002,
+ 0x06600a40, 0x050f80ff, 0x073fa00a, 0x07000003,
+ 0x060ff040, 0x045a041f, 0x010eb0ff, 0x06930013,
+ 0x02920013, 0x02800010, 0x04004002, 0x018002c9,
+ 0x04a002fd, 0x062da001, 0x05308000, 0x07005000,
+ 0x06009040, 0x04a004dc, 0x050080d8, 0x05a004e1,
+ 0x062da001, 0x02800013, 0x050fd009, 0x050fd041,
+ 0x013e4000, 0x06000080, 0x05308000, 0x03013000,
+ 0x04a004dc, 0x010440d7, 0x0349f044, 0x048102f2,
+ 0x062da001, 0x008f02f2, 0x03e00000, 0x062da001,
+ 0x02800013, 0x0249c0e5, 0x06810013, 0x062da001,
+ 0x07f00000, 0x07f00000, 0x033e5000, 0x070c0000,
+ 0x018f02f6, 0x03800011, 0x050020d8, 0x04600440,
+ 0x050f80ff, 0x073fa00a, 0x06000001, 0x07c00000,
+ 0x002fb001, 0x03800306, 0x012fb000, 0x03075087,
+ 0x068d0307, 0x03386000, 0x03020000, 0x04482075,
+ 0x06810352, 0x0648a0e6, 0x07810347, 0x0642007f,
+ 0x06810345, 0x0340007e, 0x060ff038, 0x0154047e,
+ 0x02d00334, 0x0560027d, 0x050f80ff, 0x032fa009,
+ 0x030ef000, 0x02860504, 0x0107d000, 0x05600800,
+ 0x050f80ff, 0x032fa009, 0x03681e00, 0x04500420,
+ 0x050f80ff, 0x073fa009, 0x0700003f, 0x03800311,
+ 0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819,
+ 0x078d0327, 0x02080001, 0x00081002, 0x0448807a,
+ 0x0781032e, 0x0379ff03, 0x070000ff, 0x01082003,
+ 0x068d032f, 0x02386004, 0x03010000, 0x072e6c00,
+ 0x02800352, 0x0380033a, 0x0380033c, 0x0280033e,
+ 0x02800340, 0x03800342, 0x03800344, 0x0727c005,
+ 0x02800323, 0x0627c008, 0x02800323, 0x0627c00b,
+ 0x02800323, 0x0627c00e, 0x02800323, 0x0727c011,
+ 0x02800323, 0x03800314, 0x052e6800, 0x02800352,
+ 0x044880e6, 0x07810533, 0x052e6200, 0x070ff088,
+ 0x0179feff, 0x070fffff, 0x04818501, 0x060ff083,
+ 0x0086836d, 0x033e6000, 0x07000003, 0x068d0352,
+ 0x07286000, 0x07f00000, 0x078d0355, 0x038c0306,
+ 0x0648c0e6, 0x05818372, 0x0448e0e6, 0x0781036a,
+ 0x004920e6, 0x07810365, 0x07a0056f, 0x05001088,
+ 0x00700101, 0x03100000, 0x00088001, 0x033e6000,
+ 0x07000088, 0x03800560, 0x02386001, 0x07030000,
+ 0x033e6000, 0x06000008, 0x028003f1, 0x02799075,
+ 0x0500040f, 0x06810010, 0x06601479, 0x050080ff,
+ 0x06309052, 0x0600003e, 0x02800376, 0x06602279,
+ 0x050080ff, 0x05309812, 0x07000041, 0x0648007a,
+ 0x0781037e, 0x04488075, 0x0581837e, 0x040f8008,
+ 0x070fa009, 0x0049107a, 0x01a183f3, 0x00798075,
+ 0x06000507, 0x05818521, 0x0448b075, 0x06810385,
+ 0x02493075, 0x0681050e, 0x0249c0e6, 0x048183e0,
+ 0x0648c0e6, 0x0581839a, 0x068d0389, 0x02386001,
+ 0x07030000, 0x0049107a, 0x07810390, 0x020ef083,
+ 0x0386039a, 0x06483075, 0x068103ef, 0x0678007a,
+ 0x07000035, 0x03a184cf, 0x05308000, 0x07060000,
+ 0x06009079, 0x04a004dc, 0x028003ef, 0x0448807a,
+ 0x0681039e, 0x06483075, 0x058104f9, 0x0448d07a,
+ 0x068103a2, 0x06483075, 0x058104f9, 0x068d03a2,
+ 0x02386001, 0x07030000, 0x0444e07a, 0x0648307a,
+ 0x048183c7, 0x0448707a, 0x068103ea, 0x0648f07a,
+ 0x078103b2, 0x05a004cf, 0x04008079, 0x05a004ee,
+ 0x008683c2, 0x05a004d8, 0x028003ef, 0x0560107b,
+ 0x050f80ff, 0x032fa009, 0x0349c000, 0x058183c0,
+ 0x04600e79, 0x050f80ff, 0x073fa00a, 0x0600003d,
+ 0x06600a79, 0x050f80ff, 0x053fa80a, 0x06000010,
+ 0x028003ef, 0x0046e07a, 0x028003ea, 0x06009008,
+ 0x05308000, 0x05004000, 0x04a004dc, 0x028003ef,
+ 0x0560167b, 0x050f80ff, 0x032fa011, 0x070ff000,
+ 0x04500401, 0x030460ff, 0x060ff025, 0x00540446,
+ 0x078203d1, 0x030460ff, 0x04092046, 0x05a00218,
+ 0x06600679, 0x050f80ff, 0x00201007, 0x012fa80a,
+ 0x0046047a, 0x034630ff, 0x050020ff, 0x06003051,
+ 0x04600e79, 0x050f80ff, 0x073fa012, 0x06000001,
+ 0x028003ef, 0x033e6a00, 0x0202000e, 0x02079051,
+ 0x07000088, 0x078d03e4, 0x0744c000, 0x01088000,
+ 0x03386006, 0x03010000, 0x02800010, 0x05a004cf,
+ 0x05308000, 0x03020000, 0x06009079, 0x04a004dc,
+ 0x033e6a00, 0x0302000a, 0x02079051, 0x02800010,
+ 0x04603e79, 0x050f80ff, 0x032fa009, 0x070ff000,
+ 0x0186040c, 0x057dfeff, 0x07ffffff, 0x0581040c,
+ 0x050f8000, 0x012fa811, 0x0079fe02, 0x070000ff,
+ 0x077d66ff, 0x060000dc, 0x0781840c, 0x060ff001,
+ 0x0286840d, 0x064b0002, 0x06420002, 0x060ff002,
+ 0x05500400, 0x050f80ff, 0x05004084, 0x073fa00a,
+ 0x06000002, 0x07c00000, 0x04600201, 0x050f80ff,
+ 0x073fa009, 0x06000001, 0x0079fe02, 0x070000ff,
+ 0x077d72ff, 0x070000dd, 0x0781840c, 0x064b0002,
+ 0x06420002, 0x06000001, 0x01800406, 0x0605004c,
+ 0x0180041e, 0x0493041a, 0x04a004d5, 0x054bc450,
+ 0x05810421, 0x01d00422, 0x01800421, 0x00800432,
+ 0x00800434, 0x00800432, 0x008004a7, 0x0180043f,
+ 0x00800434, 0x01800471, 0x00800432, 0x00800432,
+ 0x008004ab, 0x00800432, 0x018004af, 0x008004c4,
+ 0x01800488, 0x00800432, 0x00800432, 0x00209432,
+ 0x018004e4, 0x0379ff50, 0x070fffff, 0x060ff079,
+ 0x055c0450, 0x048104a4, 0x002fb008, 0x060ff079,
+ 0x055c0450, 0x058104a3, 0x04a004c7, 0x0180049c,
+ 0x0179fe50, 0x070fffff, 0x070050ff, 0x060ff079,
+ 0x055c0405, 0x04810449, 0x002fb008, 0x060ff079,
+ 0x055c0405, 0x078184a0, 0x070ff087, 0x017980ff,
+ 0x06000507, 0x06818451, 0x02203040, 0x05002087,
+ 0x0049d002, 0x0481046b, 0x04930458, 0x01257000,
+ 0x073c3fff, 0x0700000f, 0x052e4003, 0x072e5030,
+ 0x0304c050, 0x02400057, 0x06740057, 0x06000002,
+ 0x06820016, 0x04002083, 0x07003084, 0x04004085,
+ 0x06602279, 0x050f80ff, 0x063fa01a, 0x06000001,
+ 0x05a004cf, 0x07a00578, 0x033e6a00, 0x0302000a,
+ 0x062e5020, 0x003e4002, 0x07000a00, 0x028003f1,
+ 0x07420003, 0x0781844e, 0x00798002, 0x06000507,
+ 0x06818451, 0x0180045c, 0x05930478, 0x01257000,
+ 0x073c3fff, 0x0700000f, 0x052e4003, 0x072e5030,
+ 0x0304c050, 0x067800e6, 0x07000041, 0x0581047d,
+ 0x07a00581, 0x04818016, 0x002fb008, 0x067800e6,
+ 0x07000041, 0x04810483, 0x07a00581, 0x04818016,
+ 0x062e5020, 0x003e4002, 0x07000a00, 0x03e00000,
+ 0x02800010, 0x0379ff50, 0x070fffff, 0x060ff079,
+ 0x055c0450, 0x0781848e, 0x0245507a, 0x002fb008,
+ 0x060ff079, 0x055c0450, 0x07818493, 0x0245507a,
+ 0x002fb008, 0x05600e50, 0x050f80ff, 0x012fa809,
+ 0x02455001, 0x05600e50, 0x050f80ff, 0x012fa80a,
+ 0x0080049d, 0x002fb008, 0x003e4002, 0x07000a00,
+ 0x02800016, 0x079384a3, 0x062e5020, 0x042e4002,
+ 0x002fb008, 0x013e4000, 0x05000e00, 0x02800016,
+ 0x0179fe50, 0x070fffff, 0x010210ff, 0x02800016,
+ 0x0179fe50, 0x070fffff, 0x050340ff, 0x0080049d,
+ 0x0179fe50, 0x070fffff, 0x0102e0ff, 0x0760282e,
+ 0x050f80ff, 0x05222000, 0x07223000, 0x05224000,
+ 0x07225000, 0x07226000, 0x05227000, 0x05228000,
+ 0x07229000, 0x0722a000, 0x0522b000, 0x063fa051,
+ 0x07000011, 0x0202c026, 0x0522d000, 0x052e400c,
+ 0x02800016, 0x030430d4, 0x062e5008, 0x00800176,
+ 0x05600e50, 0x050f80ff, 0x032fa009, 0x03460000,
+ 0x018004d2, 0x0246007a, 0x0045207a, 0x008004d0,
+ 0x0246007a, 0x0600007a, 0x04600e79, 0x050f80ff,
+ 0x032fa00a, 0x07c00000, 0x029284d5, 0x070500e1,
+ 0x07c00000, 0x0245f008, 0x048404d9, 0x020e0008,
+ 0x07c00000, 0x070ff009, 0x065a0008, 0x058404de,
+ 0x020e0008, 0x07c00000, 0x058404e1, 0x020e0008,
+ 0x07c00000, 0x05308000, 0x0500d000, 0x04a004dc,
+ 0x04a004e9, 0x02800010, 0x052e4300, 0x072e500c,
+ 0x073c3fff, 0x0700000f, 0x07c00000, 0x06602208,
+ 0x050f80ff, 0x032fa011, 0x076a0000, 0x068184f7,
+ 0x066a0001, 0x048104f7, 0x04002051, 0x07c00000,
+ 0x00202001, 0x07c00000, 0x0648307a, 0x00a18608,
+ 0x05a004cc, 0x05308000, 0x05001000, 0x06009079,
+ 0x04a004dc, 0x03800560, 0x0249c0e6, 0x058104f9,
+ 0x0280036d, 0x0648307a, 0x07818196, 0x05a004cf,
+ 0x05308000, 0x03013000, 0x03209006, 0x04a004dc,
+ 0x033e6000, 0x07030000, 0x02800345, 0x02490075,
+ 0x0781051e, 0x04002089, 0x04780102, 0x07f00000,
+ 0x05001088, 0x07a0056f, 0x04740101, 0x03100000,
+ 0x060ff002, 0x045c0401, 0x0481851f, 0x00088001,
+ 0x033e6000, 0x070000c0, 0x0380055c, 0x07f00000,
+ 0x0220951f, 0x018004e4, 0x0648307a, 0x07810527,
+ 0x06780075, 0x06000007, 0x0581852e, 0x06a00608,
+ 0x06486075, 0x06818194, 0x02490075, 0x0781819a,
+ 0x04487075, 0x05818536, 0x0280053d, 0x05308000,
+ 0x03010000, 0x06009079, 0x04a004dc, 0x02800010,
+ 0x0448e0e6, 0x04818352, 0x00800192, 0x05308000,
+ 0x0500e000, 0x06009079, 0x04a004dc, 0x04008089,
+ 0x05a004e1, 0x0380055c, 0x05a004cc, 0x05308000,
+ 0x0700f000, 0x06009079, 0x07000088, 0x06a00545,
+ 0x04a004dc, 0x02800010, 0x03386000, 0x07030000,
+ 0x07f00000, 0x078d0548, 0x033e6a00, 0x0202000e,
+ 0x02079051, 0x0448b075, 0x07810553, 0x02493075,
+ 0x07810553, 0x05301005, 0x03010000, 0x03800555,
+ 0x05301006, 0x03010000, 0x05002087, 0x06485002,
+ 0x05818555, 0x0744c000, 0x01088000, 0x02086001,
+ 0x07c00000, 0x05001088, 0x07a0056f, 0x0644c001,
+ 0x00088001, 0x033e6a00, 0x0202000e, 0x004920e6,
+ 0x05818565, 0x02079051, 0x078d0565, 0x060ff089,
+ 0x034990ff, 0x0781056c, 0x03386005, 0x03010000,
+ 0x02800010, 0x03386006, 0x03010000, 0x02800010,
+ 0x078d056f, 0x03386000, 0x07030000, 0x07f00000,
+ 0x068d0573, 0x070ff087, 0x074850ff, 0x05818574,
+ 0x07c00000, 0x078d0578, 0x02386001, 0x07030000,
+ 0x07f00000, 0x068d057c, 0x070ff087, 0x074850ff,
+ 0x0581857d, 0x07c00000, 0x05002087, 0x0049d002,
+ 0x05818590, 0x002fb008, 0x067800e6, 0x07000041,
+ 0x002fb008, 0x05818590, 0x07a005a6, 0x0448e002,
+ 0x07810593, 0x0648a002, 0x0481859d, 0x06486002,
+ 0x06810597, 0x02400057, 0x056a02ff, 0x07c00000,
+ 0x07a005a6, 0x06788102, 0x06000004, 0x05818590,
+ 0x04002089, 0x070ff0d4, 0x045c0402, 0x077800ff,
+ 0x07f00000, 0x05818590, 0x00202010, 0x038c0590,
+ 0x07f00000, 0x06420002, 0x0481859e, 0x07a00578,
+ 0x033e6a00, 0x0302000a, 0x07c00000, 0x07f00000,
+ 0x060ff0a2, 0x050020ff, 0x060ff0a2, 0x045c0402,
+ 0x048185a7, 0x07c00000, 0x05a00218, 0x03495047,
+ 0x078105b2, 0x0320901d, 0x02800604, 0x0220901f,
+ 0x02800604, 0x014980e4, 0x04818010, 0x013e4000,
+ 0x07003000, 0x05600e35, 0x050f80ff, 0x07a006fc,
+ 0x01208003, 0x05a004e1, 0x038005cc, 0x03209009,
+ 0x02800604, 0x03209011, 0x02800604, 0x02209007,
+ 0x02800604, 0x03209003, 0x02800604, 0x00498043,
+ 0x058185be, 0x00497043, 0x048185c2, 0x02209001,
+ 0x02800604, 0x0220900d, 0x02800604, 0x0320900f,
+ 0x02800604, 0x03493000, 0x068105d5, 0x027c0045,
+ 0x070a0000, 0x078105de, 0x0220900b, 0x02800604,
+ 0x02209013, 0x05308000, 0x01012000, 0x04a004dc,
+ 0x00800183, 0x03209005, 0x02800604, 0x072e500c,
+ 0x00208002, 0x05a004e1, 0x02800010, 0x02209015,
+ 0x02800604, 0x072d6000, 0x05308000, 0x05007000,
+ 0x07f00000, 0x070090d1, 0x0379ff09, 0x0700ffff,
+ 0x04a004dc, 0x03209017, 0x02800604, 0x033e5000,
+ 0x06000080, 0x02209019, 0x02800604, 0x072d6000,
+ 0x033e5000, 0x06000080, 0x07f00000, 0x060ff0d0,
+ 0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff,
+ 0x04818010, 0x02400058, 0x00642058, 0x06820010,
+ 0x033e5000, 0x06000080, 0x04058051, 0x0320901b,
+ 0x02800604, 0x05308000, 0x01012000, 0x04a004dc,
+ 0x00800176, 0x05a00218, 0x05308000, 0x05008000,
+ 0x06009079, 0x04a004dc, 0x07c00000, 0x034900e4,
+ 0x05818618, 0x013e4000, 0x070000c0, 0x07f00000,
+ 0x034900e4, 0x04818616, 0x07c00000, 0x013e4000,
+ 0x06000080, 0x07f00000, 0x07f00000, 0x07f00000,
+ 0x034900e4, 0x06810610, 0x03800618, 0x072d6000,
+ 0x00498043, 0x06810632, 0x060ff0d0, 0x0179feff,
+ 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x058185e2,
+ 0x050f8030, 0x032fa009, 0x0379ff00, 0x0700ffff,
+ 0x070ff0d1, 0x0179feff, 0x0700ffff, 0x055c0400,
+ 0x078105e2, 0x04004051, 0x0280067a, 0x06a006dc,
+ 0x062d6001, 0x020ef004, 0x038605e4, 0x06600004,
+ 0x050f80ff, 0x032fa009, 0x074b0000, 0x05002000,
+ 0x0769ff00, 0x01640800, 0x078205e4, 0x01640e00,
+ 0x058285e4, 0x070ff036, 0x045c0404, 0x0581864d,
+ 0x072d6000, 0x050f8030, 0x032fa009, 0x0379ff00,
+ 0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff,
+ 0x055c0400, 0x078105e2, 0x04482034, 0x078105ff,
+ 0x06483034, 0x058185ff, 0x070ff0d4, 0x077800ff,
+ 0x070000f0, 0x037c00ff, 0x06000010, 0x0681067a,
+ 0x06a006d6, 0x024900e5, 0x0681065d, 0x033e5000,
+ 0x06000080, 0x02800010, 0x04601c04, 0x050f80ff,
+ 0x053fa809, 0x06000020, 0x030ef041, 0x038605ee,
+ 0x062d6002, 0x05602a41, 0x050f80ff, 0x012fa809,
+ 0x060ff0d0, 0x074b00ff, 0x045c0401, 0x05818678,
+ 0x062d6001, 0x07602841, 0x050f80ff, 0x053fa809,
+ 0x06000001, 0x070ff0d1, 0x054b80ff, 0x074b0003,
+ 0x055c0403, 0x05818678, 0x033e5000, 0x06000080,
+ 0x0080070e, 0x07600041, 0x0280065e, 0x06a006d6,
+ 0x024900e5, 0x06810680, 0x033e5000, 0x06000080,
+ 0x02800010, 0x06a006c2, 0x030ef041, 0x028605f2,
+ 0x04058051, 0x072d6000, 0x05601041, 0x050f80ff,
+ 0x012fa809, 0x0600a0d0, 0x0500b0d1, 0x062d6001,
+ 0x07f00000, 0x07f00000, 0x0600c0d0, 0x0500d0d1,
+ 0x062d6002, 0x0279ff0d, 0x07ff0000, 0x044d800d,
+ 0x060ff0d0, 0x074b00ff, 0x065a000d, 0x06601201,
+ 0x050f80ff, 0x073fa022, 0x07000005, 0x0079fe0d,
+ 0x070000ff, 0x050020ff, 0x05602a41, 0x050f80ff,
+ 0x073fa00a, 0x06000001, 0x020ef004, 0x028606bf,
+ 0x04601c04, 0x050f80ff, 0x053fa809, 0x06000001,
+ 0x050f80ff, 0x053fa80a, 0x06000020, 0x07602841,
+ 0x050f80ff, 0x073fa009, 0x06000001, 0x0279ff02,
+ 0x070000ff, 0x0678000d, 0x0700ff00, 0x065a0002,
+ 0x07602841, 0x050f80ff, 0x073fa00a, 0x06000001,
+ 0x07600041, 0x050f80ff, 0x053fa80a, 0x06000001,
+ 0x07601241, 0x050f80ff, 0x073fa00a, 0x06000002,
+ 0x033e5000, 0x06000080, 0x0080070e, 0x040f8032,
+ 0x073fa011, 0x06000001, 0x060ff002, 0x055c0403,
+ 0x058186ca, 0x00041051, 0x07c00000, 0x04600402,
+ 0x04500432, 0x050f80ff, 0x053fa809, 0x06000020,
+ 0x00400402, 0x01680eff, 0x070030ff, 0x040f8032,
+ 0x053fa80a, 0x06000001, 0x07c00000, 0x024900e5,
+ 0x068106d9, 0x07c00000, 0x033e5000, 0x070000c0,
+ 0x07c00000, 0x05004036, 0x060000d0, 0x0179fe00,
+ 0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068106fb,
+ 0x070000d1, 0x0379ff00, 0x0700ffff, 0x06005051,
+ 0x060ff031, 0x05500405, 0x050f80ff, 0x073fa009,
+ 0x06000002, 0x020ef004, 0x038606f5, 0x04600404,
+ 0x050f80ff, 0x012fa809, 0x0079fe01, 0x0700ffff,
+ 0x055c0400, 0x068106fb, 0x01400405, 0x070050ff,
+ 0x057de0ff, 0x06000007, 0x058186e7, 0x04004051,
+ 0x07c00000, 0x072d6000, 0x07f00000, 0x07f00000,
+ 0x000110d0, 0x010120d1, 0x062d6001, 0x07f00000,
+ 0x07f00000, 0x020130d0, 0x010140d1, 0x062d6002,
+ 0x010170d4, 0x07f00000, 0x020150d0, 0x030160d1,
+ 0x053fa83a, 0x06000008, 0x07c00000, 0x07600c41,
+ 0x050f80ff, 0x073fa009, 0x06000001, 0x04780102,
+ 0x07ffff00, 0x046a0702, 0x050f80ff, 0x073fa00a,
+ 0x06000001, 0x05600e41, 0x050f80ff, 0x032fa069,
+ 0x03800053, 0xba6b4e34, 0x02800004, 0x00000000,
+ 0x00008000, 0x00000518, 0x040f801f, 0x012fa8c9,
+ 0x040f801f, 0x073fa081, 0x06000010, 0x03200005,
+ 0x07420000, 0x050fb000, 0x040f801f, 0x073fa011,
+ 0x06000038, 0x040f801f, 0x053fa859, 0x0700003a,
+ 0x050fe000, 0x0581800a, 0x0684003d, 0x04958019,
+ 0x030e0011, 0x072e4200, 0x03800014, 0x0291001f,
+ 0x050010c0, 0x04482001, 0x058180e8, 0x06483001,
+ 0x0781814b, 0x02920029, 0x068b0029, 0x018a0150,
+ 0x050010c0, 0x06780001, 0x050007c0, 0x06818223,
+ 0x06780001, 0x0500f800, 0x07818263, 0x03910030,
+ 0x040fe029, 0x03860030, 0x076c001d, 0x04810294,
+ 0x076c0a1d, 0x048102b9, 0x0292003d, 0x040fe02f,
+ 0x0286003d, 0x06000013, 0x050fb000, 0x066c0073,
+ 0x068103c2, 0x0297003d, 0x014920e4, 0x0481803d,
+ 0x03400000, 0x076c0a00, 0x04818034, 0x0796003f,
+ 0x03b900b8, 0x05908014, 0x010170e1, 0x07780017,
+ 0x03e00000, 0x06810092, 0x050010ff, 0x0179fe17,
+ 0x031fffff, 0x070000ff, 0x05600800, 0x050f80ff,
+ 0x073fa009, 0x06000001, 0x06780002, 0x02800040,
+ 0x037c00ff, 0x03800000, 0x0681005e, 0x0249f002,
+ 0x068100ab, 0x0448e002, 0x0681005e, 0x07600c00,
+ 0x050f80ff, 0x073fa009, 0x06000001, 0x06780002,
+ 0x07ffff00, 0x037c00ff, 0x05000200, 0x048180ab,
+ 0x064bd401, 0x03d00060, 0x038000a9, 0x02800068,
+ 0x03800072, 0x0280007c, 0x02800086, 0x03800090,
+ 0x038000a9, 0x038000a9, 0x050fe027, 0x0186806c,
+ 0x01028000, 0x0380006f, 0x07600027, 0x050f80ff,
+ 0x032fa00a, 0x01027000, 0x02400029, 0x028000ab,
+ 0x040fe025, 0x00868076, 0x03026000, 0x02800079,
+ 0x06600025, 0x050f80ff, 0x032fa00a, 0x03025000,
+ 0x02400029, 0x028000ab, 0x050fe021, 0x00868080,
+ 0x01022000, 0x02800083, 0x07600021, 0x050f80ff,
+ 0x032fa00a, 0x01021000, 0x02400029, 0x028000ab,
+ 0x040fe023, 0x0086808a, 0x01024000, 0x0380008d,
+ 0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000,
+ 0x02400029, 0x028000ab, 0x06a000c8, 0x028000ab,
+ 0x01640817, 0x058280a9, 0x070ff017, 0x03d00096,
+ 0x0280009e, 0x038000a0, 0x038000a3, 0x038000a6,
+ 0x038000a9, 0x038000a9, 0x038000a9, 0x038000a9,
+ 0x03e00000, 0x03800014, 0x059080a0, 0x030160e1,
+ 0x028000ab, 0x059080a3, 0x030150e1, 0x028000ab,
+ 0x059080a6, 0x010140e1, 0x028000ab, 0x060fc013,
+ 0x06a00510, 0x03800014, 0x072e4800, 0x07000012,
+ 0x038000bb, 0x0747f000, 0x05600800, 0x050f80ff,
+ 0x012fa809, 0x0249f001, 0x078100bb, 0x01012000,
+ 0x052e4c00, 0x07c00000, 0x070000eb, 0x0349f000,
+ 0x058180af, 0x05600800, 0x050f80ff, 0x012fa809,
+ 0x0448e001, 0x068100c1, 0x07c00000, 0x0079c101,
+ 0x07ffffff, 0x027a4b01, 0x03800000, 0x05600800,
+ 0x050f80ff, 0x012fa80a, 0x07600c00, 0x050f80ff,
+ 0x012fa821, 0x06780001, 0x07ffff00, 0x037c00ff,
+ 0x05000700, 0x078100dd, 0x06601804, 0x070030ff,
+ 0x050f80ff, 0x012fa809, 0x05002000, 0x050f8003,
+ 0x073fa00a, 0x06000001, 0x040fe001, 0x038600de,
+ 0x04600201, 0x050f80ff, 0x032fa00a, 0x07c00000,
+ 0x050fe02e, 0x008680e3, 0x0102e000, 0x0302f000,
+ 0x038000e7, 0x0760002e, 0x050f80ff, 0x032fa00a,
+ 0x0102e000, 0x07c00000, 0x022c0004, 0x056c041d,
+ 0x078100fc, 0x056c021d, 0x04810113, 0x056c081d,
+ 0x04810125, 0x076c061d, 0x0581013f, 0x0521d000,
+ 0x0202c013, 0x0202a013, 0x02020013, 0x0460021a,
+ 0x050f80ff, 0x053fa80a, 0x07000009, 0x03b600ac,
+ 0x0484801f, 0x0280003d, 0x040fe02a, 0x028600f2,
+ 0x06000013, 0x04001013, 0x0560102b, 0x050f80ff,
+ 0x032fa012, 0x06420029, 0x0660002a, 0x050f80ff,
+ 0x053fa809, 0x06000001, 0x050fe003, 0x00860110,
+ 0x01028003, 0x0660002a, 0x050f80ff, 0x053fa80a,
+ 0x07000009, 0x00800140, 0x00028013, 0x00027013,
+ 0x00800140, 0x040fe02a, 0x028600f1, 0x06420029,
+ 0x0660002a, 0x050f80ff, 0x053fa809, 0x06000001,
+ 0x050fe003, 0x01860122, 0x03026003, 0x0660002a,
+ 0x050f80ff, 0x053fa80a, 0x07000009, 0x00800140,
+ 0x02026013, 0x02025013, 0x00800140, 0x040fe02a,
+ 0x028600f1, 0x06420029, 0x0660002a, 0x050f80ff,
+ 0x053fa809, 0x06000001, 0x050fe003, 0x00860134,
+ 0x01022003, 0x0660002a, 0x050f80ff, 0x053fa80a,
+ 0x07000009, 0x01800136, 0x00022013, 0x00021013,
+ 0x0647f020, 0x007a0120, 0x04000101, 0x04a00285,
+ 0x0400802a, 0x05a004f5, 0x009480f1, 0x0521d005,
+ 0x028000f2, 0x038000fa, 0x0647f020, 0x06486020,
+ 0x06818145, 0x04a00285, 0x028000f1, 0x007a0120,
+ 0x04000101, 0x04a00285, 0x0400802a, 0x05a004f5,
+ 0x028000f1, 0x040fd02a, 0x052e4003, 0x00208010,
+ 0x05a004f5, 0x038000fa, 0x00018098, 0x07480018,
+ 0x06818161, 0x05481018, 0x0781815f, 0x05482018,
+ 0x0681815d, 0x07483018, 0x0681815b, 0x002fb004,
+ 0x00800162, 0x012fb003, 0x00800162, 0x002fb002,
+ 0x00800162, 0x002fb001, 0x00800162, 0x012fb000,
+ 0x0179fe78, 0x070000ff, 0x030190ff, 0x00017086,
+ 0x058b0166, 0x03385000, 0x03020000, 0x07780017,
+ 0x00430407, 0x078181ee, 0x046c0419, 0x048101a2,
+ 0x046c0219, 0x05810172, 0x07219000, 0x00800186,
+ 0x07219000, 0x07483017, 0x0481018c, 0x05482017,
+ 0x05810193, 0x0448b075, 0x06818186, 0x06601476,
+ 0x050f80ff, 0x073fa022, 0x0600003e, 0x06000080,
+ 0x05001081, 0x05002082, 0x06003083, 0x05004084,
+ 0x04601c76, 0x050f80ff, 0x022fa02a, 0x07219000,
+ 0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff,
+ 0x0484801f, 0x0280003d, 0x040fe07f, 0x0086019b,
+ 0x05a001bb, 0x00920186, 0x040fe07f, 0x07a681bb,
+ 0x00800186, 0x0560107b, 0x050f80ff, 0x032fa009,
+ 0x0744f000, 0x0560107b, 0x050f80ff, 0x032fa00a,
+ 0x00800179, 0x052e400c, 0x040080fb, 0x046aa108,
+ 0x06009076, 0x04002075, 0x05a004fc, 0x00800186,
+ 0x06219001, 0x05482017, 0x058101af, 0x058b01a5,
+ 0x060ff086, 0x0349f0ff, 0x07818165, 0x07483017,
+ 0x058101ac, 0x050fd0ff, 0x040fe07f, 0x07a681bb,
+ 0x00800186, 0x05004084, 0x05a00205, 0x00920186,
+ 0x070ff07d, 0x0450047c, 0x056004ff, 0x050f80ff,
+ 0x032fa009, 0x070ff000, 0x00540479, 0x030790ff,
+ 0x01800193, 0x060ff079, 0x0054047a, 0x058201e7,
+ 0x058101e7, 0x070ff07d, 0x0450047c, 0x050f80ff,
+ 0x002fa819, 0x058b01c3, 0x02080001, 0x00081002,
+ 0x01082003, 0x048b01c7, 0x03385000, 0x03010000,
+ 0x02400019, 0x070ff003, 0x04500479, 0x030790ff,
+ 0x0340007e, 0x0642007f, 0x058101e7, 0x070ff07e,
+ 0x050f80ff, 0x032fa009, 0x050fe000, 0x028681e6,
+ 0x070ff07d, 0x056002ff, 0x050f80ff, 0x032fa009,
+ 0x0107d000, 0x018601e8, 0x0560087d, 0x050f80ff,
+ 0x032fa009, 0x0569fe00, 0x0550041b, 0x050f80ff,
+ 0x032fa009, 0x0107e000, 0x070ff07e, 0x018001d2,
+ 0x0307c000, 0x07c00000, 0x052e400c, 0x040080fb,
+ 0x046aa108, 0x06009076, 0x04002075, 0x018004fc,
+ 0x040fd076, 0x050fd017, 0x060ff086, 0x077800ff,
+ 0x07000060, 0x037c00ff, 0x07000060, 0x078181f0,
+ 0x07780078, 0x07ffff00, 0x045a0419, 0x010780ff,
+ 0x06601476, 0x050f80ff, 0x073fa022, 0x0600003e,
+ 0x052e400c, 0x040080fb, 0x066a8108, 0x06009076,
+ 0x04002075, 0x05a004fc, 0x02800029, 0x0240007f,
+ 0x0742007e, 0x050f807e, 0x032fa009, 0x050fe000,
+ 0x0286821f, 0x070ff07d, 0x055c047b, 0x05810214,
+ 0x0760007d, 0x050f80ff, 0x032fa009, 0x050fe000,
+ 0x03868214, 0x070ff07b, 0x0107d0ff, 0x0560087d,
+ 0x050f80ff, 0x032fa009, 0x03681e00, 0x0450041c,
+ 0x0107e0ff, 0x050f80ff, 0x032fa009, 0x050fe000,
+ 0x01860221, 0x0307c000, 0x07c00000, 0x040fd076,
+ 0x02800510, 0x010180c0, 0x0548e018, 0x0781823c,
+ 0x0748f018, 0x06818238, 0x03490018, 0x06818234,
+ 0x01491018, 0x07818230, 0x073c0000, 0x06000040,
+ 0x02200004, 0x0180023f, 0x073c0000, 0x06000020,
+ 0x03200003, 0x0180023f, 0x073c0000, 0x06000010,
+ 0x02200002, 0x0180023f, 0x073c0000, 0x06000008,
+ 0x02200001, 0x0180023f, 0x073c0000, 0x06000004,
+ 0x06000013, 0x050fb000, 0x040fe076, 0x00860258,
+ 0x046c0273, 0x04810268, 0x066c0073, 0x04810249,
+ 0x040fd076, 0x06a00510, 0x03800014, 0x040fd076,
+ 0x0080024c, 0x00452075, 0x00077013, 0x0647f075,
+ 0x06486075, 0x06818252, 0x05a0028b, 0x00800258,
+ 0x007a0175, 0x04000101, 0x05a0028b, 0x04008076,
+ 0x0245f008, 0x05a004f5, 0x07273000, 0x05600272,
+ 0x050f80ff, 0x053fa80a, 0x07000009, 0x0379ff78,
+ 0x070000ff, 0x02076013, 0x02075013, 0x0484801f,
+ 0x0280003d, 0x070fc0ff, 0x052e400c, 0x00208020,
+ 0x05a004f5, 0x00800261, 0x04600276, 0x050010ff,
+ 0x040f8001, 0x032fa009, 0x040f8001, 0x053fa80a,
+ 0x07000009, 0x070ff000, 0x0286827a, 0x06601276,
+ 0x050f80ff, 0x073fa009, 0x0700000c, 0x07601818,
+ 0x050f80ff, 0x053fa80a, 0x07000009, 0x0180027b,
+ 0x07a000de, 0x0448b075, 0x0581024b, 0x06000013,
+ 0x04001013, 0x0560107b, 0x050f80ff, 0x032fa012,
+ 0x0046b075, 0x03b600ac, 0x0080024c, 0x06000020,
+ 0x04001016, 0x0460082a, 0x050f80ff, 0x032fa012,
+ 0x07c00000, 0x06000075, 0x040010a2, 0x044b0801,
+ 0x060ff016, 0x065a0001, 0x04600876, 0x050f80ff,
+ 0x032fa012, 0x07c00000, 0x050fe022, 0x0186029a,
+ 0x0421d004, 0x0302a022, 0x04a002c1, 0x018002b1,
+ 0x040fe026, 0x008602b3, 0x0421d001, 0x0202a026,
+ 0x04a002c1, 0x0202c013, 0x00683e20, 0x070060ff,
+ 0x056c0206, 0x048102f4, 0x056c0406, 0x0781030a,
+ 0x076c0606, 0x06810379, 0x056c1606, 0x078182b1,
+ 0x04488020, 0x07810387, 0x040fd02a, 0x0521d000,
+ 0x0202a013, 0x02020013, 0x008002b3, 0x04a004ec,
+ 0x008002bf, 0x050fe028, 0x008602bf, 0x0302a028,
+ 0x0421d002, 0x04a002c1, 0x008002c8, 0x050fe022,
+ 0x008602bf, 0x0421d004, 0x0302a022, 0x04a002c1,
+ 0x04a004ec, 0x05848030, 0x0280003d, 0x0460082a,
+ 0x050f80ff, 0x022fa031, 0x03020000, 0x0002b004,
+ 0x01018005, 0x07c00000, 0x0400702a, 0x06a003ba,
+ 0x007a0101, 0x07060000, 0x07303000, 0x07008290,
+ 0x07600018, 0x050f80ff, 0x053fa809, 0x07000003,
+ 0x0448e007, 0x068182d6, 0x06006013, 0x018002dd,
+ 0x02400010, 0x048102d6, 0x06006010, 0x0460322a,
+ 0x050f80ff, 0x073fa00a, 0x07000003, 0x050f801e,
+ 0x032fa03a, 0x063aa020, 0x06000002, 0x013e4000,
+ 0x07000030, 0x009802e3, 0x070ff0f6, 0x036830ff,
+ 0x078182e4, 0x070f001e, 0x0560102b, 0x050f10ff,
+ 0x063f3c08, 0x0600000d, 0x013e4000, 0x06000020,
+ 0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012,
+ 0x0202c013, 0x008002bf, 0x04007013, 0x06a003ba,
+ 0x007a0101, 0x07050000, 0x07303000, 0x07008890,
+ 0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a,
+ 0x05601a2b, 0x050f80ff, 0x022fa019, 0x04001002,
+ 0x04002013, 0x040f801f, 0x022fa01a, 0x073aa00c,
+ 0x06000002, 0x07300c03, 0x0600000d, 0x028003a7,
+ 0x04007013, 0x06a003ba, 0x007a0101, 0x03070000,
+ 0x0660282a, 0x050f80ff, 0x073fa009, 0x06000004,
+ 0x02499008, 0x07810317, 0x07303000, 0x07008890,
+ 0x02800319, 0x07303000, 0x04008980, 0x05007003,
+ 0x074d0005, 0x06006013, 0x050f801e, 0x032fa03a,
+ 0x0760142b, 0x050f80ff, 0x032fa021, 0x064b0002,
+ 0x02499008, 0x06810325, 0x0644c002, 0x054b0400,
+ 0x050040ff, 0x06698104, 0x0581833a, 0x06000013,
+ 0x04001013, 0x04780102, 0x06000010, 0x06003013,
+ 0x04004013, 0x06005013, 0x06006013, 0x04007013,
+ 0x00644015, 0x07820336, 0x04448002, 0x02205008,
+ 0x040f801f, 0x032fa042, 0x04008015, 0x03800371,
+ 0x046c8004, 0x05818348, 0x01208018, 0x06780002,
+ 0x07000003, 0x0581834b, 0x06003001, 0x06000013,
+ 0x04001013, 0x04004013, 0x06005013, 0x040f801f,
+ 0x022fa032, 0x03800371, 0x040fd02a, 0x06a00510,
+ 0x03800014, 0x04488002, 0x07810350, 0x070ff003,
+ 0x04500408, 0x050080ff, 0x06489002, 0x06810357,
+ 0x0379ff00, 0x070000ff, 0x070ff000, 0x04500408,
+ 0x050080ff, 0x07005003, 0x05004000, 0x06003001,
+ 0x06000013, 0x04001013, 0x040f801f, 0x022fa032,
+ 0x05601c2b, 0x050f80ff, 0x022fa031, 0x06600c1f,
+ 0x050f80ff, 0x022fa032, 0x02680608, 0x07810371,
+ 0x016408ff, 0x057dfeff, 0x07ffffff, 0x034000ff,
+ 0x045a0407, 0x070000ff, 0x0760061e, 0x050f80ff,
+ 0x032fa00a, 0x06600908, 0x0669f908, 0x027a0008,
+ 0x06000020, 0x070aa0ff, 0x014a20ff, 0x037a00ff,
+ 0x060000dc, 0x070000ff, 0x028003a7, 0x04007013,
+ 0x06a003ba, 0x007a0101, 0x07030000, 0x07303000,
+ 0x07008190, 0x06006013, 0x050f801e, 0x032fa03a,
+ 0x073aa000, 0x06000002, 0x07300c00, 0x07000005,
+ 0x028003a7, 0x04007013, 0x06a003ba, 0x007a0101,
+ 0x07810000, 0x07303000, 0x07000090, 0x06006013,
+ 0x06600c2a, 0x050f80ff, 0x053fa809, 0x07000003,
+ 0x04780107, 0x07ffff00, 0x007c0107, 0x07000500,
+ 0x0581839a, 0x07303000, 0x05000890, 0x074d0005,
+ 0x0660282a, 0x050f80ff, 0x053fa809, 0x07000003,
+ 0x0049d007, 0x068103a1, 0x02206001, 0x050f801e,
+ 0x032fa03a, 0x073aa000, 0x06000002, 0x07300c00,
+ 0x07000005, 0x013e4000, 0x07000030, 0x039803a9,
+ 0x070ff0f6, 0x036830ff, 0x058183aa, 0x070f001e,
+ 0x040f101f, 0x070f3000, 0x013e4000, 0x06000020,
+ 0x040f801a, 0x0320000a, 0x022017d0, 0x032fa012,
+ 0x008002bf, 0x03200000, 0x06006076, 0x028003bc,
+ 0x03200011, 0x0600602a, 0x05a00441, 0x05600406,
+ 0x050f80ff, 0x053fa809, 0x06000002, 0x07c00000,
+ 0x0207602f, 0x04600876, 0x050f80ff, 0x022fa031,
+ 0x03075000, 0x0007b004, 0x01018005, 0x06600076,
+ 0x050020ff, 0x050f80ff, 0x012fa809, 0x0202f001,
+ 0x008683d0, 0x0002e013, 0x040f8002, 0x053fa80a,
+ 0x07000009, 0x06273001, 0x0448b075, 0x048183da,
+ 0x04602076, 0x050f80ff, 0x053fa811, 0x0700003c,
+ 0x0179fe78, 0x070000ff, 0x030190ff, 0x018683e2,
+ 0x07a003f6, 0x00078019, 0x039203f5, 0x0180043a,
+ 0x040fd076, 0x040fd019, 0x04600276, 0x050020ff,
+ 0x050f80ff, 0x032fa009, 0x040f8002, 0x053fa80a,
+ 0x07000009, 0x050fe000, 0x008683f2, 0x07601818,
+ 0x050f80ff, 0x053fa80a, 0x07000009, 0x038003f3,
+ 0x07a000de, 0x07273000, 0x02076013, 0x0280003d,
+ 0x078b03f6, 0x03385000, 0x07030000, 0x05600818,
+ 0x050f80ff, 0x032fa009, 0x054b0400, 0x0308a0ff,
+ 0x0179fe00, 0x070000ff, 0x010880ff, 0x0448b075,
+ 0x04810410, 0x0760147b, 0x050f80ff, 0x002fa819,
+ 0x064b0001, 0x02080002, 0x01081003, 0x00082001,
+ 0x02083001, 0x02079001, 0x0207a001, 0x00084013,
+ 0x0207f013, 0x00800432, 0x06485075, 0x05810428,
+ 0x02465075, 0x06601476, 0x050f80ff, 0x073fa021,
+ 0x0600003e, 0x070ff07d, 0x0450047c, 0x050f80ff,
+ 0x002fa819, 0x058b041b, 0x02080001, 0x00081002,
+ 0x01082003, 0x03079003, 0x0208307a, 0x0340007e,
+ 0x0642007f, 0x0581042d, 0x070ff07e, 0x05a001d2,
+ 0x0392842d, 0x01800439, 0x058b0428, 0x06601476,
+ 0x050f80ff, 0x073fa041, 0x0600003e, 0x06602476,
+ 0x050f80ff, 0x073fa009, 0x06000007, 0x0008400e,
+ 0x048b0432, 0x03385000, 0x03010000, 0x06219001,
+ 0x040fe07f, 0x01860439, 0x018001bb, 0x07c00000,
+ 0x00683e75, 0x0581043f, 0x0448d075, 0x05810465,
+ 0x01800493, 0x05a004f0, 0x038003f5, 0x0297844c,
+ 0x07602418, 0x050f80ff, 0x012fa809, 0x06780001,
+ 0x070000ff, 0x075a0000, 0x070ff014, 0x0569feff,
+ 0x054b08ff, 0x075a0000, 0x05600418, 0x050f80ff,
+ 0x012fa809, 0x040fe007, 0x03868453, 0x01204000,
+ 0x00800461, 0x00700101, 0x03010000, 0x06780001,
+ 0x07ff0000, 0x076c00ff, 0x0681845b, 0x00700101,
+ 0x03010000, 0x05600418, 0x050f80ff, 0x012fa80a,
+ 0x06780001, 0x07ff0000, 0x050040ff, 0x0279ff01,
+ 0x0700ffff, 0x05002014, 0x07c00000, 0x04007076,
+ 0x0448b075, 0x0481047f, 0x03200011, 0x06006076,
+ 0x06a003bc, 0x007a0101, 0x07060000, 0x07303000,
+ 0x07008290, 0x07600018, 0x050f80ff, 0x053fa809,
+ 0x07000003, 0x0448e007, 0x07818477, 0x06006013,
+ 0x0180048e, 0x02400010, 0x05810477, 0x06006010,
+ 0x04603276, 0x050f80ff, 0x073fa00a, 0x07000003,
+ 0x0180048e, 0x04602a76, 0x050f80ff, 0x032fa009,
+ 0x060ff07a, 0x05500400, 0x070000ff, 0x04602a76,
+ 0x050f80ff, 0x032fa00a, 0x07a003b7, 0x007a0101,
+ 0x03010000, 0x06303008, 0x05008000, 0x0600600e,
+ 0x050f8074, 0x032fa03a, 0x053079a0, 0x0700000c,
+ 0x008004d3, 0x00683e75, 0x076c0aff, 0x058104b2,
+ 0x04007013, 0x03200011, 0x06006076, 0x06a003bc,
+ 0x007a0101, 0x03070000, 0x06602876, 0x050f80ff,
+ 0x053fa809, 0x06000001, 0x03499003, 0x048104a7,
+ 0x07303000, 0x07008890, 0x053079a0, 0x0700000c,
+ 0x008004ab, 0x07303000, 0x04008980, 0x04307920,
+ 0x0700000c, 0x074d0005, 0x06006013, 0x050f8074,
+ 0x032fa03a, 0x04307920, 0x0700000c, 0x008004d3,
+ 0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a,
+ 0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff,
+ 0x032fa00a, 0x04007076, 0x07a003b7, 0x007a0101,
+ 0x03010000, 0x06303008, 0x07008800, 0x074d0005,
+ 0x06600a76, 0x050f80ff, 0x073fa009, 0x07000003,
+ 0x054b0406, 0x045a0404, 0x050040ff, 0x0600600e,
+ 0x050f8074, 0x032fa03a, 0x0648c075, 0x058104d1,
+ 0x06307d20, 0x0700000c, 0x008004d3, 0x04307920,
+ 0x0700000c, 0x013e4000, 0x07000030, 0x009804d5,
+ 0x070ff0f6, 0x074850ff, 0x068184d6, 0x050f2074,
+ 0x060a0007, 0x040070fb, 0x046a7007, 0x050f40ff,
+ 0x013e4000, 0x06000020, 0x0678007a, 0x07fff000,
+ 0x068184e6, 0x0320000a, 0x022017d0, 0x008004e9,
+ 0x0320000a, 0x06301b58, 0x06000001, 0x050f8072,
+ 0x032fa012, 0x038003f5, 0x01208060, 0x0600902a,
+ 0x04002020, 0x018004fc, 0x040080fb, 0x066ae108,
+ 0x06009076, 0x04002075, 0x018004fc, 0x03201100,
+ 0x078484fa, 0x06420001, 0x078184f6, 0x02800513,
+ 0x020e0008, 0x07c00000, 0x050fd009, 0x040fd008,
+ 0x03201100, 0x05848503, 0x06420001, 0x078184ff,
+ 0x02800513, 0x007a0102, 0x04000101, 0x05600809,
+ 0x050f80ff, 0x073fa00a, 0x06000001, 0x020e0008,
+ 0x0684050d, 0x030e0009, 0x07c00000, 0x01011009,
+ 0x052e4300, 0x07c00000, 0x052e400f, 0x01208090,
+ 0x018004f5, 0x070fc0ff, 0x040f8013, 0x032fa009,
+ 0x02800516, 0x15416ea9, 0xffef0b01
+};
+
+#ifdef UNIQUE_FW_NAME
+uint32_t fw2400_length02 = 0x000014ff ;
+#else
+uint32_t risc_code_length02 = 0x000014ff ;
+#endif
+
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 48e460eef05a..b17ee62dd1a9 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -232,7 +232,7 @@ 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);
+ return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device);
}
static ssize_t
@@ -541,7 +541,7 @@ struct fc_function_template qla2xxx_transport_functions = {
void
qla2x00_init_host_attr(scsi_qla_host_t *ha)
{
- 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_node_name(ha->host) = wwn_to_u64(ha->node_name);
+ fc_host_port_name(ha->host) = wwn_to_u64(ha->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 5c5d2315cfab..2d9b12ffe09c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1003,10 +1003,10 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
fw = (struct qla24xx_fw_dump *) ha->fw_dump24;
rval = QLA_SUCCESS;
- fw->hccr = RD_REG_DWORD(&reg->hccr);
+ fw->host_status = RD_REG_DWORD(&reg->host_status);
/* Pause RISC. */
- if ((fw->hccr & HCCRX_RISC_PAUSE) == 0) {
+ if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
HCCRX_CLR_HOST_INT);
RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
@@ -1021,16 +1021,54 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
}
}
- /* Disable interrupts. */
- WRT_REG_DWORD(&reg->ictrl, 0);
- RD_REG_DWORD(&reg->ictrl);
-
if (rval == QLA_SUCCESS) {
/* Host interface registers. */
dmp_reg = (uint32_t __iomem *)(reg + 0);
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
fw->host_reg[cnt] = RD_REG_DWORD(dmp_reg++);
+ /* Disable interrupts. */
+ WRT_REG_DWORD(&reg->ictrl, 0);
+ RD_REG_DWORD(&reg->ictrl);
+
+ /* Shadow registers. */
+ WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+ RD_REG_DWORD(&reg->iobase_addr);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0000000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0100000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0200000);
+ 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);
+ WRT_REG_DWORD(dmp_reg, 0xB0300000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0400000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0500000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
+
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
+ WRT_REG_DWORD(dmp_reg, 0xB0600000);
+ dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
+ fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
+
/* Mailbox registers. */
mbx_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80);
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
@@ -1308,43 +1346,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
for (cnt = 0; cnt < 16; cnt++)
*iter_reg++ = RD_REG_DWORD(dmp_reg++);
- WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
- RD_REG_DWORD(&reg->iobase_addr);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0000000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[0] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0100000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[1] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0200000);
- 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);
- WRT_REG_DWORD(dmp_reg, 0xB0300000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[3] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0400000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[4] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0500000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[5] = RD_REG_DWORD(dmp_reg);
-
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0);
- WRT_REG_DWORD(dmp_reg, 0xB0600000);
- dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC);
- fw->shadow_reg[6] = RD_REG_DWORD(dmp_reg);
-
/* Local memory controller registers. */
iter_reg = fw->lmc_reg;
WRT_REG_DWORD(&reg->iobase_addr, 0x3000);
@@ -1677,7 +1678,7 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version, ha->fw_attributes);
- qla_uprintf(&uiter, "\nHCCR Register\n%04x\n", fw->hccr);
+ qla_uprintf(&uiter, "\nR2H Status Register\n%04x\n", fw->host_status);
qla_uprintf(&uiter, "\nHost Interface Registers");
for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) {
@@ -1687,6 +1688,14 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
qla_uprintf(&uiter, "%08x ", fw->host_reg[cnt]);
}
+ qla_uprintf(&uiter, "\n\nShadow Registers");
+ for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
+ if (cnt % 8 == 0)
+ qla_uprintf(&uiter, "\n");
+
+ qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
+ }
+
qla_uprintf(&uiter, "\n\nMailbox Registers");
for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) {
if (cnt % 8 == 0)
@@ -1855,14 +1864,6 @@ qla24xx_ascii_fw_dump(scsi_qla_host_t *ha)
qla_uprintf(&uiter, "%08x ", fw->risc_gp_reg[cnt]);
}
- qla_uprintf(&uiter, "\n\nShadow Registers");
- for (cnt = 0; cnt < sizeof(fw->shadow_reg) / 4; cnt++) {
- if (cnt % 8 == 0)
- qla_uprintf(&uiter, "\n");
-
- qla_uprintf(&uiter, "%08x ", fw->shadow_reg[cnt]);
- }
-
qla_uprintf(&uiter, "\n\nLMC Registers");
for (cnt = 0; cnt < sizeof(fw->lmc_reg) / 4; cnt++) {
if (cnt % 8 == 0)
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 935a59a8c054..ab6afeaa2f2c 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -227,8 +227,9 @@ struct qla2100_fw_dump {
#define FW_DUMP_SIZE_24XX 0x2B0000
struct qla24xx_fw_dump {
- uint32_t hccr;
+ uint32_t host_status;
uint32_t host_reg[32];
+ uint32_t shadow_reg[7];
uint16_t mailbox_reg[32];
uint32_t xseq_gp_reg[128];
uint32_t xseq_0_reg[16];
@@ -250,7 +251,6 @@ struct qla24xx_fw_dump {
uint32_t rcvt0_data_dma_reg[32];
uint32_t rcvt1_data_dma_reg[32];
uint32_t risc_gp_reg[128];
- uint32_t shadow_reg[7];
uint32_t lmc_reg[112];
uint32_t fpm_hdw_reg[192];
uint32_t fb_hdw_reg[176];
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7b3efd531297..79d8a914f9d0 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -22,6 +22,7 @@
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
+#include <linux/firmware.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
@@ -29,6 +30,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
#if defined(CONFIG_SCSI_QLA21XX) || defined(CONFIG_SCSI_QLA21XX_MODULE)
#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
#else
@@ -79,9 +81,23 @@
#define IS_QLA2522(ha) 0
#endif
+#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
+#define IS_QLA2100(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2100)
+#define IS_QLA2200(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2200)
+#define IS_QLA2300(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2300)
+#define IS_QLA2312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2312)
+#define IS_QLA2322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322)
+#define IS_QLA6312(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312)
+#define IS_QLA6322(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6322)
+#define IS_QLA2422(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422)
+#define IS_QLA2432(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+#define IS_QLA2512(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2512)
+#define IS_QLA2522(ha) ((ha)->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2522)
+#endif
+
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
-
#define IS_QLA24XX(ha) (IS_QLA2422(ha) || IS_QLA2432(ha))
#define IS_QLA25XX(ha) (IS_QLA2512(ha) || IS_QLA2522(ha))
@@ -2124,6 +2140,12 @@ struct qla_board_info {
struct scsi_host_template *sht;
};
+struct fw_blob {
+ char *name;
+ uint32_t segs[4];
+ const struct firmware *fw;
+};
+
/* Return data from MBC_GET_ID_LIST call. */
struct gid_list_info {
uint8_t al_pa;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index fedcb0d3fc72..32be4c14cccb 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -33,8 +33,8 @@ extern int qla24xx_nvram_config(struct scsi_qla_host *);
extern void qla2x00_update_fw_options(struct scsi_qla_host *);
extern void qla24xx_update_fw_options(scsi_qla_host_t *);
extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
+extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla24xx_load_risc_flash(scsi_qla_host_t *, uint32_t *);
-extern int qla24xx_load_risc_hotplug(scsi_qla_host_t *, uint32_t *);
extern fc_port_t *qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t);
@@ -62,6 +62,7 @@ extern int qlport_down_retry;
extern int ql2xplogiabsentdevice;
extern int ql2xloginretrycount;
extern int ql2xfdmienable;
+extern int ql2xprocessrscn;
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
@@ -76,6 +77,8 @@ extern void qla2x00_blink_led(scsi_qla_host_t *);
extern int qla2x00_down_timeout(struct semaphore *, unsigned long);
+extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
+
/*
* Global Function Prototypes in qla_iocb.c source file.
*/
@@ -94,10 +97,7 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t);
* Global Function Prototypes in qla_mbx.c source file.
*/
extern int
-qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t);
-
-extern int
-qla2x00_load_ram_ext(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
+qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t);
extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index cd6f7c3cfe68..d620a8e8a614 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -538,6 +538,7 @@ qla2x00_rff_id(scsi_qla_host_t *ha)
ct_req->req.rff_id.port_id[1] = ha->d_id.b.area;
ct_req->req.rff_id.port_id[2] = ha->d_id.b.al_pa;
+ ct_req->req.rff_id.fc4_feature = BIT_1;
ct_req->req.rff_id.fc4_type = 0x08; /* SCSI - FCP */
/* Execute MS IOCB */
@@ -1529,9 +1530,9 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
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_QLA24XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(4);
else if (IS_QLA23XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(2);
else
@@ -1553,9 +1554,6 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha)
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;
}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index c46d2469b85f..a91fea69ad63 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/vmalloc.h>
-#include <linux/firmware.h>
#include <scsi/scsi_transport_fc.h>
#include "qla_devtbl.h"
@@ -1015,11 +1014,13 @@ qla24xx_update_fw_options(scsi_qla_host_t *ha)
int rval;
/* Update Serial Link options. */
- if ((ha->fw_seriallink_options24[0] & BIT_0) == 0)
+ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0)
return;
- rval = qla2x00_set_serdes_params(ha, ha->fw_seriallink_options24[1],
- ha->fw_seriallink_options24[2], ha->fw_seriallink_options24[3]);
+ rval = qla2x00_set_serdes_params(ha,
+ le16_to_cpu(ha->fw_seriallink_options24[1]),
+ le16_to_cpu(ha->fw_seriallink_options24[2]),
+ le16_to_cpu(ha->fw_seriallink_options24[3]));
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to update Serial Link options (%x).\n", rval);
@@ -1940,6 +1941,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
"information -- get_port_database=%x, "
"loop_id=0x%04x\n",
ha->host_no, rval2, new_fcport->loop_id));
+ DEBUG2(printk("scsi(%ld): Scheduling resync...\n",
+ ha->host_no));
+ set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
continue;
}
@@ -2649,7 +2653,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
switch (format) {
case 0:
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
!IS_QLA6312(ha) && !IS_QLA6322(ha) &&
!IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done) {
@@ -3403,6 +3408,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
ha->node_name = icb->node_name;
ha->port_name = icb->port_name;
+ icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+
ha->retry_count = le16_to_cpu(nv->login_retry_count);
/* Set minimum login_timeout to 4 seconds. */
@@ -3484,17 +3491,16 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
return (rval);
}
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
int
qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
- int rval;
- uint16_t cnt;
- uint16_t *risc_code;
- unsigned long risc_address;
- unsigned long risc_code_size;
- int num;
- int i;
- uint16_t *req_ring;
+ int rval, num, i;
+ uint32_t cnt;
+ uint16_t *risc_code;
+ uint32_t risc_addr, risc_size;
+ uint16_t *req_ring;
struct qla_fw_info *fw_iter;
rval = QLA_SUCCESS;
@@ -3504,37 +3510,29 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
*srisc_addr = *ha->brd_info->fw_info->fwstart;
while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
risc_code = fw_iter->fwcode;
- risc_code_size = *fw_iter->fwlen;
-
- if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
- risc_address = *fw_iter->fwstart;
- } else {
- /* Extended address */
- risc_address = *fw_iter->lfwstart;
- }
+ risc_size = *fw_iter->fwlen;
+ if (fw_iter->addressing == FW_INFO_ADDR_NORMAL)
+ risc_addr = *fw_iter->fwstart;
+ else
+ risc_addr = *fw_iter->lfwstart;
num = 0;
rval = 0;
- while (risc_code_size > 0 && !rval) {
+ while (risc_size > 0 && !rval) {
cnt = (uint16_t)(ha->fw_transfer_size >> 1);
- if (cnt > risc_code_size)
- cnt = risc_code_size;
+ if (cnt > risc_size)
+ cnt = risc_size;
DEBUG7(printk("scsi(%ld): Loading risc segment@ "
"addr %p, number of bytes 0x%x, offset 0x%lx.\n",
- ha->host_no, risc_code, cnt, risc_address));
+ ha->host_no, risc_code, cnt, risc_addr));
req_ring = (uint16_t *)ha->request_ring;
for (i = 0; i < cnt; i++)
req_ring[i] = cpu_to_le16(risc_code[i]);
- if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) {
- rval = qla2x00_load_ram(ha, ha->request_dma,
- risc_address, cnt);
- } else {
- rval = qla2x00_load_ram_ext(ha,
- ha->request_dma, risc_address, cnt);
- }
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ cnt);
if (rval) {
DEBUG(printk("scsi(%ld): [ERROR] Failed to "
"load segment %d of firmware\n",
@@ -3548,16 +3546,76 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
}
risc_code += cnt;
- risc_address += cnt;
- risc_code_size -= cnt;
+ risc_addr += cnt;
+ risc_size -= cnt;
num++;
}
/* Next firmware sequence */
fw_iter++;
}
+ return rval;
+}
- return (rval);
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+ int rval, num, i;
+ uint32_t cnt;
+ uint32_t *risc_code;
+ uint32_t risc_addr, risc_size;
+ uint32_t *req_ring;
+ struct qla_fw_info *fw_iter;
+
+ rval = QLA_SUCCESS;
+
+ /* Load firmware sequences */
+ fw_iter = ha->brd_info->fw_info;
+ *srisc_addr = *((uint32_t *)fw_iter->lfwstart);
+ while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
+ risc_code = (uint32_t *)fw_iter->fwcode;
+ risc_size = *((uint32_t *)fw_iter->fwlen);
+ risc_addr = *((uint32_t *)fw_iter->lfwstart);
+
+ num = 0;
+ rval = 0;
+ while (risc_size > 0 && !rval) {
+ cnt = (uint32_t)(ha->fw_transfer_size >> 2);
+ if (cnt > risc_size)
+ cnt = risc_size;
+
+ DEBUG7(printk("scsi(%ld): Loading risc segment@ "
+ "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
+ ha->host_no, risc_code, cnt, risc_addr));
+
+ req_ring = (uint32_t *)ha->request_ring;
+ for (i = 0; i < cnt; i++)
+ req_ring[i] = cpu_to_le32(risc_code[i]);
+
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ cnt);
+ if (rval) {
+ DEBUG(printk("scsi(%ld): [ERROR] Failed to "
+ "load segment %d of firmware\n",
+ ha->host_no, num));
+ qla_printk(KERN_WARNING, ha,
+ "[ERROR] Failed to load segment %d of "
+ "firmware\n", num);
+
+ qla2x00_dump_regs(ha);
+ break;
+ }
+
+ risc_code += cnt;
+ risc_addr += cnt;
+ risc_size -= cnt;
+ num++;
+ }
+
+ /* Next firmware sequence */
+ fw_iter++;
+ }
+ return rval;
}
int
@@ -3617,8 +3675,8 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
@@ -3642,8 +3700,108 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
return rval;
}
+#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
+int
+qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+ int rval;
+ int i, fragment;
+ uint16_t *wcode, *fwcode;
+ uint32_t risc_addr, risc_size, fwclen, wlen, *seg;
+ struct fw_blob *blob;
+
+ /* Load firmware blob. */
+ blob = qla2x00_request_firmware(ha);
+ if (!blob) {
+ qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+ rval = QLA_SUCCESS;
+
+ wcode = (uint16_t *)ha->request_ring;
+ *srisc_addr = 0;
+ fwcode = (uint16_t *)blob->fw->data;
+ fwclen = 0;
+
+ /* Validate firmware image by checking version. */
+ if (blob->fw->size < 8 * sizeof(uint16_t)) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image (%Zd)!\n",
+ blob->fw->size);
+ goto fail_fw_integrity;
+ }
+ for (i = 0; i < 4; i++)
+ wcode[i] = be16_to_cpu(fwcode[i + 4]);
+ if ((wcode[0] == 0xffff && wcode[1] == 0xffff && wcode[2] == 0xffff &&
+ wcode[3] == 0xffff) || (wcode[0] == 0 && wcode[1] == 0 &&
+ wcode[2] == 0 && wcode[3] == 0)) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image!\n");
+ qla_printk(KERN_WARNING, ha,
+ "Firmware data: %04x %04x %04x %04x!\n", wcode[0],
+ wcode[1], wcode[2], wcode[3]);
+ goto fail_fw_integrity;
+ }
+
+ seg = blob->segs;
+ while (*seg && rval == QLA_SUCCESS) {
+ risc_addr = *seg;
+ *srisc_addr = *srisc_addr == 0 ? *seg : *srisc_addr;
+ risc_size = be16_to_cpu(fwcode[3]);
+
+ /* Validate firmware image size. */
+ fwclen += risc_size * sizeof(uint16_t);
+ if (blob->fw->size < fwclen) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to verify integrity of firmware image "
+ "(%Zd)!\n", blob->fw->size);
+ goto fail_fw_integrity;
+ }
+
+ fragment = 0;
+ while (risc_size > 0 && rval == QLA_SUCCESS) {
+ wlen = (uint16_t)(ha->fw_transfer_size >> 1);
+ if (wlen > risc_size)
+ wlen = risc_size;
+
+ DEBUG7(printk("scsi(%ld): Loading risc segment@ risc "
+ "addr %x, number of words 0x%x.\n", ha->host_no,
+ risc_addr, wlen));
+
+ for (i = 0; i < wlen; i++)
+ wcode[i] = swab16(fwcode[i]);
+
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ wlen);
+ if (rval) {
+ DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
+ "segment %d of firmware\n", ha->host_no,
+ fragment));
+ qla_printk(KERN_WARNING, ha,
+ "[ERROR] Failed to load segment %d of "
+ "firmware\n", fragment);
+ break;
+ }
+
+ fwcode += wlen;
+ risc_addr += wlen;
+ risc_size -= wlen;
+ fragment++;
+ }
+
+ /* Next segment. */
+ seg++;
+ }
+ return rval;
+
+fail_fw_integrity:
+ return QLA_FUNCTION_FAILED;
+}
+
int
-qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
{
int rval;
int segments, fragment;
@@ -3651,14 +3809,13 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
uint32_t risc_addr;
uint32_t risc_size;
uint32_t i;
- const struct firmware *fw_entry;
+ struct fw_blob *blob;
uint32_t *fwcode, fwclen;
- if (request_firmware(&fw_entry, ha->brd_info->fw_fname,
- &ha->pdev->dev)) {
- qla_printk(KERN_ERR, ha,
- "Firmware image file not available: '%s'\n",
- ha->brd_info->fw_fname);
+ /* Load firmware blob. */
+ blob = qla2x00_request_firmware(ha);
+ if (!blob) {
+ qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
return QLA_FUNCTION_FAILED;
}
@@ -3667,14 +3824,14 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
segments = FA_RISC_CODE_SEGMENTS;
dcode = (uint32_t *)ha->request_ring;
*srisc_addr = 0;
- fwcode = (uint32_t *)fw_entry->data;
+ fwcode = (uint32_t *)blob->fw->data;
fwclen = 0;
/* Validate firmware image by checking version. */
- if (fw_entry->size < 8 * sizeof(uint32_t)) {
+ if (blob->fw->size < 8 * sizeof(uint32_t)) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware image "
- "(%Zd)!\n", fw_entry->size);
+ "Unable to verify integrity of firmware image (%Zd)!\n",
+ blob->fw->size);
goto fail_fw_integrity;
}
for (i = 0; i < 4; i++)
@@ -3684,7 +3841,7 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
(dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
dcode[3] == 0)) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware image!\n");
+ "Unable to verify integrity of firmware image!\n");
qla_printk(KERN_WARNING, ha,
"Firmware data: %08x %08x %08x %08x!\n", dcode[0],
dcode[1], dcode[2], dcode[3]);
@@ -3698,10 +3855,11 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
/* Validate firmware image size. */
fwclen += risc_size * sizeof(uint32_t);
- if (fw_entry->size < fwclen) {
+ if (blob->fw->size < fwclen) {
qla_printk(KERN_WARNING, ha,
- "Unable to verify integrity of flash firmware "
- "image (%Zd)!\n", fw_entry->size);
+ "Unable to verify integrity of firmware image "
+ "(%Zd)!\n", blob->fw->size);
+
goto fail_fw_integrity;
}
@@ -3718,8 +3876,8 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
for (i = 0; i < dlen; i++)
dcode[i] = swab32(fwcode[i]);
- rval = qla2x00_load_ram_ext(ha, ha->request_dma,
- risc_addr, dlen);
+ rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+ dlen);
if (rval) {
DEBUG(printk("scsi(%ld):[ERROR] Failed to load "
"segment %d of firmware\n", ha->host_no,
@@ -3739,13 +3897,9 @@ qla24xx_load_risc_hotplug(scsi_qla_host_t *ha, uint32_t *srisc_addr)
/* Next segment. */
segments--;
}
-
- release_firmware(fw_entry);
return rval;
fail_fw_integrity:
-
- release_firmware(fw_entry);
return QLA_FUNCTION_FAILED;
-
}
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 5181d966fecb..f63af081d4ff 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -519,7 +519,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
* us, create a new entry in our rscn fcports list and handle
* the event like an RSCN.
*/
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
+ if (ql2xprocessrscn &&
+ !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
!IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA25XX(ha) &&
ha->flags.init_done && mb[1] != 0xffff &&
((ha->operating_mode == P2P && mb[1] != 0) ||
@@ -963,15 +964,16 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
break;
case CS_DATA_UNDERRUN:
- DEBUG2(printk(KERN_INFO
- "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n",
- ha->host_no, cp->device->id, cp->device->lun, comp_status,
- scsi_status));
-
resid = resid_len;
if (scsi_status & SS_RESIDUAL_UNDER) {
cp->resid = resid;
CMD_RESID_LEN(cp) = resid;
+ } else {
+ DEBUG2(printk(KERN_INFO
+ "scsi(%ld:%d:%d) UNDERRUN status detected "
+ "0x%x-0x%x.\n", ha->host_no, cp->device->id,
+ cp->device->lun, comp_status, scsi_status));
+
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9746cd1e664b..3099b379de9d 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -196,7 +196,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
/* Check for pending interrupts. */
qla2x00_poll(ha);
- udelay(10); /* v4.27 */
+ if (command != MBC_LOAD_RISC_RAM_EXTENDED &&
+ !ha->flags.mbox_int)
+ msleep(10);
} /* while */
}
@@ -325,113 +327,30 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
return rval;
}
-/*
- * qla2x00_load_ram
- * Load adapter RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
int
-qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint16_t risc_addr,
- uint16_t risc_code_size)
+qla2x00_load_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t risc_addr,
+ uint32_t risc_code_size)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- uint32_t req_len;
- dma_addr_t nml_dma;
- uint32_t nml_len;
- uint32_t normalized;
-
- DEBUG11(printk("qla2x00_load_ram(%ld): entered.\n",
- ha->host_no);)
- req_len = risc_code_size;
- nml_dma = 0;
- nml_len = 0;
-
- normalized = qla2x00_normalize_dma_addr(&req_dma, &req_len, &nml_dma,
- &nml_len);
-
- /* Load first segment */
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr;
- mcp->mb[2] = MSW(req_dma);
- mcp->mb[3] = LSW(req_dma);
- mcp->mb[4] = (uint16_t)req_len;
- mcp->mb[6] = MSW(MSD(req_dma));
- mcp->mb[7] = LSW(MSD(req_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
-
- /* Load second segment - if necessary */
- if (normalized && (rval == QLA_SUCCESS)) {
- mcp->mb[0] = MBC_LOAD_RISC_RAM;
- mcp->mb[1] = risc_addr + (uint16_t)req_len;
- mcp->mb[2] = MSW(nml_dma);
- mcp->mb[3] = LSW(nml_dma);
- mcp->mb[4] = (uint16_t)nml_len;
- mcp->mb[6] = MSW(MSD(nml_dma));
- mcp->mb[7] = LSW(MSD(nml_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = 30;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(ha, mcp);
- }
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
- if (rval == QLA_SUCCESS) {
- /* Empty */
- DEBUG11(printk("qla2x00_load_ram(%ld): done.\n", ha->host_no);)
+ if (MSW(risc_addr) || IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
+ mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
+ mcp->mb[8] = MSW(risc_addr);
+ mcp->out_mb = MBX_8|MBX_0;
} else {
- /* Empty */
- DEBUG2_3_11(printk("qla2x00_load_ram(%ld): failed. rval=%x "
- "mb[0]=%x.\n", ha->host_no, rval, mcp->mb[0]);)
+ mcp->mb[0] = MBC_LOAD_RISC_RAM;
+ mcp->out_mb = MBX_0;
}
- return rval;
-}
-
-/*
- * qla2x00_load_ram_ext
- * Load adapter extended RAM using DMA.
- *
- * Input:
- * ha = adapter block pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_load_ram_ext(scsi_qla_host_t *ha, dma_addr_t req_dma,
- uint32_t risc_addr, uint32_t risc_code_size)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
-
- DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
-
- mcp->mb[0] = MBC_LOAD_RISC_RAM_EXTENDED;
mcp->mb[1] = LSW(risc_addr);
mcp->mb[2] = MSW(req_dma);
mcp->mb[3] = LSW(req_dma);
mcp->mb[6] = MSW(MSD(req_dma));
mcp->mb[7] = LSW(MSD(req_dma));
- mcp->mb[8] = MSW(risc_addr);
- mcp->out_mb = MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1;
if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
mcp->mb[4] = MSW(risc_code_size);
mcp->mb[5] = LSW(risc_code_size);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c58c9d97b041..4916847d84ec 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -54,10 +54,12 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
-int ql2xfwloadbin=1;
-module_param(ql2xfwloadbin, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xfwloadbin,
- "Load ISP2xxx firmware image via hotplug.");
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+int ql2xfwloadflash;
+module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfwloadflash,
+ "Load ISP24xx firmware image from FLASH (onboard memory).");
+#endif
static void qla2x00_free_device(scsi_qla_host_t *);
@@ -69,6 +71,12 @@ MODULE_PARM_DESC(ql2xfdmienable,
"Enables FDMI registratons "
"Default is 0 - no FDMI. 1 - perfom FDMI.");
+int ql2xprocessrscn;
+module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xprocessrscn,
+ "Option to enable port RSCN handling via a series of less"
+ "fabric intrusive ADISCs and PLOGIs.");
+
/*
* SCSI host template entry points
*/
@@ -1261,12 +1269,16 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
char pci_info[20];
char fw_str[30];
fc_port_t *fcport;
+ struct scsi_host_template *sht;
if (pci_enable_device(pdev))
goto probe_out;
- host = scsi_host_alloc(brd_info->sht ? brd_info->sht:
- &qla2x00_driver_template, sizeof(scsi_qla_host_t));
+ sht = &qla2x00_driver_template;
+ if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432)
+ sht = &qla24xx_driver_template;
+ host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t));
if (host == NULL) {
printk(KERN_WARNING
"qla2xxx: Couldn't allocate host from scsi layer!\n");
@@ -1291,8 +1303,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
goto probe_failed;
qla_printk(KERN_INFO, ha,
- "Found an %s, irq %d, iobase 0x%p\n", ha->brd_info->isp_name,
- pdev->irq, ha->iobase);
+ "Found an ISP%04X, irq %d, iobase 0x%p\n", pdev->device, pdev->irq,
+ ha->iobase);
spin_lock_init(&ha->hardware_lock);
@@ -1368,9 +1380,11 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
ha->isp_ops.reset_adapter = qla24xx_reset_adapter;
ha->isp_ops.nvram_config = qla24xx_nvram_config;
ha->isp_ops.update_fw_options = qla24xx_update_fw_options;
- ha->isp_ops.load_risc = qla24xx_load_risc_flash;
- if (ql2xfwloadbin)
- ha->isp_ops.load_risc = qla24xx_load_risc_hotplug;
+ ha->isp_ops.load_risc = qla24xx_load_risc;
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+ if (ql2xfwloadflash)
+ ha->isp_ops.load_risc = qla24xx_load_risc_flash;
+#endif
ha->isp_ops.pci_info_str = qla24xx_pci_info_str;
ha->isp_ops.fw_version_str = qla24xx_fw_version_str;
ha->isp_ops.intr_handler = qla24xx_intr_handler;
@@ -1531,11 +1545,12 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
qla_printk(KERN_INFO, ha, "\n"
" QLogic Fibre Channel HBA Driver: %s\n"
" QLogic %s - %s\n"
- " %s: %s @ %s hdma%c, host#=%ld, fw=%s\n", qla2x00_version_str,
- ha->model_number, ha->model_desc ? ha->model_desc: "",
- ha->brd_info->isp_name, ha->isp_ops.pci_info_str(ha, pci_info),
- pci_name(pdev), ha->flags.enable_64bit_addressing ? '+': '-',
- ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str));
+ " ISP%04X: %s @ %s hdma%c, host#=%ld, fw=%s\n",
+ qla2x00_version_str, ha->model_number,
+ ha->model_desc ? ha->model_desc: "", pdev->device,
+ ha->isp_ops.pci_info_str(ha, pci_info), pci_name(pdev),
+ ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
+ ha->isp_ops.fw_version_str(ha, fw_str));
/* Go with fc_rport registration. */
list_for_each_entry(fcport, &ha->fcports, list)
@@ -2483,45 +2498,115 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
return -ETIMEDOUT;
}
-static struct qla_board_info qla_board_tbl[] = {
- {
- .drv_name = "qla2400",
- .isp_name = "ISP2422",
- .fw_fname = "ql2400_fw.bin",
- .sht = &qla24xx_driver_template,
- },
- {
- .drv_name = "qla2400",
- .isp_name = "ISP2432",
- .fw_fname = "ql2400_fw.bin",
- .sht = &qla24xx_driver_template,
- },
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+
+#define qla2x00_release_firmware() do { } while (0)
+#define qla2x00_pci_module_init() (0)
+#define qla2x00_pci_module_exit() do { } while (0)
+
+#else /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+
+/* Firmware interface routines. */
+
+#define FW_BLOBS 6
+#define FW_ISP21XX 0
+#define FW_ISP22XX 1
+#define FW_ISP2300 2
+#define FW_ISP2322 3
+#define FW_ISP63XX 4
+#define FW_ISP24XX 5
+
+static DECLARE_MUTEX(qla_fw_lock);
+
+static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
+ { .name = "ql2100_fw.bin", .segs = { 0x1000, 0 }, },
+ { .name = "ql2200_fw.bin", .segs = { 0x1000, 0 }, },
+ { .name = "ql2300_fw.bin", .segs = { 0x800, 0 }, },
+ { .name = "ql2322_fw.bin", .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
+ { .name = "ql6312_fw.bin", .segs = { 0x800, 0 }, },
+ { .name = "ql2400_fw.bin", },
+};
+
+struct fw_blob *
+qla2x00_request_firmware(scsi_qla_host_t *ha)
+{
+ struct fw_blob *blob;
+
+ blob = NULL;
+ if (IS_QLA2100(ha)) {
+ blob = &qla_fw_blobs[FW_ISP21XX];
+ } else if (IS_QLA2200(ha)) {
+ blob = &qla_fw_blobs[FW_ISP22XX];
+ } else if (IS_QLA2300(ha) || IS_QLA2312(ha)) {
+ blob = &qla_fw_blobs[FW_ISP2300];
+ } else if (IS_QLA2322(ha)) {
+ blob = &qla_fw_blobs[FW_ISP2322];
+ } else if (IS_QLA6312(ha) || IS_QLA6322(ha)) {
+ blob = &qla_fw_blobs[FW_ISP63XX];
+ } else if (IS_QLA24XX(ha)) {
+ blob = &qla_fw_blobs[FW_ISP24XX];
+ }
+
+ down(&qla_fw_lock);
+ if (blob->fw)
+ goto out;
+
+ if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
+ DEBUG2(printk("scsi(%ld): Failed to load firmware image "
+ "(%s).\n", ha->host_no, blob->name));
+ blob->fw = NULL;
+ blob = NULL;
+ goto out;
+ }
+
+out:
+ up(&qla_fw_lock);
+ return blob;
+}
+
+static void
+qla2x00_release_firmware(void)
+{
+ int idx;
+
+ down(&qla_fw_lock);
+ for (idx = 0; idx < FW_BLOBS; idx++)
+ if (qla_fw_blobs[idx].fw)
+ release_firmware(qla_fw_blobs[idx].fw);
+ up(&qla_fw_lock);
+}
+
+static struct qla_board_info qla_board_tbl = {
+ .drv_name = "qla2xxx",
};
static struct pci_device_id qla2xxx_pci_tbl[] = {
- {
- .vendor = PCI_VENDOR_ID_QLOGIC,
- .device = PCI_DEVICE_ID_QLOGIC_ISP2422,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = (unsigned long)&qla_board_tbl[0],
- },
- {
- .vendor = PCI_VENDOR_ID_QLOGIC,
- .device = PCI_DEVICE_ID_QLOGIC_ISP2432,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = (unsigned long)&qla_board_tbl[1],
- },
- {0, 0},
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ { 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
static int __devinit
qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- return qla2x00_probe_one(pdev,
- (struct qla_board_info *)id->driver_data);
+ return qla2x00_probe_one(pdev, &qla_board_tbl);
}
static void __devexit
@@ -2532,11 +2617,28 @@ qla2xxx_remove_one(struct pci_dev *pdev)
static struct pci_driver qla2xxx_pci_driver = {
.name = "qla2xxx",
+ .driver = {
+ .owner = THIS_MODULE,
+ },
.id_table = qla2xxx_pci_tbl,
.probe = qla2xxx_probe_one,
.remove = __devexit_p(qla2xxx_remove_one),
};
+static inline int
+qla2x00_pci_module_init(void)
+{
+ return pci_module_init(&qla2xxx_pci_driver);
+}
+
+static inline void
+qla2x00_pci_module_exit(void)
+{
+ pci_unregister_driver(&qla2xxx_pci_driver);
+}
+
+#endif
+
/**
* qla2x00_module_init - Module initialization.
**/
@@ -2556,6 +2658,9 @@ qla2x00_module_init(void)
/* Derive version string. */
strcpy(qla2x00_version_str, QLA2XXX_VERSION);
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+ strcat(qla2x00_version_str, "-fw");
+#endif
#if DEBUG_QLA2100
strcat(qla2x00_version_str, "-debug");
#endif
@@ -2565,7 +2670,7 @@ qla2x00_module_init(void)
return -ENODEV;
printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
- ret = pci_module_init(&qla2xxx_pci_driver);
+ ret = qla2x00_pci_module_init();
if (ret) {
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
@@ -2579,7 +2684,8 @@ qla2x00_module_init(void)
static void __exit
qla2x00_module_exit(void)
{
- pci_unregister_driver(&qla2xxx_pci_driver);
+ qla2x00_pci_module_exit();
+ qla2x00_release_firmware();
kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
}
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index d54d2a99c3d3..f4d755a643e4 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -573,6 +573,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
}
} while (0);
+ /* Enable flash write-protection. */
+ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c);
+
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index f7937f7f9c68..d537192a1edb 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.01.03-k"
+#define QLA2XXX_VERSION "8.01.04-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 1
-#define QLA_DRIVER_PATCH_VER 3
+#define QLA_DRIVER_PATCH_VER 4
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 5b1c12041a4f..50c398aab557 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -115,7 +115,7 @@ static DECLARE_TRANSPORT_CLASS(raid_class,
raid_remove,
NULL);
-static struct {
+static const struct {
enum raid_state value;
char *name;
} raid_states[] = {
@@ -148,9 +148,11 @@ static struct {
{ RAID_LEVEL_LINEAR, "linear" },
{ RAID_LEVEL_0, "raid0" },
{ RAID_LEVEL_1, "raid1" },
+ { RAID_LEVEL_10, "raid10" },
{ RAID_LEVEL_3, "raid3" },
{ RAID_LEVEL_4, "raid4" },
{ RAID_LEVEL_5, "raid5" },
+ { RAID_LEVEL_50, "raid50" },
{ RAID_LEVEL_6, "raid6" },
};
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 9321cdf45680..cd54244058b5 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -374,7 +374,6 @@ static struct scsi_host_template mv_sht = {
.dma_boundary = MV_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations mv5_ops = {
@@ -431,7 +430,7 @@ static const struct ata_port_operations mv6_ops = {
.host_stop = mv_host_stop,
};
-static struct ata_port_info mv_port_info[] = {
+static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
.sht = &mv_sht,
.host_flags = MV_COMMON_FLAGS,
@@ -1243,8 +1242,10 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant,
VPRINTK("port %u IRQ found for qc, "
"ata_status 0x%x\n", port,ata_status);
/* mark qc status appropriately */
- if (!(qc->tf.ctl & ATA_NIEN))
- ata_qc_complete(qc, err_mask);
+ if (!(qc->tf.ctl & ATA_NIEN)) {
+ qc->err_mask |= err_mask;
+ ata_qc_complete(qc);
+ }
}
}
}
@@ -1865,7 +1866,8 @@ static void mv_eng_timeout(struct ata_port *ap)
*/
spin_lock_irqsave(&ap->host_set->lock, flags);
qc->scsidone = scsi_finish_command;
- ata_qc_complete(qc, AC_ERR_OTHER);
+ qc->err_mask |= AC_ERR_OTHER;
+ ata_qc_complete(qc);
spin_unlock_irqrestore(&ap->host_set->lock, flags);
}
}
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 4954896dfdb9..bbbb55eeb73a 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -29,6 +29,12 @@
* NV-specific details such as register offsets, SATA phy location,
* hotplug info, etc.
*
+ * 0.10
+ * - Fixed spurious interrupts issue seen with the Maxtor 6H500F0 500GB
+ * drive. Also made the check_hotplug() callbacks return whether there
+ * was a hotplug interrupt or not. This was not the source of the
+ * spurious interrupts, but is the right thing to do anyway.
+ *
* 0.09
* - Fixed bug introduced by 0.08's MCP51 and MCP55 support.
*
@@ -124,10 +130,10 @@ 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);
static void nv_enable_hotplug(struct ata_probe_ent *probe_ent);
static void nv_disable_hotplug(struct ata_host_set *host_set);
-static void nv_check_hotplug(struct ata_host_set *host_set);
+static int nv_check_hotplug(struct ata_host_set *host_set);
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent);
static void nv_disable_hotplug_ck804(struct ata_host_set *host_set);
-static void nv_check_hotplug_ck804(struct ata_host_set *host_set);
+static int nv_check_hotplug_ck804(struct ata_host_set *host_set);
enum nv_host_type
{
@@ -176,7 +182,7 @@ struct nv_host_desc
enum nv_host_type host_type;
void (*enable_hotplug)(struct ata_probe_ent *probe_ent);
void (*disable_hotplug)(struct ata_host_set *host_set);
- void (*check_hotplug)(struct ata_host_set *host_set);
+ int (*check_hotplug)(struct ata_host_set *host_set);
};
static struct nv_host_desc nv_device_tbl[] = {
@@ -235,7 +241,6 @@ static struct scsi_host_template nv_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations nv_ops = {
@@ -310,12 +315,16 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance,
qc = ata_qc_from_tag(ap, ap->active_tag);
if (qc && (!(qc->tf.ctl & ATA_NIEN)))
handled += ata_host_intr(ap, qc);
+ else
+ // No request pending? Clear interrupt status
+ // anyway, in case there's one pending.
+ ap->ops->check_status(ap);
}
}
if (host->host_desc->check_hotplug)
- host->host_desc->check_hotplug(host_set);
+ handled += host->host_desc->check_hotplug(host_set);
spin_unlock_irqrestore(&host_set->lock, flags);
@@ -498,7 +507,7 @@ static void nv_disable_hotplug(struct ata_host_set *host_set)
outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
}
-static void nv_check_hotplug(struct ata_host_set *host_set)
+static int nv_check_hotplug(struct ata_host_set *host_set)
{
u8 intr_status;
@@ -523,7 +532,11 @@ static void nv_check_hotplug(struct ata_host_set *host_set)
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
+
+ return 1;
}
+
+ return 0;
}
static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent)
@@ -561,7 +574,7 @@ static void nv_disable_hotplug_ck804(struct ata_host_set *host_set)
pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
}
-static void nv_check_hotplug_ck804(struct ata_host_set *host_set)
+static int nv_check_hotplug_ck804(struct ata_host_set *host_set)
{
u8 intr_status;
@@ -586,7 +599,11 @@ static void nv_check_hotplug_ck804(struct ata_host_set *host_set)
if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
printk(KERN_WARNING "nv_sata: "
"Secondary device removed\n");
+
+ return 1;
}
+
+ return 0;
}
static int __init nv_init(void)
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 2691625f9bce..b0b0a69b3563 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -66,6 +66,7 @@ enum {
board_2037x = 0, /* FastTrak S150 TX2plus */
board_20319 = 1, /* FastTrak S150 TX4 */
board_20619 = 2, /* FastTrak TX4000 */
+ board_20771 = 3, /* FastTrak TX2300 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
@@ -114,7 +115,6 @@ static struct scsi_host_template pdc_ata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations pdc_sata_ops = {
@@ -161,7 +161,7 @@ static const struct ata_port_operations pdc_pata_ops = {
.host_stop = ata_pci_host_stop,
};
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
/* board_2037x */
{
.sht = &pdc_ata_sht,
@@ -191,6 +191,16 @@ static struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_pata_ops,
},
+
+ /* board_20771 */
+ {
+ .sht = &pdc_ata_sht,
+ .host_flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_sata_ops,
+ },
};
static const struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -227,6 +237,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20619 },
+ { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20771 },
{ } /* terminate list */
};
@@ -401,7 +413,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
drv_stat = ata_wait_idle(ap);
- ata_qc_complete(qc, __ac_err_mask(drv_stat));
+ qc->err_mask |= __ac_err_mask(drv_stat);
+ ata_qc_complete(qc);
break;
default:
@@ -410,7 +423,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
ap->id, qc->tf.command, drv_stat);
- ata_qc_complete(qc, ac_err_mask(drv_stat));
+ qc->err_mask |= ac_err_mask(drv_stat);
+ ata_qc_complete(qc);
break;
}
@@ -422,21 +436,21 @@ out:
static inline unsigned int pdc_host_intr( struct ata_port *ap,
struct ata_queued_cmd *qc)
{
- unsigned int handled = 0, err_mask = 0;
+ unsigned int handled = 0;
u32 tmp;
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
tmp = readl(mmio);
if (tmp & PDC_ERR_MASK) {
- err_mask = AC_ERR_DEV;
+ qc->err_mask |= AC_ERR_DEV;
pdc_reset_port(ap);
}
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
- err_mask |= ac_err_mask(ata_wait_idle(ap));
- ata_qc_complete(qc, err_mask);
+ qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+ ata_qc_complete(qc);
handled = 1;
break;
@@ -703,7 +717,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->port[3].scr_addr = base + 0x700;
break;
case board_2037x:
- probe_ent->n_ports = 2;
+ probe_ent->n_ports = 2;
+ break;
+ case board_20771:
+ probe_ent->n_ports = 2;
break;
case board_20619:
probe_ent->n_ports = 4;
@@ -713,7 +730,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->port[2].scr_addr = base + 0x600;
probe_ent->port[3].scr_addr = base + 0x700;
- break;
+ break;
default:
BUG();
break;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index a8987f5ff5cc..de05e2883f9c 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -170,7 +170,7 @@ static const struct ata_port_operations qs_ata_ops = {
.bmdma_status = qs_bmdma_status,
};
-static struct ata_port_info qs_port_info[] = {
+static const struct ata_port_info qs_port_info[] = {
/* board_2068_idx */
{
.sht = &qs_ata_sht,
@@ -409,8 +409,8 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set)
case 3: /* device error */
pp->state = qs_state_idle;
qs_enter_reg_mode(qc->ap);
- ata_qc_complete(qc,
- ac_err_mask(sDST));
+ qc->err_mask |= ac_err_mask(sDST);
+ ata_qc_complete(qc);
break;
default:
break;
@@ -447,7 +447,8 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set)
/* complete taskfile transaction */
pp->state = qs_state_idle;
- ata_qc_complete(qc, ac_err_mask(status));
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
handled = 1;
}
}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 36091868560d..b017f85e6d6a 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -147,7 +147,6 @@ static struct scsi_host_template sil_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations sil_ops = {
@@ -176,7 +175,7 @@ static const struct ata_port_operations sil_ops = {
.host_stop = ata_pci_host_stop,
};
-static struct ata_port_info sil_port_info[] = {
+static const struct ata_port_info sil_port_info[] = {
/* sil_3112 */
{
.sht = &sil_sht,
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index e0d6f194f54f..923130185a9e 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -292,7 +292,6 @@ static struct scsi_host_template sil24_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1, /* NCQ not supported yet */
};
static const struct ata_port_operations sil24_ops = {
@@ -654,7 +653,8 @@ static void sil24_eng_timeout(struct ata_port *ap)
*/
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
qc->scsidone = scsi_finish_command;
- ata_qc_complete(qc, AC_ERR_OTHER);
+ qc->err_mask |= AC_ERR_OTHER;
+ ata_qc_complete(qc);
sil24_reset_controller(ap);
}
@@ -711,8 +711,10 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
sil24_reset_controller(ap);
}
- if (qc)
- ata_qc_complete(qc, err_mask);
+ if (qc) {
+ qc->err_mask |= err_mask;
+ ata_qc_complete(qc);
+ }
}
static inline void sil24_host_intr(struct ata_port *ap)
@@ -734,8 +736,10 @@ static inline void sil24_host_intr(struct ata_port *ap)
*/
sil24_update_tf(ap);
- if (qc)
- ata_qc_complete(qc, ac_err_mask(pp->tf.command));
+ if (qc) {
+ qc->err_mask |= ac_err_mask(pp->tf.command);
+ ata_qc_complete(qc);
+ }
} else
sil24_error_intr(ap, slot_stat);
}
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 32e12620b162..2df8c5632ac3 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -99,7 +99,6 @@ static struct scsi_host_template sis_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations sis_ops = {
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 6e7f7c83a75a..d8472563fde8 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -303,7 +303,6 @@ static struct scsi_host_template k2_sata_sht = {
.proc_info = k2_sata_proc_info,
#endif
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
@@ -471,6 +470,7 @@ static const struct pci_device_id k2_sata_pci_tbl[] = {
{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ }
};
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index ac7b0d819ebc..bc87c16c80d2 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -194,7 +194,6 @@ static struct scsi_host_template pdc_sata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations pdc_20621_ops = {
@@ -215,7 +214,7 @@ static const struct ata_port_operations pdc_20621_ops = {
.host_stop = pdc20621_host_stop,
};
-static struct ata_port_info pdc_port_info[] = {
+static const struct ata_port_info pdc_port_info[] = {
/* board_20621 */
{
.sht = &pdc_sata_sht,
@@ -719,7 +718,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* get drive status; clear intr; complete txn */
- ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+ qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+ ata_qc_complete(qc);
pdc20621_pop_hdma(qc);
}
@@ -757,7 +757,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* get drive status; clear intr; complete txn */
- ata_qc_complete(qc, ac_err_mask(ata_wait_idle(ap)));
+ qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+ ata_qc_complete(qc);
pdc20621_pop_hdma(qc);
}
handled = 1;
@@ -767,7 +768,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
- ata_qc_complete(qc, ac_err_mask(status));
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
handled = 1;
} else {
@@ -882,7 +884,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
printk(KERN_ERR "ata%u: command timeout\n", ap->id);
- ata_qc_complete(qc, __ac_err_mask(ata_wait_idle(ap)));
+ qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
+ ata_qc_complete(qc);
break;
default:
@@ -891,7 +894,8 @@ static void pdc_eng_timeout(struct ata_port *ap)
printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
ap->id, qc->tf.command, drv_stat);
- ata_qc_complete(qc, ac_err_mask(drv_stat));
+ qc->err_mask |= ac_err_mask(drv_stat);
+ ata_qc_complete(qc);
break;
}
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index b2422a0f25c8..9635ca700977 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -87,7 +87,6 @@ static struct scsi_host_template uli_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations uli_ops = {
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index c76215692da2..6d5b0a794cfd 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -106,7 +106,6 @@ static struct scsi_host_template svia_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
static const struct ata_port_operations svia_sata_ops = {
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index fcfa486965b4..2e2c3b7acb0c 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -235,7 +235,6 @@ static struct scsi_host_template vsc_sata_sht = {
.dma_boundary = ATA_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
- .ordered_flush = 1,
};
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 180676d7115a..245ca99a641e 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -55,6 +55,7 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -69,7 +70,6 @@
#include "scsi_logging.h"
static void scsi_done(struct scsi_cmnd *cmd);
-static int scsi_retry_command(struct scsi_cmnd *cmd);
/*
* Definitions and constants.
@@ -210,7 +210,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = {
.gfp_mask = __GFP_DMA,
};
-static DECLARE_MUTEX(host_cmd_pool_mutex);
+static DEFINE_MUTEX(host_cmd_pool_mutex);
static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost,
gfp_t gfp_mask)
@@ -331,7 +331,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
* Select a command slab for this host and create it if not
* yet existant.
*/
- down(&host_cmd_pool_mutex);
+ mutex_lock(&host_cmd_pool_mutex);
pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);
if (!pool->users) {
pool->slab = kmem_cache_create(pool->name,
@@ -343,7 +343,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
pool->users++;
shost->cmd_pool = pool;
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
/*
* Get one backup command for this host.
@@ -360,7 +360,7 @@ int scsi_setup_command_freelist(struct Scsi_Host *shost)
kmem_cache_destroy(pool->slab);
return -ENOMEM;
fail:
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
return -ENOMEM;
}
@@ -382,10 +382,10 @@ void scsi_destroy_command_freelist(struct Scsi_Host *shost)
kmem_cache_free(shost->cmd_pool->slab, cmd);
}
- down(&host_cmd_pool_mutex);
+ mutex_lock(&host_cmd_pool_mutex);
if (!--shost->cmd_pool->users)
kmem_cache_destroy(shost->cmd_pool->slab);
- up(&host_cmd_pool_mutex);
+ mutex_unlock(&host_cmd_pool_mutex);
}
#ifdef CONFIG_SCSI_LOGGING
@@ -752,7 +752,7 @@ static void scsi_done(struct scsi_cmnd *cmd)
* isn't running --- used by scsi_times_out */
void __scsi_done(struct scsi_cmnd *cmd)
{
- unsigned long flags;
+ struct request *rq = cmd->request;
/*
* Set the serial numbers back to zero
@@ -763,71 +763,14 @@ void __scsi_done(struct scsi_cmnd *cmd)
if (cmd->result)
atomic_inc(&cmd->device->ioerr_cnt);
+ BUG_ON(!rq);
+
/*
- * Next, enqueue the command into the done queue.
- * It is a per-CPU queue, so we just disable local interrupts
- * and need no spinlock.
+ * The uptodate/nbytes values don't matter, as we allow partial
+ * completes and thus will check this in the softirq callback
*/
- local_irq_save(flags);
- list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q));
- raise_softirq_irqoff(SCSI_SOFTIRQ);
- local_irq_restore(flags);
-}
-
-/**
- * scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
- *
- * This is the consumer of the done queue.
- *
- * This is called with all interrupts enabled. This should reduce
- * interrupt latency, stack depth, and reentrancy of the low-level
- * drivers.
- */
-static void scsi_softirq(struct softirq_action *h)
-{
- int disposition;
- LIST_HEAD(local_q);
-
- local_irq_disable();
- list_splice_init(&__get_cpu_var(scsi_done_q), &local_q);
- local_irq_enable();
-
- 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)) {
- sdev_printk(KERN_ERR, cmd->device,
- "timing out command, waited %lus\n",
- wait_for/HZ);
- disposition = SUCCESS;
- }
-
- scsi_log_completion(cmd, disposition);
- switch (disposition) {
- case SUCCESS:
- scsi_finish_command(cmd);
- break;
- case NEEDS_RETRY:
- scsi_retry_command(cmd);
- break;
- case ADD_TO_MLQUEUE:
- scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
- break;
- default:
- if (!scsi_eh_scmd_add(cmd, 0))
- scsi_finish_command(cmd);
- }
- }
+ rq->completion_data = cmd;
+ blk_complete_request(rq);
}
/*
@@ -840,7 +783,7 @@ static void scsi_softirq(struct softirq_action *h)
* level drivers should not become re-entrant as a result of
* this.
*/
-static int scsi_retry_command(struct scsi_cmnd *cmd)
+int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
@@ -1273,38 +1216,6 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
}
EXPORT_SYMBOL(scsi_device_cancel);
-#ifdef CONFIG_HOTPLUG_CPU
-static int scsi_cpu_notify(struct notifier_block *self,
- unsigned long action, void *hcpu)
-{
- int cpu = (unsigned long)hcpu;
-
- switch(action) {
- case CPU_DEAD:
- /* Drain scsi_done_q. */
- local_irq_disable();
- list_splice_init(&per_cpu(scsi_done_q, cpu),
- &__get_cpu_var(scsi_done_q));
- raise_softirq_irqoff(SCSI_SOFTIRQ);
- local_irq_enable();
- break;
- default:
- break;
- }
- return NOTIFY_OK;
-}
-
-static struct notifier_block __devinitdata scsi_cpu_nb = {
- .notifier_call = scsi_cpu_notify,
-};
-
-#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)
-#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)
-#else
-#define register_scsi_cpu()
-#define unregister_scsi_cpu()
-#endif /* CONFIG_HOTPLUG_CPU */
-
MODULE_DESCRIPTION("SCSI core");
MODULE_LICENSE("GPL");
@@ -1338,8 +1249,6 @@ static int __init init_scsi(void)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));
devfs_mk_dir("scsi");
- open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
- register_scsi_cpu();
printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0;
@@ -1367,7 +1276,6 @@ static void __exit exit_scsi(void)
devfs_remove("scsi");
scsi_exit_procfs();
scsi_exit_queue();
- unregister_scsi_cpu();
}
subsys_initcall(init_scsi);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3ded9daaf4a0..0e529f8171c4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus;
static struct device_driver sdebug_driverfs_driver = {
.name = sdebug_proc_name,
.bus = &pseudo_lld_bus,
- .probe = sdebug_driver_probe,
- .remove = sdebug_driver_remove,
};
static const int check_condition_result =
@@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev,
static struct bus_type pseudo_lld_bus = {
.name = "pseudo",
.match = pseudo_lld_bus_match,
+ .probe = sdebug_driver_probe,
+ .remove = sdebug_driver_remove,
};
static void sdebug_release_adapter(struct device * dev)
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index e69477d1889b..f01ec0a7c506 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -354,8 +354,9 @@ static int scsi_dev_info_list_add_str(char *dev_list)
* @model, if found, return the matching flags value, else return
* the host or global default settings.
**/
-int scsi_get_device_flags(struct scsi_device *sdev, unsigned char *vendor,
- unsigned char *model)
+int scsi_get_device_flags(struct scsi_device *sdev,
+ const unsigned char *vendor,
+ const unsigned char *model)
{
struct scsi_dev_info_list *devinfo;
unsigned int bflags;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index c0ae9e965f6f..a2333d2c7af0 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1320,23 +1320,6 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
}
/**
- * scsi_eh_lock_done - done function for eh door lock request
- * @scmd: SCSI command block for the door lock request
- *
- * Notes:
- * We completed the asynchronous door lock request, and it has either
- * locked the door or failed. We must free the command structures
- * associated with this request.
- **/
-static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
-{
- struct scsi_request *sreq = scmd->sc_request;
-
- scsi_release_request(sreq);
-}
-
-
-/**
* scsi_eh_lock_door - Prevent medium removal for the specified device
* @sdev: SCSI device to prevent medium removal
*
@@ -1358,29 +1341,17 @@ static void scsi_eh_lock_done(struct scsi_cmnd *scmd)
**/
static void scsi_eh_lock_door(struct scsi_device *sdev)
{
- struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+ unsigned char cmnd[MAX_COMMAND_SIZE];
- if (unlikely(!sreq)) {
- printk(KERN_ERR "%s: request allocate failed,"
- "prevent media removal cmd not sent\n", __FUNCTION__);
- return;
- }
+ cmnd[0] = ALLOW_MEDIUM_REMOVAL;
+ cmnd[1] = 0;
+ cmnd[2] = 0;
+ cmnd[3] = 0;
+ cmnd[4] = SCSI_REMOVAL_PREVENT;
+ cmnd[5] = 0;
- sreq->sr_cmnd[0] = ALLOW_MEDIUM_REMOVAL;
- sreq->sr_cmnd[1] = 0;
- sreq->sr_cmnd[2] = 0;
- sreq->sr_cmnd[3] = 0;
- sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT;
- sreq->sr_cmnd[5] = 0;
- sreq->sr_data_direction = DMA_NONE;
- sreq->sr_bufflen = 0;
- sreq->sr_buffer = NULL;
- sreq->sr_allowed = 5;
- sreq->sr_done = scsi_eh_lock_done;
- sreq->sr_timeout_per_command = 10 * HZ;
- sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
-
- scsi_insert_special_req(sreq, 1);
+ scsi_execute_async(sdev, cmnd, DMA_NONE, NULL, 0, 0, 10 * HZ,
+ 5, NULL, NULL, GFP_KERNEL);
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index dc249cb970ea..3574ba935af8 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -63,39 +63,6 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
};
#undef SP
-
-/*
- * Function: scsi_insert_special_req()
- *
- * Purpose: Insert pre-formed request into request queue.
- *
- * Arguments: sreq - request that is ready to be queued.
- * at_head - boolean. True if we should insert at head
- * of queue, false if we should insert at tail.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns: Nothing
- *
- * Notes: This function is called from character device and from
- * ioctl types of functions where the caller knows exactly
- * what SCSI command needs to be issued. The idea is that
- * we merely inject the command into the queue (at the head
- * for now), and then call the queue request function to actually
- * process it.
- */
-int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
-{
- /*
- * Because users of this function are apt to reuse requests with no
- * modification, we have to sanitise the request flags here
- */
- sreq->sr_request->flags &= ~REQ_DONTPREP;
- blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
- at_head, sreq);
- return 0;
-}
-
static void scsi_run_queue(struct request_queue *q);
/*
@@ -249,8 +216,13 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
/*
* head injection *required* here otherwise quiesce won't work
+ *
+ * Because users of this function are apt to reuse requests with no
+ * modification, we have to sanitise the request flags here
*/
- scsi_insert_special_req(sreq, 1);
+ sreq->sr_request->flags &= ~REQ_DONTPREP;
+ blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
+ 1, sreq);
}
EXPORT_SYMBOL(scsi_do_req);
@@ -287,6 +259,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
memcpy(req->cmd, cmd, req->cmd_len);
req->sense = sense;
req->sense_len = 0;
+ req->retries = retries;
req->timeout = timeout;
req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET;
@@ -327,6 +300,200 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
}
EXPORT_SYMBOL(scsi_execute_req);
+struct scsi_io_context {
+ void *data;
+ void (*done)(void *data, char *sense, int result, int resid);
+ char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+static kmem_cache_t *scsi_io_context_cache;
+
+static void scsi_end_async(struct request *req, int uptodate)
+{
+ struct scsi_io_context *sioc = req->end_io_data;
+
+ if (sioc->done)
+ sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
+
+ kmem_cache_free(scsi_io_context_cache, sioc);
+ __blk_put_request(req->q, req);
+}
+
+static int scsi_merge_bio(struct request *rq, struct bio *bio)
+{
+ struct request_queue *q = rq->q;
+
+ bio->bi_flags &= ~(1 << BIO_SEG_VALID);
+ if (rq_data_dir(rq) == WRITE)
+ bio->bi_rw |= (1 << BIO_RW);
+ blk_queue_bounce(q, &bio);
+
+ if (!rq->bio)
+ blk_rq_bio_prep(q, rq, bio);
+ else if (!q->back_merge_fn(q, rq, bio))
+ return -EINVAL;
+ else {
+ rq->biotail->bi_next = bio;
+ rq->biotail = bio;
+ rq->hard_nr_sectors += bio_sectors(bio);
+ rq->nr_sectors = rq->hard_nr_sectors;
+ }
+
+ return 0;
+}
+
+static int scsi_bi_endio(struct bio *bio, unsigned int bytes_done, int error)
+{
+ if (bio->bi_size)
+ return 1;
+
+ bio_put(bio);
+ return 0;
+}
+
+/**
+ * scsi_req_map_sg - map a scatterlist into a request
+ * @rq: request to fill
+ * @sg: scatterlist
+ * @nsegs: number of elements
+ * @bufflen: len of buffer
+ * @gfp: memory allocation flags
+ *
+ * scsi_req_map_sg maps a scatterlist into a request so that the
+ * request can be sent to the block layer. We do not trust the scatterlist
+ * sent to use, as some ULDs use that struct to only organize the pages.
+ */
+static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
+ int nsegs, unsigned bufflen, gfp_t gfp)
+{
+ struct request_queue *q = rq->q;
+ int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned int data_len = 0, len, bytes, off;
+ struct page *page;
+ struct bio *bio = NULL;
+ int i, err, nr_vecs = 0;
+
+ for (i = 0; i < nsegs; i++) {
+ page = sgl[i].page;
+ off = sgl[i].offset;
+ len = sgl[i].length;
+ data_len += len;
+
+ while (len > 0) {
+ bytes = min_t(unsigned int, len, PAGE_SIZE - off);
+
+ if (!bio) {
+ nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
+ nr_pages -= nr_vecs;
+
+ bio = bio_alloc(gfp, nr_vecs);
+ if (!bio) {
+ err = -ENOMEM;
+ goto free_bios;
+ }
+ bio->bi_end_io = scsi_bi_endio;
+ }
+
+ if (bio_add_pc_page(q, bio, page, bytes, off) !=
+ bytes) {
+ bio_put(bio);
+ err = -EINVAL;
+ goto free_bios;
+ }
+
+ if (bio->bi_vcnt >= nr_vecs) {
+ err = scsi_merge_bio(rq, bio);
+ if (err) {
+ bio_endio(bio, bio->bi_size, 0);
+ goto free_bios;
+ }
+ bio = NULL;
+ }
+
+ page++;
+ len -= bytes;
+ off = 0;
+ }
+ }
+
+ rq->buffer = rq->data = NULL;
+ rq->data_len = data_len;
+ return 0;
+
+free_bios:
+ while ((bio = rq->bio) != NULL) {
+ rq->bio = bio->bi_next;
+ /*
+ * call endio instead of bio_put incase it was bounced
+ */
+ bio_endio(bio, bio->bi_size, 0);
+ }
+
+ return err;
+}
+
+/**
+ * scsi_execute_async - insert request
+ * @sdev: scsi device
+ * @cmd: scsi command
+ * @data_direction: data direction
+ * @buffer: data buffer (this can be a kernel buffer or scatterlist)
+ * @bufflen: len of buffer
+ * @use_sg: if buffer is a scatterlist this is the number of elements
+ * @timeout: request timeout in seconds
+ * @retries: number of times to retry request
+ * @flags: or into request flags
+ **/
+int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ int use_sg, int timeout, int retries, void *privdata,
+ void (*done)(void *, char *, int, int), gfp_t gfp)
+{
+ struct request *req;
+ struct scsi_io_context *sioc;
+ int err = 0;
+ int write = (data_direction == DMA_TO_DEVICE);
+
+ sioc = kmem_cache_alloc(scsi_io_context_cache, gfp);
+ if (!sioc)
+ return DRIVER_ERROR << 24;
+ memset(sioc, 0, sizeof(*sioc));
+
+ req = blk_get_request(sdev->request_queue, write, gfp);
+ if (!req)
+ goto free_sense;
+ req->flags |= REQ_BLOCK_PC | REQ_QUIET;
+
+ if (use_sg)
+ err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
+ else if (bufflen)
+ err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp);
+
+ if (err)
+ goto free_req;
+
+ req->cmd_len = COMMAND_SIZE(cmd[0]);
+ memcpy(req->cmd, cmd, req->cmd_len);
+ req->sense = sioc->sense;
+ req->sense_len = 0;
+ req->timeout = timeout;
+ req->retries = retries;
+ req->end_io_data = sioc;
+
+ sioc->data = privdata;
+ sioc->done = done;
+
+ blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async);
+ return 0;
+
+free_req:
+ blk_put_request(req);
+free_sense:
+ kfree(sioc);
+ return DRIVER_ERROR << 24;
+}
+EXPORT_SYMBOL_GPL(scsi_execute_async);
+
/*
* Function: scsi_init_cmd_errh()
*
@@ -624,7 +791,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,
spin_lock_irqsave(q->queue_lock, flags);
if (blk_rq_tagged(req))
blk_queue_end_tag(q, req);
- end_that_request_last(req);
+ end_that_request_last(req, uptodate);
spin_unlock_irqrestore(q->queue_lock, flags);
/*
@@ -765,9 +932,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
int sense_valid = 0;
int sense_deferred = 0;
- if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
- return;
-
/*
* Free up any indirection buffers we allocated for DMA purposes.
* For the case of a READ, we need to copy the data out of the
@@ -884,7 +1048,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes,
* system where READ CAPACITY failed, we may have read
* past the end of the disk.
*/
- if (cmd->device->use_10_for_rw &&
+ if ((cmd->device->use_10_for_rw &&
+ sshdr.asc == 0x20 && sshdr.ascq == 0x00) &&
(cmd->cmnd[0] == READ_10 ||
cmd->cmnd[0] == WRITE_10)) {
cmd->device->use_10_for_rw = 0;
@@ -1031,38 +1196,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
return BLKPREP_KILL;
}
-static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct scsi_driver *drv;
-
- if (sdev->sdev_state == SDEV_RUNNING) {
- drv = *(struct scsi_driver **) rq->rq_disk->private_data;
-
- if (drv->prepare_flush)
- return drv->prepare_flush(q, rq);
- }
-
- return 0;
-}
-
-static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct request *flush_rq = rq->end_io_data;
- struct scsi_driver *drv;
-
- if (flush_rq->errors) {
- printk("scsi: barrier error, disabling flush support\n");
- blk_queue_ordered(q, QUEUE_ORDERED_NONE);
- }
-
- if (sdev->sdev_state == SDEV_RUNNING) {
- drv = *(struct scsi_driver **) rq->rq_disk->private_data;
- drv->end_flush(q, rq);
- }
-}
-
static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
sector_t *error_sector)
{
@@ -1079,13 +1212,19 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
return -EOPNOTSUPP;
}
-static void scsi_generic_done(struct scsi_cmnd *cmd)
+static void scsi_blk_pc_done(struct scsi_cmnd *cmd)
{
BUG_ON(!blk_pc_request(cmd->request));
- scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0);
+ /*
+ * This will complete the whole command with uptodate=1 so
+ * as far as the block layer is concerned the command completed
+ * successfully. Since this is a REQ_BLOCK_PC command the
+ * caller should check the request's errors value
+ */
+ scsi_io_completion(cmd, cmd->bufflen, 0);
}
-void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries)
+static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd)
{
struct request *req = cmd->request;
@@ -1100,10 +1239,10 @@ void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries)
cmd->sc_data_direction = DMA_FROM_DEVICE;
cmd->transfersize = req->data_len;
- cmd->allowed = retries;
+ cmd->allowed = req->retries;
cmd->timeout_per_command = req->timeout;
+ cmd->done = scsi_blk_pc_done;
}
-EXPORT_SYMBOL_GPL(scsi_setup_blk_pc_cmnd);
static int scsi_prep_fn(struct request_queue *q, struct request *req)
{
@@ -1200,7 +1339,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
* happening now.
*/
if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
- struct scsi_driver *drv;
int ret;
/*
@@ -1232,16 +1370,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
/*
* Initialize the actual SCSI command for this request.
*/
- if (req->rq_disk) {
+ if (req->flags & REQ_BLOCK_PC) {
+ scsi_setup_blk_pc_cmnd(cmd);
+ } else if (req->rq_disk) {
+ struct scsi_driver *drv;
+
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 {
- scsi_setup_blk_pc_cmnd(cmd, 3);
- cmd->done = scsi_generic_done;
}
}
@@ -1354,6 +1493,41 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
__scsi_done(cmd);
}
+static void scsi_softirq_done(struct request *rq)
+{
+ struct scsi_cmnd *cmd = rq->completion_data;
+ unsigned long wait_for = cmd->allowed * cmd->timeout_per_command;
+ int disposition;
+
+ INIT_LIST_HEAD(&cmd->eh_entry);
+
+ disposition = scsi_decide_disposition(cmd);
+ if (disposition != SUCCESS &&
+ time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+ sdev_printk(KERN_ERR, cmd->device,
+ "timing out command, waited %lus\n",
+ wait_for/HZ);
+ disposition = SUCCESS;
+ }
+
+ scsi_log_completion(cmd, disposition);
+
+ switch (disposition) {
+ case SUCCESS:
+ scsi_finish_command(cmd);
+ break;
+ case NEEDS_RETRY:
+ scsi_retry_command(cmd);
+ break;
+ case ADD_TO_MLQUEUE:
+ scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+ break;
+ default:
+ if (!scsi_eh_scmd_add(cmd, 0))
+ scsi_finish_command(cmd);
+ }
+}
+
/*
* Function: scsi_request_fn()
*
@@ -1528,17 +1702,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
-
- /*
- * ordered tags are superior to flush ordering
- */
- if (shost->ordered_tag)
- blk_queue_ordered(q, QUEUE_ORDERED_TAG);
- else if (shost->ordered_flush) {
- blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
- q->prepare_flush_fn = scsi_prepare_flush_fn;
- q->end_flush_fn = scsi_end_flush_fn;
- }
+ blk_queue_softirq_done(q, scsi_softirq_done);
if (!shost->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
@@ -1603,6 +1767,14 @@ int __init scsi_init_queue(void)
{
int i;
+ scsi_io_context_cache = kmem_cache_create("scsi_io_context",
+ sizeof(struct scsi_io_context),
+ 0, 0, NULL, NULL);
+ if (!scsi_io_context_cache) {
+ printk(KERN_ERR "SCSI: can't init scsi io context cache\n");
+ return -ENOMEM;
+ }
+
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
int size = sgp->size * sizeof(struct scatterlist);
@@ -1630,6 +1802,8 @@ void scsi_exit_queue(void)
{
int i;
+ kmem_cache_destroy(scsi_io_context_cache);
+
for (i = 0; i < SG_MEMPOOL_NR; i++) {
struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
mempool_destroy(sgp->pool);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index d632d9e1493c..27c48274e8cb 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -26,12 +26,6 @@ struct Scsi_Host;
#define SCSI_SENSE_VALID(scmd) \
(((scmd)->sense_buffer[0] & 0x70) == 0x70)
-/*
- * Special value for scanning to specify scanning or rescanning of all
- * possible channels, (target) ids, or luns on a given shost.
- */
-#define SCAN_WILD_CARD ~0
-
/* hosts.c */
extern int scsi_init_hosts(void);
extern void scsi_exit_hosts(void);
@@ -40,11 +34,11 @@ extern void scsi_exit_hosts(void);
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
-extern int scsi_insert_special_req(struct scsi_request *sreq, int);
extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
struct scsi_request *sreq);
extern void __scsi_release_request(struct scsi_request *sreq);
extern void __scsi_done(struct scsi_cmnd *cmd);
+extern int scsi_retry_command(struct scsi_cmnd *cmd);
#ifdef CONFIG_SCSI_LOGGING
void scsi_log_send(struct scsi_cmnd *cmd);
void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
@@ -57,7 +51,8 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
/* scsi_devinfo.c */
extern int scsi_get_device_flags(struct scsi_device *sdev,
- unsigned char *vendor, unsigned char *model);
+ const unsigned char *vendor,
+ const unsigned char *model);
extern int __init scsi_init_devinfo(void);
extern void scsi_exit_devinfo(void);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index a50958b1b6ee..07be62bbaaea 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -25,11 +25,13 @@
#include <linux/errno.h>
#include <linux/blkdev.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
#include "scsi_priv.h"
#include "scsi_logging.h"
@@ -41,7 +43,7 @@
static struct proc_dir_entry *proc_scsi;
/* Protect sht->present and sht->proc_dir */
-static DECLARE_MUTEX(global_host_template_sem);
+static DEFINE_MUTEX(global_host_template_mutex);
static int proc_scsi_read(char *buffer, char **start, off_t offset,
int length, int *eof, void *data)
@@ -83,7 +85,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
if (!sht->proc_info)
return;
- down(&global_host_template_sem);
+ mutex_lock(&global_host_template_mutex);
if (!sht->present++) {
sht->proc_dir = proc_mkdir(sht->proc_name, proc_scsi);
if (!sht->proc_dir)
@@ -92,7 +94,7 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
else
sht->proc_dir->owner = sht->module;
}
- up(&global_host_template_sem);
+ mutex_unlock(&global_host_template_mutex);
}
void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
@@ -100,12 +102,12 @@ void scsi_proc_hostdir_rm(struct scsi_host_template *sht)
if (!sht->proc_info)
return;
- down(&global_host_template_sem);
+ mutex_lock(&global_host_template_mutex);
if (!--sht->present && sht->proc_dir) {
remove_proc_entry(sht->proc_name, proc_scsi);
sht->proc_dir = NULL;
}
- up(&global_host_template_sem);
+ mutex_unlock(&global_host_template_mutex);
}
void scsi_proc_host_add(struct Scsi_Host *shost)
@@ -199,7 +201,10 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
if (IS_ERR(shost))
return PTR_ERR(shost);
- error = scsi_scan_host_selected(shost, channel, id, lun, 1);
+ if (shost->transportt->user_scan)
+ error = shost->transportt->user_scan(shost, channel, id, lun);
+ else
+ error = scsi_scan_host_selected(shost, channel, id, lun, 1);
scsi_host_put(shost);
return error;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 4e6709f448e1..752fb5da3de4 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -74,7 +74,7 @@
#define SCSI_SCAN_TARGET_PRESENT 1
#define SCSI_SCAN_LUN_PRESENT 2
-static char *scsi_null_device_strs = "nullnullnullnull";
+static const char *scsi_null_device_strs = "nullnullnullnull";
#define MAX_SCSI_LUNS 512
@@ -334,19 +334,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
struct scsi_target *starget;
struct scsi_target *found_target;
- /*
- * Obtain the real parent from the transport. The transport
- * is allowed to fail (no error) if there is nothing at that
- * target id.
- */
- if (shost->transportt->target_parent) {
- spin_lock_irqsave(shost->host_lock, flags);
- parent = shost->transportt->target_parent(shost, channel, id);
- spin_unlock_irqrestore(shost->host_lock, flags);
- if (!parent)
- return NULL;
- }
-
starget = kmalloc(size, GFP_KERNEL);
if (!starget) {
printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
@@ -1283,20 +1270,21 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
struct scsi_device *sdev;
struct device *parent = &shost->shost_gendev;
int res;
- struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+ struct scsi_target *starget;
+ starget = scsi_alloc_target(parent, channel, id);
if (!starget)
return ERR_PTR(-ENOMEM);
get_device(&starget->dev);
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
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);
+ mutex_unlock(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
@@ -1404,10 +1392,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel,
{
struct Scsi_Host *shost = dev_to_shost(parent);
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (scsi_host_scan_allowed(shost))
__scsi_scan_target(parent, channel, id, lun, rescan);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_scan_target);
@@ -1454,7 +1442,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (scsi_host_scan_allowed(shost)) {
if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel;
@@ -1464,7 +1452,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
else
scsi_scan_channel(shost, channel, id, lun, rescan);
}
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
return 0;
}
@@ -1522,7 +1510,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
struct scsi_device *sdev = NULL;
struct scsi_target *starget;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
if (!scsi_host_scan_allowed(shost))
goto out;
starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
@@ -1536,7 +1524,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
}
put_device(&starget->dev);
out:
- up(&shost->scan_mutex);
+ mutex_unlock(&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 46349293de08..a77b32deaf8f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -21,7 +21,7 @@
#include "scsi_priv.h"
#include "scsi_logging.h"
-static struct {
+static const struct {
enum scsi_device_state value;
char *name;
} sdev_states[] = {
@@ -48,7 +48,7 @@ const char *scsi_device_state_name(enum scsi_device_state state)
return name;
}
-static struct {
+static const struct {
enum scsi_host_state value;
char *name;
} shost_states[] = {
@@ -106,7 +106,10 @@ static int scsi_scan(struct Scsi_Host *shost, const char *str)
return -EINVAL;
if (check_set(&lun, s3))
return -EINVAL;
- res = scsi_scan_host_selected(shost, channel, id, lun, 1);
+ if (shost->transportt->user_scan)
+ res = shost->transportt->user_scan(shost, channel, id, lun);
+ else
+ res = scsi_scan_host_selected(shost, channel, id, lun, 1);
return res;
}
@@ -263,9 +266,40 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv)
return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
}
+static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_host_template *sht = sdev->host->hostt;
+ int err;
+
+ err = scsi_device_quiesce(sdev);
+ if (err)
+ return err;
+
+ if (sht->suspend)
+ err = sht->suspend(sdev);
+
+ return err;
+}
+
+static int scsi_bus_resume(struct device * dev)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct scsi_host_template *sht = sdev->host->hostt;
+ int err = 0;
+
+ if (sht->resume)
+ err = sht->resume(sdev);
+
+ scsi_device_resume(sdev);
+ return err;
+}
+
struct bus_type scsi_bus_type = {
.name = "scsi",
.match = scsi_bus_match,
+ .suspend = scsi_bus_suspend,
+ .resume = scsi_bus_resume,
};
int scsi_sysfs_register(void)
@@ -714,9 +748,9 @@ void scsi_remove_device(struct scsi_device *sdev)
{
struct Scsi_Host *shost = sdev->host;
- down(&shost->scan_mutex);
+ mutex_lock(&shost->scan_mutex);
__scsi_remove_device(sdev);
- up(&shost->scan_mutex);
+ mutex_unlock(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 2a1a99a2ef56..f2c9acf11bd0 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -112,7 +112,7 @@ fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
/* Convert fc_tgtid_binding_type values to ascii string name */
-static struct {
+static const struct {
enum fc_tgtid_binding_type value;
char *name;
int matchlen;
@@ -150,7 +150,7 @@ get_fc_##title##_names(u32 table_key, char *buf) \
/* Convert FC_COS bit values to ascii string name */
-static struct {
+static const struct {
u32 value;
char *name;
} fc_cos_names[] = {
@@ -164,7 +164,7 @@ fc_bitfield_name_search(cos, fc_cos_names)
/* Convert FC_PORTSPEED bit values to ascii string name */
-static struct {
+static const struct {
u32 value;
char *name;
} fc_port_speed_names[] = {
@@ -190,7 +190,7 @@ show_fc_fc4s (char *buf, u8 *fc4_list)
/* Convert FC_RPORT_ROLE bit values to ascii string name */
-static struct {
+static const struct {
u32 value;
char *name;
} fc_remote_port_role_names[] = {
@@ -295,6 +295,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
*/
fc_host_node_name(shost) = -1;
fc_host_port_name(shost) = -1;
+ fc_host_permanent_port_name(shost) = -1;
fc_host_supported_classes(shost) = FC_COS_UNSPECIFIED;
memset(fc_host_supported_fc4s(shost), 0,
sizeof(fc_host_supported_fc4s(shost)));
@@ -795,6 +796,8 @@ static FC_CLASS_DEVICE_ATTR(host, supported_speeds, S_IRUGO,
fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
+fc_private_host_rd_attr_cast(permanent_port_name, "0x%llx\n", 20,
+ unsigned long long);
fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
@@ -1090,17 +1093,23 @@ static int fc_rport_match(struct attribute_container *cont,
/*
* Must be called with shost->host_lock held
*/
-static struct device *fc_target_parent(struct Scsi_Host *shost,
- int channel, uint id)
+static int fc_user_scan(struct Scsi_Host *shost, uint channel,
+ uint id, uint lun)
{
struct fc_rport *rport;
- list_for_each_entry(rport, &fc_host_rports(shost), peers)
- if ((rport->channel == channel) &&
- (rport->scsi_target_id == id))
- return &rport->dev;
+ list_for_each_entry(rport, &fc_host_rports(shost), peers) {
+ if (rport->scsi_target_id == -1)
+ continue;
+
+ if ((channel == SCAN_WILD_CARD || channel == rport->channel) &&
+ (id == SCAN_WILD_CARD || id == rport->scsi_target_id)) {
+ scsi_scan_target(&rport->dev, rport->channel,
+ rport->scsi_target_id, lun, 1);
+ }
+ }
- return NULL;
+ return 0;
}
struct scsi_transport_template *
@@ -1139,7 +1148,7 @@ fc_attach_transport(struct fc_function_template *ft)
/* Transport uses the shost workq for scsi scanning */
i->t.create_work_queue = 1;
- i->t.target_parent = fc_target_parent;
+ i->t.user_scan = fc_user_scan;
/*
* Setup SCSI Target Attributes.
@@ -1160,6 +1169,7 @@ fc_attach_transport(struct fc_function_template *ft)
count=0;
SETUP_HOST_ATTRIBUTE_RD(node_name);
SETUP_HOST_ATTRIBUTE_RD(port_name);
+ SETUP_HOST_ATTRIBUTE_RD(permanent_port_name);
SETUP_HOST_ATTRIBUTE_RD(supported_classes);
SETUP_HOST_ATTRIBUTE_RD(supported_fc4s);
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e08462d50c97..59a1c9d9d3bd 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -21,11 +21,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
#include <linux/mempool.h>
+#include <linux/mutex.h>
#include <net/tcp.h>
-
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
@@ -45,11 +43,6 @@ struct iscsi_internal {
*/
struct list_head sessions;
/*
- * lock to serialize access to the sessions list which must
- * be taken after the rx_queue_sema
- */
- spinlock_t session_lock;
- /*
* based on transport capabilities, at register time we set these
* bits to tell the transport class it wants attributes displayed
* in sysfs or that it can support different iSCSI Data-Path
@@ -70,7 +63,7 @@ struct iscsi_internal {
/*
* list of registered transports and lock that must
* be held while accessing list. The iscsi_transport_lock must
- * be acquired after the rx_queue_sema.
+ * be acquired after the rx_queue_mutex.
*/
static LIST_HEAD(iscsi_transports);
static DEFINE_SPINLOCK(iscsi_transport_lock);
@@ -145,7 +138,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
static struct sock *nls;
static int daemon_pid;
-static DECLARE_MUTEX(rx_queue_sema);
+static DEFINE_MUTEX(rx_queue_mutex);
struct mempool_zone {
mempool_t *pool;
@@ -156,7 +149,7 @@ struct mempool_zone {
spinlock_t freelock;
};
-static struct mempool_zone z_reply;
+static struct mempool_zone *z_reply;
/*
* Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time
@@ -171,50 +164,271 @@ static struct mempool_zone z_reply;
#define Z_MAX_ERROR 16
#define Z_HIWAT_ERROR 12
-struct iscsi_if_conn {
- struct list_head conn_list; /* item in connlist */
- struct list_head session_list; /* item in session->connections */
- iscsi_connh_t connh;
- int active; /* must be accessed with the connlock */
- struct Scsi_Host *host; /* originated shost */
- struct device dev; /* sysfs transport/container device */
- struct iscsi_transport *transport;
- struct mempool_zone z_error;
- struct mempool_zone z_pdu;
- struct list_head freequeue;
-};
+static LIST_HEAD(connlist);
+static DEFINE_SPINLOCK(connlock);
-#define iscsi_dev_to_if_conn(_dev) \
- container_of(_dev, struct iscsi_if_conn, dev)
+/*
+ * The following functions can be used by LLDs that allocate
+ * their own scsi_hosts or by software iscsi LLDs
+ */
+static void iscsi_session_release(struct device *dev)
+{
+ struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
+ struct iscsi_transport *transport = session->transport;
+ struct Scsi_Host *shost;
-#define iscsi_cdev_to_if_conn(_cdev) \
- iscsi_dev_to_if_conn(_cdev->dev)
+ shost = iscsi_session_to_shost(session);
+ scsi_host_put(shost);
+ kfree(session);
+ module_put(transport->owner);
+}
-static LIST_HEAD(connlist);
-static DEFINE_SPINLOCK(connlock);
+static int iscsi_is_session_dev(const struct device *dev)
+{
+ return dev->release == iscsi_session_release;
+}
-struct iscsi_if_session {
- struct list_head list; /* item in session_list */
- struct list_head connections;
- iscsi_sessionh_t sessionh;
- struct iscsi_transport *transport;
- struct device dev; /* sysfs transport/container device */
-};
+/**
+ * iscsi_create_session - create iscsi class session
+ * @shost: scsi host
+ * @transport: iscsi transport
+ *
+ * This can be called from a LLD or iscsi_transport
+ **/
+struct iscsi_cls_session *
+iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+{
+ struct iscsi_cls_session *session;
+ int err;
+
+ if (!try_module_get(transport->owner))
+ return NULL;
+
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ goto module_put;
+ session->transport = transport;
+
+ /* this is released in the dev's release function */
+ scsi_host_get(shost);
+ snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+ session->dev.parent = &shost->shost_gendev;
+ session->dev.release = iscsi_session_release;
+ err = device_register(&session->dev);
+ if (err) {
+ dev_printk(KERN_ERR, &session->dev, "iscsi: could not "
+ "register session's dev\n");
+ goto free_session;
+ }
+ transport_register_device(&session->dev);
+
+ return session;
+
+free_session:
+ kfree(session);
+module_put:
+ module_put(transport->owner);
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_session);
+
+/**
+ * iscsi_destroy_session - destroy iscsi session
+ * @session: iscsi_session
+ *
+ * Can be called by a LLD or iscsi_transport. There must not be
+ * any running connections.
+ **/
+int iscsi_destroy_session(struct iscsi_cls_session *session)
+{
+ transport_unregister_device(&session->dev);
+ device_unregister(&session->dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_session);
+
+static void iscsi_conn_release(struct device *dev)
+{
+ struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
+ struct device *parent = conn->dev.parent;
+
+ kfree(conn);
+ put_device(parent);
+}
+
+static int iscsi_is_conn_dev(const struct device *dev)
+{
+ return dev->release == iscsi_conn_release;
+}
+
+/**
+ * iscsi_create_conn - create iscsi class connection
+ * @session: iscsi cls session
+ * @cid: connection id
+ *
+ * This can be called from a LLD or iscsi_transport. The connection
+ * is child of the session so cid must be unique for all connections
+ * on the session.
+ **/
+struct iscsi_cls_conn *
+iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
+{
+ struct iscsi_transport *transport = session->transport;
+ struct Scsi_Host *shost = iscsi_session_to_shost(session);
+ struct iscsi_cls_conn *conn;
+ int err;
+
+ conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL);
+ if (!conn)
+ return NULL;
+
+ if (transport->conndata_size)
+ conn->dd_data = &conn[1];
+
+ INIT_LIST_HEAD(&conn->conn_list);
+ conn->transport = transport;
+
+ /* this is released in the dev's release function */
+ if (!get_device(&session->dev))
+ goto free_conn;
+ snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+ shost->host_no, cid);
+ conn->dev.parent = &session->dev;
+ conn->dev.release = iscsi_conn_release;
+ err = device_register(&conn->dev);
+ if (err) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: could not register "
+ "connection's dev\n");
+ goto release_parent_ref;
+ }
+ transport_register_device(&conn->dev);
+ return conn;
+
+release_parent_ref:
+ put_device(&session->dev);
+free_conn:
+ kfree(conn);
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_create_conn);
+
+/**
+ * iscsi_destroy_conn - destroy iscsi class connection
+ * @session: iscsi cls session
+ *
+ * This can be called from a LLD or iscsi_transport.
+ **/
+int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+{
+ transport_unregister_device(&conn->dev);
+ device_unregister(&conn->dev);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+
+/*
+ * These functions are used only by software iscsi_transports
+ * which do not allocate and more their scsi_hosts since this
+ * is initiated from userspace.
+ */
+
+/*
+ * iSCSI Session's hostdata organization:
+ *
+ * *------------------* <== hostdata_session(host->hostdata)
+ * | ptr to class sess|
+ * |------------------| <== iscsi_hostdata(host->hostdata)
+ * | transport's data |
+ * *------------------*
+ */
+
+#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
+ _t->hostdata_size % sizeof(unsigned long))
+
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_transport_create_session - create iscsi cls session and host
+ * scsit: scsi transport template
+ * transport: iscsi transport template
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+struct Scsi_Host *
+iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ struct iscsi_transport *transport)
+{
+ struct iscsi_cls_session *session;
+ struct Scsi_Host *shost;
+
+ shost = scsi_host_alloc(transport->host_template,
+ hostdata_privsize(transport));
+ if (!shost) {
+ printk(KERN_ERR "iscsi: can not allocate SCSI host for "
+ "session\n");
+ return NULL;
+ }
+
+ shost->max_id = 1;
+ shost->max_channel = 0;
+ shost->max_lun = transport->max_lun;
+ shost->max_cmd_len = transport->max_cmd_len;
+ shost->transportt = scsit;
+ shost->transportt->create_work_queue = 1;
+
+ if (scsi_add_host(shost, NULL))
+ goto free_host;
+
+ session = iscsi_create_session(shost, transport);
+ if (!session)
+ goto remove_host;
-#define iscsi_dev_to_if_session(_dev) \
- container_of(_dev, struct iscsi_if_session, dev)
+ *(unsigned long*)shost->hostdata = (unsigned long)session;
+ return shost;
+
+remove_host:
+ scsi_remove_host(shost);
+free_host:
+ scsi_host_put(shost);
+ return NULL;
+}
-#define iscsi_cdev_to_if_session(_cdev) \
- iscsi_dev_to_if_session(_cdev->dev)
+EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
-#define iscsi_if_session_to_shost(_session) \
- dev_to_shost(_session->dev.parent)
+/**
+ * iscsi_transport_destroy_session - destroy session and scsi host
+ * shost: scsi host
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+int iscsi_transport_destroy_session(struct Scsi_Host *shost)
+{
+ struct iscsi_cls_session *session;
-static struct iscsi_if_conn*
+ scsi_remove_host(shost);
+ session = hostdata_session(shost->hostdata);
+ iscsi_destroy_session(session);
+ /* ref from host alloc */
+ scsi_host_put(shost);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
+
+/*
+ * iscsi interface functions
+ */
+static struct iscsi_cls_conn*
iscsi_if_find_conn(uint64_t key)
{
unsigned long flags;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
spin_lock_irqsave(&connlock, flags);
list_for_each_entry(conn, &connlist, conn_list)
@@ -249,7 +463,7 @@ static inline struct list_head *skb_to_lh(struct sk_buff *skb)
}
static void*
-mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data)
+mempool_zone_alloc_skb(unsigned int gfp_mask, void *pool_data)
{
struct mempool_zone *zone = pool_data;
@@ -281,14 +495,21 @@ mempool_zone_complete(struct mempool_zone *zone)
spin_unlock_irqrestore(&zone->freelock, flags);
}
-static int
-mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
- unsigned hiwat)
+static struct mempool_zone *
+mempool_zone_init(unsigned max, unsigned size, unsigned hiwat)
{
+ struct mempool_zone *zp;
+
+ zp = kzalloc(sizeof(*zp), GFP_KERNEL);
+ if (!zp)
+ return NULL;
+
zp->pool = mempool_create(max, mempool_zone_alloc_skb,
mempool_zone_free_skb, zp);
- if (!zp->pool)
- return -ENOMEM;
+ if (!zp->pool) {
+ kfree(zp);
+ return NULL;
+ }
zp->size = size;
zp->hiwat = hiwat;
@@ -297,9 +518,14 @@ mempool_zone_init(struct mempool_zone *zp, unsigned max, unsigned size,
spin_lock_init(&zp->freelock);
atomic_set(&zp->allocated, 0);
- return 0;
+ return zp;
}
+static void mempool_zone_destroy(struct mempool_zone *zp)
+{
+ mempool_destroy(zp->pool);
+ kfree(zp);
+}
static struct sk_buff*
mempool_zone_get_skb(struct mempool_zone *zone)
@@ -339,7 +565,7 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
char *pdu;
int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
data_size);
@@ -347,13 +573,13 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
conn = iscsi_if_find_conn(connh);
BUG_ON(!conn);
- mempool_zone_complete(&conn->z_pdu);
+ mempool_zone_complete(conn->z_pdu);
- skb = mempool_zone_get_skb(&conn->z_pdu);
+ skb = mempool_zone_get_skb(conn->z_pdu);
if (!skb) {
iscsi_conn_error(connh, ISCSI_ERR_CONN_FAILED);
- printk(KERN_ERR "iscsi%d: can not deliver control PDU: OOM\n",
- conn->host->host_no);
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver "
+ "control PDU: OOM\n");
return -ENOMEM;
}
@@ -362,14 +588,14 @@ int iscsi_recv_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr,
memset(ev, 0, sizeof(*ev));
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_RECV_PDU;
- if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
+ if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
ev->iferror = -ENOMEM;
ev->r.recv_req.conn_handle = connh;
pdu = (char*)ev + sizeof(*ev);
memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
- return iscsi_unicast_skb(&conn->z_pdu, skb);
+ return iscsi_unicast_skb(conn->z_pdu, skb);
}
EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
@@ -378,18 +604,18 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
struct nlmsghdr *nlh;
struct sk_buff *skb;
struct iscsi_uevent *ev;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
int len = NLMSG_SPACE(sizeof(*ev));
conn = iscsi_if_find_conn(connh);
BUG_ON(!conn);
- mempool_zone_complete(&conn->z_error);
+ mempool_zone_complete(conn->z_error);
- skb = mempool_zone_get_skb(&conn->z_error);
+ skb = mempool_zone_get_skb(conn->z_error);
if (!skb) {
- printk(KERN_ERR "iscsi%d: gracefully ignored conn error (%d)\n",
- conn->host->host_no, error);
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored "
+ "conn error (%d)\n", error);
return;
}
@@ -397,15 +623,15 @@ void iscsi_conn_error(iscsi_connh_t connh, enum iscsi_err error)
ev = NLMSG_DATA(nlh);
ev->transport_handle = iscsi_handle(conn->transport);
ev->type = ISCSI_KEVENT_CONN_ERROR;
- if (atomic_read(&conn->z_error.allocated) >= conn->z_error.hiwat)
+ if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
ev->iferror = -ENOMEM;
ev->r.connerror.error = error;
ev->r.connerror.conn_handle = connh;
- iscsi_unicast_skb(&conn->z_error, skb);
+ iscsi_unicast_skb(conn->z_error, skb);
- printk(KERN_INFO "iscsi%d: detected conn error (%d)\n",
- conn->host->host_no, error);
+ dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
+ error);
}
EXPORT_SYMBOL_GPL(iscsi_conn_error);
@@ -419,9 +645,9 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
int flags = multi ? NLM_F_MULTI : 0;
int t = done ? NLMSG_DONE : type;
- mempool_zone_complete(&z_reply);
+ mempool_zone_complete(z_reply);
- skb = mempool_zone_get_skb(&z_reply);
+ skb = mempool_zone_get_skb(z_reply);
/*
* FIXME:
* user is supposed to react on iferror == -ENOMEM;
@@ -432,366 +658,197 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi,
nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
nlh->nlmsg_flags = flags;
memcpy(NLMSG_DATA(nlh), payload, size);
- return iscsi_unicast_skb(&z_reply, skb);
+ return iscsi_unicast_skb(z_reply, skb);
}
-/*
- * iSCSI Session's hostdata organization:
- *
- * *------------------* <== host->hostdata
- * | transport |
- * |------------------| <== iscsi_hostdata(host->hostdata)
- * | transport's data |
- * |------------------| <== hostdata_session(host->hostdata)
- * | interface's data |
- * *------------------*
- */
+static int
+iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
+ struct nlmsghdr *nlh)
+{
+ struct iscsi_uevent *ev = NLMSG_DATA(nlh);
+ struct iscsi_stats *stats;
+ struct sk_buff *skbstat;
+ struct iscsi_cls_conn *conn;
+ struct nlmsghdr *nlhstat;
+ struct iscsi_uevent *evstat;
+ int len = NLMSG_SPACE(sizeof(*ev) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ ISCSI_STATS_CUSTOM_MAX);
+ int err = 0;
-#define hostdata_privsize(_t) (sizeof(unsigned long) + _t->hostdata_size + \
- _t->hostdata_size % sizeof(unsigned long) + \
- sizeof(struct iscsi_if_session))
+ conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
+ if (!conn)
+ return -EEXIST;
-#define hostdata_session(_hostdata) ((void*)_hostdata + sizeof(unsigned long) + \
- ((struct iscsi_transport *) \
- iscsi_ptr(*(uint64_t *)_hostdata))->hostdata_size)
+ do {
+ int actual_size;
-static void iscsi_if_session_dev_release(struct device *dev)
-{
- struct iscsi_if_session *session = iscsi_dev_to_if_session(dev);
- struct iscsi_transport *transport = session->transport;
- struct Scsi_Host *shost = iscsi_if_session_to_shost(session);
- struct iscsi_if_conn *conn, *tmp;
- unsigned long flags;
+ mempool_zone_complete(conn->z_pdu);
- /* now free connections */
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry_safe(conn, tmp, &session->connections,
- session_list) {
- list_del(&conn->session_list);
- mempool_destroy(conn->z_pdu.pool);
- mempool_destroy(conn->z_error.pool);
- kfree(conn);
- }
- spin_unlock_irqrestore(&connlock, flags);
- scsi_host_put(shost);
- module_put(transport->owner);
+ skbstat = mempool_zone_get_skb(conn->z_pdu);
+ if (!skbstat) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not "
+ "deliver stats: OOM\n");
+ return -ENOMEM;
+ }
+
+ nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
+ (len - sizeof(*nlhstat)), 0);
+ evstat = NLMSG_DATA(nlhstat);
+ memset(evstat, 0, sizeof(*evstat));
+ evstat->transport_handle = iscsi_handle(conn->transport);
+ evstat->type = nlh->nlmsg_type;
+ if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
+ evstat->iferror = -ENOMEM;
+ evstat->u.get_stats.conn_handle =
+ ev->u.get_stats.conn_handle;
+ stats = (struct iscsi_stats *)
+ ((char*)evstat + sizeof(*evstat));
+ memset(stats, 0, sizeof(*stats));
+
+ transport->get_stats(ev->u.get_stats.conn_handle, stats);
+ actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
+ sizeof(struct iscsi_stats) +
+ sizeof(struct iscsi_stats_custom) *
+ stats->custom_length);
+ actual_size -= sizeof(*nlhstat);
+ actual_size = NLMSG_LENGTH(actual_size);
+ skb_trim(skb, NLMSG_ALIGN(actual_size));
+ nlhstat->nlmsg_len = actual_size;
+
+ err = iscsi_unicast_skb(conn->z_pdu, skbstat);
+ } while (err < 0 && err != -ECONNREFUSED);
+
+ return err;
}
static int
iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
- struct iscsi_if_session *session;
struct Scsi_Host *shost;
- unsigned long flags;
- int error;
-
- if (!try_module_get(transport->owner))
- return -EPERM;
- shost = scsi_host_alloc(transport->host_template,
- hostdata_privsize(transport));
- if (!shost) {
- ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
- printk(KERN_ERR "iscsi: can not allocate SCSI host for "
- "session\n");
- error = -ENOMEM;
- goto out_module_put;
- }
- shost->max_id = 1;
- shost->max_channel = 0;
- shost->max_lun = transport->max_lun;
- shost->max_cmd_len = transport->max_cmd_len;
- shost->transportt = &priv->t;
-
- /* store struct iscsi_transport in hostdata */
- *(uint64_t*)shost->hostdata = ev->transport_handle;
+ if (!transport->create_session)
+ return -EINVAL;
- ev->r.c_session_ret.session_handle = transport->create_session(
- ev->u.c_session.initial_cmdsn, shost);
- if (ev->r.c_session_ret.session_handle == iscsi_handle(NULL)) {
- error = 0;
- goto out_host_put;
- }
+ shost = transport->create_session(&priv->t,
+ ev->u.c_session.initial_cmdsn);
+ if (!shost)
+ return -ENOMEM;
- /* host_no becomes assigned SID */
+ ev->r.c_session_ret.session_handle = iscsi_handle(iscsi_hostdata(shost->hostdata));
ev->r.c_session_ret.sid = shost->host_no;
- /* initialize session */
- session = hostdata_session(shost->hostdata);
- INIT_LIST_HEAD(&session->connections);
- INIT_LIST_HEAD(&session->list);
- session->sessionh = ev->r.c_session_ret.session_handle;
- session->transport = transport;
-
- error = scsi_add_host(shost, NULL);
- if (error)
- goto out_destroy_session;
-
- /*
- * this is released in the dev's release function)
- */
- scsi_host_get(shost);
- snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
- session->dev.parent = &shost->shost_gendev;
- session->dev.release = iscsi_if_session_dev_release;
- error = device_register(&session->dev);
- if (error) {
- printk(KERN_ERR "iscsi: could not register session%d's dev\n",
- shost->host_no);
- goto out_remove_host;
- }
- transport_register_device(&session->dev);
-
- /* add this session to the list of active sessions */
- spin_lock_irqsave(&priv->session_lock, flags);
- list_add(&session->list, &priv->sessions);
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
return 0;
-
-out_remove_host:
- scsi_remove_host(shost);
-out_destroy_session:
- transport->destroy_session(ev->r.c_session_ret.session_handle);
- ev->r.c_session_ret.session_handle = iscsi_handle(NULL);
-out_host_put:
- scsi_host_put(shost);
-out_module_put:
- module_put(transport->owner);
- return error;
}
static int
iscsi_if_destroy_session(struct iscsi_internal *priv, struct iscsi_uevent *ev)
{
struct iscsi_transport *transport = priv->iscsi_transport;
+
struct Scsi_Host *shost;
- struct iscsi_if_session *session;
- unsigned long flags;
- struct iscsi_if_conn *conn;
- int error = 0;
+
+ if (!transport->destroy_session)
+ return -EINVAL;
shost = scsi_host_lookup(ev->u.d_session.sid);
if (shost == ERR_PTR(-ENXIO))
return -EEXIST;
- session = hostdata_session(shost->hostdata);
- /* check if we have active connections */
- spin_lock_irqsave(&connlock, flags);
- list_for_each_entry(conn, &session->connections, session_list) {
- if (conn->active) {
- printk(KERN_ERR "iscsi%d: can not destroy session: "
- "has active connection (%p)\n",
- shost->host_no, iscsi_ptr(conn->connh));
- spin_unlock_irqrestore(&connlock, flags);
- error = EIO;
- goto out_release_ref;
- }
- }
- spin_unlock_irqrestore(&connlock, flags);
-
- scsi_remove_host(shost);
- transport->destroy_session(ev->u.d_session.session_handle);
- transport_unregister_device(&session->dev);
- device_unregister(&session->dev);
-
- /* remove this session from the list of active sessions */
- spin_lock_irqsave(&priv->session_lock, flags);
- list_del(&session->list);
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
- /* ref from host alloc */
- scsi_host_put(shost);
-out_release_ref:
- /* ref from host lookup */
- scsi_host_put(shost);
- return error;
-}
-
-static void iscsi_if_conn_dev_release(struct device *dev)
-{
- struct iscsi_if_conn *conn = iscsi_dev_to_if_conn(dev);
- struct Scsi_Host *shost = conn->host;
-
- scsi_host_put(shost);
+ if (transport->destroy_session)
+ transport->destroy_session(shost);
+ /* ref from host lookup */
+ scsi_host_put(shost);
+ return 0;
}
static int
-iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
-{
- struct iscsi_if_session *session;
+iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev){
struct Scsi_Host *shost;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
unsigned long flags;
- int error;
+
+ if (!transport->create_conn)
+ return -EINVAL;
shost = scsi_host_lookup(ev->u.c_conn.sid);
if (shost == ERR_PTR(-ENXIO))
return -EEXIST;
- session = hostdata_session(shost->hostdata);
- conn = kmalloc(sizeof(struct iscsi_if_conn), GFP_KERNEL);
- if (!conn) {
- error = -ENOMEM;
- goto out_release_ref;
- }
- memset(conn, 0, sizeof(struct iscsi_if_conn));
- INIT_LIST_HEAD(&conn->session_list);
- INIT_LIST_HEAD(&conn->conn_list);
- conn->host = shost;
- conn->transport = transport;
+ conn = transport->create_conn(shost, ev->u.c_conn.cid);
+ if (!conn)
+ goto release_ref;
- error = mempool_zone_init(&conn->z_pdu, Z_MAX_PDU,
+ conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
NLMSG_SPACE(sizeof(struct iscsi_uevent) +
sizeof(struct iscsi_hdr) +
DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH),
Z_HIWAT_PDU);
- if (error) {
- printk(KERN_ERR "iscsi%d: can not allocate pdu zone for new "
- "conn\n", shost->host_no);
- goto out_free_conn;
+ if (!conn->z_pdu) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+ "pdu zone for new conn\n");
+ goto destroy_conn;
}
- error = mempool_zone_init(&conn->z_error, Z_MAX_ERROR,
+
+ conn->z_error = mempool_zone_init(Z_MAX_ERROR,
NLMSG_SPACE(sizeof(struct iscsi_uevent)),
Z_HIWAT_ERROR);
- if (error) {
- printk(KERN_ERR "iscsi%d: can not allocate error zone for "
- "new conn\n", shost->host_no);
- goto out_free_pdu_pool;
- }
-
- ev->r.handle = transport->create_conn(ev->u.c_conn.session_handle,
- ev->u.c_conn.cid);
- if (!ev->r.handle) {
- error = -ENODEV;
- goto out_free_error_pool;
+ if (!conn->z_error) {
+ dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate "
+ "error zone for new conn\n");
+ goto free_pdu_pool;
}
- conn->connh = ev->r.handle;
-
- /*
- * this is released in the dev's release function
- */
- if (!scsi_host_get(shost))
- goto out_destroy_conn;
- snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
- shost->host_no, ev->u.c_conn.cid);
- conn->dev.parent = &session->dev;
- conn->dev.release = iscsi_if_conn_dev_release;
- error = device_register(&conn->dev);
- if (error) {
- printk(KERN_ERR "iscsi%d: could not register connections%u "
- "dev\n", shost->host_no, ev->u.c_conn.cid);
- goto out_release_parent_ref;
- }
- transport_register_device(&conn->dev);
+ ev->r.handle = conn->connh = iscsi_handle(conn->dd_data);
spin_lock_irqsave(&connlock, flags);
list_add(&conn->conn_list, &connlist);
- list_add(&conn->session_list, &session->connections);
conn->active = 1;
spin_unlock_irqrestore(&connlock, flags);
scsi_host_put(shost);
return 0;
-out_release_parent_ref:
+free_pdu_pool:
+ mempool_zone_destroy(conn->z_pdu);
+destroy_conn:
+ if (transport->destroy_conn)
+ transport->destroy_conn(conn->dd_data);
+release_ref:
scsi_host_put(shost);
-out_destroy_conn:
- transport->destroy_conn(ev->r.handle);
-out_free_error_pool:
- mempool_destroy(conn->z_error.pool);
-out_free_pdu_pool:
- mempool_destroy(conn->z_pdu.pool);
-out_free_conn:
- kfree(conn);
-out_release_ref:
- scsi_host_put(shost);
- return error;
+ return -ENOMEM;
}
static int
iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
{
unsigned long flags;
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
+ struct mempool_zone *z_error, *z_pdu;
conn = iscsi_if_find_conn(ev->u.d_conn.conn_handle);
if (!conn)
return -EEXIST;
- transport->destroy_conn(ev->u.d_conn.conn_handle);
+ if (!transport->destroy_conn)
+ return -EINVAL;
spin_lock_irqsave(&connlock, flags);
conn->active = 0;
list_del(&conn->conn_list);
spin_unlock_irqrestore(&connlock, flags);
- transport_unregister_device(&conn->dev);
- device_unregister(&conn->dev);
- return 0;
-}
-
-static int
-iscsi_if_get_stats(struct iscsi_transport *transport, struct sk_buff *skb,
- struct nlmsghdr *nlh)
-{
- struct iscsi_uevent *ev = NLMSG_DATA(nlh);
- struct iscsi_stats *stats;
- struct sk_buff *skbstat;
- struct iscsi_if_conn *conn;
- struct nlmsghdr *nlhstat;
- struct iscsi_uevent *evstat;
- int len = NLMSG_SPACE(sizeof(*ev) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- ISCSI_STATS_CUSTOM_MAX);
- int err = 0;
-
- conn = iscsi_if_find_conn(ev->u.get_stats.conn_handle);
- if (!conn)
- return -EEXIST;
-
- do {
- int actual_size;
-
- mempool_zone_complete(&conn->z_pdu);
-
- skbstat = mempool_zone_get_skb(&conn->z_pdu);
- if (!skbstat) {
- printk(KERN_ERR "iscsi%d: can not deliver stats: OOM\n",
- conn->host->host_no);
- return -ENOMEM;
- }
-
- nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
- (len - sizeof(*nlhstat)), 0);
- evstat = NLMSG_DATA(nlhstat);
- memset(evstat, 0, sizeof(*evstat));
- evstat->transport_handle = iscsi_handle(conn->transport);
- evstat->type = nlh->nlmsg_type;
- if (atomic_read(&conn->z_pdu.allocated) >= conn->z_pdu.hiwat)
- evstat->iferror = -ENOMEM;
- evstat->u.get_stats.conn_handle =
- ev->u.get_stats.conn_handle;
- stats = (struct iscsi_stats *)
- ((char*)evstat + sizeof(*evstat));
- memset(stats, 0, sizeof(*stats));
+ z_pdu = conn->z_pdu;
+ z_error = conn->z_error;
- transport->get_stats(ev->u.get_stats.conn_handle, stats);
- actual_size = NLMSG_SPACE(sizeof(struct iscsi_uevent) +
- sizeof(struct iscsi_stats) +
- sizeof(struct iscsi_stats_custom) *
- stats->custom_length);
- actual_size -= sizeof(*nlhstat);
- actual_size = NLMSG_LENGTH(actual_size);
- skb_trim(skb, NLMSG_ALIGN(actual_size));
- nlhstat->nlmsg_len = actual_size;
+ if (transport->destroy_conn)
+ transport->destroy_conn(conn);
- err = iscsi_unicast_skb(&conn->z_pdu, skbstat);
- } while (err < 0 && err != -ECONNREFUSED);
+ mempool_zone_destroy(z_pdu);
+ mempool_zone_destroy(z_error);
- return err;
+ return 0;
}
static int
@@ -881,7 +938,7 @@ iscsi_if_rx(struct sock *sk, int len)
{
struct sk_buff *skb;
- down(&rx_queue_sema);
+ mutex_lock(&rx_queue_mutex);
while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
while (skb->len >= NLMSG_SPACE(0)) {
int err;
@@ -915,17 +972,20 @@ iscsi_if_rx(struct sock *sk, int len)
err = iscsi_if_send_reply(
NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq,
nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
- if (atomic_read(&z_reply.allocated) >=
- z_reply.hiwat)
+ if (atomic_read(&z_reply->allocated) >=
+ z_reply->hiwat)
ev->iferror = -ENOMEM;
} while (err < 0 && err != -ECONNREFUSED);
skb_pull(skb, rlen);
}
kfree_skb(skb);
}
- up(&rx_queue_sema);
+ mutex_unlock(&rx_queue_mutex);
}
+#define iscsi_cdev_to_conn(_cdev) \
+ iscsi_dev_to_conn(_cdev->dev)
+
/*
* iSCSI connection attrs
*/
@@ -934,12 +994,10 @@ static ssize_t \
show_conn_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
- struct iscsi_if_conn *conn = iscsi_cdev_to_if_conn(cdev); \
- struct iscsi_internal *priv; \
+ struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev); \
+ struct iscsi_transport *t = conn->transport; \
\
- priv = to_iscsi_internal(conn->host->transportt); \
- if (priv->param_mask & (1 << param)) \
- priv->iscsi_transport->get_param(conn->connh, param, &value); \
+ t->get_conn_param(conn->dd_data, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -954,6 +1012,9 @@ iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+#define iscsi_cdev_to_session(_cdev) \
+ iscsi_dev_to_session(_cdev->dev)
+
/*
* iSCSI session attrs
*/
@@ -962,20 +1023,11 @@ static ssize_t \
show_session_int_param_##param(struct class_device *cdev, char *buf) \
{ \
uint32_t value = 0; \
- struct iscsi_if_session *session = iscsi_cdev_to_if_session(cdev); \
- struct Scsi_Host *shost = iscsi_if_session_to_shost(session); \
- struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
- struct iscsi_if_conn *conn = NULL; \
- unsigned long flags; \
- \
- spin_lock_irqsave(&connlock, flags); \
- if (!list_empty(&session->connections)) \
- conn = list_entry(session->connections.next, \
- struct iscsi_if_conn, session_list); \
- spin_unlock_irqrestore(&connlock, flags); \
+ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct Scsi_Host *shost = iscsi_session_to_shost(session); \
+ struct iscsi_transport *t = session->transport; \
\
- if (conn && (priv->param_mask & (1 << param))) \
- priv->iscsi_transport->get_param(conn->connh, param, &value);\
+ t->get_session_param(shost, param, &value); \
return snprintf(buf, 20, format"\n", value); \
}
@@ -1004,23 +1056,18 @@ iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
count++; \
}
-static int iscsi_is_session_dev(const struct device *dev)
-{
- return dev->release == iscsi_if_session_dev_release;
-}
-
static int iscsi_session_match(struct attribute_container *cont,
struct device *dev)
{
- struct iscsi_if_session *session;
+ struct iscsi_cls_session *session;
struct Scsi_Host *shost;
struct iscsi_internal *priv;
if (!iscsi_is_session_dev(dev))
return 0;
- session = iscsi_dev_to_if_session(dev);
- shost = iscsi_if_session_to_shost(session);
+ session = iscsi_dev_to_session(dev);
+ shost = iscsi_session_to_shost(session);
if (!shost->transportt)
return 0;
@@ -1031,23 +1078,21 @@ static int iscsi_session_match(struct attribute_container *cont,
return &priv->session_cont.ac == cont;
}
-static int iscsi_is_conn_dev(const struct device *dev)
-{
- return dev->release == iscsi_if_conn_dev_release;
-}
-
static int iscsi_conn_match(struct attribute_container *cont,
struct device *dev)
{
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_session *session;
+ struct iscsi_cls_conn *conn;
struct Scsi_Host *shost;
struct iscsi_internal *priv;
if (!iscsi_is_conn_dev(dev))
return 0;
- conn = iscsi_dev_to_if_conn(dev);
- shost = conn->host;
+ conn = iscsi_dev_to_conn(dev);
+ session = iscsi_dev_to_session(conn->dev.parent);
+ shost = iscsi_session_to_shost(session);
+
if (!shost->transportt)
return 0;
@@ -1058,7 +1103,8 @@ static int iscsi_conn_match(struct attribute_container *cont,
return &priv->conn_cont.ac == cont;
}
-int iscsi_register_transport(struct iscsi_transport *tt)
+struct scsi_transport_template *
+iscsi_register_transport(struct iscsi_transport *tt)
{
struct iscsi_internal *priv;
unsigned long flags;
@@ -1068,15 +1114,14 @@ int iscsi_register_transport(struct iscsi_transport *tt)
priv = iscsi_if_transport_lookup(tt);
if (priv)
- return -EEXIST;
+ return NULL;
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
- return -ENOMEM;
+ return NULL;
memset(priv, 0, sizeof(*priv));
INIT_LIST_HEAD(&priv->list);
INIT_LIST_HEAD(&priv->sessions);
- spin_lock_init(&priv->session_lock);
priv->iscsi_transport = tt;
priv->cdev.class = &iscsi_transport_class;
@@ -1142,13 +1187,13 @@ int iscsi_register_transport(struct iscsi_transport *tt)
spin_unlock_irqrestore(&iscsi_transport_lock, flags);
printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
- return 0;
+ return &priv->t;
unregister_cdev:
class_device_unregister(&priv->cdev);
free_priv:
kfree(priv);
- return err;
+ return NULL;
}
EXPORT_SYMBOL_GPL(iscsi_register_transport);
@@ -1159,19 +1204,11 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
BUG_ON(!tt);
- down(&rx_queue_sema);
+ mutex_lock(&rx_queue_mutex);
priv = iscsi_if_transport_lookup(tt);
BUG_ON (!priv);
- spin_lock_irqsave(&priv->session_lock, flags);
- if (!list_empty(&priv->sessions)) {
- spin_unlock_irqrestore(&priv->session_lock, flags);
- up(&rx_queue_sema);
- return -EPERM;
- }
- spin_unlock_irqrestore(&priv->session_lock, flags);
-
spin_lock_irqsave(&iscsi_transport_lock, flags);
list_del(&priv->list);
spin_unlock_irqrestore(&iscsi_transport_lock, flags);
@@ -1181,7 +1218,7 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
class_device_unregister(&priv->cdev);
- up(&rx_queue_sema);
+ mutex_unlock(&rx_queue_mutex);
return 0;
}
@@ -1194,14 +1231,14 @@ iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr)
if (event == NETLINK_URELEASE &&
n->protocol == NETLINK_ISCSI && n->pid) {
- struct iscsi_if_conn *conn;
+ struct iscsi_cls_conn *conn;
unsigned long flags;
- mempool_zone_complete(&z_reply);
+ mempool_zone_complete(z_reply);
spin_lock_irqsave(&connlock, flags);
list_for_each_entry(conn, &connlist, conn_list) {
- mempool_zone_complete(&conn->z_error);
- mempool_zone_complete(&conn->z_pdu);
+ mempool_zone_complete(conn->z_error);
+ mempool_zone_complete(conn->z_pdu);
}
spin_unlock_irqrestore(&connlock, flags);
}
@@ -1234,15 +1271,15 @@ static __init int iscsi_transport_init(void)
goto unregister_session_class;
nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx,
- THIS_MODULE);
+ THIS_MODULE);
if (!nls) {
err = -ENOBUFS;
goto unregister_notifier;
}
- err = mempool_zone_init(&z_reply, Z_MAX_REPLY,
+ z_reply = mempool_zone_init(Z_MAX_REPLY,
NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY);
- if (!err)
+ if (z_reply)
return 0;
sock_release(nls->sk_socket);
@@ -1259,7 +1296,7 @@ unregister_transport_class:
static void __exit iscsi_transport_exit(void)
{
- mempool_destroy(z_reply.pool);
+ mempool_zone_destroy(z_reply);
sock_release(nls->sk_socket);
netlink_unregister_notifier(&iscsi_nl_notifier);
transport_class_unregister(&iscsi_connection_class);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index edabbd05d258..a3e0b7bc2d7b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/string.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@@ -62,7 +63,7 @@ struct sas_internal {
struct sas_host_attrs {
struct list_head rphy_list;
- spinlock_t lock;
+ struct mutex lock;
u32 next_target_id;
};
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
@@ -165,7 +166,7 @@ static int sas_host_setup(struct transport_container *tc, struct device *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);
+ mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
return 0;
}
@@ -626,7 +627,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
transport_add_device(&rphy->dev);
transport_configure_device(&rphy->dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_add_tail(&rphy->list, &sas_host->rphy_list);
if (identify->device_type == SAS_END_DEVICE &&
(identify->target_port_protocols &
@@ -634,10 +635,10 @@ int sas_rphy_add(struct sas_rphy *rphy)
rphy->scsi_target_id = sas_host->next_target_id++;
else
rphy->scsi_target_id = -1;
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
if (rphy->scsi_target_id != -1) {
- scsi_scan_target(&rphy->dev, parent->number,
+ scsi_scan_target(&rphy->dev, parent->port_identifier,
rphy->scsi_target_id, ~0, 0);
}
@@ -661,9 +662,9 @@ 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);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
transport_destroy_device(&rphy->dev);
put_device(rphy->dev.parent);
@@ -687,15 +688,27 @@ sas_rphy_delete(struct sas_rphy *rphy)
struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
- scsi_remove_target(dev);
+ switch (rphy->identify.device_type) {
+ case SAS_END_DEVICE:
+ scsi_remove_target(dev);
+ break;
+ case SAS_EDGE_EXPANDER_DEVICE:
+ case SAS_FANOUT_EXPANDER_DEVICE:
+ device_for_each_child(dev, NULL, do_sas_phy_delete);
+ break;
+ default:
+ break;
+ }
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
+
+ parent->rphy = NULL;
put_device(&parent->dev);
}
@@ -719,23 +732,28 @@ EXPORT_SYMBOL(scsi_is_sas_rphy);
* SCSI scan helper
*/
-static struct device *sas_target_parent(struct Scsi_Host *shost,
- int channel, uint id)
+static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ uint id, uint lun)
{
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
struct sas_rphy *rphy;
- struct device *dev = NULL;
- spin_lock(&sas_host->lock);
+ mutex_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;
+
+ if (rphy->scsi_target_id == -1)
+ continue;
+
+ if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
+ (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
+ scsi_scan_target(&rphy->dev, parent->port_identifier,
+ rphy->scsi_target_id, lun, 1);
+ }
}
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
- return dev;
+ return 0;
}
@@ -780,7 +798,7 @@ sas_attach_transport(struct sas_function_template *ft)
return NULL;
memset(i, 0, sizeof(struct sas_internal));
- i->t.target_parent = sas_target_parent;
+ i->t.user_scan = sas_user_scan;
i->t.host_attrs.ac.attrs = &i->host_attrs[0];
i->t.host_attrs.ac.class = &sas_host_class.class;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 38a53b5f9e9a..7ee95eb83dda 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -18,12 +18,13 @@
* 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/ctype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/blkdev.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include <scsi/scsi.h>
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
@@ -47,7 +48,7 @@
/* Private data accessors (keep these out of the header file) */
#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
-#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)
+#define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex)
struct spi_internal {
struct scsi_transport_template t;
@@ -241,7 +242,7 @@ static int spi_setup_transport_attrs(struct transport_container *tc,
spi_hold_mcs(starget) = 0;
spi_dv_pending(starget) = 0;
spi_initial_dv(starget) = 0;
- init_MUTEX(&spi_dv_sem(starget));
+ mutex_init(&spi_dv_mutex(starget));
return 0;
}
@@ -378,9 +379,7 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
/* Translate the period into ns according to the current spec
* for SDTR/PPR messages */
-static ssize_t
-show_spi_transport_period_helper(struct class_device *cdev, char *buf,
- int period)
+static int period_to_str(char *buf, int period)
{
int len, picosec;
@@ -398,6 +397,14 @@ show_spi_transport_period_helper(struct class_device *cdev, char *buf,
len = sprint_frac(buf, picosec, 1000);
}
+ return len;
+}
+
+static ssize_t
+show_spi_transport_period_helper(struct class_device *cdev, char *buf,
+ int period)
+{
+ int len = period_to_str(buf, period);
buf[len++] = '\n';
buf[len] = '\0';
return len;
@@ -908,7 +915,7 @@ spi_dv_device(struct scsi_device *sdev)
scsi_target_quiesce(starget);
spi_dv_pending(starget) = 1;
- down(&spi_dv_sem(starget));
+ mutex_lock(&spi_dv_mutex(starget));
starget_printk(KERN_INFO, starget, "Beginning Domain Validation\n");
@@ -916,7 +923,7 @@ spi_dv_device(struct scsi_device *sdev)
starget_printk(KERN_INFO, starget, "Ending Domain Validation\n");
- up(&spi_dv_sem(starget));
+ mutex_unlock(&spi_dv_mutex(starget));
spi_dv_pending(starget) = 0;
scsi_target_resume(starget);
@@ -1041,12 +1048,133 @@ void spi_display_xfer_agreement(struct scsi_target *starget)
tp->hold_mcs ? " HMCS" : "",
tmp, tp->offset);
} else {
- dev_info(&starget->dev, "%sasynchronous.\n",
+ dev_info(&starget->dev, "%sasynchronous\n",
tp->width ? "wide " : "");
}
}
EXPORT_SYMBOL(spi_display_xfer_agreement);
+#ifdef CONFIG_SCSI_CONSTANTS
+static const char * const one_byte_msgs[] = {
+/* 0x00 */ "Command Complete", NULL, "Save Pointers",
+/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error",
+/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
+/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
+/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue",
+/* 0x0f */ "Initiate Recovery", "Release Recovery"
+};
+
+static const char * const two_byte_msgs[] = {
+/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag",
+/* 0x23 */ "Ignore Wide Residue"
+};
+
+static const char * const extended_msgs[] = {
+/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
+/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request",
+/* 0x04 */ "Parallel Protocol Request"
+};
+
+static void print_nego(const unsigned char *msg, int per, int off, int width)
+{
+ if (per) {
+ char buf[20];
+ period_to_str(buf, msg[per]);
+ printk("period = %s ns ", buf);
+ }
+
+ if (off)
+ printk("offset = %d ", msg[off]);
+ if (width)
+ printk("width = %d ", 8 << msg[width]);
+}
+
+int spi_print_msg(const unsigned char *msg)
+{
+ int len = 0, i;
+ if (msg[0] == EXTENDED_MESSAGE) {
+ len = 3 + msg[1];
+ if (msg[2] < ARRAY_SIZE(extended_msgs))
+ printk ("%s ", extended_msgs[msg[2]]);
+ else
+ printk ("Extended Message, reserved code (0x%02x) ",
+ (int) msg[2]);
+ switch (msg[2]) {
+ case EXTENDED_MODIFY_DATA_POINTER:
+ printk("pointer = %d", (int) (msg[3] << 24) |
+ (msg[4] << 16) | (msg[5] << 8) | msg[6]);
+ break;
+ case EXTENDED_SDTR:
+ print_nego(msg, 3, 4, 0);
+ break;
+ case EXTENDED_WDTR:
+ print_nego(msg, 0, 0, 3);
+ break;
+ case EXTENDED_PPR:
+ print_nego(msg, 3, 5, 6);
+ break;
+ default:
+ for (i = 2; i < len; ++i)
+ printk("%02x ", msg[i]);
+ }
+ /* Identify */
+ } else if (msg[0] & 0x80) {
+ printk("Identify disconnect %sallowed %s %d ",
+ (msg[0] & 0x40) ? "" : "not ",
+ (msg[0] & 0x20) ? "target routine" : "lun",
+ msg[0] & 0x7);
+ len = 1;
+ /* Normal One byte */
+ } else if (msg[0] < 0x1f) {
+ if (msg[0] < ARRAY_SIZE(one_byte_msgs))
+ printk(one_byte_msgs[msg[0]]);
+ else
+ printk("reserved (%02x) ", msg[0]);
+ len = 1;
+ /* Two byte */
+ } else if (msg[0] <= 0x2f) {
+ if ((msg[0] - 0x20) < ARRAY_SIZE(two_byte_msgs))
+ printk("%s %02x ", two_byte_msgs[msg[0] - 0x20],
+ msg[1]);
+ else
+ printk("reserved two byte (%02x %02x) ",
+ msg[0], msg[1]);
+ len = 2;
+ } else
+ printk("reserved");
+ return len;
+}
+EXPORT_SYMBOL(spi_print_msg);
+
+#else /* ifndef CONFIG_SCSI_CONSTANTS */
+
+int spi_print_msg(const unsigned char *msg)
+{
+ int len = 0, i;
+
+ if (msg[0] == EXTENDED_MESSAGE) {
+ len = 3 + msg[1];
+ for (i = 0; i < len; ++i)
+ printk("%02x ", msg[i]);
+ /* Identify */
+ } else if (msg[0] & 0x80) {
+ printk("%02x ", msg[0]);
+ len = 1;
+ /* Normal One byte */
+ } else if (msg[0] < 0x1f) {
+ printk("%02x ", msg[0]);
+ len = 1;
+ /* Two byte */
+ } else if (msg[0] <= 0x2f) {
+ printk("%02x %02x", msg[0], msg[1]);
+ len = 2;
+ } else
+ printk("%02x ", msg[0]);
+ return len;
+}
+EXPORT_SYMBOL(spi_print_msg);
+#endif /* ! CONFIG_SCSI_CONSTANTS */
+
#define SETUP_ATTRIBUTE(field) \
i->private_attrs[count] = class_device_attr_##field; \
if (!i->f->set_##field) { \
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 03fcbab30033..930db398d107 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -49,6 +49,7 @@
#include <linux/blkpg.h>
#include <linux/kref.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -102,6 +103,7 @@ struct scsi_disk {
u8 write_prot;
unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */
+ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
};
static DEFINE_IDR(sd_index_idr);
@@ -110,7 +112,7 @@ static DEFINE_SPINLOCK(sd_index_lock);
/* This semaphore is used to mediate the 0->1 reference get in the
* face of object destruction (i.e. we can't allow a get on an
* object after last put) */
-static DECLARE_MUTEX(sd_ref_sem);
+static DEFINE_MUTEX(sd_ref_mutex);
static int sd_revalidate_disk(struct gendisk *disk);
static void sd_rw_intr(struct scsi_cmnd * SCpnt);
@@ -121,8 +123,7 @@ static void sd_shutdown(struct device *dev);
static void sd_rescan(struct device *);
static int sd_init_command(struct scsi_cmnd *);
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_prepare_flush(request_queue_t *, struct request *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
unsigned char *buffer);
@@ -137,8 +138,6 @@ static struct scsi_driver sd_template = {
.rescan = sd_rescan,
.init_command = sd_init_command,
.issue_flush = sd_issue_flush,
- .prepare_flush = sd_prepare_flush,
- .end_flush = sd_end_flush,
};
/*
@@ -195,9 +194,9 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
{
struct scsi_disk *sdkp;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
sdkp = __scsi_disk_get(disk);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return sdkp;
}
@@ -205,11 +204,11 @@ static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
{
struct scsi_disk *sdkp;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
sdkp = dev_get_drvdata(dev);
if (sdkp)
sdkp = __scsi_disk_get(sdkp->disk);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return sdkp;
}
@@ -217,10 +216,10 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
{
struct scsi_device *sdev = sdkp->device;
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
kref_put(&sdkp->kref, scsi_disk_release);
scsi_device_put(sdev);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
}
/**
@@ -233,34 +232,12 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
**/
static int sd_init_command(struct scsi_cmnd * SCpnt)
{
- unsigned int this_count, timeout;
- struct gendisk *disk;
- sector_t block;
struct scsi_device *sdp = SCpnt->device;
struct request *rq = SCpnt->request;
-
- timeout = sdp->timeout;
-
- /*
- * SG_IO from block layer already setup, just copy cdb basically
- */
- if (blk_pc_request(rq)) {
- scsi_setup_blk_pc_cmnd(SCpnt, SD_PASSTHROUGH_RETRIES);
- if (rq->timeout)
- timeout = rq->timeout;
-
- goto queue;
- }
-
- /*
- * we only do REQ_CMD and REQ_BLOCK_PC
- */
- if (!blk_fs_request(rq))
- return 0;
-
- disk = rq->rq_disk;
- block = rq->sector;
- this_count = SCpnt->request_bufflen >> 9;
+ struct gendisk *disk = rq->rq_disk;
+ sector_t block = rq->sector;
+ unsigned int this_count = SCpnt->request_bufflen >> 9;
+ unsigned int timeout = sdp->timeout;
SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
"count=%d\n", disk->disk_name,
@@ -346,6 +323,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
if (block > 0xffffffff) {
SCpnt->cmnd[0] += READ_16 - READ_6;
+ SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
@@ -365,6 +343,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
this_count = 0xffff;
SCpnt->cmnd[0] += READ_10 - READ_6;
+ SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0;
SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff;
SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff;
SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff;
@@ -373,6 +352,17 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff;
SCpnt->cmnd[8] = (unsigned char) this_count & 0xff;
} else {
+ if (unlikely(blk_fua_rq(rq))) {
+ /*
+ * This happens only if this drive failed
+ * 10byte rw command with ILLEGAL_REQUEST
+ * during operation and thus turned off
+ * use_10_for_rw.
+ */
+ printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n");
+ return 0;
+ }
+
SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f);
SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff);
SCpnt->cmnd[3] = (unsigned char) block & 0xff;
@@ -390,8 +380,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
SCpnt->transfersize = sdp->sector_size;
SCpnt->underflow = this_count << 9;
SCpnt->allowed = SD_MAX_RETRIES;
-
-queue:
SCpnt->timeout_per_command = timeout;
/*
@@ -516,7 +504,7 @@ static int sd_release(struct inode *inode, struct file *filp)
return 0;
}
-static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc)
+static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
{
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdp = sdkp->device;
@@ -534,15 +522,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *
else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo);
- if (put_user(diskinfo[0], &loc->heads))
- return -EFAULT;
- if (put_user(diskinfo[1], &loc->sectors))
- return -EFAULT;
- if (put_user(diskinfo[2], &loc->cylinders))
- return -EFAULT;
- if (put_user((unsigned)get_start_sect(bdev),
- (unsigned long __user *)&loc->start))
- return -EFAULT;
+ geo->heads = diskinfo[0];
+ geo->sectors = diskinfo[1];
+ geo->cylinders = diskinfo[2];
return 0;
}
@@ -582,12 +564,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
if (!scsi_block_when_processing_errors(sdp) || !error)
return error;
- if (cmd == HDIO_GETGEO) {
- if (!arg)
- return -EINVAL;
- return sd_hdio_getgeo(bdev, p);
- }
-
/*
* Send SCSI addressing ioctls directly to mid level, send other
* ioctls to block level and then onto mid level if they can't be
@@ -729,42 +705,13 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector)
return ret;
}
-static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
+static void sd_prepare_flush(request_queue_t *q, struct request *rq)
{
- struct request *rq = flush_rq->end_io_data;
- struct scsi_cmnd *cmd = rq->special;
- unsigned int bytes = rq->hard_nr_sectors << 9;
-
- if (!flush_rq->errors) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, bytes, 0);
- spin_lock(q->queue_lock);
- } else if (blk_barrier_postflush(rq)) {
- spin_unlock(q->queue_lock);
- scsi_io_completion(cmd, 0, bytes);
- spin_lock(q->queue_lock);
- } else {
- /*
- * force journal abort of barriers
- */
- end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
- end_that_request_last(rq);
- }
-}
-
-static int sd_prepare_flush(request_queue_t *q, struct request *rq)
-{
- struct scsi_device *sdev = q->queuedata;
- struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);
-
- if (!sdkp || !sdkp->WCE)
- return 0;
-
memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+ rq->flags |= REQ_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
rq->cmd[0] = SYNCHRONIZE_CACHE;
- return 1;
+ rq->cmd_len = 10;
}
static void sd_rescan(struct device *dev)
@@ -818,6 +765,7 @@ static struct block_device_operations sd_fops = {
.open = sd_open,
.release = sd_release,
.ioctl = sd_ioctl,
+ .getgeo = sd_getgeo,
#ifdef CONFIG_COMPAT
.compat_ioctl = sd_compat_ioctl,
#endif
@@ -865,15 +813,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
relatively rare error condition, no care is taken to avoid
unnecessary additional work such as memcpy's that could be avoided.
*/
-
- /*
- * If SG_IO from block layer then set good_bytes to stop retries;
- * else if errors, check them, and if necessary prepare for
- * (partial) retries.
- */
- if (blk_pc_request(SCpnt->request))
- good_bytes = this_count;
- else if (driver_byte(result) != 0 &&
+ if (driver_byte(result) != 0 &&
sense_valid && !sense_deferred) {
switch (sshdr.sense_key) {
case MEDIUM_ERROR:
@@ -1427,10 +1367,18 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
sdkp->RCD = 0;
}
+ sdkp->DPOFUA = (data.device_specific & 0x10) != 0;
+ if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+ printk(KERN_NOTICE "SCSI device %s: uses "
+ "READ/WRITE(6), disabling FUA\n", diskname);
+ sdkp->DPOFUA = 0;
+ }
+
ct = sdkp->RCD + 2*sdkp->WCE;
- printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n",
- diskname, types[ct]);
+ printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n",
+ diskname, types[ct],
+ sdkp->DPOFUA ? " w/ FUA" : "");
return;
}
@@ -1462,6 +1410,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
unsigned char *buffer;
+ unsigned ordered;
SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));
@@ -1495,12 +1444,24 @@ static int sd_revalidate_disk(struct gendisk *disk)
*/
if (sdkp->media_present) {
sd_read_capacity(sdkp, disk->disk_name, buffer);
- if (sdp->removable)
- sd_read_write_protect_flag(sdkp, disk->disk_name,
- buffer);
+ sd_read_write_protect_flag(sdkp, disk->disk_name, buffer);
sd_read_cache_type(sdkp, disk->disk_name, buffer);
}
-
+
+ /*
+ * We now have all cache related info, determine how we deal
+ * with ordered requests. Note that as the current SCSI
+ * dispatch function can alter request order, we cannot use
+ * QUEUE_ORDERED_TAG_* even when ordered tag is supported.
+ */
+ if (sdkp->WCE)
+ ordered = sdkp->DPOFUA
+ ? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH;
+ else
+ ordered = QUEUE_ORDERED_DRAIN;
+
+ blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush);
+
set_capacity(disk, sdkp->capacity);
kfree(buffer);
@@ -1600,6 +1561,7 @@ static int sd_probe(struct device *dev)
strcpy(gd->devfs_name, sdp->devfs_name);
gd->private_data = &sdkp->driver;
+ gd->queue = sdkp->device->request_queue;
sd_revalidate_disk(gd);
@@ -1607,7 +1569,6 @@ static int sd_probe(struct device *dev)
gd->flags = GENHD_FL_DRIVERFS;
if (sdp->removable)
gd->flags |= GENHD_FL_REMOVABLE;
- gd->queue = sdkp->device->request_queue;
dev_set_drvdata(dev, sdkp);
add_disk(gd);
@@ -1643,10 +1604,10 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk);
sd_shutdown(dev);
- down(&sd_ref_sem);
+ mutex_lock(&sd_ref_mutex);
dev_set_drvdata(dev, NULL);
kref_put(&sdkp->kref, scsi_disk_release);
- up(&sd_ref_sem);
+ mutex_unlock(&sd_ref_mutex);
return 0;
}
@@ -1655,7 +1616,7 @@ static int sd_remove(struct device *dev)
* scsi_disk_release - Called to free the scsi_disk structure
* @kref: pointer to embedded kref
*
- * sd_ref_sem must be held entering this routine. Because it is
+ * sd_ref_mutex must be held entering this routine. Because it is
* called on last put, you should always use the scsi_disk_get()
* scsi_disk_put() helpers which manipulate the semaphore directly
* and never do a direct kref_put().
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b55c2a8a547c..78aad9582bcf 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -104,8 +104,6 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF;
static int sg_add(struct class_device *, struct class_interface *);
static void sg_remove(struct class_device *, struct class_interface *);
-static Scsi_Request *dummy_cmdp; /* only used for sizeof */
-
static DEFINE_RWLOCK(sg_dev_arr_lock); /* Also used to lock
file descriptor list for device */
@@ -119,7 +117,7 @@ typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
unsigned bufflen; /* Size of (aggregate) data buffer */
unsigned b_malloc_len; /* actual len malloc'ed in buffer */
- void *buffer; /* Data buffer or scatter list (k_use_sg>0) */
+ struct scatterlist *buffer;/* scatter list */
char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */
unsigned char cmd_opcode; /* first byte of command */
} Sg_scatter_hold;
@@ -128,12 +126,11 @@ struct sg_device; /* forward declarations */
struct sg_fd;
typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
- Scsi_Request *my_cmdp; /* != 0 when request with lower levels */
struct sg_request *nextrp; /* NULL -> tail request (slist) */
struct sg_fd *parentfp; /* NULL -> not in use */
Sg_scatter_hold data; /* hold buffer, perhaps scatter list */
sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */
- unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
+ unsigned char sense_b[SCSI_SENSE_BUFFERSIZE];
char res_used; /* 1 -> using reserve buffer, 0 -> not ... */
char orphan; /* 1 -> drop on sight, 0 -> normal */
char sg_io_owned; /* 1 -> packet belongs to SG_IO */
@@ -174,7 +171,8 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
} Sg_device;
static int sg_fasync(int fd, struct file *filp, int mode);
-static void sg_cmd_done(Scsi_Cmnd * SCpnt); /* tasklet or soft irq callback */
+/* tasklet or soft irq callback */
+static void sg_cmd_done(void *data, char *sense, int result, int resid);
static int sg_start_req(Sg_request * srp);
static void sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
@@ -195,8 +193,8 @@ static void sg_remove_scat(Sg_scatter_hold * schp);
static void sg_build_reserve(Sg_fd * sfp, int req_size);
static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
-static char *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
-static void sg_page_free(char *buff, int size);
+static struct page *sg_page_malloc(int rqSz, int lowDma, int *retSzp);
+static void sg_page_free(struct page *page, int size);
static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
@@ -207,7 +205,6 @@ static int sg_res_in_use(Sg_fd * sfp);
static int sg_allow_access(unsigned char opcode, char dev_type);
static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
static Sg_device *sg_get_dev(int dev);
-static inline unsigned char *sg_scatg2virt(const struct scatterlist *sclp);
#ifdef CONFIG_SCSI_PROC_FS
static int sg_last_dev(void);
#endif
@@ -226,6 +223,7 @@ sg_open(struct inode *inode, struct file *filp)
{
int dev = iminor(inode);
int flags = filp->f_flags;
+ struct request_queue *q;
Sg_device *sdp;
Sg_fd *sfp;
int res;
@@ -287,7 +285,9 @@ sg_open(struct inode *inode, struct file *filp)
}
if (!sdp->headfp) { /* no existing opens on this device */
sdp->sgdebug = 0;
- sdp->sg_tablesize = sdp->device->host->sg_tablesize;
+ q = sdp->device->request_queue;
+ sdp->sg_tablesize = min(q->max_hw_segments,
+ q->max_phys_segments);
}
if ((sfp = sg_add_sfp(sdp, dev)))
filp->private_data = sfp;
@@ -340,6 +340,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n",
sdp->disk->disk_name, (int) count));
+
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
if (sfp->force_packid && (count >= SZ_SG_HEADER)) {
@@ -491,7 +492,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp)
if ((hp->mx_sb_len > 0) && hp->sbp) {
if ((CHECK_CONDITION & hp->masked_status) ||
(DRIVER_SENSE & hp->driver_status)) {
- int sb_len = sizeof (dummy_cmdp->sr_sense_buffer);
+ int sb_len = SCSI_SENSE_BUFFERSIZE;
sb_len = (hp->mx_sb_len > sb_len) ? sb_len : hp->mx_sb_len;
len = 8 + (int) srp->sense_b[7]; /* Additional sense length field */
len = (len > sb_len) ? sb_len : len;
@@ -525,7 +526,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
Sg_request *srp;
struct sg_header old_hdr;
sg_io_hdr_t *hp;
- unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
+ unsigned char cmnd[MAX_COMMAND_SIZE];
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
return -ENXIO;
@@ -624,7 +625,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
int k;
Sg_request *srp;
sg_io_hdr_t *hp;
- unsigned char cmnd[sizeof (dummy_cmdp->sr_cmnd)];
+ unsigned char cmnd[MAX_COMMAND_SIZE];
int timeout;
unsigned long ul_timeout;
@@ -692,11 +693,9 @@ static int
sg_common_write(Sg_fd * sfp, Sg_request * srp,
unsigned char *cmnd, int timeout, int blocking)
{
- int k;
- Scsi_Request *SRpnt;
+ int k, data_dir;
Sg_device *sdp = sfp->parentdp;
sg_io_hdr_t *hp = &srp->header;
- request_queue_t *q;
srp->data.cmd_opcode = cmnd[0]; /* hold opcode of command */
hp->status = 0;
@@ -723,51 +722,36 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
sg_finish_rem_req(srp);
return -ENODEV;
}
- SRpnt = scsi_allocate_request(sdp->device, GFP_ATOMIC);
- if (SRpnt == NULL) {
- SCSI_LOG_TIMEOUT(1, printk("sg_write: no mem\n"));
- sg_finish_rem_req(srp);
- return -ENOMEM;
- }
- srp->my_cmdp = SRpnt;
- q = SRpnt->sr_device->request_queue;
- SRpnt->sr_request->rq_disk = sdp->disk;
- SRpnt->sr_sense_buffer[0] = 0;
- SRpnt->sr_cmd_len = hp->cmd_len;
- SRpnt->sr_use_sg = srp->data.k_use_sg;
- SRpnt->sr_sglist_len = srp->data.sglist_len;
- SRpnt->sr_bufflen = srp->data.bufflen;
- SRpnt->sr_underflow = 0;
- SRpnt->sr_buffer = srp->data.buffer;
switch (hp->dxfer_direction) {
case SG_DXFER_TO_FROM_DEV:
case SG_DXFER_FROM_DEV:
- SRpnt->sr_data_direction = DMA_FROM_DEVICE;
+ data_dir = DMA_FROM_DEVICE;
break;
case SG_DXFER_TO_DEV:
- SRpnt->sr_data_direction = DMA_TO_DEVICE;
+ data_dir = DMA_TO_DEVICE;
break;
case SG_DXFER_UNKNOWN:
- SRpnt->sr_data_direction = DMA_BIDIRECTIONAL;
+ data_dir = DMA_BIDIRECTIONAL;
break;
default:
- SRpnt->sr_data_direction = DMA_NONE;
+ data_dir = DMA_NONE;
break;
}
- SRpnt->upper_private_data = srp;
- srp->data.k_use_sg = 0;
- srp->data.sglist_len = 0;
- srp->data.bufflen = 0;
- srp->data.buffer = NULL;
hp->duration = jiffies_to_msecs(jiffies);
/* Now send everything of to mid-level. The next time we hear about this
packet is when sg_cmd_done() is called (i.e. a callback). */
- scsi_do_req(SRpnt, (void *) cmnd,
- (void *) SRpnt->sr_buffer, hp->dxfer_len,
- sg_cmd_done, timeout, SG_DEFAULT_RETRIES);
- /* dxfer_len overwrites SRpnt->sr_bufflen, hence need for b_malloc_len */
- return 0;
+ if (scsi_execute_async(sdp->device, cmnd, data_dir, srp->data.buffer,
+ hp->dxfer_len, srp->data.k_use_sg, timeout,
+ SG_DEFAULT_RETRIES, srp, sg_cmd_done,
+ GFP_ATOMIC)) {
+ SCSI_LOG_TIMEOUT(1, printk("sg_write: scsi_execute_async failed\n"));
+ /*
+ * most likely out of mem, but could also be a bad map
+ */
+ return -ENOMEM;
+ } else
+ return 0;
}
static int
@@ -1156,45 +1140,22 @@ sg_fasync(int fd, struct file *filp, int mode)
return (retval < 0) ? retval : 0;
}
-static inline unsigned char *
-sg_scatg2virt(const struct scatterlist *sclp)
-{
- return (sclp && sclp->page) ?
- (unsigned char *) page_address(sclp->page) + sclp->offset : NULL;
-}
-
/* When startFinish==1 increments page counts for pages other than the
- first of scatter gather elements obtained from __get_free_pages().
+ first of scatter gather elements obtained from alloc_pages().
When startFinish==0 decrements ... */
static void
sg_rb_correct4mmap(Sg_scatter_hold * rsv_schp, int startFinish)
{
- void *page_ptr;
+ struct scatterlist *sg = rsv_schp->buffer;
struct page *page;
int k, m;
SCSI_LOG_TIMEOUT(3, printk("sg_rb_correct4mmap: startFinish=%d, scatg=%d\n",
startFinish, rsv_schp->k_use_sg));
/* N.B. correction _not_ applied to base page of each allocation */
- if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
- struct scatterlist *sclp = rsv_schp->buffer;
-
- for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
- for (m = PAGE_SIZE; m < sclp->length; m += PAGE_SIZE) {
- page_ptr = sg_scatg2virt(sclp) + m;
- page = virt_to_page(page_ptr);
- if (startFinish)
- get_page(page);
- else {
- if (page_count(page) > 0)
- __put_page(page);
- }
- }
- }
- } else { /* reserve buffer is just a single allocation */
- for (m = PAGE_SIZE; m < rsv_schp->bufflen; m += PAGE_SIZE) {
- page_ptr = (unsigned char *) rsv_schp->buffer + m;
- page = virt_to_page(page_ptr);
+ for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
+ for (m = PAGE_SIZE; m < sg->length; m += PAGE_SIZE) {
+ page = sg->page;
if (startFinish)
get_page(page);
else {
@@ -1210,9 +1171,10 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
{
Sg_fd *sfp;
struct page *page = NOPAGE_SIGBUS;
- void *page_ptr = NULL;
- unsigned long offset;
+ unsigned long offset, len, sa;
Sg_scatter_hold *rsv_schp;
+ struct scatterlist *sg;
+ int k;
if ((NULL == vma) || (!(sfp = (Sg_fd *) vma->vm_private_data)))
return page;
@@ -1222,30 +1184,21 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type)
return page;
SCSI_LOG_TIMEOUT(3, printk("sg_vma_nopage: offset=%lu, scatg=%d\n",
offset, rsv_schp->k_use_sg));
- if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
- int k;
- unsigned long sa = vma->vm_start;
- unsigned long len;
- struct scatterlist *sclp = rsv_schp->buffer;
-
- for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, ++sclp) {
- len = vma->vm_end - sa;
- len = (len < sclp->length) ? len : sclp->length;
- if (offset < len) {
- page_ptr = sg_scatg2virt(sclp) + offset;
- page = virt_to_page(page_ptr);
- get_page(page); /* increment page count */
- break;
- }
- sa += len;
- offset -= len;
+ sg = rsv_schp->buffer;
+ sa = vma->vm_start;
+ for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+ ++k, ++sg) {
+ len = vma->vm_end - sa;
+ len = (len < sg->length) ? len : sg->length;
+ if (offset < len) {
+ page = sg->page;
+ get_page(page); /* increment page count */
+ break;
}
- } else { /* reserve buffer is just a single allocation */
- page_ptr = (unsigned char *) rsv_schp->buffer + offset;
- page = virt_to_page(page_ptr);
- get_page(page); /* increment page count */
+ sa += len;
+ offset -= len;
}
+
if (type)
*type = VM_FAULT_MINOR;
return page;
@@ -1259,8 +1212,10 @@ static int
sg_mmap(struct file *filp, struct vm_area_struct *vma)
{
Sg_fd *sfp;
- unsigned long req_sz;
+ unsigned long req_sz, len, sa;
Sg_scatter_hold *rsv_schp;
+ int k;
+ struct scatterlist *sg;
if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
return -ENXIO;
@@ -1273,24 +1228,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
if (req_sz > rsv_schp->bufflen)
return -ENOMEM; /* cannot map more than reserved buffer */
- if (rsv_schp->k_use_sg) { /* reserve buffer is a scatter gather list */
- int k;
- unsigned long sa = vma->vm_start;
- unsigned long len;
- struct scatterlist *sclp = rsv_schp->buffer;
-
- for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
- ++k, ++sclp) {
- if (0 != sclp->offset)
- return -EFAULT; /* non page aligned memory ?? */
- len = vma->vm_end - sa;
- len = (len < sclp->length) ? len : sclp->length;
- sa += len;
- }
- } else { /* reserve buffer is just a single allocation */
- if ((unsigned long) rsv_schp->buffer & (PAGE_SIZE - 1))
- return -EFAULT; /* non page aligned memory ?? */
+ sa = vma->vm_start;
+ sg = rsv_schp->buffer;
+ for (k = 0; (k < rsv_schp->k_use_sg) && (sa < vma->vm_end);
+ ++k, ++sg) {
+ len = vma->vm_end - sa;
+ len = (len < sg->length) ? len : sg->length;
+ sa += len;
}
+
if (0 == sfp->mmap_called) {
sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */
sfp->mmap_called = 1;
@@ -1304,21 +1250,16 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
/* This function is a "bottom half" handler that is called by the
* mid level when a command is completed (or has failed). */
static void
-sg_cmd_done(Scsi_Cmnd * SCpnt)
+sg_cmd_done(void *data, char *sense, int result, int resid)
{
- Scsi_Request *SRpnt = NULL;
+ Sg_request *srp = data;
Sg_device *sdp = NULL;
Sg_fd *sfp;
- Sg_request *srp = NULL;
unsigned long iflags;
unsigned int ms;
- if (SCpnt && (SRpnt = SCpnt->sc_request))
- srp = (Sg_request *) SRpnt->upper_private_data;
if (NULL == srp) {
printk(KERN_ERR "sg_cmd_done: NULL request\n");
- if (SRpnt)
- scsi_release_request(SRpnt);
return;
}
sfp = srp->parentfp;
@@ -1326,49 +1267,34 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
sdp = sfp->parentdp;
if ((NULL == sdp) || sdp->detached) {
printk(KERN_INFO "sg_cmd_done: device detached\n");
- scsi_release_request(SRpnt);
return;
}
- /* First transfer ownership of data buffers to sg_device object. */
- srp->data.k_use_sg = SRpnt->sr_use_sg;
- srp->data.sglist_len = SRpnt->sr_sglist_len;
- srp->data.bufflen = SRpnt->sr_bufflen;
- srp->data.buffer = SRpnt->sr_buffer;
- /* now clear out request structure */
- SRpnt->sr_use_sg = 0;
- SRpnt->sr_sglist_len = 0;
- SRpnt->sr_bufflen = 0;
- SRpnt->sr_buffer = NULL;
- SRpnt->sr_underflow = 0;
- SRpnt->sr_request->rq_disk = NULL; /* "sg" _disowns_ request blk */
-
- srp->my_cmdp = NULL;
SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n",
- sdp->disk->disk_name, srp->header.pack_id, (int) SRpnt->sr_result));
- srp->header.resid = SCpnt->resid;
+ sdp->disk->disk_name, srp->header.pack_id, result));
+ srp->header.resid = resid;
ms = jiffies_to_msecs(jiffies);
srp->header.duration = (ms > srp->header.duration) ?
(ms - srp->header.duration) : 0;
- if (0 != SRpnt->sr_result) {
+ if (0 != result) {
struct scsi_sense_hdr sshdr;
- memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
- sizeof (srp->sense_b));
- srp->header.status = 0xff & SRpnt->sr_result;
- srp->header.masked_status = status_byte(SRpnt->sr_result);
- srp->header.msg_status = msg_byte(SRpnt->sr_result);
- srp->header.host_status = host_byte(SRpnt->sr_result);
- srp->header.driver_status = driver_byte(SRpnt->sr_result);
+ memcpy(srp->sense_b, sense, sizeof (srp->sense_b));
+ srp->header.status = 0xff & result;
+ srp->header.masked_status = status_byte(result);
+ srp->header.msg_status = msg_byte(result);
+ srp->header.host_status = host_byte(result);
+ srp->header.driver_status = driver_byte(result);
if ((sdp->sgdebug > 0) &&
((CHECK_CONDITION == srp->header.masked_status) ||
(COMMAND_TERMINATED == srp->header.masked_status)))
- scsi_print_req_sense("sg_cmd_done", SRpnt);
+ __scsi_print_sense("sg_cmd_done", sense,
+ SCSI_SENSE_BUFFERSIZE);
/* Following if statement is a patch supplied by Eric Youngdale */
- if (driver_byte(SRpnt->sr_result) != 0
- && scsi_command_normalize_sense(SCpnt, &sshdr)
+ if (driver_byte(result) != 0
+ && scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)
&& !scsi_sense_is_deferred(&sshdr)
&& sshdr.sense_key == UNIT_ATTENTION
&& sdp->device->removable) {
@@ -1379,8 +1305,6 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
}
/* Rely on write phase to clean out srp status values, so no "else" */
- scsi_release_request(SRpnt);
- SRpnt = NULL;
if (sfp->closed) { /* whoops this fd already released, cleanup */
SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n"));
sg_finish_rem_req(srp);
@@ -1431,6 +1355,7 @@ static int sg_sysfs_valid = 0;
static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
{
+ struct request_queue *q = scsidp->request_queue;
Sg_device *sdp;
unsigned long iflags;
void *old_sg_dev_arr = NULL;
@@ -1473,7 +1398,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
sdp->disk = disk;
sdp->device = scsidp;
init_waitqueue_head(&sdp->o_excl_wait);
- sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
+ sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
sg_nr_dev++;
sg_dev_arr[k] = sdp;
@@ -1753,36 +1678,35 @@ sg_finish_rem_req(Sg_request * srp)
static int
sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp, int tablesize)
{
- int ret_sz;
- int elem_sz = sizeof (struct scatterlist);
- int sg_bufflen = tablesize * elem_sz;
- int mx_sc_elems = tablesize;
+ int sg_bufflen = tablesize * sizeof(struct scatterlist);
+ unsigned int gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
- schp->buffer = sg_page_malloc(sg_bufflen, sfp->low_dma, &ret_sz);
+ /*
+ * TODO: test without low_dma, we should not need it since
+ * the block layer will bounce the buffer for us
+ *
+ * XXX(hch): we shouldn't need GFP_DMA for the actual S/G list.
+ */
+ if (sfp->low_dma)
+ gfp_flags |= GFP_DMA;
+ schp->buffer = kzalloc(sg_bufflen, gfp_flags);
if (!schp->buffer)
return -ENOMEM;
- else if (ret_sz != sg_bufflen) {
- sg_bufflen = ret_sz;
- mx_sc_elems = sg_bufflen / elem_sz;
- }
schp->sglist_len = sg_bufflen;
- memset(schp->buffer, 0, sg_bufflen);
- return mx_sc_elems; /* number of scat_gath elements allocated */
+ return tablesize; /* number of scat_gath elements allocated */
}
#ifdef SG_ALLOW_DIO_CODE
/* vvvvvvvv following code borrowed from st driver's direct IO vvvvvvvvv */
- /* hopefully this generic code will moved to a library */
+ /* TODO: hopefully we can use the generic block layer code */
/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
- mapping of all pages not successful
- - any page is above max_pfn
(i.e., either completely successful or fails)
*/
static int
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 uaddr, size_t count, int rw)
{
unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long start = uaddr >> PAGE_SHIFT;
@@ -1828,21 +1752,17 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
* probably wrong function for rw==WRITE
*/
flush_dcache_page(pages[i]);
- if (page_to_pfn(pages[i]) > max_pfn)
- goto out_unlock;
/* ?? Is locking needed? I don't think so */
/* if (TestSetPageLocked(pages[i]))
goto out_unlock; */
}
- /* Populate the scatter/gather list */
- sgl[0].page = pages[0];
+ sgl[0].page = pages[0];
sgl[0].offset = uaddr & ~PAGE_MASK;
if (nr_pages > 1) {
sgl[0].length = PAGE_SIZE - sgl[0].offset;
count -= sgl[0].length;
for (i=1; i < nr_pages ; i++) {
- sgl[i].offset = 0;
sgl[i].page = pages[i];
sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE;
count -= PAGE_SIZE;
@@ -1855,10 +1775,6 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
kfree(pages);
return nr_pages;
- out_unlock:
- /* for (j=0; j < i; j++)
- unlock_page(pages[j]); */
- res = 0;
out_unmap:
if (res > 0) {
for (j=0; j < res; j++)
@@ -1904,20 +1820,20 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
sg_io_hdr_t *hp = &srp->header;
Sg_scatter_hold *schp = &srp->data;
int sg_tablesize = sfp->parentdp->sg_tablesize;
- struct scatterlist *sgl;
int mx_sc_elems, res;
struct scsi_device *sdev = sfp->parentdp->device;
if (((unsigned long)hp->dxferp &
queue_dma_alignment(sdev->request_queue)) != 0)
return 1;
+
mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
if (mx_sc_elems <= 0) {
return 1;
}
- sgl = (struct scatterlist *)schp->buffer;
- res = st_map_user_pages(sgl, mx_sc_elems, (unsigned long)hp->dxferp, dxfer_len,
- (SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0, ULONG_MAX);
+ res = st_map_user_pages(schp->buffer, mx_sc_elems,
+ (unsigned long)hp->dxferp, dxfer_len,
+ (SG_DXFER_TO_DEV == hp->dxfer_direction) ? 1 : 0);
if (res <= 0)
return 1;
schp->k_use_sg = res;
@@ -1932,9 +1848,11 @@ sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len)
static int
sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
{
- int ret_sz;
+ struct scatterlist *sg;
+ int ret_sz = 0, k, rem_sz, num, mx_sc_elems;
+ int sg_tablesize = sfp->parentdp->sg_tablesize;
int blk_size = buff_size;
- unsigned char *p = NULL;
+ struct page *p = NULL;
if ((blk_size < 0) || (!sfp))
return -EFAULT;
@@ -1944,59 +1862,35 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n",
buff_size, blk_size));
- if (blk_size <= SG_SCATTER_SZ) {
- p = sg_page_malloc(blk_size, sfp->low_dma, &ret_sz);
- if (!p)
- return -ENOMEM;
- if (blk_size == ret_sz) { /* got it on the first attempt */
- schp->k_use_sg = 0;
- schp->buffer = p;
- schp->bufflen = blk_size;
- schp->b_malloc_len = blk_size;
- return 0;
- }
- } else {
- p = sg_page_malloc(SG_SCATTER_SZ, sfp->low_dma, &ret_sz);
+
+ /* N.B. ret_sz carried into this block ... */
+ mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
+ if (mx_sc_elems < 0)
+ return mx_sc_elems; /* most likely -ENOMEM */
+
+ for (k = 0, sg = schp->buffer, rem_sz = blk_size;
+ (rem_sz > 0) && (k < mx_sc_elems);
+ ++k, rem_sz -= ret_sz, ++sg) {
+
+ num = (rem_sz > SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
+ p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
if (!p)
return -ENOMEM;
- }
-/* Want some local declarations, so start new block ... */
- { /* lets try and build a scatter gather list */
- struct scatterlist *sclp;
- int k, rem_sz, num;
- int mx_sc_elems;
- int sg_tablesize = sfp->parentdp->sg_tablesize;
- int first = 1;
-
- /* N.B. ret_sz carried into this block ... */
- mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize);
- if (mx_sc_elems < 0)
- return mx_sc_elems; /* most likely -ENOMEM */
-
- for (k = 0, sclp = schp->buffer, rem_sz = blk_size;
- (rem_sz > 0) && (k < mx_sc_elems);
- ++k, rem_sz -= ret_sz, ++sclp) {
- if (first)
- first = 0;
- else {
- num =
- (rem_sz >
- SG_SCATTER_SZ) ? SG_SCATTER_SZ : rem_sz;
- p = sg_page_malloc(num, sfp->low_dma, &ret_sz);
- if (!p)
- break;
- }
- sg_set_buf(sclp, p, ret_sz);
-
- SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
- k, sg_scatg2virt(sclp), ret_sz));
- } /* end of for loop */
- schp->k_use_sg = k;
- SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
- schp->bufflen = blk_size;
- if (rem_sz > 0) /* must have failed */
- return -ENOMEM;
- }
+
+ sg->page = p;
+ sg->length = ret_sz;
+
+ SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n",
+ k, p, ret_sz));
+ } /* end of for loop */
+
+ schp->k_use_sg = k;
+ SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz));
+
+ schp->bufflen = blk_size;
+ if (rem_sz > 0) /* must have failed */
+ return -ENOMEM;
+
return 0;
}
@@ -2005,6 +1899,7 @@ sg_write_xfer(Sg_request * srp)
{
sg_io_hdr_t *hp = &srp->header;
Sg_scatter_hold *schp = &srp->data;
+ struct scatterlist *sg = schp->buffer;
int num_xfer = 0;
int j, k, onum, usglen, ksglen, res;
int iovec_count = (int) hp->iovec_count;
@@ -2033,63 +1928,45 @@ sg_write_xfer(Sg_request * srp)
} else
onum = 1;
- if (0 == schp->k_use_sg) { /* kernel has single buffer */
- for (j = 0, p = schp->buffer; j < onum; ++j) {
- res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
- if (res)
- return res;
- usglen = (num_xfer > usglen) ? usglen : num_xfer;
- if (__copy_from_user(p, up, usglen))
- return -EFAULT;
- p += usglen;
- num_xfer -= usglen;
- if (num_xfer <= 0)
- return 0;
- }
- } else { /* kernel using scatter gather list */
- struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
- ksglen = (int) sclp->length;
- p = sg_scatg2virt(sclp);
- for (j = 0, k = 0; j < onum; ++j) {
- res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
- if (res)
- return res;
-
- for (; p; ++sclp, ksglen = (int) sclp->length,
- p = sg_scatg2virt(sclp)) {
- if (usglen <= 0)
- break;
- if (ksglen > usglen) {
- if (usglen >= num_xfer) {
- if (__copy_from_user
- (p, up, num_xfer))
- return -EFAULT;
- return 0;
- }
- if (__copy_from_user(p, up, usglen))
- return -EFAULT;
- p += usglen;
- ksglen -= usglen;
- break;
- } else {
- if (ksglen >= num_xfer) {
- if (__copy_from_user
- (p, up, num_xfer))
- return -EFAULT;
- return 0;
- }
- if (__copy_from_user(p, up, ksglen))
+ ksglen = sg->length;
+ p = page_address(sg->page);
+ for (j = 0, k = 0; j < onum; ++j) {
+ res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
+ if (res)
+ return res;
+
+ for (; p; ++sg, ksglen = sg->length,
+ p = page_address(sg->page)) {
+ if (usglen <= 0)
+ break;
+ if (ksglen > usglen) {
+ if (usglen >= num_xfer) {
+ if (__copy_from_user(p, up, num_xfer))
return -EFAULT;
- up += ksglen;
- usglen -= ksglen;
+ return 0;
}
- ++k;
- if (k >= schp->k_use_sg)
+ if (__copy_from_user(p, up, usglen))
+ return -EFAULT;
+ p += usglen;
+ ksglen -= usglen;
+ break;
+ } else {
+ if (ksglen >= num_xfer) {
+ if (__copy_from_user(p, up, num_xfer))
+ return -EFAULT;
return 0;
+ }
+ if (__copy_from_user(p, up, ksglen))
+ return -EFAULT;
+ up += ksglen;
+ usglen -= ksglen;
}
+ ++k;
+ if (k >= schp->k_use_sg)
+ return 0;
}
}
+
return 0;
}
@@ -2127,29 +2004,25 @@ sg_remove_scat(Sg_scatter_hold * schp)
{
SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg));
if (schp->buffer && (schp->sglist_len > 0)) {
- struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
+ struct scatterlist *sg = schp->buffer;
if (schp->dio_in_use) {
#ifdef SG_ALLOW_DIO_CODE
- st_unmap_user_pages(sclp, schp->k_use_sg, TRUE);
+ st_unmap_user_pages(sg, schp->k_use_sg, TRUE);
#endif
} else {
int k;
- for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
- ++k, ++sclp) {
+ for (k = 0; (k < schp->k_use_sg) && sg->page;
+ ++k, ++sg) {
SCSI_LOG_TIMEOUT(5, printk(
"sg_remove_scat: k=%d, a=0x%p, len=%d\n",
- k, sg_scatg2virt(sclp), sclp->length));
- sg_page_free(sg_scatg2virt(sclp), sclp->length);
- sclp->page = NULL;
- sclp->offset = 0;
- sclp->length = 0;
+ k, sg->page, sg->length));
+ sg_page_free(sg->page, sg->length);
}
}
- sg_page_free(schp->buffer, schp->sglist_len);
- } else if (schp->buffer)
- sg_page_free(schp->buffer, schp->b_malloc_len);
+ kfree(schp->buffer);
+ }
memset(schp, 0, sizeof (*schp));
}
@@ -2158,6 +2031,7 @@ sg_read_xfer(Sg_request * srp)
{
sg_io_hdr_t *hp = &srp->header;
Sg_scatter_hold *schp = &srp->data;
+ struct scatterlist *sg = schp->buffer;
int num_xfer = 0;
int j, k, onum, usglen, ksglen, res;
int iovec_count = (int) hp->iovec_count;
@@ -2186,63 +2060,45 @@ sg_read_xfer(Sg_request * srp)
} else
onum = 1;
- if (0 == schp->k_use_sg) { /* kernel has single buffer */
- for (j = 0, p = schp->buffer; j < onum; ++j) {
- res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
- if (res)
- return res;
- usglen = (num_xfer > usglen) ? usglen : num_xfer;
- if (__copy_to_user(up, p, usglen))
- return -EFAULT;
- p += usglen;
- num_xfer -= usglen;
- if (num_xfer <= 0)
- return 0;
- }
- } else { /* kernel using scatter gather list */
- struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
- ksglen = (int) sclp->length;
- p = sg_scatg2virt(sclp);
- for (j = 0, k = 0; j < onum; ++j) {
- res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
- if (res)
- return res;
-
- for (; p; ++sclp, ksglen = (int) sclp->length,
- p = sg_scatg2virt(sclp)) {
- if (usglen <= 0)
- break;
- if (ksglen > usglen) {
- if (usglen >= num_xfer) {
- if (__copy_to_user
- (up, p, num_xfer))
- return -EFAULT;
- return 0;
- }
- if (__copy_to_user(up, p, usglen))
- return -EFAULT;
- p += usglen;
- ksglen -= usglen;
- break;
- } else {
- if (ksglen >= num_xfer) {
- if (__copy_to_user
- (up, p, num_xfer))
- return -EFAULT;
- return 0;
- }
- if (__copy_to_user(up, p, ksglen))
+ p = page_address(sg->page);
+ ksglen = sg->length;
+ for (j = 0, k = 0; j < onum; ++j) {
+ res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
+ if (res)
+ return res;
+
+ for (; p; ++sg, ksglen = sg->length,
+ p = page_address(sg->page)) {
+ if (usglen <= 0)
+ break;
+ if (ksglen > usglen) {
+ if (usglen >= num_xfer) {
+ if (__copy_to_user(up, p, num_xfer))
return -EFAULT;
- up += ksglen;
- usglen -= ksglen;
+ return 0;
}
- ++k;
- if (k >= schp->k_use_sg)
+ if (__copy_to_user(up, p, usglen))
+ return -EFAULT;
+ p += usglen;
+ ksglen -= usglen;
+ break;
+ } else {
+ if (ksglen >= num_xfer) {
+ if (__copy_to_user(up, p, num_xfer))
+ return -EFAULT;
return 0;
+ }
+ if (__copy_to_user(up, p, ksglen))
+ return -EFAULT;
+ up += ksglen;
+ usglen -= ksglen;
}
+ ++k;
+ if (k >= schp->k_use_sg)
+ return 0;
}
}
+
return 0;
}
@@ -2250,37 +2106,32 @@ static int
sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer)
{
Sg_scatter_hold *schp = &srp->data;
+ struct scatterlist *sg = schp->buffer;
+ int k, num;
SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n",
num_read_xfer));
if ((!outp) || (num_read_xfer <= 0))
return 0;
- if (schp->k_use_sg > 0) {
- int k, num;
- struct scatterlist *sclp = (struct scatterlist *) schp->buffer;
-
- for (k = 0; (k < schp->k_use_sg) && sg_scatg2virt(sclp);
- ++k, ++sclp) {
- num = (int) sclp->length;
- if (num > num_read_xfer) {
- if (__copy_to_user
- (outp, sg_scatg2virt(sclp), num_read_xfer))
- return -EFAULT;
+
+ for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) {
+ num = sg->length;
+ if (num > num_read_xfer) {
+ if (__copy_to_user(outp, page_address(sg->page),
+ num_read_xfer))
+ return -EFAULT;
+ break;
+ } else {
+ if (__copy_to_user(outp, page_address(sg->page),
+ num))
+ return -EFAULT;
+ num_read_xfer -= num;
+ if (num_read_xfer <= 0)
break;
- } else {
- if (__copy_to_user
- (outp, sg_scatg2virt(sclp), num))
- return -EFAULT;
- num_read_xfer -= num;
- if (num_read_xfer <= 0)
- break;
- outp += num;
- }
+ outp += num;
}
- } else {
- if (__copy_to_user(outp, schp->buffer, num_read_xfer))
- return -EFAULT;
}
+
return 0;
}
@@ -2306,44 +2157,31 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size)
{
Sg_scatter_hold *req_schp = &srp->data;
Sg_scatter_hold *rsv_schp = &sfp->reserve;
+ struct scatterlist *sg = rsv_schp->buffer;
+ int k, num, rem;
srp->res_used = 1;
SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size));
- size = (size + 1) & (~1); /* round to even for aha1542 */
- if (rsv_schp->k_use_sg > 0) {
- int k, num;
- int rem = size;
- struct scatterlist *sclp =
- (struct scatterlist *) rsv_schp->buffer;
-
- for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sclp) {
- num = (int) sclp->length;
- if (rem <= num) {
- if (0 == k) {
- req_schp->k_use_sg = 0;
- req_schp->buffer = sg_scatg2virt(sclp);
- } else {
- sfp->save_scat_len = num;
- sclp->length = (unsigned) rem;
- req_schp->k_use_sg = k + 1;
- req_schp->sglist_len =
- rsv_schp->sglist_len;
- req_schp->buffer = rsv_schp->buffer;
- }
- req_schp->bufflen = size;
- req_schp->b_malloc_len = rsv_schp->b_malloc_len;
- break;
- } else
- rem -= num;
- }
- if (k >= rsv_schp->k_use_sg)
- SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
- } else {
- req_schp->k_use_sg = 0;
- req_schp->bufflen = size;
- req_schp->buffer = rsv_schp->buffer;
- req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+ rem = size = (size + 1) & (~1); /* round to even for aha1542 */
+
+ for (k = 0; k < rsv_schp->k_use_sg; ++k, ++sg) {
+ num = sg->length;
+ if (rem <= num) {
+ sfp->save_scat_len = num;
+ sg->length = rem;
+ req_schp->k_use_sg = k + 1;
+ req_schp->sglist_len = rsv_schp->sglist_len;
+ req_schp->buffer = rsv_schp->buffer;
+
+ req_schp->bufflen = size;
+ req_schp->b_malloc_len = rsv_schp->b_malloc_len;
+ break;
+ } else
+ rem -= num;
}
+
+ if (k >= rsv_schp->k_use_sg)
+ SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n"));
}
static void
@@ -2355,11 +2193,10 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp)
SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n",
(int) req_schp->k_use_sg));
if ((rsv_schp->k_use_sg > 0) && (req_schp->k_use_sg > 0)) {
- struct scatterlist *sclp =
- (struct scatterlist *) rsv_schp->buffer;
+ struct scatterlist *sg = rsv_schp->buffer;
if (sfp->save_scat_len > 0)
- (sclp + (req_schp->k_use_sg - 1))->length =
+ (sg + (req_schp->k_use_sg - 1))->length =
(unsigned) sfp->save_scat_len;
else
SCSI_LOG_TIMEOUT(1, printk ("sg_unlink_reserve: BAD save_scat_len\n"));
@@ -2445,7 +2282,6 @@ sg_add_request(Sg_fd * sfp)
if (resp) {
resp->nextrp = NULL;
resp->header.duration = jiffies_to_msecs(jiffies);
- resp->my_cmdp = NULL;
}
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
return resp;
@@ -2463,8 +2299,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
if ((!sfp) || (!srp) || (!sfp->headrp))
return res;
write_lock_irqsave(&sfp->rq_list_lock, iflags);
- if (srp->my_cmdp)
- srp->my_cmdp->upper_private_data = NULL;
prev_rp = sfp->headrp;
if (srp == prev_rp) {
sfp->headrp = prev_rp->nextrp;
@@ -2507,10 +2341,10 @@ sg_add_sfp(Sg_device * sdp, int dev)
Sg_fd *sfp;
unsigned long iflags;
- sfp = (Sg_fd *) sg_page_malloc(sizeof (Sg_fd), 0, NULL);
+ sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN);
if (!sfp)
return NULL;
- memset(sfp, 0, sizeof (Sg_fd));
+
init_waitqueue_head(&sfp->read_wait);
rwlock_init(&sfp->rq_list_lock);
@@ -2567,7 +2401,7 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
}
sfp->parentdp = NULL;
SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: sfp=0x%p\n", sfp));
- sg_page_free((char *) sfp, sizeof (Sg_fd));
+ kfree(sfp);
}
/* Returns 0 in normal case, 1 when detached and sdp object removed */
@@ -2632,10 +2466,10 @@ sg_res_in_use(Sg_fd * sfp)
}
/* If retSzp==NULL want exact size or fail */
-static char *
+static struct page *
sg_page_malloc(int rqSz, int lowDma, int *retSzp)
{
- char *resp = NULL;
+ struct page *resp = NULL;
gfp_t page_mask;
int order, a_size;
int resSz = rqSz;
@@ -2650,16 +2484,16 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
for (order = 0, a_size = PAGE_SIZE; a_size < rqSz;
order++, a_size <<= 1) ;
- resp = (char *) __get_free_pages(page_mask, order);
+ resp = alloc_pages(page_mask, order);
while ((!resp) && order && retSzp) {
--order;
a_size >>= 1; /* divide by 2, until PAGE_SIZE */
- resp = (char *) __get_free_pages(page_mask, order); /* try half */
+ resp = alloc_pages(page_mask, order); /* try half */
resSz = a_size;
}
if (resp) {
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- memset(resp, 0, resSz);
+ memset(page_address(resp), 0, resSz);
if (retSzp)
*retSzp = resSz;
}
@@ -2667,15 +2501,15 @@ sg_page_malloc(int rqSz, int lowDma, int *retSzp)
}
static void
-sg_page_free(char *buff, int size)
+sg_page_free(struct page *page, int size)
{
int order, a_size;
- if (!buff)
+ if (!page)
return;
for (order = 0, a_size = PAGE_SIZE; a_size < size;
order++, a_size <<= 1) ;
- free_pages((unsigned long) buff, order);
+ __free_pages(page, order);
}
#ifndef MAINTENANCE_IN_CMD
@@ -3067,13 +2901,11 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
cp = " ";
}
seq_printf(s, cp);
- blen = srp->my_cmdp ?
- srp->my_cmdp->sr_bufflen : srp->data.bufflen;
- usg = srp->my_cmdp ?
- srp->my_cmdp->sr_use_sg : srp->data.k_use_sg;
+ blen = srp->data.bufflen;
+ usg = srp->data.k_use_sg;
seq_printf(s, srp->done ?
((1 == srp->done) ? "rcv:" : "fin:")
- : (srp->my_cmdp ? "act:" : "prior:"));
+ : "act:");
seq_printf(s, " id=%d blen=%d",
srp->header.pack_id, blen);
if (srp->done)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index fb4012b5c188..997f8e30509b 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -44,6 +44,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/blkdev.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock);
/* This semaphore is used to mediate the 0->1 reference get in the
* face of object destruction (i.e. we can't allow a get on an
* object after last put) */
-static DECLARE_MUTEX(sr_ref_sem);
+static DEFINE_MUTEX(sr_ref_mutex);
static int sr_open(struct cdrom_device_info *, int);
static void sr_release(struct cdrom_device_info *);
@@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
{
struct scsi_cd *cd = NULL;
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
if (disk->private_data == NULL)
goto out;
cd = scsi_cd(disk);
@@ -146,18 +147,18 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
kref_put(&cd->kref, sr_kref_release);
cd = NULL;
out:
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
return cd;
}
-static inline void scsi_cd_put(struct scsi_cd *cd)
+static void scsi_cd_put(struct scsi_cd *cd)
{
struct scsi_device *sdev = cd->device;
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
scsi_device_put(sdev);
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
}
/*
@@ -237,8 +238,6 @@ static void rw_intr(struct scsi_cmnd * SCpnt)
case ILLEGAL_REQUEST:
if (!(SCpnt->sense_buffer[0] & 0x90))
break;
- if (!blk_fs_request(SCpnt->request))
- break;
error_sector = (SCpnt->sense_buffer[3] << 24) |
(SCpnt->sense_buffer[4] << 16) |
(SCpnt->sense_buffer[5] << 8) |
@@ -317,23 +316,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
}
/*
- * these are already setup, just copy cdb basically
- */
- if (SCpnt->request->flags & REQ_BLOCK_PC) {
- scsi_setup_blk_pc_cmnd(SCpnt, MAX_RETRIES);
-
- if (SCpnt->timeout_per_command)
- timeout = SCpnt->timeout_per_command;
-
- goto queue;
- }
-
- if (!(SCpnt->request->flags & REQ_CMD)) {
- blk_dump_rq_flags(SCpnt->request, "sr unsup command");
- return 0;
- }
-
- /*
* we do lazy blocksize switching (when reading XA sectors,
* see CDROMREADMODE2 ioctl)
*/
@@ -421,8 +403,6 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
*/
SCpnt->transfersize = cd->device->sector_size;
SCpnt->underflow = this_count << 9;
-
-queue:
SCpnt->allowed = MAX_RETRIES;
SCpnt->timeout_per_command = timeout;
@@ -716,7 +696,7 @@ static void get_capabilities(struct scsi_cd *cd)
unsigned int the_result;
int retries, rc, n;
- static char *loadmech[] =
+ static const char *loadmech[] =
{
"caddy",
"tray",
@@ -762,8 +742,9 @@ static void get_capabilities(struct scsi_cd *cd)
/* failed, drive doesn't have capabilities mode page */
cd->cdi.speed = 1;
cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R |
- CDC_DVD | CDC_DVD_RAM |
- CDC_SELECT_DISC | CDC_SELECT_SPEED);
+ CDC_DVD | CDC_DVD_RAM |
+ CDC_SELECT_DISC | CDC_SELECT_SPEED |
+ CDC_MRW | CDC_MRW_W | CDC_RAM);
kfree(buffer);
printk("%s: scsi-1 drive\n", cd->cdi.name);
return;
@@ -845,7 +826,7 @@ static int sr_packet(struct cdrom_device_info *cdi,
* sr_kref_release - Called to free the scsi_cd structure
* @kref: pointer to embedded kref
*
- * sr_ref_sem must be held entering this routine. Because it is
+ * sr_ref_mutex must be held entering this routine. Because it is
* called on last put, you should always use the scsi_cd_get()
* scsi_cd_put() helpers which manipulate the semaphore directly
* and never do a direct kref_put().
@@ -874,9 +855,9 @@ static int sr_remove(struct device *dev)
del_gendisk(cd->disk);
- down(&sr_ref_sem);
+ mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
- up(&sr_ref_sem);
+ mutex_unlock(&sr_ref_mutex);
return 0;
}
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 6e45ac3c43c5..5d02ff4db6cc 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -31,6 +31,79 @@ static int xa_test = 0;
module_param(xa_test, int, S_IRUGO | S_IWUSR);
+/* primitive to determine whether we need to have GFP_DMA set based on
+ * the status of the unchecked_isa_dma flag in the host structure */
+#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
+
+
+static int sr_read_tochdr(struct cdrom_device_info *cdi,
+ struct cdrom_tochdr *tochdr)
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+ unsigned char *buffer;
+
+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+ if (!buffer)
+ return -ENOMEM;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cgc.cmd[8] = 12; /* LSB of length */
+ cgc.buffer = buffer;
+ cgc.buflen = 12;
+ cgc.quiet = 1;
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
+
+ tochdr->cdth_trk0 = buffer[2];
+ tochdr->cdth_trk1 = buffer[3];
+
+ kfree(buffer);
+ return result;
+}
+
+static int sr_read_tocentry(struct cdrom_device_info *cdi,
+ struct cdrom_tocentry *tocentry)
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+ unsigned char *buffer;
+
+ buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
+ if (!buffer)
+ return -ENOMEM;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
+ cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
+ cgc.cmd[6] = tocentry->cdte_track;
+ cgc.cmd[8] = 12; /* LSB of length */
+ cgc.buffer = buffer;
+ cgc.buflen = 12;
+ cgc.data_direction = DMA_FROM_DEVICE;
+
+ result = sr_do_ioctl(cd, &cgc);
+
+ tocentry->cdte_ctrl = buffer[5] & 0xf;
+ tocentry->cdte_adr = buffer[5] >> 4;
+ tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
+ if (tocentry->cdte_format == CDROM_MSF) {
+ tocentry->cdte_addr.msf.minute = buffer[9];
+ tocentry->cdte_addr.msf.second = buffer[10];
+ tocentry->cdte_addr.msf.frame = buffer[11];
+ } else
+ tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
+ + buffer[10]) << 8) + buffer[11];
+
+ kfree(buffer);
+ return result;
+}
#define IOCTL_RETRIES 3
@@ -45,7 +118,8 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
struct packet_command cgc;
int ntracks, ret;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr)))
+ ret = sr_read_tochdr(cdi, &tochdr);
+ if (ret)
return ret;
ntracks = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
@@ -60,9 +134,11 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
trk1_te.cdte_track = ti->cdti_trk1;
trk1_te.cdte_format = CDROM_MSF;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk0_te)))
+ ret = sr_read_tocentry(cdi, &trk0_te);
+ if (ret)
return ret;
- if ((ret = sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &trk1_te)))
+ ret = sr_read_tocentry(cdi, &trk1_te);
+ if (ret)
return ret;
memset(&cgc, 0, sizeof(struct packet_command));
@@ -78,6 +154,30 @@ static int sr_fake_playtrkind(struct cdrom_device_info *cdi, struct cdrom_ti *ti
return sr_do_ioctl(cdi->handle, &cgc);
}
+static int sr_play_trkind(struct cdrom_device_info *cdi,
+ struct cdrom_ti *ti)
+
+{
+ struct scsi_cd *cd = cdi->handle;
+ struct packet_command cgc;
+ int result;
+
+ memset(&cgc, 0, sizeof(struct packet_command));
+ cgc.timeout = IOCTL_TIMEOUT;
+ cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
+ cgc.cmd[4] = ti->cdti_trk0;
+ cgc.cmd[5] = ti->cdti_ind0;
+ cgc.cmd[7] = ti->cdti_trk1;
+ cgc.cmd[8] = ti->cdti_ind1;
+ cgc.data_direction = DMA_NONE;
+
+ result = sr_do_ioctl(cd, &cgc);
+ if (result == -EDRIVE_CANT_DO_THIS)
+ result = sr_fake_playtrkind(cdi, ti);
+
+ return result;
+}
+
/* We do our own retries because we want to know what the specific
error code is. Normally the UNIT_ATTENTION code will automatically
clear after one error */
@@ -229,13 +329,14 @@ int sr_disk_status(struct cdrom_device_info *cdi)
int i, rc, have_datatracks = 0;
/* look for data tracks */
- if (0 != (rc = sr_audio_ioctl(cdi, CDROMREADTOCHDR, &toc_h)))
+ rc = sr_read_tochdr(cdi, &toc_h);
+ if (rc)
return (rc == -ENOMEDIUM) ? CDS_NO_DISC : CDS_NO_INFO;
for (i = toc_h.cdth_trk0; i <= toc_h.cdth_trk1; i++) {
toc_e.cdte_track = i;
toc_e.cdte_format = CDROM_LBA;
- if (sr_audio_ioctl(cdi, CDROMREADTOCENTRY, &toc_e))
+ if (sr_read_tocentry(cdi, &toc_e))
return CDS_NO_INFO;
if (toc_e.cdte_ctrl & CDROM_DATA_TRACK) {
have_datatracks = 1;
@@ -262,10 +363,6 @@ int sr_get_last_session(struct cdrom_device_info *cdi,
return 0;
}
-/* primitive to determine whether we need to have GFP_DMA set based on
- * the status of the unchecked_isa_dma flag in the host structure */
-#define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0)
-
int sr_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
{
Scsi_CD *cd = cdi->handle;
@@ -329,93 +426,16 @@ int sr_select_speed(struct cdrom_device_info *cdi, int speed)
int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg)
{
- Scsi_CD *cd = cdi->handle;
- struct packet_command cgc;
- int result;
- unsigned char *buffer = kmalloc(32, GFP_KERNEL | SR_GFP_DMA(cd));
-
- if (!buffer)
- return -ENOMEM;
-
- memset(&cgc, 0, sizeof(struct packet_command));
- cgc.timeout = IOCTL_TIMEOUT;
-
switch (cmd) {
case CDROMREADTOCHDR:
- {
- struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
-
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[8] = 12; /* LSB of length */
- cgc.buffer = buffer;
- cgc.buflen = 12;
- cgc.quiet = 1;
- cgc.data_direction = DMA_FROM_DEVICE;
-
- result = sr_do_ioctl(cd, &cgc);
-
- tochdr->cdth_trk0 = buffer[2];
- tochdr->cdth_trk1 = buffer[3];
-
- break;
- }
-
+ return sr_read_tochdr(cdi, arg);
case CDROMREADTOCENTRY:
- {
- struct cdrom_tocentry *tocentry = (struct cdrom_tocentry *) arg;
-
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] |= (tocentry->cdte_format == CDROM_MSF) ? 0x02 : 0;
- cgc.cmd[6] = tocentry->cdte_track;
- cgc.cmd[8] = 12; /* LSB of length */
- cgc.buffer = buffer;
- cgc.buflen = 12;
- cgc.data_direction = DMA_FROM_DEVICE;
-
- result = sr_do_ioctl(cd, &cgc);
-
- tocentry->cdte_ctrl = buffer[5] & 0xf;
- tocentry->cdte_adr = buffer[5] >> 4;
- tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04) ? 1 : 0;
- if (tocentry->cdte_format == CDROM_MSF) {
- tocentry->cdte_addr.msf.minute = buffer[9];
- tocentry->cdte_addr.msf.second = buffer[10];
- tocentry->cdte_addr.msf.frame = buffer[11];
- } else
- tocentry->cdte_addr.lba = (((((buffer[8] << 8) + buffer[9]) << 8)
- + buffer[10]) << 8) + buffer[11];
-
- break;
- }
-
- case CDROMPLAYTRKIND: {
- struct cdrom_ti* ti = (struct cdrom_ti*)arg;
-
- cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
- cgc.cmd[4] = ti->cdti_trk0;
- cgc.cmd[5] = ti->cdti_ind0;
- cgc.cmd[7] = ti->cdti_trk1;
- cgc.cmd[8] = ti->cdti_ind1;
- cgc.data_direction = DMA_NONE;
-
- result = sr_do_ioctl(cd, &cgc);
- if (result == -EDRIVE_CANT_DO_THIS)
- result = sr_fake_playtrkind(cdi, ti);
-
- break;
- }
-
+ return sr_read_tocentry(cdi, arg);
+ case CDROMPLAYTRKIND:
+ return sr_play_trkind(cdi, arg);
default:
- result = -EINVAL;
+ return -EINVAL;
}
-
-#if 0
- if (result)
- printk("DEBUG: sr_audio: result for ioctl %x: %x\n", cmd, result);
-#endif
-
- kfree(buffer);
- return result;
}
/* -----------------------------------------------------------------------
diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c
index 78274dc91f5c..9dde8df2f5c9 100644
--- a/drivers/scsi/sr_vendor.c
+++ b/drivers/scsi/sr_vendor.c
@@ -68,8 +68,8 @@ void sr_vendor_init(Scsi_CD *cd)
#ifndef CONFIG_BLK_DEV_SR_VENDOR
cd->vendor = VENDOR_SCSI3;
#else
- char *vendor = cd->device->vendor;
- char *model = cd->device->model;
+ const char *vendor = cd->device->vendor;
+ const char *model = cd->device->model;
/* default */
cd->vendor = VENDOR_SCSI3;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index dd592f6a2529..13b1d3aac265 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 = "20050830";
+static const char *verstr = "20050830";
#include <linux/module.h>
@@ -38,6 +38,7 @@ static char *verstr = "20050830";
#include <linux/devfs_fs_kernel.h>
#include <linux/cdev.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
@@ -50,7 +51,6 @@ static char *verstr = "20050830";
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
#include <scsi/sg.h>
@@ -134,7 +134,7 @@ static struct st_dev_parm {
#endif
/* Bit reversed order to get same names for same minors with all
mode counts */
-static char *st_formats[] = {
+static const char *st_formats[] = {
"", "r", "k", "s", "l", "t", "o", "u",
"m", "v", "p", "x", "a", "y", "q", "z"};
@@ -188,15 +188,12 @@ static int from_buffer(struct st_buffer *, char __user *, int);
static void move_buffer_data(struct st_buffer *, int);
static void buf_to_sg(struct st_buffer *, unsigned int);
-static int st_map_user_pages(struct scatterlist *, const unsigned int,
- unsigned long, size_t, int, unsigned long);
static int sgl_map_user_pages(struct scatterlist *, const unsigned int,
unsigned long, size_t, int);
static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
static int st_probe(struct device *);
static int st_remove(struct device *);
-static int st_init_command(struct scsi_cmnd *);
static void do_create_driverfs_files(void);
static void do_remove_driverfs_files(void);
@@ -209,7 +206,6 @@ static struct scsi_driver st_template = {
.probe = st_probe,
.remove = st_remove,
},
- .init_command = st_init_command,
};
static int st_compression(struct scsi_tape *, int);
@@ -223,7 +219,7 @@ 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);
+static DEFINE_MUTEX(st_ref_mutex);
#include "osst_detect.h"
@@ -240,7 +236,7 @@ static struct scsi_tape *scsi_tape_get(int dev)
{
struct scsi_tape *STp = NULL;
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
write_lock(&st_dev_arr_lock);
if (dev < st_dev_max && scsi_tapes != NULL)
@@ -262,7 +258,7 @@ out_put:
STp = NULL;
out:
write_unlock(&st_dev_arr_lock);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
return STp;
}
@@ -270,10 +266,10 @@ static void scsi_tape_put(struct scsi_tape *STp)
{
struct scsi_device *sdev = STp->device;
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
kref_put(&STp->kref, scsi_tape_release);
scsi_device_put(sdev);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
}
struct st_reject_data {
@@ -313,12 +309,13 @@ static inline char *tape_name(struct scsi_tape *tape)
}
-static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
+static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s)
{
const u8 *ucp;
- const u8 *sense = SRpnt->sr_sense_buffer;
+ const u8 *sense = SRpnt->sense;
- s->have_sense = scsi_request_normalize_sense(SRpnt, &s->sense_hdr);
+ s->have_sense = scsi_normalize_sense(SRpnt->sense,
+ SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
s->flags = 0;
if (s->have_sense) {
@@ -345,9 +342,9 @@ static void st_analyze_sense(struct scsi_request *SRpnt, struct st_cmdstatus *s)
/* Convert the result to success code */
-static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
+static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
{
- int result = SRpnt->sr_result;
+ int result = SRpnt->result;
u8 scode;
DEB(const char *stp;)
char *name = tape_name(STp);
@@ -366,13 +363,12 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
DEB(
if (debugging) {
- printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
+ printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n",
name, result,
- SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
- SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
- SRpnt->sr_bufflen);
+ SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
+ SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
if (cmdstatp->have_sense)
- scsi_print_req_sense("st", SRpnt);
+ __scsi_print_sense("st", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
} ) /* end DEB */
if (!debugging) { /* Abnormal conditions for tape */
if (!cmdstatp->have_sense)
@@ -386,20 +382,21 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
/* scode != UNIT_ATTENTION && */
scode != BLANK_CHECK &&
scode != VOLUME_OVERFLOW &&
- SRpnt->sr_cmnd[0] != MODE_SENSE &&
- SRpnt->sr_cmnd[0] != TEST_UNIT_READY) {
+ SRpnt->cmd[0] != MODE_SENSE &&
+ SRpnt->cmd[0] != TEST_UNIT_READY) {
printk(KERN_WARNING "%s: Error with sense data: ", name);
- scsi_print_req_sense("st", SRpnt);
+ __scsi_print_sense("st", SRpnt->sense,
+ SCSI_SENSE_BUFFERSIZE);
}
}
if (cmdstatp->fixed_format &&
STp->cln_mode >= EXTENDED_SENSE_START) { /* Only fixed format sense */
if (STp->cln_sense_value)
- STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+ STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
STp->cln_sense_mask) == STp->cln_sense_value);
else
- STp->cleaning_req |= ((SRpnt->sr_sense_buffer[STp->cln_mode] &
+ STp->cleaning_req |= ((SRpnt->sense[STp->cln_mode] &
STp->cln_sense_mask) != 0);
}
if (cmdstatp->have_sense &&
@@ -411,8 +408,8 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
if (cmdstatp->have_sense &&
scode == RECOVERED_ERROR
#if ST_RECOVERED_WRITE_FATAL
- && SRpnt->sr_cmnd[0] != WRITE_6
- && SRpnt->sr_cmnd[0] != WRITE_FILEMARKS
+ && SRpnt->cmd[0] != WRITE_6
+ && SRpnt->cmd[0] != WRITE_FILEMARKS
#endif
) {
STp->recover_count++;
@@ -420,9 +417,9 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
DEB(
if (debugging) {
- if (SRpnt->sr_cmnd[0] == READ_6)
+ if (SRpnt->cmd[0] == READ_6)
stp = "read";
- else if (SRpnt->sr_cmnd[0] == WRITE_6)
+ else if (SRpnt->cmd[0] == WRITE_6)
stp = "write";
else
stp = "ioctl";
@@ -438,28 +435,37 @@ static int st_chk_result(struct scsi_tape *STp, struct scsi_request * SRpnt)
/* Wakeup from interrupt */
-static void st_sleep_done(struct scsi_cmnd * SCpnt)
+static void st_sleep_done(void *data, char *sense, int result, int resid)
{
- struct scsi_tape *STp = container_of(SCpnt->request->rq_disk->private_data,
- struct scsi_tape, driver);
+ struct st_request *SRpnt = data;
+ struct scsi_tape *STp = SRpnt->stp;
- (STp->buffer)->cmdstat.midlevel_result = SCpnt->result;
- SCpnt->request->rq_status = RQ_SCSI_DONE;
+ memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
+ (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
DEB( STp->write_pending = 0; )
- if (SCpnt->request->waiting)
- complete(SCpnt->request->waiting);
+ if (SRpnt->waiting)
+ complete(SRpnt->waiting);
+}
+
+static struct st_request *st_allocate_request(void)
+{
+ return kzalloc(sizeof(struct st_request), GFP_KERNEL);
+}
+
+static void st_release_request(struct st_request *streq)
+{
+ kfree(streq);
}
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise write_behind_check() is used to check that the command
has finished. */
-static struct scsi_request *
-st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd,
+static struct st_request *
+st_do_scsi(struct st_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)) {
@@ -473,7 +479,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
}
if (SRpnt == NULL) {
- SRpnt = scsi_allocate_request(STp->device, GFP_ATOMIC);
+ SRpnt = st_allocate_request();
if (SRpnt == NULL) {
DEBC( printk(KERN_ERR "%s: Can't get SCSI request.\n",
tape_name(STp)); );
@@ -483,6 +489,7 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
(STp->buffer)->syscall_result = (-EBUSY);
return NULL;
}
+ SRpnt->stp = STp;
}
/* If async IO, set last_SRpnt. This ptr tells write_behind_check
@@ -492,32 +499,28 @@ st_do_scsi(struct scsi_request * SRpnt, struct scsi_tape * STp, unsigned char *c
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)
- buf_to_sg(STp->buffer, bytes);
- SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
- bp = (char *) &((STp->buffer)->sg[0]);
- } else
- bp = (STp->buffer)->b_data;
- SRpnt->sr_data_direction = direction;
- SRpnt->sr_cmd_len = 0;
- 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;
+ SRpnt->waiting = waiting;
- scsi_do_req(SRpnt, (void *) cmd, bp, bytes,
- st_sleep_done, timeout, retries);
+ if (!STp->buffer->do_dio)
+ buf_to_sg(STp->buffer, bytes);
- if (do_wait) {
+ memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
+ STp->buffer->cmdstat.have_sense = 0;
+ STp->buffer->syscall_result = 0;
+
+ if (scsi_execute_async(STp->device, cmd, direction,
+ &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
+ timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
+ /* could not allocate the buffer or request was too large */
+ (STp->buffer)->syscall_result = (-EBUSY);
+ (STp->buffer)->last_SRpnt = NULL;
+ }
+ else if (do_wait) {
wait_for_completion(waiting);
- SRpnt->sr_request->waiting = NULL;
- if (SRpnt->sr_request->rq_status != RQ_SCSI_DONE)
- SRpnt->sr_result |= (DRIVER_ERROR << 24);
+ SRpnt->waiting = NULL;
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
}
+
return SRpnt;
}
@@ -532,7 +535,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;
+ struct st_request *SRpnt;
STbuffer = STp->buffer;
if (!STbuffer->writing)
@@ -548,12 +551,10 @@ static int write_behind_check(struct scsi_tape * STp)
wait_for_completion(&(STp->wait));
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);
+ SRpnt->waiting = NULL;
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
STbuffer->buffer_bytes -= STbuffer->writing;
STps = &(STp->ps[STp->partition]);
@@ -593,7 +594,7 @@ static int write_behind_check(struct scsi_tape * STp)
it messes up the block number). */
static int cross_eof(struct scsi_tape * STp, int forward)
{
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
unsigned char cmd[MAX_COMMAND_SIZE];
cmd[0] = SPACE;
@@ -613,7 +614,7 @@ static int cross_eof(struct scsi_tape * STp, int forward)
if (!SRpnt)
return (STp->buffer)->syscall_result;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
if ((STp->buffer)->cmdstat.midlevel_result != 0)
@@ -630,7 +631,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
int offset, transfer, blks;
int result;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
struct st_partstat *STps;
result = write_behind_check(STp);
@@ -688,7 +689,7 @@ static int flush_write_buffer(struct scsi_tape * STp)
STp->dirty = 0;
(STp->buffer)->buffer_bytes = 0;
}
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
}
return result;
@@ -785,7 +786,7 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm)
}
-/* Lock or unlock the drive door. Don't use when scsi_request allocated. */
+/* Lock or unlock the drive door. Don't use when st_request allocated. */
static int do_door_lock(struct scsi_tape * STp, int do_lock)
{
int retval, cmd;
@@ -844,7 +845,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
int attentions, waits, max_wait, scode;
int retval = CHKRES_READY, new_session = 0;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
@@ -903,7 +904,7 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
}
if (SRpnt != NULL)
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
return retval;
}
@@ -918,7 +919,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
int i, retval, new_session = 0, do_wait;
unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;
unsigned short st_flags = filp->f_flags;
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
struct st_modedef *STm;
struct st_partstat *STps;
char *name = tape_name(STp);
@@ -993,7 +994,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
goto err_out;
}
- if (!SRpnt->sr_result && !STp->buffer->cmdstat.have_sense) {
+ if (!SRpnt->result && !STp->buffer->cmdstat.have_sense) {
STp->max_block = ((STp->buffer)->b_data[1] << 16) |
((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
STp->min_block = ((STp->buffer)->b_data[4] << 8) |
@@ -1045,7 +1046,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
}
STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
}
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
STp->inited = 1;
@@ -1196,7 +1197,7 @@ static int st_flush(struct file *filp)
{
int result = 0, result2;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
struct scsi_tape *STp = filp->private_data;
struct st_modedef *STm = &(STp->modes[STp->current_mode]);
struct st_partstat *STps = &(STp->ps[STp->partition]);
@@ -1249,7 +1250,7 @@ static int st_flush(struct file *filp)
cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
(!cmdstatp->remainder_valid || cmdstatp->uremainder64 == 0))) {
/* Write successful at EOM */
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
if (STps->drv_file >= 0)
STps->drv_file++;
@@ -1259,7 +1260,7 @@ static int st_flush(struct file *filp)
STps->eof = ST_FM;
}
else { /* Write error */
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
printk(KERN_ERR "%s: Error on write filemark.\n", name);
if (result == 0)
@@ -1400,11 +1401,11 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
i = STp->try_dio && try_rdio;
else
i = STp->try_dio && try_wdio;
+
if (i && ((unsigned long)buf & queue_dma_alignment(
STp->device->request_queue)) == 0) {
- i = st_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
- (unsigned long)buf, count, (is_read ? READ : WRITE),
- STp->max_pfn);
+ i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
+ (unsigned long)buf, count, (is_read ? READ : WRITE));
if (i > 0) {
STbp->do_dio = i;
STbp->buffer_bytes = 0; /* can be used as transfer counter */
@@ -1449,14 +1450,15 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
/* Can be called more than once after each setup_buffer() */
-static void release_buffering(struct scsi_tape *STp)
+static void release_buffering(struct scsi_tape *STp, int is_read)
{
struct st_buffer *STbp;
STbp = STp->buffer;
if (STbp->do_dio) {
- sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, 0);
+ sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
STbp->do_dio = 0;
+ STbp->sg_segs = 0;
}
}
@@ -1472,7 +1474,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
int async_write;
unsigned char cmd[MAX_COMMAND_SIZE];
const char __user *b_point;
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
struct scsi_tape *STp = filp->private_data;
struct st_modedef *STm;
struct st_partstat *STps;
@@ -1624,7 +1626,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
retval = STbp->syscall_result;
goto out;
}
- if (async_write) {
+ if (async_write && !STbp->syscall_result) {
STbp->writing = transfer;
STp->dirty = !(STbp->writing ==
STbp->buffer_bytes);
@@ -1698,7 +1700,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
} else {
count += do_count;
STps->drv_block = (-1); /* Too cautious? */
- retval = (-EIO);
+ retval = STbp->syscall_result;
}
}
@@ -1728,8 +1730,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
out:
if (SRpnt != NULL)
- scsi_release_request(SRpnt);
- release_buffering(STp);
+ st_release_request(SRpnt);
+ release_buffering(STp, 0);
up(&STp->lock);
return retval;
@@ -1742,11 +1744,11 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
Does release user buffer mapping if it is set.
*/
static long read_tape(struct scsi_tape *STp, long count,
- struct scsi_request ** aSRpnt)
+ struct st_request ** aSRpnt)
{
int transfer, blks, bytes;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
struct st_modedef *STm;
struct st_partstat *STps;
struct st_buffer *STbp;
@@ -1787,7 +1789,7 @@ static long read_tape(struct scsi_tape *STp, long count,
SRpnt = *aSRpnt;
SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, DMA_FROM_DEVICE,
STp->device->timeout, MAX_RETRIES, 1);
- release_buffering(STp);
+ release_buffering(STp, 1);
*aSRpnt = SRpnt;
if (!SRpnt)
return STbp->syscall_result;
@@ -1802,10 +1804,10 @@ static long read_tape(struct scsi_tape *STp, long count,
retval = 1;
DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
name,
- SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
- SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
- SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
- SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));
+ SRpnt->sense[0], SRpnt->sense[1],
+ SRpnt->sense[2], SRpnt->sense[3],
+ SRpnt->sense[4], SRpnt->sense[5],
+ SRpnt->sense[6], SRpnt->sense[7]));
if (cmdstatp->have_sense) {
if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
@@ -1835,7 +1837,7 @@ static long read_tape(struct scsi_tape *STp, long count,
}
STbp->buffer_bytes = bytes - transfer;
} else {
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = *aSRpnt = NULL;
if (transfer == blks) { /* We did not get anything, error */
printk(KERN_NOTICE "%s: Incorrect block size.\n", name);
@@ -1929,7 +1931,7 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
ssize_t retval = 0;
ssize_t i, transfer;
int special, do_dio = 0;
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
struct scsi_tape *STp = filp->private_data;
struct st_modedef *STm;
struct st_partstat *STps;
@@ -2054,11 +2056,11 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
out:
if (SRpnt != NULL) {
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
}
if (do_dio) {
- release_buffering(STp);
+ release_buffering(STp, 1);
STbp->buffer_bytes = 0;
}
up(&STp->lock);
@@ -2284,7 +2286,7 @@ static int st_set_options(struct scsi_tape *STp, long options)
static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
{
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SENSE;
@@ -2298,7 +2300,7 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
if (SRpnt == NULL)
return (STp->buffer)->syscall_result;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
return (STp->buffer)->syscall_result;
}
@@ -2310,7 +2312,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
{
int pgo;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt = NULL;
+ struct st_request *SRpnt = NULL;
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
@@ -2329,7 +2331,7 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
if (SRpnt == NULL)
return (STp->buffer)->syscall_result;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
return (STp->buffer)->syscall_result;
}
@@ -2412,7 +2414,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
DEB( char *name = tape_name(STp); )
unsigned char cmd[MAX_COMMAND_SIZE];
struct st_partstat *STps;
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
if (STp->ready != ST_READY && !load_code) {
if (STp->ready == ST_NO_TAPE)
@@ -2455,7 +2457,7 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
return (STp->buffer)->syscall_result;
retval = (STp->buffer)->syscall_result;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
if (!retval) { /* SCSI command successful */
@@ -2503,7 +2505,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
int ioctl_result;
int chg_eof = 1;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
struct st_partstat *STps;
int fileno, blkno, at_sm, undone;
int datalen = 0, direction = DMA_NONE;
@@ -2757,7 +2759,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
ioctl_result = (STp->buffer)->syscall_result;
if (!ioctl_result) { /* SCSI command successful */
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
STps->drv_block = blkno;
STps->drv_file = fileno;
@@ -2872,7 +2874,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
/* Try the other possible state of Page Format if not
already tried */
STp->use_pf = !STp->use_pf | PF_TESTED;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
return st_int_ioctl(STp, cmd_in, arg);
}
@@ -2882,7 +2884,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK)
STps->eof = ST_EOD;
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
}
@@ -2898,7 +2900,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
{
int result;
unsigned char scmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
DEB( char *name = tape_name(STp); )
if (STp->ready != ST_READY)
@@ -2944,7 +2946,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
*block, *partition));
}
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
return result;
@@ -2961,7 +2963,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
unsigned int blk;
int timeout;
unsigned char scmd[MAX_COMMAND_SIZE];
- struct scsi_request *SRpnt;
+ struct st_request *SRpnt;
DEB( char *name = tape_name(STp); )
if (STp->ready != ST_READY)
@@ -3047,7 +3049,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
result = 0;
}
- scsi_release_request(SRpnt);
+ st_release_request(SRpnt);
SRpnt = NULL;
return result;
@@ -3577,7 +3579,7 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
static struct st_buffer *
new_tape_buffer(int from_initialization, int need_dma, int max_sg)
{
- int i, got = 0, segs = 0;
+ int i, got = 0;
gfp_t priority;
struct st_buffer *tb;
@@ -3594,10 +3596,8 @@ static struct st_buffer *
return NULL;
}
memset(tb, 0, i);
- tb->frp_segs = tb->orig_frp_segs = segs;
+ tb->frp_segs = tb->orig_frp_segs = 0;
tb->use_sg = max_sg;
- if (segs > 0)
- tb->b_data = page_address(tb->sg[0].page);
tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
tb->in_use = 1;
@@ -3628,7 +3628,7 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
priority = GFP_KERNEL | __GFP_NOWARN;
if (need_dma)
priority |= GFP_DMA;
- for (b_size = PAGE_SIZE, order=0;
+ for (b_size = PAGE_SIZE, order=0; order <= 6 &&
b_size < new_size - STbuffer->buffer_size;
order++, b_size *= 2)
; /* empty */
@@ -3670,6 +3670,7 @@ static void normalize_buffer(struct st_buffer * STbuffer)
}
STbuffer->frp_segs = STbuffer->orig_frp_segs;
STbuffer->frp_sg_current = 0;
+ STbuffer->sg_segs = 0;
}
@@ -3882,7 +3883,6 @@ static int st_probe(struct device *dev)
struct st_buffer *buffer;
int i, j, mode, dev_num, error;
char *stp;
- u64 bounce_limit;
if (SDp->type != TYPE_TAPE)
return -ENODEV;
@@ -3892,7 +3892,8 @@ static int st_probe(struct device *dev)
return -ENODEV;
}
- i = SDp->host->sg_tablesize;
+ i = min(SDp->request_queue->max_hw_segments,
+ SDp->request_queue->max_phys_segments);
if (st_max_sg_segs < i)
i = st_max_sg_segs;
buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
@@ -3994,11 +3995,6 @@ static int st_probe(struct device *dev)
tpnt->long_timeout = ST_LONG_TIMEOUT;
tpnt->try_dio = try_direct_io && !SDp->host->unchecked_isa_dma;
- bounce_limit = scsi_calculate_bounce_limit(SDp->host) >> PAGE_SHIFT;
- if (bounce_limit > ULONG_MAX)
- bounce_limit = ULONG_MAX;
- tpnt->max_pfn = bounce_limit;
-
for (i = 0; i < ST_NBR_MODES; i++) {
STm = &(tpnt->modes[i]);
STm->defined = 0;
@@ -4077,9 +4073,9 @@ static int st_probe(struct device *dev)
sdev_printk(KERN_WARNING, SDp,
"Attached scsi tape %s", tape_name(tpnt));
- printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B), max page reachable by HBA %lu\n",
+ printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n",
tape_name(tpnt), tpnt->try_dio ? "yes" : "no",
- queue_dma_alignment(SDp->request_queue) + 1, tpnt->max_pfn);
+ queue_dma_alignment(SDp->request_queue) + 1);
return 0;
@@ -4144,9 +4140,9 @@ static int st_remove(struct device *dev)
}
}
- down(&st_ref_sem);
+ mutex_lock(&st_ref_mutex);
kref_put(&tpnt->kref, scsi_tape_release);
- up(&st_ref_sem);
+ mutex_unlock(&st_ref_mutex);
return 0;
}
}
@@ -4159,7 +4155,7 @@ static int st_remove(struct device *dev)
* 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
+ * st_ref_mutex 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().
@@ -4183,25 +4179,6 @@ static void scsi_tape_release(struct kref *kref)
return;
}
-static void st_intr(struct scsi_cmnd *SCpnt)
-{
- scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1);
-}
-
-/*
- * st_init_command: only called via the scsi_cmd_ioctl (block SG_IO)
- * interface for REQ_BLOCK_PC commands.
- */
-static int st_init_command(struct scsi_cmnd *SCpnt)
-{
- if (!(SCpnt->request->flags & REQ_BLOCK_PC))
- return 0;
-
- scsi_setup_blk_pc_cmnd(SCpnt, 0);
- SCpnt->done = st_intr;
- return 1;
-}
-
static int __init init_st(void)
{
validate_options();
@@ -4390,34 +4367,6 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
return;
}
-
-/* Pin down user pages and put them into a scatter gather list. Returns <= 0 if
- - mapping of all pages not successful
- - any page is above max_pfn
- (i.e., either completely successful or fails)
-*/
-static int st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
- unsigned long uaddr, size_t count, int rw,
- unsigned long max_pfn)
-{
- int i, nr_pages;
-
- nr_pages = sgl_map_user_pages(sgl, max_pages, uaddr, count, rw);
- if (nr_pages <= 0)
- return nr_pages;
-
- for (i=0; i < nr_pages; i++) {
- if (page_to_pfn(sgl[i].page) > max_pfn)
- goto out_unmap;
- }
- return nr_pages;
-
- out_unmap:
- sgl_unmap_user_pages(sgl, nr_pages, 0);
- return 0;
-}
-
-
/* The following functions may be useful for a larger audience. */
static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
unsigned long uaddr, size_t count, int rw)
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index 790acac160bc..411209048d74 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -4,6 +4,7 @@
#include <linux/completion.h>
#include <linux/kref.h>
+#include <scsi/scsi_cmnd.h>
/* Descriptor for analyzed sense data */
struct st_cmdstatus {
@@ -17,6 +18,17 @@ struct st_cmdstatus {
u8 deferred;
};
+struct scsi_tape;
+
+/* scsi tape command */
+struct st_request {
+ unsigned char cmd[MAX_COMMAND_SIZE];
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+ int result;
+ struct scsi_tape *stp;
+ struct completion *waiting;
+};
+
/* The tape buffer descriptor. */
struct st_buffer {
unsigned char in_use;
@@ -28,7 +40,7 @@ struct st_buffer {
int read_pointer;
int writing;
int syscall_result;
- struct scsi_request *last_SRpnt;
+ struct st_request *last_SRpnt;
struct st_cmdstatus cmdstat;
unsigned char *b_data;
unsigned short use_sg; /* zero or max number of s/g segments for this adapter */
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index c041bfd56e12..25cced91c8a6 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -70,6 +70,7 @@
*
*/
#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_transport_spi.h>
/*
* Further development / testing that should be done :
@@ -2378,7 +2379,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
* 3..length+1 arguments
*
* Start the extended message buffer with the EXTENDED_MESSAGE
- * byte, since scsi_print_msg() wants the whole thing.
+ * byte, since spi_print_msg() wants the whole thing.
*/
extended_msg[0] = EXTENDED_MESSAGE;
/* Accept first byte by clearing ACK */
@@ -2431,7 +2432,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
default:
if (!tmp) {
printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
- scsi_print_msg (extended_msg);
+ spi_print_msg(extended_msg);
printk("\n");
} else if (tmp != EXTENDED_MESSAGE)
printk(KERN_DEBUG "scsi%d: rejecting unknown "
@@ -2566,7 +2567,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
if (!(msg[0] & 0x80)) {
printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
- scsi_print_msg(msg);
+ spi_print_msg(msg);
do_abort(instance);
return;
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 2d9437d7242b..3659dd7b9d76 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.2.1"
+#define SYM_VERSION "2.2.2"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c
index fd36cf9858cb..9916a2a22558 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.c
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.c
@@ -37,11 +37,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
#include "sym_glue.h"
-#endif
/*
* Macros used for all firmwares.
@@ -60,19 +56,12 @@
#define SYM_FWA_SCR sym_fw1a_scr
#define SYM_FWB_SCR sym_fw1b_scr
#define SYM_FWZ_SCR sym_fw1z_scr
-#ifdef __FreeBSD__
-#include <dev/sym/sym_fw1.h>
-#else
#include "sym_fw1.h"
-#endif
static struct sym_fwa_ofs sym_fw1a_ofs = {
SYM_GEN_FW_A(struct SYM_FWA_SCR)
};
static struct sym_fwb_ofs sym_fw1b_ofs = {
SYM_GEN_FW_B(struct SYM_FWB_SCR)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- SYM_GEN_B(struct SYM_FWB_SCR, data_io)
-#endif
};
static struct sym_fwz_ofs sym_fw1z_ofs = {
SYM_GEN_FW_Z(struct SYM_FWZ_SCR)
@@ -88,19 +77,12 @@ static struct sym_fwz_ofs sym_fw1z_ofs = {
#define SYM_FWA_SCR sym_fw2a_scr
#define SYM_FWB_SCR sym_fw2b_scr
#define SYM_FWZ_SCR sym_fw2z_scr
-#ifdef __FreeBSD__
-#include <dev/sym/sym_fw2.h>
-#else
#include "sym_fw2.h"
-#endif
static struct sym_fwa_ofs sym_fw2a_ofs = {
SYM_GEN_FW_A(struct SYM_FWA_SCR)
};
static struct sym_fwb_ofs sym_fw2b_ofs = {
SYM_GEN_FW_B(struct SYM_FWB_SCR)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- SYM_GEN_B(struct SYM_FWB_SCR, data_io)
-#endif
SYM_GEN_B(struct SYM_FWB_SCR, start64)
SYM_GEN_B(struct SYM_FWB_SCR, pm_handle)
};
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.h b/drivers/scsi/sym53c8xx_2/sym_fw.h
index 43f6810a4045..66ec35beab5b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw.h
@@ -92,9 +92,6 @@ struct sym_fwa_ofs {
};
struct sym_fwb_ofs {
SYM_GEN_FW_B(u_short)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- SYM_GEN_B(u_short, data_io)
-#endif
SYM_GEN_B(u_short, start64)
SYM_GEN_B(u_short, pm_handle)
};
@@ -111,9 +108,6 @@ struct sym_fwa_ba {
};
struct sym_fwb_ba {
SYM_GEN_FW_B(u32)
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- SYM_GEN_B(u32, data_io)
-#endif
SYM_GEN_B(u32, start64);
SYM_GEN_B(u32, pm_handle);
};
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw1.h b/drivers/scsi/sym53c8xx_2/sym_fw1.h
index cdd92d82f4b2..7b39f4a35e98 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw1.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw1.h
@@ -197,12 +197,6 @@ struct SYM_FWB_SCR {
u32 bad_status [ 7];
u32 wsr_ma_helper [ 4];
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- /* Unknown direction handling */
- u32 data_io [ 2];
- u32 data_io_com [ 8];
- u32 data_io_out [ 7];
-#endif
/* Data area */
u32 zero [ 1];
u32 scratch [ 1];
@@ -1747,48 +1741,6 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = {
SCR_JUMP,
PADDR_A (dispatch),
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-}/*-------------------------< DATA_IO >--------------------------*/,{
- /*
- * We jump here if the data direction was unknown at the
- * time we had to queue the command to the scripts processor.
- * Pointers had been set as follow in this situation:
- * savep --> DATA_IO
- * lastp --> start pointer when DATA_IN
- * wlastp --> start pointer when DATA_OUT
- * This script sets savep and lastp according to the
- * direction chosen by the target.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
- PADDR_B (data_io_out),
-}/*-------------------------< DATA_IO_COM >----------------------*/,{
- /*
- * Direction is DATA IN.
- */
- SCR_COPY (4),
- HADDR_1 (ccb_head.lastp),
- HADDR_1 (ccb_head.savep),
- /*
- * Jump to the SCRIPTS according to actual direction.
- */
- SCR_COPY (4),
- HADDR_1 (ccb_head.savep),
- RADDR_1 (temp),
- SCR_RETURN,
- 0,
-}/*-------------------------< DATA_IO_OUT >----------------------*/,{
- /*
- * Direction is DATA OUT.
- */
- SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
- 0,
- SCR_COPY (4),
- HADDR_1 (ccb_head.wlastp),
- HADDR_1 (ccb_head.lastp),
- SCR_JUMP,
- PADDR_B(data_io_com),
-#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
-
}/*-------------------------< ZERO >-----------------------------*/,{
SCR_DATA_ZERO,
}/*-------------------------< SCRATCH >--------------------------*/,{
diff --git a/drivers/scsi/sym53c8xx_2/sym_fw2.h b/drivers/scsi/sym53c8xx_2/sym_fw2.h
index 7ea7151f5d1d..851f2706f220 100644
--- a/drivers/scsi/sym53c8xx_2/sym_fw2.h
+++ b/drivers/scsi/sym53c8xx_2/sym_fw2.h
@@ -191,13 +191,6 @@ struct SYM_FWB_SCR {
u32 pm_wsr_handle [ 38];
u32 wsr_ma_helper [ 4];
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- /* Unknown direction handling */
- u32 data_io [ 2];
- u32 data_io_in [ 2];
- u32 data_io_com [ 6];
- u32 data_io_out [ 8];
-#endif
/* Data area */
u32 zero [ 1];
u32 scratch [ 1];
@@ -1838,51 +1831,6 @@ static struct SYM_FWB_SCR SYM_FWB_SCR = {
SCR_JUMP,
PADDR_A (dispatch),
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-}/*-------------------------< DATA_IO >--------------------------*/,{
- /*
- * We jump here if the data direction was unknown at the
- * time we had to queue the command to the scripts processor.
- * Pointers had been set as follow in this situation:
- * savep --> DATA_IO
- * lastp --> start pointer when DATA_IN
- * wlastp --> start pointer when DATA_OUT
- * This script sets savep and lastp according to the
- * direction chosen by the target.
- */
- SCR_JUMP ^ IFTRUE (WHEN (SCR_DATA_OUT)),
- PADDR_B (data_io_out),
-}/*-------------------------< DATA_IO_IN >-----------------------*/,{
- /*
- * Direction is DATA IN.
- */
- SCR_LOAD_REL (scratcha, 4),
- offsetof (struct sym_ccb, phys.head.lastp),
-}/*-------------------------< DATA_IO_COM >----------------------*/,{
- SCR_STORE_REL (scratcha, 4),
- offsetof (struct sym_ccb, phys.head.savep),
-
- /*
- * Jump to the SCRIPTS according to actual direction.
- */
- SCR_LOAD_REL (temp, 4),
- offsetof (struct sym_ccb, phys.head.savep),
- SCR_RETURN,
- 0,
-}/*-------------------------< DATA_IO_OUT >----------------------*/,{
- /*
- * Direction is DATA OUT.
- */
- SCR_REG_REG (HF_REG, SCR_AND, (~HF_DATA_IN)),
- 0,
- SCR_LOAD_REL (scratcha, 4),
- offsetof (struct sym_ccb, phys.head.wlastp),
- SCR_STORE_REL (scratcha, 4),
- offsetof (struct sym_ccb, phys.head.lastp),
- SCR_JUMP,
- PADDR_B(data_io_com),
-#endif /* SYM_OPT_HANDLE_DIR_UNKNOWN */
-
}/*-------------------------< ZERO >-----------------------------*/,{
SCR_DATA_ZERO,
}/*-------------------------< SCRATCH >--------------------------*/,{
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 7fc0b97173e1..1fffd2b3c654 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -514,9 +514,10 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struc
*/
int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
- int dir;
struct sym_tcb *tp = &np->target[cp->target];
struct sym_lcb *lp = sym_lp(tp, cp->lun);
+ u32 lastp, goalp;
+ int dir;
/*
* Build the CDB.
@@ -534,15 +535,47 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
sym_set_cam_status(cmd, DID_ERROR);
goto out_abort;
}
+
+ /*
+ * No segments means no data.
+ */
+ if (!cp->segments)
+ dir = DMA_NONE;
} else {
cp->data_len = 0;
cp->segments = 0;
}
/*
- * Set data pointers.
+ * Set the data pointer.
*/
- sym_setup_data_pointers(np, cp, dir);
+ switch (dir) {
+ case DMA_BIDIRECTIONAL:
+ printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np));
+ sym_set_cam_status(cmd, DID_ERROR);
+ goto out_abort;
+ case DMA_TO_DEVICE:
+ goalp = SCRIPTA_BA(np, data_out2) + 8;
+ lastp = goalp - 8 - (cp->segments * (2*4));
+ break;
+ case DMA_FROM_DEVICE:
+ cp->host_flags |= HF_DATA_IN;
+ goalp = SCRIPTA_BA(np, data_in2) + 8;
+ lastp = goalp - 8 - (cp->segments * (2*4));
+ break;
+ case DMA_NONE:
+ default:
+ lastp = goalp = SCRIPTB_BA(np, no_data);
+ break;
+ }
+
+ /*
+ * Set all pointers values needed by SCRIPTS.
+ */
+ cp->phys.head.lastp = cpu_to_scr(lastp);
+ cp->phys.head.savep = cpu_to_scr(lastp);
+ cp->startp = cp->phys.head.savep;
+ cp->goalp = cpu_to_scr(goalp);
/*
* When `#ifed 1', the code below makes the driver
@@ -563,10 +596,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
/*
* activate this job.
*/
- if (lp)
- sym_start_next_ccbs(np, lp, 2);
- else
- sym_put_start_queue(np, cp);
+ sym_start_next_ccbs(np, lp, 2);
return 0;
out_abort:
@@ -981,15 +1011,14 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun)
static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
{
- struct sym_hcb *np;
- struct sym_tcb *tp;
+ struct sym_hcb *np = sym_get_hcb(sdev->host);
+ struct sym_tcb *tp = &np->target[sdev->id];
+ struct sym_lcb *lp;
if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN)
return -ENXIO;
- np = sym_get_hcb(sdev->host);
- tp = &np->target[sdev->id];
-
+ tp->starget = sdev->sdev_target;
/*
* Fail the device init if the device is flagged NOSCAN at BOOT in
* the NVRAM. This may speed up boot and maintain coherency with
@@ -999,35 +1028,41 @@ static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
* lun devices behave badly when asked for a non zero LUN.
*/
- if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
- ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && sdev->lun != 0)) {
+ if (tp->usrflags & SYM_SCAN_BOOT_DISABLED) {
tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
+ starget_printk(KERN_INFO, tp->starget,
+ "Scan at boot disabled in NVRAM\n");
return -ENXIO;
}
- tp->starget = sdev->sdev_target;
+ if (tp->usrflags & SYM_SCAN_LUNS_DISABLED) {
+ if (sdev->lun != 0)
+ return -ENXIO;
+ starget_printk(KERN_INFO, tp->starget,
+ "Multiple LUNs disabled in NVRAM\n");
+ }
+
+ lp = sym_alloc_lcb(np, sdev->id, sdev->lun);
+ if (!lp)
+ return -ENOMEM;
+
+ spi_min_period(tp->starget) = tp->usr_period;
+ spi_max_width(tp->starget) = tp->usr_width;
+
return 0;
}
/*
* Linux entry point for device queue sizing.
*/
-static int sym53c8xx_slave_configure(struct scsi_device *device)
+static int sym53c8xx_slave_configure(struct scsi_device *sdev)
{
- struct sym_hcb *np = sym_get_hcb(device->host);
- struct sym_tcb *tp = &np->target[device->id];
- struct sym_lcb *lp;
+ struct sym_hcb *np = sym_get_hcb(sdev->host);
+ struct sym_tcb *tp = &np->target[sdev->id];
+ struct sym_lcb *lp = sym_lp(tp, sdev->lun);
int reqtags, depth_to_use;
/*
- * Allocate the LCB if not yet.
- * If it fail, we may well be in the sh*t. :)
- */
- lp = sym_alloc_lcb(np, device->id, device->lun);
- if (!lp)
- return -ENOMEM;
-
- /*
* Get user flags.
*/
lp->curr_flags = lp->user_flags;
@@ -1038,10 +1073,10 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
* Use at least 2.
* Donnot use more than our maximum.
*/
- reqtags = device_queue_depth(np, device->id, device->lun);
+ reqtags = device_queue_depth(np, sdev->id, sdev->lun);
if (reqtags > tp->usrtags)
reqtags = tp->usrtags;
- if (!device->tagged_supported)
+ if (!sdev->tagged_supported)
reqtags = 0;
#if 1 /* Avoid to locally queue commands for no good reasons */
if (reqtags > SYM_CONF_MAX_TAG)
@@ -1050,19 +1085,30 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
#else
depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2);
#endif
- scsi_adjust_queue_depth(device,
- (device->tagged_supported ?
+ scsi_adjust_queue_depth(sdev,
+ (sdev->tagged_supported ?
MSG_SIMPLE_TAG : 0),
depth_to_use);
lp->s.scdev_depth = depth_to_use;
- sym_tune_dev_queuing(tp, device->lun, reqtags);
+ sym_tune_dev_queuing(tp, sdev->lun, reqtags);
- if (!spi_initial_dv(device->sdev_target))
- spi_dv_device(device);
+ if (!spi_initial_dv(sdev->sdev_target))
+ spi_dv_device(sdev);
return 0;
}
+static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
+{
+ struct sym_hcb *np = sym_get_hcb(sdev->host);
+ struct sym_lcb *lp = sym_lp(&np->target[sdev->id], sdev->lun);
+
+ if (lp->itlq_tbl)
+ sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK * 4, "ITLQ_TBL");
+ kfree(lp->cb_tags);
+ sym_mfree_dma(lp, sizeof(*lp), "LCB");
+}
+
/*
* Linux entry point for info() function
*/
@@ -1497,7 +1543,7 @@ static int sym_setup_bus_dma_mask(struct sym_hcb *np)
{
#if SYM_CONF_DMA_ADDRESSING_MODE > 0
#if SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define DMA_DAC_MASK 0x000000ffffffffffULL /* 40-bit */
+#define DMA_DAC_MASK DMA_40BIT_MASK
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
#define DMA_DAC_MASK DMA_64BIT_MASK
#endif
@@ -1926,6 +1972,7 @@ static struct scsi_host_template sym2_template = {
.queuecommand = sym53c8xx_queue_command,
.slave_alloc = sym53c8xx_slave_alloc,
.slave_configure = sym53c8xx_slave_configure,
+ .slave_destroy = sym53c8xx_slave_destroy,
.eh_abort_handler = sym53c8xx_eh_abort_handler,
.eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index d3d52f14d7c0..cc92d0c70cd7 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -68,7 +68,6 @@
*/
#define SYM_CONF_TIMER_INTERVAL ((HZ+1)/2)
-#define SYM_OPT_HANDLE_DIR_UNKNOWN
#define SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
@@ -268,6 +267,5 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np);
void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
void sym_log_bus_error(struct sym_hcb *np);
-void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
#endif /* SYM_GLUE_H */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 1564ca203a3e..8260f040d39c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <asm/param.h> /* for timeouts in units of HZ */
+#include <scsi/scsi_dbg.h>
#include "sym_glue.h"
#include "sym_nvram.h"
@@ -70,32 +71,12 @@ static void sym_printl_hex(u_char *p, int n)
printf (".\n");
}
-/*
- * Print out the content of a SCSI message.
- */
-static int sym_show_msg (u_char * msg)
-{
- u_char i;
- printf ("%x",*msg);
- if (*msg==M_EXTENDED) {
- for (i=1;i<8;i++) {
- if (i-1>msg[1]) break;
- printf ("-%x",msg[i]);
- }
- return (i+1);
- } else if ((*msg & 0xf0) == 0x20) {
- printf ("-%x",msg[1]);
- return (2);
- }
- return (1);
-}
-
static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
{
sym_print_addr(cp->cmd, "%s: ", label);
- sym_show_msg(msg);
- printf(".\n");
+ spi_print_msg(msg);
+ printf("\n");
}
static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg)
@@ -103,8 +84,8 @@ static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_ch
struct sym_tcb *tp = &np->target[target];
dev_info(&tp->starget->dev, "%s: ", label);
- sym_show_msg(msg);
- printf(".\n");
+ spi_print_msg(msg);
+ printf("\n");
}
/*
@@ -635,29 +616,6 @@ static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
}
}
-
-/*
- * Print out the list of targets that have some flag disabled by user.
- */
-static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
-{
- int cnt;
- int i;
-
- for (cnt = 0, i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
- if (i == np->myaddr)
- continue;
- if (np->target[i].usrflags & mask) {
- if (!cnt++)
- printf("%s: %s disabled for targets",
- sym_name(np), msg);
- printf(" %d", i);
- }
- }
- if (cnt)
- printf(".\n");
-}
-
/*
* Save initial settings of some IO registers.
* Assumed to have been set by BIOS.
@@ -962,7 +920,7 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
tp->usrtags = SYM_SETUP_MAX_TAG;
- sym_nvram_setup_target(np, i, nvram);
+ sym_nvram_setup_target(tp, i, nvram);
if (!tp->usrtags)
tp->usrflags &= ~SYM_TAGS_ENABLED;
@@ -1005,13 +963,6 @@ static int sym_prepare_setting(struct Scsi_Host *shost, struct sym_hcb *np, stru
sym_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl,
np->rv_ctest3, np->rv_ctest4, np->rv_ctest5);
}
- /*
- * Let user be aware of targets that have some disable flags set.
- */
- sym_print_targets_flag(np, SYM_SCAN_BOOT_DISABLED, "SCAN AT BOOT");
- if (sym_verbose)
- sym_print_targets_flag(np, SYM_SCAN_LUNS_DISABLED,
- "SCAN FOR LUNS");
return 0;
}
@@ -1523,7 +1474,7 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
/*
* Insert a job into the start queue.
*/
-void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
+static void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp)
{
u_short qidx;
@@ -3654,7 +3605,7 @@ static int sym_evaluate_dp(struct sym_hcb *np, struct sym_ccb *cp, u32 scr, int
* If result is dp_sg = SYM_CONF_MAX_SG, then we are at the
* end of the data.
*/
- tmp = scr_to_cpu(sym_goalp(cp));
+ tmp = scr_to_cpu(cp->goalp);
dp_sg = SYM_CONF_MAX_SG;
if (dp_scr != tmp)
dp_sg -= (tmp - 8 - (int)dp_scr) / (2*4);
@@ -3761,7 +3712,7 @@ static void sym_modify_dp(struct sym_hcb *np, struct sym_tcb *tp, struct sym_ccb
* And our alchemy:) allows to easily calculate the data
* script address we want to return for the next data phase.
*/
- dp_ret = cpu_to_scr(sym_goalp(cp));
+ dp_ret = cpu_to_scr(cp->goalp);
dp_ret = dp_ret - 8 - (SYM_CONF_MAX_SG - dp_sg) * (2*4);
/*
@@ -3857,7 +3808,7 @@ int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp)
* If all data has been transferred,
* there is no residual.
*/
- if (cp->phys.head.lastp == sym_goalp(cp))
+ if (cp->phys.head.lastp == cp->goalp)
return resid;
/*
@@ -4664,30 +4615,7 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
goto out;
cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
-#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- /*
- * If the LCB is not yet available and the LUN
- * has been probed ok, try to allocate the LCB.
- */
- if (!lp && sym_is_bit(tp->lun_map, ln)) {
- lp = sym_alloc_lcb(np, tn, ln);
- if (!lp)
- goto out_free;
- }
-#endif
-
- /*
- * If the LCB is not available here, then the
- * logical unit is not yet discovered. For those
- * ones only accept 1 SCSI IO per logical unit,
- * since we cannot allow disconnections.
- */
- if (!lp) {
- if (!sym_is_bit(tp->busy0_map, ln))
- sym_set_bit(tp->busy0_map, ln);
- else
- goto out_free;
- } else {
+ {
/*
* If we have been asked for a tagged command.
*/
@@ -4840,12 +4768,6 @@ void sym_free_ccb (struct sym_hcb *np, struct sym_ccb *cp)
lp->head.resel_sa =
cpu_to_scr(SCRIPTB_BA(np, resel_bad_lun));
}
- /*
- * Otherwise, we only accept 1 IO per LUN.
- * Clear the bit that keeps track of this IO.
- */
- else
- sym_clr_bit(tp->busy0_map, cp->lun);
/*
* We donnot queue more than 1 ccb per target
@@ -4997,20 +4919,7 @@ static void sym_init_tcb (struct sym_hcb *np, u_char tn)
struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
{
struct sym_tcb *tp = &np->target[tn];
- struct sym_lcb *lp = sym_lp(tp, ln);
-
- /*
- * Already done, just return.
- */
- if (lp)
- return lp;
-
- /*
- * Donnot allow LUN control block
- * allocation for not probed LUNs.
- */
- if (!sym_is_bit(tp->lun_map, ln))
- return NULL;
+ struct sym_lcb *lp = NULL;
/*
* Initialize the target control block if not yet.
@@ -5082,13 +4991,7 @@ struct sym_lcb *sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
lp->started_max = SYM_CONF_MAX_TASK;
lp->started_limit = SYM_CONF_MAX_TASK;
#endif
- /*
- * If we are busy, count the IO.
- */
- if (sym_is_bit(tp->busy0_map, ln)) {
- lp->busy_itl = 1;
- sym_clr_bit(tp->busy0_map, ln);
- }
+
fail:
return lp;
}
@@ -5103,12 +5006,6 @@ static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
int i;
/*
- * If LCB not available, try to allocate it.
- */
- if (!lp && !(lp = sym_alloc_lcb(np, tn, ln)))
- goto fail;
-
- /*
* Allocate the task table and and the tag allocation
* circular buffer. We want both or none.
*/
@@ -5481,8 +5378,7 @@ finish:
/*
* Donnot start more than 1 command after an error.
*/
- if (lp)
- sym_start_next_ccbs(np, lp, 1);
+ sym_start_next_ccbs(np, lp, 1);
#endif
}
@@ -5521,17 +5417,11 @@ void sym_complete_ok (struct sym_hcb *np, struct sym_ccb *cp)
lp = sym_lp(tp, cp->lun);
/*
- * Assume device discovered on first success.
- */
- if (!lp)
- sym_set_bit(tp->lun_map, cp->lun);
-
- /*
* If all data have been transferred, given than no
* extended error did occur, there is no residual.
*/
resid = 0;
- if (cp->phys.head.lastp != sym_goalp(cp))
+ if (cp->phys.head.lastp != cp->goalp)
resid = sym_compute_residual(np, cp);
/*
@@ -5551,15 +5441,6 @@ if (resid)
*/
sym_set_cam_result_ok(cp, cmd, resid);
-#ifdef SYM_OPT_SNIFF_INQUIRY
- /*
- * On standard INQUIRY response (EVPD and CmDt
- * not set), sniff out device capabilities.
- */
- if (cp->cdb_buf[0] == INQUIRY && !(cp->cdb_buf[1] & 0x3))
- sym_sniff_inquiry(np, cmd, resid);
-#endif
-
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
/*
* If max number of started ccbs had been reduced,
@@ -5587,7 +5468,7 @@ if (resid)
/*
* Requeue a couple of awaiting scsi commands.
*/
- if (lp && !sym_que_empty(&lp->waiting_ccbq))
+ if (!sym_que_empty(&lp->waiting_ccbq))
sym_start_next_ccbs(np, lp, 2);
#endif
/*
@@ -5830,8 +5711,7 @@ void sym_hcb_free(struct sym_hcb *np)
SYM_QUEHEAD *qp;
struct sym_ccb *cp;
struct sym_tcb *tp;
- struct sym_lcb *lp;
- int target, lun;
+ int target;
if (np->scriptz0)
sym_mfree_dma(np->scriptz0, np->scriptz_sz, "SCRIPTZ0");
@@ -5857,16 +5737,6 @@ void sym_hcb_free(struct sym_hcb *np)
for (target = 0; target < SYM_CONF_MAX_TARGET ; target++) {
tp = &np->target[target];
- for (lun = 0 ; lun < SYM_CONF_MAX_LUN ; lun++) {
- lp = sym_lp(tp, lun);
- if (!lp)
- continue;
- if (lp->itlq_tbl)
- sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4,
- "ITLQ_TBL");
- kfree(lp->cb_tags);
- sym_mfree_dma(lp, sizeof(*lp), "LCB");
- }
#if SYM_CONF_MAX_LUN > 1
kfree(tp->lunmp);
#endif
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index 3a264a408216..2456090bb241 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -48,12 +48,6 @@
* They may be defined in platform specific headers, if they
* are useful.
*
- * SYM_OPT_HANDLE_DIR_UNKNOWN
- * When this option is set, the SCRIPTS used by the driver
- * are able to handle SCSI transfers with direction not
- * supplied by user.
- * (set for Linux-2.0.X)
- *
* SYM_OPT_HANDLE_DEVICE_QUEUEING
* When this option is set, the driver will use a queue per
* device and handle QUEUE FULL status requeuing internally.
@@ -64,7 +58,6 @@
* (set for Linux)
*/
#if 0
-#define SYM_OPT_HANDLE_DIR_UNKNOWN
#define SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING
#endif
@@ -416,19 +409,6 @@ struct sym_tcb {
struct sym_lcb **lunmp; /* Other LCBs [1..MAX_LUN] */
#endif
- /*
- * Bitmap that tells about LUNs that succeeded at least
- * 1 IO and therefore assumed to be a real device.
- * Avoid useless allocation of the LCB structure.
- */
- u32 lun_map[(SYM_CONF_MAX_LUN+31)/32];
-
- /*
- * Bitmap that tells about LUNs that haven't yet an LCB
- * allocated (not discovered or LCB allocation failed).
- */
- u32 busy0_map[(SYM_CONF_MAX_LUN+31)/32];
-
#ifdef SYM_HAVE_STCB
/*
* O/S specific data structure.
@@ -454,8 +434,10 @@ struct sym_tcb {
* Other user settable limits and options.
* These limits are read from the NVRAM if present.
*/
- u_char usrflags;
- u_short usrtags;
+ unsigned char usrflags;
+ unsigned char usr_period;
+ unsigned char usr_width;
+ unsigned short usrtags;
struct scsi_target *starget;
};
@@ -672,9 +654,6 @@ struct sym_ccbh {
*/
u32 savep; /* Jump address to saved data pointer */
u32 lastp; /* SCRIPTS address at end of data */
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- u32 wlastp;
-#endif
/*
* Status fields.
@@ -804,9 +783,6 @@ struct sym_ccb {
SYM_QUEHEAD link_ccbq; /* Link to free/busy CCB queue */
u32 startp; /* Initial data pointer */
u32 goalp; /* Expected last data pointer */
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- u32 wgoalp;
-#endif
int ext_sg; /* Extreme data pointer, used */
int ext_ofs; /* to calculate the residual. */
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
@@ -821,12 +797,6 @@ struct sym_ccb {
#define CCB_BA(cp,lbl) cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
-#define sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
-#else
-#define sym_goalp(cp) (cp->goalp)
-#endif
-
typedef struct device *m_pool_ident_t;
/*
@@ -1077,7 +1047,6 @@ char *sym_driver_name(void);
void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
-void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#endif
@@ -1136,71 +1105,6 @@ bad:
#endif
/*
- * Set up data pointers used by SCRIPTS.
- * Called from O/S specific code.
- */
-static inline void sym_setup_data_pointers(struct sym_hcb *np,
- struct sym_ccb *cp, int dir)
-{
- u32 lastp, goalp;
-
- /*
- * No segments means no data.
- */
- if (!cp->segments)
- dir = DMA_NONE;
-
- /*
- * Set the data pointer.
- */
- switch(dir) {
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- case DMA_BIDIRECTIONAL:
-#endif
- case DMA_TO_DEVICE:
- goalp = SCRIPTA_BA(np, data_out2) + 8;
- lastp = goalp - 8 - (cp->segments * (2*4));
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- cp->wgoalp = cpu_to_scr(goalp);
- if (dir != DMA_BIDIRECTIONAL)
- break;
- cp->phys.head.wlastp = cpu_to_scr(lastp);
- /* fall through */
-#else
- break;
-#endif
- case DMA_FROM_DEVICE:
- cp->host_flags |= HF_DATA_IN;
- goalp = SCRIPTA_BA(np, data_in2) + 8;
- lastp = goalp - 8 - (cp->segments * (2*4));
- break;
- case DMA_NONE:
- default:
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- cp->host_flags |= HF_DATA_IN;
-#endif
- lastp = goalp = SCRIPTB_BA(np, no_data);
- break;
- }
-
- /*
- * Set all pointers values needed by SCRIPTS.
- */
- cp->phys.head.lastp = cpu_to_scr(lastp);
- cp->phys.head.savep = cpu_to_scr(lastp);
- cp->startp = cp->phys.head.savep;
- cp->goalp = cpu_to_scr(goalp);
-
-#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- /*
- * If direction is unknown, start at data_io.
- */
- if (dir == DMA_BIDIRECTIONAL)
- cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
-#endif
-}
-
-/*
* MEMORY ALLOCATOR.
*/
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index a34d403ccc6c..92bf9b14a7a2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -37,11 +37,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
#include "sym_glue.h"
-#endif
/*
* Simple power of two buddy-like generic allocator.
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 994b7566bcac..15d69298ab6e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -92,29 +92,32 @@ void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sy
* Get target set-up from Symbios format NVRAM.
*/
static void
-sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram)
+sym_Symbios_setup_target(struct sym_tcb *tp, int target, Symbios_nvram *nvram)
{
- struct sym_tcb *tp = &np->target[target];
Symbios_target *tn = &nvram->target[target];
- tp->usrtags =
- (tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
-
+ if (!(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED))
+ tp->usrtags = 0;
if (!(tn->flags & SYMBIOS_DISCONNECT_ENABLE))
tp->usrflags &= ~SYM_DISC_ENABLED;
if (!(tn->flags & SYMBIOS_SCAN_AT_BOOT_TIME))
tp->usrflags |= SYM_SCAN_BOOT_DISABLED;
if (!(tn->flags & SYMBIOS_SCAN_LUNS))
tp->usrflags |= SYM_SCAN_LUNS_DISABLED;
+ tp->usr_period = (tn->sync_period + 3) / 4;
+ tp->usr_width = (tn->bus_width == 0x8) ? 0 : 1;
}
+static const unsigned char Tekram_sync[16] = {
+ 25, 31, 37, 43, 50, 62, 75, 125, 12, 15, 18, 21, 6, 7, 9, 10
+};
+
/*
* Get target set-up from Tekram format NVRAM.
*/
static void
-sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
+sym_Tekram_setup_target(struct sym_tcb *tp, int target, Tekram_nvram *nvram)
{
- struct sym_tcb *tp = &np->target[target];
struct Tekram_target *tn = &nvram->target[target];
if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
@@ -124,22 +127,22 @@ sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
if (tn->flags & TEKRAM_DISCONNECT_ENABLE)
tp->usrflags |= SYM_DISC_ENABLED;
- /* If any device does not support parity, we will not use this option */
- if (!(tn->flags & TEKRAM_PARITY_CHECK))
- np->rv_scntl0 &= ~0x0a; /* SCSI parity checking disabled */
+ if (tn->flags & TEKRAM_SYNC_NEGO)
+ tp->usr_period = Tekram_sync[tn->sync_index & 0xf];
+ tp->usr_width = (tn->flags & TEKRAM_WIDE_NEGO) ? 1 : 0;
}
/*
* Get target setup from NVRAM.
*/
-void sym_nvram_setup_target(struct sym_hcb *np, int target, struct sym_nvram *nvp)
+void sym_nvram_setup_target(struct sym_tcb *tp, int target, struct sym_nvram *nvp)
{
switch (nvp->type) {
case SYM_SYMBIOS_NVRAM:
- sym_Symbios_setup_target(np, target, &nvp->data.Symbios);
+ sym_Symbios_setup_target(tp, target, &nvp->data.Symbios);
break;
case SYM_TEKRAM_NVRAM:
- sym_Tekram_setup_target(np, target, &nvp->data.Tekram);
+ sym_Tekram_setup_target(tp, target, &nvp->data.Tekram);
break;
default:
break;
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.h b/drivers/scsi/sym53c8xx_2/sym_nvram.h
index 1538bede5277..bdfbbb083b69 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.h
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.h
@@ -194,12 +194,12 @@ struct sym_nvram {
#if SYM_CONF_NVRAM_SUPPORT
void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram);
-void sym_nvram_setup_target (struct sym_hcb *np, int target, struct sym_nvram *nvp);
+void sym_nvram_setup_target (struct sym_tcb *tp, int target, struct sym_nvram *nvp);
int sym_read_nvram (struct sym_device *np, struct sym_nvram *nvp);
char *sym_nvram_type(struct sym_nvram *nvp);
#else
static inline void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) { }
-static inline void sym_nvram_setup_target(struct sym_hcb *np, struct sym_nvram *nvram) { }
+static inline void sym_nvram_setup_target(struct sym_tcb *tp, struct sym_nvram *nvram) { }
static inline int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
{
nvp->type = 0;
diff --git a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h
deleted file mode 100644
index 20ae2b17df58..000000000000
--- a/drivers/scsi/sym53c8xx_comm.h
+++ /dev/null
@@ -1,792 +0,0 @@
-/******************************************************************************
-** High Performance device driver for the Symbios 53C896 controller.
-**
-** Copyright (C) 1998-2001 Gerard Roudier <groudier@free.fr>
-**
-** This driver also supports all the Symbios 53C8XX controller family,
-** except 53C810 revisions < 16, 53C825 revisions < 16 and all
-** revisions of 53C815 controllers.
-**
-** This driver is based on the Linux port of the FreeBSD ncr driver.
-**
-** Copyright (C) 1994 Wolfgang Stanglmeier
-**
-**-----------------------------------------------------------------------------
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the 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.
-**
-**-----------------------------------------------------------------------------
-**
-** The Linux port of the FreeBSD ncr driver has been achieved in
-** november 1995 by:
-**
-** Gerard Roudier <groudier@free.fr>
-**
-** Being given that this driver originates from the FreeBSD version, and
-** in order to keep synergy on both, any suggested enhancements and corrections
-** received on Linux are automatically a potential candidate for the FreeBSD
-** version.
-**
-** The original driver has been written for 386bsd and FreeBSD by
-** Wolfgang Stanglmeier <wolf@cologne.de>
-** Stefan Esser <se@mi.Uni-Koeln.de>
-**
-**-----------------------------------------------------------------------------
-**
-** Major contributions:
-** --------------------
-**
-** NVRAM detection and reading.
-** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
-**
-*******************************************************************************
-*/
-
-/*==========================================================
-**
-** Debugging tags
-**
-**==========================================================
-*/
-
-#define DEBUG_ALLOC (0x0001)
-#define DEBUG_PHASE (0x0002)
-#define DEBUG_QUEUE (0x0008)
-#define DEBUG_RESULT (0x0010)
-#define DEBUG_POINTER (0x0020)
-#define DEBUG_SCRIPT (0x0040)
-#define DEBUG_TINY (0x0080)
-#define DEBUG_TIMING (0x0100)
-#define DEBUG_NEGO (0x0200)
-#define DEBUG_TAGS (0x0400)
-#define DEBUG_SCATTER (0x0800)
-#define DEBUG_IC (0x1000)
-
-/*
-** Enable/Disable debug messages.
-** Can be changed at runtime too.
-*/
-
-#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT
-static int ncr_debug = SCSI_NCR_DEBUG_FLAGS;
- #define DEBUG_FLAGS ncr_debug
-#else
- #define DEBUG_FLAGS SCSI_NCR_DEBUG_FLAGS
-#endif
-
-static inline struct list_head *ncr_list_pop(struct list_head *head)
-{
- if (!list_empty(head)) {
- struct list_head *elem = head->next;
-
- list_del(elem);
- return elem;
- }
-
- return NULL;
-}
-
-#ifdef __sparc__
-#include <asm/irq.h>
-#endif
-
-/*==========================================================
-**
-** Simple power of two buddy-like allocator.
-**
-** This simple code is not intended to be fast, but to
-** provide power of 2 aligned memory allocations.
-** Since the SCRIPTS processor only supplies 8 bit
-** arithmetic, this allocator allows simple and fast
-** address calculations from the SCRIPTS code.
-** In addition, cache line alignment is guaranteed for
-** power of 2 cache line size.
-** Enhanced in linux-2.3.44 to provide a memory pool
-** per pcidev to support dynamic dma mapping. (I would
-** have preferred a real bus astraction, btw).
-**
-**==========================================================
-*/
-
-#define MEMO_SHIFT 4 /* 16 bytes minimum memory chunk */
-#if PAGE_SIZE >= 8192
-#define MEMO_PAGE_ORDER 0 /* 1 PAGE maximum */
-#else
-#define MEMO_PAGE_ORDER 1 /* 2 PAGES maximum */
-#endif
-#define MEMO_FREE_UNUSED /* Free unused pages immediately */
-#define MEMO_WARN 1
-#define MEMO_GFP_FLAGS GFP_ATOMIC
-#define MEMO_CLUSTER_SHIFT (PAGE_SHIFT+MEMO_PAGE_ORDER)
-#define MEMO_CLUSTER_SIZE (1UL << MEMO_CLUSTER_SHIFT)
-#define MEMO_CLUSTER_MASK (MEMO_CLUSTER_SIZE-1)
-
-typedef u_long m_addr_t; /* Enough bits to bit-hack addresses */
-typedef struct device *m_bush_t; /* Something that addresses DMAable */
-
-typedef struct m_link { /* Link between free memory chunks */
- struct m_link *next;
-} m_link_s;
-
-typedef struct m_vtob { /* Virtual to Bus address translation */
- struct m_vtob *next;
- m_addr_t vaddr;
- m_addr_t baddr;
-} m_vtob_s;
-#define VTOB_HASH_SHIFT 5
-#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
-#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
-#define VTOB_HASH_CODE(m) \
- ((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)
-
-typedef struct m_pool { /* Memory pool of a given kind */
- m_bush_t bush;
- m_addr_t (*getp)(struct m_pool *);
- void (*freep)(struct m_pool *, m_addr_t);
- int nump;
- m_vtob_s *(vtob[VTOB_HASH_SIZE]);
- struct m_pool *next;
- struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];
-} m_pool_s;
-
-static void *___m_alloc(m_pool_s *mp, int size)
-{
- int i = 0;
- int s = (1 << MEMO_SHIFT);
- int j;
- m_addr_t a;
- m_link_s *h = mp->h;
-
- if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
- return NULL;
-
- while (size > s) {
- s <<= 1;
- ++i;
- }
-
- j = i;
- while (!h[j].next) {
- if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
- h[j].next = (m_link_s *)mp->getp(mp);
- if (h[j].next)
- h[j].next->next = NULL;
- break;
- }
- ++j;
- s <<= 1;
- }
- a = (m_addr_t) h[j].next;
- if (a) {
- h[j].next = h[j].next->next;
- while (j > i) {
- j -= 1;
- s >>= 1;
- h[j].next = (m_link_s *) (a+s);
- h[j].next->next = NULL;
- }
- }
-#ifdef DEBUG
- printk("___m_alloc(%d) = %p\n", size, (void *) a);
-#endif
- return (void *) a;
-}
-
-static void ___m_free(m_pool_s *mp, void *ptr, int size)
-{
- int i = 0;
- int s = (1 << MEMO_SHIFT);
- m_link_s *q;
- m_addr_t a, b;
- m_link_s *h = mp->h;
-
-#ifdef DEBUG
- printk("___m_free(%p, %d)\n", ptr, size);
-#endif
-
- if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))
- return;
-
- while (size > s) {
- s <<= 1;
- ++i;
- }
-
- a = (m_addr_t) ptr;
-
- while (1) {
-#ifdef MEMO_FREE_UNUSED
- if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {
- mp->freep(mp, a);
- break;
- }
-#endif
- b = a ^ s;
- q = &h[i];
- while (q->next && q->next != (m_link_s *) b) {
- q = q->next;
- }
- if (!q->next) {
- ((m_link_s *) a)->next = h[i].next;
- h[i].next = (m_link_s *) a;
- break;
- }
- q->next = q->next->next;
- a = a & b;
- s <<= 1;
- ++i;
- }
-}
-
-static DEFINE_SPINLOCK(ncr53c8xx_lock);
-
-static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags)
-{
- void *p;
-
- p = ___m_alloc(mp, size);
-
- if (DEBUG_FLAGS & DEBUG_ALLOC)
- printk ("new %-10s[%4d] @%p.\n", name, size, p);
-
- if (p)
- memset(p, 0, size);
- else if (uflags & MEMO_WARN)
- printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);
-
- return p;
-}
-
-#define __m_calloc(mp, s, n) __m_calloc2(mp, s, n, MEMO_WARN)
-
-static void __m_free(m_pool_s *mp, void *ptr, int size, char *name)
-{
- if (DEBUG_FLAGS & DEBUG_ALLOC)
- printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);
-
- ___m_free(mp, ptr, size);
-
-}
-
-/*
- * With pci bus iommu support, we use a default pool of unmapped memory
- * for memory we donnot need to DMA from/to and one pool per pcidev for
- * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
- */
-
-static m_addr_t ___mp0_getp(m_pool_s *mp)
-{
- m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER);
- if (m)
- ++mp->nump;
- return m;
-}
-
-static void ___mp0_freep(m_pool_s *mp, m_addr_t m)
-{
- free_pages(m, MEMO_PAGE_ORDER);
- --mp->nump;
-}
-
-static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};
-
-/*
- * DMAable pools.
- */
-
-/*
- * With pci bus iommu support, we maintain one pool per pcidev and a
- * hashed reverse table for virtual to bus physical address translations.
- */
-static m_addr_t ___dma_getp(m_pool_s *mp)
-{
- m_addr_t vp;
- m_vtob_s *vbp;
-
- vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");
- if (vbp) {
- dma_addr_t daddr;
- vp = (m_addr_t) dma_alloc_coherent(mp->bush,
- PAGE_SIZE<<MEMO_PAGE_ORDER,
- &daddr, GFP_ATOMIC);
- if (vp) {
- int hc = VTOB_HASH_CODE(vp);
- vbp->vaddr = vp;
- vbp->baddr = daddr;
- vbp->next = mp->vtob[hc];
- mp->vtob[hc] = vbp;
- ++mp->nump;
- return vp;
- }
- }
- if (vbp)
- __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
- return 0;
-}
-
-static void ___dma_freep(m_pool_s *mp, m_addr_t m)
-{
- m_vtob_s **vbpp, *vbp;
- int hc = VTOB_HASH_CODE(m);
-
- vbpp = &mp->vtob[hc];
- while (*vbpp && (*vbpp)->vaddr != m)
- vbpp = &(*vbpp)->next;
- if (*vbpp) {
- vbp = *vbpp;
- *vbpp = (*vbpp)->next;
- dma_free_coherent(mp->bush, PAGE_SIZE<<MEMO_PAGE_ORDER,
- (void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
- __m_free(&mp0, vbp, sizeof(*vbp), "VTOB");
- --mp->nump;
- }
-}
-
-static inline m_pool_s *___get_dma_pool(m_bush_t bush)
-{
- m_pool_s *mp;
- for (mp = mp0.next; mp && mp->bush != bush; mp = mp->next);
- return mp;
-}
-
-static m_pool_s *___cre_dma_pool(m_bush_t bush)
-{
- m_pool_s *mp;
- mp = __m_calloc(&mp0, sizeof(*mp), "MPOOL");
- if (mp) {
- memset(mp, 0, sizeof(*mp));
- mp->bush = bush;
- mp->getp = ___dma_getp;
- mp->freep = ___dma_freep;
- mp->next = mp0.next;
- mp0.next = mp;
- }
- return mp;
-}
-
-static void ___del_dma_pool(m_pool_s *p)
-{
- struct m_pool **pp = &mp0.next;
-
- while (*pp && *pp != p)
- pp = &(*pp)->next;
- if (*pp) {
- *pp = (*pp)->next;
- __m_free(&mp0, p, sizeof(*p), "MPOOL");
- }
-}
-
-static void *__m_calloc_dma(m_bush_t bush, int size, char *name)
-{
- u_long flags;
- struct m_pool *mp;
- void *m = NULL;
-
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (!mp)
- mp = ___cre_dma_pool(bush);
- if (mp)
- m = __m_calloc(mp, size, name);
- if (mp && !mp->nump)
- ___del_dma_pool(mp);
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
-
- return m;
-}
-
-static void __m_free_dma(m_bush_t bush, void *m, int size, char *name)
-{
- u_long flags;
- struct m_pool *mp;
-
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (mp)
- __m_free(mp, m, size, name);
- if (mp && !mp->nump)
- ___del_dma_pool(mp);
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
-}
-
-static m_addr_t __vtobus(m_bush_t bush, void *m)
-{
- u_long flags;
- m_pool_s *mp;
- int hc = VTOB_HASH_CODE(m);
- m_vtob_s *vp = NULL;
- m_addr_t a = ((m_addr_t) m) & ~MEMO_CLUSTER_MASK;
-
- spin_lock_irqsave(&ncr53c8xx_lock, flags);
- mp = ___get_dma_pool(bush);
- if (mp) {
- vp = mp->vtob[hc];
- while (vp && (m_addr_t) vp->vaddr != a)
- vp = vp->next;
- }
- spin_unlock_irqrestore(&ncr53c8xx_lock, flags);
- return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
-}
-
-#define _m_calloc_dma(np, s, n) __m_calloc_dma(np->dev, s, n)
-#define _m_free_dma(np, p, s, n) __m_free_dma(np->dev, p, s, n)
-#define m_calloc_dma(s, n) _m_calloc_dma(np, s, n)
-#define m_free_dma(p, s, n) _m_free_dma(np, p, s, n)
-#define _vtobus(np, p) __vtobus(np->dev, p)
-#define vtobus(p) _vtobus(np, p)
-
-/*
- * Deal with DMA mapping/unmapping.
- */
-
-/* To keep track of the dma mapping (sg/single) that has been set */
-#define __data_mapped SCp.phase
-#define __data_mapping SCp.have_data_in
-
-static void __unmap_scsi_data(struct device *dev, struct scsi_cmnd *cmd)
-{
- switch(cmd->__data_mapped) {
- case 2:
- dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
- break;
- case 1:
- dma_unmap_single(dev, cmd->__data_mapping,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- break;
- }
- cmd->__data_mapped = 0;
-}
-
-static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
-{
- dma_addr_t mapping;
-
- if (cmd->request_bufflen == 0)
- return 0;
-
- mapping = dma_map_single(dev, cmd->request_buffer,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- cmd->__data_mapped = 1;
- cmd->__data_mapping = mapping;
-
- return mapping;
-}
-
-static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
-{
- int use_sg;
-
- if (cmd->use_sg == 0)
- return 0;
-
- use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
- cmd->__data_mapped = 2;
- cmd->__data_mapping = use_sg;
-
- return use_sg;
-}
-
-#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
-#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
-#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
-
-/*==========================================================
-**
-** Driver setup.
-**
-** This structure is initialized from linux config
-** options. It can be overridden at boot-up by the boot
-** command line.
-**
-**==========================================================
-*/
-static struct ncr_driver_setup
- driver_setup = SCSI_NCR_DRIVER_SETUP;
-
-#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-static struct ncr_driver_setup
- driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
-#endif
-
-#define initverbose (driver_setup.verbose)
-#define bootverbose (np->verbose)
-
-
-/*===================================================================
-**
-** Driver setup from the boot command line
-**
-**===================================================================
-*/
-
-#ifdef MODULE
-#define ARG_SEP ' '
-#else
-#define ARG_SEP ','
-#endif
-
-#define OPT_TAGS 1
-#define OPT_MASTER_PARITY 2
-#define OPT_SCSI_PARITY 3
-#define OPT_DISCONNECTION 4
-#define OPT_SPECIAL_FEATURES 5
-#define OPT_UNUSED_1 6
-#define OPT_FORCE_SYNC_NEGO 7
-#define OPT_REVERSE_PROBE 8
-#define OPT_DEFAULT_SYNC 9
-#define OPT_VERBOSE 10
-#define OPT_DEBUG 11
-#define OPT_BURST_MAX 12
-#define OPT_LED_PIN 13
-#define OPT_MAX_WIDE 14
-#define OPT_SETTLE_DELAY 15
-#define OPT_DIFF_SUPPORT 16
-#define OPT_IRQM 17
-#define OPT_PCI_FIX_UP 18
-#define OPT_BUS_CHECK 19
-#define OPT_OPTIMIZE 20
-#define OPT_RECOVERY 21
-#define OPT_SAFE_SETUP 22
-#define OPT_USE_NVRAM 23
-#define OPT_EXCLUDE 24
-#define OPT_HOST_ID 25
-
-#ifdef SCSI_NCR_IARB_SUPPORT
-#define OPT_IARB 26
-#endif
-
-static char setup_token[] __initdata =
- "tags:" "mpar:"
- "spar:" "disc:"
- "specf:" "ultra:"
- "fsn:" "revprob:"
- "sync:" "verb:"
- "debug:" "burst:"
- "led:" "wide:"
- "settle:" "diff:"
- "irqm:" "pcifix:"
- "buschk:" "optim:"
- "recovery:"
- "safe:" "nvram:"
- "excl:" "hostid:"
-#ifdef SCSI_NCR_IARB_SUPPORT
- "iarb:"
-#endif
- ; /* DONNOT REMOVE THIS ';' */
-
-#ifdef MODULE
-#define ARG_SEP ' '
-#else
-#define ARG_SEP ','
-#endif
-
-static int __init get_setup_token(char *p)
-{
- char *cur = setup_token;
- char *pc;
- int i = 0;
-
- while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
- ++pc;
- ++i;
- if (!strncmp(p, cur, pc - cur))
- return i;
- cur = pc;
- }
- return 0;
-}
-
-
-static int __init sym53c8xx__setup(char *str)
-{
-#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
- char *cur = str;
- char *pc, *pv;
- int i, val, c;
- int xi = 0;
-
- while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
- char *pe;
-
- val = 0;
- pv = pc;
- c = *++pv;
-
- if (c == 'n')
- val = 0;
- else if (c == 'y')
- val = 1;
- else
- val = (int) simple_strtoul(pv, &pe, 0);
-
- switch (get_setup_token(cur)) {
- case OPT_TAGS:
- driver_setup.default_tags = val;
- if (pe && *pe == '/') {
- i = 0;
- while (*pe && *pe != ARG_SEP &&
- i < sizeof(driver_setup.tag_ctrl)-1) {
- driver_setup.tag_ctrl[i++] = *pe++;
- }
- driver_setup.tag_ctrl[i] = '\0';
- }
- break;
- case OPT_MASTER_PARITY:
- driver_setup.master_parity = val;
- break;
- case OPT_SCSI_PARITY:
- driver_setup.scsi_parity = val;
- break;
- case OPT_DISCONNECTION:
- driver_setup.disconnection = val;
- break;
- case OPT_SPECIAL_FEATURES:
- driver_setup.special_features = val;
- break;
- case OPT_FORCE_SYNC_NEGO:
- driver_setup.force_sync_nego = val;
- break;
- case OPT_REVERSE_PROBE:
- driver_setup.reverse_probe = val;
- break;
- case OPT_DEFAULT_SYNC:
- driver_setup.default_sync = val;
- break;
- case OPT_VERBOSE:
- driver_setup.verbose = val;
- break;
- case OPT_DEBUG:
- driver_setup.debug = val;
- break;
- case OPT_BURST_MAX:
- driver_setup.burst_max = val;
- break;
- case OPT_LED_PIN:
- driver_setup.led_pin = val;
- break;
- case OPT_MAX_WIDE:
- driver_setup.max_wide = val? 1:0;
- break;
- case OPT_SETTLE_DELAY:
- driver_setup.settle_delay = val;
- break;
- case OPT_DIFF_SUPPORT:
- driver_setup.diff_support = val;
- break;
- case OPT_IRQM:
- driver_setup.irqm = val;
- break;
- case OPT_PCI_FIX_UP:
- driver_setup.pci_fix_up = val;
- break;
- case OPT_BUS_CHECK:
- driver_setup.bus_check = val;
- break;
- case OPT_OPTIMIZE:
- driver_setup.optimize = val;
- break;
- case OPT_RECOVERY:
- driver_setup.recovery = val;
- break;
- case OPT_USE_NVRAM:
- driver_setup.use_nvram = val;
- break;
- case OPT_SAFE_SETUP:
- memcpy(&driver_setup, &driver_safe_setup,
- sizeof(driver_setup));
- break;
- case OPT_EXCLUDE:
- if (xi < SCSI_NCR_MAX_EXCLUDES)
- driver_setup.excludes[xi++] = val;
- break;
- case OPT_HOST_ID:
- driver_setup.host_id = val;
- break;
-#ifdef SCSI_NCR_IARB_SUPPORT
- case OPT_IARB:
- driver_setup.iarb = val;
- break;
-#endif
- default:
- printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
- break;
- }
-
- if ((cur = strchr(cur, ARG_SEP)) != NULL)
- ++cur;
- }
-#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
- return 1;
-}
-
-/*===================================================================
-**
-** Get device queue depth from boot command line.
-**
-**===================================================================
-*/
-#define DEF_DEPTH (driver_setup.default_tags)
-#define ALL_TARGETS -2
-#define NO_TARGET -1
-#define ALL_LUNS -2
-#define NO_LUN -1
-
-static int device_queue_depth(int unit, int target, int lun)
-{
- int c, h, t, u, v;
- char *p = driver_setup.tag_ctrl;
- char *ep;
-
- h = -1;
- t = NO_TARGET;
- u = NO_LUN;
- while ((c = *p++) != 0) {
- v = simple_strtoul(p, &ep, 0);
- switch(c) {
- case '/':
- ++h;
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- case 't':
- if (t != target)
- t = (target == v) ? v : NO_TARGET;
- u = ALL_LUNS;
- break;
- case 'u':
- if (u != lun)
- u = (lun == v) ? v : NO_LUN;
- break;
- case 'q':
- if (h == unit &&
- (t == ALL_TARGETS || t == target) &&
- (u == ALL_LUNS || u == lun))
- return v;
- break;
- case '-':
- t = ALL_TARGETS;
- u = ALL_LUNS;
- break;
- default:
- break;
- }
- p = ep;
- }
- return DEF_DEPTH;
-}
diff --git a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h
deleted file mode 100644
index 139cd0e12e62..000000000000
--- a/drivers/scsi/sym53c8xx_defs.h
+++ /dev/null
@@ -1,1320 +0,0 @@
-/******************************************************************************
-** High Performance device driver for the Symbios 53C896 controller.
-**
-** Copyright (C) 1998-2001 Gerard Roudier <groudier@free.fr>
-**
-** This driver also supports all the Symbios 53C8XX controller family,
-** except 53C810 revisions < 16, 53C825 revisions < 16 and all
-** revisions of 53C815 controllers.
-**
-** This driver is based on the Linux port of the FreeBSD ncr driver.
-**
-** Copyright (C) 1994 Wolfgang Stanglmeier
-**
-**-----------------------------------------------------------------------------
-**
-** This program is free software; you can redistribute it and/or modify
-** it under the terms of the 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.
-**
-**-----------------------------------------------------------------------------
-**
-** The Linux port of the FreeBSD ncr driver has been achieved in
-** november 1995 by:
-**
-** Gerard Roudier <groudier@free.fr>
-**
-** Being given that this driver originates from the FreeBSD version, and
-** in order to keep synergy on both, any suggested enhancements and corrections
-** received on Linux are automatically a potential candidate for the FreeBSD
-** version.
-**
-** The original driver has been written for 386bsd and FreeBSD by
-** Wolfgang Stanglmeier <wolf@cologne.de>
-** Stefan Esser <se@mi.Uni-Koeln.de>
-**
-**-----------------------------------------------------------------------------
-**
-** Major contributions:
-** --------------------
-**
-** NVRAM detection and reading.
-** Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
-**
-** Added support for MIPS big endian systems.
-** Carsten Langgaard, carstenl@mips.com
-** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
-**
-** Added support for HP PARISC big endian systems.
-** Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
-**
-*******************************************************************************
-*/
-
-#ifndef SYM53C8XX_DEFS_H
-#define SYM53C8XX_DEFS_H
-
-#include <linux/config.h>
-
-/*
-** If you want a driver as small as possible, donnot define the
-** following options.
-*/
-#define SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
-#define SCSI_NCR_DEBUG_INFO_SUPPORT
-
-/*
-** To disable integrity checking, do not define the
-** following option.
-*/
-#ifdef CONFIG_SCSI_NCR53C8XX_INTEGRITY_CHECK
-# define SCSI_NCR_ENABLE_INTEGRITY_CHECK
-#endif
-
-/* ---------------------------------------------------------------------
-** Take into account kernel configured parameters.
-** Most of these options can be overridden at startup by a command line.
-** ---------------------------------------------------------------------
-*/
-
-/*
- * For Ultra2 and Ultra3 SCSI support option, use special features.
- *
- * Value (default) means:
- * bit 0 : all features enabled, except:
- * bit 1 : PCI Write And Invalidate.
- * bit 2 : Data Phase Mismatch handling from SCRIPTS.
- *
- * Use boot options ncr53c8xx=specf:1 if you want all chip features to be
- * enabled by the driver.
- */
-#define SCSI_NCR_SETUP_SPECIAL_FEATURES (3)
-
-#define SCSI_NCR_MAX_SYNC (80)
-
-/*
- * Allow tags from 2 to 256, default 8
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#if CONFIG_SCSI_NCR53C8XX_MAX_TAGS < 2
-#define SCSI_NCR_MAX_TAGS (2)
-#elif CONFIG_SCSI_NCR53C8XX_MAX_TAGS > 256
-#define SCSI_NCR_MAX_TAGS (256)
-#else
-#define SCSI_NCR_MAX_TAGS CONFIG_SCSI_NCR53C8XX_MAX_TAGS
-#endif
-#else
-#define SCSI_NCR_MAX_TAGS (8)
-#endif
-
-/*
- * Allow tagged command queuing support if configured with default number
- * of tags set to max (see above).
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#define SCSI_NCR_SETUP_DEFAULT_TAGS CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS
-#elif defined CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
-#define SCSI_NCR_SETUP_DEFAULT_TAGS SCSI_NCR_MAX_TAGS
-#else
-#define SCSI_NCR_SETUP_DEFAULT_TAGS (0)
-#endif
-
-/*
- * Immediate arbitration
- */
-#if defined(CONFIG_SCSI_NCR53C8XX_IARB)
-#define SCSI_NCR_IARB_SUPPORT
-#endif
-
-/*
- * Sync transfer frequency at startup.
- * Allow from 5Mhz to 80Mhz default 20 Mhz.
- */
-#ifndef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC (20)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC > SCSI_NCR_MAX_SYNC
-#undef CONFIG_SCSI_NCR53C8XX_SYNC
-#define CONFIG_SCSI_NCR53C8XX_SYNC SCSI_NCR_MAX_SYNC
-#endif
-
-#if CONFIG_SCSI_NCR53C8XX_SYNC == 0
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (255)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 5
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (50)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 20
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (250/(CONFIG_SCSI_NCR53C8XX_SYNC))
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 33
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (11)
-#elif CONFIG_SCSI_NCR53C8XX_SYNC <= 40
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (10)
-#else
-#define SCSI_NCR_SETUP_DEFAULT_SYNC (9)
-#endif
-
-/*
- * Disallow disconnections at boot-up
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
-#define SCSI_NCR_SETUP_DISCONNECTION (0)
-#else
-#define SCSI_NCR_SETUP_DISCONNECTION (1)
-#endif
-
-/*
- * Force synchronous negotiation for all targets
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_FORCE_SYNC_NEGO
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (1)
-#else
-#define SCSI_NCR_SETUP_FORCE_SYNC_NEGO (0)
-#endif
-
-/*
- * Disable master parity checking (flawed hardwares need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_MPARITY_CHECK
-#define SCSI_NCR_SETUP_MASTER_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_MASTER_PARITY (1)
-#endif
-
-/*
- * Disable scsi parity checking (flawed devices may need that)
- */
-#ifdef CONFIG_SCSI_NCR53C8XX_DISABLE_PARITY_CHECK
-#define SCSI_NCR_SETUP_SCSI_PARITY (0)
-#else
-#define SCSI_NCR_SETUP_SCSI_PARITY (1)
-#endif
-
-/*
- * Settle time after reset at boot-up
- */
-#define SCSI_NCR_SETUP_SETTLE_TIME (2)
-
-/*
-** Bridge quirks work-around option defaulted to 1.
-*/
-#ifndef SCSI_NCR_PCIQ_WORK_AROUND_OPT
-#define SCSI_NCR_PCIQ_WORK_AROUND_OPT 1
-#endif
-
-/*
-** Work-around common bridge misbehaviour.
-**
-** - Do not flush posted writes in the opposite
-** direction on read.
-** - May reorder DMA writes to memory.
-**
-** This option should not affect performances
-** significantly, so it is the default.
-*/
-#if SCSI_NCR_PCIQ_WORK_AROUND_OPT == 1
-#define SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
-#define SCSI_NCR_PCIQ_MAY_REORDER_WRITES
-#define SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
-
-/*
-** Same as option 1, but also deal with
-** misconfigured interrupts.
-**
-** - Edge triggerred instead of level sensitive.
-** - No interrupt line connected.
-** - IRQ number misconfigured.
-**
-** If no interrupt is delivered, the driver will
-** catch the interrupt conditions 10 times per
-** second. No need to say that this option is
-** not recommended.
-*/
-#elif SCSI_NCR_PCIQ_WORK_AROUND_OPT == 2
-#define SCSI_NCR_PCIQ_MAY_NOT_FLUSH_PW_UPSTREAM
-#define SCSI_NCR_PCIQ_MAY_REORDER_WRITES
-#define SCSI_NCR_PCIQ_MAY_MISS_COMPLETIONS
-#define SCSI_NCR_PCIQ_BROKEN_INTR
-
-/*
-** Some bridge designers decided to flush
-** everything prior to deliver the interrupt.
-** This option tries to deal with such a
-** behaviour.
-*/
-#elif SCSI_NCR_PCIQ_WORK_AROUND_OPT == 3
-#define SCSI_NCR_PCIQ_SYNC_ON_INTR
-#endif
-
-/*
-** Other parameters not configurable with "make config"
-** Avoid to change these constants, unless you know what you are doing.
-*/
-
-#define SCSI_NCR_ALWAYS_SIMPLE_TAG
-#define SCSI_NCR_MAX_SCATTER (127)
-#define SCSI_NCR_MAX_TARGET (16)
-
-/*
-** Compute some desirable value for CAN_QUEUE
-** and CMD_PER_LUN.
-** The driver will use lower values if these
-** ones appear to be too large.
-*/
-#define SCSI_NCR_CAN_QUEUE (8*SCSI_NCR_MAX_TAGS + 2*SCSI_NCR_MAX_TARGET)
-#define SCSI_NCR_CMD_PER_LUN (SCSI_NCR_MAX_TAGS)
-
-#define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER)
-#define SCSI_NCR_TIMER_INTERVAL (HZ)
-
-#if 1 /* defined CONFIG_SCSI_MULTI_LUN */
-#define SCSI_NCR_MAX_LUN (16)
-#else
-#define SCSI_NCR_MAX_LUN (1)
-#endif
-
-/*
- * IO functions definition for big/little endian CPU support.
- * For now, the NCR is only supported in little endian addressing mode,
- */
-
-#ifdef __BIG_ENDIAN
-
-#define inw_l2b inw
-#define inl_l2b inl
-#define outw_b2l outw
-#define outl_b2l outl
-
-#define readb_raw readb
-#define writeb_raw writeb
-
-#if defined(SCSI_NCR_BIG_ENDIAN)
-#define readw_l2b __raw_readw
-#define readl_l2b __raw_readl
-#define writew_b2l __raw_writew
-#define writel_b2l __raw_writel
-#define readw_raw __raw_readw
-#define readl_raw __raw_readl
-#define writew_raw __raw_writew
-#define writel_raw __raw_writel
-#else /* Other big-endian */
-#define readw_l2b readw
-#define readl_l2b readl
-#define writew_b2l writew
-#define writel_b2l writel
-#define readw_raw readw
-#define readl_raw readl
-#define writew_raw writew
-#define writel_raw writel
-#endif
-
-#else /* little endian */
-
-#define inw_raw inw
-#define inl_raw inl
-#define outw_raw outw
-#define outl_raw outl
-
-#define readb_raw readb
-#define readw_raw readw
-#define readl_raw readl
-#define writeb_raw writeb
-#define writew_raw writew
-#define writel_raw writel
-
-#endif
-
-#if !defined(__hppa__) && !defined(__mips__)
-#ifdef SCSI_NCR_BIG_ENDIAN
-#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
-#endif
-#endif
-
-#define MEMORY_BARRIER() mb()
-
-
-/*
- * If the NCR uses big endian addressing mode over the
- * PCI, actual io register addresses for byte and word
- * accesses must be changed according to lane routing.
- * Btw, ncr_offb() and ncr_offw() macros only apply to
- * constants and so donnot generate bloated code.
- */
-
-#if defined(SCSI_NCR_BIG_ENDIAN)
-
-#define ncr_offb(o) (((o)&~3)+((~((o)&3))&3))
-#define ncr_offw(o) (((o)&~3)+((~((o)&3))&2))
-
-#else
-
-#define ncr_offb(o) (o)
-#define ncr_offw(o) (o)
-
-#endif
-
-/*
- * If the CPU and the NCR use same endian-ness addressing,
- * no byte reordering is needed for script patching.
- * Macro cpu_to_scr() is to be used for script patching.
- * Macro scr_to_cpu() is to be used for getting a DWORD
- * from the script.
- */
-
-#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw) cpu_to_le32(dw)
-#define scr_to_cpu(dw) le32_to_cpu(dw)
-
-#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define cpu_to_scr(dw) cpu_to_be32(dw)
-#define scr_to_cpu(dw) be32_to_cpu(dw)
-
-#else
-
-#define cpu_to_scr(dw) (dw)
-#define scr_to_cpu(dw) (dw)
-
-#endif
-
-/*
- * Access to the controller chip.
- *
- * If the CPU and the NCR use same endian-ness addressing,
- * no byte reordering is needed for accessing chip io
- * registers. Functions suffixed by '_raw' are assumed
- * to access the chip over the PCI without doing byte
- * reordering. Functions suffixed by '_l2b' are
- * assumed to perform little-endian to big-endian byte
- * reordering, those suffixed by '_b2l' blah, blah,
- * blah, ...
- */
-
-/*
- * MEMORY mapped IO input / output
- */
-
-#define INB_OFF(o) readb_raw((char __iomem *)np->reg + ncr_offb(o))
-#define OUTB_OFF(o, val) writeb_raw((val), (char __iomem *)np->reg + ncr_offb(o))
-
-#if defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_l2b((char __iomem *)np->reg + ncr_offw(o))
-#define INL_OFF(o) readl_l2b((char __iomem *)np->reg + (o))
-
-#define OUTW_OFF(o, val) writew_b2l((val), (char __iomem *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val) writel_b2l((val), (char __iomem *)np->reg + (o))
-
-#elif defined(__LITTLE_ENDIAN) && defined(SCSI_NCR_BIG_ENDIAN)
-
-#define INW_OFF(o) readw_b2l((char __iomem *)np->reg + ncr_offw(o))
-#define INL_OFF(o) readl_b2l((char __iomem *)np->reg + (o))
-
-#define OUTW_OFF(o, val) writew_l2b((val), (char __iomem *)np->reg + ncr_offw(o))
-#define OUTL_OFF(o, val) writel_l2b((val), (char __iomem *)np->reg + (o))
-
-#else
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
-/* Only 8 or 32 bit transfers allowed */
-#define INW_OFF(o) (readb((char __iomem *)np->reg + ncr_offw(o)) << 8 | readb((char __iomem *)np->reg + ncr_offw(o) + 1))
-#else
-#define INW_OFF(o) readw_raw((char __iomem *)np->reg + ncr_offw(o))
-#endif
-#define INL_OFF(o) readl_raw((char __iomem *)np->reg + (o))
-
-#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
-/* Only 8 or 32 bit transfers allowed */
-#define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char __iomem *)np->reg + ncr_offw(o)); writeb((char)(val), (char __iomem *)np->reg + ncr_offw(o) + 1); } while (0)
-#else
-#define OUTW_OFF(o, val) writew_raw((val), (char __iomem *)np->reg + ncr_offw(o))
-#endif
-#define OUTL_OFF(o, val) writel_raw((val), (char __iomem *)np->reg + (o))
-
-#endif
-
-#define INB(r) INB_OFF (offsetof(struct ncr_reg,r))
-#define INW(r) INW_OFF (offsetof(struct ncr_reg,r))
-#define INL(r) INL_OFF (offsetof(struct ncr_reg,r))
-
-#define OUTB(r, val) OUTB_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTW(r, val) OUTW_OFF (offsetof(struct ncr_reg,r), (val))
-#define OUTL(r, val) OUTL_OFF (offsetof(struct ncr_reg,r), (val))
-
-/*
- * Set bit field ON, OFF
- */
-
-#define OUTONB(r, m) OUTB(r, INB(r) | (m))
-#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m))
-#define OUTONW(r, m) OUTW(r, INW(r) | (m))
-#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
-#define OUTONL(r, m) OUTL(r, INL(r) | (m))
-#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m))
-
-/*
- * We normally want the chip to have a consistent view
- * of driver internal data structures when we restart it.
- * Thus these macros.
- */
-#define OUTL_DSP(v) \
- do { \
- MEMORY_BARRIER(); \
- OUTL (nc_dsp, (v)); \
- } while (0)
-
-#define OUTONB_STD() \
- do { \
- MEMORY_BARRIER(); \
- OUTONB (nc_dcntl, (STD|NOCOM)); \
- } while (0)
-
-
-/*
-** NCR53C8XX devices features table.
-*/
-struct ncr_chip {
- unsigned short revision_id;
- unsigned char burst_max; /* log-base-2 of max burst */
- unsigned char offset_max;
- unsigned char nr_divisor;
- unsigned int features;
-#define FE_LED0 (1<<0)
-#define FE_WIDE (1<<1) /* Wide data transfers */
-#define FE_ULTRA (1<<2) /* Ultra speed 20Mtrans/sec */
-#define FE_DBLR (1<<4) /* Clock doubler present */
-#define FE_QUAD (1<<5) /* Clock quadrupler present */
-#define FE_ERL (1<<6) /* Enable read line */
-#define FE_CLSE (1<<7) /* Cache line size enable */
-#define FE_WRIE (1<<8) /* Write & Invalidate enable */
-#define FE_ERMP (1<<9) /* Enable read multiple */
-#define FE_BOF (1<<10) /* Burst opcode fetch */
-#define FE_DFS (1<<11) /* DMA fifo size */
-#define FE_PFEN (1<<12) /* Prefetch enable */
-#define FE_LDSTR (1<<13) /* Load/Store supported */
-#define FE_RAM (1<<14) /* On chip RAM present */
-#define FE_VARCLK (1<<15) /* SCSI clock may vary */
-#define FE_RAM8K (1<<16) /* On chip RAM sized 8Kb */
-#define FE_64BIT (1<<17) /* Have a 64-bit PCI interface */
-#define FE_IO256 (1<<18) /* Requires full 256 bytes in PCI space */
-#define FE_NOPM (1<<19) /* Scripts handles phase mismatch */
-#define FE_LEDC (1<<20) /* Hardware control of LED */
-#define FE_DIFF (1<<21) /* Support Differential SCSI */
-#define FE_66MHZ (1<<23) /* 66MHz PCI Support */
-#define FE_DAC (1<<24) /* Support DAC cycles (64 bit addressing) */
-#define FE_ISTAT1 (1<<25) /* Have ISTAT1, MBOX0, MBOX1 registers */
-#define FE_DAC_IN_USE (1<<26) /* Platform does DAC cycles */
-#define FE_EHP (1<<27) /* 720: Even host parity */
-#define FE_MUX (1<<28) /* 720: Multiplexed bus */
-#define FE_EA (1<<29) /* 720: Enable Ack */
-
-#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
-#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_DBLR|FE_QUAD|F_CLK80)
-#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
-};
-
-
-/*
-** Driver setup structure.
-**
-** This structure is initialized from linux config options.
-** It can be overridden at boot-up by the boot command line.
-*/
-#define SCSI_NCR_MAX_EXCLUDES 8
-struct ncr_driver_setup {
- u8 master_parity;
- u8 scsi_parity;
- u8 disconnection;
- u8 special_features;
- u8 force_sync_nego;
- u8 reverse_probe;
- u8 pci_fix_up;
- u8 use_nvram;
- u8 verbose;
- u8 default_tags;
- u16 default_sync;
- u16 debug;
- u8 burst_max;
- u8 led_pin;
- u8 max_wide;
- u8 settle_delay;
- u8 diff_support;
- u8 irqm;
- u8 bus_check;
- u8 optimize;
- u8 recovery;
- u8 host_id;
- u16 iarb;
- u32 excludes[SCSI_NCR_MAX_EXCLUDES];
- char tag_ctrl[100];
-};
-
-/*
-** Initial setup.
-** Can be overriden at startup by a command line.
-*/
-#define SCSI_NCR_DRIVER_SETUP \
-{ \
- SCSI_NCR_SETUP_MASTER_PARITY, \
- SCSI_NCR_SETUP_SCSI_PARITY, \
- SCSI_NCR_SETUP_DISCONNECTION, \
- SCSI_NCR_SETUP_SPECIAL_FEATURES, \
- SCSI_NCR_SETUP_FORCE_SYNC_NEGO, \
- 0, \
- 0, \
- 1, \
- 0, \
- SCSI_NCR_SETUP_DEFAULT_TAGS, \
- SCSI_NCR_SETUP_DEFAULT_SYNC, \
- 0x00, \
- 7, \
- 0, \
- 1, \
- SCSI_NCR_SETUP_SETTLE_TIME, \
- 0, \
- 0, \
- 1, \
- 0, \
- 0, \
- 255, \
- 0x00 \
-}
-
-/*
-** Boot fail safe setup.
-** Override initial setup from boot command line:
-** ncr53c8xx=safe:y
-*/
-#define SCSI_NCR_DRIVER_SAFE_SETUP \
-{ \
- 0, \
- 1, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- 1, \
- 2, \
- 0, \
- 255, \
- 0x00, \
- 255, \
- 0, \
- 0, \
- 10, \
- 1, \
- 1, \
- 1, \
- 0, \
- 0, \
- 255 \
-}
-
-/**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
-
-/*-----------------------------------------------------------------
-**
-** The ncr 53c810 register structure.
-**
-**-----------------------------------------------------------------
-*/
-
-struct ncr_reg {
-/*00*/ u8 nc_scntl0; /* full arb., ena parity, par->ATN */
-
-/*01*/ u8 nc_scntl1; /* no reset */
- #define ISCON 0x10 /* connected to scsi */
- #define CRST 0x08 /* force reset */
- #define IARB 0x02 /* immediate arbitration */
-
-/*02*/ u8 nc_scntl2; /* no disconnect expected */
- #define SDU 0x80 /* cmd: disconnect will raise error */
- #define CHM 0x40 /* sta: chained mode */
- #define WSS 0x08 /* sta: wide scsi send [W]*/
- #define WSR 0x01 /* sta: wide scsi received [W]*/
-
-/*03*/ u8 nc_scntl3; /* cnf system clock dependent */
- #define EWS 0x08 /* cmd: enable wide scsi [W]*/
- #define ULTRA 0x80 /* cmd: ULTRA enable */
- /* bits 0-2, 7 rsvd for C1010 */
-
-/*04*/ u8 nc_scid; /* cnf host adapter scsi address */
- #define RRE 0x40 /* r/w:e enable response to resel. */
- #define SRE 0x20 /* r/w:e enable response to select */
-
-/*05*/ u8 nc_sxfer; /* ### Sync speed and count */
- /* bits 6-7 rsvd for C1010 */
-
-/*06*/ u8 nc_sdid; /* ### Destination-ID */
-
-/*07*/ u8 nc_gpreg; /* ??? IO-Pins */
-
-/*08*/ u8 nc_sfbr; /* ### First byte in phase */
-
-/*09*/ u8 nc_socl;
- #define CREQ 0x80 /* r/w: SCSI-REQ */
- #define CACK 0x40 /* r/w: SCSI-ACK */
- #define CBSY 0x20 /* r/w: SCSI-BSY */
- #define CSEL 0x10 /* r/w: SCSI-SEL */
- #define CATN 0x08 /* r/w: SCSI-ATN */
- #define CMSG 0x04 /* r/w: SCSI-MSG */
- #define CC_D 0x02 /* r/w: SCSI-C_D */
- #define CI_O 0x01 /* r/w: SCSI-I_O */
-
-/*0a*/ u8 nc_ssid;
-
-/*0b*/ u8 nc_sbcl;
-
-/*0c*/ u8 nc_dstat;
- #define DFE 0x80 /* sta: dma fifo empty */
- #define MDPE 0x40 /* int: master data parity error */
- #define BF 0x20 /* int: script: bus fault */
- #define ABRT 0x10 /* int: script: command aborted */
- #define SSI 0x08 /* int: script: single step */
- #define SIR 0x04 /* int: script: interrupt instruct. */
- #define IID 0x01 /* int: script: illegal instruct. */
-
-/*0d*/ u8 nc_sstat0;
- #define ILF 0x80 /* sta: data in SIDL register lsb */
- #define ORF 0x40 /* sta: data in SODR register lsb */
- #define OLF 0x20 /* sta: data in SODL register lsb */
- #define AIP 0x10 /* sta: arbitration in progress */
- #define LOA 0x08 /* sta: arbitration lost */
- #define WOA 0x04 /* sta: arbitration won */
- #define IRST 0x02 /* sta: scsi reset signal */
- #define SDP 0x01 /* sta: scsi parity signal */
-
-/*0e*/ u8 nc_sstat1;
- #define FF3210 0xf0 /* sta: bytes in the scsi fifo */
-
-/*0f*/ u8 nc_sstat2;
- #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/
- #define ORF1 0x40 /* sta: data in SODR register msb[W]*/
- #define OLF1 0x20 /* sta: data in SODL register msb[W]*/
- #define DM 0x04 /* sta: DIFFSENS mismatch (895/6 only) */
- #define LDSC 0x02 /* sta: disconnect & reconnect */
-
-/*10*/ u8 nc_dsa; /* --> Base page */
-/*11*/ u8 nc_dsa1;
-/*12*/ u8 nc_dsa2;
-/*13*/ u8 nc_dsa3;
-
-/*14*/ u8 nc_istat; /* --> Main Command and status */
- #define CABRT 0x80 /* cmd: abort current operation */
- #define SRST 0x40 /* mod: reset chip */
- #define SIGP 0x20 /* r/w: message from host to ncr */
- #define SEM 0x10 /* r/w: message between host + ncr */
- #define CON 0x08 /* sta: connected to scsi */
- #define INTF 0x04 /* sta: int on the fly (reset by wr)*/
- #define SIP 0x02 /* sta: scsi-interrupt */
- #define DIP 0x01 /* sta: host/script interrupt */
-
-/*15*/ u8 nc_istat1; /* 896 and later cores only */
- #define FLSH 0x04 /* sta: chip is flushing */
- #define SRUN 0x02 /* sta: scripts are running */
- #define SIRQD 0x01 /* r/w: disable INT pin */
-
-/*16*/ u8 nc_mbox0; /* 896 and later cores only */
-/*17*/ u8 nc_mbox1; /* 896 and later cores only */
-
-/*18*/ u8 nc_ctest0;
- #define EHP 0x04 /* 720 even host parity */
-/*19*/ u8 nc_ctest1;
-
-/*1a*/ u8 nc_ctest2;
- #define CSIGP 0x40
- /* bits 0-2,7 rsvd for C1010 */
-
-/*1b*/ u8 nc_ctest3;
- #define FLF 0x08 /* cmd: flush dma fifo */
- #define CLF 0x04 /* cmd: clear dma fifo */
- #define FM 0x02 /* mod: fetch pin mode */
- #define WRIE 0x01 /* mod: write and invalidate enable */
- /* bits 4-7 rsvd for C1010 */
-
-/*1c*/ u32 nc_temp; /* ### Temporary stack */
-
-/*20*/ u8 nc_dfifo;
-/*21*/ u8 nc_ctest4;
- #define MUX 0x80 /* 720 host bus multiplex mode */
- #define BDIS 0x80 /* mod: burst disable */
- #define MPEE 0x08 /* mod: master parity error enable */
-
-/*22*/ u8 nc_ctest5;
- #define DFS 0x20 /* mod: dma fifo size */
- /* bits 0-1, 3-7 rsvd for C1010 */
-/*23*/ u8 nc_ctest6;
-
-/*24*/ u32 nc_dbc; /* ### Byte count and command */
-/*28*/ u32 nc_dnad; /* ### Next command register */
-/*2c*/ u32 nc_dsp; /* --> Script Pointer */
-/*30*/ u32 nc_dsps; /* --> Script pointer save/opcode#2 */
-
-/*34*/ u8 nc_scratcha; /* Temporary register a */
-/*35*/ u8 nc_scratcha1;
-/*36*/ u8 nc_scratcha2;
-/*37*/ u8 nc_scratcha3;
-
-/*38*/ u8 nc_dmode;
- #define BL_2 0x80 /* mod: burst length shift value +2 */
- #define BL_1 0x40 /* mod: burst length shift value +1 */
- #define ERL 0x08 /* mod: enable read line */
- #define ERMP 0x04 /* mod: enable read multiple */
- #define BOF 0x02 /* mod: burst op code fetch */
-
-/*39*/ u8 nc_dien;
-/*3a*/ u8 nc_sbr;
-
-/*3b*/ u8 nc_dcntl; /* --> Script execution control */
- #define CLSE 0x80 /* mod: cache line size enable */
- #define PFF 0x40 /* cmd: pre-fetch flush */
- #define PFEN 0x20 /* mod: pre-fetch enable */
- #define EA 0x20 /* mod: 720 enable-ack */
- #define SSM 0x10 /* mod: single step mode */
- #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */
- #define STD 0x04 /* cmd: start dma mode */
- #define IRQD 0x02 /* mod: irq disable */
- #define NOCOM 0x01 /* cmd: protect sfbr while reselect */
- /* bits 0-1 rsvd for C1010 */
-
-/*3c*/ u32 nc_adder;
-
-/*40*/ u16 nc_sien; /* -->: interrupt enable */
-/*42*/ u16 nc_sist; /* <--: interrupt status */
- #define SBMC 0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
- #define STO 0x0400/* sta: timeout (select) */
- #define GEN 0x0200/* sta: timeout (general) */
- #define HTH 0x0100/* sta: timeout (handshake) */
- #define MA 0x80 /* sta: phase mismatch */
- #define CMP 0x40 /* sta: arbitration complete */
- #define SEL 0x20 /* sta: selected by another device */
- #define RSL 0x10 /* sta: reselected by another device*/
- #define SGE 0x08 /* sta: gross error (over/underflow)*/
- #define UDC 0x04 /* sta: unexpected disconnect */
- #define RST 0x02 /* sta: scsi bus reset detected */
- #define PAR 0x01 /* sta: scsi parity error */
-
-/*44*/ u8 nc_slpar;
-/*45*/ u8 nc_swide;
-/*46*/ u8 nc_macntl;
-/*47*/ u8 nc_gpcntl;
-/*48*/ u8 nc_stime0; /* cmd: timeout for select&handshake*/
-/*49*/ u8 nc_stime1; /* cmd: timeout user defined */
-/*4a*/ u16 nc_respid; /* sta: Reselect-IDs */
-
-/*4c*/ u8 nc_stest0;
-
-/*4d*/ u8 nc_stest1;
- #define SCLK 0x80 /* Use the PCI clock as SCSI clock */
- #define DBLEN 0x08 /* clock doubler running */
- #define DBLSEL 0x04 /* clock doubler selected */
-
-
-/*4e*/ u8 nc_stest2;
- #define ROF 0x40 /* reset scsi offset (after gross error!) */
- #define DIF 0x20 /* 720 SCSI differential mode */
- #define EXT 0x02 /* extended filtering */
-
-/*4f*/ u8 nc_stest3;
- #define TE 0x80 /* c: tolerAnt enable */
- #define HSC 0x20 /* c: Halt SCSI Clock */
- #define CSF 0x02 /* c: clear scsi fifo */
-
-/*50*/ u16 nc_sidl; /* Lowlevel: latched from scsi data */
-/*52*/ u8 nc_stest4;
- #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */
- #define SMODE_HVD 0x40 /* High Voltage Differential */
- #define SMODE_SE 0x80 /* Single Ended */
- #define SMODE_LVD 0xc0 /* Low Voltage Differential */
- #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */
- /* bits 0-5 rsvd for C1010 */
-
-/*53*/ u8 nc_53_;
-/*54*/ u16 nc_sodl; /* Lowlevel: data out to scsi data */
-/*56*/ u8 nc_ccntl0; /* Chip Control 0 (896) */
- #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
- #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
- #define ENNDJ 0x20 /* Enable Non Data PM Jump */
- #define DISFC 0x10 /* Disable Auto FIFO Clear */
- #define DILS 0x02 /* Disable Internal Load/Store */
- #define DPR 0x01 /* Disable Pipe Req */
-
-/*57*/ u8 nc_ccntl1; /* Chip Control 1 (896) */
- #define ZMOD 0x80 /* High Impedance Mode */
- #define DIC 0x10 /* Disable Internal Cycles */
- #define DDAC 0x08 /* Disable Dual Address Cycle */
- #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
- #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
- #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
-
-/*58*/ u16 nc_sbdl; /* Lowlevel: data from scsi data */
-/*5a*/ u16 nc_5a_;
-
-/*5c*/ u8 nc_scr0; /* Working register B */
-/*5d*/ u8 nc_scr1; /* */
-/*5e*/ u8 nc_scr2; /* */
-/*5f*/ u8 nc_scr3; /* */
-
-/*60*/ u8 nc_scrx[64]; /* Working register C-R */
-/*a0*/ u32 nc_mmrs; /* Memory Move Read Selector */
-/*a4*/ u32 nc_mmws; /* Memory Move Write Selector */
-/*a8*/ u32 nc_sfs; /* Script Fetch Selector */
-/*ac*/ u32 nc_drs; /* DSA Relative Selector */
-/*b0*/ u32 nc_sbms; /* Static Block Move Selector */
-/*b4*/ u32 nc_dbms; /* Dynamic Block Move Selector */
-/*b8*/ u32 nc_dnad64; /* DMA Next Address 64 */
-/*bc*/ u16 nc_scntl4; /* C1010 only */
- #define U3EN 0x80 /* Enable Ultra 3 */
- #define AIPEN 0x40 /* Allow check upper byte lanes */
- #define XCLKH_DT 0x08 /* Extra clock of data hold on DT
- transfer edge */
- #define XCLKH_ST 0x04 /* Extra clock of data hold on ST
- transfer edge */
-
-/*be*/ u8 nc_aipcntl0; /* Epat Control 1 C1010 only */
-/*bf*/ u8 nc_aipcntl1; /* AIP Control C1010_66 Only */
-
-/*c0*/ u32 nc_pmjad1; /* Phase Mismatch Jump Address 1 */
-/*c4*/ u32 nc_pmjad2; /* Phase Mismatch Jump Address 2 */
-/*c8*/ u8 nc_rbc; /* Remaining Byte Count */
-/*c9*/ u8 nc_rbc1; /* */
-/*ca*/ u8 nc_rbc2; /* */
-/*cb*/ u8 nc_rbc3; /* */
-
-/*cc*/ u8 nc_ua; /* Updated Address */
-/*cd*/ u8 nc_ua1; /* */
-/*ce*/ u8 nc_ua2; /* */
-/*cf*/ u8 nc_ua3; /* */
-/*d0*/ u32 nc_esa; /* Entry Storage Address */
-/*d4*/ u8 nc_ia; /* Instruction Address */
-/*d5*/ u8 nc_ia1;
-/*d6*/ u8 nc_ia2;
-/*d7*/ u8 nc_ia3;
-/*d8*/ u32 nc_sbc; /* SCSI Byte Count (3 bytes only) */
-/*dc*/ u32 nc_csbc; /* Cumulative SCSI Byte Count */
-
- /* Following for C1010 only */
-/*e0*/ u16 nc_crcpad; /* CRC Value */
-/*e2*/ u8 nc_crccntl0; /* CRC control register */
- #define SNDCRC 0x10 /* Send CRC Request */
-/*e3*/ u8 nc_crccntl1; /* CRC control register */
-/*e4*/ u32 nc_crcdata; /* CRC data register */
-/*e8*/ u32 nc_e8_; /* rsvd */
-/*ec*/ u32 nc_ec_; /* rsvd */
-/*f0*/ u16 nc_dfbc; /* DMA FIFO byte count */
-
-};
-
-/*-----------------------------------------------------------
-**
-** Utility macros for the script.
-**
-**-----------------------------------------------------------
-*/
-
-#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r))
-#define REG(r) REGJ (nc_, r)
-
-typedef u32 ncrcmd;
-
-/*-----------------------------------------------------------
-**
-** SCSI phases
-**
-** DT phases illegal for ncr driver.
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_DATA_OUT 0x00000000
-#define SCR_DATA_IN 0x01000000
-#define SCR_COMMAND 0x02000000
-#define SCR_STATUS 0x03000000
-#define SCR_DT_DATA_OUT 0x04000000
-#define SCR_DT_DATA_IN 0x05000000
-#define SCR_MSG_OUT 0x06000000
-#define SCR_MSG_IN 0x07000000
-
-#define SCR_ILG_OUT 0x04000000
-#define SCR_ILG_IN 0x05000000
-
-/*-----------------------------------------------------------
-**
-** Data transfer via SCSI.
-**
-**-----------------------------------------------------------
-**
-** MOVE_ABS (LEN)
-** <<start address>>
-**
-** MOVE_IND (LEN)
-** <<dnad_offset>>
-**
-** MOVE_TBL
-** <<dnad_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define OPC_MOVE 0x08000000
-
-#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
-#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
-#define SCR_MOVE_TBL (0x10000000 | OPC_MOVE)
-
-#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
-#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
-#define SCR_CHMOV_TBL (0x10000000)
-
-struct scr_tblmove {
- u32 size;
- u32 addr;
-};
-
-/*-----------------------------------------------------------
-**
-** Selection
-**
-**-----------------------------------------------------------
-**
-** SEL_ABS | SCR_ID (0..15) [ | REL_JMP]
-** <<alternate_address>>
-**
-** SEL_TBL | << dnad_offset>> [ | REL_JMP]
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SEL_ABS 0x40000000
-#define SCR_SEL_ABS_ATN 0x41000000
-#define SCR_SEL_TBL 0x42000000
-#define SCR_SEL_TBL_ATN 0x43000000
-
-
-#ifdef SCSI_NCR_BIG_ENDIAN
-struct scr_tblsel {
- u8 sel_scntl3;
- u8 sel_id;
- u8 sel_sxfer;
- u8 sel_scntl4;
-};
-#else
-struct scr_tblsel {
- u8 sel_scntl4;
- u8 sel_sxfer;
- u8 sel_id;
- u8 sel_scntl3;
-};
-#endif
-
-#define SCR_JMP_REL 0x04000000
-#define SCR_ID(id) (((u32)(id)) << 16)
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** WAIT_DISC
-** dummy: <<alternate_address>>
-**
-** WAIT_RESEL
-** <<alternate_address>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_WAIT_DISC 0x48000000
-#define SCR_WAIT_RESEL 0x50000000
-
-/*-----------------------------------------------------------
-**
-** Bit Set / Reset
-**
-**-----------------------------------------------------------
-**
-** SET (flags {|.. })
-**
-** CLR (flags {|.. })
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_SET(f) (0x58000000 | (f))
-#define SCR_CLR(f) (0x60000000 | (f))
-
-#define SCR_CARRY 0x00000400
-#define SCR_TRG 0x00000200
-#define SCR_ACK 0x00000040
-#define SCR_ATN 0x00000008
-
-
-
-
-/*-----------------------------------------------------------
-**
-** Memory to memory move
-**
-**-----------------------------------------------------------
-**
-** COPY (bytecount)
-** << source_address >>
-** << destination_address >>
-**
-** SCR_COPY sets the NO FLUSH option by default.
-** SCR_COPY_F does not set this option.
-**
-** For chips which do not support this option,
-** ncr_copy_and_bind() will remove this bit.
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_FLUSH 0x01000000
-
-#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
-#define SCR_COPY_F(n) (0xc0000000 | (n))
-
-/*-----------------------------------------------------------
-**
-** Register move and binary operations
-**
-**-----------------------------------------------------------
-**
-** SFBR_REG (reg, op, data) reg = SFBR op data
-** << 0 >>
-**
-** REG_SFBR (reg, op, data) SFBR = reg op data
-** << 0 >>
-**
-** REG_REG (reg, op, data) reg = reg op data
-** << 0 >>
-**
-**-----------------------------------------------------------
-** On 810A, 860, 825A, 875, 895 and 896 chips the content
-** of SFBR register can be used as data (SCR_SFBR_DATA).
-** The 896 has additionnal IO registers starting at
-** offset 0x80. Bit 7 of register offset is stored in
-** bit 7 of the SCRIPTS instruction first DWORD.
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul) + ((ofs) & 0x80))
-
-#define SCR_SFBR_REG(reg,op,data) \
- (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-#define SCR_REG_SFBR(reg,op,data) \
- (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-#define SCR_REG_REG(reg,op,data) \
- (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
-
-
-#define SCR_LOAD 0x00000000
-#define SCR_SHL 0x01000000
-#define SCR_OR 0x02000000
-#define SCR_XOR 0x03000000
-#define SCR_AND 0x04000000
-#define SCR_SHR 0x05000000
-#define SCR_ADD 0x06000000
-#define SCR_ADDC 0x07000000
-
-#define SCR_SFBR_DATA (0x00800000>>8ul) /* Use SFBR as data */
-
-/*-----------------------------------------------------------
-**
-** FROM_REG (reg) SFBR = reg
-** << 0 >>
-**
-** TO_REG (reg) reg = SFBR
-** << 0 >>
-**
-** LOAD_REG (reg, data) reg = <data>
-** << 0 >>
-**
-** LOAD_SFBR(data) SFBR = <data>
-** << 0 >>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_FROM_REG(reg) \
- SCR_REG_SFBR(reg,SCR_OR,0)
-
-#define SCR_TO_REG(reg) \
- SCR_SFBR_REG(reg,SCR_OR,0)
-
-#define SCR_LOAD_REG(reg,data) \
- SCR_REG_REG(reg,SCR_LOAD,data)
-
-#define SCR_LOAD_SFBR(data) \
- (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
-
-/*-----------------------------------------------------------
-**
-** LOAD from memory to register.
-** STORE from register to memory.
-**
-** Only supported by 810A, 860, 825A, 875, 895 and 896.
-**
-**-----------------------------------------------------------
-**
-** LOAD_ABS (LEN)
-** <<start address>>
-**
-** LOAD_REL (LEN) (DSA relative)
-** <<dsa_offset>>
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
-#define SCR_NO_FLUSH2 0x02000000
-#define SCR_DSA_REL2 0x10000000
-
-#define SCR_LOAD_R(reg, how, n) \
- (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
-
-#define SCR_STORE_R(reg, how, n) \
- (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
-
-#define SCR_LOAD_ABS(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_LOAD_REL(reg, n) SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
-#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
-#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
-
-#define SCR_STORE_ABS(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
-#define SCR_STORE_REL(reg, n) SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
-#define SCR_STORE_ABS_F(reg, n) SCR_STORE_R(reg, 0, n)
-#define SCR_STORE_REL_F(reg, n) SCR_STORE_R(reg, SCR_DSA_REL2, n)
-
-
-/*-----------------------------------------------------------
-**
-** Waiting for Disconnect or Reselect
-**
-**-----------------------------------------------------------
-**
-** JUMP [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** JUMPR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** CALL [ | IFTRUE/IFFALSE ( ... ) ]
-** <<address>>
-**
-** CALLR [ | IFTRUE/IFFALSE ( ... ) ]
-** <<distance>>
-**
-** RETURN [ | IFTRUE/IFFALSE ( ... ) ]
-** <<dummy>>
-**
-** INT [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ]
-** <<ident>>
-**
-** Conditions:
-** WHEN (phase)
-** IF (phase)
-** CARRYSET
-** DATA (data, mask)
-**
-**-----------------------------------------------------------
-*/
-
-#define SCR_NO_OP 0x80000000
-#define SCR_JUMP 0x80080000
-#define SCR_JUMP64 0x80480000
-#define SCR_JUMPR 0x80880000
-#define SCR_CALL 0x88080000
-#define SCR_CALLR 0x88880000
-#define SCR_RETURN 0x90080000
-#define SCR_INT 0x98080000
-#define SCR_INT_FLY 0x98180000
-
-#define IFFALSE(arg) (0x00080000 | (arg))
-#define IFTRUE(arg) (0x00000000 | (arg))
-
-#define WHEN(phase) (0x00030000 | (phase))
-#define IF(phase) (0x00020000 | (phase))
-
-#define DATA(D) (0x00040000 | ((D) & 0xff))
-#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
-
-#define CARRYSET (0x00200000)
-
-/*-----------------------------------------------------------
-**
-** SCSI constants.
-**
-**-----------------------------------------------------------
-*/
-
-/*
-** Messages
-*/
-
-#define M_COMPLETE COMMAND_COMPLETE
-#define M_EXTENDED EXTENDED_MESSAGE
-#define M_SAVE_DP SAVE_POINTERS
-#define M_RESTORE_DP RESTORE_POINTERS
-#define M_DISCONNECT DISCONNECT
-#define M_ID_ERROR INITIATOR_ERROR
-#define M_ABORT ABORT_TASK_SET
-#define M_REJECT MESSAGE_REJECT
-#define M_NOOP NOP
-#define M_PARITY MSG_PARITY_ERROR
-#define M_LCOMPLETE LINKED_CMD_COMPLETE
-#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
-#define M_RESET TARGET_RESET
-#define M_ABORT_TAG ABORT_TASK
-#define M_CLEAR_QUEUE CLEAR_TASK_SET
-#define M_INIT_REC INITIATE_RECOVERY
-#define M_REL_REC RELEASE_RECOVERY
-#define M_TERMINATE (0x11)
-#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
-#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
-#define M_ORDERED_TAG ORDERED_QUEUE_TAG
-#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
-#define M_IDENTIFY (0x80)
-
-#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
-#define M_X_SYNC_REQ EXTENDED_SDTR
-#define M_X_WIDE_REQ EXTENDED_WDTR
-#define M_X_PPR_REQ EXTENDED_PPR
-
-/*
-** Status
-*/
-
-#define S_GOOD (0x00)
-#define S_CHECK_COND (0x02)
-#define S_COND_MET (0x04)
-#define S_BUSY (0x08)
-#define S_INT (0x10)
-#define S_INT_COND_MET (0x14)
-#define S_CONFLICT (0x18)
-#define S_TERMINATED (0x20)
-#define S_QUEUE_FULL (0x28)
-#define S_ILLEGAL (0xff)
-#define S_SENSE (0x80)
-
-/*
- * End of ncrreg from FreeBSD
- */
-
-#endif /* defined SYM53C8XX_DEFS_H */
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index fd63add6a577..fb53eeaee617 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -465,7 +465,7 @@ wd33c93_execute(struct Scsi_Host *instance)
*/
cmd = (struct scsi_cmnd *) hostdata->input_Q;
- prev = 0;
+ prev = NULL;
while (cmd) {
if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)))
break;
@@ -1569,7 +1569,7 @@ wd33c93_abort(struct scsi_cmnd * cmd)
*/
tmp = (struct scsi_cmnd *) hostdata->input_Q;
- prev = 0;
+ prev = NULL;
while (tmp) {
if (tmp == cmd) {
if (prev)
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index b5cf39468d18..221999bcf8fe 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -94,15 +94,6 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
status = *CSR_UARTFLG;
while (!(status & 0x10) && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
ch = *CSR_UARTDR;
flag = TTY_NORMAL;
port->icount.rx++;
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 67e9afa000c1..8cbf0fc5a225 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD;
* memory if large numbers of serial ports are open.
*/
static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */
-DECLARE_MUTEX(tmp_buf_sem);
static inline int serial_paranoia_check(struct m68k_serial *info,
char *name, const char *routine)
@@ -294,7 +293,7 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
{
struct tty_struct *tty = info->tty;
m68328_uart *uart = &uart_addr[info->line];
- unsigned char ch;
+ unsigned char ch, flag;
/*
* This do { } while() loop will get ALL chars out of Rx FIFO
@@ -332,26 +331,24 @@ static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *reg
/*
* Make sure that we do not overflow the buffer
*/
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ if (tty_request_buffer_room(tty, 1) == 0) {
schedule_work(&tty->flip.work);
return;
}
+ flag = TTY_NORMAL;
+
if(rx & URX_PARITY_ERROR) {
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
status_handle(info, rx);
} else if(rx & URX_OVRUN) {
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
status_handle(info, rx);
} else if(rx & URX_FRAME_ERROR) {
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ flag = TTY_FRAME;
status_handle(info, rx);
- } else {
- *tty->flip.flag_buf_ptr++ = 0; /* XXX */
}
- *tty->flip.char_buf_ptr++ = ch;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, ch, flag);
#ifndef CONFIG_XCOPILOT_BUGS
} while((rx = uart->urx.w) & URX_DATA_READY);
#endif
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 170c9d2a749c..60f5a5dc17f1 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -394,7 +394,7 @@ static void rs_360_start(struct tty_struct *tty)
static _INLINE_ void receive_chars(ser_info_t *info)
{
struct tty_struct *tty = info->tty;
- unsigned char ch, *cp;
+ unsigned char ch, flag, *cp;
/*int ignored = 0;*/
int i;
ushort status;
@@ -438,24 +438,15 @@ static _INLINE_ void receive_chars(ser_info_t *info)
cp = (char *)bdp->buf;
status = bdp->status;
- /* Check to see if there is room in the tty buffer for
- * the characters in our BD buffer. If not, we exit
- * now, leaving the BD with the characters. We'll pick
- * them up again on the next receive interrupt (which could
- * be a timeout).
- */
- if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE)
- break;
-
while (i-- > 0) {
ch = *cp++;
- *tty->flip.char_buf_ptr = ch;
icount->rx++;
#ifdef SERIAL_DEBUG_INTR
printk("DR%02x:%02x...", ch, status);
#endif
- *tty->flip.flag_buf_ptr = 0;
+ flag = TTY_NORMAL;
+
if (status & (BD_SC_BR | BD_SC_FR |
BD_SC_PR | BD_SC_OV)) {
/*
@@ -490,30 +481,18 @@ static _INLINE_ void receive_chars(ser_info_t *info)
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (status & BD_SC_PR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & BD_SC_FR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & BD_SC_OV) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr =
- TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
}
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
+ if (status & BD_SC_OV)
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
/* This BD is ready to be used again. Clear status.
@@ -541,12 +520,7 @@ static _INLINE_ void receive_break(ser_info_t *info)
/* Check to see if there is room in the tty buffer for
* the break. If not, we exit now, losing the break. FIXME
*/
- if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
- return;
- *(tty->flip.flag_buf_ptr++) = TTY_BREAK;
- *(tty->flip.char_buf_ptr++) = 0;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, 0, TTY_BREAK);
schedule_work(&tty->flip.work);
}
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d2bcd1f87cd6..bc36edff2058 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -41,6 +41,7 @@
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/nmi.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -54,6 +55,8 @@
*/
static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
+static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
+
/*
* Debugging.
*/
@@ -296,7 +299,7 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
#endif
-static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
+static unsigned int serial_in(struct uart_8250_port *up, int offset)
{
offset = map_8250_in_reg(up, offset) << up->port.regshift;
@@ -321,7 +324,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
}
}
-static _INLINE_ void
+static void
serial_out(struct uart_8250_port *up, int offset, int value)
{
offset = map_8250_out_reg(up, offset) << up->port.regshift;
@@ -1131,7 +1134,7 @@ static void serial8250_enable_ms(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
-static _INLINE_ void
+static void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
@@ -1140,19 +1143,6 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
char flag;
do {
- /* 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) {
- 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
- */
- }
ch = serial_inp(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1217,7 +1207,7 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
*status = lsr;
}
-static _INLINE_ void transmit_chars(struct uart_8250_port *up)
+static void transmit_chars(struct uart_8250_port *up)
{
struct circ_buf *xmit = &up->port.info->xmit;
int count;
@@ -1255,25 +1245,24 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
__stop_tx(up);
}
-static _INLINE_ void check_modem_status(struct uart_8250_port *up)
+static unsigned int check_modem_status(struct uart_8250_port *up)
{
- int status;
-
- status = serial_in(up, UART_MSR);
+ unsigned int status = serial_in(up, UART_MSR);
- if ((status & UART_MSR_ANY_DELTA) == 0)
- return;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI) {
+ if (status & UART_MSR_TERI)
+ up->port.icount.rng++;
+ if (status & UART_MSR_DDSR)
+ up->port.icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
- if (status & UART_MSR_TERI)
- up->port.icount.rng++;
- if (status & UART_MSR_DDSR)
- up->port.icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
+ wake_up_interruptible(&up->port.info->delta_msr_wait);
+ }
- wake_up_interruptible(&up->port.info->delta_msr_wait);
+ return status;
}
/*
@@ -1282,7 +1271,11 @@ static _INLINE_ void check_modem_status(struct uart_8250_port *up)
static inline void
serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
{
- unsigned int status = serial_inp(up, UART_LSR);
+ unsigned int status;
+
+ spin_lock(&up->port.lock);
+
+ status = serial_inp(up, UART_LSR);
DEBUG_INTR("status = %x...", status);
@@ -1291,6 +1284,8 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs)
check_modem_status(up);
if (status & UART_LSR_THRE)
transmit_chars(up);
+
+ spin_unlock(&up->port.lock);
}
/*
@@ -1326,9 +1321,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *r
iir = serial_in(up, UART_IIR);
if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
serial8250_handle_port(up, regs);
- spin_unlock(&up->port.lock);
handled = 1;
@@ -1427,11 +1420,8 @@ static void serial8250_timeout(unsigned long data)
unsigned int iir;
iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT)) {
- spin_lock(&up->port.lock);
+ if (!(iir & UART_IIR_NO_INT))
serial8250_handle_port(up, NULL);
- spin_unlock(&up->port.lock);
- }
timeout = up->port.timeout;
timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
@@ -1454,10 +1444,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
static unsigned int serial8250_get_mctrl(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
- unsigned char status;
+ unsigned int status;
unsigned int ret;
- status = serial_in(up, UART_MSR);
+ status = check_modem_status(up);
ret = 0;
if (status & UART_MSR_DCD)
@@ -2118,7 +2108,7 @@ static void __init serial8250_isa_init_ports(void)
return;
first = 0;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
up->port.line = i;
@@ -2137,7 +2127,7 @@ static void __init serial8250_isa_init_ports(void)
}
for (i = 0, up = serial8250_ports;
- i < ARRAY_SIZE(old_serial_port) && i < UART_NR;
+ i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
@@ -2159,7 +2149,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
serial8250_isa_init_ports();
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
up->port.dev = dev;
@@ -2262,7 +2252,7 @@ static int serial8250_console_setup(struct console *co, char *options)
* if so, search for the first available port that does have
* console support.
*/
- if (co->index >= UART_NR)
+ if (co->index >= nr_uarts)
co->index = 0;
port = &serial8250_ports[co->index].port;
if (!port->iobase && !port->membase)
@@ -2298,11 +2288,9 @@ static int __init find_port(struct uart_port *p)
int line;
struct uart_port *port;
- for (line = 0; line < UART_NR; line++) {
+ for (line = 0; line < nr_uarts; line++) {
port = &serial8250_ports[line].port;
- if (p->iotype == port->iotype &&
- p->iobase == port->iobase &&
- p->membase == port->membase)
+ if (uart_match_port(p, port))
return line;
}
return -ENODEV;
@@ -2422,7 +2410,7 @@ static int __devexit serial8250_remove(struct platform_device *dev)
{
int i;
- for (i = 0; i < UART_NR; i++) {
+ for (i = 0; i < nr_uarts; i++) {
struct uart_8250_port *up = &serial8250_ports[i];
if (up->port.dev == &dev->dev)
@@ -2466,6 +2454,7 @@ static struct platform_driver serial8250_isa_driver = {
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
+ .owner = THIS_MODULE,
},
};
@@ -2480,7 +2469,7 @@ static struct platform_device *serial8250_isa_devs;
* 16x50 serial ports to be configured at run-time, to support PCMCIA
* modems and PCI multiport cards.
*/
-static DECLARE_MUTEX(serial_sem);
+static DEFINE_MUTEX(serial_mutex);
static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port)
{
@@ -2489,7 +2478,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
/*
* First, find a port entry which matches.
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (uart_match_port(&serial8250_ports[i].port, port))
return &serial8250_ports[i];
@@ -2498,7 +2487,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
* free entry. We look for one which hasn't been previously
* used (indicated by zero iobase).
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (serial8250_ports[i].port.type == PORT_UNKNOWN &&
serial8250_ports[i].port.iobase == 0)
return &serial8250_ports[i];
@@ -2507,7 +2496,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *
* That also failed. Last resort is to find any entry which
* doesn't have a real port associated with it.
*/
- for (i = 0; i < UART_NR; i++)
+ for (i = 0; i < nr_uarts; i++)
if (serial8250_ports[i].port.type == PORT_UNKNOWN)
return &serial8250_ports[i];
@@ -2535,7 +2524,7 @@ int serial8250_register_port(struct uart_port *port)
if (port->uartclk == 0)
return -EINVAL;
- down(&serial_sem);
+ mutex_lock(&serial_mutex);
uart = serial8250_find_match_or_unused(port);
if (uart) {
@@ -2557,7 +2546,7 @@ int serial8250_register_port(struct uart_port *port)
if (ret == 0)
ret = uart->port.line;
}
- up(&serial_sem);
+ mutex_unlock(&serial_mutex);
return ret;
}
@@ -2574,7 +2563,7 @@ void serial8250_unregister_port(int line)
{
struct uart_8250_port *uart = &serial8250_ports[line];
- down(&serial_sem);
+ mutex_lock(&serial_mutex);
uart_remove_one_port(&serial8250_reg, &uart->port);
if (serial8250_isa_devs) {
uart->port.flags &= ~UPF_BOOT_AUTOCONF;
@@ -2584,7 +2573,7 @@ void serial8250_unregister_port(int line)
} else {
uart->port.dev = NULL;
}
- up(&serial_sem);
+ mutex_unlock(&serial_mutex);
}
EXPORT_SYMBOL(serial8250_unregister_port);
@@ -2592,8 +2581,11 @@ static int __init serial8250_init(void)
{
int ret, i;
+ if (nr_uarts > UART_NR)
+ nr_uarts = UART_NR;
+
printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "
- "%d ports, IRQ sharing %sabled\n", (int) UART_NR,
+ "%d ports, IRQ sharing %sabled\n", nr_uarts,
share_irqs ? "en" : "dis");
for (i = 0; i < NR_IRQS; i++)
@@ -2603,21 +2595,27 @@ static int __init serial8250_init(void)
if (ret)
goto out;
- serial8250_isa_devs = platform_device_register_simple("serial8250",
- PLAT8250_DEV_LEGACY, NULL, 0);
- if (IS_ERR(serial8250_isa_devs)) {
- ret = PTR_ERR(serial8250_isa_devs);
- goto unreg;
+ serial8250_isa_devs = platform_device_alloc("serial8250",
+ PLAT8250_DEV_LEGACY);
+ if (!serial8250_isa_devs) {
+ ret = -ENOMEM;
+ goto unreg_uart_drv;
}
+ ret = platform_device_add(serial8250_isa_devs);
+ if (ret)
+ goto put_dev;
+
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
ret = platform_driver_register(&serial8250_isa_driver);
if (ret == 0)
goto out;
- platform_device_unregister(serial8250_isa_devs);
- unreg:
+ platform_device_del(serial8250_isa_devs);
+ put_dev:
+ platform_device_put(serial8250_isa_devs);
+ unreg_uart_drv:
uart_unregister_driver(&serial8250_reg);
out:
return ret;
@@ -2653,6 +2651,9 @@ module_param(share_irqs, uint, 0644);
MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
" (unsafe)");
+module_param(nr_uarts, uint, 0644);
+MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
+
#ifdef CONFIG_SERIAL_8250_RSA
module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index a607b98016db..490606b87095 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -51,12 +51,6 @@ struct serial8250_config {
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
-#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
-#define _INLINE_ inline
-#else
-#define _INLINE_
-#endif
-
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 8adca0ce267f..2a912153321e 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -837,8 +837,8 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
return quirk;
}
-static _INLINE_ int
-get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
+static inline int get_pci_irq(struct pci_dev *dev,
+ struct pciserial_board *board)
{
if (board->flags & FL_NOIRQ)
return 0;
@@ -853,14 +853,15 @@ get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)
* driver_data member.
*
* The makeup of these names are:
- * pbn_bn{_bt}_n_baud
+ * pbn_bn{_bt}_n_baud{_offsetinhex}
*
- * bn = PCI BAR number
- * bt = Index using PCI BARs
- * n = number of serial ports
- * baud = baud rate
+ * bn = PCI BAR number
+ * bt = Index using PCI BARs
+ * n = number of serial ports
+ * baud = baud rate
+ * offsetinhex = offset for each sequential port (in hex)
*
- * This table is sorted by (in order): baud, bt, bn, n.
+ * This table is sorted by (in order): bn, bt, baud, offsetindex, n.
*
* Please note: in theory if n = 1, _bt infix should make no difference.
* ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200
@@ -881,6 +882,13 @@ enum pci_board_num_t {
pbn_b0_4_1152000,
+ pbn_b0_2_1843200,
+ pbn_b0_4_1843200,
+
+ pbn_b0_2_1843200_200,
+ pbn_b0_4_1843200_200,
+ pbn_b0_8_1843200_200,
+
pbn_b0_bt_1_115200,
pbn_b0_bt_2_115200,
pbn_b0_bt_8_115200,
@@ -904,6 +912,8 @@ enum pci_board_num_t {
pbn_b1_4_921600,
pbn_b1_8_921600,
+ pbn_b1_2_1250000,
+
pbn_b1_bt_2_921600,
pbn_b1_1_1382400,
@@ -930,6 +940,7 @@ enum pci_board_num_t {
pbn_b2_bt_2_921600,
pbn_b2_bt_4_921600,
+ pbn_b3_2_115200,
pbn_b3_4_115200,
pbn_b3_8_115200,
@@ -1029,6 +1040,38 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b0_2_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+ [pbn_b0_4_1843200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 8,
+ },
+
+ [pbn_b0_2_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_4_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+ [pbn_b0_8_1843200_200] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 1843200,
+ .uart_offset = 0x200,
+ },
+
[pbn_b0_bt_1_115200] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
@@ -1141,6 +1184,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 8,
},
+ [pbn_b1_2_1250000] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+ .base_baud = 1250000,
+ .uart_offset = 8,
+ },
[pbn_b1_bt_2_921600] = {
.flags = FL_BASE1|FL_BASE_BARS,
@@ -1263,6 +1312,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8,
},
+ [pbn_b3_2_115200] = {
+ .flags = FL_BASE3,
+ .num_ports = 2,
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
[pbn_b3_4_115200] = {
.flags = FL_BASE3,
.num_ports = 4,
@@ -1801,6 +1856,66 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0,
pbn_b1_4_921600 },
+ { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0,
+ pbn_b1_2_1250000 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0,
+ pbn_b0_2_1843200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0,
+ pbn_b0_4_1843200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0,
+ pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0,
+ pbn_b0_2_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0,
+ pbn_b0_4_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+ PCI_SUBVENDOR_ID_CONNECT_TECH,
+ PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
+ pbn_b0_8_1843200_200 },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -2164,6 +2279,9 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_nec_nile4 },
+ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b3_2_115200 },
{ PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b3_4_115200 },
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 812bae62c8ec..9fd1925de361 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -95,6 +95,16 @@ config SERIAL_8250_NR_UARTS
PCI enumeration and any ports that may be added at run-time
via hot-plug, or any ISA multi-port serial cards.
+config SERIAL_8250_RUNTIME_UARTS
+ int "Number of 8250/16550 serial ports to register at runtime"
+ depends on SERIAL_8250
+ default "4"
+ help
+ Set this to the maximum number of serial ports you want
+ the kernel to register at boot time. This can be overriden
+ with the module parameter "nr_uarts", or boot-time parameter
+ 8250.nr_uarts
+
config SERIAL_8250_EXTENDED
bool "Extended 8250/16550 serial driver options"
depends on SERIAL_8250
@@ -180,7 +190,6 @@ config SERIAL_8250_BOCA
To compile this driver as a module, choose M here: the module
will be called 8250_boca.
-
config SERIAL_8250_HUB6
tristate "Support Hub6 cards"
depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
@@ -270,6 +279,40 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
+config SERIAL_AT91
+ bool "AT91RM9200 serial port support"
+ depends on ARM && ARCH_AT91RM9200
+ select SERIAL_CORE
+ help
+ This enables the driver for the on-chip UARTs of the AT91RM9200
+ processor.
+
+config SERIAL_AT91_CONSOLE
+ bool "Support for console on AT91RM9200 serial port"
+ depends on SERIAL_AT91=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Say Y here if you wish to use a UART on the AT91RM9200 as the system
+ console (the system console is the device which receives all kernel
+ messages and warnings and which allows logins in single user mode).
+
+config SERIAL_AT91_TTYAT
+ bool "Install as device ttyAT0-4 instead of ttyS0-4"
+ depends on SERIAL_AT91=y
+ help
+ Say Y here if you wish to have the five internal AT91RM9200 UARTs
+ appear as /dev/ttyAT0-4 (major 204, minor 154-158) instead of the
+ normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if
+ you also want other UARTs, such as external 8250/16C550 compatible
+ UARTs.
+ The ttySn nodes are legally reserved for the 8250 serial driver
+ but are often misused by other serial drivers.
+
+ To use this, you should create suitable ttyATn device nodes in
+ /dev/, and pass "console=ttyATn" to the kernel.
+
+ Say Y if you have an external 8250/16C550 UART. If unsure, say N.
+
config SERIAL_CLPS711X
tristate "CLPS711X serial port support"
depends on ARM && ARCH_CLPS711X
@@ -359,29 +402,6 @@ config SERIAL_21285_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.)
-config SERIAL_UART00
- bool "Excalibur serial port (uart00) support"
- depends on ARM && ARCH_CAMELOT
- select SERIAL_CORE
- help
- Say Y here if you want to use the hard logic uart on Excalibur. This
- driver also supports soft logic implementations of this uart core.
-
-config SERIAL_UART00_CONSOLE
- bool "Support for console on Excalibur serial port"
- depends on SERIAL_UART00
- select SERIAL_CORE_CONSOLE
- help
- Say Y here if you want to support a serial console on an Excalibur
- hard logic uart or uart00 IP core.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (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.)
-
config SERIAL_MPSC
bool "Marvell MPSC serial port support"
depends on PPC32 && MV64X60
@@ -827,7 +847,7 @@ config SERIAL_M32R_SIO_CONSOLE
config SERIAL_M32R_PLDSIO
bool "M32R SIO I/F on a PLD"
- depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PALT_USRV || PLAT_M32700UT)
+ depends on SERIAL_M32R_SIO=y && (PLAT_OPSPUT || PLAT_USRV || PLAT_M32700UT)
default n
help
Say Y here if you want to use the M32R serial controller
@@ -873,7 +893,7 @@ config SERIAL_VR41XX_CONSOLE
config SERIAL_JSM
tristate "Digi International NEO PCI Support"
- depends on PCI
+ depends on PCI && BROKEN
select SERIAL_CORE
help
This is a driver for Digi International's Neo series
@@ -896,4 +916,12 @@ config SERIAL_SGI_IOC4
and wish to use the serial ports on this card, say Y.
Otherwise, say N.
+config SERIAL_SGI_IOC3
+ tristate "SGI Altix IOC3 serial support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC3
+ select SERIAL_CORE
+ help
+ If you have an SGI Altix with an IOC3 serial card,
+ say Y or M. Otherwise, say N.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index d7c7c7180e33..eaf8e01db198 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
obj-$(CONFIG_SERIAL_PXA) += pxa.o
obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
-obj-$(CONFIG_SERIAL_UART00) += uart00.o
obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
@@ -57,3 +56,5 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
+obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
+obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index ddd0307fece2..3490022e9fdc 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -47,12 +47,12 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/amba_serial.h>
#define UART_NR 2
@@ -154,15 +154,6 @@ pl010_rx_chars(struct uart_port *port)
status = UART_GET_FR(port);
while (UART_RX_DATA(status) && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts.
- */
- }
-
ch = UART_GET_CHAR(port);
flag = TTY_NORMAL;
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index d84476ee6592..034a029e356e 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -47,12 +47,12 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
-#include <asm/hardware/amba_serial.h>
#define UART_NR 14
@@ -120,15 +120,6 @@ pl011_rx_chars(struct uart_amba_port *uap)
status = readw(uap->port.membase + UART01x_FR);
while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
flag = TTY_NORMAL;
uap->port.icount.rx++;
@@ -761,10 +752,6 @@ static int pl011_probe(struct amba_device *dev, void *id)
goto unmap;
}
- ret = clk_use(uap->clk);
- if (ret)
- goto putclk;
-
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
@@ -782,8 +769,6 @@ static int pl011_probe(struct amba_device *dev, void *id)
if (ret) {
amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL;
- clk_unuse(uap->clk);
- putclk:
clk_put(uap->clk);
unmap:
iounmap(base);
@@ -808,7 +793,6 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL;
iounmap(uap->port.membase);
- clk_unuse(uap->clk);
clk_put(uap->clk);
kfree(uap);
return 0;
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
new file mode 100644
index 000000000000..2113feb75c39
--- /dev/null
+++ b/drivers/serial/at91_serial.c
@@ -0,0 +1,892 @@
+/*
+ * linux/drivers/char/at91_serial.c
+ *
+ * Driver for Atmel AT91RM9200 Serial ports
+ *
+ * Copyright (C) 2003 Rick Bronson
+ *
+ * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/tty_flip.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/at91rm9200_usart.h>
+#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/board.h>
+#include <asm/arch/pio.h>
+
+
+#if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#ifdef CONFIG_SERIAL_AT91_TTYAT
+
+/* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we
+ * should coexist with the 8250 driver, such as if we have an external 16C550
+ * UART. */
+#define SERIAL_AT91_MAJOR 204
+#define MINOR_START 154
+#define AT91_DEVICENAME "ttyAT"
+
+#else
+
+/* Use device name ttyS, major 4, minor 64-68. This is the usual serial port
+ * name, but it is legally reserved for the 8250 driver. */
+#define SERIAL_AT91_MAJOR TTY_MAJOR
+#define MINOR_START 64
+#define AT91_DEVICENAME "ttyS"
+
+#endif
+
+#define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU)
+#define AT91_ISR_PASS_LIMIT 256
+
+#define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR)
+#define UART_GET_MR(port) readl((port)->membase + AT91_US_MR)
+#define UART_PUT_MR(port,v) writel(v, (port)->membase + AT91_US_MR)
+#define UART_PUT_IER(port,v) writel(v, (port)->membase + AT91_US_IER)
+#define UART_PUT_IDR(port,v) writel(v, (port)->membase + AT91_US_IDR)
+#define UART_GET_IMR(port) readl((port)->membase + AT91_US_IMR)
+#define UART_GET_CSR(port) readl((port)->membase + AT91_US_CSR)
+#define UART_GET_CHAR(port) readl((port)->membase + AT91_US_RHR)
+#define UART_PUT_CHAR(port,v) writel(v, (port)->membase + AT91_US_THR)
+#define UART_GET_BRGR(port) readl((port)->membase + AT91_US_BRGR)
+#define UART_PUT_BRGR(port,v) writel(v, (port)->membase + AT91_US_BRGR)
+#define UART_PUT_RTOR(port,v) writel(v, (port)->membase + AT91_US_RTOR)
+
+// #define UART_GET_CR(port) readl((port)->membase + AT91_US_CR) // is write-only
+
+ /* PDC registers */
+#define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR)
+#define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR)
+#define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR)
+#define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR)
+#define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR)
+#define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR)
+
+
+static int (*at91_open)(struct uart_port *);
+static void (*at91_close)(struct uart_port *);
+
+#ifdef SUPPORT_SYSRQ
+static struct console at91_console;
+#endif
+
+/*
+ * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty.
+ */
+static u_int at91_tx_empty(struct uart_port *port)
+{
+ return (UART_GET_CSR(port) & AT91_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+}
+
+/*
+ * Set state of the modem control output lines
+ */
+static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ unsigned int control = 0;
+
+ /*
+ * Errata #39: RTS0 is not internally connected to PA21. We need to drive
+ * the pin manually.
+ */
+ if (port->mapbase == AT91_VA_BASE_US0) {
+ if (mctrl & TIOCM_RTS)
+ at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
+ else
+ at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+ }
+
+ if (mctrl & TIOCM_RTS)
+ control |= AT91_US_RTSEN;
+ else
+ control |= AT91_US_RTSDIS;
+
+ if (mctrl & TIOCM_DTR)
+ control |= AT91_US_DTREN;
+ else
+ control |= AT91_US_DTRDIS;
+
+ UART_PUT_CR(port,control);
+}
+
+/*
+ * Get state of the modem control input lines
+ */
+static u_int at91_get_mctrl(struct uart_port *port)
+{
+ unsigned int status, ret = 0;
+
+ status = UART_GET_CSR(port);
+
+ /*
+ * The control signals are active low.
+ */
+ if (!(status & AT91_US_DCD))
+ ret |= TIOCM_CD;
+ if (!(status & AT91_US_CTS))
+ ret |= TIOCM_CTS;
+ if (!(status & AT91_US_DSR))
+ ret |= TIOCM_DSR;
+ if (!(status & AT91_US_RI))
+ ret |= TIOCM_RI;
+
+ return ret;
+}
+
+/*
+ * Stop transmitting.
+ */
+static void at91_stop_tx(struct uart_port *port)
+{
+ UART_PUT_IDR(port, AT91_US_TXRDY);
+ port->read_status_mask &= ~AT91_US_TXRDY;
+}
+
+/*
+ * Start transmitting.
+ */
+static void at91_start_tx(struct uart_port *port)
+{
+ port->read_status_mask |= AT91_US_TXRDY;
+ UART_PUT_IER(port, AT91_US_TXRDY);
+}
+
+/*
+ * Stop receiving - port is in process of being closed.
+ */
+static void at91_stop_rx(struct uart_port *port)
+{
+ UART_PUT_IDR(port, AT91_US_RXRDY);
+}
+
+/*
+ * Enable modem status interrupts
+ */
+static void at91_enable_ms(struct uart_port *port)
+{
+ port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
+ UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
+}
+
+/*
+ * Control the transmission of a break signal
+ */
+static void at91_break_ctl(struct uart_port *port, int break_state)
+{
+ if (break_state != 0)
+ UART_PUT_CR(port, AT91_US_STTBRK); /* start break */
+ else
+ UART_PUT_CR(port, AT91_US_STPBRK); /* stop break */
+}
+
+/*
+ * Characters received (called from interrupt handler)
+ */
+static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs)
+{
+ struct tty_struct *tty = port->info->tty;
+ unsigned int status, ch, flg;
+
+ status = UART_GET_CSR(port) & port->read_status_mask;
+ while (status & (AT91_US_RXRDY)) {
+ ch = UART_GET_CHAR(port);
+
+ port->icount.rx++;
+
+ flg = TTY_NORMAL;
+
+ /*
+ * note that the error handling code is
+ * out of the main execution path
+ */
+ if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) {
+ UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */
+ if (status & (AT91_US_PARE))
+ port->icount.parity++;
+ if (status & (AT91_US_FRAME))
+ port->icount.frame++;
+ if (status & (AT91_US_OVRE))
+ port->icount.overrun++;
+
+ if (status & AT91_US_PARE)
+ flg = TTY_PARITY;
+ else if (status & AT91_US_FRAME)
+ flg = TTY_FRAME;
+ if (status & AT91_US_OVRE) {
+ /*
+ * overrun does *not* affect the character
+ * we read from the FIFO
+ */
+ tty_insert_flip_char(tty, ch, flg);
+ ch = 0;
+ flg = TTY_OVERRUN;
+ }
+#ifdef SUPPORT_SYSRQ
+ port->sysrq = 0;
+#endif
+ }
+
+ if (uart_handle_sysrq_char(port, ch, regs))
+ goto ignore_char;
+
+ tty_insert_flip_char(tty, ch, flg);
+
+ ignore_char:
+ status = UART_GET_CSR(port) & port->read_status_mask;
+ }
+
+ tty_flip_buffer_push(tty);
+}
+
+/*
+ * Transmit characters (called from interrupt handler)
+ */
+static void at91_tx_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->info->xmit;
+
+ if (port->x_char) {
+ UART_PUT_CHAR(port, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ at91_stop_tx(port);
+ return;
+ }
+
+ while (UART_GET_CSR(port) & AT91_US_TXRDY) {
+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ at91_stop_tx(port);
+}
+
+/*
+ * Interrupt handler
+ */
+static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct uart_port *port = dev_id;
+ unsigned int status, pending, pass_counter = 0;
+
+ status = UART_GET_CSR(port);
+ pending = status & port->read_status_mask;
+ if (pending) {
+ do {
+ if (pending & AT91_US_RXRDY)
+ at91_rx_chars(port, regs);
+
+ /* Clear the relevent break bits */
+ if (pending & AT91_US_RXBRK) {
+ UART_PUT_CR(port, AT91_US_RSTSTA);
+ port->icount.brk++;
+ uart_handle_break(port);
+ }
+
+ // TODO: All reads to CSR will clear these interrupts!
+ if (pending & AT91_US_RIIC) port->icount.rng++;
+ if (pending & AT91_US_DSRIC) port->icount.dsr++;
+ if (pending & AT91_US_DCDIC)
+ uart_handle_dcd_change(port, !(status & AT91_US_DCD));
+ if (pending & AT91_US_CTSIC)
+ uart_handle_cts_change(port, !(status & AT91_US_CTS));
+ if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
+ wake_up_interruptible(&port->info->delta_msr_wait);
+
+ if (pending & AT91_US_TXRDY)
+ at91_tx_chars(port);
+ if (pass_counter++ > AT91_ISR_PASS_LIMIT)
+ break;
+
+ status = UART_GET_CSR(port);
+ pending = status & port->read_status_mask;
+ } while (pending);
+ }
+ return IRQ_HANDLED;
+}
+
+/*
+ * Perform initialization and enable port for reception
+ */
+static int at91_startup(struct uart_port *port)
+{
+ int retval;
+
+ /*
+ * Ensure that no interrupts are enabled otherwise when
+ * request_irq() is called we could get stuck trying to
+ * handle an unexpected interrupt
+ */
+ UART_PUT_IDR(port, -1);
+
+ /*
+ * Allocate the IRQ
+ */
+ retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port);
+ if (retval) {
+ printk("at91_serial: at91_startup - Can't get irq\n");
+ return retval;
+ }
+
+ /*
+ * If there is a specific "open" function (to register
+ * control line interrupts)
+ */
+ if (at91_open) {
+ retval = at91_open(port);
+ if (retval) {
+ free_irq(port->irq, port);
+ return retval;
+ }
+ }
+
+ port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE
+ | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK;
+ /*
+ * Finally, enable the serial port
+ */
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */
+ UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */
+ return 0;
+}
+
+/*
+ * Disable the port
+ */
+static void at91_shutdown(struct uart_port *port)
+{
+ /*
+ * Disable all interrupts, port and break condition.
+ */
+ UART_PUT_CR(port, AT91_US_RSTSTA);
+ UART_PUT_IDR(port, -1);
+
+ /*
+ * Free the interrupt
+ */
+ free_irq(port->irq, port);
+
+ /*
+ * If there is a specific "close" function (to unregister
+ * control line interrupts)
+ */
+ if (at91_close)
+ at91_close(port);
+}
+
+/*
+ * Power / Clock management.
+ */
+static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+ switch (state) {
+ case 0:
+ /*
+ * Enable the peripheral clock for this serial port.
+ * This is called on uart_open() or a resume event.
+ */
+ at91_sys_write(AT91_PMC_PCER, 1 << port->irq);
+ break;
+ case 3:
+ /*
+ * Disable the peripheral clock for this serial port.
+ * This is called on uart_close() or a suspend event.
+ */
+ if (port->irq != AT91_ID_SYS) /* is this a shared clock? */
+ at91_sys_write(AT91_PMC_PCDR, 1 << port->irq);
+ break;
+ default:
+ printk(KERN_ERR "at91_serial: unknown pm %d\n", state);
+ }
+}
+
+/*
+ * Change the port parameters
+ */
+static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old)
+{
+ unsigned long flags;
+ unsigned int mode, imr, quot, baud;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ /* Get current mode register */
+ mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR);
+
+ /* byte size */
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ mode |= AT91_US_CHRL_5;
+ break;
+ case CS6:
+ mode |= AT91_US_CHRL_6;
+ break;
+ case CS7:
+ mode |= AT91_US_CHRL_7;
+ break;
+ default:
+ mode |= AT91_US_CHRL_8;
+ break;
+ }
+
+ /* stop bits */
+ if (termios->c_cflag & CSTOPB)
+ mode |= AT91_US_NBSTOP_2;
+
+ /* parity */
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */
+ if (termios->c_cflag & PARODD)
+ mode |= AT91_US_PAR_MARK;
+ else
+ mode |= AT91_US_PAR_SPACE;
+ }
+ else if (termios->c_cflag & PARODD)
+ mode |= AT91_US_PAR_ODD;
+ else
+ mode |= AT91_US_PAR_EVEN;
+ }
+ else
+ mode |= AT91_US_PAR_NONE;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->read_status_mask |= AT91_US_OVRE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= AT91_US_RXBRK;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE);
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= AT91_US_RXBRK;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= AT91_US_OVRE;
+ }
+
+ // TODO: Ignore all characters if CREAD is set.
+
+ /* update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ /* disable interrupts and drain transmitter */
+ imr = UART_GET_IMR(port); /* get interrupt mask */
+ UART_PUT_IDR(port, -1); /* disable all interrupts */
+ while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); }
+
+ /* disable receiver and transmitter */
+ UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS);
+
+ /* set the parity, stop bits and data size */
+ UART_PUT_MR(port, mode);
+
+ /* set the baud rate */
+ UART_PUT_BRGR(port, quot);
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
+
+ /* restore interrupts */
+ UART_PUT_IER(port, imr);
+
+ /* CTS flow-control and modem-status interrupts */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+ port->ops->enable_ms(port);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * Return string describing the specified port
+ */
+static const char *at91_type(struct uart_port *port)
+{
+ return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'.
+ */
+static void at91_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase,
+ (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'.
+ */
+static int at91_request_port(struct uart_port *port)
+{
+ return request_mem_region(port->mapbase,
+ (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K,
+ "at91_serial") != NULL ? 0 : -EBUSY;
+
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void at91_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_AT91RM9200;
+ at91_request_port(port);
+ }
+}
+
+/*
+ * Verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ int ret = 0;
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
+ ret = -EINVAL;
+ if (port->irq != ser->irq)
+ ret = -EINVAL;
+ if (ser->io_type != SERIAL_IO_MEM)
+ ret = -EINVAL;
+ if (port->uartclk / 16 != ser->baud_base)
+ ret = -EINVAL;
+ if ((void *)port->mapbase != ser->iomem_base)
+ ret = -EINVAL;
+ if (port->iobase != ser->port)
+ ret = -EINVAL;
+ if (ser->hub6 != 0)
+ ret = -EINVAL;
+ return ret;
+}
+
+static struct uart_ops at91_pops = {
+ .tx_empty = at91_tx_empty,
+ .set_mctrl = at91_set_mctrl,
+ .get_mctrl = at91_get_mctrl,
+ .stop_tx = at91_stop_tx,
+ .start_tx = at91_start_tx,
+ .stop_rx = at91_stop_rx,
+ .enable_ms = at91_enable_ms,
+ .break_ctl = at91_break_ctl,
+ .startup = at91_startup,
+ .shutdown = at91_shutdown,
+ .set_termios = at91_set_termios,
+ .type = at91_type,
+ .release_port = at91_release_port,
+ .request_port = at91_request_port,
+ .config_port = at91_config_port,
+ .verify_port = at91_verify_port,
+ .pm = at91_serial_pm,
+};
+
+static struct uart_port at91_ports[AT91_NR_UART];
+
+void __init at91_init_ports(void)
+{
+ static int first = 1;
+ int i;
+
+ if (!first)
+ return;
+ first = 0;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ at91_ports[i].iotype = UPIO_MEM;
+ at91_ports[i].flags = UPF_BOOT_AUTOCONF;
+ at91_ports[i].uartclk = at91_master_clock;
+ at91_ports[i].ops = &at91_pops;
+ at91_ports[i].fifosize = 1;
+ at91_ports[i].line = i;
+ }
+}
+
+void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
+{
+ if (fns->enable_ms)
+ at91_pops.enable_ms = fns->enable_ms;
+ if (fns->get_mctrl)
+ at91_pops.get_mctrl = fns->get_mctrl;
+ if (fns->set_mctrl)
+ at91_pops.set_mctrl = fns->set_mctrl;
+ at91_open = fns->open;
+ at91_close = fns->close;
+ at91_pops.pm = fns->pm;
+ at91_pops.set_wake = fns->set_wake;
+}
+
+/*
+ * Setup ports.
+ */
+void __init at91_register_uart(int idx, int port)
+{
+ if ((idx < 0) || (idx >= AT91_NR_UART)) {
+ printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
+ return;
+ }
+
+ switch (port) {
+ case 0:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US0;
+ at91_ports[idx].irq = AT91_ID_US0;
+ AT91_CfgPIO_USART0();
+ break;
+ case 1:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US1;
+ at91_ports[idx].irq = AT91_ID_US1;
+ AT91_CfgPIO_USART1();
+ break;
+ case 2:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US2;
+ at91_ports[idx].irq = AT91_ID_US2;
+ AT91_CfgPIO_USART2();
+ break;
+ case 3:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3;
+ at91_ports[idx].mapbase = AT91_VA_BASE_US3;
+ at91_ports[idx].irq = AT91_ID_US3;
+ AT91_CfgPIO_USART3();
+ break;
+ case 4:
+ at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU;
+ at91_ports[idx].mapbase = AT91_VA_BASE_DBGU;
+ at91_ports[idx].irq = AT91_ID_SYS;
+ AT91_CfgPIO_DBGU();
+ break;
+ default:
+ printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port);
+ }
+}
+
+#ifdef CONFIG_SERIAL_AT91_CONSOLE
+
+/*
+ * Interrupts are disabled on entering
+ */
+static void at91_console_write(struct console *co, const char *s, u_int count)
+{
+ struct uart_port *port = at91_ports + co->index;
+ unsigned int status, i, imr;
+
+ /*
+ * First, save IMR and then disable interrupts
+ */
+ imr = UART_GET_IMR(port); /* get interrupt mask */
+ UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY);
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++) {
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_CHAR(port, s[i]);
+ if (s[i] == '\n') {
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_CHAR(port, '\r');
+ }
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore IMR
+ */
+ do {
+ status = UART_GET_CSR(port);
+ } while (!(status & AT91_US_TXRDY));
+ UART_PUT_IER(port, imr); /* set interrupts back the way they were */
+}
+
+/*
+ * If the port was already initialised (eg, by a boot loader), try to determine
+ * the current setup.
+ */
+static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
+{
+ unsigned int mr, quot;
+
+// TODO: CR is a write-only register
+// unsigned int cr;
+//
+// cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN);
+// if (cr == (AT91_US_RXEN | AT91_US_TXEN)) {
+// /* ok, the port was enabled */
+// }
+
+ mr = UART_GET_MR(port) & AT91_US_CHRL;
+ if (mr == AT91_US_CHRL_8)
+ *bits = 8;
+ else
+ *bits = 7;
+
+ mr = UART_GET_MR(port) & AT91_US_PAR;
+ if (mr == AT91_US_PAR_EVEN)
+ *parity = 'e';
+ else if (mr == AT91_US_PAR_ODD)
+ *parity = 'o';
+
+ quot = UART_GET_BRGR(port);
+ *baud = port->uartclk / (16 * (quot));
+}
+
+static int __init at91_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ port = uart_get_console(at91_ports, AT91_NR_UART, co);
+
+ /*
+ * Enable the serial console, in-case bootloader did not do it.
+ */
+ at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */
+ UART_PUT_IDR(port, -1); /* disable interrupts */
+ UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
+ UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ at91_console_get_options(port, &baud, &parity, &bits);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver at91_uart;
+
+static struct console at91_console = {
+ .name = AT91_DEVICENAME,
+ .write = at91_console_write,
+ .device = uart_console_device,
+ .setup = at91_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &at91_uart,
+};
+
+#define AT91_CONSOLE_DEVICE &at91_console
+
+static int __init at91_console_init(void)
+{
+ at91_init_ports();
+
+ at91_console.index = at91_console_port;
+ register_console(&at91_console);
+ return 0;
+}
+console_initcall(at91_console_init);
+
+#else
+#define AT91_CONSOLE_DEVICE NULL
+#endif
+
+static struct uart_driver at91_uart = {
+ .owner = THIS_MODULE,
+ .driver_name = AT91_DEVICENAME,
+ .dev_name = AT91_DEVICENAME,
+ .devfs_name = AT91_DEVICENAME,
+ .major = SERIAL_AT91_MAJOR,
+ .minor = MINOR_START,
+ .nr = AT91_NR_UART,
+ .cons = AT91_CONSOLE_DEVICE,
+};
+
+static int __init at91_serial_init(void)
+{
+ int ret, i;
+
+ at91_init_ports();
+
+ ret = uart_register_driver(&at91_uart);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (at91_serial_map[i] >= 0)
+ uart_add_one_port(&at91_uart, &at91_ports[i]);
+ }
+
+ return 0;
+}
+
+static void __exit at91_serial_exit(void)
+{
+ int i;
+
+ for (i = 0; i < AT91_NR_UART; i++) {
+ if (at91_serial_map[i] >= 0)
+ uart_remove_one_port(&at91_uart, &at91_ports[i]);
+ }
+
+ uart_unregister_driver(&at91_uart);
+}
+
+module_init(at91_serial_init);
+module_exit(at91_serial_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("AT91 generic serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index a274ebf256a1..ceb5d7f37bbd 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -241,18 +241,12 @@ static _INLINE_ void
receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; // if TTY_DONT_FLIP is set
- }
ch = serial_inp(up, UART_RX);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -292,30 +286,23 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
#endif
if (*status & UART_LSR_BI) {
DEBUG_INTR("handling break....");
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (*status & UART_LSR_OE)
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
*status = serial_inp(up, UART_LSR);
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 87ef368384fb..8ef999481f93 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -104,8 +104,6 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
while (!(status & SYSFLG_URXFE)) {
ch = clps_readl(UARTDR(port));
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
port->icount.rx++;
flg = TTY_NORMAL;
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 987d22b53c22..16af5626c243 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -608,7 +608,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
p = cpm2cpu_addr(bdp->cbd_bufaddr);
- *p++ = xmit->buf[xmit->tail];
+ *p++ = port->x_char;
bdp->cbd_datlen = 1;
bdp->cbd_sc |= BD_SC_READY;
/* Get next BD. */
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 08c42c000188..be12623d8544 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -442,6 +442,7 @@ static char *serial_version = "$Revision: 1.25 $";
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -1315,11 +1316,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] =
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf;
-#ifdef DECLARE_MUTEX
-static DECLARE_MUTEX(tmp_buf_sem);
-#else
-static struct semaphore tmp_buf_sem = MUTEX;
-#endif
+static DEFINE_MUTEX(tmp_buf_mutex);
/* Calculate the chartime depending on baudrate, numbor of bits etc. */
static void update_char_time(struct e100_serial * info)
@@ -3661,7 +3658,7 @@ rs_raw_write(struct tty_struct * tty, int from_user,
* design.
*/
if (from_user) {
- down(&tmp_buf_sem);
+ mutex_lock(&tmp_buf_mutex);
while (1) {
int c1;
c = CIRC_SPACE_TO_END(info->xmit.head,
@@ -3692,7 +3689,7 @@ rs_raw_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
- up(&tmp_buf_sem);
+ mutex_unlock(&tmp_buf_mutex);
} else {
cli();
while (count) {
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index 4d8516d1bb71..a64ba26a94e8 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -216,8 +216,6 @@ static inline void dz_receive_chars(struct dz_port *dport)
if (!tty)
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
icount->rx++;
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c
index eb31125c6a30..144a7a352b28 100644
--- a/drivers/serial/icom.c
+++ b/drivers/serial/icom.c
@@ -729,19 +729,20 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
unsigned short int status;
struct uart_icount *icount;
unsigned long offset;
+ unsigned char flag;
trace(icom_port, "RCV_COMPLETE", 0);
rcv_buff = icom_port->next_rcv;
status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
while (status & SA_FL_RCV_DONE) {
+ int first = -1;
trace(icom_port, "FID_STATUS", status);
count = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].leLength);
+ count = tty_buffer_request_room(tty, count);
trace(icom_port, "RCV_COUNT", count);
- if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
trace(icom_port, "REAL_COUNT", count);
@@ -749,15 +750,10 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
cpu_to_le32(icom_port->statStg->rcv[rcv_buff].leBuffer) -
icom_port->recv_buf_pci;
- memcpy(tty->flip.char_buf_ptr,(unsigned char *)
- ((unsigned long)icom_port->recv_buf + offset), count);
-
+ /* Block copy all but the last byte as this may have status */
if (count > 0) {
- tty->flip.count += count - 1;
- tty->flip.char_buf_ptr += count - 1;
-
- memset(tty->flip.flag_buf_ptr, 0, count);
- tty->flip.flag_buf_ptr += count - 1;
+ first = icom_port->recv_buf[offset];
+ tty_insert_flip_string(tty, icom_port->recv_buf + offset, count - 1);
}
icount = &icom_port->uart_port.icount;
@@ -765,12 +761,14 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
/* Break detect logic */
if ((status & SA_FLAGS_FRAME_ERROR)
- && (tty->flip.char_buf_ptr[0] == 0x00)) {
+ && first == 0) {
status &= ~SA_FLAGS_FRAME_ERROR;
status |= SA_FLAGS_BREAK_DET;
trace(icom_port, "BREAK_DET", 0);
}
+ flag = TTY_NORMAL;
+
if (status &
(SA_FLAGS_BREAK_DET | SA_FLAGS_PARITY_ERROR |
SA_FLAGS_FRAME_ERROR | SA_FLAGS_OVERRUN)) {
@@ -797,33 +795,26 @@ static void recv_interrupt(u16 port_int_reg, struct icom_port *icom_port)
status &= icom_port->read_status_mask;
if (status & SA_FLAGS_BREAK_DET) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (status & SA_FLAGS_PARITY_ERROR) {
trace(icom_port, "PARITY_ERROR", 0);
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (status & SA_FLAGS_FRAME_ERROR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
-
- if (status & SA_FLAGS_OVERRUN) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
- }
+ flag = TTY_FRAME;
+
}
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- ignore_char:
- icom_port->statStg->rcv[rcv_buff].flags = 0;
+ tty_insert_flip_char(tty, *(icom_port->recv_buf + offset + count - 1), flag);
+
+ if (status & SA_FLAGS_OVERRUN)
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ignore_char:
+ icom_port->statStg->rcv[rcv_buff].flags = 0;
icom_port->statStg->rcv[rcv_buff].leLength = 0;
icom_port->statStg->rcv[rcv_buff].WorkingLength =
(unsigned short int) cpu_to_le16(RCV_BUFF_SZ);
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index 83c4c1216587..587cc6a95114 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -256,9 +256,6 @@ static irqreturn_t imx_rxint(int irq, void *dev_id, struct pt_regs *regs)
error_return:
tty_insert_flip_char(tty, rx, flg);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto out;
-
ignore_char:
rx = URXD0((u32)sport->port.membase);
} while(rx & URXD_CHARRDY);
@@ -502,7 +499,7 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
ucr2 |= UCR2_STPB;
if (termios->c_cflag & PARENB) {
ucr2 |= UCR2_PREN;
- if (!(termios->c_cflag & PARODD))
+ if (termios->c_cflag & PARODD)
ucr2 |= UCR2_PROE;
}
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c
new file mode 100644
index 000000000000..8097cd91f16b
--- /dev/null
+++ b/drivers/serial/ioc3_serial.c
@@ -0,0 +1,2197 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file contains a module version of the ioc3 serial driver. This
+ * includes all the support functions needed (support functions, etc.)
+ * and the serial driver itself.
+ */
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/circ_buf.h>
+#include <linux/serial_reg.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/serial_core.h>
+#include <linux/ioc3.h>
+
+/*
+ * Interesting things about the ioc3
+ */
+
+#define LOGICAL_PORTS 2 /* rs232(0) and rs422(1) */
+#define PORTS_PER_CARD 2
+#define LOGICAL_PORTS_PER_CARD (PORTS_PER_CARD * LOGICAL_PORTS)
+#define MAX_CARDS 8
+#define MAX_LOGICAL_PORTS (LOGICAL_PORTS_PER_CARD * MAX_CARDS)
+
+/* determine given the sio_ir what port it applies to */
+#define GET_PORT_FROM_SIO_IR(_x) (_x & SIO_IR_SA) ? 0 : 1
+
+
+/*
+ * we have 2 logical ports (rs232, rs422) for each physical port
+ * evens are rs232, odds are rs422
+ */
+#define GET_PHYSICAL_PORT(_x) ((_x) >> 1)
+#define GET_LOGICAL_PORT(_x) ((_x) & 1)
+#define IS_PHYSICAL_PORT(_x) !((_x) & 1)
+#define IS_RS232(_x) !((_x) & 1)
+
+static unsigned int Num_of_ioc3_cards;
+static unsigned int Submodule_slot;
+
+/* defining this will get you LOTS of great debug info */
+//#define DEBUG_INTERRUPTS
+#define DPRINT_CONFIG(_x...) ;
+//#define DPRINT_CONFIG(_x...) printk _x
+#define NOT_PROGRESS() ;
+//#define NOT_PROGRESS() printk("%s : fails %d\n", __FUNCTION__, __LINE__)
+
+/* number of characters we want to transmit to the lower level at a time */
+#define MAX_CHARS 256
+#define FIFO_SIZE (MAX_CHARS-1) /* it's a uchar */
+
+/* Device name we're using */
+#define DEVICE_NAME "ttySIOC"
+#define DEVICE_MAJOR 204
+#define DEVICE_MINOR 116
+
+/* flags for next_char_state */
+#define NCS_BREAK 0x1
+#define NCS_PARITY 0x2
+#define NCS_FRAMING 0x4
+#define NCS_OVERRUN 0x8
+
+/* cause we need SOME parameters ... */
+#define MIN_BAUD_SUPPORTED 1200
+#define MAX_BAUD_SUPPORTED 115200
+
+/* protocol types supported */
+#define PROTO_RS232 0
+#define PROTO_RS422 1
+
+/* Notification types */
+#define N_DATA_READY 0x01
+#define N_OUTPUT_LOWAT 0x02
+#define N_BREAK 0x04
+#define N_PARITY_ERROR 0x08
+#define N_FRAMING_ERROR 0x10
+#define N_OVERRUN_ERROR 0x20
+#define N_DDCD 0x40
+#define N_DCTS 0x80
+
+#define N_ALL_INPUT (N_DATA_READY | N_BREAK \
+ | N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define N_ALL_OUTPUT N_OUTPUT_LOWAT
+
+#define N_ALL_ERRORS (N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR)
+
+#define N_ALL (N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK \
+ | N_PARITY_ERROR | N_FRAMING_ERROR \
+ | N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define SER_CLK_SPEED(prediv) ((22000000 << 1) / prediv)
+#define SER_DIVISOR(x, clk) (((clk) + (x) * 8) / ((x) * 16))
+#define DIVISOR_TO_BAUD(div, clk) ((clk) / 16 / (div))
+
+/* Some masks */
+#define LCR_MASK_BITS_CHAR (UART_LCR_WLEN5 | UART_LCR_WLEN6 \
+ | UART_LCR_WLEN7 | UART_LCR_WLEN8)
+#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
+
+#define PENDING(_a, _p) (readl(&(_p)->vma->sio_ir) & (_a)->ic_enable)
+
+#define RING_BUF_SIZE 4096
+#define BUF_SIZE_BIT SBBR_L_SIZE
+#define PROD_CONS_MASK PROD_CONS_PTR_4K
+
+#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
+
+/* driver specific - one per card */
+struct ioc3_card {
+ struct {
+ /* uart ports are allocated here */
+ struct uart_port icp_uart_port[LOGICAL_PORTS];
+ /* the ioc3_port used for this port */
+ struct ioc3_port *icp_port;
+ } ic_port[PORTS_PER_CARD];
+ /* currently enabled interrupts */
+ uint32_t ic_enable;
+};
+
+/* Local port info for each IOC3 serial port */
+struct ioc3_port {
+ /* handy reference material */
+ struct uart_port *ip_port;
+ struct ioc3_card *ip_card;
+ struct ioc3_driver_data *ip_idd;
+ struct ioc3_submodule *ip_is;
+
+ /* pci mem addresses for this port */
+ struct ioc3_serialregs __iomem *ip_serial_regs;
+ struct ioc3_uartregs __iomem *ip_uart_regs;
+
+ /* Ring buffer page for this port */
+ dma_addr_t ip_dma_ringbuf;
+ /* vaddr of ring buffer */
+ struct ring_buffer *ip_cpu_ringbuf;
+
+ /* Rings for this port */
+ struct ring *ip_inring;
+ struct ring *ip_outring;
+
+ /* Hook to port specific values */
+ struct port_hooks *ip_hooks;
+
+ spinlock_t ip_lock;
+
+ /* Various rx/tx parameters */
+ int ip_baud;
+ int ip_tx_lowat;
+ int ip_rx_timeout;
+
+ /* Copy of notification bits */
+ int ip_notify;
+
+ /* Shadow copies of various registers so we don't need to PIO
+ * read them constantly
+ */
+ uint32_t ip_sscr;
+ uint32_t ip_tx_prod;
+ uint32_t ip_rx_cons;
+ unsigned char ip_flags;
+};
+
+/* tx low water mark. We need to notify the driver whenever tx is getting
+ * close to empty so it can refill the tx buffer and keep things going.
+ * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
+ * have no trouble getting in more chars in time (I certainly hope so).
+ */
+#define TX_LOWAT_LATENCY 1000
+#define TX_LOWAT_HZ (1000000 / TX_LOWAT_LATENCY)
+#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
+
+/* Flags per port */
+#define INPUT_HIGH 0x01
+ /* used to signify that we have turned off the rx_high
+ * temporarily - we need to drain the fifo and don't
+ * want to get blasted with interrupts.
+ */
+#define DCD_ON 0x02
+ /* DCD state is on */
+#define LOWAT_WRITTEN 0x04
+#define READ_ABORTED 0x08
+ /* the read was aborted - used to avaoid infinate looping
+ * in the interrupt handler
+ */
+#define INPUT_ENABLE 0x10
+
+/* Since each port has different register offsets and bitmasks
+ * for everything, we'll store those that we need in tables so we
+ * don't have to be constantly checking the port we are dealing with.
+ */
+struct port_hooks {
+ uint32_t intr_delta_dcd;
+ uint32_t intr_delta_cts;
+ uint32_t intr_tx_mt;
+ uint32_t intr_rx_timer;
+ uint32_t intr_rx_high;
+ uint32_t intr_tx_explicit;
+ uint32_t intr_clear;
+ uint32_t intr_all;
+ char rs422_select_pin;
+};
+
+static struct port_hooks hooks_array[PORTS_PER_CARD] = {
+ /* values for port A */
+ {
+ .intr_delta_dcd = SIO_IR_SA_DELTA_DCD,
+ .intr_delta_cts = SIO_IR_SA_DELTA_CTS,
+ .intr_tx_mt = SIO_IR_SA_TX_MT,
+ .intr_rx_timer = SIO_IR_SA_RX_TIMER,
+ .intr_rx_high = SIO_IR_SA_RX_HIGH,
+ .intr_tx_explicit = SIO_IR_SA_TX_EXPLICIT,
+ .intr_clear = (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL
+ | SIO_IR_SA_RX_HIGH
+ | SIO_IR_SA_RX_TIMER
+ | SIO_IR_SA_DELTA_DCD
+ | SIO_IR_SA_DELTA_CTS
+ | SIO_IR_SA_INT
+ | SIO_IR_SA_TX_EXPLICIT
+ | SIO_IR_SA_MEMERR),
+ .intr_all = SIO_IR_SA,
+ .rs422_select_pin = GPPR_UARTA_MODESEL_PIN,
+ },
+
+ /* values for port B */
+ {
+ .intr_delta_dcd = SIO_IR_SB_DELTA_DCD,
+ .intr_delta_cts = SIO_IR_SB_DELTA_CTS,
+ .intr_tx_mt = SIO_IR_SB_TX_MT,
+ .intr_rx_timer = SIO_IR_SB_RX_TIMER,
+ .intr_rx_high = SIO_IR_SB_RX_HIGH,
+ .intr_tx_explicit = SIO_IR_SB_TX_EXPLICIT,
+ .intr_clear = (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL
+ | SIO_IR_SB_RX_HIGH
+ | SIO_IR_SB_RX_TIMER
+ | SIO_IR_SB_DELTA_DCD
+ | SIO_IR_SB_DELTA_CTS
+ | SIO_IR_SB_INT
+ | SIO_IR_SB_TX_EXPLICIT
+ | SIO_IR_SB_MEMERR),
+ .intr_all = SIO_IR_SB,
+ .rs422_select_pin = GPPR_UARTB_MODESEL_PIN,
+ }
+};
+
+struct ring_entry {
+ union {
+ struct {
+ uint32_t alldata;
+ uint32_t allsc;
+ } all;
+ struct {
+ char data[4]; /* data bytes */
+ char sc[4]; /* status/control */
+ } s;
+ } u;
+};
+
+/* Test the valid bits in any of the 4 sc chars using "allsc" member */
+#define RING_ANY_VALID \
+ ((uint32_t)(RXSB_MODEM_VALID | RXSB_DATA_VALID) * 0x01010101)
+
+#define ring_sc u.s.sc
+#define ring_data u.s.data
+#define ring_allsc u.all.allsc
+
+/* Number of entries per ring buffer. */
+#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
+
+/* An individual ring */
+struct ring {
+ struct ring_entry entries[ENTRIES_PER_RING];
+};
+
+/* The whole enchilada */
+struct ring_buffer {
+ struct ring TX_A;
+ struct ring RX_A;
+ struct ring TX_B;
+ struct ring RX_B;
+};
+
+/* Get a ring from a port struct */
+#define RING(_p, _wh) &(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
+
+/* for Infinite loop detection */
+#define MAXITER 10000000
+
+
+/**
+ * set_baud - Baud rate setting code
+ * @port: port to set
+ * @baud: baud rate to use
+ */
+static int set_baud(struct ioc3_port *port, int baud)
+{
+ int divisor;
+ int actual_baud;
+ int diff;
+ int lcr, prediv;
+ struct ioc3_uartregs __iomem *uart;
+
+ for (prediv = 6; prediv < 64; prediv++) {
+ divisor = SER_DIVISOR(baud, SER_CLK_SPEED(prediv));
+ if (!divisor)
+ continue; /* invalid divisor */
+ actual_baud = DIVISOR_TO_BAUD(divisor, SER_CLK_SPEED(prediv));
+
+ diff = actual_baud - baud;
+ if (diff < 0)
+ diff = -diff;
+
+ /* if we're within 1% we've found a match */
+ if (diff * 100 <= actual_baud)
+ break;
+ }
+
+ /* if the above loop completed, we didn't match
+ * the baud rate. give up.
+ */
+ if (prediv == 64) {
+ NOT_PROGRESS();
+ return 1;
+ }
+
+ uart = port->ip_uart_regs;
+ lcr = readb(&uart->iu_lcr);
+
+ writeb(lcr | UART_LCR_DLAB, &uart->iu_lcr);
+ writeb((unsigned char)divisor, &uart->iu_dll);
+ writeb((unsigned char)(divisor >> 8), &uart->iu_dlm);
+ writeb((unsigned char)prediv, &uart->iu_scr);
+ writeb((unsigned char)lcr, &uart->iu_lcr);
+
+ return 0;
+}
+
+/**
+ * get_ioc3_port - given a uart port, return the control structure
+ * @the_port: uart port to find
+ */
+static struct ioc3_port *get_ioc3_port(struct uart_port *the_port)
+{
+ struct ioc3_driver_data *idd = dev_get_drvdata(the_port->dev);
+ struct ioc3_card *card_ptr = idd->data[Submodule_slot];
+ int ii, jj;
+
+ if (!card_ptr) {
+ NOT_PROGRESS();
+ return NULL;
+ }
+ for (ii = 0; ii < PORTS_PER_CARD; ii++) {
+ for (jj = 0; jj < LOGICAL_PORTS; jj++) {
+ if (the_port == &card_ptr->ic_port[ii].icp_uart_port[jj])
+ return card_ptr->ic_port[ii].icp_port;
+ }
+ }
+ NOT_PROGRESS();
+ return NULL;
+}
+
+/**
+ * port_init - Initialize the sio and ioc3 hardware for a given port
+ * called per port from attach...
+ * @port: port to initialize
+ */
+static int inline port_init(struct ioc3_port *port)
+{
+ uint32_t sio_cr;
+ struct port_hooks *hooks = port->ip_hooks;
+ struct ioc3_uartregs __iomem *uart;
+ int reset_loop_counter = 0xfffff;
+ struct ioc3_driver_data *idd = port->ip_idd;
+
+ /* Idle the IOC3 serial interface */
+ writel(SSCR_RESET, &port->ip_serial_regs->sscr);
+
+ /* Wait until any pending bus activity for this port has ceased */
+ do {
+ sio_cr = readl(&idd->vma->sio_cr);
+ if (reset_loop_counter-- <= 0) {
+ printk(KERN_WARNING
+ "IOC3 unable to come out of reset"
+ " scr 0x%x\n", sio_cr);
+ return -1;
+ }
+ } while (!(sio_cr & SIO_CR_ARB_DIAG_IDLE) &&
+ (((sio_cr &= SIO_CR_ARB_DIAG) == SIO_CR_ARB_DIAG_TXA)
+ || sio_cr == SIO_CR_ARB_DIAG_TXB
+ || sio_cr == SIO_CR_ARB_DIAG_RXA
+ || sio_cr == SIO_CR_ARB_DIAG_RXB));
+
+ /* Finish reset sequence */
+ writel(0, &port->ip_serial_regs->sscr);
+
+ /* Once RESET is done, reload cached tx_prod and rx_cons values
+ * and set rings to empty by making prod == cons
+ */
+ port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+ writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
+ port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+ writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
+
+ /* Disable interrupts for this 16550 */
+ uart = port->ip_uart_regs;
+ writeb(0, &uart->iu_lcr);
+ writeb(0, &uart->iu_ier);
+
+ /* Set the default baud */
+ set_baud(port, port->ip_baud);
+
+ /* Set line control to 8 bits no parity */
+ writeb(UART_LCR_WLEN8 | 0, &uart->iu_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Enable the FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO, &uart->iu_fcr);
+ /* then reset 16550 FIFOs */
+ writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+ &uart->iu_fcr);
+
+ /* Clear modem control register */
+ writeb(0, &uart->iu_mcr);
+
+ /* Clear deltas in modem status register */
+ writel(0, &port->ip_serial_regs->shadow);
+
+ /* Only do this once per port pair */
+ if (port->ip_hooks == &hooks_array[0]) {
+ unsigned long ring_pci_addr;
+ uint32_t __iomem *sbbr_l, *sbbr_h;
+
+ sbbr_l = &idd->vma->sbbr_l;
+ sbbr_h = &idd->vma->sbbr_h;
+ ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+ DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
+ __FUNCTION__, (void *)ring_pci_addr));
+
+ writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
+ writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
+ }
+
+ /* Set the receive timeout value to 10 msec */
+ writel(SRTR_HZ / 100, &port->ip_serial_regs->srtr);
+
+ /* Set rx threshold, enable DMA */
+ /* Set high water mark at 3/4 of full ring */
+ port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
+
+ /* uart experiences pauses at high baud rate reducing actual
+ * throughput by 10% or so unless we enable high speed polling
+ * XXX when this hardware bug is resolved we should revert to
+ * normal polling speed
+ */
+ port->ip_sscr |= SSCR_HIGH_SPD;
+
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Disable and clear all serial related interrupt bits */
+ port->ip_card->ic_enable &= ~hooks->intr_clear;
+ ioc3_disable(port->ip_is, idd, hooks->intr_clear);
+ ioc3_ack(port->ip_is, idd, hooks->intr_clear);
+ return 0;
+}
+
+/**
+ * enable_intrs - enable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static void enable_intrs(struct ioc3_port *port, uint32_t mask)
+{
+ if ((port->ip_card->ic_enable & mask) != mask) {
+ port->ip_card->ic_enable |= mask;
+ ioc3_enable(port->ip_is, port->ip_idd, mask);
+ }
+}
+
+/**
+ * local_open - local open a port
+ * @port: port to open
+ */
+static inline int local_open(struct ioc3_port *port)
+{
+ int spiniter = 0;
+
+ port->ip_flags = INPUT_ENABLE;
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER) {
+ NOT_PROGRESS();
+ return -1;
+ }
+ }
+ }
+
+ /* Reset the input fifo. If the uart received chars while the port
+ * was closed and DMA is not enabled, the uart may have a bunch of
+ * chars hanging around in its rx fifo which will not be discarded
+ * by rclr in the upper layer. We must get rid of them here.
+ */
+ writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
+ &port->ip_uart_regs->iu_fcr);
+
+ writeb(UART_LCR_WLEN8, &port->ip_uart_regs->iu_lcr);
+ /* UART_LCR_STOP == 1 stop */
+
+ /* Re-enable DMA, set default threshold to intr whenever there is
+ * data available.
+ */
+ port->ip_sscr &= ~SSCR_RX_THRESHOLD;
+ port->ip_sscr |= 1; /* default threshold */
+
+ /* Plug in the new sscr. This implicitly clears the DMA_PAUSE
+ * flag if it was set above
+ */
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ port->ip_tx_lowat = 1;
+ return 0;
+}
+
+/**
+ * set_rx_timeout - Set rx timeout and threshold values.
+ * @port: port to use
+ * @timeout: timeout value in ticks
+ */
+static inline int set_rx_timeout(struct ioc3_port *port, int timeout)
+{
+ int threshold;
+
+ port->ip_rx_timeout = timeout;
+
+ /* Timeout is in ticks. Let's figure out how many chars we
+ * can receive at the current baud rate in that interval
+ * and set the rx threshold to that amount. There are 4 chars
+ * per ring entry, so we'll divide the number of chars that will
+ * arrive in timeout by 4.
+ * So .... timeout * baud / 10 / HZ / 4, with HZ = 100.
+ */
+ threshold = timeout * port->ip_baud / 4000;
+ if (threshold == 0)
+ threshold = 1; /* otherwise we'll intr all the time! */
+
+ if ((unsigned)threshold > (unsigned)SSCR_RX_THRESHOLD)
+ return 1;
+
+ port->ip_sscr &= ~SSCR_RX_THRESHOLD;
+ port->ip_sscr |= threshold;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Now set the rx timeout to the given value
+ * again timeout * SRTR_HZ / HZ
+ */
+ timeout = timeout * SRTR_HZ / 100;
+ if (timeout > SRTR_CNT)
+ timeout = SRTR_CNT;
+ writel(timeout, &port->ip_serial_regs->srtr);
+ return 0;
+}
+
+/**
+ * config_port - config the hardware
+ * @port: port to config
+ * @baud: baud rate for the port
+ * @byte_size: data size
+ * @stop_bits: number of stop bits
+ * @parenb: parity enable ?
+ * @parodd: odd parity ?
+ */
+static inline int
+config_port(struct ioc3_port *port,
+ int baud, int byte_size, int stop_bits, int parenb, int parodd)
+{
+ char lcr, sizebits;
+ int spiniter = 0;
+
+ DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
+ "parodd %d\n",
+ __FUNCTION__, ((struct uart_port *)port->ip_port)->line,
+ baud, byte_size, stop_bits, parenb, parodd));
+
+ if (set_baud(port, baud))
+ return 1;
+
+ switch (byte_size) {
+ case 5:
+ sizebits = UART_LCR_WLEN5;
+ break;
+ case 6:
+ sizebits = UART_LCR_WLEN6;
+ break;
+ case 7:
+ sizebits = UART_LCR_WLEN7;
+ break;
+ case 8:
+ sizebits = UART_LCR_WLEN8;
+ break;
+ default:
+ return 1;
+ }
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+
+ /* Clear relevant fields in lcr */
+ lcr = readb(&port->ip_uart_regs->iu_lcr);
+ lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
+ UART_LCR_PARITY | LCR_MASK_STOP_BITS);
+
+ /* Set byte size in lcr */
+ lcr |= sizebits;
+
+ /* Set parity */
+ if (parenb) {
+ lcr |= UART_LCR_PARITY;
+ if (!parodd)
+ lcr |= UART_LCR_EPAR;
+ }
+
+ /* Set stop bits */
+ if (stop_bits)
+ lcr |= UART_LCR_STOP /* 2 stop bits */ ;
+
+ writeb(lcr, &port->ip_uart_regs->iu_lcr);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ port->ip_baud = baud;
+
+ /* When we get within this number of ring entries of filling the
+ * entire ring on tx, place an EXPLICIT intr to generate a lowat
+ * notification when output has drained.
+ */
+ port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
+ if (port->ip_tx_lowat == 0)
+ port->ip_tx_lowat = 1;
+
+ set_rx_timeout(port, 2);
+ return 0;
+}
+
+/**
+ * do_write - Write bytes to the port. Returns the number of bytes
+ * actually written. Called from transmit_chars
+ * @port: port to use
+ * @buf: the stuff to write
+ * @len: how many bytes in 'buf'
+ */
+static inline int do_write(struct ioc3_port *port, char *buf, int len)
+{
+ int prod_ptr, cons_ptr, total = 0;
+ struct ring *outring;
+ struct ring_entry *entry;
+ struct port_hooks *hooks = port->ip_hooks;
+
+ BUG_ON(!(len >= 0));
+
+ prod_ptr = port->ip_tx_prod;
+ cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+ outring = port->ip_outring;
+
+ /* Maintain a 1-entry red-zone. The ring buffer is full when
+ * (cons - prod) % ring_size is 1. Rather than do this subtraction
+ * in the body of the loop, I'll do it now.
+ */
+ cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
+
+ /* Stuff the bytes into the output */
+ while ((prod_ptr != cons_ptr) && (len > 0)) {
+ int xx;
+
+ /* Get 4 bytes (one ring entry) at a time */
+ entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
+
+ /* Invalidate all entries */
+ entry->ring_allsc = 0;
+
+ /* Copy in some bytes */
+ for (xx = 0; (xx < 4) && (len > 0); xx++) {
+ entry->ring_data[xx] = *buf++;
+ entry->ring_sc[xx] = TXCB_VALID;
+ len--;
+ total++;
+ }
+
+ /* If we are within some small threshold of filling up the
+ * entire ring buffer, we must place an EXPLICIT intr here
+ * to generate a lowat interrupt in case we subsequently
+ * really do fill up the ring and the caller goes to sleep.
+ * No need to place more than one though.
+ */
+ if (!(port->ip_flags & LOWAT_WRITTEN) &&
+ ((cons_ptr - prod_ptr) & PROD_CONS_MASK)
+ <= port->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
+ port->ip_flags |= LOWAT_WRITTEN;
+ entry->ring_sc[0] |= TXCB_INT_WHEN_DONE;
+ }
+
+ /* Go on to next entry */
+ prod_ptr += sizeof(struct ring_entry);
+ prod_ptr &= PROD_CONS_MASK;
+ }
+
+ /* If we sent something, start DMA if necessary */
+ if (total > 0 && !(port->ip_sscr & SSCR_DMA_EN)) {
+ port->ip_sscr |= SSCR_DMA_EN;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+
+ /* Store the new producer pointer. If tx is disabled, we stuff the
+ * data into the ring buffer, but we don't actually start tx.
+ */
+ if (!uart_tx_stopped(port->ip_port)) {
+ writel(prod_ptr, &port->ip_serial_regs->stpir);
+
+ /* If we are now transmitting, enable tx_mt interrupt so we
+ * can disable DMA if necessary when the tx finishes.
+ */
+ if (total > 0)
+ enable_intrs(port, hooks->intr_tx_mt);
+ }
+ port->ip_tx_prod = prod_ptr;
+
+ return total;
+}
+
+/**
+ * disable_intrs - disable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static inline void disable_intrs(struct ioc3_port *port, uint32_t mask)
+{
+ if (port->ip_card->ic_enable & mask) {
+ ioc3_disable(port->ip_is, port->ip_idd, mask);
+ port->ip_card->ic_enable &= ~mask;
+ }
+}
+
+/**
+ * set_notification - Modify event notification
+ * @port: port to use
+ * @mask: events mask
+ * @set_on: set ?
+ */
+static int set_notification(struct ioc3_port *port, int mask, int set_on)
+{
+ struct port_hooks *hooks = port->ip_hooks;
+ uint32_t intrbits, sscrbits;
+
+ BUG_ON(!mask);
+
+ intrbits = sscrbits = 0;
+
+ if (mask & N_DATA_READY)
+ intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
+ if (mask & N_OUTPUT_LOWAT)
+ intrbits |= hooks->intr_tx_explicit;
+ if (mask & N_DDCD) {
+ intrbits |= hooks->intr_delta_dcd;
+ sscrbits |= SSCR_RX_RING_DCD;
+ }
+ if (mask & N_DCTS)
+ intrbits |= hooks->intr_delta_cts;
+
+ if (set_on) {
+ enable_intrs(port, intrbits);
+ port->ip_notify |= mask;
+ port->ip_sscr |= sscrbits;
+ } else {
+ disable_intrs(port, intrbits);
+ port->ip_notify &= ~mask;
+ port->ip_sscr &= ~sscrbits;
+ }
+
+ /* We require DMA if either DATA_READY or DDCD notification is
+ * currently requested. If neither of these is requested and
+ * there is currently no tx in progress, DMA may be disabled.
+ */
+ if (port->ip_notify & (N_DATA_READY | N_DDCD))
+ port->ip_sscr |= SSCR_DMA_EN;
+ else if (!(port->ip_card->ic_enable & hooks->intr_tx_mt))
+ port->ip_sscr &= ~SSCR_DMA_EN;
+
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ return 0;
+}
+
+/**
+ * set_mcr - set the master control reg
+ * @the_port: port to use
+ * @mask1: mcr mask
+ * @mask2: shadow mask
+ */
+static inline int set_mcr(struct uart_port *the_port,
+ int mask1, int mask2)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ uint32_t shadow;
+ int spiniter = 0;
+ char mcr;
+
+ if (!port)
+ return -1;
+
+ /* Pause the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr | SSCR_DMA_PAUSE,
+ &port->ip_serial_regs->sscr);
+ while ((readl(&port->ip_serial_regs->sscr)
+ & SSCR_PAUSE_STATE) == 0) {
+ spiniter++;
+ if (spiniter > MAXITER)
+ return -1;
+ }
+ }
+ shadow = readl(&port->ip_serial_regs->shadow);
+ mcr = (shadow & 0xff000000) >> 24;
+
+ /* Set new value */
+ mcr |= mask1;
+ shadow |= mask2;
+ writeb(mcr, &port->ip_uart_regs->iu_mcr);
+ writel(shadow, &port->ip_serial_regs->shadow);
+
+ /* Re-enable the DMA interface if necessary */
+ if (port->ip_sscr & SSCR_DMA_EN) {
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ return 0;
+}
+
+/**
+ * ioc3_set_proto - set the protocol for the port
+ * @port: port to use
+ * @proto: protocol to use
+ */
+static int ioc3_set_proto(struct ioc3_port *port, int proto)
+{
+ struct port_hooks *hooks = port->ip_hooks;
+
+ switch (proto) {
+ default:
+ case PROTO_RS232:
+ /* Clear the appropriate GIO pin */
+ DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__));
+ writel(0, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+
+ case PROTO_RS422:
+ /* Set the appropriate GIO pin */
+ DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__));
+ writel(1, (&port->ip_idd->vma->gppr[0]
+ + hooks->rs422_select_pin));
+ break;
+ }
+ return 0;
+}
+
+/**
+ * transmit_chars - upper level write, called with the_port->lock
+ * @the_port: port to write
+ */
+static void transmit_chars(struct uart_port *the_port)
+{
+ int xmit_count, tail, head;
+ int result;
+ char *start;
+ struct tty_struct *tty;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ struct uart_info *info;
+
+ if (!the_port)
+ return;
+ if (!port)
+ return;
+
+ info = the_port->info;
+ tty = info->tty;
+
+ if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) {
+ /* Nothing to do or hw stopped */
+ set_notification(port, N_ALL_OUTPUT, 0);
+ return;
+ }
+
+ head = info->xmit.head;
+ tail = info->xmit.tail;
+ start = (char *)&info->xmit.buf[tail];
+
+ /* write out all the data or until the end of the buffer */
+ xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
+ if (xmit_count > 0) {
+ result = do_write(port, start, xmit_count);
+ if (result > 0) {
+ /* booking */
+ xmit_count -= result;
+ the_port->icount.tx += result;
+ /* advance the pointers */
+ tail += result;
+ tail &= UART_XMIT_SIZE - 1;
+ info->xmit.tail = tail;
+ start = (char *)&info->xmit.buf[tail];
+ }
+ }
+ if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(the_port);
+
+ if (uart_circ_empty(&info->xmit)) {
+ set_notification(port, N_OUTPUT_LOWAT, 0);
+ } else {
+ set_notification(port, N_OUTPUT_LOWAT, 1);
+ }
+}
+
+/**
+ * ioc3_change_speed - change the speed of the port
+ * @the_port: port to change
+ * @new_termios: new termios settings
+ * @old_termios: old termios settings
+ */
+static void
+ioc3_change_speed(struct uart_port *the_port,
+ struct termios *new_termios, struct termios *old_termios)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ unsigned int cflag;
+ int baud;
+ int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8;
+ struct uart_info *info = the_port->info;
+
+ cflag = new_termios->c_cflag;
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ new_data = 5;
+ break;
+ case CS6:
+ new_data = 6;
+ break;
+ case CS7:
+ new_data = 7;
+ break;
+ case CS8:
+ new_data = 8;
+ break;
+ default:
+ /* cuz we always need a default ... */
+ new_data = 5;
+ break;
+ }
+ if (cflag & CSTOPB) {
+ new_stop = 1;
+ }
+ if (cflag & PARENB) {
+ new_parity_enable = 1;
+ if (cflag & PARODD)
+ new_parity = 1;
+ }
+ baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+ MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+ DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud,
+ the_port->line));
+
+ if (!the_port->fifosize)
+ the_port->fifosize = FIFO_SIZE;
+ uart_update_timeout(the_port, cflag, baud);
+
+ the_port->ignore_status_mask = N_ALL_INPUT;
+
+ info->tty->low_latency = 1;
+
+ if (I_IGNPAR(info->tty))
+ the_port->ignore_status_mask &= ~(N_PARITY_ERROR
+ | N_FRAMING_ERROR);
+ if (I_IGNBRK(info->tty)) {
+ the_port->ignore_status_mask &= ~N_BREAK;
+ if (I_IGNPAR(info->tty))
+ the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
+ }
+ if (!(cflag & CREAD)) {
+ /* ignore everything */
+ the_port->ignore_status_mask &= ~N_DATA_READY;
+ }
+
+ if (cflag & CRTSCTS) {
+ /* enable hardware flow control */
+ port->ip_sscr |= SSCR_HFC_EN;
+ }
+ else {
+ /* disable hardware flow control */
+ port->ip_sscr &= ~SSCR_HFC_EN;
+ }
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+ /* Set the configuration and proper notification call */
+ DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
+ "config_port(baud %d data %d stop %d penable %d "
+ " parity %d), notification 0x%x\n",
+ __FUNCTION__, (void *)port, the_port->line, cflag, baud,
+ new_data, new_stop, new_parity_enable, new_parity,
+ the_port->ignore_status_mask));
+
+ if ((config_port(port, baud, /* baud */
+ new_data, /* byte size */
+ new_stop, /* stop bits */
+ new_parity_enable, /* set parity */
+ new_parity)) >= 0) { /* parity 1==odd */
+ set_notification(port, the_port->ignore_status_mask, 1);
+ }
+}
+
+/**
+ * ic3_startup_local - Start up the serial port - returns >= 0 if no errors
+ * @the_port: Port to operate on
+ */
+static inline int ic3_startup_local(struct uart_port *the_port)
+{
+ struct ioc3_port *port;
+
+ if (!the_port) {
+ NOT_PROGRESS();
+ return -1;
+ }
+
+ port = get_ioc3_port(the_port);
+ if (!port) {
+ NOT_PROGRESS();
+ return -1;
+ }
+
+ local_open(port);
+
+ /* set the protocol */
+ ioc3_set_proto(port, IS_RS232(the_port->line) ? PROTO_RS232 :
+ PROTO_RS422);
+ return 0;
+}
+
+/*
+ * ioc3_cb_output_lowat - called when the output low water mark is hit
+ * @port: port to output
+ */
+static void ioc3_cb_output_lowat(struct ioc3_port *port)
+{
+ unsigned long pflags;
+
+ /* the_port->lock is set on the call here */
+ if (port->ip_port) {
+ spin_lock_irqsave(&port->ip_port->lock, pflags);
+ transmit_chars(port->ip_port);
+ spin_unlock_irqrestore(&port->ip_port->lock, pflags);
+ }
+}
+
+/*
+ * ioc3_cb_post_ncs - called for some basic errors
+ * @port: port to use
+ * @ncs: event
+ */
+static void ioc3_cb_post_ncs(struct uart_port *the_port, int ncs)
+{
+ struct uart_icount *icount;
+
+ icount = &the_port->icount;
+
+ if (ncs & NCS_BREAK)
+ icount->brk++;
+ if (ncs & NCS_FRAMING)
+ icount->frame++;
+ if (ncs & NCS_OVERRUN)
+ icount->overrun++;
+ if (ncs & NCS_PARITY)
+ icount->parity++;
+}
+
+/**
+ * do_read - Read in bytes from the port. Return the number of bytes
+ * actually read.
+ * @the_port: port to use
+ * @buf: place to put the stuff we read
+ * @len: how big 'buf' is
+ */
+
+static inline int do_read(struct uart_port *the_port, char *buf, int len)
+{
+ int prod_ptr, cons_ptr, total;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ struct ring *inring;
+ struct ring_entry *entry;
+ struct port_hooks *hooks = port->ip_hooks;
+ int byte_num;
+ char *sc;
+ int loop_counter;
+
+ BUG_ON(!(len >= 0));
+ BUG_ON(!port);
+
+ /* There is a nasty timing issue in the IOC3. When the rx_timer
+ * expires or the rx_high condition arises, we take an interrupt.
+ * At some point while servicing the interrupt, we read bytes from
+ * the ring buffer and re-arm the rx_timer. However the rx_timer is
+ * not started until the first byte is received *after* it is armed,
+ * and any bytes pending in the rx construction buffers are not drained
+ * to memory until either there are 4 bytes available or the rx_timer
+ * expires. This leads to a potential situation where data is left
+ * in the construction buffers forever - 1 to 3 bytes were received
+ * after the interrupt was generated but before the rx_timer was
+ * re-armed. At that point as long as no subsequent bytes are received
+ * the timer will never be started and the bytes will remain in the
+ * construction buffer forever. The solution is to execute a DRAIN
+ * command after rearming the timer. This way any bytes received before
+ * the DRAIN will be drained to memory, and any bytes received after
+ * the DRAIN will start the TIMER and be drained when it expires.
+ * Luckily, this only needs to be done when the DMA buffer is empty
+ * since there is no requirement that this function return all
+ * available data as long as it returns some.
+ */
+ /* Re-arm the timer */
+
+ writel(port->ip_rx_cons | SRCIR_ARM, &port->ip_serial_regs->srcir);
+
+ prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+ cons_ptr = port->ip_rx_cons;
+
+ if (prod_ptr == cons_ptr) {
+ int reset_dma = 0;
+
+ /* Input buffer appears empty, do a flush. */
+
+ /* DMA must be enabled for this to work. */
+ if (!(port->ip_sscr & SSCR_DMA_EN)) {
+ port->ip_sscr |= SSCR_DMA_EN;
+ reset_dma = 1;
+ }
+
+ /* Potential race condition: we must reload the srpir after
+ * issuing the drain command, otherwise we could think the rx
+ * buffer is empty, then take a very long interrupt, and when
+ * we come back it's full and we wait forever for the drain to
+ * complete.
+ */
+ writel(port->ip_sscr | SSCR_RX_DRAIN,
+ &port->ip_serial_regs->sscr);
+ prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+
+ /* We must not wait for the DRAIN to complete unless there are
+ * at least 8 bytes (2 ring entries) available to receive the
+ * data otherwise the DRAIN will never complete and we'll
+ * deadlock here.
+ * In fact, to make things easier, I'll just ignore the flush if
+ * there is any data at all now available.
+ */
+ if (prod_ptr == cons_ptr) {
+ loop_counter = 0;
+ while (readl(&port->ip_serial_regs->sscr) &
+ SSCR_RX_DRAIN) {
+ loop_counter++;
+ if (loop_counter > MAXITER)
+ return -1;
+ }
+
+ /* SIGH. We have to reload the prod_ptr *again* since
+ * the drain may have caused it to change
+ */
+ prod_ptr = readl(&port->ip_serial_regs->srpir)
+ & PROD_CONS_MASK;
+ }
+ if (reset_dma) {
+ port->ip_sscr &= ~SSCR_DMA_EN;
+ writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+ }
+ }
+ inring = port->ip_inring;
+ port->ip_flags &= ~READ_ABORTED;
+
+ total = 0;
+ loop_counter = 0xfffff; /* to avoid hangs */
+
+ /* Grab bytes from the hardware */
+ while ((prod_ptr != cons_ptr) && (len > 0)) {
+ entry = (struct ring_entry *)((caddr_t) inring + cons_ptr);
+
+ if (loop_counter-- <= 0) {
+ printk(KERN_WARNING "IOC3 serial: "
+ "possible hang condition/"
+ "port stuck on read (line %d).\n",
+ the_port->line);
+ break;
+ }
+
+ /* According to the producer pointer, this ring entry
+ * must contain some data. But if the PIO happened faster
+ * than the DMA, the data may not be available yet, so let's
+ * wait until it arrives.
+ */
+ if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+ /* Indicate the read is aborted so we don't disable
+ * the interrupt thinking that the consumer is
+ * congested.
+ */
+ port->ip_flags |= READ_ABORTED;
+ len = 0;
+ break;
+ }
+
+ /* Load the bytes/status out of the ring entry */
+ for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
+ sc = &(entry->ring_sc[byte_num]);
+
+ /* Check for change in modem state or overrun */
+ if ((*sc & RXSB_MODEM_VALID)
+ && (port->ip_notify & N_DDCD)) {
+ /* Notify upper layer if DCD dropped */
+ if ((port->ip_flags & DCD_ON)
+ && !(*sc & RXSB_DCD)) {
+ /* If we have already copied some data,
+ * return it. We'll pick up the carrier
+ * drop on the next pass. That way we
+ * don't throw away the data that has
+ * already been copied back to
+ * the caller's buffer.
+ */
+ if (total > 0) {
+ len = 0;
+ break;
+ }
+ port->ip_flags &= ~DCD_ON;
+
+ /* Turn off this notification so the
+ * carrier drop protocol won't see it
+ * again when it does a read.
+ */
+ *sc &= ~RXSB_MODEM_VALID;
+
+ /* To keep things consistent, we need
+ * to update the consumer pointer so
+ * the next reader won't come in and
+ * try to read the same ring entries
+ * again. This must be done here before
+ * the dcd change.
+ */
+
+ if ((entry->ring_allsc & RING_ANY_VALID)
+ == 0) {
+ cons_ptr += (int)sizeof
+ (struct ring_entry);
+ cons_ptr &= PROD_CONS_MASK;
+ }
+ writel(cons_ptr,
+ &port->ip_serial_regs->srcir);
+ port->ip_rx_cons = cons_ptr;
+
+ /* Notify upper layer of carrier drop */
+ if ((port->ip_notify & N_DDCD)
+ && port->ip_port) {
+ uart_handle_dcd_change
+ (port->ip_port, 0);
+ wake_up_interruptible
+ (&the_port->info->
+ delta_msr_wait);
+ }
+
+ /* If we had any data to return, we
+ * would have returned it above.
+ */
+ return 0;
+ }
+ }
+ if (*sc & RXSB_MODEM_VALID) {
+ /* Notify that an input overrun occurred */
+ if ((*sc & RXSB_OVERRUN)
+ && (port->ip_notify & N_OVERRUN_ERROR)) {
+ ioc3_cb_post_ncs(the_port, NCS_OVERRUN);
+ }
+ /* Don't look at this byte again */
+ *sc &= ~RXSB_MODEM_VALID;
+ }
+
+ /* Check for valid data or RX errors */
+ if ((*sc & RXSB_DATA_VALID) &&
+ ((*sc & (RXSB_PAR_ERR
+ | RXSB_FRAME_ERR | RXSB_BREAK))
+ && (port->ip_notify & (N_PARITY_ERROR
+ | N_FRAMING_ERROR
+ | N_BREAK)))) {
+ /* There is an error condition on the next byte.
+ * If we have already transferred some bytes,
+ * we'll stop here. Otherwise if this is the
+ * first byte to be read, we'll just transfer
+ * it alone after notifying the
+ * upper layer of its status.
+ */
+ if (total > 0) {
+ len = 0;
+ break;
+ } else {
+ if ((*sc & RXSB_PAR_ERR) &&
+ (port->
+ ip_notify & N_PARITY_ERROR)) {
+ ioc3_cb_post_ncs(the_port,
+ NCS_PARITY);
+ }
+ if ((*sc & RXSB_FRAME_ERR) &&
+ (port->
+ ip_notify & N_FRAMING_ERROR)) {
+ ioc3_cb_post_ncs(the_port,
+ NCS_FRAMING);
+ }
+ if ((*sc & RXSB_BREAK)
+ && (port->ip_notify & N_BREAK)) {
+ ioc3_cb_post_ncs
+ (the_port, NCS_BREAK);
+ }
+ len = 1;
+ }
+ }
+ if (*sc & RXSB_DATA_VALID) {
+ *sc &= ~RXSB_DATA_VALID;
+ *buf = entry->ring_data[byte_num];
+ buf++;
+ len--;
+ total++;
+ }
+ }
+
+ /* If we used up this entry entirely, go on to the next one,
+ * otherwise we must have run out of buffer space, so
+ * leave the consumer pointer here for the next read in case
+ * there are still unread bytes in this entry.
+ */
+ if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+ cons_ptr += (int)sizeof(struct ring_entry);
+ cons_ptr &= PROD_CONS_MASK;
+ }
+ }
+
+ /* Update consumer pointer and re-arm rx timer interrupt */
+ writel(cons_ptr, &port->ip_serial_regs->srcir);
+ port->ip_rx_cons = cons_ptr;
+
+ /* If we have now dipped below the rx high water mark and we have
+ * rx_high interrupt turned off, we can now turn it back on again.
+ */
+ if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
+ & PROD_CONS_MASK) <
+ ((port->
+ ip_sscr &
+ SSCR_RX_THRESHOLD)
+ << PROD_CONS_PTR_OFF))) {
+ port->ip_flags &= ~INPUT_HIGH;
+ enable_intrs(port, hooks->intr_rx_high);
+ }
+ return total;
+}
+
+/**
+ * receive_chars - upper level read.
+ * @the_port: port to read from
+ */
+static int receive_chars(struct uart_port *the_port)
+{
+ struct tty_struct *tty;
+ unsigned char ch[MAX_CHARS];
+ int read_count = 0, read_room, flip = 0;
+ struct uart_info *info = the_port->info;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ unsigned long pflags;
+
+ /* Make sure all the pointers are "good" ones */
+ if (!info)
+ return 0;
+ if (!info->tty)
+ return 0;
+
+ if (!(port->ip_flags & INPUT_ENABLE))
+ return 0;
+
+ spin_lock_irqsave(&the_port->lock, pflags);
+ tty = info->tty;
+
+ read_count = do_read(the_port, ch, MAX_CHARS);
+ if (read_count > 0) {
+ flip = 1;
+ read_room = tty_buffer_request_room(tty, read_count);
+ tty_insert_flip_string(tty, ch, read_room);
+ the_port->icount.rx += read_count;
+ }
+ spin_unlock_irqrestore(&the_port->lock, pflags);
+
+ if (flip)
+ tty_flip_buffer_push(tty);
+
+ return read_count;
+}
+
+/**
+ * ioc3uart_intr_one - lowest level (per port) interrupt handler.
+ * @is : submodule
+ * @idd: driver data
+ * @pending: interrupts to handle
+ * @regs: pt_regs
+ */
+
+static int inline
+ioc3uart_intr_one(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd,
+ unsigned int pending, struct pt_regs *regs)
+{
+ int port_num = GET_PORT_FROM_SIO_IR(pending);
+ struct port_hooks *hooks;
+ unsigned int rx_high_rd_aborted = 0;
+ unsigned long flags;
+ struct uart_port *the_port;
+ struct ioc3_port *port;
+ int loop_counter;
+ struct ioc3_card *card_ptr;
+ unsigned int sio_ir;
+
+ card_ptr = idd->data[is->id];
+ port = card_ptr->ic_port[port_num].icp_port;
+ hooks = port->ip_hooks;
+
+ /* Possible race condition here: The tx_mt interrupt bit may be
+ * cleared without the intervention of the interrupt handler,
+ * e.g. by a write. If the top level interrupt handler reads a
+ * tx_mt, then some other processor does a write, starting up
+ * output, then we come in here, see the tx_mt and stop DMA, the
+ * output started by the other processor will hang. Thus we can
+ * only rely on tx_mt being legitimate if it is read while the
+ * port lock is held. Therefore this bit must be ignored in the
+ * passed in interrupt mask which was read by the top level
+ * interrupt handler since the port lock was not held at the time
+ * it was read. We can only rely on this bit being accurate if it
+ * is read while the port lock is held. So we'll clear it for now,
+ * and reload it later once we have the port lock.
+ */
+
+ sio_ir = pending & ~(hooks->intr_tx_mt);
+ spin_lock_irqsave(&port->ip_lock, flags);
+
+ loop_counter = MAXITER; /* to avoid hangs */
+
+ do {
+ uint32_t shadow;
+
+ if (loop_counter-- <= 0) {
+ printk(KERN_WARNING "IOC3 serial: "
+ "possible hang condition/"
+ "port stuck on interrupt (line %d).\n",
+ ((struct uart_port *)port->ip_port)->line);
+ break;
+ }
+ /* Handle a DCD change */
+ if (sio_ir & hooks->intr_delta_dcd) {
+ ioc3_ack(is, idd, hooks->intr_delta_dcd);
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DDCD)
+ && (shadow & SHADOW_DCD)
+ && (port->ip_port)) {
+ the_port = port->ip_port;
+ uart_handle_dcd_change(the_port,
+ shadow & SHADOW_DCD);
+ wake_up_interruptible
+ (&the_port->info->delta_msr_wait);
+ } else if ((port->ip_notify & N_DDCD)
+ && !(shadow & SHADOW_DCD)) {
+ /* Flag delta DCD/no DCD */
+ uart_handle_dcd_change(port->ip_port,
+ shadow & SHADOW_DCD);
+ port->ip_flags |= DCD_ON;
+ }
+ }
+
+ /* Handle a CTS change */
+ if (sio_ir & hooks->intr_delta_cts) {
+ ioc3_ack(is, idd, hooks->intr_delta_cts);
+ shadow = readl(&port->ip_serial_regs->shadow);
+
+ if ((port->ip_notify & N_DCTS) && (port->ip_port)) {
+ the_port = port->ip_port;
+ uart_handle_cts_change(the_port, shadow
+ & SHADOW_CTS);
+ wake_up_interruptible
+ (&the_port->info->delta_msr_wait);
+ }
+ }
+
+ /* rx timeout interrupt. Must be some data available. Put this
+ * before the check for rx_high since servicing this condition
+ * may cause that condition to clear.
+ */
+ if (sio_ir & hooks->intr_rx_timer) {
+ ioc3_ack(is, idd, hooks->intr_rx_timer);
+ if ((port->ip_notify & N_DATA_READY)
+ && (port->ip_port)) {
+ receive_chars(port->ip_port);
+ }
+ }
+
+ /* rx high interrupt. Must be after rx_timer. */
+ else if (sio_ir & hooks->intr_rx_high) {
+ /* Data available, notify upper layer */
+ if ((port->ip_notify & N_DATA_READY) && port->ip_port) {
+ receive_chars(port->ip_port);
+ }
+
+ /* We can't ACK this interrupt. If receive_chars didn't
+ * cause the condition to clear, we'll have to disable
+ * the interrupt until the data is drained.
+ * If the read was aborted, don't disable the interrupt
+ * as this may cause us to hang indefinitely. An
+ * aborted read generally means that this interrupt
+ * hasn't been delivered to the cpu yet anyway, even
+ * though we see it as asserted when we read the sio_ir.
+ */
+ if ((sio_ir = PENDING(card_ptr, idd))
+ & hooks->intr_rx_high) {
+ if (port->ip_flags & READ_ABORTED) {
+ rx_high_rd_aborted++;
+ }
+ else {
+ card_ptr->ic_enable &= ~hooks->intr_rx_high;
+ port->ip_flags |= INPUT_HIGH;
+ }
+ }
+ }
+
+ /* We got a low water interrupt: notify upper layer to
+ * send more data. Must come before tx_mt since servicing
+ * this condition may cause that condition to clear.
+ */
+ if (sio_ir & hooks->intr_tx_explicit) {
+ port->ip_flags &= ~LOWAT_WRITTEN;
+ ioc3_ack(is, idd, hooks->intr_tx_explicit);
+ if (port->ip_notify & N_OUTPUT_LOWAT)
+ ioc3_cb_output_lowat(port);
+ }
+
+ /* Handle tx_mt. Must come after tx_explicit. */
+ else if (sio_ir & hooks->intr_tx_mt) {
+ /* If we are expecting a lowat notification
+ * and we get to this point it probably means that for
+ * some reason the tx_explicit didn't work as expected
+ * (that can legitimately happen if the output buffer is
+ * filled up in just the right way).
+ * So send the notification now.
+ */
+ if (port->ip_notify & N_OUTPUT_LOWAT) {
+ ioc3_cb_output_lowat(port);
+
+ /* We need to reload the sio_ir since the lowat
+ * call may have caused another write to occur,
+ * clearing the tx_mt condition.
+ */
+ sio_ir = PENDING(card_ptr, idd);
+ }
+
+ /* If the tx_mt condition still persists even after the
+ * lowat call, we've got some work to do.
+ */
+ if (sio_ir & hooks->intr_tx_mt) {
+ /* If we are not currently expecting DMA input,
+ * and the transmitter has just gone idle,
+ * there is no longer any reason for DMA, so
+ * disable it.
+ */
+ if (!(port->ip_notify
+ & (N_DATA_READY | N_DDCD))) {
+ BUG_ON(!(port->ip_sscr
+ & SSCR_DMA_EN));
+ port->ip_sscr &= ~SSCR_DMA_EN;
+ writel(port->ip_sscr,
+ &port->ip_serial_regs->sscr);
+ }
+ /* Prevent infinite tx_mt interrupt */
+ card_ptr->ic_enable &= ~hooks->intr_tx_mt;
+ }
+ }
+ sio_ir = PENDING(card_ptr, idd);
+
+ /* if the read was aborted and only hooks->intr_rx_high,
+ * clear hooks->intr_rx_high, so we do not loop forever.
+ */
+
+ if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
+ sio_ir &= ~hooks->intr_rx_high;
+ }
+ } while (sio_ir & hooks->intr_all);
+
+ spin_unlock_irqrestore(&port->ip_lock, flags);
+ ioc3_enable(is, idd, card_ptr->ic_enable);
+ return 0;
+}
+
+/**
+ * ioc3uart_intr - field all serial interrupts
+ * @is : submodule
+ * @idd: driver data
+ * @pending: interrupts to handle
+ * @regs: pt_regs
+ *
+ */
+
+static int ioc3uart_intr(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd,
+ unsigned int pending, struct pt_regs *regs)
+{
+ int ret = 0;
+
+ /*
+ * The upper level interrupt handler sends interrupts for both ports
+ * here. So we need to call for each port with its interrupts.
+ */
+
+ if (pending & SIO_IR_SA)
+ ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SA, regs);
+ if (pending & SIO_IR_SB)
+ ret |= ioc3uart_intr_one(is, idd, pending & SIO_IR_SB, regs);
+
+ return ret;
+}
+
+/**
+ * ic3_type
+ * @port: Port to operate with (we ignore since we only have one port)
+ *
+ */
+static const char *ic3_type(struct uart_port *the_port)
+{
+ if (IS_RS232(the_port->line))
+ return "SGI IOC3 Serial [rs232]";
+ else
+ return "SGI IOC3 Serial [rs422]";
+}
+
+/**
+ * ic3_tx_empty - Is the transmitter empty?
+ * @port: Port to operate on
+ *
+ */
+static unsigned int ic3_tx_empty(struct uart_port *the_port)
+{
+ unsigned int ret = 0;
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (readl(&port->ip_serial_regs->shadow) & SHADOW_TEMT)
+ ret = TIOCSER_TEMT;
+ return ret;
+}
+
+/**
+ * ic3_stop_tx - stop the transmitter
+ * @port: Port to operate on
+ *
+ */
+static void ic3_stop_tx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port)
+ set_notification(port, N_OUTPUT_LOWAT, 0);
+}
+
+/**
+ * ic3_stop_rx - stop the receiver
+ * @port: Port to operate on
+ *
+ */
+static void ic3_stop_rx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port)
+ port->ip_flags &= ~INPUT_ENABLE;
+}
+
+/**
+ * null_void_function
+ * @port: Port to operate on
+ *
+ */
+static void null_void_function(struct uart_port *the_port)
+{
+}
+
+/**
+ * ic3_shutdown - shut down the port - free irq and disable
+ * @port: port to shut down
+ *
+ */
+static void ic3_shutdown(struct uart_port *the_port)
+{
+ unsigned long port_flags;
+ struct ioc3_port *port;
+ struct uart_info *info;
+
+ port = get_ioc3_port(the_port);
+ if (!port)
+ return;
+
+ info = the_port->info;
+ wake_up_interruptible(&info->delta_msr_wait);
+
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ set_notification(port, N_ALL, 0);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+}
+
+/**
+ * ic3_set_mctrl - set control lines (dtr, rts, etc)
+ * @port: Port to operate on
+ * @mctrl: Lines to set/unset
+ *
+ */
+static void ic3_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
+{
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ set_mcr(the_port, mcr, SHADOW_DTR);
+}
+
+/**
+ * ic3_get_mctrl - get control line info
+ * @port: port to operate on
+ *
+ */
+static unsigned int ic3_get_mctrl(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+ uint32_t shadow;
+ unsigned int ret = 0;
+
+ if (!port)
+ return 0;
+
+ shadow = readl(&port->ip_serial_regs->shadow);
+ if (shadow & SHADOW_DCD)
+ ret |= TIOCM_CD;
+ if (shadow & SHADOW_DR)
+ ret |= TIOCM_DSR;
+ if (shadow & SHADOW_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+/**
+ * ic3_start_tx - Start transmitter. Called with the_port->lock
+ * @port: Port to operate on
+ *
+ */
+static void ic3_start_tx(struct uart_port *the_port)
+{
+ struct ioc3_port *port = get_ioc3_port(the_port);
+
+ if (port) {
+ set_notification(port, N_OUTPUT_LOWAT, 1);
+ enable_intrs(port, port->ip_hooks->intr_tx_mt);
+ }
+}
+
+/**
+ * ic3_break_ctl - handle breaks
+ * @port: Port to operate on
+ * @break_state: Break state
+ *
+ */
+static void ic3_break_ctl(struct uart_port *the_port, int break_state)
+{
+}
+
+/**
+ * ic3_startup - Start up the serial port - always return 0 (We're always on)
+ * @port: Port to operate on
+ *
+ */
+static int ic3_startup(struct uart_port *the_port)
+{
+ int retval;
+ struct ioc3_port *port;
+ struct ioc3_card *card_ptr;
+ unsigned long port_flags;
+
+ if (!the_port) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+ port = get_ioc3_port(the_port);
+ if (!port) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+ card_ptr = port->ip_card;
+ port->ip_port = the_port;
+
+ if (!card_ptr) {
+ NOT_PROGRESS();
+ return -ENODEV;
+ }
+
+ /* Start up the serial port */
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ retval = ic3_startup_local(the_port);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+ return retval;
+}
+
+/**
+ * ic3_set_termios - set termios stuff
+ * @port: port to operate on
+ * @termios: New settings
+ * @termios: Old
+ *
+ */
+static void
+ic3_set_termios(struct uart_port *the_port,
+ struct termios *termios, struct termios *old_termios)
+{
+ unsigned long port_flags;
+
+ spin_lock_irqsave(&the_port->lock, port_flags);
+ ioc3_change_speed(the_port, termios, old_termios);
+ spin_unlock_irqrestore(&the_port->lock, port_flags);
+}
+
+/**
+ * ic3_request_port - allocate resources for port - no op....
+ * @port: port to operate on
+ *
+ */
+static int ic3_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+/* Associate the uart functions above - given to serial core */
+static struct uart_ops ioc3_ops = {
+ .tx_empty = ic3_tx_empty,
+ .set_mctrl = ic3_set_mctrl,
+ .get_mctrl = ic3_get_mctrl,
+ .stop_tx = ic3_stop_tx,
+ .start_tx = ic3_start_tx,
+ .stop_rx = ic3_stop_rx,
+ .enable_ms = null_void_function,
+ .break_ctl = ic3_break_ctl,
+ .startup = ic3_startup,
+ .shutdown = ic3_shutdown,
+ .set_termios = ic3_set_termios,
+ .type = ic3_type,
+ .release_port = null_void_function,
+ .request_port = ic3_request_port,
+};
+
+/*
+ * Boot-time initialization code
+ */
+
+static struct uart_driver ioc3_uart = {
+ .owner = THIS_MODULE,
+ .driver_name = "ioc3_serial",
+ .dev_name = DEVICE_NAME,
+ .major = DEVICE_MAJOR,
+ .minor = DEVICE_MINOR,
+ .nr = MAX_LOGICAL_PORTS
+};
+
+/**
+ * ioc3_serial_core_attach - register with serial core
+ * This is done during pci probing
+ * @is: submodule struct for this
+ * @idd: handle for this card
+ */
+static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd)
+{
+ struct ioc3_port *port;
+ struct uart_port *the_port;
+ struct ioc3_card *card_ptr = idd->data[is->id];
+ int ii, phys_port;
+ struct pci_dev *pdev = idd->pdev;
+
+ DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
+ __FUNCTION__, pdev, (void *)card_ptr));
+
+ if (!card_ptr)
+ return -ENODEV;
+
+ /* once around for each logical port on this card */
+ for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
+ phys_port = GET_PHYSICAL_PORT(ii);
+ the_port = &card_ptr->ic_port[phys_port].
+ icp_uart_port[GET_LOGICAL_PORT(ii)];
+ port = card_ptr->ic_port[phys_port].icp_port;
+ port->ip_port = the_port;
+
+ DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
+ __FUNCTION__, (void *)the_port, (void *)port,
+ phys_port, ii));
+
+ /* membase, iobase and mapbase just need to be non-0 */
+ the_port->membase = (unsigned char __iomem *)1;
+ the_port->iobase = (pdev->bus->number << 16) | ii;
+ the_port->line = (Num_of_ioc3_cards << 2) | ii;
+ the_port->mapbase = 1;
+ the_port->type = PORT_16550A;
+ the_port->fifosize = FIFO_SIZE;
+ the_port->ops = &ioc3_ops;
+ the_port->irq = idd->irq_io;
+ the_port->dev = &pdev->dev;
+
+ if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
+ printk(KERN_WARNING
+ "%s: unable to add port %d bus %d\n",
+ __FUNCTION__, the_port->line, pdev->bus->number);
+ } else {
+ DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
+ the_port->line, the_port->irq, pdev->bus->number));
+ }
+
+ /* all ports are rs232 for now */
+ if (IS_PHYSICAL_PORT(ii))
+ ioc3_set_proto(port, PROTO_RS232);
+ }
+ return 0;
+}
+
+/**
+ * ioc3uart_remove - register detach function
+ * @is: submodule struct for this submodule
+ * @idd: ioc3 driver data for this submodule
+ */
+
+static int ioc3uart_remove(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd)
+{
+ struct ioc3_card *card_ptr = idd->data[is->id];
+ struct uart_port *the_port;
+ struct ioc3_port *port;
+ int ii;
+
+ if (card_ptr) {
+ for (ii = 0; ii < LOGICAL_PORTS_PER_CARD; ii++) {
+ the_port = &card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
+ icp_uart_port[GET_LOGICAL_PORT(ii)];
+ if (the_port)
+ uart_remove_one_port(&ioc3_uart, the_port);
+ port = card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].icp_port;
+ if (port && IS_PHYSICAL_PORT(ii)
+ && (GET_PHYSICAL_PORT(ii) == 0)) {
+ pci_free_consistent(port->ip_idd->pdev,
+ TOTAL_RING_BUF_SIZE,
+ (void *)port->ip_cpu_ringbuf,
+ port->ip_dma_ringbuf);
+ kfree(port);
+ card_ptr->ic_port[GET_PHYSICAL_PORT(ii)].
+ icp_port = NULL;
+ }
+ }
+ kfree(card_ptr);
+ idd->data[is->id] = NULL;
+ }
+ return 0;
+}
+
+/**
+ * ioc3uart_probe - card probe function called from shim driver
+ * @is: submodule struct for this submodule
+ * @idd: ioc3 driver data for this card
+ */
+
+static int __devinit
+ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
+{
+ struct pci_dev *pdev = idd->pdev;
+ struct ioc3_card *card_ptr;
+ int ret = 0;
+ struct ioc3_port *port;
+ struct ioc3_port *ports[PORTS_PER_CARD];
+ int phys_port;
+
+ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
+
+ card_ptr = kmalloc(sizeof(struct ioc3_card), GFP_KERNEL);
+ if (!card_ptr) {
+ printk(KERN_WARNING "ioc3_attach_one"
+ ": unable to get memory for the IOC3\n");
+ return -ENOMEM;
+ }
+ memset(card_ptr, 0, sizeof(struct ioc3_card));
+ idd->data[is->id] = card_ptr;
+ Submodule_slot = is->id;
+
+ writel(((UARTA_BASE >> 3) << SIO_CR_SER_A_BASE_SHIFT) |
+ ((UARTB_BASE >> 3) << SIO_CR_SER_B_BASE_SHIFT) |
+ (0xf << SIO_CR_CMD_PULSE_SHIFT), &idd->vma->sio_cr);
+
+ pci_write_config_dword(pdev, PCI_LAT, 0xff00);
+
+ /* Enable serial port mode select generic PIO pins as outputs */
+ ioc3_gpcr_set(idd, GPCR_UARTA_MODESEL | GPCR_UARTB_MODESEL);
+
+ /* Create port structures for each port */
+ for (phys_port = 0; phys_port < PORTS_PER_CARD; phys_port++) {
+ port = kmalloc(sizeof(struct ioc3_port), GFP_KERNEL);
+ if (!port) {
+ printk(KERN_WARNING
+ "IOC3 serial memory not available for port\n");
+ goto out4;
+ }
+ memset(port, 0, sizeof(struct ioc3_port));
+ spin_lock_init(&port->ip_lock);
+
+ /* we need to remember the previous ones, to point back to
+ * them farther down - setting up the ring buffers.
+ */
+ ports[phys_port] = port;
+
+ /* init to something useful */
+ card_ptr->ic_port[phys_port].icp_port = port;
+ port->ip_is = is;
+ port->ip_idd = idd;
+ port->ip_baud = 9600;
+ port->ip_card = card_ptr;
+ port->ip_hooks = &hooks_array[phys_port];
+
+ /* Setup each port */
+ if (phys_port == 0) {
+ port->ip_serial_regs = &idd->vma->port_a;
+ port->ip_uart_regs = &idd->vma->sregs.uarta;
+
+ DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* setup ring buffers */
+ port->ip_cpu_ringbuf = pci_alloc_consistent(pdev,
+ TOTAL_RING_BUF_SIZE, &port->ip_dma_ringbuf);
+
+ BUG_ON(!((((int64_t) port->ip_dma_ringbuf) &
+ (TOTAL_RING_BUF_SIZE - 1)) == 0));
+ port->ip_inring = RING(port, RX_A);
+ port->ip_outring = RING(port, TX_A);
+ DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+ }
+ else {
+ port->ip_serial_regs = &idd->vma->port_b;
+ port->ip_uart_regs = &idd->vma->sregs.uartb;
+
+ DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
+ "ip_uart_regs 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* share the ring buffers */
+ port->ip_dma_ringbuf =
+ ports[phys_port - 1]->ip_dma_ringbuf;
+ port->ip_cpu_ringbuf =
+ ports[phys_port - 1]->ip_cpu_ringbuf;
+ port->ip_inring = RING(port, RX_B);
+ port->ip_outring = RING(port, TX_B);
+ DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
+ "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
+ "ip_outring 0x%p\n",
+ __FUNCTION__,
+ (void *)port->ip_cpu_ringbuf,
+ (void *)port->ip_dma_ringbuf,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+ }
+
+ DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
+ __FUNCTION__,
+ phys_port, (void *)port, (void *)card_ptr));
+ DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
+ (void *)port->ip_serial_regs,
+ (void *)port->ip_uart_regs));
+
+ /* Initialize the hardware for IOC3 */
+ port_init(port);
+
+ DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
+ "outring 0x%p\n",
+ __FUNCTION__,
+ phys_port, (void *)port,
+ (void *)port->ip_inring,
+ (void *)port->ip_outring));
+
+ }
+
+ /* register port with the serial core */
+
+ if ((ret = ioc3_serial_core_attach(is, idd)))
+ goto out4;
+
+ Num_of_ioc3_cards++;
+
+ return ret;
+
+ /* error exits that give back resources */
+out4:
+ kfree(card_ptr);
+ return ret;
+}
+
+static struct ioc3_submodule ioc3uart_submodule = {
+ .name = "IOC3uart",
+ .probe = ioc3uart_probe,
+ .remove = ioc3uart_remove,
+ /* call .intr for both ports initially */
+ .irq_mask = SIO_IR_SA | SIO_IR_SB,
+ .intr = ioc3uart_intr,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * ioc3_detect - module init called,
+ */
+static int __devinit ioc3uart_init(void)
+{
+ int ret;
+
+ /* register with serial core */
+ if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
+ printk(KERN_WARNING
+ "%s: Couldn't register IOC3 uart serial driver\n",
+ __FUNCTION__);
+ return ret;
+ }
+ ret = ioc3_register_submodule(&ioc3uart_submodule);
+ if (ret)
+ uart_unregister_driver(&ioc3_uart);
+ return ret;
+}
+
+static void __devexit ioc3uart_exit(void)
+{
+ ioc3_unregister_submodule(&ioc3uart_submodule);
+ uart_unregister_driver(&ioc3_uart);
+}
+
+module_init(ioc3uart_init);
+module_exit(ioc3uart_exit);
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC3 card");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index 771676abee60..1d85533d46d2 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2327,19 +2327,13 @@ static void receive_chars(struct uart_port *the_port)
spin_lock_irqsave(&the_port->lock, pflags);
tty = info->tty;
- if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count)
- request_count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2);
if (request_count > 0) {
icount = &the_port->icount;
read_count = do_read(the_port, ch, request_count);
if (read_count > 0) {
- flip = 1;
- memcpy(tty->flip.char_buf_ptr, ch, read_count);
- memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
- tty->flip.char_buf_ptr += read_count;
- tty->flip.flag_buf_ptr += read_count;
- tty->flip.count += read_count;
+ tty_insert_flip_string(tty, ch, read_count);
icount->rx += read_count;
}
}
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index ef132349f310..66f117d15065 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -259,13 +259,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */
while (1) {
- unsigned char ch, r1;
-
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; /* XXX Ignores SysRq when we need it most. Fix. */
- }
+ unsigned char ch, r1, flag;
r1 = read_zsreg(channel, R1);
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
@@ -303,8 +297,7 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
}
/* A real serial line, record the character and status. */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
if (r1 & BRK_ABRT) {
@@ -321,28 +314,21 @@ static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up,
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto next_char;
if (up->port.ignore_status_mask == 0xff ||
- (r1 & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ (r1 & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
next_char:
ch = readb(&channel->control);
ZSDELAY();
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index b0ecc7537ce5..b48066a64a7d 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -331,17 +331,12 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status,
{
struct tty_struct *tty = up->port.info->tty;
unsigned char ch;
+ unsigned char flag;
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return; // if TTY_DONT_FLIP is set
- }
ch = sio_in(up, SIORXB);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -380,30 +375,24 @@ static _INLINE_ void receive_chars(struct uart_sio_port *up, int *status,
if (*status & UART_LSR_BI) {
DEBUG_INTR("handling break....");
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (*status & UART_LSR_OE) {
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
ignore_char:
*status = serial_in(up, UART_LSR);
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 47f7404cb045..d957a3a9edf1 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -313,7 +313,7 @@ static inline void receive_chars(struct mcf_serial *info)
{
volatile unsigned char *uartp;
struct tty_struct *tty = info->tty;
- unsigned char status, ch;
+ unsigned char status, ch, flag;
if (!tty)
return;
@@ -321,10 +321,6 @@ static inline void receive_chars(struct mcf_serial *info)
uartp = info->addr;
while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
ch = uartp[MCFUART_URB];
info->stats.rx++;
@@ -335,29 +331,24 @@ static inline void receive_chars(struct mcf_serial *info)
}
#endif
- tty->flip.count++;
+ flag = TTY_NORMAL;
if (status & MCFUART_USR_RXERR) {
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
if (status & MCFUART_USR_RXBREAK) {
info->stats.rxbreak++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (status & MCFUART_USR_RXPARITY) {
info->stats.rxparity++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ flag = TTY_PARITY;
} else if (status & MCFUART_USR_RXOVERRUN) {
info->stats.rxoverrun++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
} else if (status & MCFUART_USR_RXFRAMING) {
info->stats.rxframing++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
- } else {
- /* This should never happen... */
- *tty->flip.flag_buf_ptr++ = 0;
+ flag = TTY_FRAME;
}
- } else {
- *tty->flip.flag_buf_ptr++ = 0;
}
- *tty->flip.char_buf_ptr++ = ch;
+ tty_insert_flip_char(tty, ch, flag);
}
schedule_work(&tty->flip.work);
@@ -1525,7 +1516,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_ICR0 + MCFINT_UART0 + info->line);
- *icrp = 0x33; /* UART0 with level 6, priority 3 */
+ *icrp = 0x30 + info->line; /* level 6, line based priority */
imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_IMRL);
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index b8727d9bf690..61dd17d7bace 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -37,11 +37,11 @@
* by the bootloader or in the platform init code.
*
* The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
- * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
- * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
- * the console code : without this 1:1 mapping, at early boot time, when we are
- * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
- * mapped to.
+ * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and
+ * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly
+ * fpr the console code : without this 1:1 mapping, at early boot time, when we
+ * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it
+ * will be mapped to.
*/
#include <linux/config.h>
@@ -65,6 +65,10 @@
#include <linux/serial_core.h>
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_PSC_MAJOR 204
+#define SERIAL_PSC_MINOR 148
+
#define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */
@@ -401,17 +405,13 @@ static inline int
mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
{
struct tty_struct *tty = port->info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
unsigned short status;
/* While we can read, do so ! */
while ( (status = in_be16(&PSC(port)->mpc52xx_psc_status)) &
MPC52xx_PSC_SR_RXRDY) {
- /* If we are full, just stop reading */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
-
/* Get the char */
ch = in_8(&PSC(port)->mpc52xx_psc_buffer_8);
@@ -424,45 +424,35 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port, struct pt_regs *regs)
#endif
/* Store it */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = 0;
+
+ flag = TTY_NORMAL;
port->icount.rx++;
if ( status & (MPC52xx_PSC_SR_PE |
MPC52xx_PSC_SR_FE |
- MPC52xx_PSC_SR_RB |
- MPC52xx_PSC_SR_OE) ) {
+ MPC52xx_PSC_SR_RB) ) {
if (status & MPC52xx_PSC_SR_RB) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
uart_handle_break(port);
} else if (status & MPC52xx_PSC_SR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (status & MPC52xx_PSC_SR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (status & MPC52xx_PSC_SR_OE) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < (TTY_FLIPBUF_SIZE-1)) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
+ flag = TTY_FRAME;
/* Clear error condition */
out_8(&PSC(port)->command,MPC52xx_PSC_RST_ERR_STAT);
}
-
- tty->flip.char_buf_ptr++;
- tty->flip.flag_buf_ptr++;
- tty->flip.count++;
-
+ tty_insert_flip_char(tty, ch, flag);
+ if (status & MPC52xx_PSC_SR_OE) {
+ /*
+ * Overrun is special, since it's
+ * reported immediately, and doesn't
+ * affect the current character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
}
tty_flip_buffer_push(tty);
@@ -668,15 +658,15 @@ mpc52xx_console_setup(struct console *co, char *options)
}
-extern struct uart_driver mpc52xx_uart_driver;
+static struct uart_driver mpc52xx_uart_driver;
static struct console mpc52xx_console = {
- .name = "ttyS",
+ .name = "ttyPSC",
.write = mpc52xx_console_write,
.device = uart_console_device,
.setup = mpc52xx_console_setup,
.flags = CON_PRINTBUFFER,
- .index = -1, /* Specified on the cmdline (e.g. console=ttyS0 ) */
+ .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0 ) */
.data = &mpc52xx_uart_driver,
};
@@ -703,10 +693,10 @@ console_initcall(mpc52xx_console_init);
static struct uart_driver mpc52xx_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "mpc52xx_psc_uart",
- .dev_name = "ttyS",
- .devfs_name = "ttyS",
- .major = TTY_MAJOR,
- .minor = 64,
+ .dev_name = "ttyPSC",
+ .devfs_name = "ttyPSC",
+ .major = SERIAL_PSC_MAJOR,
+ .minor = SERIAL_PSC_MINOR,
.nr = MPC52xx_PSC_MAXNUM,
.cons = MPC52xx_PSC_CONSOLE,
};
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index 8f83e4007ecd..0ca83ac31d07 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -769,12 +769,12 @@ mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs)
bytes_in = be16_to_cpu(rxre->bytecnt);
/* Following use of tty struct directly is deprecated */
- if (unlikely((tty->flip.count + bytes_in) >= TTY_FLIPBUF_SIZE)){
+ if (unlikely(tty_buffer_request_room(tty, bytes_in) < bytes_in)) {
if (tty->low_latency)
tty_flip_buffer_push(tty);
/*
- * If this failed then we will throw awa the bytes
- * but mst do so to clear interrupts.
+ * If this failed then we will throw away the bytes
+ * but must do so to clear interrupts.
*/
}
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
index 7633132a10aa..4e49168c3176 100644
--- a/drivers/serial/mux.c
+++ b/drivers/serial/mux.c
@@ -223,11 +223,6 @@ static void mux_read(struct uart_port *port)
if (MUX_EOFIFO(data))
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
-
- *tty->flip.char_buf_ptr = data & 0xffu;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
port->icount.rx++;
if (MUX_BREAK(data)) {
@@ -239,9 +234,7 @@ static void mux_read(struct uart_port *port)
if (uart_handle_sysrq_char(port, data & 0xffu, NULL))
continue;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, data & 0xFF, TTY_NORMAL);
}
if (start_count != port->icount.rx) {
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c
index 5ddd8ab1f108..4e03a87f3fb4 100644
--- a/drivers/serial/pmac_zilog.c
+++ b/drivers/serial/pmac_zilog.c
@@ -60,6 +60,7 @@
#include <linux/pmu.h>
#include <linux/bitops.h>
#include <linux/sysrq.h>
+#include <linux/mutex.h>
#include <asm/sections.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -68,7 +69,6 @@
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
#include <asm/macio.h>
-#include <asm/semaphore.h>
#if defined (CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
@@ -96,7 +96,7 @@ MODULE_LICENSE("GPL");
*/
static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS];
static int pmz_ports_count;
-static DECLARE_MUTEX(pmz_irq_sem);
+static DEFINE_MUTEX(pmz_irq_mutex);
static struct uart_driver pmz_uart_reg = {
.owner = THIS_MODULE,
@@ -210,10 +210,9 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
struct pt_regs *regs)
{
struct tty_struct *tty = NULL;
- unsigned char ch, r1, drop, error;
+ unsigned char ch, r1, drop, error, flag;
int loops = 0;
- retry:
/* The interrupt can be enabled when the port isn't open, typically
* that happens when using one port is open and the other closed (stale
* interrupt) or when one port is used as a console.
@@ -246,20 +245,6 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
error = 0;
drop = 0;
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- /* Have to drop the lock here */
- pmz_debug("pmz: flip overflow\n");
- spin_unlock(&uap->port.lock);
- tty->flip.work.func((void *)tty);
- spin_lock(&uap->port.lock);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- drop = 1;
- if (ZS_IS_ASLEEP(uap))
- return NULL;
- if (!ZS_IS_OPEN(uap))
- goto retry;
- }
-
r1 = read_zsreg(uap, R1);
ch = read_zsdata(uap);
@@ -295,8 +280,7 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
if (drop)
goto next_char;
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
uap->port.icount.rx++;
if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) {
@@ -316,26 +300,19 @@ static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap,
uap->port.icount.overrun++;
r1 &= uap->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uap->port.ignore_status_mask == 0xff ||
(r1 & uap->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
}
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
next_char:
/* We can get stuck in an infinite loop getting char 0 when the
* line is in a wrong HW state, we break that here.
@@ -945,7 +922,7 @@ static int pmz_startup(struct uart_port *port)
if (uap->node == NULL)
return -ENODEV;
- down(&pmz_irq_sem);
+ mutex_lock(&pmz_irq_mutex);
uap->flags |= PMACZILOG_FLAG_IS_OPEN;
@@ -963,11 +940,11 @@ static int pmz_startup(struct uart_port *port)
dev_err(&uap->dev->ofdev.dev,
"Unable to register zs interrupt handler.\n");
pmz_set_scc_power(uap, 0);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
return -ENXIO;
}
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
/* Right now, we deal with delay by blocking here, I'll be
* smarter later on
@@ -1004,7 +981,7 @@ static void pmz_shutdown(struct uart_port *port)
if (uap->node == NULL)
return;
- down(&pmz_irq_sem);
+ mutex_lock(&pmz_irq_mutex);
/* Release interrupt handler */
free_irq(uap->port.irq, uap);
@@ -1025,7 +1002,7 @@ static void pmz_shutdown(struct uart_port *port)
if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) {
spin_unlock_irqrestore(&port->lock, flags);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
return;
}
@@ -1042,7 +1019,7 @@ static void pmz_shutdown(struct uart_port *port)
spin_unlock_irqrestore(&port->lock, flags);
- up(&pmz_irq_sem);
+ mutex_unlock(&pmz_irq_mutex);
pmz_debug("pmz: shutdown() done.\n");
}
@@ -1431,11 +1408,14 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
char name[1];
} *slots;
int len;
+ struct resource r_ports, r_rxdma, r_txdma;
/*
* Request & map chip registers
*/
- uap->port.mapbase = np->addrs[0].address;
+ if (of_address_to_resource(np, 0, &r_ports))
+ return -ENODEV;
+ uap->port.mapbase = r_ports.start;
uap->port.membase = ioremap(uap->port.mapbase, 0x1000);
uap->control_reg = uap->port.membase;
@@ -1445,16 +1425,20 @@ static int __init pmz_init_port(struct uart_pmac_port *uap)
* Request & map DBDMA registers
*/
#ifdef HAS_DBDMA
- if (np->n_addrs >= 3 && np->n_intrs >= 3)
+ if (of_address_to_resource(np, 1, &r_txdma) == 0 &&
+ of_address_to_resource(np, 2, &r_rxdma) == 0)
uap->flags |= PMACZILOG_FLAG_HAS_DMA;
+#else
+ memset(&r_txdma, 0, sizeof(struct resource));
+ memset(&r_rxdma, 0, sizeof(struct resource));
#endif
if (ZS_HAS_DMA(uap)) {
- uap->tx_dma_regs = ioremap(np->addrs[np->n_addrs - 2].address, 0x1000);
+ uap->tx_dma_regs = ioremap(r_txdma.start, 0x100);
if (uap->tx_dma_regs == NULL) {
uap->flags &= ~PMACZILOG_FLAG_HAS_DMA;
goto no_dma;
}
- uap->rx_dma_regs = ioremap(np->addrs[np->n_addrs - 1].address, 0x1000);
+ uap->rx_dma_regs = ioremap(r_rxdma.start, 0x100);
if (uap->rx_dma_regs == NULL) {
iounmap(uap->tx_dma_regs);
uap->tx_dma_regs = NULL;
@@ -1607,8 +1591,8 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
state = pmz_uart_reg.state + uap->port.line;
- down(&pmz_irq_sem);
- down(&state->sem);
+ mutex_lock(&pmz_irq_mutex);
+ mutex_lock(&state->mutex);
spin_lock_irqsave(&uap->port.lock, flags);
@@ -1639,8 +1623,8 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
/* Shut the chip down */
pmz_set_scc_power(uap, 0);
- up(&state->sem);
- up(&pmz_irq_sem);
+ mutex_unlock(&state->mutex);
+ mutex_unlock(&pmz_irq_mutex);
pmz_debug("suspend, switching complete\n");
@@ -1667,8 +1651,8 @@ static int pmz_resume(struct macio_dev *mdev)
state = pmz_uart_reg.state + uap->port.line;
- down(&pmz_irq_sem);
- down(&state->sem);
+ mutex_lock(&pmz_irq_mutex);
+ mutex_lock(&state->mutex);
spin_lock_irqsave(&uap->port.lock, flags);
if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) {
@@ -1700,8 +1684,8 @@ static int pmz_resume(struct macio_dev *mdev)
}
bail:
- up(&state->sem);
- up(&pmz_irq_sem);
+ mutex_unlock(&state->mutex);
+ mutex_unlock(&pmz_irq_mutex);
/* Right now, we deal with delay by blocking here, I'll be
* smarter later on
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index cc998b99a19f..10535f00301f 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -107,14 +107,6 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
int max_count = 256;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
ch = serial_in(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 47681c4654e4..eb4883efb7c6 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -72,12 +72,12 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/delay.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
@@ -323,16 +323,6 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
break;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
-
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
uerstat = rd_regl(port, S3C2410_UERSTAT);
ch = rd_regb(port, S3C2410_URXH);
@@ -782,11 +772,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
- clk_unuse(ourport->baudclk);
ourport->baudclk = NULL;
}
- clk_use(clk);
clk_enable(clk);
ourport->clksrc = clksrc;
@@ -1077,9 +1065,6 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->clk = clk_get(&platdev->dev, "uart");
- if (ourport->clk != NULL && !IS_ERR(ourport->clk))
- clk_use(ourport->clk);
-
dbg("port: map=%08x, mem=%08x, irq=%d, clock=%ld\n",
port->mapbase, port->membase, port->irq, port->uartclk);
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 25a086458ab9..1bd93168f504 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -201,8 +201,6 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
while (status & UTSR1_TO_SM(UTSR1_RNE)) {
ch = UART_GET_CHAR(sport);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
sport->port.icount.rx++;
flg = TTY_NORMAL;
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index c17d680e3f04..943770470b9d 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -33,6 +33,7 @@
#include <linux/device.h>
#include <linux/serial.h> /* for serial_state and serial_icounter_struct */
#include <linux/delay.h>
+#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -47,7 +48,7 @@
/*
* This is used to lock changes in serial line configuration.
*/
-static DECLARE_MUTEX(port_sem);
+static DEFINE_MUTEX(port_mutex);
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
@@ -637,7 +638,7 @@ static int uart_set_info(struct uart_state *state,
* module insertion/removal doesn't change anything
* under us.
*/
- down(&state->sem);
+ mutex_lock(&state->mutex);
change_irq = new_serial.irq != port->irq;
@@ -796,7 +797,7 @@ static int uart_set_info(struct uart_state *state,
} else
retval = uart_startup(state, 1);
exit:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return retval;
}
@@ -833,7 +834,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
struct uart_port *port = state->port;
int result = -EIO;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
result = port->mctrl;
@@ -842,7 +843,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
result |= port->ops->get_mctrl(port);
spin_unlock_irq(&port->lock);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return result;
}
@@ -855,13 +856,13 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
struct uart_port *port = state->port;
int ret = -EIO;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
uart_update_mctrl(port, set, clear);
ret = 0;
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return ret;
}
@@ -872,12 +873,12 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
BUG_ON(!kernel_locked());
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (port->type != PORT_UNKNOWN)
port->ops->break_ctl(port, break_state);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static int uart_do_autoconfig(struct uart_state *state)
@@ -893,7 +894,7 @@ static int uart_do_autoconfig(struct uart_state *state)
* changing, and hence any extra opens of the port while
* we're auto-configuring.
*/
- if (down_interruptible(&state->sem))
+ if (mutex_lock_interruptible(&state->mutex))
return -ERESTARTSYS;
ret = -EBUSY;
@@ -919,7 +920,7 @@ static int uart_do_autoconfig(struct uart_state *state)
ret = uart_startup(state, 1);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return ret;
}
@@ -1073,7 +1074,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
if (ret != -ENOIOCTLCMD)
goto out;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (tty_hung_up_p(filp)) {
ret = -EIO;
@@ -1097,7 +1098,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
}
}
out_up:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
out:
return ret;
}
@@ -1185,7 +1186,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
DPRINTK("uart_close(%d) called\n", port->line);
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (tty_hung_up_p(filp))
goto done;
@@ -1259,7 +1260,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&state->info->open_wait);
done:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1333,7 +1334,7 @@ static void uart_hangup(struct tty_struct *tty)
BUG_ON(!kernel_locked());
DPRINTK("uart_hangup(%d)\n", state->port->line);
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
@@ -1343,7 +1344,7 @@ static void uart_hangup(struct tty_struct *tty)
wake_up_interruptible(&state->info->open_wait);
wake_up_interruptible(&state->info->delta_msr_wait);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
/*
@@ -1440,14 +1441,15 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
* modem is ready for us.
*/
spin_lock_irq(&port->lock);
+ port->ops->enable_ms(port);
mctrl = port->ops->get_mctrl(port);
spin_unlock_irq(&port->lock);
if (mctrl & TIOCM_CAR)
break;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
schedule();
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (signal_pending(current))
break;
@@ -1471,9 +1473,9 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state;
- down(&port_sem);
+ mutex_lock(&port_mutex);
state = drv->state + line;
- if (down_interruptible(&state->sem)) {
+ if (mutex_lock_interruptible(&state->mutex)) {
state = ERR_PTR(-ERESTARTSYS);
goto out;
}
@@ -1481,7 +1483,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
state->count++;
if (!state->port) {
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
state = ERR_PTR(-ENXIO);
goto out;
}
@@ -1502,13 +1504,13 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
(unsigned long)state);
} else {
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
state = ERR_PTR(-ENOMEM);
}
}
out:
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return state;
}
@@ -1569,7 +1571,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
if (tty_hung_up_p(filp)) {
retval = -EAGAIN;
state->count--;
- up(&state->sem);
+ mutex_unlock(&state->mutex);
goto fail;
}
@@ -1589,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
*/
if (retval == 0)
retval = uart_block_til_ready(filp, state);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
/*
* If this is the first open to succeed, adjust things to suit.
@@ -1865,7 +1867,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
- down(&state->sem);
+ mutex_lock(&state->mutex);
if (state->info && state->info->flags & UIF_INITIALIZED) {
struct uart_ops *ops = port->ops;
@@ -1894,7 +1896,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
uart_change_pm(state, 3);
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return 0;
}
@@ -1903,7 +1905,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = drv->state + port->line;
- down(&state->sem);
+ mutex_lock(&state->mutex);
uart_change_pm(state, 0);
@@ -1952,7 +1954,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
}
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return 0;
}
@@ -2047,7 +2049,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
if (info && info->tty)
tty_vhangup(info->tty);
- down(&state->sem);
+ mutex_lock(&state->mutex);
state->info = NULL;
@@ -2070,7 +2072,7 @@ uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state)
kfree(info);
}
- up(&state->sem);
+ mutex_unlock(&state->mutex);
}
static struct tty_operations uart_ops = {
@@ -2159,7 +2161,7 @@ int uart_register_driver(struct uart_driver *drv)
state->close_delay = 500; /* .5 seconds */
state->closing_wait = 30000; /* 30 seconds */
- init_MUTEX(&state->sem);
+ mutex_init(&state->mutex);
}
retval = tty_register_driver(normal);
@@ -2218,7 +2220,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
state = drv->state + port->line;
- down(&port_sem);
+ mutex_lock(&port_mutex);
if (state->port) {
ret = -EINVAL;
goto out;
@@ -2254,7 +2256,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
register_console(port->cons);
out:
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return ret;
}
@@ -2278,7 +2280,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
printk(KERN_ALERT "Removing wrong port: %p != %p\n",
state->port, port);
- down(&port_sem);
+ mutex_lock(&port_mutex);
/*
* Remove the devices from devfs
@@ -2287,7 +2289,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
uart_unconfigure_port(drv, state);
state->port = NULL;
- up(&port_sem);
+ mutex_unlock(&port_mutex);
return 0;
}
@@ -2307,7 +2309,7 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2)
return (port1->iobase == port2->iobase) &&
(port1->hub6 == port2->hub6);
case UPIO_MEM:
- return (port1->membase == port2->membase);
+ return (port1->mapbase == port2->mapbase);
}
return 0;
}
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 7ce0c7e66d37..c30333694fde 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -114,15 +114,7 @@ struct serial_cfg_mem {
static void serial_config(dev_link_t * link);
-static int serial_event(event_t event, int priority,
- event_callback_args_t * args);
-static dev_info_t dev_info = "serial_cs";
-
-static dev_link_t *serial_attach(void);
-static void serial_detach(dev_link_t *);
-
-static dev_link_t *dev_list = NULL;
/*======================================================================
@@ -159,8 +151,9 @@ static void serial_remove(dev_link_t *link)
}
}
-static void serial_suspend(dev_link_t *link)
+static int serial_suspend(struct pcmcia_device *dev)
{
+ dev_link_t *link = dev_to_instance(dev);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
@@ -173,10 +166,13 @@ static void serial_suspend(dev_link_t *link)
if (!info->slave)
pcmcia_release_configuration(link->handle);
}
+
+ return 0;
}
-static void serial_resume(dev_link_t *link)
+static int serial_resume(struct pcmcia_device *dev)
{
+ dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND;
if (DEV_OK(link)) {
@@ -189,6 +185,8 @@ static void serial_resume(dev_link_t *link)
for (i = 0; i < info->ndev; i++)
serial8250_resume_port(info->line[i]);
}
+
+ return 0;
}
/*======================================================================
@@ -199,19 +197,17 @@ static void serial_resume(dev_link_t *link)
======================================================================*/
-static dev_link_t *serial_attach(void)
+static int serial_probe(struct pcmcia_device *p_dev)
{
struct serial_info *info;
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
DEBUG(0, "serial_attach()\n");
/* Create new serial device */
info = kmalloc(sizeof (*info), GFP_KERNEL);
if (!info)
- return NULL;
+ return -ENOMEM;
memset(info, 0, sizeof (*info));
link = &info->link;
link->priv = info;
@@ -227,20 +223,12 @@ static dev_link_t *serial_attach(void)
}
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- 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);
- serial_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ serial_config(link);
- return link;
+ return 0;
}
/*======================================================================
@@ -252,21 +240,13 @@ static dev_link_t *serial_attach(void)
======================================================================*/
-static void serial_detach(dev_link_t * link)
+static void serial_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct serial_info *info = link->priv;
- dev_link_t **linkp;
- int ret;
DEBUG(0, "serial_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp == NULL)
- return;
-
/*
* Ensure any outstanding scheduled tasks are completed.
*/
@@ -277,14 +257,7 @@ static void serial_detach(dev_link_t * link)
*/
serial_remove(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
-
- /* Unlink device structure, free bits */
- *linkp = link->next;
+ /* free bits */
kfree(info);
}
@@ -718,54 +691,6 @@ void serial_config(dev_link_t * link)
kfree(cfg_mem);
}
-/*======================================================================
-
- The card status event handler. Mostly, this schedules other
- stuff to run after an event is received. A CARD_REMOVAL event
- also sets some flags to discourage the serial drivers from
- talking to the ports.
-
-======================================================================*/
-
-static int
-serial_event(event_t event, int priority, event_callback_args_t * args)
-{
- dev_link_t *link = args->client_data;
- struct serial_info *info = link->priv;
-
- DEBUG(1, "serial_event(0x%06x)\n", event);
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- serial_remove(link);
- break;
-
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- serial_config(link);
- break;
-
- case CS_EVENT_PM_SUSPEND:
- serial_suspend(link);
- break;
-
- case CS_EVENT_RESET_PHYSICAL:
- if ((link->state & DEV_CONFIG) && !info->slave)
- pcmcia_release_configuration(link->handle);
- break;
-
- case CS_EVENT_PM_RESUME:
- serial_resume(link);
- break;
-
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link) && !info->slave)
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
- return 0;
-}
-
static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
@@ -860,6 +785,8 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"),
PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"),
PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"),
@@ -877,10 +804,11 @@ static struct pcmcia_driver serial_cs_driver = {
.drv = {
.name = "serial_cs",
},
- .attach = serial_attach,
- .event = serial_event,
- .detach = serial_detach,
+ .probe = serial_probe,
+ .remove = serial_detach,
.id_table = serial_ids,
+ .suspend = serial_suspend,
+ .resume = serial_resume,
};
static int __init init_serial_cs(void)
@@ -891,7 +819,6 @@ static int __init init_serial_cs(void)
static void __exit exit_serial_cs(void)
{
pcmcia_unregister_driver(&serial_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_serial_cs);
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index d01dbe5da3b9..d4a1f0e798c1 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -148,15 +148,6 @@ lh7a40xuart_rx_chars (struct uart_port* port)
unsigned int data, flag;/* Received data and status */
while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- /*
- * If this failed then we will throw away the
- * bytes but must do so to clear interrupts
- */
- }
-
data = UR (port, UART_R_DATA);
flag = TTY_NORMAL;
++port->icount.rx;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index f10c86d60b64..ee98a867bc6d 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -52,6 +52,7 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
+#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -303,17 +304,6 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
char flag;
do {
- /* 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) {
- 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 */
- }
ch = sio_in(up, TXX9_SIRFIFO);
flag = TTY_NORMAL;
up->port.icount.rx++;
@@ -1029,7 +1019,7 @@ 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);
+static DEFINE_MUTEX(serial_txx9_mutex);
/**
* serial_txx9_register_port - register a serial port
@@ -1048,7 +1038,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
struct uart_txx9_port *uart;
int ret = -ENOSPC;
- down(&serial_txx9_sem);
+ mutex_lock(&serial_txx9_mutex);
for (i = 0; i < UART_NR; i++) {
uart = &serial_txx9_ports[i];
if (uart->port.type == PORT_UNKNOWN)
@@ -1069,7 +1059,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port)
if (ret == 0)
ret = uart->port.line;
}
- up(&serial_txx9_sem);
+ mutex_unlock(&serial_txx9_mutex);
return ret;
}
@@ -1084,7 +1074,7 @@ static void __devexit serial_txx9_unregister_port(int line)
{
struct uart_txx9_port *uart = &serial_txx9_ports[line];
- down(&serial_txx9_sem);
+ mutex_lock(&serial_txx9_mutex);
uart_remove_one_port(&serial_txx9_reg, &uart->port);
uart->port.flags = 0;
uart->port.type = PORT_UNKNOWN;
@@ -1093,7 +1083,7 @@ static void __devexit serial_txx9_unregister_port(int line)
uart->port.membase = 0;
uart->port.dev = NULL;
uart_add_one_port(&serial_txx9_reg, &uart->port);
- up(&serial_txx9_sem);
+ mutex_unlock(&serial_txx9_mutex);
}
/*
@@ -1195,7 +1185,7 @@ static int __init serial_txx9_init(void)
serial_txx9_register_ports(&serial_txx9_reg);
#ifdef ENABLE_SERIAL_TXX9_PCI
- ret = pci_module_init(&serial_txx9_pci_driver);
+ ret = pci_register_driver(&serial_txx9_pci_driver);
#endif
}
return ret;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 430754ebac8a..a9e070759628 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -482,6 +482,7 @@ static inline void sci_receive_chars(struct uart_port *port,
struct tty_struct *tty = port->info->tty;
int i, count, copied = 0;
unsigned short status;
+ unsigned char flag;
status = sci_in(port, SCxSR);
if (!(status & SCxSR_RDxF(port)))
@@ -499,8 +500,7 @@ static inline void sci_receive_chars(struct uart_port *port,
#endif
/* Don't copy more bytes than there is room for in the buffer */
- if (tty->flip.count + count > TTY_FLIPBUF_SIZE)
- count = TTY_FLIPBUF_SIZE - tty->flip.count;
+ count = tty_buffer_request_room(tty, count);
/* If for any reason we can't copy more data, we're done! */
if (count == 0)
@@ -512,8 +512,7 @@ static inline void sci_receive_chars(struct uart_port *port,
|| uart_handle_sysrq_char(port, c, regs)) {
count = 0;
} else {
- tty->flip.char_buf_ptr[0] = c;
- tty->flip.flag_buf_ptr[0] = TTY_NORMAL;
+ tty_insert_flip_char(tty, c, TTY_NORMAL);
}
} else {
for (i=0; i<count; i++) {
@@ -542,26 +541,21 @@ static inline void sci_receive_chars(struct uart_port *port,
}
/* Store data and status */
- tty->flip.char_buf_ptr[i] = c;
if (status&SCxSR_FER(port)) {
- tty->flip.flag_buf_ptr[i] = TTY_FRAME;
+ flag = TTY_FRAME;
pr_debug("sci: frame error\n");
} else if (status&SCxSR_PER(port)) {
- tty->flip.flag_buf_ptr[i] = TTY_PARITY;
+ flag = TTY_PARITY;
pr_debug("sci: parity error\n");
- } else {
- tty->flip.flag_buf_ptr[i] = TTY_NORMAL;
- }
+ } else
+ flag = TTY_NORMAL;
+ tty_insert_flip_char(tty, c, flag);
}
}
sci_in(port, SCxSR); /* dummy read */
sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
- /* Update the kernel buffer end */
- tty->flip.count += count;
- tty->flip.char_buf_ptr += count;
- tty->flip.flag_buf_ptr += count;
copied += count;
port->icount.rx += count;
}
@@ -608,48 +602,45 @@ static inline int sci_handle_errors(struct uart_port *port)
unsigned short status = sci_in(port, SCxSR);
struct tty_struct *tty = port->info->tty;
- if (status&SCxSR_ORER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_ORER(port)) {
/* overrun error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+ copied++;
pr_debug("sci: overrun error\n");
}
- if (status&SCxSR_FER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_FER(port)) {
if (sci_rxd_in(port) == 0) {
/* Notify of BREAK */
struct sci_port * sci_port = (struct sci_port *)port;
- if(!sci_port->break_flag) {
- sci_port->break_flag = 1;
- sci_schedule_break_timer((struct sci_port *)port);
+ if(!sci_port->break_flag) {
+ sci_port->break_flag = 1;
+ sci_schedule_break_timer((struct sci_port *)port);
/* Do sysrq handling. */
- if(uart_handle_break(port)) {
+ if(uart_handle_break(port))
return 0;
- }
pr_debug("sci: BREAK detected\n");
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+ copied++;
}
}
else {
/* frame error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ if(tty_insert_flip_char(tty, 0, TTY_FRAME))
+ copied++;
pr_debug("sci: frame error\n");
}
}
- if (status&SCxSR_PER(port) && tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if (status&SCxSR_PER(port)) {
+ if(tty_insert_flip_char(tty, 0, TTY_PARITY))
+ copied++;
/* parity error */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
pr_debug("sci: parity error\n");
}
- if (copied) {
- tty->flip.count += copied;
+ if (copied)
tty_flip_buffer_push(tty);
- }
return copied;
}
@@ -661,15 +652,14 @@ static inline int sci_handle_breaks(struct uart_port *port)
struct tty_struct *tty = port->info->tty;
struct sci_port *s = &sci_ports[port->line];
- if (!s->break_flag && status & SCxSR_BRK(port) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if (!s->break_flag && status & SCxSR_BRK(port))
#if defined(CONFIG_CPU_SH3)
/* Debounce break */
s->break_flag = 1;
#endif
/* Notify of BREAK */
- copied++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+ copied++;
pr_debug("sci: BREAK detected\n");
}
@@ -677,19 +667,15 @@ static inline int sci_handle_breaks(struct uart_port *port)
/* XXX: Handle SCIF overrun error */
if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
sci_out(port, SCLSR, 0);
- if(tty->flip.count<TTY_FLIPBUF_SIZE) {
+ if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
copied++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
pr_debug("sci: overrun error\n");
}
}
#endif
- if (copied) {
- tty->flip.count += copied;
+ if (copied)
tty_flip_buffer_push(tty);
- }
-
return copied;
}
@@ -732,12 +718,9 @@ static irqreturn_t sci_er_interrupt(int irq, void *ptr, struct pt_regs *regs)
struct tty_struct *tty = port->info->tty;
sci_out(port, SCLSR, 0);
- if(tty->flip.count<TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- tty->flip.count++;
- tty_flip_buffer_push(tty);
- pr_debug("scif: overrun error\n");
- }
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ tty_flip_buffer_push(tty);
+ pr_debug("scif: overrun error\n");
}
#endif
sci_rx_interrupt(irq, ptr, regs);
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 313f9df24a2d..5468e5a767e2 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -519,11 +519,7 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
/* record the character to pass up to the tty layer */
if (tty) {
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- if (tty->flip.count == TTY_FLIPBUF_SIZE)
+ if(tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
break;
}
port->sc_port.icount.rx++;
diff --git a/drivers/serial/suncore.c b/drivers/serial/suncore.c
index 5fc4a62173d9..fa4ae94243c2 100644
--- a/drivers/serial/suncore.c
+++ b/drivers/serial/suncore.c
@@ -34,6 +34,7 @@ sunserial_console_termios(struct console *con)
char *mode_prop = "ttyX-mode";
char *cd_prop = "ttyX-ignore-cd";
char *dtr_prop = "ttyX-rts-dtr-off";
+ char *ssp_console_modes_prop = "ssp-console-modes";
int baud, bits, stop, cflag;
char parity;
int carrier = 0;
@@ -43,14 +44,39 @@ sunserial_console_termios(struct console *con)
if (!serial_console)
return;
- if (serial_console == 1) {
+ switch (serial_console) {
+ case PROMDEV_OTTYA:
mode_prop[3] = 'a';
cd_prop[3] = 'a';
dtr_prop[3] = 'a';
- } else {
+ break;
+
+ case PROMDEV_OTTYB:
mode_prop[3] = 'b';
cd_prop[3] = 'b';
dtr_prop[3] = 'b';
+ break;
+
+ case PROMDEV_ORSC:
+
+ nd = prom_pathtoinode("rsc");
+ if (!nd) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ if (!prom_node_has_property(nd, ssp_console_modes_prop)) {
+ strcpy(mode, "115200,8,n,1,-");
+ goto no_options;
+ }
+
+ memset(mode, 0, sizeof(mode));
+ prom_getstring(nd, ssp_console_modes_prop, mode, sizeof(mode));
+ goto no_options;
+
+ default:
+ strcpy(mode, "9600,8,n,1,-");
+ goto no_options;
}
topnd = prom_getchild(prom_root_node);
@@ -110,6 +136,10 @@ no_options:
case 9600: cflag |= B9600; break;
case 19200: cflag |= B19200; break;
case 38400: cflag |= B38400; break;
+ case 57600: cflag |= B57600; break;
+ case 115200: cflag |= B115200; break;
+ case 230400: cflag |= B230400; break;
+ case 460800: cflag |= B460800; break;
default: baud = 9600; cflag |= B9600; break;
}
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index ba9381fd3f2d..8bcaebcc0ad7 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -159,21 +159,14 @@ receive_chars(struct uart_sunsab_port *up,
saw_console_brk = 1;
for (i = 0; i < count; i++) {
- unsigned char ch = buf[i];
+ unsigned char ch = buf[i], flag;
if (tty == NULL) {
uart_handle_sysrq_char(&up->port, ch, regs);
continue;
}
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return tty; // if TTY_DONT_FLIP is set
- }
-
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(stat->sreg.isr0 & (SAB82532_ISR0_PERR |
@@ -209,34 +202,21 @@ receive_chars(struct uart_sunsab_port *up,
stat->sreg.isr1 &= ((up->port.read_status_mask >> 8) & 0xff);
if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (stat->sreg.isr0 & SAB82532_ISR0_PERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (stat->sreg.isr0 & SAB82532_ISR0_FERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
continue;
if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&
- (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0){
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((stat->sreg.isr0 & SAB82532_ISR0_RFO) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ (stat->sreg.isr1 & ((up->port.ignore_status_mask >> 8) & 0xff)) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (stat->sreg.isr0 & SAB82532_ISR0_RFO)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
if (saw_console_brk)
@@ -917,9 +897,6 @@ static int sunsab_console_setup(struct console *con, char *options)
sunserial_console_termios(con);
- /* Firmware console speed is limited to 150-->38400 baud so
- * this hackish cflag thing is OK.
- */
switch (con->cflag & CBAUD) {
case B150: baud = 150; break;
case B300: baud = 300; break;
@@ -930,6 +907,10 @@ static int sunsab_console_setup(struct console *con, char *options)
default: case B9600: baud = 9600; break;
case B19200: baud = 19200; break;
case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
};
/*
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index f0738533f39a..9a3665b34d97 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -323,19 +323,13 @@ static _INLINE_ struct tty_struct *
receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs *regs)
{
struct tty_struct *tty = up->port.info->tty;
- unsigned char ch;
+ unsigned char ch, flag;
int max_count = 256;
int saw_console_brk = 0;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return tty; // if TTY_DONT_FLIP is set
- }
ch = serial_inp(up, UART_RX);
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
@@ -377,31 +371,23 @@ receive_chars(struct uart_sunsu_port *up, unsigned char *status, struct pt_regs
}
if (*status & UART_LSR_BI) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
+ if ((*status & up->port.ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+ if (*status & UART_LSR_OE)
/*
* Overrun is special, since it's reported
* immediately, and doesn't affect the current
* character.
*/
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
ignore_char:
*status = serial_inp(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 7653d6cf05af..3c72484adea7 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -319,7 +319,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
struct pt_regs *regs)
{
struct tty_struct *tty;
- unsigned char ch, r1;
+ unsigned char ch, r1, flag;
tty = NULL;
if (up->port.info != NULL && /* Unopened serial console */
@@ -362,19 +362,8 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
continue;
}
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- tty->flip.work.func((void *)tty);
- /*
- * The 8250 bails out of the loop here,
- * but we need to read everything, or die.
- */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- continue;
- }
-
/* A real serial line, record the character and status. */
- *tty->flip.char_buf_ptr = ch;
- *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ flag = TTY_NORMAL;
up->port.icount.rx++;
if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) {
if (r1 & BRK_ABRT) {
@@ -391,28 +380,21 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
up->port.icount.overrun++;
r1 &= up->port.read_status_mask;
if (r1 & BRK_ABRT)
- *tty->flip.flag_buf_ptr = TTY_BREAK;
+ flag = TTY_BREAK;
else if (r1 & PAR_ERR)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
+ flag = TTY_PARITY;
else if (r1 & CRC_ERR)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
+ flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
continue;
if (up->port.ignore_status_mask == 0xff ||
(r1 & up->port.ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((r1 & Rx_OVR) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
+ tty_insert_flip_char(tty, ch, flag);
}
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
return tty;
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c
deleted file mode 100644
index 47b504ff38b2..000000000000
--- a/drivers/serial/uart00.c
+++ /dev/null
@@ -1,782 +0,0 @@
-/*
- * linux/drivers/serial/uart00.c
- *
- * Driver for UART00 serial ports
- *
- * Based on drivers/char/serial_amba.c, by ARM Limited &
- * Deep Blue Solutions Ltd.
- * Copyright 2001 Altera Corporation
- *
- * Update for 2.6.4 by Dirk Behme <dirk.behme@de.bosch.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public 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
- *
- * $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $
- *
- */
-#include <linux/config.h>
-
-#if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/sizes.h>
-
-#include <asm/arch/excalibur.h>
-#define UART00_TYPE (volatile unsigned int*)
-#include <asm/arch/uart00.h>
-#include <asm/arch/int_ctrl00.h>
-
-#define UART_NR 2
-
-#define SERIAL_UART00_NAME "ttyUA"
-#define SERIAL_UART00_MAJOR 204
-#define SERIAL_UART00_MINOR 16 /* Temporary - will change in future */
-#define SERIAL_UART00_NR UART_NR
-#define UART_PORT_SIZE 0x50
-
-#define UART00_ISR_PASS_LIMIT 256
-
-/*
- * Access macros for the UART00 UARTs
- */
-#define UART_GET_INT_STATUS(p) inl(UART_ISR((p)->membase))
-#define UART_PUT_IES(p, c) outl(c,UART_IES((p)->membase))
-#define UART_GET_IES(p) inl(UART_IES((p)->membase))
-#define UART_PUT_IEC(p, c) outl(c,UART_IEC((p)->membase))
-#define UART_GET_IEC(p) inl(UART_IEC((p)->membase))
-#define UART_PUT_CHAR(p, c) outl(c,UART_TD((p)->membase))
-#define UART_GET_CHAR(p) inl(UART_RD((p)->membase))
-#define UART_GET_RSR(p) inl(UART_RSR((p)->membase))
-#define UART_GET_RDS(p) inl(UART_RDS((p)->membase))
-#define UART_GET_MSR(p) inl(UART_MSR((p)->membase))
-#define UART_GET_MCR(p) inl(UART_MCR((p)->membase))
-#define UART_PUT_MCR(p, c) outl(c,UART_MCR((p)->membase))
-#define UART_GET_MC(p) inl(UART_MC((p)->membase))
-#define UART_PUT_MC(p, c) outl(c,UART_MC((p)->membase))
-#define UART_GET_TSR(p) inl(UART_TSR((p)->membase))
-#define UART_GET_DIV_HI(p) inl(UART_DIV_HI((p)->membase))
-#define UART_PUT_DIV_HI(p,c) outl(c,UART_DIV_HI((p)->membase))
-#define UART_GET_DIV_LO(p) inl(UART_DIV_LO((p)->membase))
-#define UART_PUT_DIV_LO(p,c) outl(c,UART_DIV_LO((p)->membase))
-#define UART_RX_DATA(s) ((s) & UART_RSR_RX_LEVEL_MSK)
-#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)
-{
- UART_PUT_IEC(port, UART_IEC_TIE_MSK);
-}
-
-static void uart00_stop_rx(struct uart_port *port)
-{
- UART_PUT_IEC(port, UART_IEC_RE_MSK);
-}
-
-static void uart00_enable_ms(struct uart_port *port)
-{
- UART_PUT_IES(port, UART_IES_ME_MSK);
-}
-
-static void
-uart00_rx_chars(struct uart_port *port, struct pt_regs *regs)
-{
- struct tty_struct *tty = port->info->tty;
- unsigned int status, ch, rds, flg, ignored = 0;
-
- status = UART_GET_RSR(port);
- while (UART_RX_DATA(status)) {
- /*
- * We need to read rds before reading the
- * character from the fifo
- */
- rds = UART_GET_RDS(port);
- ch = UART_GET_CHAR(port);
- port->icount.rx++;
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- goto ignore_char;
-
- flg = TTY_NORMAL;
-
- /*
- * Note that the error handling code is
- * out of the main execution path
- */
- if (rds & (UART_RDS_BI_MSK |UART_RDS_FE_MSK|
- UART_RDS_PE_MSK |UART_RDS_PE_MSK))
- goto handle_error;
- if (uart_handle_sysrq_char(port, ch, regs))
- goto ignore_char;
-
- error_return:
- tty_insert_flip_char(tty, ch, flg);
-
- ignore_char:
- status = UART_GET_RSR(port);
- }
- out:
- tty_flip_buffer_push(tty);
- return;
-
- handle_error:
- if (rds & UART_RDS_BI_MSK) {
- status &= ~(UART_RDS_FE_MSK | UART_RDS_PE_MSK);
- port->icount.brk++;
- if (uart_handle_break(port))
- goto ignore_char;
- } else if (rds & UART_RDS_PE_MSK)
- port->icount.parity++;
- else if (rds & UART_RDS_FE_MSK)
- port->icount.frame++;
- if (rds & UART_RDS_OE_MSK)
- port->icount.overrun++;
-
- if (rds & port->ignore_status_mask) {
- if (++ignored > 100)
- goto out;
- goto ignore_char;
- }
- rds &= port->read_status_mask;
-
- if (rds & UART_RDS_BI_MSK)
- flg = TTY_BREAK;
- else if (rds & UART_RDS_PE_MSK)
- flg = TTY_PARITY;
- else if (rds & UART_RDS_FE_MSK)
- flg = TTY_FRAME;
-
- if (rds & UART_RDS_OE_MSK) {
- /*
- * CHECK: does overrun affect the current character?
- * ASSUMPTION: it does not.
- */
- tty_insert_flip_char(tty, ch, flg);
- ch = 0;
- flg = TTY_OVERRUN;
- }
-#ifdef SUPPORT_SYSRQ
- port->sysrq = 0;
-#endif
- goto error_return;
-}
-
-static void uart00_tx_chars(struct uart_port *port)
-{
- struct circ_buf *xmit = &port->info->xmit;
- int count;
-
- if (port->x_char) {
- while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
- barrier();
- UART_PUT_CHAR(port, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- uart00_stop_tx(port);
- return;
- }
-
- count = port->fifosize >> 1;
- do {
- while ((UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK) == 15)
- barrier();
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- if (uart_circ_empty(xmit))
- uart00_stop_tx(port);
-}
-
-static void uart00_start_tx(struct uart_port *port)
-{
- UART_PUT_IES(port, UART_IES_TIE_MSK);
- uart00_tx_chars(port);
-}
-
-static void uart00_modem_status(struct uart_port *port)
-{
- unsigned int status;
-
- status = UART_GET_MSR(port);
-
- if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK |
- UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)))
- return;
-
- if (status & UART_MSR_DDCD_MSK)
- uart_handle_dcd_change(port, status & UART_MSR_DCD_MSK);
-
- if (status & UART_MSR_DDSR_MSK)
- port->icount.dsr++;
-
- if (status & UART_MSR_DCTS_MSK)
- uart_handle_cts_change(port, status & UART_MSR_CTS_MSK);
-
- wake_up_interruptible(&port->info->delta_msr_wait);
-}
-
-static irqreturn_t uart00_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct uart_port *port = dev_id;
- unsigned int status, pass_counter = 0;
-
- status = UART_GET_INT_STATUS(port);
- do {
- if (status & UART_ISR_RI_MSK)
- uart00_rx_chars(port, regs);
- if (status & UART_ISR_MI_MSK)
- uart00_modem_status(port);
- if (status & (UART_ISR_TI_MSK | UART_ISR_TII_MSK))
- uart00_tx_chars(port);
- if (pass_counter++ > UART00_ISR_PASS_LIMIT)
- break;
-
- status = UART_GET_INT_STATUS(port);
- } while (status);
-
- return IRQ_HANDLED;
-}
-
-static unsigned int uart00_tx_empty(struct uart_port *port)
-{
- return UART_GET_TSR(port) & UART_TSR_TX_LEVEL_MSK? 0 : TIOCSER_TEMT;
-}
-
-static unsigned int uart00_get_mctrl(struct uart_port *port)
-{
- unsigned int result = 0;
- unsigned int status;
-
- status = UART_GET_MSR(port);
- if (status & UART_MSR_DCD_MSK)
- result |= TIOCM_CAR;
- if (status & UART_MSR_DSR_MSK)
- result |= TIOCM_DSR;
- if (status & UART_MSR_CTS_MSK)
- result |= TIOCM_CTS;
- if (status & UART_MSR_RI_MSK)
- result |= TIOCM_RI;
-
- return result;
-}
-
-static void uart00_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
-{
-}
-
-static void uart00_break_ctl(struct uart_port *port, int break_state)
-{
- unsigned long flags;
- unsigned int mcr;
-
- spin_lock_irqsave(&port->lock, flags);
- mcr = UART_GET_MCR(port);
- if (break_state == -1)
- mcr |= UART_MCR_BR_MSK;
- else
- mcr &= ~UART_MCR_BR_MSK;
- UART_PUT_MCR(port, mcr);
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void
-uart00_set_termios(struct uart_port *port, struct termios *termios,
- struct termios *old)
-{
- unsigned int uart_mc, old_ies, baud, quot;
- unsigned long flags;
-
- /*
- * We don't support CREAD (yet)
- */
- termios->c_cflag |= CREAD;
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- /* byte size and parity */
- switch (termios->c_cflag & CSIZE) {
- case CS5:
- uart_mc = UART_MC_CLS_CHARLEN_5;
- break;
- case CS6:
- uart_mc = UART_MC_CLS_CHARLEN_6;
- break;
- case CS7:
- uart_mc = UART_MC_CLS_CHARLEN_7;
- break;
- default: // CS8
- uart_mc = UART_MC_CLS_CHARLEN_8;
- break;
- }
- if (termios->c_cflag & CSTOPB)
- uart_mc|= UART_MC_ST_TWO;
- if (termios->c_cflag & PARENB) {
- uart_mc |= UART_MC_PE_MSK;
- if (!(termios->c_cflag & PARODD))
- uart_mc |= UART_MC_EP_MSK;
- }
-
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UART_RDS_OE_MSK;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
- if (termios->c_iflag & (BRKINT | PARMRK))
- port->read_status_mask |= UART_RDS_BI_MSK;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_RDS_FE_MSK | UART_RDS_PE_MSK;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= UART_RDS_BI_MSK;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns to (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_RDS_OE_MSK;
- }
-
- /* first, disable everything */
- old_ies = UART_GET_IES(port);
-
- if (UART_ENABLE_MS(port, termios->c_cflag))
- old_ies |= UART_IES_ME_MSK;
-
- /* Set baud rate */
- UART_PUT_DIV_LO(port, (quot & 0xff));
- UART_PUT_DIV_HI(port, ((quot & 0xf00) >> 8));
-
- UART_PUT_MC(port, uart_mc);
- UART_PUT_IES(port, old_ies);
-
- spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int uart00_startup(struct uart_port *port)
-{
- int result;
-
- /*
- * Allocate the IRQ
- */
- result = request_irq(port->irq, uart00_int, 0, "uart00", port);
- if (result) {
- printk(KERN_ERR "Request of irq %d failed\n", port->irq);
- return result;
- }
-
- /*
- * Finally, enable interrupts. Use the TII interrupt to minimise
- * the number of interrupts generated. If higher performance is
- * needed, consider using the TI interrupt with a suitable FIFO
- * threshold
- */
- UART_PUT_IES(port, UART_IES_RE_MSK | UART_IES_TIE_MSK);
-
- return 0;
-}
-
-static void uart00_shutdown(struct uart_port *port)
-{
- /*
- * disable all interrupts, disable the port
- */
- UART_PUT_IEC(port, 0xff);
-
- /* disable break condition and fifos */
- UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
-
- /*
- * Free the interrupt
- */
- free_irq(port->irq, port);
-}
-
-static const char *uart00_type(struct uart_port *port)
-{
- return port->type == PORT_UART00 ? "Altera UART00" : NULL;
-}
-
-/*
- * Release the memory region(s) being used by 'port'
- */
-static void uart00_release_port(struct uart_port *port)
-{
- release_mem_region(port->mapbase, UART_PORT_SIZE);
-
-#ifdef CONFIG_ARCH_CAMELOT
- if (port->membase != (void*)IO_ADDRESS(EXC_UART00_BASE)) {
- iounmap(port->membase);
- }
-#endif
-}
-
-/*
- * Request the memory region(s) being used by 'port'
- */
-static int uart00_request_port(struct uart_port *port)
-{
- return request_mem_region(port->mapbase, UART_PORT_SIZE, "serial_uart00")
- != NULL ? 0 : -EBUSY;
-}
-
-/*
- * Configure/autoconfigure the port.
- */
-static void uart00_config_port(struct uart_port *port, int flags)
-{
-
- /*
- * Map the io memory if this is a soft uart
- */
- if (!port->membase)
- port->membase = ioremap_nocache(port->mapbase,SZ_4K);
-
- if (!port->membase)
- printk(KERN_ERR "serial00: cannot map io memory\n");
- else
- port->type = PORT_UART00;
-
-}
-
-/*
- * verify the new serial_struct (for TIOCSSERIAL).
- */
-static int uart00_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- int ret = 0;
- if (ser->type != PORT_UNKNOWN && ser->type != PORT_UART00)
- ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= NR_IRQS)
- ret = -EINVAL;
- if (ser->baud_base < 9600)
- ret = -EINVAL;
- return ret;
-}
-
-static struct uart_ops uart00_pops = {
- .tx_empty = uart00_tx_empty,
- .set_mctrl = uart00_set_mctrl_null,
- .get_mctrl = uart00_get_mctrl,
- .stop_tx = uart00_stop_tx,
- .start_tx = uart00_start_tx,
- .stop_rx = uart00_stop_rx,
- .enable_ms = uart00_enable_ms,
- .break_ctl = uart00_break_ctl,
- .startup = uart00_startup,
- .shutdown = uart00_shutdown,
- .set_termios = uart00_set_termios,
- .type = uart00_type,
- .release_port = uart00_release_port,
- .request_port = uart00_request_port,
- .config_port = uart00_config_port,
- .verify_port = uart00_verify_port,
-};
-
-
-#ifdef CONFIG_ARCH_CAMELOT
-static struct uart_port epxa10db_port = {
- .membase = (void*)IO_ADDRESS(EXC_UART00_BASE),
- .mapbase = EXC_UART00_BASE,
- .iotype = SERIAL_IO_MEM,
- .irq = IRQ_UART,
- .uartclk = EXC_AHB2_CLK_FREQUENCY,
- .fifosize = 16,
- .ops = &uart00_pops,
- .flags = ASYNC_BOOT_AUTOCONF,
-};
-#endif
-
-
-#ifdef CONFIG_SERIAL_UART00_CONSOLE
-static void uart00_console_write(struct console *co, const char *s, unsigned count)
-{
-#ifdef CONFIG_ARCH_CAMELOT
- struct uart_port *port = &epxa10db_port;
- unsigned int status, old_ies;
- int i;
-
- /*
- * First save the CR then disable the interrupts
- */
- old_ies = UART_GET_IES(port);
- UART_PUT_IEC(port,0xff);
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++) {
- do {
- status = UART_GET_TSR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, s[i]);
- if (s[i] == '\n') {
- do {
- status = UART_GET_TSR(port);
- } while (!UART_TX_READY(status));
- UART_PUT_CHAR(port, '\r');
- }
- }
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IES
- */
- do {
- status = UART_GET_TSR(port);
- } while (status & UART_TSR_TX_LEVEL_MSK);
- UART_PUT_IES(port, old_ies);
-#endif
-}
-
-static void __init
-uart00_console_get_options(struct uart_port *port, int *baud,
- int *parity, int *bits)
-{
- unsigned int uart_mc, quot;
-
- uart_mc = UART_GET_MC(port);
-
- *parity = 'n';
- if (uart_mc & UART_MC_PE_MSK) {
- if (uart_mc & UART_MC_EP_MSK)
- *parity = 'e';
- else
- *parity = 'o';
- }
-
- switch (uart_mc & UART_MC_CLS_MSK) {
- case UART_MC_CLS_CHARLEN_5:
- *bits = 5;
- break;
- case UART_MC_CLS_CHARLEN_6:
- *bits = 6;
- break;
- case UART_MC_CLS_CHARLEN_7:
- *bits = 7;
- break;
- case UART_MC_CLS_CHARLEN_8:
- *bits = 8;
- break;
- }
- quot = UART_GET_DIV_LO(port) | (UART_GET_DIV_HI(port) << 8);
- *baud = port->uartclk / (16 *quot );
-}
-
-static int __init uart00_console_setup(struct console *co, char *options)
-{
- struct uart_port *port;
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
-#ifdef CONFIG_ARCH_CAMELOT
- port = &epxa10db_port; ;
-#else
- return -ENODEV;
-#endif
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else
- uart00_console_get_options(port, &baud, &parity, &bits);
-
- return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-extern struct uart_driver uart00_reg;
-static struct console uart00_console = {
- .name = SERIAL_UART00_NAME,
- .write = uart00_console_write,
- .device = uart_console_device,
- .setup = uart00_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = 0,
- .data = &uart00_reg,
-};
-
-static int __init uart00_console_init(void)
-{
- register_console(&uart00_console);
- return 0;
-}
-console_initcall(uart00_console_init);
-
-#define UART00_CONSOLE &uart00_console
-#else
-#define UART00_CONSOLE NULL
-#endif
-
-static struct uart_driver uart00_reg = {
- .owner = NULL,
- .driver_name = SERIAL_UART00_NAME,
- .dev_name = SERIAL_UART00_NAME,
- .major = SERIAL_UART00_MAJOR,
- .minor = SERIAL_UART00_MINOR,
- .nr = UART_NR,
- .cons = UART00_CONSOLE,
-};
-
-struct dev_port_entry{
- unsigned int base_addr;
- struct uart_port *port;
-};
-
-#ifdef CONFIG_PLD_HOTSWAP
-
-static struct dev_port_entry dev_port_map[UART_NR];
-
-/*
- * Keep a mapping of dev_info addresses -> port lines to use when
- * removing ports dev==NULL indicates unused entry
- */
-
-struct uart00_ps_data{
- unsigned int clk;
- unsigned int fifosize;
-};
-
-int uart00_add_device(struct pldhs_dev_info* dev_info, void* dev_ps_data)
-{
- struct uart00_ps_data* dev_ps=dev_ps_data;
- struct uart_port * port;
- int i,result;
-
- i=0;
- while(dev_port_map[i].port)
- i++;
-
- if(i==UART_NR){
- printk(KERN_WARNING "uart00: Maximum number of ports reached\n");
- return 0;
- }
-
- port=kmalloc(sizeof(struct uart_port),GFP_KERNEL);
- if(!port)
- return -ENOMEM;
-
- printk("clk=%d fifo=%d\n",dev_ps->clk,dev_ps->fifosize);
- port->membase=0;
- port->mapbase=dev_info->base_addr;
- port->iotype=SERIAL_IO_MEM;
- port->irq=dev_info->irq;
- port->uartclk=dev_ps->clk;
- port->fifosize=dev_ps->fifosize;
- port->ops=&uart00_pops;
- port->line=i;
- port->flags=ASYNC_BOOT_AUTOCONF;
-
- result=uart_add_one_port(&uart00_reg, port);
- if(result){
- printk("uart_add_one_port returned %d\n",result);
- return result;
- }
- dev_port_map[i].base_addr=dev_info->base_addr;
- dev_port_map[i].port=port;
- printk("uart00: added device at %x as ttyUA%d\n",dev_port_map[i].base_addr,i);
- return 0;
-
-}
-
-int uart00_remove_devices(void)
-{
- int i,result;
-
-
- result=0;
- for(i=1;i<UART_NR;i++){
- if(dev_port_map[i].base_addr){
- result=uart_remove_one_port(&uart00_reg, dev_port_map[i].port);
- if(result)
- return result;
-
- /* port removed sucessfully, so now tidy up */
- kfree(dev_port_map[i].port);
- dev_port_map[i].base_addr=0;
- dev_port_map[i].port=NULL;
- }
- }
- return 0;
-
-}
-
-struct pld_hotswap_ops uart00_pldhs_ops={
- .name = "uart00",
- .add_device = uart00_add_device,
- .remove_devices = uart00_remove_devices,
-};
-
-#endif
-
-static int __init uart00_init(void)
-{
- int result;
-
- printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");
-
- printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"
- " - these WILL change in the future\n");
-
- result = uart_register_driver(&uart00_reg);
- if (result)
- return result;
-#ifdef CONFIG_ARCH_CAMELOT
- result = uart_add_one_port(&uart00_reg,&epxa10db_port);
-#endif
- if (result)
- uart_unregister_driver(&uart00_reg);
-
-#ifdef CONFIG_PLD_HOTSWAP
- pldhs_register_driver(&uart00_pldhs_ops);
-#endif
- return result;
-}
-
-__initcall(uart00_init);
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 865d4dea65df..d61494d185cd 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Serial Interface Unit.
*
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* Based on drivers/serial/8250.c, by Russell King.
*
@@ -371,11 +371,6 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status,
lsr = *status;
do {
- if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if (tty->low_latency)
- tty_flip_buffer_push(tty);
- }
-
ch = siu_read(port, UART_RX);
port->icount.rx++;
flag = TTY_NORMAL;
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 7bdab2a7f59c..94b229031198 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv)
{
drv->drv.name = drv->name;
drv->drv.bus = &superhyway_bus_type;
- drv->drv.probe = superhyway_device_probe;
- drv->drv.remove = superhyway_device_remove;
return driver_register(&drv->drv);
}
@@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = {
#ifdef CONFIG_SYSFS
.dev_attrs = superhyway_dev_attrs,
#endif
+ .probe = superhyway_device_probe,
+ .remove = superhyway_device_remove,
};
static int __init superhyway_bus_init(void)
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
index 13b8d249da5c..d95265b187a3 100644
--- a/drivers/sn/Kconfig
+++ b/drivers/sn/Kconfig
@@ -17,4 +17,18 @@ config SGI_IOC4
If you have an SGI Altix with an IOC4-based
I/O controller say Y. Otherwise say N.
+config SGI_IOC3
+ tristate "SGI IOC3 Base IO support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2)
+ default m
+ ---help---
+ This option enables basic support for the SGI IOC3-based Base IO
+ controller card. This option does not enable any specific
+ functions on such a card, but provides necessary infrastructure
+ for other drivers to utilize.
+
+ If you have an SGI Altix with an IOC3-based
+ I/O controller or a PCI IOC3 serial card say Y.
+ Otherwise say N.
+
endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index c2a284185372..2cda011597c0 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_SGI_IOC4) += ioc4.o
+obj-$(CONFIG_SGI_IOC3) += ioc3.o
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
new file mode 100644
index 000000000000..aaa009f4a7bf
--- /dev/null
+++ b/drivers/sn/ioc3.c
@@ -0,0 +1,851 @@
+/*
+ * SGI IOC3 master driver and IRQ demuxer
+ *
+ * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
+ * Heavily based on similar work by:
+ * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
+ * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ioc3.h>
+#include <linux/rwsem.h>
+
+#define IOC3_PCI_SIZE 0x100000
+
+static LIST_HEAD(ioc3_devices);
+static int ioc3_counter;
+static DECLARE_RWSEM(ioc3_devices_rwsem);
+
+static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
+static struct ioc3_submodule *ioc3_ethernet;
+static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED;
+
+/* NIC probing code */
+
+#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
+
+static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
+{
+ return (pulse << 10) | (sample << 2);
+}
+
+static int nic_wait(struct ioc3_driver_data *idd)
+{
+ volatile unsigned mcr;
+
+ do {
+ mcr = (volatile unsigned)idd->vma->mcr;
+ } while (!(mcr & 2));
+
+ return mcr & 1;
+}
+
+static int nic_reset(struct ioc3_driver_data *idd)
+{
+ int presence;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ idd->vma->mcr = mcr_pack(500, 65);
+ presence = nic_wait(idd);
+ local_irq_restore(flags);
+
+ udelay(500);
+
+ return presence;
+}
+
+static inline int nic_read_bit(struct ioc3_driver_data *idd)
+{
+ int result;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ idd->vma->mcr = mcr_pack(6, 13);
+ result = nic_wait(idd);
+ local_irq_restore(flags);
+
+ udelay(500);
+
+ return result;
+}
+
+static inline void nic_write_bit(struct ioc3_driver_data *idd, int bit)
+{
+ if (bit)
+ idd->vma->mcr = mcr_pack(6, 110);
+ else
+ idd->vma->mcr = mcr_pack(80, 30);
+
+ nic_wait(idd);
+}
+
+static unsigned nic_read_byte(struct ioc3_driver_data *idd)
+{
+ unsigned result = 0;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ result = (result >> 1) | (nic_read_bit(idd) << 7);
+
+ return result;
+}
+
+static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
+{
+ int i, bit;
+
+ for (i = 8; i; i--) {
+ bit = byte & 1;
+ byte >>= 1;
+
+ nic_write_bit(idd, bit);
+ }
+}
+
+static unsigned long
+nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
+{
+ int a, b, index, disc;
+
+ nic_reset(idd);
+
+ /* Search ROM. */
+ nic_write_byte(idd, 0xF0);
+
+ /* Algorithm from ``Book of iButton Standards''. */
+ for (index = 0, disc = 0; index < 64; index++) {
+ a = nic_read_bit(idd);
+ b = nic_read_bit(idd);
+
+ if (a && b) {
+ printk(KERN_WARNING "IOC3 NIC search failed.\n");
+ *last = 0;
+ return 0;
+ }
+
+ if (!a && !b) {
+ if (index == *last) {
+ addr |= 1UL << index;
+ } else if (index > *last) {
+ addr &= ~(1UL << index);
+ disc = index;
+ } else if ((addr & (1UL << index)) == 0)
+ disc = index;
+ nic_write_bit(idd, (addr>>index)&1);
+ continue;
+ } else {
+ if (a)
+ addr |= 1UL << index;
+ else
+ addr &= ~(1UL << index);
+ nic_write_bit(idd, a);
+ continue;
+ }
+ }
+ *last = disc;
+ return addr;
+}
+
+static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ int index;
+
+ nic_reset(idd);
+ nic_write_byte(idd, 0xF0);
+ for (index = 0; index < 64; index++) {
+ nic_read_bit(idd);
+ nic_read_bit(idd);
+ nic_write_bit(idd, (addr>>index)&1);
+ }
+}
+
+static void crc16_byte(unsigned int *crc, unsigned char db)
+{
+ int i;
+
+ for(i=0;i<8;i++) {
+ *crc <<= 1;
+ if((db^(*crc>>16)) & 1)
+ *crc ^= 0x8005;
+ db >>= 1;
+ }
+ *crc &= 0xFFFF;
+}
+
+static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc)
+{
+ while(size--)
+ crc16_byte(&crc, *(dbs++));
+ return crc;
+}
+
+static void crc8_byte(unsigned int *crc, unsigned char db)
+{
+ int i,f;
+
+ for(i=0;i<8;i++) {
+ f = (*crc ^ db) & 1;
+ *crc >>= 1;
+ db >>= 1;
+ if(f)
+ *crc ^= 0x8c;
+ }
+ *crc &= 0xff;
+}
+
+static unsigned int crc8_addr(unsigned long addr)
+{
+ int i;
+ unsigned int crc = 0x00;
+
+ for(i=0;i<8;i++)
+ crc8_byte(&crc, addr>>(i<<3));
+ return crc;
+}
+
+static void
+read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page,
+ unsigned char *redir, unsigned char *data)
+{
+ int loops = 16, i;
+
+ while(redir[page] != 0xFF) {
+ page = redir[page]^0xFF;
+ loops--;
+ if(loops<0) {
+ printk(KERN_ERR "IOC3: NIC circular redirection\n");
+ return;
+ }
+ }
+ loops = 3;
+ while(loops>0) {
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xF0);
+ nic_write_byte(idd, (page << 5) & 0xE0);
+ nic_write_byte(idd, (page >> 3) & 0x1F);
+ for(i=0;i<0x20;i++)
+ data[i] = nic_read_byte(idd);
+ if(crc16_area(data, 0x20, 0x0000) == 0x800d)
+ return;
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in data page\n");
+ for(i=0;i<0x20;i++)
+ data[i] = 0x00;
+}
+
+static void
+read_redir_map(struct ioc3_driver_data *idd, unsigned long addr,
+ unsigned char *redir)
+{
+ int i,j,loops = 3,crc_ok;
+ unsigned int crc;
+
+ while(loops>0) {
+ crc_ok = 1;
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xAA);
+ nic_write_byte(idd, 0x00);
+ nic_write_byte(idd, 0x01);
+ for(i=0;i<64;i+=8) {
+ for(j=0;j<8;j++)
+ redir[i+j] = nic_read_byte(idd);
+ crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000);
+ crc16_byte(&crc, nic_read_byte(idd));
+ crc16_byte(&crc, nic_read_byte(idd));
+ if(crc != 0x800d)
+ crc_ok = 0;
+ }
+ if(crc_ok)
+ return;
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in redirection page\n");
+ for(i=0;i<64;i++)
+ redir[i] = 0xFF;
+}
+
+static void read_nic(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ unsigned char redir[64];
+ unsigned char data[64],part[32];
+ int i,j;
+
+ /* read redirections */
+ read_redir_map(idd, addr, redir);
+ /* read data pages */
+ read_redir_page(idd, addr, 0, redir, data);
+ read_redir_page(idd, addr, 1, redir, data+32);
+ /* assemble the part # */
+ j=0;
+ for(i=0;i<19;i++)
+ if(data[i+11] != ' ')
+ part[j++] = data[i+11];
+ for(i=0;i<6;i++)
+ if(data[i+32] != ' ')
+ part[j++] = data[i+32];
+ part[j] = 0;
+ /* skip Octane power supplies */
+ if(!strncmp(part, "060-0035-", 9))
+ return;
+ if(!strncmp(part, "060-0038-", 9))
+ return;
+ strcpy(idd->nic_part, part);
+ /* assemble the serial # */
+ j=0;
+ for(i=0;i<10;i++)
+ if(data[i+1] != ' ')
+ idd->nic_serial[j++] = data[i+1];
+ idd->nic_serial[j] = 0;
+}
+
+static void read_mac(struct ioc3_driver_data *idd, unsigned long addr)
+{
+ int i, loops = 3;
+ unsigned char data[13];
+
+ while(loops>0) {
+ nic_addr(idd, addr);
+ nic_write_byte(idd, 0xF0);
+ nic_write_byte(idd, 0x00);
+ nic_write_byte(idd, 0x00);
+ nic_read_byte(idd);
+ for(i=0;i<13;i++)
+ data[i] = nic_read_byte(idd);
+ if(crc16_area(data, 13, 0x0000) == 0x800d) {
+ for(i=10;i>4;i--)
+ idd->nic_mac[10-i] = data[i];
+ return;
+ }
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in MAC address\n");
+ for(i=0;i<6;i++)
+ idd->nic_mac[i] = 0x00;
+}
+
+static void probe_nic(struct ioc3_driver_data *idd)
+{
+ int save = 0, loops = 3;
+ unsigned long first, addr;
+
+ idd->vma->gpcr_s = GPCR_MLAN_EN;
+
+ while(loops>0) {
+ idd->nic_part[0] = 0;
+ idd->nic_serial[0] = 0;
+ addr = first = nic_find(idd, &save, 0);
+ if(!first)
+ return;
+ while(1) {
+ if(crc8_addr(addr))
+ break;
+ else {
+ switch(addr & 0xFF) {
+ case 0x0B:
+ read_nic(idd, addr);
+ break;
+ case 0x09:
+ case 0x89:
+ case 0x91:
+ read_mac(idd, addr);
+ break;
+ }
+ }
+ addr = nic_find(idd, &save, addr);
+ if(addr == first)
+ return;
+ }
+ loops--;
+ }
+ printk(KERN_ERR "IOC3: CRC error in NIC address\n");
+}
+
+/* Interrupts */
+
+static inline void
+write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&idd->ir_lock, flags);
+ switch (which) {
+ case IOC3_W_IES:
+ writel(val, &idd->vma->sio_ies);
+ break;
+ case IOC3_W_IEC:
+ writel(val, &idd->vma->sio_iec);
+ break;
+ }
+ spin_unlock_irqrestore(&idd->ir_lock, flags);
+}
+static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd)
+{
+ unsigned long flag;
+ uint32_t intrs = 0;
+
+ spin_lock_irqsave(&idd->ir_lock, flag);
+ intrs = readl(&idd->vma->sio_ir);
+ intrs &= readl(&idd->vma->sio_ies);
+ spin_unlock_irqrestore(&idd->ir_lock, flag);
+ return intrs;
+}
+
+static irqreturn_t ioc3_intr_io(int irq, void *arg, struct pt_regs *regs)
+{
+ unsigned long flags;
+ struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
+ int handled = 1, id;
+ unsigned int pending;
+
+ read_lock_irqsave(&ioc3_submodules_lock, flags);
+
+ if(idd->dual_irq && idd->vma->eisr) {
+ /* send Ethernet IRQ to the driver */
+ if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
+ ioc3_ethernet->intr) {
+ handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
+ idd, 0, regs);
+ }
+ }
+ pending = get_pending_intrs(idd); /* look at the IO IRQs */
+
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++) {
+ if(idd->active[id] && ioc3_submodules[id]
+ && (pending & ioc3_submodules[id]->irq_mask)
+ && ioc3_submodules[id]->intr) {
+ write_ireg(idd, ioc3_submodules[id]->irq_mask,
+ IOC3_W_IEC);
+ if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
+ idd, pending & ioc3_submodules[id]->irq_mask,
+ regs))
+ pending &= ~ioc3_submodules[id]->irq_mask;
+ if (ioc3_submodules[id]->reset_mask)
+ write_ireg(idd, ioc3_submodules[id]->irq_mask,
+ IOC3_W_IES);
+ }
+ }
+ read_unlock_irqrestore(&ioc3_submodules_lock, flags);
+ if(pending) {
+ printk(KERN_WARNING
+ "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending);
+ write_ireg(idd, pending, IOC3_W_IEC);
+ handled = 1;
+ }
+ return handled?IRQ_HANDLED:IRQ_NONE;
+}
+
+static irqreturn_t ioc3_intr_eth(int irq, void *arg, struct pt_regs *regs)
+{
+ unsigned long flags;
+ struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
+ int handled = 1;
+
+ if(!idd->dual_irq)
+ return IRQ_NONE;
+ read_lock_irqsave(&ioc3_submodules_lock, flags);
+ if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
+ && ioc3_ethernet->intr)
+ handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0,
+ regs);
+ read_unlock_irqrestore(&ioc3_submodules_lock, flags);
+ return handled?IRQ_HANDLED:IRQ_NONE;
+}
+
+void ioc3_enable(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd, unsigned int irqs)
+{
+ write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES);
+}
+
+void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd,
+ unsigned int irqs)
+{
+ writel(irqs & is->irq_mask, &idd->vma->sio_ir);
+}
+
+void ioc3_disable(struct ioc3_submodule *is,
+ struct ioc3_driver_data *idd, unsigned int irqs)
+{
+ write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC);
+}
+
+void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&idd->gpio_lock, flags);
+ writel(val, &idd->vma->gpcr_s);
+ spin_unlock_irqrestore(&idd->gpio_lock, flags);
+}
+
+/* Keep it simple, stupid! */
+static int find_slot(void **tab, int max)
+{
+ int i;
+ for(i=0;i<max;i++)
+ if(!(tab[i]))
+ return i;
+ return -1;
+}
+
+/* Register an IOC3 submodule */
+int ioc3_register_submodule(struct ioc3_submodule *is)
+{
+ struct ioc3_driver_data *idd;
+ int alloc_id;
+ unsigned long flags;
+
+ write_lock_irqsave(&ioc3_submodules_lock, flags);
+ alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
+ if(alloc_id != -1) {
+ ioc3_submodules[alloc_id] = is;
+ if(is->ethernet) {
+ if(ioc3_ethernet==NULL)
+ ioc3_ethernet=is;
+ else
+ printk(KERN_WARNING
+ "IOC3 Ethernet module already registered!\n");
+ }
+ }
+ write_unlock_irqrestore(&ioc3_submodules_lock, flags);
+
+ if(alloc_id == -1) {
+ printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
+ return -ENOMEM;
+ }
+
+ is->id=alloc_id;
+
+ /* Initialize submodule for each IOC3 */
+ if (!is->probe)
+ return 0;
+
+ down_read(&ioc3_devices_rwsem);
+ list_for_each_entry(idd, &ioc3_devices, list) {
+ /* set to 1 for IRQs in probe */
+ idd->active[alloc_id] = 1;
+ idd->active[alloc_id] = !is->probe(is, idd);
+ }
+ up_read(&ioc3_devices_rwsem);
+
+ return 0;
+}
+
+/* Unregister an IOC3 submodule */
+void ioc3_unregister_submodule(struct ioc3_submodule *is)
+{
+ struct ioc3_driver_data *idd;
+ unsigned long flags;
+
+ write_lock_irqsave(&ioc3_submodules_lock, flags);
+ if(ioc3_submodules[is->id]==is)
+ ioc3_submodules[is->id]=NULL;
+ else
+ printk(KERN_WARNING
+ "IOC3 submodule %s has wrong ID.\n",is->name);
+ if(ioc3_ethernet==is)
+ ioc3_ethernet = NULL;
+ write_unlock_irqrestore(&ioc3_submodules_lock, flags);
+
+ /* Remove submodule for each IOC3 */
+ down_read(&ioc3_devices_rwsem);
+ list_for_each_entry(idd, &ioc3_devices, list)
+ if(idd->active[is->id]) {
+ if(is->remove)
+ if(is->remove(is, idd))
+ printk(KERN_WARNING
+ "%s: IOC3 submodule %s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__, module_name(is->owner),
+ pci_name(idd->pdev));
+ idd->active[is->id] = 0;
+ if(is->irq_mask)
+ write_ireg(idd, is->irq_mask, IOC3_W_IEC);
+ }
+ up_read(&ioc3_devices_rwsem);
+}
+
+/*********************
+ * Device management *
+ *********************/
+
+static char *
+ioc3_class_names[]={"unknown", "IP27 BaseIO", "IP30 system", "MENET 1/2/3",
+ "MENET 4", "CADduo", "Altix Serial"};
+
+static int ioc3_class(struct ioc3_driver_data *idd)
+{
+ int res = IOC3_CLASS_NONE;
+ /* NIC-based logic */
+ if(!strncmp(idd->nic_part, "030-0891-", 9))
+ res = IOC3_CLASS_BASE_IP30;
+ if(!strncmp(idd->nic_part, "030-1155-", 9))
+ res = IOC3_CLASS_CADDUO;
+ if(!strncmp(idd->nic_part, "030-1657-", 9))
+ res = IOC3_CLASS_SERIAL;
+ if(!strncmp(idd->nic_part, "030-1664-", 9))
+ res = IOC3_CLASS_SERIAL;
+ /* total random heuristics */
+#ifdef CONFIG_SGI_IP27
+ if(!idd->nic_part[0])
+ res = IOC3_CLASS_BASE_IP27;
+#endif
+ /* print educational message */
+ printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n",
+ idd->nic_part, idd->nic_serial, ioc3_class_names[res]);
+ return res;
+}
+/* Adds a new instance of an IOC3 card */
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+ struct ioc3_driver_data *idd;
+ uint32_t pcmd;
+ int ret, id;
+
+ /* Enable IOC3 and take ownership of it */
+ if ((ret = pci_enable_device(pdev))) {
+ printk(KERN_WARNING
+ "%s: Failed to enable IOC3 device for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ goto out;
+ }
+ pci_set_master(pdev);
+
+#ifdef USE_64BIT_DMA
+ ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (!ret) {
+ ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+ if (ret < 0) {
+ printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
+ "for consistent allocations\n",
+ __FUNCTION__);
+ }
+ }
+#endif
+
+ /* Set up per-IOC3 data */
+ idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
+ if (!idd) {
+ printk(KERN_WARNING
+ "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_idd;
+ }
+ memset(idd, 0, sizeof(struct ioc3_driver_data));
+ spin_lock_init(&idd->ir_lock);
+ spin_lock_init(&idd->gpio_lock);
+ idd->pdev = pdev;
+
+ /* Map all IOC3 registers. These are shared between subdevices
+ * so the main IOC3 module manages them.
+ */
+ idd->pma = pci_resource_start(pdev, 0);
+ if (!idd->pma) {
+ printk(KERN_WARNING
+ "%s: Unable to find IOC3 resource "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ if (!request_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
+ printk(KERN_WARNING
+ "%s: Unable to request IOC3 region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE);
+ if (!idd->vma) {
+ printk(KERN_WARNING
+ "%s: Unable to remap IOC3 region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_misc_region;
+ }
+
+ /* Track PCI-device specific data */
+ pci_set_drvdata(pdev, idd);
+ down_write(&ioc3_devices_rwsem);
+ list_add(&idd->list, &ioc3_devices);
+ idd->id = ioc3_counter++;
+ up_write(&ioc3_devices_rwsem);
+
+ idd->gpdr_shadow = idd->vma->gpdr;
+
+ /* Read IOC3 NIC contents */
+ probe_nic(idd);
+
+ /* Detect IOC3 class */
+ idd->class = ioc3_class(idd);
+
+ /* Initialize IOC3 */
+ pci_read_config_dword(pdev, PCI_COMMAND, &pcmd);
+ pci_write_config_dword(pdev, PCI_COMMAND,
+ pcmd | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_PARITY | PCI_COMMAND_SERR |
+ PCI_SCR_DROP_MODE_EN);
+
+ write_ireg(idd, ~0, IOC3_W_IEC);
+ writel(~0, &idd->vma->sio_ir);
+
+ /* Set up IRQs */
+ if(idd->class == IOC3_CLASS_BASE_IP30
+ || idd->class == IOC3_CLASS_BASE_IP27) {
+ writel(0, &idd->vma->eier);
+ writel(~0, &idd->vma->eisr);
+
+ idd->dual_irq = 1;
+ if (!request_irq(pdev->irq, ioc3_intr_eth, SA_SHIRQ,
+ "ioc3-eth", (void *)idd)) {
+ idd->irq_eth = pdev->irq;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq);
+ }
+ if (!request_irq(pdev->irq+2, ioc3_intr_io, SA_SHIRQ,
+ "ioc3-io", (void *)idd)) {
+ idd->irq_io = pdev->irq+2;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq+2);
+ }
+ } else {
+ if (!request_irq(pdev->irq, ioc3_intr_io, SA_SHIRQ,
+ "ioc3", (void *)idd)) {
+ idd->irq_io = pdev->irq;
+ } else {
+ printk(KERN_WARNING
+ "%s : request_irq fails for IRQ 0x%x\n ",
+ __FUNCTION__, pdev->irq);
+ }
+ }
+
+ /* Add this IOC3 to all submodules */
+ read_lock(&ioc3_submodules_lock);
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++)
+ if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
+ idd->active[id] = 1;
+ idd->active[id] = !ioc3_submodules[id]->probe
+ (ioc3_submodules[id], idd);
+ }
+ read_unlock(&ioc3_submodules_lock);
+
+ printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
+
+ return 0;
+
+out_misc_region:
+ release_region(idd->pma, IOC3_PCI_SIZE);
+out_pci:
+ kfree(idd);
+out_idd:
+ pci_disable_device(pdev);
+out:
+ return ret;
+}
+
+/* Removes a particular instance of an IOC3 card. */
+static void ioc3_remove(struct pci_dev *pdev)
+{
+ int id;
+ struct ioc3_driver_data *idd;
+
+ idd = pci_get_drvdata(pdev);
+
+ /* Remove this IOC3 from all submodules */
+ read_lock(&ioc3_submodules_lock);
+ for(id=0;id<IOC3_MAX_SUBMODULES;id++)
+ if(idd->active[id]) {
+ if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
+ if(ioc3_submodules[id]->remove(ioc3_submodules[id],
+ idd))
+ printk(KERN_WARNING
+ "%s: IOC3 submodule 0x%s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__,
+ module_name(ioc3_submodules[id]->owner),
+ pci_name(pdev));
+ idd->active[id] = 0;
+ }
+ read_unlock(&ioc3_submodules_lock);
+
+ /* Clear and disable all IRQs */
+ write_ireg(idd, ~0, IOC3_W_IEC);
+ writel(~0, &idd->vma->sio_ir);
+
+ /* Release resources */
+ free_irq(idd->irq_io, (void *)idd);
+ if(idd->dual_irq)
+ free_irq(idd->irq_eth, (void *)idd);
+ iounmap(idd->vma);
+ release_region(idd->pma, IOC3_PCI_SIZE);
+
+ /* Disable IOC3 and relinquish */
+ pci_disable_device(pdev);
+
+ /* Remove and free driver data */
+ down_write(&ioc3_devices_rwsem);
+ list_del(&idd->list);
+ up_write(&ioc3_devices_rwsem);
+ kfree(idd);
+}
+
+static struct pci_device_id ioc3_id_table[] = {
+ {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID},
+ {0}
+};
+
+static struct pci_driver ioc3_driver = {
+ .name = "IOC3",
+ .id_table = ioc3_id_table,
+ .probe = ioc3_probe,
+ .remove = ioc3_remove,
+};
+
+MODULE_DEVICE_TABLE(pci, ioc3_id_table);
+
+/*********************
+ * Module management *
+ *********************/
+
+/* Module load */
+static int __devinit ioc3_init(void)
+{
+ if (ia64_platform_is("sn2"))
+ return pci_register_driver(&ioc3_driver);
+ return 0;
+}
+
+/* Module unload */
+static void __devexit ioc3_exit(void)
+{
+ pci_unregister_driver(&ioc3_driver);
+}
+
+module_init(ioc3_init);
+module_exit(ioc3_exit);
+
+MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
+MODULE_DESCRIPTION("PCI driver for SGI IOC3");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc3_register_submodule);
+EXPORT_SYMBOL(ioc3_unregister_submodule);
+EXPORT_SYMBOL(ioc3_ack);
+EXPORT_SYMBOL(ioc3_gpcr_set);
+EXPORT_SYMBOL(ioc3_disable);
+EXPORT_SYMBOL(ioc3_enable);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
new file mode 100644
index 000000000000..b77dbd63e596
--- /dev/null
+++ b/drivers/spi/Kconfig
@@ -0,0 +1,109 @@
+#
+# SPI driver configuration
+#
+# NOTE: the reason this doesn't show SPI slave support is mostly that
+# nobody's needed a slave side API yet. The master-role API is not
+# fully appropriate there, so it'd need some thought to do well.
+#
+menu "SPI support"
+
+config SPI
+ bool "SPI support"
+ help
+ The "Serial Peripheral Interface" is a low level synchronous
+ protocol. Chips that support SPI can have data transfer rates
+ up to several tens of Mbit/sec. Chips are addressed with a
+ controller and a chipselect. Most SPI slaves don't support
+ dynamic device discovery; some are even write-only or read-only.
+
+ SPI is widely used by microcontollers to talk with sensors,
+ eeprom and flash memory, codecs and various other controller
+ chips, analog to digital (and d-to-a) converters, and more.
+ MMC and SD cards can be accessed using SPI protocol; and for
+ DataFlash cards used in MMC sockets, SPI must always be used.
+
+ SPI is one of a family of similar protocols using a four wire
+ interface (select, clock, data in, data out) including Microwire
+ (half duplex), SSP, SSI, and PSP. This driver framework should
+ work with most such devices and controllers.
+
+config SPI_DEBUG
+ boolean "Debug support for SPI drivers"
+ depends on SPI && DEBUG_KERNEL
+ help
+ Say "yes" to enable debug messaging (like dev_dbg and pr_debug),
+ sysfs, and debugfs support in SPI controller and protocol drivers.
+
+#
+# MASTER side ... talking to discrete SPI slave chips including microcontrollers
+#
+
+config SPI_MASTER
+# boolean "SPI Master Support"
+ boolean
+ default SPI
+ help
+ If your system has an master-capable SPI controller (which
+ provides the clock and chipselect), you can enable that
+ controller and the protocol drivers for the SPI slave chips
+ that are connected.
+
+comment "SPI Master Controller Drivers"
+ depends on SPI_MASTER
+
+config SPI_BITBANG
+ tristate "Bitbanging SPI master"
+ depends on SPI_MASTER && EXPERIMENTAL
+ help
+ With a few GPIO pins, your system can bitbang the SPI protocol.
+ Select this to get SPI support through I/O pins (GPIO, parallel
+ port, etc). Or, some systems' SPI master controller drivers use
+ this code to manage the per-word or per-transfer accesses to the
+ hardware shift registers.
+
+ This is library code, and is automatically selected by drivers that
+ need it. You only need to select this explicitly to support driver
+ modules that aren't part of this kernel tree.
+
+config SPI_BUTTERFLY
+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This uses a custom parallel port cable to connect to an AVR
+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an
+ inexpensive battery powered microcontroller evaluation board.
+ This same cable can be used to flash new firmware.
+
+config SPI_BUTTERFLY
+ tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)"
+ depends on SPI_MASTER && PARPORT && EXPERIMENTAL
+ select SPI_BITBANG
+ help
+ This uses a custom parallel port cable to connect to an AVR
+ Butterfly <http://www.atmel.com/products/avr/butterfly>, an
+ inexpensive battery powered microcontroller evaluation board.
+ This same cable can be used to flash new firmware.
+
+#
+# Add new SPI master controllers in alphabetical order above this line
+#
+
+
+#
+# There are lots of SPI device types, with sensors and memory
+# being probably the most widely used ones.
+#
+comment "SPI Protocol Masters"
+ depends on SPI_MASTER
+
+
+#
+# Add new SPI protocol masters in alphabetical order above this line
+#
+
+
+# (slave support would go here)
+
+endmenu # "SPI support"
+
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
new file mode 100644
index 000000000000..c2c87e845abf
--- /dev/null
+++ b/drivers/spi/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for kernel SPI drivers.
+#
+
+ifeq ($(CONFIG_SPI_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+# small core, mostly translating board-specific
+# config declarations into driver model code
+obj-$(CONFIG_SPI_MASTER) += spi.o
+
+# SPI master controller drivers (bus)
+obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
+obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
+# ... add above this line ...
+
+# SPI protocol drivers (device/link on bus)
+# ... add above this line ...
+
+# SPI slave controller drivers (upstream link)
+# ... add above this line ...
+
+# SPI slave drivers (protocol for that link)
+# ... add above this line ...
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
new file mode 100644
index 000000000000..791c4dc550ae
--- /dev/null
+++ b/drivers/spi/spi.c
@@ -0,0 +1,642 @@
+/*
+ * spi.c - SPI init/core code
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/spi/spi.h>
+
+
+/* SPI bustype and spi_master class are registered after board init code
+ * provides the SPI device tables, ensuring that both are present by the
+ * time controller driver registration causes spi_devices to "enumerate".
+ */
+static void spidev_release(struct device *dev)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ /* spi masters may cleanup for released devices */
+ if (spi->master->cleanup)
+ spi->master->cleanup(spi);
+
+ spi_master_put(spi->master);
+ kfree(dev);
+}
+
+static ssize_t
+modalias_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias);
+}
+
+static struct device_attribute spi_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
+/* modalias support makes "modprobe $MODALIAS" new-style hotplug work,
+ * and the sysfs version makes coldplug work too.
+ */
+
+static int spi_match_device(struct device *dev, struct device_driver *drv)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
+}
+
+static int spi_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ const struct spi_device *spi = to_spi_device(dev);
+
+ envp[0] = buffer;
+ snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias);
+ envp[1] = NULL;
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+/*
+ * NOTE: the suspend() method for an spi_master controller driver
+ * should verify that all its child devices are marked as suspended;
+ * suspend requests delivered through sysfs power/state files don't
+ * enforce such constraints.
+ */
+static int spi_suspend(struct device *dev, pm_message_t message)
+{
+ int value;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ if (!drv->suspend)
+ return 0;
+
+ /* suspend will stop irqs and dma; no more i/o */
+ value = drv->suspend(to_spi_device(dev), message);
+ if (value == 0)
+ dev->power.power_state = message;
+ return value;
+}
+
+static int spi_resume(struct device *dev)
+{
+ int value;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ if (!drv->resume)
+ return 0;
+
+ /* resume may restart the i/o queue */
+ value = drv->resume(to_spi_device(dev));
+ if (value == 0)
+ dev->power.power_state = PMSG_ON;
+ return value;
+}
+
+#else
+#define spi_suspend NULL
+#define spi_resume NULL
+#endif
+
+struct bus_type spi_bus_type = {
+ .name = "spi",
+ .dev_attrs = spi_dev_attrs,
+ .match = spi_match_device,
+ .uevent = spi_uevent,
+ .suspend = spi_suspend,
+ .resume = spi_resume,
+};
+EXPORT_SYMBOL_GPL(spi_bus_type);
+
+
+static int spi_drv_probe(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ return sdrv->probe(to_spi_device(dev));
+}
+
+static int spi_drv_remove(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ return sdrv->remove(to_spi_device(dev));
+}
+
+static void spi_drv_shutdown(struct device *dev)
+{
+ const struct spi_driver *sdrv = to_spi_driver(dev->driver);
+
+ sdrv->shutdown(to_spi_device(dev));
+}
+
+int spi_register_driver(struct spi_driver *sdrv)
+{
+ sdrv->driver.bus = &spi_bus_type;
+ if (sdrv->probe)
+ sdrv->driver.probe = spi_drv_probe;
+ if (sdrv->remove)
+ sdrv->driver.remove = spi_drv_remove;
+ if (sdrv->shutdown)
+ sdrv->driver.shutdown = spi_drv_shutdown;
+ return driver_register(&sdrv->driver);
+}
+EXPORT_SYMBOL_GPL(spi_register_driver);
+
+/*-------------------------------------------------------------------------*/
+
+/* SPI devices should normally not be created by SPI device drivers; that
+ * would make them board-specific. Similarly with SPI master drivers.
+ * Device registration normally goes into like arch/.../mach.../board-YYY.c
+ * with other readonly (flashable) information about mainboard devices.
+ */
+
+struct boardinfo {
+ struct list_head list;
+ unsigned n_board_info;
+ struct spi_board_info board_info[0];
+};
+
+static LIST_HEAD(board_list);
+static DECLARE_MUTEX(board_lock);
+
+
+/* On typical mainboards, this is purely internal; and it's not needed
+ * after board init creates the hard-wired devices. Some development
+ * platforms may not be able to use spi_register_board_info though, and
+ * this is exported so that for example a USB or parport based adapter
+ * driver could add devices (which it would learn about out-of-band).
+ */
+struct spi_device *__init_or_module
+spi_new_device(struct spi_master *master, struct spi_board_info *chip)
+{
+ struct spi_device *proxy;
+ struct device *dev = master->cdev.dev;
+ int status;
+
+ /* NOTE: caller did any chip->bus_num checks necessary */
+
+ if (!spi_master_get(master))
+ return NULL;
+
+ proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
+ if (!proxy) {
+ dev_err(dev, "can't alloc dev for cs%d\n",
+ chip->chip_select);
+ goto fail;
+ }
+ proxy->master = master;
+ proxy->chip_select = chip->chip_select;
+ proxy->max_speed_hz = chip->max_speed_hz;
+ proxy->irq = chip->irq;
+ proxy->modalias = chip->modalias;
+
+ snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
+ "%s.%u", master->cdev.class_id,
+ chip->chip_select);
+ proxy->dev.parent = dev;
+ proxy->dev.bus = &spi_bus_type;
+ proxy->dev.platform_data = (void *) chip->platform_data;
+ proxy->controller_data = chip->controller_data;
+ proxy->controller_state = NULL;
+ proxy->dev.release = spidev_release;
+
+ /* drivers may modify this default i/o setup */
+ status = master->setup(proxy);
+ if (status < 0) {
+ dev_dbg(dev, "can't %s %s, status %d\n",
+ "setup", proxy->dev.bus_id, status);
+ goto fail;
+ }
+
+ /* driver core catches callers that misbehave by defining
+ * devices that already exist.
+ */
+ status = device_register(&proxy->dev);
+ if (status < 0) {
+ dev_dbg(dev, "can't %s %s, status %d\n",
+ "add", proxy->dev.bus_id, status);
+ goto fail;
+ }
+ dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
+ return proxy;
+
+fail:
+ spi_master_put(master);
+ kfree(proxy);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spi_new_device);
+
+/*
+ * Board-specific early init code calls this (probably during arch_initcall)
+ * with segments of the SPI device table. Any device nodes are created later,
+ * after the relevant parent SPI controller (bus_num) is defined. We keep
+ * this table of devices forever, so that reloading a controller driver will
+ * not make Linux forget about these hard-wired devices.
+ *
+ * Other code can also call this, e.g. a particular add-on board might provide
+ * SPI devices through its expansion connector, so code initializing that board
+ * would naturally declare its SPI devices.
+ *
+ * The board info passed can safely be __initdata ... but be careful of
+ * any embedded pointers (platform_data, etc), they're copied as-is.
+ */
+int __init
+spi_register_board_info(struct spi_board_info const *info, unsigned n)
+{
+ struct boardinfo *bi;
+
+ bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL);
+ if (!bi)
+ return -ENOMEM;
+ bi->n_board_info = n;
+ memcpy(bi->board_info, info, n * sizeof *info);
+
+ down(&board_lock);
+ list_add_tail(&bi->list, &board_list);
+ up(&board_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_register_board_info);
+
+/* FIXME someone should add support for a __setup("spi", ...) that
+ * creates board info from kernel command lines
+ */
+
+static void __init_or_module
+scan_boardinfo(struct spi_master *master)
+{
+ struct boardinfo *bi;
+ struct device *dev = master->cdev.dev;
+
+ down(&board_lock);
+ list_for_each_entry(bi, &board_list, list) {
+ struct spi_board_info *chip = bi->board_info;
+ unsigned n;
+
+ for (n = bi->n_board_info; n > 0; n--, chip++) {
+ if (chip->bus_num != master->bus_num)
+ continue;
+ /* some controllers only have one chip, so they
+ * might not use chipselects. otherwise, the
+ * chipselects are numbered 0..max.
+ */
+ if (chip->chip_select >= master->num_chipselect
+ && master->num_chipselect) {
+ dev_dbg(dev, "cs%d > max %d\n",
+ chip->chip_select,
+ master->num_chipselect);
+ continue;
+ }
+ (void) spi_new_device(master, chip);
+ }
+ }
+ up(&board_lock);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void spi_master_release(struct class_device *cdev)
+{
+ struct spi_master *master;
+
+ master = container_of(cdev, struct spi_master, cdev);
+ kfree(master);
+}
+
+static struct class spi_master_class = {
+ .name = "spi_master",
+ .owner = THIS_MODULE,
+ .release = spi_master_release,
+};
+
+
+/**
+ * spi_alloc_master - allocate SPI master controller
+ * @dev: the controller, possibly using the platform_bus
+ * @size: how much driver-private data to preallocate; the pointer to this
+ * memory is in the class_data field of the returned class_device,
+ * accessible with spi_master_get_devdata().
+ *
+ * This call is used only by SPI master controller drivers, which are the
+ * only ones directly touching chip registers. It's how they allocate
+ * an spi_master structure, prior to calling spi_add_master().
+ *
+ * This must be called from context that can sleep. It returns the SPI
+ * master structure on success, else NULL.
+ *
+ * The caller is responsible for assigning the bus number and initializing
+ * the master's methods before calling spi_add_master(); and (after errors
+ * adding the device) calling spi_master_put() to prevent a memory leak.
+ */
+struct spi_master * __init_or_module
+spi_alloc_master(struct device *dev, unsigned size)
+{
+ struct spi_master *master;
+
+ if (!dev)
+ return NULL;
+
+ master = kzalloc(size + sizeof *master, SLAB_KERNEL);
+ if (!master)
+ return NULL;
+
+ class_device_initialize(&master->cdev);
+ master->cdev.class = &spi_master_class;
+ master->cdev.dev = get_device(dev);
+ spi_master_set_devdata(master, &master[1]);
+
+ return master;
+}
+EXPORT_SYMBOL_GPL(spi_alloc_master);
+
+/**
+ * spi_register_master - register SPI master controller
+ * @master: initialized master, originally from spi_alloc_master()
+ *
+ * SPI master controllers connect to their drivers using some non-SPI bus,
+ * such as the platform bus. The final stage of probe() in that code
+ * includes calling spi_register_master() to hook up to this SPI bus glue.
+ *
+ * SPI controllers use board specific (often SOC specific) bus numbers,
+ * and board-specific addressing for SPI devices combines those numbers
+ * with chip select numbers. Since SPI does not directly support dynamic
+ * device identification, boards need configuration tables telling which
+ * chip is at which address.
+ *
+ * This must be called from context that can sleep. It returns zero on
+ * success, else a negative error code (dropping the master's refcount).
+ * After a successful return, the caller is responsible for calling
+ * spi_unregister_master().
+ */
+int __init_or_module
+spi_register_master(struct spi_master *master)
+{
+ static atomic_t dyn_bus_id = ATOMIC_INIT(0);
+ struct device *dev = master->cdev.dev;
+ int status = -ENODEV;
+ int dynamic = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ /* convention: dynamically assigned bus IDs count down from the max */
+ if (master->bus_num == 0) {
+ master->bus_num = atomic_dec_return(&dyn_bus_id);
+ dynamic = 1;
+ }
+
+ /* register the device, then userspace will see it.
+ * registration fails if the bus ID is in use.
+ */
+ snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+ "spi%u", master->bus_num);
+ status = class_device_add(&master->cdev);
+ if (status < 0)
+ goto done;
+ dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+ dynamic ? " (dynamic)" : "");
+
+ /* populate children from any spi device tables */
+ scan_boardinfo(master);
+ status = 0;
+done:
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_register_master);
+
+
+static int __unregister(struct device *dev, void *unused)
+{
+ /* note: before about 2.6.14-rc1 this would corrupt memory: */
+ spi_unregister_device(to_spi_device(dev));
+ return 0;
+}
+
+/**
+ * spi_unregister_master - unregister SPI master controller
+ * @master: the master being unregistered
+ *
+ * This call is used only by SPI master controller drivers, which are the
+ * only ones directly touching chip registers.
+ *
+ * This must be called from context that can sleep.
+ */
+void spi_unregister_master(struct spi_master *master)
+{
+ (void) device_for_each_child(master->cdev.dev, NULL, __unregister);
+ class_device_unregister(&master->cdev);
+ master->cdev.dev = NULL;
+}
+EXPORT_SYMBOL_GPL(spi_unregister_master);
+
+/**
+ * spi_busnum_to_master - look up master associated with bus_num
+ * @bus_num: the master's bus number
+ *
+ * This call may be used with devices that are registered after
+ * arch init time. It returns a refcounted pointer to the relevant
+ * spi_master (which the caller must release), or NULL if there is
+ * no such master registered.
+ */
+struct spi_master *spi_busnum_to_master(u16 bus_num)
+{
+ if (bus_num) {
+ char name[8];
+ struct kobject *bus;
+
+ snprintf(name, sizeof name, "spi%u", bus_num);
+ bus = kset_find_obj(&spi_master_class.subsys.kset, name);
+ if (bus)
+ return container_of(bus, struct spi_master, cdev.kobj);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(spi_busnum_to_master);
+
+
+/*-------------------------------------------------------------------------*/
+
+static void spi_complete(void *arg)
+{
+ complete(arg);
+}
+
+/**
+ * spi_sync - blocking/synchronous SPI data transfers
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers
+ *
+ * This call may only be used from a context that may sleep. The sleep
+ * is non-interruptible, and has no timeout. Low-overhead controller
+ * drivers may DMA directly into and out of the message buffers.
+ *
+ * Note that the SPI device's chip select is active during the message,
+ * and then is normally disabled between messages. Drivers for some
+ * frequently-used devices may want to minimize costs of selecting a chip,
+ * by leaving it selected in anticipation that the next message will go
+ * to the same chip. (That may increase power usage.)
+ *
+ * Also, the caller is guaranteeing that the memory associated with the
+ * message will not be freed before this call returns.
+ *
+ * The return value is a negative error code if the message could not be
+ * submitted, else zero. When the value is zero, then message->status is
+ * also defined: it's the completion code for the transfer, either zero
+ * or a negative error code from the controller driver.
+ */
+int spi_sync(struct spi_device *spi, struct spi_message *message)
+{
+ DECLARE_COMPLETION(done);
+ int status;
+
+ message->complete = spi_complete;
+ message->context = &done;
+ status = spi_async(spi, message);
+ if (status == 0)
+ wait_for_completion(&done);
+ message->context = NULL;
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_sync);
+
+#define SPI_BUFSIZ (SMP_CACHE_BYTES)
+
+static u8 *buf;
+
+/**
+ * spi_write_then_read - SPI synchronous write followed by read
+ * @spi: device with which data will be exchanged
+ * @txbuf: data to be written (need not be dma-safe)
+ * @n_tx: size of txbuf, in bytes
+ * @rxbuf: buffer into which data will be read
+ * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
+ *
+ * This performs a half duplex MicroWire style transaction with the
+ * device, sending txbuf and then reading rxbuf. The return value
+ * is zero for success, else a negative errno status code.
+ * This call may only be used from a context that may sleep.
+ *
+ * Parameters to this routine are always copied using a small buffer;
+ * performance-sensitive or bulk transfer code should instead use
+ * spi_{async,sync}() calls with dma-safe buffers.
+ */
+int spi_write_then_read(struct spi_device *spi,
+ const u8 *txbuf, unsigned n_tx,
+ u8 *rxbuf, unsigned n_rx)
+{
+ static DECLARE_MUTEX(lock);
+
+ int status;
+ struct spi_message message;
+ struct spi_transfer x[2];
+ u8 *local_buf;
+
+ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
+ * (as a pure convenience thing), but we can keep heap costs
+ * out of the hot path ...
+ */
+ if ((n_tx + n_rx) > SPI_BUFSIZ)
+ return -EINVAL;
+
+ spi_message_init(&message);
+ memset(x, 0, sizeof x);
+ if (n_tx) {
+ x[0].len = n_tx;
+ spi_message_add_tail(&x[0], &message);
+ }
+ if (n_rx) {
+ x[1].len = n_rx;
+ spi_message_add_tail(&x[1], &message);
+ }
+
+ /* ... unless someone else is using the pre-allocated buffer */
+ if (down_trylock(&lock)) {
+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
+ if (!local_buf)
+ return -ENOMEM;
+ } else
+ local_buf = buf;
+
+ memcpy(local_buf, txbuf, n_tx);
+ x[0].tx_buf = local_buf;
+ x[1].rx_buf = local_buf + n_tx;
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0) {
+ memcpy(rxbuf, x[1].rx_buf, n_rx);
+ status = message.status;
+ }
+
+ if (x[0].tx_buf == buf)
+ up(&lock);
+ else
+ kfree(local_buf);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_write_then_read);
+
+/*-------------------------------------------------------------------------*/
+
+static int __init spi_init(void)
+{
+ int status;
+
+ buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL);
+ if (!buf) {
+ status = -ENOMEM;
+ goto err0;
+ }
+
+ status = bus_register(&spi_bus_type);
+ if (status < 0)
+ goto err1;
+
+ status = class_register(&spi_master_class);
+ if (status < 0)
+ goto err2;
+ return 0;
+
+err2:
+ bus_unregister(&spi_bus_type);
+err1:
+ kfree(buf);
+ buf = NULL;
+err0:
+ return status;
+}
+
+/* board_info is normally registered in arch_initcall(),
+ * but even essential drivers wait till later
+ *
+ * REVISIT only boardinfo really needs static linking. the rest (device and
+ * driver registration) _could_ be dynamically linked (modular) ... costs
+ * include needing to have boardinfo data structures be much more public.
+ */
+subsys_initcall(spi_init);
+
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
new file mode 100644
index 000000000000..f037e5593269
--- /dev/null
+++ b/drivers/spi/spi_bitbang.c
@@ -0,0 +1,472 @@
+/*
+ * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support.
+ * Use this for GPIO or shift-register level hardware APIs.
+ *
+ * spi_bitbang_cs is in spi_device->controller_state, which is unavailable
+ * to glue code. These bitbang setup() and cleanup() routines are always
+ * used, though maybe they're called from controller-aware code.
+ *
+ * chipselect() and friends may use use spi_device->controller_data and
+ * controller registers as appropriate.
+ *
+ *
+ * NOTE: SPI controller pins can often be used as GPIO pins instead,
+ * which means you could use a bitbang driver either to get hardware
+ * working quickly, or testing for differences that aren't speed related.
+ */
+
+struct spi_bitbang_cs {
+ unsigned nsecs; /* (clock cycle time)/2 */
+ u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs,
+ u32 word, u8 bits);
+ unsigned (*txrx_bufs)(struct spi_device *,
+ u32 (*txrx_word)(
+ struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned, struct spi_transfer *);
+};
+
+static unsigned bitbang_txrx_8(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u8 *tx = t->tx_buf;
+ u8 *rx = t->rx_buf;
+
+ while (likely(count > 0)) {
+ u8 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 1;
+ }
+ return t->len - count;
+}
+
+static unsigned bitbang_txrx_16(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u16 *tx = t->tx_buf;
+ u16 *rx = t->rx_buf;
+
+ while (likely(count > 1)) {
+ u16 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 2;
+ }
+ return t->len - count;
+}
+
+static unsigned bitbang_txrx_32(
+ struct spi_device *spi,
+ u32 (*txrx_word)(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits),
+ unsigned ns,
+ struct spi_transfer *t
+) {
+ unsigned bits = spi->bits_per_word;
+ unsigned count = t->len;
+ const u32 *tx = t->tx_buf;
+ u32 *rx = t->rx_buf;
+
+ while (likely(count > 3)) {
+ u32 word = 0;
+
+ if (tx)
+ word = *tx++;
+ word = txrx_word(spi, ns, word, bits);
+ if (rx)
+ *rx++ = word;
+ count -= 4;
+ }
+ return t->len - count;
+}
+
+/**
+ * spi_bitbang_setup - default setup for per-word I/O loops
+ */
+int spi_bitbang_setup(struct spi_device *spi)
+{
+ struct spi_bitbang_cs *cs = spi->controller_state;
+ struct spi_bitbang *bitbang;
+
+ if (!spi->max_speed_hz)
+ return -EINVAL;
+
+ if (!cs) {
+ cs = kzalloc(sizeof *cs, SLAB_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+ spi->controller_state = cs;
+ }
+ bitbang = spi_master_get_devdata(spi->master);
+
+ if (!spi->bits_per_word)
+ spi->bits_per_word = 8;
+
+ /* spi_transfer level calls that work per-word */
+ if (spi->bits_per_word <= 8)
+ cs->txrx_bufs = bitbang_txrx_8;
+ else if (spi->bits_per_word <= 16)
+ cs->txrx_bufs = bitbang_txrx_16;
+ else if (spi->bits_per_word <= 32)
+ cs->txrx_bufs = bitbang_txrx_32;
+ else
+ return -EINVAL;
+
+ /* per-word shift register access, in hardware or bitbanging */
+ cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)];
+ if (!cs->txrx_word)
+ return -EINVAL;
+
+ /* nsecs = (clock period)/2 */
+ cs->nsecs = (1000000000/2) / (spi->max_speed_hz);
+ if (cs->nsecs > MAX_UDELAY_MS * 1000)
+ return -EINVAL;
+
+ dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n",
+ __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA),
+ spi->bits_per_word, 2 * cs->nsecs);
+
+ /* NOTE we _need_ to call chipselect() early, ideally with adapter
+ * setup, unless the hardware defaults cooperate to avoid confusion
+ * between normal (active low) and inverted chipselects.
+ */
+
+ /* deselect chip (low or high) */
+ spin_lock(&bitbang->lock);
+ if (!bitbang->busy) {
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(cs->nsecs);
+ }
+ spin_unlock(&bitbang->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_setup);
+
+/**
+ * spi_bitbang_cleanup - default cleanup for per-word I/O loops
+ */
+void spi_bitbang_cleanup(const struct spi_device *spi)
+{
+ kfree(spi->controller_state);
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_cleanup);
+
+static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+ struct spi_bitbang_cs *cs = spi->controller_state;
+ unsigned nsecs = cs->nsecs;
+
+ return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t);
+}
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * SECOND PART ... simple transfer queue runner.
+ *
+ * This costs a task context per controller, running the queue by
+ * performing each transfer in sequence. Smarter hardware can queue
+ * several DMA transfers at once, and process several controller queues
+ * in parallel; this driver doesn't match such hardware very well.
+ *
+ * Drivers can provide word-at-a-time i/o primitives, or provide
+ * transfer-at-a-time ones to leverage dma or fifo hardware.
+ */
+static void bitbang_work(void *_bitbang)
+{
+ struct spi_bitbang *bitbang = _bitbang;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ bitbang->busy = 1;
+ while (!list_empty(&bitbang->queue)) {
+ struct spi_message *m;
+ struct spi_device *spi;
+ unsigned nsecs;
+ struct spi_transfer *t = NULL;
+ unsigned tmp;
+ unsigned cs_change;
+ int status;
+
+ m = container_of(bitbang->queue.next, struct spi_message,
+ queue);
+ list_del_init(&m->queue);
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+
+ /* FIXME this is made-up ... the correct value is known to
+ * word-at-a-time bitbang code, and presumably chipselect()
+ * should enforce these requirements too?
+ */
+ nsecs = 100;
+
+ spi = m->spi;
+ tmp = 0;
+ cs_change = 1;
+ status = 0;
+
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ if (bitbang->shutdown) {
+ status = -ESHUTDOWN;
+ break;
+ }
+
+ /* set up default clock polarity, and activate chip;
+ * this implicitly updates clock and spi modes as
+ * previously recorded for this device via setup().
+ * (and also deselects any other chip that might be
+ * selected ...)
+ */
+ if (cs_change) {
+ bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
+ ndelay(nsecs);
+ }
+ cs_change = t->cs_change;
+ if (!t->tx_buf && !t->rx_buf && t->len) {
+ status = -EINVAL;
+ break;
+ }
+
+ /* transfer data. the lower level code handles any
+ * new dma mappings it needs. our caller always gave
+ * us dma-safe buffers.
+ */
+ if (t->len) {
+ /* REVISIT dma API still needs a designated
+ * DMA_ADDR_INVALID; ~0 might be better.
+ */
+ if (!m->is_dma_mapped)
+ t->rx_dma = t->tx_dma = 0;
+ status = bitbang->txrx_bufs(spi, t);
+ }
+ if (status != t->len) {
+ if (status > 0)
+ status = -EMSGSIZE;
+ break;
+ }
+ m->actual_length += status;
+ status = 0;
+
+ /* protocol tweaks before next transfer */
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+
+ if (!cs_change)
+ continue;
+ if (t->transfer_list.next == &m->transfers)
+ break;
+
+ /* sometimes a short mid-message deselect of the chip
+ * may be needed to terminate a mode or command
+ */
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ m->status = status;
+ m->complete(m->context);
+
+ /* normally deactivate chipselect ... unless no error and
+ * cs_change has hinted that the next message will probably
+ * be for this chip too.
+ */
+ if (!(status == 0 && cs_change)) {
+ ndelay(nsecs);
+ bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
+ ndelay(nsecs);
+ }
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ }
+ bitbang->busy = 0;
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+}
+
+/**
+ * spi_bitbang_transfer - default submit to transfer queue
+ */
+int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m)
+{
+ struct spi_bitbang *bitbang;
+ unsigned long flags;
+
+ m->actual_length = 0;
+ m->status = -EINPROGRESS;
+
+ bitbang = spi_master_get_devdata(spi->master);
+ if (bitbang->shutdown)
+ return -ESHUTDOWN;
+
+ spin_lock_irqsave(&bitbang->lock, flags);
+ list_add_tail(&m->queue, &bitbang->queue);
+ queue_work(bitbang->workqueue, &bitbang->work);
+ spin_unlock_irqrestore(&bitbang->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_transfer);
+
+/*----------------------------------------------------------------------*/
+
+/**
+ * spi_bitbang_start - start up a polled/bitbanging SPI master driver
+ * @bitbang: driver handle
+ *
+ * Caller should have zero-initialized all parts of the structure, and then
+ * provided callbacks for chip selection and I/O loops. If the master has
+ * a transfer method, its final step should call spi_bitbang_transfer; or,
+ * that's the default if the transfer routine is not initialized. It should
+ * also set up the bus number and number of chipselects.
+ *
+ * For i/o loops, provide callbacks either per-word (for bitbanging, or for
+ * hardware that basically exposes a shift register) or per-spi_transfer
+ * (which takes better advantage of hardware like fifos or DMA engines).
+ *
+ * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and
+ * spi_bitbang_cleanup to handle those spi master methods. Those methods are
+ * the defaults if the bitbang->txrx_bufs routine isn't initialized.
+ *
+ * This routine registers the spi_master, which will process requests in a
+ * dedicated task, keeping IRQs unblocked most of the time. To stop
+ * processing those requests, call spi_bitbang_stop().
+ */
+int spi_bitbang_start(struct spi_bitbang *bitbang)
+{
+ int status;
+
+ if (!bitbang->master || !bitbang->chipselect)
+ return -EINVAL;
+
+ INIT_WORK(&bitbang->work, bitbang_work, bitbang);
+ spin_lock_init(&bitbang->lock);
+ INIT_LIST_HEAD(&bitbang->queue);
+
+ if (!bitbang->master->transfer)
+ bitbang->master->transfer = spi_bitbang_transfer;
+ if (!bitbang->txrx_bufs) {
+ bitbang->use_dma = 0;
+ bitbang->txrx_bufs = spi_bitbang_bufs;
+ if (!bitbang->master->setup) {
+ bitbang->master->setup = spi_bitbang_setup;
+ bitbang->master->cleanup = spi_bitbang_cleanup;
+ }
+ } else if (!bitbang->master->setup)
+ return -EINVAL;
+
+ /* this task is the only thing to touch the SPI bits */
+ bitbang->busy = 0;
+ bitbang->workqueue = create_singlethread_workqueue(
+ bitbang->master->cdev.dev->bus_id);
+ if (bitbang->workqueue == NULL) {
+ status = -EBUSY;
+ goto err1;
+ }
+
+ /* driver may get busy before register() returns, especially
+ * if someone registered boardinfo for devices
+ */
+ status = spi_register_master(bitbang->master);
+ if (status < 0)
+ goto err2;
+
+ return status;
+
+err2:
+ destroy_workqueue(bitbang->workqueue);
+err1:
+ return status;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_start);
+
+/**
+ * spi_bitbang_stop - stops the task providing spi communication
+ */
+int spi_bitbang_stop(struct spi_bitbang *bitbang)
+{
+ unsigned limit = 500;
+
+ spin_lock_irq(&bitbang->lock);
+ bitbang->shutdown = 0;
+ while (!list_empty(&bitbang->queue) && limit--) {
+ spin_unlock_irq(&bitbang->lock);
+
+ dev_dbg(bitbang->master->cdev.dev, "wait for queue\n");
+ msleep(10);
+
+ spin_lock_irq(&bitbang->lock);
+ }
+ spin_unlock_irq(&bitbang->lock);
+ if (!list_empty(&bitbang->queue)) {
+ dev_err(bitbang->master->cdev.dev, "queue didn't empty\n");
+ return -EBUSY;
+ }
+
+ destroy_workqueue(bitbang->workqueue);
+
+ spi_unregister_master(bitbang->master);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_bitbang_stop);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
new file mode 100644
index 000000000000..79a3c59615ab
--- /dev/null
+++ b/drivers/spi/spi_butterfly.c
@@ -0,0 +1,423 @@
+/*
+ * spi_butterfly.c - parport-to-butterfly adapter
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/parport.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/flash.h>
+
+#include <linux/mtd/partitions.h>
+
+
+/*
+ * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
+ * with a battery powered AVR microcontroller and lots of goodies. You
+ * can use GCC to develop firmware for this.
+ *
+ * See Documentation/spi/butterfly for information about how to build
+ * and use this custom parallel port cable.
+ */
+
+#undef HAVE_USI /* nyet */
+
+
+/* DATA output bits (pins 2..9 == D0..D7) */
+#define butterfly_nreset (1 << 1) /* pin 3 */
+
+#define spi_sck_bit (1 << 0) /* pin 2 */
+#define spi_mosi_bit (1 << 7) /* pin 9 */
+
+#define usi_sck_bit (1 << 3) /* pin 5 */
+#define usi_mosi_bit (1 << 4) /* pin 6 */
+
+#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
+
+/* STATUS input bits */
+#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
+
+#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */
+
+/* CONTROL output bits */
+#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
+/* USI uses no chipselect */
+
+
+
+static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
+{
+ return spi->controller_data;
+}
+
+static inline int is_usidev(struct spi_device *spi)
+{
+#ifdef HAVE_USI
+ return spi->chip_select != 1;
+#else
+ return 0;
+#endif
+}
+
+
+struct butterfly {
+ /* REVISIT ... for now, this must be first */
+ struct spi_bitbang bitbang;
+
+ struct parport *port;
+ struct pardevice *pd;
+
+ u8 lastbyte;
+
+ struct spi_device *dataflash;
+ struct spi_device *butterfly;
+ struct spi_board_info info[2];
+
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * these routines may be slower than necessary because they're hiding
+ * the fact that there are two different SPI busses on this cable: one
+ * to the DataFlash chip (or AVR SPI controller), the other to the
+ * AVR USI controller.
+ */
+
+static inline void
+setsck(struct spi_device *spi, int is_on)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ u8 bit, byte = pp->lastbyte;
+
+ if (is_usidev(spi))
+ bit = usi_sck_bit;
+ else
+ bit = spi_sck_bit;
+
+ if (is_on)
+ byte |= bit;
+ else
+ byte &= ~bit;
+ parport_write_data(pp->port, byte);
+ pp->lastbyte = byte;
+}
+
+static inline void
+setmosi(struct spi_device *spi, int is_on)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ u8 bit, byte = pp->lastbyte;
+
+ if (is_usidev(spi))
+ bit = usi_mosi_bit;
+ else
+ bit = spi_mosi_bit;
+
+ if (is_on)
+ byte |= bit;
+ else
+ byte &= ~bit;
+ parport_write_data(pp->port, byte);
+ pp->lastbyte = byte;
+}
+
+static inline int getmiso(struct spi_device *spi)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+ int value;
+ u8 bit;
+
+ if (is_usidev(spi))
+ bit = usi_miso_bit;
+ else
+ bit = spi_miso_bit;
+
+ /* only STATUS_BUSY is NOT negated */
+ value = !(parport_read_status(pp->port) & bit);
+ return (bit == PARPORT_STATUS_BUSY) ? value : !value;
+}
+
+static void butterfly_chipselect(struct spi_device *spi, int value)
+{
+ struct butterfly *pp = spidev_to_pp(spi);
+
+ /* set default clock polarity */
+ if (value)
+ setsck(spi, spi->mode & SPI_CPOL);
+
+ /* no chipselect on this USI link config */
+ if (is_usidev(spi))
+ return;
+
+ /* here, value == "activate or not" */
+
+ /* most PARPORT_CONTROL_* bits are negated */
+ if (spi_cs_bit == PARPORT_CONTROL_INIT)
+ value = !value;
+
+ /* here, value == "bit value to write in control register" */
+
+ parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
+}
+
+
+/* we only needed to implement one mode here, and choose SPI_MODE_0 */
+
+#define spidelay(X) do{}while(0)
+//#define spidelay ndelay
+
+#define EXPAND_BITBANG_TXRX
+#include <linux/spi/spi_bitbang.h>
+
+static u32
+butterfly_txrx_word_mode0(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* override default partitioning with cmdlinepart */
+static struct mtd_partition partitions[] = { {
+ /* JFFS2 wants partitions of 4*N blocks for this device ... */
+
+ /* sector 0 = 8 pages * 264 bytes/page (1 block)
+ * sector 1 = 248 pages * 264 bytes/page
+ */
+ .name = "bookkeeping", // 66 KB
+ .offset = 0,
+ .size = (8 + 248) * 264,
+// .mask_flags = MTD_WRITEABLE,
+}, {
+ /* sector 2 = 256 pages * 264 bytes/page
+ * sectors 3-5 = 512 pages * 264 bytes/page
+ */
+ .name = "filesystem", // 462 KB
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+} };
+
+static struct flash_platform_data flash = {
+ .name = "butterflash",
+ .parts = partitions,
+ .nr_parts = ARRAY_SIZE(partitions),
+};
+
+
+/* REVISIT remove this ugly global and its "only one" limitation */
+static struct butterfly *butterfly;
+
+static void butterfly_attach(struct parport *p)
+{
+ struct pardevice *pd;
+ int status;
+ struct butterfly *pp;
+ struct spi_master *master;
+ struct platform_device *pdev;
+
+ if (butterfly)
+ return;
+
+ /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
+ * and no way to be selective about what it binds to.
+ */
+
+ /* FIXME where should master->cdev.dev come from?
+ * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc
+ * setting up a platform device like this is an ugly kluge...
+ */
+ pdev = platform_device_register_simple("butterfly", -1, NULL, 0);
+
+ master = spi_alloc_master(&pdev->dev, sizeof *pp);
+ if (!master) {
+ status = -ENOMEM;
+ goto done;
+ }
+ pp = spi_master_get_devdata(master);
+
+ /*
+ * SPI and bitbang hookup
+ *
+ * use default setup(), cleanup(), and transfer() methods; and
+ * only bother implementing mode 0. Start it later.
+ */
+ master->bus_num = 42;
+ master->num_chipselect = 2;
+
+ pp->bitbang.master = spi_master_get(master);
+ pp->bitbang.chipselect = butterfly_chipselect;
+ pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
+
+ /*
+ * parport hookup
+ */
+ pp->port = p;
+ pd = parport_register_device(p, "spi_butterfly",
+ NULL, NULL, NULL,
+ 0 /* FLAGS */, pp);
+ if (!pd) {
+ status = -ENOMEM;
+ goto clean0;
+ }
+ pp->pd = pd;
+
+ status = parport_claim(pd);
+ if (status < 0)
+ goto clean1;
+
+ /*
+ * Butterfly reset, powerup, run firmware
+ */
+ pr_debug("%s: powerup/reset Butterfly\n", p->name);
+
+ /* nCS for dataflash (this bit is inverted on output) */
+ parport_frob_control(pp->port, spi_cs_bit, 0);
+
+ /* stabilize power with chip in reset (nRESET), and
+ * both spi_sck_bit and usi_sck_bit clear (CPOL=0)
+ */
+ pp->lastbyte |= vcc_bits;
+ parport_write_data(pp->port, pp->lastbyte);
+ msleep(5);
+
+ /* take it out of reset; assume long reset delay */
+ pp->lastbyte |= butterfly_nreset;
+ parport_write_data(pp->port, pp->lastbyte);
+ msleep(100);
+
+
+ /*
+ * Start SPI ... for now, hide that we're two physical busses.
+ */
+ status = spi_bitbang_start(&pp->bitbang);
+ if (status < 0)
+ goto clean2;
+
+ /* Bus 1 lets us talk to at45db041b (firmware disables AVR)
+ * or AVR (firmware resets at45, acts as spi slave)
+ */
+ pp->info[0].max_speed_hz = 15 * 1000 * 1000;
+ strcpy(pp->info[0].modalias, "mtd_dataflash");
+ pp->info[0].platform_data = &flash;
+ pp->info[0].chip_select = 1;
+ pp->info[0].controller_data = pp;
+ pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
+ if (pp->dataflash)
+ pr_debug("%s: dataflash at %s\n", p->name,
+ pp->dataflash->dev.bus_id);
+
+#ifdef HAVE_USI
+ /* even more custom AVR firmware */
+ pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000;
+ strcpy(pp->info[1].modalias, "butterfly");
+ // pp->info[1].platform_data = ... TBD ... ;
+ pp->info[1].chip_select = 2,
+ pp->info[1].controller_data = pp;
+ pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]);
+ if (pp->butterfly)
+ pr_debug("%s: butterfly at %s\n", p->name,
+ pp->butterfly->dev.bus_id);
+
+ /* FIXME setup ACK for the IRQ line ... */
+#endif
+
+ // dev_info(_what?_, ...)
+ pr_info("%s: AVR Butterfly\n", p->name);
+ butterfly = pp;
+ return;
+
+clean2:
+ /* turn off VCC */
+ parport_write_data(pp->port, 0);
+
+ parport_release(pp->pd);
+clean1:
+ parport_unregister_device(pd);
+clean0:
+ (void) spi_master_put(pp->bitbang.master);
+done:
+ platform_device_unregister(pdev);
+ pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
+}
+
+static void butterfly_detach(struct parport *p)
+{
+ struct butterfly *pp;
+ struct platform_device *pdev;
+ int status;
+
+ /* FIXME this global is ugly ... but, how to quickly get from
+ * the parport to the "struct butterfly" associated with it?
+ * "old school" driver-internal device lists?
+ */
+ if (!butterfly || butterfly->port != p)
+ return;
+ pp = butterfly;
+ butterfly = NULL;
+
+#ifdef HAVE_USI
+ spi_unregister_device(pp->butterfly);
+ pp->butterfly = NULL;
+#endif
+ spi_unregister_device(pp->dataflash);
+ pp->dataflash = NULL;
+
+ status = spi_bitbang_stop(&pp->bitbang);
+
+ /* turn off VCC */
+ parport_write_data(pp->port, 0);
+ msleep(10);
+
+ parport_release(pp->pd);
+ parport_unregister_device(pp->pd);
+
+ pdev = to_platform_device(pp->bitbang.master->cdev.dev);
+
+ (void) spi_master_put(pp->bitbang.master);
+
+ platform_device_unregister(pdev);
+}
+
+static struct parport_driver butterfly_driver = {
+ .name = "spi_butterfly",
+ .attach = butterfly_attach,
+ .detach = butterfly_detach,
+};
+
+
+static int __init butterfly_init(void)
+{
+ return parport_register_driver(&butterfly_driver);
+}
+device_initcall(butterfly_init);
+
+static void __exit butterfly_exit(void)
+{
+ parport_unregister_driver(&butterfly_driver);
+}
+module_exit(butterfly_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 57c0c6e3fbed..d3a7b0c3d38b 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -34,24 +34,19 @@ typedef struct ixj_info_t {
struct ixj *port;
} ixj_info_t;
-static dev_link_t *ixj_attach(void);
-static void ixj_detach(dev_link_t *);
+static void ixj_detach(struct pcmcia_device *p_dev);
static void ixj_config(dev_link_t * link);
static void ixj_cs_release(dev_link_t * link);
-static int ixj_event(event_t event, int priority, event_callback_args_t * args);
-static dev_info_t dev_info = "ixj_cs";
-static dev_link_t *dev_list = NULL;
-static dev_link_t *ixj_attach(void)
+static int ixj_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg;
dev_link_t *link;
- int ret;
+
DEBUG(0, "ixj_attach()\n");
/* Create new ixj device */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
- return NULL;
+ return -ENOMEM;
memset(link, 0, sizeof(struct dev_link_t));
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@@ -61,44 +56,29 @@ static dev_link_t *ixj_attach(void)
link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
if (!link->priv) {
kfree(link);
- return NULL;
+ return -ENOMEM;
}
memset(link->priv, 0, sizeof(struct ixj_info_t));
- /* Register with Card Services */
- 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);
- ixj_detach(link);
- return NULL;
- }
- return link;
+
+ link->handle = p_dev;
+ p_dev->instance = link;
+
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ ixj_config(link);
+
+ return 0;
}
-static void ixj_detach(dev_link_t * link)
+static void ixj_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
- int ret;
+ dev_link_t *link = dev_to_instance(p_dev);
+
DEBUG(0, "ixj_detach(0x%p)\n", link);
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp == NULL)
- return;
+
link->state &= ~DEV_RELEASE_PENDING;
if (link->state & DEV_CONFIG)
ixj_cs_release(link);
- if (link->handle) {
- ret = pcmcia_deregister_client(link->handle);
- if (ret != CS_SUCCESS)
- cs_error(link->handle, DeregisterClient, ret);
- }
- /* Unlink device structure, free bits */
- *linkp = link->next;
+
kfree(link->priv);
kfree(link);
}
@@ -255,37 +235,25 @@ static void ixj_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG;
}
-static int ixj_event(event_t event, int priority, event_callback_args_t * args)
+static int ixj_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- DEBUG(1, "ixj_event(0x%06x)\n", event);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- link->state |= DEV_RELEASE_PENDING;
- ixj_cs_release(link);
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- ixj_config(link);
- break;
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (DEV_OK(link))
- pcmcia_request_configuration(link->handle, &link->conf);
- break;
- }
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int ixj_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+
+ link->state &= ~DEV_SUSPEND;
+ if (DEV_OK(link))
+ pcmcia_request_configuration(link->handle, &link->conf);
+
return 0;
}
@@ -300,10 +268,11 @@ static struct pcmcia_driver ixj_driver = {
.drv = {
.name = "ixj_cs",
},
- .attach = ixj_attach,
- .event = ixj_event,
- .detach = ixj_detach,
+ .probe = ixj_attach,
+ .remove = ixj_detach,
.id_table = ixj_ids,
+ .suspend = ixj_suspend,
+ .resume = ixj_resume,
};
static int __init ixj_pcmcia_init(void)
@@ -314,7 +283,6 @@ static int __init ixj_pcmcia_init(void)
static void ixj_pcmcia_exit(void)
{
pcmcia_unregister_driver(&ixj_driver);
- BUG_ON(dev_list != NULL);
}
module_init(ixj_pcmcia_init);
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index a50c2bc506f2..3639c3f8d357 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_MIDI) += class/
obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/
+obj-$(CONFIG_USB) += storage/
obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/
diff --git a/drivers/usb/atm/Kconfig b/drivers/usb/atm/Kconfig
index f429862e0974..550ddfa71a43 100644
--- a/drivers/usb/atm/Kconfig
+++ b/drivers/usb/atm/Kconfig
@@ -44,6 +44,19 @@ config USB_CXACRU
To compile this driver as a module, choose M here: the
module will be called cxacru.
+config USB_UEAGLEATM
+ tristate "ADI 930 and eagle USB DSL modem"
+ depends on USB_ATM
+ select FW_LOADER
+ help
+ Say Y here if you have an ADSL USB modem based on the ADI 930
+ or eagle chipset. In order to use your modem you will need to
+ install firmwares and CMV (Command Management Variables); see
+ <https://gna.org/projects/ueagleatm/> for details.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ueagle-atm.
+
config USB_XUSBATM
tristate "Other USB DSL modem support"
depends on USB_ATM
diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile
index 85099718c683..4c4a776ab1cd 100644
--- a/drivers/usb/atm/Makefile
+++ b/drivers/usb/atm/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_USB_CXACRU) += cxacru.o
obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
+obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o
obj-$(CONFIG_USB_ATM) += usbatm.o
obj-$(CONFIG_USB_XUSBATM) += xusbatm.o
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 9d59dc62e6d2..af0a41e7870e 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -853,7 +853,6 @@ static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_
}
static struct usb_driver cxacru_usb_driver = {
- .owner = THIS_MODULE,
.name = cxacru_driver_name,
.probe = cxacru_usb_probe,
.disconnect = usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index d0cbbb7f0385..c1b47d74e206 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -532,9 +532,9 @@ static void speedtch_handle_int(struct urb *int_urb, struct pt_regs *regs)
int ret = int_urb->status;
/* The magic interrupt for "up state" */
- const static unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
+ static const unsigned char up_int[6] = { 0xa1, 0x00, 0x01, 0x00, 0x00, 0x00 };
/* The magic interrupt for "down state" */
- const static unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const unsigned char down_int[6] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00 };
atm_dbg(usbatm, "%s entered\n", __func__);
@@ -659,7 +659,6 @@ MODULE_DEVICE_TABLE(usb, speedtch_usb_ids);
static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *);
static struct usb_driver speedtch_usb_driver = {
- .owner = THIS_MODULE,
.name = speedtch_driver_name,
.probe = speedtch_usb_probe,
.disconnect = usbatm_usb_disconnect,
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
new file mode 100644
index 000000000000..7d2a679989ed
--- /dev/null
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -0,0 +1,1820 @@
+/*-
+ * Copyright (c) 2003, 2004
+ * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
+ *
+ * Copyright (c) 2005 Matthieu Castet <castet.matthieu@free.fr>
+ *
+ * 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
+ * BSD license below:
+ *
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * GPL license :
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * HISTORY : some part of the code was base on ueagle 1.3 BSD driver,
+ * Damien Bergamini agree to put his code under a DUAL GPL/BSD license.
+ *
+ * The rest of the code was was rewritten from scratch.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/usb.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <asm/unaligned.h>
+
+#include "usbatm.h"
+
+#define EAGLEUSBVERSION "ueagle 1.1"
+
+
+/*
+ * Debug macros
+ */
+#define uea_dbg(usb_dev, format, args...) \
+ do { \
+ if (debug >= 1) \
+ dev_dbg(&(usb_dev)->dev, \
+ "[ueagle-atm dbg] %s: " format, \
+ __FUNCTION__, ##args); \
+ } while (0)
+
+#define uea_vdbg(usb_dev, format, args...) \
+ do { \
+ if (debug >= 2) \
+ dev_dbg(&(usb_dev)->dev, \
+ "[ueagle-atm vdbg] " format, ##args); \
+ } while (0)
+
+#define uea_enters(usb_dev) \
+ uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
+
+#define uea_leaves(usb_dev) \
+ uea_vdbg(usb_dev, "leaving %s\n", __FUNCTION__)
+
+#define uea_err(usb_dev, format,args...) \
+ dev_err(&(usb_dev)->dev ,"[UEAGLE-ATM] " format , ##args)
+
+#define uea_warn(usb_dev, format,args...) \
+ dev_warn(&(usb_dev)->dev ,"[Ueagle-atm] " format, ##args)
+
+#define uea_info(usb_dev, format,args...) \
+ dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args)
+
+struct uea_cmvs {
+ u32 address;
+ u16 offset;
+ u32 data;
+} __attribute__ ((packed));
+
+struct uea_softc {
+ struct usb_device *usb_dev;
+ struct usbatm_data *usbatm;
+
+ int modem_index;
+ unsigned int driver_info;
+
+ int booting;
+ int reset;
+
+ wait_queue_head_t sync_q;
+
+ struct task_struct *kthread;
+ u32 data;
+ wait_queue_head_t cmv_ack_wait;
+ int cmv_ack;
+
+ struct work_struct task;
+ u16 pageno;
+ u16 ovl;
+
+ const struct firmware *dsp_firm;
+ struct urb *urb_int;
+
+ u8 cmv_function;
+ u16 cmv_idx;
+ u32 cmv_address;
+ u16 cmv_offset;
+
+ /* keep in sync with eaglectl */
+ struct uea_stats {
+ struct {
+ u32 state;
+ u32 flags;
+ u32 mflags;
+ u32 vidcpe;
+ u32 vidco;
+ u32 dsrate;
+ u32 usrate;
+ u32 dsunc;
+ u32 usunc;
+ u32 dscorr;
+ u32 uscorr;
+ u32 txflow;
+ u32 rxflow;
+ u32 usattenuation;
+ u32 dsattenuation;
+ u32 dsmargin;
+ u32 usmargin;
+ u32 firmid;
+ } phy;
+ } stats;
+};
+
+/*
+ * Elsa IDs
+ */
+#define ELSA_VID 0x05CC
+#define ELSA_PID_PSTFIRM 0x3350
+#define ELSA_PID_PREFIRM 0x3351
+
+/*
+ * Sagem USB IDs
+ */
+#define EAGLE_VID 0x1110
+#define EAGLE_I_PID_PREFIRM 0x9010 /* Eagle I */
+#define EAGLE_I_PID_PSTFIRM 0x900F /* Eagle I */
+
+#define EAGLE_IIC_PID_PREFIRM 0x9024 /* Eagle IIC */
+#define EAGLE_IIC_PID_PSTFIRM 0x9023 /* Eagle IIC */
+
+#define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */
+#define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */
+
+/*
+ * Eagle III Pid
+ */
+#define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */
+#define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */
+
+/*
+ * USR USB IDs
+ */
+#define USR_VID 0x0BAF
+#define MILLER_A_PID_PREFIRM 0x00F2
+#define MILLER_A_PID_PSTFIRM 0x00F1
+#define MILLER_B_PID_PREFIRM 0x00FA
+#define MILLER_B_PID_PSTFIRM 0x00F9
+#define HEINEKEN_A_PID_PREFIRM 0x00F6
+#define HEINEKEN_A_PID_PSTFIRM 0x00F5
+#define HEINEKEN_B_PID_PREFIRM 0x00F8
+#define HEINEKEN_B_PID_PSTFIRM 0x00F7
+
+#define PREFIRM 0
+#define PSTFIRM (1<<7)
+enum {
+ ADI930 = 0,
+ EAGLE_I,
+ EAGLE_II,
+ EAGLE_III
+};
+
+/* macros for both struct usb_device_id and struct uea_softc */
+#define UEA_IS_PREFIRM(x) \
+ (!((x)->driver_info & PSTFIRM))
+#define UEA_CHIP_VERSION(x) \
+ ((x)->driver_info & 0xf)
+
+#define IS_ISDN(sc) \
+ (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)
+
+#define INS_TO_USBDEV(ins) ins->usb_dev
+
+#define GET_STATUS(data) \
+ ((data >> 8) & 0xf)
+#define IS_OPERATIONAL(sc) \
+ (GET_STATUS(sc->stats.phy.state) == 2)
+
+/*
+ * Set of macros to handle unaligned data in the firmware blob.
+ * The FW_GET_BYTE() macro is provided only for consistency.
+ */
+
+#define FW_GET_BYTE(p) *((__u8 *) (p))
+#define FW_GET_WORD(p) le16_to_cpu(get_unaligned((__le16 *) (p)))
+#define FW_GET_LONG(p) le32_to_cpu(get_unaligned((__le32 *) (p)))
+
+#define FW_DIR "ueagle-atm/"
+#define NB_MODEM 4
+
+#define BULK_TIMEOUT 300
+#define CTRL_TIMEOUT 1000
+
+#define ACK_TIMEOUT msecs_to_jiffies(1500)
+
+#define UEA_INTR_IFACE_NO 0
+#define UEA_US_IFACE_NO 1
+#define UEA_DS_IFACE_NO 2
+
+#define FASTEST_ISO_INTF 8
+
+#define UEA_BULK_DATA_PIPE 0x02
+#define UEA_IDMA_PIPE 0x04
+#define UEA_INTR_PIPE 0x04
+#define UEA_ISO_DATA_PIPE 0x08
+
+#define UEA_SET_BLOCK 0x0001
+#define UEA_SET_MODE 0x0003
+#define UEA_SET_2183_DATA 0x0004
+#define UEA_SET_TIMEOUT 0x0011
+
+#define UEA_LOOPBACK_OFF 0x0002
+#define UEA_LOOPBACK_ON 0x0003
+#define UEA_BOOT_IDMA 0x0006
+#define UEA_START_RESET 0x0007
+#define UEA_END_RESET 0x0008
+
+#define UEA_SWAP_MAILBOX (0x3fcd | 0x4000)
+#define UEA_MPTX_START (0x3fce | 0x4000)
+#define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000)
+#define UEA_MPRX_MAILBOX (0x3fdf | 0x4000)
+
+/* structure describing a block within a DSP page */
+struct block_info {
+ __le16 wHdr;
+#define UEA_BIHDR 0xabcd
+ __le16 wAddress;
+ __le16 wSize;
+ __le16 wOvlOffset;
+ __le16 wOvl; /* overlay */
+ __le16 wLast;
+} __attribute__ ((packed));
+#define BLOCK_INFO_SIZE 12
+
+/* structure representing a CMV (Configuration and Management Variable) */
+struct cmv {
+ __le16 wPreamble;
+#define PREAMBLE 0x535c
+ __u8 bDirection;
+#define MODEMTOHOST 0x01
+#define HOSTTOMODEM 0x10
+ __u8 bFunction;
+#define FUNCTION_TYPE(f) ((f) >> 4)
+#define MEMACCESS 0x1
+#define ADSLDIRECTIVE 0x7
+
+#define FUNCTION_SUBTYPE(f) ((f) & 0x0f)
+/* for MEMACCESS */
+#define REQUESTREAD 0x0
+#define REQUESTWRITE 0x1
+#define REPLYREAD 0x2
+#define REPLYWRITE 0x3
+/* for ADSLDIRECTIVE */
+#define KERNELREADY 0x0
+#define MODEMREADY 0x1
+
+#define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf))
+ __le16 wIndex;
+ __le32 dwSymbolicAddress;
+#define MAKESA(a, b, c, d) \
+ (((c) & 0xff) << 24 | \
+ ((d) & 0xff) << 16 | \
+ ((a) & 0xff) << 8 | \
+ ((b) & 0xff))
+
+#define SA_CNTL MAKESA('C', 'N', 'T', 'L')
+#define SA_DIAG MAKESA('D', 'I', 'A', 'G')
+#define SA_INFO MAKESA('I', 'N', 'F', 'O')
+#define SA_OPTN MAKESA('O', 'P', 'T', 'N')
+#define SA_RATE MAKESA('R', 'A', 'T', 'E')
+#define SA_STAT MAKESA('S', 'T', 'A', 'T')
+ __le16 wOffsetAddress;
+ __le32 dwData;
+} __attribute__ ((packed));
+#define CMV_SIZE 16
+
+/* structure representing swap information */
+struct swap_info {
+ __u8 bSwapPageNo;
+ __u8 bOvl; /* overlay */
+} __attribute__ ((packed));
+
+/* structure representing interrupt data */
+struct intr_pkt {
+ __u8 bType;
+ __u8 bNotification;
+ __le16 wValue;
+ __le16 wIndex;
+ __le16 wLength;
+ __le16 wInterrupt;
+#define INT_LOADSWAPPAGE 0x0001
+#define INT_INCOMINGCMV 0x0002
+ union {
+ struct {
+ struct swap_info swapinfo;
+ __le16 wDataSize;
+ } __attribute__ ((packed)) s1;
+
+ struct {
+ struct cmv cmv;
+ __le16 wDataSize;
+ } __attribute__ ((packed)) s2;
+ } __attribute__ ((packed)) u;
+#define bSwapPageNo u.s1.swapinfo.bSwapPageNo
+#define bOvl u.s1.swapinfo.bOvl
+} __attribute__ ((packed));
+#define INTR_PKT_SIZE 28
+
+static struct usb_driver uea_driver;
+static DECLARE_MUTEX(uea_semaphore);
+static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
+
+static int modem_index;
+static unsigned int debug;
+static int sync_wait[NB_MODEM];
+static char *cmv_file[NB_MODEM];
+
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(sync_wait, bool, NULL, 0644);
+MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
+module_param_array(cmv_file, charp, NULL, 0644);
+MODULE_PARM_DESC(cmv_file,
+ "file name with configuration and management variables");
+
+#define UPDATE_ATM_STAT(type, val) \
+ do { \
+ if (sc->usbatm->atm_dev) \
+ sc->usbatm->atm_dev->type = val; \
+ } while (0)
+
+/* Firmware loading */
+#define LOAD_INTERNAL 0xA0
+#define F8051_USBCS 0x7f92
+
+/**
+ * uea_send_modem_cmd - Send a command for pre-firmware devices.
+ */
+static int uea_send_modem_cmd(struct usb_device *usb,
+ u16 addr, u16 size, u8 * buff)
+{
+ int ret = -ENOMEM;
+ u8 *xfer_buff;
+
+ xfer_buff = kmalloc(size, GFP_KERNEL);
+ if (xfer_buff) {
+ memcpy(xfer_buff, buff, size);
+ ret = usb_control_msg(usb,
+ usb_sndctrlpipe(usb, 0),
+ LOAD_INTERNAL,
+ USB_DIR_OUT | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, addr, 0, xfer_buff,
+ size, CTRL_TIMEOUT);
+ kfree(xfer_buff);
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return (ret == size) ? 0 : -EIO;
+}
+
+static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *context)
+{
+ struct usb_device *usb = context;
+ u8 *pfw, value;
+ u32 crc = 0;
+ int ret, size;
+
+ uea_enters(usb);
+ if (!fw_entry) {
+ uea_err(usb, "firmware is not available\n");
+ goto err;
+ }
+
+ pfw = fw_entry->data;
+ size = fw_entry->size;
+ if (size < 4)
+ goto err_fw_corrupted;
+
+ crc = FW_GET_LONG(pfw);
+ pfw += 4;
+ size -= 4;
+ if (crc32_be(0, pfw, size) != crc)
+ goto err_fw_corrupted;
+
+ /*
+ * Start to upload formware : send reset
+ */
+ value = 1;
+ ret = uea_send_modem_cmd(usb, F8051_USBCS, sizeof(value), &value);
+
+ if (ret < 0) {
+ uea_err(usb, "modem reset failed with error %d\n", ret);
+ goto err;
+ }
+
+ while (size > 3) {
+ u8 len = FW_GET_BYTE(pfw);
+ u16 add = FW_GET_WORD(pfw + 1);
+
+ size -= len + 3;
+ if (size < 0)
+ goto err_fw_corrupted;
+
+ ret = uea_send_modem_cmd(usb, add, len, pfw + 3);
+ if (ret < 0) {
+ uea_err(usb, "uploading firmware data failed "
+ "with error %d\n", ret);
+ goto err;
+ }
+ pfw += len + 3;
+ }
+
+ if (size != 0)
+ goto err_fw_corrupted;
+
+ /*
+ * Tell the modem we finish : de-assert reset
+ */
+ value = 0;
+ ret = uea_send_modem_cmd(usb, F8051_USBCS, 1, &value);
+ if (ret < 0)
+ uea_err(usb, "modem de-assert failed with error %d\n", ret);
+ else
+ uea_info(usb, "firmware uploaded\n");
+
+ uea_leaves(usb);
+ return;
+
+err_fw_corrupted:
+ uea_err(usb, "firmware is corrupted\n");
+err:
+ uea_leaves(usb);
+}
+
+/**
+ * uea_load_firmware - Load usb firmware for pre-firmware devices.
+ */
+static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
+{
+ int ret;
+ char *fw_name = FW_DIR "eagle.fw";
+
+ uea_enters(usb);
+ uea_info(usb, "pre-firmware device, uploading firmware\n");
+
+ switch (ver) {
+ case ADI930:
+ fw_name = FW_DIR "adi930.fw";
+ break;
+ case EAGLE_I:
+ fw_name = FW_DIR "eagleI.fw";
+ break;
+ case EAGLE_II:
+ fw_name = FW_DIR "eagleII.fw";
+ break;
+ case EAGLE_III:
+ fw_name = FW_DIR "eagleIII.fw";
+ break;
+ }
+
+ ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware);
+ if (ret)
+ uea_err(usb, "firmware %s is not available\n", fw_name);
+ else
+ uea_info(usb, "loading firmware %s\n", fw_name);
+
+ uea_leaves(usb);
+ return ret;
+}
+
+/* modem management : dsp firmware, send/read CMV, monitoring statistic
+ */
+
+/*
+ * Make sure that the DSP code provided is safe to use.
+ */
+static int check_dsp(u8 *dsp, unsigned int len)
+{
+ u8 pagecount, blockcount;
+ u16 blocksize;
+ u32 pageoffset;
+ unsigned int i, j, p, pp;
+
+ pagecount = FW_GET_BYTE(dsp);
+ p = 1;
+
+ /* enough space for page offsets? */
+ if (p + 4 * pagecount > len)
+ return 1;
+
+ for (i = 0; i < pagecount; i++) {
+
+ pageoffset = FW_GET_LONG(dsp + p);
+ p += 4;
+
+ if (pageoffset == 0)
+ continue;
+
+ /* enough space for blockcount? */
+ if (pageoffset >= len)
+ return 1;
+
+ pp = pageoffset;
+ blockcount = FW_GET_BYTE(dsp + pp);
+ pp += 1;
+
+ for (j = 0; j < blockcount; j++) {
+
+ /* enough space for block header? */
+ if (pp + 4 > len)
+ return 1;
+
+ pp += 2; /* skip blockaddr */
+ blocksize = FW_GET_WORD(dsp + pp);
+ pp += 2;
+
+ /* enough space for block data? */
+ if (pp + blocksize > len)
+ return 1;
+
+ pp += blocksize;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * send data to the idma pipe
+ * */
+static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
+{
+ int ret = -ENOMEM;
+ u8 *xfer_buff;
+ int bytes_read;
+
+ xfer_buff = kmalloc(size, GFP_KERNEL);
+ if (!xfer_buff) {
+ uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+ return ret;
+ }
+
+ memcpy(xfer_buff, data, size);
+
+ ret = usb_bulk_msg(sc->usb_dev,
+ usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
+ xfer_buff, size, &bytes_read, BULK_TIMEOUT);
+
+ kfree(xfer_buff);
+ if (ret < 0)
+ return ret;
+ if (size != bytes_read) {
+ uea_err(INS_TO_USBDEV(sc), "size != bytes_read %d %d\n", size,
+ bytes_read);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int request_dsp(struct uea_softc *sc)
+{
+ int ret;
+ char *dsp_name;
+
+ if (UEA_CHIP_VERSION(sc) == ADI930) {
+ if (IS_ISDN(sc))
+ dsp_name = FW_DIR "DSP9i.bin";
+ else
+ dsp_name = FW_DIR "DSP9p.bin";
+ } else {
+ if (IS_ISDN(sc))
+ dsp_name = FW_DIR "DSPei.bin";
+ else
+ dsp_name = FW_DIR "DSPep.bin";
+ }
+
+ ret = request_firmware(&sc->dsp_firm,
+ dsp_name, &sc->usb_dev->dev);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "requesting firmware %s failed with error %d\n",
+ dsp_name, ret);
+ return ret;
+ }
+
+ if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) {
+ uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+ dsp_name);
+ release_firmware(sc->dsp_firm);
+ sc->dsp_firm = NULL;
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+/*
+ * The uea_load_page() function must be called within a process context
+ */
+static void uea_load_page(void *xsc)
+{
+ struct uea_softc *sc = xsc;
+ u16 pageno = sc->pageno;
+ u16 ovl = sc->ovl;
+ struct block_info bi;
+
+ u8 *p;
+ u8 pagecount, blockcount;
+ u16 blockaddr, blocksize;
+ u32 pageoffset;
+ int i;
+
+ /* reload firmware when reboot start and it's loaded already */
+ if (ovl == 0 && pageno == 0 && sc->dsp_firm) {
+ release_firmware(sc->dsp_firm);
+ sc->dsp_firm = NULL;
+ }
+
+ if (sc->dsp_firm == NULL && request_dsp(sc) < 0)
+ return;
+
+ p = sc->dsp_firm->data;
+ pagecount = FW_GET_BYTE(p);
+ p += 1;
+
+ if (pageno >= pagecount)
+ goto bad1;
+
+ p += 4 * pageno;
+ pageoffset = FW_GET_LONG(p);
+
+ if (pageoffset == 0)
+ goto bad1;
+
+ p = sc->dsp_firm->data + pageoffset;
+ blockcount = FW_GET_BYTE(p);
+ p += 1;
+
+ uea_dbg(INS_TO_USBDEV(sc),
+ "sending %u blocks for DSP page %u\n", blockcount, pageno);
+
+ bi.wHdr = cpu_to_le16(UEA_BIHDR);
+ bi.wOvl = cpu_to_le16(ovl);
+ bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);
+
+ for (i = 0; i < blockcount; i++) {
+ blockaddr = FW_GET_WORD(p);
+ p += 2;
+
+ blocksize = FW_GET_WORD(p);
+ p += 2;
+
+ bi.wSize = cpu_to_le16(blocksize);
+ bi.wAddress = cpu_to_le16(blockaddr);
+ bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0);
+
+ /* send block info through the IDMA pipe */
+ if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE))
+ goto bad2;
+
+ /* send block data through the IDMA pipe */
+ if (uea_idma_write(sc, p, blocksize))
+ goto bad2;
+
+ p += blocksize;
+ }
+
+ return;
+
+bad2:
+ uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
+ return;
+bad1:
+ uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+}
+
+static inline void wake_up_cmv_ack(struct uea_softc *sc)
+{
+ sc->cmv_ack = 1;
+ wake_up(&sc->cmv_ack_wait);
+}
+
+static inline int wait_cmv_ack(struct uea_softc *sc)
+{
+ int ret = wait_event_timeout(sc->cmv_ack_wait,
+ sc->cmv_ack, ACK_TIMEOUT);
+ sc->cmv_ack = 0;
+
+ if (ret < 0)
+ return ret;
+
+ return (ret == 0) ? -ETIMEDOUT : 0;
+
+}
+
+#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
+
+static int uea_request(struct uea_softc *sc,
+ u16 value, u16 index, u16 size, void *data)
+{
+ u8 *xfer_buff;
+ int ret = -ENOMEM;
+
+ xfer_buff = kmalloc(size, GFP_KERNEL);
+ if (!xfer_buff) {
+ uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
+ return ret;
+ }
+ memcpy(xfer_buff, data, size);
+
+ ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
+ UCDC_SEND_ENCAPSULATED_COMMAND,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, xfer_buff, size, CTRL_TIMEOUT);
+
+ kfree(xfer_buff);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc), "usb_control_msg error %d\n", ret);
+ return ret;
+ }
+
+ if (ret != size) {
+ uea_err(INS_TO_USBDEV(sc),
+ "usb_control_msg send only %d bytes (instead of %d)\n",
+ ret, size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int uea_cmv(struct uea_softc *sc,
+ u8 function, u32 address, u16 offset, u32 data)
+{
+ struct cmv cmv;
+ int ret;
+
+ /* we send a request, but we expect a reply */
+ sc->cmv_function = function | 0x2;
+ sc->cmv_idx++;
+ sc->cmv_address = address;
+ sc->cmv_offset = offset;
+
+ cmv.wPreamble = cpu_to_le16(PREAMBLE);
+ cmv.bDirection = HOSTTOMODEM;
+ cmv.bFunction = function;
+ cmv.wIndex = cpu_to_le16(sc->cmv_idx);
+ put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);
+ cmv.wOffsetAddress = cpu_to_le16(offset);
+ put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);
+
+ ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
+ if (ret < 0)
+ return ret;
+ return wait_cmv_ack(sc);
+}
+
+static inline int uea_read_cmv(struct uea_softc *sc,
+ u32 address, u16 offset, u32 *data)
+{
+ int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD),
+ address, offset, 0);
+ if (ret < 0)
+ uea_err(INS_TO_USBDEV(sc),
+ "reading cmv failed with error %d\n", ret);
+ else
+ *data = sc->data;
+
+ return ret;
+}
+
+static inline int uea_write_cmv(struct uea_softc *sc,
+ u32 address, u16 offset, u32 data)
+{
+ int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE),
+ address, offset, data);
+ if (ret < 0)
+ uea_err(INS_TO_USBDEV(sc),
+ "writing cmv failed with error %d\n", ret);
+
+ return ret;
+}
+
+/*
+ * Monitor the modem and update the stat
+ * return 0 if everything is ok
+ * return < 0 if an error occurs (-EAGAIN reboot needed)
+ */
+static int uea_stat(struct uea_softc *sc)
+{
+ u32 data;
+ int ret;
+
+ uea_enters(INS_TO_USBDEV(sc));
+ data = sc->stats.phy.state;
+
+ ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state);
+ if (ret < 0)
+ return ret;
+
+ switch (GET_STATUS(sc->stats.phy.state)) {
+ case 0: /* not yet synchronized */
+ uea_dbg(INS_TO_USBDEV(sc),
+ "modem not yet synchronized\n");
+ return 0;
+
+ case 1: /* initialization */
+ uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n");
+ return 0;
+
+ case 2: /* operational */
+ uea_vdbg(INS_TO_USBDEV(sc), "modem operational\n");
+ break;
+
+ case 3: /* fail ... */
+ uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");
+ return -EAGAIN;
+
+ case 4 ... 6: /* test state */
+ uea_warn(INS_TO_USBDEV(sc),
+ "modem in test mode - not supported\n");
+ return -EAGAIN;
+
+ case 7: /* fast-retain ... */
+ uea_info(INS_TO_USBDEV(sc), "modem in fast-retain mode\n");
+ return 0;
+ default:
+ uea_err(INS_TO_USBDEV(sc), "modem invalid SW mode %d\n",
+ GET_STATUS(sc->stats.phy.state));
+ return -EAGAIN;
+ }
+
+ if (GET_STATUS(data) != 2) {
+ uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL);
+ uea_info(INS_TO_USBDEV(sc), "modem operational\n");
+
+ /* release the dsp firmware as it is not needed until
+ * the next failure
+ */
+ if (sc->dsp_firm) {
+ release_firmware(sc->dsp_firm);
+ sc->dsp_firm = NULL;
+ }
+
+ ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
+ if (ret < 0)
+ return ret;
+ uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
+ sc->stats.phy.firmid);
+ }
+
+ /* always update it as atm layer could not be init when we switch to
+ * operational state
+ */
+ UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND);
+
+ /* wake up processes waiting for synchronization */
+ wake_up(&sc->sync_q);
+
+ ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags);
+ if (ret < 0)
+ return ret;
+ sc->stats.phy.mflags |= sc->stats.phy.flags;
+
+ /* in case of a flags ( for example delineation LOSS (& 0x10)),
+ * we check the status again in order to detect the failure earlier
+ */
+ if (sc->stats.phy.flags) {
+ uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+ sc->stats.phy.flags);
+ return 0;
+ }
+
+ ret = uea_read_cmv(sc, SA_RATE, 0, &data);
+ if (ret < 0)
+ return ret;
+
+ /* in bulk mode the modem have problem with high rate
+ * changing internal timing could improve things, but the
+ * value is misterious.
+ * ADI930 don't support it (-EPIPE error).
+ */
+ if (UEA_CHIP_VERSION(sc) != ADI930
+ && sc->stats.phy.dsrate != (data >> 16) * 32) {
+ /* Original timming from ADI(used in windows driver)
+ * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
+ */
+ u16 timeout = (data <= 0x20ffff) ? 0 : 1;
+ ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL);
+ uea_info(INS_TO_USBDEV(sc),
+ "setting new timeout %d%s\n", timeout,
+ ret < 0?" failed":"");
+ }
+ sc->stats.phy.dsrate = (data >> 16) * 32;
+ sc->stats.phy.usrate = (data & 0xffff) * 32;
+ UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424);
+
+ ret = uea_read_cmv(sc, SA_DIAG, 23, &data);
+ if (ret < 0)
+ return ret;
+ sc->stats.phy.dsattenuation = (data & 0xff) / 2;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 47, &data);
+ if (ret < 0)
+ return ret;
+ sc->stats.phy.usattenuation = (data & 0xff) / 2;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc);
+ if (ret < 0)
+ return ret;
+
+ /* only for atu-c */
+ ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr);
+ if (ret < 0)
+ return ret;
+
+ /* only for atu-c */
+ ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco);
+ if (ret < 0)
+ return ret;
+
+ ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int request_cmvs(struct uea_softc *sc,
+ struct uea_cmvs **cmvs, const struct firmware **fw)
+{
+ int ret, size;
+ u8 *data;
+ char *file;
+ static char cmv_name[256] = FW_DIR;
+
+ if (cmv_file[sc->modem_index] == NULL) {
+ if (UEA_CHIP_VERSION(sc) == ADI930)
+ file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin";
+ else
+ file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin";
+ } else
+ file = cmv_file[sc->modem_index];
+
+ strcpy(cmv_name, FW_DIR);
+ strlcat(cmv_name, file, sizeof(cmv_name));
+
+ ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "requesting firmware %s failed with error %d\n",
+ cmv_name, ret);
+ return ret;
+ }
+
+ data = (u8 *) (*fw)->data;
+ size = *data * sizeof(struct uea_cmvs) + 1;
+ if (size != (*fw)->size) {
+ uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+ cmv_name);
+ release_firmware(*fw);
+ return -EILSEQ;
+ }
+
+ *cmvs = (struct uea_cmvs *)(data + 1);
+ return *data;
+}
+
+/* Start boot post firmware modem:
+ * - send reset commands through usb control pipe
+ * - start workqueue for DSP loading
+ * - send CMV options to modem
+ */
+
+static int uea_start_reset(struct uea_softc *sc)
+{
+ u16 zero = 0; /* ;-) */
+ int i, len, ret;
+ struct uea_cmvs *cmvs;
+ const struct firmware *cmvs_fw;
+
+ uea_enters(INS_TO_USBDEV(sc));
+ uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
+
+ sc->booting = 1;
+ UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
+
+ /* reset statistics */
+ memset(&sc->stats, 0, sizeof(struct uea_stats));
+
+ /* tell the modem that we want to boot in IDMA mode */
+ uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+ uea_request(sc, UEA_SET_MODE, UEA_BOOT_IDMA, 0, NULL);
+
+ /* enter reset mode */
+ uea_request(sc, UEA_SET_MODE, UEA_START_RESET, 0, NULL);
+
+ /* original driver use 200ms, but windows driver use 100ms */
+ msleep(100);
+
+ /* leave reset mode */
+ uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL);
+
+ /* clear tx and rx mailboxes */
+ uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero);
+ uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero);
+ uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero);
+
+ msleep(1000);
+ sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+ sc->booting = 0;
+
+ /* start loading DSP */
+ sc->pageno = 0;
+ sc->ovl = 0;
+ schedule_work(&sc->task);
+
+ /* wait for modem ready CMV */
+ ret = wait_cmv_ack(sc);
+ if (ret < 0)
+ return ret;
+
+ /* Enter in R-IDLE (cmv) until instructed otherwise */
+ ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
+ if (ret < 0)
+ return ret;
+
+ /* get options */
+ ret = len = request_cmvs(sc, &cmvs, &cmvs_fw);
+ if (ret < 0)
+ return ret;
+
+ /* send options */
+ for (i = 0; i < len; i++) {
+ ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address),
+ FW_GET_WORD(&cmvs[i].offset),
+ FW_GET_LONG(&cmvs[i].data));
+ if (ret < 0)
+ goto out;
+ }
+ /* Enter in R-ACT-REQ */
+ ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+out:
+ release_firmware(cmvs_fw);
+ sc->reset = 0;
+ uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+}
+
+/*
+ * In case of an error wait 1s before rebooting the modem
+ * if the modem don't request reboot (-EAGAIN).
+ * Monitor the modem every 1s.
+ */
+
+static int uea_kthread(void *data)
+{
+ struct uea_softc *sc = data;
+ int ret = -EAGAIN;
+
+ uea_enters(INS_TO_USBDEV(sc));
+ while (!kthread_should_stop()) {
+ if (ret < 0 || sc->reset)
+ ret = uea_start_reset(sc);
+ if (!ret)
+ ret = uea_stat(sc);
+ if (ret != -EAGAIN)
+ msleep(1000);
+ }
+ uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+}
+
+/* Load second usb firmware for ADI930 chip */
+static int load_XILINX_firmware(struct uea_softc *sc)
+{
+ const struct firmware *fw_entry;
+ int ret, size, u, ln;
+ u8 *pfw, value;
+ char *fw_name = FW_DIR "930-fpga.bin";
+
+ uea_enters(INS_TO_USBDEV(sc));
+
+ ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev);
+ if (ret) {
+ uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n",
+ fw_name);
+ goto err0;
+ }
+
+ pfw = fw_entry->data;
+ size = fw_entry->size;
+ if (size != 0x577B) {
+ uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n",
+ fw_name);
+ ret = -EILSEQ;
+ goto err1;
+ }
+ for (u = 0; u < size; u += ln) {
+ ln = min(size - u, 64);
+ ret = uea_request(sc, 0xe, 0, ln, pfw + u);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "elsa download data failed (%d)\n", ret);
+ goto err1;
+ }
+ }
+
+ /* finish to send the fpga
+ */
+ ret = uea_request(sc, 0xe, 1, 0, NULL);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "elsa download data failed (%d)\n", ret);
+ goto err1;
+ }
+
+ /*
+ * Tell the modem we finish : de-assert reset
+ */
+ value = 0;
+ ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
+ if (ret < 0)
+ uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret);
+
+
+err1:
+ release_firmware(fw_entry);
+err0:
+ uea_leaves(INS_TO_USBDEV(sc));
+ return ret;
+}
+
+static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
+{
+ uea_enters(INS_TO_USBDEV(sc));
+ if (le16_to_cpu(cmv->wPreamble) != PREAMBLE)
+ goto bad1;
+
+ if (cmv->bDirection != MODEMTOHOST)
+ goto bad1;
+
+ /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to
+ * the first MEMACESS cmv. Ignore it...
+ */
+ if (cmv->bFunction != sc->cmv_function) {
+ if (UEA_CHIP_VERSION(sc) == ADI930
+ && cmv->bFunction == MAKEFUNCTION(2, 2)) {
+ cmv->wIndex = cpu_to_le16(sc->cmv_idx);
+ put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress);
+ cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset);
+ }
+ else
+ goto bad2;
+ }
+
+ if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
+ wake_up_cmv_ack(sc);
+ return;
+ }
+
+ /* in case of MEMACCESS */
+ if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx ||
+ le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) !=
+ sc->cmv_address
+ || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset)
+ goto bad2;
+
+ sc->data = le32_to_cpu(get_unaligned(&cmv->dwData));
+ sc->data = sc->data << 16 | sc->data >> 16;
+
+ wake_up_cmv_ack(sc);
+ return;
+
+bad2:
+ uea_err(INS_TO_USBDEV(sc), "unexpected cmv received,"
+ "Function : %d, Subfunction : %d\n",
+ FUNCTION_TYPE(cmv->bFunction),
+ FUNCTION_SUBTYPE(cmv->bFunction));
+ return;
+
+bad1:
+ uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
+ "wPreamble %d, bDirection %d\n",
+ le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+}
+
+/*
+ * interrupt handler
+ */
+static void uea_intr(struct urb *urb, struct pt_regs *regs)
+{
+ struct uea_softc *sc = (struct uea_softc *)urb->context;
+ struct intr_pkt *intr;
+ uea_enters(INS_TO_USBDEV(sc));
+
+ if (urb->status < 0) {
+ uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
+ urb->status);
+ return;
+ }
+
+ intr = (struct intr_pkt *) urb->transfer_buffer;
+
+ /* device-to-host interrupt */
+ if (intr->bType != 0x08 || sc->booting) {
+ uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
+ // rebooting ?
+ // sc->reset = 1;
+ goto resubmit;
+ }
+
+ switch (le16_to_cpu(intr->wInterrupt)) {
+ case INT_LOADSWAPPAGE:
+ sc->pageno = intr->bSwapPageNo;
+ sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4;
+ schedule_work(&sc->task);
+ break;
+
+ case INT_INCOMINGCMV:
+ uea_dispatch_cmv(sc, &intr->u.s2.cmv);
+ break;
+
+ default:
+ uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+ le16_to_cpu(intr->wInterrupt));
+ }
+
+resubmit:
+ usb_submit_urb(sc->urb_int, GFP_ATOMIC);
+}
+
+/*
+ * Start the modem : init the data and start kernel thread
+ */
+static int uea_boot(struct uea_softc *sc)
+{
+ int ret;
+ struct intr_pkt *intr;
+
+ uea_enters(INS_TO_USBDEV(sc));
+
+ INIT_WORK(&sc->task, uea_load_page, sc);
+ init_waitqueue_head(&sc->sync_q);
+ init_waitqueue_head(&sc->cmv_ack_wait);
+
+ if (UEA_CHIP_VERSION(sc) == ADI930)
+ load_XILINX_firmware(sc);
+
+ intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL);
+ if (!intr) {
+ uea_err(INS_TO_USBDEV(sc),
+ "cannot allocate interrupt package\n");
+ uea_leaves(INS_TO_USBDEV(sc));
+ return -ENOMEM;
+ }
+
+ sc->urb_int = usb_alloc_urb(0, GFP_KERNEL);
+ if (!sc->urb_int) {
+ uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n");
+ goto err;
+ }
+
+ usb_fill_int_urb(sc->urb_int, sc->usb_dev,
+ usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
+ intr, INTR_PKT_SIZE, uea_intr, sc,
+ sc->usb_dev->actconfig->interface[0]->altsetting[0].
+ endpoint[0].desc.bInterval);
+
+ ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
+ if (ret < 0) {
+ uea_err(INS_TO_USBDEV(sc),
+ "urb submition failed with error %d\n", ret);
+ goto err1;
+ }
+
+ sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
+ if (sc->kthread == ERR_PTR(-ENOMEM)) {
+ uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+ goto err2;
+ }
+
+ uea_leaves(INS_TO_USBDEV(sc));
+ return 0;
+
+err2:
+ usb_kill_urb(sc->urb_int);
+err1:
+ kfree(intr);
+err:
+ usb_free_urb(sc->urb_int);
+ uea_leaves(INS_TO_USBDEV(sc));
+ return -ENOMEM;
+}
+
+/*
+ * Stop the modem : kill kernel thread and free data
+ */
+static void uea_stop(struct uea_softc *sc)
+{
+ int ret;
+ uea_enters(INS_TO_USBDEV(sc));
+ ret = kthread_stop(sc->kthread);
+ uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+
+ /* stop any pending boot process */
+ flush_scheduled_work();
+
+ uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);
+
+ usb_kill_urb(sc->urb_int);
+ kfree(sc->urb_int->transfer_buffer);
+ usb_free_urb(sc->urb_int);
+
+ if (sc->dsp_firm)
+ release_firmware(sc->dsp_firm);
+ uea_leaves(INS_TO_USBDEV(sc));
+}
+
+/* syfs interface */
+static struct uea_softc *dev_to_uea(struct device *dev)
+{
+ struct usb_interface *intf;
+ struct usbatm_data *usbatm;
+
+ intf = to_usb_interface(dev);
+ if (!intf)
+ return NULL;
+
+ usbatm = usb_get_intfdata(intf);
+ if (!usbatm)
+ return NULL;
+
+ return usbatm->driver_data;
+}
+
+static ssize_t read_status(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+ down(&uea_semaphore);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+ ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
+out:
+ up(&uea_semaphore);
+ return ret;
+}
+
+static ssize_t reboot(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+ down(&uea_semaphore);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+ sc->reset = 1;
+ ret = count;
+out:
+ up(&uea_semaphore);
+ return ret;
+}
+
+static DEVICE_ATTR(stat_status, S_IWUGO | S_IRUGO, read_status, reboot);
+
+static ssize_t read_human_status(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+ down(&uea_semaphore);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+
+ switch (GET_STATUS(sc->stats.phy.state)) {
+ case 0:
+ ret = sprintf(buf, "Modem is booting\n");
+ break;
+ case 1:
+ ret = sprintf(buf, "Modem is initializing\n");
+ break;
+ case 2:
+ ret = sprintf(buf, "Modem is operational\n");
+ break;
+ default:
+ ret = sprintf(buf, "Modem synchronization failed\n");
+ break;
+ }
+out:
+ up(&uea_semaphore);
+ return ret;
+}
+
+static DEVICE_ATTR(stat_human_status, S_IWUGO | S_IRUGO, read_human_status, NULL);
+
+static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int ret = -ENODEV;
+ struct uea_softc *sc;
+
+ down(&uea_semaphore);
+ sc = dev_to_uea(dev);
+ if (!sc)
+ goto out;
+
+ if (sc->stats.phy.flags & 0x0C00)
+ ret = sprintf(buf, "ERROR\n");
+ else if (sc->stats.phy.flags & 0x0030)
+ ret = sprintf(buf, "LOSS\n");
+ else
+ ret = sprintf(buf, "GOOD\n");
+out:
+ up(&uea_semaphore);
+ return ret;
+}
+
+static DEVICE_ATTR(stat_delin, S_IWUGO | S_IRUGO, read_delin, NULL);
+
+#define UEA_ATTR(name, reset) \
+ \
+static ssize_t read_##name(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ int ret = -ENODEV; \
+ struct uea_softc *sc; \
+ \
+ down(&uea_semaphore); \
+ sc = dev_to_uea(dev); \
+ if (!sc) \
+ goto out; \
+ ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.name); \
+ if (reset) \
+ sc->stats.phy.name = 0; \
+out: \
+ up(&uea_semaphore); \
+ return ret; \
+} \
+ \
+static DEVICE_ATTR(stat_##name, S_IRUGO, read_##name, NULL)
+
+UEA_ATTR(mflags, 1);
+UEA_ATTR(vidcpe, 0);
+UEA_ATTR(usrate, 0);
+UEA_ATTR(dsrate, 0);
+UEA_ATTR(usattenuation, 0);
+UEA_ATTR(dsattenuation, 0);
+UEA_ATTR(usmargin, 0);
+UEA_ATTR(dsmargin, 0);
+UEA_ATTR(txflow, 0);
+UEA_ATTR(rxflow, 0);
+UEA_ATTR(uscorr, 0);
+UEA_ATTR(dscorr, 0);
+UEA_ATTR(usunc, 0);
+UEA_ATTR(dsunc, 0);
+
+/* Retrieve the device End System Identifier (MAC) */
+
+#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10)
+static int uea_getesi(struct uea_softc *sc, u_char * esi)
+{
+ unsigned char mac_str[2 * ETH_ALEN + 1];
+ int i;
+ if (usb_string
+ (sc->usb_dev, sc->usb_dev->descriptor.iSerialNumber, mac_str,
+ sizeof(mac_str)) != 2 * ETH_ALEN)
+ return 1;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]);
+
+ return 0;
+}
+
+/* ATM stuff */
+static int uea_atm_open(struct usbatm_data *usbatm, struct atm_dev *atm_dev)
+{
+ struct uea_softc *sc = usbatm->driver_data;
+
+ return uea_getesi(sc, atm_dev->esi);
+}
+
+static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+ struct uea_softc *sc = usbatm->driver_data;
+
+ wait_event(sc->sync_q, IS_OPERATIONAL(sc));
+
+ return 0;
+
+}
+
+static int claim_interface(struct usb_device *usb_dev,
+ struct usbatm_data *usbatm, int ifnum)
+{
+ int ret;
+ struct usb_interface *intf = usb_ifnum_to_if(usb_dev, ifnum);
+
+ if (!intf) {
+ uea_err(usb_dev, "interface %d not found\n", ifnum);
+ return -ENODEV;
+ }
+
+ ret = usb_driver_claim_interface(&uea_driver, intf, usbatm);
+ if (ret != 0)
+ uea_err(usb_dev, "can't claim interface %d, error %d\n", ifnum,
+ ret);
+ return ret;
+}
+
+static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+ /* sysfs interface */
+ device_create_file(&intf->dev, &dev_attr_stat_status);
+ device_create_file(&intf->dev, &dev_attr_stat_mflags);
+ device_create_file(&intf->dev, &dev_attr_stat_human_status);
+ device_create_file(&intf->dev, &dev_attr_stat_delin);
+ device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
+ device_create_file(&intf->dev, &dev_attr_stat_usrate);
+ device_create_file(&intf->dev, &dev_attr_stat_dsrate);
+ device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
+ device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
+ device_create_file(&intf->dev, &dev_attr_stat_usmargin);
+ device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
+ device_create_file(&intf->dev, &dev_attr_stat_txflow);
+ device_create_file(&intf->dev, &dev_attr_stat_rxflow);
+ device_create_file(&intf->dev, &dev_attr_stat_uscorr);
+ device_create_file(&intf->dev, &dev_attr_stat_dscorr);
+ device_create_file(&intf->dev, &dev_attr_stat_usunc);
+ device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
+ const struct usb_device_id *id, int *heavy)
+{
+ struct usb_device *usb = interface_to_usbdev(intf);
+ struct uea_softc *sc;
+ int ret, ifnum = intf->altsetting->desc.bInterfaceNumber;
+
+ uea_enters(usb);
+
+ /* interface 0 is for firmware/monitoring */
+ if (ifnum != UEA_INTR_IFACE_NO)
+ return -ENODEV;
+
+ *heavy = sync_wait[modem_index];
+
+ /* interface 1 is for outbound traffic */
+ ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
+ if (ret < 0)
+ return ret;
+
+ /* ADI930 has only 2 interfaces and inbound traffic
+ * is on interface 1
+ */
+ if (UEA_CHIP_VERSION(id) != ADI930) {
+ /* interface 2 is for inbound traffic */
+ ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
+ if (ret < 0)
+ return ret;
+ }
+
+ sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
+ if (!sc) {
+ uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+ return -ENOMEM;
+ }
+
+ sc->usb_dev = usb;
+ usbatm->driver_data = sc;
+ sc->usbatm = usbatm;
+ sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
+ sc->driver_info = id->driver_info;
+
+ ret = uea_boot(sc);
+ if (ret < 0) {
+ kfree(sc);
+ return ret;
+ }
+
+ create_fs_entries(sc, intf);
+ return 0;
+}
+
+static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+{
+ /* sysfs interface */
+ device_remove_file(&intf->dev, &dev_attr_stat_status);
+ device_remove_file(&intf->dev, &dev_attr_stat_mflags);
+ device_remove_file(&intf->dev, &dev_attr_stat_human_status);
+ device_remove_file(&intf->dev, &dev_attr_stat_delin);
+ device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
+ device_remove_file(&intf->dev, &dev_attr_stat_usrate);
+ device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
+ device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
+ device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
+ device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
+ device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
+ device_remove_file(&intf->dev, &dev_attr_stat_txflow);
+ device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
+ device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
+ device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
+ device_remove_file(&intf->dev, &dev_attr_stat_usunc);
+ device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+}
+
+static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
+{
+ struct uea_softc *sc = usbatm->driver_data;
+
+ destroy_fs_entries(sc, intf);
+ uea_stop(sc);
+ kfree(sc);
+}
+
+static struct usbatm_driver uea_usbatm_driver = {
+ .driver_name = "ueagle-atm",
+ .owner = THIS_MODULE,
+ .bind = uea_bind,
+ .atm_start = uea_atm_open,
+ .unbind = uea_unbind,
+ .heavy_init = uea_heavy,
+ .in = UEA_BULK_DATA_PIPE,
+ .out = UEA_BULK_DATA_PIPE,
+};
+
+static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *usb = interface_to_usbdev(intf);
+
+ uea_enters(usb);
+ uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",
+ le16_to_cpu(usb->descriptor.idVendor),
+ le16_to_cpu(usb->descriptor.idProduct),
+ chip_name[UEA_CHIP_VERSION(id)]);
+
+ usb_reset_device(usb);
+
+ if (UEA_IS_PREFIRM(id))
+ return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
+
+ return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+}
+
+static void uea_disconnect(struct usb_interface *intf)
+{
+ struct usb_device *usb = interface_to_usbdev(intf);
+ int ifnum = intf->altsetting->desc.bInterfaceNumber;
+ uea_enters(usb);
+
+ /* ADI930 has 2 interfaces and eagle 3 interfaces.
+ * Pre-firmware device has one interface
+ */
+ if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
+ down(&uea_semaphore);
+ usbatm_usb_disconnect(intf);
+ up(&uea_semaphore);
+ uea_info(usb, "ADSL device removed\n");
+ }
+
+ uea_leaves(usb);
+}
+
+/*
+ * List of supported VID/PID
+ */
+static const struct usb_device_id uea_ids[] = {
+ {USB_DEVICE(ELSA_VID, ELSA_PID_PREFIRM), .driver_info = ADI930 | PREFIRM},
+ {USB_DEVICE(ELSA_VID, ELSA_PID_PSTFIRM), .driver_info = ADI930 | PSTFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_I_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_II_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PREFIRM), .driver_info = EAGLE_II | PREFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM},
+ {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM},
+ {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+ {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
+ {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM},
+ {USB_DEVICE(USR_VID, MILLER_B_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM},
+ {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+ {USB_DEVICE(USR_VID, HEINEKEN_A_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+ {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PREFIRM),.driver_info = EAGLE_I | PREFIRM},
+ {USB_DEVICE(USR_VID, HEINEKEN_B_PID_PSTFIRM),.driver_info = EAGLE_I | PSTFIRM},
+ {}
+};
+
+/*
+ * USB driver descriptor
+ */
+static struct usb_driver uea_driver = {
+ .name = "ueagle-atm",
+ .id_table = uea_ids,
+ .probe = uea_probe,
+ .disconnect = uea_disconnect,
+};
+
+MODULE_DEVICE_TABLE(usb, uea_ids);
+
+/**
+ * uea_init - Initialize the module.
+ * Register to USB subsystem
+ */
+static int __init uea_init(void)
+{
+ printk(KERN_INFO "[ueagle-atm] driver " EAGLEUSBVERSION " loaded\n");
+
+ usb_register(&uea_driver);
+
+ return 0;
+}
+
+module_init(uea_init);
+
+/**
+ * uea_exit - Destroy module
+ * Deregister with USB subsystem
+ */
+static void __exit uea_exit(void)
+{
+ /*
+ * This calls automatically the uea_disconnect method if necessary:
+ */
+ usb_deregister(&uea_driver);
+
+ printk(KERN_INFO "[ueagle-atm] driver unloaded\n");
+}
+
+module_exit(uea_exit);
+
+MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka");
+MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 2e6593e6c1bd..7af1883d4bf9 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -207,7 +207,7 @@ static inline void usbatm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
** urbs **
************/
-static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
+static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
{
struct urb *urb;
@@ -224,7 +224,7 @@ static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
return urb;
}
-static inline int usbatm_submit_urb(struct urb *urb)
+static int usbatm_submit_urb(struct urb *urb)
{
struct usbatm_channel *channel = urb->context;
int ret;
@@ -646,14 +646,14 @@ static void usbatm_destroy_instance(struct kref *kref)
kfree(instance);
}
-void usbatm_get_instance(struct usbatm_data *instance)
+static void usbatm_get_instance(struct usbatm_data *instance)
{
dbg("%s", __func__);
kref_get(&instance->refcount);
}
-void usbatm_put_instance(struct usbatm_data *instance)
+static void usbatm_put_instance(struct usbatm_data *instance)
{
dbg("%s", __func__);
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 7fe7fb484d10..5c76e3aaaa5e 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -140,7 +140,6 @@ static int xusbatm_usb_probe(struct usb_interface *intf,
}
static struct usb_driver xusbatm_usb_driver = {
- .owner = THIS_MODULE,
.name = xusbatm_driver_name,
.probe = xusbatm_usb_probe,
.disconnect = usbatm_usb_disconnect,
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 50858273f8d3..3ad9ee8b84a9 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -2732,7 +2732,6 @@ static struct usb_device_id usb_audio_ids [] = {
MODULE_DEVICE_TABLE (usb, usb_audio_ids);
static struct usb_driver usb_audio_driver = {
- .owner = THIS_MODULE,
.name = "audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 1b4751412970..b9fd39fd1b5b 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -6,6 +6,7 @@
* Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Oliver Neukum <oliver@neukum.name>
+ * Copyright (c) 2005 David Kubicek <dave@awk.cz>
*
* USB Abstract Control Model driver for USB modems and ISDN adapters
*
@@ -29,6 +30,7 @@
* config we want, sysadmin changes bConfigurationValue in sysfs.
* v0.23 - use softirq for rx processing, as needed by tty layer
* v0.24 - change probe method to evaluate CDC union descriptor
+ * v0.25 - downstream tasks paralelized to maximize throughput
*/
/*
@@ -63,14 +65,15 @@
#include <linux/usb_cdc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
+#include <linux/list.h>
#include "cdc-acm.h"
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.23"
-#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
+#define DRIVER_VERSION "v0.25"
+#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
static struct usb_driver acm_driver;
@@ -284,7 +287,9 @@ exit:
/* data interface returns incoming bytes, or we got unthrottled */
static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
{
- struct acm *acm = urb->context;
+ struct acm_rb *buf;
+ struct acm_ru *rcv = urb->context;
+ struct acm *acm = rcv->instance;
dbg("Entering acm_read_bulk with status %d\n", urb->status);
if (!ACM_READY(acm))
@@ -293,49 +298,104 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
if (urb->status)
dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
- /* calling tty_flip_buffer_push() in_irq() isn't allowed */
- tasklet_schedule(&acm->bh);
+ buf = rcv->buffer;
+ buf->size = urb->actual_length;
+
+ spin_lock(&acm->read_lock);
+ list_add_tail(&rcv->list, &acm->spare_read_urbs);
+ list_add_tail(&buf->list, &acm->filled_read_bufs);
+ spin_unlock(&acm->read_lock);
+
+ tasklet_schedule(&acm->urb_task);
}
static void acm_rx_tasklet(unsigned long _acm)
{
struct acm *acm = (void *)_acm;
- struct urb *urb = acm->readurb;
+ struct acm_rb *buf;
struct tty_struct *tty = acm->tty;
- unsigned char *data = urb->transfer_buffer;
+ struct acm_ru *rcv;
+ //unsigned long flags;
int i = 0;
dbg("Entering acm_rx_tasklet");
- if (urb->actual_length > 0 && !acm->throttle) {
- for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- * we drop them. */
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- tty_insert_flip_char(tty, data[i], 0);
- }
- dbg("Handed %d bytes to tty layer", i+1);
- tty_flip_buffer_push(tty);
+ if (!ACM_READY(acm) || acm->throttle)
+ return;
+
+next_buffer:
+ spin_lock(&acm->read_lock);
+ if (list_empty(&acm->filled_read_bufs)) {
+ spin_unlock(&acm->read_lock);
+ goto urbs;
}
+ buf = list_entry(acm->filled_read_bufs.next,
+ struct acm_rb, list);
+ list_del(&buf->list);
+ spin_unlock(&acm->read_lock);
+
+ dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
+
+ tty_buffer_request_room(tty, buf->size);
+ if (!acm->throttle)
+ tty_insert_flip_string(tty, buf->base, buf->size);
+ tty_flip_buffer_push(tty);
spin_lock(&acm->throttle_lock);
if (acm->throttle) {
dbg("Throtteling noticed");
- memmove(data, data + i, urb->actual_length - i);
- urb->actual_length -= i;
- acm->resubmit_to_unthrottle = 1;
+ memmove(buf->base, buf->base + i, buf->size - i);
+ buf->size -= i;
spin_unlock(&acm->throttle_lock);
+ spin_lock(&acm->read_lock);
+ list_add(&buf->list, &acm->filled_read_bufs);
+ spin_unlock(&acm->read_lock);
return;
}
spin_unlock(&acm->throttle_lock);
- urb->actual_length = 0;
- urb->dev = acm->dev;
-
- i = usb_submit_urb(urb, GFP_ATOMIC);
- if (i)
- dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
+ spin_lock(&acm->read_lock);
+ list_add(&buf->list, &acm->spare_read_bufs);
+ spin_unlock(&acm->read_lock);
+ goto next_buffer;
+
+urbs:
+ while (!list_empty(&acm->spare_read_bufs)) {
+ spin_lock(&acm->read_lock);
+ if (list_empty(&acm->spare_read_urbs)) {
+ spin_unlock(&acm->read_lock);
+ return;
+ }
+ rcv = list_entry(acm->spare_read_urbs.next,
+ struct acm_ru, list);
+ list_del(&rcv->list);
+ spin_unlock(&acm->read_lock);
+
+ buf = list_entry(acm->spare_read_bufs.next,
+ struct acm_rb, list);
+ list_del(&buf->list);
+
+ rcv->buffer = buf;
+
+ usb_fill_bulk_urb(rcv->urb, acm->dev,
+ acm->rx_endpoint,
+ buf->base,
+ acm->readsize,
+ acm_read_bulk, rcv);
+ rcv->urb->transfer_dma = buf->dma;
+ rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
+
+ /* This shouldn't kill the driver as unsuccessful URBs are returned to the
+ free-urbs-pool and resubmited ASAP */
+ if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+ list_add(&buf->list, &acm->spare_read_bufs);
+ spin_lock(&acm->read_lock);
+ list_add(&rcv->list, &acm->spare_read_urbs);
+ spin_unlock(&acm->read_lock);
+ return;
+ }
+ }
}
/* data interface wrote those outgoing bytes */
@@ -369,6 +429,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
struct acm *acm;
int rv = -EINVAL;
+ int i;
dbg("Entering acm_tty_open.\n");
down(&open_sem);
@@ -382,7 +443,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
tty->driver_data = acm;
acm->tty = tty;
-
+ /* force low_latency on so that our tty_push actually forces the data through,
+ otherwise it is scheduled, and with high data rates data can get lost. */
+ tty->low_latency = 1;
if (acm->used++) {
goto done;
@@ -394,18 +457,20 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto bail_out;
}
- acm->readurb->dev = acm->dev;
- if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
- dbg("usb_submit_urb(read bulk) failed");
- goto bail_out_and_unlink;
- }
-
if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
goto full_bailout;
- /* force low_latency on so that our tty_push actually forces the data through,
- otherwise it is scheduled, and with high data rates data can get lost. */
- tty->low_latency = 1;
+ INIT_LIST_HEAD(&acm->spare_read_urbs);
+ INIT_LIST_HEAD(&acm->spare_read_bufs);
+ INIT_LIST_HEAD(&acm->filled_read_bufs);
+ for (i = 0; i < ACM_NRU; i++) {
+ list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
+ }
+ for (i = 0; i < ACM_NRB; i++) {
+ list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
+ }
+
+ tasklet_schedule(&acm->urb_task);
done:
err_out:
@@ -413,8 +478,6 @@ err_out:
return rv;
full_bailout:
- usb_kill_urb(acm->readurb);
-bail_out_and_unlink:
usb_kill_urb(acm->ctrlurb);
bail_out:
acm->used--;
@@ -424,18 +487,22 @@ bail_out:
static void acm_tty_unregister(struct acm *acm)
{
+ int i;
+
tty_unregister_device(acm_tty_driver, acm->minor);
usb_put_intf(acm->control);
acm_table[acm->minor] = NULL;
usb_free_urb(acm->ctrlurb);
- usb_free_urb(acm->readurb);
usb_free_urb(acm->writeurb);
+ for (i = 0; i < ACM_NRU; i++)
+ usb_free_urb(acm->ru[i].urb);
kfree(acm);
}
static void acm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct acm *acm = tty->driver_data;
+ int i;
if (!acm || !acm->used)
return;
@@ -446,7 +513,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
acm_set_control(acm, acm->ctrlout = 0);
usb_kill_urb(acm->ctrlurb);
usb_kill_urb(acm->writeurb);
- usb_kill_urb(acm->readurb);
+ for (i = 0; i < ACM_NRU; i++)
+ usb_kill_urb(acm->ru[i].urb);
} else
acm_tty_unregister(acm);
}
@@ -528,10 +596,7 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
spin_lock_bh(&acm->throttle_lock);
acm->throttle = 0;
spin_unlock_bh(&acm->throttle_lock);
- if (acm->resubmit_to_unthrottle) {
- acm->resubmit_to_unthrottle = 0;
- acm_read_bulk(acm->readurb, NULL);
- }
+ tasklet_schedule(&acm->urb_task);
}
static void acm_tty_break_ctl(struct tty_struct *tty, int state)
@@ -588,7 +653,7 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
return -ENOIOCTLCMD;
}
-static __u32 acm_tty_speed[] = {
+static const __u32 acm_tty_speed[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600,
1200, 1800, 2400, 4800, 9600, 19200, 38400,
57600, 115200, 230400, 460800, 500000, 576000,
@@ -596,7 +661,7 @@ static __u32 acm_tty_speed[] = {
2500000, 3000000, 3500000, 4000000
};
-static __u8 acm_tty_size[] = {
+static const __u8 acm_tty_size[] = {
5, 6, 7, 8
};
@@ -694,6 +759,7 @@ static int acm_probe (struct usb_interface *intf,
int call_interface_num = -1;
int data_interface_num;
unsigned long quirks;
+ int i;
/* handle quirks deadly to normal probing*/
quirks = (unsigned long)id->driver_info;
@@ -833,7 +899,7 @@ skip_normal_probe:
}
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
- readsize = le16_to_cpu(epread->wMaxPacketSize);
+ readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
acm->control = control_interface;
acm->data = data_interface;
@@ -842,12 +908,14 @@ skip_normal_probe:
acm->ctrl_caps = ac_management_function;
acm->ctrlsize = ctrlsize;
acm->readsize = readsize;
- acm->bh.func = acm_rx_tasklet;
- acm->bh.data = (unsigned long) acm;
+ acm->urb_task.func = acm_rx_tasklet;
+ acm->urb_task.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint, acm);
spin_lock_init(&acm->throttle_lock);
spin_lock_init(&acm->write_lock);
+ spin_lock_init(&acm->read_lock);
acm->write_ready = 1;
+ acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
@@ -856,13 +924,6 @@ skip_normal_probe:
}
acm->ctrl_buffer = buf;
- buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
- if (!buf) {
- dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
- goto alloc_fail3;
- }
- acm->read_buffer = buf;
-
if (acm_write_buffers_alloc(acm) < 0) {
dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
goto alloc_fail4;
@@ -873,10 +934,25 @@ skip_normal_probe:
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
goto alloc_fail5;
}
- acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!acm->readurb) {
- dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
- goto alloc_fail6;
+ for (i = 0; i < ACM_NRU; i++) {
+ struct acm_ru *rcv = &(acm->ru[i]);
+
+ if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
+ goto alloc_fail7;
+ }
+
+ rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ rcv->instance = acm;
+ }
+ for (i = 0; i < ACM_NRB; i++) {
+ struct acm_rb *buf = &(acm->rb[i]);
+
+ // Using usb_buffer_alloc instead of kmalloc as Oliver suggested
+ if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
+ dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
+ goto alloc_fail7;
+ }
}
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) {
@@ -889,15 +965,9 @@ skip_normal_probe:
acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
acm->ctrlurb->transfer_dma = acm->ctrl_dma;
- usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
- acm->read_buffer, readsize, acm_read_bulk, acm);
- acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
- acm->readurb->transfer_dma = acm->read_dma;
-
usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
NULL, acm->writesize, acm_write_bulk, acm);
acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
- /* acm->writeurb->transfer_dma = 0; */
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
@@ -917,14 +987,14 @@ skip_normal_probe:
return 0;
alloc_fail7:
- usb_free_urb(acm->readurb);
-alloc_fail6:
+ for (i = 0; i < ACM_NRB; i++)
+ usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
+ for (i = 0; i < ACM_NRU; i++)
+ usb_free_urb(acm->ru[i].urb);
usb_free_urb(acm->ctrlurb);
alloc_fail5:
acm_write_buffers_free(acm);
alloc_fail4:
- usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
-alloc_fail3:
usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail2:
kfree(acm);
@@ -936,6 +1006,7 @@ static void acm_disconnect(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata (intf);
struct usb_device *usb_dev = interface_to_usbdev(intf);
+ int i;
if (!acm || !acm->dev) {
dbg("disconnect on nonexisting interface");
@@ -946,15 +1017,24 @@ static void acm_disconnect(struct usb_interface *intf)
acm->dev = NULL;
usb_set_intfdata (intf, NULL);
+ tasklet_disable(&acm->urb_task);
+
usb_kill_urb(acm->ctrlurb);
- usb_kill_urb(acm->readurb);
usb_kill_urb(acm->writeurb);
+ for (i = 0; i < ACM_NRU; i++)
+ usb_kill_urb(acm->ru[i].urb);
+
+ INIT_LIST_HEAD(&acm->filled_read_bufs);
+ INIT_LIST_HEAD(&acm->spare_read_bufs);
+
+ tasklet_enable(&acm->urb_task);
flush_scheduled_work(); /* wait for acm_softint */
acm_write_buffers_free(acm);
- usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
+ for (i = 0; i < ACM_NRB; i++)
+ usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
usb_driver_release_interface(&acm_driver, acm->data);
@@ -1003,7 +1083,6 @@ static struct usb_device_id acm_ids[] = {
MODULE_DEVICE_TABLE (usb, acm_ids);
static struct usb_driver acm_driver = {
- .owner = THIS_MODULE,
.name = "cdc_acm",
.probe = acm_probe,
.disconnect = acm_disconnect,
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index 963a5dfd2096..fd2aaccdcbac 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -59,6 +59,9 @@
* when processing onlcr, so we only need 2 buffers.
*/
#define ACM_NWB 2
+#define ACM_NRU 16
+#define ACM_NRB 16
+
struct acm_wb {
unsigned char *buf;
dma_addr_t dmah;
@@ -66,22 +69,43 @@ struct acm_wb {
int use;
};
+struct acm_rb {
+ struct list_head list;
+ int size;
+ unsigned char *base;
+ dma_addr_t dma;
+};
+
+struct acm_ru {
+ struct list_head list;
+ struct acm_rb *buffer;
+ struct urb *urb;
+ struct acm *instance;
+};
+
struct acm {
struct usb_device *dev; /* the corresponding usb device */
struct usb_interface *control; /* control interface */
struct usb_interface *data; /* data interface */
struct tty_struct *tty; /* the corresponding tty */
- struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
- u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */
- dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */
+ struct urb *ctrlurb, *writeurb; /* urbs */
+ u8 *ctrl_buffer; /* buffers of urbs */
+ dma_addr_t ctrl_dma; /* dma handles of buffers */
struct acm_wb wb[ACM_NWB];
+ struct acm_ru ru[ACM_NRU];
+ struct acm_rb rb[ACM_NRB];
+ int rx_endpoint;
+ spinlock_t read_lock;
+ struct list_head spare_read_urbs;
+ struct list_head spare_read_bufs;
+ struct list_head filled_read_bufs;
int write_current; /* current write buffer */
int write_used; /* number of non-empty write buffers */
int write_ready; /* write urb is not running */
spinlock_t write_lock;
struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
- struct tasklet_struct bh; /* rx processing */
+ struct tasklet_struct urb_task; /* rx processing */
spinlock_t throttle_lock; /* synchronize throtteling and read callback */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
@@ -91,7 +115,6 @@ struct acm {
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
- unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
};
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 5f8af35e7633..f13f004d311f 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -2027,7 +2027,6 @@ static struct usb_device_id id_table[] = {
};
static struct usb_driver usb_midi_driver = {
- .owner = THIS_MODULE,
.name = "midi",
.probe = usb_midi_probe,
.disconnect = usb_midi_disconnect,
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 357e75335f17..dba4cc026077 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
- * Copyright (c) 2000 Randy Dunlap <rddunlap@osdl.org>
+ * Copyright (c) 2000 Randy Dunlap <rdunlap@xenotime.net>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
@@ -199,7 +199,7 @@ struct quirk_printer_struct {
#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
-static struct quirk_printer_struct quirk_printers[] = {
+static const struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
@@ -301,7 +301,7 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
* Get and print printer errors.
*/
-static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
+static const char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
static int usblp_check_status(struct usblp *usblp, int err)
{
@@ -438,7 +438,7 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
| (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
}
-static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
int length, err, i;
@@ -838,7 +838,8 @@ static struct file_operations usblp_fops = {
.read = usblp_read,
.write = usblp_write,
.poll = usblp_poll,
- .ioctl = usblp_ioctl,
+ .unlocked_ioctl = usblp_ioctl,
+ .compat_ioctl = usblp_ioctl,
.open = usblp_open,
.release = usblp_release,
};
@@ -849,6 +850,20 @@ static struct usb_class_driver usblp_class = {
.minor_base = USBLP_MINOR_BASE,
};
+static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usblp *usblp = usb_get_intfdata (intf);
+
+ if (usblp->device_id_string[0] == 0 &&
+ usblp->device_id_string[1] == 0)
+ return 0;
+
+ return sprintf(buf, "%s", usblp->device_id_string+2);
+}
+
+static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL);
+
static int usblp_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -933,20 +948,12 @@ static int usblp_probe(struct usb_interface *intf,
/* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp);
+ device_create_file(&intf->dev, &dev_attr_ieee1284_id);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
- info("usblp%d: USB %sdirectional printer dev %d "
- "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
- usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
- usblp->ifnum,
- usblp->protocol[usblp->current_protocol].alt_setting,
- usblp->current_protocol,
- le16_to_cpu(usblp->dev->descriptor.idVendor),
- le16_to_cpu(usblp->dev->descriptor.idProduct));
-
usb_set_intfdata (intf, usblp);
usblp->present = 1;
@@ -957,11 +964,20 @@ static int usblp_probe(struct usb_interface *intf,
goto abort_intfdata;
}
usblp->minor = intf->minor;
+ info("usblp%d: USB %sdirectional printer dev %d "
+ "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+ usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
+ usblp->ifnum,
+ usblp->protocol[usblp->current_protocol].alt_setting,
+ usblp->current_protocol,
+ le16_to_cpu(usblp->dev->descriptor.idVendor),
+ le16_to_cpu(usblp->dev->descriptor.idProduct));
return 0;
abort_intfdata:
usb_set_intfdata (intf, NULL);
+ device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
abort:
if (usblp) {
if (usblp->writebuf)
@@ -1156,6 +1172,8 @@ static void usblp_disconnect(struct usb_interface *intf)
BUG ();
}
+ device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
+
down (&usblp_sem);
down (&usblp->sem);
usblp->present = 0;
@@ -1186,7 +1204,6 @@ static struct usb_device_id usblp_ids [] = {
MODULE_DEVICE_TABLE (usb, usblp_ids);
static struct usb_driver usblp_driver = {
- .owner = THIS_MODULE,
.name = "usblp",
.probe = usblp_probe,
.disconnect = usblp_disconnect,
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 86d5c380892d..28329ddf187c 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -2,7 +2,7 @@
# Makefile for USB Core files and filesystem
#
-usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
+usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o devio.o notify.o
ifeq ($(CONFIG_PCI),y)
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 419c9943a7cb..ad742cec94fa 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -55,6 +55,9 @@ int hcd_buffer_create (struct usb_hcd *hcd)
char name [16];
int i, size;
+ if (!hcd->self.controller->dma_mask)
+ return 0;
+
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (!(size = pool_max [i]))
continue;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 83e815d3cd52..2684e15b813b 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -67,45 +67,45 @@
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
-static char *format_topo =
+static const char *format_topo =
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
-static char *format_string_manufacturer =
+static const char *format_string_manufacturer =
/* S: Manufacturer=xxxx */
"S: Manufacturer=%.100s\n";
-static char *format_string_product =
+static const char *format_string_product =
/* S: Product=xxxx */
"S: Product=%.100s\n";
#ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
+static const char *format_string_serialnumber =
/* S: SerialNumber=xxxx */
"S: SerialNumber=%.100s\n";
#endif
-static char *format_bandwidth =
+static const char *format_bandwidth =
/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
"B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-static char *format_device1 =
+static const char *format_device1 =
/* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
"D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
-static char *format_device2 =
+static const char *format_device2 =
/* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
"P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
-static char *format_config =
+static const char *format_config =
/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
"C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-static char *format_iface =
+static const char *format_iface =
/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
"I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
-static char *format_endpt =
+static const char *format_endpt =
/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
"E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
@@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
struct usb_device *childdev = usbdev->children[chix];
if (childdev) {
- down(&childdev->serialize);
+ usb_lock_device(childdev);
ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
bus, level + 1, chix, ++cnt);
- up(&childdev->serialize);
+ usb_unlock_device(childdev);
if (ret == -EFAULT)
return total_written;
total_written += ret;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index b1d6e9af732d..2b68998fe4b3 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -402,7 +402,6 @@ static void driver_disconnect(struct usb_interface *intf)
}
struct usb_driver usbfs_driver = {
- .owner = THIS_MODULE,
.name = "usbfs",
.probe = driver_probe,
.disconnect = driver_disconnect,
@@ -1350,9 +1349,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
usb_unlock_device(ps->dev);
- usb_lock_all_devices();
bus_rescan_devices(intf->dev.bus);
- usb_unlock_all_devices();
usb_lock_device(ps->dev);
break;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
new file mode 100644
index 000000000000..076462c8ba2a
--- /dev/null
+++ b/drivers/usb/core/driver.c
@@ -0,0 +1,472 @@
+/*
+ * drivers/usb/driver.c - most of the driver model stuff for usb
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000-2004
+ * (C) Copyright Yggdrasil Computing, Inc. 2000
+ * (usb_device_id matching changes by Adam J. Richter)
+ * (C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ * NOTE! This is not actually a driver at all, rather this is
+ * just a collection of helper routines that implement the
+ * generic USB things that the real drivers can use..
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+#include "hcd.h"
+#include "usb.h"
+
+static int usb_match_one_id(struct usb_interface *interface,
+ const struct usb_device_id *id);
+
+struct usb_dynid {
+ struct list_head node;
+ struct usb_device_id id;
+};
+
+
+static int generic_probe(struct device *dev)
+{
+ return 0;
+}
+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;
+}
+
+struct device_driver usb_generic_driver = {
+ .owner = THIS_MODULE,
+ .name = "usb",
+ .bus = &usb_bus_type,
+ .probe = generic_probe,
+ .remove = generic_remove,
+};
+
+/* Fun hack to determine if the struct device is a
+ * usb device or a usb interface. */
+int usb_generic_driver_data;
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Adds a new dynamic USBdevice ID to this driver,
+ * and cause the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *driver,
+ const char *buf, size_t count)
+{
+ struct usb_driver *usb_drv = to_usb_driver(driver);
+ struct usb_dynid *dynid;
+ u32 idVendor = 0;
+ u32 idProduct = 0;
+ int fields = 0;
+
+ fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
+ if (fields < 2)
+ return -EINVAL;
+
+ dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+ if (!dynid)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&dynid->node);
+ dynid->id.idVendor = idVendor;
+ dynid->id.idProduct = idProduct;
+ dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+
+ spin_lock(&usb_drv->dynids.lock);
+ list_add_tail(&usb_drv->dynids.list, &dynid->node);
+ spin_unlock(&usb_drv->dynids.lock);
+
+ if (get_driver(driver)) {
+ driver_attach(driver);
+ put_driver(driver);
+ }
+
+ return count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+ int error = 0;
+
+ if (usb_drv->no_dynamic_id)
+ goto exit;
+
+ if (usb_drv->probe != NULL)
+ error = sysfs_create_file(&usb_drv->driver.kobj,
+ &driver_attr_new_id.attr);
+exit:
+ return error;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+ if (usb_drv->no_dynamic_id)
+ return;
+
+ if (usb_drv->probe != NULL)
+ sysfs_remove_file(&usb_drv->driver.kobj,
+ &driver_attr_new_id.attr);
+}
+
+static void usb_free_dynids(struct usb_driver *usb_drv)
+{
+ struct usb_dynid *dynid, *n;
+
+ spin_lock(&usb_drv->dynids.lock);
+ list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
+ list_del(&dynid->node);
+ kfree(dynid);
+ }
+ spin_unlock(&usb_drv->dynids.lock);
+}
+#else
+static inline int usb_create_newid_file(struct usb_driver *usb_drv)
+{
+ return 0;
+}
+
+static void usb_remove_newid_file(struct usb_driver *usb_drv)
+{
+}
+
+static inline void usb_free_dynids(struct usb_driver *usb_drv)
+{
+}
+#endif
+
+static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
+ struct usb_driver *drv)
+{
+ struct usb_dynid *dynid;
+
+ spin_lock(&drv->dynids.lock);
+ list_for_each_entry(dynid, &drv->dynids.list, node) {
+ if (usb_match_one_id(intf, &dynid->id)) {
+ spin_unlock(&drv->dynids.lock);
+ return &dynid->id;
+ }
+ }
+ spin_unlock(&drv->dynids.lock);
+ return NULL;
+}
+
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_probe_interface(struct device *dev)
+{
+ struct usb_interface * intf = to_usb_interface(dev);
+ struct usb_driver * driver = to_usb_driver(dev->driver);
+ const struct usb_device_id *id;
+ int error = -ENODEV;
+
+ dev_dbg(dev, "%s\n", __FUNCTION__);
+
+ if (!driver->probe)
+ return error;
+ /* FIXME we'd much prefer to just resume it ... */
+ if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+ return -EHOSTUNREACH;
+
+ id = usb_match_id(intf, driver->id_table);
+ if (!id)
+ id = usb_match_dynamic_id(intf, driver);
+ if (id) {
+ dev_dbg(dev, "%s - got id\n", __FUNCTION__);
+
+ /* Interface "power state" doesn't correspond to any hardware
+ * state whatsoever. We use it to record when it's bound to
+ * a driver that may start I/0: it's not frozen/quiesced.
+ */
+ mark_active(intf);
+ intf->condition = USB_INTERFACE_BINDING;
+ error = driver->probe(intf, id);
+ if (error) {
+ mark_quiesced(intf);
+ intf->condition = USB_INTERFACE_UNBOUND;
+ } else
+ intf->condition = USB_INTERFACE_BOUND;
+ }
+
+ return error;
+}
+
+/* called from driver core with usb_bus_type.subsys writelock */
+static int usb_unbind_interface(struct device *dev)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+
+ intf->condition = USB_INTERFACE_UNBINDING;
+
+ /* release all urbs for this interface */
+ usb_disable_interface(interface_to_usbdev(intf), intf);
+
+ if (driver && driver->disconnect)
+ driver->disconnect(intf);
+
+ /* reset other interface state */
+ usb_set_interface(interface_to_usbdev(intf),
+ intf->altsetting[0].desc.bInterfaceNumber,
+ 0);
+ usb_set_intfdata(intf, NULL);
+ intf->condition = USB_INTERFACE_UNBOUND;
+ mark_quiesced(intf);
+
+ return 0;
+}
+
+/* returns 0 if no match, 1 if match */
+static int usb_match_one_id(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_host_interface *intf;
+ struct usb_device *dev;
+
+ /* proc_connectinfo in devio.c may call us with id == NULL. */
+ if (id == NULL)
+ return 0;
+
+ intf = interface->cur_altsetting;
+ dev = interface_to_usbdev(interface);
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+ id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
+ id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
+ return 0;
+
+ /* No need to test id->bcdDevice_lo != 0, since 0 is never
+ greater than any unsigned number. */
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
+ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
+ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
+ (id->bDeviceClass != dev->descriptor.bDeviceClass))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
+ (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
+ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
+ (id->bInterfaceClass != intf->desc.bInterfaceClass))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
+ (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
+ return 0;
+
+ if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
+ (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
+ return 0;
+
+ return 1;
+}
+/**
+ * usb_match_id - find first usb_device_id matching device or interface
+ * @interface: the interface of interest
+ * @id: array of usb_device_id structures, terminated by zero entry
+ *
+ * usb_match_id searches an array of usb_device_id's and returns
+ * the first one matching the device or interface, or null.
+ * This is used when binding (or rebinding) a driver to an interface.
+ * Most USB device drivers will use this indirectly, through the usb core,
+ * but some layered driver frameworks use it directly.
+ * These device tables are exported with MODULE_DEVICE_TABLE, through
+ * modutils, to support the driver loading functionality of USB hotplugging.
+ *
+ * What Matches:
+ *
+ * The "match_flags" element in a usb_device_id controls which
+ * members are used. If the corresponding bit is set, the
+ * value in the device_id must match its corresponding member
+ * in the device or interface descriptor, or else the device_id
+ * does not match.
+ *
+ * "driver_info" is normally used only by device drivers,
+ * but you can create a wildcard "matches anything" usb_device_id
+ * as a driver's "modules.usbmap" entry if you provide an id with
+ * only a nonzero "driver_info" field. If you do this, the USB device
+ * driver's probe() routine should use additional intelligence to
+ * decide whether to bind to the specified interface.
+ *
+ * What Makes Good usb_device_id Tables:
+ *
+ * The match algorithm is very simple, so that intelligence in
+ * driver selection must come from smart driver id records.
+ * Unless you have good reasons to use another selection policy,
+ * provide match elements only in related groups, and order match
+ * specifiers from specific to general. Use the macros provided
+ * for that purpose if you can.
+ *
+ * The most specific match specifiers use device descriptor
+ * data. These are commonly used with product-specific matches;
+ * the USB_DEVICE macro lets you provide vendor and product IDs,
+ * and you can also match against ranges of product revisions.
+ * These are widely used for devices with application or vendor
+ * specific bDeviceClass values.
+ *
+ * Matches based on device class/subclass/protocol specifications
+ * are slightly more general; use the USB_DEVICE_INFO macro, or
+ * its siblings. These are used with single-function devices
+ * where bDeviceClass doesn't specify that each interface has
+ * its own class.
+ *
+ * Matches based on interface class/subclass/protocol are the
+ * most general; they let drivers bind to any interface on a
+ * multiple-function device. Use the USB_INTERFACE_INFO
+ * macro, or its siblings, to match class-per-interface style
+ * devices (as recorded in bDeviceClass).
+ *
+ * Within those groups, remember that not all combinations are
+ * meaningful. For example, don't give a product version range
+ * without vendor and product IDs; or specify a protocol without
+ * its associated class and subclass.
+ */
+const struct usb_device_id *usb_match_id(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ /* proc_connectinfo in devio.c may call us with id == NULL. */
+ if (id == NULL)
+ return NULL;
+
+ /* It is important to check that id->driver_info is nonzero,
+ since an entry that is all zeroes except for a nonzero
+ id->driver_info is the way to create an entry that
+ indicates that the driver want to examine every
+ device and interface. */
+ for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+ id->driver_info; id++) {
+ if (usb_match_one_id(interface, id))
+ return id;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(usb_match_id);
+
+int usb_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct usb_interface *intf;
+ struct usb_driver *usb_drv;
+ const struct usb_device_id *id;
+
+ /* check for generic driver, which we don't match any device with */
+ if (drv == &usb_generic_driver)
+ return 0;
+
+ intf = to_usb_interface(dev);
+ usb_drv = to_usb_driver(drv);
+
+ id = usb_match_id(intf, usb_drv->id_table);
+ if (id)
+ return 1;
+
+ id = usb_match_dynamic_id(intf, usb_drv);
+ if (id)
+ return 1;
+ return 0;
+}
+
+/**
+ * usb_register_driver - register a USB driver
+ * @new_driver: USB operations for the driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB driver with the USB core. The list of unattached
+ * interfaces will be rescanned whenever a new driver is added, allowing
+ * the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ *
+ * NOTE: if you want your driver to use the USB major number, you must call
+ * usb_register_dev() to enable that functionality. This function no longer
+ * takes care of that.
+ */
+int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
+{
+ int retval = 0;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ new_driver->driver.name = (char *)new_driver->name;
+ new_driver->driver.bus = &usb_bus_type;
+ new_driver->driver.probe = usb_probe_interface;
+ new_driver->driver.remove = usb_unbind_interface;
+ new_driver->driver.owner = owner;
+ spin_lock_init(&new_driver->dynids.lock);
+ INIT_LIST_HEAD(&new_driver->dynids.list);
+
+ retval = driver_register(&new_driver->driver);
+
+ if (!retval) {
+ pr_info("%s: registered new driver %s\n",
+ usbcore_name, new_driver->name);
+ usbfs_update_special();
+ usb_create_newid_file(new_driver);
+ } else {
+ printk(KERN_ERR "%s: error %d registering driver %s\n",
+ usbcore_name, retval, new_driver->name);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_driver);
+
+/**
+ * usb_deregister - unregister a USB driver
+ * @driver: USB operations of the driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ *
+ * NOTE: If you called usb_register_dev(), you still need to call
+ * usb_deregister_dev() to clean up your driver's allocated minor numbers,
+ * this * call will no longer do it for you.
+ */
+void usb_deregister(struct usb_driver *driver)
+{
+ pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+
+ usb_remove_newid_file(driver);
+ usb_free_dynids(driver);
+ driver_unregister(&driver->driver);
+
+ usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index da24c31ee00d..0018bbc4de34 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -857,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
return (retval < 0) ? retval : -EMSGSIZE;
}
- usb_lock_device (usb_dev);
retval = usb_new_device (usb_dev);
- usb_unlock_device (usb_dev);
if (retval) {
usb_dev->bus->root_hub = NULL;
dev_err (parent_dev, "can't register root hub for %s, %d\n",
@@ -1827,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
retval = -ENOMEM;
goto err_allocate_root_hub;
}
- rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
- USB_SPEED_FULL;
/* Although in principle hcd->driver->start() might need to use rhdev,
* none of the current drivers do.
@@ -1846,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup;
+ rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
+ USB_SPEED_FULL;
+ rhdev->bus_mA = min(500u, hcd->power_budget);
if ((retval = register_root_hub(rhdev, hcd)) != 0)
goto err_register_root_hub;
@@ -1891,7 +1890,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 0;
spin_unlock_irq (&hcd_root_hub_lock);
+
+ down(&usb_bus_list_lock);
usb_disconnect(&hcd->self.root_hub);
+ up(&usb_bus_list_lock);
hcd->poll_rh = 0;
del_timer_sync(&hcd->rh_timer);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index c8a1b350e2cf..591b5aad1a18 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -380,6 +380,7 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#ifdef CONFIG_PM
extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
+extern void usb_root_hub_lost_power (struct usb_device *rhdev);
extern int hcd_bus_suspend (struct usb_bus *bus);
extern int hcd_bus_resume (struct usb_bus *bus);
#else
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f78bd124d290..650d5ee5871b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -32,7 +32,7 @@
#include "hub.h"
/* Protect struct usb_device->state and ->children members
- * Note: Both are also protected by ->serialize, except that ->state can
+ * Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
static DEFINE_SPINLOCK(device_state_lock);
@@ -515,6 +515,31 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
return ret;
}
+
+/* caller has locked the hub device */
+static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
+{
+ struct usb_device *hdev = hub->hdev;
+ int port1;
+
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ if (hdev->children[port1 - 1]) {
+ usb_disconnect(&hdev->children[port1 - 1]);
+ if (disable_ports)
+ hub_port_disable(hub, port1, 0);
+ }
+ }
+ hub_quiesce(hub);
+}
+
+/* caller has locked the hub device */
+static void hub_post_reset(struct usb_hub *hub)
+{
+ hub_activate(hub);
+ hub_power_on(hub);
+}
+
+
static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
@@ -677,26 +702,40 @@ static int hub_configure(struct usb_hub *hub,
* and battery-powered root hubs (may provide just 8 mA).
*/
ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
- if (ret < 0) {
+ if (ret < 2) {
message = "can't get hub status";
goto fail;
}
le16_to_cpus(&hubstatus);
if (hdev == hdev->bus->root_hub) {
- struct usb_hcd *hcd =
- container_of(hdev->bus, struct usb_hcd, self);
-
- hub->power_budget = min(500u, hcd->power_budget) / 2;
+ if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
+ hub->mA_per_port = 500;
+ else {
+ hub->mA_per_port = hdev->bus_mA;
+ hub->limited_power = 1;
+ }
} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
hub->descriptor->bHubContrCurrent);
- hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
- / 2;
+ hub->limited_power = 1;
+ if (hdev->maxchild > 0) {
+ int remaining = hdev->bus_mA -
+ hub->descriptor->bHubContrCurrent;
+
+ if (remaining < hdev->maxchild * 100)
+ dev_warn(hub_dev,
+ "insufficient power available "
+ "to use all downstream ports\n");
+ hub->mA_per_port = 100; /* 7.2.1.1 */
+ }
+ } else { /* Self-powered external hub */
+ /* FIXME: What about battery-powered external hubs that
+ * provide less current per port? */
+ hub->mA_per_port = 500;
}
- if (hub->power_budget)
- dev_dbg(hub_dev, "%dmA bus power budget for children\n",
- hub->power_budget * 2);
-
+ if (hub->mA_per_port < 500)
+ dev_dbg(hub_dev, "%umA bus power budget for each child\n",
+ hub->mA_per_port);
ret = hub_hub_status(hub, &hubstatus, &hubchange);
if (ret < 0) {
@@ -750,29 +789,10 @@ 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;
usb_set_intfdata (intf, NULL);
hdev = hub->hdev;
@@ -780,7 +800,9 @@ static void hub_disconnect(struct usb_interface *intf)
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
- hub_quiesce(hub);
+ /* Disconnect all children and quiesce the hub */
+ hub_pre_reset(hub, 1);
+
usb_free_urb(hub->urb);
hub->urb = NULL;
@@ -800,27 +822,7 @@ static void hub_disconnect(struct usb_interface *intf)
hub->buffer = NULL;
}
- /* 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);
- }
+ kfree(hub);
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -917,26 +919,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
}
}
-/* caller has locked the hub device */
-static void hub_pre_reset(struct usb_hub *hub)
-{
- struct usb_device *hdev = hub->hdev;
- int i;
-
- for (i = 0; i < hdev->maxchild; ++i) {
- if (hdev->children[i])
- usb_disconnect(&hdev->children[i]);
- }
- hub_quiesce(hub);
-}
-
-/* caller has locked the hub device */
-static void hub_post_reset(struct usb_hub *hub)
-{
- hub_activate(hub);
- hub_power_on(hub);
-}
-
/* grab device/port lock, returning index of that port (zero based).
* protects the upstream link used by this device from concurrent
@@ -964,24 +946,21 @@ static int locktree(struct usb_device *udev)
t = locktree(hdev);
if (t < 0)
return t;
- for (t = 0; t < hdev->maxchild; t++) {
- if (hdev->children[t] == udev) {
- /* everything is fail-fast once disconnect
- * processing starts
- */
- if (udev->state == USB_STATE_NOTATTACHED)
- break;
- /* when everyone grabs locks top->bottom,
- * non-overlapping work may be concurrent
- */
- down(&udev->serialize);
- up(&hdev->serialize);
- return t + 1;
- }
+ /* everything is fail-fast once disconnect
+ * processing starts
+ */
+ if (udev->state == USB_STATE_NOTATTACHED) {
+ usb_unlock_device(hdev);
+ return -ENODEV;
}
+
+ /* when everyone grabs locks top->bottom,
+ * non-overlapping work may be concurrent
+ */
+ usb_lock_device(udev);
usb_unlock_device(hdev);
- return -ENODEV;
+ return udev->portnum;
}
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
@@ -1039,6 +1018,39 @@ void usb_set_device_state(struct usb_device *udev,
EXPORT_SYMBOL(usb_set_device_state);
+#ifdef CONFIG_PM
+
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset. The routine marks all the children of the root hub
+ * as NOTATTACHED and marks logical connect-change events on their ports.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+ struct usb_hub *hub;
+ int port1;
+ unsigned long flags;
+
+ dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+ spin_lock_irqsave(&device_state_lock, flags);
+ hub = hdev_to_hub(rhdev);
+ for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
+ if (rhdev->children[port1 - 1]) {
+ recursively_mark_NOTATTACHED(
+ rhdev->children[port1 - 1]);
+ set_bit(port1, hub->change_bits);
+ }
+ }
+ spin_unlock_irqrestore(&device_state_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
+#endif
+
static void choose_address(struct usb_device *udev)
{
int devnum;
@@ -1099,16 +1111,10 @@ void usb_disconnect(struct usb_device **pdev)
* this quiesces everyting except pending urbs.
*/
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-
- /* lock the bus list on behalf of HCDs unregistering their root hubs */
- if (!udev->parent) {
- down(&usb_bus_list_lock);
- usb_lock_device(udev);
- } else
- down(&udev->serialize);
-
dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
+ usb_lock_device(udev);
+
/* Free up all the children before we remove this device */
for (i = 0; i < USB_MAXCHILDREN; i++) {
if (udev->children[i])
@@ -1136,54 +1142,112 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
spin_unlock_irq(&device_state_lock);
- if (!udev->parent) {
- usb_unlock_device(udev);
- up(&usb_bus_list_lock);
- } else
- up(&udev->serialize);
+ usb_unlock_device(udev);
device_unregister(&udev->dev);
}
+static inline const char *plural(int n)
+{
+ return (n == 1 ? "" : "s");
+}
+
static int choose_configuration(struct usb_device *udev)
{
- int c, i;
+ int i;
+ u16 devstatus;
+ int bus_powered;
+ int num_configs;
+ struct usb_host_config *c, *best;
+
+ /* If this fails, assume the device is bus-powered */
+ devstatus = 0;
+ usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+ le16_to_cpus(&devstatus);
+ bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
+ dev_dbg(&udev->dev, "device is %s-powered\n",
+ bus_powered ? "bus" : "self");
+
+ best = NULL;
+ c = udev->config;
+ num_configs = udev->descriptor.bNumConfigurations;
+ for (i = 0; i < num_configs; (i++, c++)) {
+ struct usb_interface_descriptor *desc =
+ &c->intf_cache[0]->altsetting->desc;
+
+ /*
+ * HP's USB bus-powered keyboard has only one configuration
+ * and it claims to be self-powered; other devices may have
+ * similar errors in their descriptors. If the next test
+ * were allowed to execute, such configurations would always
+ * be rejected and the devices would not work as expected.
+ */
+#if 0
+ /* Rule out self-powered configs for a bus-powered device */
+ if (bus_powered && (c->desc.bmAttributes &
+ USB_CONFIG_ATT_SELFPOWER))
+ continue;
+#endif
- /* NOTE: this should interact with hub power budgeting */
+ /*
+ * The next test may not be as effective as it should be.
+ * Some hubs have errors in their descriptor, claiming
+ * to be self-powered when they are really bus-powered.
+ * We will overestimate the amount of current such hubs
+ * make available for each port.
+ *
+ * This is a fairly benign sort of failure. It won't
+ * cause us to reject configurations that we should have
+ * accepted.
+ */
- c = udev->config[0].desc.bConfigurationValue;
- if (udev->descriptor.bNumConfigurations != 1) {
- for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
- struct usb_interface_descriptor *desc;
+ /* Rule out configs that draw too much bus current */
+ if (c->desc.bMaxPower * 2 > udev->bus_mA)
+ continue;
- /* heuristic: Linux is more likely to have class
- * drivers, so avoid vendor-specific interfaces.
- */
- desc = &udev->config[i].intf_cache[0]
- ->altsetting->desc;
- if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
- continue;
- /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS.
- * MSFT needs this to be the first config; never use
- * it as the default unless Linux has host-side RNDIS.
- * A second config would ideally be CDC-Ethernet, but
- * may instead be the "vendor specific" CDC subset
- * long used by ARM Linux for sa1100 or pxa255.
- */
- if (desc->bInterfaceClass == USB_CLASS_COMM
- && desc->bInterfaceSubClass == 2
- && desc->bInterfaceProtocol == 0xff) {
- c = udev->config[1].desc.bConfigurationValue;
- continue;
- }
- c = udev->config[i].desc.bConfigurationValue;
+ /* If the first config's first interface is COMM/2/0xff
+ * (MSFT RNDIS), rule it out unless Linux has host-side
+ * RNDIS support. */
+ if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
+ && desc->bInterfaceSubClass == 2
+ && desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS
+ continue;
+#else
+ best = c;
+#endif
+ }
+
+ /* From the remaining configs, choose the first one whose
+ * first interface is for a non-vendor-specific class.
+ * Reason: Linux is more likely to have a class driver
+ * than a vendor-specific driver. */
+ else if (udev->descriptor.bDeviceClass !=
+ USB_CLASS_VENDOR_SPEC &&
+ desc->bInterfaceClass !=
+ USB_CLASS_VENDOR_SPEC) {
+ best = c;
break;
}
+
+ /* If all the remaining configs are vendor-specific,
+ * choose the first one. */
+ else if (!best)
+ best = c;
+ }
+
+ if (best) {
+ i = best->desc.bConfigurationValue;
dev_info(&udev->dev,
- "configuration #%d chosen from %d choices\n",
- c, udev->descriptor.bNumConfigurations);
+ "configuration #%d chosen from %d choice%s\n",
+ i, num_configs, plural(num_configs));
+ } else {
+ i = -1;
+ dev_warn(&udev->dev,
+ "no configuration chosen from %d choice%s\n",
+ num_configs, plural(num_configs));
}
- return c;
+ return i;
}
#ifdef DEBUG
@@ -1210,8 +1274,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
- * for any device configuration. The caller must have locked udev and
- * either the parent hub (if udev is a normal device) or else the
+ * for any device configuration. The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
* usb_bus_list_lock (if udev is a root hub). The parent's pointer to
* udev has already been installed, but udev is not yet visible through
* sysfs or other filesystem code.
@@ -1221,8 +1285,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
*
* This call is synchronous, and may not be used in an interrupt context.
*
- * Only the hub driver should ever call this; root hub registration
- * uses it indirectly.
+ * Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
{
@@ -1269,15 +1332,9 @@ int usb_new_device(struct usb_device *udev)
le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
- unsigned port1;
+ unsigned port1 = udev->portnum;
struct usb_device *root = udev->parent;
- for (port1 = 1; port1 <= root->maxchild;
- port1++) {
- if (root->children[port1-1] == udev)
- break;
- }
-
dev_info(&udev->dev,
"Dual-Role OTG device on %sHNP port\n",
(port1 == bus->otg_port)
@@ -1331,27 +1388,27 @@ int usb_new_device(struct usb_device *udev)
}
usb_create_sysfs_dev_files (udev);
+ usb_lock_device(udev);
+
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
*/
c = choose_configuration(udev);
- if (c < 0)
- dev_warn(&udev->dev,
- "can't choose an initial configuration\n");
- else {
+ if (c >= 0) {
err = usb_set_configuration(udev, c);
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
- usb_remove_sysfs_dev_files(udev);
- device_del(&udev->dev);
- goto fail;
+ /* This need not be fatal. The user can try to
+ * set other configurations. */
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
+ usb_unlock_device(udev);
+
return 0;
fail:
@@ -1654,15 +1711,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
int usb_suspend_device(struct usb_device *udev)
{
#ifdef CONFIG_USB_SUSPEND
- int port1, status;
-
- port1 = locktree(udev);
- if (port1 < 0)
- return port1;
-
- status = __usb_suspend_device(udev, port1);
- usb_unlock_device(udev);
- return status;
+ if (udev->state == USB_STATE_NOTATTACHED)
+ return -ENODEV;
+ return __usb_suspend_device(udev, udev->portnum);
#else
/* NOTE: udev->state unchanged, it's not lying ... */
udev->dev.power.power_state = PMSG_SUSPEND;
@@ -1694,13 +1745,14 @@ static int finish_device_resume(struct usb_device *udev)
usb_set_device_state(udev, udev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
+ udev->dev.power.power_state = PMSG_ON;
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
* and device drivers will know about any resume quirks.
*/
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
- if (status < 0)
+ if (status < 2)
dev_dbg(&udev->dev,
"gone after usb resume? status %d\n",
status);
@@ -1709,7 +1761,7 @@ static int finish_device_resume(struct usb_device *udev)
int (*resume)(struct device *);
le16_to_cpus(&devstatus);
- if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
+ if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
&& udev->parent) {
status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
@@ -1729,8 +1781,14 @@ static int finish_device_resume(struct usb_device *udev)
* may have a child resume event to deal with soon
*/
resume = udev->dev.bus->resume;
- for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
- (void) resume(&udev->actconfig->interface[i]->dev);
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ struct device *dev =
+ &udev->actconfig->interface[i]->dev;
+
+ down(&dev->sem);
+ (void) resume(dev);
+ up(&dev->sem);
+ }
status = 0;
} else if (udev->devnum <= 0) {
@@ -1813,11 +1871,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
*/
int usb_resume_device(struct usb_device *udev)
{
- int port1, status;
+ int status;
- port1 = locktree(udev);
- if (port1 < 0)
- return port1;
+ if (udev->state == USB_STATE_NOTATTACHED)
+ return -ENODEV;
#ifdef CONFIG_USB_SUSPEND
/* selective resume of one downstream hub-to-device port */
@@ -1826,7 +1883,7 @@ int usb_resume_device(struct usb_device *udev)
// NOTE swsusp may bork us, device state being wrong...
// NOTE this fails if parent is also suspended...
status = hub_port_resume(hdev_to_hub(udev->parent),
- port1, udev);
+ udev->portnum, udev);
} else
status = 0;
} else
@@ -1836,13 +1893,11 @@ int usb_resume_device(struct usb_device *udev)
dev_dbg(&udev->dev, "can't resume, status %d\n",
status);
- usb_unlock_device(udev);
-
/* rebind drivers that had no suspend() */
if (status == 0) {
- usb_lock_all_devices();
+ usb_unlock_device(udev);
bus_rescan_devices(&usb_bus_type);
- usb_unlock_all_devices();
+ usb_lock_device(udev);
}
return status;
}
@@ -1856,14 +1911,14 @@ static int remote_wakeup(struct usb_device *udev)
/* don't repeat RESUME sequence if this device
* was already woken up by some other task
*/
- down(&udev->serialize);
+ usb_lock_device(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "RESUME (wakeup)\n");
/* TRSMRCY = 10 msec */
msleep(10);
status = finish_device_resume(udev);
}
- up(&udev->serialize);
+ usb_unlock_device(udev);
#endif
return status;
}
@@ -1964,7 +2019,7 @@ static int hub_resume(struct usb_interface *intf)
if (!udev || status < 0)
continue;
- down (&udev->serialize);
+ usb_lock_device(udev);
if (portstat & USB_PORT_STAT_SUSPEND)
status = hub_port_resume(hub, port1, udev);
else {
@@ -1975,7 +2030,7 @@ static int hub_resume(struct usb_interface *intf)
hub_port_logical_disconnect(hub, port1);
}
}
- up(&udev->serialize);
+ usb_unlock_device(udev);
}
}
#endif
@@ -2359,39 +2414,36 @@ hub_power_remaining (struct usb_hub *hub)
{
struct usb_device *hdev = hub->hdev;
int remaining;
- unsigned i;
+ int port1;
- remaining = hub->power_budget;
- if (!remaining) /* self-powered */
+ if (!hub->limited_power)
return 0;
- for (i = 0; i < hdev->maxchild; i++) {
- struct usb_device *udev = hdev->children[i];
- int delta, ceiling;
+ remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ struct usb_device *udev = hdev->children[port1 - 1];
+ int delta;
if (!udev)
continue;
- /* 100mA per-port ceiling, or 8mA for OTG ports */
- if (i != (udev->bus->otg_port - 1) || hdev->parent)
- ceiling = 50;
- else
- ceiling = 4;
-
+ /* Unconfigured devices may not use more than 100mA,
+ * or 8mA for OTG ports */
if (udev->actconfig)
- delta = udev->actconfig->desc.bMaxPower;
+ delta = udev->actconfig->desc.bMaxPower * 2;
+ else if (port1 != udev->bus->otg_port || hdev->parent)
+ delta = 100;
else
- delta = ceiling;
- // dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta);
- if (delta > ceiling)
- dev_warn(&udev->dev, "%dmA over %dmA budget!\n",
- 2 * (delta - ceiling), 2 * ceiling);
+ delta = 8;
+ if (delta > hub->mA_per_port)
+ dev_warn(&udev->dev, "%dmA is over %umA budget "
+ "for port %d!\n",
+ delta, hub->mA_per_port, port1);
remaining -= delta;
}
if (remaining < 0) {
- dev_warn(hub->intfdev,
- "%dmA over power budget!\n",
- -2 * remaining);
+ dev_warn(hub->intfdev, "%dmA over power budget!\n",
+ - remaining);
remaining = 0;
}
return remaining;
@@ -2486,7 +2538,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
usb_set_device_state(udev, USB_STATE_POWERED);
udev->speed = USB_SPEED_UNKNOWN;
-
+ udev->bus_mA = hub->mA_per_port;
+
/* set the address */
choose_address(udev);
if (udev->devnum <= 0) {
@@ -2506,16 +2559,16 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* on the parent.
*/
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
- && hub->power_budget) {
+ && udev->bus_mA <= 100) {
u16 devstat;
status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
&devstat);
- if (status < 0) {
+ if (status < 2) {
dev_dbg(&udev->dev, "get status %d ?\n", status);
goto loop_disable;
}
- cpu_to_le16s(&devstat);
+ le16_to_cpus(&devstat);
if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
dev_err(&udev->dev,
"can't connect bus-powered hub "
@@ -2540,7 +2593,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* udev becomes globally accessible, although presumably
* no one will look at it until hdev is unlocked.
*/
- down (&udev->serialize);
status = 0;
/* We mustn't add new devices if the parent hub has
@@ -2564,15 +2616,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
}
- up (&udev->serialize);
if (status)
goto loop_disable;
status = hub_power_remaining(hub);
if (status)
- dev_dbg(hub_dev,
- "%dmA power budget left\n",
- 2 * status);
+ dev_dbg(hub_dev, "%dmA power budget left\n", status);
return;
@@ -2648,6 +2697,8 @@ static void hub_events(void)
if (i) {
dpm_runtime_resume(&hdev->dev);
dpm_runtime_resume(&intf->dev);
+ usb_put_intf(intf);
+ continue;
}
/* Lock the device, then check to see if we were
@@ -2661,7 +2712,7 @@ static void hub_events(void)
/* If the hub has died, clean up after it */
if (hdev->state == USB_STATE_NOTATTACHED) {
- hub_pre_reset(hub);
+ hub_pre_reset(hub, 0);
goto loop;
}
@@ -2784,6 +2835,11 @@ static void hub_events(void)
if (hubchange & HUB_CHANGE_LOCAL_POWER) {
dev_dbg (hub_dev, "power change\n");
clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
+ if (hubstatus & HUB_STATUS_LOCAL_POWER)
+ /* FIXME: Is this always true? */
+ hub->limited_power = 0;
+ else
+ hub->limited_power = 1;
}
if (hubchange & HUB_CHANGE_OVERCURRENT) {
dev_dbg (hub_dev, "overcurrent change\n");
@@ -2832,7 +2888,6 @@ static struct usb_device_id hub_id_table [] = {
MODULE_DEVICE_TABLE (usb, hub_id_table);
static struct usb_driver hub_driver = {
- .owner = THIS_MODULE,
.name = "hub",
.probe = hub_probe,
.disconnect = hub_disconnect,
@@ -2944,7 +2999,8 @@ int usb_reset_device(struct usb_device *udev)
struct usb_hub *parent_hub;
struct usb_device_descriptor descriptor = udev->descriptor;
struct usb_hub *hub = NULL;
- int i, ret = 0, port1 = -1;
+ int i, ret = 0;
+ int port1 = udev->portnum;
if (udev->state == USB_STATE_NOTATTACHED ||
udev->state == USB_STATE_SUSPENDED) {
@@ -2958,18 +3014,6 @@ int usb_reset_device(struct usb_device *udev)
dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
return -EISDIR;
}
-
- for (i = 0; i < parent_hdev->maxchild; i++)
- if (parent_hdev->children[i] == udev) {
- port1 = i + 1;
- break;
- }
-
- if (port1 < 0) {
- /* If this ever happens, it's very bad */
- dev_err(&udev->dev, "Can't locate device's port!\n");
- return -ENOENT;
- }
parent_hub = hdev_to_hub(parent_hdev);
/* If we're resetting an active hub, take some special actions */
@@ -2977,7 +3021,7 @@ int usb_reset_device(struct usb_device *udev)
udev->actconfig->interface[0]->dev.driver ==
&hub_driver.driver &&
(hub = hdev_to_hub(udev)) != NULL) {
- hub_pre_reset(hub);
+ hub_pre_reset(hub, 0);
}
set_bit(port1, parent_hub->busy_bits);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index bf23f8978024..29d5f45a8456 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -220,8 +220,9 @@ struct usb_hub {
struct usb_hub_descriptor *descriptor; /* class descriptor */
struct usb_tt tt; /* Transaction Translator */
- u8 power_budget; /* in 2mA units; or zero */
+ unsigned mA_per_port; /* current for each child */
+ unsigned limited_power:1;
unsigned quiescing:1;
unsigned activating:1;
unsigned resume_root_hub:1;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index c44bbedec817..3cf945cc5b9a 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -184,13 +184,13 @@ static void update_bus(struct dentry *bus)
bus->d_inode->i_gid = busgid;
bus->d_inode->i_mode = S_IFDIR | busmode;
- down(&bus->d_inode->i_sem);
+ mutex_lock(&bus->d_inode->i_mutex);
- list_for_each_entry(dev, &bus->d_subdirs, d_child)
+ list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child)
if (dev->d_inode)
update_dev(dev);
- up(&bus->d_inode->i_sem);
+ mutex_unlock(&bus->d_inode->i_mutex);
}
static void update_sb(struct super_block *sb)
@@ -201,9 +201,9 @@ static void update_sb(struct super_block *sb)
if (!root)
return;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
- list_for_each_entry(bus, &root->d_subdirs, d_child) {
+ list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) {
if (bus->d_inode) {
switch (S_IFMT & bus->d_inode->i_mode) {
case S_IFDIR:
@@ -219,7 +219,7 @@ static void update_sb(struct super_block *sb)
}
}
- up(&root->d_inode->i_sem);
+ mutex_unlock(&root->d_inode->i_mutex);
}
static int remount(struct super_block *sb, int *flags, char *data)
@@ -319,7 +319,7 @@ static int usbfs_empty (struct dentry *dentry)
spin_lock(&dcache_lock);
list_for_each(list, &dentry->d_subdirs) {
- struct dentry *de = list_entry(list, struct dentry, d_child);
+ struct dentry *de = list_entry(list, struct dentry, d_u.d_child);
if (usbfs_positive(de)) {
spin_unlock(&dcache_lock);
return 0;
@@ -333,10 +333,10 @@ static int usbfs_empty (struct dentry *dentry)
static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
dentry->d_inode->i_nlink--;
dput(dentry);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
d_delete(dentry);
return 0;
}
@@ -346,7 +346,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
int error = -ENOTEMPTY;
struct inode * inode = dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
dentry_unhash(dentry);
if (usbfs_empty(dentry)) {
dentry->d_inode->i_nlink -= 2;
@@ -355,7 +355,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
dir->i_nlink--;
error = 0;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (!error)
d_delete(dentry);
dput(dentry);
@@ -380,7 +380,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
{
loff_t retval = -EINVAL;
- down(&file->f_dentry->d_inode->i_sem);
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
switch(orig) {
case 0:
if (offset > 0) {
@@ -397,7 +397,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
default:
break;
}
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return retval;
}
@@ -480,7 +480,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
}
*dentry = NULL;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
@@ -489,7 +489,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
error = usbfs_create (parent->d_inode, *dentry, mode);
} else
error = PTR_ERR(dentry);
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
@@ -528,7 +528,7 @@ static void fs_remove_file (struct dentry *dentry)
if (!parent || !parent->d_inode)
return;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
if (usbfs_positive(dentry)) {
if (dentry->d_inode) {
if (S_ISDIR(dentry->d_inode->i_mode))
@@ -538,7 +538,7 @@ static void fs_remove_file (struct dentry *dentry)
dput(dentry);
}
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
}
/* --------------------------------------------------------------------- */
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index fe74f99ca5f4..319de03944e7 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1387,6 +1387,12 @@ free_interfaces:
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device (dev, 1); // Skip ep0
+ i = dev->bus_mA - cp->desc.bMaxPower * 2;
+ if (i < 0)
+ dev_warn(&dev->dev, "new config #%d exceeds power "
+ "limit by %dmA\n",
+ configuration, -i);
+
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index e80ef9467825..13d1d367f7f1 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -32,7 +32,6 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
-#include <linux/rwsem.h>
#include <linux/usb.h>
#include <asm/io.h>
@@ -47,165 +46,7 @@
const char *usbcore_name = "usbcore";
static int nousb; /* Disable USB when built into kernel image */
- /* Not honored on modular build */
-static DECLARE_RWSEM(usb_all_devices_rwsem);
-
-
-static int generic_probe (struct device *dev)
-{
- return 0;
-}
-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;
-}
-
-static struct device_driver usb_generic_driver = {
- .owner = THIS_MODULE,
- .name = "usb",
- .bus = &usb_bus_type,
- .probe = generic_probe,
- .remove = generic_remove,
-};
-
-static int usb_generic_driver_data;
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_probe_interface(struct device *dev)
-{
- struct usb_interface * intf = to_usb_interface(dev);
- struct usb_driver * driver = to_usb_driver(dev->driver);
- const struct usb_device_id *id;
- int error = -ENODEV;
-
- dev_dbg(dev, "%s\n", __FUNCTION__);
-
- if (!driver->probe)
- return error;
- /* FIXME we'd much prefer to just resume it ... */
- if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
- return -EHOSTUNREACH;
-
- id = usb_match_id (intf, driver->id_table);
- if (id) {
- dev_dbg (dev, "%s - got id\n", __FUNCTION__);
-
- /* Interface "power state" doesn't correspond to any hardware
- * state whatsoever. We use it to record when it's bound to
- * a driver that may start I/0: it's not frozen/quiesced.
- */
- mark_active(intf);
- intf->condition = USB_INTERFACE_BINDING;
- error = driver->probe (intf, id);
- if (error) {
- mark_quiesced(intf);
- intf->condition = USB_INTERFACE_UNBOUND;
- } else
- intf->condition = USB_INTERFACE_BOUND;
- }
-
- return error;
-}
-
-/* called from driver core with usb_bus_type.subsys writelock */
-static int usb_unbind_interface(struct device *dev)
-{
- struct usb_interface *intf = to_usb_interface(dev);
- struct usb_driver *driver = to_usb_driver(intf->dev.driver);
-
- intf->condition = USB_INTERFACE_UNBINDING;
-
- /* release all urbs for this interface */
- usb_disable_interface(interface_to_usbdev(intf), intf);
-
- if (driver && driver->disconnect)
- driver->disconnect(intf);
-
- /* reset other interface state */
- usb_set_interface(interface_to_usbdev(intf),
- intf->altsetting[0].desc.bInterfaceNumber,
- 0);
- usb_set_intfdata(intf, NULL);
- intf->condition = USB_INTERFACE_UNBOUND;
- mark_quiesced(intf);
-
- return 0;
-}
-
-/**
- * usb_register - register a USB driver
- * @new_driver: USB operations for the driver
- *
- * Registers a USB driver with the USB core. The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
- * Returns a negative error code on failure and 0 on success.
- *
- * NOTE: if you want your driver to use the USB major number, you must call
- * usb_register_dev() to enable that functionality. This function no longer
- * takes care of that.
- */
-int usb_register(struct usb_driver *new_driver)
-{
- int retval = 0;
-
- if (nousb)
- return -ENODEV;
-
- new_driver->driver.name = (char *)new_driver->name;
- new_driver->driver.bus = &usb_bus_type;
- new_driver->driver.probe = usb_probe_interface;
- new_driver->driver.remove = usb_unbind_interface;
- new_driver->driver.owner = new_driver->owner;
-
- usb_lock_all_devices();
- retval = driver_register(&new_driver->driver);
- usb_unlock_all_devices();
-
- if (!retval) {
- pr_info("%s: registered new driver %s\n",
- usbcore_name, new_driver->name);
- usbfs_update_special();
- } else {
- printk(KERN_ERR "%s: error %d registering driver %s\n",
- usbcore_name, retval, new_driver->name);
- }
-
- return retval;
-}
-
-/**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
- * Context: must be able to sleep
- *
- * Unlinks the specified driver from the internal USB driver list.
- *
- * NOTE: If you called usb_register_dev(), you still need to call
- * usb_deregister_dev() to clean up your driver's allocated minor numbers,
- * this * call will no longer do it for you.
- */
-void usb_deregister(struct usb_driver *driver)
-{
- pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
-
- usb_lock_all_devices();
- driver_unregister (&driver->driver);
- usb_unlock_all_devices();
-
- usbfs_update_special();
-}
/**
* usb_ifnum_to_if - get the interface object with a given interface number
@@ -352,151 +193,23 @@ void usb_driver_release_interface(struct usb_driver *driver,
mark_quiesced(iface);
}
-/**
- * usb_match_id - find first usb_device_id matching device or interface
- * @interface: the interface of interest
- * @id: array of usb_device_id structures, terminated by zero entry
- *
- * usb_match_id searches an array of usb_device_id's and returns
- * the first one matching the device or interface, or null.
- * This is used when binding (or rebinding) a driver to an interface.
- * Most USB device drivers will use this indirectly, through the usb core,
- * but some layered driver frameworks use it directly.
- * These device tables are exported with MODULE_DEVICE_TABLE, through
- * modutils and "modules.usbmap", to support the driver loading
- * functionality of USB hotplugging.
- *
- * What Matches:
- *
- * The "match_flags" element in a usb_device_id controls which
- * members are used. If the corresponding bit is set, the
- * value in the device_id must match its corresponding member
- * in the device or interface descriptor, or else the device_id
- * does not match.
- *
- * "driver_info" is normally used only by device drivers,
- * but you can create a wildcard "matches anything" usb_device_id
- * as a driver's "modules.usbmap" entry if you provide an id with
- * only a nonzero "driver_info" field. If you do this, the USB device
- * driver's probe() routine should use additional intelligence to
- * decide whether to bind to the specified interface.
- *
- * What Makes Good usb_device_id Tables:
- *
- * The match algorithm is very simple, so that intelligence in
- * driver selection must come from smart driver id records.
- * Unless you have good reasons to use another selection policy,
- * provide match elements only in related groups, and order match
- * specifiers from specific to general. Use the macros provided
- * for that purpose if you can.
- *
- * The most specific match specifiers use device descriptor
- * data. These are commonly used with product-specific matches;
- * the USB_DEVICE macro lets you provide vendor and product IDs,
- * and you can also match against ranges of product revisions.
- * These are widely used for devices with application or vendor
- * specific bDeviceClass values.
- *
- * Matches based on device class/subclass/protocol specifications
- * are slightly more general; use the USB_DEVICE_INFO macro, or
- * its siblings. These are used with single-function devices
- * where bDeviceClass doesn't specify that each interface has
- * its own class.
- *
- * Matches based on interface class/subclass/protocol are the
- * most general; they let drivers bind to any interface on a
- * multiple-function device. Use the USB_INTERFACE_INFO
- * macro, or its siblings, to match class-per-interface style
- * devices (as recorded in bDeviceClass).
- *
- * Within those groups, remember that not all combinations are
- * meaningful. For example, don't give a product version range
- * without vendor and product IDs; or specify a protocol without
- * its associated class and subclass.
- */
-const struct usb_device_id *
-usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
-{
- struct usb_host_interface *intf;
- struct usb_device *dev;
-
- /* proc_connectinfo in devio.c may call us with id == NULL. */
- if (id == NULL)
- return NULL;
-
- intf = interface->cur_altsetting;
- dev = interface_to_usbdev(interface);
-
- /* It is important to check that id->driver_info is nonzero,
- since an entry that is all zeroes except for a nonzero
- id->driver_info is the way to create an entry that
- indicates that the driver want to examine every
- device and interface. */
- for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
- id->driver_info; id++) {
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
- id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
- id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
- continue;
-
- /* No need to test id->bcdDevice_lo != 0, since 0 is never
- greater than any unsigned number. */
- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
- (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
- (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
- (id->bDeviceClass != dev->descriptor.bDeviceClass))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
- (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
- (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
- (id->bInterfaceClass != intf->desc.bInterfaceClass))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
- (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
- continue;
-
- if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
- (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
- continue;
-
- return id;
- }
-
- return NULL;
-}
-
+struct find_interface_arg {
+ int minor;
+ struct usb_interface *interface;
+};
static int __find_interface(struct device * dev, void * data)
{
- struct usb_interface ** ret = (struct usb_interface **)data;
- struct usb_interface * intf = *ret;
- int *minor = (int *)data;
+ struct find_interface_arg *arg = data;
+ struct usb_interface *intf;
/* can't look at usb devices, only interfaces */
if (dev->driver == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
- if (intf->minor != -1 && intf->minor == *minor) {
- *ret = intf;
+ if (intf->minor != -1 && intf->minor == arg->minor) {
+ arg->interface = intf;
return 1;
}
return 0;
@@ -513,42 +226,18 @@ static int __find_interface(struct device * dev, void * data)
*/
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
{
- struct usb_interface *intf = (struct usb_interface *)(long)minor;
- int ret;
-
- ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
-
- return ret ? intf : NULL;
-}
-
-static int usb_device_match (struct device *dev, struct device_driver *drv)
-{
- struct usb_interface *intf;
- struct usb_driver *usb_drv;
- const struct usb_device_id *id;
-
- /* check for generic driver, which we don't match any device with */
- if (drv == &usb_generic_driver)
- return 0;
-
- intf = to_usb_interface(dev);
- usb_drv = to_usb_driver(drv);
-
- id = usb_match_id (intf, usb_drv->id_table);
- if (id)
- return 1;
+ struct find_interface_arg argb;
- return 0;
+ argb.minor = minor;
+ argb.interface = NULL;
+ driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+ return argb.interface;
}
-
#ifdef CONFIG_HOTPLUG
/*
- * USB hotplugging invokes what /proc/sys/kernel/hotplug says
- * (normally /sbin/hotplug) when USB devices get added or removed.
- *
- * This invokes a user mode policy agent, typically helping to load driver
+ * This sends an uevent to userspace, typically helping to load driver
* or other modules, configure the device, and more. Drivers can provide
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
*
@@ -557,8 +246,8 @@ static int usb_device_match (struct device *dev, struct device_driver *drv)
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
* device (and this configuration!) are still present.
*/
-static int usb_hotplug (struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
{
struct usb_interface *intf;
struct usb_device *usb_dev;
@@ -570,7 +259,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
return -ENODEV;
/* driver is often null here; dev_dbg() would oops */
- pr_debug ("usb %s: hotplug\n", dev->bus_id);
+ pr_debug ("usb %s: uevent\n", dev->bus_id);
/* Must check driver_data here, as on remove driver is always NULL */
if ((dev->driver == &usb_generic_driver) ||
@@ -597,51 +286,51 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
*
* FIXME reduce hardwired intelligence here
*/
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "DEVICE=/proc/bus/usb/%03d/%03d",
- usb_dev->bus->busnum, usb_dev->devnum))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEVICE=/proc/bus/usb/%03d/%03d",
+ usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM;
#endif
/* per-device configurations are common */
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PRODUCT=%x/%x/%x",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PRODUCT=%x/%x/%x",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM;
/* class-based driver binding models */
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "TYPE=%d/%d/%d",
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "TYPE=%d/%d/%d",
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "INTERFACE=%d/%d/%d",
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "INTERFACE=%d/%d/%d",
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
return -ENOMEM;
- if (add_hotplug_env_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
- le16_to_cpu(usb_dev->descriptor.idVendor),
- le16_to_cpu(usb_dev->descriptor.idProduct),
- le16_to_cpu(usb_dev->descriptor.bcdDevice),
- usb_dev->descriptor.bDeviceClass,
- usb_dev->descriptor.bDeviceSubClass,
- usb_dev->descriptor.bDeviceProtocol,
- alt->desc.bInterfaceClass,
- alt->desc.bInterfaceSubClass,
- alt->desc.bInterfaceProtocol))
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice),
+ usb_dev->descriptor.bDeviceClass,
+ usb_dev->descriptor.bDeviceSubClass,
+ usb_dev->descriptor.bDeviceProtocol,
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol))
return -ENOMEM;
envp[i] = NULL;
@@ -651,7 +340,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
#else
-static int usb_hotplug (struct device *dev, char **envp,
+static int usb_uevent(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size)
{
return -ENODEV;
@@ -750,12 +439,11 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
/* hub driver sets up TT records */
}
+ dev->portnum = port1;
dev->bus = bus;
dev->parent = parent;
INIT_LIST_HEAD(&dev->filelist);
- init_MUTEX(&dev->serialize);
-
return dev;
}
@@ -828,76 +516,21 @@ void usb_put_intf(struct usb_interface *intf)
/* USB device locking
*
- * Although locking USB devices should be straightforward, it is
- * complicated by the way the driver-model core works. When a new USB
- * driver is registered or unregistered, the core will automatically
- * probe or disconnect all matching interfaces on all USB devices while
- * holding the USB subsystem writelock. There's no good way for us to
- * tell which devices will be used or to lock them beforehand; our only
- * option is to effectively lock all the USB devices.
- *
- * We do that by using a private rw-semaphore, usb_all_devices_rwsem.
- * When locking an individual device you must first acquire the rwsem's
- * readlock. When a driver is registered or unregistered the writelock
- * must be held. These actions are encapsulated in the subroutines
- * below, so all a driver needs to do is call usb_lock_device() and
- * usb_unlock_device().
+ * USB devices and interfaces are locked using the semaphore in their
+ * embedded struct device. The hub driver guarantees that whenever a
+ * device is connected or disconnected, drivers are called with the
+ * USB device locked as well as their particular interface.
*
* Complications arise when several devices are to be locked at the same
* time. Only hub-aware drivers that are part of usbcore ever have to
- * do this; nobody else needs to worry about it. The problem is that
- * usb_lock_device() must not be called to lock a second device since it
- * would acquire the rwsem's readlock reentrantly, leading to deadlock if
- * another thread was waiting for the writelock. The solution is simple:
- *
- * When locking more than one device, call usb_lock_device()
- * to lock the first one. Lock the others by calling
- * down(&udev->serialize) directly.
- *
- * When unlocking multiple devices, use up(&udev->serialize)
- * to unlock all but the last one. Unlock the last one by
- * calling usb_unlock_device().
+ * do this; nobody else needs to worry about it. The rule for locking
+ * is simple:
*
* When locking both a device and its parent, always lock the
* the parent first.
*/
/**
- * usb_lock_device - acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Use this routine when you don't hold any other device locks;
- * to acquire nested inner locks call down(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_lock_device(struct usb_device *udev)
-{
- down_read(&usb_all_devices_rwsem);
- down(&udev->serialize);
-}
-
-/**
- * usb_trylock_device - attempt to acquire the lock for a usb device structure
- * @udev: device that's being locked
- *
- * Don't use this routine if you already hold a device lock;
- * use down_trylock(&udev->serialize) instead.
- * This is necessary for proper interaction with usb_lock_all_devices().
- *
- * Returns 1 if successful, 0 if contention.
- */
-int usb_trylock_device(struct usb_device *udev)
-{
- if (!down_read_trylock(&usb_all_devices_rwsem))
- return 0;
- if (down_trylock(&udev->serialize)) {
- up_read(&usb_all_devices_rwsem);
- return 0;
- }
- return 1;
-}
-
-/**
* usb_lock_device_for_reset - cautiously acquire the lock for a
* usb device structure
* @udev: device that's being locked
@@ -935,7 +568,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
}
- while (!usb_trylock_device(udev)) {
+ while (usb_trylock_device(udev) != 0) {
/* If we can't acquire the lock after waiting one second,
* we're probably deadlocked */
@@ -953,39 +586,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
return 1;
}
-/**
- * usb_unlock_device - release the lock for a usb device structure
- * @udev: device that's being unlocked
- *
- * Use this routine when releasing the only device lock you hold;
- * to release inner nested locks call up(&udev->serialize) directly.
- * This is necessary for proper interaction with usb_lock_all_devices().
- */
-void usb_unlock_device(struct usb_device *udev)
-{
- up(&udev->serialize);
- up_read(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_lock_all_devices - acquire the lock for all usb device structures
- *
- * This is necessary when registering a new driver or probing a bus,
- * since the driver-model core may try to use any usb_device.
- */
-void usb_lock_all_devices(void)
-{
- down_write(&usb_all_devices_rwsem);
-}
-
-/**
- * usb_unlock_all_devices - release the lock for all usb device structures
- */
-void usb_unlock_all_devices(void)
-{
- up_write(&usb_all_devices_rwsem);
-}
-
static struct usb_device *match_device(struct usb_device *dev,
u16 vendor_id, u16 product_id)
@@ -1008,10 +608,10 @@ static struct usb_device *match_device(struct usb_device *dev,
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
- down(&dev->children[child]->serialize);
+ usb_lock_device(dev->children[child]);
ret_dev = match_device(dev->children[child],
vendor_id, product_id);
- up(&dev->children[child]->serialize);
+ usb_unlock_device(dev->children[child]);
if (ret_dev)
goto exit;
}
@@ -1491,23 +1091,13 @@ static int usb_generic_resume(struct device *dev)
struct bus_type usb_bus_type = {
.name = "usb",
.match = usb_device_match,
- .hotplug = usb_hotplug,
+ .uevent = usb_uevent,
.suspend = usb_generic_suspend,
.resume = usb_generic_resume,
};
-#ifndef MODULE
-
-static int __init usb_setup_disable(char *str)
-{
- nousb = 1;
- return 1;
-}
-
/* format to disable USB on kernel command line is: nousb */
-__setup("nousb", usb_setup_disable);
-
-#endif
+__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
/*
* for external read access to <nousb>
@@ -1598,8 +1188,6 @@ module_exit(usb_exit);
* driver modules to use.
*/
-EXPORT_SYMBOL(usb_register);
-EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_disabled);
EXPORT_SYMBOL_GPL(usb_get_intf);
@@ -1610,14 +1198,10 @@ EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);
EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
-EXPORT_SYMBOL(usb_lock_device);
-EXPORT_SYMBOL(usb_trylock_device);
EXPORT_SYMBOL(usb_lock_device_for_reset);
-EXPORT_SYMBOL(usb_unlock_device);
EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_driver_release_interface);
-EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c4a68499dce..4647e1ebc68d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -16,9 +16,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
-extern void usb_lock_all_devices(void);
-extern void usb_unlock_all_devices(void);
-
extern void usb_kick_khubd(struct usb_device *dev);
extern void usb_suspend_root_hub(struct usb_device *hdev);
extern void usb_resume_root_hub(struct usb_device *dev);
@@ -33,6 +30,9 @@ extern void usb_host_cleanup(void);
extern int usb_suspend_device(struct usb_device *dev);
extern int usb_resume_device(struct usb_device *dev);
+extern struct device_driver usb_generic_driver;
+extern int usb_generic_driver_data;
+extern int usb_device_match(struct device *dev, struct device_driver *drv);
/* Interfaces and their "power state" are owned by usbcore */
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index c655d46c8aed..9734cb76dd6c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -138,7 +138,7 @@ static const char *const ep_name [] = {
/* or like sa1100: two fixed function endpoints */
"ep1out-bulk", "ep2in-bulk",
};
-#define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *))
+#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
/*-------------------------------------------------------------------------*/
@@ -896,7 +896,7 @@ dummy_gadget_release (struct device *dev)
#endif
}
-static int dummy_udc_probe (struct platform_device *dev)
+static int dummy_udc_probe (struct platform_device *pdev)
{
struct dummy *dum = the_controller;
int rc;
@@ -909,7 +909,7 @@ static int dummy_udc_probe (struct platform_device *dev)
dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
strcpy (dum->gadget.dev.bus_id, "gadget");
- dum->gadget.dev.parent = &dev->dev;
+ dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register (&dum->gadget.dev);
if (rc < 0)
@@ -919,47 +919,47 @@ static int dummy_udc_probe (struct platform_device *dev)
usb_bus_get (&dummy_to_hcd (dum)->self);
#endif
- platform_set_drvdata (dev, dum);
+ platform_set_drvdata (pdev, dum);
device_create_file (&dum->gadget.dev, &dev_attr_function);
return rc;
}
-static int dummy_udc_remove (struct platform_device *dev)
+static int dummy_udc_remove (struct platform_device *pdev)
{
- struct dummy *dum = platform_get_drvdata (dev);
+ struct dummy *dum = platform_get_drvdata (pdev);
- platform_set_drvdata (dev, NULL);
+ platform_set_drvdata (pdev, NULL);
device_remove_file (&dum->gadget.dev, &dev_attr_function);
device_unregister (&dum->gadget.dev);
return 0;
}
-static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
{
- struct dummy *dum = platform_get_drvdata(dev);
+ struct dummy *dum = platform_get_drvdata(pdev);
- dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 1;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
- dev->dev.power.power_state = state;
+ pdev->dev.power.power_state = state;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
-static int dummy_udc_resume (struct platform_device *dev)
+static int dummy_udc_resume (struct platform_device *pdev)
{
- struct dummy *dum = platform_get_drvdata(dev);
+ struct dummy *dum = platform_get_drvdata(pdev);
- dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 0;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
- dev->dev.power.power_state = PMSG_ON;
+ pdev->dev.power.power_state = PMSG_ON;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
@@ -1576,7 +1576,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
dum = hcd_to_dummy (hcd);
spin_lock_irqsave (&dum->lock, flags);
- if (hcd->state != HC_STATE_RUNNING)
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
goto done;
if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@@ -1623,7 +1623,7 @@ static int dummy_hub_control (
int retval = 0;
unsigned long flags;
- if (hcd->state != HC_STATE_RUNNING)
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
return -ETIMEDOUT;
dum = hcd_to_dummy (hcd);
@@ -1756,9 +1756,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
+
spin_lock_irq (&dum->lock);
dum->rh_state = DUMMY_RH_SUSPENDED;
set_link_state (dum);
+ hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irq (&dum->lock);
return 0;
}
@@ -1766,14 +1769,23 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
static int dummy_bus_resume (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
+ int rc = 0;
+
+ dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
- dum->rh_state = DUMMY_RH_RUNNING;
- set_link_state (dum);
- if (!list_empty(&dum->urbp_list))
- mod_timer (&dum->timer, jiffies);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
+ rc = -ENODEV;
+ } else {
+ dum->rh_state = DUMMY_RH_RUNNING;
+ set_link_state (dum);
+ if (!list_empty(&dum->urbp_list))
+ mod_timer (&dum->timer, jiffies);
+ hcd->state = HC_STATE_RUNNING;
+ }
spin_unlock_irq (&dum->lock);
- return 0;
+ return rc;
}
/*-------------------------------------------------------------------------*/
@@ -1899,14 +1911,14 @@ static const struct hc_driver dummy_hcd = {
.bus_resume = dummy_bus_resume,
};
-static int dummy_hcd_probe (struct platform_device *dev)
+static int dummy_hcd_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
int retval;
- dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
- hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);
+ hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
if (!hcd)
return -ENOMEM;
the_controller = hcd_to_dummy (hcd);
@@ -1919,36 +1931,43 @@ static int dummy_hcd_probe (struct platform_device *dev)
return retval;
}
-static int dummy_hcd_remove (struct platform_device *dev)
+static int dummy_hcd_remove (struct platform_device *pdev)
{
struct usb_hcd *hcd;
- hcd = platform_get_drvdata (dev);
+ hcd = platform_get_drvdata (pdev);
usb_remove_hcd (hcd);
usb_put_hcd (hcd);
the_controller = NULL;
return 0;
}
-static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state)
+static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd;
+ struct dummy *dum;
+ int rc = 0;
- dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
- hcd = platform_get_drvdata (dev);
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
- hcd->state = HC_STATE_SUSPENDED;
- return 0;
+ hcd = platform_get_drvdata (pdev);
+ dum = hcd_to_dummy (hcd);
+ if (dum->rh_state == DUMMY_RH_RUNNING) {
+ dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
+ rc = -EBUSY;
+ } else
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ return rc;
}
-static int dummy_hcd_resume (struct platform_device *dev)
+static int dummy_hcd_resume (struct platform_device *pdev)
{
struct usb_hcd *hcd;
- dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
- hcd = platform_get_drvdata (dev);
- hcd->state = HC_STATE_RUNNING;
+ dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
+ hcd = platform_get_drvdata (pdev);
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
usb_hcd_poll_rh_status (hcd);
return 0;
}
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8f402f85e1ca..afc84cfb61f9 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driver = {
.driver = {
.name = (char *) shortname,
.owner = THIS_MODULE,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index ea09aaa3cab6..de59c58896d6 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -224,6 +224,7 @@
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/kref.h>
#include <linux/kthread.h>
#include <linux/limits.h>
#include <linux/list.h>
@@ -238,7 +239,6 @@
#include <linux/string.h>
#include <linux/suspend.h>
#include <linux/utsname.h>
-#include <linux/wait.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
@@ -250,7 +250,7 @@
#define DRIVER_DESC "File-backed Storage Gadget"
#define DRIVER_NAME "g_file_storage"
-#define DRIVER_VERSION "20 October 2004"
+#define DRIVER_VERSION "28 November 2005"
static const char longname[] = DRIVER_DESC;
static const char shortname[] = DRIVER_NAME;
@@ -335,8 +335,8 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MAX_LUNS 8
/* Arggh! There should be a module_param_array_named macro! */
-static char *file[MAX_LUNS] = {NULL, };
-static int ro[MAX_LUNS] = {0, };
+static char *file[MAX_LUNS];
+static int ro[MAX_LUNS];
static struct {
int num_filenames;
@@ -587,7 +587,7 @@ enum fsg_buffer_state {
struct fsg_buffhd {
void *buf;
dma_addr_t dma;
- volatile enum fsg_buffer_state state;
+ enum fsg_buffer_state state;
struct fsg_buffhd *next;
/* The NetChip 2280 is faster, and handles some protocol faults
@@ -596,9 +596,9 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length;
struct usb_request *inreq;
- volatile int inreq_busy;
+ int inreq_busy;
struct usb_request *outreq;
- volatile int outreq_busy;
+ int outreq_busy;
};
enum fsg_state {
@@ -631,13 +631,16 @@ struct fsg_dev {
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
+ /* reference counting: wait until all LUNs are released */
+ struct kref ref;
+
struct usb_ep *ep0; // Handy copy of gadget->ep0
struct usb_request *ep0req; // For control responses
- volatile unsigned int ep0_req_tag;
+ unsigned int ep0_req_tag;
const char *ep0req_name;
struct usb_request *intreq; // For interrupt responses
- volatile int intreq_busy;
+ int intreq_busy;
struct fsg_buffhd *intr_buffhd;
unsigned int bulk_out_maxpacket;
@@ -667,7 +670,6 @@ struct fsg_dev {
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[NUM_BUFFERS];
- wait_queue_head_t thread_wqh;
int thread_wakeup_needed;
struct completion thread_notifier;
struct task_struct *thread_task;
@@ -694,7 +696,6 @@ struct fsg_dev {
unsigned int nluns;
struct lun *luns;
struct lun *curlun;
- struct completion lun_released;
};
typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -1073,11 +1074,13 @@ static int populate_config_buf(struct usb_gadget *gadget,
/* These routines may be called in process context or in_irq */
+/* Caller must hold fsg->lock */
static void wakeup_thread(struct fsg_dev *fsg)
{
/* Tell the main thread that something has happened */
fsg->thread_wakeup_needed = 1;
- wake_up_all(&fsg->thread_wqh);
+ if (fsg->thread_task)
+ wake_up_process(fsg->thread_task);
}
@@ -1164,11 +1167,12 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
+ smp_wmb();
spin_lock(&fsg->lock);
bh->inreq_busy = 0;
bh->state = BUF_STATE_EMPTY;
- spin_unlock(&fsg->lock);
wakeup_thread(fsg);
+ spin_unlock(&fsg->lock);
}
static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
@@ -1185,11 +1189,12 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
+ smp_wmb();
spin_lock(&fsg->lock);
bh->outreq_busy = 0;
bh->state = BUF_STATE_FULL;
- spin_unlock(&fsg->lock);
wakeup_thread(fsg);
+ spin_unlock(&fsg->lock);
}
@@ -1206,11 +1211,12 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
+ smp_wmb();
spin_lock(&fsg->lock);
fsg->intreq_busy = 0;
bh->state = BUF_STATE_EMPTY;
- spin_unlock(&fsg->lock);
wakeup_thread(fsg);
+ spin_unlock(&fsg->lock);
}
#else
@@ -1261,8 +1267,8 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
fsg->cbbuf_cmnd_size = req->actual;
memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
- spin_unlock(&fsg->lock);
wakeup_thread(fsg);
+ spin_unlock(&fsg->lock);
}
#else
@@ -1514,8 +1520,8 @@ static int fsg_setup(struct usb_gadget *gadget,
/* Use this for bulk or interrupt transfers, not ep0 */
static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
- struct usb_request *req, volatile int *pbusy,
- volatile enum fsg_buffer_state *state)
+ struct usb_request *req, int *pbusy,
+ enum fsg_buffer_state *state)
{
int rc;
@@ -1523,8 +1529,11 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
dump_msg(fsg, "bulk-in", req->buf, req->length);
else if (ep == fsg->intr_in)
dump_msg(fsg, "intr-in", req->buf, req->length);
+
+ spin_lock_irq(&fsg->lock);
*pbusy = 1;
*state = BUF_STATE_BUSY;
+ spin_unlock_irq(&fsg->lock);
rc = usb_ep_queue(ep, req, GFP_KERNEL);
if (rc != 0) {
*pbusy = 0;
@@ -1544,14 +1553,23 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
static int sleep_thread(struct fsg_dev *fsg)
{
- int rc;
+ int rc = 0;
/* Wait until a signal arrives or we are woken up */
- rc = wait_event_interruptible(fsg->thread_wqh,
- fsg->thread_wakeup_needed);
+ for (;;) {
+ try_to_freeze();
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
+ if (fsg->thread_wakeup_needed)
+ break;
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
fsg->thread_wakeup_needed = 0;
- try_to_freeze();
- return (rc ? -EINTR : 0);
+ return rc;
}
@@ -1788,6 +1806,7 @@ static int do_write(struct fsg_dev *fsg)
if (bh->state == BUF_STATE_EMPTY && !get_some_more)
break; // We stopped early
if (bh->state == BUF_STATE_FULL) {
+ smp_rmb();
fsg->next_buffhd_to_drain = bh->next;
bh->state = BUF_STATE_EMPTY;
@@ -1872,7 +1891,7 @@ static int fsync_sub(struct lun *curlun)
return -EINVAL;
inode = filp->f_dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
current->flags |= PF_SYNCWRITE;
rc = filemap_fdatawrite(inode->i_mapping);
err = filp->f_op->fsync(filp, filp->f_dentry, 1);
@@ -1882,7 +1901,7 @@ static int fsync_sub(struct lun *curlun)
if (!rc)
rc = err;
current->flags &= ~PF_SYNCWRITE;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
VLDBG(curlun, "fdatasync -> %d\n", rc);
return rc;
}
@@ -2356,6 +2375,7 @@ static int throw_away_data(struct fsg_dev *fsg)
/* Throw away the data in a filled buffer */
if (bh->state == BUF_STATE_FULL) {
+ smp_rmb();
bh->state = BUF_STATE_EMPTY;
fsg->next_buffhd_to_drain = bh->next;
@@ -3021,6 +3041,7 @@ static int get_next_command(struct fsg_dev *fsg)
if ((rc = sleep_thread(fsg)) != 0)
return rc;
}
+ smp_rmb();
rc = received_cbw(fsg, bh);
bh->state = BUF_STATE_EMPTY;
@@ -3642,11 +3663,19 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
/*-------------------------------------------------------------------------*/
+static void fsg_release(struct kref *ref)
+{
+ struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
+
+ kfree(fsg->luns);
+ kfree(fsg);
+}
+
static void lun_release(struct device *dev)
{
struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
- complete(&fsg->lun_released);
+ kref_put(&fsg->ref, fsg_release);
}
static void fsg_unbind(struct usb_gadget *gadget)
@@ -3660,14 +3689,12 @@ static void fsg_unbind(struct usb_gadget *gadget)
clear_bit(REGISTERED, &fsg->atomic_bitflags);
/* Unregister the sysfs attribute files and the LUNs */
- init_completion(&fsg->lun_released);
for (i = 0; i < fsg->nluns; ++i) {
curlun = &fsg->luns[i];
if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file);
device_unregister(&curlun->dev);
- wait_for_completion(&fsg->lun_released);
curlun->registered = 0;
}
}
@@ -3846,6 +3873,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
curlun->dev.release = lun_release;
device_create_file(&curlun->dev, &dev_attr_ro);
device_create_file(&curlun->dev, &dev_attr_file);
+ kref_get(&fsg->ref);
}
if (file[i] && *file[i]) {
@@ -4061,7 +4089,7 @@ static int __init fsg_alloc(void)
return -ENOMEM;
spin_lock_init(&fsg->lock);
init_rwsem(&fsg->filesem);
- init_waitqueue_head(&fsg->thread_wqh);
+ kref_init(&fsg->ref);
init_completion(&fsg->thread_notifier);
the_fsg = fsg;
@@ -4069,13 +4097,6 @@ static int __init fsg_alloc(void)
}
-static void fsg_free(struct fsg_dev *fsg)
-{
- kfree(fsg->luns);
- kfree(fsg);
-}
-
-
static int __init fsg_init(void)
{
int rc;
@@ -4085,7 +4106,7 @@ static int __init fsg_init(void)
return rc;
fsg = the_fsg;
if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
- fsg_free(fsg);
+ kref_put(&fsg->ref, fsg_release);
return rc;
}
module_init(fsg_init);
@@ -4103,6 +4124,6 @@ static void __exit fsg_cleanup(void)
wait_for_completion(&fsg->thread_notifier);
close_all_backing_files(fsg);
- fsg_free(fsg);
+ kref_put(&fsg->ref, fsg_release);
}
module_exit(fsg_cleanup);
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 5c40980a5bd9..9a4edc5657aa 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1562,10 +1562,10 @@ restart:
spin_unlock_irq (&dev->lock);
/* break link to dcache */
- down (&parent->i_sem);
+ mutex_lock (&parent->i_mutex);
d_delete (dentry);
dput (dentry);
- up (&parent->i_sem);
+ mutex_unlock (&parent->i_mutex);
/* fds may still be open */
goto restart;
@@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = {
.driver = {
.name = (char *) shortname,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b35ac6d334f8..ba9acd531024 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = {
.disconnect = gs_disconnect,
.driver = {
.name = GS_SHORT_NAME,
- /* .shutdown = ... */
- /* .suspend = ... */
- /* .resume = ... */
},
};
@@ -890,10 +887,12 @@ static void gs_close(struct tty_struct *tty, struct file *file)
/* wait for write buffer to drain, or */
/* at most GS_CLOSE_TIMEOUT seconds */
if (gs_buf_data_avail(port->port_write_buf) > 0) {
+ spin_unlock_irqrestore(&port->port_lock, flags);
wait_cond_interruptible_timeout(port->port_write_wait,
port->port_dev == NULL
|| gs_buf_data_avail(port->port_write_buf) == 0,
&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
+ spin_lock_irqsave(&port->port_lock, flags);
}
/* free disconnected port on final close */
@@ -1269,6 +1268,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
unsigned int len;
struct gs_port *port;
int ret;
+ struct tty_struct *tty;
/* TEMPORARY -- only port 0 is supported right now */
port = dev->dev_port[0];
@@ -1288,7 +1288,10 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
goto exit;
}
- if (port->port_tty == NULL) {
+
+ tty = port->port_tty;
+
+ if (tty == NULL) {
printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n",
port->port_num);
ret = -EIO;
@@ -1302,20 +1305,13 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, unsigned int size)
goto exit;
}
- len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count);
- if (len < size)
- size = len;
-
- if (size > 0) {
- memcpy(port->port_tty->flip.char_buf_ptr, packet, size);
- port->port_tty->flip.char_buf_ptr += size;
- port->port_tty->flip.count += size;
+ len = tty_buffer_request_room(tty, size);
+ if (len > 0) {
+ tty_insert_flip_string(tty, packet, len);
tty_flip_buffer_push(port->port_tty);
wake_up_interruptible(&port->port_tty->read_wait);
}
-
ret = 0;
-
exit:
spin_unlock(&port->port_lock);
return ret;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 6c58636e914b..2fc110d3ad5a 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = {
.driver = {
.name = (char *) shortname,
.owner = THIS_MODULE,
- // .shutdown = ...
- // .suspend = ...
- // .resume = ...
},
};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index ed1899d307db..be3fd9bce573 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -11,14 +11,14 @@ config USB_EHCI_HCD
The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
"high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
If your USB host controller supports USB 2.0, you will likely want to
- configure this Host Controller Driver. At this writing, the primary
- implementation of EHCI is a chip from NEC, widely available in add-on
- PCI cards, but implementations are in the works from other vendors
- including Intel and Philips. Motherboard support is appearing.
+ configure this Host Controller Driver. At the time of this writing,
+ the primary implementation of EHCI is a chip from NEC, widely available
+ in add-on PCI cards, but implementations are in the works from other
+ vendors including Intel and Philips. Motherboard support is appearing.
EHCI controllers are packaged with "companion" host controllers (OHCI
or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports
- will connect to EHCI if it the device is high speed, otherwise they
+ will connect to EHCI if the device is high speed, otherwise they
connect to a companion controller. If you configure EHCI, you should
probably configure the OHCI (for NEC and some other vendors) USB Host
Controller Driver or UHCI (for Via motherboards) Host Controller
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 58321d3f314c..e3020f4b17be 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -2,6 +2,10 @@
# Makefile for USB Host Controller Drivers
#
+ifeq ($(CONFIG_USB_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+endif
+
obj-$(CONFIG_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 29f52a44b928..9dd3d14c64f3 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -17,13 +17,6 @@
*/
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dmapool.h>
@@ -624,7 +617,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
/* remote wakeup [4.3.1] */
- if ((status & STS_PCD) && hcd->remote_wakeup) {
+ if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 82caf336e9b6..69b0b9be7a64 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -59,7 +59,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
t2 |= PORT_SUSPEND;
- if (hcd->remote_wakeup)
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@@ -517,7 +517,7 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0
|| (temp & PORT_RESET) != 0)
goto error;
- if (hcd->remote_wakeup)
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
temp |= PORT_WAKE_BITS;
writel (temp | PORT_SUSPEND,
&ehci->regs->port_status [wIndex]);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 13f73a836e45..08ca0f849dab 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -210,7 +210,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
- /* REVISIT: per-port wake capability (PCI 0x62) currently unused */
+ /* Workaround current PCI init glitch: wakeup bits aren't
+ * being set from PCI PM capability.
+ */
+ if (!device_can_wakeup(&pdev->dev)) {
+ u16 port_wake;
+
+ pci_read_config_word(pdev, 0x62, &port_wake);
+ if (port_wake & 0x0001)
+ device_init_wakeup(&pdev->dev, 1);
+ }
retval = ehci_pci_reinit(ehci, pdev);
done:
@@ -269,7 +278,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned port;
- struct usb_device *root = hcd->self.root_hub;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval = -EINVAL;
@@ -303,13 +311,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
restart:
ehci_dbg(ehci, "lost power, restarting\n");
- for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
- port--;
- if (!root->children [port])
- continue;
- usb_set_device_state(root->children[port],
- USB_STATE_NOTATTACHED);
- }
+ usb_root_hub_lost_power(hcd->self.root_hub);
/* Else reset, to cope with power loss or flush-to-storage
* style "resume" having let BIOS kick in during reboot.
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index bf03ec0d8ee2..9b13bf2fa98d 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -514,18 +514,18 @@ qh_urb_transaction (
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
+
+ /* for zero length DATA stages, STATUS is always IN */
+ if (len == 0)
+ token |= (1 /* "in" */ << 8);
}
/*
* data transfer stage: buffer setup
*/
- if (likely (len > 0))
- buf = urb->transfer_dma;
- else
- buf = 0;
+ buf = urb->transfer_dma;
- /* for zero length DATA stages, STATUS is always IN */
- if (!buf || is_input)
+ if (is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
@@ -572,7 +572,7 @@ qh_urb_transaction (
* control requests may need a terminating data "status" ack;
* bulk ones may need a terminating short packet (zero length).
*/
- if (likely (buf != 0)) {
+ if (likely (urb->transfer_buffer_length != 0)) {
int one_more = 0;
if (usb_pipecontrol (urb->pipe)) {
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 0eaabeb37ac3..641268d7e6f3 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -4397,7 +4397,7 @@ static int __init etrax_usb_hc_init(void)
device_initialize(&fake_device);
kobject_set_name(&fake_device.kobj, "etrax_usb");
kobject_add(&fake_device.kobj);
- kobject_hotplug(&fake_device.kobj, KOBJ_ADD);
+ kobject_uevent(&fake_device.kobj, KOBJ_ADD);
hc->bus->controller = &fake_device;
usb_register_bus(hc->bus);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 82f64986bc22..584b8dc65119 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -55,19 +55,13 @@
/* enqueuing/finishing log of urbs */
//#define URB_TRACE
-#include <linux/config.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/list.h>
-#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb_isp116x.h>
#include <linux/platform_device.h>
@@ -77,14 +71,10 @@
#include <asm/system.h>
#include <asm/byteorder.h>
-#ifndef DEBUG
-# define STUB_DEBUG_FILE
-#endif
-
#include "../core/hcd.h"
#include "isp116x.h"
-#define DRIVER_VERSION "05 Aug 2005"
+#define DRIVER_VERSION "03 Nov 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC);
@@ -164,13 +154,11 @@ static void pack_fifo(struct isp116x *isp116x)
struct ptd *ptd;
int buflen = isp116x->atl_last_dir == PTD_DIR_IN
? isp116x->atl_bufshrt : isp116x->atl_buflen;
- int ptd_count = 0;
isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
for (ep = isp116x->atl_active; ep; ep = ep->active) {
- ++ptd_count;
ptd = &ep->ptd;
dump_ptd(ptd);
dump_ptd_out_data(ptd, ep->data);
@@ -305,9 +293,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
udev = urb->dev;
ptd = &ep->ptd;
cc = PTD_GET_CC(ptd);
-
- spin_lock(&urb->lock);
short_not_ok = 1;
+ spin_lock(&urb->lock);
/* Data underrun is special. For allowed underrun
we clear the error and continue as normal. For
@@ -420,7 +407,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
ep->nextpid = 0;
break;
default:
- BUG_ON(1);
+ BUG();
}
spin_unlock(&urb->lock);
}
@@ -628,8 +615,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
if (intstat & HCINT_UE) {
- ERR("Unrecoverable error\n");
- /* What should we do here? Reset? */
+ ERR("Unrecoverable error, HC is dead!\n");
+ /* IRQ's are off, we do no DMA,
+ perfectly ready to die ... */
+ hcd->state = HC_STATE_HALT;
+ ret = IRQ_HANDLED;
+ goto done;
}
if (intstat & HCINT_RHSC)
/* When root hub or any of its ports is going
@@ -640,7 +631,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n");
usb_hcd_resume_root_hub(hcd);
- ret = IRQ_HANDLED;
}
irqstat &= ~HCuPINT_OPR;
ret = IRQ_HANDLED;
@@ -651,6 +641,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
}
isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+ done:
spin_unlock(&isp116x->lock);
return ret;
}
@@ -724,6 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags);
if (!HC_IS_RUNNING(hcd->state)) {
+ kfree(ep);
ret = -ENODEV;
goto fail;
}
@@ -888,7 +880,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *hep)
{
int i;
- struct isp116x_ep *ep = hep->hcpriv;;
+ struct isp116x_ep *ep = hep->hcpriv;
if (!ep)
return;
@@ -916,8 +908,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
return (int)fmnum;
}
-/*----------------------------------------------------------------*/
-
/*
Adapted from ohci-hub.c. Currently we don't support autosuspend.
*/
@@ -968,11 +958,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
desc->bHubContrCurrent = 0;
desc->bNbrPorts = (u8) (reg & 0x3);
/* Power switching, device type, overcurrent. */
- desc->wHubCharacteristics =
- (__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
+ desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
/* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
- desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+ desc->bitmap[0] = 0;
desc->bitmap[1] = ~0;
}
@@ -1159,135 +1148,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
return ret;
}
-#ifdef CONFIG_PM
-
-static int isp116x_bus_suspend(struct usb_hcd *hcd)
-{
- struct isp116x *isp116x = hcd_to_isp116x(hcd);
- unsigned long flags;
- u32 val;
- int ret = 0;
-
- spin_lock_irqsave(&isp116x->lock, flags);
-
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- switch (val & HCCONTROL_HCFS) {
- case HCCONTROL_USB_OPER:
- hcd->state = HC_STATE_QUIESCING;
- val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
- val |= HCCONTROL_USB_SUSPEND;
- if (hcd->remote_wakeup)
- val |= HCCONTROL_RWE;
- /* Wait for usb transfers to finish */
- mdelay(2);
- isp116x_write_reg32(isp116x, HCCONTROL, val);
- hcd->state = HC_STATE_SUSPENDED;
- /* Wait for devices to suspend */
- mdelay(5);
- case HCCONTROL_USB_SUSPEND:
- break;
- case HCCONTROL_USB_RESUME:
- isp116x_write_reg32(isp116x, HCCONTROL,
- (val & ~HCCONTROL_HCFS) |
- HCCONTROL_USB_RESET);
- case HCCONTROL_USB_RESET:
- ret = -EBUSY;
- break;
- default:
- ret = -EINVAL;
- }
-
- spin_unlock_irqrestore(&isp116x->lock, flags);
- return ret;
-}
-
-static int isp116x_bus_resume(struct usb_hcd *hcd)
-{
- struct isp116x *isp116x = hcd_to_isp116x(hcd);
- u32 val;
- int ret = -EINPROGRESS;
-
- msleep(5);
- spin_lock_irq(&isp116x->lock);
-
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- switch (val & HCCONTROL_HCFS) {
- case HCCONTROL_USB_SUSPEND:
- val &= ~HCCONTROL_HCFS;
- val |= HCCONTROL_USB_RESUME;
- isp116x_write_reg32(isp116x, HCCONTROL, val);
- case HCCONTROL_USB_RESUME:
- break;
- case HCCONTROL_USB_OPER:
- /* Without setting power_state here the
- SUSPENDED state won't be removed from
- sysfs/usbN/power.state as a response to remote
- wakeup. Maybe in the future. */
- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
- ret = 0;
- break;
- default:
- ret = -EBUSY;
- }
-
- if (ret != -EINPROGRESS) {
- spin_unlock_irq(&isp116x->lock);
- return ret;
- }
-
- val = isp116x->rhdesca & RH_A_NDP;
- while (val--) {
- u32 stat =
- isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
- /* force global, not selective, resume */
- if (!(stat & RH_PS_PSS))
- continue;
- DBG("%s: Resuming port %d\n", __func__, val);
- isp116x_write_reg32(isp116x, RH_PS_POCI, val
- ? HCRHPORT2 : HCRHPORT1);
- }
- spin_unlock_irq(&isp116x->lock);
-
- hcd->state = HC_STATE_RESUMING;
- mdelay(20);
-
- /* Go operational */
- spin_lock_irq(&isp116x->lock);
- val = isp116x_read_reg32(isp116x, HCCONTROL);
- isp116x_write_reg32(isp116x, HCCONTROL,
- (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
- spin_unlock_irq(&isp116x->lock);
- /* see analogous comment above */
- hcd->self.root_hub->dev.power.power_state = PMSG_ON;
- hcd->state = HC_STATE_RUNNING;
-
- return 0;
-}
-
-
-#else
-
-#define isp116x_bus_suspend NULL
-#define isp116x_bus_resume NULL
-
-#endif
-
/*-----------------------------------------------------------------*/
-#ifdef STUB_DEBUG_FILE
-
-static inline void create_debug_file(struct isp116x *isp116x)
-{
-}
-
-static inline void remove_debug_file(struct isp116x *isp116x)
-{
-}
-
-#else
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#ifdef CONFIG_DEBUG_FS
static void dump_irq(struct seq_file *s, char *label, u16 mask)
{
@@ -1311,13 +1174,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
}
-static int proc_isp116x_show(struct seq_file *s, void *unused)
+static int isp116x_show_dbg(struct seq_file *s, void *unused)
{
struct isp116x *isp116x = s->private;
- struct isp116x_ep *ep;
- struct urb *urb;
- unsigned i;
- char *str;
seq_printf(s, "%s\n%s version %s\n",
isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@@ -1333,105 +1192,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
}
spin_lock_irq(&isp116x->lock);
-
dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
-
- list_for_each_entry(ep, &isp116x->async, schedule) {
-
- switch (ep->nextpid) {
- case USB_PID_IN:
- str = "in";
- break;
- case USB_PID_OUT:
- str = "out";
- break;
- case USB_PID_SETUP:
- str = "setup";
- break;
- case USB_PID_ACK:
- str = "status";
- break;
- default:
- str = "?";
- break;
- };
- seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
- ep->epnum, str, ep->maxpacket);
- list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
- seq_printf(s, " urb%p, %d/%d\n", urb,
- urb->actual_length,
- urb->transfer_buffer_length);
- }
- }
- if (!list_empty(&isp116x->async))
- seq_printf(s, "\n");
-
- seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
-
- for (i = 0; i < PERIODIC_SIZE; i++) {
- ep = isp116x->periodic[i];
- if (!ep)
- continue;
- seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
-
- /* DUMB: prints shared entries multiple times */
- do {
- seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n",
- ep->period, ep,
- (ep->udev->speed ==
- USB_SPEED_FULL) ? "" : "ls ",
- ep->udev->devnum, ep->epnum,
- (ep->epnum ==
- 0) ? "" : ((ep->nextpid ==
- USB_PID_IN) ? "in" : "out"),
- ep->maxpacket);
- ep = ep->next;
- } while (ep);
- }
+ isp116x_show_regs_seq(isp116x, s);
spin_unlock_irq(&isp116x->lock);
seq_printf(s, "\n");
return 0;
}
-static int proc_isp116x_open(struct inode *inode, struct file *file)
+static int isp116x_open_seq(struct inode *inode, struct file *file)
{
- return single_open(file, proc_isp116x_show, PDE(inode)->data);
+ return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
}
-static struct file_operations proc_ops = {
- .open = proc_isp116x_open,
+static struct file_operations isp116x_debug_fops = {
+ .open = isp116x_open_seq,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
-/* expect just one isp116x per system */
-static const char proc_filename[] = "driver/isp116x";
-
-static void create_debug_file(struct isp116x *isp116x)
+static int create_debug_file(struct isp116x *isp116x)
{
- struct proc_dir_entry *pde;
-
- pde = create_proc_entry(proc_filename, 0, NULL);
- if (pde == NULL)
- return;
-
- pde->proc_fops = &proc_ops;
- pde->data = isp116x;
- isp116x->pde = pde;
+ isp116x->dentry = debugfs_create_file(hcd_name,
+ S_IRUGO, NULL, isp116x,
+ &isp116x_debug_fops);
+ if (!isp116x->dentry)
+ return -ENOMEM;
+ return 0;
}
static void remove_debug_file(struct isp116x *isp116x)
{
- if (isp116x->pde)
- remove_proc_entry(proc_filename, NULL);
+ debugfs_remove(isp116x->dentry);
}
-#endif
+#else
+
+#define create_debug_file(d) 0
+#define remove_debug_file(d) do{}while(0)
+
+#endif /* CONFIG_DEBUG_FS */
/*-----------------------------------------------------------------*/
@@ -1466,7 +1270,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long t;
u16 clkrdy = 0;
- int ret = 0, timeout = 15 /* ms */ ;
+ int ret, timeout = 15 /* ms */ ;
ret = isp116x_sw_reset(isp116x);
if (ret)
@@ -1482,7 +1286,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
break;
}
if (!clkrdy) {
- ERR("Clock not ready after 20ms\n");
+ ERR("Clock not ready after %dms\n", timeout);
/* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */
ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@@ -1572,7 +1376,8 @@ static int isp116x_start(struct usb_hcd *hcd)
val = 0;
if (board->remote_wakeup_enable) {
- hcd->can_wakeup = 1;
+ if (!device_can_wakeup(hcd->self.controller))
+ device_init_wakeup(hcd->self.controller, 1);
val |= RH_HS_DRWE;
}
isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@@ -1600,12 +1405,126 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
- isp116x_show_regs(isp116x);
+ isp116x_show_regs_log(isp116x);
spin_unlock_irqrestore(&isp116x->lock, flags);
return 0;
}
-/*-----------------------------------------------------------------*/
+#ifdef CONFIG_PM
+
+static int isp116x_bus_suspend(struct usb_hcd *hcd)
+{
+ struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ unsigned long flags;
+ u32 val;
+ int ret = 0;
+
+ spin_lock_irqsave(&isp116x->lock, flags);
+
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ switch (val & HCCONTROL_HCFS) {
+ case HCCONTROL_USB_OPER:
+ val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
+ val |= HCCONTROL_USB_SUSPEND;
+ if (device_may_wakeup(&hcd->self.root_hub->dev))
+ val |= HCCONTROL_RWE;
+ /* Wait for usb transfers to finish */
+ mdelay(2);
+ isp116x_write_reg32(isp116x, HCCONTROL, val);
+ /* Wait for devices to suspend */
+ mdelay(5);
+ case HCCONTROL_USB_SUSPEND:
+ break;
+ case HCCONTROL_USB_RESUME:
+ isp116x_write_reg32(isp116x, HCCONTROL,
+ (val & ~HCCONTROL_HCFS) |
+ HCCONTROL_USB_RESET);
+ case HCCONTROL_USB_RESET:
+ ret = -EBUSY;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&isp116x->lock, flags);
+ return ret;
+}
+
+static int isp116x_bus_resume(struct usb_hcd *hcd)
+{
+ struct isp116x *isp116x = hcd_to_isp116x(hcd);
+ u32 val;
+
+ msleep(5);
+ spin_lock_irq(&isp116x->lock);
+
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ switch (val & HCCONTROL_HCFS) {
+ case HCCONTROL_USB_SUSPEND:
+ val &= ~HCCONTROL_HCFS;
+ val |= HCCONTROL_USB_RESUME;
+ isp116x_write_reg32(isp116x, HCCONTROL, val);
+ case HCCONTROL_USB_RESUME:
+ break;
+ case HCCONTROL_USB_OPER:
+ spin_unlock_irq(&isp116x->lock);
+ /* Without setting power_state here the
+ SUSPENDED state won't be removed from
+ sysfs/usbN/power.state as a response to remote
+ wakeup. Maybe in the future. */
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ default:
+ /* HCCONTROL_USB_RESET: this may happen, when during
+ suspension the HC lost power. Reinitialize completely */
+ spin_unlock_irq(&isp116x->lock);
+ DBG("Chip has been reset while suspended. Reinit from scratch.\n");
+ isp116x_reset(hcd);
+ isp116x_start(hcd);
+ isp116x_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_POWER, 1, NULL, 0);
+ if ((isp116x->rhdesca & RH_A_NDP) == 2)
+ isp116x_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_POWER, 2, NULL, 0);
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ return 0;
+ }
+
+ val = isp116x->rhdesca & RH_A_NDP;
+ while (val--) {
+ u32 stat =
+ isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
+ /* force global, not selective, resume */
+ if (!(stat & RH_PS_PSS))
+ continue;
+ DBG("%s: Resuming port %d\n", __func__, val);
+ isp116x_write_reg32(isp116x, RH_PS_POCI, val
+ ? HCRHPORT2 : HCRHPORT1);
+ }
+ spin_unlock_irq(&isp116x->lock);
+
+ hcd->state = HC_STATE_RESUMING;
+ msleep(20);
+
+ /* Go operational */
+ spin_lock_irq(&isp116x->lock);
+ val = isp116x_read_reg32(isp116x, HCCONTROL);
+ isp116x_write_reg32(isp116x, HCCONTROL,
+ (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
+ spin_unlock_irq(&isp116x->lock);
+ /* see analogous comment above */
+ hcd->self.root_hub->dev.power.power_state = PMSG_ON;
+ hcd->state = HC_STATE_RUNNING;
+
+ return 0;
+}
+
+#else
+
+#define isp116x_bus_suspend NULL
+#define isp116x_bus_resume NULL
+
+#endif
static struct hc_driver isp116x_hc_driver = {
.description = hcd_name,
@@ -1735,12 +1654,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
}
ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
- if (ret != 0)
+ if (ret)
goto err6;
- create_debug_file(isp116x);
+ ret = create_debug_file(isp116x);
+ if (ret) {
+ ERR("Couldn't create debugfs entry\n");
+ goto err7;
+ }
+
return 0;
+ err7:
+ usb_remove_hcd(hcd);
err6:
usb_put_hcd(hcd);
err5:
@@ -1762,13 +1688,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
*/
static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
{
- int ret = 0;
-
- VDBG("%s: state %x\n", __func__, state);
-
+ VDBG("%s: state %x\n", __func__, state.event);
dev->dev.power.power_state = state;
-
- return ret;
+ return 0;
}
/*
@@ -1776,13 +1698,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
*/
static int isp116x_resume(struct platform_device *dev)
{
- int ret = 0;
-
- VDBG("%s: state %x\n", __func__, dev->dev.power.power_state);
-
+ VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
dev->dev.power.power_state = PMSG_ON;
-
- return ret;
+ return 0;
}
#else
diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h
index c6fec96785fe..a1b7c3813d3a 100644
--- a/drivers/usb/host/isp116x.h
+++ b/drivers/usb/host/isp116x.h
@@ -259,7 +259,7 @@ struct isp116x {
struct isp116x_platform_data *board;
- struct proc_dir_entry *pde;
+ struct dentry *dentry;
unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */
@@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
isp116x_write_data32(isp116x, (u32) val);
}
-#define isp116x_show_reg(d,r) { \
+#define isp116x_show_reg_log(d,r,s) { \
if ((r) < 0x20) { \
DBG("%-12s[%02x]: %08x\n", #r, \
r, isp116x_read_reg32(d, r)); \
@@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
r, isp116x_read_reg16(d, r)); \
} \
}
+#define isp116x_show_reg_seq(d,r,s) { \
+ if ((r) < 0x20) { \
+ seq_printf(s, "%-12s[%02x]: %08x\n", #r, \
+ r, isp116x_read_reg32(d, r)); \
+ } else { \
+ seq_printf(s, "%-12s[%02x]: %04x\n", #r, \
+ r, isp116x_read_reg16(d, r)); \
+ } \
+}
-static inline void isp116x_show_regs(struct isp116x *isp116x)
+#define isp116x_show_regs(d,type,s) { \
+ isp116x_show_reg_##type(d, HCREVISION, s); \
+ isp116x_show_reg_##type(d, HCCONTROL, s); \
+ isp116x_show_reg_##type(d, HCCMDSTAT, s); \
+ isp116x_show_reg_##type(d, HCINTSTAT, s); \
+ isp116x_show_reg_##type(d, HCINTENB, s); \
+ isp116x_show_reg_##type(d, HCFMINTVL, s); \
+ isp116x_show_reg_##type(d, HCFMREM, s); \
+ isp116x_show_reg_##type(d, HCFMNUM, s); \
+ isp116x_show_reg_##type(d, HCLSTHRESH, s); \
+ isp116x_show_reg_##type(d, HCRHDESCA, s); \
+ isp116x_show_reg_##type(d, HCRHDESCB, s); \
+ isp116x_show_reg_##type(d, HCRHSTATUS, s); \
+ isp116x_show_reg_##type(d, HCRHPORT1, s); \
+ isp116x_show_reg_##type(d, HCRHPORT2, s); \
+ isp116x_show_reg_##type(d, HCHWCFG, s); \
+ isp116x_show_reg_##type(d, HCDMACFG, s); \
+ isp116x_show_reg_##type(d, HCXFERCTR, s); \
+ isp116x_show_reg_##type(d, HCuPINT, s); \
+ isp116x_show_reg_##type(d, HCuPINTENB, s); \
+ isp116x_show_reg_##type(d, HCCHIPID, s); \
+ isp116x_show_reg_##type(d, HCSCRATCH, s); \
+ isp116x_show_reg_##type(d, HCITLBUFLEN, s); \
+ isp116x_show_reg_##type(d, HCATLBUFLEN, s); \
+ isp116x_show_reg_##type(d, HCBUFSTAT, s); \
+ isp116x_show_reg_##type(d, HCRDITL0LEN, s); \
+ isp116x_show_reg_##type(d, HCRDITL1LEN, s); \
+}
+
+/*
+ Dump registers for debugfs.
+*/
+static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
+ struct seq_file *s)
+{
+ isp116x_show_regs(isp116x, seq, s);
+}
+
+/*
+ Dump registers to syslog.
+*/
+static inline void isp116x_show_regs_log(struct isp116x *isp116x)
{
- isp116x_show_reg(isp116x, HCREVISION);
- isp116x_show_reg(isp116x, HCCONTROL);
- isp116x_show_reg(isp116x, HCCMDSTAT);
- isp116x_show_reg(isp116x, HCINTSTAT);
- isp116x_show_reg(isp116x, HCINTENB);
- isp116x_show_reg(isp116x, HCFMINTVL);
- isp116x_show_reg(isp116x, HCFMREM);
- isp116x_show_reg(isp116x, HCFMNUM);
- isp116x_show_reg(isp116x, HCLSTHRESH);
- isp116x_show_reg(isp116x, HCRHDESCA);
- isp116x_show_reg(isp116x, HCRHDESCB);
- isp116x_show_reg(isp116x, HCRHSTATUS);
- isp116x_show_reg(isp116x, HCRHPORT1);
- isp116x_show_reg(isp116x, HCRHPORT2);
- isp116x_show_reg(isp116x, HCHWCFG);
- isp116x_show_reg(isp116x, HCDMACFG);
- isp116x_show_reg(isp116x, HCXFERCTR);
- isp116x_show_reg(isp116x, HCuPINT);
- isp116x_show_reg(isp116x, HCuPINTENB);
- isp116x_show_reg(isp116x, HCCHIPID);
- isp116x_show_reg(isp116x, HCSCRATCH);
- isp116x_show_reg(isp116x, HCITLBUFLEN);
- isp116x_show_reg(isp116x, HCATLBUFLEN);
- isp116x_show_reg(isp116x, HCBUFSTAT);
- isp116x_show_reg(isp116x, HCRDITL0LEN);
- isp116x_show_reg(isp116x, HCRDITL1LEN);
+ isp116x_show_regs(isp116x, log, NULL);
}
#if defined(URB_TRACE)
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index d9cf3b327d96..77cd6ac07e3c 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -19,6 +19,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
#include <asm/mach-au1x00/au1000.h>
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index bf1d9abc07ac..a4b12404ae08 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,13 +75,6 @@
*/
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-# define DEBUG
-#else
-# undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@@ -802,7 +795,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
int temp;
int i;
struct urb_priv *priv;
- struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
/* mark any devices gone, so they do nothing till khubd disconnects.
* recycle any "live" eds/tds (and urbs) right away.
@@ -811,11 +803,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/
spin_lock_irq(&ohci->lock);
disable (ohci);
- for (i = 0; i < root->maxchild; i++) {
- if (root->children [i])
- usb_set_device_state (root->children[i],
- USB_STATE_NOTATTACHED);
- }
+ usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
if (!list_empty (&ohci->pending))
ohci_dbg(ohci, "abort schedule...\n");
list_for_each_entry (priv, &ohci->pending, pending) {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 72e3b12a1926..4b2226d77b34 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -372,7 +372,7 @@ done:
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
- && usb_trylock_device (hcd->self.root_hub)
+ && usb_trylock_device (hcd->self.root_hub) == 0
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_bus_suspend (hcd);
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index 3959ccc88332..0020ed7a39d0 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -17,6 +17,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
#include <asm/hardware.h>
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index c9e29d808711..3785b3f7df1b 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -17,6 +17,7 @@
#include <linux/signal.h> /* SA_INTERRUPT */
#include <linux/jiffies.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -27,7 +28,6 @@
#include <asm/arch/gpio.h>
#include <asm/arch/fpga.h>
#include <asm/arch/usb.h>
-#include <asm/hardware/clock.h>
/* OMAP-1510 OHCI has its own MMU for DMA */
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index 2ec6a78bd65e..b2a8dfa48870 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -15,6 +15,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/signal.h>
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 9d65ec307990..acde8868da21 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -26,18 +26,12 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
-
-
-#define PMM_NPS_MODE 1
-#define PMM_GLOBAL_MODE 2
-#define PMM_PERPORT_MODE 3
+#include <asm/arch/ohci.h>
#define PXA_UHC_MAX_PORTNUM 3
#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
-static int pxa27x_ohci_pmm_state;
-
/*
PMM_NPS_MODE -- PMM Non-power switching mode
Ports are powered continuously.
@@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state;
*/
static int pxa27x_ohci_select_pmm( int mode )
{
- pxa27x_ohci_pmm_state = mode;
-
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
@@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int mode )
"Invalid mode %d, set to non-power switch mode.\n",
mode );
- pxa27x_ohci_pmm_state = PMM_NPS_MODE;
UHCRHDA |= RH_A_NPS;
}
@@ -82,8 +73,13 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
-static void pxa27x_start_hc(struct platform_device *dev)
+static int pxa27x_start_hc(struct device *dev)
{
+ int retval = 0;
+ struct pxaohci_platform_data *inf;
+
+ inf = dev->platform_data;
+
pxa_set_cken(CKEN10_USBHOST, 1);
UHCHR |= UHCHR_FHR;
@@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platform_device *dev)
while (UHCHR & UHCHR_FSBIR)
cpu_relax();
- /* This could be properly abstracted away through the
- device data the day more machines are supported and
- their differences can be figured out correctly. */
- if (machine_is_mainstone()) {
- /* setup Port1 GPIO pin. */
- pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
- pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
-
- /* Set the Power Control Polarity Low and Power Sense
- Polarity Low to active low. Supply power to USB ports. */
- UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
- ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
+ if (inf->init)
+ retval = inf->init(dev);
- pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
- }
+ if (retval < 0)
+ return retval;
UHCHR &= ~UHCHR_SSE;
@@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platform_device *dev)
/* Clear any OTG Pin Hold */
if (PSSR & PSSR_OTGPH)
PSSR |= PSSR_OTGPH;
+
+ return 0;
}
-static void pxa27x_stop_hc(struct platform_device *dev)
+static void pxa27x_stop_hc(struct device *dev)
{
+ struct pxaohci_platform_data *inf;
+
+ inf = dev->platform_data;
+
+ if (inf->exit)
+ inf->exit(dev);
+
UHCHR |= UHCHR_FHR;
udelay(11);
UHCHR &= ~UHCHR_FHR;
@@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platform_device *dev)
* through the hotplug entry's driver_data.
*
*/
-int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
- struct platform_device *dev)
+int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
int retval;
struct usb_hcd *hcd;
+ struct pxaohci_platform_data *inf;
- if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ inf = pdev->dev.platform_data;
+
+ if (!inf)
+ return -ENODEV;
+
+ if (pdev->resource[1].flags != IORESOURCE_IRQ) {
pr_debug ("resource[1] is not IORESOURCE_IRQ");
return -ENOMEM;
}
- hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
+ hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
if (!hcd)
return -ENOMEM;
- hcd->rsrc_start = dev->resource[0].start;
- hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+ hcd->rsrc_start = pdev->resource[0].start;
+ hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed");
@@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
goto err2;
}
- pxa27x_start_hc(dev);
+ if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
+ pr_debug("pxa27x_start_hc failed");
+ goto err3;
+ }
/* Select Power Management Mode */
- pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
+ pxa27x_ohci_select_pmm(inf->port_mode);
ohci_hcd_init(hcd_to_ohci(hcd));
- retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
if (retval == 0)
return retval;
- pxa27x_stop_hc(dev);
+ pxa27x_stop_hc(&pdev->dev);
+ err3:
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
* context, normally "rmmod", "apmd", or something similar.
*
*/
-void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
+void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
usb_remove_hcd(hcd);
- pxa27x_stop_hc(dev);
+ pxa27x_stop_hc(&pdev->dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
@@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
{
- int ret;
-
pr_debug ("In ohci_hcd_pxa27x_drv_probe");
if (usb_disabled())
return -ENODEV;
- ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
- return ret;
+ return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
}
static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
@@ -308,31 +309,55 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_hcd_pxa27x_remove(hcd, pdev);
+ platform_set_drvdata(pdev, NULL);
return 0;
}
-static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state)
+#ifdef CONFIG_PM
+static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
-// struct usb_hcd *hcd = platform_get_drvdata(dev);
- printk("%s: not implemented yet\n", __FUNCTION__);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ pxa27x_stop_hc(&pdev->dev);
+ hcd->state = HC_STATE_SUSPENDED;
+ pdev->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
-static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev)
+static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
{
-// struct usb_hcd *hcd = platform_get_drvdata(dev);
- printk("%s: not implemented yet\n", __FUNCTION__);
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int status;
+
+ if (time_before(jiffies, ohci->next_statechange))
+ msleep(5);
+ ohci->next_statechange = jiffies;
+
+ if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
+ return status;
+
+ pdev->dev.power.power_state = PMSG_ON;
+ usb_hcd_resume_root_hub(hcd);
return 0;
}
+#endif
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
+#ifdef CONFIG_PM
.suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
+#endif
.driver = {
.name = "pxa27x-ohci",
},
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 35cc9402adc0..372527a83593 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -20,9 +20,9 @@
*/
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
-#include <asm/hardware/clock.h>
#include <asm/arch/usb-control.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@@ -363,7 +363,6 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
goto err1;
}
- clk_use(clk);
s3c2410_start_hc(dev, hcd);
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
@@ -384,7 +383,6 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
err2:
s3c2410_stop_hc(dev);
iounmap(hcd->regs);
- clk_unuse(clk);
clk_put(clk);
err1:
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index e46528c825bf..3ef2c0cdf1db 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -9,12 +9,6 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a7722a6a5a5b..517360b77d8e 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -32,13 +32,6 @@
#undef PACKET_TRACE
#include <linux/config.h>
-
-#ifdef CONFIG_USB_DEBUG
-# define DEBUG
-#else
-# undef DEBUG
-#endif
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -1581,7 +1574,9 @@ sl811h_start(struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
if (sl811->board) {
- hcd->can_wakeup = sl811->board->can_wakeup;
+ if (!device_can_wakeup(hcd->self.controller))
+ device_init_wakeup(hcd->self.controller,
+ sl811->board->can_wakeup);
hcd->power_budget = sl811->board->power * 2;
}
@@ -1805,9 +1800,10 @@ sl811h_resume(struct platform_device *dev)
* let's assume it'd only be powered to enable remote wakeup.
*/
if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
- || !hcd->can_wakeup) {
+ || !device_can_wakeup(&hcd->self.root_hub->dev)) {
sl811->port1 = 0;
port_power(sl811, 1);
+ usb_root_hub_lost_power(hcd->self.root_hub);
return 0;
}
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index e73faf831b24..466384d7c79f 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
/* MACROS */
/*====================================================================*/
-#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
+#if defined(DEBUG) || defined(PCMCIA_DEBUG)
static int pc_debug = 0;
module_param(pc_debug, int, 0644);
@@ -66,13 +66,13 @@ module_param(pc_debug, int, 0644);
static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
-static dev_link_t *dev_list = NULL;
-
typedef struct local_info_t {
dev_link_t link;
dev_node_t node;
} local_info_t;
+static void sl811_cs_release(dev_link_t * link);
+
/*====================================================================*/
static void release_platform_dev(struct device * dev)
@@ -129,7 +129,8 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
resources[2].end = base_addr + 1;
/* The driver core will probe for us. We know sl811-hcd has been
- * initialized already because of the link order dependency.
+ * initialized already because of the link order dependency created
+ * by referencing "sl811h_driver".
*/
platform_dev.name = sl811h_driver.name;
return platform_device_register(&platform_dev);
@@ -137,26 +138,16 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
/*====================================================================*/
-static void sl811_cs_detach(dev_link_t *link)
+static void sl811_cs_detach(struct pcmcia_device *p_dev)
{
- dev_link_t **linkp;
+ dev_link_t *link = dev_to_instance(p_dev);
DBG(0, "sl811_cs_detach(0x%p)\n", link);
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
- if (*linkp == link)
- break;
- }
- if (*linkp == NULL)
- return;
-
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG)
+ sl811_cs_release(link);
- /* Unlink device structure, and free it */
- *linkp = link->next;
/* This points to the parent local_info_t struct */
kfree(link->priv);
}
@@ -166,13 +157,6 @@ static void sl811_cs_release(dev_link_t * link)
DBG(0, "sl811_cs_release(0x%p)\n", link);
- if (link->open) {
- DBG(1, "sl811_cs: release postponed, '%s' still open\n",
- link->dev->dev_name);
- link->state |= DEV_STALE_CONFIG;
- return;
- }
-
/* Unlink the device chain */
link->dev = NULL;
@@ -183,9 +167,6 @@ static void sl811_cs_release(dev_link_t * link)
if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
-
- if (link->state & DEV_STALE_LINK)
- sl811_cs_detach(link);
}
static void sl811_cs_config(dev_link_t *link)
@@ -322,55 +303,36 @@ cs_failed:
}
}
-static int
-sl811_cs_event(event_t event, int priority, event_callback_args_t *args)
+static int sl811_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
+ dev_link_t *link = dev_to_instance(dev);
- DBG(1, "sl811_cs_event(0x%06x)\n", event);
+ link->state |= DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- sl811_cs_release(link);
- break;
+ return 0;
+}
- case CS_EVENT_CARD_INSERTION:
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- sl811_cs_config(link);
- break;
+static int sl811_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
- case CS_EVENT_PM_SUSPEND:
- link->state |= DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
+ link->state &= ~DEV_SUSPEND;
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
- case CS_EVENT_PM_RESUME:
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- if (link->state & DEV_CONFIG)
- pcmcia_request_configuration(link->handle, &link->conf);
- DBG(0, "reset sl811-hcd here?\n");
- break;
- }
return 0;
}
-static dev_link_t *sl811_cs_attach(void)
+static int sl811_cs_attach(struct pcmcia_device *p_dev)
{
local_info_t *local;
dev_link_t *link;
- client_reg_t client_reg;
- int ret;
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
- return NULL;
+ return -ENOMEM;
memset(local, 0, sizeof(local_info_t));
link = &local->link;
link->priv = local;
@@ -384,21 +346,13 @@ static dev_link_t *sl811_cs_attach(void)
link->conf.Vcc = 33;
link->conf.IntType = INT_MEMORY_AND_IO;
- /* Register with Card Services */
- link->next = dev_list;
- dev_list = link;
- client_reg.dev_info = (dev_info_t *) &driver_name;
- client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
- 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);
- sl811_cs_detach(link);
- return NULL;
- }
+ link->handle = p_dev;
+ p_dev->instance = link;
- return link;
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ sl811_cs_config(link);
+
+ return 0;
}
static struct pcmcia_device_id sl811_ids[] = {
@@ -412,10 +366,11 @@ static struct pcmcia_driver sl811_cs_driver = {
.drv = {
.name = (char *)driver_name,
},
- .attach = sl811_cs_attach,
- .event = sl811_cs_event,
- .detach = sl811_cs_detach,
+ .probe = sl811_cs_attach,
+ .remove = sl811_cs_detach,
.id_table = sl811_ids,
+ .suspend = sl811_suspend,
+ .resume = sl811_resume,
};
/*====================================================================*/
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 151154df37fa..5832953086f8 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -2,8 +2,8 @@
* UHCI-specific debugging code. Invaluable when something
* goes wrong, but don't get in my face.
*
- * Kernel visible pointers are surrounded in []'s and bus
- * visible pointers are surrounded in ()'s
+ * Kernel visible pointers are surrounded in []s and bus
+ * visible pointers are surrounded in ()s
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2001 Johannes Erdfelt
@@ -19,7 +19,7 @@
static struct dentry *uhci_debugfs_root = NULL;
-/* Handle REALLY large printk's so we don't overflow buffers */
+/* Handle REALLY large printks so we don't overflow buffers */
static inline void lprintk(char *buf)
{
char *p;
@@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
}
if (active && ni > i) {
- out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
+ out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
tmp = ntmp;
td = ntd;
i = ni;
@@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
if (list_empty(&urbp->queue_list) || urbp->queued)
goto out;
- out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+ out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
head = &urbp->queue_list;
tmp = head->next;
@@ -197,7 +197,7 @@ out:
}
#ifdef CONFIG_PROC_FS
-static const char *qh_names[] = {
+static const char * const qh_names[] = {
"skel_int128_qh", "skel_int64_qh",
"skel_int32_qh", "skel_int16_qh",
"skel_int8_qh", "skel_int4_qh",
@@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
} while (tmp != head);
}
- out += sprintf(out, "Skeleton QH's\n");
+ out += sprintf(out, "Skeleton QHs\n");
for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
int shown = 0;
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 79efaf7d86a3..dfe121d35887 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -23,11 +23,6 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@@ -67,10 +62,10 @@ Alan Stern"
/*
* debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
+ * debug = 1, dump failed URBs except for stalls
+ * debug = 2, dump all failed URBs (including stalls)
* show all queues in /debug/uhci/[pci_addr]
- * debug = 3, show all TD's in URB's when dumping
+ * debug = 3, show all TDs in URBs when dumping
*/
#ifdef DEBUG
static int debug = 1;
@@ -93,7 +88,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
#define FSBR_DELAY msecs_to_jiffies(50)
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TD's */
+/* depth first traversal. We'll do it in groups of this number of TDs */
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
@@ -478,8 +473,6 @@ static int uhci_start(struct usb_hcd *hcd)
struct dentry *dentry;
hcd->uses_new_polling = 1;
- if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
- hcd->can_wakeup = 1; /* Assume it supports PME# */
dentry = debugfs_create_file(hcd->self.bus_name,
S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
@@ -573,7 +566,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
/* This dummy TD is to work around a bug in Intel PIIX controllers */
- uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
+ uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
@@ -735,8 +728,9 @@ static int uhci_resume(struct usb_hcd *hcd)
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
- /* We aren't in D3 state anymore, we do that even if dead as I
- * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
+ /* Since we aren't in D3 any more, it's safe to set this flag
+ * even if the controller was dead. It might not even be dead
+ * any more, if the firmware or quirks code has reset it.
*/
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb();
@@ -755,8 +749,12 @@ static int uhci_resume(struct usb_hcd *hcd)
check_and_reset_hc(uhci);
configure_hc(uhci);
- if (uhci->rh_state == UHCI_RH_RESET)
+ if (uhci->rh_state == UHCI_RH_RESET) {
+
+ /* The controller had to be reset */
+ usb_root_hub_lost_power(hcd->self.root_hub);
suspend_rh(uhci, UHCI_RH_SUSPENDED);
+ }
spin_unlock_irq(&uhci->lock);
@@ -882,7 +880,7 @@ static int __init uhci_hcd_init(void)
init_failed:
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
up_failed:
debugfs_remove(uhci_debugfs_root);
@@ -900,7 +898,7 @@ static void __exit uhci_hcd_cleanup(void)
pci_unregister_driver(&uhci_pci_driver);
if (kmem_cache_destroy(uhci_up_cachep))
- warn("not all urb_priv's were freed!");
+ warn("not all urb_privs were freed!");
debugfs_remove(uhci_debugfs_root);
kfree(errbuf);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index e576db57a926..8b4b887a7d41 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -71,8 +71,6 @@
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
-#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
-
#define UHCI_PTR_BITS cpu_to_le32(0x000F)
#define UHCI_PTR_TERM cpu_to_le32(0x0001)
#define UHCI_PTR_QH cpu_to_le32(0x0002)
@@ -168,9 +166,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */
#define TD_TOKEN_PID_MASK 0xFF
-#define uhci_explen(len) ((len) << TD_TOKEN_EXPLEN_SHIFT)
+#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
+ TD_TOKEN_EXPLEN_SHIFT)
-#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
+#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
+ 1) & TD_TOKEN_EXPLEN_MASK)
#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
#define uhci_endpoint(token) (((token) >> 15) & 0xf)
#define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
@@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) {
*/
/*
- * The UHCI driver places Interrupt, Control and Bulk into QH's both
- * to group together TD's for one transfer, and also to faciliate queuing
- * of URB's. To make it easy to insert entries into the schedule, we have
- * a skeleton of QH's for each predefined Interrupt latency, low-speed
+ * The UHCI driver places Interrupt, Control and Bulk into QHs both
+ * to group together TDs for one transfer, and also to facilitate queuing
+ * of URBs. To make it easy to insert entries into the schedule, we have
+ * a skeleton of QHs for each predefined Interrupt latency, low-speed
* control, full-speed control and terminating QH (see explanation for
* the terminating QH below).
*
@@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) {
* reclamation.
*
* Isochronous transfers are stored before the start of the skeleton
- * schedule and don't use QH's. While the UHCI spec doesn't forbid the
- * use of QH's for Isochronous, it doesn't use them either. And the spec
+ * schedule and don't use QHs. While the UHCI spec doesn't forbid the
+ * use of QHs for Isochronous, it doesn't use them either. And the spec
* says that queues never advance on an error completion status, which
* makes them totally unsuitable for Isochronous transfers.
*/
@@ -359,7 +359,7 @@ struct uhci_hcd {
struct dma_pool *td_pool;
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
- struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
+ struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
spinlock_t lock;
@@ -389,22 +389,22 @@ struct uhci_hcd {
unsigned long resuming_ports;
unsigned long ports_timeout; /* Time to stop signalling */
- /* Main list of URB's currently controlled by this HC */
+ /* Main list of URBs currently controlled by this HC */
struct list_head urb_list;
- /* List of QH's that are done, but waiting to be unlinked (race) */
+ /* List of QHs that are done, but waiting to be unlinked (race) */
struct list_head qh_remove_list;
unsigned int qh_remove_age; /* Age in frames */
- /* List of TD's that are done, but waiting to be freed (race) */
+ /* List of TDs that are done, but waiting to be freed (race) */
struct list_head td_remove_list;
unsigned int td_remove_age; /* Age in frames */
- /* List of asynchronously unlinked URB's */
+ /* List of asynchronously unlinked URBs */
struct list_head urb_remove_list;
unsigned int urb_remove_age; /* Age in frames */
- /* List of URB's awaiting completion callback */
+ /* List of URBs awaiting completion callback */
struct list_head complete_list;
int rh_numports; /* Number of root-hub ports */
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 7e46887d9e12..b6076004a437 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
}
/*
- * We insert Isochronous URB's directly into the frame list at the beginning
+ * We insert Isochronous URBs directly into the frame list at the beginning
*/
static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
{
@@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
uhci_fixup_toggle(urb,
uhci_toggle(td_token(lltd)) ^ 1));
- /* All qh's in the queue need to link to the next queue */
+ /* All qhs in the queue need to link to the next queue */
urbp->qh->link = eurbp->qh->link;
wmb(); /* Make sure we flush everything */
@@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
}
/* Check to see if the remove list is empty. Set the IOC bit */
- /* to force an interrupt so we can remove the TD's*/
+ /* to force an interrupt so we can remove the TDs*/
if (list_empty(&uhci->td_remove_list))
uhci_set_next_interrupt(uhci);
@@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(7),
+ uhci_fill_td(td, status, destination | uhci_explen(8),
urb->setup_dma);
/*
@@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
}
/*
- * Build the DATA TD's
+ * Build the DATA TDs
*/
while (len > 0) {
int pktsze = len;
@@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
destination ^= TD_TOKEN_TOGGLE;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze),
data);
data += pktsze;
@@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status | TD_CTRL_IOC,
- destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+ destination | uhci_explen(0), 0);
qh = uhci_alloc_qh(uhci);
if (!qh)
@@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
urb->actual_length = 0;
- /* The rest of the TD's (but the last) are data */
+ /* The rest of the TDs (but the last) are data */
tmp = tmp->next;
while (tmp != head && tmp->next != head) {
unsigned int ctrlstat;
@@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
status |= TD_CTRL_SPD;
/*
- * Build the DATA TD's
+ * Build the DATA TDs
*/
do { /* Allow zero length packets */
int pktsze = maxsze;
@@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+ uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+ uhci_fill_td(td, status, destination | uhci_explen(0) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig
list_for_each_entry(up, &uhci->urb_list, urb_list) {
struct urb *u = up->urb;
- /* look for pending URB's with identical pipe handle */
+ /* look for pending URBs with identical pipe handle */
if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
(u->status == -EINPROGRESS) && (u != urb)) {
if (!last_urb)
@@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
- uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+ uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
urb->transfer_dma + urb->iso_frame_desc[i].offset);
if (i + 1 >= urb->number_of_packets)
@@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
uhci_delete_queued_urb(uhci, urb);
- /* The interrupt loop will reclaim the QH's */
+ /* The interrupt loop will reclaim the QHs */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = NULL;
}
@@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
list_for_each_entry(td, head, list) {
/*
* Make sure we don't do the last one (since it'll have the
- * TERM bit set) as well as we skip every so many TD's to
+ * TERM bit set) as well as we skip every so many TDs to
* make sure it doesn't hog the bandwidth
*/
if (td->list.next != head && (count % DEPTH_INTERVAL) ==
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 1d973bcf56aa..049871145d63 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -962,7 +962,6 @@ MODULE_DEVICE_TABLE (usb, mdc800_table);
*/
static struct usb_driver mdc800_usb_driver =
{
- .owner = THIS_MODULE,
.name = "mdc800",
.probe = mdc800_usb_probe,
.disconnect = mdc800_usb_disconnect,
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 950543aa5ac7..28538db9eaf3 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -160,7 +160,6 @@ static void mts_usb_disconnect(struct usb_interface *intf);
static struct usb_device_id mts_usb_ids [];
static struct usb_driver mts_usb_driver = {
- .owner = THIS_MODULE,
.name = "microtekX6",
.probe = mts_usb_probe,
.disconnect = mts_usb_disconnect,
@@ -675,7 +674,7 @@ struct vendor_product
/* These are taken from the msmUSB.inf file on the Windows driver CD */
-const static struct vendor_product mts_supported_products[] =
+static const struct vendor_product mts_supported_products[] =
{
{ "Phantom 336CX", mts_sup_unknown},
{ "Phantom 336CX", mts_sup_unknown},
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 1e53934907c0..5246b35301de 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -37,6 +37,16 @@ config USB_HIDINPUT
If unsure, say Y.
+config USB_HIDINPUT_POWERBOOK
+ bool "Enable support for iBook/PowerBook special keys"
+ default n
+ depends on USB_HIDINPUT
+ help
+ Say Y here if you want support for the special keys (Fn, Numlock) on
+ Apple iBooks and PowerBooks.
+
+ If unsure, say N.
+
config HID_FF
bool "Force feedback support (EXPERIMENTAL)"
depends on USB_HIDINPUT && EXPERIMENTAL
@@ -273,6 +283,20 @@ config USB_ATI_REMOTE
To compile this driver as a module, choose M here: the module will be
called ati_remote.
+config USB_ATI_REMOTE2
+ tristate "ATI / Philips USB RF remote control"
+ depends on USB && INPUT
+ ---help---
+ Say Y here if you want to use an ATI or Philips USB RF remote control.
+ These are RF remotes with USB receivers.
+ ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
+ and is also available as a separate product.
+ This driver provides mouse pointer, left and right mouse buttons,
+ and maps all the other remote buttons to keypress events.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ati_remote2.
+
config USB_KEYSPAN_REMOTE
tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index 07cb17db42fc..d512d9f488fe 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -28,6 +28,7 @@ endif
obj-$(CONFIG_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o
+obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_USB_HID) += usbhid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index a32558b4048e..df29b8078b54 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -261,7 +261,6 @@ static struct usb_device_id usb_acecad_id_table [] = {
MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
static struct usb_driver usb_acecad_driver = {
- .owner = THIS_MODULE,
.name = "usb_acecad",
.probe = usb_acecad_probe,
.disconnect = usb_acecad_disconnect,
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 0e2505c073db..a6693b0d1c4c 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -338,7 +338,7 @@ struct aiptek {
* the bitmap which comes from the tablet. This hides the
* issue that the F_keys are not sequentially numbered.
*/
-static int macroKeyEvents[] = {
+static const int macroKeyEvents[] = {
KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17,
@@ -2093,7 +2093,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Programming the tablet macro keys needs to be done with a for loop
* as the keycodes are discontiguous.
*/
- for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
+ for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
set_bit(macroKeyEvents[i], inputdev->keybit);
/*
@@ -2135,7 +2135,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
* not an error :-)
*/
- for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
+ for (i = 0; i < ARRAY_SIZE(speeds); ++i) {
aiptek->curSetting.programmableDelay = speeds[i];
(void)aiptek_program_tablet(aiptek);
if (aiptek->inputdev->absmax[ABS_X] > 0) {
@@ -2190,7 +2190,6 @@ fail1: input_free_device(inputdev);
static void aiptek_disconnect(struct usb_interface *intf);
static struct usb_driver aiptek_driver = {
- .owner = THIS_MODULE,
.name = "aiptek",
.probe = aiptek_probe,
.disconnect = aiptek_disconnect,
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 15840db092a5..c222ed13deab 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -6,6 +6,7 @@
* Copyright (C) 2005 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
*
* Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
*
@@ -38,6 +39,11 @@
/* Apple has powerbooks which have the keyboard with different Product IDs */
#define APPLE_VENDOR_ID 0x05AC
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define GEYSER_ANSI_PRODUCT_ID 0x0214
+#define GEYSER_ISO_PRODUCT_ID 0x0215
+#define GEYSER_JIS_PRODUCT_ID 0x0216
+
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
@@ -53,13 +59,17 @@ static struct usb_device_id atp_table [] = {
{ ATP_DEVICE(0x020F) },
{ ATP_DEVICE(0x030A) },
{ ATP_DEVICE(0x030B) },
- { } /* Terminating entry */
+
+ /* PowerBooks Oct 2005 */
+ { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+ /* 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
@@ -108,6 +118,8 @@ struct atp {
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
/* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+ int overflowwarn; /* overflow warning printed? */
+ int datalen; /* size of an USB urb transfer */
};
#define dbg_dump(msg, tab) \
@@ -124,7 +136,7 @@ struct atp {
if (debug) printk(format, ##a); \
} while (0)
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
MODULE_LICENSE("GPL");
@@ -132,6 +144,16 @@ static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+ int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+ return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER_ISO_PRODUCT_ID) ||
+ (productId == GEYSER_JIS_PRODUCT_ID);
+}
+
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int *z, int *fingers)
{
@@ -168,13 +190,20 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
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;
+ int retval, i, j;
struct atp *dev = urb->context;
switch (urb->status) {
case 0:
/* success */
break;
+ case -EOVERFLOW:
+ if(!dev->overflowwarn) {
+ printk("appletouch: OVERFLOW with data "
+ "length %d, actual length is %d\n",
+ dev->datalen, dev->urb->actual_length);
+ dev->overflowwarn = 1;
+ }
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
@@ -189,23 +218,45 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
}
/* drop incomplete datasets */
- if (dev->urb->actual_length != ATP_DATASIZE) {
+ if (dev->urb->actual_length != dev->datalen) {
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];
+ if (atp_is_geyser_2(dev)) {
+ memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+ /*
+ * The values are laid out like this:
+ * Y1, Y2, -, Y3, Y4, -, ..., X1, X2, -, X3, X4, -, ...
+ * '-' is an unused value.
+ */
+
+ /* read X values */
+ for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+ dev->xy_cur[i] = dev->data[j];
+ dev->xy_cur[i + 1] = dev->data[j + 1];
+ }
+
+ /* read Y values */
+ for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+ dev->xy_cur[ATP_XSENSORS + i] = dev->data[j];
+ dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 1];
+ }
+ } else {
+ 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);
@@ -216,16 +267,24 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
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");
+ /* 17" Powerbooks have extra X sensors */
+ for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+ if (!dev->xy_cur[i]) continue;
+
+ printk("appletouch: 17\" model detected.\n");
+ if(atp_is_geyser_2(dev))
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (20 - 1) *
+ ATP_XFACT - 1,
+ ATP_FUZZ, 0);
+ else
input_set_abs_params(dev->input, ABS_X, 0,
(ATP_XSENSORS - 1) *
ATP_XFACT - 1,
ATP_FUZZ, 0);
- break;
- }
+
+ break;
+ }
goto exit;
}
@@ -282,7 +341,8 @@ static void atp_complete(struct urb* urb, struct pt_regs* regs)
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
}
- input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+ input_report_key(dev->input, BTN_LEFT,
+ !!dev->data[dev->datalen - 1]);
input_sync(dev->input);
@@ -353,6 +413,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
dev->udev = udev;
dev->input = input_dev;
+ dev->overflowwarn = 0;
+ dev->datalen = (atp_is_geyser_2(dev)?64:81);
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb) {
@@ -360,7 +422,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
goto err_free_devs;
}
- dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+ dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data) {
retval = -ENOMEM;
@@ -369,7 +431,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
usb_fill_int_urb(dev->urb, udev,
usb_rcvintpipe(udev, int_in_endpointAddr),
- dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+ dev->data, dev->datalen, atp_complete, dev, 1);
usb_make_path(udev, dev->phys, sizeof(dev->phys));
strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -385,14 +447,25 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
set_bit(EV_ABS, input_dev->evbit);
- /*
- * 12" and 15" Powerbooks only have 16 x sensors,
- * 17" models are detected later.
- */
- input_set_abs_params(input_dev, ABS_X, 0,
- (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
- input_set_abs_params(input_dev, ABS_Y, 0,
- (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+ if (atp_is_geyser_2(dev)) {
+ /*
+ * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+ * later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+ } else {
+ /*
+ * 12" and 15" Powerbooks only have 16 x sensors,
+ * 17" models are detected later.
+ */
+ input_set_abs_params(input_dev, ABS_X, 0,
+ (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+ }
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
set_bit(EV_KEY, input_dev->evbit);
@@ -427,7 +500,7 @@ static void atp_disconnect(struct usb_interface *iface)
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
usb_free_urb(dev->urb);
- usb_buffer_free(dev->udev, ATP_DATASIZE,
+ usb_buffer_free(dev->udev, dev->datalen,
dev->data, dev->urb->transfer_dma);
kfree(dev);
}
@@ -452,7 +525,6 @@ static int atp_resume(struct usb_interface *iface)
}
static struct usb_driver atp_driver = {
- .owner = THIS_MODULE,
.name = "appletouch",
.probe = atp_probe,
.disconnect = atp_disconnect,
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 9a2a47db9494..f7bdc506e613 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -96,6 +96,7 @@
#include <linux/usb.h>
#include <linux/usb_input.h>
#include <linux/wait.h>
+#include <linux/jiffies.h>
/*
* Module and Version Information, Module Parameters
@@ -146,7 +147,7 @@ static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
/* Acceleration curve for directional control pad */
-static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
/* Duplicate event filtering time.
* Sequential, identical KIND_FILTERED inputs with less than
@@ -197,7 +198,7 @@ struct ati_remote {
#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
/* Translation table from hardware messages to input events. */
-static struct {
+static const struct {
short kind;
unsigned char data1, data2;
int type;
@@ -295,7 +296,6 @@ static void ati_remote_disconnect (struct usb_interface *interface);
/* usb specific object to register with the usb subsystem */
static struct usb_driver ati_remote_driver = {
- .owner = THIS_MODULE,
.name = "ati_remote",
.probe = ati_remote_probe,
.disconnect = ati_remote_disconnect,
@@ -472,7 +472,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
/* Filter duplicate events which happen "too close" together. */
if ((ati_remote->old_data[0] == data[1]) &&
(ati_remote->old_data[1] == data[2]) &&
- ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
+ time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
ati_remote->repeat_count++;
} else {
ati_remote->repeat_count = 0;
@@ -507,16 +507,16 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
* pad down, so we increase acceleration, ramping up over two seconds to
* a maximum speed. The acceleration curve is #defined above.
*/
- if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) {
+ if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
acc = 1;
ati_remote->acc_jiffies = jiffies;
}
- else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0];
- else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1];
- else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2];
- else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3];
- else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4];
- else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
+ else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5];
else acc = accel[6];
input_regs(dev, regs);
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
new file mode 100644
index 000000000000..ab1a1ae24be9
--- /dev/null
+++ b/drivers/usb/input/ati_remote2.c
@@ -0,0 +1,477 @@
+/*
+ * ati_remote2 - ATI/Philips USB RF remote driver
+ *
+ * Copyright (C) 2005 Ville Syrjala <syrjala@sci.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/usb_input.h>
+
+#define DRIVER_DESC "ATI/Philips USB RF remote driver"
+#define DRIVER_VERSION "0.1"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
+MODULE_LICENSE("GPL");
+
+static unsigned int mode_mask = 0x1F;
+module_param(mode_mask, uint, 0644);
+MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
+
+static struct usb_device_id ati_remote2_id_table[] = {
+ { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */
+ { }
+};
+MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
+
+static struct {
+ int hw_code;
+ int key_code;
+} ati_remote2_key_table[] = {
+ { 0x00, KEY_0 },
+ { 0x01, KEY_1 },
+ { 0x02, KEY_2 },
+ { 0x03, KEY_3 },
+ { 0x04, KEY_4 },
+ { 0x05, KEY_5 },
+ { 0x06, KEY_6 },
+ { 0x07, KEY_7 },
+ { 0x08, KEY_8 },
+ { 0x09, KEY_9 },
+ { 0x0c, KEY_POWER },
+ { 0x0d, KEY_MUTE },
+ { 0x10, KEY_VOLUMEUP },
+ { 0x11, KEY_VOLUMEDOWN },
+ { 0x20, KEY_CHANNELUP },
+ { 0x21, KEY_CHANNELDOWN },
+ { 0x28, KEY_FORWARD },
+ { 0x29, KEY_REWIND },
+ { 0x2c, KEY_PLAY },
+ { 0x30, KEY_PAUSE },
+ { 0x31, KEY_STOP },
+ { 0x37, KEY_RECORD },
+ { 0x38, KEY_DVD },
+ { 0x39, KEY_TV },
+ { 0x54, KEY_MENU },
+ { 0x58, KEY_UP },
+ { 0x59, KEY_DOWN },
+ { 0x5a, KEY_LEFT },
+ { 0x5b, KEY_RIGHT },
+ { 0x5c, KEY_OK },
+ { 0x78, KEY_A },
+ { 0x79, KEY_B },
+ { 0x7a, KEY_C },
+ { 0x7b, KEY_D },
+ { 0x7c, KEY_E },
+ { 0x7d, KEY_F },
+ { 0x82, KEY_ENTER },
+ { 0x8e, KEY_VENDOR },
+ { 0x96, KEY_COFFEE },
+ { 0xa9, BTN_LEFT },
+ { 0xaa, BTN_RIGHT },
+ { 0xbe, KEY_QUESTION },
+ { 0xd5, KEY_FRONT },
+ { 0xd0, KEY_EDIT },
+ { 0xf9, KEY_INFO },
+ { (0x00 << 8) | 0x3f, KEY_PROG1 },
+ { (0x01 << 8) | 0x3f, KEY_PROG2 },
+ { (0x02 << 8) | 0x3f, KEY_PROG3 },
+ { (0x03 << 8) | 0x3f, KEY_PROG4 },
+ { (0x04 << 8) | 0x3f, KEY_PC },
+ { 0, KEY_RESERVED }
+};
+
+struct ati_remote2 {
+ struct input_dev *idev;
+ struct usb_device *udev;
+
+ struct usb_interface *intf[2];
+ struct usb_endpoint_descriptor *ep[2];
+ struct urb *urb[2];
+ void *buf[2];
+ dma_addr_t buf_dma[2];
+
+ unsigned long jiffies;
+ int mode;
+
+ char name[64];
+ char phys[64];
+};
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
+static void ati_remote2_disconnect(struct usb_interface *interface);
+
+static struct usb_driver ati_remote2_driver = {
+ .name = "ati_remote2",
+ .probe = ati_remote2_probe,
+ .disconnect = ati_remote2_disconnect,
+ .id_table = ati_remote2_id_table,
+};
+
+static int ati_remote2_open(struct input_dev *idev)
+{
+ struct ati_remote2 *ar2 = idev->private;
+ int r;
+
+ r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
+ if (r) {
+ dev_err(&ar2->intf[0]->dev,
+ "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+ return r;
+ }
+ r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
+ if (r) {
+ usb_kill_urb(ar2->urb[0]);
+ dev_err(&ar2->intf[1]->dev,
+ "%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
+ return r;
+ }
+
+ return 0;
+}
+
+static void ati_remote2_close(struct input_dev *idev)
+{
+ struct ati_remote2 *ar2 = idev->private;
+
+ usb_kill_urb(ar2->urb[0]);
+ usb_kill_urb(ar2->urb[1]);
+}
+
+static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+ struct input_dev *idev = ar2->idev;
+ u8 *data = ar2->buf[0];
+
+ if (data[0] > 4) {
+ dev_err(&ar2->intf[0]->dev,
+ "Unknown mode byte (%02x %02x %02x %02x)\n",
+ data[3], data[2], data[1], data[0]);
+ return;
+ }
+
+ if (!((1 << data[0]) & mode_mask))
+ return;
+
+ input_regs(idev, regs);
+ input_event(idev, EV_REL, REL_X, (s8) data[1]);
+ input_event(idev, EV_REL, REL_Y, (s8) data[2]);
+ input_sync(idev);
+}
+
+static int ati_remote2_lookup(unsigned int hw_code)
+{
+ int i;
+
+ for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+ if (ati_remote2_key_table[i].hw_code == hw_code)
+ return i;
+
+ return -1;
+}
+
+static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs)
+{
+ struct input_dev *idev = ar2->idev;
+ u8 *data = ar2->buf[1];
+ int hw_code, index;
+
+ if (data[0] > 4) {
+ dev_err(&ar2->intf[1]->dev,
+ "Unknown mode byte (%02x %02x %02x %02x)\n",
+ data[3], data[2], data[1], data[0]);
+ return;
+ }
+
+ hw_code = data[2];
+ /*
+ * Mode keys (AUX1-AUX4, PC) all generate the same code byte.
+ * Use the mode byte to figure out which one was pressed.
+ */
+ if (hw_code == 0x3f) {
+ /*
+ * For some incomprehensible reason the mouse pad generates
+ * events which look identical to the events from the last
+ * pressed mode key. Naturally we don't want to generate key
+ * events for the mouse pad so we filter out any subsequent
+ * events from the same mode key.
+ */
+ if (ar2->mode == data[0])
+ return;
+
+ if (data[1] == 0)
+ ar2->mode = data[0];
+
+ hw_code |= data[0] << 8;
+ }
+
+ if (!((1 << data[0]) & mode_mask))
+ return;
+
+ index = ati_remote2_lookup(hw_code);
+ if (index < 0) {
+ dev_err(&ar2->intf[1]->dev,
+ "Unknown code byte (%02x %02x %02x %02x)\n",
+ data[3], data[2], data[1], data[0]);
+ return;
+ }
+
+ switch (data[1]) {
+ case 0: /* release */
+ break;
+ case 1: /* press */
+ ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]);
+ break;
+ case 2: /* repeat */
+
+ /* No repeat for mouse buttons. */
+ if (ati_remote2_key_table[index].key_code == BTN_LEFT ||
+ ati_remote2_key_table[index].key_code == BTN_RIGHT)
+ return;
+
+ if (!time_after_eq(jiffies, ar2->jiffies))
+ return;
+
+ ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]);
+ break;
+ default:
+ dev_err(&ar2->intf[1]->dev,
+ "Unknown state byte (%02x %02x %02x %02x)\n",
+ data[3], data[2], data[1], data[0]);
+ return;
+ }
+
+ input_regs(idev, regs);
+ input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
+ input_sync(idev);
+}
+
+static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs)
+{
+ struct ati_remote2 *ar2 = urb->context;
+ int r;
+
+ switch (urb->status) {
+ case 0:
+ ati_remote2_input_mouse(ar2, regs);
+ break;
+ case -ENOENT:
+ case -EILSEQ:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dev_dbg(&ar2->intf[0]->dev,
+ "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ return;
+ default:
+ dev_err(&ar2->intf[0]->dev,
+ "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ }
+
+ r = usb_submit_urb(urb, GFP_ATOMIC);
+ if (r)
+ dev_err(&ar2->intf[0]->dev,
+ "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs)
+{
+ struct ati_remote2 *ar2 = urb->context;
+ int r;
+
+ switch (urb->status) {
+ case 0:
+ ati_remote2_input_key(ar2, regs);
+ break;
+ case -ENOENT:
+ case -EILSEQ:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ dev_dbg(&ar2->intf[1]->dev,
+ "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ return;
+ default:
+ dev_err(&ar2->intf[1]->dev,
+ "%s(): urb status = %d\n", __FUNCTION__, urb->status);
+ }
+
+ r = usb_submit_urb(urb, GFP_ATOMIC);
+ if (r)
+ dev_err(&ar2->intf[1]->dev,
+ "%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
+}
+
+static int ati_remote2_input_init(struct ati_remote2 *ar2)
+{
+ struct input_dev *idev;
+ int i;
+
+ idev = input_allocate_device();
+ if (!idev)
+ return -ENOMEM;
+
+ ar2->idev = idev;
+ idev->private = ar2;
+
+ idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
+ idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
+ idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+ for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
+ set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
+
+ idev->rep[REP_DELAY] = 250;
+ idev->rep[REP_PERIOD] = 33;
+
+ idev->open = ati_remote2_open;
+ idev->close = ati_remote2_close;
+
+ idev->name = ar2->name;
+ idev->phys = ar2->phys;
+
+ usb_to_input_id(ar2->udev, &idev->id);
+ idev->cdev.dev = &ar2->udev->dev;
+
+ i = input_register_device(idev);
+ if (i)
+ input_free_device(idev);
+
+ return i;
+}
+
+static int ati_remote2_urb_init(struct ati_remote2 *ar2)
+{
+ struct usb_device *udev = ar2->udev;
+ int i, pipe, maxp;
+
+ for (i = 0; i < 2; i++) {
+ ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
+ if (!ar2->buf[i])
+ return -ENOMEM;
+
+ ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ar2->urb[i])
+ return -ENOMEM;
+
+ pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ maxp = maxp > 4 ? 4 : maxp;
+
+ usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
+ i ? ati_remote2_complete_key : ati_remote2_complete_mouse,
+ ar2, ar2->ep[i]->bInterval);
+ ar2->urb[i]->transfer_dma = ar2->buf_dma[i];
+ ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ return 0;
+}
+
+static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (ar2->urb[i])
+ usb_free_urb(ar2->urb[i]);
+
+ if (ar2->buf[i])
+ usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
+ }
+}
+
+static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct usb_host_interface *alt = interface->cur_altsetting;
+ struct ati_remote2 *ar2;
+ int r;
+
+ if (alt->desc.bInterfaceNumber)
+ return -ENODEV;
+
+ ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL);
+ if (!ar2)
+ return -ENOMEM;
+
+ ar2->udev = udev;
+
+ ar2->intf[0] = interface;
+ ar2->ep[0] = &alt->endpoint[0].desc;
+
+ ar2->intf[1] = usb_ifnum_to_if(udev, 1);
+ r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
+ if (r)
+ goto fail1;
+ alt = ar2->intf[1]->cur_altsetting;
+ ar2->ep[1] = &alt->endpoint[0].desc;
+
+ r = ati_remote2_urb_init(ar2);
+ if (r)
+ goto fail2;
+
+ usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
+ strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
+
+ strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
+
+ r = ati_remote2_input_init(ar2);
+ if (r)
+ goto fail2;
+
+ usb_set_intfdata(interface, ar2);
+
+ return 0;
+
+ fail2:
+ ati_remote2_urb_cleanup(ar2);
+
+ usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+ fail1:
+ kfree(ar2);
+
+ return r;
+}
+
+static void ati_remote2_disconnect(struct usb_interface *interface)
+{
+ struct ati_remote2 *ar2;
+ struct usb_host_interface *alt = interface->cur_altsetting;
+
+ if (alt->desc.bInterfaceNumber)
+ return;
+
+ ar2 = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+ input_unregister_device(ar2->idev);
+
+ ati_remote2_urb_cleanup(ar2);
+
+ usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
+
+ kfree(ar2);
+}
+
+static int __init ati_remote2_init(void)
+{
+ int r;
+
+ r = usb_register(&ati_remote2_driver);
+ if (r)
+ printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r);
+ else
+ printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n");
+
+ return r;
+}
+
+static void __exit ati_remote2_exit(void)
+{
+ usb_deregister(&ati_remote2_driver);
+}
+
+module_init(ati_remote2_init);
+module_exit(ati_remote2_exit);
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h
index 26ca5b890a61..b44d398de071 100644
--- a/drivers/usb/input/fixp-arith.h
+++ b/drivers/usb/input/fixp-arith.h
@@ -38,7 +38,7 @@ typedef s16 fixp_t;
#define FRAC_MASK ((1<<FRAC_N)-1)
// Not to be used directly. Use fixp_{cos,sin}
-static fixp_t cos_table[45] = {
+static const fixp_t cos_table[45] = {
0x0100, 0x00FF, 0x00FF, 0x00FE, 0x00FD, 0x00FC, 0x00FA, 0x00F8,
0x00F6, 0x00F3, 0x00F0, 0x00ED, 0x00E9, 0x00E6, 0x00E2, 0x00DD,
0x00D9, 0x00D4, 0x00CF, 0x00C9, 0x00C4, 0x00BE, 0x00B8, 0x00B1,
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index a3e44ef1df43..a91e72c41415 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1450,11 +1450,14 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304
+#define USB_VENDOR_ID_CHERRY 0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
+
/*
* Alphabetically sorted blacklist by quirk type.
*/
-static struct hid_blacklist {
+static const struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
unsigned quirks;
@@ -1580,6 +1583,16 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
+
+ { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+
{ 0, 0 }
};
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
}
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+
+static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ info("Fixing up Cherry Cymotion report descriptor");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return NULL;
}
+ if ((quirks & HID_QUIRK_CYMOTION))
+ hid_fixup_cymotion_descriptor(rdesc, rsize);
+
#ifdef DEBUG_DATA
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
@@ -1930,7 +1960,6 @@ static struct usb_device_id hid_usb_ids [] = {
MODULE_DEVICE_TABLE (usb, hid_usb_ids);
static struct usb_driver hid_driver = {
- .owner = THIS_MODULE,
.name = "usbhid",
.probe = hid_probe,
.disconnect = hid_disconnect,
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index ceebab99eff2..702c48c2f81b 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -681,6 +681,21 @@ static char *keys[KEY_MAX + 1] = {
[KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
[KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
[KEY_DOCUMENTS] = "Documents",
+ [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
+ [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
+ [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
+ [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F",
+ [KEY_FN_S] = "Fn+S",
+ [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2",
+ [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4",
+ [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6",
+ [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8",
+ [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10",
+ [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12",
+ [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
+ [KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
+ [KEY_KBDILLUMUP] = "KbdIlluminationUp",
+ [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
};
static char *relatives[REL_MAX + 1] = {
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 1220a5004a5c..cb0d80f49252 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -39,7 +39,7 @@
#define unk KEY_UNKNOWN
-static unsigned char hid_keyboard[256] = {
+static const unsigned char hid_keyboard[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
@@ -58,7 +58,7 @@ static unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
-static struct {
+static const struct {
__s32 x;
__s32 y;
} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
@@ -73,6 +73,160 @@ static struct {
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+
+struct hidinput_key_translation {
+ u16 from;
+ u16 to;
+ u8 flags;
+};
+
+#define POWERBOOK_FLAG_FKEY 0x01
+
+static struct hidinput_key_translation powerbook_fn_keys[] = {
+ { KEY_BACKSPACE, KEY_DELETE },
+ { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
+ { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
+ { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
+ { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
+ { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
+ { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
+ { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
+ { KEY_UP, KEY_PAGEUP },
+ { KEY_DOWN, KEY_PAGEDOWN },
+ { KEY_LEFT, KEY_HOME },
+ { KEY_RIGHT, KEY_END },
+ { }
+};
+
+static struct hidinput_key_translation powerbook_numlock_keys[] = {
+ { KEY_J, KEY_KP1 },
+ { KEY_K, KEY_KP2 },
+ { KEY_L, KEY_KP3 },
+ { KEY_U, KEY_KP4 },
+ { KEY_I, KEY_KP5 },
+ { KEY_O, KEY_KP6 },
+ { KEY_7, KEY_KP7 },
+ { KEY_8, KEY_KP8 },
+ { KEY_9, KEY_KP9 },
+ { KEY_M, KEY_KP0 },
+ { KEY_DOT, KEY_KPDOT },
+ { KEY_SLASH, KEY_KPPLUS },
+ { KEY_SEMICOLON, KEY_KPMINUS },
+ { KEY_P, KEY_KPASTERISK },
+ { KEY_MINUS, KEY_KPEQUAL },
+ { KEY_0, KEY_KPSLASH },
+ { KEY_F6, KEY_NUMLOCK },
+ { KEY_KPENTER, KEY_KPENTER },
+ { KEY_BACKSPACE, KEY_BACKSPACE },
+ { }
+};
+
+static int usbhid_pb_fnmode = 1;
+module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+ "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
+
+static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
+{
+ struct hidinput_key_translation *trans;
+
+ /* Look for the translation */
+ for (trans = table; trans->from; trans++)
+ if (trans->from == from)
+ return trans;
+
+ return NULL;
+}
+
+static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ struct hid_usage *usage, __s32 value)
+{
+ struct hidinput_key_translation *trans;
+
+ if (usage->code == KEY_FN) {
+ if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
+ else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
+
+ input_event(input, usage->type, usage->code, value);
+
+ return 1;
+ }
+
+ if (usbhid_pb_fnmode) {
+ int do_translate;
+
+ trans = find_translation(powerbook_fn_keys, usage->code);
+ if (trans) {
+ if (test_bit(usage->code, hid->pb_pressed_fn))
+ do_translate = 1;
+ else if (trans->flags & POWERBOOK_FLAG_FKEY)
+ do_translate =
+ (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+ (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
+ else
+ do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
+
+ if (do_translate) {
+ if (value)
+ set_bit(usage->code, hid->pb_pressed_fn);
+ else
+ clear_bit(usage->code, hid->pb_pressed_fn);
+
+ input_event(input, usage->type, trans->to, value);
+
+ return 1;
+ }
+ }
+
+ if (test_bit(usage->code, hid->pb_pressed_numlock) ||
+ test_bit(LED_NUML, input->led)) {
+ trans = find_translation(powerbook_numlock_keys, usage->code);
+
+ if (trans) {
+ if (value)
+ set_bit(usage->code, hid->pb_pressed_numlock);
+ else
+ clear_bit(usage->code, hid->pb_pressed_numlock);
+
+ input_event(input, usage->type, trans->to, value);
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void hidinput_pb_setup(struct input_dev *input)
+{
+ struct hidinput_key_translation *trans;
+
+ set_bit(KEY_NUMLOCK, input->keybit);
+
+ /* Enable all needed keys */
+ for (trans = powerbook_fn_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+
+ for (trans = powerbook_numlock_keys; trans->from; trans++)
+ set_bit(trans->to, input->keybit);
+}
+#else
+static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ struct hid_usage *usage, __s32 value)
+{
+ return 0;
+}
+
+static inline void hidinput_pb_setup(struct input_dev *input)
+{
+}
+#endif
+
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case HID_UP_SIMULATION:
switch (usage->hid & 0xffff) {
- case 0xba: map_abs(ABS_RUDDER); break;
+ case 0xba: map_abs(ABS_RUDDER); break;
case 0xbb: map_abs(ABS_THROTTLE); break;
+ case 0xc4: map_abs(ABS_GAS); break;
+ case 0xc5: map_abs(ABS_BRAKE); break;
+ case 0xc8: map_abs(ABS_WHEEL); break;
default: goto ignore;
}
break;
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x226: map_key_clear(KEY_STOP); break;
case 0x227: map_key_clear(KEY_REFRESH); break;
case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
+ case 0x233: map_key_clear(KEY_SCROLLUP); break;
+ case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
case 0x238: map_rel(REL_HWHEEL); break;
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;
+
+ /* Reported on a Cherry Cymotion keyboard */
+ case 0x301: map_key_clear(KEY_PROG1); break;
+ case 0x302: map_key_clear(KEY_PROG2); break;
+ case 0x303: map_key_clear(KEY_PROG3); break;
+
default: goto ignore;
}
break;
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
- case 0x003: map_key_clear(KEY_FN); break;
+ case 0x003:
+ /* The fn key on Apple PowerBooks */
+ map_key_clear(KEY_FN);
+ hidinput_pb_setup(input);
+ break;
+
default: goto ignore;
}
break;
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}
+ if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
+ return;
+
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}
- if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
+ if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;
input_event(input, usage->type, usage->code, value);
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index ee48a2276104..8b0d4346ce9c 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -235,17 +235,20 @@ struct hid_item {
* HID device quirks.
*/
-#define HID_QUIRK_INVERT 0x001
-#define HID_QUIRK_NOTOUCH 0x002
-#define HID_QUIRK_IGNORE 0x004
-#define HID_QUIRK_NOGET 0x008
-#define HID_QUIRK_HIDDEV 0x010
-#define HID_QUIRK_BADPAD 0x020
-#define HID_QUIRK_MULTI_INPUT 0x040
-#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
+#define HID_QUIRK_INVERT 0x00000001
+#define HID_QUIRK_NOTOUCH 0x00000002
+#define HID_QUIRK_IGNORE 0x00000004
+#define HID_QUIRK_NOGET 0x00000008
+#define HID_QUIRK_HIDDEV 0x00000010
+#define HID_QUIRK_BADPAD 0x00000020
+#define HID_QUIRK_MULTI_INPUT 0x00000040
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
+#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
+#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400
+#define HID_QUIRK_CYMOTION 0x00000800
+#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
+#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
/*
* This is the global environment of the parser. This information is
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */
void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */
int (*ff_event)(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value);
+
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+ unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
+ unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
+#endif
};
#define HID_GLOBAL_STACK_SIZE 4
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 440377c7a0da..4dff8473553d 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -826,7 +826,6 @@ static int hiddev_usbd_probe(struct usb_interface *intf,
static /* const */ struct usb_driver hiddev_driver = {
- .owner = THIS_MODULE,
.name = "hiddev",
.probe = hiddev_usbd_probe,
};
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 4a50acb39d29..7618ae5c104f 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -250,7 +250,6 @@ static void itmtouch_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, itmtouch_ids);
static struct usb_driver itmtouch_driver = {
- .owner = THIS_MODULE,
.name = "itmtouch",
.probe = itmtouch_probe,
.disconnect = itmtouch_disconnect,
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index fd48e74e78ed..f6d5cead542b 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -197,7 +197,6 @@ static void kbtab_disconnect(struct usb_interface *intf)
}
static struct usb_driver kbtab_driver = {
- .owner = THIS_MODULE,
.name = "kbtab",
.probe = kbtab_probe,
.disconnect = kbtab_disconnect,
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index a32cfe51b77d..b4a051b549d1 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -95,7 +95,7 @@ struct usb_keyspan {
* Currently there are 15 and 17 button models so RESERVED codes
* are blank areas in the mapping.
*/
-static int keyspan_key_table[] = {
+static const int keyspan_key_table[] = {
KEY_RESERVED, /* 0 is just a place holder. */
KEY_RESERVED,
KEY_STOP,
@@ -559,7 +559,6 @@ static void keyspan_disconnect(struct usb_interface *interface)
*/
static struct usb_driver keyspan_driver =
{
- .owner = THIS_MODULE,
.name = "keyspan_remote",
.probe = keyspan_probe,
.disconnect = keyspan_disconnect,
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 52cc18cd247d..f018953a5485 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -310,7 +310,6 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
static struct usb_driver mtouchusb_driver = {
- .owner = THIS_MODULE,
.name = "mtouchusb",
.probe = mtouchusb_probe,
.disconnect = mtouchusb_disconnect,
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index 19e015d171aa..d9d9f656b8c9 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
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);
+ struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
struct input_dev *input_dev = hidinput->input;
private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index b7476233ef5d..fdf0f788062c 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -441,7 +441,6 @@ static struct usb_device_id powermate_devices [] = {
MODULE_DEVICE_TABLE (usb, powermate_devices);
static struct usb_driver powermate_driver = {
- .owner = THIS_MODULE,
.name = "powermate",
.probe = powermate_probe,
.disconnect = powermate_disconnect,
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 7420c6b84284..3b3c7b4120a2 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -1,7 +1,7 @@
/******************************************************************************
* touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens
*
- * Copyright (C) 2004 by Daniel Ritz
+ * Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
*
* This program is free software; you can redistribute it and/or
@@ -41,15 +41,13 @@
#define TOUCHKIT_MAX_YC 0x07ff
#define TOUCHKIT_YC_FUZZ 0x0
#define TOUCHKIT_YC_FLAT 0x0
-#define TOUCHKIT_REPORT_DATA_SIZE 8
+#define TOUCHKIT_REPORT_DATA_SIZE 16
#define TOUCHKIT_DOWN 0x01
-#define TOUCHKIT_POINT_TOUCH 0x81
-#define TOUCHKIT_POINT_NOTOUCH 0x80
-#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0)
-#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4])
-#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2])
+#define TOUCHKIT_PKT_TYPE_MASK 0xFE
+#define TOUCHKIT_PKT_TYPE_REPT 0x80
+#define TOUCHKIT_PKT_TYPE_DIAG 0x0A
#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
@@ -62,6 +60,8 @@ MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
struct touchkit_usb {
unsigned char *data;
dma_addr_t data_dma;
+ char buffer[TOUCHKIT_REPORT_DATA_SIZE];
+ int buf_len;
struct urb *irq;
struct usb_device *udev;
struct input_dev *input;
@@ -77,11 +77,128 @@ static struct usb_device_id touchkit_devices[] = {
{}
};
+/* helpers to read the data */
+static inline int touchkit_get_touched(char *data)
+{
+ return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
+}
+
+static inline int touchkit_get_x(char *data)
+{
+ return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
+}
+
+static inline int touchkit_get_y(char *data)
+{
+ return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
+}
+
+
+/* processes one input packet. */
+static void touchkit_process_pkt(struct touchkit_usb *touchkit,
+ struct pt_regs *regs, char *pkt)
+{
+ int x, y;
+
+ /* only process report packets */
+ if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
+ return;
+
+ if (swap_xy) {
+ y = touchkit_get_x(pkt);
+ x = touchkit_get_y(pkt);
+ } else {
+ x = touchkit_get_x(pkt);
+ y = touchkit_get_y(pkt);
+ }
+
+ input_regs(touchkit->input, regs);
+ input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
+ input_report_abs(touchkit->input, ABS_X, x);
+ input_report_abs(touchkit->input, ABS_Y, y);
+ input_sync(touchkit->input);
+}
+
+
+static int touchkit_get_pkt_len(char *buf)
+{
+ switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
+ case TOUCHKIT_PKT_TYPE_REPT:
+ return 5;
+
+ case TOUCHKIT_PKT_TYPE_DIAG:
+ return buf[1] + 2;
+ }
+
+ return 0;
+}
+
+static void touchkit_process(struct touchkit_usb *touchkit, int len,
+ struct pt_regs *regs)
+{
+ char *buffer;
+ int pkt_len, buf_len, pos;
+
+ /* if the buffer contains data, append */
+ if (unlikely(touchkit->buf_len)) {
+ int tmp;
+
+ /* if only 1 byte in buffer, add another one to get length */
+ if (touchkit->buf_len == 1)
+ touchkit->buffer[1] = touchkit->data[0];
+
+ pkt_len = touchkit_get_pkt_len(touchkit->buffer);
+
+ /* unknown packet: drop everything */
+ if (!pkt_len)
+ return;
+
+ /* append, process */
+ tmp = pkt_len - touchkit->buf_len;
+ memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
+ touchkit_process_pkt(touchkit, regs, touchkit->buffer);
+
+ buffer = touchkit->data + tmp;
+ buf_len = len - tmp;
+ } else {
+ buffer = touchkit->data;
+ buf_len = len;
+ }
+
+ /* only one byte left in buffer */
+ if (unlikely(buf_len == 1)) {
+ touchkit->buffer[0] = buffer[0];
+ touchkit->buf_len = 1;
+ return;
+ }
+
+ /* loop over the buffer */
+ pos = 0;
+ while (pos < buf_len) {
+ /* get packet len */
+ pkt_len = touchkit_get_pkt_len(buffer + pos);
+
+ /* unknown packet: drop everything */
+ if (unlikely(!pkt_len))
+ return;
+
+ /* full packet: process */
+ if (likely(pkt_len <= buf_len)) {
+ touchkit_process_pkt(touchkit, regs, buffer + pos);
+ } else {
+ /* incomplete packet: save in buffer */
+ memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
+ touchkit->buf_len = buf_len - pos;
+ }
+ pos += pkt_len;
+ }
+}
+
+
static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
{
struct touchkit_usb *touchkit = urb->context;
int retval;
- int x, y;
switch (urb->status) {
case 0:
@@ -105,20 +222,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
- if (swap_xy) {
- y = TOUCHKIT_GET_X(touchkit->data);
- x = TOUCHKIT_GET_Y(touchkit->data);
- } else {
- x = TOUCHKIT_GET_X(touchkit->data);
- y = TOUCHKIT_GET_Y(touchkit->data);
- }
-
- input_regs(touchkit->input, regs);
- input_report_key(touchkit->input, BTN_TOUCH,
- TOUCHKIT_GET_TOUCHED(touchkit->data));
- input_report_abs(touchkit->input, ABS_X, x);
- input_report_abs(touchkit->input, ABS_Y, y);
- input_sync(touchkit->input);
+ touchkit_process(touchkit, urb->actual_length, regs);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -267,7 +371,6 @@ static void touchkit_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, touchkit_devices);
static struct usb_driver touchkit_driver = {
- .owner = THIS_MODULE,
.name = "touchkitusb",
.probe = touchkit_probe,
.disconnect = touchkit_disconnect,
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 226b6f90a907..2f3edc26cb50 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -345,7 +345,6 @@ static struct usb_device_id usb_kbd_id_table [] = {
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
static struct usb_driver usb_kbd_driver = {
- .owner = THIS_MODULE,
.name = "usbkbd",
.probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect,
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 230f6b1b314a..af526135d210 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -226,7 +226,6 @@ static struct usb_device_id usb_mouse_id_table [] = {
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
static struct usb_driver usb_mouse_driver = {
- .owner = THIS_MODULE,
.name = "usbmouse",
.probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect,
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index dc099bbe12bf..d3e15df9e815 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE);
enum {
PENPARTNER = 0,
GRAPHIRE,
- G4,
+ WACOM_G4,
PL,
INTUOS,
INTUOS3,
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
case 2: /* Mouse with wheel */
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
- if (wacom->features->type == G4) {
+ if (wacom->features->type == WACOM_G4) {
rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03);
input_report_rel(dev, REL_WHEEL, rw);
} else
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
id = CURSOR_DEVICE_ID;
input_report_key(dev, BTN_LEFT, data[1] & 0x01);
input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
- if (wacom->features->type == G4)
+ if (wacom->features->type == WACOM_G4)
input_report_abs(dev, ABS_DISTANCE, data[6]);
else
input_report_abs(dev, ABS_DISTANCE, data[7]);
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
input_sync(dev);
/* send pad data */
- if (wacom->features->type == G4) {
+ if (wacom->features->type == WACOM_G4) {
/* fist time sending pad data */
if (wacom->tool[1] != BTN_TOOL_FINGER) {
wacom->id[1] = 0;
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq },
- { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq },
- { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq },
+ { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq },
+ { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq },
{ "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq },
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq },
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
switch (wacom->features->type) {
- case G4:
+ case WACOM_G4:
input_dev->evbit[0] |= BIT(EV_MSC);
input_dev->mscbit[0] |= BIT(MSC_SERIAL);
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
@@ -945,7 +945,6 @@ static void wacom_disconnect(struct usb_interface *intf)
}
static struct usb_driver wacom_driver = {
- .owner = THIS_MODULE,
.name = "wacom",
.probe = wacom_probe,
.disconnect = wacom_disconnect,
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 43112f040b6d..e278489a80c6 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -70,7 +70,7 @@
#define XPAD_PKT_LEN 32
-static struct xpad_device {
+static const struct xpad_device {
u16 idVendor;
u16 idProduct;
char *name;
@@ -81,13 +81,13 @@ static struct xpad_device {
{ 0x0000, 0x0000, "X-Box pad" }
};
-static signed short xpad_btn[] = {
+static const signed short xpad_btn[] = {
BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */
BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
-1 /* terminating entry */
};
-static signed short xpad_abs[] = {
+static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
ABS_Z, ABS_RZ, /* triggers left/right */
@@ -316,7 +316,6 @@ static void xpad_disconnect(struct usb_interface *intf)
}
static struct usb_driver xpad_driver = {
- .owner = THIS_MODULE,
.name = "xpad",
.probe = xpad_probe,
.disconnect = xpad_disconnect,
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index f526aebea502..1bfc105ad4d6 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -987,7 +987,6 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
static struct usb_driver yealink_driver = {
- .owner = THIS_MODULE,
.name = "yealink",
.probe = usb_probe,
.disconnect = usb_disconnect,
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 27b23c55bbc7..18d8eaf408d5 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -812,7 +812,6 @@ static struct usb_device_id dabusb_ids [] = {
MODULE_DEVICE_TABLE (usb, dabusb_ids);
static struct usb_driver dabusb_driver = {
- .owner = THIS_MODULE,
.name = "dabusb",
.probe = dabusb_probe,
.disconnect = dabusb_disconnect,
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 7503f5b96f59..25646804d5be 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -127,6 +127,7 @@ static struct file_operations usb_dsbr100_fops = {
.open = usb_dsbr100_open,
.release = usb_dsbr100_close,
.ioctl = usb_dsbr100_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -150,7 +151,6 @@ MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
/* USB subsystem interface */
static struct usb_driver usb_dsbr100_driver = {
- .owner = THIS_MODULE,
.name = "dsbr100",
.probe = usb_dsbr100_probe,
.disconnect = usb_dsbr100_disconnect,
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index ba41fc7b95c2..a42c22294124 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -3457,7 +3457,7 @@ static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
if(init_model3_input) {
if (debug > 0)
info("Setting input to RCA.");
- for (i=0; i < (sizeof(initData)/sizeof(initData[0])); i++) {
+ for (i=0; i < ARRAY_SIZE(initData); i++) {
ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
}
}
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 9fe2c2710d13..e2ede583518f 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -77,14 +77,14 @@ static int saturation = MAX_SATURATION/2;
static int sharpness = MAX_SHARPNESS/2;
static int whitebal = 3*(MAX_WHITEBAL/4);
-static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
+static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
/* These FPS speeds are from the windows config box. They are
* indexed on size (0-2) and speed (0-6). Divide by 3 to get the
* real fps.
*/
-static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
+static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
{ 24, 40, 48, 60, 72, 80, 100 },
{ 18, 30, 36, 45, 54, 60, 75 },
{ 6, 10, 12, 15, 18, 21, 25 } };
@@ -95,7 +95,7 @@ struct cam_size {
u8 cmd;
};
-static struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
+static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
{ 160, 136, 0xa },
{ 176, 144, 0x4 },
{ 320, 240, 0x5 } };
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 036c485d1d1e..8af665bbe330 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -211,7 +211,7 @@ static struct ov51x_decomp_ops *ov518_mmx_decomp_ops;
/* Number of times to retry a failed I2C transaction. Increase this if you
* are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 5;
+static const int i2c_detect_tries = 5;
/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
#if defined(__i386__) || defined(__x86_64__)
@@ -4774,6 +4774,7 @@ static struct file_operations ov511_fops = {
.read = ov51x_v4l1_read,
.mmap = ov51x_v4l1_mmap,
.ioctl = ov51x_v4l1_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -6008,7 +6009,6 @@ ov51x_disconnect(struct usb_interface *intf)
}
static struct usb_driver ov511_driver = {
- .owner = THIS_MODULE,
.name = "ov511",
.id_table = device_table,
.probe = ov51x_probe,
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 53099190952c..359c4b2df735 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -109,7 +109,7 @@
#define PT_RESET_CONTROL_FORMATTER 0x02
#define PT_STATUS_FORMATTER 0x03
-static char *size2name[PSZ_MAX] =
+static const char *size2name[PSZ_MAX] =
{
"subQCIF",
"QSIF",
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 5524fd70210b..4f9b0dc6fd7b 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -111,7 +111,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
static void usb_pwc_disconnect(struct usb_interface *intf);
static struct usb_driver pwc_driver = {
- .owner = THIS_MODULE,
.name = "Philips webcam", /* name */
.id_table = pwc_device_table,
.probe = usb_pwc_probe, /* probe() */
@@ -155,6 +154,7 @@ static struct file_operations pwc_fops = {
.poll = pwc_video_poll,
.mmap = pwc_video_mmap,
.ioctl = pwc_video_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device pwc_template = {
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index f69e443cd1bc..2ba562285fda 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1193,6 +1193,7 @@ static struct file_operations se401_fops = {
.read = se401_read,
.mmap = se401_mmap,
.ioctl = se401_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device se401_template = {
@@ -1401,7 +1402,6 @@ static void se401_disconnect(struct usb_interface *intf)
}
static struct usb_driver se401_driver = {
- .owner = THIS_MODULE,
.name = "se401",
.id_table = device_table,
.probe = se401_probe,
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index b2e66e3b90aa..8d1a1c357d5a 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -1316,7 +1316,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
struct v4l2_control ctrl;
struct v4l2_queryctrl *qctrl;
struct v4l2_rect* rect;
- u8 i = 0, n = 0;
+ u8 i = 0;
int err = 0;
if (!(cam->state & DEV_INITIALIZED)) {
@@ -1352,7 +1352,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
return err;
if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
- DBG(3, "Compressed video format is active, quality %d",
+ DBG(3, "Compressed video format is active, quality %d",
cam->compression.quality)
else
DBG(3, "Uncompressed video format is active")
@@ -1364,9 +1364,8 @@ static int sn9c102_init(struct sn9c102_device* cam)
}
if (s->set_ctrl) {
- n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
- for (i = 0; i < n; i++)
- if (s->qctrl[i].id != 0 &&
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+ if (s->qctrl[i].id != 0 &&
!(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
ctrl.id = s->qctrl[i].id;
ctrl.value = qctrl[i].default_value;
@@ -1388,7 +1387,7 @@ static int sn9c102_init(struct sn9c102_device* cam)
init_waitqueue_head(&cam->wait_stream);
cam->nreadbuffers = 2;
memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
- memcpy(&(s->_rect), &(s->cropcap.defrect),
+ memcpy(&(s->_rect), &(s->cropcap.defrect),
sizeof(struct v4l2_rect));
cam->state |= DEV_INITIALIZED;
}
@@ -1810,13 +1809,12 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
{
struct sn9c102_sensor* s = cam->sensor;
struct v4l2_queryctrl qc;
- u8 i, n;
+ u8 i;
if (copy_from_user(&qc, arg, sizeof(qc)))
return -EFAULT;
- n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
- for (i = 0; i < n; i++)
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
if (qc.id && qc.id == s->qctrl[i].id) {
memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
if (copy_to_user(arg, &qc, sizeof(qc)))
@@ -1852,7 +1850,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
{
struct sn9c102_sensor* s = cam->sensor;
struct v4l2_control ctrl;
- u8 i, n;
+ u8 i;
int err = 0;
if (!s->set_ctrl)
@@ -1861,8 +1859,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
return -EFAULT;
- n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);
- for (i = 0; i < n; i++)
+ for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
if (ctrl.id == s->qctrl[i].id) {
if (ctrl.value < s->qctrl[i].minimum ||
ctrl.value > s->qctrl[i].maximum)
@@ -2544,7 +2541,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
unsigned int i, n;
int err = 0, r;
- n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]);
+ n = ARRAY_SIZE(sn9c102_id_table);
for (i = 0; i < n-1; i++)
if (le16_to_cpu(udev->descriptor.idVendor) ==
sn9c102_id_table[i].idVendor &&
@@ -2711,7 +2708,6 @@ static void sn9c102_usb_disconnect(struct usb_interface* intf)
static struct usb_driver sn9c102_usb_driver = {
- .owner = THIS_MODULE,
.name = "sn9c102",
.id_table = sn9c102_id_table,
.probe = sn9c102_usb_probe,
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 0fd0fa9fec21..b497a6a0a206 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1343,6 +1343,7 @@ static struct file_operations stv680_fops = {
.read = stv680_read,
.mmap = stv680_mmap,
.ioctl = stv680_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device stv680_template = {
@@ -1477,7 +1478,6 @@ static void stv680_disconnect (struct usb_interface *intf)
}
static struct usb_driver stv680_driver = {
- .owner = THIS_MODULE,
.name = "stv680",
.probe = stv680_probe,
.disconnect = stv680_disconnect,
diff --git a/drivers/usb/media/stv680.h b/drivers/usb/media/stv680.h
index 445940612603..b0551cdb280b 100644
--- a/drivers/usb/media/stv680.h
+++ b/drivers/usb/media/stv680.h
@@ -151,7 +151,7 @@ struct usb_stv {
};
-static unsigned char red[256] = {
+static const unsigned char red[256] = {
0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 25, 30, 35, 38, 42,
44, 47, 50, 53, 54, 57, 59, 61, 63, 65, 67, 69,
@@ -176,7 +176,7 @@ static unsigned char red[256] = {
220, 220, 221, 221
};
-static unsigned char green[256] = {
+static const unsigned char green[256] = {
0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
21, 21, 21, 21, 21, 21, 21, 28, 34, 39, 43, 47,
50, 53, 56, 59, 61, 64, 66, 68, 71, 73, 75, 77,
@@ -201,7 +201,7 @@ static unsigned char green[256] = {
245, 245, 246, 246
};
-static unsigned char blue[256] = {
+static const unsigned char blue[256] = {
0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 30, 37, 42, 47, 51,
55, 58, 61, 64, 67, 70, 72, 74, 78, 80, 82, 84,
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index 24efb21969c6..63a72e550a1b 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -725,7 +725,7 @@ int usbvideo_register(
/* Allocate user_data separately because of kmalloc's limits */
if (num_extra > 0) {
up->user_size = num_cams * num_extra;
- up->user_data = (char *) kmalloc(up->user_size, GFP_KERNEL);
+ up->user_data = kmalloc(up->user_size, GFP_KERNEL);
if (up->user_data == NULL) {
err("%s: Failed to allocate user_data (%d. bytes)",
__FUNCTION__, up->user_size);
@@ -953,9 +953,10 @@ static struct file_operations usbvideo_fops = {
.read = usbvideo_v4l_read,
.mmap = usbvideo_v4l_mmap,
.ioctl = usbvideo_v4l_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
-static struct video_device usbvideo_template = {
+static const struct video_device usbvideo_template = {
.owner = THIS_MODULE,
.type = VID_TYPE_CAPTURE,
.hardware = VID_HARDWARE_CPIA,
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 0bc0b1247a6b..5df144073871 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1236,6 +1236,7 @@ static struct file_operations vicam_fops = {
.read = vicam_read,
.mmap = vicam_mmap,
.ioctl = vicam_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
@@ -1257,7 +1258,6 @@ static struct usb_device_id vicam_table[] = {
MODULE_DEVICE_TABLE(usb, vicam_table);
static struct usb_driver vicam_driver = {
- .owner = THIS_MODULE,
.name = "vicam",
.probe = vicam_probe,
.disconnect = vicam_disconnect,
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 67612c81cb9f..bff9434c8e55 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -1533,12 +1533,12 @@ static int w9968cf_i2c_attach_inform(struct i2c_client* client)
}
} else {
DBG(4, "Rejected client [%s] with driver [%s]",
- client->name, client->driver->name)
+ client->name, client->driver->driver.name)
return -EINVAL;
}
DBG(5, "I2C attach client [%s] with driver [%s]",
- client->name, client->driver->name)
+ client->name, client->driver->driver.name)
return 0;
}
@@ -2958,7 +2958,7 @@ static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
};
#define V4L1_IOCTL(cmd) \
- ((_IOC_NR((cmd)) < sizeof(v4l1_ioctls)/sizeof(char*)) ? \
+ ((_IOC_NR((cmd)) < ARRAY_SIZE(v4l1_ioctls)) ? \
v4l1_ioctls[_IOC_NR((cmd))] : "?")
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
@@ -3490,6 +3490,7 @@ static struct file_operations w9968cf_fops = {
.release = w9968cf_release,
.read = w9968cf_read,
.ioctl = w9968cf_ioctl,
+ .compat_ioctl = v4l_compat_ioctl32,
.mmap = w9968cf_mmap,
.llseek = no_llseek,
};
@@ -3554,7 +3555,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
/* Allocate 2 bytes of memory for camera control USB transfers */
- if (!(cam->control_buffer = (u16*)kmalloc(2, GFP_KERNEL))) {
+ if (!(cam->control_buffer = kmalloc(2, GFP_KERNEL))) {
DBG(1,"Couldn't allocate memory for camera control transfers")
err = -ENOMEM;
goto fail;
@@ -3562,7 +3563,7 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
memset(cam->control_buffer, 0, 2);
/* Allocate 8 bytes of memory for USB data transfers to the FSB */
- if (!(cam->data_buffer = (u16*)kmalloc(8, GFP_KERNEL))) {
+ if (!(cam->data_buffer = kmalloc(8, GFP_KERNEL))) {
DBG(1, "Couldn't allocate memory for data "
"transfers to the FSB")
err = -ENOMEM;
@@ -3668,7 +3669,6 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
static struct usb_driver w9968cf_usb_driver = {
- .owner = THIS_MODULE,
.name = "w9968cf",
.id_table = winbond_id_table,
.probe = w9968cf_usb_probe,
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index b293db3c28c3..449b2501acf3 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -767,7 +767,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned
memset (bep, 0, sizeof (auerbuf_t));
bep->list = bcp;
INIT_LIST_HEAD (&bep->buff_list);
- bep->bufp = (char *) kmalloc (bufsize, GFP_KERNEL);
+ bep->bufp = kmalloc (bufsize, GFP_KERNEL);
if (!bep->bufp)
goto bl_fail;
bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
@@ -1123,7 +1123,7 @@ static int auerswald_int_open (pauerswald_t cp)
}
}
if (!cp->intbufp) {
- cp->intbufp = (char *) kmalloc (irqsize, GFP_KERNEL);
+ cp->intbufp = kmalloc (irqsize, GFP_KERNEL);
if (!cp->intbufp) {
ret = -ENOMEM;
goto intoend;
@@ -2103,7 +2103,6 @@ MODULE_DEVICE_TABLE (usb, auerswald_ids);
/* Standard usb driver struct */
static struct usb_driver auerswald_driver = {
- .owner = THIS_MODULE,
.name = "auerswald",
.probe = auerswald_probe,
.disconnect = auerswald_disconnect,
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index b33044d56a1e..6671317b495f 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -50,7 +50,6 @@ static void cytherm_disconnect(struct usb_interface *interface);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver cytherm_driver = {
- .owner = THIS_MODULE,
.name = "cytherm",
.probe = cytherm_probe,
.disconnect = cytherm_disconnect,
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index c8155209bf4b..3824df33094e 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -227,7 +227,6 @@ static void emi26_disconnect(struct usb_interface *intf)
}
static struct usb_driver emi26_driver = {
- .owner = THIS_MODULE,
.name = "emi26 - firmware loader",
.probe = emi26_probe,
.disconnect = emi26_disconnect,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 189986af2ac7..52fea2e08db8 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -266,7 +266,6 @@ static void emi62_disconnect(struct usb_interface *intf)
}
static struct usb_driver emi62_driver = {
- .owner = THIS_MODULE,
.name = "emi62 - firmware loader",
.probe = emi62_probe,
.disconnect = emi62_disconnect,
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 1dc3e0f73014..d8cde1017985 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -114,7 +114,6 @@ static struct usb_class_driver idmouse_class = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver idmouse_driver = {
- .owner = THIS_MODULE,
.name = DRIVER_SHORT,
.probe = idmouse_probe,
.disconnect = idmouse_disconnect,
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7e93ac96490f..981d8a5fbfd9 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -763,7 +763,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver ld_usb_driver = {
- .owner = THIS_MODULE,
.name = "ldusb",
.probe = ld_usb_probe,
.disconnect = ld_usb_disconnect,
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 2703e205bc8f..1336745b8f55 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -282,7 +282,6 @@ static struct usb_class_driver tower_class = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver tower_driver = {
- .owner = THIS_MODULE,
.name = "legousbtower",
.probe = tower_probe,
.disconnect = tower_disconnect,
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 067a81486921..605a3c87e05c 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -555,7 +555,6 @@ static void interfacekit_disconnect(struct usb_interface *interface)
}
static struct usb_driver interfacekit_driver = {
- .owner = THIS_MODULE,
.name = "phidgetkit",
.probe = interfacekit_probe,
.disconnect = interfacekit_disconnect,
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index a30d4a6ee824..b3418d2bcc69 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -306,7 +306,6 @@ servo_disconnect(struct usb_interface *interface)
}
static struct usb_driver servo_driver = {
- .owner = THIS_MODULE,
.name = "phidgetservo",
.probe = servo_probe,
.disconnect = servo_disconnect,
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index 9590dbac5d9a..384fa3769805 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -465,14 +465,14 @@ static int probe_rio(struct usb_interface *intf,
rio->rio_dev = dev;
- if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+ if (!(rio->obuf = kmalloc(OBUF_SIZE, GFP_KERNEL))) {
err("probe_rio: Not enough memory for the output buffer");
usb_deregister_dev(intf, &usb_rio_class);
return -ENOMEM;
}
dbg("probe_rio: obuf address:%p", rio->obuf);
- if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+ if (!(rio->ibuf = kmalloc(IBUF_SIZE, GFP_KERNEL))) {
err("probe_rio: Not enough memory for the input buffer");
usb_deregister_dev(intf, &usb_rio_class);
kfree(rio->obuf);
@@ -522,7 +522,6 @@ static struct usb_device_id rio_table [] = {
MODULE_DEVICE_TABLE (usb, rio_table);
static struct usb_driver rio_driver = {
- .owner = THIS_MODULE,
.name = "rio500",
.probe = probe_rio,
.disconnect = disconnect_rio,
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 41ef2b606751..3260d595441f 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -863,9 +863,6 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
switch (length) {
- case 0:
- return ret;
-
case 1:
if (userbuffer) {
if (get_user(swap8, (u8 __user *)userbuffer))
@@ -1221,9 +1218,6 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
switch (length) {
- case 0:
- return ret;
-
case 1:
ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
@@ -2443,8 +2437,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init)
u8 *tempbuf;
u16 *tempbufb;
size_t written;
- static char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
- static char bootlogo[] = "(o_ //\\ V_/_";
+ static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer.";
+ static const char bootlogo[] = "(o_ //\\ V_/_";
/* sisusb->lock is down */
@@ -3489,7 +3483,6 @@ static struct usb_device_id sisusb_table [] = {
MODULE_DEVICE_TABLE (usb, sisusb_table);
static struct usb_driver sisusb_driver = {
- .owner = THIS_MODULE,
.name = "sisusb",
.probe = sisusb_probe,
.disconnect = sisusb_disconnect,
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 85f3725334b0..cc3dae3f34e0 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -371,7 +371,6 @@ static void lcd_disconnect(struct usb_interface *interface)
}
static struct usb_driver lcd_driver = {
- .owner = THIS_MODULE,
.name = "usblcd",
.probe = lcd_probe,
.disconnect = lcd_disconnect,
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index 3c93921cb6b3..877b081a3a6e 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -148,7 +148,6 @@ static void led_disconnect(struct usb_interface *interface)
}
static struct usb_driver led_driver = {
- .owner = THIS_MODULE,
.name = "usbled",
.probe = led_probe,
.disconnect = led_disconnect,
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 605a2afe34ed..84fa1728f052 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2134,7 +2134,6 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver usbtest_driver = {
- .owner = THIS_MODULE,
.name = "usbtest",
.id_table = id_table,
.probe = usbtest_probe,
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 1cabe7ed91f5..4081990b7d1a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -780,7 +780,6 @@ MODULE_DEVICE_TABLE (usb, uss720_table);
static struct usb_driver uss720_driver = {
- .owner = THIS_MODULE,
.name = "uss720",
.probe = uss720_probe,
.disconnect = uss720_disconnect,
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 17d0190ef64e..611612146ae9 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -97,19 +97,12 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
if (len >= DATA_MAX)
len = DATA_MAX;
- /*
- * Bulk is easy to shortcut reliably.
- * XXX Other pipe types need consideration. Currently, we overdo it
- * and collect garbage for them: better more than less.
- */
- if (usb_pipebulk(pipe) || usb_pipecontrol(pipe)) {
- if (usb_pipein(pipe)) {
- if (ev_type == 'S')
- return '<';
- } else {
- if (ev_type == 'C')
- return '>';
- }
+ if (usb_pipein(pipe)) {
+ if (ev_type == 'S')
+ return '<';
+ } else {
+ if (ev_type == 'C')
+ return '>';
}
/*
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 542120ef1fd2..541181695040 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -912,13 +912,16 @@ static const struct usb_device_id products [] = {
// ASIX AX88772 10/100
USB_DEVICE (0x0b95, 0x7720),
.driver_info = (unsigned long) &ax88772_info,
+}, {
+ // Linksys USB200M Rev 2
+ USB_DEVICE (0x13b1, 0x0018),
+ .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,
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index 37ef365a2472..be5f5e142dd0 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -934,7 +934,6 @@ static struct usb_device_id catc_id_table [] = {
MODULE_DEVICE_TABLE(usb, catc_id_table);
static struct usb_driver catc_driver = {
- .owner = THIS_MODULE,
.name = driver_name,
.probe = catc_probe,
.disconnect = catc_disconnect,
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index c008c981862b..63f1f3ba8e0b 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -476,7 +476,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver cdc_driver = {
- .owner = THIS_MODULE,
.name = "cdc_ether",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c
index f05cfb83c82d..ec801e8bb1bb 100644
--- a/drivers/usb/net/cdc_subset.c
+++ b/drivers/usb/net/cdc_subset.c
@@ -306,7 +306,6 @@ MODULE_DEVICE_TABLE(usb, products);
/*-------------------------------------------------------------------------*/
static struct usb_driver cdc_subset_driver = {
- .owner = THIS_MODULE,
.name = "cdc_subset",
.probe = usbnet_probe,
.suspend = usbnet_suspend,
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index 2455e9a85674..faf1e86be687 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -377,7 +377,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver gl620a_driver = {
- .owner = THIS_MODULE,
.name = "gl620a",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index b5776518020f..def3bb8e2290 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -175,7 +175,6 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table);
* kaweth_driver
****************************************************************/
static struct usb_driver kaweth_driver = {
- .owner = THIS_MODULE,
.name = driver_name,
.probe = kaweth_probe,
.disconnect = kaweth_disconnect,
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index b3799b1a2b0d..78e6a43b1087 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -593,7 +593,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver net1080_driver = {
- .owner = THIS_MODULE,
.name = "net1080",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 683e3df5d607..156a2f1cb39a 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -45,7 +45,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.6.12 (2005/01/13)"
+#define DRIVER_VERSION "v0.6.13 (2005/11/13)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
@@ -57,12 +57,14 @@ static const char driver_name[] = "pegasus";
static int loopback = 0;
static int mii_mode = 0;
+static char *devid=NULL;
static struct usb_eth_dev usb_dev_id[] = {
#define PEGASUS_DEV(pn, vid, pid, flags) \
{.name = pn, .vendor = vid, .device = pid, .private = flags},
#include "pegasus.h"
#undef PEGASUS_DEV
+ {NULL, 0, 0, 0},
{NULL, 0, 0, 0}
};
@@ -71,6 +73,7 @@ static struct usb_device_id pegasus_ids[] = {
{.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid},
#include "pegasus.h"
#undef PEGASUS_DEV
+ {},
{}
};
@@ -79,8 +82,10 @@ MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_param(loopback, bool, 0);
module_param(mii_mode, bool, 0);
+module_param(devid, charp, 0);
MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
+MODULE_PARM_DESC(devid, "The format is: 'DEV_name:VendorID:DeviceID:Flags'");
/* use ethtool to change the level for any given device */
static int msg_level = -1;
@@ -113,7 +118,7 @@ static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
break;
default:
if (netif_msg_drv(pegasus))
- dev_err(&pegasus->intf->dev, "%s, status %d\n",
+ dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
__FUNCTION__, urb->status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
@@ -308,9 +313,9 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
__le16 regdi;
int ret;
- ret = set_register(pegasus, PhyCtrl, 0);
- ret = set_registers(pegasus, PhyAddr, sizeof (data), data);
- ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ));
+ set_register(pegasus, PhyCtrl, 0);
+ set_registers(pegasus, PhyAddr, sizeof (data), data);
+ set_register(pegasus, PhyCtrl, (indx | PHY_READ));
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
@@ -319,12 +324,12 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
if (i < REG_TIMEOUT) {
ret = get_registers(pegasus, PhyData, 2, &regdi);
*regd = le16_to_cpu(regdi);
- return 1;
+ return ret;
}
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
- return 0;
+ return ret;
}
static int mdio_read(struct net_device *dev, int phy_id, int loc)
@@ -344,20 +349,20 @@ static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
data[1] = (u8) regd;
data[2] = (u8) (regd >> 8);
- ret = set_register(pegasus, PhyCtrl, 0);
- ret = set_registers(pegasus, PhyAddr, sizeof(data), data);
- ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
+ set_register(pegasus, PhyCtrl, 0);
+ set_registers(pegasus, PhyAddr, sizeof(data), data);
+ set_register(pegasus, PhyCtrl, (indx | PHY_WRITE));
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, PhyCtrl, 1, data);
if (data[0] & PHY_DONE)
break;
}
if (i < REG_TIMEOUT)
- return 0;
+ return ret;
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
- return 1;
+ return -ETIMEDOUT;
}
static void mdio_write(struct net_device *dev, int phy_id, int loc, int val)
@@ -374,9 +379,9 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
__le16 retdatai;
int ret;
- ret = set_register(pegasus, EpromCtrl, 0);
- ret = set_register(pegasus, EpromOffset, index);
- ret = set_register(pegasus, EpromCtrl, EPROM_READ);
+ set_register(pegasus, EpromCtrl, 0);
+ set_register(pegasus, EpromOffset, index);
+ set_register(pegasus, EpromCtrl, EPROM_READ);
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -386,12 +391,12 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
if (i < REG_TIMEOUT) {
ret = get_registers(pegasus, EpromData, 2, &retdatai);
*retdata = le16_to_cpu(retdatai);
- return 0;
+ return ret;
}
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
- return -1;
+ return -ETIMEDOUT;
}
#ifdef PEGASUS_WRITE_EEPROM
@@ -400,8 +405,8 @@ static inline void enable_eprom_write(pegasus_t * pegasus)
__u8 tmp;
int ret;
- ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
- ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
+ get_registers(pegasus, EthCtrl2, 1, &tmp);
+ set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE);
}
static inline void disable_eprom_write(pegasus_t * pegasus)
@@ -409,9 +414,9 @@ static inline void disable_eprom_write(pegasus_t * pegasus)
__u8 tmp;
int ret;
- ret = get_registers(pegasus, EthCtrl2, 1, &tmp);
- ret = set_register(pegasus, EpromCtrl, 0);
- ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
+ get_registers(pegasus, EthCtrl2, 1, &tmp);
+ set_register(pegasus, EpromCtrl, 0);
+ set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE);
}
static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
@@ -420,11 +425,11 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
__u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE };
int ret;
- ret = set_registers(pegasus, EpromOffset, 4, d);
+ set_registers(pegasus, EpromOffset, 4, d);
enable_eprom_write(pegasus);
- ret = set_register(pegasus, EpromOffset, index);
- ret = set_registers(pegasus, EpromData, 2, &data);
- ret = set_register(pegasus, EpromCtrl, EPROM_WRITE);
+ set_register(pegasus, EpromOffset, index);
+ set_registers(pegasus, EpromData, 2, &data);
+ set_register(pegasus, EpromCtrl, EPROM_WRITE);
for (i = 0; i < REG_TIMEOUT; i++) {
ret = get_registers(pegasus, EpromCtrl, 1, &tmp);
@@ -433,10 +438,10 @@ static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data)
}
disable_eprom_write(pegasus);
if (i < REG_TIMEOUT)
- return 0;
+ return ret;
if (netif_msg_drv(pegasus))
dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__);
- return -1;
+ return -ETIMEDOUT;
}
#endif /* PEGASUS_WRITE_EEPROM */
@@ -454,10 +459,9 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
static void set_ethernet_addr(pegasus_t * pegasus)
{
__u8 node_id[6];
- int ret;
get_node_id(pegasus, node_id);
- ret = set_registers(pegasus, EthID, sizeof (node_id), node_id);
+ set_registers(pegasus, EthID, sizeof (node_id), node_id);
memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id));
}
@@ -465,30 +469,29 @@ static inline int reset_mac(pegasus_t * pegasus)
{
__u8 data = 0x8;
int i;
- int ret;
- ret = set_register(pegasus, EthCtrl1, data);
+ set_register(pegasus, EthCtrl1, data);
for (i = 0; i < REG_TIMEOUT; i++) {
- ret = get_registers(pegasus, EthCtrl1, 1, &data);
+ get_registers(pegasus, EthCtrl1, 1, &data);
if (~data & 0x08) {
if (loopback & 1)
break;
if (mii_mode && (pegasus->features & HAS_HOME_PNA))
- ret = set_register(pegasus, Gpio1, 0x34);
+ set_register(pegasus, Gpio1, 0x34);
else
- ret = set_register(pegasus, Gpio1, 0x26);
- ret = set_register(pegasus, Gpio0, pegasus->features);
- ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
+ set_register(pegasus, Gpio1, 0x26);
+ set_register(pegasus, Gpio0, pegasus->features);
+ set_register(pegasus, Gpio0, DEFAULT_GPIO_SET);
break;
}
}
if (i == REG_TIMEOUT)
- return 1;
+ return -ETIMEDOUT;
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS ||
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) {
- ret = set_register(pegasus, Gpio0, 0x24);
- ret = set_register(pegasus, Gpio0, 0x26);
+ set_register(pegasus, Gpio0, 0x24);
+ set_register(pegasus, Gpio0, 0x26);
}
if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) {
__u16 auxmode;
@@ -527,7 +530,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
write_mii_word(pegasus, 0, 0x1b, auxmode | 4);
}
- return 0;
+ return ret;
}
static void fill_skb_pool(pegasus_t * pegasus)
@@ -881,9 +884,8 @@ static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
static inline void disable_net_traffic(pegasus_t * pegasus)
{
int tmp = 0;
- int ret;
- ret = set_registers(pegasus, EthCtrl0, 2, &tmp);
+ set_registers(pegasus, EthCtrl0, 2, &tmp);
}
static inline void get_interrupt_interval(pegasus_t * pegasus)
@@ -1206,18 +1208,17 @@ static __u8 mii_phy_probe(pegasus_t * pegasus)
static inline void setup_pegasus_II(pegasus_t * pegasus)
{
__u8 data = 0xa5;
- int ret;
- ret = set_register(pegasus, Reg1d, 0);
- ret = set_register(pegasus, Reg7b, 1);
+ set_register(pegasus, Reg1d, 0);
+ set_register(pegasus, Reg7b, 1);
mdelay(100);
if ((pegasus->features & HAS_HOME_PNA) && mii_mode)
- ret = set_register(pegasus, Reg7b, 0);
+ set_register(pegasus, Reg7b, 0);
else
- ret = set_register(pegasus, Reg7b, 2);
+ set_register(pegasus, Reg7b, 2);
- ret = set_register(pegasus, 0x83, data);
- ret = get_registers(pegasus, 0x83, 1, &data);
+ set_register(pegasus, 0x83, data);
+ get_registers(pegasus, 0x83, 1, &data);
if (data == 0xa5) {
pegasus->chip = 0x8513;
@@ -1225,14 +1226,14 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
pegasus->chip = 0;
}
- ret = set_register(pegasus, 0x80, 0xc0);
- ret = set_register(pegasus, 0x83, 0xff);
- ret = set_register(pegasus, 0x84, 0x01);
+ set_register(pegasus, 0x80, 0xc0);
+ set_register(pegasus, 0x83, 0xff);
+ set_register(pegasus, 0x84, 0x01);
if (pegasus->features & HAS_HOME_PNA && mii_mode)
- ret = set_register(pegasus, Reg81, 6);
+ set_register(pegasus, Reg81, 6);
else
- ret = set_register(pegasus, Reg81, 2);
+ set_register(pegasus, Reg81, 2);
}
@@ -1414,9 +1415,42 @@ static struct usb_driver pegasus_driver = {
.resume = pegasus_resume,
};
+static void parse_id(char *id)
+{
+ unsigned int vendor_id=0, device_id=0, flags=0, i=0;
+ char *token, *name=NULL;
+
+ if ((token = strsep(&id, ":")) != NULL)
+ name = token;
+ /* name now points to a null terminated string*/
+ if ((token = strsep(&id, ":")) != NULL)
+ vendor_id = simple_strtoul(token, NULL, 16);
+ if ((token = strsep(&id, ":")) != NULL)
+ device_id = simple_strtoul(token, NULL, 16);
+ flags = simple_strtoul(id, NULL, 16);
+ pr_info("%s: new device %s, vendor ID 0x%04x, device ID 0x%04x, flags: 0x%x\n",
+ driver_name, name, vendor_id, device_id, flags);
+
+ if (vendor_id > 0x10000 || vendor_id == 0)
+ return;
+ if (device_id > 0x10000 || device_id == 0)
+ return;
+
+ for (i=0; usb_dev_id[i].name; i++);
+ usb_dev_id[i].name = name;
+ usb_dev_id[i].vendor = vendor_id;
+ usb_dev_id[i].device = device_id;
+ usb_dev_id[i].private = flags;
+ pegasus_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ pegasus_ids[i].idVendor = vendor_id;
+ pegasus_ids[i].idProduct = device_id;
+}
+
static int __init pegasus_init(void)
{
pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
+ if (devid)
+ parse_id(devid);
pegasus_workqueue = create_singlethread_workqueue("pegasus");
if (!pegasus_workqueue)
return -ENOMEM;
diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c
index 89856aa0e3b8..4fe863389cb7 100644
--- a/drivers/usb/net/plusb.c
+++ b/drivers/usb/net/plusb.c
@@ -127,7 +127,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver plusb_driver = {
- .owner = THIS_MODULE,
.name = "plusb",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index c0ecbab6f6ba..49991ac1bf3b 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -586,7 +586,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver rndis_driver = {
- .owner = THIS_MODULE,
.name = "rndis_host",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 787dd3591d6a..8ca52be23976 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -177,7 +177,6 @@ static int rtl8150_probe(struct usb_interface *intf,
static const char driver_name [] = "rtl8150";
static struct usb_driver rtl8150_driver = {
- .owner = THIS_MODULE,
.name = driver_name,
.probe = rtl8150_probe,
.disconnect = rtl8150_disconnect,
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index 680d13957af4..9c5ab251370c 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -357,7 +357,6 @@ static const struct usb_device_id products [] = {
MODULE_DEVICE_TABLE(usb, products);
static struct usb_driver zaurus_driver = {
- .owner = THIS_MODULE,
.name = "zaurus",
.id_table = products,
.probe = usbnet_probe,
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
index 2f52261c7cc1..f3a8e2807c3b 100644
--- a/drivers/usb/net/zd1201.c
+++ b/drivers/usb/net/zd1201.c
@@ -1722,7 +1722,7 @@ static const struct iw_priv_args zd1201_private_args[] = {
IW_PRIV_TYPE_NONE, "sethostauth" },
{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
- { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
+ { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
IW_PRIV_TYPE_NONE, "authstation" },
{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
IW_PRIV_TYPE_NONE, "setmaxassoc" },
@@ -1731,9 +1731,9 @@ static const struct iw_priv_args zd1201_private_args[] = {
};
static const struct iw_handler_def zd1201_iw_handlers = {
- .num_standard = sizeof(zd1201_iw_handler)/sizeof(iw_handler),
- .num_private = sizeof(zd1201_private_handler)/sizeof(iw_handler),
- .num_private_args = sizeof(zd1201_private_args)/sizeof(struct iw_priv_args),
+ .num_standard = ARRAY_SIZE(zd1201_iw_handler),
+ .num_private = ARRAY_SIZE(zd1201_private_handler),
+ .num_private_args = ARRAY_SIZE(zd1201_private_args),
.standard = (iw_handler *)zd1201_iw_handler,
.private = (iw_handler *)zd1201_private_handler,
.private_args = (struct iw_priv_args *) zd1201_private_args,
@@ -1829,6 +1829,8 @@ static int zd1201_probe(struct usb_interface *interface,
if (err)
goto err_net;
+ SET_NETDEV_DEV(zd->dev, &usb->dev);
+
err = register_netdev(zd->dev);
if (err)
goto err_net;
@@ -1923,7 +1925,6 @@ static int zd1201_resume(struct usb_interface *interface)
#endif
static struct usb_driver zd1201_usb = {
- .owner = THIS_MODULE,
.name = "zd1201",
.probe = zd1201_probe,
.disconnect = zd1201_disconnect,
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 14f55fd26a64..be5dc80836c3 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -84,7 +84,7 @@ config USB_SERIAL_BELKIN
config USB_SERIAL_WHITEHEAT
tristate "USB ConnectTech WhiteHEAT Serial Driver"
- depends on USB_SERIAL && BROKEN_ON_SMP
+ depends on USB_SERIAL
help
Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
USB to serial converter device.
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 1f29d8837327..dbf1f063098c 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -23,11 +23,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver airprime_driver = {
- .owner = THIS_MODULE,
.name = "airprime",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver airprime_device = {
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
index 18022a74a3dc..343f6f228220 100644
--- a/drivers/usb/serial/anydata.c
+++ b/drivers/usb/serial/anydata.c
@@ -27,11 +27,11 @@ static int buffer_size;
static int debug;
static struct usb_driver anydata_driver = {
- .owner = THIS_MODULE,
.name = "anydata",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static int anydata_open(struct usb_serial_port *port, struct file *filp)
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 84bc0ee4f061..4144777ea18b 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -113,11 +113,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver belkin_driver = {
- .owner = THIS_MODULE,
.name = "belkin",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
/* All of the device info needed for the serial converters */
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 664139afcfa9..e9f9f4bafa17 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr
return 0;
}
-struct bus_type usb_serial_bus_type = {
- .name = "usb-serial",
- .match = usb_serial_device_match,
-};
-
static int usb_serial_device_probe (struct device *dev)
{
struct usb_serial_driver *driver;
@@ -109,14 +104,18 @@ exit:
return retval;
}
+struct bus_type usb_serial_bus_type = {
+ .name = "usb-serial",
+ .match = usb_serial_device_match,
+ .probe = usb_serial_device_probe,
+ .remove = usb_serial_device_remove,
+};
+
int usb_serial_bus_register(struct usb_serial_driver *driver)
{
int retval;
driver->driver.bus = &usb_serial_bus_type;
- driver->driver.probe = usb_serial_device_probe;
- driver->driver.remove = usb_serial_device_remove;
-
retval = driver_register(&driver->driver);
return retval;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index c9787001cf2a..da46b351e188 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -67,11 +67,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver cp2101_driver = {
- .owner = THIS_MODULE,
.name = "cp2101",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver cp2101_device = {
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index e581e4ae8483..2357b1d102d7 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -76,11 +76,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver cyberjack_driver = {
- .owner = THIS_MODULE,
.name = "cyberjack",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver cyberjack_device = {
@@ -364,7 +364,6 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
short todo;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -381,14 +380,8 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index af9290ed257b..68067fe117a4 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -112,6 +112,7 @@ static struct usb_driver cypress_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
struct cypress_private {
@@ -356,7 +357,7 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
} while (retval != 5 && retval != ENODEV);
if (retval != 5) {
- err("%s - failed to retreive serial line settings - %d", __FUNCTION__, retval);
+ err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
return retval;
} else {
spin_lock_irqsave(&priv->lock, flags);
@@ -1262,12 +1263,10 @@ 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)) {
+ bytes = tty_buffer_request_room(tty, bytes);
for (; i < bytes ; ++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);
- }
tty_insert_flip_char(tty, data[i], tty_flag);
}
tty_flip_buffer_push(port->tty);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index dc74644a603d..b3f776a90c93 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -493,11 +493,11 @@ static struct usb_device_id id_table_4 [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver digi_driver = {
- .owner = THIS_MODULE,
.name = "digi_acceleport",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
@@ -946,13 +946,10 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
spin_lock_irqsave( &priv->dp_port_lock, flags );
/* send any buffered chars from throttle time on to tty subsystem */
- len = min(priv->dp_in_buf_len, TTY_FLIPBUF_SIZE - tty->flip.count );
+
+ len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
if( len > 0 ) {
- memcpy( tty->flip.char_buf_ptr, priv->dp_in_buf, len );
- memcpy( tty->flip.flag_buf_ptr, priv->dp_in_flag_buf, len );
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty->flip.count += len;
+ tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
tty_flip_buffer_push( tty );
}
@@ -1827,6 +1824,7 @@ static int digi_read_inb_callback( struct urb *urb )
int status = ((unsigned char *)urb->transfer_buffer)[2];
unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
int flag,throttled;
+ int i;
/* do not process callbacks on closed ports */
/* but do continue the read chain */
@@ -1885,20 +1883,18 @@ static int digi_read_inb_callback( struct urb *urb )
}
} else {
-
- len = min( len, TTY_FLIPBUF_SIZE - tty->flip.count );
-
+ len = tty_buffer_request_room(tty, len);
if( len > 0 ) {
- memcpy( tty->flip.char_buf_ptr, data, len );
- memset( tty->flip.flag_buf_ptr, flag, len );
- tty->flip.char_buf_ptr += len;
- tty->flip.flag_buf_ptr += len;
- tty->flip.count += len;
+ /* Hot path */
+ if(flag == TTY_NORMAL)
+ tty_insert_flip_string(tty, data, len);
+ else {
+ for(i = 0; i < len; i++)
+ tty_insert_flip_char(tty, data[i], flag);
+ }
tty_flip_buffer_push( tty );
}
-
}
-
}
spin_unlock( &priv->dp_port_lock );
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 0b0546dcc7b9..63f7c78a1152 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -105,11 +105,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver empeg_driver = {
- .owner = THIS_MODULE,
.name = "empeg",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver empeg_device = {
@@ -344,7 +344,6 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -359,19 +358,8 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* gb - 2000/11/13
- * If we insert too many characters we'll overflow the buffer.
- * This means we'll lose bytes - Decidedly bad.
- */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- tty_insert_flip_char(tty, data[i], 0);
- }
- /* gb - 2000/11/13
- * Goes straight through instead of scheduling - if tty->low_latency is set.
- */
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 06e04b442ff1..10bc1bf23b35 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -471,12 +471,15 @@ static struct usb_device_id id_table_combined [] = {
{ 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(FTDI_VID, FTDI_TERATRONIK_VCP_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_TERATRONIK_D2XX_PID) },
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
{ USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
+ { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -488,9 +491,10 @@ static struct usb_driver ftdi_driver = {
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
-static char *ftdi_chip_name[] = {
+static const char *ftdi_chip_name[] = {
[SIO] = "SIO", /* the serial part of FT8U100AX */
[FT8U232AM] = "FT8U232AM",
[FT232BM] = "FT232BM",
@@ -1606,24 +1610,11 @@ static void ftdi_process_read (void *param)
length = 0;
}
- /* have to make sure we don't overflow the buffer
- with tty_insert_flip_char's */
- if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- need_flip = 0;
-
- if (tty->flip.count != 0) {
- /* flip didn't work, this happens when ftdi_process_read() is
- * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
- dbg("%s - flip buffer push failed", __FUNCTION__);
- break;
- }
- }
if (priv->rx_flags & THROTTLED) {
dbg("%s - throttled", __FUNCTION__);
break;
}
- if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+ if (tty_buffer_request_room(tty, length) < length) {
/* break out & wait for throttling/unthrottling to happen */
dbg("%s - receive room low", __FUNCTION__);
break;
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 773ea3eca086..00d45f8600de 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -343,6 +343,13 @@
#define XSENS_CONVERTER_7_PID 0xD38F
/*
+ * Teratronik product ids.
+ * Submitted by O. Wölfelschneider.
+ */
+#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */
+#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */
+
+/*
* Evolution Robotics products (http://www.evolution.com/).
* Submitted by Shawn M. Lavelle.
*/
@@ -352,6 +359,12 @@
/* Pyramid Computer GmbH */
#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */
+/*
+ * Posiflex inc retail equipment (http://www.posiflex.com.tw)
+ */
+#define POSIFLEX_VID 0x0d3a /* Vendor ID */
+#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */
+
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
@@ -714,7 +727,7 @@ typedef enum {
*/
/* FTDI_SIO_GET_MODEM_STATUS */
-/* Retreive the current value of the modem status register */
+/* Retrieve the current value of the modem status register */
#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 35820bda7ae1..d6f55e9dccae 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -222,11 +222,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver garmin_driver = {
- .owner = THIS_MODULE,
.name = "garmin_gps",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
@@ -275,23 +275,14 @@ static void send_to_tty(struct usb_serial_port *port,
char *data, unsigned int actual_length)
{
struct tty_struct *tty = port->tty;
- int i;
if (tty && actual_length) {
usb_serial_debug_data(debug, &port->dev,
__FUNCTION__, actual_length, data);
- for (i = 0; i < actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless
- tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, actual_length);
+ tty_insert_flip_string(tty, data, actual_length);
tty_flip_buffer_push(tty);
}
}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 53a47c31cd0e..476cda107f4f 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -68,11 +68,11 @@ static int generic_probe(struct usb_interface *interface,
}
static struct usb_driver generic_driver = {
- .owner = THIS_MODULE,
.name = "usbserial_generic",
.probe = generic_probe,
.disconnect = usb_serial_disconnect,
.id_table = generic_serial_ids,
+ .no_dynamic_id = 1,
};
#endif
@@ -254,7 +254,6 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -268,14 +267,8 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/hp4x.c b/drivers/usb/serial/hp4x.c
index 8eadfb705601..e9719da2aca1 100644
--- a/drivers/usb/serial/hp4x.c
+++ b/drivers/usb/serial/hp4x.c
@@ -37,11 +37,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver hp49gp_driver = {
- .owner = THIS_MODULE,
.name = "hp4X",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver hp49gp_device = {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index dc4c498bd1ed..3f29e6b0fd19 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -184,7 +184,7 @@ struct divisor_table_entry {
// These assume a 3.6864MHz crystal, the standard /16, and
// MCR.7 = 0.
//
-static struct divisor_table_entry divisor_table[] = {
+static const struct divisor_table_entry divisor_table[] = {
{ 50, 4608},
{ 75, 3072},
{ 110, 2095}, /* 2094.545455 => 230450 => .0217 % over */
@@ -242,11 +242,11 @@ static void edge_shutdown (struct usb_serial *serial);
#include "io_tables.h" /* all of the devices that this driver supports */
static struct usb_driver io_driver = {
- .owner = THIS_MODULE,
.name = "io_edgeport",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
/* function prototypes for all of our local functions */
@@ -1965,20 +1965,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
- __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
data += cnt;
length -= cnt;
} while (length > 0);
@@ -2353,7 +2347,7 @@ static int calc_baud_rate_divisor (int baudrate, int *divisor)
dbg("%s - %d", __FUNCTION__, baudrate);
- for (i = 0; i < NUM_ENTRIES(divisor_table); i++) {
+ for (i = 0; i < ARRAY_SIZE(divisor_table); i++) {
if ( divisor_table[i].BaudRate == baudrate ) {
*divisor = divisor_table[i].Divisor;
return 0;
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 5112d7aac055..123fa8a904e6 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -31,9 +31,6 @@
#ifndef HIGH8
#define HIGH8(a) ((unsigned char)((a & 0xff00) >> 8))
#endif
-#ifndef NUM_ENTRIES
- #define NUM_ENTRIES(x) (sizeof(x)/sizeof((x)[0]))
-#endif
#ifndef __KERNEL__
#define __KERNEL__
diff --git a/drivers/usb/serial/io_fw_boot2.h b/drivers/usb/serial/io_fw_boot2.h
index c7c3a3c305fe..e3463de99de4 100644
--- a/drivers/usb/serial/io_fw_boot2.h
+++ b/drivers/usb/serial/io_fw_boot2.h
@@ -537,7 +537,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
};
-static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
+static const struct edge_firmware_version_info IMAGE_VERSION_NAME = {
2, 0, 3 }; // Major, Minor, Build
#undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 832b6d6734c0..afc0f34b3a46 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -216,11 +216,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver io_driver = {
- .owner = THIS_MODULE,
.name = "io_ti",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
@@ -1865,20 +1865,14 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n",
- __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n",
+ __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
data += cnt;
length -= cnt;
} while (length > 0);
@@ -2843,7 +2837,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size)
* Free the buffer and all associated memory.
*/
-void edge_buf_free(struct edge_buf *eb)
+static void edge_buf_free(struct edge_buf *eb)
{
if (eb) {
kfree(eb->buf_buf);
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d5d066488100..9a5c97989562 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -542,11 +542,11 @@ static struct usb_device_id ipaq_id_table [] = {
MODULE_DEVICE_TABLE (usb, ipaq_id_table);
static struct usb_driver ipaq_driver = {
- .owner = THIS_MODULE,
.name = "ipaq",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = ipaq_id_table,
+ .no_dynamic_id = 1,
};
@@ -711,7 +711,7 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int i, result;
+ int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -724,14 +724,8 @@ static void ipaq_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
bytes_in += urb->actual_length;
}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 7744b8148bc5..e760a70242c1 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -152,11 +152,11 @@ static struct usb_device_id usb_ipw_ids[] = {
MODULE_DEVICE_TABLE(usb, usb_ipw_ids);
static struct usb_driver usb_ipw_driver = {
- .owner = THIS_MODULE,
.name = "ipwtty",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = usb_ipw_ids,
+ .no_dynamic_id = 1,
};
static int debug;
@@ -166,7 +166,6 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
- int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -180,14 +179,8 @@ static void ipw_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 19f329e9bdcf..a59010421444 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -125,11 +125,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver ir_driver = {
- .owner = THIS_MODULE,
.name = "ir-usb",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 5cfc13b5e56f..7472ed6bf626 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -520,11 +520,11 @@ static struct usb_device_id keyspan_ids_combined[] = {
MODULE_DEVICE_TABLE(usb, keyspan_ids_combined);
static struct usb_driver keyspan_driver = {
- .owner = THIS_MODULE,
.name = "keyspan",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = keyspan_ids_combined,
+ .no_dynamic_id = 1,
};
/* usb_device_id table for the pre-firmware download keyspan devices */
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index cd4f48bd83b6..b0441c35f98f 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -150,11 +150,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver keyspan_pda_driver = {
- .owner = THIS_MODULE,
.name = "keyspan_pda",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
static struct usb_device_id id_table_std [] = {
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index a8951c0fd020..78335a5f7743 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -116,11 +116,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver kl5kusb105d_driver = {
- .owner = THIS_MODULE,
.name = "kl5kusb105d",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver kl5kusb105d_device = {
@@ -648,7 +648,6 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
urb->actual_length, data);
} else {
- int i;
int bytes_sent = ((__u8 *) data)[0] +
((unsigned int) ((__u8 *) data)[1] << 8);
tty = port->tty;
@@ -669,16 +668,8 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
bytes_sent = urb->actual_length - 2;
}
- for (i = 2; i < 2+bytes_sent; i++) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters,
- * we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless
- * tty->low_latency is set */
- tty_insert_flip_char(tty, ((__u8*) data)[i], 0);
- }
+ tty_buffer_request_room(tty, bytes_sent);
+ tty_insert_flip_string(tty, data + 2, bytes_sent);
tty_flip_buffer_push(tty);
/* again lockless, but debug info only */
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 9456dd9dd136..b8b213185d0f 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -97,11 +97,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver kobil_driver = {
- .owner = THIS_MODULE,
.name = "kobil",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
@@ -365,7 +365,6 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
{
- int i;
int result;
struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
struct tty_struct *tty;
@@ -397,14 +396,8 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
*/
// END DEBUG
- for (i = 0; i < purb->actual_length; ++i) {
- // if we insert more than TTY_FLIPBUF_SIZE characters, we drop them.
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- // this doesn't actually push the data through unless tty->low_latency is set
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, purb->actual_length);
+ tty_insert_flip_string(tty, data, purb->actual_length);
tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index ca5dbadb9b7e..b6d6cab9c859 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -125,11 +125,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver mct_u232_driver = {
- .owner = THIS_MODULE,
.name = "mct_u232",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver mct_u232_device = {
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 3caf97072ac0..762d8ff9a1e4 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -80,11 +80,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver omninet_driver = {
- .owner = THIS_MODULE,
.name = "omninet",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 7716000045b7..52bdf6fe46f2 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -95,11 +95,11 @@ static struct usb_device_id option_ids[] = {
MODULE_DEVICE_TABLE(usb, option_ids);
static struct usb_driver option_driver = {
- .owner = THIS_MODULE,
.name = "option",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = option_ids,
+ .no_dynamic_id = 1,
};
/* The card has three separate interfaces, wich the serial driver
@@ -321,7 +321,7 @@ static int option_write(struct usb_serial_port *port,
static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
{
- int i, err;
+ int err;
int endpoint;
struct usb_serial_port *port;
struct tty_struct *tty;
@@ -338,11 +338,8 @@ static void option_indat_callback(struct urb *urb, struct pt_regs *regs)
} else {
tty = port->tty;
if (urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- tty_flip_buffer_push(tty);
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
} else {
dbg("%s: empty read urb received", __FUNCTION__);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 41a45a5025b2..0eb883f44ada 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -43,8 +43,6 @@ static int debug;
#define PL2303_BUF_SIZE 1024
#define PL2303_TMP_BUF_SIZE 1024
-static DECLARE_MUTEX(pl2303_tmp_buf_sem);
-
struct pl2303_buf {
unsigned int buf_size;
char *buf_buf;
@@ -82,11 +80,11 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver pl2303_driver = {
- .owner = THIS_MODULE,
.name = "pl2303",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
#define SET_LINE_REQUEST_TYPE 0x21
@@ -810,7 +808,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 status_idx = UART_STATE;
- u8 length = UART_STATE;
+ u8 length = UART_STATE + 1;
if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
(le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
@@ -924,16 +922,12 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
+ tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
if (status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-
- for (i = 0; i < urb->actual_length; ++i) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
+ for (i = 0; i < urb->actual_length; ++i)
tty_insert_flip_char (tty, data[i], tty_flag);
- }
tty_flip_buffer_push (tty);
}
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index c22bdc0c4dfd..f0215f850d2d 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -160,14 +160,14 @@ static struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver safe_driver = {
- .owner = THIS_MODULE,
.name = "safe_serial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
+ .no_dynamic_id = 1,
};
-static __u16 crc10_table[256] = {
+static const __u16 crc10_table[256] = {
0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
@@ -425,7 +425,7 @@ static int __init safe_init (void)
if (vendor || product) {
info ("vendor: %x product: %x\n", vendor, product);
- for (i = 0; i < (sizeof (id_table) / sizeof (struct usb_device_id)); i++) {
+ for (i = 0; i < ARRAY_SIZE(id_table); i++) {
if (!id_table[i].idVendor && !id_table[i].idProduct) {
id_table[i].idVendor = vendor;
id_table[i].idProduct = product;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 205dbf7201da..c18db3257073 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -248,11 +248,11 @@ static struct usb_device_id ti_id_table_combined[] = {
};
static struct usb_driver ti_usb_driver = {
- .owner = THIS_MODULE,
.name = "ti_usb_3410_5052",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = ti_id_table_combined,
+ .no_dynamic_id = 1,
};
static struct usb_serial_driver ti_1port_device = {
@@ -351,17 +351,14 @@ static int __init ti_init(void)
int i,j;
int ret;
-
/* insert extra vendor and product ids */
- j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id)
- - TI_EXTRA_VID_PID_COUNT - 1;
+ j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1;
for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
ti_id_table_3410[j].idVendor = vendor_3410[i];
ti_id_table_3410[j].idProduct = product_3410[i];
ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
}
- j = sizeof(ti_id_table_5052)/sizeof(struct usb_device_id)
- - TI_EXTRA_VID_PID_COUNT - 1;
+ j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1;
for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
ti_id_table_5052[j].idVendor = vendor_5052[i];
ti_id_table_5052[j].idProduct = product_5052[i];
@@ -1283,24 +1280,18 @@ static void ti_recv(struct device *dev, struct tty_struct *tty,
int cnt;
do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length);
- return;
- }
+ cnt = tty_buffer_request_room(tty, length);
+ if (cnt < length) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length - cnt);
+ if(cnt == 0)
+ break;
}
- cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
- memcpy(tty->flip.char_buf_ptr, data, cnt);
- memset(tty->flip.flag_buf_ptr, 0, cnt);
- tty->flip.char_buf_ptr += cnt;
- tty->flip.flag_buf_ptr += cnt;
- tty->flip.count += cnt;
+ tty_insert_flip_string(tty, data, cnt);
+ tty_flip_buffer_push(tty);
data += cnt;
length -= cnt;
} while (length > 0);
- tty_flip_buffer_push(tty);
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 0c4881d18cd5..4dd6865d32b0 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -30,6 +30,7 @@
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
+#include <asm/semaphore.h>
#include <linux/usb.h>
#include "usb-serial.h"
#include "pl2303.h"
@@ -42,10 +43,10 @@
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
- .owner = THIS_MODULE,
.name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
+ .no_dynamic_id = 1,
};
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
@@ -188,6 +189,11 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
portNumber = tty->index - serial->minor;
port = serial->port[portNumber];
+ if (!port)
+ return -ENODEV;
+
+ if (down_interruptible(&port->sem))
+ return -ERESTARTSYS;
++port->open_count;
@@ -213,6 +219,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
goto bailout_module_put;
}
+ up(&port->sem);
return 0;
bailout_module_put:
@@ -220,6 +227,7 @@ bailout_module_put:
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
port->open_count = 0;
+ up(&port->sem);
return retval;
}
@@ -232,8 +240,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
+ down(&port->sem);
+
if (port->open_count == 0)
- return;
+ goto out;
--port->open_count;
if (port->open_count == 0) {
@@ -251,6 +261,9 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
}
kref_put(&port->serial->kref, destroy_serial);
+
+out:
+ up(&port->sem);
}
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
@@ -258,6 +271,9 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
+ if (!port)
+ goto exit;
+
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
if (!port->open_count) {
@@ -277,6 +293,9 @@ static int serial_write_room (struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
+ if (!port)
+ goto exit;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -296,6 +315,9 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data;
int retval = -EINVAL;
+ if (!port)
+ goto exit;
+
dbg("%s = port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -314,6 +336,9 @@ static void serial_throttle (struct tty_struct * tty)
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ return;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -330,6 +355,9 @@ static void serial_unthrottle (struct tty_struct * tty)
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ return;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -347,6 +375,9 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
struct usb_serial_port *port = tty->driver_data;
int retval = -ENODEV;
+ if (!port)
+ goto exit;
+
dbg("%s - port %d, cmd 0x%.4x", __FUNCTION__, port->number, cmd);
if (!port->open_count) {
@@ -368,6 +399,9 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ return;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -384,6 +418,9 @@ static void serial_break (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ return;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -445,6 +482,9 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ goto exit;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -464,6 +504,9 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
{
struct usb_serial_port *port = tty->driver_data;
+ if (!port)
+ goto exit;
+
dbg("%s - port %d", __FUNCTION__, port->number);
if (!port->open_count) {
@@ -541,7 +584,7 @@ static struct usb_serial_driver *search_serial_device(struct usb_interface *ifac
const struct usb_device_id *id;
struct usb_serial_driver *t;
- /* List trough know devices and see if the usb id matches */
+ /* Check if the usb id matches a known device */
list_for_each(p, &usb_serial_driver_list) {
t = list_entry(p, struct usb_serial_driver, driver_list);
id = usb_match_id(iface, t->id_table);
@@ -742,6 +785,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->number = i + serial->minor;
port->serial = serial;
spin_lock_init(&port->lock);
+ sema_init(&port->sem, 1);
INIT_WORK(&port->work, usb_serial_port_softint, port);
serial->port[i] = port;
}
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 238a5a871ed6..d7d27c3385b3 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -16,6 +16,7 @@
#include <linux/config.h>
#include <linux/kref.h>
+#include <asm/semaphore.h>
#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */
#define SERIAL_TTY_MINORS 255 /* loads of devices :) */
@@ -30,6 +31,8 @@
* @serial: pointer back to the struct usb_serial owner of this port.
* @tty: pointer to the corresponding tty for this port.
* @lock: spinlock to grab when updating portions of this structure.
+ * @sem: semaphore used to synchronize serial_open() and serial_close()
+ * access for this port.
* @number: the number of the port (the minor number).
* @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
* @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -60,6 +63,7 @@ struct usb_serial_port {
struct usb_serial * serial;
struct tty_struct * tty;
spinlock_t lock;
+ struct semaphore sem;
unsigned char number;
unsigned char * interrupt_in_buffer;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index a473c1c34559..bce3d55affd8 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -173,11 +173,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver visor_driver = {
- .owner = THIS_MODULE,
.name = "visor",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
@@ -488,7 +488,6 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
unsigned long flags;
- int i;
int throttled;
int result;
@@ -503,14 +502,8 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
tty = port->tty;
if (tty && urb->actual_length) {
- for (i = 0; i < urb->actual_length ; ++i) {
- /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
- /* this doesn't actually push the data through unless tty->low_latency is set */
- tty_insert_flip_char(tty, data[i], 0);
- }
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
spin_lock_irqsave(&priv->lock, flags);
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 18c3183be769..557411c6e7c7 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -127,11 +127,11 @@ static struct usb_device_id id_table_combined [] = {
MODULE_DEVICE_TABLE (usb, id_table_combined);
static struct usb_driver whiteheat_driver = {
- .owner = THIS_MODULE,
.name = "whiteheat",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table_combined,
+ .no_dynamic_id = 1,
};
/* function prototypes for the Connect Tech WhiteHEAT prerenumeration device */
@@ -1434,7 +1434,9 @@ static void rx_data_softint(void *private)
urb = wrap->urb;
if (tty && urb->actual_length) {
- if (urb->actual_length > TTY_FLIPBUF_SIZE - tty->flip.count) {
+ int len = tty_buffer_request_room(tty, urb->actual_length);
+ /* This stuff can go away now I suspect */
+ if (unlikely(len < urb->actual_length)) {
spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urb_q);
spin_unlock_irqrestore(&info->lock, flags);
@@ -1442,11 +1444,8 @@ static void rx_data_softint(void *private)
schedule_work(&info->rx_work);
return;
}
-
- memcpy(tty->flip.char_buf_ptr, urb->transfer_buffer, urb->actual_length);
- tty->flip.char_buf_ptr += urb->actual_length;
- tty->flip.count += urb->actual_length;
- sent += urb->actual_length;
+ tty_insert_flip_string(tty, urb->transfer_buffer, len);
+ sent += len;
}
urb->dev = port->serial->dev;
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index c41d64dbb0f0..92be101feba7 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -112,6 +112,15 @@ config USB_STORAGE_JUMPSHOT
Say Y here to include additional code to support the Lexar Jumpshot
USB CompactFlash reader.
+config USB_STORAGE_ALAUDA
+ bool "Olympus MAUSB-10/Fuji DPC-R1 support (EXPERIMENTAL)"
+ depends on USB_STORAGE && EXPERIMENTAL
+ help
+ Say Y here to include additional code to support the Olympus MAUSB-10
+ and Fujifilm DPC-R1 USB Card reader/writer devices.
+
+ These devices are based on the Alauda chip and support support both
+ XD and SmartMedia cards.
config USB_STORAGE_ONETOUCH
bool "Support OneTouch Button on Maxtor Hard Drives (EXPERIMENTAL)"
@@ -124,3 +133,17 @@ config USB_STORAGE_ONETOUCH
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)
+
+config USB_LIBUSUAL
+ bool "The shared table of common (or usual) storage devices"
+ depends on USB
+ help
+ This module contains a table of common (or usual) devices
+ for usb-storage and ub drivers, and allows to switch binding
+ of these devices without rebuilding modules.
+
+ Typical syntax of /etc/modprobe.conf is:
+
+ options libusual bias="ub"
+
+ If unsure, say N.
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 44ab8f9978fe..8cbba22508a4 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -18,7 +18,12 @@ 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_ALAUDA) += alauda.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)
+
+ifneq ($(CONFIG_USB_LIBUSUAL),)
+ obj-$(CONFIG_USB) += libusual.o
+endif
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
new file mode 100644
index 000000000000..4d3cbb12b713
--- /dev/null
+++ b/drivers/usb/storage/alauda.c
@@ -0,0 +1,1119 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ * (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * The 'Alauda' is a chip manufacturered by RATOC for OEM use.
+ *
+ * Alauda implements a vendor-specific command set to access two media reader
+ * ports (XD, SmartMedia). This driver converts SCSI commands to the commands
+ * which are accepted by these devices.
+ *
+ * The driver was developed through reverse-engineering, with the help of the
+ * sddr09 driver which has many similarities, and with some help from the
+ * (very old) vendor-supplied GPL sma03 driver.
+ *
+ * For protocol info, see http://alauda.sourceforge.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, 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 <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+#include "alauda.h"
+
+#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
+#define LSB_of(s) ((s)&0xFF)
+#define MSB_of(s) ((s)>>8)
+
+#define MEDIA_PORT(us) us->srb->device->lun
+#define MEDIA_INFO(us) ((struct alauda_info *)us->extra)->port[MEDIA_PORT(us)]
+
+#define PBA_LO(pba) ((pba & 0xF) << 5)
+#define PBA_HI(pba) (pba >> 3)
+#define PBA_ZONE(pba) (pba >> 11)
+
+/*
+ * Media handling
+ */
+
+struct alauda_card_info {
+ unsigned char id; /* id byte */
+ unsigned char chipshift; /* 1<<cs bytes total capacity */
+ unsigned char pageshift; /* 1<<ps bytes in a page */
+ unsigned char blockshift; /* 1<<bs pages per block */
+ unsigned char zoneshift; /* 1<<zs blocks per zone */
+};
+
+static struct alauda_card_info alauda_card_ids[] = {
+ /* NAND flash */
+ { 0x6e, 20, 8, 4, 8}, /* 1 MB */
+ { 0xe8, 20, 8, 4, 8}, /* 1 MB */
+ { 0xec, 20, 8, 4, 8}, /* 1 MB */
+ { 0x64, 21, 8, 4, 9}, /* 2 MB */
+ { 0xea, 21, 8, 4, 9}, /* 2 MB */
+ { 0x6b, 22, 9, 4, 9}, /* 4 MB */
+ { 0xe3, 22, 9, 4, 9}, /* 4 MB */
+ { 0xe5, 22, 9, 4, 9}, /* 4 MB */
+ { 0xe6, 23, 9, 4, 10}, /* 8 MB */
+ { 0x73, 24, 9, 5, 10}, /* 16 MB */
+ { 0x75, 25, 9, 5, 10}, /* 32 MB */
+ { 0x76, 26, 9, 5, 10}, /* 64 MB */
+ { 0x79, 27, 9, 5, 10}, /* 128 MB */
+ { 0x71, 28, 9, 5, 10}, /* 256 MB */
+
+ /* MASK ROM */
+ { 0x5d, 21, 9, 4, 8}, /* 2 MB */
+ { 0xd5, 22, 9, 4, 9}, /* 4 MB */
+ { 0xd6, 23, 9, 4, 10}, /* 8 MB */
+ { 0x57, 24, 9, 4, 11}, /* 16 MB */
+ { 0x58, 25, 9, 4, 12}, /* 32 MB */
+ { 0,}
+};
+
+static struct alauda_card_info *alauda_card_find_id(unsigned char id) {
+ int i;
+
+ for (i = 0; alauda_card_ids[i].id != 0; i++)
+ if (alauda_card_ids[i].id == id)
+ return &(alauda_card_ids[i]);
+ return NULL;
+}
+
+/*
+ * ECC computation.
+ */
+
+static unsigned char parity[256];
+static unsigned char ecc2[256];
+
+static void nand_init_ecc(void) {
+ int i, j, a;
+
+ parity[0] = 0;
+ for (i = 1; i < 256; i++)
+ parity[i] = (parity[i&(i-1)] ^ 1);
+
+ for (i = 0; i < 256; i++) {
+ a = 0;
+ for (j = 0; j < 8; j++) {
+ if (i & (1<<j)) {
+ if ((j & 1) == 0)
+ a ^= 0x04;
+ if ((j & 2) == 0)
+ a ^= 0x10;
+ if ((j & 4) == 0)
+ a ^= 0x40;
+ }
+ }
+ ecc2[i] = ~(a ^ (a<<1) ^ (parity[i] ? 0xa8 : 0));
+ }
+}
+
+/* compute 3-byte ecc on 256 bytes */
+static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) {
+ int i, j, a;
+ unsigned char par, bit, bits[8];
+
+ par = 0;
+ for (j = 0; j < 8; j++)
+ bits[j] = 0;
+
+ /* collect 16 checksum bits */
+ for (i = 0; i < 256; i++) {
+ par ^= data[i];
+ bit = parity[data[i]];
+ for (j = 0; j < 8; j++)
+ if ((i & (1<<j)) == 0)
+ bits[j] ^= bit;
+ }
+
+ /* put 4+4+4 = 12 bits in the ecc */
+ a = (bits[3] << 6) + (bits[2] << 4) + (bits[1] << 2) + bits[0];
+ ecc[0] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+ a = (bits[7] << 6) + (bits[6] << 4) + (bits[5] << 2) + bits[4];
+ ecc[1] = ~(a ^ (a<<1) ^ (parity[par] ? 0xaa : 0));
+
+ ecc[2] = ecc2[par];
+}
+
+static int nand_compare_ecc(unsigned char *data, unsigned char *ecc) {
+ return (data[0] == ecc[0] && data[1] == ecc[1] && data[2] == ecc[2]);
+}
+
+static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
+ memcpy(data, ecc, 3);
+}
+
+/*
+ * Alauda driver
+ */
+
+/*
+ * Forget our PBA <---> LBA mappings for a particular port
+ */
+static void alauda_free_maps (struct alauda_media_info *media_info)
+{
+ unsigned int shift = media_info->zoneshift
+ + media_info->blockshift + media_info->pageshift;
+ unsigned int num_zones = media_info->capacity >> shift;
+ unsigned int i;
+
+ if (media_info->lba_to_pba != NULL)
+ for (i = 0; i < num_zones; i++) {
+ kfree(media_info->lba_to_pba[i]);
+ media_info->lba_to_pba[i] = NULL;
+ }
+
+ if (media_info->pba_to_lba != NULL)
+ for (i = 0; i < num_zones; i++) {
+ kfree(media_info->pba_to_lba[i]);
+ media_info->pba_to_lba[i] = NULL;
+ }
+}
+
+/*
+ * Returns 2 bytes of status data
+ * The first byte describes media status, and second byte describes door status
+ */
+static int alauda_get_media_status(struct us_data *us, unsigned char *data)
+{
+ int rc;
+ unsigned char command;
+
+ if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+ command = ALAUDA_GET_XD_MEDIA_STATUS;
+ else
+ command = ALAUDA_GET_SM_MEDIA_STATUS;
+
+ rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+ command, 0xc0, 0, 1, data, 2);
+
+ US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
+ data[0], data[1]);
+
+ return rc;
+}
+
+/*
+ * Clears the "media was changed" bit so that we know when it changes again
+ * in the future.
+ */
+static int alauda_ack_media(struct us_data *us)
+{
+ unsigned char command;
+
+ if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+ command = ALAUDA_ACK_XD_MEDIA_CHANGE;
+ else
+ command = ALAUDA_ACK_SM_MEDIA_CHANGE;
+
+ return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+ command, 0x40, 0, 1, NULL, 0);
+}
+
+/*
+ * Retrieves a 4-byte media signature, which indicates manufacturer, capacity,
+ * and some other details.
+ */
+static int alauda_get_media_signature(struct us_data *us, unsigned char *data)
+{
+ unsigned char command;
+
+ if (MEDIA_PORT(us) == ALAUDA_PORT_XD)
+ command = ALAUDA_GET_XD_MEDIA_SIG;
+ else
+ command = ALAUDA_GET_SM_MEDIA_SIG;
+
+ return usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
+ command, 0xc0, 0, 0, data, 4);
+}
+
+/*
+ * Resets the media status (but not the whole device?)
+ */
+static int alauda_reset_media(struct us_data *us)
+{
+ unsigned char *command = us->iobuf;
+
+ memset(command, 0, 9);
+ command[0] = ALAUDA_BULK_CMD;
+ command[1] = ALAUDA_BULK_RESET_MEDIA;
+ command[8] = MEDIA_PORT(us);
+
+ return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+}
+
+/*
+ * Examines the media and deduces capacity, etc.
+ */
+static int alauda_init_media(struct us_data *us)
+{
+ unsigned char *data = us->iobuf;
+ int ready = 0;
+ struct alauda_card_info *media_info;
+ unsigned int num_zones;
+
+ while (ready == 0) {
+ msleep(20);
+
+ if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ if (data[0] & 0x10)
+ ready = 1;
+ }
+
+ US_DEBUGP("alauda_init_media: We are ready for action!\n");
+
+ if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ msleep(10);
+
+ if (alauda_get_media_status(us, data) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ if (data[0] != 0x14) {
+ US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
+ data[0], data[1], data[2], data[3]);
+ media_info = alauda_card_find_id(data[1]);
+ if (media_info == NULL) {
+ printk("alauda_init_media: Unrecognised media signature: "
+ "%02X %02X %02X %02X\n",
+ data[0], data[1], data[2], data[3]);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
+ US_DEBUGP("Found media with capacity: %ldMB\n",
+ MEDIA_INFO(us).capacity >> 20);
+
+ MEDIA_INFO(us).pageshift = media_info->pageshift;
+ MEDIA_INFO(us).blockshift = media_info->blockshift;
+ MEDIA_INFO(us).zoneshift = media_info->zoneshift;
+
+ MEDIA_INFO(us).pagesize = 1 << media_info->pageshift;
+ MEDIA_INFO(us).blocksize = 1 << media_info->blockshift;
+ MEDIA_INFO(us).zonesize = 1 << media_info->zoneshift;
+
+ MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125;
+ MEDIA_INFO(us).blockmask = MEDIA_INFO(us).blocksize - 1;
+
+ num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+ + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+ MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+ MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO);
+
+ if (alauda_reset_media(us) != USB_STOR_XFER_GOOD)
+ return USB_STOR_TRANSPORT_ERROR;
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Examines the media status and does the right thing when the media has gone,
+ * appeared, or changed.
+ */
+static int alauda_check_media(struct us_data *us)
+{
+ struct alauda_info *info = (struct alauda_info *) us->extra;
+ unsigned char status[2];
+ int rc;
+
+ rc = alauda_get_media_status(us, status);
+
+ /* Check for no media or door open */
+ if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
+ || ((status[1] & 0x01) == 0)) {
+ US_DEBUGP("alauda_check_media: No media, or door open\n");
+ alauda_free_maps(&MEDIA_INFO(us));
+ info->sense_key = 0x02;
+ info->sense_asc = 0x3A;
+ info->sense_ascq = 0x00;
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ /* Check for media change */
+ if (status[0] & 0x08) {
+ US_DEBUGP("alauda_check_media: Media change detected\n");
+ alauda_free_maps(&MEDIA_INFO(us));
+ alauda_init_media(us);
+
+ info->sense_key = UNIT_ATTENTION;
+ info->sense_asc = 0x28;
+ info->sense_ascq = 0x00;
+ return USB_STOR_TRANSPORT_FAILED;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Checks the status from the 2nd status register
+ * Returns 3 bytes of status data, only the first is known
+ */
+static int alauda_check_status2(struct us_data *us)
+{
+ int rc;
+ unsigned char command[] = {
+ ALAUDA_BULK_CMD, ALAUDA_BULK_GET_STATUS2,
+ 0, 0, 0, 0, 3, 0, MEDIA_PORT(us)
+ };
+ unsigned char data[3];
+
+ rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, 3, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+ if (data[0] & ALAUDA_STATUS_ERROR)
+ return USB_STOR_XFER_ERROR;
+
+ return USB_STOR_XFER_GOOD;
+}
+
+/*
+ * Gets the redundancy data for the first page of a PBA
+ * Returns 16 bytes.
+ */
+static int alauda_get_redu_data(struct us_data *us, u16 pba, unsigned char *data)
+{
+ int rc;
+ unsigned char command[] = {
+ ALAUDA_BULK_CMD, ALAUDA_BULK_GET_REDU_DATA,
+ PBA_HI(pba), PBA_ZONE(pba), 0, PBA_LO(pba), 0, 0, MEDIA_PORT(us)
+ };
+
+ rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, 16, NULL);
+}
+
+/*
+ * Finds the first unused PBA in a zone
+ * Returns the absolute PBA of an unused PBA, or 0 if none found.
+ */
+static u16 alauda_find_unused_pba(struct alauda_media_info *info,
+ unsigned int zone)
+{
+ u16 *pba_to_lba = info->pba_to_lba[zone];
+ unsigned int i;
+
+ for (i = 0; i < info->zonesize; i++)
+ if (pba_to_lba[i] == UNDEF)
+ return (zone << info->zoneshift) + i;
+
+ return 0;
+}
+
+/*
+ * Reads the redundancy data for all PBA's in a zone
+ * Produces lba <--> pba mappings
+ */
+static int alauda_read_map(struct us_data *us, unsigned int zone)
+{
+ unsigned char *data = us->iobuf;
+ int result;
+ int i, j;
+ unsigned int zonesize = MEDIA_INFO(us).zonesize;
+ unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+ unsigned int lba_offset, lba_real, blocknum;
+ unsigned int zone_base_lba = zone * uzonesize;
+ unsigned int zone_base_pba = zone * zonesize;
+ u16 *lba_to_pba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+ u16 *pba_to_lba = kcalloc(zonesize, sizeof(u16), GFP_NOIO);
+ if (lba_to_pba == NULL || pba_to_lba == NULL) {
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto error;
+ }
+
+ US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+
+ /* 1024 PBA's per zone */
+ for (i = 0; i < zonesize; i++)
+ lba_to_pba[i] = pba_to_lba[i] = UNDEF;
+
+ for (i = 0; i < zonesize; i++) {
+ blocknum = zone_base_pba + i;
+
+ result = alauda_get_redu_data(us, blocknum, data);
+ if (result != USB_STOR_XFER_GOOD) {
+ result = USB_STOR_TRANSPORT_ERROR;
+ goto error;
+ }
+
+ /* special PBAs have control field 0^16 */
+ for (j = 0; j < 16; j++)
+ if (data[j] != 0)
+ goto nonz;
+ pba_to_lba[i] = UNUSABLE;
+ US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+ continue;
+
+ nonz:
+ /* unwritten PBAs have control field FF^16 */
+ for (j = 0; j < 16; j++)
+ if (data[j] != 0xff)
+ goto nonff;
+ continue;
+
+ nonff:
+ /* normal PBAs start with six FFs */
+ if (j < 6) {
+ US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
+ "reserved area = %02X%02X%02X%02X "
+ "data status %02X block status %02X\n",
+ blocknum, data[0], data[1], data[2], data[3],
+ data[4], data[5]);
+ pba_to_lba[i] = UNUSABLE;
+ continue;
+ }
+
+ if ((data[6] >> 4) != 0x01) {
+ US_DEBUGP("alauda_read_map: PBA %d has invalid address "
+ "field %02X%02X/%02X%02X\n",
+ blocknum, data[6], data[7], data[11], data[12]);
+ pba_to_lba[i] = UNUSABLE;
+ continue;
+ }
+
+ /* check even parity */
+ if (parity[data[6] ^ data[7]]) {
+ printk("alauda_read_map: Bad parity in LBA for block %d"
+ " (%02X %02X)\n", i, data[6], data[7]);
+ pba_to_lba[i] = UNUSABLE;
+ continue;
+ }
+
+ lba_offset = short_pack(data[7], data[6]);
+ lba_offset = (lba_offset & 0x07FF) >> 1;
+ lba_real = lba_offset + zone_base_lba;
+
+ /*
+ * Every 1024 physical blocks ("zone"), the LBA numbers
+ * go back to zero, but are within a higher block of LBA's.
+ * Also, there is a maximum of 1000 LBA's per zone.
+ * In other words, in PBA 1024-2047 you will find LBA 0-999
+ * which are really LBA 1000-1999. This allows for 24 bad
+ * or special physical blocks per zone.
+ */
+
+ if (lba_offset >= uzonesize) {
+ printk("alauda_read_map: Bad low LBA %d for block %d\n",
+ lba_real, blocknum);
+ continue;
+ }
+
+ if (lba_to_pba[lba_offset] != UNDEF) {
+ printk("alauda_read_map: LBA %d seen for PBA %d and %d\n",
+ lba_real, lba_to_pba[lba_offset], blocknum);
+ continue;
+ }
+
+ pba_to_lba[i] = lba_real;
+ lba_to_pba[lba_offset] = blocknum;
+ continue;
+ }
+
+ MEDIA_INFO(us).lba_to_pba[zone] = lba_to_pba;
+ MEDIA_INFO(us).pba_to_lba[zone] = pba_to_lba;
+ result = 0;
+ goto out;
+
+error:
+ kfree(lba_to_pba);
+ kfree(pba_to_lba);
+out:
+ return result;
+}
+
+/*
+ * Checks to see whether we have already mapped a certain zone
+ * If we haven't, the map is generated
+ */
+static void alauda_ensure_map_for_zone(struct us_data *us, unsigned int zone)
+{
+ if (MEDIA_INFO(us).lba_to_pba[zone] == NULL
+ || MEDIA_INFO(us).pba_to_lba[zone] == NULL)
+ alauda_read_map(us, zone);
+}
+
+/*
+ * Erases an entire block
+ */
+static int alauda_erase_block(struct us_data *us, u16 pba)
+{
+ int rc;
+ unsigned char command[] = {
+ ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba),
+ PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, MEDIA_PORT(us)
+ };
+ unsigned char buf[2];
+
+ US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+
+ rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ rc = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ buf, 2, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
+ buf[0], buf[1]);
+ return rc;
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, including interleaved
+ * redundancy data. Returns (pagesize+64)*pages bytes in data.
+ */
+static int alauda_read_block_raw(struct us_data *us, u16 pba,
+ unsigned int page, unsigned int pages, unsigned char *data)
+{
+ int rc;
+ unsigned char command[] = {
+ ALAUDA_BULK_CMD, ALAUDA_BULK_READ_BLOCK, PBA_HI(pba),
+ PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
+ };
+
+ US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
+ pba, page, pages);
+
+ rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+ data, (MEDIA_INFO(us).pagesize + 64) * pages, NULL);
+}
+
+/*
+ * Reads data from a certain offset page inside a PBA, excluding redundancy
+ * data. Returns pagesize*pages bytes in data. Note that data must be big enough
+ * to hold (pagesize+64)*pages bytes of data, but you can ignore those 'extra'
+ * trailing bytes outside this function.
+ */
+static int alauda_read_block(struct us_data *us, u16 pba,
+ unsigned int page, unsigned int pages, unsigned char *data)
+{
+ int i, rc;
+ unsigned int pagesize = MEDIA_INFO(us).pagesize;
+
+ rc = alauda_read_block_raw(us, pba, page, pages, data);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ /* Cut out the redundancy data */
+ for (i = 0; i < pages; i++) {
+ int dest_offset = i * pagesize;
+ int src_offset = i * (pagesize + 64);
+ memmove(data + dest_offset, data + src_offset, pagesize);
+ }
+
+ return rc;
+}
+
+/*
+ * Writes an entire block of data and checks status after write.
+ * Redundancy data must be already included in data. Data should be
+ * (pagesize+64)*blocksize bytes in length.
+ */
+static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
+{
+ int rc;
+ struct alauda_info *info = (struct alauda_info *) us->extra;
+ unsigned char command[] = {
+ ALAUDA_BULK_CMD, ALAUDA_BULK_WRITE_BLOCK, PBA_HI(pba),
+ PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
+ };
+
+ US_DEBUGP("alauda_write_block: pba %d\n", pba);
+
+ rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+ command, 9, NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ rc = usb_stor_bulk_transfer_buf(us, info->wr_ep, data,
+ (MEDIA_INFO(us).pagesize + 64) * MEDIA_INFO(us).blocksize,
+ NULL);
+ if (rc != USB_STOR_XFER_GOOD)
+ return rc;
+
+ return alauda_check_status2(us);
+}
+
+/*
+ * Write some data to a specific LBA.
+ */
+static int alauda_write_lba(struct us_data *us, u16 lba,
+ unsigned int page, unsigned int pages,
+ unsigned char *ptr, unsigned char *blockbuffer)
+{
+ u16 pba, lbap, new_pba;
+ unsigned char *bptr, *cptr, *xptr;
+ unsigned char ecc[3];
+ int i, result;
+ unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+ unsigned int zonesize = MEDIA_INFO(us).zonesize;
+ unsigned int pagesize = MEDIA_INFO(us).pagesize;
+ unsigned int blocksize = MEDIA_INFO(us).blocksize;
+ unsigned int lba_offset = lba % uzonesize;
+ unsigned int new_pba_offset;
+ unsigned int zone = lba / uzonesize;
+
+ alauda_ensure_map_for_zone(us, zone);
+
+ pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+ if (pba == 1) {
+ /* Maybe it is impossible to write to PBA 1.
+ Fake success, but don't do anything. */
+ printk("alauda_write_lba: avoid writing to pba 1\n");
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone);
+ if (!new_pba) {
+ printk("alauda_write_lba: Out of unused blocks\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* read old contents */
+ if (pba != UNDEF) {
+ result = alauda_read_block_raw(us, pba, 0,
+ blocksize, blockbuffer);
+ if (result != USB_STOR_XFER_GOOD)
+ return result;
+ } else {
+ memset(blockbuffer, 0, blocksize * (pagesize + 64));
+ }
+
+ lbap = (lba_offset << 1) | 0x1000;
+ if (parity[MSB_of(lbap) ^ LSB_of(lbap)])
+ lbap ^= 1;
+
+ /* check old contents and fill lba */
+ for (i = 0; i < blocksize; i++) {
+ bptr = blockbuffer + (i * (pagesize + 64));
+ cptr = bptr + pagesize;
+ nand_compute_ecc(bptr, ecc);
+ if (!nand_compare_ecc(cptr+13, ecc)) {
+ US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
+ i, pba);
+ nand_store_ecc(cptr+13, ecc);
+ }
+ nand_compute_ecc(bptr + (pagesize / 2), ecc);
+ if (!nand_compare_ecc(cptr+8, ecc)) {
+ US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
+ i, pba);
+ nand_store_ecc(cptr+8, ecc);
+ }
+ cptr[6] = cptr[11] = MSB_of(lbap);
+ cptr[7] = cptr[12] = LSB_of(lbap);
+ }
+
+ /* copy in new stuff and compute ECC */
+ xptr = ptr;
+ for (i = page; i < page+pages; i++) {
+ bptr = blockbuffer + (i * (pagesize + 64));
+ cptr = bptr + pagesize;
+ memcpy(bptr, xptr, pagesize);
+ xptr += pagesize;
+ nand_compute_ecc(bptr, ecc);
+ nand_store_ecc(cptr+13, ecc);
+ nand_compute_ecc(bptr + (pagesize / 2), ecc);
+ nand_store_ecc(cptr+8, ecc);
+ }
+
+ result = alauda_write_block(us, new_pba, blockbuffer);
+ if (result != USB_STOR_XFER_GOOD)
+ return result;
+
+ new_pba_offset = new_pba - (zone * zonesize);
+ MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
+ MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
+ US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
+ lba, new_pba);
+
+ if (pba != UNDEF) {
+ unsigned int pba_offset = pba - (zone * zonesize);
+ result = alauda_erase_block(us, pba);
+ if (result != USB_STOR_XFER_GOOD)
+ return result;
+ MEDIA_INFO(us).pba_to_lba[zone][pba_offset] = UNDEF;
+ }
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Read data from a specific sector address
+ */
+static int alauda_read_data(struct us_data *us, unsigned long address,
+ unsigned int sectors)
+{
+ unsigned char *buffer;
+ u16 lba, max_lba;
+ unsigned int page, len, index, offset;
+ unsigned int blockshift = MEDIA_INFO(us).blockshift;
+ unsigned int pageshift = MEDIA_INFO(us).pageshift;
+ unsigned int blocksize = MEDIA_INFO(us).blocksize;
+ unsigned int pagesize = MEDIA_INFO(us).pagesize;
+ unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
+ int result;
+
+ /*
+ * Since we only read in one block at a time, we have to create
+ * a bounce buffer and move the data a piece at a time between the
+ * bounce buffer and the actual transfer buffer.
+ * We make this buffer big enough to hold temporary redundancy data,
+ * which we use when reading the data blocks.
+ */
+
+ len = min(sectors, blocksize) * (pagesize + 64);
+ buffer = kmalloc(len, GFP_NOIO);
+ if (buffer == NULL) {
+ printk("alauda_read_data: Out of memory\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* Figure out the initial LBA and page */
+ lba = address >> blockshift;
+ page = (address & MEDIA_INFO(us).blockmask);
+ max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift);
+
+ result = USB_STOR_TRANSPORT_GOOD;
+ index = offset = 0;
+
+ while (sectors > 0) {
+ unsigned int zone = lba / uzonesize; /* integer division */
+ unsigned int lba_offset = lba - (zone * uzonesize);
+ unsigned int pages;
+ u16 pba;
+ alauda_ensure_map_for_zone(us, zone);
+
+ /* Not overflowing capacity? */
+ if (lba >= max_lba) {
+ US_DEBUGP("Error: Requested lba %u exceeds "
+ "maximum %u\n", lba, max_lba);
+ result = USB_STOR_TRANSPORT_ERROR;
+ break;
+ }
+
+ /* Find number of pages we can read in this block */
+ pages = min(sectors, blocksize - page);
+ len = pages << pageshift;
+
+ /* Find where this lba lives on disk */
+ pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
+
+ if (pba == UNDEF) { /* this lba was never written */
+ US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
+ pages, lba, page);
+
+ /* This is not really an error. It just means
+ that the block has never been written.
+ Instead of returning USB_STOR_TRANSPORT_ERROR
+ it is better to return all zero data. */
+
+ memset(buffer, 0, len);
+ } else {
+ US_DEBUGP("Read %d pages, from PBA %d"
+ " (LBA %d) page %d\n",
+ pages, pba, lba, page);
+
+ result = alauda_read_block(us, pba, page, pages, buffer);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ break;
+ }
+
+ /* Store the data in the transfer buffer */
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &index, &offset, TO_XFER_BUF);
+
+ page = 0;
+ lba++;
+ sectors -= pages;
+ }
+
+ kfree(buffer);
+ return result;
+}
+
+/*
+ * Write data to a specific sector address
+ */
+static int alauda_write_data(struct us_data *us, unsigned long address,
+ unsigned int sectors)
+{
+ unsigned char *buffer, *blockbuffer;
+ unsigned int page, len, index, offset;
+ unsigned int blockshift = MEDIA_INFO(us).blockshift;
+ unsigned int pageshift = MEDIA_INFO(us).pageshift;
+ unsigned int blocksize = MEDIA_INFO(us).blocksize;
+ unsigned int pagesize = MEDIA_INFO(us).pagesize;
+ u16 lba, max_lba;
+ int result;
+
+ /*
+ * Since we don't write the user data directly to the device,
+ * we have to create a bounce buffer and move the data a piece
+ * at a time between the bounce buffer and the actual transfer buffer.
+ */
+
+ len = min(sectors, blocksize) * pagesize;
+ buffer = kmalloc(len, GFP_NOIO);
+ if (buffer == NULL) {
+ printk("alauda_write_data: Out of memory\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /*
+ * We also need a temporary block buffer, where we read in the old data,
+ * overwrite parts with the new data, and manipulate the redundancy data
+ */
+ blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO);
+ if (blockbuffer == NULL) {
+ printk("alauda_write_data: Out of memory\n");
+ kfree(buffer);
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+
+ /* Figure out the initial LBA and page */
+ lba = address >> blockshift;
+ page = (address & MEDIA_INFO(us).blockmask);
+ max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift);
+
+ result = USB_STOR_TRANSPORT_GOOD;
+ index = offset = 0;
+
+ while (sectors > 0) {
+ /* Write as many sectors as possible in this block */
+ unsigned int pages = min(sectors, blocksize - page);
+ len = pages << pageshift;
+
+ /* Not overflowing capacity? */
+ if (lba >= max_lba) {
+ US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
+ "maximum %u\n", lba, max_lba);
+ result = USB_STOR_TRANSPORT_ERROR;
+ break;
+ }
+
+ /* Get the data from the transfer buffer */
+ usb_stor_access_xfer_buf(buffer, len, us->srb,
+ &index, &offset, FROM_XFER_BUF);
+
+ result = alauda_write_lba(us, lba, page, pages, buffer,
+ blockbuffer);
+ if (result != USB_STOR_TRANSPORT_GOOD)
+ break;
+
+ page = 0;
+ lba++;
+ sectors -= pages;
+ }
+
+ kfree(buffer);
+ kfree(blockbuffer);
+ return result;
+}
+
+/*
+ * Our interface with the rest of the world
+ */
+
+static void alauda_info_destructor(void *extra)
+{
+ struct alauda_info *info = (struct alauda_info *) extra;
+ int port;
+
+ if (!info)
+ return;
+
+ for (port = 0; port < 2; port++) {
+ struct alauda_media_info *media_info = &info->port[port];
+
+ alauda_free_maps(media_info);
+ kfree(media_info->lba_to_pba);
+ kfree(media_info->pba_to_lba);
+ }
+}
+
+/*
+ * Initialize alauda_info struct and find the data-write endpoint
+ */
+int init_alauda(struct us_data *us)
+{
+ struct alauda_info *info;
+ struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting;
+ nand_init_ecc();
+
+ us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
+ if (!us->extra) {
+ US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
+ "alauda info struct!\n");
+ return USB_STOR_TRANSPORT_ERROR;
+ }
+ info = (struct alauda_info *) us->extra;
+ us->extra_destructor = alauda_info_destructor;
+
+ info->wr_ep = usb_sndbulkpipe(us->pusb_dev,
+ altsetting->endpoint[0].desc.bEndpointAddress
+ & USB_ENDPOINT_NUMBER_MASK);
+
+ return USB_STOR_TRANSPORT_GOOD;
+}
+
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+ int rc;
+ struct alauda_info *info = (struct alauda_info *) us->extra;
+ unsigned char *ptr = us->iobuf;
+ static unsigned char inquiry_response[36] = {
+ 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
+ };
+
+ if (srb->cmnd[0] == INQUIRY) {
+ US_DEBUGP("alauda_transport: INQUIRY. "
+ "Returning bogus response.\n");
+ memcpy(ptr, inquiry_response, sizeof(inquiry_response));
+ fill_inquiry_response(us, ptr, 36);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ if (srb->cmnd[0] == TEST_UNIT_READY) {
+ US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+ return alauda_check_media(us);
+ }
+
+ if (srb->cmnd[0] == READ_CAPACITY) {
+ unsigned int num_zones;
+ unsigned long capacity;
+
+ rc = alauda_check_media(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ num_zones = MEDIA_INFO(us).capacity >> (MEDIA_INFO(us).zoneshift
+ + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift);
+
+ capacity = num_zones * MEDIA_INFO(us).uzonesize
+ * MEDIA_INFO(us).blocksize;
+
+ /* Report capacity and page size */
+ ((__be32 *) ptr)[0] = cpu_to_be32(capacity - 1);
+ ((__be32 *) ptr)[1] = cpu_to_be32(512);
+
+ usb_stor_set_xfer_buf(ptr, 8, srb);
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ if (srb->cmnd[0] == READ_10) {
+ unsigned int page, pages;
+
+ rc = alauda_check_media(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+ page <<= 16;
+ page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+ pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+ US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
+ page, pages);
+
+ return alauda_read_data(us, page, pages);
+ }
+
+ if (srb->cmnd[0] == WRITE_10) {
+ unsigned int page, pages;
+
+ rc = alauda_check_media(us);
+ if (rc != USB_STOR_TRANSPORT_GOOD)
+ return rc;
+
+ page = short_pack(srb->cmnd[3], srb->cmnd[2]);
+ page <<= 16;
+ page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
+ pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
+
+ US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
+ page, pages);
+
+ return alauda_write_data(us, page, pages);
+ }
+
+ if (srb->cmnd[0] == REQUEST_SENSE) {
+ US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+
+ memset(ptr, 0, 18);
+ ptr[0] = 0xF0;
+ ptr[2] = info->sense_key;
+ ptr[7] = 11;
+ ptr[12] = info->sense_asc;
+ ptr[13] = info->sense_ascq;
+ usb_stor_set_xfer_buf(ptr, 18, srb);
+
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+ /* sure. whatever. not like we can stop the user from popping
+ the media out of the device (no locking doors, etc) */
+ return USB_STOR_TRANSPORT_GOOD;
+ }
+
+ US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
+ srb->cmnd[0], srb->cmnd[0]);
+ info->sense_key = 0x05;
+ info->sense_asc = 0x20;
+ info->sense_ascq = 0x00;
+ return USB_STOR_TRANSPORT_FAILED;
+}
+
diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h
new file mode 100644
index 000000000000..a700f87d0803
--- /dev/null
+++ b/drivers/usb/storage/alauda.h
@@ -0,0 +1,100 @@
+/*
+ * Driver for Alauda-based card readers
+ *
+ * Current development and maintenance by:
+ * (c) 2005 Daniel Drake <dsd@gentoo.org>
+ *
+ * See alauda.c for more explanation.
+ *
+ * This program is free software; you can redistribute 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 _USB_ALAUDA_H
+#define _USB_ALAUDA_H
+
+/*
+ * Status bytes
+ */
+#define ALAUDA_STATUS_ERROR 0x01
+#define ALAUDA_STATUS_READY 0x40
+
+/*
+ * Control opcodes (for request field)
+ */
+#define ALAUDA_GET_XD_MEDIA_STATUS 0x08
+#define ALAUDA_GET_SM_MEDIA_STATUS 0x98
+#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a
+#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a
+#define ALAUDA_GET_XD_MEDIA_SIG 0x86
+#define ALAUDA_GET_SM_MEDIA_SIG 0x96
+
+/*
+ * Bulk command identity (byte 0)
+ */
+#define ALAUDA_BULK_CMD 0x40
+
+/*
+ * Bulk opcodes (byte 1)
+ */
+#define ALAUDA_BULK_GET_REDU_DATA 0x85
+#define ALAUDA_BULK_READ_BLOCK 0x94
+#define ALAUDA_BULK_ERASE_BLOCK 0xa3
+#define ALAUDA_BULK_WRITE_BLOCK 0xb4
+#define ALAUDA_BULK_GET_STATUS2 0xb7
+#define ALAUDA_BULK_RESET_MEDIA 0xe0
+
+/*
+ * Port to operate on (byte 8)
+ */
+#define ALAUDA_PORT_XD 0x00
+#define ALAUDA_PORT_SM 0x01
+
+/*
+ * LBA and PBA are unsigned ints. Special values.
+ */
+#define UNDEF 0xffff
+#define SPARE 0xfffe
+#define UNUSABLE 0xfffd
+
+int init_alauda(struct us_data *us);
+int alauda_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+struct alauda_media_info {
+ unsigned long capacity; /* total media size in bytes */
+ unsigned int pagesize; /* page size in bytes */
+ unsigned int blocksize; /* number of pages per block */
+ unsigned int uzonesize; /* number of usable blocks per zone */
+ unsigned int zonesize; /* number of blocks per zone */
+ unsigned int blockmask; /* mask to get page from address */
+
+ unsigned char pageshift;
+ unsigned char blockshift;
+ unsigned char zoneshift;
+
+ u16 **lba_to_pba; /* logical to physical block map */
+ u16 **pba_to_lba; /* physical to logical block map */
+};
+
+struct alauda_info {
+ struct alauda_media_info port[2];
+ int wr_ep; /* endpoint to write data out of */
+
+ unsigned char sense_key;
+ unsigned long sense_asc; /* additional sense code */
+ unsigned long sense_ascq; /* additional sense code qualifier */
+};
+
+#endif
+
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index 5a9321705a74..01e430654a13 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -132,6 +132,7 @@ void usb_stor_show_command(struct scsi_cmnd *srb)
case 0x5C: what = "READ BUFFER CAPACITY"; break;
case 0x5D: what = "SEND CUE SHEET"; break;
case GPCMD_BLANK: what = "BLANK"; break;
+ case REPORT_LUNS: what = "REPORT LUNS"; break;
case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
case READ_12: what = "READ_12"; break;
case WRITE_12: what = "WRITE_12"; break;
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 7372386f33d5..4c1b2bd2e2e4 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -45,10 +45,6 @@
* mode */
int usb_stor_euscsi_init(struct us_data *us);
-#ifdef CONFIG_USB_STORAGE_SDDR09
-int sddr09_init(struct us_data *us);
-#endif
-
/* This function is required to activate all four slots on the UCR-61S2B
* flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us);
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
new file mode 100644
index 000000000000..b28151d1b609
--- /dev/null
+++ b/drivers/usb/storage/libusual.c
@@ -0,0 +1,266 @@
+/*
+ * libusual
+ *
+ * The libusual contains the table of devices common for ub and usb-storage.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/vmalloc.h>
+
+/*
+ */
+#define USU_MOD_FL_THREAD 1 /* Thread is running */
+#define USU_MOD_FL_PRESENT 2 /* The module is loaded */
+
+struct mod_status {
+ unsigned long fls;
+};
+
+static struct mod_status stat[3];
+static DEFINE_SPINLOCK(usu_lock);
+
+/*
+ */
+#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR
+static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS);
+
+#define BIAS_NAME_SIZE (sizeof("usb-storage"))
+static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+
+static DECLARE_MUTEX_LOCKED(usu_init_notify);
+static DECLARE_COMPLETION(usu_end_notify);
+static atomic_t total_threads = ATOMIC_INIT(0);
+
+static int usu_probe_thread(void *arg);
+
+/*
+ * The table.
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName,useProtocol, useTransport, \
+ initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+ .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+ .driver_info = ((useType)<<24) }
+
+struct usb_device_id storage_usb_ids [] = {
+# include "unusual_devs.h"
+ { } /* Terminating entry */
+};
+
+#undef USUAL_DEV
+#undef UNUSUAL_DEV
+
+MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+EXPORT_SYMBOL_GPL(storage_usb_ids);
+
+/*
+ * @type: the module type as an integer
+ */
+void usb_usual_set_present(int type)
+{
+ struct mod_status *st;
+ unsigned long flags;
+
+ if (type <= 0 || type >= 3)
+ return;
+ st = &stat[type];
+ spin_lock_irqsave(&usu_lock, flags);
+ st->fls |= USU_MOD_FL_PRESENT;
+ spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_set_present);
+
+void usb_usual_clear_present(int type)
+{
+ struct mod_status *st;
+ unsigned long flags;
+
+ if (type <= 0 || type >= 3)
+ return;
+ st = &stat[type];
+ spin_lock_irqsave(&usu_lock, flags);
+ st->fls &= ~USU_MOD_FL_PRESENT;
+ spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_usual_clear_present);
+
+/*
+ * Match the calling driver type against the table.
+ * Returns: 0 if the device matches.
+ */
+int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
+{
+ int id_type = USB_US_TYPE(id->driver_info);
+
+ if (caller_type <= 0 || caller_type >= 3)
+ return -EINVAL;
+
+ /* Drivers grab fixed assignment devices */
+ if (id_type == caller_type)
+ return 0;
+ /* Drivers grab devices biased to them */
+ if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias))
+ return 0;
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usb_usual_check_type);
+
+/*
+ */
+static int usu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int type;
+ int rc;
+ unsigned long flags;
+
+ type = USB_US_TYPE(id->driver_info);
+ if (type == 0)
+ type = atomic_read(&usu_bias);
+
+ spin_lock_irqsave(&usu_lock, flags);
+ if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
+ spin_unlock_irqrestore(&usu_lock, flags);
+ return -ENXIO;
+ }
+ stat[type].fls |= USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+
+ rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
+ if (rc < 0) {
+ printk(KERN_WARNING "libusual: "
+ "Unable to start the thread for %s: %d\n",
+ bias_names[type], rc);
+ spin_lock_irqsave(&usu_lock, flags);
+ stat[type].fls &= ~USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+ return rc; /* Not being -ENXIO causes a message printed */
+ }
+ atomic_inc(&total_threads);
+
+ return -ENXIO;
+}
+
+static void usu_disconnect(struct usb_interface *intf)
+{
+ ; /* We should not be here. */
+}
+
+static struct usb_driver usu_driver = {
+ .name = "libusual",
+ .probe = usu_probe,
+ .disconnect = usu_disconnect,
+ .id_table = storage_usb_ids,
+};
+
+/*
+ * A whole new thread for a purpose of request_module seems quite stupid.
+ * The request_module forks once inside again. However, if we attempt
+ * to load a storage module from our own modprobe thread, that module
+ * references our symbols, which cannot be resolved until our module is
+ * initialized. I wish there was a way to wait for the end of initialization.
+ * The module notifier reports MODULE_STATE_COMING only.
+ * So, we wait until module->init ends as the next best thing.
+ */
+static int usu_probe_thread(void *arg)
+{
+ int type = (unsigned long) arg;
+ struct mod_status *st = &stat[type];
+ int rc;
+ unsigned long flags;
+
+ daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
+
+ /* A completion does not work here because it's counted. */
+ down(&usu_init_notify);
+ up(&usu_init_notify);
+
+ rc = request_module(bias_names[type]);
+ spin_lock_irqsave(&usu_lock, flags);
+ if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+ /*
+ * This should not happen, but let us keep tabs on it.
+ */
+ printk(KERN_NOTICE "libusual: "
+ "modprobe for %s succeeded, but module is not present\n",
+ bias_names[type]);
+ }
+ st->fls &= ~USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+
+ complete_and_exit(&usu_end_notify, 0);
+}
+
+/*
+ */
+static int __init usb_usual_init(void)
+{
+ int rc;
+
+ rc = usb_register(&usu_driver);
+ up(&usu_init_notify);
+ return rc;
+}
+
+static void __exit usb_usual_exit(void)
+{
+ /*
+ * We do not check for any drivers present, because
+ * they keep us pinned with symbol references.
+ */
+
+ usb_deregister(&usu_driver);
+
+ while (atomic_read(&total_threads) > 0) {
+ wait_for_completion(&usu_end_notify);
+ atomic_dec(&total_threads);
+ }
+}
+
+/*
+ * Validate and accept the bias parameter.
+ */
+static int usu_set_bias(const char *bias_s, struct kernel_param *kp)
+{
+ int i;
+ int len;
+ int bias_n = 0;
+
+ len = strlen(bias_s);
+ if (len == 0)
+ return -EDOM;
+ if (bias_s[len-1] == '\n')
+ --len;
+
+ for (i = 1; i < 3; i++) {
+ if (strncmp(bias_s, bias_names[i], len) == 0) {
+ bias_n = i;
+ break;
+ }
+ }
+ if (bias_n == 0)
+ return -EINVAL;
+
+ atomic_set(&usu_bias, bias_n);
+ return 0;
+}
+
+static int usu_get_bias(char *buffer, struct kernel_param *kp)
+{
+ return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)]));
+}
+
+module_init(usb_usual_init);
+module_exit(usb_usual_exit);
+
+module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR);
+__MODULE_PARM_TYPE(bias, "string");
+MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 89401a59f952..55ee2d36d585 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -52,6 +52,7 @@ struct usb_onetouch {
struct urb *irq; /* urb for interrupt in report */
unsigned char *data; /* input data */
dma_addr_t data_dma;
+ unsigned int is_open:1;
};
static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
@@ -89,6 +90,7 @@ static int usb_onetouch_open(struct input_dev *dev)
{
struct usb_onetouch *onetouch = dev->private;
+ onetouch->is_open = 1;
onetouch->irq->dev = onetouch->udev;
if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
err("usb_submit_urb failed");
@@ -103,8 +105,30 @@ static void usb_onetouch_close(struct input_dev *dev)
struct usb_onetouch *onetouch = dev->private;
usb_kill_urb(onetouch->irq);
+ onetouch->is_open = 0;
}
+#ifdef CONFIG_PM
+static void usb_onetouch_pm_hook(struct us_data *us, int action)
+{
+ struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra;
+
+ if (onetouch->is_open) {
+ switch (action) {
+ case US_SUSPEND:
+ usb_kill_urb(onetouch->irq);
+ break;
+ case US_RESUME:
+ if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+ err("usb_submit_urb failed");
+ break;
+ default:
+ break;
+ }
+ }
+}
+#endif /* CONFIG_PM */
+
int onetouch_connect_input(struct us_data *ss)
{
struct usb_device *udev = ss->pusb_dev;
@@ -185,6 +209,9 @@ int onetouch_connect_input(struct us_data *ss)
ss->extra_destructor = onetouch_release_input;
ss->extra = onetouch;
+#ifdef CONFIG_PM
+ ss->suspend_resume_hook = usb_onetouch_pm_hook;
+#endif
input_register_device(onetouch->dev);
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 02bff01ab09c..845bed4b8031 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,20 +41,6 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_
-/* Sub Classes */
-
-#define US_SC_RBC 0x01 /* Typically, flash devices */
-#define US_SC_8020 0x02 /* CD-ROM */
-#define US_SC_QIC 0x03 /* QIC-157 Tapes */
-#define US_SC_UFI 0x04 /* Floppy */
-#define US_SC_8070 0x05 /* Removable media */
-#define US_SC_SCSI 0x06 /* Transparent */
-#define US_SC_ISD200 0x07 /* ISD200 ATA */
-#define US_SC_MIN US_SC_RBC
-#define US_SC_MAX US_SC_ISD200
-
-#define US_SC_DEVICE 0xff /* Use device's value */
-
/* Protocol handling routines */
extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 0ea2f5ab66ba..fb8bacaae27c 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -133,13 +133,11 @@ static struct nand_flash_dev nand_flash_ids[] = {
{ 0,}
};
-#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
-
static struct nand_flash_dev *
nand_find_id(unsigned char id) {
int i;
- for (i = 0; i < SIZE(nand_flash_ids); i++)
+ for (i = 0; i < ARRAY_SIZE(nand_flash_ids); i++)
if (nand_flash_ids[i].model_id == id)
return &(nand_flash_ids[i]);
return NULL;
@@ -214,6 +212,20 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
* The actual driver starts here.
*/
+struct sddr09_card_info {
+ unsigned long capacity; /* Size of card in bytes */
+ int pagesize; /* Size of page in bytes */
+ int pageshift; /* log2 of pagesize */
+ int blocksize; /* Size of block in pages */
+ int blockshift; /* log2 of blocksize */
+ int blockmask; /* 2^blockshift - 1 */
+ int *lba_to_pba; /* logical to physical map */
+ int *pba_to_lba; /* physical to logical map */
+ int lbact; /* number of available pages */
+ int flags;
+#define SDDR09_WP 1 /* write protected */
+};
+
/*
* On my 16MB card, control blocks have size 64 (16 real control bytes,
* and 48 junk bytes). In reality of course the card uses 16 control bytes,
@@ -237,7 +249,7 @@ static void nand_store_ecc(unsigned char *data, unsigned char *ecc) {
#define SPARE 0xfffffffe
#define UNUSABLE 0xfffffffd
-static int erase_bad_lba_entries = 0;
+static const int erase_bad_lba_entries = 0;
/* send vendor interface command (0x41) */
/* called for requests 0, 1, 8 */
@@ -260,8 +272,11 @@ sddr09_send_command(struct us_data *us,
rc = usb_stor_ctrl_transfer(us, pipe, request, requesttype,
0, 0, xfer_data, xfer_len);
- return (rc == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD :
- USB_STOR_TRANSPORT_ERROR);
+ switch (rc) {
+ case USB_STOR_XFER_GOOD: return 0;
+ case USB_STOR_XFER_STALLED: return -EPIPE;
+ default: return -EIO;
+ }
}
static int
@@ -308,20 +323,12 @@ sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) {
command[4] = buflen;
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD) {
- US_DEBUGP("request sense failed\n");
+ if (result)
return result;
- }
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
sensebuf, buflen, NULL);
- if (result != USB_STOR_XFER_GOOD) {
- US_DEBUGP("request sense bulk in failed\n");
- return USB_STOR_TRANSPORT_ERROR;
- } else {
- US_DEBUGP("request sense worked\n");
- return USB_STOR_TRANSPORT_GOOD;
- }
+ return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
}
/*
@@ -369,7 +376,7 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
x, result);
return result;
@@ -381,9 +388,9 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
x, result);
- return USB_STOR_TRANSPORT_ERROR;
+ return -EIO;
}
- return USB_STOR_TRANSPORT_GOOD;
+ return 0;
}
/*
@@ -497,7 +504,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
US_DEBUGP("Result for send_control in sddr09_erase %d\n",
result);
@@ -555,7 +562,7 @@ sddr09_writeX(struct us_data *us,
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
result);
return result;
@@ -567,9 +574,9 @@ sddr09_writeX(struct us_data *us,
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
result);
- return USB_STOR_TRANSPORT_ERROR;
+ return -EIO;
}
- return USB_STOR_TRANSPORT_GOOD;
+ return 0;
}
/* erase address, write same address */
@@ -633,7 +640,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
result = sddr09_send_scsi_command(us, command, 4*nsg+3);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
result);
return result;
@@ -641,7 +648,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
if (!buf)
- return USB_STOR_TRANSPORT_ERROR;
+ return -ENOMEM;
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
buf, bulklen, NULL);
@@ -649,10 +656,10 @@ sddr09_read_sg_test_only(struct us_data *us) {
if (result != USB_STOR_XFER_GOOD) {
US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
result);
- return USB_STOR_TRANSPORT_ERROR;
+ return -EIO;
}
- return USB_STOR_TRANSPORT_GOOD;
+ return 0;
}
#endif
@@ -681,14 +688,13 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
command[1] = LUNBITS;
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
return result;
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
data, 64, NULL);
*status = data[0];
- return (result == USB_STOR_XFER_GOOD ?
- USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+ return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
}
static int
@@ -703,6 +709,13 @@ sddr09_read_data(struct us_data *us,
unsigned int len, index, offset;
int result;
+ // Figure out the initial LBA and page
+ lba = address >> info->blockshift;
+ page = (address & info->blockmask);
+ maxlba = info->capacity >> (info->pageshift + info->blockshift);
+ if (lba >= maxlba)
+ return -EIO;
+
// Since we only read in one block at a time, we have to create
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
@@ -711,18 +724,13 @@ sddr09_read_data(struct us_data *us,
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL) {
printk("sddr09_read_data: Out of memory\n");
- return USB_STOR_TRANSPORT_ERROR;
+ return -ENOMEM;
}
- // Figure out the initial LBA and page
- lba = address >> info->blockshift;
- page = (address & info->blockmask);
- maxlba = info->capacity >> (info->pageshift + info->blockshift);
-
// This could be made much more efficient by checking for
// contiguous LBA's. Another exercise left to the student.
- result = USB_STOR_TRANSPORT_GOOD;
+ result = 0;
index = offset = 0;
while (sectors > 0) {
@@ -735,7 +743,7 @@ sddr09_read_data(struct us_data *us,
if (lba >= maxlba) {
US_DEBUGP("Error: Requested lba %u exceeds "
"maximum %u\n", lba, maxlba);
- result = USB_STOR_TRANSPORT_ERROR;
+ result = -EIO;
break;
}
@@ -749,7 +757,7 @@ sddr09_read_data(struct us_data *us,
/* This is not really an error. It just means
that the block has never been written.
- Instead of returning USB_STOR_TRANSPORT_ERROR
+ Instead of returning an error
it is better to return all zero data. */
memset(buffer, 0, len);
@@ -764,7 +772,7 @@ sddr09_read_data(struct us_data *us,
result = sddr09_read20(us, address>>1,
pages, info->pageshift, buffer, 0);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
break;
}
@@ -830,7 +838,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
pba = sddr09_find_unused_pba(info, lba);
if (!pba) {
printk("sddr09_write_lba: Out of unused blocks\n");
- return USB_STOR_TRANSPORT_ERROR;
+ return -ENOSPC;
}
info->pba_to_lba[pba] = lba;
info->lba_to_pba[lba] = pba;
@@ -841,7 +849,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
/* Maybe it is impossible to write to PBA 1.
Fake success, but don't do anything. */
printk("sddr09: avoid writing to pba 1\n");
- return USB_STOR_TRANSPORT_GOOD;
+ return 0;
}
pagelen = (1 << info->pageshift) + (1 << CONTROL_SHIFT);
@@ -850,7 +858,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
address = (pba << (info->pageshift + info->blockshift));
result = sddr09_read22(us, address>>1, info->blocksize,
info->pageshift, blockbuffer, 0);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
return result;
/* check old contents and fill lba */
@@ -897,7 +905,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
{
unsigned char status = 0;
int result2 = sddr09_read_status(us, &status);
- if (result2 != USB_STOR_TRANSPORT_GOOD)
+ if (result2)
US_DEBUGP("sddr09_write_inplace: cannot read status\n");
else if (status != 0xc0)
US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
@@ -920,13 +928,20 @@ sddr09_write_data(struct us_data *us,
unsigned int sectors) {
struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
- unsigned int lba, page, pages;
+ unsigned int lba, maxlba, page, pages;
unsigned int pagelen, blocklen;
unsigned char *blockbuffer;
unsigned char *buffer;
unsigned int len, index, offset;
int result;
+ // Figure out the initial LBA and page
+ lba = address >> info->blockshift;
+ page = (address & info->blockmask);
+ maxlba = info->capacity >> (info->pageshift + info->blockshift);
+ if (lba >= maxlba)
+ return -EIO;
+
// blockbuffer is used for reading in the old data, overwriting
// with the new data, and performing ECC calculations
@@ -938,7 +953,7 @@ sddr09_write_data(struct us_data *us,
blockbuffer = kmalloc(blocklen, GFP_NOIO);
if (!blockbuffer) {
printk("sddr09_write_data: Out of memory\n");
- return USB_STOR_TRANSPORT_ERROR;
+ return -ENOMEM;
}
// Since we don't write the user data directly to the device,
@@ -950,14 +965,10 @@ sddr09_write_data(struct us_data *us,
if (buffer == NULL) {
printk("sddr09_write_data: Out of memory\n");
kfree(blockbuffer);
- return USB_STOR_TRANSPORT_ERROR;
+ return -ENOMEM;
}
- // Figure out the initial LBA and page
- lba = address >> info->blockshift;
- page = (address & info->blockmask);
-
- result = USB_STOR_TRANSPORT_GOOD;
+ result = 0;
index = offset = 0;
while (sectors > 0) {
@@ -967,13 +978,21 @@ sddr09_write_data(struct us_data *us,
pages = min(sectors, info->blocksize - page);
len = (pages << info->pageshift);
+ /* Not overflowing capacity? */
+ if (lba >= maxlba) {
+ US_DEBUGP("Error: Requested lba %u exceeds "
+ "maximum %u\n", lba, maxlba);
+ result = -EIO;
+ break;
+ }
+
// Get the data from the transfer buffer
usb_stor_access_xfer_buf(buffer, len, us->srb,
&index, &offset, FROM_XFER_BUF);
result = sddr09_write_lba(us, lba, page, pages,
buffer, blockbuffer);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
break;
page = 0;
@@ -1022,7 +1041,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
command[1] = LUNBITS;
result = sddr09_send_scsi_command(us, command, 12);
- if (result != USB_STOR_TRANSPORT_GOOD)
+ if (result)
return result;
result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
@@ -1031,8 +1050,7 @@ sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) {
for (i = 0; i < 4; i++)
deviceID[i] = content[i];
- return (result == USB_STOR_XFER_GOOD ?
- USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+ return (result == USB_STOR_XFER_GOOD ? 0 : -EIO);
}
static int
@@ -1041,7 +1059,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
unsigned char status;
result = sddr09_read_status(us, &status);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("sddr09_get_wp: read_status fails\n");
return result;
}
@@ -1057,7 +1075,7 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
if (status & 0x1)
US_DEBUGP(" Error");
US_DEBUGP("\n");
- return USB_STOR_TRANSPORT_GOOD;
+ return 0;
}
#if 0
@@ -1089,7 +1107,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
result = sddr09_read_deviceID(us, deviceID);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("Result of read_deviceID is %d\n", result);
printk("sddr09: could not read card info\n");
return NULL;
@@ -1200,7 +1218,7 @@ sddr09_read_map(struct us_data *us) {
us, address>>1,
min(alloc_blocks, numblocks - i),
buffer, 0);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
result = -1;
goto done;
}
@@ -1342,29 +1360,53 @@ sddr09_card_info_destructor(void *extra) {
kfree(info->pba_to_lba);
}
-static void
-sddr09_init_card_info(struct us_data *us) {
- if (!us->extra) {
- us->extra = kmalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
- if (us->extra) {
- memset(us->extra, 0, sizeof(struct sddr09_card_info));
- us->extra_destructor = sddr09_card_info_destructor;
- }
+static int
+sddr09_common_init(struct us_data *us) {
+ int result;
+
+ /* set the configuration -- STALL is an acceptable response here */
+ if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
+ US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
+ ->actconfig->desc.bConfigurationValue);
+ return -EINVAL;
+ }
+
+ result = usb_reset_configuration(us->pusb_dev);
+ US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+ if (result == -EPIPE) {
+ US_DEBUGP("-- stall on control interface\n");
+ } else if (result != 0) {
+ /* it's not a stall, but another error -- time to bail */
+ US_DEBUGP("-- Unknown error. Rejecting device\n");
+ return -EINVAL;
}
+
+ us->extra = kzalloc(sizeof(struct sddr09_card_info), GFP_NOIO);
+ if (!us->extra)
+ return -ENOMEM;
+ us->extra_destructor = sddr09_card_info_destructor;
+
+ nand_init_ecc();
+ return 0;
}
+
/*
* This is needed at a very early stage. If this is not listed in the
* unusual devices list but called from here then LUN 0 of the combo reader
* is not recognized. But I do not know what precisely these calls do.
*/
int
-sddr09_init(struct us_data *us) {
+usb_stor_sddr09_dpcm_init(struct us_data *us) {
int result;
unsigned char *data = us->iobuf;
+ result = sddr09_common_init(us);
+ if (result)
+ return result;
+
result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("sddr09_init: send_command fails\n");
return result;
}
@@ -1373,7 +1415,7 @@ sddr09_init(struct us_data *us) {
// get 07 02
result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("sddr09_init: 2nd send_command fails\n");
return result;
}
@@ -1382,7 +1424,7 @@ sddr09_init(struct us_data *us) {
// get 07 00
result = sddr09_request_sense(us, data, 18);
- if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) {
+ if (result == 0 && data[2] != 0) {
int j;
for (j=0; j<18; j++)
printk(" %02X", data[j]);
@@ -1398,7 +1440,7 @@ sddr09_init(struct us_data *us) {
// test unit ready
- return USB_STOR_TRANSPORT_GOOD; /* not result */
+ return 0; /* not result */
}
/*
@@ -1427,13 +1469,6 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
};
info = (struct sddr09_card_info *)us->extra;
- if (!info) {
- nand_init_ecc();
- sddr09_init_card_info(us);
- info = (struct sddr09_card_info *)us->extra;
- if (!info)
- return USB_STOR_TRANSPORT_ERROR;
- }
if (srb->cmnd[0] == REQUEST_SENSE && havefakesense) {
/* for a faked command, we have to follow with a faked sense */
@@ -1536,7 +1571,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("READ_10: read page %d pagect %d\n",
page, pages);
- return sddr09_read_data(us, page, pages);
+ result = sddr09_read_data(us, page, pages);
+ return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+ USB_STOR_TRANSPORT_ERROR);
}
if (srb->cmnd[0] == WRITE_10) {
@@ -1549,7 +1586,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("WRITE_10: write page %d pagect %d\n",
page, pages);
- return sddr09_write_data(us, page, pages);
+ result = sddr09_write_data(us, page, pages);
+ return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
+ USB_STOR_TRANSPORT_ERROR);
}
/* catch-all for all other commands, except
@@ -1575,10 +1614,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
result = sddr09_send_scsi_command(us, srb->cmnd, 12);
- if (result != USB_STOR_TRANSPORT_GOOD) {
+ if (result) {
US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
"returns %d\n", result);
- return result;
+ return USB_STOR_TRANSPORT_ERROR;
}
if (srb->request_bufflen == 0)
@@ -1606,3 +1645,10 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
return USB_STOR_TRANSPORT_GOOD;
}
+/*
+ * Initialization routine for the sddr09 subdriver
+ */
+int
+usb_stor_sddr09_init(struct us_data *us) {
+ return sddr09_common_init(us);
+}
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index c9d78d6188b1..c03089a9ec38 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -31,18 +31,7 @@
extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
-struct sddr09_card_info {
- unsigned long capacity; /* Size of card in bytes */
- int pagesize; /* Size of page in bytes */
- int pageshift; /* log2 of pagesize */
- int blocksize; /* Size of block in pages */
- int blockshift; /* log2 of blocksize */
- int blockmask; /* 2^blockshift - 1 */
- int *lba_to_pba; /* logical to physical map */
- int *pba_to_lba; /* physical to logical map */
- int lbact; /* number of available pages */
- int flags;
-#define SDDR09_WP 1 /* write protected */
-};
+extern int usb_stor_sddr09_dpcm_init(struct us_data *us);
+extern int usb_stor_sddr09_init(struct us_data *us);
#endif
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 0a362cc781ad..633a715850a4 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -41,39 +41,8 @@
#ifndef _TRANSPORT_H_
#define _TRANSPORT_H_
-#include <linux/config.h>
#include <linux/blkdev.h>
-/* Protocols */
-
-#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
-#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
-#define US_PR_BULK 0x50 /* bulk only */
-#ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */
-#endif
-#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#define US_PR_FREECOM 0xf1 /* Freecom */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
-#endif
-
-#define US_PR_DEVICE 0xff /* Use device's value */
-
/*
* Bulk only data structures
*/
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f5f47a34b168..dc301e567cfc 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -79,13 +79,6 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
US_SC_8070, US_PR_USBAT, 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.
@@ -96,6 +89,13 @@ UNUSUAL_DEV( 0x0409, 0x0040, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
+/* 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 ),
+
/* 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.
@@ -187,6 +187,14 @@ UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
+/* Patch for Nikon coolpix 2000
+ * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/
+UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010,
+ "NIKON",
+ "NIKON DSC E2000",
+ US_SC_DEVICE, US_PR_DEVICE,NULL,
+ US_FL_NOT_LOCKABLE ),
+
/* BENQ DC5330
* Reported by Manuel Fombuena <mfombuena@ya.com> and
* Frank Copeland <fjc@thingy.apana.org.au> */
@@ -276,14 +284,14 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
"Sandisk",
"ImageMate SDDR09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN ),
+ US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+ 0),
/* This entry is from Andries.Brouwer@cwi.nl */
UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208,
"SCM Microsystems",
"eUSB SmartMedia / CompactFlash Adapter",
- US_SC_SCSI, US_PR_DPCM_USB, sddr09_init,
+ US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
0),
#endif
@@ -527,6 +535,13 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999,
"Silicon Media R/W",
US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102,
+ "Fujifilm",
+ "DPC-R1 (Alauda)",
+ US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
/* Fabrizio Fellini <fello@libero.it> */
UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210,
"Fujifilm",
@@ -673,8 +688,8 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
"Olympus",
"Camedia MAUSB-2",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN ),
+ US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+ 0),
#endif
/* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
@@ -739,8 +754,8 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999,
"Sandisk",
"ImageMate SDDR-09",
- US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
- US_FL_SINGLE_LUN ),
+ US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
+ 0),
#endif
#ifdef CONFIG_USB_STORAGE_FREECOM
@@ -776,6 +791,13 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100,
US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ),
#endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102,
+ "Olympus",
+ "MAUSB-10 (Alauda)",
+ US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ),
+#endif
+
#ifdef CONFIG_USB_STORAGE_DATAFAB
UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
"Datafab",
@@ -1134,3 +1156,27 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
US_SC_SCSI, US_PR_SDDR55, NULL,
US_FL_SINGLE_LUN),
#endif
+
+/* Control/Bulk transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+
+/* Control/Bulk/Interrupt transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+
+/* Bulk-only transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3847ebed2aa4..dbcf23980ff1 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -94,6 +94,9 @@
#ifdef CONFIG_USB_STORAGE_ONETOUCH
#include "onetouch.h"
#endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+#include "alauda.h"
+#endif
/* Some informational data */
MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -112,49 +115,33 @@ static atomic_t total_threads = ATOMIC_INIT(0);
static DECLARE_COMPLETION(threads_gone);
-/* The entries in this table, except for final ones here
- * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
- * line for line with the entries of us_unsuaul_dev_list[].
+/*
+ * The entries in this table correspond, line for line,
+ * with the entries of us_unusual_dev_list[].
*/
+#ifndef CONFIG_USB_LIBUSUAL
#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
vendorName, productName,useProtocol, useTransport, \
initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+ .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+ .driver_info = (USB_US_TYPE_STOR<<24) }
static struct usb_device_id storage_usb_ids [] = {
# include "unusual_devs.h"
#undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
-
- /* Bulk-only transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-
+#undef USUAL_DEV
/* Terminating entry */
{ }
};
MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */
/* This is the list of devices we recognize, along with their flag data */
@@ -167,7 +154,6 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
* are free to use as many characters as you like.
*/
-#undef UNUSUAL_DEV
#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
vendor_name, product_name, use_protocol, use_transport, \
init_function, Flags) \
@@ -177,53 +163,18 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
.useProtocol = use_protocol, \
.useTransport = use_transport, \
.initFunction = init_function, \
- .flags = Flags, \
+}
+
+#define USUAL_DEV(use_protocol, use_transport, use_type) \
+{ \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
}
static struct us_unusual_dev us_unusual_dev_list[] = {
# include "unusual_devs.h"
# undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_CB},
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_CBI},
-
- /* Bulk-only transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_BULK},
+# undef USUAL_DEV
/* Terminating entry */
{ NULL }
@@ -240,6 +191,8 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
down(&us->dev_semaphore);
US_DEBUGP("%s\n", __FUNCTION__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_SUSPEND);
iface->dev.power.power_state.event = message.event;
/* When runtime PM is working, we'll set a flag to indicate
@@ -256,6 +209,8 @@ static int storage_resume(struct usb_interface *iface)
down(&us->dev_semaphore);
US_DEBUGP("%s\n", __FUNCTION__);
+ if (us->suspend_resume_hook)
+ (us->suspend_resume_hook)(us, US_RESUME);
iface->dev.power.power_state.event = PM_EVENT_ON;
up(&us->dev_semaphore);
@@ -484,14 +439,20 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
return 0;
}
+/* Find an unusual_dev descriptor (always succeeds in the current code) */
+static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
+{
+ const int id_index = id - storage_usb_ids;
+ return &us_unusual_dev_list[id_index];
+}
+
/* Get the unusual_devs entries and the string descriptors */
-static void get_device_info(struct us_data *us, int id_index)
+static void get_device_info(struct us_data *us, const struct usb_device_id *id)
{
struct usb_device *dev = us->pusb_dev;
struct usb_interface_descriptor *idesc =
&us->pusb_intf->cur_altsetting->desc;
- struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
- struct usb_device_id *id = &storage_usb_ids[id_index];
+ struct us_unusual_dev *unusual_dev = find_unusual(id);
/* Store the entries */
us->unusual_dev = unusual_dev;
@@ -501,7 +462,7 @@ static void get_device_info(struct us_data *us, int id_index)
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
- us->flags = unusual_dev->flags;
+ us->flags = USB_US_ORIG_FLAGS(id->driver_info);
/*
* This flag is only needed when we're in high-speed, so let's
@@ -516,7 +477,7 @@ static void get_device_info(struct us_data *us, int id_index)
* from the unusual_devs.h table.
*/
if (id->idVendor || id->idProduct) {
- static char *msgs[3] = {
+ static const char *msgs[3] = {
"an unneeded SubClass entry",
"an unneeded Protocol entry",
"unneeded SubClass and Protocol entries"};
@@ -529,7 +490,7 @@ static void get_device_info(struct us_data *us, int id_index)
if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == idesc->bInterfaceProtocol)
msg += 2;
- if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE))
+ if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x,%04x S %02x P %02x)"
" has %s in unusual_devs.h\n"
@@ -686,6 +647,15 @@ static int get_protocol(struct us_data *us)
break;
#endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+ case US_PR_ALAUDA:
+ us->transport_name = "Alauda Control/Bulk";
+ us->transport = alauda_transport;
+ us->transport_reset = usb_stor_Bulk_reset;
+ us->max_lun = 1;
+ break;
+#endif
+
default:
return -EIO;
}
@@ -921,10 +891,12 @@ static int storage_probe(struct usb_interface *intf,
{
struct Scsi_Host *host;
struct us_data *us;
- const int id_index = id - storage_usb_ids;
int result;
struct task_struct *th;
+ if (usb_usual_check_type(id, USB_US_TYPE_STOR))
+ return -ENXIO;
+
US_DEBUGP("USB Mass Storage device detected\n");
/*
@@ -957,29 +929,7 @@ static int storage_probe(struct usb_interface *intf,
* of the match from the usb_device_id table, so we can find the
* corresponding entry in the private table.
*/
- get_device_info(us, id_index);
-
-#ifdef CONFIG_USB_STORAGE_SDDR09
- if (us->protocol == US_PR_EUSB_SDDR09 ||
- us->protocol == US_PR_DPCM_USB) {
- /* set the configuration -- STALL is an acceptable response here */
- if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
- US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
- ->actconfig->desc.bConfigurationValue);
- goto BadDevice;
- }
- result = usb_reset_configuration(us->pusb_dev);
-
- US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
- if (result == -EPIPE) {
- US_DEBUGP("-- stall on control interface\n");
- } else if (result != 0) {
- /* it's not a stall, but another error -- time to bail */
- US_DEBUGP("-- Unknown error. Rejecting device\n");
- goto BadDevice;
- }
- }
-#endif
+ get_device_info(us, id);
/* Get the transport, protocol, and pipe settings */
result = get_transport(us);
@@ -1044,7 +994,6 @@ static void storage_disconnect(struct usb_interface *intf)
***********************************************************************/
static struct usb_driver usb_storage_driver = {
- .owner = THIS_MODULE,
.name = "usb-storage",
.probe = storage_probe,
.disconnect = storage_disconnect,
@@ -1062,9 +1011,10 @@ static int __init usb_stor_init(void)
/* register the driver, return usb_register return code if error */
retval = usb_register(&usb_storage_driver);
- if (retval == 0)
+ if (retval == 0) {
printk(KERN_INFO "USB Mass Storage support registered.\n");
-
+ usb_usual_set_present(USB_US_TYPE_STOR);
+ }
return retval;
}
@@ -1088,6 +1038,8 @@ static void __exit usb_stor_exit(void)
wait_for_completion(&threads_gone);
atomic_dec(&total_threads);
}
+
+ usb_usual_clear_present(USB_US_TYPE_STOR);
}
module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 98b09711a739..7259fd1f6b0d 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -45,6 +45,7 @@
#define _USB_H_
#include <linux/usb.h>
+#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
@@ -63,38 +64,8 @@ struct us_unusual_dev {
__u8 useProtocol;
__u8 useTransport;
int (*initFunction)(struct us_data *);
- unsigned int flags;
};
-/*
- * Static flag definitions. We use this roundabout technique so that the
- * proc_info() routine can automatically display a message for each flag.
- */
-#define US_DO_ALL_FLAGS \
- US_FLAG(SINGLE_LUN, 0x00000001) \
- /* allow access to only LUN 0 */ \
- US_FLAG(NEED_OVERRIDE, 0x00000002) \
- /* unusual_devs entry is necessary */ \
- US_FLAG(SCM_MULT_TARG, 0x00000004) \
- /* supports multiple targets */ \
- US_FLAG(FIX_INQUIRY, 0x00000008) \
- /* INQUIRY response needs faking */ \
- US_FLAG(FIX_CAPACITY, 0x00000010) \
- /* READ CAPACITY response too big */ \
- US_FLAG(IGNORE_RESIDUE, 0x00000020) \
- /* reported residue is wrong */ \
- US_FLAG(BULK32, 0x00000040) \
- /* Uses 32-byte CBW length */ \
- US_FLAG(NOT_LOCKABLE, 0x00000080) \
- /* PREVENT/ALLOW not supported */ \
- US_FLAG(GO_SLOW, 0x00000100) \
- /* Need delay after Command phase */ \
- US_FLAG(NO_WP_DETECT, 0x00000200) \
- /* Don't check for write-protect */ \
-
-#define US_FLAG(name, value) US_FL_##name = value ,
-enum { US_DO_ALL_FLAGS };
-#undef US_FLAG
/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
@@ -122,7 +93,11 @@ enum { US_DO_ALL_FLAGS };
typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
typedef int (*trans_reset)(struct us_data*);
typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
-typedef void (*extra_data_destructor)(void *); /* extra data destructor */
+typedef void (*extra_data_destructor)(void *); /* extra data destructor */
+typedef void (*pm_hook)(struct us_data *, int); /* power management hook */
+
+#define US_SUSPEND 0
+#define US_RESUME 1
/* we allocate one of these for every device that we remember */
struct us_data {
@@ -178,6 +153,9 @@ struct us_data {
/* subdriver information */
void *extra; /* Any extra data */
extra_data_destructor extra_destructor;/* extra data destructor */
+#ifdef CONFIG_PM
+ pm_hook suspend_resume_hook;
+#endif
};
/* Convert between us_data and the corresponding Scsi_Host */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 6c3a53f8f26c..5d02f16b7d0e 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -39,10 +39,15 @@ MODULE_DEVICE_TABLE (usb, skel_table);
/* Get a minor range for your devices from the usb maintainer */
#define USB_SKEL_MINOR_BASE 192
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER ( PAGE_SIZE - 512 )
+#define WRITES_IN_FLIGHT 8
+
/* Structure to hold all of our device specific stuff */
struct usb_skel {
struct usb_device * udev; /* the usb device for this device */
struct usb_interface * interface; /* the interface for this device */
+ struct semaphore limit_sem; /* limiting the number of writes in progress */
unsigned char * bulk_in_buffer; /* the buffer to receive data */
size_t bulk_in_size; /* the size of the receive buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
@@ -152,6 +157,7 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
+ up(&dev->limit_sem);
}
static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
@@ -160,6 +166,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
int retval = 0;
struct urb *urb = NULL;
char *buf = NULL;
+ size_t writesize = min(count, (size_t)MAX_TRANSFER);
dev = (struct usb_skel *)file->private_data;
@@ -167,6 +174,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
if (count == 0)
goto exit;
+ /* limit the number of URBs in flight to stop a user from using up all RAM */
+ if (down_interruptible(&dev->limit_sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
@@ -174,13 +187,13 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
goto error;
}
- buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+ buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}
- if (copy_from_user(buf, user_buffer, count)) {
+ if (copy_from_user(buf, user_buffer, writesize)) {
retval = -EFAULT;
goto error;
}
@@ -188,7 +201,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
/* initialize the urb properly */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
- buf, count, skel_write_bulk_callback, dev);
+ buf, writesize, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* send the data out the bulk port */
@@ -202,11 +215,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
usb_free_urb(urb);
exit:
- return count;
+ return writesize;
error:
- usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+ usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
usb_free_urb(urb);
+ up(&dev->limit_sem);
return retval;
}
@@ -238,13 +252,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
int retval = -ENOMEM;
/* allocate memory for our device state and initialize it */
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
err("Out of memory");
goto error;
}
- memset(dev, 0x00, sizeof(*dev));
kref_init(&dev->kref);
+ sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
@@ -330,7 +344,6 @@ static void skel_disconnect(struct usb_interface *interface)
}
static struct usb_driver skel_driver = {
- .owner = THIS_MODULE,
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 3b0ddc55236b..78488bb41aeb 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -102,8 +102,7 @@ static int mc68x328fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
-static int mc68x328fb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma);
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
static struct fb_ops mc68x328fb_ops = {
.fb_check_var = mc68x328fb_check_var,
@@ -398,8 +397,7 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var,
* Most drivers don't need their own mmap function
*/
-static int mc68x328fb_mmap(struct fb_info *info, struct file *file,
- struct vm_area_struct *vma)
+static int mc68x328fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
#ifndef MMU
/* this is uClinux (no MMU) specific code */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc8e3bf5001b..3e153d313bb0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -993,12 +993,6 @@ config FB_ATY_GENERIC_LCD
Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility,
Rage XC, or Rage XL chipset.
-config FB_ATY_XL_INIT
- bool "Rage XL No-BIOS Init support"
- depends on FB_ATY_CT
- help
- Say Y here to support booting a Rage XL without BIOS support.
-
config FB_ATY_GX
bool "Mach64 GX support" if PCI
depends on FB_ATY
@@ -1151,7 +1145,7 @@ config FB_VOODOO1
config FB_CYBLA
tristate "Cyberblade/i1 support"
- depends on FB && PCI
+ depends on FB && PCI && X86_32 && !64BIT
select FB_CFB_IMAGEBLIT
select VIDEO_SELECT
---help---
@@ -1376,7 +1370,7 @@ config FB_PXA
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 vfb. If you want to compile it as a module,
+ module will be called pxafb. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
@@ -1409,7 +1403,7 @@ config FB_W100
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 vfb. If you want to compile it as a module,
+ module will be called w100fb. If you want to compile it as a module,
say M here and read <file:Documentation/modules.txt>.
If unsure, say N.
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 750cebb18306..b058273527bb 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -883,7 +883,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
* Note that we are entered with the kernel locked.
*/
static int
-acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+acornfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
unsigned long off, start;
u32 len;
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index a3c2c45e29e0..b2187175d03f 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -21,12 +21,11 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/list.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/clk.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
-#include <asm/hardware/clock.h>
-
-#include <asm/hardware/amba_clcd.h>
#define to_clcd(info) container_of(info, struct clcd_fb, fb)
@@ -308,7 +307,7 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info)
return 0;
}
-static int clcdfb_mmap(struct fb_info *info, struct file *file,
+static int clcdfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct clcd_fb *fb = to_clcd(info);
@@ -346,10 +345,6 @@ static int clcdfb_register(struct clcd_fb *fb)
goto out;
}
- ret = clk_use(fb->clk);
- if (ret)
- goto free_clk;
-
fb->fb.fix.mmio_start = fb->dev->res.start;
fb->fb.fix.mmio_len = SZ_4K;
@@ -357,7 +352,7 @@ static int clcdfb_register(struct clcd_fb *fb)
if (!fb->regs) {
printk(KERN_ERR "CLCD: unable to remap registers\n");
ret = -ENOMEM;
- goto unuse_clk;
+ goto free_clk;
}
fb->fb.fbops = &clcdfb_ops;
@@ -427,8 +422,6 @@ static int clcdfb_register(struct clcd_fb *fb)
printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret);
iounmap(fb->regs);
- unuse_clk:
- clk_unuse(fb->clk);
free_clk:
clk_put(fb->clk);
out:
@@ -489,7 +482,6 @@ static int clcdfb_remove(struct amba_device *dev)
clcdfb_disable(fb);
unregister_framebuffer(&fb->fb);
iounmap(fb->regs);
- clk_unuse(fb->clk);
clk_put(fb->clk);
fb->board->remove(fb);
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index d549e215f3c5..3033c72dea20 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -590,6 +590,8 @@ static u_short maxfmode, chipset;
#define highw(x) ((u_long)(x)>>16 & 0xffff)
#define loww(x) ((u_long)(x) & 0xffff)
+#define custom amiga_custom
+
#define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
#define VBlankOff() custom.intena = IF_COPER
@@ -1129,9 +1131,7 @@ static void amifb_copyarea(struct fb_info *info,
const struct fb_copyarea *region);
static void amifb_imageblit(struct fb_info *info,
const struct fb_image *image);
-static int amifb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
+static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
/*
@@ -1164,8 +1164,8 @@ static void ami_update_display(void);
static void ami_init_display(void);
static void ami_do_blank(void);
static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data);
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data);
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
static int ami_get_cursorstate(struct fb_cursorstate *state);
static int ami_set_cursorstate(struct fb_cursorstate *state);
static void ami_set_sprite(void);
@@ -2170,15 +2170,15 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
* Amiga Frame Buffer Specific ioctls
*/
-static int amifb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int amifb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
union {
struct fb_fix_cursorinfo fix;
struct fb_var_cursorinfo var;
struct fb_cursorstate state;
} crsr;
+ void __user *argp = (void __user *)arg;
int i;
switch (cmd) {
@@ -2186,33 +2186,32 @@ static int amifb_ioctl(struct inode *inode, struct file *file,
i = ami_get_fix_cursorinfo(&crsr.fix);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.fix,
+ return copy_to_user(argp, &crsr.fix,
sizeof(crsr.fix)) ? -EFAULT : 0;
case FBIOGET_VCURSORINFO:
i = ami_get_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo *)arg)->data);
+ ((struct fb_var_cursorinfo __user *)arg)->data);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.var,
+ return copy_to_user(argp, &crsr.var,
sizeof(crsr.var)) ? -EFAULT : 0;
case FBIOPUT_VCURSORINFO:
- if (copy_from_user(&crsr.var, (void *)arg,
- sizeof(crsr.var)))
+ if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
return -EFAULT;
return ami_set_var_cursorinfo(&crsr.var,
- ((struct fb_var_cursorinfo *)arg)->data);
+ ((struct fb_var_cursorinfo __user *)arg)->data);
case FBIOGET_CURSORSTATE:
i = ami_get_cursorstate(&crsr.state);
if (i)
return i;
- return copy_to_user((void *)arg, &crsr.state,
+ return copy_to_user(argp, &crsr.state,
sizeof(crsr.state)) ? -EFAULT : 0;
case FBIOPUT_CURSORSTATE:
- if (copy_from_user(&crsr.state, (void *)arg,
+ if (copy_from_user(&crsr.state, argp,
sizeof(crsr.state)))
return -EFAULT;
return ami_set_cursorstate(&crsr.state);
@@ -3325,7 +3324,7 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
return 0;
}
-static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
+static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
{
struct amifb_par *par = &currentpar;
register u_short *lspr, *sspr;
@@ -3347,14 +3346,14 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
var->yspot = par->crsr.spot_y;
if (size > var->height*var->width)
return -ENAMETOOLONG;
- if (!access_ok(VERIFY_WRITE, (void *)data, size))
+ if (!access_ok(VERIFY_WRITE, data, size))
return -EFAULT;
delta = 1<<par->crsr.fmode;
lspr = lofsprite + (delta<<1);
if (par->bplcon0 & BPC0_LACE)
sspr = shfsprite + (delta<<1);
else
- sspr = 0;
+ sspr = NULL;
for (height = (short)var->height-1; height >= 0; height--) {
bits = 0; words = delta; datawords = 0;
for (width = (short)var->width-1; width >= 0; width--) {
@@ -3400,7 +3399,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
return 0;
}
-static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
+static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
{
struct amifb_par *par = &currentpar;
register u_short *lspr, *sspr;
@@ -3427,7 +3426,7 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
return -EINVAL;
if (!var->height)
return -EINVAL;
- if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height))
+ if (!access_ok(VERIFY_READ, data, var->width*var->height))
return -EFAULT;
delta = 1<<fmode;
lofsprite = shfsprite = (u_short *)spritememory;
@@ -3442,13 +3441,13 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data)
if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
return -EINVAL;
memset(lspr, 0, (var->height+2)<<fmode<<2);
- sspr = 0;
+ sspr = NULL;
}
for (height = (short)var->height-1; height >= 0; height--) {
bits = 16; words = delta; datawords = 0;
for (width = (short)var->width-1; width >= 0; width--) {
unsigned long tdata = 0;
- get_user(tdata, (char *)data);
+ get_user(tdata, data);
data++;
#ifdef __mc68000__
asm volatile (
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 2784f0a9d693..df8e5667b348 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -366,7 +366,8 @@ static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
}
}
-void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void arcfb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
{
struct arcfb_par *par = info->par;
@@ -376,7 +377,8 @@ void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
}
-void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void arcfb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
{
struct arcfb_par *par = info->par;
@@ -386,7 +388,7 @@ void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
}
-void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct arcfb_par *par = info->par;
@@ -397,9 +399,8 @@ void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
image->height);
}
-static int arcfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int arcfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
struct arcfb_par *par = info->par;
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index c64de59398f4..69f75547865d 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -549,7 +549,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
if (!request_mem_region(addr, size, "asiliantfb"))
return -EBUSY;
- p = framebuffer_alloc(sizeof(u32) * 256, &dp->dev);
+ p = framebuffer_alloc(sizeof(u32) * 16, &dp->dev);
if (!p) {
release_mem_region(addr, size);
return -ENOMEM;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 15ec1295bc29..e69ab65f7843 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -2571,8 +2571,7 @@ atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
}
static int
-atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, int con, struct fb_info *info)
+atafb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
#ifdef FBCMD_GET_CURRENTPAR
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 9dec96249ffb..18521397a6e3 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -5,7 +5,6 @@ obj-$(CONFIG_FB_RADEON) += radeonfb.o
atyfb-y := atyfb_base.o mach64_accel.o mach64_cursor.o
atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o
atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o
-atyfb-$(CONFIG_FB_ATY_XL_INIT) += xlinit.o
atyfb-objs := $(atyfb-y)
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e686185a076d..bfc8a93b2c73 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -431,8 +431,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int aty128fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *fb);
static int aty128fb_blank(int blank, struct fb_info *fb);
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info);
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, unsigned long arg);
static int aty128fb_sync(struct fb_info *info);
/*
@@ -2108,8 +2107,7 @@ static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/* in param: u32* backlight value: 0 to 15 */
#define FBIO_ATY128_SET_MIRROR _IOW('@', 2, __u32)
-static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct aty128fb_par *par = info->par;
u32 value;
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index 09de173c1164..e9b7a64c1ac4 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -50,6 +50,7 @@ struct pll_info {
int sclk, mclk, mclk_pm, xclk;
int ref_div;
int ref_clk;
+ int ecp_max;
};
typedef struct {
@@ -354,6 +355,5 @@ static inline void wait_for_idle(struct atyfb_par *par)
extern void aty_reset_engine(const struct atyfb_par *par);
extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
-extern int atyfb_xl_init(struct fb_info *info);
extern void aty_st_pll_ct(int offset, u8 val, const struct atyfb_par *par);
extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 08edbfcfca58..485be386a8ff 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -109,9 +109,18 @@
#define GUI_RESERVE (1 * PAGE_SIZE)
/* FIXME: remove the FAIL definition */
-#define FAIL(msg) do { printk(KERN_CRIT "atyfb: " msg "\n"); return -EINVAL; } while (0)
-#define FAIL_MAX(msg, x, _max_) do { if(x > _max_) { printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); return -EINVAL; } } while (0)
-
+#define FAIL(msg) do { \
+ if (!(var->activate & FB_ACTIVATE_TEST)) \
+ printk(KERN_CRIT "atyfb: " msg "\n"); \
+ return -EINVAL; \
+} while (0)
+#define FAIL_MAX(msg, x, _max_) do { \
+ if (x > _max_) { \
+ if (!(var->activate & FB_ACTIVATE_TEST)) \
+ printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \
+ return -EINVAL; \
+ } \
+} while (0)
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)
#else
@@ -229,13 +238,12 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
static int atyfb_blank(int blank, struct fb_info *info);
-static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info);
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
extern void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
extern void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
extern void atyfb_imageblit(struct fb_info *info, const struct fb_image *image);
#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);
#endif
static int atyfb_sync(struct fb_info *info);
@@ -340,6 +348,7 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)
#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)
+/* FIXME what is this chip? */
#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)
/* make sets shorter */
@@ -359,58 +368,60 @@ static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
static struct {
u16 pci_id;
const char *name;
- int pll, mclk, xclk;
+ int pll, mclk, xclk, ecp_max;
u32 features;
} aty_chips[] __devinitdata = {
#ifdef CONFIG_FB_ATY_GX
/* Mach64 GX */
- { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
- { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, ATI_CHIP_88800CX },
+ { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX },
+ { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },
#endif /* CONFIG_FB_ATY_GX */
#ifdef CONFIG_FB_ATY_CT
- { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, ATI_CHIP_264CT },
- { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, ATI_CHIP_264ET },
- { PCI_CHIP_MACH64VT, "ATI264VT? (Mach64 VT)", 170, 67, 67, ATI_CHIP_264VT },
- { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, ATI_CHIP_264GT },
- /* FIXME { ...ATI_264GU, maybe ATI_CHIP_264GTDVD }, */
- { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GTB)", 200, 67, 67, ATI_CHIP_264GTB },
- { PCI_CHIP_MACH64VU, "ATI264VTB (Mach64 VU)", 200, 67, 67, ATI_CHIP_264VT3 },
-
- { PCI_CHIP_MACH64LT, "3D RAGE LT (Mach64 LT)", 135, 63, 63, ATI_CHIP_264LT },
- /* FIXME chipset maybe ATI_CHIP_264LTPRO ? */
- { PCI_CHIP_MACH64LG, "3D RAGE LT-G (Mach64 LG)", 230, 63, 63, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
-
- { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, ATI_CHIP_264VT4 },
-
- { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, ATI_CHIP_264GT2C },
- { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, ATI_CHIP_264GT2C },
-
- { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
- { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, ATI_CHIP_264GTPRO },
- { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, ATI_CHIP_264GTPRO },
-
- { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
- { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
- { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, ATI_CHIP_264LTPRO },
-
- { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GN, "3D RAGE XL (Mach64 GN, AGP)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66/BGA)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33MHz)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GL, "3D RAGE XL (Mach64 GL, PCI)", 230, 83, 63, ATI_CHIP_264XL },
- { PCI_CHIP_MACH64GS, "3D RAGE XL (Mach64 GS, PCI)", 230, 83, 63, ATI_CHIP_264XL },
-
- { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
- { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT },
+ { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET },
+
+ /* FIXME what is this chip? */
+ { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT },
+
+ { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT },
+ { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT },
+
+ { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 },
+ { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB },
+
+ { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 },
+
+ { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 },
+
+ { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+ { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C },
+
+ { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE },
+ { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+ { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO },
+
+ { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+ { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+ { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO },
+
+ { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL },
+ { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL },
+ { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL },
+
+ { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
+ { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },
#endif /* CONFIG_FB_ATY_CT */
};
@@ -431,6 +442,7 @@ static int __devinit correct_chipset(struct atyfb_par *par)
par->pll_limits.pll_max = aty_chips[i].pll;
par->pll_limits.mclk = aty_chips[i].mclk;
par->pll_limits.xclk = aty_chips[i].xclk;
+ par->pll_limits.ecp_max = aty_chips[i].ecp_max;
par->features = aty_chips[i].features;
chip_id = aty_ld_le32(CONFIG_CHIP_ID, par);
@@ -450,39 +462,63 @@ static int __devinit correct_chipset(struct atyfb_par *par)
#endif
#ifdef CONFIG_FB_ATY_CT
case PCI_CHIP_MACH64VT:
- rev &= 0xc7;
- if(rev == 0x00) {
- name = "ATI264VTA3 (Mach64 VT)";
- par->pll_limits.pll_max = 170;
- par->pll_limits.mclk = 67;
- par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VT;
- } else if(rev == 0x40) {
- name = "ATI264VTA4 (Mach64 VT)";
+ switch (rev & 0x07) {
+ case 0x00:
+ switch (rev & 0xc0) {
+ case 0x00:
+ name = "ATI264VT (A3) (Mach64 VT)";
+ par->pll_limits.pll_max = 170;
+ par->pll_limits.mclk = 67;
+ par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT;
+ break;
+ case 0x40:
+ name = "ATI264VT2 (A4) (Mach64 VT)";
+ par->pll_limits.pll_max = 200;
+ par->pll_limits.mclk = 67;
+ par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
+ break;
+ }
+ break;
+ case 0x01:
+ name = "ATI264VT3 (B1) (Mach64 VT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;
- } else {
- name = "ATI264VTB (Mach64 VT)";
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VTB;
+ break;
+ case 0x02:
+ name = "ATI264VT3 (B2) (Mach64 VT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
- par->features = ATI_CHIP_264VTB;
+ par->pll_limits.ecp_max = 80;
+ par->features = ATI_CHIP_264VT3;
+ break;
}
break;
case PCI_CHIP_MACH64GT:
- rev &= 0x07;
- if(rev == 0x01) {
+ switch (rev & 0x07) {
+ case 0x01:
+ name = "3D RAGE II (Mach64 GT)";
par->pll_limits.pll_max = 170;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 80;
par->features = ATI_CHIP_264GTB;
- } else if(rev == 0x02) {
+ break;
+ case 0x02:
+ name = "3D RAGE II+ (Mach64 GT)";
par->pll_limits.pll_max = 200;
par->pll_limits.mclk = 67;
par->pll_limits.xclk = 67;
+ par->pll_limits.ecp_max = 100;
par->features = ATI_CHIP_264GTB;
+ break;
}
break;
#endif
@@ -692,7 +728,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |
(SHADOW_EN | SHADOW_RW_EN), par);
- DPRINTK("set secondary CRT to %ix%i %c%c\n",
+ DPRINTK("set shadow CRT to %ix%i %c%c\n",
((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),
(crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');
@@ -840,11 +876,14 @@ static int aty_var_to_crtc(const struct fb_info *info,
know if one is connected. So it's better to fail then.
*/
if (crtc->lcd_gen_cntl & CRT_ON) {
- PRINTKI("Disable lcd panel, because video mode does not fit.\n");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKI("Disable LCD panel, because video mode does not fit.\n");
crtc->lcd_gen_cntl &= ~LCD_ON;
/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/
} else {
- FAIL("Video mode exceeds size of lcd panel.\nConnect this computer to a conventional monitor if you really need this mode.");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");
+ return -EINVAL;
}
}
}
@@ -858,9 +897,9 @@ static int aty_var_to_crtc(const struct fb_info *info,
vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);
/* This is horror! When we simulate, say 640x480 on an 800x600
- lcd monitor, the CRTC should be programmed 800x600 values for
+ LCD monitor, the CRTC should be programmed 800x600 values for
the non visible part, but 640x480 for the visible part.
- This code has been tested on a laptop with it's 1400x1050 lcd
+ This code has been tested on a laptop with it's 1400x1050 LCD
monitor and a conventional monitor both switched on.
Tested modes: 1280x1024, 1152x864, 1024x768, 800x600,
works with little glitches also with DOUBLESCAN modes
@@ -955,16 +994,6 @@ static int aty_var_to_crtc(const struct fb_info *info,
vdisplay = yres;
if(vmode & FB_VMODE_DOUBLE)
vdisplay <<= 1;
- if(vmode & FB_VMODE_INTERLACED) {
- vdisplay >>= 1;
-
- /* The prefered mode for the lcd is not interlaced, so disable it if
- it was enabled. For doublescan there is no problem, because we can
- compensate for it in the hardware stretching (we stretch half as much)
- */
- vmode &= ~FB_VMODE_INTERLACED;
- /*crtc->gen_cntl &= ~CRTC_INTERLACE_EN;*/
- }
crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH);
crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 |
/*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/
@@ -980,7 +1009,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
crtc->horz_stretching &=
~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO |
HORZ_STRETCH_MODE | HORZ_STRETCH_EN);
- if (xres < par->lcd_width) {
+ if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) {
do {
/*
* The horizontal blender misbehaves when HDisplay is less than a
@@ -1042,7 +1071,7 @@ static int aty_var_to_crtc(const struct fb_info *info,
} while (0);
}
- if (vdisplay < par->lcd_height) {
+ if (vdisplay < par->lcd_height && crtc->lcd_gen_cntl & LCD_ON) {
crtc->vert_stretching = (VERT_STRETCH_USE0 | VERT_STRETCH_EN |
(((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0));
@@ -1065,9 +1094,8 @@ static int aty_var_to_crtc(const struct fb_info *info,
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
if (M64_HAS(MAGIC_FIFO)) {
- /* Not VTB/GTB */
- /* FIXME: magic FIFO values */
- crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC2_PIX_WIDTH);
+ /* FIXME: display FIFO low watermark values */
+ crtc->gen_cntl |= (aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_FIFO_LWM);
}
crtc->dp_pix_width = dp_pix_width;
crtc->dp_chain_mask = dp_chain_mask;
@@ -1184,7 +1212,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *va
var->transp.length = 8;
break;
default:
- FAIL("Invalid pixel width");
+ PRINTKE("Invalid pixel width\n");
+ return -EINVAL;
}
/* output */
@@ -1241,7 +1270,8 @@ static int atyfb_set_par(struct fb_info *info)
pixclock = atyfb_get_pixclock(var, par);
if (pixclock == 0) {
- FAIL("Invalid pixclock");
+ PRINTKE("Invalid pixclock\n");
+ return -EINVAL;
} else {
if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll)))
return err;
@@ -1446,7 +1476,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
pixclock = atyfb_get_pixclock(var, par);
if (pixclock == 0) {
- FAIL("Invalid pixclock");
+ if (!(var->activate & FB_ACTIVATE_TEST))
+ PRINTKE("Invalid pixclock\n");
+ return -EINVAL;
} else {
if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))
return err;
@@ -1706,8 +1738,7 @@ struct atyclk {
#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
#endif
-static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
#ifdef __sparc__
@@ -1812,7 +1843,7 @@ static int atyfb_sync(struct fb_info *info)
}
#ifdef __sparc__
-static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
unsigned int size, page, map_size = 0;
@@ -2291,10 +2322,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
par->dac_ops = &aty_dac_ct;
par->pll_ops = &aty_pll_ct;
par->bus_type = PCI;
-#ifdef CONFIG_FB_ATY_XL_INIT
- if (IS_XL(par->pci_id))
- atyfb_xl_init(info);
-#endif
par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07);
ramname = aty_ct_ram[par->ram_type];
/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
@@ -2638,16 +2665,16 @@ static int __init store_video_par(char *video_str, unsigned char m64_num)
static int atyfb_blank(int blank, struct fb_info *info)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
- u8 gen_cntl;
+ u32 gen_cntl;
if (par->lock_blank || par->asleep)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
+ if ((_machine == _MACH_Pmac) && blank > FB_BLANK_NORMAL)
set_backlight_enable(0);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
- if (par->lcd_table && blank &&
+ if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
pm &= ~PWR_BLON;
@@ -2655,31 +2682,31 @@ static int atyfb_blank(int blank, struct fb_info *info)
}
#endif
- gen_cntl = aty_ld_8(CRTC_GEN_CNTL, par);
+ gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);
switch (blank) {
case FB_BLANK_UNBLANK:
- gen_cntl &= ~(0x4c);
+ gen_cntl &= ~0x400004c;
break;
case FB_BLANK_NORMAL:
- gen_cntl |= 0x40;
+ gen_cntl |= 0x4000040;
break;
case FB_BLANK_VSYNC_SUSPEND:
- gen_cntl |= 0x8;
+ gen_cntl |= 0x4000048;
break;
case FB_BLANK_HSYNC_SUSPEND:
- gen_cntl |= 0x4;
+ gen_cntl |= 0x4000044;
break;
case FB_BLANK_POWERDOWN:
- gen_cntl |= 0x4c;
+ gen_cntl |= 0x400004c;
break;
}
- aty_st_8(CRTC_GEN_CNTL, gen_cntl, par);
+ aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
+ if ((_machine == _MACH_Pmac) && blank <= FB_BLANK_NORMAL)
set_backlight_enable(1);
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
- if (par->lcd_table && !blank &&
+ if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
u32 pm = aty_ld_lcd(POWER_MANAGEMENT, par);
pm |= PWR_BLON;
@@ -3157,15 +3184,15 @@ static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]);
par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate];
/* We now need to determine the crtc parameters for the
- * lcd monitor. This is tricky, because they are not stored
+ * LCD monitor. This is tricky, because they are not stored
* individually in the BIOS. Instead, the BIOS contains a
* table of display modes that work for this monitor.
*
* The idea is that we search for a mode of the same dimensions
- * as the dimensions of the lcd monitor. Say our lcd monitor
+ * as the dimensions of the LCD monitor. Say our LCD monitor
* is 800x600 pixels, we search for a 800x600 monitor.
* The CRTC parameters we find here are the ones that we need
- * to use to simulate other resolutions on the lcd screen.
+ * to use to simulate other resolutions on the LCD screen.
*/
lcdmodeptr = (u16 *)(par->lcd_table + 64);
while (*lcdmodeptr != 0) {
@@ -3472,7 +3499,7 @@ err_release_mem:
static int __devinit atyfb_atari_probe(void)
{
- struct aty_par *par;
+ struct atyfb_par *par;
struct fb_info *info;
int m64_num;
u32 clock_r;
@@ -3692,9 +3719,7 @@ static int __init atyfb_init(void)
atyfb_setup(option);
#endif
-#ifdef CONFIG_PCI
pci_register_driver(&atyfb_driver);
-#endif
#ifdef CONFIG_ATARI
atyfb_atari_probe();
#endif
@@ -3703,9 +3728,7 @@ static int __init atyfb_init(void)
static void __exit atyfb_exit(void)
{
-#ifdef CONFIG_PCI
pci_unregister_driver(&atyfb_driver);
-#endif
}
module_init(atyfb_init);
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
index 9bdb2aab01aa..e7056934c6a8 100644
--- a/drivers/video/aty/mach64_ct.c
+++ b/drivers/video/aty/mach64_ct.c
@@ -206,9 +206,7 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll
{
u32 q;
struct atyfb_par *par = (struct atyfb_par *) info->par;
-#ifdef DEBUG
int pllvclk;
-#endif
/* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
q = par->ref_clk_per * pll->pll_ref_div * 4 / vclk_per;
@@ -223,13 +221,26 @@ static int aty_valid_pll_ct(const struct fb_info *info, u32 vclk_per, struct pll
pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
// pll->vclk_post_div <<= 6;
pll->vclk_fb_div = q * pll->vclk_post_div_real / 8;
-#ifdef DEBUG
pllvclk = (1000000 * 2 * pll->vclk_fb_div) /
(par->ref_clk_per * pll->pll_ref_div);
+#ifdef DEBUG
printk("atyfb(%s): pllvclk=%d MHz, vclk=%d MHz\n",
__FUNCTION__, pllvclk, pllvclk / pll->vclk_post_div_real);
#endif
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
+
+ /* Set ECP (scaler/overlay clock) divider */
+ if (par->pll_limits.ecp_max) {
+ int ecp = pllvclk / pll->vclk_post_div_real;
+ int ecp_div = 0;
+
+ while (ecp > par->pll_limits.ecp_max && ecp_div < 2) {
+ ecp >>= 1;
+ ecp_div++;
+ }
+ pll->pll_vclk_cntl |= ecp_div << 4;
+ }
+
return 0;
}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 4f01ccc02aa4..c9f0c5a07e6e 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -594,7 +594,7 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
}
/*
- * Retreive PLL infos by different means (BIOS, Open Firmware, register probing...)
+ * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
*/
static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
{
@@ -660,17 +660,17 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
#ifdef CONFIG_PPC_OF
/*
- * Retreive PLL infos from Open Firmware first
+ * Retrieve PLL infos from Open Firmware first
*/
if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
- printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n");
goto found;
}
#endif /* CONFIG_PPC_OF */
/*
* Check out if we have an X86 which gave us some PLL informations
- * and if yes, retreive them
+ * and if yes, retrieve them
*/
if (!force_measure_pll && rinfo->bios_seg) {
u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
@@ -682,7 +682,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12);
rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16);
- printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n");
goto found;
}
@@ -691,7 +691,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
* probe them
*/
if (radeon_probe_pll_params(rinfo) == 0) {
- printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");
+ printk(KERN_INFO "radeonfb: Retrieved PLL infos from registers\n");
goto found;
}
@@ -702,7 +702,7 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo)
found:
/*
- * Some methods fail to retreive SCLK and MCLK values, we apply default
+ * Some methods fail to retrieve SCLK and MCLK values, we apply default
* settings in this case (200Mhz). If that really happne often, we could
* fetch from registers instead...
*/
@@ -864,8 +864,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
}
-static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct radeonfb_info *rinfo = info->par;
unsigned int tmp;
@@ -2393,7 +2393,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mapped_vram/1024);
/*
- * Map the BIOS ROM if any and retreive PLL parameters from
+ * Map the BIOS ROM if any and retrieve PLL parameters from
* the BIOS. We skip that on mobility chips as the real panel
* values we need aren't in the ROM but in the BIOS image in
* memory. This is definitely not the best meacnism though,
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index ea7c86306918..7f9838dceab5 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -423,7 +423,7 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo,
/*
* Probe display on both primary and secondary card's connector (if any)
* by various available techniques (i2c, OF device tree, BIOS, ...) and
- * try to retreive EDID. The algorithm here comes from XFree's radeon
+ * try to retrieve EDID. The algorithm here comes from XFree's radeon
* driver
*/
void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 097d668c4fe5..556895e99645 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -2734,7 +2734,7 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
* BIOS does tho. Right now, all this PM stuff is pmac-only for that
* reason. --BenH
*/
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (_machine == _MACH_Pmac && rinfo->of_node) {
if (rinfo->is_mobility && rinfo->pm_reg &&
rinfo->family <= CHIP_FAMILY_RV250)
@@ -2778,12 +2778,12 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000);
#endif
}
-#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_OF) */
+#endif /* defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) */
}
void radeonfb_pm_exit(struct radeonfb_info *rinfo)
{
-#if defined(CONFIG_PM) && defined(CONFIG_PPC_OF)
+#if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC)
if (rinfo->pm_mode != radeon_pm_none)
pmac_set_early_video_resume(NULL, NULL);
#endif
diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c
deleted file mode 100644
index a085cbf74ecb..000000000000
--- a/drivers/video/aty/xlinit.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * ATI Rage XL Initialization. Support for Xpert98 and Victoria
- * PCI cards.
- *
- * Copyright (C) 2002 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * stevel@mvista.com or 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <video/mach64.h>
-#include "atyfb.h"
-
-#define MPLL_GAIN 0xad
-#define VPLL_GAIN 0xd5
-
-enum {
- VICTORIA = 0,
- XPERT98,
- NUM_XL_CARDS
-};
-
-extern const struct aty_pll_ops aty_pll_ct;
-
-#define DEFAULT_CARD XPERT98
-static int xl_card = DEFAULT_CARD;
-
-static const struct xl_card_cfg_t {
- int ref_crystal; // 10^4 Hz
- int mem_type;
- int mem_size;
- u32 mem_cntl;
- u32 ext_mem_cntl;
- u32 mem_addr_config;
- u32 bus_cntl;
- u32 dac_cntl;
- u32 hw_debug;
- u32 custom_macro_cntl;
- u8 dll2_cntl;
- u8 pll_yclk_cntl;
-} card_cfg[NUM_XL_CARDS] = {
- // VICTORIA
- { 2700, SDRAM, 0x800000,
- 0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040,
- 0x82010102, 0x48803800, 0x005E0179,
- 0x50, 0x25
- },
- // XPERT98
- { 1432, WRAM, 0x800000,
- 0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001,
- 0x8000000A, 0x48833800, 0x007F0779,
- 0x10, 0x19
- }
-};
-
-typedef struct {
- u8 lcd_reg;
- u32 val;
-} lcd_tbl_t;
-
-static const lcd_tbl_t lcd_tbl[] = {
- { 0x01, 0x000520C0 },
- { 0x08, 0x02000408 },
- { 0x03, 0x00000F00 },
- { 0x00, 0x00000000 },
- { 0x02, 0x00000000 },
- { 0x04, 0x00000000 },
- { 0x05, 0x00000000 },
- { 0x06, 0x00000000 },
- { 0x33, 0x00000000 },
- { 0x34, 0x00000000 },
- { 0x35, 0x00000000 },
- { 0x36, 0x00000000 },
- { 0x37, 0x00000000 }
-};
-
-static void reset_gui(struct atyfb_par *par)
-{
- aty_st_8(GEN_TEST_CNTL+1, 0x01, par);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
- mdelay(5);
-}
-
-static void reset_sdram(struct atyfb_par *par)
-{
- u8 temp;
-
- temp = aty_ld_8(EXT_MEM_CNTL, par);
- temp |= 0x02;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_RESET = 1b
- temp |= 0x08;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 10b
- temp |= 0x0c;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 11b
- mdelay(5);
- temp &= 0xf3;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_CYC_TEST = 00b
- temp &= 0xfd;
- aty_st_8(EXT_MEM_CNTL, temp, par); // MEM_SDRAM_REST = 0b
- mdelay(5);
-}
-
-static void init_dll(struct atyfb_par *par)
-{
- // enable DLL
- aty_st_pll_ct(PLL_GEN_CNTL,
- aty_ld_pll_ct(PLL_GEN_CNTL, par) & 0x7f,
- par);
-
- // reset DLL
- aty_st_pll_ct(DLL_CNTL, 0x82, par);
- aty_st_pll_ct(DLL_CNTL, 0xE2, par);
- mdelay(5);
- aty_st_pll_ct(DLL_CNTL, 0x82, par);
- mdelay(6);
-}
-
-static void reset_clocks(struct atyfb_par *par, struct pll_ct *pll,
- int hsync_enb)
-{
- reset_gui(par);
- aty_st_pll_ct(MCLK_FB_DIV, pll->mclk_fb_div, par);
- aty_st_pll_ct(SCLK_FB_DIV, pll->sclk_fb_div, par);
-
- mdelay(15);
- init_dll(par);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- mdelay(5);
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- mdelay(6);
- reset_sdram(par);
- aty_st_8(CRTC_GEN_CNTL+3,
- hsync_enb ? 0x00 : 0x04, par);
-
- aty_st_pll_ct(SPLL_CNTL2, pll->spll_cntl2, par);
- aty_st_pll_ct(PLL_GEN_CNTL, pll->pll_gen_cntl, par);
- aty_st_pll_ct(PLL_VCLK_CNTL, pll->pll_vclk_cntl, par);
-}
-
-int atyfb_xl_init(struct fb_info *info)
-{
- const struct xl_card_cfg_t * card = &card_cfg[xl_card];
- struct atyfb_par *par = (struct atyfb_par *) info->par;
- union aty_pll pll;
- int err;
- u32 temp;
-
- aty_st_8(CONFIG_STAT0, 0x85, par);
- mdelay(10);
-
- /*
- * The following needs to be set before the call
- * to var_to_pll() below. They'll be re-set again
- * to the same values in aty_init().
- */
- par->ref_clk_per = 100000000UL/card->ref_crystal;
- par->ram_type = card->mem_type;
- info->fix.smem_len = card->mem_size;
- if (xl_card == VICTORIA) {
- // the MCLK, XCLK are 120MHz on victoria card
- par->mclk_per = 1000000/120;
- par->xclk_per = 1000000/120;
- par->features &= ~M64F_MFB_FORCE_4;
- }
-
- /*
- * Calculate mclk and xclk dividers, etc. The passed
- * pixclock and bpp values don't matter yet, the vclk
- * isn't programmed until later.
- */
- if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
- return err;
-
- aty_st_pll_ct(LVDS_CNTL0, 0x00, par);
- aty_st_pll_ct(DLL2_CNTL, card->dll2_cntl, par);
- aty_st_pll_ct(V2PLL_CNTL, 0x10, par);
- aty_st_pll_ct(MPLL_CNTL, MPLL_GAIN, par);
- aty_st_pll_ct(VPLL_CNTL, VPLL_GAIN, par);
- aty_st_pll_ct(PLL_VCLK_CNTL, 0x00, par);
- aty_st_pll_ct(VFC_CNTL, 0x1B, par);
- aty_st_pll_ct(PLL_REF_DIV, pll.ct.pll_ref_div, par);
- aty_st_pll_ct(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(SPLL_CNTL2, 0x03, par);
- aty_st_pll_ct(PLL_GEN_CNTL, 0x44, par);
-
- reset_clocks(par, &pll.ct, 0);
- mdelay(10);
-
- aty_st_pll_ct(VCLK_POST_DIV, 0x03, par);
- aty_st_pll_ct(VCLK0_FB_DIV, 0xDA, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0x0F, par);
- aty_st_pll_ct(VCLK1_FB_DIV, 0xF5, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0x3F, par);
- aty_st_pll_ct(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(VCLK2_FB_DIV, 0x00, par);
- aty_st_pll_ct(VCLK_POST_DIV, 0xFF, par);
- aty_st_pll_ct(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, par);
- aty_st_pll_ct(VCLK3_FB_DIV, 0x00, par);
-
- aty_st_8(BUS_CNTL, 0x01, par);
- aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, par);
-
- aty_st_le32(CRTC_GEN_CNTL, 0x04000200, par);
- aty_st_le16(CONFIG_STAT0, 0x0020, par);
- aty_st_le32(MEM_CNTL, 0x10151A33, par);
- aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, par);
- aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, par);
- aty_st_le32(DAC_CNTL, card->dac_cntl, par);
- aty_st_le16(GEN_TEST_CNTL, 0x0100, par);
- aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, par);
- aty_st_le32(MEM_BUF_CNTL, 0x00382848, par);
-
- aty_st_le32(HW_DEBUG, card->hw_debug, par);
- aty_st_le16(MEM_ADDR_CONFIG, 0x0000, par);
- aty_st_le16(GP_IO+2, 0x0000, par);
- aty_st_le16(GEN_TEST_CNTL, 0x0000, par);
- aty_st_le16(EXT_DAC_REGS+2, 0x0000, par);
- aty_st_le32(CRTC_INT_CNTL, 0x00000000, par);
- aty_st_le32(TIMER_CONFIG, 0x00000000, par);
- aty_st_le32(0xEC, 0x00000000, par);
- aty_st_le32(0xFC, 0x00000000, par);
-
-#if defined (CONFIG_FB_ATY_GENERIC_LCD)
- {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(lcd_tbl); i++)
- aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par);
- }
-#endif
-
- aty_st_le16(CONFIG_STAT0, 0x00A4, par);
- mdelay(10);
-
- aty_st_8(BUS_CNTL+1, 0xA0, par);
- mdelay(10);
-
- reset_clocks(par, &pll.ct, 1);
- mdelay(10);
-
- // something about power management
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA, 0x0A, par);
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA+3, 0x02, par);
- aty_st_8(LCD_INDEX, 0x08, par);
- aty_st_8(LCD_DATA, 0x0B, par);
- mdelay(2);
-
- // enable display requests, enable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
- // disable display
- aty_st_8(CRTC_GEN_CNTL, 0x40, par);
- // disable display requests, disable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- mdelay(10);
-
- aty_st_pll_ct(PLL_YCLK_CNTL, 0x25, par);
-
- aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, par);
- aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, par);
- aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, par);
- aty_st_8(CUSTOM_MACRO_CNTL+1,
- (card->custom_macro_cntl>>8) & 0xff, par);
-
- aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, par);
- aty_st_le32(MEM_CNTL, card->mem_cntl, par);
- aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, par);
-
- aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, par);
-
- aty_st_pll_ct(PLL_YCLK_CNTL, 0x01, par);
- mdelay(15);
- aty_st_pll_ct(PLL_YCLK_CNTL, card->pll_yclk_cntl, par);
- mdelay(1);
-
- reset_clocks(par, &pll.ct, 0);
- mdelay(50);
- reset_clocks(par, &pll.ct, 0);
- mdelay(50);
-
- // enable extended register block
- aty_st_8(BUS_CNTL+3, 0x7B, par);
- mdelay(1);
- // disable extended register block
- aty_st_8(BUS_CNTL+3, 0x73, par);
-
- aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, par);
-
- // disable display requests, disable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x04, par);
- // disable mapping registers in VGA aperture
- aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, par) & ~0x04, par);
- mdelay(50);
- // enable display requests, enable CRTC
- aty_st_8(CRTC_GEN_CNTL+3, 0x02, par);
-
- // make GPIO's 14,15,16 all inputs
- aty_st_8(LCD_INDEX, 0x07, par);
- aty_st_8(LCD_DATA+3, 0x00, par);
-
- // enable the display
- aty_st_8(CRTC_GEN_CNTL, 0x00, par);
- mdelay(17);
- // reset the memory controller
- aty_st_8(GEN_TEST_CNTL+1, 0x02, par);
- mdelay(15);
- aty_st_8(GEN_TEST_CNTL+1, 0x00, par);
- mdelay(30);
-
- // enable extended register block
- aty_st_8(BUS_CNTL+3,
- (u8)(aty_ld_8(BUS_CNTL+3, par) | 0x08),
- par);
- // set FIFO size to 512 (PIO)
- aty_st_le32(GUI_CNTL,
- aty_ld_le32(GUI_CNTL, par) & ~0x3,
- par);
-
- // enable CRT and disable lcd
- aty_st_8(LCD_INDEX, 0x01, par);
- temp = aty_ld_le32(LCD_DATA, par);
- temp = (temp | 0x01) & ~0x02;
- aty_st_le32(LCD_DATA, temp, par);
- return 0;
-}
-
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a5129806172f..2406899f1207 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -379,7 +379,7 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle)
* Map video memory in user space. We don't use the generic fb_mmap method mainly
* to allow the use of the TLB streaming flag (CCA=6)
*/
-int au1100fb_fb_mmap(struct fb_info *fbi, struct file *file, struct vm_area_struct *vma)
+int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
{
struct au1100fb_device *fbdev = to_au1100fb_device(fbi);
unsigned int len;
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 6a219b2c77e3..d0aaf450e8c7 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -20,6 +20,7 @@
#include <linux/backlight.h>
#include <asm/arch/sharpsl.h>
+#include <asm/hardware/sharpsl_pm.h>
#define CORGI_DEFAULT_INTENSITY 0x1f
#define CORGI_LIMIT_MASK 0x0b
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 9248fe1fbb1a..c029db4646f6 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -35,9 +35,8 @@
static int bw2_blank(int, struct fb_info *);
-static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int bw2_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int bw2_mmap(struct fb_info *, struct vm_area_struct *);
+static int bw2_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -169,7 +168,7 @@ static struct sbus_mmap_map bw2_mmap_map[] = {
{ .size = 0 }
};
-static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int bw2_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct bw2_par *par = (struct bw2_par *)info->par;
@@ -181,8 +180,7 @@ static int bw2_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct bw2_par *par = (struct bw2_par *) info->par;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index a56147102abb..63b6c79c8a0a 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -31,9 +31,8 @@
static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
-static int cg14_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg14_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg14_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg14_ioctl(struct fb_info *, unsigned int, unsigned long);
static int cg14_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -268,7 +267,7 @@ static int cg14_setcolreg(unsigned regno,
return 0;
}
-static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg14_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg14_par *par = (struct cg14_par *) info->par;
@@ -277,8 +276,7 @@ static int cg14_mmap(struct fb_info *info, struct file *file, struct vm_area_str
par->iospace, vma);
}
-static int cg14_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg14_par *par = (struct cg14_par *) info->par;
struct cg14_regs __iomem *regs = par->regs;
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 9fcd89608ed7..3de6e1b5ab2f 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -33,9 +33,8 @@ static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int cg3_blank(int, struct fb_info *);
-static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg3_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg3_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg3_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -230,7 +229,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = {
{ .size = 0 }
};
-static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg3_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg3_par *par = (struct cg3_par *)info->par;
@@ -240,8 +239,7 @@ static int cg3_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg3_par *par = (struct cg3_par *) info->par;
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 050835e39aa3..7aab91ead681 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -36,9 +36,8 @@ static int cg6_blank(int, struct fb_info *);
static void cg6_imageblit(struct fb_info *, const struct fb_image *);
static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
static int cg6_sync(struct fb_info *);
-static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int cg6_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
+static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -524,7 +523,7 @@ static struct sbus_mmap_map cg6_mmap_map[] = {
{ .size = 0 }
};
-static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct cg6_par *par = (struct cg6_par *)info->par;
@@ -534,8 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct cg6_par *par = (struct cg6_par *) info->par;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index a5d09e159cd1..6ee449858a5c 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
config VGA_CONSOLE
bool "VGA text console" if EMBEDDED || !X86
- depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !ARCH_VERSATILE
+ depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE
default y
help
Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index e65fc3ef7630..eea422eb1ab5 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -234,14 +234,14 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void bit_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines, int fg, int bg)
+static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1;
char *src;
@@ -310,7 +310,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -323,10 +323,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3660e51b2612..041d06987861 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -209,13 +209,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
#endif
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
if (!(info->flags & FBINFO_MISC_TILEBLITTING) &&
- p->con_rotate < 4)
- ops->rotate = p->con_rotate;
+ ops->p->con_rotate < 4)
+ ops->rotate = ops->p->con_rotate;
else
ops->rotate = 0;
}
@@ -265,7 +265,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
fbcon_set_all_vcs(info);
}
#else
-static inline void fbcon_set_rotation(struct fb_info *info, struct display *p)
+static inline void fbcon_set_rotation(struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
@@ -402,7 +402,7 @@ static void fb_flashcursor(void *private)
c = scr_readw((u16 *) vc->vc_pos);
mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
CM_ERASE : CM_DRAW;
- ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, mode, softback_lines, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
release_console_sem();
}
@@ -647,29 +647,27 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
}
#ifdef CONFIG_FB_TILEBLITTING
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
- struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
- ops->p = (p) ? p : &fb_display[vc->vc_num];
+ ops->p = &fb_display[vc->vc_num];
if ((info->flags & FBINFO_MISC_TILEBLITTING))
- fbcon_set_tileops(vc, info, p, ops);
+ fbcon_set_tileops(vc, info);
else {
- fbcon_set_rotation(info, ops->p);
+ fbcon_set_rotation(info);
fbcon_set_bitops(ops);
}
}
#else
-static void set_blitting_type(struct vc_data *vc, struct fb_info *info,
- struct display *p)
+static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
struct fbcon_ops *ops = info->fbcon_par;
info->flags &= ~FBINFO_MISC_TILEBLITTING;
- ops->p = (p) ? p : &fb_display[vc->vc_num];
- fbcon_set_rotation(info, ops->p);
+ ops->p = &fb_display[vc->vc_num];
+ fbcon_set_rotation(info);
fbcon_set_bitops(ops);
}
#endif /* CONFIG_MISC_TILEBLITTING */
@@ -689,15 +687,14 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
err = -ENODEV;
if (!err) {
- ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
if (!ops)
err = -ENOMEM;
}
if (!err) {
- memset(ops, 0, sizeof(struct fbcon_ops));
info->fbcon_par = ops;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
}
if (err) {
@@ -921,19 +918,18 @@ static const char *fbcon_startup(void)
return NULL;
}
- ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+ ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
if (!ops) {
module_put(owner);
return NULL;
}
- memset(ops, 0, sizeof(struct fbcon_ops));
ops->currcon = -1;
ops->graphics = 1;
ops->cur_rotate = -1;
info->fbcon_par = ops;
p->con_rotate = rotate;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
if (info->fix.type != FB_TYPE_TEXT) {
if (fbcon_softback_size) {
@@ -1093,7 +1089,7 @@ static void fbcon_init(struct vc_data *vc, int init)
ops = info->fbcon_par;
p->con_rotate = rotate;
- set_blitting_type(vc, info, NULL);
+ set_blitting_type(vc, info);
cols = vc->vc_cols;
rows = vc->vc_rows;
@@ -1110,7 +1106,7 @@ static void fbcon_init(struct vc_data *vc, int init)
*
* We need to do it in fbcon_init() to prevent screen corruption.
*/
- if (CON_IS_VISIBLE(vc)) {
+ if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
if (info->fbops->fb_set_par &&
!(ops->flags & FBCON_FLAGS_INIT))
info->fbops->fb_set_par(info);
@@ -1141,9 +1137,9 @@ static void fbcon_init(struct vc_data *vc, int init)
if (vc == svc && softback_buf)
fbcon_update_softback(vc);
- if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+ if (ops->rotate_font && ops->rotate_font(info, vc)) {
ops->rotate = FB_ROTATE_UR;
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
}
}
@@ -1243,7 +1239,6 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
- struct display *p = &fb_display[vc->vc_num];
int y;
int c = scr_readw((u16 *) vc->vc_pos);
@@ -1260,7 +1255,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
y = 0;
}
- ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1),
+ ops->cursor(vc, info, mode, y, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
@@ -1411,16 +1406,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct display *p = &fb_display[vc->vc_num];
- int redraw = 0;
p->yscroll += count;
+
if (p->yscroll > p->vrows - vc->vc_rows) {
p->yscroll -= p->vrows - vc->vc_rows;
- redraw = 1;
- }
-
- if (redraw)
fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
+ }
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1462,16 +1454,13 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
struct display *p = &fb_display[vc->vc_num];
- int redraw = 0;
p->yscroll -= count;
+
if (p->yscroll < 0) {
p->yscroll += p->vrows - vc->vc_rows;
- redraw = 1;
- }
-
- if (redraw)
fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
+ }
ops->var.xoffset = 0;
ops->var.yoffset = p->yscroll * vc->vc_font.height;
@@ -1968,7 +1957,8 @@ static __inline__ void updatescrollmode(struct display *p,
divides(ypan, vc->vc_font.height) && vyres > yres;
int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
divides(ywrap, vc->vc_font.height) &&
- divides(vc->vc_font.height, vyres);
+ divides(vc->vc_font.height, vyres) &&
+ divides(vc->vc_font.height, yres);
int reading_fast = cap & FBINFO_READS_FAST;
int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED);
@@ -2107,16 +2097,19 @@ static int fbcon_switch(struct vc_data *vc)
info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
if (info->fbops->fb_set_par)
info->fbops->fb_set_par(info);
- fbcon_del_cursor_timer(old_info);
- fbcon_add_cursor_timer(info);
+
+ if (old_info != info) {
+ fbcon_del_cursor_timer(old_info);
+ fbcon_add_cursor_timer(info);
+ }
}
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
ops->cursor_reset = 1;
- if (ops->rotate_font && ops->rotate_font(info, vc, p)) {
+ if (ops->rotate_font && ops->rotate_font(info, vc)) {
ops->rotate = FB_ROTATE_UR;
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
}
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
@@ -2739,7 +2732,7 @@ static void fbcon_modechanged(struct fb_info *info)
return;
p = &fb_display[vc->vc_num];
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
if (CON_IS_VISIBLE(vc)) {
var_to_display(p, &info->var, info);
@@ -2781,7 +2774,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
continue;
p = &fb_display[vc->vc_num];
- set_blitting_type(vc, info, p);
+ set_blitting_type(vc, info);
var_to_display(p, &info->var, info);
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
@@ -2806,6 +2799,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
fbcon_update_softback(vc);
}
}
+
+ ops->p = &fb_display[ops->currcon];
}
static int fbcon_mode_deleted(struct fb_info *info,
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 6892e7ff34de..c38c3d8e7a74 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -62,12 +62,10 @@ struct fbcon_ops {
int fg, int bg);
void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
int bottom_only);
- void (*cursor)(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg);
+ void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg);
int (*update_start)(struct fb_info *info);
- int (*rotate_font)(struct fb_info *info, struct vc_data *vc,
- struct display *p);
+ int (*rotate_font)(struct fb_info *info, struct vc_data *vc);
struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */
struct timer_list cursor_timer; /* Cursor timer */
struct fb_cursor cursor_state;
@@ -173,8 +171,7 @@ struct fbcon_ops {
#define SCROLL_PAN_REDRAW 0x005
#ifdef CONFIG_FB_TILEBLITTING
-extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
- struct display *p, struct fbcon_ops *ops);
+extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 4952b66ae206..990289a69b78 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -219,19 +219,18 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(p->scrollmode, info);
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -303,7 +302,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -323,10 +322,10 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6d92b8456206..d44c5fa515fb 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -203,19 +203,18 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void cw_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vxres = GETVXRES(p->scrollmode, info);
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -287,7 +286,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
@@ -307,10 +306,10 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/fbcon_rotate.c b/drivers/video/console/fbcon_rotate.c
index ec0dd8fe241c..2dc091fbd5c9 100644
--- a/drivers/video/console/fbcon_rotate.c
+++ b/drivers/video/console/fbcon_rotate.c
@@ -18,8 +18,7 @@
#include "fbcon.h"
#include "fbcon_rotate.h"
-static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
- struct display *p)
+static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
{
struct fbcon_ops *ops = info->fbcon_par;
int len, err = 0;
@@ -28,12 +27,12 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc,
u8 *dst;
if (vc->vc_font.data == ops->fontdata &&
- p->con_rotate == ops->cur_rotate)
+ ops->p->con_rotate == ops->cur_rotate)
goto finished;
src = ops->fontdata = vc->vc_font.data;
- ops->cur_rotate = p->con_rotate;
- len = (!p->userfont) ? 256 : FNTCHARCNT(src);
+ ops->cur_rotate = ops->p->con_rotate;
+ len = (!ops->p->userfont) ? 256 : FNTCHARCNT(src);
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;
diff --git a/drivers/video/console/fbcon_rotate.h b/drivers/video/console/fbcon_rotate.h
index 1b8f92fdc6a8..75be5ce53dc5 100644
--- a/drivers/video/console/fbcon_rotate.h
+++ b/drivers/video/console/fbcon_rotate.h
@@ -11,8 +11,6 @@
#ifndef _FBCON_ROTATE_H
#define _FBCON_ROTATE_H
-#define FNTCHARCNT(fd) (((int *)(fd))[-3])
-
#define GETVYRES(s,i) ({ \
(s == SCROLL_REDRAW || s == SCROLL_MOVE) ? \
(i)->var.yres : (i)->var.yres_virtual; })
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 9dd059e8b645..f56ed068a5bc 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -249,20 +249,19 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
}
}
-static void ud_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
+ struct fbcon_ops *ops = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
- int y = real_y(p, vc->vc_y);
+ int y = real_y(ops->p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(p->scrollmode, info);
- u32 vxres = GETVXRES(p->scrollmode, info);
+ u32 vyres = GETVYRES(ops->p->scrollmode, info);
+ u32 vxres = GETVXRES(ops->p->scrollmode, info);
if (!ops->fontbuffer)
return;
@@ -334,7 +333,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info,
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != p->cursor_shape ||
+ vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
@@ -347,10 +346,10 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info,
kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
- p->cursor_shape = vc->vc_cursor_type;
+ ops->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (p->cursor_shape & CUR_HWMASK) {
+ switch (ops->p->cursor_shape & CUR_HWMASK) {
case CUR_NONE:
cur_height = 0;
break;
diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c
index 8529bf08db28..3957fc7523e2 100644
--- a/drivers/video/console/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -17,6 +17,8 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#include "fbcon.h"
+
int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
unsigned int scan_align = info->pixmap.scan_align - 1;
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index cb25324a5635..153352ca9461 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -80,9 +80,8 @@ static void tile_clear_margins(struct vc_data *vc, struct fb_info *info,
return;
}
-static void tile_cursor(struct vc_data *vc, struct fb_info *info,
- struct display *p, int mode, int softback_lines,
- int fg, int bg)
+static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode,
+ int softback_lines, int fg, int bg)
{
struct fb_tilecursor cursor;
int use_sw = (vc->vc_cursor_type & 0x01);
@@ -130,10 +129,10 @@ static int tile_update_start(struct fb_info *info)
return err;
}
-void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
- struct display *p, struct fbcon_ops *ops)
+void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
{
struct fb_tilemap map;
+ struct fbcon_ops *ops = info->fbcon_par;
ops->bmove = tile_bmove;
ops->clear = tile_clear;
@@ -142,13 +141,13 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
ops->cursor = tile_cursor;
ops->update_start = tile_update_start;
- if (p) {
+ if (ops->p) {
map.width = vc->vc_font.width;
map.height = vc->vc_font.height;
map.depth = 1;
- map.length = (p->userfont) ?
- FNTCHARCNT(p->fontdata) : 256;
- map.data = p->fontdata;
+ map.length = (ops->p->userfont) ?
+ FNTCHARCNT(ops->p->fontdata) : 256;
+ map.data = ops->p->fontdata;
info->tileops->fb_settile(info, &map);
}
}
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 167de397e4b4..12d9329d1408 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -56,6 +56,8 @@
static DEFINE_SPINLOCK(vga_lock);
static int cursor_size_lastfrom;
static int cursor_size_lastto;
+static u32 vgacon_xres;
+static u32 vgacon_yres;
static struct vgastate state;
#define BLANK 0x0020
@@ -69,7 +71,7 @@ static struct vgastate state;
* appear.
*/
#undef TRIDENT_GLITCH
-
+#define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */
/*
* Interface used by the world
*/
@@ -325,6 +327,10 @@ static const char __init *vgacon_startup(void)
vga_scan_lines =
vga_video_font_height * vga_video_num_lines;
}
+
+ vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
+ vgacon_yres = vga_scan_lines;
+
return display_desc;
}
@@ -503,10 +509,18 @@ static int vgacon_doresize(struct vc_data *c,
{
unsigned long flags;
unsigned int scanlines = height * c->vc_font.height;
- u8 scanlines_lo, r7, vsync_end, mode;
+ u8 scanlines_lo, r7, vsync_end, mode, max_scan;
spin_lock_irqsave(&vga_lock, flags);
+ outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg);
+ max_scan = inb_p(vga_video_port_val);
+
+ if (max_scan & 0x80)
+ scanlines <<= 1;
+
+ vgacon_xres = width * VGA_FONTWIDTH;
+ vgacon_yres = height * c->vc_font.height;
outb_p(VGA_CRTC_MODE, vga_video_port_reg);
mode = inb_p(vga_video_port_val);
@@ -551,6 +565,10 @@ static int vgacon_doresize(struct vc_data *c,
static int vgacon_switch(struct vc_data *c)
{
+ int x = c->vc_cols * VGA_FONTWIDTH;
+ int y = c->vc_rows * c->vc_font.height;
+ int rows = ORIG_VIDEO_LINES * vga_default_font_height/
+ c->vc_font.height;
/*
* We need to save screen size here as it's the only way
* we can spot the screen has been resized and we need to
@@ -566,10 +584,11 @@ static int vgacon_switch(struct vc_data *c)
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
- if (!(vga_video_num_columns % 2) &&
- vga_video_num_columns <= ORIG_VIDEO_COLS &&
- vga_video_num_lines <= (ORIG_VIDEO_LINES *
- vga_default_font_height) / c->vc_font.height)
+
+ if ((vgacon_xres != x || vgacon_yres != y) &&
+ (!(vga_video_num_columns % 2) &&
+ vga_video_num_columns <= ORIG_VIDEO_COLS &&
+ vga_video_num_lines <= rows))
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
@@ -993,7 +1012,8 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- if (font->width != 8 || (charcount != 256 && charcount != 512))
+ if (font->width != VGA_FONTWIDTH ||
+ (charcount != 256 && charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
@@ -1010,7 +1030,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font)
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- font->width = 8;
+ font->width = VGA_FONTWIDTH;
font->height = c->vc_font.height;
font->charcount = vga_512_chars ? 512 : 256;
if (!font->data)
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 403d17377f8d..655301a8671c 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -128,17 +128,11 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int controlfb_blank(int blank_mode, struct fb_info *info);
-static int controlfb_mmap(struct fb_info *info, struct file *file,
+static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static int controlfb_set_par (struct fb_info *info);
static int controlfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info);
-/*
- * inititialization
- */
-int control_init(void);
-void control_setup(char *);
-
/******************** Prototypes for internal functions **********************/
static void set_control_clock(unsigned char *params);
@@ -286,7 +280,7 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
* for controlfb.
* Note there's no locking in here; it's done in fb_mmap() in fbmem.c.
*/
-static int controlfb_mmap(struct fb_info *info, struct file *file,
+static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long off, start;
@@ -550,9 +544,46 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
/*
- * Called from fbmem.c for probing & initializing
+ * Parse user speficied options (`video=controlfb:')
*/
-int __init control_init(void)
+static void __init control_setup(char *options)
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return;
+
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ if (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX &&
+ control_mac_modes[vmode - 1].m[1] >= 0)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ int depth = simple_strtoul(this_opt+6, NULL, 0);
+ switch (depth) {
+ case CMODE_8:
+ case CMODE_16:
+ case CMODE_32:
+ default_cmode = depth;
+ break;
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+ }
+}
+
+static int __init control_init(void)
{
struct device_node *dp;
char *option = NULL;
@@ -651,15 +682,16 @@ static void __init find_vram_size(struct fb_info_control *p)
static int __init control_of_init(struct device_node *dp)
{
struct fb_info_control *p;
- unsigned long addr;
- int i;
+ struct resource fb_res, reg_res;
if (control_fb) {
printk(KERN_ERR "controlfb: only one control is supported\n");
return -ENXIO;
}
- if(dp->n_addrs != 2) {
- printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
+
+ if (of_pci_address_to_resource(dp, 2, &fb_res) ||
+ of_pci_address_to_resource(dp, 1, &reg_res)) {
+ printk(KERN_ERR "can't get 2 addresses for control\n");
return -ENXIO;
}
p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -669,18 +701,12 @@ static int __init control_of_init(struct device_node *dp)
memset(p, 0, sizeof(*p));
/* Map in frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- if (dp->addrs[i].size >= 0x800000) {
- p->fb_orig_base = addr;
- p->fb_orig_size = dp->addrs[i].size;
- /* use the big-endian aperture (??) */
- p->frame_buffer_phys = addr + 0x800000;
- } else {
- p->control_regs_phys = addr;
- p->control_regs_size = dp->addrs[i].size;
- }
- }
+ p->fb_orig_base = fb_res.start;
+ p->fb_orig_size = fb_res.end - fb_res.start + 1;
+ /* use the big-endian aperture (??) */
+ p->frame_buffer_phys = fb_res.start + 0x800000;
+ p->control_regs_phys = reg_res.start;
+ p->control_regs_size = reg_res.end - reg_res.start + 1;
if (!p->fb_orig_base ||
!request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {
@@ -1059,43 +1085,3 @@ static void control_cleanup(void)
}
-/*
- * Parse user speficied options (`video=controlfb:')
- */
-void __init control_setup(char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!strncmp(this_opt, "vmode:", 6)) {
- int vmode = simple_strtoul(this_opt+6, NULL, 0);
- if (vmode > 0 && vmode <= VMODE_MAX &&
- control_mac_modes[vmode - 1].m[1] >= 0)
- default_vmode = vmode;
- } else if (!strncmp(this_opt, "cmode:", 6)) {
- int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
- case CMODE_8:
- case CMODE_16:
- case CMODE_32:
- default_cmode = depth;
- break;
- case 8:
- default_cmode = CMODE_8;
- break;
- case 15:
- case 16:
- default_cmode = CMODE_16;
- break;
- case 24:
- case 32:
- default_cmode = CMODE_32;
- break;
- }
- }
- }
-}
-
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index a9300f930ef2..55a3514157ed 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -50,7 +50,6 @@
#include <linux/init.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 03fbe83d71a8..2b972461a030 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -7,11 +7,12 @@
* tridentfb.c by Jani Monoses
* see files above for further credits
*
- * TODO:
- *
*/
#define CYBLAFB_DEBUG 0
+#define CYBLAFB_KD_GRAPHICS_QUIRK 1
+
+#define CYBLAFB_PIXMAPSIZE 8192
#include <linux/config.h>
#include <linux/module.h>
@@ -22,7 +23,7 @@
#include <asm/types.h>
#include <video/cyblafb.h>
-#define VERSION "0.54"
+#define VERSION "0.62"
struct cyblafb_par {
u32 pseudo_pal[16];
@@ -32,7 +33,9 @@ struct cyblafb_par {
static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
.id = "CyBla",
.type = FB_TYPE_PACKED_PIXELS,
+ .xpanstep = 1,
.ypanstep = 1,
+ .ywrapstep = 1,
.visual = FB_VISUAL_PSEUDOCOLOR,
.accel = FB_ACCEL_NONE,
};
@@ -43,8 +46,9 @@ static int ref __devinitdata = 75;
static int fp __devinitdata;
static int crt __devinitdata;
static int memsize __devinitdata;
-static int vesafb __devinitdata;
+static int basestride;
+static int vesafb;
static int nativex;
static int center;
static int stretch;
@@ -52,26 +56,50 @@ static int pciwb = 1;
static int pcirb = 1;
static int pciwr = 1;
static int pcirr = 1;
+static int disabled;
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);
+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);
+
+//=========================================
+//
+// Well, we have to fix the upper layers.
+// Until this has been done, we work around
+// the bugs.
+//
+//=========================================
+
+#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
+ if (disabled) { \
+ printk("********\n");\
+ dump_stack();\
+ return val;\
+ }
+
+#elif CYBLAFB_KD_GRAPHICS_QUIRK
+#define KD_GRAPHICS_RETURN(val)\
+ if (disabled) {\
+ return val;\
+ }
+#else
+#define KD_GRAPHICS_RETURN(val)
+#endif
//=========================================
//
@@ -79,10 +107,10 @@ module_param(vesafb,int,0);
//
//=========================================
-#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)
+#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)
//======================================
//
@@ -90,47 +118,47 @@ module_param(vesafb,int,0);
//
//======================================
-static inline unsigned char read3X4(int reg)
+static inline u8 read3X4(u32 reg)
{
- out8(0x3D4,reg);
+ out8(0x3D4, reg);
return in8(0x3D5);
}
-static inline unsigned char read3C4(int reg)
+static inline u8 read3C4(u32 reg)
{
- out8(0x3C4,reg);
+ out8(0x3C4, reg);
return in8(0x3C5);
}
-static inline unsigned char read3CE(int reg)
+static inline u8 read3CE(u32 reg)
{
- out8(0x3CE,reg);
+ out8(0x3CE, reg);
return in8(0x3CF);
}
-static inline void write3X4(int reg,unsigned char val)
+static inline void write3X4(u32 reg, u8 val)
{
- out8(0x3D4,reg);
- out8(0x3D5,val);
+ out8(0x3D4, reg);
+ out8(0x3D5, val);
}
-static inline void write3C4(int reg,unsigned char val)
+static inline void write3C4(u32 reg, u8 val)
{
- out8(0x3C4,reg);
- out8(0x3C5,val);
+ out8(0x3C4, reg);
+ out8(0x3C5, val);
}
-static inline void write3CE(int reg,unsigned char val)
+static inline void write3CE(u32 reg, u8 val)
{
- out8(0x3CE,reg);
- out8(0x3CF,val);
+ out8(0x3CE, reg);
+ out8(0x3CF, val);
}
-static inline void write3C0(int reg,unsigned char val)
+static inline void write3C0(u32 reg, u8 val)
{
- in8(0x3DA); // read to reset index
- out8(0x3C0,reg);
- out8(0x3C0,val);
+ in8(0x3DA); // read to reset index
+ out8(0x3C0, reg);
+ out8(0x3C0, val);
}
//=================================================
@@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val)
//
//=================================================
-static inline void enable_mmio(void)
+static void enable_mmio(void)
{
- int tmp;
+ u8 tmp;
- outb(0x0B,0x3C4);
+ outb(0x0B, 0x3C4);
inb(0x3C5); // Set NEW mode
- outb(SR0E,0x3C4); // write enable a lot of extended ports
- outb(0x80,0x3C5);
+ 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(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(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
+ outb(CR39, 0x3D4);
+ outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
}
//=================================================
//
// Set pixel clock VCLK1
-// - multipliers set elswhere
-// - freq in units of 0.01 MHz
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+// Hardware bug: SR18 >= 250 is broken for the
+// cyberblade/i1
//
//=================================================
static void set_vclk(struct cyblafb_par *par, int freq)
{
- u32 m,n,k;
- int f,fi,d,di;
- u8 lo=0,hi=0;
+ 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);
+ for (m = 0; m < 64; m++)
+ for (n = 0; n < 250; n++) {
+ 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)
+ write3C4(SR19, hi);
+ write3C4(SR18, lo);
+ if (verbosity > 0)
output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
- freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+ freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
}
//================================================
@@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq)
//
//================================================
-static void cyblafb_setup_GE(int pitch,int bpp)
+static void cyblafb_setup_GE(int pitch, int bpp)
{
- int base = (pitch>>3)<<20;
+ KD_GRAPHICS_RETURN();
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;
+ case 8:
+ basestride = ((pitch >> 3) << 20) | (0 << 29);
+ break;
+ case 15:
+ basestride = ((pitch >> 3) << 20) | (5 << 29);
+ break;
+ case 16:
+ basestride = ((pitch >> 3) << 20) | (1 << 29);
+ break;
+ case 24:
+ case 32:
+ basestride = ((pitch >> 3) << 20) | (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
+ write3X4(CR36, 0x90); // reset GE
+ write3X4(CR36, 0x80); // enable GE
+ out32(GE24, 1 << 7); // reset all GE pointers by toggling
+ out32(GE24, 0); // d7 of GE24
+ write3X4(CR2D, 0x00); // GE Timinigs, no delays
+ 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.
+// Cyberblade specific syncing
+//
+// A 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
+// First we try to sync ignoring that problem, as most of the
+// time that will succeed immediately and the enable_mmio()
+// would only degrade performance.
//
//=====================================================================
static int cyblafb_sync(struct fb_info *info)
{
- int status, i=100000;
- while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+ u32 status, i = 100000;
+
+ KD_GRAPHICS_RETURN(0);
+
+ while (((status = in32(GE20)) & 0xFe800000) && 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 = 1000000;
+ while (((status = in32(GE20)) & 0xFA800000) && i != 0)
i--;
if (i == 0) {
- output("GE Timeout, status: %x\n",status);
- if(status & 0x80000000)
+ output("GE Timeout, status: %x\n", status);
+ if (status & 0x80000000)
output("Bresenham Engine : Busy\n");
- if(status & 0x40000000)
+ if (status & 0x40000000)
output("Setup Engine : Busy\n");
- if(status & 0x20000000)
+ if (status & 0x20000000)
output("SP / DPE : Busy\n");
- if(status & 0x10000000)
+ if (status & 0x10000000)
output("Memory Interface : Busy\n");
- if(status & 0x08000000)
+ if (status & 0x08000000)
output("Com Lst Proc : Busy\n");
- if(status & 0x04000000)
+ if (status & 0x04000000)
output("Block Write : Busy\n");
- if(status & 0x02000000)
+ if (status & 0x02000000)
output("Command Buffer : Full\n");
- if(status & 0x01000000)
+ if (status & 0x01000000)
output("RESERVED : Busy\n");
- if(status & 0x00800000)
+ if (status & 0x00800000)
output("PCI Write Buffer : Busy\n");
cyblafb_setup_GE(info->var.xres,
info->var.bits_per_pixel);
@@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info)
//
//==============================
-static void cyblafb_fillrect(struct fb_info * info,
- const struct fb_fillrect *fr)
+static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
{
- int bpp = info->var.bits_per_pixel;
- int col;
+ u32 bpp = info->var.bits_per_pixel, col, desty, height;
+
+ KD_GRAPHICS_RETURN();
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;
+ 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));
-
+ desty = fr->dy;
+ height = fr->height;
+ while (height) {
+ out32(GEB8, basestride | ((desty * info->var.xres_virtual *
+ bpp) >> 6));
+ out32(GE60, col);
+ out32(GE48, fr->rop ? 0x66 : ROP_S);
+ out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+ out32(GE08, point(fr->dx, 0));
+ out32(GE0C, point(fr->dx + fr->width - 1,
+ height > 4096 ? 4095 : height - 1));
+ if (likely(height <= 4096))
+ return;
+ desty += 4096;
+ height -= 4096;
+ }
}
-//==============================
+//================================================
//
// Cyberblade specific copyarea
//
-//==============================
+// This function silently assumes that it never
+// will be called with width or height exceeding
+// 4096.
+//
+//================================================
-static void cyblafb_copyarea(struct fb_info *info,
- const struct fb_copyarea *ca)
+static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
{
- __u32 s1,s2,d1,d2;
- int direction;
+ u32 s1, s2, d1, d2, direction;
+
+ KD_GRAPHICS_RETURN();
+
+ s1 = point(ca->sx, 0);
+ s2 = point(ca->sx + ca->width - 1, ca->height - 1);
+ d1 = point(ca->dx, 0);
+ d2 = point(ca->dx + ca->width - 1, ca->height - 1);
- 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);
-
+ out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
+ info->var.bits_per_pixel) >> 6));
+ out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
+ info->var.bits_per_pixel) >> 6));
+ 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.
+// Accelerated for the most usual case, blitting 1 - bit deep
+// character images. Everything else is passed to the generic imageblit
+// unless it is so insane that it is better to printk an alert.
+//
+// Hardware bug: _Never_ blit across pixel column 2048, that will lock
+// the system. We split those blit requests into three blitting
+// operations.
//
//=======================================================================
static void cyblafb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
-
u32 fgcol, bgcol;
+ u32 *pd = (u32 *) image->data;
+ u32 bpp = info->var.bits_per_pixel;
- 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);
+ KD_GRAPHICS_RETURN();
+
+ // Used only for drawing the penguine (image->depth > 1)
+ if (image->depth != 1) {
+ cfb_imageblit(info, image);
+ return;
+ }
+ // That should never happen, but it would be fatal
+ if (image->width == 0 || image->height == 0) {
+ output("imageblit: width/height 0 detected\n");
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];
+ 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;
+ case 8:
+ fgcol |= fgcol << 8;
+ bgcol |= bgcol << 8;
+ case 16:
+ fgcol |= fgcol << 16;
+ bgcol |= bgcol << 16;
+ 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));
+ out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
+ bpp) >> 6));
+ out32(GE60, fgcol);
+ out32(GE64, bgcol);
+
+ if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
+ u32 dds = ((image->width + 31) >> 5) * image->height;
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx, 0));
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ while (dds--)
+ out32(GE9C, *pd++);
+ } else {
+ int i, j;
+ u32 ddstotal = (image->width + 31) >> 5;
+ u32 ddsleft = (2048 - image->dx + 31) >> 5;
+ u32 skipleft = ddstotal - ddsleft;
+
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx, 0));
+ out32(GE0C, point(2048 - 1, image->height - 1));
+ for (i = 0; i < image->height; i++) {
+ for (j = 0; j < ddsleft; j++)
+ out32(GE9C, *pd++);
+ pd += skipleft;
+ }
- while(index < index_end) {
- const char *p = image->data + index;
- for(i=0;i<width_dds;i++) {
- out32(GE9C,*(u32*)p);
- p+=4;
- index+=4;
+ if (image->dx % 32) {
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(2048, 0));
+ if (image->width > ddsleft << 5)
+ out32(GE0C, point(image->dx + (ddsleft << 5) -
+ 1, image->height - 1));
+ else
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
+ for (i = 0; i < image->height; i++) {
+ out32(GE9C, swab32(swab32(*pd) << ((32 -
+ (image->dx & 31)) & 31)));
+ pd += ddstotal;
+ }
}
- switch(width_dbs) {
- case 0: break;
- case 8: out32(GE9C,*(u8*)p);
- index+=1;
- break;
- case 16: out32(GE9C,*(u16*)p);
- index+=2;
- break;
- case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16);
- index+=3;
- break;
+
+ if (skipleft) {
+ out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+ out32(GE08, point(image->dx + (ddsleft << 5), 0));
+ out32(GE0C, point(image->dx + image->width - 1,
+ image->height - 1));
+ pd = (u32 *) image->data;
+ for (i = 0; i < image->height; i++) {
+ pd += ddsleft;
+ for (j = 0; j < skipleft; j++)
+ out32(GE9C, *pd++);
+ }
}
}
}
@@ -443,7 +526,6 @@ 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,
@@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
// (This is what tridentfb does ... will be changed in the future)
//
//
- if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+ if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
bpp = 8;
- if (bpp == 24 )
+ if (bpp == 24)
bpp = var->bits_per_pixel = 32;
//
@@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
//
- // xres != xres_virtual is broken, fail if such an
- // unusual mode is requested
+ // we do not allow vclk to exceed 230 MHz. If the requested
+ // vclk is too high, we default to 200 MHz
//
- if (var->xres != var->xres_virtual)
- return -EINVAL;
+ if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
+ var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
//
- // we do not allow vclk to exceed 230 MHz
+ // enforce (h|v)sync_len limits
//
- if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
- return -EINVAL;
+ var->hsync_len &= ~7;
+ if(var->hsync_len > 248)
+ var->hsync_len = 248;
+
+ var->vsync_len &= 15;
//
- // 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
+ // Enforce horizontal and vertical hardware limits.
+ // 1600x1200 is mentioned as a maximum, but higher resolutions could
+ // work with slow refresh, small margins and short sync.
//
- 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)
+ var->xres &= ~7;
+
+ if (((var->xres + var->left_margin + var->right_margin +
+ var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
+ ((var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len) > 2047))
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:
+ if ((var->xres > 1600) || (var->yres > 1200))
+ output("Mode %dx%d exceeds documented limits.\n",
+ var->xres, var->yres);
+ //
+ // try to be smart about (x|y)res_virtual problems.
+ //
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ if (bpp == 8 || bpp == 16) {
+ if (var->xres_virtual > 4088)
+ var->xres_virtual = 4088;
+ } else {
+ if (var->xres_virtual > 2040)
+ var->xres_virtual = 2040;
+ }
+ var->xres_virtual &= ~7;
+ while (var->xres_virtual * var->yres_virtual * bpp / 8 >
+ info->fix.smem_len) {
+ if (var->yres_virtual > var->yres)
+ var->yres_virtual--;
+ else if (var->xres_virtual > var->xres)
+ var->xres_virtual -= 8;
+ else
return -EINVAL;
}
- return 0;
+ 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;
}
//=====================================================================
@@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
// 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.
//
+// BUT:
+//
+// As of internal version 0.60 we do not use vga panning any longer.
+// Vga panning did not allow us the use of all available video memory
+// and thus prevented ywrap scrolling. We do use the "right view"
+// register now.
+//
+//
//=====================================================================
static int cyblafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- unsigned int offset;
+ KD_GRAPHICS_RETURN(0);
- 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));
-
+ out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
+ var->xres_virtual)) * var->bits_per_pixel / 32));
return 0;
}
@@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par)
return;
printk("\n");
- for(i=0; i<=0xff; i++) {
- outb(i,0x3d4);
- printk("CR%02x=%02x ",i,inb(0x3d5));
- if (i%16==15)
+ 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));
+ 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)
+ if (i % 16 == 15)
printk("\n");
}
- outb(0x30,0x3ce);
- outb(inb(0x3cf) & 0xbf,0x3cf);
+ 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)
+ 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)
+ 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)
+ 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
+ inb(0x3DA); // reset internal flag to 3c0 index
+ outb(0x20, 0x3C0); // enable attr
+
+ return;
+}
+
+//=======================================================================
+//
+// Save State
+//
+// This function is called while a switch to KD_TEXT is in progress,
+// before any of the other functions are called.
+//
+//=======================================================================
+static void cyblafb_save_state(struct fb_info *info)
+{
+ struct cyblafb_par *par = info->par;
+ if (verbosity > 0)
+ output("Switching to KD_TEXT\n");
+ disabled = 0;
+ regdump(par);
+ enable_mmio();
+ return;
+}
+
+//=======================================================================
+//
+// Restore State
+//
+// This function is called while a switch to KD_GRAPHICS is in progress,
+// We have to turn on vga style panning registers again because the
+// trident driver of X does not know about GE10.
+//
+//=======================================================================
+
+static void cyblafb_restore_state(struct fb_info *info)
+{
+ if (verbosity > 0)
+ output("Switching to KD_GRAPHICS\n");
+ out32(GE10, 0);
+ disabled = 1;
return;
}
@@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par)
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;
+ 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;
+ KD_GRAPHICS_RETURN(0);
+
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);
+ 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;
+ 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);
+ preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
vtotal = var->yres + var->upper_margin + var->lower_margin +
- var->vsync_len - 2;
+ var->vsync_len - 2;
vdispend = var->yres - 1;
vsyncstart = var->yres + var->lower_margin;
vblankstart = var->yres;
@@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info)
enable_mmio(); // necessary! ... check X ...
- write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+ write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
- write3CE(GR30,8);
+ write3CE(GR30, 8);
if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
// stretch or center ?
- out8(0x3C2,0xEB);
+ out8(0x3C2, 0xEB);
- write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+ 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);
+ 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);
+ 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);
+ 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_virtual * bpp) / (4 * 16)) & 0xFF);
+ write3X4(CR14, 0x40); // double word mode
+ write3X4(CR15, vblankstart & 0xFF);
+ write3X4(CR16, vblankend & 0xFF);
+ write3X4(CR17, 0xE3);
+ 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);
+ 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
+ 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);
+ 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);
+ write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
+ 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
+ write3X4(CR2F, 0x92); // conservative, better signal quality
// CR30: reserved
// CR31: reserved
// CR32: reserved
@@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info)
// 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
+ 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
+ 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);
+ out8(0x3C4, 0x0b);
in8(0x3C5); // Set NEW mode
- write3C4(SR0D,0x00); // test ... check
+ write3C4(SR0D, 0x00); // test ... check
- set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
- info->var.pixclock); //SR18,SR19
+ 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,
+ 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); // vclk / 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
+ 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
+ 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); // 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) |
+ 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->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;
+ info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
+ info->cmap.len = (bpp == 8) ? 256 : 16;
//
// init acceleration engine
//
- cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+ cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
+
+ //
+ // Set/clear flags to allow proper scroll mode selection.
+ //
+ if (var->xres == var->xres_virtual)
+ info->flags &= ~FBINFO_HWACCEL_XPAN;
+ else
+ info->flags |= FBINFO_HWACCEL_XPAN;
+
+ if (var->yres == var->yres_virtual)
+ info->flags &= ~FBINFO_HWACCEL_YPAN;
+ else
+ info->flags |= FBINFO_HWACCEL_YPAN;
+
+ if (info->fix.smem_len !=
+ var->xres_virtual * var->yres_virtual * bpp / 8)
+ info->flags &= ~FBINFO_HWACCEL_YWRAP;
+ else
+ info->flags |= FBINFO_HWACCEL_YWRAP;
regdump(par);
@@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
{
int bpp = info->var.bits_per_pixel;
+ KD_GRAPHICS_RETURN(0);
+
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);
+ 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;
}
@@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int cyblafb_blank(int blank_mode, struct fb_info *info)
{
- unsigned char PMCont,DPMSCont;
+ unsigned char PMCont, DPMSCont;
+
+ KD_GRAPHICS_RETURN(0);
if (displaytype == DISPLAY_FP)
return 0;
- out8(0x83C8,0x04); // DPMS Control
+ 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
+ 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
+ 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
+ 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
+ case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off
PMCont |= 0x00;
DPMSCont |= 0x03;
break;
}
- write3CE(GR23,DPMSCont);
- out8(0x83C8,4);
- out8(0x83C6,PMCont);
+ write3CE(GR23, DPMSCont);
+ out8(0x83C8, 4);
+ out8(0x83C6, PMCont);
//
// let fbcon do a softblank for us
//
@@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info)
}
static struct fb_ops cyblafb_ops __devinitdata = {
- .owner = THIS_MODULE,
+ .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_copyarea = cyblafb_copyarea,
.fb_imageblit = cyblafb_imageblit,
+ .fb_sync = cyblafb_sync,
+ .fb_restore_state = cyblafb_restore_state,
+ .fb_save_state = cyblafb_save_state,
};
//==========================================================================
@@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = {
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;
+ 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}
+ int xres; int vxres; 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, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
+ 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
+ 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
+ 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
+ 1280, 2048, 1024, 4096, 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;
+ 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;
+ 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;
+ 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;
+ | (cr27 & 0x40) << 4;
+ vblankend = cr16;
- modedb[0].yres = vdispend + 1;
- modedb[0].vsync_len = vsyncend;
+ 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;
+ 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;
+ tmp == 8 ? 32 : 8;
- fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+ 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 !
@@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info)
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].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);
//
@@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info)
// do not want to do it in another way!
//
- tryagain:
+ 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;
+ !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) {
+ 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
- ));
+ ((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;
+ if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
+ info->var.xres_virtual = modedb[i].vxres;
+ else
+ 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;
@@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info)
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
+ 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){
+ 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;
+ // try 640x480 - 8@75 ...
+ if (i == 0) {
+ mode = "640x480";
+ bpp = 8;
+ ref = 75;
output("Detected mode failed check_var! "
- "Trying 640x480-8@75\n");
+ "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;
+ "Falling back to startup mode.\n", mode);
+ mode = NULL;
goto tryagain;
}
return 0;
-
}
//========================================================
@@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void)
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);
+ case 0x03:
+ k = 1 * 1024 * 1024;
+ break;
+ case 0x07:
+ k = 2 * 1024 * 1024;
+ break;
+ case 0x0F:
+ k = 4 * 1024 * 1024;
+ break;
+ case 0x04:
+ k = 8 * 1024 * 1024;
+ break;
+ default:
+ k = 1 * 1024 * 1024;
+ 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);
+ output("framebuffer size = %d Kb\n", k / Kb);
return k;
}
@@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void)
return DISPLAY_FP;
if (crt)
return DISPLAY_CRT;
- return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+ return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
}
//=====================================
@@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void)
static int __devinit get_nativex(void)
{
- int x,y,tmp;
+ int x, y, tmp;
if (nativex)
return nativex;
@@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void)
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;
+ 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);
+ 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)
+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);
-
+ info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
if (!info)
- goto errout_alloc;
+ goto errout_alloc_info;
+
+ info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ output("allocation of pixmap buffer failed!\n");
+ goto errout_alloc_pixmap;
+ }
+ info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
+ info->pixmap.buf_align = 4;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 4;
par = info->par;
par->ops = cyblafb_ops;
@@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * 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");
+ if (!request_region(0x3c0, 0x20, "cyblafb")) {
+ output("region 0x3c0/0x20 already reserved\n");
+ vesafb |= 1;
+ }
//
// Graphics Engine Registers
//
- request_region(GEBase,0x100,"cyblafb");
+ if (!request_region(GEBase, 0x100, "cyblafb")) {
+ output("region %#x/0x100 already reserved\n", GEBase);
+ vesafb |= 2;
+ }
regdump(par);
enable_mmio();
// setup MMIO region
- info->fix.mmio_start = pci_resource_start(dev,1);
+ 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")) {
+ info->fix.mmio_len, "cyblafb")) {
output("request_mem_region failed for mmio region!\n");
goto errout_mmio_reqmem;
}
@@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
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);
+ // is useful if both are loaded.
+ 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->fix.smem_len, "cyblafb")) {
+ output("region %#lx/%#x already reserved\n",
+ info->fix.smem_start, info->fix.smem_len);
+ vesafb |= 4;
}
info->screen_base = ioremap_nocache(info->fix.smem_start,
@@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
displaytype = get_displaytype();
- if(displaytype == DISPLAY_FP)
+ 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->flags = FBINFO_DEFAULT
+ | FBINFO_HWACCEL_COPYAREA
+ | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_IMAGEBLIT
+ | FBINFO_READS_FAST
+// | FBINFO_PARTIAL_PAN_OK
+ | FBINFO_MISC_ALWAYS_SETPAR;
info->pseudo_palette = par->pseudo_pal;
- if(getstartupmode(info))
+ if (getstartupmode(info))
goto errout_findmode;
- fb_alloc_cmap(&info->cmap,256,0);
+ 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);
+ pci_set_drvdata(dev, info);
//
// normal exit and error paths
@@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
return 0;
- errout_register:
- errout_findmode:
+ 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:
+ errout_smem_remap:
+ if (!(vesafb & 4))
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
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:
+ errout_mmio_remap:
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ errout_mmio_reqmem:
+ if (!(vesafb & 1))
+ release_region(0x3c0, 32);
+ errout_enable:
+ kfree(info->pixmap.addr);
+ errout_alloc_pixmap:
framebuffer_release(info);
- errout_alloc:
- output("CyblaFB version %s aborting init.\n",VERSION);
+ errout_alloc_info:
+ output("CyblaFB version %s aborting init.\n", VERSION);
return -ENODEV;
}
@@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *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);
+ if (!(vesafb & 4))
+ 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);
+ if (!(vesafb & 2))
+ release_region(GEBase, 0x100);
+ if (!(vesafb & 1))
+ release_region(0x3c0, 32);
+ kfree(info->pixmap.addr);
framebuffer_release(info);
- output("CyblaFB version %s normal exit.\n",VERSION);
+ 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},
+ {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
-MODULE_DEVICE_TABLE(pci,cybla_devices);
+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)
+ .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 ...
+// video=cyblafb:1280x1024, bpp=16, ref=50 ...
//
// modprobe command line example:
//
@@ -1401,46 +1627,46 @@ static int __devinit cyblafb_init(void)
char *options = NULL;
char *opt;
- if (fb_get_options("cyblafb",&options))
+ 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))
+ 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))
+ 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))
+ 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))
+ 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 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
mode = opt;
}
#endif
- output("CyblaFB version %s initializing\n",VERSION);
+ output("CyblaFB version %s initializing\n", VERSION);
return pci_module_init(&cyblafb_pci_driver);
+ return pci_register_driver(&cyblafb_pci_driver);
}
static void __exit cyblafb_exit(void)
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index 0b6af00d197e..ac90883dc3aa 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -214,12 +214,11 @@ 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);
+ u8 *buf = kzalloc(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;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 10dfdf035264..d2dede6ed3e5 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -589,17 +589,19 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
return info->fbops->fb_read(file, buf, count, ppos);
total_size = info->screen_size;
+
if (total_size == 0)
total_size = info->fix.smem_len;
if (p >= total_size)
- return 0;
+ return 0;
+
if (count >= total_size)
- count = total_size;
+ count = total_size;
+
if (count + p > total_size)
count = total_size - p;
- cnt = 0;
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
@@ -636,6 +638,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
}
kfree(buffer);
+
return (err) ? err : cnt;
}
@@ -648,7 +651,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
struct fb_info *info = registered_fb[fbidx];
u32 *buffer, *src;
u32 __iomem *dst;
- int c, i, cnt = 0, err;
+ int c, i, cnt = 0, err = 0;
unsigned long total_size;
if (!info || !info->screen_base)
@@ -661,19 +664,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
return info->fbops->fb_write(file, buf, count, ppos);
total_size = info->screen_size;
+
if (total_size == 0)
total_size = info->fix.smem_len;
if (p > total_size)
- return -ENOSPC;
+ return 0;
+
if (count >= total_size)
- count = total_size;
- err = 0;
- if (count + p > total_size) {
- count = total_size - p;
- err = -ENOSPC;
- }
- cnt = 0;
+ count = total_size;
+
+ if (count + p > total_size)
+ count = total_size - p;
+
buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
@@ -687,12 +690,15 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
while (count) {
c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
src = buffer;
+
if (copy_from_user(src, buf, c)) {
err = -EFAULT;
break;
}
+
for (i = c >> 2; i--; )
fb_writel(*src++, dst++);
+
if (c & 3) {
u8 *src8 = (u8 *) src;
u8 __iomem *dst8 = (u8 __iomem *) dst;
@@ -702,11 +708,13 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
dst = (u32 __iomem *) dst8;
}
+
*ppos += c;
buf += c;
cnt += c;
count -= c;
}
+
kfree(buffer);
return (err) ? err : cnt;
@@ -949,7 +957,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
default:
if (fb->fb_ioctl == NULL)
return -EINVAL;
- return fb->fb_ioctl(inode, file, cmd, arg, info);
+ return fb->fb_ioctl(info, cmd, arg);
}
}
@@ -1099,7 +1107,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
default:
if (fb->fb_compat_ioctl)
- ret = fb->fb_compat_ioctl(file, cmd, arg, info);
+ ret = fb->fb_compat_ioctl(info, cmd, arg);
break;
}
unlock_kernel();
@@ -1127,7 +1135,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
if (fb->fb_mmap) {
int res;
lock_kernel();
- res = fb->fb_mmap(info, file, vma);
+ res = fb->fb_mmap(info, vma);
unlock_kernel();
return res;
}
@@ -1226,6 +1234,7 @@ fb_open(struct inode *inode, struct file *file)
return -ENODEV;
if (!try_module_get(info->fbops->owner))
return -ENODEV;
+ file->private_data = info;
if (info->fbops->fb_open) {
res = info->fbops->fb_open(info,1);
if (res)
@@ -1237,11 +1246,9 @@ fb_open(struct inode *inode, struct file *file)
static int
fb_release(struct inode *inode, struct file *file)
{
- int fbidx = iminor(inode);
- struct fb_info *info;
+ struct fb_info * const info = file->private_data;
lock_kernel();
- info = registered_fb[fbidx];
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
module_put(info->fbops->owner);
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index fc7965b66775..7c74e7325d95 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -317,26 +317,29 @@ static int edid_is_monitor_block(unsigned char *block)
static void calc_mode_timings(int xres, int yres, int refresh,
struct fb_videomode *mode)
{
- struct fb_var_screeninfo var;
- struct fb_info info;
+ struct fb_var_screeninfo *var;
- memset(&var, 0, sizeof(struct fb_var_screeninfo));
- var.xres = xres;
- var.yres = yres;
- fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
- refresh, &var, &info);
- mode->xres = xres;
- mode->yres = yres;
- mode->pixclock = var.pixclock;
- mode->refresh = refresh;
- mode->left_margin = var.left_margin;
- mode->right_margin = var.right_margin;
- mode->upper_margin = var.upper_margin;
- mode->lower_margin = var.lower_margin;
- mode->hsync_len = var.hsync_len;
- mode->vsync_len = var.vsync_len;
- mode->vmode = 0;
- mode->sync = 0;
+ var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+
+ if (var) {
+ var->xres = xres;
+ var->yres = yres;
+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
+ refresh, var, NULL);
+ mode->xres = xres;
+ mode->yres = yres;
+ mode->pixclock = var->pixclock;
+ mode->refresh = refresh;
+ mode->left_margin = var->left_margin;
+ mode->right_margin = var->right_margin;
+ mode->upper_margin = var->upper_margin;
+ mode->lower_margin = var->lower_margin;
+ mode->hsync_len = var->hsync_len;
+ mode->vsync_len = var->vsync_len;
+ mode->vmode = 0;
+ mode->sync = 0;
+ kfree(var);
+ }
}
static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
@@ -525,10 +528,9 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
unsigned char *block;
int num = 0, i;
- mode = kmalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+ mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
if (mode == NULL)
return NULL;
- memset(mode, 0, 50 * sizeof(struct fb_videomode));
if (edid == NULL || !edid_checksum(edid) ||
!edid_check_header(edid)) {
@@ -1105,15 +1107,21 @@ static void fb_timings_dclk(struct __fb_timings *timings)
*/
int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct __fb_timings timings;
+ struct __fb_timings *timings;
u32 interlace = 1, dscan = 1;
- u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
+ u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+
+ timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
+
+ if (!timings)
+ return -ENOMEM;
/*
* If monspecs are invalid, use values that are enough
* for 640x480@60
*/
- if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+ if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
!info->monspecs.dclkmax ||
info->monspecs.hfmax < info->monspecs.hfmin ||
info->monspecs.vfmax < info->monspecs.vfmin ||
@@ -1130,65 +1138,66 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
dclkmax = info->monspecs.dclkmax;
}
- memset(&timings, 0, sizeof(struct __fb_timings));
- timings.hactive = var->xres;
- timings.vactive = var->yres;
+ timings->hactive = var->xres;
+ timings->vactive = var->yres;
if (var->vmode & FB_VMODE_INTERLACED) {
- timings.vactive /= 2;
+ timings->vactive /= 2;
interlace = 2;
}
if (var->vmode & FB_VMODE_DOUBLE) {
- timings.vactive *= 2;
+ timings->vactive *= 2;
dscan = 2;
}
switch (flags & ~FB_IGNOREMON) {
case FB_MAXTIMINGS: /* maximize refresh rate */
- timings.hfreq = hfmax;
- fb_timings_hfreq(&timings);
- if (timings.vfreq > vfmax) {
- timings.vfreq = vfmax;
- fb_timings_vfreq(&timings);
+ timings->hfreq = hfmax;
+ fb_timings_hfreq(timings);
+ if (timings->vfreq > vfmax) {
+ timings->vfreq = vfmax;
+ fb_timings_vfreq(timings);
}
- if (timings.dclk > dclkmax) {
- timings.dclk = dclkmax;
- fb_timings_dclk(&timings);
+ if (timings->dclk > dclkmax) {
+ timings->dclk = dclkmax;
+ fb_timings_dclk(timings);
}
break;
case FB_VSYNCTIMINGS: /* vrefresh driven */
- timings.vfreq = val;
- fb_timings_vfreq(&timings);
+ timings->vfreq = val;
+ fb_timings_vfreq(timings);
break;
case FB_HSYNCTIMINGS: /* hsync driven */
- timings.hfreq = val;
- fb_timings_hfreq(&timings);
+ timings->hfreq = val;
+ fb_timings_hfreq(timings);
break;
case FB_DCLKTIMINGS: /* pixelclock driven */
- timings.dclk = PICOS2KHZ(val) * 1000;
- fb_timings_dclk(&timings);
+ timings->dclk = PICOS2KHZ(val) * 1000;
+ fb_timings_dclk(timings);
break;
default:
- return -EINVAL;
+ err = -EINVAL;
}
- if (!(flags & FB_IGNOREMON) &&
- (timings.vfreq < vfmin || timings.vfreq > vfmax ||
- timings.hfreq < hfmin || timings.hfreq > hfmax ||
- timings.dclk < dclkmin || timings.dclk > dclkmax))
- return -EINVAL;
-
- var->pixclock = KHZ2PICOS(timings.dclk/1000);
- var->hsync_len = (timings.htotal * 8)/100;
- var->right_margin = (timings.hblank/2) - var->hsync_len;
- var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
-
- var->vsync_len = (3 * interlace)/dscan;
- var->lower_margin = (1 * interlace)/dscan;
- var->upper_margin = (timings.vblank * interlace)/dscan -
- (var->vsync_len + var->lower_margin);
+ if (err || (!(flags & FB_IGNOREMON) &&
+ (timings->vfreq < vfmin || timings->vfreq > vfmax ||
+ timings->hfreq < hfmin || timings->hfreq > hfmax ||
+ timings->dclk < dclkmin || timings->dclk > dclkmax))) {
+ err = -EINVAL;
+ } else {
+ var->pixclock = KHZ2PICOS(timings->dclk/1000);
+ var->hsync_len = (timings->htotal * 8)/100;
+ var->right_margin = (timings->hblank/2) - var->hsync_len;
+ var->left_margin = timings->hblank - var->right_margin -
+ var->hsync_len;
+ var->vsync_len = (3 * interlace)/dscan;
+ var->lower_margin = (1 * interlace)/dscan;
+ var->upper_margin = (timings->vblank * interlace)/dscan -
+ (var->vsync_len + var->lower_margin);
+ }
- return 0;
+ kfree(timings);
+ return err;
}
#else
int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 08dac9580d15..6d26057337e2 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -43,10 +43,11 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
if (size)
fb_info_size += PADDING;
- p = kmalloc(fb_info_size + size, GFP_KERNEL);
+ p = kzalloc(fb_info_size + size, GFP_KERNEL);
+
if (!p)
return NULL;
- memset(p, 0, fb_info_size + size);
+
info = (struct fb_info *) p;
if (size)
@@ -106,8 +107,7 @@ static int mode_string(char *buf, unsigned int offset,
static ssize_t store_mode(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
char mstr[100];
struct fb_var_screeninfo var;
struct fb_modelist *modelist;
@@ -137,8 +137,7 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf,
static ssize_t show_mode(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
if (!fb_info->mode)
return 0;
@@ -149,8 +148,7 @@ static ssize_t show_mode(struct class_device *class_device, char *buf)
static ssize_t store_modes(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
LIST_HEAD(old_list);
int i = count / sizeof(struct fb_videomode);
@@ -174,8 +172,7 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf,
static ssize_t show_modes(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
unsigned int i;
struct list_head *pos;
struct fb_modelist *modelist;
@@ -193,8 +190,7 @@ static ssize_t show_modes(struct class_device *class_device, char *buf)
static ssize_t store_bpp(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char ** last = NULL;
int err;
@@ -208,8 +204,7 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf,
static ssize_t show_bpp(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
}
@@ -280,8 +275,7 @@ static ssize_t show_con_rotate(struct class_device *class_device, char *buf)
static ssize_t store_virtual(struct class_device *class_device,
const char * buf, size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -300,16 +294,14 @@ static ssize_t store_virtual(struct class_device *class_device,
static ssize_t show_virtual(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
fb_info->var.yres_virtual);
}
static ssize_t show_stride(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
@@ -320,7 +312,7 @@ static ssize_t show_stride(struct class_device *class_device, char *buf)
static ssize_t store_cmap(struct class_device *class_device, const char *buf,
size_t count)
{
- struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
int rc, i, start, length, transp = 0;
if ((count > PAGE_SIZE) || ((count % 16) != 0))
@@ -380,8 +372,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf,
static ssize_t show_cmap(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
unsigned int i;
if (!fb_info->cmap.red || !fb_info->cmap.blue ||
@@ -405,8 +396,7 @@ static ssize_t show_cmap(struct class_device *class_device, char *buf)
static ssize_t store_blank(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
char *last = NULL;
int err;
@@ -422,41 +412,40 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf,
static ssize_t show_blank(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_console(struct class_device *class_device,
const char * buf, size_t count)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t show_console(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_cursor(struct class_device *class_device,
const char * buf, size_t count)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t show_cursor(struct class_device *class_device, char *buf)
{
-// struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+// struct fb_info *fb_info = class_get_devdata(class_device);
return 0;
}
static ssize_t store_pan(struct class_device *class_device, const char * buf,
size_t count)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@@ -479,19 +468,40 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf,
static ssize_t show_pan(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info =
- (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
fb_info->var.xoffset);
}
static ssize_t show_name(struct class_device *class_device, char *buf)
{
- struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+ struct fb_info *fb_info = class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
}
+static ssize_t store_fbstate(struct class_device *class_device,
+ const char *buf, size_t count)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ u32 state;
+ char *last = NULL;
+
+ state = simple_strtoul(buf, &last, 0);
+
+ acquire_console_sem();
+ fb_set_suspend(fb_info, (int)state);
+ release_console_sem();
+
+ return count;
+}
+
+static ssize_t show_fbstate(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
+}
+
static struct class_device_attribute class_device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
@@ -507,6 +517,7 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
__ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
__ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
+ __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
};
int fb_init_class_device(struct fb_info *fb_info)
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index c4870d559afc..9c9b21d469a1 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -37,9 +37,8 @@ static void ffb_imageblit(struct fb_info *, const struct fb_image *);
static void ffb_fillrect(struct fb_info *, const struct fb_fillrect *);
static void ffb_copyarea(struct fb_info *, const struct fb_copyarea *);
static int ffb_sync(struct fb_info *);
-static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int ffb_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int ffb_mmap(struct fb_info *, struct vm_area_struct *);
+static int ffb_ioctl(struct fb_info *, unsigned int, unsigned long);
static int ffb_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -839,7 +838,7 @@ static struct sbus_mmap_map ffb_mmap_map[] = {
{ .size = 0 }
};
-static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct ffb_par *par = (struct ffb_par *)info->par;
@@ -848,8 +847,7 @@ static int ffb_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
0, vma);
}
-static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct ffb_par *par = (struct ffb_par *) info->par;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index d744c51807b7..38d22729b129 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -979,7 +979,7 @@ static int gbefb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return 0;
}
-static int gbefb_mmap(struct fb_info *info, struct file *file,
+static int gbefb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
@@ -1000,7 +1000,6 @@ static int gbefb_mmap(struct fb_info *info, struct file *file,
pgprot_fb(pgprot_val(vma->vm_page_prot));
vma->vm_flags |= VM_IO | VM_RESERVED;
- vma->vm_file = file;
/* look for the starting tile */
tile = &gbe_tiles.cpu[offset >> TILE_SHIFT];
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 8e8da7433994..20e69156d728 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -215,11 +215,11 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
if (ret < 0)
return ret;
- ret = pci_request_region(dev, 1, "gx1fb (video)");
+ ret = pci_request_region(dev, 0, "gx1fb (video)");
if (ret < 0)
return ret;
- par->vid_regs = ioremap(pci_resource_start(dev, 1),
- pci_resource_len(dev, 1));
+ par->vid_regs = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
if (!par->vid_regs)
return -ENOMEM;
@@ -229,12 +229,9 @@ static int __init gx1fb_map_video_memory(struct fb_info *info, struct pci_dev *d
if (!par->dc_regs)
return -ENOMEM;
- 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_start = gx_base + 0x800000;
info->fix.smem_len = fb_len;
info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
if (!info->screen_base)
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index b37cea7d1094..4e39035cf335 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -42,6 +42,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/vga.h>
@@ -107,7 +108,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
/* Framebuffer driver structures */
-static struct fb_var_screeninfo hga_default_var = {
+static struct fb_var_screeninfo __initdata hga_default_var = {
.xres = 720,
.yres = 348,
.xres_virtual = 720,
@@ -121,7 +122,7 @@ static struct fb_var_screeninfo hga_default_var = {
.width = -1,
};
-static struct fb_fix_screeninfo hga_fix = {
+static struct fb_fix_screeninfo __initdata hga_fix = {
.id = "HGA",
.type = FB_TYPE_PACKED_PIXELS, /* (not sure) */
.visual = FB_VISUAL_MONO10,
@@ -131,8 +132,6 @@ static struct fb_fix_screeninfo hga_fix = {
.accel = FB_ACCEL_NONE
};
-static struct fb_info fb_info;
-
/* Don't assume that tty1 will be the initial current console. */
static int release_io_port = 0;
static int release_io_ports = 0;
@@ -549,10 +548,9 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-static int __init hgafb_init(void)
+static int __init hgafb_probe(struct device *device)
{
- if (fb_get_options("hgafb", NULL))
- return -ENODEV;
+ struct fb_info *info;
if (! hga_card_detect()) {
printk(KERN_INFO "hgafb: HGA card not detected.\n");
@@ -564,41 +562,95 @@ static int __init hgafb_init(void)
printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
hga_type_name, hga_vram_len/1024);
+ info = framebuffer_alloc(0, NULL);
+ if (!info) {
+ iounmap(hga_vram);
+ return -ENOMEM;
+ }
+
hga_fix.smem_start = (unsigned long)hga_vram;
hga_fix.smem_len = hga_vram_len;
- fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
- fb_info.var = hga_default_var;
- fb_info.fix = hga_fix;
- fb_info.monspecs.hfmin = 0;
- fb_info.monspecs.hfmax = 0;
- fb_info.monspecs.vfmin = 10000;
- fb_info.monspecs.vfmax = 10000;
- fb_info.monspecs.dpms = 0;
- fb_info.fbops = &hgafb_ops;
- fb_info.screen_base = hga_vram;
-
- if (register_framebuffer(&fb_info) < 0) {
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+ info->var = hga_default_var;
+ info->fix = hga_fix;
+ info->monspecs.hfmin = 0;
+ info->monspecs.hfmax = 0;
+ info->monspecs.vfmin = 10000;
+ info->monspecs.vfmax = 10000;
+ info->monspecs.dpms = 0;
+ info->fbops = &hgafb_ops;
+ info->screen_base = hga_vram;
+
+ if (register_framebuffer(info) < 0) {
+ framebuffer_release(info);
iounmap(hga_vram);
return -EINVAL;
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ info->node, info->fix.id);
+ dev_set_drvdata(device, info);
return 0;
}
-#ifdef MODULE
-static void __exit hgafb_exit(void)
+static int hgafb_remove(struct device *device)
{
+ struct fb_info *info = dev_get_drvdata(device);
+
hga_txt_mode();
hga_clear_screen();
- unregister_framebuffer(&fb_info);
+
+ if (info) {
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+ }
+
iounmap(hga_vram);
- if (release_io_ports) release_region(0x3b0, 12);
- if (release_io_port) release_region(0x3bf, 1);
+
+ if (release_io_ports)
+ release_region(0x3b0, 12);
+
+ if (release_io_port)
+ release_region(0x3bf, 1);
+
+ return 0;
+}
+
+static struct device_driver hgafb_driver = {
+ .name = "hgafb",
+ .bus = &platform_bus_type,
+ .probe = hgafb_probe,
+ .remove = hgafb_remove,
+};
+
+static struct platform_device hgafb_device = {
+ .name = "hgafb",
+};
+
+static int __init hgafb_init(void)
+{
+ int ret;
+
+ if (fb_get_options("hgafb", NULL))
+ return -ENODEV;
+
+ ret = driver_register(&hgafb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&hgafb_device);
+ if (ret)
+ driver_unregister(&hgafb_driver);
+ }
+
+ return ret;
+}
+
+static void __exit hgafb_exit(void)
+{
+ platform_device_unregister(&hgafb_device);
+ driver_unregister(&hgafb_driver);
}
-#endif
/* -------------------------------------------------------------------------
*
@@ -613,7 +665,4 @@ MODULE_LICENSE("GPL");
module_param(nologo, bool, 0);
MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
module_init(hgafb_init);
-
-#ifdef MODULE
module_exit(hgafb_exit);
-#endif
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index c61bad0da20f..bd410e06db73 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -17,6 +17,7 @@
#include <linux/fb.h>
#include "i810.h"
#include "i810_regs.h"
+#include "i810_main.h"
#include "../edid.h"
#define I810_DDC 0x50
@@ -42,7 +43,7 @@
static void i810i2c_setscl(void *data, int state)
{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_i2c_chan *chan = data;
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/i810/i810_accel.c
index 64cd1c827cf0..76764ea3486a 100644
--- a/drivers/video/i810/i810_accel.c
+++ b/drivers/video/i810/i810_accel.c
@@ -14,6 +14,7 @@
#include "i810_regs.h"
#include "i810.h"
+#include "i810_main.h"
static u32 i810fb_rop[] = {
COLOR_COPY_ROP, /* ROP_COPY */
@@ -57,7 +58,7 @@ static inline void i810_report_error(u8 __iomem *mmio)
*/
static inline int wait_for_space(struct fb_info *info, u32 space)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 head, count = WAIT_COUNT, tail;
u8 __iomem *mmio = par->mmio_start_virtual;
@@ -88,7 +89,7 @@ static inline int wait_for_space(struct fb_info *info, u32 space)
*/
static inline int wait_for_engine_idle(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
int count = WAIT_COUNT;
@@ -116,7 +117,7 @@ static inline int wait_for_engine_idle(struct fb_info *info)
*/
static inline u32 begin_iring(struct fb_info *info, u32 space)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (par->dev_flags & ALWAYS_SYNC)
wait_for_engine_idle(info);
@@ -161,7 +162,7 @@ static inline void source_copy_blit(int dwidth, int dheight, int dpitch,
int xdir, int src, int dest, int rop,
int blit_bpp, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + IRING_PAD)) return;
@@ -195,7 +196,7 @@ static inline void color_blit(int width, int height, int pitch, int dest,
int rop, int what, int blit_bpp,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + IRING_PAD)) return;
@@ -236,7 +237,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
int dest, const u32 *src, int bg,
int fg, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 24 + (dsize << 2) + IRING_PAD)) return;
@@ -254,7 +255,7 @@ static inline void mono_src_copy_imm_blit(int dwidth, int dheight, int dpitch,
static inline void load_front(int offset, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (begin_iring(info, 8 + IRING_PAD)) return;
@@ -296,7 +297,7 @@ static inline void i810fb_iring_enable(struct i810fb_par *par, u32 mode)
void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 dx, dy, width, height, dest, rop = 0, color = 0;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -322,7 +323,7 @@ void i810fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 sx, sy, dx, dy, pitch, width, height, src, dest, xdir;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -361,7 +362,7 @@ void i810fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 fg = 0, bg = 0, size, dst;
if (!info->var.accel_flags || par->dev_flags & LOCKUP ||
@@ -397,7 +398,7 @@ void i810fb_imageblit(struct fb_info *info, const struct fb_image *image)
int i810fb_sync(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
if (!info->var.accel_flags || par->dev_flags & LOCKUP)
return 0;
@@ -407,7 +408,7 @@ int i810fb_sync(struct fb_info *info)
void i810fb_load_front(u32 offset, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
if (!info->var.accel_flags || par->dev_flags & LOCKUP)
@@ -427,7 +428,7 @@ void i810fb_load_front(u32 offset, struct fb_info *info)
*/
void i810fb_init_ringbuffer(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 tmp1, tmp2;
u8 __iomem *mmio = par->mmio_start_virtual;
diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/i810/i810_gtf.c
index 64f087a4466b..9743d51e7f8c 100644
--- a/drivers/video/i810/i810_gtf.c
+++ b/drivers/video/i810/i810_gtf.c
@@ -14,6 +14,7 @@
#include "i810_regs.h"
#include "i810.h"
+#include "i810_main.h"
/*
* FIFO and Watermark tables - based almost wholly on i810_wmark.c in
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index c0c974b1afaa..266d0ab92663 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -42,20 +42,62 @@
#include <linux/pci_ids.h>
#include <linux/resource.h>
#include <linux/unistd.h>
+#include <linux/console.h>
#include <asm/io.h>
#include <asm/div64.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
#include <asm/page.h>
#include "i810_regs.h"
#include "i810.h"
#include "i810_main.h"
+/*
+ * voffset - framebuffer offset in MiB from aperture start address. In order for
+ * the driver to work with X, we must try to use memory holes left untouched by X. The
+ * following table lists where X's different surfaces start at.
+ *
+ * ---------------------------------------------
+ * : : 64 MiB : 32 MiB :
+ * ----------------------------------------------
+ * : FrontBuffer : 0 : 0 :
+ * : DepthBuffer : 48 : 16 :
+ * : BackBuffer : 56 : 24 :
+ * ----------------------------------------------
+ *
+ * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
+ * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
+ * work, allowing 7 + 1 MiB of Framebuffer memory.
+ * Note, the size of the hole may change depending on how much memory you allocate to X,
+ * and how the memory is split up between these surfaces.
+ *
+ * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
+ * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
+ *
+ * Experiment with v_offset to find out which works best for you.
+ */
+static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
+static u32 voffset __initdata = 0;
+
+static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
+static int __devinit i810fb_init_pci (struct pci_dev *dev,
+ const struct pci_device_id *entry);
+static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static int i810fb_resume(struct pci_dev *dev);
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
+
+/* Chipset Specific Functions */
+static int i810fb_set_par (struct fb_info *info);
+static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
+ u8 *transp, struct fb_info *info);
+static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info);
+static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int i810fb_blank (int blank_mode, struct fb_info *info);
+
+/* Initialization */
+static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
+
/* PCI */
static const char *i810_pci_list[] __devinitdata = {
"Intel(R) 810 Framebuffer Device" ,
@@ -776,7 +818,7 @@ static void i810_load_cursor_image(int width, int height, u8 *data,
static void i810_load_cursor_colors(int fg, int bg, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 red, green, blue, trans, temp;
@@ -949,7 +991,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
static int i810_check_params(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
int line_length, vidmem, mode_valid = 0, retval = 0;
u32 vyres = var->yres_virtual, vxres = var->xres_virtual;
/*
@@ -1043,7 +1085,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
*/
static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
@@ -1154,7 +1196,7 @@ static void decode_var(const struct fb_var_screeninfo *var,
static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
u8 *transp, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 temp;
@@ -1193,7 +1235,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
static int i810fb_open(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count = atomic_read(&par->use_count);
if (count == 0) {
@@ -1212,7 +1254,7 @@ static int i810fb_open(struct fb_info *info, int user)
static int i810fb_release(struct fb_info *info, int user)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 count;
count = atomic_read(&par->use_count);
@@ -1234,7 +1276,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
u8 temp;
int i;
@@ -1328,7 +1370,7 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int i810fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u32 total;
total = var->xoffset * par->depth +
@@ -1340,7 +1382,7 @@ static int i810fb_pan_display(struct fb_var_screeninfo *var,
static int i810fb_blank (int blank_mode, struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
int mode = 0, pwr, scr_off = 0;
@@ -1385,7 +1427,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info)
static int i810fb_set_par(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
decode_var(&info->var, par);
i810_load_regs(par);
@@ -1429,7 +1471,7 @@ static int i810fb_check_var(struct fb_var_screeninfo *var,
static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct i810fb_par *par = (struct i810fb_par *)info->par;
+ struct i810fb_par *par = info->par;
u8 __iomem *mmio = par->mmio_start_virtual;
if (!par->dev_flags & LOCKUP)
@@ -1516,36 +1558,29 @@ static struct fb_ops i810fb_ops __devinitdata = {
static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
- int blank = 0, prev_state = par->cur_state;
-
- if (state.event == prev_state)
- return 0;
+ struct i810fb_par *par = info->par;
par->cur_state = state.event;
- switch (state.event) {
- case 1:
- blank = VESA_VSYNC_SUSPEND;
- break;
- case 2:
- blank = VESA_HSYNC_SUSPEND;
- break;
- case 3:
- blank = VESA_POWERDOWN;
- break;
- default:
- return -EINVAL;
+ if (state.event == PM_EVENT_FREEZE) {
+ dev->dev.power.power_state = state;
+ return 0;
}
- info->fbops->fb_blank(blank, info);
- if (!prev_state) {
- agp_unbind_memory(par->i810_gtt.i810_fb_memory);
- agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
- pci_disable_device(dev);
- }
+ acquire_console_sem();
+ fb_set_suspend(info, 1);
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+ i810fb_blank(FB_BLANK_POWERDOWN, info);
+ agp_unbind_memory(par->i810_gtt.i810_fb_memory);
+ agp_unbind_memory(par->i810_gtt.i810_cursor_memory);
+
pci_save_state(dev);
+ pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
+ release_console_sem();
return 0;
}
@@ -1553,23 +1588,29 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
static int i810fb_resume(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
+ int cur_state = par->cur_state;
+
+ par->cur_state = PM_EVENT_ON;
- if (par->cur_state == 0)
+ if (cur_state == PM_EVENT_FREEZE) {
+ pci_set_power_state(dev, PCI_D0);
return 0;
+ }
- pci_restore_state(dev);
+ acquire_console_sem();
pci_set_power_state(dev, PCI_D0);
+ pci_restore_state(dev);
pci_enable_device(dev);
+ pci_set_master(dev);
agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset);
agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset);
-
+ i810fb_set_par(info);
+ fb_set_suspend (info, 0);
info->fbops->fb_blank(VESA_NO_BLANKING, info);
-
- par->cur_state = 0;
-
+ release_console_sem();
return 0;
}
/***********************************************************************
@@ -1610,7 +1651,7 @@ static void __devinit i810_fix_offsets(struct i810fb_par *par)
static int __devinit i810_alloc_agp_mem(struct fb_info *info)
{
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
int size;
struct agp_bridge_data *bridge;
@@ -2074,7 +2115,7 @@ static void i810fb_release_resource(struct fb_info *info,
static void __exit i810fb_remove_pci(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct i810fb_par *par = (struct i810fb_par *) info->par;
+ struct i810fb_par *par = info->par;
unregister_framebuffer(info);
i810fb_release_resource(info, par);
diff --git a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h
index 06072a6466f2..51d4f3d4116d 100644
--- a/drivers/video/i810/i810_main.h
+++ b/drivers/video/i810/i810_main.h
@@ -14,55 +14,6 @@
#ifndef __I810_MAIN_H__
#define __I810_MAIN_H__
-static int __devinit i810fb_init_pci (struct pci_dev *dev,
- const struct pci_device_id *entry);
-static void __exit i810fb_remove_pci(struct pci_dev *dev);
-static int i810fb_resume(struct pci_dev *dev);
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
-
-/*
- * voffset - framebuffer offset in MiB from aperture start address. In order for
- * the driver to work with X, we must try to use memory holes left untouched by X. The
- * following table lists where X's different surfaces start at.
- *
- * ---------------------------------------------
- * : : 64 MiB : 32 MiB :
- * ----------------------------------------------
- * : FrontBuffer : 0 : 0 :
- * : DepthBuffer : 48 : 16 :
- * : BackBuffer : 56 : 24 :
- * ----------------------------------------------
- *
- * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to
- * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should
- * work, allowing 7 + 1 MiB of Framebuffer memory.
- * Note, the size of the hole may change depending on how much memory you allocate to X,
- * and how the memory is split up between these surfaces.
- *
- * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with
- * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load.
- *
- * Experiment with v_offset to find out which works best for you.
- */
-static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */
-static u32 voffset __initdata = 0;
-
-static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-
-/* Chipset Specific Functions */
-static int i810fb_set_par (struct fb_info *info);
-static int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue,
- u8 *transp, struct fb_info *info);
-static int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info);
-static int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
-static int i810fb_blank (int blank_mode, struct fb_info *info);
-
-/* Initialization */
-static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par);
-extern int __init agp_intel_init(void);
-
-
/* Video Timings */
extern void round_off_xres (u32 *xres);
extern void round_off_yres (u32 *xres, u32 *yres);
@@ -101,7 +52,7 @@ static inline void i810_delete_i2c_busses(struct i810fb_par *par) { }
/* Conditionals */
#ifdef CONFIG_X86
-inline void flush_cache(void)
+static inline void flush_cache(void)
{
asm volatile ("wbinvd":::"memory");
}
@@ -110,7 +61,9 @@ inline void flush_cache(void)
#endif
#ifdef CONFIG_MTRR
-#define KERNEL_HAS_MTRR 1
+
+#include <asm/mtrr.h>
+
static inline void __devinit set_mtrr(struct i810fb_par *par)
{
par->mtrr_reg = mtrr_add((u32) par->aperture.physical,
@@ -128,7 +81,6 @@ static inline void unset_mtrr(struct i810fb_par *par)
par->aperture.size);
}
#else
-#define KERNEL_HAS_MTRR 0
#define set_mtrr(x) printk("set_mtrr: MTRR is disabled in the kernel\n")
#define unset_mtrr(x) do { } while (0)
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e326f44f652d..6b88050d21bf 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -219,7 +219,7 @@ static void iga_blank_border(struct iga_par *par)
}
#ifdef __sparc__
-static int igafb_mmap(struct fb_info *info, struct file *file,
+static int igafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct iga_par *par = (struct iga_par *)info->par;
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7fbe24206b19..ad416ae47596 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -323,6 +323,7 @@ struct imstt_par {
unsigned long cmap_regs_phys;
__u8 *cmap_regs;
__u32 ramdac;
+ __u32 palette[16];
};
enum {
@@ -657,7 +658,7 @@ set_imstt_regvals_tvp (struct imstt_par *par, u_int bpp)
static void
set_imstt_regvals (struct fb_info *info, u_int bpp)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
struct imstt_regvals *init = &par->init;
__u32 ctl, pitch, byteswap, scr;
@@ -749,7 +750,7 @@ set_imstt_regvals (struct fb_info *info, u_int bpp)
static inline void
set_offset (struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 off = var->yoffset * (info->fix.line_length >> 3)
+ ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);
write_reg_le32(par->dc_regs, SSR, off);
@@ -863,7 +864,7 @@ imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_set_par(struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
return -EINVAL;
@@ -881,7 +882,7 @@ static int
imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
u_int bpp = info->var.bits_per_pixel;
if (regno > 255)
@@ -905,14 +906,17 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
if (regno < 16)
switch (bpp) {
case 16:
- ((u16 *)info->pseudo_palette)[regno] = (regno << (info->var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+ par->palette[regno] =
+ (regno << (info->var.green.length ==
+ 5 ? 10 : 11)) | (regno << 5) | regno;
break;
case 24:
- ((u32 *)info->pseudo_palette)[regno] = (regno << 16) | (regno << 8) | regno;
+ par->palette[regno] =
+ (regno << 16) | (regno << 8) | regno;
break;
case 32: {
int i = (regno << 8) | regno;
- ((u32 *)info->pseudo_palette)[regno] = (i << 16) | i;
+ par->palette[regno] = (i << 16) |i;
break;
}
}
@@ -935,7 +939,7 @@ imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
static int
imsttfb_blank(int blank, struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 ctrl;
ctrl = read_reg_le32(par->dc_regs, STGCTL);
@@ -989,7 +993,7 @@ imsttfb_blank(int blank, struct fb_info *info)
static void
imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, bgc, dx, dy, width, height;
bgc = rect->color;
@@ -1033,7 +1037,7 @@ imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
static void
imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl;
__u32 cnt, bltctl, sx, sy, dx, dy, height, width;
@@ -1195,7 +1199,7 @@ imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
static int
imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
u32 flags = cursor->set, fg, bg, xx, yy;
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
@@ -1263,10 +1267,9 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
#define FBIMSTT_GETIDXREG 0x545406
static int
-imsttfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, struct fb_info *info)
+imsttfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
void __user *argp = (void __user *)arg;
__u32 reg[2];
__u8 idx[2];
@@ -1350,7 +1353,7 @@ static struct fb_ops imsttfb_ops = {
static void __devinit
init_imstt(struct fb_info *info)
{
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
__u32 i, tmp, *ip, *end;
tmp = read_reg_le32(par->dc_regs, PRC);
@@ -1413,7 +1416,7 @@ init_imstt(struct fb_info *info)
if ((info->var.xres * info->var.yres) * (info->var.bits_per_pixel >> 3) > info->fix.smem_len
|| !(compute_imstt_regvals(par, info->var.xres, info->var.yres))) {
printk("imsttfb: %ux%ux%u not supported\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
- kfree(info);
+ framebuffer_release(info);
return;
}
@@ -1449,7 +1452,7 @@ init_imstt(struct fb_info *info)
fb_alloc_cmap(&info->cmap, 0, 0);
if (register_framebuffer(info) < 0) {
- kfree(info);
+ framebuffer_release(info);
return;
}
@@ -1474,26 +1477,21 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
#endif /* CONFIG_PPC_OF */
- size = sizeof(struct fb_info) + sizeof(struct imstt_par) +
- sizeof(u32) * 16;
-
- info = kmalloc(size, GFP_KERNEL);
+ info = framebuffer_alloc(sizeof(struct imstt_par), &pdev->dev);
if (!info) {
printk(KERN_ERR "imsttfb: Can't allocate memory\n");
return -ENOMEM;
}
- memset(info, 0, size);
-
- par = (struct imstt_par *) (info + 1);
+ par = info->par;
addr = pci_resource_start (pdev, 0);
size = pci_resource_len (pdev, 0);
if (!request_mem_region(addr, size, "imsttfb")) {
printk(KERN_ERR "imsttfb: Can't reserve memory region\n");
- kfree(info);
+ framebuffer_release(info);
return -ENODEV;
}
@@ -1516,14 +1514,13 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
info->fix.smem_start = addr;
- info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000);
+ info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
+ 0x400000 : 0x800000);
info->fix.mmio_start = addr + 0x800000;
par->dc_regs = ioremap(addr + 0x800000, 0x1000);
par->cmap_regs_phys = addr + 0x840000;
par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
- info->par = par;
- info->pseudo_palette = (void *) (par + 1);
- info->device = &pdev->dev;
+ info->pseudo_palette = par->palette;
init_imstt(info);
pci_set_drvdata(pdev, info);
@@ -1534,7 +1531,7 @@ static void __devexit
imsttfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct imstt_par *par = (struct imstt_par *) info->par;
+ struct imstt_par *par = info->par;
int size = pci_resource_len(pdev, 0);
unregister_framebuffer(info);
@@ -1542,7 +1539,7 @@ imsttfb_remove(struct pci_dev *pdev)
iounmap(par->dc_regs);
iounmap(info->screen_base);
release_mem_region(info->fix.smem_start, size);
- kfree(info);
+ framebuffer_release(info);
}
#ifndef MODULE
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 5924cc225c95..1718baaeed2a 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -554,7 +554,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
inf = pdev->dev.platform_data;
if(!inf) {
- dev_err(dev,"No platform_data available\n");
+ dev_err(&pdev->dev,"No platform_data available\n");
return -ENOMEM;
}
@@ -579,7 +579,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
if (!inf->fixed_screen_cpu) {
ret = imxfb_map_video_memory(info);
if (ret) {
- dev_err(dev, "Failed to allocate video RAM: %d\n", ret);
+ dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto failed_map;
}
@@ -608,7 +608,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
imxfb_set_par(info);
ret = register_framebuffer(info);
if (ret < 0) {
- dev_err(dev, "failed to register framebuffer\n");
+ dev_err(&pdev->dev, "failed to register framebuffer\n");
goto failed_register;
}
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0090544842f5..6b8bd3cdf9c0 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -157,9 +157,8 @@ static int intelfb_cursor(struct fb_info *info,
static int intelfb_sync(struct fb_info *info);
-static int intelfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info);
+static int intelfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg);
static int __devinit intelfb_pci_register(struct pci_dev *pdev,
const struct pci_device_id *ent);
@@ -1380,8 +1379,7 @@ intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
/* When/if we have our own ioctls. */
static int
-intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
int retval = 0;
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index 7e33cd307d47..ab5285a7f1d6 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include "STG4000Reg.h"
+#include "STG4000Interface.h"
/* SDRAM fixed settings */
#define SDRAM_CFG_0 0x49A1
diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/kyro/STG4000Interface.h
index e75b3b4a4aa1..b7c83d5dfb13 100644
--- a/drivers/video/kyro/STG4000Interface.h
+++ b/drivers/video/kyro/STG4000Interface.h
@@ -11,7 +11,8 @@
#ifndef _STG4000INTERFACE_H
#define _STG4000INTERFACE_H
-struct pci_dev;
+#include <linux/pci.h>
+#include <video/kyro.h>
/*
* Ramdac Setup
diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/kyro/STG4000OverlayDevice.c
index 2ae9bafacdd0..a8c9713413e6 100644
--- a/drivers/video/kyro/STG4000OverlayDevice.c
+++ b/drivers/video/kyro/STG4000OverlayDevice.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include "STG4000Reg.h"
+#include "STG4000Interface.h"
/* HW Defines */
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 5eb4d5c177bd..477ad297de4e 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -73,8 +73,6 @@ static struct fb_var_screeninfo kyro_var __devinitdata = {
.vmode = FB_VMODE_NONINTERLACED,
};
-static struct kyrofb_info *currentpar;
-
typedef struct {
STG4000REG __iomem *pSTGReg; /* Virtual address of PCI register region */
u32 ulNextFreeVidMem; /* Offset from start of vid mem to next free region */
@@ -309,7 +307,7 @@ enum {
/* Accessors */
static int kyro_dev_video_mode_set(struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
/* Turn off display */
StopVTG(deviceInfo.pSTGReg);
@@ -402,7 +400,7 @@ static inline unsigned long get_line_length(int x, int bpp)
static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
@@ -478,7 +476,7 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int kyrofb_set_par(struct fb_info *info)
{
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
unsigned long lineclock;
unsigned long frameclock;
@@ -536,20 +534,22 @@ static int kyrofb_set_par(struct fb_info *info)
static int kyrofb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
{
+ struct kyrofb_info *par = info->par;
+
if (regno > 255)
return 1; /* Invalid register */
if (regno < 16) {
switch (info->var.bits_per_pixel) {
case 16:
- ((u16*)(info->pseudo_palette))[regno] =
+ par->palette[regno] =
(red & 0xf800) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
case 32:
red >>= 8; green >>= 8; blue >>= 8; transp >>= 8;
- ((u32*)(info->pseudo_palette))[regno] =
+ par->palette[regno] =
(transp << 24) | (red << 16) | (green << 8) | blue;
break;
}
@@ -586,9 +586,8 @@ static int __init kyrofb_setup(char *options)
}
#endif
-static int kyrofb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int kyrofb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
overlay_create ol_create;
overlay_viewport_set ol_viewport_set;
@@ -675,6 +674,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct fb_info *info;
+ struct kyrofb_info *currentpar;
unsigned long size;
int err;
@@ -683,14 +683,11 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
return err;
}
- size = sizeof(struct fb_info) + sizeof(struct kyrofb_info) + 16 * sizeof(u32);
- info = kmalloc(size, GFP_KERNEL);
+ info = framebuffer_alloc(sizeof(struct kyrofb_info), &pdev->dev);
if (!info)
return -ENOMEM;
- memset(info, 0, size);
-
- currentpar = (struct kyrofb_info *)(info + 1);
+ currentpar = info->par;
kyro_fix.smem_start = pci_resource_start(pdev, 0);
kyro_fix.smem_len = pci_resource_len(pdev, 0);
@@ -716,8 +713,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
info->fbops = &kyrofb_ops;
info->fix = kyro_fix;
- info->par = currentpar;
- info->pseudo_palette = (void *)(currentpar + 1);
+ info->pseudo_palette = currentpar->palette;
info->flags = FBINFO_DEFAULT;
SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
@@ -741,7 +737,6 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
fb_memset(info->screen_base, 0, size);
- info->device = &pdev->dev;
if (register_framebuffer(info) < 0)
goto out_unmap;
@@ -757,7 +752,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
out_unmap:
iounmap(currentpar->regbase);
iounmap(info->screen_base);
- kfree(info);
+ framebuffer_release(info);
return -EINVAL;
}
@@ -765,7 +760,7 @@ out_unmap:
static void __devexit kyrofb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct kyrofb_info *par = (struct kyrofb_info *)info->par;
+ struct kyrofb_info *par = info->par;
/* Reset the board */
StopVTG(deviceInfo.pSTGReg);
@@ -789,7 +784,7 @@ static void __devexit kyrofb_remove(struct pci_dev *pdev)
unregister_framebuffer(info);
pci_set_drvdata(pdev, NULL);
- kfree(info);
+ framebuffer_release(info);
}
static int __init kyrofb_init(void)
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 494287f8f8bf..a23cfdb9d826 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -32,9 +32,8 @@ static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int leo_blank(int, struct fb_info *);
-static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int leo_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int leo_mmap(struct fb_info *, struct vm_area_struct *);
+static int leo_ioctl(struct fb_info *, unsigned int, unsigned long);
static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -363,7 +362,7 @@ static struct sbus_mmap_map leo_mmap_map[] = {
{ .size = 0 }
};
-static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int leo_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct leo_par *par = (struct leo_par *)info->par;
@@ -373,8 +372,7 @@ static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct leo_par *par = (struct leo_par *) info->par;
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
index d0244c04af5a..4ef5cd19609d 100644
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -16,7 +16,7 @@ obj-$(CONFIG_LOGO_M32R_CLUT224) += logo_m32r_clut224.o
# How to generate logo's
-# Use logo-cfiles to retreive list of .c files to be built
+# Use logo-cfiles to retrieve list of .c files to be built
logo-cfiles = $(notdir $(patsubst %.$(2), %.c, \
$(wildcard $(srctree)/$(src)/*$(1).$(2))))
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index cfc748e94272..e6cbd9de944a 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -609,18 +609,19 @@ void __init macfb_setup(char *options)
}
}
-void __init macfb_init(void)
+static int __init macfb_init(void)
{
int video_cmap_len, video_is_nubus = 0;
struct nubus_dev* ndev = NULL;
char *option = NULL;
+ int err;
if (fb_get_options("macfb", &option))
return -ENODEV;
macfb_setup(option);
if (!MACH_IS_MAC)
- return;
+ return -ENODEV;
/* There can only be one internal video controller anyway so
we're not too worried about this */
@@ -958,11 +959,11 @@ void __init macfb_init(void)
fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
- if (register_framebuffer(&fb_info) < 0)
- return;
-
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ err = register_framebuffer(&fb_info);
+ if (!err)
+ printk("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+ return err;
}
module_init(macfb_init);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 1e74f4cca53b..4055ff6f5a81 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -865,9 +865,8 @@ static struct matrox_altout panellink_output = {
.name = "Panellink output",
};
-static int matroxfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- struct fb_info *info)
+static int matroxfb_ioctl(struct fb_info *info,
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
MINFO_FROM_INFO(info);
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index a8c47ad2cdb6..3a3e1804c56a 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -50,8 +50,6 @@
#include <asm/mtrr.h>
#endif
-#include "../console/fbcon.h"
-
#if defined(CONFIG_PPC_PMAC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
@@ -351,8 +349,6 @@ struct matrox_bios {
} output;
};
-extern struct display fb_display[];
-
struct matrox_switch;
struct matroxfb_driver;
struct matroxfb_dh_fb_info;
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index d52d7d825c41..27eb4bb4f89f 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -419,11 +419,10 @@ static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, stru
return 0;
}
-static int matroxfb_dh_ioctl(struct inode* inode,
- struct file* file,
+static int matroxfb_dh_ioctl(struct fb_info *info,
unsigned int cmd,
- unsigned long arg,
- struct fb_info* info) {
+ unsigned long arg)
+{
#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
MINFO_FROM(m2info->primary_dev);
@@ -457,7 +456,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
case MATROXFB_GET_OUTPUT_MODE:
case MATROXFB_GET_ALL_OUTPUTS:
{
- return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, &ACCESS_FBINFO(fbcon));
+ return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(&ACCESS_FBINFO(fbcon), cmd, arg);
}
case MATROXFB_SET_OUTPUT_CONNECTION:
{
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c
index 35008af7db75..c122d8743dd2 100644
--- a/drivers/video/matrox/matroxfb_g450.c
+++ b/drivers/video/matrox/matroxfb_g450.c
@@ -20,6 +20,8 @@
#include <asm/uaccess.h>
#include <asm/div64.h>
+#include "matroxfb_g450.h"
+
/* Definition of the various controls */
struct mctl {
struct v4l2_queryctrl desc;
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index ad60bbb16cdf..6019710dc298 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -968,7 +968,7 @@ static inline int maven_compute_timming(struct maven_data* md,
return 0;
}
-static inline int maven_program_timming(struct maven_data* md,
+static int maven_program_timming(struct maven_data* md,
const struct mavenregs* m) {
struct i2c_client* c = md->client;
@@ -1288,18 +1288,13 @@ static int maven_detach_client(struct i2c_client* client) {
return 0;
}
-static int maven_command(struct i2c_client* client, unsigned int cmd, void* arg) {
- return -ENOIOCTLCMD; /* or -EINVAL, depends on who will call this */
-}
-
static struct i2c_driver maven_driver={
- .owner = THIS_MODULE,
- .name = "maven",
+ .driver = {
+ .name = "maven",
+ },
.id = I2C_DRIVERID_MGATVO,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = maven_attach_adapter,
.detach_client = maven_detach_client,
- .command = maven_command,
};
/* ************************** */
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index d9d3e9f6c08e..455a46ce840c 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -192,11 +192,8 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
unsigned int wd;
unsigned int divider;
int i;
- int fwidth;
struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw);
- fwidth = 8;
-
DBG(__FUNCTION__)
hw->SEQ[0] = 0x00;
@@ -235,10 +232,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
hw->ATTR[16] = 0x41;
hw->ATTR[17] = 0xFF;
hw->ATTR[18] = 0x0F;
- if (fwidth == 9)
- hw->ATTR[19] = 0x08;
- else
- hw->ATTR[19] = 0x00;
+ hw->ATTR[19] = 0x00;
hw->ATTR[20] = 0x00;
hd = m->HDisplay >> 3;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 8486e77872dc..747602aa5615 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -485,7 +485,7 @@ static void vgaHWRestore(const struct fb_info *info,
*/
static inline int neo2200_sync(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int waitcycles;
while (readl(&par->neo2200->bltStat) & 1)
@@ -525,7 +525,7 @@ static inline void neo2200_wait_fifo(struct fb_info *info,
static inline void neo2200_accel_init(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
Neo2200 __iomem *neo2200 = par->neo2200;
u32 bltMod, pitch;
@@ -560,7 +560,7 @@ static inline void neo2200_accel_init(struct fb_info *info,
static int
neofb_open(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
@@ -575,7 +575,7 @@ neofb_open(struct fb_info *info, int user)
static int
neofb_release(struct fb_info *info, int user)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt)
@@ -590,7 +590,7 @@ neofb_release(struct fb_info *info, int user)
static int
neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned int pixclock = var->pixclock;
struct xtimings timings;
int memlen, vramlen;
@@ -757,7 +757,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int neofb_set_par(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct xtimings timings;
unsigned char temp;
int i, clock_hi = 0;
@@ -853,7 +853,7 @@ static int neofb_set_par(struct fb_info *info)
/* If the user did not specify any display devices, then... */
if (par->PanelDispCntlReg1 == 0x00) {
/* Default to internal (i.e., LCD) only. */
- par->PanelDispCntlReg1 |= 0x02;
+ par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
}
/* If we are using a fixed mode, then tell the chip we are. */
@@ -1216,7 +1216,7 @@ static int neofb_set_par(struct fb_info *info)
static void neofb_update_start(struct fb_info *info,
struct fb_var_screeninfo *var)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
struct vgastate *state = &par->state;
int oldExtCRTDispAddr;
int Base;
@@ -1331,7 +1331,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
* wms...Enable VESA DPMS compatible powerdown mode
* run "setterm -powersave powerdown" to take advantage
*/
- struct neofb_par *par = (struct neofb_par *)info->par;
+ struct neofb_par *par = info->par;
int seqflags, lcdflags, dpmsflags, reg;
switch (blank_mode) {
@@ -1404,7 +1404,7 @@ static int neofb_blank(int blank_mode, struct fb_info *info)
static void
neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long dst, rop;
dst = rect->dx + rect->dy * info->var.xres_virtual;
@@ -1440,7 +1440,7 @@ static void
neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
u_long src, dst, bltCntl;
bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
@@ -1472,7 +1472,7 @@ neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
static void
neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int s_pitch = (image->width * image->depth + 7) >> 3;
int scan_align = info->pixmap.scan_align - 1;
int buf_align = info->pixmap.buf_align - 1;
@@ -1686,7 +1686,7 @@ static struct fb_videomode __devinitdata mode800x480 = {
static int __devinit neo_map_mmio(struct fb_info *info,
struct pci_dev *dev)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_map_mmio");
@@ -1733,7 +1733,7 @@ static int __devinit neo_map_mmio(struct fb_info *info,
static void neo_unmap_mmio(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
DBG("neo_unmap_mmio");
@@ -1796,7 +1796,7 @@ static void neo_unmap_video(struct fb_info *info)
#ifdef CONFIG_MTRR
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
mtrr_del(par->mtrr, info->fix.smem_start,
info->fix.smem_len);
@@ -1811,7 +1811,7 @@ static void neo_unmap_video(struct fb_info *info)
static int __devinit neo_scan_monitor(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
unsigned char type, display;
int w;
@@ -1890,7 +1890,7 @@ static int __devinit neo_scan_monitor(struct fb_info *info)
static int __devinit neo_init_hw(struct fb_info *info)
{
- struct neofb_par *par = (struct neofb_par *) info->par;
+ struct neofb_par *par = info->par;
int videoRam = 896;
int maxClock = 65000;
int CursorMem = 1024;
@@ -2014,7 +2014,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
struct fb_info *info;
struct neofb_par *par;
- info = framebuffer_alloc(sizeof(struct neofb_par) + sizeof(u32) * 256, &dev->dev);
+ info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
if (!info)
return NULL;
@@ -2081,7 +2081,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
info->fbops = &neofb_ops;
- info->pseudo_palette = (void *) (par + 1);
+ info->pseudo_palette = par->palette;
return info;
}
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index b989358437b3..99c3a8e6a237 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -52,6 +52,7 @@
#include <linux/pci.h>
#include "nv_type.h"
#include "nv_local.h"
+#include "nv_proto.h"
void NVLockUnlock(struct nvidia_par *par, int Lock)
{
@@ -848,7 +849,7 @@ void NVCalcStateExt(struct nvidia_par *par,
int width,
int hDisplaySize, int height, int dotClock, int flags)
{
- int pixelDepth, VClk;
+ int pixelDepth, VClk = 0;
/*
* Save mode parameters.
*/
@@ -938,15 +939,24 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
if (par->Architecture == NV_ARCH_04) {
NV_WR32(par->PFB, 0x0200, state->config);
- } else if ((par->Chipset & 0xfff0) == 0x0090) {
- for (i = 0; i < 15; i++) {
- NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
- NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
- }
- } else {
+ } else if ((par->Architecture < NV_ARCH_40) ||
+ (par->Chipset & 0xfff0) == 0x0040) {
for (i = 0; i < 8; i++) {
NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
- NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+ NV_WR32(par->PFB, 0x0244 + (i * 0x10),
+ par->FbMapSize - 1);
+ }
+ } else {
+ int regions = 12;
+
+ if (((par->Chipset & 0xfff0) == 0x0090) ||
+ ((par->Chipset & 0xfff0) == 0x01D0) ||
+ ((par->Chipset & 0xfff0) == 0x0290))
+ regions = 15;
+ for(i = 0; i < regions; i++) {
+ NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+ NV_WR32(par->PFB, 0x0604 + (i * 0x10),
+ par->FbMapSize - 1);
}
}
@@ -1182,11 +1192,17 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
} else {
if (par->Architecture >= NV_ARCH_40) {
+ u32 tmp;
+
NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+ tmp = NV_RD32(par->REGS, 0x1540) & 0xff;
+ for(i = 0; tmp && !(tmp & 1); tmp >>= 1, i++);
+ NV_WR32(par->PGRAPH, 0x5000, i);
+
if ((par->Chipset & 0xfff0) == 0x0040) {
NV_WR32(par->PGRAPH, 0x09b0,
0x83280fff);
@@ -1211,6 +1227,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0xffff7fff);
break;
case 0x00C0:
+ case 0x0120:
NV_WR32(par->PGRAPH, 0x0828,
0x007596ff);
NV_WR32(par->PGRAPH, 0x082C,
@@ -1245,6 +1262,7 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
0x00100000);
break;
case 0x0090:
+ case 0x0290:
NV_WR32(par->PRAMDAC, 0x0608,
NV_RD32(par->PRAMDAC, 0x0608) |
0x00100000);
@@ -1310,14 +1328,44 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
}
}
- if ((par->Chipset & 0xfff0) == 0x0090) {
- for (i = 0; i < 60; i++)
- NV_WR32(par->PGRAPH, 0x0D00 + i,
- NV_RD32(par->PFB, 0x0600 + i));
+ if ((par->Architecture < NV_ARCH_40) ||
+ ((par->Chipset & 0xfff0) == 0x0040)) {
+ for (i = 0; i < 32; i++) {
+ NV_WR32(par->PGRAPH, 0x0900 + i*4,
+ NV_RD32(par->PFB, 0x0240 +i*4));
+ NV_WR32(par->PGRAPH, 0x6900 + i*4,
+ NV_RD32(par->PFB, 0x0240 +i*4));
+ }
} else {
- for (i = 0; i < 32; i++)
- NV_WR32(par->PGRAPH, 0x0900 + i,
- NV_RD32(par->PFB, 0x0240 + i));
+ if (((par->Chipset & 0xfff0) == 0x0090) ||
+ ((par->Chipset & 0xfff0) == 0x01D0) ||
+ ((par->Chipset & 0xfff0) == 0x0290)) {
+ for (i = 0; i < 60; i++) {
+ NV_WR32(par->PGRAPH,
+ 0x0D00 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ NV_WR32(par->PGRAPH,
+ 0x6900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ }
+ } else {
+ for (i = 0; i < 48; i++) {
+ NV_WR32(par->PGRAPH,
+ 0x0900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ if(((par->Chipset & 0xfff0)
+ != 0x0160) &&
+ ((par->Chipset & 0xfff0)
+ != 0x0220))
+ NV_WR32(par->PGRAPH,
+ 0x6900 + i*4,
+ NV_RD32(par->PFB,
+ 0x0600 + i*4));
+ }
+ }
}
if (par->Architecture >= NV_ARCH_40) {
@@ -1338,7 +1386,9 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
NV_WR32(par->PGRAPH, 0x0868,
par->FbMapSize - 1);
} else {
- if((par->Chipset & 0xfff0) == 0x0090) {
+ if ((par->Chipset & 0xfff0) == 0x0090 ||
+ (par->Chipset & 0xfff0) == 0x01D0 ||
+ (par->Chipset & 0xfff0) == 0x0290) {
NV_WR32(par->PGRAPH, 0x0DF0,
NV_RD32(par->PFB, 0x0200));
NV_WR32(par->PGRAPH, 0x0DF4,
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 12f2884d3f0b..bd9eca05e146 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -46,7 +46,7 @@ static void nvidia_gpio_setscl(void *data, int state)
static void nvidia_gpio_setsda(void *data, int state)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val;
@@ -64,7 +64,7 @@ static void nvidia_gpio_setsda(void *data, int state)
static int nvidia_gpio_getscl(void *data)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val = 0;
@@ -79,7 +79,7 @@ static int nvidia_gpio_getscl(void *data)
static int nvidia_gpio_getsda(void *data)
{
- struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+ struct nvidia_i2c_chan *chan = data;
struct nvidia_par *par = chan->par;
u32 val = 0;
@@ -136,13 +136,13 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
par->chan[2].par = par;
par->chan[0].ddc_base = 0x3e;
- nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+ nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0");
par->chan[1].ddc_base = 0x36;
- nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+ nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1");
par->chan[2].ddc_base = 0x50;
- nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+ nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2");
}
void nvidia_delete_i2c_busses(struct nvidia_par *par)
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 3353103e8b0b..b149a690ee0f 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -4,7 +4,7 @@
#define __NV_PROTO_H__
/* in nv_setup.c */
-void NVCommonSetup(struct fb_info *info);
+int NVCommonSetup(struct fb_info *info);
void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
u8 NVReadCrtc(struct nvidia_par *par, u8 index);
void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 1f06a9f1bd0f..a18a9aebf05f 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -285,28 +285,34 @@ static void nv10GetConfig(struct nvidia_par *par)
par->CrystalFreqKHz = 27000;
}
- par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
par->CURSOR = NULL; /* can't set this here */
par->MinVClockFreqKHz = 12000;
par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
}
-void NVCommonSetup(struct fb_info *info)
+int NVCommonSetup(struct fb_info *info)
{
struct nvidia_par *par = info->par;
- struct fb_var_screeninfo var;
+ struct fb_var_screeninfo *var;
u16 implementation = par->Chipset & 0x0ff0;
u8 *edidA = NULL, *edidB = NULL;
- struct fb_monspecs monitorA, monitorB;
+ struct fb_monspecs *monitorA, *monitorB;
struct fb_monspecs *monA = NULL, *monB = NULL;
int mobile = 0;
int tvA = 0;
int tvB = 0;
int FlatPanel = -1; /* really means the CRTC is slaved */
int Television = 0;
+ int err = 0;
- memset(&monitorA, 0, sizeof(struct fb_monspecs));
- memset(&monitorB, 0, sizeof(struct fb_monspecs));
+ var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
+ monitorA = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+ monitorB = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);
+
+ if (!var || !monitorA || !monitorB) {
+ err = -ENOMEM;
+ goto done;
+ }
par->PRAMIN = par->REGS + (0x00710000 / 4);
par->PCRTC0 = par->REGS + (0x00600000 / 4);
@@ -382,6 +388,8 @@ void NVCommonSetup(struct fb_info *info)
case 0x0146:
case 0x0147:
case 0x0148:
+ case 0x0098:
+ case 0x0099:
mobile = 1;
break;
default:
@@ -406,9 +414,9 @@ void NVCommonSetup(struct fb_info *info)
par->CRTCnumber = 0;
if (nvidia_probe_i2c_connector(info, 1, &edidA))
nvidia_probe_of_connector(info, 1, &edidA);
- if (edidA && !fb_parse_edid(edidA, &var)) {
+ if (edidA && !fb_parse_edid(edidA, var)) {
printk("nvidiafb: EDID found from BUS1\n");
- monA = &monitorA;
+ monA = monitorA;
fb_edid_to_monspecs(edidA, monA);
FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
@@ -494,17 +502,17 @@ void NVCommonSetup(struct fb_info *info)
if (nvidia_probe_i2c_connector(info, 1, &edidA))
nvidia_probe_of_connector(info, 1, &edidA);
- if (edidA && !fb_parse_edid(edidA, &var)) {
+ if (edidA && !fb_parse_edid(edidA, var)) {
printk("nvidiafb: EDID found from BUS1\n");
- monA = &monitorA;
+ monA = monitorA;
fb_edid_to_monspecs(edidA, monA);
}
if (nvidia_probe_i2c_connector(info, 2, &edidB))
nvidia_probe_of_connector(info, 2, &edidB);
- if (edidB && !fb_parse_edid(edidB, &var)) {
+ if (edidB && !fb_parse_edid(edidB, var)) {
printk("nvidiafb: EDID found from BUS2\n");
- monB = &monitorB;
+ monB = monitorB;
fb_edid_to_monspecs(edidB, monB);
}
@@ -639,4 +647,9 @@ void NVCommonSetup(struct fb_info *info)
kfree(edidA);
kfree(edidB);
+done:
+ kfree(var);
+ kfree(monitorA);
+ kfree(monitorB);
+ return err;
}
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index bee09c6e48f6..dbcb8962e57d 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -284,6 +284,16 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0252,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NVIDIA, 0x0313,
@@ -418,6 +428,7 @@ static int noaccel __devinitdata = 0;
static int noscale __devinitdata = 0;
static int paneltweak __devinitdata = 0;
static int vram __devinitdata = 0;
+static int bpp __devinitdata = 8;
#ifdef CONFIG_MTRR
static int nomtrr __devinitdata = 0;
#endif
@@ -485,7 +496,7 @@ static int nvidia_backlight_levels[] = {
static int nvidia_set_backlight_enable(int on, int level, void *data)
{
- struct nvidia_par *par = (struct nvidia_par *)data;
+ struct nvidia_par *par = data;
u32 tmp_pcrt, tmp_pmc, fpcontrol;
tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
@@ -1382,24 +1393,36 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->monspecs.modedb_len, &info->modelist);
fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+ switch (bpp) {
+ case 0 ... 8:
+ bpp = 8;
+ break;
+ case 9 ... 16:
+ bpp = 16;
+ break;
+ default:
+ bpp = 32;
+ break;
+ }
+
if (specs->modedb != NULL) {
struct fb_videomode *modedb;
modedb = fb_find_best_display(specs, &info->modelist);
fb_videomode_to_var(&nvidiafb_default_var, modedb);
- nvidiafb_default_var.bits_per_pixel = 8;
+ nvidiafb_default_var.bits_per_pixel = bpp;
} else if (par->fpWidth && par->fpHeight) {
char buf[16];
memset(buf, 0, 16);
snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
- specs->modedb_len, &modedb, 8);
+ specs->modedb_len, &modedb, bpp);
}
if (mode_option)
fb_find_mode(&nvidiafb_default_var, info, mode_option,
- specs->modedb, specs->modedb_len, &modedb, 8);
+ specs->modedb, specs->modedb_len, &modedb, bpp);
info->var = nvidiafb_default_var;
info->fix.visual = (info->var.bits_per_pixel == 8) ?
@@ -1448,11 +1471,34 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
return nvidiafb_check_var(&info->var, info);
}
-static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+static u32 __devinit nvidia_get_chipset(struct fb_info *info)
{
+ struct nvidia_par *par = info->par;
+ u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
+
+ printk("nvidiafb: PCI id - %x\n", id);
+ if ((id & 0xfff0) == 0x00f0) {
+ /* pci-e */
+ printk("nvidiafb: PCI-E card\n");
+ id = NV_RD32(par->REGS, 0x1800);
+
+ if ((id & 0x0000ffff) == 0x000010DE)
+ id = 0x10DE0000 | (id >> 16);
+ else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
+ id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
+ ((id >> 8) & 0x000000ff);
+ }
+
+ printk("nvidiafb: Actual id - %x\n", id);
+ return id;
+}
+
+static u32 __devinit nvidia_get_arch(struct fb_info *info)
+{
+ struct nvidia_par *par = info->par;
u32 arch = 0;
- switch (pd->device & 0x0ff0) {
+ switch (par->Chipset & 0x0ff0) {
case 0x0100: /* GeForce 256 */
case 0x0110: /* GeForce2 MX */
case 0x0150: /* GeForce2 */
@@ -1485,6 +1531,8 @@ static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
case 0x0210:
case 0x0220:
case 0x0230:
+ case 0x0290:
+ case 0x0390:
arch = NV_ARCH_40;
break;
case 0x0020: /* TNT, TNT2 */
@@ -1513,7 +1561,7 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
if (!info)
goto err_out;
- par = (struct nvidia_par *)info->par;
+ par = info->par;
par->pci_dev = pd;
info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -1533,18 +1581,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
goto err_out_request;
}
- par->Architecture = nvidia_get_arch(pd);
-
- par->Chipset = (pd->vendor << 16) | pd->device;
- printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
-
- if (par->Architecture == 0) {
- printk(KERN_ERR PFX "unknown NV_ARCH\n");
- goto err_out_free_base0;
- }
-
- sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
-
par->FlatPanel = flatpanel;
if (flatpanel == 1)
printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1570,7 +1606,19 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
goto err_out_free_base0;
}
- NVCommonSetup(info);
+ par->Chipset = nvidia_get_chipset(info);
+ printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+ par->Architecture = nvidia_get_arch(info);
+
+ if (par->Architecture == 0) {
+ printk(KERN_ERR PFX "unknown NV_ARCH\n");
+ goto err_out_arch;
+ }
+
+ sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+ if (NVCommonSetup(info))
+ goto err_out_arch;
par->FbAddress = nvidiafb_fix.smem_start;
par->FbMapSize = par->RamAmountKBytes * 1024;
@@ -1581,10 +1629,15 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
if (par->FbMapSize > 64 * 1024 * 1024)
par->FbMapSize = 64 * 1024 * 1024;
- par->FbUsableSize = par->FbMapSize - (128 * 1024);
+ if(par->Architecture >= NV_ARCH_40)
+ par->FbUsableSize = par->FbMapSize - (560 * 1024);
+ else
+ par->FbUsableSize = par->FbMapSize - (128 * 1024);
par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
16 * 1024;
par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+ par->CursorStart = par->FbUsableSize + (32 * 1024);
+
info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
info->screen_size = par->FbUsableSize;
nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
@@ -1640,21 +1693,22 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
NVTRACE_LEAVE();
return 0;
- err_out_iounmap_fb:
+err_out_iounmap_fb:
iounmap(info->screen_base);
- err_out_free_base1:
+err_out_free_base1:
fb_destroy_modedb(info->monspecs.modedb);
nvidia_delete_i2c_busses(par);
+err_out_arch:
iounmap(par->REGS);
- err_out_free_base0:
+err_out_free_base0:
pci_release_regions(pd);
- err_out_request:
+err_out_request:
pci_disable_device(pd);
- err_out_enable:
+err_out_enable:
kfree(info->pixmap.addr);
- err_out_kfree:
+err_out_kfree:
framebuffer_release(info);
- err_out:
+err_out:
return -ENODEV;
}
@@ -1729,6 +1783,8 @@ static int __devinit nvidiafb_setup(char *options)
#endif
} else if (!strncmp(this_opt, "fpdither:", 9)) {
fpdither = simple_strtol(this_opt+9, NULL, 0);
+ } else if (!strncmp(this_opt, "bpp:", 4)) {
+ bpp = simple_strtoul(this_opt+4, NULL, 0);
} else
mode_option = this_opt;
}
@@ -1804,6 +1860,11 @@ module_param(vram, int, 0);
MODULE_PARM_DESC(vram,
"amount of framebuffer memory to remap in MiB"
"(default=0 - remap entire memory)");
+module_param(mode_option, charp, 0);
+MODULE_PARM_DESC(mode_option, "Specify initial video mode");
+module_param(bpp, int, 0);
+MODULE_PARM_DESC(bpp, "pixel width in bits"
+ "(default=8)");
#ifdef CONFIG_MTRR
module_param(nomtrr, bool, 0);
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 00d87f5bb7be..ad1434e3f227 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -223,6 +223,7 @@ static int offb_blank(int blank, struct fb_info *info)
int __init offb_init(void)
{
struct device_node *dp = NULL, *boot_disp = NULL;
+
#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
struct device_node *macos_display = NULL;
#endif
@@ -234,60 +235,54 @@ int __init offb_init(void)
if (boot_infos != 0) {
unsigned long addr =
(unsigned long) boot_infos->dispDeviceBase;
+ u32 *addrp;
+ u64 daddr, dsize;
+ unsigned int flags;
+
/* find the device node corresponding to the macos display */
while ((dp = of_find_node_by_type(dp, "display"))) {
int i;
- /*
- * Grrr... It looks like the MacOS ATI driver
- * munges the assigned-addresses property (but
- * the AAPL,address value is OK).
- */
- if (strncmp(dp->name, "ATY,", 4) == 0
- && dp->n_addrs == 1) {
- unsigned int *ap =
- (unsigned int *) get_property(dp,
- "AAPL,address",
- NULL);
- if (ap != NULL) {
- dp->addrs[0].address = *ap;
- dp->addrs[0].size = 0x01000000;
- }
- }
/*
- * The LTPro on the Lombard powerbook has no addresses
- * on the display nodes, they are on their parent.
+ * Look for an AAPL,address property first.
*/
- if (dp->n_addrs == 0
- && device_is_compatible(dp, "ATY,264LTPro")) {
- int na;
- unsigned int *ap = (unsigned int *)
- get_property(dp, "AAPL,address", &na);
- if (ap != 0)
- for (na /= sizeof(unsigned int);
- na > 0; --na, ++ap)
- if (*ap <= addr
- && addr <
- *ap + 0x1000000)
- goto foundit;
+ unsigned int na;
+ unsigned int *ap =
+ (unsigned int *)get_property(dp, "AAPL,address",
+ &na);
+ if (ap != 0) {
+ for (na /= sizeof(unsigned int); na > 0;
+ --na, ++ap)
+ if (*ap <= addr &&
+ addr < *ap + 0x1000000) {
+ macos_display = dp;
+ goto foundit;
+ }
}
/*
* See if the display address is in one of the address
* ranges for this display.
*/
- for (i = 0; i < dp->n_addrs; ++i) {
- if (dp->addrs[i].address <= addr
- && addr <
- dp->addrs[i].address +
- dp->addrs[i].size)
+ i = 0;
+ for (;;) {
+ addrp = of_get_address(dp, i++, &dsize, &flags);
+ if (addrp == NULL)
break;
+ if (!(flags & IORESOURCE_MEM))
+ continue;
+ daddr = of_translate_address(dp, addrp);
+ if (daddr == OF_BAD_ADDR)
+ continue;
+ if (daddr <= addr && addr < (daddr + dsize)) {
+ macos_display = dp;
+ goto foundit;
+ }
}
- if (i < dp->n_addrs) {
- foundit:
+ foundit:
+ if (macos_display) {
printk(KERN_INFO "MacOS display is %s\n",
dp->full_name);
- macos_display = dp;
break;
}
}
@@ -326,8 +321,10 @@ static void __init offb_init_nodriver(struct device_node *dp)
int *pp, i;
unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
- unsigned int rsize, *up;
- unsigned long address = 0;
+ unsigned int flags, rsize, *up;
+ u64 address = OF_BAD_ADDR;
+ u32 *addrp;
+ u64 asize;
if ((pp = (int *) get_property(dp, "depth", &len)) != NULL
&& len == sizeof(int))
@@ -363,7 +360,7 @@ static void __init offb_init_nodriver(struct device_node *dp)
break;
}
if (pdev) {
- for (i = 0; i < 6 && address == 0; i++) {
+ for (i = 0; i < 6 && address == OF_BAD_ADDR; i++) {
if ((pci_resource_flags(pdev, i) &
IORESOURCE_MEM) &&
(pci_resource_len(pdev, i) >= rsize))
@@ -374,27 +371,33 @@ static void __init offb_init_nodriver(struct device_node *dp)
}
#endif /* CONFIG_PCI */
- if (address == 0 &&
- (up = (unsigned *) get_property(dp, "address", &len)) != NULL &&
- len == sizeof(unsigned))
- address = (u_long) * up;
- if (address == 0) {
- for (i = 0; i < dp->n_addrs; ++i)
- if (dp->addrs[i].size >=
- pitch * height * depth / 8)
- break;
- if (i >= dp->n_addrs) {
+ /* This one is dodgy, we may drop it ... */
+ if (address == OF_BAD_ADDR &&
+ (up = (unsigned *) get_property(dp, "address", &len)) != NULL &&
+ len == sizeof(unsigned int))
+ address = (u64) * up;
+
+ if (address == OF_BAD_ADDR) {
+ for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
+ != NULL; i++) {
+ if (!(flags & IORESOURCE_MEM))
+ continue;
+ if (asize >= pitch * height * depth / 8)
+ break;
+ }
+ if (addrp == NULL) {
printk(KERN_ERR
"no framebuffer address found for %s\n",
dp->full_name);
return;
}
-
- address = (u_long) dp->addrs[i].address;
-
-#ifdef CONFIG_PPC64
- address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
-#endif
+ address = of_translate_address(dp, addrp);
+ if (address == OF_BAD_ADDR) {
+ printk(KERN_ERR
+ "can't translate framebuffer address for %s\n",
+ dp->full_name);
+ return;
+ }
/* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0)
@@ -459,7 +462,9 @@ static void __init offb_init_fb(const char *name, const char *full_name,
par->cmap_type = cmap_unknown;
if (depth == 8) {
- /* XXX kludge for ati */
+
+ /* Palette hacks disabled for now */
+#if 0
if (dp && !strncmp(name, "ATY,Rage128", 11)) {
unsigned long regbase = dp->addrs[2].address;
par->cmap_adr = ioremap(regbase, 0x1FFF);
@@ -490,6 +495,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
par->cmap_adr = ioremap(regbase + 0x6000, 0x1000);
par->cmap_type = cmap_gxt2000;
}
+#endif
fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_STATIC_PSEUDOCOLOR;
} else
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b251e754e16c..0d1957505359 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -31,9 +31,8 @@ static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int p9100_blank(int, struct fb_info *);
-static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int p9100_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
+static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
/*
* Frame buffer operations
@@ -222,7 +221,7 @@ static struct sbus_mmap_map p9100_mmap_map[] = {
{ 0, 0, 0 }
};
-static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct p9100_par *par = (struct p9100_par *)info->par;
@@ -232,8 +231,8 @@ static int p9100_mmap(struct fb_info *info, struct file *file, struct vm_area_st
vma);
}
-static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct p9100_par *par = (struct p9100_par *) info->par;
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index ca4082ae5a18..335e37465559 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -69,6 +69,8 @@ struct fb_info_platinum {
unsigned long total_vram;
int clktype;
int dactype;
+
+ struct resource rsrc_fb, rsrc_reg;
};
/*
@@ -97,9 +99,6 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
* Interface used by the world
*/
-int platinumfb_init(void);
-int platinumfb_setup(char*);
-
static struct fb_ops platinumfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = platinumfb_check_var,
@@ -138,13 +137,15 @@ static int platinumfb_set_par (struct fb_info *info)
init = platinum_reg_init[pinfo->vmode-1];
- if (pinfo->vmode == 13 && pinfo->cmode > 0)
- offset = 0x10;
+ if ((pinfo->vmode == VMODE_832_624_75) && (pinfo->cmode > CMODE_8))
+ offset = 0x10;
+
info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
info->fix.visual = (pinfo->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) + offset;
+ info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
+ + offset;
printk("line_length: %x\n", info->fix.line_length);
return 0;
}
@@ -221,7 +222,9 @@ static int platinumfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static inline int platinum_vram_reqd(int video_mode, int color_mode)
{
return vmode_attrs[video_mode-1].vres *
- (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000;
+ (vmode_attrs[video_mode-1].hres * (1<<color_mode) +
+ ((video_mode == VMODE_832_624_75) &&
+ (color_mode > CMODE_8)) ? 0x10 : 0x20) + 0x1000;
}
#define STORE_D2(a, d) { \
@@ -481,7 +484,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var,
/*
* Parse user speficied options (`video=platinumfb:')
*/
-int __init platinumfb_setup(char *options)
+static int __init platinumfb_setup(char *options)
{
char *this_opt;
@@ -522,19 +525,15 @@ int __init platinumfb_setup(char *options)
#define invalidate_cache(addr)
#endif
-static int __devinit platinumfb_probe(struct of_device* odev, const struct of_device_id *match)
+static int __devinit platinumfb_probe(struct of_device* odev,
+ const struct of_device_id *match)
{
struct device_node *dp = odev->node;
struct fb_info *info;
struct fb_info_platinum *pinfo;
- unsigned long addr, size;
volatile __u8 *fbuffer;
- int i, bank0, bank1, bank2, bank3, rc;
+ int bank0, bank1, bank2, bank3, rc;
- if (dp->n_addrs != 2) {
- printk(KERN_ERR "expecting 2 address for platinum (got %d)", dp->n_addrs);
- return -ENXIO;
- }
printk(KERN_INFO "platinumfb: Found Apple Platinum video hardware\n");
info = framebuffer_alloc(sizeof(*pinfo), &odev->dev);
@@ -542,26 +541,39 @@ static int __devinit platinumfb_probe(struct of_device* odev, const struct of_de
return -ENOMEM;
pinfo = info->par;
- /* Map in frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- /* Let's assume we can request either all or nothing */
- if (!request_mem_region(addr, size, "platinumfb")) {
- framebuffer_release(info);
- return -ENXIO;
- }
- if (size >= 0x400000) {
- /* frame buffer - map only 4MB */
- pinfo->frame_buffer_phys = addr;
- pinfo->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
- pinfo->base_frame_buffer = pinfo->frame_buffer;
- } else {
- /* registers */
- pinfo->platinum_regs_phys = addr;
- pinfo->platinum_regs = ioremap(addr, size);
- }
+ if (of_address_to_resource(dp, 0, &pinfo->rsrc_reg) ||
+ of_address_to_resource(dp, 1, &pinfo->rsrc_fb)) {
+ printk(KERN_ERR "platinumfb: Can't get resources\n");
+ framebuffer_release(info);
+ return -ENXIO;
}
+ if (!request_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.start -
+ pinfo->rsrc_reg.end + 1,
+ "platinumfb registers")) {
+ framebuffer_release(info);
+ return -ENXIO;
+ }
+ if (!request_mem_region(pinfo->rsrc_fb.start,
+ pinfo->rsrc_fb.start
+ - pinfo->rsrc_fb.end + 1,
+ "platinumfb framebuffer")) {
+ release_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.end -
+ pinfo->rsrc_reg.start + 1);
+ framebuffer_release(info);
+ return -ENXIO;
+ }
+
+ /* frame buffer - map only 4MB */
+ pinfo->frame_buffer_phys = pinfo->rsrc_fb.start;
+ pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000,
+ _PAGE_WRITETHRU);
+ pinfo->base_frame_buffer = pinfo->frame_buffer;
+
+ /* registers */
+ pinfo->platinum_regs_phys = pinfo->rsrc_reg.start;
+ pinfo->platinum_regs = ioremap(pinfo->rsrc_reg.start, 0x1000);
pinfo->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
request_mem_region(pinfo->cmap_regs_phys, 0x1000, "platinumfb cmap");
@@ -624,18 +636,16 @@ static int __devexit platinumfb_remove(struct of_device* odev)
{
struct fb_info *info = dev_get_drvdata(&odev->dev);
struct fb_info_platinum *pinfo = info->par;
- struct device_node *dp = odev->node;
- unsigned long addr, size;
- int i;
unregister_framebuffer (info);
/* Unmap frame buffer and registers */
- for (i = 0; i < dp->n_addrs; ++i) {
- addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- release_mem_region(addr, size);
- }
+ release_mem_region(pinfo->rsrc_fb.start,
+ pinfo->rsrc_fb.end -
+ pinfo->rsrc_fb.start + 1);
+ release_mem_region(pinfo->rsrc_reg.start,
+ pinfo->rsrc_reg.end -
+ pinfo->rsrc_reg.start + 1);
iounmap(pinfo->frame_buffer);
iounmap(pinfo->platinum_regs);
release_mem_region(pinfo->cmap_regs_phys, 0x1000);
@@ -662,7 +672,7 @@ static struct of_platform_driver platinum_driver =
.remove = platinumfb_remove,
};
-int __init platinumfb_init(void)
+static int __init platinumfb_init(void)
{
#ifndef MODULE
char *option = NULL;
@@ -676,7 +686,7 @@ int __init platinumfb_init(void)
return 0;
}
-void __exit platinumfb_exit(void)
+static void __exit platinumfb_exit(void)
{
of_unregister_driver(&platinum_driver);
}
diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h
index 2834fc1c344b..f6bd77cafd17 100644
--- a/drivers/video/platinumfb.h
+++ b/drivers/video/platinumfb.h
@@ -158,7 +158,9 @@ static struct platinum_regvals platinum_reg_init_14 = {
/* 832x624, 75Hz (13) */
static struct platinum_regvals platinum_reg_init_13 = {
0x70,
- { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */
+ { 864, 1680, 3344 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB,
+ * and we use 3344 instead of 3360 to fit in 2Mb
+ */
{ 0xff0, 4, 0, 0, 0, 0, 0x299, 0,
0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37,
0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52,
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 0277ce031e5e..5fe197943deb 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -91,6 +91,7 @@ struct pm2fb_par
u32 mem_config; /* MemConfig reg at probe */
u32 mem_control; /* MemControl reg at probe */
u32 boot_address; /* BootAddress reg at probe */
+ u32 palette[16];
};
/*
@@ -674,7 +675,7 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
*/
static int pm2fb_set_par(struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
u32 pixclock;
u32 width, height, depth;
u32 hsstart, hsend, hbend, htotal;
@@ -854,7 +855,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
if (regno >= info->cmap.len) /* no. of hw registers */
return 1;
@@ -929,7 +930,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
case 16:
case 24:
case 32:
- ((u32*)(info->pseudo_palette))[regno] = v;
+ par->palette[regno] = v;
break;
}
return 0;
@@ -955,7 +956,7 @@ static int pm2fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int pm2fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct pm2fb_par *p = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *p = info->par;
u32 base;
u32 depth;
u32 xres;
@@ -987,7 +988,7 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var,
*/
static int pm2fb_blank(int blank_mode, struct fb_info *info)
{
- struct pm2fb_par *par = (struct pm2fb_par *) info->par;
+ struct pm2fb_par *par = info->par;
u32 video = par->video;
DPRINTK("blank_mode %d\n", blank_mode);
@@ -1054,8 +1055,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
{
struct pm2fb_par *default_par;
struct fb_info *info;
- int size, err;
- int err_retval = -ENXIO;
+ int err, err_retval = -ENXIO;
err = pci_enable_device(pdev);
if ( err ) {
@@ -1063,11 +1063,10 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
return err;
}
- size = sizeof(struct pm2fb_par) + 256 * sizeof(u32);
- info = framebuffer_alloc(size, &pdev->dev);
+ info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev);
if ( !info )
return -ENOMEM;
- default_par = (struct pm2fb_par *) info->par;
+ default_par = info->par;
switch (pdev->device) {
case PCI_DEVICE_ID_TI_TVP4020:
@@ -1171,7 +1170,7 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
info->fbops = &pm2fb_ops;
info->fix = pm2fb_fix;
- info->pseudo_palette = (void *)(default_par + 1);
+ info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN;
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 2e11b601c488..0e78ddc81583 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -657,9 +657,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
static void pm3fb_detect(void);
static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info);
-static int pm3fb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info);
+static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
/* the struct that hold them together */
@@ -3438,9 +3436,7 @@ static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
return 0;
}
-static int pm3fb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, int con,
- struct fb_info *info)
+static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
u32 cm, i;
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index 28d1fe5fe340..d92f352211ef 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -299,8 +299,7 @@ static int aafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return -EINVAL;
}
-static int aafb_ioctl(struct inode *inode, struct file *file, u32 cmd,
- unsigned long arg, int con, struct fb_info *info)
+static int aafb_ioctl(struct fb_info *info, u32 cmd, unsigned long arg)
{
/* TODO: Not yet implemented */
return -ENOIOCTLCMD;
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 9fc10b9e6f57..53ad61f1038c 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -395,7 +395,7 @@ static int pxafb_blank(int blank, struct fb_info *info)
return 0;
}
-static int pxafb_mmap(struct fb_info *info, struct file *file,
+static int pxafb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct pxafb_info *fbi = (struct pxafb_info *)info;
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 600318f708f2..db9fb9074dbc 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -1497,8 +1497,8 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
}
-static int radeonfb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
unsigned int tmp;
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9f96e9237d..6c19ab6afb01 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -630,7 +630,7 @@ static void riva_load_video_mode(struct fb_info *info)
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct riva_regs newmode;
NVTRACE_ENTER();
@@ -925,7 +925,7 @@ riva_set_rop_solid(struct riva_par *par, int rop)
static void riva_setup_accel(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
RIVA_FIFO_FREE(par->riva, Clip, 2);
NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
@@ -979,7 +979,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
#ifdef CONFIG_PMAC_BACKLIGHT
static int riva_set_backlight_enable(int on, int level, void *data)
{
- struct riva_par *par = (struct riva_par *)data;
+ struct riva_par *par = data;
U032 tmp_pcrt, tmp_pmc;
tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
@@ -1008,7 +1008,7 @@ static int riva_set_backlight_level(int level, void *data)
static int rivafb_open(struct fb_info *info, int user)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
NVTRACE_ENTER();
@@ -1034,7 +1034,7 @@ static int rivafb_open(struct fb_info *info, int user)
static int rivafb_release(struct fb_info *info, int user)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int cnt = atomic_read(&par->ref_count);
NVTRACE_ENTER();
@@ -1057,7 +1057,7 @@ static int rivafb_release(struct fb_info *info, int user)
static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct fb_videomode *mode;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
int nom, den; /* translating from pixels->bytes */
int mode_valid = 0;
@@ -1166,7 +1166,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int rivafb_set_par(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
/* vgaHWunlock() + riva unlock (0x7F) */
@@ -1205,43 +1205,19 @@ static int rivafb_set_par(struct fb_info *info)
static int rivafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
unsigned int base;
NVTRACE_ENTER();
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if (var->yoffset > (var->yres_virtual - var->yres))
- return -EINVAL;
-
- if (var->vmode & FB_VMODE_YWRAP) {
- if (var->yoffset < 0
- || var->yoffset >= info->var.yres_virtual
- || var->xoffset) return -EINVAL;
- } else {
- if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
- return -EINVAL;
- }
-
base = var->yoffset * info->fix.line_length + var->xoffset;
-
par->riva.SetStartAddress(&par->riva, base);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
-
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
NVTRACE_LEAVE();
return 0;
}
static int rivafb_blank(int blank, struct fb_info *info)
{
- struct riva_par *par= (struct riva_par *)info->par;
+ struct riva_par *par= info->par;
unsigned char tmp, vesa;
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
@@ -1304,7 +1280,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
RIVA_HW_INST *chip = &par->riva;
int i;
@@ -1393,7 +1369,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
*/
static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u_int color, rop = 0;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
@@ -1449,7 +1425,7 @@ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
*/
static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
cfb_copyarea(info, region);
@@ -1495,7 +1471,7 @@ static inline void convert_bgcolor_16(u32 *col)
static void rivafb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u32 fgx = 0, bgx = 0, width, tmp;
u8 *cdat = (u8 *) image->data;
volatile u32 __iomem *d;
@@ -1580,7 +1556,7 @@ static void rivafb_imageblit(struct fb_info *info,
*/
static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
u8 data[MAX_CURS * MAX_CURS/8];
int i, set = cursor->set;
u16 fg, bg;
@@ -1664,7 +1640,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
static int rivafb_sync(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
+ struct riva_par *par = info->par;
wait_for_idle(par);
return 0;
@@ -1696,7 +1672,7 @@ static struct fb_ops riva_fb_ops = {
static int __devinit riva_set_fbinfo(struct fb_info *info)
{
unsigned int cmap_len;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
info->flags = FBINFO_DEFAULT
@@ -1733,7 +1709,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
#ifdef CONFIG_PPC_OF
static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct device_node *dp;
unsigned char *pedid = NULL;
unsigned char *disptype = NULL;
@@ -1767,7 +1743,7 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
static int __devinit riva_get_EDID_i2c(struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
struct fb_var_screeninfo var;
int i;
@@ -1837,7 +1813,7 @@ static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
static void __devinit riva_get_edidinfo(struct fb_info *info)
{
struct fb_var_screeninfo *var = &rivafb_default_var;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
fb_edid_to_monspecs(par->EDID, &info->monspecs);
fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
@@ -1909,7 +1885,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
ret = -ENOMEM;
goto err_ret;
}
- default_par = (struct riva_par *) info->par;
+ default_par = info->par;
default_par->pdev = pd;
info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
@@ -2070,7 +2046,7 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
err_iounmap_screen_base:
#ifdef CONFIG_FB_RIVA_I2C
- riva_delete_i2c_busses((struct riva_par *) info->par);
+ riva_delete_i2c_busses(info->par);
#endif
iounmap(info->screen_base);
err_iounmap_pramin:
@@ -2093,7 +2069,7 @@ err_ret:
static void __exit rivafb_remove(struct pci_dev *pd)
{
struct fb_info *info = pci_get_drvdata(pd);
- struct riva_par *par = (struct riva_par *) info->par;
+ struct riva_par *par = info->par;
NVTRACE_ENTER();
if (!info)
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 77151d8e0766..8b1967fc116a 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -30,7 +30,7 @@
static void riva_gpio_setscl(void* data, int state)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val;
@@ -48,7 +48,7 @@ static void riva_gpio_setscl(void* data, int state)
static void riva_gpio_setsda(void* data, int state)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val;
@@ -66,7 +66,7 @@ static void riva_gpio_setsda(void* data, int state)
static int riva_gpio_getscl(void* data)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val = 0;
@@ -81,7 +81,7 @@ static int riva_gpio_getscl(void* data)
static int riva_gpio_getsda(void* data)
{
- struct riva_i2c_chan *chan = (struct riva_i2c_chan *)data;
+ struct riva_i2c_chan *chan = data;
struct riva_par *par = chan->par;
u32 val = 0;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ce6e749db3a7..d574dd3c9c8a 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -87,6 +87,7 @@
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -96,7 +97,6 @@
#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>
@@ -552,7 +552,7 @@ static inline void modify_gpio(void __iomem *reg,
* s3c2410fb_init_registers - Initialise all LCD-related registers
*/
-int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
+static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi)
{
unsigned long flags;
@@ -634,7 +634,7 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id, struct pt_regs *r)
static char driver_name[]="s3c2410fb";
-int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __init s3c2410fb_probe(struct platform_device *pdev)
{
struct s3c2410fb_info *info;
struct fb_info *fbinfo;
@@ -667,8 +667,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
info->fb = fbinfo;
platform_set_drvdata(pdev, fbinfo);
- s3c2410fb_init_registers(info);
-
dprintk("devinit\n");
strcpy(fbinfo->fix.id, driver_name);
@@ -701,8 +699,8 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
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.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;
@@ -746,7 +744,6 @@ int __init s3c2410fb_probe(struct platform_device *pdev)
goto release_irq;
}
- clk_use(info->clk);
clk_enable(info->clk);
dprintk("got and enabled clock\n");
@@ -783,7 +780,6 @@ 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);
@@ -828,7 +824,6 @@ static int s3c2410fb_remove(struct platform_device *pdev)
if (info->clk) {
clk_disable(info->clk);
- clk_unuse(info->clk);
clk_put(info->clk);
info->clk = NULL;
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 2ea1354e439f..8a893ce7040d 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -178,7 +178,6 @@
#include <asm/hardware.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
#include <asm/arch/assabet.h>
@@ -816,7 +815,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
return 0;
}
-static int sa1100fb_mmap(struct fb_info *info, struct file *file,
+static int sa1100fb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
@@ -1455,7 +1454,11 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
static int __init sa1100fb_probe(struct platform_device *pdev)
{
struct sa1100fb_info *fbi;
- int ret;
+ int ret, irq;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ return -EINVAL;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
@@ -1470,7 +1473,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
if (ret)
goto failed;
- ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
+ ret = request_irq(irq, sa1100fb_handle_irq, SA_INTERRUPT,
"LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
@@ -1492,7 +1495,7 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
ret = register_framebuffer(&fbi->fb);
if (ret < 0)
- goto failed;
+ goto err_free_irq;
#ifdef CONFIG_CPU_FREQ
fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1504,7 +1507,9 @@ static int __init sa1100fb_probe(struct platform_device *pdev)
/* This driver cannot be unloaded at the moment */
return 0;
-failed:
+ err_free_irq:
+ free_irq(irq, fbi);
+ failed:
platform_set_drvdata(pdev, NULL);
kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 3c98457783c4..00719a91479f 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -49,7 +49,7 @@
static void savage4_gpio_setscl(void *data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
r = readl(chan->ioaddr + chan->reg);
@@ -63,7 +63,7 @@ static void savage4_gpio_setscl(void *data, int val)
static void savage4_gpio_setsda(void *data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
r = readl(chan->ioaddr + chan->reg);
@@ -77,21 +77,21 @@ static void savage4_gpio_setsda(void *data, int val)
static int savage4_gpio_getscl(void *data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
}
static int savage4_gpio_getsda(void *data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
}
static void prosavage_gpio_setscl(void* data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
u32 r;
SET_CR_IX(chan->ioaddr, chan->reg);
@@ -107,7 +107,7 @@ static void prosavage_gpio_setscl(void* data, int val)
static void prosavage_gpio_setsda(void* data, int val)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
unsigned int r;
SET_CR_IX(chan->ioaddr, chan->reg);
@@ -123,7 +123,7 @@ static void prosavage_gpio_setsda(void* data, int val)
static int prosavage_gpio_getscl(void* data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
SET_CR_IX(chan->ioaddr, chan->reg);
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SCL_IN));
@@ -131,7 +131,7 @@ static int prosavage_gpio_getscl(void* data)
static int prosavage_gpio_getsda(void* data)
{
- struct savagefb_i2c_chan *chan = (struct savagefb_i2c_chan *)data;
+ struct savagefb_i2c_chan *chan = data;
SET_CR_IX(chan->ioaddr, chan->reg);
return (0 != (GET_CR_DATA(chan->ioaddr) & PROSAVAGE_I2C_SDA_IN));
@@ -140,10 +140,9 @@ static int prosavage_gpio_getsda(void* data)
static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
const char *name)
{
- int (*add_bus)(struct i2c_adapter *) = symbol_get(i2c_bit_add_bus);
int rc = 0;
- if (add_bus && chan->par) {
+ if (chan->par) {
strcpy(chan->adapter.name, name);
chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_SAVAGE;
@@ -161,7 +160,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
chan->algo.setscl(chan, 1);
udelay(20);
- rc = add_bus(&chan->adapter);
+ rc = i2c_bit_add_bus(&chan->adapter);
if (rc == 0)
dev_dbg(&chan->par->pcidev->dev,
@@ -169,8 +168,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
else
dev_warn(&chan->par->pcidev->dev,
"Failed to register I2C bus %s.\n", name);
-
- symbol_put(i2c_bit_add_bus);
} else
chan->par = NULL;
@@ -179,7 +176,7 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
void savagefb_create_i2c_busses(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
par->chan.par = par;
switch(info->fix.accel) {
@@ -193,6 +190,7 @@ void savagefb_create_i2c_busses(struct fb_info *info)
par->chan.algo.getscl = prosavage_gpio_getscl;
break;
case FB_ACCEL_SAVAGE4:
+ case FB_ACCEL_SAVAGE2000:
par->chan.reg = 0xff20;
par->chan.ioaddr = par->mmio.vbase;
par->chan.algo.setsda = savage4_gpio_setsda;
@@ -209,14 +207,10 @@ void savagefb_create_i2c_busses(struct fb_info *info)
void savagefb_delete_i2c_busses(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
- int (*del_bus)(struct i2c_adapter *) =
- symbol_get(i2c_bit_del_bus);
+ struct savagefb_par *par = info->par;
- if (del_bus && par->chan.par) {
- del_bus(&par->chan.adapter);
- symbol_put(i2c_bit_del_bus);
- }
+ if (par->chan.par)
+ i2c_bit_del_bus(&par->chan.adapter);
par->chan.par = NULL;
}
@@ -224,8 +218,6 @@ void savagefb_delete_i2c_busses(struct fb_info *info)
static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
{
u8 start = 0x0;
- int (*transfer)(struct i2c_adapter *, struct i2c_msg *, int) =
- symbol_get(i2c_transfer);
struct i2c_msg msgs[] = {
{
.addr = SAVAGE_DDC,
@@ -239,21 +231,19 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
};
u8 *buf = NULL;
- if (transfer && chan->par) {
+ if (chan->par) {
buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (buf) {
msgs[1].buf = buf;
- if (transfer(&chan->adapter, msgs, 2) != 2) {
+ if (i2c_transfer(&chan->adapter, msgs, 2) != 2) {
dev_dbg(&chan->par->pcidev->dev,
"Unable to read EDID block.\n");
kfree(buf);
buf = NULL;
}
}
-
- symbol_put(i2c_transfer);
}
return buf;
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
index bac8ea3a0108..bbcc055d3bb7 100644
--- a/drivers/video/savage/savagefb_accel.c
+++ b/drivers/video/savage/savagefb_accel.c
@@ -21,7 +21,7 @@ static u32 savagefb_rop[] = {
int savagefb_sync(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
par->SavageWaitIdle(par);
return 0;
@@ -29,7 +29,7 @@ int savagefb_sync(struct fb_info *info)
void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int sx = region->sx, dx = region->dx;
int sy = region->sy, dy = region->dy;
int cmd;
@@ -63,7 +63,7 @@ void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int cmd, color;
if (!rect->width || !rect->height)
@@ -90,7 +90,7 @@ void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int fg, bg, size, i, width;
int cmd;
u32 *src = (u32 *) image->data;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 09e2f2841901..ab727eaa7f43 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -686,7 +686,7 @@ static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode
static int savagefb_check_var (struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int memlen, vramlen, mode_valid = 0;
DBG("savagefb_check_var");
@@ -1025,7 +1025,7 @@ static int savagefb_setcolreg(unsigned regno,
unsigned transp,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
if (regno >= NR_PALETTE)
return -EINVAL;
@@ -1328,7 +1328,7 @@ static void savagefb_set_fix(struct fb_info *info)
#if defined(CONFIG_FB_SAVAGE_ACCEL)
static void savagefb_set_clip(struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int cmd;
cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
@@ -1342,7 +1342,7 @@ static void savagefb_set_clip(struct fb_info *info)
static int savagefb_set_par (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
struct fb_var_screeninfo *var = &info->var;
int err;
@@ -1381,29 +1381,9 @@ static int savagefb_set_par (struct fb_info *info)
static int savagefb_pan_display (struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
- u_int y_bottom;
-
- y_bottom = var->yoffset;
-
- if (!(var->vmode & FB_VMODE_YWRAP))
- y_bottom += var->yres;
-
- if (var->xoffset > (var->xres_virtual - var->xres))
- return -EINVAL;
- if (y_bottom > info->var.yres_virtual)
- return -EINVAL;
+ struct savagefb_par *par = info->par;
savagefb_update_start (par, var);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
-
- if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
- else
- info->var.vmode &= ~FB_VMODE_YWRAP;
-
return 0;
}
@@ -1534,7 +1514,7 @@ static void savage_disable_mmio (struct savagefb_par *par)
static int __devinit savage_map_mmio (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG ("savage_map_mmio");
if (S3_SAVAGE3D_SERIES (par->chip))
@@ -1567,7 +1547,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
static void __devinit savage_unmap_mmio (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG ("savage_unmap_mmio");
savage_disable_mmio(par);
@@ -1581,7 +1561,7 @@ static void __devinit savage_unmap_mmio (struct fb_info *info)
static int __devinit savage_map_video (struct fb_info *info,
int video_len)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int resource;
DBG("savage_map_video");
@@ -1619,7 +1599,7 @@ static int __devinit savage_map_video (struct fb_info *info,
static void __devinit savage_unmap_video (struct fb_info *info)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
DBG("savage_unmap_video");
@@ -1869,7 +1849,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
struct pci_dev *dev,
const struct pci_device_id *id)
{
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct savagefb_par *par = info->par;
int err = 0;
par->pcidev = dev;
@@ -2139,8 +2119,7 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
static void __devexit savagefb_remove (struct pci_dev *dev)
{
- struct fb_info *info =
- (struct fb_info *)pci_get_drvdata(dev);
+ struct fb_info *info = pci_get_drvdata(dev);
DBG("savagefb_remove");
@@ -2174,9 +2153,8 @@ static void __devexit savagefb_remove (struct pci_dev *dev)
static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
{
- struct fb_info *info =
- (struct fb_info *)pci_get_drvdata(dev);
- struct savagefb_par *par = (struct savagefb_par *)info->par;
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct savagefb_par *par = info->par;
DBG("savagefb_suspend");
@@ -2210,9 +2188,8 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
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;
+ struct fb_info *info = pci_get_drvdata(dev);
+ struct savagefb_par *par = info->par;
int cur_state = par->pm_state;
DBG("savage_resume");
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 3a74a63dd4f2..a4d7cc51ce0b 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -199,8 +199,7 @@ struct fbcmap32 {
#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
-static int fbiogetputcmap(struct file *file, struct fb_info *info,
- unsigned int cmd, unsigned long arg)
+static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
struct fbcmap32 __user *argp = (void __user *)arg;
struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
@@ -216,10 +215,10 @@ static int fbiogetputcmap(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->blue);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
+ return info->fbops->fb_ioctl(info,
(cmd == FBIOPUTCMAP32) ?
FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
- (unsigned long)p, info);
+ (unsigned long)p);
}
struct fbcursor32 {
@@ -236,8 +235,7 @@ struct fbcursor32 {
#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
-static int fbiogscursor(struct file *file, struct fb_info *info,
- unsigned long arg)
+static int fbiogscursor(struct fb_info *info, unsigned long arg)
{
struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
struct fbcursor32 __user *argp = (void __user *)arg;
@@ -260,12 +258,10 @@ static int fbiogscursor(struct file *file, struct fb_info *info,
ret |= put_user(compat_ptr(addr), &p->image);
if (ret)
return -EFAULT;
- return info->fbops->fb_ioctl(file->f_dentry->d_inode, file,
- FBIOSCURSOR, (unsigned long)p, info);
+ return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
}
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case FBIOGTYPE:
@@ -278,14 +274,13 @@ long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
case FBIOSCURPOS:
case FBIOGCURPOS:
case FBIOGCURMAX:
- return info->fbops->fb_ioctl(file->f_dentry->d_inode,
- file, cmd, arg, info);
+ return info->fbops->fb_ioctl(info, cmd, arg);
case FBIOPUTCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOGETCMAP32:
- return fbiogetputcmap(file, info, cmd, arg);
+ return fbiogetputcmap(info, cmd, arg);
case FBIOSCURSOR32:
- return fbiogscursor(file, info, arg);
+ return fbiogscursor(info, arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h
index b470e52ce9e2..492828c3fe8f 100644
--- a/drivers/video/sbuslib.h
+++ b/drivers/video/sbuslib.h
@@ -20,7 +20,7 @@ extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fb_info *info,
int type, int fb_depth, unsigned long fb_size);
-long sbusfb_compat_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info);
+int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
#endif /* _SBUSLIB_H */
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 7054660767e4..2e6df1fcb2b9 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -115,7 +115,7 @@ static int sgivwfb_set_par(struct fb_info *info);
static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static struct fb_ops sgivwfb_ops = {
@@ -706,7 +706,7 @@ static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green,
return 0;
}
-static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
unsigned long size = vma->vm_end - vma->vm_start;
@@ -723,7 +723,6 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file,
if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
size, vma->vm_page_prot))
return -EAGAIN;
- vma->vm_file = file;
printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
return 0;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index dea1a46c67c4..8adf5bf91eee 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -1743,13 +1743,14 @@ sisfb_blank(int blank, struct fb_info *info)
/* ----------- FBDev related routines for all series ---------- */
-static int
-sisfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- int con,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
+#else
+static int sisfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info)
#endif
- struct fb_info *info)
{
struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
struct sis_memreq sismemreq;
@@ -1924,19 +1925,6 @@ sisfb_ioctl(struct inode *inode, struct file *file,
return 0;
}
-#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();
- return ret;
-}
-#endif
-
static int
sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
@@ -2007,7 +1995,7 @@ static struct fb_ops sisfb_ops = {
#endif
.fb_sync = fbcon_sis_sync,
#ifdef SIS_NEW_CONFIG_COMPAT
- .fb_compat_ioctl= sisfb_compat_ioctl,
+ .fb_compat_ioctl= sisfb_ioctl,
#endif
.fb_ioctl = sisfb_ioctl
};
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 445bcbba03ae..70b6df371b8e 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -727,9 +727,14 @@ static int sisfb_ioctl(struct inode *inode, struct file *file,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
+static int sisfb_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
+#else
static int sisfb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
struct fb_info *info);
+#endif
static int sisfb_set_par(struct fb_info *info);
static int sisfb_blank(int blank,
struct fb_info *info);
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a01e7ecc15ed..9b707771d757 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -115,7 +115,8 @@ static struct fb_fix_screeninfo xxxfb_fix __initdata = {
/*
* If your driver supports multiple boards or it supports multiple
* framebuffers, you should make these arrays, or allocate them
- * dynamically (using kmalloc()).
+ * dynamically using framebuffer_alloc() and free them with
+ * framebuffer_release().
*/
static struct fb_info info;
@@ -179,18 +180,31 @@ static int xxxfb_release(const struct fb_info *info, int user)
* intent to only test a mode and not actually set it. The stuff in
* modedb.c is a example of this. If the var passed in is slightly
* off by what the hardware can support then we alter the var PASSED in
- * to what we can do. If the hardware doesn't support mode change
- * a -EINVAL will be returned by the upper layers. You don't need to
- * implement this function then. If you hardware doesn't support
- * changing the resolution then this function is not needed. In this
- * case the driver woudl just provide a var that represents the static
- * state the screen is in.
+ * to what we can do.
+ *
+ * For values that are off, this function must round them _up_ to the
+ * next value that is supported by the hardware. If the value is
+ * greater than the highest value supported by the hardware, then this
+ * function must return -EINVAL.
+ *
+ * Exception to the above rule: Some drivers have a fixed mode, ie,
+ * the hardware is already set at boot up, and cannot be changed. In
+ * this case, it is more acceptable that this function just return
+ * a copy of the currently working var (info->var). Better is to not
+ * implement this function, as the upper layer will do the copying
+ * of the current var for you.
+ *
+ * Note: This is the only function where the contents of var can be
+ * freely adjusted after the driver has been registered. If you find
+ * that you have code outside of this function that alters the content
+ * of var, then you are doing something wrong. Note also that the
+ * contents of info->var must be left untouched at all times after
+ * driver registration.
*
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- const struct xxx_par *par = (const struct xxx_par *) info->par;
/* ... */
return 0;
}
@@ -204,14 +218,39 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
* fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
* fb_info since we are using that data. This means we depend on the
* data in var inside fb_info to be supported by the hardware.
- * xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ * This function is also used to recover/restore the hardware to a
+ * known working state.
+ *
+ * xxxfb_check_var is always called before xxxfb_set_par to ensure that
+ * the contents of var is always valid.
+ *
* Again if you can't change the resolution you don't need this function.
*
+ * However, even if your hardware does not support mode changing,
+ * a set_par might be needed to at least initialize the hardware to
+ * a known working state, especially if it came back from another
+ * process that also modifies the same hardware, such as X.
+ *
+ * If this is the case, a combination such as the following should work:
+ *
+ * static int xxxfb_check_var(struct fb_var_screeninfo *var,
+ * struct fb_info *info)
+ * {
+ * *var = info->var;
+ * return 0;
+ * }
+ *
+ * static int xxxfb_set_par(struct fb_info *info)
+ * {
+ * init your hardware here
+ * }
+ *
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_set_par(struct fb_info *info)
{
- struct xxx_par *par = (struct xxx_par *) info->par;
+ struct xxx_par *par = info->par;
/* ... */
return 0;
}
@@ -258,70 +297,110 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of DAC
- * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
+ * pseudo_palette[X] is programmed to (X << red.offset) |
+ * (X << green.offset) |
+ * (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = SUM(var->{color}.length)
*
* Pseudocolor:
- * uses offset = 0 && length = DAC register width.
* var->{color}.offset is 0
- * var->{color}.length contains widht of DAC
- * cmap is not used
- * DAC[X] is programmed to (red, green, blue)
+ * var->{color}.length contains width of DAC or the number of unique
+ * colors available (color depth)
+ * pseudo_palette is not used
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = var->{color}.length
+ *
+ * Static pseudocolor:
+ * same as Pseudocolor, but the RAMDAC is not programmed (read-only)
+ *
+ * Mono01/Mono10:
+ * Has only 2 values, black on white or white on black (fg on bg),
+ * var->{color}.offset is 0
+ * white = (1 << var->{color}.length) - 1, black = 0
+ * pseudo_palette is not used
+ * RAMDAC does not exist
+ * color depth is always 2
+ *
* Truecolor:
* does not use RAMDAC (usually has 3 of them).
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
- * cmap is programmed to (red << red.offset) | (green << green.offset) |
- * (blue << blue.offset) | (transp << transp.offset)
+ * pseudo_palette is programmed to (red << red.offset) |
+ * (green << green.offset) |
+ * (blue << blue.offset) |
+ * (transp << transp.offset)
* RAMDAC does not exist
+ * color depth = SUM(var->{color}.length})
+ *
+ * The color depth is used by fbcon for choosing the logo and also
+ * for color palette transformation if color depth < 4
+ *
+ * As can be seen from the above, the field bits_per_pixel is _NOT_
+ * a criteria for describing the color visual.
+ *
+ * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor,
+ * and higher than that, true/directcolor. This is incorrect, one needs
+ * to look at the fix->visual.
+ *
+ * Another common mistake is using bits_per_pixel to calculate the color
+ * depth. The bits_per_pixel field does not directly translate to color
+ * depth. You have to compute for the color depth (using the color
+ * bitfields) and fix->visual as seen above.
+ */
+
+ /*
+ * This is the point where the color is converted to something that
+ * is acceptable by the hardware.
*/
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
- switch (info->fix.visual) {
- case FB_VISUAL_TRUECOLOR:
- case FB_VISUAL_PSEUDOCOLOR:
- red = CNVT_TOHW(red, info->var.red.length);
- green = CNVT_TOHW(green, info->var.green.length);
- blue = CNVT_TOHW(blue, info->var.blue.length);
- transp = CNVT_TOHW(transp, info->var.transp.length);
- break;
- case FB_VISUAL_DIRECTCOLOR:
- /* example here assumes 8 bit DAC. Might be different
- * for your hardware */
- red = CNVT_TOHW(red, 8);
- green = CNVT_TOHW(green, 8);
- blue = CNVT_TOHW(blue, 8);
- /* hey, there is bug in transp handling... */
- transp = CNVT_TOHW(transp, 8);
- break;
- }
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
#undef CNVT_TOHW
- /* Truecolor has hardware independent palette */
- if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
- u32 v;
-
- if (regno >= 16)
- return -EINVAL;
-
- v = (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset) |
- (transp << info->var.transp.offset);
-
- switch (info->var.bits_per_pixel) {
- case 8:
- /* Yes some hand held devices have this. */
- ((u8*)(info->pseudo_palette))[regno] = v;
- break;
- case 16:
- ((u16*)(info->pseudo_palette))[regno] = v;
- break;
- case 24:
- case 32:
- ((u32*)(info->pseudo_palette))[regno] = v;
- break;
- }
- return 0;
+ /*
+ * This is the point where the function feeds the color to the hardware
+ * palette after converting the colors to something acceptable by
+ * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and
+ * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette.
+ * If you have code that writes to the hardware CLUT, and it's not
+ * any of the above visuals, then you are doing something wrong.
+ */
+ if (info->fix.visual == FB_VISUAL_DIRECTCOLOR ||
+ info->fix.visual == FB_VISUAL_TRUECOLOR)
+ write_{red|green|blue|transp}_to_clut();
+
+ /* This is the point were you need to fill up the contents of
+ * info->pseudo_palette. This structure is used _only_ by fbcon, thus
+ * it only contains 16 entries to match the number of colors supported
+ * by the console. The pseudo_palette is used only if the visual is
+ * in directcolor or truecolor mode. With other visuals, the
+ * pseudo_palette is not used. (This might change in the future.)
+ *
+ * The contents of the pseudo_palette is in raw pixel format. Ie, each
+ * entry can be written directly to the framebuffer without any conversion.
+ * The pseudo_palette is (void *). However, if using the generic
+ * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette
+ * must be casted to (u32 *) _regardless_ of the bits per pixel. If the
+ * driver is using its own drawing functions, then it can use whatever
+ * size it wants.
+ */
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ ((u32*)(info->pseudo_palette))[regno] = v;
}
+
/* ... */
return 0;
}
@@ -340,6 +419,17 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int xxxfb_pan_display(struct fb_var_screeninfo *var,
const struct fb_info *info)
{
+ /*
+ * If your hardware does not support panning, _do_ _not_ implement this
+ * function. Creating a dummy function will just confuse user apps.
+ */
+
+ /*
+ * Note that even if this function is fully functional, a setting of
+ * 0 in both xpanstep and ypanstep means that this function will never
+ * get called.
+ */
+
/* ... */
return 0;
}
@@ -349,15 +439,20 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var,
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*
- * Blank the screen if blank_mode != 0, else unblank. Return 0 if
- * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
- * video mode which doesn't support it. Implements VESA suspend
- * and powerdown modes on hardware that supports disabling hsync/vsync:
- * blank_mode == 2: suspend vsync
- * blank_mode == 3: suspend hsync
- * blank_mode == 4: powerdown
+ * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
+ * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+ * e.g. a video mode which doesn't support it.
*
- * Returns negative errno on error, or zero on success.
+ * Implements VESA suspend and powerdown modes on hardware that supports
+ * disabling hsync/vsync:
+ *
+ * FB_BLANK_NORMAL = display is blanked, syncs are on.
+ * FB_BLANK_HSYNC_SUSPEND = hsync off
+ * FB_BLANK_VSYNC_SUSPEND = vsync off
+ * FB_BLANK_POWERDOWN = hsync and vsync off
+ *
+ * If implementing this function, at least support FB_BLANK_UNBLANK.
+ * Return !0 for any modes that are unimplemented.
*
*/
static int xxxfb_blank(int blank_mode, const struct fb_info *info)
@@ -454,6 +549,14 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
* @data: The actual data used to construct the image on the display.
* @cmap: The colormap used for color images.
*/
+
+/*
+ * The generic function, cfb_imageblit, expects that the bitmap scanlines are
+ * padded to the next byte. Most hardware accelerators may require padding to
+ * the next u16 or the next u32. If that is the case, the driver can specify
+ * this by setting info->pixmap.scan_align = 2 or 4. See a more
+ * comprehensive description of the pixmap below.
+ */
}
/**
@@ -517,6 +620,7 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
*/
void xxxfb_rotate(struct fb_info *info, int angle)
{
+/* Will be deprecated */
}
/**
@@ -540,6 +644,9 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait)
* so we can have consistent display output.
*
* @info: frame buffer structure that represents a single frame buffer
+ *
+ * If the driver has implemented its own hardware-based drawing function,
+ * implementing this function is highly recommended.
*/
void xxxfb_sync(struct fb_info *info)
{
@@ -549,20 +656,25 @@ void xxxfb_sync(struct fb_info *info)
* Initialization
*/
-int __init xxxfb_init(void)
+/* static int __init xxfb_probe (struct device *device) -- for platform devs */
+static int __init xxxfb_probe(struct pci_dev *dev,
+ const_struct pci_device_id *ent)
{
+ struct fb_info *info;
+ struct xxx_par *par;
+ struct device = &dev->dev; /* for pci drivers */
int cmap_len, retval;
/*
- * For kernel boot options (in 'video=xxxfb:<options>' format)
+ * Dynamically allocate info and par
*/
-#ifndef MODULE
- char *option = NULL;
+ info = framebuffer_alloc(sizeof(struct xxx_par), device);
- if (fb_get_options("xxxfb", &option))
- return -ENODEV;
- xxxfb_setup(option);
-#endif
+ if (!info) {
+ /* goto error path */
+ }
+
+ par = info->par;
/*
* Here we set the screen_base to the virtual memory address
@@ -570,18 +682,87 @@ int __init xxxfb_init(void)
* from the bus layer and then translate it to virtual memory
* space via ioremap. Consult ioport.h.
*/
- info.screen_base = framebuffer_virtual_memory;
- info.fbops = &xxxfb_ops;
- info.fix = xxxfb_fix;
- info.pseudo_palette = pseudo_palette;
-
+ info->screen_base = framebuffer_virtual_memory;
+ info->fbops = &xxxfb_ops;
+ info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be
+ * used, so mark it as __initdata
+ */
+ info->pseudo_palette = pseudo_palette; /* The pseudopalette is an
+ * 16-member array
+ */
/*
* Set up flags to indicate what sort of acceleration your
* driver can provide (pan/wrap/copyarea/etc.) and whether it
* is a module -- see FBINFO_* in include/linux/fb.h
+ *
+ * If your hardware can support any of the hardware accelerated functions
+ * fbcon performance will improve if info->flags is set properly.
+ *
+ * FBINFO_HWACCEL_COPYAREA - hardware moves
+ * FBINFO_HWACCEL_FILLRECT - hardware fills
+ * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion
+ * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis
+ * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis
+ * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled
+ * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion
+ * FBINFO_MISC_TILEBLITTING - hardware can do tile blits
+ *
+ * NOTE: These are for fbcon use only.
+ */
+ info->flags = FBINFO_DEFAULT;
+
+/********************* This stage is optional ******************************/
+ /*
+ * The struct pixmap is a scratch pad for the drawing functions. This
+ * is where the monochrome bitmap is constructed by the higher layers
+ * and then passed to the accelerator. For drivers that uses
+ * cfb_imageblit, you can skip this part. For those that have a more
+ * rigorous requirement, this stage is needed
+ */
+
+ /* PIXMAP_SIZE should be small enough to optimize drawing, but not
+ * large enough that memory is wasted. A safe size is
+ * (max_xres * max_font_height/8). max_xres is driver dependent,
+ * max_font_height is 32.
+ */
+ info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL);
+ if (!info->pixmap.addr) {
+ /* goto error */
+ }
+
+ info->pixmap.size = PIXMAP_SIZE;
+
+ /*
+ * FB_PIXMAP_SYSTEM - memory is in system ram
+ * FB_PIXMAP_IO - memory is iomapped
+ * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap,
+ * usually if FB_PIXMAP_IO is set.
+ *
+ * Currently, FB_PIXMAP_IO is unimplemented.
+ */
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+ /*
+ * scan_align is the number of padding for each scanline. It is in bytes.
+ * Thus for accelerators that need padding to the next u32, put 4 here.
+ */
+ info->pixmap.scan_align = 4;
+
+ /*
+ * buf_align is the amount to be padded for the buffer. For example,
+ * the i810fb needs a scan_align of 2 but expects it to be fed with
+ * dwords, so a buf_align = 4 is required.
*/
- info.flags = FBINFO_DEFAULT;
- info.par = current_par;
+ info->pixmap.buf_align = 4;
+
+ /* access_align is how many bits can be accessed from the framebuffer
+ * ie. some epson cards allow 16-bit access only. Most drivers will
+ * be safe with u32 here.
+ *
+ * NOTE: This field is currently unused.
+ */
+ info->pixmap.scan_align = 32
+/***************************** End optional stage ***************************/
/*
* This should give a reasonable default video mode. The following is
@@ -590,42 +771,145 @@ int __init xxxfb_init(void)
if (!mode_option)
mode_option = "640x480@60";
- retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8);
+ retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8);
if (!retval || retval == 4)
return -EINVAL;
/* This has to been done !!! */
- fb_alloc_cmap(&info.cmap, cmap_len, 0);
+ fb_alloc_cmap(info->cmap, cmap_len, 0);
/*
* The following is done in the case of having hardware with a static
* mode. If we are setting the mode ourselves we don't call this.
*/
- info.var = xxxfb_var;
-
- if (register_framebuffer(&info) < 0)
+ info->var = xxxfb_var;
+
+ /*
+ * For drivers that can...
+ */
+ xxxfb_check_var(&info->var, info);
+
+ /*
+ * Does a call to fb_set_par() before register_framebuffer needed? This
+ * will depend on you and the hardware. If you are sure that your driver
+ * is the only device in the system, a call to fb_set_par() is safe.
+ *
+ * Hardware in x86 systems has a VGA core. Calling set_par() at this
+ * point will corrupt the VGA console, so it might be safer to skip a
+ * call to set_par here and just allow fbcon to do it for you.
+ */
+ /* xxxfb_set_par(info); */
+
+ if (register_framebuffer(info) < 0)
return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
- info.fix.id);
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+ pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
return 0;
}
/*
* Cleanup
*/
+/* static void __exit xxxfb_remove(struct device *device) */
+static void __exit xxxfb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drv_data(dev);
+ /* or dev_get_drv_data(device); */
+
+ if (info) {
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info.cmap);
+ /* ... */
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
-static void __exit xxxfb_cleanup(void)
+#if CONFIG_PCI
+/* For PCI drivers */
+static struct pci_driver xxxfb_driver = {
+ .name = "xxxfb",
+ .id_table = xxxfb_devices,
+ .probe = xxxfb_probe,
+ .remove = __devexit_p(xxxfb_remove),
+ .suspend = xxxfb_suspend, /* optional */
+ .resume = xxxfb_resume, /* optional */
+};
+
+static int __init xxxfb_init(void)
{
- /*
- * If your driver supports multiple boards, you should unregister and
- * clean up all instances.
- */
+ /*
+ * For kernel boot options (in 'video=xxxfb:<options>' format)
+ */
+#ifndef MODULE
+ char *option = NULL;
- unregister_framebuffer(info);
- fb_dealloc_cmap(&info.cmap);
- /* ... */
+ if (fb_get_options("xxxfb", &option))
+ return -ENODEV;
+ xxxfb_setup(option);
+#endif
+
+ return pci_register_driver(&xxxfb_driver);
+}
+
+static void __exit xxxfb_exit(void)
+{
+ pci_unregister_driver(&xxxfb_driver);
}
+#else
+#include <linux/platform_device.h>
+/* for platform devices */
+static struct device_driver xxxfb_driver = {
+ .name = "xxxfb",
+ .bus = &platform_bus_type,
+ .probe = xxxfb_probe,
+ .remove = xxxfb_remove,
+ .suspend = xxxfb_suspend, /* optional */
+ .resume = xxxfb_resume, /* optional */
+};
+
+static struct platform_device xxxfb_device = {
+ .name = "xxxfb",
+};
+
+static int __init xxxfb_init(void)
+{
+ int ret;
+ /*
+ * For kernel boot options (in 'video=xxxfb:<options>' format)
+ */
+#ifndef MODULE
+ char *option = NULL;
+
+ if (fb_get_options("xxxfb", &option))
+ return -ENODEV;
+ xxxfb_setup(option);
+#endif
+ ret = driver_register(&xxxfb_driver);
+
+ if (!ret) {
+ ret = platform_device_register(&xxxfb_device);
+ if (ret)
+ driver_unregister(&xxxfb_driver);
+ }
+
+ return ret;
+}
+
+static void __exit xxxfb_exit(void)
+{
+ platform_device_unregister(&xxxfb_device);
+ driver_unregister(&xxxfb_driver);
+}
+#endif
+
+MODULE_LICENSE("GPL");
+module_init(xxxfb_init);
+module_exit(xxxfb_exit);
+
/*
* Setup
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index e0f14df840d9..99921df35474 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -382,7 +382,7 @@ static void sstfb_clear_screen(struct fb_info *info)
static int sstfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int hSyncOff = var->xres + var->right_margin + var->left_margin;
int vSyncOff = var->yres + var->lower_margin + var->upper_margin;
int vBackPorch = var->left_margin, yDim = var->yres;
@@ -542,7 +542,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
*/
static int sstfb_set_par(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
struct pci_dev *sst_dev = par->dev;
unsigned int freq;
@@ -748,13 +748,14 @@ static int sstfb_set_par(struct fb_info *info)
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
+ struct sstfb_par *par = info->par;
u32 col;
f_dddprintk("sstfb_setcolreg\n");
f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
regno, red, green, blue, transp);
- if (regno >= 16)
- return -EINVAL;
+ if (regno > 15)
+ return 0;
red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length);
@@ -765,15 +766,14 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
| (blue << info->var.blue.offset)
| (transp << info->var.transp.offset);
- ((u32 *)info->pseudo_palette)[regno] = col;
+ par->palette[regno] = col;
return 0;
}
-static int sstfb_ioctl(struct inode *inode, struct file *file,
- u_int cmd, u_long arg, struct fb_info *info )
+static int sstfb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *sst_dev = par->dev;
u32 fbiinit0, tmp, val;
u_long p;
@@ -830,7 +830,7 @@ static int sstfb_ioctl(struct inode *inode, struct file *file,
#if 0
static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
@@ -855,7 +855,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
*/
static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u32 stride = info->fix.line_length;
if (!IS_VOODOO2(par))
@@ -925,7 +925,7 @@ static int __devinit sst_get_memsize(struct fb_info *info, __u32 *memsize)
static int __devinit sst_detect_att(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int i, mir, dir;
for (i=0; i<3; i++) {
@@ -950,7 +950,7 @@ static int __devinit sst_detect_att(struct fb_info *info)
static int __devinit sst_detect_ti(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int i, mir, dir;
for (i = 0; i<3; i++) {
@@ -986,7 +986,7 @@ static int __devinit sst_detect_ti(struct fb_info *info)
*/
static int __devinit sst_detect_ics(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
int m_clk0_1, m_clk0_7, m_clk1_b;
int n_clk0_1, n_clk0_7, n_clk1_b;
int i;
@@ -1023,7 +1023,7 @@ static int __devinit sst_detect_ics(struct fb_info *info)
static int sst_set_pll_att_ti(struct fb_info *info,
const struct pll_timing *t, const int clock)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 cr0, cc;
/* enable indexed mode */
@@ -1077,7 +1077,7 @@ static int sst_set_pll_att_ti(struct fb_info *info,
static int sst_set_pll_ics(struct fb_info *info,
const struct pll_timing *t, const int clock)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 pll_ctrl;
sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
@@ -1114,7 +1114,7 @@ static int sst_set_pll_ics(struct fb_info *info,
static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
u8 cr0;
sst_dac_write(DACREG_WMA, 0); /* backdoor */
@@ -1149,7 +1149,7 @@ static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
switch(bpp) {
case 16:
@@ -1308,7 +1308,7 @@ static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
static void __devexit sst_shutdown(struct fb_info *info)
{
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings;
int Fout;
@@ -1394,12 +1394,6 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
struct sst_spec *spec;
int err;
- struct all_info {
- struct fb_info info;
- struct sstfb_par par;
- u32 pseudo_palette[16];
- } *all;
-
/* Enable device in PCI config. */
if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n");
@@ -1407,14 +1401,13 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
}
/* Allocate the fb and par structures. */
- all = kmalloc(sizeof(*all), GFP_KERNEL);
- if (!all)
+ info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
+ if (!info)
return -ENOMEM;
- memset(all, 0, sizeof(*all));
- pci_set_drvdata(pdev, all);
+
+ pci_set_drvdata(pdev, info);
- info = &all->info;
- par = info->par = &all->par;
+ par = info->par;
fix = &info->fix;
par->type = id->driver_data;
@@ -1471,7 +1464,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
info->flags = FBINFO_DEFAULT;
info->fbops = &sstfb_ops;
- info->pseudo_palette = &all->pseudo_palette;
+ info->pseudo_palette = par->palette;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR;
@@ -1527,7 +1520,7 @@ fail_mmio_remap:
fail_fb_mem:
release_mem_region(fix->mmio_start, info->fix.mmio_len);
fail_mmio_mem:
- kfree(info);
+ framebuffer_release(info);
return -ENXIO; /* no voodoo detected */
}
@@ -1537,7 +1530,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
struct fb_info *info;
info = pci_get_drvdata(pdev);
- par = (struct sstfb_par *) info->par;
+ par = info->par;
sst_shutdown(info);
unregister_framebuffer(info);
@@ -1545,7 +1538,7 @@ static void __devexit sstfb_remove(struct pci_dev *pdev)
iounmap(par->mmio_vbase);
release_mem_region(info->fix.smem_start, 0x400000);
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
- kfree(info);
+ framebuffer_release(info);
}
@@ -1613,7 +1606,7 @@ static int sstfb_dump_regs(struct fb_info *info)
const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]);
const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]);
- struct sstfb_par *par = (struct sstfb_par *) info->par;
+ struct sstfb_par *par = info->par;
struct pci_dev *dev = par->dev;
u32 pci_res[pci_s];
u32 sst_res[sst_s];
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index fbb17332afd7..56d71d6e9a72 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -3,7 +3,7 @@
* Low level Frame buffer driver for HP workstations with
* STI (standard text interface) video firmware.
*
- * Copyright (C) 2001-2004 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2005 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*
* Based on:
@@ -73,16 +73,13 @@
#include "sticore.h"
/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
-#ifdef __LP64__
- #define REGION_BASE(fb_info, index) \
- (fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)
-#else
- #define REGION_BASE(fb_info, index) \
- fb_info->sti->glob_cfg->region_ptrs[index]
-#endif
+#define REGION_BASE(fb_info, index) \
+ F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
#define NGLEDEVDEPROM_CRT_REGION 1
+#define NR_PALETTE 256
+
typedef struct {
__s32 video_config_reg;
__s32 misc_video_start;
@@ -112,7 +109,7 @@ struct stifb_info {
ngle_rom_t ngle_rom;
struct sti_struct *sti;
int deviceSpecificConfig;
- u32 pseudo_palette[256];
+ u32 pseudo_palette[16];
};
static int __initdata stifb_bpp_pref[MAX_STI_ROMS];
@@ -352,10 +349,10 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable)
#define IS_888_DEVICE(fb) \
(!(IS_24_DEVICE(fb)))
-#define GET_FIFO_SLOTS(fb, cnt, numslots) \
-{ while (cnt < numslots) \
+#define GET_FIFO_SLOTS(fb, cnt, numslots) \
+{ while (cnt < numslots) \
cnt = READ_WORD(fb, REG_34); \
- cnt -= numslots; \
+ cnt -= numslots; \
}
#define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */
@@ -995,7 +992,7 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
struct stifb_info *fb = (struct stifb_info *) info;
u32 color;
- if (regno >= 256) /* no. of hw registers */
+ if (regno >= NR_PALETTE)
return 1;
red >>= 8;
@@ -1005,8 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
DEBUG_OFF();
START_IMAGE_COLORMAP_ACCESS(fb);
-
- if (fb->info.var.grayscale) {
+
+ if (unlikely(fb->info.var.grayscale)) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
color = ((red * 77) +
(green * 151) +
@@ -1017,17 +1014,17 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
(blue));
}
- if (info->var.bits_per_pixel == 32) {
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- } else {
- ((u32 *)(info->pseudo_palette))[regno] = regno;
+ if (fb->info.fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ struct fb_var_screeninfo *var = &fb->info.var;
+ if (regno < 16)
+ ((u32 *)fb->info.pseudo_palette)[regno] =
+ regno << var->red.offset |
+ regno << var->green.offset |
+ regno << var->blue.offset;
}
WRITE_IMAGE_COLOR(fb, regno, color);
-
+
if (fb->id == S9000_ID_HCRX) {
NgleLutBltCtl lutBltCtl;
@@ -1066,9 +1063,9 @@ stifb_blank(int blank_mode, struct fb_info *info)
case S9000_ID_HCRX:
HYPER_ENABLE_DISABLE_DISPLAY(fb, enable);
break;
- case S9000_ID_A1659A:; /* fall through */
- case S9000_ID_TIMBER:;
- case CRX24_OVERLAY_PLANES:;
+ case S9000_ID_A1659A: /* fall through */
+ case S9000_ID_TIMBER:
+ case CRX24_OVERLAY_PLANES:
default:
ENABLE_DISABLE_DISPLAY(fb, enable);
break;
@@ -1250,12 +1247,10 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
memset(&fb->ngle_rom, 0, sizeof(fb->ngle_rom));
if ((fb->sti->regions_phys[0] & 0xfc000000) ==
(fb->sti->regions_phys[2] & 0xfc000000))
- sti_rom_address = fb->sti->regions_phys[0];
+ sti_rom_address = F_EXTEND(fb->sti->regions_phys[0]);
else
- sti_rom_address = fb->sti->regions_phys[1];
-#ifdef __LP64__
- sti_rom_address |= 0xffffffff00000000;
-#endif
+ sti_rom_address = F_EXTEND(fb->sti->regions_phys[1]);
+
fb->deviceSpecificConfig = gsc_readl(sti_rom_address);
if (IS_24_DEVICE(fb)) {
if (bpp_pref == 8 || bpp_pref == 32)
@@ -1315,7 +1310,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
break;
case 32:
fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
var->blue.offset = 0;
var->green.offset = 8;
@@ -1337,7 +1332,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref)
info->pseudo_palette = &fb->pseudo_palette;
/* This has to been done !!! */
- fb_alloc_cmap(&info->cmap, 256, 0);
+ fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
stifb_init_display(fb);
if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) {
@@ -1488,7 +1483,3 @@ module_exit(stifb_cleanup);
MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
MODULE_DESCRIPTION("Framebuffer driver for HP's NGLE series graphics cards in HP PARISC machines");
MODULE_LICENSE("GPL v2");
-
-MODULE_PARM(bpp, "i");
-MODULE_PARM_DESC(mem, "Bits per pixel (default: 8)");
-
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 2b27b4474001..95b918229d9b 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -33,9 +33,8 @@ static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned,
unsigned, struct fb_info *);
static int tcx_blank(int, struct fb_info *);
-static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *);
-static int tcx_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long, struct fb_info *);
+static int tcx_mmap(struct fb_info *, struct vm_area_struct *);
+static int tcx_ioctl(struct fb_info *, unsigned int, unsigned long);
static int tcx_pan_display(struct fb_var_screeninfo *, struct fb_info *);
/*
@@ -302,7 +301,7 @@ static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = {
{ .size = 0 }
};
-static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma)
+static int tcx_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct tcx_par *par = (struct tcx_par *)info->par;
@@ -312,8 +311,8 @@ static int tcx_mmap(struct fb_info *info, struct file *file, struct vm_area_stru
vma);
}
-static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info)
+static int tcx_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
struct tcx_par *par = (struct tcx_par *) info->par;
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 9d53387e6a66..3e7baf4c9fa8 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -291,7 +291,7 @@ static inline void banshee_make_room(struct tdfx_par *par, int size)
static int banshee_wait_idle(struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int i = 0;
banshee_make_room(par, 1);
@@ -364,7 +364,7 @@ static u32 do_calc_pll(int freq, int* freq_out)
static void do_write_regs(struct fb_info *info, struct banshee_reg* reg)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int i;
banshee_wait_idle(info);
@@ -469,7 +469,7 @@ static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 lpitch;
if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
@@ -558,7 +558,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
static int tdfxfb_set_par(struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 hdispend, hsyncsta, hsyncend, htotal;
u32 hd, hs, he, ht, hbs, hbe;
u32 vd, vs, ve, vt, vbs, vbe;
@@ -780,7 +780,7 @@ static int tdfxfb_set_par(struct fb_info *info)
static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue,unsigned transp,struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 rgbcol;
if (regno >= info->cmap.len || regno > 255) return 1;
@@ -794,11 +794,15 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
break;
/* Truecolor has no hardware color palettes. */
case FB_VISUAL_TRUECOLOR:
- rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) |
- (CNVT_TOHW( green, info->var.green.length) << info->var.green.offset) |
- (CNVT_TOHW( blue, info->var.blue.length) << info->var.blue.offset) |
- (CNVT_TOHW( transp, info->var.transp.length) << info->var.transp.offset);
- ((u32*)(info->pseudo_palette))[regno] = rgbcol;
+ rgbcol = (CNVT_TOHW( red, info->var.red.length) <<
+ info->var.red.offset) |
+ (CNVT_TOHW( green, info->var.green.length) <<
+ info->var.green.offset) |
+ (CNVT_TOHW( blue, info->var.blue.length) <<
+ info->var.blue.offset) |
+ (CNVT_TOHW( transp, info->var.transp.length) <<
+ info->var.transp.offset);
+ par->palette[regno] = rgbcol;
break;
default:
DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
@@ -810,7 +814,7 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static int tdfxfb_blank(int blank, struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 dacmode, state = 0, vgablank = 0;
dacmode = tdfx_inl(par, DACMODE);
@@ -855,7 +859,7 @@ static int tdfxfb_blank(int blank, struct fb_info *info)
static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 addr;
if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
@@ -878,7 +882,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
*/
static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
@@ -894,7 +898,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
tdfx_outl(par, COLORFORE, rect->color);
} else { /* FB_VISUAL_TRUECOLOR */
- tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
+ tdfx_outl(par, COLORFORE, par->palette[rect->color]);
}
tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
@@ -906,7 +910,7 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
*/
static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
@@ -938,7 +942,7 @@ static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area
static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
int size = image->height * ((image->width * image->depth + 7)>>3);
int fifo_free;
int i, stride = info->fix.line_length;
@@ -961,8 +965,10 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
break;
case FB_VISUAL_TRUECOLOR:
default:
- tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[image->fg_color]);
- tdfx_outl(par, COLORBACK, ((u32*)(info->pseudo_palette))[image->bg_color]);
+ tdfx_outl(par, COLORFORE,
+ par->palette[image->fg_color]);
+ tdfx_outl(par, COLORBACK,
+ par->palette[image->bg_color]);
}
#ifdef __BIG_ENDIAN
srcfmt = 0x400000 | BIT(20);
@@ -1007,7 +1013,7 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
#ifdef TDFX_HARDWARE_CURSOR
static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
unsigned long flags;
/*
@@ -1157,18 +1163,17 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
{
struct tdfx_par *default_par;
struct fb_info *info;
- int size, err, lpitch;
+ int err, lpitch;
if ((err = pci_enable_device(pdev))) {
printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
return err;
}
- size = sizeof(struct tdfx_par)+256*sizeof(u32);
+ info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
- info = framebuffer_alloc(size, &pdev->dev);
-
- if (!info) return -ENOMEM;
+ if (!info)
+ return -ENOMEM;
default_par = info->par;
@@ -1248,7 +1253,7 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix;
- info->pseudo_palette = (void *)(default_par + 1);
+ info->pseudo_palette = default_par->palette;
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
#ifdef CONFIG_FB_3DFX_ACCEL
info->flags |= FBINFO_HWACCEL_FILLRECT |
@@ -1307,7 +1312,7 @@ out_err:
}
#ifndef MODULE
-void tdfxfb_setup(char *options)
+static void tdfxfb_setup(char *options)
{
char* this_opt;
@@ -1340,7 +1345,7 @@ void tdfxfb_setup(char *options)
static void __devexit tdfxfb_remove(struct pci_dev *pdev)
{
struct fb_info *info = pci_get_drvdata(pdev);
- struct tdfx_par *par = (struct tdfx_par *) info->par;
+ struct tdfx_par *par = info->par;
unregister_framebuffer(info);
iounmap(par->regbase_virt);
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index ce97ec8eae97..2bdeb4baa952 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -342,19 +342,19 @@ int __init valkyriefb_init(void)
#else /* ppc (!CONFIG_MAC) */
{
struct device_node *dp;
+ struct resource r;
- dp = find_devices("valkyrie");
+ dp = of_find_node_by_name(NULL, "valkyrie");
if (dp == 0)
return 0;
- if (dp->n_addrs != 1) {
- printk(KERN_ERR "expecting 1 address for valkyrie (got %d)\n",
- dp->n_addrs);
+ if (of_address_to_resource(dp, 0, &r)) {
+ printk(KERN_ERR "can't find address for valkyrie\n");
return 0;
}
- frame_buffer_phys = dp->addrs[0].address;
- cmap_regs_phys = dp->addrs[0].address+0x304000;
+ frame_buffer_phys = r.start;
+ cmap_regs_phys = r.start + 0x304000;
flags = _PAGE_WRITETHRU;
}
#endif /* ppc (!CONFIG_MAC) */
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3e58ddc2bc38..8982e540214c 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -57,7 +57,6 @@ static unsigned short *pmi_base = NULL;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static int depth;
-static int vga_compat;
/* --------------------------------------------------------------------- */
@@ -67,15 +66,6 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
#ifdef __i386__
int offset;
- if (!ypan)
- return -EINVAL;
- if (var->xoffset)
- return -EINVAL;
- if (var->yoffset > var->yres_virtual)
- return -EINVAL;
- if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
- return -EINVAL;
-
offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
__asm__ __volatile__(
@@ -90,37 +80,6 @@ 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;
-
- if (blank == FB_BLANK_POWERDOWN) {
- seq = 0x20;
- crtc17 = 0x00;
- err = 0;
- } else {
- seq = 0x00;
- crtc17 = 0x80;
- err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
- }
-
- 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)
{
@@ -205,7 +164,6 @@ 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,
@@ -459,9 +417,8 @@ static int __init vesafb_probe(struct platform_device *dev)
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 (!ypan)
+ info->fbops->fb_pan_display = NULL;
if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
err = -ENOMEM;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index ffa1ad474226..53208cb58396 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -81,7 +81,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
-static int vfb_mmap(struct fb_info *info, struct file *file,
+static int vfb_mmap(struct fb_info *info,
struct vm_area_struct *vma);
static struct fb_ops vfb_ops = {
@@ -368,7 +368,7 @@ static int vfb_pan_display(struct fb_var_screeninfo *var,
* Most drivers don't need their own mmap function
*/
-static int vfb_mmap(struct fb_info *info, struct file *file,
+static int vfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
return -EINVAL;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 226ae8a88482..f3f16fd9f231 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -705,15 +705,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int vga16fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
- return -EINVAL;
-
vga16fb_pan_var(info, var);
-
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
- info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index d9e01daee630..15179ec62339 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -356,10 +356,11 @@ int save_vga(struct vgastate *state)
{
struct regstate *saved;
- saved = kmalloc(sizeof(struct regstate), GFP_KERNEL);
+ saved = kzalloc(sizeof(struct regstate), GFP_KERNEL);
+
if (saved == NULL)
return 1;
- memset (saved, 0, sizeof(struct regstate));
+
state->vidstate = (void *)saved;
if (state->flags & VGA_SAVE_CMAP) {
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 9a1e00dd3e02..4baf61a22327 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -3,7 +3,7 @@ menu "Dallas's 1-wire bus"
config W1
tristate "Dallas's 1-wire support"
---help---
- Dallas's 1-wire bus is usefull to connect slow 1-pin devices
+ Dallas's 1-wire bus is useful to connect slow 1-pin devices
such as iButtons and thermal sensors.
If you want W1 support, you should say Y here.
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index 15fb250451e5..b9146306df49 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -52,7 +52,6 @@ static int ds_send_control_cmd(struct ds_device *, u16, u16);
static struct usb_driver ds_driver = {
- .owner = THIS_MODULE,
.name = "DS9490R",
.probe = ds_probe,
.disconnect = ds_disconnect,
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 14016b1cd948..024206c4a0e4 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -142,12 +142,12 @@ static struct bin_attribute w1_slave_attr_bin_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 int w1_uevent(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,
+ .uevent = w1_uevent,
};
struct device_driver w1_master_driver = {
@@ -361,7 +361,7 @@ void w1_destroy_master_attributes(struct w1_master *master)
}
#ifdef CONFIG_HOTPLUG
-static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
struct w1_master *md = NULL;
struct w1_slave *sl = NULL;
@@ -377,7 +377,7 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
event_owner = "slave";
name = sl->name;
} else {
- dev_dbg(dev, "Unknown hotplug event.\n");
+ dev_dbg(dev, "Unknown event.\n");
return -EINVAL;
}
@@ -386,18 +386,18 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
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);
+ err = add_uevent_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);
+ err = add_uevent_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)
+static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
return 0;
}
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c
index 1a409c2c320c..7aa2d3de6d37 100644
--- a/drivers/zorro/proc.c
+++ b/drivers/zorro/proc.c
@@ -45,7 +45,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence)
}
static ssize_t
-proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
struct inode *ino = file->f_dentry->d_inode;
struct proc_dir_entry *dp = PDE(ino);
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c
index ccba227676f2..fcbee748c592 100644
--- a/drivers/zorro/zorro-driver.c
+++ b/drivers/zorro/zorro-driver.c
@@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv)
/* initialize common driver fields */
drv->driver.name = drv->name;
drv->driver.bus = &zorro_bus_type;
- drv->driver.probe = zorro_device_probe;
/* register with core */
count = driver_register(&drv->driver);
@@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv)
struct bus_type zorro_bus_type = {
.name = "zorro",
- .match = zorro_bus_match
+ .match = zorro_bus_match,
+ .probe = zorro_device_probe,
};
diff --git a/fs/9p/9p.c b/fs/9p/9p.c
index e847f504a47c..1a6d08761f39 100644
--- a/fs/9p/9p.c
+++ b/fs/9p/9p.c
@@ -1,8 +1,9 @@
/*
* linux/fs/9p/9p.c
*
- * This file contains functions 9P2000 functions
+ * This file contains functions to perform synchronous 9P calls
*
+ * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
@@ -33,6 +34,7 @@
#include "debug.h"
#include "v9fs.h"
#include "9p.h"
+#include "conv.h"
#include "mux.h"
/**
@@ -46,16 +48,21 @@
int
v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
- char *version, struct v9fs_fcall **fcall)
+ char *version, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
- msg.id = TVERSION;
- msg.params.tversion.msize = msize;
- msg.params.tversion.version = version;
+ tc = v9fs_create_tversion(msize, version);
- return v9fs_mux_rpc(v9ses, &msg, fcall);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
}
/**
@@ -71,19 +78,45 @@ v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
int
v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
- u32 fid, u32 afid, struct v9fs_fcall **fcall)
+ u32 fid, u32 afid, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall* tc;
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);
+ tc = v9fs_create_tattach(fid, afid, uname, aname);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
+}
+
+static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
+ struct v9fs_fcall *rc, int err)
+{
+ int fid;
+ struct v9fs_session_info *v9ses;
+
+ if (err)
+ return;
+
+ fid = tc->params.tclunk.fid;
+ kfree(tc);
+
+ if (!rc)
+ return;
+
+ dprintk(DEBUG_9P, "tcall id %d rcall id %d\n", tc->id, rc->id);
+ v9ses = a;
+ if (rc->id == RCLUNK)
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+
+ kfree(rc);
}
/**
@@ -95,16 +128,25 @@ v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
*/
int
-v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_fcall **fcall)
+v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc, *rc;
dprintk(DEBUG_9P, "fid %d\n", fid);
- msg.id = TCLUNK;
- msg.params.tclunk.fid = fid;
- return v9fs_mux_rpc(v9ses, &msg, fcall);
+ rc = NULL;
+ tc = v9fs_create_tclunk(fid);
+ if (!IS_ERR(tc))
+ ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
+ else
+ ret = PTR_ERR(tc);
+
+ if (ret)
+ dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);
+
+ v9fs_t_clunk_cb(v9ses, tc, rc, ret);
+ return ret;
}
/**
@@ -114,14 +156,21 @@ v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid,
*
*/
-int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
+int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
+
+ dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
+
+ tc = v9fs_create_tflush(oldtag);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
- dprintk(DEBUG_9P, "oldtag %d\n", tag);
- msg.id = TFLUSH;
- msg.params.tflush.oldtag = tag;
- return v9fs_mux_rpc(v9ses, &msg, NULL);
+ return ret;
}
/**
@@ -133,17 +182,22 @@ int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 tag)
*/
int
-v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
+v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
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);
+ ret = -ENOMEM;
+ tc = v9fs_create_tstat(fid);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
}
/**
@@ -157,16 +211,21 @@ v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **fcall)
int
v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_stat *stat, struct v9fs_fcall **fcall)
+ struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
+
+ dprintk(DEBUG_9P, "fid %d\n", fid);
- 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;
+ tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
- return v9fs_mux_rpc(v9ses, &msg, fcall);
+ return ret;
}
/**
@@ -183,23 +242,27 @@ v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
int
v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
- char *name, struct v9fs_fcall **fcall)
+ char *name, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
+ int nwname;
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);
+
+ if (name)
+ nwname = 1;
+ else
+ nwname = 0;
+
+ tc = v9fs_create_twalk(fid, newfid, nwname, &name);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
}
/**
@@ -214,19 +277,21 @@ v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
int
v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
- struct v9fs_fcall **fcall)
+ struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
- long errorno = -1;
+ int ret;
+ struct v9fs_fcall *tc;
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);
+ tc = v9fs_create_topen(fid, mode);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
- return errorno;
+ return ret;
}
/**
@@ -239,14 +304,21 @@ v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
int
v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_fcall **fcall)
+ struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
dprintk(DEBUG_9P, "fid %d\n", fid);
- msg.id = TREMOVE;
- msg.params.tremove.fid = fid;
- return v9fs_mux_rpc(v9ses, &msg, fcall);
+
+ tc = v9fs_create_tremove(fid);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
}
/**
@@ -262,20 +334,22 @@ v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
int
v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
- u32 perm, u8 mode, struct v9fs_fcall **fcall)
+ u32 perm, u8 mode, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
+ int ret;
+ struct v9fs_fcall *tc;
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;
+ tc = v9fs_create_tcreate(fid, name, perm, mode);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
- return v9fs_mux_rpc(v9ses, &msg, fcall);
+ return ret;
}
/**
@@ -290,31 +364,29 @@ v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
int
v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
- u32 count, struct v9fs_fcall **fcall)
+ u32 count, struct v9fs_fcall **rcp)
{
- 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;
+ int ret;
+ struct v9fs_fcall *tc, *rc;
+
+ dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
+ (long long unsigned) offset, count);
+
+ tc = v9fs_create_tread(fid, offset, count);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
+ if (!ret)
+ ret = rc->params.rread.count;
+ if (rcp)
+ *rcp = rc;
+ else
+ kfree(rc);
+
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
+
+ return ret;
}
/**
@@ -328,32 +400,30 @@ v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
*/
int
-v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid,
- u64 offset, u32 count, void *data, struct v9fs_fcall **fcall)
+v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
+ const char __user *data, struct v9fs_fcall **rcp)
{
- struct v9fs_fcall msg;
- struct v9fs_fcall *rc = NULL;
- long errorno = -1;
+ int ret;
+ struct v9fs_fcall *tc, *rc;
- dprintk(DEBUG_9P, "fid %d offset 0x%llx count 0x%x\n", fid,
- (unsigned long long)offset, count);
- dump_data(data, count);
+ dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
+ (long long unsigned) offset, count);
- msg.id = TWRITE;
- msg.params.twrite.fid = fid;
- msg.params.twrite.offset = offset;
- msg.params.twrite.count = count;
- msg.params.twrite.data = data;
+ tc = v9fs_create_twrite(fid, offset, count, data);
+ if (!IS_ERR(tc)) {
+ ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
- errorno = v9fs_mux_rpc(v9ses, &msg, &rc);
+ if (!ret)
+ ret = rc->params.rwrite.count;
+ if (rcp)
+ *rcp = rc;
+ else
+ kfree(rc);
- if (!errorno)
- errorno = rc->params.rwrite.count;
+ kfree(tc);
+ } else
+ ret = PTR_ERR(tc);
- if (fcall)
- *fcall = rc;
- else
- kfree(rc);
-
- return errorno;
+ return ret;
}
+
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
index f55424216be2..0cd374d94717 100644
--- a/fs/9p/9p.h
+++ b/fs/9p/9p.h
@@ -3,6 +3,7 @@
*
* 9P protocol definitions.
*
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
@@ -100,9 +101,18 @@ enum {
V9FS_QTFILE = 0x00,
};
+#define V9FS_NOTAG (u16)(~0)
+#define V9FS_NOFID (u32)(~0)
+#define V9FS_MAXWELEM 16
+
/* ample room for Twrite/Rread header (iounit) */
#define V9FS_IOHDRSZ 24
+struct v9fs_str {
+ u16 len;
+ char *str;
+};
+
/* qids are the unique ID for a file (like an inode */
struct v9fs_qid {
u8 type;
@@ -120,6 +130,29 @@ struct v9fs_stat {
u32 atime;
u32 mtime;
u64 length;
+ struct v9fs_str name;
+ struct v9fs_str uid;
+ struct v9fs_str gid;
+ struct v9fs_str muid;
+ struct v9fs_str extension; /* 9p2000.u extensions */
+ u32 n_uid; /* 9p2000.u extensions */
+ u32 n_gid; /* 9p2000.u extensions */
+ u32 n_muid; /* 9p2000.u extensions */
+};
+
+/* file metadata (stat) structure used to create Twstat message
+ The is similar to v9fs_stat, but the strings don't point to
+ the same memory block and should be freed separately
+*/
+struct v9fs_wstat {
+ u16 size;
+ u16 type;
+ u32 dev;
+ struct v9fs_qid qid;
+ u32 mode;
+ u32 atime;
+ u32 mtime;
+ u64 length;
char *name;
char *uid;
char *gid;
@@ -128,25 +161,24 @@ struct v9fs_stat {
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 v9fs_str version;
};
struct Rversion {
u32 msize;
- char *version;
+ struct v9fs_str version;
};
struct Tauth {
u32 afid;
- char *uname;
- char *aname;
+ struct v9fs_str uname;
+ struct v9fs_str aname;
};
struct Rauth {
@@ -154,12 +186,12 @@ struct Rauth {
};
struct Rerror {
- char *error;
+ struct v9fs_str error;
u32 errno; /* 9p2000.u extension */
};
struct Tflush {
- u32 oldtag;
+ u16 oldtag;
};
struct Rflush {
@@ -168,8 +200,8 @@ struct Rflush {
struct Tattach {
u32 fid;
u32 afid;
- char *uname;
- char *aname;
+ struct v9fs_str uname;
+ struct v9fs_str aname;
};
struct Rattach {
@@ -179,13 +211,13 @@ struct Rattach {
struct Twalk {
u32 fid;
u32 newfid;
- u32 nwname;
- char **wnames;
+ u16 nwname;
+ struct v9fs_str wnames[16];
};
struct Rwalk {
- u32 nwqid;
- struct v9fs_qid *wqids;
+ u16 nwqid;
+ struct v9fs_qid wqids[16];
};
struct Topen {
@@ -200,7 +232,7 @@ struct Ropen {
struct Tcreate {
u32 fid;
- char *name;
+ struct v9fs_str name;
u32 perm;
u8 mode;
};
@@ -251,12 +283,12 @@ struct Tstat {
};
struct Rstat {
- struct v9fs_stat *stat;
+ struct v9fs_stat stat;
};
struct Twstat {
u32 fid;
- struct v9fs_stat *stat;
+ struct v9fs_stat stat;
};
struct Rwstat {
@@ -271,6 +303,7 @@ struct v9fs_fcall {
u32 size;
u8 id;
u16 tag;
+ void *sdata;
union {
struct Tversion tversion;
@@ -303,7 +336,9 @@ struct v9fs_fcall {
} params;
};
-#define FCALL_ERROR(fcall) (fcall ? fcall->params.rerror.error : "")
+#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \
+ fcall?fcall->params.rerror.error.len:0, \
+ fcall?fcall->params.rerror.error.str:"");
int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
char *version, struct v9fs_fcall **rcall);
@@ -311,8 +346,7 @@ int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
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_clunk(struct v9fs_session_info *v9ses, u32 fid);
int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag);
@@ -320,7 +354,7 @@ 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);
+ struct v9fs_wstat *wstat, struct v9fs_fcall **rcall);
int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
char *name, struct v9fs_fcall **rcall);
@@ -338,4 +372,5 @@ 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);
+ u32 count, const char __user * data,
+ struct v9fs_fcall **rcall);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index e4e4ffe5a7dc..2f4ce43f7b6c 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,17 +1,18 @@
obj-$(CONFIG_9P_FS) := 9p2000.o
9p2000-objs := \
+ trans_fd.o \
+ trans_sock.o \
+ mux.o \
+ 9p.o \
+ conv.o \
vfs_super.o \
vfs_inode.o \
+ vfs_addr.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
index 18121af99d3e..32a9f99154e2 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -30,7 +30,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/idr.h>
-
+#include <asm/uaccess.h>
#include "debug.h"
#include "v9fs.h"
#include "9p.h"
@@ -56,20 +56,23 @@ static inline int buf_check_overflow(struct cbuf *buf)
return buf->p > buf->ep;
}
-static inline int buf_check_size(struct cbuf *buf, int len)
+static int buf_check_size(struct cbuf *buf, int len)
{
- if (buf->p+len > buf->ep) {
+ if (buf->p + len > buf->ep) {
if (buf->p < buf->ep) {
- eprintk(KERN_ERR, "buffer overflow\n");
+ eprintk(KERN_ERR, "buffer overflow: want %d has %d\n",
+ len, (int)(buf->ep - buf->p));
+ dump_stack();
buf->p = buf->ep + 1;
- return 0;
}
+
+ return 0;
}
return 1;
}
-static inline void *buf_alloc(struct cbuf *buf, int len)
+static void *buf_alloc(struct cbuf *buf, int len)
{
void *ret = NULL;
@@ -81,7 +84,7 @@ static inline void *buf_alloc(struct cbuf *buf, int len)
return ret;
}
-static inline void buf_put_int8(struct cbuf *buf, u8 val)
+static void buf_put_int8(struct cbuf *buf, u8 val)
{
if (buf_check_size(buf, 1)) {
buf->p[0] = val;
@@ -89,7 +92,7 @@ static inline void buf_put_int8(struct cbuf *buf, u8 val)
}
}
-static inline void buf_put_int16(struct cbuf *buf, u16 val)
+static void buf_put_int16(struct cbuf *buf, u16 val)
{
if (buf_check_size(buf, 2)) {
*(__le16 *) buf->p = cpu_to_le16(val);
@@ -97,7 +100,7 @@ static inline void buf_put_int16(struct cbuf *buf, u16 val)
}
}
-static inline void buf_put_int32(struct cbuf *buf, u32 val)
+static void buf_put_int32(struct cbuf *buf, u32 val)
{
if (buf_check_size(buf, 4)) {
*(__le32 *)buf->p = cpu_to_le32(val);
@@ -105,7 +108,7 @@ static inline void buf_put_int32(struct cbuf *buf, u32 val)
}
}
-static inline void buf_put_int64(struct cbuf *buf, u64 val)
+static void buf_put_int64(struct cbuf *buf, u64 val)
{
if (buf_check_size(buf, 8)) {
*(__le64 *)buf->p = cpu_to_le64(val);
@@ -113,7 +116,7 @@ static inline void buf_put_int64(struct cbuf *buf, u64 val)
}
}
-static inline void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
+static void buf_put_stringn(struct cbuf *buf, const char *s, u16 slen)
{
if (buf_check_size(buf, slen + 2)) {
buf_put_int16(buf, slen);
@@ -127,15 +130,7 @@ 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)
-{
- if (buf_check_size(buf, datalen)) {
- memcpy(buf->p, data, datalen);
- buf->p += datalen;
- }
-}
-
-static inline u8 buf_get_int8(struct cbuf *buf)
+static u8 buf_get_int8(struct cbuf *buf)
{
u8 ret = 0;
@@ -147,7 +142,7 @@ static inline u8 buf_get_int8(struct cbuf *buf)
return ret;
}
-static inline u16 buf_get_int16(struct cbuf *buf)
+static u16 buf_get_int16(struct cbuf *buf)
{
u16 ret = 0;
@@ -159,7 +154,7 @@ static inline u16 buf_get_int16(struct cbuf *buf)
return ret;
}
-static inline u32 buf_get_int32(struct cbuf *buf)
+static u32 buf_get_int32(struct cbuf *buf)
{
u32 ret = 0;
@@ -171,7 +166,7 @@ static inline u32 buf_get_int32(struct cbuf *buf)
return ret;
}
-static inline u64 buf_get_int64(struct cbuf *buf)
+static u64 buf_get_int64(struct cbuf *buf)
{
u64 ret = 0;
@@ -183,86 +178,37 @@ static inline u64 buf_get_int64(struct cbuf *buf)
return ret;
}
-static inline int
-buf_get_string(struct cbuf *buf, char *data, unsigned int datalen)
-{
- u16 len = 0;
-
- len = buf_get_int16(buf);
- if (!buf_check_overflow(buf) && buf_check_size(buf, len) && len+1>datalen) {
- memcpy(data, buf->p, len);
- data[len] = 0;
- buf->p += len;
- len++;
- }
-
- return len;
-}
-
-static inline char *buf_get_stringb(struct cbuf *buf, struct cbuf *sbuf)
-{
- char *ret;
- u16 len;
-
- ret = NULL;
- len = buf_get_int16(buf);
-
- if (!buf_check_overflow(buf) && buf_check_size(buf, len) &&
- buf_check_size(sbuf, len+1)) {
-
- memcpy(sbuf->p, buf->p, len);
- sbuf->p[len] = 0;
- ret = sbuf->p;
- buf->p += len;
- sbuf->p += len + 1;
- }
-
- return ret;
-}
-
-static inline int buf_get_data(struct cbuf *buf, void *data, int datalen)
+static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
{
- int ret = 0;
-
- if (buf_check_size(buf, datalen)) {
- memcpy(data, buf->p, datalen);
- buf->p += datalen;
- ret = datalen;
+ vstr->len = buf_get_int16(buf);
+ if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
+ vstr->str = buf->p;
+ buf->p += vstr->len;
+ } else {
+ vstr->len = 0;
+ vstr->str = NULL;
}
-
- return ret;
}
-static inline void *buf_get_datab(struct cbuf *buf, struct cbuf *dbuf,
- int datalen)
+static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
{
- char *ret = NULL;
- int n = 0;
-
- if (buf_check_size(dbuf, datalen)) {
- n = buf_get_data(buf, dbuf->p, datalen);
- if (n > 0) {
- ret = dbuf->p;
- dbuf->p += n;
- }
- }
-
- return ret;
+ qid->type = buf_get_int8(bufp);
+ qid->version = buf_get_int32(bufp);
+ qid->path = buf_get_int64(bufp);
}
/**
- * v9fs_size_stat - calculate the size of a variable length stat struct
- * @v9ses: session information
+ * v9fs_size_wstat - calculate the size of a variable length stat struct
* @stat: metadata (stat) structure
+ * @extended: non-zero if 9P2000.u
*
*/
-static int v9fs_size_stat(struct v9fs_session_info *v9ses,
- struct v9fs_stat *stat)
+static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
{
int size = 0;
- if (stat == NULL) {
+ if (wstat == NULL) {
eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
return 0;
}
@@ -279,82 +225,38 @@ static int v9fs_size_stat(struct v9fs_session_info *v9ses,
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 (wstat->name)
+ size += strlen(wstat->name);
+ if (wstat->uid)
+ size += strlen(wstat->uid);
+ if (wstat->gid)
+ size += strlen(wstat->gid);
+ if (wstat->muid)
+ size += strlen(wstat->muid);
- if (v9ses->extended) {
+ if (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);
+ if (wstat->extension)
+ size += strlen(wstat->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
+ * buf_get_stat - safely decode a recieved metadata (stat) structure
* @bufp: buffer to deserialize
* @stat: metadata (stat) structure
- * @dbufp: buffer to deserialize variable strings into
+ * @extended: non-zero if 9P2000.u
*
*/
-static inline int
-deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *bufp,
- struct v9fs_stat *stat, struct cbuf *dbufp)
+static void
+buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
{
-
stat->size = buf_get_int16(bufp);
stat->type = buf_get_int16(bufp);
stat->dev = buf_get_int32(bufp);
@@ -365,282 +267,82 @@ deserialize_stat(struct v9fs_session_info *v9ses, struct cbuf *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);
+ buf_get_str(bufp, &stat->name);
+ buf_get_str(bufp, &stat->uid);
+ buf_get_str(bufp, &stat->gid);
+ buf_get_str(bufp, &stat->muid);
- if (v9ses->extended) {
- stat->extension = buf_get_stringb(bufp, dbufp);
+ if (extended) {
+ buf_get_str(bufp, &stat->extension);
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
+ * @extended: non-zero if 9P2000.u
*
+ * Note: stat will point to the buf region.
*/
int
-v9fs_deserialize_stat(struct v9fs_session_info *v9ses, void *buf,
- u32 buflen, struct v9fs_stat *stat, u32 statlen)
+v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
+ int extended)
{
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- struct cbuf dbuffer;
- struct cbuf *dbufp = &dbuffer;
+ unsigned char *p;
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;
- }
+ p = bufp->p;
+ buf_get_stat(bufp, stat, extended);
if (buf_check_overflow(bufp))
- return -EIO;
-
- return fcall->size;
+ return 0;
+ else
+ return bufp->p - p;
}
/**
* 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
+ * @extended: non-zero if 9P2000.u
*
*/
int
-v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
- void *buf, u32 buflen, struct v9fs_fcall *rcall,
- int rcalllen)
+v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
+ int extended)
{
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->size = buf_get_int32(bufp);
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);
+ buf_get_str(bufp, &rcall->params.rversion.version);
break;
case RFLUSH:
break;
@@ -651,34 +353,27 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
break;
case RWALK:
rcall->params.rwalk.nwqid = buf_get_int16(bufp);
- rcall->params.rwalk.wqids = buf_alloc(dbufp,
- 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);
- }
+ if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) {
+ eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n",
+ V9FS_MAXWELEM, rcall->params.rwalk.nwqid);
+ return -EPROTO;
+ }
+
+ for (i = 0; i < rcall->params.rwalk.nwqid; i++)
+ buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
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);
+ buf_get_qid(bufp, &rcall->params.ropen.qid);
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);
+ buf_get_qid(bufp, &rcall->params.rcreate.qid);
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);
+ rcall->params.rread.data = bufp->p;
+ buf_check_size(bufp, rcall->params.rread.count);
break;
case RWRITE:
rcall->params.rwrite.count = buf_get_int32(bufp);
@@ -689,20 +384,443 @@ v9fs_deserialize_fcall(struct v9fs_session_info *v9ses, u32 msgsize,
break;
case RSTAT:
buf_get_int16(bufp);
- rcall->params.rstat.stat =
- deserialize_statb(v9ses, bufp, dbufp);
+ buf_get_stat(bufp, &rcall->params.rstat.stat, extended);
break;
case RWSTAT:
break;
case RERROR:
- rcall->params.rerror.error = buf_get_stringb(bufp, dbufp);
- if (v9ses->extended)
+ buf_get_str(bufp, &rcall->params.rerror.error);
+ if (extended)
rcall->params.rerror.errno = buf_get_int16(bufp);
break;
}
- if (buf_check_overflow(bufp) || buf_check_overflow(dbufp))
+ if (buf_check_overflow(bufp)) {
+ dprintk(DEBUG_ERROR, "buffer overflow\n");
return -EIO;
+ }
+
+ return bufp->p - bufp->sp;
+}
+
+static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p)
+{
+ *p = val;
+ buf_put_int8(bufp, val);
+}
+
+static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p)
+{
+ *p = val;
+ buf_put_int16(bufp, val);
+}
+
+static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p)
+{
+ *p = val;
+ buf_put_int32(bufp, val);
+}
+
+static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
+{
+ *p = val;
+ buf_put_int64(bufp, val);
+}
+
+static void
+v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
+{
+ if (data) {
+ str->len = strlen(data);
+ str->str = bufp->p;
+ } else {
+ str->len = 0;
+ str->str = NULL;
+ }
+
+ buf_put_stringn(bufp, data, str->len);
+}
+
+static int
+v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
+ unsigned char **pdata)
+{
+ *pdata = buf_alloc(bufp, count);
+ return copy_from_user(*pdata, data, count);
+}
+
+static void
+v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat,
+ struct v9fs_stat *stat, int statsz, int extended)
+{
+ v9fs_put_int16(bufp, statsz, &stat->size);
+ v9fs_put_int16(bufp, wstat->type, &stat->type);
+ v9fs_put_int32(bufp, wstat->dev, &stat->dev);
+ v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type);
+ v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version);
+ v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path);
+ v9fs_put_int32(bufp, wstat->mode, &stat->mode);
+ v9fs_put_int32(bufp, wstat->atime, &stat->atime);
+ v9fs_put_int32(bufp, wstat->mtime, &stat->mtime);
+ v9fs_put_int64(bufp, wstat->length, &stat->length);
+
+ v9fs_put_str(bufp, wstat->name, &stat->name);
+ v9fs_put_str(bufp, wstat->uid, &stat->uid);
+ v9fs_put_str(bufp, wstat->gid, &stat->gid);
+ v9fs_put_str(bufp, wstat->muid, &stat->muid);
+
+ if (extended) {
+ v9fs_put_str(bufp, wstat->extension, &stat->extension);
+ v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid);
+ v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid);
+ v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid);
+ }
+}
+
+static struct v9fs_fcall *
+v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
+{
+ struct v9fs_fcall *fc;
+
+ size += 4 + 1 + 2; /* size[4] id[1] tag[2] */
+ fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL);
+ if (!fc)
+ return ERR_PTR(-ENOMEM);
+
+ fc->sdata = (char *)fc + sizeof(*fc);
+
+ buf_init(bufp, (char *)fc->sdata, size);
+ v9fs_put_int32(bufp, size, &fc->size);
+ v9fs_put_int8(bufp, id, &fc->id);
+ v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag);
+
+ return fc;
+}
+
+void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
+{
+ fc->tag = tag;
+ *(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
+}
+
+struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 2 + strlen(version); /* msize[4] version[s] */
+ fc = v9fs_create_common(bufp, size, TVERSION);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, msize, &fc->params.tversion.msize);
+ v9fs_put_str(bufp, version, &fc->params.tversion.version);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */
+ fc = v9fs_create_common(bufp, size, TAUTH);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, afid, &fc->params.tauth.afid);
+ v9fs_put_str(bufp, uname, &fc->params.tauth.uname);
+ v9fs_put_str(bufp, aname, &fc->params.tauth.aname);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *
+v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */
+ fc = v9fs_create_common(bufp, size, TATTACH);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tattach.fid);
+ v9fs_put_int32(bufp, afid, &fc->params.tattach.afid);
+ v9fs_put_str(bufp, uname, &fc->params.tattach.uname);
+ v9fs_put_str(bufp, aname, &fc->params.tattach.aname);
+
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tflush(u16 oldtag)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 2; /* oldtag[2] */
+ fc = v9fs_create_common(bufp, size, TFLUSH);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
+ char **wnames)
+{
+ int i, size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ if (nwname > V9FS_MAXWELEM) {
+ dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM);
+ return NULL;
+ }
+
+ size = 4 + 4 + 2; /* fid[4] newfid[4] nwname[2] ... */
+ for (i = 0; i < nwname; i++) {
+ size += 2 + strlen(wnames[i]); /* wname[s] */
+ }
+
+ fc = v9fs_create_common(bufp, size, TWALK);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.twalk.fid);
+ v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid);
+ v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname);
+ for (i = 0; i < nwname; i++) {
+ v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
+ }
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
- return rcall->size;
+struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 1; /* fid[4] mode[1] */
+ fc = v9fs_create_common(bufp, size, TOPEN);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.topen.fid);
+ v9fs_put_int8(bufp, mode, &fc->params.topen.mode);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */
+ fc = v9fs_create_common(bufp, size, TCREATE);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid);
+ v9fs_put_str(bufp, name, &fc->params.tcreate.name);
+ v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
+ v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */
+ fc = v9fs_create_common(bufp, size, TREAD);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tread.fid);
+ v9fs_put_int64(bufp, offset, &fc->params.tread.offset);
+ v9fs_put_int32(bufp, count, &fc->params.tread.count);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
+ const char __user * data)
+{
+ int size, err;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */
+ fc = v9fs_create_common(bufp, size, TWRITE);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.twrite.fid);
+ v9fs_put_int64(bufp, offset, &fc->params.twrite.offset);
+ v9fs_put_int32(bufp, count, &fc->params.twrite.count);
+ err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data);
+ if (err) {
+ kfree(fc);
+ fc = ERR_PTR(err);
+ }
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4; /* fid[4] */
+ fc = v9fs_create_common(bufp, size, TCLUNK);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tremove(u32 fid)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4; /* fid[4] */
+ fc = v9fs_create_common(bufp, size, TREMOVE);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_tstat(u32 fid)
+{
+ int size;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ size = 4; /* fid[4] */
+ fc = v9fs_create_common(bufp, size, TSTAT);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
+}
+
+struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
+ int extended)
+{
+ int size, statsz;
+ struct v9fs_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ statsz = v9fs_size_wstat(wstat, extended);
+ size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */
+ fc = v9fs_create_common(bufp, size, TWSTAT);
+ if (IS_ERR(fc))
+ goto error;
+
+ v9fs_put_int32(bufp, fid, &fc->params.twstat.fid);
+ buf_put_int16(bufp, statsz + 2);
+ v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+ error:
+ return fc;
}
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
index ee849613c61a..26a736e4a2e7 100644
--- a/fs/9p/conv.h
+++ b/fs/9p/conv.h
@@ -1,8 +1,9 @@
/*
* linux/fs/9p/conv.h
*
- * 9P protocol conversion definitions
+ * 9P protocol conversion definitions.
*
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*
@@ -24,13 +25,27 @@
*
*/
-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);
+int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
+ int extended);
+int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
+ int extended);
-/* this one is actually in error.c right now */
-int v9fs_errstr2errno(char *errstr);
+void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag);
+
+struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version);
+struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname);
+struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname,
+ char *aname);
+struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
+struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
+ char **wnames);
+struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
+struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode);
+struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
+struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
+ const char __user *data);
+struct v9fs_fcall *v9fs_create_tclunk(u32 fid);
+struct v9fs_fcall *v9fs_create_tremove(u32 fid);
+struct v9fs_fcall *v9fs_create_tstat(u32 fid);
+struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
+ int extended);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
index 4445f06919d9..fe551032788b 100644
--- a/fs/9p/debug.h
+++ b/fs/9p/debug.h
@@ -51,16 +51,23 @@ do { \
#if DEBUG_DUMP_PKT
static inline void dump_data(const unsigned char *data, unsigned int datalen)
{
- int i, j;
- int len = datalen;
+ int i, n;
+ char buf[5*8];
- 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 " ");
+ n = 0;
+ i = 0;
+ while (i < datalen) {
+ n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]);
+ if (i%4 == 0)
+ n += snprintf(buf+n, sizeof(buf)-n, " ");
+
+ if (i%16 == 0) {
+ dprintk(DEBUG_ERROR, "%s\n", buf);
+ n = 0;
+ }
}
- printk(KERN_DEBUG "\n");
+
+ dprintk(DEBUG_ERROR, "%s\n", buf);
}
#else /* DEBUG_DUMP_PKT */
static inline void dump_data(const unsigned char *data, unsigned int datalen)
diff --git a/fs/9p/error.c b/fs/9p/error.c
index 834cb179e388..e4b6f8f38b6f 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -33,7 +33,6 @@
#include <linux/list.h>
#include <linux/jhash.h>
-#include <linux/string.h>
#include "debug.h"
#include "error.h"
@@ -55,7 +54,8 @@ int v9fs_error_init(void)
/* load initial error map into hash table */
for (c = errmap; c->name != NULL; c++) {
- bucket = jhash(c->name, strlen(c->name), 0) % ERRHASHSZ;
+ c->namelen = strlen(c->name);
+ bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
INIT_HLIST_NODE(&c->list);
hlist_add_head(&c->list, &hash_errmap[bucket]);
}
@@ -69,15 +69,15 @@ int v9fs_error_init(void)
*
*/
-int v9fs_errstr2errno(char *errstr)
+int v9fs_errstr2errno(char *errstr, int len)
{
int errno = 0;
struct hlist_node *p = NULL;
struct errormap *c = NULL;
- int bucket = jhash(errstr, strlen(errstr), 0) % ERRHASHSZ;
+ int bucket = jhash(errstr, len, 0) % ERRHASHSZ;
hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
- if (!strcmp(c->name, errstr)) {
+ if (c->namelen==len && !memcmp(c->name, errstr, len)) {
errno = c->val;
break;
}
diff --git a/fs/9p/error.h b/fs/9p/error.h
index 78f89acf7c9a..a9794e85fe51 100644
--- a/fs/9p/error.h
+++ b/fs/9p/error.h
@@ -36,6 +36,7 @@ struct errormap {
char *name;
int val;
+ int namelen;
struct hlist_node list;
};
@@ -175,4 +176,3 @@ static struct errormap errmap[] = {
};
extern int v9fs_error_init(void);
-extern int v9fs_errstr2errno(char *errstr);
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index d95f8626d170..eda449778fa5 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -31,9 +31,6 @@
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
-#include "transport.h"
-#include "mux.h"
-#include "conv.h"
#include "fid.h"
/**
@@ -164,7 +161,7 @@ static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
return v9fs_fid_create(dentry, v9ses, fidnum, 0);
clunk_fid:
- v9fs_t_clunk(v9ses, fidnum, NULL);
+ v9fs_t_clunk(v9ses, fidnum);
return ERR_PTR(err);
}
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index 8835b576f744..945cb368d451 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -4,7 +4,7 @@
* Protocol Multiplexer
*
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004-2005 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
@@ -28,448 +28,943 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/fs.h>
+#include <linux/poll.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 "transport.h"
#include "mux.h"
+#define ERREQFLUSH 1
+#define SCHED_TIMEOUT 10
+#define MAXPOLLWADDR 2
+
+enum {
+ Rworksched = 1, /* read work scheduled or running */
+ Rpending = 2, /* can read */
+ Wworksched = 4, /* write work scheduled or running */
+ Wpending = 8, /* can write */
+};
+
+struct v9fs_mux_poll_task;
+
+struct v9fs_req {
+ int tag;
+ struct v9fs_fcall *tcall;
+ struct v9fs_fcall *rcall;
+ int err;
+ v9fs_mux_req_callback cb;
+ void *cba;
+ struct list_head req_list;
+};
+
+struct v9fs_mux_data {
+ spinlock_t lock;
+ struct list_head mux_list;
+ struct v9fs_mux_poll_task *poll_task;
+ int msize;
+ unsigned char *extended;
+ struct v9fs_transport *trans;
+ struct v9fs_idpool tidpool;
+ int err;
+ wait_queue_head_t equeue;
+ struct list_head req_list;
+ struct list_head unsent_req_list;
+ struct v9fs_fcall *rcall;
+ int rpos;
+ char *rbuf;
+ int wpos;
+ int wsize;
+ char *wbuf;
+ wait_queue_t poll_wait[MAXPOLLWADDR];
+ wait_queue_head_t *poll_waddr[MAXPOLLWADDR];
+ poll_table pt;
+ struct work_struct rq;
+ struct work_struct wq;
+ unsigned long wsched;
+};
+
+struct v9fs_mux_poll_task {
+ struct task_struct *task;
+ struct list_head mux_list;
+ int muxnum;
+};
+
+struct v9fs_mux_rpc {
+ struct v9fs_mux_data *m;
+ struct v9fs_req *req;
+ int err;
+ struct v9fs_fcall *rcall;
+ wait_queue_head_t wqueue;
+};
+
+static int v9fs_poll_proc(void *);
+static void v9fs_read_work(void *);
+static void v9fs_write_work(void *);
+static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
+ poll_table * p);
+static u16 v9fs_mux_get_tag(struct v9fs_mux_data *);
+static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16);
+
+static DECLARE_MUTEX(v9fs_mux_task_lock);
+static struct workqueue_struct *v9fs_mux_wq;
+
+static int v9fs_mux_num;
+static int v9fs_mux_poll_task_num;
+static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100];
+
+int v9fs_mux_global_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++)
+ v9fs_mux_poll_tasks[i].task = NULL;
+
+ v9fs_mux_wq = create_workqueue("v9fs");
+ if (!v9fs_mux_wq)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void v9fs_mux_global_exit(void)
+{
+ destroy_workqueue(v9fs_mux_wq);
+}
+
/**
- * dprintcond - print condition of session info
- * @v9ses: session info structure
- * @req: RPC request structure
+ * v9fs_mux_calc_poll_procs - calculates the number of polling procs
+ * based on the number of mounted v9fs filesystems.
*
+ * The current implementation returns sqrt of the number of mounts.
*/
+inline int v9fs_mux_calc_poll_procs(int muxnum)
+{
+ int n;
+
+ if (v9fs_mux_poll_task_num)
+ n = muxnum / v9fs_mux_poll_task_num +
+ (muxnum % v9fs_mux_poll_task_num ? 1 : 0);
+ else
+ n = 1;
+
+ if (n > ARRAY_SIZE(v9fs_mux_poll_tasks))
+ n = ARRAY_SIZE(v9fs_mux_poll_tasks);
+
+ return n;
+}
-static inline int
-dprintcond(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
{
- dprintk(DEBUG_MUX, "condition: %d, %p\n", v9ses->transport->status,
- req->rcall);
+ int i, n;
+ struct v9fs_mux_poll_task *vpt, *vptlast;
+ struct task_struct *pproc;
+
+ dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num,
+ v9fs_mux_poll_task_num);
+ up(&v9fs_mux_task_lock);
+
+ n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1);
+ if (n > v9fs_mux_poll_task_num) {
+ for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
+ if (v9fs_mux_poll_tasks[i].task == NULL) {
+ vpt = &v9fs_mux_poll_tasks[i];
+ dprintk(DEBUG_MUX, "create proc %p\n", vpt);
+ pproc = kthread_create(v9fs_poll_proc, vpt,
+ "v9fs-poll");
+
+ if (!IS_ERR(pproc)) {
+ vpt->task = pproc;
+ INIT_LIST_HEAD(&vpt->mux_list);
+ vpt->muxnum = 0;
+ v9fs_mux_poll_task_num++;
+ wake_up_process(vpt->task);
+ }
+ break;
+ }
+ }
+
+ if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks))
+ dprintk(DEBUG_ERROR, "warning: no free poll slots\n");
+ }
+
+ n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num +
+ ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0);
+
+ vptlast = NULL;
+ for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
+ vpt = &v9fs_mux_poll_tasks[i];
+ if (vpt->task != NULL) {
+ vptlast = vpt;
+ if (vpt->muxnum < n) {
+ dprintk(DEBUG_MUX, "put in proc %d\n", i);
+ list_add(&m->mux_list, &vpt->mux_list);
+ vpt->muxnum++;
+ m->poll_task = vpt;
+ memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
+ init_poll_funcptr(&m->pt, v9fs_pollwait);
+ break;
+ }
+ }
+ }
+
+ if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) {
+ if (vptlast == NULL)
+ return -ENOMEM;
+
+ dprintk(DEBUG_MUX, "put in proc %d\n", i);
+ list_add(&m->mux_list, &vptlast->mux_list);
+ vptlast->muxnum++;
+ m->poll_task = vptlast;
+ memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
+ init_poll_funcptr(&m->pt, v9fs_pollwait);
+ }
+
+ v9fs_mux_num++;
+ down(&v9fs_mux_task_lock);
+
return 0;
}
+static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
+{
+ int i;
+ struct v9fs_mux_poll_task *vpt;
+
+ up(&v9fs_mux_task_lock);
+ vpt = m->poll_task;
+ list_del(&m->mux_list);
+ for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+ if (m->poll_waddr[i] != NULL) {
+ remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]);
+ m->poll_waddr[i] = NULL;
+ }
+ }
+ vpt->muxnum--;
+ if (!vpt->muxnum) {
+ dprintk(DEBUG_MUX, "destroy proc %p\n", vpt);
+ send_sig(SIGKILL, vpt->task, 1);
+ vpt->task = NULL;
+ v9fs_mux_poll_task_num--;
+ }
+ v9fs_mux_num--;
+ down(&v9fs_mux_task_lock);
+}
+
/**
- * xread - force read of a certain number of bytes
- * @v9ses: session info structure
- * @ptr: pointer to buffer
- * @sz: number of bytes to read
+ * v9fs_mux_init - allocate and initialize the per-session mux data
+ * Creates the polling task if this is the first session.
*
- * Chuck Cranor CS-533 project1
+ * @trans - transport structure
+ * @msize - maximum message size
+ * @extended - pointer to the extended flag
*/
-
-static int xread(struct v9fs_session_info *v9ses, void *ptr, unsigned long sz)
+struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
+ unsigned char *extended)
{
- 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;
+ int i, n;
+ struct v9fs_mux_data *m, *mtmp;
+
+ dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize);
+ m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL);
+ if (!m)
+ return ERR_PTR(-ENOMEM);
+
+ spin_lock_init(&m->lock);
+ INIT_LIST_HEAD(&m->mux_list);
+ m->msize = msize;
+ m->extended = extended;
+ m->trans = trans;
+ idr_init(&m->tidpool.pool);
+ init_MUTEX(&m->tidpool.lock);
+ m->err = 0;
+ init_waitqueue_head(&m->equeue);
+ INIT_LIST_HEAD(&m->req_list);
+ INIT_LIST_HEAD(&m->unsent_req_list);
+ m->rcall = NULL;
+ m->rpos = 0;
+ m->rbuf = NULL;
+ m->wpos = m->wsize = 0;
+ m->wbuf = NULL;
+ INIT_WORK(&m->rq, v9fs_read_work, m);
+ INIT_WORK(&m->wq, v9fs_write_work, m);
+ m->wsched = 0;
+ memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
+ m->poll_task = NULL;
+ n = v9fs_mux_poll_start(m);
+ if (n)
+ return ERR_PTR(n);
+
+ n = trans->poll(trans, &m->pt);
+ if (n & POLLIN) {
+ dprintk(DEBUG_MUX, "mux %p can read\n", m);
+ set_bit(Rpending, &m->wsched);
+ }
+
+ if (n & POLLOUT) {
+ dprintk(DEBUG_MUX, "mux %p can write\n", m);
+ set_bit(Wpending, &m->wsched);
+ }
+
+ for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+ if (IS_ERR(m->poll_waddr[i])) {
+ v9fs_mux_poll_stop(m);
+ mtmp = (void *)m->poll_waddr; /* the error code */
+ kfree(m);
+ m = mtmp;
+ break;
}
- rd += ret;
- ptr += ret;
}
- return (rd);
+
+ return m;
}
/**
- * read_message - read a full 9P2000 fcall packet
- * @v9ses: session info structure
- * @rcall: fcall structure to read into
- * @rcalllen: size of fcall buffer
- *
+ * v9fs_mux_destroy - cancels all pending requests and frees mux resources
*/
+void v9fs_mux_destroy(struct v9fs_mux_data *m)
+{
+ dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m,
+ m->mux_list.prev, m->mux_list.next);
+ v9fs_mux_cancel(m, -ECONNRESET);
+
+ if (!list_empty(&m->req_list)) {
+ /* wait until all processes waiting on this session exit */
+ dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n",
+ m);
+ wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000);
+ dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m,
+ list_empty(&m->req_list));
+ }
+
+ v9fs_mux_poll_stop(m);
+ m->trans = NULL;
+
+ kfree(m);
+}
-static int
-read_message(struct v9fs_session_info *v9ses,
- struct v9fs_fcall *rcall, int rcalllen)
+/**
+ * v9fs_pollwait - called by files poll operation to add v9fs-poll task
+ * to files wait queue
+ */
+static void
+v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
+ poll_table * p)
{
- 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;
+ int i;
+ struct v9fs_mux_data *m;
+
+ m = container_of(p, struct v9fs_mux_data, pt);
+ for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
+ if (m->poll_waddr[i] == NULL)
+ break;
+
+ if (i >= ARRAY_SIZE(m->poll_waddr)) {
+ dprintk(DEBUG_ERROR, "not enough wait_address slots\n");
+ return;
}
- if (res < 4) {
- dprintk(DEBUG_ERROR,
- "Reading of count field failed returned: %d\n", res);
- return -EIO;
+ m->poll_waddr[i] = wait_address;
+
+ if (!wait_address) {
+ dprintk(DEBUG_ERROR, "no wait_address\n");
+ m->poll_waddr[i] = ERR_PTR(-EIO);
+ return;
}
- size = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
- dprintk(DEBUG_MUX, "got a packet count: %d\n", size);
+ init_waitqueue_entry(&m->poll_wait[i], m->poll_task->task);
+ add_wait_queue(wait_address, &m->poll_wait[i]);
+}
+
+/**
+ * v9fs_poll_mux - polls a mux and schedules read or write works if necessary
+ */
+static inline void v9fs_poll_mux(struct v9fs_mux_data *m)
+{
+ int n;
- /* adjust for the four bytes of size */
- size -= 4;
+ if (m->err < 0)
+ return;
- if (size > v9ses->maxdata) {
- dprintk(DEBUG_ERROR, "packet too big: %d\n", size);
- return -E2BIG;
+ n = m->trans->poll(m->trans, NULL);
+ if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
+ dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n);
+ if (n >= 0)
+ n = -ECONNRESET;
+ v9fs_mux_cancel(m, n);
}
- data = kmalloc(size, GFP_KERNEL);
- if (!data) {
- eprintk(KERN_WARNING, "out of memory\n");
- return -ENOMEM;
+ if (n & POLLIN) {
+ set_bit(Rpending, &m->wsched);
+ dprintk(DEBUG_MUX, "mux %p can read\n", m);
+ if (!test_and_set_bit(Rworksched, &m->wsched)) {
+ dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
+ queue_work(v9fs_mux_wq, &m->rq);
+ }
}
- res = xread(v9ses, data, size);
- if (res < size) {
- dprintk(DEBUG_ERROR, "Reading of fcall failed returned: %d\n",
- res);
- kfree(data);
- return res;
+ if (n & POLLOUT) {
+ set_bit(Wpending, &m->wsched);
+ dprintk(DEBUG_MUX, "mux %p can write\n", m);
+ if ((m->wsize || !list_empty(&m->unsent_req_list))
+ && !test_and_set_bit(Wworksched, &m->wsched)) {
+ dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
+ queue_work(v9fs_mux_wq, &m->wq);
+ }
}
+}
+
+/**
+ * v9fs_poll_proc - polls all v9fs transports for new events and queues
+ * the appropriate work to the work queue
+ */
+static int v9fs_poll_proc(void *a)
+{
+ struct v9fs_mux_data *m, *mtmp;
+ struct v9fs_mux_poll_task *vpt;
- /* 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);
+ vpt = a;
+ dprintk(DEBUG_MUX, "start %p %p\n", current, vpt);
+ allow_signal(SIGKILL);
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (signal_pending(current))
+ break;
- kfree(data);
+ list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
+ v9fs_poll_mux(m);
+ }
- if (res < 0)
- return res;
+ dprintk(DEBUG_MUX, "sleeping...\n");
+ schedule_timeout(SCHED_TIMEOUT * HZ);
+ }
+ __set_current_state(TASK_RUNNING);
+ dprintk(DEBUG_MUX, "finish\n");
return 0;
}
/**
- * v9fs_recv - receive an RPC response for a particular tag
- * @v9ses: session info structure
- * @req: RPC request structure
- *
+ * v9fs_write_work - called when a transport can send some data
*/
-
-static int v9fs_recv(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+static void v9fs_write_work(void *a)
{
- int ret = 0;
+ int n, err;
+ struct v9fs_mux_data *m;
+ struct v9fs_req *req;
- 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)));
+ m = a;
- dprintk(DEBUG_MUX, "got it: rcall %p\n", req->rcall);
+ if (m->err < 0) {
+ clear_bit(Wworksched, &m->wsched);
+ return;
+ }
- spin_lock(&v9ses->muxlock);
- list_del(&req->next);
- spin_unlock(&v9ses->muxlock);
+ if (!m->wsize) {
+ if (list_empty(&m->unsent_req_list)) {
+ clear_bit(Wworksched, &m->wsched);
+ return;
+ }
- if (req->err < 0)
- return req->err;
+ spin_lock(&m->lock);
+ req =
+ list_entry(m->unsent_req_list.next, struct v9fs_req,
+ req_list);
+ list_move_tail(&req->req_list, &m->req_list);
+ m->wbuf = req->tcall->sdata;
+ m->wsize = req->tcall->size;
+ m->wpos = 0;
+ dump_data(m->wbuf, m->wsize);
+ spin_unlock(&m->lock);
+ }
- if (v9ses->transport->status == Disconnected)
- return -ECONNRESET;
+ dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize);
+ clear_bit(Wpending, &m->wsched);
+ err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos);
+ dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
+ if (err == -EAGAIN) {
+ clear_bit(Wworksched, &m->wsched);
+ return;
+ }
- return ret;
-}
+ if (err <= 0)
+ goto error;
-/**
- * v9fs_send - send a 9P request
- * @v9ses: session info structure
- * @req: RPC request to send
- *
- */
+ m->wpos += err;
+ if (m->wpos == m->wsize)
+ m->wpos = m->wsize = 0;
+
+ if (m->wsize == 0 && !list_empty(&m->unsent_req_list)) {
+ if (test_and_clear_bit(Wpending, &m->wsched))
+ n = POLLOUT;
+ else
+ n = m->trans->poll(m->trans, NULL);
+
+ if (n & POLLOUT) {
+ dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
+ queue_work(v9fs_mux_wq, &m->wq);
+ } else
+ clear_bit(Wworksched, &m->wsched);
+ } else
+ clear_bit(Wworksched, &m->wsched);
+
+ return;
-static int v9fs_send(struct v9fs_session_info *v9ses, struct v9fs_rpcreq *req)
+ error:
+ v9fs_mux_cancel(m, err);
+ clear_bit(Wworksched, &m->wsched);
+}
+
+static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
{
- int ret = -1;
- void *data = NULL;
- struct v9fs_fcall *tcall = req->tcall;
+ int ecode, tag;
+ struct v9fs_str *ename;
- data = kmalloc(v9ses->maxdata + V9FS_IOHDRSZ, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
+ tag = req->tag;
+ if (req->rcall->id == RERROR && !req->err) {
+ ecode = req->rcall->params.rerror.errno;
+ ename = &req->rcall->params.rerror.error;
- tcall->size = 0; /* enforce size recalculation */
- ret =
- v9fs_serialize_fcall(v9ses, tcall, data,
- v9ses->maxdata + V9FS_IOHDRSZ);
- if (ret < 0)
- goto free_data;
+ dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str);
- spin_lock(&v9ses->muxlock);
- list_add(&req->next, &v9ses->mux_fcalls);
- spin_unlock(&v9ses->muxlock);
+ if (*m->extended)
+ req->err = -ecode;
- dprintk(DEBUG_MUX, "sending message: tag %d size %d\n", tcall->tag,
- tcall->size);
- ret = v9ses->transport->write(v9ses->transport, data, tcall->size);
+ if (!req->err) {
+ req->err = v9fs_errstr2errno(ename->str, ename->len);
- if (ret != tcall->size) {
- spin_lock(&v9ses->muxlock);
- list_del(&req->next);
- kfree(req->rcall);
+ if (!req->err) { /* string match failed */
+ PRINT_FCALL_ERROR("unknown error", req->rcall);
+ }
+
+ if (!req->err)
+ req->err = -ESERVERFAULT;
+ }
+ } else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
+ dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n",
+ req->tcall->id + 1, req->rcall->id);
+ if (!req->err)
+ req->err = -EIO;
+ }
- spin_unlock(&v9ses->muxlock);
- if (ret >= 0)
- ret = -EREMOTEIO;
+ if (req->cb && req->err != ERREQFLUSH) {
+ dprintk(DEBUG_MUX, "calling callback tcall %p rcall %p\n",
+ req->tcall, req->rcall);
+
+ (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
+ req->cb = NULL;
} else
- ret = 0;
+ kfree(req->rcall);
- free_data:
- kfree(data);
- return ret;
+ v9fs_mux_put_tag(m, tag);
+
+ wake_up(&m->equeue);
+ kfree(req);
}
/**
- * v9fs_mux_rpc - send a request, receive a response
- * @v9ses: session info structure
- * @tcall: fcall to send
- * @rcall: buffer to place response into
- *
+ * v9fs_read_work - called when there is some data to be read from a transport
*/
-
-long
-v9fs_mux_rpc(struct v9fs_session_info *v9ses, struct v9fs_fcall *tcall,
- struct v9fs_fcall **rcall)
+static void v9fs_read_work(void *a)
{
- 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;
+ int n, err;
+ struct v9fs_mux_data *m;
+ struct v9fs_req *req, *rptr, *rreq;
+ struct v9fs_fcall *rcall;
+ char *rbuf;
+
+ m = a;
+
+ if (m->err < 0)
+ return;
+
+ rcall = NULL;
+ dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
+
+ if (!m->rcall) {
+ m->rcall =
+ kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL);
+ if (!m->rcall) {
+ err = -ENOMEM;
+ goto error;
+ }
- if (rcall)
- *rcall = NULL;
+ m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
+ m->rpos = 0;
+ }
- if (tcall->id != TVERSION) {
- tid = v9fs_get_idpool(&v9ses->tidpool);
- if (tid < 0)
- return -ENOMEM;
+ clear_bit(Rpending, &m->wsched);
+ err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
+ dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err);
+ if (err == -EAGAIN) {
+ clear_bit(Rworksched, &m->wsched);
+ return;
}
- tcall->tag = tid;
+ if (err <= 0)
+ goto error;
- req.tcall = tcall;
- req.err = 0;
- req.rcall = NULL;
+ m->rpos += err;
+ while (m->rpos > 4) {
+ n = le32_to_cpu(*(__le32 *) m->rbuf);
+ if (n >= m->msize) {
+ dprintk(DEBUG_ERROR,
+ "requested packet size too big: %d\n", n);
+ err = -EIO;
+ goto error;
+ }
- ret = v9fs_send(v9ses, &req);
+ if (m->rpos < n)
+ break;
- if (ret < 0) {
- if (tcall->id != TVERSION)
- v9fs_put_idpool(tid, &v9ses->tidpool);
- dprintk(DEBUG_MUX, "error %d\n", ret);
- return ret;
- }
+ dump_data(m->rbuf, n);
+ err =
+ v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
+ if (err < 0) {
+ goto error;
+ }
+
+ rcall = m->rcall;
+ rbuf = m->rbuf;
+ if (m->rpos > n) {
+ m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize,
+ GFP_KERNEL);
+ if (!m->rcall) {
+ err = -ENOMEM;
+ goto error;
+ }
- 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");
+ m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
+ memmove(m->rbuf, rbuf + n, m->rpos - n);
+ m->rpos -= n;
+ } else {
+ m->rcall = NULL;
+ m->rbuf = NULL;
+ m->rpos = 0;
}
- 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;
+ dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id,
+ rcall->tag);
+
+ req = NULL;
+ spin_lock(&m->lock);
+ list_for_each_entry_safe(rreq, rptr, &m->req_list, req_list) {
+ if (rreq->tag == rcall->tag) {
+ req = rreq;
+ req->rcall = rcall;
+ list_del(&req->req_list);
+ spin_unlock(&m->lock);
+ process_request(m, req);
+ break;
}
- } else if (fcall->id != tcall->id + 1) {
- dprintk(DEBUG_ERROR,
- "fcall mismatch: expected %d, got %d\n",
- tcall->id + 1, fcall->id);
- ret = -EIO;
+
+ }
+
+ if (!req) {
+ spin_unlock(&m->lock);
+ if (err >= 0 && rcall->id != RFLUSH)
+ dprintk(DEBUG_ERROR,
+ "unexpected response mux %p id %d tag %d\n",
+ m, rcall->id, rcall->tag);
+ kfree(rcall);
}
}
- release_req:
- if (tcall->id != TVERSION)
- v9fs_put_idpool(tid, &v9ses->tidpool);
- if (rcall)
- *rcall = fcall;
- else
- kfree(fcall);
+ if (!list_empty(&m->req_list)) {
+ if (test_and_clear_bit(Rpending, &m->wsched))
+ n = POLLIN;
+ else
+ n = m->trans->poll(m->trans, NULL);
+
+ if (n & POLLIN) {
+ dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
+ queue_work(v9fs_mux_wq, &m->rq);
+ } else
+ clear_bit(Rworksched, &m->wsched);
+ } else
+ clear_bit(Rworksched, &m->wsched);
+
+ return;
- return ret;
+ error:
+ v9fs_mux_cancel(m, err);
+ clear_bit(Rworksched, &m->wsched);
}
/**
- * v9fs_mux_cancel_requests - cancels all pending requests
+ * v9fs_send_request - send 9P request
+ * The function can sleep until the request is scheduled for sending.
+ * The function can be interrupted. Return from the function is not
+ * a guarantee that the request is sent succesfully. Can return errors
+ * that can be retrieved by PTR_ERR macros.
*
- * @v9ses: session info structure
- * @err: error code to return to the requests
+ * @m: mux data
+ * @tc: request to be sent
+ * @cb: callback function to call when response is received
+ * @cba: parameter to pass to the callback function
*/
-void v9fs_mux_cancel_requests(struct v9fs_session_info *v9ses, int err)
+static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
+ struct v9fs_fcall *tc,
+ v9fs_mux_req_callback cb, void *cba)
{
- struct v9fs_rpcreq *rptr;
- struct v9fs_rpcreq *rreq;
+ int n;
+ struct v9fs_req *req;
- 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);
-}
+ dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
+ tc, tc->id);
+ if (m->err < 0)
+ return ERR_PTR(m->err);
-/**
- * v9fs_recvproc - kproc to handle demultiplexing responses
- * @data: session info structure
- *
- */
+ req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL);
+ if (!req)
+ return ERR_PTR(-ENOMEM);
-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;
+ if (tc->id == TVERSION)
+ n = V9FS_NOTAG;
+ else
+ n = v9fs_mux_get_tag(m);
- 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;
- }
+ if (n < 0)
+ return ERR_PTR(-ENOMEM);
- 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;
- }
- }
- }
+ v9fs_set_tag(tc, n);
- 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;
- }
+ req->tag = n;
+ req->tcall = tc;
+ req->rcall = NULL;
+ req->err = 0;
+ req->cb = cb;
+ req->cba = cba;
+
+ spin_lock(&m->lock);
+ list_add_tail(&req->req_list, &m->unsent_req_list);
+ spin_unlock(&m->lock);
+
+ if (test_and_clear_bit(Wpending, &m->wsched))
+ n = POLLOUT;
+ else
+ n = m->trans->poll(m->trans, NULL);
+
+ if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
+ queue_work(v9fs_mux_wq, &m->wq);
+
+ return req;
+}
+
+static inline void
+v9fs_mux_flush_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc,
+ int err)
+{
+ v9fs_mux_req_callback cb;
+ int tag;
+ struct v9fs_mux_data *m;
+ struct v9fs_req *req, *rptr;
+
+ m = a;
+ dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m, tc,
+ rc, err, tc->params.tflush.oldtag);
+
+ spin_lock(&m->lock);
+ cb = NULL;
+ tag = tc->params.tflush.oldtag;
+ list_for_each_entry_safe(req, rptr, &m->req_list, req_list) {
+ if (req->tag == tag) {
+ list_del(&req->req_list);
+ if (req->cb) {
+ cb = req->cb;
+ req->cb = NULL;
+ spin_unlock(&m->lock);
+ (*cb) (req->cba, req->tcall, req->rcall,
+ req->err);
}
+ kfree(req);
+ wake_up(&m->equeue);
+ break;
}
+ }
- spin_unlock(&v9ses->muxlock);
+ if (!cb)
+ spin_unlock(&m->lock);
- if (!req) {
- if (err >= 0)
- dprintk(DEBUG_ERROR,
- "unexpected response: id %d tag %d\n",
- rcall->id, rcall->tag);
+ v9fs_mux_put_tag(m, tag);
+ kfree(tc);
+ kfree(rc);
+}
- kfree(rcall);
- }
+static void
+v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+{
+ struct v9fs_fcall *fc;
- wake_up_all(&v9ses->read_wait);
- set_current_state(TASK_INTERRUPTIBLE);
+ dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
+
+ fc = v9fs_create_tflush(req->tag);
+ v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
+}
+
+static void
+v9fs_mux_rpc_cb(void *a, struct v9fs_fcall *tc, struct v9fs_fcall *rc, int err)
+{
+ struct v9fs_mux_rpc *r;
+
+ if (err == ERREQFLUSH) {
+ dprintk(DEBUG_MUX, "err req flush\n");
+ return;
}
- v9ses->transport->close(v9ses->transport);
+ r = a;
+ dprintk(DEBUG_MUX, "mux %p req %p tc %p rc %p err %d\n", r->m, r->req,
+ tc, rc, err);
+ r->rcall = rc;
+ r->err = err;
+ wake_up(&r->wqueue);
+}
- /* Inform all pending processes about the failure */
- wake_up_all(&v9ses->read_wait);
+/**
+ * v9fs_mux_rpc - sends 9P request and waits until a response is available.
+ * The function can be interrupted.
+ * @m: mux data
+ * @tc: request to be sent
+ * @rc: pointer where a pointer to the response is stored
+ */
+int
+v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
+ struct v9fs_fcall **rc)
+{
+ int err;
+ unsigned long flags;
+ struct v9fs_req *req;
+ struct v9fs_mux_rpc r;
+
+ r.err = 0;
+ r.rcall = NULL;
+ r.m = m;
+ init_waitqueue_head(&r.wqueue);
+
+ if (rc)
+ *rc = NULL;
+
+ req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
+ if (IS_ERR(req)) {
+ err = PTR_ERR(req);
+ dprintk(DEBUG_MUX, "error %d\n", err);
+ return PTR_ERR(req);
+ }
- if (signal_pending(current))
- complete(&v9ses->proccmpl);
+ r.req = req;
+ dprintk(DEBUG_MUX, "mux %p tc %p tag %d rpc %p req %p\n", m, tc,
+ req->tag, &r, req);
+ err = wait_event_interruptible(r.wqueue, r.rcall != NULL || r.err < 0);
+ if (r.err < 0)
+ err = r.err;
+
+ if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
+ spin_lock(&m->lock);
+ req->tcall = NULL;
+ req->err = ERREQFLUSH;
+ spin_unlock(&m->lock);
+
+ clear_thread_flag(TIF_SIGPENDING);
+ v9fs_mux_flush_request(m, req);
+ spin_lock_irqsave(&current->sighand->siglock, flags);
+ recalc_sigpending();
+ spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ }
- dprintk(DEBUG_MUX, "recvproc: end\n");
- v9ses->recvproc = NULL;
+ if (!err) {
+ if (r.rcall)
+ dprintk(DEBUG_MUX, "got response id %d tag %d\n",
+ r.rcall->id, r.rcall->tag);
+
+ if (rc)
+ *rc = r.rcall;
+ else
+ kfree(r.rcall);
+ } else {
+ kfree(r.rcall);
+ dprintk(DEBUG_MUX, "got error %d\n", err);
+ if (err > 0)
+ err = -EIO;
+ }
- return err >= 0;
+ return err;
}
/**
- * v9fs_mux_init - initialize multiplexer (spawn kproc)
- * @v9ses: session info structure
- * @dev_name: mount device information (to create unique kproc)
- *
+ * v9fs_mux_rpcnb - sends 9P request without waiting for response.
+ * @m: mux data
+ * @tc: request to be sent
+ * @cb: callback function to be called when response arrives
+ * @cba: value to pass to the callback function
*/
+int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
+ v9fs_mux_req_callback cb, void *a)
+{
+ int err;
+ struct v9fs_req *req;
+
+ req = v9fs_send_request(m, tc, cb, a);
+ if (IS_ERR(req)) {
+ err = PTR_ERR(req);
+ dprintk(DEBUG_MUX, "error %d\n", err);
+ return PTR_ERR(req);
+ }
+
+ dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
+ return 0;
+}
-int v9fs_mux_init(struct v9fs_session_info *v9ses, const char *dev_name)
+/**
+ * v9fs_mux_cancel - cancel all pending requests with error
+ * @m: mux data
+ * @err: error code
+ */
+void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
{
- 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;
+ struct v9fs_req *req, *rtmp;
+ LIST_HEAD(cancel_list);
+
+ dprintk(DEBUG_MUX, "mux %p err %d\n", m, err);
+ m->err = err;
+ spin_lock(&m->lock);
+ list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
+ list_move(&req->req_list, &cancel_list);
}
+ spin_unlock(&m->lock);
- wake_up_process(v9ses->recvproc);
- wait_for_completion(&v9ses->proccmpl);
+ list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
+ list_del(&req->req_list);
+ if (!req->err)
+ req->err = err;
- return 0;
+ if (req->cb)
+ (*req->cb) (req->cba, req->tcall, req->rcall, req->err);
+ else
+ kfree(req->rcall);
+
+ kfree(req);
+ }
+
+ wake_up(&m->equeue);
+}
+
+static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
+{
+ int tag;
+
+ tag = v9fs_get_idpool(&m->tidpool);
+ if (tag < 0)
+ return V9FS_NOTAG;
+ else
+ return (u16) tag;
+}
+
+static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag)
+{
+ if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tidpool))
+ v9fs_put_idpool(tag, &m->tidpool);
}
diff --git a/fs/9p/mux.h b/fs/9p/mux.h
index 4994cb10badf..9473b84f24b2 100644
--- a/fs/9p/mux.h
+++ b/fs/9p/mux.h
@@ -3,6 +3,7 @@
*
* Multiplexer Definitions
*
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -23,19 +24,35 @@
*
*/
-/* structure to manage each RPC transaction */
+struct v9fs_mux_data;
-struct v9fs_rpcreq {
- struct v9fs_fcall *tcall;
- struct v9fs_fcall *rcall;
- int err; /* error code if response failed */
+/**
+ * v9fs_mux_req_callback - callback function that is called when the
+ * response of a request is received. The callback is called from
+ * a workqueue and shouldn't block.
+ *
+ * @a - the pointer that was specified when the request was send to be
+ * passed to the callback
+ * @tc - request call
+ * @rc - response call
+ * @err - error code (non-zero if error occured)
+ */
+typedef void (*v9fs_mux_req_callback)(void *a, struct v9fs_fcall *tc,
+ struct v9fs_fcall *rc, int err);
+
+int v9fs_mux_global_init(void);
+void v9fs_mux_global_exit(void);
- /* XXX - could we put scatter/gather buffers here? */
+struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
+ unsigned char *extended);
+void v9fs_mux_destroy(struct v9fs_mux_data *);
- struct list_head next;
-};
+int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc);
+struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m);
+int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc);
+int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
+ v9fs_mux_req_callback cb, void *a);
-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);
+void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush);
+void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
+int v9fs_errstr2errno(char *errstr, int len);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
index 63b58ce98ff4..1a28ef97a3d1 100644
--- a/fs/9p/trans_fd.c
+++ b/fs/9p/trans_fd.c
@@ -3,6 +3,7 @@
*
* File Descriptor Transport Layer
*
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -106,9 +107,6 @@ v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
return -ENOPROTOOPT;
}
- sema_init(&trans->writelock, 1);
- sema_init(&trans->readlock, 1);
-
ts = kmalloc(sizeof(struct v9fs_trans_fd), GFP_KERNEL);
if (!ts)
@@ -148,12 +146,12 @@ static void v9fs_fd_close(struct v9fs_transport *trans)
if (!trans)
return;
- trans->status = Disconnected;
- ts = trans->priv;
+ ts = xchg(&trans->priv, NULL);
if (!ts)
return;
+ trans->status = Disconnected;
if (ts->in_file)
fput(ts->in_file);
@@ -163,10 +161,55 @@ static void v9fs_fd_close(struct v9fs_transport *trans)
kfree(ts);
}
+static unsigned int
+v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
+{
+ int ret, n;
+ struct v9fs_trans_fd *ts;
+ mm_segment_t oldfs;
+
+ if (!trans)
+ return -EIO;
+
+ ts = trans->priv;
+ if (trans->status != Connected || !ts)
+ return -EIO;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+
+ if (!ts->in_file->f_op || !ts->in_file->f_op->poll) {
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = ts->in_file->f_op->poll(ts->in_file, pt);
+
+ if (ts->out_file != ts->in_file) {
+ if (!ts->out_file->f_op || !ts->out_file->f_op->poll) {
+ ret = -EIO;
+ goto end;
+ }
+
+ n = ts->out_file->f_op->poll(ts->out_file, pt);
+
+ ret &= ~POLLOUT;
+ n &= ~POLLIN;
+
+ ret |= n;
+ }
+
+end:
+ set_fs(oldfs);
+ return ret;
+}
+
+
struct v9fs_transport v9fs_trans_fd = {
.init = v9fs_fd_init,
.write = v9fs_fd_send,
.read = v9fs_fd_recv,
.close = v9fs_fd_close,
+ .poll = v9fs_fd_poll,
};
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
index a93c2bf94c33..44e830697acb 100644
--- a/fs/9p/trans_sock.c
+++ b/fs/9p/trans_sock.c
@@ -3,6 +3,7 @@
*
* Socket Transport Layer
*
+ * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
* 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>
@@ -26,6 +27,7 @@
*/
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/ipv6.h>
@@ -35,6 +37,7 @@
#include <asm/uaccess.h>
#include <linux/inet.h>
#include <linux/idr.h>
+#include <linux/file.h>
#include "debug.h"
#include "v9fs.h"
@@ -44,6 +47,7 @@
struct v9fs_trans_sock {
struct socket *s;
+ struct file *filp;
};
/**
@@ -56,41 +60,26 @@ struct v9fs_trans_sock {
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;
+ int ret;
+ struct v9fs_trans_sock *ts;
- if (trans->status == Disconnected)
+ if (!trans || trans->status == Disconnected) {
+ dprintk(DEBUG_ERROR, "disconnected ...\n");
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;
+ ts = trans->priv;
- result = kernel_recvmsg(ts->s, &msg, &iov, 1, len, 0);
+ if (!(ts->filp->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking read ...\n");
- dprintk(DEBUG_TRANS, "socket state %d\n", ts->s->state);
- set_fs(oldfs);
-
- if (result <= 0) {
- if (result != -ERESTARTSYS)
+ ret = kernel_read(ts->filp, ts->filp->f_pos, v, len);
+ if (ret <= 0) {
+ if (ret != -ERESTARTSYS && ret != -EAGAIN)
trans->status = Disconnected;
}
- return result;
+ return ret;
}
/**
@@ -103,40 +92,72 @@ static int v9fs_sock_recv(struct v9fs_transport *trans, void *v, int len)
static int v9fs_sock_send(struct v9fs_transport *trans, void *v, int len)
{
- struct kvec iov;
- struct msghdr msg;
- int result = -1;
+ int ret;
mm_segment_t oldfs;
- struct v9fs_trans_sock *ts = trans ? trans->priv : NULL;
+ struct v9fs_trans_sock *ts;
- dprintk(DEBUG_TRANS, "Sending packet size %d (%x)\n", len, len);
- dump_data(v, len);
+ if (!trans || trans->status == Disconnected) {
+ dprintk(DEBUG_ERROR, "disconnected ...\n");
+ return -EREMOTEIO;
+ }
+
+ ts = trans->priv;
+ if (!ts) {
+ dprintk(DEBUG_ERROR, "no transport ...\n");
+ return -EREMOTEIO;
+ }
- down(&trans->writelock);
+ if (!(ts->filp->f_flags & O_NONBLOCK))
+ dprintk(DEBUG_ERROR, "blocking write ...\n");
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);
+ ret = vfs_write(ts->filp, (void __user *)v, len, &ts->filp->f_pos);
set_fs(oldfs);
- if (result < 0) {
- if (result != -ERESTARTSYS)
+ if (ret < 0) {
+ if (ret != -ERESTARTSYS)
trans->status = Disconnected;
}
- up(&trans->writelock);
- return result;
+ return ret;
+}
+
+static unsigned int v9fs_sock_poll(struct v9fs_transport *trans,
+ struct poll_table_struct *pt) {
+
+ int ret;
+ struct v9fs_trans_sock *ts;
+ mm_segment_t oldfs;
+
+ if (!trans) {
+ dprintk(DEBUG_ERROR, "no transport\n");
+ return -EIO;
+ }
+
+ ts = trans->priv;
+ if (trans->status != Connected || !ts) {
+ dprintk(DEBUG_ERROR, "transport disconnected: %d\n", trans->status);
+ return -EIO;
+ }
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+
+ if (!ts->filp->f_op || !ts->filp->f_op->poll) {
+ dprintk(DEBUG_ERROR, "no poll operation\n");
+ ret = -EIO;
+ goto end;
+ }
+
+ ret = ts->filp->f_op->poll(ts->filp, pt);
+
+end:
+ set_fs(oldfs);
+ return ret;
}
+
/**
* v9fs_tcp_init - initialize TCP socket
* @v9ses: session information
@@ -153,9 +174,9 @@ v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
int rc = 0;
struct v9fs_trans_sock *ts = NULL;
struct v9fs_transport *trans = v9ses->transport;
+ int fd;
- sema_init(&trans->writelock, 1);
- sema_init(&trans->readlock, 1);
+ trans->status = Disconnected;
ts = kmalloc(sizeof(struct v9fs_trans_sock), GFP_KERNEL);
@@ -164,6 +185,7 @@ v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
trans->priv = ts;
ts->s = NULL;
+ ts->filp = NULL;
if (!addr)
return -EINVAL;
@@ -184,7 +206,18 @@ v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
return rc;
}
csocket->sk->sk_allocation = GFP_NOIO;
+
+ fd = sock_map_fd(csocket);
+ if (fd < 0) {
+ sock_release(csocket);
+ kfree(ts);
+ trans->priv = NULL;
+ return fd;
+ }
+
ts->s = csocket;
+ ts->filp = fget(fd);
+ ts->filp->f_flags |= O_NONBLOCK;
trans->status = Connected;
return 0;
@@ -202,7 +235,7 @@ static int
v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
char *data)
{
- int rc;
+ int rc, fd;
struct socket *csocket;
struct sockaddr_un sun_server;
struct v9fs_transport *trans;
@@ -212,6 +245,8 @@ v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
csocket = NULL;
trans = v9ses->transport;
+ trans->status = Disconnected;
+
if (strlen(dev_name) > UNIX_PATH_MAX) {
eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
dev_name);
@@ -224,9 +259,7 @@ v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
trans->priv = ts;
ts->s = NULL;
-
- sema_init(&trans->writelock, 1);
- sema_init(&trans->readlock, 1);
+ ts->filp = NULL;
sun_server.sun_family = PF_UNIX;
strcpy(sun_server.sun_path, dev_name);
@@ -240,7 +273,18 @@ v9fs_unix_init(struct v9fs_session_info *v9ses, const char *dev_name,
return rc;
}
csocket->sk->sk_allocation = GFP_NOIO;
+
+ fd = sock_map_fd(csocket);
+ if (fd < 0) {
+ sock_release(csocket);
+ kfree(ts);
+ trans->priv = NULL;
+ return fd;
+ }
+
ts->s = csocket;
+ ts->filp = fget(fd);
+ ts->filp->f_flags |= O_NONBLOCK;
trans->status = Connected;
return 0;
@@ -261,12 +305,11 @@ static void v9fs_sock_close(struct v9fs_transport *trans)
ts = trans->priv;
- if ((ts) && (ts->s)) {
- dprintk(DEBUG_TRANS, "closing the socket %p\n", ts->s);
- sock_release(ts->s);
+ if ((ts) && (ts->filp)) {
+ fput(ts->filp);
+ ts->filp = NULL;
ts->s = NULL;
trans->status = Disconnected;
- dprintk(DEBUG_TRANS, "socket closed\n");
}
kfree(ts);
@@ -279,6 +322,7 @@ struct v9fs_transport v9fs_trans_tcp = {
.write = v9fs_sock_send,
.read = v9fs_sock_recv,
.close = v9fs_sock_close,
+ .poll = v9fs_sock_poll,
};
struct v9fs_transport v9fs_trans_unix = {
@@ -286,4 +330,5 @@ struct v9fs_transport v9fs_trans_unix = {
.write = v9fs_sock_send,
.read = v9fs_sock_recv,
.close = v9fs_sock_close,
+ .poll = v9fs_sock_poll,
};
diff --git a/fs/9p/transport.h b/fs/9p/transport.h
index 9e9cd418efd5..91fcdb94b361 100644
--- a/fs/9p/transport.h
+++ b/fs/9p/transport.h
@@ -3,6 +3,7 @@
*
* Transport Definition
*
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -31,14 +32,13 @@ enum v9fs_transport_status {
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 *);
+ unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *);
};
extern struct v9fs_transport v9fs_trans_tcp;
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 418c3743fdee..5250c428fc1f 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -37,7 +37,6 @@
#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 */
@@ -213,7 +212,8 @@ retry:
return -1;
}
- error = idr_get_new(&p->pool, NULL, &i);
+ /* no need to store exactly p, we just need something non-null */
+ error = idr_get_new(&p->pool, p, &i);
up(&p->lock);
if (error == -EAGAIN)
@@ -243,6 +243,16 @@ void v9fs_put_idpool(int id, struct v9fs_idpool *p)
}
/**
+ * v9fs_check_idpool - check if the specified id is available
+ * @id - id to check
+ * @p - pool
+ */
+int v9fs_check_idpool(int id, struct v9fs_idpool *p)
+{
+ return idr_find(&p->pool, id) != NULL;
+}
+
+/**
* v9fs_session_init - initialize session
* @v9ses: session information structure
* @dev_name: device being mounted
@@ -259,6 +269,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
int n = 0;
int newfid = -1;
int retval = -EINVAL;
+ struct v9fs_str *version;
v9ses->name = __getname();
if (!v9ses->name)
@@ -281,9 +292,6 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
/* 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:
@@ -320,7 +328,12 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
v9ses->shutdown = 0;
v9ses->session_hung = 0;
- if ((retval = v9fs_mux_init(v9ses, dev_name)) < 0) {
+ v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ,
+ &v9ses->extended);
+
+ if (IS_ERR(v9ses->mux)) {
+ retval = PTR_ERR(v9ses->mux);
+ v9ses->mux = NULL;
dprintk(DEBUG_ERROR, "problem initializing mux\n");
goto SessCleanUp;
}
@@ -339,13 +352,16 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
goto FreeFcall;
}
- /* Really should check for 9P1 and report error */
- if (!strcmp(fcall->params.rversion.version, "9P2000.u")) {
+ version = &fcall->params.rversion.version;
+ if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
v9ses->extended = 1;
- } else {
+ } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
v9ses->extended = 0;
+ } else {
+ retval = -EREMOTEIO;
+ goto FreeFcall;
}
n = fcall->params.rversion.msize;
@@ -381,7 +397,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
}
if (v9ses->afid != ~0) {
- if (v9fs_t_clunk(v9ses, v9ses->afid, NULL))
+ if (v9fs_t_clunk(v9ses, v9ses->afid))
dprintk(DEBUG_ERROR, "clunk failed\n");
}
@@ -403,13 +419,16 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
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->mux) {
+ v9fs_mux_destroy(v9ses->mux);
+ v9ses->mux = NULL;
}
- if (v9ses->transport)
+ if (v9ses->transport) {
v9ses->transport->close(v9ses->transport);
+ kfree(v9ses->transport);
+ v9ses->transport = NULL;
+ }
__putname(v9ses->name);
__putname(v9ses->remotename);
@@ -420,8 +439,9 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
* and cancel all pending requests.
*/
void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
+ dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses);
v9ses->transport->status = Disconnected;
- v9fs_mux_cancel_requests(v9ses, -EIO);
+ v9fs_mux_cancel(v9ses->mux, -EIO);
}
extern int v9fs_error_init(void);
@@ -433,11 +453,17 @@ extern int v9fs_error_init(void);
static int __init init_v9fs(void)
{
+ int ret;
+
v9fs_error_init();
printk(KERN_INFO "Installing v9fs 9P2000 file system support\n");
- return register_filesystem(&v9fs_fs_type);
+ ret = v9fs_mux_global_init();
+ if (!ret)
+ ret = register_filesystem(&v9fs_fs_type);
+
+ return ret;
}
/**
@@ -447,6 +473,7 @@ static int __init init_v9fs(void)
static void __exit exit_v9fs(void)
{
+ v9fs_mux_global_exit();
unregister_filesystem(&v9fs_fs_type);
}
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 45dcef42bdd6..f337da7a0eec 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -57,24 +57,14 @@ struct v9fs_session_info {
/* 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;
+ struct v9fs_mux_data *mux;
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;
+ struct dentry *debugfs_dir;
};
/* possible values of ->proto */
@@ -84,11 +74,14 @@ enum {
PROTO_FD,
};
+extern struct dentry *v9fs_debugfs_root;
+
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);
+int v9fs_check_idpool(int id, struct v9fs_idpool *p);
void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_MAGIC 0x01021997
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 2f2cea7ee3e7..69cf2905dc90 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -39,15 +39,15 @@
*/
extern struct file_system_type v9fs_fs_type;
+extern struct address_space_operations v9fs_addr_operations;
extern struct file_operations v9fs_file_operations;
extern struct file_operations v9fs_dir_operations;
extern 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 *);
+void v9fs_stat2inode(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_inode2stat(struct inode *inode, struct v9fs_stat *stat);
void v9fs_dentry_release(struct dentry *);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
new file mode 100644
index 000000000000..8100fb5171b7
--- /dev/null
+++ b/fs/9p/vfs_addr.c
@@ -0,0 +1,109 @@
+/*
+ * linux/fs/9p/vfs_addr.c
+ *
+ * This file contians vfs address (mmap) ops for 9P2000.
+ *
+ * Copyright (C) 2005 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/pagemap.h>
+#include <linux/idr.h>
+
+#include "debug.h"
+#include "v9fs.h"
+#include "9p.h"
+#include "v9fs_vfs.h"
+#include "fid.h"
+
+/**
+ * v9fs_vfs_readpage - read an entire page in from 9P
+ *
+ * @file: file being read
+ * @page: structure to page
+ *
+ */
+
+static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+{
+ char *buffer = NULL;
+ int retval = -EIO;
+ loff_t offset = page_offset(page);
+ int count = PAGE_CACHE_SIZE;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+ int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
+ struct v9fs_fid *v9f = filp->private_data;
+ struct v9fs_fcall *fcall = NULL;
+ int fid = v9f->fid;
+ int total = 0;
+ int result = 0;
+
+ buffer = kmap(page);
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
+
+ if (result < 0) {
+ printk(KERN_ERR "v9fs_t_read returned %d\n",
+ result);
+
+ kfree(fcall);
+ goto UnmapAndUnlock;
+ } else
+ offset += result;
+
+ memcpy(buffer, fcall->params.rread.data, result);
+
+ count -= result;
+ buffer += result;
+ total += result;
+
+ kfree(fcall);
+
+ if (result < rsize)
+ break;
+ } while (count);
+
+ memset(buffer, 0, count);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ retval = 0;
+
+UnmapAndUnlock:
+ kunmap(page);
+ unlock_page(page);
+ return retval;
+}
+
+struct address_space_operations v9fs_addr_operations = {
+ .readpage = v9fs_vfs_readpage,
+};
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index a6aa947de0f9..2dd806dac9f1 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -40,7 +40,6 @@
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
-#include "conv.h"
#include "fid.h"
/**
@@ -95,24 +94,22 @@ static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd)
void v9fs_dentry_release(struct dentry *dentry)
{
+ int err;
+
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));
+ err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid);
- v9fs_put_idpool(current_fid->fid,
- &current_fid->v9ses->fidpool);
+ if (err < 0)
+ dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n",
+ err, dentry->d_iname);
- kfree(fcall);
v9fs_fid_destroy(current_fid);
}
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 57a43b8feef5..ae6d032b9b59 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -37,8 +37,8 @@
#include "debug.h"
#include "v9fs.h"
#include "9p.h"
-#include "v9fs_vfs.h"
#include "conv.h"
+#include "v9fs_vfs.h"
#include "fid.h"
/**
@@ -74,20 +74,16 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
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;
+ unsigned int i, n, s;
int fid = -1;
int ret = 0;
- struct v9fs_stat *mi = NULL;
+ struct v9fs_stat stat;
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;
@@ -97,20 +93,20 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
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);
+ s = v9fs_deserialize_stat(
+ file->rdir_fcall->params.rread.data + i,
+ n - i, &stat, v9ses->extended);
if (s == 0) {
dprintk(DEBUG_ERROR,
- "error while deserializing mistat\n");
+ "error while deserializing stat\n");
ret = -EIO;
goto FreeStructs;
}
- over = filldir(dirent, mi->name, strlen(mi->name),
- filp->f_pos, v9fs_qid2ino(&mi->qid),
- dt_type(mi));
+ over = filldir(dirent, stat.name.str, stat.name.len,
+ filp->f_pos, v9fs_qid2ino(&stat.qid),
+ dt_type(&stat));
if (over) {
file->rdir_fpos = i;
@@ -130,7 +126,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
while (!over) {
ret = v9fs_t_read(v9ses, fid, filp->f_pos,
- v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
+ v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
if (ret < 0) {
dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
ret, fcall);
@@ -141,19 +137,18 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
n = ret;
i = 0;
while (i < n) {
- int s = v9fs_deserialize_stat(v9ses,
- fcall->params.rread.data + i, n - i, mi,
- v9ses->maxdata);
+ s = v9fs_deserialize_stat(fcall->params.rread.data + i,
+ n - i, &stat, v9ses->extended);
if (s == 0) {
dprintk(DEBUG_ERROR,
- "error while deserializing mistat\n");
+ "error while deserializing stat\n");
return -EIO;
}
- over = filldir(dirent, mi->name, strlen(mi->name),
- filp->f_pos, v9fs_qid2ino(&mi->qid),
- dt_type(mi));
+ over = filldir(dirent, stat.name.str, stat.name.len,
+ filp->f_pos, v9fs_qid2ino(&stat.qid),
+ dt_type(&stat));
if (over) {
file->rdir_fcall = fcall;
@@ -172,7 +167,6 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
FreeStructs:
kfree(fcall);
- kfree(mi);
return ret;
}
@@ -193,18 +187,15 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
fid->fid);
fidnum = fid->fid;
- filemap_fdatawrite(inode->i_mapping);
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
if (fidnum >= 0) {
dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
fid->fid);
- if (v9fs_t_clunk(v9ses, fidnum, NULL))
+ if (v9fs_t_clunk(v9ses, fidnum))
dprintk(DEBUG_ERROR, "clunk failed\n");
- v9fs_put_idpool(fid->fid, &v9ses->fidpool);
-
kfree(fid->rdir_fcall);
kfree(fid);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 89c849da8504..c7e14d917215 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -32,6 +32,7 @@
#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>
@@ -117,9 +118,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
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));
+ PRINT_FCALL_ERROR("open failed", fcall);
kfree(fcall);
return result;
}
@@ -165,8 +164,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
return -ENOLCK;
if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
- filemap_fdatawrite(inode->i_mapping);
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
invalidate_inode_pages(&inode->i_data);
}
@@ -257,7 +255,6 @@ v9fs_file_write(struct file *filp, const char __user * data,
int result = -EIO;
int rsize = 0;
int total = 0;
- char *buf;
dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
(int)*offset);
@@ -265,28 +262,14 @@ v9fs_file_write(struct file *filp, const char __user * data,
if (v9fid->iounit != 0 && rsize > v9fid->iounit)
rsize = v9fid->iounit;
- buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
do {
if (count < rsize)
rsize = count;
- result = copy_from_user(buf, data, rsize);
- if (result) {
- dprintk(DEBUG_ERROR, "Problem copying from user\n");
- kfree(buf);
- return -EFAULT;
- }
-
- dump_data(buf, rsize);
- result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall);
+ result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall);
if (result < 0) {
- eprintk(KERN_ERR, "error while writing: %s(%d)\n",
- FCALL_ERROR(fcall), result);
+ PRINT_FCALL_ERROR("error while writing", fcall);
kfree(fcall);
- kfree(buf);
return result;
} else
*offset += result;
@@ -306,7 +289,9 @@ v9fs_file_write(struct file *filp, const char __user * data,
total += result;
} while (count);
- kfree(buf);
+ if(inode->i_mapping->nrpages)
+ invalidate_inode_pages2(inode->i_mapping);
+
return total;
}
@@ -317,4 +302,5 @@ struct file_operations v9fs_file_operations = {
.open = v9fs_file_open,
.release = v9fs_dir_release,
.lock = v9fs_file_lock,
+ .mmap = generic_file_mmap,
};
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 0ea965c3bb7d..91f552454c76 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -40,7 +40,6 @@
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
-#include "conv.h"
#include "fid.h"
static struct inode_operations v9fs_dir_inode_operations;
@@ -127,100 +126,32 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
}
/**
- * v9fs_blank_mistat - helper function to setup a 9P stat structure
+ * v9fs_blank_wstat - helper function to setup a 9P stat structure
* @v9ses: 9P session info (for determining extended mode)
- * @mistat: structure to initialize
+ * @wstat: structure to initialize
*
*/
static void
-v9fs_blank_mistat(struct v9fs_session_info *v9ses, struct v9fs_stat *mistat)
+v9fs_blank_wstat(struct v9fs_wstat *wstat)
{
- 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;
+ wstat->type = ~0;
+ wstat->dev = ~0;
+ wstat->qid.type = ~0;
+ wstat->qid.version = ~0;
+ *((long long *)&wstat->qid.path) = ~0;
+ wstat->mode = ~0;
+ wstat->atime = ~0;
+ wstat->mtime = ~0;
+ wstat->length = ~0;
+ wstat->name = NULL;
+ wstat->uid = NULL;
+ wstat->gid = NULL;
+ wstat->muid = NULL;
+ wstat->n_uid = ~0;
+ wstat->n_gid = ~0;
+ wstat->n_muid = ~0;
+ wstat->extension = NULL;
}
/**
@@ -246,6 +177,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
inode->i_blocks = 0;
inode->i_rdev = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->a_ops = &v9fs_addr_operations;
switch (mode & S_IFMT) {
case S_IFIFO:
@@ -312,12 +244,12 @@ v9fs_create(struct inode *dir,
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;
int wfidno = -1;
+ int err;
perm = unixmode2p9mode(v9ses, perm);
@@ -349,57 +281,64 @@ v9fs_create(struct inode *dir,
result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall);
if (result < 0) {
- dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
+ PRINT_FCALL_ERROR("clone error", fcall);
v9fs_put_idpool(newfid, &v9ses->fidpool);
newfid = -1;
goto CleanUpFid;
}
kfree(fcall);
+ fcall = NULL;
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);
-
+ PRINT_FCALL_ERROR("create fails", fcall);
goto CleanUpFid;
}
iounit = fcall->params.rcreate.iounit;
qid = fcall->params.rcreate.qid;
kfree(fcall);
+ fcall = NULL;
- fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1);
- dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate);
- if (!fid) {
- result = -ENOMEM;
- goto CleanUpFid;
- }
+ if (!(perm&V9FS_DMDIR)) {
+ fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1);
+ dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate);
+ if (!fid) {
+ result = -ENOMEM;
+ goto CleanUpFid;
+ }
- fid->qid = qid;
- fid->iounit = iounit;
+ fid->qid = qid;
+ fid->iounit = iounit;
+ } else {
+ err = v9fs_t_clunk(v9ses, newfid);
+ newfid = -1;
+ if (err < 0)
+ dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err);
+ }
/* walk to the newly created file and put the fid in the dentry */
wfidno = v9fs_get_idpool(&v9ses->fidpool);
- if (newfid < 0) {
+ if (wfidno < 0) {
eprintk(KERN_WARNING, "no free fids available\n");
return -ENOSPC;
}
result = v9fs_t_walk(v9ses, dirfidnum, wfidno,
- (char *) file_dentry->d_name.name, NULL);
+ (char *) file_dentry->d_name.name, &fcall);
if (result < 0) {
- dprintk(DEBUG_ERROR, "clone error: %s\n", FCALL_ERROR(fcall));
+ PRINT_FCALL_ERROR("clone error", fcall);
v9fs_put_idpool(wfidno, &v9ses->fidpool);
wfidno = -1;
goto CleanUpFid;
}
+ kfree(fcall);
+ fcall = NULL;
if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) {
- if (!v9fs_t_clunk(v9ses, newfid, &fcall)) {
- v9fs_put_idpool(wfidno, &v9ses->fidpool);
- }
+ v9fs_put_idpool(wfidno, &v9ses->fidpool);
goto CleanUpFid;
}
@@ -409,62 +348,43 @@ v9fs_create(struct inode *dir,
(perm & V9FS_DMDEVICE))
return 0;
- result = v9fs_t_stat(v9ses, newfid, &fcall);
+ result = v9fs_t_stat(v9ses, wfidno, &fcall);
if (result < 0) {
- dprintk(DEBUG_ERROR, "stat error: %s(%d)\n", FCALL_ERROR(fcall),
- result);
+ PRINT_FCALL_ERROR("stat error", fcall);
goto CleanUpFid;
}
- v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
- file_inode = v9fs_get_inode(sb, newstat.st_mode);
+ file_inode = v9fs_get_inode(sb,
+ p9mode2unixmode(v9ses, fcall->params.rstat.stat.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);
+ v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb);
kfree(fcall);
fcall = NULL;
file_dentry->d_op = &v9fs_dentry_operations;
d_instantiate(file_dentry, file_inode);
- if (perm & V9FS_DMDIR) {
- if (!v9fs_t_clunk(v9ses, newfid, &fcall))
- v9fs_put_idpool(newfid, &v9ses->fidpool);
- else
- dprintk(DEBUG_ERROR, "clunk for mkdir failed: %s\n",
- FCALL_ERROR(fcall));
- kfree(fcall);
- fid->fidopen = 0;
- fid->fidcreate = 0;
- d_drop(file_dentry);
- }
-
return 0;
CleanUpFid:
kfree(fcall);
+ fcall = NULL;
if (newfid >= 0) {
- if (!v9fs_t_clunk(v9ses, newfid, &fcall))
- v9fs_put_idpool(newfid, &v9ses->fidpool);
- else
- dprintk(DEBUG_ERROR, "clunk failed: %s\n",
- FCALL_ERROR(fcall));
-
- kfree(fcall);
+ err = v9fs_t_clunk(v9ses, newfid);
+ if (err < 0)
+ dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
}
if (wfidno >= 0) {
- if (!v9fs_t_clunk(v9ses, wfidno, &fcall))
- v9fs_put_idpool(wfidno, &v9ses->fidpool);
- else
- dprintk(DEBUG_ERROR, "clunk failed: %s\n",
- FCALL_ERROR(fcall));
-
- kfree(fcall);
+ err = v9fs_t_clunk(v9ses, wfidno);
+ if (err < 0)
+ dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
}
return result;
}
@@ -509,10 +429,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
}
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 {
+ if (result < 0) {
+ PRINT_FCALL_ERROR("remove fails", fcall);
+ } else {
v9fs_put_idpool(fid, &v9ses->fidpool);
v9fs_fid_destroy(v9fid);
}
@@ -567,7 +486,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
struct v9fs_fid *fid;
struct inode *inode;
struct v9fs_fcall *fcall = NULL;
- struct stat newstat;
int dirfidnum = -1;
int newfid = -1;
int result = 0;
@@ -620,8 +538,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
goto FreeFcall;
}
- v9fs_mistat2unix(fcall->params.rstat.stat, &newstat, sb);
- inode = v9fs_get_inode(sb, newstat.st_mode);
+ inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
+ fcall->params.rstat.stat.mode));
if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
@@ -631,7 +549,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
goto FreeFcall;
}
- inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat->qid);
+ inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
fid = v9fs_fid_create(dentry, v9ses, newfid, 0);
if (fid == NULL) {
@@ -640,10 +558,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
goto FreeFcall;
}
- fid->qid = fcall->params.rstat.stat->qid;
+ fid->qid = fcall->params.rstat.stat.qid;
dentry->d_op = &v9fs_dentry_operations;
- v9fs_mistat2inode(fcall->params.rstat.stat, inode, inode->i_sb);
+ v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
d_add(dentry, inode);
kfree(fcall);
@@ -699,7 +617,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
v9fs_fid_lookup(old_dentry->d_parent);
struct v9fs_fid *newdirfid =
v9fs_fid_lookup(new_dentry->d_parent);
- struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ struct v9fs_wstat wstat;
struct v9fs_fcall *fcall = NULL;
int fid = -1;
int olddirfidnum = -1;
@@ -708,9 +626,6 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
dprintk(DEBUG_VFS, "\n");
- if (!mistat)
- return -ENOMEM;
-
if ((!oldfid) || (!olddirfid) || (!newdirfid)) {
dprintk(DEBUG_ERROR, "problem with arguments\n");
return -EBADF;
@@ -734,33 +649,22 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
goto FreeFcallnBail;
}
- v9fs_blank_mistat(v9ses, mistat);
+ v9fs_blank_wstat(&wstat);
+ wstat.muid = v9ses->name;
+ wstat.name = (char *) new_dentry->d_name.name;
- 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);
+ retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
FreeFcallnBail:
- kfree(mistat);
-
if (retval < 0)
- dprintk(DEBUG_ERROR, "v9fs_t_wstat error: %s\n",
- FCALL_ERROR(fcall));
+ PRINT_FCALL_ERROR("wstat error", fcall);
kfree(fcall);
return retval;
}
/**
- * v9fs_vfs_getattr - retreive file metadata
+ * v9fs_vfs_getattr - retrieve file metadata
* @mnt - mount information
* @dentry - file to get attributes on
* @stat - metadata structure to populate
@@ -788,7 +692,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
if (err < 0)
dprintk(DEBUG_ERROR, "stat error\n");
else {
- v9fs_mistat2inode(fcall->params.rstat.stat, dentry->d_inode,
+ v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
dentry->d_inode->i_sb);
generic_fillattr(dentry->d_inode, stat);
}
@@ -809,57 +713,44 @@ 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);
struct v9fs_fcall *fcall = NULL;
- struct v9fs_stat *mistat = kmalloc(v9ses->maxdata, GFP_KERNEL);
+ struct v9fs_wstat wstat;
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);
+ v9fs_blank_wstat(&wstat);
if (iattr->ia_valid & ATTR_MODE)
- mistat->mode = unixmode2p9mode(v9ses, iattr->ia_mode);
+ wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode);
if (iattr->ia_valid & ATTR_MTIME)
- mistat->mtime = iattr->ia_mtime.tv_sec;
+ wstat.mtime = iattr->ia_mtime.tv_sec;
if (iattr->ia_valid & ATTR_ATIME)
- mistat->atime = iattr->ia_atime.tv_sec;
+ wstat.atime = iattr->ia_atime.tv_sec;
if (iattr->ia_valid & ATTR_SIZE)
- mistat->length = iattr->ia_size;
+ wstat.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_UID)
+ wstat.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;
- }
+ if (iattr->ia_valid & ATTR_GID)
+ wstat.n_gid = iattr->ia_gid;
}
- res = v9fs_t_wstat(v9ses, fid->fid, mistat, &fcall);
+ res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
if (res < 0)
- dprintk(DEBUG_ERROR, "wstat error: %s\n", FCALL_ERROR(fcall));
+ PRINT_FCALL_ERROR("wstat error", fcall);
- kfree(mistat);
kfree(fcall);
-
if (res >= 0)
res = inode_setattr(dentry->d_inode, iattr);
@@ -867,51 +758,47 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
}
/**
- * v9fs_mistat2inode - populate an inode structure with mistat info
- * @mistat: Plan 9 metadata (mistat) structure
+ * v9fs_stat2inode - populate an inode structure with mistat info
+ * @stat: 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)
+v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
+ struct super_block *sb)
{
+ int n;
+ char ext[32];
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_atime.tv_sec = stat->atime;
+ inode->i_mtime.tv_sec = stat->mtime;
+ inode->i_ctime.tv_sec = stat->mtime;
- inode->i_uid = -1;
- inode->i_gid = -1;
+ inode->i_uid = v9ses->uid;
+ inode->i_gid = v9ses->gid;
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);
+ inode->i_uid = stat->n_uid;
+ inode->i_gid = stat->n_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);
+ inode->i_mode = p9mode2unixmode(v9ses, stat->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);
+
+ n = stat->extension.len;
+ if (n > sizeof(ext)-1)
+ n = sizeof(ext)-1;
+ memmove(ext, stat->extension.str, n);
+ ext[n] = 0;
+ sscanf(ext, "%c %u %u", &type, &major, &minor);
switch (type) {
case 'c':
inode->i_mode &= ~S_IFBLK;
@@ -920,14 +807,14 @@ v9fs_mistat2inode(struct v9fs_stat *mistat, struct inode *inode,
case 'b':
break;
default:
- dprintk(DEBUG_ERROR, "Unknown special type %c (%s)\n",
- type, mistat->extension);
+ dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n",
+ type, stat->extension.len, stat->extension.str);
};
inode->i_rdev = MKDEV(major, minor);
} else
inode->i_rdev = 0;
- inode->i_size = mistat->length;
+ inode->i_size = stat->length;
inode->i_blksize = sb->s_blocksize;
inode->i_blocks =
@@ -955,71 +842,6 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid)
}
/**
- * 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);
-
- /* 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
@@ -1058,16 +880,17 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
if (!fcall)
return -EIO;
- if (!(fcall->params.rstat.stat->mode & V9FS_DMSYMLINK)) {
+ 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);
+ if (fcall->params.rstat.stat.extension.len < buflen)
+ buflen = fcall->params.rstat.stat.extension.len;
- memcpy(buffer, fcall->params.rstat.stat->extension, buflen + 1);
+ memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+ buffer[buflen-1] = 0;
retval = buflen;
@@ -1157,6 +980,77 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
__putname(s);
}
+static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
+ int mode, const char *extension)
+{
+ int err, retval;
+ struct v9fs_session_info *v9ses;
+ struct v9fs_fcall *fcall;
+ struct v9fs_fid *fid;
+ struct v9fs_wstat wstat;
+
+ v9ses = v9fs_inode2v9ses(dir);
+ retval = -EPERM;
+ fcall = NULL;
+
+ if (!v9ses->extended) {
+ dprintk(DEBUG_ERROR, "not extended\n");
+ goto free_mem;
+ }
+
+ /* issue a create */
+ retval = v9fs_create(dir, dentry, mode, 0);
+ if (retval != 0)
+ goto free_mem;
+
+ fid = v9fs_fid_get_created(dentry);
+ if (!fid) {
+ dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n");
+ goto free_mem;
+ }
+
+ /* issue a Twstat */
+ v9fs_blank_wstat(&wstat);
+ wstat.muid = v9ses->name;
+ wstat.extension = (char *) extension;
+ retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
+ if (retval < 0) {
+ PRINT_FCALL_ERROR("wstat error", fcall);
+ goto free_mem;
+ }
+
+ err = v9fs_t_clunk(v9ses, fid->fid);
+ if (err < 0) {
+ dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
+ goto free_mem;
+ }
+
+ d_drop(dentry); /* FID - will this also clunk? */
+
+free_mem:
+ kfree(fcall);
+ return retval;
+}
+
+/**
+ * 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)
+{
+ dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+ symname);
+
+ return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
+}
+
/**
* v9fs_vfs_link - create a hardlink
* @old_dentry: dentry for file to link to
@@ -1173,64 +1067,24 @@ 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);
- struct v9fs_fid *newfid = NULL;
- char *symname = __getname();
+ int retval;
+ struct v9fs_fid *oldfid;
+ char *name;
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);
- 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;
+ oldfid = v9fs_fid_lookup(old_dentry);
+ if (!oldfid) {
+ dprintk(DEBUG_ERROR, "can't find oldfid\n");
+ return -EPERM;
}
- d_drop(dentry); /* FID - will this also clunk? */
-
- kfree(fcall);
- fcall = NULL;
+ name = __getname();
+ sprintf(name, "hardlink(%d)\n", oldfid->fid);
+ retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
+ __putname(name);
- FreeMem:
- kfree(mistat);
- kfree(fcall);
- __putname(symname);
return retval;
}
@@ -1246,82 +1100,30 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
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();
+ int retval;
+ char *name;
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);
- if (!newfid) {
- dprintk(DEBUG_ERROR, "coudn't resove fid from dentry\n");
- retval = -EINVAL;
- goto FreeMem;
- }
+ if (!new_valid_dev(rdev))
+ return -EINVAL;
+ name = __getname();
/* build extension */
if (S_ISBLK(mode))
- sprintf(symname, "b %u %u", MAJOR(rdev), MINOR(rdev));
+ sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev));
else if (S_ISCHR(mode))
- sprintf(symname, "c %u %u", MAJOR(rdev), MINOR(rdev));
+ sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev));
else if (S_ISFIFO(mode))
- ; /* DO NOTHING */
+ *name = 0;
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;
- }
+ __putname(name);
+ return -EINVAL;
}
- /* 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);
+ retval = v9fs_vfs_mkspecial(dir, dentry, mode, name);
+ __putname(name);
return retval;
}
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 82c5b0084079..2c4fa75be025 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -44,7 +44,6 @@
#include "v9fs.h"
#include "9p.h"
#include "v9fs_vfs.h"
-#include "conv.h"
#include "fid.h"
static void v9fs_clear_inode(struct inode *);
@@ -92,7 +91,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
sb->s_op = &v9fs_super_ops;
sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
- MS_NODIRATIME | MS_NOATIME;
+ MS_NOATIME;
}
/**
@@ -123,12 +122,13 @@ static struct super_block *v9fs_get_sb(struct file_system_type
dprintk(DEBUG_VFS, " \n");
- v9ses = kcalloc(1, sizeof(struct v9fs_session_info), GFP_KERNEL);
+ v9ses = kzalloc(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");
+ kfree(v9ses);
return ERR_PTR(newfid);
}
@@ -157,7 +157,7 @@ static struct super_block *v9fs_get_sb(struct file_system_type
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_t_clunk(v9ses, newfid);
v9fs_put_idpool(newfid, &v9ses->fidpool);
} else {
/* Setup the Root Inode */
@@ -167,10 +167,10 @@ static struct super_block *v9fs_get_sb(struct file_system_type
goto put_back_sb;
}
- root_fid->qid = fcall->params.rstat.stat->qid;
+ 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);
+ v9fs_qid2ino(&fcall->params.rstat.stat.qid);
+ v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb);
}
kfree(fcall);
diff --git a/fs/Kconfig b/fs/Kconfig
index d5255e627b5f..ef78e3a42d32 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -70,6 +70,7 @@ config FS_XIP
config EXT3_FS
tristate "Ext3 journalling file system support"
+ select JBD
help
This is the journaling version of the Second extended file system
(often called ext3), the de facto standard Linux file system
@@ -138,23 +139,20 @@ config EXT3_FS_SECURITY
extended attributes for file security labels, say N.
config JBD
-# CONFIG_JBD could be its own option (even modular), but until there are
-# other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
-# dep_tristate ' Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
tristate
- default EXT3_FS
help
This is a generic journaling layer for block devices. It is
- currently used by the ext3 file system, but it could also be used to
- add journal support to other file systems or block devices such as
- RAID or LVM.
+ currently used by the ext3 and OCFS2 file systems, but it could
+ also be used to add journal support to other file systems or block
+ devices such as RAID or LVM.
- If you are using the ext3 file system, you need to say Y here. If
- you are not using ext3 then you will probably want to say N.
+ If you are using the ext3 or OCFS2 file systems, you need to
+ say Y here. If you are not using ext3 OCFS2 then you will probably
+ want to say N.
To compile this device as a module, choose M here: the module will be
- called jbd. If you are compiling ext3 into the kernel, you cannot
- compile this code as a module.
+ called jbd. If you are compiling ext3 or OCFS2 into the kernel,
+ you cannot compile this code as a module.
config JBD_DEBUG
bool "JBD (ext3) debugging support"
@@ -326,6 +324,38 @@ config FS_POSIX_ACL
source "fs/xfs/Kconfig"
+config OCFS2_FS
+ tristate "OCFS2 file system support (EXPERIMENTAL)"
+ depends on NET && EXPERIMENTAL
+ select CONFIGFS_FS
+ select JBD
+ select CRC32
+ select INET
+ help
+ OCFS2 is a general purpose extent based shared disk cluster file
+ system with many similarities to ext3. It supports 64 bit inode
+ numbers, and has automatically extending metadata groups which may
+ also make it attractive for non-clustered use.
+
+ You'll want to install the ocfs2-tools package in order to at least
+ get "mount.ocfs2".
+
+ Project web page: http://oss.oracle.com/projects/ocfs2
+ Tools web page: http://oss.oracle.com/projects/ocfs2-tools
+ OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
+
+ Note: Features which OCFS2 does not support yet:
+ - extended attributes
+ - shared writeable mmap
+ - loopback is supported, but data written will not
+ be cluster coherent.
+ - quotas
+ - cluster aware flock
+ - Directory change notification (F_NOTIFY)
+ - Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
+ - POSIX ACLs
+ - readpages / writepages (not user visible)
+
config MINIX_FS
tristate "Minix fs support"
help
@@ -768,7 +798,7 @@ config PROC_KCORE
config PROC_VMCORE
bool "/proc/vmcore support (EXPERIMENTAL)"
- depends on PROC_FS && EMBEDDED && EXPERIMENTAL && CRASH_DUMP
+ depends on PROC_FS && EXPERIMENTAL && CRASH_DUMP
help
Exports the dump image of crashed kernel in ELF format.
@@ -841,6 +871,20 @@ config RELAYFS_FS
If unsure, say N.
+config CONFIGFS_FS
+ tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ configfs is a ram-based filesystem that provides the converse
+ of sysfs's functionality. Where sysfs is a filesystem-based
+ view of kernel objects, configfs is a filesystem-based manager
+ of kernel objects, or config_items.
+
+ Both sysfs and configfs can and should exist together on the
+ same system. One is not a replacement for the other.
+
+ If unsure, say N.
+
endmenu
menu "Miscellaneous filesystems"
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 175b2e8177c1..f3d3d81eb7e9 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -1,6 +1,6 @@
config BINFMT_ELF
bool "Kernel support for ELF binaries"
- depends on MMU
+ depends on MMU && (BROKEN || !FRV)
default y
---help---
ELF (Executable and Linkable Format) is a format for libraries and
diff --git a/fs/Makefile b/fs/Makefile
index 4c2655759078..1db711319c80 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -10,11 +10,11 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \
ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
- ioprio.o pnode.o
+ ioprio.o pnode.o drop_caches.o
obj-$(CONFIG_INOTIFY) += inotify.o
obj-$(CONFIG_EPOLL) += eventpoll.o
-obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
nfsd-$(CONFIG_NFSD) := nfsctl.o
obj-y += $(nfsd-y) $(nfsd-m)
@@ -101,3 +101,5 @@ obj-$(CONFIG_BEFS_FS) += befs/
obj-$(CONFIG_HOSTFS) += hostfs/
obj-$(CONFIG_HPPFS) += hppfs/
obj-$(CONFIG_DEBUG_FS) += debugfs/
+obj-$(CONFIG_CONFIGFS_FS) += configfs/
+obj-$(CONFIG_OCFS2_FS) += ocfs2/
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 9ebe881c6786..44d439cb69f4 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -244,10 +244,10 @@ affs_put_inode(struct inode *inode)
pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
affs_free_prealloc(inode);
if (atomic_read(&inode->i_count) == 1) {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (inode->i_size != AFFS_I(inode)->mmu_private)
affs_truncate(inode);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
}
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 0a57fd7c726f..9eef6bf156ab 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -118,7 +118,7 @@ static int kafscmd(void *arg)
_SRXAFSCM_xxxx_t func;
int die;
- printk("kAFS: Started kafscmd %d\n", current->pid);
+ printk(KERN_INFO "kAFS: Started kafscmd %d\n", current->pid);
daemonize("kafscmd");
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 6682d6d7f294..5c61c24dab2a 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -137,7 +137,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
#endif
/* determine how many magic numbers there should be in this page */
- latter = dir->i_size - (page->index << PAGE_CACHE_SHIFT);
+ latter = dir->i_size - page_offset(page);
if (latter >= PAGE_SIZE)
qty = PAGE_SIZE;
else
diff --git a/fs/afs/volume.h b/fs/afs/volume.h
index 1e691889c4c9..bfdcf19ba3f3 100644
--- a/fs/afs/volume.h
+++ b/fs/afs/volume.h
@@ -18,8 +18,6 @@
#include "kafsasyncd.h"
#include "cache.h"
-#define __packed __attribute__((packed))
-
typedef enum {
AFS_VLUPD_SLEEP, /* sleeping waiting for update timer to fire */
AFS_VLUPD_PENDING, /* on pending queue */
@@ -115,7 +113,7 @@ struct afs_volume
struct cachefs_cookie *cache; /* caching cookie */
#endif
afs_volid_t vid; /* volume ID */
- afs_voltype_t __packed type; /* type of volume */
+ afs_voltype_t type; /* type of volume */
char type_force; /* force volume type (suppress R/O -> R/W) */
unsigned short nservers; /* number of server slots filled */
unsigned short rjservers; /* number of servers discarded due to -ENOMEDIUM */
diff --git a/fs/aio.c b/fs/aio.c
index 5a28b69ad223..aec2b1916d1b 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -29,7 +29,6 @@
#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>
@@ -514,7 +513,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(rcuref_dec_and_test(&req->ki_filp->f_count))) {
+ if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) {
get_ioctx(ctx);
spin_lock(&fput_lock);
list_add(&req->ki_list, &fput_head);
diff --git a/fs/attr.c b/fs/attr.c
index 67bcd9b14ea5..97de94670878 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -10,11 +10,11 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
+#include <linux/capability.h>
#include <linux/fsnotify.h>
#include <linux/fcntl.h>
#include <linux/quotaops.h>
#include <linux/security.h>
-#include <linux/time.h>
/* Taken over from the old code... */
@@ -67,20 +67,12 @@ EXPORT_SYMBOL(inode_change_ok);
int inode_setattr(struct inode * inode, struct iattr * attr)
{
unsigned int ia_valid = attr->ia_valid;
- int error = 0;
-
- if (ia_valid & ATTR_SIZE) {
- if (attr->ia_size != i_size_read(inode)) {
- error = vmtruncate(inode, attr->ia_size);
- if (error || (ia_valid == ATTR_SIZE))
- goto out;
- } else {
- /*
- * We skipped the truncate but must still update
- * timestamps
- */
- ia_valid |= ATTR_MTIME|ATTR_CTIME;
- }
+
+ if (ia_valid & ATTR_SIZE &&
+ attr->ia_size != i_size_read(inode)) {
+ int error = vmtruncate(inode, attr->ia_size);
+ if (error)
+ return error;
}
if (ia_valid & ATTR_UID)
@@ -104,8 +96,8 @@ int inode_setattr(struct inode * inode, struct iattr * attr)
inode->i_mode = mode;
}
mark_inode_dirty(inode);
-out:
- return error;
+
+ return 0;
}
EXPORT_SYMBOL(inode_setattr);
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index a1ab1c0ed215..870e2cf33016 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -10,6 +10,7 @@
*
* ------------------------------------------------------------------------- */
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
@@ -229,9 +230,9 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
dentry->d_flags |= DCACHE_AUTOFS_PENDING;
d_add(dentry, NULL);
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
autofs_revalidate(dentry, nd);
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
/*
* If we are still pending, check if we had to handle
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index fca83e28edcf..385bed09b0d8 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -209,7 +209,7 @@ static inline int simple_empty_nolock(struct dentry *dentry)
struct dentry *child;
int ret = 0;
- list_for_each_entry(child, &dentry->d_subdirs, d_child)
+ list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
if (simple_positive(child))
goto out;
ret = 1;
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index feb6ac427d05..dc39589df165 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -105,7 +105,7 @@ repeat:
next = this_parent->d_subdirs.next;
resume:
while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_child);
+ struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
if (!simple_positive(dentry)) {
@@ -138,7 +138,7 @@ resume:
}
if (this_parent != top) {
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
goto resume;
}
@@ -163,7 +163,7 @@ repeat:
next = this_parent->d_subdirs.next;
resume:
while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_child);
+ struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
if (!simple_positive(dentry)) {
@@ -199,7 +199,7 @@ cont:
}
if (this_parent != parent) {
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
goto resume;
}
@@ -238,7 +238,7 @@ static struct dentry *autofs4_expire(struct super_block *sb,
/* On exit from the loop expire is set to a dgot dentry
* to expire or it's NULL */
while ( next != &root->d_subdirs ) {
- struct dentry *dentry = list_entry(next, struct dentry, d_child);
+ struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - give up */
if ( !simple_positive(dentry) ) {
@@ -302,7 +302,7 @@ next:
expired, (int)expired->d_name.len, expired->d_name.name);
spin_lock(&dcache_lock);
list_del(&expired->d_parent->d_subdirs);
- list_add(&expired->d_parent->d_subdirs, &expired->d_child);
+ list_add(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
spin_unlock(&dcache_lock);
return expired;
}
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 818b37be5153..2d3082854a29 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -91,7 +91,7 @@ repeat:
next = this_parent->d_subdirs.next;
resume:
while (next != &this_parent->d_subdirs) {
- struct dentry *dentry = list_entry(next, struct dentry, d_child);
+ struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child);
/* Negative dentry - don`t care */
if (!simple_positive(dentry)) {
@@ -117,7 +117,7 @@ resume:
if (this_parent != sbi->root) {
struct dentry *dentry = this_parent;
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
spin_unlock(&dcache_lock);
DPRINTK("parent dentry %p %.*s",
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 2a771ec66956..62d8d4acb8bb 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -12,6 +12,7 @@
*
* ------------------------------------------------------------------------- */
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
@@ -86,7 +87,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent,
/* Update usage from here to top of tree, so that scan of
top-level directories will give a useful result */
-static void autofs4_update_usage(struct dentry *dentry)
+static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry)
{
struct dentry *top = dentry->d_sb->s_root;
@@ -95,7 +96,7 @@ static void autofs4_update_usage(struct dentry *dentry)
struct autofs_info *ino = autofs4_dentry_ino(dentry);
if (ino) {
- update_atime(dentry->d_inode);
+ touch_atime(mnt, dentry);
ino->last_used = jiffies;
}
}
@@ -143,7 +144,8 @@ static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t f
}
while(1) {
- struct dentry *de = list_entry(list, struct dentry, d_child);
+ struct dentry *de = list_entry(list,
+ struct dentry, d_u.d_child);
if (!d_unhashed(de) && de->d_inode) {
spin_unlock(&dcache_lock);
@@ -193,6 +195,8 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
if (!empty)
d_invalidate(dentry);
+ nd.dentry = dentry;
+ nd.mnt = mnt;
nd.flags = LOOKUP_DIRECTORY;
status = (dentry->d_op->d_revalidate)(dentry, &nd);
@@ -288,10 +292,10 @@ out:
return autofs4_dcache_readdir(file, dirent, filldir);
}
-static int try_to_fill_dentry(struct dentry *dentry,
- struct super_block *sb,
- struct autofs_sb_info *sbi, int flags)
+static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags)
{
+ struct super_block *sb = mnt->mnt_sb;
+ struct autofs_sb_info *sbi = autofs4_sbi(sb);
struct autofs_info *de_info = autofs4_dentry_ino(dentry);
int status = 0;
@@ -366,7 +370,7 @@ static int try_to_fill_dentry(struct dentry *dentry,
/* We don't update the usages for the autofs daemon itself, this
is necessary for recursive autofs mounts */
if (!autofs4_oz_mode(sbi))
- autofs4_update_usage(dentry);
+ autofs4_update_usage(mnt, dentry);
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
@@ -391,7 +395,7 @@ static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
/* Pending dentry */
if (autofs4_ispending(dentry)) {
if (!oz_mode)
- status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
+ status = try_to_fill_dentry(nd->mnt, dentry, flags);
return status;
}
@@ -408,14 +412,14 @@ static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd)
dentry, dentry->d_name.len, dentry->d_name.name);
spin_unlock(&dcache_lock);
if (!oz_mode)
- status = try_to_fill_dentry(dentry, dir->i_sb, sbi, flags);
+ status = try_to_fill_dentry(nd->mnt, dentry, flags);
return status;
}
spin_unlock(&dcache_lock);
/* Update the usage list */
if (!oz_mode)
- autofs4_update_usage(dentry);
+ autofs4_update_usage(nd->mnt, dentry);
return 1;
}
@@ -488,9 +492,9 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s
d_add(dentry, NULL);
if (dentry->d_op && dentry->d_op->d_revalidate) {
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
(dentry->d_op->d_revalidate)(dentry, nd);
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
}
/*
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 72011826f0cb..f312103434d4 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -33,8 +33,6 @@ static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(struct file*);
static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
-extern void dump_thread(struct pt_regs *, struct user *);
-
static struct linux_binfmt aout_format = {
.module = THIS_MODULE,
.load_binary = load_aout_binary,
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index f36f2210204f..1b117a441298 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -58,7 +58,7 @@ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
* If we don't support core dumping, then supply a NULL so we
* don't even try.
*/
-#ifdef USE_ELF_CORE_DUMP
+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file);
#else
#define elf_core_dump NULL
@@ -288,11 +288,17 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
struct elf_phdr *eppnt, int prot, int type)
{
unsigned long map_addr;
+ unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
down_write(&current->mm->mmap_sem);
- map_addr = do_mmap(filep, ELF_PAGESTART(addr),
- eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,
- eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
+ /* mmap() will return -EINVAL if given a zero size, but a
+ * segment with zero filesize is perfectly valid */
+ if (eppnt->p_filesz + pageoffset)
+ map_addr = do_mmap(filep, ELF_PAGESTART(addr),
+ eppnt->p_filesz + pageoffset, prot, type,
+ eppnt->p_offset - pageoffset);
+ else
+ map_addr = ELF_PAGESTART(addr);
up_write(&current->mm->mmap_sem);
return(map_addr);
}
@@ -616,7 +622,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out_free_file;
retval = -ENOMEM;
- elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
+ elf_interpreter = kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL);
if (!elf_interpreter)
goto out_free_file;
@@ -1107,7 +1113,7 @@ out:
* Note that some platforms still use traditional core dumps and not
* the ELF core dump. Each platform can select it as appropriate.
*/
-#ifdef USE_ELF_CORE_DUMP
+#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
/*
* ELF core dumper
@@ -1212,7 +1218,7 @@ static int writenote(struct memelfnote *men, struct file *file)
if (!dump_seek(file, (off))) \
goto end_coredump;
-static inline void fill_elf_header(struct elfhdr *elf, int segs)
+static void fill_elf_header(struct elfhdr *elf, int segs)
{
memcpy(elf->e_ident, ELFMAG, SELFMAG);
elf->e_ident[EI_CLASS] = ELF_CLASS;
@@ -1237,7 +1243,7 @@ static inline void fill_elf_header(struct elfhdr *elf, int segs)
return;
}
-static inline void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
+static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
{
phdr->p_type = PT_NOTE;
phdr->p_offset = offset;
@@ -1628,17 +1634,17 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
ELF_CORE_WRITE_EXTRA_DATA;
#endif
- if ((off_t) file->f_pos != offset) {
+ if ((off_t)file->f_pos != offset) {
/* Sanity check */
- printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
- (off_t) file->f_pos, offset);
+ printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
+ (off_t)file->f_pos, offset);
}
end_coredump:
set_fs(fs);
cleanup:
- while(!list_empty(&thread_list)) {
+ while (!list_empty(&thread_list)) {
struct list_head *tmp = thread_list.next;
list_del(tmp);
kfree(list_entry(tmp, struct elf_thread_status, list));
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index e0344f69c79d..5b3076e8ee90 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -187,7 +187,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
goto error;
/* read the name of the interpreter into memory */
- interpreter_name = (char *) kmalloc(phdr->p_filesz, GFP_KERNEL);
+ interpreter_name = kmalloc(phdr->p_filesz, GFP_KERNEL);
if (!interpreter_name)
goto error;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 9d6625829b99..108d56bbd0d0 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -77,8 +77,6 @@ static int load_flat_shared_library(int id, struct lib_info *p);
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
-extern void dump_thread(struct pt_regs *, struct user *);
-
static struct linux_binfmt flat_format = {
.module = THIS_MODULE,
.load_binary = load_flat_binary,
@@ -444,19 +442,22 @@ static int load_flat_file(struct linux_binprm * bprm,
flags = ntohl(hdr->flags);
rev = ntohl(hdr->rev);
- if (flags & FLAT_FLAG_KTRACE)
- printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
-
- if (strncmp(hdr->magic, "bFLT", 4) ||
- (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION)) {
+ if (strncmp(hdr->magic, "bFLT", 4)) {
/*
* because a lot of people do not manage to produce good
* flat binaries, we leave this printk to help them realise
* the problem. We only print the error if its not a script file
*/
if (strncmp(hdr->magic, "#!", 2))
- printk("BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
- rev, (int) FLAT_VERSION);
+ printk("BINFMT_FLAT: bad header magic\n");
+ return -ENOEXEC;
+ }
+
+ if (flags & FLAT_FLAG_KTRACE)
+ printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
+
+ if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
+ printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
return -ENOEXEC;
}
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 2568eb41cb3a..6a7b730c206b 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -264,7 +264,7 @@ static int unquote(char *from)
return p - from;
}
-static inline char * check_special_flags (char * sfs, Node * e)
+static char * check_special_flags (char * sfs, Node * e)
{
char * p = sfs;
int cont = 1;
@@ -588,11 +588,11 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
case 2: set_bit(Enabled, &e->flags);
break;
case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
kill_node(e);
- up(&root->d_inode->i_sem);
+ mutex_unlock(&root->d_inode->i_mutex);
dput(root);
break;
default: return res;
@@ -622,7 +622,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
return PTR_ERR(e);
root = dget(sb->s_root);
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
dentry = lookup_one_len(e->name, root, strlen(e->name));
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
@@ -658,7 +658,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
out2:
dput(dentry);
out:
- up(&root->d_inode->i_sem);
+ mutex_unlock(&root->d_inode->i_mutex);
dput(root);
if (err) {
@@ -703,12 +703,12 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer,
case 1: enabled = 0; break;
case 2: enabled = 1; break;
case 3: root = dget(file->f_vfsmnt->mnt_sb->s_root);
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
while (!list_empty(&entries))
kill_node(list_entry(entries.next, Node, list));
- up(&root->d_inode->i_sem);
+ mutex_unlock(&root->d_inode->i_mutex);
dput(root);
default: return res;
}
diff --git a/fs/bio.c b/fs/bio.c
index 460554b07ff9..bbc442b8c867 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -123,9 +123,10 @@ static void bio_fs_destructor(struct bio *bio)
bio_free(bio, fs_bio_set);
}
-inline void bio_init(struct bio *bio)
+void bio_init(struct bio *bio)
{
bio->bi_next = NULL;
+ bio->bi_bdev = NULL;
bio->bi_flags = 1 << BIO_UPTODATE;
bio->bi_rw = 0;
bio->bi_vcnt = 0;
@@ -252,7 +253,7 @@ inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
* the actual data it points to. Reference count of returned
* bio will be one.
*/
-inline void __bio_clone(struct bio *bio, struct bio *bio_src)
+void __bio_clone(struct bio *bio, struct bio *bio_src)
{
request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
@@ -313,7 +314,8 @@ int bio_get_nr_vecs(struct block_device *bdev)
}
static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
- *page, unsigned int len, unsigned int offset)
+ *page, unsigned int len, unsigned int offset,
+ unsigned short max_sectors)
{
int retried_segments = 0;
struct bio_vec *bvec;
@@ -324,10 +326,31 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
if (unlikely(bio_flagged(bio, BIO_CLONED)))
return 0;
- if (bio->bi_vcnt >= bio->bi_max_vecs)
+ if (((bio->bi_size + len) >> 9) > max_sectors)
return 0;
- if (((bio->bi_size + len) >> 9) > q->max_sectors)
+ /*
+ * For filesystems with a blocksize smaller than the pagesize
+ * we will often be called with the same page as last time and
+ * a consecutive offset. Optimize this special case.
+ */
+ if (bio->bi_vcnt > 0) {
+ struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1];
+
+ if (page == prev->bv_page &&
+ offset == prev->bv_offset + prev->bv_len) {
+ prev->bv_len += len;
+ if (q->merge_bvec_fn &&
+ q->merge_bvec_fn(q, bio, prev) < len) {
+ prev->bv_len -= len;
+ return 0;
+ }
+
+ goto done;
+ }
+ }
+
+ if (bio->bi_vcnt >= bio->bi_max_vecs)
return 0;
/*
@@ -381,11 +404,31 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
bio->bi_vcnt++;
bio->bi_phys_segments++;
bio->bi_hw_segments++;
+ done:
bio->bi_size += len;
return len;
}
/**
+ * bio_add_pc_page - attempt to add page to bio
+ * @bio: destination bio
+ * @page: page to add
+ * @len: vec entry length
+ * @offset: vec entry offset
+ *
+ * Attempt to add a page to the bio_vec maplist. This can fail for a
+ * number of reasons, such as the bio being full or target block
+ * device limitations. The target block device must allow bio's
+ * smaller than PAGE_SIZE, so it is always possible to add a single
+ * page to an empty bio. This should only be used by REQ_PC bios.
+ */
+int bio_add_pc_page(request_queue_t *q, struct bio *bio, struct page *page,
+ unsigned int len, unsigned int offset)
+{
+ return __bio_add_page(q, bio, page, len, offset, q->max_hw_sectors);
+}
+
+/**
* bio_add_page - attempt to add page to bio
* @bio: destination bio
* @page: page to add
@@ -401,8 +444,8 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
unsigned int offset)
{
- return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page,
- len, offset);
+ struct request_queue *q = bdev_get_queue(bio->bi_bdev);
+ return __bio_add_page(q, bio, page, len, offset, q->max_sectors);
}
struct bio_map_data {
@@ -514,7 +557,7 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
break;
}
- if (__bio_add_page(q, bio, page, bytes, 0) < bytes) {
+ if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
ret = -EINVAL;
break;
}
@@ -628,7 +671,8 @@ static struct bio *__bio_map_user_iov(request_queue_t *q,
/*
* sorry...
*/
- if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes)
+ if (bio_add_pc_page(q, bio, pages[j], bytes, offset) <
+ bytes)
break;
len -= bytes;
@@ -801,8 +845,8 @@ static struct bio *__bio_map_kern(request_queue_t *q, void *data,
if (bytes > len)
bytes = len;
- if (__bio_add_page(q, bio, virt_to_page(data), bytes,
- offset) < bytes)
+ if (bio_add_pc_page(q, bio, virt_to_page(data), bytes,
+ offset) < bytes)
break;
data += bytes;
@@ -1228,6 +1272,7 @@ EXPORT_SYMBOL(bio_clone);
EXPORT_SYMBOL(bio_phys_segments);
EXPORT_SYMBOL(bio_hw_segments);
EXPORT_SYMBOL(bio_add_page);
+EXPORT_SYMBOL(bio_add_pc_page);
EXPORT_SYMBOL(bio_get_nr_vecs);
EXPORT_SYMBOL(bio_map_user);
EXPORT_SYMBOL(bio_unmap_user);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index e0df94c37b7e..6e50346fb1ee 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -202,7 +202,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
loff_t size;
loff_t retval;
- down(&bd_inode->i_sem);
+ mutex_lock(&bd_inode->i_mutex);
size = i_size_read(bd_inode);
switch (origin) {
@@ -219,7 +219,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
}
retval = offset;
}
- up(&bd_inode->i_sem);
+ mutex_unlock(&bd_inode->i_mutex);
return retval;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 5287be18633b..3dc712f29d2d 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -26,6 +26,7 @@
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
+#include <linux/capability.h>
#include <linux/blkdev.h>
#include <linux/file.h>
#include <linux/quotaops.h>
@@ -153,14 +154,8 @@ int sync_blockdev(struct block_device *bdev)
{
int ret = 0;
- if (bdev) {
- int err;
-
- ret = filemap_fdatawrite(bdev->bd_inode->i_mapping);
- err = filemap_fdatawait(bdev->bd_inode->i_mapping);
- if (!ret)
- ret = err;
- }
+ if (bdev)
+ ret = filemap_write_and_wait(bdev->bd_inode->i_mapping);
return ret;
}
EXPORT_SYMBOL(sync_blockdev);
@@ -358,11 +353,11 @@ static long do_fsync(unsigned int fd, int datasync)
* We need to protect against concurrent writers,
* which could cause livelocks in fsync_buffers_list
*/
- down(&mapping->host->i_sem);
+ mutex_lock(&mapping->host->i_mutex);
err = file->f_op->fsync(file, file->f_dentry, datasync);
if (!ret)
ret = err;
- up(&mapping->host->i_sem);
+ mutex_unlock(&mapping->host->i_mutex);
err = filemap_fdatawait(mapping);
if (!ret)
ret = err;
@@ -1032,7 +1027,7 @@ try_again:
/* Link the buffer to its page */
set_bh_page(bh, page, offset);
- bh->b_end_io = NULL;
+ init_buffer(bh, NULL, NULL);
}
return head;
/*
@@ -1170,7 +1165,7 @@ failed:
* some of those buffers may be aliases of filesystem data.
* grow_dev_page() will go BUG() if this happens.
*/
-static inline int
+static int
grow_buffers(struct block_device *bdev, sector_t block, int size)
{
struct page *page;
@@ -1396,7 +1391,7 @@ static void bh_lru_install(struct buffer_head *bh)
/*
* Look up the bh in this cpu's LRU. If it's there, move it to the head.
*/
-static inline struct buffer_head *
+static struct buffer_head *
lookup_bh_lru(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *ret = NULL;
@@ -1546,7 +1541,7 @@ EXPORT_SYMBOL(set_bh_page);
/*
* Called when truncating a buffer on a page completely.
*/
-static inline void discard_buffer(struct buffer_head * bh)
+static void discard_buffer(struct buffer_head * bh)
{
lock_buffer(bh);
clear_buffer_dirty(bh);
@@ -1768,7 +1763,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
* handle that here by just cleaning them.
*/
- block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
head = page_buffers(page);
bh = head;
@@ -2160,11 +2155,12 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
* truncates. Uses prepare/commit_write to allow the filesystem to
* deal with the hole.
*/
-int generic_cont_expand(struct inode *inode, loff_t size)
+static int __generic_cont_expand(struct inode *inode, loff_t size,
+ pgoff_t index, unsigned int offset)
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
- unsigned long index, offset, limit;
+ unsigned long limit;
int err;
err = -EFBIG;
@@ -2176,24 +2172,24 @@ int generic_cont_expand(struct inode *inode, loff_t size)
if (size > inode->i_sb->s_maxbytes)
goto out;
- offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
-
- /* ugh. in prepare/commit_write, if from==to==start of block, we
- ** skip the prepare. make sure we never send an offset for the start
- ** of a block
- */
- if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) {
- offset++;
- }
- index = size >> PAGE_CACHE_SHIFT;
err = -ENOMEM;
page = grab_cache_page(mapping, index);
if (!page)
goto out;
err = mapping->a_ops->prepare_write(NULL, page, offset, offset);
- if (!err) {
- err = mapping->a_ops->commit_write(NULL, page, offset, offset);
+ if (err) {
+ /*
+ * ->prepare_write() may have instantiated a few blocks
+ * outside i_size. Trim these off again.
+ */
+ unlock_page(page);
+ page_cache_release(page);
+ vmtruncate(inode, inode->i_size);
+ goto out;
}
+
+ err = mapping->a_ops->commit_write(NULL, page, offset, offset);
+
unlock_page(page);
page_cache_release(page);
if (err > 0)
@@ -2202,6 +2198,36 @@ out:
return err;
}
+int generic_cont_expand(struct inode *inode, loff_t size)
+{
+ pgoff_t index;
+ unsigned int offset;
+
+ offset = (size & (PAGE_CACHE_SIZE - 1)); /* Within page */
+
+ /* ugh. in prepare/commit_write, if from==to==start of block, we
+ ** skip the prepare. make sure we never send an offset for the start
+ ** of a block
+ */
+ if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) {
+ /* caller must handle this extra byte. */
+ offset++;
+ }
+ index = size >> PAGE_CACHE_SHIFT;
+
+ return __generic_cont_expand(inode, size, index, offset);
+}
+
+int generic_cont_expand_simple(struct inode *inode, loff_t size)
+{
+ loff_t pos = size - 1;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+ unsigned int offset = (pos & (PAGE_CACHE_SIZE - 1)) + 1;
+
+ /* prepare/commit_write can handle even if from==to==start of block. */
+ return __generic_cont_expand(inode, size, index, offset);
+}
+
/*
* For moronic filesystems that do not allow holes in file.
* We may have to extend the file.
@@ -2313,7 +2339,7 @@ int generic_commit_write(struct file *file, struct page *page,
__block_commit_write(inode,page,from,to);
/*
* No need to use i_size_read() here, the i_size
- * cannot change under us because we hold i_sem.
+ * cannot change under us because we hold i_mutex.
*/
if (pos > inode->i_size) {
i_size_write(inode, pos);
@@ -2610,7 +2636,7 @@ int block_truncate_page(struct address_space *mapping,
pgoff_t index = from >> PAGE_CACHE_SHIFT;
unsigned offset = from & (PAGE_CACHE_SIZE-1);
unsigned blocksize;
- pgoff_t iblock;
+ sector_t iblock;
unsigned length, pos;
struct inode *inode = mapping->host;
struct page *page;
@@ -2626,7 +2652,7 @@ int block_truncate_page(struct address_space *mapping,
return 0;
length = blocksize - length;
- iblock = index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+ iblock = (sector_t)index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
page = grab_cache_page(mapping, index);
err = -ENOMEM;
@@ -3145,6 +3171,7 @@ EXPORT_SYMBOL(fsync_bdev);
EXPORT_SYMBOL(generic_block_bmap);
EXPORT_SYMBOL(generic_commit_write);
EXPORT_SYMBOL(generic_cont_expand);
+EXPORT_SYMBOL(generic_cont_expand_simple);
EXPORT_SYMBOL(init_buffer);
EXPORT_SYMBOL(invalidate_bdev);
EXPORT_SYMBOL(ll_rw_block);
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 3b1b1eefdbb0..21195c481637 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -35,7 +35,7 @@ static struct char_device_struct {
unsigned int major;
unsigned int baseminor;
int minorct;
- const char *name;
+ char name[64];
struct file_operations *fops;
struct cdev *cdev; /* will die */
} *chrdevs[MAX_PROBE_HASH];
@@ -46,34 +46,84 @@ static inline int major_to_index(int major)
return major % MAX_PROBE_HASH;
}
-/* get char device names in somewhat random order */
-int get_chrdev_list(char *page)
-{
+struct chrdev_info {
+ int index;
struct char_device_struct *cd;
- int i, len;
+};
- len = sprintf(page, "Character devices:\n");
+void *get_next_chrdev(void *dev)
+{
+ struct chrdev_info *info;
+ if (dev == NULL) {
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ goto out;
+ info->index=0;
+ info->cd = chrdevs[info->index];
+ if (info->cd)
+ goto out;
+ } else {
+ info = dev;
+ }
+
+ while (info->index < ARRAY_SIZE(chrdevs)) {
+ if (info->cd)
+ info->cd = info->cd->next;
+ if (info->cd)
+ goto out;
+ /*
+ * No devices on this chain, move to the next
+ */
+ info->index++;
+ info->cd = (info->index < ARRAY_SIZE(chrdevs)) ?
+ chrdevs[info->index] : NULL;
+ if (info->cd)
+ goto out;
+ }
+
+out:
+ return info;
+}
+
+void *acquire_chrdev_list(void)
+{
down(&chrdevs_lock);
+ return get_next_chrdev(NULL);
+}
+
+void release_chrdev_list(void *dev)
+{
+ up(&chrdevs_lock);
+ kfree(dev);
+}
+
+
+int count_chrdev_list(void)
+{
+ struct char_device_struct *cd;
+ int i, count;
+
+ count = 0;
+
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
- for (cd = chrdevs[i]; cd; cd = cd->next) {
- /*
- * if the current name, plus the 5 extra characters
- * in the device line for this entry
- * would run us off the page, we're done
- */
- if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
- goto page_full;
-
-
- len += sprintf(page+len, "%3d %s\n",
- cd->major, cd->name);
- }
+ for (cd = chrdevs[i]; cd; cd = cd->next)
+ count++;
}
-page_full:
- up(&chrdevs_lock);
- return len;
+ return count;
+}
+
+int get_chrdev_info(void *dev, int *major, char **name)
+{
+ struct chrdev_info *info = dev;
+
+ if (info->cd == NULL)
+ return 1;
+
+ *major = info->cd->major;
+ *name = info->cd->name;
+ return 0;
}
/*
@@ -121,7 +171,7 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor,
cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
- cd->name = name;
+ strncpy(cd->name,name, 64);
i = major_to_index(major);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 943ef9b82244..d335015473a5 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,11 @@
+Version 1.40
+------------
+Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
+of readpages by eliminating one extra memcpy. Allow update of file size
+from remote server even if file is open for write as long as mount is
+directio. Recognize share mode security and send NTLM encrypted password
+on tree connect if share mode negotiated.
+
Version 1.39
------------
Defer close of a file handle slightly if pending writes depend on that handle
@@ -7,6 +15,8 @@ Fix SFU style symlinks and mknod needed for servers which do not support the
CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative
dentries so files that the client sees as deleted but that later get created
on the server will be recognized. Add client side permission check on setattr.
+Timeout stuck requests better (where server has never responded or sent corrupt
+responses)
Version 1.38
------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e5d09a2fc7a5..b0070d1b149d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -436,7 +436,17 @@ A partial list of the supported mount options follows:
SFU does). In the future the bottom 9 bits of the mode
mode also will be emulated using queries of the security
descriptor (ACL).
-
+sec Security mode. Allowed values are:
+ none attempt to connection as a null user (no name)
+ krb5 Use Kerberos version 5 authentication
+ krb5i Use Kerberos authentication and packet signing
+ ntlm Use NTLM password hashing (default)
+ ntlmi Use NTLM password hashing with signing (if
+ /proc/fs/cifs/PacketSigningEnabled on or if
+ server requires signing also can be the default)
+ ntlmv2 Use NTLMv2 password hashing
+ ntlmv2i Use NTLMv2 password hashing with packet signing
+
The mount.cifs mount helper also accepts a few mount options before -o
including:
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 22a444a3fe4c..f4124a32bef8 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -219,6 +219,10 @@ cifs_stats_write(struct file *file, const char __user *buffer,
if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
read_lock(&GlobalSMBSeslock);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_set(&totBufAllocCount, 0);
+ atomic_set(&totSmBufAllocCount, 0);
+#endif /* CONFIG_CIFS_STATS2 */
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo,
cifsConnectionList);
@@ -276,6 +280,14 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
smBufAllocCount.counter,cifs_min_small);
length += item_length;
buf += item_length;
+#ifdef CONFIG_CIFS_STATS2
+ item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+ atomic_read(&totBufAllocCount),
+ atomic_read(&totSmBufAllocCount));
+ length += item_length;
+ buf += item_length;
+#endif /* CONFIG_CIFS_STATS2 */
+
item_length =
sprintf(buf,"Operations (MIDs): %d\n",
midCount.counter);
@@ -389,8 +401,8 @@ static read_proc_t ntlmv2_enabled_read;
static write_proc_t ntlmv2_enabled_write;
static read_proc_t packet_signing_enabled_read;
static write_proc_t packet_signing_enabled_write;
-static read_proc_t quotaEnabled_read;
-static write_proc_t quotaEnabled_write;
+static read_proc_t experimEnabled_read;
+static write_proc_t experimEnabled_write;
static read_proc_t linuxExtensionsEnabled_read;
static write_proc_t linuxExtensionsEnabled_write;
@@ -430,9 +442,9 @@ cifs_proc_init(void)
pde->write_proc = oplockEnabled_write;
pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs,
- quotaEnabled_read, NULL);
+ experimEnabled_read, NULL);
if (pde)
- pde->write_proc = quotaEnabled_write;
+ pde->write_proc = experimEnabled_write;
pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
linuxExtensionsEnabled_read, NULL);
@@ -574,14 +586,13 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
}
static int
-quotaEnabled_read(char *page, char **start, off_t off,
+experimEnabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len;
len = sprintf(page, "%d\n", experimEnabled);
-/* could also check if quotas are enabled in kernel
- as a whole first */
+
len -= off;
*start = page + off;
@@ -596,21 +607,23 @@ quotaEnabled_read(char *page, char **start, off_t off,
return len;
}
static int
-quotaEnabled_write(struct file *file, const char __user *buffer,
+experimEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
- char c;
- int rc;
+ char c;
+ int rc;
- rc = get_user(c, buffer);
- if (rc)
- return rc;
- if (c == '0' || c == 'n' || c == 'N')
- experimEnabled = 0;
- else if (c == '1' || c == 'y' || c == 'Y')
- experimEnabled = 1;
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ experimEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ experimEnabled = 1;
+ else if (c == '2')
+ experimEnabled = 2;
- return count;
+ return count;
}
static int
@@ -620,8 +633,6 @@ linuxExtensionsEnabled_read(char *page, char **start, off_t off,
int len;
len = sprintf(page, "%d\n", linuxExtEnabled);
-/* could also check if quotas are enabled in kernel
- as a whole first */
len -= off;
*start = page + off;
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index f799f6f0e729..ad58eb0c4d6d 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -24,9 +24,10 @@
#define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */
#define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */
#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */
-#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
-#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
+#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */
+#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */
#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */
+#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
index decd138f14d4..da2ad5b451ac 100644
--- a/fs/cifs/cifs_uniupr.h
+++ b/fs/cifs/cifs_uniupr.h
@@ -242,7 +242,7 @@ static signed char UniCaseRangeLff20[27] = {
/*
* Lower Case Range
*/
-const static struct UniCaseRange CifsUniLowerRange[] = {
+static const struct UniCaseRange CifsUniLowerRange[] = {
0x0380, 0x03ab, UniCaseRangeL0380,
0x0400, 0x042f, UniCaseRangeL0400,
0x0490, 0x04cb, UniCaseRangeL0490,
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
new file mode 100644
index 000000000000..d0776ac2b804
--- /dev/null
+++ b/fs/cifs/cifsacl.h
@@ -0,0 +1,38 @@
+/*
+ * fs/cifs/cifsacl.h
+ *
+ * Copyright (c) International Business Machines Corp., 2005
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _CIFSACL_H
+#define _CIFSACL_H
+
+struct cifs_sid {
+ __u8 revision; /* revision level */
+ __u8 num_subauths;
+ __u8 authority[6];
+ __u32 sub_auth[4];
+ /* next sub_auth if any ... */
+} __attribute__((packed));
+
+/* everyone */
+extern const struct cifs_sid sid_everyone;
+/* group users */
+extern const struct cifs_sid sid_user;
+
+#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index fe2bb7c4c912..a2c24858d40f 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsencrypt.c
*
- * Copyright (C) International Business Machines Corp., 2003
+ * Copyright (C) International Business Machines Corp., 2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -82,6 +82,59 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
return rc;
}
+static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
+ const char * key, char * signature)
+{
+ struct MD5Context context;
+
+ if((iov == NULL) || (signature == NULL))
+ return -EINVAL;
+
+ MD5Init(&context);
+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+
+/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */
+
+ MD5Final(signature,&context);
+
+ return -EOPNOTSUPP;
+/* return 0; */
+}
+
+
+int cifs_sign_smb2(struct kvec * iov, int n_vec, struct TCP_Server_Info *server,
+ __u32 * pexpected_response_sequence_number)
+{
+ int rc = 0;
+ char smb_signature[20];
+ struct smb_hdr * cifs_pdu = iov[0].iov_base;
+
+ if((cifs_pdu == NULL) || (server == NULL))
+ return -EINVAL;
+
+ if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0)
+ return rc;
+
+ spin_lock(&GlobalMid_Lock);
+ cifs_pdu->Signature.Sequence.SequenceNumber =
+ cpu_to_le32(server->sequence_number);
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ *pexpected_response_sequence_number = server->sequence_number++;
+ server->sequence_number++;
+ spin_unlock(&GlobalMid_Lock);
+
+ rc = cifs_calc_signature2(iov, n_vec, server->mac_signing_key,
+ smb_signature);
+ if(rc)
+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+ else
+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+ return rc;
+
+}
+
int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
__u32 expected_sequence_number)
{
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 2a13a2bac8f1..79eeccd0437f 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -513,6 +513,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
return written;
}
+static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
+{
+ /* origin == SEEK_END => we must revalidate the cached file length */
+ if (origin == 2) {
+ int retval = cifs_revalidate(file->f_dentry);
+ if (retval < 0)
+ return (loff_t)retval;
+ }
+ return remote_llseek(file, offset, origin);
+}
+
static struct file_system_type cifs_fs_type = {
.owner = THIS_MODULE,
.name = "cifs",
@@ -586,6 +597,7 @@ struct file_operations cifs_file_ops = {
.flush = cifs_flush,
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
+ .llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
@@ -609,7 +621,7 @@ struct file_operations cifs_file_direct_ops = {
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
-
+ .llseek = cifs_llseek,
#ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -627,6 +639,7 @@ struct file_operations cifs_file_nobrl_ops = {
.flush = cifs_flush,
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
+ .llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
@@ -649,7 +662,7 @@ struct file_operations cifs_file_direct_nobrl_ops = {
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
-
+ .llseek = cifs_llseek,
#ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
@@ -733,7 +746,7 @@ cifs_init_request_bufs(void)
kmem_cache_destroy(cifs_req_cachep);
return -ENOMEM;
}
- /* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
+ /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
almost all handle based requests (but not write response, nor is it
sufficient for path based requests). A smaller size would have
been more efficient (compacting multiple slab items on one 4k page)
@@ -742,7 +755,8 @@ cifs_init_request_bufs(void)
efficient to alloc 1 per page off the slab compared to 17K (5page)
alloc of large cifs buffers even when page debugging is on */
cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
- MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
if (cifs_sm_req_cachep == NULL) {
mempool_destroy(cifs_req_poolp);
kmem_cache_destroy(cifs_req_cachep);
@@ -860,9 +874,9 @@ static int cifs_oplock_thread(void * dummyarg)
DeleteOplockQEntry(oplock_item);
/* can not grab inode sem here since it would
deadlock when oplock received on delete
- since vfs_unlink holds the i_sem across
+ since vfs_unlink holds the i_mutex across
the call */
- /* down(&inode->i_sem);*/
+ /* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
if(CIFS_I(inode)->clientCanCacheRead == 0) {
@@ -871,7 +885,7 @@ static int cifs_oplock_thread(void * dummyarg)
}
} else
rc = 0;
- /* up(&inode->i_sem);*/
+ /* mutex_unlock(&inode->i_mutex);*/
if (rc)
CIFS_I(inode)->write_behind_rc = rc;
cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
@@ -954,6 +968,12 @@ init_cifs(void)
atomic_set(&tconInfoReconnectCount, 0);
atomic_set(&bufAllocCount, 0);
+ atomic_set(&smBufAllocCount, 0);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_set(&totBufAllocCount, 0);
+ atomic_set(&totSmBufAllocCount, 0);
+#endif /* CONFIG_CIFS_STATS2 */
+
atomic_set(&midCount, 0);
GlobalCurrentXid = 0;
GlobalTotalActiveXid = 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 9ec40e0e54fc..821a8eb22559 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg);
-#define CIFS_VERSION "1.39"
+#define CIFS_VERSION "1.40"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1ba08f8c5bc4..7bed27601ce5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -233,6 +233,8 @@ struct cifsTconInfo {
atomic_t num_hardlinks;
atomic_t num_symlinks;
atomic_t num_locks;
+ atomic_t num_acl_get;
+ atomic_t num_acl_set;
#ifdef CONFIG_CIFS_STATS2
unsigned long long time_writes;
unsigned long long time_reads;
@@ -285,6 +287,7 @@ struct cifs_search_info {
unsigned endOfSearch:1;
unsigned emptyDir:1;
unsigned unicode:1;
+ unsigned smallBuf:1; /* so we know which buf_release function to call */
};
struct cifsFileInfo {
@@ -420,7 +423,12 @@ struct dir_notify_req {
#define MID_RESPONSE_RECEIVED 4
#define MID_RETRY_NEEDED 8 /* session closed while this request out */
#define MID_NO_RESP_NEEDED 0x10
-#define MID_SMALL_BUFFER 0x20 /* 112 byte response buffer instead of 4K */
+
+/* Types of response buffer returned from SendReceive2 */
+#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
+#define CIFS_SMALL_BUFFER 1
+#define CIFS_LARGE_BUFFER 2
+#define CIFS_IOVEC 4 /* array of response buffers */
/*
*****************************************************************
@@ -505,8 +513,12 @@ GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
/* Various Debug counters to remove someday (BB) */
-GLOBAL_EXTERN atomic_t bufAllocCount;
-GLOBAL_EXTERN atomic_t smBufAllocCount;
+GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */
+#ifdef CONFIG_CIFS_STATS2
+GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */
+GLOBAL_EXTERN atomic_t totSmBufAllocCount;
+#endif
+GLOBAL_EXTERN atomic_t smBufAllocCount;
GLOBAL_EXTERN atomic_t midCount;
/* Misc globals */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 33e1859fd2f6..cc2471094ca5 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifspdu.h
*
- * Copyright (c) International Business Machines Corp., 2002
+ * Copyright (c) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -80,7 +80,11 @@
#define NT_TRANSACT_GET_USER_QUOTA 0x07
#define NT_TRANSACT_SET_USER_QUOTA 0x08
-#define MAX_CIFS_HDR_SIZE 256 /* is future chained NTCreateXReadX bigger? */
+#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
+/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
+/* among the requests (NTCreateX response is bigger with wct of 34) */
+#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
+#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
/* internal cifs vfs structures */
/*****************************************************************
@@ -524,7 +528,7 @@ typedef union smb_com_session_setup_andx {
/* STRING PrimaryDomain */
/* STRING NativeOS */
/* STRING NativeLanMan */
- } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) request format */
+ } __attribute__((packed)) old_req; /* pre-NTLM (LANMAN2.1) req format */
struct { /* default (NTLM) response format */
struct smb_hdr hdr; /* wct = 3 */
@@ -536,7 +540,7 @@ typedef union smb_com_session_setup_andx {
unsigned char NativeOS[1]; /* followed by */
/* unsigned char * NativeLanMan; */
/* unsigned char * PrimaryDomain; */
- } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response format */
+ } __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
} __attribute__((packed)) SESSION_SETUP_ANDX;
#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
@@ -1003,10 +1007,49 @@ typedef struct smb_com_setattr_rsp {
/* empty wct response to setattr */
-/***************************************************/
-/* NT Transact structure defintions follow */
-/* Currently only ioctl and notify are implemented */
-/***************************************************/
+/*******************************************************/
+/* NT Transact structure defintions follow */
+/* Currently only ioctl, acl (get security descriptor) */
+/* and notify are implemented */
+/*******************************************************/
+typedef struct smb_com_ntransact_req {
+ struct smb_hdr hdr; /* wct >= 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* four setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
+ /* SetupCount words follow then */
+ __le16 ByteCount;
+ __u8 Pad[3];
+ __u8 Parms[0];
+} __attribute__((packed)) NTRANSACT_REQ;
+
+typedef struct smb_com_ntransact_rsp {
+ struct smb_hdr hdr; /* wct = 18 */
+ __u8 Reserved[3];
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 ParameterDisplacement;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __le32 DataDisplacement;
+ __u8 SetupCount; /* 0 */
+ __u16 ByteCount;
+ /* __u8 Pad[3]; */
+ /* parms and data follow */
+} __attribute__((packed)) NTRANSACT_RSP;
+
typedef struct smb_com_transaction_ioctl_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
@@ -1021,11 +1064,11 @@ typedef struct smb_com_transaction_ioctl_req {
__le32 DataOffset;
__u8 SetupCount; /* four setup words follow subcommand */
/* SNIA spec incorrectly included spurious pad here */
- __le16 SubCommand;/* 2 = IOCTL/FSCTL */
+ __le16 SubCommand; /* 2 = IOCTL/FSCTL */
__le32 FunctionCode;
__u16 Fid;
- __u8 IsFsctl; /* 1 = File System Control, 0 = device control (IOCTL)*/
- __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
+ __u8 IsFsctl; /* 1 = File System Control 0 = device control (IOCTL) */
+ __u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS) */
__le16 ByteCount;
__u8 Pad[3];
__u8 Data[1];
@@ -1045,9 +1088,35 @@ typedef struct smb_com_transaction_ioctl_rsp {
__u8 SetupCount; /* 1 */
__le16 ReturnedDataLen;
__u16 ByteCount;
- __u8 Pad[3];
} __attribute__((packed)) TRANSACT_IOCTL_RSP;
+#define CIFS_ACL_OWNER 1
+#define CIFS_ACL_GROUP 2
+#define CIFS_ACL_DACL 4
+#define CIFS_ACL_SACL 8
+
+typedef struct smb_com_transaction_qsec_req {
+ struct smb_hdr hdr; /* wct = 19 */
+ __u8 MaxSetupCount;
+ __u16 Reserved;
+ __le32 TotalParameterCount;
+ __le32 TotalDataCount;
+ __le32 MaxParameterCount;
+ __le32 MaxDataCount;
+ __le32 ParameterCount;
+ __le32 ParameterOffset;
+ __le32 DataCount;
+ __le32 DataOffset;
+ __u8 SetupCount; /* no setup words follow subcommand */
+ /* SNIA spec incorrectly included spurious pad here */
+ __le16 SubCommand; /* 6 = QUERY_SECURITY_DESC */
+ __le16 ByteCount; /* bcc = 3 + 8 */
+ __u8 Pad[3];
+ __u16 Fid;
+ __u16 Reserved2;
+ __le32 AclFlags;
+} __attribute__((packed)) QUERY_SEC_DESC_REQ;
+
typedef struct smb_com_transaction_change_notify_req {
struct smb_hdr hdr; /* wct = 23 */
__u8 MaxSetupCount;
@@ -1068,10 +1137,12 @@ typedef struct smb_com_transaction_change_notify_req {
__u8 WatchTree; /* 1 = Monitor subdirectories */
__u8 Reserved2;
__le16 ByteCount;
-/* __u8 Pad[3];*/
+/* __u8 Pad[3];*/
/* __u8 Data[1];*/
} __attribute__((packed)) TRANSACT_CHANGE_NOTIFY_REQ;
+/* BB eventually change to use generic ntransact rsp struct
+ and validation routine */
typedef struct smb_com_transaction_change_notify_rsp {
struct smb_hdr hdr; /* wct = 18 */
__u8 Reserved[3];
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 1b73f4f4c5ce..3c03aadaff0c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -48,8 +48,8 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
struct smb_hdr * /* out */ ,
int * /* bytes returned */ , const int long_op);
extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
- struct kvec *, int /* nvec */,
- int * /* bytes returned */ , const int long_op);
+ struct kvec *, int /* nvec to send */,
+ int * /* type of buf returned */ , const int long_op);
extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
extern int is_valid_oplock_break(struct smb_hdr *smb);
@@ -93,11 +93,12 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const struct nls_table *);
extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
- const char *searchName, const struct nls_table *nls_codepage,
- __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
+ const char *searchName, const struct nls_table *nls_codepage,
+ __u16 *searchHandle, struct cifs_search_info * psrch_inf,
+ int map, const char dirsep);
extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
- __u16 searchHandle, struct cifs_search_info * psrch_inf);
+ __u16 searchHandle, struct cifs_search_info * psrch_inf);
extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
const __u16 search_handle);
@@ -230,19 +231,18 @@ extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id);
extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
- const int netfid, unsigned int count,
- const __u64 lseek, unsigned int *nbytes, char **buf);
+ const int netfid, unsigned int count,
+ const __u64 lseek, unsigned int *nbytes, char **buf,
+ int * return_buf_type);
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes,
const char *buf, const char __user *ubuf,
const int long_op);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes,
struct kvec *iov, const int nvec, const int long_op);
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 * inode_number,
const struct nls_table *nls_codepage,
@@ -269,6 +269,8 @@ extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_reconnect(struct TCP_Server_Info *server);
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *);
+extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
+ __u32 *);
extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
__u32 expected_sequence_number);
extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
@@ -297,6 +299,9 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const char * ea_name,
const void * ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars);
+extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
+ __u16 fid, char *acl_inf, const int buflen,
+ const int acl_type /* ACCESS vs. DEFAULT */);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen,const int acl_type,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6867e556d37e..217323b0c896 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -37,6 +37,7 @@
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
+#include "cifsacl.h"
#ifdef CONFIG_CIFS_POSIX
static struct {
@@ -372,8 +373,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc == 0) {
- server->secMode = pSMBr->SecurityMode;
- server->secType = NTLM; /* BB override default for
+ server->secMode = pSMBr->SecurityMode;
+ if((server->secMode & SECMODE_USER) == 0)
+ cFYI(1,("share mode security"));
+ server->secType = NTLM; /* BB override default for
NTLMv2 or kerberos v5 */
/* one byte - no need to convert this or EncryptionKeyLen
from little endian */
@@ -383,7 +386,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
min(le32_to_cpu(pSMBr->MaxBufferSize),
(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
- cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
+ cFYI(0, ("Max buf = %d", ses->server->maxBuf));
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
@@ -411,8 +414,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
- cFYI(1,
- ("UID of server does not match previous connection to same ip address"));
+ cFYI(1, ("server UID changed"));
memcpy(server->
server_GUID,
pSMBr->u.
@@ -958,21 +960,19 @@ openRetry:
return rc;
}
-/* If no buffer passed in, then caller wants to do the copy
- as in the case of readpages so the SMB buffer must be
- freed by the caller */
-
int
CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
- const int netfid, const unsigned int count,
- const __u64 lseek, unsigned int *nbytes, char **buf)
+ const int netfid, const unsigned int count,
+ const __u64 lseek, unsigned int *nbytes, char **buf,
+ int * pbuf_type)
{
int rc = -EACCES;
READ_REQ *pSMB = NULL;
READ_RSP *pSMBr = NULL;
char *pReadData = NULL;
- int bytes_returned;
int wct;
+ int resp_buf_type = 0;
+ struct kvec iov[1];
cFYI(1,("Reading %d bytes on fid %d",count,netfid));
if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -981,8 +981,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
wct = 10; /* old style read */
*nbytes = 0;
- rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB);
if (rc)
return rc;
@@ -990,13 +989,13 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
if (tcon->ses->server == NULL)
return -ECONNABORTED;
- pSMB->AndXCommand = 0xFF; /* none */
+ pSMB->AndXCommand = 0xFF; /* none */
pSMB->Fid = netfid;
pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
if(wct == 12)
pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
- else if((lseek >> 32) > 0) /* can not handle this big offset for old */
- return -EIO;
+ else if((lseek >> 32) > 0) /* can not handle this big offset for old */
+ return -EIO;
pSMB->Remaining = 0;
pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
@@ -1005,14 +1004,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
pSMB->ByteCount = 0; /* no need to do le conversion since 0 */
else {
/* old style read */
- struct smb_com_readx_req * pSMBW =
+ struct smb_com_readx_req * pSMBW =
(struct smb_com_readx_req *)pSMB;
- pSMBW->ByteCount = 0;
+ pSMBW->ByteCount = 0;
}
-
- rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
- (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
+ rc = SendReceive2(xid, tcon->ses, iov,
+ 1 /* num iovecs */,
+ &resp_buf_type, 0);
cifs_stats_inc(&tcon->num_reads);
+ pSMBr = (READ_RSP *)iov[0].iov_base;
if (rc) {
cERROR(1, ("Send error in read = %d", rc));
} else {
@@ -1022,33 +1025,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
*nbytes = data_length;
/*check that DataLength would not go beyond end of SMB */
- if ((data_length > CIFSMaxBufSize)
+ if ((data_length > CIFSMaxBufSize)
|| (data_length > count)) {
cFYI(1,("bad length %d for count %d",data_length,count));
rc = -EIO;
*nbytes = 0;
} else {
- pReadData =
- (char *) (&pSMBr->hdr.Protocol) +
+ pReadData = (char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset);
-/* if(rc = copy_to_user(buf, pReadData, data_length)) {
- cERROR(1,("Faulting on read rc = %d",rc));
- rc = -EFAULT;
- }*/ /* can not use copy_to_user when using page cache*/
+/* if(rc = copy_to_user(buf, pReadData, data_length)) {
+ cERROR(1,("Faulting on read rc = %d",rc));
+ rc = -EFAULT;
+ }*/ /* can not use copy_to_user when using page cache*/
if(*buf)
- memcpy(*buf,pReadData,data_length);
+ memcpy(*buf,pReadData,data_length);
}
}
- if(*buf)
- cifs_buf_release(pSMB);
- else
- *buf = (char *)pSMB;
- /* Note: On -EAGAIN error only caller can retry on handle based calls
+ cifs_small_buf_release(pSMB);
+ if(*buf) {
+ if(resp_buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(iov[0].iov_base);
+ else if(resp_buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(iov[0].iov_base);
+ } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
+ *buf = iov[0].iov_base;
+ if(resp_buf_type == CIFS_SMALL_BUFFER)
+ *pbuf_type = CIFS_SMALL_BUFFER;
+ else if(resp_buf_type == CIFS_LARGE_BUFFER)
+ *pbuf_type = CIFS_LARGE_BUFFER;
+ }
+
+ /* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
return rc;
}
+
int
CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
@@ -1155,7 +1168,6 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
return rc;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
int
CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
@@ -1164,10 +1176,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
{
int rc = -EACCES;
WRITE_REQ *pSMB = NULL;
- int bytes_returned, wct;
+ int wct;
int smb_hdr_len;
+ int resp_buf_type = 0;
- /* BB removeme BB */
cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
if(tcon->ses->capabilities & CAP_LARGE_FILES)
@@ -1210,22 +1222,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
pSMBW->ByteCount = cpu_to_le16(count + 5);
}
iov[0].iov_base = pSMB;
- iov[0].iov_len = smb_hdr_len + 4;
+ if(wct == 14)
+ iov[0].iov_len = smb_hdr_len + 4;
+ else /* wct == 12 pad bigger by four bytes */
+ iov[0].iov_len = smb_hdr_len + 8;
+
- rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &bytes_returned,
+ rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type,
long_op);
cifs_stats_inc(&tcon->num_writes);
if (rc) {
cFYI(1, ("Send error Write2 = %d", rc));
*nbytes = 0;
+ } else if(resp_buf_type == 0) {
+ /* presumably this can not happen, but best to be safe */
+ rc = -EIO;
+ *nbytes = 0;
} else {
- WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
+ WRITE_RSP * pSMBr = (WRITE_RSP *)iov[0].iov_base;
*nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16;
*nbytes += le16_to_cpu(pSMBr->Count);
- }
+ }
cifs_small_buf_release(pSMB);
+ if(resp_buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(iov[0].iov_base);
+ else if(resp_buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(iov[0].iov_base);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
@@ -1234,8 +1258,6 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
}
-#endif /* CIFS_EXPERIMENTAL */
-
int
CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u64 len,
@@ -1906,6 +1928,90 @@ querySymLinkRetry:
return rc;
}
+/* Initialize NT TRANSACT SMB into small smb request buffer.
+ This assumes that all NT TRANSACTS that we init here have
+ total parm and data under about 400 bytes (to fit in small cifs
+ buffer size), which is the case so far, it easily fits. NB:
+ Setup words themselves and ByteCount
+ MaxSetupCount (size of returned setup area) and
+ MaxParameterCount (returned parms size) must be set by caller */
+static int
+smb_init_ntransact(const __u16 sub_command, const int setup_count,
+ const int parm_len, struct cifsTconInfo *tcon,
+ void ** ret_buf)
+{
+ int rc;
+ __u32 temp_offset;
+ struct smb_com_ntransact_req * pSMB;
+
+ rc = small_smb_init(SMB_COM_NT_TRANSACT, 19 + setup_count, tcon,
+ (void **)&pSMB);
+ if (rc)
+ return rc;
+ *ret_buf = (void *)pSMB;
+ pSMB->Reserved = 0;
+ pSMB->TotalParameterCount = cpu_to_le32(parm_len);
+ pSMB->TotalDataCount = 0;
+ pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+ pSMB->ParameterCount = pSMB->TotalParameterCount;
+ pSMB->DataCount = pSMB->TotalDataCount;
+ temp_offset = offsetof(struct smb_com_ntransact_req, Parms) +
+ (setup_count * 2) - 4 /* for rfc1001 length itself */;
+ pSMB->ParameterOffset = cpu_to_le32(temp_offset);
+ pSMB->DataOffset = cpu_to_le32(temp_offset + parm_len);
+ pSMB->SetupCount = setup_count; /* no need to le convert byte fields */
+ pSMB->SubCommand = cpu_to_le16(sub_command);
+ return 0;
+}
+
+static int
+validate_ntransact(char * buf, char ** ppparm, char ** ppdata,
+ int * pdatalen, int * pparmlen)
+{
+ char * end_of_smb;
+ __u32 data_count, data_offset, parm_count, parm_offset;
+ struct smb_com_ntransact_rsp * pSMBr;
+
+ if(buf == NULL)
+ return -EINVAL;
+
+ pSMBr = (struct smb_com_ntransact_rsp *)buf;
+
+ /* ByteCount was converted from little endian in SendReceive */
+ end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount +
+ (char *)&pSMBr->ByteCount;
+
+
+ data_offset = le32_to_cpu(pSMBr->DataOffset);
+ data_count = le32_to_cpu(pSMBr->DataCount);
+ parm_offset = le32_to_cpu(pSMBr->ParameterOffset);
+ parm_count = le32_to_cpu(pSMBr->ParameterCount);
+
+ *ppparm = (char *)&pSMBr->hdr.Protocol + parm_offset;
+ *ppdata = (char *)&pSMBr->hdr.Protocol + data_offset;
+
+ /* should we also check that parm and data areas do not overlap? */
+ if(*ppparm > end_of_smb) {
+ cFYI(1,("parms start after end of smb"));
+ return -EINVAL;
+ } else if(parm_count + *ppparm > end_of_smb) {
+ cFYI(1,("parm end after end of smb"));
+ return -EINVAL;
+ } else if(*ppdata > end_of_smb) {
+ cFYI(1,("data starts after end of smb"));
+ return -EINVAL;
+ } else if(data_count + *ppdata > end_of_smb) {
+ cFYI(1,("data %p + count %d (%p) ends after end of smb %p start %p",
+ *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr)); /* BB FIXME */
+ return -EINVAL;
+ } else if(parm_count + data_count > pSMBr->ByteCount) {
+ cFYI(1,("parm count and data count larger than SMB"));
+ return -EINVAL;
+ }
+ return 0;
+}
+
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
@@ -1928,7 +2034,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le32(2);
/* BB find exact data count max from sess structure BB */
- pSMB->MaxDataCount = cpu_to_le32(4000);
+ pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0;
pSMB->ParameterOffset = 0;
@@ -1955,7 +2062,9 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
rc = -EIO; /* bad smb */
else {
if(data_count && (data_count < 2048)) {
- char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
+ char * end_of_smb = 2 /* sizeof byte count */ +
+ pSMBr->ByteCount +
+ (char *)&pSMBr->ByteCount;
struct reparse_data * reparse_buf = (struct reparse_data *)
((char *)&pSMBr->hdr.Protocol + data_offset);
@@ -2199,6 +2308,7 @@ queryAclRetry:
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+ cifs_stats_inc(&tcon->num_acl_get);
if (rc) {
cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
} else {
@@ -2386,6 +2496,92 @@ GetExtAttrOut:
#endif /* CONFIG_POSIX */
+
+/* security id for everyone */
+const struct cifs_sid sid_everyone = {1, 1, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}};
+/* group users */
+const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0}};
+
+/* Convert CIFS ACL to POSIX form */
+static int parse_sec_desc(struct cifs_sid * psec_desc, int acl_len)
+{
+ return 0;
+}
+
+/* Get Security Descriptor (by handle) from remote server for a file or dir */
+int
+CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
+ /* BB fix up return info */ char *acl_inf, const int buflen,
+ const int acl_type /* ACCESS/DEFAULT not sure implication */)
+{
+ int rc = 0;
+ int buf_type = 0;
+ QUERY_SEC_DESC_REQ * pSMB;
+ struct kvec iov[1];
+
+ cFYI(1, ("GetCifsACL"));
+
+ rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
+ 8 /* parm len */, tcon, (void **) &pSMB);
+ if (rc)
+ return rc;
+
+ pSMB->MaxParameterCount = cpu_to_le32(4);
+ /* BB TEST with big acls that might need to be e.g. larger than 16K */
+ pSMB->MaxSetupCount = 0;
+ pSMB->Fid = fid; /* file handle always le */
+ pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP |
+ CIFS_ACL_DACL);
+ pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */
+ pSMB->hdr.smb_buf_length += 11;
+ iov[0].iov_base = (char *)pSMB;
+ iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
+
+ rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 0);
+ cifs_stats_inc(&tcon->num_acl_get);
+ if (rc) {
+ cFYI(1, ("Send error in QuerySecDesc = %d", rc));
+ } else { /* decode response */
+ struct cifs_sid * psec_desc;
+ __le32 * parm;
+ int parm_len;
+ int data_len;
+ int acl_len;
+ struct smb_com_ntransact_rsp * pSMBr;
+
+/* validate_nttransact */
+ rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
+ (char **)&psec_desc,
+ &parm_len, &data_len);
+
+ if(rc)
+ goto qsec_out;
+ pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;
+
+ cERROR(1,("smb %p parm %p data %p",pSMBr,parm,psec_desc)); /* BB removeme BB */
+
+ if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
+ rc = -EIO; /* bad smb */
+ goto qsec_out;
+ }
+
+/* BB check that data area is minimum length and as big as acl_len */
+
+ acl_len = le32_to_cpu(*(__le32 *)parm);
+ /* BB check if(acl_len > bufsize) */
+
+ parse_sec_desc(psec_desc, acl_len);
+ }
+qsec_out:
+ if(buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(iov[0].iov_base);
+ else if(buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(iov[0].iov_base);
+ cifs_small_buf_release(pSMB);
+ return rc;
+}
+
+
/* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */
int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
@@ -4284,7 +4480,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
{
int rc = 0;
struct smb_com_transaction_change_notify_req * pSMB = NULL;
- struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
+ struct smb_com_ntransaction_change_notify_rsp * pSMBr = NULL;
struct dir_notify_req *dnotify_req;
int bytes_returned;
@@ -4299,6 +4495,10 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
pSMB->MaxParameterCount = cpu_to_le32(2);
/* BB find exact data count max from sess structure BB */
pSMB->MaxDataCount = 0; /* same in little endian or be */
+/* BB VERIFY verify which is correct for above BB */
+ pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf -
+ MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+
pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0;
pSMB->ParameterOffset = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index c467de857610..88f60aa52058 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -76,12 +76,19 @@ struct smb_vol {
unsigned setuids:1;
unsigned noperm:1;
unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+ unsigned cifs_acl:1;
unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
unsigned direct_io:1;
unsigned remap:1; /* set to remap seven reserved chars in filenames */
unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
unsigned sfu_emul:1;
+ unsigned krb5:1;
+ unsigned ntlm:1;
+ unsigned ntlmv2:1;
+ unsigned nullauth:1; /* attempt to authenticate with null user */
+ unsigned sign:1;
+ unsigned seal:1; /* encrypt */
unsigned nocase; /* request case insensitive filenames */
unsigned nobrl; /* disable sending byte range locks to srv */
unsigned int rsize;
@@ -508,7 +515,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* else length ok */
reconnect = 0;
- if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
+ if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
isLargeBuf = TRUE;
memcpy(bigbuf, smallbuf, 4);
smb_buffer = bigbuf;
@@ -777,7 +784,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
vol->rw = TRUE;
-
+ vol->ntlm = TRUE;
/* default is always to request posix paths. */
vol->posix_paths = 1;
@@ -903,6 +910,39 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
printk(KERN_WARNING "CIFS: ip address too long\n");
return 1;
}
+ } else if (strnicmp(data, "sec", 3) == 0) {
+ if (!value || !*value) {
+ cERROR(1,("no security value specified"));
+ continue;
+ } else if (strnicmp(value, "krb5i", 5) == 0) {
+ vol->sign = 1;
+ vol->krb5 = 1;
+ } else if (strnicmp(value, "krb5p", 5) == 0) {
+ /* vol->seal = 1;
+ vol->krb5 = 1; */
+ cERROR(1,("Krb5 cifs privacy not supported"));
+ return 1;
+ } else if (strnicmp(value, "krb5", 4) == 0) {
+ vol->krb5 = 1;
+ } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
+ vol->ntlmv2 = 1;
+ vol->sign = 1;
+ } else if (strnicmp(value, "ntlmv2", 6) == 0) {
+ vol->ntlmv2 = 1;
+ } else if (strnicmp(value, "ntlmi", 5) == 0) {
+ vol->ntlm = 1;
+ vol->sign = 1;
+ } else if (strnicmp(value, "ntlm", 4) == 0) {
+ /* ntlm is default so can be turned off too */
+ vol->ntlm = 1;
+ } else if (strnicmp(value, "nontlm", 6) == 0) {
+ vol->ntlm = 0;
+ } else if (strnicmp(value, "none", 4) == 0) {
+ vol->nullauth = 1;
+ } else {
+ cERROR(1,("bad security option: %s", value));
+ return 1;
+ }
} else if ((strnicmp(data, "unc", 3) == 0)
|| (strnicmp(data, "target", 6) == 0)
|| (strnicmp(data, "path", 4) == 0)) {
@@ -1120,6 +1160,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
vol->server_ino = 1;
} else if (strnicmp(data, "noserverino",9) == 0) {
vol->server_ino = 0;
+ } else if (strnicmp(data, "cifsacl",7) == 0) {
+ vol->cifs_acl = 1;
+ } else if (strnicmp(data, "nocifsacl", 9) == 0) {
+ vol->cifs_acl = 0;
} else if (strnicmp(data, "acl",3) == 0) {
vol->no_psx_acl = 0;
} else if (strnicmp(data, "noacl",5) == 0) {
@@ -1546,7 +1590,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cFYI(1, ("Username: %s ", volume_info.username));
} else {
- cifserror("No username specified ");
+ cifserror("No username specified");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
kfree(volume_info.UNC);
@@ -1587,7 +1631,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
return -EINVAL;
} else /* which servers DFS root would we conect to */ {
cERROR(1,
- ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
+ ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
kfree(volume_info.UNC);
kfree(volume_info.password);
FreeXid(xid);
@@ -1626,7 +1670,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (srvTcp) {
- cFYI(1, ("Existing tcp session with server found "));
+ cFYI(1, ("Existing tcp session with server found"));
} else { /* create socket */
if(volume_info.port)
sin_server.sin_port = htons(volume_info.port);
@@ -1689,11 +1733,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (existingCifsSes) {
pSesInfo = existingCifsSes;
- cFYI(1, ("Existing smb sess found "));
+ cFYI(1, ("Existing smb sess found"));
kfree(volume_info.password);
/* volume_info.UNC freed at end of function */
} else if (!rc) {
- cFYI(1, ("Existing smb sess not found "));
+ cFYI(1, ("Existing smb sess not found"));
pSesInfo = sesInfoAlloc();
if (pSesInfo == NULL)
rc = -ENOMEM;
@@ -1751,7 +1795,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_gid = volume_info.linux_gid;
cifs_sb->mnt_file_mode = volume_info.file_mode;
cifs_sb->mnt_dir_mode = volume_info.dir_mode;
- cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+ cFYI(1,("file mode: 0x%x dir mode: 0x%x",
+ cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
if(volume_info.noperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
@@ -1767,6 +1812,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
if(volume_info.nobrl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
+ if(volume_info.cifs_acl)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
if(volume_info.direct_io) {
cFYI(1,("mounting share using direct i/o"));
@@ -1777,7 +1824,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
volume_info.username);
if (tcon) {
- cFYI(1, ("Found match on UNC path "));
+ cFYI(1, ("Found match on UNC path"));
/* we can have only one retry value for a connection
to a share so for resources mounted more than once
to the same server share the last value passed in
@@ -1926,7 +1973,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
__u32 capabilities;
__u16 count;
- cFYI(1, ("In sesssetup "));
+ cFYI(1, ("In sesssetup"));
if(ses == NULL)
return -EINVAL;
user = ses->userName;
@@ -3202,9 +3249,26 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
pSMB->AndXCommand = 0xFF;
pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
- pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
bcc_ptr = &pSMB->Password[0];
- bcc_ptr++; /* skip password */
+ if((ses->server->secMode) & SECMODE_USER) {
+ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
+ bcc_ptr++; /* skip password */
+ } else {
+ pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+ /* BB FIXME add code to fail this if NTLMv2 or Kerberos
+ specified as required (when that support is added to
+ the vfs in the future) as only NTLM or the much
+ weaker LANMAN (which we do not send) is accepted
+ by Samba (not sure whether other servers allow
+ NTLMv2 password here) */
+ SMBNTencrypt(ses->password,
+ ses->server->cryptKey,
+ bcc_ptr);
+
+ bcc_ptr += CIFS_SESSION_KEY_SIZE;
+ *bcc_ptr = 0;
+ bcc_ptr++; /* align */
+ }
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -3222,7 +3286,6 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
bcc_ptr += 2; /* skip trailing null */
} else { /* ASCII */
-
strcpy(bcc_ptr, tree);
bcc_ptr += strlen(tree) + 1;
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 32cc96cafa3e..fed55e3c53df 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
*
* vfs operations that deal with dentries
*
- * Copyright (C) International Business Machines Corp., 2002,2003
+ * Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -200,8 +200,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(oplock & CIFS_CREATE_ACTION))
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
- (__u64)current->euid,
- (__u64)current->egid,
+ (__u64)current->fsuid,
+ (__u64)current->fsgid,
0 /* dev */,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -325,7 +325,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
else if (pTcon->ses->capabilities & CAP_UNIX) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
- mode,(__u64)current->euid,(__u64)current->egid,
+ mode,(__u64)current->fsuid,(__u64)current->fsgid,
device_number, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 14a1c72ced92..77c990f0cb98 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -127,8 +127,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
if (file->f_dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate
since namei code should already have it locked? */
- filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
- filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
+ filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
}
cFYI(1, ("invalidating remote inode since open detected it "
"changed"));
@@ -419,8 +418,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
pCifsInode = CIFS_I(inode);
if (pCifsInode) {
if (can_flush) {
- filemap_fdatawrite(inode->i_mapping);
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
/* temporarily disable caching while we
go to server to get inode info */
pCifsInode->clientCanCacheAll = FALSE;
@@ -555,13 +553,13 @@ int cifs_closedir(struct inode *inode, struct file *file)
}
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
if (ptmp) {
- /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
+ cFYI(1, ("closedir free smb buf in srch struct"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
cifs_buf_release(ptmp);
}
ptmp = pCFileStruct->search_resume_name;
if (ptmp) {
- /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
+ cFYI(1, ("closedir free resume name"));
pCFileStruct->search_resume_name = NULL;
kfree(ptmp);
}
@@ -870,10 +868,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
if (rc != 0)
break;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
/* BB FIXME We can not sign across two buffers yet */
- if((experimEnabled) && ((pTcon->ses->server->secMode &
- (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
+ if((pTcon->ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
struct kvec iov[2];
unsigned int len;
@@ -889,7 +886,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
iov, 1, long_op);
} else
/* BB FIXME fixup indentation of line below */
-#endif
rc = CIFSSMBWrite(xid, pTcon,
open_file->netfid,
min_t(const int, cifs_sb->wsize,
@@ -1026,7 +1022,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
return rc;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
static int cifs_writepages(struct address_space *mapping,
struct writeback_control *wbc)
{
@@ -1229,7 +1224,6 @@ retry:
return rc;
}
-#endif
static int cifs_writepage(struct page* page, struct writeback_control *wbc)
{
@@ -1428,6 +1422,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
rc = -EAGAIN;
smb_read_data = NULL;
while (rc == -EAGAIN) {
+ int buf_type = CIFS_NO_BUFFER;
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
rc = cifs_reopen_file(file->f_dentry->d_inode,
@@ -1436,20 +1431,22 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
break;
}
rc = CIFSSMBRead(xid, pTcon,
- open_file->netfid,
- current_read_size, *poffset,
- &bytes_read, &smb_read_data);
+ open_file->netfid,
+ current_read_size, *poffset,
+ &bytes_read, &smb_read_data,
+ &buf_type);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
if (copy_to_user(current_offset,
smb_read_data + 4 /* RFC1001 hdr */
+ le16_to_cpu(pSMBr->DataOffset),
bytes_read)) {
rc = -EFAULT;
- FreeXid(xid);
- return rc;
- }
+ }
if (smb_read_data) {
- cifs_buf_release(smb_read_data);
+ if(buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(smb_read_data);
+ else if(buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
}
@@ -1482,6 +1479,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int xid;
char *current_offset;
struct cifsFileInfo *open_file;
+ int buf_type = CIFS_NO_BUFFER;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1518,9 +1516,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
break;
}
rc = CIFSSMBRead(xid, pTcon,
- open_file->netfid,
- current_read_size, *poffset,
- &bytes_read, &current_offset);
+ open_file->netfid,
+ current_read_size, *poffset,
+ &bytes_read, &current_offset,
+ &buf_type);
}
if (rc || (bytes_read == 0)) {
if (total_read) {
@@ -1618,6 +1617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
struct smb_com_read_rsp *pSMBr;
struct pagevec lru_pvec;
struct cifsFileInfo *open_file;
+ int buf_type = CIFS_NO_BUFFER;
xid = GetXid();
if (file->private_data == NULL) {
@@ -1674,14 +1674,17 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
}
rc = CIFSSMBRead(xid, pTcon,
- open_file->netfid,
- read_size, offset,
- &bytes_read, &smb_read_data);
-
+ open_file->netfid,
+ read_size, offset,
+ &bytes_read, &smb_read_data,
+ &buf_type);
/* BB more RC checks ? */
if (rc== -EAGAIN) {
if (smb_read_data) {
- cifs_buf_release(smb_read_data);
+ if(buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(smb_read_data);
+ else if(buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
}
@@ -1738,7 +1741,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
break;
}
if (smb_read_data) {
- cifs_buf_release(smb_read_data);
+ if(buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(smb_read_data);
+ else if(buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
bytes_read = 0;
@@ -1748,7 +1754,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
/* need to free smb_read_data buf before exit */
if (smb_read_data) {
- cifs_buf_release(smb_read_data);
+ if(buf_type == CIFS_SMALL_BUFFER)
+ cifs_small_buf_release(smb_read_data);
+ else if(buf_type == CIFS_LARGE_BUFFER)
+ cifs_buf_release(smb_read_data);
smb_read_data = NULL;
}
@@ -1827,10 +1836,20 @@ int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
open_file = find_writable_file(cifsInode);
if(open_file) {
+ struct cifs_sb_info *cifs_sb;
+
/* there is not actually a write pending so let
this handle go free and allow it to
be closable if needed */
atomic_dec(&open_file->wrtPending);
+
+ cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
+ if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
+ /* since no page cache to corrupt on directio
+ we can change size safely */
+ return 1;
+ }
+
return 0;
} else
return 1;
@@ -1875,9 +1894,7 @@ struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
.writepages = cifs_writepages,
-#endif
.prepare_write = cifs_prepare_write,
.commit_write = cifs_commit_write,
.set_page_dirty = __set_page_dirty_nobuffers,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 411c1f7f84da..59359911f481 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -229,11 +229,12 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc==0) {
+ int buf_type = CIFS_NO_BUFFER;
/* Read header */
rc = CIFSSMBRead(xid, pTcon,
netfid,
24 /* length */, 0 /* offset */,
- &bytes_read, &pbuf);
+ &bytes_read, &pbuf, &buf_type);
if((rc == 0) && (bytes_read >= 8)) {
if(memcmp("IntxBLK", pbuf, 8) == 0) {
cFYI(1,("Block device"));
@@ -267,7 +268,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
} else {
inode->i_mode |= S_IFREG; /* then it is a file */
rc = -EOPNOTSUPP; /* or some unknown SFU type */
- }
+ }
CIFSSMBClose(xid, pTcon, netfid);
}
return rc;
@@ -750,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
- (__u64)current->euid,
- (__u64)current->egid,
+ (__u64)current->fsuid,
+ (__u64)current->fsgid,
0 /* dev_t */,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
@@ -1040,9 +1041,9 @@ int cifs_revalidate(struct dentry *direntry)
}
/* can not grab this sem since kernel filesys locking documentation
- indicates i_sem may be taken by the kernel on lookup and rename
- which could deadlock if we grab the i_sem here as well */
-/* down(&direntry->d_inode->i_sem);*/
+ indicates i_mutex may be taken by the kernel on lookup and rename
+ which could deadlock if we grab the i_mutex here as well */
+/* mutex_lock(&direntry->d_inode->i_mutex);*/
/* need to write out dirty pages here */
if (direntry->d_inode->i_mapping) {
/* do we need to lock inode until after invalidate completes
@@ -1066,7 +1067,7 @@ int cifs_revalidate(struct dentry *direntry)
}
}
}
-/* up(&direntry->d_inode->i_sem); */
+/* mutex_unlock(&direntry->d_inode->i_mutex); */
kfree(full_path);
FreeXid(xid);
@@ -1148,8 +1149,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
/* BB check if we need to refresh inode from server now ? BB */
/* need to flush data before changing file size on server */
- filemap_fdatawrite(direntry->d_inode->i_mapping);
- filemap_fdatawait(direntry->d_inode->i_mapping);
+ filemap_write_and_wait(direntry->d_inode->i_mapping);
if (attrs->ia_valid & ATTR_SIZE) {
/* To avoid spurious oplock breaks from server, in the case of
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 94baf6c8ecbd..812c6bb0fe38 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1,7 +1,7 @@
/*
* fs/cifs/misc.c
*
- * Copyright (C) International Business Machines Corp., 2002,2004
+ * Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -161,6 +161,9 @@ cifs_buf_get(void)
if (ret_buf) {
memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
atomic_inc(&bufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_inc(&totBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
}
return ret_buf;
@@ -195,6 +198,10 @@ cifs_small_buf_get(void)
/* No need to clear memory here, cleared in header assemble */
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
atomic_inc(&smBufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+ atomic_inc(&totSmBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
+
}
return ret_buf;
}
@@ -292,7 +299,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
struct cifsSesInfo * ses;
char *temp = (char *) buffer;
- memset(temp,0,MAX_CIFS_HDR_SIZE);
+ memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
buffer->smb_buf_length =
(2 * word_count) + sizeof (struct smb_hdr) -
@@ -348,12 +355,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
/* BB Add support for establishing new tCon and SMB Session */
/* with userid/password pairs found on the smb session */
/* for other target tcp/ip addresses BB */
- if(current->uid != treeCon->ses->linux_uid) {
- cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+ if(current->fsuid != treeCon->ses->linux_uid) {
+ cFYI(1,("Multiuser mode and UID did not match tcon uid"));
read_lock(&GlobalSMBSeslock);
list_for_each(temp_item, &GlobalSMBSessionList) {
ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
- if(ses->linux_uid == current->uid) {
+ if(ses->linux_uid == current->fsuid) {
if(ses->server == treeCon->ses->server) {
cFYI(1,("found matching uid substitute right smb_uid"));
buffer->Uid = ses->Suid;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9bdaaecae36f..288cc048d37f 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -214,8 +214,7 @@ static void fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_fop = &cifs_file_nobrl_ops;
else
tmp_inode->i_fop = &cifs_file_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- tmp_inode->i_fop->lock = NULL;
+
tmp_inode->i_data.a_ops = &cifs_addr_ops;
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
(cifs_sb->tcon->ses->server->maxBuf <
@@ -327,12 +326,18 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
if (S_ISREG(tmp_inode->i_mode)) {
cFYI(1, ("File inode"));
tmp_inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
- tmp_inode->i_fop = &cifs_file_direct_ops;
+
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+ if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
+ else
+ tmp_inode->i_fop = &cifs_file_direct_ops;
+
+ } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+ tmp_inode->i_fop = &cifs_file_nobrl_ops;
else
tmp_inode->i_fop = &cifs_file_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
- tmp_inode->i_fop->lock = NULL;
+
tmp_inode->i_data.a_ops = &cifs_addr_ops;
if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
(cifs_sb->tcon->ses->server->maxBuf <
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index 9222033cad8e..aede606132aa 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -24,11 +24,11 @@
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
/* RFC 1002 session packet types */
-#define RFC1002_SESSION_MESASAGE 0x00
+#define RFC1002_SESSION_MESSAGE 0x00
#define RFC1002_SESSION_REQUEST 0x81
#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
-#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
+#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
#define RFC1002_SESSION_KEEP_ALIVE 0x85
/* RFC 1002 flags (only one defined */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f8871196098c..7b98792150ea 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -206,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
return rc;
}
-#ifdef CONFIG_CIFS_EXPERIMENTAL
static int
smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
struct sockaddr *sin)
@@ -299,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
int
SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
- struct kvec *iov, int n_vec, int *pbytes_returned,
+ struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
const int long_op)
{
int rc = 0;
@@ -307,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
unsigned long timeout;
struct mid_q_entry *midQ;
struct smb_hdr *in_buf = iov[0].iov_base;
+
+ *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
if (ses == NULL) {
cERROR(1,("Null smb session"));
@@ -392,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
return -ENOMEM;
}
-/* BB FIXME */
-/* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
+ rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
midQ->midState = MID_REQUEST_SUBMITTED;
#ifdef CONFIG_CIFS_STATS2
@@ -489,21 +489,23 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
receive_len, xid));
rc = -EIO;
} else { /* rcvd frame is ok */
-
if (midQ->resp_buf &&
(midQ->midState == MID_RESPONSE_RECEIVED)) {
- in_buf->smb_buf_length = receive_len;
- /* BB verify that length would not overrun small buf */
- memcpy((char *)in_buf + 4,
- (char *)midQ->resp_buf + 4,
- receive_len);
- dump_smb(in_buf, 80);
+ iov[0].iov_base = (char *)midQ->resp_buf;
+ if(midQ->largeBuf)
+ *pRespBufType = CIFS_LARGE_BUFFER;
+ else
+ *pRespBufType = CIFS_SMALL_BUFFER;
+ iov[0].iov_len = receive_len + 4;
+ iov[1].iov_len = 0;
+
+ dump_smb(midQ->resp_buf, 80);
/* convert the length into a more usable form */
if((receive_len > 24) &&
(ses->server->secMode & (SECMODE_SIGN_REQUIRED |
SECMODE_SIGN_ENABLED))) {
- rc = cifs_verify_signature(in_buf,
+ rc = cifs_verify_signature(midQ->resp_buf,
ses->server->mac_signing_key,
midQ->sequence_number+1);
if(rc) {
@@ -512,18 +514,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
}
}
- *pbytes_returned = in_buf->smb_buf_length;
-
/* BB special case reconnect tid and uid here? */
/* BB special case Errbadpassword and pwdexpired here */
- rc = map_smb_to_linux_error(in_buf);
+ rc = map_smb_to_linux_error(midQ->resp_buf);
/* convert ByteCount if necessary */
if (receive_len >=
sizeof (struct smb_hdr) -
4 /* do not count RFC1001 header */ +
- (2 * in_buf->WordCount) + 2 /* bcc */ )
- BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf));
+ (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
+ BCC(midQ->resp_buf) =
+ le16_to_cpu(BCC_LE(midQ->resp_buf));
+ midQ->resp_buf = NULL; /* mark it so will not be freed
+ by DeleteMidQEntry */
} else {
rc = -EIO;
cFYI(1,("Bad MID state?"));
@@ -549,7 +552,6 @@ out_unlock2:
return rc;
}
-#endif /* CIFS_EXPERIMENTAL */
int
SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -790,7 +792,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
} else {
rc = -EIO;
- cERROR(1,("Bad MID state? "));
+ cERROR(1,("Bad MID state?"));
}
}
cifs_no_response_exit:
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index f375f87c7dbd..777e3363c2a4 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -254,7 +254,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
buf_size, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
+ } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
+ strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
#ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL)
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
@@ -262,10 +263,27 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
+/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+ __u16 fid;
+ int oplock = FALSE;
+ rc = CIFSSMBOpen(xid, pTcon, full_path,
+ FILE_OPEN, GENERIC_READ, 0, &fid,
+ &oplock, NULL, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if(rc == 0) {
+ rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
+ ea_value, buf_size,
+ ACL_TYPE_ACCESS);
+ CIFSSMBClose(xid, pTcon, fid)
+ }
+ } */ /* BB enable after fixing up return data */
+
#else
cFYI(1,("query POSIX ACL not supported yet"));
#endif /* CONFIG_CIFS_POSIX */
- } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
+ } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
+ strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
#ifdef CONFIG_CIFS_POSIX
if(sb->s_flags & MS_POSIXACL)
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 80072fd9b7fa..c607d923350a 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -93,7 +93,7 @@ static void coda_flag_children(struct dentry *parent, int flag)
spin_lock(&dcache_lock);
list_for_each(child, &parent->d_subdirs)
{
- de = list_entry(child, struct dentry, d_child);
+ de = list_entry(child, struct dentry, d_u.d_child);
/* don't know what to do with negative dentries */
if ( ! de->d_inode )
continue;
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 2391766e9c7c..8f1a517f8b4e 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -453,7 +453,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
coda_vfs_stat.readdir++;
host_inode = host_file->f_dentry->d_inode;
- down(&host_inode->i_sem);
+ mutex_lock(&host_inode->i_mutex);
host_file->f_pos = coda_file->f_pos;
if (!host_file->f_op->readdir) {
@@ -475,7 +475,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
}
out:
coda_file->f_pos = host_file->f_pos;
- up(&host_inode->i_sem);
+ mutex_unlock(&host_inode->i_mutex);
return ret;
}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index e6bc022568f3..30b4630bd735 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -77,14 +77,14 @@ coda_file_write(struct file *coda_file, const char __user *buf, size_t count, lo
return -EINVAL;
host_inode = host_file->f_dentry->d_inode;
- down(&coda_inode->i_sem);
+ mutex_lock(&coda_inode->i_mutex);
ret = host_file->f_op->write(host_file, buf, count, ppos);
coda_inode->i_size = host_inode->i_size;
coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME_SEC;
- up(&coda_inode->i_sem);
+ mutex_unlock(&coda_inode->i_mutex);
return ret;
}
@@ -272,9 +272,9 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
if (host_file->f_op && host_file->f_op->fsync) {
host_dentry = host_file->f_dentry;
host_inode = host_dentry->d_inode;
- down(&host_inode->i_sem);
+ mutex_lock(&host_inode->i_mutex);
err = host_file->f_op->fsync(host_file, host_dentry, datasync);
- up(&host_inode->i_sem);
+ mutex_unlock(&host_inode->i_mutex);
}
if ( !err && !datasync ) {
diff --git a/fs/compat.c b/fs/compat.c
index 818634120b69..18b21b4c9e3a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -53,6 +53,8 @@
#include <asm/mmu_context.h>
#include <asm/ioctls.h>
+extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
+
/*
* Not all architectures have sys_utime, so implement this in terms
* of sys_utimes.
@@ -68,10 +70,10 @@ asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __
tv[0].tv_usec = 0;
tv[1].tv_usec = 0;
}
- return do_utimes(filename, t ? tv : NULL);
+ return do_utimes(AT_FDCWD, filename, t ? tv : NULL);
}
-asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
+asmlinkage long compat_sys_futimesat(int dfd, char __user *filename, struct compat_timeval __user *t)
{
struct timeval tv[2];
@@ -82,14 +84,19 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
get_user(tv[1].tv_usec, &t[1].tv_usec))
return -EFAULT;
}
- return do_utimes(filename, t ? tv : NULL);
+ return do_utimes(dfd, filename, t ? tv : NULL);
+}
+
+asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
+{
+ return compat_sys_futimesat(AT_FDCWD, filename, t);
}
asmlinkage long compat_sys_newstat(char __user * filename,
struct compat_stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_stat(filename, &stat);
+ int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_compat_stat(&stat, statbuf);
@@ -100,10 +107,31 @@ asmlinkage long compat_sys_newlstat(char __user * filename,
struct compat_stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_lstat(filename, &stat);
+ int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
+
+ if (!error)
+ error = cp_compat_stat(&stat, statbuf);
+ return error;
+}
+
+asmlinkage long compat_sys_newfstatat(int dfd, char __user *filename,
+ struct compat_stat __user *statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_fd(dfd, filename, &stat);
if (!error)
error = cp_compat_stat(&stat, statbuf);
+
+out:
return error;
}
@@ -494,9 +522,21 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs(old_fs);
if (cmd == F_GETLK && ret == 0) {
- if ((f.l_start >= COMPAT_OFF_T_MAX) ||
- ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
+ /* GETLK was successfule and we need to return the data...
+ * but it needs to fit in the compat structure.
+ * l_start shouldn't be too big, unless the original
+ * start + end is greater than COMPAT_OFF_T_MAX, in which
+ * case the app was asking for trouble, so we return
+ * -EOVERFLOW in that case.
+ * l_len could be too big, in which case we just truncate it,
+ * and only allow the app to see that part of the conflicting
+ * lock that might make sense to it anyway
+ */
+
+ if (f.l_start > COMPAT_OFF_T_MAX)
ret = -EOVERFLOW;
+ if (f.l_len > COMPAT_OFF_T_MAX)
+ f.l_len = COMPAT_OFF_T_MAX;
if (ret == 0)
ret = put_compat_flock(&f, compat_ptr(arg));
}
@@ -515,9 +555,11 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
(unsigned long)&f);
set_fs(old_fs);
if (cmd == F_GETLK64 && ret == 0) {
- if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
- ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
+ /* need to return lock information - see above for commentary */
+ if (f.l_start > COMPAT_LOFF_T_MAX)
ret = -EOVERFLOW;
+ if (f.l_len > COMPAT_LOFF_T_MAX)
+ f.l_len = COMPAT_LOFF_T_MAX;
if (ret == 0)
ret = put_compat_flock64(&f, compat_ptr(arg));
}
@@ -1170,7 +1212,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
}
ret = rw_verify_area(type, file, pos, tot_len);
- if (ret)
+ if (ret < 0)
goto out;
fnv = NULL;
@@ -1276,7 +1318,17 @@ out:
asmlinkage long
compat_sys_open(const char __user *filename, int flags, int mode)
{
- return do_sys_open(filename, flags, mode);
+ return do_sys_open(AT_FDCWD, filename, flags, mode);
+}
+
+/*
+ * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
+ * O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_openat(int dfd, const char __user *filename, int flags, int mode)
+{
+ return do_sys_open(dfd, filename, flags, mode);
}
/*
@@ -1523,7 +1575,7 @@ out_ret:
* Ooo, nasty. We need here to frob 32-bit unsigned longs to
* 64-bit unsigned longs.
*/
-static inline
+static
int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
unsigned long *fdset)
{
@@ -1556,7 +1608,7 @@ int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
return 0;
}
-static inline
+static
void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
unsigned long *fdset)
{
@@ -1607,36 +1659,14 @@ static void select_bits_free(void *bits, int size)
#define MAX_SELECT_SECONDS \
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-asmlinkage long
-compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp,
- compat_ulong_t __user *exp, struct compat_timeval __user *tvp)
+int compat_core_sys_select(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
{
fd_set_bits fds;
char *bits;
- long timeout;
int size, max_fdset, ret = -EINVAL;
struct fdtable *fdt;
- timeout = MAX_SCHEDULE_TIMEOUT;
- if (tvp) {
- time_t sec, usec;
-
- if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
- || __get_user(sec, &tvp->tv_sec)
- || __get_user(usec, &tvp->tv_usec)) {
- ret = -EFAULT;
- goto out_nofds;
- }
-
- if (sec < 0 || usec < 0)
- goto out_nofds;
-
- if ((unsigned long) sec < MAX_SELECT_SECONDS) {
- timeout = ROUND_UP(usec, 1000000/HZ);
- timeout += sec * (unsigned long) HZ;
- }
- }
-
if (n < 0)
goto out_nofds;
@@ -1673,19 +1703,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, &timeout);
-
- if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
- time_t sec = 0, usec = 0;
- if (timeout) {
- sec = timeout / HZ;
- usec = timeout % HZ;
- usec *= (1000000/HZ);
- }
- if (put_user(sec, &tvp->tv_sec) ||
- put_user(usec, &tvp->tv_usec))
- ret = -EFAULT;
- }
+ ret = do_select(n, &fds, timeout);
if (ret < 0)
goto out;
@@ -1706,6 +1724,224 @@ out_nofds:
return ret;
}
+asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timeval __user *tvp)
+{
+ s64 timeout = -1;
+ struct compat_timeval tv;
+ int ret;
+
+ if (tvp) {
+ if (copy_from_user(&tv, tvp, sizeof(tv)))
+ return -EFAULT;
+
+ if (tv.tv_sec < 0 || tv.tv_usec < 0)
+ return -EINVAL;
+
+ /* Cast to u64 to make GCC stop complaining */
+ if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(tv.tv_sec, 1000000/HZ);
+ timeout += tv.tv_sec * HZ;
+ }
+ }
+
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tvp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+ tv.tv_sec = timeout;
+ if (copy_to_user(tvp, &tv, sizeof(tv))) {
+sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize)
+{
+ compat_sigset_t ss32;
+ sigset_t ksigmask, sigsaved;
+ long timeout = MAX_SCHEDULE_TIMEOUT;
+ struct compat_timespec ts;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+ return -EINVAL;
+ }
+
+ if (sigmask) {
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &ss32);
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ do {
+ if (tsp) {
+ if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
+ timeout = ROUND_UP(ts.tv_nsec, 1000000000/HZ);
+ timeout += ts.tv_sec * (unsigned long)HZ;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ } else {
+ ts.tv_sec -= MAX_SELECT_SECONDS;
+ timeout = MAX_SELECT_SECONDS * HZ;
+ }
+ }
+
+ ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
+
+ } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
+
+ if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
+ ts.tv_sec += timeout / HZ;
+ ts.tv_nsec += (timeout % HZ) * (1000000000/HZ);
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000;
+ }
+ (void)copy_to_user(tsp, &ts, sizeof(ts));
+ }
+
+ if (ret == -ERESTARTNOHAND) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+
+asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp, compat_ulong_t __user *exp,
+ struct compat_timespec __user *tsp, void __user *sig)
+{
+ compat_size_t sigsetsize = 0;
+ compat_uptr_t up = 0;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig,
+ sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
+ __get_user(up, (compat_uptr_t __user *)sig) ||
+ __get_user(sigsetsize,
+ (compat_size_t __user *)(sig+sizeof(up))))
+ return -EFAULT;
+ }
+ return compat_sys_pselect7(n, inp, outp, exp, tsp, compat_ptr(up),
+ sigsetsize);
+}
+
+asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
+ unsigned int nfds, struct compat_timespec __user *tsp,
+ const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
+{
+ compat_sigset_t ss32;
+ sigset_t ksigmask, sigsaved;
+ struct compat_timespec ts;
+ s64 timeout = -1;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ /* We assume that ts.tv_sec is always lower than
+ the number of seconds that can be expressed in
+ an s64. Otherwise the compiler bitches at us */
+ timeout = ROUND_UP(ts.tv_sec, 1000000000/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+
+ if (sigmask) {
+ if (sigsetsize |= sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+ return -EFAULT;
+ sigset_from_compat(&ksigmask, &ss32);
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_sys_poll(ufds, nfds, &timeout);
+
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ if (tsp && timeout >= 0) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ /* Yes, we know it's actually an s64, but it's also positive. */
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND && timeout >= 0)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
/* Stuff for NFS server syscalls... */
struct compat_nfsctl_svc {
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 43a2508ac696..5dd0207ffd46 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -10,11 +10,11 @@
* ioctls.
*/
-#ifdef INCLUDES
#include <linux/config.h>
#include <linux/types.h>
#include <linux/compat.h>
#include <linux/kernel.h>
+#include <linux/capability.h>
#include <linux/compiler.h>
#include <linux/sched.h>
#include <linux/smp.h>
@@ -81,13 +81,9 @@
#include <linux/capi.h>
#include <scsi/scsi.h>
-/* Ugly hack. */
-#undef __KERNEL__
#include <scsi/scsi_ioctl.h>
-#define __KERNEL__
#include <scsi/sg.h>
-#include <asm/types.h>
#include <asm/uaccess.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -95,7 +91,6 @@
#include <linux/watchdog.h>
#include <linux/dm-ioctl.h>
-#include <asm/module.h>
#include <linux/soundcard.h>
#include <linux/lp.h>
#include <linux/ppdev.h>
@@ -127,11 +122,7 @@
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
-
-#undef INCLUDES
-#endif
-
-#ifdef CODE
+#include <linux/lp.h>
/* Aiee. Someone does not find a difference between int and long */
#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int)
@@ -148,6 +139,12 @@
#define EXT2_IOC32_GETVERSION _IOR('v', 1, int)
#define EXT2_IOC32_SETVERSION _IOW('v', 2, int)
+static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
+ unsigned long arg, struct file *f)
+{
+ return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
+}
+
static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
@@ -207,244 +204,6 @@ static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
}
-struct video_tuner32 {
- compat_int_t tuner;
- char name[32];
- compat_ulong_t rangelow, rangehigh;
- u32 flags; /* It is really u32 in videodev.h */
- u16 mode, signal;
-};
-
-static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
-{
- int i;
-
- if(get_user(kp->tuner, &up->tuner))
- return -EFAULT;
- for(i = 0; i < 32; i++)
- __get_user(kp->name[i], &up->name[i]);
- __get_user(kp->rangelow, &up->rangelow);
- __get_user(kp->rangehigh, &up->rangehigh);
- __get_user(kp->flags, &up->flags);
- __get_user(kp->mode, &up->mode);
- __get_user(kp->signal, &up->signal);
- return 0;
-}
-
-static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
-{
- int i;
-
- if(put_user(kp->tuner, &up->tuner))
- return -EFAULT;
- for(i = 0; i < 32; i++)
- __put_user(kp->name[i], &up->name[i]);
- __put_user(kp->rangelow, &up->rangelow);
- __put_user(kp->rangehigh, &up->rangehigh);
- __put_user(kp->flags, &up->flags);
- __put_user(kp->mode, &up->mode);
- __put_user(kp->signal, &up->signal);
- return 0;
-}
-
-struct video_buffer32 {
- compat_caddr_t base;
- compat_int_t height, width, depth, bytesperline;
-};
-
-static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
-{
- u32 tmp;
-
- if (get_user(tmp, &up->base))
- return -EFAULT;
-
- /* This is actually a physical address stored
- * as a void pointer.
- */
- kp->base = (void *)(unsigned long) tmp;
-
- __get_user(kp->height, &up->height);
- __get_user(kp->width, &up->width);
- __get_user(kp->depth, &up->depth);
- __get_user(kp->bytesperline, &up->bytesperline);
- return 0;
-}
-
-static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
-{
- u32 tmp = (u32)((unsigned long)kp->base);
-
- if(put_user(tmp, &up->base))
- return -EFAULT;
- __put_user(kp->height, &up->height);
- __put_user(kp->width, &up->width);
- __put_user(kp->depth, &up->depth);
- __put_user(kp->bytesperline, &up->bytesperline);
- return 0;
-}
-
-struct video_clip32 {
- s32 x, y, width, height; /* Its really s32 in videodev.h */
- compat_caddr_t next;
-};
-
-struct video_window32 {
- u32 x, y, width, height, chromakey, flags;
- compat_caddr_t clips;
- compat_int_t clipcount;
-};
-
-/* You get back everything except the clips... */
-static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
-{
- if(put_user(kp->x, &up->x))
- return -EFAULT;
- __put_user(kp->y, &up->y);
- __put_user(kp->width, &up->width);
- __put_user(kp->height, &up->height);
- __put_user(kp->chromakey, &up->chromakey);
- __put_user(kp->flags, &up->flags);
- __put_user(kp->clipcount, &up->clipcount);
- return 0;
-}
-
-#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
-#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
-#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
-#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
-#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
-#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
-#define VIDIOCGFREQ32 _IOR('v',14, u32)
-#define VIDIOCSFREQ32 _IOW('v',15, u32)
-
-enum {
- MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
-};
-
-static int do_set_window(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- struct video_window32 __user *up = compat_ptr(arg);
- struct video_window __user *vw;
- struct video_clip __user *p;
- int nclips;
- u32 n;
-
- if (get_user(nclips, &up->clipcount))
- return -EFAULT;
-
- /* Peculiar interface... */
- if (nclips < 0)
- nclips = VIDEO_CLIPMAP_SIZE;
-
- if (nclips > MaxClips)
- return -ENOMEM;
-
- vw = compat_alloc_user_space(sizeof(struct video_window) +
- nclips * sizeof(struct video_clip));
-
- p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
-
- if (get_user(n, &up->x) || put_user(n, &vw->x) ||
- get_user(n, &up->y) || put_user(n, &vw->y) ||
- get_user(n, &up->width) || put_user(n, &vw->width) ||
- get_user(n, &up->height) || put_user(n, &vw->height) ||
- get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
- get_user(n, &up->flags) || put_user(n, &vw->flags) ||
- get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
- get_user(n, &up->clips) || put_user(p, &vw->clips))
- return -EFAULT;
-
- if (nclips) {
- struct video_clip32 __user *u = compat_ptr(n);
- int i;
- if (!u)
- return -EINVAL;
- for (i = 0; i < nclips; i++, u++, p++) {
- s32 v;
- if (get_user(v, &u->x) ||
- put_user(v, &p->x) ||
- get_user(v, &u->y) ||
- put_user(v, &p->y) ||
- get_user(v, &u->width) ||
- put_user(v, &p->width) ||
- get_user(v, &u->height) ||
- put_user(v, &p->height) ||
- put_user(NULL, &p->next))
- return -EFAULT;
- }
- }
-
- return sys_ioctl(fd, VIDIOCSWIN, (unsigned long)p);
-}
-
-static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- union {
- struct video_tuner vt;
- struct video_buffer vb;
- struct video_window vw;
- unsigned long vx;
- } karg;
- mm_segment_t old_fs = get_fs();
- void __user *up = compat_ptr(arg);
- int err = 0;
-
- /* First, convert the command. */
- switch(cmd) {
- case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
- case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
- case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
- case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
- case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
- case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
- case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
- };
-
- switch(cmd) {
- case VIDIOCSTUNER:
- case VIDIOCGTUNER:
- err = get_video_tuner32(&karg.vt, up);
- break;
-
- case VIDIOCSFBUF:
- err = get_video_buffer32(&karg.vb, up);
- break;
-
- case VIDIOCSFREQ:
- err = get_user(karg.vx, (u32 __user *)up);
- break;
- };
- if(err)
- goto out;
-
- set_fs(KERNEL_DS);
- err = sys_ioctl(fd, cmd, (unsigned long)&karg);
- set_fs(old_fs);
-
- if(err == 0) {
- switch(cmd) {
- case VIDIOCGTUNER:
- err = put_video_tuner32(&karg.vt, up);
- break;
-
- case VIDIOCGWIN:
- err = put_video_window32(&karg.vw, up);
- break;
-
- case VIDIOCGFBUF:
- err = put_video_buffer32(&karg.vb, up);
- break;
-
- case VIDIOCGFREQ:
- err = put_user(((u32)karg.vx), (u32 __user *)up);
- break;
- };
- }
-out:
- return err;
-}
-
struct compat_dmx_event {
dmx_event_t event;
compat_time_t timeStamp;
@@ -1158,6 +917,40 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
return err;
}
+struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
+ char req_state;
+ char orphan;
+ char sg_io_owned;
+ char problem;
+ int pack_id;
+ compat_uptr_t usr_ptr;
+ unsigned int duration;
+ int unused;
+};
+
+static int sg_grt_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ int err, i;
+ sg_req_info_t *r;
+ struct compat_sg_req_info *o = (struct compat_sg_req_info *)arg;
+ r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE);
+ err = sys_ioctl(fd,cmd,(unsigned long)r);
+ if (err < 0)
+ return err;
+ for (i = 0; i < SG_MAX_QUEUE; i++) {
+ void __user *ptr;
+ int d;
+
+ if (copy_in_user(o + i, r + i, offsetof(sg_req_info_t, usr_ptr)) ||
+ get_user(ptr, &r[i].usr_ptr) ||
+ get_user(d, &r[i].duration) ||
+ put_user((u32)(unsigned long)(ptr), &o[i].usr_ptr) ||
+ put_user(d, &o[i].duration))
+ return -EFAULT;
+ }
+ return err;
+}
+
struct sock_fprog32 {
unsigned short len;
compat_caddr_t filter;
@@ -2713,6 +2506,49 @@ static int old_bridge_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg
return -EINVAL;
}
+#define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t)
+#define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t)
+#define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t)
+#define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t)
+
+static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg)
+{
+ mm_segment_t oldfs = get_fs();
+ compat_ulong_t val32;
+ unsigned long kval;
+ int ret;
+
+ switch (cmd) {
+ case RTC_IRQP_READ32:
+ case RTC_EPOCH_READ32:
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ?
+ RTC_IRQP_READ : RTC_EPOCH_READ,
+ (unsigned long)&kval);
+ set_fs(oldfs);
+ if (ret)
+ return ret;
+ val32 = kval;
+ return put_user(val32, (unsigned int __user *)arg);
+ case RTC_IRQP_SET32:
+ case RTC_EPOCH_SET32:
+ ret = get_user(val32, (unsigned int __user *)arg);
+ if (ret)
+ return ret;
+ kval = val32;
+
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, (cmd == RTC_IRQP_SET32) ?
+ RTC_IRQP_SET : RTC_EPOCH_SET,
+ (unsigned long)&kval);
+ set_fs(oldfs);
+ return ret;
+ default:
+ /* unreached */
+ return -ENOIOCTLCMD;
+ }
+}
+
#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
struct ncp_ioctl_request_32 {
u32 function;
@@ -2900,10 +2736,34 @@ static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned lon
}
#endif
-#undef CODE
-#endif
+static int
+lp_timeout_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct compat_timeval *tc = (struct compat_timeval *)arg;
+ struct timeval *tn = compat_alloc_user_space(sizeof(struct timeval));
+ struct timeval ts;
+ if (get_user(ts.tv_sec, &tc->tv_sec) ||
+ get_user(ts.tv_usec, &tc->tv_usec) ||
+ put_user(ts.tv_sec, &tn->tv_sec) ||
+ put_user(ts.tv_usec, &tn->tv_usec))
+ return -EFAULT;
+ return sys_ioctl(fd, cmd, (unsigned long)tn);
+}
+
+#define HANDLE_IOCTL(cmd,handler) \
+ { (cmd), (ioctl_trans_handler_t)(handler) },
+
+/* pointer to compatible structure or no argument */
+#define COMPATIBLE_IOCTL(cmd) \
+ { (cmd), do_ioctl32_pointer },
+
+/* argument is an unsigned long integer, not a pointer */
+#define ULONG_IOCTL(cmd) \
+ { (cmd), (ioctl_trans_handler_t)sys_ioctl },
-#ifdef DECLARES
+
+struct ioctl_trans ioctl_start[] = {
+#include <linux/compat_ioctl.h>
HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
#ifdef CONFIG_NET
@@ -2983,6 +2843,7 @@ HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
HANDLE_IOCTL(SG_IO,sg_ioctl_trans)
+HANDLE_IOCTL(SG_GET_REQUEST_TABLE, sg_grt_trans)
HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
HANDLE_IOCTL(PPPIOCSPASS32, ppp_sock_fprog_ioctl_trans)
@@ -3015,14 +2876,6 @@ COMPATIBLE_IOCTL(EXT3_IOC_GROUP_ADD)
#ifdef CONFIG_JBD_DEBUG
HANDLE_IOCTL(EXT3_IOC32_WAIT_FOR_READONLY, do_ext3_ioctl)
#endif
-HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCSWIN32, do_set_window)
-HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl)
-HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
/* One SMB ioctl needs translations. */
#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t)
HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
@@ -3104,6 +2957,10 @@ HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl)
HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl)
HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)
HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl)
+HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl)
+HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
+HANDLE_IOCTL(RTC_EPOCH_SET32, rtc_ioctl)
#if defined(CONFIG_NCP_FS) || defined(CONFIG_NCP_FS_MODULE)
HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest)
@@ -3121,5 +2978,19 @@ HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette)
-#undef DECLARES
-#endif
+/* parport */
+COMPATIBLE_IOCTL(LPTIME)
+COMPATIBLE_IOCTL(LPCHAR)
+COMPATIBLE_IOCTL(LPABORTOPEN)
+COMPATIBLE_IOCTL(LPCAREFUL)
+COMPATIBLE_IOCTL(LPWAIT)
+COMPATIBLE_IOCTL(LPSETIRQ)
+COMPATIBLE_IOCTL(LPGETSTATUS)
+COMPATIBLE_IOCTL(LPGETSTATUS)
+COMPATIBLE_IOCTL(LPRESET)
+/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/
+COMPATIBLE_IOCTL(LPGETFLAGS)
+HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
+};
+
+int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff --git a/fs/configfs/Makefile b/fs/configfs/Makefile
new file mode 100644
index 000000000000..00ffb278e98c
--- /dev/null
+++ b/fs/configfs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the configfs virtual filesystem
+#
+
+obj-$(CONFIG_CONFIGFS_FS) += configfs.o
+
+configfs-objs := inode.o file.o dir.o symlink.o mount.o item.o
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
new file mode 100644
index 000000000000..8899d9c5f6bf
--- /dev/null
+++ b/fs/configfs/configfs_internal.h
@@ -0,0 +1,142 @@
+/* -*- mode: c; c-basic-offset:8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * configfs_internal.h - Internal stuff for configfs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#include <linux/slab.h>
+#include <linux/list.h>
+
+struct configfs_dirent {
+ atomic_t s_count;
+ struct list_head s_sibling;
+ struct list_head s_children;
+ struct list_head s_links;
+ void * s_element;
+ int s_type;
+ umode_t s_mode;
+ struct dentry * s_dentry;
+};
+
+#define CONFIGFS_ROOT 0x0001
+#define CONFIGFS_DIR 0x0002
+#define CONFIGFS_ITEM_ATTR 0x0004
+#define CONFIGFS_ITEM_LINK 0x0020
+#define CONFIGFS_USET_DIR 0x0040
+#define CONFIGFS_USET_DEFAULT 0x0080
+#define CONFIGFS_USET_DROPPING 0x0100
+#define CONFIGFS_NOT_PINNED (CONFIGFS_ITEM_ATTR)
+
+extern struct vfsmount * configfs_mount;
+
+extern int configfs_is_root(struct config_item *item);
+
+extern struct inode * configfs_new_inode(mode_t mode);
+extern int configfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+
+extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
+extern int configfs_make_dirent(struct configfs_dirent *,
+ struct dentry *, void *, umode_t, int);
+
+extern int configfs_add_file(struct dentry *, const struct configfs_attribute *, int);
+extern void configfs_hash_and_remove(struct dentry * dir, const char * name);
+
+extern const unsigned char * configfs_get_name(struct configfs_dirent *sd);
+extern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent);
+
+extern int configfs_pin_fs(void);
+extern void configfs_release_fs(void);
+
+extern struct rw_semaphore configfs_rename_sem;
+extern struct super_block * configfs_sb;
+extern struct file_operations configfs_dir_operations;
+extern struct file_operations configfs_file_operations;
+extern struct file_operations bin_fops;
+extern struct inode_operations configfs_dir_inode_operations;
+extern struct inode_operations configfs_symlink_inode_operations;
+
+extern int configfs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname);
+extern int configfs_unlink(struct inode *dir, struct dentry *dentry);
+
+struct configfs_symlink {
+ struct list_head sl_list;
+ struct config_item *sl_target;
+};
+
+extern int configfs_create_link(struct configfs_symlink *sl,
+ struct dentry *parent,
+ struct dentry *dentry);
+
+static inline struct config_item * to_item(struct dentry * dentry)
+{
+ struct configfs_dirent * sd = dentry->d_fsdata;
+ return ((struct config_item *) sd->s_element);
+}
+
+static inline struct configfs_attribute * to_attr(struct dentry * dentry)
+{
+ struct configfs_dirent * sd = dentry->d_fsdata;
+ return ((struct configfs_attribute *) sd->s_element);
+}
+
+static inline struct config_item *configfs_get_config_item(struct dentry *dentry)
+{
+ struct config_item * item = NULL;
+
+ spin_lock(&dcache_lock);
+ if (!d_unhashed(dentry)) {
+ struct configfs_dirent * sd = dentry->d_fsdata;
+ if (sd->s_type & CONFIGFS_ITEM_LINK) {
+ struct configfs_symlink * sl = sd->s_element;
+ item = config_item_get(sl->sl_target);
+ } else
+ item = config_item_get(sd->s_element);
+ }
+ spin_unlock(&dcache_lock);
+
+ return item;
+}
+
+static inline void release_configfs_dirent(struct configfs_dirent * sd)
+{
+ if (!(sd->s_type & CONFIGFS_ROOT))
+ kfree(sd);
+}
+
+static inline struct configfs_dirent * configfs_get(struct configfs_dirent * sd)
+{
+ if (sd) {
+ WARN_ON(!atomic_read(&sd->s_count));
+ atomic_inc(&sd->s_count);
+ }
+ return sd;
+}
+
+static inline void configfs_put(struct configfs_dirent * sd)
+{
+ WARN_ON(!atomic_read(&sd->s_count));
+ if (atomic_dec_and_test(&sd->s_count))
+ release_configfs_dirent(sd);
+}
+
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
new file mode 100644
index 000000000000..b668ec61527e
--- /dev/null
+++ b/fs/configfs/dir.c
@@ -0,0 +1,1102 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir.c - Operations for configfs directories.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#undef DEBUG
+
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+#include "configfs_internal.h"
+
+DECLARE_RWSEM(configfs_rename_sem);
+
+static void configfs_d_iput(struct dentry * dentry,
+ struct inode * inode)
+{
+ struct configfs_dirent * sd = dentry->d_fsdata;
+
+ if (sd) {
+ BUG_ON(sd->s_dentry != dentry);
+ sd->s_dentry = NULL;
+ configfs_put(sd);
+ }
+ iput(inode);
+}
+
+/*
+ * We _must_ delete our dentries on last dput, as the chain-to-parent
+ * behavior is required to clear the parents of default_groups.
+ */
+static int configfs_d_delete(struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct dentry_operations configfs_dentry_ops = {
+ .d_iput = configfs_d_iput,
+ /* simple_delete_dentry() isn't exported */
+ .d_delete = configfs_d_delete,
+};
+
+/*
+ * Allocates a new configfs_dirent and links it to the parent configfs_dirent
+ */
+static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * parent_sd,
+ void * element)
+{
+ struct configfs_dirent * sd;
+
+ sd = kmalloc(sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return NULL;
+
+ memset(sd, 0, sizeof(*sd));
+ atomic_set(&sd->s_count, 1);
+ INIT_LIST_HEAD(&sd->s_links);
+ INIT_LIST_HEAD(&sd->s_children);
+ list_add(&sd->s_sibling, &parent_sd->s_children);
+ sd->s_element = element;
+
+ return sd;
+}
+
+int configfs_make_dirent(struct configfs_dirent * parent_sd,
+ struct dentry * dentry, void * element,
+ umode_t mode, int type)
+{
+ struct configfs_dirent * sd;
+
+ sd = configfs_new_dirent(parent_sd, element);
+ if (!sd)
+ return -ENOMEM;
+
+ sd->s_mode = mode;
+ sd->s_type = type;
+ sd->s_dentry = dentry;
+ if (dentry) {
+ dentry->d_fsdata = configfs_get(sd);
+ dentry->d_op = &configfs_dentry_ops;
+ }
+
+ return 0;
+}
+
+static int init_dir(struct inode * inode)
+{
+ inode->i_op = &configfs_dir_inode_operations;
+ inode->i_fop = &configfs_dir_operations;
+
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ return 0;
+}
+
+static int init_file(struct inode * inode)
+{
+ inode->i_size = PAGE_SIZE;
+ inode->i_fop = &configfs_file_operations;
+ return 0;
+}
+
+static int init_symlink(struct inode * inode)
+{
+ inode->i_op = &configfs_symlink_inode_operations;
+ return 0;
+}
+
+static int create_dir(struct config_item * k, struct dentry * p,
+ struct dentry * d)
+{
+ int error;
+ umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+
+ error = configfs_create(d, mode, init_dir);
+ if (!error) {
+ error = configfs_make_dirent(p->d_fsdata, d, k, mode,
+ CONFIGFS_DIR);
+ if (!error) {
+ p->d_inode->i_nlink++;
+ (d)->d_op = &configfs_dentry_ops;
+ }
+ }
+ return error;
+}
+
+
+/**
+ * configfs_create_dir - create a directory for an config_item.
+ * @item: config_itemwe're creating directory for.
+ * @dentry: config_item's dentry.
+ */
+
+static int configfs_create_dir(struct config_item * item, struct dentry *dentry)
+{
+ struct dentry * parent;
+ int error = 0;
+
+ BUG_ON(!item);
+
+ if (item->ci_parent)
+ parent = item->ci_parent->ci_dentry;
+ else if (configfs_mount && configfs_mount->mnt_sb)
+ parent = configfs_mount->mnt_sb->s_root;
+ else
+ return -EFAULT;
+
+ error = create_dir(item,parent,dentry);
+ if (!error)
+ item->ci_dentry = dentry;
+ return error;
+}
+
+int configfs_create_link(struct configfs_symlink *sl,
+ struct dentry *parent,
+ struct dentry *dentry)
+{
+ int err = 0;
+ umode_t mode = S_IFLNK | S_IRWXUGO;
+
+ err = configfs_create(dentry, mode, init_symlink);
+ if (!err) {
+ err = configfs_make_dirent(parent->d_fsdata, dentry, sl,
+ mode, CONFIGFS_ITEM_LINK);
+ if (!err)
+ dentry->d_op = &configfs_dentry_ops;
+ }
+ return err;
+}
+
+static void remove_dir(struct dentry * d)
+{
+ struct dentry * parent = dget(d->d_parent);
+ struct configfs_dirent * sd;
+
+ sd = d->d_fsdata;
+ list_del_init(&sd->s_sibling);
+ configfs_put(sd);
+ if (d->d_inode)
+ simple_rmdir(parent->d_inode,d);
+
+ pr_debug(" o %s removing done (%d)\n",d->d_name.name,
+ atomic_read(&d->d_count));
+
+ dput(parent);
+}
+
+/**
+ * configfs_remove_dir - remove an config_item's directory.
+ * @item: config_item we're removing.
+ *
+ * The only thing special about this is that we remove any files in
+ * the directory before we remove the directory, and we've inlined
+ * what used to be configfs_rmdir() below, instead of calling separately.
+ */
+
+static void configfs_remove_dir(struct config_item * item)
+{
+ struct dentry * dentry = dget(item->ci_dentry);
+
+ if (!dentry)
+ return;
+
+ remove_dir(dentry);
+ /**
+ * Drop reference from dget() on entrance.
+ */
+ dput(dentry);
+}
+
+
+/* attaches attribute's configfs_dirent to the dentry corresponding to the
+ * attribute file
+ */
+static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * dentry)
+{
+ struct configfs_attribute * attr = sd->s_element;
+ int error;
+
+ error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, init_file);
+ if (error)
+ return error;
+
+ dentry->d_op = &configfs_dentry_ops;
+ dentry->d_fsdata = configfs_get(sd);
+ sd->s_dentry = dentry;
+ d_rehash(dentry);
+
+ return 0;
+}
+
+static struct dentry * configfs_lookup(struct inode *dir,
+ struct dentry *dentry,
+ struct nameidata *nd)
+{
+ struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
+ struct configfs_dirent * sd;
+ int found = 0;
+ int err = 0;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_type & CONFIGFS_NOT_PINNED) {
+ const unsigned char * name = configfs_get_name(sd);
+
+ if (strcmp(name, dentry->d_name.name))
+ continue;
+
+ found = 1;
+ err = configfs_attach_attr(sd, dentry);
+ break;
+ }
+ }
+
+ if (!found) {
+ /*
+ * If it doesn't exist and it isn't a NOT_PINNED item,
+ * it must be negative.
+ */
+ return simple_lookup(dir, dentry, nd);
+ }
+
+ return ERR_PTR(err);
+}
+
+/*
+ * Only subdirectories count here. Files (CONFIGFS_NOT_PINNED) are
+ * attributes and are removed by rmdir(). We recurse, taking i_mutex
+ * on all children that are candidates for default detach. If the
+ * result is clean, then configfs_detach_group() will handle dropping
+ * i_mutex. If there is an error, the caller will clean up the i_mutex
+ * holders via configfs_detach_rollback().
+ */
+static int configfs_detach_prep(struct dentry *dentry)
+{
+ struct configfs_dirent *parent_sd = dentry->d_fsdata;
+ struct configfs_dirent *sd;
+ int ret;
+
+ ret = -EBUSY;
+ if (!list_empty(&parent_sd->s_links))
+ goto out;
+
+ ret = 0;
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_type & CONFIGFS_NOT_PINNED)
+ continue;
+ if (sd->s_type & CONFIGFS_USET_DEFAULT) {
+ mutex_lock(&sd->s_dentry->d_inode->i_mutex);
+ /* Mark that we've taken i_mutex */
+ sd->s_type |= CONFIGFS_USET_DROPPING;
+
+ ret = configfs_detach_prep(sd->s_dentry);
+ if (!ret)
+ continue;
+ } else
+ ret = -ENOTEMPTY;
+
+ break;
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * Walk the tree, dropping i_mutex wherever CONFIGFS_USET_DROPPING is
+ * set.
+ */
+static void configfs_detach_rollback(struct dentry *dentry)
+{
+ struct configfs_dirent *parent_sd = dentry->d_fsdata;
+ struct configfs_dirent *sd;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_type & CONFIGFS_USET_DEFAULT) {
+ configfs_detach_rollback(sd->s_dentry);
+
+ if (sd->s_type & CONFIGFS_USET_DROPPING) {
+ sd->s_type &= ~CONFIGFS_USET_DROPPING;
+ mutex_unlock(&sd->s_dentry->d_inode->i_mutex);
+ }
+ }
+ }
+}
+
+static void detach_attrs(struct config_item * item)
+{
+ struct dentry * dentry = dget(item->ci_dentry);
+ struct configfs_dirent * parent_sd;
+ struct configfs_dirent * sd, * tmp;
+
+ if (!dentry)
+ return;
+
+ pr_debug("configfs %s: dropping attrs for dir\n",
+ dentry->d_name.name);
+
+ parent_sd = dentry->d_fsdata;
+ list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
+ if (!sd->s_element || !(sd->s_type & CONFIGFS_NOT_PINNED))
+ continue;
+ list_del_init(&sd->s_sibling);
+ configfs_drop_dentry(sd, dentry);
+ configfs_put(sd);
+ }
+
+ /**
+ * Drop reference from dget() on entrance.
+ */
+ dput(dentry);
+}
+
+static int populate_attrs(struct config_item *item)
+{
+ struct config_item_type *t = item->ci_type;
+ struct configfs_attribute *attr;
+ int error = 0;
+ int i;
+
+ if (!t)
+ return -EINVAL;
+ if (t->ct_attrs) {
+ for (i = 0; (attr = t->ct_attrs[i]) != NULL; i++) {
+ if ((error = configfs_create_file(item, attr)))
+ break;
+ }
+ }
+
+ if (error)
+ detach_attrs(item);
+
+ return error;
+}
+
+static int configfs_attach_group(struct config_item *parent_item,
+ struct config_item *item,
+ struct dentry *dentry);
+static void configfs_detach_group(struct config_item *item);
+
+static void detach_groups(struct config_group *group)
+{
+ struct dentry * dentry = dget(group->cg_item.ci_dentry);
+ struct dentry *child;
+ struct configfs_dirent *parent_sd;
+ struct configfs_dirent *sd, *tmp;
+
+ if (!dentry)
+ return;
+
+ parent_sd = dentry->d_fsdata;
+ list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
+ if (!sd->s_element ||
+ !(sd->s_type & CONFIGFS_USET_DEFAULT))
+ continue;
+
+ child = sd->s_dentry;
+
+ configfs_detach_group(sd->s_element);
+ child->d_inode->i_flags |= S_DEAD;
+
+ /*
+ * From rmdir/unregister, a configfs_detach_prep() pass
+ * has taken our i_mutex for us. Drop it.
+ * From mkdir/register cleanup, there is no sem held.
+ */
+ if (sd->s_type & CONFIGFS_USET_DROPPING)
+ mutex_unlock(&child->d_inode->i_mutex);
+
+ d_delete(child);
+ dput(child);
+ }
+
+ /**
+ * Drop reference from dget() on entrance.
+ */
+ dput(dentry);
+}
+
+/*
+ * This fakes mkdir(2) on a default_groups[] entry. It
+ * creates a dentry, attachs it, and then does fixup
+ * on the sd->s_type.
+ *
+ * We could, perhaps, tweak our parent's ->mkdir for a minute and
+ * try using vfs_mkdir. Just a thought.
+ */
+static int create_default_group(struct config_group *parent_group,
+ struct config_group *group)
+{
+ int ret;
+ struct qstr name;
+ struct configfs_dirent *sd;
+ /* We trust the caller holds a reference to parent */
+ struct dentry *child, *parent = parent_group->cg_item.ci_dentry;
+
+ if (!group->cg_item.ci_name)
+ group->cg_item.ci_name = group->cg_item.ci_namebuf;
+ name.name = group->cg_item.ci_name;
+ name.len = strlen(name.name);
+ name.hash = full_name_hash(name.name, name.len);
+
+ ret = -ENOMEM;
+ child = d_alloc(parent, &name);
+ if (child) {
+ d_add(child, NULL);
+
+ ret = configfs_attach_group(&parent_group->cg_item,
+ &group->cg_item, child);
+ if (!ret) {
+ sd = child->d_fsdata;
+ sd->s_type |= CONFIGFS_USET_DEFAULT;
+ } else {
+ d_delete(child);
+ dput(child);
+ }
+ }
+
+ return ret;
+}
+
+static int populate_groups(struct config_group *group)
+{
+ struct config_group *new_group;
+ struct dentry *dentry = group->cg_item.ci_dentry;
+ int ret = 0;
+ int i;
+
+ if (group && group->default_groups) {
+ /* FYI, we're faking mkdir here
+ * I'm not sure we need this semaphore, as we're called
+ * from our parent's mkdir. That holds our parent's
+ * i_mutex, so afaik lookup cannot continue through our
+ * parent to find us, let alone mess with our tree.
+ * That said, taking our i_mutex is closer to mkdir
+ * emulation, and shouldn't hurt. */
+ mutex_lock(&dentry->d_inode->i_mutex);
+
+ for (i = 0; group->default_groups[i]; i++) {
+ new_group = group->default_groups[i];
+
+ ret = create_default_group(group, new_group);
+ if (ret)
+ break;
+ }
+
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ }
+
+ if (ret)
+ detach_groups(group);
+
+ return ret;
+}
+
+/*
+ * All of link_obj/unlink_obj/link_group/unlink_group require that
+ * subsys->su_sem is held.
+ */
+
+static void unlink_obj(struct config_item *item)
+{
+ struct config_group *group;
+
+ group = item->ci_group;
+ if (group) {
+ list_del_init(&item->ci_entry);
+
+ item->ci_group = NULL;
+ item->ci_parent = NULL;
+ config_item_put(item);
+
+ config_group_put(group);
+ }
+}
+
+static void link_obj(struct config_item *parent_item, struct config_item *item)
+{
+ /* Parent seems redundant with group, but it makes certain
+ * traversals much nicer. */
+ item->ci_parent = parent_item;
+ item->ci_group = config_group_get(to_config_group(parent_item));
+ list_add_tail(&item->ci_entry, &item->ci_group->cg_children);
+
+ config_item_get(item);
+}
+
+static void unlink_group(struct config_group *group)
+{
+ int i;
+ struct config_group *new_group;
+
+ if (group->default_groups) {
+ for (i = 0; group->default_groups[i]; i++) {
+ new_group = group->default_groups[i];
+ unlink_group(new_group);
+ }
+ }
+
+ group->cg_subsys = NULL;
+ unlink_obj(&group->cg_item);
+}
+
+static void link_group(struct config_group *parent_group, struct config_group *group)
+{
+ int i;
+ struct config_group *new_group;
+ struct configfs_subsystem *subsys = NULL; /* gcc is a turd */
+
+ link_obj(&parent_group->cg_item, &group->cg_item);
+
+ if (parent_group->cg_subsys)
+ subsys = parent_group->cg_subsys;
+ else if (configfs_is_root(&parent_group->cg_item))
+ subsys = to_configfs_subsystem(group);
+ else
+ BUG();
+ group->cg_subsys = subsys;
+
+ if (group->default_groups) {
+ for (i = 0; group->default_groups[i]; i++) {
+ new_group = group->default_groups[i];
+ link_group(group, new_group);
+ }
+ }
+}
+
+/*
+ * The goal is that configfs_attach_item() (and
+ * configfs_attach_group()) can be called from either the VFS or this
+ * module. That is, they assume that the items have been created,
+ * the dentry allocated, and the dcache is all ready to go.
+ *
+ * If they fail, they must clean up after themselves as if they
+ * had never been called. The caller (VFS or local function) will
+ * handle cleaning up the dcache bits.
+ *
+ * configfs_detach_group() and configfs_detach_item() behave similarly on
+ * the way out. They assume that the proper semaphores are held, they
+ * clean up the configfs items, and they expect their callers will
+ * handle the dcache bits.
+ */
+static int configfs_attach_item(struct config_item *parent_item,
+ struct config_item *item,
+ struct dentry *dentry)
+{
+ int ret;
+
+ ret = configfs_create_dir(item, dentry);
+ if (!ret) {
+ ret = populate_attrs(item);
+ if (ret) {
+ configfs_remove_dir(item);
+ d_delete(dentry);
+ }
+ }
+
+ return ret;
+}
+
+static void configfs_detach_item(struct config_item *item)
+{
+ detach_attrs(item);
+ configfs_remove_dir(item);
+}
+
+static int configfs_attach_group(struct config_item *parent_item,
+ struct config_item *item,
+ struct dentry *dentry)
+{
+ int ret;
+ struct configfs_dirent *sd;
+
+ ret = configfs_attach_item(parent_item, item, dentry);
+ if (!ret) {
+ sd = dentry->d_fsdata;
+ sd->s_type |= CONFIGFS_USET_DIR;
+
+ ret = populate_groups(to_config_group(item));
+ if (ret) {
+ configfs_detach_item(item);
+ d_delete(dentry);
+ }
+ }
+
+ return ret;
+}
+
+static void configfs_detach_group(struct config_item *item)
+{
+ detach_groups(to_config_group(item));
+ configfs_detach_item(item);
+}
+
+/*
+ * Drop the initial reference from make_item()/make_group()
+ * This function assumes that reference is held on item
+ * and that item holds a valid reference to the parent. Also, it
+ * assumes the caller has validated ci_type.
+ */
+static void client_drop_item(struct config_item *parent_item,
+ struct config_item *item)
+{
+ struct config_item_type *type;
+
+ type = parent_item->ci_type;
+ BUG_ON(!type);
+
+ if (type->ct_group_ops && type->ct_group_ops->drop_item)
+ type->ct_group_ops->drop_item(to_config_group(parent_item),
+ item);
+ else
+ config_item_put(item);
+}
+
+
+static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int ret;
+ struct config_group *group;
+ struct config_item *item;
+ struct config_item *parent_item;
+ struct configfs_subsystem *subsys;
+ struct configfs_dirent *sd;
+ struct config_item_type *type;
+ struct module *owner;
+ char *name;
+
+ if (dentry->d_parent == configfs_sb->s_root)
+ return -EPERM;
+
+ sd = dentry->d_parent->d_fsdata;
+ if (!(sd->s_type & CONFIGFS_USET_DIR))
+ return -EPERM;
+
+ parent_item = configfs_get_config_item(dentry->d_parent);
+ type = parent_item->ci_type;
+ subsys = to_config_group(parent_item)->cg_subsys;
+ BUG_ON(!subsys);
+
+ if (!type || !type->ct_group_ops ||
+ (!type->ct_group_ops->make_group &&
+ !type->ct_group_ops->make_item)) {
+ config_item_put(parent_item);
+ return -EPERM; /* What lack-of-mkdir returns */
+ }
+
+ name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL);
+ if (!name) {
+ config_item_put(parent_item);
+ return -ENOMEM;
+ }
+ snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
+
+ down(&subsys->su_sem);
+ group = NULL;
+ item = NULL;
+ if (type->ct_group_ops->make_group) {
+ group = type->ct_group_ops->make_group(to_config_group(parent_item), name);
+ if (group) {
+ link_group(to_config_group(parent_item), group);
+ item = &group->cg_item;
+ }
+ } else {
+ item = type->ct_group_ops->make_item(to_config_group(parent_item), name);
+ if (item)
+ link_obj(parent_item, item);
+ }
+ up(&subsys->su_sem);
+
+ kfree(name);
+ if (!item) {
+ config_item_put(parent_item);
+ return -ENOMEM;
+ }
+
+ ret = -EINVAL;
+ type = item->ci_type;
+ if (type) {
+ owner = type->ct_owner;
+ if (try_module_get(owner)) {
+ if (group) {
+ ret = configfs_attach_group(parent_item,
+ item,
+ dentry);
+ } else {
+ ret = configfs_attach_item(parent_item,
+ item,
+ dentry);
+ }
+
+ if (ret) {
+ down(&subsys->su_sem);
+ if (group)
+ unlink_group(group);
+ else
+ unlink_obj(item);
+ client_drop_item(parent_item, item);
+ up(&subsys->su_sem);
+
+ config_item_put(parent_item);
+ module_put(owner);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ struct config_item *parent_item;
+ struct config_item *item;
+ struct configfs_subsystem *subsys;
+ struct configfs_dirent *sd;
+ struct module *owner = NULL;
+ int ret;
+
+ if (dentry->d_parent == configfs_sb->s_root)
+ return -EPERM;
+
+ sd = dentry->d_fsdata;
+ if (sd->s_type & CONFIGFS_USET_DEFAULT)
+ return -EPERM;
+
+ parent_item = configfs_get_config_item(dentry->d_parent);
+ subsys = to_config_group(parent_item)->cg_subsys;
+ BUG_ON(!subsys);
+
+ if (!parent_item->ci_type) {
+ config_item_put(parent_item);
+ return -EINVAL;
+ }
+
+ ret = configfs_detach_prep(dentry);
+ if (ret) {
+ configfs_detach_rollback(dentry);
+ config_item_put(parent_item);
+ return ret;
+ }
+
+ item = configfs_get_config_item(dentry);
+
+ /* Drop reference from above, item already holds one. */
+ config_item_put(parent_item);
+
+ if (item->ci_type)
+ owner = item->ci_type->ct_owner;
+
+ if (sd->s_type & CONFIGFS_USET_DIR) {
+ configfs_detach_group(item);
+
+ down(&subsys->su_sem);
+ unlink_group(to_config_group(item));
+ } else {
+ configfs_detach_item(item);
+
+ down(&subsys->su_sem);
+ unlink_obj(item);
+ }
+
+ client_drop_item(parent_item, item);
+ up(&subsys->su_sem);
+
+ /* Drop our reference from above */
+ config_item_put(item);
+
+ module_put(owner);
+
+ return 0;
+}
+
+struct inode_operations configfs_dir_inode_operations = {
+ .mkdir = configfs_mkdir,
+ .rmdir = configfs_rmdir,
+ .symlink = configfs_symlink,
+ .unlink = configfs_unlink,
+ .lookup = configfs_lookup,
+};
+
+#if 0
+int configfs_rename_dir(struct config_item * item, const char *new_name)
+{
+ int error = 0;
+ struct dentry * new_dentry, * parent;
+
+ if (!strcmp(config_item_name(item), new_name))
+ return -EINVAL;
+
+ if (!item->parent)
+ return -EINVAL;
+
+ down_write(&configfs_rename_sem);
+ parent = item->parent->dentry;
+
+ mutex_lock(&parent->d_inode->i_mutex);
+
+ new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
+ if (!IS_ERR(new_dentry)) {
+ if (!new_dentry->d_inode) {
+ error = config_item_set_name(item, "%s", new_name);
+ if (!error) {
+ d_add(new_dentry, NULL);
+ d_move(item->dentry, new_dentry);
+ }
+ else
+ d_delete(new_dentry);
+ } else
+ error = -EEXIST;
+ dput(new_dentry);
+ }
+ mutex_unlock(&parent->d_inode->i_mutex);
+ up_write(&configfs_rename_sem);
+
+ return error;
+}
+#endif
+
+static int configfs_dir_open(struct inode *inode, struct file *file)
+{
+ struct dentry * dentry = file->f_dentry;
+ struct configfs_dirent * parent_sd = dentry->d_fsdata;
+
+ mutex_lock(&dentry->d_inode->i_mutex);
+ file->private_data = configfs_new_dirent(parent_sd, NULL);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+
+ return file->private_data ? 0 : -ENOMEM;
+
+}
+
+static int configfs_dir_close(struct inode *inode, struct file *file)
+{
+ struct dentry * dentry = file->f_dentry;
+ struct configfs_dirent * cursor = file->private_data;
+
+ mutex_lock(&dentry->d_inode->i_mutex);
+ list_del_init(&cursor->s_sibling);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+
+ release_configfs_dirent(cursor);
+
+ return 0;
+}
+
+/* Relationship between s_mode and the DT_xxx types */
+static inline unsigned char dt_type(struct configfs_dirent *sd)
+{
+ return (sd->s_mode >> 12) & 15;
+}
+
+static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+ struct dentry *dentry = filp->f_dentry;
+ struct configfs_dirent * parent_sd = dentry->d_fsdata;
+ struct configfs_dirent *cursor = filp->private_data;
+ struct list_head *p, *q = &cursor->s_sibling;
+ ino_t ino;
+ int i = filp->f_pos;
+
+ switch (i) {
+ case 0:
+ ino = dentry->d_inode->i_ino;
+ if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+ break;
+ filp->f_pos++;
+ i++;
+ /* fallthrough */
+ case 1:
+ ino = parent_ino(dentry);
+ if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+ break;
+ filp->f_pos++;
+ i++;
+ /* fallthrough */
+ default:
+ if (filp->f_pos == 2) {
+ list_del(q);
+ list_add(q, &parent_sd->s_children);
+ }
+ for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
+ struct configfs_dirent *next;
+ const char * name;
+ int len;
+
+ next = list_entry(p, struct configfs_dirent,
+ s_sibling);
+ if (!next->s_element)
+ continue;
+
+ name = configfs_get_name(next);
+ len = strlen(name);
+ if (next->s_dentry)
+ ino = next->s_dentry->d_inode->i_ino;
+ else
+ ino = iunique(configfs_sb, 2);
+
+ if (filldir(dirent, name, len, filp->f_pos, ino,
+ dt_type(next)) < 0)
+ return 0;
+
+ list_del(q);
+ list_add(q, p);
+ p = q;
+ filp->f_pos++;
+ }
+ }
+ return 0;
+}
+
+static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin)
+{
+ struct dentry * dentry = file->f_dentry;
+
+ mutex_lock(&dentry->d_inode->i_mutex);
+ switch (origin) {
+ case 1:
+ offset += file->f_pos;
+ case 0:
+ if (offset >= 0)
+ break;
+ default:
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ return -EINVAL;
+ }
+ if (offset != file->f_pos) {
+ file->f_pos = offset;
+ if (file->f_pos >= 2) {
+ struct configfs_dirent *sd = dentry->d_fsdata;
+ struct configfs_dirent *cursor = file->private_data;
+ struct list_head *p;
+ loff_t n = file->f_pos - 2;
+
+ list_del(&cursor->s_sibling);
+ p = sd->s_children.next;
+ while (n && p != &sd->s_children) {
+ struct configfs_dirent *next;
+ next = list_entry(p, struct configfs_dirent,
+ s_sibling);
+ if (next->s_element)
+ n--;
+ p = p->next;
+ }
+ list_add_tail(&cursor->s_sibling, p);
+ }
+ }
+ mutex_unlock(&dentry->d_inode->i_mutex);
+ return offset;
+}
+
+struct file_operations configfs_dir_operations = {
+ .open = configfs_dir_open,
+ .release = configfs_dir_close,
+ .llseek = configfs_dir_lseek,
+ .read = generic_read_dir,
+ .readdir = configfs_readdir,
+};
+
+int configfs_register_subsystem(struct configfs_subsystem *subsys)
+{
+ int err;
+ struct config_group *group = &subsys->su_group;
+ struct qstr name;
+ struct dentry *dentry;
+ struct configfs_dirent *sd;
+
+ err = configfs_pin_fs();
+ if (err)
+ return err;
+
+ if (!group->cg_item.ci_name)
+ group->cg_item.ci_name = group->cg_item.ci_namebuf;
+
+ sd = configfs_sb->s_root->d_fsdata;
+ link_group(to_config_group(sd->s_element), group);
+
+ mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
+
+ name.name = group->cg_item.ci_name;
+ name.len = strlen(name.name);
+ name.hash = full_name_hash(name.name, name.len);
+
+ err = -ENOMEM;
+ dentry = d_alloc(configfs_sb->s_root, &name);
+ if (!dentry)
+ goto out_release;
+
+ d_add(dentry, NULL);
+
+ err = configfs_attach_group(sd->s_element, &group->cg_item,
+ dentry);
+ if (!err)
+ dentry = NULL;
+ else
+ d_delete(dentry);
+
+ mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+
+ if (dentry) {
+ dput(dentry);
+out_release:
+ unlink_group(group);
+ configfs_release_fs();
+ }
+
+ return err;
+}
+
+void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
+{
+ struct config_group *group = &subsys->su_group;
+ struct dentry *dentry = group->cg_item.ci_dentry;
+
+ if (dentry->d_parent != configfs_sb->s_root) {
+ printk(KERN_ERR "configfs: Tried to unregister non-subsystem!\n");
+ return;
+ }
+
+ mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
+ mutex_lock(&dentry->d_inode->i_mutex);
+ if (configfs_detach_prep(dentry)) {
+ printk(KERN_ERR "configfs: Tried to unregister non-empty subsystem!\n");
+ }
+ configfs_detach_group(&group->cg_item);
+ dentry->d_inode->i_flags |= S_DEAD;
+ mutex_unlock(&dentry->d_inode->i_mutex);
+
+ d_delete(dentry);
+
+ mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
+
+ dput(dentry);
+
+ unlink_group(group);
+ configfs_release_fs();
+}
+
+EXPORT_SYMBOL(configfs_register_subsystem);
+EXPORT_SYMBOL(configfs_unregister_subsystem);
diff --git a/fs/configfs/file.c b/fs/configfs/file.c
new file mode 100644
index 000000000000..c26cd61f13af
--- /dev/null
+++ b/fs/configfs/file.c
@@ -0,0 +1,360 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * file.c - operations for regular (text) files.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/dnotify.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include <linux/configfs.h>
+#include "configfs_internal.h"
+
+
+struct configfs_buffer {
+ size_t count;
+ loff_t pos;
+ char * page;
+ struct configfs_item_operations * ops;
+ struct semaphore sem;
+ int needs_read_fill;
+};
+
+
+/**
+ * fill_read_buffer - allocate and fill buffer from item.
+ * @dentry: dentry pointer.
+ * @buffer: data buffer for file.
+ *
+ * Allocate @buffer->page, if it hasn't been already, then call the
+ * config_item's show() method to fill the buffer with this attribute's
+ * data.
+ * This is called only once, on the file's first read.
+ */
+static int fill_read_buffer(struct dentry * dentry, struct configfs_buffer * buffer)
+{
+ struct configfs_attribute * attr = to_attr(dentry);
+ struct config_item * item = to_item(dentry->d_parent);
+ struct configfs_item_operations * ops = buffer->ops;
+ int ret = 0;
+ ssize_t count;
+
+ if (!buffer->page)
+ buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
+ if (!buffer->page)
+ return -ENOMEM;
+
+ count = ops->show_attribute(item,attr,buffer->page);
+ buffer->needs_read_fill = 0;
+ BUG_ON(count > (ssize_t)PAGE_SIZE);
+ if (count >= 0)
+ buffer->count = count;
+ else
+ ret = count;
+ return ret;
+}
+
+
+/**
+ * flush_read_buffer - push buffer to userspace.
+ * @buffer: data buffer for file.
+ * @userbuf: user-passed buffer.
+ * @count: number of bytes requested.
+ * @ppos: file position.
+ *
+ * Copy the buffer we filled in fill_read_buffer() to userspace.
+ * This is done at the reader's leisure, copying and advancing
+ * the amount they specify each time.
+ * This may be called continuously until the buffer is empty.
+ */
+static int flush_read_buffer(struct configfs_buffer * buffer, char __user * buf,
+ size_t count, loff_t * ppos)
+{
+ int error;
+
+ if (*ppos > buffer->count)
+ return 0;
+
+ if (count > (buffer->count - *ppos))
+ count = buffer->count - *ppos;
+
+ error = copy_to_user(buf,buffer->page + *ppos,count);
+ if (!error)
+ *ppos += count;
+ return error ? -EFAULT : count;
+}
+
+/**
+ * configfs_read_file - read an attribute.
+ * @file: file pointer.
+ * @buf: buffer to fill.
+ * @count: number of bytes to read.
+ * @ppos: starting offset in file.
+ *
+ * Userspace wants to read an attribute file. The attribute descriptor
+ * is in the file's ->d_fsdata. The target item is in the directory's
+ * ->d_fsdata.
+ *
+ * We call fill_read_buffer() to allocate and fill the buffer from the
+ * item's show() method exactly once (if the read is happening from
+ * the beginning of the file). That should fill the entire buffer with
+ * all the data the item has to offer for that attribute.
+ * We then call flush_read_buffer() to copy the buffer to userspace
+ * in the increments specified.
+ */
+
+static ssize_t
+configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct configfs_buffer * buffer = file->private_data;
+ ssize_t retval = 0;
+
+ down(&buffer->sem);
+ if (buffer->needs_read_fill) {
+ if ((retval = fill_read_buffer(file->f_dentry,buffer)))
+ goto out;
+ }
+ pr_debug("%s: count = %d, ppos = %lld, buf = %s\n",
+ __FUNCTION__,count,*ppos,buffer->page);
+ retval = flush_read_buffer(buffer,buf,count,ppos);
+out:
+ up(&buffer->sem);
+ return retval;
+}
+
+
+/**
+ * fill_write_buffer - copy buffer from userspace.
+ * @buffer: data buffer for file.
+ * @userbuf: data from user.
+ * @count: number of bytes in @userbuf.
+ *
+ * Allocate @buffer->page if it hasn't been already, then
+ * copy the user-supplied buffer into it.
+ */
+
+static int
+fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count)
+{
+ int error;
+
+ if (!buffer->page)
+ buffer->page = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!buffer->page)
+ return -ENOMEM;
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+ error = copy_from_user(buffer->page,buf,count);
+ buffer->needs_read_fill = 1;
+ return error ? -EFAULT : count;
+}
+
+
+/**
+ * flush_write_buffer - push buffer to config_item.
+ * @file: file pointer.
+ * @buffer: data buffer for file.
+ *
+ * Get the correct pointers for the config_item and the attribute we're
+ * dealing with, then call the store() method for the attribute,
+ * passing the buffer that we acquired in fill_write_buffer().
+ */
+
+static int
+flush_write_buffer(struct dentry * dentry, struct configfs_buffer * buffer, size_t count)
+{
+ struct configfs_attribute * attr = to_attr(dentry);
+ struct config_item * item = to_item(dentry->d_parent);
+ struct configfs_item_operations * ops = buffer->ops;
+
+ return ops->store_attribute(item,attr,buffer->page,count);
+}
+
+
+/**
+ * configfs_write_file - write an attribute.
+ * @file: file pointer
+ * @buf: data to write
+ * @count: number of bytes
+ * @ppos: starting offset
+ *
+ * Similar to configfs_read_file(), though working in the opposite direction.
+ * We allocate and fill the data from the user in fill_write_buffer(),
+ * then push it to the config_item in flush_write_buffer().
+ * There is no easy way for us to know if userspace is only doing a partial
+ * write, so we don't support them. We expect the entire buffer to come
+ * on the first write.
+ * Hint: if you're writing a value, first read the file, modify only the
+ * the value you're changing, then write entire buffer back.
+ */
+
+static ssize_t
+configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct configfs_buffer * buffer = file->private_data;
+
+ down(&buffer->sem);
+ count = fill_write_buffer(buffer,buf,count);
+ if (count > 0)
+ count = flush_write_buffer(file->f_dentry,buffer,count);
+ if (count > 0)
+ *ppos += count;
+ up(&buffer->sem);
+ return count;
+}
+
+static int check_perm(struct inode * inode, struct file * file)
+{
+ struct config_item *item = configfs_get_config_item(file->f_dentry->d_parent);
+ struct configfs_attribute * attr = to_attr(file->f_dentry);
+ struct configfs_buffer * buffer;
+ struct configfs_item_operations * ops = NULL;
+ int error = 0;
+
+ if (!item || !attr)
+ goto Einval;
+
+ /* Grab the module reference for this attribute if we have one */
+ if (!try_module_get(attr->ca_owner)) {
+ error = -ENODEV;
+ goto Done;
+ }
+
+ if (item->ci_type)
+ ops = item->ci_type->ct_item_ops;
+ else
+ goto Eaccess;
+
+ /* File needs write support.
+ * The inode's perms must say it's ok,
+ * and we must have a store method.
+ */
+ if (file->f_mode & FMODE_WRITE) {
+
+ if (!(inode->i_mode & S_IWUGO) || !ops->store_attribute)
+ goto Eaccess;
+
+ }
+
+ /* File needs read support.
+ * The inode's perms must say it's ok, and we there
+ * must be a show method for it.
+ */
+ if (file->f_mode & FMODE_READ) {
+ if (!(inode->i_mode & S_IRUGO) || !ops->show_attribute)
+ goto Eaccess;
+ }
+
+ /* No error? Great, allocate a buffer for the file, and store it
+ * it in file->private_data for easy access.
+ */
+ buffer = kmalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
+ if (buffer) {
+ memset(buffer,0,sizeof(struct configfs_buffer));
+ init_MUTEX(&buffer->sem);
+ buffer->needs_read_fill = 1;
+ buffer->ops = ops;
+ file->private_data = buffer;
+ } else
+ error = -ENOMEM;
+ goto Done;
+
+ Einval:
+ error = -EINVAL;
+ goto Done;
+ Eaccess:
+ error = -EACCES;
+ module_put(attr->ca_owner);
+ Done:
+ if (error && item)
+ config_item_put(item);
+ return error;
+}
+
+static int configfs_open_file(struct inode * inode, struct file * filp)
+{
+ return check_perm(inode,filp);
+}
+
+static int configfs_release(struct inode * inode, struct file * filp)
+{
+ struct config_item * item = to_item(filp->f_dentry->d_parent);
+ struct configfs_attribute * attr = to_attr(filp->f_dentry);
+ struct module * owner = attr->ca_owner;
+ struct configfs_buffer * buffer = filp->private_data;
+
+ if (item)
+ config_item_put(item);
+ /* After this point, attr should not be accessed. */
+ module_put(owner);
+
+ if (buffer) {
+ if (buffer->page)
+ free_page((unsigned long)buffer->page);
+ kfree(buffer);
+ }
+ return 0;
+}
+
+struct file_operations configfs_file_operations = {
+ .read = configfs_read_file,
+ .write = configfs_write_file,
+ .llseek = generic_file_llseek,
+ .open = configfs_open_file,
+ .release = configfs_release,
+};
+
+
+int configfs_add_file(struct dentry * dir, const struct configfs_attribute * attr, int type)
+{
+ struct configfs_dirent * parent_sd = dir->d_fsdata;
+ umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
+ int error = 0;
+
+ mutex_lock(&dir->d_inode->i_mutex);
+ error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
+ mutex_unlock(&dir->d_inode->i_mutex);
+
+ return error;
+}
+
+
+/**
+ * configfs_create_file - create an attribute file for an item.
+ * @item: item we're creating for.
+ * @attr: atrribute descriptor.
+ */
+
+int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
+{
+ BUG_ON(!item || !item->ci_dentry || !attr);
+
+ return configfs_add_file(item->ci_dentry, attr,
+ CONFIGFS_ITEM_ATTR);
+}
+
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
new file mode 100644
index 000000000000..6577c588de9d
--- /dev/null
+++ b/fs/configfs/inode.c
@@ -0,0 +1,162 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * inode.c - basic inode and dentry operations.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * Please see Documentation/filesystems/configfs.txt for more information.
+ */
+
+#undef DEBUG
+
+#include <linux/pagemap.h>
+#include <linux/namei.h>
+#include <linux/backing-dev.h>
+
+#include <linux/configfs.h>
+#include "configfs_internal.h"
+
+extern struct super_block * configfs_sb;
+
+static struct address_space_operations configfs_aops = {
+ .readpage = simple_readpage,
+ .prepare_write = simple_prepare_write,
+ .commit_write = simple_commit_write
+};
+
+static struct backing_dev_info configfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+struct inode * configfs_new_inode(mode_t mode)
+{
+ struct inode * inode = new_inode(configfs_sb);
+ if (inode) {
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_mapping->a_ops = &configfs_aops;
+ inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
+ }
+ return inode;
+}
+
+int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
+{
+ int error = 0;
+ struct inode * inode = NULL;
+ if (dentry) {
+ if (!dentry->d_inode) {
+ if ((inode = configfs_new_inode(mode))) {
+ if (dentry->d_parent && dentry->d_parent->d_inode) {
+ struct inode *p_inode = dentry->d_parent->d_inode;
+ p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
+ }
+ goto Proceed;
+ }
+ else
+ error = -ENOMEM;
+ } else
+ error = -EEXIST;
+ } else
+ error = -ENOENT;
+ goto Done;
+
+ Proceed:
+ if (init)
+ error = init(inode);
+ if (!error) {
+ d_instantiate(dentry, inode);
+ if (S_ISDIR(mode) || S_ISLNK(mode))
+ dget(dentry); /* pin link and directory dentries in core */
+ } else
+ iput(inode);
+ Done:
+ return error;
+}
+
+/*
+ * Get the name for corresponding element represented by the given configfs_dirent
+ */
+const unsigned char * configfs_get_name(struct configfs_dirent *sd)
+{
+ struct attribute * attr;
+
+ if (!sd || !sd->s_element)
+ BUG();
+
+ /* These always have a dentry, so use that */
+ if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
+ return sd->s_dentry->d_name.name;
+
+ if (sd->s_type & CONFIGFS_ITEM_ATTR) {
+ attr = sd->s_element;
+ return attr->name;
+ }
+ return NULL;
+}
+
+
+/*
+ * Unhashes the dentry corresponding to given configfs_dirent
+ * Called with parent inode's i_mutex held.
+ */
+void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent)
+{
+ struct dentry * dentry = sd->s_dentry;
+
+ if (dentry) {
+ spin_lock(&dcache_lock);
+ if (!(d_unhashed(dentry) && dentry->d_inode)) {
+ dget_locked(dentry);
+ __d_drop(dentry);
+ spin_unlock(&dcache_lock);
+ simple_unlink(parent->d_inode, dentry);
+ } else
+ spin_unlock(&dcache_lock);
+ }
+}
+
+void configfs_hash_and_remove(struct dentry * dir, const char * name)
+{
+ struct configfs_dirent * sd;
+ struct configfs_dirent * parent_sd = dir->d_fsdata;
+
+ mutex_lock(&dir->d_inode->i_mutex);
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (!sd->s_element)
+ continue;
+ if (!strcmp(configfs_get_name(sd), name)) {
+ list_del_init(&sd->s_sibling);
+ configfs_drop_dentry(sd, dir);
+ configfs_put(sd);
+ break;
+ }
+ }
+ mutex_unlock(&dir->d_inode->i_mutex);
+}
+
+
diff --git a/fs/configfs/item.c b/fs/configfs/item.c
new file mode 100644
index 000000000000..e07485ac50ad
--- /dev/null
+++ b/fs/configfs/item.c
@@ -0,0 +1,227 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * item.c - library routines for handling generic config items
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on kobject:
+ * kobject is Copyright (c) 2002-2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * Please see the file Documentation/filesystems/configfs.txt for
+ * critical information about using the config_item interface.
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+
+#include <linux/configfs.h>
+
+
+static inline struct config_item * to_item(struct list_head * entry)
+{
+ return container_of(entry,struct config_item,ci_entry);
+}
+
+/* Evil kernel */
+static void config_item_release(struct kref *kref);
+
+/**
+ * config_item_init - initialize item.
+ * @item: item in question.
+ */
+void config_item_init(struct config_item * item)
+{
+ kref_init(&item->ci_kref);
+ INIT_LIST_HEAD(&item->ci_entry);
+}
+
+/**
+ * config_item_set_name - Set the name of an item
+ * @item: item.
+ * @name: name.
+ *
+ * If strlen(name) >= CONFIGFS_ITEM_NAME_LEN, then use a
+ * dynamically allocated string that @item->ci_name points to.
+ * Otherwise, use the static @item->ci_namebuf array.
+ */
+
+int config_item_set_name(struct config_item * item, const char * fmt, ...)
+{
+ int error = 0;
+ int limit = CONFIGFS_ITEM_NAME_LEN;
+ int need;
+ va_list args;
+ char * name;
+
+ /*
+ * First, try the static array
+ */
+ va_start(args,fmt);
+ need = vsnprintf(item->ci_namebuf,limit,fmt,args);
+ va_end(args);
+ if (need < limit)
+ name = item->ci_namebuf;
+ else {
+ /*
+ * Need more space? Allocate it and try again
+ */
+ limit = need + 1;
+ name = kmalloc(limit,GFP_KERNEL);
+ if (!name) {
+ error = -ENOMEM;
+ goto Done;
+ }
+ va_start(args,fmt);
+ need = vsnprintf(name,limit,fmt,args);
+ va_end(args);
+
+ /* Still? Give up. */
+ if (need >= limit) {
+ kfree(name);
+ error = -EFAULT;
+ goto Done;
+ }
+ }
+
+ /* Free the old name, if necessary. */
+ if (item->ci_name && item->ci_name != item->ci_namebuf)
+ kfree(item->ci_name);
+
+ /* Now, set the new name */
+ item->ci_name = name;
+ Done:
+ return error;
+}
+
+EXPORT_SYMBOL(config_item_set_name);
+
+void config_item_init_type_name(struct config_item *item,
+ const char *name,
+ struct config_item_type *type)
+{
+ config_item_set_name(item, name);
+ item->ci_type = type;
+ config_item_init(item);
+}
+EXPORT_SYMBOL(config_item_init_type_name);
+
+void config_group_init_type_name(struct config_group *group, const char *name,
+ struct config_item_type *type)
+{
+ config_item_set_name(&group->cg_item, name);
+ group->cg_item.ci_type = type;
+ config_group_init(group);
+}
+EXPORT_SYMBOL(config_group_init_type_name);
+
+struct config_item * config_item_get(struct config_item * item)
+{
+ if (item)
+ kref_get(&item->ci_kref);
+ return item;
+}
+
+/**
+ * config_item_cleanup - free config_item resources.
+ * @item: item.
+ */
+
+void config_item_cleanup(struct config_item * item)
+{
+ struct config_item_type * t = item->ci_type;
+ struct config_group * s = item->ci_group;
+ struct config_item * parent = item->ci_parent;
+
+ pr_debug("config_item %s: cleaning up\n",config_item_name(item));
+ if (item->ci_name != item->ci_namebuf)
+ kfree(item->ci_name);
+ item->ci_name = NULL;
+ if (t && t->ct_item_ops && t->ct_item_ops->release)
+ t->ct_item_ops->release(item);
+ if (s)
+ config_group_put(s);
+ if (parent)
+ config_item_put(parent);
+}
+
+static void config_item_release(struct kref *kref)
+{
+ config_item_cleanup(container_of(kref, struct config_item, ci_kref));
+}
+
+/**
+ * config_item_put - decrement refcount for item.
+ * @item: item.
+ *
+ * Decrement the refcount, and if 0, call config_item_cleanup().
+ */
+void config_item_put(struct config_item * item)
+{
+ if (item)
+ kref_put(&item->ci_kref, config_item_release);
+}
+
+
+/**
+ * config_group_init - initialize a group for use
+ * @k: group
+ */
+
+void config_group_init(struct config_group *group)
+{
+ config_item_init(&group->cg_item);
+ INIT_LIST_HEAD(&group->cg_children);
+}
+
+
+/**
+ * config_group_find_obj - search for item in group.
+ * @group: group we're looking in.
+ * @name: item's name.
+ *
+ * Lock group via @group->cg_subsys, and iterate over @group->cg_list,
+ * looking for a matching config_item. If matching item is found
+ * take a reference and return the item.
+ */
+
+struct config_item * config_group_find_obj(struct config_group * group, const char * name)
+{
+ struct list_head * entry;
+ struct config_item * ret = NULL;
+
+ /* XXX LOCKING! */
+ list_for_each(entry,&group->cg_children) {
+ struct config_item * item = to_item(entry);
+ if (config_item_name(item) &&
+ !strcmp(config_item_name(item), name)) {
+ ret = config_item_get(item);
+ break;
+ }
+ }
+ return ret;
+}
+
+
+EXPORT_SYMBOL(config_item_init);
+EXPORT_SYMBOL(config_group_init);
+EXPORT_SYMBOL(config_item_get);
+EXPORT_SYMBOL(config_item_put);
+
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
new file mode 100644
index 000000000000..1a2f6f6a4d91
--- /dev/null
+++ b/fs/configfs/mount.c
@@ -0,0 +1,159 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mount.c - operations for initializing and mounting configfs.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+
+#include <linux/configfs.h>
+#include "configfs_internal.h"
+
+/* Random magic number */
+#define CONFIGFS_MAGIC 0x62656570
+
+struct vfsmount * configfs_mount = NULL;
+struct super_block * configfs_sb = NULL;
+static int configfs_mnt_count = 0;
+
+static struct super_operations configfs_ops = {
+ .statfs = simple_statfs,
+ .drop_inode = generic_delete_inode,
+};
+
+static struct config_group configfs_root_group = {
+ .cg_item = {
+ .ci_namebuf = "root",
+ .ci_name = configfs_root_group.cg_item.ci_namebuf,
+ },
+};
+
+int configfs_is_root(struct config_item *item)
+{
+ return item == &configfs_root_group.cg_item;
+}
+
+static struct configfs_dirent configfs_root = {
+ .s_sibling = LIST_HEAD_INIT(configfs_root.s_sibling),
+ .s_children = LIST_HEAD_INIT(configfs_root.s_children),
+ .s_element = &configfs_root_group.cg_item,
+ .s_type = CONFIGFS_ROOT,
+};
+
+static int configfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ struct inode *inode;
+ struct dentry *root;
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = CONFIGFS_MAGIC;
+ sb->s_op = &configfs_ops;
+ configfs_sb = sb;
+
+ inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+ if (inode) {
+ inode->i_op = &configfs_dir_inode_operations;
+ inode->i_fop = &configfs_dir_operations;
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inode->i_nlink++;
+ } else {
+ pr_debug("configfs: could not get root inode\n");
+ return -ENOMEM;
+ }
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
+ iput(inode);
+ return -ENOMEM;
+ }
+ config_group_init(&configfs_root_group);
+ configfs_root_group.cg_item.ci_dentry = root;
+ root->d_fsdata = &configfs_root;
+ sb->s_root = root;
+ return 0;
+}
+
+static struct super_block *configfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return get_sb_single(fs_type, flags, data, configfs_fill_super);
+}
+
+static struct file_system_type configfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "configfs",
+ .get_sb = configfs_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+int configfs_pin_fs(void)
+{
+ return simple_pin_fs("configfs", &configfs_mount,
+ &configfs_mnt_count);
+}
+
+void configfs_release_fs(void)
+{
+ simple_release_fs(&configfs_mount, &configfs_mnt_count);
+}
+
+
+static decl_subsys(config, NULL, NULL);
+
+static int __init configfs_init(void)
+{
+ int err;
+
+ kset_set_kset_s(&config_subsys, kernel_subsys);
+ err = subsystem_register(&config_subsys);
+ if (err)
+ return err;
+
+ err = register_filesystem(&configfs_fs_type);
+ if (err) {
+ printk(KERN_ERR "configfs: Unable to register filesystem!\n");
+ subsystem_unregister(&config_subsys);
+ }
+
+ return err;
+}
+
+static void __exit configfs_exit(void)
+{
+ unregister_filesystem(&configfs_fs_type);
+ subsystem_unregister(&config_subsys);
+}
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.1");
+MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
+
+module_init(configfs_init);
+module_exit(configfs_exit);
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
new file mode 100644
index 000000000000..50f5840521a9
--- /dev/null
+++ b/fs/configfs/symlink.c
@@ -0,0 +1,281 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * symlink.c - operations for configfs symlinks.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/namei.h>
+
+#include <linux/configfs.h>
+#include "configfs_internal.h"
+
+static int item_depth(struct config_item * item)
+{
+ struct config_item * p = item;
+ int depth = 0;
+ do { depth++; } while ((p = p->ci_parent) && !configfs_is_root(p));
+ return depth;
+}
+
+static int item_path_length(struct config_item * item)
+{
+ struct config_item * p = item;
+ int length = 1;
+ do {
+ length += strlen(config_item_name(p)) + 1;
+ p = p->ci_parent;
+ } while (p && !configfs_is_root(p));
+ return length;
+}
+
+static void fill_item_path(struct config_item * item, char * buffer, int length)
+{
+ struct config_item * p;
+
+ --length;
+ for (p = item; p && !configfs_is_root(p); p = p->ci_parent) {
+ int cur = strlen(config_item_name(p));
+
+ /* back up enough to print this bus id with '/' */
+ length -= cur;
+ strncpy(buffer + length,config_item_name(p),cur);
+ *(buffer + --length) = '/';
+ }
+}
+
+static int create_link(struct config_item *parent_item,
+ struct config_item *item,
+ struct dentry *dentry)
+{
+ struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata;
+ struct configfs_symlink *sl;
+ int ret;
+
+ ret = -ENOMEM;
+ sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
+ if (sl) {
+ sl->sl_target = config_item_get(item);
+ /* FIXME: needs a lock, I'd bet */
+ list_add(&sl->sl_list, &target_sd->s_links);
+ ret = configfs_create_link(sl, parent_item->ci_dentry,
+ dentry);
+ if (ret) {
+ list_del_init(&sl->sl_list);
+ config_item_put(item);
+ kfree(sl);
+ }
+ }
+
+ return ret;
+}
+
+
+static int get_target(const char *symname, struct nameidata *nd,
+ struct config_item **target)
+{
+ int ret;
+
+ ret = path_lookup(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, nd);
+ if (!ret) {
+ if (nd->dentry->d_sb == configfs_sb) {
+ *target = configfs_get_config_item(nd->dentry);
+ if (!*target) {
+ ret = -ENOENT;
+ path_release(nd);
+ }
+ } else
+ ret = -EPERM;
+ }
+
+ return ret;
+}
+
+
+int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+ int ret;
+ struct nameidata nd;
+ struct config_item *parent_item;
+ struct config_item *target_item;
+ struct config_item_type *type;
+
+ ret = -EPERM; /* What lack-of-symlink returns */
+ if (dentry->d_parent == configfs_sb->s_root)
+ goto out;
+
+ parent_item = configfs_get_config_item(dentry->d_parent);
+ type = parent_item->ci_type;
+
+ if (!type || !type->ct_item_ops ||
+ !type->ct_item_ops->allow_link)
+ goto out_put;
+
+ ret = get_target(symname, &nd, &target_item);
+ if (ret)
+ goto out_put;
+
+ ret = type->ct_item_ops->allow_link(parent_item, target_item);
+ if (!ret)
+ ret = create_link(parent_item, target_item, dentry);
+
+ config_item_put(target_item);
+ path_release(&nd);
+
+out_put:
+ config_item_put(parent_item);
+
+out:
+ return ret;
+}
+
+int configfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ struct configfs_dirent *sd = dentry->d_fsdata;
+ struct configfs_symlink *sl;
+ struct config_item *parent_item;
+ struct config_item_type *type;
+ int ret;
+
+ ret = -EPERM; /* What lack-of-symlink returns */
+ if (!(sd->s_type & CONFIGFS_ITEM_LINK))
+ goto out;
+
+ if (dentry->d_parent == configfs_sb->s_root)
+ BUG();
+
+ sl = sd->s_element;
+
+ parent_item = configfs_get_config_item(dentry->d_parent);
+ type = parent_item->ci_type;
+
+ list_del_init(&sd->s_sibling);
+ configfs_drop_dentry(sd, dentry->d_parent);
+ dput(dentry);
+ configfs_put(sd);
+
+ /*
+ * drop_link() must be called before
+ * list_del_init(&sl->sl_list), so that the order of
+ * drop_link(this, target) and drop_item(target) is preserved.
+ */
+ if (type && type->ct_item_ops &&
+ type->ct_item_ops->drop_link)
+ type->ct_item_ops->drop_link(parent_item,
+ sl->sl_target);
+
+ /* FIXME: Needs lock */
+ list_del_init(&sl->sl_list);
+
+ /* Put reference from create_link() */
+ config_item_put(sl->sl_target);
+ kfree(sl);
+
+ config_item_put(parent_item);
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int configfs_get_target_path(struct config_item * item, struct config_item * target,
+ char *path)
+{
+ char * s;
+ int depth, size;
+
+ depth = item_depth(item);
+ size = item_path_length(target) + depth * 3 - 1;
+ if (size > PATH_MAX)
+ return -ENAMETOOLONG;
+
+ pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size);
+
+ for (s = path; depth--; s += 3)
+ strcpy(s,"../");
+
+ fill_item_path(target, path, size);
+ pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
+
+ return 0;
+}
+
+static int configfs_getlink(struct dentry *dentry, char * path)
+{
+ struct config_item *item, *target_item;
+ int error = 0;
+
+ item = configfs_get_config_item(dentry->d_parent);
+ if (!item)
+ return -EINVAL;
+
+ target_item = configfs_get_config_item(dentry);
+ if (!target_item) {
+ config_item_put(item);
+ return -EINVAL;
+ }
+
+ down_read(&configfs_rename_sem);
+ error = configfs_get_target_path(item, target_item, path);
+ up_read(&configfs_rename_sem);
+
+ config_item_put(item);
+ config_item_put(target_item);
+ return error;
+
+}
+
+static void *configfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ int error = -ENOMEM;
+ unsigned long page = get_zeroed_page(GFP_KERNEL);
+
+ if (page) {
+ error = configfs_getlink(dentry, (char *)page);
+ if (!error) {
+ nd_set_link(nd, (char *)page);
+ return (void *)page;
+ }
+ }
+
+ nd_set_link(nd, ERR_PTR(error));
+ return NULL;
+}
+
+static void configfs_put_link(struct dentry *dentry, struct nameidata *nd,
+ void *cookie)
+{
+ if (cookie) {
+ unsigned long page = (unsigned long)cookie;
+ free_page(page);
+ }
+}
+
+struct inode_operations configfs_symlink_inode_operations = {
+ .follow_link = configfs_follow_link,
+ .readlink = generic_readlink,
+ .put_link = configfs_put_link,
+};
+
diff --git a/fs/dcache.c b/fs/dcache.c
index 17e439138681..86bdb93789c6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -71,7 +71,7 @@ struct dentry_stat_t dentry_stat = {
static void d_callback(struct rcu_head *head)
{
- struct dentry * dentry = container_of(head, struct dentry, d_rcu);
+ struct dentry * dentry = container_of(head, struct dentry, d_u.d_rcu);
if (dname_external(dentry))
kfree(dentry->d_name.name);
@@ -86,7 +86,7 @@ static void d_free(struct dentry *dentry)
{
if (dentry->d_op && dentry->d_op->d_release)
dentry->d_op->d_release(dentry);
- call_rcu(&dentry->d_rcu, d_callback);
+ call_rcu(&dentry->d_u.d_rcu, d_callback);
}
/*
@@ -94,7 +94,7 @@ static void d_free(struct dentry *dentry)
* d_iput() operation if defined.
* Called with dcache_lock and per dentry lock held, drops both.
*/
-static inline void dentry_iput(struct dentry * dentry)
+static void dentry_iput(struct dentry * dentry)
{
struct inode *inode = dentry->d_inode;
if (inode) {
@@ -193,7 +193,7 @@ kill_it: {
list_del(&dentry->d_lru);
dentry_stat.nr_unused--;
}
- list_del(&dentry->d_child);
+ list_del(&dentry->d_u.d_child);
dentry_stat.nr_dentry--; /* For d_free, below */
/*drops the locks, at that point nobody can reach this dentry */
dentry_iput(dentry);
@@ -367,7 +367,7 @@ static inline void prune_one_dentry(struct dentry * dentry)
struct dentry * parent;
__d_drop(dentry);
- list_del(&dentry->d_child);
+ list_del(&dentry->d_u.d_child);
dentry_stat.nr_dentry--; /* For d_free, below */
dentry_iput(dentry);
parent = dentry->d_parent;
@@ -518,7 +518,7 @@ repeat:
resume:
while (next != &this_parent->d_subdirs) {
struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
+ struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
next = tmp->next;
/* Have we found a mount point ? */
if (d_mountpoint(dentry))
@@ -532,7 +532,7 @@ resume:
* All done at this level ... ascend and resume the search.
*/
if (this_parent != parent) {
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
goto resume;
}
@@ -569,7 +569,7 @@ repeat:
resume:
while (next != &this_parent->d_subdirs) {
struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
+ struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
next = tmp->next;
if (!list_empty(&dentry->d_lru)) {
@@ -610,7 +610,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name, found);
* All done at this level ... ascend and resume the search.
*/
if (this_parent != parent) {
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
this_parent = this_parent->d_parent;
#ifdef DCACHE_DEBUG
printk(KERN_DEBUG "select_parent: ascending to %s/%s, found=%d\n",
@@ -753,12 +753,12 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_parent = dget(parent);
dentry->d_sb = parent->d_sb;
} else {
- INIT_LIST_HEAD(&dentry->d_child);
+ INIT_LIST_HEAD(&dentry->d_u.d_child);
}
spin_lock(&dcache_lock);
if (parent)
- list_add(&dentry->d_child, &parent->d_subdirs);
+ list_add(&dentry->d_u.d_child, &parent->d_subdirs);
dentry_stat.nr_dentry++;
spin_unlock(&dcache_lock);
@@ -808,10 +808,14 @@ void d_instantiate(struct dentry *entry, struct inode * inode)
*
* Fill in inode information in the entry. On success, it returns NULL.
* If an unhashed alias of "entry" already exists, then we return the
- * aliased dentry instead.
+ * aliased dentry instead and drop one reference to inode.
*
* Note that in order to avoid conflicts with rename() etc, the caller
* had better be holding the parent directory semaphore.
+ *
+ * This also assumes that the inode count has been incremented
+ * (or otherwise set) by the caller to indicate that it is now
+ * in use by the dcache.
*/
struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
{
@@ -838,6 +842,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
dget_locked(alias);
spin_unlock(&dcache_lock);
BUG_ON(!d_unhashed(alias));
+ iput(inode);
return alias;
}
list_add(&entry->d_alias, &inode->i_dentry);
@@ -1310,8 +1315,8 @@ already_unhashed:
/* Unhash the target: dput() will then get rid of it */
__d_drop(target);
- list_del(&dentry->d_child);
- list_del(&target->d_child);
+ list_del(&dentry->d_u.d_child);
+ list_del(&target->d_u.d_child);
/* Switch the names.. */
switch_names(dentry, target);
@@ -1322,15 +1327,15 @@ already_unhashed:
if (IS_ROOT(dentry)) {
dentry->d_parent = target->d_parent;
target->d_parent = target;
- INIT_LIST_HEAD(&target->d_child);
+ INIT_LIST_HEAD(&target->d_u.d_child);
} else {
do_switch(dentry->d_parent, target->d_parent);
/* And add them back to the (new) parent lists */
- list_add(&target->d_child, &target->d_parent->d_subdirs);
+ list_add(&target->d_u.d_child, &target->d_parent->d_subdirs);
}
- list_add(&dentry->d_child, &dentry->d_parent->d_subdirs);
+ list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
spin_unlock(&target->d_lock);
spin_unlock(&dentry->d_lock);
write_sequnlock(&rename_lock);
@@ -1568,7 +1573,7 @@ repeat:
resume:
while (next != &this_parent->d_subdirs) {
struct list_head *tmp = next;
- struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
+ struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child);
next = tmp->next;
if (d_unhashed(dentry)||!dentry->d_inode)
continue;
@@ -1579,7 +1584,7 @@ resume:
atomic_dec(&dentry->d_count);
}
if (this_parent != root) {
- next = this_parent->d_child.next;
+ next = this_parent->d_u.d_child.next;
atomic_dec(&this_parent->d_count);
this_parent = this_parent->d_parent;
goto resume;
diff --git a/fs/dcookies.c b/fs/dcookies.c
index 02aa0ddc582a..f8274a8f83bd 100644
--- a/fs/dcookies.c
+++ b/fs/dcookies.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/mount.h>
+#include <linux/capability.h>
#include <linux/dcache.h>
#include <linux/mm.h>
#include <linux/errno.h>
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index a86ac4aeaedb..d4f1a2cddd47 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -146,7 +146,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
}
*dentry = NULL;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
@@ -155,7 +155,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
error = debugfs_create(parent->d_inode, *dentry, mode);
} else
error = PTR_ERR(dentry);
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
@@ -273,7 +273,7 @@ void debugfs_remove(struct dentry *dentry)
if (!parent || !parent->d_inode)
return;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
if (debugfs_positive(dentry)) {
if (dentry->d_inode) {
if (S_ISDIR(dentry->d_inode->i_mode))
@@ -283,7 +283,7 @@ void debugfs_remove(struct dentry *dentry)
dput(dentry);
}
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
}
EXPORT_SYMBOL_GPL(debugfs_remove);
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 1274422a5384..b621521e09d4 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2162,27 +2162,27 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd)
*
* make sure that
* d_instantiate always runs under lock
- * we release i_sem lock before going to sleep
+ * we release i_mutex lock before going to sleep
*
* unfortunately sometimes d_revalidate is called with
- * and sometimes without i_sem lock held. The following checks
+ * and sometimes without i_mutex lock held. The following checks
* attempt to deduce when we need to add (and drop resp.) lock
* here. This relies on current (2.6.2) calling coventions:
*
- * lookup_hash is always run under i_sem and is passing NULL
+ * lookup_hash is always run under i_mutex and is passing NULL
* as nd
*
- * open(...,O_CREATE,...) calls _lookup_hash under i_sem
+ * open(...,O_CREATE,...) calls _lookup_hash under i_mutex
* and sets flags to LOOKUP_OPEN|LOOKUP_CREATE
*
* all other invocations of ->d_revalidate seem to happen
- * outside of i_sem
+ * outside of i_mutex
*/
need_lock = nd &&
(!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT));
if (need_lock)
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
if (is_devfsd_or_child(fs_info)) {
devfs_handle_t de = lookup_info->de;
@@ -2221,9 +2221,9 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd)
add_wait_queue(&lookup_info->wait_queue, &wait);
read_unlock(&parent->u.dir.lock);
/* at this point it is always (hopefully) locked */
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
schedule();
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
/*
* This does not need nor should remove wait from wait_queue.
* Wait queue head is never reused - nothing is ever added to it
@@ -2238,7 +2238,7 @@ static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd)
out:
if (need_lock)
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
return 1;
} /* End Function devfs_d_revalidate_wait */
@@ -2284,9 +2284,9 @@ static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry,
/* Unlock directory semaphore, which will release any waiters. They
will get the hashed dentry, and may be forced to wait for
revalidation */
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */
- down(&dir->i_sem); /* Grab it again because them's the rules */
+ mutex_lock(&dir->i_mutex); /* Grab it again because them's the rules */
de = lookup_info.de;
/* If someone else has been so kind as to make the inode, we go home
early */
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index f2be44d4491f..bfb8a230bac9 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -130,7 +130,7 @@ static struct dentry *get_node(int num)
{
char s[12];
struct dentry *root = devpts_root;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
return lookup_one_len(s, root, sprintf(s, "%d", num));
}
@@ -161,7 +161,7 @@ int devpts_pty_new(struct tty_struct *tty)
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
return 0;
}
@@ -178,7 +178,7 @@ struct tty_struct *devpts_get_tty(int number)
dput(dentry);
}
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
return tty;
}
@@ -196,7 +196,7 @@ void devpts_pty_kill(int number)
}
dput(dentry);
}
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
}
static int __init init_devpts_fs(void)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 3931e7f1e6bf..30dbbd1df511 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -56,7 +56,7 @@
* lock_type is DIO_LOCKING for regular files on direct-IO-naive filesystems.
* This determines whether we need to do the fancy locking which prevents
* direct-IO from being able to read uninitialised disk blocks. If its zero
- * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_sem is
+ * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_mutex is
* not held for the entire direct write (taken briefly, initially, during a
* direct read though, but its never held for the duration of a direct-IO).
*/
@@ -930,7 +930,7 @@ out:
}
/*
- * Releases both i_sem and i_alloc_sem
+ * Releases both i_mutex and i_alloc_sem
*/
static ssize_t
direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
@@ -1062,11 +1062,11 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
/*
* All block lookups have been performed. For READ requests
- * we can let i_sem go now that its achieved its purpose
+ * we can let i_mutex go now that its achieved its purpose
* of protecting us from looking up uninitialized blocks.
*/
if ((rw == READ) && (dio->lock_type == DIO_LOCKING))
- up(&dio->inode->i_sem);
+ mutex_unlock(&dio->inode->i_mutex);
/*
* OK, all BIOs are submitted, so we can decrement bio_count to truly
@@ -1145,18 +1145,18 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
* The locking rules are governed by the dio_lock_type parameter.
*
* DIO_NO_LOCKING (no locking, for raw block device access)
- * For writes, i_sem is not held on entry; it is never taken.
+ * For writes, i_mutex is not held on entry; it is never taken.
*
* DIO_LOCKING (simple locking for regular files)
- * For writes we are called under i_sem and return with i_sem held, even though
+ * For writes we are called under i_mutex and return with i_mutex held, even though
* it is internally dropped.
- * For reads, i_sem is not held on entry, but it is taken and dropped before
+ * For reads, i_mutex is not held on entry, but it is taken and dropped before
* returning.
*
* DIO_OWN_LOCKING (filesystem provides synchronisation and handling of
* uninitialised data, allowing parallel direct readers and writers)
- * For writes we are called without i_sem, return without it, never touch it.
- * For reads, i_sem is held on entry and will be released before returning.
+ * For writes we are called without i_mutex, return without it, never touch it.
+ * For reads, i_mutex is held on entry and will be released before returning.
*
* Additional i_alloc_sem locking requirements described inline below.
*/
@@ -1214,11 +1214,11 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
* For block device access DIO_NO_LOCKING is used,
* neither readers nor writers do any locking at all
* For regular files using DIO_LOCKING,
- * readers need to grab i_sem and i_alloc_sem
- * writers need to grab i_alloc_sem only (i_sem is already held)
+ * readers need to grab i_mutex and i_alloc_sem
+ * writers need to grab i_alloc_sem only (i_mutex is already held)
* For regular files using DIO_OWN_LOCKING,
* neither readers nor writers take any locks here
- * (i_sem is already held and release for writers here)
+ * (i_mutex is already held and release for writers here)
*/
dio->lock_type = dio_lock_type;
if (dio_lock_type != DIO_NO_LOCKING) {
@@ -1228,7 +1228,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
mapping = iocb->ki_filp->f_mapping;
if (dio_lock_type != DIO_OWN_LOCKING) {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
reader_with_isem = 1;
}
@@ -1240,7 +1240,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
}
if (dio_lock_type == DIO_OWN_LOCKING) {
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
reader_with_isem = 0;
}
}
@@ -1266,7 +1266,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
out:
if (reader_with_isem)
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (rw & WRITE)
current->flags &= ~PF_SYNCWRITE;
return retval;
diff --git a/fs/dquot.c b/fs/dquot.c
index 2a62b3dc20ec..1966c890b48d 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -77,6 +77,7 @@
#include <linux/kmod.h>
#include <linux/namei.h>
#include <linux/buffer_head.h>
+#include <linux/capability.h>
#include <linux/quotaops.h>
#include <asm/uaccess.h>
@@ -100,7 +101,7 @@
* operation is just reading pointers from inode (or not using them at all) the
* read lock is enough. If pointers are altered function must hold write lock
* (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_sem is also needed). If operation is holding
+ * for altering the flag i_mutex is also needed). If operation is holding
* reference to dquot in other way (e.g. quotactl ops) it must be guarded by
* dqonoff_sem.
* This locking assures that:
@@ -117,9 +118,9 @@
* spinlock to internal buffers before writing.
*
* Lock ordering (including related VFS locks) is the following:
- * i_sem > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem >
+ * i_mutex > dqonoff_sem > iprune_sem > journal_lock > dqptr_sem >
* > dquot->dq_lock > dqio_sem
- * i_sem on quota files is special (it's below dqio_sem)
+ * i_mutex on quota files is special (it's below dqio_sem)
*/
static DEFINE_SPINLOCK(dq_list_lock);
@@ -1369,11 +1370,11 @@ int vfs_quota_off(struct super_block *sb, int type)
/* If quota was reenabled in the meantime, we have
* nothing to do */
if (!sb_has_quota_enabled(sb, cnt)) {
- down(&toputinode[cnt]->i_sem);
+ mutex_lock(&toputinode[cnt]->i_mutex);
toputinode[cnt]->i_flags &= ~(S_IMMUTABLE |
S_NOATIME | S_NOQUOTA);
truncate_inode_pages(&toputinode[cnt]->i_data, 0);
- up(&toputinode[cnt]->i_sem);
+ mutex_unlock(&toputinode[cnt]->i_mutex);
mark_inode_dirty(toputinode[cnt]);
iput(toputinode[cnt]);
}
@@ -1417,7 +1418,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
write_inode_now(inode, 1);
/* And now flush the block cache so that kernel sees the changes */
invalidate_bdev(sb->s_bdev, 0);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
down(&dqopt->dqonoff_sem);
if (sb_has_quota_enabled(sb, type)) {
error = -EBUSY;
@@ -1449,7 +1450,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
goto out_file_init;
}
up(&dqopt->dqio_sem);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
set_enable_flags(dqopt, type);
add_dquot_ref(sb, type);
@@ -1470,7 +1471,7 @@ out_lock:
inode->i_flags |= oldflags;
up_write(&dqopt->dqptr_sem);
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out_fmt:
put_quota_format(fmt);
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
new file mode 100644
index 000000000000..4e4762389bdc
--- /dev/null
+++ b/fs/drop_caches.c
@@ -0,0 +1,68 @@
+/*
+ * Implement the manual drop-all-pagecache function
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/writeback.h>
+#include <linux/sysctl.h>
+#include <linux/gfp.h>
+
+/* A global variable is a bit ugly, but it keeps the code simple */
+int sysctl_drop_caches;
+
+static void drop_pagecache_sb(struct super_block *sb)
+{
+ struct inode *inode;
+
+ spin_lock(&inode_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ if (inode->i_state & (I_FREEING|I_WILL_FREE))
+ continue;
+ invalidate_inode_pages(inode->i_mapping);
+ }
+ spin_unlock(&inode_lock);
+}
+
+void drop_pagecache(void)
+{
+ struct super_block *sb;
+
+ spin_lock(&sb_lock);
+restart:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ if (sb->s_root)
+ drop_pagecache_sb(sb);
+ up_read(&sb->s_umount);
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
+ }
+ spin_unlock(&sb_lock);
+}
+
+void drop_slab(void)
+{
+ int nr_objects;
+
+ do {
+ nr_objects = shrink_slab(1000, GFP_KERNEL, 1000);
+ } while (nr_objects > 10);
+}
+
+int drop_caches_sysctl_handler(ctl_table *table, int write,
+ struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+{
+ proc_dointvec_minmax(table, write, file, buffer, length, ppos);
+ if (write) {
+ if (sysctl_drop_caches & 1)
+ drop_pagecache();
+ if (sysctl_drop_caches & 2)
+ drop_slab();
+ }
+ return 0;
+}
diff --git a/fs/efs/super.c b/fs/efs/super.c
index d8d5ea9a9997..afc4891feb36 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -222,12 +222,13 @@ static efs_block_t efs_validate_vh(struct volume_header *vh) {
sblock);
#endif
}
- return(sblock);
+ return sblock;
}
static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
- if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) return -1;
+ if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic)))
+ return -1;
sb->fs_magic = be32_to_cpu(super->fs_magic);
sb->total_blocks = be32_to_cpu(super->fs_size);
diff --git a/fs/exec.c b/fs/exec.c
index 22533cce0611..055378d2513e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -324,7 +324,7 @@ void install_arg_page(struct vm_area_struct *vma,
lru_cache_add_active(page);
set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
page, vma->vm_page_prot))));
- page_add_anon_rmap(page, vma, address);
+ page_add_new_anon_rmap(page, vma, address);
pte_unmap_unlock(pte, ptl);
/* no need for flush_tlb */
@@ -477,7 +477,7 @@ struct file *open_exec(const char *name)
int err;
struct file *file;
- err = path_lookup_open(name, LOOKUP_FOLLOW, &nd, FMODE_READ);
+ err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ);
file = ERR_PTR(err);
if (!err) {
@@ -575,7 +575,7 @@ static int exec_mmap(struct mm_struct *mm)
* disturbing other processes. (Other processes might share the signal
* table via the CLONE_SIGHAND option to clone().)
*/
-static inline int de_thread(struct task_struct *tsk)
+static int de_thread(struct task_struct *tsk)
{
struct signal_struct *sig = tsk->signal;
struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
@@ -632,10 +632,10 @@ static inline int de_thread(struct task_struct *tsk)
* synchronize with any firing (by calling del_timer_sync)
* before we can safely let the old group leader die.
*/
- sig->real_timer.data = (unsigned long)current;
+ sig->real_timer.data = current;
spin_unlock_irq(lock);
- if (del_timer_sync(&sig->real_timer))
- add_timer(&sig->real_timer);
+ if (hrtimer_cancel(&sig->real_timer))
+ hrtimer_restart(&sig->real_timer);
spin_lock_irq(lock);
}
while (atomic_read(&sig->count) > count) {
@@ -760,7 +760,7 @@ no_thread_group:
spin_lock(&oldsighand->siglock);
spin_lock(&newsighand->siglock);
- current->sighand = newsighand;
+ rcu_assign_pointer(current->sighand, newsighand);
recalc_sigpending();
spin_unlock(&newsighand->siglock);
@@ -768,7 +768,7 @@ no_thread_group:
write_unlock_irq(&tasklist_lock);
if (atomic_dec_and_test(&oldsighand->count))
- kmem_cache_free(sighand_cachep, oldsighand);
+ sighand_free(oldsighand);
}
BUG_ON(!thread_group_leader(current));
@@ -780,7 +780,7 @@ no_thread_group:
* so that a new one can be started
*/
-static inline void flush_old_files(struct files_struct * files)
+static void flush_old_files(struct files_struct * files)
{
long j = -1;
struct fdtable *fdt;
@@ -964,7 +964,7 @@ int prepare_binprm(struct linux_binprm *bprm)
EXPORT_SYMBOL(prepare_binprm);
-static inline int unsafe_exec(struct task_struct *p)
+static int unsafe_exec(struct task_struct *p)
{
int unsafe = 0;
if (p->ptrace & PT_PTRACED) {
@@ -1462,6 +1462,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
current->signal->flags = SIGNAL_GROUP_EXIT;
current->signal->group_exit_code = exit_code;
+ current->signal->group_stop_count = 0;
retval = 0;
}
spin_unlock_irq(&current->sighand->siglock);
@@ -1477,7 +1478,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
* Clear any false indication of pending signals that might
* be seen by the filesystem code called to write the core file.
*/
- current->signal->group_stop_count = 0;
clear_thread_flag(TIF_SIGPENDING);
if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
@@ -1505,7 +1505,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
goto close_fail;
if (!file->f_op->write)
goto close_fail;
- if (do_truncate(file->f_dentry, 0, file) != 0)
+ if (do_truncate(file->f_dentry, 0, 0, file) != 0)
goto close_fail;
retval = binfmt->core_dump(signr, regs, file);
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index c49d6254379a..b06b54f1bbbb 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -11,6 +11,33 @@ struct export_operations export_op_default;
#define dprintk(fmt, args...) do{}while(0)
+static struct dentry *
+find_acceptable_alias(struct dentry *result,
+ int (*acceptable)(void *context, struct dentry *dentry),
+ void *context)
+{
+ struct dentry *dentry, *toput = NULL;
+
+ spin_lock(&dcache_lock);
+ list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
+ dget_locked(dentry);
+ spin_unlock(&dcache_lock);
+ if (toput)
+ dput(toput);
+ if (dentry != result && acceptable(context, dentry)) {
+ dput(result);
+ return dentry;
+ }
+ spin_lock(&dcache_lock);
+ toput = dentry;
+ }
+ spin_unlock(&dcache_lock);
+
+ if (toput)
+ dput(toput);
+ return NULL;
+}
+
/**
* find_exported_dentry - helper routine to implement export_operations->decode_fh
* @sb: The &super_block identifying the filesystem
@@ -52,8 +79,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
struct dentry *target_dir;
int err;
struct export_operations *nops = sb->s_export_op;
- struct list_head *le, *head;
- struct dentry *toput = NULL;
+ struct dentry *alias;
int noprogress;
char nbuf[NAME_MAX+1];
@@ -79,27 +105,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
/* there is no other dentry, so fail */
goto err_result;
}
- /* try any other aliases */
- spin_lock(&dcache_lock);
- head = &result->d_inode->i_dentry;
- list_for_each(le, head) {
- struct dentry *dentry = list_entry(le, struct dentry, d_alias);
- dget_locked(dentry);
- spin_unlock(&dcache_lock);
- if (toput)
- dput(toput);
- toput = NULL;
- if (dentry != result &&
- acceptable(context, dentry)) {
- dput(result);
- return dentry;
- }
- spin_lock(&dcache_lock);
- toput = dentry;
- }
- spin_unlock(&dcache_lock);
- if (toput)
- dput(toput);
+
+ alias = find_acceptable_alias(result, acceptable, context);
+ if (alias)
+ return alias;
}
/* It's a directory, or we are required to confirm the file's
@@ -177,9 +186,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
struct dentry *ppd;
struct dentry *npd;
- down(&pd->d_inode->i_sem);
+ mutex_lock(&pd->d_inode->i_mutex);
ppd = CALL(nops,get_parent)(pd);
- up(&pd->d_inode->i_sem);
+ mutex_unlock(&pd->d_inode->i_mutex);
if (IS_ERR(ppd)) {
err = PTR_ERR(ppd);
@@ -201,9 +210,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
break;
}
dprintk("find_exported_dentry: found name: %s\n", nbuf);
- down(&ppd->d_inode->i_sem);
+ mutex_lock(&ppd->d_inode->i_mutex);
npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
- up(&ppd->d_inode->i_sem);
+ mutex_unlock(&ppd->d_inode->i_mutex);
if (IS_ERR(npd)) {
err = PTR_ERR(npd);
dprintk("find_exported_dentry: lookup failed: %d\n", err);
@@ -242,9 +251,9 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
struct dentry *nresult;
err = CALL(nops,get_name)(target_dir, nbuf, result);
if (!err) {
- down(&target_dir->d_inode->i_sem);
+ mutex_lock(&target_dir->d_inode->i_mutex);
nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
- up(&target_dir->d_inode->i_sem);
+ mutex_unlock(&target_dir->d_inode->i_mutex);
if (!IS_ERR(nresult)) {
if (nresult->d_inode) {
dput(result);
@@ -258,26 +267,10 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
/* now result is properly connected, it is our best bet */
if (acceptable(context, result))
return result;
- /* one last try of the aliases.. */
- spin_lock(&dcache_lock);
- toput = NULL;
- head = &result->d_inode->i_dentry;
- list_for_each(le, head) {
- struct dentry *dentry = list_entry(le, struct dentry, d_alias);
- dget_locked(dentry);
- spin_unlock(&dcache_lock);
- if (toput) dput(toput);
- if (dentry != result &&
- acceptable(context, dentry)) {
- dput(result);
- return dentry;
- }
- spin_lock(&dcache_lock);
- toput = dentry;
- }
- spin_unlock(&dcache_lock);
- if (toput)
- dput(toput);
+
+ alias = find_acceptable_alias(result, acceptable, context);
+ if (alias)
+ return alias;
/* drat - I just cannot find anything acceptable */
dput(result);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 6af2f4130290..35acc43b897f 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -4,6 +4,7 @@
* Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
@@ -149,7 +150,7 @@ ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl,
}
/*
- * inode->i_sem: don't care
+ * inode->i_mutex: don't care
*/
static struct posix_acl *
ext2_get_acl(struct inode *inode, int type)
@@ -211,7 +212,7 @@ ext2_get_acl(struct inode *inode, int type)
}
/*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
static int
ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
@@ -301,8 +302,8 @@ ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
/*
* Initialize the ACLs of a new inode. Called from ext2_new_inode.
*
- * dir->i_sem: down
- * inode->i_sem: up (access to inode is still exclusive)
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
*/
int
ext2_init_acl(struct inode *inode, struct inode *dir)
@@ -361,7 +362,7 @@ cleanup:
* for directories) are added. There are no more bits available in the
* file mode.
*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
ext2_acl_chmod(struct inode *inode)
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index bb6908066494..2c00953d4b0b 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -16,6 +16,7 @@
#include <linux/quotaops.h>
#include <linux/sched.h>
#include <linux/buffer_head.h>
+#include <linux/capability.h>
/*
* balloc.c contains the blocks allocation and deallocation routines
diff --git a/fs/ext2/bitmap.c b/fs/ext2/bitmap.c
index 20145b74623f..e9983a0dd396 100644
--- a/fs/ext2/bitmap.c
+++ b/fs/ext2/bitmap.c
@@ -7,8 +7,12 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
+#ifdef EXT2FS_DEBUG
+
#include <linux/buffer_head.h>
+#include "ext2.h"
+
static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
@@ -23,3 +27,6 @@ unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
nibblemap[(map->b_data[i] >> 4) & 0xf];
return (sum);
}
+
+#endif /* EXT2FS_DEBUG */
+
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 5b5f52876b42..7442bdd1267a 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -592,7 +592,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
goto fail;
}
kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr, 0, chunk_size);
+ memset(kaddr, 0, chunk_size);
de = (struct ext2_dir_entry_2 *)kaddr;
de->name_len = 1;
de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1));
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index e977f8566d14..00de0a7312a2 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -53,7 +53,7 @@ struct ext2_inode_info {
#ifdef CONFIG_EXT2_FS_XATTR
/*
* Extended attributes can be read independently of the main file
- * data. Taking i_sem even when reading would cause contention
+ * data. Taking i_mutex even when reading would cause contention
* between readers of EAs and writers of regular file data, so
* instead we synchronize on xattr_sem when reading or changing
* EAs.
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 709d8676b962..3ca9afdf713d 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -8,6 +8,7 @@
*/
#include "ext2.h"
+#include <linux/capability.h>
#include <linux/time.h>
#include <linux/sched.h>
#include <asm/current.h>
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index c5513953c825..ad1432a2a62e 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -83,10 +83,7 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
if (!inode)
return ERR_PTR(-EACCES);
}
- if (inode)
- return d_splice_alias(inode, dentry);
- d_add(dentry, inode);
- return NULL;
+ return d_splice_alias(inode, dentry);
}
struct dentry *ext2_get_parent(struct dentry *child)
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 522fa70dd8ea..8d6819846fc9 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1152,7 +1152,7 @@ static ssize_t ext2_quota_write(struct super_block *sb, int type,
struct buffer_head tmp_bh;
struct buffer_head *bh;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
while (towrite > 0) {
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
@@ -1189,7 +1189,7 @@ out:
inode->i_version++;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return len - towrite;
}
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index 0099462d4271..a2ca3107d475 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -325,7 +325,7 @@ cleanup:
/*
* Inode operation listxattr()
*
- * dentry->d_inode->i_sem: don't care
+ * dentry->d_inode->i_mutex: don't care
*/
ssize_t
ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -389,10 +389,6 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
name_index, name, value, (long)value_len);
- if (IS_RDONLY(inode))
- return -EROFS;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
if (value == NULL)
value_len = 0;
if (name == NULL)
diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
index 52b30ee6a25f..f28a6a499c96 100644
--- a/fs/ext2/xattr_trusted.c
+++ b/fs/ext2/xattr_trusted.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/smp_lock.h>
#include <linux/ext2_fs.h>
@@ -38,8 +39,6 @@ ext2_xattr_trusted_get(struct inode *inode, const char *name,
{
if (strcmp(name, "") == 0)
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
buffer, size);
}
@@ -50,8 +49,6 @@ ext2_xattr_trusted_set(struct inode *inode, const char *name,
{
if (strcmp(name, "") == 0)
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index 0c03ea131a94..f383e7c3a7b5 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -35,16 +35,10 @@ static int
ext2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
- int error;
-
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
- error = permission(inode, MAY_READ, NULL);
- if (error)
- return error;
-
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, buffer, size);
}
@@ -52,18 +46,10 @@ static int
ext2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- int error;
-
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
- if ( !S_ISREG(inode->i_mode) &&
- (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
- return -EPERM;
- error = permission(inode, MAY_WRITE, NULL);
- if (error)
- return error;
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
value, size, flags);
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 3ac38266fc9e..47a9da2dfb4f 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/ext3_jbd.h>
#include <linux/ext3_fs.h>
@@ -152,7 +153,7 @@ ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl,
/*
* Inode operation get_posix_acl().
*
- * inode->i_sem: don't care
+ * inode->i_mutex: don't care
*/
static struct posix_acl *
ext3_get_acl(struct inode *inode, int type)
@@ -216,7 +217,7 @@ ext3_get_acl(struct inode *inode, int type)
/*
* Set the access or default ACL of an inode.
*
- * inode->i_sem: down unless called from ext3_new_inode
+ * inode->i_mutex: down unless called from ext3_new_inode
*/
static int
ext3_set_acl(handle_t *handle, struct inode *inode, int type,
@@ -306,8 +307,8 @@ ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
/*
* Initialize the ACLs of a new inode. Called from ext3_new_inode.
*
- * dir->i_sem: down
- * inode->i_sem: up (access to inode is still exclusive)
+ * dir->i_mutex: down
+ * inode->i_mutex: up (access to inode is still exclusive)
*/
int
ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
@@ -368,7 +369,7 @@ cleanup:
* for directories) are added. There are no more bits available in the
* file mode.
*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
ext3_acl_chmod(struct inode *inode)
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index ae1148c24c53..6250fcdf14a1 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <linux/time.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/jbd.h>
#include <linux/ext3_fs.h>
@@ -20,8 +21,6 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
-#include "bitmap.h"
-
/*
* balloc.c contains the blocks allocation and deallocation routines
*/
diff --git a/fs/ext3/bitmap.c b/fs/ext3/bitmap.c
index 5b4ba3e246e6..cb16b4c5d5df 100644
--- a/fs/ext3/bitmap.c
+++ b/fs/ext3/bitmap.c
@@ -7,8 +7,11 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
+#ifdef EXT3FS_DEBUG
+
#include <linux/buffer_head.h>
-#include "bitmap.h"
+
+#include "ext3_fs.h"
static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
@@ -24,3 +27,6 @@ unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars)
nibblemap[(map->b_data[i] >> 4) & 0xf];
return (sum);
}
+
+#endif /* EXT3FS_DEBUG */
+
diff --git a/fs/ext3/bitmap.h b/fs/ext3/bitmap.h
deleted file mode 100644
index 6ee503a6bb4e..000000000000
--- a/fs/ext3/bitmap.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/* linux/fs/ext3/bitmap.c
- *
- * Copyright (C) 2005 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- *
-*/
-
-extern unsigned long ext3_count_free (struct buffer_head *, unsigned int );
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 9e4a24376210..dc826464f313 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -26,7 +26,6 @@
#include <asm/byteorder.h>
-#include "bitmap.h"
#include "xattr.h"
#include "acl.h"
@@ -651,7 +650,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
/* Error cases - e2fsck has already cleaned up for us */
if (ino > max_ino) {
ext3_warning(sb, __FUNCTION__,
- "bad orphan ino %lu! e2fsck was run?\n", ino);
+ "bad orphan ino %lu! e2fsck was run?", ino);
goto out;
}
@@ -660,7 +659,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
bitmap_bh = read_inode_bitmap(sb, block_group);
if (!bitmap_bh) {
ext3_warning(sb, __FUNCTION__,
- "inode bitmap error for orphan %lu\n", ino);
+ "inode bitmap error for orphan %lu", ino);
goto out;
}
@@ -672,7 +671,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino)
!(inode = iget(sb, ino)) || is_bad_inode(inode) ||
NEXT_ORPHAN(inode) > max_ino) {
ext3_warning(sb, __FUNCTION__,
- "bad orphan inode %lu! e2fsck was run?\n", ino);
+ "bad orphan inode %lu! e2fsck was run?", ino);
printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n",
bit, (unsigned long long)bitmap_bh->b_blocknr,
ext3_test_bit(bit, bitmap_bh->b_data));
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 706d68608381..556cd5510078 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -9,6 +9,7 @@
#include <linux/fs.h>
#include <linux/jbd.h>
+#include <linux/capability.h>
#include <linux/ext3_fs.h>
#include <linux/ext3_jbd.h>
#include <linux/time.h>
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index b3c690a3b54a..8bd8ac077704 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1005,10 +1005,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str
if (!inode)
return ERR_PTR(-EACCES);
}
- if (inode)
- return d_splice_alias(inode, dentry);
- d_add(dentry, inode);
- return NULL;
+ return d_splice_alias(inode, dentry);
}
@@ -1476,7 +1473,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
if (levels && (dx_get_count(frames->entries) ==
dx_get_limit(frames->entries))) {
ext3_warning(sb, __FUNCTION__,
- "Directory index full!\n");
+ "Directory index full!");
err = -ENOSPC;
goto cleanup;
}
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 6104ad310507..1041dab6de2f 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -31,7 +31,7 @@ static int verify_group_input(struct super_block *sb,
unsigned start = le32_to_cpu(es->s_blocks_count);
unsigned end = start + input->blocks_count;
unsigned group = input->group;
- unsigned itend = input->inode_table + EXT3_SB(sb)->s_itb_per_group;
+ unsigned itend = input->inode_table + sbi->s_itb_per_group;
unsigned overhead = ext3_bg_has_super(sb, group) ?
(1 + ext3_bg_num_gdb(sb, group) +
le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
@@ -340,7 +340,7 @@ static int verify_reserved_gdb(struct super_block *sb,
while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){
ext3_warning(sb, __FUNCTION__,
- "reserved GDT %ld missing grp %d (%ld)\n",
+ "reserved GDT %ld missing grp %d (%ld)",
blk, grp,
grp * EXT3_BLOCKS_PER_GROUP(sb) + blk);
return -EINVAL;
@@ -393,7 +393,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
if (EXT3_SB(sb)->s_sbh->b_blocknr !=
le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) {
ext3_warning(sb, __FUNCTION__,
- "won't resize using backup superblock at %llu\n",
+ "won't resize using backup superblock at %llu",
(unsigned long long)EXT3_SB(sb)->s_sbh->b_blocknr);
return -EPERM;
}
@@ -417,7 +417,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
data = (__u32 *)dind->b_data;
if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
ext3_warning(sb, __FUNCTION__,
- "new group %u GDT block %lu not reserved\n",
+ "new group %u GDT block %lu not reserved",
input->group, gdblock);
err = -EINVAL;
goto exit_dind;
@@ -540,7 +540,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
for (res = 0; res < reserved_gdb; res++, blk++) {
if (le32_to_cpu(*data) != blk) {
ext3_warning(sb, __FUNCTION__,
- "reserved block %lu not at offset %ld\n",
+ "reserved block %lu not at offset %ld",
blk, (long)(data - (__u32 *)dind->b_data));
err = -EINVAL;
goto exit_bh;
@@ -683,7 +683,7 @@ exit_err:
if (err) {
ext3_warning(sb, __FUNCTION__,
"can't update backup for group %d (err %d), "
- "forcing fsck on next reboot\n", group, err);
+ "forcing fsck on next reboot", group, err);
sbi->s_mount_state &= ~EXT3_VALID_FS;
sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS);
mark_buffer_dirty(sbi->s_sbh);
@@ -722,7 +722,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb,
EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
ext3_warning(sb, __FUNCTION__,
- "Can't resize non-sparse filesystem further\n");
+ "Can't resize non-sparse filesystem further");
return -EPERM;
}
@@ -730,13 +730,13 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
if (!EXT3_HAS_COMPAT_FEATURE(sb,
EXT3_FEATURE_COMPAT_RESIZE_INODE)){
ext3_warning(sb, __FUNCTION__,
- "No reserved GDT blocks, can't resize\n");
+ "No reserved GDT blocks, can't resize");
return -EPERM;
}
inode = iget(sb, EXT3_RESIZE_INO);
if (!inode || is_bad_inode(inode)) {
ext3_warning(sb, __FUNCTION__,
- "Error opening resize inode\n");
+ "Error opening resize inode");
iput(inode);
return -ENOENT;
}
@@ -764,9 +764,9 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
}
lock_super(sb);
- if (input->group != EXT3_SB(sb)->s_groups_count) {
+ if (input->group != sbi->s_groups_count) {
ext3_warning(sb, __FUNCTION__,
- "multiple resizers run on filesystem!\n");
+ "multiple resizers run on filesystem!");
err = -EBUSY;
goto exit_journal;
}
@@ -799,7 +799,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
* data. So we need to be careful to set all of the relevant
* group descriptor data etc. *before* we enable the group.
*
- * The key field here is EXT3_SB(sb)->s_groups_count: as long as
+ * The key field here is sbi->s_groups_count: as long as
* that retains its old value, nobody is going to access the new
* group.
*
@@ -859,7 +859,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
smp_wmb();
/* Update the global fs size fields */
- EXT3_SB(sb)->s_groups_count++;
+ sbi->s_groups_count++;
ext3_journal_dirty_metadata(handle, primary);
@@ -874,7 +874,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
percpu_counter_mod(&sbi->s_freeinodes_counter,
EXT3_INODES_PER_GROUP(sb));
- ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ ext3_journal_dirty_metadata(handle, sbi->s_sbh);
sb->s_dirt = 1;
exit_journal:
@@ -937,7 +937,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
if (last == 0) {
ext3_warning(sb, __FUNCTION__,
- "need to use ext2online to resize further\n");
+ "need to use ext2online to resize further");
return -EPERM;
}
@@ -973,7 +973,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
lock_super(sb);
if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
ext3_warning(sb, __FUNCTION__,
- "multiple resizers run on filesystem!\n");
+ "multiple resizers run on filesystem!");
err = -EBUSY;
goto exit_put;
}
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 4e6730622d90..56bf76586019 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -43,7 +43,8 @@
#include "acl.h"
#include "namei.h"
-static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
+static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
+ unsigned long journal_devnum);
static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
int);
static void ext3_commit_super (struct super_block * sb,
@@ -628,7 +629,7 @@ enum {
Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
- Opt_commit, Opt_journal_update, Opt_journal_inum,
+ Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
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,
@@ -666,6 +667,7 @@ static match_table_t tokens = {
{Opt_commit, "commit=%u"},
{Opt_journal_update, "journal=update"},
{Opt_journal_inum, "journal=%u"},
+ {Opt_journal_dev, "journal_dev=%u"},
{Opt_abort, "abort"},
{Opt_data_journal, "data=journal"},
{Opt_data_ordered, "data=ordered"},
@@ -705,8 +707,9 @@ static unsigned long get_sb_block(void **data)
return sb_block;
}
-static int parse_options (char * options, struct super_block *sb,
- unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
+static int parse_options (char *options, struct super_block *sb,
+ unsigned long *inum, unsigned long *journal_devnum,
+ unsigned long *n_blocks_count, int is_remount)
{
struct ext3_sb_info *sbi = EXT3_SB(sb);
char * p;
@@ -839,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb,
return 0;
*inum = option;
break;
+ case Opt_journal_dev:
+ if (is_remount) {
+ printk(KERN_ERR "EXT3-fs: cannot specify "
+ "journal on remount\n");
+ return 0;
+ }
+ if (match_int(&args[0], &option))
+ return 0;
+ *journal_devnum = option;
+ break;
case Opt_noload:
set_opt (sbi->s_mount_opt, NOLOAD);
break;
@@ -1331,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
unsigned long logic_sb_block;
unsigned long offset = 0;
unsigned long journal_inum = 0;
+ unsigned long journal_devnum = 0;
unsigned long def_mount_opts;
struct inode *root;
int blocksize;
@@ -1411,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
set_opt(sbi->s_mount_opt, RESERVATION);
- if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
+ if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
+ NULL, 0))
goto failed_mount;
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
@@ -1622,7 +1637,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
*/
if (!test_opt(sb, NOLOAD) &&
EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
- if (ext3_load_journal(sb, es))
+ if (ext3_load_journal(sb, es, journal_devnum))
goto failed_mount2;
} else if (journal_inum) {
if (ext3_create_journal(sb, es, journal_inum))
@@ -1902,15 +1917,24 @@ out_bdev:
return NULL;
}
-static int ext3_load_journal(struct super_block * sb,
- struct ext3_super_block * es)
+static int ext3_load_journal(struct super_block *sb,
+ struct ext3_super_block *es,
+ unsigned long journal_devnum)
{
journal_t *journal;
int journal_inum = le32_to_cpu(es->s_journal_inum);
- dev_t journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
+ dev_t journal_dev;
int err = 0;
int really_read_only;
+ if (journal_devnum &&
+ journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+ printk(KERN_INFO "EXT3-fs: external journal device major/minor "
+ "numbers have changed\n");
+ journal_dev = new_decode_dev(journal_devnum);
+ } else
+ journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
+
really_read_only = bdev_read_only(sb->s_bdev);
/*
@@ -1969,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb,
EXT3_SB(sb)->s_journal = journal;
ext3_clear_journal_err(sb, es);
+
+ if (journal_devnum &&
+ journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+ es->s_journal_dev = cpu_to_le32(journal_devnum);
+ sb->s_dirt = 1;
+
+ /* Make sure we flush the recovery flag to disk. */
+ ext3_commit_super(sb, es, 1);
+ }
+
return 0;
}
@@ -2116,7 +2150,7 @@ int ext3_force_commit(struct super_block *sb)
static void ext3_write_super (struct super_block * sb)
{
- if (down_trylock(&sb->s_lock) == 0)
+ if (mutex_trylock(&sb->s_lock) != 0)
BUG();
sb->s_dirt = 0;
}
@@ -2197,7 +2231,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
/*
* Allow the "check" option to be passed as a remount option.
*/
- if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
+ if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
err = -EINVAL;
goto restore_opts;
}
@@ -2567,7 +2601,7 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
struct buffer_head *bh;
handle_t *handle = journal_current_handle();
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
while (towrite > 0) {
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
@@ -2610,7 +2644,7 @@ out:
inode->i_version++;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
ext3_mark_inode_dirty(handle, inode);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return len - towrite;
}
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 430de9f63be3..e8d60bf6b7df 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -140,7 +140,7 @@ ext3_xattr_handler(int name_index)
/*
* Inode operation listxattr()
*
- * dentry->d_inode->i_sem: don't care
+ * dentry->d_inode->i_mutex: don't care
*/
ssize_t
ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -946,10 +946,6 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
};
int error;
- if (IS_RDONLY(inode))
- return -EROFS;
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
if (!name)
return -EINVAL;
if (strlen(name) > 255)
diff --git a/fs/ext3/xattr_trusted.c b/fs/ext3/xattr_trusted.c
index f68bfd1cf519..86d91f1186dc 100644
--- a/fs/ext3/xattr_trusted.c
+++ b/fs/ext3/xattr_trusted.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/smp_lock.h>
#include <linux/ext3_jbd.h>
@@ -39,8 +40,6 @@ ext3_xattr_trusted_get(struct inode *inode, const char *name,
{
if (strcmp(name, "") == 0)
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
buffer, size);
}
@@ -51,8 +50,6 @@ ext3_xattr_trusted_set(struct inode *inode, const char *name,
{
if (strcmp(name, "") == 0)
return -EINVAL;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
value, size, flags);
}
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index e907cae7a07c..a85a0a17c4fd 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -37,16 +37,10 @@ static int
ext3_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
- int error;
-
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
- error = permission(inode, MAY_READ, NULL);
- if (error)
- return error;
-
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, buffer, size);
}
@@ -54,19 +48,10 @@ static int
ext3_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- int error;
-
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
- if ( !S_ISREG(inode->i_mode) &&
- (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
- return -EPERM;
- error = permission(inode, MAY_WRITE, NULL);
- if (error)
- return error;
-
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
value, size, flags);
}
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 77c24fcf712a..1acc941245fb 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -295,7 +295,8 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
return dclus;
}
-int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
+int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ unsigned long *mapped_blocks)
{
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
@@ -303,9 +304,12 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
int cluster, offset;
*phys = 0;
+ *mapped_blocks = 0;
if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) {
- if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits))
+ if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits)) {
*phys = sector + sbi->dir_start;
+ *mapped_blocks = 1;
+ }
return 0;
}
last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
@@ -318,7 +322,11 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys)
cluster = fat_bmap_cluster(inode, cluster);
if (cluster < 0)
return cluster;
- else if (cluster)
+ else if (cluster) {
*phys = fat_clus_to_blknr(sbi, cluster) + offset;
+ *mapped_blocks = sbi->sec_per_clus - offset;
+ if (*mapped_blocks > last_block - sector)
+ *mapped_blocks = last_block - sector;
+ }
return 0;
}
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index ba824964b9bb..db0de5c621c7 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -45,8 +45,8 @@ static inline void fat_dir_readahead(struct inode *dir, sector_t iblock,
if ((sbi->fat_bits != 32) && (dir->i_ino == MSDOS_ROOT_INO))
return;
- bh = sb_getblk(sb, phys);
- if (bh && !buffer_uptodate(bh)) {
+ bh = sb_find_get_block(sb, phys);
+ if (bh == NULL || !buffer_uptodate(bh)) {
for (sec = 0; sec < sbi->sec_per_clus; sec++)
sb_breadahead(sb, phys + sec);
}
@@ -68,8 +68,8 @@ static int fat__get_entry(struct inode *dir, loff_t *pos,
{
struct super_block *sb = dir->i_sb;
sector_t phys, iblock;
- int offset;
- int err;
+ unsigned long mapped_blocks;
+ int err, offset;
next:
if (*bh)
@@ -77,7 +77,7 @@ next:
*bh = NULL;
iblock = *pos >> sb->s_blocksize_bits;
- err = fat_bmap(dir, iblock, &phys);
+ err = fat_bmap(dir, iblock, &phys, &mapped_blocks);
if (err || !phys)
return -1; /* beyond EOF or error */
@@ -418,7 +418,7 @@ EODir:
return err;
}
-EXPORT_SYMBOL(fat_search_long);
+EXPORT_SYMBOL_GPL(fat_search_long);
struct fat_ioctl_filldir_callback {
struct dirent __user *dirent;
@@ -729,13 +729,13 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp,
buf.dirent = d1;
buf.result = 0;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = -ENOENT;
if (!IS_DEADDIR(inode)) {
ret = __fat_readdir(inode, filp, &buf, fat_ioctl_filldir,
short_only, both);
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret >= 0)
ret = buf.result;
return ret;
@@ -780,7 +780,7 @@ int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
return -ENOENT;
}
-EXPORT_SYMBOL(fat_get_dotdot_entry);
+EXPORT_SYMBOL_GPL(fat_get_dotdot_entry);
/* See if directory is empty */
int fat_dir_empty(struct inode *dir)
@@ -803,7 +803,7 @@ int fat_dir_empty(struct inode *dir)
return result;
}
-EXPORT_SYMBOL(fat_dir_empty);
+EXPORT_SYMBOL_GPL(fat_dir_empty);
/*
* fat_subdirs counts the number of sub-directories of dir. It can be run
@@ -849,7 +849,7 @@ int fat_scan(struct inode *dir, const unsigned char *name,
return -ENOENT;
}
-EXPORT_SYMBOL(fat_scan);
+EXPORT_SYMBOL_GPL(fat_scan);
static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
{
@@ -936,7 +936,7 @@ int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
return 0;
}
-EXPORT_SYMBOL(fat_remove_entries);
+EXPORT_SYMBOL_GPL(fat_remove_entries);
static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
struct buffer_head **bhs, int nr_bhs)
@@ -1048,7 +1048,7 @@ error:
return err;
}
-EXPORT_SYMBOL(fat_alloc_new_dir);
+EXPORT_SYMBOL_GPL(fat_alloc_new_dir);
static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,
int *nr_cluster, struct msdos_dir_entry **de,
@@ -1264,4 +1264,4 @@ error_remove:
return err;
}
-EXPORT_SYMBOL(fat_add_entries);
+EXPORT_SYMBOL_GPL(fat_add_entries);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 4164cd54c4d1..a1a9e0451217 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -476,6 +476,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
sbi->prev_free = entry;
if (sbi->free_clusters != -1)
sbi->free_clusters--;
+ sb->s_dirt = 1;
cluster[idx_clus] = entry;
idx_clus++;
@@ -496,6 +497,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
/* Couldn't allocate the free entries */
sbi->free_clusters = 0;
+ sb->s_dirt = 1;
err = -ENOSPC;
out:
@@ -509,7 +511,6 @@ out:
}
for (i = 0; i < nr_bhs; i++)
brelse(bhs[i]);
- fat_clusters_flush(sb);
if (err && idx_clus)
fat_free_clusters(inode, cluster[0]);
@@ -542,8 +543,10 @@ int fat_free_clusters(struct inode *inode, int cluster)
}
ops->ent_put(&fatent, FAT_ENT_FREE);
- if (sbi->free_clusters != -1)
+ if (sbi->free_clusters != -1) {
sbi->free_clusters++;
+ sb->s_dirt = 1;
+ }
if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {
if (sb->s_flags & MS_SYNCHRONOUS) {
@@ -578,7 +581,7 @@ error:
return err;
}
-EXPORT_SYMBOL(fat_free_clusters);
+EXPORT_SYMBOL_GPL(fat_free_clusters);
int fat_count_free_clusters(struct super_block *sb)
{
@@ -605,6 +608,7 @@ int fat_count_free_clusters(struct super_block *sb)
} while (fat_ent_next(sbi, &fatent));
}
sbi->free_clusters = free;
+ sb->s_dirt = 1;
fatent_brelse(&fatent);
out:
unlock_fat(sbi);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 7134403d5be2..e99c5a73b39e 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -6,11 +6,13 @@
* regular file handling primitives for fat-based filesystems
*/
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/time.h>
#include <linux/msdos_fs.h>
#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
+#include <linux/writeback.h>
int fat_generic_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
@@ -40,7 +42,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
if (err)
return err;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (IS_RDONLY(inode)) {
err = -EROFS;
@@ -102,7 +104,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
mark_inode_dirty(inode);
up:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return err;
}
default:
@@ -124,6 +126,24 @@ struct file_operations fat_file_operations = {
.sendfile = generic_file_sendfile,
};
+static int fat_cont_expand(struct inode *inode, loff_t size)
+{
+ struct address_space *mapping = inode->i_mapping;
+ loff_t start = inode->i_size, count = size - inode->i_size;
+ int err;
+
+ err = generic_cont_expand_simple(inode, size);
+ if (err)
+ goto out;
+
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+ if (IS_SYNC(inode))
+ err = sync_page_range_nolock(inode, mapping, start, count);
+out:
+ return err;
+}
+
int fat_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
@@ -132,11 +152,17 @@ int fat_notify_change(struct dentry *dentry, struct iattr *attr)
lock_kernel();
- /* FAT cannot truncate to a longer file */
+ /*
+ * Expand the file. Since inode_setattr() updates ->i_size
+ * before calling the ->truncate(), but FAT needs to fill the
+ * hole before it.
+ */
if (attr->ia_valid & ATTR_SIZE) {
if (attr->ia_size > inode->i_size) {
- error = -EPERM;
- goto out;
+ error = fat_cont_expand(inode, attr->ia_size);
+ if (error || attr->ia_valid == ATTR_SIZE)
+ goto out;
+ attr->ia_valid &= ~ATTR_SIZE;
}
}
@@ -173,7 +199,7 @@ out:
return error;
}
-EXPORT_SYMBOL(fat_notify_change);
+EXPORT_SYMBOL_GPL(fat_notify_change);
/* Free all clusters after the skip'th cluster. */
static int fat_free(struct inode *inode, int skip)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a0f9b9fe1307..e7f4aa7fc686 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -18,10 +18,12 @@
#include <linux/seq_file.h>
#include <linux/msdos_fs.h>
#include <linux/pagemap.h>
+#include <linux/mpage.h>
#include <linux/buffer_head.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/parser.h>
+#include <linux/uio.h>
#include <asm/unaligned.h>
#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
@@ -48,51 +50,97 @@ static int fat_add_cluster(struct inode *inode)
return err;
}
-static int fat_get_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create)
+static int __fat_get_blocks(struct inode *inode, sector_t iblock,
+ unsigned long *max_blocks,
+ struct buffer_head *bh_result, int create)
{
struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
sector_t phys;
- int err;
+ unsigned long mapped_blocks;
+ int err, offset;
- err = fat_bmap(inode, iblock, &phys);
+ err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
if (err)
return err;
if (phys) {
map_bh(bh_result, sb, phys);
+ *max_blocks = min(mapped_blocks, *max_blocks);
return 0;
}
if (!create)
return 0;
+
if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
return -EIO;
}
- if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
+
+ offset = (unsigned long)iblock & (sbi->sec_per_clus - 1);
+ if (!offset) {
+ /* TODO: multiple cluster allocation would be desirable. */
err = fat_add_cluster(inode);
if (err)
return err;
}
- MSDOS_I(inode)->mmu_private += sb->s_blocksize;
- err = fat_bmap(inode, iblock, &phys);
+ /* available blocks on this cluster */
+ mapped_blocks = sbi->sec_per_clus - offset;
+
+ *max_blocks = min(mapped_blocks, *max_blocks);
+ MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits;
+
+ err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
if (err)
return err;
- if (!phys)
- BUG();
+ BUG_ON(!phys);
+ BUG_ON(*max_blocks != mapped_blocks);
set_buffer_new(bh_result);
map_bh(bh_result, sb, phys);
return 0;
}
+static int fat_get_blocks(struct inode *inode, sector_t iblock,
+ unsigned long max_blocks,
+ struct buffer_head *bh_result, int create)
+{
+ struct super_block *sb = inode->i_sb;
+ int err;
+
+ err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
+ if (err)
+ return err;
+ bh_result->b_size = max_blocks << sb->s_blocksize_bits;
+ return 0;
+}
+
+static int fat_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ unsigned long max_blocks = 1;
+ return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
+}
+
static int fat_writepage(struct page *page, struct writeback_control *wbc)
{
return block_write_full_page(page, fat_get_block, wbc);
}
+static int fat_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ return mpage_writepages(mapping, wbc, fat_get_block);
+}
+
static int fat_readpage(struct file *file, struct page *page)
{
- return block_read_full_page(page, fat_get_block);
+ return mpage_readpage(page, fat_get_block);
+}
+
+static int fat_readpages(struct file *file, struct address_space *mapping,
+ struct list_head *pages, unsigned nr_pages)
+{
+ return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
}
static int fat_prepare_write(struct file *file, struct page *page,
@@ -115,6 +163,34 @@ static int fat_commit_write(struct file *file, struct page *page,
return err;
}
+static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
+ const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+
+ if (rw == WRITE) {
+ /*
+ * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(),
+ * so we need to update the ->mmu_private to block boundary.
+ *
+ * But we must fill the remaining area or hole by nul for
+ * updating ->mmu_private.
+ */
+ loff_t size = offset + iov_length(iov, nr_segs);
+ if (MSDOS_I(inode)->mmu_private < size)
+ return -EINVAL;
+ }
+
+ /*
+ * FAT need to use the DIO_LOCKING for avoiding the race
+ * condition of fat_get_block() and ->truncate().
+ */
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ offset, nr_segs, fat_get_blocks, NULL);
+}
+
static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping, block, fat_get_block);
@@ -122,10 +198,13 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
static struct address_space_operations fat_aops = {
.readpage = fat_readpage,
+ .readpages = fat_readpages,
.writepage = fat_writepage,
+ .writepages = fat_writepages,
.sync_page = block_sync_page,
.prepare_write = fat_prepare_write,
.commit_write = fat_commit_write,
+ .direct_IO = fat_direct_IO,
.bmap = _fat_bmap
};
@@ -182,7 +261,7 @@ void fat_attach(struct inode *inode, loff_t i_pos)
spin_unlock(&sbi->inode_hash_lock);
}
-EXPORT_SYMBOL(fat_attach);
+EXPORT_SYMBOL_GPL(fat_attach);
void fat_detach(struct inode *inode)
{
@@ -193,7 +272,7 @@ void fat_detach(struct inode *inode)
spin_unlock(&sbi->inode_hash_lock);
}
-EXPORT_SYMBOL(fat_detach);
+EXPORT_SYMBOL_GPL(fat_detach);
struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
{
@@ -347,7 +426,7 @@ out:
return inode;
}
-EXPORT_SYMBOL(fat_build_inode);
+EXPORT_SYMBOL_GPL(fat_build_inode);
static void fat_delete_inode(struct inode *inode)
{
@@ -374,12 +453,17 @@ static void fat_clear_inode(struct inode *inode)
unlock_kernel();
}
-static void fat_put_super(struct super_block *sb)
+static void fat_write_super(struct super_block *sb)
{
- struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ sb->s_dirt = 0;
if (!(sb->s_flags & MS_RDONLY))
fat_clusters_flush(sb);
+}
+
+static void fat_put_super(struct super_block *sb)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
if (sbi->nls_disk) {
unload_nls(sbi->nls_disk);
@@ -537,7 +621,7 @@ int fat_sync_inode(struct inode *inode)
return fat_write_inode(inode, 1);
}
-EXPORT_SYMBOL(fat_sync_inode);
+EXPORT_SYMBOL_GPL(fat_sync_inode);
static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
static struct super_operations fat_sops = {
@@ -546,6 +630,7 @@ static struct super_operations fat_sops = {
.write_inode = fat_write_inode,
.delete_inode = fat_delete_inode,
.put_super = fat_put_super,
+ .write_super = fat_write_super,
.statfs = fat_statfs,
.clear_inode = fat_clear_inode,
.remount_fs = fat_remount,
@@ -1347,7 +1432,7 @@ out_fail:
return error;
}
-EXPORT_SYMBOL(fat_fill_super);
+EXPORT_SYMBOL_GPL(fat_fill_super);
int __init fat_cache_init(void);
void fat_cache_destroy(void);
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 2a0df2122f5d..32fb0a3f1da4 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -33,7 +33,7 @@ void fat_fs_panic(struct super_block *s, const char *fmt, ...)
}
}
-EXPORT_SYMBOL(fat_fs_panic);
+EXPORT_SYMBOL_GPL(fat_fs_panic);
/* Flushes the number of free clusters on FAT32 */
/* XXX: Need to write one per FSINFO block. Currently only writes 1 */
@@ -67,8 +67,6 @@ void fat_clusters_flush(struct super_block *sb)
if (sbi->prev_free != -1)
fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
mark_buffer_dirty(bh);
- if (sb->s_flags & MS_SYNCHRONOUS)
- sync_dirty_buffer(bh);
}
brelse(bh);
}
@@ -194,7 +192,7 @@ void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
*date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
}
-EXPORT_SYMBOL(fat_date_unix2dos);
+EXPORT_SYMBOL_GPL(fat_date_unix2dos);
int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
{
@@ -222,4 +220,4 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
return err;
}
-EXPORT_SYMBOL(fat_sync_bhs);
+EXPORT_SYMBOL_GPL(fat_sync_bhs);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 863b46e0d78a..5f96786d1c73 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
+#include <linux/capability.h>
#include <linux/dnotify.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
@@ -35,7 +36,7 @@ void fastcall set_close_on_exec(unsigned int fd, int flag)
spin_unlock(&files->file_lock);
}
-static inline int get_close_on_exec(unsigned int fd)
+static int get_close_on_exec(unsigned int fd)
{
struct files_struct *files = current->files;
struct fdtable *fdt;
@@ -457,11 +458,11 @@ static void send_sigio_to_task(struct task_struct *p,
else
si.si_band = band_table[reason - POLL_IN];
si.si_fd = fd;
- if (!send_group_sig_info(fown->signum, &si, p))
+ if (!group_send_sig_info(fown->signum, &si, p))
break;
/* fall-through: fall back on the old plain SIGIO signal */
case 0:
- send_group_sig_info(SIGIO, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGIO, SEND_SIG_PRIV, p);
}
}
@@ -495,7 +496,7 @@ static void send_sigurg_to_task(struct task_struct *p,
struct fown_struct *fown)
{
if (sigio_perm(p, fown, SIGURG))
- send_group_sig_info(SIGURG, SEND_SIG_PRIV, p);
+ group_send_sig_info(SIGURG, SEND_SIG_PRIV, p);
}
int send_sigurg(struct fown_struct *fown)
diff --git a/fs/fifo.c b/fs/fifo.c
index 5455916241f0..923371b753ab 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -35,7 +35,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
int ret;
ret = -ERESTARTSYS;
- if (down_interruptible(PIPE_SEM(*inode)))
+ if (mutex_lock_interruptible(PIPE_MUTEX(*inode)))
goto err_nolock_nocleanup;
if (!inode->i_pipe) {
@@ -119,7 +119,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
}
/* Ok! */
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return 0;
err_rd:
@@ -139,7 +139,7 @@ err:
free_pipe_info(inode);
err_nocleanup:
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
err_nolock_nocleanup:
return ret;
diff --git a/fs/file_table.c b/fs/file_table.c
index c3a5e2fd663b..768b58167543 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -16,6 +16,7 @@
#include <linux/eventpoll.h>
#include <linux/rcupdate.h>
#include <linux/mount.h>
+#include <linux/capability.h>
#include <linux/cdev.h>
#include <linux/fsnotify.h>
@@ -117,7 +118,7 @@ EXPORT_SYMBOL(get_empty_filp);
void fastcall fput(struct file *file)
{
- if (rcuref_dec_and_test(&file->f_count))
+ if (atomic_dec_and_test(&file->f_count))
__fput(file);
}
@@ -166,7 +167,7 @@ struct file fastcall *fget(unsigned int fd)
rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
- if (!rcuref_inc_lf(&file->f_count)) {
+ if (!atomic_inc_not_zero(&file->f_count)) {
/* File object ref couldn't be taken */
rcu_read_unlock();
return NULL;
@@ -198,7 +199,7 @@ struct file fastcall *fget_light(unsigned int fd, int *fput_needed)
rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
- if (rcuref_inc_lf(&file->f_count))
+ if (atomic_inc_not_zero(&file->f_count))
*fput_needed = 1;
else
/* Didn't get the reference, someone's freed */
@@ -213,7 +214,7 @@ struct file fastcall *fget_light(unsigned int fd, int *fput_needed)
void put_filp(struct file *file)
{
- if (rcuref_dec_and_test(&file->f_count)) {
+ if (atomic_dec_and_test(&file->f_count)) {
security_file_free(file);
file_kill(file);
file_free(file);
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index d0401dc68d41..6f5df1700e95 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -99,8 +99,8 @@ static int
vxfs_immed_readpage(struct file *fp, struct page *pp)
{
struct vxfs_inode_info *vip = VXFS_INO(pp->mapping->host);
- u_int64_t offset = pp->index << PAGE_CACHE_SHIFT;
- caddr_t kaddr;
+ u_int64_t offset = (u_int64_t)pp->index << PAGE_CACHE_SHIFT;
+ caddr_t kaddr;
kaddr = kmap(pp);
memcpy(kaddr, vip->vii_immed.vi_immed + offset, PAGE_CACHE_SIZE);
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 8f873e621f41..4526da8907c6 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -21,18 +21,18 @@ MODULE_ALIAS_MISCDEV(FUSE_MINOR);
static kmem_cache_t *fuse_req_cachep;
-static inline struct fuse_conn *fuse_get_conn(struct file *file)
+static struct fuse_conn *fuse_get_conn(struct file *file)
{
struct fuse_conn *fc;
spin_lock(&fuse_lock);
fc = file->private_data;
- if (fc && !fc->mounted)
+ if (fc && !fc->connected)
fc = NULL;
spin_unlock(&fuse_lock);
return fc;
}
-static inline void fuse_request_init(struct fuse_req *req)
+static void fuse_request_init(struct fuse_req *req)
{
memset(req, 0, sizeof(*req));
INIT_LIST_HEAD(&req->list);
@@ -53,7 +53,7 @@ void fuse_request_free(struct fuse_req *req)
kmem_cache_free(fuse_req_cachep, req);
}
-static inline void block_sigs(sigset_t *oldset)
+static void block_sigs(sigset_t *oldset)
{
sigset_t mask;
@@ -61,7 +61,7 @@ static inline void block_sigs(sigset_t *oldset)
sigprocmask(SIG_BLOCK, &mask, oldset);
}
-static inline void restore_sigs(sigset_t *oldset)
+static void restore_sigs(sigset_t *oldset)
{
sigprocmask(SIG_SETMASK, oldset, NULL);
}
@@ -109,18 +109,24 @@ struct fuse_req *fuse_get_request(struct fuse_conn *fc)
int intr;
sigset_t oldset;
+ atomic_inc(&fc->num_waiting);
block_sigs(&oldset);
intr = down_interruptible(&fc->outstanding_sem);
restore_sigs(&oldset);
- return intr ? NULL : do_get_request(fc);
+ if (intr) {
+ atomic_dec(&fc->num_waiting);
+ return NULL;
+ }
+ return do_get_request(fc);
}
static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req)
{
spin_lock(&fuse_lock);
- if (req->preallocated)
+ if (req->preallocated) {
+ atomic_dec(&fc->num_waiting);
list_add(&req->list, &fc->unused_list);
- else
+ } else
fuse_request_free(req);
/* If we are in debt decrease that first */
@@ -151,19 +157,20 @@ void fuse_release_background(struct fuse_req *req)
/*
* 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
- * occurred during communication with userspace, or the device file was
- * closed. It decreases the reference count for the request. In case
- * of a background request the reference 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
+ * occurred during communication with userspace, or the device file
+ * was closed. In case of a background request the reference to the
+ * stored objects are released. The requester thread is woken up (if
+ * still waiting), the 'end' callback is called if given, else the
+ * reference to the request is released
*
* 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);
+ void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
+ req->end = NULL;
+ list_del(&req->list);
+ req->state = FUSE_REQ_FINISHED;
spin_unlock(&fuse_lock);
if (req->background) {
down_read(&fc->sbput_sem);
@@ -172,28 +179,10 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *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);
- } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
- /* Special case for failed iget in CREATE */
- u64 nodeid = req->in.h.nodeid;
- __fuse_get_request(req);
- fuse_reset_request(req);
- fuse_send_forget(fc, req, nodeid, 1);
- putback = 0;
- }
- if (putback)
- fuse_putback_request(fc, req);
+ if (end)
+ end(fc, req);
+ else
+ fuse_put_request(fc, req);
}
/*
@@ -244,14 +233,16 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
spin_unlock(&fuse_lock);
block_sigs(&oldset);
- wait_event_interruptible(req->waitq, req->finished);
+ wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
restore_sigs(&oldset);
spin_lock(&fuse_lock);
- if (req->finished)
+ if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
return;
- req->out.h.error = -EINTR;
- req->interrupted = 1;
+ if (!req->interrupted) {
+ 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
@@ -262,10 +253,10 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
wait_event(req->waitq, !req->locked);
spin_lock(&fuse_lock);
}
- if (!req->sent && !list_empty(&req->list)) {
+ if (req->state == FUSE_REQ_PENDING) {
list_del(&req->list);
__fuse_put_request(req);
- } else if (!req->finished && req->sent)
+ } else if (req->state == FUSE_REQ_SENT)
background_request(fc, req);
}
@@ -300,6 +291,7 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
fc->outstanding_debt++;
}
list_add_tail(&req->list, &fc->pending);
+ req->state = FUSE_REQ_PENDING;
wake_up(&fc->waitq);
}
@@ -352,30 +344,12 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
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)
+static int lock_request(struct fuse_req *req)
{
int err = 0;
if (req) {
@@ -394,7 +368,7 @@ static inline int lock_request(struct fuse_req *req)
* requester thread is currently waiting for it to be unlocked, so
* wake it up.
*/
-static inline void unlock_request(struct fuse_req *req)
+static void unlock_request(struct fuse_req *req)
{
if (req) {
spin_lock(&fuse_lock);
@@ -430,7 +404,7 @@ static void fuse_copy_init(struct fuse_copy_state *cs, int write,
}
/* Unmap and put previous page of userspace buffer */
-static inline void fuse_copy_finish(struct fuse_copy_state *cs)
+static void fuse_copy_finish(struct fuse_copy_state *cs)
{
if (cs->mapaddr) {
kunmap_atomic(cs->mapaddr, KM_USER0);
@@ -479,8 +453,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs)
}
/* 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)
+static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
{
unsigned ncpy = min(*size, cs->len);
if (val) {
@@ -500,8 +473,8 @@ static inline int fuse_copy_do(struct fuse_copy_state *cs, void **val,
* 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)
+static 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);
@@ -583,7 +556,7 @@ 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)) {
+ while (fc->connected && list_empty(&fc->pending)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current))
break;
@@ -615,6 +588,7 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
struct fuse_copy_state cs;
unsigned reqsize;
+ restart:
spin_lock(&fuse_lock);
fc = file->private_data;
err = -EPERM;
@@ -622,28 +596,34 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
goto err_unlock;
request_wait(fc);
err = -ENODEV;
- if (!fc->mounted)
+ if (!fc->connected)
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);
+ req->state = FUSE_REQ_READING;
+ list_move(&req->list, &fc->io);
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);
+ reqsize = in->h.len;
+ /* If request is too large, reply with an error and restart the read */
+ if (iov_length(iov, nr_segs) < reqsize) {
+ req->out.h.error = -EIO;
+ /* SETXATTR is special, since it may contain too large data */
+ if (in->h.opcode == FUSE_SETXATTR)
+ req->out.h.error = -E2BIG;
+ request_end(fc, req);
+ goto restart;
}
+ spin_unlock(&fuse_lock);
+ fuse_copy_init(&cs, 1, req, iov, nr_segs);
+ err = fuse_copy_one(&cs, &in->h, sizeof(in->h));
+ if (!err)
+ err = fuse_copy_args(&cs, in->numargs, in->argpages,
+ (struct fuse_arg *) in->args, 0);
fuse_copy_finish(&cs);
-
spin_lock(&fuse_lock);
req->locked = 0;
if (!err && req->interrupted)
@@ -657,8 +637,8 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov,
if (!req->isreply)
request_end(fc, req);
else {
- req->sent = 1;
- list_add_tail(&req->list, &fc->processing);
+ req->state = FUSE_REQ_SENT;
+ list_move_tail(&req->list, &fc->processing);
spin_unlock(&fuse_lock);
}
return reqsize;
@@ -746,17 +726,23 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
goto err_finish;
spin_lock(&fuse_lock);
+ err = -ENOENT;
+ if (!fc->connected)
+ goto err_unlock;
+
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);
+ spin_unlock(&fuse_lock);
fuse_copy_finish(&cs);
+ spin_lock(&fuse_lock);
+ request_end(fc, req);
return -ENOENT;
}
+ list_move(&req->list, &fc->io);
req->out.h = oh;
req->locked = 1;
cs.req = req;
@@ -810,19 +796,90 @@ static unsigned fuse_dev_poll(struct file *file, poll_table *wait)
return mask;
}
-/* Abort all requests on the given list (pending or processing) */
+/*
+ * Abort all requests on the given list (pending or processing)
+ *
+ * This function releases and reacquires fuse_lock
+ */
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);
}
}
+/*
+ * Abort requests under I/O
+ *
+ * The requests are set to interrupted and finished, and the request
+ * waiter is woken up. This will make request_wait_answer() wait
+ * until the request is unlocked and then return.
+ *
+ * If the request is asynchronous, then the end function needs to be
+ * called after waiting for the request to be unlocked (if it was
+ * locked).
+ */
+static void end_io_requests(struct fuse_conn *fc)
+{
+ while (!list_empty(&fc->io)) {
+ struct fuse_req *req =
+ list_entry(fc->io.next, struct fuse_req, list);
+ void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
+
+ req->interrupted = 1;
+ req->out.h.error = -ECONNABORTED;
+ req->state = FUSE_REQ_FINISHED;
+ list_del_init(&req->list);
+ wake_up(&req->waitq);
+ if (end) {
+ req->end = NULL;
+ /* The end function will consume this reference */
+ __fuse_get_request(req);
+ spin_unlock(&fuse_lock);
+ wait_event(req->waitq, !req->locked);
+ end(fc, req);
+ spin_lock(&fuse_lock);
+ }
+ }
+}
+
+/*
+ * Abort all requests.
+ *
+ * Emergency exit in case of a malicious or accidental deadlock, or
+ * just a hung filesystem.
+ *
+ * The same effect is usually achievable through killing the
+ * filesystem daemon and all users of the filesystem. The exception
+ * is the combination of an asynchronous request and the tricky
+ * deadlock (see Documentation/filesystems/fuse.txt).
+ *
+ * During the aborting, progression of requests from the pending and
+ * processing lists onto the io list, and progression of new requests
+ * onto the pending list is prevented by req->connected being false.
+ *
+ * Progression of requests under I/O to the processing list is
+ * prevented by the req->interrupted flag being true for these
+ * requests. For this reason requests on the io list must be aborted
+ * first.
+ */
+void fuse_abort_conn(struct fuse_conn *fc)
+{
+ spin_lock(&fuse_lock);
+ if (fc->connected) {
+ fc->connected = 0;
+ end_io_requests(fc);
+ end_requests(fc, &fc->pending);
+ end_requests(fc, &fc->processing);
+ wake_up_all(&fc->waitq);
+ }
+ spin_unlock(&fuse_lock);
+}
+
static int fuse_dev_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc;
@@ -833,9 +890,11 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
fc->connected = 0;
end_requests(fc, &fc->pending);
end_requests(fc, &fc->processing);
- fuse_release_conn(fc);
}
spin_unlock(&fuse_lock);
+ if (fc)
+ kobject_put(&fc->kobj);
+
return 0;
}
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 51f5da652771..21fd59c7bc24 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -13,15 +13,66 @@
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/namei.h>
-#include <linux/mount.h>
-static inline unsigned long time_to_jiffies(unsigned long sec,
- unsigned long nsec)
+/*
+ * FUSE caches dentries and attributes with separate timeout. The
+ * time in jiffies until the dentry/attributes are valid is stored in
+ * dentry->d_time and fuse_inode->i_time respectively.
+ */
+
+/*
+ * Calculate the time in jiffies until a dentry/attributes are valid
+ */
+static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec)
{
struct timespec ts = {sec, nsec};
return jiffies + timespec_to_jiffies(&ts);
}
+/*
+ * Set dentry and possibly attribute timeouts from the lookup/mk*
+ * replies
+ */
+static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
+{
+ entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
+ if (entry->d_inode)
+ get_fuse_inode(entry->d_inode)->i_time =
+ time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+}
+
+/*
+ * Mark the attributes as stale, so that at the next call to
+ * ->getattr() they will be fetched from userspace
+ */
+void fuse_invalidate_attr(struct inode *inode)
+{
+ get_fuse_inode(inode)->i_time = jiffies - 1;
+}
+
+/*
+ * Just mark the entry as stale, so that a next attempt to look it up
+ * will result in a new lookup call to userspace
+ *
+ * This is called when a dentry is about to become negative and the
+ * timeout is unknown (unlink, rmdir, rename and in some cases
+ * lookup)
+ */
+static void fuse_invalidate_entry_cache(struct dentry *entry)
+{
+ entry->d_time = jiffies - 1;
+}
+
+/*
+ * Same as fuse_invalidate_entry_cache(), but also try to remove the
+ * dentry from the hash
+ */
+static void fuse_invalidate_entry(struct dentry *entry)
+{
+ d_invalidate(entry);
+ fuse_invalidate_entry_cache(entry);
+}
+
static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
struct dentry *entry,
struct fuse_entry_out *outarg)
@@ -37,17 +88,34 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
req->out.args[0].value = outarg;
}
+/*
+ * Check whether the dentry is still valid
+ *
+ * If the entry validity timeout has expired and the dentry is
+ * positive, try to redo the lookup. If the lookup results in a
+ * different inode, then let the VFS invalidate the dentry and redo
+ * the lookup once more. If the lookup results in the same inode,
+ * then refresh the attributes, timeouts and mark the dentry valid.
+ */
static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
{
- if (!entry->d_inode || is_bad_inode(entry->d_inode))
+ struct inode *inode = entry->d_inode;
+
+ if (inode && is_bad_inode(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);
+ struct fuse_conn *fc;
+ struct fuse_req *req;
+
+ /* Doesn't hurt to "reset" the validity timeout */
+ fuse_invalidate_entry_cache(entry);
+ if (!inode)
+ return 0;
+
+ fc = get_fuse_conn(inode);
+ req = fuse_get_request(fc);
if (!req)
return 0;
@@ -55,6 +123,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
request_send(fc, req);
err = req->out.h.error;
if (!err) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
if (outarg.nodeid != get_node_id(inode)) {
fuse_send_forget(fc, req, outarg.nodeid, 1);
return 0;
@@ -66,18 +135,18 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
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);
+ fuse_change_timeout(entry, &outarg);
}
return 1;
}
+/*
+ * Check if there's already a hashed alias of this directory inode.
+ * If yes, then lookup and mkdir must not create a new alias.
+ */
static int dir_alias(struct inode *inode)
{
if (S_ISDIR(inode->i_mode)) {
- /* Don't allow creating an alias to a directory */
struct dentry *alias = d_find_alias(inode);
if (alias) {
dput(alias);
@@ -87,7 +156,7 @@ static int dir_alias(struct inode *inode)
return 0;
}
-static inline int invalid_nodeid(u64 nodeid)
+static int invalid_nodeid(u64 nodeid)
{
return !nodeid || nodeid == FUSE_ROOT_ID;
}
@@ -96,8 +165,14 @@ 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)
+static int valid_mode(int m)
+{
+ return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
+ S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
+}
+
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+ struct nameidata *nd)
{
int err;
struct fuse_entry_out outarg;
@@ -106,53 +181,49 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
struct fuse_req *req;
if (entry->d_name.len > FUSE_NAME_MAX)
- return -ENAMETOOLONG;
+ return ERR_PTR(-ENAMETOOLONG);
req = fuse_get_request(fc);
if (!req)
- return -EINTR;
+ return ERR_PTR(-EINTR);
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
err = req->out.h.error;
- if (!err && invalid_nodeid(outarg.nodeid))
+ if (!err && ((outarg.nodeid && invalid_nodeid(outarg.nodeid)) ||
+ !valid_mode(outarg.attr.mode)))
err = -EIO;
- if (!err) {
+ if (!err && outarg.nodeid) {
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
&outarg.attr);
if (!inode) {
fuse_send_forget(fc, req, outarg.nodeid, 1);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
}
fuse_put_request(fc, req);
if (err && err != -ENOENT)
- return err;
+ return ERR_PTR(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);
+ if (inode && dir_alias(inode)) {
+ iput(inode);
+ return ERR_PTR(-EIO);
}
-
+ d_add(entry, inode);
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;
+ if (!err)
+ fuse_change_timeout(entry, &outarg);
+ else
+ fuse_invalidate_entry_cache(entry);
+ return NULL;
}
+/*
+ * Atomic create+open operation
+ *
+ * If the filesystem doesn't support this, then fall back to separate
+ * 'mknod' + 'open' requests.
+ */
static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct nameidata *nd)
{
@@ -163,7 +234,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct fuse_open_in inarg;
struct fuse_open_out outopen;
struct fuse_entry_out outentry;
- struct fuse_inode *fi;
struct fuse_file *ff;
struct file *file;
int flags = nd->intent.open.flags - 1;
@@ -172,10 +242,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
if (fc->no_create)
goto out;
- err = -ENAMETOOLONG;
- if (entry->d_name.len > FUSE_NAME_MAX)
- goto out;
-
err = -EINTR;
req = fuse_get_request(fc);
if (!req)
@@ -220,17 +286,15 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
if (!inode) {
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
ff->fh = outopen.fh;
+ /* Special release, with inode = NULL, this will
+ trigger a 'forget' request when the release is
+ complete */
fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
goto out_put_request;
}
fuse_put_request(fc, req);
- entry->d_time = time_to_jiffies(outentry.entry_valid,
- outentry.entry_valid_nsec);
- fi = get_fuse_inode(inode);
- fi->i_time = time_to_jiffies(outentry.attr_valid,
- outentry.attr_valid_nsec);
-
d_instantiate(entry, inode);
+ fuse_change_timeout(entry, &outentry);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
ff->fh = outopen.fh;
@@ -248,13 +312,15 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
return err;
}
+/*
+ * Code shared between mknod, mkdir, symlink and link
+ */
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);
@@ -268,10 +334,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
fuse_put_request(fc, req);
return err;
}
- if (invalid_nodeid(outarg.nodeid)) {
- fuse_put_request(fc, req);
- return -EIO;
- }
+ err = -EIO;
+ if (invalid_nodeid(outarg.nodeid))
+ goto out_put_request;
+
+ if ((outarg.attr.mode ^ mode) & S_IFMT)
+ goto out_put_request;
+
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
&outarg.attr);
if (!inode) {
@@ -280,22 +349,19 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
}
fuse_put_request(fc, req);
- /* Don't allow userspace to do really stupid things... */
- if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) {
+ if (dir_alias(inode)) {
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_change_timeout(entry, &outarg);
fuse_invalidate_attr(dir);
return 0;
+
+ out_put_request:
+ fuse_put_request(fc, req);
+ return err;
}
static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
@@ -355,12 +421,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
{
struct fuse_conn *fc = get_fuse_conn(dir);
unsigned len = strlen(link) + 1;
- struct fuse_req *req;
-
- if (len > FUSE_SYMLINK_MAX)
- return -ENAMETOOLONG;
-
- req = fuse_get_request(fc);
+ struct fuse_req *req = fuse_get_request(fc);
if (!req)
return -EINTR;
@@ -399,6 +460,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
inode->i_nlink = 0;
fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir);
+ fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR)
fuse_invalidate_entry(entry);
return err;
@@ -424,6 +486,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
if (!err) {
entry->d_inode->i_nlink = 0;
fuse_invalidate_attr(dir);
+ fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR)
fuse_invalidate_entry(entry);
return err;
@@ -459,6 +522,10 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
fuse_invalidate_attr(olddir);
if (olddir != newdir)
fuse_invalidate_attr(newdir);
+
+ /* newent will end up negative */
+ if (newent->d_inode)
+ fuse_invalidate_entry_cache(newent);
} else if (err == -EINTR) {
/* If request was interrupted, DEITY only knows if the
rename actually took place. If the invalidation
@@ -566,6 +633,15 @@ static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
return 0;
}
+/*
+ * Check whether the inode attributes are still valid
+ *
+ * If the attribute validity timeout has expired, then fetch the fresh
+ * attributes with a 'getattr' request
+ *
+ * I'm not sure why cached attributes are never returned for the root
+ * inode, this is probably being too cautious.
+ */
static int fuse_revalidate(struct dentry *entry)
{
struct inode *inode = entry->d_inode;
@@ -613,6 +689,19 @@ static int fuse_access(struct inode *inode, int mask)
return err;
}
+/*
+ * Check permission. The two basic access models of FUSE are:
+ *
+ * 1) Local access checking ('default_permissions' mount option) based
+ * on file mode. This is the plain old disk filesystem permission
+ * modell.
+ *
+ * 2) "Remote" access checking, where server is responsible for
+ * checking permission in each inode operation. An exception to this
+ * is if ->permission() was invoked from sys_access() in which case an
+ * access request is sent. Execute permission is still checked
+ * locally based on file mode.
+ */
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -631,14 +720,10 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
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... */
+ /* Note: the opposite of the above test does not
+ exist. So if permissions are revoked this won't be
+ noticed immediately, only after the attribute
+ timeout has expired */
return err;
} else {
@@ -677,13 +762,6 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
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;
@@ -691,7 +769,12 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
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);
+ struct fuse_req *req;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
+ req = fuse_get_request(fc);
if (!req)
return -EINTR;
@@ -702,7 +785,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
}
req->num_pages = 1;
req->pages[0] = page;
- nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
+ fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR);
+ request_send(fc, req);
+ nbytes = req->out.args[0].size;
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err)
@@ -806,6 +891,15 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
}
}
+/*
+ * Set attributes, and at the same time refresh them.
+ *
+ * Truncation is slightly complicated, because the 'truncate' request
+ * may fail, in which case we don't want to touch the mapping.
+ * vmtruncate() doesn't allow for this case. So do the rlimit
+ * checking by hand and call vmtruncate() only after the file has
+ * actually been truncated.
+ */
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
struct inode *inode = entry->d_inode;
@@ -883,23 +977,6 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
return err;
}
-static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
- struct nameidata *nd)
-{
- struct inode *inode;
- int err;
-
- err = fuse_lookup_iget(dir, entry, &inode);
- if (err)
- return ERR_PTR(err);
- if (inode && dir_alias(inode)) {
- iput(inode);
- return ERR_PTR(-EIO);
- }
- d_add(entry, inode);
- return NULL;
-}
-
static int fuse_setxattr(struct dentry *entry, const char *name,
const void *value, size_t size, int flags)
{
@@ -909,9 +986,6 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
struct fuse_setxattr_in inarg;
int err;
- if (size > FUSE_XATTR_SIZE_MAX)
- return -E2BIG;
-
if (fc->no_setxattr)
return -EOPNOTSUPP;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2ca86141d13a..a7ef5e716f3c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -113,6 +113,14 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
return err;
}
+/* Special case for failed iget in CREATE */
+static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+ u64 nodeid = req->in.h.nodeid;
+ fuse_reset_request(req);
+ fuse_send_forget(fc, req, nodeid, 1);
+}
+
void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
u64 nodeid, struct inode *inode, int flags, int isdir)
{
@@ -128,6 +136,8 @@ void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
req->in.args[0].size = sizeof(struct fuse_release_in);
req->in.args[0].value = inarg;
request_send_background(fc, req);
+ if (!inode)
+ req->end = fuse_release_end;
kfree(ff);
}
@@ -163,6 +173,9 @@ static int fuse_flush(struct file *file)
struct fuse_flush_in inarg;
int err;
+ if (is_bad_inode(inode))
+ return -EIO;
+
if (fc->no_flush)
return 0;
@@ -199,6 +212,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
struct fuse_fsync_in inarg;
int err;
+ if (is_bad_inode(inode))
+ return -EIO;
+
if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
return 0;
@@ -234,54 +250,57 @@ 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)
+void fuse_read_fill(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count, int opcode)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
- struct fuse_read_in inarg;
+ struct fuse_read_in *inarg = &req->misc.read_in;
- 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;
+ inarg->fh = ff->fh;
+ inarg->offset = pos;
+ inarg->size = count;
+ req->in.h.opcode = opcode;
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->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)
+static 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);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ request_send(fc, req);
+ return req->out.args[0].size;
}
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;
+ struct fuse_req *req;
+ int err;
+
+ err = -EIO;
+ if (is_bad_inode(inode))
+ goto out;
+
+ err = -EINTR;
+ req = fuse_get_request(fc);
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);
+ fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE);
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err)
@@ -292,21 +311,33 @@ static int fuse_readpage(struct file *file, struct page *page)
return err;
}
-static int fuse_send_readpages(struct fuse_req *req, struct file *file,
- struct inode *inode)
+static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
{
- 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);
+ int i;
+
+ fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */
+
for (i = 0; i < req->num_pages; i++) {
struct page *page = req->pages[i];
if (!req->out.h.error)
SetPageUptodate(page);
+ else
+ SetPageError(page);
unlock_page(page);
}
- return req->out.h.error;
+ fuse_put_request(fc, req);
+}
+
+static void fuse_send_readpages(struct fuse_req *req, struct file *file,
+ struct inode *inode)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ loff_t pos = page_offset(req->pages[0]);
+ size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+ req->out.page_zeroing = 1;
+ req->end = fuse_readpages_end;
+ fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+ request_send_background(fc, req);
}
struct fuse_readpages_data {
@@ -326,12 +357,12 @@ static int fuse_readpages_fill(void *_data, struct page *page)
(req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
(req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
req->pages[req->num_pages - 1]->index + 1 != page->index)) {
- int err = fuse_send_readpages(req, data->file, inode);
- if (err) {
+ fuse_send_readpages(req, data->file, inode);
+ data->req = req = fuse_get_request(fc);
+ if (!req) {
unlock_page(page);
- return err;
+ return -EINTR;
}
- fuse_reset_request(req);
}
req->pages[req->num_pages] = page;
req->num_pages ++;
@@ -345,6 +376,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_readpages_data data;
int err;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
data.file = file;
data.inode = inode;
data.req = fuse_get_request(fc);
@@ -352,10 +387,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
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 */
+ if (!err)
+ fuse_send_readpages(data.req, file, inode);
return err;
}
@@ -402,8 +435,13 @@ static int fuse_commit_write(struct file *file, struct page *page,
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);
+ loff_t pos = page_offset(page) + offset;
+ struct fuse_req *req;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
+ req = fuse_get_request(fc);
if (!req)
return -EINTR;
@@ -454,7 +492,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
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);
+ npages = min(max(npages, 1), 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);
@@ -475,12 +513,16 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
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);
+ struct fuse_req *req;
+
+ if (is_bad_inode(inode))
+ return -EIO;
+
+ 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);
@@ -488,8 +530,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
res = err;
break;
}
- tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
- nbytes = min(nbytes, tmp);
+ nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+ nbytes = min(count, nbytes);
if (write)
nres = fuse_send_write(req, file, inode, pos, nbytes);
else
@@ -535,9 +577,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
struct inode *inode = file->f_dentry->d_inode;
ssize_t res;
/* Don't allow parallel writes to the same file */
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
res = fuse_direct_io(file, buf, count, ppos, 1);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0ea5301f86be..46cf933aa3bf 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -21,6 +21,9 @@
/** If more requests are outstanding, then the operation will block */
#define FUSE_MAX_OUTSTANDING 10
+/** It could be as large as PATH_MAX, but would that have any uses? */
+#define FUSE_NAME_MAX 1024
+
/** 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 */
@@ -91,6 +94,11 @@ struct fuse_out {
/** Header returned from userspace */
struct fuse_out_header h;
+ /*
+ * The following bitfields are not changed during the request
+ * processing
+ */
+
/** Last argument is variable length (can be shorter than
arg->size) */
unsigned argvar:1;
@@ -108,15 +116,23 @@ struct fuse_out {
struct fuse_arg args[3];
};
-struct fuse_req;
+/** The request state */
+enum fuse_req_state {
+ FUSE_REQ_INIT = 0,
+ FUSE_REQ_PENDING,
+ FUSE_REQ_READING,
+ FUSE_REQ_SENT,
+ FUSE_REQ_FINISHED
+};
+
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 */
+ /** This can be on either unused_list, pending processing or
+ io lists in fuse_conn */
struct list_head list;
/** Entry on the background list */
@@ -125,6 +141,12 @@ struct fuse_req {
/** refcount */
atomic_t count;
+ /*
+ * The following bitfields are either set once before the
+ * request is queued or setting/clearing them is protected by
+ * fuse_lock
+ */
+
/** True if the request has reply */
unsigned isreply:1;
@@ -140,11 +162,8 @@ struct fuse_req {
/** 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;
+ /** State of the request */
+ enum fuse_req_state state;
/** The request input */
struct fuse_in in;
@@ -159,7 +178,9 @@ struct fuse_req {
union {
struct fuse_forget_in forget_in;
struct fuse_release_in release_in;
- struct fuse_init_in_out init_in_out;
+ struct fuse_init_in init_in;
+ struct fuse_init_out init_out;
+ struct fuse_read_in read_in;
} misc;
/** page vector */
@@ -179,6 +200,9 @@ struct fuse_req {
/** File used in the request (or NULL) */
struct file *file;
+
+ /** Request completion callback */
+ void (*end)(struct fuse_conn *, struct fuse_req *);
};
/**
@@ -189,9 +213,6 @@ struct fuse_req {
* unmounted.
*/
struct fuse_conn {
- /** Reference count */
- int count;
-
/** The user id for this mount */
uid_t user_id;
@@ -216,6 +237,9 @@ struct fuse_conn {
/** The list of requests being processed */
struct list_head processing;
+ /** The list of requests under I/O */
+ struct list_head io;
+
/** Requests put in the background (RELEASE or any other
interrupted request) */
struct list_head background;
@@ -237,14 +261,22 @@ struct fuse_conn {
u64 reqctr;
/** Mount is active */
- unsigned mounted : 1;
+ unsigned mounted;
- /** Connection established */
- unsigned connected : 1;
+ /** Connection established, cleared on umount, connection
+ abort and device release */
+ unsigned connected;
- /** Connection failed (version mismatch) */
+ /** Connection failed (version mismatch). Cannot race with
+ setting other bitfields since it is only set once in INIT
+ reply, before any other request, and never cleared */
unsigned conn_error : 1;
+ /*
+ * The following bitfields are only for optimization purposes
+ * and hence races in setting them will not cause malfunction
+ */
+
/** Is fsync not implemented by fs? */
unsigned no_fsync : 1;
@@ -272,18 +304,22 @@ struct fuse_conn {
/** Is create not implemented by fs? */
unsigned no_create : 1;
+ /** The number of requests waiting for completion */
+ atomic_t num_waiting;
+
+ /** Negotiated minor version */
+ unsigned minor;
+
/** 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;
-}
+ /** kobject */
+ struct kobject kobj;
+};
static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
{
- return *get_fuse_conn_super_p(sb);
+ return sb->s_fs_info;
}
static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
@@ -291,6 +327,11 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
return get_fuse_conn_super(inode->i_sb);
}
+static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj)
+{
+ return container_of(obj, struct fuse_conn, kobj);
+}
+
static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
{
return container_of(inode, struct fuse_inode, inode);
@@ -332,11 +373,10 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
unsigned long nodeid, u64 nlookup);
/**
- * Send READ or READDIR request
+ * Initialize 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);
+void fuse_read_fill(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count, int opcode);
/**
* Send OPEN or OPENDIR request
@@ -391,12 +431,6 @@ void fuse_init_symlink(struct inode *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);
@@ -452,6 +486,9 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
*/
void fuse_release_background(struct fuse_req *req);
+/* Abort all requests */
+void fuse_abort_conn(struct fuse_conn *fc);
+
/**
* Get the attributes of a file
*/
@@ -461,8 +498,3 @@ 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
index e69a546844d0..c755a0440a66 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -24,6 +24,13 @@ MODULE_LICENSE("GPL");
spinlock_t fuse_lock;
static kmem_cache_t *fuse_inode_cachep;
+static struct subsystem connections_subsys;
+
+struct fuse_conn_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct fuse_conn *, char *);
+ ssize_t (*store)(struct fuse_conn *, const char *, size_t);
+};
#define FUSE_SUPER_MAGIC 0x65735546
@@ -135,12 +142,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
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);
- }
+ } else
+ BUG();
}
static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
@@ -193,6 +196,11 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
return inode;
}
+static void fuse_umount_begin(struct super_block *sb)
+{
+ fuse_abort_conn(get_fuse_conn_super(sb));
+}
+
static void fuse_put_super(struct super_block *sb)
{
struct fuse_conn *fc = get_fuse_conn_super(sb);
@@ -204,20 +212,20 @@ static void fuse_put_super(struct super_block *sb)
spin_lock(&fuse_lock);
fc->mounted = 0;
- fc->user_id = 0;
- fc->group_id = 0;
- fc->flags = 0;
+ fc->connected = 0;
+ spin_unlock(&fuse_lock);
+ up_write(&fc->sbput_sem);
/* Flush all readers on this fs */
wake_up_all(&fc->waitq);
- up_write(&fc->sbput_sem);
- fuse_release_conn(fc);
- spin_unlock(&fuse_lock);
+ kobject_del(&fc->kobj);
+ kobject_put(&fc->kobj);
}
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_frsize = attr->frsize;
stbuf->f_blocks = attr->blocks;
stbuf->f_bfree = attr->bfree;
stbuf->f_bavail = attr->bavail;
@@ -238,10 +246,12 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
if (!req)
return -EINTR;
+ memset(&outarg, 0, sizeof(outarg));
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].size =
+ fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
@@ -357,8 +367,10 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
return 0;
}
-static void free_conn(struct fuse_conn *fc)
+static void fuse_conn_release(struct kobject *kobj)
{
+ struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
+
while (!list_empty(&fc->unused_list)) {
struct fuse_req *req;
req = list_entry(fc->unused_list.next, struct fuse_req, list);
@@ -368,33 +380,28 @@ static void free_conn(struct fuse_conn *fc)
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) {
+ fc = kzalloc(sizeof(*fc), GFP_KERNEL);
+ if (fc) {
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->io);
INIT_LIST_HEAD(&fc->unused_list);
INIT_LIST_HEAD(&fc->background);
- sema_init(&fc->outstanding_sem, 0);
+ sema_init(&fc->outstanding_sem, 1); /* One for INIT */
init_rwsem(&fc->sbput_sem);
+ kobj_set_kset_s(fc, connections_subsys);
+ kobject_init(&fc->kobj);
+ atomic_set(&fc->num_waiting, 0);
for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
struct fuse_req *req = fuse_request_alloc();
if (!req) {
- free_conn(fc);
+ kobject_put(&fc->kobj);
return NULL;
}
list_add(&req->list, &fc->unused_list);
@@ -409,25 +416,32 @@ static struct fuse_conn *new_conn(void)
static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
{
struct fuse_conn *fc;
+ int err;
+ err = -EINVAL;
if (file->f_op != &fuse_dev_operations)
- return ERR_PTR(-EINVAL);
+ goto out_err;
+
+ err = -ENOMEM;
fc = new_conn();
- if (fc == NULL)
- return ERR_PTR(-ENOMEM);
+ if (!fc)
+ goto out_err;
+
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;
- }
+ err = -EINVAL;
+ if (file->private_data)
+ goto out_unlock;
+
+ kobject_get(&fc->kobj);
+ file->private_data = fc;
spin_unlock(&fuse_lock);
return fc;
+
+ out_unlock:
+ spin_unlock(&fuse_lock);
+ kobject_put(&fc->kobj);
+ out_err:
+ return ERR_PTR(err);
}
static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
@@ -446,16 +460,74 @@ static struct super_operations fuse_super_operations = {
.read_inode = fuse_read_inode,
.clear_inode = fuse_clear_inode,
.put_super = fuse_put_super,
+ .umount_begin = fuse_umount_begin,
.statfs = fuse_statfs,
.show_options = fuse_show_options,
};
+static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
+{
+ int i;
+ struct fuse_init_out *arg = &req->misc.init_out;
+
+ if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
+ fc->conn_error = 1;
+ else {
+ fc->minor = arg->minor;
+ fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
+ }
+
+ /* After INIT reply is received other requests can go
+ out. So do (FUSE_MAX_OUTSTANDING - 1) number of
+ up()s on outstanding_sem. The last up() is done in
+ fuse_putback_request() */
+ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
+ up(&fc->outstanding_sem);
+
+ fuse_put_request(fc, req);
+}
+
+static void fuse_send_init(struct fuse_conn *fc)
+{
+ /* This is called from fuse_read_super() so there's guaranteed
+ to be exactly one request available */
+ struct fuse_req *req = fuse_get_request(fc);
+ struct fuse_init_in *arg = &req->misc.init_in;
+
+ arg->major = FUSE_KERNEL_VERSION;
+ 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;
+ /* Variable length arguement used for backward compatibility
+ with interface version < 7.5. Rest of init_out is zeroed
+ by do_get_request(), so a short reply is not a problem */
+ req->out.argvar = 1;
+ req->out.args[0].size = sizeof(struct fuse_init_out);
+ req->out.args[0].value = &req->misc.init_out;
+ req->end = process_init_reply;
+ request_send_background(fc, req);
+}
+
+static unsigned long long conn_id(void)
+{
+ static unsigned long long ctr = 1;
+ unsigned long long val;
+ spin_lock(&fuse_lock);
+ val = ctr++;
+ spin_unlock(&fuse_lock);
+ return val;
+}
+
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;
+ struct dentry *root_dentry;
int err;
if (!parse_fuse_opt((char *) data, &d))
@@ -482,25 +554,43 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
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;
+
+ /* Used by get_root_inode() */
+ sb->s_fs_info = fc;
err = -ENOMEM;
root = get_root_inode(sb, d.rootmode);
- if (root == NULL)
+ if (!root)
goto err;
- sb->s_root = d_alloc_root(root);
- if (!sb->s_root) {
+ root_dentry = d_alloc_root(root);
+ if (!root_dentry) {
iput(root);
goto err;
}
+
+ err = kobject_set_name(&fc->kobj, "%llu", conn_id());
+ if (err)
+ goto err_put_root;
+
+ err = kobject_add(&fc->kobj);
+ if (err)
+ goto err_put_root;
+
+ sb->s_root = root_dentry;
+ spin_lock(&fuse_lock);
+ fc->mounted = 1;
+ fc->connected = 1;
+ spin_unlock(&fuse_lock);
+
fuse_send_init(fc);
+
return 0;
+ err_put_root:
+ dput(root_dentry);
err:
- spin_lock(&fuse_lock);
- fuse_release_conn(fc);
- spin_unlock(&fuse_lock);
+ kobject_put(&fc->kobj);
return err;
}
@@ -518,6 +608,69 @@ static struct file_system_type fuse_fs_type = {
.kill_sb = kill_anon_super,
};
+static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page)
+{
+ return sprintf(page, "%i\n", atomic_read(&fc->num_waiting));
+}
+
+static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page,
+ size_t count)
+{
+ fuse_abort_conn(fc);
+ return count;
+}
+
+static struct fuse_conn_attr fuse_conn_waiting =
+ __ATTR(waiting, 0400, fuse_conn_waiting_show, NULL);
+static struct fuse_conn_attr fuse_conn_abort =
+ __ATTR(abort, 0600, NULL, fuse_conn_abort_store);
+
+static struct attribute *fuse_conn_attrs[] = {
+ &fuse_conn_waiting.attr,
+ &fuse_conn_abort.attr,
+ NULL,
+};
+
+static ssize_t fuse_conn_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *page)
+{
+ struct fuse_conn_attr *fca =
+ container_of(attr, struct fuse_conn_attr, attr);
+
+ if (fca->show)
+ return fca->show(get_fuse_conn_kobj(kobj), page);
+ else
+ return -EACCES;
+}
+
+static ssize_t fuse_conn_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *page, size_t count)
+{
+ struct fuse_conn_attr *fca =
+ container_of(attr, struct fuse_conn_attr, attr);
+
+ if (fca->store)
+ return fca->store(get_fuse_conn_kobj(kobj), page, count);
+ else
+ return -EACCES;
+}
+
+static struct sysfs_ops fuse_conn_sysfs_ops = {
+ .show = &fuse_conn_attr_show,
+ .store = &fuse_conn_attr_store,
+};
+
+static struct kobj_type ktype_fuse_conn = {
+ .release = fuse_conn_release,
+ .sysfs_ops = &fuse_conn_sysfs_ops,
+ .default_attrs = fuse_conn_attrs,
+};
+
+static decl_subsys(fuse, NULL, NULL);
+static decl_subsys(connections, &ktype_fuse_conn, NULL);
+
static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
unsigned long flags)
{
@@ -555,6 +708,34 @@ static void fuse_fs_cleanup(void)
kmem_cache_destroy(fuse_inode_cachep);
}
+static int fuse_sysfs_init(void)
+{
+ int err;
+
+ kset_set_kset_s(&fuse_subsys, fs_subsys);
+ err = subsystem_register(&fuse_subsys);
+ if (err)
+ goto out_err;
+
+ kset_set_kset_s(&connections_subsys, fuse_subsys);
+ err = subsystem_register(&connections_subsys);
+ if (err)
+ goto out_fuse_unregister;
+
+ return 0;
+
+ out_fuse_unregister:
+ subsystem_unregister(&fuse_subsys);
+ out_err:
+ return err;
+}
+
+static void fuse_sysfs_cleanup(void)
+{
+ subsystem_unregister(&connections_subsys);
+ subsystem_unregister(&fuse_subsys);
+}
+
static int __init fuse_init(void)
{
int res;
@@ -571,8 +752,14 @@ static int __init fuse_init(void)
if (res)
goto err_fs_cleanup;
+ res = fuse_sysfs_init();
+ if (res)
+ goto err_dev_cleanup;
+
return 0;
+ err_dev_cleanup:
+ fuse_dev_cleanup();
err_fs_cleanup:
fuse_fs_cleanup();
err:
@@ -583,6 +770,7 @@ static void __exit fuse_exit(void)
{
printk(KERN_DEBUG "fuse exit\n");
+ fuse_sysfs_cleanup();
fuse_fs_cleanup();
fuse_dev_cleanup();
}
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index 89450ae32228..f13f1494d4fe 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
else
e = rec - 1;
} while (b <= e);
- //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
if (rec != e && e >= 0) {
len = hfs_brec_lenoff(bnode, e, &off);
keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
return res;
invalid:
- printk("HFS: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+ printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
height, bnode->height, bnode->type, nidx, parent);
res = -EIO;
release:
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 3d5cdc6847c0..a7a7d77f3fd3 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -198,7 +198,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
// move down?
if (!node->prev && !node->next) {
- printk("hfs_btree_del_level\n");
+ printk(KERN_DEBUG "hfs_btree_del_level\n");
}
if (!node->parent) {
tree->root = 0;
@@ -219,7 +219,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
struct hfs_bnode *node;
if (cnid >= tree->node_count) {
- printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+ printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
return NULL;
}
@@ -242,7 +242,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
loff_t off;
if (cnid >= tree->node_count) {
- printk("HFS: request for non-existent node %d in B*Tree\n", cnid);
+ printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
return NULL;
}
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 7d8fff2c25fc..5c87cf4801fc 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -362,7 +362,7 @@ again:
end_off = hfs_bnode_read_u16(parent, end_rec_off);
if (end_rec_off - end_off < diff) {
- printk("splitting index node...\n");
+ printk(KERN_DEBUG "hfs: splitting index node...\n");
fd->bnode = parent;
new_node = hfs_bnode_split(fd);
if (IS_ERR(new_node))
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 394725efa1c8..7bb11edd1488 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -111,7 +111,7 @@ void hfs_btree_close(struct hfs_btree *tree)
while ((node = tree->node_hash[i])) {
tree->node_hash[i] = node->next_hash;
if (atomic_read(&node->refcnt))
- printk("HFS: node %d:%d still has %d user(s)!\n",
+ printk(KERN_ERR "hfs: node %d:%d still has %d user(s)!\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
hfs_bnode_free(node);
tree->node_hash_cnt--;
@@ -252,7 +252,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
kunmap(*pagep);
nidx = node->next;
if (!nidx) {
- printk("create new bmap node...\n");
+ printk(KERN_DEBUG "hfs: create new bmap node...\n");
next_node = hfs_bmap_new_bmap(node, idx);
} else
next_node = hfs_bnode_find(tree, nidx);
@@ -292,7 +292,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
hfs_bnode_put(node);
if (!i) {
/* panic */;
- printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+ printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
return;
}
node = hfs_bnode_find(tree, i);
@@ -300,7 +300,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
return;
if (node->type != HFS_NODE_MAP) {
/* panic */;
- printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+ printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
hfs_bnode_put(node);
return;
}
@@ -313,7 +313,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
m = 1 << (~nidx & 7);
byte = data[off];
if (!(byte & m)) {
- printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+ printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
kunmap(page);
hfs_bnode_put(node);
return;
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 2fcd679f0238..ba851576ebb1 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -184,7 +184,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
type = rec.type;
if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
- printk("HFS-fs: Found bad thread record in catalog\n");
+ printk(KERN_ERR "hfs: found bad thread record in catalog\n");
return -EIO;
}
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index e1f24befba58..534e5a7480ef 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -81,12 +81,12 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
case 1:
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
if (entry.type != HFS_CDR_THD) {
- printk("HFS: bad catalog folder thread\n");
+ printk(KERN_ERR "hfs: bad catalog folder thread\n");
err = -EIO;
goto out;
}
//if (fd.entrylength < HFS_MIN_THREAD_SZ) {
- // printk("HFS: truncated catalog thread\n");
+ // printk(KERN_ERR "hfs: truncated catalog thread\n");
// err = -EIO;
// goto out;
//}
@@ -105,7 +105,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
for (;;) {
if (be32_to_cpu(fd.key->cat.ParID) != inode->i_ino) {
- printk("HFS: walked past end of dir\n");
+ printk(KERN_ERR "hfs: walked past end of dir\n");
err = -EIO;
goto out;
}
@@ -114,7 +114,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
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");
+ printk(KERN_ERR "hfs: small dir entry\n");
err = -EIO;
goto out;
}
@@ -123,7 +123,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break;
} else if (type == HFS_CDR_FIL) {
if (fd.entrylength < sizeof(struct hfs_cat_file)) {
- printk("HFS: small file entry\n");
+ printk(KERN_ERR "hfs: small file entry\n");
err = -EIO;
goto out;
}
@@ -131,7 +131,7 @@ static int hfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
be32_to_cpu(entry.file.FlNum), DT_REG))
break;
} else {
- printk("HFS: bad catalog entry type %d\n", type);
+ printk(KERN_ERR "hfs: bad catalog entry type %d\n", type);
err = -EIO;
goto out;
}
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index cc5dcd52e23d..18ce47ab1b71 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -35,9 +35,6 @@
#define dprint(flg, fmt, args...) \
if (flg & DBG_MASK) printk(fmt , ## args)
-#define hfs_warn(format, args...) printk(KERN_WARNING format , ## args)
-#define hfs_error(format, args...) printk(KERN_ERR format , ## args)
-
/*
* struct hfs_inode_info
*
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index d499393a8ae7..39fd85b9b916 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -95,7 +95,6 @@ static int hfs_releasepage(struct page *page, gfp_t mask)
} while (--i && nidx < tree->node_count);
spin_unlock(&tree->hash_lock);
}
- //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
return res ? try_to_free_buffers(page) : 0;
}
@@ -547,13 +546,13 @@ static int hfs_file_release(struct inode *inode, struct file *file)
if (atomic_read(&file->f_count) != 0)
return 0;
if (atomic_dec_and_test(&HFS_I(inode)->opencnt)) {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
hfs_file_truncate(inode);
//if (inode->i_flags & S_DEAD) {
// hfs_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
// hfs_delete_inode(inode);
//}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
return 0;
}
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index 0a473f79c89f..b4651e128d7f 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -47,7 +47,7 @@ static int hfs_get_last_session(struct super_block *sb,
*start = (sector_t)te.cdte_addr.lba << 2;
return 0;
}
- printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+ printk(KERN_ERR "hfs: invalid session number or type of track\n");
return -EINVAL;
}
ms_info.addr_format = CDROM_LBA;
@@ -100,7 +100,7 @@ int hfs_mdb_get(struct super_block *sb)
HFS_SB(sb)->alloc_blksz = size = be32_to_cpu(mdb->drAlBlkSiz);
if (!size || (size & (HFS_SECTOR_SIZE - 1))) {
- hfs_warn("hfs_fs: bad allocation block size %d\n", size);
+ printk(KERN_ERR "hfs: bad allocation block size %d\n", size);
goto out_bh;
}
@@ -117,7 +117,7 @@ int hfs_mdb_get(struct super_block *sb)
size >>= 1;
brelse(bh);
if (!sb_set_blocksize(sb, size)) {
- printk("hfs_fs: unable to set blocksize to %u\n", size);
+ printk(KERN_ERR "hfs: unable to set blocksize to %u\n", size);
goto out;
}
@@ -161,8 +161,8 @@ int hfs_mdb_get(struct super_block *sb)
}
if (!HFS_SB(sb)->alt_mdb) {
- hfs_warn("hfs_fs: unable to locate alternate MDB\n");
- hfs_warn("hfs_fs: continuing without an alternate MDB\n");
+ printk(KERN_WARNING "hfs: unable to locate alternate MDB\n");
+ printk(KERN_WARNING "hfs: continuing without an alternate MDB\n");
}
HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
@@ -177,7 +177,7 @@ int hfs_mdb_get(struct super_block *sb)
while (size) {
bh = sb_bread(sb, off >> sb->s_blocksize_bits);
if (!bh) {
- hfs_warn("hfs_fs: unable to read volume bitmap\n");
+ printk(KERN_ERR "hfs: unable to read volume bitmap\n");
goto out;
}
off2 = off & (sb->s_blocksize - 1);
@@ -191,23 +191,23 @@ int hfs_mdb_get(struct super_block *sb)
HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp);
if (!HFS_SB(sb)->ext_tree) {
- hfs_warn("hfs_fs: unable to open extent tree\n");
+ printk(KERN_ERR "hfs: unable to open extent tree\n");
goto out;
}
HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp);
if (!HFS_SB(sb)->cat_tree) {
- hfs_warn("hfs_fs: unable to open catalog tree\n");
+ printk(KERN_ERR "hfs: unable to open catalog tree\n");
goto out;
}
attrib = mdb->drAtrb;
if (!(attrib & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
- hfs_warn("HFS-fs warning: Filesystem was not cleanly unmounted, "
+ printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
"running fsck.hfs is recommended. mounting read-only.\n");
sb->s_flags |= MS_RDONLY;
}
if ((attrib & cpu_to_be16(HFS_SB_ATTRIB_SLOCK))) {
- hfs_warn("HFS-fs: Filesystem is marked locked, mounting read-only.\n");
+ printk(KERN_WARNING "hfs: filesystem is marked locked, mounting read-only.\n");
sb->s_flags |= MS_RDONLY;
}
if (!(sb->s_flags & MS_RDONLY)) {
@@ -303,7 +303,7 @@ void hfs_mdb_commit(struct super_block *sb)
while (size) {
bh = sb_bread(sb, block);
if (!bh) {
- hfs_warn("hfs_fs: unable to read volume bitmap\n");
+ printk(KERN_ERR "hfs: unable to read volume bitmap\n");
break;
}
len = min((int)sb->s_blocksize - off, size);
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index c5074aeafcae..1181d116117d 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -101,12 +101,12 @@ static int hfs_remount(struct super_block *sb, int *flags, char *data)
return 0;
if (!(*flags & MS_RDONLY)) {
if (!(HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_UNMNT))) {
- printk("HFS-fs warning: Filesystem was not cleanly unmounted, "
+ printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
"running fsck.hfs is recommended. leaving read-only.\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
} else if (HFS_SB(sb)->mdb->drAtrb & cpu_to_be16(HFS_SB_ATTRIB_SLOCK)) {
- printk("HFS-fs: Filesystem is marked locked, leaving read-only.\n");
+ printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
}
@@ -229,21 +229,21 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
switch (token) {
case opt_uid:
if (match_int(&args[0], &tmp)) {
- printk("HFS: uid requires an argument\n");
+ printk(KERN_ERR "hfs: uid requires an argument\n");
return 0;
}
hsb->s_uid = (uid_t)tmp;
break;
case opt_gid:
if (match_int(&args[0], &tmp)) {
- printk("HFS: gid requires an argument\n");
+ printk(KERN_ERR "hfs: gid requires an argument\n");
return 0;
}
hsb->s_gid = (gid_t)tmp;
break;
case opt_umask:
if (match_octal(&args[0], &tmp)) {
- printk("HFS: umask requires a value\n");
+ printk(KERN_ERR "hfs: umask requires a value\n");
return 0;
}
hsb->s_file_umask = (umode_t)tmp;
@@ -251,39 +251,39 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
break;
case opt_file_umask:
if (match_octal(&args[0], &tmp)) {
- printk("HFS: file_umask requires a value\n");
+ printk(KERN_ERR "hfs: file_umask requires a value\n");
return 0;
}
hsb->s_file_umask = (umode_t)tmp;
break;
case opt_dir_umask:
if (match_octal(&args[0], &tmp)) {
- printk("HFS: dir_umask requires a value\n");
+ printk(KERN_ERR "hfs: dir_umask requires a value\n");
return 0;
}
hsb->s_dir_umask = (umode_t)tmp;
break;
case opt_part:
if (match_int(&args[0], &hsb->part)) {
- printk("HFS: part requires an argument\n");
+ printk(KERN_ERR "hfs: part requires an argument\n");
return 0;
}
break;
case opt_session:
if (match_int(&args[0], &hsb->session)) {
- printk("HFS: session requires an argument\n");
+ printk(KERN_ERR "hfs: session requires an argument\n");
return 0;
}
break;
case opt_type:
if (match_fourchar(&args[0], &hsb->s_type)) {
- printk("HFS+-fs: type requires a 4 character value\n");
+ printk(KERN_ERR "hfs: type requires a 4 character value\n");
return 0;
}
break;
case opt_creator:
if (match_fourchar(&args[0], &hsb->s_creator)) {
- printk("HFS+-fs: creator requires a 4 character value\n");
+ printk(KERN_ERR "hfs: creator requires a 4 character value\n");
return 0;
}
break;
@@ -292,13 +292,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
break;
case opt_codepage:
if (hsb->nls_disk) {
- printk("HFS+-fs: unable to change codepage\n");
+ printk(KERN_ERR "hfs: 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);
+ printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p);
kfree(p);
return 0;
}
@@ -306,13 +306,13 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
break;
case opt_iocharset:
if (hsb->nls_io) {
- printk("HFS: unable to change iocharset\n");
+ printk(KERN_ERR "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);
+ printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p);
kfree(p);
return 0;
}
@@ -326,7 +326,7 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
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");
+ printk(KERN_ERR "hfs: unable to load default iocharset\n");
return 0;
}
}
@@ -364,7 +364,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
res = -EINVAL;
if (!parse_options((char *)data, sbi)) {
- hfs_warn("hfs_fs: unable to parse mount options.\n");
+ printk(KERN_ERR "hfs: unable to parse mount options.\n");
goto bail;
}
@@ -375,7 +375,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
res = hfs_mdb_get(sb);
if (res) {
if (!silent)
- hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n",
+ printk(KERN_WARNING "hfs: can't find a HFS filesystem on dev %s.\n",
hfs_mdb_name(sb));
res = -EINVAL;
goto bail;
@@ -407,7 +407,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
bail_iput:
iput(root_inode);
bail_no_root:
- hfs_warn("hfs_fs: get root inode failed.\n");
+ printk(KERN_ERR "hfs: get root inode failed.\n");
bail:
hfs_mdb_put(sb);
return res;
@@ -454,7 +454,7 @@ static void __exit exit_hfs_fs(void)
{
unregister_filesystem(&hfs_fs_type);
if (kmem_cache_destroy(hfs_inode_cachep))
- printk(KERN_INFO "hfs_inode_cache: not all structures were freed\n");
+ printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n");
}
module_init(init_hfs_fs)
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 257cdde0514b..5007a41f1be9 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -64,7 +64,6 @@ int __hfs_brec_find(struct hfs_bnode *bnode, struct hfs_find_data *fd)
else
e = rec - 1;
} while (b <= e);
- //printk("%d: %d,%d,%d\n", bnode->this, b, e, rec);
if (rec != e && e >= 0) {
len = hfs_brec_lenoff(bnode, e, &off);
keylen = hfs_brec_keylen(bnode, e);
@@ -127,7 +126,7 @@ int hfs_brec_find(struct hfs_find_data *fd)
return res;
invalid:
- printk("HFS+-fs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
+ printk(KERN_ERR "hfs: inconsistency in B*Tree (%d,%d,%d,%u,%u)\n",
height, bnode->height, bnode->type, nidx, parent);
res = -EIO;
release:
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index c7d316455fa0..9fb51632303c 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -29,7 +29,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
return size;
dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
- down(&HFSPLUS_SB(sb).alloc_file->i_sem);
+ mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
(filler_t *)mapping->a_ops->readpage, NULL);
@@ -143,7 +143,7 @@ done:
sb->s_dirt = 1;
dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
out:
- up(&HFSPLUS_SB(sb).alloc_file->i_sem);
+ mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
return start;
}
@@ -164,7 +164,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
if ((offset + count) > HFSPLUS_SB(sb).total_blocks)
return -2;
- down(&HFSPLUS_SB(sb).alloc_file->i_sem);
+ mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
pnr = offset / PAGE_CACHE_BITS;
page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL);
@@ -215,7 +215,7 @@ out:
kunmap(page);
HFSPLUS_SB(sb).free_blocks += len;
sb->s_dirt = 1;
- up(&HFSPLUS_SB(sb).alloc_file->i_sem);
+ mutex_unlock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
return 0;
}
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 930cd9212de8..8f07e8fbd03d 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -358,7 +358,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
// move down?
if (!node->prev && !node->next) {
- printk("hfs_btree_del_level\n");
+ printk(KERN_DEBUG "hfs_btree_del_level\n");
}
if (!node->parent) {
tree->root = 0;
@@ -379,7 +379,7 @@ struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
struct hfs_bnode *node;
if (cnid >= tree->node_count) {
- printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+ printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
return NULL;
}
@@ -402,7 +402,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
loff_t off;
if (cnid >= tree->node_count) {
- printk("HFS+-fs: request for non-existent node %d in B*Tree\n", cnid);
+ printk(KERN_ERR "hfs: request for non-existent node %d in B*Tree\n", cnid);
return NULL;
}
@@ -576,8 +576,9 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
node = hfs_bnode_findhash(tree, num);
spin_unlock(&tree->hash_lock);
if (node) {
- printk("new node %u already hashed?\n", num);
- BUG();
+ printk(KERN_CRIT "new node %u already hashed?\n", num);
+ WARN_ON(1);
+ return node;
}
node = __hfs_bnode_create(tree, num);
if (!node)
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 0ccef2ab790c..c88e5d72a402 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -360,7 +360,7 @@ again:
end_off = hfs_bnode_read_u16(parent, end_rec_off);
if (end_rec_off - end_off < diff) {
- printk("splitting index node...\n");
+ printk(KERN_DEBUG "hfs: splitting index node...\n");
fd->bnode = parent;
new_node = hfs_bnode_split(fd);
if (IS_ERR(new_node))
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index 44326aa2bd34..a67edfa34e9e 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -31,17 +31,8 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
init_MUTEX(&tree->tree_lock);
spin_lock_init(&tree->hash_lock);
- /* Set the correct compare function */
tree->sb = sb;
tree->cnid = id;
- if (id == HFSPLUS_EXT_CNID) {
- tree->keycmp = hfsplus_ext_cmp_key;
- } else if (id == HFSPLUS_CAT_CNID) {
- tree->keycmp = hfsplus_cat_cmp_key;
- } else {
- printk("HFS+-fs: unknown B*Tree requested\n");
- goto free_tree;
- }
tree->inode = iget(sb, id);
if (!tree->inode)
goto free_tree;
@@ -64,6 +55,20 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
tree->max_key_len = be16_to_cpu(head->max_key_len);
tree->depth = be16_to_cpu(head->depth);
+ /* Set the correct compare function */
+ if (id == HFSPLUS_EXT_CNID) {
+ tree->keycmp = hfsplus_ext_cmp_key;
+ } else if (id == HFSPLUS_CAT_CNID) {
+ if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) &&
+ (head->key_type == HFSPLUS_KEY_BINARY))
+ tree->keycmp = hfsplus_cat_bin_cmp_key;
+ else
+ tree->keycmp = hfsplus_cat_case_cmp_key;
+ } else {
+ printk(KERN_ERR "hfs: unknown B*Tree requested\n");
+ goto fail_page;
+ }
+
size = tree->node_size;
if (!size || size & (size - 1))
goto fail_page;
@@ -99,7 +104,7 @@ void hfs_btree_close(struct hfs_btree *tree)
while ((node = tree->node_hash[i])) {
tree->node_hash[i] = node->next_hash;
if (atomic_read(&node->refcnt))
- printk("HFS+: node %d:%d still has %d user(s)!\n",
+ printk(KERN_CRIT "hfs: node %d:%d still has %d user(s)!\n",
node->tree->cnid, node->this, atomic_read(&node->refcnt));
hfs_bnode_free(node);
tree->node_hash_cnt--;
@@ -223,10 +228,6 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
tree->free_nodes--;
mark_inode_dirty(tree->inode);
hfs_bnode_put(node);
- if (!idx) {
- printk("unexpected idx %u (%u)\n", idx, node->this);
- BUG();
- }
return hfs_bnode_create(tree, idx);
}
}
@@ -242,7 +243,7 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
kunmap(*pagep);
nidx = node->next;
if (!nidx) {
- printk("create new bmap node...\n");
+ printk(KERN_DEBUG "hfs: create new bmap node...\n");
next_node = hfs_bmap_new_bmap(node, idx);
} else
next_node = hfs_bnode_find(tree, nidx);
@@ -284,7 +285,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
hfs_bnode_put(node);
if (!i) {
/* panic */;
- printk("HFS: unable to free bnode %u. bmap not found!\n", node->this);
+ printk(KERN_CRIT "hfs: unable to free bnode %u. bmap not found!\n", node->this);
return;
}
node = hfs_bnode_find(tree, i);
@@ -292,7 +293,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
return;
if (node->type != HFS_NODE_MAP) {
/* panic */;
- printk("HFS: invalid bmap found! (%u,%d)\n", node->this, node->type);
+ printk(KERN_CRIT "hfs: invalid bmap found! (%u,%d)\n", node->this, node->type);
hfs_bnode_put(node);
return;
}
@@ -305,7 +306,7 @@ void hfs_bmap_free(struct hfs_bnode *node)
m = 1 << (~nidx & 7);
byte = data[off];
if (!(byte & m)) {
- printk("HFS: trying to free free bnode %u(%d)\n", node->this, node->type);
+ printk(KERN_CRIT "hfs: trying to free free bnode %u(%d)\n", node->this, node->type);
kunmap(page);
hfs_bnode_put(node);
return;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 94712790c8b3..f2d7c49ce759 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -13,7 +13,8 @@
#include "hfsplus_fs.h"
#include "hfsplus_raw.h"
-int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
{
__be32 k1p, k2p;
@@ -22,7 +23,20 @@ int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
if (k1p != k2p)
return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
- return hfsplus_unistrcmp(&k1->cat.name, &k2->cat.name);
+ return hfsplus_strcasecmp(&k1->cat.name, &k2->cat.name);
+}
+
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
+{
+ __be32 k1p, k2p;
+
+ k1p = k1->cat.parent;
+ k2p = k2->cat.parent;
+ if (k1p != k2p)
+ return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
+
+ return hfsplus_strcmp(&k1->cat.name, &k2->cat.name);
}
void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
@@ -80,8 +94,11 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
memset(folder, 0, sizeof(*folder));
folder->type = cpu_to_be16(HFSPLUS_FOLDER);
folder->id = cpu_to_be32(inode->i_ino);
- folder->create_date = folder->content_mod_date =
- folder->attribute_mod_date = folder->access_date = hfsp_now2mt();
+ HFSPLUS_I(inode).create_date =
+ folder->create_date =
+ folder->content_mod_date =
+ folder->attribute_mod_date =
+ folder->access_date = hfsp_now2mt();
hfsplus_set_perms(inode, &folder->permissions);
if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
/* invisible and namelocked */
@@ -95,18 +112,27 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry, u32 cnid, struct i
file->type = cpu_to_be16(HFSPLUS_FILE);
file->flags = cpu_to_be16(HFSPLUS_FILE_THREAD_EXISTS);
file->id = cpu_to_be32(cnid);
- file->create_date = file->content_mod_date =
- file->attribute_mod_date = file->access_date = hfsp_now2mt();
+ HFSPLUS_I(inode).create_date =
+ file->create_date =
+ file->content_mod_date =
+ file->attribute_mod_date =
+ file->access_date = hfsp_now2mt();
if (cnid == inode->i_ino) {
hfsplus_set_perms(inode, &file->permissions);
- file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
- file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+ if (S_ISLNK(inode->i_mode)) {
+ file->user_info.fdType = cpu_to_be32(HFSP_SYMLINK_TYPE);
+ file->user_info.fdCreator = cpu_to_be32(HFSP_SYMLINK_CREATOR);
+ } else {
+ file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
+ file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+ }
if ((file->permissions.rootflags | file->permissions.userflags) & HFSPLUS_FLG_IMMUTABLE)
file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
} else {
file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
file->user_info.fdFlags = cpu_to_be16(0x100);
+ file->create_date = HFSPLUS_I(HFSPLUS_SB(inode->i_sb).hidden_dir).create_date;
file->permissions.dev = cpu_to_be32(HFSPLUS_I(inode).dev);
}
return sizeof(*file);
@@ -139,7 +165,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
type = be16_to_cpu(tmp.type);
if (type != HFSPLUS_FOLDER_THREAD && type != HFSPLUS_FILE_THREAD) {
- printk("HFS+-fs: Found bad thread record in catalog\n");
+ printk(KERN_ERR "hfs: found bad thread record in catalog\n");
return -EIO;
}
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 50c8f44b6c66..01a6fe3a395c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -66,25 +66,32 @@ again:
}
cnid = be32_to_cpu(entry.file.id);
if (entry.file.user_info.fdType == cpu_to_be32(HFSP_HARDLINK_TYPE) &&
- entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR)) {
+ entry.file.user_info.fdCreator == cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+ (entry.file.create_date == HFSPLUS_I(HFSPLUS_SB(sb).hidden_dir).create_date ||
+ entry.file.create_date == HFSPLUS_I(sb->s_root->d_inode).create_date) &&
+ HFSPLUS_SB(sb).hidden_dir) {
struct qstr str;
char name[32];
if (dentry->d_fsdata) {
- err = -ENOENT;
- inode = NULL;
- goto out;
+ /*
+ * We found a link pointing to another link,
+ * so ignore it and treat it as regular file.
+ */
+ cnid = (unsigned long)dentry->d_fsdata;
+ linkid = 0;
+ } else {
+ dentry->d_fsdata = (void *)(unsigned long)cnid;
+ linkid = be32_to_cpu(entry.file.permissions.dev);
+ str.len = sprintf(name, "iNode%d", linkid);
+ str.name = name;
+ hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
+ goto again;
}
- dentry->d_fsdata = (void *)(unsigned long)cnid;
- linkid = be32_to_cpu(entry.file.permissions.dev);
- str.len = sprintf(name, "iNode%d", linkid);
- str.name = name;
- hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_SB(sb).hidden_dir->i_ino, &str);
- goto again;
} else if (!dentry->d_fsdata)
dentry->d_fsdata = (void *)(unsigned long)cnid;
} else {
- printk("HFS+-fs: Illegal catalog entry type in lookup\n");
+ printk(KERN_ERR "hfs: invalid catalog entry type in lookup\n");
err = -EIO;
goto fail;
}
@@ -132,12 +139,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
case 1:
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
- printk("HFS+-fs: bad catalog folder thread\n");
+ printk(KERN_ERR "hfs: bad catalog folder thread\n");
err = -EIO;
goto out;
}
if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
- printk("HFS+-fs: truncated catalog thread\n");
+ printk(KERN_ERR "hfs: truncated catalog thread\n");
err = -EIO;
goto out;
}
@@ -156,7 +163,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
for (;;) {
if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
- printk("HFS+-fs: walked past end of dir\n");
+ printk(KERN_ERR "hfs: walked past end of dir\n");
err = -EIO;
goto out;
}
@@ -168,7 +175,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto out;
if (type == HFSPLUS_FOLDER) {
if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
- printk("HFS+-fs: small dir entry\n");
+ printk(KERN_ERR "hfs: small dir entry\n");
err = -EIO;
goto out;
}
@@ -180,7 +187,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
break;
} else if (type == HFSPLUS_FILE) {
if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
- printk("HFS+-fs: small file entry\n");
+ printk(KERN_ERR "hfs: small file entry\n");
err = -EIO;
goto out;
}
@@ -188,7 +195,7 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
be32_to_cpu(entry.file.id), DT_REG))
break;
} else {
- printk("HFS+-fs: bad catalog entry type\n");
+ printk(KERN_ERR "hfs: bad catalog entry type\n");
err = -EIO;
goto out;
}
@@ -330,7 +337,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
if (res)
return res;
- inode->i_nlink--;
+ if (inode->i_nlink > 0)
+ inode->i_nlink--;
hfsplus_delete_inode(inode);
if (inode->i_ino != cnid && !inode->i_nlink) {
if (!atomic_read(&HFSPLUS_I(inode).opencnt)) {
@@ -339,7 +347,8 @@ static int hfsplus_unlink(struct inode *dir, struct dentry *dentry)
hfsplus_delete_inode(inode);
} else
inode->i_flags |= S_DEAD;
- }
+ } else
+ inode->i_nlink = 0;
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index e3ff56a03011..1a7480089e82 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -16,7 +16,8 @@
#include "hfsplus_raw.h"
/* Compare two extents keys, returns 0 on same, pos/neg for difference */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *k1,
+ const hfsplus_btree_key *k2)
{
__be32 k1id, k2id;
__be32 k1s, k2s;
@@ -349,10 +350,9 @@ int hfsplus_file_extend(struct inode *inode)
if (HFSPLUS_SB(sb).alloc_file->i_size * 8 < HFSPLUS_SB(sb).total_blocks - HFSPLUS_SB(sb).free_blocks + 8) {
// extend alloc file
- printk("extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
+ printk(KERN_ERR "hfs: extend alloc file! (%Lu,%u,%u)\n", HFSPLUS_SB(sb).alloc_file->i_size * 8,
HFSPLUS_SB(sb).total_blocks, HFSPLUS_SB(sb).free_blocks);
return -ENOSPC;
- //BUG();
}
down(&HFSPLUS_I(inode).extents_lock);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index df16fcbff3fb..7ae393637a0c 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -36,7 +36,7 @@
#define HFSPLUS_TYPE_DATA 0x00
#define HFSPLUS_TYPE_RSRC 0xFF
-typedef int (*btree_keycmp)(hfsplus_btree_key *, hfsplus_btree_key *);
+typedef int (*btree_keycmp)(const hfsplus_btree_key *, const hfsplus_btree_key *);
#define NODE_HASH_SIZE 256
@@ -143,15 +143,13 @@ struct hfsplus_sb_info {
unsigned long flags;
- atomic_t inode_cnt;
- u32 last_inode_cnt;
-
struct hlist_head rsrc_inodes;
};
#define HFSPLUS_SB_WRITEBACKUP 0x0001
#define HFSPLUS_SB_NODECOMPOSE 0x0002
#define HFSPLUS_SB_FORCE 0x0004
+#define HFSPLUS_SB_HFSX 0x0008
struct hfsplus_inode_info {
@@ -168,6 +166,7 @@ struct hfsplus_inode_info {
struct inode *rsrc_inode;
unsigned long flags;
+ __be32 create_date;
/* Device number in hfsplus_permissions in catalog */
u32 dev;
/* BSD system and user file flags */
@@ -306,7 +305,8 @@ int hfs_brec_read(struct hfs_find_data *, void *, int);
int hfs_brec_goto(struct hfs_find_data *, int);
/* catalog.c */
-int hfsplus_cat_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
+int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
void hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *, u32, struct qstr *);
int hfsplus_find_cat(struct super_block *, u32, struct hfs_find_data *);
int hfsplus_create_cat(u32, struct inode *, struct qstr *, struct inode *);
@@ -315,7 +315,7 @@ int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
struct inode *, struct qstr *);
/* extents.c */
-int hfsplus_ext_cmp_key(hfsplus_btree_key *, hfsplus_btree_key *);
+int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
void hfsplus_ext_write_extent(struct inode *);
int hfsplus_get_block(struct inode *, sector_t, struct buffer_head *, int);
int hfsplus_free_fork(struct super_block *, u32, struct hfsplus_fork_raw *, int);
@@ -353,7 +353,8 @@ extern u16 hfsplus_decompose_table[];
extern u16 hfsplus_compose_table[];
/* unicode.c */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
+int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *);
int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index b4fbed633219..49205531a500 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -22,8 +22,10 @@
#define HFSPLUS_SECTOR_SHIFT 9
#define HFSPLUS_VOLHEAD_SECTOR 2
#define HFSPLUS_VOLHEAD_SIG 0x482b
+#define HFSPLUS_VOLHEAD_SIGX 0x4858
#define HFSPLUS_SUPER_MAGIC 0x482b
-#define HFSPLUS_CURRENT_VERSION 4
+#define HFSPLUS_MIN_VERSION 4
+#define HFSPLUS_CURRENT_VERSION 5
#define HFSP_WRAP_MAGIC 0x4244
#define HFSP_WRAP_ATTRIB_SLOCK 0x8000
@@ -41,6 +43,9 @@
#define HFSP_HARDLINK_TYPE 0x686c6e6b /* 'hlnk' */
#define HFSP_HFSPLUS_CREATOR 0x6866732b /* 'hfs+' */
+#define HFSP_SYMLINK_TYPE 0x736c6e6b /* 'slnk' */
+#define HFSP_SYMLINK_CREATOR 0x72686170 /* 'rhap' */
+
#define HFSP_MOUNT_VERSION 0x482b4c78 /* 'H+Lx' */
/* Structures used on disk */
@@ -161,7 +166,7 @@ struct hfs_btree_header_rec {
u16 reserved1;
__be32 clump_size;
u8 btree_type;
- u8 reserved2;
+ u8 key_type;
__be32 attributes;
u32 reserved3[16];
} __packed;
@@ -186,6 +191,10 @@ struct hfs_btree_header_rec {
#define HFSPLUS_EXCH_CNID 15 /* ExchangeFiles temp id */
#define HFSPLUS_FIRSTUSER_CNID 16 /* first available user id */
+/* btree key type */
+#define HFSPLUS_KEY_CASEFOLDING 0xCF /* case-insensitive */
+#define HFSPLUS_KEY_BINARY 0xBC /* case-sensitive */
+
/* HFS+ catalog entry key */
struct hfsplus_cat_key {
__be16 key_len;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index fc98583cf045..12ed2b7d046b 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -18,13 +18,11 @@
static int hfsplus_readpage(struct file *file, struct page *page)
{
- //printk("readpage: %lu\n", page->index);
return block_read_full_page(page, hfsplus_get_block);
}
static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
{
- //printk("writepage: %lu\n", page->index);
return block_write_full_page(page, hfsplus_get_block, wbc);
}
@@ -92,7 +90,6 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)
} while (--i && nidx < tree->node_count);
spin_unlock(&tree->hash_lock);
}
- //printk("releasepage: %lu,%x = %d\n", page->index, mask, res);
return res ? try_to_free_buffers(page) : 0;
}
@@ -182,11 +179,6 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dent
igrab(dir);
hlist_add_head(&inode->i_hash, &HFSPLUS_SB(sb).rsrc_inodes);
mark_inode_dirty(inode);
- {
- void hfsplus_inode_check(struct super_block *sb);
- atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
- hfsplus_inode_check(sb);
- }
out:
d_add(dentry, inode);
return NULL;
@@ -276,13 +268,13 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
if (atomic_read(&file->f_count) != 0)
return 0;
if (atomic_dec_and_test(&HFSPLUS_I(inode).opencnt)) {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
hfsplus_file_truncate(inode);
if (inode->i_flags & S_DEAD) {
hfsplus_delete_cat(inode->i_ino, HFSPLUS_SB(sb).hidden_dir, NULL);
hfsplus_delete_inode(inode);
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
return 0;
}
@@ -317,11 +309,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
if (!inode)
return NULL;
- {
- void hfsplus_inode_check(struct super_block *sb);
- atomic_inc(&HFSPLUS_SB(sb).inode_cnt);
- hfsplus_inode_check(sb);
- }
inode->i_ino = HFSPLUS_SB(sb).next_cnid++;
inode->i_mode = mode;
inode->i_uid = current->fsuid;
@@ -444,7 +431,8 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
inode->i_size = 2 + be32_to_cpu(folder->valence);
inode->i_atime = hfsp_mt2ut(folder->access_date);
inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
- inode->i_ctime = inode->i_mtime;
+ inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
+ HFSPLUS_I(inode).create_date = folder->create_date;
HFSPLUS_I(inode).fs_blocks = 0;
inode->i_op = &hfsplus_dir_inode_operations;
inode->i_fop = &hfsplus_dir_operations;
@@ -475,9 +463,10 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
}
inode->i_atime = hfsp_mt2ut(file->access_date);
inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
- inode->i_ctime = inode->i_mtime;
+ inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
+ HFSPLUS_I(inode).create_date = file->create_date;
} else {
- printk("HFS+-fs: bad catalog entry used to create inode\n");
+ printk(KERN_ERR "hfs: bad catalog entry used to create inode\n");
res = -EIO;
}
return res;
diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
index e07aa096e07c..13cf848ac833 100644
--- a/fs/hfsplus/ioctl.c
+++ b/fs/hfsplus/ioctl.c
@@ -12,6 +12,7 @@
* hfsplus ioctls
*/
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/xattr.h>
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 935dafba0078..dc64fac00831 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -83,58 +83,58 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
switch (token) {
case opt_creator:
if (match_fourchar(&args[0], &sbi->creator)) {
- printk("HFS+-fs: creator requires a 4 character value\n");
+ printk(KERN_ERR "hfs: creator requires a 4 character value\n");
return 0;
}
break;
case opt_type:
if (match_fourchar(&args[0], &sbi->type)) {
- printk("HFS+-fs: type requires a 4 character value\n");
+ printk(KERN_ERR "hfs: type requires a 4 character value\n");
return 0;
}
break;
case opt_umask:
if (match_octal(&args[0], &tmp)) {
- printk("HFS+-fs: umask requires a value\n");
+ printk(KERN_ERR "hfs: umask requires a value\n");
return 0;
}
sbi->umask = (umode_t)tmp;
break;
case opt_uid:
if (match_int(&args[0], &tmp)) {
- printk("HFS+-fs: uid requires an argument\n");
+ printk(KERN_ERR "hfs: uid requires an argument\n");
return 0;
}
sbi->uid = (uid_t)tmp;
break;
case opt_gid:
if (match_int(&args[0], &tmp)) {
- printk("HFS+-fs: gid requires an argument\n");
+ printk(KERN_ERR "hfs: gid requires an argument\n");
return 0;
}
sbi->gid = (gid_t)tmp;
break;
case opt_part:
if (match_int(&args[0], &sbi->part)) {
- printk("HFS+-fs: part requires an argument\n");
+ printk(KERN_ERR "hfs: part requires an argument\n");
return 0;
}
break;
case opt_session:
if (match_int(&args[0], &sbi->session)) {
- printk("HFS+-fs: session requires an argument\n");
+ printk(KERN_ERR "hfs: session requires an argument\n");
return 0;
}
break;
case opt_nls:
if (sbi->nls) {
- printk("HFS+-fs: unable to change nls mapping\n");
+ printk(KERN_ERR "hfs: unable to change nls mapping\n");
return 0;
}
p = match_strdup(&args[0]);
sbi->nls = load_nls(p);
if (!sbi->nls) {
- printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p);
+ printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
kfree(p);
return 0;
}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 8093351bd7c3..7843f792a4b7 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -22,29 +22,12 @@ static void hfsplus_destroy_inode(struct inode *inode);
#include "hfsplus_fs.h"
-void hfsplus_inode_check(struct super_block *sb)
-{
-#if 0
- u32 cnt = atomic_read(&HFSPLUS_SB(sb).inode_cnt);
- u32 last_cnt = HFSPLUS_SB(sb).last_inode_cnt;
-
- if (cnt <= (last_cnt / 2) ||
- cnt >= (last_cnt * 2)) {
- HFSPLUS_SB(sb).last_inode_cnt = cnt;
- printk("inode_check: %u,%u,%u\n", cnt, last_cnt,
- HFSPLUS_SB(sb).cat_tree ? HFSPLUS_SB(sb).cat_tree->node_hash_cnt : 0);
- }
-#endif
-}
-
static void hfsplus_read_inode(struct inode *inode)
{
struct hfs_find_data fd;
struct hfsplus_vh *vhdr;
int err;
- atomic_inc(&HFSPLUS_SB(inode->i_sb).inode_cnt);
- hfsplus_inode_check(inode->i_sb);
INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
init_MUTEX(&HFSPLUS_I(inode).extents_lock);
HFSPLUS_I(inode).flags = 0;
@@ -155,12 +138,10 @@ static int hfsplus_write_inode(struct inode *inode, int unused)
static void hfsplus_clear_inode(struct inode *inode)
{
dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino);
- atomic_dec(&HFSPLUS_SB(inode->i_sb).inode_cnt);
if (HFSPLUS_IS_RSRC(inode)) {
HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL;
iput(HFSPLUS_I(inode).rsrc_inode);
}
- hfsplus_inode_check(inode->i_sb);
}
static void hfsplus_write_super(struct super_block *sb)
@@ -188,7 +169,7 @@ static void hfsplus_write_super(struct super_block *sb)
block = HFSPLUS_SB(sb).blockoffset;
block += (HFSPLUS_SB(sb).sect_count - 2) >> (sb->s_blocksize_bits - 9);
offset = ((HFSPLUS_SB(sb).sect_count - 2) << 9) & (sb->s_blocksize - 1);
- printk("backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
+ printk(KERN_DEBUG "hfs: backup: %u,%u,%u,%u\n", HFSPLUS_SB(sb).blockoffset,
HFSPLUS_SB(sb).sect_count, block, offset);
bh = sb_bread(sb, block);
if (bh) {
@@ -198,7 +179,7 @@ static void hfsplus_write_super(struct super_block *sb)
mark_buffer_dirty(bh);
brelse(bh);
} else
- printk("backup not found!\n");
+ printk(KERN_WARNING "hfs: backup not found!\n");
}
}
HFSPLUS_SB(sb).flags &= ~HFSPLUS_SB_WRITEBACKUP;
@@ -259,18 +240,18 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
return -EINVAL;
if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
- printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+ printk(KERN_WARNING "hfs: filesystem was not cleanly unmounted, "
"running fsck.hfsplus is recommended. leaving read-only.\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
} else if (sbi.flags & HFSPLUS_SB_FORCE) {
/* nothing */
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
- printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n");
+ printk(KERN_WARNING "hfs: filesystem is marked locked, leaving read-only.\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
- printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n");
+ printk(KERN_WARNING "hfs: filesystem is marked journaled, leaving read-only.\n");
sb->s_flags |= MS_RDONLY;
*flags |= MS_RDONLY;
}
@@ -311,8 +292,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
INIT_HLIST_HEAD(&sbi->rsrc_inodes);
hfsplus_fill_defaults(sbi);
if (!hfsplus_parse_options(data, sbi)) {
- if (!silent)
- printk("HFS+-fs: unable to parse mount options\n");
+ printk(KERN_ERR "hfs: unable to parse mount options\n");
err = -EINVAL;
goto cleanup;
}
@@ -320,8 +300,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
/* temporarily use utf8 to correctly find the hidden dir below */
nls = sbi->nls;
sbi->nls = load_nls("utf8");
- if (!nls) {
- printk("HFS+: unable to load nls for utf8\n");
+ if (!sbi->nls) {
+ printk(KERN_ERR "hfs: unable to load nls for utf8\n");
err = -EINVAL;
goto cleanup;
}
@@ -329,17 +309,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
/* Grab the volume header */
if (hfsplus_read_wrapper(sb)) {
if (!silent)
- printk("HFS+-fs: unable to find HFS+ superblock\n");
+ printk(KERN_WARNING "hfs: unable to find HFS+ superblock\n");
err = -EINVAL;
goto cleanup;
}
vhdr = HFSPLUS_SB(sb).s_vhdr;
/* Copy parts of the volume header into the superblock */
- sb->s_magic = be16_to_cpu(vhdr->signature);
- if (be16_to_cpu(vhdr->version) != HFSPLUS_CURRENT_VERSION) {
- if (!silent)
- printk("HFS+-fs: wrong filesystem version\n");
+ sb->s_magic = HFSPLUS_VOLHEAD_SIG;
+ if (be16_to_cpu(vhdr->version) < HFSPLUS_MIN_VERSION ||
+ be16_to_cpu(vhdr->version) > HFSPLUS_CURRENT_VERSION) {
+ printk(KERN_ERR "hfs: wrong filesystem version\n");
goto cleanup;
}
HFSPLUS_SB(sb).total_blocks = be32_to_cpu(vhdr->total_blocks);
@@ -360,20 +340,17 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
sb->s_maxbytes = MAX_LFS_FILESIZE;
if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
- if (!silent)
- printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
- "running fsck.hfsplus is recommended. mounting read-only.\n");
+ printk(KERN_WARNING "hfs: Filesystem was not cleanly unmounted, "
+ "running fsck.hfsplus is recommended. mounting read-only.\n");
sb->s_flags |= MS_RDONLY;
} else if (sbi->flags & HFSPLUS_SB_FORCE) {
/* nothing */
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
- if (!silent)
- printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
+ printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
sb->s_flags |= MS_RDONLY;
} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
- if (!silent)
- printk("HFS+-fs: write access to a jounaled filesystem is not supported, "
- "use the force option at your own risk, mounting read-only.\n");
+ printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
+ "use the force option at your own risk, mounting read-only.\n");
sb->s_flags |= MS_RDONLY;
}
sbi->flags &= ~HFSPLUS_SB_FORCE;
@@ -381,21 +358,18 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
/* Load metadata objects (B*Trees) */
HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID);
if (!HFSPLUS_SB(sb).ext_tree) {
- if (!silent)
- printk("HFS+-fs: failed to load extents file\n");
+ printk(KERN_ERR "hfs: failed to load extents file\n");
goto cleanup;
}
HFSPLUS_SB(sb).cat_tree = hfs_btree_open(sb, HFSPLUS_CAT_CNID);
if (!HFSPLUS_SB(sb).cat_tree) {
- if (!silent)
- printk("HFS+-fs: failed to load catalog file\n");
+ printk(KERN_ERR "hfs: failed to load catalog file\n");
goto cleanup;
}
HFSPLUS_SB(sb).alloc_file = iget(sb, HFSPLUS_ALLOC_CNID);
if (!HFSPLUS_SB(sb).alloc_file) {
- if (!silent)
- printk("HFS+-fs: failed to load allocation file\n");
+ printk(KERN_ERR "hfs: failed to load allocation file\n");
goto cleanup;
}
@@ -403,8 +377,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
root = iget(sb, HFSPLUS_ROOT_CNID);
sb->s_root = d_alloc_root(root);
if (!sb->s_root) {
- if (!silent)
- printk("HFS+-fs: failed to load root directory\n");
+ printk(KERN_ERR "hfs: failed to load root directory\n");
iput(root);
goto cleanup;
}
@@ -438,7 +411,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
sync_dirty_buffer(HFSPLUS_SB(sb).s_vhbh);
if (!HFSPLUS_SB(sb).hidden_dir) {
- printk("HFS+: create hidden dir...\n");
+ printk(KERN_DEBUG "hfs: create hidden dir...\n");
HFSPLUS_SB(sb).hidden_dir = hfsplus_new_inode(sb, S_IFDIR);
hfsplus_create_cat(HFSPLUS_SB(sb).hidden_dir->i_ino, sb->s_root->d_inode,
&str, HFSPLUS_SB(sb).hidden_dir);
@@ -518,7 +491,7 @@ static void __exit exit_hfsplus_fs(void)
{
unregister_filesystem(&hfsplus_fs_type);
if (kmem_cache_destroy(hfsplus_inode_cachep))
- printk(KERN_INFO "hfsplus_inode_cache: not all structures were freed\n");
+ printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
}
module_init(init_hfsplus_fs)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 060c69048c3d..689c8bd721fb 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -28,7 +28,8 @@ static inline u16 case_fold(u16 c)
}
/* Compare unicode strings, return values like normal strcmp */
-int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2)
+int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
+ const struct hfsplus_unistr *s2)
{
u16 len1, len2, c1, c2;
const hfsplus_unichr *p1, *p2;
@@ -59,6 +60,33 @@ int hfsplus_unistrcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unis
}
}
+/* Compare names as a sequence of 16-bit unsigned integers */
+int hfsplus_strcmp(const struct hfsplus_unistr *s1,
+ const struct hfsplus_unistr *s2)
+{
+ u16 len1, len2, c1, c2;
+ const hfsplus_unichr *p1, *p2;
+ int len;
+
+ len1 = be16_to_cpu(s1->length);
+ len2 = be16_to_cpu(s2->length);
+ p1 = s1->unicode;
+ p2 = s2->unicode;
+
+ for (len = min(len1, len2); len > 0; len--) {
+ c1 = be16_to_cpu(*p1);
+ c2 = be16_to_cpu(*p2);
+ if (c1 != c2)
+ return c1 < c2 ? -1 : 1;
+ p1++;
+ p2++;
+ }
+
+ return len1 < len2 ? -1 :
+ len1 > len2 ? 1 : 0;
+}
+
+
#define Hangul_SBase 0xac00
#define Hangul_LBase 0x1100
#define Hangul_VBase 0x1161
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 95455e839231..72cab78f0509 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -28,8 +28,11 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
{
u32 extent;
u16 attrib;
+ __be16 sig;
- if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+ sig = *(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG);
+ if (sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIG) &&
+ sig != cpu_to_be16(HFSPLUS_VOLHEAD_SIGX))
return 0;
attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
@@ -70,7 +73,7 @@ static int hfsplus_get_last_session(struct super_block *sb,
*start = (sector_t)te.cdte_addr.lba << 2;
return 0;
}
- printk(KERN_ERR "HFS: Invalid session number or type of track\n");
+ printk(KERN_ERR "hfs: invalid session number or type of track\n");
return -EINVAL;
}
ms_info.addr_format = CDROM_LBA;
@@ -114,6 +117,10 @@ int hfsplus_read_wrapper(struct super_block *sb)
}
if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIG))
break;
+ if (vhdr->signature == cpu_to_be16(HFSPLUS_VOLHEAD_SIGX)) {
+ HFSPLUS_SB(sb).flags |= HFSPLUS_SB_HFSX;
+ break;
+ }
brelse(bh);
/* check for a partition block
@@ -143,7 +150,7 @@ int hfsplus_read_wrapper(struct super_block *sb)
blocksize >>= 1;
if (sb_set_blocksize(sb, blocksize) != blocksize) {
- printk("HFS+: unable to blocksize to %u!\n", blocksize);
+ printk(KERN_ERR "hfs: unable to set blocksize to %u!\n", blocksize);
return -EINVAL;
}
@@ -158,7 +165,9 @@ int hfsplus_read_wrapper(struct super_block *sb)
return -EIO;
/* should still be the same... */
- if (be16_to_cpu(vhdr->signature) != HFSPLUS_VOLHEAD_SIG)
+ if (vhdr->signature != (HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX ?
+ cpu_to_be16(HFSPLUS_VOLHEAD_SIGX) :
+ cpu_to_be16(HFSPLUS_VOLHEAD_SIG)))
goto error;
HFSPLUS_SB(sb).s_vhbh = bh;
HFSPLUS_SB(sb).s_vhdr = vhdr;
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 0217c3a04441..5591f9623aa2 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -32,19 +32,19 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
/*printk("dir lseek\n");*/
if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
- down(&i->i_sem);
+ mutex_lock(&i->i_mutex);
pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
while (pos != new_off) {
if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
else goto fail;
if (pos == 12) goto fail;
}
- up(&i->i_sem);
+ mutex_unlock(&i->i_mutex);
ok:
unlock_kernel();
return filp->f_pos = new_off;
fail:
- up(&i->i_sem);
+ mutex_unlock(&i->i_mutex);
/*printk("illegal lseek: %016llx\n", new_off);*/
unlock_kernel();
return -ESPIPE;
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 52930915bad8..a44dc5897399 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -171,12 +171,12 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
err = -ENOMEM;
parent = HPPFS_I(ino)->proc_dentry;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
proc_dentry = d_lookup(parent, &dentry->d_name);
if(proc_dentry == NULL){
proc_dentry = d_alloc(parent, &dentry->d_name);
if(proc_dentry == NULL){
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
goto out;
}
new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
@@ -186,7 +186,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
proc_dentry = new;
}
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
if(IS_ERR(proc_dentry))
return(proc_dentry);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 8c1cef3bb677..f568102da1e8 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -18,6 +18,7 @@
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/capability.h>
#include <linux/backing-dev.h>
#include <linux/hugetlb.h>
#include <linux/pagevec.h>
@@ -100,9 +101,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
loff_t len, vma_len;
int ret;
- if ((vma->vm_flags & (VM_MAYSHARE | VM_WRITE)) == VM_WRITE)
- return -EINVAL;
-
if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1))
return -EINVAL;
@@ -121,7 +119,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
vma_len = (loff_t)(vma->vm_end - vma->vm_start);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
file_accessed(file);
vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
vma->vm_ops = &hugetlb_vm_ops;
@@ -136,7 +134,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
if (inode->i_size < len)
inode->i_size = len;
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return ret;
}
@@ -404,7 +402,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
info = HUGETLBFS_I(inode);
- mpol_shared_policy_init(&info->policy);
+ mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
diff --git a/fs/inode.c b/fs/inode.c
index d8d04bd72b59..108138d4e909 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -22,6 +22,7 @@
#include <linux/cdev.h>
#include <linux/bootmem.h>
#include <linux/inotify.h>
+#include <linux/mount.h>
/*
* This is needed for the following functions:
@@ -192,7 +193,7 @@ void inode_init_once(struct inode *inode)
INIT_HLIST_NODE(&inode->i_hash);
INIT_LIST_HEAD(&inode->i_dentry);
INIT_LIST_HEAD(&inode->i_devices);
- sema_init(&inode->i_sem, 1);
+ mutex_init(&inode->i_mutex);
init_rwsem(&inode->i_alloc_sem);
INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
rwlock_init(&inode->i_data.tree_lock);
@@ -770,7 +771,7 @@ EXPORT_SYMBOL(igrab);
*
* Note, @test is called with the inode_lock held, so can't sleep.
*/
-static inline struct inode *ifind(struct super_block *sb,
+static struct inode *ifind(struct super_block *sb,
struct hlist_head *head, int (*test)(struct inode *, void *),
void *data, const int wait)
{
@@ -804,7 +805,7 @@ static inline struct inode *ifind(struct super_block *sb,
*
* Otherwise NULL is returned.
*/
-static inline struct inode *ifind_fast(struct super_block *sb,
+static struct inode *ifind_fast(struct super_block *sb,
struct hlist_head *head, unsigned long ino)
{
struct inode *inode;
@@ -1176,22 +1177,33 @@ sector_t bmap(struct inode * inode, sector_t block)
EXPORT_SYMBOL(bmap);
/**
- * update_atime - update the access time
+ * touch_atime - update the access time
+ * @mnt: mount the inode is accessed on
* @inode: inode accessed
*
* Update the accessed time on an inode and mark it for writeback.
* This function automatically handles read only file systems and media,
* as well as the "noatime" flag and inode specific "noatime" markers.
*/
-void update_atime(struct inode *inode)
+void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
{
+ struct inode *inode = dentry->d_inode;
struct timespec now;
- if (IS_NOATIME(inode))
+ if (IS_RDONLY(inode))
return;
- if (IS_NODIRATIME(inode) && S_ISDIR(inode->i_mode))
+
+ if ((inode->i_flags & S_NOATIME) ||
+ (inode->i_sb->s_flags & MS_NOATIME) ||
+ ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
return;
- if (IS_RDONLY(inode))
+
+ /*
+ * We may have a NULL vfsmount when coming from NFSD
+ */
+ if (mnt &&
+ ((mnt->mnt_flags & MNT_NOATIME) ||
+ ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
return;
now = current_fs_time(inode->i_sb);
@@ -1201,19 +1213,23 @@ void update_atime(struct inode *inode)
}
}
-EXPORT_SYMBOL(update_atime);
+EXPORT_SYMBOL(touch_atime);
/**
- * inode_update_time - update mtime and ctime time
- * @inode: inode accessed
- * @ctime_too: update ctime too
+ * file_update_time - update mtime and ctime time
+ * @file: file accessed
*
- * Update the mtime time on an inode and mark it for writeback.
- * When ctime_too is specified update the ctime too.
+ * Update the mtime and ctime members of an inode and mark the inode
+ * for writeback. Note that this function is meant exclusively for
+ * usage in the file write path of filesystems, and filesystems may
+ * choose to explicitly ignore update via this function with the
+ * S_NOCTIME inode flag, e.g. for network filesystem where these
+ * timestamps are handled by the server.
*/
-void inode_update_time(struct inode *inode, int ctime_too)
+void file_update_time(struct file *file)
{
+ struct inode *inode = file->f_dentry->d_inode;
struct timespec now;
int sync_it = 0;
@@ -1227,16 +1243,15 @@ void inode_update_time(struct inode *inode, int ctime_too)
sync_it = 1;
inode->i_mtime = now;
- if (ctime_too) {
- if (!timespec_equal(&inode->i_ctime, &now))
- sync_it = 1;
- inode->i_ctime = now;
- }
+ if (!timespec_equal(&inode->i_ctime, &now))
+ sync_it = 1;
+ inode->i_ctime = now;
+
if (sync_it)
mark_inode_dirty_sync(inode);
}
-EXPORT_SYMBOL(inode_update_time);
+EXPORT_SYMBOL(file_update_time);
int inode_needs_sync(struct inode *inode)
{
diff --git a/fs/inotify.c b/fs/inotify.c
index 2fecb7af4a77..878ccca61213 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -33,6 +33,7 @@
#include <linux/list.h>
#include <linux/writeback.h>
#include <linux/inotify.h>
+#include <linux/syscalls.h>
#include <asm/ioctls.h>
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 569209181425..f8aeec3ca10c 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -8,6 +8,7 @@
#include <linux/syscalls.h>
#include <linux/mm.h>
#include <linux/smp_lock.h>
+#include <linux/capability.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/security.h>
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 4bf1c6365a19..ca77008146c0 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/ioprio.h>
#include <linux/blkdev.h>
+#include <linux/capability.h>
#include <linux/syscalls.h>
static int set_task_ioprio(struct task_struct *task, int ioprio)
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index e37e82b7cbf0..e7ba0c30e071 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -185,8 +185,5 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n
}
}
unlock_kernel();
- if (inode)
- return d_splice_alias(inode, dentry);
- d_add(dentry, inode);
- return NULL;
+ return d_splice_alias(inode, dentry);
}
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 014a51fd00d7..e6265a0b56b8 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -24,29 +24,75 @@
#include <linux/slab.h>
/*
- * Unlink a buffer from a transaction.
+ * Unlink a buffer from a transaction checkpoint list.
*
* Called with j_list_lock held.
*/
-static inline void __buffer_unlink(struct journal_head *jh)
+static void __buffer_unlink_first(struct journal_head *jh)
{
transaction_t *transaction;
transaction = jh->b_cp_transaction;
- jh->b_cp_transaction = NULL;
jh->b_cpnext->b_cpprev = jh->b_cpprev;
jh->b_cpprev->b_cpnext = jh->b_cpnext;
- if (transaction->t_checkpoint_list == jh)
+ if (transaction->t_checkpoint_list == jh) {
transaction->t_checkpoint_list = jh->b_cpnext;
- if (transaction->t_checkpoint_list == jh)
- transaction->t_checkpoint_list = NULL;
+ if (transaction->t_checkpoint_list == jh)
+ transaction->t_checkpoint_list = NULL;
+ }
+}
+
+/*
+ * Unlink a buffer from a transaction checkpoint(io) list.
+ *
+ * Called with j_list_lock held.
+ */
+
+static inline void __buffer_unlink(struct journal_head *jh)
+{
+ transaction_t *transaction;
+
+ transaction = jh->b_cp_transaction;
+
+ __buffer_unlink_first(jh);
+ if (transaction->t_checkpoint_io_list == jh) {
+ transaction->t_checkpoint_io_list = jh->b_cpnext;
+ if (transaction->t_checkpoint_io_list == jh)
+ transaction->t_checkpoint_io_list = NULL;
+ }
+}
+
+/*
+ * Move a buffer from the checkpoint list to the checkpoint io list
+ *
+ * Called with j_list_lock held
+ */
+
+static inline void __buffer_relink_io(struct journal_head *jh)
+{
+ transaction_t *transaction;
+
+ transaction = jh->b_cp_transaction;
+ __buffer_unlink_first(jh);
+
+ if (!transaction->t_checkpoint_io_list) {
+ jh->b_cpnext = jh->b_cpprev = jh;
+ } else {
+ jh->b_cpnext = transaction->t_checkpoint_io_list;
+ jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
+ jh->b_cpprev->b_cpnext = jh;
+ jh->b_cpnext->b_cpprev = jh;
+ }
+ transaction->t_checkpoint_io_list = jh;
}
/*
* Try to release a checkpointed buffer from its transaction.
- * Returns 1 if we released it.
+ * Returns 1 if we released it and 2 if we also released the
+ * whole transaction.
+ *
* Requires j_list_lock
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
*/
@@ -57,12 +103,11 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
JBUFFER_TRACE(jh, "remove from checkpoint list");
- __journal_remove_checkpoint(jh);
+ ret = __journal_remove_checkpoint(jh) + 1;
jbd_unlock_bh_state(bh);
journal_remove_journal_head(bh);
BUFFER_TRACE(bh, "release");
__brelse(bh);
- ret = 1;
} else {
jbd_unlock_bh_state(bh);
}
@@ -117,83 +162,53 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
}
/*
- * Clean up a transaction's checkpoint list.
- *
- * We wait for any pending IO to complete and make sure any clean
- * buffers are removed from the transaction.
- *
- * Return 1 if we performed any actions which might have destroyed the
- * checkpoint. (journal_remove_checkpoint() deletes the transaction when
- * the last checkpoint buffer is cleansed)
+ * Clean up transaction's list of buffers submitted for io.
+ * We wait for any pending IO to complete and remove any clean
+ * buffers. Note that we take the buffers in the opposite ordering
+ * from the one in which they were submitted for IO.
*
* Called with j_list_lock held.
*/
-static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
+
+static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
{
- struct journal_head *jh, *next_jh, *last_jh;
+ struct journal_head *jh;
struct buffer_head *bh;
- int ret = 0;
-
- assert_spin_locked(&journal->j_list_lock);
- jh = transaction->t_checkpoint_list;
- if (!jh)
- return 0;
-
- last_jh = jh->b_cpprev;
- next_jh = jh;
- do {
- jh = next_jh;
+ tid_t this_tid;
+ int released = 0;
+
+ this_tid = transaction->t_tid;
+restart:
+ /* Didn't somebody clean up the transaction in the meanwhile */
+ if (journal->j_checkpoint_transactions != transaction ||
+ transaction->t_tid != this_tid)
+ return;
+ while (!released && transaction->t_checkpoint_io_list) {
+ jh = transaction->t_checkpoint_io_list;
bh = jh2bh(jh);
+ if (!jbd_trylock_bh_state(bh)) {
+ jbd_sync_bh(journal, bh);
+ spin_lock(&journal->j_list_lock);
+ goto restart;
+ }
if (buffer_locked(bh)) {
atomic_inc(&bh->b_count);
spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh);
wait_on_buffer(bh);
/* the journal_head may have gone by now */
BUFFER_TRACE(bh, "brelse");
__brelse(bh);
- goto out_return_1;
- }
-
- /*
- * This is foul
- */
- if (!jbd_trylock_bh_state(bh)) {
- jbd_sync_bh(journal, bh);
- goto out_return_1;
+ spin_lock(&journal->j_list_lock);
+ goto restart;
}
-
- if (jh->b_transaction != NULL) {
- transaction_t *t = jh->b_transaction;
- tid_t tid = t->t_tid;
-
- spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
- log_start_commit(journal, tid);
- log_wait_commit(journal, tid);
- goto out_return_1;
- }
-
/*
- * AKPM: I think the buffer_jbddirty test is redundant - it
- * shouldn't have NULL b_transaction?
+ * Now in whatever state the buffer currently is, we know that
+ * it has been written out and so we can drop it from the list
*/
- next_jh = jh->b_cpnext;
- if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) {
- BUFFER_TRACE(bh, "remove from checkpoint");
- __journal_remove_checkpoint(jh);
- jbd_unlock_bh_state(bh);
- journal_remove_journal_head(bh);
- __brelse(bh);
- ret = 1;
- } else {
- jbd_unlock_bh_state(bh);
- }
- } while (jh != last_jh);
-
- return ret;
-out_return_1:
- spin_lock(&journal->j_list_lock);
- return 1;
+ released = __journal_remove_checkpoint(jh);
+ jbd_unlock_bh_state(bh);
+ }
}
#define NR_BATCH 64
@@ -203,9 +218,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
{
int i;
- spin_unlock(&journal->j_list_lock);
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];
clear_buffer_jwrite(bh);
@@ -221,19 +234,46 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
* Return 1 if something happened which requires us to abort the current
* scan of the checkpoint list.
*
- * Called with j_list_lock held.
+ * Called with j_list_lock held and drops it if 1 is returned
* Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
*/
-static int __flush_buffer(journal_t *journal, struct journal_head *jh,
- struct buffer_head **bhs, int *batch_count,
- int *drop_count)
+static int __process_buffer(journal_t *journal, struct journal_head *jh,
+ struct buffer_head **bhs, int *batch_count)
{
struct buffer_head *bh = jh2bh(jh);
int ret = 0;
- if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) {
- J_ASSERT_JH(jh, jh->b_transaction == NULL);
+ if (buffer_locked(bh)) {
+ get_bh(bh);
+ spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh);
+ wait_on_buffer(bh);
+ /* the journal_head may have gone by now */
+ BUFFER_TRACE(bh, "brelse");
+ put_bh(bh);
+ ret = 1;
+ }
+ else if (jh->b_transaction != NULL) {
+ transaction_t *t = jh->b_transaction;
+ tid_t tid = t->t_tid;
+ spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh);
+ log_start_commit(journal, tid);
+ log_wait_commit(journal, tid);
+ ret = 1;
+ }
+ else if (!buffer_dirty(bh)) {
+ J_ASSERT_JH(jh, !buffer_jbddirty(bh));
+ BUFFER_TRACE(bh, "remove from checkpoint");
+ __journal_remove_checkpoint(jh);
+ spin_unlock(&journal->j_list_lock);
+ jbd_unlock_bh_state(bh);
+ journal_remove_journal_head(bh);
+ put_bh(bh);
+ ret = 1;
+ }
+ else {
/*
* Important: we are about to write the buffer, and
* possibly block, while still holding the journal lock.
@@ -246,45 +286,30 @@ static int __flush_buffer(journal_t *journal, struct journal_head *jh,
J_ASSERT_BH(bh, !buffer_jwrite(bh));
set_buffer_jwrite(bh);
bhs[*batch_count] = bh;
+ __buffer_relink_io(jh);
jbd_unlock_bh_state(bh);
(*batch_count)++;
if (*batch_count == NR_BATCH) {
+ spin_unlock(&journal->j_list_lock);
__flush_batch(journal, bhs, batch_count);
ret = 1;
}
- } else {
- int last_buffer = 0;
- if (jh->b_cpnext == jh) {
- /* We may be about to drop the transaction. Tell the
- * caller that the lists have changed.
- */
- last_buffer = 1;
- }
- if (__try_to_free_cp_buf(jh)) {
- (*drop_count)++;
- ret = last_buffer;
- }
}
return ret;
}
/*
- * Perform an actual checkpoint. We don't write out only enough to
- * satisfy the current blocked requests: rather we submit a reasonably
- * sized chunk of the outstanding data to disk at once for
- * efficiency. __log_wait_for_space() will retry if we didn't free enough.
+ * Perform an actual checkpoint. We take the first transaction on the
+ * list of transactions to be checkpointed and send all its buffers
+ * to disk. We submit larger chunks of data at once.
*
- * However, we _do_ take into account the amount requested so that once
- * the IO has been queued, we can return as soon as enough of it has
- * completed to disk.
- *
* The journal should be locked before calling this function.
*/
int log_do_checkpoint(journal_t *journal)
{
+ transaction_t *transaction;
+ tid_t this_tid;
int result;
- int batch_count = 0;
- struct buffer_head *bhs[NR_BATCH];
jbd_debug(1, "Start checkpoint\n");
@@ -299,79 +324,70 @@ int log_do_checkpoint(journal_t *journal)
return result;
/*
- * OK, we need to start writing disk blocks. Try to free up a
- * quarter of the log in a single checkpoint if we can.
+ * OK, we need to start writing disk blocks. Take one transaction
+ * and write it.
*/
+ spin_lock(&journal->j_list_lock);
+ if (!journal->j_checkpoint_transactions)
+ goto out;
+ transaction = journal->j_checkpoint_transactions;
+ this_tid = transaction->t_tid;
+restart:
/*
- * AKPM: check this code. I had a feeling a while back that it
- * degenerates into a busy loop at unmount time.
+ * If someone cleaned up this transaction while we slept, we're
+ * done (maybe it's a new transaction, but it fell at the same
+ * address).
*/
- spin_lock(&journal->j_list_lock);
- while (journal->j_checkpoint_transactions) {
- transaction_t *transaction;
- struct journal_head *jh, *last_jh, *next_jh;
- int drop_count = 0;
- int cleanup_ret, retry = 0;
- tid_t this_tid;
-
- transaction = journal->j_checkpoint_transactions;
- this_tid = transaction->t_tid;
- jh = transaction->t_checkpoint_list;
- last_jh = jh->b_cpprev;
- next_jh = jh;
- do {
+ if (journal->j_checkpoint_transactions == transaction &&
+ transaction->t_tid == this_tid) {
+ int batch_count = 0;
+ struct buffer_head *bhs[NR_BATCH];
+ struct journal_head *jh;
+ int retry = 0;
+
+ while (!retry && transaction->t_checkpoint_list) {
struct buffer_head *bh;
- jh = next_jh;
- next_jh = jh->b_cpnext;
+ jh = transaction->t_checkpoint_list;
bh = jh2bh(jh);
if (!jbd_trylock_bh_state(bh)) {
jbd_sync_bh(journal, bh);
- spin_lock(&journal->j_list_lock);
retry = 1;
break;
}
- retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count);
- if (cond_resched_lock(&journal->j_list_lock)) {
+ retry = __process_buffer(journal, jh, bhs,
+ &batch_count);
+ if (!retry &&
+ lock_need_resched(&journal->j_list_lock)) {
+ spin_unlock(&journal->j_list_lock);
retry = 1;
break;
}
- } while (jh != last_jh && !retry);
+ }
if (batch_count) {
+ if (!retry) {
+ spin_unlock(&journal->j_list_lock);
+ retry = 1;
+ }
__flush_batch(journal, bhs, &batch_count);
- retry = 1;
}
+ if (retry) {
+ spin_lock(&journal->j_list_lock);
+ goto restart;
+ }
/*
- * If someone cleaned up this transaction while we slept, we're
- * done
- */
- if (journal->j_checkpoint_transactions != transaction)
- break;
- if (retry)
- continue;
- /*
- * Maybe it's a new transaction, but it fell at the same
- * address
- */
- if (transaction->t_tid != this_tid)
- continue;
- /*
- * We have walked the whole transaction list without
- * finding anything to write to disk. We had better be
- * able to make some progress or we are in trouble.
+ * Now we have cleaned up the first transaction's checkpoint
+ * list. Let's clean up the second one.
*/
- cleanup_ret = __cleanup_transaction(journal, transaction);
- J_ASSERT(drop_count != 0 || cleanup_ret != 0);
- if (journal->j_checkpoint_transactions != transaction)
- break;
+ __wait_cp_io(journal, transaction);
}
+out:
spin_unlock(&journal->j_list_lock);
result = cleanup_journal_tail(journal);
if (result < 0)
return result;
-
return 0;
}
@@ -456,52 +472,91 @@ int cleanup_journal_tail(journal_t *journal)
/* Checkpoint list management */
/*
+ * journal_clean_one_cp_list
+ *
+ * Find all the written-back checkpoint buffers in the given list and release them.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of bufers reaped (for debug)
+ */
+
+static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+{
+ struct journal_head *last_jh;
+ struct journal_head *next_jh = jh;
+ int ret, freed = 0;
+
+ *released = 0;
+ if (!jh)
+ return 0;
+
+ last_jh = jh->b_cpprev;
+ do {
+ jh = next_jh;
+ next_jh = jh->b_cpnext;
+ /* Use trylock because of the ranking */
+ if (jbd_trylock_bh_state(jh2bh(jh))) {
+ ret = __try_to_free_cp_buf(jh);
+ if (ret) {
+ freed++;
+ if (ret == 2) {
+ *released = 1;
+ return freed;
+ }
+ }
+ }
+ /*
+ * This function only frees up some memory if possible so we
+ * dont have an obligation to finish processing. Bail out if
+ * preemption requested:
+ */
+ if (need_resched())
+ return freed;
+ } while (jh != last_jh);
+
+ return freed;
+}
+
+/*
* journal_clean_checkpoint_list
*
* Find all the written-back checkpoint buffers in the journal and release them.
*
* Called with the journal locked.
* Called with j_list_lock held.
- * Returns number of bufers reaped (for debug)
+ * Returns number of buffers reaped (for debug)
*/
int __journal_clean_checkpoint_list(journal_t *journal)
{
transaction_t *transaction, *last_transaction, *next_transaction;
- int ret = 0;
+ int ret = 0, released;
transaction = journal->j_checkpoint_transactions;
- if (transaction == 0)
+ if (!transaction)
goto out;
last_transaction = transaction->t_cpprev;
next_transaction = transaction;
do {
- struct journal_head *jh;
-
transaction = next_transaction;
next_transaction = transaction->t_cpnext;
- jh = transaction->t_checkpoint_list;
- if (jh) {
- struct journal_head *last_jh = jh->b_cpprev;
- struct journal_head *next_jh = jh;
-
- do {
- jh = next_jh;
- next_jh = jh->b_cpnext;
- /* Use trylock because of the ranknig */
- if (jbd_trylock_bh_state(jh2bh(jh)))
- ret += __try_to_free_cp_buf(jh);
- /*
- * This function only frees up some memory
- * if possible so we dont have an obligation
- * to finish processing. Bail out if preemption
- * requested:
- */
- if (need_resched())
- goto out;
- } while (jh != last_jh);
- }
+ ret += journal_clean_one_cp_list(transaction->
+ t_checkpoint_list, &released);
+ if (need_resched())
+ goto out;
+ if (released)
+ continue;
+ /*
+ * It is essential that we are as careful as in the case of
+ * t_checkpoint_list with removing the buffer from the list as
+ * we can possibly see not yet submitted buffers on io_list
+ */
+ ret += journal_clean_one_cp_list(transaction->
+ t_checkpoint_io_list, &released);
+ if (need_resched())
+ goto out;
} while (transaction != last_transaction);
out:
return ret;
@@ -516,18 +571,22 @@ out:
* buffer updates committed in that transaction have safely been stored
* elsewhere on disk. To achieve this, all of the buffers in a
* transaction need to be maintained on the transaction's checkpoint
- * list until they have been rewritten, at which point this function is
+ * lists until they have been rewritten, at which point this function is
* called to remove the buffer from the existing transaction's
- * checkpoint list.
+ * checkpoint lists.
+ *
+ * The function returns 1 if it frees the transaction, 0 otherwise.
*
* This function is called with the journal locked.
* This function is called with j_list_lock held.
+ * This function is called with jbd_lock_bh_state(jh2bh(jh))
*/
-void __journal_remove_checkpoint(struct journal_head *jh)
+int __journal_remove_checkpoint(struct journal_head *jh)
{
transaction_t *transaction;
journal_t *journal;
+ int ret = 0;
JBUFFER_TRACE(jh, "entry");
@@ -538,8 +597,10 @@ void __journal_remove_checkpoint(struct journal_head *jh)
journal = transaction->t_journal;
__buffer_unlink(jh);
+ jh->b_cp_transaction = NULL;
- if (transaction->t_checkpoint_list != NULL)
+ if (transaction->t_checkpoint_list != NULL ||
+ transaction->t_checkpoint_io_list != NULL)
goto out;
JBUFFER_TRACE(jh, "transaction has no more buffers");
@@ -565,8 +626,10 @@ void __journal_remove_checkpoint(struct journal_head *jh)
/* Just in case anybody was waiting for more transactions to be
checkpointed... */
wake_up(&journal->j_wait_logspace);
+ ret = 1;
out:
JBUFFER_TRACE(jh, "exit");
+ return ret;
}
/*
@@ -628,6 +691,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction)
J_ASSERT(transaction->t_shadow_list == NULL);
J_ASSERT(transaction->t_log_list == NULL);
J_ASSERT(transaction->t_checkpoint_list == NULL);
+ J_ASSERT(transaction->t_checkpoint_io_list == NULL);
J_ASSERT(transaction->t_updates == 0);
J_ASSERT(journal->j_committing_transaction != transaction);
J_ASSERT(journal->j_running_transaction != transaction);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 002ad2bbc769..29e62d98bae6 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -829,7 +829,8 @@ restart_loop:
journal->j_committing_transaction = NULL;
spin_unlock(&journal->j_state_lock);
- if (commit_transaction->t_checkpoint_list == NULL) {
+ if (commit_transaction->t_checkpoint_list == NULL &&
+ commit_transaction->t_checkpoint_io_list == NULL) {
__journal_drop_transaction(journal, commit_transaction);
} else {
if (journal->j_checkpoint_transactions == NULL) {
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 3dcc6d2162cb..fc3855a1aef3 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -757,7 +757,7 @@ jffs_do_readpage_nolock(struct file *file, struct page *page)
read_len = 0;
result = 0;
- offset = page->index << PAGE_CACHE_SHIFT;
+ offset = page_offset(page);
kmap(page);
buf = page_address(page);
@@ -1415,7 +1415,7 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
* This will never trigger with sane page sizes. leave it in
* anyway, since I'm thinking about how to merge larger writes
* (the current idea is to poke a thread that does the actual
- * I/O and starts by doing a down(&inode->i_sem). then we
+ * I/O and starts by doing a mutex_lock(&inode->i_mutex). then we
* would need to get the page cache pages and have a list of
* I/O requests and do write-merging here.
* -- prumpf
@@ -1545,7 +1545,7 @@ jffs_commit_write(struct file *filp, struct page *page,
{
void *addr = page_address(page) + from;
/* XXX: PAGE_CACHE_SHIFT or PAGE_SHIFT */
- loff_t pos = (page->index<<PAGE_CACHE_SHIFT) + from;
+ loff_t pos = page_offset(page) + from;
return jffs_file_write(filp, addr, to-from, &pos);
} /* jffs_commit_write() */
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index fff108bb118b..70f7a896c04a 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -47,7 +47,7 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
ic = next_inode(&i, ic, (c)))
-static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
+static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
struct jffs2_inode_cache *ic)
{
struct jffs2_full_dirent *fd;
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index d0fcc5f3497e..09e5d10b8840 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index c79eebb8ab32..b635e167a3fa 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -134,7 +134,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_
/*
* Allocate and initializes a new fragment.
*/
-static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size)
+static struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size)
{
struct jffs2_node_frag *newfrag;
@@ -513,7 +513,7 @@ free_out:
*
* Checks the node if we are in the checking stage.
*/
-static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn)
+static int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn)
{
int ret;
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 68000a50ceb6..2967b7393415 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -302,8 +302,7 @@ int dbSync(struct inode *ipbmap)
/*
* write out dirty pages of bmap
*/
- filemap_fdatawrite(ipbmap->i_mapping);
- filemap_fdatawait(ipbmap->i_mapping);
+ filemap_write_and_wait(ipbmap->i_mapping);
diWriteSpecial(ipbmap, 0);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 28201b194f53..31b4aa13dd4b 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -265,8 +265,7 @@ int diSync(struct inode *ipimap)
/*
* write out dirty pages of imap
*/
- filemap_fdatawrite(ipimap->i_mapping);
- filemap_fdatawait(ipimap->i_mapping);
+ filemap_write_and_wait(ipimap->i_mapping);
diWriteSpecial(ipimap, 0);
@@ -565,8 +564,7 @@ void diFreeSpecial(struct inode *ip)
jfs_err("diFreeSpecial called with NULL ip!");
return;
}
- filemap_fdatawrite(ip->i_mapping);
- filemap_fdatawait(ip->i_mapping);
+ filemap_write_and_wait(ip->i_mapping);
truncate_inode_pages(ip->i_mapping, 0);
iput(ip);
}
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index c0fd7b3eadc6..dc21a5bd54d4 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -58,7 +58,7 @@ struct jfs_inode_info {
/*
* rdwrlock serializes xtree between reads & writes and synchronizes
* changes to special inodes. It's use would be redundant on
- * directories since the i_sem taken in the VFS is sufficient.
+ * directories since the i_mutex taken in the VFS is sufficient.
*/
struct rw_semaphore rdwrlock;
/*
@@ -68,7 +68,7 @@ struct jfs_inode_info {
* inode is blocked in txBegin or TxBeginAnon
*/
struct semaphore commit_sem;
- /* xattr_sem allows us to access the xattrs without taking i_sem */
+ /* xattr_sem allows us to access the xattrs without taking i_mutex */
struct rw_semaphore xattr_sem;
lid_t xtlid; /* lid of xtree lock on directory */
#ifdef CONFIG_JFS_POSIX_ACL
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index b660c93c92de..2ddb6b892bcf 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1231,10 +1231,8 @@ int txCommit(tid_t tid, /* transaction identifier */
* when we don't need to worry about it at all.
*
* if ((!S_ISDIR(ip->i_mode))
- * && (tblk->flag & COMMIT_DELETE) == 0) {
- * filemap_fdatawrite(ip->i_mapping);
- * filemap_fdatawait(ip->i_mapping);
- * }
+ * && (tblk->flag & COMMIT_DELETE) == 0)
+ * filemap_write_and_wait(ip->i_mapping);
*/
/*
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 5cf91785b541..21eaf7ac0fcb 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -108,8 +108,7 @@ int jfs_umount(struct super_block *sb)
* Make sure all metadata makes it to disk before we mark
* the superblock as clean
*/
- filemap_fdatawrite(sbi->direct_inode->i_mapping);
- filemap_fdatawait(sbi->direct_inode->i_mapping);
+ filemap_write_and_wait(sbi->direct_inode->i_mapping);
/*
* ensure all file system file pages are propagated to their
@@ -161,8 +160,7 @@ int jfs_umount_rw(struct super_block *sb)
* mark the superblock clean before everything is flushed to
* disk.
*/
- filemap_fdatawrite(sbi->direct_inode->i_mapping);
- filemap_fdatawait(sbi->direct_inode->i_mapping);
+ filemap_write_and_wait(sbi->direct_inode->i_mapping);
updateSuper(sb, FM_CLEAN);
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index c6dc254d3253..45180361871c 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -376,8 +376,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
* by txCommit();
*/
filemap_fdatawait(ipbmap->i_mapping);
- filemap_fdatawrite(ipbmap->i_mapping);
- filemap_fdatawait(ipbmap->i_mapping);
+ filemap_write_and_wait(ipbmap->i_mapping);
diWriteSpecial(ipbmap, 0);
newPage = nPages; /* first new page number */
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 4226af3ea91b..8d31f1336431 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -502,8 +502,7 @@ out_no_rw:
jfs_err("jfs_umount failed with return code %d", rc);
}
out_mount_failed:
- filemap_fdatawrite(sbi->direct_inode->i_mapping);
- filemap_fdatawait(sbi->direct_inode->i_mapping);
+ filemap_write_and_wait(sbi->direct_inode->i_mapping);
truncate_inode_pages(sbi->direct_inode->i_mapping, 0);
make_bad_inode(sbi->direct_inode);
iput(sbi->direct_inode);
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 23aa5066b5a4..f23048f9471f 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/xattr.h>
#include <linux/posix_acl_xattr.h>
@@ -83,21 +84,6 @@ struct ea_buffer {
#define EA_NEW 0x0004
#define EA_MALLOC 0x0008
-/* Namespaces */
-#define XATTR_SYSTEM_PREFIX "system."
-#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
-
-#define XATTR_USER_PREFIX "user."
-#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
-
-#define XATTR_OS2_PREFIX "os2."
-#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
-
-/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */
-#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
-
-#define XATTR_TRUSTED_PREFIX "trusted."
-#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
/*
* These three routines are used to recognize on-disk extended attributes
@@ -773,36 +759,23 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
static int can_set_xattr(struct inode *inode, const char *name,
const void *value, size_t value_len)
{
- if (IS_RDONLY(inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
-
- if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
- /*
- * "system.*"
- */
+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return can_set_system_xattr(inode, name, value, value_len);
- if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0)
- return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
-
-#ifdef CONFIG_JFS_SECURITY
- if (strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)
- == 0)
- return 0; /* Leave it to the security module */
-#endif
-
- if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&
- (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))
+ /*
+ * Don't allow setting an attribute in an unknown namespace.
+ */
+ if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
+ strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
+ strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
+ strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))
return -EOPNOTSUPP;
if (!S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))
return -EPERM;
- return permission(inode, MAY_WRITE, NULL);
+ return 0;
}
int __jfs_setxattr(tid_t tid, struct inode *inode, const char *name,
@@ -972,22 +945,6 @@ int jfs_setxattr(struct dentry *dentry, const char *name, const void *value,
return rc;
}
-static int can_get_xattr(struct inode *inode, const char *name)
-{
-#ifdef CONFIG_JFS_SECURITY
- if(strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0)
- return 0;
-#endif
-
- if(strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0)
- return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
-
- if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
- return 0;
-
- return permission(inode, MAY_READ, NULL);
-}
-
ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
size_t buf_size)
{
@@ -998,12 +955,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
ssize_t size;
int namelen = strlen(name);
char *os2name = NULL;
- int rc;
char *value;
- if ((rc = can_get_xattr(inode, name)))
- return rc;
-
if (strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
os2name = kmalloc(namelen - XATTR_OS2_PREFIX_LEN + 1,
GFP_KERNEL);
diff --git a/fs/libfs.c b/fs/libfs.c
index 58101dff2c66..63c020e6589e 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -74,7 +74,7 @@ int dcache_dir_close(struct inode *inode, struct file *file)
loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
{
- down(&file->f_dentry->d_inode->i_sem);
+ mutex_lock(&file->f_dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += file->f_pos;
@@ -82,7 +82,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
@@ -93,20 +93,20 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
loff_t n = file->f_pos - 2;
spin_lock(&dcache_lock);
- list_del(&cursor->d_child);
+ list_del(&cursor->d_u.d_child);
p = file->f_dentry->d_subdirs.next;
while (n && p != &file->f_dentry->d_subdirs) {
struct dentry *next;
- next = list_entry(p, struct dentry, d_child);
+ next = list_entry(p, struct dentry, d_u.d_child);
if (!d_unhashed(next) && next->d_inode)
n--;
p = p->next;
}
- list_add_tail(&cursor->d_child, p);
+ list_add_tail(&cursor->d_u.d_child, p);
spin_unlock(&dcache_lock);
}
}
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return offset;
}
@@ -126,7 +126,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_dentry;
struct dentry *cursor = filp->private_data;
- struct list_head *p, *q = &cursor->d_child;
+ struct list_head *p, *q = &cursor->d_u.d_child;
ino_t ino;
int i = filp->f_pos;
@@ -153,7 +153,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
}
for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
struct dentry *next;
- next = list_entry(p, struct dentry, d_child);
+ next = list_entry(p, struct dentry, d_u.d_child);
if (d_unhashed(next) || !next->d_inode)
continue;
@@ -261,7 +261,7 @@ int simple_empty(struct dentry *dentry)
int ret = 0;
spin_lock(&dcache_lock);
- list_for_each_entry(child, &dentry->d_subdirs, d_child)
+ list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child)
if (simple_positive(child))
goto out;
ret = 1;
@@ -356,7 +356,7 @@ int simple_commit_write(struct file *file, struct page *page,
/*
* No need to use i_size_read() here, the i_size
- * cannot change under us because we hold the i_sem.
+ * cannot change under us because we hold the i_mutex.
*/
if (pos > inode->i_size)
i_size_write(inode, pos);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index c5a33648e9fd..145524039577 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -26,11 +26,12 @@
static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
-static void nlmclnt_unlock_callback(struct rpc_task *);
-static void nlmclnt_cancel_callback(struct rpc_task *);
static int nlm_stat_to_errno(u32 stat);
static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
+static const struct rpc_call_ops nlmclnt_unlock_ops;
+static const struct rpc_call_ops nlmclnt_cancel_ops;
+
/*
* Cookie counter for NLM requests
*/
@@ -221,8 +222,7 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
goto done;
}
clnt->cl_softrtry = nfssrv->client->cl_softrtry;
- clnt->cl_intr = nfssrv->client->cl_intr;
- clnt->cl_chatty = nfssrv->client->cl_chatty;
+ clnt->cl_intr = nfssrv->client->cl_intr;
}
/* Keep the old signal mask */
@@ -399,8 +399,7 @@ in_grace_period:
/*
* Generic NLM call, async version.
*/
-int
-nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
+int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
@@ -419,13 +418,12 @@ nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
msg.rpc_proc = &clnt->cl_procinfo[proc];
/* bootstrap and kick off the async RPC call */
- status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
+ status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
return status;
}
-static int
-nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
+static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
@@ -448,7 +446,7 @@ nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
/* Increment host refcount */
nlm_get_host(host);
/* bootstrap and kick off the async RPC call */
- status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
+ status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req);
if (status < 0)
nlm_release_host(host);
return status;
@@ -664,7 +662,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
if (req->a_flags & RPC_TASK_ASYNC) {
status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
- nlmclnt_unlock_callback);
+ &nlmclnt_unlock_ops);
/* Hrmf... Do the unlock early since locks_remove_posix()
* really expects us to free the lock synchronously */
do_vfs_lock(fl);
@@ -692,10 +690,9 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
return -ENOLCK;
}
-static void
-nlmclnt_unlock_callback(struct rpc_task *task)
+static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
{
- struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
+ struct nlm_rqst *req = data;
int status = req->a_res.status;
if (RPC_ASSASSINATED(task))
@@ -722,6 +719,10 @@ die:
rpc_restart_call(task);
}
+static const struct rpc_call_ops nlmclnt_unlock_ops = {
+ .rpc_call_done = nlmclnt_unlock_callback,
+};
+
/*
* Cancel a blocked lock request.
* We always use an async RPC call for this in order not to hang a
@@ -750,8 +751,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
nlmclnt_setlockargs(req, fl);
- status = nlmclnt_async_call(req, NLMPROC_CANCEL,
- nlmclnt_cancel_callback);
+ status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops);
if (status < 0) {
nlmclnt_release_lockargs(req);
kfree(req);
@@ -765,10 +765,9 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
return status;
}
-static void
-nlmclnt_cancel_callback(struct rpc_task *task)
+static void nlmclnt_cancel_callback(struct rpc_task *task, void *data)
{
- struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
+ struct nlm_rqst *req = data;
if (RPC_ASSASSINATED(task))
goto die;
@@ -807,6 +806,10 @@ retry_cancel:
rpc_delay(task, 30 * HZ);
}
+static const struct rpc_call_ops nlmclnt_cancel_ops = {
+ .rpc_call_done = nlmclnt_cancel_callback,
+};
+
/*
* Convert an NLM status code to a generic kernel errno
*/
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index c4c8601096e0..82f7a0b1d8ae 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host)
if ((clnt = host->h_rpcclnt) != NULL) {
xprt = clnt->cl_xprt;
if (time_after_eq(jiffies, host->h_nextrebind)) {
- clnt->cl_port = 0;
+ rpc_force_rebind(clnt);
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
dprintk("lockd: next rebind in %ld jiffies\n",
host->h_nextrebind - jiffies);
@@ -217,7 +217,7 @@ nlm_rebind_host(struct nlm_host *host)
{
dprintk("lockd: rebind host %s\n", host->h_name);
if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) {
- host->h_rpcclnt->cl_port = 0;
+ rpc_force_rebind(host->h_rpcclnt);
host->h_nextrebind = jiffies + NLM_HOST_REBIND;
}
}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 2d144abe84ad..0edc03e67966 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -123,7 +123,6 @@ nsm_create(void)
if (IS_ERR(clnt))
goto out_err;
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
return clnt;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 12a857c29e25..71a30b416d1a 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -178,6 +178,8 @@ lockd(struct svc_rqst *rqstp)
}
+ flush_signals(current);
+
/*
* Check whether there's a new lockd process before
* shutting down the hosts and clearing the slot.
@@ -192,8 +194,6 @@ lockd(struct svc_rqst *rqstp)
"lockd: new process, skipping host shutdown\n");
wake_up(&lockd_exit);
- flush_signals(current);
-
/* Exit the RPC thread */
svc_exit_thread(rqstp);
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 489670e21769..4063095d849e 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -22,7 +22,8 @@
#define NLMDBG_FACILITY NLMDBG_CLIENT
static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *);
-static void nlm4svc_callback_exit(struct rpc_task *);
+
+static const struct rpc_call_ops nlm4svc_callback_ops;
/*
* Obtain client and file from arguments
@@ -470,7 +471,6 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp,
}
-
/*
* This is the generic lockd callback for async RPC calls
*/
@@ -494,7 +494,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
call->a_host = host;
memcpy(&call->a_args, resp, sizeof(*resp));
- if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0)
+ if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0)
goto error;
return rpc_success;
@@ -504,10 +504,9 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
return rpc_system_err;
}
-static void
-nlm4svc_callback_exit(struct rpc_task *task)
+static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
{
- struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
+ struct nlm_rqst *call = data;
if (task->tk_status < 0) {
dprintk("lockd: %4d callback failed (errno = %d)\n",
@@ -517,6 +516,10 @@ nlm4svc_callback_exit(struct rpc_task *task)
kfree(call);
}
+static const struct rpc_call_ops nlm4svc_callback_ops = {
+ .rpc_call_done = nlm4svc_callback_exit,
+};
+
/*
* NLM Server procedures.
*/
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 49f959796b66..9cfced65d4a2 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -41,7 +41,8 @@
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
static int nlmsvc_remove_block(struct nlm_block *block);
-static void nlmsvc_grant_callback(struct rpc_task *task);
+
+static const struct rpc_call_ops nlmsvc_grant_ops;
/*
* The list of blocked locks to retry
@@ -226,31 +227,27 @@ failed:
* It is the caller's responsibility to check whether the file
* can be closed hereafter.
*/
-static void
+static int
nlmsvc_delete_block(struct nlm_block *block, int unlock)
{
struct file_lock *fl = &block->b_call.a_args.lock.fl;
struct nlm_file *file = block->b_file;
struct nlm_block **bp;
+ int status = 0;
dprintk("lockd: deleting block %p...\n", block);
/* Remove block from list */
nlmsvc_remove_block(block);
- if (fl->fl_next)
- posix_unblock_lock(file->f_file, fl);
- if (unlock) {
- fl->fl_type = F_UNLCK;
- posix_lock_file(file->f_file, fl);
- block->b_granted = 0;
- }
+ if (unlock)
+ status = posix_unblock_lock(file->f_file, fl);
/* If the block is in the middle of a GRANT callback,
* don't kill it yet. */
if (block->b_incall) {
nlmsvc_insert_block(block, NLM_NEVER);
block->b_done = 1;
- return;
+ return status;
}
/* Remove block from file's list of blocks */
@@ -265,6 +262,7 @@ nlmsvc_delete_block(struct nlm_block *block, int unlock)
nlm_release_host(block->b_host);
nlmclnt_freegrantargs(&block->b_call);
kfree(block);
+ return status;
}
/*
@@ -275,6 +273,7 @@ int
nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action)
{
struct nlm_block *block, *next;
+ /* XXX: Will everything get cleaned up if we don't unlock here? */
down(&file->f_sema);
for (block = file->f_blocks; block; block = next) {
@@ -444,6 +443,7 @@ u32
nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
{
struct nlm_block *block;
+ int status = 0;
dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
file->f_file->f_dentry->d_inode->i_sb->s_id,
@@ -454,9 +454,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
down(&file->f_sema);
if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL)
- nlmsvc_delete_block(block, 1);
+ status = nlmsvc_delete_block(block, 1);
up(&file->f_sema);
- return nlm_granted;
+ return status ? nlm_lck_denied : nlm_granted;
}
/*
@@ -562,7 +562,7 @@ callback:
/* Call the client */
nlm_get_host(block->b_call.a_host);
if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
- nlmsvc_grant_callback) < 0)
+ &nlmsvc_grant_ops) < 0)
nlm_release_host(block->b_call.a_host);
up(&file->f_sema);
}
@@ -575,10 +575,9 @@ callback:
* chain once more in order to have it removed by lockd itself (which can
* then sleep on the file semaphore without disrupting e.g. the nfs client).
*/
-static void
-nlmsvc_grant_callback(struct rpc_task *task)
+static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
{
- struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
+ struct nlm_rqst *call = data;
struct nlm_block *block;
unsigned long timeout;
struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client);
@@ -614,6 +613,10 @@ nlmsvc_grant_callback(struct rpc_task *task)
nlm_release_host(call->a_host);
}
+static const struct rpc_call_ops nlmsvc_grant_ops = {
+ .rpc_call_done = nlmsvc_grant_callback,
+};
+
/*
* We received a GRANT_RES callback. Try to find the corresponding
* block.
@@ -633,11 +636,12 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
file->f_count++;
down(&file->f_sema);
- if ((block = nlmsvc_find_block(cookie,&rqstp->rq_addr)) != NULL) {
+ block = nlmsvc_find_block(cookie, &rqstp->rq_addr);
+ if (block) {
if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
/* Try again in a couple of seconds */
nlmsvc_insert_block(block, 10 * HZ);
- block = NULL;
+ up(&file->f_sema);
} else {
/* Lock is now held by client, or has been rejected.
* In both cases, the block should be removed. */
@@ -648,8 +652,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status
nlmsvc_delete_block(block, 1);
}
}
- if (!block)
- up(&file->f_sema);
nlm_release_file(file);
}
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 757e344cf200..3bc437e0cf5b 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -23,7 +23,8 @@
#define NLMDBG_FACILITY NLMDBG_CLIENT
static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *);
-static void nlmsvc_callback_exit(struct rpc_task *);
+
+static const struct rpc_call_ops nlmsvc_callback_ops;
#ifdef CONFIG_LOCKD_V4
static u32
@@ -518,7 +519,7 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
call->a_host = host;
memcpy(&call->a_args, resp, sizeof(*resp));
- if (nlmsvc_async_call(call, proc, nlmsvc_callback_exit) < 0)
+ if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0)
goto error;
return rpc_success;
@@ -528,10 +529,9 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
return rpc_system_err;
}
-static void
-nlmsvc_callback_exit(struct rpc_task *task)
+static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
{
- struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
+ struct nlm_rqst *call = data;
if (task->tk_status < 0) {
dprintk("lockd: %4d callback failed (errno = %d)\n",
@@ -541,6 +541,10 @@ nlmsvc_callback_exit(struct rpc_task *task)
kfree(call);
}
+static const struct rpc_call_ops nlmsvc_callback_ops = {
+ .rpc_call_done = nlmsvc_callback_exit,
+};
+
/*
* NLM Server procedures.
*/
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
index f01e9c0d2677..200fbda2c6d1 100644
--- a/fs/lockd/xdr.c
+++ b/fs/lockd/xdr.c
@@ -44,7 +44,7 @@ loff_t_to_s32(loff_t offset)
/*
* XDR functions for basic NLM types
*/
-static inline u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
+static u32 *nlm_decode_cookie(u32 *p, struct nlm_cookie *c)
{
unsigned int len;
@@ -79,7 +79,7 @@ nlm_encode_cookie(u32 *p, struct nlm_cookie *c)
return p;
}
-static inline u32 *
+static u32 *
nlm_decode_fh(u32 *p, struct nfs_fh *f)
{
unsigned int len;
@@ -119,7 +119,7 @@ nlm_encode_oh(u32 *p, struct xdr_netobj *oh)
return xdr_encode_netobj(p, oh);
}
-static inline u32 *
+static u32 *
nlm_decode_lock(u32 *p, struct nlm_lock *lock)
{
struct file_lock *fl = &lock->fl;
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index ae4d6b426c62..fdcf105a5303 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -354,7 +354,9 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
return 0;
argp->state = ntohl(*p++);
/* Preserve the address in network byte order */
- argp->addr = *p++;
+ argp->addr = *p++;
+ argp->vers = *p++;
+ argp->proto = *p++;
return xdr_argsize_check(rqstp, p);
}
diff --git a/fs/locks.c b/fs/locks.c
index 250ef53d25ef..909eab8fb1d0 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -154,7 +154,7 @@ static struct file_lock *locks_alloc_lock(void)
}
/* Free a lock which is not in use. */
-static inline void locks_free_lock(struct file_lock *fl)
+static void locks_free_lock(struct file_lock *fl)
{
if (fl == NULL) {
BUG();
@@ -475,8 +475,7 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
/*
* Check whether two locks have the same owner.
*/
-static inline int
-posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
+static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
{
if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
return fl2->fl_lmops == fl1->fl_lmops &&
@@ -487,7 +486,7 @@ posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
/* Remove waiter from blocker's block list.
* When blocker ends up pointing to itself then the list is empty.
*/
-static inline void __locks_delete_block(struct file_lock *waiter)
+static void __locks_delete_block(struct file_lock *waiter)
{
list_del_init(&waiter->fl_block);
list_del_init(&waiter->fl_link);
@@ -1958,22 +1957,18 @@ EXPORT_SYMBOL(posix_block_lock);
*
* lockd needs to block waiting for locks.
*/
-void
+int
posix_unblock_lock(struct file *filp, struct file_lock *waiter)
{
- /*
- * A remote machine may cancel the lock request after it's been
- * granted locally. If that happens, we need to delete the lock.
- */
+ int status = 0;
+
lock_kernel();
- if (waiter->fl_next) {
+ if (waiter->fl_next)
__locks_delete_block(waiter);
- unlock_kernel();
- } else {
- unlock_kernel();
- waiter->fl_type = F_UNLCK;
- posix_lock_file(filp, waiter);
- }
+ else
+ status = -ENOENT;
+ unlock_kernel();
+ return status;
}
EXPORT_SYMBOL(posix_unblock_lock);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 0f1e4530670f..f5bbe4c97c58 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -126,7 +126,7 @@ __mb_cache_entry_is_hashed(struct mb_cache_entry *ce)
}
-static inline void
+static void
__mb_cache_entry_unhash(struct mb_cache_entry *ce)
{
int n;
@@ -139,7 +139,7 @@ __mb_cache_entry_unhash(struct mb_cache_entry *ce)
}
-static inline void
+static void
__mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
{
struct mb_cache *cache = ce->e_cache;
@@ -158,7 +158,7 @@ __mb_cache_entry_forget(struct mb_cache_entry *ce, gfp_t gfp_mask)
}
-static inline void
+static void
__mb_cache_entry_release_unlock(struct mb_cache_entry *ce)
{
/* Wake up all processes queuing for this cache entry. */
diff --git a/fs/mpage.c b/fs/mpage.c
index c5adcdddf3cc..e431cb3878d6 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -184,7 +184,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
if (page_has_buffers(page))
goto confused;
- block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
+ block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
last_block = (i_size_read(inode) + blocksize - 1) >> blkbits;
bh.b_page = page;
@@ -466,7 +466,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
* The page has no buffers: map it to disk
*/
BUG_ON(!PageUptodate(page));
- block_in_file = page->index << (PAGE_CACHE_SHIFT - blkbits);
+ block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
last_block = (i_size - 1) >> blkbits;
map_bh.b_page = page;
for (page_block = 0; page_block < blocks_per_page; ) {
@@ -721,7 +721,7 @@ retry:
&last_block_in_bio, &ret, wbc,
page->mapping->a_ops->writepage);
}
- if (unlikely(ret == WRITEPAGE_ACTIVATE))
+ if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
unlock_page(page);
if (ret || (--(wbc->nr_to_write) <= 0))
done = 1;
diff --git a/fs/namei.c b/fs/namei.c
index 6dbbd42d8b95..4acdac043b6b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -28,7 +28,10 @@
#include <linux/syscalls.h>
#include <linux/mount.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/namei.h>
#include <asm/namei.h>
#include <asm/uaccess.h>
@@ -112,7 +115,7 @@
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
* PATH_MAX includes the nul terminator --RR.
*/
-static inline int do_getname(const char __user *filename, char *page)
+static int do_getname(const char __user *filename, char *page)
{
int retval;
unsigned long len = PATH_MAX;
@@ -395,7 +398,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
* short-cut DAC fails, then call permission() to do more
* complete permission check.
*/
-static inline int exec_permission_lite(struct inode *inode,
+static int exec_permission_lite(struct inode *inode,
struct nameidata *nd)
{
umode_t mode = inode->i_mode;
@@ -438,7 +441,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
struct dentry * result;
struct inode *dir = parent->d_inode;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
/*
* First re-do the cached lookup just in case it was created
* while we waited for the directory semaphore..
@@ -464,7 +467,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
else
result = dentry;
}
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
return result;
}
@@ -472,7 +475,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
* Uhhuh! Nasty case: the cache was re-populated while
* we waited on the semaphore. Need to revalidate.
*/
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
if (result->d_op && result->d_op->d_revalidate) {
if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
@@ -485,7 +488,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
static int __emul_lookup_dentry(const char *, struct nameidata *);
/* SMP-safe */
-static inline int
+static __always_inline int
walk_init_root(const char *name, struct nameidata *nd)
{
read_lock(&current->fs->lock);
@@ -503,7 +506,7 @@ walk_init_root(const char *name, struct nameidata *nd)
return 1;
}
-static inline int __vfs_follow_link(struct nameidata *nd, const char *link)
+static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
char *name;
@@ -543,7 +546,7 @@ struct path {
struct dentry *dentry;
};
-static inline int __do_follow_link(struct path *path, struct nameidata *nd)
+static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
{
int error;
void *cookie;
@@ -689,7 +692,7 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
return 0;
}
-static inline void follow_dotdot(struct nameidata *nd)
+static __always_inline void follow_dotdot(struct nameidata *nd)
{
while(1) {
struct vfsmount *parent;
@@ -1062,7 +1065,8 @@ set_it:
}
/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
+static int fastcall do_path_lookup(int dfd, const char *name,
+ unsigned int flags, struct nameidata *nd)
{
int retval = 0;
@@ -1082,9 +1086,38 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
}
nd->mnt = mntget(current->fs->rootmnt);
nd->dentry = dget(current->fs->root);
- } else {
+ } else if (dfd == AT_FDCWD) {
nd->mnt = mntget(current->fs->pwdmnt);
nd->dentry = dget(current->fs->pwd);
+ } else {
+ struct file *file;
+ int fput_needed;
+ struct dentry *dentry;
+
+ file = fget_light(dfd, &fput_needed);
+ if (!file) {
+ retval = -EBADF;
+ goto out_fail;
+ }
+
+ dentry = file->f_dentry;
+
+ if (!S_ISDIR(dentry->d_inode->i_mode)) {
+ retval = -ENOTDIR;
+ fput_light(file, fput_needed);
+ goto out_fail;
+ }
+
+ retval = file_permission(file, MAY_EXEC);
+ if (retval) {
+ fput_light(file, fput_needed);
+ goto out_fail;
+ }
+
+ nd->mnt = mntget(file->f_vfsmnt);
+ nd->dentry = dget(dentry);
+
+ fput_light(file, fput_needed);
}
read_unlock(&current->fs->lock);
current->total_link_count = 0;
@@ -1093,11 +1126,19 @@ out:
if (unlikely(current->audit_context
&& nd && nd->dentry && nd->dentry->d_inode))
audit_inode(name, nd->dentry->d_inode, flags);
+out_fail:
return retval;
}
-static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags,
- struct nameidata *nd, int open_flags, int create_mode)
+int fastcall path_lookup(const char *name, unsigned int flags,
+ struct nameidata *nd)
+{
+ return do_path_lookup(AT_FDCWD, name, flags, nd);
+}
+
+static int __path_lookup_intent_open(int dfd, const char *name,
+ unsigned int lookup_flags, struct nameidata *nd,
+ int open_flags, int create_mode)
{
struct file *filp = get_empty_filp();
int err;
@@ -1107,7 +1148,7 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags
nd->intent.open.file = filp;
nd->intent.open.flags = open_flags;
nd->intent.open.create_mode = create_mode;
- err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd);
+ err = do_path_lookup(dfd, name, lookup_flags|LOOKUP_OPEN, nd);
if (IS_ERR(nd->intent.open.file)) {
if (err == 0) {
err = PTR_ERR(nd->intent.open.file);
@@ -1125,10 +1166,10 @@ static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags
* @nd: pointer to nameidata
* @open_flags: open intent flags
*/
-int path_lookup_open(const char *name, unsigned int lookup_flags,
+int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags,
struct nameidata *nd, int open_flags)
{
- return __path_lookup_intent_open(name, lookup_flags, nd,
+ return __path_lookup_intent_open(dfd, name, lookup_flags, nd,
open_flags, 0);
}
@@ -1140,12 +1181,12 @@ int path_lookup_open(const char *name, unsigned int lookup_flags,
* @open_flags: open intent flags
* @create_mode: create intent flags
*/
-static int path_lookup_create(const char *name, unsigned int lookup_flags,
- struct nameidata *nd, int open_flags,
- int create_mode)
+static int path_lookup_create(int dfd, const char *name,
+ unsigned int lookup_flags, struct nameidata *nd,
+ int open_flags, int create_mode)
{
- return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd,
- open_flags, create_mode);
+ return __path_lookup_intent_open(dfd, name, lookup_flags|LOOKUP_CREATE,
+ nd, open_flags, create_mode);
}
int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
@@ -1155,7 +1196,7 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
int err = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
- err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0);
+ err = __path_lookup_intent_open(AT_FDCWD, tmp, lookup_flags, nd, open_flags, 0);
putname(tmp);
}
return err;
@@ -1247,18 +1288,24 @@ access:
* that namei follows links, while lnamei does not.
* SMP-safe
*/
-int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+ struct nameidata *nd)
{
char *tmp = getname(name);
int err = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
- err = path_lookup(tmp, flags, nd);
+ err = do_path_lookup(dfd, tmp, flags, nd);
putname(tmp);
}
return err;
}
+int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+{
+ return __user_walk_fd(AT_FDCWD, name, flags, nd);
+}
+
/*
* It's inline, so penalty for filesystems that don't use sticky bit is
* minimal.
@@ -1293,7 +1340,7 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
+static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
{
int error;
@@ -1366,7 +1413,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
struct dentry *p;
if (p1 == p2) {
- down(&p1->d_inode->i_sem);
+ mutex_lock(&p1->d_inode->i_mutex);
return NULL;
}
@@ -1374,30 +1421,30 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
for (p = p1; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p2) {
- down(&p2->d_inode->i_sem);
- down(&p1->d_inode->i_sem);
+ mutex_lock(&p2->d_inode->i_mutex);
+ mutex_lock(&p1->d_inode->i_mutex);
return p;
}
}
for (p = p2; p->d_parent != p; p = p->d_parent) {
if (p->d_parent == p1) {
- down(&p1->d_inode->i_sem);
- down(&p2->d_inode->i_sem);
+ mutex_lock(&p1->d_inode->i_mutex);
+ mutex_lock(&p2->d_inode->i_mutex);
return p;
}
}
- down(&p1->d_inode->i_sem);
- down(&p2->d_inode->i_sem);
+ mutex_lock(&p1->d_inode->i_mutex);
+ mutex_lock(&p2->d_inode->i_mutex);
return NULL;
}
void unlock_rename(struct dentry *p1, struct dentry *p2)
{
- up(&p1->d_inode->i_sem);
+ mutex_unlock(&p1->d_inode->i_mutex);
if (p1 != p2) {
- up(&p2->d_inode->i_sem);
+ mutex_unlock(&p2->d_inode->i_mutex);
up(&p1->d_inode->i_sb->s_vfs_rename_sem);
}
}
@@ -1491,7 +1538,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(dentry, 0, NULL);
+ error = do_truncate(dentry, 0, ATTR_MTIME|ATTR_CTIME, NULL);
}
put_write_access(inode);
if (error)
@@ -1517,7 +1564,8 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
* for symlinks (where the permissions are checked later).
* SMP-safe
*/
-int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
+int open_namei(int dfd, const char *pathname, int flag,
+ int mode, struct nameidata *nd)
{
int acc_mode, error;
struct path path;
@@ -1539,7 +1587,8 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
- error = path_lookup_open(pathname, lookup_flags(flag), nd, flag);
+ error = path_lookup_open(dfd, pathname, lookup_flags(flag),
+ nd, flag);
if (error)
return error;
goto ok;
@@ -1548,7 +1597,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
/*
* Create - we need to know the parent.
*/
- error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode);
+ error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode);
if (error)
return error;
@@ -1563,14 +1612,14 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
dir = nd->dentry;
nd->flags &= ~LOOKUP_PARENT;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
path.dentry = lookup_hash(nd);
path.mnt = nd->mnt;
do_last:
error = PTR_ERR(path.dentry);
if (IS_ERR(path.dentry)) {
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
goto exit;
}
@@ -1579,7 +1628,7 @@ do_last:
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
error = vfs_create(dir->d_inode, path.dentry, mode, nd);
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
dput(nd->dentry);
nd->dentry = path.dentry;
if (error)
@@ -1593,7 +1642,7 @@ do_last:
/*
* It already exists.
*/
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
error = -EEXIST;
if (flag & O_EXCL)
@@ -1665,7 +1714,7 @@ do_link:
goto exit;
}
dir = nd->dentry;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
path.dentry = lookup_hash(nd);
path.mnt = nd->mnt;
__putname(nd->last.name);
@@ -1680,13 +1729,13 @@ do_link:
* Simple function to lookup and return a dentry and create it
* if it doesn't exist. Is SMP-safe.
*
- * Returns with nd->dentry->d_inode->i_sem locked.
+ * Returns with nd->dentry->d_inode->i_mutex locked.
*/
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
{
struct dentry *dentry = ERR_PTR(-EEXIST);
- down(&nd->dentry->d_inode->i_sem);
+ mutex_lock(&nd->dentry->d_inode->i_mutex);
/*
* Yucky last component or no last component at all?
* (foo/., foo/.., /////)
@@ -1743,7 +1792,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
return error;
}
-asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
+asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
+ unsigned dev)
{
int error = 0;
char * tmp;
@@ -1756,7 +1806,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
if (IS_ERR(tmp))
return PTR_ERR(tmp);
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
dentry = lookup_create(&nd, 0);
@@ -1784,7 +1834,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, unsigned dev)
}
dput(dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
path_release(&nd);
out:
putname(tmp);
@@ -1792,6 +1842,11 @@ out:
return error;
}
+asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev)
+{
+ return sys_mknodat(AT_FDCWD, filename, mode, dev);
+}
+
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int error = may_create(dir, dentry, NULL);
@@ -1814,7 +1869,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return error;
}
-asmlinkage long sys_mkdir(const char __user * pathname, int mode)
+asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
{
int error = 0;
char * tmp;
@@ -1825,7 +1880,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode)
struct dentry *dentry;
struct nameidata nd;
- error = path_lookup(tmp, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
dentry = lookup_create(&nd, 1);
@@ -1836,7 +1891,7 @@ asmlinkage long sys_mkdir(const char __user * pathname, int mode)
error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
dput(dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
path_release(&nd);
out:
putname(tmp);
@@ -1845,6 +1900,11 @@ out:
return error;
}
+asmlinkage long sys_mkdir(const char __user *pathname, int mode)
+{
+ return sys_mkdirat(AT_FDCWD, pathname, mode);
+}
+
/*
* We try to drop the dentry early: we should have
* a usage count of 2 if we're the only user of this
@@ -1885,7 +1945,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
DQUOT_INIT(dir);
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
dentry_unhash(dentry);
if (d_mountpoint(dentry))
error = -EBUSY;
@@ -1897,7 +1957,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
dentry->d_inode->i_flags |= S_DEAD;
}
}
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
if (!error) {
d_delete(dentry);
}
@@ -1906,7 +1966,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
return error;
}
-asmlinkage long sys_rmdir(const char __user * pathname)
+static long do_rmdir(int dfd, const char __user *pathname)
{
int error = 0;
char * name;
@@ -1917,7 +1977,7 @@ asmlinkage long sys_rmdir(const char __user * pathname)
if(IS_ERR(name))
return PTR_ERR(name);
- error = path_lookup(name, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
if (error)
goto exit;
@@ -1932,14 +1992,14 @@ asmlinkage long sys_rmdir(const char __user * pathname)
error = -EBUSY;
goto exit1;
}
- down(&nd.dentry->d_inode->i_sem);
+ mutex_lock(&nd.dentry->d_inode->i_mutex);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
error = vfs_rmdir(nd.dentry->d_inode, dentry);
dput(dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
exit1:
path_release(&nd);
exit:
@@ -1947,6 +2007,11 @@ exit:
return error;
}
+asmlinkage long sys_rmdir(const char __user *pathname)
+{
+ return do_rmdir(AT_FDCWD, pathname);
+}
+
int vfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error = may_delete(dir, dentry, 0);
@@ -1959,7 +2024,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
DQUOT_INIT(dir);
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
if (d_mountpoint(dentry))
error = -EBUSY;
else {
@@ -1967,7 +2032,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
if (!error)
error = dir->i_op->unlink(dir, dentry);
}
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
/* We don't d_delete() NFS sillyrenamed files--they still exist. */
if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
@@ -1979,11 +2044,11 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
/*
* Make sure that the actual truncation of the file will occur outside its
- * directory's i_sem. Truncate can take a long time if there is a lot of
+ * directory's i_mutex. Truncate can take a long time if there is a lot of
* writeout happening, and we don't want to prevent access to the directory
* while waiting on the I/O.
*/
-asmlinkage long sys_unlink(const char __user * pathname)
+static long do_unlinkat(int dfd, const char __user *pathname)
{
int error = 0;
char * name;
@@ -1995,13 +2060,13 @@ asmlinkage long sys_unlink(const char __user * pathname)
if(IS_ERR(name))
return PTR_ERR(name);
- error = path_lookup(name, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
if (error)
goto exit;
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
- down(&nd.dentry->d_inode->i_sem);
+ mutex_lock(&nd.dentry->d_inode->i_mutex);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
@@ -2015,7 +2080,7 @@ asmlinkage long sys_unlink(const char __user * pathname)
exit2:
dput(dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
if (inode)
iput(inode); /* truncate the inode here */
exit1:
@@ -2030,6 +2095,22 @@ slashes:
goto exit2;
}
+asmlinkage long sys_unlinkat(int dfd, const char __user *pathname, int flag)
+{
+ if ((flag & ~AT_REMOVEDIR) != 0)
+ return -EINVAL;
+
+ if (flag & AT_REMOVEDIR)
+ return do_rmdir(dfd, pathname);
+
+ return do_unlinkat(dfd, pathname);
+}
+
+asmlinkage long sys_unlink(const char __user *pathname)
+{
+ return do_unlinkat(AT_FDCWD, pathname);
+}
+
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, int mode)
{
int error = may_create(dir, dentry, NULL);
@@ -2051,7 +2132,8 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname, i
return error;
}
-asmlinkage long sys_symlink(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_symlinkat(const char __user *oldname,
+ int newdfd, const char __user *newname)
{
int error = 0;
char * from;
@@ -2066,7 +2148,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new
struct dentry *dentry;
struct nameidata nd;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
if (error)
goto out;
dentry = lookup_create(&nd, 0);
@@ -2075,7 +2157,7 @@ asmlinkage long sys_symlink(const char __user * oldname, const char __user * new
error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
dput(dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
path_release(&nd);
out:
putname(to);
@@ -2084,6 +2166,11 @@ out:
return error;
}
+asmlinkage long sys_symlink(const char __user *oldname, const char __user *newname)
+{
+ return sys_symlinkat(oldname, AT_FDCWD, newname);
+}
+
int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
{
struct inode *inode = old_dentry->d_inode;
@@ -2113,10 +2200,10 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
if (error)
return error;
- down(&old_dentry->d_inode->i_sem);
+ mutex_lock(&old_dentry->d_inode->i_mutex);
DQUOT_INIT(dir);
error = dir->i_op->link(old_dentry, dir, new_dentry);
- up(&old_dentry->d_inode->i_sem);
+ mutex_unlock(&old_dentry->d_inode->i_mutex);
if (!error)
fsnotify_create(dir, new_dentry->d_name.name);
return error;
@@ -2131,7 +2218,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
* with linux 2.0, and to avoid hard-linking to directories
* and other special files. --ADM
*/
-asmlinkage long sys_link(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
+ int newdfd, const char __user *newname)
{
struct dentry *new_dentry;
struct nameidata nd, old_nd;
@@ -2142,10 +2230,10 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam
if (IS_ERR(to))
return PTR_ERR(to);
- error = __user_walk(oldname, 0, &old_nd);
+ error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
if (error)
goto exit;
- error = path_lookup(to, LOOKUP_PARENT, &nd);
+ error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
if (error)
goto out;
error = -EXDEV;
@@ -2157,7 +2245,7 @@ asmlinkage long sys_link(const char __user * oldname, const char __user * newnam
error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
dput(new_dentry);
}
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
out_release:
path_release(&nd);
out:
@@ -2168,6 +2256,11 @@ exit:
return error;
}
+asmlinkage long sys_link(const char __user *oldname, const char __user *newname)
+{
+ return sys_linkat(AT_FDCWD, oldname, AT_FDCWD, newname);
+}
+
/*
* The worst of all namespace operations - renaming directory. "Perverted"
* doesn't even start to describe it. Somebody in UCB had a heck of a trip...
@@ -2178,7 +2271,7 @@ exit:
* sb->s_vfs_rename_sem. We might be more accurate, but that's another
* story.
* c) we have to lock _three_ objects - parents and victim (if it exists).
- * And that - after we got ->i_sem on parents (until then we don't know
+ * And that - after we got ->i_mutex on parents (until then we don't know
* whether the target exists). Solution: try to be smart with locking
* order for inodes. We rely on the fact that tree topology may change
* only under ->s_vfs_rename_sem _and_ that parent of the object we
@@ -2195,9 +2288,9 @@ exit:
* stuff into VFS), but the former is not going away. Solution: the same
* trick as in rmdir().
* e) conversion from fhandle to dentry may come in the wrong moment - when
- * we are removing the target. Solution: we will have to grab ->i_sem
+ * we are removing the target. Solution: we will have to grab ->i_mutex
* in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
- * ->i_sem on parents, which works but leads to some truely excessive
+ * ->i_mutex on parents, which works but leads to some truely excessive
* locking].
*/
static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
@@ -2222,7 +2315,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
target = new_dentry->d_inode;
if (target) {
- down(&target->i_sem);
+ mutex_lock(&target->i_mutex);
dentry_unhash(new_dentry);
}
if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
@@ -2232,7 +2325,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
if (target) {
if (!error)
target->i_flags |= S_DEAD;
- up(&target->i_sem);
+ mutex_unlock(&target->i_mutex);
if (d_unhashed(new_dentry))
d_rehash(new_dentry);
dput(new_dentry);
@@ -2255,7 +2348,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
dget(new_dentry);
target = new_dentry->d_inode;
if (target)
- down(&target->i_sem);
+ mutex_lock(&target->i_mutex);
if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
error = -EBUSY;
else
@@ -2266,7 +2359,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
d_move(old_dentry, new_dentry);
}
if (target)
- up(&target->i_sem);
+ mutex_unlock(&target->i_mutex);
dput(new_dentry);
return error;
}
@@ -2314,7 +2407,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return error;
}
-static inline int do_rename(const char * oldname, const char * newname)
+static int do_rename(int olddfd, const char *oldname,
+ int newdfd, const char *newname)
{
int error = 0;
struct dentry * old_dir, * new_dir;
@@ -2322,11 +2416,11 @@ static inline int do_rename(const char * oldname, const char * newname)
struct dentry * trap;
struct nameidata oldnd, newnd;
- error = path_lookup(oldname, LOOKUP_PARENT, &oldnd);
+ error = do_path_lookup(olddfd, oldname, LOOKUP_PARENT, &oldnd);
if (error)
goto exit;
- error = path_lookup(newname, LOOKUP_PARENT, &newnd);
+ error = do_path_lookup(newdfd, newname, LOOKUP_PARENT, &newnd);
if (error)
goto exit1;
@@ -2390,7 +2484,8 @@ exit:
return error;
}
-asmlinkage long sys_rename(const char __user * oldname, const char __user * newname)
+asmlinkage long sys_renameat(int olddfd, const char __user *oldname,
+ int newdfd, const char __user *newname)
{
int error;
char * from;
@@ -2402,13 +2497,18 @@ asmlinkage long sys_rename(const char __user * oldname, const char __user * newn
to = getname(newname);
error = PTR_ERR(to);
if (!IS_ERR(to)) {
- error = do_rename(from,to);
+ error = do_rename(olddfd, from, newdfd, to);
putname(to);
}
putname(from);
return error;
}
+asmlinkage long sys_rename(const char __user *oldname, const char __user *newname)
+{
+ return sys_renameat(AT_FDCWD, oldname, AT_FDCWD, newname);
+}
+
int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen, const char *link)
{
int len;
@@ -2552,6 +2652,7 @@ struct inode_operations page_symlink_inode_operations = {
};
EXPORT_SYMBOL(__user_walk);
+EXPORT_SYMBOL(__user_walk_fd);
EXPORT_SYMBOL(follow_down);
EXPORT_SYMBOL(follow_up);
EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
diff --git a/fs/namespace.c b/fs/namespace.c
index 2019899f2ab8..ce97becff461 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/quotaops.h>
#include <linux/acct.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/namespace.h>
@@ -47,6 +48,10 @@ static int hash_mask __read_mostly, hash_bits __read_mostly;
static kmem_cache_t *mnt_cache;
static struct rw_semaphore namespace_sem;
+/* /sys/fs */
+decl_subsys(fs, NULL, NULL);
+EXPORT_SYMBOL_GPL(fs_subsys);
+
static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
{
unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
@@ -355,14 +360,14 @@ static int show_vfsmnt(struct seq_file *m, void *v)
{ MS_SYNCHRONOUS, ",sync" },
{ MS_DIRSYNC, ",dirsync" },
{ MS_MANDLOCK, ",mand" },
- { MS_NOATIME, ",noatime" },
- { MS_NODIRATIME, ",nodiratime" },
{ 0, NULL }
};
static struct proc_fs_info mnt_info[] = {
{ MNT_NOSUID, ",nosuid" },
{ MNT_NODEV, ",nodev" },
{ MNT_NOEXEC, ",noexec" },
+ { MNT_NOATIME, ",noatime" },
+ { MNT_NODIRATIME, ",nodiratime" },
{ 0, NULL }
};
struct proc_fs_info *fs_infop;
@@ -451,7 +456,7 @@ EXPORT_SYMBOL(may_umount);
void release_mounts(struct list_head *head)
{
struct vfsmount *mnt;
- while(!list_empty(head)) {
+ while (!list_empty(head)) {
mnt = list_entry(head->next, struct vfsmount, mnt_hash);
list_del_init(&mnt->mnt_hash);
if (mnt->mnt_parent != mnt) {
@@ -814,7 +819,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
return -ENOTDIR;
err = -ENOENT;
- down(&nd->dentry->d_inode->i_sem);
+ mutex_lock(&nd->dentry->d_inode->i_mutex);
if (IS_DEADDIR(nd->dentry->d_inode))
goto out_unlock;
@@ -826,7 +831,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry))
err = attach_recursive_mnt(mnt, nd, NULL);
out_unlock:
- up(&nd->dentry->d_inode->i_sem);
+ mutex_unlock(&nd->dentry->d_inode->i_mutex);
if (!err)
security_sb_post_addmount(mnt, nd);
return err;
@@ -962,7 +967,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
goto out;
err = -ENOENT;
- down(&nd->dentry->d_inode->i_sem);
+ mutex_lock(&nd->dentry->d_inode->i_mutex);
if (IS_DEADDIR(nd->dentry->d_inode))
goto out1;
@@ -1004,7 +1009,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
list_del_init(&old_nd.mnt->mnt_expire);
spin_unlock(&vfsmount_lock);
out1:
- up(&nd->dentry->d_inode->i_sem);
+ mutex_unlock(&nd->dentry->d_inode->i_mutex);
out:
up_write(&namespace_sem);
if (!err)
@@ -1286,7 +1291,13 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,
mnt_flags |= MNT_NODEV;
if (flags & MS_NOEXEC)
mnt_flags |= MNT_NOEXEC;
- flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE);
+ if (flags & MS_NOATIME)
+ mnt_flags |= MNT_NOATIME;
+ if (flags & MS_NODIRATIME)
+ mnt_flags |= MNT_NODIRATIME;
+
+ flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
+ MS_NOATIME | MS_NODIRATIME);
/* ... and get the mountpoint */
retval = path_lookup(dir_name, LOOKUP_FOLLOW, &nd);
@@ -1526,6 +1537,10 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd)
* pointed to by put_old must yield the same directory as new_root. No other
* file system may be mounted on put_old. After all, new_root is a mountpoint.
*
+ * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
+ * See Documentation/filesystems/ramfs-rootfs-initramfs.txt for alternatives
+ * in this situation.
+ *
* Notes:
* - we don't move root/cwd if they are not at the root (reason: if something
* cared enough to change them, it's probably wrong to force them elsewhere)
@@ -1569,7 +1584,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
user_nd.dentry = dget(current->fs->root);
read_unlock(&current->fs->lock);
down_write(&namespace_sem);
- down(&old_nd.dentry->d_inode->i_sem);
+ mutex_lock(&old_nd.dentry->d_inode->i_mutex);
error = -EINVAL;
if (IS_MNT_SHARED(old_nd.mnt) ||
IS_MNT_SHARED(new_nd.mnt->mnt_parent) ||
@@ -1622,7 +1637,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root,
path_release(&root_parent);
path_release(&parent_nd);
out2:
- up(&old_nd.dentry->d_inode->i_sem);
+ mutex_unlock(&old_nd.dentry->d_inode->i_mutex);
up_write(&namespace_sem);
path_release(&user_nd);
path_release(&old_nd);
@@ -1714,6 +1729,7 @@ void __init mnt_init(unsigned long mempages)
i--;
} while (i);
sysfs_init();
+ subsystem_register(&fs_subsys);
init_rootfs();
init_mount_tree();
}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index a9f7a8ab1d59..cfd76f431dc0 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -365,7 +365,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
spin_lock(&dcache_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dent = list_entry(next, struct dentry, d_child);
+ dent = list_entry(next, struct dentry, d_u.d_child);
if ((unsigned long)dent->d_fsdata == fpos) {
if (dent->d_inode)
dget_locked(dent);
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 4947d9b11fc1..973b444d6914 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -262,7 +262,7 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
}
vfree(bouncebuffer);
- inode_update_time(inode, 1);
+ file_update_time(file);
*ppos = pos;
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index 8c8839203cd5..d277a58bd128 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -716,10 +716,8 @@ static void ncp_put_super(struct super_block *sb)
fput(server->ncp_filp);
kill_proc(server->m.wdog_pid, SIGTERM, 1);
- if (server->priv.data)
- ncp_kfree_s(server->priv.data, server->priv.len);
- if (server->auth.object_name)
- ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
+ kfree(server->priv.data);
+ kfree(server->auth.object_name);
vfree(server->packet);
sb->s_fs_info = NULL;
kfree(server);
@@ -958,11 +956,6 @@ out:
return result;
}
-#ifdef DEBUG_NCP_MALLOC
-int ncp_malloced;
-int ncp_current_malloced;
-#endif
-
static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
@@ -981,10 +974,6 @@ static int __init init_ncp_fs(void)
int err;
DPRINTK("ncpfs: init_module called\n");
-#ifdef DEBUG_NCP_MALLOC
- ncp_malloced = 0;
- ncp_current_malloced = 0;
-#endif
err = init_inodecache();
if (err)
goto out1;
@@ -1003,10 +992,6 @@ static void __exit exit_ncp_fs(void)
DPRINTK("ncpfs: cleanup_module called\n");
unregister_filesystem(&ncp_fs_type);
destroy_inodecache();
-#ifdef DEBUG_NCP_MALLOC
- PRINTK("ncp_malloced: %d\n", ncp_malloced);
- PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
-#endif
}
module_init(init_ncp_fs)
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index fd3efdca5ae3..eb3813ad136f 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <asm/uaccess.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
@@ -517,10 +518,11 @@ outrel:
if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN)
return -ENOMEM;
if (user.object_name_len) {
- newname = ncp_kmalloc(user.object_name_len, GFP_USER);
- if (!newname) return -ENOMEM;
+ newname = kmalloc(user.object_name_len, GFP_USER);
+ if (!newname)
+ return -ENOMEM;
if (copy_from_user(newname, user.object_name, user.object_name_len)) {
- ncp_kfree_s(newname, user.object_name_len);
+ kfree(newname);
return -EFAULT;
}
} else {
@@ -539,8 +541,8 @@ outrel:
server->priv.len = 0;
server->priv.data = NULL;
/* leave critical section */
- if (oldprivate) ncp_kfree_s(oldprivate, oldprivatelen);
- if (oldname) ncp_kfree_s(oldname, oldnamelen);
+ kfree(oldprivate);
+ kfree(oldname);
return 0;
}
case NCP_IOC_GETPRIVATEDATA:
@@ -580,10 +582,11 @@ outrel:
if (user.len > NCP_PRIVATE_DATA_MAX_LEN)
return -ENOMEM;
if (user.len) {
- new = ncp_kmalloc(user.len, GFP_USER);
- if (!new) return -ENOMEM;
+ new = kmalloc(user.len, GFP_USER);
+ if (!new)
+ return -ENOMEM;
if (copy_from_user(new, user.data, user.len)) {
- ncp_kfree_s(new, user.len);
+ kfree(new);
return -EFAULT;
}
} else {
@@ -595,7 +598,7 @@ outrel:
server->priv.len = user.len;
server->priv.data = new;
/* leave critical section */
- if (old) ncp_kfree_s(old, oldlen);
+ kfree(old);
return 0;
}
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 9e4dc30c2435..799e5c2bec55 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -196,7 +196,7 @@ ncp_renew_dentries(struct dentry *parent)
spin_lock(&dcache_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dentry = list_entry(next, struct dentry, d_child);
+ dentry = list_entry(next, struct dentry, d_u.d_child);
if (dentry->d_fsdata == NULL)
ncp_age_dentry(server, dentry);
@@ -218,7 +218,7 @@ ncp_invalidate_dircache_entries(struct dentry *parent)
spin_lock(&dcache_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dentry = list_entry(next, struct dentry, d_child);
+ dentry = list_entry(next, struct dentry, d_u.d_child);
dentry->d_fsdata = NULL;
ncp_age_dentry(server, dentry);
next = next->next;
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 8b3bb715d177..ec61fd56a1a9 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -13,4 +13,5 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o
nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
+nfs-$(CONFIG_SYSCTL) += sysctl.o
nfs-objs := $(nfs-y)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index f2ca782aba33..fcd97406a778 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,9 @@
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfs_fs.h>
+
+#include <net/inet_sock.h>
+
#include "nfs4_fs.h"
#include "callback.h"
@@ -31,6 +34,7 @@ static struct nfs_callback_data nfs_callback_info;
static DECLARE_MUTEX(nfs_callback_sema);
static struct svc_program nfs4_callback_program;
+unsigned int nfs_callback_set_tcpport;
unsigned short nfs_callback_tcpport;
/*
@@ -95,7 +99,7 @@ int nfs_callback_up(void)
if (!serv)
goto out_err;
/* FIXME: We don't want to register this socket with the portmapper */
- ret = svc_makesock(serv, IPPROTO_TCP, 0);
+ ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport);
if (ret < 0)
goto out_destroy;
if (!list_empty(&serv->sv_permsocks)) {
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index a0db2d4f9415..b252e7fe53a5 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -65,6 +65,7 @@ extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
extern int nfs_callback_up(void);
extern int nfs_callback_down(void);
+extern unsigned int nfs_callback_set_tcpport;
extern unsigned short nfs_callback_tcpport;
#endif /* __LINUX_FS_NFS_CALLBACK_H */
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 65f1e19e4d19..462cfceb50c5 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -35,7 +35,9 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres
if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
goto out_iput;
res->size = i_size_read(inode);
- res->change_attr = NFS_CHANGE_ATTR(inode);
+ res->change_attr = delegation->change_attr;
+ if (nfsi->npages != 0)
+ res->change_attr++;
res->ctime = inode->i_ctime;
res->mtime = inode->i_mtime;
res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 618a327027b3..c6f07c1c71e6 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -8,6 +8,7 @@
*/
#include <linux/config.h>
#include <linux/completion.h>
+#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
@@ -130,6 +131,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
sizeof(delegation->stateid.data));
delegation->type = res->delegation_type;
delegation->maxsize = res->maxsize;
+ delegation->change_attr = nfsi->change_attr;
delegation->cred = get_rpccred(cred);
delegation->inode = inode;
@@ -157,8 +159,6 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
{
int res = 0;
- __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-
res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
nfs_free_delegation(delegation);
return res;
@@ -231,6 +231,49 @@ restart:
spin_unlock(&clp->cl_lock);
}
+int nfs_do_expire_all_delegations(void *ptr)
+{
+ struct nfs4_client *clp = ptr;
+ struct nfs_delegation *delegation;
+ struct inode *inode;
+
+ allow_signal(SIGKILL);
+restart:
+ spin_lock(&clp->cl_lock);
+ if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
+ goto out;
+ if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
+ goto out;
+ list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+ inode = igrab(delegation->inode);
+ if (inode == NULL)
+ continue;
+ spin_unlock(&clp->cl_lock);
+ nfs_inode_return_delegation(inode);
+ iput(inode);
+ goto restart;
+ }
+out:
+ spin_unlock(&clp->cl_lock);
+ nfs4_put_client(clp);
+ module_put_and_exit(0);
+}
+
+void nfs_expire_all_delegations(struct nfs4_client *clp)
+{
+ struct task_struct *task;
+
+ __module_get(THIS_MODULE);
+ atomic_inc(&clp->cl_count);
+ task = kthread_run(nfs_do_expire_all_delegations, clp,
+ "%u.%u.%u.%u-delegreturn",
+ NIPQUAD(clp->cl_addr));
+ if (!IS_ERR(task))
+ return;
+ nfs4_put_client(clp);
+ module_put(THIS_MODULE);
+}
+
/*
* Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
*/
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 2fcc30de924b..7a0b2bfce771 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -21,6 +21,7 @@ struct nfs_delegation {
#define NFS_DELEGATION_NEED_RECLAIM 1
long flags;
loff_t maxsize;
+ __u64 change_attr;
};
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
@@ -30,6 +31,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle);
void nfs_return_all_delegations(struct super_block *sb);
+void nfs_expire_all_delegations(struct nfs4_client *clp);
void nfs_handle_cb_pathdown(struct nfs4_client *clp);
void nfs_delegation_mark_reclaim(struct nfs4_client *clp);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index c0d1a214572c..a1554bead692 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -194,7 +194,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
spin_unlock(&inode->i_lock);
/* Ensure consistent page alignment of the data.
* Note: assumes we have exclusive access to this mapping either
- * through inode->i_sem or some other mechanism.
+ * through inode->i_mutex or some other mechanism.
*/
if (page->index == 0)
invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
@@ -573,7 +573,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
{
- down(&filp->f_dentry->d_inode->i_sem);
+ mutex_lock(&filp->f_dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += filp->f_pos;
@@ -589,7 +589,7 @@ loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
}
out:
- up(&filp->f_dentry->d_inode->i_sem);
+ mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
return offset;
}
@@ -1001,7 +1001,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
openflags &= ~(O_CREAT|O_TRUNC);
/*
- * Note: we're not holding inode->i_sem and so may be racing with
+ * Note: we're not holding inode->i_mutex and so may be racing with
* operations that change the directory. We therefore save the
* change attribute *before* we do the RPC call.
*/
@@ -1051,7 +1051,7 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
return dentry;
if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
return NULL;
- /* Note: caller is already holding the dir->i_sem! */
+ /* Note: caller is already holding the dir->i_mutex! */
dentry = d_alloc(parent, &name);
if (dentry == NULL)
return NULL;
@@ -1550,8 +1550,10 @@ go_ahead:
}
nfs_inode_return_delegation(old_inode);
- if (new_inode)
+ if (new_inode != NULL) {
+ nfs_inode_return_delegation(new_inode);
d_delete(new_dentry);
+ }
nfs_begin_data_update(old_dir);
nfs_begin_data_update(new_dir);
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 079228817603..10ae377e68ff 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -122,9 +122,10 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
{
int i;
for (i = 0; i < npages; i++) {
- if (do_dirty)
- set_page_dirty_lock(pages[i]);
- page_cache_release(pages[i]);
+ struct page *page = pages[i];
+ if (do_dirty && !PageCompound(page))
+ set_page_dirty_lock(page);
+ page_cache_release(page);
}
kfree(pages);
}
@@ -154,6 +155,7 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int
struct list_head *list;
struct nfs_direct_req *dreq;
unsigned int reads = 0;
+ unsigned int rpages = (rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL);
if (!dreq)
@@ -167,7 +169,7 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int
list = &dreq->list;
for(;;) {
- struct nfs_read_data *data = nfs_readdata_alloc();
+ struct nfs_read_data *data = nfs_readdata_alloc(rpages);
if (unlikely(!data)) {
while (!list_empty(list)) {
@@ -268,8 +270,6 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq,
NFS_PROTO(inode)->read_setup(data);
data->task.tk_cookie = (unsigned long) inode;
- data->task.tk_calldata = data;
- data->task.tk_release = nfs_readdata_release;
data->complete = nfs_direct_read_result;
lock_kernel();
@@ -433,7 +433,7 @@ static ssize_t nfs_direct_write_seg(struct inode *inode,
struct nfs_writeverf first_verf;
struct nfs_write_data *wdata;
- wdata = nfs_writedata_alloc();
+ wdata = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
if (!wdata)
return -ENOMEM;
@@ -662,10 +662,10 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
.iov_len = count,
};
- dprintk("nfs: direct read(%s/%s, %lu@%lu)\n",
+ dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
file->f_dentry->d_name.name,
- (unsigned long) count, (unsigned long) pos);
+ (unsigned long) count, (long long) pos);
if (!is_sync_kiocb(iocb))
goto out;
@@ -718,9 +718,7 @@ out:
ssize_t
nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos)
{
- ssize_t retval = -EINVAL;
- loff_t *ppos = &iocb->ki_pos;
- unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ ssize_t retval;
struct file *file = iocb->ki_filp;
struct nfs_open_context *ctx =
(struct nfs_open_context *) file->private_data;
@@ -728,35 +726,32 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
struct inode *inode = mapping->host;
struct iovec iov = {
.iov_base = (char __user *)buf,
- .iov_len = count,
};
- dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n",
+ dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n",
file->f_dentry->d_parent->d_name.name,
- file->f_dentry->d_name.name, inode->i_ino,
- (unsigned long) count, (unsigned long) pos);
+ file->f_dentry->d_name.name,
+ (unsigned long) count, (long long) pos);
+ retval = -EINVAL;
if (!is_sync_kiocb(iocb))
goto out;
- if (count < 0)
- goto out;
- if (pos < 0)
+
+ retval = generic_write_checks(file, &pos, &count, 0);
+ if (retval)
goto out;
- retval = -EFAULT;
- if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
+
+ retval = -EINVAL;
+ if ((ssize_t) count < 0)
goto out;
- retval = -EFBIG;
- if (limit != RLIM_INFINITY) {
- if (pos >= limit) {
- send_sig(SIGXFSZ, current, 0);
- goto out;
- }
- if (count > limit - (unsigned long) pos)
- count = limit - (unsigned long) pos;
- }
retval = 0;
if (!count)
goto out;
+ iov.iov_len = count,
+
+ retval = -EFAULT;
+ if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
+ goto out;
retval = nfs_sync_mapping(mapping);
if (retval)
@@ -766,7 +761,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
if (mapping->nrpages)
invalidate_inode_pages2(mapping);
if (retval > 0)
- *ppos = pos + retval;
+ iocb->ki_pos = pos + retval;
out:
return retval;
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index ffb8df91dc34..821edd30333b 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -54,7 +54,11 @@
#define IDMAP_HASH_SZ 128
+/* Default cache timeout is 10 minutes */
+unsigned int nfs_idmap_cache_timeout = 600 * HZ;
+
struct idmap_hashent {
+ unsigned long ih_expires;
__u32 ih_id;
int ih_namelen;
char ih_name[IDMAP_NAMESZ];
@@ -149,6 +153,8 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len)
if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0)
return NULL;
+ if (time_after(jiffies, he->ih_expires))
+ return NULL;
return he;
}
@@ -164,6 +170,8 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id)
struct idmap_hashent *he = idmap_id_hash(h, id);
if (he->ih_id != id || he->ih_namelen == 0)
return NULL;
+ if (time_after(jiffies, he->ih_expires))
+ return NULL;
return he;
}
@@ -192,6 +200,7 @@ idmap_update_entry(struct idmap_hashent *he, const char *name,
memcpy(he->ih_name, name, namelen);
he->ih_name[namelen] = '\0';
he->ih_namelen = namelen;
+ he->ih_expires = jiffies + nfs_idmap_cache_timeout;
}
/*
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 432f41cd75e6..a77ee95b7efb 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -40,6 +40,7 @@
#include <asm/uaccess.h>
#include "nfs4_fs.h"
+#include "callback.h"
#include "delegation.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -221,10 +222,10 @@ nfs_calc_block_size(u64 tsize)
static inline unsigned long
nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
{
- if (bsize < 1024)
- bsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
- else if (bsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)
- bsize = NFS_MAX_FILE_IO_BUFFER_SIZE;
+ if (bsize < NFS_MIN_FILE_IO_SIZE)
+ bsize = NFS_DEF_FILE_IO_SIZE;
+ else if (bsize >= NFS_MAX_FILE_IO_SIZE)
+ bsize = NFS_MAX_FILE_IO_SIZE;
return nfs_block_bits(bsize, nrbitsp);
}
@@ -307,20 +308,15 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
if (server->rsize > max_rpc_payload)
server->rsize = max_rpc_payload;
- if (server->wsize > max_rpc_payload)
- server->wsize = max_rpc_payload;
-
+ if (server->rsize > NFS_MAX_FILE_IO_SIZE)
+ server->rsize = NFS_MAX_FILE_IO_SIZE;
server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- if (server->rpages > NFS_READ_MAXIOV) {
- server->rpages = NFS_READ_MAXIOV;
- server->rsize = server->rpages << PAGE_CACHE_SHIFT;
- }
+ if (server->wsize > max_rpc_payload)
+ server->wsize = max_rpc_payload;
+ if (server->wsize > NFS_MAX_FILE_IO_SIZE)
+ server->wsize = NFS_MAX_FILE_IO_SIZE;
server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- if (server->wpages > NFS_WRITE_MAXIOV) {
- server->wpages = NFS_WRITE_MAXIOV;
- server->wsize = server->wpages << PAGE_CACHE_SHIFT;
- }
if (sb->s_blocksize == 0)
sb->s_blocksize = nfs_block_bits(server->wsize,
@@ -417,7 +413,6 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
clnt->cl_intr = 1;
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
return clnt;
@@ -575,11 +570,10 @@ nfs_statfs(struct super_block *sb, struct kstatfs *buf)
buf->f_namelen = server->namelen;
out:
unlock_kernel();
-
return 0;
out_err:
- printk(KERN_WARNING "nfs_statfs: statfs error = %d\n", -error);
+ dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
goto out;
@@ -650,10 +644,7 @@ int nfs_sync_mapping(struct address_space *mapping)
if (mapping->nrpages == 0)
return 0;
unmap_mapping_range(mapping, 0, 0, 0);
- ret = filemap_fdatawrite(mapping);
- if (ret != 0)
- goto out;
- ret = filemap_fdatawait(mapping);
+ ret = filemap_write_and_wait(mapping);
if (ret != 0)
goto out;
ret = nfs_wb_all(mapping->host);
@@ -870,8 +861,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
nfs_begin_data_update(inode);
/* Write all dirty data if we're changing file permissions or size */
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) {
- if (filemap_fdatawrite(inode->i_mapping) == 0)
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
nfs_wb_all(inode);
}
/*
@@ -958,11 +948,22 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
int err;
- if (__IS_FLG(inode, MS_NOATIME))
- need_atime = 0;
- else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))
+ /* Flush out writes to the server in order to update c/mtime */
+ nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT);
+
+ /*
+ * We may force a getattr if the user cares about atime.
+ *
+ * Note that we only have to check the vfsmount flags here:
+ * - NFS always sets S_NOATIME by so checking it would give a
+ * bogus result
+ * - NFS never sets MS_NOATIME or MS_NODIRATIME so there is
+ * no point in checking those.
+ */
+ if ((mnt->mnt_flags & MNT_NOATIME) ||
+ ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
need_atime = 0;
- /* We may force a getattr if the user cares about atime */
+
if (need_atime)
err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
else
@@ -1252,6 +1253,33 @@ void nfs_end_data_update(struct inode *inode)
atomic_dec(&nfsi->data_updates);
}
+static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
+ && nfsi->change_attr == fattr->pre_change_attr) {
+ nfsi->change_attr = fattr->change_attr;
+ nfsi->cache_change_attribute = jiffies;
+ }
+
+ /* If we have atomic WCC data, we may update some attributes */
+ if ((fattr->valid & NFS_ATTR_WCC) != 0) {
+ if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
+ memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ nfsi->cache_change_attribute = jiffies;
+ }
+ if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
+ memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+ nfsi->cache_change_attribute = jiffies;
+ }
+ if (inode->i_size == fattr->pre_size && nfsi->npages == 0) {
+ inode->i_size = fattr->size;
+ nfsi->cache_change_attribute = jiffies;
+ }
+ }
+}
+
/**
* nfs_check_inode_attributes - verify consistency of the inode attribute cache
* @inode - pointer to inode
@@ -1268,22 +1296,20 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
int data_unstable;
+ if ((fattr->valid & NFS_ATTR_FATTR) == 0)
+ return 0;
+
/* Are we in the process of updating data on the server? */
data_unstable = nfs_caches_unstable(inode);
- if (fattr->valid & NFS_ATTR_FATTR_V4) {
- if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
- && nfsi->change_attr == fattr->pre_change_attr)
- nfsi->change_attr = fattr->change_attr;
- if (nfsi->change_attr != fattr->change_attr) {
- nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
- if (!data_unstable)
- nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
- }
- }
+ /* Do atomic weak cache consistency updates */
+ nfs_wcc_update_inode(inode, fattr);
- if ((fattr->valid & NFS_ATTR_FATTR) == 0) {
- return 0;
+ if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+ nfsi->change_attr != fattr->change_attr) {
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+ if (!data_unstable)
+ nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
}
/* Has the inode gone and changed behind our back? */
@@ -1295,14 +1321,6 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
cur_size = i_size_read(inode);
new_isize = nfs_size_to_loff_t(fattr->size);
- /* If we have atomic WCC data, we may update some attributes */
- if ((fattr->valid & NFS_ATTR_WCC) != 0) {
- if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime))
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
- if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime))
- memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
- }
-
/* Verify a few of the more important attributes */
if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
@@ -1410,14 +1428,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
return 0;
- if (nfsi->fileid != fattr->fileid) {
- printk(KERN_ERR "%s: inode number mismatch\n"
- "expected (%s/0x%Lx), got (%s/0x%Lx)\n",
- __FUNCTION__,
- inode->i_sb->s_id, (long long)nfsi->fileid,
- inode->i_sb->s_id, (long long)fattr->fileid);
- goto out_err;
- }
+ if (nfsi->fileid != fattr->fileid)
+ goto out_fileid;
/*
* Make sure the inode's type hasn't changed.
@@ -1436,6 +1448,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (data_stable)
nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+ /* Do atomic weak cache consistency updates */
+ nfs_wcc_update_inode(inode, fattr);
+
/* Check if our cached file size is stale */
new_isize = nfs_size_to_loff_t(fattr->size);
cur_isize = i_size_read(inode);
@@ -1539,6 +1554,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
*/
nfs_invalidate_inode(inode);
return -ESTALE;
+
+ out_fileid:
+ printk(KERN_ERR "NFS: server %s error: fileid changed\n"
+ "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n",
+ NFS_SERVER(inode)->hostname, inode->i_sb->s_id,
+ (long long)nfsi->fileid, (long long)fattr->fileid);
+ goto out_err;
}
/*
@@ -1820,25 +1842,10 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
}
clnt->cl_intr = 1;
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
clp->cl_rpcclient = clnt;
- clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
- if (IS_ERR(clp->cl_cred)) {
- up_write(&clp->cl_sem);
- err = PTR_ERR(clp->cl_cred);
- clp->cl_cred = NULL;
- goto out_fail;
- }
memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
nfs_idmap_new(clp);
}
- if (list_empty(&clp->cl_superblocks)) {
- err = nfs4_init_client(clp);
- if (err != 0) {
- up_write(&clp->cl_sem);
- goto out_fail;
- }
- }
list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
clnt = rpc_clone_client(clp->cl_rpcclient);
if (!IS_ERR(clnt))
@@ -2033,6 +2040,35 @@ static struct file_system_type nfs4_fs_type = {
.fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
};
+static const int nfs_set_port_min = 0;
+static const int nfs_set_port_max = 65535;
+static int param_set_port(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ int num = simple_strtol(val, &endp, 0);
+ if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
+ return -EINVAL;
+ *((int *)kp->arg) = num;
+ return 0;
+}
+
+module_param_call(callback_tcpport, param_set_port, param_get_int,
+ &nfs_callback_set_tcpport, 0644);
+
+static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ int num = simple_strtol(val, &endp, 0);
+ int jif = num * HZ;
+ if (endp == val || *endp || num < 0 || jif < num)
+ return -EINVAL;
+ *((int *)kp->arg) = jif;
+ return 0;
+}
+
+module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
+ &nfs_idmap_cache_timeout, 0644);
+
#define nfs4_init_once(nfsi) \
do { \
INIT_LIST_HEAD(&(nfsi)->open_states); \
@@ -2040,8 +2076,25 @@ static struct file_system_type nfs4_fs_type = {
nfsi->delegation_state = 0; \
init_rwsem(&nfsi->rwsem); \
} while(0)
-#define register_nfs4fs() register_filesystem(&nfs4_fs_type)
-#define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type)
+
+static inline int register_nfs4fs(void)
+{
+ int ret;
+
+ ret = nfs_register_sysctl();
+ if (ret != 0)
+ return ret;
+ ret = register_filesystem(&nfs4_fs_type);
+ if (ret != 0)
+ nfs_unregister_sysctl();
+ return ret;
+}
+
+static inline void unregister_nfs4fs(void)
+{
+ unregister_filesystem(&nfs4_fs_type);
+ nfs_unregister_sysctl();
+}
#else
#define nfs4_init_once(nfsi) \
do { } while (0)
@@ -2166,11 +2219,11 @@ out:
#ifdef CONFIG_PROC_FS
rpc_proc_unregister("nfs");
#endif
- nfs_destroy_writepagecache();
#ifdef CONFIG_NFS_DIRECTIO
-out0:
nfs_destroy_directcache();
+out0:
#endif
+ nfs_destroy_writepagecache();
out1:
nfs_destroy_readpagecache();
out2:
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 0e82617f2de0..db99b8f678f8 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -82,7 +82,6 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
RPC_AUTH_UNIX);
if (!IS_ERR(clnt)) {
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
clnt->cl_intr = 1;
}
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 59049e864ca7..7fc0560c89c9 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -146,23 +146,23 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
return p;
}
-#define SATTR(p, attr, flag, field) \
- *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
static inline u32 *
xdr_encode_sattr(u32 *p, struct iattr *attr)
{
- SATTR(p, attr, ATTR_MODE, ia_mode);
- SATTR(p, attr, ATTR_UID, ia_uid);
- SATTR(p, attr, ATTR_GID, ia_gid);
- SATTR(p, attr, ATTR_SIZE, ia_size);
+ const u32 not_set = __constant_htonl(0xFFFFFFFF);
+
+ *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
+ *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
+ *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
+ *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
if (attr->ia_valid & ATTR_ATIME_SET) {
p = xdr_encode_time(p, &attr->ia_atime);
} else if (attr->ia_valid & ATTR_ATIME) {
p = xdr_encode_current_server_time(p, &attr->ia_atime);
} else {
- *p++ = ~(u32) 0;
- *p++ = ~(u32) 0;
+ *p++ = not_set;
+ *p++ = not_set;
}
if (attr->ia_valid & ATTR_MTIME_SET) {
@@ -170,12 +170,11 @@ xdr_encode_sattr(u32 *p, struct iattr *attr)
} else if (attr->ia_valid & ATTR_MTIME) {
p = xdr_encode_current_server_time(p, &attr->ia_mtime);
} else {
- *p++ = ~(u32) 0;
- *p++ = ~(u32) 0;
+ *p++ = not_set;
+ *p++ = not_set;
}
return p;
}
-#undef SATTR
/*
* NFS encode functions
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 92c870d19ccd..ed67567f0556 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -68,27 +68,39 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
return 1;
}
-/*
- * Bare-bones access to getattr: this is for nfs_read_super.
- */
static int
-nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fsinfo *info)
+do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
+ struct nfs_fsinfo *info)
{
int status;
dprintk("%s: call fsinfo\n", __FUNCTION__);
nfs_fattr_init(info->fattr);
- status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0);
+ status = rpc_call(client, NFS3PROC_FSINFO, fhandle, info, 0);
dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status);
if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
- status = rpc_call(server->client_sys, NFS3PROC_GETATTR, fhandle, info->fattr, 0);
+ status = rpc_call(client, NFS3PROC_GETATTR, fhandle, info->fattr, 0);
dprintk("%s: reply getattr: %d\n", __FUNCTION__, status);
}
return status;
}
/*
+ * Bare-bones access to getattr: this is for nfs_read_super.
+ */
+static int
+nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+ struct nfs_fsinfo *info)
+{
+ int status;
+
+ status = do_proc_get_root(server->client, fhandle, info);
+ if (status && server->client_sys != server->client)
+ status = do_proc_get_root(server->client_sys, fhandle, info);
+ return status;
+}
+
+/*
* One function for each procedure in the NFS protocol.
*/
static int
@@ -732,19 +744,23 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
-static void
-nfs3_read_done(struct rpc_task *task)
+static void nfs3_read_done(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
+ struct nfs_read_data *data = calldata;
if (nfs3_async_handle_jukebox(task))
return;
/* Call back common NFS readpage processing */
if (task->tk_status >= 0)
nfs_refresh_inode(data->inode, &data->fattr);
- nfs_readpage_result(task);
+ nfs_readpage_result(task, calldata);
}
+static const struct rpc_call_ops nfs3_read_ops = {
+ .rpc_call_done = nfs3_read_done,
+ .rpc_release = nfs_readdata_release,
+};
+
static void
nfs3_proc_read_setup(struct nfs_read_data *data)
{
@@ -762,23 +778,26 @@ nfs3_proc_read_setup(struct nfs_read_data *data)
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data);
rpc_call_setup(task, &msg, 0);
}
-static void
-nfs3_write_done(struct rpc_task *task)
+static void nfs3_write_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data;
+ struct nfs_write_data *data = calldata;
if (nfs3_async_handle_jukebox(task))
return;
- data = (struct nfs_write_data *)task->tk_calldata;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_writeback_done(task);
+ nfs_writeback_done(task, calldata);
}
+static const struct rpc_call_ops nfs3_write_ops = {
+ .rpc_call_done = nfs3_write_done,
+ .rpc_release = nfs_writedata_release,
+};
+
static void
nfs3_proc_write_setup(struct nfs_write_data *data, int how)
{
@@ -806,23 +825,26 @@ nfs3_proc_write_setup(struct nfs_write_data *data, int how)
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data);
rpc_call_setup(task, &msg, 0);
}
-static void
-nfs3_commit_done(struct rpc_task *task)
+static void nfs3_commit_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data;
+ struct nfs_write_data *data = calldata;
if (nfs3_async_handle_jukebox(task))
return;
- data = (struct nfs_write_data *)task->tk_calldata;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_commit_done(task);
+ nfs_commit_done(task, calldata);
}
+static const struct rpc_call_ops nfs3_commit_ops = {
+ .rpc_call_done = nfs3_commit_done,
+ .rpc_release = nfs_commit_release,
+};
+
static void
nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
{
@@ -840,7 +862,7 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data);
rpc_call_setup(task, &msg, 0);
}
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 0498bd36602c..b6c0b5012bce 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -182,7 +182,7 @@ xdr_encode_sattr(u32 *p, struct iattr *attr)
{
if (attr->ia_valid & ATTR_MODE) {
*p++ = xdr_one;
- *p++ = htonl(attr->ia_mode);
+ *p++ = htonl(attr->ia_mode & S_IALLUGO);
} else {
*p++ = xdr_zero;
}
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b7f262dcb6e3..0f5e4e7cddec 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -38,7 +38,8 @@ struct idmap;
((err) != NFSERR_NOFILEHANDLE))
enum nfs4_client_state {
- NFS4CLNT_OK = 0,
+ NFS4CLNT_STATE_RECOVER = 0,
+ NFS4CLNT_LEASE_EXPIRED,
};
/*
@@ -67,7 +68,6 @@ struct nfs4_client {
atomic_t cl_count;
struct rpc_clnt * cl_rpcclient;
- struct rpc_cred * cl_cred;
struct list_head cl_superblocks; /* List of nfs_server structs */
@@ -76,7 +76,6 @@ struct nfs4_client {
struct work_struct cl_renewd;
struct work_struct cl_recoverd;
- wait_queue_head_t cl_waitq;
struct rpc_wait_queue cl_rpcwaitq;
/* used for the setclientid verifier */
@@ -182,8 +181,9 @@ struct nfs4_state {
nfs4_stateid stateid;
- unsigned int nreaders;
- unsigned int nwriters;
+ unsigned int n_rdonly;
+ unsigned int n_wronly;
+ unsigned int n_rdwr;
int state; /* State on the server (R,W, or RW) */
atomic_t count;
};
@@ -210,10 +210,10 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
/* nfs4proc.c */
extern int nfs4_map_errors(int err);
-extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
-extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
-extern int nfs4_proc_async_renew(struct nfs4_client *);
-extern int nfs4_proc_renew(struct nfs4_client *);
+extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short, struct rpc_cred *);
+extern int nfs4_proc_setclientid_confirm(struct nfs4_client *, struct rpc_cred *);
+extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *);
+extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *);
extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
@@ -237,8 +237,8 @@ extern void init_nfsv4_state(struct nfs_server *);
extern void destroy_nfsv4_state(struct nfs_server *);
extern struct nfs4_client *nfs4_get_client(struct in_addr *);
extern void nfs4_put_client(struct nfs4_client *clp);
-extern int nfs4_init_client(struct nfs4_client *clp);
extern struct nfs4_client *nfs4_find_client(struct in_addr *);
+struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp);
extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f988a9417b13..984ca3454d04 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -57,11 +57,13 @@
#define NFS4_POLL_RETRY_MIN (1*HZ)
#define NFS4_POLL_RETRY_MAX (15*HZ)
-static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid);
+struct nfs4_opendata;
+static int _nfs4_proc_open(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
+static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp);
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
extern struct rpc_procinfo nfs4_procedures[];
@@ -173,8 +175,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
kunmap_atomic(start, KM_USER0);
}
-static void
-renew_lease(struct nfs_server *server, unsigned long timestamp)
+static void renew_lease(const struct nfs_server *server, unsigned long timestamp)
{
struct nfs4_client *clp = server->nfs4_state;
spin_lock(&clp->cl_lock);
@@ -194,21 +195,123 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
spin_unlock(&inode->i_lock);
}
+struct nfs4_opendata {
+ atomic_t count;
+ struct nfs_openargs o_arg;
+ struct nfs_openres o_res;
+ struct nfs_open_confirmargs c_arg;
+ struct nfs_open_confirmres c_res;
+ struct nfs_fattr f_attr;
+ struct nfs_fattr dir_attr;
+ struct dentry *dentry;
+ struct dentry *dir;
+ struct nfs4_state_owner *owner;
+ struct iattr attrs;
+ unsigned long timestamp;
+ int rpc_status;
+ int cancelled;
+};
+
+static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+ struct nfs4_state_owner *sp, int flags,
+ const struct iattr *attrs)
+{
+ struct dentry *parent = dget_parent(dentry);
+ struct inode *dir = parent->d_inode;
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs4_opendata *p;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
+ goto err;
+ p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
+ if (p->o_arg.seqid == NULL)
+ goto err_free;
+ atomic_set(&p->count, 1);
+ p->dentry = dget(dentry);
+ p->dir = parent;
+ p->owner = sp;
+ atomic_inc(&sp->so_count);
+ p->o_arg.fh = NFS_FH(dir);
+ p->o_arg.open_flags = flags,
+ p->o_arg.clientid = server->nfs4_state->cl_clientid;
+ p->o_arg.id = sp->so_id;
+ p->o_arg.name = &dentry->d_name;
+ p->o_arg.server = server;
+ p->o_arg.bitmask = server->attr_bitmask;
+ p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
+ p->o_res.f_attr = &p->f_attr;
+ p->o_res.dir_attr = &p->dir_attr;
+ p->o_res.server = server;
+ nfs_fattr_init(&p->f_attr);
+ nfs_fattr_init(&p->dir_attr);
+ if (flags & O_EXCL) {
+ u32 *s = (u32 *) p->o_arg.u.verifier.data;
+ s[0] = jiffies;
+ s[1] = current->pid;
+ } else if (flags & O_CREAT) {
+ p->o_arg.u.attrs = &p->attrs;
+ memcpy(&p->attrs, attrs, sizeof(p->attrs));
+ }
+ p->c_arg.fh = &p->o_res.fh;
+ p->c_arg.stateid = &p->o_res.stateid;
+ p->c_arg.seqid = p->o_arg.seqid;
+ return p;
+err_free:
+ kfree(p);
+err:
+ dput(parent);
+ return NULL;
+}
+
+static void nfs4_opendata_free(struct nfs4_opendata *p)
+{
+ if (p != NULL && atomic_dec_and_test(&p->count)) {
+ nfs_free_seqid(p->o_arg.seqid);
+ nfs4_put_state_owner(p->owner);
+ dput(p->dir);
+ dput(p->dentry);
+ kfree(p);
+ }
+}
+
/* Helper for asynchronous RPC calls */
-static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin,
- rpc_action tk_exit, void *calldata)
+static int nfs4_call_async(struct rpc_clnt *clnt,
+ const struct rpc_call_ops *tk_ops, void *calldata)
{
struct rpc_task *task;
- if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC)))
+ if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
return -ENOMEM;
-
- task->tk_calldata = calldata;
- task->tk_action = tk_begin;
rpc_execute(task);
return 0;
}
+static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
+{
+ sigset_t oldset;
+ int ret;
+
+ rpc_clnt_sigmask(task->tk_client, &oldset);
+ ret = rpc_wait_for_completion_task(task);
+ rpc_clnt_sigunmask(task->tk_client, &oldset);
+ return ret;
+}
+
+static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
+{
+ switch (open_flags) {
+ case FMODE_WRITE:
+ state->n_wronly++;
+ break;
+ case FMODE_READ:
+ state->n_rdonly++;
+ break;
+ case FMODE_READ|FMODE_WRITE:
+ state->n_rdwr++;
+ }
+}
+
static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
{
struct inode *inode = state->inode;
@@ -218,41 +321,134 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
spin_lock(&state->owner->so_lock);
spin_lock(&inode->i_lock);
memcpy(&state->stateid, stateid, sizeof(state->stateid));
- if ((open_flags & FMODE_WRITE))
- state->nwriters++;
- if (open_flags & FMODE_READ)
- state->nreaders++;
+ update_open_stateflags(state, open_flags);
nfs4_state_set_mode_locked(state, state->state | open_flags);
spin_unlock(&inode->i_lock);
spin_unlock(&state->owner->so_lock);
}
+static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
+{
+ struct inode *inode;
+ struct nfs4_state *state = NULL;
+
+ if (!(data->f_attr.valid & NFS_ATTR_FATTR))
+ goto out;
+ inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+ if (inode == NULL)
+ goto out;
+ state = nfs4_get_open_state(inode, data->owner);
+ if (state == NULL)
+ goto put_inode;
+ update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
+put_inode:
+ iput(inode);
+out:
+ return state;
+}
+
+static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
+{
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_open_context *ctx;
+
+ spin_lock(&state->inode->i_lock);
+ list_for_each_entry(ctx, &nfsi->open_files, list) {
+ if (ctx->state != state)
+ continue;
+ get_nfs_open_context(ctx);
+ spin_unlock(&state->inode->i_lock);
+ return ctx;
+ }
+ spin_unlock(&state->inode->i_lock);
+ return ERR_PTR(-ENOENT);
+}
+
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, nfs4_stateid *stateid)
+{
+ int ret;
+
+ opendata->o_arg.open_flags = openflags;
+ ret = _nfs4_proc_open(opendata);
+ if (ret != 0)
+ return ret;
+ memcpy(stateid->data, opendata->o_res.stateid.data,
+ sizeof(stateid->data));
+ return 0;
+}
+
+static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
+{
+ nfs4_stateid stateid;
+ struct nfs4_state *newstate;
+ int mode = 0;
+ int delegation = 0;
+ int ret;
+
+ /* memory barrier prior to reading state->n_* */
+ smp_rmb();
+ if (state->n_rdwr != 0) {
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &stateid);
+ if (ret != 0)
+ return ret;
+ mode |= FMODE_READ|FMODE_WRITE;
+ if (opendata->o_res.delegation_type != 0)
+ delegation = opendata->o_res.delegation_type;
+ smp_rmb();
+ }
+ if (state->n_wronly != 0) {
+ ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &stateid);
+ if (ret != 0)
+ return ret;
+ mode |= FMODE_WRITE;
+ if (opendata->o_res.delegation_type != 0)
+ delegation = opendata->o_res.delegation_type;
+ smp_rmb();
+ }
+ if (state->n_rdonly != 0) {
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ, &stateid);
+ if (ret != 0)
+ return ret;
+ mode |= FMODE_READ;
+ }
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+ if (mode == 0)
+ return 0;
+ if (opendata->o_res.delegation_type == 0)
+ opendata->o_res.delegation_type = delegation;
+ opendata->o_arg.open_flags |= mode;
+ newstate = nfs4_opendata_to_nfs4_state(opendata);
+ if (newstate != NULL) {
+ if (opendata->o_res.delegation_type != 0) {
+ struct nfs_inode *nfsi = NFS_I(newstate->inode);
+ int delegation_flags = 0;
+ if (nfsi->delegation)
+ delegation_flags = nfsi->delegation->flags;
+ if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
+ nfs_inode_set_delegation(newstate->inode,
+ opendata->owner->so_cred,
+ &opendata->o_res);
+ else
+ nfs_inode_reclaim_delegation(newstate->inode,
+ opendata->owner->so_cred,
+ &opendata->o_res);
+ }
+ nfs4_close_state(newstate, opendata->o_arg.open_flags);
+ }
+ if (newstate != state)
+ return -ESTALE;
+ return 0;
+}
+
/*
* OPEN_RECLAIM:
* reclaim state on the server after a reboot.
*/
-static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
{
- struct inode *inode = state->inode;
- struct nfs_server *server = NFS_SERVER(inode);
- struct nfs_delegation *delegation = NFS_I(inode)->delegation;
- struct nfs_openargs o_arg = {
- .fh = NFS_FH(inode),
- .id = sp->so_id,
- .open_flags = state->state,
- .clientid = server->nfs4_state->cl_clientid,
- .claim = NFS4_OPEN_CLAIM_PREVIOUS,
- .bitmask = server->attr_bitmask,
- };
- struct nfs_openres o_res = {
- .server = server, /* Grrr */
- };
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
- .rpc_argp = &o_arg,
- .rpc_resp = &o_res,
- .rpc_cred = sp->so_cred,
- };
+ struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
+ struct nfs4_opendata *opendata;
+ int delegation_type = 0;
int status;
if (delegation != NULL) {
@@ -262,38 +458,27 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st
set_bit(NFS_DELEGATED_STATE, &state->flags);
return 0;
}
- o_arg.u.delegation_type = delegation->type;
+ delegation_type = delegation->type;
}
- o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
- if (o_arg.seqid == NULL)
+ opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+ if (opendata == NULL)
return -ENOMEM;
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- /* Confirm the sequence as being established */
- nfs_confirm_seqid(&sp->so_seqid, status);
- nfs_increment_open_seqid(status, o_arg.seqid);
- if (status == 0) {
- memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
- if (o_res.delegation_type != 0) {
- nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
- /* Did the server issue an immediate delegation recall? */
- if (o_res.do_recall)
- nfs_async_inode_return_delegation(inode, &o_res.stateid);
- }
- }
- nfs_free_seqid(o_arg.seqid);
- clear_bit(NFS_DELEGATED_STATE, &state->flags);
- /* Ensure we update the inode attributes */
- NFS_CACHEINV(inode);
+ opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
+ opendata->o_arg.fh = NFS_FH(state->inode);
+ nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
+ opendata->o_arg.u.delegation_type = delegation_type;
+ status = nfs4_open_recover(opendata, state);
+ nfs4_opendata_free(opendata);
return status;
}
-static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
int err;
do {
- err = _nfs4_open_reclaim(sp, state);
+ err = _nfs4_do_open_reclaim(sp, state, dentry);
if (err != -NFS4ERR_DELAY)
break;
nfs4_handle_exception(server, err, &exception);
@@ -301,63 +486,36 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
return err;
}
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+ struct nfs_open_context *ctx;
+ int ret;
+
+ ctx = nfs4_state_find_open_context(state);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+ ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
+ put_nfs_open_context(ctx);
+ return ret;
+}
+
static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
{
struct nfs4_state_owner *sp = state->owner;
- struct inode *inode = dentry->d_inode;
- struct nfs_server *server = NFS_SERVER(inode);
- struct dentry *parent = dget_parent(dentry);
- struct nfs_openargs arg = {
- .fh = NFS_FH(parent->d_inode),
- .clientid = server->nfs4_state->cl_clientid,
- .name = &dentry->d_name,
- .id = sp->so_id,
- .server = server,
- .bitmask = server->attr_bitmask,
- .claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
- };
- struct nfs_openres res = {
- .server = server,
- };
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- .rpc_cred = sp->so_cred,
- };
- int status = 0;
+ struct nfs4_opendata *opendata;
+ int ret;
if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
- goto out;
- if (state->state == 0)
- goto out;
- arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
- status = -ENOMEM;
- if (arg.seqid == NULL)
- goto out;
- arg.open_flags = state->state;
- memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- nfs_increment_open_seqid(status, arg.seqid);
- if (status != 0)
- goto out_free;
- if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
- status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode),
- sp, &res.stateid, arg.seqid);
- if (status != 0)
- goto out_free;
- }
- nfs_confirm_seqid(&sp->so_seqid, 0);
- if (status >= 0) {
- memcpy(state->stateid.data, res.stateid.data,
- sizeof(state->stateid.data));
- clear_bit(NFS_DELEGATED_STATE, &state->flags);
- }
-out_free:
- nfs_free_seqid(arg.seqid);
-out:
- dput(parent);
- return status;
+ return 0;
+ opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+ if (opendata == NULL)
+ return -ENOMEM;
+ opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
+ memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
+ sizeof(opendata->o_arg.u.delegation.data));
+ ret = nfs4_open_recover(opendata, state);
+ nfs4_opendata_free(opendata);
+ return ret;
}
int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
@@ -382,82 +540,202 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
return err;
}
-static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid)
+static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata)
{
- struct nfs_open_confirmargs arg = {
- .fh = fh,
- .seqid = seqid,
- .stateid = *stateid,
- };
- struct nfs_open_confirmres res;
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- .rpc_cred = sp->so_cred,
+ struct nfs4_opendata *data = calldata;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
+ .rpc_argp = &data->c_arg,
+ .rpc_resp = &data->c_res,
+ .rpc_cred = data->owner->so_cred,
};
+ data->timestamp = jiffies;
+ rpc_call_setup(task, &msg, 0);
+}
+
+static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_opendata *data = calldata;
+
+ data->rpc_status = task->tk_status;
+ if (RPC_ASSASSINATED(task))
+ return;
+ if (data->rpc_status == 0) {
+ memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
+ sizeof(data->o_res.stateid.data));
+ renew_lease(data->o_res.server, data->timestamp);
+ }
+ nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
+ nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
+}
+
+static void nfs4_open_confirm_release(void *calldata)
+{
+ struct nfs4_opendata *data = calldata;
+ struct nfs4_state *state = NULL;
+
+ /* If this request hasn't been cancelled, do nothing */
+ if (data->cancelled == 0)
+ goto out_free;
+ /* In case of error, no cleanup! */
+ if (data->rpc_status != 0)
+ goto out_free;
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
+ state = nfs4_opendata_to_nfs4_state(data);
+ if (state != NULL)
+ nfs4_close_state(state, data->o_arg.open_flags);
+out_free:
+ nfs4_opendata_free(data);
+}
+
+static const struct rpc_call_ops nfs4_open_confirm_ops = {
+ .rpc_call_prepare = nfs4_open_confirm_prepare,
+ .rpc_call_done = nfs4_open_confirm_done,
+ .rpc_release = nfs4_open_confirm_release,
+};
+
+/*
+ * Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata
+ */
+static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
+{
+ struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
+ struct rpc_task *task;
int status;
- status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
- /* Confirm the sequence as being established */
- nfs_confirm_seqid(&sp->so_seqid, status);
- nfs_increment_open_seqid(status, seqid);
- if (status >= 0)
- memcpy(stateid, &res.stateid, sizeof(*stateid));
+ atomic_inc(&data->count);
+ task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
+ if (IS_ERR(task)) {
+ nfs4_opendata_free(data);
+ return PTR_ERR(task);
+ }
+ status = nfs4_wait_for_completion_rpc_task(task);
+ if (status != 0) {
+ data->cancelled = 1;
+ smp_wmb();
+ } else
+ status = data->rpc_status;
+ rpc_release_task(task);
return status;
}
-static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
+static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
{
- struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs4_opendata *data = calldata;
+ struct nfs4_state_owner *sp = data->owner;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
- .rpc_argp = o_arg,
- .rpc_resp = o_res,
+ .rpc_argp = &data->o_arg,
+ .rpc_resp = &data->o_res,
.rpc_cred = sp->so_cred,
};
- int status;
+
+ if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
+ return;
+ /* Update sequence id. */
+ data->o_arg.id = sp->so_id;
+ data->o_arg.clientid = sp->so_client->cl_clientid;
+ if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
+ msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
+ data->timestamp = jiffies;
+ rpc_call_setup(task, &msg, 0);
+}
- /* Update sequence id. The caller must serialize! */
- o_arg->id = sp->so_id;
- o_arg->clientid = sp->so_client->cl_clientid;
+static void nfs4_open_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_opendata *data = calldata;
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- if (status == 0) {
- /* OPEN on anything except a regular file is disallowed in NFSv4 */
- switch (o_res->f_attr->mode & S_IFMT) {
+ data->rpc_status = task->tk_status;
+ if (RPC_ASSASSINATED(task))
+ return;
+ if (task->tk_status == 0) {
+ switch (data->o_res.f_attr->mode & S_IFMT) {
case S_IFREG:
break;
case S_IFLNK:
- status = -ELOOP;
+ data->rpc_status = -ELOOP;
break;
case S_IFDIR:
- status = -EISDIR;
+ data->rpc_status = -EISDIR;
break;
default:
- status = -ENOTDIR;
+ data->rpc_status = -ENOTDIR;
}
+ renew_lease(data->o_res.server, data->timestamp);
}
+ nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+}
+
+static void nfs4_open_release(void *calldata)
+{
+ struct nfs4_opendata *data = calldata;
+ struct nfs4_state *state = NULL;
- nfs_increment_open_seqid(status, o_arg->seqid);
+ /* If this request hasn't been cancelled, do nothing */
+ if (data->cancelled == 0)
+ goto out_free;
+ /* In case of error, no cleanup! */
+ if (data->rpc_status != 0)
+ goto out_free;
+ /* In case we need an open_confirm, no cleanup! */
+ if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
+ goto out_free;
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
+ state = nfs4_opendata_to_nfs4_state(data);
+ if (state != NULL)
+ nfs4_close_state(state, data->o_arg.open_flags);
+out_free:
+ nfs4_opendata_free(data);
+}
+
+static const struct rpc_call_ops nfs4_open_ops = {
+ .rpc_call_prepare = nfs4_open_prepare,
+ .rpc_call_done = nfs4_open_done,
+ .rpc_release = nfs4_open_release,
+};
+
+/*
+ * Note: On error, nfs4_proc_open will free the struct nfs4_opendata
+ */
+static int _nfs4_proc_open(struct nfs4_opendata *data)
+{
+ struct inode *dir = data->dir->d_inode;
+ struct nfs_server *server = NFS_SERVER(dir);
+ struct nfs_openargs *o_arg = &data->o_arg;
+ struct nfs_openres *o_res = &data->o_res;
+ struct rpc_task *task;
+ int status;
+
+ atomic_inc(&data->count);
+ task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
+ if (IS_ERR(task)) {
+ nfs4_opendata_free(data);
+ return PTR_ERR(task);
+ }
+ status = nfs4_wait_for_completion_rpc_task(task);
+ if (status != 0) {
+ data->cancelled = 1;
+ smp_wmb();
+ } else
+ status = data->rpc_status;
+ rpc_release_task(task);
if (status != 0)
- goto out;
+ return status;
+
if (o_arg->open_flags & O_CREAT) {
update_changeattr(dir, &o_res->cinfo);
nfs_post_op_update_inode(dir, o_res->dir_attr);
} else
nfs_refresh_inode(dir, o_res->dir_attr);
if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
- status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
- sp, &o_res->stateid, o_arg->seqid);
+ status = _nfs4_proc_open_confirm(data);
if (status != 0)
- goto out;
+ return status;
}
- nfs_confirm_seqid(&sp->so_seqid, 0);
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
- status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
-out:
- return status;
+ return server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
+ return 0;
}
static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
@@ -488,6 +766,15 @@ out:
return -EACCES;
}
+int nfs4_recover_expired_lease(struct nfs_server *server)
+{
+ struct nfs4_client *clp = server->nfs4_state;
+
+ if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
+ nfs4_schedule_state_recovery(clp);
+ return nfs4_wait_clnt_recover(server->client, clp);
+}
+
/*
* OPEN_EXPIRED:
* reclaim state on the server after a network partition.
@@ -495,77 +782,31 @@ out:
*/
static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
{
- struct dentry *parent = dget_parent(dentry);
- struct inode *dir = parent->d_inode;
struct inode *inode = state->inode;
- struct nfs_server *server = NFS_SERVER(dir);
struct nfs_delegation *delegation = NFS_I(inode)->delegation;
- struct nfs_fattr f_attr, dir_attr;
- struct nfs_openargs o_arg = {
- .fh = NFS_FH(dir),
- .open_flags = state->state,
- .name = &dentry->d_name,
- .bitmask = server->attr_bitmask,
- .claim = NFS4_OPEN_CLAIM_NULL,
- };
- struct nfs_openres o_res = {
- .f_attr = &f_attr,
- .dir_attr = &dir_attr,
- .server = server,
- };
- int status = 0;
+ struct nfs4_opendata *opendata;
+ int openflags = state->state & (FMODE_READ|FMODE_WRITE);
+ int ret;
if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
- status = _nfs4_do_access(inode, sp->so_cred, state->state);
- if (status < 0)
- goto out;
+ ret = _nfs4_do_access(inode, sp->so_cred, openflags);
+ if (ret < 0)
+ return ret;
memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
set_bit(NFS_DELEGATED_STATE, &state->flags);
- goto out;
+ return 0;
}
- o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
- status = -ENOMEM;
- if (o_arg.seqid == NULL)
- goto out;
- nfs_fattr_init(&f_attr);
- nfs_fattr_init(&dir_attr);
- status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
- if (status != 0)
- goto out_nodeleg;
- /* Check if files differ */
- if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
- goto out_stale;
- /* Has the file handle changed? */
- if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) {
- /* Verify if the change attributes are the same */
- if (f_attr.change_attr != NFS_I(inode)->change_attr)
- goto out_stale;
- if (nfs_size_to_loff_t(f_attr.size) != inode->i_size)
- goto out_stale;
- /* Lets just pretend that this is the same file */
- nfs_copy_fh(NFS_FH(inode), &o_res.fh);
- NFS_I(inode)->fileid = f_attr.fileid;
- }
- memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
- if (o_res.delegation_type != 0) {
- if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
- nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
- else
- nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+ opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
+ if (opendata == NULL)
+ return -ENOMEM;
+ ret = nfs4_open_recover(opendata, state);
+ if (ret == -ESTALE) {
+ /* Invalidate the state owner so we don't ever use it again */
+ nfs4_drop_state_owner(sp);
+ d_drop(dentry);
}
-out_nodeleg:
- nfs_free_seqid(o_arg.seqid);
- clear_bit(NFS_DELEGATED_STATE, &state->flags);
-out:
- dput(parent);
- return status;
-out_stale:
- status = -ESTALE;
- /* Invalidate the state owner so we don't ever use it again */
- nfs4_drop_state_owner(sp);
- d_drop(dentry);
- /* Should we be trying to close that stateid? */
- goto out_nodeleg;
+ nfs4_opendata_free(opendata);
+ return ret;
}
static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
@@ -584,26 +825,19 @@ static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_
static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
- struct nfs_inode *nfsi = NFS_I(state->inode);
struct nfs_open_context *ctx;
- int status;
+ int ret;
- spin_lock(&state->inode->i_lock);
- list_for_each_entry(ctx, &nfsi->open_files, list) {
- if (ctx->state != state)
- continue;
- get_nfs_open_context(ctx);
- spin_unlock(&state->inode->i_lock);
- status = nfs4_do_open_expired(sp, state, ctx->dentry);
- put_nfs_open_context(ctx);
- return status;
- }
- spin_unlock(&state->inode->i_lock);
- return -ENOENT;
+ ctx = nfs4_state_find_open_context(state);
+ if (IS_ERR(ctx))
+ return PTR_ERR(ctx);
+ ret = nfs4_do_open_expired(sp, state, ctx->dentry);
+ put_nfs_open_context(ctx);
+ return ret;
}
/*
- * Returns an nfs4_state + an extra reference to the inode
+ * Returns a referenced nfs4_state if there is an open delegation on the file
*/
static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
{
@@ -616,6 +850,14 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
int open_flags = flags & (FMODE_READ|FMODE_WRITE);
int err;
+ err = -ENOMEM;
+ if (!(sp = nfs4_get_state_owner(server, cred))) {
+ dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
+ return err;
+ }
+ err = nfs4_recover_expired_lease(server);
+ if (err != 0)
+ goto out_put_state_owner;
/* Protect against reboot recovery - NOTE ORDER! */
down_read(&clp->cl_sem);
/* Protect against delegation recall */
@@ -625,10 +867,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
if (delegation == NULL || (delegation->type & open_flags) != open_flags)
goto out_err;
err = -ENOMEM;
- if (!(sp = nfs4_get_state_owner(server, cred))) {
- dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
- goto out_err;
- }
state = nfs4_get_open_state(inode, sp);
if (state == NULL)
goto out_err;
@@ -636,39 +874,34 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred
err = -ENOENT;
if ((state->state & open_flags) == open_flags) {
spin_lock(&inode->i_lock);
- if (open_flags & FMODE_READ)
- state->nreaders++;
- if (open_flags & FMODE_WRITE)
- state->nwriters++;
+ update_open_stateflags(state, open_flags);
spin_unlock(&inode->i_lock);
goto out_ok;
} else if (state->state != 0)
- goto out_err;
+ goto out_put_open_state;
lock_kernel();
err = _nfs4_do_access(inode, cred, open_flags);
unlock_kernel();
if (err != 0)
- goto out_err;
+ goto out_put_open_state;
set_bit(NFS_DELEGATED_STATE, &state->flags);
update_open_stateid(state, &delegation->stateid, open_flags);
out_ok:
nfs4_put_state_owner(sp);
up_read(&nfsi->rwsem);
up_read(&clp->cl_sem);
- igrab(inode);
*res = state;
- return 0;
+ return 0;
+out_put_open_state:
+ nfs4_put_open_state(state);
out_err:
- if (sp != NULL) {
- if (state != NULL)
- nfs4_put_open_state(state);
- nfs4_put_state_owner(sp);
- }
up_read(&nfsi->rwsem);
up_read(&clp->cl_sem);
if (err != -EACCES)
nfs_inode_return_delegation(inode);
+out_put_state_owner:
+ nfs4_put_state_owner(sp);
return err;
}
@@ -689,7 +922,7 @@ static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, st
}
/*
- * Returns an nfs4_state + an referenced inode
+ * Returns a referenced nfs4_state
*/
static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
{
@@ -697,73 +930,46 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
struct nfs4_state *state = NULL;
struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_client *clp = server->nfs4_state;
- struct inode *inode = NULL;
+ struct nfs4_opendata *opendata;
int status;
- struct nfs_fattr f_attr, dir_attr;
- struct nfs_openargs o_arg = {
- .fh = NFS_FH(dir),
- .open_flags = flags,
- .name = &dentry->d_name,
- .server = server,
- .bitmask = server->attr_bitmask,
- .claim = NFS4_OPEN_CLAIM_NULL,
- };
- struct nfs_openres o_res = {
- .f_attr = &f_attr,
- .dir_attr = &dir_attr,
- .server = server,
- };
/* Protect against reboot recovery conflicts */
- down_read(&clp->cl_sem);
status = -ENOMEM;
if (!(sp = nfs4_get_state_owner(server, cred))) {
dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
goto out_err;
}
- if (flags & O_EXCL) {
- u32 *p = (u32 *) o_arg.u.verifier.data;
- p[0] = jiffies;
- p[1] = current->pid;
- } else
- o_arg.u.attrs = sattr;
- /* Serialization for the sequence id */
+ status = nfs4_recover_expired_lease(server);
+ if (status != 0)
+ goto err_put_state_owner;
+ down_read(&clp->cl_sem);
+ status = -ENOMEM;
+ opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
+ if (opendata == NULL)
+ goto err_put_state_owner;
- o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
- if (o_arg.seqid == NULL)
- return -ENOMEM;
- nfs_fattr_init(&f_attr);
- nfs_fattr_init(&dir_attr);
- status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+ status = _nfs4_proc_open(opendata);
if (status != 0)
- goto out_err;
+ goto err_opendata_free;
status = -ENOMEM;
- inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
- if (!inode)
- goto out_err;
- state = nfs4_get_open_state(inode, sp);
- if (!state)
- goto out_err;
- update_open_stateid(state, &o_res.stateid, flags);
- if (o_res.delegation_type != 0)
- nfs_inode_set_delegation(inode, cred, &o_res);
- nfs_free_seqid(o_arg.seqid);
+ state = nfs4_opendata_to_nfs4_state(opendata);
+ if (state == NULL)
+ goto err_opendata_free;
+ if (opendata->o_res.delegation_type != 0)
+ nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
+ nfs4_opendata_free(opendata);
nfs4_put_state_owner(sp);
up_read(&clp->cl_sem);
*res = state;
return 0;
+err_opendata_free:
+ nfs4_opendata_free(opendata);
+err_put_state_owner:
+ nfs4_put_state_owner(sp);
out_err:
- if (sp != NULL) {
- if (state != NULL)
- nfs4_put_open_state(state);
- nfs_free_seqid(o_arg.seqid);
- nfs4_put_state_owner(sp);
- }
/* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
up_read(&clp->cl_sem);
- if (inode != NULL)
- iput(inode);
*res = NULL;
return status;
}
@@ -830,6 +1036,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
.rpc_argp = &arg,
.rpc_resp = &res,
};
+ unsigned long timestamp = jiffies;
int status;
nfs_fattr_init(fattr);
@@ -841,6 +1048,8 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
status = rpc_call_sync(server->client, &msg, 0);
+ if (status == 0 && state != NULL)
+ renew_lease(server, timestamp);
return status;
}
@@ -865,12 +1074,13 @@ struct nfs4_closedata {
struct nfs_closeargs arg;
struct nfs_closeres res;
struct nfs_fattr fattr;
+ unsigned long timestamp;
};
-static void nfs4_free_closedata(struct nfs4_closedata *calldata)
+static void nfs4_free_closedata(void *data)
{
- struct nfs4_state *state = calldata->state;
- struct nfs4_state_owner *sp = state->owner;
+ struct nfs4_closedata *calldata = data;
+ struct nfs4_state_owner *sp = calldata->state->owner;
nfs4_put_open_state(calldata->state);
nfs_free_seqid(calldata->arg.seqid);
@@ -878,12 +1088,14 @@ static void nfs4_free_closedata(struct nfs4_closedata *calldata)
kfree(calldata);
}
-static void nfs4_close_done(struct rpc_task *task)
+static void nfs4_close_done(struct rpc_task *task, void *data)
{
- struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+ struct nfs4_closedata *calldata = data;
struct nfs4_state *state = calldata->state;
struct nfs_server *server = NFS_SERVER(calldata->inode);
+ if (RPC_ASSASSINATED(task))
+ return;
/* hmm. we are done with the inode, and in the process of freeing
* the state_owner. we keep this around to process errors
*/
@@ -892,6 +1104,7 @@ static void nfs4_close_done(struct rpc_task *task)
case 0:
memcpy(&state->stateid, &calldata->res.stateid,
sizeof(state->stateid));
+ renew_lease(server, calldata->timestamp);
break;
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
@@ -904,12 +1117,11 @@ static void nfs4_close_done(struct rpc_task *task)
}
}
nfs_refresh_inode(calldata->inode, calldata->res.fattr);
- nfs4_free_closedata(calldata);
}
-static void nfs4_close_begin(struct rpc_task *task)
+static void nfs4_close_prepare(struct rpc_task *task, void *data)
{
- struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata;
+ struct nfs4_closedata *calldata = data;
struct nfs4_state *state = calldata->state;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
@@ -918,10 +1130,8 @@ static void nfs4_close_begin(struct rpc_task *task)
.rpc_cred = state->owner->so_cred,
};
int mode = 0, old_mode;
- int status;
- status = nfs_wait_on_sequence(calldata->arg.seqid, task);
- if (status != 0)
+ if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
return;
/* Recalculate the new open mode in case someone reopened the file
* while we were waiting in line to be scheduled.
@@ -929,26 +1139,34 @@ static void nfs4_close_begin(struct rpc_task *task)
spin_lock(&state->owner->so_lock);
spin_lock(&calldata->inode->i_lock);
mode = old_mode = state->state;
- if (state->nreaders == 0)
- mode &= ~FMODE_READ;
- if (state->nwriters == 0)
- mode &= ~FMODE_WRITE;
+ if (state->n_rdwr == 0) {
+ if (state->n_rdonly == 0)
+ mode &= ~FMODE_READ;
+ if (state->n_wronly == 0)
+ mode &= ~FMODE_WRITE;
+ }
nfs4_state_set_mode_locked(state, mode);
spin_unlock(&calldata->inode->i_lock);
spin_unlock(&state->owner->so_lock);
if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
- nfs4_free_closedata(calldata);
- task->tk_exit = NULL;
- rpc_exit(task, 0);
+ /* Note: exit _without_ calling nfs4_close_done */
+ task->tk_action = NULL;
return;
}
nfs_fattr_init(calldata->res.fattr);
if (mode != 0)
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
calldata->arg.open_flags = mode;
+ calldata->timestamp = jiffies;
rpc_call_setup(task, &msg, 0);
}
+static const struct rpc_call_ops nfs4_close_ops = {
+ .rpc_call_prepare = nfs4_close_prepare,
+ .rpc_call_done = nfs4_close_done,
+ .rpc_release = nfs4_free_closedata,
+};
+
/*
* It is possible for data to be read/written from a mem-mapped file
* after the sys_close call (which hits the vfs layer as a flush).
@@ -981,8 +1199,7 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
calldata->res.fattr = &calldata->fattr;
calldata->res.server = server;
- status = nfs4_call_async(server->client, nfs4_close_begin,
- nfs4_close_done, calldata);
+ status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
if (status == 0)
goto out;
@@ -1034,7 +1251,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
d_add(dentry, NULL);
return (struct dentry *)state;
}
- res = d_add_unique(dentry, state->inode);
+ res = d_add_unique(dentry, igrab(state->inode));
if (res != NULL)
dentry = res;
nfs4_intent_set_file(nd, dentry, state);
@@ -1046,7 +1263,6 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
{
struct rpc_cred *cred;
struct nfs4_state *state;
- struct inode *inode;
cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
if (IS_ERR(cred))
@@ -1070,9 +1286,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
}
goto out_drop;
}
- inode = state->inode;
- iput(inode);
- if (inode == dentry->d_inode) {
+ if (state->inode == dentry->d_inode) {
nfs4_intent_set_file(nd, dentry, state);
return 1;
}
@@ -1508,11 +1722,13 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata)
wdata->args.bitmask = server->attr_bitmask;
wdata->res.server = server;
+ wdata->timestamp = jiffies;
nfs_fattr_init(fattr);
status = rpc_call_sync(server->client, &msg, rpcflags);
dprintk("NFS reply write: %d\n", status);
if (status < 0)
return status;
+ renew_lease(server, wdata->timestamp);
nfs_post_op_update_inode(inode, fattr);
return wdata->res.count;
}
@@ -1547,8 +1763,11 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata)
cdata->args.bitmask = server->attr_bitmask;
cdata->res.server = server;
+ cdata->timestamp = jiffies;
nfs_fattr_init(fattr);
status = rpc_call_sync(server->client, &msg, 0);
+ if (status >= 0)
+ renew_lease(server, cdata->timestamp);
dprintk("NFS reply commit: %d\n", status);
if (status >= 0)
nfs_post_op_update_inode(inode, fattr);
@@ -1601,7 +1820,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
status = PTR_ERR(state);
goto out;
}
- d_instantiate(dentry, state->inode);
+ d_instantiate(dentry, igrab(state->inode));
if (flags & O_EXCL) {
struct nfs_fattr fattr;
status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
@@ -2125,10 +2344,9 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
return err;
}
-static void
-nfs4_read_done(struct rpc_task *task)
+static void nfs4_read_done(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
+ struct nfs_read_data *data = calldata;
struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2138,9 +2356,14 @@ nfs4_read_done(struct rpc_task *task)
if (task->tk_status > 0)
renew_lease(NFS_SERVER(inode), data->timestamp);
/* Call back common NFS readpage processing */
- nfs_readpage_result(task);
+ nfs_readpage_result(task, calldata);
}
+static const struct rpc_call_ops nfs4_read_ops = {
+ .rpc_call_done = nfs4_read_done,
+ .rpc_release = nfs_readdata_release,
+};
+
static void
nfs4_proc_read_setup(struct nfs_read_data *data)
{
@@ -2160,14 +2383,13 @@ nfs4_proc_read_setup(struct nfs_read_data *data)
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data);
rpc_call_setup(task, &msg, 0);
}
-static void
-nfs4_write_done(struct rpc_task *task)
+static void nfs4_write_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+ struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2179,9 +2401,14 @@ nfs4_write_done(struct rpc_task *task)
nfs_post_op_update_inode(inode, data->res.fattr);
}
/* Call back common NFS writeback processing */
- nfs_writeback_done(task);
+ nfs_writeback_done(task, calldata);
}
+static const struct rpc_call_ops nfs4_write_ops = {
+ .rpc_call_done = nfs4_write_done,
+ .rpc_release = nfs_writedata_release,
+};
+
static void
nfs4_proc_write_setup(struct nfs_write_data *data, int how)
{
@@ -2214,14 +2441,13 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how)
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data);
rpc_call_setup(task, &msg, 0);
}
-static void
-nfs4_commit_done(struct rpc_task *task)
+static void nfs4_commit_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+ struct nfs_write_data *data = calldata;
struct inode *inode = data->inode;
if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
@@ -2231,9 +2457,14 @@ nfs4_commit_done(struct rpc_task *task)
if (task->tk_status >= 0)
nfs_post_op_update_inode(inode, data->res.fattr);
/* Call back common NFS writeback processing */
- nfs_commit_done(task);
+ nfs_commit_done(task, calldata);
}
+static const struct rpc_call_ops nfs4_commit_ops = {
+ .rpc_call_done = nfs4_commit_done,
+ .rpc_release = nfs_commit_release,
+};
+
static void
nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
{
@@ -2255,7 +2486,7 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data);
rpc_call_setup(task, &msg, 0);
}
@@ -2263,11 +2494,10 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how)
* nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special
* standalone procedure for queueing an asynchronous RENEW.
*/
-static void
-renew_done(struct rpc_task *task)
+static void nfs4_renew_done(struct rpc_task *task, void *data)
{
struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
- unsigned long timestamp = (unsigned long)task->tk_calldata;
+ unsigned long timestamp = (unsigned long)data;
if (task->tk_status < 0) {
switch (task->tk_status) {
@@ -2284,26 +2514,28 @@ renew_done(struct rpc_task *task)
spin_unlock(&clp->cl_lock);
}
-int
-nfs4_proc_async_renew(struct nfs4_client *clp)
+static const struct rpc_call_ops nfs4_renew_ops = {
+ .rpc_call_done = nfs4_renew_done,
+};
+
+int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred)
{
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
.rpc_argp = clp,
- .rpc_cred = clp->cl_cred,
+ .rpc_cred = cred,
};
return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT,
- renew_done, (void *)jiffies);
+ &nfs4_renew_ops, (void *)jiffies);
}
-int
-nfs4_proc_renew(struct nfs4_client *clp)
+int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred)
{
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
.rpc_argp = clp,
- .rpc_cred = clp->cl_cred,
+ .rpc_cred = cred,
};
unsigned long now = jiffies;
int status;
@@ -2519,7 +2751,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
case -NFS4ERR_EXPIRED:
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
nfs4_schedule_state_recovery(clp);
- if (test_bit(NFS4CLNT_OK, &clp->cl_state))
+ if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
rpc_wake_up_task(task);
task->tk_status = 0;
return -EAGAIN;
@@ -2536,25 +2768,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
return 0;
}
+static int nfs4_wait_bit_interruptible(void *word)
+{
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ schedule();
+ return 0;
+}
+
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
{
- DEFINE_WAIT(wait);
sigset_t oldset;
- int interruptible, res = 0;
+ int res;
might_sleep();
rpc_clnt_sigmask(clnt, &oldset);
- interruptible = TASK_UNINTERRUPTIBLE;
- if (clnt->cl_intr)
- interruptible = TASK_INTERRUPTIBLE;
- prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
- nfs4_schedule_state_recovery(clp);
- if (clnt->cl_intr && signalled())
- res = -ERESTARTSYS;
- else if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
- schedule();
- finish_wait(&clp->cl_waitq, &wait);
+ res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
+ nfs4_wait_bit_interruptible,
+ TASK_INTERRUPTIBLE);
rpc_clnt_sigunmask(clnt, &oldset);
return res;
}
@@ -2597,6 +2829,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
+ nfs4_schedule_state_recovery(clp);
ret = nfs4_wait_clnt_recover(server->client, clp);
if (ret == 0)
exception->retry = 1;
@@ -2613,7 +2846,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct
return nfs4_map_errors(ret);
}
-int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
+int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port, struct rpc_cred *cred)
{
nfs4_verifier sc_verifier;
struct nfs4_setclientid setclientid = {
@@ -2624,7 +2857,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
.rpc_argp = &setclientid,
.rpc_resp = clp,
- .rpc_cred = clp->cl_cred,
+ .rpc_cred = cred,
};
u32 *p;
int loop = 0;
@@ -2638,7 +2871,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
setclientid.sc_name_len = scnprintf(setclientid.sc_name,
sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
- clp->cl_cred->cr_ops->cr_name,
+ cred->cr_ops->cr_name,
clp->cl_id_uniquifier);
setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
sizeof(setclientid.sc_netid), "tcp");
@@ -2661,14 +2894,14 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p
}
int
-nfs4_proc_setclientid_confirm(struct nfs4_client *clp)
+nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
{
struct nfs_fsinfo fsinfo;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
.rpc_argp = clp,
.rpc_resp = &fsinfo,
- .rpc_cred = clp->cl_cred,
+ .rpc_cred = cred,
};
unsigned long now;
int status;
@@ -2679,24 +2912,92 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp)
spin_lock(&clp->cl_lock);
clp->cl_lease_time = fsinfo.lease_time * HZ;
clp->cl_last_renewal = now;
+ clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
spin_unlock(&clp->cl_lock);
}
return status;
}
-static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+struct nfs4_delegreturndata {
+ struct nfs4_delegreturnargs args;
+ struct nfs4_delegreturnres res;
+ struct nfs_fh fh;
+ nfs4_stateid stateid;
+ struct rpc_cred *cred;
+ unsigned long timestamp;
+ struct nfs_fattr fattr;
+ int rpc_status;
+};
+
+static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
{
- struct nfs4_delegreturnargs args = {
- .fhandle = NFS_FH(inode),
- .stateid = stateid,
- };
+ struct nfs4_delegreturndata *data = calldata;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
- .rpc_argp = &args,
- .rpc_cred = cred,
+ .rpc_argp = &data->args,
+ .rpc_resp = &data->res,
+ .rpc_cred = data->cred,
};
+ nfs_fattr_init(data->res.fattr);
+ rpc_call_setup(task, &msg, 0);
+}
- return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_delegreturndata *data = calldata;
+ data->rpc_status = task->tk_status;
+ if (data->rpc_status == 0)
+ renew_lease(data->res.server, data->timestamp);
+}
+
+static void nfs4_delegreturn_release(void *calldata)
+{
+ struct nfs4_delegreturndata *data = calldata;
+
+ put_rpccred(data->cred);
+ kfree(calldata);
+}
+
+const static struct rpc_call_ops nfs4_delegreturn_ops = {
+ .rpc_call_prepare = nfs4_delegreturn_prepare,
+ .rpc_call_done = nfs4_delegreturn_done,
+ .rpc_release = nfs4_delegreturn_release,
+};
+
+static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+{
+ struct nfs4_delegreturndata *data;
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct rpc_task *task;
+ int status;
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ data->args.fhandle = &data->fh;
+ data->args.stateid = &data->stateid;
+ data->args.bitmask = server->attr_bitmask;
+ nfs_copy_fh(&data->fh, NFS_FH(inode));
+ memcpy(&data->stateid, stateid, sizeof(data->stateid));
+ data->res.fattr = &data->fattr;
+ data->res.server = server;
+ data->cred = get_rpccred(cred);
+ data->timestamp = jiffies;
+ data->rpc_status = 0;
+
+ task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
+ if (IS_ERR(task)) {
+ nfs4_delegreturn_release(data);
+ return PTR_ERR(task);
+ }
+ status = nfs4_wait_for_completion_rpc_task(task);
+ if (status == 0) {
+ status = data->rpc_status;
+ if (status == 0)
+ nfs_post_op_update_inode(inode, &data->fattr);
+ }
+ rpc_release_task(task);
+ return status;
}
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
@@ -2734,43 +3035,17 @@ nfs4_set_lock_task_retry(unsigned long timeout)
return timeout;
}
-static inline int
-nfs4_lck_type(int cmd, struct file_lock *request)
-{
- /* set lock type */
- switch (request->fl_type) {
- case F_RDLCK:
- return IS_SETLKW(cmd) ? NFS4_READW_LT : NFS4_READ_LT;
- case F_WRLCK:
- return IS_SETLKW(cmd) ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
- case F_UNLCK:
- return NFS4_WRITE_LT;
- }
- BUG();
- return 0;
-}
-
-static inline uint64_t
-nfs4_lck_length(struct file_lock *request)
-{
- if (request->fl_end == OFFSET_MAX)
- return ~(uint64_t)0;
- return request->fl_end - request->fl_start + 1;
-}
-
static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
struct inode *inode = state->inode;
struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_client *clp = server->nfs4_state;
- struct nfs_lockargs arg = {
+ struct nfs_lockt_args arg = {
.fh = NFS_FH(inode),
- .type = nfs4_lck_type(cmd, request),
- .offset = request->fl_start,
- .length = nfs4_lck_length(request),
+ .fl = request,
};
- struct nfs_lockres res = {
- .server = server,
+ struct nfs_lockt_res res = {
+ .denied = request,
};
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
@@ -2778,36 +3053,23 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
.rpc_resp = &res,
.rpc_cred = state->owner->so_cred,
};
- struct nfs_lowner nlo;
struct nfs4_lock_state *lsp;
int status;
down_read(&clp->cl_sem);
- nlo.clientid = clp->cl_clientid;
+ arg.lock_owner.clientid = clp->cl_clientid;
status = nfs4_set_lock_state(state, request);
if (status != 0)
goto out;
lsp = request->fl_u.nfs4_fl.owner;
- nlo.id = lsp->ls_id;
- arg.u.lockt = &nlo;
+ arg.lock_owner.id = lsp->ls_id;
status = rpc_call_sync(server->client, &msg, 0);
- if (!status) {
- request->fl_type = F_UNLCK;
- } else if (status == -NFS4ERR_DENIED) {
- int64_t len, start, end;
- start = res.u.denied.offset;
- len = res.u.denied.length;
- end = start + len - 1;
- if (end < 0 || len == 0)
- request->fl_end = OFFSET_MAX;
- else
- request->fl_end = (loff_t)end;
- request->fl_start = (loff_t)start;
- request->fl_type = F_WRLCK;
- if (res.u.denied.type & 1)
- request->fl_type = F_RDLCK;
- request->fl_pid = 0;
- status = 0;
+ switch (status) {
+ case 0:
+ request->fl_type = F_UNLCK;
+ break;
+ case -NFS4ERR_DENIED:
+ status = 0;
}
out:
up_read(&clp->cl_sem);
@@ -2847,196 +3109,314 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
}
struct nfs4_unlockdata {
- struct nfs_lockargs arg;
- struct nfs_locku_opargs luargs;
- struct nfs_lockres res;
+ struct nfs_locku_args arg;
+ struct nfs_locku_res res;
struct nfs4_lock_state *lsp;
struct nfs_open_context *ctx;
- atomic_t refcount;
- struct completion completion;
+ struct file_lock fl;
+ const struct nfs_server *server;
+ unsigned long timestamp;
};
-static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata)
-{
- if (atomic_dec_and_test(&calldata->refcount)) {
- nfs_free_seqid(calldata->luargs.seqid);
- nfs4_put_lock_state(calldata->lsp);
- put_nfs_open_context(calldata->ctx);
- kfree(calldata);
- }
+static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
+ struct nfs_open_context *ctx,
+ struct nfs4_lock_state *lsp,
+ struct nfs_seqid *seqid)
+{
+ struct nfs4_unlockdata *p;
+ struct inode *inode = lsp->ls_state->inode;
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
+ return NULL;
+ p->arg.fh = NFS_FH(inode);
+ p->arg.fl = &p->fl;
+ p->arg.seqid = seqid;
+ p->arg.stateid = &lsp->ls_stateid;
+ p->lsp = lsp;
+ atomic_inc(&lsp->ls_count);
+ /* Ensure we don't close file until we're done freeing locks! */
+ p->ctx = get_nfs_open_context(ctx);
+ memcpy(&p->fl, fl, sizeof(p->fl));
+ p->server = NFS_SERVER(inode);
+ return p;
}
-static void nfs4_locku_complete(struct nfs4_unlockdata *calldata)
+static void nfs4_locku_release_calldata(void *data)
{
- complete(&calldata->completion);
- nfs4_locku_release_calldata(calldata);
+ struct nfs4_unlockdata *calldata = data;
+ nfs_free_seqid(calldata->arg.seqid);
+ nfs4_put_lock_state(calldata->lsp);
+ put_nfs_open_context(calldata->ctx);
+ kfree(calldata);
}
-static void nfs4_locku_done(struct rpc_task *task)
+static void nfs4_locku_done(struct rpc_task *task, void *data)
{
- struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+ struct nfs4_unlockdata *calldata = data;
- nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid);
+ if (RPC_ASSASSINATED(task))
+ return;
+ nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid);
switch (task->tk_status) {
case 0:
memcpy(calldata->lsp->ls_stateid.data,
- calldata->res.u.stateid.data,
+ calldata->res.stateid.data,
sizeof(calldata->lsp->ls_stateid.data));
+ renew_lease(calldata->server, calldata->timestamp);
break;
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
- nfs4_schedule_state_recovery(calldata->res.server->nfs4_state);
+ nfs4_schedule_state_recovery(calldata->server->nfs4_state);
break;
default:
- if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) {
+ if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) {
rpc_restart_call(task);
- return;
}
}
- nfs4_locku_complete(calldata);
}
-static void nfs4_locku_begin(struct rpc_task *task)
+static void nfs4_locku_prepare(struct rpc_task *task, void *data)
{
- struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata;
+ struct nfs4_unlockdata *calldata = data;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
.rpc_argp = &calldata->arg,
.rpc_resp = &calldata->res,
.rpc_cred = calldata->lsp->ls_state->owner->so_cred,
};
- int status;
- status = nfs_wait_on_sequence(calldata->luargs.seqid, task);
- if (status != 0)
+ if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
return;
if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) {
- nfs4_locku_complete(calldata);
- task->tk_exit = NULL;
- rpc_exit(task, 0);
+ /* Note: exit _without_ running nfs4_locku_done */
+ task->tk_action = NULL;
return;
}
+ calldata->timestamp = jiffies;
rpc_call_setup(task, &msg, 0);
}
+static const struct rpc_call_ops nfs4_locku_ops = {
+ .rpc_call_prepare = nfs4_locku_prepare,
+ .rpc_call_done = nfs4_locku_done,
+ .rpc_release = nfs4_locku_release_calldata,
+};
+
+static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
+ struct nfs_open_context *ctx,
+ struct nfs4_lock_state *lsp,
+ struct nfs_seqid *seqid)
+{
+ struct nfs4_unlockdata *data;
+ struct rpc_task *task;
+
+ data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
+ if (data == NULL) {
+ nfs_free_seqid(seqid);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Unlock _before_ we do the RPC call */
+ do_vfs_lock(fl->fl_file, fl);
+ task = rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data);
+ if (IS_ERR(task))
+ nfs4_locku_release_calldata(data);
+ return task;
+}
+
static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
{
- struct nfs4_unlockdata *calldata;
- struct inode *inode = state->inode;
- struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_seqid *seqid;
struct nfs4_lock_state *lsp;
- int status;
+ struct rpc_task *task;
+ int status = 0;
/* Is this a delegated lock? */
if (test_bit(NFS_DELEGATED_STATE, &state->flags))
- return do_vfs_lock(request->fl_file, request);
+ goto out_unlock;
+ /* Is this open_owner holding any locks on the server? */
+ if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
+ goto out_unlock;
status = nfs4_set_lock_state(state, request);
if (status != 0)
- return status;
+ goto out_unlock;
lsp = request->fl_u.nfs4_fl.owner;
- /* We might have lost the locks! */
- if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
- return 0;
- calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
- if (calldata == NULL)
- return -ENOMEM;
- calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid);
- if (calldata->luargs.seqid == NULL) {
- kfree(calldata);
- return -ENOMEM;
- }
- calldata->luargs.stateid = &lsp->ls_stateid;
- calldata->arg.fh = NFS_FH(inode);
- calldata->arg.type = nfs4_lck_type(cmd, request);
- calldata->arg.offset = request->fl_start;
- calldata->arg.length = nfs4_lck_length(request);
- calldata->arg.u.locku = &calldata->luargs;
- calldata->res.server = server;
- calldata->lsp = lsp;
- atomic_inc(&lsp->ls_count);
-
- /* Ensure we don't close file until we're done freeing locks! */
- calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data);
-
- atomic_set(&calldata->refcount, 2);
- init_completion(&calldata->completion);
-
- status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin,
- nfs4_locku_done, calldata);
- if (status == 0)
- wait_for_completion_interruptible(&calldata->completion);
+ status = -ENOMEM;
+ seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+ if (seqid == NULL)
+ goto out_unlock;
+ task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid);
+ status = PTR_ERR(task);
+ if (IS_ERR(task))
+ goto out_unlock;
+ status = nfs4_wait_for_completion_rpc_task(task);
+ rpc_release_task(task);
+ return status;
+out_unlock:
do_vfs_lock(request->fl_file, request);
- nfs4_locku_release_calldata(calldata);
return status;
}
-static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
+struct nfs4_lockdata {
+ struct nfs_lock_args arg;
+ struct nfs_lock_res res;
+ struct nfs4_lock_state *lsp;
+ struct nfs_open_context *ctx;
+ struct file_lock fl;
+ unsigned long timestamp;
+ int rpc_status;
+ int cancelled;
+};
+
+static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
+ struct nfs_open_context *ctx, struct nfs4_lock_state *lsp)
{
- struct inode *inode = state->inode;
+ struct nfs4_lockdata *p;
+ struct inode *inode = lsp->ls_state->inode;
struct nfs_server *server = NFS_SERVER(inode);
- struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
- struct nfs_lock_opargs largs = {
- .lock_stateid = &lsp->ls_stateid,
- .open_stateid = &state->stateid,
- .lock_owner = {
- .clientid = server->nfs4_state->cl_clientid,
- .id = lsp->ls_id,
- },
- .reclaim = reclaim,
- };
- struct nfs_lockargs arg = {
- .fh = NFS_FH(inode),
- .type = nfs4_lck_type(cmd, request),
- .offset = request->fl_start,
- .length = nfs4_lck_length(request),
- .u = {
- .lock = &largs,
- },
- };
- struct nfs_lockres res = {
- .server = server,
- };
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
+ return NULL;
+
+ p->arg.fh = NFS_FH(inode);
+ p->arg.fl = &p->fl;
+ p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
+ if (p->arg.lock_seqid == NULL)
+ goto out_free;
+ p->arg.lock_stateid = &lsp->ls_stateid;
+ p->arg.lock_owner.clientid = server->nfs4_state->cl_clientid;
+ p->arg.lock_owner.id = lsp->ls_id;
+ p->lsp = lsp;
+ atomic_inc(&lsp->ls_count);
+ p->ctx = get_nfs_open_context(ctx);
+ memcpy(&p->fl, fl, sizeof(p->fl));
+ return p;
+out_free:
+ kfree(p);
+ return NULL;
+}
+
+static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_lockdata *data = calldata;
+ struct nfs4_state *state = data->lsp->ls_state;
+ struct nfs4_state_owner *sp = state->owner;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- .rpc_cred = state->owner->so_cred,
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
+ .rpc_argp = &data->arg,
+ .rpc_resp = &data->res,
+ .rpc_cred = sp->so_cred,
};
- int status = -ENOMEM;
-
- largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid);
- if (largs.lock_seqid == NULL)
- return -ENOMEM;
- if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) {
- struct nfs4_state_owner *owner = state->owner;
- largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid);
- if (largs.open_seqid == NULL)
+ if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0)
+ return;
+ dprintk("%s: begin!\n", __FUNCTION__);
+ /* Do we need to do an open_to_lock_owner? */
+ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
+ data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid);
+ if (data->arg.open_seqid == NULL) {
+ data->rpc_status = -ENOMEM;
+ task->tk_action = NULL;
goto out;
- largs.new_lock_owner = 1;
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- /* increment open seqid on success, and seqid mutating errors */
- if (largs.new_lock_owner != 0) {
- nfs_increment_open_seqid(status, largs.open_seqid);
- if (status == 0)
- nfs_confirm_seqid(&lsp->ls_seqid, 0);
}
- nfs_free_seqid(largs.open_seqid);
- } else
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- /* increment lock seqid on success, and seqid mutating errors*/
- nfs_increment_lock_seqid(status, largs.lock_seqid);
- /* save the returned stateid. */
- if (status == 0) {
- memcpy(lsp->ls_stateid.data, res.u.stateid.data,
- sizeof(lsp->ls_stateid.data));
- lsp->ls_flags |= NFS_LOCK_INITIALIZED;
- } else if (status == -NFS4ERR_DENIED)
- status = -EAGAIN;
+ data->arg.open_stateid = &state->stateid;
+ data->arg.new_lock_owner = 1;
+ }
+ data->timestamp = jiffies;
+ rpc_call_setup(task, &msg, 0);
out:
- nfs_free_seqid(largs.lock_seqid);
- return status;
+ dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status);
+}
+
+static void nfs4_lock_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs4_lockdata *data = calldata;
+
+ dprintk("%s: begin!\n", __FUNCTION__);
+
+ data->rpc_status = task->tk_status;
+ if (RPC_ASSASSINATED(task))
+ goto out;
+ if (data->arg.new_lock_owner != 0) {
+ nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid);
+ if (data->rpc_status == 0)
+ nfs_confirm_seqid(&data->lsp->ls_seqid, 0);
+ else
+ goto out;
+ }
+ if (data->rpc_status == 0) {
+ memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
+ sizeof(data->lsp->ls_stateid.data));
+ data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+ renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
+ }
+ nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
+out:
+ dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status);
+}
+
+static void nfs4_lock_release(void *calldata)
+{
+ struct nfs4_lockdata *data = calldata;
+
+ dprintk("%s: begin!\n", __FUNCTION__);
+ if (data->arg.open_seqid != NULL)
+ nfs_free_seqid(data->arg.open_seqid);
+ if (data->cancelled != 0) {
+ struct rpc_task *task;
+ task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
+ data->arg.lock_seqid);
+ if (!IS_ERR(task))
+ rpc_release_task(task);
+ dprintk("%s: cancelling lock!\n", __FUNCTION__);
+ } else
+ nfs_free_seqid(data->arg.lock_seqid);
+ nfs4_put_lock_state(data->lsp);
+ put_nfs_open_context(data->ctx);
+ kfree(data);
+ dprintk("%s: done!\n", __FUNCTION__);
+}
+
+static const struct rpc_call_ops nfs4_lock_ops = {
+ .rpc_call_prepare = nfs4_lock_prepare,
+ .rpc_call_done = nfs4_lock_done,
+ .rpc_release = nfs4_lock_release,
+};
+
+static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim)
+{
+ struct nfs4_lockdata *data;
+ struct rpc_task *task;
+ int ret;
+
+ dprintk("%s: begin!\n", __FUNCTION__);
+ data = nfs4_alloc_lockdata(fl, fl->fl_file->private_data,
+ fl->fl_u.nfs4_fl.owner);
+ if (data == NULL)
+ return -ENOMEM;
+ if (IS_SETLKW(cmd))
+ data->arg.block = 1;
+ if (reclaim != 0)
+ data->arg.reclaim = 1;
+ task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC,
+ &nfs4_lock_ops, data);
+ if (IS_ERR(task)) {
+ nfs4_lock_release(data);
+ return PTR_ERR(task);
+ }
+ ret = nfs4_wait_for_completion_rpc_task(task);
+ if (ret == 0) {
+ ret = data->rpc_status;
+ if (ret == -NFS4ERR_DENIED)
+ ret = -EAGAIN;
+ } else
+ data->cancelled = 1;
+ rpc_release_task(task);
+ dprintk("%s: done, ret = %d!\n", __FUNCTION__, ret);
+ return ret;
}
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index a3001628ad32..5d764d8e6d8a 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -54,6 +54,7 @@
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include "nfs4_fs.h"
+#include "delegation.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -61,6 +62,7 @@ void
nfs4_renew_state(void *data)
{
struct nfs4_client *clp = (struct nfs4_client *)data;
+ struct rpc_cred *cred;
long lease, timeout;
unsigned long last, now;
@@ -68,7 +70,7 @@ nfs4_renew_state(void *data)
dprintk("%s: start\n", __FUNCTION__);
/* Are there any active superblocks? */
if (list_empty(&clp->cl_superblocks))
- goto out;
+ goto out;
spin_lock(&clp->cl_lock);
lease = clp->cl_lease_time;
last = clp->cl_last_renewal;
@@ -76,9 +78,17 @@ nfs4_renew_state(void *data)
timeout = (2 * lease) / 3 + (long)last - (long)now;
/* Are we close to a lease timeout? */
if (time_after(now, last + lease/3)) {
+ cred = nfs4_get_renew_cred(clp);
+ if (cred == NULL) {
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ spin_unlock(&clp->cl_lock);
+ nfs_expire_all_delegations(clp);
+ goto out;
+ }
spin_unlock(&clp->cl_lock);
/* Queue an asynchronous RENEW. */
- nfs4_proc_async_renew(clp);
+ nfs4_proc_async_renew(clp, cred);
+ put_rpccred(cred);
timeout = (2 * lease) / 3;
spin_lock(&clp->cl_lock);
} else
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5ef4c57618fe..afad0255e7db 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -43,6 +43,8 @@
#include <linux/smp_lock.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
@@ -57,8 +59,6 @@ const nfs4_stateid zero_stateid;
static DEFINE_SPINLOCK(state_spinlock);
static LIST_HEAD(nfs4_clientid_list);
-static void nfs4_recover_state(void *);
-
void
init_nfsv4_state(struct nfs_server *server)
{
@@ -91,11 +91,10 @@ nfs4_alloc_client(struct in_addr *addr)
if (nfs_callback_up() < 0)
return NULL;
- if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
+ if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
nfs_callback_down();
return NULL;
}
- memset(clp, 0, sizeof(*clp));
memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
init_rwsem(&clp->cl_sem);
INIT_LIST_HEAD(&clp->cl_delegations);
@@ -103,14 +102,12 @@ nfs4_alloc_client(struct in_addr *addr)
INIT_LIST_HEAD(&clp->cl_unused);
spin_lock_init(&clp->cl_lock);
atomic_set(&clp->cl_count, 1);
- INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
INIT_LIST_HEAD(&clp->cl_superblocks);
- init_waitqueue_head(&clp->cl_waitq);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
clp->cl_rpcclient = ERR_PTR(-EINVAL);
clp->cl_boot_time = CURRENT_TIME;
- clp->cl_state = 1 << NFS4CLNT_OK;
+ clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
return clp;
}
@@ -127,8 +124,6 @@ nfs4_free_client(struct nfs4_client *clp)
kfree(sp);
}
BUG_ON(!list_empty(&clp->cl_state_owners));
- if (clp->cl_cred)
- put_rpccred(clp->cl_cred);
nfs_idmap_delete(clp);
if (!IS_ERR(clp->cl_rpcclient))
rpc_shutdown_client(clp->cl_rpcclient);
@@ -193,27 +188,22 @@ nfs4_put_client(struct nfs4_client *clp)
list_del(&clp->cl_servers);
spin_unlock(&state_spinlock);
BUG_ON(!list_empty(&clp->cl_superblocks));
- wake_up_all(&clp->cl_waitq);
rpc_wake_up(&clp->cl_rpcwaitq);
nfs4_kill_renewd(clp);
nfs4_free_client(clp);
}
-static int __nfs4_init_client(struct nfs4_client *clp)
+static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred)
{
- int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
+ int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
+ nfs_callback_tcpport, cred);
if (status == 0)
- status = nfs4_proc_setclientid_confirm(clp);
+ status = nfs4_proc_setclientid_confirm(clp, cred);
if (status == 0)
nfs4_schedule_state_renewal(clp);
return status;
}
-int nfs4_init_client(struct nfs4_client *clp)
-{
- return nfs4_map_errors(__nfs4_init_client(clp));
-}
-
u32
nfs4_alloc_lockowner_id(struct nfs4_client *clp)
{
@@ -235,6 +225,32 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred)
return sp;
}
+struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp)
+{
+ struct nfs4_state_owner *sp;
+ struct rpc_cred *cred = NULL;
+
+ list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+ if (list_empty(&sp->so_states))
+ continue;
+ cred = get_rpccred(sp->so_cred);
+ break;
+ }
+ return cred;
+}
+
+struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp)
+{
+ struct nfs4_state_owner *sp;
+
+ if (!list_empty(&clp->cl_state_owners)) {
+ sp = list_entry(clp->cl_state_owners.next,
+ struct nfs4_state_owner, so_list);
+ return get_rpccred(sp->so_cred);
+ }
+ return NULL;
+}
+
static struct nfs4_state_owner *
nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred)
{
@@ -349,14 +365,9 @@ nfs4_alloc_open_state(void)
{
struct nfs4_state *state;
- state = kmalloc(sizeof(*state), GFP_KERNEL);
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return NULL;
- state->state = 0;
- state->nreaders = 0;
- state->nwriters = 0;
- state->flags = 0;
- memset(state->stateid.data, 0, sizeof(state->stateid.data));
atomic_set(&state->count, 1);
INIT_LIST_HEAD(&state->lock_states);
spin_lock_init(&state->state_lock);
@@ -475,15 +486,23 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
/* Protect against nfs4_find_state() */
spin_lock(&owner->so_lock);
spin_lock(&inode->i_lock);
- if (mode & FMODE_READ)
- state->nreaders--;
- if (mode & FMODE_WRITE)
- state->nwriters--;
+ switch (mode & (FMODE_READ | FMODE_WRITE)) {
+ case FMODE_READ:
+ state->n_rdonly--;
+ break;
+ case FMODE_WRITE:
+ state->n_wronly--;
+ break;
+ case FMODE_READ|FMODE_WRITE:
+ state->n_rdwr--;
+ }
oldstate = newstate = state->state;
- if (state->nreaders == 0)
- newstate &= ~FMODE_READ;
- if (state->nwriters == 0)
- newstate &= ~FMODE_WRITE;
+ if (state->n_rdwr == 0) {
+ if (state->n_rdonly == 0)
+ newstate &= ~FMODE_READ;
+ if (state->n_wronly == 0)
+ newstate &= ~FMODE_WRITE;
+ }
if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
nfs4_state_set_mode_locked(state, newstate);
oldstate = newstate;
@@ -733,45 +752,43 @@ out:
}
static int reclaimer(void *);
-struct reclaimer_args {
- struct nfs4_client *clp;
- struct completion complete;
-};
+
+static inline void nfs4_clear_recover_bit(struct nfs4_client *clp)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER);
+ rpc_wake_up(&clp->cl_rpcwaitq);
+}
/*
* State recovery routine
*/
-void
-nfs4_recover_state(void *data)
+static void nfs4_recover_state(struct nfs4_client *clp)
{
- struct nfs4_client *clp = (struct nfs4_client *)data;
- struct reclaimer_args args = {
- .clp = clp,
- };
- might_sleep();
-
- init_completion(&args.complete);
+ struct task_struct *task;
- if (kernel_thread(reclaimer, &args, CLONE_KERNEL) < 0)
- goto out_failed_clear;
- wait_for_completion(&args.complete);
- return;
-out_failed_clear:
- set_bit(NFS4CLNT_OK, &clp->cl_state);
- wake_up_all(&clp->cl_waitq);
- rpc_wake_up(&clp->cl_rpcwaitq);
+ __module_get(THIS_MODULE);
+ atomic_inc(&clp->cl_count);
+ task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim",
+ NIPQUAD(clp->cl_addr));
+ if (!IS_ERR(task))
+ return;
+ nfs4_clear_recover_bit(clp);
+ nfs4_put_client(clp);
+ module_put(THIS_MODULE);
}
/*
* Schedule a state recovery attempt
*/
-void
-nfs4_schedule_state_recovery(struct nfs4_client *clp)
+void nfs4_schedule_state_recovery(struct nfs4_client *clp)
{
if (!clp)
return;
- if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state))
- schedule_work(&clp->cl_recoverd);
+ if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
+ nfs4_recover_state(clp);
}
static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
@@ -887,18 +904,14 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
static int reclaimer(void *ptr)
{
- struct reclaimer_args *args = (struct reclaimer_args *)ptr;
- struct nfs4_client *clp = args->clp;
+ struct nfs4_client *clp = ptr;
struct nfs4_state_owner *sp;
struct nfs4_state_recovery_ops *ops;
+ struct rpc_cred *cred;
int status = 0;
- daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
allow_signal(SIGKILL);
- atomic_inc(&clp->cl_count);
- complete(&args->complete);
-
/* Ensure exclusive access to NFSv4 state */
lock_kernel();
down_write(&clp->cl_sem);
@@ -906,20 +919,33 @@ static int reclaimer(void *ptr)
if (list_empty(&clp->cl_superblocks))
goto out;
restart_loop:
- status = nfs4_proc_renew(clp);
- switch (status) {
- case 0:
- case -NFS4ERR_CB_PATH_DOWN:
- goto out;
- case -NFS4ERR_STALE_CLIENTID:
- case -NFS4ERR_LEASE_MOVED:
- ops = &nfs4_reboot_recovery_ops;
- break;
- default:
- ops = &nfs4_network_partition_recovery_ops;
- };
+ ops = &nfs4_network_partition_recovery_ops;
+ /* Are there any open files on this volume? */
+ cred = nfs4_get_renew_cred(clp);
+ if (cred != NULL) {
+ /* Yes there are: try to renew the old lease */
+ status = nfs4_proc_renew(clp, cred);
+ switch (status) {
+ case 0:
+ case -NFS4ERR_CB_PATH_DOWN:
+ put_rpccred(cred);
+ goto out;
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+ ops = &nfs4_reboot_recovery_ops;
+ }
+ } else {
+ /* "reboot" to ensure we clear all state on the server */
+ clp->cl_boot_time = CURRENT_TIME;
+ cred = nfs4_get_setclientid_cred(clp);
+ }
+ /* We're going to have to re-establish a clientid */
nfs4_state_mark_reclaim(clp);
- status = __nfs4_init_client(clp);
+ status = -ENOENT;
+ if (cred != NULL) {
+ status = nfs4_init_client(clp, cred);
+ put_rpccred(cred);
+ }
if (status)
goto out_error;
/* Mark all delegations for reclaim */
@@ -940,14 +966,13 @@ restart_loop:
}
nfs_delegation_reap_unclaimed(clp);
out:
- set_bit(NFS4CLNT_OK, &clp->cl_state);
up_write(&clp->cl_sem);
unlock_kernel();
- wake_up_all(&clp->cl_waitq);
- rpc_wake_up(&clp->cl_rpcwaitq);
if (status == -NFS4ERR_CB_PATH_DOWN)
nfs_handle_cb_pathdown(clp);
+ nfs4_clear_recover_bit(clp);
nfs4_put_client(clp);
+ module_put_and_exit(0);
return 0;
out_error:
printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index fbbace8a30c4..4bbf5ef57785 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -392,9 +392,11 @@ static int nfs_stat_to_errno(int);
decode_getattr_maxsz)
#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
- encode_delegreturn_maxsz)
+ encode_delegreturn_maxsz + \
+ encode_getattr_maxsz)
#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
- decode_delegreturn_maxsz)
+ decode_delegreturn_maxsz + \
+ decode_getattr_maxsz)
#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
@@ -564,7 +566,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
}
if (iap->ia_valid & ATTR_MODE) {
bmval1 |= FATTR4_WORD1_MODE;
- WRITE32(iap->ia_mode);
+ WRITE32(iap->ia_mode & S_IALLUGO);
}
if (iap->ia_valid & ATTR_UID) {
bmval1 |= FATTR4_WORD1_OWNER;
@@ -742,69 +744,80 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
return 0;
}
+static inline int nfs4_lock_type(struct file_lock *fl, int block)
+{
+ if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK)
+ return block ? NFS4_READW_LT : NFS4_READ_LT;
+ return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
+}
+
+static inline uint64_t nfs4_lock_length(struct file_lock *fl)
+{
+ if (fl->fl_end == OFFSET_MAX)
+ return ~(uint64_t)0;
+ return fl->fl_end - fl->fl_start + 1;
+}
+
/*
* opcode,type,reclaim,offset,length,new_lock_owner = 32
* open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
*/
-static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
+static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
{
uint32_t *p;
- struct nfs_lock_opargs *opargs = arg->u.lock;
RESERVE_SPACE(32);
WRITE32(OP_LOCK);
- WRITE32(arg->type);
- WRITE32(opargs->reclaim);
- WRITE64(arg->offset);
- WRITE64(arg->length);
- WRITE32(opargs->new_lock_owner);
- if (opargs->new_lock_owner){
+ WRITE32(nfs4_lock_type(args->fl, args->block));
+ WRITE32(args->reclaim);
+ WRITE64(args->fl->fl_start);
+ WRITE64(nfs4_lock_length(args->fl));
+ WRITE32(args->new_lock_owner);
+ if (args->new_lock_owner){
RESERVE_SPACE(40);
- WRITE32(opargs->open_seqid->sequence->counter);
- WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data));
- WRITE32(opargs->lock_seqid->sequence->counter);
- WRITE64(opargs->lock_owner.clientid);
+ WRITE32(args->open_seqid->sequence->counter);
+ WRITEMEM(args->open_stateid->data, sizeof(args->open_stateid->data));
+ WRITE32(args->lock_seqid->sequence->counter);
+ WRITE64(args->lock_owner.clientid);
WRITE32(4);
- WRITE32(opargs->lock_owner.id);
+ WRITE32(args->lock_owner.id);
}
else {
RESERVE_SPACE(20);
- WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data));
- WRITE32(opargs->lock_seqid->sequence->counter);
+ WRITEMEM(args->lock_stateid->data, sizeof(args->lock_stateid->data));
+ WRITE32(args->lock_seqid->sequence->counter);
}
return 0;
}
-static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
+static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args)
{
uint32_t *p;
- struct nfs_lowner *opargs = arg->u.lockt;
RESERVE_SPACE(40);
WRITE32(OP_LOCKT);
- WRITE32(arg->type);
- WRITE64(arg->offset);
- WRITE64(arg->length);
- WRITE64(opargs->clientid);
+ WRITE32(nfs4_lock_type(args->fl, 0));
+ WRITE64(args->fl->fl_start);
+ WRITE64(nfs4_lock_length(args->fl));
+ WRITE64(args->lock_owner.clientid);
WRITE32(4);
- WRITE32(opargs->id);
+ WRITE32(args->lock_owner.id);
return 0;
}
-static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
+static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args)
{
uint32_t *p;
- struct nfs_locku_opargs *opargs = arg->u.locku;
RESERVE_SPACE(44);
WRITE32(OP_LOCKU);
- WRITE32(arg->type);
- WRITE32(opargs->seqid->sequence->counter);
- WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data));
- WRITE64(arg->offset);
- WRITE64(arg->length);
+ WRITE32(nfs4_lock_type(args->fl, 0));
+ WRITE32(args->seqid->sequence->counter);
+ WRITEMEM(args->stateid->data, sizeof(args->stateid->data));
+ WRITE64(args->fl->fl_start);
+ WRITE64(nfs4_lock_length(args->fl));
return 0;
}
@@ -964,9 +977,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
{
uint32_t *p;
- RESERVE_SPACE(8+sizeof(arg->stateid.data));
+ RESERVE_SPACE(8+sizeof(arg->stateid->data));
WRITE32(OP_OPEN_CONFIRM);
- WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
+ WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
WRITE32(arg->seqid->sequence->counter);
return 0;
@@ -1499,9 +1512,6 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
};
int status;
- status = nfs_wait_on_sequence(args->seqid, req->rq_task);
- if (status != 0)
- goto out;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh);
@@ -1538,9 +1548,6 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n
};
int status;
- status = nfs_wait_on_sequence(args->seqid, req->rq_task);
- if (status != 0)
- goto out;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh);
@@ -1558,19 +1565,19 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 3,
};
int status;
- status = nfs_wait_on_sequence(args->seqid, req->rq_task);
- if (status != 0)
- goto out;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh);
if (status)
goto out;
status = encode_open(&xdr, args);
+ if (status)
+ goto out;
+ status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
@@ -1602,21 +1609,14 @@ out:
/*
* Encode a LOCK request
*/
-static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
+static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
};
- struct nfs_lock_opargs *opargs = args->u.lock;
int status;
- status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task);
- if (status != 0)
- goto out;
- /* Do we need to do an open_to_lock_owner? */
- if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)
- opargs->new_lock_owner = 0;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh);
@@ -1630,7 +1630,7 @@ out:
/*
* Encode a LOCKT request
*/
-static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
+static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockt_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
@@ -1651,7 +1651,7 @@ out:
/*
* Encode a LOCKU request
*/
-static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
+static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_locku_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
@@ -1985,14 +1985,20 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const str
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 3,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->fhandle)) == 0)
- status = encode_delegreturn(&xdr, args->stateid);
+ status = encode_putfh(&xdr, args->fhandle);
+ if (status != 0)
+ goto out;
+ status = encode_delegreturn(&xdr, args->stateid);
+ if (status != 0)
+ goto out;
+ status = encode_getfattr(&xdr, args->bitmask);
+out:
return status;
}
@@ -2955,55 +2961,64 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
/*
* We create the owner, so we know a proper owner.id length is 4.
*/
-static int decode_lock_denied (struct xdr_stream *xdr, struct nfs_lock_denied *denied)
+static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
{
+ uint64_t offset, length, clientid;
uint32_t *p;
- uint32_t namelen;
+ uint32_t namelen, type;
READ_BUF(32);
- READ64(denied->offset);
- READ64(denied->length);
- READ32(denied->type);
- READ64(denied->owner.clientid);
+ READ64(offset);
+ READ64(length);
+ READ32(type);
+ if (fl != NULL) {
+ fl->fl_start = (loff_t)offset;
+ fl->fl_end = fl->fl_start + (loff_t)length - 1;
+ if (length == ~(uint64_t)0)
+ fl->fl_end = OFFSET_MAX;
+ fl->fl_type = F_WRLCK;
+ if (type & 1)
+ fl->fl_type = F_RDLCK;
+ fl->fl_pid = 0;
+ }
+ READ64(clientid);
READ32(namelen);
READ_BUF(namelen);
- if (namelen == 4)
- READ32(denied->owner.id);
return -NFS4ERR_DENIED;
}
-static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res)
+static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
{
uint32_t *p;
int status;
status = decode_op_hdr(xdr, OP_LOCK);
if (status == 0) {
- READ_BUF(sizeof(res->u.stateid.data));
- COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
+ READ_BUF(sizeof(res->stateid.data));
+ COPYMEM(res->stateid.data, sizeof(res->stateid.data));
} else if (status == -NFS4ERR_DENIED)
- return decode_lock_denied(xdr, &res->u.denied);
+ return decode_lock_denied(xdr, NULL);
return status;
}
-static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockres *res)
+static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
{
int status;
status = decode_op_hdr(xdr, OP_LOCKT);
if (status == -NFS4ERR_DENIED)
- return decode_lock_denied(xdr, &res->u.denied);
+ return decode_lock_denied(xdr, res->denied);
return status;
}
-static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res)
+static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
{
uint32_t *p;
int status;
status = decode_op_hdr(xdr, OP_LOCKU);
if (status == 0) {
- READ_BUF(sizeof(res->u.stateid.data));
- COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
+ READ_BUF(sizeof(res->stateid.data));
+ COPYMEM(res->stateid.data, sizeof(res->stateid.data));
}
return status;
}
@@ -3831,6 +3846,9 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct
if (status)
goto out;
status = decode_open(&xdr, res);
+ if (status)
+ goto out;
+ decode_getfattr(&xdr, res->f_attr, res->server);
out:
return status;
}
@@ -3864,7 +3882,7 @@ out:
/*
* Decode LOCK response
*/
-static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
+static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lock_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -3885,7 +3903,7 @@ out:
/*
* Decode LOCKT response
*/
-static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
+static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockt_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -3906,7 +3924,7 @@ out:
/*
* Decode LOCKU response
*/
-static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
+static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_locku_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4174,7 +4192,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
/*
* DELEGRETURN request
*/
-static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
+static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_delegreturnres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4182,11 +4200,14 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *d
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
- if (status == 0) {
- status = decode_putfh(&xdr);
- if (status == 0)
- status = decode_delegreturn(&xdr);
- }
+ if (status != 0)
+ goto out;
+ status = decode_putfh(&xdr);
+ if (status != 0)
+ goto out;
+ status = decode_delegreturn(&xdr);
+ decode_getfattr(&xdr, res->fattr, res->server);
+out:
return status;
}
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 1b272a135a31..e897e00c2c9d 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -275,7 +275,9 @@ static int __init root_nfs_parse(char *name, char *buf)
case Opt_noacl:
nfs_data.flags |= NFS_MOUNT_NOACL;
break;
- default :
+ default:
+ printk(KERN_WARNING "Root-NFS: unknown "
+ "option: %s\n", p);
return 0;
}
}
@@ -296,8 +298,8 @@ static int __init root_nfs_name(char *name)
nfs_port = -1;
nfs_data.version = NFS_MOUNT_VERSION;
nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */
- nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
- nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE;
+ nfs_data.rsize = NFS_DEF_FILE_IO_SIZE;
+ nfs_data.wsize = NFS_DEF_FILE_IO_SIZE;
nfs_data.acregmin = 3;
nfs_data.acregmax = 60;
nfs_data.acdirmin = 30;
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index e1e3ca5d746b..f5150d71c03d 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -111,6 +111,9 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
};
int status;
+ /* Mask out the non-modebit related stuff from attr->ia_mode */
+ sattr->ia_mode &= S_IALLUGO;
+
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0);
@@ -547,10 +550,9 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
-static void
-nfs_read_done(struct rpc_task *task)
+static void nfs_read_done(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata;
+ struct nfs_read_data *data = calldata;
if (task->tk_status >= 0) {
nfs_refresh_inode(data->inode, data->res.fattr);
@@ -560,9 +562,14 @@ nfs_read_done(struct rpc_task *task)
if (data->args.offset + data->args.count >= data->res.fattr->size)
data->res.eof = 1;
}
- nfs_readpage_result(task);
+ nfs_readpage_result(task, calldata);
}
+static const struct rpc_call_ops nfs_read_ops = {
+ .rpc_call_done = nfs_read_done,
+ .rpc_release = nfs_readdata_release,
+};
+
static void
nfs_proc_read_setup(struct nfs_read_data *data)
{
@@ -580,20 +587,24 @@ nfs_proc_read_setup(struct nfs_read_data *data)
flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_read_ops, data);
rpc_call_setup(task, &msg, 0);
}
-static void
-nfs_write_done(struct rpc_task *task)
+static void nfs_write_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+ struct nfs_write_data *data = calldata;
if (task->tk_status >= 0)
nfs_post_op_update_inode(data->inode, data->res.fattr);
- nfs_writeback_done(task);
+ nfs_writeback_done(task, calldata);
}
+static const struct rpc_call_ops nfs_write_ops = {
+ .rpc_call_done = nfs_write_done,
+ .rpc_release = nfs_writedata_release,
+};
+
static void
nfs_proc_write_setup(struct nfs_write_data *data, int how)
{
@@ -614,7 +625,7 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how)
flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC;
/* Finalize the task. */
- rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags);
+ rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data);
rpc_call_setup(task, &msg, 0);
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 5f20eafba8ec..05eb43fadf8e 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -42,9 +42,8 @@ mempool_t *nfs_rdata_mempool;
#define MIN_POOL_READ (32)
-void nfs_readdata_release(struct rpc_task *task)
+void nfs_readdata_release(void *data)
{
- struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
nfs_readdata_free(data);
}
@@ -84,7 +83,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
int result;
struct nfs_read_data *rdata;
- rdata = nfs_readdata_alloc();
+ rdata = nfs_readdata_alloc(1);
if (!rdata)
return -ENOMEM;
@@ -220,9 +219,6 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
NFS_PROTO(inode)->read_setup(data);
data->task.tk_cookie = (unsigned long)inode;
- data->task.tk_calldata = data;
- /* Release requests */
- data->task.tk_release = nfs_readdata_release;
dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
data->task.tk_pid,
@@ -287,7 +283,7 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
nbytes = req->wb_bytes;
for(;;) {
- data = nfs_readdata_alloc();
+ data = nfs_readdata_alloc(1);
if (!data)
goto out_bad;
INIT_LIST_HEAD(&data->pages);
@@ -343,7 +339,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)
if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
return nfs_pagein_multi(head, inode);
- data = nfs_readdata_alloc();
+ data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages);
if (!data)
goto out_bad;
@@ -452,9 +448,9 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
* This is the callback from RPC telling us whether a reply was
* received or some error occurred (timeout or socket shutdown).
*/
-void nfs_readpage_result(struct rpc_task *task)
+void nfs_readpage_result(struct rpc_task *task, void *calldata)
{
- struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
+ struct nfs_read_data *data = calldata;
struct nfs_readargs *argp = &data->args;
struct nfs_readres *resp = &data->res;
int status = task->tk_status;
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
new file mode 100644
index 000000000000..4c486eb867ca
--- /dev/null
+++ b/fs/nfs/sysctl.c
@@ -0,0 +1,84 @@
+/*
+ * linux/fs/nfs/sysctl.c
+ *
+ * Sysctl interface to NFS parameters
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/linkage.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <linux/sysctl.h>
+#include <linux/module.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_idmap.h>
+
+#include "callback.h"
+
+static const int nfs_set_port_min = 0;
+static const int nfs_set_port_max = 65535;
+static struct ctl_table_header *nfs_callback_sysctl_table;
+/*
+ * Something that isn't CTL_ANY, CTL_NONE or a value that may clash.
+ * Use the same values as fs/lockd/svc.c
+ */
+#define CTL_UNNUMBERED -2
+
+static ctl_table nfs_cb_sysctls[] = {
+#ifdef CONFIG_NFS_V4
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nfs_callback_tcpport",
+ .data = &nfs_callback_set_tcpport,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = (int *)&nfs_set_port_min,
+ .extra2 = (int *)&nfs_set_port_max,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "idmap_cache_timeout",
+ .data = &nfs_idmap_cache_timeout,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
+ },
+#endif
+ { .ctl_name = 0 }
+};
+
+static ctl_table nfs_cb_sysctl_dir[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nfs",
+ .mode = 0555,
+ .child = nfs_cb_sysctls,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table nfs_cb_sysctl_root[] = {
+ {
+ .ctl_name = CTL_FS,
+ .procname = "fs",
+ .mode = 0555,
+ .child = nfs_cb_sysctl_dir,
+ },
+ { .ctl_name = 0 }
+};
+
+int nfs_register_sysctl(void)
+{
+ nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root, 0);
+ if (nfs_callback_sysctl_table == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+void nfs_unregister_sysctl(void)
+{
+ unregister_sysctl_table(nfs_callback_sysctl_table);
+ nfs_callback_sysctl_table = NULL;
+}
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index d639d172d568..a65c7b53d558 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -87,10 +87,9 @@ nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
* We delay initializing RPC info until after the call to dentry_iput()
* in order to minimize races against rename().
*/
-static void
-nfs_async_unlink_init(struct rpc_task *task)
+static void nfs_async_unlink_init(struct rpc_task *task, void *calldata)
{
- struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata;
+ struct nfs_unlinkdata *data = calldata;
struct dentry *dir = data->dir;
struct rpc_message msg = {
.rpc_cred = data->cred,
@@ -116,10 +115,9 @@ nfs_async_unlink_init(struct rpc_task *task)
*
* Do the directory attribute update.
*/
-static void
-nfs_async_unlink_done(struct rpc_task *task)
+static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
{
- struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata;
+ struct nfs_unlinkdata *data = calldata;
struct dentry *dir = data->dir;
struct inode *dir_i;
@@ -141,13 +139,18 @@ nfs_async_unlink_done(struct rpc_task *task)
* We need to call nfs_put_unlinkdata as a 'tk_release' task since the
* rpc_task would be freed too.
*/
-static void
-nfs_async_unlink_release(struct rpc_task *task)
+static void nfs_async_unlink_release(void *calldata)
{
- struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata;
+ struct nfs_unlinkdata *data = calldata;
nfs_put_unlinkdata(data);
}
+static const struct rpc_call_ops nfs_unlink_ops = {
+ .rpc_call_prepare = nfs_async_unlink_init,
+ .rpc_call_done = nfs_async_unlink_done,
+ .rpc_release = nfs_async_unlink_release,
+};
+
/**
* nfs_async_unlink - asynchronous unlinking of a file
* @dentry: dentry to unlink
@@ -157,7 +160,6 @@ nfs_async_unlink(struct dentry *dentry)
{
struct dentry *dir = dentry->d_parent;
struct nfs_unlinkdata *data;
- struct rpc_task *task;
struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode);
int status = -ENOMEM;
@@ -178,17 +180,13 @@ nfs_async_unlink(struct dentry *dentry)
nfs_deletes = data;
data->count = 1;
- task = &data->task;
- rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC);
- task->tk_calldata = data;
- task->tk_action = nfs_async_unlink_init;
- task->tk_release = nfs_async_unlink_release;
+ rpc_init_task(&data->task, clnt, RPC_TASK_ASYNC, &nfs_unlink_ops, data);
spin_lock(&dentry->d_lock);
dentry->d_flags |= DCACHE_NFSFS_RENAMED;
spin_unlock(&dentry->d_lock);
- rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);
+ rpc_sleep_on(&nfs_delete_queue, &data->task, NULL, NULL);
status = 0;
out:
return status;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 3107908e5f3f..9449b6835509 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -89,24 +89,38 @@ static mempool_t *nfs_commit_mempool;
static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
-static inline struct nfs_write_data *nfs_commit_alloc(void)
+static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
{
struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
+
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
+ if (pagecount < NFS_PAGEVEC_SIZE)
+ p->pagevec = &p->page_array[0];
+ else {
+ size_t size = ++pagecount * sizeof(struct page *);
+ p->pagevec = kmalloc(size, GFP_NOFS);
+ if (p->pagevec) {
+ memset(p->pagevec, 0, size);
+ } else {
+ mempool_free(p, nfs_commit_mempool);
+ p = NULL;
+ }
+ }
}
return p;
}
static inline void nfs_commit_free(struct nfs_write_data *p)
{
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
mempool_free(p, nfs_commit_mempool);
}
-static void nfs_writedata_release(struct rpc_task *task)
+void nfs_writedata_release(void *wdata)
{
- struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
nfs_writedata_free(wdata);
}
@@ -168,7 +182,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
int result, written = 0;
struct nfs_write_data *wdata;
- wdata = nfs_writedata_alloc();
+ wdata = nfs_writedata_alloc(1);
if (!wdata)
return -ENOMEM;
@@ -232,19 +246,16 @@ static int nfs_writepage_async(struct nfs_open_context *ctx,
unsigned int offset, unsigned int count)
{
struct nfs_page *req;
- int status;
req = nfs_update_request(ctx, inode, page, offset, count);
- status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
- if (status < 0)
- goto out;
+ if (IS_ERR(req))
+ return PTR_ERR(req);
/* Update file length */
nfs_grow_file(page, offset, count);
/* Set the PG_uptodate flag? */
nfs_mark_uptodate(page, offset, count);
nfs_unlock_request(req);
- out:
- return status;
+ return 0;
}
static int wb_priority(struct writeback_control *wbc)
@@ -304,11 +315,8 @@ do_it:
lock_kernel();
if (!IS_SYNC(inode) && inode_referenced) {
err = nfs_writepage_async(ctx, inode, page, 0, offset);
- if (err >= 0) {
- err = 0;
- if (wbc->for_reclaim)
- nfs_flush_inode(inode, 0, 0, FLUSH_STABLE);
- }
+ if (!wbc->for_writepages)
+ nfs_flush_inode(inode, 0, 0, wb_priority(wbc));
} else {
err = nfs_writepage_sync(ctx, inode, page, 0,
offset, priority);
@@ -877,9 +885,6 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
data->task.tk_priority = flush_task_priority(how);
data->task.tk_cookie = (unsigned long)inode;
- data->task.tk_calldata = data;
- /* Release requests */
- data->task.tk_release = nfs_writedata_release;
dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n",
data->task.tk_pid,
@@ -919,7 +924,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how)
nbytes = req->wb_bytes;
for (;;) {
- data = nfs_writedata_alloc();
+ data = nfs_writedata_alloc(1);
if (!data)
goto out_bad;
list_add(&data->pages, &list);
@@ -983,7 +988,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE)
return nfs_flush_multi(head, inode, how);
- data = nfs_writedata_alloc();
+ data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
if (!data)
goto out_bad;
@@ -1137,9 +1142,9 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
/*
* This function is called when the WRITE call is complete.
*/
-void nfs_writeback_done(struct rpc_task *task)
+void nfs_writeback_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata;
+ struct nfs_write_data *data = calldata;
struct nfs_writeargs *argp = &data->args;
struct nfs_writeres *resp = &data->res;
@@ -1206,9 +1211,8 @@ void nfs_writeback_done(struct rpc_task *task)
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-static void nfs_commit_release(struct rpc_task *task)
+void nfs_commit_release(void *wdata)
{
- struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata;
nfs_commit_free(wdata);
}
@@ -1244,9 +1248,6 @@ static void nfs_commit_rpcsetup(struct list_head *head,
data->task.tk_priority = flush_task_priority(how);
data->task.tk_cookie = (unsigned long)inode;
- data->task.tk_calldata = data;
- /* Release requests */
- data->task.tk_release = nfs_commit_release;
dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid);
}
@@ -1255,12 +1256,12 @@ static void nfs_commit_rpcsetup(struct list_head *head,
* Commit dirty pages
*/
static int
-nfs_commit_list(struct list_head *head, int how)
+nfs_commit_list(struct inode *inode, struct list_head *head, int how)
{
struct nfs_write_data *data;
struct nfs_page *req;
- data = nfs_commit_alloc();
+ data = nfs_commit_alloc(NFS_SERVER(inode)->wpages);
if (!data)
goto out_bad;
@@ -1283,10 +1284,9 @@ nfs_commit_list(struct list_head *head, int how)
/*
* COMMIT call returned
*/
-void
-nfs_commit_done(struct rpc_task *task)
+void nfs_commit_done(struct rpc_task *task, void *calldata)
{
- struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata;
+ struct nfs_write_data *data = calldata;
struct nfs_page *req;
int res = 0;
@@ -1366,7 +1366,7 @@ int nfs_commit_inode(struct inode *inode, int how)
res = nfs_scan_commit(inode, &head, 0, 0);
spin_unlock(&nfsi->req_lock);
if (res) {
- error = nfs_commit_list(&head, how);
+ error = nfs_commit_list(inode, &head, how);
if (error < 0)
return error;
}
@@ -1377,22 +1377,23 @@ int nfs_commit_inode(struct inode *inode, int how)
int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
unsigned int npages, int how)
{
- int error,
- wait;
+ int nocommit = how & FLUSH_NOCOMMIT;
+ int wait = how & FLUSH_WAIT;
+ int error;
- wait = how & FLUSH_WAIT;
- how &= ~FLUSH_WAIT;
+ how &= ~(FLUSH_WAIT|FLUSH_NOCOMMIT);
do {
- error = 0;
- if (wait)
+ if (wait) {
error = nfs_wait_on_requests(inode, idx_start, npages);
- if (error == 0)
- error = nfs_flush_inode(inode, idx_start, npages, how);
-#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
- if (error == 0)
+ if (error != 0)
+ continue;
+ }
+ error = nfs_flush_inode(inode, idx_start, npages, how);
+ if (error != 0)
+ continue;
+ if (!nocommit)
error = nfs_commit_inode(inode, how);
-#endif
} while (error > 0);
return error;
}
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index 0b14938b5b62..0d4cf9486068 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -5,6 +5,7 @@
*
*/
#include <linux/config.h>
+#include <linux/types.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/sunrpc/svc.h>
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 041380fe667b..6d2dfed1de08 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -56,13 +56,20 @@ static int
nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
struct nfsd3_attrstat *resp)
{
- int nfserr;
+ int err, nfserr;
dprintk("nfsd: GETATTR(3) %s\n",
- SVCFH_fmt(&argp->fh));
+ SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ if (nfserr)
+ RETURN_STATUS(nfserr);
+
+ err = vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry, &resp->stat);
+ nfserr = nfserrno(err);
+
RETURN_STATUS(nfserr);
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 9147b8524d05..243d94b9653a 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -154,37 +154,34 @@ decode_sattr3(u32 *p, struct iattr *iap)
}
static inline u32 *
-encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+ struct kstat *stat)
{
- struct vfsmount *mnt = fhp->fh_export->ex_mnt;
struct dentry *dentry = fhp->fh_dentry;
- struct kstat stat;
struct timespec time;
- vfs_getattr(mnt, dentry, &stat);
-
- *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]);
- *p++ = htonl((u32) stat.mode);
- *p++ = htonl((u32) stat.nlink);
- *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
- *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
- if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) {
+ *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
+ *p++ = htonl((u32) stat->mode);
+ *p++ = htonl((u32) stat->nlink);
+ *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
+ if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
} else {
- p = xdr_encode_hyper(p, (u64) stat.size);
+ p = xdr_encode_hyper(p, (u64) stat->size);
}
- p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9);
- *p++ = htonl((u32) MAJOR(stat.rdev));
- *p++ = htonl((u32) MINOR(stat.rdev));
+ p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
+ *p++ = htonl((u32) MAJOR(stat->rdev));
+ *p++ = htonl((u32) MINOR(stat->rdev));
if (is_fsid(fhp, rqstp->rq_reffh))
p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
else
- p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev));
- p = xdr_encode_hyper(p, (u64) stat.ino);
- p = encode_time3(p, &stat.atime);
+ p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
+ p = xdr_encode_hyper(p, (u64) stat->ino);
+ p = encode_time3(p, &stat->atime);
lease_get_mtime(dentry->d_inode, &time);
p = encode_time3(p, &time);
- p = encode_time3(p, &stat.ctime);
+ p = encode_time3(p, &stat->ctime);
return p;
}
@@ -232,8 +229,14 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{
struct dentry *dentry = fhp->fh_dentry;
if (dentry && dentry->d_inode != NULL) {
- *p++ = xdr_one; /* attributes follow */
- return encode_fattr3(rqstp, p, fhp);
+ int err;
+ struct kstat stat;
+
+ err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
+ if (!err) {
+ *p++ = xdr_one; /* attributes follow */
+ return encode_fattr3(rqstp, p, fhp, &stat);
+ }
}
*p++ = xdr_zero;
return p;
@@ -616,7 +619,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_attrstat *resp)
{
if (resp->status == 0)
- p = encode_fattr3(rqstp, p, &resp->fh);
+ p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
return xdr_ressize_check(rqstp, p);
}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 583c0710e45e..d828662d737d 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -53,7 +53,7 @@
#define NFSPROC4_CB_COMPOUND 1
/* declarations */
-static void nfs4_cb_null(struct rpc_task *task);
+static const struct rpc_call_ops nfs4_cb_null_ops;
/* Index of predefined Linux callback client operations */
@@ -431,7 +431,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
}
clnt->cl_intr = 0;
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
/* Kick rpciod, put the call on the wire. */
@@ -447,7 +446,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
msg.rpc_cred = nfsd4_lookupcred(clp,0);
if (IS_ERR(msg.rpc_cred))
goto out_rpciod;
- status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL);
+ status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
put_rpccred(msg.rpc_cred);
if (status != 0) {
@@ -469,7 +468,7 @@ out_err:
}
static void
-nfs4_cb_null(struct rpc_task *task)
+nfs4_cb_null(struct rpc_task *task, void *dummy)
{
struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp;
struct nfs4_callback *cb = &clp->cl_callback;
@@ -488,6 +487,10 @@ out:
put_nfs4_client(clp);
}
+static const struct rpc_call_ops nfs4_cb_null_ops = {
+ .rpc_call_done = nfs4_cb_null,
+};
+
/*
* called with dp->dl_count inc'ed.
* nfs4_lock_state() may or may not have been called.
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 361b4007d4a0..a00fe8686293 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -192,6 +192,14 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
}
if (status)
goto out;
+
+ /* Openowner is now set, so sequence id will get bumped. Now we need
+ * these checks before we do any creates: */
+ if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_grace;
+ if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
+ return nfserr_no_grace;
+
switch (open->op_claim_type) {
case NFS4_OPEN_CLAIM_DELEGATE_CUR:
status = nfserr_inval;
@@ -210,6 +218,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
goto out;
break;
case NFS4_OPEN_CLAIM_PREVIOUS:
+ open->op_stateowner->so_confirmed = 1;
/*
* The CURRENT_FH is already set to the file being
* opened. (1) set open->op_cinfo, (2) set
@@ -221,6 +230,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
goto out;
break;
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ open->op_stateowner->so_confirmed = 1;
printk("NFSD: unsupported OPEN claim type %d\n",
open->op_claim_type);
status = nfserr_notsupp;
@@ -584,31 +594,23 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
{
int status = nfs_ok;
- if (!current_fh->fh_dentry)
- return nfserr_nofilehandle;
-
- status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh,
- &setattr->sa_stateid,
- CHECK_FH | WR_STATE, NULL))) {
- dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
- goto out_unlock;
- }
+ status = nfs4_preprocess_stateid_op(current_fh,
+ &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
nfs4_unlock_state();
+ if (status) {
+ dprintk("NFSD: nfsd4_setattr: couldn't process stateid!");
+ return status;
+ }
}
status = nfs_ok;
if (setattr->sa_acl != NULL)
status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
if (status)
- goto out;
+ return status;
status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
0, (time_t)0);
-out:
- return status;
-out_unlock:
- nfs4_unlock_state();
return status;
}
@@ -626,15 +628,17 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
- CHECK_FH | WR_STATE, &filp))) {
- dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
- goto out;
- }
+ status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ CHECK_FH | WR_STATE, &filp);
if (filp)
get_file(filp);
nfs4_unlock_state();
+ if (status) {
+ dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
+ return status;
+ }
+
write->wr_bytes_written = write->wr_buflen;
write->wr_how_written = write->wr_stable_how;
p = (u32 *)write->wr_verifier.data;
@@ -650,9 +654,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
if (status == nfserr_symlink)
status = nfserr_inval;
return status;
-out:
- nfs4_unlock_state();
- return status;
}
/* This routine never returns NFS_OK! If there are no other errors, it
@@ -768,6 +769,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
while (!status && resp->opcnt < args->opcnt) {
op = &args->ops[resp->opcnt++];
+ dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
+
/*
* The XDR decode routines may have pre-set op->status;
* for example, if there is a miscellaneous XDR error
@@ -792,17 +795,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
/* All operations except RENEW, SETCLIENTID, RESTOREFH
* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
* require a valid current filehandle
- *
- * SETATTR NOFILEHANDLE error handled in nfsd4_setattr
- * due to required returned bitmap argument
*/
if ((!current_fh->fh_dentry) &&
!((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) ||
(op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) ||
- (op->opnum == OP_RELEASE_LOCKOWNER) ||
- (op->opnum == OP_SETATTR))) {
+ (op->opnum == OP_RELEASE_LOCKOWNER))) {
op->status = nfserr_nofilehandle;
goto encode_op;
}
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 954cf893d50c..06da7506363c 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -121,9 +121,9 @@ out:
static void
nfsd4_sync_rec_dir(void)
{
- down(&rec_dir.dentry->d_inode->i_sem);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
nfsd_sync_dir(rec_dir.dentry);
- up(&rec_dir.dentry->d_inode->i_sem);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
}
int
@@ -143,7 +143,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
nfs4_save_user(&uid, &gid);
/* lock the parent */
- down(&rec_dir.dentry->d_inode->i_sem);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
if (IS_ERR(dentry)) {
@@ -159,7 +159,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
out_put:
dput(dentry);
out_unlock:
- up(&rec_dir.dentry->d_inode->i_sem);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
if (status == 0) {
clp->cl_firststate = 1;
nfsd4_sync_rec_dir();
@@ -222,8 +222,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
nfs4_save_user(&uid, &gid);
- filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
- O_RDWR);
+ filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY);
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
@@ -259,9 +258,9 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
printk("nfsd4: non-file found in client recovery directory\n");
return -EINVAL;
}
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
status = vfs_unlink(dir->d_inode, dentry);
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
@@ -274,9 +273,9 @@ nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
* any regular files anyway, just in case the directory was created by
* a kernel from the future.... */
nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
status = vfs_rmdir(dir->d_inode, dentry);
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return status;
}
@@ -288,9 +287,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen)
dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
- down(&rec_dir.dentry->d_inode->i_sem);
+ mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
dentry = lookup_one_len(name, rec_dir.dentry, namlen);
- up(&rec_dir.dentry->d_inode->i_sem);
+ mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
if (IS_ERR(dentry)) {
status = PTR_ERR(dentry);
return status;
@@ -400,9 +399,10 @@ nfsd4_init_recdir(char *rec_dirname)
nfs4_save_user(&uid, &gid);
- status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
- if (status == -ENOENT)
- printk("NFSD: recovery directory %s doesn't exist\n",
+ status = path_lookup(rec_dirname, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+ &rec_dir);
+ if (status)
+ printk("NFSD: unable to find recovery directory %s\n",
rec_dirname);
if (!status)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6bbefd06f10d..1143cfb64549 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1088,7 +1088,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_seqid = open->op_seqid;
sop->so_confirmed = 0;
rp = &sop->so_replay;
- rp->rp_status = NFSERR_SERVERFAULT;
+ rp->rp_status = nfserr_serverfault;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
return sop;
@@ -1178,7 +1178,6 @@ release_stateid(struct nfs4_stateid *stp, int flags)
locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
put_nfs4_file(stp->st_file);
kmem_cache_free(stateid_slab, stp);
- stp = NULL;
}
static void
@@ -1191,22 +1190,6 @@ move_to_close_lru(struct nfs4_stateowner *sop)
sop->so_time = get_seconds();
}
-static void
-release_state_owner(struct nfs4_stateid *stp, int flag)
-{
- struct nfs4_stateowner *sop = stp->st_stateowner;
-
- dprintk("NFSD: release_state_owner\n");
- release_stateid(stp, flag);
-
- /* place unused nfs4_stateowners on so_close_lru list to be
- * released by the laundromat service after the lease period
- * to enable us to handle CLOSE replay
- */
- if (sop->so_confirmed && list_empty(&sop->so_stateids))
- move_to_close_lru(sop);
-}
-
static int
cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) {
return ((sop->so_owner.len == owner->len) &&
@@ -1446,92 +1429,61 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
};
-/*
- * nfsd4_process_open1()
- * lookup stateowner.
- * found:
- * check confirmed
- * confirmed:
- * check seqid
- * not confirmed:
- * delete owner
- * create new owner
- * notfound:
- * verify clientid
- * create new owner
- *
- * called with nfs4_lock_state() held.
- */
int
nfsd4_process_open1(struct nfsd4_open *open)
{
- int status;
clientid_t *clientid = &open->op_clientid;
struct nfs4_client *clp = NULL;
unsigned int strhashval;
struct nfs4_stateowner *sop = NULL;
- status = nfserr_inval;
if (!check_name(open->op_owner))
- goto out;
+ return nfserr_inval;
if (STALE_CLIENTID(&open->op_clientid))
return nfserr_stale_clientid;
strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
sop = find_openstateowner_str(strhashval, open);
- if (sop) {
- open->op_stateowner = sop;
- /* check for replay */
- if (open->op_seqid == sop->so_seqid - 1){
- if (sop->so_replay.rp_buflen)
- return NFSERR_REPLAY_ME;
- else {
- /* The original OPEN failed so spectacularly
- * that we don't even have replay data saved!
- * Therefore, we have no choice but to continue
- * processing this OPEN; presumably, we'll
- * fail again for the same reason.
- */
- dprintk("nfsd4_process_open1:"
- " replay with no replay cache\n");
- goto renew;
- }
- } else if (sop->so_confirmed) {
- if (open->op_seqid == sop->so_seqid)
- goto renew;
- status = nfserr_bad_seqid;
- goto out;
- } else {
- /* If we get here, we received an OPEN for an
- * unconfirmed nfs4_stateowner. Since the seqid's are
- * different, purge the existing nfs4_stateowner, and
- * instantiate a new one.
- */
- clp = sop->so_client;
- release_stateowner(sop);
- }
- } else {
- /* nfs4_stateowner not found.
- * Verify clientid and instantiate new nfs4_stateowner.
- * If verify fails this is presumably the result of the
- * client's lease expiring.
- */
- status = nfserr_expired;
+ open->op_stateowner = sop;
+ if (!sop) {
+ /* Make sure the client's lease hasn't expired. */
clp = find_confirmed_client(clientid);
if (clp == NULL)
- goto out;
+ return nfserr_expired;
+ goto renew;
}
- status = nfserr_resource;
- sop = alloc_init_open_stateowner(strhashval, clp, open);
- if (sop == NULL)
- goto out;
- open->op_stateowner = sop;
+ if (!sop->so_confirmed) {
+ /* Replace unconfirmed owners without checking for replay. */
+ clp = sop->so_client;
+ release_stateowner(sop);
+ open->op_stateowner = NULL;
+ goto renew;
+ }
+ if (open->op_seqid == sop->so_seqid - 1) {
+ if (sop->so_replay.rp_buflen)
+ return NFSERR_REPLAY_ME;
+ /* The original OPEN failed so spectacularly
+ * that we don't even have replay data saved!
+ * Therefore, we have no choice but to continue
+ * processing this OPEN; presumably, we'll
+ * fail again for the same reason.
+ */
+ dprintk("nfsd4_process_open1: replay with no replay cache\n");
+ goto renew;
+ }
+ if (open->op_seqid != sop->so_seqid)
+ return nfserr_bad_seqid;
renew:
- status = nfs_ok;
+ if (open->op_stateowner == NULL) {
+ sop = alloc_init_open_stateowner(strhashval, clp, open);
+ if (sop == NULL)
+ return nfserr_resource;
+ open->op_stateowner = sop;
+ }
+ list_del_init(&sop->so_close_lru);
renew_client(sop->so_client);
-out:
- return status;
+ return nfs_ok;
}
static inline int
@@ -1648,7 +1600,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
if (!open->op_truncate)
return 0;
if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
- return -EINVAL;
+ return nfserr_inval;
return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
}
@@ -1657,26 +1609,26 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
{
struct file *filp = stp->st_vfs_file;
struct inode *inode = filp->f_dentry->d_inode;
- unsigned int share_access;
+ unsigned int share_access, new_writer;
int status;
set_access(&share_access, stp->st_access_bmap);
- share_access = ~share_access;
- share_access &= open->op_share_access;
-
- if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
- return nfsd4_truncate(rqstp, cur_fh, open);
+ new_writer = (~share_access) & open->op_share_access
+ & NFS4_SHARE_ACCESS_WRITE;
- status = get_write_access(inode);
- if (status)
- return nfserrno(status);
+ if (new_writer) {
+ status = get_write_access(inode);
+ if (status)
+ return nfserrno(status);
+ }
status = nfsd4_truncate(rqstp, cur_fh, open);
if (status) {
- put_write_access(inode);
+ if (new_writer)
+ put_write_access(inode);
return status;
}
/* remember the open */
- filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+ filp->f_mode |= open->op_share_access;
set_bit(open->op_share_access, &stp->st_access_bmap);
set_bit(open->op_share_deny, &stp->st_deny_bmap);
@@ -1780,12 +1732,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct nfs4_delegation *dp = NULL;
int status;
- if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
- return nfserr_grace;
-
- if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
- return nfserr_no_grace;
-
status = nfserr_inval;
if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
goto out;
@@ -2423,15 +2369,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
CHECK_FH | OPEN_STATE | CLOSE_STATE,
&close->cl_stateowner, &stp, NULL)))
goto out;
- /*
- * Return success, but first update the stateid.
- */
status = nfs_ok;
update_stateid(&stp->st_stateid);
memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
- /* release_state_owner() calls nfsd_close() if needed */
- release_state_owner(stp, OPEN_STATE);
+ /* release_stateid() calls nfsd_close() if needed */
+ release_stateid(stp, OPEN_STATE);
+
+ /* place unused nfs4_stateowners on so_close_lru list to be
+ * released by the laundromat service after the lease period
+ * to enable us to handle CLOSE replay
+ */
+ if (list_empty(&close->cl_stateowner->so_stateids))
+ move_to_close_lru(close->cl_stateowner);
out:
if (close->cl_stateowner) {
nfs4_get_stateowner(close->cl_stateowner);
@@ -2633,7 +2583,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
sop->so_seqid = lock->lk_new_lock_seqid + 1;
sop->so_confirmed = 1;
rp = &sop->so_replay;
- rp->rp_status = NFSERR_SERVERFAULT;
+ rp->rp_status = nfserr_serverfault;
rp->rp_buflen = 0;
rp->rp_buf = rp->rp_ibuf;
return sop;
@@ -2700,6 +2650,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (check_lock_length(lock->lk_offset, lock->lk_length))
return nfserr_inval;
+ if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+ dprintk("NFSD: nfsd4_lock: permission denied!\n");
+ return status;
+ }
+
nfs4_lock_state();
if (lock->lk_is_new) {
@@ -2720,11 +2675,11 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
lock->lk_new_open_seqid,
&lock->lk_new_open_stateid,
CHECK_FH | OPEN_STATE,
- &lock->lk_stateowner, &open_stp,
+ &lock->lk_replay_owner, &open_stp,
lock);
if (status)
goto out;
- open_sop = lock->lk_stateowner;
+ open_sop = lock->lk_replay_owner;
/* create lockowner and lock stateid */
fp = open_stp->st_file;
strhashval = lock_ownerstr_hashval(fp->fi_inode,
@@ -2739,29 +2694,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
if (lock_sop == NULL)
goto out;
lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
- if (lock_stp == NULL) {
- release_stateowner(lock_sop);
+ if (lock_stp == NULL)
goto out;
- }
} else {
/* lock (lock owner + lock stateid) already exists */
status = nfs4_preprocess_seqid_op(current_fh,
lock->lk_old_lock_seqid,
&lock->lk_old_lock_stateid,
CHECK_FH | LOCK_STATE,
- &lock->lk_stateowner, &lock_stp, lock);
+ &lock->lk_replay_owner, &lock_stp, lock);
if (status)
goto out;
- lock_sop = lock->lk_stateowner;
+ lock_sop = lock->lk_replay_owner;
}
- /* lock->lk_stateowner and lock_stp have been created or found */
+ /* lock->lk_replay_owner 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))) {
- dprintk("NFSD: nfsd4_lock: permission denied!\n");
- goto out;
- }
-
status = nfserr_grace;
if (nfs4_in_grace() && !lock->lk_reclaim)
goto out;
@@ -2802,8 +2750,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
*/
status = posix_lock_file(filp, &file_lock);
- if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
- file_lock.fl_ops->fl_release_private(&file_lock);
dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
switch (-status) {
case 0: /* success! */
@@ -2815,9 +2761,12 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
goto conflicting_lock;
case (EDEADLK):
status = nfserr_deadlock;
+ dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
+ goto out;
default:
+ status = nfserrno(status);
dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status);
- goto out_destroy_new_stateid;
+ goto out;
}
conflicting_lock:
@@ -2831,20 +2780,12 @@ conflicting_lock:
goto out;
}
nfs4_set_lock_denied(conflock, &lock->lk_denied);
-
-out_destroy_new_stateid:
- if (lock->lk_is_new) {
- dprintk("NFSD: nfsd4_lock: destroy new stateid!\n");
- /*
- * An error encountered after instantiation of the new
- * stateid has forced us to destroy it.
- */
- release_state_owner(lock_stp, LOCK_STATE);
- }
out:
- if (lock->lk_stateowner) {
- nfs4_get_stateowner(lock->lk_stateowner);
- *replay_owner = lock->lk_stateowner;
+ if (status && lock->lk_is_new && lock_sop)
+ release_stateowner(lock_sop);
+ if (lock->lk_replay_owner) {
+ nfs4_get_stateowner(lock->lk_replay_owner);
+ *replay_owner = lock->lk_replay_owner;
}
nfs4_unlock_state();
return status;
@@ -2977,8 +2918,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
* Try to unlock the file in the VFS.
*/
status = posix_lock_file(filp, &file_lock);
- if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
- file_lock.fl_ops->fl_release_private(&file_lock);
if (status) {
dprintk("NFSD: nfs4_locku: posix_lock_file failed!\n");
goto out_nfserr;
@@ -3016,9 +2955,10 @@ check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
lock_kernel();
for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
- if ((*flpp)->fl_owner == (fl_owner_t)lowner)
+ if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
status = 1;
goto out;
+ }
}
out:
unlock_kernel();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index dcd673186944..69d3501173a8 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -528,7 +528,7 @@ nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
{
DECODE_HEAD;
- lock->lk_stateowner = NULL;
+ lock->lk_replay_owner = NULL;
/*
* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
*/
@@ -1764,10 +1764,11 @@ nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
*/
if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
goto fail;
- nfserr = nfserr_toosmall;
p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
- if (p == NULL)
+ if (p == NULL) {
+ nfserr = nfserr_toosmall;
goto fail;
+ }
}
cd->buflen -= (p - cd->buffer);
cd->buffer = p;
@@ -1895,7 +1896,6 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie
static void
nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
{
-
ENCODE_SEQID_OP_HEAD;
if (!nfserr) {
@@ -1906,7 +1906,7 @@ nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock
} else if (nfserr == nfserr_denied)
nfsd4_encode_lock_denied(resp, &lock->lk_denied);
- ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
+ ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
}
static void
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 0aa1b9603d7f..3e6b75cd90fd 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -36,6 +36,22 @@ nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
return nfs_ok;
}
+static int
+nfsd_return_attrs(int err, struct nfsd_attrstat *resp)
+{
+ if (err) return err;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
+}
+static int
+nfsd_return_dirop(int err, struct nfsd_diropres *resp)
+{
+ if (err) return err;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
+}
/*
* Get a file's attributes
* N.B. After this call resp->fh needs an fh_put
@@ -44,10 +60,12 @@ static int
nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
struct nfsd_attrstat *resp)
{
+ int nfserr;
dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
fh_copy(&resp->fh, &argp->fh);
- return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -58,12 +76,14 @@ static int
nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
struct nfsd_attrstat *resp)
{
+ int nfserr;
dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
SVCFH_fmt(&argp->fh),
argp->attrs.ia_valid, (long) argp->attrs.ia_size);
fh_copy(&resp->fh, &argp->fh);
- return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+ nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -86,7 +106,7 @@ nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
&resp->fh);
fh_put(&argp->fh);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
/*
@@ -142,7 +162,10 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
argp->vec, argp->vlen,
&resp->count);
- return nfserr;
+ if (nfserr) return nfserr;
+ return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt,
+ resp->fh.fh_dentry,
+ &resp->stat));
}
/*
@@ -165,7 +188,7 @@ nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
argp->vec, argp->vlen,
argp->len,
&stable);
- return nfserr;
+ return nfsd_return_attrs(nfserr, resp);
}
/*
@@ -322,7 +345,7 @@ out_unlock:
done:
fh_put(dirfhp);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
static int
@@ -425,7 +448,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
&argp->attrs, S_IFDIR, 0, &resp->fh);
fh_put(&argp->fh);
- return nfserr;
+ return nfsd_return_dirop(nfserr, resp);
}
/*
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index b45999ff33e6..e3a0797dd56b 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -37,7 +37,7 @@ static u32 nfs_ftypes[] = {
/*
* XDR functions for basic NFS types
*/
-static inline u32 *
+static u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
fh_init(fhp, NFS_FHSIZE);
@@ -151,47 +151,45 @@ decode_sattr(u32 *p, struct iattr *iap)
return p;
}
-static inline u32 *
-encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+static u32 *
+encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp,
+ struct kstat *stat)
{
- struct vfsmount *mnt = fhp->fh_export->ex_mnt;
struct dentry *dentry = fhp->fh_dentry;
- struct kstat stat;
int type;
struct timespec time;
- vfs_getattr(mnt, dentry, &stat);
- type = (stat.mode & S_IFMT);
+ type = (stat->mode & S_IFMT);
*p++ = htonl(nfs_ftypes[type >> 12]);
- *p++ = htonl((u32) stat.mode);
- *p++ = htonl((u32) stat.nlink);
- *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
- *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
+ *p++ = htonl((u32) stat->mode);
+ *p++ = htonl((u32) stat->nlink);
+ *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
- if (S_ISLNK(type) && stat.size > NFS_MAXPATHLEN) {
+ if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
*p++ = htonl(NFS_MAXPATHLEN);
} else {
- *p++ = htonl((u32) stat.size);
+ *p++ = htonl((u32) stat->size);
}
- *p++ = htonl((u32) stat.blksize);
+ *p++ = htonl((u32) stat->blksize);
if (S_ISCHR(type) || S_ISBLK(type))
- *p++ = htonl(new_encode_dev(stat.rdev));
+ *p++ = htonl(new_encode_dev(stat->rdev));
else
*p++ = htonl(0xffffffff);
- *p++ = htonl((u32) stat.blocks);
+ *p++ = htonl((u32) stat->blocks);
if (is_fsid(fhp, rqstp->rq_reffh))
*p++ = htonl((u32) fhp->fh_export->ex_fsid);
else
- *p++ = htonl(new_encode_dev(stat.dev));
- *p++ = htonl((u32) stat.ino);
- *p++ = htonl((u32) stat.atime.tv_sec);
- *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0);
+ *p++ = htonl(new_encode_dev(stat->dev));
+ *p++ = htonl((u32) stat->ino);
+ *p++ = htonl((u32) stat->atime.tv_sec);
+ *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
lease_get_mtime(dentry->d_inode, &time);
*p++ = htonl((u32) time.tv_sec);
*p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0);
- *p++ = htonl((u32) stat.ctime.tv_sec);
- *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0);
+ *p++ = htonl((u32) stat->ctime.tv_sec);
+ *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0);
return p;
}
@@ -199,7 +197,9 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
/* Helper function for NFSv2 ACL code */
u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{
- return encode_fattr(rqstp, p, fhp);
+ struct kstat stat;
+ vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat);
+ return encode_fattr(rqstp, p, fhp, &stat);
}
/*
@@ -394,7 +394,7 @@ int
nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd_attrstat *resp)
{
- p = encode_fattr(rqstp, p, &resp->fh);
+ p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
return xdr_ressize_check(rqstp, p);
}
@@ -403,7 +403,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
struct nfsd_diropres *resp)
{
p = encode_fh(p, &resp->fh);
- p = encode_fattr(rqstp, p, &resp->fh);
+ p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
return xdr_ressize_check(rqstp, p);
}
@@ -428,7 +428,7 @@ int
nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p,
struct nfsd_readres *resp)
{
- p = encode_fattr(rqstp, p, &resp->fh);
+ p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
*p++ = htonl(resp->count);
xdr_ressize_check(rqstp, p);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index af7c3c3074b0..5320e5afaddb 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -48,8 +48,8 @@
#include <linux/fsnotify.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl_xattr.h>
-#ifdef CONFIG_NFSD_V4
#include <linux/xattr.h>
+#ifdef CONFIG_NFSD_V4
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
#include <linux/nfsd_idmap.h>
@@ -365,8 +365,30 @@ out_nfserr:
goto out;
}
-#if defined(CONFIG_NFSD_V4)
+#if defined(CONFIG_NFSD_V2_ACL) || \
+ defined(CONFIG_NFSD_V3_ACL) || \
+ defined(CONFIG_NFSD_V4)
+static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
+{
+ ssize_t buflen;
+ int error;
+
+ buflen = vfs_getxattr(dentry, key, NULL, 0);
+ if (buflen <= 0)
+ return buflen;
+
+ *buf = kmalloc(buflen, GFP_KERNEL);
+ if (!*buf)
+ return -ENOMEM;
+
+ error = vfs_getxattr(dentry, key, *buf, buflen);
+ if (error < 0)
+ return error;
+ return buflen;
+}
+#endif
+#if defined(CONFIG_NFSD_V4)
static int
set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
{
@@ -374,7 +396,6 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
size_t buflen;
char *buf = NULL;
int error = 0;
- struct inode *inode = dentry->d_inode;
buflen = posix_acl_xattr_size(pacl->a_count);
buf = kmalloc(buflen, GFP_KERNEL);
@@ -388,15 +409,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
goto out;
}
- error = -EOPNOTSUPP;
- if (inode->i_op && inode->i_op->setxattr) {
- down(&inode->i_sem);
- security_inode_setxattr(dentry, key, buf, len, 0);
- error = inode->i_op->setxattr(dentry, key, buf, len, 0);
- if (!error)
- security_inode_post_setxattr(dentry, key, buf, len, 0);
- up(&inode->i_sem);
- }
+ error = vfs_setxattr(dentry, key, buf, len, 0);
out:
kfree(buf);
return error;
@@ -455,44 +468,19 @@ out_nfserr:
static struct posix_acl *
_get_posix_acl(struct dentry *dentry, char *key)
{
- struct inode *inode = dentry->d_inode;
- char *buf = NULL;
- int buflen, error = 0;
+ void *buf = NULL;
struct posix_acl *pacl = NULL;
+ int buflen;
- error = -EOPNOTSUPP;
- if (inode->i_op == NULL)
- goto out_err;
- if (inode->i_op->getxattr == NULL)
- goto out_err;
-
- error = security_inode_getxattr(dentry, key);
- if (error)
- goto out_err;
-
- buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
- if (buflen <= 0) {
- error = buflen < 0 ? buflen : -ENODATA;
- goto out_err;
- }
-
- buf = kmalloc(buflen, GFP_KERNEL);
- if (buf == NULL) {
- error = -ENOMEM;
- goto out_err;
- }
-
- error = inode->i_op->getxattr(dentry, key, buf, buflen);
- if (error < 0)
- goto out_err;
+ buflen = nfsd_getxattr(dentry, key, &buf);
+ if (!buflen)
+ buflen = -ENODATA;
+ if (buflen <= 0)
+ return ERR_PTR(buflen);
pacl = posix_acl_from_xattr(buf, buflen);
- out:
kfree(buf);
return pacl;
- out_err:
- pacl = ERR_PTR(error);
- goto out;
}
int
@@ -717,33 +705,40 @@ nfsd_close(struct file *filp)
* As this calls fsync (not fdatasync) there is no need for a write_inode
* after it.
*/
-static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
- struct file_operations *fop)
+static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
+ struct file_operations *fop)
{
struct inode *inode = dp->d_inode;
int (*fsync) (struct file *, struct dentry *, int);
+ int err;
+
+ err = filemap_fdatawrite(inode->i_mapping);
+ if (err == 0 && fop && (fsync = fop->fsync))
+ err = fsync(filp, dp, 0);
+ if (err == 0)
+ err = filemap_fdatawait(inode->i_mapping);
- filemap_fdatawrite(inode->i_mapping);
- if (fop && (fsync = fop->fsync))
- fsync(filp, dp, 0);
- filemap_fdatawait(inode->i_mapping);
+ return err;
}
-static void
+static int
nfsd_sync(struct file *filp)
{
+ int err;
struct inode *inode = filp->f_dentry->d_inode;
dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
- down(&inode->i_sem);
- nfsd_dosync(filp, filp->f_dentry, filp->f_op);
- up(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
+ err=nfsd_dosync(filp, filp->f_dentry, filp->f_op);
+ mutex_unlock(&inode->i_mutex);
+
+ return err;
}
-void
+int
nfsd_sync_dir(struct dentry *dp)
{
- nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
+ return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
}
/*
@@ -820,7 +815,7 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
return size;
}
-static inline int
+static int
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
{
@@ -874,7 +869,17 @@ out:
return err;
}
-static inline int
+static void kill_suid(struct dentry *dentry)
+{
+ struct iattr ia;
+ ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
+
+ mutex_lock(&dentry->d_inode->i_mutex);
+ notify_change(dentry, &ia);
+ mutex_unlock(&dentry->d_inode->i_mutex);
+}
+
+static int
nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen,
unsigned long cnt, int *stablep)
@@ -886,9 +891,9 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
int err = 0;
int stable = *stablep;
+#ifdef MSNFS
err = nfserr_perm;
-#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
goto out;
@@ -927,14 +932,8 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
}
/* clear setuid/setgid flag after write */
- if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
- struct iattr ia;
- ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID;
-
- down(&inode->i_sem);
- notify_change(dentry, &ia);
- up(&inode->i_sem);
- }
+ if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
+ kill_suid(dentry);
if (err >= 0 && stable) {
static ino_t last_ino;
@@ -962,7 +961,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
if (inode->i_state & I_DIRTY) {
dprintk("nfsd: write sync %d\n", current->pid);
- nfsd_sync(file);
+ err=nfsd_sync(file);
}
#if 0
wake_up(&inode->i_wait);
@@ -1066,7 +1065,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
return err;
if (EX_ISSYNC(fhp->fh_export)) {
if (file->f_op && file->f_op->fsync) {
- nfsd_sync(file);
+ err = nfserrno(nfsd_sync(file));
} else {
err = nfserr_notsupp;
}
@@ -1134,7 +1133,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
"nfsd_create: parent %s/%s not locked!\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
- err = -EIO;
+ err = nfserr_io;
goto out;
}
}
@@ -1177,7 +1176,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export)) {
- nfsd_sync_dir(dentry);
+ err = nfserrno(nfsd_sync_dir(dentry));
write_inode_now(dchild->d_inode, 1);
}
@@ -1187,9 +1186,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
* send along the gid when it tries to implement setgid
* directories via NFS.
*/
- err = 0;
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
- err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0) {
+ int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if (err2)
+ err = err2;
+ }
/*
* Update the file handle to get the new inode info.
*/
@@ -1308,17 +1309,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
if (EX_ISSYNC(fhp->fh_export)) {
- nfsd_sync_dir(dentry);
+ err = nfserrno(nfsd_sync_dir(dentry));
/* setattr will sync the child (or not) */
}
- /*
- * Update the filehandle to get the new inode info.
- */
- err = fh_update(resfhp);
- if (err)
- goto out;
-
if (createmode == NFS3_CREATE_EXCLUSIVE) {
/* Cram the verifier into atime/mtime/mode */
iap->ia_valid = ATTR_MTIME|ATTR_ATIME
@@ -1339,8 +1333,17 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
* implement setgid directories via NFS. Clear out all that cruft.
*/
set_attr:
- if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
- err = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0) {
+ int err2 = nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0);
+ if (err2)
+ err = err2;
+ }
+
+ /*
+ * Update the filehandle to get the new inode info.
+ */
+ if (!err)
+ err = fh_update(resfhp);
out:
fh_unlock(fhp);
@@ -1449,10 +1452,10 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
} else
err = vfs_symlink(dentry->d_inode, dnew, path, mode);
- if (!err) {
+ if (!err)
if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
- } else
+ err = nfsd_sync_dir(dentry);
+ if (err)
err = nfserrno(err);
fh_unlock(fhp);
@@ -1508,7 +1511,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = vfs_link(dold, dirp, dnew);
if (!err) {
if (EX_ISSYNC(ffhp->fh_export)) {
- nfsd_sync_dir(ddir);
+ err = nfserrno(nfsd_sync_dir(ddir));
write_inode_now(dest, 1);
}
} else {
@@ -1592,13 +1595,14 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
((atomic_read(&odentry->d_count) > 1)
|| (atomic_read(&ndentry->d_count) > 1))) {
- err = nfserr_perm;
+ err = -EPERM;
} else
#endif
err = vfs_rename(fdir, odentry, tdir, ndentry);
if (!err && EX_ISSYNC(tfhp->fh_export)) {
- nfsd_sync_dir(tdentry);
- nfsd_sync_dir(fdentry);
+ err = nfsd_sync_dir(tdentry);
+ if (!err)
+ err = nfsd_sync_dir(fdentry);
}
out_dput_new:
@@ -1663,7 +1667,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(atomic_read(&rdentry->d_count) > 1)) {
- err = nfserr_perm;
+ err = -EPERM;
} else
#endif
err = vfs_unlink(dirp, rdentry);
@@ -1673,17 +1677,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dput(rdentry);
- if (err)
- goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
-
-out:
- return err;
+ if (err == 0 &&
+ EX_ISSYNC(fhp->fh_export))
+ err = nfsd_sync_dir(dentry);
out_nfserr:
err = nfserrno(err);
- goto out;
+out:
+ return err;
}
/*
@@ -1874,39 +1875,25 @@ nfsd_get_posix_acl(struct svc_fh *fhp, int type)
ssize_t size;
struct posix_acl *acl;
- if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
+ if (!IS_POSIXACL(inode))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ switch (type) {
+ case ACL_TYPE_ACCESS:
+ name = POSIX_ACL_XATTR_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = POSIX_ACL_XATTR_DEFAULT;
+ break;
+ default:
return ERR_PTR(-EOPNOTSUPP);
- switch(type) {
- case ACL_TYPE_ACCESS:
- name = POSIX_ACL_XATTR_ACCESS;
- break;
- case ACL_TYPE_DEFAULT:
- name = POSIX_ACL_XATTR_DEFAULT;
- break;
- default:
- return ERR_PTR(-EOPNOTSUPP);
}
- size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
+ size = nfsd_getxattr(fhp->fh_dentry, name, &value);
+ if (size < 0)
+ return ERR_PTR(size);
- if (size < 0) {
- acl = ERR_PTR(size);
- goto getout;
- } else if (size > 0) {
- value = kmalloc(size, GFP_KERNEL);
- if (!value) {
- acl = ERR_PTR(-ENOMEM);
- goto getout;
- }
- size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
- if (size < 0) {
- acl = ERR_PTR(size);
- goto getout;
- }
- }
acl = posix_acl_from_xattr(value, size);
-
-getout:
kfree(value);
return acl;
}
@@ -1947,16 +1934,13 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
} else
size = 0;
- if (!fhp->fh_locked)
- fh_lock(fhp); /* unlocking is done automatically */
if (size)
- error = inode->i_op->setxattr(fhp->fh_dentry, name,
- value, size, 0);
+ error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
else {
if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
error = 0;
else {
- error = inode->i_op->removexattr(fhp->fh_dentry, name);
+ error = vfs_removexattr(fhp->fh_dentry, name);
if (error == -ENODATA)
error = 0;
}
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index 50a7749cfca1..02f44094bda9 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -884,7 +884,7 @@ ToDo/Notes:
- Add handling for initialized_size != data_size in compressed files.
- Reduce function local stack usage from 0x3d4 bytes to just noise in
- fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>)
+ fs/ntfs/upcase.c. (Randy Dunlap <rdunlap@xenotime.net>)
- Remove compiler warnings for newer gcc.
- Pages are no longer kmapped by mm/filemap.c::generic_file_write()
around calls to ->{prepare,commit}_write. Adapt NTFS appropriately
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index eda056bac256..9480a0526cd3 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1532,7 +1532,7 @@ int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
* NOTE to self: No changes in the attribute list are required to move from
* a resident to a non-resident attribute.
*
- * Locking: - The caller must hold i_sem on the inode.
+ * Locking: - The caller must hold i_mutex on the inode.
*/
int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
{
@@ -1728,7 +1728,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
/*
* This needs to be last since the address space operations ->readpage
* and ->writepage can run concurrently with us as they are not
- * serialized on i_sem. Note, we are not allowed to fail once we flip
+ * serialized on i_mutex. Note, we are not allowed to fail once we flip
* this switch, which is another reason to do this last.
*/
NInoSetNonResident(ni);
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 795c3d1930f5..b0690d4c8906 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -69,7 +69,7 @@ ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
* work but we don't care for how quickly one can access them. This also fixes
* the dcache aliasing issues.
*
- * Locking: - Caller must hold i_sem on the directory.
+ * Locking: - Caller must hold i_mutex on the directory.
* - Each page cache page in the index allocation mapping must be
* locked whilst being accessed otherwise we may find a corrupt
* page due to it being under ->writepage at the moment which
@@ -1085,11 +1085,11 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
* While this will return the names in random order this doesn't matter for
* ->readdir but OTOH results in a faster ->readdir.
*
- * VFS calls ->readdir without BKL but with i_sem held. This protects the VFS
+ * VFS calls ->readdir without BKL but with i_mutex held. This protects the VFS
* parts (e.g. ->f_pos and ->i_size, and it also protects against directory
* modifications).
*
- * Locking: - Caller must hold i_sem on the directory.
+ * Locking: - Caller must hold i_mutex on the directory.
* - Each page cache page in the index allocation mapping must be
* locked whilst being accessed otherwise we may find a corrupt
* page due to it being under ->writepage at the moment which
@@ -1520,7 +1520,7 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
* Note: In the past @filp could be NULL so we ignore it as we don't need it
* anyway.
*
- * Locking: Caller must hold i_sem on the inode.
+ * Locking: Caller must hold i_mutex on the inode.
*
* TODO: We should probably also write all attribute/index inodes associated
* with this inode but since we have no simple way of getting to them we ignore
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c73c8864cbad..3a119a87686a 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -106,7 +106,7 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
* this is the case, the necessary zeroing will also have happened and that all
* metadata is self-consistent.
*
- * Locking: i_sem on the vfs inode corrseponsind to the ntfs inode @ni must be
+ * Locking: i_mutex on the vfs inode corrseponsind to the ntfs inode @ni must be
* held by the caller.
*/
static int ntfs_attr_extend_initialized(ntfs_inode *ni, const s64 new_init_size,
@@ -473,7 +473,7 @@ static inline int ntfs_submit_bh_for_read(struct buffer_head *bh)
* @bytes: number of bytes to be written
*
* This is called for non-resident attributes from ntfs_file_buffered_write()
- * with i_sem held on the inode (@pages[0]->mapping->host). There are
+ * with i_mutex held on the inode (@pages[0]->mapping->host). There are
* @nr_pages pages in @pages which are locked but not kmap()ped. The source
* data has not yet been copied into the @pages.
*
@@ -1637,7 +1637,7 @@ err_out:
* @pos: byte position in file at which the write begins
* @bytes: number of bytes to be written
*
- * This is called from ntfs_file_buffered_write() with i_sem held on the inode
+ * This is called from ntfs_file_buffered_write() with i_mutex held on the inode
* (@pages[0]->mapping->host). There are @nr_pages pages in @pages which are
* locked but not kmap()ped. The source data has already been copied into the
* @page. ntfs_prepare_pages_for_non_resident_write() has been called before
@@ -1814,7 +1814,7 @@ err_out:
/**
* ntfs_file_buffered_write -
*
- * Locking: The vfs is holding ->i_sem on the inode.
+ * Locking: The vfs is holding ->i_mutex on the inode.
*/
static ssize_t ntfs_file_buffered_write(struct kiocb *iocb,
const struct iovec *iov, unsigned long nr_segs,
@@ -2173,7 +2173,7 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
err = remove_suid(file->f_dentry);
if (err)
goto out;
- inode_update_time(inode, 1);
+ file_update_time(file);
written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
count);
out:
@@ -2196,9 +2196,9 @@ static ssize_t ntfs_file_aio_write(struct kiocb *iocb, const char __user *buf,
BUG_ON(iocb->ki_pos != pos);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = ntfs_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = sync_page_range(inode, mapping, pos, ret);
if (err < 0)
@@ -2221,12 +2221,12 @@ static ssize_t ntfs_file_writev(struct file *file, const struct iovec *iov,
struct kiocb kiocb;
ssize_t ret;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
init_sync_kiocb(&kiocb, file);
ret = ntfs_file_aio_write_nolock(&kiocb, iov, nr_segs, ppos);
if (ret == -EIOCBQUEUED)
ret = wait_on_sync_kiocb(&kiocb);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err = sync_page_range(inode, mapping, *ppos - ret, ret);
if (err < 0)
@@ -2269,7 +2269,7 @@ static ssize_t ntfs_file_write(struct file *file, const char __user *buf,
* Note: In the past @filp could be NULL so we ignore it as we don't need it
* anyway.
*
- * Locking: Caller must hold i_sem on the inode.
+ * Locking: Caller must hold i_mutex on the inode.
*
* TODO: We should probably also write all attribute/index inodes associated
* with this inode but since we have no simple way of getting to them we ignore
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index 8f2d5727546f..9f5427c2d105 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -32,7 +32,7 @@
* Allocate a new index context, initialize it with @idx_ni and return it.
* Return NULL if allocation failed.
*
- * Locking: Caller must hold i_sem on the index inode.
+ * Locking: Caller must hold i_mutex on the index inode.
*/
ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni)
{
@@ -50,7 +50,7 @@ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni)
*
* Release the index context @ictx, releasing all associated resources.
*
- * Locking: Caller must hold i_sem on the index inode.
+ * Locking: Caller must hold i_mutex on the index inode.
*/
void ntfs_index_ctx_put(ntfs_index_context *ictx)
{
@@ -106,7 +106,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx)
* or ntfs_index_entry_write() before the call to ntfs_index_ctx_put() to
* ensure that the changes are written to disk.
*
- * Locking: - Caller must hold i_sem on the index inode.
+ * Locking: - Caller must hold i_mutex on the index inode.
* - Each page cache page in the index allocation mapping must be
* locked whilst being accessed otherwise we may find a corrupt
* page due to it being under ->writepage at the moment which
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index b24f4c4b2c5c..ea1bd3feea1b 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -2125,13 +2125,13 @@ void ntfs_put_inode(struct inode *vi)
ntfs_inode *ni = NTFS_I(vi);
if (NInoIndexAllocPresent(ni)) {
struct inode *bvi = NULL;
- down(&vi->i_sem);
+ mutex_lock(&vi->i_mutex);
if (atomic_read(&vi->i_count) == 2) {
bvi = ni->itype.index.bmp_ino;
if (bvi)
ni->itype.index.bmp_ino = NULL;
}
- up(&vi->i_sem);
+ mutex_unlock(&vi->i_mutex);
if (bvi)
iput(bvi);
}
@@ -2311,7 +2311,7 @@ static const char *es = " Leaving inconsistent metadata. Unmount and run "
*
* Returns 0 on success or -errno on error.
*
- * Called with ->i_sem held. In all but one case ->i_alloc_sem is held for
+ * Called with ->i_mutex held. In all but one case ->i_alloc_sem is held for
* writing. The only case in the kernel where ->i_alloc_sem is not held is
* mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
* with the current i_size as the offset. The analogous place in NTFS is in
@@ -2767,7 +2767,25 @@ unm_done:
up_write(&ni->runlist.lock);
done:
/* Update the mtime and ctime on the base inode. */
- inode_update_time(VFS_I(base_ni), 1);
+ /* normally ->truncate shouldn't update ctime or mtime,
+ * but ntfs did before so it got a copy & paste version
+ * of file_update_time. one day someone should fix this
+ * for real.
+ */
+ if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
+ struct timespec now = current_fs_time(VFS_I(base_ni)->i_sb);
+ int sync_it = 0;
+
+ if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
+ !timespec_equal(&VFS_I(base_ni)->i_ctime, &now))
+ sync_it = 1;
+ VFS_I(base_ni)->i_mtime = now;
+ VFS_I(base_ni)->i_ctime = now;
+
+ if (sync_it)
+ mark_inode_dirty_sync(VFS_I(base_ni));
+ }
+
if (likely(!err)) {
NInoClearTruncateFailed(ni);
ntfs_debug("Done.");
@@ -2831,7 +2849,7 @@ void ntfs_truncate_vfs(struct inode *vi) {
* We also abort all changes of user, group, and mode as we do not implement
* the NTFS ACLs yet.
*
- * Called with ->i_sem held. For the ATTR_SIZE (i.e. ->truncate) case, also
+ * Called with ->i_mutex held. For the ATTR_SIZE (i.e. ->truncate) case, also
* called with ->i_alloc_sem held for writing.
*
* Basically this is a copy of generic notify_change() and inode_setattr()
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 351dbc3b6e40..5ea9eb93af62 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -96,7 +96,7 @@
* name. We then convert the name to the current NLS code page, and proceed
* searching for a dentry with this name, etc, as in case 2), above.
*
- * Locking: Caller must hold i_sem on the directory.
+ * Locking: Caller must hold i_mutex on the directory.
*/
static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
struct nameidata *nd)
@@ -254,7 +254,7 @@ handle_name:
nls_name.hash = full_name_hash(nls_name.name, nls_name.len);
/*
- * Note: No need for dent->d_lock lock as i_sem is held on the
+ * Note: No need for dent->d_lock lock as i_mutex is held on the
* parent inode.
*/
@@ -374,7 +374,7 @@ struct inode_operations ntfs_dir_inode_ops = {
* The code is based on the ext3 ->get_parent() implementation found in
* fs/ext3/namei.c::ext3_get_parent().
*
- * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_sem down.
+ * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down.
*
* Return the dentry of the parent directory on success or the error code on
* error (IS_ERR() is true).
diff --git a/fs/ntfs/quota.c b/fs/ntfs/quota.c
index 833df2a4e9fb..d0ef4182147b 100644
--- a/fs/ntfs/quota.c
+++ b/fs/ntfs/quota.c
@@ -48,7 +48,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
ntfs_error(vol->sb, "Quota inodes are not open.");
return FALSE;
}
- down(&vol->quota_q_ino->i_sem);
+ mutex_lock(&vol->quota_q_ino->i_mutex);
ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino));
if (!ictx) {
ntfs_error(vol->sb, "Failed to get index context.");
@@ -98,7 +98,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
ntfs_index_entry_mark_dirty(ictx);
set_done:
ntfs_index_ctx_put(ictx);
- up(&vol->quota_q_ino->i_sem);
+ mutex_unlock(&vol->quota_q_ino->i_mutex);
/*
* We set the flag so we do not try to mark the quotas out of date
* again on remount.
@@ -110,7 +110,7 @@ done:
err_out:
if (ictx)
ntfs_index_ctx_put(ictx);
- up(&vol->quota_q_ino->i_sem);
+ mutex_unlock(&vol->quota_q_ino->i_mutex);
return FALSE;
}
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 6c16db9e1a8a..c3a3f1a8310b 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -443,8 +443,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_debug("Entering with remount options string: %s", opt);
#ifndef NTFS_RW
- /* For read-only compiled driver, enforce all read-only flags. */
- *flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ /* For read-only compiled driver, enforce read-only flag. */
+ *flags |= MS_RDONLY;
#else /* NTFS_RW */
/*
* For the read-write compiled driver, if we are remounting read-write,
@@ -1213,10 +1213,10 @@ static int check_windows_hibernation_status(ntfs_volume *vol)
* Find the inode number for the hibernation file by looking up the
* filename hiberfil.sys in the root directory.
*/
- down(&vol->root_ino->i_sem);
+ mutex_lock(&vol->root_ino->i_mutex);
mref = ntfs_lookup_inode_by_name(NTFS_I(vol->root_ino), hiberfil, 12,
&name);
- up(&vol->root_ino->i_sem);
+ mutex_unlock(&vol->root_ino->i_mutex);
if (IS_ERR_MREF(mref)) {
ret = MREF_ERR(mref);
/* If the file does not exist, Windows is not hibernated. */
@@ -1307,10 +1307,10 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
* Find the inode number for the quota file by looking up the filename
* $Quota in the extended system files directory $Extend.
*/
- down(&vol->extend_ino->i_sem);
+ mutex_lock(&vol->extend_ino->i_mutex);
mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), Quota, 6,
&name);
- up(&vol->extend_ino->i_sem);
+ mutex_unlock(&vol->extend_ino->i_mutex);
if (IS_ERR_MREF(mref)) {
/*
* If the file does not exist, quotas are disabled and have
@@ -1390,10 +1390,10 @@ static BOOL load_and_init_usnjrnl(ntfs_volume *vol)
* Find the inode number for the transaction log file by looking up the
* filename $UsnJrnl in the extended system files directory $Extend.
*/
- down(&vol->extend_ino->i_sem);
+ mutex_lock(&vol->extend_ino->i_mutex);
mref = ntfs_lookup_inode_by_name(NTFS_I(vol->extend_ino), UsnJrnl, 8,
&name);
- up(&vol->extend_ino->i_sem);
+ mutex_unlock(&vol->extend_ino->i_mutex);
if (IS_ERR_MREF(mref)) {
/*
* If the file does not exist, transaction logging is disabled,
@@ -1721,7 +1721,7 @@ static BOOL load_system_files(ntfs_volume *vol)
es3);
goto iput_mirr_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s",
!vol->mftmirr_ino ? es1 : es2, es3);
} else
@@ -1837,7 +1837,7 @@ get_ctx_vol_failed:
es1, es2);
goto iput_vol_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
@@ -1874,7 +1874,7 @@ get_ctx_vol_failed:
}
goto iput_logfile_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
@@ -1919,7 +1919,7 @@ get_ctx_vol_failed:
es1, es2);
goto iput_root_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
@@ -1943,7 +1943,7 @@ get_ctx_vol_failed:
goto iput_root_err_out;
}
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
/*
* Do not set NVolErrors() because ntfs_remount() might manage
* to set the dirty flag in which case all would be well.
@@ -1970,7 +1970,7 @@ get_ctx_vol_failed:
goto iput_root_err_out;
}
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
NVolSetErrors(vol);
}
#endif
@@ -1989,7 +1989,7 @@ get_ctx_vol_failed:
goto iput_root_err_out;
}
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
NVolSetErrors(vol);
}
#endif /* NTFS_RW */
@@ -2030,7 +2030,7 @@ get_ctx_vol_failed:
es1, es2);
goto iput_quota_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
@@ -2053,7 +2053,7 @@ get_ctx_vol_failed:
goto iput_quota_err_out;
}
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
NVolSetErrors(vol);
}
/*
@@ -2074,7 +2074,7 @@ get_ctx_vol_failed:
es1, es2);
goto iput_usnjrnl_err_out;
}
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
} else
ntfs_warning(sb, "%s. Will not be able to remount "
@@ -2097,7 +2097,7 @@ get_ctx_vol_failed:
goto iput_usnjrnl_err_out;
}
ntfs_error(sb, "%s. Mounting read-only%s", es1, es2);
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
NVolSetErrors(vol);
}
#endif /* NTFS_RW */
@@ -2312,9 +2312,9 @@ static void ntfs_put_super(struct super_block *sb)
if (!list_empty(&sb->s_dirty)) {
const char *s1, *s2;
- down(&vol->mft_ino->i_sem);
+ mutex_lock(&vol->mft_ino->i_mutex);
truncate_inode_pages(vol->mft_ino->i_mapping, 0);
- up(&vol->mft_ino->i_sem);
+ mutex_unlock(&vol->mft_ino->i_mutex);
write_inode_now(vol->mft_ino, 1);
if (!list_empty(&sb->s_dirty)) {
static const char *_s1 = "inodes";
@@ -2689,7 +2689,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_debug("Entering.");
#ifndef NTFS_RW
- sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
+ sb->s_flags |= MS_RDONLY;
#endif /* ! NTFS_RW */
/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS);
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
new file mode 100644
index 000000000000..7d3be845a614
--- /dev/null
+++ b/fs/ocfs2/Makefile
@@ -0,0 +1,33 @@
+EXTRA_CFLAGS += -Ifs/ocfs2
+
+EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
+
+obj-$(CONFIG_OCFS2_FS) += ocfs2.o
+
+ocfs2-objs := \
+ alloc.o \
+ aops.o \
+ buffer_head_io.o \
+ dcache.o \
+ dir.o \
+ dlmglue.o \
+ export.o \
+ extent_map.o \
+ file.o \
+ heartbeat.o \
+ inode.o \
+ journal.o \
+ localalloc.o \
+ mmap.o \
+ namei.o \
+ slot_map.o \
+ suballoc.o \
+ super.o \
+ symlink.o \
+ sysfile.o \
+ uptodate.o \
+ ver.o \
+ vote.o
+
+obj-$(CONFIG_OCFS2_FS) += cluster/
+obj-$(CONFIG_OCFS2_FS) += dlm/
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
new file mode 100644
index 000000000000..6b9812db3779
--- /dev/null
+++ b/fs/ocfs2/alloc.c
@@ -0,0 +1,2040 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * alloc.c
+ *
+ * Extent allocs and frees
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#define MLOG_MASK_PREFIX ML_DISK_ALLOC
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "inode.h"
+#include "journal.h"
+#include "localalloc.h"
+#include "suballoc.h"
+#include "sysfile.h"
+#include "file.h"
+#include "super.h"
+#include "uptodate.h"
+
+#include "buffer_head_io.h"
+
+static int ocfs2_extent_contig(struct inode *inode,
+ struct ocfs2_extent_rec *ext,
+ u64 blkno);
+
+static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ int wanted,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head *bhs[]);
+
+static int ocfs2_add_branch(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head *eb_bh,
+ struct buffer_head *last_eb_bh,
+ struct ocfs2_alloc_context *meta_ac);
+
+static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head **ret_new_eb_bh);
+
+static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 blkno,
+ u32 new_clusters);
+
+static int ocfs2_find_branch_target(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head **target_bh);
+
+static int ocfs2_find_new_last_ext_blk(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct ocfs2_dinode *fe,
+ unsigned int new_i_clusters,
+ struct buffer_head *old_last_eb,
+ struct buffer_head **new_last_eb);
+
+static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc);
+
+static int ocfs2_extent_contig(struct inode *inode,
+ struct ocfs2_extent_rec *ext,
+ u64 blkno)
+{
+ return blkno == (le64_to_cpu(ext->e_blkno) +
+ ocfs2_clusters_to_blocks(inode->i_sb,
+ le32_to_cpu(ext->e_clusters)));
+}
+
+/*
+ * How many free extents have we got before we need more meta data?
+ */
+int ocfs2_num_free_extents(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct ocfs2_dinode *fe)
+{
+ int retval;
+ struct ocfs2_extent_list *el;
+ struct ocfs2_extent_block *eb;
+ struct buffer_head *eb_bh = NULL;
+
+ mlog_entry_void();
+
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+ retval = -EIO;
+ goto bail;
+ }
+
+ if (fe->i_last_eb_blk) {
+ retval = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
+ &eb_bh, OCFS2_BH_CACHED, inode);
+ if (retval < 0) {
+ mlog_errno(retval);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) eb_bh->b_data;
+ el = &eb->h_list;
+ } else
+ el = &fe->id2.i_list;
+
+ BUG_ON(el->l_tree_depth != 0);
+
+ retval = le16_to_cpu(el->l_count) - le16_to_cpu(el->l_next_free_rec);
+bail:
+ if (eb_bh)
+ brelse(eb_bh);
+
+ mlog_exit(retval);
+ return retval;
+}
+
+/* expects array to already be allocated
+ *
+ * sets h_signature, h_blkno, h_suballoc_bit, h_suballoc_slot, and
+ * l_count for you
+ */
+static int ocfs2_create_new_meta_bhs(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ int wanted,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head *bhs[])
+{
+ int count, status, i;
+ u16 suballoc_bit_start;
+ u32 num_got;
+ u64 first_blkno;
+ struct ocfs2_extent_block *eb;
+
+ mlog_entry_void();
+
+ count = 0;
+ while (count < wanted) {
+ status = ocfs2_claim_metadata(osb,
+ handle,
+ meta_ac,
+ wanted - count,
+ &suballoc_bit_start,
+ &num_got,
+ &first_blkno);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ for(i = count; i < (num_got + count); i++) {
+ bhs[i] = sb_getblk(osb->sb, first_blkno);
+ if (bhs[i] == NULL) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_set_new_buffer_uptodate(inode, bhs[i]);
+
+ status = ocfs2_journal_access(handle, inode, bhs[i],
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ memset(bhs[i]->b_data, 0, osb->sb->s_blocksize);
+ eb = (struct ocfs2_extent_block *) bhs[i]->b_data;
+ /* Ok, setup the minimal stuff here. */
+ strcpy(eb->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE);
+ eb->h_blkno = cpu_to_le64(first_blkno);
+ eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
+
+#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
+ /* we always use slot zero's suballocator */
+ eb->h_suballoc_slot = 0;
+#else
+ eb->h_suballoc_slot = cpu_to_le16(osb->slot_num);
+#endif
+ eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
+ eb->h_list.l_count =
+ cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
+
+ suballoc_bit_start++;
+ first_blkno++;
+
+ /* We'll also be dirtied by the caller, so
+ * this isn't absolutely necessary. */
+ status = ocfs2_journal_dirty(handle, bhs[i]);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ count += num_got;
+ }
+
+ status = 0;
+bail:
+ if (status < 0) {
+ for(i = 0; i < wanted; i++) {
+ if (bhs[i])
+ brelse(bhs[i]);
+ bhs[i] = NULL;
+ }
+ }
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Add an entire tree branch to our inode. eb_bh is the extent block
+ * to start at, if we don't want to start the branch at the dinode
+ * structure.
+ *
+ * last_eb_bh is required as we have to update it's next_leaf pointer
+ * for the new last extent block.
+ *
+ * the new branch will be 'empty' in the sense that every block will
+ * contain a single record with e_clusters == 0.
+ */
+static int ocfs2_add_branch(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head *eb_bh,
+ struct buffer_head *last_eb_bh,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int status, new_blocks, i;
+ u64 next_blkno, new_last_eb_blk;
+ struct buffer_head *bh;
+ struct buffer_head **new_eb_bhs = NULL;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *eb_el;
+ struct ocfs2_extent_list *el;
+
+ mlog_entry_void();
+
+ BUG_ON(!last_eb_bh);
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ if (eb_bh) {
+ eb = (struct ocfs2_extent_block *) eb_bh->b_data;
+ el = &eb->h_list;
+ } else
+ el = &fe->id2.i_list;
+
+ /* we never add a branch to a leaf. */
+ BUG_ON(!el->l_tree_depth);
+
+ new_blocks = le16_to_cpu(el->l_tree_depth);
+
+ /* allocate the number of new eb blocks we need */
+ new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *),
+ GFP_KERNEL);
+ if (!new_eb_bhs) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_create_new_meta_bhs(osb, handle, inode, new_blocks,
+ meta_ac, new_eb_bhs);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
+ * linked with the rest of the tree.
+ * conversly, new_eb_bhs[0] is the new bottommost leaf.
+ *
+ * when we leave the loop, new_last_eb_blk will point to the
+ * newest leaf, and next_blkno will point to the topmost extent
+ * block. */
+ next_blkno = new_last_eb_blk = 0;
+ for(i = 0; i < new_blocks; i++) {
+ bh = new_eb_bhs[i];
+ eb = (struct ocfs2_extent_block *) bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+ eb_el = &eb->h_list;
+
+ status = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ eb->h_next_leaf_blk = 0;
+ eb_el->l_tree_depth = cpu_to_le16(i);
+ eb_el->l_next_free_rec = cpu_to_le16(1);
+ eb_el->l_recs[0].e_cpos = fe->i_clusters;
+ eb_el->l_recs[0].e_blkno = cpu_to_le64(next_blkno);
+ eb_el->l_recs[0].e_clusters = cpu_to_le32(0);
+ if (!eb_el->l_tree_depth)
+ new_last_eb_blk = le64_to_cpu(eb->h_blkno);
+
+ status = ocfs2_journal_dirty(handle, bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ next_blkno = le64_to_cpu(eb->h_blkno);
+ }
+
+ /* This is a bit hairy. We want to update up to three blocks
+ * here without leaving any of them in an inconsistent state
+ * in case of error. We don't have to worry about
+ * journal_dirty erroring as it won't unless we've aborted the
+ * handle (in which case we would never be here) so reserving
+ * the write with journal_access is all we need to do. */
+ status = ocfs2_journal_access(handle, inode, last_eb_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ if (eb_bh) {
+ status = ocfs2_journal_access(handle, inode, eb_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ /* Link the new branch into the rest of the tree (el will
+ * either be on the fe, or the extent block passed in. */
+ i = le16_to_cpu(el->l_next_free_rec);
+ el->l_recs[i].e_blkno = cpu_to_le64(next_blkno);
+ el->l_recs[i].e_cpos = fe->i_clusters;
+ el->l_recs[i].e_clusters = 0;
+ le16_add_cpu(&el->l_next_free_rec, 1);
+
+ /* fe needs a new last extent block pointer, as does the
+ * next_leaf on the previously last-extent-block. */
+ fe->i_last_eb_blk = cpu_to_le64(new_last_eb_blk);
+
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ eb->h_next_leaf_blk = cpu_to_le64(new_last_eb_blk);
+
+ status = ocfs2_journal_dirty(handle, last_eb_bh);
+ if (status < 0)
+ mlog_errno(status);
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0)
+ mlog_errno(status);
+ if (eb_bh) {
+ status = ocfs2_journal_dirty(handle, eb_bh);
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+ status = 0;
+bail:
+ if (new_eb_bhs) {
+ for (i = 0; i < new_blocks; i++)
+ if (new_eb_bhs[i])
+ brelse(new_eb_bhs[i]);
+ kfree(new_eb_bhs);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * adds another level to the allocation tree.
+ * returns back the new extent block so you can add a branch to it
+ * after this call.
+ */
+static int ocfs2_shift_tree_depth(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head **ret_new_eb_bh)
+{
+ int status, i;
+ struct buffer_head *new_eb_bh = NULL;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *fe_el;
+ struct ocfs2_extent_list *eb_el;
+
+ mlog_entry_void();
+
+ status = ocfs2_create_new_meta_bhs(osb, handle, inode, 1, meta_ac,
+ &new_eb_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ eb = (struct ocfs2_extent_block *) new_eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+
+ eb_el = &eb->h_list;
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ fe_el = &fe->id2.i_list;
+
+ status = ocfs2_journal_access(handle, inode, new_eb_bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* copy the fe data into the new extent block */
+ eb_el->l_tree_depth = fe_el->l_tree_depth;
+ eb_el->l_next_free_rec = fe_el->l_next_free_rec;
+ for(i = 0; i < le16_to_cpu(fe_el->l_next_free_rec); i++) {
+ eb_el->l_recs[i].e_cpos = fe_el->l_recs[i].e_cpos;
+ eb_el->l_recs[i].e_clusters = fe_el->l_recs[i].e_clusters;
+ eb_el->l_recs[i].e_blkno = fe_el->l_recs[i].e_blkno;
+ }
+
+ status = ocfs2_journal_dirty(handle, new_eb_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* update fe now */
+ le16_add_cpu(&fe_el->l_tree_depth, 1);
+ fe_el->l_recs[0].e_cpos = 0;
+ fe_el->l_recs[0].e_blkno = eb->h_blkno;
+ fe_el->l_recs[0].e_clusters = fe->i_clusters;
+ for(i = 1; i < le16_to_cpu(fe_el->l_next_free_rec); i++) {
+ fe_el->l_recs[i].e_cpos = 0;
+ fe_el->l_recs[i].e_clusters = 0;
+ fe_el->l_recs[i].e_blkno = 0;
+ }
+ fe_el->l_next_free_rec = cpu_to_le16(1);
+
+ /* If this is our 1st tree depth shift, then last_eb_blk
+ * becomes the allocated extent block */
+ if (fe_el->l_tree_depth == cpu_to_le16(1))
+ fe->i_last_eb_blk = eb->h_blkno;
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *ret_new_eb_bh = new_eb_bh;
+ new_eb_bh = NULL;
+ status = 0;
+bail:
+ if (new_eb_bh)
+ brelse(new_eb_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Expects the tree to already have room in the rightmost leaf for the
+ * extent. Updates all the extent blocks (and the dinode) on the way
+ * down.
+ */
+static int ocfs2_do_insert_extent(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 start_blk,
+ u32 new_clusters)
+{
+ int status, i, num_bhs = 0;
+ u64 next_blkno;
+ u16 next_free;
+ struct buffer_head **eb_bhs = NULL;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+
+ mlog_entry_void();
+
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ el = &fe->id2.i_list;
+ if (el->l_tree_depth) {
+ /* This is another operation where we want to be
+ * careful about our tree updates. An error here means
+ * none of the previous changes we made should roll
+ * forward. As a result, we have to record the buffers
+ * for this part of the tree in an array and reserve a
+ * journal write to them before making any changes. */
+ num_bhs = le16_to_cpu(fe->id2.i_list.l_tree_depth);
+ eb_bhs = kcalloc(num_bhs, sizeof(struct buffer_head *),
+ GFP_KERNEL);
+ if (!eb_bhs) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ i = 0;
+ while(el->l_tree_depth) {
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ if (next_free == 0) {
+ ocfs2_error(inode->i_sb,
+ "Dinode %"MLFu64" has a bad "
+ "extent list",
+ OCFS2_I(inode)->ip_blkno);
+ status = -EIO;
+ goto bail;
+ }
+ next_blkno = le64_to_cpu(el->l_recs[next_free - 1].e_blkno);
+
+ BUG_ON(i >= num_bhs);
+ status = ocfs2_read_block(osb, next_blkno, &eb_bhs[i],
+ OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) eb_bhs[i]->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
+ eb);
+ status = -EIO;
+ goto bail;
+ }
+
+ status = ocfs2_journal_access(handle, inode, eb_bhs[i],
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ el = &eb->h_list;
+ i++;
+ /* When we leave this loop, eb_bhs[num_bhs - 1] will
+ * hold the bottom-most leaf extent block. */
+ }
+ BUG_ON(el->l_tree_depth);
+
+ el = &fe->id2.i_list;
+ /* If we have tree depth, then the fe update is
+ * trivial, and we want to switch el out for the
+ * bottom-most leaf in order to update it with the
+ * actual extent data below. */
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ if (next_free == 0) {
+ ocfs2_error(inode->i_sb,
+ "Dinode %"MLFu64" has a bad "
+ "extent list",
+ OCFS2_I(inode)->ip_blkno);
+ status = -EIO;
+ goto bail;
+ }
+ le32_add_cpu(&el->l_recs[next_free - 1].e_clusters,
+ new_clusters);
+ /* (num_bhs - 1) to avoid the leaf */
+ for(i = 0; i < (num_bhs - 1); i++) {
+ eb = (struct ocfs2_extent_block *) eb_bhs[i]->b_data;
+ el = &eb->h_list;
+
+ /* finally, make our actual change to the
+ * intermediate extent blocks. */
+ next_free = le16_to_cpu(el->l_next_free_rec);
+ le32_add_cpu(&el->l_recs[next_free - 1].e_clusters,
+ new_clusters);
+
+ status = ocfs2_journal_dirty(handle, eb_bhs[i]);
+ if (status < 0)
+ mlog_errno(status);
+ }
+ BUG_ON(i != (num_bhs - 1));
+ /* note that the leaf block wasn't touched in
+ * the loop above */
+ eb = (struct ocfs2_extent_block *) eb_bhs[num_bhs - 1]->b_data;
+ el = &eb->h_list;
+ BUG_ON(el->l_tree_depth);
+ }
+
+ /* yay, we can finally add the actual extent now! */
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+ if (le16_to_cpu(el->l_next_free_rec) &&
+ ocfs2_extent_contig(inode, &el->l_recs[i], start_blk)) {
+ le32_add_cpu(&el->l_recs[i].e_clusters, new_clusters);
+ } else if (le16_to_cpu(el->l_next_free_rec) &&
+ (le32_to_cpu(el->l_recs[i].e_clusters) == 0)) {
+ /* having an empty extent at eof is legal. */
+ if (el->l_recs[i].e_cpos != fe->i_clusters) {
+ ocfs2_error(inode->i_sb,
+ "Dinode %"MLFu64" trailing extent is bad: "
+ "cpos (%u) != number of clusters (%u)",
+ le32_to_cpu(el->l_recs[i].e_cpos),
+ le32_to_cpu(fe->i_clusters));
+ status = -EIO;
+ goto bail;
+ }
+ el->l_recs[i].e_blkno = cpu_to_le64(start_blk);
+ el->l_recs[i].e_clusters = cpu_to_le32(new_clusters);
+ } else {
+ /* No contiguous record, or no empty record at eof, so
+ * we add a new one. */
+
+ BUG_ON(le16_to_cpu(el->l_next_free_rec) >=
+ le16_to_cpu(el->l_count));
+ i = le16_to_cpu(el->l_next_free_rec);
+
+ el->l_recs[i].e_blkno = cpu_to_le64(start_blk);
+ el->l_recs[i].e_clusters = cpu_to_le32(new_clusters);
+ el->l_recs[i].e_cpos = fe->i_clusters;
+ le16_add_cpu(&el->l_next_free_rec, 1);
+ }
+
+ /*
+ * extent_map errors are not fatal, so they are ignored outside
+ * of flushing the thing.
+ */
+ status = ocfs2_extent_map_append(inode, &el->l_recs[i],
+ new_clusters);
+ if (status) {
+ mlog_errno(status);
+ ocfs2_extent_map_drop(inode, le32_to_cpu(fe->i_clusters));
+ }
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0)
+ mlog_errno(status);
+ if (fe->id2.i_list.l_tree_depth) {
+ status = ocfs2_journal_dirty(handle, eb_bhs[num_bhs - 1]);
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+ status = 0;
+bail:
+ if (eb_bhs) {
+ for (i = 0; i < num_bhs; i++)
+ if (eb_bhs[i])
+ brelse(eb_bhs[i]);
+ kfree(eb_bhs);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Should only be called when there is no space left in any of the
+ * leaf nodes. What we want to do is find the lowest tree depth
+ * non-leaf extent block with room for new records. There are three
+ * valid results of this search:
+ *
+ * 1) a lowest extent block is found, then we pass it back in
+ * *lowest_eb_bh and return '0'
+ *
+ * 2) the search fails to find anything, but the dinode has room. We
+ * pass NULL back in *lowest_eb_bh, but still return '0'
+ *
+ * 3) the search fails to find anything AND the dinode is full, in
+ * which case we return > 0
+ *
+ * return status < 0 indicates an error.
+ */
+static int ocfs2_find_branch_target(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head **target_bh)
+{
+ int status = 0, i;
+ u64 blkno;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *bh = NULL;
+ struct buffer_head *lowest_bh = NULL;
+
+ mlog_entry_void();
+
+ *target_bh = NULL;
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ el = &fe->id2.i_list;
+
+ while(le16_to_cpu(el->l_tree_depth) > 1) {
+ if (le16_to_cpu(el->l_next_free_rec) == 0) {
+ ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has empty "
+ "extent list (next_free_rec == 0)",
+ OCFS2_I(inode)->ip_blkno);
+ status = -EIO;
+ goto bail;
+ }
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+ blkno = le64_to_cpu(el->l_recs[i].e_blkno);
+ if (!blkno) {
+ ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has extent "
+ "list where extent # %d has no physical "
+ "block start",
+ OCFS2_I(inode)->ip_blkno, i);
+ status = -EIO;
+ goto bail;
+ }
+
+ if (bh) {
+ brelse(bh);
+ bh = NULL;
+ }
+
+ status = ocfs2_read_block(osb, blkno, &bh, OCFS2_BH_CACHED,
+ inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ eb = (struct ocfs2_extent_block *) bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+ el = &eb->h_list;
+
+ if (le16_to_cpu(el->l_next_free_rec) <
+ le16_to_cpu(el->l_count)) {
+ if (lowest_bh)
+ brelse(lowest_bh);
+ lowest_bh = bh;
+ get_bh(lowest_bh);
+ }
+ }
+
+ /* If we didn't find one and the fe doesn't have any room,
+ * then return '1' */
+ if (!lowest_bh
+ && (fe->id2.i_list.l_next_free_rec == fe->id2.i_list.l_count))
+ status = 1;
+
+ *target_bh = lowest_bh;
+bail:
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* the caller needs to update fe->i_clusters */
+int ocfs2_insert_extent(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 start_blk,
+ u32 new_clusters,
+ struct ocfs2_alloc_context *meta_ac)
+{
+ int status, i, shift;
+ struct buffer_head *last_eb_bh = NULL;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+
+ mlog_entry_void();
+
+ mlog(0, "add %u clusters starting at block %"MLFu64" to "
+ "inode %"MLFu64"\n",
+ new_clusters, start_blk, OCFS2_I(inode)->ip_blkno);
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ el = &fe->id2.i_list;
+
+ if (el->l_tree_depth) {
+ /* jump to end of tree */
+ status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
+ &last_eb_bh, OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_exit(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ el = &eb->h_list;
+ }
+
+ /* Can we allocate without adding/shifting tree bits? */
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+ if (le16_to_cpu(el->l_next_free_rec) == 0
+ || (le16_to_cpu(el->l_next_free_rec) < le16_to_cpu(el->l_count))
+ || le32_to_cpu(el->l_recs[i].e_clusters) == 0
+ || ocfs2_extent_contig(inode, &el->l_recs[i], start_blk))
+ goto out_add;
+
+ mlog(0, "ocfs2_allocate_extent: couldn't do a simple add, traversing "
+ "tree now.\n");
+
+ shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
+ if (shift < 0) {
+ status = shift;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* We traveled all the way to the bottom of the allocation tree
+ * and didn't find room for any more extents - we need to add
+ * another tree level */
+ if (shift) {
+ /* if we hit a leaf, we'd better be empty :) */
+ BUG_ON(le16_to_cpu(el->l_next_free_rec) !=
+ le16_to_cpu(el->l_count));
+ BUG_ON(bh);
+ mlog(0, "ocfs2_allocate_extent: need to shift tree depth "
+ "(current = %u)\n",
+ le16_to_cpu(fe->id2.i_list.l_tree_depth));
+
+ /* ocfs2_shift_tree_depth will return us a buffer with
+ * the new extent block (so we can pass that to
+ * ocfs2_add_branch). */
+ status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
+ meta_ac, &bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ /* Special case: we have room now if we shifted from
+ * tree_depth 0 */
+ if (fe->id2.i_list.l_tree_depth == cpu_to_le16(1))
+ goto out_add;
+ }
+
+ /* call ocfs2_add_branch to add the final part of the tree with
+ * the new data. */
+ mlog(0, "ocfs2_allocate_extent: add branch. bh = %p\n", bh);
+ status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
+ meta_ac);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+out_add:
+ /* Finally, we can add clusters. */
+ status = ocfs2_do_insert_extent(osb, handle, inode, fe_bh,
+ start_blk, new_clusters);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ if (bh)
+ brelse(bh);
+
+ if (last_eb_bh)
+ brelse(last_eb_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+static inline int ocfs2_truncate_log_needs_flush(struct ocfs2_super *osb)
+{
+ struct buffer_head *tl_bh = osb->osb_tl_bh;
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+
+ di = (struct ocfs2_dinode *) tl_bh->b_data;
+ tl = &di->id2.i_dealloc;
+
+ mlog_bug_on_msg(le16_to_cpu(tl->tl_used) > le16_to_cpu(tl->tl_count),
+ "slot %d, invalid truncate log parameters: used = "
+ "%u, count = %u\n", osb->slot_num,
+ le16_to_cpu(tl->tl_used), le16_to_cpu(tl->tl_count));
+ return le16_to_cpu(tl->tl_used) == le16_to_cpu(tl->tl_count);
+}
+
+static int ocfs2_truncate_log_can_coalesce(struct ocfs2_truncate_log *tl,
+ unsigned int new_start)
+{
+ unsigned int tail_index;
+ unsigned int current_tail;
+
+ /* No records, nothing to coalesce */
+ if (!le16_to_cpu(tl->tl_used))
+ return 0;
+
+ tail_index = le16_to_cpu(tl->tl_used) - 1;
+ current_tail = le32_to_cpu(tl->tl_recs[tail_index].t_start);
+ current_tail += le32_to_cpu(tl->tl_recs[tail_index].t_clusters);
+
+ return current_tail == new_start;
+}
+
+static int ocfs2_truncate_log_append(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ u64 start_blk,
+ unsigned int num_clusters)
+{
+ int status, index;
+ unsigned int start_cluster, tl_count;
+ struct inode *tl_inode = osb->osb_tl_inode;
+ struct buffer_head *tl_bh = osb->osb_tl_bh;
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+
+ mlog_entry("start_blk = %"MLFu64", num_clusters = %u\n", start_blk,
+ num_clusters);
+
+ BUG_ON(mutex_trylock(&tl_inode->i_mutex));
+
+ start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk);
+
+ di = (struct ocfs2_dinode *) tl_bh->b_data;
+ tl = &di->id2.i_dealloc;
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
+ status = -EIO;
+ goto bail;
+ }
+
+ tl_count = le16_to_cpu(tl->tl_count);
+ mlog_bug_on_msg(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) ||
+ tl_count == 0,
+ "Truncate record count on #%"MLFu64" invalid ("
+ "wanted %u, actual %u\n", OCFS2_I(tl_inode)->ip_blkno,
+ ocfs2_truncate_recs_per_inode(osb->sb),
+ le16_to_cpu(tl->tl_count));
+
+ /* Caller should have known to flush before calling us. */
+ index = le16_to_cpu(tl->tl_used);
+ if (index >= tl_count) {
+ status = -ENOSPC;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_journal_access(handle, tl_inode, tl_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "Log truncate of %u clusters starting at cluster %u to "
+ "%"MLFu64" (index = %d)\n", num_clusters, start_cluster,
+ OCFS2_I(tl_inode)->ip_blkno, index);
+
+ if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) {
+ /*
+ * Move index back to the record we are coalescing with.
+ * ocfs2_truncate_log_can_coalesce() guarantees nonzero
+ */
+ index--;
+
+ num_clusters += le32_to_cpu(tl->tl_recs[index].t_clusters);
+ mlog(0, "Coalesce with index %u (start = %u, clusters = %u)\n",
+ index, le32_to_cpu(tl->tl_recs[index].t_start),
+ num_clusters);
+ } else {
+ tl->tl_recs[index].t_start = cpu_to_le32(start_cluster);
+ tl->tl_used = cpu_to_le16(index + 1);
+ }
+ tl->tl_recs[index].t_clusters = cpu_to_le32(num_clusters);
+
+ status = ocfs2_journal_dirty(handle, tl_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_replay_truncate_records(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *data_alloc_inode,
+ struct buffer_head *data_alloc_bh)
+{
+ int status = 0;
+ int i;
+ unsigned int num_clusters;
+ u64 start_blk;
+ struct ocfs2_truncate_rec rec;
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+ struct inode *tl_inode = osb->osb_tl_inode;
+ struct buffer_head *tl_bh = osb->osb_tl_bh;
+
+ mlog_entry_void();
+
+ di = (struct ocfs2_dinode *) tl_bh->b_data;
+ tl = &di->id2.i_dealloc;
+ i = le16_to_cpu(tl->tl_used) - 1;
+ while (i >= 0) {
+ /* Caller has given us at least enough credits to
+ * update the truncate log dinode */
+ status = ocfs2_journal_access(handle, tl_inode, tl_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ tl->tl_used = cpu_to_le16(i);
+
+ status = ocfs2_journal_dirty(handle, tl_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* TODO: Perhaps we can calculate the bulk of the
+ * credits up front rather than extending like
+ * this. */
+ status = ocfs2_extend_trans(handle,
+ OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ rec = tl->tl_recs[i];
+ start_blk = ocfs2_clusters_to_blocks(data_alloc_inode->i_sb,
+ le32_to_cpu(rec.t_start));
+ num_clusters = le32_to_cpu(rec.t_clusters);
+
+ /* if start_blk is not set, we ignore the record as
+ * invalid. */
+ if (start_blk) {
+ mlog(0, "free record %d, start = %u, clusters = %u\n",
+ i, le32_to_cpu(rec.t_start), num_clusters);
+
+ status = ocfs2_free_clusters(handle, data_alloc_inode,
+ data_alloc_bh, start_blk,
+ num_clusters);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ i--;
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* Expects you to already be holding tl_inode->i_mutex */
+static int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
+{
+ int status;
+ unsigned int num_to_flush;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct inode *tl_inode = osb->osb_tl_inode;
+ struct inode *data_alloc_inode = NULL;
+ struct buffer_head *tl_bh = osb->osb_tl_bh;
+ struct buffer_head *data_alloc_bh = NULL;
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+
+ mlog_entry_void();
+
+ BUG_ON(mutex_trylock(&tl_inode->i_mutex));
+
+ di = (struct ocfs2_dinode *) tl_bh->b_data;
+ tl = &di->id2.i_dealloc;
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ OCFS2_RO_ON_INVALID_DINODE(osb->sb, di);
+ status = -EIO;
+ goto bail;
+ }
+
+ num_to_flush = le16_to_cpu(tl->tl_used);
+ mlog(0, "Flush %u records from truncate log #%"MLFu64"\n",
+ num_to_flush, OCFS2_I(tl_inode)->ip_blkno);
+ if (!num_to_flush) {
+ status = 0;
+ goto bail;
+ }
+
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ data_alloc_inode = ocfs2_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!data_alloc_inode) {
+ status = -EINVAL;
+ mlog(ML_ERROR, "Could not get bitmap inode!\n");
+ goto bail;
+ }
+
+ ocfs2_handle_add_inode(handle, data_alloc_inode);
+ status = ocfs2_meta_lock(data_alloc_inode, handle, &data_alloc_bh, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_TRUNCATE_LOG_UPDATE);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_replay_truncate_records(osb, handle, data_alloc_inode,
+ data_alloc_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (data_alloc_inode)
+ iput(data_alloc_inode);
+
+ if (data_alloc_bh)
+ brelse(data_alloc_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_flush_truncate_log(struct ocfs2_super *osb)
+{
+ int status;
+ struct inode *tl_inode = osb->osb_tl_inode;
+
+ mutex_lock(&tl_inode->i_mutex);
+ status = __ocfs2_flush_truncate_log(osb);
+ mutex_unlock(&tl_inode->i_mutex);
+
+ return status;
+}
+
+static void ocfs2_truncate_log_worker(void *data)
+{
+ int status;
+ struct ocfs2_super *osb = data;
+
+ mlog_entry_void();
+
+ status = ocfs2_flush_truncate_log(osb);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+}
+
+#define OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL (2 * HZ)
+void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb,
+ int cancel)
+{
+ if (osb->osb_tl_inode) {
+ /* We want to push off log flushes while truncates are
+ * still running. */
+ if (cancel)
+ cancel_delayed_work(&osb->osb_truncate_log_wq);
+
+ queue_delayed_work(ocfs2_wq, &osb->osb_truncate_log_wq,
+ OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL);
+ }
+}
+
+static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb,
+ int slot_num,
+ struct inode **tl_inode,
+ struct buffer_head **tl_bh)
+{
+ int status;
+ struct inode *inode = NULL;
+ struct buffer_head *bh = NULL;
+
+ inode = ocfs2_get_system_file_inode(osb,
+ TRUNCATE_LOG_SYSTEM_INODE,
+ slot_num);
+ if (!inode) {
+ status = -EINVAL;
+ mlog(ML_ERROR, "Could not get load truncate log inode!\n");
+ goto bail;
+ }
+
+ status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
+ OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ iput(inode);
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *tl_inode = inode;
+ *tl_bh = bh;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* called during the 1st stage of node recovery. we stamp a clean
+ * truncate log and pass back a copy for processing later. if the
+ * truncate log does not require processing, a *tl_copy is set to
+ * NULL. */
+int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
+ int slot_num,
+ struct ocfs2_dinode **tl_copy)
+{
+ int status;
+ struct inode *tl_inode = NULL;
+ struct buffer_head *tl_bh = NULL;
+ struct ocfs2_dinode *di;
+ struct ocfs2_truncate_log *tl;
+
+ *tl_copy = NULL;
+
+ mlog(0, "recover truncate log from slot %d\n", slot_num);
+
+ status = ocfs2_get_truncate_log_info(osb, slot_num, &tl_inode, &tl_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ di = (struct ocfs2_dinode *) tl_bh->b_data;
+ tl = &di->id2.i_dealloc;
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ OCFS2_RO_ON_INVALID_DINODE(tl_inode->i_sb, di);
+ status = -EIO;
+ goto bail;
+ }
+
+ if (le16_to_cpu(tl->tl_used)) {
+ mlog(0, "We'll have %u logs to recover\n",
+ le16_to_cpu(tl->tl_used));
+
+ *tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL);
+ if (!(*tl_copy)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Assuming the write-out below goes well, this copy
+ * will be passed back to recovery for processing. */
+ memcpy(*tl_copy, tl_bh->b_data, tl_bh->b_size);
+
+ /* All we need to do to clear the truncate log is set
+ * tl_used. */
+ tl->tl_used = 0;
+
+ status = ocfs2_write_block(osb, tl_bh, tl_inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+bail:
+ if (tl_inode)
+ iput(tl_inode);
+ if (tl_bh)
+ brelse(tl_bh);
+
+ if (status < 0 && (*tl_copy)) {
+ kfree(*tl_copy);
+ *tl_copy = NULL;
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
+ struct ocfs2_dinode *tl_copy)
+{
+ int status = 0;
+ int i;
+ unsigned int clusters, num_recs, start_cluster;
+ u64 start_blk;
+ struct ocfs2_journal_handle *handle;
+ struct inode *tl_inode = osb->osb_tl_inode;
+ struct ocfs2_truncate_log *tl;
+
+ mlog_entry_void();
+
+ if (OCFS2_I(tl_inode)->ip_blkno == le64_to_cpu(tl_copy->i_blkno)) {
+ mlog(ML_ERROR, "Asked to recover my own truncate log!\n");
+ return -EINVAL;
+ }
+
+ tl = &tl_copy->id2.i_dealloc;
+ num_recs = le16_to_cpu(tl->tl_used);
+ mlog(0, "cleanup %u records from %"MLFu64"\n", num_recs,
+ tl_copy->i_blkno);
+
+ mutex_lock(&tl_inode->i_mutex);
+ for(i = 0; i < num_recs; i++) {
+ if (ocfs2_truncate_log_needs_flush(osb)) {
+ status = __ocfs2_flush_truncate_log(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_up;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, NULL,
+ OCFS2_TRUNCATE_LOG_UPDATE);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ mlog_errno(status);
+ goto bail_up;
+ }
+
+ clusters = le32_to_cpu(tl->tl_recs[i].t_clusters);
+ start_cluster = le32_to_cpu(tl->tl_recs[i].t_start);
+ start_blk = ocfs2_clusters_to_blocks(osb->sb, start_cluster);
+
+ status = ocfs2_truncate_log_append(osb, handle,
+ start_blk, clusters);
+ ocfs2_commit_trans(handle);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_up;
+ }
+ }
+
+bail_up:
+ mutex_unlock(&tl_inode->i_mutex);
+
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb)
+{
+ int status;
+ struct inode *tl_inode = osb->osb_tl_inode;
+
+ mlog_entry_void();
+
+ if (tl_inode) {
+ cancel_delayed_work(&osb->osb_truncate_log_wq);
+ flush_workqueue(ocfs2_wq);
+
+ status = ocfs2_flush_truncate_log(osb);
+ if (status < 0)
+ mlog_errno(status);
+
+ brelse(osb->osb_tl_bh);
+ iput(osb->osb_tl_inode);
+ }
+
+ mlog_exit_void();
+}
+
+int ocfs2_truncate_log_init(struct ocfs2_super *osb)
+{
+ int status;
+ struct inode *tl_inode = NULL;
+ struct buffer_head *tl_bh = NULL;
+
+ mlog_entry_void();
+
+ status = ocfs2_get_truncate_log_info(osb,
+ osb->slot_num,
+ &tl_inode,
+ &tl_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* ocfs2_truncate_log_shutdown keys on the existence of
+ * osb->osb_tl_inode so we don't set any of the osb variables
+ * until we're sure all is well. */
+ INIT_WORK(&osb->osb_truncate_log_wq, ocfs2_truncate_log_worker, osb);
+ osb->osb_tl_bh = tl_bh;
+ osb->osb_tl_inode = tl_inode;
+
+ mlog_exit(status);
+ return status;
+}
+
+/* This function will figure out whether the currently last extent
+ * block will be deleted, and if it will, what the new last extent
+ * block will be so we can update his h_next_leaf_blk field, as well
+ * as the dinodes i_last_eb_blk */
+static int ocfs2_find_new_last_ext_blk(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct ocfs2_dinode *fe,
+ u32 new_i_clusters,
+ struct buffer_head *old_last_eb,
+ struct buffer_head **new_last_eb)
+{
+ int i, status = 0;
+ u64 block = 0;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *bh = NULL;
+
+ *new_last_eb = NULL;
+
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+ status = -EIO;
+ goto bail;
+ }
+
+ /* we have no tree, so of course, no last_eb. */
+ if (!fe->id2.i_list.l_tree_depth)
+ goto bail;
+
+ /* trunc to zero special case - this makes tree_depth = 0
+ * regardless of what it is. */
+ if (!new_i_clusters)
+ goto bail;
+
+ eb = (struct ocfs2_extent_block *) old_last_eb->b_data;
+ el = &(eb->h_list);
+ BUG_ON(!el->l_next_free_rec);
+
+ /* Make sure that this guy will actually be empty after we
+ * clear away the data. */
+ if (le32_to_cpu(el->l_recs[0].e_cpos) < new_i_clusters)
+ goto bail;
+
+ /* Ok, at this point, we know that last_eb will definitely
+ * change, so lets traverse the tree and find the second to
+ * last extent block. */
+ el = &(fe->id2.i_list);
+ /* go down the tree, */
+ do {
+ for(i = (le16_to_cpu(el->l_next_free_rec) - 1); i >= 0; i--) {
+ if (le32_to_cpu(el->l_recs[i].e_cpos) <
+ new_i_clusters) {
+ block = le64_to_cpu(el->l_recs[i].e_blkno);
+ break;
+ }
+ }
+ BUG_ON(i < 0);
+
+ if (bh) {
+ brelse(bh);
+ bh = NULL;
+ }
+
+ status = ocfs2_read_block(osb, block, &bh, OCFS2_BH_CACHED,
+ inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) bh->b_data;
+ el = &eb->h_list;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+ } while (el->l_tree_depth);
+
+ *new_last_eb = bh;
+ get_bh(*new_last_eb);
+ mlog(0, "returning block %"MLFu64"\n", le64_to_cpu(eb->h_blkno));
+bail:
+ if (bh)
+ brelse(bh);
+
+ return status;
+}
+
+static int ocfs2_do_truncate(struct ocfs2_super *osb,
+ unsigned int clusters_to_del,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head *old_last_eb_bh,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_truncate_context *tc)
+{
+ int status, i, depth;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_block *last_eb = NULL;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *eb_bh = NULL;
+ struct buffer_head *last_eb_bh = NULL;
+ u64 next_eb = 0;
+ u64 delete_blk = 0;
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ status = ocfs2_find_new_last_ext_blk(osb,
+ inode,
+ fe,
+ le32_to_cpu(fe->i_clusters) -
+ clusters_to_del,
+ old_last_eb_bh,
+ &last_eb_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ if (last_eb_bh)
+ last_eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ el = &(fe->id2.i_list);
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters) -
+ clusters_to_del;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ le32_add_cpu(&fe->i_clusters, -clusters_to_del);
+ fe->i_mtime = cpu_to_le64(CURRENT_TIME.tv_sec);
+ fe->i_mtime_nsec = cpu_to_le32(CURRENT_TIME.tv_nsec);
+
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+
+ BUG_ON(le32_to_cpu(el->l_recs[i].e_clusters) < clusters_to_del);
+ le32_add_cpu(&el->l_recs[i].e_clusters, -clusters_to_del);
+ /* tree depth zero, we can just delete the clusters, otherwise
+ * we need to record the offset of the next level extent block
+ * as we may overwrite it. */
+ if (!el->l_tree_depth)
+ delete_blk = le64_to_cpu(el->l_recs[i].e_blkno)
+ + ocfs2_clusters_to_blocks(osb->sb,
+ le32_to_cpu(el->l_recs[i].e_clusters));
+ else
+ next_eb = le64_to_cpu(el->l_recs[i].e_blkno);
+
+ if (!el->l_recs[i].e_clusters) {
+ /* if we deleted the whole extent record, then clear
+ * out the other fields and update the extent
+ * list. For depth > 0 trees, we've already recorded
+ * the extent block in 'next_eb' */
+ el->l_recs[i].e_cpos = 0;
+ el->l_recs[i].e_blkno = 0;
+ BUG_ON(!el->l_next_free_rec);
+ le16_add_cpu(&el->l_next_free_rec, -1);
+ }
+
+ depth = le16_to_cpu(el->l_tree_depth);
+ if (!fe->i_clusters) {
+ /* trunc to zero is a special case. */
+ el->l_tree_depth = 0;
+ fe->i_last_eb_blk = 0;
+ } else if (last_eb)
+ fe->i_last_eb_blk = last_eb->h_blkno;
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (last_eb) {
+ /* If there will be a new last extent block, then by
+ * definition, there cannot be any leaves to the right of
+ * him. */
+ status = ocfs2_journal_access(handle, inode, last_eb_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ last_eb->h_next_leaf_blk = 0;
+ status = ocfs2_journal_dirty(handle, last_eb_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ /* if our tree depth > 0, update all the tree blocks below us. */
+ while (depth) {
+ mlog(0, "traveling tree (depth = %d, next_eb = %"MLFu64")\n",
+ depth, next_eb);
+ status = ocfs2_read_block(osb, next_eb, &eb_bh,
+ OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *)eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+ el = &(eb->h_list);
+
+ status = ocfs2_journal_access(handle, inode, eb_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ BUG_ON(le16_to_cpu(el->l_next_free_rec) == 0);
+ BUG_ON(depth != (le16_to_cpu(el->l_tree_depth) + 1));
+
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+
+ mlog(0, "extent block %"MLFu64", before: record %d: "
+ "(%u, %u, %"MLFu64"), next = %u\n",
+ le64_to_cpu(eb->h_blkno), i,
+ le32_to_cpu(el->l_recs[i].e_cpos),
+ le32_to_cpu(el->l_recs[i].e_clusters),
+ le64_to_cpu(el->l_recs[i].e_blkno),
+ le16_to_cpu(el->l_next_free_rec));
+
+ BUG_ON(le32_to_cpu(el->l_recs[i].e_clusters) < clusters_to_del);
+ le32_add_cpu(&el->l_recs[i].e_clusters, -clusters_to_del);
+
+ next_eb = le64_to_cpu(el->l_recs[i].e_blkno);
+ /* bottom-most block requires us to delete data.*/
+ if (!el->l_tree_depth)
+ delete_blk = le64_to_cpu(el->l_recs[i].e_blkno)
+ + ocfs2_clusters_to_blocks(osb->sb,
+ le32_to_cpu(el->l_recs[i].e_clusters));
+ if (!el->l_recs[i].e_clusters) {
+ el->l_recs[i].e_cpos = 0;
+ el->l_recs[i].e_blkno = 0;
+ BUG_ON(!el->l_next_free_rec);
+ le16_add_cpu(&el->l_next_free_rec, -1);
+ }
+ mlog(0, "extent block %"MLFu64", after: record %d: "
+ "(%u, %u, %"MLFu64"), next = %u\n",
+ le64_to_cpu(eb->h_blkno), i,
+ le32_to_cpu(el->l_recs[i].e_cpos),
+ le32_to_cpu(el->l_recs[i].e_clusters),
+ le64_to_cpu(el->l_recs[i].e_blkno),
+ le16_to_cpu(el->l_next_free_rec));
+
+ status = ocfs2_journal_dirty(handle, eb_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (!el->l_next_free_rec) {
+ mlog(0, "deleting this extent block.\n");
+
+ ocfs2_remove_from_cache(inode, eb_bh);
+
+ BUG_ON(eb->h_suballoc_slot);
+ BUG_ON(el->l_recs[0].e_clusters);
+ BUG_ON(el->l_recs[0].e_cpos);
+ BUG_ON(el->l_recs[0].e_blkno);
+ status = ocfs2_free_extent_block(handle,
+ tc->tc_ext_alloc_inode,
+ tc->tc_ext_alloc_bh,
+ eb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ brelse(eb_bh);
+ eb_bh = NULL;
+ depth--;
+ }
+
+ BUG_ON(!delete_blk);
+ status = ocfs2_truncate_log_append(osb, handle, delete_blk,
+ clusters_to_del);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ status = 0;
+bail:
+ if (!status)
+ ocfs2_extent_map_trunc(inode, le32_to_cpu(fe->i_clusters));
+ else
+ ocfs2_extent_map_drop(inode, 0);
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * It is expected, that by the time you call this function,
+ * inode->i_size and fe->i_size have been adjusted.
+ *
+ * WARNING: This will kfree the truncate context
+ */
+int ocfs2_commit_truncate(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_truncate_context *tc)
+{
+ int status, i, credits, tl_sem = 0;
+ u32 clusters_to_del, target_i_clusters;
+ u64 last_eb = 0;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *last_eb_bh;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct inode *tl_inode = osb->osb_tl_inode;
+
+ mlog_entry_void();
+
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ target_i_clusters = ocfs2_clusters_for_bytes(osb->sb,
+ i_size_read(inode));
+
+ last_eb_bh = tc->tc_last_eb_bh;
+ tc->tc_last_eb_bh = NULL;
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ if (fe->id2.i_list.l_tree_depth) {
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ el = &eb->h_list;
+ } else
+ el = &fe->id2.i_list;
+ last_eb = le64_to_cpu(fe->i_last_eb_blk);
+start:
+ mlog(0, "ocfs2_commit_truncate: fe->i_clusters = %u, "
+ "last_eb = %"MLFu64", fe->i_last_eb_blk = %"MLFu64", "
+ "fe->id2.i_list.l_tree_depth = %u last_eb_bh = %p\n",
+ le32_to_cpu(fe->i_clusters), last_eb,
+ le64_to_cpu(fe->i_last_eb_blk),
+ le16_to_cpu(fe->id2.i_list.l_tree_depth), last_eb_bh);
+
+ if (last_eb != le64_to_cpu(fe->i_last_eb_blk)) {
+ mlog(0, "last_eb changed!\n");
+ BUG_ON(!fe->id2.i_list.l_tree_depth);
+ last_eb = le64_to_cpu(fe->i_last_eb_blk);
+ /* i_last_eb_blk may have changed, read it if
+ * necessary. We don't have to worry about the
+ * truncate to zero case here (where there becomes no
+ * last_eb) because we never loop back after our work
+ * is done. */
+ if (last_eb_bh) {
+ brelse(last_eb_bh);
+ last_eb_bh = NULL;
+ }
+
+ status = ocfs2_read_block(osb, last_eb,
+ &last_eb_bh, OCFS2_BH_CACHED,
+ inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ status = -EIO;
+ goto bail;
+ }
+ el = &(eb->h_list);
+ }
+
+ /* by now, el will point to the extent list on the bottom most
+ * portion of this tree. */
+ i = le16_to_cpu(el->l_next_free_rec) - 1;
+ if (le32_to_cpu(el->l_recs[i].e_cpos) >= target_i_clusters)
+ clusters_to_del = le32_to_cpu(el->l_recs[i].e_clusters);
+ else
+ clusters_to_del = (le32_to_cpu(el->l_recs[i].e_clusters) +
+ le32_to_cpu(el->l_recs[i].e_cpos)) -
+ target_i_clusters;
+
+ mlog(0, "clusters_to_del = %u in this pass\n", clusters_to_del);
+
+ mutex_lock(&tl_inode->i_mutex);
+ tl_sem = 1;
+ /* ocfs2_truncate_log_needs_flush guarantees us at least one
+ * record is free for use. If there isn't any, we flush to get
+ * an empty truncate log. */
+ if (ocfs2_truncate_log_needs_flush(osb)) {
+ status = __ocfs2_flush_truncate_log(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ credits = ocfs2_calc_tree_trunc_credits(osb->sb, clusters_to_del,
+ fe, el);
+ handle = ocfs2_start_trans(osb, NULL, credits);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+ status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+ status = ocfs2_do_truncate(osb, clusters_to_del, inode, fe_bh,
+ last_eb_bh, handle, tc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mutex_unlock(&tl_inode->i_mutex);
+ tl_sem = 0;
+
+ ocfs2_commit_trans(handle);
+ handle = NULL;
+
+ BUG_ON(le32_to_cpu(fe->i_clusters) < target_i_clusters);
+ if (le32_to_cpu(fe->i_clusters) > target_i_clusters)
+ goto start;
+bail:
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ocfs2_schedule_truncate_log_flush(osb, 1);
+
+ if (tl_sem)
+ mutex_unlock(&tl_inode->i_mutex);
+
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (last_eb_bh)
+ brelse(last_eb_bh);
+
+ /* This will drop the ext_alloc cluster lock for us */
+ ocfs2_free_truncate_context(tc);
+
+ mlog_exit(status);
+ return status;
+}
+
+
+/*
+ * Expects the inode to already be locked. This will figure out which
+ * inodes need to be locked and will put them on the returned truncate
+ * context.
+ */
+int ocfs2_prepare_truncate(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_truncate_context **tc)
+{
+ int status, metadata_delete;
+ unsigned int new_i_clusters;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_list *el;
+ struct buffer_head *last_eb_bh = NULL;
+ struct inode *ext_alloc_inode = NULL;
+ struct buffer_head *ext_alloc_bh = NULL;
+
+ mlog_entry_void();
+
+ *tc = NULL;
+
+ new_i_clusters = ocfs2_clusters_for_bytes(osb->sb,
+ i_size_read(inode));
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ mlog(0, "fe->i_clusters = %u, new_i_clusters = %u, fe->i_size ="
+ "%"MLFu64"\n", fe->i_clusters, new_i_clusters, fe->i_size);
+
+ if (le32_to_cpu(fe->i_clusters) <= new_i_clusters) {
+ ocfs2_error(inode->i_sb, "Dinode %"MLFu64" has cluster count "
+ "%u and size %"MLFu64" whereas struct inode has "
+ "cluster count %u and size %llu which caused an "
+ "invalid truncate to %u clusters.",
+ le64_to_cpu(fe->i_blkno),
+ le32_to_cpu(fe->i_clusters),
+ le64_to_cpu(fe->i_size),
+ OCFS2_I(inode)->ip_clusters, i_size_read(inode),
+ new_i_clusters);
+ mlog_meta_lvb(ML_ERROR, &OCFS2_I(inode)->ip_meta_lockres);
+ status = -EIO;
+ goto bail;
+ }
+
+ *tc = kcalloc(1, sizeof(struct ocfs2_truncate_context), GFP_KERNEL);
+ if (!(*tc)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ metadata_delete = 0;
+ if (fe->id2.i_list.l_tree_depth) {
+ /* If we have a tree, then the truncate may result in
+ * metadata deletes. Figure this out from the
+ * rightmost leaf block.*/
+ status = ocfs2_read_block(osb, le64_to_cpu(fe->i_last_eb_blk),
+ &last_eb_bh, OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ eb = (struct ocfs2_extent_block *) last_eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+
+ brelse(last_eb_bh);
+ status = -EIO;
+ goto bail;
+ }
+ el = &(eb->h_list);
+ if (le32_to_cpu(el->l_recs[0].e_cpos) >= new_i_clusters)
+ metadata_delete = 1;
+ }
+
+ (*tc)->tc_last_eb_bh = last_eb_bh;
+
+ if (metadata_delete) {
+ mlog(0, "Will have to delete metadata for this trunc. "
+ "locking allocator.\n");
+ ext_alloc_inode = ocfs2_get_system_file_inode(osb, EXTENT_ALLOC_SYSTEM_INODE, 0);
+ if (!ext_alloc_inode) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mutex_lock(&ext_alloc_inode->i_mutex);
+ (*tc)->tc_ext_alloc_inode = ext_alloc_inode;
+
+ status = ocfs2_meta_lock(ext_alloc_inode,
+ NULL,
+ &ext_alloc_bh,
+ 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ (*tc)->tc_ext_alloc_bh = ext_alloc_bh;
+ (*tc)->tc_ext_alloc_locked = 1;
+ }
+
+ status = 0;
+bail:
+ if (status < 0) {
+ if (*tc)
+ ocfs2_free_truncate_context(*tc);
+ *tc = NULL;
+ }
+ mlog_exit_void();
+ return status;
+}
+
+static void ocfs2_free_truncate_context(struct ocfs2_truncate_context *tc)
+{
+ if (tc->tc_ext_alloc_inode) {
+ if (tc->tc_ext_alloc_locked)
+ ocfs2_meta_unlock(tc->tc_ext_alloc_inode, 1);
+
+ mutex_unlock(&tc->tc_ext_alloc_inode->i_mutex);
+ iput(tc->tc_ext_alloc_inode);
+ }
+
+ if (tc->tc_ext_alloc_bh)
+ brelse(tc->tc_ext_alloc_bh);
+
+ if (tc->tc_last_eb_bh)
+ brelse(tc->tc_last_eb_bh);
+
+ kfree(tc);
+}
diff --git a/fs/ocfs2/alloc.h b/fs/ocfs2/alloc.h
new file mode 100644
index 000000000000..12ba897743f4
--- /dev/null
+++ b/fs/ocfs2/alloc.h
@@ -0,0 +1,82 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * alloc.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_ALLOC_H
+#define OCFS2_ALLOC_H
+
+struct ocfs2_alloc_context;
+int ocfs2_insert_extent(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 blkno,
+ u32 new_clusters,
+ struct ocfs2_alloc_context *meta_ac);
+int ocfs2_num_free_extents(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct ocfs2_dinode *fe);
+/* how many new metadata chunks would an allocation need at maximum? */
+static inline int ocfs2_extend_meta_needed(struct ocfs2_dinode *fe)
+{
+ /*
+ * Rather than do all the work of determining how much we need
+ * (involves a ton of reads and locks), just ask for the
+ * maximal limit. That's a tree depth shift. So, one block for
+ * level of the tree (current l_tree_depth), one block for the
+ * new tree_depth==0 extent_block, and one block at the new
+ * top-of-the tree.
+ */
+ return le16_to_cpu(fe->id2.i_list.l_tree_depth) + 2;
+}
+
+int ocfs2_truncate_log_init(struct ocfs2_super *osb);
+void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb);
+void ocfs2_schedule_truncate_log_flush(struct ocfs2_super *osb,
+ int cancel);
+int ocfs2_flush_truncate_log(struct ocfs2_super *osb);
+int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb,
+ int slot_num,
+ struct ocfs2_dinode **tl_copy);
+int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb,
+ struct ocfs2_dinode *tl_copy);
+
+struct ocfs2_truncate_context {
+ struct inode *tc_ext_alloc_inode;
+ struct buffer_head *tc_ext_alloc_bh;
+ int tc_ext_alloc_locked; /* is it cluster locked? */
+ /* these get destroyed once it's passed to ocfs2_commit_truncate. */
+ struct buffer_head *tc_last_eb_bh;
+};
+
+int ocfs2_prepare_truncate(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_truncate_context **tc);
+int ocfs2_commit_truncate(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_truncate_context *tc);
+
+#endif /* OCFS2_ALLOC_H */
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
new file mode 100644
index 000000000000..8f4467a930a5
--- /dev/null
+++ b/fs/ocfs2/aops.c
@@ -0,0 +1,643 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <asm/byteorder.h>
+
+#define MLOG_MASK_PREFIX ML_FILE_IO
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "aops.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "file.h"
+#include "inode.h"
+#include "journal.h"
+#include "super.h"
+#include "symlink.h"
+
+#include "buffer_head_io.h"
+
+static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ int err = -EIO;
+ int status;
+ struct ocfs2_dinode *fe = NULL;
+ struct buffer_head *bh = NULL;
+ struct buffer_head *buffer_cache_bh = NULL;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ void *kaddr;
+
+ mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode,
+ (unsigned long long)iblock, bh_result, create);
+
+ BUG_ON(ocfs2_inode_is_fast_symlink(inode));
+
+ if ((iblock << inode->i_sb->s_blocksize_bits) > PATH_MAX + 1) {
+ mlog(ML_ERROR, "block offset > PATH_MAX: %llu",
+ (unsigned long long)iblock);
+ goto bail;
+ }
+
+ status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ OCFS2_I(inode)->ip_blkno,
+ &bh, OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ fe = (struct ocfs2_dinode *) bh->b_data;
+
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ mlog(ML_ERROR, "Invalid dinode #%"MLFu64": signature = %.*s\n",
+ fe->i_blkno, 7, fe->i_signature);
+ goto bail;
+ }
+
+ if ((u64)iblock >= ocfs2_clusters_to_blocks(inode->i_sb,
+ le32_to_cpu(fe->i_clusters))) {
+ mlog(ML_ERROR, "block offset is outside the allocated size: "
+ "%llu\n", (unsigned long long)iblock);
+ goto bail;
+ }
+
+ /* We don't use the page cache to create symlink data, so if
+ * need be, copy it over from the buffer cache. */
+ if (!buffer_uptodate(bh_result) && ocfs2_inode_is_new(inode)) {
+ u64 blkno = le64_to_cpu(fe->id2.i_list.l_recs[0].e_blkno) +
+ iblock;
+ buffer_cache_bh = sb_getblk(osb->sb, blkno);
+ if (!buffer_cache_bh) {
+ mlog(ML_ERROR, "couldn't getblock for symlink!\n");
+ goto bail;
+ }
+
+ /* we haven't locked out transactions, so a commit
+ * could've happened. Since we've got a reference on
+ * the bh, even if it commits while we're doing the
+ * copy, the data is still good. */
+ if (buffer_jbd(buffer_cache_bh)
+ && ocfs2_inode_is_new(inode)) {
+ kaddr = kmap_atomic(bh_result->b_page, KM_USER0);
+ if (!kaddr) {
+ mlog(ML_ERROR, "couldn't kmap!\n");
+ goto bail;
+ }
+ memcpy(kaddr + (bh_result->b_size * iblock),
+ buffer_cache_bh->b_data,
+ bh_result->b_size);
+ kunmap_atomic(kaddr, KM_USER0);
+ set_buffer_uptodate(bh_result);
+ }
+ brelse(buffer_cache_bh);
+ }
+
+ map_bh(bh_result, inode->i_sb,
+ le64_to_cpu(fe->id2.i_list.l_recs[0].e_blkno) + iblock);
+
+ err = 0;
+
+bail:
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(err);
+ return err;
+}
+
+static int ocfs2_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ int err = 0;
+ u64 p_blkno, past_eof;
+
+ mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode,
+ (unsigned long long)iblock, bh_result, create);
+
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE)
+ mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n",
+ inode, inode->i_ino);
+
+ if (S_ISLNK(inode->i_mode)) {
+ /* this always does I/O for some reason. */
+ err = ocfs2_symlink_get_block(inode, iblock, bh_result, create);
+ goto bail;
+ }
+
+ /* this can happen if another node truncs after our extend! */
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ if (iblock >= ocfs2_clusters_to_blocks(inode->i_sb,
+ OCFS2_I(inode)->ip_clusters))
+ err = -EIO;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ if (err)
+ goto bail;
+
+ err = ocfs2_extent_map_get_blocks(inode, iblock, 1, &p_blkno,
+ NULL);
+ if (err) {
+ mlog(ML_ERROR, "Error %d from get_blocks(0x%p, %llu, 1, "
+ "%"MLFu64", NULL)\n", err, inode,
+ (unsigned long long)iblock, p_blkno);
+ goto bail;
+ }
+
+ map_bh(bh_result, inode->i_sb, p_blkno);
+
+ if (bh_result->b_blocknr == 0) {
+ err = -EIO;
+ mlog(ML_ERROR, "iblock = %llu p_blkno = %"MLFu64" "
+ "blkno=(%"MLFu64")\n", (unsigned long long)iblock,
+ p_blkno, OCFS2_I(inode)->ip_blkno);
+ }
+
+ past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
+ mlog(0, "Inode %lu, past_eof = %"MLFu64"\n", inode->i_ino, past_eof);
+
+ if (create && (iblock >= past_eof))
+ set_buffer_new(bh_result);
+
+bail:
+ if (err < 0)
+ err = -EIO;
+
+ mlog_exit(err);
+ return err;
+}
+
+static int ocfs2_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ int ret, unlock = 1;
+
+ mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0));
+
+ ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page);
+ if (ret != 0) {
+ if (ret == AOP_TRUNCATED_PAGE)
+ unlock = 0;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ /*
+ * i_size might have just been updated as we grabed the meta lock. We
+ * might now be discovering a truncate that hit on another node.
+ * block_read_full_page->get_block freaks out if it is asked to read
+ * beyond the end of a file, so we check here. Callers
+ * (generic_file_read, fault->nopage) are clever enough to check i_size
+ * and notice that the page they just read isn't needed.
+ *
+ * XXX sys_readahead() seems to get that wrong?
+ */
+ if (start >= i_size_read(inode)) {
+ char *addr = kmap(page);
+ memset(addr, 0, PAGE_SIZE);
+ flush_dcache_page(page);
+ kunmap(page);
+ SetPageUptodate(page);
+ ret = 0;
+ goto out_alloc;
+ }
+
+ ret = ocfs2_data_lock_with_page(inode, 0, page);
+ if (ret != 0) {
+ if (ret == AOP_TRUNCATED_PAGE)
+ unlock = 0;
+ mlog_errno(ret);
+ goto out_alloc;
+ }
+
+ ret = block_read_full_page(page, ocfs2_get_block);
+ unlock = 0;
+
+ ocfs2_data_unlock(inode, 0);
+out_alloc:
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+ ocfs2_meta_unlock(inode, 0);
+out:
+ if (unlock)
+ unlock_page(page);
+ mlog_exit(ret);
+ return ret;
+}
+
+/* Note: Because we don't support holes, our allocation has
+ * already happened (allocation writes zeros to the file data)
+ * so we don't have to worry about ordered writes in
+ * ocfs2_writepage.
+ *
+ * ->writepage is called during the process of invalidating the page cache
+ * during blocked lock processing. It can't block on any cluster locks
+ * to during block mapping. It's relying on the fact that the block
+ * mapping can't have disappeared under the dirty pages that it is
+ * being asked to write back.
+ */
+static int ocfs2_writepage(struct page *page, struct writeback_control *wbc)
+{
+ int ret;
+
+ mlog_entry("(0x%p)\n", page);
+
+ ret = block_write_full_page(page, ocfs2_get_block, wbc);
+
+ mlog_exit(ret);
+
+ return ret;
+}
+
+/*
+ * ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called
+ * from loopback. It must be able to perform its own locking around
+ * ocfs2_get_block().
+ */
+int ocfs2_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ struct inode *inode = page->mapping->host;
+ int ret;
+
+ mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
+
+ ret = ocfs2_meta_lock_with_page(inode, NULL, NULL, 0, page);
+ if (ret != 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ret = block_prepare_write(page, from, to, ocfs2_get_block);
+
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+ ocfs2_meta_unlock(inode, 0);
+out:
+ mlog_exit(ret);
+ return ret;
+}
+
+/* Taken from ext3. We don't necessarily need the full blown
+ * functionality yet, but IMHO it's better to cut and paste the whole
+ * thing so we can avoid introducing our own bugs (and easily pick up
+ * their fixes when they happen) --Mark */
+static int walk_page_buffers( handle_t *handle,
+ struct buffer_head *head,
+ unsigned from,
+ unsigned to,
+ int *partial,
+ int (*fn)( handle_t *handle,
+ struct buffer_head *bh))
+{
+ struct buffer_head *bh;
+ unsigned block_start, block_end;
+ unsigned blocksize = head->b_size;
+ int err, ret = 0;
+ struct buffer_head *next;
+
+ for ( bh = head, block_start = 0;
+ ret == 0 && (bh != head || !block_start);
+ block_start = block_end, bh = next)
+ {
+ next = bh->b_this_page;
+ block_end = block_start + blocksize;
+ if (block_end <= from || block_start >= to) {
+ if (partial && !buffer_uptodate(bh))
+ *partial = 1;
+ continue;
+ }
+ err = (*fn)(handle, bh);
+ if (!ret)
+ ret = err;
+ }
+ return ret;
+}
+
+struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
+ struct page *page,
+ unsigned from,
+ unsigned to)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_journal_handle *handle = NULL;
+ int ret = 0;
+
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
+ if (!handle) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ if (ocfs2_should_order_data(inode)) {
+ ret = walk_page_buffers(handle->k_handle,
+ page_buffers(page),
+ from, to, NULL,
+ ocfs2_journal_dirty_data);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+out:
+ if (ret) {
+ if (handle)
+ ocfs2_commit_trans(handle);
+ handle = ERR_PTR(ret);
+ }
+ return handle;
+}
+
+static int ocfs2_commit_write(struct file *file, struct page *page,
+ unsigned from, unsigned to)
+{
+ int ret, extending = 0, locklevel = 0;
+ loff_t new_i_size;
+ struct buffer_head *di_bh = NULL;
+ struct inode *inode = page->mapping->host;
+ struct ocfs2_journal_handle *handle = NULL;
+
+ mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to);
+
+ /* NOTE: ocfs2_file_aio_write has ensured that it's safe for
+ * us to sample inode->i_size here without the metadata lock:
+ *
+ * 1) We're currently holding the inode alloc lock, so no
+ * nodes can change it underneath us.
+ *
+ * 2) We've had to take the metadata lock at least once
+ * already to check for extending writes, hence insuring
+ * that our current copy is also up to date.
+ */
+ new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+ if (new_i_size > i_size_read(inode)) {
+ extending = 1;
+ locklevel = 1;
+ }
+
+ ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page);
+ if (ret != 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_data_lock_with_page(inode, 1, page);
+ if (ret != 0) {
+ mlog_errno(ret);
+ goto out_unlock_meta;
+ }
+
+ if (extending) {
+ handle = ocfs2_start_walk_page_trans(inode, page, from, to);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ handle = NULL;
+ goto out_unlock_data;
+ }
+
+ /* Mark our buffer early. We'd rather catch this error up here
+ * as opposed to after a successful commit_write which would
+ * require us to set back inode->i_size. */
+ ret = ocfs2_journal_access(handle, inode, di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+ }
+
+ /* might update i_size */
+ ret = generic_commit_write(file, page, from, to);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+
+ if (extending) {
+ loff_t size = (u64) i_size_read(inode);
+ struct ocfs2_dinode *di =
+ (struct ocfs2_dinode *)di_bh->b_data;
+
+ /* ocfs2_mark_inode_dirty is too heavy to use here. */
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(size);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ di->i_size = cpu_to_le64(size);
+ di->i_ctime = di->i_mtime =
+ cpu_to_le64(inode->i_mtime.tv_sec);
+ di->i_ctime_nsec = di->i_mtime_nsec =
+ cpu_to_le32(inode->i_mtime.tv_nsec);
+
+ ret = ocfs2_journal_dirty(handle, di_bh);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_commit;
+ }
+ }
+
+ BUG_ON(extending && (i_size_read(inode) != new_i_size));
+
+out_commit:
+ if (handle)
+ ocfs2_commit_trans(handle);
+out_unlock_data:
+ ocfs2_data_unlock(inode, 1);
+out_unlock_meta:
+ ocfs2_meta_unlock(inode, locklevel);
+out:
+ if (di_bh)
+ brelse(di_bh);
+
+ mlog_exit(ret);
+ return ret;
+}
+
+static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
+{
+ sector_t status;
+ u64 p_blkno = 0;
+ int err = 0;
+ struct inode *inode = mapping->host;
+
+ mlog_entry("(block = %llu)\n", (unsigned long long)block);
+
+ /* We don't need to lock journal system files, since they aren't
+ * accessed concurrently from multiple nodes.
+ */
+ if (!INODE_JOURNAL(inode)) {
+ err = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (err) {
+ if (err != -ENOENT)
+ mlog_errno(err);
+ goto bail;
+ }
+ down_read(&OCFS2_I(inode)->ip_alloc_sem);
+ }
+
+ err = ocfs2_extent_map_get_blocks(inode, block, 1, &p_blkno,
+ NULL);
+
+ if (!INODE_JOURNAL(inode)) {
+ up_read(&OCFS2_I(inode)->ip_alloc_sem);
+ ocfs2_meta_unlock(inode, 0);
+ }
+
+ if (err) {
+ mlog(ML_ERROR, "get_blocks() failed, block = %llu\n",
+ (unsigned long long)block);
+ mlog_errno(err);
+ goto bail;
+ }
+
+
+bail:
+ status = err ? 0 : p_blkno;
+
+ mlog_exit((int)status);
+
+ return status;
+}
+
+/*
+ * TODO: Make this into a generic get_blocks function.
+ *
+ * From do_direct_io in direct-io.c:
+ * "So what we do is to permit the ->get_blocks function to populate
+ * bh.b_size with the size of IO which is permitted at this offset and
+ * this i_blkbits."
+ *
+ * This function is called directly from get_more_blocks in direct-io.c.
+ *
+ * called like this: dio->get_blocks(dio->inode, fs_startblk,
+ * fs_count, map_bh, dio->rw == WRITE);
+ */
+static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock,
+ unsigned long max_blocks,
+ struct buffer_head *bh_result, int create)
+{
+ int ret;
+ u64 vbo_max; /* file offset, max_blocks from iblock */
+ u64 p_blkno;
+ int contig_blocks;
+ unsigned char blocksize_bits;
+
+ if (!inode || !bh_result) {
+ mlog(ML_ERROR, "inode or bh_result is null\n");
+ return -EIO;
+ }
+
+ blocksize_bits = inode->i_sb->s_blocksize_bits;
+
+ /* This function won't even be called if the request isn't all
+ * nicely aligned and of the right size, so there's no need
+ * for us to check any of that. */
+
+ vbo_max = ((u64)iblock + max_blocks) << blocksize_bits;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ if ((iblock + max_blocks) >
+ ocfs2_clusters_to_blocks(inode->i_sb,
+ OCFS2_I(inode)->ip_clusters)) {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ ret = -EIO;
+ goto bail;
+ }
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ /* This figures out the size of the next contiguous block, and
+ * our logical offset */
+ ret = ocfs2_extent_map_get_blocks(inode, iblock, 1, &p_blkno,
+ &contig_blocks);
+ if (ret) {
+ mlog(ML_ERROR, "get_blocks() failed iblock=%llu\n",
+ (unsigned long long)iblock);
+ ret = -EIO;
+ goto bail;
+ }
+
+ map_bh(bh_result, inode->i_sb, p_blkno);
+
+ /* make sure we don't map more than max_blocks blocks here as
+ that's all the kernel will handle at this point. */
+ if (max_blocks < contig_blocks)
+ contig_blocks = max_blocks;
+ bh_result->b_size = contig_blocks << blocksize_bits;
+bail:
+ return ret;
+}
+
+/*
+ * ocfs2_dio_end_io is called by the dio core when a dio is finished. We're
+ * particularly interested in the aio/dio case. Like the core uses
+ * i_alloc_sem, we use the rw_lock DLM lock to protect io on one node from
+ * truncation on another.
+ */
+static void ocfs2_dio_end_io(struct kiocb *iocb,
+ loff_t offset,
+ ssize_t bytes,
+ void *private)
+{
+ struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+
+ /* this io's submitter should not have unlocked this before we could */
+ BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
+ ocfs2_iocb_clear_rw_locked(iocb);
+ up_read(&inode->i_alloc_sem);
+ ocfs2_rw_unlock(inode, 0);
+}
+
+static ssize_t ocfs2_direct_IO(int rw,
+ struct kiocb *iocb,
+ const struct iovec *iov,
+ loff_t offset,
+ unsigned long nr_segs)
+{
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
+ int ret;
+
+ mlog_entry_void();
+ ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
+ inode->i_sb->s_bdev, iov, offset,
+ nr_segs,
+ ocfs2_direct_IO_get_blocks,
+ ocfs2_dio_end_io);
+ mlog_exit(ret);
+ return ret;
+}
+
+struct address_space_operations ocfs2_aops = {
+ .readpage = ocfs2_readpage,
+ .writepage = ocfs2_writepage,
+ .prepare_write = ocfs2_prepare_write,
+ .commit_write = ocfs2_commit_write,
+ .bmap = ocfs2_bmap,
+ .sync_page = block_sync_page,
+ .direct_IO = ocfs2_direct_IO
+};
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h
new file mode 100644
index 000000000000..d40456d509a0
--- /dev/null
+++ b/fs/ocfs2/aops.h
@@ -0,0 +1,41 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2002, 2004, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_AOPS_H
+#define OCFS2_AOPS_H
+
+int ocfs2_prepare_write(struct file *file, struct page *page,
+ unsigned from, unsigned to);
+
+struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode,
+ struct page *page,
+ unsigned from,
+ unsigned to);
+
+/* all ocfs2_dio_end_io()'s fault */
+#define ocfs2_iocb_is_rw_locked(iocb) \
+ test_bit(0, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_set_rw_locked(iocb) \
+ set_bit(0, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_clear_rw_locked(iocb) \
+ clear_bit(0, (unsigned long *)&iocb->private)
+
+#endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c
new file mode 100644
index 000000000000..d424041b38e9
--- /dev/null
+++ b/fs/ocfs2/buffer_head_io.c
@@ -0,0 +1,232 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * io.c
+ *
+ * Buffer cache handling
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "inode.h"
+#include "journal.h"
+#include "uptodate.h"
+
+#include "buffer_head_io.h"
+
+int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh,
+ struct inode *inode)
+{
+ int ret = 0;
+
+ mlog_entry("(bh->b_blocknr = %llu, inode=%p)\n",
+ (unsigned long long)bh->b_blocknr, inode);
+
+ BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO);
+ BUG_ON(buffer_jbd(bh));
+
+ /* No need to check for a soft readonly file system here. non
+ * journalled writes are only ever done on system files which
+ * can get modified during recovery even if read-only. */
+ if (ocfs2_is_hard_readonly(osb)) {
+ ret = -EROFS;
+ goto out;
+ }
+
+ down(&OCFS2_I(inode)->ip_io_sem);
+
+ lock_buffer(bh);
+ set_buffer_uptodate(bh);
+
+ /* remove from dirty list before I/O. */
+ clear_buffer_dirty(bh);
+
+ get_bh(bh); /* for end_buffer_write_sync() */
+ bh->b_end_io = end_buffer_write_sync;
+ submit_bh(WRITE, bh);
+
+ wait_on_buffer(bh);
+
+ if (buffer_uptodate(bh)) {
+ ocfs2_set_buffer_uptodate(inode, bh);
+ } else {
+ /* We don't need to remove the clustered uptodate
+ * information for this bh as it's not marked locally
+ * uptodate. */
+ ret = -EIO;
+ brelse(bh);
+ }
+
+ up(&OCFS2_I(inode)->ip_io_sem);
+out:
+ mlog_exit(ret);
+ return ret;
+}
+
+int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr,
+ struct buffer_head *bhs[], int flags,
+ struct inode *inode)
+{
+ int status = 0;
+ struct super_block *sb;
+ int i, ignore_cache = 0;
+ struct buffer_head *bh;
+
+ mlog_entry("(block=(%"MLFu64"), nr=(%d), flags=%d, inode=%p)\n",
+ block, nr, flags, inode);
+
+ if (osb == NULL || osb->sb == NULL || bhs == NULL) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (nr < 0) {
+ mlog(ML_ERROR, "asked to read %d blocks!\n", nr);
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (nr == 0) {
+ mlog(ML_BH_IO, "No buffers will be read!\n");
+ status = 0;
+ goto bail;
+ }
+
+ sb = osb->sb;
+
+ if (flags & OCFS2_BH_CACHED && !inode)
+ flags &= ~OCFS2_BH_CACHED;
+
+ if (inode)
+ down(&OCFS2_I(inode)->ip_io_sem);
+ for (i = 0 ; i < nr ; i++) {
+ if (bhs[i] == NULL) {
+ bhs[i] = sb_getblk(sb, block++);
+ if (bhs[i] == NULL) {
+ if (inode)
+ up(&OCFS2_I(inode)->ip_io_sem);
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ bh = bhs[i];
+ ignore_cache = 0;
+
+ if (flags & OCFS2_BH_CACHED &&
+ !ocfs2_buffer_uptodate(inode, bh)) {
+ mlog(ML_UPTODATE,
+ "bh (%llu), inode %"MLFu64" not uptodate\n",
+ (unsigned long long)bh->b_blocknr,
+ OCFS2_I(inode)->ip_blkno);
+ ignore_cache = 1;
+ }
+
+ /* XXX: Can we ever get this and *not* have the cached
+ * flag set? */
+ if (buffer_jbd(bh)) {
+ if (!(flags & OCFS2_BH_CACHED) || ignore_cache)
+ mlog(ML_BH_IO, "trying to sync read a jbd "
+ "managed bh (blocknr = %llu)\n",
+ (unsigned long long)bh->b_blocknr);
+ continue;
+ }
+
+ if (!(flags & OCFS2_BH_CACHED) || ignore_cache) {
+ if (buffer_dirty(bh)) {
+ /* This should probably be a BUG, or
+ * at least return an error. */
+ mlog(ML_BH_IO, "asking me to sync read a dirty "
+ "buffer! (blocknr = %llu)\n",
+ (unsigned long long)bh->b_blocknr);
+ continue;
+ }
+
+ lock_buffer(bh);
+ if (buffer_jbd(bh)) {
+#ifdef CATCH_BH_JBD_RACES
+ mlog(ML_ERROR, "block %llu had the JBD bit set "
+ "while I was in lock_buffer!",
+ (unsigned long long)bh->b_blocknr);
+ BUG();
+#else
+ unlock_buffer(bh);
+ continue;
+#endif
+ }
+ clear_buffer_uptodate(bh);
+ get_bh(bh); /* for end_buffer_read_sync() */
+ bh->b_end_io = end_buffer_read_sync;
+ if (flags & OCFS2_BH_READAHEAD)
+ submit_bh(READA, bh);
+ else
+ submit_bh(READ, bh);
+ continue;
+ }
+ }
+
+ status = 0;
+
+ for (i = (nr - 1); i >= 0; i--) {
+ bh = bhs[i];
+
+ /* We know this can't have changed as we hold the
+ * inode sem. Avoid doing any work on the bh if the
+ * journal has it. */
+ if (!buffer_jbd(bh))
+ wait_on_buffer(bh);
+
+ if (!buffer_uptodate(bh)) {
+ /* Status won't be cleared from here on out,
+ * so we can safely record this and loop back
+ * to cleanup the other buffers. Don't need to
+ * remove the clustered uptodate information
+ * for this bh as it's not marked locally
+ * uptodate. */
+ status = -EIO;
+ brelse(bh);
+ bhs[i] = NULL;
+ continue;
+ }
+
+ if (inode)
+ ocfs2_set_buffer_uptodate(inode, bh);
+ }
+ if (inode)
+ up(&OCFS2_I(inode)->ip_io_sem);
+
+ mlog(ML_BH_IO, "block=(%"MLFu64"), nr=(%d), cached=%s\n", block, nr,
+ (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes");
+
+bail:
+
+ mlog_exit(status);
+ return status;
+}
diff --git a/fs/ocfs2/buffer_head_io.h b/fs/ocfs2/buffer_head_io.h
new file mode 100644
index 000000000000..6ecb90937b68
--- /dev/null
+++ b/fs/ocfs2/buffer_head_io.h
@@ -0,0 +1,73 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_buffer_head.h
+ *
+ * Buffer cache handling functions defined
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_BUFFER_HEAD_IO_H
+#define OCFS2_BUFFER_HEAD_IO_H
+
+#include <linux/buffer_head.h>
+
+void ocfs2_end_buffer_io_sync(struct buffer_head *bh,
+ int uptodate);
+
+static inline int ocfs2_read_block(struct ocfs2_super *osb,
+ u64 off,
+ struct buffer_head **bh,
+ int flags,
+ struct inode *inode);
+
+int ocfs2_write_block(struct ocfs2_super *osb,
+ struct buffer_head *bh,
+ struct inode *inode);
+int ocfs2_read_blocks(struct ocfs2_super *osb,
+ u64 block,
+ int nr,
+ struct buffer_head *bhs[],
+ int flags,
+ struct inode *inode);
+
+
+#define OCFS2_BH_CACHED 1
+#define OCFS2_BH_READAHEAD 8 /* use this to pass READA down to submit_bh */
+
+static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off,
+ struct buffer_head **bh, int flags,
+ struct inode *inode)
+{
+ int status = 0;
+
+ if (bh == NULL) {
+ printk("ocfs2: bh == NULL\n");
+ status = -EINVAL;
+ goto bail;
+ }
+
+ status = ocfs2_read_blocks(osb, off, 1, bh,
+ flags, inode);
+
+bail:
+ return status;
+}
+
+#endif /* OCFS2_BUFFER_HEAD_IO_H */
diff --git a/fs/ocfs2/cluster/Makefile b/fs/ocfs2/cluster/Makefile
new file mode 100644
index 000000000000..cdd162f13650
--- /dev/null
+++ b/fs/ocfs2/cluster/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_OCFS2_FS) += ocfs2_nodemanager.o
+
+ocfs2_nodemanager-objs := heartbeat.o masklog.o sys.o nodemanager.o \
+ quorum.o tcp.o ver.o
diff --git a/fs/ocfs2/cluster/endian.h b/fs/ocfs2/cluster/endian.h
new file mode 100644
index 000000000000..2df9082f4e35
--- /dev/null
+++ b/fs/ocfs2/cluster/endian.h
@@ -0,0 +1,30 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_CLUSTER_ENDIAN_H
+#define OCFS2_CLUSTER_ENDIAN_H
+
+static inline void be32_add_cpu(__be32 *var, u32 val)
+{
+ *var = cpu_to_be32(be32_to_cpu(*var) + val);
+}
+
+#endif /* OCFS2_CLUSTER_ENDIAN_H */
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
new file mode 100644
index 000000000000..7307ba528913
--- /dev/null
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -0,0 +1,1797 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2004, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/file.h>
+#include <linux/kthread.h>
+#include <linux/configfs.h>
+#include <linux/random.h>
+#include <linux/crc32.h>
+#include <linux/time.h>
+
+#include "heartbeat.h"
+#include "tcp.h"
+#include "nodemanager.h"
+#include "quorum.h"
+
+#include "masklog.h"
+
+
+/*
+ * The first heartbeat pass had one global thread that would serialize all hb
+ * callback calls. This global serializing sem should only be removed once
+ * we've made sure that all callees can deal with being called concurrently
+ * from multiple hb region threads.
+ */
+static DECLARE_RWSEM(o2hb_callback_sem);
+
+/*
+ * multiple hb threads are watching multiple regions. A node is live
+ * whenever any of the threads sees activity from the node in its region.
+ */
+static spinlock_t o2hb_live_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head o2hb_live_slots[O2NM_MAX_NODES];
+static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+static LIST_HEAD(o2hb_node_events);
+static DECLARE_WAIT_QUEUE_HEAD(o2hb_steady_queue);
+
+static LIST_HEAD(o2hb_all_regions);
+
+static struct o2hb_callback {
+ struct list_head list;
+} o2hb_callbacks[O2HB_NUM_CB];
+
+static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type);
+
+#define O2HB_DEFAULT_BLOCK_BITS 9
+
+unsigned int o2hb_dead_threshold = O2HB_DEFAULT_DEAD_THRESHOLD;
+
+/* Only sets a new threshold if there are no active regions.
+ *
+ * No locking or otherwise interesting code is required for reading
+ * o2hb_dead_threshold as it can't change once regions are active and
+ * it's not interesting to anyone until then anyway. */
+static void o2hb_dead_threshold_set(unsigned int threshold)
+{
+ if (threshold > O2HB_MIN_DEAD_THRESHOLD) {
+ spin_lock(&o2hb_live_lock);
+ if (list_empty(&o2hb_all_regions))
+ o2hb_dead_threshold = threshold;
+ spin_unlock(&o2hb_live_lock);
+ }
+}
+
+struct o2hb_node_event {
+ struct list_head hn_item;
+ enum o2hb_callback_type hn_event_type;
+ struct o2nm_node *hn_node;
+ int hn_node_num;
+};
+
+struct o2hb_disk_slot {
+ struct o2hb_disk_heartbeat_block *ds_raw_block;
+ u8 ds_node_num;
+ u64 ds_last_time;
+ u64 ds_last_generation;
+ u16 ds_equal_samples;
+ u16 ds_changed_samples;
+ struct list_head ds_live_item;
+};
+
+/* each thread owns a region.. when we're asked to tear down the region
+ * we ask the thread to stop, who cleans up the region */
+struct o2hb_region {
+ struct config_item hr_item;
+
+ struct list_head hr_all_item;
+ unsigned hr_unclean_stop:1;
+
+ /* protected by the hr_callback_sem */
+ struct task_struct *hr_task;
+
+ unsigned int hr_blocks;
+ unsigned long long hr_start_block;
+
+ unsigned int hr_block_bits;
+ unsigned int hr_block_bytes;
+
+ unsigned int hr_slots_per_page;
+ unsigned int hr_num_pages;
+
+ struct page **hr_slot_data;
+ struct block_device *hr_bdev;
+ struct o2hb_disk_slot *hr_slots;
+
+ /* let the person setting up hb wait for it to return until it
+ * has reached a 'steady' state. This will be fixed when we have
+ * a more complete api that doesn't lead to this sort of fragility. */
+ atomic_t hr_steady_iterations;
+
+ char hr_dev_name[BDEVNAME_SIZE];
+
+ unsigned int hr_timeout_ms;
+
+ /* randomized as the region goes up and down so that a node
+ * recognizes a node going up and down in one iteration */
+ u64 hr_generation;
+
+ struct work_struct hr_write_timeout_work;
+ unsigned long hr_last_timeout_start;
+
+ /* Used during o2hb_check_slot to hold a copy of the block
+ * being checked because we temporarily have to zero out the
+ * crc field. */
+ struct o2hb_disk_heartbeat_block *hr_tmp_block;
+};
+
+struct o2hb_bio_wait_ctxt {
+ atomic_t wc_num_reqs;
+ struct completion wc_io_complete;
+};
+
+static void o2hb_write_timeout(void *arg)
+{
+ struct o2hb_region *reg = arg;
+
+ mlog(ML_ERROR, "Heartbeat write timeout to device %s after %u "
+ "milliseconds\n", reg->hr_dev_name,
+ jiffies_to_msecs(jiffies - reg->hr_last_timeout_start));
+ o2quo_disk_timeout();
+}
+
+static void o2hb_arm_write_timeout(struct o2hb_region *reg)
+{
+ mlog(0, "Queue write timeout for %u ms\n", O2HB_MAX_WRITE_TIMEOUT_MS);
+
+ cancel_delayed_work(&reg->hr_write_timeout_work);
+ reg->hr_last_timeout_start = jiffies;
+ schedule_delayed_work(&reg->hr_write_timeout_work,
+ msecs_to_jiffies(O2HB_MAX_WRITE_TIMEOUT_MS));
+}
+
+static void o2hb_disarm_write_timeout(struct o2hb_region *reg)
+{
+ cancel_delayed_work(&reg->hr_write_timeout_work);
+ flush_scheduled_work();
+}
+
+static inline void o2hb_bio_wait_init(struct o2hb_bio_wait_ctxt *wc,
+ unsigned int num_ios)
+{
+ atomic_set(&wc->wc_num_reqs, num_ios);
+ init_completion(&wc->wc_io_complete);
+}
+
+/* Used in error paths too */
+static inline void o2hb_bio_wait_dec(struct o2hb_bio_wait_ctxt *wc,
+ unsigned int num)
+{
+ /* sadly atomic_sub_and_test() isn't available on all platforms. The
+ * good news is that the fast path only completes one at a time */
+ while(num--) {
+ if (atomic_dec_and_test(&wc->wc_num_reqs)) {
+ BUG_ON(num > 0);
+ complete(&wc->wc_io_complete);
+ }
+ }
+}
+
+static void o2hb_wait_on_io(struct o2hb_region *reg,
+ struct o2hb_bio_wait_ctxt *wc)
+{
+ struct address_space *mapping = reg->hr_bdev->bd_inode->i_mapping;
+
+ blk_run_address_space(mapping);
+
+ wait_for_completion(&wc->wc_io_complete);
+}
+
+static int o2hb_bio_end_io(struct bio *bio,
+ unsigned int bytes_done,
+ int error)
+{
+ struct o2hb_bio_wait_ctxt *wc = bio->bi_private;
+
+ if (error)
+ mlog(ML_ERROR, "IO Error %d\n", error);
+
+ if (bio->bi_size)
+ return 1;
+
+ o2hb_bio_wait_dec(wc, 1);
+ return 0;
+}
+
+/* Setup a Bio to cover I/O against num_slots slots starting at
+ * start_slot. */
+static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg,
+ struct o2hb_bio_wait_ctxt *wc,
+ unsigned int start_slot,
+ unsigned int num_slots)
+{
+ int i, nr_vecs, len, first_page, last_page;
+ unsigned int vec_len, vec_start;
+ unsigned int bits = reg->hr_block_bits;
+ unsigned int spp = reg->hr_slots_per_page;
+ struct bio *bio;
+ struct page *page;
+
+ nr_vecs = (num_slots + spp - 1) / spp;
+
+ /* Testing has shown this allocation to take long enough under
+ * GFP_KERNEL that the local node can get fenced. It would be
+ * nicest if we could pre-allocate these bios and avoid this
+ * all together. */
+ bio = bio_alloc(GFP_ATOMIC, nr_vecs);
+ if (!bio) {
+ mlog(ML_ERROR, "Could not alloc slots BIO!\n");
+ bio = ERR_PTR(-ENOMEM);
+ goto bail;
+ }
+
+ /* Must put everything in 512 byte sectors for the bio... */
+ bio->bi_sector = (reg->hr_start_block + start_slot) << (bits - 9);
+ bio->bi_bdev = reg->hr_bdev;
+ bio->bi_private = wc;
+ bio->bi_end_io = o2hb_bio_end_io;
+
+ first_page = start_slot / spp;
+ last_page = first_page + nr_vecs;
+ vec_start = (start_slot << bits) % PAGE_CACHE_SIZE;
+ for(i = first_page; i < last_page; i++) {
+ page = reg->hr_slot_data[i];
+
+ vec_len = PAGE_CACHE_SIZE;
+ /* last page might be short */
+ if (((i + 1) * spp) > (start_slot + num_slots))
+ vec_len = ((num_slots + start_slot) % spp) << bits;
+ vec_len -= vec_start;
+
+ mlog(ML_HB_BIO, "page %d, vec_len = %u, vec_start = %u\n",
+ i, vec_len, vec_start);
+
+ len = bio_add_page(bio, page, vec_len, vec_start);
+ if (len != vec_len) {
+ bio_put(bio);
+ bio = ERR_PTR(-EIO);
+
+ mlog(ML_ERROR, "Error adding page to bio i = %d, "
+ "vec_len = %u, len = %d\n, start = %u\n",
+ i, vec_len, len, vec_start);
+ goto bail;
+ }
+
+ vec_start = 0;
+ }
+
+bail:
+ return bio;
+}
+
+/*
+ * Compute the maximum number of sectors the bdev can handle in one bio,
+ * as a power of two.
+ *
+ * Stolen from oracleasm, thanks Joel!
+ */
+static int compute_max_sectors(struct block_device *bdev)
+{
+ int max_pages, max_sectors, pow_two_sectors;
+
+ struct request_queue *q;
+
+ q = bdev_get_queue(bdev);
+ max_pages = q->max_sectors >> (PAGE_SHIFT - 9);
+ if (max_pages > BIO_MAX_PAGES)
+ max_pages = BIO_MAX_PAGES;
+ if (max_pages > q->max_phys_segments)
+ max_pages = q->max_phys_segments;
+ if (max_pages > q->max_hw_segments)
+ max_pages = q->max_hw_segments;
+ max_pages--; /* Handle I/Os that straddle a page */
+
+ max_sectors = max_pages << (PAGE_SHIFT - 9);
+
+ /* Why is fls() 1-based???? */
+ pow_two_sectors = 1 << (fls(max_sectors) - 1);
+
+ return pow_two_sectors;
+}
+
+static inline void o2hb_compute_request_limits(struct o2hb_region *reg,
+ unsigned int num_slots,
+ unsigned int *num_bios,
+ unsigned int *slots_per_bio)
+{
+ unsigned int max_sectors, io_sectors;
+
+ max_sectors = compute_max_sectors(reg->hr_bdev);
+
+ io_sectors = num_slots << (reg->hr_block_bits - 9);
+
+ *num_bios = (io_sectors + max_sectors - 1) / max_sectors;
+ *slots_per_bio = max_sectors >> (reg->hr_block_bits - 9);
+
+ mlog(ML_HB_BIO, "My io size is %u sectors for %u slots. This "
+ "device can handle %u sectors of I/O\n", io_sectors, num_slots,
+ max_sectors);
+ mlog(ML_HB_BIO, "Will need %u bios holding %u slots each\n",
+ *num_bios, *slots_per_bio);
+}
+
+static int o2hb_read_slots(struct o2hb_region *reg,
+ unsigned int max_slots)
+{
+ unsigned int num_bios, slots_per_bio, start_slot, num_slots;
+ int i, status;
+ struct o2hb_bio_wait_ctxt wc;
+ struct bio **bios;
+ struct bio *bio;
+
+ o2hb_compute_request_limits(reg, max_slots, &num_bios, &slots_per_bio);
+
+ bios = kcalloc(num_bios, sizeof(struct bio *), GFP_KERNEL);
+ if (!bios) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ return status;
+ }
+
+ o2hb_bio_wait_init(&wc, num_bios);
+
+ num_slots = slots_per_bio;
+ for(i = 0; i < num_bios; i++) {
+ start_slot = i * slots_per_bio;
+
+ /* adjust num_slots at last bio */
+ if (max_slots < (start_slot + num_slots))
+ num_slots = max_slots - start_slot;
+
+ bio = o2hb_setup_one_bio(reg, &wc, start_slot, num_slots);
+ if (IS_ERR(bio)) {
+ o2hb_bio_wait_dec(&wc, num_bios - i);
+
+ status = PTR_ERR(bio);
+ mlog_errno(status);
+ goto bail_and_wait;
+ }
+ bios[i] = bio;
+
+ submit_bio(READ, bio);
+ }
+
+ status = 0;
+
+bail_and_wait:
+ o2hb_wait_on_io(reg, &wc);
+
+ if (bios) {
+ for(i = 0; i < num_bios; i++)
+ if (bios[i])
+ bio_put(bios[i]);
+ kfree(bios);
+ }
+
+ return status;
+}
+
+static int o2hb_issue_node_write(struct o2hb_region *reg,
+ struct bio **write_bio,
+ struct o2hb_bio_wait_ctxt *write_wc)
+{
+ int status;
+ unsigned int slot;
+ struct bio *bio;
+
+ o2hb_bio_wait_init(write_wc, 1);
+
+ slot = o2nm_this_node();
+
+ bio = o2hb_setup_one_bio(reg, write_wc, slot, 1);
+ if (IS_ERR(bio)) {
+ status = PTR_ERR(bio);
+ mlog_errno(status);
+ goto bail;
+ }
+
+ submit_bio(WRITE, bio);
+
+ *write_bio = bio;
+ status = 0;
+bail:
+ return status;
+}
+
+static u32 o2hb_compute_block_crc_le(struct o2hb_region *reg,
+ struct o2hb_disk_heartbeat_block *hb_block)
+{
+ __le32 old_cksum;
+ u32 ret;
+
+ /* We want to compute the block crc with a 0 value in the
+ * hb_cksum field. Save it off here and replace after the
+ * crc. */
+ old_cksum = hb_block->hb_cksum;
+ hb_block->hb_cksum = 0;
+
+ ret = crc32_le(0, (unsigned char *) hb_block, reg->hr_block_bytes);
+
+ hb_block->hb_cksum = old_cksum;
+
+ return ret;
+}
+
+static void o2hb_dump_slot(struct o2hb_disk_heartbeat_block *hb_block)
+{
+ mlog(ML_ERROR, "Dump slot information: seq = 0x%"MLFx64", node = %u, "
+ "cksum = 0x%x, generation 0x%"MLFx64"\n",
+ le64_to_cpu(hb_block->hb_seq), hb_block->hb_node,
+ le32_to_cpu(hb_block->hb_cksum),
+ le64_to_cpu(hb_block->hb_generation));
+}
+
+static int o2hb_verify_crc(struct o2hb_region *reg,
+ struct o2hb_disk_heartbeat_block *hb_block)
+{
+ u32 read, computed;
+
+ read = le32_to_cpu(hb_block->hb_cksum);
+ computed = o2hb_compute_block_crc_le(reg, hb_block);
+
+ return read == computed;
+}
+
+/* We want to make sure that nobody is heartbeating on top of us --
+ * this will help detect an invalid configuration. */
+static int o2hb_check_last_timestamp(struct o2hb_region *reg)
+{
+ int node_num, ret;
+ struct o2hb_disk_slot *slot;
+ struct o2hb_disk_heartbeat_block *hb_block;
+
+ node_num = o2nm_this_node();
+
+ ret = 1;
+ slot = &reg->hr_slots[node_num];
+ /* Don't check on our 1st timestamp */
+ if (slot->ds_last_time) {
+ hb_block = slot->ds_raw_block;
+
+ if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time)
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static inline void o2hb_prepare_block(struct o2hb_region *reg,
+ u64 generation)
+{
+ int node_num;
+ u64 cputime;
+ struct o2hb_disk_slot *slot;
+ struct o2hb_disk_heartbeat_block *hb_block;
+
+ node_num = o2nm_this_node();
+ slot = &reg->hr_slots[node_num];
+
+ hb_block = (struct o2hb_disk_heartbeat_block *)slot->ds_raw_block;
+ memset(hb_block, 0, reg->hr_block_bytes);
+ /* TODO: time stuff */
+ cputime = CURRENT_TIME.tv_sec;
+ if (!cputime)
+ cputime = 1;
+
+ hb_block->hb_seq = cpu_to_le64(cputime);
+ hb_block->hb_node = node_num;
+ hb_block->hb_generation = cpu_to_le64(generation);
+
+ /* This step must always happen last! */
+ hb_block->hb_cksum = cpu_to_le32(o2hb_compute_block_crc_le(reg,
+ hb_block));
+
+ mlog(ML_HB_BIO, "our node generation = 0x%"MLFx64", cksum = 0x%x\n",
+ cpu_to_le64(generation), le32_to_cpu(hb_block->hb_cksum));
+}
+
+static void o2hb_fire_callbacks(struct o2hb_callback *hbcall,
+ struct o2nm_node *node,
+ int idx)
+{
+ struct list_head *iter;
+ struct o2hb_callback_func *f;
+
+ list_for_each(iter, &hbcall->list) {
+ f = list_entry(iter, struct o2hb_callback_func, hc_item);
+ mlog(ML_HEARTBEAT, "calling funcs %p\n", f);
+ (f->hc_func)(node, idx, f->hc_data);
+ }
+}
+
+/* Will run the list in order until we process the passed event */
+static void o2hb_run_event_list(struct o2hb_node_event *queued_event)
+{
+ int empty;
+ struct o2hb_callback *hbcall;
+ struct o2hb_node_event *event;
+
+ spin_lock(&o2hb_live_lock);
+ empty = list_empty(&queued_event->hn_item);
+ spin_unlock(&o2hb_live_lock);
+ if (empty)
+ return;
+
+ /* Holding callback sem assures we don't alter the callback
+ * lists when doing this, and serializes ourselves with other
+ * processes wanting callbacks. */
+ down_write(&o2hb_callback_sem);
+
+ spin_lock(&o2hb_live_lock);
+ while (!list_empty(&o2hb_node_events)
+ && !list_empty(&queued_event->hn_item)) {
+ event = list_entry(o2hb_node_events.next,
+ struct o2hb_node_event,
+ hn_item);
+ list_del_init(&event->hn_item);
+ spin_unlock(&o2hb_live_lock);
+
+ mlog(ML_HEARTBEAT, "Node %s event for %d\n",
+ event->hn_event_type == O2HB_NODE_UP_CB ? "UP" : "DOWN",
+ event->hn_node_num);
+
+ hbcall = hbcall_from_type(event->hn_event_type);
+
+ /* We should *never* have gotten on to the list with a
+ * bad type... This isn't something that we should try
+ * to recover from. */
+ BUG_ON(IS_ERR(hbcall));
+
+ o2hb_fire_callbacks(hbcall, event->hn_node, event->hn_node_num);
+
+ spin_lock(&o2hb_live_lock);
+ }
+ spin_unlock(&o2hb_live_lock);
+
+ up_write(&o2hb_callback_sem);
+}
+
+static void o2hb_queue_node_event(struct o2hb_node_event *event,
+ enum o2hb_callback_type type,
+ struct o2nm_node *node,
+ int node_num)
+{
+ assert_spin_locked(&o2hb_live_lock);
+
+ event->hn_event_type = type;
+ event->hn_node = node;
+ event->hn_node_num = node_num;
+
+ mlog(ML_HEARTBEAT, "Queue node %s event for node %d\n",
+ type == O2HB_NODE_UP_CB ? "UP" : "DOWN", node_num);
+
+ list_add_tail(&event->hn_item, &o2hb_node_events);
+}
+
+static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot)
+{
+ struct o2hb_node_event event =
+ { .hn_item = LIST_HEAD_INIT(event.hn_item), };
+ struct o2nm_node *node;
+
+ node = o2nm_get_node_by_num(slot->ds_node_num);
+ if (!node)
+ return;
+
+ spin_lock(&o2hb_live_lock);
+ if (!list_empty(&slot->ds_live_item)) {
+ mlog(ML_HEARTBEAT, "Shutdown, node %d leaves region\n",
+ slot->ds_node_num);
+
+ list_del_init(&slot->ds_live_item);
+
+ if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+ clear_bit(slot->ds_node_num, o2hb_live_node_bitmap);
+
+ o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node,
+ slot->ds_node_num);
+ }
+ }
+ spin_unlock(&o2hb_live_lock);
+
+ o2hb_run_event_list(&event);
+
+ o2nm_node_put(node);
+}
+
+static int o2hb_check_slot(struct o2hb_region *reg,
+ struct o2hb_disk_slot *slot)
+{
+ int changed = 0, gen_changed = 0;
+ struct o2hb_node_event event =
+ { .hn_item = LIST_HEAD_INIT(event.hn_item), };
+ struct o2nm_node *node;
+ struct o2hb_disk_heartbeat_block *hb_block = reg->hr_tmp_block;
+ u64 cputime;
+
+ memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes);
+
+ /* Is this correct? Do we assume that the node doesn't exist
+ * if we're not configured for him? */
+ node = o2nm_get_node_by_num(slot->ds_node_num);
+ if (!node)
+ return 0;
+
+ if (!o2hb_verify_crc(reg, hb_block)) {
+ /* all paths from here will drop o2hb_live_lock for
+ * us. */
+ spin_lock(&o2hb_live_lock);
+
+ /* Don't print an error on the console in this case -
+ * a freshly formatted heartbeat area will not have a
+ * crc set on it. */
+ if (list_empty(&slot->ds_live_item))
+ goto out;
+
+ /* The node is live but pushed out a bad crc. We
+ * consider it a transient miss but don't populate any
+ * other values as they may be junk. */
+ mlog(ML_ERROR, "Node %d has written a bad crc to %s\n",
+ slot->ds_node_num, reg->hr_dev_name);
+ o2hb_dump_slot(hb_block);
+
+ slot->ds_equal_samples++;
+ goto fire_callbacks;
+ }
+
+ /* we don't care if these wrap.. the state transitions below
+ * clear at the right places */
+ cputime = le64_to_cpu(hb_block->hb_seq);
+ if (slot->ds_last_time != cputime)
+ slot->ds_changed_samples++;
+ else
+ slot->ds_equal_samples++;
+ slot->ds_last_time = cputime;
+
+ /* The node changed heartbeat generations. We assume this to
+ * mean it dropped off but came back before we timed out. We
+ * want to consider it down for the time being but don't want
+ * to lose any changed_samples state we might build up to
+ * considering it live again. */
+ if (slot->ds_last_generation != le64_to_cpu(hb_block->hb_generation)) {
+ gen_changed = 1;
+ slot->ds_equal_samples = 0;
+ mlog(ML_HEARTBEAT, "Node %d changed generation (0x%"MLFx64" "
+ "to 0x%"MLFx64")\n", slot->ds_node_num,
+ slot->ds_last_generation,
+ le64_to_cpu(hb_block->hb_generation));
+ }
+
+ slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation);
+
+ mlog(ML_HEARTBEAT, "Slot %d gen 0x%"MLFx64" cksum 0x%x "
+ "seq %"MLFu64" last %"MLFu64" changed %u equal %u\n",
+ slot->ds_node_num, slot->ds_last_generation,
+ le32_to_cpu(hb_block->hb_cksum), le64_to_cpu(hb_block->hb_seq),
+ slot->ds_last_time, slot->ds_changed_samples,
+ slot->ds_equal_samples);
+
+ spin_lock(&o2hb_live_lock);
+
+fire_callbacks:
+ /* dead nodes only come to life after some number of
+ * changes at any time during their dead time */
+ if (list_empty(&slot->ds_live_item) &&
+ slot->ds_changed_samples >= O2HB_LIVE_THRESHOLD) {
+ mlog(ML_HEARTBEAT, "Node %d (id 0x%"MLFx64") joined my "
+ "region\n", slot->ds_node_num, slot->ds_last_generation);
+
+ /* first on the list generates a callback */
+ if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+ set_bit(slot->ds_node_num, o2hb_live_node_bitmap);
+
+ o2hb_queue_node_event(&event, O2HB_NODE_UP_CB, node,
+ slot->ds_node_num);
+
+ changed = 1;
+ }
+
+ list_add_tail(&slot->ds_live_item,
+ &o2hb_live_slots[slot->ds_node_num]);
+
+ slot->ds_equal_samples = 0;
+ goto out;
+ }
+
+ /* if the list is dead, we're done.. */
+ if (list_empty(&slot->ds_live_item))
+ goto out;
+
+ /* live nodes only go dead after enough consequtive missed
+ * samples.. reset the missed counter whenever we see
+ * activity */
+ if (slot->ds_equal_samples >= o2hb_dead_threshold || gen_changed) {
+ mlog(ML_HEARTBEAT, "Node %d left my region\n",
+ slot->ds_node_num);
+
+ /* last off the live_slot generates a callback */
+ list_del_init(&slot->ds_live_item);
+ if (list_empty(&o2hb_live_slots[slot->ds_node_num])) {
+ clear_bit(slot->ds_node_num, o2hb_live_node_bitmap);
+
+ o2hb_queue_node_event(&event, O2HB_NODE_DOWN_CB, node,
+ slot->ds_node_num);
+
+ changed = 1;
+ }
+
+ /* We don't clear this because the node is still
+ * actually writing new blocks. */
+ if (!gen_changed)
+ slot->ds_changed_samples = 0;
+ goto out;
+ }
+ if (slot->ds_changed_samples) {
+ slot->ds_changed_samples = 0;
+ slot->ds_equal_samples = 0;
+ }
+out:
+ spin_unlock(&o2hb_live_lock);
+
+ o2hb_run_event_list(&event);
+
+ o2nm_node_put(node);
+ return changed;
+}
+
+/* This could be faster if we just implmented a find_last_bit, but I
+ * don't think the circumstances warrant it. */
+static int o2hb_highest_node(unsigned long *nodes,
+ int numbits)
+{
+ int highest, node;
+
+ highest = numbits;
+ node = -1;
+ while ((node = find_next_bit(nodes, numbits, node + 1)) != -1) {
+ if (node >= numbits)
+ break;
+
+ highest = node;
+ }
+
+ return highest;
+}
+
+static void o2hb_do_disk_heartbeat(struct o2hb_region *reg)
+{
+ int i, ret, highest_node, change = 0;
+ unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ struct bio *write_bio;
+ struct o2hb_bio_wait_ctxt write_wc;
+
+ if (o2nm_configured_node_map(configured_nodes, sizeof(configured_nodes)))
+ return;
+
+ highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
+ if (highest_node >= O2NM_MAX_NODES) {
+ mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
+ return;
+ }
+
+ /* No sense in reading the slots of nodes that don't exist
+ * yet. Of course, if the node definitions have holes in them
+ * then we're reading an empty slot anyway... Consider this
+ * best-effort. */
+ ret = o2hb_read_slots(reg, highest_node + 1);
+ if (ret < 0) {
+ mlog_errno(ret);
+ return;
+ }
+
+ /* With an up to date view of the slots, we can check that no
+ * other node has been improperly configured to heartbeat in
+ * our slot. */
+ if (!o2hb_check_last_timestamp(reg))
+ mlog(ML_ERROR, "Device \"%s\": another node is heartbeating "
+ "in our slot!\n", reg->hr_dev_name);
+
+ /* fill in the proper info for our next heartbeat */
+ o2hb_prepare_block(reg, reg->hr_generation);
+
+ /* And fire off the write. Note that we don't wait on this I/O
+ * until later. */
+ ret = o2hb_issue_node_write(reg, &write_bio, &write_wc);
+ if (ret < 0) {
+ mlog_errno(ret);
+ return;
+ }
+
+ i = -1;
+ while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
+
+ change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
+ }
+
+ /*
+ * We have to be sure we've advertised ourselves on disk
+ * before we can go to steady state. This ensures that
+ * people we find in our steady state have seen us.
+ */
+ o2hb_wait_on_io(reg, &write_wc);
+ bio_put(write_bio);
+ o2hb_arm_write_timeout(reg);
+
+ /* let the person who launched us know when things are steady */
+ if (!change && (atomic_read(&reg->hr_steady_iterations) != 0)) {
+ if (atomic_dec_and_test(&reg->hr_steady_iterations))
+ wake_up(&o2hb_steady_queue);
+ }
+}
+
+/* Subtract b from a, storing the result in a. a *must* have a larger
+ * value than b. */
+static void o2hb_tv_subtract(struct timeval *a,
+ struct timeval *b)
+{
+ /* just return 0 when a is after b */
+ if (a->tv_sec < b->tv_sec ||
+ (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) {
+ a->tv_sec = 0;
+ a->tv_usec = 0;
+ return;
+ }
+
+ a->tv_sec -= b->tv_sec;
+ a->tv_usec -= b->tv_usec;
+ while ( a->tv_usec < 0 ) {
+ a->tv_sec--;
+ a->tv_usec += 1000000;
+ }
+}
+
+static unsigned int o2hb_elapsed_msecs(struct timeval *start,
+ struct timeval *end)
+{
+ struct timeval res = *end;
+
+ o2hb_tv_subtract(&res, start);
+
+ return res.tv_sec * 1000 + res.tv_usec / 1000;
+}
+
+/*
+ * we ride the region ref that the region dir holds. before the region
+ * dir is removed and drops it ref it will wait to tear down this
+ * thread.
+ */
+static int o2hb_thread(void *data)
+{
+ int i, ret;
+ struct o2hb_region *reg = data;
+ struct bio *write_bio;
+ struct o2hb_bio_wait_ctxt write_wc;
+ struct timeval before_hb, after_hb;
+ unsigned int elapsed_msec;
+
+ mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread running\n");
+
+ set_user_nice(current, -20);
+
+ while (!kthread_should_stop() && !reg->hr_unclean_stop) {
+ /* We track the time spent inside
+ * o2hb_do_disk_heartbeat so that we avoid more then
+ * hr_timeout_ms between disk writes. On busy systems
+ * this should result in a heartbeat which is less
+ * likely to time itself out. */
+ do_gettimeofday(&before_hb);
+
+ o2hb_do_disk_heartbeat(reg);
+
+ do_gettimeofday(&after_hb);
+ elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
+
+ mlog(0, "start = %lu.%lu, end = %lu.%lu, msec = %u\n",
+ before_hb.tv_sec, before_hb.tv_usec,
+ after_hb.tv_sec, after_hb.tv_usec, elapsed_msec);
+
+ if (elapsed_msec < reg->hr_timeout_ms) {
+ /* the kthread api has blocked signals for us so no
+ * need to record the return value. */
+ msleep_interruptible(reg->hr_timeout_ms - elapsed_msec);
+ }
+ }
+
+ o2hb_disarm_write_timeout(reg);
+
+ /* unclean stop is only used in very bad situation */
+ for(i = 0; !reg->hr_unclean_stop && i < reg->hr_blocks; i++)
+ o2hb_shutdown_slot(&reg->hr_slots[i]);
+
+ /* Explicit down notification - avoid forcing the other nodes
+ * to timeout on this region when we could just as easily
+ * write a clear generation - thus indicating to them that
+ * this node has left this region.
+ *
+ * XXX: Should we skip this on unclean_stop? */
+ o2hb_prepare_block(reg, 0);
+ ret = o2hb_issue_node_write(reg, &write_bio, &write_wc);
+ if (ret == 0) {
+ o2hb_wait_on_io(reg, &write_wc);
+ bio_put(write_bio);
+ } else {
+ mlog_errno(ret);
+ }
+
+ mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread exiting\n");
+
+ return 0;
+}
+
+void o2hb_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(o2hb_callbacks); i++)
+ INIT_LIST_HEAD(&o2hb_callbacks[i].list);
+
+ for (i = 0; i < ARRAY_SIZE(o2hb_live_slots); i++)
+ INIT_LIST_HEAD(&o2hb_live_slots[i]);
+
+ INIT_LIST_HEAD(&o2hb_node_events);
+
+ memset(o2hb_live_node_bitmap, 0, sizeof(o2hb_live_node_bitmap));
+}
+
+/* if we're already in a callback then we're already serialized by the sem */
+static void o2hb_fill_node_map_from_callback(unsigned long *map,
+ unsigned bytes)
+{
+ BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long)));
+
+ memcpy(map, &o2hb_live_node_bitmap, bytes);
+}
+
+/*
+ * get a map of all nodes that are heartbeating in any regions
+ */
+void o2hb_fill_node_map(unsigned long *map, unsigned bytes)
+{
+ /* callers want to serialize this map and callbacks so that they
+ * can trust that they don't miss nodes coming to the party */
+ down_read(&o2hb_callback_sem);
+ spin_lock(&o2hb_live_lock);
+ o2hb_fill_node_map_from_callback(map, bytes);
+ spin_unlock(&o2hb_live_lock);
+ up_read(&o2hb_callback_sem);
+}
+EXPORT_SYMBOL_GPL(o2hb_fill_node_map);
+
+/*
+ * heartbeat configfs bits. The heartbeat set is a default set under
+ * the cluster set in nodemanager.c.
+ */
+
+static struct o2hb_region *to_o2hb_region(struct config_item *item)
+{
+ return item ? container_of(item, struct o2hb_region, hr_item) : NULL;
+}
+
+/* drop_item only drops its ref after killing the thread, nothing should
+ * be using the region anymore. this has to clean up any state that
+ * attributes might have built up. */
+static void o2hb_region_release(struct config_item *item)
+{
+ int i;
+ struct page *page;
+ struct o2hb_region *reg = to_o2hb_region(item);
+
+ if (reg->hr_tmp_block)
+ kfree(reg->hr_tmp_block);
+
+ if (reg->hr_slot_data) {
+ for (i = 0; i < reg->hr_num_pages; i++) {
+ page = reg->hr_slot_data[i];
+ if (page)
+ __free_page(page);
+ }
+ kfree(reg->hr_slot_data);
+ }
+
+ if (reg->hr_bdev)
+ blkdev_put(reg->hr_bdev);
+
+ if (reg->hr_slots)
+ kfree(reg->hr_slots);
+
+ spin_lock(&o2hb_live_lock);
+ list_del(&reg->hr_all_item);
+ spin_unlock(&o2hb_live_lock);
+
+ kfree(reg);
+}
+
+static int o2hb_read_block_input(struct o2hb_region *reg,
+ const char *page,
+ size_t count,
+ unsigned long *ret_bytes,
+ unsigned int *ret_bits)
+{
+ unsigned long bytes;
+ char *p = (char *)page;
+
+ bytes = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ /* Heartbeat and fs min / max block sizes are the same. */
+ if (bytes > 4096 || bytes < 512)
+ return -ERANGE;
+ if (hweight16(bytes) != 1)
+ return -EINVAL;
+
+ if (ret_bytes)
+ *ret_bytes = bytes;
+ if (ret_bits)
+ *ret_bits = ffs(bytes) - 1;
+
+ return 0;
+}
+
+static ssize_t o2hb_region_block_bytes_read(struct o2hb_region *reg,
+ char *page)
+{
+ return sprintf(page, "%u\n", reg->hr_block_bytes);
+}
+
+static ssize_t o2hb_region_block_bytes_write(struct o2hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ int status;
+ unsigned long block_bytes;
+ unsigned int block_bits;
+
+ if (reg->hr_bdev)
+ return -EINVAL;
+
+ status = o2hb_read_block_input(reg, page, count,
+ &block_bytes, &block_bits);
+ if (status)
+ return status;
+
+ reg->hr_block_bytes = (unsigned int)block_bytes;
+ reg->hr_block_bits = block_bits;
+
+ return count;
+}
+
+static ssize_t o2hb_region_start_block_read(struct o2hb_region *reg,
+ char *page)
+{
+ return sprintf(page, "%llu\n", reg->hr_start_block);
+}
+
+static ssize_t o2hb_region_start_block_write(struct o2hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ unsigned long long tmp;
+ char *p = (char *)page;
+
+ if (reg->hr_bdev)
+ return -EINVAL;
+
+ tmp = simple_strtoull(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ reg->hr_start_block = tmp;
+
+ return count;
+}
+
+static ssize_t o2hb_region_blocks_read(struct o2hb_region *reg,
+ char *page)
+{
+ return sprintf(page, "%d\n", reg->hr_blocks);
+}
+
+static ssize_t o2hb_region_blocks_write(struct o2hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ unsigned long tmp;
+ char *p = (char *)page;
+
+ if (reg->hr_bdev)
+ return -EINVAL;
+
+ tmp = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp > O2NM_MAX_NODES || tmp == 0)
+ return -ERANGE;
+
+ reg->hr_blocks = (unsigned int)tmp;
+
+ return count;
+}
+
+static ssize_t o2hb_region_dev_read(struct o2hb_region *reg,
+ char *page)
+{
+ unsigned int ret = 0;
+
+ if (reg->hr_bdev)
+ ret = sprintf(page, "%s\n", reg->hr_dev_name);
+
+ return ret;
+}
+
+static void o2hb_init_region_params(struct o2hb_region *reg)
+{
+ reg->hr_slots_per_page = PAGE_CACHE_SIZE >> reg->hr_block_bits;
+ reg->hr_timeout_ms = O2HB_REGION_TIMEOUT_MS;
+
+ mlog(ML_HEARTBEAT, "hr_start_block = %llu, hr_blocks = %u\n",
+ reg->hr_start_block, reg->hr_blocks);
+ mlog(ML_HEARTBEAT, "hr_block_bytes = %u, hr_block_bits = %u\n",
+ reg->hr_block_bytes, reg->hr_block_bits);
+ mlog(ML_HEARTBEAT, "hr_timeout_ms = %u\n", reg->hr_timeout_ms);
+ mlog(ML_HEARTBEAT, "dead threshold = %u\n", o2hb_dead_threshold);
+}
+
+static int o2hb_map_slot_data(struct o2hb_region *reg)
+{
+ int i, j;
+ unsigned int last_slot;
+ unsigned int spp = reg->hr_slots_per_page;
+ struct page *page;
+ char *raw;
+ struct o2hb_disk_slot *slot;
+
+ reg->hr_tmp_block = kmalloc(reg->hr_block_bytes, GFP_KERNEL);
+ if (reg->hr_tmp_block == NULL) {
+ mlog_errno(-ENOMEM);
+ return -ENOMEM;
+ }
+
+ reg->hr_slots = kcalloc(reg->hr_blocks,
+ sizeof(struct o2hb_disk_slot), GFP_KERNEL);
+ if (reg->hr_slots == NULL) {
+ mlog_errno(-ENOMEM);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < reg->hr_blocks; i++) {
+ slot = &reg->hr_slots[i];
+ slot->ds_node_num = i;
+ INIT_LIST_HEAD(&slot->ds_live_item);
+ slot->ds_raw_block = NULL;
+ }
+
+ reg->hr_num_pages = (reg->hr_blocks + spp - 1) / spp;
+ mlog(ML_HEARTBEAT, "Going to require %u pages to cover %u blocks "
+ "at %u blocks per page\n",
+ reg->hr_num_pages, reg->hr_blocks, spp);
+
+ reg->hr_slot_data = kcalloc(reg->hr_num_pages, sizeof(struct page *),
+ GFP_KERNEL);
+ if (!reg->hr_slot_data) {
+ mlog_errno(-ENOMEM);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < reg->hr_num_pages; i++) {
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ mlog_errno(-ENOMEM);
+ return -ENOMEM;
+ }
+
+ reg->hr_slot_data[i] = page;
+
+ last_slot = i * spp;
+ raw = page_address(page);
+ for (j = 0;
+ (j < spp) && ((j + last_slot) < reg->hr_blocks);
+ j++) {
+ BUG_ON((j + last_slot) >= reg->hr_blocks);
+
+ slot = &reg->hr_slots[j + last_slot];
+ slot->ds_raw_block =
+ (struct o2hb_disk_heartbeat_block *) raw;
+
+ raw += reg->hr_block_bytes;
+ }
+ }
+
+ return 0;
+}
+
+/* Read in all the slots available and populate the tracking
+ * structures so that we can start with a baseline idea of what's
+ * there. */
+static int o2hb_populate_slot_data(struct o2hb_region *reg)
+{
+ int ret, i;
+ struct o2hb_disk_slot *slot;
+ struct o2hb_disk_heartbeat_block *hb_block;
+
+ mlog_entry_void();
+
+ ret = o2hb_read_slots(reg, reg->hr_blocks);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /* We only want to get an idea of the values initially in each
+ * slot, so we do no verification - o2hb_check_slot will
+ * actually determine if each configured slot is valid and
+ * whether any values have changed. */
+ for(i = 0; i < reg->hr_blocks; i++) {
+ slot = &reg->hr_slots[i];
+ hb_block = (struct o2hb_disk_heartbeat_block *) slot->ds_raw_block;
+
+ /* Only fill the values that o2hb_check_slot uses to
+ * determine changing slots */
+ slot->ds_last_time = le64_to_cpu(hb_block->hb_seq);
+ slot->ds_last_generation = le64_to_cpu(hb_block->hb_generation);
+ }
+
+out:
+ mlog_exit(ret);
+ return ret;
+}
+
+/* this is acting as commit; we set up all of hr_bdev and hr_task or nothing */
+static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
+ const char *page,
+ size_t count)
+{
+ long fd;
+ int sectsize;
+ char *p = (char *)page;
+ struct file *filp = NULL;
+ struct inode *inode = NULL;
+ ssize_t ret = -EINVAL;
+
+ if (reg->hr_bdev)
+ goto out;
+
+ /* We can't heartbeat without having had our node number
+ * configured yet. */
+ if (o2nm_this_node() == O2NM_MAX_NODES)
+ goto out;
+
+ fd = simple_strtol(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ goto out;
+
+ if (fd < 0 || fd >= INT_MAX)
+ goto out;
+
+ filp = fget(fd);
+ if (filp == NULL)
+ goto out;
+
+ if (reg->hr_blocks == 0 || reg->hr_start_block == 0 ||
+ reg->hr_block_bytes == 0)
+ goto out;
+
+ inode = igrab(filp->f_mapping->host);
+ if (inode == NULL)
+ goto out;
+
+ if (!S_ISBLK(inode->i_mode))
+ goto out;
+
+ reg->hr_bdev = I_BDEV(filp->f_mapping->host);
+ ret = blkdev_get(reg->hr_bdev, FMODE_WRITE | FMODE_READ, 0);
+ if (ret) {
+ reg->hr_bdev = NULL;
+ goto out;
+ }
+ inode = NULL;
+
+ bdevname(reg->hr_bdev, reg->hr_dev_name);
+
+ sectsize = bdev_hardsect_size(reg->hr_bdev);
+ if (sectsize != reg->hr_block_bytes) {
+ mlog(ML_ERROR,
+ "blocksize %u incorrect for device, expected %d",
+ reg->hr_block_bytes, sectsize);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ o2hb_init_region_params(reg);
+
+ /* Generation of zero is invalid */
+ do {
+ get_random_bytes(&reg->hr_generation,
+ sizeof(reg->hr_generation));
+ } while (reg->hr_generation == 0);
+
+ ret = o2hb_map_slot_data(reg);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = o2hb_populate_slot_data(reg);
+ if (ret) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ INIT_WORK(&reg->hr_write_timeout_work, o2hb_write_timeout, reg);
+
+ /*
+ * A node is considered live after it has beat LIVE_THRESHOLD
+ * times. We're not steady until we've given them a chance
+ * _after_ our first read.
+ */
+ atomic_set(&reg->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1);
+
+ reg->hr_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
+ reg->hr_item.ci_name);
+ if (IS_ERR(reg->hr_task)) {
+ ret = PTR_ERR(reg->hr_task);
+ mlog_errno(ret);
+ reg->hr_task = NULL;
+ goto out;
+ }
+
+ ret = wait_event_interruptible(o2hb_steady_queue,
+ atomic_read(&reg->hr_steady_iterations) == 0);
+ if (ret) {
+ kthread_stop(reg->hr_task);
+ reg->hr_task = NULL;
+ goto out;
+ }
+
+ ret = count;
+out:
+ if (filp)
+ fput(filp);
+ if (inode)
+ iput(inode);
+ if (ret < 0) {
+ if (reg->hr_bdev) {
+ blkdev_put(reg->hr_bdev);
+ reg->hr_bdev = NULL;
+ }
+ }
+ return ret;
+}
+
+struct o2hb_region_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct o2hb_region *, char *);
+ ssize_t (*store)(struct o2hb_region *, const char *, size_t);
+};
+
+static struct o2hb_region_attribute o2hb_region_attr_block_bytes = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "block_bytes",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2hb_region_block_bytes_read,
+ .store = o2hb_region_block_bytes_write,
+};
+
+static struct o2hb_region_attribute o2hb_region_attr_start_block = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "start_block",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2hb_region_start_block_read,
+ .store = o2hb_region_start_block_write,
+};
+
+static struct o2hb_region_attribute o2hb_region_attr_blocks = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "blocks",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2hb_region_blocks_read,
+ .store = o2hb_region_blocks_write,
+};
+
+static struct o2hb_region_attribute o2hb_region_attr_dev = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "dev",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2hb_region_dev_read,
+ .store = o2hb_region_dev_write,
+};
+
+static struct configfs_attribute *o2hb_region_attrs[] = {
+ &o2hb_region_attr_block_bytes.attr,
+ &o2hb_region_attr_start_block.attr,
+ &o2hb_region_attr_blocks.attr,
+ &o2hb_region_attr_dev.attr,
+ NULL,
+};
+
+static ssize_t o2hb_region_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct o2hb_region *reg = to_o2hb_region(item);
+ struct o2hb_region_attribute *o2hb_region_attr =
+ container_of(attr, struct o2hb_region_attribute, attr);
+ ssize_t ret = 0;
+
+ if (o2hb_region_attr->show)
+ ret = o2hb_region_attr->show(reg, page);
+ return ret;
+}
+
+static ssize_t o2hb_region_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct o2hb_region *reg = to_o2hb_region(item);
+ struct o2hb_region_attribute *o2hb_region_attr =
+ container_of(attr, struct o2hb_region_attribute, attr);
+ ssize_t ret = -EINVAL;
+
+ if (o2hb_region_attr->store)
+ ret = o2hb_region_attr->store(reg, page, count);
+ return ret;
+}
+
+static struct configfs_item_operations o2hb_region_item_ops = {
+ .release = o2hb_region_release,
+ .show_attribute = o2hb_region_show,
+ .store_attribute = o2hb_region_store,
+};
+
+static struct config_item_type o2hb_region_type = {
+ .ct_item_ops = &o2hb_region_item_ops,
+ .ct_attrs = o2hb_region_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/* heartbeat set */
+
+struct o2hb_heartbeat_group {
+ struct config_group hs_group;
+ /* some stuff? */
+};
+
+static struct o2hb_heartbeat_group *to_o2hb_heartbeat_group(struct config_group *group)
+{
+ return group ?
+ container_of(group, struct o2hb_heartbeat_group, hs_group)
+ : NULL;
+}
+
+static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *group,
+ const char *name)
+{
+ struct o2hb_region *reg = NULL;
+ struct config_item *ret = NULL;
+
+ reg = kcalloc(1, sizeof(struct o2hb_region), GFP_KERNEL);
+ if (reg == NULL)
+ goto out; /* ENOMEM */
+
+ config_item_init_type_name(&reg->hr_item, name, &o2hb_region_type);
+
+ ret = &reg->hr_item;
+
+ spin_lock(&o2hb_live_lock);
+ list_add_tail(&reg->hr_all_item, &o2hb_all_regions);
+ spin_unlock(&o2hb_live_lock);
+out:
+ if (ret == NULL)
+ kfree(reg);
+
+ return ret;
+}
+
+static void o2hb_heartbeat_group_drop_item(struct config_group *group,
+ struct config_item *item)
+{
+ struct o2hb_region *reg = to_o2hb_region(item);
+
+ /* stop the thread when the user removes the region dir */
+ if (reg->hr_task) {
+ kthread_stop(reg->hr_task);
+ reg->hr_task = NULL;
+ }
+
+ config_item_put(item);
+}
+
+struct o2hb_heartbeat_group_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct o2hb_heartbeat_group *, char *);
+ ssize_t (*store)(struct o2hb_heartbeat_group *, const char *, size_t);
+};
+
+static ssize_t o2hb_heartbeat_group_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item));
+ struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr =
+ container_of(attr, struct o2hb_heartbeat_group_attribute, attr);
+ ssize_t ret = 0;
+
+ if (o2hb_heartbeat_group_attr->show)
+ ret = o2hb_heartbeat_group_attr->show(reg, page);
+ return ret;
+}
+
+static ssize_t o2hb_heartbeat_group_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct o2hb_heartbeat_group *reg = to_o2hb_heartbeat_group(to_config_group(item));
+ struct o2hb_heartbeat_group_attribute *o2hb_heartbeat_group_attr =
+ container_of(attr, struct o2hb_heartbeat_group_attribute, attr);
+ ssize_t ret = -EINVAL;
+
+ if (o2hb_heartbeat_group_attr->store)
+ ret = o2hb_heartbeat_group_attr->store(reg, page, count);
+ return ret;
+}
+
+static ssize_t o2hb_heartbeat_group_threshold_show(struct o2hb_heartbeat_group *group,
+ char *page)
+{
+ return sprintf(page, "%u\n", o2hb_dead_threshold);
+}
+
+static ssize_t o2hb_heartbeat_group_threshold_store(struct o2hb_heartbeat_group *group,
+ const char *page,
+ size_t count)
+{
+ unsigned long tmp;
+ char *p = (char *)page;
+
+ tmp = simple_strtoul(p, &p, 10);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ /* this will validate ranges for us. */
+ o2hb_dead_threshold_set((unsigned int) tmp);
+
+ return count;
+}
+
+static struct o2hb_heartbeat_group_attribute o2hb_heartbeat_group_attr_threshold = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "dead_threshold",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2hb_heartbeat_group_threshold_show,
+ .store = o2hb_heartbeat_group_threshold_store,
+};
+
+static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
+ &o2hb_heartbeat_group_attr_threshold.attr,
+ NULL,
+};
+
+static struct configfs_item_operations o2hb_hearbeat_group_item_ops = {
+ .show_attribute = o2hb_heartbeat_group_show,
+ .store_attribute = o2hb_heartbeat_group_store,
+};
+
+static struct configfs_group_operations o2hb_heartbeat_group_group_ops = {
+ .make_item = o2hb_heartbeat_group_make_item,
+ .drop_item = o2hb_heartbeat_group_drop_item,
+};
+
+static struct config_item_type o2hb_heartbeat_group_type = {
+ .ct_group_ops = &o2hb_heartbeat_group_group_ops,
+ .ct_item_ops = &o2hb_hearbeat_group_item_ops,
+ .ct_attrs = o2hb_heartbeat_group_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/* this is just here to avoid touching group in heartbeat.h which the
+ * entire damn world #includes */
+struct config_group *o2hb_alloc_hb_set(void)
+{
+ struct o2hb_heartbeat_group *hs = NULL;
+ struct config_group *ret = NULL;
+
+ hs = kcalloc(1, sizeof(struct o2hb_heartbeat_group), GFP_KERNEL);
+ if (hs == NULL)
+ goto out;
+
+ config_group_init_type_name(&hs->hs_group, "heartbeat",
+ &o2hb_heartbeat_group_type);
+
+ ret = &hs->hs_group;
+out:
+ if (ret == NULL)
+ kfree(hs);
+ return ret;
+}
+
+void o2hb_free_hb_set(struct config_group *group)
+{
+ struct o2hb_heartbeat_group *hs = to_o2hb_heartbeat_group(group);
+ kfree(hs);
+}
+
+/* hb callback registration and issueing */
+
+static struct o2hb_callback *hbcall_from_type(enum o2hb_callback_type type)
+{
+ if (type == O2HB_NUM_CB)
+ return ERR_PTR(-EINVAL);
+
+ return &o2hb_callbacks[type];
+}
+
+void o2hb_setup_callback(struct o2hb_callback_func *hc,
+ enum o2hb_callback_type type,
+ o2hb_cb_func *func,
+ void *data,
+ int priority)
+{
+ INIT_LIST_HEAD(&hc->hc_item);
+ hc->hc_func = func;
+ hc->hc_data = data;
+ hc->hc_priority = priority;
+ hc->hc_type = type;
+ hc->hc_magic = O2HB_CB_MAGIC;
+}
+EXPORT_SYMBOL_GPL(o2hb_setup_callback);
+
+int o2hb_register_callback(struct o2hb_callback_func *hc)
+{
+ struct o2hb_callback_func *tmp;
+ struct list_head *iter;
+ struct o2hb_callback *hbcall;
+ int ret;
+
+ BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
+ BUG_ON(!list_empty(&hc->hc_item));
+
+ hbcall = hbcall_from_type(hc->hc_type);
+ if (IS_ERR(hbcall)) {
+ ret = PTR_ERR(hbcall);
+ goto out;
+ }
+
+ down_write(&o2hb_callback_sem);
+
+ list_for_each(iter, &hbcall->list) {
+ tmp = list_entry(iter, struct o2hb_callback_func, hc_item);
+ if (hc->hc_priority < tmp->hc_priority) {
+ list_add_tail(&hc->hc_item, iter);
+ break;
+ }
+ }
+ if (list_empty(&hc->hc_item))
+ list_add_tail(&hc->hc_item, &hbcall->list);
+
+ up_write(&o2hb_callback_sem);
+ ret = 0;
+out:
+ mlog(ML_HEARTBEAT, "returning %d on behalf of %p for funcs %p\n",
+ ret, __builtin_return_address(0), hc);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(o2hb_register_callback);
+
+int o2hb_unregister_callback(struct o2hb_callback_func *hc)
+{
+ BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
+
+ mlog(ML_HEARTBEAT, "on behalf of %p for funcs %p\n",
+ __builtin_return_address(0), hc);
+
+ if (list_empty(&hc->hc_item))
+ return 0;
+
+ down_write(&o2hb_callback_sem);
+
+ list_del_init(&hc->hc_item);
+
+ up_write(&o2hb_callback_sem);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(o2hb_unregister_callback);
+
+int o2hb_check_node_heartbeating(u8 node_num)
+{
+ unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+
+ o2hb_fill_node_map(testing_map, sizeof(testing_map));
+ if (!test_bit(node_num, testing_map)) {
+ mlog(ML_HEARTBEAT,
+ "node (%u) does not have heartbeating enabled.\n",
+ node_num);
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating);
+
+int o2hb_check_node_heartbeating_from_callback(u8 node_num)
+{
+ unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+
+ o2hb_fill_node_map_from_callback(testing_map, sizeof(testing_map));
+ if (!test_bit(node_num, testing_map)) {
+ mlog(ML_HEARTBEAT,
+ "node (%u) does not have heartbeating enabled.\n",
+ node_num);
+ return 0;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating_from_callback);
+
+/* Makes sure our local node is configured with a node number, and is
+ * heartbeating. */
+int o2hb_check_local_node_heartbeating(void)
+{
+ u8 node_num;
+
+ /* if this node was set then we have networking */
+ node_num = o2nm_this_node();
+ if (node_num == O2NM_MAX_NODES) {
+ mlog(ML_HEARTBEAT, "this node has not been configured.\n");
+ return 0;
+ }
+
+ return o2hb_check_node_heartbeating(node_num);
+}
+EXPORT_SYMBOL_GPL(o2hb_check_local_node_heartbeating);
+
+/*
+ * this is just a hack until we get the plumbing which flips file systems
+ * read only and drops the hb ref instead of killing the node dead.
+ */
+void o2hb_stop_all_regions(void)
+{
+ struct o2hb_region *reg;
+
+ mlog(ML_ERROR, "stopping heartbeat on all active regions.\n");
+
+ spin_lock(&o2hb_live_lock);
+
+ list_for_each_entry(reg, &o2hb_all_regions, hr_all_item)
+ reg->hr_unclean_stop = 1;
+
+ spin_unlock(&o2hb_live_lock);
+}
+EXPORT_SYMBOL_GPL(o2hb_stop_all_regions);
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
new file mode 100644
index 000000000000..cac6223206a9
--- /dev/null
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -0,0 +1,82 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * heartbeat.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef O2CLUSTER_HEARTBEAT_H
+#define O2CLUSTER_HEARTBEAT_H
+
+#include "ocfs2_heartbeat.h"
+
+#define O2HB_REGION_TIMEOUT_MS 2000
+
+/* number of changes to be seen as live */
+#define O2HB_LIVE_THRESHOLD 2
+/* number of equal samples to be seen as dead */
+extern unsigned int o2hb_dead_threshold;
+#define O2HB_DEFAULT_DEAD_THRESHOLD 7
+/* Otherwise MAX_WRITE_TIMEOUT will be zero... */
+#define O2HB_MIN_DEAD_THRESHOLD 2
+#define O2HB_MAX_WRITE_TIMEOUT_MS (O2HB_REGION_TIMEOUT_MS * (o2hb_dead_threshold - 1))
+
+#define O2HB_CB_MAGIC 0x51d1e4ec
+
+/* callback stuff */
+enum o2hb_callback_type {
+ O2HB_NODE_DOWN_CB = 0,
+ O2HB_NODE_UP_CB,
+ O2HB_NUM_CB
+};
+
+struct o2nm_node;
+typedef void (o2hb_cb_func)(struct o2nm_node *, int, void *);
+
+struct o2hb_callback_func {
+ u32 hc_magic;
+ struct list_head hc_item;
+ o2hb_cb_func *hc_func;
+ void *hc_data;
+ int hc_priority;
+ enum o2hb_callback_type hc_type;
+};
+
+struct config_group *o2hb_alloc_hb_set(void);
+void o2hb_free_hb_set(struct config_group *group);
+
+void o2hb_setup_callback(struct o2hb_callback_func *hc,
+ enum o2hb_callback_type type,
+ o2hb_cb_func *func,
+ void *data,
+ int priority);
+int o2hb_register_callback(struct o2hb_callback_func *hc);
+int o2hb_unregister_callback(struct o2hb_callback_func *hc);
+void o2hb_fill_node_map(unsigned long *map,
+ unsigned bytes);
+void o2hb_init(void);
+int o2hb_check_node_heartbeating(u8 node_num);
+int o2hb_check_node_heartbeating_from_callback(u8 node_num);
+int o2hb_check_local_node_heartbeating(void);
+void o2hb_stop_all_regions(void);
+
+#endif /* O2CLUSTER_HEARTBEAT_H */
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
new file mode 100644
index 000000000000..fd741cea5705
--- /dev/null
+++ b/fs/ocfs2/cluster/masklog.c
@@ -0,0 +1,166 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2004, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+#include "masklog.h"
+
+struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK);
+EXPORT_SYMBOL_GPL(mlog_and_bits);
+struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(MLOG_INITIAL_NOT_MASK);
+EXPORT_SYMBOL_GPL(mlog_not_bits);
+
+static ssize_t mlog_mask_show(u64 mask, char *buf)
+{
+ char *state;
+
+ if (__mlog_test_u64(mask, mlog_and_bits))
+ state = "allow";
+ else if (__mlog_test_u64(mask, mlog_not_bits))
+ state = "deny";
+ else
+ state = "off";
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", state);
+}
+
+static ssize_t mlog_mask_store(u64 mask, const char *buf, size_t count)
+{
+ if (!strnicmp(buf, "allow", 5)) {
+ __mlog_set_u64(mask, mlog_and_bits);
+ __mlog_clear_u64(mask, mlog_not_bits);
+ } else if (!strnicmp(buf, "deny", 4)) {
+ __mlog_set_u64(mask, mlog_not_bits);
+ __mlog_clear_u64(mask, mlog_and_bits);
+ } else if (!strnicmp(buf, "off", 3)) {
+ __mlog_clear_u64(mask, mlog_not_bits);
+ __mlog_clear_u64(mask, mlog_and_bits);
+ } else
+ return -EINVAL;
+
+ return count;
+}
+
+struct mlog_attribute {
+ struct attribute attr;
+ u64 mask;
+};
+
+#define to_mlog_attr(_attr) container_of(_attr, struct mlog_attribute, attr)
+
+#define define_mask(_name) { \
+ .attr = { \
+ .name = #_name, \
+ .mode = S_IRUGO | S_IWUSR, \
+ }, \
+ .mask = ML_##_name, \
+}
+
+static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
+ define_mask(ENTRY),
+ define_mask(EXIT),
+ define_mask(TCP),
+ define_mask(MSG),
+ define_mask(SOCKET),
+ define_mask(HEARTBEAT),
+ define_mask(HB_BIO),
+ define_mask(DLMFS),
+ define_mask(DLM),
+ define_mask(DLM_DOMAIN),
+ define_mask(DLM_THREAD),
+ define_mask(DLM_MASTER),
+ define_mask(DLM_RECOVERY),
+ define_mask(AIO),
+ define_mask(JOURNAL),
+ define_mask(DISK_ALLOC),
+ define_mask(SUPER),
+ define_mask(FILE_IO),
+ define_mask(EXTENT_MAP),
+ define_mask(DLM_GLUE),
+ define_mask(BH_IO),
+ define_mask(UPTODATE),
+ define_mask(NAMEI),
+ define_mask(INODE),
+ define_mask(VOTE),
+ define_mask(DCACHE),
+ define_mask(CONN),
+ define_mask(QUORUM),
+ define_mask(EXPORT),
+ define_mask(ERROR),
+ define_mask(NOTICE),
+ define_mask(KTHREAD),
+};
+
+static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, };
+
+static ssize_t mlog_show(struct kobject *obj, struct attribute *attr,
+ char *buf)
+{
+ struct mlog_attribute *mlog_attr = to_mlog_attr(attr);
+
+ return mlog_mask_show(mlog_attr->mask, buf);
+}
+
+static ssize_t mlog_store(struct kobject *obj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ struct mlog_attribute *mlog_attr = to_mlog_attr(attr);
+
+ return mlog_mask_store(mlog_attr->mask, buf, count);
+}
+
+static struct sysfs_ops mlog_attr_ops = {
+ .show = mlog_show,
+ .store = mlog_store,
+};
+
+static struct kobj_type mlog_ktype = {
+ .default_attrs = mlog_attr_ptrs,
+ .sysfs_ops = &mlog_attr_ops,
+};
+
+static struct kset mlog_kset = {
+ .kobj = {.name = "logmask", .ktype = &mlog_ktype},
+};
+
+int mlog_sys_init(struct subsystem *o2cb_subsys)
+{
+ int i = 0;
+
+ while (mlog_attrs[i].attr.mode) {
+ mlog_attr_ptrs[i] = &mlog_attrs[i].attr;
+ i++;
+ }
+ mlog_attr_ptrs[i] = NULL;
+
+ mlog_kset.subsys = o2cb_subsys;
+ return kset_register(&mlog_kset);
+}
+
+void mlog_sys_shutdown(void)
+{
+ kset_unregister(&mlog_kset);
+}
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
new file mode 100644
index 000000000000..e8c56a3d9c64
--- /dev/null
+++ b/fs/ocfs2/cluster/masklog.h
@@ -0,0 +1,274 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef O2CLUSTER_MASKLOG_H
+#define O2CLUSTER_MASKLOG_H
+
+/*
+ * For now this is a trivial wrapper around printk() that gives the critical
+ * ability to enable sets of debugging output at run-time. In the future this
+ * will almost certainly be redirected to relayfs so that it can pay a
+ * substantially lower heisenberg tax.
+ *
+ * Callers associate the message with a bitmask and a global bitmask is
+ * maintained with help from /proc. If any of the bits match the message is
+ * output.
+ *
+ * We must have efficient bit tests on i386 and it seems gcc still emits crazy
+ * code for the 64bit compare. It emits very good code for the dual unsigned
+ * long tests, though, completely avoiding tests that can never pass if the
+ * caller gives a constant bitmask that fills one of the longs with all 0s. So
+ * the desire is to have almost all of the calls decided on by comparing just
+ * one of the longs. This leads to having infrequently given bits that are
+ * frequently matched in the high bits.
+ *
+ * _ERROR and _NOTICE are used for messages that always go to the console and
+ * have appropriate KERN_ prefixes. We wrap these in our function instead of
+ * just calling printk() so that this can eventually make its way through
+ * relayfs along with the debugging messages. Everything else gets KERN_DEBUG.
+ * The inline tests and macro dance give GCC the opportunity to quite cleverly
+ * only emit the appropriage printk() when the caller passes in a constant
+ * mask, as is almost always the case.
+ *
+ * All this bitmask nonsense is hidden from the /proc interface so that Joel
+ * doesn't have an aneurism. Reading the file gives a straight forward
+ * indication of which bits are on or off:
+ * ENTRY off
+ * EXIT off
+ * TCP off
+ * MSG off
+ * SOCKET off
+ * ERROR off
+ * NOTICE on
+ *
+ * Writing changes the state of a given bit and requires a strictly formatted
+ * single write() call:
+ *
+ * write(fd, "ENTRY on", 8);
+ *
+ * would turn the entry bit on. "1" is also accepted in the place of "on", and
+ * "off" and "0" behave as expected.
+ *
+ * Some trivial shell can flip all the bits on or off:
+ *
+ * log_mask="/proc/fs/ocfs2_nodemanager/log_mask"
+ * cat $log_mask | (
+ * while read bit status; do
+ * # $1 is "on" or "off", say
+ * echo "$bit $1" > $log_mask
+ * done
+ * )
+ */
+
+/* for task_struct */
+#include <linux/sched.h>
+
+/* bits that are frequently given and infrequently matched in the low word */
+/* NOTE: If you add a flag, you need to also update mlog.c! */
+#define ML_ENTRY 0x0000000000000001ULL /* func call entry */
+#define ML_EXIT 0x0000000000000002ULL /* func call exit */
+#define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */
+#define ML_MSG 0x0000000000000008ULL /* net network messages */
+#define ML_SOCKET 0x0000000000000010ULL /* net socket lifetime */
+#define ML_HEARTBEAT 0x0000000000000020ULL /* hb all heartbeat tracking */
+#define ML_HB_BIO 0x0000000000000040ULL /* hb io tracing */
+#define ML_DLMFS 0x0000000000000080ULL /* dlm user dlmfs */
+#define ML_DLM 0x0000000000000100ULL /* dlm general debugging */
+#define ML_DLM_DOMAIN 0x0000000000000200ULL /* dlm domain debugging */
+#define ML_DLM_THREAD 0x0000000000000400ULL /* dlm domain thread */
+#define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */
+#define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */
+#define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */
+#define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */
+#define ML_DISK_ALLOC 0x0000000000008000ULL /* ocfs2 disk allocation */
+#define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */
+#define ML_FILE_IO 0x0000000000020000ULL /* ocfs2 file I/O */
+#define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */
+#define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */
+#define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */
+#define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */
+#define ML_NAMEI 0x0000000000400000ULL /* ocfs2 directory / namespace */
+#define ML_INODE 0x0000000000800000ULL /* ocfs2 inode manipulation */
+#define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */
+#define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */
+#define ML_CONN 0x0000000004000000ULL /* net connection management */
+#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */
+#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */
+/* bits that are infrequently given and frequently matched in the high word */
+#define ML_ERROR 0x0000000100000000ULL /* sent to KERN_ERR */
+#define ML_NOTICE 0x0000000200000000ULL /* setn to KERN_NOTICE */
+#define ML_KTHREAD 0x0000000400000000ULL /* kernel thread activity */
+
+#define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
+#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
+#ifndef MLOG_MASK_PREFIX
+#define MLOG_MASK_PREFIX 0
+#endif
+
+#define MLOG_MAX_BITS 64
+
+struct mlog_bits {
+ unsigned long words[MLOG_MAX_BITS / BITS_PER_LONG];
+};
+
+extern struct mlog_bits mlog_and_bits, mlog_not_bits;
+
+#if BITS_PER_LONG == 32
+
+#define __mlog_test_u64(mask, bits) \
+ ( (u32)(mask & 0xffffffff) & bits.words[0] || \
+ ((u64)(mask) >> 32) & bits.words[1] )
+#define __mlog_set_u64(mask, bits) do { \
+ bits.words[0] |= (u32)(mask & 0xffffffff); \
+ bits.words[1] |= (u64)(mask) >> 32; \
+} while (0)
+#define __mlog_clear_u64(mask, bits) do { \
+ bits.words[0] &= ~((u32)(mask & 0xffffffff)); \
+ bits.words[1] &= ~((u64)(mask) >> 32); \
+} while (0)
+#define MLOG_BITS_RHS(mask) { \
+ { \
+ [0] = (u32)(mask & 0xffffffff), \
+ [1] = (u64)(mask) >> 32, \
+ } \
+}
+
+#else /* 32bit long above, 64bit long below */
+
+#define __mlog_test_u64(mask, bits) ((mask) & bits.words[0])
+#define __mlog_set_u64(mask, bits) do { \
+ bits.words[0] |= (mask); \
+} while (0)
+#define __mlog_clear_u64(mask, bits) do { \
+ bits.words[0] &= ~(mask); \
+} while (0)
+#define MLOG_BITS_RHS(mask) { { (mask) } }
+
+#endif
+
+/*
+ * smp_processor_id() "helpfully" screams when called outside preemptible
+ * regions in current kernels. sles doesn't have the variants that don't
+ * scream. just do this instead of trying to guess which we're building
+ * against.. *sigh*.
+ */
+#define __mlog_cpu_guess ({ \
+ unsigned long _cpu = get_cpu(); \
+ put_cpu(); \
+ _cpu; \
+})
+
+/* In the following two macros, the whitespace after the ',' just
+ * before ##args is intentional. Otherwise, gcc 2.95 will eat the
+ * previous token if args expands to nothing.
+ */
+#define __mlog_printk(level, fmt, args...) \
+ printk(level "(%u,%lu):%s:%d " fmt, current->pid, \
+ __mlog_cpu_guess, __PRETTY_FUNCTION__, __LINE__ , \
+ ##args)
+
+#define mlog(mask, fmt, args...) do { \
+ u64 __m = MLOG_MASK_PREFIX | (mask); \
+ if (__mlog_test_u64(__m, mlog_and_bits) && \
+ !__mlog_test_u64(__m, mlog_not_bits)) { \
+ if (__m & ML_ERROR) \
+ __mlog_printk(KERN_ERR, "ERROR: "fmt , ##args); \
+ else if (__m & ML_NOTICE) \
+ __mlog_printk(KERN_NOTICE, fmt , ##args); \
+ else __mlog_printk(KERN_INFO, fmt , ##args); \
+ } \
+} while (0)
+
+#define mlog_errno(st) do { \
+ int _st = (st); \
+ if (_st != -ERESTARTSYS && _st != -EINTR && \
+ _st != AOP_TRUNCATED_PAGE) \
+ mlog(ML_ERROR, "status = %lld\n", (long long)_st); \
+} while (0)
+
+#define mlog_entry(fmt, args...) do { \
+ mlog(ML_ENTRY, "ENTRY:" fmt , ##args); \
+} while (0)
+
+#define mlog_entry_void() do { \
+ mlog(ML_ENTRY, "ENTRY:\n"); \
+} while (0)
+
+/*
+ * We disable this for sparse.
+ */
+#if !defined(__CHECKER__)
+#define mlog_exit(st) do { \
+ if (__builtin_types_compatible_p(typeof(st), unsigned long)) \
+ mlog(ML_EXIT, "EXIT: %lu\n", (unsigned long) (st)); \
+ else if (__builtin_types_compatible_p(typeof(st), signed long)) \
+ mlog(ML_EXIT, "EXIT: %ld\n", (signed long) (st)); \
+ else if (__builtin_types_compatible_p(typeof(st), unsigned int) \
+ || __builtin_types_compatible_p(typeof(st), unsigned short) \
+ || __builtin_types_compatible_p(typeof(st), unsigned char)) \
+ mlog(ML_EXIT, "EXIT: %u\n", (unsigned int) (st)); \
+ else if (__builtin_types_compatible_p(typeof(st), signed int) \
+ || __builtin_types_compatible_p(typeof(st), signed short) \
+ || __builtin_types_compatible_p(typeof(st), signed char)) \
+ mlog(ML_EXIT, "EXIT: %d\n", (signed int) (st)); \
+ else if (__builtin_types_compatible_p(typeof(st), long long)) \
+ mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \
+ else \
+ mlog(ML_EXIT, "EXIT: %llu\n", (unsigned long long) (st)); \
+} while (0)
+#else
+#define mlog_exit(st) do { \
+ mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \
+} while (0)
+#endif
+
+#define mlog_exit_ptr(ptr) do { \
+ mlog(ML_EXIT, "EXIT: %p\n", ptr); \
+} while (0)
+
+#define mlog_exit_void() do { \
+ mlog(ML_EXIT, "EXIT\n"); \
+} while (0)
+
+#define mlog_bug_on_msg(cond, fmt, args...) do { \
+ if (cond) { \
+ mlog(ML_ERROR, "bug expression: " #cond "\n"); \
+ mlog(ML_ERROR, fmt, ##args); \
+ BUG(); \
+ } \
+} while (0)
+
+#if (BITS_PER_LONG == 32) || defined(CONFIG_X86_64)
+#define MLFi64 "lld"
+#define MLFu64 "llu"
+#define MLFx64 "llx"
+#else
+#define MLFi64 "ld"
+#define MLFu64 "lu"
+#define MLFx64 "lx"
+#endif
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+int mlog_sys_init(struct subsystem *o2cb_subsys);
+void mlog_sys_shutdown(void);
+
+#endif /* O2CLUSTER_MASKLOG_H */
diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c
new file mode 100644
index 000000000000..cf7828f23361
--- /dev/null
+++ b/fs/ocfs2/cluster/nodemanager.c
@@ -0,0 +1,791 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2004, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
+#include <linux/configfs.h>
+
+#include "endian.h"
+#include "tcp.h"
+#include "nodemanager.h"
+#include "heartbeat.h"
+#include "masklog.h"
+#include "sys.h"
+#include "ver.h"
+
+/* for now we operate under the assertion that there can be only one
+ * cluster active at a time. Changing this will require trickling
+ * cluster references throughout where nodes are looked up */
+static struct o2nm_cluster *o2nm_single_cluster = NULL;
+
+#define OCFS2_MAX_HB_CTL_PATH 256
+static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl";
+
+static ctl_table ocfs2_nm_table[] = {
+ {
+ .ctl_name = 1,
+ .procname = "hb_ctl_path",
+ .data = ocfs2_hb_ctl_path,
+ .maxlen = OCFS2_MAX_HB_CTL_PATH,
+ .mode = 0644,
+ .proc_handler = &proc_dostring,
+ .strategy = &sysctl_string,
+ },
+ { .ctl_name = 0 }
+};
+
+static ctl_table ocfs2_mod_table[] = {
+ {
+ .ctl_name = KERN_OCFS2_NM,
+ .procname = "nm",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0555,
+ .child = ocfs2_nm_table
+ },
+ { .ctl_name = 0}
+};
+
+static ctl_table ocfs2_kern_table[] = {
+ {
+ .ctl_name = KERN_OCFS2,
+ .procname = "ocfs2",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0555,
+ .child = ocfs2_mod_table
+ },
+ { .ctl_name = 0}
+};
+
+static ctl_table ocfs2_root_table[] = {
+ {
+ .ctl_name = CTL_FS,
+ .procname = "fs",
+ .data = NULL,
+ .maxlen = 0,
+ .mode = 0555,
+ .child = ocfs2_kern_table
+ },
+ { .ctl_name = 0 }
+};
+
+static struct ctl_table_header *ocfs2_table_header = NULL;
+
+const char *o2nm_get_hb_ctl_path(void)
+{
+ return ocfs2_hb_ctl_path;
+}
+EXPORT_SYMBOL_GPL(o2nm_get_hb_ctl_path);
+
+struct o2nm_cluster {
+ struct config_group cl_group;
+ unsigned cl_has_local:1;
+ u8 cl_local_node;
+ rwlock_t cl_nodes_lock;
+ struct o2nm_node *cl_nodes[O2NM_MAX_NODES];
+ struct rb_root cl_node_ip_tree;
+ /* this bitmap is part of a hack for disk bitmap.. will go eventually. - zab */
+ unsigned long cl_nodes_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+};
+
+struct o2nm_node *o2nm_get_node_by_num(u8 node_num)
+{
+ struct o2nm_node *node = NULL;
+
+ if (node_num >= O2NM_MAX_NODES || o2nm_single_cluster == NULL)
+ goto out;
+
+ read_lock(&o2nm_single_cluster->cl_nodes_lock);
+ node = o2nm_single_cluster->cl_nodes[node_num];
+ if (node)
+ config_item_get(&node->nd_item);
+ read_unlock(&o2nm_single_cluster->cl_nodes_lock);
+out:
+ return node;
+}
+EXPORT_SYMBOL_GPL(o2nm_get_node_by_num);
+
+int o2nm_configured_node_map(unsigned long *map, unsigned bytes)
+{
+ struct o2nm_cluster *cluster = o2nm_single_cluster;
+
+ BUG_ON(bytes < (sizeof(cluster->cl_nodes_bitmap)));
+
+ if (cluster == NULL)
+ return -EINVAL;
+
+ read_lock(&cluster->cl_nodes_lock);
+ memcpy(map, cluster->cl_nodes_bitmap, sizeof(cluster->cl_nodes_bitmap));
+ read_unlock(&cluster->cl_nodes_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(o2nm_configured_node_map);
+
+static struct o2nm_node *o2nm_node_ip_tree_lookup(struct o2nm_cluster *cluster,
+ __be32 ip_needle,
+ struct rb_node ***ret_p,
+ struct rb_node **ret_parent)
+{
+ struct rb_node **p = &cluster->cl_node_ip_tree.rb_node;
+ struct rb_node *parent = NULL;
+ struct o2nm_node *node, *ret = NULL;
+
+ while (*p) {
+ parent = *p;
+ node = rb_entry(parent, struct o2nm_node, nd_ip_node);
+
+ if (memcmp(&ip_needle, &node->nd_ipv4_address,
+ sizeof(ip_needle)) < 0)
+ p = &(*p)->rb_left;
+ else if (memcmp(&ip_needle, &node->nd_ipv4_address,
+ sizeof(ip_needle)) > 0)
+ p = &(*p)->rb_right;
+ else {
+ ret = node;
+ break;
+ }
+ }
+
+ if (ret_p != NULL)
+ *ret_p = p;
+ if (ret_parent != NULL)
+ *ret_parent = parent;
+
+ return ret;
+}
+
+struct o2nm_node *o2nm_get_node_by_ip(__be32 addr)
+{
+ struct o2nm_node *node = NULL;
+ struct o2nm_cluster *cluster = o2nm_single_cluster;
+
+ if (cluster == NULL)
+ goto out;
+
+ read_lock(&cluster->cl_nodes_lock);
+ node = o2nm_node_ip_tree_lookup(cluster, addr, NULL, NULL);
+ if (node)
+ config_item_get(&node->nd_item);
+ read_unlock(&cluster->cl_nodes_lock);
+
+out:
+ return node;
+}
+EXPORT_SYMBOL_GPL(o2nm_get_node_by_ip);
+
+void o2nm_node_put(struct o2nm_node *node)
+{
+ config_item_put(&node->nd_item);
+}
+EXPORT_SYMBOL_GPL(o2nm_node_put);
+
+void o2nm_node_get(struct o2nm_node *node)
+{
+ config_item_get(&node->nd_item);
+}
+EXPORT_SYMBOL_GPL(o2nm_node_get);
+
+u8 o2nm_this_node(void)
+{
+ u8 node_num = O2NM_MAX_NODES;
+
+ if (o2nm_single_cluster && o2nm_single_cluster->cl_has_local)
+ node_num = o2nm_single_cluster->cl_local_node;
+
+ return node_num;
+}
+EXPORT_SYMBOL_GPL(o2nm_this_node);
+
+/* node configfs bits */
+
+static struct o2nm_cluster *to_o2nm_cluster(struct config_item *item)
+{
+ return item ?
+ container_of(to_config_group(item), struct o2nm_cluster,
+ cl_group)
+ : NULL;
+}
+
+static struct o2nm_node *to_o2nm_node(struct config_item *item)
+{
+ return item ? container_of(item, struct o2nm_node, nd_item) : NULL;
+}
+
+static void o2nm_node_release(struct config_item *item)
+{
+ struct o2nm_node *node = to_o2nm_node(item);
+ kfree(node);
+}
+
+static ssize_t o2nm_node_num_read(struct o2nm_node *node, char *page)
+{
+ return sprintf(page, "%d\n", node->nd_num);
+}
+
+static struct o2nm_cluster *to_o2nm_cluster_from_node(struct o2nm_node *node)
+{
+ /* through the first node_set .parent
+ * mycluster/nodes/mynode == o2nm_cluster->o2nm_node_group->o2nm_node */
+ return to_o2nm_cluster(node->nd_item.ci_parent->ci_parent);
+}
+
+enum {
+ O2NM_NODE_ATTR_NUM = 0,
+ O2NM_NODE_ATTR_PORT,
+ O2NM_NODE_ATTR_ADDRESS,
+ O2NM_NODE_ATTR_LOCAL,
+};
+
+static ssize_t o2nm_node_num_write(struct o2nm_node *node, const char *page,
+ size_t count)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
+ unsigned long tmp;
+ char *p = (char *)page;
+
+ tmp = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp >= O2NM_MAX_NODES)
+ return -ERANGE;
+
+ /* once we're in the cl_nodes tree networking can look us up by
+ * node number and try to use our address and port attributes
+ * to connect to this node.. make sure that they've been set
+ * before writing the node attribute? */
+ if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
+ !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
+ return -EINVAL; /* XXX */
+
+ write_lock(&cluster->cl_nodes_lock);
+ if (cluster->cl_nodes[tmp])
+ p = NULL;
+ else {
+ cluster->cl_nodes[tmp] = node;
+ node->nd_num = tmp;
+ set_bit(tmp, cluster->cl_nodes_bitmap);
+ }
+ write_unlock(&cluster->cl_nodes_lock);
+ if (p == NULL)
+ return -EEXIST;
+
+ return count;
+}
+static ssize_t o2nm_node_ipv4_port_read(struct o2nm_node *node, char *page)
+{
+ return sprintf(page, "%u\n", ntohs(node->nd_ipv4_port));
+}
+
+static ssize_t o2nm_node_ipv4_port_write(struct o2nm_node *node,
+ const char *page, size_t count)
+{
+ unsigned long tmp;
+ char *p = (char *)page;
+
+ tmp = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ if (tmp == 0)
+ return -EINVAL;
+ if (tmp >= (u16)-1)
+ return -ERANGE;
+
+ node->nd_ipv4_port = htons(tmp);
+
+ return count;
+}
+
+static ssize_t o2nm_node_ipv4_address_read(struct o2nm_node *node, char *page)
+{
+ return sprintf(page, "%u.%u.%u.%u\n", NIPQUAD(node->nd_ipv4_address));
+}
+
+static ssize_t o2nm_node_ipv4_address_write(struct o2nm_node *node,
+ const char *page,
+ size_t count)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
+ int ret, i;
+ struct rb_node **p, *parent;
+ unsigned int octets[4];
+ __be32 ipv4_addr = 0;
+
+ ret = sscanf(page, "%3u.%3u.%3u.%3u", &octets[3], &octets[2],
+ &octets[1], &octets[0]);
+ if (ret != 4)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(octets); i++) {
+ if (octets[i] > 255)
+ return -ERANGE;
+ be32_add_cpu(&ipv4_addr, octets[i] << (i * 8));
+ }
+
+ ret = 0;
+ write_lock(&cluster->cl_nodes_lock);
+ if (o2nm_node_ip_tree_lookup(cluster, ipv4_addr, &p, &parent))
+ ret = -EEXIST;
+ else {
+ rb_link_node(&node->nd_ip_node, parent, p);
+ rb_insert_color(&node->nd_ip_node, &cluster->cl_node_ip_tree);
+ }
+ write_unlock(&cluster->cl_nodes_lock);
+ if (ret)
+ return ret;
+
+ memcpy(&node->nd_ipv4_address, &ipv4_addr, sizeof(ipv4_addr));
+
+ return count;
+}
+
+static ssize_t o2nm_node_local_read(struct o2nm_node *node, char *page)
+{
+ return sprintf(page, "%d\n", node->nd_local);
+}
+
+static ssize_t o2nm_node_local_write(struct o2nm_node *node, const char *page,
+ size_t count)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster_from_node(node);
+ unsigned long tmp;
+ char *p = (char *)page;
+ ssize_t ret;
+
+ tmp = simple_strtoul(p, &p, 0);
+ if (!p || (*p && (*p != '\n')))
+ return -EINVAL;
+
+ tmp = !!tmp; /* boolean of whether this node wants to be local */
+
+ /* setting local turns on networking rx for now so we require having
+ * set everything else first */
+ if (!test_bit(O2NM_NODE_ATTR_ADDRESS, &node->nd_set_attributes) ||
+ !test_bit(O2NM_NODE_ATTR_NUM, &node->nd_set_attributes) ||
+ !test_bit(O2NM_NODE_ATTR_PORT, &node->nd_set_attributes))
+ return -EINVAL; /* XXX */
+
+ /* the only failure case is trying to set a new local node
+ * when a different one is already set */
+ if (tmp && tmp == cluster->cl_has_local &&
+ cluster->cl_local_node != node->nd_num)
+ return -EBUSY;
+
+ /* bring up the rx thread if we're setting the new local node. */
+ if (tmp && !cluster->cl_has_local) {
+ ret = o2net_start_listening(node);
+ if (ret)
+ return ret;
+ }
+
+ if (!tmp && cluster->cl_has_local &&
+ cluster->cl_local_node == node->nd_num) {
+ o2net_stop_listening(node);
+ cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
+ }
+
+ node->nd_local = tmp;
+ if (node->nd_local) {
+ cluster->cl_has_local = tmp;
+ cluster->cl_local_node = node->nd_num;
+ }
+
+ return count;
+}
+
+struct o2nm_node_attribute {
+ struct configfs_attribute attr;
+ ssize_t (*show)(struct o2nm_node *, char *);
+ ssize_t (*store)(struct o2nm_node *, const char *, size_t);
+};
+
+static struct o2nm_node_attribute o2nm_node_attr_num = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "num",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_node_num_read,
+ .store = o2nm_node_num_write,
+};
+
+static struct o2nm_node_attribute o2nm_node_attr_ipv4_port = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "ipv4_port",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_node_ipv4_port_read,
+ .store = o2nm_node_ipv4_port_write,
+};
+
+static struct o2nm_node_attribute o2nm_node_attr_ipv4_address = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "ipv4_address",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_node_ipv4_address_read,
+ .store = o2nm_node_ipv4_address_write,
+};
+
+static struct o2nm_node_attribute o2nm_node_attr_local = {
+ .attr = { .ca_owner = THIS_MODULE,
+ .ca_name = "local",
+ .ca_mode = S_IRUGO | S_IWUSR },
+ .show = o2nm_node_local_read,
+ .store = o2nm_node_local_write,
+};
+
+static struct configfs_attribute *o2nm_node_attrs[] = {
+ [O2NM_NODE_ATTR_NUM] = &o2nm_node_attr_num.attr,
+ [O2NM_NODE_ATTR_PORT] = &o2nm_node_attr_ipv4_port.attr,
+ [O2NM_NODE_ATTR_ADDRESS] = &o2nm_node_attr_ipv4_address.attr,
+ [O2NM_NODE_ATTR_LOCAL] = &o2nm_node_attr_local.attr,
+ NULL,
+};
+
+static int o2nm_attr_index(struct configfs_attribute *attr)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(o2nm_node_attrs); i++) {
+ if (attr == o2nm_node_attrs[i])
+ return i;
+ }
+ BUG();
+ return 0;
+}
+
+static ssize_t o2nm_node_show(struct config_item *item,
+ struct configfs_attribute *attr,
+ char *page)
+{
+ struct o2nm_node *node = to_o2nm_node(item);
+ struct o2nm_node_attribute *o2nm_node_attr =
+ container_of(attr, struct o2nm_node_attribute, attr);
+ ssize_t ret = 0;
+
+ if (o2nm_node_attr->show)
+ ret = o2nm_node_attr->show(node, page);
+ return ret;
+}
+
+static ssize_t o2nm_node_store(struct config_item *item,
+ struct configfs_attribute *attr,
+ const char *page, size_t count)
+{
+ struct o2nm_node *node = to_o2nm_node(item);
+ struct o2nm_node_attribute *o2nm_node_attr =
+ container_of(attr, struct o2nm_node_attribute, attr);
+ ssize_t ret;
+ int attr_index = o2nm_attr_index(attr);
+
+ if (o2nm_node_attr->store == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (test_bit(attr_index, &node->nd_set_attributes))
+ return -EBUSY;
+
+ ret = o2nm_node_attr->store(node, page, count);
+ if (ret < count)
+ goto out;
+
+ set_bit(attr_index, &node->nd_set_attributes);
+out:
+ return ret;
+}
+
+static struct configfs_item_operations o2nm_node_item_ops = {
+ .release = o2nm_node_release,
+ .show_attribute = o2nm_node_show,
+ .store_attribute = o2nm_node_store,
+};
+
+static struct config_item_type o2nm_node_type = {
+ .ct_item_ops = &o2nm_node_item_ops,
+ .ct_attrs = o2nm_node_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/* node set */
+
+struct o2nm_node_group {
+ struct config_group ns_group;
+ /* some stuff? */
+};
+
+#if 0
+static struct o2nm_node_group *to_o2nm_node_group(struct config_group *group)
+{
+ return group ?
+ container_of(group, struct o2nm_node_group, ns_group)
+ : NULL;
+}
+#endif
+
+static struct config_item *o2nm_node_group_make_item(struct config_group *group,
+ const char *name)
+{
+ struct o2nm_node *node = NULL;
+ struct config_item *ret = NULL;
+
+ if (strlen(name) > O2NM_MAX_NAME_LEN)
+ goto out; /* ENAMETOOLONG */
+
+ node = kcalloc(1, sizeof(struct o2nm_node), GFP_KERNEL);
+ if (node == NULL)
+ goto out; /* ENOMEM */
+
+ strcpy(node->nd_name, name); /* use item.ci_namebuf instead? */
+ config_item_init_type_name(&node->nd_item, name, &o2nm_node_type);
+ spin_lock_init(&node->nd_lock);
+
+ ret = &node->nd_item;
+
+out:
+ if (ret == NULL)
+ kfree(node);
+
+ return ret;
+}
+
+static void o2nm_node_group_drop_item(struct config_group *group,
+ struct config_item *item)
+{
+ struct o2nm_node *node = to_o2nm_node(item);
+ struct o2nm_cluster *cluster = to_o2nm_cluster(group->cg_item.ci_parent);
+
+ o2net_disconnect_node(node);
+
+ if (cluster->cl_has_local &&
+ (cluster->cl_local_node == node->nd_num)) {
+ cluster->cl_has_local = 0;
+ cluster->cl_local_node = O2NM_INVALID_NODE_NUM;
+ o2net_stop_listening(node);
+ }
+
+ /* XXX call into net to stop this node from trading messages */
+
+ write_lock(&cluster->cl_nodes_lock);
+
+ /* XXX sloppy */
+ if (node->nd_ipv4_address)
+ rb_erase(&node->nd_ip_node, &cluster->cl_node_ip_tree);
+
+ /* nd_num might be 0 if the node number hasn't been set.. */
+ if (cluster->cl_nodes[node->nd_num] == node) {
+ cluster->cl_nodes[node->nd_num] = NULL;
+ clear_bit(node->nd_num, cluster->cl_nodes_bitmap);
+ }
+ write_unlock(&cluster->cl_nodes_lock);
+
+ config_item_put(item);
+}
+
+static struct configfs_group_operations o2nm_node_group_group_ops = {
+ .make_item = o2nm_node_group_make_item,
+ .drop_item = o2nm_node_group_drop_item,
+};
+
+static struct config_item_type o2nm_node_group_type = {
+ .ct_group_ops = &o2nm_node_group_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+/* cluster */
+
+static void o2nm_cluster_release(struct config_item *item)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+
+ kfree(cluster->cl_group.default_groups);
+ kfree(cluster);
+}
+
+static struct configfs_item_operations o2nm_cluster_item_ops = {
+ .release = o2nm_cluster_release,
+};
+
+static struct config_item_type o2nm_cluster_type = {
+ .ct_item_ops = &o2nm_cluster_item_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+/* cluster set */
+
+struct o2nm_cluster_group {
+ struct configfs_subsystem cs_subsys;
+ /* some stuff? */
+};
+
+#if 0
+static struct o2nm_cluster_group *to_o2nm_cluster_group(struct config_group *group)
+{
+ return group ?
+ container_of(to_configfs_subsystem(group), struct o2nm_cluster_group, cs_subsys)
+ : NULL;
+}
+#endif
+
+static struct config_group *o2nm_cluster_group_make_group(struct config_group *group,
+ const char *name)
+{
+ struct o2nm_cluster *cluster = NULL;
+ struct o2nm_node_group *ns = NULL;
+ struct config_group *o2hb_group = NULL, *ret = NULL;
+ void *defs = NULL;
+
+ /* this runs under the parent dir's i_mutex; there can be only
+ * one caller in here at a time */
+ if (o2nm_single_cluster)
+ goto out; /* ENOSPC */
+
+ cluster = kcalloc(1, sizeof(struct o2nm_cluster), GFP_KERNEL);
+ ns = kcalloc(1, sizeof(struct o2nm_node_group), GFP_KERNEL);
+ defs = kcalloc(3, sizeof(struct config_group *), GFP_KERNEL);
+ o2hb_group = o2hb_alloc_hb_set();
+ if (cluster == NULL || ns == NULL || o2hb_group == NULL || defs == NULL)
+ goto out;
+
+ config_group_init_type_name(&cluster->cl_group, name,
+ &o2nm_cluster_type);
+ config_group_init_type_name(&ns->ns_group, "node",
+ &o2nm_node_group_type);
+
+ cluster->cl_group.default_groups = defs;
+ cluster->cl_group.default_groups[0] = &ns->ns_group;
+ cluster->cl_group.default_groups[1] = o2hb_group;
+ cluster->cl_group.default_groups[2] = NULL;
+ rwlock_init(&cluster->cl_nodes_lock);
+ cluster->cl_node_ip_tree = RB_ROOT;
+
+ ret = &cluster->cl_group;
+ o2nm_single_cluster = cluster;
+
+out:
+ if (ret == NULL) {
+ kfree(cluster);
+ kfree(ns);
+ o2hb_free_hb_set(o2hb_group);
+ kfree(defs);
+ }
+
+ return ret;
+}
+
+static void o2nm_cluster_group_drop_item(struct config_group *group, struct config_item *item)
+{
+ struct o2nm_cluster *cluster = to_o2nm_cluster(item);
+ int i;
+ struct config_item *killme;
+
+ BUG_ON(o2nm_single_cluster != cluster);
+ o2nm_single_cluster = NULL;
+
+ for (i = 0; cluster->cl_group.default_groups[i]; i++) {
+ killme = &cluster->cl_group.default_groups[i]->cg_item;
+ cluster->cl_group.default_groups[i] = NULL;
+ config_item_put(killme);
+ }
+
+ config_item_put(item);
+}
+
+static struct configfs_group_operations o2nm_cluster_group_group_ops = {
+ .make_group = o2nm_cluster_group_make_group,
+ .drop_item = o2nm_cluster_group_drop_item,
+};
+
+static struct config_item_type o2nm_cluster_group_type = {
+ .ct_group_ops = &o2nm_cluster_group_group_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct o2nm_cluster_group o2nm_cluster_group = {
+ .cs_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "cluster",
+ .ci_type = &o2nm_cluster_group_type,
+ },
+ },
+ },
+};
+
+static void __exit exit_o2nm(void)
+{
+ if (ocfs2_table_header)
+ unregister_sysctl_table(ocfs2_table_header);
+
+ /* XXX sync with hb callbacks and shut down hb? */
+ o2net_unregister_hb_callbacks();
+ configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
+ o2cb_sys_shutdown();
+
+ o2net_exit();
+}
+
+static int __init init_o2nm(void)
+{
+ int ret = -1;
+
+ cluster_print_version();
+
+ o2hb_init();
+ o2net_init();
+
+ ocfs2_table_header = register_sysctl_table(ocfs2_root_table, 0);
+ if (!ocfs2_table_header) {
+ printk(KERN_ERR "nodemanager: unable to register sysctl\n");
+ ret = -ENOMEM; /* or something. */
+ goto out;
+ }
+
+ ret = o2net_register_hb_callbacks();
+ if (ret)
+ goto out_sysctl;
+
+ config_group_init(&o2nm_cluster_group.cs_subsys.su_group);
+ init_MUTEX(&o2nm_cluster_group.cs_subsys.su_sem);
+ ret = configfs_register_subsystem(&o2nm_cluster_group.cs_subsys);
+ if (ret) {
+ printk(KERN_ERR "nodemanager: Registration returned %d\n", ret);
+ goto out_callbacks;
+ }
+
+ ret = o2cb_sys_init();
+ if (!ret)
+ goto out;
+
+ configfs_unregister_subsystem(&o2nm_cluster_group.cs_subsys);
+out_callbacks:
+ o2net_unregister_hb_callbacks();
+out_sysctl:
+ unregister_sysctl_table(ocfs2_table_header);
+out:
+ return ret;
+}
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+
+module_init(init_o2nm)
+module_exit(exit_o2nm)
diff --git a/fs/ocfs2/cluster/nodemanager.h b/fs/ocfs2/cluster/nodemanager.h
new file mode 100644
index 000000000000..fce8033c310f
--- /dev/null
+++ b/fs/ocfs2/cluster/nodemanager.h
@@ -0,0 +1,64 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * nodemanager.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef O2CLUSTER_NODEMANAGER_H
+#define O2CLUSTER_NODEMANAGER_H
+
+#include "ocfs2_nodemanager.h"
+
+/* This totally doesn't belong here. */
+#include <linux/configfs.h>
+#include <linux/rbtree.h>
+
+#define KERN_OCFS2 988
+#define KERN_OCFS2_NM 1
+
+const char *o2nm_get_hb_ctl_path(void);
+
+struct o2nm_node {
+ spinlock_t nd_lock;
+ struct config_item nd_item;
+ char nd_name[O2NM_MAX_NAME_LEN+1]; /* replace? */
+ __u8 nd_num;
+ /* only one address per node, as attributes, for now. */
+ __be32 nd_ipv4_address;
+ __be16 nd_ipv4_port;
+ struct rb_node nd_ip_node;
+ /* there can be only one local node for now */
+ int nd_local;
+
+ unsigned long nd_set_attributes;
+};
+
+u8 o2nm_this_node(void);
+
+int o2nm_configured_node_map(unsigned long *map, unsigned bytes);
+struct o2nm_node *o2nm_get_node_by_num(u8 node_num);
+struct o2nm_node *o2nm_get_node_by_ip(__be32 addr);
+void o2nm_node_get(struct o2nm_node *node);
+void o2nm_node_put(struct o2nm_node *node);
+
+#endif /* O2CLUSTER_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/ocfs2_heartbeat.h b/fs/ocfs2/cluster/ocfs2_heartbeat.h
new file mode 100644
index 000000000000..94096069cb43
--- /dev/null
+++ b/fs/ocfs2/cluster/ocfs2_heartbeat.h
@@ -0,0 +1,37 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_heartbeat.h
+ *
+ * On-disk structures for ocfs2_heartbeat
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef _OCFS2_HEARTBEAT_H
+#define _OCFS2_HEARTBEAT_H
+
+struct o2hb_disk_heartbeat_block {
+ __le64 hb_seq;
+ __u8 hb_node;
+ __u8 hb_pad1[3];
+ __le32 hb_cksum;
+ __le64 hb_generation;
+};
+
+#endif /* _OCFS2_HEARTBEAT_H */
diff --git a/fs/ocfs2/cluster/ocfs2_nodemanager.h b/fs/ocfs2/cluster/ocfs2_nodemanager.h
new file mode 100644
index 000000000000..5b9854bad571
--- /dev/null
+++ b/fs/ocfs2/cluster/ocfs2_nodemanager.h
@@ -0,0 +1,39 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_nodemanager.h
+ *
+ * Header describing the interface between userspace and the kernel
+ * for the ocfs2_nodemanager module.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef _OCFS2_NODEMANAGER_H
+#define _OCFS2_NODEMANAGER_H
+
+#define O2NM_API_VERSION 5
+
+#define O2NM_MAX_NODES 255
+#define O2NM_INVALID_NODE_NUM 255
+
+/* host name, group name, cluster name all 64 bytes */
+#define O2NM_MAX_NAME_LEN 64 // __NEW_UTS_LEN
+
+#endif /* _OCFS2_NODEMANAGER_H */
diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c
new file mode 100644
index 000000000000..7bba98fbfc15
--- /dev/null
+++ b/fs/ocfs2/cluster/quorum.c
@@ -0,0 +1,315 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ *
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+/* This quorum hack is only here until we transition to some more rational
+ * approach that is driven from userspace. Honest. No foolin'.
+ *
+ * Imagine two nodes lose network connectivity to each other but they're still
+ * up and operating in every other way. Presumably a network timeout indicates
+ * that a node is broken and should be recovered. They can't both recover each
+ * other and both carry on without serialising their access to the file system.
+ * They need to decide who is authoritative. Now extend that problem to
+ * arbitrary groups of nodes losing connectivity between each other.
+ *
+ * So we declare that a node which has given up on connecting to a majority
+ * of nodes who are still heartbeating will fence itself.
+ *
+ * There are huge opportunities for races here. After we give up on a node's
+ * connection we need to wait long enough to give heartbeat an opportunity
+ * to declare the node as truly dead. We also need to be careful with the
+ * race between when we see a node start heartbeating and when we connect
+ * to it.
+ *
+ * So nodes that are in this transtion put a hold on the quorum decision
+ * with a counter. As they fall out of this transition they drop the count
+ * and if they're the last, they fire off the decision.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include "heartbeat.h"
+#include "nodemanager.h"
+#define MLOG_MASK_PREFIX ML_QUORUM
+#include "masklog.h"
+#include "quorum.h"
+
+static struct o2quo_state {
+ spinlock_t qs_lock;
+ struct work_struct qs_work;
+ int qs_pending;
+ int qs_heartbeating;
+ unsigned long qs_hb_bm[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ int qs_connected;
+ unsigned long qs_conn_bm[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ int qs_holds;
+ unsigned long qs_hold_bm[BITS_TO_LONGS(O2NM_MAX_NODES)];
+} o2quo_state;
+
+/* this is horribly heavy-handed. It should instead flip the file
+ * system RO and call some userspace script. */
+static void o2quo_fence_self(void)
+{
+ /* panic spins with interrupts enabled. with preempt
+ * threads can still schedule, etc, etc */
+ o2hb_stop_all_regions();
+ panic("ocfs2 is very sorry to be fencing this system by panicing\n");
+}
+
+/* Indicate that a timeout occured on a hearbeat region write. The
+ * other nodes in the cluster may consider us dead at that time so we
+ * want to "fence" ourselves so that we don't scribble on the disk
+ * after they think they've recovered us. This can't solve all
+ * problems related to writeout after recovery but this hack can at
+ * least close some of those gaps. When we have real fencing, this can
+ * go away as our node would be fenced externally before other nodes
+ * begin recovery. */
+void o2quo_disk_timeout(void)
+{
+ o2quo_fence_self();
+}
+
+static void o2quo_make_decision(void *arg)
+{
+ int quorum;
+ int lowest_hb, lowest_reachable = 0, fence = 0;
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ lowest_hb = find_first_bit(qs->qs_hb_bm, O2NM_MAX_NODES);
+ if (lowest_hb != O2NM_MAX_NODES)
+ lowest_reachable = test_bit(lowest_hb, qs->qs_conn_bm);
+
+ mlog(0, "heartbeating: %d, connected: %d, "
+ "lowest: %d (%sreachable)\n", qs->qs_heartbeating,
+ qs->qs_connected, lowest_hb, lowest_reachable ? "" : "un");
+
+ if (!test_bit(o2nm_this_node(), qs->qs_hb_bm) ||
+ qs->qs_heartbeating == 1)
+ goto out;
+
+ if (qs->qs_heartbeating & 1) {
+ /* the odd numbered cluster case is straight forward --
+ * if we can't talk to the majority we're hosed */
+ quorum = (qs->qs_heartbeating + 1)/2;
+ if (qs->qs_connected < quorum) {
+ mlog(ML_ERROR, "fencing this node because it is "
+ "only connected to %u nodes and %u is needed "
+ "to make a quorum out of %u heartbeating nodes\n",
+ qs->qs_connected, quorum,
+ qs->qs_heartbeating);
+ fence = 1;
+ }
+ } else {
+ /* the even numbered cluster adds the possibility of each half
+ * of the cluster being able to talk amongst themselves.. in
+ * that case we're hosed if we can't talk to the group that has
+ * the lowest numbered node */
+ quorum = qs->qs_heartbeating / 2;
+ if (qs->qs_connected < quorum) {
+ mlog(ML_ERROR, "fencing this node because it is "
+ "only connected to %u nodes and %u is needed "
+ "to make a quorum out of %u heartbeating nodes\n",
+ qs->qs_connected, quorum,
+ qs->qs_heartbeating);
+ fence = 1;
+ }
+ else if ((qs->qs_connected == quorum) &&
+ !lowest_reachable) {
+ mlog(ML_ERROR, "fencing this node because it is "
+ "connected to a half-quorum of %u out of %u "
+ "nodes which doesn't include the lowest active "
+ "node %u\n", quorum, qs->qs_heartbeating,
+ lowest_hb);
+ fence = 1;
+ }
+ }
+
+out:
+ spin_unlock(&qs->qs_lock);
+ if (fence)
+ o2quo_fence_self();
+}
+
+static void o2quo_set_hold(struct o2quo_state *qs, u8 node)
+{
+ assert_spin_locked(&qs->qs_lock);
+
+ if (!test_and_set_bit(node, qs->qs_hold_bm)) {
+ qs->qs_holds++;
+ mlog_bug_on_msg(qs->qs_holds == O2NM_MAX_NODES,
+ "node %u\n", node);
+ mlog(0, "node %u, %d total\n", node, qs->qs_holds);
+ }
+}
+
+static void o2quo_clear_hold(struct o2quo_state *qs, u8 node)
+{
+ assert_spin_locked(&qs->qs_lock);
+
+ if (test_and_clear_bit(node, qs->qs_hold_bm)) {
+ mlog(0, "node %u, %d total\n", node, qs->qs_holds - 1);
+ if (--qs->qs_holds == 0) {
+ if (qs->qs_pending) {
+ qs->qs_pending = 0;
+ schedule_work(&qs->qs_work);
+ }
+ }
+ mlog_bug_on_msg(qs->qs_holds < 0, "node %u, holds %d\n",
+ node, qs->qs_holds);
+ }
+}
+
+/* as a node comes up we delay the quorum decision until we know the fate of
+ * the connection. the hold will be droped in conn_up or hb_down. it might be
+ * perpetuated by con_err until hb_down. if we already have a conn, we might
+ * be dropping a hold that conn_up got. */
+void o2quo_hb_up(u8 node)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ qs->qs_heartbeating++;
+ mlog_bug_on_msg(qs->qs_heartbeating == O2NM_MAX_NODES,
+ "node %u\n", node);
+ mlog_bug_on_msg(test_bit(node, qs->qs_hb_bm), "node %u\n", node);
+ set_bit(node, qs->qs_hb_bm);
+
+ mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating);
+
+ if (!test_bit(node, qs->qs_conn_bm))
+ o2quo_set_hold(qs, node);
+ else
+ o2quo_clear_hold(qs, node);
+
+ spin_unlock(&qs->qs_lock);
+}
+
+/* hb going down releases any holds we might have had due to this node from
+ * conn_up, conn_err, or hb_up */
+void o2quo_hb_down(u8 node)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ qs->qs_heartbeating--;
+ mlog_bug_on_msg(qs->qs_heartbeating < 0,
+ "node %u, %d heartbeating\n",
+ node, qs->qs_heartbeating);
+ mlog_bug_on_msg(!test_bit(node, qs->qs_hb_bm), "node %u\n", node);
+ clear_bit(node, qs->qs_hb_bm);
+
+ mlog(0, "node %u, %d total\n", node, qs->qs_heartbeating);
+
+ o2quo_clear_hold(qs, node);
+
+ spin_unlock(&qs->qs_lock);
+}
+
+/* this tells us that we've decided that the node is still heartbeating
+ * even though we've lost it's conn. it must only be called after conn_err
+ * and indicates that we must now make a quorum decision in the future,
+ * though we might be doing so after waiting for holds to drain. Here
+ * we'll be dropping the hold from conn_err. */
+void o2quo_hb_still_up(u8 node)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ mlog(0, "node %u\n", node);
+
+ qs->qs_pending = 1;
+ o2quo_clear_hold(qs, node);
+
+ spin_unlock(&qs->qs_lock);
+}
+
+/* This is analagous to hb_up. as a node's connection comes up we delay the
+ * quorum decision until we see it heartbeating. the hold will be droped in
+ * hb_up or hb_down. it might be perpetuated by con_err until hb_down. if
+ * it's already heartbeating we we might be dropping a hold that conn_up got.
+ * */
+void o2quo_conn_up(u8 node)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ qs->qs_connected++;
+ mlog_bug_on_msg(qs->qs_connected == O2NM_MAX_NODES,
+ "node %u\n", node);
+ mlog_bug_on_msg(test_bit(node, qs->qs_conn_bm), "node %u\n", node);
+ set_bit(node, qs->qs_conn_bm);
+
+ mlog(0, "node %u, %d total\n", node, qs->qs_connected);
+
+ if (!test_bit(node, qs->qs_hb_bm))
+ o2quo_set_hold(qs, node);
+ else
+ o2quo_clear_hold(qs, node);
+
+ spin_unlock(&qs->qs_lock);
+}
+
+/* we've decided that we won't ever be connecting to the node again. if it's
+ * still heartbeating we grab a hold that will delay decisions until either the
+ * node stops heartbeating from hb_down or the caller decides that the node is
+ * still up and calls still_up */
+void o2quo_conn_err(u8 node)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock(&qs->qs_lock);
+
+ if (test_bit(node, qs->qs_conn_bm)) {
+ qs->qs_connected--;
+ mlog_bug_on_msg(qs->qs_connected < 0,
+ "node %u, connected %d\n",
+ node, qs->qs_connected);
+
+ clear_bit(node, qs->qs_conn_bm);
+ }
+
+ mlog(0, "node %u, %d total\n", node, qs->qs_connected);
+
+ if (test_bit(node, qs->qs_hb_bm))
+ o2quo_set_hold(qs, node);
+
+ spin_unlock(&qs->qs_lock);
+}
+
+void o2quo_init(void)
+{
+ struct o2quo_state *qs = &o2quo_state;
+
+ spin_lock_init(&qs->qs_lock);
+ INIT_WORK(&qs->qs_work, o2quo_make_decision, NULL);
+}
+
+void o2quo_exit(void)
+{
+ flush_scheduled_work();
+}
diff --git a/fs/ocfs2/cluster/quorum.h b/fs/ocfs2/cluster/quorum.h
new file mode 100644
index 000000000000..6649cc6f67c9
--- /dev/null
+++ b/fs/ocfs2/cluster/quorum.h
@@ -0,0 +1,36 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef O2CLUSTER_QUORUM_H
+#define O2CLUSTER_QUORUM_H
+
+void o2quo_init(void);
+void o2quo_exit(void);
+
+void o2quo_hb_up(u8 node);
+void o2quo_hb_down(u8 node);
+void o2quo_hb_still_up(u8 node);
+void o2quo_conn_up(u8 node);
+void o2quo_conn_err(u8 node);
+void o2quo_disk_timeout(void);
+
+#endif /* O2CLUSTER_QUORUM_H */
diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c
new file mode 100644
index 000000000000..1d9f6acafa2e
--- /dev/null
+++ b/fs/ocfs2/cluster/sys.c
@@ -0,0 +1,124 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * sys.c
+ *
+ * OCFS2 cluster sysfs interface
+ *
+ * Copyright (C) 2005 Oracle. 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,
+ * 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 021110-1307, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+#include "ocfs2_nodemanager.h"
+#include "masklog.h"
+#include "sys.h"
+
+struct o2cb_attribute {
+ struct attribute attr;
+ ssize_t (*show)(char *buf);
+ ssize_t (*store)(const char *buf, size_t count);
+};
+
+#define O2CB_ATTR(_name, _mode, _show, _store) \
+struct o2cb_attribute o2cb_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+#define to_o2cb_subsys(k) container_of(to_kset(k), struct subsystem, kset)
+#define to_o2cb_attr(_attr) container_of(_attr, struct o2cb_attribute, attr)
+
+static ssize_t o2cb_interface_revision_show(char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", O2NM_API_VERSION);
+}
+
+static O2CB_ATTR(interface_revision, S_IFREG | S_IRUGO, o2cb_interface_revision_show, NULL);
+
+static struct attribute *o2cb_attrs[] = {
+ &o2cb_attr_interface_revision.attr,
+ NULL,
+};
+
+static ssize_t
+o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer);
+static ssize_t
+o2cb_store(struct kobject * kobj, struct attribute * attr,
+ const char * buffer, size_t count);
+static struct sysfs_ops o2cb_sysfs_ops = {
+ .show = o2cb_show,
+ .store = o2cb_store,
+};
+
+static struct kobj_type o2cb_subsys_type = {
+ .default_attrs = o2cb_attrs,
+ .sysfs_ops = &o2cb_sysfs_ops,
+};
+
+/* gives us o2cb_subsys */
+static decl_subsys(o2cb, NULL, NULL);
+
+static ssize_t
+o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer)
+{
+ struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
+ struct subsystem *sbs = to_o2cb_subsys(kobj);
+
+ BUG_ON(sbs != &o2cb_subsys);
+
+ if (o2cb_attr->show)
+ return o2cb_attr->show(buffer);
+ return -EIO;
+}
+
+static ssize_t
+o2cb_store(struct kobject * kobj, struct attribute * attr,
+ const char * buffer, size_t count)
+{
+ struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr);
+ struct subsystem *sbs = to_o2cb_subsys(kobj);
+
+ BUG_ON(sbs != &o2cb_subsys);
+
+ if (o2cb_attr->store)
+ return o2cb_attr->store(buffer, count);
+ return -EIO;
+}
+
+void o2cb_sys_shutdown(void)
+{
+ mlog_sys_shutdown();
+ subsystem_unregister(&o2cb_subsys);
+}
+
+int o2cb_sys_init(void)
+{
+ int ret;
+
+ o2cb_subsys.kset.kobj.ktype = &o2cb_subsys_type;
+ ret = subsystem_register(&o2cb_subsys);
+ if (ret)
+ return ret;
+
+ ret = mlog_sys_init(&o2cb_subsys);
+ if (ret)
+ subsystem_unregister(&o2cb_subsys);
+ return ret;
+}
diff --git a/fs/ocfs2/cluster/sys.h b/fs/ocfs2/cluster/sys.h
new file mode 100644
index 000000000000..d66b8ab0045e
--- /dev/null
+++ b/fs/ocfs2/cluster/sys.h
@@ -0,0 +1,33 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * sys.h
+ *
+ * Function prototypes for o2cb sysfs interface
+ *
+ * Copyright (C) 2005 Oracle. 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,
+ * 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 021110-1307, USA.
+ *
+ */
+
+#ifndef O2CLUSTER_SYS_H
+#define O2CLUSTER_SYS_H
+
+void o2cb_sys_shutdown(void);
+int o2cb_sys_init(void);
+
+#endif /* O2CLUSTER_SYS_H */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
new file mode 100644
index 000000000000..35d92c01a972
--- /dev/null
+++ b/fs/ocfs2/cluster/tcp.c
@@ -0,0 +1,1829 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ *
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ * ----
+ *
+ * Callers for this were originally written against a very simple synchronus
+ * API. This implementation reflects those simple callers. Some day I'm sure
+ * we'll need to move to a more robust posting/callback mechanism.
+ *
+ * Transmit calls pass in kernel virtual addresses and block copying this into
+ * the socket's tx buffers via a usual blocking sendmsg. They'll block waiting
+ * for a failed socket to timeout. TX callers can also pass in a poniter to an
+ * 'int' which gets filled with an errno off the wire in response to the
+ * message they send.
+ *
+ * Handlers for unsolicited messages are registered. Each socket has a page
+ * that incoming data is copied into. First the header, then the data.
+ * Handlers are called from only one thread with a reference to this per-socket
+ * page. This page is destroyed after the handler call, so it can't be
+ * referenced beyond the call. Handlers may block but are discouraged from
+ * doing so.
+ *
+ * Any framing errors (bad magic, large payload lengths) close a connection.
+ *
+ * Our sock_container holds the state we associate with a socket. It's current
+ * framing state is held there as well as the refcounting we do around when it
+ * is safe to tear down the socket. The socket is only finally torn down from
+ * the container when the container loses all of its references -- so as long
+ * as you hold a ref on the container you can trust that the socket is valid
+ * for use with kernel socket APIs.
+ *
+ * Connections are initiated between a pair of nodes when the node with the
+ * higher node number gets a heartbeat callback which indicates that the lower
+ * numbered node has started heartbeating. The lower numbered node is passive
+ * and only accepts the connection if the higher numbered node is heartbeating.
+ */
+
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/kref.h>
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+
+#include "heartbeat.h"
+#include "tcp.h"
+#include "nodemanager.h"
+#define MLOG_MASK_PREFIX ML_TCP
+#include "masklog.h"
+#include "quorum.h"
+
+#include "tcp_internal.h"
+
+/*
+ * The linux network stack isn't sparse endian clean.. It has macros like
+ * ntohs() which perform the endian checks and structs like sockaddr_in
+ * which aren't annotated. So __force is found here to get the build
+ * clean. When they emerge from the dark ages and annotate the code
+ * we can remove these.
+ */
+
+#define SC_NODEF_FMT "node %s (num %u) at %u.%u.%u.%u:%u"
+#define SC_NODEF_ARGS(sc) sc->sc_node->nd_name, sc->sc_node->nd_num, \
+ NIPQUAD(sc->sc_node->nd_ipv4_address), \
+ ntohs(sc->sc_node->nd_ipv4_port)
+
+/*
+ * In the following two log macros, the whitespace after the ',' just
+ * before ##args is intentional. Otherwise, gcc 2.95 will eat the
+ * previous token if args expands to nothing.
+ */
+#define msglog(hdr, fmt, args...) do { \
+ typeof(hdr) __hdr = (hdr); \
+ mlog(ML_MSG, "[mag %u len %u typ %u stat %d sys_stat %d " \
+ "key %08x num %u] " fmt, \
+ be16_to_cpu(__hdr->magic), be16_to_cpu(__hdr->data_len), \
+ be16_to_cpu(__hdr->msg_type), be32_to_cpu(__hdr->status), \
+ be32_to_cpu(__hdr->sys_status), be32_to_cpu(__hdr->key), \
+ be32_to_cpu(__hdr->msg_num) , ##args); \
+} while (0)
+
+#define sclog(sc, fmt, args...) do { \
+ typeof(sc) __sc = (sc); \
+ mlog(ML_SOCKET, "[sc %p refs %d sock %p node %u page %p " \
+ "pg_off %zu] " fmt, __sc, \
+ atomic_read(&__sc->sc_kref.refcount), __sc->sc_sock, \
+ __sc->sc_node->nd_num, __sc->sc_page, __sc->sc_page_off , \
+ ##args); \
+} while (0)
+
+static rwlock_t o2net_handler_lock = RW_LOCK_UNLOCKED;
+static struct rb_root o2net_handler_tree = RB_ROOT;
+
+static struct o2net_node o2net_nodes[O2NM_MAX_NODES];
+
+/* XXX someday we'll need better accounting */
+static struct socket *o2net_listen_sock = NULL;
+
+/*
+ * listen work is only queued by the listening socket callbacks on the
+ * o2net_wq. teardown detaches the callbacks before destroying the workqueue.
+ * quorum work is queued as sock containers are shutdown.. stop_listening
+ * tears down all the node's sock containers, preventing future shutdowns
+ * and queued quroum work, before canceling delayed quorum work and
+ * destroying the work queue.
+ */
+static struct workqueue_struct *o2net_wq;
+static struct work_struct o2net_listen_work;
+
+static struct o2hb_callback_func o2net_hb_up, o2net_hb_down;
+#define O2NET_HB_PRI 0x1
+
+static struct o2net_handshake *o2net_hand;
+static struct o2net_msg *o2net_keep_req, *o2net_keep_resp;
+
+static int o2net_sys_err_translations[O2NET_ERR_MAX] =
+ {[O2NET_ERR_NONE] = 0,
+ [O2NET_ERR_NO_HNDLR] = -ENOPROTOOPT,
+ [O2NET_ERR_OVERFLOW] = -EOVERFLOW,
+ [O2NET_ERR_DIED] = -EHOSTDOWN,};
+
+/* can't quite avoid *all* internal declarations :/ */
+static void o2net_sc_connect_completed(void *arg);
+static void o2net_rx_until_empty(void *arg);
+static void o2net_shutdown_sc(void *arg);
+static void o2net_listen_data_ready(struct sock *sk, int bytes);
+static void o2net_sc_send_keep_req(void *arg);
+static void o2net_idle_timer(unsigned long data);
+static void o2net_sc_postpone_idle(struct o2net_sock_container *sc);
+
+static inline int o2net_sys_err_to_errno(enum o2net_system_error err)
+{
+ int trans;
+ BUG_ON(err >= O2NET_ERR_MAX);
+ trans = o2net_sys_err_translations[err];
+
+ /* Just in case we mess up the translation table above */
+ BUG_ON(err != O2NET_ERR_NONE && trans == 0);
+ return trans;
+}
+
+static struct o2net_node * o2net_nn_from_num(u8 node_num)
+{
+ BUG_ON(node_num >= ARRAY_SIZE(o2net_nodes));
+ return &o2net_nodes[node_num];
+}
+
+static u8 o2net_num_from_nn(struct o2net_node *nn)
+{
+ BUG_ON(nn == NULL);
+ return nn - o2net_nodes;
+}
+
+/* ------------------------------------------------------------ */
+
+static int o2net_prep_nsw(struct o2net_node *nn, struct o2net_status_wait *nsw)
+{
+ int ret = 0;
+
+ do {
+ if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) {
+ ret = -EAGAIN;
+ break;
+ }
+ spin_lock(&nn->nn_lock);
+ ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id);
+ if (ret == 0)
+ list_add_tail(&nsw->ns_node_item,
+ &nn->nn_status_list);
+ spin_unlock(&nn->nn_lock);
+ } while (ret == -EAGAIN);
+
+ if (ret == 0) {
+ init_waitqueue_head(&nsw->ns_wq);
+ nsw->ns_sys_status = O2NET_ERR_NONE;
+ nsw->ns_status = 0;
+ }
+
+ return ret;
+}
+
+static void o2net_complete_nsw_locked(struct o2net_node *nn,
+ struct o2net_status_wait *nsw,
+ enum o2net_system_error sys_status,
+ s32 status)
+{
+ assert_spin_locked(&nn->nn_lock);
+
+ if (!list_empty(&nsw->ns_node_item)) {
+ list_del_init(&nsw->ns_node_item);
+ nsw->ns_sys_status = sys_status;
+ nsw->ns_status = status;
+ idr_remove(&nn->nn_status_idr, nsw->ns_id);
+ wake_up(&nsw->ns_wq);
+ }
+}
+
+static void o2net_complete_nsw(struct o2net_node *nn,
+ struct o2net_status_wait *nsw,
+ u64 id, enum o2net_system_error sys_status,
+ s32 status)
+{
+ spin_lock(&nn->nn_lock);
+ if (nsw == NULL) {
+ if (id > INT_MAX)
+ goto out;
+
+ nsw = idr_find(&nn->nn_status_idr, id);
+ if (nsw == NULL)
+ goto out;
+ }
+
+ o2net_complete_nsw_locked(nn, nsw, sys_status, status);
+
+out:
+ spin_unlock(&nn->nn_lock);
+ return;
+}
+
+static void o2net_complete_nodes_nsw(struct o2net_node *nn)
+{
+ struct list_head *iter, *tmp;
+ unsigned int num_kills = 0;
+ struct o2net_status_wait *nsw;
+
+ assert_spin_locked(&nn->nn_lock);
+
+ list_for_each_safe(iter, tmp, &nn->nn_status_list) {
+ nsw = list_entry(iter, struct o2net_status_wait, ns_node_item);
+ o2net_complete_nsw_locked(nn, nsw, O2NET_ERR_DIED, 0);
+ num_kills++;
+ }
+
+ mlog(0, "completed %d messages for node %u\n", num_kills,
+ o2net_num_from_nn(nn));
+}
+
+static int o2net_nsw_completed(struct o2net_node *nn,
+ struct o2net_status_wait *nsw)
+{
+ int completed;
+ spin_lock(&nn->nn_lock);
+ completed = list_empty(&nsw->ns_node_item);
+ spin_unlock(&nn->nn_lock);
+ return completed;
+}
+
+/* ------------------------------------------------------------ */
+
+static void sc_kref_release(struct kref *kref)
+{
+ struct o2net_sock_container *sc = container_of(kref,
+ struct o2net_sock_container, sc_kref);
+ sclog(sc, "releasing\n");
+
+ if (sc->sc_sock) {
+ sock_release(sc->sc_sock);
+ sc->sc_sock = NULL;
+ }
+
+ o2nm_node_put(sc->sc_node);
+ sc->sc_node = NULL;
+
+ kfree(sc);
+}
+
+static void sc_put(struct o2net_sock_container *sc)
+{
+ sclog(sc, "put\n");
+ kref_put(&sc->sc_kref, sc_kref_release);
+}
+static void sc_get(struct o2net_sock_container *sc)
+{
+ sclog(sc, "get\n");
+ kref_get(&sc->sc_kref);
+}
+static struct o2net_sock_container *sc_alloc(struct o2nm_node *node)
+{
+ struct o2net_sock_container *sc, *ret = NULL;
+ struct page *page = NULL;
+
+ page = alloc_page(GFP_NOFS);
+ sc = kcalloc(1, sizeof(*sc), GFP_NOFS);
+ if (sc == NULL || page == NULL)
+ goto out;
+
+ kref_init(&sc->sc_kref);
+ o2nm_node_get(node);
+ sc->sc_node = node;
+
+ INIT_WORK(&sc->sc_connect_work, o2net_sc_connect_completed, sc);
+ INIT_WORK(&sc->sc_rx_work, o2net_rx_until_empty, sc);
+ INIT_WORK(&sc->sc_shutdown_work, o2net_shutdown_sc, sc);
+ INIT_WORK(&sc->sc_keepalive_work, o2net_sc_send_keep_req, sc);
+
+ init_timer(&sc->sc_idle_timeout);
+ sc->sc_idle_timeout.function = o2net_idle_timer;
+ sc->sc_idle_timeout.data = (unsigned long)sc;
+
+ sclog(sc, "alloced\n");
+
+ ret = sc;
+ sc->sc_page = page;
+ sc = NULL;
+ page = NULL;
+
+out:
+ if (page)
+ __free_page(page);
+ kfree(sc);
+
+ return ret;
+}
+
+/* ------------------------------------------------------------ */
+
+static void o2net_sc_queue_work(struct o2net_sock_container *sc,
+ struct work_struct *work)
+{
+ sc_get(sc);
+ if (!queue_work(o2net_wq, work))
+ sc_put(sc);
+}
+static void o2net_sc_queue_delayed_work(struct o2net_sock_container *sc,
+ struct work_struct *work,
+ int delay)
+{
+ sc_get(sc);
+ if (!queue_delayed_work(o2net_wq, work, delay))
+ sc_put(sc);
+}
+static void o2net_sc_cancel_delayed_work(struct o2net_sock_container *sc,
+ struct work_struct *work)
+{
+ if (cancel_delayed_work(work))
+ sc_put(sc);
+}
+
+static void o2net_set_nn_state(struct o2net_node *nn,
+ struct o2net_sock_container *sc,
+ unsigned valid, int err)
+{
+ int was_valid = nn->nn_sc_valid;
+ int was_err = nn->nn_persistent_error;
+ struct o2net_sock_container *old_sc = nn->nn_sc;
+
+ assert_spin_locked(&nn->nn_lock);
+
+ /* the node num comparison and single connect/accept path should stop
+ * an non-null sc from being overwritten with another */
+ BUG_ON(sc && nn->nn_sc && nn->nn_sc != sc);
+ mlog_bug_on_msg(err && valid, "err %d valid %u\n", err, valid);
+ mlog_bug_on_msg(valid && !sc, "valid %u sc %p\n", valid, sc);
+
+ /* we won't reconnect after our valid conn goes away for
+ * this hb iteration.. here so it shows up in the logs */
+ if (was_valid && !valid && err == 0)
+ err = -ENOTCONN;
+
+ mlog(ML_CONN, "node %u sc: %p -> %p, valid %u -> %u, err %d -> %d\n",
+ o2net_num_from_nn(nn), nn->nn_sc, sc, nn->nn_sc_valid, valid,
+ nn->nn_persistent_error, err);
+
+ nn->nn_sc = sc;
+ nn->nn_sc_valid = valid ? 1 : 0;
+ nn->nn_persistent_error = err;
+
+ /* mirrors o2net_tx_can_proceed() */
+ if (nn->nn_persistent_error || nn->nn_sc_valid)
+ wake_up(&nn->nn_sc_wq);
+
+ if (!was_err && nn->nn_persistent_error) {
+ o2quo_conn_err(o2net_num_from_nn(nn));
+ queue_delayed_work(o2net_wq, &nn->nn_still_up,
+ msecs_to_jiffies(O2NET_QUORUM_DELAY_MS));
+ }
+
+ if (was_valid && !valid) {
+ mlog(ML_NOTICE, "no longer connected to " SC_NODEF_FMT "\n",
+ SC_NODEF_ARGS(old_sc));
+ o2net_complete_nodes_nsw(nn);
+ }
+
+ if (!was_valid && valid) {
+ o2quo_conn_up(o2net_num_from_nn(nn));
+ /* this is a bit of a hack. we only try reconnecting
+ * when heartbeating starts until we get a connection.
+ * if that connection then dies we don't try reconnecting.
+ * the only way to start connecting again is to down
+ * heartbeat and bring it back up. */
+ cancel_delayed_work(&nn->nn_connect_expired);
+ mlog(ML_NOTICE, "%s " SC_NODEF_FMT "\n",
+ o2nm_this_node() > sc->sc_node->nd_num ?
+ "connected to" : "accepted connection from",
+ SC_NODEF_ARGS(sc));
+ }
+
+ /* trigger the connecting worker func as long as we're not valid,
+ * it will back off if it shouldn't connect. This can be called
+ * from node config teardown and so needs to be careful about
+ * the work queue actually being up. */
+ if (!valid && o2net_wq) {
+ unsigned long delay;
+ /* delay if we're withing a RECONNECT_DELAY of the
+ * last attempt */
+ delay = (nn->nn_last_connect_attempt +
+ msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+ - jiffies;
+ if (delay > msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS))
+ delay = 0;
+ mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
+ queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
+ }
+
+ /* keep track of the nn's sc ref for the caller */
+ if ((old_sc == NULL) && sc)
+ sc_get(sc);
+ if (old_sc && (old_sc != sc)) {
+ o2net_sc_queue_work(old_sc, &old_sc->sc_shutdown_work);
+ sc_put(old_sc);
+ }
+}
+
+/* see o2net_register_callbacks() */
+static void o2net_data_ready(struct sock *sk, int bytes)
+{
+ void (*ready)(struct sock *sk, int bytes);
+
+ read_lock(&sk->sk_callback_lock);
+ if (sk->sk_user_data) {
+ struct o2net_sock_container *sc = sk->sk_user_data;
+ sclog(sc, "data_ready hit\n");
+ do_gettimeofday(&sc->sc_tv_data_ready);
+ o2net_sc_queue_work(sc, &sc->sc_rx_work);
+ ready = sc->sc_data_ready;
+ } else {
+ ready = sk->sk_data_ready;
+ }
+ read_unlock(&sk->sk_callback_lock);
+
+ ready(sk, bytes);
+}
+
+/* see o2net_register_callbacks() */
+static void o2net_state_change(struct sock *sk)
+{
+ void (*state_change)(struct sock *sk);
+ struct o2net_sock_container *sc;
+
+ read_lock(&sk->sk_callback_lock);
+ sc = sk->sk_user_data;
+ if (sc == NULL) {
+ state_change = sk->sk_state_change;
+ goto out;
+ }
+
+ sclog(sc, "state_change to %d\n", sk->sk_state);
+
+ state_change = sc->sc_state_change;
+
+ switch(sk->sk_state) {
+ /* ignore connecting sockets as they make progress */
+ case TCP_SYN_SENT:
+ case TCP_SYN_RECV:
+ break;
+ case TCP_ESTABLISHED:
+ o2net_sc_queue_work(sc, &sc->sc_connect_work);
+ break;
+ default:
+ o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
+ break;
+ }
+out:
+ read_unlock(&sk->sk_callback_lock);
+ state_change(sk);
+}
+
+/*
+ * we register callbacks so we can queue work on events before calling
+ * the original callbacks. our callbacks our careful to test user_data
+ * to discover when they've reaced with o2net_unregister_callbacks().
+ */
+static void o2net_register_callbacks(struct sock *sk,
+ struct o2net_sock_container *sc)
+{
+ write_lock_bh(&sk->sk_callback_lock);
+
+ /* accepted sockets inherit the old listen socket data ready */
+ if (sk->sk_data_ready == o2net_listen_data_ready) {
+ sk->sk_data_ready = sk->sk_user_data;
+ sk->sk_user_data = NULL;
+ }
+
+ BUG_ON(sk->sk_user_data != NULL);
+ sk->sk_user_data = sc;
+ sc_get(sc);
+
+ sc->sc_data_ready = sk->sk_data_ready;
+ sc->sc_state_change = sk->sk_state_change;
+ sk->sk_data_ready = o2net_data_ready;
+ sk->sk_state_change = o2net_state_change;
+
+ write_unlock_bh(&sk->sk_callback_lock);
+}
+
+static int o2net_unregister_callbacks(struct sock *sk,
+ struct o2net_sock_container *sc)
+{
+ int ret = 0;
+
+ write_lock_bh(&sk->sk_callback_lock);
+ if (sk->sk_user_data == sc) {
+ ret = 1;
+ sk->sk_user_data = NULL;
+ sk->sk_data_ready = sc->sc_data_ready;
+ sk->sk_state_change = sc->sc_state_change;
+ }
+ write_unlock_bh(&sk->sk_callback_lock);
+
+ return ret;
+}
+
+/*
+ * this is a little helper that is called by callers who have seen a problem
+ * with an sc and want to detach it from the nn if someone already hasn't beat
+ * them to it. if an error is given then the shutdown will be persistent
+ * and pending transmits will be canceled.
+ */
+static void o2net_ensure_shutdown(struct o2net_node *nn,
+ struct o2net_sock_container *sc,
+ int err)
+{
+ spin_lock(&nn->nn_lock);
+ if (nn->nn_sc == sc)
+ o2net_set_nn_state(nn, NULL, 0, err);
+ spin_unlock(&nn->nn_lock);
+}
+
+/*
+ * This work queue function performs the blocking parts of socket shutdown. A
+ * few paths lead here. set_nn_state will trigger this callback if it sees an
+ * sc detached from the nn. state_change will also trigger this callback
+ * directly when it sees errors. In that case we need to call set_nn_state
+ * ourselves as state_change couldn't get the nn_lock and call set_nn_state
+ * itself.
+ */
+static void o2net_shutdown_sc(void *arg)
+{
+ struct o2net_sock_container *sc = arg;
+ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+
+ sclog(sc, "shutting down\n");
+
+ /* drop the callbacks ref and call shutdown only once */
+ if (o2net_unregister_callbacks(sc->sc_sock->sk, sc)) {
+ /* we shouldn't flush as we're in the thread, the
+ * races with pending sc work structs are harmless */
+ del_timer_sync(&sc->sc_idle_timeout);
+ o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
+ sc_put(sc);
+ sc->sc_sock->ops->shutdown(sc->sc_sock,
+ RCV_SHUTDOWN|SEND_SHUTDOWN);
+ }
+
+ /* not fatal so failed connects before the other guy has our
+ * heartbeat can be retried */
+ o2net_ensure_shutdown(nn, sc, 0);
+ sc_put(sc);
+}
+
+/* ------------------------------------------------------------ */
+
+static int o2net_handler_cmp(struct o2net_msg_handler *nmh, u32 msg_type,
+ u32 key)
+{
+ int ret = memcmp(&nmh->nh_key, &key, sizeof(key));
+
+ if (ret == 0)
+ ret = memcmp(&nmh->nh_msg_type, &msg_type, sizeof(msg_type));
+
+ return ret;
+}
+
+static struct o2net_msg_handler *
+o2net_handler_tree_lookup(u32 msg_type, u32 key, struct rb_node ***ret_p,
+ struct rb_node **ret_parent)
+{
+ struct rb_node **p = &o2net_handler_tree.rb_node;
+ struct rb_node *parent = NULL;
+ struct o2net_msg_handler *nmh, *ret = NULL;
+ int cmp;
+
+ while (*p) {
+ parent = *p;
+ nmh = rb_entry(parent, struct o2net_msg_handler, nh_node);
+ cmp = o2net_handler_cmp(nmh, msg_type, key);
+
+ if (cmp < 0)
+ p = &(*p)->rb_left;
+ else if (cmp > 0)
+ p = &(*p)->rb_right;
+ else {
+ ret = nmh;
+ break;
+ }
+ }
+
+ if (ret_p != NULL)
+ *ret_p = p;
+ if (ret_parent != NULL)
+ *ret_parent = parent;
+
+ return ret;
+}
+
+static void o2net_handler_kref_release(struct kref *kref)
+{
+ struct o2net_msg_handler *nmh;
+ nmh = container_of(kref, struct o2net_msg_handler, nh_kref);
+
+ kfree(nmh);
+}
+
+static void o2net_handler_put(struct o2net_msg_handler *nmh)
+{
+ kref_put(&nmh->nh_kref, o2net_handler_kref_release);
+}
+
+/* max_len is protection for the handler func. incoming messages won't
+ * be given to the handler if their payload is longer than the max. */
+int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
+ o2net_msg_handler_func *func, void *data,
+ struct list_head *unreg_list)
+{
+ struct o2net_msg_handler *nmh = NULL;
+ struct rb_node **p, *parent;
+ int ret = 0;
+
+ if (max_len > O2NET_MAX_PAYLOAD_BYTES) {
+ mlog(0, "max_len for message handler out of range: %u\n",
+ max_len);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!msg_type) {
+ mlog(0, "no message type provided: %u, %p\n", msg_type, func);
+ ret = -EINVAL;
+ goto out;
+
+ }
+ if (!func) {
+ mlog(0, "no message handler provided: %u, %p\n",
+ msg_type, func);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ nmh = kcalloc(1, sizeof(struct o2net_msg_handler), GFP_NOFS);
+ if (nmh == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ nmh->nh_func = func;
+ nmh->nh_func_data = data;
+ nmh->nh_msg_type = msg_type;
+ nmh->nh_max_len = max_len;
+ nmh->nh_key = key;
+ /* the tree and list get this ref.. they're both removed in
+ * unregister when this ref is dropped */
+ kref_init(&nmh->nh_kref);
+ INIT_LIST_HEAD(&nmh->nh_unregister_item);
+
+ write_lock(&o2net_handler_lock);
+ if (o2net_handler_tree_lookup(msg_type, key, &p, &parent))
+ ret = -EEXIST;
+ else {
+ rb_link_node(&nmh->nh_node, parent, p);
+ rb_insert_color(&nmh->nh_node, &o2net_handler_tree);
+ list_add_tail(&nmh->nh_unregister_item, unreg_list);
+
+ mlog(ML_TCP, "registered handler func %p type %u key %08x\n",
+ func, msg_type, key);
+ /* we've had some trouble with handlers seemingly vanishing. */
+ mlog_bug_on_msg(o2net_handler_tree_lookup(msg_type, key, &p,
+ &parent) == NULL,
+ "couldn't find handler we *just* registerd "
+ "for type %u key %08x\n", msg_type, key);
+ }
+ write_unlock(&o2net_handler_lock);
+ if (ret)
+ goto out;
+
+out:
+ if (ret)
+ kfree(nmh);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(o2net_register_handler);
+
+void o2net_unregister_handler_list(struct list_head *list)
+{
+ struct list_head *pos, *n;
+ struct o2net_msg_handler *nmh;
+
+ write_lock(&o2net_handler_lock);
+ list_for_each_safe(pos, n, list) {
+ nmh = list_entry(pos, struct o2net_msg_handler,
+ nh_unregister_item);
+ mlog(ML_TCP, "unregistering handler func %p type %u key %08x\n",
+ nmh->nh_func, nmh->nh_msg_type, nmh->nh_key);
+ rb_erase(&nmh->nh_node, &o2net_handler_tree);
+ list_del_init(&nmh->nh_unregister_item);
+ kref_put(&nmh->nh_kref, o2net_handler_kref_release);
+ }
+ write_unlock(&o2net_handler_lock);
+}
+EXPORT_SYMBOL_GPL(o2net_unregister_handler_list);
+
+static struct o2net_msg_handler *o2net_handler_get(u32 msg_type, u32 key)
+{
+ struct o2net_msg_handler *nmh;
+
+ read_lock(&o2net_handler_lock);
+ nmh = o2net_handler_tree_lookup(msg_type, key, NULL, NULL);
+ if (nmh)
+ kref_get(&nmh->nh_kref);
+ read_unlock(&o2net_handler_lock);
+
+ return nmh;
+}
+
+/* ------------------------------------------------------------ */
+
+static int o2net_recv_tcp_msg(struct socket *sock, void *data, size_t len)
+{
+ int ret;
+ mm_segment_t oldfs;
+ struct kvec vec = {
+ .iov_len = len,
+ .iov_base = data,
+ };
+ struct msghdr msg = {
+ .msg_iovlen = 1,
+ .msg_iov = (struct iovec *)&vec,
+ .msg_flags = MSG_DONTWAIT,
+ };
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ ret = sock_recvmsg(sock, &msg, len, msg.msg_flags);
+ set_fs(oldfs);
+
+ return ret;
+}
+
+static int o2net_send_tcp_msg(struct socket *sock, struct kvec *vec,
+ size_t veclen, size_t total)
+{
+ int ret;
+ mm_segment_t oldfs;
+ struct msghdr msg = {
+ .msg_iov = (struct iovec *)vec,
+ .msg_iovlen = veclen,
+ };
+
+ if (sock == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ ret = sock_sendmsg(sock, &msg, total);
+ set_fs(oldfs);
+ if (ret != total) {
+ mlog(ML_ERROR, "sendmsg returned %d instead of %zu\n", ret,
+ total);
+ if (ret >= 0)
+ ret = -EPIPE; /* should be smarter, I bet */
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (ret < 0)
+ mlog(0, "returning error: %d\n", ret);
+ return ret;
+}
+
+static void o2net_sendpage(struct o2net_sock_container *sc,
+ void *kmalloced_virt,
+ size_t size)
+{
+ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+ ssize_t ret;
+
+
+ ret = sc->sc_sock->ops->sendpage(sc->sc_sock,
+ virt_to_page(kmalloced_virt),
+ (long)kmalloced_virt & ~PAGE_MASK,
+ size, MSG_DONTWAIT);
+ if (ret != size) {
+ mlog(ML_ERROR, "sendpage of size %zu to " SC_NODEF_FMT
+ " failed with %zd\n", size, SC_NODEF_ARGS(sc), ret);
+ o2net_ensure_shutdown(nn, sc, 0);
+ }
+}
+
+static void o2net_init_msg(struct o2net_msg *msg, u16 data_len, u16 msg_type, u32 key)
+{
+ memset(msg, 0, sizeof(struct o2net_msg));
+ msg->magic = cpu_to_be16(O2NET_MSG_MAGIC);
+ msg->data_len = cpu_to_be16(data_len);
+ msg->msg_type = cpu_to_be16(msg_type);
+ msg->sys_status = cpu_to_be32(O2NET_ERR_NONE);
+ msg->status = 0;
+ msg->key = cpu_to_be32(key);
+}
+
+static int o2net_tx_can_proceed(struct o2net_node *nn,
+ struct o2net_sock_container **sc_ret,
+ int *error)
+{
+ int ret = 0;
+
+ spin_lock(&nn->nn_lock);
+ if (nn->nn_persistent_error) {
+ ret = 1;
+ *sc_ret = NULL;
+ *error = nn->nn_persistent_error;
+ } else if (nn->nn_sc_valid) {
+ kref_get(&nn->nn_sc->sc_kref);
+
+ ret = 1;
+ *sc_ret = nn->nn_sc;
+ *error = 0;
+ }
+ spin_unlock(&nn->nn_lock);
+
+ return ret;
+}
+
+int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
+ size_t caller_veclen, u8 target_node, int *status)
+{
+ int ret, error = 0;
+ struct o2net_msg *msg = NULL;
+ size_t veclen, caller_bytes = 0;
+ struct kvec *vec = NULL;
+ struct o2net_sock_container *sc = NULL;
+ struct o2net_node *nn = o2net_nn_from_num(target_node);
+ struct o2net_status_wait nsw = {
+ .ns_node_item = LIST_HEAD_INIT(nsw.ns_node_item),
+ };
+
+ if (o2net_wq == NULL) {
+ mlog(0, "attempt to tx without o2netd running\n");
+ ret = -ESRCH;
+ goto out;
+ }
+
+ if (caller_veclen == 0) {
+ mlog(0, "bad kvec array length\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ caller_bytes = iov_length((struct iovec *)caller_vec, caller_veclen);
+ if (caller_bytes > O2NET_MAX_PAYLOAD_BYTES) {
+ mlog(0, "total payload len %zu too large\n", caller_bytes);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (target_node == o2nm_this_node()) {
+ ret = -ELOOP;
+ goto out;
+ }
+
+ ret = wait_event_interruptible(nn->nn_sc_wq,
+ o2net_tx_can_proceed(nn, &sc, &error));
+ if (!ret && error)
+ ret = error;
+ if (ret)
+ goto out;
+
+ veclen = caller_veclen + 1;
+ vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC);
+ if (vec == NULL) {
+ mlog(0, "failed to %zu element kvec!\n", veclen);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ msg = kmalloc(sizeof(struct o2net_msg), GFP_ATOMIC);
+ if (!msg) {
+ mlog(0, "failed to allocate a o2net_msg!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ o2net_init_msg(msg, caller_bytes, msg_type, key);
+
+ vec[0].iov_len = sizeof(struct o2net_msg);
+ vec[0].iov_base = msg;
+ memcpy(&vec[1], caller_vec, caller_veclen * sizeof(struct kvec));
+
+ ret = o2net_prep_nsw(nn, &nsw);
+ if (ret)
+ goto out;
+
+ msg->msg_num = cpu_to_be32(nsw.ns_id);
+
+ /* finally, convert the message header to network byte-order
+ * and send */
+ ret = o2net_send_tcp_msg(sc->sc_sock, vec, veclen,
+ sizeof(struct o2net_msg) + caller_bytes);
+ msglog(msg, "sending returned %d\n", ret);
+ if (ret < 0) {
+ mlog(0, "error returned from o2net_send_tcp_msg=%d\n", ret);
+ goto out;
+ }
+
+ /* wait on other node's handler */
+ wait_event(nsw.ns_wq, o2net_nsw_completed(nn, &nsw));
+
+ /* Note that we avoid overwriting the callers status return
+ * variable if a system error was reported on the other
+ * side. Callers beware. */
+ ret = o2net_sys_err_to_errno(nsw.ns_sys_status);
+ if (status && !ret)
+ *status = nsw.ns_status;
+
+ mlog(0, "woken, returning system status %d, user status %d\n",
+ ret, nsw.ns_status);
+out:
+ if (sc)
+ sc_put(sc);
+ if (vec)
+ kfree(vec);
+ if (msg)
+ kfree(msg);
+ o2net_complete_nsw(nn, &nsw, 0, 0, 0);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(o2net_send_message_vec);
+
+int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len,
+ u8 target_node, int *status)
+{
+ struct kvec vec = {
+ .iov_base = data,
+ .iov_len = len,
+ };
+ return o2net_send_message_vec(msg_type, key, &vec, 1,
+ target_node, status);
+}
+EXPORT_SYMBOL_GPL(o2net_send_message);
+
+static int o2net_send_status_magic(struct socket *sock, struct o2net_msg *hdr,
+ enum o2net_system_error syserr, int err)
+{
+ struct kvec vec = {
+ .iov_base = hdr,
+ .iov_len = sizeof(struct o2net_msg),
+ };
+
+ BUG_ON(syserr >= O2NET_ERR_MAX);
+
+ /* leave other fields intact from the incoming message, msg_num
+ * in particular */
+ hdr->sys_status = cpu_to_be32(syserr);
+ hdr->status = cpu_to_be32(err);
+ hdr->magic = cpu_to_be16(O2NET_MSG_STATUS_MAGIC); // twiddle the magic
+ hdr->data_len = 0;
+
+ msglog(hdr, "about to send status magic %d\n", err);
+ /* hdr has been in host byteorder this whole time */
+ return o2net_send_tcp_msg(sock, &vec, 1, sizeof(struct o2net_msg));
+}
+
+/* this returns -errno if the header was unknown or too large, etc.
+ * after this is called the buffer us reused for the next message */
+static int o2net_process_message(struct o2net_sock_container *sc,
+ struct o2net_msg *hdr)
+{
+ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+ int ret = 0, handler_status;
+ enum o2net_system_error syserr;
+ struct o2net_msg_handler *nmh = NULL;
+
+ msglog(hdr, "processing message\n");
+
+ o2net_sc_postpone_idle(sc);
+
+ switch(be16_to_cpu(hdr->magic)) {
+ case O2NET_MSG_STATUS_MAGIC:
+ /* special type for returning message status */
+ o2net_complete_nsw(nn, NULL,
+ be32_to_cpu(hdr->msg_num),
+ be32_to_cpu(hdr->sys_status),
+ be32_to_cpu(hdr->status));
+ goto out;
+ case O2NET_MSG_KEEP_REQ_MAGIC:
+ o2net_sendpage(sc, o2net_keep_resp,
+ sizeof(*o2net_keep_resp));
+ goto out;
+ case O2NET_MSG_KEEP_RESP_MAGIC:
+ goto out;
+ case O2NET_MSG_MAGIC:
+ break;
+ default:
+ msglog(hdr, "bad magic\n");
+ ret = -EINVAL;
+ goto out;
+ break;
+ }
+
+ /* find a handler for it */
+ handler_status = 0;
+ nmh = o2net_handler_get(be16_to_cpu(hdr->msg_type),
+ be32_to_cpu(hdr->key));
+ if (!nmh) {
+ mlog(ML_TCP, "couldn't find handler for type %u key %08x\n",
+ be16_to_cpu(hdr->msg_type), be32_to_cpu(hdr->key));
+ syserr = O2NET_ERR_NO_HNDLR;
+ goto out_respond;
+ }
+
+ syserr = O2NET_ERR_NONE;
+
+ if (be16_to_cpu(hdr->data_len) > nmh->nh_max_len)
+ syserr = O2NET_ERR_OVERFLOW;
+
+ if (syserr != O2NET_ERR_NONE)
+ goto out_respond;
+
+ do_gettimeofday(&sc->sc_tv_func_start);
+ sc->sc_msg_key = be32_to_cpu(hdr->key);
+ sc->sc_msg_type = be16_to_cpu(hdr->msg_type);
+ handler_status = (nmh->nh_func)(hdr, sizeof(struct o2net_msg) +
+ be16_to_cpu(hdr->data_len),
+ nmh->nh_func_data);
+ do_gettimeofday(&sc->sc_tv_func_stop);
+
+out_respond:
+ /* this destroys the hdr, so don't use it after this */
+ ret = o2net_send_status_magic(sc->sc_sock, hdr, syserr,
+ handler_status);
+ hdr = NULL;
+ mlog(0, "sending handler status %d, syserr %d returned %d\n",
+ handler_status, syserr, ret);
+
+out:
+ if (nmh)
+ o2net_handler_put(nmh);
+ return ret;
+}
+
+static int o2net_check_handshake(struct o2net_sock_container *sc)
+{
+ struct o2net_handshake *hand = page_address(sc->sc_page);
+ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+
+ if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) {
+ mlog(ML_NOTICE, SC_NODEF_FMT " advertised net protocol "
+ "version %llu but %llu is required, disconnecting\n",
+ SC_NODEF_ARGS(sc),
+ (unsigned long long)be64_to_cpu(hand->protocol_version),
+ O2NET_PROTOCOL_VERSION);
+
+ /* don't bother reconnecting if its the wrong version. */
+ o2net_ensure_shutdown(nn, sc, -ENOTCONN);
+ return -1;
+ }
+
+ sc->sc_handshake_ok = 1;
+
+ spin_lock(&nn->nn_lock);
+ /* set valid and queue the idle timers only if it hasn't been
+ * shut down already */
+ if (nn->nn_sc == sc) {
+ o2net_sc_postpone_idle(sc);
+ o2net_set_nn_state(nn, sc, 1, 0);
+ }
+ spin_unlock(&nn->nn_lock);
+
+ /* shift everything up as though it wasn't there */
+ sc->sc_page_off -= sizeof(struct o2net_handshake);
+ if (sc->sc_page_off)
+ memmove(hand, hand + 1, sc->sc_page_off);
+
+ return 0;
+}
+
+/* this demuxes the queued rx bytes into header or payload bits and calls
+ * handlers as each full message is read off the socket. it returns -error,
+ * == 0 eof, or > 0 for progress made.*/
+static int o2net_advance_rx(struct o2net_sock_container *sc)
+{
+ struct o2net_msg *hdr;
+ int ret = 0;
+ void *data;
+ size_t datalen;
+
+ sclog(sc, "receiving\n");
+ do_gettimeofday(&sc->sc_tv_advance_start);
+
+ /* do we need more header? */
+ if (sc->sc_page_off < sizeof(struct o2net_msg)) {
+ data = page_address(sc->sc_page) + sc->sc_page_off;
+ datalen = sizeof(struct o2net_msg) - sc->sc_page_off;
+ ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
+ if (ret > 0) {
+ sc->sc_page_off += ret;
+
+ /* this working relies on the handshake being
+ * smaller than the normal message header */
+ if (sc->sc_page_off >= sizeof(struct o2net_handshake)&&
+ !sc->sc_handshake_ok && o2net_check_handshake(sc)) {
+ ret = -EPROTO;
+ goto out;
+ }
+
+ /* only swab incoming here.. we can
+ * only get here once as we cross from
+ * being under to over */
+ if (sc->sc_page_off == sizeof(struct o2net_msg)) {
+ hdr = page_address(sc->sc_page);
+ if (be16_to_cpu(hdr->data_len) >
+ O2NET_MAX_PAYLOAD_BYTES)
+ ret = -EOVERFLOW;
+ }
+ }
+ if (ret <= 0)
+ goto out;
+ }
+
+ if (sc->sc_page_off < sizeof(struct o2net_msg)) {
+ /* oof, still don't have a header */
+ goto out;
+ }
+
+ /* this was swabbed above when we first read it */
+ hdr = page_address(sc->sc_page);
+
+ msglog(hdr, "at page_off %zu\n", sc->sc_page_off);
+
+ /* do we need more payload? */
+ if (sc->sc_page_off - sizeof(struct o2net_msg) < be16_to_cpu(hdr->data_len)) {
+ /* need more payload */
+ data = page_address(sc->sc_page) + sc->sc_page_off;
+ datalen = (sizeof(struct o2net_msg) + be16_to_cpu(hdr->data_len)) -
+ sc->sc_page_off;
+ ret = o2net_recv_tcp_msg(sc->sc_sock, data, datalen);
+ if (ret > 0)
+ sc->sc_page_off += ret;
+ if (ret <= 0)
+ goto out;
+ }
+
+ if (sc->sc_page_off - sizeof(struct o2net_msg) == be16_to_cpu(hdr->data_len)) {
+ /* we can only get here once, the first time we read
+ * the payload.. so set ret to progress if the handler
+ * works out. after calling this the message is toast */
+ ret = o2net_process_message(sc, hdr);
+ if (ret == 0)
+ ret = 1;
+ sc->sc_page_off = 0;
+ }
+
+out:
+ sclog(sc, "ret = %d\n", ret);
+ do_gettimeofday(&sc->sc_tv_advance_stop);
+ return ret;
+}
+
+/* this work func is triggerd by data ready. it reads until it can read no
+ * more. it interprets 0, eof, as fatal. if data_ready hits while we're doing
+ * our work the work struct will be marked and we'll be called again. */
+static void o2net_rx_until_empty(void *arg)
+{
+ struct o2net_sock_container *sc = arg;
+ int ret;
+
+ do {
+ ret = o2net_advance_rx(sc);
+ } while (ret > 0);
+
+ if (ret <= 0 && ret != -EAGAIN) {
+ struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+ sclog(sc, "saw error %d, closing\n", ret);
+ /* not permanent so read failed handshake can retry */
+ o2net_ensure_shutdown(nn, sc, 0);
+ }
+
+ sc_put(sc);
+}
+
+static int o2net_set_nodelay(struct socket *sock)
+{
+ int ret, val = 1;
+ mm_segment_t oldfs;
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ /*
+ * Dear unsuspecting programmer,
+ *
+ * Don't use sock_setsockopt() for SOL_TCP. It doesn't check its level
+ * argument and assumes SOL_SOCKET so, say, your TCP_NODELAY will
+ * silently turn into SO_DEBUG.
+ *
+ * Yours,
+ * Keeper of hilariously fragile interfaces.
+ */
+ ret = sock->ops->setsockopt(sock, SOL_TCP, TCP_NODELAY,
+ (char __user *)&val, sizeof(val));
+
+ set_fs(oldfs);
+ return ret;
+}
+
+/* ------------------------------------------------------------ */
+
+/* called when a connect completes and after a sock is accepted. the
+ * rx path will see the response and mark the sc valid */
+static void o2net_sc_connect_completed(void *arg)
+{
+ struct o2net_sock_container *sc = arg;
+
+ mlog(ML_MSG, "sc sending handshake with ver %llu id %llx\n",
+ (unsigned long long)O2NET_PROTOCOL_VERSION,
+ (unsigned long long)be64_to_cpu(o2net_hand->connector_id));
+
+ o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
+ sc_put(sc);
+}
+
+/* this is called as a work_struct func. */
+static void o2net_sc_send_keep_req(void *arg)
+{
+ struct o2net_sock_container *sc = arg;
+
+ o2net_sendpage(sc, o2net_keep_req, sizeof(*o2net_keep_req));
+ sc_put(sc);
+}
+
+/* socket shutdown does a del_timer_sync against this as it tears down.
+ * we can't start this timer until we've got to the point in sc buildup
+ * where shutdown is going to be involved */
+static void o2net_idle_timer(unsigned long data)
+{
+ struct o2net_sock_container *sc = (struct o2net_sock_container *)data;
+ struct timeval now;
+
+ do_gettimeofday(&now);
+
+ mlog(ML_NOTICE, "connection to " SC_NODEF_FMT " has been idle for 10 "
+ "seconds, shutting it down.\n", SC_NODEF_ARGS(sc));
+ mlog(ML_NOTICE, "here are some times that might help debug the "
+ "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv "
+ "%ld.%ld:%ld.%ld func (%08x:%u) %ld.%ld:%ld.%ld)\n",
+ sc->sc_tv_timer.tv_sec, sc->sc_tv_timer.tv_usec,
+ now.tv_sec, now.tv_usec,
+ sc->sc_tv_data_ready.tv_sec, sc->sc_tv_data_ready.tv_usec,
+ sc->sc_tv_advance_start.tv_sec, sc->sc_tv_advance_start.tv_usec,
+ sc->sc_tv_advance_stop.tv_sec, sc->sc_tv_advance_stop.tv_usec,
+ sc->sc_msg_key, sc->sc_msg_type,
+ sc->sc_tv_func_start.tv_sec, sc->sc_tv_func_start.tv_usec,
+ sc->sc_tv_func_stop.tv_sec, sc->sc_tv_func_stop.tv_usec);
+
+ o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
+}
+
+static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
+{
+ o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
+ o2net_sc_queue_delayed_work(sc, &sc->sc_keepalive_work,
+ O2NET_KEEPALIVE_DELAY_SECS * HZ);
+ do_gettimeofday(&sc->sc_tv_timer);
+ mod_timer(&sc->sc_idle_timeout,
+ jiffies + (O2NET_IDLE_TIMEOUT_SECS * HZ));
+}
+
+/* this work func is kicked whenever a path sets the nn state which doesn't
+ * have valid set. This includes seeing hb come up, losing a connection,
+ * having a connect attempt fail, etc. This centralizes the logic which decides
+ * if a connect attempt should be made or if we should give up and all future
+ * transmit attempts should fail */
+static void o2net_start_connect(void *arg)
+{
+ struct o2net_node *nn = arg;
+ struct o2net_sock_container *sc = NULL;
+ struct o2nm_node *node = NULL;
+ struct socket *sock = NULL;
+ struct sockaddr_in myaddr = {0, }, remoteaddr = {0, };
+ int ret = 0;
+
+ /* if we're greater we initiate tx, otherwise we accept */
+ if (o2nm_this_node() <= o2net_num_from_nn(nn))
+ goto out;
+
+ /* watch for racing with tearing a node down */
+ node = o2nm_get_node_by_num(o2net_num_from_nn(nn));
+ if (node == NULL) {
+ ret = 0;
+ goto out;
+ }
+
+ spin_lock(&nn->nn_lock);
+ /* see if we already have one pending or have given up */
+ if (nn->nn_sc || nn->nn_persistent_error)
+ arg = NULL;
+ spin_unlock(&nn->nn_lock);
+ if (arg == NULL) /* *shrug*, needed some indicator */
+ goto out;
+
+ nn->nn_last_connect_attempt = jiffies;
+
+ sc = sc_alloc(node);
+ if (sc == NULL) {
+ mlog(0, "couldn't allocate sc\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
+ if (ret < 0) {
+ mlog(0, "can't create socket: %d\n", ret);
+ goto out;
+ }
+ sc->sc_sock = sock; /* freed by sc_kref_release */
+
+ sock->sk->sk_allocation = GFP_ATOMIC;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = (__force u16)htons(0); /* any port */
+
+ ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr,
+ sizeof(myaddr));
+ if (ret) {
+ mlog(0, "bind failed: %d\n", ret);
+ goto out;
+ }
+
+ ret = o2net_set_nodelay(sc->sc_sock);
+ if (ret) {
+ mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret);
+ goto out;
+ }
+
+ o2net_register_callbacks(sc->sc_sock->sk, sc);
+
+ spin_lock(&nn->nn_lock);
+ /* handshake completion will set nn->nn_sc_valid */
+ o2net_set_nn_state(nn, sc, 0, 0);
+ spin_unlock(&nn->nn_lock);
+
+ remoteaddr.sin_family = AF_INET;
+ remoteaddr.sin_addr.s_addr = (__force u32)node->nd_ipv4_address;
+ remoteaddr.sin_port = (__force u16)node->nd_ipv4_port;
+
+ ret = sc->sc_sock->ops->connect(sc->sc_sock,
+ (struct sockaddr *)&remoteaddr,
+ sizeof(remoteaddr),
+ O_NONBLOCK);
+ if (ret == -EINPROGRESS)
+ ret = 0;
+
+out:
+ if (ret) {
+ mlog(ML_NOTICE, "connect attempt to " SC_NODEF_FMT " failed "
+ "with errno %d\n", SC_NODEF_ARGS(sc), ret);
+ /* 0 err so that another will be queued and attempted
+ * from set_nn_state */
+ if (sc)
+ o2net_ensure_shutdown(nn, sc, 0);
+ }
+ if (sc)
+ sc_put(sc);
+ if (node)
+ o2nm_node_put(node);
+
+ return;
+}
+
+static void o2net_connect_expired(void *arg)
+{
+ struct o2net_node *nn = arg;
+
+ spin_lock(&nn->nn_lock);
+ if (!nn->nn_sc_valid) {
+ mlog(ML_ERROR, "no connection established with node %u after "
+ "%u seconds, giving up and returning errors.\n",
+ o2net_num_from_nn(nn), O2NET_IDLE_TIMEOUT_SECS);
+
+ o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ }
+ spin_unlock(&nn->nn_lock);
+}
+
+static void o2net_still_up(void *arg)
+{
+ struct o2net_node *nn = arg;
+
+ o2quo_hb_still_up(o2net_num_from_nn(nn));
+}
+
+/* ------------------------------------------------------------ */
+
+void o2net_disconnect_node(struct o2nm_node *node)
+{
+ struct o2net_node *nn = o2net_nn_from_num(node->nd_num);
+
+ /* don't reconnect until it's heartbeating again */
+ spin_lock(&nn->nn_lock);
+ o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
+ spin_unlock(&nn->nn_lock);
+
+ if (o2net_wq) {
+ cancel_delayed_work(&nn->nn_connect_expired);
+ cancel_delayed_work(&nn->nn_connect_work);
+ cancel_delayed_work(&nn->nn_still_up);
+ flush_workqueue(o2net_wq);
+ }
+}
+
+static void o2net_hb_node_down_cb(struct o2nm_node *node, int node_num,
+ void *data)
+{
+ o2quo_hb_down(node_num);
+
+ if (node_num != o2nm_this_node())
+ o2net_disconnect_node(node);
+}
+
+static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
+ void *data)
+{
+ struct o2net_node *nn = o2net_nn_from_num(node_num);
+
+ o2quo_hb_up(node_num);
+
+ /* ensure an immediate connect attempt */
+ nn->nn_last_connect_attempt = jiffies -
+ (msecs_to_jiffies(O2NET_RECONNECT_DELAY_MS) + 1);
+
+ if (node_num != o2nm_this_node()) {
+ /* heartbeat doesn't work unless a local node number is
+ * configured and doing so brings up the o2net_wq, so we can
+ * use it.. */
+ queue_delayed_work(o2net_wq, &nn->nn_connect_expired,
+ O2NET_IDLE_TIMEOUT_SECS * HZ);
+
+ /* believe it or not, accept and node hearbeating testing
+ * can succeed for this node before we got here.. so
+ * only use set_nn_state to clear the persistent error
+ * if that hasn't already happened */
+ spin_lock(&nn->nn_lock);
+ if (nn->nn_persistent_error)
+ o2net_set_nn_state(nn, NULL, 0, 0);
+ spin_unlock(&nn->nn_lock);
+ }
+}
+
+void o2net_unregister_hb_callbacks(void)
+{
+ int ret;
+
+ ret = o2hb_unregister_callback(&o2net_hb_up);
+ if (ret < 0)
+ mlog(ML_ERROR, "Status return %d unregistering heartbeat up "
+ "callback!\n", ret);
+
+ ret = o2hb_unregister_callback(&o2net_hb_down);
+ if (ret < 0)
+ mlog(ML_ERROR, "Status return %d unregistering heartbeat down "
+ "callback!\n", ret);
+}
+
+int o2net_register_hb_callbacks(void)
+{
+ int ret;
+
+ o2hb_setup_callback(&o2net_hb_down, O2HB_NODE_DOWN_CB,
+ o2net_hb_node_down_cb, NULL, O2NET_HB_PRI);
+ o2hb_setup_callback(&o2net_hb_up, O2HB_NODE_UP_CB,
+ o2net_hb_node_up_cb, NULL, O2NET_HB_PRI);
+
+ ret = o2hb_register_callback(&o2net_hb_up);
+ if (ret == 0)
+ ret = o2hb_register_callback(&o2net_hb_down);
+
+ if (ret)
+ o2net_unregister_hb_callbacks();
+
+ return ret;
+}
+
+/* ------------------------------------------------------------ */
+
+static int o2net_accept_one(struct socket *sock)
+{
+ int ret, slen;
+ struct sockaddr_in sin;
+ struct socket *new_sock = NULL;
+ struct o2nm_node *node = NULL;
+ struct o2net_sock_container *sc = NULL;
+ struct o2net_node *nn;
+
+ BUG_ON(sock == NULL);
+ ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type,
+ sock->sk->sk_protocol, &new_sock);
+ if (ret)
+ goto out;
+
+ new_sock->type = sock->type;
+ new_sock->ops = sock->ops;
+ ret = sock->ops->accept(sock, new_sock, O_NONBLOCK);
+ if (ret < 0)
+ goto out;
+
+ new_sock->sk->sk_allocation = GFP_ATOMIC;
+
+ ret = o2net_set_nodelay(new_sock);
+ if (ret) {
+ mlog(ML_ERROR, "setting TCP_NODELAY failed with %d\n", ret);
+ goto out;
+ }
+
+ slen = sizeof(sin);
+ ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin,
+ &slen, 1);
+ if (ret < 0)
+ goto out;
+
+ node = o2nm_get_node_by_ip((__force __be32)sin.sin_addr.s_addr);
+ if (node == NULL) {
+ mlog(ML_NOTICE, "attempt to connect from unknown node at "
+ "%u.%u.%u.%u:%d\n", NIPQUAD(sin.sin_addr.s_addr),
+ ntohs((__force __be16)sin.sin_port));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (o2nm_this_node() > node->nd_num) {
+ mlog(ML_NOTICE, "unexpected connect attempted from a lower "
+ "numbered node '%s' at " "%u.%u.%u.%u:%d with num %u\n",
+ node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+ ntohs((__force __be16)sin.sin_port), node->nd_num);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* this happens all the time when the other node sees our heartbeat
+ * and tries to connect before we see their heartbeat */
+ if (!o2hb_check_node_heartbeating_from_callback(node->nd_num)) {
+ mlog(ML_CONN, "attempt to connect from node '%s' at "
+ "%u.%u.%u.%u:%d but it isn't heartbeating\n",
+ node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+ ntohs((__force __be16)sin.sin_port));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ nn = o2net_nn_from_num(node->nd_num);
+
+ spin_lock(&nn->nn_lock);
+ if (nn->nn_sc)
+ ret = -EBUSY;
+ else
+ ret = 0;
+ spin_unlock(&nn->nn_lock);
+ if (ret) {
+ mlog(ML_NOTICE, "attempt to connect from node '%s' at "
+ "%u.%u.%u.%u:%d but it already has an open connection\n",
+ node->nd_name, NIPQUAD(sin.sin_addr.s_addr),
+ ntohs((__force __be16)sin.sin_port));
+ goto out;
+ }
+
+ sc = sc_alloc(node);
+ if (sc == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ sc->sc_sock = new_sock;
+ new_sock = NULL;
+
+ spin_lock(&nn->nn_lock);
+ o2net_set_nn_state(nn, sc, 0, 0);
+ spin_unlock(&nn->nn_lock);
+
+ o2net_register_callbacks(sc->sc_sock->sk, sc);
+ o2net_sc_queue_work(sc, &sc->sc_rx_work);
+
+ o2net_sendpage(sc, o2net_hand, sizeof(*o2net_hand));
+
+out:
+ if (new_sock)
+ sock_release(new_sock);
+ if (node)
+ o2nm_node_put(node);
+ if (sc)
+ sc_put(sc);
+ return ret;
+}
+
+static void o2net_accept_many(void *arg)
+{
+ struct socket *sock = arg;
+ while (o2net_accept_one(sock) == 0)
+ cond_resched();
+}
+
+static void o2net_listen_data_ready(struct sock *sk, int bytes)
+{
+ void (*ready)(struct sock *sk, int bytes);
+
+ read_lock(&sk->sk_callback_lock);
+ ready = sk->sk_user_data;
+ if (ready == NULL) { /* check for teardown race */
+ ready = sk->sk_data_ready;
+ goto out;
+ }
+
+ /* ->sk_data_ready is also called for a newly established child socket
+ * before it has been accepted and the acceptor has set up their
+ * data_ready.. we only want to queue listen work for our listening
+ * socket */
+ if (sk->sk_state == TCP_LISTEN) {
+ mlog(ML_TCP, "bytes: %d\n", bytes);
+ queue_work(o2net_wq, &o2net_listen_work);
+ }
+
+out:
+ read_unlock(&sk->sk_callback_lock);
+ ready(sk, bytes);
+}
+
+static int o2net_open_listening_sock(__be16 port)
+{
+ struct socket *sock = NULL;
+ int ret;
+ struct sockaddr_in sin = {
+ .sin_family = PF_INET,
+ .sin_addr = { .s_addr = (__force u32)htonl(INADDR_ANY) },
+ .sin_port = (__force u16)port,
+ };
+
+ ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
+ if (ret < 0) {
+ mlog(ML_ERROR, "unable to create socket, ret=%d\n", ret);
+ goto out;
+ }
+
+ sock->sk->sk_allocation = GFP_ATOMIC;
+
+ write_lock_bh(&sock->sk->sk_callback_lock);
+ sock->sk->sk_user_data = sock->sk->sk_data_ready;
+ sock->sk->sk_data_ready = o2net_listen_data_ready;
+ write_unlock_bh(&sock->sk->sk_callback_lock);
+
+ o2net_listen_sock = sock;
+ INIT_WORK(&o2net_listen_work, o2net_accept_many, sock);
+
+ sock->sk->sk_reuse = 1;
+ ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
+ if (ret < 0) {
+ mlog(ML_ERROR, "unable to bind socket to port %d, ret=%d\n",
+ ntohs(port), ret);
+ goto out;
+ }
+
+ ret = sock->ops->listen(sock, 64);
+ if (ret < 0) {
+ mlog(ML_ERROR, "unable to listen on port %d, ret=%d\n",
+ ntohs(port), ret);
+ }
+
+out:
+ if (ret) {
+ o2net_listen_sock = NULL;
+ if (sock)
+ sock_release(sock);
+ }
+ return ret;
+}
+
+/*
+ * called from node manager when we should bring up our network listening
+ * socket. node manager handles all the serialization to only call this
+ * once and to match it with o2net_stop_listening(). note,
+ * o2nm_this_node() doesn't work yet as we're being called while it
+ * is being set up.
+ */
+int o2net_start_listening(struct o2nm_node *node)
+{
+ int ret = 0;
+
+ BUG_ON(o2net_wq != NULL);
+ BUG_ON(o2net_listen_sock != NULL);
+
+ mlog(ML_KTHREAD, "starting o2net thread...\n");
+ o2net_wq = create_singlethread_workqueue("o2net");
+ if (o2net_wq == NULL) {
+ mlog(ML_ERROR, "unable to launch o2net thread\n");
+ return -ENOMEM; /* ? */
+ }
+
+ ret = o2net_open_listening_sock(node->nd_ipv4_port);
+ if (ret) {
+ destroy_workqueue(o2net_wq);
+ o2net_wq = NULL;
+ } else
+ o2quo_conn_up(node->nd_num);
+
+ return ret;
+}
+
+/* again, o2nm_this_node() doesn't work here as we're involved in
+ * tearing it down */
+void o2net_stop_listening(struct o2nm_node *node)
+{
+ struct socket *sock = o2net_listen_sock;
+ size_t i;
+
+ BUG_ON(o2net_wq == NULL);
+ BUG_ON(o2net_listen_sock == NULL);
+
+ /* stop the listening socket from generating work */
+ write_lock_bh(&sock->sk->sk_callback_lock);
+ sock->sk->sk_data_ready = sock->sk->sk_user_data;
+ sock->sk->sk_user_data = NULL;
+ write_unlock_bh(&sock->sk->sk_callback_lock);
+
+ for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) {
+ struct o2nm_node *node = o2nm_get_node_by_num(i);
+ if (node) {
+ o2net_disconnect_node(node);
+ o2nm_node_put(node);
+ }
+ }
+
+ /* finish all work and tear down the work queue */
+ mlog(ML_KTHREAD, "waiting for o2net thread to exit....\n");
+ destroy_workqueue(o2net_wq);
+ o2net_wq = NULL;
+
+ sock_release(o2net_listen_sock);
+ o2net_listen_sock = NULL;
+
+ o2quo_conn_err(node->nd_num);
+}
+
+/* ------------------------------------------------------------ */
+
+int o2net_init(void)
+{
+ unsigned long i;
+
+ o2quo_init();
+
+ o2net_hand = kcalloc(1, sizeof(struct o2net_handshake), GFP_KERNEL);
+ o2net_keep_req = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
+ o2net_keep_resp = kcalloc(1, sizeof(struct o2net_msg), GFP_KERNEL);
+ if (!o2net_hand || !o2net_keep_req || !o2net_keep_resp) {
+ kfree(o2net_hand);
+ kfree(o2net_keep_req);
+ kfree(o2net_keep_resp);
+ return -ENOMEM;
+ }
+
+ o2net_hand->protocol_version = cpu_to_be64(O2NET_PROTOCOL_VERSION);
+ o2net_hand->connector_id = cpu_to_be64(1);
+
+ o2net_keep_req->magic = cpu_to_be16(O2NET_MSG_KEEP_REQ_MAGIC);
+ o2net_keep_resp->magic = cpu_to_be16(O2NET_MSG_KEEP_RESP_MAGIC);
+
+ for (i = 0; i < ARRAY_SIZE(o2net_nodes); i++) {
+ struct o2net_node *nn = o2net_nn_from_num(i);
+
+ spin_lock_init(&nn->nn_lock);
+ INIT_WORK(&nn->nn_connect_work, o2net_start_connect, nn);
+ INIT_WORK(&nn->nn_connect_expired, o2net_connect_expired, nn);
+ INIT_WORK(&nn->nn_still_up, o2net_still_up, nn);
+ /* until we see hb from a node we'll return einval */
+ nn->nn_persistent_error = -ENOTCONN;
+ init_waitqueue_head(&nn->nn_sc_wq);
+ idr_init(&nn->nn_status_idr);
+ INIT_LIST_HEAD(&nn->nn_status_list);
+ }
+
+ return 0;
+}
+
+void o2net_exit(void)
+{
+ o2quo_exit();
+ kfree(o2net_hand);
+ kfree(o2net_keep_req);
+ kfree(o2net_keep_resp);
+}
diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h
new file mode 100644
index 000000000000..a6f4585501c8
--- /dev/null
+++ b/fs/ocfs2/cluster/tcp.h
@@ -0,0 +1,113 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * tcp.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef O2CLUSTER_TCP_H
+#define O2CLUSTER_TCP_H
+
+#include <linux/socket.h>
+#ifdef __KERNEL__
+#include <net/sock.h>
+#include <linux/tcp.h>
+#else
+#include <sys/socket.h>
+#endif
+#include <linux/inet.h>
+#include <linux/in.h>
+
+struct o2net_msg
+{
+ __be16 magic;
+ __be16 data_len;
+ __be16 msg_type;
+ __be16 pad1;
+ __be32 sys_status;
+ __be32 status;
+ __be32 key;
+ __be32 msg_num;
+ __u8 buf[0];
+};
+
+typedef int (o2net_msg_handler_func)(struct o2net_msg *msg, u32 len, void *data);
+
+#define O2NET_MAX_PAYLOAD_BYTES (4096 - sizeof(struct o2net_msg))
+
+/* TODO: figure this out.... */
+static inline int o2net_link_down(int err, struct socket *sock)
+{
+ if (sock) {
+ if (sock->sk->sk_state != TCP_ESTABLISHED &&
+ sock->sk->sk_state != TCP_CLOSE_WAIT)
+ return 1;
+ }
+
+ if (err >= 0)
+ return 0;
+ switch (err) {
+ /* ????????????????????????? */
+ case -ERESTARTSYS:
+ case -EBADF:
+ /* When the server has died, an ICMP port unreachable
+ * message prompts ECONNREFUSED. */
+ case -ECONNREFUSED:
+ case -ENOTCONN:
+ case -ECONNRESET:
+ case -EPIPE:
+ return 1;
+ }
+ return 0;
+}
+
+enum {
+ O2NET_DRIVER_UNINITED,
+ O2NET_DRIVER_READY,
+};
+
+int o2net_init_tcp_sock(struct inode *inode);
+int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len,
+ u8 target_node, int *status);
+int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *vec,
+ size_t veclen, u8 target_node, int *status);
+int o2net_broadcast_message(u32 msg_type, u32 key, void *data, u32 len,
+ struct inode *group);
+
+int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
+ o2net_msg_handler_func *func, void *data,
+ struct list_head *unreg_list);
+void o2net_unregister_handler_list(struct list_head *list);
+
+struct o2nm_node;
+int o2net_register_hb_callbacks(void);
+void o2net_unregister_hb_callbacks(void);
+int o2net_start_listening(struct o2nm_node *node);
+void o2net_stop_listening(struct o2nm_node *node);
+void o2net_disconnect_node(struct o2nm_node *node);
+
+int o2net_init(void);
+void o2net_exit(void);
+int o2net_proc_init(struct proc_dir_entry *parent);
+void o2net_proc_exit(struct proc_dir_entry *parent);
+
+#endif /* O2CLUSTER_TCP_H */
diff --git a/fs/ocfs2/cluster/tcp_internal.h b/fs/ocfs2/cluster/tcp_internal.h
new file mode 100644
index 000000000000..ff9e2e2104c2
--- /dev/null
+++ b/fs/ocfs2/cluster/tcp_internal.h
@@ -0,0 +1,174 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef O2CLUSTER_TCP_INTERNAL_H
+#define O2CLUSTER_TCP_INTERNAL_H
+
+#define O2NET_MSG_MAGIC ((u16)0xfa55)
+#define O2NET_MSG_STATUS_MAGIC ((u16)0xfa56)
+#define O2NET_MSG_KEEP_REQ_MAGIC ((u16)0xfa57)
+#define O2NET_MSG_KEEP_RESP_MAGIC ((u16)0xfa58)
+
+/* same as hb delay, we're waiting for another node to recognize our hb */
+#define O2NET_RECONNECT_DELAY_MS O2HB_REGION_TIMEOUT_MS
+
+/* we're delaying our quorum decision so that heartbeat will have timed
+ * out truly dead nodes by the time we come around to making decisions
+ * on their number */
+#define O2NET_QUORUM_DELAY_MS ((o2hb_dead_threshold + 2) * O2HB_REGION_TIMEOUT_MS)
+
+#define O2NET_KEEPALIVE_DELAY_SECS 5
+#define O2NET_IDLE_TIMEOUT_SECS 10
+
+/*
+ * This version number represents quite a lot, unfortunately. It not
+ * only represents the raw network message protocol on the wire but also
+ * locking semantics of the file system using the protocol. It should
+ * be somewhere else, I'm sure, but right now it isn't.
+ *
+ * New in version 2:
+ * - full 64 bit i_size in the metadata lock lvbs
+ * - introduction of "rw" lock and pushing meta/data locking down
+ */
+#define O2NET_PROTOCOL_VERSION 2ULL
+struct o2net_handshake {
+ __be64 protocol_version;
+ __be64 connector_id;
+};
+
+struct o2net_node {
+ /* this is never called from int/bh */
+ spinlock_t nn_lock;
+
+ /* set the moment an sc is allocated and a connect is started */
+ struct o2net_sock_container *nn_sc;
+ /* _valid is only set after the handshake passes and tx can happen */
+ unsigned nn_sc_valid:1;
+ /* if this is set tx just returns it */
+ int nn_persistent_error;
+
+ /* threads waiting for an sc to arrive wait on the wq for generation
+ * to increase. it is increased when a connecting socket succeeds
+ * or fails or when an accepted socket is attached. */
+ wait_queue_head_t nn_sc_wq;
+
+ struct idr nn_status_idr;
+ struct list_head nn_status_list;
+
+ /* connects are attempted from when heartbeat comes up until either hb
+ * goes down, the node is unconfigured, no connect attempts succeed
+ * before O2NET_CONN_IDLE_DELAY, or a connect succeeds. connect_work
+ * is queued from set_nn_state both from hb up and from itself if a
+ * connect attempt fails and so can be self-arming. shutdown is
+ * careful to first mark the nn such that no connects will be attempted
+ * before canceling delayed connect work and flushing the queue. */
+ struct work_struct nn_connect_work;
+ unsigned long nn_last_connect_attempt;
+
+ /* this is queued as nodes come up and is canceled when a connection is
+ * established. this expiring gives up on the node and errors out
+ * transmits */
+ struct work_struct nn_connect_expired;
+
+ /* after we give up on a socket we wait a while before deciding
+ * that it is still heartbeating and that we should do some
+ * quorum work */
+ struct work_struct nn_still_up;
+};
+
+struct o2net_sock_container {
+ struct kref sc_kref;
+ /* the next two are vaild for the life time of the sc */
+ struct socket *sc_sock;
+ struct o2nm_node *sc_node;
+
+ /* all of these sc work structs hold refs on the sc while they are
+ * queued. they should not be able to ref a freed sc. the teardown
+ * race is with o2net_wq destruction in o2net_stop_listening() */
+
+ /* rx and connect work are generated from socket callbacks. sc
+ * shutdown removes the callbacks and then flushes the work queue */
+ struct work_struct sc_rx_work;
+ struct work_struct sc_connect_work;
+ /* shutdown work is triggered in two ways. the simple way is
+ * for a code path calls ensure_shutdown which gets a lock, removes
+ * the sc from the nn, and queues the work. in this case the
+ * work is single-shot. the work is also queued from a sock
+ * callback, though, and in this case the work will find the sc
+ * still on the nn and will call ensure_shutdown itself.. this
+ * ends up triggering the shutdown work again, though nothing
+ * will be done in that second iteration. so work queue teardown
+ * has to be careful to remove the sc from the nn before waiting
+ * on the work queue so that the shutdown work doesn't remove the
+ * sc and rearm itself.
+ */
+ struct work_struct sc_shutdown_work;
+
+ struct timer_list sc_idle_timeout;
+ struct work_struct sc_keepalive_work;
+
+ unsigned sc_handshake_ok:1;
+
+ struct page *sc_page;
+ size_t sc_page_off;
+
+ /* original handlers for the sockets */
+ void (*sc_state_change)(struct sock *sk);
+ void (*sc_data_ready)(struct sock *sk, int bytes);
+
+ struct timeval sc_tv_timer;
+ struct timeval sc_tv_data_ready;
+ struct timeval sc_tv_advance_start;
+ struct timeval sc_tv_advance_stop;
+ struct timeval sc_tv_func_start;
+ struct timeval sc_tv_func_stop;
+ u32 sc_msg_key;
+ u16 sc_msg_type;
+};
+
+struct o2net_msg_handler {
+ struct rb_node nh_node;
+ u32 nh_max_len;
+ u32 nh_msg_type;
+ u32 nh_key;
+ o2net_msg_handler_func *nh_func;
+ o2net_msg_handler_func *nh_func_data;
+ struct kref nh_kref;
+ struct list_head nh_unregister_item;
+};
+
+enum o2net_system_error {
+ O2NET_ERR_NONE = 0,
+ O2NET_ERR_NO_HNDLR,
+ O2NET_ERR_OVERFLOW,
+ O2NET_ERR_DIED,
+ O2NET_ERR_MAX
+};
+
+struct o2net_status_wait {
+ enum o2net_system_error ns_sys_status;
+ s32 ns_status;
+ int ns_id;
+ wait_queue_head_t ns_wq;
+ struct list_head ns_node_item;
+};
+
+#endif /* O2CLUSTER_TCP_INTERNAL_H */
diff --git a/fs/ocfs2/cluster/ver.c b/fs/ocfs2/cluster/ver.c
new file mode 100644
index 000000000000..7286c48bb30d
--- /dev/null
+++ b/fs/ocfs2/cluster/ver.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ver.c
+ *
+ * version string
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include "ver.h"
+
+#define CLUSTER_BUILD_VERSION "1.3.3"
+
+#define VERSION_STR "OCFS2 Node Manager " CLUSTER_BUILD_VERSION
+
+void cluster_print_version(void)
+{
+ printk(KERN_INFO "%s\n", VERSION_STR);
+}
+
+MODULE_DESCRIPTION(VERSION_STR);
+
+MODULE_VERSION(CLUSTER_BUILD_VERSION);
diff --git a/fs/ocfs2/cluster/ver.h b/fs/ocfs2/cluster/ver.h
new file mode 100644
index 000000000000..32554c3382c2
--- /dev/null
+++ b/fs/ocfs2/cluster/ver.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ver.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef O2CLUSTER_VER_H
+#define O2CLUSTER_VER_H
+
+void cluster_print_version(void);
+
+#endif /* O2CLUSTER_VER_H */
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
new file mode 100644
index 000000000000..bd85182e97bc
--- /dev/null
+++ b/fs/ocfs2/dcache.c
@@ -0,0 +1,91 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dcache.c
+ *
+ * dentry cache handling code
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+
+#define MLOG_MASK_PREFIX ML_DCACHE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dcache.h"
+#include "file.h"
+#include "inode.h"
+
+static int ocfs2_dentry_revalidate(struct dentry *dentry,
+ struct nameidata *nd)
+{
+ struct inode *inode = dentry->d_inode;
+ int ret = 0; /* if all else fails, just return false */
+ struct ocfs2_super *osb;
+
+ mlog_entry("(0x%p, '%.*s')\n", dentry,
+ dentry->d_name.len, dentry->d_name.name);
+
+ /* Never trust a negative dentry - force a new lookup. */
+ if (inode == NULL) {
+ mlog(0, "negative dentry: %.*s\n", dentry->d_name.len,
+ dentry->d_name.name);
+ goto bail;
+ }
+
+ osb = OCFS2_SB(inode->i_sb);
+
+ BUG_ON(!osb);
+
+ if (inode != osb->root_inode) {
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ /* did we or someone else delete this inode? */
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ mlog(0, "inode (%"MLFu64") deleted, returning false\n",
+ OCFS2_I(inode)->ip_blkno);
+ goto bail;
+ }
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ if (!inode->i_nlink) {
+ mlog(0, "Inode %"MLFu64" orphaned, returning false "
+ "dir = %d\n", OCFS2_I(inode)->ip_blkno,
+ S_ISDIR(inode->i_mode));
+ goto bail;
+ }
+ }
+
+ ret = 1;
+
+bail:
+ mlog_exit(ret);
+
+ return ret;
+}
+
+struct dentry_operations ocfs2_dentry_ops = {
+ .d_revalidate = ocfs2_dentry_revalidate,
+};
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
new file mode 100644
index 000000000000..90072771114b
--- /dev/null
+++ b/fs/ocfs2/dcache.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dcache.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_DCACHE_H
+#define OCFS2_DCACHE_H
+
+extern struct dentry_operations ocfs2_dentry_ops;
+
+#endif /* OCFS2_DCACHE_H */
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
new file mode 100644
index 000000000000..57158fa75d91
--- /dev/null
+++ b/fs/ocfs2/dir.c
@@ -0,0 +1,618 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir.c
+ *
+ * Creates, reads, walks and deletes directory-nodes
+ *
+ * Copyright (C) 2002, 2004 Oracle. All rights reserved.
+ *
+ * Portions of this code from linux/fs/ext3/dir.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/fs/minix/dir.c
+ *
+ * Copyright (C) 1991, 1992 Linux Torvalds
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#define MLOG_MASK_PREFIX ML_NAMEI
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dir.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "file.h"
+#include "inode.h"
+#include "journal.h"
+#include "namei.h"
+#include "suballoc.h"
+#include "uptodate.h"
+
+#include "buffer_head_io.h"
+
+static unsigned char ocfs2_filetype_table[] = {
+ DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
+};
+
+static int ocfs2_extend_dir(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head **new_de_bh);
+/*
+ * ocfs2_readdir()
+ *
+ */
+int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+ int error = 0;
+ unsigned long offset, blk;
+ int i, num, stored;
+ struct buffer_head * bh, * tmp;
+ struct ocfs2_dir_entry * de;
+ int err;
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct super_block * sb = inode->i_sb;
+ int have_disk_lock = 0;
+
+ mlog_entry("dirino=%"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+
+ stored = 0;
+ bh = NULL;
+
+ error = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (error < 0) {
+ if (error != -ENOENT)
+ mlog_errno(error);
+ /* we haven't got any yet, so propagate the error. */
+ stored = error;
+ goto bail;
+ }
+ have_disk_lock = 1;
+
+ offset = filp->f_pos & (sb->s_blocksize - 1);
+
+ while (!error && !stored && filp->f_pos < i_size_read(inode)) {
+ blk = (filp->f_pos) >> sb->s_blocksize_bits;
+ bh = ocfs2_bread(inode, blk, &err, 0);
+ if (!bh) {
+ mlog(ML_ERROR, "directory #%"MLFu64" contains a hole "
+ "at offset %lld\n",
+ OCFS2_I(inode)->ip_blkno,
+ filp->f_pos);
+ filp->f_pos += sb->s_blocksize - offset;
+ continue;
+ }
+
+ /*
+ * Do the readahead (8k)
+ */
+ if (!offset) {
+ for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0;
+ i > 0; i--) {
+ tmp = ocfs2_bread(inode, ++blk, &err, 1);
+ if (tmp)
+ brelse(tmp);
+ }
+ }
+
+revalidate:
+ /* If the dir block has changed since the last call to
+ * readdir(2), then we might be pointing to an invalid
+ * dirent right now. Scan from the start of the block
+ * to make sure. */
+ if (filp->f_version != inode->i_version) {
+ for (i = 0; i < sb->s_blocksize && i < offset; ) {
+ de = (struct ocfs2_dir_entry *) (bh->b_data + i);
+ /* It's too expensive to do a full
+ * dirent test each time round this
+ * loop, but we do have to test at
+ * least that it is non-zero. A
+ * failure will be detected in the
+ * dirent test below. */
+ if (le16_to_cpu(de->rec_len) <
+ OCFS2_DIR_REC_LEN(1))
+ break;
+ i += le16_to_cpu(de->rec_len);
+ }
+ offset = i;
+ filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
+ | offset;
+ filp->f_version = inode->i_version;
+ }
+
+ while (!error && filp->f_pos < i_size_read(inode)
+ && offset < sb->s_blocksize) {
+ de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
+ if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
+ /* On error, skip the f_pos to the
+ next block. */
+ filp->f_pos = (filp->f_pos |
+ (sb->s_blocksize - 1)) + 1;
+ brelse(bh);
+ goto bail;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ if (le64_to_cpu(de->inode)) {
+ /* We might block in the next section
+ * if the data destination is
+ * currently swapped out. So, use a
+ * version stamp to detect whether or
+ * not the directory has been modified
+ * during the copy operation.
+ */
+ unsigned long version = filp->f_version;
+ unsigned char d_type = DT_UNKNOWN;
+
+ if (de->file_type < OCFS2_FT_MAX)
+ d_type = ocfs2_filetype_table[de->file_type];
+ error = filldir(dirent, de->name,
+ de->name_len,
+ filp->f_pos,
+ ino_from_blkno(sb, le64_to_cpu(de->inode)),
+ d_type);
+ if (error)
+ break;
+ if (version != filp->f_version)
+ goto revalidate;
+ stored ++;
+ }
+ filp->f_pos += le16_to_cpu(de->rec_len);
+ }
+ offset = 0;
+ brelse(bh);
+ }
+
+ stored = 0;
+bail:
+ if (have_disk_lock)
+ ocfs2_meta_unlock(inode, 0);
+
+ mlog_exit(stored);
+
+ return stored;
+}
+
+/*
+ * NOTE: this should always be called with parent dir i_mutex taken.
+ */
+int ocfs2_find_files_on_disk(const char *name,
+ int namelen,
+ u64 *blkno,
+ struct inode *inode,
+ struct buffer_head **dirent_bh,
+ struct ocfs2_dir_entry **dirent)
+{
+ int status = -ENOENT;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ mlog_entry("(osb=%p, parent=%"MLFu64", name='%.*s', blkno=%p, "
+ "inode=%p)\n",
+ osb, OCFS2_I(inode)->ip_blkno, namelen, name, blkno, inode);
+
+ *dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent);
+ if (!*dirent_bh || !*dirent) {
+ status = -ENOENT;
+ goto leave;
+ }
+
+ *blkno = le64_to_cpu((*dirent)->inode);
+
+ status = 0;
+leave:
+ if (status < 0) {
+ *dirent = NULL;
+ if (*dirent_bh) {
+ brelse(*dirent_bh);
+ *dirent_bh = NULL;
+ }
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/* Check for a name within a directory.
+ *
+ * Return 0 if the name does not exist
+ * Return -EEXIST if the directory contains the name
+ *
+ * Callers should have i_mutex + a cluster lock on dir
+ */
+int ocfs2_check_dir_for_entry(struct inode *dir,
+ const char *name,
+ int namelen)
+{
+ int ret;
+ struct buffer_head *dirent_bh = NULL;
+ struct ocfs2_dir_entry *dirent = NULL;
+
+ mlog_entry("dir %"MLFu64", name '%.*s'\n", OCFS2_I(dir)->ip_blkno,
+ namelen, name);
+
+ ret = -EEXIST;
+ dirent_bh = ocfs2_find_entry(name, namelen, dir, &dirent);
+ if (dirent_bh)
+ goto bail;
+
+ ret = 0;
+bail:
+ if (dirent_bh)
+ brelse(dirent_bh);
+
+ mlog_exit(ret);
+ return ret;
+}
+
+/*
+ * routine to check that the specified directory is empty (for rmdir)
+ */
+int ocfs2_empty_dir(struct inode *inode)
+{
+ unsigned long offset;
+ struct buffer_head * bh;
+ struct ocfs2_dir_entry * de, * de1;
+ struct super_block * sb;
+ int err;
+
+ sb = inode->i_sb;
+ if ((i_size_read(inode) <
+ (OCFS2_DIR_REC_LEN(1) + OCFS2_DIR_REC_LEN(2))) ||
+ !(bh = ocfs2_bread(inode, 0, &err, 0))) {
+ mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
+ "no data block\n",
+ OCFS2_I(inode)->ip_blkno);
+ return 1;
+ }
+
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ de1 = (struct ocfs2_dir_entry *)
+ ((char *)de + le16_to_cpu(de->rec_len));
+ if ((le64_to_cpu(de->inode) != OCFS2_I(inode)->ip_blkno) ||
+ !le64_to_cpu(de1->inode) ||
+ strcmp(".", de->name) ||
+ strcmp("..", de1->name)) {
+ mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
+ "no `.' or `..'\n",
+ OCFS2_I(inode)->ip_blkno);
+ brelse(bh);
+ return 1;
+ }
+ offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+ de = (struct ocfs2_dir_entry *)((char *)de1 + le16_to_cpu(de1->rec_len));
+ while (offset < i_size_read(inode) ) {
+ if (!bh || (void *)de >= (void *)(bh->b_data + sb->s_blocksize)) {
+ brelse(bh);
+ bh = ocfs2_bread(inode,
+ offset >> sb->s_blocksize_bits, &err, 0);
+ if (!bh) {
+ mlog(ML_ERROR, "directory #%"MLFu64" contains "
+ "a hole at offset %lu\n",
+ OCFS2_I(inode)->ip_blkno, offset);
+ offset += sb->s_blocksize;
+ continue;
+ }
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ }
+ if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
+ brelse(bh);
+ return 1;
+ }
+ if (le64_to_cpu(de->inode)) {
+ brelse(bh);
+ return 0;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ocfs2_dir_entry *)
+ ((char *)de + le16_to_cpu(de->rec_len));
+ }
+ brelse(bh);
+ return 1;
+}
+
+/* returns a bh of the 1st new block in the allocation. */
+int ocfs2_do_extend_dir(struct super_block *sb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head **new_bh)
+{
+ int status;
+ int extend;
+ u64 p_blkno;
+
+ spin_lock(&OCFS2_I(dir)->ip_lock);
+ extend = (i_size_read(dir) == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters));
+ spin_unlock(&OCFS2_I(dir)->ip_lock);
+
+ if (extend) {
+ status = ocfs2_do_extend_allocation(OCFS2_SB(sb), dir, 1,
+ parent_fe_bh, handle,
+ data_ac, meta_ac, NULL);
+ BUG_ON(status == -EAGAIN);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = ocfs2_extent_map_get_blocks(dir, (dir->i_blocks >>
+ (sb->s_blocksize_bits - 9)),
+ 1, &p_blkno, NULL);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *new_bh = sb_getblk(sb, p_blkno);
+ if (!*new_bh) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* assumes you already have a cluster lock on the directory. */
+static int ocfs2_extend_dir(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head **new_de_bh)
+{
+ int status = 0;
+ int credits, num_free_extents;
+ loff_t dir_i_size;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
+ struct ocfs2_alloc_context *data_ac = NULL;
+ struct ocfs2_alloc_context *meta_ac = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct buffer_head *new_bh = NULL;
+ struct ocfs2_dir_entry * de;
+ struct super_block *sb = osb->sb;
+
+ mlog_entry_void();
+
+ dir_i_size = i_size_read(dir);
+ mlog(0, "extending dir %"MLFu64" (i_size = %lld)\n",
+ OCFS2_I(dir)->ip_blkno, dir_i_size);
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* dir->i_size is always block aligned. */
+ spin_lock(&OCFS2_I(dir)->ip_lock);
+ if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
+ spin_unlock(&OCFS2_I(dir)->ip_lock);
+ num_free_extents = ocfs2_num_free_extents(osb, dir, fe);
+ if (num_free_extents < 0) {
+ status = num_free_extents;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (!num_free_extents) {
+ status = ocfs2_reserve_new_metadata(osb, handle,
+ fe, &meta_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ credits = ocfs2_calc_extend_credits(sb, fe, 1);
+ } else {
+ spin_unlock(&OCFS2_I(dir)->ip_lock);
+ credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
+ }
+
+ handle = ocfs2_start_trans(osb, handle, credits);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_do_extend_dir(osb->sb, handle, dir, parent_fe_bh,
+ data_ac, meta_ac, &new_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_set_new_buffer_uptodate(dir, new_bh);
+
+ status = ocfs2_journal_access(handle, dir, new_bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ memset(new_bh->b_data, 0, sb->s_blocksize);
+ de = (struct ocfs2_dir_entry *) new_bh->b_data;
+ de->inode = 0;
+ de->rec_len = cpu_to_le16(sb->s_blocksize);
+ status = ocfs2_journal_dirty(handle, new_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ dir_i_size += dir->i_sb->s_blocksize;
+ i_size_write(dir, dir_i_size);
+ dir->i_blocks = ocfs2_align_bytes_to_sectors(dir_i_size);
+ status = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *new_de_bh = new_bh;
+ get_bh(*new_de_bh);
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (data_ac)
+ ocfs2_free_alloc_context(data_ac);
+ if (meta_ac)
+ ocfs2_free_alloc_context(meta_ac);
+
+ if (new_bh)
+ brelse(new_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Search the dir for a good spot, extending it if necessary. The
+ * block containing an appropriate record is returned in ret_de_bh.
+ */
+int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ const char *name,
+ int namelen,
+ struct buffer_head **ret_de_bh)
+{
+ unsigned long offset;
+ struct buffer_head * bh = NULL;
+ unsigned short rec_len;
+ struct ocfs2_dinode *fe;
+ struct ocfs2_dir_entry *de;
+ struct super_block *sb;
+ int status;
+
+ mlog_entry_void();
+
+ mlog(0, "getting ready to insert namelen %d into dir %"MLFu64"\n",
+ namelen, OCFS2_I(dir)->ip_blkno);
+
+ BUG_ON(!S_ISDIR(dir->i_mode));
+ fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
+ BUG_ON(le64_to_cpu(fe->i_size) != i_size_read(dir));
+
+ sb = dir->i_sb;
+
+ if (!namelen) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bh = ocfs2_bread(dir, 0, &status, 0);
+ if (!bh) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ rec_len = OCFS2_DIR_REC_LEN(namelen);
+ offset = 0;
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ while (1) {
+ if ((char *)de >= sb->s_blocksize + bh->b_data) {
+ brelse(bh);
+ bh = NULL;
+
+ if (i_size_read(dir) <= offset) {
+ status = ocfs2_extend_dir(osb,
+ dir,
+ parent_fe_bh,
+ &bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ BUG_ON(!bh);
+ *ret_de_bh = bh;
+ get_bh(*ret_de_bh);
+ goto bail;
+ }
+ bh = ocfs2_bread(dir,
+ offset >> sb->s_blocksize_bits,
+ &status,
+ 0);
+ if (!bh) {
+ mlog_errno(status);
+ goto bail;
+ }
+ /* move to next block */
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ }
+ if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
+ status = -ENOENT;
+ goto bail;
+ }
+ if (ocfs2_match(namelen, name, de)) {
+ status = -EEXIST;
+ goto bail;
+ }
+ if (((le64_to_cpu(de->inode) == 0) &&
+ (le16_to_cpu(de->rec_len) >= rec_len)) ||
+ (le16_to_cpu(de->rec_len) >=
+ (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
+ /* Ok, we found a spot. Return this bh and let
+ * the caller actually fill it in. */
+ *ret_de_bh = bh;
+ get_bh(*ret_de_bh);
+ status = 0;
+ goto bail;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len));
+ }
+
+ status = 0;
+bail:
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
diff --git a/fs/ocfs2/dir.h b/fs/ocfs2/dir.h
new file mode 100644
index 000000000000..5f614ec9649c
--- /dev/null
+++ b/fs/ocfs2/dir.h
@@ -0,0 +1,54 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_DIR_H
+#define OCFS2_DIR_H
+
+int ocfs2_check_dir_for_entry(struct inode *dir,
+ const char *name,
+ int namelen);
+int ocfs2_empty_dir(struct inode *inode); /* FIXME: to namei.c */
+int ocfs2_find_files_on_disk(const char *name,
+ int namelen,
+ u64 *blkno,
+ struct inode *inode,
+ struct buffer_head **dirent_bh,
+ struct ocfs2_dir_entry **dirent);
+int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir);
+int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ const char *name,
+ int namelen,
+ struct buffer_head **ret_de_bh);
+struct ocfs2_alloc_context;
+int ocfs2_do_extend_dir(struct super_block *sb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ struct buffer_head *parent_fe_bh,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ struct buffer_head **new_bh);
+#endif /* OCFS2_DIR_H */
diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
new file mode 100644
index 000000000000..ce3f7c29d270
--- /dev/null
+++ b/fs/ocfs2/dlm/Makefile
@@ -0,0 +1,8 @@
+EXTRA_CFLAGS += -Ifs/ocfs2
+
+obj-$(CONFIG_OCFS2_FS) += ocfs2_dlm.o ocfs2_dlmfs.o
+
+ocfs2_dlm-objs := dlmdomain.o dlmdebug.o dlmthread.o dlmrecovery.o \
+ dlmmaster.o dlmast.o dlmconvert.o dlmlock.o dlmunlock.o dlmver.o
+
+ocfs2_dlmfs-objs := userdlm.o dlmfs.o dlmfsver.o
diff --git a/fs/ocfs2/dlm/dlmapi.h b/fs/ocfs2/dlm/dlmapi.h
new file mode 100644
index 000000000000..53652f51c0e1
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmapi.h
@@ -0,0 +1,214 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmapi.h
+ *
+ * externally exported dlm interfaces
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef DLMAPI_H
+#define DLMAPI_H
+
+struct dlm_lock;
+struct dlm_ctxt;
+
+/* NOTE: changes made to this enum should be reflected in dlmdebug.c */
+enum dlm_status {
+ DLM_NORMAL = 0, /* 0: request in progress */
+ DLM_GRANTED, /* 1: request granted */
+ DLM_DENIED, /* 2: request denied */
+ DLM_DENIED_NOLOCKS, /* 3: request denied, out of system resources */
+ DLM_WORKING, /* 4: async request in progress */
+ DLM_BLOCKED, /* 5: lock request blocked */
+ DLM_BLOCKED_ORPHAN, /* 6: lock request blocked by a orphan lock*/
+ DLM_DENIED_GRACE_PERIOD, /* 7: topological change in progress */
+ DLM_SYSERR, /* 8: system error */
+ DLM_NOSUPPORT, /* 9: unsupported */
+ DLM_CANCELGRANT, /* 10: can't cancel convert: already granted */
+ DLM_IVLOCKID, /* 11: bad lockid */
+ DLM_SYNC, /* 12: synchronous request granted */
+ DLM_BADTYPE, /* 13: bad resource type */
+ DLM_BADRESOURCE, /* 14: bad resource handle */
+ DLM_MAXHANDLES, /* 15: no more resource handles */
+ DLM_NOCLINFO, /* 16: can't contact cluster manager */
+ DLM_NOLOCKMGR, /* 17: can't contact lock manager */
+ DLM_NOPURGED, /* 18: can't contact purge daemon */
+ DLM_BADARGS, /* 19: bad api args */
+ DLM_VOID, /* 20: no status */
+ DLM_NOTQUEUED, /* 21: NOQUEUE was specified and request failed */
+ DLM_IVBUFLEN, /* 22: invalid resource name length */
+ DLM_CVTUNGRANT, /* 23: attempted to convert ungranted lock */
+ DLM_BADPARAM, /* 24: invalid lock mode specified */
+ DLM_VALNOTVALID, /* 25: value block has been invalidated */
+ DLM_REJECTED, /* 26: request rejected, unrecognized client */
+ DLM_ABORT, /* 27: blocked lock request cancelled */
+ DLM_CANCEL, /* 28: conversion request cancelled */
+ DLM_IVRESHANDLE, /* 29: invalid resource handle */
+ DLM_DEADLOCK, /* 30: deadlock recovery refused this request */
+ DLM_DENIED_NOASTS, /* 31: failed to allocate AST */
+ DLM_FORWARD, /* 32: request must wait for primary's response */
+ DLM_TIMEOUT, /* 33: timeout value for lock has expired */
+ DLM_IVGROUPID, /* 34: invalid group specification */
+ DLM_VERS_CONFLICT, /* 35: version conflicts prevent request handling */
+ DLM_BAD_DEVICE_PATH, /* 36: Locks device does not exist or path wrong */
+ DLM_NO_DEVICE_PERMISSION, /* 37: Client has insufficient pers for device */
+ DLM_NO_CONTROL_DEVICE, /* 38: Cannot set options on opened device */
+
+ DLM_RECOVERING, /* 39: extension, allows caller to fail a lock
+ request if it is being recovered */
+ DLM_MIGRATING, /* 40: extension, allows caller to fail a lock
+ request if it is being migrated */
+ DLM_MAXSTATS, /* 41: upper limit for return code validation */
+};
+
+/* for pretty-printing dlm_status error messages */
+const char *dlm_errmsg(enum dlm_status err);
+/* for pretty-printing dlm_status error names */
+const char *dlm_errname(enum dlm_status err);
+
+/* Eventually the DLM will use standard errno values, but in the
+ * meantime this lets us track dlm errors as they bubble up. When we
+ * bring its error reporting into line with the rest of the stack,
+ * these can just be replaced with calls to mlog_errno. */
+#define dlm_error(st) do { \
+ if ((st) != DLM_RECOVERING && \
+ (st) != DLM_MIGRATING && \
+ (st) != DLM_FORWARD) \
+ mlog(ML_ERROR, "dlm status = %s\n", dlm_errname((st))); \
+} while (0)
+
+#define DLM_LKSB_UNUSED1 0x01
+#define DLM_LKSB_PUT_LVB 0x02
+#define DLM_LKSB_GET_LVB 0x04
+#define DLM_LKSB_UNUSED2 0x08
+#define DLM_LKSB_UNUSED3 0x10
+#define DLM_LKSB_UNUSED4 0x20
+#define DLM_LKSB_UNUSED5 0x40
+#define DLM_LKSB_UNUSED6 0x80
+
+#define DLM_LVB_LEN 64
+
+/* Callers are only allowed access to the lvb and status members of
+ * this struct. */
+struct dlm_lockstatus {
+ enum dlm_status status;
+ u32 flags;
+ struct dlm_lock *lockid;
+ char lvb[DLM_LVB_LEN];
+};
+
+/* Valid lock modes. */
+#define LKM_IVMODE (-1) /* invalid mode */
+#define LKM_NLMODE 0 /* null lock */
+#define LKM_CRMODE 1 /* concurrent read unsupported */
+#define LKM_CWMODE 2 /* concurrent write unsupported */
+#define LKM_PRMODE 3 /* protected read */
+#define LKM_PWMODE 4 /* protected write unsupported */
+#define LKM_EXMODE 5 /* exclusive */
+#define LKM_MAXMODE 5
+#define LKM_MODEMASK 0xff
+
+/* Flags passed to dlmlock and dlmunlock:
+ * reserved: flags used by the "real" dlm
+ * only a few are supported by this dlm
+ * (U) = unsupported by ocfs2 dlm */
+#define LKM_ORPHAN 0x00000010 /* this lock is orphanable (U) */
+#define LKM_PARENTABLE 0x00000020 /* this lock was orphaned (U) */
+#define LKM_BLOCK 0x00000040 /* blocking lock request (U) */
+#define LKM_LOCAL 0x00000080 /* local lock request */
+#define LKM_VALBLK 0x00000100 /* lock value block request */
+#define LKM_NOQUEUE 0x00000200 /* non blocking request */
+#define LKM_CONVERT 0x00000400 /* conversion request */
+#define LKM_NODLCKWT 0x00000800 /* this lock wont deadlock (U) */
+#define LKM_UNLOCK 0x00001000 /* deallocate this lock */
+#define LKM_CANCEL 0x00002000 /* cancel conversion request */
+#define LKM_DEQALL 0x00004000 /* remove all locks held by proc (U) */
+#define LKM_INVVALBLK 0x00008000 /* invalidate lock value block */
+#define LKM_SYNCSTS 0x00010000 /* return synchronous status if poss (U) */
+#define LKM_TIMEOUT 0x00020000 /* lock request contains timeout (U) */
+#define LKM_SNGLDLCK 0x00040000 /* request can self-deadlock (U) */
+#define LKM_FINDLOCAL 0x00080000 /* find local lock request (U) */
+#define LKM_PROC_OWNED 0x00100000 /* owned by process, not group (U) */
+#define LKM_XID 0x00200000 /* use transaction id for deadlock (U) */
+#define LKM_XID_CONFLICT 0x00400000 /* do not allow lock inheritance (U) */
+#define LKM_FORCE 0x00800000 /* force unlock flag */
+#define LKM_REVVALBLK 0x01000000 /* temporary solution: re-validate
+ lock value block (U) */
+/* unused */
+#define LKM_UNUSED1 0x00000001 /* unused */
+#define LKM_UNUSED2 0x00000002 /* unused */
+#define LKM_UNUSED3 0x00000004 /* unused */
+#define LKM_UNUSED4 0x00000008 /* unused */
+#define LKM_UNUSED5 0x02000000 /* unused */
+#define LKM_UNUSED6 0x04000000 /* unused */
+#define LKM_UNUSED7 0x08000000 /* unused */
+
+/* ocfs2 extensions: internal only
+ * should never be used by caller */
+#define LKM_MIGRATION 0x10000000 /* extension: lockres is to be migrated
+ to another node */
+#define LKM_PUT_LVB 0x20000000 /* extension: lvb is being passed
+ should be applied to lockres */
+#define LKM_GET_LVB 0x40000000 /* extension: lvb should be copied
+ from lockres when lock is granted */
+#define LKM_RECOVERY 0x80000000 /* extension: flag for recovery lock
+ used to avoid recovery rwsem */
+
+
+typedef void (dlm_astlockfunc_t)(void *);
+typedef void (dlm_bastlockfunc_t)(void *, int);
+typedef void (dlm_astunlockfunc_t)(void *, enum dlm_status);
+
+enum dlm_status dlmlock(struct dlm_ctxt *dlm,
+ int mode,
+ struct dlm_lockstatus *lksb,
+ int flags,
+ const char *name,
+ dlm_astlockfunc_t *ast,
+ void *data,
+ dlm_bastlockfunc_t *bast);
+
+enum dlm_status dlmunlock(struct dlm_ctxt *dlm,
+ struct dlm_lockstatus *lksb,
+ int flags,
+ dlm_astunlockfunc_t *unlockast,
+ void *data);
+
+struct dlm_ctxt * dlm_register_domain(const char *domain, u32 key);
+
+void dlm_unregister_domain(struct dlm_ctxt *dlm);
+
+void dlm_print_one_lock(struct dlm_lock *lockid);
+
+typedef void (dlm_eviction_func)(int, void *);
+struct dlm_eviction_cb {
+ struct list_head ec_item;
+ dlm_eviction_func *ec_func;
+ void *ec_data;
+};
+void dlm_setup_eviction_cb(struct dlm_eviction_cb *cb,
+ dlm_eviction_func *f,
+ void *data);
+void dlm_register_eviction_cb(struct dlm_ctxt *dlm,
+ struct dlm_eviction_cb *cb);
+void dlm_unregister_eviction_cb(struct dlm_eviction_cb *cb);
+
+#endif /* DLMAPI_H */
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
new file mode 100644
index 000000000000..8d17d28ef91c
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -0,0 +1,466 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmast.c
+ *
+ * AST and BAST functionality for local and remote nodes
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/spinlock.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+#include "cluster/endian.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+
+#define MLOG_MASK_PREFIX ML_DLM
+#include "cluster/masklog.h"
+
+static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+static int dlm_should_cancel_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
+
+/* Should be called as an ast gets queued to see if the new
+ * lock level will obsolete a pending bast.
+ * For example, if dlm_thread queued a bast for an EX lock that
+ * was blocking another EX, but before sending the bast the
+ * lock owner downconverted to NL, the bast is now obsolete.
+ * Only the ast should be sent.
+ * This is needed because the lock and convert paths can queue
+ * asts out-of-band (not waiting for dlm_thread) in order to
+ * allow for LKM_NOQUEUE to get immediate responses. */
+static int dlm_should_cancel_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ assert_spin_locked(&dlm->ast_lock);
+ assert_spin_locked(&lock->spinlock);
+
+ if (lock->ml.highest_blocked == LKM_IVMODE)
+ return 0;
+ BUG_ON(lock->ml.highest_blocked == LKM_NLMODE);
+
+ if (lock->bast_pending &&
+ list_empty(&lock->bast_list))
+ /* old bast already sent, ok */
+ return 0;
+
+ if (lock->ml.type == LKM_EXMODE)
+ /* EX blocks anything left, any bast still valid */
+ return 0;
+ else if (lock->ml.type == LKM_NLMODE)
+ /* NL blocks nothing, no reason to send any bast, cancel it */
+ return 1;
+ else if (lock->ml.highest_blocked != LKM_EXMODE)
+ /* PR only blocks EX */
+ return 1;
+
+ return 0;
+}
+
+static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ mlog_entry_void();
+
+ BUG_ON(!dlm);
+ BUG_ON(!lock);
+
+ assert_spin_locked(&dlm->ast_lock);
+ if (!list_empty(&lock->ast_list)) {
+ mlog(ML_ERROR, "ast list not empty!! pending=%d, newlevel=%d\n",
+ lock->ast_pending, lock->ml.type);
+ BUG();
+ }
+ BUG_ON(!list_empty(&lock->ast_list));
+ if (lock->ast_pending)
+ mlog(0, "lock has an ast getting flushed right now\n");
+
+ /* putting lock on list, add a ref */
+ dlm_lock_get(lock);
+ spin_lock(&lock->spinlock);
+
+ /* check to see if this ast obsoletes the bast */
+ if (dlm_should_cancel_bast(dlm, lock)) {
+ struct dlm_lock_resource *res = lock->lockres;
+ mlog(0, "%s: cancelling bast for %.*s\n",
+ dlm->name, res->lockname.len, res->lockname.name);
+ lock->bast_pending = 0;
+ list_del_init(&lock->bast_list);
+ lock->ml.highest_blocked = LKM_IVMODE;
+ /* removing lock from list, remove a ref. guaranteed
+ * this won't be the last ref because of the get above,
+ * so res->spinlock will not be taken here */
+ dlm_lock_put(lock);
+ /* free up the reserved bast that we are cancelling.
+ * guaranteed that this will not be the last reserved
+ * ast because *both* an ast and a bast were reserved
+ * to get to this point. the res->spinlock will not be
+ * taken here */
+ dlm_lockres_release_ast(dlm, res);
+ }
+ list_add_tail(&lock->ast_list, &dlm->pending_asts);
+ lock->ast_pending = 1;
+ spin_unlock(&lock->spinlock);
+}
+
+void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ mlog_entry_void();
+
+ BUG_ON(!dlm);
+ BUG_ON(!lock);
+
+ spin_lock(&dlm->ast_lock);
+ __dlm_queue_ast(dlm, lock);
+ spin_unlock(&dlm->ast_lock);
+}
+
+
+static void __dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ mlog_entry_void();
+
+ BUG_ON(!dlm);
+ BUG_ON(!lock);
+ assert_spin_locked(&dlm->ast_lock);
+
+ BUG_ON(!list_empty(&lock->bast_list));
+ if (lock->bast_pending)
+ mlog(0, "lock has a bast getting flushed right now\n");
+
+ /* putting lock on list, add a ref */
+ dlm_lock_get(lock);
+ spin_lock(&lock->spinlock);
+ list_add_tail(&lock->bast_list, &dlm->pending_basts);
+ lock->bast_pending = 1;
+ spin_unlock(&lock->spinlock);
+}
+
+void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ mlog_entry_void();
+
+ BUG_ON(!dlm);
+ BUG_ON(!lock);
+
+ spin_lock(&dlm->ast_lock);
+ __dlm_queue_bast(dlm, lock);
+ spin_unlock(&dlm->ast_lock);
+}
+
+static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ struct dlm_lockstatus *lksb = lock->lksb;
+ BUG_ON(!lksb);
+
+ /* only updates if this node masters the lockres */
+ if (res->owner == dlm->node_num) {
+
+ spin_lock(&res->spinlock);
+ /* check the lksb flags for the direction */
+ if (lksb->flags & DLM_LKSB_GET_LVB) {
+ mlog(0, "getting lvb from lockres for %s node\n",
+ lock->ml.node == dlm->node_num ? "master" :
+ "remote");
+ memcpy(lksb->lvb, res->lvb, DLM_LVB_LEN);
+ } else if (lksb->flags & DLM_LKSB_PUT_LVB) {
+ mlog(0, "setting lvb from lockres for %s node\n",
+ lock->ml.node == dlm->node_num ? "master" :
+ "remote");
+ memcpy(res->lvb, lksb->lvb, DLM_LVB_LEN);
+ }
+ spin_unlock(&res->spinlock);
+ }
+
+ /* reset any lvb flags on the lksb */
+ lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB);
+}
+
+void dlm_do_local_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ dlm_astlockfunc_t *fn;
+ struct dlm_lockstatus *lksb;
+
+ mlog_entry_void();
+
+ lksb = lock->lksb;
+ fn = lock->ast;
+ BUG_ON(lock->ml.node != dlm->node_num);
+
+ dlm_update_lvb(dlm, res, lock);
+ (*fn)(lock->astdata);
+}
+
+
+int dlm_do_remote_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ int ret;
+ struct dlm_lockstatus *lksb;
+ int lksbflags;
+
+ mlog_entry_void();
+
+ lksb = lock->lksb;
+ BUG_ON(lock->ml.node == dlm->node_num);
+
+ lksbflags = lksb->flags;
+ dlm_update_lvb(dlm, res, lock);
+
+ /* lock request came from another node
+ * go do the ast over there */
+ ret = dlm_send_proxy_ast(dlm, res, lock, lksbflags);
+ return ret;
+}
+
+void dlm_do_local_bast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int blocked_type)
+{
+ dlm_bastlockfunc_t *fn = lock->bast;
+
+ mlog_entry_void();
+ BUG_ON(lock->ml.node != dlm->node_num);
+
+ (*fn)(lock->astdata, blocked_type);
+}
+
+
+
+int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ int ret;
+ unsigned int locklen;
+ struct dlm_ctxt *dlm = data;
+ struct dlm_lock_resource *res = NULL;
+ struct dlm_lock *lock = NULL;
+ struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf;
+ char *name;
+ struct list_head *iter, *head=NULL;
+ u64 cookie;
+ u32 flags;
+
+ if (!dlm_grab(dlm)) {
+ dlm_error(DLM_REJECTED);
+ return DLM_REJECTED;
+ }
+
+ mlog_bug_on_msg(!dlm_domain_fully_joined(dlm),
+ "Domain %s not fully joined!\n", dlm->name);
+
+ name = past->name;
+ locklen = past->namelen;
+ cookie = be64_to_cpu(past->cookie);
+ flags = be32_to_cpu(past->flags);
+
+ if (locklen > DLM_LOCKID_NAME_MAX) {
+ ret = DLM_IVBUFLEN;
+ mlog(ML_ERROR, "Invalid name length in proxy ast handler!\n");
+ goto leave;
+ }
+
+ if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) ==
+ (LKM_PUT_LVB|LKM_GET_LVB)) {
+ mlog(ML_ERROR, "both PUT and GET lvb specified\n");
+ ret = DLM_BADARGS;
+ goto leave;
+ }
+
+ mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" :
+ (flags & LKM_GET_LVB ? "get lvb" : "none"));
+
+ mlog(0, "type=%d, blocked_type=%d\n", past->type, past->blocked_type);
+
+ if (past->type != DLM_AST &&
+ past->type != DLM_BAST) {
+ mlog(ML_ERROR, "Unknown ast type! %d, cookie=%"MLFu64", "
+ "name=%.*s\n", past->type, cookie, locklen, name);
+ ret = DLM_IVLOCKID;
+ goto leave;
+ }
+
+ res = dlm_lookup_lockres(dlm, name, locklen);
+ if (!res) {
+ mlog(ML_ERROR, "got %sast for unknown lockres! "
+ "cookie=%"MLFu64", name=%.*s, namelen=%u\n",
+ past->type == DLM_AST ? "" : "b",
+ cookie, locklen, name, locklen);
+ ret = DLM_IVLOCKID;
+ goto leave;
+ }
+
+ /* cannot get a proxy ast message if this node owns it */
+ BUG_ON(res->owner == dlm->node_num);
+
+ mlog(0, "lockres %.*s\n", res->lockname.len, res->lockname.name);
+
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ mlog(0, "responding with DLM_RECOVERING!\n");
+ ret = DLM_RECOVERING;
+ goto unlock_out;
+ }
+ if (res->state & DLM_LOCK_RES_MIGRATING) {
+ mlog(0, "responding with DLM_MIGRATING!\n");
+ ret = DLM_MIGRATING;
+ goto unlock_out;
+ }
+ /* try convert queue for both ast/bast */
+ head = &res->converting;
+ lock = NULL;
+ list_for_each(iter, head) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (be64_to_cpu(lock->ml.cookie) == cookie)
+ goto do_ast;
+ }
+
+ /* if not on convert, try blocked for ast, granted for bast */
+ if (past->type == DLM_AST)
+ head = &res->blocked;
+ else
+ head = &res->granted;
+
+ list_for_each(iter, head) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (be64_to_cpu(lock->ml.cookie) == cookie)
+ goto do_ast;
+ }
+
+ mlog(ML_ERROR, "got %sast for unknown lock! cookie=%"MLFu64", "
+ "name=%.*s, namelen=%u\n",
+ past->type == DLM_AST ? "" : "b", cookie, locklen, name, locklen);
+
+ ret = DLM_NORMAL;
+unlock_out:
+ spin_unlock(&res->spinlock);
+ goto leave;
+
+do_ast:
+ ret = DLM_NORMAL;
+ if (past->type == DLM_AST) {
+ /* do not alter lock refcount. switching lists. */
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, &res->granted);
+ mlog(0, "ast: adding to granted list... type=%d, "
+ "convert_type=%d\n", lock->ml.type, lock->ml.convert_type);
+ if (lock->ml.convert_type != LKM_IVMODE) {
+ lock->ml.type = lock->ml.convert_type;
+ lock->ml.convert_type = LKM_IVMODE;
+ } else {
+ // should already be there....
+ }
+
+ lock->lksb->status = DLM_NORMAL;
+
+ /* if we requested the lvb, fetch it into our lksb now */
+ if (flags & LKM_GET_LVB) {
+ BUG_ON(!(lock->lksb->flags & DLM_LKSB_GET_LVB));
+ memcpy(lock->lksb->lvb, past->lvb, DLM_LVB_LEN);
+ }
+ }
+ spin_unlock(&res->spinlock);
+
+ if (past->type == DLM_AST)
+ dlm_do_local_ast(dlm, res, lock);
+ else
+ dlm_do_local_bast(dlm, res, lock, past->blocked_type);
+
+leave:
+
+ if (res)
+ dlm_lockres_put(res);
+
+ dlm_put(dlm);
+ return ret;
+}
+
+
+
+int dlm_send_proxy_ast_msg(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int msg_type,
+ int blocked_type, int flags)
+{
+ int ret = 0;
+ struct dlm_proxy_ast past;
+ struct kvec vec[2];
+ size_t veclen = 1;
+ int status;
+
+ mlog_entry("res %.*s, to=%u, type=%d, blocked_type=%d\n",
+ res->lockname.len, res->lockname.name, lock->ml.node,
+ msg_type, blocked_type);
+
+ memset(&past, 0, sizeof(struct dlm_proxy_ast));
+ past.node_idx = dlm->node_num;
+ past.type = msg_type;
+ past.blocked_type = blocked_type;
+ past.namelen = res->lockname.len;
+ memcpy(past.name, res->lockname.name, past.namelen);
+ past.cookie = lock->ml.cookie;
+
+ vec[0].iov_len = sizeof(struct dlm_proxy_ast);
+ vec[0].iov_base = &past;
+ if (flags & DLM_LKSB_GET_LVB) {
+ mlog(0, "returning requested LVB data\n");
+ be32_add_cpu(&past.flags, LKM_GET_LVB);
+ vec[1].iov_len = DLM_LVB_LEN;
+ vec[1].iov_base = lock->lksb->lvb;
+ veclen++;
+ }
+
+ ret = o2net_send_message_vec(DLM_PROXY_AST_MSG, dlm->key, vec, veclen,
+ lock->ml.node, &status);
+ if (ret < 0)
+ mlog_errno(ret);
+ else {
+ if (status == DLM_RECOVERING) {
+ mlog(ML_ERROR, "sent AST to node %u, it thinks this "
+ "node is dead!\n", lock->ml.node);
+ BUG();
+ } else if (status == DLM_MIGRATING) {
+ mlog(ML_ERROR, "sent AST to node %u, it returned "
+ "DLM_MIGRATING!\n", lock->ml.node);
+ BUG();
+ } else if (status != DLM_NORMAL) {
+ mlog(ML_ERROR, "AST to node %u returned %d!\n",
+ lock->ml.node, status);
+ /* ignore it */
+ }
+ ret = 0;
+ }
+ return ret;
+}
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
new file mode 100644
index 000000000000..3fecba0a6023
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -0,0 +1,884 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmcommon.h
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef DLMCOMMON_H
+#define DLMCOMMON_H
+
+#include <linux/kref.h>
+
+#define DLM_HB_NODE_DOWN_PRI (0xf000000)
+#define DLM_HB_NODE_UP_PRI (0x8000000)
+
+#define DLM_LOCKID_NAME_MAX 32
+
+#define DLM_DOMAIN_NAME_MAX_LEN 255
+#define DLM_LOCK_RES_OWNER_UNKNOWN O2NM_MAX_NODES
+#define DLM_THREAD_SHUFFLE_INTERVAL 5 // flush everything every 5 passes
+#define DLM_THREAD_MS 200 // flush at least every 200 ms
+
+#define DLM_HASH_BITS 7
+#define DLM_HASH_SIZE (1 << DLM_HASH_BITS)
+#define DLM_HASH_MASK (DLM_HASH_SIZE - 1)
+
+enum dlm_ast_type {
+ DLM_AST = 0,
+ DLM_BAST,
+ DLM_ASTUNLOCK
+};
+
+
+#define LKM_VALID_FLAGS (LKM_VALBLK | LKM_CONVERT | LKM_UNLOCK | \
+ LKM_CANCEL | LKM_INVVALBLK | LKM_FORCE | \
+ LKM_RECOVERY | LKM_LOCAL | LKM_NOQUEUE)
+
+#define DLM_RECOVERY_LOCK_NAME "$RECOVERY"
+#define DLM_RECOVERY_LOCK_NAME_LEN 9
+
+static inline int dlm_is_recovery_lock(const char *lock_name, int name_len)
+{
+ if (name_len == DLM_RECOVERY_LOCK_NAME_LEN &&
+ memcmp(lock_name, DLM_RECOVERY_LOCK_NAME, name_len)==0)
+ return 1;
+ return 0;
+}
+
+#define DLM_RECO_STATE_ACTIVE 0x0001
+
+struct dlm_recovery_ctxt
+{
+ struct list_head resources;
+ struct list_head received;
+ struct list_head node_data;
+ u8 new_master;
+ u8 dead_node;
+ u16 state;
+ unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ wait_queue_head_t event;
+};
+
+enum dlm_ctxt_state {
+ DLM_CTXT_NEW = 0,
+ DLM_CTXT_JOINED,
+ DLM_CTXT_IN_SHUTDOWN,
+ DLM_CTXT_LEAVING,
+};
+
+struct dlm_ctxt
+{
+ struct list_head list;
+ struct list_head *resources;
+ struct list_head dirty_list;
+ struct list_head purge_list;
+ struct list_head pending_asts;
+ struct list_head pending_basts;
+ unsigned int purge_count;
+ spinlock_t spinlock;
+ spinlock_t ast_lock;
+ char *name;
+ u8 node_num;
+ u32 key;
+ u8 joining_node;
+ wait_queue_head_t dlm_join_events;
+ unsigned long live_nodes_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long domain_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long recovery_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ struct dlm_recovery_ctxt reco;
+ spinlock_t master_lock;
+ struct list_head master_list;
+ struct list_head mle_hb_events;
+
+ /* these give a really vague idea of the system load */
+ atomic_t local_resources;
+ atomic_t remote_resources;
+ atomic_t unknown_resources;
+
+ /* NOTE: Next three are protected by dlm_domain_lock */
+ struct kref dlm_refs;
+ enum dlm_ctxt_state dlm_state;
+ unsigned int num_joins;
+
+ struct o2hb_callback_func dlm_hb_up;
+ struct o2hb_callback_func dlm_hb_down;
+ struct task_struct *dlm_thread_task;
+ struct task_struct *dlm_reco_thread_task;
+ wait_queue_head_t dlm_thread_wq;
+ wait_queue_head_t dlm_reco_thread_wq;
+ wait_queue_head_t ast_wq;
+ wait_queue_head_t migration_wq;
+
+ struct work_struct dispatched_work;
+ struct list_head work_list;
+ spinlock_t work_lock;
+ struct list_head dlm_domain_handlers;
+ struct list_head dlm_eviction_callbacks;
+};
+
+/* these keventd work queue items are for less-frequently
+ * called functions that cannot be directly called from the
+ * net message handlers for some reason, usually because
+ * they need to send net messages of their own. */
+void dlm_dispatch_work(void *data);
+
+struct dlm_lock_resource;
+struct dlm_work_item;
+
+typedef void (dlm_workfunc_t)(struct dlm_work_item *, void *);
+
+struct dlm_request_all_locks_priv
+{
+ u8 reco_master;
+ u8 dead_node;
+};
+
+struct dlm_mig_lockres_priv
+{
+ struct dlm_lock_resource *lockres;
+ u8 real_master;
+};
+
+struct dlm_assert_master_priv
+{
+ struct dlm_lock_resource *lockres;
+ u8 request_from;
+ u32 flags;
+ unsigned ignore_higher:1;
+};
+
+
+struct dlm_work_item
+{
+ struct list_head list;
+ dlm_workfunc_t *func;
+ struct dlm_ctxt *dlm;
+ void *data;
+ union {
+ struct dlm_request_all_locks_priv ral;
+ struct dlm_mig_lockres_priv ml;
+ struct dlm_assert_master_priv am;
+ } u;
+};
+
+static inline void dlm_init_work_item(struct dlm_ctxt *dlm,
+ struct dlm_work_item *i,
+ dlm_workfunc_t *f, void *data)
+{
+ memset(i, 0, sizeof(*i));
+ i->func = f;
+ INIT_LIST_HEAD(&i->list);
+ i->data = data;
+ i->dlm = dlm; /* must have already done a dlm_grab on this! */
+}
+
+
+
+static inline void __dlm_set_joining_node(struct dlm_ctxt *dlm,
+ u8 node)
+{
+ assert_spin_locked(&dlm->spinlock);
+
+ dlm->joining_node = node;
+ wake_up(&dlm->dlm_join_events);
+}
+
+#define DLM_LOCK_RES_UNINITED 0x00000001
+#define DLM_LOCK_RES_RECOVERING 0x00000002
+#define DLM_LOCK_RES_READY 0x00000004
+#define DLM_LOCK_RES_DIRTY 0x00000008
+#define DLM_LOCK_RES_IN_PROGRESS 0x00000010
+#define DLM_LOCK_RES_MIGRATING 0x00000020
+
+#define DLM_PURGE_INTERVAL_MS (8 * 1000)
+
+struct dlm_lock_resource
+{
+ /* WARNING: Please see the comment in dlm_init_lockres before
+ * adding fields here. */
+ struct list_head list;
+ struct kref refs;
+
+ /* please keep these next 3 in this order
+ * some funcs want to iterate over all lists */
+ struct list_head granted;
+ struct list_head converting;
+ struct list_head blocked;
+
+ struct list_head dirty;
+ struct list_head recovering; // dlm_recovery_ctxt.resources list
+
+ /* unused lock resources have their last_used stamped and are
+ * put on a list for the dlm thread to run. */
+ struct list_head purge;
+ unsigned long last_used;
+
+ unsigned migration_pending:1;
+ atomic_t asts_reserved;
+ spinlock_t spinlock;
+ wait_queue_head_t wq;
+ u8 owner; //node which owns the lock resource, or unknown
+ u16 state;
+ struct qstr lockname;
+ char lvb[DLM_LVB_LEN];
+};
+
+struct dlm_migratable_lock
+{
+ __be64 cookie;
+
+ /* these 3 are just padding for the in-memory structure, but
+ * list and flags are actually used when sent over the wire */
+ __be16 pad1;
+ u8 list; // 0=granted, 1=converting, 2=blocked
+ u8 flags;
+
+ s8 type;
+ s8 convert_type;
+ s8 highest_blocked;
+ u8 node;
+}; // 16 bytes
+
+struct dlm_lock
+{
+ struct dlm_migratable_lock ml;
+
+ struct list_head list;
+ struct list_head ast_list;
+ struct list_head bast_list;
+ struct dlm_lock_resource *lockres;
+ spinlock_t spinlock;
+ struct kref lock_refs;
+
+ // ast and bast must be callable while holding a spinlock!
+ dlm_astlockfunc_t *ast;
+ dlm_bastlockfunc_t *bast;
+ void *astdata;
+ struct dlm_lockstatus *lksb;
+ unsigned ast_pending:1,
+ bast_pending:1,
+ convert_pending:1,
+ lock_pending:1,
+ cancel_pending:1,
+ unlock_pending:1,
+ lksb_kernel_allocated:1;
+};
+
+
+#define DLM_LKSB_UNUSED1 0x01
+#define DLM_LKSB_PUT_LVB 0x02
+#define DLM_LKSB_GET_LVB 0x04
+#define DLM_LKSB_UNUSED2 0x08
+#define DLM_LKSB_UNUSED3 0x10
+#define DLM_LKSB_UNUSED4 0x20
+#define DLM_LKSB_UNUSED5 0x40
+#define DLM_LKSB_UNUSED6 0x80
+
+
+enum dlm_lockres_list {
+ DLM_GRANTED_LIST = 0,
+ DLM_CONVERTING_LIST,
+ DLM_BLOCKED_LIST
+};
+
+static inline struct list_head *
+dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx)
+{
+ struct list_head *ret = NULL;
+ if (idx == DLM_GRANTED_LIST)
+ ret = &res->granted;
+ else if (idx == DLM_CONVERTING_LIST)
+ ret = &res->converting;
+ else if (idx == DLM_BLOCKED_LIST)
+ ret = &res->blocked;
+ else
+ BUG();
+ return ret;
+}
+
+
+
+
+struct dlm_node_iter
+{
+ unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ int curnode;
+};
+
+
+enum {
+ DLM_MASTER_REQUEST_MSG = 500,
+ DLM_UNUSED_MSG1, /* 501 */
+ DLM_ASSERT_MASTER_MSG, /* 502 */
+ DLM_CREATE_LOCK_MSG, /* 503 */
+ DLM_CONVERT_LOCK_MSG, /* 504 */
+ DLM_PROXY_AST_MSG, /* 505 */
+ DLM_UNLOCK_LOCK_MSG, /* 506 */
+ DLM_UNUSED_MSG2, /* 507 */
+ DLM_MIGRATE_REQUEST_MSG, /* 508 */
+ DLM_MIG_LOCKRES_MSG, /* 509 */
+ DLM_QUERY_JOIN_MSG, /* 510 */
+ DLM_ASSERT_JOINED_MSG, /* 511 */
+ DLM_CANCEL_JOIN_MSG, /* 512 */
+ DLM_EXIT_DOMAIN_MSG, /* 513 */
+ DLM_MASTER_REQUERY_MSG, /* 514 */
+ DLM_LOCK_REQUEST_MSG, /* 515 */
+ DLM_RECO_DATA_DONE_MSG, /* 516 */
+ DLM_BEGIN_RECO_MSG, /* 517 */
+ DLM_FINALIZE_RECO_MSG /* 518 */
+};
+
+struct dlm_reco_node_data
+{
+ int state;
+ u8 node_num;
+ struct list_head list;
+};
+
+enum {
+ DLM_RECO_NODE_DATA_DEAD = -1,
+ DLM_RECO_NODE_DATA_INIT = 0,
+ DLM_RECO_NODE_DATA_REQUESTING,
+ DLM_RECO_NODE_DATA_REQUESTED,
+ DLM_RECO_NODE_DATA_RECEIVING,
+ DLM_RECO_NODE_DATA_DONE,
+ DLM_RECO_NODE_DATA_FINALIZE_SENT,
+};
+
+
+enum {
+ DLM_MASTER_RESP_NO = 0,
+ DLM_MASTER_RESP_YES,
+ DLM_MASTER_RESP_MAYBE,
+ DLM_MASTER_RESP_ERROR
+};
+
+
+struct dlm_master_request
+{
+ u8 node_idx;
+ u8 namelen;
+ __be16 pad1;
+ __be32 flags;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+};
+
+#define DLM_ASSERT_MASTER_MLE_CLEANUP 0x00000001
+#define DLM_ASSERT_MASTER_REQUERY 0x00000002
+#define DLM_ASSERT_MASTER_FINISH_MIGRATION 0x00000004
+struct dlm_assert_master
+{
+ u8 node_idx;
+ u8 namelen;
+ __be16 pad1;
+ __be32 flags;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_migrate_request
+{
+ u8 master;
+ u8 new_master;
+ u8 namelen;
+ u8 pad1;
+ __be32 pad2;
+ u8 name[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_master_requery
+{
+ u8 pad1;
+ u8 pad2;
+ u8 node_idx;
+ u8 namelen;
+ __be32 pad3;
+ u8 name[O2NM_MAX_NAME_LEN];
+};
+
+#define DLM_MRES_RECOVERY 0x01
+#define DLM_MRES_MIGRATION 0x02
+#define DLM_MRES_ALL_DONE 0x04
+
+/*
+ * We would like to get one whole lockres into a single network
+ * message whenever possible. Generally speaking, there will be
+ * at most one dlm_lock on a lockres for each node in the cluster,
+ * plus (infrequently) any additional locks coming in from userdlm.
+ *
+ * struct _dlm_lockres_page
+ * {
+ * dlm_migratable_lockres mres;
+ * dlm_migratable_lock ml[DLM_MAX_MIGRATABLE_LOCKS];
+ * u8 pad[DLM_MIG_LOCKRES_RESERVED];
+ * };
+ *
+ * from ../cluster/tcp.h
+ * NET_MAX_PAYLOAD_BYTES (4096 - sizeof(net_msg))
+ * (roughly 4080 bytes)
+ * and sizeof(dlm_migratable_lockres) = 112 bytes
+ * and sizeof(dlm_migratable_lock) = 16 bytes
+ *
+ * Choosing DLM_MAX_MIGRATABLE_LOCKS=240 and
+ * DLM_MIG_LOCKRES_RESERVED=128 means we have this:
+ *
+ * (DLM_MAX_MIGRATABLE_LOCKS * sizeof(dlm_migratable_lock)) +
+ * sizeof(dlm_migratable_lockres) + DLM_MIG_LOCKRES_RESERVED =
+ * NET_MAX_PAYLOAD_BYTES
+ * (240 * 16) + 112 + 128 = 4080
+ *
+ * So a lockres would need more than 240 locks before it would
+ * use more than one network packet to recover. Not too bad.
+ */
+#define DLM_MAX_MIGRATABLE_LOCKS 240
+
+struct dlm_migratable_lockres
+{
+ u8 master;
+ u8 lockname_len;
+ u8 num_locks; // locks sent in this structure
+ u8 flags;
+ __be32 total_locks; // locks to be sent for this migration cookie
+ __be64 mig_cookie; // cookie for this lockres migration
+ // or zero if not needed
+ // 16 bytes
+ u8 lockname[DLM_LOCKID_NAME_MAX];
+ // 48 bytes
+ u8 lvb[DLM_LVB_LEN];
+ // 112 bytes
+ struct dlm_migratable_lock ml[0]; // 16 bytes each, begins at byte 112
+};
+#define DLM_MIG_LOCKRES_MAX_LEN \
+ (sizeof(struct dlm_migratable_lockres) + \
+ (sizeof(struct dlm_migratable_lock) * \
+ DLM_MAX_MIGRATABLE_LOCKS) )
+
+/* from above, 128 bytes
+ * for some undetermined future use */
+#define DLM_MIG_LOCKRES_RESERVED (NET_MAX_PAYLOAD_BYTES - \
+ DLM_MIG_LOCKRES_MAX_LEN)
+
+struct dlm_create_lock
+{
+ __be64 cookie;
+
+ __be32 flags;
+ u8 pad1;
+ u8 node_idx;
+ s8 requested_type;
+ u8 namelen;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_convert_lock
+{
+ __be64 cookie;
+
+ __be32 flags;
+ u8 pad1;
+ u8 node_idx;
+ s8 requested_type;
+ u8 namelen;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+
+ s8 lvb[0];
+};
+#define DLM_CONVERT_LOCK_MAX_LEN (sizeof(struct dlm_convert_lock)+DLM_LVB_LEN)
+
+struct dlm_unlock_lock
+{
+ __be64 cookie;
+
+ __be32 flags;
+ __be16 pad1;
+ u8 node_idx;
+ u8 namelen;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+
+ s8 lvb[0];
+};
+#define DLM_UNLOCK_LOCK_MAX_LEN (sizeof(struct dlm_unlock_lock)+DLM_LVB_LEN)
+
+struct dlm_proxy_ast
+{
+ __be64 cookie;
+
+ __be32 flags;
+ u8 node_idx;
+ u8 type;
+ u8 blocked_type;
+ u8 namelen;
+
+ u8 name[O2NM_MAX_NAME_LEN];
+
+ s8 lvb[0];
+};
+#define DLM_PROXY_AST_MAX_LEN (sizeof(struct dlm_proxy_ast)+DLM_LVB_LEN)
+
+#define DLM_MOD_KEY (0x666c6172)
+enum dlm_query_join_response {
+ JOIN_DISALLOW = 0,
+ JOIN_OK,
+ JOIN_OK_NO_MAP,
+};
+
+struct dlm_lock_request
+{
+ u8 node_idx;
+ u8 dead_node;
+ __be16 pad1;
+ __be32 pad2;
+};
+
+struct dlm_reco_data_done
+{
+ u8 node_idx;
+ u8 dead_node;
+ __be16 pad1;
+ __be32 pad2;
+
+ /* unused for now */
+ /* eventually we can use this to attempt
+ * lvb recovery based on each node's info */
+ u8 reco_lvb[DLM_LVB_LEN];
+};
+
+struct dlm_begin_reco
+{
+ u8 node_idx;
+ u8 dead_node;
+ __be16 pad1;
+ __be32 pad2;
+};
+
+
+struct dlm_query_join_request
+{
+ u8 node_idx;
+ u8 pad1[2];
+ u8 name_len;
+ u8 domain[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_assert_joined
+{
+ u8 node_idx;
+ u8 pad1[2];
+ u8 name_len;
+ u8 domain[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_cancel_join
+{
+ u8 node_idx;
+ u8 pad1[2];
+ u8 name_len;
+ u8 domain[O2NM_MAX_NAME_LEN];
+};
+
+struct dlm_exit_domain
+{
+ u8 node_idx;
+ u8 pad1[3];
+};
+
+struct dlm_finalize_reco
+{
+ u8 node_idx;
+ u8 dead_node;
+ __be16 pad1;
+ __be32 pad2;
+};
+
+static inline enum dlm_status
+__dlm_lockres_state_to_status(struct dlm_lock_resource *res)
+{
+ enum dlm_status status = DLM_NORMAL;
+
+ assert_spin_locked(&res->spinlock);
+
+ if (res->state & DLM_LOCK_RES_RECOVERING)
+ status = DLM_RECOVERING;
+ else if (res->state & DLM_LOCK_RES_MIGRATING)
+ status = DLM_MIGRATING;
+ else if (res->state & DLM_LOCK_RES_IN_PROGRESS)
+ status = DLM_FORWARD;
+
+ return status;
+}
+
+struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
+ struct dlm_lockstatus *lksb);
+void dlm_lock_get(struct dlm_lock *lock);
+void dlm_lock_put(struct dlm_lock *lock);
+
+void dlm_lock_attach_lockres(struct dlm_lock *lock,
+ struct dlm_lock_resource *res);
+
+int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data);
+
+void dlm_revert_pending_convert(struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+void dlm_revert_pending_lock(struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+
+int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data);
+void dlm_commit_pending_cancel(struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+void dlm_commit_pending_unlock(struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+
+int dlm_launch_thread(struct dlm_ctxt *dlm);
+void dlm_complete_thread(struct dlm_ctxt *dlm);
+int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
+void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
+void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
+
+void dlm_put(struct dlm_ctxt *dlm);
+struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
+int dlm_domain_fully_joined(struct dlm_ctxt *dlm);
+
+void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+void dlm_purge_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *lockres);
+void dlm_lockres_get(struct dlm_lock_resource *res);
+void dlm_lockres_put(struct dlm_lock_resource *res);
+void __dlm_unhash_lockres(struct dlm_lock_resource *res);
+void __dlm_insert_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int len);
+struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int len);
+
+int dlm_is_host_down(int errno);
+void dlm_change_lockres_owner(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 owner);
+struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
+ const char *lockid,
+ int flags);
+struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int namelen);
+
+void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
+void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
+void dlm_do_local_ast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+int dlm_do_remote_ast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock);
+void dlm_do_local_bast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ int blocked_type);
+int dlm_send_proxy_ast_msg(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ int msg_type,
+ int blocked_type, int flags);
+static inline int dlm_send_proxy_bast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ int blocked_type)
+{
+ return dlm_send_proxy_ast_msg(dlm, res, lock, DLM_BAST,
+ blocked_type, 0);
+}
+
+static inline int dlm_send_proxy_ast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ int flags)
+{
+ return dlm_send_proxy_ast_msg(dlm, res, lock, DLM_AST,
+ 0, flags);
+}
+
+void dlm_print_one_lock_resource(struct dlm_lock_resource *res);
+void __dlm_print_one_lock_resource(struct dlm_lock_resource *res);
+
+u8 dlm_nm_this_node(struct dlm_ctxt *dlm);
+void dlm_kick_thread(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
+void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
+
+
+int dlm_nm_init(struct dlm_ctxt *dlm);
+int dlm_heartbeat_init(struct dlm_ctxt *dlm);
+void dlm_hb_node_down_cb(struct o2nm_node *node, int idx, void *data);
+void dlm_hb_node_up_cb(struct o2nm_node *node, int idx, void *data);
+
+int dlm_lockres_is_dirty(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
+int dlm_migrate_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 target);
+int dlm_finish_migration(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 old_master);
+void dlm_lockres_release_ast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+void __dlm_lockres_reserve_ast(struct dlm_lock_resource *res);
+
+int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data);
+int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data);
+
+int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ int ignore_higher,
+ u8 request_from,
+ u32 flags);
+
+
+int dlm_send_one_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_migratable_lockres *mres,
+ u8 send_to,
+ u8 flags);
+void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+
+/* will exit holding res->spinlock, but may drop in function */
+void __dlm_wait_on_lockres_flags(struct dlm_lock_resource *res, int flags);
+void __dlm_wait_on_lockres_flags_set(struct dlm_lock_resource *res, int flags);
+
+/* will exit holding res->spinlock, but may drop in function */
+static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
+{
+ __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_IN_PROGRESS|
+ DLM_LOCK_RES_RECOVERING|
+ DLM_LOCK_RES_MIGRATING));
+}
+
+
+int dlm_init_mle_cache(void);
+void dlm_destroy_mle_cache(void);
+void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up);
+void dlm_clean_master_list(struct dlm_ctxt *dlm,
+ u8 dead_node);
+int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock);
+
+
+static inline const char * dlm_lock_mode_name(int mode)
+{
+ switch (mode) {
+ case LKM_EXMODE:
+ return "EX";
+ case LKM_PRMODE:
+ return "PR";
+ case LKM_NLMODE:
+ return "NL";
+ }
+ return "UNKNOWN";
+}
+
+
+static inline int dlm_lock_compatible(int existing, int request)
+{
+ /* NO_LOCK compatible with all */
+ if (request == LKM_NLMODE ||
+ existing == LKM_NLMODE)
+ return 1;
+
+ /* EX incompatible with all non-NO_LOCK */
+ if (request == LKM_EXMODE)
+ return 0;
+
+ /* request must be PR, which is compatible with PR */
+ if (existing == LKM_PRMODE)
+ return 1;
+
+ return 0;
+}
+
+static inline int dlm_lock_on_list(struct list_head *head,
+ struct dlm_lock *lock)
+{
+ struct list_head *iter;
+ struct dlm_lock *tmplock;
+
+ list_for_each(iter, head) {
+ tmplock = list_entry(iter, struct dlm_lock, list);
+ if (tmplock == lock)
+ return 1;
+ }
+ return 0;
+}
+
+
+static inline enum dlm_status dlm_err_to_dlm_status(int err)
+{
+ enum dlm_status ret;
+ if (err == -ENOMEM)
+ ret = DLM_SYSERR;
+ else if (err == -ETIMEDOUT || o2net_link_down(err, NULL))
+ ret = DLM_NOLOCKMGR;
+ else if (err == -EINVAL)
+ ret = DLM_BADPARAM;
+ else if (err == -ENAMETOOLONG)
+ ret = DLM_IVBUFLEN;
+ else
+ ret = DLM_BADARGS;
+ return ret;
+}
+
+
+static inline void dlm_node_iter_init(unsigned long *map,
+ struct dlm_node_iter *iter)
+{
+ memcpy(iter->node_map, map, sizeof(iter->node_map));
+ iter->curnode = -1;
+}
+
+static inline int dlm_node_iter_next(struct dlm_node_iter *iter)
+{
+ int bit;
+ bit = find_next_bit(iter->node_map, O2NM_MAX_NODES, iter->curnode+1);
+ if (bit >= O2NM_MAX_NODES) {
+ iter->curnode = O2NM_MAX_NODES;
+ return -ENOENT;
+ }
+ iter->curnode = bit;
+ return bit;
+}
+
+
+
+#endif /* DLMCOMMON_H */
diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c
new file mode 100644
index 000000000000..6001b22a997d
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmconvert.c
@@ -0,0 +1,530 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmconvert.c
+ *
+ * underlying calls for lock conversion
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/spinlock.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+
+#include "dlmconvert.h"
+
+#define MLOG_MASK_PREFIX ML_DLM
+#include "cluster/masklog.h"
+
+/* NOTE: __dlmconvert_master is the only function in here that
+ * needs a spinlock held on entry (res->spinlock) and it is the
+ * only one that holds a lock on exit (res->spinlock).
+ * All other functions in here need no locks and drop all of
+ * the locks that they acquire. */
+static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags,
+ int type, int *call_ast,
+ int *kick_thread);
+static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type);
+
+/*
+ * this is only called directly by dlmlock(), and only when the
+ * local node is the owner of the lockres
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock
+ * held on exit: none
+ * returns: see __dlmconvert_master
+ */
+enum dlm_status dlmconvert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type)
+{
+ int call_ast = 0, kick_thread = 0;
+ enum dlm_status status;
+
+ spin_lock(&res->spinlock);
+ /* we are not in a network handler, this is fine */
+ __dlm_wait_on_lockres(res);
+ __dlm_lockres_reserve_ast(res);
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+
+ status = __dlmconvert_master(dlm, res, lock, flags, type,
+ &call_ast, &kick_thread);
+
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+ if (status != DLM_NORMAL && status != DLM_NOTQUEUED)
+ dlm_error(status);
+
+ /* either queue the ast or release it */
+ if (call_ast)
+ dlm_queue_ast(dlm, lock);
+ else
+ dlm_lockres_release_ast(dlm, res);
+
+ if (kick_thread)
+ dlm_kick_thread(dlm, res);
+
+ return status;
+}
+
+/* performs lock conversion at the lockres master site
+ * locking:
+ * caller needs: res->spinlock
+ * taken: takes and drops lock->spinlock
+ * held on exit: res->spinlock
+ * returns: DLM_NORMAL, DLM_NOTQUEUED, DLM_DENIED
+ * call_ast: whether ast should be called for this lock
+ * kick_thread: whether dlm_kick_thread should be called
+ */
+static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags,
+ int type, int *call_ast,
+ int *kick_thread)
+{
+ enum dlm_status status = DLM_NORMAL;
+ struct list_head *iter;
+ struct dlm_lock *tmplock=NULL;
+
+ assert_spin_locked(&res->spinlock);
+
+ mlog_entry("type=%d, convert_type=%d, new convert_type=%d\n",
+ lock->ml.type, lock->ml.convert_type, type);
+
+ spin_lock(&lock->spinlock);
+
+ /* already converting? */
+ if (lock->ml.convert_type != LKM_IVMODE) {
+ mlog(ML_ERROR, "attempted to convert a lock with a lock "
+ "conversion pending\n");
+ status = DLM_DENIED;
+ goto unlock_exit;
+ }
+
+ /* must be on grant queue to convert */
+ if (!dlm_lock_on_list(&res->granted, lock)) {
+ mlog(ML_ERROR, "attempted to convert a lock not on grant "
+ "queue\n");
+ status = DLM_DENIED;
+ goto unlock_exit;
+ }
+
+ if (flags & LKM_VALBLK) {
+ switch (lock->ml.type) {
+ case LKM_EXMODE:
+ /* EX + LKM_VALBLK + convert == set lvb */
+ mlog(0, "will set lvb: converting %s->%s\n",
+ dlm_lock_mode_name(lock->ml.type),
+ dlm_lock_mode_name(type));
+ lock->lksb->flags |= DLM_LKSB_PUT_LVB;
+ break;
+ case LKM_PRMODE:
+ case LKM_NLMODE:
+ /* refetch if new level is not NL */
+ if (type > LKM_NLMODE) {
+ mlog(0, "will fetch new value into "
+ "lvb: converting %s->%s\n",
+ dlm_lock_mode_name(lock->ml.type),
+ dlm_lock_mode_name(type));
+ lock->lksb->flags |= DLM_LKSB_GET_LVB;
+ } else {
+ mlog(0, "will NOT fetch new value "
+ "into lvb: converting %s->%s\n",
+ dlm_lock_mode_name(lock->ml.type),
+ dlm_lock_mode_name(type));
+ flags &= ~(LKM_VALBLK);
+ }
+ break;
+ }
+ }
+
+
+ /* in-place downconvert? */
+ if (type <= lock->ml.type)
+ goto grant;
+
+ /* upconvert from here on */
+ status = DLM_NORMAL;
+ list_for_each(iter, &res->granted) {
+ tmplock = list_entry(iter, struct dlm_lock, list);
+ if (tmplock == lock)
+ continue;
+ if (!dlm_lock_compatible(tmplock->ml.type, type))
+ goto switch_queues;
+ }
+
+ list_for_each(iter, &res->converting) {
+ tmplock = list_entry(iter, struct dlm_lock, list);
+ if (!dlm_lock_compatible(tmplock->ml.type, type))
+ goto switch_queues;
+ /* existing conversion requests take precedence */
+ if (!dlm_lock_compatible(tmplock->ml.convert_type, type))
+ goto switch_queues;
+ }
+
+ /* fall thru to grant */
+
+grant:
+ mlog(0, "res %.*s, granting %s lock\n", res->lockname.len,
+ res->lockname.name, dlm_lock_mode_name(type));
+ /* immediately grant the new lock type */
+ lock->lksb->status = DLM_NORMAL;
+ if (lock->ml.node == dlm->node_num)
+ mlog(0, "doing in-place convert for nonlocal lock\n");
+ lock->ml.type = type;
+ status = DLM_NORMAL;
+ *call_ast = 1;
+ goto unlock_exit;
+
+switch_queues:
+ if (flags & LKM_NOQUEUE) {
+ mlog(0, "failed to convert NOQUEUE lock %.*s from "
+ "%d to %d...\n", res->lockname.len, res->lockname.name,
+ lock->ml.type, type);
+ status = DLM_NOTQUEUED;
+ goto unlock_exit;
+ }
+ mlog(0, "res %.*s, queueing...\n", res->lockname.len,
+ res->lockname.name);
+
+ lock->ml.convert_type = type;
+ /* do not alter lock refcount. switching lists. */
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, &res->converting);
+
+unlock_exit:
+ spin_unlock(&lock->spinlock);
+ if (status == DLM_DENIED) {
+ __dlm_print_one_lock_resource(res);
+ }
+ if (status == DLM_NORMAL)
+ *kick_thread = 1;
+ return status;
+}
+
+void dlm_revert_pending_convert(struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ /* do not alter lock refcount. switching lists. */
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, &res->granted);
+ lock->ml.convert_type = LKM_IVMODE;
+ lock->lksb->flags &= ~(DLM_LKSB_GET_LVB|DLM_LKSB_PUT_LVB);
+}
+
+/* messages the master site to do lock conversion
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock, uses DLM_LOCK_RES_IN_PROGRESS
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_RECOVERING, status from remote node
+ */
+enum dlm_status dlmconvert_remote(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type)
+{
+ enum dlm_status status;
+
+ mlog(0, "type=%d, convert_type=%d, busy=%d\n", lock->ml.type,
+ lock->ml.convert_type, res->state & DLM_LOCK_RES_IN_PROGRESS);
+
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ mlog(0, "bailing out early since res is RECOVERING "
+ "on secondary queue\n");
+ /* __dlm_print_one_lock_resource(res); */
+ status = DLM_RECOVERING;
+ goto bail;
+ }
+ /* will exit this call with spinlock held */
+ __dlm_wait_on_lockres(res);
+
+ if (lock->ml.convert_type != LKM_IVMODE) {
+ __dlm_print_one_lock_resource(res);
+ mlog(ML_ERROR, "converting a remote lock that is already "
+ "converting! (cookie=%"MLFu64", conv=%d)\n",
+ lock->ml.cookie, lock->ml.convert_type);
+ status = DLM_DENIED;
+ goto bail;
+ }
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+ /* move lock to local convert queue */
+ /* do not alter lock refcount. switching lists. */
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, &res->converting);
+ lock->convert_pending = 1;
+ lock->ml.convert_type = type;
+
+ if (flags & LKM_VALBLK) {
+ if (lock->ml.type == LKM_EXMODE) {
+ flags |= LKM_PUT_LVB;
+ lock->lksb->flags |= DLM_LKSB_PUT_LVB;
+ } else {
+ if (lock->ml.convert_type == LKM_NLMODE)
+ flags &= ~LKM_VALBLK;
+ else {
+ flags |= LKM_GET_LVB;
+ lock->lksb->flags |= DLM_LKSB_GET_LVB;
+ }
+ }
+ }
+ spin_unlock(&res->spinlock);
+
+ /* no locks held here.
+ * need to wait for a reply as to whether it got queued or not. */
+ status = dlm_send_remote_convert_request(dlm, res, lock, flags, type);
+
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ lock->convert_pending = 0;
+ /* if it failed, move it back to granted queue */
+ if (status != DLM_NORMAL) {
+ if (status != DLM_NOTQUEUED)
+ dlm_error(status);
+ dlm_revert_pending_convert(res, lock);
+ }
+bail:
+ spin_unlock(&res->spinlock);
+
+ /* TODO: should this be a wake_one? */
+ /* wake up any IN_PROGRESS waiters */
+ wake_up(&res->wq);
+
+ return status;
+}
+
+/* sends DLM_CONVERT_LOCK_MSG to master site
+ * locking:
+ * caller needs: none
+ * taken: none
+ * held on exit: none
+ * returns: DLM_NOLOCKMGR, status from remote node
+ */
+static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type)
+{
+ struct dlm_convert_lock convert;
+ int tmpret;
+ enum dlm_status ret;
+ int status = 0;
+ struct kvec vec[2];
+ size_t veclen = 1;
+
+ mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+
+ memset(&convert, 0, sizeof(struct dlm_convert_lock));
+ convert.node_idx = dlm->node_num;
+ convert.requested_type = type;
+ convert.cookie = lock->ml.cookie;
+ convert.namelen = res->lockname.len;
+ convert.flags = cpu_to_be32(flags);
+ memcpy(convert.name, res->lockname.name, convert.namelen);
+
+ vec[0].iov_len = sizeof(struct dlm_convert_lock);
+ vec[0].iov_base = &convert;
+
+ if (flags & LKM_PUT_LVB) {
+ /* extra data to send if we are updating lvb */
+ vec[1].iov_len = DLM_LVB_LEN;
+ vec[1].iov_base = lock->lksb->lvb;
+ veclen++;
+ }
+
+ tmpret = o2net_send_message_vec(DLM_CONVERT_LOCK_MSG, dlm->key,
+ vec, veclen, res->owner, &status);
+ if (tmpret >= 0) {
+ // successfully sent and received
+ ret = status; // this is already a dlm_status
+ if (ret == DLM_RECOVERING) {
+ mlog(0, "node %u returned DLM_RECOVERING from convert "
+ "message!\n", res->owner);
+ } else if (ret == DLM_MIGRATING) {
+ mlog(0, "node %u returned DLM_MIGRATING from convert "
+ "message!\n", res->owner);
+ } else if (ret == DLM_FORWARD) {
+ mlog(0, "node %u returned DLM_FORWARD from convert "
+ "message!\n", res->owner);
+ } else if (ret != DLM_NORMAL && ret != DLM_NOTQUEUED)
+ dlm_error(ret);
+ } else {
+ mlog_errno(tmpret);
+ if (dlm_is_host_down(tmpret)) {
+ ret = DLM_RECOVERING;
+ mlog(0, "node %u died so returning DLM_RECOVERING "
+ "from convert message!\n", res->owner);
+ } else {
+ ret = dlm_err_to_dlm_status(tmpret);
+ }
+ }
+
+ return ret;
+}
+
+/* handler for DLM_CONVERT_LOCK_MSG on master site
+ * locking:
+ * caller needs: none
+ * taken: takes and drop res->spinlock
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_IVLOCKID, DLM_BADARGS,
+ * status from __dlmconvert_master
+ */
+int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_convert_lock *cnv = (struct dlm_convert_lock *)msg->buf;
+ struct dlm_lock_resource *res = NULL;
+ struct list_head *iter;
+ struct dlm_lock *lock = NULL;
+ struct dlm_lockstatus *lksb;
+ enum dlm_status status = DLM_NORMAL;
+ u32 flags;
+ int call_ast = 0, kick_thread = 0;
+
+ if (!dlm_grab(dlm)) {
+ dlm_error(DLM_REJECTED);
+ return DLM_REJECTED;
+ }
+
+ mlog_bug_on_msg(!dlm_domain_fully_joined(dlm),
+ "Domain %s not fully joined!\n", dlm->name);
+
+ if (cnv->namelen > DLM_LOCKID_NAME_MAX) {
+ status = DLM_IVBUFLEN;
+ dlm_error(status);
+ goto leave;
+ }
+
+ flags = be32_to_cpu(cnv->flags);
+
+ if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) ==
+ (LKM_PUT_LVB|LKM_GET_LVB)) {
+ mlog(ML_ERROR, "both PUT and GET lvb specified\n");
+ status = DLM_BADARGS;
+ goto leave;
+ }
+
+ mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" :
+ (flags & LKM_GET_LVB ? "get lvb" : "none"));
+
+ status = DLM_IVLOCKID;
+ res = dlm_lookup_lockres(dlm, cnv->name, cnv->namelen);
+ if (!res) {
+ dlm_error(status);
+ goto leave;
+ }
+
+ spin_lock(&res->spinlock);
+ list_for_each(iter, &res->granted) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock->ml.cookie == cnv->cookie &&
+ lock->ml.node == cnv->node_idx) {
+ dlm_lock_get(lock);
+ break;
+ }
+ lock = NULL;
+ }
+ spin_unlock(&res->spinlock);
+ if (!lock) {
+ status = DLM_IVLOCKID;
+ dlm_error(status);
+ goto leave;
+ }
+
+ /* found the lock */
+ lksb = lock->lksb;
+
+ /* see if caller needed to get/put lvb */
+ if (flags & LKM_PUT_LVB) {
+ BUG_ON(lksb->flags & (DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB));
+ lksb->flags |= DLM_LKSB_PUT_LVB;
+ memcpy(&lksb->lvb[0], &cnv->lvb[0], DLM_LVB_LEN);
+ } else if (flags & LKM_GET_LVB) {
+ BUG_ON(lksb->flags & (DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB));
+ lksb->flags |= DLM_LKSB_GET_LVB;
+ }
+
+ spin_lock(&res->spinlock);
+ status = __dlm_lockres_state_to_status(res);
+ if (status == DLM_NORMAL) {
+ __dlm_lockres_reserve_ast(res);
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+ status = __dlmconvert_master(dlm, res, lock, flags,
+ cnv->requested_type,
+ &call_ast, &kick_thread);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ }
+ spin_unlock(&res->spinlock);
+
+ if (status != DLM_NORMAL) {
+ if (status != DLM_NOTQUEUED)
+ dlm_error(status);
+ lksb->flags &= ~(DLM_LKSB_GET_LVB|DLM_LKSB_PUT_LVB);
+ }
+
+leave:
+ if (!lock)
+ mlog(ML_ERROR, "did not find lock to convert on grant queue! "
+ "cookie=%"MLFu64"\n",
+ cnv->cookie);
+ else
+ dlm_lock_put(lock);
+
+ /* either queue the ast or release it */
+ if (call_ast)
+ dlm_queue_ast(dlm, lock);
+ else
+ dlm_lockres_release_ast(dlm, res);
+
+ if (kick_thread)
+ dlm_kick_thread(dlm, res);
+
+ if (res)
+ dlm_lockres_put(res);
+
+ dlm_put(dlm);
+
+ return status;
+}
diff --git a/fs/ocfs2/dlm/dlmconvert.h b/fs/ocfs2/dlm/dlmconvert.h
new file mode 100644
index 000000000000..b2e3677df878
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmconvert.h
@@ -0,0 +1,35 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmconvert.h
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef DLMCONVERT_H
+#define DLMCONVERT_H
+
+enum dlm_status dlmconvert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type);
+enum dlm_status dlmconvert_remote(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags, int type);
+
+#endif
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
new file mode 100644
index 000000000000..f339fe27975a
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -0,0 +1,246 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmdebug.c
+ *
+ * debug functionality for the dlm
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/sysctl.h>
+#include <linux/spinlock.h>
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+#include "dlmdebug.h"
+
+#include "dlmdomain.h"
+#include "dlmdebug.h"
+
+#define MLOG_MASK_PREFIX ML_DLM
+#include "cluster/masklog.h"
+
+void dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+{
+ mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+ res->lockname.len, res->lockname.name,
+ res->owner, res->state);
+ spin_lock(&res->spinlock);
+ __dlm_print_one_lock_resource(res);
+ spin_unlock(&res->spinlock);
+}
+
+void __dlm_print_one_lock_resource(struct dlm_lock_resource *res)
+{
+ struct list_head *iter2;
+ struct dlm_lock *lock;
+
+ assert_spin_locked(&res->spinlock);
+
+ mlog(ML_NOTICE, "lockres: %.*s, owner=%u, state=%u\n",
+ res->lockname.len, res->lockname.name,
+ res->owner, res->state);
+ mlog(ML_NOTICE, " last used: %lu, on purge list: %s\n",
+ res->last_used, list_empty(&res->purge) ? "no" : "yes");
+ mlog(ML_NOTICE, " granted queue: \n");
+ list_for_each(iter2, &res->granted) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+ spin_lock(&lock->spinlock);
+ mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+ "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ list_empty(&lock->ast_list) ? 'y' : 'n',
+ lock->ast_pending ? 'y' : 'n',
+ list_empty(&lock->bast_list) ? 'y' : 'n',
+ lock->bast_pending ? 'y' : 'n');
+ spin_unlock(&lock->spinlock);
+ }
+ mlog(ML_NOTICE, " converting queue: \n");
+ list_for_each(iter2, &res->converting) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+ spin_lock(&lock->spinlock);
+ mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+ "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ list_empty(&lock->ast_list) ? 'y' : 'n',
+ lock->ast_pending ? 'y' : 'n',
+ list_empty(&lock->bast_list) ? 'y' : 'n',
+ lock->bast_pending ? 'y' : 'n');
+ spin_unlock(&lock->spinlock);
+ }
+ mlog(ML_NOTICE, " blocked queue: \n");
+ list_for_each(iter2, &res->blocked) {
+ lock = list_entry(iter2, struct dlm_lock, list);
+ spin_lock(&lock->spinlock);
+ mlog(ML_NOTICE, " type=%d, conv=%d, node=%u, "
+ "cookie=%"MLFu64", ast=(empty=%c,pend=%c), bast=(empty=%c,pend=%c)\n",
+ lock->ml.type, lock->ml.convert_type, lock->ml.node, lock->ml.cookie,
+ list_empty(&lock->ast_list) ? 'y' : 'n',
+ lock->ast_pending ? 'y' : 'n',
+ list_empty(&lock->bast_list) ? 'y' : 'n',
+ lock->bast_pending ? 'y' : 'n');
+ spin_unlock(&lock->spinlock);
+ }
+}
+
+void dlm_print_one_lock(struct dlm_lock *lockid)
+{
+ dlm_print_one_lock_resource(lockid->lockres);
+}
+EXPORT_SYMBOL_GPL(dlm_print_one_lock);
+
+void dlm_dump_lock_resources(struct dlm_ctxt *dlm)
+{
+ struct dlm_lock_resource *res;
+ struct list_head *iter;
+ struct list_head *bucket;
+ int i;
+
+ mlog(ML_NOTICE, "struct dlm_ctxt: %s, node=%u, key=%u\n",
+ dlm->name, dlm->node_num, dlm->key);
+ if (!dlm || !dlm->name) {
+ mlog(ML_ERROR, "dlm=%p\n", dlm);
+ return;
+ }
+
+ spin_lock(&dlm->spinlock);
+ for (i=0; i<DLM_HASH_SIZE; i++) {
+ bucket = &(dlm->resources[i]);
+ list_for_each(iter, bucket) {
+ res = list_entry(iter, struct dlm_lock_resource, list);
+ dlm_print_one_lock_resource(res);
+ }
+ }
+ spin_unlock(&dlm->spinlock);
+}
+
+static const char *dlm_errnames[] = {
+ [DLM_NORMAL] = "DLM_NORMAL",
+ [DLM_GRANTED] = "DLM_GRANTED",
+ [DLM_DENIED] = "DLM_DENIED",
+ [DLM_DENIED_NOLOCKS] = "DLM_DENIED_NOLOCKS",
+ [DLM_WORKING] = "DLM_WORKING",
+ [DLM_BLOCKED] = "DLM_BLOCKED",
+ [DLM_BLOCKED_ORPHAN] = "DLM_BLOCKED_ORPHAN",
+ [DLM_DENIED_GRACE_PERIOD] = "DLM_DENIED_GRACE_PERIOD",
+ [DLM_SYSERR] = "DLM_SYSERR",
+ [DLM_NOSUPPORT] = "DLM_NOSUPPORT",
+ [DLM_CANCELGRANT] = "DLM_CANCELGRANT",
+ [DLM_IVLOCKID] = "DLM_IVLOCKID",
+ [DLM_SYNC] = "DLM_SYNC",
+ [DLM_BADTYPE] = "DLM_BADTYPE",
+ [DLM_BADRESOURCE] = "DLM_BADRESOURCE",
+ [DLM_MAXHANDLES] = "DLM_MAXHANDLES",
+ [DLM_NOCLINFO] = "DLM_NOCLINFO",
+ [DLM_NOLOCKMGR] = "DLM_NOLOCKMGR",
+ [DLM_NOPURGED] = "DLM_NOPURGED",
+ [DLM_BADARGS] = "DLM_BADARGS",
+ [DLM_VOID] = "DLM_VOID",
+ [DLM_NOTQUEUED] = "DLM_NOTQUEUED",
+ [DLM_IVBUFLEN] = "DLM_IVBUFLEN",
+ [DLM_CVTUNGRANT] = "DLM_CVTUNGRANT",
+ [DLM_BADPARAM] = "DLM_BADPARAM",
+ [DLM_VALNOTVALID] = "DLM_VALNOTVALID",
+ [DLM_REJECTED] = "DLM_REJECTED",
+ [DLM_ABORT] = "DLM_ABORT",
+ [DLM_CANCEL] = "DLM_CANCEL",
+ [DLM_IVRESHANDLE] = "DLM_IVRESHANDLE",
+ [DLM_DEADLOCK] = "DLM_DEADLOCK",
+ [DLM_DENIED_NOASTS] = "DLM_DENIED_NOASTS",
+ [DLM_FORWARD] = "DLM_FORWARD",
+ [DLM_TIMEOUT] = "DLM_TIMEOUT",
+ [DLM_IVGROUPID] = "DLM_IVGROUPID",
+ [DLM_VERS_CONFLICT] = "DLM_VERS_CONFLICT",
+ [DLM_BAD_DEVICE_PATH] = "DLM_BAD_DEVICE_PATH",
+ [DLM_NO_DEVICE_PERMISSION] = "DLM_NO_DEVICE_PERMISSION",
+ [DLM_NO_CONTROL_DEVICE ] = "DLM_NO_CONTROL_DEVICE ",
+ [DLM_RECOVERING] = "DLM_RECOVERING",
+ [DLM_MIGRATING] = "DLM_MIGRATING",
+ [DLM_MAXSTATS] = "DLM_MAXSTATS",
+};
+
+static const char *dlm_errmsgs[] = {
+ [DLM_NORMAL] = "request in progress",
+ [DLM_GRANTED] = "request granted",
+ [DLM_DENIED] = "request denied",
+ [DLM_DENIED_NOLOCKS] = "request denied, out of system resources",
+ [DLM_WORKING] = "async request in progress",
+ [DLM_BLOCKED] = "lock request blocked",
+ [DLM_BLOCKED_ORPHAN] = "lock request blocked by a orphan lock",
+ [DLM_DENIED_GRACE_PERIOD] = "topological change in progress",
+ [DLM_SYSERR] = "system error",
+ [DLM_NOSUPPORT] = "unsupported",
+ [DLM_CANCELGRANT] = "can't cancel convert: already granted",
+ [DLM_IVLOCKID] = "bad lockid",
+ [DLM_SYNC] = "synchronous request granted",
+ [DLM_BADTYPE] = "bad resource type",
+ [DLM_BADRESOURCE] = "bad resource handle",
+ [DLM_MAXHANDLES] = "no more resource handles",
+ [DLM_NOCLINFO] = "can't contact cluster manager",
+ [DLM_NOLOCKMGR] = "can't contact lock manager",
+ [DLM_NOPURGED] = "can't contact purge daemon",
+ [DLM_BADARGS] = "bad api args",
+ [DLM_VOID] = "no status",
+ [DLM_NOTQUEUED] = "NOQUEUE was specified and request failed",
+ [DLM_IVBUFLEN] = "invalid resource name length",
+ [DLM_CVTUNGRANT] = "attempted to convert ungranted lock",
+ [DLM_BADPARAM] = "invalid lock mode specified",
+ [DLM_VALNOTVALID] = "value block has been invalidated",
+ [DLM_REJECTED] = "request rejected, unrecognized client",
+ [DLM_ABORT] = "blocked lock request cancelled",
+ [DLM_CANCEL] = "conversion request cancelled",
+ [DLM_IVRESHANDLE] = "invalid resource handle",
+ [DLM_DEADLOCK] = "deadlock recovery refused this request",
+ [DLM_DENIED_NOASTS] = "failed to allocate AST",
+ [DLM_FORWARD] = "request must wait for primary's response",
+ [DLM_TIMEOUT] = "timeout value for lock has expired",
+ [DLM_IVGROUPID] = "invalid group specification",
+ [DLM_VERS_CONFLICT] = "version conflicts prevent request handling",
+ [DLM_BAD_DEVICE_PATH] = "Locks device does not exist or path wrong",
+ [DLM_NO_DEVICE_PERMISSION] = "Client has insufficient perms for device",
+ [DLM_NO_CONTROL_DEVICE] = "Cannot set options on opened device ",
+ [DLM_RECOVERING] = "lock resource being recovered",
+ [DLM_MIGRATING] = "lock resource being migrated",
+ [DLM_MAXSTATS] = "invalid error number",
+};
+
+const char *dlm_errmsg(enum dlm_status err)
+{
+ if (err >= DLM_MAXSTATS || err < 0)
+ return dlm_errmsgs[DLM_MAXSTATS];
+ return dlm_errmsgs[err];
+}
+EXPORT_SYMBOL_GPL(dlm_errmsg);
+
+const char *dlm_errname(enum dlm_status err)
+{
+ if (err >= DLM_MAXSTATS || err < 0)
+ return dlm_errnames[DLM_MAXSTATS];
+ return dlm_errnames[err];
+}
+EXPORT_SYMBOL_GPL(dlm_errname);
diff --git a/fs/ocfs2/dlm/dlmdebug.h b/fs/ocfs2/dlm/dlmdebug.h
new file mode 100644
index 000000000000..6858510c3ccd
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmdebug.h
@@ -0,0 +1,30 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmdebug.h
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef DLMDEBUG_H
+#define DLMDEBUG_H
+
+void dlm_dump_lock_resources(struct dlm_ctxt *dlm);
+
+#endif
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
new file mode 100644
index 000000000000..da3c22045f89
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -0,0 +1,1469 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmdomain.c
+ *
+ * defines domain join / leave apis
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+
+#include "dlmdebug.h"
+#include "dlmdomain.h"
+
+#include "dlmver.h"
+
+#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN)
+#include "cluster/masklog.h"
+
+/*
+ *
+ * spinlock lock ordering: if multiple locks are needed, obey this ordering:
+ * dlm_domain_lock
+ * struct dlm_ctxt->spinlock
+ * struct dlm_lock_resource->spinlock
+ * struct dlm_ctxt->master_lock
+ * struct dlm_ctxt->ast_lock
+ * dlm_master_list_entry->spinlock
+ * dlm_lock->spinlock
+ *
+ */
+
+spinlock_t dlm_domain_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(dlm_domains);
+static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
+
+#define DLM_DOMAIN_BACKOFF_MS 200
+
+static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data);
+static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data);
+static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data);
+static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data);
+
+static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
+
+void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
+{
+ list_del_init(&lockres->list);
+ dlm_lockres_put(lockres);
+}
+
+void __dlm_insert_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ struct list_head *bucket;
+ struct qstr *q;
+
+ assert_spin_locked(&dlm->spinlock);
+
+ q = &res->lockname;
+ q->hash = full_name_hash(q->name, q->len);
+ bucket = &(dlm->resources[q->hash & DLM_HASH_MASK]);
+
+ /* get a reference for our hashtable */
+ dlm_lockres_get(res);
+
+ list_add_tail(&res->list, bucket);
+}
+
+struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int len)
+{
+ unsigned int hash;
+ struct list_head *iter;
+ struct dlm_lock_resource *tmpres=NULL;
+ struct list_head *bucket;
+
+ mlog_entry("%.*s\n", len, name);
+
+ assert_spin_locked(&dlm->spinlock);
+
+ hash = full_name_hash(name, len);
+
+ bucket = &(dlm->resources[hash & DLM_HASH_MASK]);
+
+ /* check for pre-existing lock */
+ list_for_each(iter, bucket) {
+ tmpres = list_entry(iter, struct dlm_lock_resource, list);
+ if (tmpres->lockname.len == len &&
+ memcmp(tmpres->lockname.name, name, len) == 0) {
+ dlm_lockres_get(tmpres);
+ break;
+ }
+
+ tmpres = NULL;
+ }
+ return tmpres;
+}
+
+struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int len)
+{
+ struct dlm_lock_resource *res;
+
+ spin_lock(&dlm->spinlock);
+ res = __dlm_lookup_lockres(dlm, name, len);
+ spin_unlock(&dlm->spinlock);
+ return res;
+}
+
+static struct dlm_ctxt * __dlm_lookup_domain_full(const char *domain, int len)
+{
+ struct dlm_ctxt *tmp = NULL;
+ struct list_head *iter;
+
+ assert_spin_locked(&dlm_domain_lock);
+
+ /* tmp->name here is always NULL terminated,
+ * but domain may not be! */
+ list_for_each(iter, &dlm_domains) {
+ tmp = list_entry (iter, struct dlm_ctxt, list);
+ if (strlen(tmp->name) == len &&
+ memcmp(tmp->name, domain, len)==0)
+ break;
+ tmp = NULL;
+ }
+
+ return tmp;
+}
+
+/* For null terminated domain strings ONLY */
+static struct dlm_ctxt * __dlm_lookup_domain(const char *domain)
+{
+ assert_spin_locked(&dlm_domain_lock);
+
+ return __dlm_lookup_domain_full(domain, strlen(domain));
+}
+
+
+/* returns true on one of two conditions:
+ * 1) the domain does not exist
+ * 2) the domain exists and it's state is "joined" */
+static int dlm_wait_on_domain_helper(const char *domain)
+{
+ int ret = 0;
+ struct dlm_ctxt *tmp = NULL;
+
+ spin_lock(&dlm_domain_lock);
+
+ tmp = __dlm_lookup_domain(domain);
+ if (!tmp)
+ ret = 1;
+ else if (tmp->dlm_state == DLM_CTXT_JOINED)
+ ret = 1;
+
+ spin_unlock(&dlm_domain_lock);
+ return ret;
+}
+
+static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
+{
+ if (dlm->resources)
+ free_page((unsigned long) dlm->resources);
+
+ if (dlm->name)
+ kfree(dlm->name);
+
+ kfree(dlm);
+}
+
+/* A little strange - this function will be called while holding
+ * dlm_domain_lock and is expected to be holding it on the way out. We
+ * will however drop and reacquire it multiple times */
+static void dlm_ctxt_release(struct kref *kref)
+{
+ struct dlm_ctxt *dlm;
+
+ dlm = container_of(kref, struct dlm_ctxt, dlm_refs);
+
+ BUG_ON(dlm->num_joins);
+ BUG_ON(dlm->dlm_state == DLM_CTXT_JOINED);
+
+ /* we may still be in the list if we hit an error during join. */
+ list_del_init(&dlm->list);
+
+ spin_unlock(&dlm_domain_lock);
+
+ mlog(0, "freeing memory from domain %s\n", dlm->name);
+
+ wake_up(&dlm_domain_events);
+
+ dlm_free_ctxt_mem(dlm);
+
+ spin_lock(&dlm_domain_lock);
+}
+
+void dlm_put(struct dlm_ctxt *dlm)
+{
+ spin_lock(&dlm_domain_lock);
+ kref_put(&dlm->dlm_refs, dlm_ctxt_release);
+ spin_unlock(&dlm_domain_lock);
+}
+
+static void __dlm_get(struct dlm_ctxt *dlm)
+{
+ kref_get(&dlm->dlm_refs);
+}
+
+/* given a questionable reference to a dlm object, gets a reference if
+ * it can find it in the list, otherwise returns NULL in which case
+ * you shouldn't trust your pointer. */
+struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm)
+{
+ struct list_head *iter;
+ struct dlm_ctxt *target = NULL;
+
+ spin_lock(&dlm_domain_lock);
+
+ list_for_each(iter, &dlm_domains) {
+ target = list_entry (iter, struct dlm_ctxt, list);
+
+ if (target == dlm) {
+ __dlm_get(target);
+ break;
+ }
+
+ target = NULL;
+ }
+
+ spin_unlock(&dlm_domain_lock);
+
+ return target;
+}
+
+int dlm_domain_fully_joined(struct dlm_ctxt *dlm)
+{
+ int ret;
+
+ spin_lock(&dlm_domain_lock);
+ ret = (dlm->dlm_state == DLM_CTXT_JOINED) ||
+ (dlm->dlm_state == DLM_CTXT_IN_SHUTDOWN);
+ spin_unlock(&dlm_domain_lock);
+
+ return ret;
+}
+
+static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
+{
+ dlm_unregister_domain_handlers(dlm);
+ dlm_complete_thread(dlm);
+ dlm_complete_recovery_thread(dlm);
+
+ /* We've left the domain. Now we can take ourselves out of the
+ * list and allow the kref stuff to help us free the
+ * memory. */
+ spin_lock(&dlm_domain_lock);
+ list_del_init(&dlm->list);
+ spin_unlock(&dlm_domain_lock);
+
+ /* Wake up anyone waiting for us to remove this domain */
+ wake_up(&dlm_domain_events);
+}
+
+static void dlm_migrate_all_locks(struct dlm_ctxt *dlm)
+{
+ int i;
+ struct dlm_lock_resource *res;
+
+ mlog(0, "Migrating locks from domain %s\n", dlm->name);
+restart:
+ spin_lock(&dlm->spinlock);
+ for (i=0; i<DLM_HASH_SIZE; i++) {
+ while (!list_empty(&dlm->resources[i])) {
+ res = list_entry(dlm->resources[i].next,
+ struct dlm_lock_resource, list);
+ /* need reference when manually grabbing lockres */
+ dlm_lockres_get(res);
+ /* this should unhash the lockres
+ * and exit with dlm->spinlock */
+ mlog(0, "purging res=%p\n", res);
+ if (dlm_lockres_is_dirty(dlm, res)) {
+ /* HACK! this should absolutely go.
+ * need to figure out why some empty
+ * lockreses are still marked dirty */
+ mlog(ML_ERROR, "lockres %.*s dirty!\n",
+ res->lockname.len, res->lockname.name);
+
+ spin_unlock(&dlm->spinlock);
+ dlm_kick_thread(dlm, res);
+ wait_event(dlm->ast_wq, !dlm_lockres_is_dirty(dlm, res));
+ dlm_lockres_put(res);
+ goto restart;
+ }
+ dlm_purge_lockres(dlm, res);
+ dlm_lockres_put(res);
+ }
+ }
+ spin_unlock(&dlm->spinlock);
+
+ mlog(0, "DONE Migrating locks from domain %s\n", dlm->name);
+}
+
+static int dlm_no_joining_node(struct dlm_ctxt *dlm)
+{
+ int ret;
+
+ spin_lock(&dlm->spinlock);
+ ret = dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN;
+ spin_unlock(&dlm->spinlock);
+
+ return ret;
+}
+
+static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm)
+{
+ /* Yikes, a double spinlock! I need domain_lock for the dlm
+ * state and the dlm spinlock for join state... Sorry! */
+again:
+ spin_lock(&dlm_domain_lock);
+ spin_lock(&dlm->spinlock);
+
+ if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "Node %d is joining, we wait on it.\n",
+ dlm->joining_node);
+ spin_unlock(&dlm->spinlock);
+ spin_unlock(&dlm_domain_lock);
+
+ wait_event(dlm->dlm_join_events, dlm_no_joining_node(dlm));
+ goto again;
+ }
+
+ dlm->dlm_state = DLM_CTXT_LEAVING;
+ spin_unlock(&dlm->spinlock);
+ spin_unlock(&dlm_domain_lock);
+}
+
+static void __dlm_print_nodes(struct dlm_ctxt *dlm)
+{
+ int node = -1;
+
+ assert_spin_locked(&dlm->spinlock);
+
+ mlog(ML_NOTICE, "Nodes in my domain (\"%s\"):\n", dlm->name);
+
+ while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
+ node + 1)) < O2NM_MAX_NODES) {
+ mlog(ML_NOTICE, " node %d\n", node);
+ }
+}
+
+static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ unsigned int node;
+ struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf;
+
+ mlog_entry("%p %u %p", msg, len, data);
+
+ if (!dlm_grab(dlm))
+ return 0;
+
+ node = exit_msg->node_idx;
+
+ mlog(0, "Node %u leaves domain %s\n", node, dlm->name);
+
+ spin_lock(&dlm->spinlock);
+ clear_bit(node, dlm->domain_map);
+ __dlm_print_nodes(dlm);
+
+ /* notify anything attached to the heartbeat events */
+ dlm_hb_event_notify_attached(dlm, node, 0);
+
+ spin_unlock(&dlm->spinlock);
+
+ dlm_put(dlm);
+
+ return 0;
+}
+
+static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm,
+ unsigned int node)
+{
+ int status;
+ struct dlm_exit_domain leave_msg;
+
+ mlog(0, "Asking node %u if we can leave the domain %s me = %u\n",
+ node, dlm->name, dlm->node_num);
+
+ memset(&leave_msg, 0, sizeof(leave_msg));
+ leave_msg.node_idx = dlm->node_num;
+
+ status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key,
+ &leave_msg, sizeof(leave_msg), node,
+ NULL);
+
+ mlog(0, "status return %d from o2net_send_message\n", status);
+
+ return status;
+}
+
+
+static void dlm_leave_domain(struct dlm_ctxt *dlm)
+{
+ int node, clear_node, status;
+
+ /* At this point we've migrated away all our locks and won't
+ * accept mastership of new ones. The dlm is responsible for
+ * almost nothing now. We make sure not to confuse any joining
+ * nodes and then commence shutdown procedure. */
+
+ spin_lock(&dlm->spinlock);
+ /* Clear ourselves from the domain map */
+ clear_bit(dlm->node_num, dlm->domain_map);
+ while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
+ 0)) < O2NM_MAX_NODES) {
+ /* Drop the dlm spinlock. This is safe wrt the domain_map.
+ * -nodes cannot be added now as the
+ * query_join_handlers knows to respond with OK_NO_MAP
+ * -we catch the right network errors if a node is
+ * removed from the map while we're sending him the
+ * exit message. */
+ spin_unlock(&dlm->spinlock);
+
+ clear_node = 1;
+
+ status = dlm_send_one_domain_exit(dlm, node);
+ if (status < 0 &&
+ status != -ENOPROTOOPT &&
+ status != -ENOTCONN) {
+ mlog(ML_NOTICE, "Error %d sending domain exit message "
+ "to node %d\n", status, node);
+
+ /* Not sure what to do here but lets sleep for
+ * a bit in case this was a transient
+ * error... */
+ msleep(DLM_DOMAIN_BACKOFF_MS);
+ clear_node = 0;
+ }
+
+ spin_lock(&dlm->spinlock);
+ /* If we're not clearing the node bit then we intend
+ * to loop back around to try again. */
+ if (clear_node)
+ clear_bit(node, dlm->domain_map);
+ }
+ spin_unlock(&dlm->spinlock);
+}
+
+int dlm_joined(struct dlm_ctxt *dlm)
+{
+ int ret = 0;
+
+ spin_lock(&dlm_domain_lock);
+
+ if (dlm->dlm_state == DLM_CTXT_JOINED)
+ ret = 1;
+
+ spin_unlock(&dlm_domain_lock);
+
+ return ret;
+}
+
+int dlm_shutting_down(struct dlm_ctxt *dlm)
+{
+ int ret = 0;
+
+ spin_lock(&dlm_domain_lock);
+
+ if (dlm->dlm_state == DLM_CTXT_IN_SHUTDOWN)
+ ret = 1;
+
+ spin_unlock(&dlm_domain_lock);
+
+ return ret;
+}
+
+void dlm_unregister_domain(struct dlm_ctxt *dlm)
+{
+ int leave = 0;
+
+ spin_lock(&dlm_domain_lock);
+ BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);
+ BUG_ON(!dlm->num_joins);
+
+ dlm->num_joins--;
+ if (!dlm->num_joins) {
+ /* We mark it "in shutdown" now so new register
+ * requests wait until we've completely left the
+ * domain. Don't use DLM_CTXT_LEAVING yet as we still
+ * want new domain joins to communicate with us at
+ * least until we've completed migration of our
+ * resources. */
+ dlm->dlm_state = DLM_CTXT_IN_SHUTDOWN;
+ leave = 1;
+ }
+ spin_unlock(&dlm_domain_lock);
+
+ if (leave) {
+ mlog(0, "shutting down domain %s\n", dlm->name);
+
+ /* We changed dlm state, notify the thread */
+ dlm_kick_thread(dlm, NULL);
+
+ dlm_migrate_all_locks(dlm);
+ dlm_mark_domain_leaving(dlm);
+ dlm_leave_domain(dlm);
+ dlm_complete_dlm_shutdown(dlm);
+ }
+ dlm_put(dlm);
+}
+EXPORT_SYMBOL_GPL(dlm_unregister_domain);
+
+static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_query_join_request *query;
+ enum dlm_query_join_response response;
+ struct dlm_ctxt *dlm = NULL;
+
+ query = (struct dlm_query_join_request *) msg->buf;
+
+ mlog(0, "node %u wants to join domain %s\n", query->node_idx,
+ query->domain);
+
+ /*
+ * If heartbeat doesn't consider the node live, tell it
+ * to back off and try again. This gives heartbeat a chance
+ * to catch up.
+ */
+ if (!o2hb_check_node_heartbeating(query->node_idx)) {
+ mlog(0, "node %u is not in our live map yet\n",
+ query->node_idx);
+
+ response = JOIN_DISALLOW;
+ goto respond;
+ }
+
+ response = JOIN_OK_NO_MAP;
+
+ spin_lock(&dlm_domain_lock);
+ dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
+ /* Once the dlm ctxt is marked as leaving then we don't want
+ * to be put in someone's domain map. */
+ if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) {
+ spin_lock(&dlm->spinlock);
+
+ if (dlm->dlm_state == DLM_CTXT_NEW &&
+ dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /*If this is a brand new context and we
+ * haven't started our join process yet, then
+ * the other node won the race. */
+ response = JOIN_OK_NO_MAP;
+ } else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* Disallow parallel joins. */
+ response = JOIN_DISALLOW;
+ } else {
+ /* Alright we're fully a part of this domain
+ * so we keep some state as to who's joining
+ * and indicate to him that needs to be fixed
+ * up. */
+ response = JOIN_OK;
+ __dlm_set_joining_node(dlm, query->node_idx);
+ }
+
+ spin_unlock(&dlm->spinlock);
+ }
+ spin_unlock(&dlm_domain_lock);
+
+respond:
+ mlog(0, "We respond with %u\n", response);
+
+ return response;
+}
+
+static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_assert_joined *assert;
+ struct dlm_ctxt *dlm = NULL;
+
+ assert = (struct dlm_assert_joined *) msg->buf;
+
+ mlog(0, "node %u asserts join on domain %s\n", assert->node_idx,
+ assert->domain);
+
+ spin_lock(&dlm_domain_lock);
+ dlm = __dlm_lookup_domain_full(assert->domain, assert->name_len);
+ /* XXX should we consider no dlm ctxt an error? */
+ if (dlm) {
+ spin_lock(&dlm->spinlock);
+
+ /* Alright, this node has officially joined our
+ * domain. Set him in the map and clean up our
+ * leftover join state. */
+ BUG_ON(dlm->joining_node != assert->node_idx);
+ set_bit(assert->node_idx, dlm->domain_map);
+ __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
+
+ __dlm_print_nodes(dlm);
+
+ /* notify anything attached to the heartbeat events */
+ dlm_hb_event_notify_attached(dlm, assert->node_idx, 1);
+
+ spin_unlock(&dlm->spinlock);
+ }
+ spin_unlock(&dlm_domain_lock);
+
+ return 0;
+}
+
+static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_cancel_join *cancel;
+ struct dlm_ctxt *dlm = NULL;
+
+ cancel = (struct dlm_cancel_join *) msg->buf;
+
+ mlog(0, "node %u cancels join on domain %s\n", cancel->node_idx,
+ cancel->domain);
+
+ spin_lock(&dlm_domain_lock);
+ dlm = __dlm_lookup_domain_full(cancel->domain, cancel->name_len);
+
+ if (dlm) {
+ spin_lock(&dlm->spinlock);
+
+ /* Yikes, this guy wants to cancel his join. No
+ * problem, we simply cleanup our join state. */
+ BUG_ON(dlm->joining_node != cancel->node_idx);
+ __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
+
+ spin_unlock(&dlm->spinlock);
+ }
+ spin_unlock(&dlm_domain_lock);
+
+ return 0;
+}
+
+static int dlm_send_one_join_cancel(struct dlm_ctxt *dlm,
+ unsigned int node)
+{
+ int status;
+ struct dlm_cancel_join cancel_msg;
+
+ memset(&cancel_msg, 0, sizeof(cancel_msg));
+ cancel_msg.node_idx = dlm->node_num;
+ cancel_msg.name_len = strlen(dlm->name);
+ memcpy(cancel_msg.domain, dlm->name, cancel_msg.name_len);
+
+ status = o2net_send_message(DLM_CANCEL_JOIN_MSG, DLM_MOD_KEY,
+ &cancel_msg, sizeof(cancel_msg), node,
+ NULL);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ return status;
+}
+
+/* map_size should be in bytes. */
+static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
+ unsigned long *node_map,
+ unsigned int map_size)
+{
+ int status, tmpstat;
+ unsigned int node;
+
+ if (map_size != (BITS_TO_LONGS(O2NM_MAX_NODES) *
+ sizeof(unsigned long))) {
+ mlog(ML_ERROR,
+ "map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n",
+ map_size, BITS_TO_LONGS(O2NM_MAX_NODES));
+ return -EINVAL;
+ }
+
+ status = 0;
+ node = -1;
+ while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
+ node + 1)) < O2NM_MAX_NODES) {
+ if (node == dlm->node_num)
+ continue;
+
+ tmpstat = dlm_send_one_join_cancel(dlm, node);
+ if (tmpstat) {
+ mlog(ML_ERROR, "Error return %d cancelling join on "
+ "node %d\n", tmpstat, node);
+ if (!status)
+ status = tmpstat;
+ }
+ }
+
+ if (status)
+ mlog_errno(status);
+ return status;
+}
+
+static int dlm_request_join(struct dlm_ctxt *dlm,
+ int node,
+ enum dlm_query_join_response *response)
+{
+ int status, retval;
+ struct dlm_query_join_request join_msg;
+
+ mlog(0, "querying node %d\n", node);
+
+ memset(&join_msg, 0, sizeof(join_msg));
+ join_msg.node_idx = dlm->node_num;
+ join_msg.name_len = strlen(dlm->name);
+ memcpy(join_msg.domain, dlm->name, join_msg.name_len);
+
+ status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg,
+ sizeof(join_msg), node, &retval);
+ if (status < 0 && status != -ENOPROTOOPT) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* -ENOPROTOOPT from the net code means the other side isn't
+ listening for our message type -- that's fine, it means
+ his dlm isn't up, so we can consider him a 'yes' but not
+ joined into the domain. */
+ if (status == -ENOPROTOOPT) {
+ status = 0;
+ *response = JOIN_OK_NO_MAP;
+ } else if (retval == JOIN_DISALLOW ||
+ retval == JOIN_OK ||
+ retval == JOIN_OK_NO_MAP) {
+ *response = retval;
+ } else {
+ status = -EINVAL;
+ mlog(ML_ERROR, "invalid response %d from node %u\n", retval,
+ node);
+ }
+
+ mlog(0, "status %d, node %d response is %d\n", status, node,
+ *response);
+
+bail:
+ return status;
+}
+
+static int dlm_send_one_join_assert(struct dlm_ctxt *dlm,
+ unsigned int node)
+{
+ int status;
+ struct dlm_assert_joined assert_msg;
+
+ mlog(0, "Sending join assert to node %u\n", node);
+
+ memset(&assert_msg, 0, sizeof(assert_msg));
+ assert_msg.node_idx = dlm->node_num;
+ assert_msg.name_len = strlen(dlm->name);
+ memcpy(assert_msg.domain, dlm->name, assert_msg.name_len);
+
+ status = o2net_send_message(DLM_ASSERT_JOINED_MSG, DLM_MOD_KEY,
+ &assert_msg, sizeof(assert_msg), node,
+ NULL);
+ if (status < 0)
+ mlog_errno(status);
+
+ return status;
+}
+
+static void dlm_send_join_asserts(struct dlm_ctxt *dlm,
+ unsigned long *node_map)
+{
+ int status, node, live;
+
+ status = 0;
+ node = -1;
+ while ((node = find_next_bit(node_map, O2NM_MAX_NODES,
+ node + 1)) < O2NM_MAX_NODES) {
+ if (node == dlm->node_num)
+ continue;
+
+ do {
+ /* It is very important that this message be
+ * received so we spin until either the node
+ * has died or it gets the message. */
+ status = dlm_send_one_join_assert(dlm, node);
+
+ spin_lock(&dlm->spinlock);
+ live = test_bit(node, dlm->live_nodes_map);
+ spin_unlock(&dlm->spinlock);
+
+ if (status) {
+ mlog(ML_ERROR, "Error return %d asserting "
+ "join on node %d\n", status, node);
+
+ /* give us some time between errors... */
+ if (live)
+ msleep(DLM_DOMAIN_BACKOFF_MS);
+ }
+ } while (status && live);
+ }
+}
+
+struct domain_join_ctxt {
+ unsigned long live_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long yes_resp_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+};
+
+static int dlm_should_restart_join(struct dlm_ctxt *dlm,
+ struct domain_join_ctxt *ctxt,
+ enum dlm_query_join_response response)
+{
+ int ret;
+
+ if (response == JOIN_DISALLOW) {
+ mlog(0, "Latest response of disallow -- should restart\n");
+ return 1;
+ }
+
+ spin_lock(&dlm->spinlock);
+ /* For now, we restart the process if the node maps have
+ * changed at all */
+ ret = memcmp(ctxt->live_map, dlm->live_nodes_map,
+ sizeof(dlm->live_nodes_map));
+ spin_unlock(&dlm->spinlock);
+
+ if (ret)
+ mlog(0, "Node maps changed -- should restart\n");
+
+ return ret;
+}
+
+static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
+{
+ int status = 0, tmpstat, node;
+ struct domain_join_ctxt *ctxt;
+ enum dlm_query_join_response response;
+
+ mlog_entry("%p", dlm);
+
+ ctxt = kcalloc(1, sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* group sem locking should work for us here -- we're already
+ * registered for heartbeat events so filling this should be
+ * atomic wrt getting those handlers called. */
+ o2hb_fill_node_map(dlm->live_nodes_map, sizeof(dlm->live_nodes_map));
+
+ spin_lock(&dlm->spinlock);
+ memcpy(ctxt->live_map, dlm->live_nodes_map, sizeof(ctxt->live_map));
+
+ __dlm_set_joining_node(dlm, dlm->node_num);
+
+ spin_unlock(&dlm->spinlock);
+
+ node = -1;
+ while ((node = find_next_bit(ctxt->live_map, O2NM_MAX_NODES,
+ node + 1)) < O2NM_MAX_NODES) {
+ if (node == dlm->node_num)
+ continue;
+
+ status = dlm_request_join(dlm, node, &response);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Ok, either we got a response or the node doesn't have a
+ * dlm up. */
+ if (response == JOIN_OK)
+ set_bit(node, ctxt->yes_resp_map);
+
+ if (dlm_should_restart_join(dlm, ctxt, response)) {
+ status = -EAGAIN;
+ goto bail;
+ }
+ }
+
+ mlog(0, "Yay, done querying nodes!\n");
+
+ /* Yay, everyone agree's we can join the domain. My domain is
+ * comprised of all nodes who were put in the
+ * yes_resp_map. Copy that into our domain map and send a join
+ * assert message to clean up everyone elses state. */
+ spin_lock(&dlm->spinlock);
+ memcpy(dlm->domain_map, ctxt->yes_resp_map,
+ sizeof(ctxt->yes_resp_map));
+ set_bit(dlm->node_num, dlm->domain_map);
+ spin_unlock(&dlm->spinlock);
+
+ dlm_send_join_asserts(dlm, ctxt->yes_resp_map);
+
+ /* Joined state *must* be set before the joining node
+ * information, otherwise the query_join handler may read no
+ * current joiner but a state of NEW and tell joining nodes
+ * we're not in the domain. */
+ spin_lock(&dlm_domain_lock);
+ dlm->dlm_state = DLM_CTXT_JOINED;
+ dlm->num_joins++;
+ spin_unlock(&dlm_domain_lock);
+
+bail:
+ spin_lock(&dlm->spinlock);
+ __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
+ if (!status)
+ __dlm_print_nodes(dlm);
+ spin_unlock(&dlm->spinlock);
+
+ if (ctxt) {
+ /* Do we need to send a cancel message to any nodes? */
+ if (status < 0) {
+ tmpstat = dlm_send_join_cancels(dlm,
+ ctxt->yes_resp_map,
+ sizeof(ctxt->yes_resp_map));
+ if (tmpstat < 0)
+ mlog_errno(tmpstat);
+ }
+ kfree(ctxt);
+ }
+
+ mlog(0, "returning %d\n", status);
+ return status;
+}
+
+static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm)
+{
+ o2hb_unregister_callback(&dlm->dlm_hb_up);
+ o2hb_unregister_callback(&dlm->dlm_hb_down);
+ o2net_unregister_handler_list(&dlm->dlm_domain_handlers);
+}
+
+static int dlm_register_domain_handlers(struct dlm_ctxt *dlm)
+{
+ int status;
+
+ mlog(0, "registering handlers.\n");
+
+ o2hb_setup_callback(&dlm->dlm_hb_down, O2HB_NODE_DOWN_CB,
+ dlm_hb_node_down_cb, dlm, DLM_HB_NODE_DOWN_PRI);
+ status = o2hb_register_callback(&dlm->dlm_hb_down);
+ if (status)
+ goto bail;
+
+ o2hb_setup_callback(&dlm->dlm_hb_up, O2HB_NODE_UP_CB,
+ dlm_hb_node_up_cb, dlm, DLM_HB_NODE_UP_PRI);
+ status = o2hb_register_callback(&dlm->dlm_hb_up);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_MASTER_REQUEST_MSG, dlm->key,
+ sizeof(struct dlm_master_request),
+ dlm_master_request_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_ASSERT_MASTER_MSG, dlm->key,
+ sizeof(struct dlm_assert_master),
+ dlm_assert_master_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_CREATE_LOCK_MSG, dlm->key,
+ sizeof(struct dlm_create_lock),
+ dlm_create_lock_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_CONVERT_LOCK_MSG, dlm->key,
+ DLM_CONVERT_LOCK_MAX_LEN,
+ dlm_convert_lock_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_UNLOCK_LOCK_MSG, dlm->key,
+ DLM_UNLOCK_LOCK_MAX_LEN,
+ dlm_unlock_lock_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_PROXY_AST_MSG, dlm->key,
+ DLM_PROXY_AST_MAX_LEN,
+ dlm_proxy_ast_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_EXIT_DOMAIN_MSG, dlm->key,
+ sizeof(struct dlm_exit_domain),
+ dlm_exit_domain_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_MIGRATE_REQUEST_MSG, dlm->key,
+ sizeof(struct dlm_migrate_request),
+ dlm_migrate_request_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_MIG_LOCKRES_MSG, dlm->key,
+ DLM_MIG_LOCKRES_MAX_LEN,
+ dlm_mig_lockres_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_MASTER_REQUERY_MSG, dlm->key,
+ sizeof(struct dlm_master_requery),
+ dlm_master_requery_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_LOCK_REQUEST_MSG, dlm->key,
+ sizeof(struct dlm_lock_request),
+ dlm_request_all_locks_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_RECO_DATA_DONE_MSG, dlm->key,
+ sizeof(struct dlm_reco_data_done),
+ dlm_reco_data_done_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_BEGIN_RECO_MSG, dlm->key,
+ sizeof(struct dlm_begin_reco),
+ dlm_begin_reco_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_FINALIZE_RECO_MSG, dlm->key,
+ sizeof(struct dlm_finalize_reco),
+ dlm_finalize_reco_handler,
+ dlm, &dlm->dlm_domain_handlers);
+ if (status)
+ goto bail;
+
+bail:
+ if (status)
+ dlm_unregister_domain_handlers(dlm);
+
+ return status;
+}
+
+static int dlm_join_domain(struct dlm_ctxt *dlm)
+{
+ int status;
+
+ BUG_ON(!dlm);
+
+ mlog(0, "Join domain %s\n", dlm->name);
+
+ status = dlm_register_domain_handlers(dlm);
+ if (status) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = dlm_launch_thread(dlm);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = dlm_launch_recovery_thread(dlm);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ do {
+ unsigned int backoff;
+ status = dlm_try_to_join_domain(dlm);
+
+ /* If we're racing another node to the join, then we
+ * need to back off temporarily and let them
+ * complete. */
+ if (status == -EAGAIN) {
+ if (signal_pending(current)) {
+ status = -ERESTARTSYS;
+ goto bail;
+ }
+
+ /*
+ * <chip> After you!
+ * <dale> No, after you!
+ * <chip> I insist!
+ * <dale> But you first!
+ * ...
+ */
+ backoff = (unsigned int)(jiffies & 0x3);
+ backoff *= DLM_DOMAIN_BACKOFF_MS;
+ mlog(0, "backoff %d\n", backoff);
+ msleep(backoff);
+ }
+ } while (status == -EAGAIN);
+
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ wake_up(&dlm_domain_events);
+
+ if (status) {
+ dlm_unregister_domain_handlers(dlm);
+ dlm_complete_thread(dlm);
+ dlm_complete_recovery_thread(dlm);
+ }
+
+ return status;
+}
+
+static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain,
+ u32 key)
+{
+ int i;
+ struct dlm_ctxt *dlm = NULL;
+
+ dlm = kcalloc(1, sizeof(*dlm), GFP_KERNEL);
+ if (!dlm) {
+ mlog_errno(-ENOMEM);
+ goto leave;
+ }
+
+ dlm->name = kmalloc(strlen(domain) + 1, GFP_KERNEL);
+ if (dlm->name == NULL) {
+ mlog_errno(-ENOMEM);
+ kfree(dlm);
+ dlm = NULL;
+ goto leave;
+ }
+
+ dlm->resources = (struct list_head *) __get_free_page(GFP_KERNEL);
+ if (!dlm->resources) {
+ mlog_errno(-ENOMEM);
+ kfree(dlm->name);
+ kfree(dlm);
+ dlm = NULL;
+ goto leave;
+ }
+ memset(dlm->resources, 0, PAGE_SIZE);
+
+ for (i=0; i<DLM_HASH_SIZE; i++)
+ INIT_LIST_HEAD(&dlm->resources[i]);
+
+ strcpy(dlm->name, domain);
+ dlm->key = key;
+ dlm->node_num = o2nm_this_node();
+
+ spin_lock_init(&dlm->spinlock);
+ spin_lock_init(&dlm->master_lock);
+ spin_lock_init(&dlm->ast_lock);
+ INIT_LIST_HEAD(&dlm->list);
+ INIT_LIST_HEAD(&dlm->dirty_list);
+ INIT_LIST_HEAD(&dlm->reco.resources);
+ INIT_LIST_HEAD(&dlm->reco.received);
+ INIT_LIST_HEAD(&dlm->reco.node_data);
+ INIT_LIST_HEAD(&dlm->purge_list);
+ INIT_LIST_HEAD(&dlm->dlm_domain_handlers);
+ dlm->reco.state = 0;
+
+ INIT_LIST_HEAD(&dlm->pending_asts);
+ INIT_LIST_HEAD(&dlm->pending_basts);
+
+ mlog(0, "dlm->recovery_map=%p, &(dlm->recovery_map[0])=%p\n",
+ dlm->recovery_map, &(dlm->recovery_map[0]));
+
+ memset(dlm->recovery_map, 0, sizeof(dlm->recovery_map));
+ memset(dlm->live_nodes_map, 0, sizeof(dlm->live_nodes_map));
+ memset(dlm->domain_map, 0, sizeof(dlm->domain_map));
+
+ dlm->dlm_thread_task = NULL;
+ dlm->dlm_reco_thread_task = NULL;
+ init_waitqueue_head(&dlm->dlm_thread_wq);
+ init_waitqueue_head(&dlm->dlm_reco_thread_wq);
+ init_waitqueue_head(&dlm->reco.event);
+ init_waitqueue_head(&dlm->ast_wq);
+ init_waitqueue_head(&dlm->migration_wq);
+ INIT_LIST_HEAD(&dlm->master_list);
+ INIT_LIST_HEAD(&dlm->mle_hb_events);
+
+ dlm->joining_node = DLM_LOCK_RES_OWNER_UNKNOWN;
+ init_waitqueue_head(&dlm->dlm_join_events);
+
+ dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
+ dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+ atomic_set(&dlm->local_resources, 0);
+ atomic_set(&dlm->remote_resources, 0);
+ atomic_set(&dlm->unknown_resources, 0);
+
+ spin_lock_init(&dlm->work_lock);
+ INIT_LIST_HEAD(&dlm->work_list);
+ INIT_WORK(&dlm->dispatched_work, dlm_dispatch_work, dlm);
+
+ kref_init(&dlm->dlm_refs);
+ dlm->dlm_state = DLM_CTXT_NEW;
+
+ INIT_LIST_HEAD(&dlm->dlm_eviction_callbacks);
+
+ mlog(0, "context init: refcount %u\n",
+ atomic_read(&dlm->dlm_refs.refcount));
+
+leave:
+ return dlm;
+}
+
+/*
+ * dlm_register_domain: one-time setup per "domain"
+ */
+struct dlm_ctxt * dlm_register_domain(const char *domain,
+ u32 key)
+{
+ int ret;
+ struct dlm_ctxt *dlm = NULL;
+ struct dlm_ctxt *new_ctxt = NULL;
+
+ if (strlen(domain) > O2NM_MAX_NAME_LEN) {
+ ret = -ENAMETOOLONG;
+ mlog(ML_ERROR, "domain name length too long\n");
+ goto leave;
+ }
+
+ if (!o2hb_check_local_node_heartbeating()) {
+ mlog(ML_ERROR, "the local node has not been configured, or is "
+ "not heartbeating\n");
+ ret = -EPROTO;
+ goto leave;
+ }
+
+ mlog(0, "register called for domain \"%s\"\n", domain);
+
+retry:
+ dlm = NULL;
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ mlog_errno(ret);
+ goto leave;
+ }
+
+ spin_lock(&dlm_domain_lock);
+
+ dlm = __dlm_lookup_domain(domain);
+ if (dlm) {
+ if (dlm->dlm_state != DLM_CTXT_JOINED) {
+ spin_unlock(&dlm_domain_lock);
+
+ mlog(0, "This ctxt is not joined yet!\n");
+ wait_event_interruptible(dlm_domain_events,
+ dlm_wait_on_domain_helper(
+ domain));
+ goto retry;
+ }
+
+ __dlm_get(dlm);
+ dlm->num_joins++;
+
+ spin_unlock(&dlm_domain_lock);
+
+ ret = 0;
+ goto leave;
+ }
+
+ /* doesn't exist */
+ if (!new_ctxt) {
+ spin_unlock(&dlm_domain_lock);
+
+ new_ctxt = dlm_alloc_ctxt(domain, key);
+ if (new_ctxt)
+ goto retry;
+
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto leave;
+ }
+
+ /* a little variable switch-a-roo here... */
+ dlm = new_ctxt;
+ new_ctxt = NULL;
+
+ /* add the new domain */
+ list_add_tail(&dlm->list, &dlm_domains);
+ spin_unlock(&dlm_domain_lock);
+
+ ret = dlm_join_domain(dlm);
+ if (ret) {
+ mlog_errno(ret);
+ dlm_put(dlm);
+ goto leave;
+ }
+
+ ret = 0;
+leave:
+ if (new_ctxt)
+ dlm_free_ctxt_mem(new_ctxt);
+
+ if (ret < 0)
+ dlm = ERR_PTR(ret);
+
+ return dlm;
+}
+EXPORT_SYMBOL_GPL(dlm_register_domain);
+
+static LIST_HEAD(dlm_join_handlers);
+
+static void dlm_unregister_net_handlers(void)
+{
+ o2net_unregister_handler_list(&dlm_join_handlers);
+}
+
+static int dlm_register_net_handlers(void)
+{
+ int status = 0;
+
+ status = o2net_register_handler(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY,
+ sizeof(struct dlm_query_join_request),
+ dlm_query_join_handler,
+ NULL, &dlm_join_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_ASSERT_JOINED_MSG, DLM_MOD_KEY,
+ sizeof(struct dlm_assert_joined),
+ dlm_assert_joined_handler,
+ NULL, &dlm_join_handlers);
+ if (status)
+ goto bail;
+
+ status = o2net_register_handler(DLM_CANCEL_JOIN_MSG, DLM_MOD_KEY,
+ sizeof(struct dlm_cancel_join),
+ dlm_cancel_join_handler,
+ NULL, &dlm_join_handlers);
+
+bail:
+ if (status < 0)
+ dlm_unregister_net_handlers();
+
+ return status;
+}
+
+/* Domain eviction callback handling.
+ *
+ * The file system requires notification of node death *before* the
+ * dlm completes it's recovery work, otherwise it may be able to
+ * acquire locks on resources requiring recovery. Since the dlm can
+ * evict a node from it's domain *before* heartbeat fires, a similar
+ * mechanism is required. */
+
+/* Eviction is not expected to happen often, so a per-domain lock is
+ * not necessary. Eviction callbacks are allowed to sleep for short
+ * periods of time. */
+static DECLARE_RWSEM(dlm_callback_sem);
+
+void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm,
+ int node_num)
+{
+ struct list_head *iter;
+ struct dlm_eviction_cb *cb;
+
+ down_read(&dlm_callback_sem);
+ list_for_each(iter, &dlm->dlm_eviction_callbacks) {
+ cb = list_entry(iter, struct dlm_eviction_cb, ec_item);
+
+ cb->ec_func(node_num, cb->ec_data);
+ }
+ up_read(&dlm_callback_sem);
+}
+
+void dlm_setup_eviction_cb(struct dlm_eviction_cb *cb,
+ dlm_eviction_func *f,
+ void *data)
+{
+ INIT_LIST_HEAD(&cb->ec_item);
+ cb->ec_func = f;
+ cb->ec_data = data;
+}
+EXPORT_SYMBOL_GPL(dlm_setup_eviction_cb);
+
+void dlm_register_eviction_cb(struct dlm_ctxt *dlm,
+ struct dlm_eviction_cb *cb)
+{
+ down_write(&dlm_callback_sem);
+ list_add_tail(&cb->ec_item, &dlm->dlm_eviction_callbacks);
+ up_write(&dlm_callback_sem);
+}
+EXPORT_SYMBOL_GPL(dlm_register_eviction_cb);
+
+void dlm_unregister_eviction_cb(struct dlm_eviction_cb *cb)
+{
+ down_write(&dlm_callback_sem);
+ list_del_init(&cb->ec_item);
+ up_write(&dlm_callback_sem);
+}
+EXPORT_SYMBOL_GPL(dlm_unregister_eviction_cb);
+
+static int __init dlm_init(void)
+{
+ int status;
+
+ dlm_print_version();
+
+ status = dlm_init_mle_cache();
+ if (status)
+ return -1;
+
+ status = dlm_register_net_handlers();
+ if (status) {
+ dlm_destroy_mle_cache();
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit dlm_exit (void)
+{
+ dlm_unregister_net_handlers();
+ dlm_destroy_mle_cache();
+}
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+
+module_init(dlm_init);
+module_exit(dlm_exit);
diff --git a/fs/ocfs2/dlm/dlmdomain.h b/fs/ocfs2/dlm/dlmdomain.h
new file mode 100644
index 000000000000..2f7f60bfeb3b
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmdomain.h
@@ -0,0 +1,36 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmdomain.h
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+#ifndef DLMDOMAIN_H
+#define DLMDOMAIN_H
+
+extern spinlock_t dlm_domain_lock;
+extern struct list_head dlm_domains;
+
+int dlm_joined(struct dlm_ctxt *dlm);
+int dlm_shutting_down(struct dlm_ctxt *dlm);
+void dlm_fire_domain_eviction_callbacks(struct dlm_ctxt *dlm,
+ int node_num);
+
+#endif
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
new file mode 100644
index 000000000000..dd2d24dc25e0
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -0,0 +1,640 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmfs.c
+ *
+ * Code which implements the kernel side of a minimal userspace
+ * interface to our DLM. This file handles the virtual file system
+ * used for communication with userspace. Credit should go to ramfs,
+ * which was a template for the fs side of this module.
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+/* Simple VFS hooks based on: */
+/*
+ * Resizable simple ram filesystem for Linux.
+ *
+ * Copyright (C) 2000 Linus Torvalds.
+ * 2000 Transmeta Corp.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/backing-dev.h>
+
+#include <asm/uaccess.h>
+
+
+#include "cluster/nodemanager.h"
+#include "cluster/heartbeat.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+
+#include "userdlm.h"
+
+#include "dlmfsver.h"
+
+#define MLOG_MASK_PREFIX ML_DLMFS
+#include "cluster/masklog.h"
+
+static struct super_operations dlmfs_ops;
+static struct file_operations dlmfs_file_operations;
+static struct inode_operations dlmfs_dir_inode_operations;
+static struct inode_operations dlmfs_root_inode_operations;
+static struct inode_operations dlmfs_file_inode_operations;
+static kmem_cache_t *dlmfs_inode_cache;
+
+struct workqueue_struct *user_dlm_worker;
+
+/*
+ * decodes a set of open flags into a valid lock level and a set of flags.
+ * returns < 0 if we have invalid flags
+ * flags which mean something to us:
+ * O_RDONLY -> PRMODE level
+ * O_WRONLY -> EXMODE level
+ *
+ * O_NONBLOCK -> LKM_NOQUEUE
+ */
+static int dlmfs_decode_open_flags(int open_flags,
+ int *level,
+ int *flags)
+{
+ if (open_flags & (O_WRONLY|O_RDWR))
+ *level = LKM_EXMODE;
+ else
+ *level = LKM_PRMODE;
+
+ *flags = 0;
+ if (open_flags & O_NONBLOCK)
+ *flags |= LKM_NOQUEUE;
+
+ return 0;
+}
+
+static int dlmfs_file_open(struct inode *inode,
+ struct file *file)
+{
+ int status, level, flags;
+ struct dlmfs_filp_private *fp = NULL;
+ struct dlmfs_inode_private *ip;
+
+ if (S_ISDIR(inode->i_mode))
+ BUG();
+
+ mlog(0, "open called on inode %lu, flags 0x%x\n", inode->i_ino,
+ file->f_flags);
+
+ status = dlmfs_decode_open_flags(file->f_flags, &level, &flags);
+ if (status < 0)
+ goto bail;
+
+ /* We don't want to honor O_APPEND at read/write time as it
+ * doesn't make sense for LVB writes. */
+ file->f_flags &= ~O_APPEND;
+
+ fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ if (!fp) {
+ status = -ENOMEM;
+ goto bail;
+ }
+ fp->fp_lock_level = level;
+
+ ip = DLMFS_I(inode);
+
+ status = user_dlm_cluster_lock(&ip->ip_lockres, level, flags);
+ if (status < 0) {
+ /* this is a strange error to return here but I want
+ * to be able userspace to be able to distinguish a
+ * valid lock request from one that simply couldn't be
+ * granted. */
+ if (flags & LKM_NOQUEUE && status == -EAGAIN)
+ status = -ETXTBSY;
+ kfree(fp);
+ goto bail;
+ }
+
+ file->private_data = fp;
+bail:
+ return status;
+}
+
+static int dlmfs_file_release(struct inode *inode,
+ struct file *file)
+{
+ int level, status;
+ struct dlmfs_inode_private *ip = DLMFS_I(inode);
+ struct dlmfs_filp_private *fp =
+ (struct dlmfs_filp_private *) file->private_data;
+
+ if (S_ISDIR(inode->i_mode))
+ BUG();
+
+ mlog(0, "close called on inode %lu\n", inode->i_ino);
+
+ status = 0;
+ if (fp) {
+ level = fp->fp_lock_level;
+ if (level != LKM_IVMODE)
+ user_dlm_cluster_unlock(&ip->ip_lockres, level);
+
+ kfree(fp);
+ file->private_data = NULL;
+ }
+
+ return 0;
+}
+
+static ssize_t dlmfs_file_read(struct file *filp,
+ char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int bytes_left;
+ ssize_t readlen;
+ char *lvb_buf;
+ struct inode *inode = filp->f_dentry->d_inode;
+
+ mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+ inode->i_ino, count, *ppos);
+
+ if (*ppos >= i_size_read(inode))
+ return 0;
+
+ if (!count)
+ return 0;
+
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+
+ /* don't read past the lvb */
+ if ((count + *ppos) > i_size_read(inode))
+ readlen = i_size_read(inode) - *ppos;
+ else
+ readlen = count - *ppos;
+
+ lvb_buf = kmalloc(readlen, GFP_KERNEL);
+ if (!lvb_buf)
+ return -ENOMEM;
+
+ user_dlm_read_lvb(inode, lvb_buf, readlen);
+ bytes_left = __copy_to_user(buf, lvb_buf, readlen);
+ readlen -= bytes_left;
+
+ kfree(lvb_buf);
+
+ *ppos = *ppos + readlen;
+
+ mlog(0, "read %zd bytes\n", readlen);
+ return readlen;
+}
+
+static ssize_t dlmfs_file_write(struct file *filp,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ int bytes_left;
+ ssize_t writelen;
+ char *lvb_buf;
+ struct inode *inode = filp->f_dentry->d_inode;
+
+ mlog(0, "inode %lu, count = %zu, *ppos = %llu\n",
+ inode->i_ino, count, *ppos);
+
+ if (*ppos >= i_size_read(inode))
+ return -ENOSPC;
+
+ if (!count)
+ return 0;
+
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ /* don't write past the lvb */
+ if ((count + *ppos) > i_size_read(inode))
+ writelen = i_size_read(inode) - *ppos;
+ else
+ writelen = count - *ppos;
+
+ lvb_buf = kmalloc(writelen, GFP_KERNEL);
+ if (!lvb_buf)
+ return -ENOMEM;
+
+ bytes_left = copy_from_user(lvb_buf, buf, writelen);
+ writelen -= bytes_left;
+ if (writelen)
+ user_dlm_write_lvb(inode, lvb_buf, writelen);
+
+ kfree(lvb_buf);
+
+ *ppos = *ppos + writelen;
+ mlog(0, "wrote %zd bytes\n", writelen);
+ return writelen;
+}
+
+static void dlmfs_init_once(void *foo,
+ kmem_cache_t *cachep,
+ unsigned long flags)
+{
+ struct dlmfs_inode_private *ip =
+ (struct dlmfs_inode_private *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ ip->ip_dlm = NULL;
+ ip->ip_parent = NULL;
+
+ inode_init_once(&ip->ip_vfs_inode);
+ }
+}
+
+static struct inode *dlmfs_alloc_inode(struct super_block *sb)
+{
+ struct dlmfs_inode_private *ip;
+
+ ip = kmem_cache_alloc(dlmfs_inode_cache, SLAB_NOFS);
+ if (!ip)
+ return NULL;
+
+ return &ip->ip_vfs_inode;
+}
+
+static void dlmfs_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(dlmfs_inode_cache, DLMFS_I(inode));
+}
+
+static void dlmfs_clear_inode(struct inode *inode)
+{
+ int status;
+ struct dlmfs_inode_private *ip;
+
+ if (!inode)
+ return;
+
+ mlog(0, "inode %lu\n", inode->i_ino);
+
+ ip = DLMFS_I(inode);
+
+ if (S_ISREG(inode->i_mode)) {
+ status = user_dlm_destroy_lock(&ip->ip_lockres);
+ if (status < 0)
+ mlog_errno(status);
+ iput(ip->ip_parent);
+ goto clear_fields;
+ }
+
+ mlog(0, "we're a directory, ip->ip_dlm = 0x%p\n", ip->ip_dlm);
+ /* we must be a directory. If required, lets unregister the
+ * dlm context now. */
+ if (ip->ip_dlm)
+ user_dlm_unregister_context(ip->ip_dlm);
+clear_fields:
+ ip->ip_parent = NULL;
+ ip->ip_dlm = NULL;
+}
+
+static struct backing_dev_info dlmfs_backing_dev_info = {
+ .ra_pages = 0, /* No readahead */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+};
+
+static struct inode *dlmfs_get_root_inode(struct super_block *sb)
+{
+ struct inode *inode = new_inode(sb);
+ int mode = S_IFDIR | 0755;
+ struct dlmfs_inode_private *ip;
+
+ if (inode) {
+ ip = DLMFS_I(inode);
+
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ inode->i_nlink++;
+
+ inode->i_fop = &simple_dir_operations;
+ inode->i_op = &dlmfs_root_inode_operations;
+ }
+
+ return inode;
+}
+
+static struct inode *dlmfs_get_inode(struct inode *parent,
+ struct dentry *dentry,
+ int mode)
+{
+ struct super_block *sb = parent->i_sb;
+ struct inode * inode = new_inode(sb);
+ struct dlmfs_inode_private *ip;
+
+ if (!inode)
+ return NULL;
+
+ inode->i_mode = mode;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+ inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ ip = DLMFS_I(inode);
+ ip->ip_dlm = DLMFS_I(parent)->ip_dlm;
+
+ switch (mode & S_IFMT) {
+ default:
+ /* for now we don't support anything other than
+ * directories and regular files. */
+ BUG();
+ break;
+ case S_IFREG:
+ inode->i_op = &dlmfs_file_inode_operations;
+ inode->i_fop = &dlmfs_file_operations;
+
+ i_size_write(inode, DLM_LVB_LEN);
+
+ user_dlm_lock_res_init(&ip->ip_lockres, dentry);
+
+ /* released at clear_inode time, this insures that we
+ * get to drop the dlm reference on each lock *before*
+ * we call the unregister code for releasing parent
+ * directories. */
+ ip->ip_parent = igrab(parent);
+ BUG_ON(!ip->ip_parent);
+ break;
+ case S_IFDIR:
+ inode->i_op = &dlmfs_dir_inode_operations;
+ inode->i_fop = &simple_dir_operations;
+
+ /* directory inodes start off with i_nlink ==
+ * 2 (for "." entry) */
+ inode->i_nlink++;
+ break;
+ }
+
+ if (parent->i_mode & S_ISGID) {
+ inode->i_gid = parent->i_gid;
+ if (S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
+ }
+
+ return inode;
+}
+
+/*
+ * File creation. Allocate an inode, and we're done..
+ */
+/* SMP-safe */
+static int dlmfs_mkdir(struct inode * dir,
+ struct dentry * dentry,
+ int mode)
+{
+ int status;
+ struct inode *inode = NULL;
+ struct qstr *domain = &dentry->d_name;
+ struct dlmfs_inode_private *ip;
+ struct dlm_ctxt *dlm;
+
+ mlog(0, "mkdir %.*s\n", domain->len, domain->name);
+
+ /* verify that we have a proper domain */
+ if (domain->len >= O2NM_MAX_NAME_LEN) {
+ status = -EINVAL;
+ mlog(ML_ERROR, "invalid domain name for directory.\n");
+ goto bail;
+ }
+
+ inode = dlmfs_get_inode(dir, dentry, mode | S_IFDIR);
+ if (!inode) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ip = DLMFS_I(inode);
+
+ dlm = user_dlm_register_context(domain);
+ if (IS_ERR(dlm)) {
+ status = PTR_ERR(dlm);
+ mlog(ML_ERROR, "Error %d could not register domain \"%.*s\"\n",
+ status, domain->len, domain->name);
+ goto bail;
+ }
+ ip->ip_dlm = dlm;
+
+ dir->i_nlink++;
+ d_instantiate(dentry, inode);
+ dget(dentry); /* Extra count - pin the dentry in core */
+
+ status = 0;
+bail:
+ if (status < 0)
+ iput(inode);
+ return status;
+}
+
+static int dlmfs_create(struct inode *dir,
+ struct dentry *dentry,
+ int mode,
+ struct nameidata *nd)
+{
+ int status = 0;
+ struct inode *inode;
+ struct qstr *name = &dentry->d_name;
+
+ mlog(0, "create %.*s\n", name->len, name->name);
+
+ /* verify name is valid and doesn't contain any dlm reserved
+ * characters */
+ if (name->len >= USER_DLM_LOCK_ID_MAX_LEN ||
+ name->name[0] == '$') {
+ status = -EINVAL;
+ mlog(ML_ERROR, "invalid lock name, %.*s\n", name->len,
+ name->name);
+ goto bail;
+ }
+
+ inode = dlmfs_get_inode(dir, dentry, mode | S_IFREG);
+ if (!inode) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ d_instantiate(dentry, inode);
+ dget(dentry); /* Extra count - pin the dentry in core */
+bail:
+ return status;
+}
+
+static int dlmfs_unlink(struct inode *dir,
+ struct dentry *dentry)
+{
+ int status;
+ struct inode *inode = dentry->d_inode;
+
+ mlog(0, "unlink inode %lu\n", inode->i_ino);
+
+ /* if there are no current holders, or none that are waiting
+ * to acquire a lock, this basically destroys our lockres. */
+ status = user_dlm_destroy_lock(&DLMFS_I(inode)->ip_lockres);
+ if (status < 0) {
+ mlog(ML_ERROR, "unlink %.*s, error %d from destroy\n",
+ dentry->d_name.len, dentry->d_name.name, status);
+ goto bail;
+ }
+ status = simple_unlink(dir, dentry);
+bail:
+ return status;
+}
+
+static int dlmfs_fill_super(struct super_block * sb,
+ void * data,
+ int silent)
+{
+ struct inode * inode;
+ struct dentry * root;
+
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = DLMFS_MAGIC;
+ sb->s_op = &dlmfs_ops;
+ inode = dlmfs_get_root_inode(sb);
+ if (!inode)
+ return -ENOMEM;
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ iput(inode);
+ return -ENOMEM;
+ }
+ sb->s_root = root;
+ return 0;
+}
+
+static struct file_operations dlmfs_file_operations = {
+ .open = dlmfs_file_open,
+ .release = dlmfs_file_release,
+ .read = dlmfs_file_read,
+ .write = dlmfs_file_write,
+};
+
+static struct inode_operations dlmfs_dir_inode_operations = {
+ .create = dlmfs_create,
+ .lookup = simple_lookup,
+ .unlink = dlmfs_unlink,
+};
+
+/* this way we can restrict mkdir to only the toplevel of the fs. */
+static struct inode_operations dlmfs_root_inode_operations = {
+ .lookup = simple_lookup,
+ .mkdir = dlmfs_mkdir,
+ .rmdir = simple_rmdir,
+};
+
+static struct super_operations dlmfs_ops = {
+ .statfs = simple_statfs,
+ .alloc_inode = dlmfs_alloc_inode,
+ .destroy_inode = dlmfs_destroy_inode,
+ .clear_inode = dlmfs_clear_inode,
+ .drop_inode = generic_delete_inode,
+};
+
+static struct inode_operations dlmfs_file_inode_operations = {
+ .getattr = simple_getattr,
+};
+
+static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super);
+}
+
+static struct file_system_type dlmfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ocfs2_dlmfs",
+ .get_sb = dlmfs_get_sb,
+ .kill_sb = kill_litter_super,
+};
+
+static int __init init_dlmfs_fs(void)
+{
+ int status;
+ int cleanup_inode = 0, cleanup_worker = 0;
+
+ dlmfs_print_version();
+
+ dlmfs_inode_cache = kmem_cache_create("dlmfs_inode_cache",
+ sizeof(struct dlmfs_inode_private),
+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+ dlmfs_init_once, NULL);
+ if (!dlmfs_inode_cache)
+ return -ENOMEM;
+ cleanup_inode = 1;
+
+ user_dlm_worker = create_singlethread_workqueue("user_dlm");
+ if (!user_dlm_worker) {
+ status = -ENOMEM;
+ goto bail;
+ }
+ cleanup_worker = 1;
+
+ status = register_filesystem(&dlmfs_fs_type);
+bail:
+ if (status) {
+ if (cleanup_inode)
+ kmem_cache_destroy(dlmfs_inode_cache);
+ if (cleanup_worker)
+ destroy_workqueue(user_dlm_worker);
+ } else
+ printk("OCFS2 User DLM kernel interface loaded\n");
+ return status;
+}
+
+static void __exit exit_dlmfs_fs(void)
+{
+ unregister_filesystem(&dlmfs_fs_type);
+
+ flush_workqueue(user_dlm_worker);
+ destroy_workqueue(user_dlm_worker);
+
+ if (kmem_cache_destroy(dlmfs_inode_cache))
+ printk(KERN_INFO "dlmfs_inode_cache: not all structures "
+ "were freed\n");
+}
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+
+module_init(init_dlmfs_fs)
+module_exit(exit_dlmfs_fs)
diff --git a/fs/ocfs2/dlm/dlmfsver.c b/fs/ocfs2/dlm/dlmfsver.c
new file mode 100644
index 000000000000..d2be3ad841f9
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmfsver.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmfsver.c
+ *
+ * version string
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include "dlmfsver.h"
+
+#define DLM_BUILD_VERSION "1.3.3"
+
+#define VERSION_STR "OCFS2 DLMFS " DLM_BUILD_VERSION
+
+void dlmfs_print_version(void)
+{
+ printk(KERN_INFO "%s\n", VERSION_STR);
+}
+
+MODULE_DESCRIPTION(VERSION_STR);
+
+MODULE_VERSION(DLM_BUILD_VERSION);
diff --git a/fs/ocfs2/dlm/dlmfsver.h b/fs/ocfs2/dlm/dlmfsver.h
new file mode 100644
index 000000000000..f35eadbed25c
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmfsver.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmver.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef DLMFS_VER_H
+#define DLMFS_VER_H
+
+void dlmfs_print_version(void);
+
+#endif /* DLMFS_VER_H */
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
new file mode 100644
index 000000000000..d1a0038557a3
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -0,0 +1,676 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmlock.c
+ *
+ * underlying calls for lock creation
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+
+#include "dlmconvert.h"
+
+#define MLOG_MASK_PREFIX ML_DLM
+#include "cluster/masklog.h"
+
+static spinlock_t dlm_cookie_lock = SPIN_LOCK_UNLOCKED;
+static u64 dlm_next_cookie = 1;
+
+static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags);
+static void dlm_init_lock(struct dlm_lock *newlock, int type,
+ u8 node, u64 cookie);
+static void dlm_lock_release(struct kref *kref);
+static void dlm_lock_detach_lockres(struct dlm_lock *lock);
+
+/* Tell us whether we can grant a new lock request.
+ * locking:
+ * caller needs: res->spinlock
+ * taken: none
+ * held on exit: none
+ * returns: 1 if the lock can be granted, 0 otherwise.
+ */
+static int dlm_can_grant_new_lock(struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ struct list_head *iter;
+ struct dlm_lock *tmplock;
+
+ list_for_each(iter, &res->granted) {
+ tmplock = list_entry(iter, struct dlm_lock, list);
+
+ if (!dlm_lock_compatible(tmplock->ml.type, lock->ml.type))
+ return 0;
+ }
+
+ list_for_each(iter, &res->converting) {
+ tmplock = list_entry(iter, struct dlm_lock, list);
+
+ if (!dlm_lock_compatible(tmplock->ml.type, lock->ml.type))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* performs lock creation at the lockres master site
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_NOTQUEUED
+ */
+static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags)
+{
+ int call_ast = 0, kick_thread = 0;
+ enum dlm_status status = DLM_NORMAL;
+
+ mlog_entry("type=%d\n", lock->ml.type);
+
+ spin_lock(&res->spinlock);
+ /* if called from dlm_create_lock_handler, need to
+ * ensure it will not sleep in dlm_wait_on_lockres */
+ status = __dlm_lockres_state_to_status(res);
+ if (status != DLM_NORMAL &&
+ lock->ml.node != dlm->node_num) {
+ /* erf. state changed after lock was dropped. */
+ spin_unlock(&res->spinlock);
+ dlm_error(status);
+ return status;
+ }
+ __dlm_wait_on_lockres(res);
+ __dlm_lockres_reserve_ast(res);
+
+ if (dlm_can_grant_new_lock(res, lock)) {
+ mlog(0, "I can grant this lock right away\n");
+ /* got it right away */
+ lock->lksb->status = DLM_NORMAL;
+ status = DLM_NORMAL;
+ dlm_lock_get(lock);
+ list_add_tail(&lock->list, &res->granted);
+
+ /* for the recovery lock, we can't allow the ast
+ * to be queued since the dlmthread is already
+ * frozen. but the recovery lock is always locked
+ * with LKM_NOQUEUE so we do not need the ast in
+ * this special case */
+ if (!dlm_is_recovery_lock(res->lockname.name,
+ res->lockname.len)) {
+ kick_thread = 1;
+ call_ast = 1;
+ }
+ } else {
+ /* for NOQUEUE request, unless we get the
+ * lock right away, return DLM_NOTQUEUED */
+ if (flags & LKM_NOQUEUE)
+ status = DLM_NOTQUEUED;
+ else {
+ dlm_lock_get(lock);
+ list_add_tail(&lock->list, &res->blocked);
+ kick_thread = 1;
+ }
+ }
+
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+
+ /* either queue the ast or release it */
+ if (call_ast)
+ dlm_queue_ast(dlm, lock);
+ else
+ dlm_lockres_release_ast(dlm, res);
+
+ dlm_lockres_calc_usage(dlm, res);
+ if (kick_thread)
+ dlm_kick_thread(dlm, res);
+
+ return status;
+}
+
+void dlm_revert_pending_lock(struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ /* remove from local queue if it failed */
+ list_del_init(&lock->list);
+ lock->lksb->flags &= ~DLM_LKSB_GET_LVB;
+}
+
+
+/*
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock
+ * held on exit: none
+ * returns: DLM_DENIED, DLM_RECOVERING, or net status
+ */
+static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags)
+{
+ enum dlm_status status = DLM_DENIED;
+
+ mlog_entry("type=%d\n", lock->ml.type);
+ mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len,
+ res->lockname.name, flags);
+
+ spin_lock(&res->spinlock);
+
+ /* will exit this call with spinlock held */
+ __dlm_wait_on_lockres(res);
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+
+ /* add lock to local (secondary) queue */
+ dlm_lock_get(lock);
+ list_add_tail(&lock->list, &res->blocked);
+ lock->lock_pending = 1;
+ spin_unlock(&res->spinlock);
+
+ /* spec seems to say that you will get DLM_NORMAL when the lock
+ * has been queued, meaning we need to wait for a reply here. */
+ status = dlm_send_remote_lock_request(dlm, res, lock, flags);
+
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ lock->lock_pending = 0;
+ if (status != DLM_NORMAL) {
+ if (status != DLM_NOTQUEUED)
+ dlm_error(status);
+ dlm_revert_pending_lock(res, lock);
+ dlm_lock_put(lock);
+ }
+ spin_unlock(&res->spinlock);
+
+ dlm_lockres_calc_usage(dlm, res);
+
+ wake_up(&res->wq);
+ return status;
+}
+
+
+/* for remote lock creation.
+ * locking:
+ * caller needs: none, but need res->state & DLM_LOCK_RES_IN_PROGRESS
+ * taken: none
+ * held on exit: none
+ * returns: DLM_NOLOCKMGR, or net status
+ */
+static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock, int flags)
+{
+ struct dlm_create_lock create;
+ int tmpret, status = 0;
+ enum dlm_status ret;
+
+ mlog_entry_void();
+
+ memset(&create, 0, sizeof(create));
+ create.node_idx = dlm->node_num;
+ create.requested_type = lock->ml.type;
+ create.cookie = lock->ml.cookie;
+ create.namelen = res->lockname.len;
+ create.flags = cpu_to_be32(flags);
+ memcpy(create.name, res->lockname.name, create.namelen);
+
+ tmpret = o2net_send_message(DLM_CREATE_LOCK_MSG, dlm->key, &create,
+ sizeof(create), res->owner, &status);
+ if (tmpret >= 0) {
+ // successfully sent and received
+ ret = status; // this is already a dlm_status
+ } else {
+ mlog_errno(tmpret);
+ if (dlm_is_host_down(tmpret)) {
+ ret = DLM_RECOVERING;
+ mlog(0, "node %u died so returning DLM_RECOVERING "
+ "from lock message!\n", res->owner);
+ } else {
+ ret = dlm_err_to_dlm_status(tmpret);
+ }
+ }
+
+ return ret;
+}
+
+void dlm_lock_get(struct dlm_lock *lock)
+{
+ kref_get(&lock->lock_refs);
+}
+
+void dlm_lock_put(struct dlm_lock *lock)
+{
+ kref_put(&lock->lock_refs, dlm_lock_release);
+}
+
+static void dlm_lock_release(struct kref *kref)
+{
+ struct dlm_lock *lock;
+
+ lock = container_of(kref, struct dlm_lock, lock_refs);
+
+ BUG_ON(!list_empty(&lock->list));
+ BUG_ON(!list_empty(&lock->ast_list));
+ BUG_ON(!list_empty(&lock->bast_list));
+ BUG_ON(lock->ast_pending);
+ BUG_ON(lock->bast_pending);
+
+ dlm_lock_detach_lockres(lock);
+
+ if (lock->lksb_kernel_allocated) {
+ mlog(0, "freeing kernel-allocated lksb\n");
+ kfree(lock->lksb);
+ }
+ kfree(lock);
+}
+
+/* associate a lock with it's lockres, getting a ref on the lockres */
+void dlm_lock_attach_lockres(struct dlm_lock *lock,
+ struct dlm_lock_resource *res)
+{
+ dlm_lockres_get(res);
+ lock->lockres = res;
+}
+
+/* drop ref on lockres, if there is still one associated with lock */
+static void dlm_lock_detach_lockres(struct dlm_lock *lock)
+{
+ struct dlm_lock_resource *res;
+
+ res = lock->lockres;
+ if (res) {
+ lock->lockres = NULL;
+ mlog(0, "removing lock's lockres reference\n");
+ dlm_lockres_put(res);
+ }
+}
+
+static void dlm_init_lock(struct dlm_lock *newlock, int type,
+ u8 node, u64 cookie)
+{
+ INIT_LIST_HEAD(&newlock->list);
+ INIT_LIST_HEAD(&newlock->ast_list);
+ INIT_LIST_HEAD(&newlock->bast_list);
+ spin_lock_init(&newlock->spinlock);
+ newlock->ml.type = type;
+ newlock->ml.convert_type = LKM_IVMODE;
+ newlock->ml.highest_blocked = LKM_IVMODE;
+ newlock->ml.node = node;
+ newlock->ml.pad1 = 0;
+ newlock->ml.list = 0;
+ newlock->ml.flags = 0;
+ newlock->ast = NULL;
+ newlock->bast = NULL;
+ newlock->astdata = NULL;
+ newlock->ml.cookie = cpu_to_be64(cookie);
+ newlock->ast_pending = 0;
+ newlock->bast_pending = 0;
+ newlock->convert_pending = 0;
+ newlock->lock_pending = 0;
+ newlock->unlock_pending = 0;
+ newlock->cancel_pending = 0;
+ newlock->lksb_kernel_allocated = 0;
+
+ kref_init(&newlock->lock_refs);
+}
+
+struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
+ struct dlm_lockstatus *lksb)
+{
+ struct dlm_lock *lock;
+ int kernel_allocated = 0;
+
+ lock = kcalloc(1, sizeof(*lock), GFP_KERNEL);
+ if (!lock)
+ return NULL;
+
+ if (!lksb) {
+ /* zero memory only if kernel-allocated */
+ lksb = kcalloc(1, sizeof(*lksb), GFP_KERNEL);
+ if (!lksb) {
+ kfree(lock);
+ return NULL;
+ }
+ kernel_allocated = 1;
+ }
+
+ dlm_init_lock(lock, type, node, cookie);
+ if (kernel_allocated)
+ lock->lksb_kernel_allocated = 1;
+ lock->lksb = lksb;
+ lksb->lockid = lock;
+ return lock;
+}
+
+/* handler for lock creation net message
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_SYSERR, DLM_IVLOCKID, DLM_NOTQUEUED
+ */
+int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_create_lock *create = (struct dlm_create_lock *)msg->buf;
+ struct dlm_lock_resource *res = NULL;
+ struct dlm_lock *newlock = NULL;
+ struct dlm_lockstatus *lksb = NULL;
+ enum dlm_status status = DLM_NORMAL;
+ char *name;
+ unsigned int namelen;
+
+ BUG_ON(!dlm);
+
+ mlog_entry_void();
+
+ if (!dlm_grab(dlm))
+ return DLM_REJECTED;
+
+ mlog_bug_on_msg(!dlm_domain_fully_joined(dlm),
+ "Domain %s not fully joined!\n", dlm->name);
+
+ name = create->name;
+ namelen = create->namelen;
+
+ status = DLM_IVBUFLEN;
+ if (namelen > DLM_LOCKID_NAME_MAX) {
+ dlm_error(status);
+ goto leave;
+ }
+
+ status = DLM_SYSERR;
+ newlock = dlm_new_lock(create->requested_type,
+ create->node_idx,
+ be64_to_cpu(create->cookie), NULL);
+ if (!newlock) {
+ dlm_error(status);
+ goto leave;
+ }
+
+ lksb = newlock->lksb;
+
+ if (be32_to_cpu(create->flags) & LKM_GET_LVB) {
+ lksb->flags |= DLM_LKSB_GET_LVB;
+ mlog(0, "set DLM_LKSB_GET_LVB flag\n");
+ }
+
+ status = DLM_IVLOCKID;
+ res = dlm_lookup_lockres(dlm, name, namelen);
+ if (!res) {
+ dlm_error(status);
+ goto leave;
+ }
+
+ spin_lock(&res->spinlock);
+ status = __dlm_lockres_state_to_status(res);
+ spin_unlock(&res->spinlock);
+
+ if (status != DLM_NORMAL) {
+ mlog(0, "lockres recovering/migrating/in-progress\n");
+ goto leave;
+ }
+
+ dlm_lock_attach_lockres(newlock, res);
+
+ status = dlmlock_master(dlm, res, newlock, be32_to_cpu(create->flags));
+leave:
+ if (status != DLM_NORMAL)
+ if (newlock)
+ dlm_lock_put(newlock);
+
+ if (res)
+ dlm_lockres_put(res);
+
+ dlm_put(dlm);
+
+ return status;
+}
+
+
+/* fetch next node-local (u8 nodenum + u56 cookie) into u64 */
+static inline void dlm_get_next_cookie(u8 node_num, u64 *cookie)
+{
+ u64 tmpnode = node_num;
+
+ /* shift single byte of node num into top 8 bits */
+ tmpnode <<= 56;
+
+ spin_lock(&dlm_cookie_lock);
+ *cookie = (dlm_next_cookie | tmpnode);
+ if (++dlm_next_cookie & 0xff00000000000000ull) {
+ mlog(0, "This node's cookie will now wrap!\n");
+ dlm_next_cookie = 1;
+ }
+ spin_unlock(&dlm_cookie_lock);
+}
+
+enum dlm_status dlmlock(struct dlm_ctxt *dlm, int mode,
+ struct dlm_lockstatus *lksb, int flags,
+ const char *name, dlm_astlockfunc_t *ast, void *data,
+ dlm_bastlockfunc_t *bast)
+{
+ enum dlm_status status;
+ struct dlm_lock_resource *res = NULL;
+ struct dlm_lock *lock = NULL;
+ int convert = 0, recovery = 0;
+
+ /* yes this function is a mess.
+ * TODO: clean this up. lots of common code in the
+ * lock and convert paths, especially in the retry blocks */
+ if (!lksb) {
+ dlm_error(DLM_BADARGS);
+ return DLM_BADARGS;
+ }
+
+ status = DLM_BADPARAM;
+ if (mode != LKM_EXMODE && mode != LKM_PRMODE && mode != LKM_NLMODE) {
+ dlm_error(status);
+ goto error;
+ }
+
+ if (flags & ~LKM_VALID_FLAGS) {
+ dlm_error(status);
+ goto error;
+ }
+
+ convert = (flags & LKM_CONVERT);
+ recovery = (flags & LKM_RECOVERY);
+
+ if (recovery &&
+ (!dlm_is_recovery_lock(name, strlen(name)) || convert) ) {
+ dlm_error(status);
+ goto error;
+ }
+ if (convert && (flags & LKM_LOCAL)) {
+ mlog(ML_ERROR, "strange LOCAL convert request!\n");
+ goto error;
+ }
+
+ if (convert) {
+ /* CONVERT request */
+
+ /* if converting, must pass in a valid dlm_lock */
+ lock = lksb->lockid;
+ if (!lock) {
+ mlog(ML_ERROR, "NULL lock pointer in convert "
+ "request\n");
+ goto error;
+ }
+
+ res = lock->lockres;
+ if (!res) {
+ mlog(ML_ERROR, "NULL lockres pointer in convert "
+ "request\n");
+ goto error;
+ }
+ dlm_lockres_get(res);
+
+ /* XXX: for ocfs2 purposes, the ast/bast/astdata/lksb are
+ * static after the original lock call. convert requests will
+ * ensure that everything is the same, or return DLM_BADARGS.
+ * this means that DLM_DENIED_NOASTS will never be returned.
+ */
+ if (lock->lksb != lksb || lock->ast != ast ||
+ lock->bast != bast || lock->astdata != data) {
+ status = DLM_BADARGS;
+ mlog(ML_ERROR, "new args: lksb=%p, ast=%p, bast=%p, "
+ "astdata=%p\n", lksb, ast, bast, data);
+ mlog(ML_ERROR, "orig args: lksb=%p, ast=%p, bast=%p, "
+ "astdata=%p\n", lock->lksb, lock->ast,
+ lock->bast, lock->astdata);
+ goto error;
+ }
+retry_convert:
+ dlm_wait_for_recovery(dlm);
+
+ if (res->owner == dlm->node_num)
+ status = dlmconvert_master(dlm, res, lock, flags, mode);
+ else
+ status = dlmconvert_remote(dlm, res, lock, flags, mode);
+ if (status == DLM_RECOVERING || status == DLM_MIGRATING ||
+ status == DLM_FORWARD) {
+ /* for now, see how this works without sleeping
+ * and just retry right away. I suspect the reco
+ * or migration will complete fast enough that
+ * no waiting will be necessary */
+ mlog(0, "retrying convert with migration/recovery/"
+ "in-progress\n");
+ msleep(100);
+ goto retry_convert;
+ }
+ } else {
+ u64 tmpcookie;
+
+ /* LOCK request */
+ status = DLM_BADARGS;
+ if (!name) {
+ dlm_error(status);
+ goto error;
+ }
+
+ status = DLM_IVBUFLEN;
+ if (strlen(name) > DLM_LOCKID_NAME_MAX || strlen(name) < 1) {
+ dlm_error(status);
+ goto error;
+ }
+
+ dlm_get_next_cookie(dlm->node_num, &tmpcookie);
+ lock = dlm_new_lock(mode, dlm->node_num, tmpcookie, lksb);
+ if (!lock) {
+ dlm_error(status);
+ goto error;
+ }
+
+ if (!recovery)
+ dlm_wait_for_recovery(dlm);
+
+ /* find or create the lock resource */
+ res = dlm_get_lock_resource(dlm, name, flags);
+ if (!res) {
+ status = DLM_IVLOCKID;
+ dlm_error(status);
+ goto error;
+ }
+
+ mlog(0, "type=%d, flags = 0x%x\n", mode, flags);
+ mlog(0, "creating lock: lock=%p res=%p\n", lock, res);
+
+ dlm_lock_attach_lockres(lock, res);
+ lock->ast = ast;
+ lock->bast = bast;
+ lock->astdata = data;
+
+retry_lock:
+ if (flags & LKM_VALBLK) {
+ mlog(0, "LKM_VALBLK passed by caller\n");
+
+ /* LVB requests for non PR, PW or EX locks are
+ * ignored. */
+ if (mode < LKM_PRMODE)
+ flags &= ~LKM_VALBLK;
+ else {
+ flags |= LKM_GET_LVB;
+ lock->lksb->flags |= DLM_LKSB_GET_LVB;
+ }
+ }
+
+ if (res->owner == dlm->node_num)
+ status = dlmlock_master(dlm, res, lock, flags);
+ else
+ status = dlmlock_remote(dlm, res, lock, flags);
+
+ if (status == DLM_RECOVERING || status == DLM_MIGRATING ||
+ status == DLM_FORWARD) {
+ mlog(0, "retrying lock with migration/"
+ "recovery/in progress\n");
+ msleep(100);
+ dlm_wait_for_recovery(dlm);
+ goto retry_lock;
+ }
+
+ if (status != DLM_NORMAL) {
+ lock->lksb->flags &= ~DLM_LKSB_GET_LVB;
+ if (status != DLM_NOTQUEUED)
+ dlm_error(status);
+ goto error;
+ }
+ }
+
+error:
+ if (status != DLM_NORMAL) {
+ if (lock && !convert)
+ dlm_lock_put(lock);
+ // this is kind of unnecessary
+ lksb->status = status;
+ }
+
+ /* put lockres ref from the convert path
+ * or from dlm_get_lock_resource */
+ if (res)
+ dlm_lockres_put(res);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(dlmlock);
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
new file mode 100644
index 000000000000..27e984f7e4cd
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -0,0 +1,2664 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmmod.c
+ *
+ * standalone DLM module
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+#include "dlmdebug.h"
+#include "dlmdomain.h"
+
+#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER)
+#include "cluster/masklog.h"
+
+enum dlm_mle_type {
+ DLM_MLE_BLOCK,
+ DLM_MLE_MASTER,
+ DLM_MLE_MIGRATION
+};
+
+struct dlm_lock_name
+{
+ u8 len;
+ u8 name[DLM_LOCKID_NAME_MAX];
+};
+
+struct dlm_master_list_entry
+{
+ struct list_head list;
+ struct list_head hb_events;
+ struct dlm_ctxt *dlm;
+ spinlock_t spinlock;
+ wait_queue_head_t wq;
+ atomic_t woken;
+ struct kref mle_refs;
+ unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ unsigned long node_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ u8 master;
+ u8 new_master;
+ enum dlm_mle_type type;
+ struct o2hb_callback_func mle_hb_up;
+ struct o2hb_callback_func mle_hb_down;
+ union {
+ struct dlm_lock_resource *res;
+ struct dlm_lock_name name;
+ } u;
+};
+
+static void dlm_mle_node_down(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ struct o2nm_node *node,
+ int idx);
+static void dlm_mle_node_up(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ struct o2nm_node *node,
+ int idx);
+
+static void dlm_assert_master_worker(struct dlm_work_item *item, void *data);
+static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname,
+ unsigned int namelen, void *nodemap,
+ u32 flags);
+
+static inline int dlm_mle_equal(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ const char *name,
+ unsigned int namelen)
+{
+ struct dlm_lock_resource *res;
+
+ if (dlm != mle->dlm)
+ return 0;
+
+ if (mle->type == DLM_MLE_BLOCK ||
+ mle->type == DLM_MLE_MIGRATION) {
+ if (namelen != mle->u.name.len ||
+ memcmp(name, mle->u.name.name, namelen)!=0)
+ return 0;
+ } else {
+ res = mle->u.res;
+ if (namelen != res->lockname.len ||
+ memcmp(res->lockname.name, name, namelen) != 0)
+ return 0;
+ }
+ return 1;
+}
+
+#if 0
+/* Code here is included but defined out as it aids debugging */
+
+void dlm_print_one_mle(struct dlm_master_list_entry *mle)
+{
+ int i = 0, refs;
+ char *type;
+ char attached;
+ u8 master;
+ unsigned int namelen;
+ const char *name;
+ struct kref *k;
+
+ k = &mle->mle_refs;
+ if (mle->type == DLM_MLE_BLOCK)
+ type = "BLK";
+ else if (mle->type == DLM_MLE_MASTER)
+ type = "MAS";
+ else
+ type = "MIG";
+ refs = atomic_read(&k->refcount);
+ master = mle->master;
+ attached = (list_empty(&mle->hb_events) ? 'N' : 'Y');
+
+ if (mle->type != DLM_MLE_MASTER) {
+ namelen = mle->u.name.len;
+ name = mle->u.name.name;
+ } else {
+ namelen = mle->u.res->lockname.len;
+ name = mle->u.res->lockname.name;
+ }
+
+ mlog(ML_NOTICE, " #%3d: %3s %3d %3u %3u %c (%d)%.*s\n",
+ i, type, refs, master, mle->new_master, attached,
+ namelen, namelen, name);
+}
+
+static void dlm_dump_mles(struct dlm_ctxt *dlm)
+{
+ struct dlm_master_list_entry *mle;
+ struct list_head *iter;
+
+ mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
+ mlog(ML_NOTICE, " ####: type refs owner new events? lockname nodemap votemap respmap maybemap\n");
+ spin_lock(&dlm->master_lock);
+ list_for_each(iter, &dlm->master_list) {
+ mle = list_entry(iter, struct dlm_master_list_entry, list);
+ dlm_print_one_mle(mle);
+ }
+ spin_unlock(&dlm->master_lock);
+}
+
+int dlm_dump_all_mles(const char __user *data, unsigned int len)
+{
+ struct list_head *iter;
+ struct dlm_ctxt *dlm;
+
+ spin_lock(&dlm_domain_lock);
+ list_for_each(iter, &dlm_domains) {
+ dlm = list_entry (iter, struct dlm_ctxt, list);
+ mlog(ML_NOTICE, "found dlm: %p, name=%s\n", dlm, dlm->name);
+ dlm_dump_mles(dlm);
+ }
+ spin_unlock(&dlm_domain_lock);
+ return len;
+}
+EXPORT_SYMBOL_GPL(dlm_dump_all_mles);
+
+#endif /* 0 */
+
+
+static kmem_cache_t *dlm_mle_cache = NULL;
+
+
+static void dlm_mle_release(struct kref *kref);
+static void dlm_init_mle(struct dlm_master_list_entry *mle,
+ enum dlm_mle_type type,
+ struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ const char *name,
+ unsigned int namelen);
+static void dlm_put_mle(struct dlm_master_list_entry *mle);
+static void __dlm_put_mle(struct dlm_master_list_entry *mle);
+static int dlm_find_mle(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry **mle,
+ char *name, unsigned int namelen);
+
+static int dlm_do_master_request(struct dlm_master_list_entry *mle, int to);
+
+
+static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ int *blocked);
+static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ int blocked);
+static int dlm_add_migration_mle(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ struct dlm_master_list_entry **oldmle,
+ const char *name, unsigned int namelen,
+ u8 new_master, u8 master);
+
+static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res);
+static int dlm_mark_lockres_migrating(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 target);
+
+
+int dlm_is_host_down(int errno)
+{
+ switch (errno) {
+ case -EBADF:
+ case -ECONNREFUSED:
+ case -ENOTCONN:
+ case -ECONNRESET:
+ case -EPIPE:
+ case -EHOSTDOWN:
+ case -EHOSTUNREACH:
+ case -ETIMEDOUT:
+ case -ECONNABORTED:
+ case -ENETDOWN:
+ case -ENETUNREACH:
+ case -ENETRESET:
+ case -ESHUTDOWN:
+ case -ENOPROTOOPT:
+ case -EINVAL: /* if returned from our tcp code,
+ this means there is no socket */
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * MASTER LIST FUNCTIONS
+ */
+
+
+/*
+ * regarding master list entries and heartbeat callbacks:
+ *
+ * in order to avoid sleeping and allocation that occurs in
+ * heartbeat, master list entries are simply attached to the
+ * dlm's established heartbeat callbacks. the mle is attached
+ * when it is created, and since the dlm->spinlock is held at
+ * that time, any heartbeat event will be properly discovered
+ * by the mle. the mle needs to be detached from the
+ * dlm->mle_hb_events list as soon as heartbeat events are no
+ * longer useful to the mle, and before the mle is freed.
+ *
+ * as a general rule, heartbeat events are no longer needed by
+ * the mle once an "answer" regarding the lock master has been
+ * received.
+ */
+static inline void __dlm_mle_attach_hb_events(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle)
+{
+ assert_spin_locked(&dlm->spinlock);
+
+ list_add_tail(&mle->hb_events, &dlm->mle_hb_events);
+}
+
+
+static inline void __dlm_mle_detach_hb_events(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle)
+{
+ if (!list_empty(&mle->hb_events))
+ list_del_init(&mle->hb_events);
+}
+
+
+static inline void dlm_mle_detach_hb_events(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle)
+{
+ spin_lock(&dlm->spinlock);
+ __dlm_mle_detach_hb_events(dlm, mle);
+ spin_unlock(&dlm->spinlock);
+}
+
+/* remove from list and free */
+static void __dlm_put_mle(struct dlm_master_list_entry *mle)
+{
+ struct dlm_ctxt *dlm;
+ dlm = mle->dlm;
+
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&dlm->master_lock);
+ BUG_ON(!atomic_read(&mle->mle_refs.refcount));
+
+ kref_put(&mle->mle_refs, dlm_mle_release);
+}
+
+
+/* must not have any spinlocks coming in */
+static void dlm_put_mle(struct dlm_master_list_entry *mle)
+{
+ struct dlm_ctxt *dlm;
+ dlm = mle->dlm;
+
+ spin_lock(&dlm->spinlock);
+ spin_lock(&dlm->master_lock);
+ __dlm_put_mle(mle);
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+}
+
+static inline void dlm_get_mle(struct dlm_master_list_entry *mle)
+{
+ kref_get(&mle->mle_refs);
+}
+
+static void dlm_init_mle(struct dlm_master_list_entry *mle,
+ enum dlm_mle_type type,
+ struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ const char *name,
+ unsigned int namelen)
+{
+ assert_spin_locked(&dlm->spinlock);
+
+ mle->dlm = dlm;
+ mle->type = type;
+ INIT_LIST_HEAD(&mle->list);
+ INIT_LIST_HEAD(&mle->hb_events);
+ memset(mle->maybe_map, 0, sizeof(mle->maybe_map));
+ spin_lock_init(&mle->spinlock);
+ init_waitqueue_head(&mle->wq);
+ atomic_set(&mle->woken, 0);
+ kref_init(&mle->mle_refs);
+ memset(mle->response_map, 0, sizeof(mle->response_map));
+ mle->master = O2NM_MAX_NODES;
+ mle->new_master = O2NM_MAX_NODES;
+
+ if (mle->type == DLM_MLE_MASTER) {
+ BUG_ON(!res);
+ mle->u.res = res;
+ } else if (mle->type == DLM_MLE_BLOCK) {
+ BUG_ON(!name);
+ memcpy(mle->u.name.name, name, namelen);
+ mle->u.name.len = namelen;
+ } else /* DLM_MLE_MIGRATION */ {
+ BUG_ON(!name);
+ memcpy(mle->u.name.name, name, namelen);
+ mle->u.name.len = namelen;
+ }
+
+ /* copy off the node_map and register hb callbacks on our copy */
+ memcpy(mle->node_map, dlm->domain_map, sizeof(mle->node_map));
+ memcpy(mle->vote_map, dlm->domain_map, sizeof(mle->vote_map));
+ clear_bit(dlm->node_num, mle->vote_map);
+ clear_bit(dlm->node_num, mle->node_map);
+
+ /* attach the mle to the domain node up/down events */
+ __dlm_mle_attach_hb_events(dlm, mle);
+}
+
+
+/* returns 1 if found, 0 if not */
+static int dlm_find_mle(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry **mle,
+ char *name, unsigned int namelen)
+{
+ struct dlm_master_list_entry *tmpmle;
+ struct list_head *iter;
+
+ assert_spin_locked(&dlm->master_lock);
+
+ list_for_each(iter, &dlm->master_list) {
+ tmpmle = list_entry(iter, struct dlm_master_list_entry, list);
+ if (!dlm_mle_equal(dlm, tmpmle, name, namelen))
+ continue;
+ dlm_get_mle(tmpmle);
+ *mle = tmpmle;
+ return 1;
+ }
+ return 0;
+}
+
+void dlm_hb_event_notify_attached(struct dlm_ctxt *dlm, int idx, int node_up)
+{
+ struct dlm_master_list_entry *mle;
+ struct list_head *iter;
+
+ assert_spin_locked(&dlm->spinlock);
+
+ list_for_each(iter, &dlm->mle_hb_events) {
+ mle = list_entry(iter, struct dlm_master_list_entry,
+ hb_events);
+ if (node_up)
+ dlm_mle_node_up(dlm, mle, NULL, idx);
+ else
+ dlm_mle_node_down(dlm, mle, NULL, idx);
+ }
+}
+
+static void dlm_mle_node_down(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ struct o2nm_node *node, int idx)
+{
+ spin_lock(&mle->spinlock);
+
+ if (!test_bit(idx, mle->node_map))
+ mlog(0, "node %u already removed from nodemap!\n", idx);
+ else
+ clear_bit(idx, mle->node_map);
+
+ spin_unlock(&mle->spinlock);
+}
+
+static void dlm_mle_node_up(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle,
+ struct o2nm_node *node, int idx)
+{
+ spin_lock(&mle->spinlock);
+
+ if (test_bit(idx, mle->node_map))
+ mlog(0, "node %u already in node map!\n", idx);
+ else
+ set_bit(idx, mle->node_map);
+
+ spin_unlock(&mle->spinlock);
+}
+
+
+int dlm_init_mle_cache(void)
+{
+ dlm_mle_cache = kmem_cache_create("dlm_mle_cache",
+ sizeof(struct dlm_master_list_entry),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (dlm_mle_cache == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+void dlm_destroy_mle_cache(void)
+{
+ if (dlm_mle_cache)
+ kmem_cache_destroy(dlm_mle_cache);
+}
+
+static void dlm_mle_release(struct kref *kref)
+{
+ struct dlm_master_list_entry *mle;
+ struct dlm_ctxt *dlm;
+
+ mlog_entry_void();
+
+ mle = container_of(kref, struct dlm_master_list_entry, mle_refs);
+ dlm = mle->dlm;
+
+ if (mle->type != DLM_MLE_MASTER) {
+ mlog(0, "calling mle_release for %.*s, type %d\n",
+ mle->u.name.len, mle->u.name.name, mle->type);
+ } else {
+ mlog(0, "calling mle_release for %.*s, type %d\n",
+ mle->u.res->lockname.len,
+ mle->u.res->lockname.name, mle->type);
+ }
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&dlm->master_lock);
+
+ /* remove from list if not already */
+ if (!list_empty(&mle->list))
+ list_del_init(&mle->list);
+
+ /* detach the mle from the domain node up/down events */
+ __dlm_mle_detach_hb_events(dlm, mle);
+
+ /* NOTE: kfree under spinlock here.
+ * if this is bad, we can move this to a freelist. */
+ kmem_cache_free(dlm_mle_cache, mle);
+}
+
+
+/*
+ * LOCK RESOURCE FUNCTIONS
+ */
+
+static void dlm_set_lockres_owner(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 owner)
+{
+ assert_spin_locked(&res->spinlock);
+
+ mlog_entry("%.*s, %u\n", res->lockname.len, res->lockname.name, owner);
+
+ if (owner == dlm->node_num)
+ atomic_inc(&dlm->local_resources);
+ else if (owner == DLM_LOCK_RES_OWNER_UNKNOWN)
+ atomic_inc(&dlm->unknown_resources);
+ else
+ atomic_inc(&dlm->remote_resources);
+
+ res->owner = owner;
+}
+
+void dlm_change_lockres_owner(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res, u8 owner)
+{
+ assert_spin_locked(&res->spinlock);
+
+ if (owner == res->owner)
+ return;
+
+ if (res->owner == dlm->node_num)
+ atomic_dec(&dlm->local_resources);
+ else if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN)
+ atomic_dec(&dlm->unknown_resources);
+ else
+ atomic_dec(&dlm->remote_resources);
+
+ dlm_set_lockres_owner(dlm, res, owner);
+}
+
+
+static void dlm_lockres_release(struct kref *kref)
+{
+ struct dlm_lock_resource *res;
+
+ res = container_of(kref, struct dlm_lock_resource, refs);
+
+ /* This should not happen -- all lockres' have a name
+ * associated with them at init time. */
+ BUG_ON(!res->lockname.name);
+
+ mlog(0, "destroying lockres %.*s\n", res->lockname.len,
+ res->lockname.name);
+
+ /* By the time we're ready to blow this guy away, we shouldn't
+ * be on any lists. */
+ BUG_ON(!list_empty(&res->list));
+ BUG_ON(!list_empty(&res->granted));
+ BUG_ON(!list_empty(&res->converting));
+ BUG_ON(!list_empty(&res->blocked));
+ BUG_ON(!list_empty(&res->dirty));
+ BUG_ON(!list_empty(&res->recovering));
+ BUG_ON(!list_empty(&res->purge));
+
+ kfree(res->lockname.name);
+
+ kfree(res);
+}
+
+void dlm_lockres_get(struct dlm_lock_resource *res)
+{
+ kref_get(&res->refs);
+}
+
+void dlm_lockres_put(struct dlm_lock_resource *res)
+{
+ kref_put(&res->refs, dlm_lockres_release);
+}
+
+static void dlm_init_lockres(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ const char *name, unsigned int namelen)
+{
+ char *qname;
+
+ /* If we memset here, we lose our reference to the kmalloc'd
+ * res->lockname.name, so be sure to init every field
+ * correctly! */
+
+ qname = (char *) res->lockname.name;
+ memcpy(qname, name, namelen);
+
+ res->lockname.len = namelen;
+ res->lockname.hash = full_name_hash(name, namelen);
+
+ init_waitqueue_head(&res->wq);
+ spin_lock_init(&res->spinlock);
+ INIT_LIST_HEAD(&res->list);
+ INIT_LIST_HEAD(&res->granted);
+ INIT_LIST_HEAD(&res->converting);
+ INIT_LIST_HEAD(&res->blocked);
+ INIT_LIST_HEAD(&res->dirty);
+ INIT_LIST_HEAD(&res->recovering);
+ INIT_LIST_HEAD(&res->purge);
+ atomic_set(&res->asts_reserved, 0);
+ res->migration_pending = 0;
+
+ kref_init(&res->refs);
+
+ /* just for consistency */
+ spin_lock(&res->spinlock);
+ dlm_set_lockres_owner(dlm, res, DLM_LOCK_RES_OWNER_UNKNOWN);
+ spin_unlock(&res->spinlock);
+
+ res->state = DLM_LOCK_RES_IN_PROGRESS;
+
+ res->last_used = 0;
+
+ memset(res->lvb, 0, DLM_LVB_LEN);
+}
+
+struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
+ const char *name,
+ unsigned int namelen)
+{
+ struct dlm_lock_resource *res;
+
+ res = kmalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL);
+ if (!res)
+ return NULL;
+
+ res->lockname.name = kmalloc(namelen, GFP_KERNEL);
+ if (!res->lockname.name) {
+ kfree(res);
+ return NULL;
+ }
+
+ dlm_init_lockres(dlm, res, name, namelen);
+ return res;
+}
+
+/*
+ * lookup a lock resource by name.
+ * may already exist in the hashtable.
+ * lockid is null terminated
+ *
+ * if not, allocate enough for the lockres and for
+ * the temporary structure used in doing the mastering.
+ *
+ * also, do a lookup in the dlm->master_list to see
+ * if another node has begun mastering the same lock.
+ * if so, there should be a block entry in there
+ * for this name, and we should *not* attempt to master
+ * the lock here. need to wait around for that node
+ * to assert_master (or die).
+ *
+ */
+struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
+ const char *lockid,
+ int flags)
+{
+ struct dlm_lock_resource *tmpres=NULL, *res=NULL;
+ struct dlm_master_list_entry *mle = NULL;
+ struct dlm_master_list_entry *alloc_mle = NULL;
+ int blocked = 0;
+ int ret, nodenum;
+ struct dlm_node_iter iter;
+ unsigned int namelen;
+ int tries = 0;
+
+ BUG_ON(!lockid);
+
+ namelen = strlen(lockid);
+
+ mlog(0, "get lockres %s (len %d)\n", lockid, namelen);
+
+lookup:
+ spin_lock(&dlm->spinlock);
+ tmpres = __dlm_lookup_lockres(dlm, lockid, namelen);
+ if (tmpres) {
+ spin_unlock(&dlm->spinlock);
+ mlog(0, "found in hash!\n");
+ if (res)
+ dlm_lockres_put(res);
+ res = tmpres;
+ goto leave;
+ }
+
+ if (!res) {
+ spin_unlock(&dlm->spinlock);
+ mlog(0, "allocating a new resource\n");
+ /* nothing found and we need to allocate one. */
+ alloc_mle = (struct dlm_master_list_entry *)
+ kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL);
+ if (!alloc_mle)
+ goto leave;
+ res = dlm_new_lockres(dlm, lockid, namelen);
+ if (!res)
+ goto leave;
+ goto lookup;
+ }
+
+ mlog(0, "no lockres found, allocated our own: %p\n", res);
+
+ if (flags & LKM_LOCAL) {
+ /* caller knows it's safe to assume it's not mastered elsewhere
+ * DONE! return right away */
+ spin_lock(&res->spinlock);
+ dlm_change_lockres_owner(dlm, res, dlm->node_num);
+ __dlm_insert_lockres(dlm, res);
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+ /* lockres still marked IN_PROGRESS */
+ goto wake_waiters;
+ }
+
+ /* check master list to see if another node has started mastering it */
+ spin_lock(&dlm->master_lock);
+
+ /* if we found a block, wait for lock to be mastered by another node */
+ blocked = dlm_find_mle(dlm, &mle, (char *)lockid, namelen);
+ if (blocked) {
+ if (mle->type == DLM_MLE_MASTER) {
+ mlog(ML_ERROR, "master entry for nonexistent lock!\n");
+ BUG();
+ } else if (mle->type == DLM_MLE_MIGRATION) {
+ /* migration is in progress! */
+ /* the good news is that we now know the
+ * "current" master (mle->master). */
+
+ spin_unlock(&dlm->master_lock);
+ assert_spin_locked(&dlm->spinlock);
+
+ /* set the lockres owner and hash it */
+ spin_lock(&res->spinlock);
+ dlm_set_lockres_owner(dlm, res, mle->master);
+ __dlm_insert_lockres(dlm, res);
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+
+ /* master is known, detach */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ mle = NULL;
+ goto wake_waiters;
+ }
+ } else {
+ /* go ahead and try to master lock on this node */
+ mle = alloc_mle;
+ /* make sure this does not get freed below */
+ alloc_mle = NULL;
+ dlm_init_mle(mle, DLM_MLE_MASTER, dlm, res, NULL, 0);
+ set_bit(dlm->node_num, mle->maybe_map);
+ list_add(&mle->list, &dlm->master_list);
+ }
+
+ /* at this point there is either a DLM_MLE_BLOCK or a
+ * DLM_MLE_MASTER on the master list, so it's safe to add the
+ * lockres to the hashtable. anyone who finds the lock will
+ * still have to wait on the IN_PROGRESS. */
+
+ /* finally add the lockres to its hash bucket */
+ __dlm_insert_lockres(dlm, res);
+ /* get an extra ref on the mle in case this is a BLOCK
+ * if so, the creator of the BLOCK may try to put the last
+ * ref at this time in the assert master handler, so we
+ * need an extra one to keep from a bad ptr deref. */
+ dlm_get_mle(mle);
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ /* must wait for lock to be mastered elsewhere */
+ if (blocked)
+ goto wait;
+
+redo_request:
+ ret = -EINVAL;
+ dlm_node_iter_init(mle->vote_map, &iter);
+ while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
+ ret = dlm_do_master_request(mle, nodenum);
+ if (ret < 0)
+ mlog_errno(ret);
+ if (mle->master != O2NM_MAX_NODES) {
+ /* found a master ! */
+ break;
+ }
+ }
+
+wait:
+ /* keep going until the response map includes all nodes */
+ ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked);
+ if (ret < 0) {
+ mlog(0, "%s:%.*s: node map changed, redo the "
+ "master request now, blocked=%d\n",
+ dlm->name, res->lockname.len,
+ res->lockname.name, blocked);
+ if (++tries > 20) {
+ mlog(ML_ERROR, "%s:%.*s: spinning on "
+ "dlm_wait_for_lock_mastery, blocked=%d\n",
+ dlm->name, res->lockname.len,
+ res->lockname.name, blocked);
+ dlm_print_one_lock_resource(res);
+ /* dlm_print_one_mle(mle); */
+ tries = 0;
+ }
+ goto redo_request;
+ }
+
+ mlog(0, "lockres mastered by %u\n", res->owner);
+ /* make sure we never continue without this */
+ BUG_ON(res->owner == O2NM_MAX_NODES);
+
+ /* master is known, detach if not already detached */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ /* put the extra ref */
+ dlm_put_mle(mle);
+
+wake_waiters:
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+
+leave:
+ /* need to free the unused mle */
+ if (alloc_mle)
+ kmem_cache_free(dlm_mle_cache, alloc_mle);
+
+ return res;
+}
+
+
+#define DLM_MASTERY_TIMEOUT_MS 5000
+
+static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ int *blocked)
+{
+ u8 m;
+ int ret, bit;
+ int map_changed, voting_done;
+ int assert, sleep;
+
+recheck:
+ ret = 0;
+ assert = 0;
+
+ /* check if another node has already become the owner */
+ spin_lock(&res->spinlock);
+ if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ spin_unlock(&res->spinlock);
+ goto leave;
+ }
+ spin_unlock(&res->spinlock);
+
+ spin_lock(&mle->spinlock);
+ m = mle->master;
+ map_changed = (memcmp(mle->vote_map, mle->node_map,
+ sizeof(mle->vote_map)) != 0);
+ voting_done = (memcmp(mle->vote_map, mle->response_map,
+ sizeof(mle->vote_map)) == 0);
+
+ /* restart if we hit any errors */
+ if (map_changed) {
+ int b;
+ mlog(0, "%s: %.*s: node map changed, restarting\n",
+ dlm->name, res->lockname.len, res->lockname.name);
+ ret = dlm_restart_lock_mastery(dlm, res, mle, *blocked);
+ b = (mle->type == DLM_MLE_BLOCK);
+ if ((*blocked && !b) || (!*blocked && b)) {
+ mlog(0, "%s:%.*s: status change: old=%d new=%d\n",
+ dlm->name, res->lockname.len, res->lockname.name,
+ *blocked, b);
+ *blocked = b;
+ }
+ spin_unlock(&mle->spinlock);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto leave;
+ }
+ mlog(0, "%s:%.*s: restart lock mastery succeeded, "
+ "rechecking now\n", dlm->name, res->lockname.len,
+ res->lockname.name);
+ goto recheck;
+ }
+
+ if (m != O2NM_MAX_NODES) {
+ /* another node has done an assert!
+ * all done! */
+ sleep = 0;
+ } else {
+ sleep = 1;
+ /* have all nodes responded? */
+ if (voting_done && !*blocked) {
+ bit = find_next_bit(mle->maybe_map, O2NM_MAX_NODES, 0);
+ if (dlm->node_num <= bit) {
+ /* my node number is lowest.
+ * now tell other nodes that I am
+ * mastering this. */
+ mle->master = dlm->node_num;
+ assert = 1;
+ sleep = 0;
+ }
+ /* if voting is done, but we have not received
+ * an assert master yet, we must sleep */
+ }
+ }
+
+ spin_unlock(&mle->spinlock);
+
+ /* sleep if we haven't finished voting yet */
+ if (sleep) {
+ unsigned long timeo = msecs_to_jiffies(DLM_MASTERY_TIMEOUT_MS);
+
+ /*
+ if (atomic_read(&mle->mle_refs.refcount) < 2)
+ mlog(ML_ERROR, "mle (%p) refs=%d, name=%.*s\n", mle,
+ atomic_read(&mle->mle_refs.refcount),
+ res->lockname.len, res->lockname.name);
+ */
+ atomic_set(&mle->woken, 0);
+ (void)wait_event_timeout(mle->wq,
+ (atomic_read(&mle->woken) == 1),
+ timeo);
+ if (res->owner == O2NM_MAX_NODES) {
+ mlog(0, "waiting again\n");
+ goto recheck;
+ }
+ mlog(0, "done waiting, master is %u\n", res->owner);
+ ret = 0;
+ goto leave;
+ }
+
+ ret = 0; /* done */
+ if (assert) {
+ m = dlm->node_num;
+ mlog(0, "about to master %.*s here, this=%u\n",
+ res->lockname.len, res->lockname.name, m);
+ ret = dlm_do_assert_master(dlm, res->lockname.name,
+ res->lockname.len, mle->vote_map, 0);
+ if (ret) {
+ /* This is a failure in the network path,
+ * not in the response to the assert_master
+ * (any nonzero response is a BUG on this node).
+ * Most likely a socket just got disconnected
+ * due to node death. */
+ mlog_errno(ret);
+ }
+ /* no longer need to restart lock mastery.
+ * all living nodes have been contacted. */
+ ret = 0;
+ }
+
+ /* set the lockres owner */
+ spin_lock(&res->spinlock);
+ dlm_change_lockres_owner(dlm, res, m);
+ spin_unlock(&res->spinlock);
+
+leave:
+ return ret;
+}
+
+struct dlm_bitmap_diff_iter
+{
+ int curnode;
+ unsigned long *orig_bm;
+ unsigned long *cur_bm;
+ unsigned long diff_bm[BITS_TO_LONGS(O2NM_MAX_NODES)];
+};
+
+enum dlm_node_state_change
+{
+ NODE_DOWN = -1,
+ NODE_NO_CHANGE = 0,
+ NODE_UP
+};
+
+static void dlm_bitmap_diff_iter_init(struct dlm_bitmap_diff_iter *iter,
+ unsigned long *orig_bm,
+ unsigned long *cur_bm)
+{
+ unsigned long p1, p2;
+ int i;
+
+ iter->curnode = -1;
+ iter->orig_bm = orig_bm;
+ iter->cur_bm = cur_bm;
+
+ for (i = 0; i < BITS_TO_LONGS(O2NM_MAX_NODES); i++) {
+ p1 = *(iter->orig_bm + i);
+ p2 = *(iter->cur_bm + i);
+ iter->diff_bm[i] = (p1 & ~p2) | (p2 & ~p1);
+ }
+}
+
+static int dlm_bitmap_diff_iter_next(struct dlm_bitmap_diff_iter *iter,
+ enum dlm_node_state_change *state)
+{
+ int bit;
+
+ if (iter->curnode >= O2NM_MAX_NODES)
+ return -ENOENT;
+
+ bit = find_next_bit(iter->diff_bm, O2NM_MAX_NODES,
+ iter->curnode+1);
+ if (bit >= O2NM_MAX_NODES) {
+ iter->curnode = O2NM_MAX_NODES;
+ return -ENOENT;
+ }
+
+ /* if it was there in the original then this node died */
+ if (test_bit(bit, iter->orig_bm))
+ *state = NODE_DOWN;
+ else
+ *state = NODE_UP;
+
+ iter->curnode = bit;
+ return bit;
+}
+
+
+static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ int blocked)
+{
+ struct dlm_bitmap_diff_iter bdi;
+ enum dlm_node_state_change sc;
+ int node;
+ int ret = 0;
+
+ mlog(0, "something happened such that the "
+ "master process may need to be restarted!\n");
+
+ assert_spin_locked(&mle->spinlock);
+
+ dlm_bitmap_diff_iter_init(&bdi, mle->vote_map, mle->node_map);
+ node = dlm_bitmap_diff_iter_next(&bdi, &sc);
+ while (node >= 0) {
+ if (sc == NODE_UP) {
+ /* a node came up. easy. might not even need
+ * to talk to it if its node number is higher
+ * or if we are already blocked. */
+ mlog(0, "node up! %d\n", node);
+ if (blocked)
+ goto next;
+
+ if (node > dlm->node_num) {
+ mlog(0, "node > this node. skipping.\n");
+ goto next;
+ }
+
+ /* redo the master request, but only for the new node */
+ mlog(0, "sending request to new node\n");
+ clear_bit(node, mle->response_map);
+ set_bit(node, mle->vote_map);
+ } else {
+ mlog(ML_ERROR, "node down! %d\n", node);
+
+ /* if the node wasn't involved in mastery skip it,
+ * but clear it out from the maps so that it will
+ * not affect mastery of this lockres */
+ clear_bit(node, mle->response_map);
+ clear_bit(node, mle->vote_map);
+ if (!test_bit(node, mle->maybe_map))
+ goto next;
+
+ /* if we're already blocked on lock mastery, and the
+ * dead node wasn't the expected master, or there is
+ * another node in the maybe_map, keep waiting */
+ if (blocked) {
+ int lowest = find_next_bit(mle->maybe_map,
+ O2NM_MAX_NODES, 0);
+
+ /* act like it was never there */
+ clear_bit(node, mle->maybe_map);
+
+ if (node != lowest)
+ goto next;
+
+ mlog(ML_ERROR, "expected master %u died while "
+ "this node was blocked waiting on it!\n",
+ node);
+ lowest = find_next_bit(mle->maybe_map,
+ O2NM_MAX_NODES,
+ lowest+1);
+ if (lowest < O2NM_MAX_NODES) {
+ mlog(0, "still blocked. waiting "
+ "on %u now\n", lowest);
+ goto next;
+ }
+
+ /* mle is an MLE_BLOCK, but there is now
+ * nothing left to block on. we need to return
+ * all the way back out and try again with
+ * an MLE_MASTER. dlm_do_local_recovery_cleanup
+ * has already run, so the mle refcount is ok */
+ mlog(0, "no longer blocking. we can "
+ "try to master this here\n");
+ mle->type = DLM_MLE_MASTER;
+ memset(mle->maybe_map, 0,
+ sizeof(mle->maybe_map));
+ memset(mle->response_map, 0,
+ sizeof(mle->maybe_map));
+ memcpy(mle->vote_map, mle->node_map,
+ sizeof(mle->node_map));
+ mle->u.res = res;
+ set_bit(dlm->node_num, mle->maybe_map);
+
+ ret = -EAGAIN;
+ goto next;
+ }
+
+ clear_bit(node, mle->maybe_map);
+ if (node > dlm->node_num)
+ goto next;
+
+ mlog(0, "dead node in map!\n");
+ /* yuck. go back and re-contact all nodes
+ * in the vote_map, removing this node. */
+ memset(mle->response_map, 0,
+ sizeof(mle->response_map));
+ }
+ ret = -EAGAIN;
+next:
+ node = dlm_bitmap_diff_iter_next(&bdi, &sc);
+ }
+ return ret;
+}
+
+
+/*
+ * DLM_MASTER_REQUEST_MSG
+ *
+ * returns: 0 on success,
+ * -errno on a network error
+ *
+ * on error, the caller should assume the target node is "dead"
+ *
+ */
+
+static int dlm_do_master_request(struct dlm_master_list_entry *mle, int to)
+{
+ struct dlm_ctxt *dlm = mle->dlm;
+ struct dlm_master_request request;
+ int ret, response=0, resend;
+
+ memset(&request, 0, sizeof(request));
+ request.node_idx = dlm->node_num;
+
+ BUG_ON(mle->type == DLM_MLE_MIGRATION);
+
+ if (mle->type != DLM_MLE_MASTER) {
+ request.namelen = mle->u.name.len;
+ memcpy(request.name, mle->u.name.name, request.namelen);
+ } else {
+ request.namelen = mle->u.res->lockname.len;
+ memcpy(request.name, mle->u.res->lockname.name,
+ request.namelen);
+ }
+
+again:
+ ret = o2net_send_message(DLM_MASTER_REQUEST_MSG, dlm->key, &request,
+ sizeof(request), to, &response);
+ if (ret < 0) {
+ if (ret == -ESRCH) {
+ /* should never happen */
+ mlog(ML_ERROR, "TCP stack not ready!\n");
+ BUG();
+ } else if (ret == -EINVAL) {
+ mlog(ML_ERROR, "bad args passed to o2net!\n");
+ BUG();
+ } else if (ret == -ENOMEM) {
+ mlog(ML_ERROR, "out of memory while trying to send "
+ "network message! retrying\n");
+ /* this is totally crude */
+ msleep(50);
+ goto again;
+ } else if (!dlm_is_host_down(ret)) {
+ /* not a network error. bad. */
+ mlog_errno(ret);
+ mlog(ML_ERROR, "unhandled error!");
+ BUG();
+ }
+ /* all other errors should be network errors,
+ * and likely indicate node death */
+ mlog(ML_ERROR, "link to %d went down!\n", to);
+ goto out;
+ }
+
+ ret = 0;
+ resend = 0;
+ spin_lock(&mle->spinlock);
+ switch (response) {
+ case DLM_MASTER_RESP_YES:
+ set_bit(to, mle->response_map);
+ mlog(0, "node %u is the master, response=YES\n", to);
+ mle->master = to;
+ break;
+ case DLM_MASTER_RESP_NO:
+ mlog(0, "node %u not master, response=NO\n", to);
+ set_bit(to, mle->response_map);
+ break;
+ case DLM_MASTER_RESP_MAYBE:
+ mlog(0, "node %u not master, response=MAYBE\n", to);
+ set_bit(to, mle->response_map);
+ set_bit(to, mle->maybe_map);
+ break;
+ case DLM_MASTER_RESP_ERROR:
+ mlog(0, "node %u hit an error, resending\n", to);
+ resend = 1;
+ response = 0;
+ break;
+ default:
+ mlog(ML_ERROR, "bad response! %u\n", response);
+ BUG();
+ }
+ spin_unlock(&mle->spinlock);
+ if (resend) {
+ /* this is also totally crude */
+ msleep(50);
+ goto again;
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * locks that can be taken here:
+ * dlm->spinlock
+ * res->spinlock
+ * mle->spinlock
+ * dlm->master_list
+ *
+ * if possible, TRIM THIS DOWN!!!
+ */
+int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ u8 response = DLM_MASTER_RESP_MAYBE;
+ struct dlm_ctxt *dlm = data;
+ struct dlm_lock_resource *res;
+ struct dlm_master_request *request = (struct dlm_master_request *) msg->buf;
+ struct dlm_master_list_entry *mle = NULL, *tmpmle = NULL;
+ char *name;
+ unsigned int namelen;
+ int found, ret;
+ int set_maybe;
+
+ if (!dlm_grab(dlm))
+ return DLM_MASTER_RESP_NO;
+
+ if (!dlm_domain_fully_joined(dlm)) {
+ response = DLM_MASTER_RESP_NO;
+ goto send_response;
+ }
+
+ name = request->name;
+ namelen = request->namelen;
+
+ if (namelen > DLM_LOCKID_NAME_MAX) {
+ response = DLM_IVBUFLEN;
+ goto send_response;
+ }
+
+way_up_top:
+ spin_lock(&dlm->spinlock);
+ res = __dlm_lookup_lockres(dlm, name, namelen);
+ if (res) {
+ spin_unlock(&dlm->spinlock);
+
+ /* take care of the easy cases up front */
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ spin_unlock(&res->spinlock);
+ mlog(0, "returning DLM_MASTER_RESP_ERROR since res is "
+ "being recovered\n");
+ response = DLM_MASTER_RESP_ERROR;
+ if (mle)
+ kmem_cache_free(dlm_mle_cache, mle);
+ goto send_response;
+ }
+
+ if (res->owner == dlm->node_num) {
+ u32 flags = DLM_ASSERT_MASTER_MLE_CLEANUP;
+ spin_unlock(&res->spinlock);
+ // mlog(0, "this node is the master\n");
+ response = DLM_MASTER_RESP_YES;
+ if (mle)
+ kmem_cache_free(dlm_mle_cache, mle);
+
+ /* this node is the owner.
+ * there is some extra work that needs to
+ * happen now. the requesting node has
+ * caused all nodes up to this one to
+ * create mles. this node now needs to
+ * go back and clean those up. */
+ mlog(0, "%u is the owner of %.*s, cleaning everyone else\n",
+ dlm->node_num, res->lockname.len, res->lockname.name);
+ ret = dlm_dispatch_assert_master(dlm, res, 1,
+ request->node_idx,
+ flags);
+ if (ret < 0) {
+ mlog(ML_ERROR, "failed to dispatch assert "
+ "master work\n");
+ response = DLM_MASTER_RESP_ERROR;
+ }
+ goto send_response;
+ } else if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ spin_unlock(&res->spinlock);
+ // mlog(0, "node %u is the master\n", res->owner);
+ response = DLM_MASTER_RESP_NO;
+ if (mle)
+ kmem_cache_free(dlm_mle_cache, mle);
+ goto send_response;
+ }
+
+ /* ok, there is no owner. either this node is
+ * being blocked, or it is actively trying to
+ * master this lock. */
+ if (!(res->state & DLM_LOCK_RES_IN_PROGRESS)) {
+ mlog(ML_ERROR, "lock with no owner should be "
+ "in-progress!\n");
+ BUG();
+ }
+
+ // mlog(0, "lockres is in progress...\n");
+ spin_lock(&dlm->master_lock);
+ found = dlm_find_mle(dlm, &tmpmle, name, namelen);
+ if (!found) {
+ mlog(ML_ERROR, "no mle found for this lock!\n");
+ BUG();
+ }
+ set_maybe = 1;
+ spin_lock(&tmpmle->spinlock);
+ if (tmpmle->type == DLM_MLE_BLOCK) {
+ // mlog(0, "this node is waiting for "
+ // "lockres to be mastered\n");
+ response = DLM_MASTER_RESP_NO;
+ } else if (tmpmle->type == DLM_MLE_MIGRATION) {
+ mlog(0, "node %u is master, but trying to migrate to "
+ "node %u.\n", tmpmle->master, tmpmle->new_master);
+ if (tmpmle->master == dlm->node_num) {
+ response = DLM_MASTER_RESP_YES;
+ mlog(ML_ERROR, "no owner on lockres, but this "
+ "node is trying to migrate it to %u?!\n",
+ tmpmle->new_master);
+ BUG();
+ } else {
+ /* the real master can respond on its own */
+ response = DLM_MASTER_RESP_NO;
+ }
+ } else if (tmpmle->master != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ set_maybe = 0;
+ if (tmpmle->master == dlm->node_num)
+ response = DLM_MASTER_RESP_YES;
+ else
+ response = DLM_MASTER_RESP_NO;
+ } else {
+ // mlog(0, "this node is attempting to "
+ // "master lockres\n");
+ response = DLM_MASTER_RESP_MAYBE;
+ }
+ if (set_maybe)
+ set_bit(request->node_idx, tmpmle->maybe_map);
+ spin_unlock(&tmpmle->spinlock);
+
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&res->spinlock);
+
+ /* keep the mle attached to heartbeat events */
+ dlm_put_mle(tmpmle);
+ if (mle)
+ kmem_cache_free(dlm_mle_cache, mle);
+ goto send_response;
+ }
+
+ /*
+ * lockres doesn't exist on this node
+ * if there is an MLE_BLOCK, return NO
+ * if there is an MLE_MASTER, return MAYBE
+ * otherwise, add an MLE_BLOCK, return NO
+ */
+ spin_lock(&dlm->master_lock);
+ found = dlm_find_mle(dlm, &tmpmle, name, namelen);
+ if (!found) {
+ /* this lockid has never been seen on this node yet */
+ // mlog(0, "no mle found\n");
+ if (!mle) {
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ mle = (struct dlm_master_list_entry *)
+ kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL);
+ if (!mle) {
+ // bad bad bad... this sucks.
+ response = DLM_MASTER_RESP_ERROR;
+ goto send_response;
+ }
+ spin_lock(&dlm->spinlock);
+ dlm_init_mle(mle, DLM_MLE_BLOCK, dlm, NULL,
+ name, namelen);
+ spin_unlock(&dlm->spinlock);
+ goto way_up_top;
+ }
+
+ // mlog(0, "this is second time thru, already allocated, "
+ // "add the block.\n");
+ set_bit(request->node_idx, mle->maybe_map);
+ list_add(&mle->list, &dlm->master_list);
+ response = DLM_MASTER_RESP_NO;
+ } else {
+ // mlog(0, "mle was found\n");
+ set_maybe = 1;
+ spin_lock(&tmpmle->spinlock);
+ if (tmpmle->type == DLM_MLE_BLOCK)
+ response = DLM_MASTER_RESP_NO;
+ else if (tmpmle->type == DLM_MLE_MIGRATION) {
+ mlog(0, "migration mle was found (%u->%u)\n",
+ tmpmle->master, tmpmle->new_master);
+ if (tmpmle->master == dlm->node_num) {
+ mlog(ML_ERROR, "no lockres, but migration mle "
+ "says that this node is master!\n");
+ BUG();
+ }
+ /* real master can respond on its own */
+ response = DLM_MASTER_RESP_NO;
+ } else {
+ if (tmpmle->master == dlm->node_num) {
+ response = DLM_MASTER_RESP_YES;
+ set_maybe = 0;
+ } else
+ response = DLM_MASTER_RESP_MAYBE;
+ }
+ if (set_maybe)
+ set_bit(request->node_idx, tmpmle->maybe_map);
+ spin_unlock(&tmpmle->spinlock);
+ }
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ if (found) {
+ /* keep the mle attached to heartbeat events */
+ dlm_put_mle(tmpmle);
+ }
+send_response:
+ dlm_put(dlm);
+ return response;
+}
+
+/*
+ * DLM_ASSERT_MASTER_MSG
+ */
+
+
+/*
+ * NOTE: this can be used for debugging
+ * can periodically run all locks owned by this node
+ * and re-assert across the cluster...
+ */
+static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname,
+ unsigned int namelen, void *nodemap,
+ u32 flags)
+{
+ struct dlm_assert_master assert;
+ int to, tmpret;
+ struct dlm_node_iter iter;
+ int ret = 0;
+
+ BUG_ON(namelen > O2NM_MAX_NAME_LEN);
+
+ /* note that if this nodemap is empty, it returns 0 */
+ dlm_node_iter_init(nodemap, &iter);
+ while ((to = dlm_node_iter_next(&iter)) >= 0) {
+ int r = 0;
+ mlog(0, "sending assert master to %d (%.*s)\n", to,
+ namelen, lockname);
+ memset(&assert, 0, sizeof(assert));
+ assert.node_idx = dlm->node_num;
+ assert.namelen = namelen;
+ memcpy(assert.name, lockname, namelen);
+ assert.flags = cpu_to_be32(flags);
+
+ tmpret = o2net_send_message(DLM_ASSERT_MASTER_MSG, dlm->key,
+ &assert, sizeof(assert), to, &r);
+ if (tmpret < 0) {
+ mlog(ML_ERROR, "assert_master returned %d!\n", tmpret);
+ if (!dlm_is_host_down(tmpret)) {
+ mlog(ML_ERROR, "unhandled error!\n");
+ BUG();
+ }
+ /* a node died. finish out the rest of the nodes. */
+ mlog(ML_ERROR, "link to %d went down!\n", to);
+ /* any nonzero status return will do */
+ ret = tmpret;
+ } else if (r < 0) {
+ /* ok, something horribly messed. kill thyself. */
+ mlog(ML_ERROR,"during assert master of %.*s to %u, "
+ "got %d.\n", namelen, lockname, to, r);
+ dlm_dump_lock_resources(dlm);
+ BUG();
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * locks that can be taken here:
+ * dlm->spinlock
+ * res->spinlock
+ * mle->spinlock
+ * dlm->master_list
+ *
+ * if possible, TRIM THIS DOWN!!!
+ */
+int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_master_list_entry *mle = NULL;
+ struct dlm_assert_master *assert = (struct dlm_assert_master *)msg->buf;
+ struct dlm_lock_resource *res = NULL;
+ char *name;
+ unsigned int namelen;
+ u32 flags;
+
+ if (!dlm_grab(dlm))
+ return 0;
+
+ name = assert->name;
+ namelen = assert->namelen;
+ flags = be32_to_cpu(assert->flags);
+
+ if (namelen > DLM_LOCKID_NAME_MAX) {
+ mlog(ML_ERROR, "Invalid name length!");
+ goto done;
+ }
+
+ spin_lock(&dlm->spinlock);
+
+ if (flags)
+ mlog(0, "assert_master with flags: %u\n", flags);
+
+ /* find the MLE */
+ spin_lock(&dlm->master_lock);
+ if (!dlm_find_mle(dlm, &mle, name, namelen)) {
+ /* not an error, could be master just re-asserting */
+ mlog(0, "just got an assert_master from %u, but no "
+ "MLE for it! (%.*s)\n", assert->node_idx,
+ namelen, name);
+ } else {
+ int bit = find_next_bit (mle->maybe_map, O2NM_MAX_NODES, 0);
+ if (bit >= O2NM_MAX_NODES) {
+ /* not necessarily an error, though less likely.
+ * could be master just re-asserting. */
+ mlog(ML_ERROR, "no bits set in the maybe_map, but %u "
+ "is asserting! (%.*s)\n", assert->node_idx,
+ namelen, name);
+ } else if (bit != assert->node_idx) {
+ if (flags & DLM_ASSERT_MASTER_MLE_CLEANUP) {
+ mlog(0, "master %u was found, %u should "
+ "back off\n", assert->node_idx, bit);
+ } else {
+ /* with the fix for bug 569, a higher node
+ * number winning the mastery will respond
+ * YES to mastery requests, but this node
+ * had no way of knowing. let it pass. */
+ mlog(ML_ERROR, "%u is the lowest node, "
+ "%u is asserting. (%.*s) %u must "
+ "have begun after %u won.\n", bit,
+ assert->node_idx, namelen, name, bit,
+ assert->node_idx);
+ }
+ }
+ }
+ spin_unlock(&dlm->master_lock);
+
+ /* ok everything checks out with the MLE
+ * now check to see if there is a lockres */
+ res = __dlm_lookup_lockres(dlm, name, namelen);
+ if (res) {
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ mlog(ML_ERROR, "%u asserting but %.*s is "
+ "RECOVERING!\n", assert->node_idx, namelen, name);
+ goto kill;
+ }
+ if (!mle) {
+ if (res->owner != assert->node_idx) {
+ mlog(ML_ERROR, "assert_master from "
+ "%u, but current owner is "
+ "%u! (%.*s)\n",
+ assert->node_idx, res->owner,
+ namelen, name);
+ goto kill;
+ }
+ } else if (mle->type != DLM_MLE_MIGRATION) {
+ if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* owner is just re-asserting */
+ if (res->owner == assert->node_idx) {
+ mlog(0, "owner %u re-asserting on "
+ "lock %.*s\n", assert->node_idx,
+ namelen, name);
+ goto ok;
+ }
+ mlog(ML_ERROR, "got assert_master from "
+ "node %u, but %u is the owner! "
+ "(%.*s)\n", assert->node_idx,
+ res->owner, namelen, name);
+ goto kill;
+ }
+ if (!(res->state & DLM_LOCK_RES_IN_PROGRESS)) {
+ mlog(ML_ERROR, "got assert from %u, but lock "
+ "with no owner should be "
+ "in-progress! (%.*s)\n",
+ assert->node_idx,
+ namelen, name);
+ goto kill;
+ }
+ } else /* mle->type == DLM_MLE_MIGRATION */ {
+ /* should only be getting an assert from new master */
+ if (assert->node_idx != mle->new_master) {
+ mlog(ML_ERROR, "got assert from %u, but "
+ "new master is %u, and old master "
+ "was %u (%.*s)\n",
+ assert->node_idx, mle->new_master,
+ mle->master, namelen, name);
+ goto kill;
+ }
+
+ }
+ok:
+ spin_unlock(&res->spinlock);
+ }
+ spin_unlock(&dlm->spinlock);
+
+ // mlog(0, "woo! got an assert_master from node %u!\n",
+ // assert->node_idx);
+ if (mle) {
+ int extra_ref;
+
+ spin_lock(&mle->spinlock);
+ extra_ref = !!(mle->type == DLM_MLE_BLOCK
+ || mle->type == DLM_MLE_MIGRATION);
+ mle->master = assert->node_idx;
+ atomic_set(&mle->woken, 1);
+ wake_up(&mle->wq);
+ spin_unlock(&mle->spinlock);
+
+ if (mle->type == DLM_MLE_MIGRATION && res) {
+ mlog(0, "finishing off migration of lockres %.*s, "
+ "from %u to %u\n",
+ res->lockname.len, res->lockname.name,
+ dlm->node_num, mle->new_master);
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_MIGRATING;
+ dlm_change_lockres_owner(dlm, res, mle->new_master);
+ BUG_ON(res->state & DLM_LOCK_RES_DIRTY);
+ spin_unlock(&res->spinlock);
+ }
+ /* master is known, detach if not already detached */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+
+ if (extra_ref) {
+ /* the assert master message now balances the extra
+ * ref given by the master / migration request message.
+ * if this is the last put, it will be removed
+ * from the list. */
+ dlm_put_mle(mle);
+ }
+ }
+
+done:
+ if (res)
+ dlm_lockres_put(res);
+ dlm_put(dlm);
+ return 0;
+
+kill:
+ /* kill the caller! */
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+ dlm_lockres_put(res);
+ mlog(ML_ERROR, "Bad message received from another node. Dumping state "
+ "and killing the other node now! This node is OK and can continue.\n");
+ dlm_dump_lock_resources(dlm);
+ dlm_put(dlm);
+ return -EINVAL;
+}
+
+int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ int ignore_higher, u8 request_from, u32 flags)
+{
+ struct dlm_work_item *item;
+ item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+ if (!item)
+ return -ENOMEM;
+
+
+ /* queue up work for dlm_assert_master_worker */
+ dlm_grab(dlm); /* get an extra ref for the work item */
+ dlm_init_work_item(dlm, item, dlm_assert_master_worker, NULL);
+ item->u.am.lockres = res; /* already have a ref */
+ /* can optionally ignore node numbers higher than this node */
+ item->u.am.ignore_higher = ignore_higher;
+ item->u.am.request_from = request_from;
+ item->u.am.flags = flags;
+
+ spin_lock(&dlm->work_lock);
+ list_add_tail(&item->list, &dlm->work_list);
+ spin_unlock(&dlm->work_lock);
+
+ schedule_work(&dlm->dispatched_work);
+ return 0;
+}
+
+static void dlm_assert_master_worker(struct dlm_work_item *item, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ int ret = 0;
+ struct dlm_lock_resource *res;
+ unsigned long nodemap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+ int ignore_higher;
+ int bit;
+ u8 request_from;
+ u32 flags;
+
+ dlm = item->dlm;
+ res = item->u.am.lockres;
+ ignore_higher = item->u.am.ignore_higher;
+ request_from = item->u.am.request_from;
+ flags = item->u.am.flags;
+
+ spin_lock(&dlm->spinlock);
+ memcpy(nodemap, dlm->domain_map, sizeof(nodemap));
+ spin_unlock(&dlm->spinlock);
+
+ clear_bit(dlm->node_num, nodemap);
+ if (ignore_higher) {
+ /* if is this just to clear up mles for nodes below
+ * this node, do not send the message to the original
+ * caller or any node number higher than this */
+ clear_bit(request_from, nodemap);
+ bit = dlm->node_num;
+ while (1) {
+ bit = find_next_bit(nodemap, O2NM_MAX_NODES,
+ bit+1);
+ if (bit >= O2NM_MAX_NODES)
+ break;
+ clear_bit(bit, nodemap);
+ }
+ }
+
+ /* this call now finishes out the nodemap
+ * even if one or more nodes die */
+ mlog(0, "worker about to master %.*s here, this=%u\n",
+ res->lockname.len, res->lockname.name, dlm->node_num);
+ ret = dlm_do_assert_master(dlm, res->lockname.name,
+ res->lockname.len,
+ nodemap, flags);
+ if (ret < 0) {
+ /* no need to restart, we are done */
+ mlog_errno(ret);
+ }
+
+ dlm_lockres_put(res);
+
+ mlog(0, "finished with dlm_assert_master_worker\n");
+}
+
+
+/*
+ * DLM_MIGRATE_LOCKRES
+ */
+
+
+int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ u8 target)
+{
+ struct dlm_master_list_entry *mle = NULL;
+ struct dlm_master_list_entry *oldmle = NULL;
+ struct dlm_migratable_lockres *mres = NULL;
+ int ret = -EINVAL;
+ const char *name;
+ unsigned int namelen;
+ int mle_added = 0;
+ struct list_head *queue, *iter;
+ int i;
+ struct dlm_lock *lock;
+ int empty = 1;
+
+ if (!dlm_grab(dlm))
+ return -EINVAL;
+
+ name = res->lockname.name;
+ namelen = res->lockname.len;
+
+ mlog(0, "migrating %.*s to %u\n", namelen, name, target);
+
+ /*
+ * ensure this lockres is a proper candidate for migration
+ */
+ spin_lock(&res->spinlock);
+ if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "cannot migrate lockres with unknown owner!\n");
+ spin_unlock(&res->spinlock);
+ goto leave;
+ }
+ if (res->owner != dlm->node_num) {
+ mlog(0, "cannot migrate lockres this node doesn't own!\n");
+ spin_unlock(&res->spinlock);
+ goto leave;
+ }
+ mlog(0, "checking queues...\n");
+ queue = &res->granted;
+ for (i=0; i<3; i++) {
+ list_for_each(iter, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ empty = 0;
+ if (lock->ml.node == dlm->node_num) {
+ mlog(0, "found a lock owned by this node "
+ "still on the %s queue! will not "
+ "migrate this lockres\n",
+ i==0 ? "granted" :
+ (i==1 ? "converting" : "blocked"));
+ spin_unlock(&res->spinlock);
+ ret = -ENOTEMPTY;
+ goto leave;
+ }
+ }
+ queue++;
+ }
+ mlog(0, "all locks on this lockres are nonlocal. continuing\n");
+ spin_unlock(&res->spinlock);
+
+ /* no work to do */
+ if (empty) {
+ mlog(0, "no locks were found on this lockres! done!\n");
+ ret = 0;
+ goto leave;
+ }
+
+ /*
+ * preallocate up front
+ * if this fails, abort
+ */
+
+ ret = -ENOMEM;
+ mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_KERNEL);
+ if (!mres) {
+ mlog_errno(ret);
+ goto leave;
+ }
+
+ mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache,
+ GFP_KERNEL);
+ if (!mle) {
+ mlog_errno(ret);
+ goto leave;
+ }
+ ret = 0;
+
+ /*
+ * find a node to migrate the lockres to
+ */
+
+ mlog(0, "picking a migration node\n");
+ spin_lock(&dlm->spinlock);
+ /* pick a new node */
+ if (!test_bit(target, dlm->domain_map) ||
+ target >= O2NM_MAX_NODES) {
+ target = dlm_pick_migration_target(dlm, res);
+ }
+ mlog(0, "node %u chosen for migration\n", target);
+
+ if (target >= O2NM_MAX_NODES ||
+ !test_bit(target, dlm->domain_map)) {
+ /* target chosen is not alive */
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ spin_unlock(&dlm->spinlock);
+ goto fail;
+ }
+
+ mlog(0, "continuing with target = %u\n", target);
+
+ /*
+ * clear any existing master requests and
+ * add the migration mle to the list
+ */
+ spin_lock(&dlm->master_lock);
+ ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
+ namelen, target, dlm->node_num);
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ if (ret == -EEXIST) {
+ mlog(0, "another process is already migrating it\n");
+ goto fail;
+ }
+ mle_added = 1;
+
+ /*
+ * set the MIGRATING flag and flush asts
+ * if we fail after this we need to re-dirty the lockres
+ */
+ if (dlm_mark_lockres_migrating(dlm, res, target) < 0) {
+ mlog(ML_ERROR, "tried to migrate %.*s to %u, but "
+ "the target went down.\n", res->lockname.len,
+ res->lockname.name, target);
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_MIGRATING;
+ spin_unlock(&res->spinlock);
+ ret = -EINVAL;
+ }
+
+fail:
+ if (oldmle) {
+ /* master is known, detach if not already detached */
+ dlm_mle_detach_hb_events(dlm, oldmle);
+ dlm_put_mle(oldmle);
+ }
+
+ if (ret < 0) {
+ if (mle_added) {
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ } else if (mle) {
+ kmem_cache_free(dlm_mle_cache, mle);
+ }
+ goto leave;
+ }
+
+ /*
+ * at this point, we have a migration target, an mle
+ * in the master list, and the MIGRATING flag set on
+ * the lockres
+ */
+
+
+ /* get an extra reference on the mle.
+ * otherwise the assert_master from the new
+ * master will destroy this.
+ * also, make sure that all callers of dlm_get_mle
+ * take both dlm->spinlock and dlm->master_lock */
+ spin_lock(&dlm->spinlock);
+ spin_lock(&dlm->master_lock);
+ dlm_get_mle(mle);
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ /* notify new node and send all lock state */
+ /* call send_one_lockres with migration flag.
+ * this serves as notice to the target node that a
+ * migration is starting. */
+ ret = dlm_send_one_lockres(dlm, res, mres, target,
+ DLM_MRES_MIGRATION);
+
+ if (ret < 0) {
+ mlog(0, "migration to node %u failed with %d\n",
+ target, ret);
+ /* migration failed, detach and clean up mle */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ dlm_put_mle(mle);
+ goto leave;
+ }
+
+ /* at this point, the target sends a message to all nodes,
+ * (using dlm_do_migrate_request). this node is skipped since
+ * we had to put an mle in the list to begin the process. this
+ * node now waits for target to do an assert master. this node
+ * will be the last one notified, ensuring that the migration
+ * is complete everywhere. if the target dies while this is
+ * going on, some nodes could potentially see the target as the
+ * master, so it is important that my recovery finds the migration
+ * mle and sets the master to UNKNONWN. */
+
+
+ /* wait for new node to assert master */
+ while (1) {
+ ret = wait_event_interruptible_timeout(mle->wq,
+ (atomic_read(&mle->woken) == 1),
+ msecs_to_jiffies(5000));
+
+ if (ret >= 0) {
+ if (atomic_read(&mle->woken) == 1 ||
+ res->owner == target)
+ break;
+
+ mlog(0, "timed out during migration\n");
+ }
+ if (ret == -ERESTARTSYS) {
+ /* migration failed, detach and clean up mle */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ dlm_put_mle(mle);
+ goto leave;
+ }
+ /* TODO: if node died: stop, clean up, return error */
+ }
+
+ /* all done, set the owner, clear the flag */
+ spin_lock(&res->spinlock);
+ dlm_set_lockres_owner(dlm, res, target);
+ res->state &= ~DLM_LOCK_RES_MIGRATING;
+ dlm_remove_nonlocal_locks(dlm, res);
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+
+ /* master is known, detach if not already detached */
+ dlm_mle_detach_hb_events(dlm, mle);
+ dlm_put_mle(mle);
+ ret = 0;
+
+ dlm_lockres_calc_usage(dlm, res);
+
+leave:
+ /* re-dirty the lockres if we failed */
+ if (ret < 0)
+ dlm_kick_thread(dlm, res);
+
+ /* TODO: cleanup */
+ if (mres)
+ free_page((unsigned long)mres);
+
+ dlm_put(dlm);
+
+ mlog(0, "returning %d\n", ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dlm_migrate_lockres);
+
+int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock)
+{
+ int ret;
+ spin_lock(&dlm->ast_lock);
+ spin_lock(&lock->spinlock);
+ ret = (list_empty(&lock->bast_list) && !lock->bast_pending);
+ spin_unlock(&lock->spinlock);
+ spin_unlock(&dlm->ast_lock);
+ return ret;
+}
+
+static int dlm_migration_can_proceed(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 mig_target)
+{
+ int can_proceed;
+ spin_lock(&res->spinlock);
+ can_proceed = !!(res->state & DLM_LOCK_RES_MIGRATING);
+ spin_unlock(&res->spinlock);
+
+ /* target has died, so make the caller break out of the
+ * wait_event, but caller must recheck the domain_map */
+ spin_lock(&dlm->spinlock);
+ if (!test_bit(mig_target, dlm->domain_map))
+ can_proceed = 1;
+ spin_unlock(&dlm->spinlock);
+ return can_proceed;
+}
+
+int dlm_lockres_is_dirty(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
+{
+ int ret;
+ spin_lock(&res->spinlock);
+ ret = !!(res->state & DLM_LOCK_RES_DIRTY);
+ spin_unlock(&res->spinlock);
+ return ret;
+}
+
+
+static int dlm_mark_lockres_migrating(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 target)
+{
+ int ret = 0;
+
+ mlog(0, "dlm_mark_lockres_migrating: %.*s, from %u to %u\n",
+ res->lockname.len, res->lockname.name, dlm->node_num,
+ target);
+ /* need to set MIGRATING flag on lockres. this is done by
+ * ensuring that all asts have been flushed for this lockres. */
+ spin_lock(&res->spinlock);
+ BUG_ON(res->migration_pending);
+ res->migration_pending = 1;
+ /* strategy is to reserve an extra ast then release
+ * it below, letting the release do all of the work */
+ __dlm_lockres_reserve_ast(res);
+ spin_unlock(&res->spinlock);
+
+ /* now flush all the pending asts.. hang out for a bit */
+ dlm_kick_thread(dlm, res);
+ wait_event(dlm->ast_wq, !dlm_lockres_is_dirty(dlm, res));
+ dlm_lockres_release_ast(dlm, res);
+
+ mlog(0, "about to wait on migration_wq, dirty=%s\n",
+ res->state & DLM_LOCK_RES_DIRTY ? "yes" : "no");
+ /* if the extra ref we just put was the final one, this
+ * will pass thru immediately. otherwise, we need to wait
+ * for the last ast to finish. */
+again:
+ ret = wait_event_interruptible_timeout(dlm->migration_wq,
+ dlm_migration_can_proceed(dlm, res, target),
+ msecs_to_jiffies(1000));
+ if (ret < 0) {
+ mlog(0, "woken again: migrating? %s, dead? %s\n",
+ res->state & DLM_LOCK_RES_MIGRATING ? "yes":"no",
+ test_bit(target, dlm->domain_map) ? "no":"yes");
+ } else {
+ mlog(0, "all is well: migrating? %s, dead? %s\n",
+ res->state & DLM_LOCK_RES_MIGRATING ? "yes":"no",
+ test_bit(target, dlm->domain_map) ? "no":"yes");
+ }
+ if (!dlm_migration_can_proceed(dlm, res, target)) {
+ mlog(0, "trying again...\n");
+ goto again;
+ }
+
+ /* did the target go down or die? */
+ spin_lock(&dlm->spinlock);
+ if (!test_bit(target, dlm->domain_map)) {
+ mlog(ML_ERROR, "aha. migration target %u just went down\n",
+ target);
+ ret = -EHOSTDOWN;
+ }
+ spin_unlock(&dlm->spinlock);
+
+ /*
+ * at this point:
+ *
+ * o the DLM_LOCK_RES_MIGRATING flag is set
+ * o there are no pending asts on this lockres
+ * o all processes trying to reserve an ast on this
+ * lockres must wait for the MIGRATING flag to clear
+ */
+ return ret;
+}
+
+/* last step in the migration process.
+ * original master calls this to free all of the dlm_lock
+ * structures that used to be for other nodes. */
+static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ struct list_head *iter, *iter2;
+ struct list_head *queue = &res->granted;
+ int i;
+ struct dlm_lock *lock;
+
+ assert_spin_locked(&res->spinlock);
+
+ BUG_ON(res->owner == dlm->node_num);
+
+ for (i=0; i<3; i++) {
+ list_for_each_safe(iter, iter2, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node != dlm->node_num) {
+ mlog(0, "putting lock for node %u\n",
+ lock->ml.node);
+ /* be extra careful */
+ BUG_ON(!list_empty(&lock->ast_list));
+ BUG_ON(!list_empty(&lock->bast_list));
+ BUG_ON(lock->ast_pending);
+ BUG_ON(lock->bast_pending);
+ list_del_init(&lock->list);
+ dlm_lock_put(lock);
+ }
+ }
+ queue++;
+ }
+}
+
+/* for now this is not too intelligent. we will
+ * need stats to make this do the right thing.
+ * this just finds the first lock on one of the
+ * queues and uses that node as the target. */
+static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ int i;
+ struct list_head *queue = &res->granted;
+ struct list_head *iter;
+ struct dlm_lock *lock;
+ int nodenum;
+
+ assert_spin_locked(&dlm->spinlock);
+
+ spin_lock(&res->spinlock);
+ for (i=0; i<3; i++) {
+ list_for_each(iter, queue) {
+ /* up to the caller to make sure this node
+ * is alive */
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node != dlm->node_num) {
+ spin_unlock(&res->spinlock);
+ return lock->ml.node;
+ }
+ }
+ queue++;
+ }
+ spin_unlock(&res->spinlock);
+ mlog(0, "have not found a suitable target yet! checking domain map\n");
+
+ /* ok now we're getting desperate. pick anyone alive. */
+ nodenum = -1;
+ while (1) {
+ nodenum = find_next_bit(dlm->domain_map,
+ O2NM_MAX_NODES, nodenum+1);
+ mlog(0, "found %d in domain map\n", nodenum);
+ if (nodenum >= O2NM_MAX_NODES)
+ break;
+ if (nodenum != dlm->node_num) {
+ mlog(0, "picking %d\n", nodenum);
+ return nodenum;
+ }
+ }
+
+ mlog(0, "giving up. no master to migrate to\n");
+ return DLM_LOCK_RES_OWNER_UNKNOWN;
+}
+
+
+
+/* this is called by the new master once all lockres
+ * data has been received */
+static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 master, u8 new_master,
+ struct dlm_node_iter *iter)
+{
+ struct dlm_migrate_request migrate;
+ int ret, status = 0;
+ int nodenum;
+
+ memset(&migrate, 0, sizeof(migrate));
+ migrate.namelen = res->lockname.len;
+ memcpy(migrate.name, res->lockname.name, migrate.namelen);
+ migrate.new_master = new_master;
+ migrate.master = master;
+
+ ret = 0;
+
+ /* send message to all nodes, except the master and myself */
+ while ((nodenum = dlm_node_iter_next(iter)) >= 0) {
+ if (nodenum == master ||
+ nodenum == new_master)
+ continue;
+
+ ret = o2net_send_message(DLM_MIGRATE_REQUEST_MSG, dlm->key,
+ &migrate, sizeof(migrate), nodenum,
+ &status);
+ if (ret < 0)
+ mlog_errno(ret);
+ else if (status < 0) {
+ mlog(0, "migrate request (node %u) returned %d!\n",
+ nodenum, status);
+ ret = status;
+ }
+ }
+
+ if (ret < 0)
+ mlog_errno(ret);
+
+ mlog(0, "returning ret=%d\n", ret);
+ return ret;
+}
+
+
+/* if there is an existing mle for this lockres, we now know who the master is.
+ * (the one who sent us *this* message) we can clear it up right away.
+ * since the process that put the mle on the list still has a reference to it,
+ * we can unhash it now, set the master and wake the process. as a result,
+ * we will have no mle in the list to start with. now we can add an mle for
+ * the migration and this should be the only one found for those scanning the
+ * list. */
+int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_lock_resource *res = NULL;
+ struct dlm_migrate_request *migrate = (struct dlm_migrate_request *) msg->buf;
+ struct dlm_master_list_entry *mle = NULL, *oldmle = NULL;
+ const char *name;
+ unsigned int namelen;
+ int ret = 0;
+
+ if (!dlm_grab(dlm))
+ return -EINVAL;
+
+ name = migrate->name;
+ namelen = migrate->namelen;
+
+ /* preallocate.. if this fails, abort */
+ mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache,
+ GFP_KERNEL);
+
+ if (!mle) {
+ ret = -ENOMEM;
+ goto leave;
+ }
+
+ /* check for pre-existing lock */
+ spin_lock(&dlm->spinlock);
+ res = __dlm_lookup_lockres(dlm, name, namelen);
+ spin_lock(&dlm->master_lock);
+
+ if (res) {
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ /* if all is working ok, this can only mean that we got
+ * a migrate request from a node that we now see as
+ * dead. what can we do here? drop it to the floor? */
+ spin_unlock(&res->spinlock);
+ mlog(ML_ERROR, "Got a migrate request, but the "
+ "lockres is marked as recovering!");
+ kmem_cache_free(dlm_mle_cache, mle);
+ ret = -EINVAL; /* need a better solution */
+ goto unlock;
+ }
+ res->state |= DLM_LOCK_RES_MIGRATING;
+ spin_unlock(&res->spinlock);
+ }
+
+ /* ignore status. only nonzero status would BUG. */
+ ret = dlm_add_migration_mle(dlm, res, mle, &oldmle,
+ name, namelen,
+ migrate->new_master,
+ migrate->master);
+
+unlock:
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ if (oldmle) {
+ /* master is known, detach if not already detached */
+ dlm_mle_detach_hb_events(dlm, oldmle);
+ dlm_put_mle(oldmle);
+ }
+
+ if (res)
+ dlm_lockres_put(res);
+leave:
+ dlm_put(dlm);
+ return ret;
+}
+
+/* must be holding dlm->spinlock and dlm->master_lock
+ * when adding a migration mle, we can clear any other mles
+ * in the master list because we know with certainty that
+ * the master is "master". so we remove any old mle from
+ * the list after setting it's master field, and then add
+ * the new migration mle. this way we can hold with the rule
+ * of having only one mle for a given lock name at all times. */
+static int dlm_add_migration_mle(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_master_list_entry *mle,
+ struct dlm_master_list_entry **oldmle,
+ const char *name, unsigned int namelen,
+ u8 new_master, u8 master)
+{
+ int found;
+ int ret = 0;
+
+ *oldmle = NULL;
+
+ mlog_entry_void();
+
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&dlm->master_lock);
+
+ /* caller is responsible for any ref taken here on oldmle */
+ found = dlm_find_mle(dlm, oldmle, (char *)name, namelen);
+ if (found) {
+ struct dlm_master_list_entry *tmp = *oldmle;
+ spin_lock(&tmp->spinlock);
+ if (tmp->type == DLM_MLE_MIGRATION) {
+ if (master == dlm->node_num) {
+ /* ah another process raced me to it */
+ mlog(0, "tried to migrate %.*s, but some "
+ "process beat me to it\n",
+ namelen, name);
+ ret = -EEXIST;
+ } else {
+ /* bad. 2 NODES are trying to migrate! */
+ mlog(ML_ERROR, "migration error mle: "
+ "master=%u new_master=%u // request: "
+ "master=%u new_master=%u // "
+ "lockres=%.*s\n",
+ tmp->master, tmp->new_master,
+ master, new_master,
+ namelen, name);
+ BUG();
+ }
+ } else {
+ /* this is essentially what assert_master does */
+ tmp->master = master;
+ atomic_set(&tmp->woken, 1);
+ wake_up(&tmp->wq);
+ /* remove it from the list so that only one
+ * mle will be found */
+ list_del_init(&tmp->list);
+ }
+ spin_unlock(&tmp->spinlock);
+ }
+
+ /* now add a migration mle to the tail of the list */
+ dlm_init_mle(mle, DLM_MLE_MIGRATION, dlm, res, name, namelen);
+ mle->new_master = new_master;
+ mle->master = master;
+ /* do this for consistency with other mle types */
+ set_bit(new_master, mle->maybe_map);
+ list_add(&mle->list, &dlm->master_list);
+
+ return ret;
+}
+
+
+void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ struct list_head *iter, *iter2;
+ struct dlm_master_list_entry *mle;
+ struct dlm_lock_resource *res;
+
+ mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node);
+top:
+ assert_spin_locked(&dlm->spinlock);
+
+ /* clean the master list */
+ spin_lock(&dlm->master_lock);
+ list_for_each_safe(iter, iter2, &dlm->master_list) {
+ mle = list_entry(iter, struct dlm_master_list_entry, list);
+
+ BUG_ON(mle->type != DLM_MLE_BLOCK &&
+ mle->type != DLM_MLE_MASTER &&
+ mle->type != DLM_MLE_MIGRATION);
+
+ /* MASTER mles are initiated locally. the waiting
+ * process will notice the node map change
+ * shortly. let that happen as normal. */
+ if (mle->type == DLM_MLE_MASTER)
+ continue;
+
+
+ /* BLOCK mles are initiated by other nodes.
+ * need to clean up if the dead node would have
+ * been the master. */
+ if (mle->type == DLM_MLE_BLOCK) {
+ int bit;
+
+ spin_lock(&mle->spinlock);
+ bit = find_next_bit(mle->maybe_map, O2NM_MAX_NODES, 0);
+ if (bit != dead_node) {
+ mlog(0, "mle found, but dead node %u would "
+ "not have been master\n", dead_node);
+ spin_unlock(&mle->spinlock);
+ } else {
+ /* must drop the refcount by one since the
+ * assert_master will never arrive. this
+ * may result in the mle being unlinked and
+ * freed, but there may still be a process
+ * waiting in the dlmlock path which is fine. */
+ mlog(ML_ERROR, "node %u was expected master\n",
+ dead_node);
+ atomic_set(&mle->woken, 1);
+ spin_unlock(&mle->spinlock);
+ wake_up(&mle->wq);
+ /* final put will take care of list removal */
+ __dlm_put_mle(mle);
+ }
+ continue;
+ }
+
+ /* everything else is a MIGRATION mle */
+
+ /* the rule for MIGRATION mles is that the master
+ * becomes UNKNOWN if *either* the original or
+ * the new master dies. all UNKNOWN lockreses
+ * are sent to whichever node becomes the recovery
+ * master. the new master is responsible for
+ * determining if there is still a master for
+ * this lockres, or if he needs to take over
+ * mastery. either way, this node should expect
+ * another message to resolve this. */
+ if (mle->master != dead_node &&
+ mle->new_master != dead_node)
+ continue;
+
+ /* if we have reached this point, this mle needs to
+ * be removed from the list and freed. */
+
+ /* remove from the list early. NOTE: unlinking
+ * list_head while in list_for_each_safe */
+ spin_lock(&mle->spinlock);
+ list_del_init(&mle->list);
+ atomic_set(&mle->woken, 1);
+ spin_unlock(&mle->spinlock);
+ wake_up(&mle->wq);
+
+ mlog(0, "node %u died during migration from "
+ "%u to %u!\n", dead_node,
+ mle->master, mle->new_master);
+ /* if there is a lockres associated with this
+ * mle, find it and set its owner to UNKNOWN */
+ res = __dlm_lookup_lockres(dlm, mle->u.name.name,
+ mle->u.name.len);
+ if (res) {
+ /* unfortunately if we hit this rare case, our
+ * lock ordering is messed. we need to drop
+ * the master lock so that we can take the
+ * lockres lock, meaning that we will have to
+ * restart from the head of list. */
+ spin_unlock(&dlm->master_lock);
+
+ /* move lockres onto recovery list */
+ spin_lock(&res->spinlock);
+ dlm_set_lockres_owner(dlm, res,
+ DLM_LOCK_RES_OWNER_UNKNOWN);
+ dlm_move_lockres_to_recovery_list(dlm, res);
+ spin_unlock(&res->spinlock);
+ dlm_lockres_put(res);
+
+ /* dump the mle */
+ spin_lock(&dlm->master_lock);
+ __dlm_put_mle(mle);
+ spin_unlock(&dlm->master_lock);
+
+ /* restart */
+ goto top;
+ }
+
+ /* this may be the last reference */
+ __dlm_put_mle(mle);
+ }
+ spin_unlock(&dlm->master_lock);
+}
+
+
+int dlm_finish_migration(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ u8 old_master)
+{
+ struct dlm_node_iter iter;
+ int ret = 0;
+
+ spin_lock(&dlm->spinlock);
+ dlm_node_iter_init(dlm->domain_map, &iter);
+ clear_bit(old_master, iter.node_map);
+ clear_bit(dlm->node_num, iter.node_map);
+ spin_unlock(&dlm->spinlock);
+
+ mlog(0, "now time to do a migrate request to other nodes\n");
+ ret = dlm_do_migrate_request(dlm, res, old_master,
+ dlm->node_num, &iter);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto leave;
+ }
+
+ mlog(0, "doing assert master of %.*s to all except the original node\n",
+ res->lockname.len, res->lockname.name);
+ /* this call now finishes out the nodemap
+ * even if one or more nodes die */
+ ret = dlm_do_assert_master(dlm, res->lockname.name,
+ res->lockname.len, iter.node_map,
+ DLM_ASSERT_MASTER_FINISH_MIGRATION);
+ if (ret < 0) {
+ /* no longer need to retry. all living nodes contacted. */
+ mlog_errno(ret);
+ ret = 0;
+ }
+
+ memset(iter.node_map, 0, sizeof(iter.node_map));
+ set_bit(old_master, iter.node_map);
+ mlog(0, "doing assert master of %.*s back to %u\n",
+ res->lockname.len, res->lockname.name, old_master);
+ ret = dlm_do_assert_master(dlm, res->lockname.name,
+ res->lockname.len, iter.node_map,
+ DLM_ASSERT_MASTER_FINISH_MIGRATION);
+ if (ret < 0) {
+ mlog(0, "assert master to original master failed "
+ "with %d.\n", ret);
+ /* the only nonzero status here would be because of
+ * a dead original node. we're done. */
+ ret = 0;
+ }
+
+ /* all done, set the owner, clear the flag */
+ spin_lock(&res->spinlock);
+ dlm_set_lockres_owner(dlm, res, dlm->node_num);
+ res->state &= ~DLM_LOCK_RES_MIGRATING;
+ spin_unlock(&res->spinlock);
+ /* re-dirty it on the new master */
+ dlm_kick_thread(dlm, res);
+ wake_up(&res->wq);
+leave:
+ return ret;
+}
+
+/*
+ * LOCKRES AST REFCOUNT
+ * this is integral to migration
+ */
+
+/* for future intent to call an ast, reserve one ahead of time.
+ * this should be called only after waiting on the lockres
+ * with dlm_wait_on_lockres, and while still holding the
+ * spinlock after the call. */
+void __dlm_lockres_reserve_ast(struct dlm_lock_resource *res)
+{
+ assert_spin_locked(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_MIGRATING) {
+ __dlm_print_one_lock_resource(res);
+ }
+ BUG_ON(res->state & DLM_LOCK_RES_MIGRATING);
+
+ atomic_inc(&res->asts_reserved);
+}
+
+/*
+ * used to drop the reserved ast, either because it went unused,
+ * or because the ast/bast was actually called.
+ *
+ * also, if there is a pending migration on this lockres,
+ * and this was the last pending ast on the lockres,
+ * atomically set the MIGRATING flag before we drop the lock.
+ * this is how we ensure that migration can proceed with no
+ * asts in progress. note that it is ok if the state of the
+ * queues is such that a lock should be granted in the future
+ * or that a bast should be fired, because the new master will
+ * shuffle the lists on this lockres as soon as it is migrated.
+ */
+void dlm_lockres_release_ast(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ if (!atomic_dec_and_lock(&res->asts_reserved, &res->spinlock))
+ return;
+
+ if (!res->migration_pending) {
+ spin_unlock(&res->spinlock);
+ return;
+ }
+
+ BUG_ON(res->state & DLM_LOCK_RES_MIGRATING);
+ res->migration_pending = 0;
+ res->state |= DLM_LOCK_RES_MIGRATING;
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+ wake_up(&dlm->migration_wq);
+}
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
new file mode 100644
index 000000000000..0c8eb1093f00
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -0,0 +1,2132 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmrecovery.c
+ *
+ * recovery stuff
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/timer.h>
+#include <linux/kthread.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+#include "dlmdomain.h"
+
+#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_RECOVERY)
+#include "cluster/masklog.h"
+
+static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node);
+
+static int dlm_recovery_thread(void *data);
+void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
+int dlm_launch_recovery_thread(struct dlm_ctxt *dlm);
+static void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
+static int dlm_do_recovery(struct dlm_ctxt *dlm);
+
+static int dlm_pick_recovery_master(struct dlm_ctxt *dlm);
+static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node);
+static int dlm_init_recovery_area(struct dlm_ctxt *dlm, u8 dead_node);
+static int dlm_request_all_locks(struct dlm_ctxt *dlm,
+ u8 request_from, u8 dead_node);
+static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node);
+
+static inline int dlm_num_locks_in_lockres(struct dlm_lock_resource *res);
+static void dlm_init_migratable_lockres(struct dlm_migratable_lockres *mres,
+ const char *lockname, int namelen,
+ int total_locks, u64 cookie,
+ u8 flags, u8 master);
+static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
+ struct dlm_migratable_lockres *mres,
+ u8 send_to,
+ struct dlm_lock_resource *res,
+ int total_locks);
+static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 *real_master);
+static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_migratable_lockres *mres);
+static int dlm_do_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 nodenum, u8 *real_master);
+static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm);
+static int dlm_send_all_done_msg(struct dlm_ctxt *dlm,
+ u8 dead_node, u8 send_to);
+static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node);
+static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm,
+ struct list_head *list, u8 dead_node);
+static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
+ u8 dead_node, u8 new_master);
+static void dlm_reco_ast(void *astdata);
+static void dlm_reco_bast(void *astdata, int blocked_type);
+static void dlm_reco_unlock_ast(void *astdata, enum dlm_status st);
+static void dlm_request_all_locks_worker(struct dlm_work_item *item,
+ void *data);
+static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data);
+
+static u64 dlm_get_next_mig_cookie(void);
+
+static spinlock_t dlm_reco_state_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t dlm_mig_cookie_lock = SPIN_LOCK_UNLOCKED;
+static u64 dlm_mig_cookie = 1;
+
+static u64 dlm_get_next_mig_cookie(void)
+{
+ u64 c;
+ spin_lock(&dlm_mig_cookie_lock);
+ c = dlm_mig_cookie;
+ if (dlm_mig_cookie == (~0ULL))
+ dlm_mig_cookie = 1;
+ else
+ dlm_mig_cookie++;
+ spin_unlock(&dlm_mig_cookie_lock);
+ return c;
+}
+
+static inline void dlm_reset_recovery(struct dlm_ctxt *dlm)
+{
+ spin_lock(&dlm->spinlock);
+ clear_bit(dlm->reco.dead_node, dlm->recovery_map);
+ dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+ dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
+ spin_unlock(&dlm->spinlock);
+}
+
+/* Worker function used during recovery. */
+void dlm_dispatch_work(void *data)
+{
+ struct dlm_ctxt *dlm = (struct dlm_ctxt *)data;
+ LIST_HEAD(tmp_list);
+ struct list_head *iter, *iter2;
+ struct dlm_work_item *item;
+ dlm_workfunc_t *workfunc;
+
+ spin_lock(&dlm->work_lock);
+ list_splice_init(&dlm->work_list, &tmp_list);
+ spin_unlock(&dlm->work_lock);
+
+ list_for_each_safe(iter, iter2, &tmp_list) {
+ item = list_entry(iter, struct dlm_work_item, list);
+ workfunc = item->func;
+ list_del_init(&item->list);
+
+ /* already have ref on dlm to avoid having
+ * it disappear. just double-check. */
+ BUG_ON(item->dlm != dlm);
+
+ /* this is allowed to sleep and
+ * call network stuff */
+ workfunc(item, item->data);
+
+ dlm_put(dlm);
+ kfree(item);
+ }
+}
+
+/*
+ * RECOVERY THREAD
+ */
+
+static void dlm_kick_recovery_thread(struct dlm_ctxt *dlm)
+{
+ /* wake the recovery thread
+ * this will wake the reco thread in one of three places
+ * 1) sleeping with no recovery happening
+ * 2) sleeping with recovery mastered elsewhere
+ * 3) recovery mastered here, waiting on reco data */
+
+ wake_up(&dlm->dlm_reco_thread_wq);
+}
+
+/* Launch the recovery thread */
+int dlm_launch_recovery_thread(struct dlm_ctxt *dlm)
+{
+ mlog(0, "starting dlm recovery thread...\n");
+
+ dlm->dlm_reco_thread_task = kthread_run(dlm_recovery_thread, dlm,
+ "dlm_reco_thread");
+ if (IS_ERR(dlm->dlm_reco_thread_task)) {
+ mlog_errno(PTR_ERR(dlm->dlm_reco_thread_task));
+ dlm->dlm_reco_thread_task = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void dlm_complete_recovery_thread(struct dlm_ctxt *dlm)
+{
+ if (dlm->dlm_reco_thread_task) {
+ mlog(0, "waiting for dlm recovery thread to exit\n");
+ kthread_stop(dlm->dlm_reco_thread_task);
+ dlm->dlm_reco_thread_task = NULL;
+ }
+}
+
+
+
+/*
+ * this is lame, but here's how recovery works...
+ * 1) all recovery threads cluster wide will work on recovering
+ * ONE node at a time
+ * 2) negotiate who will take over all the locks for the dead node.
+ * thats right... ALL the locks.
+ * 3) once a new master is chosen, everyone scans all locks
+ * and moves aside those mastered by the dead guy
+ * 4) each of these locks should be locked until recovery is done
+ * 5) the new master collects up all of secondary lock queue info
+ * one lock at a time, forcing each node to communicate back
+ * before continuing
+ * 6) each secondary lock queue responds with the full known lock info
+ * 7) once the new master has run all its locks, it sends a ALLDONE!
+ * message to everyone
+ * 8) upon receiving this message, the secondary queue node unlocks
+ * and responds to the ALLDONE
+ * 9) once the new master gets responses from everyone, he unlocks
+ * everything and recovery for this dead node is done
+ *10) go back to 2) while there are still dead nodes
+ *
+ */
+
+
+#define DLM_RECO_THREAD_TIMEOUT_MS (5 * 1000)
+
+static int dlm_recovery_thread(void *data)
+{
+ int status;
+ struct dlm_ctxt *dlm = data;
+ unsigned long timeout = msecs_to_jiffies(DLM_RECO_THREAD_TIMEOUT_MS);
+
+ mlog(0, "dlm thread running for %s...\n", dlm->name);
+
+ while (!kthread_should_stop()) {
+ if (dlm_joined(dlm)) {
+ status = dlm_do_recovery(dlm);
+ if (status == -EAGAIN) {
+ /* do not sleep, recheck immediately. */
+ continue;
+ }
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+ wait_event_interruptible_timeout(dlm->dlm_reco_thread_wq,
+ kthread_should_stop(),
+ timeout);
+ }
+
+ mlog(0, "quitting DLM recovery thread\n");
+ return 0;
+}
+
+/* callers of the top-level api calls (dlmlock/dlmunlock) should
+ * block on the dlm->reco.event when recovery is in progress.
+ * the dlm recovery thread will set this state when it begins
+ * recovering a dead node (as the new master or not) and clear
+ * the state and wake as soon as all affected lock resources have
+ * been marked with the RECOVERY flag */
+static int dlm_in_recovery(struct dlm_ctxt *dlm)
+{
+ int in_recovery;
+ spin_lock(&dlm->spinlock);
+ in_recovery = !!(dlm->reco.state & DLM_RECO_STATE_ACTIVE);
+ spin_unlock(&dlm->spinlock);
+ return in_recovery;
+}
+
+
+void dlm_wait_for_recovery(struct dlm_ctxt *dlm)
+{
+ wait_event(dlm->reco.event, !dlm_in_recovery(dlm));
+}
+
+static void dlm_begin_recovery(struct dlm_ctxt *dlm)
+{
+ spin_lock(&dlm->spinlock);
+ BUG_ON(dlm->reco.state & DLM_RECO_STATE_ACTIVE);
+ dlm->reco.state |= DLM_RECO_STATE_ACTIVE;
+ spin_unlock(&dlm->spinlock);
+}
+
+static void dlm_end_recovery(struct dlm_ctxt *dlm)
+{
+ spin_lock(&dlm->spinlock);
+ BUG_ON(!(dlm->reco.state & DLM_RECO_STATE_ACTIVE));
+ dlm->reco.state &= ~DLM_RECO_STATE_ACTIVE;
+ spin_unlock(&dlm->spinlock);
+ wake_up(&dlm->reco.event);
+}
+
+static int dlm_do_recovery(struct dlm_ctxt *dlm)
+{
+ int status = 0;
+
+ spin_lock(&dlm->spinlock);
+
+ /* check to see if the new master has died */
+ if (dlm->reco.new_master != O2NM_INVALID_NODE_NUM &&
+ test_bit(dlm->reco.new_master, dlm->recovery_map)) {
+ mlog(0, "new master %u died while recovering %u!\n",
+ dlm->reco.new_master, dlm->reco.dead_node);
+ /* unset the new_master, leave dead_node */
+ dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
+ }
+
+ /* select a target to recover */
+ if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) {
+ int bit;
+
+ bit = find_next_bit (dlm->recovery_map, O2NM_MAX_NODES+1, 0);
+ if (bit >= O2NM_MAX_NODES || bit < 0)
+ dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+ else
+ dlm->reco.dead_node = bit;
+ } else if (!test_bit(dlm->reco.dead_node, dlm->recovery_map)) {
+ /* BUG? */
+ mlog(ML_ERROR, "dead_node %u no longer in recovery map!\n",
+ dlm->reco.dead_node);
+ dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+ }
+
+ if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) {
+ // mlog(0, "nothing to recover! sleeping now!\n");
+ spin_unlock(&dlm->spinlock);
+ /* return to main thread loop and sleep. */
+ return 0;
+ }
+ mlog(0, "recovery thread found node %u in the recovery map!\n",
+ dlm->reco.dead_node);
+ spin_unlock(&dlm->spinlock);
+
+ /* take write barrier */
+ /* (stops the list reshuffling thread, proxy ast handling) */
+ dlm_begin_recovery(dlm);
+
+ if (dlm->reco.new_master == dlm->node_num)
+ goto master_here;
+
+ if (dlm->reco.new_master == O2NM_INVALID_NODE_NUM) {
+ /* choose a new master */
+ if (!dlm_pick_recovery_master(dlm)) {
+ /* already notified everyone. go. */
+ dlm->reco.new_master = dlm->node_num;
+ goto master_here;
+ }
+ mlog(0, "another node will master this recovery session.\n");
+ }
+ mlog(0, "dlm=%s, new_master=%u, this node=%u, dead_node=%u\n",
+ dlm->name, dlm->reco.new_master,
+ dlm->node_num, dlm->reco.dead_node);
+
+ /* it is safe to start everything back up here
+ * because all of the dead node's lock resources
+ * have been marked as in-recovery */
+ dlm_end_recovery(dlm);
+
+ /* sleep out in main dlm_recovery_thread loop. */
+ return 0;
+
+master_here:
+ mlog(0, "mastering recovery of %s:%u here(this=%u)!\n",
+ dlm->name, dlm->reco.dead_node, dlm->node_num);
+
+ status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
+ if (status < 0) {
+ mlog(ML_ERROR, "error %d remastering locks for node %u, "
+ "retrying.\n", status, dlm->reco.dead_node);
+ } else {
+ /* success! see if any other nodes need recovery */
+ dlm_reset_recovery(dlm);
+ }
+ dlm_end_recovery(dlm);
+
+ /* continue and look for another dead node */
+ return -EAGAIN;
+}
+
+static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ int status = 0;
+ struct dlm_reco_node_data *ndata;
+ struct list_head *iter;
+ int all_nodes_done;
+ int destroy = 0;
+ int pass = 0;
+
+ status = dlm_init_recovery_area(dlm, dead_node);
+ if (status < 0)
+ goto leave;
+
+ /* safe to access the node data list without a lock, since this
+ * process is the only one to change the list */
+ list_for_each(iter, &dlm->reco.node_data) {
+ ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
+ ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
+
+ mlog(0, "requesting lock info from node %u\n",
+ ndata->node_num);
+
+ if (ndata->node_num == dlm->node_num) {
+ ndata->state = DLM_RECO_NODE_DATA_DONE;
+ continue;
+ }
+
+ status = dlm_request_all_locks(dlm, ndata->node_num, dead_node);
+ if (status < 0) {
+ mlog_errno(status);
+ if (dlm_is_host_down(status))
+ ndata->state = DLM_RECO_NODE_DATA_DEAD;
+ else {
+ destroy = 1;
+ goto leave;
+ }
+ }
+
+ switch (ndata->state) {
+ case DLM_RECO_NODE_DATA_INIT:
+ case DLM_RECO_NODE_DATA_FINALIZE_SENT:
+ case DLM_RECO_NODE_DATA_REQUESTED:
+ BUG();
+ break;
+ case DLM_RECO_NODE_DATA_DEAD:
+ mlog(0, "node %u died after requesting "
+ "recovery info for node %u\n",
+ ndata->node_num, dead_node);
+ // start all over
+ destroy = 1;
+ status = -EAGAIN;
+ goto leave;
+ case DLM_RECO_NODE_DATA_REQUESTING:
+ ndata->state = DLM_RECO_NODE_DATA_REQUESTED;
+ mlog(0, "now receiving recovery data from "
+ "node %u for dead node %u\n",
+ ndata->node_num, dead_node);
+ break;
+ case DLM_RECO_NODE_DATA_RECEIVING:
+ mlog(0, "already receiving recovery data from "
+ "node %u for dead node %u\n",
+ ndata->node_num, dead_node);
+ break;
+ case DLM_RECO_NODE_DATA_DONE:
+ mlog(0, "already DONE receiving recovery data "
+ "from node %u for dead node %u\n",
+ ndata->node_num, dead_node);
+ break;
+ }
+ }
+
+ mlog(0, "done requesting all lock info\n");
+
+ /* nodes should be sending reco data now
+ * just need to wait */
+
+ while (1) {
+ /* check all the nodes now to see if we are
+ * done, or if anyone died */
+ all_nodes_done = 1;
+ spin_lock(&dlm_reco_state_lock);
+ list_for_each(iter, &dlm->reco.node_data) {
+ ndata = list_entry (iter, struct dlm_reco_node_data, list);
+
+ mlog(0, "checking recovery state of node %u\n",
+ ndata->node_num);
+ switch (ndata->state) {
+ case DLM_RECO_NODE_DATA_INIT:
+ case DLM_RECO_NODE_DATA_REQUESTING:
+ mlog(ML_ERROR, "bad ndata state for "
+ "node %u: state=%d\n",
+ ndata->node_num, ndata->state);
+ BUG();
+ break;
+ case DLM_RECO_NODE_DATA_DEAD:
+ mlog(0, "node %u died after "
+ "requesting recovery info for "
+ "node %u\n", ndata->node_num,
+ dead_node);
+ spin_unlock(&dlm_reco_state_lock);
+ // start all over
+ destroy = 1;
+ status = -EAGAIN;
+ goto leave;
+ case DLM_RECO_NODE_DATA_RECEIVING:
+ case DLM_RECO_NODE_DATA_REQUESTED:
+ all_nodes_done = 0;
+ break;
+ case DLM_RECO_NODE_DATA_DONE:
+ break;
+ case DLM_RECO_NODE_DATA_FINALIZE_SENT:
+ break;
+ }
+ }
+ spin_unlock(&dlm_reco_state_lock);
+
+ mlog(0, "pass #%d, all_nodes_done?: %s\n", ++pass,
+ all_nodes_done?"yes":"no");
+ if (all_nodes_done) {
+ int ret;
+
+ /* all nodes are now in DLM_RECO_NODE_DATA_DONE state
+ * just send a finalize message to everyone and
+ * clean up */
+ mlog(0, "all nodes are done! send finalize\n");
+ ret = dlm_send_finalize_reco_message(dlm);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ spin_lock(&dlm->spinlock);
+ dlm_finish_local_lockres_recovery(dlm, dead_node,
+ dlm->node_num);
+ spin_unlock(&dlm->spinlock);
+ mlog(0, "should be done with recovery!\n");
+
+ mlog(0, "finishing recovery of %s at %lu, "
+ "dead=%u, this=%u, new=%u\n", dlm->name,
+ jiffies, dlm->reco.dead_node,
+ dlm->node_num, dlm->reco.new_master);
+ destroy = 1;
+ status = ret;
+ /* rescan everything marked dirty along the way */
+ dlm_kick_thread(dlm, NULL);
+ break;
+ }
+ /* wait to be signalled, with periodic timeout
+ * to check for node death */
+ wait_event_interruptible_timeout(dlm->dlm_reco_thread_wq,
+ kthread_should_stop(),
+ msecs_to_jiffies(DLM_RECO_THREAD_TIMEOUT_MS));
+
+ }
+
+leave:
+ if (destroy)
+ dlm_destroy_recovery_area(dlm, dead_node);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int dlm_init_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ int num=0;
+ struct dlm_reco_node_data *ndata;
+
+ spin_lock(&dlm->spinlock);
+ memcpy(dlm->reco.node_map, dlm->domain_map, sizeof(dlm->domain_map));
+ /* nodes can only be removed (by dying) after dropping
+ * this lock, and death will be trapped later, so this should do */
+ spin_unlock(&dlm->spinlock);
+
+ while (1) {
+ num = find_next_bit (dlm->reco.node_map, O2NM_MAX_NODES, num);
+ if (num >= O2NM_MAX_NODES) {
+ break;
+ }
+ BUG_ON(num == dead_node);
+
+ ndata = kcalloc(1, sizeof(*ndata), GFP_KERNEL);
+ if (!ndata) {
+ dlm_destroy_recovery_area(dlm, dead_node);
+ return -ENOMEM;
+ }
+ ndata->node_num = num;
+ ndata->state = DLM_RECO_NODE_DATA_INIT;
+ spin_lock(&dlm_reco_state_lock);
+ list_add_tail(&ndata->list, &dlm->reco.node_data);
+ spin_unlock(&dlm_reco_state_lock);
+ num++;
+ }
+
+ return 0;
+}
+
+static void dlm_destroy_recovery_area(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ struct list_head *iter, *iter2;
+ struct dlm_reco_node_data *ndata;
+ LIST_HEAD(tmplist);
+
+ spin_lock(&dlm_reco_state_lock);
+ list_splice_init(&dlm->reco.node_data, &tmplist);
+ spin_unlock(&dlm_reco_state_lock);
+
+ list_for_each_safe(iter, iter2, &tmplist) {
+ ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ list_del_init(&ndata->list);
+ kfree(ndata);
+ }
+}
+
+static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from,
+ u8 dead_node)
+{
+ struct dlm_lock_request lr;
+ enum dlm_status ret;
+
+ mlog(0, "\n");
+
+
+ mlog(0, "dlm_request_all_locks: dead node is %u, sending request "
+ "to %u\n", dead_node, request_from);
+
+ memset(&lr, 0, sizeof(lr));
+ lr.node_idx = dlm->node_num;
+ lr.dead_node = dead_node;
+
+ // send message
+ ret = DLM_NOLOCKMGR;
+ ret = o2net_send_message(DLM_LOCK_REQUEST_MSG, dlm->key,
+ &lr, sizeof(lr), request_from, NULL);
+
+ /* negative status is handled by caller */
+ if (ret < 0)
+ mlog_errno(ret);
+
+ // return from here, then
+ // sleep until all received or error
+ return ret;
+
+}
+
+int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_lock_request *lr = (struct dlm_lock_request *)msg->buf;
+ char *buf = NULL;
+ struct dlm_work_item *item = NULL;
+
+ if (!dlm_grab(dlm))
+ return -EINVAL;
+
+ BUG_ON(lr->dead_node != dlm->reco.dead_node);
+
+ item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+ if (!item) {
+ dlm_put(dlm);
+ return -ENOMEM;
+ }
+
+ /* this will get freed by dlm_request_all_locks_worker */
+ buf = (char *) __get_free_page(GFP_KERNEL);
+ if (!buf) {
+ kfree(item);
+ dlm_put(dlm);
+ return -ENOMEM;
+ }
+
+ /* queue up work for dlm_request_all_locks_worker */
+ dlm_grab(dlm); /* get an extra ref for the work item */
+ dlm_init_work_item(dlm, item, dlm_request_all_locks_worker, buf);
+ item->u.ral.reco_master = lr->node_idx;
+ item->u.ral.dead_node = lr->dead_node;
+ spin_lock(&dlm->work_lock);
+ list_add_tail(&item->list, &dlm->work_list);
+ spin_unlock(&dlm->work_lock);
+ schedule_work(&dlm->dispatched_work);
+
+ dlm_put(dlm);
+ return 0;
+}
+
+static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data)
+{
+ struct dlm_migratable_lockres *mres;
+ struct dlm_lock_resource *res;
+ struct dlm_ctxt *dlm;
+ LIST_HEAD(resources);
+ struct list_head *iter;
+ int ret;
+ u8 dead_node, reco_master;
+
+ dlm = item->dlm;
+ dead_node = item->u.ral.dead_node;
+ reco_master = item->u.ral.reco_master;
+ BUG_ON(dead_node != dlm->reco.dead_node);
+ BUG_ON(reco_master != dlm->reco.new_master);
+
+ mres = (struct dlm_migratable_lockres *)data;
+
+ /* lock resources should have already been moved to the
+ * dlm->reco.resources list. now move items from that list
+ * to a temp list if the dead owner matches. note that the
+ * whole cluster recovers only one node at a time, so we
+ * can safely move UNKNOWN lock resources for each recovery
+ * session. */
+ dlm_move_reco_locks_to_list(dlm, &resources, dead_node);
+
+ /* now we can begin blasting lockreses without the dlm lock */
+ list_for_each(iter, &resources) {
+ res = list_entry (iter, struct dlm_lock_resource, recovering);
+ ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
+ DLM_MRES_RECOVERY);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+
+ /* move the resources back to the list */
+ spin_lock(&dlm->spinlock);
+ list_splice_init(&resources, &dlm->reco.resources);
+ spin_unlock(&dlm->spinlock);
+
+ ret = dlm_send_all_done_msg(dlm, dead_node, reco_master);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ free_page((unsigned long)data);
+}
+
+
+static int dlm_send_all_done_msg(struct dlm_ctxt *dlm, u8 dead_node, u8 send_to)
+{
+ int ret, tmpret;
+ struct dlm_reco_data_done done_msg;
+
+ memset(&done_msg, 0, sizeof(done_msg));
+ done_msg.node_idx = dlm->node_num;
+ done_msg.dead_node = dead_node;
+ mlog(0, "sending DATA DONE message to %u, "
+ "my node=%u, dead node=%u\n", send_to, done_msg.node_idx,
+ done_msg.dead_node);
+
+ ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg,
+ sizeof(done_msg), send_to, &tmpret);
+ /* negative status is ignored by the caller */
+ if (ret >= 0)
+ ret = tmpret;
+ return ret;
+}
+
+
+int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_reco_data_done *done = (struct dlm_reco_data_done *)msg->buf;
+ struct list_head *iter;
+ struct dlm_reco_node_data *ndata = NULL;
+ int ret = -EINVAL;
+
+ if (!dlm_grab(dlm))
+ return -EINVAL;
+
+ mlog(0, "got DATA DONE: dead_node=%u, reco.dead_node=%u, "
+ "node_idx=%u, this node=%u\n", done->dead_node,
+ dlm->reco.dead_node, done->node_idx, dlm->node_num);
+ BUG_ON(done->dead_node != dlm->reco.dead_node);
+
+ spin_lock(&dlm_reco_state_lock);
+ list_for_each(iter, &dlm->reco.node_data) {
+ ndata = list_entry (iter, struct dlm_reco_node_data, list);
+ if (ndata->node_num != done->node_idx)
+ continue;
+
+ switch (ndata->state) {
+ case DLM_RECO_NODE_DATA_INIT:
+ case DLM_RECO_NODE_DATA_DEAD:
+ case DLM_RECO_NODE_DATA_DONE:
+ case DLM_RECO_NODE_DATA_FINALIZE_SENT:
+ mlog(ML_ERROR, "bad ndata state for node %u:"
+ " state=%d\n", ndata->node_num,
+ ndata->state);
+ BUG();
+ break;
+ case DLM_RECO_NODE_DATA_RECEIVING:
+ case DLM_RECO_NODE_DATA_REQUESTED:
+ case DLM_RECO_NODE_DATA_REQUESTING:
+ mlog(0, "node %u is DONE sending "
+ "recovery data!\n",
+ ndata->node_num);
+
+ ndata->state = DLM_RECO_NODE_DATA_DONE;
+ ret = 0;
+ break;
+ }
+ }
+ spin_unlock(&dlm_reco_state_lock);
+
+ /* wake the recovery thread, some node is done */
+ if (!ret)
+ dlm_kick_recovery_thread(dlm);
+
+ if (ret < 0)
+ mlog(ML_ERROR, "failed to find recovery node data for node "
+ "%u\n", done->node_idx);
+ dlm_put(dlm);
+
+ mlog(0, "leaving reco data done handler, ret=%d\n", ret);
+ return ret;
+}
+
+static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm,
+ struct list_head *list,
+ u8 dead_node)
+{
+ struct dlm_lock_resource *res;
+ struct list_head *iter, *iter2;
+
+ spin_lock(&dlm->spinlock);
+ list_for_each_safe(iter, iter2, &dlm->reco.resources) {
+ res = list_entry (iter, struct dlm_lock_resource, recovering);
+ if (dlm_is_recovery_lock(res->lockname.name,
+ res->lockname.len))
+ continue;
+ if (res->owner == dead_node) {
+ mlog(0, "found lockres owned by dead node while "
+ "doing recovery for node %u. sending it.\n",
+ dead_node);
+ list_del_init(&res->recovering);
+ list_add_tail(&res->recovering, list);
+ } else if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "found UNKNOWN owner while doing recovery "
+ "for node %u. sending it.\n", dead_node);
+ list_del_init(&res->recovering);
+ list_add_tail(&res->recovering, list);
+ }
+ }
+ spin_unlock(&dlm->spinlock);
+}
+
+static inline int dlm_num_locks_in_lockres(struct dlm_lock_resource *res)
+{
+ int total_locks = 0;
+ struct list_head *iter, *queue = &res->granted;
+ int i;
+
+ for (i=0; i<3; i++) {
+ list_for_each(iter, queue)
+ total_locks++;
+ queue++;
+ }
+ return total_locks;
+}
+
+
+static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
+ struct dlm_migratable_lockres *mres,
+ u8 send_to,
+ struct dlm_lock_resource *res,
+ int total_locks)
+{
+ u64 mig_cookie = be64_to_cpu(mres->mig_cookie);
+ int mres_total_locks = be32_to_cpu(mres->total_locks);
+ int sz, ret = 0, status = 0;
+ u8 orig_flags = mres->flags,
+ orig_master = mres->master;
+
+ BUG_ON(mres->num_locks > DLM_MAX_MIGRATABLE_LOCKS);
+ if (!mres->num_locks)
+ return 0;
+
+ sz = sizeof(struct dlm_migratable_lockres) +
+ (mres->num_locks * sizeof(struct dlm_migratable_lock));
+
+ /* add an all-done flag if we reached the last lock */
+ orig_flags = mres->flags;
+ BUG_ON(total_locks > mres_total_locks);
+ if (total_locks == mres_total_locks)
+ mres->flags |= DLM_MRES_ALL_DONE;
+
+ /* send it */
+ ret = o2net_send_message(DLM_MIG_LOCKRES_MSG, dlm->key, mres,
+ sz, send_to, &status);
+ if (ret < 0) {
+ /* XXX: negative status is not handled.
+ * this will end up killing this node. */
+ mlog_errno(ret);
+ } else {
+ /* might get an -ENOMEM back here */
+ ret = status;
+ if (ret < 0) {
+ mlog_errno(ret);
+
+ if (ret == -EFAULT) {
+ mlog(ML_ERROR, "node %u told me to kill "
+ "myself!\n", send_to);
+ BUG();
+ }
+ }
+ }
+
+ /* zero and reinit the message buffer */
+ dlm_init_migratable_lockres(mres, res->lockname.name,
+ res->lockname.len, mres_total_locks,
+ mig_cookie, orig_flags, orig_master);
+ return ret;
+}
+
+static void dlm_init_migratable_lockres(struct dlm_migratable_lockres *mres,
+ const char *lockname, int namelen,
+ int total_locks, u64 cookie,
+ u8 flags, u8 master)
+{
+ /* mres here is one full page */
+ memset(mres, 0, PAGE_SIZE);
+ mres->lockname_len = namelen;
+ memcpy(mres->lockname, lockname, namelen);
+ mres->num_locks = 0;
+ mres->total_locks = cpu_to_be32(total_locks);
+ mres->mig_cookie = cpu_to_be64(cookie);
+ mres->flags = flags;
+ mres->master = master;
+}
+
+
+/* returns 1 if this lock fills the network structure,
+ * 0 otherwise */
+static int dlm_add_lock_to_array(struct dlm_lock *lock,
+ struct dlm_migratable_lockres *mres, int queue)
+{
+ struct dlm_migratable_lock *ml;
+ int lock_num = mres->num_locks;
+
+ ml = &(mres->ml[lock_num]);
+ ml->cookie = lock->ml.cookie;
+ ml->type = lock->ml.type;
+ ml->convert_type = lock->ml.convert_type;
+ ml->highest_blocked = lock->ml.highest_blocked;
+ ml->list = queue;
+ if (lock->lksb) {
+ ml->flags = lock->lksb->flags;
+ /* send our current lvb */
+ if (ml->type == LKM_EXMODE ||
+ ml->type == LKM_PRMODE) {
+ /* if it is already set, this had better be a PR
+ * and it has to match */
+ if (mres->lvb[0] && (ml->type == LKM_EXMODE ||
+ memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
+ mlog(ML_ERROR, "mismatched lvbs!\n");
+ __dlm_print_one_lock_resource(lock->lockres);
+ BUG();
+ }
+ memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN);
+ }
+ }
+ ml->node = lock->ml.node;
+ mres->num_locks++;
+ /* we reached the max, send this network message */
+ if (mres->num_locks == DLM_MAX_MIGRATABLE_LOCKS)
+ return 1;
+ return 0;
+}
+
+
+int dlm_send_one_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
+ struct dlm_migratable_lockres *mres,
+ u8 send_to, u8 flags)
+{
+ struct list_head *queue, *iter;
+ int total_locks, i;
+ u64 mig_cookie = 0;
+ struct dlm_lock *lock;
+ int ret = 0;
+
+ BUG_ON(!(flags & (DLM_MRES_RECOVERY|DLM_MRES_MIGRATION)));
+
+ mlog(0, "sending to %u\n", send_to);
+
+ total_locks = dlm_num_locks_in_lockres(res);
+ if (total_locks > DLM_MAX_MIGRATABLE_LOCKS) {
+ /* rare, but possible */
+ mlog(0, "argh. lockres has %d locks. this will "
+ "require more than one network packet to "
+ "migrate\n", total_locks);
+ mig_cookie = dlm_get_next_mig_cookie();
+ }
+
+ dlm_init_migratable_lockres(mres, res->lockname.name,
+ res->lockname.len, total_locks,
+ mig_cookie, flags, res->owner);
+
+ total_locks = 0;
+ for (i=DLM_GRANTED_LIST; i<=DLM_BLOCKED_LIST; i++) {
+ queue = dlm_list_idx_to_ptr(res, i);
+ list_for_each(iter, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+
+ /* add another lock. */
+ total_locks++;
+ if (!dlm_add_lock_to_array(lock, mres, i))
+ continue;
+
+ /* this filled the lock message,
+ * we must send it immediately. */
+ ret = dlm_send_mig_lockres_msg(dlm, mres, send_to,
+ res, total_locks);
+ if (ret < 0) {
+ // TODO
+ mlog(ML_ERROR, "dlm_send_mig_lockres_msg "
+ "returned %d, TODO\n", ret);
+ BUG();
+ }
+ }
+ }
+ /* flush any remaining locks */
+ ret = dlm_send_mig_lockres_msg(dlm, mres, send_to, res, total_locks);
+ if (ret < 0) {
+ // TODO
+ mlog(ML_ERROR, "dlm_send_mig_lockres_msg returned %d, "
+ "TODO\n", ret);
+ BUG();
+ }
+ return ret;
+}
+
+
+
+/*
+ * this message will contain no more than one page worth of
+ * recovery data, and it will work on only one lockres.
+ * there may be many locks in this page, and we may need to wait
+ * for additional packets to complete all the locks (rare, but
+ * possible).
+ */
+/*
+ * NOTE: the allocation error cases here are scary
+ * we really cannot afford to fail an alloc in recovery
+ * do we spin? returning an error only delays the problem really
+ */
+
+int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_migratable_lockres *mres =
+ (struct dlm_migratable_lockres *)msg->buf;
+ int ret = 0;
+ u8 real_master;
+ char *buf = NULL;
+ struct dlm_work_item *item = NULL;
+ struct dlm_lock_resource *res = NULL;
+
+ if (!dlm_grab(dlm))
+ return -EINVAL;
+
+ BUG_ON(!(mres->flags & (DLM_MRES_RECOVERY|DLM_MRES_MIGRATION)));
+
+ real_master = mres->master;
+ if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* cannot migrate a lockres with no master */
+ BUG_ON(!(mres->flags & DLM_MRES_RECOVERY));
+ }
+
+ mlog(0, "%s message received from node %u\n",
+ (mres->flags & DLM_MRES_RECOVERY) ?
+ "recovery" : "migration", mres->master);
+ if (mres->flags & DLM_MRES_ALL_DONE)
+ mlog(0, "all done flag. all lockres data received!\n");
+
+ ret = -ENOMEM;
+ buf = kmalloc(be16_to_cpu(msg->data_len), GFP_KERNEL);
+ item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+ if (!buf || !item)
+ goto leave;
+
+ /* lookup the lock to see if we have a secondary queue for this
+ * already... just add the locks in and this will have its owner
+ * and RECOVERY flag changed when it completes. */
+ res = dlm_lookup_lockres(dlm, mres->lockname, mres->lockname_len);
+ if (res) {
+ /* this will get a ref on res */
+ /* mark it as recovering/migrating and hash it */
+ spin_lock(&res->spinlock);
+ if (mres->flags & DLM_MRES_RECOVERY) {
+ res->state |= DLM_LOCK_RES_RECOVERING;
+ } else {
+ if (res->state & DLM_LOCK_RES_MIGRATING) {
+ /* this is at least the second
+ * lockres message */
+ mlog(0, "lock %.*s is already migrating\n",
+ mres->lockname_len,
+ mres->lockname);
+ } else if (res->state & DLM_LOCK_RES_RECOVERING) {
+ /* caller should BUG */
+ mlog(ML_ERROR, "node is attempting to migrate "
+ "lock %.*s, but marked as recovering!\n",
+ mres->lockname_len, mres->lockname);
+ ret = -EFAULT;
+ spin_unlock(&res->spinlock);
+ goto leave;
+ }
+ res->state |= DLM_LOCK_RES_MIGRATING;
+ }
+ spin_unlock(&res->spinlock);
+ } else {
+ /* need to allocate, just like if it was
+ * mastered here normally */
+ res = dlm_new_lockres(dlm, mres->lockname, mres->lockname_len);
+ if (!res)
+ goto leave;
+
+ /* to match the ref that we would have gotten if
+ * dlm_lookup_lockres had succeeded */
+ dlm_lockres_get(res);
+
+ /* mark it as recovering/migrating and hash it */
+ if (mres->flags & DLM_MRES_RECOVERY)
+ res->state |= DLM_LOCK_RES_RECOVERING;
+ else
+ res->state |= DLM_LOCK_RES_MIGRATING;
+
+ spin_lock(&dlm->spinlock);
+ __dlm_insert_lockres(dlm, res);
+ spin_unlock(&dlm->spinlock);
+
+ /* now that the new lockres is inserted,
+ * make it usable by other processes */
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ spin_unlock(&res->spinlock);
+
+ /* add an extra ref for just-allocated lockres
+ * otherwise the lockres will be purged immediately */
+ dlm_lockres_get(res);
+
+ }
+
+ /* at this point we have allocated everything we need,
+ * and we have a hashed lockres with an extra ref and
+ * the proper res->state flags. */
+ ret = 0;
+ if (mres->master == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* migration cannot have an unknown master */
+ BUG_ON(!(mres->flags & DLM_MRES_RECOVERY));
+ mlog(0, "recovery has passed me a lockres with an "
+ "unknown owner.. will need to requery: "
+ "%.*s\n", mres->lockname_len, mres->lockname);
+ } else {
+ spin_lock(&res->spinlock);
+ dlm_change_lockres_owner(dlm, res, dlm->node_num);
+ spin_unlock(&res->spinlock);
+ }
+
+ /* queue up work for dlm_mig_lockres_worker */
+ dlm_grab(dlm); /* get an extra ref for the work item */
+ memcpy(buf, msg->buf, be16_to_cpu(msg->data_len)); /* copy the whole message */
+ dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf);
+ item->u.ml.lockres = res; /* already have a ref */
+ item->u.ml.real_master = real_master;
+ spin_lock(&dlm->work_lock);
+ list_add_tail(&item->list, &dlm->work_list);
+ spin_unlock(&dlm->work_lock);
+ schedule_work(&dlm->dispatched_work);
+
+leave:
+ dlm_put(dlm);
+ if (ret < 0) {
+ if (buf)
+ kfree(buf);
+ if (item)
+ kfree(item);
+ }
+
+ mlog_exit(ret);
+ return ret;
+}
+
+
+static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_migratable_lockres *mres;
+ int ret = 0;
+ struct dlm_lock_resource *res;
+ u8 real_master;
+
+ dlm = item->dlm;
+ mres = (struct dlm_migratable_lockres *)data;
+
+ res = item->u.ml.lockres;
+ real_master = item->u.ml.real_master;
+
+ if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ /* this case is super-rare. only occurs if
+ * node death happens during migration. */
+again:
+ ret = dlm_lockres_master_requery(dlm, res, &real_master);
+ if (ret < 0) {
+ mlog(0, "dlm_lockres_master_requery failure: %d\n",
+ ret);
+ goto again;
+ }
+ if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "lockres %.*s not claimed. "
+ "this node will take it.\n",
+ res->lockname.len, res->lockname.name);
+ } else {
+ mlog(0, "master needs to respond to sender "
+ "that node %u still owns %.*s\n",
+ real_master, res->lockname.len,
+ res->lockname.name);
+ /* cannot touch this lockres */
+ goto leave;
+ }
+ }
+
+ ret = dlm_process_recovery_data(dlm, res, mres);
+ if (ret < 0)
+ mlog(0, "dlm_process_recovery_data returned %d\n", ret);
+ else
+ mlog(0, "dlm_process_recovery_data succeeded\n");
+
+ if ((mres->flags & (DLM_MRES_MIGRATION|DLM_MRES_ALL_DONE)) ==
+ (DLM_MRES_MIGRATION|DLM_MRES_ALL_DONE)) {
+ ret = dlm_finish_migration(dlm, res, mres->master);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+
+leave:
+ kfree(data);
+ mlog_exit(ret);
+}
+
+
+
+static int dlm_lockres_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 *real_master)
+{
+ struct dlm_node_iter iter;
+ int nodenum;
+ int ret = 0;
+
+ *real_master = DLM_LOCK_RES_OWNER_UNKNOWN;
+
+ /* we only reach here if one of the two nodes in a
+ * migration died while the migration was in progress.
+ * at this point we need to requery the master. we
+ * know that the new_master got as far as creating
+ * an mle on at least one node, but we do not know
+ * if any nodes had actually cleared the mle and set
+ * the master to the new_master. the old master
+ * is supposed to set the owner to UNKNOWN in the
+ * event of a new_master death, so the only possible
+ * responses that we can get from nodes here are
+ * that the master is new_master, or that the master
+ * is UNKNOWN.
+ * if all nodes come back with UNKNOWN then we know
+ * the lock needs remastering here.
+ * if any node comes back with a valid master, check
+ * to see if that master is the one that we are
+ * recovering. if so, then the new_master died and
+ * we need to remaster this lock. if not, then the
+ * new_master survived and that node will respond to
+ * other nodes about the owner.
+ * if there is an owner, this node needs to dump this
+ * lockres and alert the sender that this lockres
+ * was rejected. */
+ spin_lock(&dlm->spinlock);
+ dlm_node_iter_init(dlm->domain_map, &iter);
+ spin_unlock(&dlm->spinlock);
+
+ while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
+ /* do not send to self */
+ if (nodenum == dlm->node_num)
+ continue;
+ ret = dlm_do_master_requery(dlm, res, nodenum, real_master);
+ if (ret < 0) {
+ mlog_errno(ret);
+ BUG();
+ /* TODO: need to figure a way to restart this */
+ }
+ if (*real_master != DLM_LOCK_RES_OWNER_UNKNOWN) {
+ mlog(0, "lock master is %u\n", *real_master);
+ break;
+ }
+ }
+ return ret;
+}
+
+
+static int dlm_do_master_requery(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ u8 nodenum, u8 *real_master)
+{
+ int ret = -EINVAL;
+ struct dlm_master_requery req;
+ int status = DLM_LOCK_RES_OWNER_UNKNOWN;
+
+ memset(&req, 0, sizeof(req));
+ req.node_idx = dlm->node_num;
+ req.namelen = res->lockname.len;
+ memcpy(req.name, res->lockname.name, res->lockname.len);
+
+ ret = o2net_send_message(DLM_MASTER_REQUERY_MSG, dlm->key,
+ &req, sizeof(req), nodenum, &status);
+ /* XXX: negative status not handled properly here. */
+ if (ret < 0)
+ mlog_errno(ret);
+ else {
+ BUG_ON(status < 0);
+ BUG_ON(status > DLM_LOCK_RES_OWNER_UNKNOWN);
+ *real_master = (u8) (status & 0xff);
+ mlog(0, "node %u responded to master requery with %u\n",
+ nodenum, *real_master);
+ ret = 0;
+ }
+ return ret;
+}
+
+
+/* this function cannot error, so unless the sending
+ * or receiving of the message failed, the owner can
+ * be trusted */
+int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_master_requery *req = (struct dlm_master_requery *)msg->buf;
+ struct dlm_lock_resource *res = NULL;
+ int master = DLM_LOCK_RES_OWNER_UNKNOWN;
+ u32 flags = DLM_ASSERT_MASTER_REQUERY;
+
+ if (!dlm_grab(dlm)) {
+ /* since the domain has gone away on this
+ * node, the proper response is UNKNOWN */
+ return master;
+ }
+
+ spin_lock(&dlm->spinlock);
+ res = __dlm_lookup_lockres(dlm, req->name, req->namelen);
+ if (res) {
+ spin_lock(&res->spinlock);
+ master = res->owner;
+ if (master == dlm->node_num) {
+ int ret = dlm_dispatch_assert_master(dlm, res,
+ 0, 0, flags);
+ if (ret < 0) {
+ mlog_errno(-ENOMEM);
+ /* retry!? */
+ BUG();
+ }
+ }
+ spin_unlock(&res->spinlock);
+ }
+ spin_unlock(&dlm->spinlock);
+
+ dlm_put(dlm);
+ return master;
+}
+
+static inline struct list_head *
+dlm_list_num_to_pointer(struct dlm_lock_resource *res, int list_num)
+{
+ struct list_head *ret;
+ BUG_ON(list_num < 0);
+ BUG_ON(list_num > 2);
+ ret = &(res->granted);
+ ret += list_num;
+ return ret;
+}
+/* TODO: do ast flush business
+ * TODO: do MIGRATING and RECOVERING spinning
+ */
+
+/*
+* NOTE about in-flight requests during migration:
+*
+* Before attempting the migrate, the master has marked the lockres as
+* MIGRATING and then flushed all of its pending ASTS. So any in-flight
+* requests either got queued before the MIGRATING flag got set, in which
+* case the lock data will reflect the change and a return message is on
+* the way, or the request failed to get in before MIGRATING got set. In
+* this case, the caller will be told to spin and wait for the MIGRATING
+* flag to be dropped, then recheck the master.
+* This holds true for the convert, cancel and unlock cases, and since lvb
+* updates are tied to these same messages, it applies to lvb updates as
+* well. For the lock case, there is no way a lock can be on the master
+* queue and not be on the secondary queue since the lock is always added
+* locally first. This means that the new target node will never be sent
+* a lock that he doesn't already have on the list.
+* In total, this means that the local lock is correct and should not be
+* updated to match the one sent by the master. Any messages sent back
+* from the master before the MIGRATING flag will bring the lock properly
+* up-to-date, and the change will be ordered properly for the waiter.
+* We will *not* attempt to modify the lock underneath the waiter.
+*/
+
+static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_migratable_lockres *mres)
+{
+ struct dlm_migratable_lock *ml;
+ struct list_head *queue;
+ struct dlm_lock *newlock = NULL;
+ struct dlm_lockstatus *lksb = NULL;
+ int ret = 0;
+ int i;
+ struct list_head *iter;
+ struct dlm_lock *lock = NULL;
+
+ mlog(0, "running %d locks for this lockres\n", mres->num_locks);
+ for (i=0; i<mres->num_locks; i++) {
+ ml = &(mres->ml[i]);
+ BUG_ON(ml->highest_blocked != LKM_IVMODE);
+ newlock = NULL;
+ lksb = NULL;
+
+ queue = dlm_list_num_to_pointer(res, ml->list);
+
+ /* if the lock is for the local node it needs to
+ * be moved to the proper location within the queue.
+ * do not allocate a new lock structure. */
+ if (ml->node == dlm->node_num) {
+ /* MIGRATION ONLY! */
+ BUG_ON(!(mres->flags & DLM_MRES_MIGRATION));
+
+ spin_lock(&res->spinlock);
+ list_for_each(iter, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.cookie != ml->cookie)
+ lock = NULL;
+ else
+ break;
+ }
+
+ /* lock is always created locally first, and
+ * destroyed locally last. it must be on the list */
+ if (!lock) {
+ mlog(ML_ERROR, "could not find local lock "
+ "with cookie %"MLFu64"!\n",
+ ml->cookie);
+ BUG();
+ }
+ BUG_ON(lock->ml.node != ml->node);
+
+ /* see NOTE above about why we do not update
+ * to match the master here */
+
+ /* move the lock to its proper place */
+ /* do not alter lock refcount. switching lists. */
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, queue);
+ spin_unlock(&res->spinlock);
+
+ mlog(0, "just reordered a local lock!\n");
+ continue;
+ }
+
+ /* lock is for another node. */
+ newlock = dlm_new_lock(ml->type, ml->node,
+ be64_to_cpu(ml->cookie), NULL);
+ if (!newlock) {
+ ret = -ENOMEM;
+ goto leave;
+ }
+ lksb = newlock->lksb;
+ dlm_lock_attach_lockres(newlock, res);
+
+ if (ml->convert_type != LKM_IVMODE) {
+ BUG_ON(queue != &res->converting);
+ newlock->ml.convert_type = ml->convert_type;
+ }
+ lksb->flags |= (ml->flags &
+ (DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB));
+
+ if (mres->lvb[0]) {
+ if (lksb->flags & DLM_LKSB_PUT_LVB) {
+ /* other node was trying to update
+ * lvb when node died. recreate the
+ * lksb with the updated lvb. */
+ memcpy(lksb->lvb, mres->lvb, DLM_LVB_LEN);
+ } else {
+ /* otherwise, the node is sending its
+ * most recent valid lvb info */
+ BUG_ON(ml->type != LKM_EXMODE &&
+ ml->type != LKM_PRMODE);
+ if (res->lvb[0] && (ml->type == LKM_EXMODE ||
+ memcmp(res->lvb, mres->lvb, DLM_LVB_LEN))) {
+ mlog(ML_ERROR, "received bad lvb!\n");
+ __dlm_print_one_lock_resource(res);
+ BUG();
+ }
+ memcpy(res->lvb, mres->lvb, DLM_LVB_LEN);
+ }
+ }
+
+
+ /* NOTE:
+ * wrt lock queue ordering and recovery:
+ * 1. order of locks on granted queue is
+ * meaningless.
+ * 2. order of locks on converting queue is
+ * LOST with the node death. sorry charlie.
+ * 3. order of locks on the blocked queue is
+ * also LOST.
+ * order of locks does not affect integrity, it
+ * just means that a lock request may get pushed
+ * back in line as a result of the node death.
+ * also note that for a given node the lock order
+ * for its secondary queue locks is preserved
+ * relative to each other, but clearly *not*
+ * preserved relative to locks from other nodes.
+ */
+ spin_lock(&res->spinlock);
+ dlm_lock_get(newlock);
+ list_add_tail(&newlock->list, queue);
+ spin_unlock(&res->spinlock);
+ }
+ mlog(0, "done running all the locks\n");
+
+leave:
+ if (ret < 0) {
+ mlog_errno(ret);
+ if (newlock)
+ dlm_lock_put(newlock);
+ }
+
+ mlog_exit(ret);
+ return ret;
+}
+
+void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ int i;
+ struct list_head *queue, *iter, *iter2;
+ struct dlm_lock *lock;
+
+ res->state |= DLM_LOCK_RES_RECOVERING;
+ if (!list_empty(&res->recovering))
+ list_del_init(&res->recovering);
+ list_add_tail(&res->recovering, &dlm->reco.resources);
+
+ /* find any pending locks and put them back on proper list */
+ for (i=DLM_BLOCKED_LIST; i>=DLM_GRANTED_LIST; i--) {
+ queue = dlm_list_idx_to_ptr(res, i);
+ list_for_each_safe(iter, iter2, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ dlm_lock_get(lock);
+ if (lock->convert_pending) {
+ /* move converting lock back to granted */
+ BUG_ON(i != DLM_CONVERTING_LIST);
+ mlog(0, "node died with convert pending "
+ "on %.*s. move back to granted list.\n",
+ res->lockname.len, res->lockname.name);
+ dlm_revert_pending_convert(res, lock);
+ lock->convert_pending = 0;
+ } else if (lock->lock_pending) {
+ /* remove pending lock requests completely */
+ BUG_ON(i != DLM_BLOCKED_LIST);
+ mlog(0, "node died with lock pending "
+ "on %.*s. remove from blocked list and skip.\n",
+ res->lockname.len, res->lockname.name);
+ /* lock will be floating until ref in
+ * dlmlock_remote is freed after the network
+ * call returns. ok for it to not be on any
+ * list since no ast can be called
+ * (the master is dead). */
+ dlm_revert_pending_lock(res, lock);
+ lock->lock_pending = 0;
+ } else if (lock->unlock_pending) {
+ /* if an unlock was in progress, treat as
+ * if this had completed successfully
+ * before sending this lock state to the
+ * new master. note that the dlm_unlock
+ * call is still responsible for calling
+ * the unlockast. that will happen after
+ * the network call times out. for now,
+ * just move lists to prepare the new
+ * recovery master. */
+ BUG_ON(i != DLM_GRANTED_LIST);
+ mlog(0, "node died with unlock pending "
+ "on %.*s. remove from blocked list and skip.\n",
+ res->lockname.len, res->lockname.name);
+ dlm_commit_pending_unlock(res, lock);
+ lock->unlock_pending = 0;
+ } else if (lock->cancel_pending) {
+ /* if a cancel was in progress, treat as
+ * if this had completed successfully
+ * before sending this lock state to the
+ * new master */
+ BUG_ON(i != DLM_CONVERTING_LIST);
+ mlog(0, "node died with cancel pending "
+ "on %.*s. move back to granted list.\n",
+ res->lockname.len, res->lockname.name);
+ dlm_commit_pending_cancel(res, lock);
+ lock->cancel_pending = 0;
+ }
+ dlm_lock_put(lock);
+ }
+ }
+}
+
+
+
+/* removes all recovered locks from the recovery list.
+ * sets the res->owner to the new master.
+ * unsets the RECOVERY flag and wakes waiters. */
+static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
+ u8 dead_node, u8 new_master)
+{
+ int i;
+ struct list_head *iter, *iter2, *bucket;
+ struct dlm_lock_resource *res;
+
+ mlog_entry_void();
+
+ assert_spin_locked(&dlm->spinlock);
+
+ list_for_each_safe(iter, iter2, &dlm->reco.resources) {
+ res = list_entry (iter, struct dlm_lock_resource, recovering);
+ if (res->owner == dead_node) {
+ list_del_init(&res->recovering);
+ spin_lock(&res->spinlock);
+ dlm_change_lockres_owner(dlm, res, new_master);
+ res->state &= ~DLM_LOCK_RES_RECOVERING;
+ __dlm_dirty_lockres(dlm, res);
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+ }
+ }
+
+ /* this will become unnecessary eventually, but
+ * for now we need to run the whole hash, clear
+ * the RECOVERING state and set the owner
+ * if necessary */
+ for (i=0; i<DLM_HASH_SIZE; i++) {
+ bucket = &(dlm->resources[i]);
+ list_for_each(iter, bucket) {
+ res = list_entry (iter, struct dlm_lock_resource, list);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ if (res->owner == dead_node) {
+ mlog(0, "(this=%u) res %.*s owner=%u "
+ "was not on recovering list, but "
+ "clearing state anyway\n",
+ dlm->node_num, res->lockname.len,
+ res->lockname.name, new_master);
+ } else if (res->owner == dlm->node_num) {
+ mlog(0, "(this=%u) res %.*s owner=%u "
+ "was not on recovering list, "
+ "owner is THIS node, clearing\n",
+ dlm->node_num, res->lockname.len,
+ res->lockname.name, new_master);
+ } else
+ continue;
+
+ spin_lock(&res->spinlock);
+ dlm_change_lockres_owner(dlm, res, new_master);
+ res->state &= ~DLM_LOCK_RES_RECOVERING;
+ __dlm_dirty_lockres(dlm, res);
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+ }
+ }
+ }
+}
+
+static inline int dlm_lvb_needs_invalidation(struct dlm_lock *lock, int local)
+{
+ if (local) {
+ if (lock->ml.type != LKM_EXMODE &&
+ lock->ml.type != LKM_PRMODE)
+ return 1;
+ } else if (lock->ml.type == LKM_EXMODE)
+ return 1;
+ return 0;
+}
+
+static void dlm_revalidate_lvb(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res, u8 dead_node)
+{
+ struct list_head *iter, *queue;
+ struct dlm_lock *lock;
+ int blank_lvb = 0, local = 0;
+ int i;
+ u8 search_node;
+
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&res->spinlock);
+
+ if (res->owner == dlm->node_num)
+ /* if this node owned the lockres, and if the dead node
+ * had an EX when he died, blank out the lvb */
+ search_node = dead_node;
+ else {
+ /* if this is a secondary lockres, and we had no EX or PR
+ * locks granted, we can no longer trust the lvb */
+ search_node = dlm->node_num;
+ local = 1; /* check local state for valid lvb */
+ }
+
+ for (i=DLM_GRANTED_LIST; i<=DLM_CONVERTING_LIST; i++) {
+ queue = dlm_list_idx_to_ptr(res, i);
+ list_for_each(iter, queue) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node == search_node) {
+ if (dlm_lvb_needs_invalidation(lock, local)) {
+ /* zero the lksb lvb and lockres lvb */
+ blank_lvb = 1;
+ memset(lock->lksb->lvb, 0, DLM_LVB_LEN);
+ }
+ }
+ }
+ }
+
+ if (blank_lvb) {
+ mlog(0, "clearing %.*s lvb, dead node %u had EX\n",
+ res->lockname.len, res->lockname.name, dead_node);
+ memset(res->lvb, 0, DLM_LVB_LEN);
+ }
+}
+
+static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res, u8 dead_node)
+{
+ struct list_head *iter, *tmpiter;
+ struct dlm_lock *lock;
+
+ /* this node is the lockres master:
+ * 1) remove any stale locks for the dead node
+ * 2) if the dead node had an EX when he died, blank out the lvb
+ */
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&res->spinlock);
+
+ /* TODO: check pending_asts, pending_basts here */
+ list_for_each_safe(iter, tmpiter, &res->granted) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node == dead_node) {
+ list_del_init(&lock->list);
+ dlm_lock_put(lock);
+ }
+ }
+ list_for_each_safe(iter, tmpiter, &res->converting) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node == dead_node) {
+ list_del_init(&lock->list);
+ dlm_lock_put(lock);
+ }
+ }
+ list_for_each_safe(iter, tmpiter, &res->blocked) {
+ lock = list_entry (iter, struct dlm_lock, list);
+ if (lock->ml.node == dead_node) {
+ list_del_init(&lock->list);
+ dlm_lock_put(lock);
+ }
+ }
+
+ /* do not kick thread yet */
+ __dlm_dirty_lockres(dlm, res);
+}
+
+/* if this node is the recovery master, and there are no
+ * locks for a given lockres owned by this node that are in
+ * either PR or EX mode, zero out the lvb before requesting.
+ *
+ */
+
+
+static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ struct list_head *iter;
+ struct dlm_lock_resource *res;
+ int i;
+ struct list_head *bucket;
+
+
+ /* purge any stale mles */
+ dlm_clean_master_list(dlm, dead_node);
+
+ /*
+ * now clean up all lock resources. there are two rules:
+ *
+ * 1) if the dead node was the master, move the lockres
+ * to the recovering list. set the RECOVERING flag.
+ * this lockres needs to be cleaned up before it can
+ * be used further.
+ *
+ * 2) if this node was the master, remove all locks from
+ * each of the lockres queues that were owned by the
+ * dead node. once recovery finishes, the dlm thread
+ * can be kicked again to see if any ASTs or BASTs
+ * need to be fired as a result.
+ */
+ for (i=0; i<DLM_HASH_SIZE; i++) {
+ bucket = &(dlm->resources[i]);
+ list_for_each(iter, bucket) {
+ res = list_entry (iter, struct dlm_lock_resource, list);
+ if (dlm_is_recovery_lock(res->lockname.name,
+ res->lockname.len))
+ continue;
+
+ spin_lock(&res->spinlock);
+ /* zero the lvb if necessary */
+ dlm_revalidate_lvb(dlm, res, dead_node);
+ if (res->owner == dead_node)
+ dlm_move_lockres_to_recovery_list(dlm, res);
+ else if (res->owner == dlm->node_num) {
+ dlm_free_dead_locks(dlm, res, dead_node);
+ __dlm_lockres_calc_usage(dlm, res);
+ }
+ spin_unlock(&res->spinlock);
+ }
+ }
+
+}
+
+static void __dlm_hb_node_down(struct dlm_ctxt *dlm, int idx)
+{
+ assert_spin_locked(&dlm->spinlock);
+
+ /* check to see if the node is already considered dead */
+ if (!test_bit(idx, dlm->live_nodes_map)) {
+ mlog(0, "for domain %s, node %d is already dead. "
+ "another node likely did recovery already.\n",
+ dlm->name, idx);
+ return;
+ }
+
+ /* check to see if we do not care about this node */
+ if (!test_bit(idx, dlm->domain_map)) {
+ /* This also catches the case that we get a node down
+ * but haven't joined the domain yet. */
+ mlog(0, "node %u already removed from domain!\n", idx);
+ return;
+ }
+
+ clear_bit(idx, dlm->live_nodes_map);
+
+ /* Clean up join state on node death. */
+ if (dlm->joining_node == idx) {
+ mlog(0, "Clearing join state for node %u\n", idx);
+ __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
+ }
+
+ /* make sure local cleanup occurs before the heartbeat events */
+ if (!test_bit(idx, dlm->recovery_map))
+ dlm_do_local_recovery_cleanup(dlm, idx);
+
+ /* notify anything attached to the heartbeat events */
+ dlm_hb_event_notify_attached(dlm, idx, 0);
+
+ mlog(0, "node %u being removed from domain map!\n", idx);
+ clear_bit(idx, dlm->domain_map);
+ /* wake up migration waiters if a node goes down.
+ * perhaps later we can genericize this for other waiters. */
+ wake_up(&dlm->migration_wq);
+
+ if (test_bit(idx, dlm->recovery_map))
+ mlog(0, "domain %s, node %u already added "
+ "to recovery map!\n", dlm->name, idx);
+ else
+ set_bit(idx, dlm->recovery_map);
+}
+
+void dlm_hb_node_down_cb(struct o2nm_node *node, int idx, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+
+ if (!dlm_grab(dlm))
+ return;
+
+ spin_lock(&dlm->spinlock);
+ __dlm_hb_node_down(dlm, idx);
+ spin_unlock(&dlm->spinlock);
+
+ dlm_put(dlm);
+}
+
+void dlm_hb_node_up_cb(struct o2nm_node *node, int idx, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+
+ if (!dlm_grab(dlm))
+ return;
+
+ spin_lock(&dlm->spinlock);
+
+ set_bit(idx, dlm->live_nodes_map);
+
+ /* notify any mles attached to the heartbeat events */
+ dlm_hb_event_notify_attached(dlm, idx, 1);
+
+ spin_unlock(&dlm->spinlock);
+
+ dlm_put(dlm);
+}
+
+static void dlm_reco_ast(void *astdata)
+{
+ struct dlm_ctxt *dlm = astdata;
+ mlog(0, "ast for recovery lock fired!, this=%u, dlm=%s\n",
+ dlm->node_num, dlm->name);
+}
+static void dlm_reco_bast(void *astdata, int blocked_type)
+{
+ struct dlm_ctxt *dlm = astdata;
+ mlog(0, "bast for recovery lock fired!, this=%u, dlm=%s\n",
+ dlm->node_num, dlm->name);
+}
+static void dlm_reco_unlock_ast(void *astdata, enum dlm_status st)
+{
+ mlog(0, "unlockast for recovery lock fired!\n");
+}
+
+
+static int dlm_pick_recovery_master(struct dlm_ctxt *dlm)
+{
+ enum dlm_status ret;
+ struct dlm_lockstatus lksb;
+ int status = -EINVAL;
+
+ mlog(0, "starting recovery of %s at %lu, dead=%u, this=%u\n",
+ dlm->name, jiffies, dlm->reco.dead_node, dlm->node_num);
+retry:
+ memset(&lksb, 0, sizeof(lksb));
+
+ ret = dlmlock(dlm, LKM_EXMODE, &lksb, LKM_NOQUEUE|LKM_RECOVERY,
+ DLM_RECOVERY_LOCK_NAME, dlm_reco_ast, dlm, dlm_reco_bast);
+
+ if (ret == DLM_NORMAL) {
+ mlog(0, "dlm=%s dlmlock says I got it (this=%u)\n",
+ dlm->name, dlm->node_num);
+ /* I am master, send message to all nodes saying
+ * that I am beginning a recovery session */
+ status = dlm_send_begin_reco_message(dlm,
+ dlm->reco.dead_node);
+
+ /* recovery lock is a special case. ast will not get fired,
+ * so just go ahead and unlock it. */
+ ret = dlmunlock(dlm, &lksb, 0, dlm_reco_unlock_ast, dlm);
+ if (ret != DLM_NORMAL) {
+ /* this would really suck. this could only happen
+ * if there was a network error during the unlock
+ * because of node death. this means the unlock
+ * is actually "done" and the lock structure is
+ * even freed. we can continue, but only
+ * because this specific lock name is special. */
+ mlog(0, "dlmunlock returned %d\n", ret);
+ }
+
+ if (status < 0) {
+ mlog(0, "failed to send recovery message. "
+ "must retry with new node map.\n");
+ goto retry;
+ }
+ } else if (ret == DLM_NOTQUEUED) {
+ mlog(0, "dlm=%s dlmlock says another node got it (this=%u)\n",
+ dlm->name, dlm->node_num);
+ /* another node is master. wait on
+ * reco.new_master != O2NM_INVALID_NODE_NUM */
+ status = -EEXIST;
+ }
+
+ return status;
+}
+
+static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node)
+{
+ struct dlm_begin_reco br;
+ int ret = 0;
+ struct dlm_node_iter iter;
+ int nodenum;
+ int status;
+
+ mlog_entry("%u\n", dead_node);
+
+ mlog(0, "dead node is %u\n", dead_node);
+
+ spin_lock(&dlm->spinlock);
+ dlm_node_iter_init(dlm->domain_map, &iter);
+ spin_unlock(&dlm->spinlock);
+
+ clear_bit(dead_node, iter.node_map);
+
+ memset(&br, 0, sizeof(br));
+ br.node_idx = dlm->node_num;
+ br.dead_node = dead_node;
+
+ while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
+ ret = 0;
+ if (nodenum == dead_node) {
+ mlog(0, "not sending begin reco to dead node "
+ "%u\n", dead_node);
+ continue;
+ }
+ if (nodenum == dlm->node_num) {
+ mlog(0, "not sending begin reco to self\n");
+ continue;
+ }
+
+ ret = -EINVAL;
+ mlog(0, "attempting to send begin reco msg to %d\n",
+ nodenum);
+ ret = o2net_send_message(DLM_BEGIN_RECO_MSG, dlm->key,
+ &br, sizeof(br), nodenum, &status);
+ /* negative status is handled ok by caller here */
+ if (ret >= 0)
+ ret = status;
+ if (ret < 0) {
+ struct dlm_lock_resource *res;
+ mlog_errno(ret);
+ mlog(ML_ERROR, "begin reco of dlm %s to node %u "
+ " returned %d\n", dlm->name, nodenum, ret);
+ res = dlm_lookup_lockres(dlm, DLM_RECOVERY_LOCK_NAME,
+ DLM_RECOVERY_LOCK_NAME_LEN);
+ if (res) {
+ dlm_print_one_lock_resource(res);
+ dlm_lockres_put(res);
+ } else {
+ mlog(ML_ERROR, "recovery lock not found\n");
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_begin_reco *br = (struct dlm_begin_reco *)msg->buf;
+
+ /* ok to return 0, domain has gone away */
+ if (!dlm_grab(dlm))
+ return 0;
+
+ mlog(0, "node %u wants to recover node %u\n",
+ br->node_idx, br->dead_node);
+
+ dlm_fire_domain_eviction_callbacks(dlm, br->dead_node);
+
+ spin_lock(&dlm->spinlock);
+ if (dlm->reco.new_master != O2NM_INVALID_NODE_NUM) {
+ mlog(0, "new_master already set to %u!\n",
+ dlm->reco.new_master);
+ }
+ if (dlm->reco.dead_node != O2NM_INVALID_NODE_NUM) {
+ mlog(0, "dead_node already set to %u!\n",
+ dlm->reco.dead_node);
+ }
+ dlm->reco.new_master = br->node_idx;
+ dlm->reco.dead_node = br->dead_node;
+ if (!test_bit(br->dead_node, dlm->recovery_map)) {
+ mlog(ML_ERROR, "recovery master %u sees %u as dead, but this "
+ "node has not yet. marking %u as dead\n",
+ br->node_idx, br->dead_node, br->dead_node);
+ __dlm_hb_node_down(dlm, br->dead_node);
+ }
+ spin_unlock(&dlm->spinlock);
+
+ dlm_kick_recovery_thread(dlm);
+ dlm_put(dlm);
+ return 0;
+}
+
+static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm)
+{
+ int ret = 0;
+ struct dlm_finalize_reco fr;
+ struct dlm_node_iter iter;
+ int nodenum;
+ int status;
+
+ mlog(0, "finishing recovery for node %s:%u\n",
+ dlm->name, dlm->reco.dead_node);
+
+ spin_lock(&dlm->spinlock);
+ dlm_node_iter_init(dlm->domain_map, &iter);
+ spin_unlock(&dlm->spinlock);
+
+ memset(&fr, 0, sizeof(fr));
+ fr.node_idx = dlm->node_num;
+ fr.dead_node = dlm->reco.dead_node;
+
+ while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
+ if (nodenum == dlm->node_num)
+ continue;
+ ret = o2net_send_message(DLM_FINALIZE_RECO_MSG, dlm->key,
+ &fr, sizeof(fr), nodenum, &status);
+ if (ret >= 0) {
+ ret = status;
+ if (dlm_is_host_down(ret)) {
+ /* this has no effect on this recovery
+ * session, so set the status to zero to
+ * finish out the last recovery */
+ mlog(ML_ERROR, "node %u went down after this "
+ "node finished recovery.\n", nodenum);
+ ret = 0;
+ }
+ }
+ if (ret < 0) {
+ mlog_errno(ret);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_finalize_reco *fr = (struct dlm_finalize_reco *)msg->buf;
+
+ /* ok to return 0, domain has gone away */
+ if (!dlm_grab(dlm))
+ return 0;
+
+ mlog(0, "node %u finalizing recovery of node %u\n",
+ fr->node_idx, fr->dead_node);
+
+ spin_lock(&dlm->spinlock);
+
+ if (dlm->reco.new_master != fr->node_idx) {
+ mlog(ML_ERROR, "node %u sent recovery finalize msg, but node "
+ "%u is supposed to be the new master, dead=%u\n",
+ fr->node_idx, dlm->reco.new_master, fr->dead_node);
+ BUG();
+ }
+ if (dlm->reco.dead_node != fr->dead_node) {
+ mlog(ML_ERROR, "node %u sent recovery finalize msg for dead "
+ "node %u, but node %u is supposed to be dead\n",
+ fr->node_idx, fr->dead_node, dlm->reco.dead_node);
+ BUG();
+ }
+
+ dlm_finish_local_lockres_recovery(dlm, fr->dead_node, fr->node_idx);
+
+ spin_unlock(&dlm->spinlock);
+
+ dlm_reset_recovery(dlm);
+
+ dlm_kick_recovery_thread(dlm);
+ dlm_put(dlm);
+ return 0;
+}
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
new file mode 100644
index 000000000000..5be9d14f12cb
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -0,0 +1,692 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmthread.c
+ *
+ * standalone DLM module
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/timer.h>
+#include <linux/kthread.h>
+
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+#include "dlmdomain.h"
+
+#define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_THREAD)
+#include "cluster/masklog.h"
+
+static int dlm_thread(void *data);
+
+static void dlm_flush_asts(struct dlm_ctxt *dlm);
+
+#define dlm_lock_is_remote(dlm, lock) ((lock)->ml.node != (dlm)->node_num)
+
+/* will exit holding res->spinlock, but may drop in function */
+/* waits until flags are cleared on res->state */
+void __dlm_wait_on_lockres_flags(struct dlm_lock_resource *res, int flags)
+{
+ DECLARE_WAITQUEUE(wait, current);
+
+ assert_spin_locked(&res->spinlock);
+
+ add_wait_queue(&res->wq, &wait);
+repeat:
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (res->state & flags) {
+ spin_unlock(&res->spinlock);
+ schedule();
+ spin_lock(&res->spinlock);
+ goto repeat;
+ }
+ remove_wait_queue(&res->wq, &wait);
+ current->state = TASK_RUNNING;
+}
+
+
+static int __dlm_lockres_unused(struct dlm_lock_resource *res)
+{
+ if (list_empty(&res->granted) &&
+ list_empty(&res->converting) &&
+ list_empty(&res->blocked) &&
+ list_empty(&res->dirty))
+ return 1;
+ return 0;
+}
+
+
+/* Call whenever you may have added or deleted something from one of
+ * the lockres queue's. This will figure out whether it belongs on the
+ * unused list or not and does the appropriate thing. */
+void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&res->spinlock);
+
+ if (__dlm_lockres_unused(res)){
+ if (list_empty(&res->purge)) {
+ mlog(0, "putting lockres %.*s from purge list\n",
+ res->lockname.len, res->lockname.name);
+
+ res->last_used = jiffies;
+ list_add_tail(&res->purge, &dlm->purge_list);
+ dlm->purge_count++;
+ }
+ } else if (!list_empty(&res->purge)) {
+ mlog(0, "removing lockres %.*s from purge list\n",
+ res->lockname.len, res->lockname.name);
+
+ list_del_init(&res->purge);
+ dlm->purge_count--;
+ }
+}
+
+void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+ spin_lock(&dlm->spinlock);
+ spin_lock(&res->spinlock);
+
+ __dlm_lockres_calc_usage(dlm, res);
+
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+}
+
+/* TODO: Eventual API: Called with the dlm spinlock held, may drop it
+ * to do migration, but will re-acquire before exit. */
+void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *lockres)
+{
+ int master;
+ int ret;
+
+ spin_lock(&lockres->spinlock);
+ master = lockres->owner == dlm->node_num;
+ spin_unlock(&lockres->spinlock);
+
+ mlog(0, "purging lockres %.*s, master = %d\n", lockres->lockname.len,
+ lockres->lockname.name, master);
+
+ /* Non master is the easy case -- no migration required, just
+ * quit. */
+ if (!master)
+ goto finish;
+
+ /* Wheee! Migrate lockres here! */
+ spin_unlock(&dlm->spinlock);
+again:
+
+ ret = dlm_migrate_lockres(dlm, lockres, O2NM_MAX_NODES);
+ if (ret == -ENOTEMPTY) {
+ mlog(ML_ERROR, "lockres %.*s still has local locks!\n",
+ lockres->lockname.len, lockres->lockname.name);
+
+ BUG();
+ } else if (ret < 0) {
+ mlog(ML_NOTICE, "lockres %.*s: migrate failed, retrying\n",
+ lockres->lockname.len, lockres->lockname.name);
+ goto again;
+ }
+
+ spin_lock(&dlm->spinlock);
+
+finish:
+ if (!list_empty(&lockres->purge)) {
+ list_del_init(&lockres->purge);
+ dlm->purge_count--;
+ }
+ __dlm_unhash_lockres(lockres);
+}
+
+static void dlm_run_purge_list(struct dlm_ctxt *dlm,
+ int purge_now)
+{
+ unsigned int run_max, unused;
+ unsigned long purge_jiffies;
+ struct dlm_lock_resource *lockres;
+
+ spin_lock(&dlm->spinlock);
+ run_max = dlm->purge_count;
+
+ while(run_max && !list_empty(&dlm->purge_list)) {
+ run_max--;
+
+ lockres = list_entry(dlm->purge_list.next,
+ struct dlm_lock_resource, purge);
+
+ /* Status of the lockres *might* change so double
+ * check. If the lockres is unused, holding the dlm
+ * spinlock will prevent people from getting and more
+ * refs on it -- there's no need to keep the lockres
+ * spinlock. */
+ spin_lock(&lockres->spinlock);
+ unused = __dlm_lockres_unused(lockres);
+ spin_unlock(&lockres->spinlock);
+
+ if (!unused)
+ continue;
+
+ purge_jiffies = lockres->last_used +
+ msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);
+
+ /* Make sure that we want to be processing this guy at
+ * this time. */
+ if (!purge_now && time_after(purge_jiffies, jiffies)) {
+ /* Since resources are added to the purge list
+ * in tail order, we can stop at the first
+ * unpurgable resource -- anyone added after
+ * him will have a greater last_used value */
+ break;
+ }
+
+ list_del_init(&lockres->purge);
+ dlm->purge_count--;
+
+ /* This may drop and reacquire the dlm spinlock if it
+ * has to do migration. */
+ mlog(0, "calling dlm_purge_lockres!\n");
+ dlm_purge_lockres(dlm, lockres);
+ mlog(0, "DONE calling dlm_purge_lockres!\n");
+
+ /* Avoid adding any scheduling latencies */
+ cond_resched_lock(&dlm->spinlock);
+ }
+
+ spin_unlock(&dlm->spinlock);
+}
+
+static void dlm_shuffle_lists(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res)
+{
+ struct dlm_lock *lock, *target;
+ struct list_head *iter;
+ struct list_head *head;
+ int can_grant = 1;
+
+ //mlog(0, "res->lockname.len=%d\n", res->lockname.len);
+ //mlog(0, "res->lockname.name=%p\n", res->lockname.name);
+ //mlog(0, "shuffle res %.*s\n", res->lockname.len,
+ // res->lockname.name);
+
+ /* because this function is called with the lockres
+ * spinlock, and because we know that it is not migrating/
+ * recovering/in-progress, it is fine to reserve asts and
+ * basts right before queueing them all throughout */
+ assert_spin_locked(&res->spinlock);
+ BUG_ON((res->state & (DLM_LOCK_RES_MIGRATING|
+ DLM_LOCK_RES_RECOVERING|
+ DLM_LOCK_RES_IN_PROGRESS)));
+
+converting:
+ if (list_empty(&res->converting))
+ goto blocked;
+ mlog(0, "res %.*s has locks on a convert queue\n", res->lockname.len,
+ res->lockname.name);
+
+ target = list_entry(res->converting.next, struct dlm_lock, list);
+ if (target->ml.convert_type == LKM_IVMODE) {
+ mlog(ML_ERROR, "%.*s: converting a lock with no "
+ "convert_type!\n", res->lockname.len, res->lockname.name);
+ BUG();
+ }
+ head = &res->granted;
+ list_for_each(iter, head) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock==target)
+ continue;
+ if (!dlm_lock_compatible(lock->ml.type,
+ target->ml.convert_type)) {
+ can_grant = 0;
+ /* queue the BAST if not already */
+ if (lock->ml.highest_blocked == LKM_IVMODE) {
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_bast(dlm, lock);
+ }
+ /* update the highest_blocked if needed */
+ if (lock->ml.highest_blocked < target->ml.convert_type)
+ lock->ml.highest_blocked =
+ target->ml.convert_type;
+ }
+ }
+ head = &res->converting;
+ list_for_each(iter, head) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock==target)
+ continue;
+ if (!dlm_lock_compatible(lock->ml.type,
+ target->ml.convert_type)) {
+ can_grant = 0;
+ if (lock->ml.highest_blocked == LKM_IVMODE) {
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_bast(dlm, lock);
+ }
+ if (lock->ml.highest_blocked < target->ml.convert_type)
+ lock->ml.highest_blocked =
+ target->ml.convert_type;
+ }
+ }
+
+ /* we can convert the lock */
+ if (can_grant) {
+ spin_lock(&target->spinlock);
+ BUG_ON(target->ml.highest_blocked != LKM_IVMODE);
+
+ mlog(0, "calling ast for converting lock: %.*s, have: %d, "
+ "granting: %d, node: %u\n", res->lockname.len,
+ res->lockname.name, target->ml.type,
+ target->ml.convert_type, target->ml.node);
+
+ target->ml.type = target->ml.convert_type;
+ target->ml.convert_type = LKM_IVMODE;
+ list_del_init(&target->list);
+ list_add_tail(&target->list, &res->granted);
+
+ BUG_ON(!target->lksb);
+ target->lksb->status = DLM_NORMAL;
+
+ spin_unlock(&target->spinlock);
+
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_ast(dlm, target);
+ /* go back and check for more */
+ goto converting;
+ }
+
+blocked:
+ if (list_empty(&res->blocked))
+ goto leave;
+ target = list_entry(res->blocked.next, struct dlm_lock, list);
+
+ head = &res->granted;
+ list_for_each(iter, head) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock==target)
+ continue;
+ if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
+ can_grant = 0;
+ if (lock->ml.highest_blocked == LKM_IVMODE) {
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_bast(dlm, lock);
+ }
+ if (lock->ml.highest_blocked < target->ml.type)
+ lock->ml.highest_blocked = target->ml.type;
+ }
+ }
+
+ head = &res->converting;
+ list_for_each(iter, head) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock==target)
+ continue;
+ if (!dlm_lock_compatible(lock->ml.type, target->ml.type)) {
+ can_grant = 0;
+ if (lock->ml.highest_blocked == LKM_IVMODE) {
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_bast(dlm, lock);
+ }
+ if (lock->ml.highest_blocked < target->ml.type)
+ lock->ml.highest_blocked = target->ml.type;
+ }
+ }
+
+ /* we can grant the blocked lock (only
+ * possible if converting list empty) */
+ if (can_grant) {
+ spin_lock(&target->spinlock);
+ BUG_ON(target->ml.highest_blocked != LKM_IVMODE);
+
+ mlog(0, "calling ast for blocked lock: %.*s, granting: %d, "
+ "node: %u\n", res->lockname.len, res->lockname.name,
+ target->ml.type, target->ml.node);
+
+ // target->ml.type is already correct
+ list_del_init(&target->list);
+ list_add_tail(&target->list, &res->granted);
+
+ BUG_ON(!target->lksb);
+ target->lksb->status = DLM_NORMAL;
+
+ spin_unlock(&target->spinlock);
+
+ __dlm_lockres_reserve_ast(res);
+ dlm_queue_ast(dlm, target);
+ /* go back and check for more */
+ goto converting;
+ }
+
+leave:
+ return;
+}
+
+/* must have NO locks when calling this with res !=NULL * */
+void dlm_kick_thread(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
+{
+ mlog_entry("dlm=%p, res=%p\n", dlm, res);
+ if (res) {
+ spin_lock(&dlm->spinlock);
+ spin_lock(&res->spinlock);
+ __dlm_dirty_lockres(dlm, res);
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+ }
+ wake_up(&dlm->dlm_thread_wq);
+}
+
+void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
+{
+ mlog_entry("dlm=%p, res=%p\n", dlm, res);
+
+ assert_spin_locked(&dlm->spinlock);
+ assert_spin_locked(&res->spinlock);
+
+ /* don't shuffle secondary queues */
+ if ((res->owner == dlm->node_num) &&
+ !(res->state & DLM_LOCK_RES_DIRTY)) {
+ list_add_tail(&res->dirty, &dlm->dirty_list);
+ res->state |= DLM_LOCK_RES_DIRTY;
+ }
+}
+
+
+/* Launch the NM thread for the mounted volume */
+int dlm_launch_thread(struct dlm_ctxt *dlm)
+{
+ mlog(0, "starting dlm thread...\n");
+
+ dlm->dlm_thread_task = kthread_run(dlm_thread, dlm, "dlm_thread");
+ if (IS_ERR(dlm->dlm_thread_task)) {
+ mlog_errno(PTR_ERR(dlm->dlm_thread_task));
+ dlm->dlm_thread_task = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void dlm_complete_thread(struct dlm_ctxt *dlm)
+{
+ if (dlm->dlm_thread_task) {
+ mlog(ML_KTHREAD, "waiting for dlm thread to exit\n");
+ kthread_stop(dlm->dlm_thread_task);
+ dlm->dlm_thread_task = NULL;
+ }
+}
+
+static int dlm_dirty_list_empty(struct dlm_ctxt *dlm)
+{
+ int empty;
+
+ spin_lock(&dlm->spinlock);
+ empty = list_empty(&dlm->dirty_list);
+ spin_unlock(&dlm->spinlock);
+
+ return empty;
+}
+
+static void dlm_flush_asts(struct dlm_ctxt *dlm)
+{
+ int ret;
+ struct dlm_lock *lock;
+ struct dlm_lock_resource *res;
+ u8 hi;
+
+ spin_lock(&dlm->ast_lock);
+ while (!list_empty(&dlm->pending_asts)) {
+ lock = list_entry(dlm->pending_asts.next,
+ struct dlm_lock, ast_list);
+ /* get an extra ref on lock */
+ dlm_lock_get(lock);
+ res = lock->lockres;
+ mlog(0, "delivering an ast for this lockres\n");
+
+ BUG_ON(!lock->ast_pending);
+
+ /* remove from list (including ref) */
+ list_del_init(&lock->ast_list);
+ dlm_lock_put(lock);
+ spin_unlock(&dlm->ast_lock);
+
+ if (lock->ml.node != dlm->node_num) {
+ ret = dlm_do_remote_ast(dlm, res, lock);
+ if (ret < 0)
+ mlog_errno(ret);
+ } else
+ dlm_do_local_ast(dlm, res, lock);
+
+ spin_lock(&dlm->ast_lock);
+
+ /* possible that another ast was queued while
+ * we were delivering the last one */
+ if (!list_empty(&lock->ast_list)) {
+ mlog(0, "aha another ast got queued while "
+ "we were finishing the last one. will "
+ "keep the ast_pending flag set.\n");
+ } else
+ lock->ast_pending = 0;
+
+ /* drop the extra ref.
+ * this may drop it completely. */
+ dlm_lock_put(lock);
+ dlm_lockres_release_ast(dlm, res);
+ }
+
+ while (!list_empty(&dlm->pending_basts)) {
+ lock = list_entry(dlm->pending_basts.next,
+ struct dlm_lock, bast_list);
+ /* get an extra ref on lock */
+ dlm_lock_get(lock);
+ res = lock->lockres;
+
+ BUG_ON(!lock->bast_pending);
+
+ /* get the highest blocked lock, and reset */
+ spin_lock(&lock->spinlock);
+ BUG_ON(lock->ml.highest_blocked <= LKM_IVMODE);
+ hi = lock->ml.highest_blocked;
+ lock->ml.highest_blocked = LKM_IVMODE;
+ spin_unlock(&lock->spinlock);
+
+ /* remove from list (including ref) */
+ list_del_init(&lock->bast_list);
+ dlm_lock_put(lock);
+ spin_unlock(&dlm->ast_lock);
+
+ mlog(0, "delivering a bast for this lockres "
+ "(blocked = %d\n", hi);
+
+ if (lock->ml.node != dlm->node_num) {
+ ret = dlm_send_proxy_bast(dlm, res, lock, hi);
+ if (ret < 0)
+ mlog_errno(ret);
+ } else
+ dlm_do_local_bast(dlm, res, lock, hi);
+
+ spin_lock(&dlm->ast_lock);
+
+ /* possible that another bast was queued while
+ * we were delivering the last one */
+ if (!list_empty(&lock->bast_list)) {
+ mlog(0, "aha another bast got queued while "
+ "we were finishing the last one. will "
+ "keep the bast_pending flag set.\n");
+ } else
+ lock->bast_pending = 0;
+
+ /* drop the extra ref.
+ * this may drop it completely. */
+ dlm_lock_put(lock);
+ dlm_lockres_release_ast(dlm, res);
+ }
+ wake_up(&dlm->ast_wq);
+ spin_unlock(&dlm->ast_lock);
+}
+
+
+#define DLM_THREAD_TIMEOUT_MS (4 * 1000)
+#define DLM_THREAD_MAX_DIRTY 100
+#define DLM_THREAD_MAX_ASTS 10
+
+static int dlm_thread(void *data)
+{
+ struct dlm_lock_resource *res;
+ struct dlm_ctxt *dlm = data;
+ unsigned long timeout = msecs_to_jiffies(DLM_THREAD_TIMEOUT_MS);
+
+ mlog(0, "dlm thread running for %s...\n", dlm->name);
+
+ while (!kthread_should_stop()) {
+ int n = DLM_THREAD_MAX_DIRTY;
+
+ /* dlm_shutting_down is very point-in-time, but that
+ * doesn't matter as we'll just loop back around if we
+ * get false on the leading edge of a state
+ * transition. */
+ dlm_run_purge_list(dlm, dlm_shutting_down(dlm));
+
+ /* We really don't want to hold dlm->spinlock while
+ * calling dlm_shuffle_lists on each lockres that
+ * needs to have its queues adjusted and AST/BASTs
+ * run. So let's pull each entry off the dirty_list
+ * and drop dlm->spinlock ASAP. Once off the list,
+ * res->spinlock needs to be taken again to protect
+ * the queues while calling dlm_shuffle_lists. */
+ spin_lock(&dlm->spinlock);
+ while (!list_empty(&dlm->dirty_list)) {
+ int delay = 0;
+ res = list_entry(dlm->dirty_list.next,
+ struct dlm_lock_resource, dirty);
+
+ /* peel a lockres off, remove it from the list,
+ * unset the dirty flag and drop the dlm lock */
+ BUG_ON(!res);
+ dlm_lockres_get(res);
+
+ spin_lock(&res->spinlock);
+ res->state &= ~DLM_LOCK_RES_DIRTY;
+ list_del_init(&res->dirty);
+ spin_unlock(&res->spinlock);
+ spin_unlock(&dlm->spinlock);
+
+ /* lockres can be re-dirtied/re-added to the
+ * dirty_list in this gap, but that is ok */
+
+ spin_lock(&res->spinlock);
+ if (res->owner != dlm->node_num) {
+ __dlm_print_one_lock_resource(res);
+ mlog(ML_ERROR, "inprog:%s, mig:%s, reco:%s, dirty:%s\n",
+ res->state & DLM_LOCK_RES_IN_PROGRESS ? "yes" : "no",
+ res->state & DLM_LOCK_RES_MIGRATING ? "yes" : "no",
+ res->state & DLM_LOCK_RES_RECOVERING ? "yes" : "no",
+ res->state & DLM_LOCK_RES_DIRTY ? "yes" : "no");
+ }
+ BUG_ON(res->owner != dlm->node_num);
+
+ /* it is now ok to move lockreses in these states
+ * to the dirty list, assuming that they will only be
+ * dirty for a short while. */
+ if (res->state & (DLM_LOCK_RES_IN_PROGRESS |
+ DLM_LOCK_RES_MIGRATING |
+ DLM_LOCK_RES_RECOVERING)) {
+ /* move it to the tail and keep going */
+ spin_unlock(&res->spinlock);
+ mlog(0, "delaying list shuffling for in-"
+ "progress lockres %.*s, state=%d\n",
+ res->lockname.len, res->lockname.name,
+ res->state);
+ delay = 1;
+ goto in_progress;
+ }
+
+ /* at this point the lockres is not migrating/
+ * recovering/in-progress. we have the lockres
+ * spinlock and do NOT have the dlm lock.
+ * safe to reserve/queue asts and run the lists. */
+
+ mlog(0, "calling dlm_shuffle_lists with dlm=%p, "
+ "res=%p\n", dlm, res);
+
+ /* called while holding lockres lock */
+ dlm_shuffle_lists(dlm, res);
+ spin_unlock(&res->spinlock);
+
+ dlm_lockres_calc_usage(dlm, res);
+
+in_progress:
+
+ spin_lock(&dlm->spinlock);
+ /* if the lock was in-progress, stick
+ * it on the back of the list */
+ if (delay) {
+ spin_lock(&res->spinlock);
+ list_add_tail(&res->dirty, &dlm->dirty_list);
+ res->state |= DLM_LOCK_RES_DIRTY;
+ spin_unlock(&res->spinlock);
+ }
+ dlm_lockres_put(res);
+
+ /* unlikely, but we may need to give time to
+ * other tasks */
+ if (!--n) {
+ mlog(0, "throttling dlm_thread\n");
+ break;
+ }
+ }
+
+ spin_unlock(&dlm->spinlock);
+ dlm_flush_asts(dlm);
+
+ /* yield and continue right away if there is more work to do */
+ if (!n) {
+ yield();
+ continue;
+ }
+
+ wait_event_interruptible_timeout(dlm->dlm_thread_wq,
+ !dlm_dirty_list_empty(dlm) ||
+ kthread_should_stop(),
+ timeout);
+ }
+
+ mlog(0, "quitting DLM thread\n");
+ return 0;
+}
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
new file mode 100644
index 000000000000..cec2ce1cd318
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -0,0 +1,672 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmunlock.c
+ *
+ * underlying calls for unlocking locks
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/random.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include "cluster/heartbeat.h"
+#include "cluster/nodemanager.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+#include "dlmcommon.h"
+
+#define MLOG_MASK_PREFIX ML_DLM
+#include "cluster/masklog.h"
+
+#define DLM_UNLOCK_FREE_LOCK 0x00000001
+#define DLM_UNLOCK_CALL_AST 0x00000002
+#define DLM_UNLOCK_REMOVE_LOCK 0x00000004
+#define DLM_UNLOCK_REGRANT_LOCK 0x00000008
+#define DLM_UNLOCK_CLEAR_CONVERT_TYPE 0x00000010
+
+
+static enum dlm_status dlm_get_cancel_actions(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int *actions);
+static enum dlm_status dlm_get_unlock_actions(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int *actions);
+
+static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int flags,
+ u8 owner);
+
+
+/*
+ * according to the spec:
+ * http://opendlm.sourceforge.net/cvsmirror/opendlm/docs/dlmbook_final.pdf
+ *
+ * flags & LKM_CANCEL != 0: must be converting or blocked
+ * flags & LKM_CANCEL == 0: must be granted
+ *
+ * So to unlock a converting lock, you must first cancel the
+ * convert (passing LKM_CANCEL in flags), then call the unlock
+ * again (with no LKM_CANCEL in flags).
+ */
+
+
+/*
+ * locking:
+ * caller needs: none
+ * taken: res->spinlock and lock->spinlock taken and dropped
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_NOLOCKMGR, status from network
+ * all callers should have taken an extra ref on lock coming in
+ */
+static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int flags, int *call_ast,
+ int master_node)
+{
+ enum dlm_status status;
+ int actions = 0;
+ int in_use;
+ u8 owner;
+
+ mlog(0, "master_node = %d, valblk = %d\n", master_node,
+ flags & LKM_VALBLK);
+
+ if (master_node)
+ BUG_ON(res->owner != dlm->node_num);
+ else
+ BUG_ON(res->owner == dlm->node_num);
+
+ spin_lock(&dlm->spinlock);
+ /* We want to be sure that we're not freeing a lock
+ * that still has AST's pending... */
+ in_use = !list_empty(&lock->ast_list);
+ spin_unlock(&dlm->spinlock);
+ if (in_use) {
+ mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock "
+ "while waiting for an ast!", res->lockname.len,
+ res->lockname.name);
+ return DLM_BADPARAM;
+ }
+
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_IN_PROGRESS) {
+ if (master_node) {
+ mlog(ML_ERROR, "lockres in progress!\n");
+ spin_unlock(&res->spinlock);
+ return DLM_FORWARD;
+ }
+ /* ok for this to sleep if not in a network handler */
+ __dlm_wait_on_lockres(res);
+ res->state |= DLM_LOCK_RES_IN_PROGRESS;
+ }
+ spin_lock(&lock->spinlock);
+
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ status = DLM_RECOVERING;
+ goto leave;
+ }
+
+
+ /* see above for what the spec says about
+ * LKM_CANCEL and the lock queue state */
+ if (flags & LKM_CANCEL)
+ status = dlm_get_cancel_actions(dlm, res, lock, lksb, &actions);
+ else
+ status = dlm_get_unlock_actions(dlm, res, lock, lksb, &actions);
+
+ if (status != DLM_NORMAL)
+ goto leave;
+
+ /* By now this has been masked out of cancel requests. */
+ if (flags & LKM_VALBLK) {
+ /* make the final update to the lvb */
+ if (master_node)
+ memcpy(res->lvb, lksb->lvb, DLM_LVB_LEN);
+ else
+ flags |= LKM_PUT_LVB; /* let the send function
+ * handle it. */
+ }
+
+ if (!master_node) {
+ owner = res->owner;
+ /* drop locks and send message */
+ if (flags & LKM_CANCEL)
+ lock->cancel_pending = 1;
+ else
+ lock->unlock_pending = 1;
+ spin_unlock(&lock->spinlock);
+ spin_unlock(&res->spinlock);
+ status = dlm_send_remote_unlock_request(dlm, res, lock, lksb,
+ flags, owner);
+ spin_lock(&res->spinlock);
+ spin_lock(&lock->spinlock);
+ /* if the master told us the lock was already granted,
+ * let the ast handle all of these actions */
+ if (status == DLM_NORMAL &&
+ lksb->status == DLM_CANCELGRANT) {
+ actions &= ~(DLM_UNLOCK_REMOVE_LOCK|
+ DLM_UNLOCK_REGRANT_LOCK|
+ DLM_UNLOCK_CLEAR_CONVERT_TYPE);
+ }
+ if (flags & LKM_CANCEL)
+ lock->cancel_pending = 0;
+ else
+ lock->unlock_pending = 0;
+
+ }
+
+ /* get an extra ref on lock. if we are just switching
+ * lists here, we dont want the lock to go away. */
+ dlm_lock_get(lock);
+
+ if (actions & DLM_UNLOCK_REMOVE_LOCK) {
+ list_del_init(&lock->list);
+ dlm_lock_put(lock);
+ }
+ if (actions & DLM_UNLOCK_REGRANT_LOCK) {
+ dlm_lock_get(lock);
+ list_add_tail(&lock->list, &res->granted);
+ }
+ if (actions & DLM_UNLOCK_CLEAR_CONVERT_TYPE) {
+ mlog(0, "clearing convert_type at %smaster node\n",
+ master_node ? "" : "non-");
+ lock->ml.convert_type = LKM_IVMODE;
+ }
+
+ /* remove the extra ref on lock */
+ dlm_lock_put(lock);
+
+leave:
+ res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
+ if (!dlm_lock_on_list(&res->converting, lock))
+ BUG_ON(lock->ml.convert_type != LKM_IVMODE);
+ else
+ BUG_ON(lock->ml.convert_type == LKM_IVMODE);
+ spin_unlock(&lock->spinlock);
+ spin_unlock(&res->spinlock);
+ wake_up(&res->wq);
+
+ /* let the caller's final dlm_lock_put handle the actual kfree */
+ if (actions & DLM_UNLOCK_FREE_LOCK) {
+ /* this should always be coupled with list removal */
+ BUG_ON(!(actions & DLM_UNLOCK_REMOVE_LOCK));
+ mlog(0, "lock %"MLFu64" should be gone now! refs=%d\n",
+ lock->ml.cookie, atomic_read(&lock->lock_refs.refcount)-1);
+ dlm_lock_put(lock);
+ }
+ if (actions & DLM_UNLOCK_CALL_AST)
+ *call_ast = 1;
+
+ /* if cancel or unlock succeeded, lvb work is done */
+ if (status == DLM_NORMAL)
+ lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB);
+
+ return status;
+}
+
+void dlm_commit_pending_unlock(struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ /* leave DLM_LKSB_PUT_LVB on the lksb so any final
+ * update of the lvb will be sent to the new master */
+ list_del_init(&lock->list);
+}
+
+void dlm_commit_pending_cancel(struct dlm_lock_resource *res,
+ struct dlm_lock *lock)
+{
+ list_del_init(&lock->list);
+ list_add_tail(&lock->list, &res->granted);
+ lock->ml.convert_type = LKM_IVMODE;
+}
+
+
+static inline enum dlm_status dlmunlock_master(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int flags,
+ int *call_ast)
+{
+ return dlmunlock_common(dlm, res, lock, lksb, flags, call_ast, 1);
+}
+
+static inline enum dlm_status dlmunlock_remote(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int flags, int *call_ast)
+{
+ return dlmunlock_common(dlm, res, lock, lksb, flags, call_ast, 0);
+}
+
+/*
+ * locking:
+ * caller needs: none
+ * taken: none
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_NOLOCKMGR, status from network
+ */
+static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int flags,
+ u8 owner)
+{
+ struct dlm_unlock_lock unlock;
+ int tmpret;
+ enum dlm_status ret;
+ int status = 0;
+ struct kvec vec[2];
+ size_t veclen = 1;
+
+ mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
+
+ memset(&unlock, 0, sizeof(unlock));
+ unlock.node_idx = dlm->node_num;
+ unlock.flags = cpu_to_be32(flags);
+ unlock.cookie = lock->ml.cookie;
+ unlock.namelen = res->lockname.len;
+ memcpy(unlock.name, res->lockname.name, unlock.namelen);
+
+ vec[0].iov_len = sizeof(struct dlm_unlock_lock);
+ vec[0].iov_base = &unlock;
+
+ if (flags & LKM_PUT_LVB) {
+ /* extra data to send if we are updating lvb */
+ vec[1].iov_len = DLM_LVB_LEN;
+ vec[1].iov_base = lock->lksb->lvb;
+ veclen++;
+ }
+
+ tmpret = o2net_send_message_vec(DLM_UNLOCK_LOCK_MSG, dlm->key,
+ vec, veclen, owner, &status);
+ if (tmpret >= 0) {
+ // successfully sent and received
+ if (status == DLM_CANCELGRANT)
+ ret = DLM_NORMAL;
+ else if (status == DLM_FORWARD) {
+ mlog(0, "master was in-progress. retry\n");
+ ret = DLM_FORWARD;
+ } else
+ ret = status;
+ lksb->status = status;
+ } else {
+ mlog_errno(tmpret);
+ if (dlm_is_host_down(tmpret)) {
+ /* NOTE: this seems strange, but it is what we want.
+ * when the master goes down during a cancel or
+ * unlock, the recovery code completes the operation
+ * as if the master had not died, then passes the
+ * updated state to the recovery master. this thread
+ * just needs to finish out the operation and call
+ * the unlockast. */
+ ret = DLM_NORMAL;
+ } else {
+ /* something bad. this will BUG in ocfs2 */
+ ret = dlm_err_to_dlm_status(tmpret);
+ }
+ lksb->status = ret;
+ }
+
+ return ret;
+}
+
+/*
+ * locking:
+ * caller needs: none
+ * taken: takes and drops res->spinlock
+ * held on exit: none
+ * returns: DLM_NORMAL, DLM_BADARGS, DLM_IVLOCKID,
+ * return value from dlmunlock_master
+ */
+int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data)
+{
+ struct dlm_ctxt *dlm = data;
+ struct dlm_unlock_lock *unlock = (struct dlm_unlock_lock *)msg->buf;
+ struct dlm_lock_resource *res = NULL;
+ struct list_head *iter;
+ struct dlm_lock *lock = NULL;
+ enum dlm_status status = DLM_NORMAL;
+ int found = 0, i;
+ struct dlm_lockstatus *lksb = NULL;
+ int ignore;
+ u32 flags;
+ struct list_head *queue;
+
+ flags = be32_to_cpu(unlock->flags);
+
+ if (flags & LKM_GET_LVB) {
+ mlog(ML_ERROR, "bad args! GET_LVB specified on unlock!\n");
+ return DLM_BADARGS;
+ }
+
+ if ((flags & (LKM_PUT_LVB|LKM_CANCEL)) == (LKM_PUT_LVB|LKM_CANCEL)) {
+ mlog(ML_ERROR, "bad args! cannot modify lvb on a CANCEL "
+ "request!\n");
+ return DLM_BADARGS;
+ }
+
+ if (unlock->namelen > DLM_LOCKID_NAME_MAX) {
+ mlog(ML_ERROR, "Invalid name length in unlock handler!\n");
+ return DLM_IVBUFLEN;
+ }
+
+ if (!dlm_grab(dlm))
+ return DLM_REJECTED;
+
+ mlog_bug_on_msg(!dlm_domain_fully_joined(dlm),
+ "Domain %s not fully joined!\n", dlm->name);
+
+ mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" : "none");
+
+ res = dlm_lookup_lockres(dlm, unlock->name, unlock->namelen);
+ if (!res) {
+ /* We assume here that a no lock resource simply means
+ * it was migrated away and destroyed before the other
+ * node could detect it. */
+ mlog(0, "returning DLM_FORWARD -- res no longer exists\n");
+ status = DLM_FORWARD;
+ goto not_found;
+ }
+
+ queue=&res->granted;
+ found = 0;
+ spin_lock(&res->spinlock);
+ if (res->state & DLM_LOCK_RES_RECOVERING) {
+ spin_unlock(&res->spinlock);
+ mlog(0, "returning DLM_RECOVERING\n");
+ status = DLM_RECOVERING;
+ goto leave;
+ }
+
+ if (res->state & DLM_LOCK_RES_MIGRATING) {
+ spin_unlock(&res->spinlock);
+ mlog(0, "returning DLM_MIGRATING\n");
+ status = DLM_MIGRATING;
+ goto leave;
+ }
+
+ if (res->owner != dlm->node_num) {
+ spin_unlock(&res->spinlock);
+ mlog(0, "returning DLM_FORWARD -- not master\n");
+ status = DLM_FORWARD;
+ goto leave;
+ }
+
+ for (i=0; i<3; i++) {
+ list_for_each(iter, queue) {
+ lock = list_entry(iter, struct dlm_lock, list);
+ if (lock->ml.cookie == unlock->cookie &&
+ lock->ml.node == unlock->node_idx) {
+ dlm_lock_get(lock);
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ /* scan granted -> converting -> blocked queues */
+ queue++;
+ }
+ spin_unlock(&res->spinlock);
+ if (!found) {
+ status = DLM_IVLOCKID;
+ goto not_found;
+ }
+
+ /* lock was found on queue */
+ lksb = lock->lksb;
+ /* unlockast only called on originating node */
+ if (flags & LKM_PUT_LVB) {
+ lksb->flags |= DLM_LKSB_PUT_LVB;
+ memcpy(&lksb->lvb[0], &unlock->lvb[0], DLM_LVB_LEN);
+ }
+
+ /* if this is in-progress, propagate the DLM_FORWARD
+ * all the way back out */
+ status = dlmunlock_master(dlm, res, lock, lksb, flags, &ignore);
+ if (status == DLM_FORWARD)
+ mlog(0, "lockres is in progress\n");
+
+ if (flags & LKM_PUT_LVB)
+ lksb->flags &= ~DLM_LKSB_PUT_LVB;
+
+ dlm_lockres_calc_usage(dlm, res);
+ dlm_kick_thread(dlm, res);
+
+not_found:
+ if (!found)
+ mlog(ML_ERROR, "failed to find lock to unlock! "
+ "cookie=%"MLFu64"\n",
+ unlock->cookie);
+ else {
+ /* send the lksb->status back to the other node */
+ status = lksb->status;
+ dlm_lock_put(lock);
+ }
+
+leave:
+ if (res)
+ dlm_lockres_put(res);
+
+ dlm_put(dlm);
+
+ return status;
+}
+
+
+static enum dlm_status dlm_get_cancel_actions(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int *actions)
+{
+ enum dlm_status status;
+
+ if (dlm_lock_on_list(&res->blocked, lock)) {
+ /* cancel this outright */
+ lksb->status = DLM_NORMAL;
+ status = DLM_NORMAL;
+ *actions = (DLM_UNLOCK_CALL_AST |
+ DLM_UNLOCK_REMOVE_LOCK);
+ } else if (dlm_lock_on_list(&res->converting, lock)) {
+ /* cancel the request, put back on granted */
+ lksb->status = DLM_NORMAL;
+ status = DLM_NORMAL;
+ *actions = (DLM_UNLOCK_CALL_AST |
+ DLM_UNLOCK_REMOVE_LOCK |
+ DLM_UNLOCK_REGRANT_LOCK |
+ DLM_UNLOCK_CLEAR_CONVERT_TYPE);
+ } else if (dlm_lock_on_list(&res->granted, lock)) {
+ /* too late, already granted. DLM_CANCELGRANT */
+ lksb->status = DLM_CANCELGRANT;
+ status = DLM_NORMAL;
+ *actions = DLM_UNLOCK_CALL_AST;
+ } else {
+ mlog(ML_ERROR, "lock to cancel is not on any list!\n");
+ lksb->status = DLM_IVLOCKID;
+ status = DLM_IVLOCKID;
+ *actions = 0;
+ }
+ return status;
+}
+
+static enum dlm_status dlm_get_unlock_actions(struct dlm_ctxt *dlm,
+ struct dlm_lock_resource *res,
+ struct dlm_lock *lock,
+ struct dlm_lockstatus *lksb,
+ int *actions)
+{
+ enum dlm_status status;
+
+ /* unlock request */
+ if (!dlm_lock_on_list(&res->granted, lock)) {
+ lksb->status = DLM_DENIED;
+ status = DLM_DENIED;
+ dlm_error(status);
+ *actions = 0;
+ } else {
+ /* unlock granted lock */
+ lksb->status = DLM_NORMAL;
+ status = DLM_NORMAL;
+ *actions = (DLM_UNLOCK_FREE_LOCK |
+ DLM_UNLOCK_CALL_AST |
+ DLM_UNLOCK_REMOVE_LOCK);
+ }
+ return status;
+}
+
+/* there seems to be no point in doing this async
+ * since (even for the remote case) there is really
+ * no work to queue up... so just do it and fire the
+ * unlockast by hand when done... */
+enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb,
+ int flags, dlm_astunlockfunc_t *unlockast, void *data)
+{
+ enum dlm_status status;
+ struct dlm_lock_resource *res;
+ struct dlm_lock *lock = NULL;
+ int call_ast, is_master;
+
+ mlog_entry_void();
+
+ if (!lksb) {
+ dlm_error(DLM_BADARGS);
+ return DLM_BADARGS;
+ }
+
+ if (flags & ~(LKM_CANCEL | LKM_VALBLK | LKM_INVVALBLK)) {
+ dlm_error(DLM_BADPARAM);
+ return DLM_BADPARAM;
+ }
+
+ if ((flags & (LKM_VALBLK | LKM_CANCEL)) == (LKM_VALBLK | LKM_CANCEL)) {
+ mlog(0, "VALBLK given with CANCEL: ignoring VALBLK\n");
+ flags &= ~LKM_VALBLK;
+ }
+
+ if (!lksb->lockid || !lksb->lockid->lockres) {
+ dlm_error(DLM_BADPARAM);
+ return DLM_BADPARAM;
+ }
+
+ lock = lksb->lockid;
+ BUG_ON(!lock);
+ dlm_lock_get(lock);
+
+ res = lock->lockres;
+ BUG_ON(!res);
+ dlm_lockres_get(res);
+retry:
+ call_ast = 0;
+ /* need to retry up here because owner may have changed */
+ mlog(0, "lock=%p res=%p\n", lock, res);
+
+ spin_lock(&res->spinlock);
+ is_master = (res->owner == dlm->node_num);
+ spin_unlock(&res->spinlock);
+
+ if (is_master) {
+ status = dlmunlock_master(dlm, res, lock, lksb, flags,
+ &call_ast);
+ mlog(0, "done calling dlmunlock_master: returned %d, "
+ "call_ast is %d\n", status, call_ast);
+ } else {
+ status = dlmunlock_remote(dlm, res, lock, lksb, flags,
+ &call_ast);
+ mlog(0, "done calling dlmunlock_remote: returned %d, "
+ "call_ast is %d\n", status, call_ast);
+ }
+
+ if (status == DLM_RECOVERING ||
+ status == DLM_MIGRATING ||
+ status == DLM_FORWARD) {
+ /* We want to go away for a tiny bit to allow recovery
+ * / migration to complete on this resource. I don't
+ * know of any wait queue we could sleep on as this
+ * may be happening on another node. Perhaps the
+ * proper solution is to queue up requests on the
+ * other end? */
+
+ /* do we want to yield(); ?? */
+ msleep(50);
+
+ mlog(0, "retrying unlock due to pending recovery/"
+ "migration/in-progress\n");
+ goto retry;
+ }
+
+ if (call_ast) {
+ mlog(0, "calling unlockast(%p, %d)\n", data, lksb->status);
+ if (is_master) {
+ /* it is possible that there is one last bast
+ * pending. make sure it is flushed, then
+ * call the unlockast.
+ * not an issue if this is a mastered remotely,
+ * since this lock has been removed from the
+ * lockres queues and cannot be found. */
+ dlm_kick_thread(dlm, NULL);
+ wait_event(dlm->ast_wq,
+ dlm_lock_basts_flushed(dlm, lock));
+ }
+ (*unlockast)(data, lksb->status);
+ }
+
+ if (status == DLM_NORMAL) {
+ mlog(0, "kicking the thread\n");
+ dlm_kick_thread(dlm, res);
+ } else
+ dlm_error(status);
+
+ dlm_lockres_calc_usage(dlm, res);
+ dlm_lockres_put(res);
+ dlm_lock_put(lock);
+
+ mlog(0, "returning status=%d!\n", status);
+ return status;
+}
+EXPORT_SYMBOL_GPL(dlmunlock);
+
diff --git a/fs/ocfs2/dlm/dlmver.c b/fs/ocfs2/dlm/dlmver.c
new file mode 100644
index 000000000000..7ef2653f8f41
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmver.c
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmver.c
+ *
+ * version string
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include "dlmver.h"
+
+#define DLM_BUILD_VERSION "1.3.3"
+
+#define VERSION_STR "OCFS2 DLM " DLM_BUILD_VERSION
+
+void dlm_print_version(void)
+{
+ printk(KERN_INFO "%s\n", VERSION_STR);
+}
+
+MODULE_DESCRIPTION(VERSION_STR);
+
+MODULE_VERSION(DLM_BUILD_VERSION);
diff --git a/fs/ocfs2/dlm/dlmver.h b/fs/ocfs2/dlm/dlmver.h
new file mode 100644
index 000000000000..f674aee77a16
--- /dev/null
+++ b/fs/ocfs2/dlm/dlmver.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmfsver.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef DLM_VER_H
+#define DLM_VER_H
+
+void dlm_print_version(void);
+
+#endif /* DLM_VER_H */
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
new file mode 100644
index 000000000000..e1fdd288796e
--- /dev/null
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -0,0 +1,658 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * userdlm.c
+ *
+ * Code which implements the kernel side of a minimal userspace
+ * interface to our DLM.
+ *
+ * Many of the functions here are pared down versions of dlmglue.c
+ * functions.
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <asm/signal.h>
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/crc32.h>
+
+
+#include "cluster/nodemanager.h"
+#include "cluster/heartbeat.h"
+#include "cluster/tcp.h"
+
+#include "dlmapi.h"
+
+#include "userdlm.h"
+
+#define MLOG_MASK_PREFIX ML_DLMFS
+#include "cluster/masklog.h"
+
+static inline int user_check_wait_flag(struct user_lock_res *lockres,
+ int flag)
+{
+ int ret;
+
+ spin_lock(&lockres->l_lock);
+ ret = lockres->l_flags & flag;
+ spin_unlock(&lockres->l_lock);
+
+ return ret;
+}
+
+static inline void user_wait_on_busy_lock(struct user_lock_res *lockres)
+
+{
+ wait_event(lockres->l_event,
+ !user_check_wait_flag(lockres, USER_LOCK_BUSY));
+}
+
+static inline void user_wait_on_blocked_lock(struct user_lock_res *lockres)
+
+{
+ wait_event(lockres->l_event,
+ !user_check_wait_flag(lockres, USER_LOCK_BLOCKED));
+}
+
+/* I heart container_of... */
+static inline struct dlm_ctxt *
+dlm_ctxt_from_user_lockres(struct user_lock_res *lockres)
+{
+ struct dlmfs_inode_private *ip;
+
+ ip = container_of(lockres,
+ struct dlmfs_inode_private,
+ ip_lockres);
+ return ip->ip_dlm;
+}
+
+static struct inode *
+user_dlm_inode_from_user_lockres(struct user_lock_res *lockres)
+{
+ struct dlmfs_inode_private *ip;
+
+ ip = container_of(lockres,
+ struct dlmfs_inode_private,
+ ip_lockres);
+ return &ip->ip_vfs_inode;
+}
+
+static inline void user_recover_from_dlm_error(struct user_lock_res *lockres)
+{
+ spin_lock(&lockres->l_lock);
+ lockres->l_flags &= ~USER_LOCK_BUSY;
+ spin_unlock(&lockres->l_lock);
+}
+
+#define user_log_dlm_error(_func, _stat, _lockres) do { \
+ mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on " \
+ "resource %s: %s\n", dlm_errname(_stat), _func, \
+ _lockres->l_name, dlm_errmsg(_stat)); \
+} while (0)
+
+/* WARNING: This function lives in a world where the only three lock
+ * levels are EX, PR, and NL. It *will* have to be adjusted when more
+ * lock types are added. */
+static inline int user_highest_compat_lock_level(int level)
+{
+ int new_level = LKM_EXMODE;
+
+ if (level == LKM_EXMODE)
+ new_level = LKM_NLMODE;
+ else if (level == LKM_PRMODE)
+ new_level = LKM_PRMODE;
+ return new_level;
+}
+
+static void user_ast(void *opaque)
+{
+ struct user_lock_res *lockres = opaque;
+ struct dlm_lockstatus *lksb;
+
+ mlog(0, "AST fired for lockres %s\n", lockres->l_name);
+
+ spin_lock(&lockres->l_lock);
+
+ lksb = &(lockres->l_lksb);
+ if (lksb->status != DLM_NORMAL) {
+ mlog(ML_ERROR, "lksb status value of %u on lockres %s\n",
+ lksb->status, lockres->l_name);
+ spin_unlock(&lockres->l_lock);
+ return;
+ }
+
+ /* we're downconverting. */
+ if (lockres->l_requested < lockres->l_level) {
+ if (lockres->l_requested <=
+ user_highest_compat_lock_level(lockres->l_blocking)) {
+ lockres->l_blocking = LKM_NLMODE;
+ lockres->l_flags &= ~USER_LOCK_BLOCKED;
+ }
+ }
+
+ lockres->l_level = lockres->l_requested;
+ lockres->l_requested = LKM_IVMODE;
+ lockres->l_flags |= USER_LOCK_ATTACHED;
+ lockres->l_flags &= ~USER_LOCK_BUSY;
+
+ spin_unlock(&lockres->l_lock);
+
+ wake_up(&lockres->l_event);
+}
+
+static inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres)
+{
+ struct inode *inode;
+ inode = user_dlm_inode_from_user_lockres(lockres);
+ if (!igrab(inode))
+ BUG();
+}
+
+static void user_dlm_unblock_lock(void *opaque);
+
+static void __user_dlm_queue_lockres(struct user_lock_res *lockres)
+{
+ if (!(lockres->l_flags & USER_LOCK_QUEUED)) {
+ user_dlm_grab_inode_ref(lockres);
+
+ INIT_WORK(&lockres->l_work, user_dlm_unblock_lock,
+ lockres);
+
+ queue_work(user_dlm_worker, &lockres->l_work);
+ lockres->l_flags |= USER_LOCK_QUEUED;
+ }
+}
+
+static void __user_dlm_cond_queue_lockres(struct user_lock_res *lockres)
+{
+ int queue = 0;
+
+ if (!(lockres->l_flags & USER_LOCK_BLOCKED))
+ return;
+
+ switch (lockres->l_blocking) {
+ case LKM_EXMODE:
+ if (!lockres->l_ex_holders && !lockres->l_ro_holders)
+ queue = 1;
+ break;
+ case LKM_PRMODE:
+ if (!lockres->l_ex_holders)
+ queue = 1;
+ break;
+ default:
+ BUG();
+ }
+
+ if (queue)
+ __user_dlm_queue_lockres(lockres);
+}
+
+static void user_bast(void *opaque, int level)
+{
+ struct user_lock_res *lockres = opaque;
+
+ mlog(0, "Blocking AST fired for lockres %s. Blocking level %d\n",
+ lockres->l_name, level);
+
+ spin_lock(&lockres->l_lock);
+ lockres->l_flags |= USER_LOCK_BLOCKED;
+ if (level > lockres->l_blocking)
+ lockres->l_blocking = level;
+
+ __user_dlm_queue_lockres(lockres);
+ spin_unlock(&lockres->l_lock);
+
+ wake_up(&lockres->l_event);
+}
+
+static void user_unlock_ast(void *opaque, enum dlm_status status)
+{
+ struct user_lock_res *lockres = opaque;
+
+ mlog(0, "UNLOCK AST called on lock %s\n", lockres->l_name);
+
+ if (status != DLM_NORMAL)
+ mlog(ML_ERROR, "Dlm returns status %d\n", status);
+
+ spin_lock(&lockres->l_lock);
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN)
+ lockres->l_level = LKM_IVMODE;
+ else {
+ lockres->l_requested = LKM_IVMODE; /* cancel an
+ * upconvert
+ * request. */
+ lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+ /* we want the unblock thread to look at it again
+ * now. */
+ __user_dlm_queue_lockres(lockres);
+ }
+
+ lockres->l_flags &= ~USER_LOCK_BUSY;
+ spin_unlock(&lockres->l_lock);
+
+ wake_up(&lockres->l_event);
+}
+
+static inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres)
+{
+ struct inode *inode;
+ inode = user_dlm_inode_from_user_lockres(lockres);
+ iput(inode);
+}
+
+static void user_dlm_unblock_lock(void *opaque)
+{
+ int new_level, status;
+ struct user_lock_res *lockres = (struct user_lock_res *) opaque;
+ struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
+
+ mlog(0, "processing lockres %s\n", lockres->l_name);
+
+ spin_lock(&lockres->l_lock);
+
+ BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
+ BUG_ON(!(lockres->l_flags & USER_LOCK_QUEUED));
+
+ /* notice that we don't clear USER_LOCK_BLOCKED here. That's
+ * for user_ast to do. */
+ lockres->l_flags &= ~USER_LOCK_QUEUED;
+
+ if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) {
+ mlog(0, "lock is in teardown so we do nothing\n");
+ spin_unlock(&lockres->l_lock);
+ goto drop_ref;
+ }
+
+ if (lockres->l_flags & USER_LOCK_BUSY) {
+ mlog(0, "BUSY flag detected...\n");
+ if (lockres->l_flags & USER_LOCK_IN_CANCEL) {
+ spin_unlock(&lockres->l_lock);
+ goto drop_ref;
+ }
+
+ lockres->l_flags |= USER_LOCK_IN_CANCEL;
+ spin_unlock(&lockres->l_lock);
+
+ status = dlmunlock(dlm,
+ &lockres->l_lksb,
+ LKM_CANCEL,
+ user_unlock_ast,
+ lockres);
+ if (status == DLM_CANCELGRANT) {
+ /* If we got this, then the ast was fired
+ * before we could cancel. We cleanup our
+ * state, and restart the function. */
+ spin_lock(&lockres->l_lock);
+ lockres->l_flags &= ~USER_LOCK_IN_CANCEL;
+ spin_unlock(&lockres->l_lock);
+ } else if (status != DLM_NORMAL)
+ user_log_dlm_error("dlmunlock", status, lockres);
+ goto drop_ref;
+ }
+
+ /* If there are still incompat holders, we can exit safely
+ * without worrying about re-queueing this lock as that will
+ * happen on the last call to user_cluster_unlock. */
+ if ((lockres->l_blocking == LKM_EXMODE)
+ && (lockres->l_ex_holders || lockres->l_ro_holders)) {
+ spin_unlock(&lockres->l_lock);
+ mlog(0, "can't downconvert for ex: ro = %u, ex = %u\n",
+ lockres->l_ro_holders, lockres->l_ex_holders);
+ goto drop_ref;
+ }
+
+ if ((lockres->l_blocking == LKM_PRMODE)
+ && lockres->l_ex_holders) {
+ spin_unlock(&lockres->l_lock);
+ mlog(0, "can't downconvert for pr: ex = %u\n",
+ lockres->l_ex_holders);
+ goto drop_ref;
+ }
+
+ /* yay, we can downconvert now. */
+ new_level = user_highest_compat_lock_level(lockres->l_blocking);
+ lockres->l_requested = new_level;
+ lockres->l_flags |= USER_LOCK_BUSY;
+ mlog(0, "Downconvert lock from %d to %d\n",
+ lockres->l_level, new_level);
+ spin_unlock(&lockres->l_lock);
+
+ /* need lock downconvert request now... */
+ status = dlmlock(dlm,
+ new_level,
+ &lockres->l_lksb,
+ LKM_CONVERT|LKM_VALBLK,
+ lockres->l_name,
+ user_ast,
+ lockres,
+ user_bast);
+ if (status != DLM_NORMAL) {
+ user_log_dlm_error("dlmlock", status, lockres);
+ user_recover_from_dlm_error(lockres);
+ }
+
+drop_ref:
+ user_dlm_drop_inode_ref(lockres);
+}
+
+static inline void user_dlm_inc_holders(struct user_lock_res *lockres,
+ int level)
+{
+ switch(level) {
+ case LKM_EXMODE:
+ lockres->l_ex_holders++;
+ break;
+ case LKM_PRMODE:
+ lockres->l_ro_holders++;
+ break;
+ default:
+ BUG();
+ }
+}
+
+/* predict what lock level we'll be dropping down to on behalf
+ * of another node, and return true if the currently wanted
+ * level will be compatible with it. */
+static inline int
+user_may_continue_on_blocked_lock(struct user_lock_res *lockres,
+ int wanted)
+{
+ BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED));
+
+ return wanted <= user_highest_compat_lock_level(lockres->l_blocking);
+}
+
+int user_dlm_cluster_lock(struct user_lock_res *lockres,
+ int level,
+ int lkm_flags)
+{
+ int status, local_flags;
+ struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
+
+ if (level != LKM_EXMODE &&
+ level != LKM_PRMODE) {
+ mlog(ML_ERROR, "lockres %s: invalid request!\n",
+ lockres->l_name);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ mlog(0, "lockres %s: asking for %s lock, passed flags = 0x%x\n",
+ lockres->l_name,
+ (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE",
+ lkm_flags);
+
+again:
+ if (signal_pending(current)) {
+ status = -ERESTARTSYS;
+ goto bail;
+ }
+
+ spin_lock(&lockres->l_lock);
+
+ /* We only compare against the currently granted level
+ * here. If the lock is blocked waiting on a downconvert,
+ * we'll get caught below. */
+ if ((lockres->l_flags & USER_LOCK_BUSY) &&
+ (level > lockres->l_level)) {
+ /* is someone sitting in dlm_lock? If so, wait on
+ * them. */
+ spin_unlock(&lockres->l_lock);
+
+ user_wait_on_busy_lock(lockres);
+ goto again;
+ }
+
+ if ((lockres->l_flags & USER_LOCK_BLOCKED) &&
+ (!user_may_continue_on_blocked_lock(lockres, level))) {
+ /* is the lock is currently blocked on behalf of
+ * another node */
+ spin_unlock(&lockres->l_lock);
+
+ user_wait_on_blocked_lock(lockres);
+ goto again;
+ }
+
+ if (level > lockres->l_level) {
+ local_flags = lkm_flags | LKM_VALBLK;
+ if (lockres->l_level != LKM_IVMODE)
+ local_flags |= LKM_CONVERT;
+
+ lockres->l_requested = level;
+ lockres->l_flags |= USER_LOCK_BUSY;
+ spin_unlock(&lockres->l_lock);
+
+ BUG_ON(level == LKM_IVMODE);
+ BUG_ON(level == LKM_NLMODE);
+
+ mlog(0, "lock %s, get lock from %d to level = %d\n",
+ lockres->l_name, lockres->l_level, level);
+
+ /* call dlm_lock to upgrade lock now */
+ status = dlmlock(dlm,
+ level,
+ &lockres->l_lksb,
+ local_flags,
+ lockres->l_name,
+ user_ast,
+ lockres,
+ user_bast);
+ if (status != DLM_NORMAL) {
+ if ((lkm_flags & LKM_NOQUEUE) &&
+ (status == DLM_NOTQUEUED))
+ status = -EAGAIN;
+ else {
+ user_log_dlm_error("dlmlock", status, lockres);
+ status = -EINVAL;
+ }
+ user_recover_from_dlm_error(lockres);
+ goto bail;
+ }
+
+ mlog(0, "lock %s, successfull return from dlmlock\n",
+ lockres->l_name);
+
+ user_wait_on_busy_lock(lockres);
+ goto again;
+ }
+
+ user_dlm_inc_holders(lockres, level);
+ spin_unlock(&lockres->l_lock);
+
+ mlog(0, "lockres %s: Got %s lock!\n", lockres->l_name,
+ (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE");
+
+ status = 0;
+bail:
+ return status;
+}
+
+static inline void user_dlm_dec_holders(struct user_lock_res *lockres,
+ int level)
+{
+ switch(level) {
+ case LKM_EXMODE:
+ BUG_ON(!lockres->l_ex_holders);
+ lockres->l_ex_holders--;
+ break;
+ case LKM_PRMODE:
+ BUG_ON(!lockres->l_ro_holders);
+ lockres->l_ro_holders--;
+ break;
+ default:
+ BUG();
+ }
+}
+
+void user_dlm_cluster_unlock(struct user_lock_res *lockres,
+ int level)
+{
+ if (level != LKM_EXMODE &&
+ level != LKM_PRMODE) {
+ mlog(ML_ERROR, "lockres %s: invalid request!\n", lockres->l_name);
+ return;
+ }
+
+ mlog(0, "lockres %s: dropping %s lock\n", lockres->l_name,
+ (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE");
+
+ spin_lock(&lockres->l_lock);
+ user_dlm_dec_holders(lockres, level);
+ __user_dlm_cond_queue_lockres(lockres);
+ spin_unlock(&lockres->l_lock);
+}
+
+void user_dlm_write_lvb(struct inode *inode,
+ const char *val,
+ unsigned int len)
+{
+ struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
+ char *lvb = lockres->l_lksb.lvb;
+
+ BUG_ON(len > DLM_LVB_LEN);
+
+ spin_lock(&lockres->l_lock);
+
+ BUG_ON(lockres->l_level < LKM_EXMODE);
+ memcpy(lvb, val, len);
+
+ spin_unlock(&lockres->l_lock);
+}
+
+void user_dlm_read_lvb(struct inode *inode,
+ char *val,
+ unsigned int len)
+{
+ struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres;
+ char *lvb = lockres->l_lksb.lvb;
+
+ BUG_ON(len > DLM_LVB_LEN);
+
+ spin_lock(&lockres->l_lock);
+
+ BUG_ON(lockres->l_level < LKM_PRMODE);
+ memcpy(val, lvb, len);
+
+ spin_unlock(&lockres->l_lock);
+}
+
+void user_dlm_lock_res_init(struct user_lock_res *lockres,
+ struct dentry *dentry)
+{
+ memset(lockres, 0, sizeof(*lockres));
+
+ spin_lock_init(&lockres->l_lock);
+ init_waitqueue_head(&lockres->l_event);
+ lockres->l_level = LKM_IVMODE;
+ lockres->l_requested = LKM_IVMODE;
+ lockres->l_blocking = LKM_IVMODE;
+
+ /* should have been checked before getting here. */
+ BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN);
+
+ memcpy(lockres->l_name,
+ dentry->d_name.name,
+ dentry->d_name.len);
+}
+
+int user_dlm_destroy_lock(struct user_lock_res *lockres)
+{
+ int status = -EBUSY;
+ struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres);
+
+ mlog(0, "asked to destroy %s\n", lockres->l_name);
+
+ spin_lock(&lockres->l_lock);
+ while (lockres->l_flags & USER_LOCK_BUSY) {
+ spin_unlock(&lockres->l_lock);
+
+ mlog(0, "lock %s is busy\n", lockres->l_name);
+
+ user_wait_on_busy_lock(lockres);
+
+ spin_lock(&lockres->l_lock);
+ }
+
+ if (lockres->l_ro_holders || lockres->l_ex_holders) {
+ spin_unlock(&lockres->l_lock);
+ mlog(0, "lock %s has holders\n", lockres->l_name);
+ goto bail;
+ }
+
+ status = 0;
+ if (!(lockres->l_flags & USER_LOCK_ATTACHED)) {
+ spin_unlock(&lockres->l_lock);
+ mlog(0, "lock %s is not attached\n", lockres->l_name);
+ goto bail;
+ }
+
+ lockres->l_flags &= ~USER_LOCK_ATTACHED;
+ lockres->l_flags |= USER_LOCK_BUSY;
+ lockres->l_flags |= USER_LOCK_IN_TEARDOWN;
+ spin_unlock(&lockres->l_lock);
+
+ mlog(0, "unlocking lockres %s\n", lockres->l_name);
+ status = dlmunlock(dlm,
+ &lockres->l_lksb,
+ LKM_VALBLK,
+ user_unlock_ast,
+ lockres);
+ if (status != DLM_NORMAL) {
+ user_log_dlm_error("dlmunlock", status, lockres);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ user_wait_on_busy_lock(lockres);
+
+ status = 0;
+bail:
+ return status;
+}
+
+struct dlm_ctxt *user_dlm_register_context(struct qstr *name)
+{
+ struct dlm_ctxt *dlm;
+ u32 dlm_key;
+ char *domain;
+
+ domain = kmalloc(name->len + 1, GFP_KERNEL);
+ if (!domain) {
+ mlog_errno(-ENOMEM);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ dlm_key = crc32_le(0, name->name, name->len);
+
+ snprintf(domain, name->len + 1, "%.*s", name->len, name->name);
+
+ dlm = dlm_register_domain(domain, dlm_key);
+ if (IS_ERR(dlm))
+ mlog_errno(PTR_ERR(dlm));
+
+ kfree(domain);
+ return dlm;
+}
+
+void user_dlm_unregister_context(struct dlm_ctxt *dlm)
+{
+ dlm_unregister_domain(dlm);
+}
diff --git a/fs/ocfs2/dlm/userdlm.h b/fs/ocfs2/dlm/userdlm.h
new file mode 100644
index 000000000000..04178bc40b76
--- /dev/null
+++ b/fs/ocfs2/dlm/userdlm.h
@@ -0,0 +1,111 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * userdlm.h
+ *
+ * Userspace dlm defines
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+
+#ifndef USERDLM_H
+#define USERDLM_H
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+/* user_lock_res->l_flags flags. */
+#define USER_LOCK_ATTACHED (0x00000001) /* have we initialized
+ * the lvb */
+#define USER_LOCK_BUSY (0x00000002) /* we are currently in
+ * dlm_lock */
+#define USER_LOCK_BLOCKED (0x00000004) /* blocked waiting to
+ * downconvert*/
+#define USER_LOCK_IN_TEARDOWN (0x00000008) /* we're currently
+ * destroying this
+ * lock. */
+#define USER_LOCK_QUEUED (0x00000010) /* lock is on the
+ * workqueue */
+#define USER_LOCK_IN_CANCEL (0x00000020)
+
+struct user_lock_res {
+ spinlock_t l_lock;
+
+ int l_flags;
+
+#define USER_DLM_LOCK_ID_MAX_LEN 32
+ char l_name[USER_DLM_LOCK_ID_MAX_LEN];
+ int l_level;
+ unsigned int l_ro_holders;
+ unsigned int l_ex_holders;
+ struct dlm_lockstatus l_lksb;
+
+ int l_requested;
+ int l_blocking;
+
+ wait_queue_head_t l_event;
+
+ struct work_struct l_work;
+};
+
+extern struct workqueue_struct *user_dlm_worker;
+
+void user_dlm_lock_res_init(struct user_lock_res *lockres,
+ struct dentry *dentry);
+int user_dlm_destroy_lock(struct user_lock_res *lockres);
+int user_dlm_cluster_lock(struct user_lock_res *lockres,
+ int level,
+ int lkm_flags);
+void user_dlm_cluster_unlock(struct user_lock_res *lockres,
+ int level);
+void user_dlm_write_lvb(struct inode *inode,
+ const char *val,
+ unsigned int len);
+void user_dlm_read_lvb(struct inode *inode,
+ char *val,
+ unsigned int len);
+struct dlm_ctxt *user_dlm_register_context(struct qstr *name);
+void user_dlm_unregister_context(struct dlm_ctxt *dlm);
+
+struct dlmfs_inode_private {
+ struct dlm_ctxt *ip_dlm;
+
+ struct user_lock_res ip_lockres; /* unused for directories. */
+ struct inode *ip_parent;
+
+ struct inode ip_vfs_inode;
+};
+
+static inline struct dlmfs_inode_private *
+DLMFS_I(struct inode *inode)
+{
+ return container_of(inode,
+ struct dlmfs_inode_private,
+ ip_vfs_inode);
+}
+
+struct dlmfs_filp_private {
+ int fp_lock_level;
+};
+
+#define DLMFS_MAGIC 0x76a9f425
+
+#endif /* USERDLM_H */
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
new file mode 100644
index 000000000000..e971ec2f8407
--- /dev/null
+++ b/fs/ocfs2/dlmglue.c
@@ -0,0 +1,2904 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmglue.c
+ *
+ * Code which implements an OCFS2 specific interface to our DLM.
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/crc32.h>
+#include <linux/kthread.h>
+#include <linux/pagemap.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <cluster/heartbeat.h>
+#include <cluster/nodemanager.h>
+#include <cluster/tcp.h>
+
+#include <dlm/dlmapi.h>
+
+#define MLOG_MASK_PREFIX ML_DLM_GLUE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "journal.h"
+#include "slot_map.h"
+#include "super.h"
+#include "uptodate.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+struct ocfs2_mask_waiter {
+ struct list_head mw_item;
+ int mw_status;
+ struct completion mw_complete;
+ unsigned long mw_mask;
+ unsigned long mw_goal;
+};
+
+static void ocfs2_inode_ast_func(void *opaque);
+static void ocfs2_inode_bast_func(void *opaque,
+ int level);
+static void ocfs2_super_ast_func(void *opaque);
+static void ocfs2_super_bast_func(void *opaque,
+ int level);
+static void ocfs2_rename_ast_func(void *opaque);
+static void ocfs2_rename_bast_func(void *opaque,
+ int level);
+
+/* so far, all locks have gotten along with the same unlock ast */
+static void ocfs2_unlock_ast_func(void *opaque,
+ enum dlm_status status);
+static int ocfs2_do_unblock_meta(struct inode *inode,
+ int *requeue);
+static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
+ int *requeue);
+static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
+ int *requeue);
+static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
+ int *requeue);
+static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres,
+ int *requeue);
+typedef void (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int);
+static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int *requeue,
+ ocfs2_convert_worker_t *worker);
+
+struct ocfs2_lock_res_ops {
+ void (*ast)(void *);
+ void (*bast)(void *, int);
+ void (*unlock_ast)(void *, enum dlm_status);
+ int (*unblock)(struct ocfs2_lock_res *, int *);
+};
+
+static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = {
+ .ast = ocfs2_inode_ast_func,
+ .bast = ocfs2_inode_bast_func,
+ .unlock_ast = ocfs2_unlock_ast_func,
+ .unblock = ocfs2_unblock_inode_lock,
+};
+
+static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = {
+ .ast = ocfs2_inode_ast_func,
+ .bast = ocfs2_inode_bast_func,
+ .unlock_ast = ocfs2_unlock_ast_func,
+ .unblock = ocfs2_unblock_meta,
+};
+
+static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
+ int blocking);
+
+static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = {
+ .ast = ocfs2_inode_ast_func,
+ .bast = ocfs2_inode_bast_func,
+ .unlock_ast = ocfs2_unlock_ast_func,
+ .unblock = ocfs2_unblock_data,
+};
+
+static struct ocfs2_lock_res_ops ocfs2_super_lops = {
+ .ast = ocfs2_super_ast_func,
+ .bast = ocfs2_super_bast_func,
+ .unlock_ast = ocfs2_unlock_ast_func,
+ .unblock = ocfs2_unblock_osb_lock,
+};
+
+static struct ocfs2_lock_res_ops ocfs2_rename_lops = {
+ .ast = ocfs2_rename_ast_func,
+ .bast = ocfs2_rename_bast_func,
+ .unlock_ast = ocfs2_unlock_ast_func,
+ .unblock = ocfs2_unblock_osb_lock,
+};
+
+static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
+{
+ return lockres->l_type == OCFS2_LOCK_TYPE_META ||
+ lockres->l_type == OCFS2_LOCK_TYPE_DATA ||
+ lockres->l_type == OCFS2_LOCK_TYPE_RW;
+}
+
+static inline int ocfs2_is_super_lock(struct ocfs2_lock_res *lockres)
+{
+ return lockres->l_type == OCFS2_LOCK_TYPE_SUPER;
+}
+
+static inline int ocfs2_is_rename_lock(struct ocfs2_lock_res *lockres)
+{
+ return lockres->l_type == OCFS2_LOCK_TYPE_RENAME;
+}
+
+static inline struct ocfs2_super *ocfs2_lock_res_super(struct ocfs2_lock_res *lockres)
+{
+ BUG_ON(!ocfs2_is_super_lock(lockres)
+ && !ocfs2_is_rename_lock(lockres));
+
+ return (struct ocfs2_super *) lockres->l_priv;
+}
+
+static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres)
+{
+ BUG_ON(!ocfs2_is_inode_lock(lockres));
+
+ return (struct inode *) lockres->l_priv;
+}
+
+static int ocfs2_lock_create(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+ int dlm_flags);
+static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
+ int wanted);
+static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level);
+static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres);
+static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres);
+static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres);
+static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level);
+static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres);
+static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
+ int convert);
+#define ocfs2_log_dlm_error(_func, _stat, _lockres) do { \
+ mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on " \
+ "resource %s: %s\n", dlm_errname(_stat), _func, \
+ _lockres->l_name, dlm_errmsg(_stat)); \
+} while (0)
+static void ocfs2_vote_on_unlock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres);
+static int ocfs2_meta_lock_update(struct inode *inode,
+ struct buffer_head **bh);
+static void ocfs2_drop_osb_locks(struct ocfs2_super *osb);
+static inline int ocfs2_highest_compat_lock_level(int level);
+static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
+ struct ocfs2_lock_res *lockres,
+ int new_level);
+
+static char *ocfs2_lock_type_strings[] = {
+ [OCFS2_LOCK_TYPE_META] = "Meta",
+ [OCFS2_LOCK_TYPE_DATA] = "Data",
+ [OCFS2_LOCK_TYPE_SUPER] = "Super",
+ [OCFS2_LOCK_TYPE_RENAME] = "Rename",
+ /* Need to differntiate from [R]ename.. serializing writes is the
+ * important job it does, anyway. */
+ [OCFS2_LOCK_TYPE_RW] = "Write/Read",
+};
+
+static char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
+{
+ mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type);
+ return ocfs2_lock_type_strings[type];
+}
+
+static void ocfs2_build_lock_name(enum ocfs2_lock_type type,
+ u64 blkno,
+ u32 generation,
+ char *name)
+{
+ int len;
+
+ mlog_entry_void();
+
+ BUG_ON(type >= OCFS2_NUM_LOCK_TYPES);
+
+ len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016"MLFx64"%08x",
+ ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD, blkno,
+ generation);
+
+ BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1));
+
+ mlog(0, "built lock resource with name: %s\n", name);
+
+ mlog_exit_void();
+}
+
+static spinlock_t ocfs2_dlm_tracking_lock = SPIN_LOCK_UNLOCKED;
+
+static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res,
+ struct ocfs2_dlm_debug *dlm_debug)
+{
+ mlog(0, "Add tracking for lockres %s\n", res->l_name);
+
+ spin_lock(&ocfs2_dlm_tracking_lock);
+ list_add(&res->l_debug_list, &dlm_debug->d_lockres_tracking);
+ spin_unlock(&ocfs2_dlm_tracking_lock);
+}
+
+static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
+{
+ spin_lock(&ocfs2_dlm_tracking_lock);
+ if (!list_empty(&res->l_debug_list))
+ list_del_init(&res->l_debug_list);
+ spin_unlock(&ocfs2_dlm_tracking_lock);
+}
+
+static void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *res,
+ enum ocfs2_lock_type type,
+ u64 blkno,
+ u32 generation,
+ struct ocfs2_lock_res_ops *ops,
+ void *priv)
+{
+ ocfs2_build_lock_name(type, blkno, generation, res->l_name);
+
+ res->l_type = type;
+ res->l_ops = ops;
+ res->l_priv = priv;
+
+ res->l_level = LKM_IVMODE;
+ res->l_requested = LKM_IVMODE;
+ res->l_blocking = LKM_IVMODE;
+ res->l_action = OCFS2_AST_INVALID;
+ res->l_unlock_action = OCFS2_UNLOCK_INVALID;
+
+ res->l_flags = OCFS2_LOCK_INITIALIZED;
+
+ ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug);
+}
+
+void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res)
+{
+ /* This also clears out the lock status block */
+ memset(res, 0, sizeof(struct ocfs2_lock_res));
+ spin_lock_init(&res->l_lock);
+ init_waitqueue_head(&res->l_event);
+ INIT_LIST_HEAD(&res->l_blocked_list);
+ INIT_LIST_HEAD(&res->l_mask_waiters);
+}
+
+void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
+ enum ocfs2_lock_type type,
+ struct inode *inode)
+{
+ struct ocfs2_lock_res_ops *ops;
+
+ switch(type) {
+ case OCFS2_LOCK_TYPE_RW:
+ ops = &ocfs2_inode_rw_lops;
+ break;
+ case OCFS2_LOCK_TYPE_META:
+ ops = &ocfs2_inode_meta_lops;
+ break;
+ case OCFS2_LOCK_TYPE_DATA:
+ ops = &ocfs2_inode_data_lops;
+ break;
+ default:
+ mlog_bug_on_msg(1, "type: %d\n", type);
+ ops = NULL; /* thanks, gcc */
+ break;
+ };
+
+ ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type,
+ OCFS2_I(inode)->ip_blkno,
+ inode->i_generation, ops, inode);
+}
+
+static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res,
+ struct ocfs2_super *osb)
+{
+ /* Superblock lockres doesn't come from a slab so we call init
+ * once on it manually. */
+ ocfs2_lock_res_init_once(res);
+ ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER,
+ OCFS2_SUPER_BLOCK_BLKNO, 0,
+ &ocfs2_super_lops, osb);
+}
+
+static void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res,
+ struct ocfs2_super *osb)
+{
+ /* Rename lockres doesn't come from a slab so we call init
+ * once on it manually. */
+ ocfs2_lock_res_init_once(res);
+ ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME, 0, 0,
+ &ocfs2_rename_lops, osb);
+}
+
+void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
+{
+ mlog_entry_void();
+
+ if (!(res->l_flags & OCFS2_LOCK_INITIALIZED))
+ return;
+
+ ocfs2_remove_lockres_tracking(res);
+
+ mlog_bug_on_msg(!list_empty(&res->l_blocked_list),
+ "Lockres %s is on the blocked list\n",
+ res->l_name);
+ mlog_bug_on_msg(!list_empty(&res->l_mask_waiters),
+ "Lockres %s has mask waiters pending\n",
+ res->l_name);
+ mlog_bug_on_msg(spin_is_locked(&res->l_lock),
+ "Lockres %s is locked\n",
+ res->l_name);
+ mlog_bug_on_msg(res->l_ro_holders,
+ "Lockres %s has %u ro holders\n",
+ res->l_name, res->l_ro_holders);
+ mlog_bug_on_msg(res->l_ex_holders,
+ "Lockres %s has %u ex holders\n",
+ res->l_name, res->l_ex_holders);
+
+ /* Need to clear out the lock status block for the dlm */
+ memset(&res->l_lksb, 0, sizeof(res->l_lksb));
+
+ res->l_flags = 0UL;
+ mlog_exit_void();
+}
+
+static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,
+ int level)
+{
+ mlog_entry_void();
+
+ BUG_ON(!lockres);
+
+ switch(level) {
+ case LKM_EXMODE:
+ lockres->l_ex_holders++;
+ break;
+ case LKM_PRMODE:
+ lockres->l_ro_holders++;
+ break;
+ default:
+ BUG();
+ }
+
+ mlog_exit_void();
+}
+
+static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,
+ int level)
+{
+ mlog_entry_void();
+
+ BUG_ON(!lockres);
+
+ switch(level) {
+ case LKM_EXMODE:
+ BUG_ON(!lockres->l_ex_holders);
+ lockres->l_ex_holders--;
+ break;
+ case LKM_PRMODE:
+ BUG_ON(!lockres->l_ro_holders);
+ lockres->l_ro_holders--;
+ break;
+ default:
+ BUG();
+ }
+ mlog_exit_void();
+}
+
+/* WARNING: This function lives in a world where the only three lock
+ * levels are EX, PR, and NL. It *will* have to be adjusted when more
+ * lock types are added. */
+static inline int ocfs2_highest_compat_lock_level(int level)
+{
+ int new_level = LKM_EXMODE;
+
+ if (level == LKM_EXMODE)
+ new_level = LKM_NLMODE;
+ else if (level == LKM_PRMODE)
+ new_level = LKM_PRMODE;
+ return new_level;
+}
+
+static void lockres_set_flags(struct ocfs2_lock_res *lockres,
+ unsigned long newflags)
+{
+ struct list_head *pos, *tmp;
+ struct ocfs2_mask_waiter *mw;
+
+ assert_spin_locked(&lockres->l_lock);
+
+ lockres->l_flags = newflags;
+
+ list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) {
+ mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item);
+ if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
+ continue;
+
+ list_del_init(&mw->mw_item);
+ mw->mw_status = 0;
+ complete(&mw->mw_complete);
+ }
+}
+static void lockres_or_flags(struct ocfs2_lock_res *lockres, unsigned long or)
+{
+ lockres_set_flags(lockres, lockres->l_flags | or);
+}
+static void lockres_clear_flags(struct ocfs2_lock_res *lockres,
+ unsigned long clear)
+{
+ lockres_set_flags(lockres, lockres->l_flags & ~clear);
+}
+
+static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres)
+{
+ mlog_entry_void();
+
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+ BUG_ON(lockres->l_blocking <= LKM_NLMODE);
+
+ lockres->l_level = lockres->l_requested;
+ if (lockres->l_level <=
+ ocfs2_highest_compat_lock_level(lockres->l_blocking)) {
+ lockres->l_blocking = LKM_NLMODE;
+ lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);
+ }
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+
+ mlog_exit_void();
+}
+
+static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres)
+{
+ mlog_entry_void();
+
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
+
+ /* Convert from RO to EX doesn't really need anything as our
+ * information is already up to data. Convert from NL to
+ * *anything* however should mark ourselves as needing an
+ * update */
+ if (lockres->l_level == LKM_NLMODE)
+ lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+
+ lockres->l_level = lockres->l_requested;
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+
+ mlog_exit_void();
+}
+
+static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres)
+{
+ mlog_entry_void();
+
+ BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY));
+ BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+
+ if (lockres->l_requested > LKM_NLMODE &&
+ !(lockres->l_flags & OCFS2_LOCK_LOCAL))
+ lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+
+ lockres->l_level = lockres->l_requested;
+ lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED);
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_inode_ast_func(void *opaque)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+ struct inode *inode;
+ struct dlm_lockstatus *lksb;
+ unsigned long flags;
+
+ mlog_entry_void();
+
+ inode = ocfs2_lock_res_inode(lockres);
+
+ mlog(0, "AST fired for inode %"MLFu64", l_action = %u, type = %s\n",
+ OCFS2_I(inode)->ip_blkno, lockres->l_action,
+ ocfs2_lock_type_string(lockres->l_type));
+
+ BUG_ON(!ocfs2_is_inode_lock(lockres));
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ lksb = &(lockres->l_lksb);
+ if (lksb->status != DLM_NORMAL) {
+ mlog(ML_ERROR, "ocfs2_inode_ast_func: lksb status value of %u "
+ "on inode %"MLFu64"\n", lksb->status,
+ OCFS2_I(inode)->ip_blkno);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ mlog_exit_void();
+ return;
+ }
+
+ switch(lockres->l_action) {
+ case OCFS2_AST_ATTACH:
+ ocfs2_generic_handle_attach_action(lockres);
+ lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
+ break;
+ case OCFS2_AST_CONVERT:
+ ocfs2_generic_handle_convert_action(lockres);
+ break;
+ case OCFS2_AST_DOWNCONVERT:
+ ocfs2_generic_handle_downconvert_action(lockres);
+ break;
+ default:
+ mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u "
+ "lockres flags = 0x%lx, unlock action: %u\n",
+ lockres->l_name, lockres->l_action, lockres->l_flags,
+ lockres->l_unlock_action);
+
+ BUG();
+ }
+
+ /* data and rw locking ignores refresh flag for now. */
+ if (lockres->l_type != OCFS2_LOCK_TYPE_META)
+ lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+
+ /* set it to something invalid so if we get called again we
+ * can catch it. */
+ lockres->l_action = OCFS2_AST_INVALID;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ wake_up(&lockres->l_event);
+
+ mlog_exit_void();
+}
+
+static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,
+ int level)
+{
+ int needs_downconvert = 0;
+ mlog_entry_void();
+
+ assert_spin_locked(&lockres->l_lock);
+
+ lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
+
+ if (level > lockres->l_blocking) {
+ /* only schedule a downconvert if we haven't already scheduled
+ * one that goes low enough to satisfy the level we're
+ * blocking. this also catches the case where we get
+ * duplicate BASTs */
+ if (ocfs2_highest_compat_lock_level(level) <
+ ocfs2_highest_compat_lock_level(lockres->l_blocking))
+ needs_downconvert = 1;
+
+ lockres->l_blocking = level;
+ }
+
+ mlog_exit(needs_downconvert);
+ return needs_downconvert;
+}
+
+static void ocfs2_generic_bast_func(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level)
+{
+ int needs_downconvert;
+ unsigned long flags;
+
+ mlog_entry_void();
+
+ BUG_ON(level <= LKM_NLMODE);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ needs_downconvert = ocfs2_generic_handle_bast(lockres, level);
+ if (needs_downconvert)
+ ocfs2_schedule_blocked_lock(osb, lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ ocfs2_kick_vote_thread(osb);
+
+ wake_up(&lockres->l_event);
+ mlog_exit_void();
+}
+
+static void ocfs2_inode_bast_func(void *opaque, int level)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+ struct inode *inode;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ BUG_ON(!ocfs2_is_inode_lock(lockres));
+
+ inode = ocfs2_lock_res_inode(lockres);
+ osb = OCFS2_SB(inode->i_sb);
+
+ mlog(0, "BAST fired for inode %"MLFu64", blocking = %d, level = %d "
+ "type = %s\n", OCFS2_I(inode)->ip_blkno, level,
+ lockres->l_level,
+ ocfs2_lock_type_string(lockres->l_type));
+
+ ocfs2_generic_bast_func(osb, lockres, level);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres,
+ int ignore_refresh)
+{
+ struct dlm_lockstatus *lksb = &lockres->l_lksb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ if (lksb->status != DLM_NORMAL) {
+ mlog(ML_ERROR, "lockres %s: lksb status value of %u!\n",
+ lockres->l_name, lksb->status);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ return;
+ }
+
+ switch(lockres->l_action) {
+ case OCFS2_AST_ATTACH:
+ ocfs2_generic_handle_attach_action(lockres);
+ break;
+ case OCFS2_AST_CONVERT:
+ ocfs2_generic_handle_convert_action(lockres);
+ break;
+ case OCFS2_AST_DOWNCONVERT:
+ ocfs2_generic_handle_downconvert_action(lockres);
+ break;
+ default:
+ BUG();
+ }
+
+ if (ignore_refresh)
+ lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+
+ /* set it to something invalid so if we get called again we
+ * can catch it. */
+ lockres->l_action = OCFS2_AST_INVALID;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ wake_up(&lockres->l_event);
+}
+
+static void ocfs2_super_ast_func(void *opaque)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+
+ mlog_entry_void();
+ mlog(0, "Superblock AST fired\n");
+
+ BUG_ON(!ocfs2_is_super_lock(lockres));
+ ocfs2_generic_ast_func(lockres, 0);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_super_bast_func(void *opaque,
+ int level)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+ mlog(0, "Superblock BAST fired\n");
+
+ BUG_ON(!ocfs2_is_super_lock(lockres));
+ osb = ocfs2_lock_res_super(lockres);
+ ocfs2_generic_bast_func(osb, lockres, level);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_rename_ast_func(void *opaque)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+
+ mlog_entry_void();
+
+ mlog(0, "Rename AST fired\n");
+
+ BUG_ON(!ocfs2_is_rename_lock(lockres));
+
+ ocfs2_generic_ast_func(lockres, 1);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_rename_bast_func(void *opaque,
+ int level)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ mlog(0, "Rename BAST fired\n");
+
+ BUG_ON(!ocfs2_is_rename_lock(lockres));
+
+ osb = ocfs2_lock_res_super(lockres);
+ ocfs2_generic_bast_func(osb, lockres, level);
+
+ mlog_exit_void();
+}
+
+static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,
+ int convert)
+{
+ unsigned long flags;
+
+ mlog_entry_void();
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+ if (convert)
+ lockres->l_action = OCFS2_AST_INVALID;
+ else
+ lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ wake_up(&lockres->l_event);
+ mlog_exit_void();
+}
+
+/* Note: If we detect another process working on the lock (i.e.,
+ * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller
+ * to do the right thing in that case.
+ */
+static int ocfs2_lock_create(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+ int dlm_flags)
+{
+ int ret = 0;
+ enum dlm_status status;
+ unsigned long flags;
+
+ mlog_entry_void();
+
+ mlog(0, "lock %s, level = %d, flags = %d\n", lockres->l_name, level,
+ dlm_flags);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ if ((lockres->l_flags & OCFS2_LOCK_ATTACHED) ||
+ (lockres->l_flags & OCFS2_LOCK_BUSY)) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ goto bail;
+ }
+
+ lockres->l_action = OCFS2_AST_ATTACH;
+ lockres->l_requested = level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ status = dlmlock(osb->dlm,
+ level,
+ &lockres->l_lksb,
+ dlm_flags,
+ lockres->l_name,
+ lockres->l_ops->ast,
+ lockres,
+ lockres->l_ops->bast);
+ if (status != DLM_NORMAL) {
+ ocfs2_log_dlm_error("dlmlock", status, lockres);
+ ret = -EINVAL;
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ }
+
+ mlog(0, "lock %s, successfull return from dlmlock\n", lockres->l_name);
+
+bail:
+ mlog_exit(ret);
+ return ret;
+}
+
+static inline int ocfs2_check_wait_flag(struct ocfs2_lock_res *lockres,
+ int flag)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ ret = lockres->l_flags & flag;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ return ret;
+}
+
+static inline void ocfs2_wait_on_busy_lock(struct ocfs2_lock_res *lockres)
+
+{
+ wait_event(lockres->l_event,
+ !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY));
+}
+
+static inline void ocfs2_wait_on_refreshing_lock(struct ocfs2_lock_res *lockres)
+
+{
+ wait_event(lockres->l_event,
+ !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING));
+}
+
+/* predict what lock level we'll be dropping down to on behalf
+ * of another node, and return true if the currently wanted
+ * level will be compatible with it. */
+static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
+ int wanted)
+{
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+
+ return wanted <= ocfs2_highest_compat_lock_level(lockres->l_blocking);
+}
+
+static void ocfs2_init_mask_waiter(struct ocfs2_mask_waiter *mw)
+{
+ INIT_LIST_HEAD(&mw->mw_item);
+ init_completion(&mw->mw_complete);
+}
+
+static int ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw)
+{
+ wait_for_completion(&mw->mw_complete);
+ /* Re-arm the completion in case we want to wait on it again */
+ INIT_COMPLETION(mw->mw_complete);
+ return mw->mw_status;
+}
+
+static void lockres_add_mask_waiter(struct ocfs2_lock_res *lockres,
+ struct ocfs2_mask_waiter *mw,
+ unsigned long mask,
+ unsigned long goal)
+{
+ BUG_ON(!list_empty(&mw->mw_item));
+
+ assert_spin_locked(&lockres->l_lock);
+
+ list_add_tail(&mw->mw_item, &lockres->l_mask_waiters);
+ mw->mw_mask = mask;
+ mw->mw_goal = goal;
+}
+
+/* returns 0 if the mw that was removed was already satisfied, -EBUSY
+ * if the mask still hadn't reached its goal */
+static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
+ struct ocfs2_mask_waiter *mw)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ if (!list_empty(&mw->mw_item)) {
+ if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)
+ ret = -EBUSY;
+
+ list_del_init(&mw->mw_item);
+ init_completion(&mw->mw_complete);
+ }
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ return ret;
+
+}
+
+static int ocfs2_cluster_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level,
+ int lkm_flags,
+ int arg_flags)
+{
+ struct ocfs2_mask_waiter mw;
+ enum dlm_status status;
+ int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR);
+ int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */
+ unsigned long flags;
+
+ mlog_entry_void();
+
+ ocfs2_init_mask_waiter(&mw);
+
+again:
+ wait = 0;
+
+ if (catch_signals && signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ goto out;
+ }
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING,
+ "Cluster lock called on freeing lockres %s! flags "
+ "0x%lx\n", lockres->l_name, lockres->l_flags);
+
+ /* We only compare against the currently granted level
+ * here. If the lock is blocked waiting on a downconvert,
+ * we'll get caught below. */
+ if (lockres->l_flags & OCFS2_LOCK_BUSY &&
+ level > lockres->l_level) {
+ /* is someone sitting in dlm_lock? If so, wait on
+ * them. */
+ lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
+ wait = 1;
+ goto unlock;
+ }
+
+ if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
+ /* lock has not been created yet. */
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ goto again;
+ }
+
+ if (lockres->l_flags & OCFS2_LOCK_BLOCKED &&
+ !ocfs2_may_continue_on_blocked_lock(lockres, level)) {
+ /* is the lock is currently blocked on behalf of
+ * another node */
+ lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BLOCKED, 0);
+ wait = 1;
+ goto unlock;
+ }
+
+ if (level > lockres->l_level) {
+ if (lockres->l_action != OCFS2_AST_INVALID)
+ mlog(ML_ERROR, "lockres %s has action %u pending\n",
+ lockres->l_name, lockres->l_action);
+
+ lockres->l_action = OCFS2_AST_CONVERT;
+ lockres->l_requested = level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ BUG_ON(level == LKM_IVMODE);
+ BUG_ON(level == LKM_NLMODE);
+
+ mlog(0, "lock %s, convert from %d to level = %d\n",
+ lockres->l_name, lockres->l_level, level);
+
+ /* call dlm_lock to upgrade lock now */
+ status = dlmlock(osb->dlm,
+ level,
+ &lockres->l_lksb,
+ lkm_flags|LKM_CONVERT|LKM_VALBLK,
+ lockres->l_name,
+ lockres->l_ops->ast,
+ lockres,
+ lockres->l_ops->bast);
+ if (status != DLM_NORMAL) {
+ if ((lkm_flags & LKM_NOQUEUE) &&
+ (status == DLM_NOTQUEUED))
+ ret = -EAGAIN;
+ else {
+ ocfs2_log_dlm_error("dlmlock", status,
+ lockres);
+ ret = -EINVAL;
+ }
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ goto out;
+ }
+
+ mlog(0, "lock %s, successfull return from dlmlock\n",
+ lockres->l_name);
+
+ /* At this point we've gone inside the dlm and need to
+ * complete our work regardless. */
+ catch_signals = 0;
+
+ /* wait for busy to clear and carry on */
+ goto again;
+ }
+
+ /* Ok, if we get here then we're good to go. */
+ ocfs2_inc_holders(lockres, level);
+
+ ret = 0;
+unlock:
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+out:
+ /*
+ * This is helping work around a lock inversion between the page lock
+ * and dlm locks. One path holds the page lock while calling aops
+ * which block acquiring dlm locks. The voting thread holds dlm
+ * locks while acquiring page locks while down converting data locks.
+ * This block is helping an aop path notice the inversion and back
+ * off to unlock its page lock before trying the dlm lock again.
+ */
+ if (wait && arg_flags & OCFS2_LOCK_NONBLOCK &&
+ mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) {
+ wait = 0;
+ if (lockres_remove_mask_waiter(lockres, &mw))
+ ret = -EAGAIN;
+ else
+ goto again;
+ }
+ if (wait) {
+ ret = ocfs2_wait_for_mask(&mw);
+ if (ret == 0)
+ goto again;
+ mlog_errno(ret);
+ }
+
+ mlog_exit(ret);
+ return ret;
+}
+
+static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int level)
+{
+ unsigned long flags;
+
+ mlog_entry_void();
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ ocfs2_dec_holders(lockres, level);
+ ocfs2_vote_on_unlock(osb, lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ mlog_exit_void();
+}
+
+static int ocfs2_create_new_inode_lock(struct inode *inode,
+ struct ocfs2_lock_res *lockres)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ unsigned long flags;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
+ lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ return ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL);
+}
+
+/* Grants us an EX lock on the data and metadata resources, skipping
+ * the normal cluster directory lookup. Use this ONLY on newly created
+ * inodes which other nodes can't possibly see, and which haven't been
+ * hashed in the inode hash yet. This can give us a good performance
+ * increase as it'll skip the network broadcast normally associated
+ * with creating a new lock resource. */
+int ocfs2_create_new_inode_locks(struct inode *inode)
+{
+ int ret;
+
+ BUG_ON(!inode);
+ BUG_ON(!ocfs2_inode_is_new(inode));
+
+ mlog_entry_void();
+
+ mlog(0, "Inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+
+ /* NOTE: That we don't increment any of the holder counts, nor
+ * do we add anything to a journal handle. Since this is
+ * supposed to be a new inode which the cluster doesn't know
+ * about yet, there is no need to. As far as the LVB handling
+ * is concerned, this is basically like acquiring an EX lock
+ * on a resource which has an invalid one -- we'll set it
+ * valid when we release the EX. */
+
+ ret = ocfs2_create_new_inode_lock(inode,
+ &OCFS2_I(inode)->ip_rw_lockres);
+ if (ret) {
+ mlog_errno(ret);
+ goto bail;
+ }
+
+ ret = ocfs2_create_new_inode_lock(inode,
+ &OCFS2_I(inode)->ip_meta_lockres);
+ if (ret) {
+ mlog_errno(ret);
+ goto bail;
+ }
+
+ ret = ocfs2_create_new_inode_lock(inode,
+ &OCFS2_I(inode)->ip_data_lockres);
+ if (ret) {
+ mlog_errno(ret);
+ goto bail;
+ }
+
+bail:
+ mlog_exit(ret);
+ return ret;
+}
+
+int ocfs2_rw_lock(struct inode *inode, int write)
+{
+ int status, level;
+ struct ocfs2_lock_res *lockres;
+
+ BUG_ON(!inode);
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64" take %s RW lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ write ? "EXMODE" : "PRMODE");
+
+ lockres = &OCFS2_I(inode)->ip_rw_lockres;
+
+ level = write ? LKM_EXMODE : LKM_PRMODE;
+
+ status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level, 0,
+ 0);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_rw_unlock(struct inode *inode, int write)
+{
+ int level = write ? LKM_EXMODE : LKM_PRMODE;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres;
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64" drop %s RW lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ write ? "EXMODE" : "PRMODE");
+
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+
+ mlog_exit_void();
+}
+
+int ocfs2_data_lock_full(struct inode *inode,
+ int write,
+ int arg_flags)
+{
+ int status = 0, level;
+ struct ocfs2_lock_res *lockres;
+
+ BUG_ON(!inode);
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64" take %s DATA lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ write ? "EXMODE" : "PRMODE");
+
+ /* We'll allow faking a readonly data lock for
+ * rodevices. */
+ if (ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb))) {
+ if (write) {
+ status = -EROFS;
+ mlog_errno(status);
+ }
+ goto out;
+ }
+
+ lockres = &OCFS2_I(inode)->ip_data_lockres;
+
+ level = write ? LKM_EXMODE : LKM_PRMODE;
+
+ status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level,
+ 0, arg_flags);
+ if (status < 0 && status != -EAGAIN)
+ mlog_errno(status);
+
+out:
+ mlog_exit(status);
+ return status;
+}
+
+/* see ocfs2_meta_lock_with_page() */
+int ocfs2_data_lock_with_page(struct inode *inode,
+ int write,
+ struct page *page)
+{
+ int ret;
+
+ ret = ocfs2_data_lock_full(inode, write, OCFS2_LOCK_NONBLOCK);
+ if (ret == -EAGAIN) {
+ unlock_page(page);
+ if (ocfs2_data_lock(inode, write) == 0)
+ ocfs2_data_unlock(inode, write);
+ ret = AOP_TRUNCATED_PAGE;
+ }
+
+ return ret;
+}
+
+static void ocfs2_vote_on_unlock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+{
+ int kick = 0;
+
+ mlog_entry_void();
+
+ /* If we know that another node is waiting on our lock, kick
+ * the vote thread * pre-emptively when we reach a release
+ * condition. */
+ if (lockres->l_flags & OCFS2_LOCK_BLOCKED) {
+ switch(lockres->l_blocking) {
+ case LKM_EXMODE:
+ if (!lockres->l_ex_holders && !lockres->l_ro_holders)
+ kick = 1;
+ break;
+ case LKM_PRMODE:
+ if (!lockres->l_ex_holders)
+ kick = 1;
+ break;
+ default:
+ BUG();
+ }
+ }
+
+ if (kick)
+ ocfs2_kick_vote_thread(osb);
+
+ mlog_exit_void();
+}
+
+void ocfs2_data_unlock(struct inode *inode,
+ int write)
+{
+ int level = write ? LKM_EXMODE : LKM_PRMODE;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres;
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64" drop %s DATA lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ write ? "EXMODE" : "PRMODE");
+
+ if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+
+ mlog_exit_void();
+}
+
+#define OCFS2_SEC_BITS 34
+#define OCFS2_SEC_SHIFT (64 - 34)
+#define OCFS2_NSEC_MASK ((1ULL << OCFS2_SEC_SHIFT) - 1)
+
+/* LVB only has room for 64 bits of time here so we pack it for
+ * now. */
+static u64 ocfs2_pack_timespec(struct timespec *spec)
+{
+ u64 res;
+ u64 sec = spec->tv_sec;
+ u32 nsec = spec->tv_nsec;
+
+ res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK);
+
+ return res;
+}
+
+/* Call this with the lockres locked. I am reasonably sure we don't
+ * need ip_lock in this function as anyone who would be changing those
+ * values is supposed to be blocked in ocfs2_meta_lock right now. */
+static void __ocfs2_stuff_meta_lvb(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_lock_res *lockres = &oi->ip_meta_lockres;
+ struct ocfs2_meta_lvb *lvb;
+
+ mlog_entry_void();
+
+ lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+ lvb->lvb_version = cpu_to_be32(OCFS2_LVB_VERSION);
+ lvb->lvb_isize = cpu_to_be64(i_size_read(inode));
+ lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters);
+ lvb->lvb_iuid = cpu_to_be32(inode->i_uid);
+ lvb->lvb_igid = cpu_to_be32(inode->i_gid);
+ lvb->lvb_imode = cpu_to_be16(inode->i_mode);
+ lvb->lvb_inlink = cpu_to_be16(inode->i_nlink);
+ lvb->lvb_iatime_packed =
+ cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime));
+ lvb->lvb_ictime_packed =
+ cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime));
+ lvb->lvb_imtime_packed =
+ cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
+
+ mlog_meta_lvb(0, lockres);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_unpack_timespec(struct timespec *spec,
+ u64 packed_time)
+{
+ spec->tv_sec = packed_time >> OCFS2_SEC_SHIFT;
+ spec->tv_nsec = packed_time & OCFS2_NSEC_MASK;
+}
+
+static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_lock_res *lockres = &oi->ip_meta_lockres;
+ struct ocfs2_meta_lvb *lvb;
+
+ mlog_entry_void();
+
+ mlog_meta_lvb(0, lockres);
+
+ lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+ /* We're safe here without the lockres lock... */
+ spin_lock(&oi->ip_lock);
+ oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters);
+ i_size_write(inode, be64_to_cpu(lvb->lvb_isize));
+
+ /* fast-symlinks are a special case */
+ if (S_ISLNK(inode->i_mode) && !oi->ip_clusters)
+ inode->i_blocks = 0;
+ else
+ inode->i_blocks =
+ ocfs2_align_bytes_to_sectors(i_size_read(inode));
+
+ inode->i_uid = be32_to_cpu(lvb->lvb_iuid);
+ inode->i_gid = be32_to_cpu(lvb->lvb_igid);
+ inode->i_mode = be16_to_cpu(lvb->lvb_imode);
+ inode->i_nlink = be16_to_cpu(lvb->lvb_inlink);
+ ocfs2_unpack_timespec(&inode->i_atime,
+ be64_to_cpu(lvb->lvb_iatime_packed));
+ ocfs2_unpack_timespec(&inode->i_mtime,
+ be64_to_cpu(lvb->lvb_imtime_packed));
+ ocfs2_unpack_timespec(&inode->i_ctime,
+ be64_to_cpu(lvb->lvb_ictime_packed));
+ spin_unlock(&oi->ip_lock);
+
+ mlog_exit_void();
+}
+
+static inline int ocfs2_meta_lvb_is_trustable(struct ocfs2_lock_res *lockres)
+{
+ struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+ if (be32_to_cpu(lvb->lvb_version) == OCFS2_LVB_VERSION)
+ return 1;
+ return 0;
+}
+
+/* Determine whether a lock resource needs to be refreshed, and
+ * arbitrate who gets to refresh it.
+ *
+ * 0 means no refresh needed.
+ *
+ * > 0 means you need to refresh this and you MUST call
+ * ocfs2_complete_lock_res_refresh afterwards. */
+static int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres)
+{
+ unsigned long flags;
+ int status = 0;
+
+ mlog_entry_void();
+
+refresh_check:
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ goto bail;
+ }
+
+ if (lockres->l_flags & OCFS2_LOCK_REFRESHING) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ ocfs2_wait_on_refreshing_lock(lockres);
+ goto refresh_check;
+ }
+
+ /* Ok, I'll be the one to refresh this lock. */
+ lockres_or_flags(lockres, OCFS2_LOCK_REFRESHING);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ status = 1;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* If status is non zero, I'll mark it as not being in refresh
+ * anymroe, but i won't clear the needs refresh flag. */
+static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockres,
+ int status)
+{
+ unsigned long flags;
+ mlog_entry_void();
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING);
+ if (!status)
+ lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ wake_up(&lockres->l_event);
+
+ mlog_exit_void();
+}
+
+/* may or may not return a bh if it went to disk. */
+static int ocfs2_meta_lock_update(struct inode *inode,
+ struct buffer_head **bh)
+{
+ int status = 0;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_lock_res *lockres;
+ struct ocfs2_dinode *fe;
+
+ mlog_entry_void();
+
+ spin_lock(&oi->ip_lock);
+ if (oi->ip_flags & OCFS2_INODE_DELETED) {
+ mlog(0, "Orphaned inode %"MLFu64" was deleted while we "
+ "were waiting on a lock. ip_flags = 0x%x\n",
+ oi->ip_blkno, oi->ip_flags);
+ spin_unlock(&oi->ip_lock);
+ status = -ENOENT;
+ goto bail;
+ }
+ spin_unlock(&oi->ip_lock);
+
+ lockres = &oi->ip_meta_lockres;
+
+ if (!ocfs2_should_refresh_lock_res(lockres))
+ goto bail;
+
+ /* This will discard any caching information we might have had
+ * for the inode metadata. */
+ ocfs2_metadata_cache_purge(inode);
+
+ /* will do nothing for inode types that don't use the extent
+ * map (directories, bitmap files, etc) */
+ ocfs2_extent_map_trunc(inode, 0);
+
+ if (ocfs2_meta_lvb_is_trustable(lockres)) {
+ mlog(0, "Trusting LVB on inode %"MLFu64"\n",
+ oi->ip_blkno);
+ ocfs2_refresh_inode_from_lvb(inode);
+ } else {
+ /* Boo, we have to go to disk. */
+ /* read bh, cast, ocfs2_refresh_inode */
+ status = ocfs2_read_block(OCFS2_SB(inode->i_sb), oi->ip_blkno,
+ bh, OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_refresh;
+ }
+ fe = (struct ocfs2_dinode *) (*bh)->b_data;
+
+ /* This is a good chance to make sure we're not
+ * locking an invalid object.
+ *
+ * We bug on a stale inode here because we checked
+ * above whether it was wiped from disk. The wiping
+ * node provides a guarantee that we receive that
+ * message and can mark the inode before dropping any
+ * locks associated with it. */
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+ status = -EIO;
+ goto bail_refresh;
+ }
+ mlog_bug_on_msg(inode->i_generation !=
+ le32_to_cpu(fe->i_generation),
+ "Invalid dinode %"MLFu64" disk generation: %u "
+ "inode->i_generation: %u\n",
+ oi->ip_blkno, le32_to_cpu(fe->i_generation),
+ inode->i_generation);
+ mlog_bug_on_msg(le64_to_cpu(fe->i_dtime) ||
+ !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)),
+ "Stale dinode %"MLFu64" dtime: %"MLFu64" "
+ "flags: 0x%x\n", oi->ip_blkno,
+ le64_to_cpu(fe->i_dtime),
+ le32_to_cpu(fe->i_flags));
+
+ ocfs2_refresh_inode(inode, fe);
+ }
+
+ status = 0;
+bail_refresh:
+ ocfs2_complete_lock_res_refresh(lockres, status);
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_assign_bh(struct inode *inode,
+ struct buffer_head **ret_bh,
+ struct buffer_head *passed_bh)
+{
+ int status;
+
+ if (passed_bh) {
+ /* Ok, the update went to disk for us, use the
+ * returned bh. */
+ *ret_bh = passed_bh;
+ get_bh(*ret_bh);
+
+ return 0;
+ }
+
+ status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ OCFS2_I(inode)->ip_blkno,
+ ret_bh,
+ OCFS2_BH_CACHED,
+ inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ return status;
+}
+
+/*
+ * returns < 0 error if the callback will never be called, otherwise
+ * the result of the lock will be communicated via the callback.
+ */
+int ocfs2_meta_lock_full(struct inode *inode,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **ret_bh,
+ int ex,
+ int arg_flags)
+{
+ int status, level, dlm_flags, acquired;
+ struct ocfs2_lock_res *lockres;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct buffer_head *local_bh = NULL;
+
+ BUG_ON(!inode);
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64", take %s META lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ ex ? "EXMODE" : "PRMODE");
+
+ status = 0;
+ acquired = 0;
+ /* We'll allow faking a readonly metadata lock for
+ * rodevices. */
+ if (ocfs2_is_hard_readonly(osb)) {
+ if (ex)
+ status = -EROFS;
+ goto bail;
+ }
+
+ if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+ wait_event(osb->recovery_event,
+ ocfs2_node_map_is_empty(osb, &osb->recovery_map));
+
+ acquired = 0;
+ lockres = &OCFS2_I(inode)->ip_meta_lockres;
+ level = ex ? LKM_EXMODE : LKM_PRMODE;
+ dlm_flags = 0;
+ if (arg_flags & OCFS2_META_LOCK_NOQUEUE)
+ dlm_flags |= LKM_NOQUEUE;
+
+ status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags);
+ if (status < 0) {
+ if (status != -EAGAIN && status != -EIOCBRETRY)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Notify the error cleanup path to drop the cluster lock. */
+ acquired = 1;
+
+ /* We wait twice because a node may have died while we were in
+ * the lower dlm layers. The second time though, we've
+ * committed to owning this lock so we don't allow signals to
+ * abort the operation. */
+ if (!(arg_flags & OCFS2_META_LOCK_RECOVERY))
+ wait_event(osb->recovery_event,
+ ocfs2_node_map_is_empty(osb, &osb->recovery_map));
+
+ /* This is fun. The caller may want a bh back, or it may
+ * not. ocfs2_meta_lock_update definitely wants one in, but
+ * may or may not read one, depending on what's in the
+ * LVB. The result of all of this is that we've *only* gone to
+ * disk if we have to, so the complexity is worthwhile. */
+ status = ocfs2_meta_lock_update(inode, &local_bh);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (ret_bh) {
+ status = ocfs2_assign_bh(inode, ret_bh, local_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ if (handle) {
+ status = ocfs2_handle_add_lock(handle, inode);
+ if (status < 0)
+ mlog_errno(status);
+ }
+
+bail:
+ if (status < 0) {
+ if (ret_bh && (*ret_bh)) {
+ brelse(*ret_bh);
+ *ret_bh = NULL;
+ }
+ if (acquired)
+ ocfs2_meta_unlock(inode, ex);
+ }
+
+ if (local_bh)
+ brelse(local_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * This is working around a lock inversion between tasks acquiring DLM locks
+ * while holding a page lock and the vote thread which blocks dlm lock acquiry
+ * while acquiring page locks.
+ *
+ * ** These _with_page variantes are only intended to be called from aop
+ * methods that hold page locks and return a very specific *positive* error
+ * code that aop methods pass up to the VFS -- test for errors with != 0. **
+ *
+ * The DLM is called such that it returns -EAGAIN if it would have blocked
+ * waiting for the vote thread. In that case we unlock our page so the vote
+ * thread can make progress. Once we've done this we have to return
+ * AOP_TRUNCATED_PAGE so the aop method that called us can bubble that back up
+ * into the VFS who will then immediately retry the aop call.
+ *
+ * We do a blocking lock and immediate unlock before returning, though, so that
+ * the lock has a great chance of being cached on this node by the time the VFS
+ * calls back to retry the aop. This has a potential to livelock as nodes
+ * ping locks back and forth, but that's a risk we're willing to take to avoid
+ * the lock inversion simply.
+ */
+int ocfs2_meta_lock_with_page(struct inode *inode,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **ret_bh,
+ int ex,
+ struct page *page)
+{
+ int ret;
+
+ ret = ocfs2_meta_lock_full(inode, handle, ret_bh, ex,
+ OCFS2_LOCK_NONBLOCK);
+ if (ret == -EAGAIN) {
+ unlock_page(page);
+ if (ocfs2_meta_lock(inode, handle, ret_bh, ex) == 0)
+ ocfs2_meta_unlock(inode, ex);
+ ret = AOP_TRUNCATED_PAGE;
+ }
+
+ return ret;
+}
+
+void ocfs2_meta_unlock(struct inode *inode,
+ int ex)
+{
+ int level = ex ? LKM_EXMODE : LKM_PRMODE;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
+
+ mlog_entry_void();
+
+ mlog(0, "inode %"MLFu64" drop %s META lock\n",
+ OCFS2_I(inode)->ip_blkno,
+ ex ? "EXMODE" : "PRMODE");
+
+ if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)))
+ ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);
+
+ mlog_exit_void();
+}
+
+int ocfs2_super_lock(struct ocfs2_super *osb,
+ int ex)
+{
+ int status;
+ int level = ex ? LKM_EXMODE : LKM_PRMODE;
+ struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+ struct buffer_head *bh;
+ struct ocfs2_slot_info *si = osb->slot_info;
+
+ mlog_entry_void();
+
+ if (ocfs2_is_hard_readonly(osb))
+ return -EROFS;
+
+ status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* The super block lock path is really in the best position to
+ * know when resources covered by the lock need to be
+ * refreshed, so we do it here. Of course, making sense of
+ * everything is up to the caller :) */
+ status = ocfs2_should_refresh_lock_res(lockres);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ if (status) {
+ bh = si->si_bh;
+ status = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0,
+ si->si_inode);
+ if (status == 0)
+ ocfs2_update_slot_info(si);
+
+ ocfs2_complete_lock_res_refresh(lockres, status);
+
+ if (status < 0)
+ mlog_errno(status);
+ }
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_super_unlock(struct ocfs2_super *osb,
+ int ex)
+{
+ int level = ex ? LKM_EXMODE : LKM_PRMODE;
+ struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;
+
+ ocfs2_cluster_unlock(osb, lockres, level);
+}
+
+int ocfs2_rename_lock(struct ocfs2_super *osb)
+{
+ int status;
+ struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
+
+ if (ocfs2_is_hard_readonly(osb))
+ return -EROFS;
+
+ status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);
+ if (status < 0)
+ mlog_errno(status);
+
+ return status;
+}
+
+void ocfs2_rename_unlock(struct ocfs2_super *osb)
+{
+ struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;
+
+ ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);
+}
+
+/* Reference counting of the dlm debug structure. We want this because
+ * open references on the debug inodes can live on after a mount, so
+ * we can't rely on the ocfs2_super to always exist. */
+static void ocfs2_dlm_debug_free(struct kref *kref)
+{
+ struct ocfs2_dlm_debug *dlm_debug;
+
+ dlm_debug = container_of(kref, struct ocfs2_dlm_debug, d_refcnt);
+
+ kfree(dlm_debug);
+}
+
+void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug)
+{
+ if (dlm_debug)
+ kref_put(&dlm_debug->d_refcnt, ocfs2_dlm_debug_free);
+}
+
+static void ocfs2_get_dlm_debug(struct ocfs2_dlm_debug *debug)
+{
+ kref_get(&debug->d_refcnt);
+}
+
+struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void)
+{
+ struct ocfs2_dlm_debug *dlm_debug;
+
+ dlm_debug = kmalloc(sizeof(struct ocfs2_dlm_debug), GFP_KERNEL);
+ if (!dlm_debug) {
+ mlog_errno(-ENOMEM);
+ goto out;
+ }
+
+ kref_init(&dlm_debug->d_refcnt);
+ INIT_LIST_HEAD(&dlm_debug->d_lockres_tracking);
+ dlm_debug->d_locking_state = NULL;
+out:
+ return dlm_debug;
+}
+
+/* Access to this is arbitrated for us via seq_file->sem. */
+struct ocfs2_dlm_seq_priv {
+ struct ocfs2_dlm_debug *p_dlm_debug;
+ struct ocfs2_lock_res p_iter_res;
+ struct ocfs2_lock_res p_tmp_res;
+};
+
+static struct ocfs2_lock_res *ocfs2_dlm_next_res(struct ocfs2_lock_res *start,
+ struct ocfs2_dlm_seq_priv *priv)
+{
+ struct ocfs2_lock_res *iter, *ret = NULL;
+ struct ocfs2_dlm_debug *dlm_debug = priv->p_dlm_debug;
+
+ assert_spin_locked(&ocfs2_dlm_tracking_lock);
+
+ list_for_each_entry(iter, &start->l_debug_list, l_debug_list) {
+ /* discover the head of the list */
+ if (&iter->l_debug_list == &dlm_debug->d_lockres_tracking) {
+ mlog(0, "End of list found, %p\n", ret);
+ break;
+ }
+
+ /* We track our "dummy" iteration lockres' by a NULL
+ * l_ops field. */
+ if (iter->l_ops != NULL) {
+ ret = iter;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void *ocfs2_dlm_seq_start(struct seq_file *m, loff_t *pos)
+{
+ struct ocfs2_dlm_seq_priv *priv = m->private;
+ struct ocfs2_lock_res *iter;
+
+ spin_lock(&ocfs2_dlm_tracking_lock);
+ iter = ocfs2_dlm_next_res(&priv->p_iter_res, priv);
+ if (iter) {
+ /* Since lockres' have the lifetime of their container
+ * (which can be inodes, ocfs2_supers, etc) we want to
+ * copy this out to a temporary lockres while still
+ * under the spinlock. Obviously after this we can't
+ * trust any pointers on the copy returned, but that's
+ * ok as the information we want isn't typically held
+ * in them. */
+ priv->p_tmp_res = *iter;
+ iter = &priv->p_tmp_res;
+ }
+ spin_unlock(&ocfs2_dlm_tracking_lock);
+
+ return iter;
+}
+
+static void ocfs2_dlm_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct ocfs2_dlm_seq_priv *priv = m->private;
+ struct ocfs2_lock_res *iter = v;
+ struct ocfs2_lock_res *dummy = &priv->p_iter_res;
+
+ spin_lock(&ocfs2_dlm_tracking_lock);
+ iter = ocfs2_dlm_next_res(iter, priv);
+ list_del_init(&dummy->l_debug_list);
+ if (iter) {
+ list_add(&dummy->l_debug_list, &iter->l_debug_list);
+ priv->p_tmp_res = *iter;
+ iter = &priv->p_tmp_res;
+ }
+ spin_unlock(&ocfs2_dlm_tracking_lock);
+
+ return iter;
+}
+
+/* So that debugfs.ocfs2 can determine which format is being used */
+#define OCFS2_DLM_DEBUG_STR_VERSION 1
+static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
+{
+ int i;
+ char *lvb;
+ struct ocfs2_lock_res *lockres = v;
+
+ if (!lockres)
+ return -EINVAL;
+
+ seq_printf(m, "0x%x\t"
+ "%.*s\t"
+ "%d\t"
+ "0x%lx\t"
+ "0x%x\t"
+ "0x%x\t"
+ "%u\t"
+ "%u\t"
+ "%d\t"
+ "%d\t",
+ OCFS2_DLM_DEBUG_STR_VERSION,
+ OCFS2_LOCK_ID_MAX_LEN, lockres->l_name,
+ lockres->l_level,
+ lockres->l_flags,
+ lockres->l_action,
+ lockres->l_unlock_action,
+ lockres->l_ro_holders,
+ lockres->l_ex_holders,
+ lockres->l_requested,
+ lockres->l_blocking);
+
+ /* Dump the raw LVB */
+ lvb = lockres->l_lksb.lvb;
+ for(i = 0; i < DLM_LVB_LEN; i++)
+ seq_printf(m, "0x%x\t", lvb[i]);
+
+ /* End the line */
+ seq_printf(m, "\n");
+ return 0;
+}
+
+static struct seq_operations ocfs2_dlm_seq_ops = {
+ .start = ocfs2_dlm_seq_start,
+ .stop = ocfs2_dlm_seq_stop,
+ .next = ocfs2_dlm_seq_next,
+ .show = ocfs2_dlm_seq_show,
+};
+
+static int ocfs2_dlm_debug_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = (struct seq_file *) file->private_data;
+ struct ocfs2_dlm_seq_priv *priv = seq->private;
+ struct ocfs2_lock_res *res = &priv->p_iter_res;
+
+ ocfs2_remove_lockres_tracking(res);
+ ocfs2_put_dlm_debug(priv->p_dlm_debug);
+ return seq_release_private(inode, file);
+}
+
+static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ struct ocfs2_dlm_seq_priv *priv;
+ struct seq_file *seq;
+ struct ocfs2_super *osb;
+
+ priv = kzalloc(sizeof(struct ocfs2_dlm_seq_priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+ osb = (struct ocfs2_super *) inode->u.generic_ip;
+ ocfs2_get_dlm_debug(osb->osb_dlm_debug);
+ priv->p_dlm_debug = osb->osb_dlm_debug;
+ INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);
+
+ ret = seq_open(file, &ocfs2_dlm_seq_ops);
+ if (ret) {
+ kfree(priv);
+ mlog_errno(ret);
+ goto out;
+ }
+
+ seq = (struct seq_file *) file->private_data;
+ seq->private = priv;
+
+ ocfs2_add_lockres_tracking(&priv->p_iter_res,
+ priv->p_dlm_debug);
+
+out:
+ return ret;
+}
+
+static struct file_operations ocfs2_dlm_debug_fops = {
+ .open = ocfs2_dlm_debug_open,
+ .release = ocfs2_dlm_debug_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+static int ocfs2_dlm_init_debug(struct ocfs2_super *osb)
+{
+ int ret = 0;
+ struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;
+
+ dlm_debug->d_locking_state = debugfs_create_file("locking_state",
+ S_IFREG|S_IRUSR,
+ osb->osb_debug_root,
+ osb,
+ &ocfs2_dlm_debug_fops);
+ if (!dlm_debug->d_locking_state) {
+ ret = -EINVAL;
+ mlog(ML_ERROR,
+ "Unable to create locking state debugfs file.\n");
+ goto out;
+ }
+
+ ocfs2_get_dlm_debug(dlm_debug);
+out:
+ return ret;
+}
+
+static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
+{
+ struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;
+
+ if (dlm_debug) {
+ debugfs_remove(dlm_debug->d_locking_state);
+ ocfs2_put_dlm_debug(dlm_debug);
+ }
+}
+
+int ocfs2_dlm_init(struct ocfs2_super *osb)
+{
+ int status;
+ u32 dlm_key;
+ struct dlm_ctxt *dlm;
+
+ mlog_entry_void();
+
+ status = ocfs2_dlm_init_debug(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* launch vote thread */
+ osb->vote_task = kthread_run(ocfs2_vote_thread, osb, "ocfs2vote-%d",
+ osb->osb_id);
+ if (IS_ERR(osb->vote_task)) {
+ status = PTR_ERR(osb->vote_task);
+ osb->vote_task = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* used by the dlm code to make message headers unique, each
+ * node in this domain must agree on this. */
+ dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str));
+
+ /* for now, uuid == domain */
+ dlm = dlm_register_domain(osb->uuid_str, dlm_key);
+ if (IS_ERR(dlm)) {
+ status = PTR_ERR(dlm);
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
+ ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
+
+ dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);
+
+ osb->dlm = dlm;
+
+ status = 0;
+bail:
+ if (status < 0) {
+ ocfs2_dlm_shutdown_debug(osb);
+ if (osb->vote_task)
+ kthread_stop(osb->vote_task);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
+{
+ mlog_entry_void();
+
+ dlm_unregister_eviction_cb(&osb->osb_eviction_cb);
+
+ ocfs2_drop_osb_locks(osb);
+
+ if (osb->vote_task) {
+ kthread_stop(osb->vote_task);
+ osb->vote_task = NULL;
+ }
+
+ ocfs2_lock_res_free(&osb->osb_super_lockres);
+ ocfs2_lock_res_free(&osb->osb_rename_lockres);
+
+ dlm_unregister_domain(osb->dlm);
+ osb->dlm = NULL;
+
+ ocfs2_dlm_shutdown_debug(osb);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_unlock_ast_func(void *opaque, enum dlm_status status)
+{
+ struct ocfs2_lock_res *lockres = opaque;
+ unsigned long flags;
+
+ mlog_entry_void();
+
+ mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name,
+ lockres->l_unlock_action);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ /* We tried to cancel a convert request, but it was already
+ * granted. All we want to do here is clear our unlock
+ * state. The wake_up call done at the bottom is redundant
+ * (ocfs2_prepare_cancel_convert doesn't sleep on this) but doesn't
+ * hurt anything anyway */
+ if (status == DLM_CANCELGRANT &&
+ lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+ mlog(0, "Got cancelgrant for %s\n", lockres->l_name);
+
+ /* We don't clear the busy flag in this case as it
+ * should have been cleared by the ast which the dlm
+ * has called. */
+ goto complete_unlock;
+ }
+
+ if (status != DLM_NORMAL) {
+ mlog(ML_ERROR, "Dlm passes status %d for lock %s, "
+ "unlock_action %d\n", status, lockres->l_name,
+ lockres->l_unlock_action);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ return;
+ }
+
+ switch(lockres->l_unlock_action) {
+ case OCFS2_UNLOCK_CANCEL_CONVERT:
+ mlog(0, "Cancel convert success for %s\n", lockres->l_name);
+ lockres->l_action = OCFS2_AST_INVALID;
+ break;
+ case OCFS2_UNLOCK_DROP_LOCK:
+ lockres->l_level = LKM_IVMODE;
+ break;
+ default:
+ BUG();
+ }
+
+ lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);
+complete_unlock:
+ lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ wake_up(&lockres->l_event);
+
+ mlog_exit_void();
+}
+
+typedef void (ocfs2_pre_drop_cb_t)(struct ocfs2_lock_res *, void *);
+
+struct drop_lock_cb {
+ ocfs2_pre_drop_cb_t *drop_func;
+ void *drop_data;
+};
+
+static int ocfs2_drop_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ struct drop_lock_cb *dcb)
+{
+ enum dlm_status status;
+ unsigned long flags;
+
+ /* We didn't get anywhere near actually using this lockres. */
+ if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED))
+ goto out;
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_FREEING),
+ "lockres %s, flags 0x%lx\n",
+ lockres->l_name, lockres->l_flags);
+
+ while (lockres->l_flags & OCFS2_LOCK_BUSY) {
+ mlog(0, "waiting on busy lock \"%s\": flags = %lx, action = "
+ "%u, unlock_action = %u\n",
+ lockres->l_name, lockres->l_flags, lockres->l_action,
+ lockres->l_unlock_action);
+
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ /* XXX: Today we just wait on any busy
+ * locks... Perhaps we need to cancel converts in the
+ * future? */
+ ocfs2_wait_on_busy_lock(lockres);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ }
+
+ if (dcb)
+ dcb->drop_func(lockres, dcb->drop_data);
+
+ if (lockres->l_flags & OCFS2_LOCK_BUSY)
+ mlog(ML_ERROR, "destroying busy lock: \"%s\"\n",
+ lockres->l_name);
+ if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
+ mlog(0, "destroying blocked lock: \"%s\"\n", lockres->l_name);
+
+ if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ goto out;
+ }
+
+ lockres_clear_flags(lockres, OCFS2_LOCK_ATTACHED);
+
+ /* make sure we never get here while waiting for an ast to
+ * fire. */
+ BUG_ON(lockres->l_action != OCFS2_AST_INVALID);
+
+ /* is this necessary? */
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
+ lockres->l_unlock_action = OCFS2_UNLOCK_DROP_LOCK;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ mlog(0, "lock %s\n", lockres->l_name);
+
+ status = dlmunlock(osb->dlm, &lockres->l_lksb, LKM_VALBLK,
+ lockres->l_ops->unlock_ast, lockres);
+ if (status != DLM_NORMAL) {
+ ocfs2_log_dlm_error("dlmunlock", status, lockres);
+ mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags);
+ dlm_print_one_lock(lockres->l_lksb.lockid);
+ BUG();
+ }
+ mlog(0, "lock %s, successfull return from dlmunlock\n",
+ lockres->l_name);
+
+ ocfs2_wait_on_busy_lock(lockres);
+out:
+ mlog_exit(0);
+ return 0;
+}
+
+/* Mark the lockres as being dropped. It will no longer be
+ * queued if blocking, but we still may have to wait on it
+ * being dequeued from the vote thread before we can consider
+ * it safe to drop.
+ *
+ * You can *not* attempt to call cluster_lock on this lockres anymore. */
+void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres)
+{
+ int status;
+ struct ocfs2_mask_waiter mw;
+ unsigned long flags;
+
+ ocfs2_init_mask_waiter(&mw);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ lockres->l_flags |= OCFS2_LOCK_FREEING;
+ while (lockres->l_flags & OCFS2_LOCK_QUEUED) {
+ lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_QUEUED, 0);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ mlog(0, "Waiting on lockres %s\n", lockres->l_name);
+
+ status = ocfs2_wait_for_mask(&mw);
+ if (status)
+ mlog_errno(status);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ }
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+}
+
+static void ocfs2_drop_osb_locks(struct ocfs2_super *osb)
+{
+ int status;
+
+ mlog_entry_void();
+
+ ocfs2_mark_lockres_freeing(&osb->osb_super_lockres);
+
+ status = ocfs2_drop_lock(osb, &osb->osb_super_lockres, NULL);
+ if (status < 0)
+ mlog_errno(status);
+
+ ocfs2_mark_lockres_freeing(&osb->osb_rename_lockres);
+
+ status = ocfs2_drop_lock(osb, &osb->osb_rename_lockres, NULL);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+}
+
+static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data)
+{
+ struct inode *inode = data;
+
+ /* the metadata lock requires a bit more work as we have an
+ * LVB to worry about. */
+ if (lockres->l_flags & OCFS2_LOCK_ATTACHED &&
+ lockres->l_level == LKM_EXMODE &&
+ !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH))
+ __ocfs2_stuff_meta_lvb(inode);
+}
+
+int ocfs2_drop_inode_locks(struct inode *inode)
+{
+ int status, err;
+ struct drop_lock_cb meta_dcb = { ocfs2_meta_pre_drop, inode, };
+
+ mlog_entry_void();
+
+ /* No need to call ocfs2_mark_lockres_freeing here -
+ * ocfs2_clear_inode has done it for us. */
+
+ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+ &OCFS2_I(inode)->ip_data_lockres,
+ NULL);
+ if (err < 0)
+ mlog_errno(err);
+
+ status = err;
+
+ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+ &OCFS2_I(inode)->ip_meta_lockres,
+ &meta_dcb);
+ if (err < 0)
+ mlog_errno(err);
+ if (err < 0 && !status)
+ status = err;
+
+ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+ &OCFS2_I(inode)->ip_rw_lockres,
+ NULL);
+ if (err < 0)
+ mlog_errno(err);
+ if (err < 0 && !status)
+ status = err;
+
+ mlog_exit(status);
+ return status;
+}
+
+static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres,
+ int new_level)
+{
+ assert_spin_locked(&lockres->l_lock);
+
+ BUG_ON(lockres->l_blocking <= LKM_NLMODE);
+
+ if (lockres->l_level <= new_level) {
+ mlog(ML_ERROR, "lockres->l_level (%u) <= new_level (%u)\n",
+ lockres->l_level, new_level);
+ BUG();
+ }
+
+ mlog(0, "lock %s, new_level = %d, l_blocking = %d\n",
+ lockres->l_name, new_level, lockres->l_blocking);
+
+ lockres->l_action = OCFS2_AST_DOWNCONVERT;
+ lockres->l_requested = new_level;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
+}
+
+static int ocfs2_downconvert_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int new_level,
+ int lvb)
+{
+ int ret, dlm_flags = LKM_CONVERT;
+ enum dlm_status status;
+
+ mlog_entry_void();
+
+ if (lvb)
+ dlm_flags |= LKM_VALBLK;
+
+ status = dlmlock(osb->dlm,
+ new_level,
+ &lockres->l_lksb,
+ dlm_flags,
+ lockres->l_name,
+ lockres->l_ops->ast,
+ lockres,
+ lockres->l_ops->bast);
+ if (status != DLM_NORMAL) {
+ ocfs2_log_dlm_error("dlmlock", status, lockres);
+ ret = -EINVAL;
+ ocfs2_recover_from_dlm_error(lockres, 1);
+ goto bail;
+ }
+
+ ret = 0;
+bail:
+ mlog_exit(ret);
+ return ret;
+}
+
+/* returns 1 when the caller should unlock and call dlmunlock */
+static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+{
+ assert_spin_locked(&lockres->l_lock);
+
+ mlog_entry_void();
+ mlog(0, "lock %s\n", lockres->l_name);
+
+ if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+ /* If we're already trying to cancel a lock conversion
+ * then just drop the spinlock and allow the caller to
+ * requeue this lock. */
+
+ mlog(0, "Lockres %s, skip convert\n", lockres->l_name);
+ return 0;
+ }
+
+ /* were we in a convert when we got the bast fire? */
+ BUG_ON(lockres->l_action != OCFS2_AST_CONVERT &&
+ lockres->l_action != OCFS2_AST_DOWNCONVERT);
+ /* set things up for the unlockast to know to just
+ * clear out the ast_action and unset busy, etc. */
+ lockres->l_unlock_action = OCFS2_UNLOCK_CANCEL_CONVERT;
+
+ mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_BUSY),
+ "lock %s, invalid flags: 0x%lx\n",
+ lockres->l_name, lockres->l_flags);
+
+ return 1;
+}
+
+static int ocfs2_cancel_convert(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+{
+ int ret;
+ enum dlm_status status;
+
+ mlog_entry_void();
+ mlog(0, "lock %s\n", lockres->l_name);
+
+ ret = 0;
+ status = dlmunlock(osb->dlm,
+ &lockres->l_lksb,
+ LKM_CANCEL,
+ lockres->l_ops->unlock_ast,
+ lockres);
+ if (status != DLM_NORMAL) {
+ ocfs2_log_dlm_error("dlmunlock", status, lockres);
+ ret = -EINVAL;
+ ocfs2_recover_from_dlm_error(lockres, 0);
+ }
+
+ mlog(0, "lock %s return from dlmunlock\n", lockres->l_name);
+
+ mlog_exit(ret);
+ return ret;
+}
+
+static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
+ struct ocfs2_lock_res *lockres,
+ int new_level)
+{
+ int ret;
+
+ mlog_entry_void();
+
+ BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE);
+
+ if (lockres->l_flags & OCFS2_LOCK_REFRESHING) {
+ ret = 0;
+ mlog(0, "lockres %s currently being refreshed -- backing "
+ "off!\n", lockres->l_name);
+ } else if (new_level == LKM_PRMODE)
+ ret = !lockres->l_ex_holders &&
+ ocfs2_inode_fully_checkpointed(inode);
+ else /* Must be NLMODE we're converting to. */
+ ret = !lockres->l_ro_holders && !lockres->l_ex_holders &&
+ ocfs2_inode_fully_checkpointed(inode);
+
+ mlog_exit(ret);
+ return ret;
+}
+
+static int ocfs2_do_unblock_meta(struct inode *inode,
+ int *requeue)
+{
+ int new_level;
+ int set_lvb = 0;
+ int ret = 0;
+ struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;
+ unsigned long flags;
+
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ mlog_entry_void();
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+
+ mlog(0, "l_level=%d, l_blocking=%d\n", lockres->l_level,
+ lockres->l_blocking);
+
+ BUG_ON(lockres->l_level != LKM_EXMODE &&
+ lockres->l_level != LKM_PRMODE);
+
+ if (lockres->l_flags & OCFS2_LOCK_BUSY) {
+ *requeue = 1;
+ ret = ocfs2_prepare_cancel_convert(osb, lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ if (ret) {
+ ret = ocfs2_cancel_convert(osb, lockres);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+ goto leave;
+ }
+
+ new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking);
+
+ mlog(0, "l_level=%d, l_blocking=%d, new_level=%d\n",
+ lockres->l_level, lockres->l_blocking, new_level);
+
+ if (ocfs2_can_downconvert_meta_lock(inode, lockres, new_level)) {
+ if (lockres->l_level == LKM_EXMODE)
+ set_lvb = 1;
+
+ /* If the lock hasn't been refreshed yet (rare), then
+ * our memory inode values are old and we skip
+ * stuffing the lvb. There's no need to actually clear
+ * out the lvb here as it's value is still valid. */
+ if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) {
+ if (set_lvb)
+ __ocfs2_stuff_meta_lvb(inode);
+ } else
+ mlog(0, "lockres %s: downconverting stale lock!\n",
+ lockres->l_name);
+
+ mlog(0, "calling ocfs2_downconvert_lock with l_level=%d, "
+ "l_blocking=%d, new_level=%d\n",
+ lockres->l_level, lockres->l_blocking, new_level);
+
+ ocfs2_prepare_downconvert(lockres, new_level);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb);
+ goto leave;
+ }
+ if (!ocfs2_inode_fully_checkpointed(inode))
+ ocfs2_start_checkpoint(osb);
+
+ *requeue = 1;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ ret = 0;
+leave:
+ mlog_exit(ret);
+ return ret;
+}
+
+static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres,
+ int *requeue,
+ ocfs2_convert_worker_t *worker)
+{
+ unsigned long flags;
+ int blocking;
+ int new_level;
+ int ret = 0;
+
+ mlog_entry_void();
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+
+ BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));
+
+recheck:
+ if (lockres->l_flags & OCFS2_LOCK_BUSY) {
+ *requeue = 1;
+ ret = ocfs2_prepare_cancel_convert(osb, lockres);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ if (ret) {
+ ret = ocfs2_cancel_convert(osb, lockres);
+ if (ret < 0)
+ mlog_errno(ret);
+ }
+ goto leave;
+ }
+
+ /* if we're blocking an exclusive and we have *any* holders,
+ * then requeue. */
+ if ((lockres->l_blocking == LKM_EXMODE)
+ && (lockres->l_ex_holders || lockres->l_ro_holders)) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ *requeue = 1;
+ ret = 0;
+ goto leave;
+ }
+
+ /* If it's a PR we're blocking, then only
+ * requeue if we've got any EX holders */
+ if (lockres->l_blocking == LKM_PRMODE &&
+ lockres->l_ex_holders) {
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ *requeue = 1;
+ ret = 0;
+ goto leave;
+ }
+
+ /* If we get here, then we know that there are no more
+ * incompatible holders (and anyone asking for an incompatible
+ * lock is blocked). We can now downconvert the lock */
+ if (!worker)
+ goto downconvert;
+
+ /* Some lockres types want to do a bit of work before
+ * downconverting a lock. Allow that here. The worker function
+ * may sleep, so we save off a copy of what we're blocking as
+ * it may change while we're not holding the spin lock. */
+ blocking = lockres->l_blocking;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ worker(lockres, blocking);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ if (blocking != lockres->l_blocking) {
+ /* If this changed underneath us, then we can't drop
+ * it just yet. */
+ goto recheck;
+ }
+
+downconvert:
+ *requeue = 0;
+ new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking);
+
+ ocfs2_prepare_downconvert(lockres, new_level);
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+ ret = ocfs2_downconvert_lock(osb, lockres, new_level, 0);
+leave:
+ mlog_exit(ret);
+ return ret;
+}
+
+static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres,
+ int blocking)
+{
+ struct inode *inode;
+ struct address_space *mapping;
+
+ mlog_entry_void();
+
+ inode = ocfs2_lock_res_inode(lockres);
+ mapping = inode->i_mapping;
+
+ if (filemap_fdatawrite(mapping)) {
+ mlog(ML_ERROR, "Could not sync inode %"MLFu64" for downconvert!",
+ OCFS2_I(inode)->ip_blkno);
+ }
+ sync_mapping_buffers(mapping);
+ if (blocking == LKM_EXMODE) {
+ truncate_inode_pages(mapping, 0);
+ unmap_mapping_range(mapping, 0, 0, 0);
+ } else {
+ /* We only need to wait on the I/O if we're not also
+ * truncating pages because truncate_inode_pages waits
+ * for us above. We don't truncate pages if we're
+ * blocking anything < EXMODE because we want to keep
+ * them around in that case. */
+ filemap_fdatawait(mapping);
+ }
+
+ mlog_exit_void();
+}
+
+int ocfs2_unblock_data(struct ocfs2_lock_res *lockres,
+ int *requeue)
+{
+ int status;
+ struct inode *inode;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ inode = ocfs2_lock_res_inode(lockres);
+ osb = OCFS2_SB(inode->i_sb);
+
+ mlog(0, "unblock inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+
+ status = ocfs2_generic_unblock_lock(osb,
+ lockres,
+ requeue,
+ ocfs2_data_convert_worker);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog(0, "inode %"MLFu64", requeue = %d\n",
+ OCFS2_I(inode)->ip_blkno, *requeue);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres,
+ int *requeue)
+{
+ int status;
+ struct inode *inode;
+
+ mlog_entry_void();
+
+ mlog(0, "Unblock lockres %s\n", lockres->l_name);
+
+ inode = ocfs2_lock_res_inode(lockres);
+
+ status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb),
+ lockres,
+ requeue,
+ NULL);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+ return status;
+}
+
+
+int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres,
+ int *requeue)
+{
+ int status;
+ struct inode *inode;
+
+ mlog_entry_void();
+
+ inode = ocfs2_lock_res_inode(lockres);
+
+ mlog(0, "unblock inode %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+
+ status = ocfs2_do_unblock_meta(inode, requeue);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog(0, "inode %"MLFu64", requeue = %d\n",
+ OCFS2_I(inode)->ip_blkno, *requeue);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* Generic unblock function for any lockres whose private data is an
+ * ocfs2_super pointer. */
+static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres,
+ int *requeue)
+{
+ int status;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ mlog(0, "Unblock lockres %s\n", lockres->l_name);
+
+ osb = ocfs2_lock_res_super(lockres);
+
+ status = ocfs2_generic_unblock_lock(osb,
+ lockres,
+ requeue,
+ NULL);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+{
+ int status;
+ int requeue = 0;
+ unsigned long flags;
+
+ /* Our reference to the lockres in this function can be
+ * considered valid until we remove the OCFS2_LOCK_QUEUED
+ * flag. */
+
+ mlog_entry_void();
+
+ BUG_ON(!lockres);
+ BUG_ON(!lockres->l_ops);
+ BUG_ON(!lockres->l_ops->unblock);
+
+ mlog(0, "lockres %s blocked.\n", lockres->l_name);
+
+ /* Detect whether a lock has been marked as going away while
+ * the vote thread was processing other things. A lock can
+ * still be marked with OCFS2_LOCK_FREEING after this check,
+ * but short circuiting here will still save us some
+ * performance. */
+ spin_lock_irqsave(&lockres->l_lock, flags);
+ if (lockres->l_flags & OCFS2_LOCK_FREEING)
+ goto unqueue;
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ status = lockres->l_ops->unblock(lockres, &requeue);
+ if (status < 0)
+ mlog_errno(status);
+
+ spin_lock_irqsave(&lockres->l_lock, flags);
+unqueue:
+ if (lockres->l_flags & OCFS2_LOCK_FREEING || !requeue) {
+ lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED);
+ } else
+ ocfs2_schedule_blocked_lock(osb, lockres);
+
+ mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name,
+ requeue ? "yes" : "no");
+ spin_unlock_irqrestore(&lockres->l_lock, flags);
+
+ mlog_exit_void();
+}
+
+static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres)
+{
+ mlog_entry_void();
+
+ assert_spin_locked(&lockres->l_lock);
+
+ if (lockres->l_flags & OCFS2_LOCK_FREEING) {
+ /* Do not schedule a lock for downconvert when it's on
+ * the way to destruction - any nodes wanting access
+ * to the resource will get it soon. */
+ mlog(0, "Lockres %s won't be scheduled: flags 0x%lx\n",
+ lockres->l_name, lockres->l_flags);
+ return;
+ }
+
+ lockres_or_flags(lockres, OCFS2_LOCK_QUEUED);
+
+ spin_lock(&osb->vote_task_lock);
+ if (list_empty(&lockres->l_blocked_list)) {
+ list_add_tail(&lockres->l_blocked_list,
+ &osb->blocked_lock_list);
+ osb->blocked_lock_count++;
+ }
+ spin_unlock(&osb->vote_task_lock);
+
+ mlog_exit_void();
+}
+
+/* This aids in debugging situations where a bad LVB might be involved. */
+void ocfs2_dump_meta_lvb_info(u64 level,
+ const char *function,
+ unsigned int line,
+ struct ocfs2_lock_res *lockres)
+{
+ struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb;
+
+ mlog(level, "LVB information for %s (called from %s:%u):\n",
+ lockres->l_name, function, line);
+ mlog(level, "version: %u, clusters: %u\n",
+ be32_to_cpu(lvb->lvb_version), be32_to_cpu(lvb->lvb_iclusters));
+ mlog(level, "size: %"MLFu64", uid %u, gid %u, mode 0x%x\n",
+ be64_to_cpu(lvb->lvb_isize), be32_to_cpu(lvb->lvb_iuid),
+ be32_to_cpu(lvb->lvb_igid), be16_to_cpu(lvb->lvb_imode));
+ mlog(level, "nlink %u, atime_packed 0x%"MLFx64", "
+ "ctime_packed 0x%"MLFx64", mtime_packed 0x%"MLFx64"\n",
+ be16_to_cpu(lvb->lvb_inlink), be64_to_cpu(lvb->lvb_iatime_packed),
+ be64_to_cpu(lvb->lvb_ictime_packed),
+ be64_to_cpu(lvb->lvb_imtime_packed));
+}
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
new file mode 100644
index 000000000000..8f2d1db2d9ea
--- /dev/null
+++ b/fs/ocfs2/dlmglue.h
@@ -0,0 +1,111 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dlmglue.h
+ *
+ * description here
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+
+#ifndef DLMGLUE_H
+#define DLMGLUE_H
+
+#define OCFS2_LVB_VERSION 2
+
+struct ocfs2_meta_lvb {
+ __be32 lvb_version;
+ __be32 lvb_iclusters;
+ __be32 lvb_iuid;
+ __be32 lvb_igid;
+ __be64 lvb_iatime_packed;
+ __be64 lvb_ictime_packed;
+ __be64 lvb_imtime_packed;
+ __be64 lvb_isize;
+ __be16 lvb_imode;
+ __be16 lvb_inlink;
+ __be32 lvb_reserved[3];
+};
+
+/* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */
+/* don't wait on recovery. */
+#define OCFS2_META_LOCK_RECOVERY (0x01)
+/* Instruct the dlm not to queue ourselves on the other node. */
+#define OCFS2_META_LOCK_NOQUEUE (0x02)
+/* don't block waiting for the vote thread, instead return -EAGAIN */
+#define OCFS2_LOCK_NONBLOCK (0x04)
+
+int ocfs2_dlm_init(struct ocfs2_super *osb);
+void ocfs2_dlm_shutdown(struct ocfs2_super *osb);
+void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
+void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
+ enum ocfs2_lock_type type,
+ struct inode *inode);
+void ocfs2_lock_res_free(struct ocfs2_lock_res *res);
+int ocfs2_create_new_inode_locks(struct inode *inode);
+int ocfs2_drop_inode_locks(struct inode *inode);
+int ocfs2_data_lock_full(struct inode *inode,
+ int write,
+ int arg_flags);
+#define ocfs2_data_lock(inode, write) ocfs2_data_lock_full(inode, write, 0)
+int ocfs2_data_lock_with_page(struct inode *inode,
+ int write,
+ struct page *page);
+void ocfs2_data_unlock(struct inode *inode,
+ int write);
+int ocfs2_rw_lock(struct inode *inode, int write);
+void ocfs2_rw_unlock(struct inode *inode, int write);
+int ocfs2_meta_lock_full(struct inode *inode,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **ret_bh,
+ int ex,
+ int arg_flags);
+int ocfs2_meta_lock_with_page(struct inode *inode,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **ret_bh,
+ int ex,
+ struct page *page);
+/* 99% of the time we don't want to supply any additional flags --
+ * those are for very specific cases only. */
+#define ocfs2_meta_lock(i, h, b, e) ocfs2_meta_lock_full(i, h, b, e, 0)
+void ocfs2_meta_unlock(struct inode *inode,
+ int ex);
+int ocfs2_super_lock(struct ocfs2_super *osb,
+ int ex);
+void ocfs2_super_unlock(struct ocfs2_super *osb,
+ int ex);
+int ocfs2_rename_lock(struct ocfs2_super *osb);
+void ocfs2_rename_unlock(struct ocfs2_super *osb);
+void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
+
+/* for the vote thread */
+void ocfs2_process_blocked_lock(struct ocfs2_super *osb,
+ struct ocfs2_lock_res *lockres);
+
+struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void);
+void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug);
+
+/* aids in debugging and tracking lvbs */
+void ocfs2_dump_meta_lvb_info(u64 level,
+ const char *function,
+ unsigned int line,
+ struct ocfs2_lock_res *lockres);
+#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
+
+#endif /* DLMGLUE_H */
diff --git a/fs/ocfs2/endian.h b/fs/ocfs2/endian.h
new file mode 100644
index 000000000000..f226b2207628
--- /dev/null
+++ b/fs/ocfs2/endian.h
@@ -0,0 +1,45 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_ENDIAN_H
+#define OCFS2_ENDIAN_H
+
+static inline void le16_add_cpu(__le16 *var, u16 val)
+{
+ *var = cpu_to_le16(le16_to_cpu(*var) + val);
+}
+
+static inline void le32_add_cpu(__le32 *var, u32 val)
+{
+ *var = cpu_to_le32(le32_to_cpu(*var) + val);
+}
+
+static inline void le32_and_cpu(__le32 *var, u32 val)
+{
+ *var = cpu_to_le32(le32_to_cpu(*var) & val);
+}
+
+static inline void be32_add_cpu(__be32 *var, u32 val)
+{
+ *var = cpu_to_be32(be32_to_cpu(*var) + val);
+}
+
+#endif /* OCFS2_ENDIAN_H */
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
new file mode 100644
index 000000000000..5810160d92a8
--- /dev/null
+++ b/fs/ocfs2/export.c
@@ -0,0 +1,248 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * export.c
+ *
+ * Functions to facilitate NFS exporting
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+#define MLOG_MASK_PREFIX ML_EXPORT
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "dir.h"
+#include "dlmglue.h"
+#include "export.h"
+#include "inode.h"
+
+#include "buffer_head_io.h"
+
+struct ocfs2_inode_handle
+{
+ u64 ih_blkno;
+ u32 ih_generation;
+};
+
+static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp)
+{
+ struct ocfs2_inode_handle *handle = vobjp;
+ struct inode *inode;
+ struct dentry *result;
+
+ mlog_entry("(0x%p, 0x%p)\n", sb, handle);
+
+ if (handle->ih_blkno == 0) {
+ mlog_errno(-ESTALE);
+ return ERR_PTR(-ESTALE);
+ }
+
+ inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno);
+
+ if (IS_ERR(inode)) {
+ mlog_errno(PTR_ERR(inode));
+ return (void *)inode;
+ }
+
+ if (handle->ih_generation != inode->i_generation) {
+ iput(inode);
+ mlog_errno(-ESTALE);
+ return ERR_PTR(-ESTALE);
+ }
+
+ result = d_alloc_anon(inode);
+
+ if (!result) {
+ iput(inode);
+ mlog_errno(-ENOMEM);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ mlog_exit_ptr(result);
+ return result;
+}
+
+static struct dentry *ocfs2_get_parent(struct dentry *child)
+{
+ int status;
+ u64 blkno;
+ struct dentry *parent;
+ struct inode *inode;
+ struct inode *dir = child->d_inode;
+ struct buffer_head *dirent_bh = NULL;
+ struct ocfs2_dir_entry *dirent;
+
+ mlog_entry("(0x%p, '%.*s')\n", child,
+ child->d_name.len, child->d_name.name);
+
+ mlog(0, "find parent of directory %"MLFu64"\n",
+ OCFS2_I(dir)->ip_blkno);
+
+ status = ocfs2_meta_lock(dir, NULL, NULL, 0);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ parent = ERR_PTR(status);
+ goto bail;
+ }
+
+ status = ocfs2_find_files_on_disk("..", 2, &blkno, dir, &dirent_bh,
+ &dirent);
+ if (status < 0) {
+ parent = ERR_PTR(-ENOENT);
+ goto bail_unlock;
+ }
+
+ inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);
+ if (IS_ERR(inode)) {
+ mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);
+ parent = ERR_PTR(-EACCES);
+ goto bail_unlock;
+ }
+
+ parent = d_alloc_anon(inode);
+ if (!parent) {
+ iput(inode);
+ parent = ERR_PTR(-ENOMEM);
+ }
+
+bail_unlock:
+ ocfs2_meta_unlock(dir, 0);
+
+ if (dirent_bh)
+ brelse(dirent_bh);
+
+bail:
+ mlog_exit_ptr(parent);
+
+ return parent;
+}
+
+static int ocfs2_encode_fh(struct dentry *dentry, __be32 *fh, int *max_len,
+ int connectable)
+{
+ struct inode *inode = dentry->d_inode;
+ int len = *max_len;
+ int type = 1;
+ u64 blkno;
+ u32 generation;
+
+ mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry,
+ dentry->d_name.len, dentry->d_name.name,
+ fh, len, connectable);
+
+ if (len < 3 || (connectable && len < 6)) {
+ mlog(ML_ERROR, "fh buffer is too small for encoding\n");
+ type = 255;
+ goto bail;
+ }
+
+ blkno = OCFS2_I(inode)->ip_blkno;
+ generation = inode->i_generation;
+
+ mlog(0, "Encoding fh: blkno: %"MLFu64", generation: %u\n",
+ blkno, generation);
+
+ len = 3;
+ fh[0] = cpu_to_le32((u32)(blkno >> 32));
+ fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff));
+ fh[2] = cpu_to_le32(generation);
+
+ if (connectable && !S_ISDIR(inode->i_mode)) {
+ struct inode *parent;
+
+ spin_lock(&dentry->d_lock);
+
+ parent = dentry->d_parent->d_inode;
+ blkno = OCFS2_I(parent)->ip_blkno;
+ generation = parent->i_generation;
+
+ fh[3] = cpu_to_le32((u32)(blkno >> 32));
+ fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff));
+ fh[5] = cpu_to_le32(generation);
+
+ spin_unlock(&dentry->d_lock);
+
+ len = 6;
+ type = 2;
+
+ mlog(0, "Encoding parent: blkno: %"MLFu64", generation: %u\n",
+ blkno, generation);
+ }
+
+ *max_len = len;
+
+bail:
+ mlog_exit(type);
+ return type;
+}
+
+static struct dentry *ocfs2_decode_fh(struct super_block *sb, __be32 *fh,
+ int fh_len, int fileid_type,
+ int (*acceptable)(void *context,
+ struct dentry *de),
+ void *context)
+{
+ struct ocfs2_inode_handle handle, parent;
+ struct dentry *ret = NULL;
+
+ mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n",
+ sb, fh, fh_len, fileid_type, acceptable, context);
+
+ if (fh_len < 3 || fileid_type > 2)
+ goto bail;
+
+ if (fileid_type == 2) {
+ if (fh_len < 6)
+ goto bail;
+
+ parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32;
+ parent.ih_blkno |= (u64)le32_to_cpu(fh[4]);
+ parent.ih_generation = le32_to_cpu(fh[5]);
+
+ mlog(0, "Decoding parent: blkno: %"MLFu64", generation: %u\n",
+ parent.ih_blkno, parent.ih_generation);
+ }
+
+ handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32;
+ handle.ih_blkno |= (u64)le32_to_cpu(fh[1]);
+ handle.ih_generation = le32_to_cpu(fh[2]);
+
+ mlog(0, "Encoding fh: blkno: %"MLFu64", generation: %u\n",
+ handle.ih_blkno, handle.ih_generation);
+
+ ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent,
+ acceptable, context);
+
+bail:
+ mlog_exit_ptr(ret);
+ return ret;
+}
+
+struct export_operations ocfs2_export_ops = {
+ .decode_fh = ocfs2_decode_fh,
+ .encode_fh = ocfs2_encode_fh,
+
+ .get_parent = ocfs2_get_parent,
+ .get_dentry = ocfs2_get_dentry,
+};
diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h
new file mode 100644
index 000000000000..5b77ee7866ef
--- /dev/null
+++ b/fs/ocfs2/export.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * export.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_EXPORT_H
+#define OCFS2_EXPORT_H
+
+extern struct export_operations ocfs2_export_ops;
+
+#endif /* OCFS2_EXPORT_H */
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c
new file mode 100644
index 000000000000..f2fb40cd296a
--- /dev/null
+++ b/fs/ocfs2/extent_map.c
@@ -0,0 +1,994 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * extent_map.c
+ *
+ * In-memory extent map for OCFS2. Man, this code was prettier in
+ * the library.
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/rbtree.h>
+
+#define MLOG_MASK_PREFIX ML_EXTENT_MAP
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "extent_map.h"
+#include "inode.h"
+#include "super.h"
+
+#include "buffer_head_io.h"
+
+
+/*
+ * SUCK SUCK SUCK
+ * Our headers are so bad that struct ocfs2_extent_map is in ocfs.h
+ */
+
+struct ocfs2_extent_map_entry {
+ struct rb_node e_node;
+ int e_tree_depth;
+ struct ocfs2_extent_rec e_rec;
+};
+
+struct ocfs2_em_insert_context {
+ int need_left;
+ int need_right;
+ struct ocfs2_extent_map_entry *new_ent;
+ struct ocfs2_extent_map_entry *old_ent;
+ struct ocfs2_extent_map_entry *left_ent;
+ struct ocfs2_extent_map_entry *right_ent;
+};
+
+static kmem_cache_t *ocfs2_em_ent_cachep = NULL;
+
+
+static struct ocfs2_extent_map_entry *
+ocfs2_extent_map_lookup(struct ocfs2_extent_map *em,
+ u32 cpos, u32 clusters,
+ struct rb_node ***ret_p,
+ struct rb_node **ret_parent);
+static int ocfs2_extent_map_insert(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth);
+static int ocfs2_extent_map_insert_entry(struct ocfs2_extent_map *em,
+ struct ocfs2_extent_map_entry *ent);
+static int ocfs2_extent_map_find_leaf(struct inode *inode,
+ u32 cpos, u32 clusters,
+ struct ocfs2_extent_list *el);
+static int ocfs2_extent_map_lookup_read(struct inode *inode,
+ u32 cpos, u32 clusters,
+ struct ocfs2_extent_map_entry **ret_ent);
+static int ocfs2_extent_map_try_insert(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth,
+ struct ocfs2_em_insert_context *ctxt);
+
+/* returns 1 only if the rec contains all the given clusters -- that is that
+ * rec's cpos is <= the cluster cpos and that the rec endpoint (cpos +
+ * clusters) is >= the argument's endpoint */
+static int ocfs2_extent_rec_contains_clusters(struct ocfs2_extent_rec *rec,
+ u32 cpos, u32 clusters)
+{
+ if (le32_to_cpu(rec->e_cpos) > cpos)
+ return 0;
+ if (cpos + clusters > le32_to_cpu(rec->e_cpos) +
+ le32_to_cpu(rec->e_clusters))
+ return 0;
+ return 1;
+}
+
+
+/*
+ * Find an entry in the tree that intersects the region passed in.
+ * Note that this will find straddled intervals, it is up to the
+ * callers to enforce any boundary conditions.
+ *
+ * Callers must hold ip_lock. This lookup is not guaranteed to return
+ * a tree_depth 0 match, and as such can race inserts if the lock
+ * were not held.
+ *
+ * The rb_node garbage lets insertion share the search. Trivial
+ * callers pass NULL.
+ */
+static struct ocfs2_extent_map_entry *
+ocfs2_extent_map_lookup(struct ocfs2_extent_map *em,
+ u32 cpos, u32 clusters,
+ struct rb_node ***ret_p,
+ struct rb_node **ret_parent)
+{
+ struct rb_node **p = &em->em_extents.rb_node;
+ struct rb_node *parent = NULL;
+ struct ocfs2_extent_map_entry *ent = NULL;
+
+ while (*p)
+ {
+ parent = *p;
+ ent = rb_entry(parent, struct ocfs2_extent_map_entry,
+ e_node);
+ if ((cpos + clusters) <= le32_to_cpu(ent->e_rec.e_cpos)) {
+ p = &(*p)->rb_left;
+ ent = NULL;
+ } else if (cpos >= (le32_to_cpu(ent->e_rec.e_cpos) +
+ le32_to_cpu(ent->e_rec.e_clusters))) {
+ p = &(*p)->rb_right;
+ ent = NULL;
+ } else
+ break;
+ }
+
+ if (ret_p != NULL)
+ *ret_p = p;
+ if (ret_parent != NULL)
+ *ret_parent = parent;
+ return ent;
+}
+
+/*
+ * Find the leaf containing the interval we want. While we're on our
+ * way down the tree, fill in every record we see at any depth, because
+ * we might want it later.
+ *
+ * Note that this code is run without ip_lock. That's because it
+ * sleeps while reading. If someone is also filling the extent list at
+ * the same time we are, we might have to restart.
+ */
+static int ocfs2_extent_map_find_leaf(struct inode *inode,
+ u32 cpos, u32 clusters,
+ struct ocfs2_extent_list *el)
+{
+ int i, ret;
+ struct buffer_head *eb_bh = NULL;
+ u64 blkno;
+ u32 rec_end;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_extent_rec *rec;
+
+ /*
+ * The bh data containing the el cannot change here, because
+ * we hold alloc_sem. So we can do this without other
+ * locks.
+ */
+ while (el->l_tree_depth)
+ {
+ blkno = 0;
+ for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+ rec = &el->l_recs[i];
+ rec_end = (le32_to_cpu(rec->e_cpos) +
+ le32_to_cpu(rec->e_clusters));
+
+ ret = -EBADR;
+ if (rec_end > OCFS2_I(inode)->ip_clusters) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+
+ if (rec_end <= cpos) {
+ ret = ocfs2_extent_map_insert(inode, rec,
+ le16_to_cpu(el->l_tree_depth));
+ if (ret && (ret != -EEXIST)) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+ continue;
+ }
+ if ((cpos + clusters) <= le32_to_cpu(rec->e_cpos)) {
+ ret = ocfs2_extent_map_insert(inode, rec,
+ le16_to_cpu(el->l_tree_depth));
+ if (ret && (ret != -EEXIST)) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+ continue;
+ }
+
+ /*
+ * We've found a record that matches our
+ * interval. We don't insert it because we're
+ * about to traverse it.
+ */
+
+ /* Check to see if we're stradling */
+ ret = -ESRCH;
+ if (!ocfs2_extent_rec_contains_clusters(rec,
+ cpos,
+ clusters)) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+
+ /*
+ * If we've already found a record, the el has
+ * two records covering the same interval.
+ * EEEK!
+ */
+ ret = -EBADR;
+ if (blkno) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+
+ blkno = le64_to_cpu(rec->e_blkno);
+ }
+
+ /*
+ * We don't support holes, and we're still up
+ * in the branches, so we'd better have found someone
+ */
+ ret = -EBADR;
+ if (!blkno) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+
+ if (eb_bh) {
+ brelse(eb_bh);
+ eb_bh = NULL;
+ }
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ blkno, &eb_bh, OCFS2_BH_CACHED,
+ inode);
+ if (ret) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+ eb = (struct ocfs2_extent_block *)eb_bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ ret = -EIO;
+ goto out_free;
+ }
+ el = &eb->h_list;
+ }
+
+ if (el->l_tree_depth)
+ BUG();
+
+ for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
+ rec = &el->l_recs[i];
+ ret = ocfs2_extent_map_insert(inode, rec,
+ le16_to_cpu(el->l_tree_depth));
+ if (ret) {
+ mlog_errno(ret);
+ goto out_free;
+ }
+ }
+
+ ret = 0;
+
+out_free:
+ if (eb_bh)
+ brelse(eb_bh);
+
+ return ret;
+}
+
+/*
+ * This lookup actually will read from disk. It has one invariant:
+ * It will never re-traverse blocks. This means that all inserts should
+ * be new regions or more granular regions (both allowed by insert).
+ */
+static int ocfs2_extent_map_lookup_read(struct inode *inode,
+ u32 cpos,
+ u32 clusters,
+ struct ocfs2_extent_map_entry **ret_ent)
+{
+ int ret;
+ u64 blkno;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_extent_block *eb;
+ struct ocfs2_dinode *di;
+ struct ocfs2_extent_list *el;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ ent = ocfs2_extent_map_lookup(em, cpos, clusters, NULL, NULL);
+ if (ent) {
+ if (!ent->e_tree_depth) {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ *ret_ent = ent;
+ return 0;
+ }
+ blkno = le64_to_cpu(ent->e_rec.e_blkno);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno, &bh,
+ OCFS2_BH_CACHED, inode);
+ if (ret) {
+ mlog_errno(ret);
+ if (bh)
+ brelse(bh);
+ return ret;
+ }
+ eb = (struct ocfs2_extent_block *)bh->b_data;
+ if (!OCFS2_IS_VALID_EXTENT_BLOCK(eb)) {
+ OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, eb);
+ brelse(bh);
+ return -EIO;
+ }
+ el = &eb->h_list;
+ } else {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ OCFS2_I(inode)->ip_blkno, &bh,
+ OCFS2_BH_CACHED, inode);
+ if (ret) {
+ mlog_errno(ret);
+ if (bh)
+ brelse(bh);
+ return ret;
+ }
+ di = (struct ocfs2_dinode *)bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(di)) {
+ brelse(bh);
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, di);
+ return -EIO;
+ }
+ el = &di->id2.i_list;
+ }
+
+ ret = ocfs2_extent_map_find_leaf(inode, cpos, clusters, el);
+ brelse(bh);
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ ent = ocfs2_extent_map_lookup(em, cpos, clusters, NULL, NULL);
+ if (!ent) {
+ ret = -ESRCH;
+ mlog_errno(ret);
+ return ret;
+ }
+
+ if (ent->e_tree_depth)
+ BUG(); /* FIXME: Make sure this isn't a corruption */
+
+ *ret_ent = ent;
+
+ return 0;
+}
+
+/*
+ * Callers must hold ip_lock. This can insert pieces of the tree,
+ * thus racing lookup if the lock weren't held.
+ */
+static int ocfs2_extent_map_insert_entry(struct ocfs2_extent_map *em,
+ struct ocfs2_extent_map_entry *ent)
+{
+ struct rb_node **p, *parent;
+ struct ocfs2_extent_map_entry *old_ent;
+
+ old_ent = ocfs2_extent_map_lookup(em, le32_to_cpu(ent->e_rec.e_cpos),
+ le32_to_cpu(ent->e_rec.e_clusters),
+ &p, &parent);
+ if (old_ent)
+ return -EEXIST;
+
+ rb_link_node(&ent->e_node, parent, p);
+ rb_insert_color(&ent->e_node, &em->em_extents);
+
+ return 0;
+}
+
+
+/*
+ * Simple rule: on any return code other than -EAGAIN, anything left
+ * in the insert_context will be freed.
+ */
+static int ocfs2_extent_map_try_insert(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth,
+ struct ocfs2_em_insert_context *ctxt)
+{
+ int ret;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *old_ent;
+
+ ctxt->need_left = 0;
+ ctxt->need_right = 0;
+ ctxt->old_ent = NULL;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ ret = ocfs2_extent_map_insert_entry(em, ctxt->new_ent);
+ if (!ret) {
+ ctxt->new_ent = NULL;
+ goto out_unlock;
+ }
+
+ old_ent = ocfs2_extent_map_lookup(em, le32_to_cpu(rec->e_cpos),
+ le32_to_cpu(rec->e_clusters), NULL,
+ NULL);
+
+ if (!old_ent)
+ BUG();
+
+ ret = -EEXIST;
+ if (old_ent->e_tree_depth < tree_depth)
+ goto out_unlock;
+
+ if (old_ent->e_tree_depth == tree_depth) {
+ if (!memcmp(rec, &old_ent->e_rec,
+ sizeof(struct ocfs2_extent_rec)))
+ ret = 0;
+
+ /* FIXME: Should this be ESRCH/EBADR??? */
+ goto out_unlock;
+ }
+
+ /*
+ * We do it in this order specifically so that no actual tree
+ * changes occur until we have all the pieces we need. We
+ * don't want malloc failures to leave an inconsistent tree.
+ * Whenever we drop the lock, another process could be
+ * inserting. Also note that, if another process just beat us
+ * to an insert, we might not need the same pieces we needed
+ * the first go round. In the end, the pieces we need will
+ * be used, and the pieces we don't will be freed.
+ */
+ ctxt->need_left = !!(le32_to_cpu(rec->e_cpos) >
+ le32_to_cpu(old_ent->e_rec.e_cpos));
+ ctxt->need_right = !!((le32_to_cpu(old_ent->e_rec.e_cpos) +
+ le32_to_cpu(old_ent->e_rec.e_clusters)) >
+ (le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)));
+ ret = -EAGAIN;
+ if (ctxt->need_left) {
+ if (!ctxt->left_ent)
+ goto out_unlock;
+ *(ctxt->left_ent) = *old_ent;
+ ctxt->left_ent->e_rec.e_clusters =
+ cpu_to_le32(le32_to_cpu(rec->e_cpos) -
+ le32_to_cpu(ctxt->left_ent->e_rec.e_cpos));
+ }
+ if (ctxt->need_right) {
+ if (!ctxt->right_ent)
+ goto out_unlock;
+ *(ctxt->right_ent) = *old_ent;
+ ctxt->right_ent->e_rec.e_cpos =
+ cpu_to_le32(le32_to_cpu(rec->e_cpos) +
+ le32_to_cpu(rec->e_clusters));
+ ctxt->right_ent->e_rec.e_clusters =
+ cpu_to_le32((le32_to_cpu(old_ent->e_rec.e_cpos) +
+ le32_to_cpu(old_ent->e_rec.e_clusters)) -
+ le32_to_cpu(ctxt->right_ent->e_rec.e_cpos));
+ }
+
+ rb_erase(&old_ent->e_node, &em->em_extents);
+ /* Now that he's erased, set him up for deletion */
+ ctxt->old_ent = old_ent;
+
+ if (ctxt->need_left) {
+ ret = ocfs2_extent_map_insert_entry(em,
+ ctxt->left_ent);
+ if (ret)
+ goto out_unlock;
+ ctxt->left_ent = NULL;
+ }
+
+ if (ctxt->need_right) {
+ ret = ocfs2_extent_map_insert_entry(em,
+ ctxt->right_ent);
+ if (ret)
+ goto out_unlock;
+ ctxt->right_ent = NULL;
+ }
+
+ ret = ocfs2_extent_map_insert_entry(em, ctxt->new_ent);
+
+ if (!ret)
+ ctxt->new_ent = NULL;
+
+out_unlock:
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ return ret;
+}
+
+
+static int ocfs2_extent_map_insert(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ int tree_depth)
+{
+ int ret;
+ struct ocfs2_em_insert_context ctxt = {0, };
+
+ if ((le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)) >
+ OCFS2_I(inode)->ip_map.em_clusters) {
+ ret = -EBADR;
+ mlog_errno(ret);
+ return ret;
+ }
+
+ /* Zero e_clusters means a truncated tail record. It better be EOF */
+ if (!rec->e_clusters) {
+ if ((le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)) !=
+ OCFS2_I(inode)->ip_map.em_clusters) {
+ ret = -EBADR;
+ mlog_errno(ret);
+ return ret;
+ }
+
+ /* Ignore the truncated tail */
+ return 0;
+ }
+
+ ret = -ENOMEM;
+ ctxt.new_ent = kmem_cache_alloc(ocfs2_em_ent_cachep,
+ GFP_KERNEL);
+ if (!ctxt.new_ent) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ ctxt.new_ent->e_rec = *rec;
+ ctxt.new_ent->e_tree_depth = tree_depth;
+
+ do {
+ ret = -ENOMEM;
+ if (ctxt.need_left && !ctxt.left_ent) {
+ ctxt.left_ent =
+ kmem_cache_alloc(ocfs2_em_ent_cachep,
+ GFP_KERNEL);
+ if (!ctxt.left_ent)
+ break;
+ }
+ if (ctxt.need_right && !ctxt.right_ent) {
+ ctxt.right_ent =
+ kmem_cache_alloc(ocfs2_em_ent_cachep,
+ GFP_KERNEL);
+ if (!ctxt.right_ent)
+ break;
+ }
+
+ ret = ocfs2_extent_map_try_insert(inode, rec,
+ tree_depth, &ctxt);
+ } while (ret == -EAGAIN);
+
+ if (ret < 0)
+ mlog_errno(ret);
+
+ if (ctxt.left_ent)
+ kmem_cache_free(ocfs2_em_ent_cachep, ctxt.left_ent);
+ if (ctxt.right_ent)
+ kmem_cache_free(ocfs2_em_ent_cachep, ctxt.right_ent);
+ if (ctxt.old_ent)
+ kmem_cache_free(ocfs2_em_ent_cachep, ctxt.old_ent);
+ if (ctxt.new_ent)
+ kmem_cache_free(ocfs2_em_ent_cachep, ctxt.new_ent);
+
+ return ret;
+}
+
+/*
+ * Append this record to the tail of the extent map. It must be
+ * tree_depth 0. The record might be an extension of an existing
+ * record, and as such that needs to be handled. eg:
+ *
+ * Existing record in the extent map:
+ *
+ * cpos = 10, len = 10
+ * |---------|
+ *
+ * New Record:
+ *
+ * cpos = 10, len = 20
+ * |------------------|
+ *
+ * The passed record is the new on-disk record. The new_clusters value
+ * is how many clusters were added to the file. If the append is a
+ * contiguous append, the new_clusters has been added to
+ * rec->e_clusters. If the append is an entirely new extent, then
+ * rec->e_clusters is == new_clusters.
+ */
+int ocfs2_extent_map_append(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ u32 new_clusters)
+{
+ int ret;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent;
+ struct ocfs2_extent_rec *old;
+
+ BUG_ON(!new_clusters);
+ BUG_ON(le32_to_cpu(rec->e_clusters) < new_clusters);
+
+ if (em->em_clusters < OCFS2_I(inode)->ip_clusters) {
+ /*
+ * Size changed underneath us on disk. Drop any
+ * straddling records and update our idea of
+ * i_clusters
+ */
+ ocfs2_extent_map_drop(inode, em->em_clusters - 1);
+ em->em_clusters = OCFS2_I(inode)->ip_clusters;
+ }
+
+ mlog_bug_on_msg((le32_to_cpu(rec->e_cpos) +
+ le32_to_cpu(rec->e_clusters)) !=
+ (em->em_clusters + new_clusters),
+ "Inode %"MLFu64":\n"
+ "rec->e_cpos = %u + rec->e_clusters = %u = %u\n"
+ "em->em_clusters = %u + new_clusters = %u = %u\n",
+ OCFS2_I(inode)->ip_blkno,
+ le32_to_cpu(rec->e_cpos), le32_to_cpu(rec->e_clusters),
+ le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters),
+ em->em_clusters, new_clusters,
+ em->em_clusters + new_clusters);
+
+ em->em_clusters += new_clusters;
+
+ ret = -ENOENT;
+ if (le32_to_cpu(rec->e_clusters) > new_clusters) {
+ /* This is a contiguous append */
+ ent = ocfs2_extent_map_lookup(em, le32_to_cpu(rec->e_cpos), 1,
+ NULL, NULL);
+ if (ent) {
+ old = &ent->e_rec;
+ BUG_ON((le32_to_cpu(rec->e_cpos) +
+ le32_to_cpu(rec->e_clusters)) !=
+ (le32_to_cpu(old->e_cpos) +
+ le32_to_cpu(old->e_clusters) +
+ new_clusters));
+ if (ent->e_tree_depth == 0) {
+ BUG_ON(le32_to_cpu(old->e_cpos) !=
+ le32_to_cpu(rec->e_cpos));
+ BUG_ON(le64_to_cpu(old->e_blkno) !=
+ le64_to_cpu(rec->e_blkno));
+ ret = 0;
+ }
+ /*
+ * Let non-leafs fall through as -ENOENT to
+ * force insertion of the new leaf.
+ */
+ le32_add_cpu(&old->e_clusters, new_clusters);
+ }
+ }
+
+ if (ret == -ENOENT)
+ ret = ocfs2_extent_map_insert(inode, rec, 0);
+ if (ret < 0)
+ mlog_errno(ret);
+ return ret;
+}
+
+#if 0
+/* Code here is included but defined out as it completes the extent
+ * map api and may be used in the future. */
+
+/*
+ * Look up the record containing this cluster offset. This record is
+ * part of the extent map. Do not free it. Any changes you make to
+ * it will reflect in the extent map. So, if your last extent
+ * is (cpos = 10, clusters = 10) and you truncate the file by 5
+ * clusters, you can do:
+ *
+ * ret = ocfs2_extent_map_get_rec(em, orig_size - 5, &rec);
+ * rec->e_clusters -= 5;
+ *
+ * The lookup does not read from disk. If the map isn't filled in for
+ * an entry, you won't find it.
+ *
+ * Also note that the returned record is valid until alloc_sem is
+ * dropped. After that, truncate and extend can happen. Caveat Emptor.
+ */
+int ocfs2_extent_map_get_rec(struct inode *inode, u32 cpos,
+ struct ocfs2_extent_rec **rec,
+ int *tree_depth)
+{
+ int ret = -ENOENT;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent;
+
+ *rec = NULL;
+
+ if (cpos >= OCFS2_I(inode)->ip_clusters)
+ return -EINVAL;
+
+ if (cpos >= em->em_clusters) {
+ /*
+ * Size changed underneath us on disk. Drop any
+ * straddling records and update our idea of
+ * i_clusters
+ */
+ ocfs2_extent_map_drop(inode, em->em_clusters - 1);
+ em->em_clusters = OCFS2_I(inode)->ip_clusters ;
+ }
+
+ ent = ocfs2_extent_map_lookup(&OCFS2_I(inode)->ip_map, cpos, 1,
+ NULL, NULL);
+
+ if (ent) {
+ *rec = &ent->e_rec;
+ if (tree_depth)
+ *tree_depth = ent->e_tree_depth;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int ocfs2_extent_map_get_clusters(struct inode *inode,
+ u32 v_cpos, int count,
+ u32 *p_cpos, int *ret_count)
+{
+ int ret;
+ u32 coff, ccount;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent = NULL;
+
+ *p_cpos = ccount = 0;
+
+ if ((v_cpos + count) > OCFS2_I(inode)->ip_clusters)
+ return -EINVAL;
+
+ if ((v_cpos + count) > em->em_clusters) {
+ /*
+ * Size changed underneath us on disk. Drop any
+ * straddling records and update our idea of
+ * i_clusters
+ */
+ ocfs2_extent_map_drop(inode, em->em_clusters - 1);
+ em->em_clusters = OCFS2_I(inode)->ip_clusters;
+ }
+
+
+ ret = ocfs2_extent_map_lookup_read(inode, v_cpos, count, &ent);
+ if (ret)
+ return ret;
+
+ if (ent) {
+ /* We should never find ourselves straddling an interval */
+ if (!ocfs2_extent_rec_contains_clusters(&ent->e_rec,
+ v_cpos,
+ count))
+ return -ESRCH;
+
+ coff = v_cpos - le32_to_cpu(ent->e_rec.e_cpos);
+ *p_cpos = ocfs2_blocks_to_clusters(inode->i_sb,
+ le64_to_cpu(ent->e_rec.e_blkno)) +
+ coff;
+
+ if (ret_count)
+ *ret_count = le32_to_cpu(ent->e_rec.e_clusters) - coff;
+
+ return 0;
+ }
+
+
+ return -ENOENT;
+}
+
+#endif /* 0 */
+
+int ocfs2_extent_map_get_blocks(struct inode *inode,
+ u64 v_blkno, int count,
+ u64 *p_blkno, int *ret_count)
+{
+ int ret;
+ u64 boff;
+ u32 cpos, clusters;
+ int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1);
+ struct ocfs2_extent_map_entry *ent = NULL;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_rec *rec;
+
+ *p_blkno = 0;
+
+ cpos = ocfs2_blocks_to_clusters(inode->i_sb, v_blkno);
+ clusters = ocfs2_blocks_to_clusters(inode->i_sb,
+ (u64)count + bpc - 1);
+ if ((cpos + clusters) > OCFS2_I(inode)->ip_clusters) {
+ ret = -EINVAL;
+ mlog_errno(ret);
+ return ret;
+ }
+
+ if ((cpos + clusters) > em->em_clusters) {
+ /*
+ * Size changed underneath us on disk. Drop any
+ * straddling records and update our idea of
+ * i_clusters
+ */
+ ocfs2_extent_map_drop(inode, em->em_clusters - 1);
+ em->em_clusters = OCFS2_I(inode)->ip_clusters;
+ }
+
+ ret = ocfs2_extent_map_lookup_read(inode, cpos, clusters, &ent);
+ if (ret) {
+ mlog_errno(ret);
+ return ret;
+ }
+
+ if (ent)
+ {
+ rec = &ent->e_rec;
+
+ /* We should never find ourselves straddling an interval */
+ if (!ocfs2_extent_rec_contains_clusters(rec, cpos, clusters)) {
+ ret = -ESRCH;
+ mlog_errno(ret);
+ return ret;
+ }
+
+ boff = ocfs2_clusters_to_blocks(inode->i_sb, cpos -
+ le32_to_cpu(rec->e_cpos));
+ boff += (v_blkno & (u64)(bpc - 1));
+ *p_blkno = le64_to_cpu(rec->e_blkno) + boff;
+
+ if (ret_count) {
+ *ret_count = ocfs2_clusters_to_blocks(inode->i_sb,
+ le32_to_cpu(rec->e_clusters)) - boff;
+ }
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+int ocfs2_extent_map_init(struct inode *inode)
+{
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+
+ em->em_extents = RB_ROOT;
+ em->em_clusters = 0;
+
+ return 0;
+}
+
+/* Needs the lock */
+static void __ocfs2_extent_map_drop(struct inode *inode,
+ u32 new_clusters,
+ struct rb_node **free_head,
+ struct ocfs2_extent_map_entry **tail_ent)
+{
+ struct rb_node *node, *next;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent;
+
+ *free_head = NULL;
+
+ ent = NULL;
+ node = rb_last(&em->em_extents);
+ while (node)
+ {
+ next = rb_prev(node);
+
+ ent = rb_entry(node, struct ocfs2_extent_map_entry,
+ e_node);
+ if (le32_to_cpu(ent->e_rec.e_cpos) < new_clusters)
+ break;
+
+ rb_erase(&ent->e_node, &em->em_extents);
+
+ node->rb_right = *free_head;
+ *free_head = node;
+
+ ent = NULL;
+ node = next;
+ }
+
+ /* Do we have an entry straddling new_clusters? */
+ if (tail_ent) {
+ if (ent &&
+ ((le32_to_cpu(ent->e_rec.e_cpos) +
+ le32_to_cpu(ent->e_rec.e_clusters)) > new_clusters))
+ *tail_ent = ent;
+ else
+ *tail_ent = NULL;
+ }
+}
+
+static void __ocfs2_extent_map_drop_cleanup(struct rb_node *free_head)
+{
+ struct rb_node *node;
+ struct ocfs2_extent_map_entry *ent;
+
+ while (free_head) {
+ node = free_head;
+ free_head = node->rb_right;
+
+ ent = rb_entry(node, struct ocfs2_extent_map_entry,
+ e_node);
+ kmem_cache_free(ocfs2_em_ent_cachep, ent);
+ }
+}
+
+/*
+ * Remove all entries past new_clusters, inclusive of an entry that
+ * contains new_clusters. This is effectively a cache forget.
+ *
+ * If you want to also clip the last extent by some number of clusters,
+ * you need to call ocfs2_extent_map_trunc().
+ * This code does not check or modify ip_clusters.
+ */
+int ocfs2_extent_map_drop(struct inode *inode, u32 new_clusters)
+{
+ struct rb_node *free_head = NULL;
+ struct ocfs2_extent_map *em = &OCFS2_I(inode)->ip_map;
+ struct ocfs2_extent_map_entry *ent;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+
+ __ocfs2_extent_map_drop(inode, new_clusters, &free_head, &ent);
+
+ if (ent) {
+ rb_erase(&ent->e_node, &em->em_extents);
+ ent->e_node.rb_right = free_head;
+ free_head = &ent->e_node;
+ }
+
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ if (free_head)
+ __ocfs2_extent_map_drop_cleanup(free_head);
+
+ return 0;
+}
+
+/*
+ * Remove all entries past new_clusters and also clip any extent
+ * straddling new_clusters, if there is one. This does not check
+ * or modify ip_clusters
+ */
+int ocfs2_extent_map_trunc(struct inode *inode, u32 new_clusters)
+{
+ struct rb_node *free_head = NULL;
+ struct ocfs2_extent_map_entry *ent = NULL;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+
+ __ocfs2_extent_map_drop(inode, new_clusters, &free_head, &ent);
+
+ if (ent)
+ ent->e_rec.e_clusters = cpu_to_le32(new_clusters -
+ le32_to_cpu(ent->e_rec.e_cpos));
+
+ OCFS2_I(inode)->ip_map.em_clusters = new_clusters;
+
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ if (free_head)
+ __ocfs2_extent_map_drop_cleanup(free_head);
+
+ return 0;
+}
+
+int __init init_ocfs2_extent_maps(void)
+{
+ ocfs2_em_ent_cachep =
+ kmem_cache_create("ocfs2_em_ent",
+ sizeof(struct ocfs2_extent_map_entry),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (!ocfs2_em_ent_cachep)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void __exit exit_ocfs2_extent_maps(void)
+{
+ kmem_cache_destroy(ocfs2_em_ent_cachep);
+}
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h
new file mode 100644
index 000000000000..fa3745efa886
--- /dev/null
+++ b/fs/ocfs2/extent_map.h
@@ -0,0 +1,46 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * extent_map.h
+ *
+ * In-memory file extent mappings for OCFS2.
+ *
+ * Copyright (C) 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef _EXTENT_MAP_H
+#define _EXTENT_MAP_H
+
+int init_ocfs2_extent_maps(void);
+void exit_ocfs2_extent_maps(void);
+
+/*
+ * EVERY CALL here except _init, _trunc, and _drop expects alloc_sem
+ * to be held. The allocation cannot change at all while the map is
+ * in the process of being updated.
+ */
+int ocfs2_extent_map_init(struct inode *inode);
+int ocfs2_extent_map_append(struct inode *inode,
+ struct ocfs2_extent_rec *rec,
+ u32 new_clusters);
+int ocfs2_extent_map_get_blocks(struct inode *inode,
+ u64 v_blkno, int count,
+ u64 *p_blkno, int *ret_count);
+int ocfs2_extent_map_drop(struct inode *inode, u32 new_clusters);
+int ocfs2_extent_map_trunc(struct inode *inode, u32 new_clusters);
+
+#endif /* _EXTENT_MAP_H */
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
new file mode 100644
index 000000000000..eaf33caa0a1f
--- /dev/null
+++ b/fs/ocfs2/file.c
@@ -0,0 +1,1238 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * file.c
+ *
+ * File open, close, extend, truncate
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/capability.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/uio.h>
+
+#define MLOG_MASK_PREFIX ML_INODE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "aops.h"
+#include "dir.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "file.h"
+#include "sysfile.h"
+#include "inode.h"
+#include "journal.h"
+#include "mmap.h"
+#include "suballoc.h"
+#include "super.h"
+
+#include "buffer_head_io.h"
+
+static int ocfs2_sync_inode(struct inode *inode)
+{
+ filemap_fdatawrite(inode->i_mapping);
+ return sync_mapping_buffers(inode->i_mapping);
+}
+
+static int ocfs2_file_open(struct inode *inode, struct file *file)
+{
+ int status;
+ int mode = file->f_flags;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
+ file->f_dentry->d_name.len, file->f_dentry->d_name.name);
+
+ spin_lock(&oi->ip_lock);
+
+ /* Check that the inode hasn't been wiped from disk by another
+ * node. If it hasn't then we're safe as long as we hold the
+ * spin lock until our increment of open count. */
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
+ spin_unlock(&oi->ip_lock);
+
+ status = -ENOENT;
+ goto leave;
+ }
+
+ if (mode & O_DIRECT)
+ oi->ip_flags |= OCFS2_INODE_OPEN_DIRECT;
+
+ oi->ip_open_count++;
+ spin_unlock(&oi->ip_lock);
+ status = 0;
+leave:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_file_release(struct inode *inode, struct file *file)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file,
+ file->f_dentry->d_name.len,
+ file->f_dentry->d_name.name);
+
+ spin_lock(&oi->ip_lock);
+ if (!--oi->ip_open_count)
+ oi->ip_flags &= ~OCFS2_INODE_OPEN_DIRECT;
+ spin_unlock(&oi->ip_lock);
+
+ mlog_exit(0);
+
+ return 0;
+}
+
+static int ocfs2_sync_file(struct file *file,
+ struct dentry *dentry,
+ int datasync)
+{
+ int err = 0;
+ journal_t *journal;
+ struct inode *inode = dentry->d_inode;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", file, dentry, datasync,
+ dentry->d_name.len, dentry->d_name.name);
+
+ err = ocfs2_sync_inode(dentry->d_inode);
+ if (err)
+ goto bail;
+
+ journal = osb->journal->j_journal;
+ err = journal_force_commit(journal);
+
+bail:
+ mlog_exit(err);
+
+ return (err < 0) ? -EIO : 0;
+}
+
+int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 new_i_size)
+{
+ int status;
+
+ mlog_entry_void();
+ i_size_write(inode, new_i_size);
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(new_i_size);
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_simple_size_update(struct inode *inode,
+ struct buffer_head *di_bh,
+ u64 new_i_size)
+{
+ int ret;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_journal_handle *handle = NULL;
+
+ handle = ocfs2_start_trans(osb, NULL,
+ OCFS2_INODE_UPDATE_CREDITS);
+ if (handle == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_set_inode_size(handle, inode, di_bh,
+ new_i_size);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ ocfs2_commit_trans(handle);
+out:
+ return ret;
+}
+
+static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 new_i_size)
+{
+ int status;
+ struct ocfs2_journal_handle *handle;
+
+ mlog_entry_void();
+
+ /* TODO: This needs to actually orphan the inode in this
+ * transaction. */
+
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ mlog_errno(status);
+ goto out;
+ }
+
+ status = ocfs2_set_inode_size(handle, inode, fe_bh, new_i_size);
+ if (status < 0)
+ mlog_errno(status);
+
+ ocfs2_commit_trans(handle);
+out:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_truncate_file(struct inode *inode,
+ struct buffer_head *di_bh,
+ u64 new_i_size)
+{
+ int status = 0;
+ struct ocfs2_dinode *fe = NULL;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_truncate_context *tc = NULL;
+
+ mlog_entry("(inode = %"MLFu64", new_i_size = %"MLFu64"\n",
+ OCFS2_I(inode)->ip_blkno, new_i_size);
+
+ truncate_inode_pages(inode->i_mapping, new_i_size);
+
+ fe = (struct ocfs2_dinode *) di_bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+ status = -EIO;
+ goto bail;
+ }
+
+ mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode),
+ "Inode %"MLFu64", inode i_size = %lld != di "
+ "i_size = %"MLFu64", i_flags = 0x%x\n",
+ OCFS2_I(inode)->ip_blkno,
+ i_size_read(inode),
+ le64_to_cpu(fe->i_size), le32_to_cpu(fe->i_flags));
+
+ if (new_i_size > le64_to_cpu(fe->i_size)) {
+ mlog(0, "asked to truncate file with size (%"MLFu64") "
+ "to size (%"MLFu64")!\n",
+ le64_to_cpu(fe->i_size), new_i_size);
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "inode %"MLFu64", i_size = %"MLFu64", new_i_size = %"MLFu64"\n",
+ le64_to_cpu(fe->i_blkno), le64_to_cpu(fe->i_size), new_i_size);
+
+ /* lets handle the simple truncate cases before doing any more
+ * cluster locking. */
+ if (new_i_size == le64_to_cpu(fe->i_size))
+ goto bail;
+
+ if (le32_to_cpu(fe->i_clusters) ==
+ ocfs2_clusters_for_bytes(osb->sb, new_i_size)) {
+ mlog(0, "fe->i_clusters = %u, so we do a simple truncate\n",
+ fe->i_clusters);
+ /* No allocation change is required, so lets fast path
+ * this truncate. */
+ status = ocfs2_simple_size_update(inode, di_bh, new_i_size);
+ if (status < 0)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* This forces other nodes to sync and drop their pages */
+ status = ocfs2_data_lock(inode, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_data_unlock(inode, 1);
+
+ /* alright, we're going to need to do a full blown alloc size
+ * change. Orphan the inode so that recovery can complete the
+ * truncate if necessary. This does the task of marking
+ * i_size. */
+ status = ocfs2_orphan_for_truncate(osb, inode, di_bh, new_i_size);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_prepare_truncate(osb, inode, di_bh, &tc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_commit_truncate(osb, inode, di_bh, tc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* TODO: orphan dir cleanup here. */
+bail:
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * extend allocation only here.
+ * we'll update all the disk stuff, and oip->alloc_size
+ *
+ * expect stuff to be locked, a transaction started and enough data /
+ * metadata reservations in the contexts.
+ *
+ * Will return -EAGAIN, and a reason if a restart is needed.
+ * If passed in, *reason will always be set, even in error.
+ */
+int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
+ struct inode *inode,
+ u32 clusters_to_add,
+ struct buffer_head *fe_bh,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ enum ocfs2_alloc_restarted *reason_ret)
+{
+ int status = 0;
+ int free_extents;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ enum ocfs2_alloc_restarted reason = RESTART_NONE;
+ u32 bit_off, num_bits;
+ u64 block;
+
+ BUG_ON(!clusters_to_add);
+
+ free_extents = ocfs2_num_free_extents(osb, inode, fe);
+ if (free_extents < 0) {
+ status = free_extents;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* there are two cases which could cause us to EAGAIN in the
+ * we-need-more-metadata case:
+ * 1) we haven't reserved *any*
+ * 2) we are so fragmented, we've needed to add metadata too
+ * many times. */
+ if (!free_extents && !meta_ac) {
+ mlog(0, "we haven't reserved any metadata!\n");
+ status = -EAGAIN;
+ reason = RESTART_META;
+ goto leave;
+ } else if ((!free_extents)
+ && (ocfs2_alloc_context_bits_left(meta_ac)
+ < ocfs2_extend_meta_needed(fe))) {
+ mlog(0, "filesystem is really fragmented...\n");
+ status = -EAGAIN;
+ reason = RESTART_META;
+ goto leave;
+ }
+
+ status = ocfs2_claim_clusters(osb, handle, data_ac, 1,
+ &bit_off, &num_bits);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ BUG_ON(num_bits > clusters_to_add);
+
+ /* reserve our write early -- insert_extent may update the inode */
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ block = ocfs2_clusters_to_blocks(osb->sb, bit_off);
+ mlog(0, "Allocating %u clusters at block %u for inode %"MLFu64"\n",
+ num_bits, bit_off, OCFS2_I(inode)->ip_blkno);
+ status = ocfs2_insert_extent(osb, handle, inode, fe_bh, block,
+ num_bits, meta_ac);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ le32_add_cpu(&fe->i_clusters, num_bits);
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ clusters_to_add -= num_bits;
+
+ if (clusters_to_add) {
+ mlog(0, "need to alloc once more, clusters = %u, wanted = "
+ "%u\n", fe->i_clusters, clusters_to_add);
+ status = -EAGAIN;
+ reason = RESTART_TRANS;
+ }
+
+leave:
+ mlog_exit(status);
+ if (reason_ret)
+ *reason_ret = reason;
+ return status;
+}
+
+static int ocfs2_extend_allocation(struct inode *inode,
+ u32 clusters_to_add)
+{
+ int status = 0;
+ int restart_func = 0;
+ int drop_alloc_sem = 0;
+ int credits, num_free_extents;
+ u32 prev_clusters;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_dinode *fe = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_alloc_context *data_ac = NULL;
+ struct ocfs2_alloc_context *meta_ac = NULL;
+ enum ocfs2_alloc_restarted why;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ mlog_entry("(clusters_to_add = %u)\n", clusters_to_add);
+
+ status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno, &bh,
+ OCFS2_BH_CACHED, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ fe = (struct ocfs2_dinode *) bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
+ status = -EIO;
+ goto leave;
+ }
+
+restart_all:
+ BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
+
+ mlog(0, "extend inode %"MLFu64", i_size = %lld, fe->i_clusters = %u, "
+ "clusters_to_add = %u\n",
+ OCFS2_I(inode)->ip_blkno, i_size_read(inode),
+ fe->i_clusters, clusters_to_add);
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ num_free_extents = ocfs2_num_free_extents(osb,
+ inode,
+ fe);
+ if (num_free_extents < 0) {
+ status = num_free_extents;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (!num_free_extents) {
+ status = ocfs2_reserve_new_metadata(osb,
+ handle,
+ fe,
+ &meta_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+ }
+
+ status = ocfs2_reserve_clusters(osb,
+ handle,
+ clusters_to_add,
+ &data_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* blocks peope in read/write from reading our allocation
+ * until we're done changing it. We depend on i_mutex to block
+ * other extend/truncate calls while we're here. Ordering wrt
+ * start_trans is important here -- always do it before! */
+ down_write(&OCFS2_I(inode)->ip_alloc_sem);
+ drop_alloc_sem = 1;
+
+ credits = ocfs2_calc_extend_credits(osb->sb, fe, clusters_to_add);
+ handle = ocfs2_start_trans(osb, handle, credits);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto leave;
+ }
+
+restarted_transaction:
+ /* reserve a write to the file entry early on - that we if we
+ * run out of credits in the allocation path, we can still
+ * update i_size. */
+ status = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ prev_clusters = OCFS2_I(inode)->ip_clusters;
+
+ status = ocfs2_do_extend_allocation(osb,
+ inode,
+ clusters_to_add,
+ bh,
+ handle,
+ data_ac,
+ meta_ac,
+ &why);
+ if ((status < 0) && (status != -EAGAIN)) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_journal_dirty(handle, bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ if (why != RESTART_NONE && clusters_to_add) {
+ if (why == RESTART_META) {
+ mlog(0, "restarting function.\n");
+ restart_func = 1;
+ } else {
+ BUG_ON(why != RESTART_TRANS);
+
+ mlog(0, "restarting transaction.\n");
+ /* TODO: This can be more intelligent. */
+ credits = ocfs2_calc_extend_credits(osb->sb,
+ fe,
+ clusters_to_add);
+ status = ocfs2_extend_trans(handle, credits);
+ if (status < 0) {
+ /* handle still has to be committed at
+ * this point. */
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto leave;
+ }
+ goto restarted_transaction;
+ }
+ }
+
+ mlog(0, "fe: i_clusters = %u, i_size=%"MLFu64"\n",
+ fe->i_clusters, fe->i_size);
+ mlog(0, "inode: ip_clusters=%u, i_size=%lld\n",
+ OCFS2_I(inode)->ip_clusters, i_size_read(inode));
+
+leave:
+ if (drop_alloc_sem) {
+ up_write(&OCFS2_I(inode)->ip_alloc_sem);
+ drop_alloc_sem = 0;
+ }
+ if (handle) {
+ ocfs2_commit_trans(handle);
+ handle = NULL;
+ }
+ if (data_ac) {
+ ocfs2_free_alloc_context(data_ac);
+ data_ac = NULL;
+ }
+ if (meta_ac) {
+ ocfs2_free_alloc_context(meta_ac);
+ meta_ac = NULL;
+ }
+ if ((!status) && restart_func) {
+ restart_func = 0;
+ goto restart_all;
+ }
+ if (bh) {
+ brelse(bh);
+ bh = NULL;
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/* Some parts of this taken from generic_cont_expand, which turned out
+ * to be too fragile to do exactly what we need without us having to
+ * worry about recursive locking in ->commit_write(). */
+static int ocfs2_write_zero_page(struct inode *inode,
+ u64 size)
+{
+ struct address_space *mapping = inode->i_mapping;
+ struct page *page;
+ unsigned long index;
+ unsigned int offset;
+ struct ocfs2_journal_handle *handle = NULL;
+ int ret;
+
+ offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */
+ /* ugh. in prepare/commit_write, if from==to==start of block, we
+ ** skip the prepare. make sure we never send an offset for the start
+ ** of a block
+ */
+ if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) {
+ offset++;
+ }
+ index = size >> PAGE_CACHE_SHIFT;
+
+ page = grab_cache_page(mapping, index);
+ if (!page) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_prepare_write(NULL, page, offset, offset);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_unlock;
+ }
+
+ if (ocfs2_should_order_data(inode)) {
+ handle = ocfs2_start_walk_page_trans(inode, page, offset,
+ offset);
+ if (IS_ERR(handle)) {
+ ret = PTR_ERR(handle);
+ handle = NULL;
+ goto out_unlock;
+ }
+ }
+
+ /* must not update i_size! */
+ ret = block_commit_write(page, offset, offset);
+ if (ret < 0)
+ mlog_errno(ret);
+ else
+ ret = 0;
+
+ if (handle)
+ ocfs2_commit_trans(handle);
+out_unlock:
+ unlock_page(page);
+ page_cache_release(page);
+out:
+ return ret;
+}
+
+static int ocfs2_zero_extend(struct inode *inode,
+ u64 zero_to_size)
+{
+ int ret = 0;
+ u64 start_off;
+ struct super_block *sb = inode->i_sb;
+
+ start_off = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode));
+ while (start_off < zero_to_size) {
+ ret = ocfs2_write_zero_page(inode, start_off);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ start_off += sb->s_blocksize;
+ }
+
+out:
+ return ret;
+}
+
+static int ocfs2_extend_file(struct inode *inode,
+ struct buffer_head *di_bh,
+ u64 new_i_size)
+{
+ int ret = 0;
+ u32 clusters_to_add;
+
+ /* setattr sometimes calls us like this. */
+ if (new_i_size == 0)
+ goto out;
+
+ if (i_size_read(inode) == new_i_size)
+ goto out;
+ BUG_ON(new_i_size < i_size_read(inode));
+
+ clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size) -
+ OCFS2_I(inode)->ip_clusters;
+
+ if (clusters_to_add) {
+ ret = ocfs2_extend_allocation(inode, clusters_to_add);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_zero_extend(inode, new_i_size);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ /* No allocation required, we just use this helper to
+ * do a trivial update of i_size. */
+ ret = ocfs2_simple_size_update(inode, di_bh, new_i_size);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ int status = 0, size_change;
+ struct inode *inode = dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+ struct buffer_head *bh = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+
+ mlog_entry("(0x%p, '%.*s')\n", dentry,
+ dentry->d_name.len, dentry->d_name.name);
+
+ if (attr->ia_valid & ATTR_MODE)
+ mlog(0, "mode change: %d\n", attr->ia_mode);
+ if (attr->ia_valid & ATTR_UID)
+ mlog(0, "uid change: %d\n", attr->ia_uid);
+ if (attr->ia_valid & ATTR_GID)
+ mlog(0, "gid change: %d\n", attr->ia_gid);
+ if (attr->ia_valid & ATTR_SIZE)
+ mlog(0, "size change...\n");
+ if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME))
+ mlog(0, "time change...\n");
+
+#define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \
+ | ATTR_GID | ATTR_UID | ATTR_MODE)
+ if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) {
+ mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid);
+ return 0;
+ }
+
+ status = inode_change_ok(inode, attr);
+ if (status)
+ return status;
+
+ size_change = S_ISREG(inode->i_mode) && attr->ia_valid & ATTR_SIZE;
+ if (size_change) {
+ status = ocfs2_rw_lock(inode, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = ocfs2_meta_lock(inode, NULL, &bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail_unlock_rw;
+ }
+
+ if (size_change && attr->ia_size != i_size_read(inode)) {
+ if (i_size_read(inode) > attr->ia_size)
+ status = ocfs2_truncate_file(inode, bh, attr->ia_size);
+ else
+ status = ocfs2_extend_file(inode, bh, attr->ia_size);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ status = -ENOSPC;
+ goto bail_unlock;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ mlog_errno(status);
+ goto bail_unlock;
+ }
+
+ status = inode_setattr(inode, attr);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_commit;
+ }
+
+ status = ocfs2_mark_inode_dirty(handle, inode, bh);
+ if (status < 0)
+ mlog_errno(status);
+
+bail_commit:
+ ocfs2_commit_trans(handle);
+bail_unlock:
+ ocfs2_meta_unlock(inode, 1);
+bail_unlock_rw:
+ if (size_change)
+ ocfs2_rw_unlock(inode, 1);
+bail:
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_getattr(struct vfsmount *mnt,
+ struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+ struct super_block *sb = dentry->d_inode->i_sb;
+ struct ocfs2_super *osb = sb->s_fs_info;
+ int err;
+
+ mlog_entry_void();
+
+ err = ocfs2_inode_revalidate(dentry);
+ if (err) {
+ if (err != -ENOENT)
+ mlog_errno(err);
+ goto bail;
+ }
+
+ generic_fillattr(inode, stat);
+
+ /* We set the blksize from the cluster size for performance */
+ stat->blksize = osb->s_clustersize;
+
+bail:
+ mlog_exit(err);
+
+ return err;
+}
+
+static int ocfs2_write_remove_suid(struct inode *inode)
+{
+ int ret;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_journal_handle *handle;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_dinode *di;
+
+ mlog_entry("(Inode %"MLFu64", mode 0%o)\n", oi->ip_blkno,
+ inode->i_mode);
+
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS);
+ if (handle == NULL) {
+ ret = -ENOMEM;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_trans;
+ }
+
+ ret = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out_bh;
+ }
+
+ inode->i_mode &= ~S_ISUID;
+ if ((inode->i_mode & S_ISGID) && (inode->i_mode & S_IXGRP))
+ inode->i_mode &= ~S_ISGID;
+
+ di = (struct ocfs2_dinode *) bh->b_data;
+ di->i_mode = cpu_to_le16(inode->i_mode);
+
+ ret = ocfs2_journal_dirty(handle, bh);
+ if (ret < 0)
+ mlog_errno(ret);
+out_bh:
+ brelse(bh);
+out_trans:
+ ocfs2_commit_trans(handle);
+out:
+ mlog_exit(ret);
+ return ret;
+}
+
+static inline int ocfs2_write_should_remove_suid(struct inode *inode)
+{
+ mode_t mode = inode->i_mode;
+
+ if (!capable(CAP_FSETID)) {
+ if (unlikely(mode & S_ISUID))
+ return 1;
+
+ if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
+ return 1;
+ }
+ return 0;
+}
+
+static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
+ const char __user *buf,
+ size_t count,
+ loff_t pos)
+{
+ struct iovec local_iov = { .iov_base = (void __user *)buf,
+ .iov_len = count };
+ int ret, rw_level = -1, meta_level = -1, have_alloc_sem = 0;
+ u32 clusters;
+ struct file *filp = iocb->ki_filp;
+ struct inode *inode = filp->f_dentry->d_inode;
+ loff_t newsize, saved_pos;
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+#endif
+
+ mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
+ (unsigned int)count,
+ filp->f_dentry->d_name.len,
+ filp->f_dentry->d_name.name);
+
+ /* happy write of zero bytes */
+ if (count == 0)
+ return 0;
+
+ if (!inode) {
+ mlog(0, "bad inode\n");
+ return -EIO;
+ }
+
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ /* ugh, work around some applications which open everything O_DIRECT +
+ * O_APPEND and really don't mean to use O_DIRECT. */
+ if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS &&
+ (filp->f_flags & O_APPEND) && (filp->f_flags & O_DIRECT))
+ filp->f_flags &= ~O_DIRECT;
+#endif
+
+ mutex_lock(&inode->i_mutex);
+ /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
+ if (filp->f_flags & O_DIRECT) {
+ have_alloc_sem = 1;
+ down_read(&inode->i_alloc_sem);
+ }
+
+ /* concurrent O_DIRECT writes are allowed */
+ rw_level = (filp->f_flags & O_DIRECT) ? 0 : 1;
+ ret = ocfs2_rw_lock(inode, rw_level);
+ if (ret < 0) {
+ rw_level = -1;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /*
+ * We sample i_size under a read level meta lock to see if our write
+ * is extending the file, if it is we back off and get a write level
+ * meta lock.
+ */
+ meta_level = (filp->f_flags & O_APPEND) ? 1 : 0;
+ for(;;) {
+ ret = ocfs2_meta_lock(inode, NULL, NULL, meta_level);
+ if (ret < 0) {
+ meta_level = -1;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /* Clear suid / sgid if necessary. We do this here
+ * instead of later in the write path because
+ * remove_suid() calls ->setattr without any hint that
+ * we may have already done our cluster locking. Since
+ * ocfs2_setattr() *must* take cluster locks to
+ * proceeed, this will lead us to recursively lock the
+ * inode. There's also the dinode i_size state which
+ * can be lost via setattr during extending writes (we
+ * set inode->i_size at the end of a write. */
+ if (ocfs2_write_should_remove_suid(inode)) {
+ if (meta_level == 0) {
+ ocfs2_meta_unlock(inode, meta_level);
+ meta_level = 1;
+ continue;
+ }
+
+ ret = ocfs2_write_remove_suid(inode);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ }
+
+ /* work on a copy of ppos until we're sure that we won't have
+ * to recalculate it due to relocking. */
+ if (filp->f_flags & O_APPEND) {
+ saved_pos = i_size_read(inode);
+ mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos);
+ } else {
+ saved_pos = iocb->ki_pos;
+ }
+ newsize = count + saved_pos;
+
+ mlog(0, "pos=%lld newsize=%"MLFu64" cursize=%lld\n",
+ saved_pos, newsize, i_size_read(inode));
+
+ /* No need for a higher level metadata lock if we're
+ * never going past i_size. */
+ if (newsize <= i_size_read(inode))
+ break;
+
+ if (meta_level == 0) {
+ ocfs2_meta_unlock(inode, meta_level);
+ meta_level = 1;
+ continue;
+ }
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ clusters = ocfs2_clusters_for_bytes(inode->i_sb, newsize) -
+ OCFS2_I(inode)->ip_clusters;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ mlog(0, "Writing at EOF, may need more allocation: "
+ "i_size = %lld, newsize = %"MLFu64", need %u clusters\n",
+ i_size_read(inode), newsize, clusters);
+
+ /* We only want to continue the rest of this loop if
+ * our extend will actually require more
+ * allocation. */
+ if (!clusters)
+ break;
+
+ ret = ocfs2_extend_allocation(inode, clusters);
+ if (ret < 0) {
+ if (ret != -ENOSPC)
+ mlog_errno(ret);
+ goto out;
+ }
+
+ /* Fill any holes which would've been created by this
+ * write. If we're O_APPEND, this will wind up
+ * (correctly) being a noop. */
+ ret = ocfs2_zero_extend(inode, (u64) newsize - count);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+ break;
+ }
+
+ /* ok, we're done with i_size and alloc work */
+ iocb->ki_pos = saved_pos;
+ ocfs2_meta_unlock(inode, meta_level);
+ meta_level = -1;
+
+ /* communicate with ocfs2_dio_end_io */
+ ocfs2_iocb_set_rw_locked(iocb);
+
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS &&
+ filp->f_flags & O_DIRECT) {
+ unsigned int saved_flags = filp->f_flags;
+ int sector_size = 1 << osb->s_sectsize_bits;
+
+ if ((saved_pos & (sector_size - 1)) ||
+ (count & (sector_size - 1)) ||
+ ((unsigned long)buf & (sector_size - 1))) {
+ filp->f_flags |= O_SYNC;
+ filp->f_flags &= ~O_DIRECT;
+ }
+
+ ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
+ &iocb->ki_pos);
+
+ filp->f_flags = saved_flags;
+ } else
+#endif
+ ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
+ &iocb->ki_pos);
+
+ /* buffered aio wouldn't have proper lock coverage today */
+ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
+
+ /*
+ * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io
+ * function pointer which is called when o_direct io completes so that
+ * it can unlock our rw lock. (it's the clustered equivalent of
+ * i_alloc_sem; protects truncate from racing with pending ios).
+ * Unfortunately there are error cases which call end_io and others
+ * that don't. so we don't have to unlock the rw_lock if either an
+ * async dio is going to do it in the future or an end_io after an
+ * error has already done it.
+ */
+ if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
+ rw_level = -1;
+ have_alloc_sem = 0;
+ }
+
+out:
+ if (meta_level != -1)
+ ocfs2_meta_unlock(inode, meta_level);
+ if (have_alloc_sem)
+ up_read(&inode->i_alloc_sem);
+ if (rw_level != -1)
+ ocfs2_rw_unlock(inode, rw_level);
+ mutex_unlock(&inode->i_mutex);
+
+ mlog_exit(ret);
+ return ret;
+}
+
+static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
+ char __user *buf,
+ size_t count,
+ loff_t pos)
+{
+ int ret = 0, rw_level = -1, have_alloc_sem = 0;
+ struct file *filp = iocb->ki_filp;
+ struct inode *inode = filp->f_dentry->d_inode;
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+#endif
+
+ mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf,
+ (unsigned int)count,
+ filp->f_dentry->d_name.len,
+ filp->f_dentry->d_name.name);
+
+ if (!inode) {
+ ret = -EINVAL;
+ mlog_errno(ret);
+ goto bail;
+ }
+
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) {
+ if (filp->f_flags & O_DIRECT) {
+ int sector_size = 1 << osb->s_sectsize_bits;
+
+ if ((pos & (sector_size - 1)) ||
+ (count & (sector_size - 1)) ||
+ ((unsigned long)buf & (sector_size - 1)) ||
+ (i_size_read(inode) & (sector_size -1))) {
+ filp->f_flags &= ~O_DIRECT;
+ }
+ }
+ }
+#endif
+
+ /*
+ * buffered reads protect themselves in ->readpage(). O_DIRECT reads
+ * need locks to protect pending reads from racing with truncate.
+ */
+ if (filp->f_flags & O_DIRECT) {
+ down_read(&inode->i_alloc_sem);
+ have_alloc_sem = 1;
+
+ ret = ocfs2_rw_lock(inode, 0);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto bail;
+ }
+ rw_level = 0;
+ /* communicate with ocfs2_dio_end_io */
+ ocfs2_iocb_set_rw_locked(iocb);
+ }
+
+ ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos);
+ if (ret == -EINVAL)
+ mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n");
+
+ /* buffered aio wouldn't have proper lock coverage today */
+ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
+
+ /* see ocfs2_file_aio_write */
+ if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
+ rw_level = -1;
+ have_alloc_sem = 0;
+ }
+
+bail:
+ if (have_alloc_sem)
+ up_read(&inode->i_alloc_sem);
+ if (rw_level != -1)
+ ocfs2_rw_unlock(inode, rw_level);
+ mlog_exit(ret);
+
+ return ret;
+}
+
+struct inode_operations ocfs2_file_iops = {
+ .setattr = ocfs2_setattr,
+ .getattr = ocfs2_getattr,
+};
+
+struct inode_operations ocfs2_special_file_iops = {
+ .setattr = ocfs2_setattr,
+ .getattr = ocfs2_getattr,
+};
+
+struct file_operations ocfs2_fops = {
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .sendfile = generic_file_sendfile,
+ .mmap = ocfs2_mmap,
+ .fsync = ocfs2_sync_file,
+ .release = ocfs2_file_release,
+ .open = ocfs2_file_open,
+ .aio_read = ocfs2_file_aio_read,
+ .aio_write = ocfs2_file_aio_write,
+};
+
+struct file_operations ocfs2_dops = {
+ .read = generic_read_dir,
+ .readdir = ocfs2_readdir,
+ .fsync = ocfs2_sync_file,
+};
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h
new file mode 100644
index 000000000000..a5ea33b24060
--- /dev/null
+++ b/fs/ocfs2/file.h
@@ -0,0 +1,57 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * file.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_FILE_H
+#define OCFS2_FILE_H
+
+extern struct file_operations ocfs2_fops;
+extern struct file_operations ocfs2_dops;
+extern struct inode_operations ocfs2_file_iops;
+extern struct inode_operations ocfs2_special_file_iops;
+struct ocfs2_alloc_context;
+
+enum ocfs2_alloc_restarted {
+ RESTART_NONE = 0,
+ RESTART_TRANS,
+ RESTART_META
+};
+int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
+ struct inode *inode,
+ u32 clusters_to_add,
+ struct buffer_head *fe_bh,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *data_ac,
+ struct ocfs2_alloc_context *meta_ac,
+ enum ocfs2_alloc_restarted *reason);
+int ocfs2_setattr(struct dentry *dentry, struct iattr *attr);
+int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat);
+
+int ocfs2_set_inode_size(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ u64 new_i_size);
+
+#endif /* OCFS2_FILE_H */
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
new file mode 100644
index 000000000000..0bbd22f46c80
--- /dev/null
+++ b/fs/ocfs2/heartbeat.c
@@ -0,0 +1,378 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * heartbeat.c
+ *
+ * Register ourselves with the heartbaet service, keep our node maps
+ * up to date, and fire off recovery when needed.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/kmod.h>
+
+#include <cluster/heartbeat.h>
+#include <cluster/nodemanager.h>
+
+#include <dlm/dlmapi.h>
+
+#define MLOG_MASK_PREFIX ML_SUPER
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "journal.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+#define OCFS2_HB_NODE_DOWN_PRI (0x0000002)
+#define OCFS2_HB_NODE_UP_PRI OCFS2_HB_NODE_DOWN_PRI
+
+static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ int bit);
+static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map,
+ int bit);
+static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map);
+static void __ocfs2_node_map_dup(struct ocfs2_node_map *target,
+ struct ocfs2_node_map *from);
+static void __ocfs2_node_map_set(struct ocfs2_node_map *target,
+ struct ocfs2_node_map *from);
+
+void ocfs2_init_node_maps(struct ocfs2_super *osb)
+{
+ spin_lock_init(&osb->node_map_lock);
+ ocfs2_node_map_init(&osb->mounted_map);
+ ocfs2_node_map_init(&osb->recovery_map);
+ ocfs2_node_map_init(&osb->umount_map);
+}
+
+static void ocfs2_do_node_down(int node_num,
+ struct ocfs2_super *osb)
+{
+ BUG_ON(osb->node_num == node_num);
+
+ mlog(0, "ocfs2: node down event for %d\n", node_num);
+
+ if (!osb->dlm) {
+ /*
+ * No DLM means we're not even ready to participate yet.
+ * We check the slots after the DLM comes up, so we will
+ * notice the node death then. We can safely ignore it
+ * here.
+ */
+ return;
+ }
+
+ if (ocfs2_node_map_test_bit(osb, &osb->umount_map, node_num)) {
+ /* If a node is in the umount map, then we've been
+ * expecting him to go down and we know ahead of time
+ * that recovery is not necessary. */
+ ocfs2_node_map_clear_bit(osb, &osb->umount_map, node_num);
+ return;
+ }
+
+ ocfs2_recovery_thread(osb, node_num);
+
+ ocfs2_remove_node_from_vote_queues(osb, node_num);
+}
+
+static void ocfs2_hb_node_down_cb(struct o2nm_node *node,
+ int node_num,
+ void *data)
+{
+ ocfs2_do_node_down(node_num, (struct ocfs2_super *) data);
+}
+
+/* Called from the dlm when it's about to evict a node. We may also
+ * get a heartbeat callback later. */
+static void ocfs2_dlm_eviction_cb(int node_num,
+ void *data)
+{
+ struct ocfs2_super *osb = (struct ocfs2_super *) data;
+ struct super_block *sb = osb->sb;
+
+ mlog(ML_NOTICE, "device (%u,%u): dlm has evicted node %d\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), node_num);
+
+ ocfs2_do_node_down(node_num, osb);
+}
+
+static void ocfs2_hb_node_up_cb(struct o2nm_node *node,
+ int node_num,
+ void *data)
+{
+ struct ocfs2_super *osb = data;
+
+ BUG_ON(osb->node_num == node_num);
+
+ mlog(0, "node up event for %d\n", node_num);
+ ocfs2_node_map_clear_bit(osb, &osb->umount_map, node_num);
+}
+
+void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb)
+{
+ o2hb_setup_callback(&osb->osb_hb_down, O2HB_NODE_DOWN_CB,
+ ocfs2_hb_node_down_cb, osb,
+ OCFS2_HB_NODE_DOWN_PRI);
+
+ o2hb_setup_callback(&osb->osb_hb_up, O2HB_NODE_UP_CB,
+ ocfs2_hb_node_up_cb, osb, OCFS2_HB_NODE_UP_PRI);
+
+ /* Not exactly a heartbeat callback, but leads to essentially
+ * the same path so we set it up here. */
+ dlm_setup_eviction_cb(&osb->osb_eviction_cb,
+ ocfs2_dlm_eviction_cb,
+ osb);
+}
+
+/* Most functions here are just stubs for now... */
+int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
+{
+ int status;
+
+ status = o2hb_register_callback(&osb->osb_hb_down);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = o2hb_register_callback(&osb->osb_hb_up);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ return status;
+}
+
+void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
+{
+ int status;
+
+ status = o2hb_unregister_callback(&osb->osb_hb_down);
+ if (status < 0)
+ mlog_errno(status);
+
+ status = o2hb_unregister_callback(&osb->osb_hb_up);
+ if (status < 0)
+ mlog_errno(status);
+}
+
+void ocfs2_stop_heartbeat(struct ocfs2_super *osb)
+{
+ int ret;
+ char *argv[5], *envp[3];
+
+ if (!osb->uuid_str) {
+ /* This can happen if we don't get far enough in mount... */
+ mlog(0, "No UUID with which to stop heartbeat!\n\n");
+ return;
+ }
+
+ argv[0] = (char *)o2nm_get_hb_ctl_path();
+ argv[1] = "-K";
+ argv[2] = "-u";
+ argv[3] = osb->uuid_str;
+ argv[4] = NULL;
+
+ mlog(0, "Run: %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
+
+ /* minimal command environment taken from cpu_run_sbin_hotplug */
+ envp[0] = "HOME=/";
+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[2] = NULL;
+
+ ret = call_usermodehelper(argv[0], argv, envp, 1);
+ if (ret < 0)
+ mlog_errno(ret);
+}
+
+/* special case -1 for now
+ * TODO: should *really* make sure the calling func never passes -1!! */
+void ocfs2_node_map_init(struct ocfs2_node_map *map)
+{
+ map->num_nodes = OCFS2_NODE_MAP_MAX_NODES;
+ memset(map->map, 0, BITS_TO_LONGS(OCFS2_NODE_MAP_MAX_NODES) *
+ sizeof(unsigned long));
+}
+
+static inline void __ocfs2_node_map_set_bit(struct ocfs2_node_map *map,
+ int bit)
+{
+ set_bit(bit, map->map);
+}
+
+void ocfs2_node_map_set_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit)
+{
+ if (bit==-1)
+ return;
+ BUG_ON(bit >= map->num_nodes);
+ spin_lock(&osb->node_map_lock);
+ __ocfs2_node_map_set_bit(map, bit);
+ spin_unlock(&osb->node_map_lock);
+}
+
+static inline void __ocfs2_node_map_clear_bit(struct ocfs2_node_map *map,
+ int bit)
+{
+ clear_bit(bit, map->map);
+}
+
+void ocfs2_node_map_clear_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit)
+{
+ if (bit==-1)
+ return;
+ BUG_ON(bit >= map->num_nodes);
+ spin_lock(&osb->node_map_lock);
+ __ocfs2_node_map_clear_bit(map, bit);
+ spin_unlock(&osb->node_map_lock);
+}
+
+int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit)
+{
+ int ret;
+ if (bit >= map->num_nodes) {
+ mlog(ML_ERROR, "bit=%d map->num_nodes=%d\n", bit, map->num_nodes);
+ BUG();
+ }
+ spin_lock(&osb->node_map_lock);
+ ret = test_bit(bit, map->map);
+ spin_unlock(&osb->node_map_lock);
+ return ret;
+}
+
+static inline int __ocfs2_node_map_is_empty(struct ocfs2_node_map *map)
+{
+ int bit;
+ bit = find_next_bit(map->map, map->num_nodes, 0);
+ if (bit < map->num_nodes)
+ return 0;
+ return 1;
+}
+
+int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map)
+{
+ int ret;
+ BUG_ON(map->num_nodes == 0);
+ spin_lock(&osb->node_map_lock);
+ ret = __ocfs2_node_map_is_empty(map);
+ spin_unlock(&osb->node_map_lock);
+ return ret;
+}
+
+static void __ocfs2_node_map_dup(struct ocfs2_node_map *target,
+ struct ocfs2_node_map *from)
+{
+ BUG_ON(from->num_nodes == 0);
+ ocfs2_node_map_init(target);
+ __ocfs2_node_map_set(target, from);
+}
+
+/* returns 1 if bit is the only bit set in target, 0 otherwise */
+int ocfs2_node_map_is_only(struct ocfs2_super *osb,
+ struct ocfs2_node_map *target,
+ int bit)
+{
+ struct ocfs2_node_map temp;
+ int ret;
+
+ spin_lock(&osb->node_map_lock);
+ __ocfs2_node_map_dup(&temp, target);
+ __ocfs2_node_map_clear_bit(&temp, bit);
+ ret = __ocfs2_node_map_is_empty(&temp);
+ spin_unlock(&osb->node_map_lock);
+
+ return ret;
+}
+
+static void __ocfs2_node_map_set(struct ocfs2_node_map *target,
+ struct ocfs2_node_map *from)
+{
+ int num_longs, i;
+
+ BUG_ON(target->num_nodes != from->num_nodes);
+ BUG_ON(target->num_nodes == 0);
+
+ num_longs = BITS_TO_LONGS(target->num_nodes);
+ for (i = 0; i < num_longs; i++)
+ target->map[i] = from->map[i];
+}
+
+/* Returns whether the recovery bit was actually set - it may not be
+ * if a node is still marked as needing recovery */
+int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+ int num)
+{
+ int set = 0;
+
+ spin_lock(&osb->node_map_lock);
+
+ __ocfs2_node_map_clear_bit(&osb->mounted_map, num);
+
+ if (!test_bit(num, osb->recovery_map.map)) {
+ __ocfs2_node_map_set_bit(&osb->recovery_map, num);
+ set = 1;
+ }
+
+ spin_unlock(&osb->node_map_lock);
+
+ return set;
+}
+
+void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+ int num)
+{
+ ocfs2_node_map_clear_bit(osb, &osb->recovery_map, num);
+}
+
+int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int idx)
+{
+ int i = idx;
+
+ idx = O2NM_INVALID_NODE_NUM;
+ spin_lock(&osb->node_map_lock);
+ if ((i != O2NM_INVALID_NODE_NUM) &&
+ (i >= 0) &&
+ (i < map->num_nodes)) {
+ while(i < map->num_nodes) {
+ if (test_bit(i, map->map)) {
+ idx = i;
+ break;
+ }
+ i++;
+ }
+ }
+ spin_unlock(&osb->node_map_lock);
+ return idx;
+}
diff --git a/fs/ocfs2/heartbeat.h b/fs/ocfs2/heartbeat.h
new file mode 100644
index 000000000000..e8fb079122e4
--- /dev/null
+++ b/fs/ocfs2/heartbeat.h
@@ -0,0 +1,67 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * heartbeat.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_HEARTBEAT_H
+#define OCFS2_HEARTBEAT_H
+
+void ocfs2_init_node_maps(struct ocfs2_super *osb);
+
+void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb);
+int ocfs2_register_hb_callbacks(struct ocfs2_super *osb);
+void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb);
+void ocfs2_stop_heartbeat(struct ocfs2_super *osb);
+
+/* node map functions - used to keep track of mounted and in-recovery
+ * nodes. */
+void ocfs2_node_map_init(struct ocfs2_node_map *map);
+int ocfs2_node_map_is_empty(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map);
+void ocfs2_node_map_set_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit);
+void ocfs2_node_map_clear_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit);
+int ocfs2_node_map_test_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int bit);
+int ocfs2_node_map_iterate(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map,
+ int idx);
+static inline int ocfs2_node_map_first_set_bit(struct ocfs2_super *osb,
+ struct ocfs2_node_map *map)
+{
+ return ocfs2_node_map_iterate(osb, map, 0);
+}
+int ocfs2_recovery_map_set(struct ocfs2_super *osb,
+ int num);
+void ocfs2_recovery_map_clear(struct ocfs2_super *osb,
+ int num);
+/* returns 1 if bit is the only bit set in target, 0 otherwise */
+int ocfs2_node_map_is_only(struct ocfs2_super *osb,
+ struct ocfs2_node_map *target,
+ int bit);
+
+#endif /* OCFS2_HEARTBEAT_H */
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
new file mode 100644
index 000000000000..d4ecc0627716
--- /dev/null
+++ b/fs/ocfs2/inode.c
@@ -0,0 +1,1140 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * inode.c
+ *
+ * vfs' aops, fops, dops and iops
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
+
+#include <asm/byteorder.h>
+
+#define MLOG_MASK_PREFIX ML_INODE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "file.h"
+#include "inode.h"
+#include "journal.h"
+#include "namei.h"
+#include "suballoc.h"
+#include "super.h"
+#include "symlink.h"
+#include "sysfile.h"
+#include "uptodate.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+#define OCFS2_FI_FLAG_NOWAIT 0x1
+#define OCFS2_FI_FLAG_DELETE 0x2
+struct ocfs2_find_inode_args
+{
+ u64 fi_blkno;
+ unsigned long fi_ino;
+ unsigned int fi_flags;
+};
+
+static int ocfs2_read_locked_inode(struct inode *inode,
+ struct ocfs2_find_inode_args *args);
+static int ocfs2_init_locked_inode(struct inode *inode, void *opaque);
+static int ocfs2_find_actor(struct inode *inode, void *opaque);
+static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh);
+
+struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb,
+ u64 blkno,
+ int delete_vote)
+{
+ struct ocfs2_find_inode_args args;
+
+ /* ocfs2_ilookup_for_vote should *only* be called from the
+ * vote thread */
+ BUG_ON(current != osb->vote_task);
+
+ args.fi_blkno = blkno;
+ args.fi_flags = OCFS2_FI_FLAG_NOWAIT;
+ if (delete_vote)
+ args.fi_flags |= OCFS2_FI_FLAG_DELETE;
+ args.fi_ino = ino_from_blkno(osb->sb, blkno);
+ return ilookup5(osb->sb, args.fi_ino, ocfs2_find_actor, &args);
+}
+
+struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno)
+{
+ struct inode *inode = NULL;
+ struct super_block *sb = osb->sb;
+ struct ocfs2_find_inode_args args;
+
+ mlog_entry("(blkno = %"MLFu64")\n", blkno);
+
+ /* Ok. By now we've either got the offsets passed to us by the
+ * caller, or we just pulled them off the bh. Lets do some
+ * sanity checks to make sure they're OK. */
+ if (blkno == 0) {
+ inode = ERR_PTR(-EINVAL);
+ mlog_errno(PTR_ERR(inode));
+ goto bail;
+ }
+
+ args.fi_blkno = blkno;
+ args.fi_flags = 0;
+ args.fi_ino = ino_from_blkno(sb, blkno);
+
+ inode = iget5_locked(sb, args.fi_ino, ocfs2_find_actor,
+ ocfs2_init_locked_inode, &args);
+ /* inode was *not* in the inode cache. 2.6.x requires
+ * us to do our own read_inode call and unlock it
+ * afterwards. */
+ if (inode && inode->i_state & I_NEW) {
+ mlog(0, "Inode was not in inode cache, reading it.\n");
+ ocfs2_read_locked_inode(inode, &args);
+ unlock_new_inode(inode);
+ }
+ if (inode == NULL) {
+ inode = ERR_PTR(-ENOMEM);
+ mlog_errno(PTR_ERR(inode));
+ goto bail;
+ }
+ if (is_bad_inode(inode)) {
+ iput(inode);
+ inode = ERR_PTR(-ESTALE);
+ mlog_errno(PTR_ERR(inode));
+ goto bail;
+ }
+
+bail:
+ if (!IS_ERR(inode)) {
+ mlog(0, "returning inode with number %"MLFu64"\n",
+ OCFS2_I(inode)->ip_blkno);
+ mlog_exit_ptr(inode);
+ } else
+ mlog_errno(PTR_ERR(inode));
+
+ return inode;
+}
+
+
+/*
+ * here's how inodes get read from disk:
+ * iget5_locked -> find_actor -> OCFS2_FIND_ACTOR
+ * found? : return the in-memory inode
+ * not found? : get_new_inode -> OCFS2_INIT_LOCKED_INODE
+ */
+
+static int ocfs2_find_actor(struct inode *inode, void *opaque)
+{
+ struct ocfs2_find_inode_args *args = NULL;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ int ret = 0;
+
+ mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque);
+
+ args = opaque;
+
+ mlog_bug_on_msg(!inode, "No inode in find actor!\n");
+
+ if (oi->ip_blkno != args->fi_blkno)
+ goto bail;
+
+ /* OCFS2_FI_FLAG_NOWAIT is *only* set from
+ * ocfs2_ilookup_for_vote which won't create an inode for one
+ * that isn't found. The vote thread which doesn't want to get
+ * an inode which is in the process of going away - otherwise
+ * the call to __wait_on_freeing_inode in find_inode_fast will
+ * cause it to deadlock on an inode which may be waiting on a
+ * vote (or lock release) in delete_inode */
+ if ((args->fi_flags & OCFS2_FI_FLAG_NOWAIT) &&
+ (inode->i_state & (I_FREEING|I_CLEAR))) {
+ /* As stated above, we're not going to return an
+ * inode. In the case of a delete vote, the voting
+ * code is going to signal the other node to go
+ * ahead. Mark that state here, so this freeing inode
+ * has the state when it gets to delete_inode. */
+ if (args->fi_flags & OCFS2_FI_FLAG_DELETE) {
+ spin_lock(&oi->ip_lock);
+ ocfs2_mark_inode_remotely_deleted(inode);
+ spin_unlock(&oi->ip_lock);
+ }
+ goto bail;
+ }
+
+ ret = 1;
+bail:
+ mlog_exit(ret);
+ return ret;
+}
+
+/*
+ * initialize the new inode, but don't do anything that would cause
+ * us to sleep.
+ * return 0 on success, 1 on failure
+ */
+static int ocfs2_init_locked_inode(struct inode *inode, void *opaque)
+{
+ struct ocfs2_find_inode_args *args = opaque;
+
+ mlog_entry("inode = %p, opaque = %p\n", inode, opaque);
+
+ inode->i_ino = args->fi_ino;
+ OCFS2_I(inode)->ip_blkno = args->fi_blkno;
+
+ mlog_exit(0);
+ return 0;
+}
+
+int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
+ int create_ino)
+{
+ struct super_block *sb;
+ struct ocfs2_super *osb;
+ int status = -EINVAL;
+
+ mlog_entry("(0x%p, size:%"MLFu64")\n", inode, fe->i_size);
+
+ sb = inode->i_sb;
+ osb = OCFS2_SB(sb);
+
+ /* this means that read_inode cannot create a superblock inode
+ * today. change if needed. */
+ if (!OCFS2_IS_VALID_DINODE(fe) ||
+ !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) {
+ mlog(ML_ERROR, "Invalid dinode: i_ino=%lu, i_blkno=%"MLFu64", "
+ "signature = %.*s, flags = 0x%x\n",
+ inode->i_ino, le64_to_cpu(fe->i_blkno), 7,
+ fe->i_signature, le32_to_cpu(fe->i_flags));
+ goto bail;
+ }
+
+ if (le32_to_cpu(fe->i_fs_generation) != osb->fs_generation) {
+ mlog(ML_ERROR, "file entry generation does not match "
+ "superblock! osb->fs_generation=%x, "
+ "fe->i_fs_generation=%x\n",
+ osb->fs_generation, le32_to_cpu(fe->i_fs_generation));
+ goto bail;
+ }
+
+ inode->i_version = 1;
+ inode->i_generation = le32_to_cpu(fe->i_generation);
+ inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
+ inode->i_mode = le16_to_cpu(fe->i_mode);
+ inode->i_uid = le32_to_cpu(fe->i_uid);
+ inode->i_gid = le32_to_cpu(fe->i_gid);
+ inode->i_blksize = (u32)osb->s_clustersize;
+
+ /* Fast symlinks will have i_size but no allocated clusters. */
+ if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
+ inode->i_blocks = 0;
+ else
+ inode->i_blocks =
+ ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size));
+ inode->i_mapping->a_ops = &ocfs2_aops;
+ inode->i_flags |= S_NOATIME;
+ inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
+ inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
+ inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
+ inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);
+ inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);
+ inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);
+
+ if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno))
+ mlog(ML_ERROR,
+ "ip_blkno %"MLFu64" != i_blkno %"MLFu64"!\n",
+ OCFS2_I(inode)->ip_blkno, fe->i_blkno);
+
+ OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+ OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT;
+
+ if (create_ino)
+ inode->i_ino = ino_from_blkno(inode->i_sb,
+ le64_to_cpu(fe->i_blkno));
+
+ mlog(0, "blkno = %"MLFu64", ino = %lu, create_ino = %s\n",
+ fe->i_blkno, inode->i_ino, create_ino ? "true" : "false");
+
+ inode->i_nlink = le16_to_cpu(fe->i_links_count);
+
+ if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) {
+ OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
+ mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino);
+ } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) {
+ OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP;
+ } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) {
+ mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino);
+ /* we can't actually hit this as read_inode can't
+ * handle superblocks today ;-) */
+ BUG();
+ }
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ inode->i_fop = &ocfs2_fops;
+ inode->i_op = &ocfs2_file_iops;
+ i_size_write(inode, le64_to_cpu(fe->i_size));
+ break;
+ case S_IFDIR:
+ inode->i_op = &ocfs2_dir_iops;
+ inode->i_fop = &ocfs2_dops;
+ i_size_write(inode, le64_to_cpu(fe->i_size));
+ break;
+ case S_IFLNK:
+ if (ocfs2_inode_is_fast_symlink(inode))
+ inode->i_op = &ocfs2_fast_symlink_inode_operations;
+ else
+ inode->i_op = &ocfs2_symlink_inode_operations;
+ i_size_write(inode, le64_to_cpu(fe->i_size));
+ break;
+ default:
+ inode->i_op = &ocfs2_special_file_iops;
+ init_special_inode(inode, inode->i_mode,
+ inode->i_rdev);
+ break;
+ }
+
+ ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_rw_lockres,
+ OCFS2_LOCK_TYPE_RW, inode);
+ ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_meta_lockres,
+ OCFS2_LOCK_TYPE_META, inode);
+ ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres,
+ OCFS2_LOCK_TYPE_DATA, inode);
+
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_read_locked_inode(struct inode *inode,
+ struct ocfs2_find_inode_args *args)
+{
+ struct super_block *sb;
+ struct ocfs2_super *osb;
+ struct ocfs2_dinode *fe;
+ struct buffer_head *bh = NULL;
+ int status;
+ int sysfile = 0;
+
+ mlog_entry("(0x%p, 0x%p)\n", inode, args);
+
+ status = -EINVAL;
+ if (inode == NULL || inode->i_sb == NULL) {
+ mlog(ML_ERROR, "bad inode\n");
+ goto bail;
+ }
+ sb = inode->i_sb;
+ osb = OCFS2_SB(sb);
+
+ if (!args) {
+ mlog(ML_ERROR, "bad inode args\n");
+ make_bad_inode(inode);
+ goto bail;
+ }
+
+ /* Read the FE off disk. This is safe because the kernel only
+ * does one read_inode2 for a new inode, and if it doesn't
+ * exist yet then nobody can be working on it! */
+ status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0, NULL);
+ if (status < 0) {
+ mlog_errno(status);
+ make_bad_inode(inode);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ mlog(ML_ERROR, "Invalid dinode #%"MLFu64": signature = %.*s\n",
+ fe->i_blkno, 7, fe->i_signature);
+ make_bad_inode(inode);
+ goto bail;
+ }
+
+ if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL))
+ sysfile = 1;
+
+ if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
+ S_ISBLK(le16_to_cpu(fe->i_mode)))
+ inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
+
+ status = -EINVAL;
+ if (ocfs2_populate_inode(inode, fe, 0) < 0) {
+ mlog(ML_ERROR, "populate inode failed! i_blkno=%"MLFu64", "
+ "i_ino=%lu\n", fe->i_blkno, inode->i_ino);
+ make_bad_inode(inode);
+ goto bail;
+ }
+
+ BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
+
+ if (sysfile)
+ OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
+
+ status = 0;
+
+bail:
+ if (args && bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_sync_blockdev(struct super_block *sb)
+{
+ sync_blockdev(sb->s_bdev);
+}
+
+static int ocfs2_truncate_for_delete(struct ocfs2_super *osb,
+ struct inode *inode,
+ struct buffer_head *fe_bh)
+{
+ int status = 0;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_truncate_context *tc = NULL;
+ struct ocfs2_dinode *fe;
+
+ mlog_entry_void();
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ /* zero allocation, zero truncate :) */
+ if (!fe->i_clusters)
+ goto bail;
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_INODE_UPDATE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_set_inode_size(handle, inode, fe_bh, 0ULL);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_commit_trans(handle);
+ handle = NULL;
+
+ status = ocfs2_prepare_truncate(osb, inode, fe_bh, &tc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_commit_truncate(osb, inode, fe_bh, tc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_remove_inode(struct inode *inode,
+ struct buffer_head *di_bh,
+ struct inode *orphan_dir_inode,
+ struct buffer_head *orphan_dir_bh)
+{
+ int status;
+ struct inode *inode_alloc_inode = NULL;
+ struct buffer_head *inode_alloc_bh = NULL;
+ struct ocfs2_journal_handle *handle;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
+
+ inode_alloc_inode =
+ ocfs2_get_system_file_inode(osb, INODE_ALLOC_SYSTEM_INODE,
+ le16_to_cpu(di->i_suballoc_slot));
+ if (!inode_alloc_inode) {
+ status = -EEXIST;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mutex_lock(&inode_alloc_inode->i_mutex);
+ status = ocfs2_meta_lock(inode_alloc_inode, NULL, &inode_alloc_bh, 1);
+ if (status < 0) {
+ mutex_unlock(&inode_alloc_inode->i_mutex);
+
+ mlog_errno(status);
+ goto bail;
+ }
+
+ handle = ocfs2_start_trans(osb, NULL, OCFS2_DELETE_INODE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ mlog_errno(status);
+ goto bail_unlock;
+ }
+
+ status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode,
+ orphan_dir_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_commit;
+ }
+
+ /* set the inodes dtime */
+ status = ocfs2_journal_access(handle, inode, di_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_commit;
+ }
+
+ di->i_dtime = cpu_to_le64(CURRENT_TIME.tv_sec);
+ le32_and_cpu(&di->i_flags, ~(OCFS2_VALID_FL | OCFS2_ORPHANED_FL));
+
+ status = ocfs2_journal_dirty(handle, di_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_commit;
+ }
+
+ ocfs2_remove_from_cache(inode, di_bh);
+
+ status = ocfs2_free_dinode(handle, inode_alloc_inode,
+ inode_alloc_bh, di);
+ if (status < 0)
+ mlog_errno(status);
+
+bail_commit:
+ ocfs2_commit_trans(handle);
+bail_unlock:
+ ocfs2_meta_unlock(inode_alloc_inode, 1);
+ mutex_unlock(&inode_alloc_inode->i_mutex);
+ brelse(inode_alloc_bh);
+bail:
+ iput(inode_alloc_inode);
+
+ return status;
+}
+
+static int ocfs2_wipe_inode(struct inode *inode,
+ struct buffer_head *di_bh)
+{
+ int status, orphaned_slot;
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ /* We've already voted on this so it should be readonly - no
+ * spinlock needed. */
+ orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot;
+ orphan_dir_inode = ocfs2_get_system_file_inode(osb,
+ ORPHAN_DIR_SYSTEM_INODE,
+ orphaned_slot);
+ if (!orphan_dir_inode) {
+ status = -EEXIST;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Lock the orphan dir. The lock will be held for the entire
+ * delete_inode operation. We do this now to avoid races with
+ * recovery completion on other nodes. */
+ mutex_lock(&orphan_dir_inode->i_mutex);
+ status = ocfs2_meta_lock(orphan_dir_inode, NULL, &orphan_dir_bh, 1);
+ if (status < 0) {
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* we do this while holding the orphan dir lock because we
+ * don't want recovery being run from another node to vote for
+ * an inode delete on us -- this will result in two nodes
+ * truncating the same file! */
+ status = ocfs2_truncate_for_delete(osb, inode, di_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_unlock_dir;
+ }
+
+ status = ocfs2_remove_inode(inode, di_bh, orphan_dir_inode,
+ orphan_dir_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+bail_unlock_dir:
+ ocfs2_meta_unlock(orphan_dir_inode, 1);
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+ brelse(orphan_dir_bh);
+bail:
+ iput(orphan_dir_inode);
+
+ return status;
+}
+
+/* There is a series of simple checks that should be done before a
+ * vote is even considered. Encapsulate those in this function. */
+static int ocfs2_inode_is_valid_to_delete(struct inode *inode)
+{
+ int ret = 0;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ /* We shouldn't be getting here for the root directory
+ * inode.. */
+ if (inode == osb->root_inode) {
+ mlog(ML_ERROR, "Skipping delete of root inode.\n");
+ goto bail;
+ }
+
+ /* If we're coming from process_vote we can't go into our own
+ * voting [hello, deadlock city!], so unforuntately we just
+ * have to skip deleting this guy. That's OK though because
+ * the node who's doing the actual deleting should handle it
+ * anyway. */
+ if (current == osb->vote_task) {
+ mlog(0, "Skipping delete of %lu because we're currently "
+ "in process_vote\n", inode->i_ino);
+ goto bail;
+ }
+
+ spin_lock(&oi->ip_lock);
+ /* OCFS2 *never* deletes system files. This should technically
+ * never get here as system file inodes should always have a
+ * positive link count. */
+ if (oi->ip_flags & OCFS2_INODE_SYSTEM_FILE) {
+ mlog(ML_ERROR, "Skipping delete of system file %"MLFu64".\n",
+ oi->ip_blkno);
+ goto bail_unlock;
+ }
+
+ /* If we have voted "yes" on the wipe of this inode for
+ * another node, it will be marked here so we can safely skip
+ * it. Recovery will cleanup any inodes we might inadvertantly
+ * skip here. */
+ if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) {
+ mlog(0, "Skipping delete of %lu because another node "
+ "has done this for us.\n", inode->i_ino);
+ goto bail_unlock;
+ }
+
+ ret = 1;
+bail_unlock:
+ spin_unlock(&oi->ip_lock);
+bail:
+ return ret;
+}
+
+/* Query the cluster to determine whether we should wipe an inode from
+ * disk or not.
+ *
+ * Requires the inode to have the cluster lock. */
+static int ocfs2_query_inode_wipe(struct inode *inode,
+ struct buffer_head *di_bh,
+ int *wipe)
+{
+ int status = 0;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_dinode *di;
+
+ *wipe = 0;
+
+ /* While we were waiting for the cluster lock in
+ * ocfs2_delete_inode, another node might have asked to delete
+ * the inode. Recheck our flags to catch this. */
+ if (!ocfs2_inode_is_valid_to_delete(inode)) {
+ mlog(0, "Skipping delete of %"MLFu64" because flags changed\n",
+ oi->ip_blkno);
+ goto bail;
+ }
+
+ /* Now that we have an up to date inode, we can double check
+ * the link count. */
+ if (inode->i_nlink) {
+ mlog(0, "Skipping delete of %"MLFu64" because nlink = %u\n",
+ oi->ip_blkno, inode->i_nlink);
+ goto bail;
+ }
+
+ /* Do some basic inode verification... */
+ di = (struct ocfs2_dinode *) di_bh->b_data;
+ if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {
+ /* for lack of a better error? */
+ status = -EEXIST;
+ mlog(ML_ERROR,
+ "Inode %"MLFu64" (on-disk %"MLFu64") not orphaned! "
+ "Disk flags 0x%x, inode flags 0x%x\n",
+ oi->ip_blkno, di->i_blkno, di->i_flags, oi->ip_flags);
+ goto bail;
+ }
+
+ /* has someone already deleted us?! baaad... */
+ if (di->i_dtime) {
+ status = -EEXIST;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_request_delete_vote(inode);
+ /* -EBUSY means that other nodes are still using the
+ * inode. We're done here though, so avoid doing anything on
+ * disk and let them worry about deleting it. */
+ if (status == -EBUSY) {
+ status = 0;
+ mlog(0, "Skipping delete of %"MLFu64" because it is in use on"
+ "other nodes\n", oi->ip_blkno);
+ goto bail;
+ }
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ spin_lock(&oi->ip_lock);
+ if (oi->ip_orphaned_slot == OCFS2_INVALID_SLOT) {
+ /* Nobody knew which slot this inode was orphaned
+ * into. This may happen during node death and
+ * recovery knows how to clean it up so we can safely
+ * ignore this inode for now on. */
+ mlog(0, "Nobody knew where inode %"MLFu64" was orphaned!\n",
+ oi->ip_blkno);
+ } else {
+ *wipe = 1;
+
+ mlog(0, "Inode %"MLFu64" is ok to wipe from orphan dir %d\n",
+ oi->ip_blkno, oi->ip_orphaned_slot);
+ }
+ spin_unlock(&oi->ip_lock);
+
+bail:
+ return status;
+}
+
+/* Support function for ocfs2_delete_inode. Will help us keep the
+ * inode data in a consistent state for clear_inode. Always truncates
+ * pages, optionally sync's them first. */
+static void ocfs2_cleanup_delete_inode(struct inode *inode,
+ int sync_data)
+{
+ mlog(0, "Cleanup inode %"MLFu64", sync = %d\n",
+ OCFS2_I(inode)->ip_blkno, sync_data);
+ if (sync_data)
+ write_inode_now(inode, 1);
+ truncate_inode_pages(&inode->i_data, 0);
+}
+
+void ocfs2_delete_inode(struct inode *inode)
+{
+ int wipe, status;
+ sigset_t blocked, oldset;
+ struct buffer_head *di_bh = NULL;
+
+ mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
+
+ if (is_bad_inode(inode)) {
+ mlog(0, "Skipping delete of bad inode\n");
+ goto bail;
+ }
+
+ if (!ocfs2_inode_is_valid_to_delete(inode)) {
+ /* It's probably not necessary to truncate_inode_pages
+ * here but we do it for safety anyway (it will most
+ * likely be a no-op anyway) */
+ ocfs2_cleanup_delete_inode(inode, 0);
+ goto bail;
+ }
+
+ /* We want to block signals in delete_inode as the lock and
+ * messaging paths may return us -ERESTARTSYS. Which would
+ * cause us to exit early, resulting in inodes being orphaned
+ * forever. */
+ sigfillset(&blocked);
+ status = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+ if (status < 0) {
+ mlog_errno(status);
+ ocfs2_cleanup_delete_inode(inode, 1);
+ goto bail;
+ }
+
+ /* Lock down the inode. This gives us an up to date view of
+ * it's metadata (for verification), and allows us to
+ * serialize delete_inode votes.
+ *
+ * Even though we might be doing a truncate, we don't take the
+ * allocation lock here as it won't be needed - nobody will
+ * have the file open.
+ */
+ status = ocfs2_meta_lock(inode, NULL, &di_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ ocfs2_cleanup_delete_inode(inode, 0);
+ goto bail_unblock;
+ }
+
+ /* Query the cluster. This will be the final decision made
+ * before we go ahead and wipe the inode. */
+ status = ocfs2_query_inode_wipe(inode, di_bh, &wipe);
+ if (!wipe || status < 0) {
+ /* Error and inode busy vote both mean we won't be
+ * removing the inode, so they take almost the same
+ * path. */
+ if (status < 0)
+ mlog_errno(status);
+
+ /* Someone in the cluster has voted to not wipe this
+ * inode, or it was never completely orphaned. Write
+ * out the pages and exit now. */
+ ocfs2_cleanup_delete_inode(inode, 1);
+ goto bail_unlock_inode;
+ }
+
+ ocfs2_cleanup_delete_inode(inode, 0);
+
+ status = ocfs2_wipe_inode(inode, di_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail_unlock_inode;
+ }
+
+ /* Mark the inode as successfully deleted. This is important
+ * for ocfs2_clear_inode as it will check this flag and skip
+ * any checkpointing work */
+ OCFS2_I(inode)->ip_flags |= OCFS2_INODE_DELETED;
+
+bail_unlock_inode:
+ ocfs2_meta_unlock(inode, 1);
+ brelse(di_bh);
+bail_unblock:
+ status = sigprocmask(SIG_SETMASK, &oldset, NULL);
+ if (status < 0)
+ mlog_errno(status);
+bail:
+ clear_inode(inode);
+ mlog_exit_void();
+}
+
+void ocfs2_clear_inode(struct inode *inode)
+{
+ int status;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ mlog_entry_void();
+
+ if (!inode)
+ goto bail;
+
+ mlog(0, "Clearing inode: %"MLFu64", nlink = %u\n",
+ OCFS2_I(inode)->ip_blkno, inode->i_nlink);
+
+ mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL,
+ "Inode=%lu\n", inode->i_ino);
+
+ /* Do these before all the other work so that we don't bounce
+ * the vote thread while waiting to destroy the locks. */
+ ocfs2_mark_lockres_freeing(&oi->ip_rw_lockres);
+ ocfs2_mark_lockres_freeing(&oi->ip_meta_lockres);
+ ocfs2_mark_lockres_freeing(&oi->ip_data_lockres);
+
+ /* We very well may get a clear_inode before all an inodes
+ * metadata has hit disk. Of course, we can't drop any cluster
+ * locks until the journal has finished with it. The only
+ * exception here are successfully wiped inodes - their
+ * metadata can now be considered to be part of the system
+ * inodes from which it came. */
+ if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED))
+ ocfs2_checkpoint_inode(inode);
+
+ mlog_bug_on_msg(!list_empty(&oi->ip_io_markers),
+ "Clear inode of %"MLFu64", inode has io markers\n",
+ oi->ip_blkno);
+
+ ocfs2_extent_map_drop(inode, 0);
+ ocfs2_extent_map_init(inode);
+
+ status = ocfs2_drop_inode_locks(inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ ocfs2_lock_res_free(&oi->ip_rw_lockres);
+ ocfs2_lock_res_free(&oi->ip_meta_lockres);
+ ocfs2_lock_res_free(&oi->ip_data_lockres);
+
+ ocfs2_metadata_cache_purge(inode);
+
+ mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached,
+ "Clear inode of %"MLFu64", inode has %u cache items\n",
+ oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached);
+
+ mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),
+ "Clear inode of %"MLFu64", inode has a bad flag\n",
+ oi->ip_blkno);
+
+ mlog_bug_on_msg(spin_is_locked(&oi->ip_lock),
+ "Clear inode of %"MLFu64", inode is locked\n",
+ oi->ip_blkno);
+
+ mlog_bug_on_msg(down_trylock(&oi->ip_io_sem),
+ "Clear inode of %"MLFu64", io_sem is locked\n",
+ oi->ip_blkno);
+ up(&oi->ip_io_sem);
+
+ /*
+ * down_trylock() returns 0, down_write_trylock() returns 1
+ * kernel 1, world 0
+ */
+ mlog_bug_on_msg(!down_write_trylock(&oi->ip_alloc_sem),
+ "Clear inode of %"MLFu64", alloc_sem is locked\n",
+ oi->ip_blkno);
+ up_write(&oi->ip_alloc_sem);
+
+ mlog_bug_on_msg(oi->ip_open_count,
+ "Clear inode of %"MLFu64" has open count %d\n",
+ oi->ip_blkno, oi->ip_open_count);
+ mlog_bug_on_msg(!list_empty(&oi->ip_handle_list),
+ "Clear inode of %"MLFu64" has non empty handle list\n",
+ oi->ip_blkno);
+ mlog_bug_on_msg(oi->ip_handle,
+ "Clear inode of %"MLFu64" has non empty handle pointer\n",
+ oi->ip_blkno);
+
+ /* Clear all other flags. */
+ oi->ip_flags = OCFS2_INODE_CACHE_INLINE;
+ oi->ip_created_trans = 0;
+ oi->ip_last_trans = 0;
+ oi->ip_dir_start_lookup = 0;
+ oi->ip_blkno = 0ULL;
+
+bail:
+ mlog_exit_void();
+}
+
+/* Called under inode_lock, with no more references on the
+ * struct inode, so it's safe here to check the flags field
+ * and to manipulate i_nlink without any other locks. */
+void ocfs2_drop_inode(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ mlog_entry_void();
+
+ mlog(0, "Drop inode %"MLFu64", nlink = %u, ip_flags = 0x%x\n",
+ oi->ip_blkno, inode->i_nlink, oi->ip_flags);
+
+ /* Testing ip_orphaned_slot here wouldn't work because we may
+ * not have gotten a delete_inode vote from any other nodes
+ * yet. */
+ if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) {
+ mlog(0, "Inode was orphaned on another node, clearing nlink.\n");
+ inode->i_nlink = 0;
+ }
+
+ generic_drop_inode(inode);
+
+ mlog_exit_void();
+}
+
+/*
+ * TODO: this should probably be merged into ocfs2_get_block
+ *
+ * However, you now need to pay attention to the cont_prepare_write()
+ * stuff in ocfs2_get_block (that is, ocfs2_get_block pretty much
+ * expects never to extend).
+ */
+struct buffer_head *ocfs2_bread(struct inode *inode,
+ int block, int *err, int reada)
+{
+ struct buffer_head *bh = NULL;
+ int tmperr;
+ u64 p_blkno;
+ int readflags = OCFS2_BH_CACHED;
+
+#if 0
+ /* only turn this on if we know we can deal with read_block
+ * returning nothing */
+ if (reada)
+ readflags |= OCFS2_BH_READAHEAD;
+#endif
+
+ if (((u64)block << inode->i_sb->s_blocksize_bits) >=
+ i_size_read(inode)) {
+ BUG_ON(!reada);
+ return NULL;
+ }
+
+ tmperr = ocfs2_extent_map_get_blocks(inode, block, 1,
+ &p_blkno, NULL);
+ if (tmperr < 0) {
+ mlog_errno(tmperr);
+ goto fail;
+ }
+
+ tmperr = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, &bh,
+ readflags, inode);
+ if (tmperr < 0)
+ goto fail;
+
+ tmperr = 0;
+
+ *err = 0;
+ return bh;
+
+fail:
+ if (bh) {
+ brelse(bh);
+ bh = NULL;
+ }
+ *err = -EIO;
+ return NULL;
+}
+
+/*
+ * This is called from our getattr.
+ */
+int ocfs2_inode_revalidate(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ int status = 0;
+
+ mlog_entry("(inode = 0x%p, ino = %"MLFu64")\n", inode,
+ inode ? OCFS2_I(inode)->ip_blkno : 0ULL);
+
+ if (!inode) {
+ mlog(0, "eep, no inode!\n");
+ status = -ENOENT;
+ goto bail;
+ }
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) {
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ mlog(0, "inode deleted!\n");
+ status = -ENOENT;
+ goto bail;
+ }
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ /* Let ocfs2_meta_lock do the work of updating our struct
+ * inode for us. */
+ status = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_meta_unlock(inode, 0);
+bail:
+ mlog_exit(status);
+
+ return status;
+}
+
+/*
+ * Updates a disk inode from a
+ * struct inode.
+ * Only takes ip_lock.
+ */
+int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *bh)
+{
+ int status;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
+
+ mlog_entry("(inode %"MLFu64")\n", OCFS2_I(inode)->ip_blkno);
+
+ status = ocfs2_journal_access(handle, inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ fe->i_size = cpu_to_le64(i_size_read(inode));
+ fe->i_links_count = cpu_to_le16(inode->i_nlink);
+ fe->i_uid = cpu_to_le32(inode->i_uid);
+ fe->i_gid = cpu_to_le32(inode->i_gid);
+ fe->i_mode = cpu_to_le16(inode->i_mode);
+ fe->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
+ fe->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
+ fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+ fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+ fe->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
+ fe->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+
+ status = ocfs2_journal_dirty(handle, bh);
+ if (status < 0)
+ mlog_errno(status);
+
+ status = 0;
+leave:
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ *
+ * Updates a struct inode from a disk inode.
+ * does no i/o, only takes ip_lock.
+ */
+void ocfs2_refresh_inode(struct inode *inode,
+ struct ocfs2_dinode *fe)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+
+ OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+ i_size_write(inode, le64_to_cpu(fe->i_size));
+ inode->i_nlink = le16_to_cpu(fe->i_links_count);
+ inode->i_uid = le32_to_cpu(fe->i_uid);
+ inode->i_gid = le32_to_cpu(fe->i_gid);
+ inode->i_mode = le16_to_cpu(fe->i_mode);
+ inode->i_blksize = (u32) osb->s_clustersize;
+ if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)
+ inode->i_blocks = 0;
+ else
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(i_size_read(inode));
+ inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
+ inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
+ inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
+ inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec);
+ inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime);
+ inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec);
+
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+}
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
new file mode 100644
index 000000000000..9b0177433653
--- /dev/null
+++ b/fs/ocfs2/inode.h
@@ -0,0 +1,145 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * inode.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_INODE_H
+#define OCFS2_INODE_H
+
+/* OCFS2 Inode Private Data */
+struct ocfs2_inode_info
+{
+ u64 ip_blkno;
+
+ struct ocfs2_lock_res ip_rw_lockres;
+ struct ocfs2_lock_res ip_meta_lockres;
+ struct ocfs2_lock_res ip_data_lockres;
+
+ /* protects allocation changes on this inode. */
+ struct rw_semaphore ip_alloc_sem;
+
+ /* These fields are protected by ip_lock */
+ spinlock_t ip_lock;
+ u32 ip_open_count;
+ u32 ip_clusters;
+ struct ocfs2_extent_map ip_map;
+ struct list_head ip_io_markers;
+ int ip_orphaned_slot;
+
+ struct semaphore ip_io_sem;
+
+ /* Used by the journalling code to attach an inode to a
+ * handle. These are protected by ip_io_sem in order to lock
+ * out other I/O to the inode until we either commit or
+ * abort. */
+ struct list_head ip_handle_list;
+ struct ocfs2_journal_handle *ip_handle;
+
+ u32 ip_flags; /* see below */
+
+ /* protected by recovery_lock. */
+ struct inode *ip_next_orphan;
+
+ u32 ip_dir_start_lookup;
+
+ /* next two are protected by trans_inc_lock */
+ /* which transaction were we created on? Zero if none. */
+ unsigned long ip_created_trans;
+ /* last transaction we were a part of. */
+ unsigned long ip_last_trans;
+
+ struct ocfs2_caching_info ip_metadata_cache;
+
+ struct inode vfs_inode;
+};
+
+/*
+ * Flags for the ip_flags field
+ */
+/* System file inodes */
+#define OCFS2_INODE_SYSTEM_FILE 0x00000001
+#define OCFS2_INODE_JOURNAL 0x00000002
+#define OCFS2_INODE_BITMAP 0x00000004
+/* This inode has been wiped from disk */
+#define OCFS2_INODE_DELETED 0x00000008
+/* Another node is deleting, so our delete is a nop */
+#define OCFS2_INODE_SKIP_DELETE 0x00000010
+/* Has the inode been orphaned on another node?
+ *
+ * This hints to ocfs2_drop_inode that it should clear i_nlink before
+ * continuing.
+ *
+ * We *only* set this on unlink vote from another node. If the inode
+ * was locally orphaned, then we're sure of the state and don't need
+ * to twiddle i_nlink later - it's either zero or not depending on
+ * whether our unlink succeeded. Otherwise we got this from a node
+ * whose intention was to orphan the inode, however he may have
+ * crashed, failed etc, so we let ocfs2_drop_inode zero the value and
+ * rely on ocfs2_delete_inode to sort things out under the proper
+ * cluster locks.
+ */
+#define OCFS2_INODE_MAYBE_ORPHANED 0x00000020
+/* Does someone have the file open O_DIRECT */
+#define OCFS2_INODE_OPEN_DIRECT 0x00000040
+/* Indicates that the metadata cache should be used as an array. */
+#define OCFS2_INODE_CACHE_INLINE 0x00000080
+
+static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode)
+{
+ return container_of(inode, struct ocfs2_inode_info, vfs_inode);
+}
+
+#define INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags & OCFS2_INODE_JOURNAL)
+#define SET_INODE_JOURNAL(i) (OCFS2_I(i)->ip_flags |= OCFS2_INODE_JOURNAL)
+
+extern kmem_cache_t *ocfs2_inode_cache;
+
+extern struct address_space_operations ocfs2_aops;
+
+struct buffer_head *ocfs2_bread(struct inode *inode, int block,
+ int *err, int reada);
+void ocfs2_clear_inode(struct inode *inode);
+void ocfs2_delete_inode(struct inode *inode);
+void ocfs2_drop_inode(struct inode *inode);
+struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 feoff);
+struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb,
+ u64 blkno,
+ int delete_vote);
+int ocfs2_inode_init_private(struct inode *inode);
+int ocfs2_inode_revalidate(struct dentry *dentry);
+int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
+ int create_ino);
+void ocfs2_read_inode(struct inode *inode);
+void ocfs2_read_inode2(struct inode *inode, void *opaque);
+ssize_t ocfs2_rw_direct(int rw, struct file *filp, char *buf,
+ size_t size, loff_t *offp);
+void ocfs2_sync_blockdev(struct super_block *sb);
+void ocfs2_refresh_inode(struct inode *inode,
+ struct ocfs2_dinode *fe);
+int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *bh);
+int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
+int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
+
+#endif /* OCFS2_INODE_H */
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
new file mode 100644
index 000000000000..303c8d96457f
--- /dev/null
+++ b/fs/ocfs2/journal.c
@@ -0,0 +1,1652 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * journal.c
+ *
+ * Defines functions of journalling api
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/kthread.h>
+
+#define MLOG_MASK_PREFIX ML_JOURNAL
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "journal.h"
+#include "localalloc.h"
+#include "namei.h"
+#include "slot_map.h"
+#include "super.h"
+#include "vote.h"
+#include "sysfile.h"
+
+#include "buffer_head_io.h"
+
+spinlock_t trans_inc_lock = SPIN_LOCK_UNLOCKED;
+
+static int ocfs2_force_read_journal(struct inode *inode);
+static int ocfs2_recover_node(struct ocfs2_super *osb,
+ int node_num);
+static int __ocfs2_recovery_thread(void *arg);
+static int ocfs2_commit_cache(struct ocfs2_super *osb);
+static int ocfs2_wait_on_mount(struct ocfs2_super *osb);
+static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal,
+ struct ocfs2_journal_handle *handle);
+static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle);
+static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
+ int dirty);
+static int ocfs2_trylock_journal(struct ocfs2_super *osb,
+ int slot_num);
+static int ocfs2_recover_orphans(struct ocfs2_super *osb,
+ int slot);
+static int ocfs2_commit_thread(void *arg);
+
+static int ocfs2_commit_cache(struct ocfs2_super *osb)
+{
+ int status = 0;
+ unsigned int flushed;
+ unsigned long old_id;
+ struct ocfs2_journal *journal = NULL;
+
+ mlog_entry_void();
+
+ journal = osb->journal;
+
+ /* Flush all pending commits and checkpoint the journal. */
+ down_write(&journal->j_trans_barrier);
+
+ if (atomic_read(&journal->j_num_trans) == 0) {
+ up_write(&journal->j_trans_barrier);
+ mlog(0, "No transactions for me to flush!\n");
+ goto finally;
+ }
+
+ journal_lock_updates(journal->j_journal);
+ status = journal_flush(journal->j_journal);
+ journal_unlock_updates(journal->j_journal);
+ if (status < 0) {
+ up_write(&journal->j_trans_barrier);
+ mlog_errno(status);
+ goto finally;
+ }
+
+ old_id = ocfs2_inc_trans_id(journal);
+
+ flushed = atomic_read(&journal->j_num_trans);
+ atomic_set(&journal->j_num_trans, 0);
+ up_write(&journal->j_trans_barrier);
+
+ mlog(0, "commit_thread: flushed transaction %lu (%u handles)\n",
+ journal->j_trans_id, flushed);
+
+ ocfs2_kick_vote_thread(osb);
+ wake_up(&journal->j_checkpointed);
+finally:
+ mlog_exit(status);
+ return status;
+}
+
+struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb)
+{
+ struct ocfs2_journal_handle *retval = NULL;
+
+ retval = kcalloc(1, sizeof(*retval), GFP_KERNEL);
+ if (!retval) {
+ mlog(ML_ERROR, "Failed to allocate memory for journal "
+ "handle!\n");
+ return NULL;
+ }
+
+ retval->max_buffs = 0;
+ retval->num_locks = 0;
+ retval->k_handle = NULL;
+
+ INIT_LIST_HEAD(&retval->locks);
+ INIT_LIST_HEAD(&retval->inode_list);
+ retval->journal = osb->journal;
+
+ return retval;
+}
+
+/* pass it NULL and it will allocate a new handle object for you. If
+ * you pass it a handle however, it may still return error, in which
+ * case it has free'd the passed handle for you. */
+struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ int max_buffs)
+{
+ int ret;
+ journal_t *journal = osb->journal->j_journal;
+
+ mlog_entry("(max_buffs = %d)\n", max_buffs);
+
+ if (!osb || !osb->journal->j_journal)
+ BUG();
+
+ if (ocfs2_is_hard_readonly(osb)) {
+ ret = -EROFS;
+ goto done_free;
+ }
+
+ BUG_ON(osb->journal->j_state == OCFS2_JOURNAL_FREE);
+ BUG_ON(max_buffs <= 0);
+
+ /* JBD might support this, but our journalling code doesn't yet. */
+ if (journal_current_handle()) {
+ mlog(ML_ERROR, "Recursive transaction attempted!\n");
+ BUG();
+ }
+
+ if (!handle)
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ ret = -ENOMEM;
+ mlog(ML_ERROR, "Failed to allocate memory for journal "
+ "handle!\n");
+ goto done_free;
+ }
+
+ handle->max_buffs = max_buffs;
+
+ down_read(&osb->journal->j_trans_barrier);
+
+ /* actually start the transaction now */
+ handle->k_handle = journal_start(journal, max_buffs);
+ if (IS_ERR(handle->k_handle)) {
+ up_read(&osb->journal->j_trans_barrier);
+
+ ret = PTR_ERR(handle->k_handle);
+ handle->k_handle = NULL;
+ mlog_errno(ret);
+
+ if (is_journal_aborted(journal)) {
+ ocfs2_abort(osb->sb, "Detected aborted journal");
+ ret = -EROFS;
+ }
+ goto done_free;
+ }
+
+ atomic_inc(&(osb->journal->j_num_trans));
+ handle->flags |= OCFS2_HANDLE_STARTED;
+
+ mlog_exit_ptr(handle);
+ return handle;
+
+done_free:
+ if (handle)
+ ocfs2_commit_unstarted_handle(handle); /* will kfree handle */
+
+ mlog_exit(ret);
+ return ERR_PTR(ret);
+}
+
+void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle,
+ struct inode *inode)
+{
+ BUG_ON(!handle);
+ BUG_ON(!inode);
+
+ atomic_inc(&inode->i_count);
+
+ /* we're obviously changing it... */
+ mutex_lock(&inode->i_mutex);
+
+ /* sanity check */
+ BUG_ON(OCFS2_I(inode)->ip_handle);
+ BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list));
+
+ OCFS2_I(inode)->ip_handle = handle;
+ list_del(&(OCFS2_I(inode)->ip_handle_list));
+ list_add_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list));
+}
+
+static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle)
+{
+ struct list_head *p, *n;
+ struct inode *inode;
+ struct ocfs2_inode_info *oi;
+
+ list_for_each_safe(p, n, &handle->inode_list) {
+ oi = list_entry(p, struct ocfs2_inode_info,
+ ip_handle_list);
+ inode = &oi->vfs_inode;
+
+ OCFS2_I(inode)->ip_handle = NULL;
+ list_del_init(&OCFS2_I(inode)->ip_handle_list);
+
+ mutex_unlock(&inode->i_mutex);
+ iput(inode);
+ }
+}
+
+/* This is trivial so we do it out of the main commit
+ * paths. Beware, it can be called from start_trans too! */
+static void ocfs2_commit_unstarted_handle(struct ocfs2_journal_handle *handle)
+{
+ mlog_entry_void();
+
+ BUG_ON(handle->flags & OCFS2_HANDLE_STARTED);
+
+ ocfs2_handle_unlock_inodes(handle);
+ /* You are allowed to add journal locks before the transaction
+ * has started. */
+ ocfs2_handle_cleanup_locks(handle->journal, handle);
+
+ kfree(handle);
+
+ mlog_exit_void();
+}
+
+void ocfs2_commit_trans(struct ocfs2_journal_handle *handle)
+{
+ handle_t *jbd_handle;
+ int retval;
+ struct ocfs2_journal *journal = handle->journal;
+
+ mlog_entry_void();
+
+ BUG_ON(!handle);
+
+ if (!(handle->flags & OCFS2_HANDLE_STARTED)) {
+ ocfs2_commit_unstarted_handle(handle);
+ mlog_exit_void();
+ return;
+ }
+
+ /* release inode semaphores we took during this transaction */
+ ocfs2_handle_unlock_inodes(handle);
+
+ /* ocfs2_extend_trans may have had to call journal_restart
+ * which will always commit the transaction, but may return
+ * error for any number of reasons. If this is the case, we
+ * clear k_handle as it's not valid any more. */
+ if (handle->k_handle) {
+ jbd_handle = handle->k_handle;
+
+ if (handle->flags & OCFS2_HANDLE_SYNC)
+ jbd_handle->h_sync = 1;
+ else
+ jbd_handle->h_sync = 0;
+
+ /* actually stop the transaction. if we've set h_sync,
+ * it'll have been committed when we return */
+ retval = journal_stop(jbd_handle);
+ if (retval < 0) {
+ mlog_errno(retval);
+ mlog(ML_ERROR, "Could not commit transaction\n");
+ BUG();
+ }
+
+ handle->k_handle = NULL; /* it's been free'd in journal_stop */
+ }
+
+ ocfs2_handle_cleanup_locks(journal, handle);
+
+ up_read(&journal->j_trans_barrier);
+
+ kfree(handle);
+ mlog_exit_void();
+}
+
+/*
+ * 'nblocks' is what you want to add to the current
+ * transaction. extend_trans will either extend the current handle by
+ * nblocks, or commit it and start a new one with nblocks credits.
+ *
+ * WARNING: This will not release any semaphores or disk locks taken
+ * during the transaction, so make sure they were taken *before*
+ * start_trans or we'll have ordering deadlocks.
+ *
+ * WARNING2: Note that we do *not* drop j_trans_barrier here. This is
+ * good because transaction ids haven't yet been recorded on the
+ * cluster locks associated with this handle.
+ */
+int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
+ int nblocks)
+{
+ int status;
+
+ BUG_ON(!handle);
+ BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
+ BUG_ON(!nblocks);
+
+ mlog_entry_void();
+
+ mlog(0, "Trying to extend transaction by %d blocks\n", nblocks);
+
+ status = journal_extend(handle->k_handle, nblocks);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (status > 0) {
+ mlog(0, "journal_extend failed, trying journal_restart\n");
+ status = journal_restart(handle->k_handle, nblocks);
+ if (status < 0) {
+ handle->k_handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+ handle->max_buffs = nblocks;
+ } else
+ handle->max_buffs += nblocks;
+
+ status = 0;
+bail:
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *bh,
+ int type)
+{
+ int status;
+
+ BUG_ON(!inode);
+ BUG_ON(!handle);
+ BUG_ON(!bh);
+ BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
+
+ mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %hu\n",
+ (unsigned long long)bh->b_blocknr, type,
+ (type == OCFS2_JOURNAL_ACCESS_CREATE) ?
+ "OCFS2_JOURNAL_ACCESS_CREATE" :
+ "OCFS2_JOURNAL_ACCESS_WRITE",
+ bh->b_size);
+
+ /* we can safely remove this assertion after testing. */
+ if (!buffer_uptodate(bh)) {
+ mlog(ML_ERROR, "giving me a buffer that's not uptodate!\n");
+ mlog(ML_ERROR, "b_blocknr=%llu\n",
+ (unsigned long long)bh->b_blocknr);
+ BUG();
+ }
+
+ /* Set the current transaction information on the inode so
+ * that the locking code knows whether it can drop it's locks
+ * on this inode or not. We're protected from the commit
+ * thread updating the current transaction id until
+ * ocfs2_commit_trans() because ocfs2_start_trans() took
+ * j_trans_barrier for us. */
+ ocfs2_set_inode_lock_trans(OCFS2_SB(inode->i_sb)->journal, inode);
+
+ down(&OCFS2_I(inode)->ip_io_sem);
+ switch (type) {
+ case OCFS2_JOURNAL_ACCESS_CREATE:
+ case OCFS2_JOURNAL_ACCESS_WRITE:
+ status = journal_get_write_access(handle->k_handle, bh);
+ break;
+
+ case OCFS2_JOURNAL_ACCESS_UNDO:
+ status = journal_get_undo_access(handle->k_handle, bh);
+ break;
+
+ default:
+ status = -EINVAL;
+ mlog(ML_ERROR, "Uknown access type!\n");
+ }
+ up(&OCFS2_I(inode)->ip_io_sem);
+
+ if (status < 0)
+ mlog(ML_ERROR, "Error %d getting %d access to buffer!\n",
+ status, type);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle,
+ struct buffer_head *bh)
+{
+ int status;
+
+ BUG_ON(!(handle->flags & OCFS2_HANDLE_STARTED));
+
+ mlog_entry("(bh->b_blocknr=%llu)\n",
+ (unsigned long long)bh->b_blocknr);
+
+ status = journal_dirty_metadata(handle->k_handle, bh);
+ if (status < 0)
+ mlog(ML_ERROR, "Could not dirty metadata buffer. "
+ "(bh->b_blocknr=%llu)\n",
+ (unsigned long long)bh->b_blocknr);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_journal_dirty_data(handle_t *handle,
+ struct buffer_head *bh)
+{
+ int err = journal_dirty_data(handle, bh);
+ if (err)
+ mlog_errno(err);
+ /* TODO: When we can handle it, abort the handle and go RO on
+ * error here. */
+
+ return err;
+}
+
+/* We always assume you're adding a metadata lock at level 'ex' */
+int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle,
+ struct inode *inode)
+{
+ int status;
+ struct ocfs2_journal_lock *lock;
+
+ BUG_ON(!inode);
+
+ lock = kmem_cache_alloc(ocfs2_lock_cache, GFP_NOFS);
+ if (!lock) {
+ status = -ENOMEM;
+ mlog_errno(-ENOMEM);
+ goto bail;
+ }
+
+ if (!igrab(inode))
+ BUG();
+ lock->jl_inode = inode;
+
+ list_add_tail(&(lock->jl_lock_list), &(handle->locks));
+ handle->num_locks++;
+
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static void ocfs2_handle_cleanup_locks(struct ocfs2_journal *journal,
+ struct ocfs2_journal_handle *handle)
+{
+ struct list_head *p, *n;
+ struct ocfs2_journal_lock *lock;
+ struct inode *inode;
+
+ list_for_each_safe(p, n, &(handle->locks)) {
+ lock = list_entry(p, struct ocfs2_journal_lock,
+ jl_lock_list);
+ list_del(&lock->jl_lock_list);
+ handle->num_locks--;
+
+ inode = lock->jl_inode;
+ ocfs2_meta_unlock(inode, 1);
+ if (atomic_read(&inode->i_count) == 1)
+ mlog(ML_ERROR,
+ "Inode %"MLFu64", I'm doing a last iput for!",
+ OCFS2_I(inode)->ip_blkno);
+ iput(inode);
+ kmem_cache_free(ocfs2_lock_cache, lock);
+ }
+}
+
+#define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * 5)
+
+void ocfs2_set_journal_params(struct ocfs2_super *osb)
+{
+ journal_t *journal = osb->journal->j_journal;
+
+ spin_lock(&journal->j_state_lock);
+ journal->j_commit_interval = OCFS2_DEFAULT_COMMIT_INTERVAL;
+ if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER)
+ journal->j_flags |= JFS_BARRIER;
+ else
+ journal->j_flags &= ~JFS_BARRIER;
+ spin_unlock(&journal->j_state_lock);
+}
+
+int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty)
+{
+ int status = -1;
+ struct inode *inode = NULL; /* the journal inode */
+ journal_t *j_journal = NULL;
+ struct ocfs2_dinode *di = NULL;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_super *osb;
+ int meta_lock = 0;
+
+ mlog_entry_void();
+
+ BUG_ON(!journal);
+
+ osb = journal->j_osb;
+
+ /* already have the inode for our journal */
+ inode = ocfs2_get_system_file_inode(osb, JOURNAL_SYSTEM_INODE,
+ osb->slot_num);
+ if (inode == NULL) {
+ status = -EACCES;
+ mlog_errno(status);
+ goto done;
+ }
+ if (is_bad_inode(inode)) {
+ mlog(ML_ERROR, "access error (bad inode)\n");
+ iput(inode);
+ inode = NULL;
+ status = -EACCES;
+ goto done;
+ }
+
+ SET_INODE_JOURNAL(inode);
+ OCFS2_I(inode)->ip_open_count++;
+
+ status = ocfs2_meta_lock(inode, NULL, &bh, 1);
+ if (status < 0) {
+ if (status != -ERESTARTSYS)
+ mlog(ML_ERROR, "Could not get lock on journal!\n");
+ goto done;
+ }
+
+ meta_lock = 1;
+ di = (struct ocfs2_dinode *)bh->b_data;
+
+ if (inode->i_size < OCFS2_MIN_JOURNAL_SIZE) {
+ mlog(ML_ERROR, "Journal file size (%lld) is too small!\n",
+ inode->i_size);
+ status = -EINVAL;
+ goto done;
+ }
+
+ mlog(0, "inode->i_size = %lld\n", inode->i_size);
+ mlog(0, "inode->i_blocks = %lu\n", inode->i_blocks);
+ mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters);
+
+ /* call the kernels journal init function now */
+ j_journal = journal_init_inode(inode);
+ if (j_journal == NULL) {
+ mlog(ML_ERROR, "Linux journal layer error\n");
+ status = -EINVAL;
+ goto done;
+ }
+
+ mlog(0, "Returned from journal_init_inode\n");
+ mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen);
+
+ *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) &
+ OCFS2_JOURNAL_DIRTY_FL);
+
+ journal->j_journal = j_journal;
+ journal->j_inode = inode;
+ journal->j_bh = bh;
+
+ ocfs2_set_journal_params(osb);
+
+ journal->j_state = OCFS2_JOURNAL_LOADED;
+
+ status = 0;
+done:
+ if (status < 0) {
+ if (meta_lock)
+ ocfs2_meta_unlock(inode, 1);
+ if (bh != NULL)
+ brelse(bh);
+ if (inode) {
+ OCFS2_I(inode)->ip_open_count--;
+ iput(inode);
+ }
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,
+ int dirty)
+{
+ int status;
+ unsigned int flags;
+ struct ocfs2_journal *journal = osb->journal;
+ struct buffer_head *bh = journal->j_bh;
+ struct ocfs2_dinode *fe;
+
+ mlog_entry_void();
+
+ fe = (struct ocfs2_dinode *)bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ /* This is called from startup/shutdown which will
+ * handle the errors in a specific manner, so no need
+ * to call ocfs2_error() here. */
+ mlog(ML_ERROR, "Journal dinode %"MLFu64" has invalid "
+ "signature: %.*s", fe->i_blkno, 7, fe->i_signature);
+ status = -EIO;
+ goto out;
+ }
+
+ flags = le32_to_cpu(fe->id1.journal1.ij_flags);
+ if (dirty)
+ flags |= OCFS2_JOURNAL_DIRTY_FL;
+ else
+ flags &= ~OCFS2_JOURNAL_DIRTY_FL;
+ fe->id1.journal1.ij_flags = cpu_to_le32(flags);
+
+ status = ocfs2_write_block(osb, bh, journal->j_inode);
+ if (status < 0)
+ mlog_errno(status);
+
+out:
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * If the journal has been kmalloc'd it needs to be freed after this
+ * call.
+ */
+void ocfs2_journal_shutdown(struct ocfs2_super *osb)
+{
+ struct ocfs2_journal *journal = NULL;
+ int status = 0;
+ struct inode *inode = NULL;
+ int num_running_trans = 0;
+
+ mlog_entry_void();
+
+ if (!osb)
+ BUG();
+
+ journal = osb->journal;
+ if (!journal)
+ goto done;
+
+ inode = journal->j_inode;
+
+ if (journal->j_state != OCFS2_JOURNAL_LOADED)
+ goto done;
+
+ /* need to inc inode use count as journal_destroy will iput. */
+ if (!igrab(inode))
+ BUG();
+
+ num_running_trans = atomic_read(&(osb->journal->j_num_trans));
+ if (num_running_trans > 0)
+ mlog(0, "Shutting down journal: must wait on %d "
+ "running transactions!\n",
+ num_running_trans);
+
+ /* Do a commit_cache here. It will flush our journal, *and*
+ * release any locks that are still held.
+ * set the SHUTDOWN flag and release the trans lock.
+ * the commit thread will take the trans lock for us below. */
+ journal->j_state = OCFS2_JOURNAL_IN_SHUTDOWN;
+
+ /* The OCFS2_JOURNAL_IN_SHUTDOWN will signal to commit_cache to not
+ * drop the trans_lock (which we want to hold until we
+ * completely destroy the journal. */
+ if (osb->commit_task) {
+ /* Wait for the commit thread */
+ mlog(0, "Waiting for ocfs2commit to exit....\n");
+ kthread_stop(osb->commit_task);
+ osb->commit_task = NULL;
+ }
+
+ BUG_ON(atomic_read(&(osb->journal->j_num_trans)) != 0);
+
+ status = ocfs2_journal_toggle_dirty(osb, 0);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* Shutdown the kernel journal system */
+ journal_destroy(journal->j_journal);
+
+ OCFS2_I(inode)->ip_open_count--;
+
+ /* unlock our journal */
+ ocfs2_meta_unlock(inode, 1);
+
+ brelse(journal->j_bh);
+ journal->j_bh = NULL;
+
+ journal->j_state = OCFS2_JOURNAL_FREE;
+
+// up_write(&journal->j_trans_barrier);
+done:
+ if (inode)
+ iput(inode);
+ mlog_exit_void();
+}
+
+static void ocfs2_clear_journal_error(struct super_block *sb,
+ journal_t *journal,
+ int slot)
+{
+ int olderr;
+
+ olderr = journal_errno(journal);
+ if (olderr) {
+ mlog(ML_ERROR, "File system error %d recorded in "
+ "journal %u.\n", olderr, slot);
+ mlog(ML_ERROR, "File system on device %s needs checking.\n",
+ sb->s_id);
+
+ journal_ack_err(journal);
+ journal_clear_err(journal);
+ }
+}
+
+int ocfs2_journal_load(struct ocfs2_journal *journal)
+{
+ int status = 0;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ if (!journal)
+ BUG();
+
+ osb = journal->j_osb;
+
+ status = journal_load(journal->j_journal);
+ if (status < 0) {
+ mlog(ML_ERROR, "Failed to load journal!\n");
+ goto done;
+ }
+
+ ocfs2_clear_journal_error(osb->sb, journal->j_journal, osb->slot_num);
+
+ status = ocfs2_journal_toggle_dirty(osb, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto done;
+ }
+
+ /* Launch the commit thread */
+ osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt-%d",
+ osb->osb_id);
+ if (IS_ERR(osb->commit_task)) {
+ status = PTR_ERR(osb->commit_task);
+ osb->commit_task = NULL;
+ mlog(ML_ERROR, "unable to launch ocfs2commit thread, error=%d",
+ status);
+ goto done;
+ }
+
+done:
+ mlog_exit(status);
+ return status;
+}
+
+
+/* 'full' flag tells us whether we clear out all blocks or if we just
+ * mark the journal clean */
+int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full)
+{
+ int status;
+
+ mlog_entry_void();
+
+ if (!journal)
+ BUG();
+
+ status = journal_wipe(journal->j_journal, full);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_journal_toggle_dirty(journal->j_osb, 0);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * JBD Might read a cached version of another nodes journal file. We
+ * don't want this as this file changes often and we get no
+ * notification on those changes. The only way to be sure that we've
+ * got the most up to date version of those blocks then is to force
+ * read them off disk. Just searching through the buffer cache won't
+ * work as there may be pages backing this file which are still marked
+ * up to date. We know things can't change on this file underneath us
+ * as we have the lock by now :)
+ */
+static int ocfs2_force_read_journal(struct inode *inode)
+{
+ int status = 0;
+ int i, p_blocks;
+ u64 v_blkno, p_blkno;
+#define CONCURRENT_JOURNAL_FILL 32
+ struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL];
+
+ mlog_entry_void();
+
+ BUG_ON(inode->i_blocks !=
+ ocfs2_align_bytes_to_sectors(i_size_read(inode)));
+
+ memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL);
+
+ mlog(0, "Force reading %lu blocks\n",
+ (inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9)));
+
+ v_blkno = 0;
+ while (v_blkno <
+ (inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9))) {
+
+ status = ocfs2_extent_map_get_blocks(inode, v_blkno,
+ 1, &p_blkno,
+ &p_blocks);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (p_blocks > CONCURRENT_JOURNAL_FILL)
+ p_blocks = CONCURRENT_JOURNAL_FILL;
+
+ status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb),
+ p_blkno, p_blocks, bhs, 0,
+ inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ for(i = 0; i < p_blocks; i++) {
+ brelse(bhs[i]);
+ bhs[i] = NULL;
+ }
+
+ v_blkno += p_blocks;
+ }
+
+bail:
+ for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++)
+ if (bhs[i])
+ brelse(bhs[i]);
+ mlog_exit(status);
+ return status;
+}
+
+struct ocfs2_la_recovery_item {
+ struct list_head lri_list;
+ int lri_slot;
+ struct ocfs2_dinode *lri_la_dinode;
+ struct ocfs2_dinode *lri_tl_dinode;
+};
+
+/* Does the second half of the recovery process. By this point, the
+ * node is marked clean and can actually be considered recovered,
+ * hence it's no longer in the recovery map, but there's still some
+ * cleanup we can do which shouldn't happen within the recovery thread
+ * as locking in that context becomes very difficult if we are to take
+ * recovering nodes into account.
+ *
+ * NOTE: This function can and will sleep on recovery of other nodes
+ * during cluster locking, just like any other ocfs2 process.
+ */
+void ocfs2_complete_recovery(void *data)
+{
+ int ret;
+ struct ocfs2_super *osb = data;
+ struct ocfs2_journal *journal = osb->journal;
+ struct ocfs2_dinode *la_dinode, *tl_dinode;
+ struct ocfs2_la_recovery_item *item;
+ struct list_head *p, *n;
+ LIST_HEAD(tmp_la_list);
+
+ mlog_entry_void();
+
+ mlog(0, "completing recovery from keventd\n");
+
+ spin_lock(&journal->j_lock);
+ list_splice_init(&journal->j_la_cleanups, &tmp_la_list);
+ spin_unlock(&journal->j_lock);
+
+ list_for_each_safe(p, n, &tmp_la_list) {
+ item = list_entry(p, struct ocfs2_la_recovery_item, lri_list);
+ list_del_init(&item->lri_list);
+
+ mlog(0, "Complete recovery for slot %d\n", item->lri_slot);
+
+ la_dinode = item->lri_la_dinode;
+ if (la_dinode) {
+ mlog(0, "Clean up local alloc %"MLFu64"\n",
+ la_dinode->i_blkno);
+
+ ret = ocfs2_complete_local_alloc_recovery(osb,
+ la_dinode);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ kfree(la_dinode);
+ }
+
+ tl_dinode = item->lri_tl_dinode;
+ if (tl_dinode) {
+ mlog(0, "Clean up truncate log %"MLFu64"\n",
+ tl_dinode->i_blkno);
+
+ ret = ocfs2_complete_truncate_log_recovery(osb,
+ tl_dinode);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ kfree(tl_dinode);
+ }
+
+ ret = ocfs2_recover_orphans(osb, item->lri_slot);
+ if (ret < 0)
+ mlog_errno(ret);
+
+ kfree(item);
+ }
+
+ mlog(0, "Recovery completion\n");
+ mlog_exit_void();
+}
+
+/* NOTE: This function always eats your references to la_dinode and
+ * tl_dinode, either manually on error, or by passing them to
+ * ocfs2_complete_recovery */
+static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal,
+ int slot_num,
+ struct ocfs2_dinode *la_dinode,
+ struct ocfs2_dinode *tl_dinode)
+{
+ struct ocfs2_la_recovery_item *item;
+
+ item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_KERNEL);
+ if (!item) {
+ /* Though we wish to avoid it, we are in fact safe in
+ * skipping local alloc cleanup as fsck.ocfs2 is more
+ * than capable of reclaiming unused space. */
+ if (la_dinode)
+ kfree(la_dinode);
+
+ if (tl_dinode)
+ kfree(tl_dinode);
+
+ mlog_errno(-ENOMEM);
+ return;
+ }
+
+ INIT_LIST_HEAD(&item->lri_list);
+ item->lri_la_dinode = la_dinode;
+ item->lri_slot = slot_num;
+ item->lri_tl_dinode = tl_dinode;
+
+ spin_lock(&journal->j_lock);
+ list_add_tail(&item->lri_list, &journal->j_la_cleanups);
+ queue_work(ocfs2_wq, &journal->j_recovery_work);
+ spin_unlock(&journal->j_lock);
+}
+
+/* Called by the mount code to queue recovery the last part of
+ * recovery for it's own slot. */
+void ocfs2_complete_mount_recovery(struct ocfs2_super *osb)
+{
+ struct ocfs2_journal *journal = osb->journal;
+
+ if (osb->dirty) {
+ /* No need to queue up our truncate_log as regular
+ * cleanup will catch that. */
+ ocfs2_queue_recovery_completion(journal,
+ osb->slot_num,
+ osb->local_alloc_copy,
+ NULL);
+ ocfs2_schedule_truncate_log_flush(osb, 0);
+
+ osb->local_alloc_copy = NULL;
+ osb->dirty = 0;
+ }
+}
+
+static int __ocfs2_recovery_thread(void *arg)
+{
+ int status, node_num;
+ struct ocfs2_super *osb = arg;
+
+ mlog_entry_void();
+
+ status = ocfs2_wait_on_mount(osb);
+ if (status < 0) {
+ goto bail;
+ }
+
+restart:
+ status = ocfs2_super_lock(osb, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ while(!ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
+ node_num = ocfs2_node_map_first_set_bit(osb,
+ &osb->recovery_map);
+ if (node_num == O2NM_INVALID_NODE_NUM) {
+ mlog(0, "Out of nodes to recover.\n");
+ break;
+ }
+
+ status = ocfs2_recover_node(osb, node_num);
+ if (status < 0) {
+ mlog(ML_ERROR,
+ "Error %d recovering node %d on device (%u,%u)!\n",
+ status, node_num,
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+ mlog(ML_ERROR, "Volume requires unmount.\n");
+ continue;
+ }
+
+ ocfs2_recovery_map_clear(osb, node_num);
+ }
+ ocfs2_super_unlock(osb, 1);
+
+ /* We always run recovery on our own orphan dir - the dead
+ * node(s) may have voted "no" on an inode delete earlier. A
+ * revote is therefore required. */
+ ocfs2_queue_recovery_completion(osb->journal, osb->slot_num, NULL,
+ NULL);
+
+bail:
+ down(&osb->recovery_lock);
+ if (!status &&
+ !ocfs2_node_map_is_empty(osb, &osb->recovery_map)) {
+ up(&osb->recovery_lock);
+ goto restart;
+ }
+
+ osb->recovery_thread_task = NULL;
+ mb(); /* sync with ocfs2_recovery_thread_running */
+ wake_up(&osb->recovery_event);
+
+ up(&osb->recovery_lock);
+
+ mlog_exit(status);
+ /* no one is callint kthread_stop() for us so the kthread() api
+ * requires that we call do_exit(). And it isn't exported, but
+ * complete_and_exit() seems to be a minimal wrapper around it. */
+ complete_and_exit(NULL, status);
+ return status;
+}
+
+void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num)
+{
+ mlog_entry("(node_num=%d, osb->node_num = %d)\n",
+ node_num, osb->node_num);
+
+ down(&osb->recovery_lock);
+ if (osb->disable_recovery)
+ goto out;
+
+ /* People waiting on recovery will wait on
+ * the recovery map to empty. */
+ if (!ocfs2_recovery_map_set(osb, node_num))
+ mlog(0, "node %d already be in recovery.\n", node_num);
+
+ mlog(0, "starting recovery thread...\n");
+
+ if (osb->recovery_thread_task)
+ goto out;
+
+ osb->recovery_thread_task = kthread_run(__ocfs2_recovery_thread, osb,
+ "ocfs2rec-%d", osb->osb_id);
+ if (IS_ERR(osb->recovery_thread_task)) {
+ mlog_errno((int)PTR_ERR(osb->recovery_thread_task));
+ osb->recovery_thread_task = NULL;
+ }
+
+out:
+ up(&osb->recovery_lock);
+ wake_up(&osb->recovery_event);
+
+ mlog_exit_void();
+}
+
+/* Does the actual journal replay and marks the journal inode as
+ * clean. Will only replay if the journal inode is marked dirty. */
+static int ocfs2_replay_journal(struct ocfs2_super *osb,
+ int node_num,
+ int slot_num)
+{
+ int status;
+ int got_lock = 0;
+ unsigned int flags;
+ struct inode *inode = NULL;
+ struct ocfs2_dinode *fe;
+ journal_t *journal = NULL;
+ struct buffer_head *bh = NULL;
+
+ inode = ocfs2_get_system_file_inode(osb, JOURNAL_SYSTEM_INODE,
+ slot_num);
+ if (inode == NULL) {
+ status = -EACCES;
+ mlog_errno(status);
+ goto done;
+ }
+ if (is_bad_inode(inode)) {
+ status = -EACCES;
+ iput(inode);
+ inode = NULL;
+ mlog_errno(status);
+ goto done;
+ }
+ SET_INODE_JOURNAL(inode);
+
+ status = ocfs2_meta_lock_full(inode, NULL, &bh, 1,
+ OCFS2_META_LOCK_RECOVERY);
+ if (status < 0) {
+ mlog(0, "status returned from ocfs2_meta_lock=%d\n", status);
+ if (status != -ERESTARTSYS)
+ mlog(ML_ERROR, "Could not lock journal!\n");
+ goto done;
+ }
+ got_lock = 1;
+
+ fe = (struct ocfs2_dinode *) bh->b_data;
+
+ flags = le32_to_cpu(fe->id1.journal1.ij_flags);
+
+ if (!(flags & OCFS2_JOURNAL_DIRTY_FL)) {
+ mlog(0, "No recovery required for node %d\n", node_num);
+ goto done;
+ }
+
+ mlog(ML_NOTICE, "Recovering node %d from slot %d on device (%u,%u)\n",
+ node_num, slot_num,
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+
+ OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+
+ status = ocfs2_force_read_journal(inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto done;
+ }
+
+ mlog(0, "calling journal_init_inode\n");
+ journal = journal_init_inode(inode);
+ if (journal == NULL) {
+ mlog(ML_ERROR, "Linux journal layer error\n");
+ status = -EIO;
+ goto done;
+ }
+
+ status = journal_load(journal);
+ if (status < 0) {
+ mlog_errno(status);
+ if (!igrab(inode))
+ BUG();
+ journal_destroy(journal);
+ goto done;
+ }
+
+ ocfs2_clear_journal_error(osb->sb, journal, slot_num);
+
+ /* wipe the journal */
+ mlog(0, "flushing the journal.\n");
+ journal_lock_updates(journal);
+ status = journal_flush(journal);
+ journal_unlock_updates(journal);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* This will mark the node clean */
+ flags = le32_to_cpu(fe->id1.journal1.ij_flags);
+ flags &= ~OCFS2_JOURNAL_DIRTY_FL;
+ fe->id1.journal1.ij_flags = cpu_to_le32(flags);
+
+ status = ocfs2_write_block(osb, bh, inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ if (!igrab(inode))
+ BUG();
+
+ journal_destroy(journal);
+
+done:
+ /* drop the lock on this nodes journal */
+ if (got_lock)
+ ocfs2_meta_unlock(inode, 1);
+
+ if (inode)
+ iput(inode);
+
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Do the most important parts of node recovery:
+ * - Replay it's journal
+ * - Stamp a clean local allocator file
+ * - Stamp a clean truncate log
+ * - Mark the node clean
+ *
+ * If this function completes without error, a node in OCFS2 can be
+ * said to have been safely recovered. As a result, failure during the
+ * second part of a nodes recovery process (local alloc recovery) is
+ * far less concerning.
+ */
+static int ocfs2_recover_node(struct ocfs2_super *osb,
+ int node_num)
+{
+ int status = 0;
+ int slot_num;
+ struct ocfs2_slot_info *si = osb->slot_info;
+ struct ocfs2_dinode *la_copy = NULL;
+ struct ocfs2_dinode *tl_copy = NULL;
+
+ mlog_entry("(node_num=%d, osb->node_num = %d)\n",
+ node_num, osb->node_num);
+
+ mlog(0, "checking node %d\n", node_num);
+
+ /* Should not ever be called to recover ourselves -- in that
+ * case we should've called ocfs2_journal_load instead. */
+ if (osb->node_num == node_num)
+ BUG();
+
+ slot_num = ocfs2_node_num_to_slot(si, node_num);
+ if (slot_num == OCFS2_INVALID_SLOT) {
+ status = 0;
+ mlog(0, "no slot for this node, so no recovery required.\n");
+ goto done;
+ }
+
+ mlog(0, "node %d was using slot %d\n", node_num, slot_num);
+
+ status = ocfs2_replay_journal(osb, node_num, slot_num);
+ if (status < 0) {
+ mlog_errno(status);
+ goto done;
+ }
+
+ /* Stamp a clean local alloc file AFTER recovering the journal... */
+ status = ocfs2_begin_local_alloc_recovery(osb, slot_num, &la_copy);
+ if (status < 0) {
+ mlog_errno(status);
+ goto done;
+ }
+
+ /* An error from begin_truncate_log_recovery is not
+ * serious enough to warrant halting the rest of
+ * recovery. */
+ status = ocfs2_begin_truncate_log_recovery(osb, slot_num, &tl_copy);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* Likewise, this would be a strange but ultimately not so
+ * harmful place to get an error... */
+ ocfs2_clear_slot(si, slot_num);
+ status = ocfs2_update_disk_slots(osb, si);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* This will kfree the memory pointed to by la_copy and tl_copy */
+ ocfs2_queue_recovery_completion(osb->journal, slot_num, la_copy,
+ tl_copy);
+
+ status = 0;
+done:
+
+ mlog_exit(status);
+ return status;
+}
+
+/* Test node liveness by trylocking his journal. If we get the lock,
+ * we drop it here. Return 0 if we got the lock, -EAGAIN if node is
+ * still alive (we couldn't get the lock) and < 0 on error. */
+static int ocfs2_trylock_journal(struct ocfs2_super *osb,
+ int slot_num)
+{
+ int status, flags;
+ struct inode *inode = NULL;
+
+ inode = ocfs2_get_system_file_inode(osb, JOURNAL_SYSTEM_INODE,
+ slot_num);
+ if (inode == NULL) {
+ mlog(ML_ERROR, "access error\n");
+ status = -EACCES;
+ goto bail;
+ }
+ if (is_bad_inode(inode)) {
+ mlog(ML_ERROR, "access error (bad inode)\n");
+ iput(inode);
+ inode = NULL;
+ status = -EACCES;
+ goto bail;
+ }
+ SET_INODE_JOURNAL(inode);
+
+ flags = OCFS2_META_LOCK_RECOVERY | OCFS2_META_LOCK_NOQUEUE;
+ status = ocfs2_meta_lock_full(inode, NULL, NULL, 1, flags);
+ if (status < 0) {
+ if (status != -EAGAIN)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_meta_unlock(inode, 1);
+bail:
+ if (inode)
+ iput(inode);
+
+ return status;
+}
+
+/* Call this underneath ocfs2_super_lock. It also assumes that the
+ * slot info struct has been updated from disk. */
+int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
+{
+ int status, i, node_num;
+ struct ocfs2_slot_info *si = osb->slot_info;
+
+ /* This is called with the super block cluster lock, so we
+ * know that the slot map can't change underneath us. */
+
+ spin_lock(&si->si_lock);
+ for(i = 0; i < si->si_num_slots; i++) {
+ if (i == osb->slot_num)
+ continue;
+ if (ocfs2_is_empty_slot(si, i))
+ continue;
+
+ node_num = si->si_global_node_nums[i];
+ if (ocfs2_node_map_test_bit(osb, &osb->recovery_map, node_num))
+ continue;
+ spin_unlock(&si->si_lock);
+
+ /* Ok, we have a slot occupied by another node which
+ * is not in the recovery map. We trylock his journal
+ * file here to test if he's alive. */
+ status = ocfs2_trylock_journal(osb, i);
+ if (!status) {
+ /* Since we're called from mount, we know that
+ * the recovery thread can't race us on
+ * setting / checking the recovery bits. */
+ ocfs2_recovery_thread(osb, node_num);
+ } else if ((status < 0) && (status != -EAGAIN)) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ spin_lock(&si->si_lock);
+ }
+ spin_unlock(&si->si_lock);
+
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_recover_orphans(struct ocfs2_super *osb,
+ int slot)
+{
+ int status = 0;
+ int have_disk_lock = 0;
+ struct inode *inode = NULL;
+ struct inode *iter;
+ struct inode *orphan_dir_inode = NULL;
+ unsigned long offset, blk, local;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_dir_entry *de;
+ struct super_block *sb = osb->sb;
+ struct ocfs2_inode_info *oi;
+
+ mlog(0, "Recover inodes from orphan dir in slot %d\n", slot);
+
+ orphan_dir_inode = ocfs2_get_system_file_inode(osb,
+ ORPHAN_DIR_SYSTEM_INODE,
+ slot);
+ if (!orphan_dir_inode) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto out;
+ }
+
+ mutex_lock(&orphan_dir_inode->i_mutex);
+ status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0);
+ if (status < 0) {
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+ mlog_errno(status);
+ goto out;
+ }
+ have_disk_lock = 1;
+
+ offset = 0;
+ iter = NULL;
+ while(offset < i_size_read(orphan_dir_inode)) {
+ blk = offset >> sb->s_blocksize_bits;
+
+ bh = ocfs2_bread(orphan_dir_inode, blk, &status, 0);
+ if (!bh)
+ status = -EINVAL;
+ if (status < 0) {
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+ if (bh)
+ brelse(bh);
+ mlog_errno(status);
+ goto out;
+ }
+
+ local = 0;
+ while(offset < i_size_read(orphan_dir_inode)
+ && local < sb->s_blocksize) {
+ de = (struct ocfs2_dir_entry *) (bh->b_data + local);
+
+ if (!ocfs2_check_dir_entry(orphan_dir_inode,
+ de, bh, local)) {
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+ status = -EINVAL;
+ mlog_errno(status);
+ brelse(bh);
+ goto out;
+ }
+
+ local += le16_to_cpu(de->rec_len);
+ offset += le16_to_cpu(de->rec_len);
+
+ /* I guess we silently fail on no inode? */
+ if (!le64_to_cpu(de->inode))
+ continue;
+ if (de->file_type > OCFS2_FT_MAX) {
+ mlog(ML_ERROR,
+ "block %llu contains invalid de: "
+ "inode = %"MLFu64", rec_len = %u, "
+ "name_len = %u, file_type = %u, "
+ "name='%.*s'\n",
+ (unsigned long long)bh->b_blocknr,
+ le64_to_cpu(de->inode),
+ le16_to_cpu(de->rec_len),
+ de->name_len,
+ de->file_type,
+ de->name_len,
+ de->name);
+ continue;
+ }
+ if (de->name_len == 1 && !strncmp(".", de->name, 1))
+ continue;
+ if (de->name_len == 2 && !strncmp("..", de->name, 2))
+ continue;
+
+ iter = ocfs2_iget(osb, le64_to_cpu(de->inode));
+ if (IS_ERR(iter))
+ continue;
+
+ mlog(0, "queue orphan %"MLFu64"\n",
+ OCFS2_I(iter)->ip_blkno);
+ OCFS2_I(iter)->ip_next_orphan = inode;
+ inode = iter;
+ }
+ brelse(bh);
+ }
+ mutex_unlock(&orphan_dir_inode->i_mutex);
+
+ ocfs2_meta_unlock(orphan_dir_inode, 0);
+ have_disk_lock = 0;
+
+ iput(orphan_dir_inode);
+ orphan_dir_inode = NULL;
+
+ while (inode) {
+ oi = OCFS2_I(inode);
+ mlog(0, "iput orphan %"MLFu64"\n", oi->ip_blkno);
+
+ iter = oi->ip_next_orphan;
+
+ spin_lock(&oi->ip_lock);
+ /* Delete voting may have set these on the assumption
+ * that the other node would wipe them successfully.
+ * If they are still in the node's orphan dir, we need
+ * to reset that state. */
+ oi->ip_flags &= ~(OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE);
+
+ /* Set the proper information to get us going into
+ * ocfs2_delete_inode. */
+ oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
+ oi->ip_orphaned_slot = slot;
+ spin_unlock(&oi->ip_lock);
+
+ iput(inode);
+
+ inode = iter;
+ }
+
+out:
+ if (have_disk_lock)
+ ocfs2_meta_unlock(orphan_dir_inode, 0);
+
+ if (orphan_dir_inode)
+ iput(orphan_dir_inode);
+
+ return status;
+}
+
+static int ocfs2_wait_on_mount(struct ocfs2_super *osb)
+{
+ /* This check is good because ocfs2 will wait on our recovery
+ * thread before changing it to something other than MOUNTED
+ * or DISABLED. */
+ wait_event(osb->osb_mount_event,
+ atomic_read(&osb->vol_state) == VOLUME_MOUNTED ||
+ atomic_read(&osb->vol_state) == VOLUME_DISABLED);
+
+ /* If there's an error on mount, then we may never get to the
+ * MOUNTED flag, but this is set right before
+ * dismount_volume() so we can trust it. */
+ if (atomic_read(&osb->vol_state) == VOLUME_DISABLED) {
+ mlog(0, "mount error, exiting!\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int ocfs2_commit_thread(void *arg)
+{
+ int status;
+ struct ocfs2_super *osb = arg;
+ struct ocfs2_journal *journal = osb->journal;
+
+ /* we can trust j_num_trans here because _should_stop() is only set in
+ * shutdown and nobody other than ourselves should be able to start
+ * transactions. committing on shutdown might take a few iterations
+ * as final transactions put deleted inodes on the list */
+ while (!(kthread_should_stop() &&
+ atomic_read(&journal->j_num_trans) == 0)) {
+
+ wait_event_interruptible_timeout(osb->checkpoint_event,
+ atomic_read(&journal->j_num_trans)
+ || kthread_should_stop(),
+ OCFS2_CHECKPOINT_INTERVAL);
+
+ status = ocfs2_commit_cache(osb);
+ if (status < 0)
+ mlog_errno(status);
+
+ if (kthread_should_stop() && atomic_read(&journal->j_num_trans)){
+ mlog(ML_KTHREAD,
+ "commit_thread: %u transactions pending on "
+ "shutdown\n",
+ atomic_read(&journal->j_num_trans));
+ }
+ }
+
+ return 0;
+}
+
+/* Look for a dirty journal without taking any cluster locks. Used for
+ * hard readonly access to determine whether the file system journals
+ * require recovery. */
+int ocfs2_check_journals_nolocks(struct ocfs2_super *osb)
+{
+ int ret = 0;
+ unsigned int slot;
+ struct buffer_head *di_bh;
+ struct ocfs2_dinode *di;
+ struct inode *journal = NULL;
+
+ for(slot = 0; slot < osb->max_slots; slot++) {
+ journal = ocfs2_get_system_file_inode(osb,
+ JOURNAL_SYSTEM_INODE,
+ slot);
+ if (!journal || is_bad_inode(journal)) {
+ ret = -EACCES;
+ mlog_errno(ret);
+ goto out;
+ }
+
+ di_bh = NULL;
+ ret = ocfs2_read_block(osb, OCFS2_I(journal)->ip_blkno, &di_bh,
+ 0, journal);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ di = (struct ocfs2_dinode *) di_bh->b_data;
+
+ if (le32_to_cpu(di->id1.journal1.ij_flags) &
+ OCFS2_JOURNAL_DIRTY_FL)
+ ret = -EROFS;
+
+ brelse(di_bh);
+ if (ret)
+ break;
+ }
+
+out:
+ if (journal)
+ iput(journal);
+
+ return ret;
+}
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
new file mode 100644
index 000000000000..7d0a816184fa
--- /dev/null
+++ b/fs/ocfs2/journal.h
@@ -0,0 +1,457 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * journal.h
+ *
+ * Defines journalling api and structures.
+ *
+ * Copyright (C) 2003, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_JOURNAL_H
+#define OCFS2_JOURNAL_H
+
+#include <linux/fs.h>
+#include <linux/jbd.h>
+
+#define OCFS2_CHECKPOINT_INTERVAL (8 * HZ)
+
+enum ocfs2_journal_state {
+ OCFS2_JOURNAL_FREE = 0,
+ OCFS2_JOURNAL_LOADED,
+ OCFS2_JOURNAL_IN_SHUTDOWN,
+};
+
+struct ocfs2_super;
+struct ocfs2_dinode;
+struct ocfs2_journal_handle;
+
+struct ocfs2_journal {
+ enum ocfs2_journal_state j_state; /* Journals current state */
+
+ journal_t *j_journal; /* The kernels journal type */
+ struct inode *j_inode; /* Kernel inode pointing to
+ * this journal */
+ struct ocfs2_super *j_osb; /* pointer to the super
+ * block for the node
+ * we're currently
+ * running on -- not
+ * necessarily the super
+ * block from the node
+ * which we usually run
+ * from (recovery,
+ * etc) */
+ struct buffer_head *j_bh; /* Journal disk inode block */
+ atomic_t j_num_trans; /* Number of transactions
+ * currently in the system. */
+ unsigned long j_trans_id;
+ struct rw_semaphore j_trans_barrier;
+ wait_queue_head_t j_checkpointed;
+
+ spinlock_t j_lock;
+ struct list_head j_la_cleanups;
+ struct work_struct j_recovery_work;
+};
+
+extern spinlock_t trans_inc_lock;
+
+/* wrap j_trans_id so we never have it equal to zero. */
+static inline unsigned long ocfs2_inc_trans_id(struct ocfs2_journal *j)
+{
+ unsigned long old_id;
+ spin_lock(&trans_inc_lock);
+ old_id = j->j_trans_id++;
+ if (unlikely(!j->j_trans_id))
+ j->j_trans_id = 1;
+ spin_unlock(&trans_inc_lock);
+ return old_id;
+}
+
+static inline void ocfs2_set_inode_lock_trans(struct ocfs2_journal *journal,
+ struct inode *inode)
+{
+ spin_lock(&trans_inc_lock);
+ OCFS2_I(inode)->ip_last_trans = journal->j_trans_id;
+ spin_unlock(&trans_inc_lock);
+}
+
+/* Used to figure out whether it's safe to drop a metadata lock on an
+ * inode. Returns true if all the inodes changes have been
+ * checkpointed to disk. You should be holding the spinlock on the
+ * metadata lock while calling this to be sure that nobody can take
+ * the lock and put it on another transaction. */
+static inline int ocfs2_inode_fully_checkpointed(struct inode *inode)
+{
+ int ret;
+ struct ocfs2_journal *journal = OCFS2_SB(inode->i_sb)->journal;
+
+ spin_lock(&trans_inc_lock);
+ ret = time_after(journal->j_trans_id, OCFS2_I(inode)->ip_last_trans);
+ spin_unlock(&trans_inc_lock);
+ return ret;
+}
+
+/* convenience function to check if an inode is still new (has never
+ * hit disk) Will do you a favor and set created_trans = 0 when you've
+ * been checkpointed. returns '1' if the inode is still new. */
+static inline int ocfs2_inode_is_new(struct inode *inode)
+{
+ int ret;
+
+ /* System files are never "new" as they're written out by
+ * mkfs. This helps us early during mount, before we have the
+ * journal open and j_trans_id could be junk. */
+ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE)
+ return 0;
+ spin_lock(&trans_inc_lock);
+ ret = !(time_after(OCFS2_SB(inode->i_sb)->journal->j_trans_id,
+ OCFS2_I(inode)->ip_created_trans));
+ if (!ret)
+ OCFS2_I(inode)->ip_created_trans = 0;
+ spin_unlock(&trans_inc_lock);
+ return ret;
+}
+
+static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
+ struct inode *inode)
+{
+ spin_lock(&trans_inc_lock);
+ OCFS2_I(inode)->ip_created_trans = osb->journal->j_trans_id;
+ spin_unlock(&trans_inc_lock);
+}
+
+extern kmem_cache_t *ocfs2_lock_cache;
+
+struct ocfs2_journal_lock {
+ struct inode *jl_inode;
+ struct list_head jl_lock_list;
+};
+
+struct ocfs2_journal_handle {
+ handle_t *k_handle; /* kernel handle. */
+ struct ocfs2_journal *journal;
+ u32 flags; /* see flags below. */
+ int max_buffs; /* Buffs reserved by this handle */
+
+ /* The following two fields are for ocfs2_handle_add_lock */
+ int num_locks;
+ struct list_head locks; /* A bunch of locks to
+ * release on commit. This
+ * should be a list_head */
+
+ struct list_head inode_list;
+};
+
+#define OCFS2_HANDLE_STARTED 1
+/* should we sync-commit this handle? */
+#define OCFS2_HANDLE_SYNC 2
+static inline int ocfs2_handle_started(struct ocfs2_journal_handle *handle)
+{
+ return handle->flags & OCFS2_HANDLE_STARTED;
+}
+
+static inline void ocfs2_handle_set_sync(struct ocfs2_journal_handle *handle, int sync)
+{
+ if (sync)
+ handle->flags |= OCFS2_HANDLE_SYNC;
+ else
+ handle->flags &= ~OCFS2_HANDLE_SYNC;
+}
+
+/* Exported only for the journal struct init code in super.c. Do not call. */
+void ocfs2_complete_recovery(void *data);
+
+/*
+ * Journal Control:
+ * Initialize, Load, Shutdown, Wipe a journal.
+ *
+ * ocfs2_journal_init - Initialize journal structures in the OSB.
+ * ocfs2_journal_load - Load the given journal off disk. Replay it if
+ * there's transactions still in there.
+ * ocfs2_journal_shutdown - Shutdown a journal, this will flush all
+ * uncommitted, uncheckpointed transactions.
+ * ocfs2_journal_wipe - Wipe transactions from a journal. Optionally
+ * zero out each block.
+ * ocfs2_recovery_thread - Perform recovery on a node. osb is our own osb.
+ * ocfs2_mark_dead_nodes - Start recovery on nodes we won't get a heartbeat
+ * event on.
+ * ocfs2_start_checkpoint - Kick the commit thread to do a checkpoint.
+ */
+void ocfs2_set_journal_params(struct ocfs2_super *osb);
+int ocfs2_journal_init(struct ocfs2_journal *journal,
+ int *dirty);
+void ocfs2_journal_shutdown(struct ocfs2_super *osb);
+int ocfs2_journal_wipe(struct ocfs2_journal *journal,
+ int full);
+int ocfs2_journal_load(struct ocfs2_journal *journal);
+int ocfs2_check_journals_nolocks(struct ocfs2_super *osb);
+void ocfs2_recovery_thread(struct ocfs2_super *osb,
+ int node_num);
+int ocfs2_mark_dead_nodes(struct ocfs2_super *osb);
+void ocfs2_complete_mount_recovery(struct ocfs2_super *osb);
+
+static inline void ocfs2_start_checkpoint(struct ocfs2_super *osb)
+{
+ atomic_set(&osb->needs_checkpoint, 1);
+ wake_up(&osb->checkpoint_event);
+}
+
+static inline void ocfs2_checkpoint_inode(struct inode *inode)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ if (!ocfs2_inode_fully_checkpointed(inode)) {
+ /* WARNING: This only kicks off a single
+ * checkpoint. If someone races you and adds more
+ * metadata to the journal, you won't know, and will
+ * wind up waiting *alot* longer than necessary. Right
+ * now we only use this in clear_inode so that's
+ * OK. */
+ ocfs2_start_checkpoint(osb);
+
+ wait_event(osb->journal->j_checkpointed,
+ ocfs2_inode_fully_checkpointed(inode));
+ }
+}
+
+/*
+ * Transaction Handling:
+ * Manage the lifetime of a transaction handle.
+ *
+ * ocfs2_alloc_handle - Only allocate a handle so we can start putting
+ * cluster locks on it. To actually change blocks,
+ * call ocfs2_start_trans with the handle returned
+ * from this function. You may call ocfs2_commit_trans
+ * at any time in the lifetime of a handle.
+ * ocfs2_start_trans - Begin a transaction. Give it an upper estimate of
+ * the number of blocks that will be changed during
+ * this handle.
+ * ocfs2_commit_trans - Complete a handle.
+ * ocfs2_extend_trans - Extend a handle by nblocks credits. This may
+ * commit the handle to disk in the process, but will
+ * not release any locks taken during the transaction.
+ * ocfs2_journal_access - Notify the handle that we want to journal this
+ * buffer. Will have to call ocfs2_journal_dirty once
+ * we've actually dirtied it. Type is one of . or .
+ * ocfs2_journal_dirty - Mark a journalled buffer as having dirty data.
+ * ocfs2_journal_dirty_data - Indicate that a data buffer should go out before
+ * the current handle commits.
+ * ocfs2_handle_add_lock - Sometimes we need to delay lock release
+ * until after a transaction has been completed. Use
+ * ocfs2_handle_add_lock to indicate that a lock needs
+ * to be released at the end of that handle. Locks
+ * will be released in the order that they are added.
+ * ocfs2_handle_add_inode - Add a locked inode to a transaction.
+ */
+
+/* You must always start_trans with a number of buffs > 0, but it's
+ * perfectly legal to go through an entire transaction without having
+ * dirtied any buffers. */
+struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb);
+struct ocfs2_journal_handle *ocfs2_start_trans(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ int max_buffs);
+void ocfs2_commit_trans(struct ocfs2_journal_handle *handle);
+int ocfs2_extend_trans(struct ocfs2_journal_handle *handle,
+ int nblocks);
+
+/*
+ * Create access is for when we get a newly created buffer and we're
+ * not gonna read it off disk, but rather fill it ourselves. Right
+ * now, we don't do anything special with this (it turns into a write
+ * request), but this is a good placeholder in case we do...
+ *
+ * Write access is for when we read a block off disk and are going to
+ * modify it. This way the journalling layer knows it may need to make
+ * a copy of that block (if it's part of another, uncommitted
+ * transaction) before we do so.
+ */
+#define OCFS2_JOURNAL_ACCESS_CREATE 0
+#define OCFS2_JOURNAL_ACCESS_WRITE 1
+#define OCFS2_JOURNAL_ACCESS_UNDO 2
+
+int ocfs2_journal_access(struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct buffer_head *bh,
+ int type);
+/*
+ * A word about the journal_access/journal_dirty "dance". It is
+ * entirely legal to journal_access a buffer more than once (as long
+ * as the access type is the same -- I'm not sure what will happen if
+ * access type is different but this should never happen anyway) It is
+ * also legal to journal_dirty a buffer more than once. In fact, you
+ * can even journal_access a buffer after you've done a
+ * journal_access/journal_dirty pair. The only thing you cannot do
+ * however, is journal_dirty a buffer which you haven't yet passed to
+ * journal_access at least once.
+ *
+ * That said, 99% of the time this doesn't matter and this is what the
+ * path looks like:
+ *
+ * <read a bh>
+ * ocfs2_journal_access(handle, bh, OCFS2_JOURNAL_ACCESS_WRITE);
+ * <modify the bh>
+ * ocfs2_journal_dirty(handle, bh);
+ */
+int ocfs2_journal_dirty(struct ocfs2_journal_handle *handle,
+ struct buffer_head *bh);
+int ocfs2_journal_dirty_data(handle_t *handle,
+ struct buffer_head *bh);
+int ocfs2_handle_add_lock(struct ocfs2_journal_handle *handle,
+ struct inode *inode);
+/*
+ * Use this to protect from other processes reading buffer state while
+ * it's in flight.
+ */
+void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle,
+ struct inode *inode);
+
+/*
+ * Credit Macros:
+ * Convenience macros to calculate number of credits needed.
+ *
+ * For convenience sake, I have a set of macros here which calculate
+ * the *maximum* number of sectors which will be changed for various
+ * metadata updates.
+ */
+
+/* simple file updates like chmod, etc. */
+#define OCFS2_INODE_UPDATE_CREDITS 1
+
+/* get one bit out of a suballocator: dinode + group descriptor +
+ * prev. group desc. if we relink. */
+#define OCFS2_SUBALLOC_ALLOC (3)
+
+/* dinode + group descriptor update. We don't relink on free yet. */
+#define OCFS2_SUBALLOC_FREE (2)
+
+#define OCFS2_TRUNCATE_LOG_UPDATE OCFS2_INODE_UPDATE_CREDITS
+#define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE \
+ + OCFS2_TRUNCATE_LOG_UPDATE)
+
+/* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
+ * bitmap block for the new bit) */
+#define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
+
+/* parent fe, parent block, new file entry, inode alloc fe, inode alloc
+ * group descriptor + mkdir/symlink blocks */
+#define OCFS2_MKNOD_CREDITS (3 + OCFS2_SUBALLOC_ALLOC \
+ + OCFS2_DIR_LINK_ADDITIONAL_CREDITS)
+
+/* local alloc metadata change + main bitmap updates */
+#define OCFS2_WINDOW_MOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS \
+ + OCFS2_SUBALLOC_ALLOC + OCFS2_SUBALLOC_FREE)
+
+/* used when we don't need an allocation change for a dir extend. One
+ * for the dinode, one for the new block. */
+#define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
+
+/* file update (nlink, etc) + dir entry block */
+#define OCFS2_LINK_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
+
+/* inode + dir inode (if we unlink a dir), + dir entry block + orphan
+ * dir inode link */
+#define OCFS2_UNLINK_CREDITS (2 * OCFS2_INODE_UPDATE_CREDITS + 1 \
+ + OCFS2_LINK_CREDITS)
+
+/* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
+ * inode alloc group descriptor */
+#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 1 + 1)
+
+/* dinode update, old dir dinode update, new dir dinode update, old
+ * dir dir entry, new dir dir entry, dir entry update for renaming
+ * directory + target unlink */
+#define OCFS2_RENAME_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3 \
+ + OCFS2_UNLINK_CREDITS)
+
+static inline int ocfs2_calc_extend_credits(struct super_block *sb,
+ struct ocfs2_dinode *fe,
+ u32 bits_wanted)
+{
+ int bitmap_blocks, sysfile_bitmap_blocks, dinode_blocks;
+
+ /* bitmap dinode, group desc. + relinked group. */
+ bitmap_blocks = OCFS2_SUBALLOC_ALLOC;
+
+ /* we might need to shift tree depth so lets assume an
+ * absolute worst case of complete fragmentation. Even with
+ * that, we only need one update for the dinode, and then
+ * however many metadata chunks needed * a remaining suballoc
+ * alloc. */
+ sysfile_bitmap_blocks = 1 +
+ (OCFS2_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(fe);
+
+ /* this does not include *new* metadata blocks, which are
+ * accounted for in sysfile_bitmap_blocks. fe +
+ * prev. last_eb_blk + blocks along edge of tree.
+ * calc_symlink_credits passes because we just need 1
+ * credit for the dinode there. */
+ dinode_blocks = 1 + 1 + le16_to_cpu(fe->id2.i_list.l_tree_depth);
+
+ return bitmap_blocks + sysfile_bitmap_blocks + dinode_blocks;
+}
+
+static inline int ocfs2_calc_symlink_credits(struct super_block *sb)
+{
+ int blocks = OCFS2_MKNOD_CREDITS;
+
+ /* links can be longer than one block so we may update many
+ * within our single allocated extent. */
+ blocks += ocfs2_clusters_to_blocks(sb, 1);
+
+ return blocks;
+}
+
+static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
+ unsigned int cpg)
+{
+ int blocks;
+ int bitmap_blocks = OCFS2_SUBALLOC_ALLOC + 1;
+ /* parent inode update + new block group header + bitmap inode update
+ + bitmap blocks affected */
+ blocks = 1 + 1 + 1 + bitmap_blocks;
+ return blocks;
+}
+
+static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
+ unsigned int clusters_to_del,
+ struct ocfs2_dinode *fe,
+ struct ocfs2_extent_list *last_el)
+{
+ /* for dinode + all headers in this pass + update to next leaf */
+ u16 next_free = le16_to_cpu(last_el->l_next_free_rec);
+ u16 tree_depth = le16_to_cpu(fe->id2.i_list.l_tree_depth);
+ int credits = 1 + tree_depth + 1;
+ int i;
+
+ i = next_free - 1;
+ BUG_ON(i < 0);
+
+ /* We may be deleting metadata blocks, so metadata alloc dinode +
+ one desc. block for each possible delete. */
+ if (tree_depth && next_free == 1 &&
+ le32_to_cpu(last_el->l_recs[i].e_clusters) == clusters_to_del)
+ credits += 1 + tree_depth;
+
+ /* update to the truncate log. */
+ credits += OCFS2_TRUNCATE_LOG_UPDATE;
+
+ return credits;
+}
+
+#endif /* OCFS2_JOURNAL_H */
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
new file mode 100644
index 000000000000..149b35181666
--- /dev/null
+++ b/fs/ocfs2/localalloc.c
@@ -0,0 +1,983 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.c
+ *
+ * Node local data allocation
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/bitops.h>
+
+#define MLOG_MASK_PREFIX ML_DISK_ALLOC
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "inode.h"
+#include "journal.h"
+#include "localalloc.h"
+#include "suballoc.h"
+#include "super.h"
+#include "sysfile.h"
+
+#include "buffer_head_io.h"
+
+#define OCFS2_LOCAL_ALLOC(dinode) (&((dinode)->id2.i_lab))
+
+static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb);
+
+static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc);
+
+static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
+ struct ocfs2_dinode *alloc,
+ u32 numbits);
+
+static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc);
+
+static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_dinode *alloc,
+ struct inode *main_bm_inode,
+ struct buffer_head *main_bm_bh);
+
+static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context **ac,
+ struct inode **bitmap_inode,
+ struct buffer_head **bitmap_bh);
+
+static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac);
+
+static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
+ struct inode *local_alloc_inode);
+
+/*
+ * Determine how large our local alloc window should be, in bits.
+ *
+ * These values (and the behavior in ocfs2_alloc_should_use_local) have
+ * been chosen so that most allocations, including new block groups go
+ * through local alloc.
+ */
+static inline int ocfs2_local_alloc_window_bits(struct ocfs2_super *osb)
+{
+ BUG_ON(osb->s_clustersize_bits < 12);
+
+ return 2048 >> (osb->s_clustersize_bits - 12);
+}
+
+/*
+ * Tell us whether a given allocation should use the local alloc
+ * file. Otherwise, it has to go to the main bitmap.
+ */
+int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits)
+{
+ int la_bits = ocfs2_local_alloc_window_bits(osb);
+
+ if (osb->local_alloc_state != OCFS2_LA_ENABLED)
+ return 0;
+
+ /* la_bits should be at least twice the size (in clusters) of
+ * a new block group. We want to be sure block group
+ * allocations go through the local alloc, so allow an
+ * allocation to take up to half the bitmap. */
+ if (bits > (la_bits / 2))
+ return 0;
+
+ return 1;
+}
+
+int ocfs2_load_local_alloc(struct ocfs2_super *osb)
+{
+ int status = 0;
+ struct ocfs2_dinode *alloc = NULL;
+ struct buffer_head *alloc_bh = NULL;
+ u32 num_used;
+ struct inode *inode = NULL;
+ struct ocfs2_local_alloc *la;
+
+ mlog_entry_void();
+
+ /* read the alloc off disk */
+ inode = ocfs2_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE,
+ osb->slot_num);
+ if (!inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
+ &alloc_bh, 0, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
+ la = OCFS2_LOCAL_ALLOC(alloc);
+
+ if (!(le32_to_cpu(alloc->i_flags) &
+ (OCFS2_LOCAL_ALLOC_FL|OCFS2_BITMAP_FL))) {
+ mlog(ML_ERROR, "Invalid local alloc inode, %"MLFu64"\n",
+ OCFS2_I(inode)->ip_blkno);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ if ((la->la_size == 0) ||
+ (le16_to_cpu(la->la_size) > ocfs2_local_alloc_size(inode->i_sb))) {
+ mlog(ML_ERROR, "Local alloc size is invalid (la_size = %u)\n",
+ le16_to_cpu(la->la_size));
+ status = -EINVAL;
+ goto bail;
+ }
+
+ /* do a little verification. */
+ num_used = ocfs2_local_alloc_count_bits(alloc);
+
+ /* hopefully the local alloc has always been recovered before
+ * we load it. */
+ if (num_used
+ || alloc->id1.bitmap1.i_used
+ || alloc->id1.bitmap1.i_total
+ || la->la_bm_off)
+ mlog(ML_ERROR, "Local alloc hasn't been recovered!\n"
+ "found = %u, set = %u, taken = %u, off = %u\n",
+ num_used, le32_to_cpu(alloc->id1.bitmap1.i_used),
+ le32_to_cpu(alloc->id1.bitmap1.i_total),
+ OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
+
+ osb->local_alloc_bh = alloc_bh;
+ osb->local_alloc_state = OCFS2_LA_ENABLED;
+
+bail:
+ if (status < 0)
+ if (alloc_bh)
+ brelse(alloc_bh);
+ if (inode)
+ iput(inode);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * return any unused bits to the bitmap and write out a clean
+ * local_alloc.
+ *
+ * local_alloc_bh is optional. If not passed, we will simply use the
+ * one off osb. If you do pass it however, be warned that it *will* be
+ * returned brelse'd and NULL'd out.*/
+void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb)
+{
+ int status;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct inode *local_alloc_inode = NULL;
+ struct buffer_head *bh = NULL;
+ struct buffer_head *main_bm_bh = NULL;
+ struct inode *main_bm_inode = NULL;
+ struct ocfs2_dinode *alloc_copy = NULL;
+ struct ocfs2_dinode *alloc = NULL;
+
+ mlog_entry_void();
+
+ if (osb->local_alloc_state == OCFS2_LA_UNUSED)
+ goto bail;
+
+ local_alloc_inode =
+ ocfs2_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ osb->slot_num);
+ if (!local_alloc_inode) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ osb->local_alloc_state = OCFS2_LA_DISABLED;
+
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ main_bm_inode = ocfs2_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!main_bm_inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_handle_add_inode(handle, main_bm_inode);
+ status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* WINDOW_MOVE_CREDITS is a bit heavy... */
+ handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
+ if (IS_ERR(handle)) {
+ mlog_errno(PTR_ERR(handle));
+ handle = NULL;
+ goto bail;
+ }
+
+ bh = osb->local_alloc_bh;
+ alloc = (struct ocfs2_dinode *) bh->b_data;
+
+ alloc_copy = kmalloc(bh->b_size, GFP_KERNEL);
+ if (!alloc_copy) {
+ status = -ENOMEM;
+ goto bail;
+ }
+ memcpy(alloc_copy, alloc, bh->b_size);
+
+ status = ocfs2_journal_access(handle, local_alloc_inode, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_clear_local_alloc(alloc);
+
+ status = ocfs2_journal_dirty(handle, bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ brelse(bh);
+ osb->local_alloc_bh = NULL;
+ osb->local_alloc_state = OCFS2_LA_UNUSED;
+
+ status = ocfs2_sync_local_to_main(osb, handle, alloc_copy,
+ main_bm_inode, main_bm_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (main_bm_bh)
+ brelse(main_bm_bh);
+
+ if (main_bm_inode)
+ iput(main_bm_inode);
+
+ if (local_alloc_inode)
+ iput(local_alloc_inode);
+
+ if (alloc_copy)
+ kfree(alloc_copy);
+
+ mlog_exit_void();
+}
+
+/*
+ * We want to free the bitmap bits outside of any recovery context as
+ * we'll need a cluster lock to do so, but we must clear the local
+ * alloc before giving up the recovered nodes journal. To solve this,
+ * we kmalloc a copy of the local alloc before it's change for the
+ * caller to process with ocfs2_complete_local_alloc_recovery
+ */
+int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
+ int slot_num,
+ struct ocfs2_dinode **alloc_copy)
+{
+ int status = 0;
+ struct buffer_head *alloc_bh = NULL;
+ struct inode *inode = NULL;
+ struct ocfs2_dinode *alloc;
+
+ mlog_entry("(slot_num = %d)\n", slot_num);
+
+ *alloc_copy = NULL;
+
+ inode = ocfs2_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ slot_num);
+ if (!inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mutex_lock(&inode->i_mutex);
+
+ status = ocfs2_read_block(osb, OCFS2_I(inode)->ip_blkno,
+ &alloc_bh, 0, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *alloc_copy = kmalloc(alloc_bh->b_size, GFP_KERNEL);
+ if (!(*alloc_copy)) {
+ status = -ENOMEM;
+ goto bail;
+ }
+ memcpy((*alloc_copy), alloc_bh->b_data, alloc_bh->b_size);
+
+ alloc = (struct ocfs2_dinode *) alloc_bh->b_data;
+ ocfs2_clear_local_alloc(alloc);
+
+ status = ocfs2_write_block(osb, alloc_bh, inode);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ if ((status < 0) && (*alloc_copy)) {
+ kfree(*alloc_copy);
+ *alloc_copy = NULL;
+ }
+
+ if (alloc_bh)
+ brelse(alloc_bh);
+
+ if (inode) {
+ mutex_unlock(&inode->i_mutex);
+ iput(inode);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Step 2: By now, we've completed the journal recovery, we've stamped
+ * a clean local alloc on disk and dropped the node out of the
+ * recovery map. Dlm locks will no longer stall, so lets clear out the
+ * main bitmap.
+ */
+int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
+ struct ocfs2_dinode *alloc)
+{
+ int status;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct buffer_head *main_bm_bh = NULL;
+ struct inode *main_bm_inode = NULL;
+
+ mlog_entry_void();
+
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ main_bm_inode = ocfs2_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!main_bm_inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_handle_add_inode(handle, main_bm_inode);
+ status = ocfs2_meta_lock(main_bm_inode, handle, &main_bm_bh, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* we want the bitmap change to be recorded on disk asap */
+ ocfs2_handle_set_sync(handle, 1);
+
+ status = ocfs2_sync_local_to_main(osb, handle, alloc,
+ main_bm_inode, main_bm_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (main_bm_bh)
+ brelse(main_bm_bh);
+
+ if (main_bm_inode)
+ iput(main_bm_inode);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * make sure we've got at least bitswanted contiguous bits in the
+ * local alloc. You lose them when you drop i_mutex.
+ *
+ * We will add ourselves to the transaction passed in, but may start
+ * our own in order to shift windows.
+ */
+int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *passed_handle,
+ u32 bits_wanted,
+ struct ocfs2_alloc_context *ac)
+{
+ int status;
+ struct ocfs2_dinode *alloc;
+ struct inode *local_alloc_inode;
+ unsigned int free_bits;
+
+ mlog_entry_void();
+
+ BUG_ON(!passed_handle);
+ BUG_ON(!ac);
+ BUG_ON(passed_handle->flags & OCFS2_HANDLE_STARTED);
+
+ local_alloc_inode =
+ ocfs2_get_system_file_inode(osb,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ osb->slot_num);
+ if (!local_alloc_inode) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_handle_add_inode(passed_handle, local_alloc_inode);
+
+ if (osb->local_alloc_state != OCFS2_LA_ENABLED) {
+ status = -ENOSPC;
+ goto bail;
+ }
+
+ if (bits_wanted > ocfs2_local_alloc_window_bits(osb)) {
+ mlog(0, "Asking for more than my max window size!\n");
+ status = -ENOSPC;
+ goto bail;
+ }
+
+ alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ if (le32_to_cpu(alloc->id1.bitmap1.i_used) !=
+ ocfs2_local_alloc_count_bits(alloc)) {
+ ocfs2_error(osb->sb, "local alloc inode %"MLFu64" says it has "
+ "%u free bits, but a count shows %u",
+ le64_to_cpu(alloc->i_blkno),
+ le32_to_cpu(alloc->id1.bitmap1.i_used),
+ ocfs2_local_alloc_count_bits(alloc));
+ status = -EIO;
+ goto bail;
+ }
+
+ free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
+ le32_to_cpu(alloc->id1.bitmap1.i_used);
+ if (bits_wanted > free_bits) {
+ /* uhoh, window change time. */
+ status =
+ ocfs2_local_alloc_slide_window(osb, local_alloc_inode);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ ac->ac_inode = igrab(local_alloc_inode);
+ get_bh(osb->local_alloc_bh);
+ ac->ac_bh = osb->local_alloc_bh;
+ ac->ac_which = OCFS2_AC_USE_LOCAL;
+ status = 0;
+bail:
+ if (local_alloc_inode)
+ iput(local_alloc_inode);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 min_bits,
+ u32 *bit_off,
+ u32 *num_bits)
+{
+ int status, start;
+ struct inode *local_alloc_inode;
+ u32 bits_wanted;
+ void *bitmap;
+ struct ocfs2_dinode *alloc;
+ struct ocfs2_local_alloc *la;
+
+ mlog_entry_void();
+ BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL);
+
+ bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+ local_alloc_inode = ac->ac_inode;
+ alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+ la = OCFS2_LOCAL_ALLOC(alloc);
+
+ start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+ if (start == -1) {
+ /* TODO: Shouldn't we just BUG here? */
+ status = -ENOSPC;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bitmap = la->la_bitmap;
+ *bit_off = le32_to_cpu(la->la_bm_off) + start;
+ /* local alloc is always contiguous by nature -- we never
+ * delete bits from it! */
+ *num_bits = bits_wanted;
+
+ status = ocfs2_journal_access(handle, local_alloc_inode,
+ osb->local_alloc_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ while(bits_wanted--)
+ ocfs2_set_bit(start++, bitmap);
+
+ alloc->id1.bitmap1.i_used = cpu_to_le32(*num_bits +
+ le32_to_cpu(alloc->id1.bitmap1.i_used));
+
+ status = ocfs2_journal_dirty(handle, osb->local_alloc_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc)
+{
+ int i;
+ u8 *buffer;
+ u32 count = 0;
+ struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
+
+ mlog_entry_void();
+
+ buffer = la->la_bitmap;
+ for (i = 0; i < le16_to_cpu(la->la_size); i++)
+ count += hweight8(buffer[i]);
+
+ mlog_exit(count);
+ return count;
+}
+
+static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb,
+ struct ocfs2_dinode *alloc,
+ u32 numbits)
+{
+ int numfound, bitoff, left, startoff, lastzero;
+ void *bitmap = NULL;
+
+ mlog_entry("(numbits wanted = %u)\n", numbits);
+
+ if (!alloc->id1.bitmap1.i_total) {
+ mlog(0, "No bits in my window!\n");
+ bitoff = -1;
+ goto bail;
+ }
+
+ bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap;
+
+ numfound = bitoff = startoff = 0;
+ lastzero = -1;
+ left = le32_to_cpu(alloc->id1.bitmap1.i_total);
+ while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) {
+ if (bitoff == left) {
+ /* mlog(0, "bitoff (%d) == left", bitoff); */
+ break;
+ }
+ /* mlog(0, "Found a zero: bitoff = %d, startoff = %d, "
+ "numfound = %d\n", bitoff, startoff, numfound);*/
+
+ /* Ok, we found a zero bit... is it contig. or do we
+ * start over?*/
+ if (bitoff == startoff) {
+ /* we found a zero */
+ numfound++;
+ startoff++;
+ } else {
+ /* got a zero after some ones */
+ numfound = 1;
+ startoff = bitoff+1;
+ }
+ /* we got everything we needed */
+ if (numfound == numbits) {
+ /* mlog(0, "Found it all!\n"); */
+ break;
+ }
+ }
+
+ mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff,
+ numfound);
+
+ if (numfound == numbits)
+ bitoff = startoff - numfound;
+ else
+ bitoff = -1;
+
+bail:
+ mlog_exit(bitoff);
+ return bitoff;
+}
+
+static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc)
+{
+ struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
+ int i;
+ mlog_entry_void();
+
+ alloc->id1.bitmap1.i_total = 0;
+ alloc->id1.bitmap1.i_used = 0;
+ la->la_bm_off = 0;
+ for(i = 0; i < le16_to_cpu(la->la_size); i++)
+ la->la_bitmap[i] = 0;
+
+ mlog_exit_void();
+}
+
+#if 0
+/* turn this on and uncomment below to aid debugging window shifts. */
+static void ocfs2_verify_zero_bits(unsigned long *bitmap,
+ unsigned int start,
+ unsigned int count)
+{
+ unsigned int tmp = count;
+ while(tmp--) {
+ if (ocfs2_test_bit(start + tmp, bitmap)) {
+ printk("ocfs2_verify_zero_bits: start = %u, count = "
+ "%u\n", start, count);
+ printk("ocfs2_verify_zero_bits: bit %u is set!",
+ start + tmp);
+ BUG();
+ }
+ }
+}
+#endif
+
+/*
+ * sync the local alloc to main bitmap.
+ *
+ * assumes you've already locked the main bitmap -- the bitmap inode
+ * passed is used for caching.
+ */
+static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_dinode *alloc,
+ struct inode *main_bm_inode,
+ struct buffer_head *main_bm_bh)
+{
+ int status = 0;
+ int bit_off, left, count, start;
+ u64 la_start_blk;
+ u64 blkno;
+ void *bitmap;
+ struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc);
+
+ mlog_entry("total = %u, COUNT = %u, used = %u\n",
+ le32_to_cpu(alloc->id1.bitmap1.i_total),
+ ocfs2_local_alloc_count_bits(alloc),
+ le32_to_cpu(alloc->id1.bitmap1.i_used));
+
+ if (!alloc->id1.bitmap1.i_total) {
+ mlog(0, "nothing to sync!\n");
+ goto bail;
+ }
+
+ if (le32_to_cpu(alloc->id1.bitmap1.i_used) ==
+ le32_to_cpu(alloc->id1.bitmap1.i_total)) {
+ mlog(0, "all bits were taken!\n");
+ goto bail;
+ }
+
+ la_start_blk = ocfs2_clusters_to_blocks(osb->sb,
+ le32_to_cpu(la->la_bm_off));
+ bitmap = la->la_bitmap;
+ start = count = bit_off = 0;
+ left = le32_to_cpu(alloc->id1.bitmap1.i_total);
+
+ while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start))
+ != -1) {
+ if ((bit_off < left) && (bit_off == start)) {
+ count++;
+ start++;
+ continue;
+ }
+ if (count) {
+ blkno = la_start_blk +
+ ocfs2_clusters_to_blocks(osb->sb,
+ start - count);
+
+ mlog(0, "freeing %u bits starting at local "
+ "alloc bit %u (la_start_blk = %"MLFu64", "
+ "blkno = %"MLFu64")\n", count, start - count,
+ la_start_blk, blkno);
+
+ status = ocfs2_free_clusters(handle, main_bm_inode,
+ main_bm_bh, blkno, count);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ if (bit_off >= left)
+ break;
+ count = 1;
+ start = bit_off + 1;
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_local_alloc_reserve_for_window(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context **ac,
+ struct inode **bitmap_inode,
+ struct buffer_head **bitmap_bh)
+{
+ int status;
+
+ *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_handle = handle;
+ (*ac)->ac_bits_wanted = ocfs2_local_alloc_window_bits(osb);
+
+ status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ *bitmap_inode = (*ac)->ac_inode;
+ igrab(*bitmap_inode);
+ *bitmap_bh = (*ac)->ac_bh;
+ get_bh(*bitmap_bh);
+ status = 0;
+bail:
+ if ((status < 0) && *ac) {
+ ocfs2_free_alloc_context(*ac);
+ *ac = NULL;
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * pass it the bitmap lock in lock_bh if you have it.
+ */
+static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac)
+{
+ int status = 0;
+ u32 cluster_off, cluster_count;
+ struct ocfs2_dinode *alloc = NULL;
+ struct ocfs2_local_alloc *la;
+
+ mlog_entry_void();
+
+ alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+ la = OCFS2_LOCAL_ALLOC(alloc);
+
+ if (alloc->id1.bitmap1.i_total)
+ mlog(0, "asking me to alloc a new window over a non-empty "
+ "one\n");
+
+ mlog(0, "Allocating %u clusters for a new window.\n",
+ ocfs2_local_alloc_window_bits(osb));
+ /* we used the generic suballoc reserve function, but we set
+ * everything up nicely, so there's no reason why we can't use
+ * the more specific cluster api to claim bits. */
+ status = ocfs2_claim_clusters(osb, handle, ac,
+ ocfs2_local_alloc_window_bits(osb),
+ &cluster_off, &cluster_count);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ la->la_bm_off = cpu_to_le32(cluster_off);
+ alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count);
+ /* just in case... In the future when we find space ourselves,
+ * we don't have to get all contiguous -- but we'll have to
+ * set all previously used bits in bitmap and update
+ * la_bits_set before setting the bits in the main bitmap. */
+ alloc->id1.bitmap1.i_used = 0;
+ memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0,
+ le16_to_cpu(la->la_size));
+
+ mlog(0, "New window allocated:\n");
+ mlog(0, "window la_bm_off = %u\n",
+ OCFS2_LOCAL_ALLOC(alloc)->la_bm_off);
+ mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total));
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* Note that we do *NOT* lock the local alloc inode here as
+ * it's been locked already for us. */
+static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb,
+ struct inode *local_alloc_inode)
+{
+ int status = 0;
+ struct buffer_head *main_bm_bh = NULL;
+ struct inode *main_bm_inode = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_dinode *alloc;
+ struct ocfs2_dinode *alloc_copy = NULL;
+ struct ocfs2_alloc_context *ac = NULL;
+
+ mlog_entry_void();
+
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* This will lock the main bitmap for us. */
+ status = ocfs2_local_alloc_reserve_for_window(osb,
+ handle,
+ &ac,
+ &main_bm_inode,
+ &main_bm_bh);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_WINDOW_MOVE_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+ /* We want to clear the local alloc before doing anything
+ * else, so that if we error later during this operation,
+ * local alloc shutdown won't try to double free main bitmap
+ * bits. Make a copy so the sync function knows which bits to
+ * free. */
+ alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);
+ if (!alloc_copy) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+ memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
+
+ status = ocfs2_journal_access(handle, local_alloc_inode,
+ osb->local_alloc_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_clear_local_alloc(alloc);
+
+ status = ocfs2_journal_dirty(handle, osb->local_alloc_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_sync_local_to_main(osb, handle, alloc_copy,
+ main_bm_inode, main_bm_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_local_alloc_new_window(osb, handle, ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ atomic_inc(&osb->alloc_stats.moves);
+
+ status = 0;
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (main_bm_bh)
+ brelse(main_bm_bh);
+
+ if (main_bm_inode)
+ iput(main_bm_inode);
+
+ if (alloc_copy)
+ kfree(alloc_copy);
+
+ if (ac)
+ ocfs2_free_alloc_context(ac);
+
+ mlog_exit(status);
+ return status;
+}
+
diff --git a/fs/ocfs2/localalloc.h b/fs/ocfs2/localalloc.h
new file mode 100644
index 000000000000..30f88ce14e46
--- /dev/null
+++ b/fs/ocfs2/localalloc.h
@@ -0,0 +1,56 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_LOCALALLOC_H
+#define OCFS2_LOCALALLOC_H
+
+int ocfs2_load_local_alloc(struct ocfs2_super *osb);
+
+void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb);
+
+int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb,
+ int node_num,
+ struct ocfs2_dinode **alloc_copy);
+
+int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb,
+ struct ocfs2_dinode *alloc);
+
+int ocfs2_alloc_should_use_local(struct ocfs2_super *osb,
+ u64 bits);
+
+struct ocfs2_alloc_context;
+int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *passed_handle,
+ u32 bits_wanted,
+ struct ocfs2_alloc_context *ac);
+
+int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 min_bits,
+ u32 *bit_off,
+ u32 *num_bits);
+
+#endif /* OCFS2_LOCALALLOC_H */
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c
new file mode 100644
index 000000000000..843cf9ddefe8
--- /dev/null
+++ b/fs/ocfs2/mmap.c
@@ -0,0 +1,98 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * mmap.c
+ *
+ * Code to deal with the mess that is clustered mmap.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/uio.h>
+#include <linux/signal.h>
+#include <linux/rbtree.h>
+
+#define MLOG_MASK_PREFIX ML_FILE_IO
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "dlmglue.h"
+#include "file.h"
+#include "inode.h"
+#include "mmap.h"
+
+static struct page *ocfs2_nopage(struct vm_area_struct * area,
+ unsigned long address,
+ int *type)
+{
+ struct inode *inode = area->vm_file->f_dentry->d_inode;
+ struct page *page = NOPAGE_SIGBUS;
+ sigset_t blocked, oldset;
+ int ret;
+
+ mlog_entry("(inode %lu, address %lu)\n", inode->i_ino, address);
+
+ /* The best way to deal with signals in this path is
+ * to block them upfront, rather than allowing the
+ * locking paths to return -ERESTARTSYS. */
+ sigfillset(&blocked);
+
+ /* We should technically never get a bad ret return
+ * from sigprocmask */
+ ret = sigprocmask(SIG_BLOCK, &blocked, &oldset);
+ if (ret < 0) {
+ mlog_errno(ret);
+ goto out;
+ }
+
+ page = filemap_nopage(area, address, type);
+
+ ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
+ if (ret < 0)
+ mlog_errno(ret);
+out:
+ mlog_exit_ptr(page);
+ return page;
+}
+
+static struct vm_operations_struct ocfs2_file_vm_ops = {
+ .nopage = ocfs2_nopage,
+};
+
+int ocfs2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ /* We don't want to support shared writable mappings yet. */
+ if (((vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_MAYSHARE))
+ && ((vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_MAYWRITE))) {
+ mlog(0, "disallow shared writable mmaps %lx\n", vma->vm_flags);
+ /* This is -EINVAL because generic_file_readonly_mmap
+ * returns it in a similar situation. */
+ return -EINVAL;
+ }
+
+ file_accessed(file);
+ vma->vm_ops = &ocfs2_file_vm_ops;
+ return 0;
+}
+
diff --git a/fs/ocfs2/mmap.h b/fs/ocfs2/mmap.h
new file mode 100644
index 000000000000..1274ee0f1fe2
--- /dev/null
+++ b/fs/ocfs2/mmap.h
@@ -0,0 +1,6 @@
+#ifndef OCFS2_MMAP_H
+#define OCFS2_MMAP_H
+
+int ocfs2_mmap(struct file *file, struct vm_area_struct *vma);
+
+#endif /* OCFS2_MMAP_H */
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
new file mode 100644
index 000000000000..f6b77ff1d2bf
--- /dev/null
+++ b/fs/ocfs2/namei.c
@@ -0,0 +1,2264 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * namei.c
+ *
+ * Create and rename file, directory, symlinks
+ *
+ * Copyright (C) 2002, 2004 Oracle. All rights reserved.
+ *
+ * Portions of this code from linux/fs/ext3/dir.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/fs/minix/dir.c
+ *
+ * Copyright (C) 1991, 1992 Linux Torvalds
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#define MLOG_MASK_PREFIX ML_NAMEI
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dcache.h"
+#include "dir.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "file.h"
+#include "inode.h"
+#include "journal.h"
+#include "namei.h"
+#include "suballoc.h"
+#include "symlink.h"
+#include "sysfile.h"
+#include "uptodate.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+#define NAMEI_RA_CHUNKS 2
+#define NAMEI_RA_BLOCKS 4
+#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
+
+static int inline ocfs2_search_dirblock(struct buffer_head *bh,
+ struct inode *dir,
+ const char *name, int namelen,
+ unsigned long offset,
+ struct ocfs2_dir_entry **res_dir);
+
+static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ struct ocfs2_dir_entry *de_del,
+ struct buffer_head *bh);
+
+static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ const char *name, int namelen,
+ struct inode *inode, u64 blkno,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh);
+
+static int ocfs2_mknod_locked(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct dentry *dentry, int mode,
+ dev_t dev,
+ struct buffer_head **new_fe_bh,
+ struct buffer_head *parent_fe_bh,
+ struct ocfs2_journal_handle *handle,
+ struct inode **ret_inode,
+ struct ocfs2_alloc_context *inode_ac);
+
+static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *parent,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_alloc_context *data_ac);
+
+static int ocfs2_double_lock(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **bh1,
+ struct inode *inode1,
+ struct buffer_head **bh2,
+ struct inode *inode2);
+
+static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ char *name,
+ struct buffer_head **de_bh);
+
+static int ocfs2_orphan_add(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct ocfs2_dinode *fe,
+ char *name,
+ struct buffer_head *de_bh);
+
+static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ const char *symname);
+
+static inline int ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+ struct dentry *dentry,
+ struct inode *inode, u64 blkno,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh)
+{
+ return __ocfs2_add_entry(handle, dentry->d_parent->d_inode,
+ dentry->d_name.name, dentry->d_name.len,
+ inode, blkno, parent_fe_bh, insert_bh);
+}
+
+/* An orphan dir name is an 8 byte value, printed as a hex string */
+#define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
+
+static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
+{
+ int status;
+ u64 blkno;
+ struct buffer_head *dirent_bh = NULL;
+ struct inode *inode = NULL;
+ struct dentry *ret;
+ struct ocfs2_dir_entry *dirent;
+ struct ocfs2_inode_info *oi;
+
+ mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
+ dentry->d_name.len, dentry->d_name.name);
+
+ if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) {
+ ret = ERR_PTR(-ENAMETOOLONG);
+ goto bail;
+ }
+
+ mlog(0, "find name %.*s in directory %"MLFu64"\n", dentry->d_name.len,
+ dentry->d_name.name, OCFS2_I(dir)->ip_blkno);
+
+ status = ocfs2_meta_lock(dir, NULL, NULL, 0);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ ret = ERR_PTR(status);
+ goto bail;
+ }
+
+ status = ocfs2_find_files_on_disk(dentry->d_name.name,
+ dentry->d_name.len, &blkno,
+ dir, &dirent_bh, &dirent);
+ if (status < 0)
+ goto bail_add;
+
+ inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno);
+ if (IS_ERR(inode)) {
+ mlog(ML_ERROR, "Unable to create inode %"MLFu64"\n", blkno);
+ ret = ERR_PTR(-EACCES);
+ goto bail_unlock;
+ }
+
+ oi = OCFS2_I(inode);
+ /* Clear any orphaned state... If we were able to look up the
+ * inode from a directory, it certainly can't be orphaned. We
+ * might have the bad state from a node which intended to
+ * orphan this inode but crashed before it could commit the
+ * unlink. */
+ spin_lock(&oi->ip_lock);
+ oi->ip_flags &= ~OCFS2_INODE_MAYBE_ORPHANED;
+ oi->ip_orphaned_slot = OCFS2_INVALID_SLOT;
+ spin_unlock(&oi->ip_lock);
+
+bail_add:
+
+ dentry->d_op = &ocfs2_dentry_ops;
+ ret = d_splice_alias(inode, dentry);
+
+bail_unlock:
+ /* Don't drop the cluster lock until *after* the d_add --
+ * unlink on another node will message us to remove that
+ * dentry under this lock so otherwise we can race this with
+ * the vote thread and have a stale dentry. */
+ ocfs2_meta_unlock(dir, 0);
+
+bail:
+ if (dirent_bh)
+ brelse(dirent_bh);
+
+ mlog_exit_ptr(ret);
+
+ return ret;
+}
+
+static int ocfs2_fill_new_dir(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *parent,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ struct ocfs2_alloc_context *data_ac)
+{
+ int status;
+ struct buffer_head *new_bh = NULL;
+ struct ocfs2_dir_entry *de = NULL;
+
+ mlog_entry_void();
+
+ status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
+ data_ac, NULL, &new_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ocfs2_set_new_buffer_uptodate(inode, new_bh);
+
+ status = ocfs2_journal_access(handle, inode, new_bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ memset(new_bh->b_data, 0, osb->sb->s_blocksize);
+
+ de = (struct ocfs2_dir_entry *) new_bh->b_data;
+ de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
+ de->name_len = 1;
+ de->rec_len =
+ cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
+ strcpy(de->name, ".");
+ ocfs2_set_de_type(de, S_IFDIR);
+ de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
+ de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
+ de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
+ OCFS2_DIR_REC_LEN(1));
+ de->name_len = 2;
+ strcpy(de->name, "..");
+ ocfs2_set_de_type(de, S_IFDIR);
+
+ status = ocfs2_journal_dirty(handle, new_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ i_size_write(inode, inode->i_sb->s_blocksize);
+ inode->i_nlink = 2;
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(inode->i_sb->s_blocksize);
+ status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ if (new_bh)
+ brelse(new_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_mknod(struct inode *dir,
+ struct dentry *dentry,
+ int mode,
+ dev_t dev)
+{
+ int status = 0;
+ struct buffer_head *parent_fe_bh = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_super *osb;
+ struct ocfs2_dinode *dirfe;
+ struct buffer_head *new_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
+ struct inode *inode = NULL;
+ struct ocfs2_alloc_context *inode_ac = NULL;
+ struct ocfs2_alloc_context *data_ac = NULL;
+
+ mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
+ (unsigned long)dev, dentry->d_name.len,
+ dentry->d_name.name);
+
+ /* get our super block */
+ osb = OCFS2_SB(dir->i_sb);
+
+ if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
+ mlog(ML_ERROR, "inode %"MLFu64" has i_nlink of %u\n",
+ OCFS2_I(dir)->ip_blkno, dir->i_nlink);
+ status = -EMLINK;
+ goto leave;
+ }
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
+ if (!dirfe->i_links_count) {
+ /* can't make a file in a deleted directory. */
+ status = -ENOENT;
+ goto leave;
+ }
+
+ status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+ dentry->d_name.len);
+ if (status)
+ goto leave;
+
+ /* get a spot inside the dir. */
+ status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* reserve an inode spot */
+ status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* are we making a directory? If so, reserve a cluster for his
+ * 1st extent. */
+ if (S_ISDIR(mode)) {
+ status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto leave;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_MKNOD_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* do the real work now. */
+ status = ocfs2_mknod_locked(osb, dir, dentry, mode, dev,
+ &new_fe_bh, parent_fe_bh, handle,
+ &inode, inode_ac);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (S_ISDIR(mode)) {
+ status = ocfs2_fill_new_dir(osb, handle, dir, inode,
+ new_fe_bh, data_ac);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_journal_access(handle, dir, parent_fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+ le16_add_cpu(&dirfe->i_links_count, 1);
+ status = ocfs2_journal_dirty(handle, parent_fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+ dir->i_nlink++;
+ }
+
+ status = ocfs2_add_entry(handle, dentry, inode,
+ OCFS2_I(inode)->ip_blkno, parent_fe_bh,
+ de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ insert_inode_hash(inode);
+ dentry->d_op = &ocfs2_dentry_ops;
+ d_instantiate(dentry, inode);
+ status = 0;
+leave:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (status == -ENOSPC)
+ mlog(0, "Disk is full\n");
+
+ if (new_fe_bh)
+ brelse(new_fe_bh);
+
+ if (de_bh)
+ brelse(de_bh);
+
+ if (parent_fe_bh)
+ brelse(parent_fe_bh);
+
+ if ((status < 0) && inode)
+ iput(inode);
+
+ if (inode_ac)
+ ocfs2_free_alloc_context(inode_ac);
+
+ if (data_ac)
+ ocfs2_free_alloc_context(data_ac);
+
+ mlog_exit(status);
+
+ return status;
+}
+
+static int ocfs2_mknod_locked(struct ocfs2_super *osb,
+ struct inode *dir,
+ struct dentry *dentry, int mode,
+ dev_t dev,
+ struct buffer_head **new_fe_bh,
+ struct buffer_head *parent_fe_bh,
+ struct ocfs2_journal_handle *handle,
+ struct inode **ret_inode,
+ struct ocfs2_alloc_context *inode_ac)
+{
+ int status = 0;
+ struct ocfs2_dinode *fe = NULL;
+ struct ocfs2_extent_list *fel;
+ u64 fe_blkno = 0;
+ u16 suballoc_bit;
+ struct inode *inode = NULL;
+
+ mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
+ (unsigned long)dev, dentry->d_name.len,
+ dentry->d_name.name);
+
+ *new_fe_bh = NULL;
+ *ret_inode = NULL;
+
+ status = ocfs2_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
+ &fe_blkno);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ inode = new_inode(dir->i_sb);
+ if (IS_ERR(inode)) {
+ status = PTR_ERR(inode);
+ mlog(ML_ERROR, "new_inode failed!\n");
+ goto leave;
+ }
+
+ /* populate as many fields early on as possible - many of
+ * these are used by the support functions here and in
+ * callers. */
+ inode->i_ino = ino_from_blkno(osb->sb, fe_blkno);
+ OCFS2_I(inode)->ip_blkno = fe_blkno;
+ if (S_ISDIR(mode))
+ inode->i_nlink = 2;
+ else
+ inode->i_nlink = 1;
+ inode->i_mode = mode;
+ spin_lock(&osb->osb_lock);
+ inode->i_generation = osb->s_next_generation++;
+ spin_unlock(&osb->osb_lock);
+
+ *new_fe_bh = sb_getblk(osb->sb, fe_blkno);
+ if (!*new_fe_bh) {
+ status = -EIO;
+ mlog_errno(status);
+ goto leave;
+ }
+ ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh);
+
+ status = ocfs2_journal_access(handle, inode, *new_fe_bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ fe = (struct ocfs2_dinode *) (*new_fe_bh)->b_data;
+ memset(fe, 0, osb->sb->s_blocksize);
+
+ fe->i_generation = cpu_to_le32(inode->i_generation);
+ fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
+ fe->i_blkno = cpu_to_le64(fe_blkno);
+ fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
+ fe->i_suballoc_slot = cpu_to_le16(osb->slot_num);
+ fe->i_uid = cpu_to_le32(current->fsuid);
+ if (dir->i_mode & S_ISGID) {
+ fe->i_gid = cpu_to_le32(dir->i_gid);
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+ } else
+ fe->i_gid = cpu_to_le32(current->fsgid);
+ fe->i_mode = cpu_to_le16(mode);
+ if (S_ISCHR(mode) || S_ISBLK(mode))
+ fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
+
+ fe->i_links_count = cpu_to_le16(inode->i_nlink);
+
+ fe->i_last_eb_blk = 0;
+ strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
+ le32_add_cpu(&fe->i_flags, OCFS2_VALID_FL);
+ fe->i_atime = fe->i_ctime = fe->i_mtime =
+ cpu_to_le64(CURRENT_TIME.tv_sec);
+ fe->i_mtime_nsec = fe->i_ctime_nsec = fe->i_atime_nsec =
+ cpu_to_le32(CURRENT_TIME.tv_nsec);
+ fe->i_dtime = 0;
+
+ fel = &fe->id2.i_list;
+ fel->l_tree_depth = 0;
+ fel->l_next_free_rec = 0;
+ fel->l_count = cpu_to_le16(ocfs2_extent_recs_per_inode(osb->sb));
+
+ status = ocfs2_journal_dirty(handle, *new_fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (ocfs2_populate_inode(inode, fe, 1) < 0) {
+ mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
+ "i_blkno=%"MLFu64", i_ino=%lu\n",
+ (unsigned long long) (*new_fe_bh)->b_blocknr,
+ fe->i_blkno, inode->i_ino);
+ BUG();
+ }
+
+ ocfs2_inode_set_new(osb, inode);
+ status = ocfs2_create_new_inode_locks(inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ status = 0; /* error in ocfs2_create_new_inode_locks is not
+ * critical */
+
+ *ret_inode = inode;
+leave:
+ if (status < 0) {
+ if (*new_fe_bh) {
+ brelse(*new_fe_bh);
+ *new_fe_bh = NULL;
+ }
+ if (inode)
+ iput(inode);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_mkdir(struct inode *dir,
+ struct dentry *dentry,
+ int mode)
+{
+ int ret;
+
+ mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode,
+ dentry->d_name.len, dentry->d_name.name);
+ ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0);
+ mlog_exit(ret);
+
+ return ret;
+}
+
+static int ocfs2_create(struct inode *dir,
+ struct dentry *dentry,
+ int mode,
+ struct nameidata *nd)
+{
+ int ret;
+
+ mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode,
+ dentry->d_name.len, dentry->d_name.name);
+ ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0);
+ mlog_exit(ret);
+
+ return ret;
+}
+
+static int ocfs2_link(struct dentry *old_dentry,
+ struct inode *dir,
+ struct dentry *dentry)
+{
+ struct ocfs2_journal_handle *handle = NULL;
+ struct inode *inode = old_dentry->d_inode;
+ int err;
+ struct buffer_head *fe_bh = NULL;
+ struct buffer_head *parent_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
+ struct ocfs2_dinode *fe = NULL;
+ struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+
+ mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino,
+ old_dentry->d_name.len, old_dentry->d_name.name,
+ dentry->d_name.len, dentry->d_name.name);
+
+ if (S_ISDIR(inode->i_mode)) {
+ err = -EPERM;
+ goto bail;
+ }
+
+ if (inode->i_nlink >= OCFS2_LINK_MAX) {
+ err = -EMLINK;
+ goto bail;
+ }
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ err = -ENOMEM;
+ goto bail;
+ }
+
+ err = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
+ if (err < 0) {
+ if (err != -ENOENT)
+ mlog_errno(err);
+ goto bail;
+ }
+
+ err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+ dentry->d_name.len);
+ if (err)
+ goto bail;
+
+ err = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (err < 0) {
+ mlog_errno(err);
+ goto bail;
+ }
+
+ err = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
+ if (err < 0) {
+ if (err != -ENOENT)
+ mlog_errno(err);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) {
+ err = -EMLINK;
+ goto bail;
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_LINK_CREDITS);
+ if (IS_ERR(handle)) {
+ err = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(err);
+ goto bail;
+ }
+
+ err = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (err < 0) {
+ mlog_errno(err);
+ goto bail;
+ }
+
+ inode->i_nlink++;
+ inode->i_ctime = CURRENT_TIME;
+ fe->i_links_count = cpu_to_le16(inode->i_nlink);
+ fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
+ fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+
+ err = ocfs2_journal_dirty(handle, fe_bh);
+ if (err < 0) {
+ le16_add_cpu(&fe->i_links_count, -1);
+ inode->i_nlink--;
+ mlog_errno(err);
+ goto bail;
+ }
+
+ err = ocfs2_add_entry(handle, dentry, inode,
+ OCFS2_I(inode)->ip_blkno,
+ parent_fe_bh, de_bh);
+ if (err) {
+ le16_add_cpu(&fe->i_links_count, -1);
+ inode->i_nlink--;
+ mlog_errno(err);
+ goto bail;
+ }
+
+ atomic_inc(&inode->i_count);
+ dentry->d_op = &ocfs2_dentry_ops;
+ d_instantiate(dentry, inode);
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+ if (de_bh)
+ brelse(de_bh);
+ if (fe_bh)
+ brelse(fe_bh);
+ if (parent_fe_bh)
+ brelse(parent_fe_bh);
+
+ mlog_exit(err);
+
+ return err;
+}
+
+static int ocfs2_unlink(struct inode *dir,
+ struct dentry *dentry)
+{
+ int status;
+ unsigned int saved_nlink = 0;
+ struct inode *inode = dentry->d_inode;
+ struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
+ u64 blkno;
+ struct ocfs2_dinode *fe = NULL;
+ struct buffer_head *fe_bh = NULL;
+ struct buffer_head *parent_node_bh = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_dir_entry *dirent = NULL;
+ struct buffer_head *dirent_bh = NULL;
+ char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
+ struct buffer_head *orphan_entry_bh = NULL;
+
+ mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry,
+ dentry->d_name.len, dentry->d_name.name);
+
+ BUG_ON(dentry->d_parent->d_inode != dir);
+
+ mlog(0, "ino = %"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+
+ if (inode == osb->root_inode) {
+ mlog(0, "Cannot delete the root directory\n");
+ status = -EPERM;
+ goto leave;
+ }
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_meta_lock(dir, handle, &parent_node_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_find_files_on_disk(dentry->d_name.name,
+ dentry->d_name.len, &blkno,
+ dir, &dirent_bh, &dirent);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (OCFS2_I(inode)->ip_blkno != blkno) {
+ status = -ENOENT;
+
+ mlog(0, "ip_blkno (%"MLFu64") != dirent blkno (%"MLFu64") "
+ "ip_flags = %x\n", OCFS2_I(inode)->ip_blkno, blkno,
+ OCFS2_I(inode)->ip_flags);
+ goto leave;
+ }
+
+ status = ocfs2_meta_lock(inode, handle, &fe_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (S_ISDIR(inode->i_mode)) {
+ if (!ocfs2_empty_dir(inode)) {
+ status = -ENOTEMPTY;
+ goto leave;
+ } else if (inode->i_nlink != 2) {
+ status = -ENOTEMPTY;
+ goto leave;
+ }
+ }
+
+ /* There are still a few steps left until we can consider the
+ * unlink to have succeeded. Save off nlink here before
+ * modification so we can set it back in case we hit an issue
+ * before commit. */
+ saved_nlink = inode->i_nlink;
+ if (S_ISDIR(inode->i_mode))
+ inode->i_nlink = 0;
+ else
+ inode->i_nlink--;
+
+ status = ocfs2_request_unlink_vote(inode, dentry,
+ (unsigned int) inode->i_nlink);
+ if (status < 0) {
+ /* This vote should succeed under all normal
+ * circumstances. */
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (!inode->i_nlink) {
+ status = ocfs2_prepare_orphan_dir(osb, handle, inode,
+ orphan_name,
+ &orphan_entry_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_UNLINK_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_journal_access(handle, inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ fe = (struct ocfs2_dinode *) fe_bh->b_data;
+
+ if (!inode->i_nlink) {
+ status = ocfs2_orphan_add(osb, handle, inode, fe, orphan_name,
+ orphan_entry_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+ }
+
+ /* delete the name from the parent dir */
+ status = ocfs2_delete_entry(handle, dir, dirent, dirent_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* We can set nlink on the dinode now. clear the saved version
+ * so that it doesn't get set later. */
+ fe->i_links_count = cpu_to_le16(inode->i_nlink);
+ saved_nlink = 0;
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ if (S_ISDIR(inode->i_mode)) {
+ dir->i_nlink--;
+ status = ocfs2_mark_inode_dirty(handle, dir,
+ parent_node_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ dir->i_nlink++;
+ }
+ }
+
+leave:
+ if (status < 0 && saved_nlink)
+ inode->i_nlink = saved_nlink;
+
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (fe_bh)
+ brelse(fe_bh);
+
+ if (dirent_bh)
+ brelse(dirent_bh);
+
+ if (parent_node_bh)
+ brelse(parent_node_bh);
+
+ if (orphan_entry_bh)
+ brelse(orphan_entry_bh);
+
+ mlog_exit(status);
+
+ return status;
+}
+
+/*
+ * The only place this should be used is rename!
+ * if they have the same id, then the 1st one is the only one locked.
+ */
+static int ocfs2_double_lock(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct buffer_head **bh1,
+ struct inode *inode1,
+ struct buffer_head **bh2,
+ struct inode *inode2)
+{
+ int status;
+ struct ocfs2_inode_info *oi1 = OCFS2_I(inode1);
+ struct ocfs2_inode_info *oi2 = OCFS2_I(inode2);
+ struct buffer_head **tmpbh;
+ struct inode *tmpinode;
+
+ mlog_entry("(inode1 = %"MLFu64", inode2 = %"MLFu64")\n",
+ oi1->ip_blkno, oi2->ip_blkno);
+
+ BUG_ON(!handle);
+
+ if (*bh1)
+ *bh1 = NULL;
+ if (*bh2)
+ *bh2 = NULL;
+
+ /* we always want to lock the one with the lower lockid first. */
+ if (oi1->ip_blkno != oi2->ip_blkno) {
+ if (oi1->ip_blkno < oi2->ip_blkno) {
+ /* switch id1 and id2 around */
+ mlog(0, "switching them around...\n");
+ tmpbh = bh2;
+ bh2 = bh1;
+ bh1 = tmpbh;
+
+ tmpinode = inode2;
+ inode2 = inode1;
+ inode1 = tmpinode;
+ }
+ /* lock id2 */
+ status = ocfs2_meta_lock(inode2, handle, bh2, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ /* lock id1 */
+ status = ocfs2_meta_lock(inode1, handle, bh1, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+#define PARENT_INO(buffer) \
+ ((struct ocfs2_dir_entry *) \
+ ((char *)buffer + \
+ le16_to_cpu(((struct ocfs2_dir_entry *)buffer)->rec_len)))->inode
+
+static int ocfs2_rename(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+ struct dentry *new_dentry)
+{
+ int status = 0, rename_lock = 0;
+ struct inode *old_inode = old_dentry->d_inode;
+ struct inode *new_inode = new_dentry->d_inode;
+ struct ocfs2_dinode *newfe = NULL;
+ char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
+ struct buffer_head *orphan_entry_bh = NULL;
+ struct buffer_head *newfe_bh = NULL;
+ struct buffer_head *insert_entry_bh = NULL;
+ struct ocfs2_super *osb = NULL;
+ u64 newfe_blkno;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct buffer_head *old_dir_bh = NULL;
+ struct buffer_head *new_dir_bh = NULL;
+ struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry
+ // and new_dentry
+ struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
+ struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
+ // this is the 1st dirent bh
+ nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
+ unsigned int links_count;
+
+ /* At some point it might be nice to break this function up a
+ * bit. */
+
+ mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n",
+ old_dir, old_dentry, new_dir, new_dentry,
+ old_dentry->d_name.len, old_dentry->d_name.name,
+ new_dentry->d_name.len, new_dentry->d_name.name);
+
+ osb = OCFS2_SB(old_dir->i_sb);
+
+ if (new_inode) {
+ if (!igrab(new_inode))
+ BUG();
+ }
+
+ if (atomic_read(&old_dentry->d_count) > 2) {
+ shrink_dcache_parent(old_dentry);
+ if (atomic_read(&old_dentry->d_count) > 2) {
+ status = -EBUSY;
+ goto bail;
+ }
+ }
+
+ /* Assume a directory heirarchy thusly:
+ * a/b/c
+ * a/d
+ * a,b,c, and d are all directories.
+ *
+ * from cwd of 'a' on both nodes:
+ * node1: mv b/c d
+ * node2: mv d b/c
+ *
+ * And that's why, just like the VFS, we need a file system
+ * rename lock. */
+ if (old_dentry != new_dentry) {
+ status = ocfs2_rename_lock(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ rename_lock = 1;
+ }
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* if old and new are the same, this'll just do one lock. */
+ status = ocfs2_double_lock(osb, handle,
+ &old_dir_bh, old_dir,
+ &new_dir_bh, new_dir);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* make sure both dirs have bhs
+ * get an extra ref on old_dir_bh if old==new */
+ if (!new_dir_bh) {
+ if (old_dir_bh) {
+ new_dir_bh = old_dir_bh;
+ get_bh(new_dir_bh);
+ } else {
+ mlog(ML_ERROR, "no old_dir_bh!\n");
+ status = -EIO;
+ goto bail;
+ }
+ }
+
+ if (S_ISDIR(old_inode->i_mode)) {
+ /* Directories actually require metadata updates to
+ * the directory info so we can't get away with not
+ * doing node locking on it. */
+ status = ocfs2_meta_lock(old_inode, handle, NULL, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_request_rename_vote(old_inode, old_dentry);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = -EIO;
+ old_inode_de_bh = ocfs2_bread(old_inode, 0, &status, 0);
+ if (!old_inode_de_bh)
+ goto bail;
+
+ status = -EIO;
+ if (le64_to_cpu(PARENT_INO(old_inode_de_bh->b_data)) !=
+ OCFS2_I(old_dir)->ip_blkno)
+ goto bail;
+ status = -EMLINK;
+ if (!new_inode && new_dir!=old_dir &&
+ new_dir->i_nlink >= OCFS2_LINK_MAX)
+ goto bail;
+ } else {
+ /* Ah, the simple case - we're a file so just send a
+ * message. */
+ status = ocfs2_request_rename_vote(old_inode, old_dentry);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = -ENOENT;
+ old_de_bh = ocfs2_find_entry(old_dentry->d_name.name,
+ old_dentry->d_name.len,
+ old_dir, &old_de);
+ if (!old_de_bh)
+ goto bail;
+
+ /*
+ * Check for inode number is _not_ due to possible IO errors.
+ * We might rmdir the source, keep it as pwd of some process
+ * and merrily kill the link to whatever was created under the
+ * same name. Goodbye sticky bit ;-<
+ */
+ if (le64_to_cpu(old_de->inode) != OCFS2_I(old_inode)->ip_blkno)
+ goto bail;
+
+ /* check if the target already exists (in which case we need
+ * to delete it */
+ status = ocfs2_find_files_on_disk(new_dentry->d_name.name,
+ new_dentry->d_name.len,
+ &newfe_blkno, new_dir, &new_de_bh,
+ &new_de);
+ /* The only error we allow here is -ENOENT because the new
+ * file not existing is perfectly valid. */
+ if ((status < 0) && (status != -ENOENT)) {
+ /* If we cannot find the file specified we should just */
+ /* return the error... */
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (!new_de && new_inode)
+ mlog(ML_ERROR, "inode %lu does not exist in it's parent "
+ "directory!", new_inode->i_ino);
+
+ /* In case we need to overwrite an existing file, we blow it
+ * away first */
+ if (new_de) {
+ /* VFS didn't think there existed an inode here, but
+ * someone else in the cluster must have raced our
+ * rename to create one. Today we error cleanly, in
+ * the future we should consider calling iget to build
+ * a new struct inode for this entry. */
+ if (!new_inode) {
+ status = -EACCES;
+
+ mlog(0, "We found an inode for name %.*s but VFS "
+ "didn't give us one.\n", new_dentry->d_name.len,
+ new_dentry->d_name.name);
+ goto bail;
+ }
+
+ if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) {
+ status = -EACCES;
+
+ mlog(0, "Inode blkno (%"MLFu64") and dir (%"MLFu64") "
+ "disagree. ip_flags = %x\n",
+ OCFS2_I(new_inode)->ip_blkno, newfe_blkno,
+ OCFS2_I(new_inode)->ip_flags);
+ goto bail;
+ }
+
+ status = ocfs2_meta_lock(new_inode, handle, &newfe_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (S_ISDIR(new_inode->i_mode))
+ links_count = 0;
+ else
+ links_count = (unsigned int) (new_inode->i_nlink - 1);
+
+ status = ocfs2_request_unlink_vote(new_inode, new_dentry,
+ links_count);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ newfe = (struct ocfs2_dinode *) newfe_bh->b_data;
+
+ mlog(0, "aha rename over existing... new_de=%p "
+ "new_blkno=%"MLFu64" newfebh=%p bhblocknr=%llu\n",
+ new_de, newfe_blkno, newfe_bh, newfe_bh ?
+ (unsigned long long)newfe_bh->b_blocknr : 0ULL);
+
+ if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
+ status = ocfs2_prepare_orphan_dir(osb, handle,
+ new_inode,
+ orphan_name,
+ &orphan_entry_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ } else {
+ BUG_ON(new_dentry->d_parent->d_inode != new_dir);
+
+ status = ocfs2_check_dir_for_entry(new_dir,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len);
+ if (status)
+ goto bail;
+
+ status = ocfs2_prepare_dir_for_insert(osb, new_dir, new_dir_bh,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len,
+ &insert_entry_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, handle, OCFS2_RENAME_CREDITS);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (new_de) {
+ if (S_ISDIR(new_inode->i_mode)) {
+ if (!ocfs2_empty_dir(new_inode) ||
+ new_inode->i_nlink != 2) {
+ status = -ENOTEMPTY;
+ goto bail;
+ }
+ }
+ status = ocfs2_journal_access(handle, new_inode, newfe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (S_ISDIR(new_inode->i_mode) ||
+ (newfe->i_links_count == cpu_to_le16(1))){
+ status = ocfs2_orphan_add(osb, handle, new_inode,
+ newfe, orphan_name,
+ orphan_entry_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ /* change the dirent to point to the correct inode */
+ status = ocfs2_journal_access(handle, new_dir, new_de_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ new_de->inode = cpu_to_le64(OCFS2_I(old_inode)->ip_blkno);
+ new_de->file_type = old_de->file_type;
+ new_dir->i_version++;
+ status = ocfs2_journal_dirty(handle, new_de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (S_ISDIR(new_inode->i_mode))
+ newfe->i_links_count = 0;
+ else
+ le16_add_cpu(&newfe->i_links_count, -1);
+
+ status = ocfs2_journal_dirty(handle, newfe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ } else {
+ /* if the name was not found in new_dir, add it now */
+ status = ocfs2_add_entry(handle, new_dentry, old_inode,
+ OCFS2_I(old_inode)->ip_blkno,
+ new_dir_bh, insert_entry_bh);
+ }
+
+ old_inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(old_inode);
+
+ /* now that the name has been added to new_dir, remove the old name */
+ status = ocfs2_delete_entry(handle, old_dir, old_de, old_de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (new_inode) {
+ new_inode->i_nlink--;
+ new_inode->i_ctime = CURRENT_TIME;
+ }
+ old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+ if (old_inode_de_bh) {
+ status = ocfs2_journal_access(handle, old_inode,
+ old_inode_de_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ PARENT_INO(old_inode_de_bh->b_data) =
+ cpu_to_le64(OCFS2_I(new_dir)->ip_blkno);
+ status = ocfs2_journal_dirty(handle, old_inode_de_bh);
+ old_dir->i_nlink--;
+ if (new_inode) {
+ new_inode->i_nlink--;
+ } else {
+ new_dir->i_nlink++;
+ mark_inode_dirty(new_dir);
+ }
+ }
+ mark_inode_dirty(old_dir);
+ if (new_inode)
+ mark_inode_dirty(new_inode);
+
+ if (old_dir != new_dir)
+ if (new_dir_nlink != new_dir->i_nlink) {
+ if (!new_dir_bh) {
+ mlog(ML_ERROR, "need to change nlink for new "
+ "dir %"MLFu64" from %d to %d but bh is "
+ "NULL\n", OCFS2_I(new_dir)->ip_blkno,
+ (int)new_dir_nlink, new_dir->i_nlink);
+ } else {
+ struct ocfs2_dinode *fe;
+ status = ocfs2_journal_access(handle,
+ new_dir,
+ new_dir_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ fe = (struct ocfs2_dinode *) new_dir_bh->b_data;
+ fe->i_links_count = cpu_to_le16(new_dir->i_nlink);
+ status = ocfs2_journal_dirty(handle, new_dir_bh);
+ }
+ }
+
+ if (old_dir_nlink != old_dir->i_nlink) {
+ if (!old_dir_bh) {
+ mlog(ML_ERROR, "need to change nlink for old dir "
+ "%"MLFu64" from %d to %d but bh is NULL!\n",
+ OCFS2_I(old_dir)->ip_blkno,
+ (int)old_dir_nlink,
+ old_dir->i_nlink);
+ } else {
+ struct ocfs2_dinode *fe;
+ status = ocfs2_journal_access(handle, old_dir,
+ old_dir_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
+ fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
+ status = ocfs2_journal_dirty(handle, old_dir_bh);
+ }
+ }
+
+ status = 0;
+bail:
+ if (rename_lock)
+ ocfs2_rename_unlock(osb);
+
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (new_inode)
+ sync_mapping_buffers(old_inode->i_mapping);
+
+ if (new_inode)
+ iput(new_inode);
+ if (newfe_bh)
+ brelse(newfe_bh);
+ if (old_dir_bh)
+ brelse(old_dir_bh);
+ if (new_dir_bh)
+ brelse(new_dir_bh);
+ if (new_de_bh)
+ brelse(new_de_bh);
+ if (old_de_bh)
+ brelse(old_de_bh);
+ if (old_inode_de_bh)
+ brelse(old_inode_de_bh);
+ if (orphan_entry_bh)
+ brelse(orphan_entry_bh);
+ if (insert_entry_bh)
+ brelse(insert_entry_bh);
+
+ mlog_exit(status);
+
+ return status;
+}
+
+/*
+ * we expect i_size = strlen(symname). Copy symname into the file
+ * data, including the null terminator.
+ */
+static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ const char *symname)
+{
+ struct buffer_head **bhs = NULL;
+ const char *c;
+ struct super_block *sb = osb->sb;
+ u64 p_blkno;
+ int p_blocks;
+ int virtual, blocks, status, i, bytes_left;
+
+ bytes_left = i_size_read(inode) + 1;
+ /* we can't trust i_blocks because we're actually going to
+ * write i_size + 1 bytes. */
+ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+
+ mlog_entry("i_blocks = %lu, i_size = %llu, blocks = %d\n",
+ inode->i_blocks, i_size_read(inode), blocks);
+
+ /* Sanity check -- make sure we're going to fit. */
+ if (bytes_left >
+ ocfs2_clusters_to_bytes(sb, OCFS2_I(inode)->ip_clusters)) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bhs = kcalloc(blocks, sizeof(struct buffer_head *), GFP_KERNEL);
+ if (!bhs) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_extent_map_get_blocks(inode, 0, 1, &p_blkno,
+ &p_blocks);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* links can never be larger than one cluster so we know this
+ * is all going to be contiguous, but do a sanity check
+ * anyway. */
+ if ((p_blocks << sb->s_blocksize_bits) < bytes_left) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ virtual = 0;
+ while(bytes_left > 0) {
+ c = &symname[virtual * sb->s_blocksize];
+
+ bhs[virtual] = sb_getblk(sb, p_blkno);
+ if (!bhs[virtual]) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_set_new_buffer_uptodate(inode, bhs[virtual]);
+
+ status = ocfs2_journal_access(handle, inode, bhs[virtual],
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ memset(bhs[virtual]->b_data, 0, sb->s_blocksize);
+
+ memcpy(bhs[virtual]->b_data, c,
+ (bytes_left > sb->s_blocksize) ? sb->s_blocksize :
+ bytes_left);
+
+ status = ocfs2_journal_dirty(handle, bhs[virtual]);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ virtual++;
+ p_blkno++;
+ bytes_left -= sb->s_blocksize;
+ }
+
+ status = 0;
+bail:
+
+ if (bhs) {
+ for(i = 0; i < blocks; i++)
+ if (bhs[i])
+ brelse(bhs[i]);
+ kfree(bhs);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_symlink(struct inode *dir,
+ struct dentry *dentry,
+ const char *symname)
+{
+ int status, l, credits;
+ u64 newsize;
+ struct ocfs2_super *osb = NULL;
+ struct inode *inode = NULL;
+ struct super_block *sb;
+ struct buffer_head *new_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
+ struct buffer_head *parent_fe_bh = NULL;
+ struct ocfs2_dinode *fe = NULL;
+ struct ocfs2_dinode *dirfe;
+ struct ocfs2_journal_handle *handle = NULL;
+ struct ocfs2_alloc_context *inode_ac = NULL;
+ struct ocfs2_alloc_context *data_ac = NULL;
+
+ mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
+ dentry, symname, dentry->d_name.len, dentry->d_name.name);
+
+ sb = dir->i_sb;
+ osb = OCFS2_SB(sb);
+
+ l = strlen(symname) + 1;
+
+ credits = ocfs2_calc_symlink_credits(sb);
+
+ handle = ocfs2_alloc_handle(osb);
+ if (handle == NULL) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* lock the parent directory */
+ status = ocfs2_meta_lock(dir, handle, &parent_fe_bh, 1);
+ if (status < 0) {
+ if (status != -ENOENT)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
+ if (!dirfe->i_links_count) {
+ /* can't make a file in a deleted directory. */
+ status = -ENOENT;
+ goto bail;
+ }
+
+ status = ocfs2_check_dir_for_entry(dir, dentry->d_name.name,
+ dentry->d_name.len);
+ if (status)
+ goto bail;
+
+ status = ocfs2_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_reserve_new_inode(osb, handle, &inode_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* don't reserve bitmap space for fast symlinks. */
+ if (l > ocfs2_fast_symlink_chars(sb)) {
+ status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ handle = ocfs2_start_trans(osb, handle, credits);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_mknod_locked(osb, dir, dentry,
+ S_IFLNK | S_IRWXUGO, 0,
+ &new_fe_bh, parent_fe_bh, handle,
+ &inode, inode_ac);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) new_fe_bh->b_data;
+ inode->i_rdev = 0;
+ newsize = l - 1;
+ if (l > ocfs2_fast_symlink_chars(sb)) {
+ inode->i_op = &ocfs2_symlink_inode_operations;
+ status = ocfs2_do_extend_allocation(osb, inode, 1, new_fe_bh,
+ handle, data_ac, NULL,
+ NULL);
+ if (status < 0) {
+ if (status != -ENOSPC && status != -EINTR) {
+ mlog(ML_ERROR, "Failed to extend file to "
+ "%"MLFu64"\n",
+ newsize);
+ mlog_errno(status);
+ status = -ENOSPC;
+ }
+ goto bail;
+ }
+ i_size_write(inode, newsize);
+ inode->i_blocks = ocfs2_align_bytes_to_sectors(newsize);
+ } else {
+ inode->i_op = &ocfs2_fast_symlink_inode_operations;
+ memcpy((char *) fe->id2.i_symlink, symname, l);
+ i_size_write(inode, newsize);
+ inode->i_blocks = 0;
+ }
+
+ status = ocfs2_mark_inode_dirty(handle, inode, new_fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (!ocfs2_inode_is_fast_symlink(inode)) {
+ status = ocfs2_create_symlink_data(osb, handle, inode,
+ symname);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = ocfs2_add_entry(handle, dentry, inode,
+ le64_to_cpu(fe->i_blkno), parent_fe_bh,
+ de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ insert_inode_hash(inode);
+ dentry->d_op = &ocfs2_dentry_ops;
+ d_instantiate(dentry, inode);
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+ if (new_fe_bh)
+ brelse(new_fe_bh);
+ if (parent_fe_bh)
+ brelse(parent_fe_bh);
+ if (de_bh)
+ brelse(de_bh);
+ if (inode_ac)
+ ocfs2_free_alloc_context(inode_ac);
+ if (data_ac)
+ ocfs2_free_alloc_context(data_ac);
+ if ((status < 0) && inode)
+ iput(inode);
+
+ mlog_exit(status);
+
+ return status;
+}
+
+int ocfs2_check_dir_entry(struct inode * dir,
+ struct ocfs2_dir_entry * de,
+ struct buffer_head * bh,
+ unsigned long offset)
+{
+ const char *error_msg = NULL;
+ const int rlen = le16_to_cpu(de->rec_len);
+
+ if (rlen < OCFS2_DIR_REC_LEN(1))
+ error_msg = "rec_len is smaller than minimal";
+ else if (rlen % 4 != 0)
+ error_msg = "rec_len % 4 != 0";
+ else if (rlen < OCFS2_DIR_REC_LEN(de->name_len))
+ error_msg = "rec_len is too small for name_len";
+ else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+ error_msg = "directory entry across blocks";
+
+ if (error_msg != NULL)
+ mlog(ML_ERROR, "bad entry in directory #%"MLFu64": %s - "
+ "offset=%lu, inode=%"MLFu64", rec_len=%d, name_len=%d\n",
+ OCFS2_I(dir)->ip_blkno, error_msg, offset,
+ le64_to_cpu(de->inode), rlen, de->name_len);
+ return error_msg == NULL ? 1 : 0;
+}
+
+/* we don't always have a dentry for what we want to add, so people
+ * like orphan dir can call this instead.
+ *
+ * If you pass me insert_bh, I'll skip the search of the other dir
+ * blocks and put the record in there.
+ */
+static int __ocfs2_add_entry(struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ const char *name, int namelen,
+ struct inode *inode, u64 blkno,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh)
+{
+ unsigned long offset;
+ unsigned short rec_len;
+ struct ocfs2_dir_entry *de, *de1;
+ struct super_block *sb;
+ int retval, status;
+
+ mlog_entry_void();
+
+ sb = dir->i_sb;
+
+ if (!namelen)
+ return -EINVAL;
+
+ rec_len = OCFS2_DIR_REC_LEN(namelen);
+ offset = 0;
+ de = (struct ocfs2_dir_entry *) insert_bh->b_data;
+ while (1) {
+ BUG_ON((char *)de >= sb->s_blocksize + insert_bh->b_data);
+ /* These checks should've already been passed by the
+ * prepare function, but I guess we can leave them
+ * here anyway. */
+ if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) {
+ retval = -ENOENT;
+ goto bail;
+ }
+ if (ocfs2_match(namelen, name, de)) {
+ retval = -EEXIST;
+ goto bail;
+ }
+ if (((le64_to_cpu(de->inode) == 0) &&
+ (le16_to_cpu(de->rec_len) >= rec_len)) ||
+ (le16_to_cpu(de->rec_len) >=
+ (OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
+ status = ocfs2_journal_access(handle, dir, insert_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ /* By now the buffer is marked for journaling */
+ offset += le16_to_cpu(de->rec_len);
+ if (le64_to_cpu(de->inode)) {
+ de1 = (struct ocfs2_dir_entry *)((char *) de +
+ OCFS2_DIR_REC_LEN(de->name_len));
+ de1->rec_len =
+ cpu_to_le16(le16_to_cpu(de->rec_len) -
+ OCFS2_DIR_REC_LEN(de->name_len));
+ de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
+ de = de1;
+ }
+ de->file_type = OCFS2_FT_UNKNOWN;
+ if (blkno) {
+ de->inode = cpu_to_le64(blkno);
+ ocfs2_set_de_type(de, inode->i_mode);
+ } else
+ de->inode = 0;
+ de->name_len = namelen;
+ memcpy(de->name, name, namelen);
+
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_version++;
+ status = ocfs2_journal_dirty(handle, insert_bh);
+ retval = 0;
+ goto bail;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+ }
+
+ /* when you think about it, the assert above should prevent us
+ * from ever getting here. */
+ retval = -ENOSPC;
+bail:
+
+ mlog_exit(retval);
+ return retval;
+}
+
+
+/*
+ * ocfs2_delete_entry deletes a directory entry by merging it with the
+ * previous entry
+ */
+static int ocfs2_delete_entry(struct ocfs2_journal_handle *handle,
+ struct inode *dir,
+ struct ocfs2_dir_entry *de_del,
+ struct buffer_head *bh)
+{
+ struct ocfs2_dir_entry *de, *pde;
+ int i, status = -ENOENT;
+
+ mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh);
+
+ i = 0;
+ pde = NULL;
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ while (i < bh->b_size) {
+ if (!ocfs2_check_dir_entry(dir, de, bh, i)) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ if (de == de_del) {
+ status = ocfs2_journal_access(handle, dir, bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ if (pde)
+ pde->rec_len =
+ cpu_to_le16(le16_to_cpu(pde->rec_len) +
+ le16_to_cpu(de->rec_len));
+ else
+ de->inode = 0;
+ dir->i_version++;
+ status = ocfs2_journal_dirty(handle, bh);
+ goto bail;
+ }
+ i += le16_to_cpu(de->rec_len);
+ pde = de;
+ de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
+ }
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * Returns 0 if not found, -1 on failure, and 1 on success
+ */
+static int inline ocfs2_search_dirblock(struct buffer_head *bh,
+ struct inode *dir,
+ const char *name, int namelen,
+ unsigned long offset,
+ struct ocfs2_dir_entry **res_dir)
+{
+ struct ocfs2_dir_entry *de;
+ char *dlimit, *de_buf;
+ int de_len;
+ int ret = 0;
+
+ mlog_entry_void();
+
+ de_buf = bh->b_data;
+ dlimit = de_buf + dir->i_sb->s_blocksize;
+
+ while (de_buf < dlimit) {
+ /* this code is executed quadratically often */
+ /* do minimal checking `by hand' */
+
+ de = (struct ocfs2_dir_entry *) de_buf;
+
+ if (de_buf + namelen <= dlimit &&
+ ocfs2_match(namelen, name, de)) {
+ /* found a match - just to be sure, do a full check */
+ if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
+ ret = -1;
+ goto bail;
+ }
+ *res_dir = de;
+ ret = 1;
+ goto bail;
+ }
+
+ /* prevent looping on a bad block */
+ de_len = le16_to_cpu(de->rec_len);
+ if (de_len <= 0) {
+ ret = -1;
+ goto bail;
+ }
+
+ de_buf += de_len;
+ offset += de_len;
+ }
+
+bail:
+ mlog_exit(ret);
+ return ret;
+}
+
+struct buffer_head *ocfs2_find_entry(const char *name, int namelen,
+ struct inode *dir,
+ struct ocfs2_dir_entry **res_dir)
+{
+ struct super_block *sb;
+ struct buffer_head *bh_use[NAMEI_RA_SIZE];
+ struct buffer_head *bh, *ret = NULL;
+ unsigned long start, block, b;
+ int ra_max = 0; /* Number of bh's in the readahead
+ buffer, bh_use[] */
+ int ra_ptr = 0; /* Current index into readahead
+ buffer */
+ int num = 0;
+ int nblocks, i, err;
+
+ mlog_entry_void();
+
+ *res_dir = NULL;
+ sb = dir->i_sb;
+
+ nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
+ start = OCFS2_I(dir)->ip_dir_start_lookup;
+ if (start >= nblocks)
+ start = 0;
+ block = start;
+
+restart:
+ do {
+ /*
+ * We deal with the read-ahead logic here.
+ */
+ if (ra_ptr >= ra_max) {
+ /* Refill the readahead buffer */
+ ra_ptr = 0;
+ b = block;
+ for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
+ /*
+ * Terminate if we reach the end of the
+ * directory and must wrap, or if our
+ * search has finished at this block.
+ */
+ if (b >= nblocks || (num && block == start)) {
+ bh_use[ra_max] = NULL;
+ break;
+ }
+ num++;
+
+ /* XXX: questionable readahead stuff here */
+ bh = ocfs2_bread(dir, b++, &err, 1);
+ bh_use[ra_max] = bh;
+#if 0 // ???
+ if (bh)
+ ll_rw_block(READ, 1, &bh);
+#endif
+ }
+ }
+ if ((bh = bh_use[ra_ptr++]) == NULL)
+ goto next;
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ /* read error, skip block & hope for the best */
+ brelse(bh);
+ goto next;
+ }
+ i = ocfs2_search_dirblock(bh, dir, name, namelen,
+ block << sb->s_blocksize_bits,
+ res_dir);
+ if (i == 1) {
+ OCFS2_I(dir)->ip_dir_start_lookup = block;
+ ret = bh;
+ goto cleanup_and_exit;
+ } else {
+ brelse(bh);
+ if (i < 0)
+ goto cleanup_and_exit;
+ }
+ next:
+ if (++block >= nblocks)
+ block = 0;
+ } while (block != start);
+
+ /*
+ * If the directory has grown while we were searching, then
+ * search the last part of the directory before giving up.
+ */
+ block = nblocks;
+ nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
+ if (block < nblocks) {
+ start = 0;
+ goto restart;
+ }
+
+cleanup_and_exit:
+ /* Clean up the read-ahead blocks */
+ for (; ra_ptr < ra_max; ra_ptr++)
+ brelse(bh_use[ra_ptr]);
+
+ mlog_exit_ptr(ret);
+ return ret;
+}
+
+static int ocfs2_blkno_stringify(u64 blkno, char *name)
+{
+ int status, namelen;
+
+ mlog_entry_void();
+
+ namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016"MLFx64,
+ blkno);
+ if (namelen <= 0) {
+ if (namelen)
+ status = namelen;
+ else
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+ if (namelen != OCFS2_ORPHAN_NAMELEN) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "built filename '%s' for orphan dir (len=%d)\n", name,
+ namelen);
+
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_prepare_orphan_dir(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ char *name,
+ struct buffer_head **de_bh)
+{
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ int status = 0;
+
+ status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ orphan_dir_inode = ocfs2_get_system_file_inode(osb,
+ ORPHAN_DIR_SYSTEM_INODE,
+ osb->slot_num);
+ if (!orphan_dir_inode) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ ocfs2_handle_add_inode(handle, orphan_dir_inode);
+ status = ocfs2_meta_lock(orphan_dir_inode, handle, &orphan_dir_bh, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_prepare_dir_for_insert(osb, orphan_dir_inode,
+ orphan_dir_bh, name,
+ OCFS2_ORPHAN_NAMELEN, de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+leave:
+ if (orphan_dir_inode)
+ iput(orphan_dir_inode);
+
+ if (orphan_dir_bh)
+ brelse(orphan_dir_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_orphan_add(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *inode,
+ struct ocfs2_dinode *fe,
+ char *name,
+ struct buffer_head *de_bh)
+{
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ int status = 0;
+ struct ocfs2_dinode *orphan_fe;
+
+ mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
+
+ orphan_dir_inode = ocfs2_get_system_file_inode(osb,
+ ORPHAN_DIR_SYSTEM_INODE,
+ osb->slot_num);
+ if (!orphan_dir_inode) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_read_block(osb,
+ OCFS2_I(orphan_dir_inode)->ip_blkno,
+ &orphan_dir_bh, OCFS2_BH_CACHED,
+ orphan_dir_inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_journal_access(handle, orphan_dir_inode, orphan_dir_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* we're a cluster, and nlink can change on disk from
+ * underneath us... */
+ orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
+ if (S_ISDIR(inode->i_mode))
+ le16_add_cpu(&orphan_fe->i_links_count, 1);
+ orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+
+ status = ocfs2_journal_dirty(handle, orphan_dir_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = __ocfs2_add_entry(handle, orphan_dir_inode, name,
+ OCFS2_ORPHAN_NAMELEN, inode,
+ OCFS2_I(inode)->ip_blkno,
+ orphan_dir_bh, de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ le32_add_cpu(&fe->i_flags, OCFS2_ORPHANED_FL);
+
+ /* Record which orphan dir our inode now resides
+ * in. delete_inode will use this to determine which orphan
+ * dir to lock. */
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ OCFS2_I(inode)->ip_orphaned_slot = osb->slot_num;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ mlog(0, "Inode %"MLFu64" orphaned in slot %d\n",
+ OCFS2_I(inode)->ip_blkno, osb->slot_num);
+
+leave:
+ if (orphan_dir_inode)
+ iput(orphan_dir_inode);
+
+ if (orphan_dir_bh)
+ brelse(orphan_dir_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* unlike orphan_add, we expect the orphan dir to already be locked here. */
+int ocfs2_orphan_del(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *orphan_dir_inode,
+ struct inode *inode,
+ struct buffer_head *orphan_dir_bh)
+{
+ char name[OCFS2_ORPHAN_NAMELEN + 1];
+ struct ocfs2_dinode *orphan_fe;
+ int status = 0;
+ struct buffer_head *target_de_bh = NULL;
+ struct ocfs2_dir_entry *target_de = NULL;
+
+ mlog_entry_void();
+
+ status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ mlog(0, "removing '%s' from orphan dir %"MLFu64" (namelen=%d)\n",
+ name, OCFS2_I(orphan_dir_inode)->ip_blkno, OCFS2_ORPHAN_NAMELEN);
+
+ /* find it's spot in the orphan directory */
+ target_de_bh = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN,
+ orphan_dir_inode, &target_de);
+ if (!target_de_bh) {
+ status = -ENOENT;
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* remove it from the orphan directory */
+ status = ocfs2_delete_entry(handle, orphan_dir_inode, target_de,
+ target_de_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_journal_access(handle,orphan_dir_inode, orphan_dir_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* do the i_nlink dance! :) */
+ orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
+ if (S_ISDIR(inode->i_mode))
+ le16_add_cpu(&orphan_fe->i_links_count, -1);
+ orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
+
+ status = ocfs2_journal_dirty(handle, orphan_dir_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+leave:
+ if (target_de_bh)
+ brelse(target_de_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+struct inode_operations ocfs2_dir_iops = {
+ .create = ocfs2_create,
+ .lookup = ocfs2_lookup,
+ .link = ocfs2_link,
+ .unlink = ocfs2_unlink,
+ .rmdir = ocfs2_unlink,
+ .symlink = ocfs2_symlink,
+ .mkdir = ocfs2_mkdir,
+ .mknod = ocfs2_mknod,
+ .rename = ocfs2_rename,
+ .setattr = ocfs2_setattr,
+ .getattr = ocfs2_getattr,
+};
diff --git a/fs/ocfs2/namei.h b/fs/ocfs2/namei.h
new file mode 100644
index 000000000000..deaaa97dbf0b
--- /dev/null
+++ b/fs/ocfs2/namei.h
@@ -0,0 +1,58 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * namei.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_NAMEI_H
+#define OCFS2_NAMEI_H
+
+extern struct inode_operations ocfs2_dir_iops;
+
+struct dentry *ocfs2_get_parent(struct dentry *child);
+
+int ocfs2_check_dir_entry (struct inode *dir,
+ struct ocfs2_dir_entry *de,
+ struct buffer_head *bh,
+ unsigned long offset);
+struct buffer_head *ocfs2_find_entry(const char *name,
+ int namelen,
+ struct inode *dir,
+ struct ocfs2_dir_entry **res_dir);
+int ocfs2_orphan_del(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct inode *orphan_dir_inode,
+ struct inode *inode,
+ struct buffer_head *orphan_dir_bh);
+
+static inline int ocfs2_match(int len,
+ const char * const name,
+ struct ocfs2_dir_entry *de)
+{
+ if (len != de->name_len)
+ return 0;
+ if (!de->inode)
+ return 0;
+ return !memcmp(name, de->name, len);
+}
+
+#endif /* OCFS2_NAMEI_H */
diff --git a/fs/ocfs2/ocfs1_fs_compat.h b/fs/ocfs2/ocfs1_fs_compat.h
new file mode 100644
index 000000000000..0b499bccec5a
--- /dev/null
+++ b/fs/ocfs2/ocfs1_fs_compat.h
@@ -0,0 +1,109 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs1_fs_compat.h
+ *
+ * OCFS1 volume header definitions. OCFS2 creates valid but unmountable
+ * OCFS1 volume headers on the first two sectors of an OCFS2 volume.
+ * This allows an OCFS1 volume to see the partition and cleanly fail to
+ * mount it.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef _OCFS1_FS_COMPAT_H
+#define _OCFS1_FS_COMPAT_H
+
+#define OCFS1_MAX_VOL_SIGNATURE_LEN 128
+#define OCFS1_MAX_MOUNT_POINT_LEN 128
+#define OCFS1_MAX_VOL_ID_LENGTH 16
+#define OCFS1_MAX_VOL_LABEL_LEN 64
+#define OCFS1_MAX_CLUSTER_NAME_LEN 64
+
+#define OCFS1_MAJOR_VERSION (2)
+#define OCFS1_MINOR_VERSION (0)
+#define OCFS1_VOLUME_SIGNATURE "OracleCFS"
+
+/*
+ * OCFS1 superblock. Lives at sector 0.
+ */
+struct ocfs1_vol_disk_hdr
+{
+/*00*/ __u32 minor_version;
+ __u32 major_version;
+/*08*/ __u8 signature[OCFS1_MAX_VOL_SIGNATURE_LEN];
+/*88*/ __u8 mount_point[OCFS1_MAX_MOUNT_POINT_LEN];
+/*108*/ __u64 serial_num;
+/*110*/ __u64 device_size;
+ __u64 start_off;
+/*120*/ __u64 bitmap_off;
+ __u64 publ_off;
+/*130*/ __u64 vote_off;
+ __u64 root_bitmap_off;
+/*140*/ __u64 data_start_off;
+ __u64 root_bitmap_size;
+/*150*/ __u64 root_off;
+ __u64 root_size;
+/*160*/ __u64 cluster_size;
+ __u64 num_nodes;
+/*170*/ __u64 num_clusters;
+ __u64 dir_node_size;
+/*180*/ __u64 file_node_size;
+ __u64 internal_off;
+/*190*/ __u64 node_cfg_off;
+ __u64 node_cfg_size;
+/*1A0*/ __u64 new_cfg_off;
+ __u32 prot_bits;
+ __s32 excl_mount;
+/*1B0*/
+};
+
+
+struct ocfs1_disk_lock
+{
+/*00*/ __u32 curr_master;
+ __u8 file_lock;
+ __u8 compat_pad[3]; /* Not in orignal definition. Used to
+ make the already existing alignment
+ explicit */
+ __u64 last_write_time;
+/*10*/ __u64 last_read_time;
+ __u32 writer_node_num;
+ __u32 reader_node_num;
+/*20*/ __u64 oin_node_map;
+ __u64 dlock_seq_num;
+/*30*/
+};
+
+/*
+ * OCFS1 volume label. Lives at sector 1.
+ */
+struct ocfs1_vol_label
+{
+/*00*/ struct ocfs1_disk_lock disk_lock;
+/*30*/ __u8 label[OCFS1_MAX_VOL_LABEL_LEN];
+/*70*/ __u16 label_len;
+/*72*/ __u8 vol_id[OCFS1_MAX_VOL_ID_LENGTH];
+/*82*/ __u16 vol_id_len;
+/*84*/ __u8 cluster_name[OCFS1_MAX_CLUSTER_NAME_LEN];
+/*A4*/ __u16 cluster_name_len;
+/*A6*/
+};
+
+
+#endif /* _OCFS1_FS_COMPAT_H */
+
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
new file mode 100644
index 000000000000..f468c600cf92
--- /dev/null
+++ b/fs/ocfs2/ocfs2.h
@@ -0,0 +1,464 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2.h
+ *
+ * Defines macros and structures used in OCFS2
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_H
+#define OCFS2_H
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/workqueue.h>
+#include <linux/kref.h>
+
+#include "cluster/nodemanager.h"
+#include "cluster/heartbeat.h"
+#include "cluster/tcp.h"
+
+#include "dlm/dlmapi.h"
+
+#include "ocfs2_fs.h"
+#include "endian.h"
+#include "ocfs2_lockid.h"
+
+struct ocfs2_extent_map {
+ u32 em_clusters;
+ struct rb_root em_extents;
+};
+
+/* Most user visible OCFS2 inodes will have very few pieces of
+ * metadata, but larger files (including bitmaps, etc) must be taken
+ * into account when designing an access scheme. We allow a small
+ * amount of inlined blocks to be stored on an array and grow the
+ * structure into a rb tree when necessary. */
+#define OCFS2_INODE_MAX_CACHE_ARRAY 2
+
+struct ocfs2_caching_info {
+ unsigned int ci_num_cached;
+ union {
+ sector_t ci_array[OCFS2_INODE_MAX_CACHE_ARRAY];
+ struct rb_root ci_tree;
+ } ci_cache;
+};
+
+/* this limits us to 256 nodes
+ * if we need more, we can do a kmalloc for the map */
+#define OCFS2_NODE_MAP_MAX_NODES 256
+struct ocfs2_node_map {
+ u16 num_nodes;
+ unsigned long map[BITS_TO_LONGS(OCFS2_NODE_MAP_MAX_NODES)];
+};
+
+enum ocfs2_ast_action {
+ OCFS2_AST_INVALID = 0,
+ OCFS2_AST_ATTACH,
+ OCFS2_AST_CONVERT,
+ OCFS2_AST_DOWNCONVERT,
+};
+
+/* actions for an unlockast function to take. */
+enum ocfs2_unlock_action {
+ OCFS2_UNLOCK_INVALID = 0,
+ OCFS2_UNLOCK_CANCEL_CONVERT,
+ OCFS2_UNLOCK_DROP_LOCK,
+};
+
+/* ocfs2_lock_res->l_flags flags. */
+#define OCFS2_LOCK_ATTACHED (0x00000001) /* have we initialized
+ * the lvb */
+#define OCFS2_LOCK_BUSY (0x00000002) /* we are currently in
+ * dlm_lock */
+#define OCFS2_LOCK_BLOCKED (0x00000004) /* blocked waiting to
+ * downconvert*/
+#define OCFS2_LOCK_LOCAL (0x00000008) /* newly created inode */
+#define OCFS2_LOCK_NEEDS_REFRESH (0x00000010)
+#define OCFS2_LOCK_REFRESHING (0x00000020)
+#define OCFS2_LOCK_INITIALIZED (0x00000040) /* track initialization
+ * for shutdown paths */
+#define OCFS2_LOCK_FREEING (0x00000080) /* help dlmglue track
+ * when to skip queueing
+ * a lock because it's
+ * about to be
+ * dropped. */
+#define OCFS2_LOCK_QUEUED (0x00000100) /* queued for downconvert */
+
+struct ocfs2_lock_res_ops;
+
+typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
+
+struct ocfs2_lock_res {
+ void *l_priv;
+ struct ocfs2_lock_res_ops *l_ops;
+ spinlock_t l_lock;
+
+ struct list_head l_blocked_list;
+ struct list_head l_mask_waiters;
+
+ enum ocfs2_lock_type l_type;
+ unsigned long l_flags;
+ char l_name[OCFS2_LOCK_ID_MAX_LEN];
+ int l_level;
+ unsigned int l_ro_holders;
+ unsigned int l_ex_holders;
+ struct dlm_lockstatus l_lksb;
+
+ /* used from AST/BAST funcs. */
+ enum ocfs2_ast_action l_action;
+ enum ocfs2_unlock_action l_unlock_action;
+ int l_requested;
+ int l_blocking;
+
+ wait_queue_head_t l_event;
+
+ struct list_head l_debug_list;
+};
+
+struct ocfs2_dlm_debug {
+ struct kref d_refcnt;
+ struct dentry *d_locking_state;
+ struct list_head d_lockres_tracking;
+};
+
+enum ocfs2_vol_state
+{
+ VOLUME_INIT = 0,
+ VOLUME_MOUNTED,
+ VOLUME_DISMOUNTED,
+ VOLUME_DISABLED
+};
+
+struct ocfs2_alloc_stats
+{
+ atomic_t moves;
+ atomic_t local_data;
+ atomic_t bitmap_data;
+ atomic_t bg_allocs;
+ atomic_t bg_extends;
+};
+
+enum ocfs2_local_alloc_state
+{
+ OCFS2_LA_UNUSED = 0,
+ OCFS2_LA_ENABLED,
+ OCFS2_LA_DISABLED
+};
+
+enum ocfs2_mount_options
+{
+ OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Heartbeat started in local mode */
+ OCFS2_MOUNT_BARRIER = 1 << 1, /* Use block barriers */
+ OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */
+ OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */
+ OCFS2_MOUNT_DATA_WRITEBACK = 1 << 4, /* No data ordering */
+#ifdef OCFS2_ORACORE_WORKAROUNDS
+ OCFS2_MOUNT_COMPAT_OCFS = 1 << 30, /* ocfs1 compatibility mode */
+#endif
+};
+
+#define OCFS2_OSB_SOFT_RO 0x0001
+#define OCFS2_OSB_HARD_RO 0x0002
+#define OCFS2_OSB_ERROR_FS 0x0004
+
+struct ocfs2_journal;
+struct ocfs2_journal_handle;
+struct ocfs2_super
+{
+ u32 osb_id; /* id used by the proc interface */
+ struct task_struct *commit_task;
+ struct super_block *sb;
+ struct inode *root_inode;
+ struct inode *sys_root_inode;
+ struct inode *system_inodes[NUM_SYSTEM_INODES];
+
+ struct ocfs2_slot_info *slot_info;
+
+ spinlock_t node_map_lock;
+ struct ocfs2_node_map mounted_map;
+ struct ocfs2_node_map recovery_map;
+ struct ocfs2_node_map umount_map;
+
+ u32 num_clusters;
+ u64 root_blkno;
+ u64 system_dir_blkno;
+ u64 bitmap_blkno;
+ u32 bitmap_cpg;
+ u8 *uuid;
+ char *uuid_str;
+ u8 *vol_label;
+ u64 first_cluster_group_blkno;
+ u32 fs_generation;
+
+ u32 s_feature_compat;
+ u32 s_feature_incompat;
+ u32 s_feature_ro_compat;
+
+ /* Protects s_next_generaion, osb_flags. Could protect more on
+ * osb as it's very short lived. */
+ spinlock_t osb_lock;
+ u32 s_next_generation;
+ unsigned long osb_flags;
+
+ unsigned long s_mount_opt;
+
+ u16 max_slots;
+ u16 num_nodes;
+ s16 node_num;
+ s16 slot_num;
+ int s_sectsize_bits;
+ int s_clustersize;
+ int s_clustersize_bits;
+ struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/<maj_min> */
+
+ atomic_t vol_state;
+ struct semaphore recovery_lock;
+ struct task_struct *recovery_thread_task;
+ int disable_recovery;
+ wait_queue_head_t checkpoint_event;
+ atomic_t needs_checkpoint;
+ struct ocfs2_journal *journal;
+
+ enum ocfs2_local_alloc_state local_alloc_state;
+ struct buffer_head *local_alloc_bh;
+
+ /* Next two fields are for local node slot recovery during
+ * mount. */
+ int dirty;
+ struct ocfs2_dinode *local_alloc_copy;
+
+ struct ocfs2_alloc_stats alloc_stats;
+ char dev_str[20]; /* "major,minor" of the device */
+
+ struct dlm_ctxt *dlm;
+ struct ocfs2_lock_res osb_super_lockres;
+ struct ocfs2_lock_res osb_rename_lockres;
+ struct dlm_eviction_cb osb_eviction_cb;
+ struct ocfs2_dlm_debug *osb_dlm_debug;
+
+ struct dentry *osb_debug_root;
+
+ wait_queue_head_t recovery_event;
+
+ spinlock_t vote_task_lock;
+ struct task_struct *vote_task;
+ wait_queue_head_t vote_event;
+ unsigned long vote_wake_sequence;
+ unsigned long vote_work_sequence;
+
+ struct list_head blocked_lock_list;
+ unsigned long blocked_lock_count;
+
+ struct list_head vote_list;
+ int vote_count;
+
+ u32 net_key;
+ spinlock_t net_response_lock;
+ unsigned int net_response_ids;
+ struct list_head net_response_list;
+
+ struct o2hb_callback_func osb_hb_up;
+ struct o2hb_callback_func osb_hb_down;
+
+ struct list_head osb_net_handlers;
+
+ wait_queue_head_t osb_mount_event;
+
+ /* Truncate log info */
+ struct inode *osb_tl_inode;
+ struct buffer_head *osb_tl_bh;
+ struct work_struct osb_truncate_log_wq;
+};
+
+#define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info)
+#define OCFS2_MAX_OSB_ID 65536
+
+static inline int ocfs2_should_order_data(struct inode *inode)
+{
+ if (!S_ISREG(inode->i_mode))
+ return 0;
+ if (OCFS2_SB(inode->i_sb)->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK)
+ return 0;
+ return 1;
+}
+
+/* set / clear functions because cluster events can make these happen
+ * in parallel so we want the transitions to be atomic. this also
+ * means that any future flags osb_flags must be protected by spinlock
+ * too! */
+static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
+ unsigned long flag)
+{
+ spin_lock(&osb->osb_lock);
+ osb->osb_flags |= flag;
+ spin_unlock(&osb->osb_lock);
+}
+
+static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
+ int hard)
+{
+ spin_lock(&osb->osb_lock);
+ osb->osb_flags &= ~(OCFS2_OSB_SOFT_RO|OCFS2_OSB_HARD_RO);
+ if (hard)
+ osb->osb_flags |= OCFS2_OSB_HARD_RO;
+ else
+ osb->osb_flags |= OCFS2_OSB_SOFT_RO;
+ spin_unlock(&osb->osb_lock);
+}
+
+static inline int ocfs2_is_hard_readonly(struct ocfs2_super *osb)
+{
+ int ret;
+
+ spin_lock(&osb->osb_lock);
+ ret = osb->osb_flags & OCFS2_OSB_HARD_RO;
+ spin_unlock(&osb->osb_lock);
+
+ return ret;
+}
+
+static inline int ocfs2_is_soft_readonly(struct ocfs2_super *osb)
+{
+ int ret;
+
+ spin_lock(&osb->osb_lock);
+ ret = osb->osb_flags & OCFS2_OSB_SOFT_RO;
+ spin_unlock(&osb->osb_lock);
+
+ return ret;
+}
+
+#define OCFS2_IS_VALID_DINODE(ptr) \
+ (!strcmp((ptr)->i_signature, OCFS2_INODE_SIGNATURE))
+
+#define OCFS2_RO_ON_INVALID_DINODE(__sb, __di) do { \
+ typeof(__di) ____di = (__di); \
+ ocfs2_error((__sb), \
+ "Dinode # %"MLFu64" has bad signature %.*s", \
+ (____di)->i_blkno, 7, \
+ (____di)->i_signature); \
+} while (0);
+
+#define OCFS2_IS_VALID_EXTENT_BLOCK(ptr) \
+ (!strcmp((ptr)->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE))
+
+#define OCFS2_RO_ON_INVALID_EXTENT_BLOCK(__sb, __eb) do { \
+ typeof(__eb) ____eb = (__eb); \
+ ocfs2_error((__sb), \
+ "Extent Block # %"MLFu64" has bad signature %.*s", \
+ (____eb)->h_blkno, 7, \
+ (____eb)->h_signature); \
+} while (0);
+
+#define OCFS2_IS_VALID_GROUP_DESC(ptr) \
+ (!strcmp((ptr)->bg_signature, OCFS2_GROUP_DESC_SIGNATURE))
+
+#define OCFS2_RO_ON_INVALID_GROUP_DESC(__sb, __gd) do { \
+ typeof(__gd) ____gd = (__gd); \
+ ocfs2_error((__sb), \
+ "Group Descriptor # %"MLFu64" has bad signature %.*s", \
+ (____gd)->bg_blkno, 7, \
+ (____gd)->bg_signature); \
+} while (0);
+
+static inline unsigned long ino_from_blkno(struct super_block *sb,
+ u64 blkno)
+{
+ return (unsigned long)(blkno & (u64)ULONG_MAX);
+}
+
+static inline u64 ocfs2_clusters_to_blocks(struct super_block *sb,
+ u32 clusters)
+{
+ int c_to_b_bits = OCFS2_SB(sb)->s_clustersize_bits -
+ sb->s_blocksize_bits;
+
+ return (u64)clusters << c_to_b_bits;
+}
+
+static inline u32 ocfs2_blocks_to_clusters(struct super_block *sb,
+ u64 blocks)
+{
+ int b_to_c_bits = OCFS2_SB(sb)->s_clustersize_bits -
+ sb->s_blocksize_bits;
+
+ return (u32)(blocks >> b_to_c_bits);
+}
+
+static inline unsigned int ocfs2_clusters_for_bytes(struct super_block *sb,
+ u64 bytes)
+{
+ int cl_bits = OCFS2_SB(sb)->s_clustersize_bits;
+ unsigned int clusters;
+
+ bytes += OCFS2_SB(sb)->s_clustersize - 1;
+ /* OCFS2 just cannot have enough clusters to overflow this */
+ clusters = (unsigned int)(bytes >> cl_bits);
+
+ return clusters;
+}
+
+static inline u64 ocfs2_blocks_for_bytes(struct super_block *sb,
+ u64 bytes)
+{
+ bytes += sb->s_blocksize - 1;
+ return bytes >> sb->s_blocksize_bits;
+}
+
+static inline u64 ocfs2_clusters_to_bytes(struct super_block *sb,
+ u32 clusters)
+{
+ return (u64)clusters << OCFS2_SB(sb)->s_clustersize_bits;
+}
+
+static inline u64 ocfs2_align_bytes_to_clusters(struct super_block *sb,
+ u64 bytes)
+{
+ int cl_bits = OCFS2_SB(sb)->s_clustersize_bits;
+ unsigned int clusters;
+
+ clusters = ocfs2_clusters_for_bytes(sb, bytes);
+ return (u64)clusters << cl_bits;
+}
+
+static inline u64 ocfs2_align_bytes_to_blocks(struct super_block *sb,
+ u64 bytes)
+{
+ u64 blocks;
+
+ blocks = ocfs2_blocks_for_bytes(sb, bytes);
+ return blocks << sb->s_blocksize_bits;
+}
+
+static inline unsigned long ocfs2_align_bytes_to_sectors(u64 bytes)
+{
+ return (unsigned long)((bytes + 511) >> 9);
+}
+
+#define ocfs2_set_bit ext2_set_bit
+#define ocfs2_clear_bit ext2_clear_bit
+#define ocfs2_test_bit ext2_test_bit
+#define ocfs2_find_next_zero_bit ext2_find_next_zero_bit
+#endif /* OCFS2_H */
+
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
new file mode 100644
index 000000000000..dfb8a5bedfc8
--- /dev/null
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -0,0 +1,638 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_fs.h
+ *
+ * On-disk structures for OCFS2.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef _OCFS2_FS_H
+#define _OCFS2_FS_H
+
+/* Version */
+#define OCFS2_MAJOR_REV_LEVEL 0
+#define OCFS2_MINOR_REV_LEVEL 90
+
+/*
+ * An OCFS2 volume starts this way:
+ * Sector 0: Valid ocfs1_vol_disk_hdr that cleanly fails to mount OCFS.
+ * Sector 1: Valid ocfs1_vol_label that cleanly fails to mount OCFS.
+ * Block OCFS2_SUPER_BLOCK_BLKNO: OCFS2 superblock.
+ *
+ * All other structures are found from the superblock information.
+ *
+ * OCFS2_SUPER_BLOCK_BLKNO is in blocks, not sectors. eg, for a
+ * blocksize of 2K, it is 4096 bytes into disk.
+ */
+#define OCFS2_SUPER_BLOCK_BLKNO 2
+
+/*
+ * Cluster size limits. The maximum is kept arbitrarily at 1 MB, and could
+ * grow if needed.
+ */
+#define OCFS2_MIN_CLUSTERSIZE 4096
+#define OCFS2_MAX_CLUSTERSIZE 1048576
+
+/*
+ * Blocks cannot be bigger than clusters, so the maximum blocksize is the
+ * minimum cluster size.
+ */
+#define OCFS2_MIN_BLOCKSIZE 512
+#define OCFS2_MAX_BLOCKSIZE OCFS2_MIN_CLUSTERSIZE
+
+/* Filesystem magic number */
+#define OCFS2_SUPER_MAGIC 0x7461636f
+
+/* Object signatures */
+#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
+#define OCFS2_INODE_SIGNATURE "INODE01"
+#define OCFS2_EXTENT_BLOCK_SIGNATURE "EXBLK01"
+#define OCFS2_GROUP_DESC_SIGNATURE "GROUP01"
+
+/* Compatibility flags */
+#define OCFS2_HAS_COMPAT_FEATURE(sb,mask) \
+ ( OCFS2_SB(sb)->s_feature_compat & (mask) )
+#define OCFS2_HAS_RO_COMPAT_FEATURE(sb,mask) \
+ ( OCFS2_SB(sb)->s_feature_ro_compat & (mask) )
+#define OCFS2_HAS_INCOMPAT_FEATURE(sb,mask) \
+ ( OCFS2_SB(sb)->s_feature_incompat & (mask) )
+#define OCFS2_SET_COMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_compat |= (mask)
+#define OCFS2_SET_RO_COMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_ro_compat |= (mask)
+#define OCFS2_SET_INCOMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_incompat |= (mask)
+#define OCFS2_CLEAR_COMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_compat &= ~(mask)
+#define OCFS2_CLEAR_RO_COMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_ro_compat &= ~(mask)
+#define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask) \
+ OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
+
+#define OCFS2_FEATURE_COMPAT_SUPP 0
+#define OCFS2_FEATURE_INCOMPAT_SUPP 0
+#define OCFS2_FEATURE_RO_COMPAT_SUPP 0
+
+/*
+ * Heartbeat-only devices are missing journals and other files. The
+ * filesystem driver can't load them, but the library can. Never put
+ * this in OCFS2_FEATURE_INCOMPAT_SUPP, *ever*.
+ */
+#define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV 0x0002
+
+
+/*
+ * Flags on ocfs2_dinode.i_flags
+ */
+#define OCFS2_VALID_FL (0x00000001) /* Inode is valid */
+#define OCFS2_UNUSED2_FL (0x00000002)
+#define OCFS2_ORPHANED_FL (0x00000004) /* On the orphan list */
+#define OCFS2_UNUSED3_FL (0x00000008)
+/* System inode flags */
+#define OCFS2_SYSTEM_FL (0x00000010) /* System inode */
+#define OCFS2_SUPER_BLOCK_FL (0x00000020) /* Super block */
+#define OCFS2_LOCAL_ALLOC_FL (0x00000040) /* Slot local alloc bitmap */
+#define OCFS2_BITMAP_FL (0x00000080) /* Allocation bitmap */
+#define OCFS2_JOURNAL_FL (0x00000100) /* Slot local journal */
+#define OCFS2_HEARTBEAT_FL (0x00000200) /* Heartbeat area */
+#define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */
+#define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */
+
+/*
+ * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
+ */
+#define OCFS2_JOURNAL_DIRTY_FL (0x00000001) /* Journal needs recovery */
+
+/*
+ * superblock s_state flags
+ */
+#define OCFS2_ERROR_FS (0x00000001) /* FS saw errors */
+
+/* Limit of space in ocfs2_dir_entry */
+#define OCFS2_MAX_FILENAME_LEN 255
+
+/* Maximum slots on an ocfs2 file system */
+#define OCFS2_MAX_SLOTS 255
+
+/* Slot map indicator for an empty slot */
+#define OCFS2_INVALID_SLOT -1
+
+#define OCFS2_VOL_UUID_LEN 16
+#define OCFS2_MAX_VOL_LABEL_LEN 64
+
+/* Journal limits (in bytes) */
+#define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024)
+#define OCFS2_MAX_JOURNAL_SIZE (500 * 1024 * 1024)
+
+struct ocfs2_system_inode_info {
+ char *si_name;
+ int si_iflags;
+ int si_mode;
+};
+
+/* System file index */
+enum {
+ BAD_BLOCK_SYSTEM_INODE = 0,
+ GLOBAL_INODE_ALLOC_SYSTEM_INODE,
+ SLOT_MAP_SYSTEM_INODE,
+#define OCFS2_FIRST_ONLINE_SYSTEM_INODE SLOT_MAP_SYSTEM_INODE
+ HEARTBEAT_SYSTEM_INODE,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+#define OCFS2_LAST_GLOBAL_SYSTEM_INODE GLOBAL_BITMAP_SYSTEM_INODE
+ ORPHAN_DIR_SYSTEM_INODE,
+ EXTENT_ALLOC_SYSTEM_INODE,
+ INODE_ALLOC_SYSTEM_INODE,
+ JOURNAL_SYSTEM_INODE,
+ LOCAL_ALLOC_SYSTEM_INODE,
+ TRUNCATE_LOG_SYSTEM_INODE,
+ NUM_SYSTEM_INODES
+};
+
+static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
+ /* Global system inodes (single copy) */
+ /* The first two are only used from userspace mfks/tunefs */
+ [BAD_BLOCK_SYSTEM_INODE] = { "bad_blocks", 0, S_IFREG | 0644 },
+ [GLOBAL_INODE_ALLOC_SYSTEM_INODE] = { "global_inode_alloc", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 },
+
+ /* These are used by the running filesystem */
+ [SLOT_MAP_SYSTEM_INODE] = { "slot_map", 0, S_IFREG | 0644 },
+ [HEARTBEAT_SYSTEM_INODE] = { "heartbeat", OCFS2_HEARTBEAT_FL, S_IFREG | 0644 },
+ [GLOBAL_BITMAP_SYSTEM_INODE] = { "global_bitmap", 0, S_IFREG | 0644 },
+
+ /* Slot-specific system inodes (one copy per slot) */
+ [ORPHAN_DIR_SYSTEM_INODE] = { "orphan_dir:%04d", 0, S_IFDIR | 0755 },
+ [EXTENT_ALLOC_SYSTEM_INODE] = { "extent_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 },
+ [INODE_ALLOC_SYSTEM_INODE] = { "inode_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_CHAIN_FL, S_IFREG | 0644 },
+ [JOURNAL_SYSTEM_INODE] = { "journal:%04d", OCFS2_JOURNAL_FL, S_IFREG | 0644 },
+ [LOCAL_ALLOC_SYSTEM_INODE] = { "local_alloc:%04d", OCFS2_BITMAP_FL | OCFS2_LOCAL_ALLOC_FL, S_IFREG | 0644 },
+ [TRUNCATE_LOG_SYSTEM_INODE] = { "truncate_log:%04d", OCFS2_DEALLOC_FL, S_IFREG | 0644 }
+};
+
+/* Parameter passed from mount.ocfs2 to module */
+#define OCFS2_HB_NONE "heartbeat=none"
+#define OCFS2_HB_LOCAL "heartbeat=local"
+
+/*
+ * OCFS2 directory file types. Only the low 3 bits are used. The
+ * other bits are reserved for now.
+ */
+#define OCFS2_FT_UNKNOWN 0
+#define OCFS2_FT_REG_FILE 1
+#define OCFS2_FT_DIR 2
+#define OCFS2_FT_CHRDEV 3
+#define OCFS2_FT_BLKDEV 4
+#define OCFS2_FT_FIFO 5
+#define OCFS2_FT_SOCK 6
+#define OCFS2_FT_SYMLINK 7
+
+#define OCFS2_FT_MAX 8
+
+/*
+ * OCFS2_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define OCFS2_DIR_PAD 4
+#define OCFS2_DIR_ROUND (OCFS2_DIR_PAD - 1)
+#define OCFS2_DIR_MEMBER_LEN offsetof(struct ocfs2_dir_entry, name)
+#define OCFS2_DIR_REC_LEN(name_len) (((name_len) + OCFS2_DIR_MEMBER_LEN + \
+ OCFS2_DIR_ROUND) & \
+ ~OCFS2_DIR_ROUND)
+
+#define OCFS2_LINK_MAX 32000
+
+#define S_SHIFT 12
+static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
+ [S_IFREG >> S_SHIFT] = OCFS2_FT_REG_FILE,
+ [S_IFDIR >> S_SHIFT] = OCFS2_FT_DIR,
+ [S_IFCHR >> S_SHIFT] = OCFS2_FT_CHRDEV,
+ [S_IFBLK >> S_SHIFT] = OCFS2_FT_BLKDEV,
+ [S_IFIFO >> S_SHIFT] = OCFS2_FT_FIFO,
+ [S_IFSOCK >> S_SHIFT] = OCFS2_FT_SOCK,
+ [S_IFLNK >> S_SHIFT] = OCFS2_FT_SYMLINK,
+};
+
+
+/*
+ * Convenience casts
+ */
+#define OCFS2_RAW_SB(dinode) (&((dinode)->id2.i_super))
+
+/*
+ * On disk extent record for OCFS2
+ * It describes a range of clusters on disk.
+ */
+struct ocfs2_extent_rec {
+/*00*/ __le32 e_cpos; /* Offset into the file, in clusters */
+ __le32 e_clusters; /* Clusters covered by this extent */
+ __le64 e_blkno; /* Physical disk offset, in blocks */
+/*10*/
+};
+
+struct ocfs2_chain_rec {
+ __le32 c_free; /* Number of free bits in this chain. */
+ __le32 c_total; /* Number of total bits in this chain */
+ __le64 c_blkno; /* Physical disk offset (blocks) of 1st group */
+};
+
+struct ocfs2_truncate_rec {
+ __le32 t_start; /* 1st cluster in this log */
+ __le32 t_clusters; /* Number of total clusters covered */
+};
+
+/*
+ * On disk extent list for OCFS2 (node in the tree). Note that this
+ * is contained inside ocfs2_dinode or ocfs2_extent_block, so the
+ * offsets are relative to ocfs2_dinode.id2.i_list or
+ * ocfs2_extent_block.h_list, respectively.
+ */
+struct ocfs2_extent_list {
+/*00*/ __le16 l_tree_depth; /* Extent tree depth from this
+ point. 0 means data extents
+ hang directly off this
+ header (a leaf) */
+ __le16 l_count; /* Number of extent records */
+ __le16 l_next_free_rec; /* Next unused extent slot */
+ __le16 l_reserved1;
+ __le64 l_reserved2; /* Pad to
+ sizeof(ocfs2_extent_rec) */
+/*10*/ struct ocfs2_extent_rec l_recs[0]; /* Extent records */
+};
+
+/*
+ * On disk allocation chain list for OCFS2. Note that this is
+ * contained inside ocfs2_dinode, so the offsets are relative to
+ * ocfs2_dinode.id2.i_chain.
+ */
+struct ocfs2_chain_list {
+/*00*/ __le16 cl_cpg; /* Clusters per Block Group */
+ __le16 cl_bpc; /* Bits per cluster */
+ __le16 cl_count; /* Total chains in this list */
+ __le16 cl_next_free_rec; /* Next unused chain slot */
+ __le64 cl_reserved1;
+/*10*/ struct ocfs2_chain_rec cl_recs[0]; /* Chain records */
+};
+
+/*
+ * On disk deallocation log for OCFS2. Note that this is
+ * contained inside ocfs2_dinode, so the offsets are relative to
+ * ocfs2_dinode.id2.i_dealloc.
+ */
+struct ocfs2_truncate_log {
+/*00*/ __le16 tl_count; /* Total records in this log */
+ __le16 tl_used; /* Number of records in use */
+ __le32 tl_reserved1;
+/*08*/ struct ocfs2_truncate_rec tl_recs[0]; /* Truncate records */
+};
+
+/*
+ * On disk extent block (indirect block) for OCFS2
+ */
+struct ocfs2_extent_block
+{
+/*00*/ __u8 h_signature[8]; /* Signature for verification */
+ __le64 h_reserved1;
+/*10*/ __le16 h_suballoc_slot; /* Slot suballocator this
+ extent_header belongs to */
+ __le16 h_suballoc_bit; /* Bit offset in suballocator
+ block group */
+ __le32 h_fs_generation; /* Must match super block */
+ __le64 h_blkno; /* Offset on disk, in blocks */
+/*20*/ __le64 h_reserved3;
+ __le64 h_next_leaf_blk; /* Offset on disk, in blocks,
+ of next leaf header pointing
+ to data */
+/*30*/ struct ocfs2_extent_list h_list; /* Extent record list */
+/* Actual on-disk size is one block */
+};
+
+/*
+ * On disk superblock for OCFS2
+ * Note that it is contained inside an ocfs2_dinode, so all offsets
+ * are relative to the start of ocfs2_dinode.id2.
+ */
+struct ocfs2_super_block {
+/*00*/ __le16 s_major_rev_level;
+ __le16 s_minor_rev_level;
+ __le16 s_mnt_count;
+ __le16 s_max_mnt_count;
+ __le16 s_state; /* File system state */
+ __le16 s_errors; /* Behaviour when detecting errors */
+ __le32 s_checkinterval; /* Max time between checks */
+/*10*/ __le64 s_lastcheck; /* Time of last check */
+ __le32 s_creator_os; /* OS */
+ __le32 s_feature_compat; /* Compatible feature set */
+/*20*/ __le32 s_feature_incompat; /* Incompatible feature set */
+ __le32 s_feature_ro_compat; /* Readonly-compatible feature set */
+ __le64 s_root_blkno; /* Offset, in blocks, of root directory
+ dinode */
+/*30*/ __le64 s_system_dir_blkno; /* Offset, in blocks, of system
+ directory dinode */
+ __le32 s_blocksize_bits; /* Blocksize for this fs */
+ __le32 s_clustersize_bits; /* Clustersize for this fs */
+/*40*/ __le16 s_max_slots; /* Max number of simultaneous mounts
+ before tunefs required */
+ __le16 s_reserved1;
+ __le32 s_reserved2;
+ __le64 s_first_cluster_group; /* Block offset of 1st cluster
+ * group header */
+/*50*/ __u8 s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
+/*90*/ __u8 s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */
+/*A0*/
+};
+
+/*
+ * Local allocation bitmap for OCFS2 slots
+ * Note that it exists inside an ocfs2_dinode, so all offsets are
+ * relative to the start of ocfs2_dinode.id2.
+ */
+struct ocfs2_local_alloc
+{
+/*00*/ __le32 la_bm_off; /* Starting bit offset in main bitmap */
+ __le16 la_size; /* Size of included bitmap, in bytes */
+ __le16 la_reserved1;
+ __le64 la_reserved2;
+/*10*/ __u8 la_bitmap[0];
+};
+
+/*
+ * On disk inode for OCFS2
+ */
+struct ocfs2_dinode {
+/*00*/ __u8 i_signature[8]; /* Signature for validation */
+ __le32 i_generation; /* Generation number */
+ __le16 i_suballoc_slot; /* Slot suballocator this inode
+ belongs to */
+ __le16 i_suballoc_bit; /* Bit offset in suballocator
+ block group */
+/*10*/ __le32 i_reserved0;
+ __le32 i_clusters; /* Cluster count */
+ __le32 i_uid; /* Owner UID */
+ __le32 i_gid; /* Owning GID */
+/*20*/ __le64 i_size; /* Size in bytes */
+ __le16 i_mode; /* File mode */
+ __le16 i_links_count; /* Links count */
+ __le32 i_flags; /* File flags */
+/*30*/ __le64 i_atime; /* Access time */
+ __le64 i_ctime; /* Creation time */
+/*40*/ __le64 i_mtime; /* Modification time */
+ __le64 i_dtime; /* Deletion time */
+/*50*/ __le64 i_blkno; /* Offset on disk, in blocks */
+ __le64 i_last_eb_blk; /* Pointer to last extent
+ block */
+/*60*/ __le32 i_fs_generation; /* Generation per fs-instance */
+ __le32 i_atime_nsec;
+ __le32 i_ctime_nsec;
+ __le32 i_mtime_nsec;
+/*70*/ __le64 i_reserved1[9];
+/*B8*/ union {
+ __le64 i_pad1; /* Generic way to refer to this
+ 64bit union */
+ struct {
+ __le64 i_rdev; /* Device number */
+ } dev1;
+ struct { /* Info for bitmap system
+ inodes */
+ __le32 i_used; /* Bits (ie, clusters) used */
+ __le32 i_total; /* Total bits (clusters)
+ available */
+ } bitmap1;
+ struct { /* Info for journal system
+ inodes */
+ __le32 ij_flags; /* Mounted, version, etc. */
+ __le32 ij_pad;
+ } journal1;
+ } id1; /* Inode type dependant 1 */
+/*C0*/ union {
+ struct ocfs2_super_block i_super;
+ struct ocfs2_local_alloc i_lab;
+ struct ocfs2_chain_list i_chain;
+ struct ocfs2_extent_list i_list;
+ struct ocfs2_truncate_log i_dealloc;
+ __u8 i_symlink[0];
+ } id2;
+/* Actual on-disk size is one block */
+};
+
+/*
+ * On-disk directory entry structure for OCFS2
+ *
+ * Packed as this structure could be accessed unaligned on 64-bit platforms
+ */
+struct ocfs2_dir_entry {
+/*00*/ __le64 inode; /* Inode number */
+ __le16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+/*0C*/ char name[OCFS2_MAX_FILENAME_LEN]; /* File name */
+/* Actual on-disk length specified by rec_len */
+} __attribute__ ((packed));
+
+/*
+ * On disk allocator group structure for OCFS2
+ */
+struct ocfs2_group_desc
+{
+/*00*/ __u8 bg_signature[8]; /* Signature for validation */
+ __le16 bg_size; /* Size of included bitmap in
+ bytes. */
+ __le16 bg_bits; /* Bits represented by this
+ group. */
+ __le16 bg_free_bits_count; /* Free bits count */
+ __le16 bg_chain; /* What chain I am in. */
+/*10*/ __le32 bg_generation;
+ __le32 bg_reserved1;
+ __le64 bg_next_group; /* Next group in my list, in
+ blocks */
+/*20*/ __le64 bg_parent_dinode; /* dinode which owns me, in
+ blocks */
+ __le64 bg_blkno; /* Offset on disk, in blocks */
+/*30*/ __le64 bg_reserved2[2];
+/*40*/ __u8 bg_bitmap[0];
+};
+
+#ifdef __KERNEL__
+static inline int ocfs2_fast_symlink_chars(struct super_block *sb)
+{
+ return sb->s_blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_symlink);
+}
+
+static inline int ocfs2_extent_recs_per_inode(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_list.l_recs);
+
+ return size / sizeof(struct ocfs2_extent_rec);
+}
+
+static inline int ocfs2_chain_recs_per_inode(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_chain.cl_recs);
+
+ return size / sizeof(struct ocfs2_chain_rec);
+}
+
+static inline u16 ocfs2_extent_recs_per_eb(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_extent_block, h_list.l_recs);
+
+ return size / sizeof(struct ocfs2_extent_rec);
+}
+
+static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
+{
+ u16 size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_lab.la_bitmap);
+
+ return size;
+}
+
+static inline int ocfs2_group_bitmap_size(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_group_desc, bg_bitmap);
+
+ return size;
+}
+
+static inline int ocfs2_truncate_recs_per_inode(struct super_block *sb)
+{
+ int size;
+
+ size = sb->s_blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_dealloc.tl_recs);
+
+ return size / sizeof(struct ocfs2_truncate_rec);
+}
+#else
+static inline int ocfs2_fast_symlink_chars(int blocksize)
+{
+ return blocksize - offsetof(struct ocfs2_dinode, id2.i_symlink);
+}
+
+static inline int ocfs2_extent_recs_per_inode(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_list.l_recs);
+
+ return size / sizeof(struct ocfs2_extent_rec);
+}
+
+static inline int ocfs2_chain_recs_per_inode(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_chain.cl_recs);
+
+ return size / sizeof(struct ocfs2_chain_rec);
+}
+
+static inline int ocfs2_extent_recs_per_eb(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_extent_block, h_list.l_recs);
+
+ return size / sizeof(struct ocfs2_extent_rec);
+}
+
+static inline int ocfs2_local_alloc_size(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_lab.la_bitmap);
+
+ return size;
+}
+
+static inline int ocfs2_group_bitmap_size(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_group_desc, bg_bitmap);
+
+ return size;
+}
+
+static inline int ocfs2_truncate_recs_per_inode(int blocksize)
+{
+ int size;
+
+ size = blocksize -
+ offsetof(struct ocfs2_dinode, id2.i_dealloc.tl_recs);
+
+ return size / sizeof(struct ocfs2_truncate_rec);
+}
+#endif /* __KERNEL__ */
+
+
+static inline int ocfs2_system_inode_is_global(int type)
+{
+ return ((type >= 0) &&
+ (type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE));
+}
+
+static inline int ocfs2_sprintf_system_inode_name(char *buf, int len,
+ int type, int slot)
+{
+ int chars;
+
+ /*
+ * Global system inodes can only have one copy. Everything
+ * after OCFS2_LAST_GLOBAL_SYSTEM_INODE in the system inode
+ * list has a copy per slot.
+ */
+ if (type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE)
+ chars = snprintf(buf, len,
+ ocfs2_system_inodes[type].si_name);
+ else
+ chars = snprintf(buf, len,
+ ocfs2_system_inodes[type].si_name,
+ slot);
+
+ return chars;
+}
+
+static inline void ocfs2_set_de_type(struct ocfs2_dir_entry *de,
+ umode_t mode)
+{
+ de->file_type = ocfs2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+}
+
+#endif /* _OCFS2_FS_H */
+
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
new file mode 100644
index 000000000000..7dd9e1e705b0
--- /dev/null
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -0,0 +1,73 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ocfs2_lockid.h
+ *
+ * Defines OCFS2 lockid bits.
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_LOCKID_H
+#define OCFS2_LOCKID_H
+
+/* lock ids are made up in the following manner:
+ * name[0] --> type
+ * name[1-6] --> 6 pad characters, reserved for now
+ * name[7-22] --> block number, expressed in hex as 16 chars
+ * name[23-30] --> i_generation, expressed in hex 8 chars
+ * name[31] --> '\0' */
+#define OCFS2_LOCK_ID_MAX_LEN 32
+#define OCFS2_LOCK_ID_PAD "000000"
+
+enum ocfs2_lock_type {
+ OCFS2_LOCK_TYPE_META = 0,
+ OCFS2_LOCK_TYPE_DATA,
+ OCFS2_LOCK_TYPE_SUPER,
+ OCFS2_LOCK_TYPE_RENAME,
+ OCFS2_LOCK_TYPE_RW,
+ OCFS2_NUM_LOCK_TYPES
+};
+
+static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
+{
+ char c;
+ switch (type) {
+ case OCFS2_LOCK_TYPE_META:
+ c = 'M';
+ break;
+ case OCFS2_LOCK_TYPE_DATA:
+ c = 'D';
+ break;
+ case OCFS2_LOCK_TYPE_SUPER:
+ c = 'S';
+ break;
+ case OCFS2_LOCK_TYPE_RENAME:
+ c = 'R';
+ break;
+ case OCFS2_LOCK_TYPE_RW:
+ c = 'W';
+ break;
+ default:
+ c = '\0';
+ }
+
+ return c;
+}
+
+#endif /* OCFS2_LOCKID_H */
diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c
new file mode 100644
index 000000000000..871627961d6d
--- /dev/null
+++ b/fs/ocfs2/slot_map.c
@@ -0,0 +1,303 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * slot_map.c
+ *
+ *
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+
+#define MLOG_MASK_PREFIX ML_SUPER
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "slot_map.h"
+#include "super.h"
+#include "sysfile.h"
+
+#include "buffer_head_io.h"
+
+static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+ s16 global);
+static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+ s16 slot_num,
+ s16 node_num);
+
+/* Use the slot information we've collected to create a map of mounted
+ * nodes. Should be holding an EX on super block. assumes slot info is
+ * up to date. Note that we call this *after* we find a slot, so our
+ * own node should be set in the map too... */
+void ocfs2_populate_mounted_map(struct ocfs2_super *osb)
+{
+ int i;
+ struct ocfs2_slot_info *si = osb->slot_info;
+
+ spin_lock(&si->si_lock);
+
+ for (i = 0; i < si->si_size; i++)
+ if (si->si_global_node_nums[i] != OCFS2_INVALID_SLOT)
+ ocfs2_node_map_set_bit(osb, &osb->mounted_map,
+ si->si_global_node_nums[i]);
+
+ spin_unlock(&si->si_lock);
+}
+
+/* post the slot information on disk into our slot_info struct. */
+void ocfs2_update_slot_info(struct ocfs2_slot_info *si)
+{
+ int i;
+ __le16 *disk_info;
+
+ /* we don't read the slot block here as ocfs2_super_lock
+ * should've made sure we have the most recent copy. */
+ spin_lock(&si->si_lock);
+ disk_info = (__le16 *) si->si_bh->b_data;
+
+ for (i = 0; i < si->si_size; i++)
+ si->si_global_node_nums[i] = le16_to_cpu(disk_info[i]);
+
+ spin_unlock(&si->si_lock);
+}
+
+/* post the our slot info stuff into it's destination bh and write it
+ * out. */
+int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+ struct ocfs2_slot_info *si)
+{
+ int status, i;
+ __le16 *disk_info = (__le16 *) si->si_bh->b_data;
+
+ spin_lock(&si->si_lock);
+ for (i = 0; i < si->si_size; i++)
+ disk_info[i] = cpu_to_le16(si->si_global_node_nums[i]);
+ spin_unlock(&si->si_lock);
+
+ status = ocfs2_write_block(osb, si->si_bh, si->si_inode);
+ if (status < 0)
+ mlog_errno(status);
+
+ return status;
+}
+
+/* try to find global node in the slot info. Returns
+ * OCFS2_INVALID_SLOT if nothing is found. */
+static s16 __ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+ s16 global)
+{
+ int i;
+ s16 ret = OCFS2_INVALID_SLOT;
+
+ for(i = 0; i < si->si_num_slots; i++) {
+ if (global == si->si_global_node_nums[i]) {
+ ret = (s16) i;
+ break;
+ }
+ }
+ return ret;
+}
+
+static s16 __ocfs2_find_empty_slot(struct ocfs2_slot_info *si)
+{
+ int i;
+ s16 ret = OCFS2_INVALID_SLOT;
+
+ for(i = 0; i < si->si_num_slots; i++) {
+ if (OCFS2_INVALID_SLOT == si->si_global_node_nums[i]) {
+ ret = (s16) i;
+ break;
+ }
+ }
+ return ret;
+}
+
+s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+ s16 global)
+{
+ s16 ret;
+
+ spin_lock(&si->si_lock);
+ ret = __ocfs2_node_num_to_slot(si, global);
+ spin_unlock(&si->si_lock);
+ return ret;
+}
+
+static void __ocfs2_fill_slot(struct ocfs2_slot_info *si,
+ s16 slot_num,
+ s16 node_num)
+{
+ BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+ BUG_ON(slot_num >= si->si_num_slots);
+ BUG_ON((node_num != O2NM_INVALID_NODE_NUM) &&
+ (node_num >= O2NM_MAX_NODES));
+
+ si->si_global_node_nums[slot_num] = node_num;
+}
+
+void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+ s16 slot_num)
+{
+ spin_lock(&si->si_lock);
+ __ocfs2_fill_slot(si, slot_num, OCFS2_INVALID_SLOT);
+ spin_unlock(&si->si_lock);
+}
+
+int ocfs2_init_slot_info(struct ocfs2_super *osb)
+{
+ int status, i;
+ u64 blkno;
+ struct inode *inode = NULL;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_slot_info *si;
+
+ si = kcalloc(1, sizeof(struct ocfs2_slot_info), GFP_KERNEL);
+ if (!si) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ spin_lock_init(&si->si_lock);
+ si->si_num_slots = osb->max_slots;
+ si->si_size = OCFS2_MAX_SLOTS;
+
+ for(i = 0; i < si->si_num_slots; i++)
+ si->si_global_node_nums[i] = OCFS2_INVALID_SLOT;
+
+ inode = ocfs2_get_system_file_inode(osb, SLOT_MAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_extent_map_get_blocks(inode, 0ULL, 1, &blkno, NULL);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_read_block(osb, blkno, &bh, 0, inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ si->si_inode = inode;
+ si->si_bh = bh;
+ osb->slot_info = si;
+bail:
+ if (status < 0 && si)
+ ocfs2_free_slot_info(si);
+
+ return status;
+}
+
+void ocfs2_free_slot_info(struct ocfs2_slot_info *si)
+{
+ if (si->si_inode)
+ iput(si->si_inode);
+ if (si->si_bh)
+ brelse(si->si_bh);
+ kfree(si);
+}
+
+int ocfs2_find_slot(struct ocfs2_super *osb)
+{
+ int status;
+ s16 slot;
+ struct ocfs2_slot_info *si;
+
+ mlog_entry_void();
+
+ si = osb->slot_info;
+
+ ocfs2_update_slot_info(si);
+
+ spin_lock(&si->si_lock);
+ /* search for ourselves first and take the slot if it already
+ * exists. Perhaps we need to mark this in a variable for our
+ * own journal recovery? Possibly not, though we certainly
+ * need to warn to the user */
+ slot = __ocfs2_node_num_to_slot(si, osb->node_num);
+ if (slot == OCFS2_INVALID_SLOT) {
+ /* if no slot yet, then just take 1st available
+ * one. */
+ slot = __ocfs2_find_empty_slot(si);
+ if (slot == OCFS2_INVALID_SLOT) {
+ spin_unlock(&si->si_lock);
+ mlog(ML_ERROR, "no free slots available!\n");
+ status = -EINVAL;
+ goto bail;
+ }
+ } else
+ mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
+ slot);
+
+ __ocfs2_fill_slot(si, slot, osb->node_num);
+ osb->slot_num = slot;
+ spin_unlock(&si->si_lock);
+
+ mlog(ML_NOTICE, "taking node slot %d\n", osb->slot_num);
+
+ status = ocfs2_update_disk_slots(osb, si);
+ if (status < 0)
+ mlog_errno(status);
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+void ocfs2_put_slot(struct ocfs2_super *osb)
+{
+ int status;
+ struct ocfs2_slot_info *si = osb->slot_info;
+
+ if (!si)
+ return;
+
+ ocfs2_update_slot_info(si);
+
+ spin_lock(&si->si_lock);
+ __ocfs2_fill_slot(si, osb->slot_num, OCFS2_INVALID_SLOT);
+ osb->slot_num = OCFS2_INVALID_SLOT;
+ spin_unlock(&si->si_lock);
+
+ status = ocfs2_update_disk_slots(osb, si);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ osb->slot_info = NULL;
+ ocfs2_free_slot_info(si);
+}
+
diff --git a/fs/ocfs2/slot_map.h b/fs/ocfs2/slot_map.h
new file mode 100644
index 000000000000..d8c8ceed031b
--- /dev/null
+++ b/fs/ocfs2/slot_map.h
@@ -0,0 +1,66 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * slotmap.h
+ *
+ * description here
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+
+#ifndef SLOTMAP_H
+#define SLOTMAP_H
+
+struct ocfs2_slot_info {
+ spinlock_t si_lock;
+
+ struct inode *si_inode;
+ struct buffer_head *si_bh;
+ unsigned int si_num_slots;
+ unsigned int si_size;
+ s16 si_global_node_nums[OCFS2_MAX_SLOTS];
+};
+
+int ocfs2_init_slot_info(struct ocfs2_super *osb);
+void ocfs2_free_slot_info(struct ocfs2_slot_info *si);
+
+int ocfs2_find_slot(struct ocfs2_super *osb);
+void ocfs2_put_slot(struct ocfs2_super *osb);
+
+void ocfs2_update_slot_info(struct ocfs2_slot_info *si);
+int ocfs2_update_disk_slots(struct ocfs2_super *osb,
+ struct ocfs2_slot_info *si);
+
+s16 ocfs2_node_num_to_slot(struct ocfs2_slot_info *si,
+ s16 global);
+void ocfs2_clear_slot(struct ocfs2_slot_info *si,
+ s16 slot_num);
+
+void ocfs2_populate_mounted_map(struct ocfs2_super *osb);
+
+static inline int ocfs2_is_empty_slot(struct ocfs2_slot_info *si,
+ int slot_num)
+{
+ BUG_ON(slot_num == OCFS2_INVALID_SLOT);
+ assert_spin_locked(&si->si_lock);
+
+ return si->si_global_node_nums[slot_num] == OCFS2_INVALID_SLOT;
+}
+
+#endif
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
new file mode 100644
index 000000000000..c46c164aefbb
--- /dev/null
+++ b/fs/ocfs2/suballoc.c
@@ -0,0 +1,1651 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * suballoc.c
+ *
+ * metadata alloc and free
+ * Inspired by ext3 block groups.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#define MLOG_MASK_PREFIX ML_DISK_ALLOC
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "inode.h"
+#include "journal.h"
+#include "localalloc.h"
+#include "suballoc.h"
+#include "super.h"
+#include "sysfile.h"
+#include "uptodate.h"
+
+#include "buffer_head_io.h"
+
+static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
+static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
+static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
+static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *bg_bh,
+ u64 group_blkno,
+ u16 my_chain,
+ struct ocfs2_chain_list *cl);
+static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
+ struct inode *alloc_inode,
+ struct buffer_head *bh);
+
+static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac);
+
+static int ocfs2_cluster_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found);
+static int ocfs2_block_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found);
+static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno);
+static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno);
+static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+ int nr);
+static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
+ struct buffer_head *bg_bh,
+ unsigned int bits_wanted,
+ u16 *bit_off,
+ u16 *bits_found);
+static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits);
+static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits);
+
+static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head *bg_bh,
+ struct buffer_head *prev_bg_bh,
+ u16 chain);
+static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
+ u32 wanted);
+static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count);
+static inline u64 ocfs2_which_suballoc_group(u64 block,
+ unsigned int bit);
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+ u64 bg_blkno,
+ u16 bg_bit_off);
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+ u32 cluster);
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ u64 data_blkno,
+ u64 *bg_blkno,
+ u16 *bg_bit_off);
+
+void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
+{
+ if (ac->ac_inode)
+ iput(ac->ac_inode);
+ if (ac->ac_bh)
+ brelse(ac->ac_bh);
+ kfree(ac);
+}
+
+static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
+{
+ return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
+}
+
+static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *bg_bh,
+ u64 group_blkno,
+ u16 my_chain,
+ struct ocfs2_chain_list *cl)
+{
+ int status = 0;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+ struct super_block * sb = alloc_inode->i_sb;
+
+ mlog_entry_void();
+
+ if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) {
+ ocfs2_error(alloc_inode->i_sb, "group block (%"MLFu64") "
+ "!= b_blocknr (%llu)", group_blkno,
+ (unsigned long long) bg_bh->b_blocknr);
+ status = -EIO;
+ goto bail;
+ }
+
+ status = ocfs2_journal_access(handle,
+ alloc_inode,
+ bg_bh,
+ OCFS2_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ memset(bg, 0, sb->s_blocksize);
+ strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
+ bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
+ bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb));
+ bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl));
+ bg->bg_chain = cpu_to_le16(my_chain);
+ bg->bg_next_group = cl->cl_recs[my_chain].c_blkno;
+ bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno);
+ bg->bg_blkno = cpu_to_le64(group_blkno);
+ /* set the 1st bit in the bitmap to account for the descriptor block */
+ ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap);
+ bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1);
+
+ status = ocfs2_journal_dirty(handle, bg_bh);
+ if (status < 0)
+ mlog_errno(status);
+
+ /* There is no need to zero out or otherwise initialize the
+ * other blocks in a group - All valid FS metadata in a block
+ * group stores the superblock fs_generation value at
+ * allocation time. */
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static inline u16 ocfs2_find_smallest_chain(struct ocfs2_chain_list *cl)
+{
+ u16 curr, best;
+
+ best = curr = 0;
+ while (curr < le16_to_cpu(cl->cl_count)) {
+ if (le32_to_cpu(cl->cl_recs[best].c_total) >
+ le32_to_cpu(cl->cl_recs[curr].c_total))
+ best = curr;
+ curr++;
+ }
+ return best;
+}
+
+/*
+ * We expect the block group allocator to already be locked.
+ */
+static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
+ struct inode *alloc_inode,
+ struct buffer_head *bh)
+{
+ int status, credits;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data;
+ struct ocfs2_chain_list *cl;
+ struct ocfs2_alloc_context *ac = NULL;
+ struct ocfs2_journal_handle *handle = NULL;
+ u32 bit_off, num_bits;
+ u16 alloc_rec;
+ u64 bg_blkno;
+ struct buffer_head *bg_bh = NULL;
+ struct ocfs2_group_desc *bg;
+
+ BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode));
+
+ mlog_entry_void();
+
+ handle = ocfs2_alloc_handle(osb);
+ if (!handle) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ cl = &fe->id2.i_chain;
+ status = ocfs2_reserve_clusters(osb,
+ handle,
+ le16_to_cpu(cl->cl_cpg),
+ &ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ credits = ocfs2_calc_group_alloc_credits(osb->sb,
+ le16_to_cpu(cl->cl_cpg));
+ handle = ocfs2_start_trans(osb, handle, credits);
+ if (IS_ERR(handle)) {
+ status = PTR_ERR(handle);
+ handle = NULL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_claim_clusters(osb,
+ handle,
+ ac,
+ le16_to_cpu(cl->cl_cpg),
+ &bit_off,
+ &num_bits);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ alloc_rec = ocfs2_find_smallest_chain(cl);
+
+ /* setup the group */
+ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off);
+ mlog(0, "new descriptor, record %u, at block %"MLFu64"\n",
+ alloc_rec, bg_blkno);
+
+ bg_bh = sb_getblk(osb->sb, bg_blkno);
+ if (!bg_bh) {
+ status = -EIO;
+ mlog_errno(status);
+ goto bail;
+ }
+ ocfs2_set_new_buffer_uptodate(alloc_inode, bg_bh);
+
+ status = ocfs2_block_group_fill(handle,
+ alloc_inode,
+ bg_bh,
+ bg_blkno,
+ alloc_rec,
+ cl);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+
+ status = ocfs2_journal_access(handle, alloc_inode,
+ bh, OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ le32_add_cpu(&cl->cl_recs[alloc_rec].c_free,
+ le16_to_cpu(bg->bg_free_bits_count));
+ le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, le16_to_cpu(bg->bg_bits));
+ cl->cl_recs[alloc_rec].c_blkno = cpu_to_le64(bg_blkno);
+ if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count))
+ le16_add_cpu(&cl->cl_next_free_rec, 1);
+
+ le32_add_cpu(&fe->id1.bitmap1.i_used, le16_to_cpu(bg->bg_bits) -
+ le16_to_cpu(bg->bg_free_bits_count));
+ le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits));
+ le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg));
+
+ status = ocfs2_journal_dirty(handle, bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ spin_lock(&OCFS2_I(alloc_inode)->ip_lock);
+ OCFS2_I(alloc_inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
+ fe->i_size = cpu_to_le64(ocfs2_clusters_to_bytes(alloc_inode->i_sb,
+ le32_to_cpu(fe->i_clusters)));
+ spin_unlock(&OCFS2_I(alloc_inode)->ip_lock);
+ i_size_write(alloc_inode, le64_to_cpu(fe->i_size));
+ alloc_inode->i_blocks =
+ ocfs2_align_bytes_to_sectors(i_size_read(alloc_inode));
+
+ status = 0;
+bail:
+ if (handle)
+ ocfs2_commit_trans(handle);
+
+ if (ac)
+ ocfs2_free_alloc_context(ac);
+
+ if (bg_bh)
+ brelse(bg_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac)
+{
+ int status;
+ u32 bits_wanted = ac->ac_bits_wanted;
+ struct inode *alloc_inode = ac->ac_inode;
+ struct buffer_head *bh = NULL;
+ struct ocfs2_journal_handle *handle = ac->ac_handle;
+ struct ocfs2_dinode *fe;
+ u32 free_bits;
+
+ mlog_entry_void();
+
+ BUG_ON(handle->flags & OCFS2_HANDLE_STARTED);
+
+ ocfs2_handle_add_inode(handle, alloc_inode);
+ status = ocfs2_meta_lock(alloc_inode, handle, &bh, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
+ status = -EIO;
+ goto bail;
+ }
+ if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) {
+ ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator "
+ "# %"MLFu64, le64_to_cpu(fe->i_blkno));
+ status = -EIO;
+ goto bail;
+ }
+
+ free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) -
+ le32_to_cpu(fe->id1.bitmap1.i_used);
+
+ if (bits_wanted > free_bits) {
+ /* cluster bitmap never grows */
+ if (ocfs2_is_cluster_bitmap(alloc_inode)) {
+ mlog(0, "Disk Full: wanted=%u, free_bits=%u\n",
+ bits_wanted, free_bits);
+ status = -ENOSPC;
+ goto bail;
+ }
+
+ status = ocfs2_block_group_alloc(osb, alloc_inode, bh);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+ atomic_inc(&osb->alloc_stats.bg_extends);
+
+ /* You should never ask for this much metadata */
+ BUG_ON(bits_wanted >
+ (le32_to_cpu(fe->id1.bitmap1.i_total)
+ - le32_to_cpu(fe->id1.bitmap1.i_used)));
+ }
+
+ get_bh(bh);
+ ac->ac_bh = bh;
+bail:
+ if (bh)
+ brelse(bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_dinode *fe,
+ struct ocfs2_alloc_context **ac)
+{
+ int status;
+ struct inode *alloc_inode = NULL;
+
+ *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_bits_wanted = ocfs2_extend_meta_needed(fe);
+ (*ac)->ac_handle = handle;
+ (*ac)->ac_which = OCFS2_AC_USE_META;
+
+#ifndef OCFS2_USE_ALL_METADATA_SUBALLOCATORS
+ alloc_inode = ocfs2_get_system_file_inode(osb,
+ EXTENT_ALLOC_SYSTEM_INODE,
+ 0);
+#else
+ alloc_inode = ocfs2_get_system_file_inode(osb,
+ EXTENT_ALLOC_SYSTEM_INODE,
+ osb->slot_num);
+#endif
+ if (!alloc_inode) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_inode = igrab(alloc_inode);
+ (*ac)->ac_group_search = ocfs2_block_group_search;
+
+ status = ocfs2_reserve_suballoc_bits(osb, (*ac));
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ if ((status < 0) && *ac) {
+ ocfs2_free_alloc_context(*ac);
+ *ac = NULL;
+ }
+
+ if (alloc_inode)
+ iput(alloc_inode);
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context **ac)
+{
+ int status;
+ struct inode *alloc_inode = NULL;
+
+ *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_bits_wanted = 1;
+ (*ac)->ac_handle = handle;
+ (*ac)->ac_which = OCFS2_AC_USE_INODE;
+
+ alloc_inode = ocfs2_get_system_file_inode(osb,
+ INODE_ALLOC_SYSTEM_INODE,
+ osb->slot_num);
+ if (!alloc_inode) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_inode = igrab(alloc_inode);
+ (*ac)->ac_group_search = ocfs2_block_group_search;
+
+ status = ocfs2_reserve_suballoc_bits(osb, *ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ if ((status < 0) && *ac) {
+ ocfs2_free_alloc_context(*ac);
+ *ac = NULL;
+ }
+
+ if (alloc_inode)
+ iput(alloc_inode);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* local alloc code has to do the same thing, so rather than do this
+ * twice.. */
+int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac)
+{
+ int status;
+
+ ac->ac_inode = ocfs2_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!ac->ac_inode) {
+ status = -EINVAL;
+ mlog(ML_ERROR, "Could not get bitmap inode!\n");
+ goto bail;
+ }
+ ac->ac_which = OCFS2_AC_USE_MAIN;
+ ac->ac_group_search = ocfs2_cluster_group_search;
+
+ status = ocfs2_reserve_suballoc_bits(osb, ac);
+ if (status < 0 && status != -ENOSPC)
+ mlog_errno(status);
+bail:
+ return status;
+}
+
+/* Callers don't need to care which bitmap (local alloc or main) to
+ * use so we figure it out for them, but unfortunately this clutters
+ * things a bit. */
+int ocfs2_reserve_clusters(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ u32 bits_wanted,
+ struct ocfs2_alloc_context **ac)
+{
+ int status;
+
+ mlog_entry_void();
+
+ BUG_ON(!handle);
+
+ *ac = kcalloc(1, sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
+ if (!(*ac)) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ (*ac)->ac_bits_wanted = bits_wanted;
+ (*ac)->ac_handle = handle;
+
+ status = -ENOSPC;
+ if (ocfs2_alloc_should_use_local(osb, bits_wanted)) {
+ status = ocfs2_reserve_local_alloc_bits(osb,
+ handle,
+ bits_wanted,
+ *ac);
+ if ((status < 0) && (status != -ENOSPC)) {
+ mlog_errno(status);
+ goto bail;
+ } else if (status == -ENOSPC) {
+ /* reserve_local_bits will return enospc with
+ * the local alloc inode still locked, so we
+ * can change this safely here. */
+ mlog(0, "Disabling local alloc\n");
+ /* We set to OCFS2_LA_DISABLED so that umount
+ * can clean up what's left of the local
+ * allocation */
+ osb->local_alloc_state = OCFS2_LA_DISABLED;
+ }
+ }
+
+ if (status == -ENOSPC) {
+ status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac);
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ status = 0;
+bail:
+ if ((status < 0) && *ac) {
+ ocfs2_free_alloc_context(*ac);
+ *ac = NULL;
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * More or less lifted from ext3. I'll leave their description below:
+ *
+ * "For ext3 allocations, we must not reuse any blocks which are
+ * allocated in the bitmap buffer's "last committed data" copy. This
+ * prevents deletes from freeing up the page for reuse until we have
+ * committed the delete transaction.
+ *
+ * If we didn't do this, then deleting something and reallocating it as
+ * data would allow the old block to be overwritten before the
+ * transaction committed (because we force data to disk before commit).
+ * This would lead to corruption if we crashed between overwriting the
+ * data and committing the delete.
+ *
+ * @@@ We may want to make this allocation behaviour conditional on
+ * data-writes at some point, and disable it for metadata allocations or
+ * sync-data inodes."
+ *
+ * Note: OCFS2 already does this differently for metadata vs data
+ * allocations, as those bitmaps are seperate and undo access is never
+ * called on a metadata group descriptor.
+ */
+static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+ int nr)
+{
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+
+ if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))
+ return 0;
+ if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data)
+ return 1;
+
+ bg = (struct ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;
+ return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);
+}
+
+static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
+ struct buffer_head *bg_bh,
+ unsigned int bits_wanted,
+ u16 *bit_off,
+ u16 *bits_found)
+{
+ void *bitmap;
+ u16 best_offset, best_size;
+ int offset, start, found, status = 0;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg);
+ return -EIO;
+ }
+
+ found = start = best_offset = best_size = 0;
+ bitmap = bg->bg_bitmap;
+
+ while((offset = ocfs2_find_next_zero_bit(bitmap,
+ le16_to_cpu(bg->bg_bits),
+ start)) != -1) {
+ if (offset == le16_to_cpu(bg->bg_bits))
+ break;
+
+ if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {
+ /* We found a zero, but we can't use it as it
+ * hasn't been put to disk yet! */
+ found = 0;
+ start = offset + 1;
+ } else if (offset == start) {
+ /* we found a zero */
+ found++;
+ /* move start to the next bit to test */
+ start++;
+ } else {
+ /* got a zero after some ones */
+ found = 1;
+ start = offset + 1;
+ }
+ if (found > best_size) {
+ best_size = found;
+ best_offset = start - found;
+ }
+ /* we got everything we needed */
+ if (found == bits_wanted) {
+ /* mlog(0, "Found it all!\n"); */
+ break;
+ }
+ }
+
+ /* XXX: I think the first clause is equivalent to the second
+ * - jlbec */
+ if (found == bits_wanted) {
+ *bit_off = start - found;
+ *bits_found = found;
+ } else if (best_size) {
+ *bit_off = best_offset;
+ *bits_found = best_size;
+ } else {
+ status = -ENOSPC;
+ /* No error log here -- see the comment above
+ * ocfs2_test_bg_bit_allocatable */
+ }
+
+ return status;
+}
+
+static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits)
+{
+ int status;
+ void *bitmap = bg->bg_bitmap;
+ int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
+
+ mlog_entry_void();
+
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
+ goto bail;
+ }
+ BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);
+
+ mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
+ num_bits);
+
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
+
+ status = ocfs2_journal_access(handle,
+ alloc_inode,
+ group_bh,
+ journal_type);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ le16_add_cpu(&bg->bg_free_bits_count, -num_bits);
+
+ while(num_bits--)
+ ocfs2_set_bit(bit_off++, bitmap);
+
+ status = ocfs2_journal_dirty(handle,
+ group_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* find the one with the most empty bits */
+static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl)
+{
+ u16 curr, best;
+
+ BUG_ON(!cl->cl_next_free_rec);
+
+ best = curr = 0;
+ while (curr < le16_to_cpu(cl->cl_next_free_rec)) {
+ if (le32_to_cpu(cl->cl_recs[curr].c_free) >
+ le32_to_cpu(cl->cl_recs[best].c_free))
+ best = curr;
+ curr++;
+ }
+
+ BUG_ON(best >= le16_to_cpu(cl->cl_next_free_rec));
+ return best;
+}
+
+static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *fe_bh,
+ struct buffer_head *bg_bh,
+ struct buffer_head *prev_bg_bh,
+ u16 chain)
+{
+ int status;
+ /* there is a really tiny chance the journal calls could fail,
+ * but we wouldn't want inconsistent blocks in *any* case. */
+ u64 fe_ptr, bg_ptr, prev_bg_ptr;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
+ struct ocfs2_group_desc *prev_bg = (struct ocfs2_group_desc *) prev_bg_bh->b_data;
+
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
+ status = -EIO;
+ goto out;
+ }
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
+ goto out;
+ }
+ if (!OCFS2_IS_VALID_GROUP_DESC(prev_bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, prev_bg);
+ status = -EIO;
+ goto out;
+ }
+
+ mlog(0, "In suballoc %"MLFu64", chain %u, move group %"MLFu64" to "
+ "top, prev = %"MLFu64"\n",
+ fe->i_blkno, chain, bg->bg_blkno, prev_bg->bg_blkno);
+
+ fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno);
+ bg_ptr = le64_to_cpu(bg->bg_next_group);
+ prev_bg_ptr = le64_to_cpu(prev_bg->bg_next_group);
+
+ status = ocfs2_journal_access(handle, alloc_inode, prev_bg_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ prev_bg->bg_next_group = bg->bg_next_group;
+
+ status = ocfs2_journal_dirty(handle, prev_bg_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ status = ocfs2_journal_access(handle, alloc_inode, bg_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ bg->bg_next_group = fe->id2.i_chain.cl_recs[chain].c_blkno;
+
+ status = ocfs2_journal_dirty(handle, bg_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ status = ocfs2_journal_access(handle, alloc_inode, fe_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ fe->id2.i_chain.cl_recs[chain].c_blkno = bg->bg_blkno;
+
+ status = ocfs2_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto out_rollback;
+ }
+
+ status = 0;
+out_rollback:
+ if (status < 0) {
+ fe->id2.i_chain.cl_recs[chain].c_blkno = cpu_to_le64(fe_ptr);
+ bg->bg_next_group = cpu_to_le64(bg_ptr);
+ prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);
+ }
+out:
+ mlog_exit(status);
+ return status;
+}
+
+static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg,
+ u32 wanted)
+{
+ return le16_to_cpu(bg->bg_free_bits_count) > wanted;
+}
+
+/* return 0 on success, -ENOSPC to keep searching and any other < 0
+ * value on error. */
+static int ocfs2_cluster_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found)
+{
+ int search = -ENOSPC;
+ int ret;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
+ u16 tmp_off, tmp_found;
+
+ BUG_ON(!ocfs2_is_cluster_bitmap(inode));
+
+ if (bg->bg_free_bits_count) {
+ ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+ group_bh, bits_wanted,
+ &tmp_off, &tmp_found);
+ if (ret)
+ return ret;
+
+ /* ocfs2_block_group_find_clear_bits() might
+ * return success, but we still want to return
+ * -ENOSPC unless it found the minimum number
+ * of bits. */
+ if (min_bits <= tmp_found) {
+ *bit_off = tmp_off;
+ *bits_found = tmp_found;
+ search = 0; /* success */
+ }
+ }
+
+ return search;
+}
+
+static int ocfs2_block_group_search(struct inode *inode,
+ struct buffer_head *group_bh,
+ u32 bits_wanted, u32 min_bits,
+ u16 *bit_off, u16 *bits_found)
+{
+ int ret = -ENOSPC;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
+
+ BUG_ON(min_bits != 1);
+ BUG_ON(ocfs2_is_cluster_bitmap(inode));
+
+ if (bg->bg_free_bits_count)
+ ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+ group_bh, bits_wanted,
+ bit_off, bits_found);
+
+ return ret;
+}
+
+static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno)
+{
+ int status;
+ u16 chain, tmp_bits;
+ u32 tmp_used;
+ u64 next_group;
+ struct ocfs2_journal_handle *handle = ac->ac_handle;
+ struct inode *alloc_inode = ac->ac_inode;
+ struct buffer_head *group_bh = NULL;
+ struct buffer_head *prev_group_bh = NULL;
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;
+ struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
+ struct ocfs2_group_desc *bg;
+
+ chain = ac->ac_chain;
+ mlog(0, "trying to alloc %u bits from chain %u, inode %"MLFu64"\n",
+ bits_wanted, chain, OCFS2_I(alloc_inode)->ip_blkno);
+
+ status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),
+ le64_to_cpu(cl->cl_recs[chain].c_blkno),
+ &group_bh, OCFS2_BH_CACHED, alloc_inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ bg = (struct ocfs2_group_desc *) group_bh->b_data;
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
+ goto bail;
+ }
+
+ status = -ENOSPC;
+ /* for now, the chain search is a bit simplistic. We just use
+ * the 1st group with any empty bits. */
+ while ((status = ac->ac_group_search(alloc_inode, group_bh,
+ bits_wanted, min_bits, bit_off,
+ &tmp_bits)) == -ENOSPC) {
+ if (!bg->bg_next_group)
+ break;
+
+ if (prev_group_bh) {
+ brelse(prev_group_bh);
+ prev_group_bh = NULL;
+ }
+ next_group = le64_to_cpu(bg->bg_next_group);
+ prev_group_bh = group_bh;
+ group_bh = NULL;
+ status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb),
+ next_group, &group_bh,
+ OCFS2_BH_CACHED, alloc_inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ bg = (struct ocfs2_group_desc *) group_bh->b_data;
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
+ goto bail;
+ }
+ }
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "alloc succeeds: we give %u bits from block group %"MLFu64"\n",
+ tmp_bits, bg->bg_blkno);
+
+ *num_bits = tmp_bits;
+
+ BUG_ON(*num_bits == 0);
+
+ /*
+ * Keep track of previous block descriptor read. When
+ * we find a target, if we have read more than X
+ * number of descriptors, and the target is reasonably
+ * empty, relink him to top of his chain.
+ *
+ * We've read 0 extra blocks and only send one more to
+ * the transaction, yet the next guy to search has a
+ * much easier time.
+ *
+ * Do this *after* figuring out how many bits we're taking out
+ * of our target group.
+ */
+ if (ac->ac_allow_chain_relink &&
+ (prev_group_bh) &&
+ (ocfs2_block_group_reasonably_empty(bg, *num_bits))) {
+ status = ocfs2_relink_block_group(handle, alloc_inode,
+ ac->ac_bh, group_bh,
+ prev_group_bh, chain);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+
+ /* Ok, claim our bits now: set the info on dinode, chainlist
+ * and then the group */
+ status = ocfs2_journal_access(handle,
+ alloc_inode,
+ ac->ac_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
+ fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used);
+ le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits));
+
+ status = ocfs2_journal_dirty(handle,
+ ac->ac_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_block_group_set_bits(handle,
+ alloc_inode,
+ bg,
+ group_bh,
+ *bit_off,
+ *num_bits);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "Allocated %u bits from suballocator %"MLFu64"\n",
+ *num_bits, fe->i_blkno);
+
+ *bg_blkno = le64_to_cpu(bg->bg_blkno);
+bail:
+ if (group_bh)
+ brelse(group_bh);
+ if (prev_group_bh)
+ brelse(prev_group_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* will give out up to bits_wanted contiguous bits. */
+static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno)
+{
+ int status;
+ u16 victim, i;
+ struct ocfs2_chain_list *cl;
+ struct ocfs2_dinode *fe;
+
+ mlog_entry_void();
+
+ BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
+ BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given));
+ BUG_ON(!ac->ac_bh);
+
+ fe = (struct ocfs2_dinode *) ac->ac_bh->b_data;
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(osb->sb, fe);
+ status = -EIO;
+ goto bail;
+ }
+ if (le32_to_cpu(fe->id1.bitmap1.i_used) >=
+ le32_to_cpu(fe->id1.bitmap1.i_total)) {
+ ocfs2_error(osb->sb, "Chain allocator dinode %"MLFu64" has %u"
+ "used bits but only %u total.",
+ le64_to_cpu(fe->i_blkno),
+ le32_to_cpu(fe->id1.bitmap1.i_used),
+ le32_to_cpu(fe->id1.bitmap1.i_total));
+ status = -EIO;
+ goto bail;
+ }
+
+ cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
+
+ victim = ocfs2_find_victim_chain(cl);
+ ac->ac_chain = victim;
+ ac->ac_allow_chain_relink = 1;
+
+ status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
+ num_bits, bg_blkno);
+ if (!status)
+ goto bail;
+ if (status < 0 && status != -ENOSPC) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ mlog(0, "Search of victim chain %u came up with nothing, "
+ "trying all chains now.\n", victim);
+
+ /* If we didn't pick a good victim, then just default to
+ * searching each chain in order. Don't allow chain relinking
+ * because we only calculate enough journal credits for one
+ * relink per alloc. */
+ ac->ac_allow_chain_relink = 0;
+ for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i ++) {
+ if (i == victim)
+ continue;
+ if (!cl->cl_recs[i].c_free)
+ continue;
+
+ ac->ac_chain = i;
+ status = ocfs2_search_chain(ac, bits_wanted, min_bits,
+ bit_off, num_bits,
+ bg_blkno);
+ if (!status)
+ break;
+ if (status < 0 && status != -ENOSPC) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+bail:
+
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_claim_metadata(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u16 *suballoc_bit_start,
+ unsigned int *num_bits,
+ u64 *blkno_start)
+{
+ int status;
+ u64 bg_blkno;
+
+ BUG_ON(!ac);
+ BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
+ BUG_ON(ac->ac_which != OCFS2_AC_USE_META);
+ BUG_ON(ac->ac_handle != handle);
+
+ status = ocfs2_claim_suballoc_bits(osb,
+ ac,
+ bits_wanted,
+ 1,
+ suballoc_bit_start,
+ num_bits,
+ &bg_blkno);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ atomic_inc(&osb->alloc_stats.bg_allocs);
+
+ *blkno_start = bg_blkno + (u64) *suballoc_bit_start;
+ ac->ac_bits_given += (*num_bits);
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+int ocfs2_claim_new_inode(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u16 *suballoc_bit,
+ u64 *fe_blkno)
+{
+ int status;
+ unsigned int num_bits;
+ u64 bg_blkno;
+
+ mlog_entry_void();
+
+ BUG_ON(!ac);
+ BUG_ON(ac->ac_bits_given != 0);
+ BUG_ON(ac->ac_bits_wanted != 1);
+ BUG_ON(ac->ac_which != OCFS2_AC_USE_INODE);
+ BUG_ON(ac->ac_handle != handle);
+
+ status = ocfs2_claim_suballoc_bits(osb,
+ ac,
+ 1,
+ 1,
+ suballoc_bit,
+ &num_bits,
+ &bg_blkno);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ atomic_inc(&osb->alloc_stats.bg_allocs);
+
+ BUG_ON(num_bits != 1);
+
+ *fe_blkno = bg_blkno + (u64) (*suballoc_bit);
+ ac->ac_bits_given++;
+ status = 0;
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/* translate a group desc. blkno and it's bitmap offset into
+ * disk cluster offset. */
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+ u64 bg_blkno,
+ u16 bg_bit_off)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ u32 cluster = 0;
+
+ BUG_ON(!ocfs2_is_cluster_bitmap(inode));
+
+ if (bg_blkno != osb->first_cluster_group_blkno)
+ cluster = ocfs2_blocks_to_clusters(inode->i_sb, bg_blkno);
+ cluster += (u32) bg_bit_off;
+ return cluster;
+}
+
+/* given a cluster offset, calculate which block group it belongs to
+ * and return that block offset. */
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+ u32 cluster)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ u32 group_no;
+
+ BUG_ON(!ocfs2_is_cluster_bitmap(inode));
+
+ group_no = cluster / osb->bitmap_cpg;
+ if (!group_no)
+ return osb->first_cluster_group_blkno;
+ return ocfs2_clusters_to_blocks(inode->i_sb,
+ group_no * osb->bitmap_cpg);
+}
+
+/* given the block number of a cluster start, calculate which cluster
+ * group and descriptor bitmap offset that corresponds to. */
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+ u64 data_blkno,
+ u64 *bg_blkno,
+ u16 *bg_bit_off)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ u32 data_cluster = ocfs2_blocks_to_clusters(osb->sb, data_blkno);
+
+ BUG_ON(!ocfs2_is_cluster_bitmap(inode));
+
+ *bg_blkno = ocfs2_which_cluster_group(inode,
+ data_cluster);
+
+ if (*bg_blkno == osb->first_cluster_group_blkno)
+ *bg_bit_off = (u16) data_cluster;
+ else
+ *bg_bit_off = (u16) ocfs2_blocks_to_clusters(osb->sb,
+ data_blkno - *bg_blkno);
+}
+
+/*
+ * min_bits - minimum contiguous chunk from this total allocation we
+ * can handle. set to what we asked for originally for a full
+ * contig. allocation, set to '1' to indicate we can deal with extents
+ * of any size.
+ */
+int ocfs2_claim_clusters(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 min_clusters,
+ u32 *cluster_start,
+ u32 *num_clusters)
+{
+ int status;
+ unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+ u64 bg_blkno;
+ u16 bg_bit_off;
+
+ mlog_entry_void();
+
+ BUG_ON(!ac);
+ BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted);
+
+ BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL
+ && ac->ac_which != OCFS2_AC_USE_MAIN);
+ BUG_ON(ac->ac_handle != handle);
+
+ if (ac->ac_which == OCFS2_AC_USE_LOCAL) {
+ status = ocfs2_claim_local_alloc_bits(osb,
+ handle,
+ ac,
+ bits_wanted,
+ cluster_start,
+ num_clusters);
+ if (!status)
+ atomic_inc(&osb->alloc_stats.local_data);
+ } else {
+ if (min_clusters > (osb->bitmap_cpg - 1)) {
+ /* The only paths asking for contiguousness
+ * should know about this already. */
+ mlog(ML_ERROR, "minimum allocation requested exceeds "
+ "group bitmap size!");
+ status = -ENOSPC;
+ goto bail;
+ }
+ /* clamp the current request down to a realistic size. */
+ if (bits_wanted > (osb->bitmap_cpg - 1))
+ bits_wanted = osb->bitmap_cpg - 1;
+
+ status = ocfs2_claim_suballoc_bits(osb,
+ ac,
+ bits_wanted,
+ min_clusters,
+ &bg_bit_off,
+ num_clusters,
+ &bg_blkno);
+ if (!status) {
+ *cluster_start =
+ ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
+ bg_blkno,
+ bg_bit_off);
+ atomic_inc(&osb->alloc_stats.bitmap_data);
+ }
+ }
+ if (status < 0) {
+ if (status != -ENOSPC)
+ mlog_errno(status);
+ goto bail;
+ }
+
+ ac->ac_bits_given += *num_clusters;
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static inline int ocfs2_block_group_clear_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct ocfs2_group_desc *bg,
+ struct buffer_head *group_bh,
+ unsigned int bit_off,
+ unsigned int num_bits)
+{
+ int status;
+ unsigned int tmp;
+ int journal_type = OCFS2_JOURNAL_ACCESS_WRITE;
+ struct ocfs2_group_desc *undo_bg = NULL;
+
+ mlog_entry_void();
+
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
+ goto bail;
+ }
+
+ mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
+
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
+
+ status = ocfs2_journal_access(handle, alloc_inode, group_bh,
+ journal_type);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ undo_bg = (struct ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data;
+
+ tmp = num_bits;
+ while(tmp--) {
+ ocfs2_clear_bit((bit_off + tmp),
+ (unsigned long *) bg->bg_bitmap);
+ if (ocfs2_is_cluster_bitmap(alloc_inode))
+ ocfs2_set_bit(bit_off + tmp,
+ (unsigned long *) undo_bg->bg_bitmap);
+ }
+ le16_add_cpu(&bg->bg_free_bits_count, num_bits);
+
+ status = ocfs2_journal_dirty(handle, group_bh);
+ if (status < 0)
+ mlog_errno(status);
+bail:
+ return status;
+}
+
+/*
+ * expects the suballoc inode to already be locked.
+ */
+static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle,
+ struct inode *alloc_inode,
+ struct buffer_head *alloc_bh,
+ unsigned int start_bit,
+ u64 bg_blkno,
+ unsigned int count)
+{
+ int status = 0;
+ u32 tmp_used;
+ struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
+ struct ocfs2_dinode *fe = (struct ocfs2_dinode *) alloc_bh->b_data;
+ struct ocfs2_chain_list *cl = &fe->id2.i_chain;
+ struct buffer_head *group_bh = NULL;
+ struct ocfs2_group_desc *group;
+
+ mlog_entry_void();
+
+ if (!OCFS2_IS_VALID_DINODE(fe)) {
+ OCFS2_RO_ON_INVALID_DINODE(alloc_inode->i_sb, fe);
+ status = -EIO;
+ goto bail;
+ }
+ BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl));
+
+ mlog(0, "suballocator %"MLFu64": freeing %u bits from group %"MLFu64
+ ", starting at %u\n",
+ OCFS2_I(alloc_inode)->ip_blkno, count, bg_blkno,
+ start_bit);
+
+ status = ocfs2_read_block(osb, bg_blkno, &group_bh, OCFS2_BH_CACHED,
+ alloc_inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ group = (struct ocfs2_group_desc *) group_bh->b_data;
+ if (!OCFS2_IS_VALID_GROUP_DESC(group)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group);
+ status = -EIO;
+ goto bail;
+ }
+ BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits));
+
+ status = ocfs2_block_group_clear_bits(handle, alloc_inode,
+ group, group_bh,
+ start_bit, count);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = ocfs2_journal_access(handle, alloc_inode, alloc_bh,
+ OCFS2_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ le32_add_cpu(&cl->cl_recs[le16_to_cpu(group->bg_chain)].c_free,
+ count);
+ tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
+ fe->id1.bitmap1.i_used = cpu_to_le32(tmp_used - count);
+
+ status = ocfs2_journal_dirty(handle, alloc_bh);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+bail:
+ if (group_bh)
+ brelse(group_bh);
+
+ mlog_exit(status);
+ return status;
+}
+
+static inline u64 ocfs2_which_suballoc_group(u64 block, unsigned int bit)
+{
+ u64 group = block - (u64) bit;
+
+ return group;
+}
+
+int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
+ struct inode *inode_alloc_inode,
+ struct buffer_head *inode_alloc_bh,
+ struct ocfs2_dinode *di)
+{
+ u64 blk = le64_to_cpu(di->i_blkno);
+ u16 bit = le16_to_cpu(di->i_suballoc_bit);
+ u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+
+ return ocfs2_free_suballoc_bits(handle, inode_alloc_inode,
+ inode_alloc_bh, bit, bg_blkno, 1);
+}
+
+int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
+ struct inode *eb_alloc_inode,
+ struct buffer_head *eb_alloc_bh,
+ struct ocfs2_extent_block *eb)
+{
+ u64 blk = le64_to_cpu(eb->h_blkno);
+ u16 bit = le16_to_cpu(eb->h_suballoc_bit);
+ u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+
+ return ocfs2_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
+ bit, bg_blkno, 1);
+}
+
+int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
+ struct inode *bitmap_inode,
+ struct buffer_head *bitmap_bh,
+ u64 start_blk,
+ unsigned int num_clusters)
+{
+ int status;
+ u16 bg_start_bit;
+ u64 bg_blkno;
+ struct ocfs2_dinode *fe;
+
+ /* You can't ever have a contiguous set of clusters
+ * bigger than a block group bitmap so we never have to worry
+ * about looping on them. */
+
+ mlog_entry_void();
+
+ /* This is expensive. We can safely remove once this stuff has
+ * gotten tested really well. */
+ BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk)));
+
+ fe = (struct ocfs2_dinode *) bitmap_bh->b_data;
+
+ ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
+ &bg_start_bit);
+
+ mlog(0, "want to free %u clusters starting at block %"MLFu64"\n",
+ num_clusters, start_blk);
+ mlog(0, "bg_blkno = %"MLFu64", bg_start_bit = %u\n",
+ bg_blkno, bg_start_bit);
+
+ status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
+ bg_start_bit, bg_blkno,
+ num_clusters);
+ if (status < 0)
+ mlog_errno(status);
+
+ mlog_exit(status);
+ return status;
+}
+
+static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg)
+{
+ printk("Block Group:\n");
+ printk("bg_signature: %s\n", bg->bg_signature);
+ printk("bg_size: %u\n", bg->bg_size);
+ printk("bg_bits: %u\n", bg->bg_bits);
+ printk("bg_free_bits_count: %u\n", bg->bg_free_bits_count);
+ printk("bg_chain: %u\n", bg->bg_chain);
+ printk("bg_generation: %u\n", le32_to_cpu(bg->bg_generation));
+ printk("bg_next_group: %"MLFu64"\n", bg->bg_next_group);
+ printk("bg_parent_dinode: %"MLFu64"\n", bg->bg_parent_dinode);
+ printk("bg_blkno: %"MLFu64"\n", bg->bg_blkno);
+}
+
+static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe)
+{
+ int i;
+
+ printk("Suballoc Inode %"MLFu64":\n", fe->i_blkno);
+ printk("i_signature: %s\n", fe->i_signature);
+ printk("i_size: %"MLFu64"\n", fe->i_size);
+ printk("i_clusters: %u\n", fe->i_clusters);
+ printk("i_generation: %u\n",
+ le32_to_cpu(fe->i_generation));
+ printk("id1.bitmap1.i_used: %u\n",
+ le32_to_cpu(fe->id1.bitmap1.i_used));
+ printk("id1.bitmap1.i_total: %u\n",
+ le32_to_cpu(fe->id1.bitmap1.i_total));
+ printk("id2.i_chain.cl_cpg: %u\n", fe->id2.i_chain.cl_cpg);
+ printk("id2.i_chain.cl_bpc: %u\n", fe->id2.i_chain.cl_bpc);
+ printk("id2.i_chain.cl_count: %u\n", fe->id2.i_chain.cl_count);
+ printk("id2.i_chain.cl_next_free_rec: %u\n",
+ fe->id2.i_chain.cl_next_free_rec);
+ for(i = 0; i < fe->id2.i_chain.cl_next_free_rec; i++) {
+ printk("fe->id2.i_chain.cl_recs[%d].c_free: %u\n", i,
+ fe->id2.i_chain.cl_recs[i].c_free);
+ printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i,
+ fe->id2.i_chain.cl_recs[i].c_total);
+ printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %"MLFu64"\n", i,
+ fe->id2.i_chain.cl_recs[i].c_blkno);
+ }
+}
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
new file mode 100644
index 000000000000..a76c82a7ceac
--- /dev/null
+++ b/fs/ocfs2/suballoc.h
@@ -0,0 +1,132 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * suballoc.h
+ *
+ * Defines sub allocator api
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef _CHAINALLOC_H_
+#define _CHAINALLOC_H_
+
+typedef int (group_search_t)(struct inode *,
+ struct buffer_head *,
+ u32,
+ u32,
+ u16 *,
+ u16 *);
+
+struct ocfs2_alloc_context {
+ struct inode *ac_inode; /* which bitmap are we allocating from? */
+ struct buffer_head *ac_bh; /* file entry bh */
+ u32 ac_bits_wanted;
+ u32 ac_bits_given;
+#define OCFS2_AC_USE_LOCAL 1
+#define OCFS2_AC_USE_MAIN 2
+#define OCFS2_AC_USE_INODE 3
+#define OCFS2_AC_USE_META 4
+ u32 ac_which;
+ struct ocfs2_journal_handle *ac_handle;
+
+ /* these are used by the chain search */
+ u16 ac_chain;
+ int ac_allow_chain_relink;
+ group_search_t *ac_group_search;
+};
+
+void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
+static inline int ocfs2_alloc_context_bits_left(struct ocfs2_alloc_context *ac)
+{
+ return ac->ac_bits_wanted - ac->ac_bits_given;
+}
+
+int ocfs2_reserve_new_metadata(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_dinode *fe,
+ struct ocfs2_alloc_context **ac);
+int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context **ac);
+int ocfs2_reserve_clusters(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ u32 bits_wanted,
+ struct ocfs2_alloc_context **ac);
+
+int ocfs2_claim_metadata(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u16 *suballoc_bit_start,
+ u32 *num_bits,
+ u64 *blkno_start);
+int ocfs2_claim_new_inode(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u16 *suballoc_bit,
+ u64 *fe_blkno);
+int ocfs2_claim_clusters(struct ocfs2_super *osb,
+ struct ocfs2_journal_handle *handle,
+ struct ocfs2_alloc_context *ac,
+ u32 min_clusters,
+ u32 *cluster_start,
+ u32 *num_clusters);
+
+int ocfs2_free_dinode(struct ocfs2_journal_handle *handle,
+ struct inode *inode_alloc_inode,
+ struct buffer_head *inode_alloc_bh,
+ struct ocfs2_dinode *di);
+int ocfs2_free_extent_block(struct ocfs2_journal_handle *handle,
+ struct inode *eb_alloc_inode,
+ struct buffer_head *eb_alloc_bh,
+ struct ocfs2_extent_block *eb);
+int ocfs2_free_clusters(struct ocfs2_journal_handle *handle,
+ struct inode *bitmap_inode,
+ struct buffer_head *bitmap_bh,
+ u64 start_blk,
+ unsigned int num_clusters);
+
+static inline u32 ocfs2_cluster_from_desc(struct ocfs2_super *osb,
+ u64 bg_blkno)
+{
+ /* This should work for all block group descriptors as only
+ * the 1st group descriptor of the cluster bitmap is
+ * different. */
+
+ if (bg_blkno == osb->first_cluster_group_blkno)
+ return 0;
+
+ /* the rest of the block groups are located at the beginning
+ * of their 1st cluster, so a direct translation just
+ * works. */
+ return ocfs2_blocks_to_clusters(osb->sb, bg_blkno);
+}
+
+static inline int ocfs2_is_cluster_bitmap(struct inode *inode)
+{
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ return osb->bitmap_blkno == OCFS2_I(inode)->ip_blkno;
+}
+
+/* This is for local alloc ONLY. Others should use the task-specific
+ * apis above. */
+int ocfs2_reserve_cluster_bitmap_bits(struct ocfs2_super *osb,
+ struct ocfs2_alloc_context *ac);
+
+#endif /* _CHAINALLOC_H_ */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
new file mode 100644
index 000000000000..364d64bd5f10
--- /dev/null
+++ b/fs/ocfs2/super.c
@@ -0,0 +1,1733 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * super.c
+ *
+ * load/unload driver, mount/dismount volumes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/utsname.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/statfs.h>
+#include <linux/moduleparam.h>
+#include <linux/blkdev.h>
+#include <linux/socket.h>
+#include <linux/inet.h>
+#include <linux/parser.h>
+#include <linux/crc32.h>
+#include <linux/debugfs.h>
+
+#include <cluster/nodemanager.h>
+
+#define MLOG_MASK_PREFIX ML_SUPER
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+/* this should be the only file to include a version 1 header */
+#include "ocfs1_fs_compat.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "export.h"
+#include "extent_map.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "journal.h"
+#include "localalloc.h"
+#include "namei.h"
+#include "slot_map.h"
+#include "super.h"
+#include "sysfile.h"
+#include "uptodate.h"
+#include "ver.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+/*
+ * Globals
+ */
+static spinlock_t ocfs2_globals_lock = SPIN_LOCK_UNLOCKED;
+
+static u32 osb_id; /* Keeps track of next available OSB Id */
+
+static kmem_cache_t *ocfs2_inode_cachep = NULL;
+
+kmem_cache_t *ocfs2_lock_cache = NULL;
+
+/* OCFS2 needs to schedule several differnt types of work which
+ * require cluster locking, disk I/O, recovery waits, etc. Since these
+ * types of work tend to be heavy we avoid using the kernel events
+ * workqueue and schedule on our own. */
+struct workqueue_struct *ocfs2_wq = NULL;
+
+static struct dentry *ocfs2_debugfs_root = NULL;
+
+MODULE_AUTHOR("Oracle");
+MODULE_LICENSE("GPL");
+
+static int ocfs2_parse_options(struct super_block *sb, char *options,
+ unsigned long *mount_opt, int is_remount);
+static void ocfs2_put_super(struct super_block *sb);
+static int ocfs2_mount_volume(struct super_block *sb);
+static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
+static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err);
+static int ocfs2_initialize_mem_caches(void);
+static void ocfs2_free_mem_caches(void);
+static void ocfs2_delete_osb(struct ocfs2_super *osb);
+
+static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf);
+
+static int ocfs2_sync_fs(struct super_block *sb, int wait);
+
+static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb);
+static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb);
+static int ocfs2_release_system_inodes(struct ocfs2_super *osb);
+static int ocfs2_fill_local_node_info(struct ocfs2_super *osb);
+static int ocfs2_check_volume(struct ocfs2_super *osb);
+static int ocfs2_verify_volume(struct ocfs2_dinode *di,
+ struct buffer_head *bh,
+ u32 sectsize);
+static int ocfs2_initialize_super(struct super_block *sb,
+ struct buffer_head *bh,
+ int sector_size);
+static int ocfs2_get_sector(struct super_block *sb,
+ struct buffer_head **bh,
+ int block,
+ int sect_size);
+static void ocfs2_write_super(struct super_block *sb);
+static struct inode *ocfs2_alloc_inode(struct super_block *sb);
+static void ocfs2_destroy_inode(struct inode *inode);
+
+static unsigned long long ocfs2_max_file_offset(unsigned int blockshift);
+
+static struct super_operations ocfs2_sops = {
+ .statfs = ocfs2_statfs,
+ .alloc_inode = ocfs2_alloc_inode,
+ .destroy_inode = ocfs2_destroy_inode,
+ .drop_inode = ocfs2_drop_inode,
+ .clear_inode = ocfs2_clear_inode,
+ .delete_inode = ocfs2_delete_inode,
+ .sync_fs = ocfs2_sync_fs,
+ .write_super = ocfs2_write_super,
+ .put_super = ocfs2_put_super,
+ .remount_fs = ocfs2_remount,
+};
+
+enum {
+ Opt_barrier,
+ Opt_err_panic,
+ Opt_err_ro,
+ Opt_intr,
+ Opt_nointr,
+ Opt_hb_none,
+ Opt_hb_local,
+ Opt_data_ordered,
+ Opt_data_writeback,
+ Opt_err,
+};
+
+static match_table_t tokens = {
+ {Opt_barrier, "barrier=%u"},
+ {Opt_err_panic, "errors=panic"},
+ {Opt_err_ro, "errors=remount-ro"},
+ {Opt_intr, "intr"},
+ {Opt_nointr, "nointr"},
+ {Opt_hb_none, OCFS2_HB_NONE},
+ {Opt_hb_local, OCFS2_HB_LOCAL},
+ {Opt_data_ordered, "data=ordered"},
+ {Opt_data_writeback, "data=writeback"},
+ {Opt_err, NULL}
+};
+
+/*
+ * write_super and sync_fs ripped right out of ext3.
+ */
+static void ocfs2_write_super(struct super_block *sb)
+{
+ if (mutex_trylock(&sb->s_lock) != 0)
+ BUG();
+ sb->s_dirt = 0;
+}
+
+static int ocfs2_sync_fs(struct super_block *sb, int wait)
+{
+ int status = 0;
+ tid_t target;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ sb->s_dirt = 0;
+
+ if (ocfs2_is_hard_readonly(osb))
+ return -EROFS;
+
+ if (wait) {
+ status = ocfs2_flush_truncate_log(osb);
+ if (status < 0)
+ mlog_errno(status);
+ } else {
+ ocfs2_schedule_truncate_log_flush(osb, 0);
+ }
+
+ if (journal_start_commit(OCFS2_SB(sb)->journal->j_journal, &target)) {
+ if (wait)
+ log_wait_commit(OCFS2_SB(sb)->journal->j_journal,
+ target);
+ }
+ return 0;
+}
+
+static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb)
+{
+ struct inode *new = NULL;
+ int status = 0;
+ int i;
+
+ mlog_entry_void();
+
+ new = ocfs2_iget(osb, osb->root_blkno);
+ if (IS_ERR(new)) {
+ status = PTR_ERR(new);
+ mlog_errno(status);
+ goto bail;
+ }
+ osb->root_inode = new;
+
+ new = ocfs2_iget(osb, osb->system_dir_blkno);
+ if (IS_ERR(new)) {
+ status = PTR_ERR(new);
+ mlog_errno(status);
+ goto bail;
+ }
+ osb->sys_root_inode = new;
+
+ for (i = OCFS2_FIRST_ONLINE_SYSTEM_INODE;
+ i <= OCFS2_LAST_GLOBAL_SYSTEM_INODE; i++) {
+ new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
+ if (!new) {
+ ocfs2_release_system_inodes(osb);
+ status = -EINVAL;
+ mlog_errno(status);
+ /* FIXME: Should ERROR_RO_FS */
+ mlog(ML_ERROR, "Unable to load system inode %d, "
+ "possibly corrupt fs?", i);
+ goto bail;
+ }
+ // the array now has one ref, so drop this one
+ iput(new);
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb)
+{
+ struct inode *new = NULL;
+ int status = 0;
+ int i;
+
+ mlog_entry_void();
+
+ for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1;
+ i < NUM_SYSTEM_INODES;
+ i++) {
+ new = ocfs2_get_system_file_inode(osb, i, osb->slot_num);
+ if (!new) {
+ ocfs2_release_system_inodes(osb);
+ status = -EINVAL;
+ mlog(ML_ERROR, "status=%d, sysfile=%d, slot=%d\n",
+ status, i, osb->slot_num);
+ goto bail;
+ }
+ /* the array now has one ref, so drop this one */
+ iput(new);
+ }
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_release_system_inodes(struct ocfs2_super *osb)
+{
+ int status = 0, i;
+ struct inode *inode;
+
+ mlog_entry_void();
+
+ for (i = 0; i < NUM_SYSTEM_INODES; i++) {
+ inode = osb->system_inodes[i];
+ if (inode) {
+ iput(inode);
+ osb->system_inodes[i] = NULL;
+ }
+ }
+
+ inode = osb->sys_root_inode;
+ if (inode) {
+ iput(inode);
+ osb->sys_root_inode = NULL;
+ }
+
+ inode = osb->root_inode;
+ if (inode) {
+ iput(inode);
+ osb->root_inode = NULL;
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+/* We're allocating fs objects, use GFP_NOFS */
+static struct inode *ocfs2_alloc_inode(struct super_block *sb)
+{
+ struct ocfs2_inode_info *oi;
+
+ oi = kmem_cache_alloc(ocfs2_inode_cachep, SLAB_NOFS);
+ if (!oi)
+ return NULL;
+
+ return &oi->vfs_inode;
+}
+
+static void ocfs2_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(ocfs2_inode_cachep, OCFS2_I(inode));
+}
+
+/* From xfs_super.c:xfs_max_file_offset
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.
+ */
+static unsigned long long ocfs2_max_file_offset(unsigned int blockshift)
+{
+ unsigned int pagefactor = 1;
+ unsigned int bitshift = BITS_PER_LONG - 1;
+
+ /* Figure out maximum filesize, on Linux this can depend on
+ * the filesystem blocksize (on 32 bit platforms).
+ * __block_prepare_write does this in an [unsigned] long...
+ * page->index << (PAGE_CACHE_SHIFT - bbits)
+ * So, for page sized blocks (4K on 32 bit platforms),
+ * this wraps at around 8Tb (hence MAX_LFS_FILESIZE which is
+ * (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
+ * but for smaller blocksizes it is less (bbits = log2 bsize).
+ * Note1: get_block_t takes a long (implicit cast from above)
+ * Note2: The Large Block Device (LBD and HAVE_SECTOR_T) patch
+ * can optionally convert the [unsigned] long from above into
+ * an [unsigned] long long.
+ */
+
+#if BITS_PER_LONG == 32
+# if defined(CONFIG_LBD)
+ BUG_ON(sizeof(sector_t) != 8);
+ pagefactor = PAGE_CACHE_SIZE;
+ bitshift = BITS_PER_LONG;
+# else
+ pagefactor = PAGE_CACHE_SIZE >> (PAGE_CACHE_SHIFT - blockshift);
+# endif
+#endif
+
+ return (((unsigned long long)pagefactor) << bitshift) - 1;
+}
+
+static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
+{
+ int incompat_features;
+ int ret = 0;
+ unsigned long parsed_options;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ if (!ocfs2_parse_options(sb, data, &parsed_options, 1)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) !=
+ (parsed_options & OCFS2_MOUNT_HB_LOCAL)) {
+ ret = -EINVAL;
+ mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n");
+ goto out;
+ }
+
+ if ((osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK) !=
+ (parsed_options & OCFS2_MOUNT_DATA_WRITEBACK)) {
+ ret = -EINVAL;
+ mlog(ML_ERROR, "Cannot change data mode on remount\n");
+ goto out;
+ }
+
+ /* We're going to/from readonly mode. */
+ if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
+ /* Lock here so the check of HARD_RO and the potential
+ * setting of SOFT_RO is atomic. */
+ spin_lock(&osb->osb_lock);
+ if (osb->osb_flags & OCFS2_OSB_HARD_RO) {
+ mlog(ML_ERROR, "Remount on readonly device is forbidden.\n");
+ ret = -EROFS;
+ goto unlock_osb;
+ }
+
+ if (*flags & MS_RDONLY) {
+ mlog(0, "Going to ro mode.\n");
+ sb->s_flags |= MS_RDONLY;
+ osb->osb_flags |= OCFS2_OSB_SOFT_RO;
+ } else {
+ mlog(0, "Making ro filesystem writeable.\n");
+
+ if (osb->osb_flags & OCFS2_OSB_ERROR_FS) {
+ mlog(ML_ERROR, "Cannot remount RDWR "
+ "filesystem due to previous errors.\n");
+ ret = -EROFS;
+ goto unlock_osb;
+ }
+ incompat_features = OCFS2_HAS_RO_COMPAT_FEATURE(sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP);
+ if (incompat_features) {
+ mlog(ML_ERROR, "Cannot remount RDWR because "
+ "of unsupported optional features "
+ "(%x).\n", incompat_features);
+ ret = -EINVAL;
+ goto unlock_osb;
+ }
+ sb->s_flags &= ~MS_RDONLY;
+ osb->osb_flags &= ~OCFS2_OSB_SOFT_RO;
+ }
+unlock_osb:
+ spin_unlock(&osb->osb_lock);
+ }
+
+ if (!ret) {
+ if (!ocfs2_is_hard_readonly(osb))
+ ocfs2_set_journal_params(osb);
+
+ /* Only save off the new mount options in case of a successful
+ * remount. */
+ osb->s_mount_opt = parsed_options;
+ }
+out:
+ return ret;
+}
+
+static int ocfs2_sb_probe(struct super_block *sb,
+ struct buffer_head **bh,
+ int *sector_size)
+{
+ int status = 0, tmpstat;
+ struct ocfs1_vol_disk_hdr *hdr;
+ struct ocfs2_dinode *di;
+ int blksize;
+
+ *bh = NULL;
+
+ /* may be > 512 */
+ *sector_size = bdev_hardsect_size(sb->s_bdev);
+ if (*sector_size > OCFS2_MAX_BLOCKSIZE) {
+ mlog(ML_ERROR, "Hardware sector size too large: %d (max=%d)\n",
+ *sector_size, OCFS2_MAX_BLOCKSIZE);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ /* Can this really happen? */
+ if (*sector_size < OCFS2_MIN_BLOCKSIZE)
+ *sector_size = OCFS2_MIN_BLOCKSIZE;
+
+ /* check block zero for old format */
+ status = ocfs2_get_sector(sb, bh, 0, *sector_size);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ hdr = (struct ocfs1_vol_disk_hdr *) (*bh)->b_data;
+ if (hdr->major_version == OCFS1_MAJOR_VERSION) {
+ mlog(ML_ERROR, "incompatible version: %u.%u\n",
+ hdr->major_version, hdr->minor_version);
+ status = -EINVAL;
+ }
+ if (memcmp(hdr->signature, OCFS1_VOLUME_SIGNATURE,
+ strlen(OCFS1_VOLUME_SIGNATURE)) == 0) {
+ mlog(ML_ERROR, "incompatible volume signature: %8s\n",
+ hdr->signature);
+ status = -EINVAL;
+ }
+ brelse(*bh);
+ *bh = NULL;
+ if (status < 0) {
+ mlog(ML_ERROR, "This is an ocfs v1 filesystem which must be "
+ "upgraded before mounting with ocfs v2\n");
+ goto bail;
+ }
+
+ /*
+ * Now check at magic offset for 512, 1024, 2048, 4096
+ * blocksizes. 4096 is the maximum blocksize because it is
+ * the minimum clustersize.
+ */
+ status = -EINVAL;
+ for (blksize = *sector_size;
+ blksize <= OCFS2_MAX_BLOCKSIZE;
+ blksize <<= 1) {
+ tmpstat = ocfs2_get_sector(sb, bh,
+ OCFS2_SUPER_BLOCK_BLKNO,
+ blksize);
+ if (tmpstat < 0) {
+ status = tmpstat;
+ mlog_errno(status);
+ goto bail;
+ }
+ di = (struct ocfs2_dinode *) (*bh)->b_data;
+ status = ocfs2_verify_volume(di, *bh, blksize);
+ if (status >= 0)
+ goto bail;
+ brelse(*bh);
+ *bh = NULL;
+ if (status != -EAGAIN)
+ break;
+ }
+
+bail:
+ return status;
+}
+
+static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+{
+ struct dentry *root;
+ int status, sector_size;
+ unsigned long parsed_opt;
+ struct inode *inode = NULL;
+ struct ocfs2_super *osb = NULL;
+ struct buffer_head *bh = NULL;
+
+ mlog_entry("%p, %p, %i", sb, data, silent);
+
+ /* for now we only have one cluster/node, make sure we see it
+ * in the heartbeat universe */
+ if (!o2hb_check_local_node_heartbeating()) {
+ status = -EINVAL;
+ goto read_super_error;
+ }
+
+ /* probe for superblock */
+ status = ocfs2_sb_probe(sb, &bh, &sector_size);
+ if (status < 0) {
+ mlog(ML_ERROR, "superblock probe failed!\n");
+ goto read_super_error;
+ }
+
+ status = ocfs2_initialize_super(sb, bh, sector_size);
+ osb = OCFS2_SB(sb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto read_super_error;
+ }
+ brelse(bh);
+ bh = NULL;
+
+ if (!ocfs2_parse_options(sb, data, &parsed_opt, 0)) {
+ status = -EINVAL;
+ goto read_super_error;
+ }
+ osb->s_mount_opt = parsed_opt;
+
+ sb->s_magic = OCFS2_SUPER_MAGIC;
+
+ /* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
+ * heartbeat=none */
+ if (bdev_read_only(sb->s_bdev)) {
+ if (!(sb->s_flags & MS_RDONLY)) {
+ status = -EACCES;
+ mlog(ML_ERROR, "Readonly device detected but readonly "
+ "mount was not specified.\n");
+ goto read_super_error;
+ }
+
+ /* You should not be able to start a local heartbeat
+ * on a readonly device. */
+ if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
+ status = -EROFS;
+ mlog(ML_ERROR, "Local heartbeat specified on readonly "
+ "device.\n");
+ goto read_super_error;
+ }
+
+ status = ocfs2_check_journals_nolocks(osb);
+ if (status < 0) {
+ if (status == -EROFS)
+ mlog(ML_ERROR, "Recovery required on readonly "
+ "file system, but write access is "
+ "unavailable.\n");
+ else
+ mlog_errno(status);
+ goto read_super_error;
+ }
+
+ ocfs2_set_ro_flag(osb, 1);
+
+ printk(KERN_NOTICE "Readonly device detected. No cluster "
+ "services will be utilized for this mount. Recovery "
+ "will be skipped.\n");
+ }
+
+ if (!ocfs2_is_hard_readonly(osb)) {
+ /* If this isn't a hard readonly mount, then we need
+ * to make sure that heartbeat is in a valid state,
+ * and that we mark ourselves soft readonly is -oro
+ * was specified. */
+ if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) {
+ mlog(ML_ERROR, "No heartbeat for device (%s)\n",
+ sb->s_id);
+ status = -EINVAL;
+ goto read_super_error;
+ }
+
+ if (sb->s_flags & MS_RDONLY)
+ ocfs2_set_ro_flag(osb, 0);
+ }
+
+ osb->osb_debug_root = debugfs_create_dir(osb->uuid_str,
+ ocfs2_debugfs_root);
+ if (!osb->osb_debug_root) {
+ status = -EINVAL;
+ mlog(ML_ERROR, "Unable to create per-mount debugfs root.\n");
+ goto read_super_error;
+ }
+
+ status = ocfs2_mount_volume(sb);
+ if (osb->root_inode)
+ inode = igrab(osb->root_inode);
+
+ if (status < 0)
+ goto read_super_error;
+
+ if (!inode) {
+ status = -EIO;
+ mlog_errno(status);
+ goto read_super_error;
+ }
+
+ root = d_alloc_root(inode);
+ if (!root) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto read_super_error;
+ }
+
+ sb->s_root = root;
+
+ ocfs2_complete_mount_recovery(osb);
+
+ printk("ocfs2: Mounting device (%u,%u) on (node %d, slot %d) with %s "
+ "data mode.\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), osb->node_num,
+ osb->slot_num,
+ osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" :
+ "ordered");
+
+ atomic_set(&osb->vol_state, VOLUME_MOUNTED);
+ wake_up(&osb->osb_mount_event);
+
+ mlog_exit(status);
+ return status;
+
+read_super_error:
+ if (bh != NULL)
+ brelse(bh);
+
+ if (inode)
+ iput(inode);
+
+ if (osb) {
+ atomic_set(&osb->vol_state, VOLUME_DISABLED);
+ wake_up(&osb->osb_mount_event);
+ ocfs2_dismount_volume(sb, 1);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type,
+ int flags,
+ const char *dev_name,
+ void *data)
+{
+ return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);
+}
+
+static struct file_system_type ocfs2_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "ocfs2",
+ .get_sb = ocfs2_get_sb, /* is this called when we mount
+ * the fs? */
+ .kill_sb = kill_block_super, /* set to the generic one
+ * right now, but do we
+ * need to change that? */
+ .fs_flags = FS_REQUIRES_DEV,
+ .next = NULL
+};
+
+static int ocfs2_parse_options(struct super_block *sb,
+ char *options,
+ unsigned long *mount_opt,
+ int is_remount)
+{
+ int status;
+ char *p;
+
+ mlog_entry("remount: %d, options: \"%s\"\n", is_remount,
+ options ? options : "(none)");
+
+ *mount_opt = 0;
+
+ if (!options) {
+ status = 1;
+ goto bail;
+ }
+
+ while ((p = strsep(&options, ",")) != NULL) {
+ int token, option;
+ substring_t args[MAX_OPT_ARGS];
+
+ if (!*p)
+ continue;
+
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case Opt_hb_local:
+ *mount_opt |= OCFS2_MOUNT_HB_LOCAL;
+ break;
+ case Opt_hb_none:
+ *mount_opt &= ~OCFS2_MOUNT_HB_LOCAL;
+ break;
+ case Opt_barrier:
+ if (match_int(&args[0], &option)) {
+ status = 0;
+ goto bail;
+ }
+ if (option)
+ *mount_opt |= OCFS2_MOUNT_BARRIER;
+ else
+ *mount_opt &= ~OCFS2_MOUNT_BARRIER;
+ break;
+ case Opt_intr:
+ *mount_opt &= ~OCFS2_MOUNT_NOINTR;
+ break;
+ case Opt_nointr:
+ *mount_opt |= OCFS2_MOUNT_NOINTR;
+ break;
+ case Opt_err_panic:
+ *mount_opt |= OCFS2_MOUNT_ERRORS_PANIC;
+ break;
+ case Opt_err_ro:
+ *mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC;
+ break;
+ case Opt_data_ordered:
+ *mount_opt &= ~OCFS2_MOUNT_DATA_WRITEBACK;
+ break;
+ case Opt_data_writeback:
+ *mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK;
+ break;
+ default:
+ mlog(ML_ERROR,
+ "Unrecognized mount option \"%s\" "
+ "or missing value\n", p);
+ status = 0;
+ goto bail;
+ }
+ }
+
+ status = 1;
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+static int __init ocfs2_init(void)
+{
+ int status;
+
+ mlog_entry_void();
+
+ ocfs2_print_version();
+
+ if (init_ocfs2_extent_maps())
+ return -ENOMEM;
+
+ status = init_ocfs2_uptodate_cache();
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_initialize_mem_caches();
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ ocfs2_wq = create_singlethread_workqueue("ocfs2_wq");
+ if (!ocfs2_wq) {
+ status = -ENOMEM;
+ goto leave;
+ }
+
+ spin_lock(&ocfs2_globals_lock);
+ osb_id = 0;
+ spin_unlock(&ocfs2_globals_lock);
+
+ ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL);
+ if (!ocfs2_debugfs_root) {
+ status = -EFAULT;
+ mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
+ }
+
+leave:
+ if (status < 0) {
+ ocfs2_free_mem_caches();
+ exit_ocfs2_uptodate_cache();
+ exit_ocfs2_extent_maps();
+ }
+
+ mlog_exit(status);
+
+ if (status >= 0) {
+ return register_filesystem(&ocfs2_fs_type);
+ } else
+ return -1;
+}
+
+static void __exit ocfs2_exit(void)
+{
+ mlog_entry_void();
+
+ if (ocfs2_wq) {
+ flush_workqueue(ocfs2_wq);
+ destroy_workqueue(ocfs2_wq);
+ }
+
+ debugfs_remove(ocfs2_debugfs_root);
+
+ ocfs2_free_mem_caches();
+
+ unregister_filesystem(&ocfs2_fs_type);
+
+ exit_ocfs2_extent_maps();
+
+ exit_ocfs2_uptodate_cache();
+
+ mlog_exit_void();
+}
+
+static void ocfs2_put_super(struct super_block *sb)
+{
+ mlog_entry("(0x%p)\n", sb);
+
+ ocfs2_sync_blockdev(sb);
+ ocfs2_dismount_volume(sb, 0);
+
+ mlog_exit_void();
+}
+
+static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+ struct ocfs2_super *osb;
+ u32 numbits, freebits;
+ int status;
+ struct ocfs2_dinode *bm_lock;
+ struct buffer_head *bh = NULL;
+ struct inode *inode = NULL;
+
+ mlog_entry("(%p, %p)\n", sb, buf);
+
+ osb = OCFS2_SB(sb);
+
+ inode = ocfs2_get_system_file_inode(osb,
+ GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!inode) {
+ mlog(ML_ERROR, "failed to get bitmap inode\n");
+ status = -EIO;
+ goto bail;
+ }
+
+ status = ocfs2_meta_lock(inode, NULL, &bh, 0);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ bm_lock = (struct ocfs2_dinode *) bh->b_data;
+
+ numbits = le32_to_cpu(bm_lock->id1.bitmap1.i_total);
+ freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
+
+ buf->f_type = OCFS2_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_namelen = OCFS2_MAX_FILENAME_LEN;
+ buf->f_blocks = ((sector_t) numbits) *
+ (osb->s_clustersize >> osb->sb->s_blocksize_bits);
+ buf->f_bfree = ((sector_t) freebits) *
+ (osb->s_clustersize >> osb->sb->s_blocksize_bits);
+ buf->f_bavail = buf->f_bfree;
+ buf->f_files = numbits;
+ buf->f_ffree = freebits;
+
+ brelse(bh);
+
+ ocfs2_meta_unlock(inode, 0);
+ status = 0;
+bail:
+ if (inode)
+ iput(inode);
+
+ mlog_exit(status);
+
+ return status;
+}
+
+static void ocfs2_inode_init_once(void *data,
+ kmem_cache_t *cachep,
+ unsigned long flags)
+{
+ struct ocfs2_inode_info *oi = data;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR) {
+ oi->ip_flags = 0;
+ oi->ip_open_count = 0;
+ spin_lock_init(&oi->ip_lock);
+ ocfs2_extent_map_init(&oi->vfs_inode);
+ INIT_LIST_HEAD(&oi->ip_handle_list);
+ INIT_LIST_HEAD(&oi->ip_io_markers);
+ oi->ip_handle = NULL;
+ oi->ip_created_trans = 0;
+ oi->ip_last_trans = 0;
+ oi->ip_dir_start_lookup = 0;
+
+ init_rwsem(&oi->ip_alloc_sem);
+ init_MUTEX(&(oi->ip_io_sem));
+
+ oi->ip_blkno = 0ULL;
+ oi->ip_clusters = 0;
+
+ ocfs2_lock_res_init_once(&oi->ip_rw_lockres);
+ ocfs2_lock_res_init_once(&oi->ip_meta_lockres);
+ ocfs2_lock_res_init_once(&oi->ip_data_lockres);
+
+ ocfs2_metadata_cache_init(&oi->vfs_inode);
+
+ inode_init_once(&oi->vfs_inode);
+ }
+}
+
+static int ocfs2_initialize_mem_caches(void)
+{
+ ocfs2_inode_cachep = kmem_cache_create("ocfs2_inode_cache",
+ sizeof(struct ocfs2_inode_info),
+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+ ocfs2_inode_init_once, NULL);
+ if (!ocfs2_inode_cachep)
+ return -ENOMEM;
+
+ ocfs2_lock_cache = kmem_cache_create("ocfs2_lock",
+ sizeof(struct ocfs2_journal_lock),
+ 0,
+ SLAB_NO_REAP|SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!ocfs2_lock_cache)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ocfs2_free_mem_caches(void)
+{
+ if (ocfs2_inode_cachep)
+ kmem_cache_destroy(ocfs2_inode_cachep);
+ if (ocfs2_lock_cache)
+ kmem_cache_destroy(ocfs2_lock_cache);
+
+ ocfs2_inode_cachep = NULL;
+ ocfs2_lock_cache = NULL;
+}
+
+static int ocfs2_get_sector(struct super_block *sb,
+ struct buffer_head **bh,
+ int block,
+ int sect_size)
+{
+ if (!sb_set_blocksize(sb, sect_size)) {
+ mlog(ML_ERROR, "unable to set blocksize\n");
+ return -EIO;
+ }
+
+ *bh = sb_getblk(sb, block);
+ if (!*bh) {
+ mlog_errno(-EIO);
+ return -EIO;
+ }
+ lock_buffer(*bh);
+ if (!buffer_dirty(*bh))
+ clear_buffer_uptodate(*bh);
+ unlock_buffer(*bh);
+ ll_rw_block(READ, 1, bh);
+ wait_on_buffer(*bh);
+ return 0;
+}
+
+/* ocfs2 1.0 only allows one cluster and node identity per kernel image. */
+static int ocfs2_fill_local_node_info(struct ocfs2_super *osb)
+{
+ int status;
+
+ /* XXX hold a ref on the node while mounte? easy enough, if
+ * desirable. */
+ osb->node_num = o2nm_this_node();
+ if (osb->node_num == O2NM_MAX_NODES) {
+ mlog(ML_ERROR, "could not find this host's node number\n");
+ status = -ENOENT;
+ goto bail;
+ }
+
+ mlog(ML_NOTICE, "I am node %d\n", osb->node_num);
+
+ status = 0;
+bail:
+ return status;
+}
+
+static int ocfs2_mount_volume(struct super_block *sb)
+{
+ int status = 0;
+ int unlock_super = 0;
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ mlog_entry_void();
+
+ if (ocfs2_is_hard_readonly(osb))
+ goto leave;
+
+ status = ocfs2_fill_local_node_info(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_register_hb_callbacks(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_dlm_init(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* requires vote_thread to be running. */
+ status = ocfs2_register_net_handlers(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_super_lock(osb, 1);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+ unlock_super = 1;
+
+ /* This will load up the node map and add ourselves to it. */
+ status = ocfs2_find_slot(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ ocfs2_populate_mounted_map(osb);
+
+ /* load all node-local system inodes */
+ status = ocfs2_init_local_system_inodes(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_check_volume(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ status = ocfs2_truncate_log_init(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto leave;
+ }
+
+ /* This should be sent *after* we recovered our journal as it
+ * will cause other nodes to unmark us as needing
+ * recovery. However, we need to send it *before* dropping the
+ * super block lock as otherwise their recovery threads might
+ * try to clean us up while we're live! */
+ status = ocfs2_request_mount_vote(osb);
+ if (status < 0)
+ mlog_errno(status);
+
+leave:
+ if (unlock_super)
+ ocfs2_super_unlock(osb, 1);
+
+ mlog_exit(status);
+ return status;
+}
+
+/* we can't grab the goofy sem lock from inside wait_event, so we use
+ * memory barriers to make sure that we'll see the null task before
+ * being woken up */
+static int ocfs2_recovery_thread_running(struct ocfs2_super *osb)
+{
+ mb();
+ return osb->recovery_thread_task != NULL;
+}
+
+static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
+{
+ int tmp;
+ struct ocfs2_super *osb = NULL;
+
+ mlog_entry("(0x%p)\n", sb);
+
+ BUG_ON(!sb);
+ osb = OCFS2_SB(sb);
+ BUG_ON(!osb);
+
+ ocfs2_shutdown_local_alloc(osb);
+
+ ocfs2_truncate_log_shutdown(osb);
+
+ /* disable any new recovery threads and wait for any currently
+ * running ones to exit. Do this before setting the vol_state. */
+ down(&osb->recovery_lock);
+ osb->disable_recovery = 1;
+ up(&osb->recovery_lock);
+ wait_event(osb->recovery_event, !ocfs2_recovery_thread_running(osb));
+
+ /* At this point, we know that no more recovery threads can be
+ * launched, so wait for any recovery completion work to
+ * complete. */
+ flush_workqueue(ocfs2_wq);
+
+ ocfs2_journal_shutdown(osb);
+
+ ocfs2_sync_blockdev(sb);
+
+ /* No dlm means we've failed during mount, so skip all the
+ * steps which depended on that to complete. */
+ if (osb->dlm) {
+ tmp = ocfs2_super_lock(osb, 1);
+ if (tmp < 0) {
+ mlog_errno(tmp);
+ return;
+ }
+
+ tmp = ocfs2_request_umount_vote(osb);
+ if (tmp < 0)
+ mlog_errno(tmp);
+
+ if (osb->slot_num != OCFS2_INVALID_SLOT)
+ ocfs2_put_slot(osb);
+
+ ocfs2_super_unlock(osb, 1);
+ }
+
+ ocfs2_release_system_inodes(osb);
+
+ if (osb->dlm) {
+ ocfs2_unregister_net_handlers(osb);
+
+ ocfs2_dlm_shutdown(osb);
+ }
+
+ ocfs2_clear_hb_callbacks(osb);
+
+ debugfs_remove(osb->osb_debug_root);
+
+ if (!mnt_err)
+ ocfs2_stop_heartbeat(osb);
+
+ atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
+
+ printk("ocfs2: Unmounting device (%u,%u) on (node %d)\n",
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev), osb->node_num);
+
+ ocfs2_delete_osb(osb);
+ kfree(osb);
+ sb->s_dev = 0;
+ sb->s_fs_info = NULL;
+}
+
+static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uuid,
+ unsigned uuid_bytes)
+{
+ int i, ret;
+ char *ptr;
+
+ BUG_ON(uuid_bytes != OCFS2_VOL_UUID_LEN);
+
+ osb->uuid_str = kcalloc(1, OCFS2_VOL_UUID_LEN * 2 + 1, GFP_KERNEL);
+ if (osb->uuid_str == NULL)
+ return -ENOMEM;
+
+ memcpy(osb->uuid, uuid, OCFS2_VOL_UUID_LEN);
+
+ for (i = 0, ptr = osb->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) {
+ /* print with null */
+ ret = snprintf(ptr, 3, "%02X", uuid[i]);
+ if (ret != 2) /* drop super cleans up */
+ return -EINVAL;
+ /* then only advance past the last char */
+ ptr += 2;
+ }
+
+ return 0;
+}
+
+static int ocfs2_initialize_super(struct super_block *sb,
+ struct buffer_head *bh,
+ int sector_size)
+{
+ int status = 0;
+ int i;
+ struct ocfs2_dinode *di = NULL;
+ struct inode *inode = NULL;
+ struct buffer_head *bitmap_bh = NULL;
+ struct ocfs2_journal *journal;
+ __le32 uuid_net_key;
+ struct ocfs2_super *osb;
+
+ mlog_entry_void();
+
+ osb = kcalloc(1, sizeof(struct ocfs2_super), GFP_KERNEL);
+ if (!osb) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ sb->s_fs_info = osb;
+ sb->s_op = &ocfs2_sops;
+ sb->s_export_op = &ocfs2_export_ops;
+ sb->s_flags |= MS_NOATIME;
+ /* this is needed to support O_LARGEFILE */
+ sb->s_maxbytes = ocfs2_max_file_offset(sb->s_blocksize_bits);
+
+ osb->sb = sb;
+ /* Save off for ocfs2_rw_direct */
+ osb->s_sectsize_bits = blksize_bits(sector_size);
+ if (!osb->s_sectsize_bits)
+ BUG();
+
+ osb->net_response_ids = 0;
+ spin_lock_init(&osb->net_response_lock);
+ INIT_LIST_HEAD(&osb->net_response_list);
+
+ INIT_LIST_HEAD(&osb->osb_net_handlers);
+ init_waitqueue_head(&osb->recovery_event);
+ spin_lock_init(&osb->vote_task_lock);
+ init_waitqueue_head(&osb->vote_event);
+ osb->vote_work_sequence = 0;
+ osb->vote_wake_sequence = 0;
+ INIT_LIST_HEAD(&osb->blocked_lock_list);
+ osb->blocked_lock_count = 0;
+ INIT_LIST_HEAD(&osb->vote_list);
+ spin_lock_init(&osb->osb_lock);
+
+ atomic_set(&osb->alloc_stats.moves, 0);
+ atomic_set(&osb->alloc_stats.local_data, 0);
+ atomic_set(&osb->alloc_stats.bitmap_data, 0);
+ atomic_set(&osb->alloc_stats.bg_allocs, 0);
+ atomic_set(&osb->alloc_stats.bg_extends, 0);
+
+ ocfs2_init_node_maps(osb);
+
+ snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
+ MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+
+ init_MUTEX(&osb->recovery_lock);
+
+ osb->disable_recovery = 0;
+ osb->recovery_thread_task = NULL;
+
+ init_waitqueue_head(&osb->checkpoint_event);
+ atomic_set(&osb->needs_checkpoint, 0);
+
+ osb->node_num = O2NM_INVALID_NODE_NUM;
+ osb->slot_num = OCFS2_INVALID_SLOT;
+
+ osb->local_alloc_state = OCFS2_LA_UNUSED;
+ osb->local_alloc_bh = NULL;
+
+ ocfs2_setup_hb_callbacks(osb);
+
+ init_waitqueue_head(&osb->osb_mount_event);
+
+ osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL);
+ if (!osb->vol_label) {
+ mlog(ML_ERROR, "unable to alloc vol label\n");
+ status = -ENOMEM;
+ goto bail;
+ }
+
+ osb->uuid = kmalloc(OCFS2_VOL_UUID_LEN, GFP_KERNEL);
+ if (!osb->uuid) {
+ mlog(ML_ERROR, "unable to alloc uuid\n");
+ status = -ENOMEM;
+ goto bail;
+ }
+
+ di = (struct ocfs2_dinode *)bh->b_data;
+
+ osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots);
+ if (osb->max_slots > OCFS2_MAX_SLOTS || osb->max_slots == 0) {
+ mlog(ML_ERROR, "Invalid number of node slots (%u)\n",
+ osb->max_slots);
+ status = -EINVAL;
+ goto bail;
+ }
+ mlog(ML_NOTICE, "max_slots for this device: %u\n", osb->max_slots);
+
+ osb->s_feature_compat =
+ le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_compat);
+ osb->s_feature_ro_compat =
+ le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_ro_compat);
+ osb->s_feature_incompat =
+ le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_incompat);
+
+ if ((i = OCFS2_HAS_INCOMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_INCOMPAT_SUPP))) {
+ mlog(ML_ERROR, "couldn't mount because of unsupported "
+ "optional features (%x).\n", i);
+ status = -EINVAL;
+ goto bail;
+ }
+ if (!(osb->sb->s_flags & MS_RDONLY) &&
+ (i = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, ~OCFS2_FEATURE_RO_COMPAT_SUPP))) {
+ mlog(ML_ERROR, "couldn't mount RDWR because of "
+ "unsupported optional features (%x).\n", i);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ get_random_bytes(&osb->s_next_generation, sizeof(u32));
+
+ /* FIXME
+ * This should be done in ocfs2_journal_init(), but unknown
+ * ordering issues will cause the filesystem to crash.
+ * If anyone wants to figure out what part of the code
+ * refers to osb->journal before ocfs2_journal_init() is run,
+ * be my guest.
+ */
+ /* initialize our journal structure */
+
+ journal = kcalloc(1, sizeof(struct ocfs2_journal), GFP_KERNEL);
+ if (!journal) {
+ mlog(ML_ERROR, "unable to alloc journal\n");
+ status = -ENOMEM;
+ goto bail;
+ }
+ osb->journal = journal;
+ journal->j_osb = osb;
+
+ atomic_set(&journal->j_num_trans, 0);
+ init_rwsem(&journal->j_trans_barrier);
+ init_waitqueue_head(&journal->j_checkpointed);
+ spin_lock_init(&journal->j_lock);
+ journal->j_trans_id = (unsigned long) 1;
+ INIT_LIST_HEAD(&journal->j_la_cleanups);
+ INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery, osb);
+ journal->j_state = OCFS2_JOURNAL_FREE;
+
+ /* get some pseudo constants for clustersize bits */
+ osb->s_clustersize_bits =
+ le32_to_cpu(di->id2.i_super.s_clustersize_bits);
+ osb->s_clustersize = 1 << osb->s_clustersize_bits;
+ mlog(0, "clusterbits=%d\n", osb->s_clustersize_bits);
+
+ if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE ||
+ osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) {
+ mlog(ML_ERROR, "Volume has invalid cluster size (%d)\n",
+ osb->s_clustersize);
+ status = -EINVAL;
+ goto bail;
+ }
+
+ if (ocfs2_clusters_to_blocks(osb->sb, le32_to_cpu(di->i_clusters) - 1)
+ > (u32)~0UL) {
+ mlog(ML_ERROR, "Volume might try to write to blocks beyond "
+ "what jbd can address in 32 bits.\n");
+ status = -EINVAL;
+ goto bail;
+ }
+
+ if (ocfs2_setup_osb_uuid(osb, di->id2.i_super.s_uuid,
+ sizeof(di->id2.i_super.s_uuid))) {
+ mlog(ML_ERROR, "Out of memory trying to setup our uuid.\n");
+ status = -ENOMEM;
+ goto bail;
+ }
+
+ memcpy(&uuid_net_key, &osb->uuid[i], sizeof(osb->net_key));
+ osb->net_key = le32_to_cpu(uuid_net_key);
+
+ strncpy(osb->vol_label, di->id2.i_super.s_label, 63);
+ osb->vol_label[63] = '\0';
+ osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
+ osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);
+ osb->first_cluster_group_blkno =
+ le64_to_cpu(di->id2.i_super.s_first_cluster_group);
+ osb->fs_generation = le32_to_cpu(di->i_fs_generation);
+ mlog(0, "vol_label: %s\n", osb->vol_label);
+ mlog(0, "uuid: %s\n", osb->uuid_str);
+ mlog(0, "root_blkno=%"MLFu64", system_dir_blkno=%"MLFu64"\n",
+ osb->root_blkno, osb->system_dir_blkno);
+
+ osb->osb_dlm_debug = ocfs2_new_dlm_debug();
+ if (!osb->osb_dlm_debug) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ atomic_set(&osb->vol_state, VOLUME_INIT);
+
+ /* load root, system_dir, and all global system inodes */
+ status = ocfs2_init_global_system_inodes(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /*
+ * global bitmap
+ */
+ inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE,
+ OCFS2_INVALID_SLOT);
+ if (!inode) {
+ status = -EINVAL;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;
+
+ status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0,
+ inode);
+ iput(inode);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ di = (struct ocfs2_dinode *) bitmap_bh->b_data;
+ osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg);
+ osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
+ brelse(bitmap_bh);
+ mlog(0, "cluster bitmap inode: %"MLFu64", clusters per group: %u\n",
+ osb->bitmap_blkno, osb->bitmap_cpg);
+
+ status = ocfs2_init_slot_info(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ /* Link this osb onto the global linked list of all osb structures. */
+ /* The Global Link List is mainted for the whole driver . */
+ spin_lock(&ocfs2_globals_lock);
+ osb->osb_id = osb_id;
+ if (osb_id < OCFS2_MAX_OSB_ID)
+ osb_id++;
+ else {
+ mlog(ML_ERROR, "Too many volumes mounted\n");
+ status = -ENOMEM;
+ }
+ spin_unlock(&ocfs2_globals_lock);
+
+bail:
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * will return: -EAGAIN if it is ok to keep searching for superblocks
+ * -EINVAL if there is a bad superblock
+ * 0 on success
+ */
+static int ocfs2_verify_volume(struct ocfs2_dinode *di,
+ struct buffer_head *bh,
+ u32 blksz)
+{
+ int status = -EAGAIN;
+
+ mlog_entry_void();
+
+ if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE,
+ strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) {
+ status = -EINVAL;
+ if ((1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits)) != blksz) {
+ mlog(ML_ERROR, "found superblock with incorrect block "
+ "size: found %u, should be %u\n",
+ 1 << le32_to_cpu(di->id2.i_super.s_blocksize_bits),
+ blksz);
+ } else if (le16_to_cpu(di->id2.i_super.s_major_rev_level) !=
+ OCFS2_MAJOR_REV_LEVEL ||
+ le16_to_cpu(di->id2.i_super.s_minor_rev_level) !=
+ OCFS2_MINOR_REV_LEVEL) {
+ mlog(ML_ERROR, "found superblock with bad version: "
+ "found %u.%u, should be %u.%u\n",
+ le16_to_cpu(di->id2.i_super.s_major_rev_level),
+ le16_to_cpu(di->id2.i_super.s_minor_rev_level),
+ OCFS2_MAJOR_REV_LEVEL,
+ OCFS2_MINOR_REV_LEVEL);
+ } else if (bh->b_blocknr != le64_to_cpu(di->i_blkno)) {
+ mlog(ML_ERROR, "bad block number on superblock: "
+ "found %"MLFu64", should be %llu\n",
+ di->i_blkno, (unsigned long long)bh->b_blocknr);
+ } else if (le32_to_cpu(di->id2.i_super.s_clustersize_bits) < 12 ||
+ le32_to_cpu(di->id2.i_super.s_clustersize_bits) > 20) {
+ mlog(ML_ERROR, "bad cluster size found: %u\n",
+ 1 << le32_to_cpu(di->id2.i_super.s_clustersize_bits));
+ } else if (!le64_to_cpu(di->id2.i_super.s_root_blkno)) {
+ mlog(ML_ERROR, "bad root_blkno: 0\n");
+ } else if (!le64_to_cpu(di->id2.i_super.s_system_dir_blkno)) {
+ mlog(ML_ERROR, "bad system_dir_blkno: 0\n");
+ } else if (le16_to_cpu(di->id2.i_super.s_max_slots) > OCFS2_MAX_SLOTS) {
+ mlog(ML_ERROR,
+ "Superblock slots found greater than file system "
+ "maximum: found %u, max %u\n",
+ le16_to_cpu(di->id2.i_super.s_max_slots),
+ OCFS2_MAX_SLOTS);
+ } else {
+ /* found it! */
+ status = 0;
+ }
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static int ocfs2_check_volume(struct ocfs2_super *osb)
+{
+ int status = 0;
+ int dirty;
+ struct ocfs2_dinode *local_alloc = NULL; /* only used if we
+ * recover
+ * ourselves. */
+
+ mlog_entry_void();
+
+ /* Init our journal object. */
+ status = ocfs2_journal_init(osb->journal, &dirty);
+ if (status < 0) {
+ mlog(ML_ERROR, "Could not initialize journal!\n");
+ goto finally;
+ }
+
+ /* If the journal was unmounted cleanly then we don't want to
+ * recover anything. Otherwise, journal_load will do that
+ * dirty work for us :) */
+ if (!dirty) {
+ status = ocfs2_journal_wipe(osb->journal, 0);
+ if (status < 0) {
+ mlog_errno(status);
+ goto finally;
+ }
+ } else {
+ mlog(ML_NOTICE, "File system was not unmounted cleanly, "
+ "recovering volume.\n");
+ }
+
+ /* will play back anything left in the journal. */
+ ocfs2_journal_load(osb->journal);
+
+ if (dirty) {
+ /* recover my local alloc if we didn't unmount cleanly. */
+ status = ocfs2_begin_local_alloc_recovery(osb,
+ osb->slot_num,
+ &local_alloc);
+ if (status < 0) {
+ mlog_errno(status);
+ goto finally;
+ }
+ /* we complete the recovery process after we've marked
+ * ourselves as mounted. */
+ }
+
+ mlog(0, "Journal loaded.\n");
+
+ status = ocfs2_load_local_alloc(osb);
+ if (status < 0) {
+ mlog_errno(status);
+ goto finally;
+ }
+
+ if (dirty) {
+ /* Recovery will be completed after we've mounted the
+ * rest of the volume. */
+ osb->dirty = 1;
+ osb->local_alloc_copy = local_alloc;
+ local_alloc = NULL;
+ }
+
+ /* go through each journal, trylock it and if you get the
+ * lock, and it's marked as dirty, set the bit in the recover
+ * map and launch a recovery thread for it. */
+ status = ocfs2_mark_dead_nodes(osb);
+ if (status < 0)
+ mlog_errno(status);
+
+finally:
+ if (local_alloc)
+ kfree(local_alloc);
+
+ mlog_exit(status);
+ return status;
+}
+
+/*
+ * The routine gets called from dismount or close whenever a dismount on
+ * volume is requested and the osb open count becomes 1.
+ * It will remove the osb from the global list and also free up all the
+ * initialized resources and fileobject.
+ */
+static void ocfs2_delete_osb(struct ocfs2_super *osb)
+{
+ mlog_entry_void();
+
+ /* This function assumes that the caller has the main osb resource */
+
+ if (osb->slot_info)
+ ocfs2_free_slot_info(osb->slot_info);
+
+ /* FIXME
+ * This belongs in journal shutdown, but because we have to
+ * allocate osb->journal at the start of ocfs2_initalize_osb(),
+ * we free it here.
+ */
+ kfree(osb->journal);
+ if (osb->local_alloc_copy)
+ kfree(osb->local_alloc_copy);
+ kfree(osb->uuid_str);
+ ocfs2_put_dlm_debug(osb->osb_dlm_debug);
+ memset(osb, 0, sizeof(struct ocfs2_super));
+
+ mlog_exit_void();
+}
+
+/* Put OCFS2 into a readonly state, or (if the user specifies it),
+ * panic(). We do not support continue-on-error operation. */
+static void ocfs2_handle_error(struct super_block *sb)
+{
+ struct ocfs2_super *osb = OCFS2_SB(sb);
+
+ if (osb->s_mount_opt & OCFS2_MOUNT_ERRORS_PANIC)
+ panic("OCFS2: (device %s): panic forced after error\n",
+ sb->s_id);
+
+ ocfs2_set_osb_flag(osb, OCFS2_OSB_ERROR_FS);
+
+ if (sb->s_flags & MS_RDONLY &&
+ (ocfs2_is_soft_readonly(osb) ||
+ ocfs2_is_hard_readonly(osb)))
+ return;
+
+ printk(KERN_CRIT "File system is now read-only due to the potential "
+ "of on-disk corruption. Please run fsck.ocfs2 once the file "
+ "system is unmounted.\n");
+ sb->s_flags |= MS_RDONLY;
+ ocfs2_set_ro_flag(osb, 0);
+}
+
+static char error_buf[1024];
+
+void __ocfs2_error(struct super_block *sb,
+ const char *function,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(error_buf, fmt, args);
+ va_end(args);
+
+ /* Not using mlog here because we want to show the actual
+ * function the error came from. */
+ printk(KERN_CRIT "OCFS2: ERROR (device %s): %s: %s\n",
+ sb->s_id, function, error_buf);
+
+ ocfs2_handle_error(sb);
+}
+
+/* Handle critical errors. This is intentionally more drastic than
+ * ocfs2_handle_error, so we only use for things like journal errors,
+ * etc. */
+void __ocfs2_abort(struct super_block* sb,
+ const char *function,
+ const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(error_buf, fmt, args);
+ va_end(args);
+
+ printk(KERN_CRIT "OCFS2: abort (device %s): %s: %s\n",
+ sb->s_id, function, error_buf);
+
+ /* We don't have the cluster support yet to go straight to
+ * hard readonly in here. Until then, we want to keep
+ * ocfs2_abort() so that we can at least mark critical
+ * errors.
+ *
+ * TODO: This should abort the journal and alert other nodes
+ * that our slot needs recovery. */
+
+ /* Force a panic(). This stinks, but it's better than letting
+ * things continue without having a proper hard readonly
+ * here. */
+ OCFS2_SB(sb)->s_mount_opt |= OCFS2_MOUNT_ERRORS_PANIC;
+ ocfs2_handle_error(sb);
+}
+
+module_init(ocfs2_init);
+module_exit(ocfs2_exit);
diff --git a/fs/ocfs2/super.h b/fs/ocfs2/super.h
new file mode 100644
index 000000000000..c564177dfbdc
--- /dev/null
+++ b/fs/ocfs2/super.h
@@ -0,0 +1,44 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * super.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_SUPER_H
+#define OCFS2_SUPER_H
+
+extern struct workqueue_struct *ocfs2_wq;
+
+int ocfs2_publish_get_mount_state(struct ocfs2_super *osb,
+ int node_num);
+
+void __ocfs2_error(struct super_block *sb,
+ const char *function,
+ const char *fmt, ...);
+#define ocfs2_error(sb, fmt, args...) __ocfs2_error(sb, __PRETTY_FUNCTION__, fmt, ##args)
+
+void __ocfs2_abort(struct super_block *sb,
+ const char *function,
+ const char *fmt, ...);
+#define ocfs2_abort(sb, fmt, args...) __ocfs2_abort(sb, __PRETTY_FUNCTION__, fmt, ##args)
+
+#endif /* OCFS2_SUPER_H */
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
new file mode 100644
index 000000000000..f6986bd79e75
--- /dev/null
+++ b/fs/ocfs2/symlink.c
@@ -0,0 +1,180 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * linux/cluster/ssi/cfs/symlink.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, 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.
+ *
+ * Questions/Comments/Bugfixes to ssic-linux-devel@lists.sourceforge.net
+ *
+ * Copyright (C) 1992 Rick Sladkey
+ *
+ * Optimization changes Copyright (C) 1994 Florian La Roche
+ *
+ * Jun 7 1999, cache symlink lookups in the page cache. -DaveM
+ *
+ * Portions Copyright (C) 2001 Compaq Computer Corporation
+ *
+ * ocfs2 symlink handling code.
+ *
+ * Copyright (C) 2004, 2005 Oracle.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/utsname.h>
+
+#define MLOG_MASK_PREFIX ML_NAMEI
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "file.h"
+#include "inode.h"
+#include "journal.h"
+#include "symlink.h"
+
+#include "buffer_head_io.h"
+
+static char *ocfs2_page_getlink(struct dentry * dentry,
+ struct page **ppage);
+static char *ocfs2_fast_symlink_getlink(struct inode *inode,
+ struct buffer_head **bh);
+
+/* get the link contents into pagecache */
+static char *ocfs2_page_getlink(struct dentry * dentry,
+ struct page **ppage)
+{
+ struct page * page;
+ struct address_space *mapping = dentry->d_inode->i_mapping;
+ page = read_cache_page(mapping, 0,
+ (filler_t *)mapping->a_ops->readpage, NULL);
+ if (IS_ERR(page))
+ goto sync_fail;
+ wait_on_page_locked(page);
+ if (!PageUptodate(page))
+ goto async_fail;
+ *ppage = page;
+ return kmap(page);
+
+async_fail:
+ page_cache_release(page);
+ return ERR_PTR(-EIO);
+
+sync_fail:
+ return (char*)page;
+}
+
+static char *ocfs2_fast_symlink_getlink(struct inode *inode,
+ struct buffer_head **bh)
+{
+ int status;
+ char *link = NULL;
+ struct ocfs2_dinode *fe;
+
+ mlog_entry_void();
+
+ status = ocfs2_read_block(OCFS2_SB(inode->i_sb),
+ OCFS2_I(inode)->ip_blkno,
+ bh,
+ OCFS2_BH_CACHED,
+ inode);
+ if (status < 0) {
+ mlog_errno(status);
+ link = ERR_PTR(status);
+ goto bail;
+ }
+
+ fe = (struct ocfs2_dinode *) (*bh)->b_data;
+ link = (char *) fe->id2.i_symlink;
+bail:
+ mlog_exit(status);
+
+ return link;
+}
+
+static int ocfs2_readlink(struct dentry *dentry,
+ char __user *buffer,
+ int buflen)
+{
+ int ret;
+ char *link;
+ struct buffer_head *bh = NULL;
+ struct inode *inode = dentry->d_inode;
+
+ mlog_entry_void();
+
+ link = ocfs2_fast_symlink_getlink(inode, &bh);
+ if (IS_ERR(link)) {
+ ret = PTR_ERR(link);
+ goto out;
+ }
+
+ ret = vfs_readlink(dentry, buffer, buflen, link);
+
+ brelse(bh);
+out:
+ mlog_exit(ret);
+ return ret;
+}
+
+static void *ocfs2_follow_link(struct dentry *dentry,
+ struct nameidata *nd)
+{
+ int status;
+ char *link;
+ struct inode *inode = dentry->d_inode;
+ struct page *page = NULL;
+ struct buffer_head *bh = NULL;
+
+ if (ocfs2_inode_is_fast_symlink(inode))
+ link = ocfs2_fast_symlink_getlink(inode, &bh);
+ else
+ link = ocfs2_page_getlink(dentry, &page);
+ if (IS_ERR(link)) {
+ status = PTR_ERR(link);
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = vfs_follow_link(nd, link);
+ if (status)
+ mlog_errno(status);
+bail:
+ if (page) {
+ kunmap(page);
+ page_cache_release(page);
+ }
+ if (bh)
+ brelse(bh);
+
+ return ERR_PTR(status);
+}
+
+struct inode_operations ocfs2_symlink_inode_operations = {
+ .readlink = page_readlink,
+ .follow_link = ocfs2_follow_link,
+ .getattr = ocfs2_getattr,
+};
+struct inode_operations ocfs2_fast_symlink_inode_operations = {
+ .readlink = ocfs2_readlink,
+ .follow_link = ocfs2_follow_link,
+ .getattr = ocfs2_getattr,
+};
diff --git a/fs/ocfs2/symlink.h b/fs/ocfs2/symlink.h
new file mode 100644
index 000000000000..1ea9e4d9e9eb
--- /dev/null
+++ b/fs/ocfs2/symlink.h
@@ -0,0 +1,42 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * symlink.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_SYMLINK_H
+#define OCFS2_SYMLINK_H
+
+extern struct inode_operations ocfs2_symlink_inode_operations;
+extern struct inode_operations ocfs2_fast_symlink_inode_operations;
+
+/*
+ * Test whether an inode is a fast symlink.
+ */
+static inline int ocfs2_inode_is_fast_symlink(struct inode *inode)
+{
+ return (S_ISLNK(inode->i_mode) &&
+ inode->i_blocks == 0);
+}
+
+
+#endif /* OCFS2_SYMLINK_H */
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
new file mode 100644
index 000000000000..600a8bc5b541
--- /dev/null
+++ b/fs/ocfs2/sysfile.c
@@ -0,0 +1,131 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * sysfile.c
+ *
+ * Initialize, read, write, etc. system files.
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#include "ocfs2.h"
+
+#define MLOG_MASK_PREFIX ML_INODE
+#include <cluster/masklog.h>
+
+#include "alloc.h"
+#include "dir.h"
+#include "inode.h"
+#include "journal.h"
+#include "sysfile.h"
+
+#include "buffer_head_io.h"
+
+static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
+ int type,
+ u32 slot);
+
+static inline int is_global_system_inode(int type);
+static inline int is_in_system_inode_array(struct ocfs2_super *osb,
+ int type,
+ u32 slot);
+
+static inline int is_global_system_inode(int type)
+{
+ return type >= OCFS2_FIRST_ONLINE_SYSTEM_INODE &&
+ type <= OCFS2_LAST_GLOBAL_SYSTEM_INODE;
+}
+
+static inline int is_in_system_inode_array(struct ocfs2_super *osb,
+ int type,
+ u32 slot)
+{
+ return slot == osb->slot_num || is_global_system_inode(type);
+}
+
+struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
+ int type,
+ u32 slot)
+{
+ struct inode *inode = NULL;
+ struct inode **arr = NULL;
+
+ /* avoid the lookup if cached in local system file array */
+ if (is_in_system_inode_array(osb, type, slot))
+ arr = &(osb->system_inodes[type]);
+
+ if (arr && ((inode = *arr) != NULL)) {
+ /* get a ref in addition to the array ref */
+ inode = igrab(inode);
+ if (!inode)
+ BUG();
+
+ return inode;
+ }
+
+ /* this gets one ref thru iget */
+ inode = _ocfs2_get_system_file_inode(osb, type, slot);
+
+ /* add one more if putting into array for first time */
+ if (arr && inode) {
+ *arr = igrab(inode);
+ if (!*arr)
+ BUG();
+ }
+ return inode;
+}
+
+static struct inode * _ocfs2_get_system_file_inode(struct ocfs2_super *osb,
+ int type,
+ u32 slot)
+{
+ char namebuf[40];
+ struct inode *inode = NULL;
+ u64 blkno;
+ struct buffer_head *dirent_bh = NULL;
+ struct ocfs2_dir_entry *de = NULL;
+ int status = 0;
+
+ ocfs2_sprintf_system_inode_name(namebuf,
+ sizeof(namebuf),
+ type, slot);
+
+ status = ocfs2_find_files_on_disk(namebuf, strlen(namebuf),
+ &blkno, osb->sys_root_inode,
+ &dirent_bh, &de);
+ if (status < 0) {
+ goto bail;
+ }
+
+ inode = ocfs2_iget(osb, blkno);
+ if (IS_ERR(inode)) {
+ mlog_errno(PTR_ERR(inode));
+ inode = NULL;
+ goto bail;
+ }
+bail:
+ if (dirent_bh)
+ brelse(dirent_bh);
+ return inode;
+}
+
diff --git a/fs/ocfs2/sysfile.h b/fs/ocfs2/sysfile.h
new file mode 100644
index 000000000000..cc9ea661ffc1
--- /dev/null
+++ b/fs/ocfs2/sysfile.h
@@ -0,0 +1,33 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * sysfile.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_SYSFILE_H
+#define OCFS2_SYSFILE_H
+
+struct inode * ocfs2_get_system_file_inode(struct ocfs2_super *osb,
+ int type,
+ u32 slot);
+
+#endif /* OCFS2_SYSFILE_H */
diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c
new file mode 100644
index 000000000000..3a0458fd3e1b
--- /dev/null
+++ b/fs/ocfs2/uptodate.c
@@ -0,0 +1,544 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * uptodate.c
+ *
+ * Tracking the up-to-date-ness of a local buffer_head with respect to
+ * the cluster.
+ *
+ * Copyright (C) 2002, 2004, 2005 Oracle. 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 021110-1307, USA.
+ *
+ * Standard buffer head caching flags (uptodate, etc) are insufficient
+ * in a clustered environment - a buffer may be marked up to date on
+ * our local node but could have been modified by another cluster
+ * member. As a result an additional (and performant) caching scheme
+ * is required. A further requirement is that we consume as little
+ * memory as possible - we never pin buffer_head structures in order
+ * to cache them.
+ *
+ * We track the existence of up to date buffers on the inodes which
+ * are associated with them. Because we don't want to pin
+ * buffer_heads, this is only a (strong) hint and several other checks
+ * are made in the I/O path to ensure that we don't use a stale or
+ * invalid buffer without going to disk:
+ * - buffer_jbd is used liberally - if a bh is in the journal on
+ * this node then it *must* be up to date.
+ * - the standard buffer_uptodate() macro is used to detect buffers
+ * which may be invalid (even if we have an up to date tracking
+ * item for them)
+ *
+ * For a full understanding of how this code works together, one
+ * should read the callers in dlmglue.c, the I/O functions in
+ * buffer_head_io.c and ocfs2_journal_access in journal.c
+ */
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/buffer_head.h>
+#include <linux/rbtree.h>
+#include <linux/jbd.h>
+
+#define MLOG_MASK_PREFIX ML_UPTODATE
+
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "inode.h"
+#include "uptodate.h"
+
+struct ocfs2_meta_cache_item {
+ struct rb_node c_node;
+ sector_t c_block;
+};
+
+static kmem_cache_t *ocfs2_uptodate_cachep = NULL;
+
+void ocfs2_metadata_cache_init(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+
+ oi->ip_flags |= OCFS2_INODE_CACHE_INLINE;
+ ci->ci_num_cached = 0;
+}
+
+/* No lock taken here as 'root' is not expected to be visible to other
+ * processes. */
+static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root)
+{
+ unsigned int purged = 0;
+ struct rb_node *node;
+ struct ocfs2_meta_cache_item *item;
+
+ while ((node = rb_last(root)) != NULL) {
+ item = rb_entry(node, struct ocfs2_meta_cache_item, c_node);
+
+ mlog(0, "Purge item %llu\n",
+ (unsigned long long) item->c_block);
+
+ rb_erase(&item->c_node, root);
+ kmem_cache_free(ocfs2_uptodate_cachep, item);
+
+ purged++;
+ }
+ return purged;
+}
+
+/* Called from locking and called from ocfs2_clear_inode. Dump the
+ * cache for a given inode.
+ *
+ * This function is a few more lines longer than necessary due to some
+ * accounting done here, but I think it's worth tracking down those
+ * bugs sooner -- Mark */
+void ocfs2_metadata_cache_purge(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ unsigned int tree, to_purge, purged;
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+ struct rb_root root = RB_ROOT;
+
+ spin_lock(&oi->ip_lock);
+ tree = !(oi->ip_flags & OCFS2_INODE_CACHE_INLINE);
+ to_purge = ci->ci_num_cached;
+
+ mlog(0, "Purge %u %s items from Inode %"MLFu64"\n", to_purge,
+ tree ? "array" : "tree", oi->ip_blkno);
+
+ /* If we're a tree, save off the root so that we can safely
+ * initialize the cache. We do the work to free tree members
+ * without the spinlock. */
+ if (tree)
+ root = ci->ci_cache.ci_tree;
+
+ ocfs2_metadata_cache_init(inode);
+ spin_unlock(&oi->ip_lock);
+
+ purged = ocfs2_purge_copied_metadata_tree(&root);
+ /* If possible, track the number wiped so that we can more
+ * easily detect counting errors. Unfortunately, this is only
+ * meaningful for trees. */
+ if (tree && purged != to_purge)
+ mlog(ML_ERROR, "Inode %"MLFu64", count = %u, purged = %u\n",
+ oi->ip_blkno, to_purge, purged);
+}
+
+/* Returns the index in the cache array, -1 if not found.
+ * Requires ip_lock. */
+static int ocfs2_search_cache_array(struct ocfs2_caching_info *ci,
+ sector_t item)
+{
+ int i;
+
+ for (i = 0; i < ci->ci_num_cached; i++) {
+ if (item == ci->ci_cache.ci_array[i])
+ return i;
+ }
+
+ return -1;
+}
+
+/* Returns the cache item if found, otherwise NULL.
+ * Requires ip_lock. */
+static struct ocfs2_meta_cache_item *
+ocfs2_search_cache_tree(struct ocfs2_caching_info *ci,
+ sector_t block)
+{
+ struct rb_node * n = ci->ci_cache.ci_tree.rb_node;
+ struct ocfs2_meta_cache_item *item = NULL;
+
+ while (n) {
+ item = rb_entry(n, struct ocfs2_meta_cache_item, c_node);
+
+ if (block < item->c_block)
+ n = n->rb_left;
+ else if (block > item->c_block)
+ n = n->rb_right;
+ else
+ return item;
+ }
+
+ return NULL;
+}
+
+static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi,
+ struct buffer_head *bh)
+{
+ int index = -1;
+ struct ocfs2_meta_cache_item *item = NULL;
+
+ spin_lock(&oi->ip_lock);
+
+ mlog(0, "Inode %"MLFu64", query block %llu (inline = %u)\n",
+ oi->ip_blkno, (unsigned long long) bh->b_blocknr,
+ !!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE));
+
+ if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE)
+ index = ocfs2_search_cache_array(&oi->ip_metadata_cache,
+ bh->b_blocknr);
+ else
+ item = ocfs2_search_cache_tree(&oi->ip_metadata_cache,
+ bh->b_blocknr);
+
+ spin_unlock(&oi->ip_lock);
+
+ mlog(0, "index = %d, item = %p\n", index, item);
+
+ return (index != -1) || (item != NULL);
+}
+
+/* Warning: even if it returns true, this does *not* guarantee that
+ * the block is stored in our inode metadata cache. */
+int ocfs2_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh)
+{
+ /* Doesn't matter if the bh is in our cache or not -- if it's
+ * not marked uptodate then we know it can't have correct
+ * data. */
+ if (!buffer_uptodate(bh))
+ return 0;
+
+ /* OCFS2 does not allow multiple nodes to be changing the same
+ * block at the same time. */
+ if (buffer_jbd(bh))
+ return 1;
+
+ /* Ok, locally the buffer is marked as up to date, now search
+ * our cache to see if we can trust that. */
+ return ocfs2_buffer_cached(OCFS2_I(inode), bh);
+}
+
+/* Requires ip_lock */
+static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci,
+ sector_t block)
+{
+ BUG_ON(ci->ci_num_cached >= OCFS2_INODE_MAX_CACHE_ARRAY);
+
+ mlog(0, "block %llu takes position %u\n", (unsigned long long) block,
+ ci->ci_num_cached);
+
+ ci->ci_cache.ci_array[ci->ci_num_cached] = block;
+ ci->ci_num_cached++;
+}
+
+/* By now the caller should have checked that the item does *not*
+ * exist in the tree.
+ * Requires ip_lock. */
+static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci,
+ struct ocfs2_meta_cache_item *new)
+{
+ sector_t block = new->c_block;
+ struct rb_node *parent = NULL;
+ struct rb_node **p = &ci->ci_cache.ci_tree.rb_node;
+ struct ocfs2_meta_cache_item *tmp;
+
+ mlog(0, "Insert block %llu num = %u\n", (unsigned long long) block,
+ ci->ci_num_cached);
+
+ while(*p) {
+ parent = *p;
+
+ tmp = rb_entry(parent, struct ocfs2_meta_cache_item, c_node);
+
+ if (block < tmp->c_block)
+ p = &(*p)->rb_left;
+ else if (block > tmp->c_block)
+ p = &(*p)->rb_right;
+ else {
+ /* This should never happen! */
+ mlog(ML_ERROR, "Duplicate block %llu cached!\n",
+ (unsigned long long) block);
+ BUG();
+ }
+ }
+
+ rb_link_node(&new->c_node, parent, p);
+ rb_insert_color(&new->c_node, &ci->ci_cache.ci_tree);
+ ci->ci_num_cached++;
+}
+
+static inline int ocfs2_insert_can_use_array(struct ocfs2_inode_info *oi,
+ struct ocfs2_caching_info *ci)
+{
+ assert_spin_locked(&oi->ip_lock);
+
+ return (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) &&
+ (ci->ci_num_cached < OCFS2_INODE_MAX_CACHE_ARRAY);
+}
+
+/* tree should be exactly OCFS2_INODE_MAX_CACHE_ARRAY wide. NULL the
+ * pointers in tree after we use them - this allows caller to detect
+ * when to free in case of error. */
+static void ocfs2_expand_cache(struct ocfs2_inode_info *oi,
+ struct ocfs2_meta_cache_item **tree)
+{
+ int i;
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+
+ mlog_bug_on_msg(ci->ci_num_cached != OCFS2_INODE_MAX_CACHE_ARRAY,
+ "Inode %"MLFu64", num cached = %u, should be %u\n",
+ oi->ip_blkno, ci->ci_num_cached,
+ OCFS2_INODE_MAX_CACHE_ARRAY);
+ mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE),
+ "Inode %"MLFu64" not marked as inline anymore!\n",
+ oi->ip_blkno);
+ assert_spin_locked(&oi->ip_lock);
+
+ /* Be careful to initialize the tree members *first* because
+ * once the ci_tree is used, the array is junk... */
+ for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++)
+ tree[i]->c_block = ci->ci_cache.ci_array[i];
+
+ oi->ip_flags &= ~OCFS2_INODE_CACHE_INLINE;
+ ci->ci_cache.ci_tree = RB_ROOT;
+ /* this will be set again by __ocfs2_insert_cache_tree */
+ ci->ci_num_cached = 0;
+
+ for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {
+ __ocfs2_insert_cache_tree(ci, tree[i]);
+ tree[i] = NULL;
+ }
+
+ mlog(0, "Expanded %"MLFu64" to a tree cache: flags 0x%x, num = %u\n",
+ oi->ip_blkno, oi->ip_flags, ci->ci_num_cached);
+}
+
+/* Slow path function - memory allocation is necessary. See the
+ * comment above ocfs2_set_buffer_uptodate for more information. */
+static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi,
+ sector_t block,
+ int expand_tree)
+{
+ int i;
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+ struct ocfs2_meta_cache_item *new = NULL;
+ struct ocfs2_meta_cache_item *tree[OCFS2_INODE_MAX_CACHE_ARRAY] =
+ { NULL, };
+
+ mlog(0, "Inode %"MLFu64", block %llu, expand = %d\n",
+ oi->ip_blkno, (unsigned long long) block, expand_tree);
+
+ new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_KERNEL);
+ if (!new) {
+ mlog_errno(-ENOMEM);
+ return;
+ }
+ new->c_block = block;
+
+ if (expand_tree) {
+ /* Do *not* allocate an array here - the removal code
+ * has no way of tracking that. */
+ for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) {
+ tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep,
+ GFP_KERNEL);
+ if (!tree[i]) {
+ mlog_errno(-ENOMEM);
+ goto out_free;
+ }
+
+ /* These are initialized in ocfs2_expand_cache! */
+ }
+ }
+
+ spin_lock(&oi->ip_lock);
+ if (ocfs2_insert_can_use_array(oi, ci)) {
+ mlog(0, "Someone cleared the tree underneath us\n");
+ /* Ok, items were removed from the cache in between
+ * locks. Detect this and revert back to the fast path */
+ ocfs2_append_cache_array(ci, block);
+ spin_unlock(&oi->ip_lock);
+ goto out_free;
+ }
+
+ if (expand_tree)
+ ocfs2_expand_cache(oi, tree);
+
+ __ocfs2_insert_cache_tree(ci, new);
+ spin_unlock(&oi->ip_lock);
+
+ new = NULL;
+out_free:
+ if (new)
+ kmem_cache_free(ocfs2_uptodate_cachep, new);
+
+ /* If these were used, then ocfs2_expand_cache re-set them to
+ * NULL for us. */
+ if (tree[0]) {
+ for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++)
+ if (tree[i])
+ kmem_cache_free(ocfs2_uptodate_cachep,
+ tree[i]);
+ }
+}
+
+/* Item insertion is guarded by ip_io_sem, so the insertion path takes
+ * advantage of this by not rechecking for a duplicate insert during
+ * the slow case. Additionally, if the cache needs to be bumped up to
+ * a tree, the code will not recheck after acquiring the lock --
+ * multiple paths cannot be expanding to a tree at the same time.
+ *
+ * The slow path takes into account that items can be removed
+ * (including the whole tree wiped and reset) when this process it out
+ * allocating memory. In those cases, it reverts back to the fast
+ * path.
+ *
+ * Note that this function may actually fail to insert the block if
+ * memory cannot be allocated. This is not fatal however (but may
+ * result in a performance penalty) */
+void ocfs2_set_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh)
+{
+ int expand;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+
+ /* The block may very well exist in our cache already, so avoid
+ * doing any more work in that case. */
+ if (ocfs2_buffer_cached(oi, bh))
+ return;
+
+ mlog(0, "Inode %"MLFu64", inserting block %llu\n", oi->ip_blkno,
+ (unsigned long long) bh->b_blocknr);
+
+ /* No need to recheck under spinlock - insertion is guarded by
+ * ip_io_sem */
+ spin_lock(&oi->ip_lock);
+ if (ocfs2_insert_can_use_array(oi, ci)) {
+ /* Fast case - it's an array and there's a free
+ * spot. */
+ ocfs2_append_cache_array(ci, bh->b_blocknr);
+ spin_unlock(&oi->ip_lock);
+ return;
+ }
+
+ expand = 0;
+ if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) {
+ /* We need to bump things up to a tree. */
+ expand = 1;
+ }
+ spin_unlock(&oi->ip_lock);
+
+ __ocfs2_set_buffer_uptodate(oi, bh->b_blocknr, expand);
+}
+
+/* Called against a newly allocated buffer. Most likely nobody should
+ * be able to read this sort of metadata while it's still being
+ * allocated, but this is careful to take ip_io_sem anyway. */
+void ocfs2_set_new_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ /* This should definitely *not* exist in our cache */
+ BUG_ON(ocfs2_buffer_cached(oi, bh));
+
+ set_buffer_uptodate(bh);
+
+ down(&oi->ip_io_sem);
+ ocfs2_set_buffer_uptodate(inode, bh);
+ up(&oi->ip_io_sem);
+}
+
+/* Requires ip_lock. */
+static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci,
+ int index)
+{
+ sector_t *array = ci->ci_cache.ci_array;
+ int bytes;
+
+ BUG_ON(index < 0 || index >= OCFS2_INODE_MAX_CACHE_ARRAY);
+ BUG_ON(index >= ci->ci_num_cached);
+ BUG_ON(!ci->ci_num_cached);
+
+ mlog(0, "remove index %d (num_cached = %u\n", index,
+ ci->ci_num_cached);
+
+ ci->ci_num_cached--;
+
+ /* don't need to copy if the array is now empty, or if we
+ * removed at the tail */
+ if (ci->ci_num_cached && index < ci->ci_num_cached) {
+ bytes = sizeof(sector_t) * (ci->ci_num_cached - index);
+ memmove(&array[index], &array[index + 1], bytes);
+ }
+}
+
+/* Requires ip_lock. */
+static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci,
+ struct ocfs2_meta_cache_item *item)
+{
+ mlog(0, "remove block %llu from tree\n",
+ (unsigned long long) item->c_block);
+
+ rb_erase(&item->c_node, &ci->ci_cache.ci_tree);
+ ci->ci_num_cached--;
+}
+
+/* Called when we remove a chunk of metadata from an inode. We don't
+ * bother reverting things to an inlined array in the case of a remove
+ * which moves us back under the limit. */
+void ocfs2_remove_from_cache(struct inode *inode,
+ struct buffer_head *bh)
+{
+ int index;
+ sector_t block = bh->b_blocknr;
+ struct ocfs2_meta_cache_item *item = NULL;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ struct ocfs2_caching_info *ci = &oi->ip_metadata_cache;
+
+ spin_lock(&oi->ip_lock);
+ mlog(0, "Inode %"MLFu64", remove %llu, items = %u, array = %u\n",
+ oi->ip_blkno, (unsigned long long) block, ci->ci_num_cached,
+ oi->ip_flags & OCFS2_INODE_CACHE_INLINE);
+
+ if (oi->ip_flags & OCFS2_INODE_CACHE_INLINE) {
+ index = ocfs2_search_cache_array(ci, block);
+ if (index != -1)
+ ocfs2_remove_metadata_array(ci, index);
+ } else {
+ item = ocfs2_search_cache_tree(ci, block);
+ if (item)
+ ocfs2_remove_metadata_tree(ci, item);
+ }
+ spin_unlock(&oi->ip_lock);
+
+ if (item)
+ kmem_cache_free(ocfs2_uptodate_cachep, item);
+}
+
+int __init init_ocfs2_uptodate_cache(void)
+{
+ ocfs2_uptodate_cachep = kmem_cache_create("ocfs2_uptodate",
+ sizeof(struct ocfs2_meta_cache_item),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (!ocfs2_uptodate_cachep)
+ return -ENOMEM;
+
+ mlog(0, "%u inlined cache items per inode.\n",
+ OCFS2_INODE_MAX_CACHE_ARRAY);
+
+ return 0;
+}
+
+void __exit exit_ocfs2_uptodate_cache(void)
+{
+ if (ocfs2_uptodate_cachep)
+ kmem_cache_destroy(ocfs2_uptodate_cachep);
+}
diff --git a/fs/ocfs2/uptodate.h b/fs/ocfs2/uptodate.h
new file mode 100644
index 000000000000..e5aacdf4eabf
--- /dev/null
+++ b/fs/ocfs2/uptodate.h
@@ -0,0 +1,44 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * uptodate.h
+ *
+ * Cluster uptodate tracking
+ *
+ * Copyright (C) 2002, 2004, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_UPTODATE_H
+#define OCFS2_UPTODATE_H
+
+int __init init_ocfs2_uptodate_cache(void);
+void __exit exit_ocfs2_uptodate_cache(void);
+
+void ocfs2_metadata_cache_init(struct inode *inode);
+void ocfs2_metadata_cache_purge(struct inode *inode);
+
+int ocfs2_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh);
+void ocfs2_set_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh);
+void ocfs2_set_new_buffer_uptodate(struct inode *inode,
+ struct buffer_head *bh);
+void ocfs2_remove_from_cache(struct inode *inode,
+ struct buffer_head *bh);
+
+#endif /* OCFS2_UPTODATE_H */
diff --git a/fs/ocfs2/ver.c b/fs/ocfs2/ver.c
new file mode 100644
index 000000000000..5405ce121c99
--- /dev/null
+++ b/fs/ocfs2/ver.c
@@ -0,0 +1,43 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ver.c
+ *
+ * version string
+ *
+ * Copyright (C) 2002, 2005 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include "ver.h"
+
+#define OCFS2_BUILD_VERSION "1.3.3"
+
+#define VERSION_STR "OCFS2 " OCFS2_BUILD_VERSION
+
+void ocfs2_print_version(void)
+{
+ printk(KERN_INFO "%s\n", VERSION_STR);
+}
+
+MODULE_DESCRIPTION(VERSION_STR);
+
+MODULE_VERSION(OCFS2_BUILD_VERSION);
diff --git a/fs/ocfs2/ver.h b/fs/ocfs2/ver.h
new file mode 100644
index 000000000000..d7395cb91d2f
--- /dev/null
+++ b/fs/ocfs2/ver.h
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * ver.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#ifndef OCFS2_VER_H
+#define OCFS2_VER_H
+
+void ocfs2_print_version(void);
+
+#endif /* OCFS2_VER_H */
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
new file mode 100644
index 000000000000..021978e0576b
--- /dev/null
+++ b/fs/ocfs2/vote.c
@@ -0,0 +1,1202 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * vote.c
+ *
+ * description here
+ *
+ * Copyright (C) 2003, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kthread.h>
+
+#include <cluster/heartbeat.h>
+#include <cluster/nodemanager.h>
+#include <cluster/tcp.h>
+
+#include <dlm/dlmapi.h>
+
+#define MLOG_MASK_PREFIX ML_VOTE
+#include <cluster/masklog.h>
+
+#include "ocfs2.h"
+
+#include "alloc.h"
+#include "dlmglue.h"
+#include "extent_map.h"
+#include "heartbeat.h"
+#include "inode.h"
+#include "journal.h"
+#include "slot_map.h"
+#include "vote.h"
+
+#include "buffer_head_io.h"
+
+#define OCFS2_MESSAGE_TYPE_VOTE (0x1)
+#define OCFS2_MESSAGE_TYPE_RESPONSE (0x2)
+struct ocfs2_msg_hdr
+{
+ __be32 h_response_id; /* used to lookup message handle on sending
+ * node. */
+ __be32 h_request;
+ __be64 h_blkno;
+ __be32 h_generation;
+ __be32 h_node_num; /* node sending this particular message. */
+};
+
+/* OCFS2_MAX_FILENAME_LEN is 255 characters, but we want to align this
+ * for the network. */
+#define OCFS2_VOTE_FILENAME_LEN 256
+struct ocfs2_vote_msg
+{
+ struct ocfs2_msg_hdr v_hdr;
+ union {
+ __be32 v_generic1;
+ __be32 v_orphaned_slot; /* Used during delete votes */
+ __be32 v_nlink; /* Used during unlink votes */
+ } md1; /* Message type dependant 1 */
+ __be32 v_unlink_namelen;
+ __be64 v_unlink_parent;
+ u8 v_unlink_dirent[OCFS2_VOTE_FILENAME_LEN];
+};
+
+/* Responses are given these values to maintain backwards
+ * compatibility with older ocfs2 versions */
+#define OCFS2_RESPONSE_OK (0)
+#define OCFS2_RESPONSE_BUSY (-16)
+#define OCFS2_RESPONSE_BAD_MSG (-22)
+
+struct ocfs2_response_msg
+{
+ struct ocfs2_msg_hdr r_hdr;
+ __be32 r_response;
+ __be32 r_orphaned_slot;
+};
+
+struct ocfs2_vote_work {
+ struct list_head w_list;
+ struct ocfs2_vote_msg w_msg;
+};
+
+enum ocfs2_vote_request {
+ OCFS2_VOTE_REQ_INVALID = 0,
+ OCFS2_VOTE_REQ_DELETE,
+ OCFS2_VOTE_REQ_UNLINK,
+ OCFS2_VOTE_REQ_RENAME,
+ OCFS2_VOTE_REQ_MOUNT,
+ OCFS2_VOTE_REQ_UMOUNT,
+ OCFS2_VOTE_REQ_LAST
+};
+
+static inline int ocfs2_is_valid_vote_request(int request)
+{
+ return OCFS2_VOTE_REQ_INVALID < request &&
+ request < OCFS2_VOTE_REQ_LAST;
+}
+
+typedef void (*ocfs2_net_response_callback)(void *priv,
+ struct ocfs2_response_msg *resp);
+struct ocfs2_net_response_cb {
+ ocfs2_net_response_callback rc_cb;
+ void *rc_priv;
+};
+
+struct ocfs2_net_wait_ctxt {
+ struct list_head n_list;
+ u32 n_response_id;
+ wait_queue_head_t n_event;
+ struct ocfs2_node_map n_node_map;
+ int n_response; /* an agreggate response. 0 if
+ * all nodes are go, < 0 on any
+ * negative response from any
+ * node or network error. */
+ struct ocfs2_net_response_cb *n_callback;
+};
+
+static void ocfs2_process_mount_request(struct ocfs2_super *osb,
+ unsigned int node_num)
+{
+ mlog(0, "MOUNT vote from node %u\n", node_num);
+ /* The other node only sends us this message when he has an EX
+ * on the superblock, so our recovery threads (if having been
+ * launched) are waiting on it.*/
+ ocfs2_recovery_map_clear(osb, node_num);
+ ocfs2_node_map_set_bit(osb, &osb->mounted_map, node_num);
+
+ /* We clear the umount map here because a node may have been
+ * previously mounted, safely unmounted but never stopped
+ * heartbeating - in which case we'd have a stale entry. */
+ ocfs2_node_map_clear_bit(osb, &osb->umount_map, node_num);
+}
+
+static void ocfs2_process_umount_request(struct ocfs2_super *osb,
+ unsigned int node_num)
+{
+ mlog(0, "UMOUNT vote from node %u\n", node_num);
+ ocfs2_node_map_clear_bit(osb, &osb->mounted_map, node_num);
+ ocfs2_node_map_set_bit(osb, &osb->umount_map, node_num);
+}
+
+void ocfs2_mark_inode_remotely_deleted(struct inode *inode)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ assert_spin_locked(&oi->ip_lock);
+ /* We set the SKIP_DELETE flag on the inode so we don't try to
+ * delete it in delete_inode ourselves, thus avoiding
+ * unecessary lock pinging. If the other node failed to wipe
+ * the inode as a result of a crash, then recovery will pick
+ * up the slack. */
+ oi->ip_flags |= OCFS2_INODE_DELETED|OCFS2_INODE_SKIP_DELETE;
+}
+
+static int ocfs2_process_delete_request(struct inode *inode,
+ int *orphaned_slot)
+{
+ int response = OCFS2_RESPONSE_BUSY;
+
+ mlog(0, "DELETE vote on inode %lu, read lnk_cnt = %u, slot = %d\n",
+ inode->i_ino, inode->i_nlink, *orphaned_slot);
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+
+ /* Whatever our vote response is, we want to make sure that
+ * the orphaned slot is recorded properly on this node *and*
+ * on the requesting node. Technically, if the requesting node
+ * did not know which slot the inode is orphaned in but we
+ * respond with BUSY he doesn't actually need the orphaned
+ * slot, but it doesn't hurt to do it here anyway. */
+ if ((*orphaned_slot) != OCFS2_INVALID_SLOT) {
+ mlog_bug_on_msg(OCFS2_I(inode)->ip_orphaned_slot !=
+ OCFS2_INVALID_SLOT &&
+ OCFS2_I(inode)->ip_orphaned_slot !=
+ (*orphaned_slot),
+ "Inode %"MLFu64": This node thinks it's "
+ "orphaned in slot %d, messaged it's in %d\n",
+ OCFS2_I(inode)->ip_blkno,
+ OCFS2_I(inode)->ip_orphaned_slot,
+ *orphaned_slot);
+
+ mlog(0, "Setting orphaned slot for inode %"MLFu64" to %d\n",
+ OCFS2_I(inode)->ip_blkno, *orphaned_slot);
+
+ OCFS2_I(inode)->ip_orphaned_slot = *orphaned_slot;
+ } else {
+ mlog(0, "Sending back orphaned slot %d for inode %"MLFu64"\n",
+ OCFS2_I(inode)->ip_orphaned_slot,
+ OCFS2_I(inode)->ip_blkno);
+
+ *orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot;
+ }
+
+ /* vote no if the file is still open. */
+ if (OCFS2_I(inode)->ip_open_count) {
+ mlog(0, "open count = %u\n",
+ OCFS2_I(inode)->ip_open_count);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ goto done;
+ }
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ /* directories are a bit ugly... What if someone is sitting in
+ * it? We want to make sure the inode is removed completely as
+ * a result of the iput in process_vote. */
+ if (S_ISDIR(inode->i_mode) && (atomic_read(&inode->i_count) != 1)) {
+ mlog(0, "i_count = %u\n", atomic_read(&inode->i_count));
+ goto done;
+ }
+
+ if (filemap_fdatawrite(inode->i_mapping)) {
+ mlog(ML_ERROR, "Could not sync inode %"MLFu64" for delete!\n",
+ OCFS2_I(inode)->ip_blkno);
+ goto done;
+ }
+ sync_mapping_buffers(inode->i_mapping);
+ truncate_inode_pages(inode->i_mapping, 0);
+ ocfs2_extent_map_trunc(inode, 0);
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ /* double check open count - someone might have raced this
+ * thread into ocfs2_file_open while we were writing out
+ * data. If we're to allow a wipe of this inode now, we *must*
+ * hold the spinlock until we've marked it. */
+ if (OCFS2_I(inode)->ip_open_count) {
+ mlog(0, "Raced to wipe! open count = %u\n",
+ OCFS2_I(inode)->ip_open_count);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ goto done;
+ }
+
+ /* Mark the inode as being wiped from disk. */
+ ocfs2_mark_inode_remotely_deleted(inode);
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ /* Not sure this is necessary anymore. */
+ d_prune_aliases(inode);
+
+ /* If we get here, then we're voting 'yes', so commit the
+ * delete on our side. */
+ response = OCFS2_RESPONSE_OK;
+done:
+ return response;
+}
+
+static int ocfs2_match_dentry(struct dentry *dentry,
+ u64 parent_blkno,
+ unsigned int namelen,
+ const char *name)
+{
+ struct inode *parent;
+
+ if (!dentry->d_parent) {
+ mlog(0, "Detached from parent.\n");
+ return 0;
+ }
+
+ parent = dentry->d_parent->d_inode;
+ /* Negative parent dentry? */
+ if (!parent)
+ return 0;
+
+ /* Name is in a different directory. */
+ if (OCFS2_I(parent)->ip_blkno != parent_blkno)
+ return 0;
+
+ if (dentry->d_name.len != namelen)
+ return 0;
+
+ /* comparison above guarantees this is safe. */
+ if (memcmp(dentry->d_name.name, name, namelen))
+ return 0;
+
+ return 1;
+}
+
+static void ocfs2_process_dentry_request(struct inode *inode,
+ int rename,
+ unsigned int new_nlink,
+ u64 parent_blkno,
+ unsigned int namelen,
+ const char *name)
+{
+ struct dentry *dentry = NULL;
+ struct list_head *p;
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+
+ mlog(0, "parent %"MLFu64", namelen = %u, name = %.*s\n", parent_blkno,
+ namelen, namelen, name);
+
+ spin_lock(&dcache_lock);
+
+ /* Another node is removing this name from the system. It is
+ * up to us to find the corresponding dentry and if it exists,
+ * unhash it from the dcache. */
+ list_for_each(p, &inode->i_dentry) {
+ dentry = list_entry(p, struct dentry, d_alias);
+
+ if (ocfs2_match_dentry(dentry, parent_blkno, namelen, name)) {
+ mlog(0, "dentry found: %.*s\n",
+ dentry->d_name.len, dentry->d_name.name);
+
+ dget_locked(dentry);
+ break;
+ }
+
+ dentry = NULL;
+ }
+
+ spin_unlock(&dcache_lock);
+
+ if (dentry) {
+ d_delete(dentry);
+ dput(dentry);
+ }
+
+ /* rename votes don't send link counts */
+ if (!rename) {
+ mlog(0, "new_nlink = %u\n", new_nlink);
+
+ /* We don't have the proper locks here to directly
+ * change i_nlink and besides, the vote is sent
+ * *before* the operation so it may have failed on the
+ * other node. This passes a hint to ocfs2_drop_inode
+ * to force ocfs2_delete_inode, who will take the
+ * proper cluster locks to sort things out. */
+ if (new_nlink == 0) {
+ spin_lock(&oi->ip_lock);
+ oi->ip_flags |= OCFS2_INODE_MAYBE_ORPHANED;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+ }
+ }
+}
+
+static void ocfs2_process_vote(struct ocfs2_super *osb,
+ struct ocfs2_vote_msg *msg)
+{
+ int net_status, vote_response;
+ int orphaned_slot = 0;
+ int rename = 0;
+ unsigned int node_num, generation, new_nlink, namelen;
+ u64 blkno, parent_blkno;
+ enum ocfs2_vote_request request;
+ struct inode *inode = NULL;
+ struct ocfs2_msg_hdr *hdr = &msg->v_hdr;
+ struct ocfs2_response_msg response;
+
+ /* decode the network mumbo jumbo into local variables. */
+ request = be32_to_cpu(hdr->h_request);
+ blkno = be64_to_cpu(hdr->h_blkno);
+ generation = be32_to_cpu(hdr->h_generation);
+ node_num = be32_to_cpu(hdr->h_node_num);
+ if (request == OCFS2_VOTE_REQ_DELETE)
+ orphaned_slot = be32_to_cpu(msg->md1.v_orphaned_slot);
+
+ mlog(0, "processing vote: request = %u, blkno = %"MLFu64", "
+ "generation = %u, node_num = %u, priv1 = %u\n", request,
+ blkno, generation, node_num, be32_to_cpu(msg->md1.v_generic1));
+
+ if (!ocfs2_is_valid_vote_request(request)) {
+ mlog(ML_ERROR, "Invalid vote request %d from node %u\n",
+ request, node_num);
+ vote_response = OCFS2_RESPONSE_BAD_MSG;
+ goto respond;
+ }
+
+ vote_response = OCFS2_RESPONSE_OK;
+
+ switch (request) {
+ case OCFS2_VOTE_REQ_UMOUNT:
+ ocfs2_process_umount_request(osb, node_num);
+ goto respond;
+ case OCFS2_VOTE_REQ_MOUNT:
+ ocfs2_process_mount_request(osb, node_num);
+ goto respond;
+ default:
+ /* avoids a gcc warning */
+ break;
+ }
+
+ /* We cannot process the remaining message types before we're
+ * fully mounted. It's perfectly safe however to send a 'yes'
+ * response as we can't possibly have any of the state they're
+ * asking us to modify yet. */
+ if (atomic_read(&osb->vol_state) == VOLUME_INIT)
+ goto respond;
+
+ /* If we get here, then the request is against an inode. */
+ inode = ocfs2_ilookup_for_vote(osb, blkno,
+ request == OCFS2_VOTE_REQ_DELETE);
+
+ /* Not finding the inode is perfectly valid - it means we're
+ * not interested in what the other node is about to do to it
+ * so in those cases we automatically respond with an
+ * affirmative. Cluster locking ensures that we won't race
+ * interest in the inode with this vote request. */
+ if (!inode)
+ goto respond;
+
+ /* Check generation values. It's possible for us to get a
+ * request against a stale inode. If so then we proceed as if
+ * we had not found an inode in the first place. */
+ if (inode->i_generation != generation) {
+ mlog(0, "generation passed %u != inode generation = %u, "
+ "ip_flags = %x, ip_blkno = %"MLFu64", msg %"MLFu64", "
+ "i_count = %u, message type = %u\n",
+ generation, inode->i_generation, OCFS2_I(inode)->ip_flags,
+ OCFS2_I(inode)->ip_blkno, blkno,
+ atomic_read(&inode->i_count), request);
+ iput(inode);
+ inode = NULL;
+ goto respond;
+ }
+
+ switch (request) {
+ case OCFS2_VOTE_REQ_DELETE:
+ vote_response = ocfs2_process_delete_request(inode,
+ &orphaned_slot);
+ break;
+ case OCFS2_VOTE_REQ_RENAME:
+ rename = 1;
+ /* fall through */
+ case OCFS2_VOTE_REQ_UNLINK:
+ parent_blkno = be64_to_cpu(msg->v_unlink_parent);
+ namelen = be32_to_cpu(msg->v_unlink_namelen);
+ /* new_nlink will be ignored in case of a rename vote */
+ new_nlink = be32_to_cpu(msg->md1.v_nlink);
+ ocfs2_process_dentry_request(inode, rename, new_nlink,
+ parent_blkno, namelen,
+ msg->v_unlink_dirent);
+ break;
+ default:
+ mlog(ML_ERROR, "node %u, invalid request: %u\n",
+ node_num, request);
+ vote_response = OCFS2_RESPONSE_BAD_MSG;
+ }
+
+respond:
+ /* Response struture is small so we just put it on the stack
+ * and stuff it inline. */
+ memset(&response, 0, sizeof(struct ocfs2_response_msg));
+ response.r_hdr.h_response_id = hdr->h_response_id;
+ response.r_hdr.h_blkno = hdr->h_blkno;
+ response.r_hdr.h_generation = hdr->h_generation;
+ response.r_hdr.h_node_num = cpu_to_be32(osb->node_num);
+ response.r_response = cpu_to_be32(vote_response);
+ response.r_orphaned_slot = cpu_to_be32(orphaned_slot);
+
+ net_status = o2net_send_message(OCFS2_MESSAGE_TYPE_RESPONSE,
+ osb->net_key,
+ &response,
+ sizeof(struct ocfs2_response_msg),
+ node_num,
+ NULL);
+ /* We still want to error print for ENOPROTOOPT here. The
+ * sending node shouldn't have unregistered his net handler
+ * without sending an unmount vote 1st */
+ if (net_status < 0
+ && net_status != -ETIMEDOUT
+ && net_status != -ENOTCONN)
+ mlog(ML_ERROR, "message to node %u fails with error %d!\n",
+ node_num, net_status);
+
+ if (inode)
+ iput(inode);
+}
+
+static void ocfs2_vote_thread_do_work(struct ocfs2_super *osb)
+{
+ unsigned long processed;
+ struct ocfs2_lock_res *lockres;
+ struct ocfs2_vote_work *work;
+
+ mlog_entry_void();
+
+ spin_lock(&osb->vote_task_lock);
+ /* grab this early so we know to try again if a state change and
+ * wake happens part-way through our work */
+ osb->vote_work_sequence = osb->vote_wake_sequence;
+
+ processed = osb->blocked_lock_count;
+ while (processed) {
+ BUG_ON(list_empty(&osb->blocked_lock_list));
+
+ lockres = list_entry(osb->blocked_lock_list.next,
+ struct ocfs2_lock_res, l_blocked_list);
+ list_del_init(&lockres->l_blocked_list);
+ osb->blocked_lock_count--;
+ spin_unlock(&osb->vote_task_lock);
+
+ BUG_ON(!processed);
+ processed--;
+
+ ocfs2_process_blocked_lock(osb, lockres);
+
+ spin_lock(&osb->vote_task_lock);
+ }
+
+ while (osb->vote_count) {
+ BUG_ON(list_empty(&osb->vote_list));
+ work = list_entry(osb->vote_list.next,
+ struct ocfs2_vote_work, w_list);
+ list_del(&work->w_list);
+ osb->vote_count--;
+ spin_unlock(&osb->vote_task_lock);
+
+ ocfs2_process_vote(osb, &work->w_msg);
+ kfree(work);
+
+ spin_lock(&osb->vote_task_lock);
+ }
+ spin_unlock(&osb->vote_task_lock);
+
+ mlog_exit_void();
+}
+
+static int ocfs2_vote_thread_lists_empty(struct ocfs2_super *osb)
+{
+ int empty = 0;
+
+ spin_lock(&osb->vote_task_lock);
+ if (list_empty(&osb->blocked_lock_list) &&
+ list_empty(&osb->vote_list))
+ empty = 1;
+
+ spin_unlock(&osb->vote_task_lock);
+ return empty;
+}
+
+static int ocfs2_vote_thread_should_wake(struct ocfs2_super *osb)
+{
+ int should_wake = 0;
+
+ spin_lock(&osb->vote_task_lock);
+ if (osb->vote_work_sequence != osb->vote_wake_sequence)
+ should_wake = 1;
+ spin_unlock(&osb->vote_task_lock);
+
+ return should_wake;
+}
+
+int ocfs2_vote_thread(void *arg)
+{
+ int status = 0;
+ struct ocfs2_super *osb = arg;
+
+ /* only quit once we've been asked to stop and there is no more
+ * work available */
+ while (!(kthread_should_stop() &&
+ ocfs2_vote_thread_lists_empty(osb))) {
+
+ wait_event_interruptible(osb->vote_event,
+ ocfs2_vote_thread_should_wake(osb) ||
+ kthread_should_stop());
+
+ mlog(0, "vote_thread: awoken\n");
+
+ ocfs2_vote_thread_do_work(osb);
+ }
+
+ osb->vote_task = NULL;
+ return status;
+}
+
+static struct ocfs2_net_wait_ctxt *ocfs2_new_net_wait_ctxt(unsigned int response_id)
+{
+ struct ocfs2_net_wait_ctxt *w;
+
+ w = kcalloc(1, sizeof(*w), GFP_KERNEL);
+ if (!w) {
+ mlog_errno(-ENOMEM);
+ goto bail;
+ }
+
+ INIT_LIST_HEAD(&w->n_list);
+ init_waitqueue_head(&w->n_event);
+ ocfs2_node_map_init(&w->n_node_map);
+ w->n_response_id = response_id;
+ w->n_callback = NULL;
+bail:
+ return w;
+}
+
+static unsigned int ocfs2_new_response_id(struct ocfs2_super *osb)
+{
+ unsigned int ret;
+
+ spin_lock(&osb->net_response_lock);
+ ret = ++osb->net_response_ids;
+ spin_unlock(&osb->net_response_lock);
+
+ return ret;
+}
+
+static void ocfs2_dequeue_net_wait_ctxt(struct ocfs2_super *osb,
+ struct ocfs2_net_wait_ctxt *w)
+{
+ spin_lock(&osb->net_response_lock);
+ list_del(&w->n_list);
+ spin_unlock(&osb->net_response_lock);
+}
+
+static void ocfs2_queue_net_wait_ctxt(struct ocfs2_super *osb,
+ struct ocfs2_net_wait_ctxt *w)
+{
+ spin_lock(&osb->net_response_lock);
+ list_add_tail(&w->n_list,
+ &osb->net_response_list);
+ spin_unlock(&osb->net_response_lock);
+}
+
+static void __ocfs2_mark_node_responded(struct ocfs2_super *osb,
+ struct ocfs2_net_wait_ctxt *w,
+ int node_num)
+{
+ assert_spin_locked(&osb->net_response_lock);
+
+ ocfs2_node_map_clear_bit(osb, &w->n_node_map, node_num);
+ if (ocfs2_node_map_is_empty(osb, &w->n_node_map))
+ wake_up(&w->n_event);
+}
+
+/* Intended to be called from the node down callback, we fake remove
+ * the node from all our response contexts */
+void ocfs2_remove_node_from_vote_queues(struct ocfs2_super *osb,
+ int node_num)
+{
+ struct list_head *p;
+ struct ocfs2_net_wait_ctxt *w = NULL;
+
+ spin_lock(&osb->net_response_lock);
+
+ list_for_each(p, &osb->net_response_list) {
+ w = list_entry(p, struct ocfs2_net_wait_ctxt, n_list);
+
+ __ocfs2_mark_node_responded(osb, w, node_num);
+ }
+
+ spin_unlock(&osb->net_response_lock);
+}
+
+static int ocfs2_broadcast_vote(struct ocfs2_super *osb,
+ struct ocfs2_vote_msg *request,
+ unsigned int response_id,
+ int *response,
+ struct ocfs2_net_response_cb *callback)
+{
+ int status, i, remote_err;
+ struct ocfs2_net_wait_ctxt *w = NULL;
+ int dequeued = 0;
+
+ mlog_entry_void();
+
+ w = ocfs2_new_net_wait_ctxt(response_id);
+ if (!w) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+ w->n_callback = callback;
+
+ /* we're pretty much ready to go at this point, and this fills
+ * in n_response which we need anyway... */
+ ocfs2_queue_net_wait_ctxt(osb, w);
+
+ i = ocfs2_node_map_iterate(osb, &osb->mounted_map, 0);
+
+ while (i != O2NM_INVALID_NODE_NUM) {
+ if (i != osb->node_num) {
+ mlog(0, "trying to send request to node %i\n", i);
+ ocfs2_node_map_set_bit(osb, &w->n_node_map, i);
+
+ remote_err = 0;
+ status = o2net_send_message(OCFS2_MESSAGE_TYPE_VOTE,
+ osb->net_key,
+ request,
+ sizeof(*request),
+ i,
+ &remote_err);
+ if (status == -ETIMEDOUT) {
+ mlog(0, "remote node %d timed out!\n", i);
+ status = -EAGAIN;
+ goto bail;
+ }
+ if (remote_err < 0) {
+ status = remote_err;
+ mlog(0, "remote error %d on node %d!\n",
+ remote_err, i);
+ mlog_errno(status);
+ goto bail;
+ }
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+ }
+ i++;
+ i = ocfs2_node_map_iterate(osb, &osb->mounted_map, i);
+ mlog(0, "next is %d, i am %d\n", i, osb->node_num);
+ }
+ mlog(0, "done sending, now waiting on responses...\n");
+
+ wait_event(w->n_event, ocfs2_node_map_is_empty(osb, &w->n_node_map));
+
+ ocfs2_dequeue_net_wait_ctxt(osb, w);
+ dequeued = 1;
+
+ *response = w->n_response;
+ status = 0;
+bail:
+ if (w) {
+ if (!dequeued)
+ ocfs2_dequeue_net_wait_ctxt(osb, w);
+ kfree(w);
+ }
+
+ mlog_exit(status);
+ return status;
+}
+
+static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb,
+ u64 blkno,
+ unsigned int generation,
+ enum ocfs2_vote_request type,
+ u32 priv)
+{
+ struct ocfs2_vote_msg *request;
+ struct ocfs2_msg_hdr *hdr;
+
+ BUG_ON(!ocfs2_is_valid_vote_request(type));
+
+ request = kcalloc(1, sizeof(*request), GFP_KERNEL);
+ if (!request) {
+ mlog_errno(-ENOMEM);
+ } else {
+ hdr = &request->v_hdr;
+ hdr->h_node_num = cpu_to_be32(osb->node_num);
+ hdr->h_request = cpu_to_be32(type);
+ hdr->h_blkno = cpu_to_be64(blkno);
+ hdr->h_generation = cpu_to_be32(generation);
+
+ request->md1.v_generic1 = cpu_to_be32(priv);
+ }
+
+ return request;
+}
+
+/* Complete the buildup of a new vote request and process the
+ * broadcast return value. */
+static int ocfs2_do_request_vote(struct ocfs2_super *osb,
+ struct ocfs2_vote_msg *request,
+ struct ocfs2_net_response_cb *callback)
+{
+ int status, response;
+ unsigned int response_id;
+ struct ocfs2_msg_hdr *hdr;
+
+ response_id = ocfs2_new_response_id(osb);
+
+ hdr = &request->v_hdr;
+ hdr->h_response_id = cpu_to_be32(response_id);
+
+ status = ocfs2_broadcast_vote(osb, request, response_id, &response,
+ callback);
+ if (status < 0) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = response;
+bail:
+
+ return status;
+}
+
+static int ocfs2_request_vote(struct inode *inode,
+ struct ocfs2_vote_msg *request,
+ struct ocfs2_net_response_cb *callback)
+{
+ int status;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+ if (ocfs2_inode_is_new(inode))
+ return 0;
+
+ status = -EAGAIN;
+ while (status == -EAGAIN) {
+ if (!(osb->s_mount_opt & OCFS2_MOUNT_NOINTR) &&
+ signal_pending(current))
+ return -ERESTARTSYS;
+
+ status = ocfs2_super_lock(osb, 0);
+ if (status < 0) {
+ mlog_errno(status);
+ break;
+ }
+
+ status = 0;
+ if (!ocfs2_node_map_is_only(osb, &osb->mounted_map,
+ osb->node_num))
+ status = ocfs2_do_request_vote(osb, request, callback);
+
+ ocfs2_super_unlock(osb, 0);
+ }
+ return status;
+}
+
+static void ocfs2_delete_response_cb(void *priv,
+ struct ocfs2_response_msg *resp)
+{
+ int orphaned_slot, node;
+ struct inode *inode = priv;
+
+ orphaned_slot = be32_to_cpu(resp->r_orphaned_slot);
+ node = be32_to_cpu(resp->r_hdr.h_node_num);
+ mlog(0, "node %d tells us that inode %"MLFu64" is orphaned in slot "
+ "%d\n", node, OCFS2_I(inode)->ip_blkno, orphaned_slot);
+
+ /* The other node may not actually know which slot the inode
+ * is orphaned in. */
+ if (orphaned_slot == OCFS2_INVALID_SLOT)
+ return;
+
+ /* Ok, the responding node knows which slot this inode is
+ * orphaned in. We verify that the information is correct and
+ * then record this in the inode. ocfs2_delete_inode will use
+ * this information to determine which lock to take. */
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ mlog_bug_on_msg(OCFS2_I(inode)->ip_orphaned_slot != orphaned_slot &&
+ OCFS2_I(inode)->ip_orphaned_slot
+ != OCFS2_INVALID_SLOT, "Inode %"MLFu64": Node %d "
+ "says it's orphaned in slot %d, we think it's in %d\n",
+ OCFS2_I(inode)->ip_blkno,
+ be32_to_cpu(resp->r_hdr.h_node_num),
+ orphaned_slot, OCFS2_I(inode)->ip_orphaned_slot);
+
+ OCFS2_I(inode)->ip_orphaned_slot = orphaned_slot;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+}
+
+int ocfs2_request_delete_vote(struct inode *inode)
+{
+ int orphaned_slot, status;
+ struct ocfs2_net_response_cb delete_cb;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_vote_msg *request;
+
+ spin_lock(&OCFS2_I(inode)->ip_lock);
+ orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot;
+ spin_unlock(&OCFS2_I(inode)->ip_lock);
+
+ delete_cb.rc_cb = ocfs2_delete_response_cb;
+ delete_cb.rc_priv = inode;
+
+ mlog(0, "Inode %"MLFu64", we start thinking orphaned slot is %d\n",
+ OCFS2_I(inode)->ip_blkno, orphaned_slot);
+
+ status = -ENOMEM;
+ request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno,
+ inode->i_generation,
+ OCFS2_VOTE_REQ_DELETE, orphaned_slot);
+ if (request) {
+ status = ocfs2_request_vote(inode, request, &delete_cb);
+
+ kfree(request);
+ }
+
+ return status;
+}
+
+static void ocfs2_setup_unlink_vote(struct ocfs2_vote_msg *request,
+ struct dentry *dentry)
+{
+ struct inode *parent = dentry->d_parent->d_inode;
+
+ /* We need some values which will uniquely identify a dentry
+ * on the other nodes so that they can find it and run
+ * d_delete against it. Parent directory block and full name
+ * should suffice. */
+
+ mlog(0, "unlink/rename request: parent: %"MLFu64" name: %.*s\n",
+ OCFS2_I(parent)->ip_blkno, dentry->d_name.len,
+ dentry->d_name.name);
+
+ request->v_unlink_parent = cpu_to_be64(OCFS2_I(parent)->ip_blkno);
+ request->v_unlink_namelen = cpu_to_be32(dentry->d_name.len);
+ memcpy(request->v_unlink_dirent, dentry->d_name.name,
+ dentry->d_name.len);
+}
+
+int ocfs2_request_unlink_vote(struct inode *inode,
+ struct dentry *dentry,
+ unsigned int nlink)
+{
+ int status;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_vote_msg *request;
+
+ if (dentry->d_name.len > OCFS2_VOTE_FILENAME_LEN)
+ return -ENAMETOOLONG;
+
+ status = -ENOMEM;
+ request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno,
+ inode->i_generation,
+ OCFS2_VOTE_REQ_UNLINK, nlink);
+ if (request) {
+ ocfs2_setup_unlink_vote(request, dentry);
+
+ status = ocfs2_request_vote(inode, request, NULL);
+
+ kfree(request);
+ }
+ return status;
+}
+
+int ocfs2_request_rename_vote(struct inode *inode,
+ struct dentry *dentry)
+{
+ int status;
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+ struct ocfs2_vote_msg *request;
+
+ if (dentry->d_name.len > OCFS2_VOTE_FILENAME_LEN)
+ return -ENAMETOOLONG;
+
+ status = -ENOMEM;
+ request = ocfs2_new_vote_request(osb, OCFS2_I(inode)->ip_blkno,
+ inode->i_generation,
+ OCFS2_VOTE_REQ_RENAME, 0);
+ if (request) {
+ ocfs2_setup_unlink_vote(request, dentry);
+
+ status = ocfs2_request_vote(inode, request, NULL);
+
+ kfree(request);
+ }
+ return status;
+}
+
+int ocfs2_request_mount_vote(struct ocfs2_super *osb)
+{
+ int status;
+ struct ocfs2_vote_msg *request = NULL;
+
+ request = ocfs2_new_vote_request(osb, 0ULL, 0,
+ OCFS2_VOTE_REQ_MOUNT, 0);
+ if (!request) {
+ status = -ENOMEM;
+ goto bail;
+ }
+
+ status = -EAGAIN;
+ while (status == -EAGAIN) {
+ if (!(osb->s_mount_opt & OCFS2_MOUNT_NOINTR) &&
+ signal_pending(current)) {
+ status = -ERESTARTSYS;
+ goto bail;
+ }
+
+ if (ocfs2_node_map_is_only(osb, &osb->mounted_map,
+ osb->node_num)) {
+ status = 0;
+ goto bail;
+ }
+
+ status = ocfs2_do_request_vote(osb, request, NULL);
+ }
+
+bail:
+ if (request)
+ kfree(request);
+
+ return status;
+}
+
+int ocfs2_request_umount_vote(struct ocfs2_super *osb)
+{
+ int status;
+ struct ocfs2_vote_msg *request = NULL;
+
+ request = ocfs2_new_vote_request(osb, 0ULL, 0,
+ OCFS2_VOTE_REQ_UMOUNT, 0);
+ if (!request) {
+ status = -ENOMEM;
+ goto bail;
+ }
+
+ status = -EAGAIN;
+ while (status == -EAGAIN) {
+ /* Do not check signals on this vote... We really want
+ * this one to go all the way through. */
+
+ if (ocfs2_node_map_is_only(osb, &osb->mounted_map,
+ osb->node_num)) {
+ status = 0;
+ goto bail;
+ }
+
+ status = ocfs2_do_request_vote(osb, request, NULL);
+ }
+
+bail:
+ if (request)
+ kfree(request);
+
+ return status;
+}
+
+/* TODO: This should eventually be a hash table! */
+static struct ocfs2_net_wait_ctxt * __ocfs2_find_net_wait_ctxt(struct ocfs2_super *osb,
+ u32 response_id)
+{
+ struct list_head *p;
+ struct ocfs2_net_wait_ctxt *w = NULL;
+
+ list_for_each(p, &osb->net_response_list) {
+ w = list_entry(p, struct ocfs2_net_wait_ctxt, n_list);
+ if (response_id == w->n_response_id)
+ break;
+ w = NULL;
+ }
+
+ return w;
+}
+
+/* Translate response codes into local node errno values */
+static inline int ocfs2_translate_response(int response)
+{
+ int ret;
+
+ switch (response) {
+ case OCFS2_RESPONSE_OK:
+ ret = 0;
+ break;
+
+ case OCFS2_RESPONSE_BUSY:
+ ret = -EBUSY;
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int ocfs2_handle_response_message(struct o2net_msg *msg,
+ u32 len,
+ void *data)
+{
+ unsigned int response_id, node_num;
+ int response_status;
+ struct ocfs2_super *osb = data;
+ struct ocfs2_response_msg *resp;
+ struct ocfs2_net_wait_ctxt * w;
+ struct ocfs2_net_response_cb *resp_cb;
+
+ resp = (struct ocfs2_response_msg *) msg->buf;
+
+ response_id = be32_to_cpu(resp->r_hdr.h_response_id);
+ node_num = be32_to_cpu(resp->r_hdr.h_node_num);
+ response_status =
+ ocfs2_translate_response(be32_to_cpu(resp->r_response));
+
+ mlog(0, "received response message:\n");
+ mlog(0, "h_response_id = %u\n", response_id);
+ mlog(0, "h_request = %u\n", be32_to_cpu(resp->r_hdr.h_request));
+ mlog(0, "h_blkno = %"MLFu64"\n", be64_to_cpu(resp->r_hdr.h_blkno));
+ mlog(0, "h_generation = %u\n", be32_to_cpu(resp->r_hdr.h_generation));
+ mlog(0, "h_node_num = %u\n", node_num);
+ mlog(0, "r_response = %d\n", response_status);
+
+ spin_lock(&osb->net_response_lock);
+ w = __ocfs2_find_net_wait_ctxt(osb, response_id);
+ if (!w) {
+ mlog(0, "request not found!\n");
+ goto bail;
+ }
+ resp_cb = w->n_callback;
+
+ if (response_status && (!w->n_response)) {
+ /* we only really need one negative response so don't
+ * set it twice. */
+ w->n_response = response_status;
+ }
+
+ if (resp_cb) {
+ spin_unlock(&osb->net_response_lock);
+
+ resp_cb->rc_cb(resp_cb->rc_priv, resp);
+
+ spin_lock(&osb->net_response_lock);
+ }
+
+ __ocfs2_mark_node_responded(osb, w, node_num);
+bail:
+ spin_unlock(&osb->net_response_lock);
+
+ return 0;
+}
+
+static int ocfs2_handle_vote_message(struct o2net_msg *msg,
+ u32 len,
+ void *data)
+{
+ int status;
+ struct ocfs2_super *osb = data;
+ struct ocfs2_vote_work *work;
+
+ work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_KERNEL);
+ if (!work) {
+ status = -ENOMEM;
+ mlog_errno(status);
+ goto bail;
+ }
+
+ INIT_LIST_HEAD(&work->w_list);
+ memcpy(&work->w_msg, msg->buf, sizeof(struct ocfs2_vote_msg));
+
+ mlog(0, "scheduling vote request:\n");
+ mlog(0, "h_response_id = %u\n",
+ be32_to_cpu(work->w_msg.v_hdr.h_response_id));
+ mlog(0, "h_request = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_request));
+ mlog(0, "h_blkno = %"MLFu64"\n",
+ be64_to_cpu(work->w_msg.v_hdr.h_blkno));
+ mlog(0, "h_generation = %u\n",
+ be32_to_cpu(work->w_msg.v_hdr.h_generation));
+ mlog(0, "h_node_num = %u\n",
+ be32_to_cpu(work->w_msg.v_hdr.h_node_num));
+ mlog(0, "v_generic1 = %u\n", be32_to_cpu(work->w_msg.md1.v_generic1));
+
+ spin_lock(&osb->vote_task_lock);
+ list_add_tail(&work->w_list, &osb->vote_list);
+ osb->vote_count++;
+ spin_unlock(&osb->vote_task_lock);
+
+ ocfs2_kick_vote_thread(osb);
+
+ status = 0;
+bail:
+ return status;
+}
+
+void ocfs2_unregister_net_handlers(struct ocfs2_super *osb)
+{
+ if (!osb->net_key)
+ return;
+
+ o2net_unregister_handler_list(&osb->osb_net_handlers);
+
+ if (!list_empty(&osb->net_response_list))
+ mlog(ML_ERROR, "net response list not empty!\n");
+
+ osb->net_key = 0;
+}
+
+int ocfs2_register_net_handlers(struct ocfs2_super *osb)
+{
+ int status = 0;
+
+ status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE,
+ osb->net_key,
+ sizeof(struct ocfs2_response_msg),
+ ocfs2_handle_response_message,
+ osb, &osb->osb_net_handlers);
+ if (status) {
+ mlog_errno(status);
+ goto bail;
+ }
+
+ status = o2net_register_handler(OCFS2_MESSAGE_TYPE_VOTE,
+ osb->net_key,
+ sizeof(struct ocfs2_vote_msg),
+ ocfs2_handle_vote_message,
+ osb, &osb->osb_net_handlers);
+ if (status) {
+ mlog_errno(status);
+ goto bail;
+ }
+bail:
+ if (status < 0)
+ ocfs2_unregister_net_handlers(osb);
+
+ return status;
+}
diff --git a/fs/ocfs2/vote.h b/fs/ocfs2/vote.h
new file mode 100644
index 000000000000..9cce60703466
--- /dev/null
+++ b/fs/ocfs2/vote.h
@@ -0,0 +1,56 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * vote.h
+ *
+ * description here
+ *
+ * Copyright (C) 2002, 2004 Oracle. 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 021110-1307, USA.
+ */
+
+
+#ifndef VOTE_H
+#define VOTE_H
+
+int ocfs2_vote_thread(void *arg);
+static inline void ocfs2_kick_vote_thread(struct ocfs2_super *osb)
+{
+ spin_lock(&osb->vote_task_lock);
+ /* make sure the voting thread gets a swipe at whatever changes
+ * the caller may have made to the voting state */
+ osb->vote_wake_sequence++;
+ spin_unlock(&osb->vote_task_lock);
+ wake_up(&osb->vote_event);
+}
+
+int ocfs2_request_delete_vote(struct inode *inode);
+int ocfs2_request_unlink_vote(struct inode *inode,
+ struct dentry *dentry,
+ unsigned int nlink);
+int ocfs2_request_rename_vote(struct inode *inode,
+ struct dentry *dentry);
+int ocfs2_request_mount_vote(struct ocfs2_super *osb);
+int ocfs2_request_umount_vote(struct ocfs2_super *osb);
+int ocfs2_register_net_handlers(struct ocfs2_super *osb);
+void ocfs2_unregister_net_handlers(struct ocfs2_super *osb);
+
+void ocfs2_mark_inode_remotely_deleted(struct inode *inode);
+
+void ocfs2_remove_node_from_vote_queues(struct ocfs2_super *osb,
+ int node_num);
+#endif
diff --git a/fs/open.c b/fs/open.c
index f53a5b9ffb7d..70e0230d8e77 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -16,9 +16,11 @@
#include <linux/tty.h>
#include <linux/namei.h>
#include <linux/backing-dev.h>
+#include <linux/capability.h>
#include <linux/security.h>
#include <linux/mount.h>
#include <linux/vfs.h>
+#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/personality.h>
@@ -194,7 +196,8 @@ out:
return error;
}
-int do_truncate(struct dentry *dentry, loff_t length, struct file *filp)
+int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+ struct file *filp)
{
int err;
struct iattr newattrs;
@@ -204,19 +207,19 @@ int do_truncate(struct dentry *dentry, loff_t length, struct file *filp)
return -EINVAL;
newattrs.ia_size = length;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ newattrs.ia_valid = ATTR_SIZE | time_attrs;
if (filp) {
newattrs.ia_file = filp;
newattrs.ia_valid |= ATTR_FILE;
}
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
err = notify_change(dentry, &newattrs);
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
return err;
}
-static inline long do_sys_truncate(const char __user * path, loff_t length)
+static long do_sys_truncate(const char __user * path, loff_t length)
{
struct nameidata nd;
struct inode * inode;
@@ -266,7 +269,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
error = locks_verify_truncate(inode, NULL, length);
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(nd.dentry, length, NULL);
+ error = do_truncate(nd.dentry, length, 0, NULL);
}
put_write_access(inode);
@@ -282,7 +285,7 @@ asmlinkage long sys_truncate(const char __user * path, unsigned long length)
return do_sys_truncate(path, (long)length);
}
-static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
{
struct inode * inode;
struct dentry *dentry;
@@ -318,7 +321,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
error = locks_verify_truncate(inode, file, length);
if (!error)
- error = do_truncate(dentry, length, file);
+ error = do_truncate(dentry, length, 0, file);
out_putf:
fput(file);
out:
@@ -381,7 +384,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
newattrs.ia_atime.tv_nsec = 0;
- if (!error)
+ if (!error)
error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
newattrs.ia_mtime.tv_nsec = 0;
if (error)
@@ -397,9 +400,9 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
(error = vfs_permission(&nd, MAY_WRITE)) != 0)
goto dput_and_out;
}
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
error = notify_change(nd.dentry, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
dput_and_out:
path_release(&nd);
out:
@@ -412,14 +415,14 @@ out:
* must be owner or have write permission.
* Else, update from *times, must be owner or super user.
*/
-long do_utimes(char __user * filename, struct timeval * times)
+long do_utimes(int dfd, char __user *filename, struct timeval *times)
{
int error;
struct nameidata nd;
struct inode * inode;
struct iattr newattrs;
- error = user_path_walk(filename, &nd);
+ error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
if (error)
goto out;
@@ -450,22 +453,27 @@ long do_utimes(char __user * filename, struct timeval * times)
(error = vfs_permission(&nd, MAY_WRITE)) != 0)
goto dput_and_out;
}
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
error = notify_change(nd.dentry, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
dput_and_out:
path_release(&nd);
out:
return error;
}
-asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes)
+asmlinkage long sys_futimesat(int dfd, char __user *filename, struct timeval __user *utimes)
{
struct timeval times[2];
if (utimes && copy_from_user(&times, utimes, sizeof(times)))
return -EFAULT;
- return do_utimes(filename, utimes ? times : NULL);
+ return do_utimes(dfd, filename, utimes ? times : NULL);
+}
+
+asmlinkage long sys_utimes(char __user *filename, struct timeval __user *utimes)
+{
+ return sys_futimesat(AT_FDCWD, filename, utimes);
}
@@ -474,7 +482,7 @@ asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utime
* We do this by temporarily clearing all FS-related capabilities and
* switching the fsuid/fsgid around to the real ones.
*/
-asmlinkage long sys_access(const char __user * filename, int mode)
+asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
{
struct nameidata nd;
int old_fsuid, old_fsgid;
@@ -504,7 +512,7 @@ asmlinkage long sys_access(const char __user * filename, int mode)
else
current->cap_effective = current->cap_permitted;
- res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
+ res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
if (!res) {
res = vfs_permission(&nd, mode);
/* SuS v2 requires we report a read only fs too */
@@ -521,6 +529,11 @@ asmlinkage long sys_access(const char __user * filename, int mode)
return res;
}
+asmlinkage long sys_access(const char __user *filename, int mode)
+{
+ return sys_faccessat(AT_FDCWD, filename, mode);
+}
+
asmlinkage long sys_chdir(const char __user * filename)
{
struct nameidata nd;
@@ -619,13 +632,13 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
err = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto out_putf;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
err = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out_putf:
fput(file);
@@ -633,14 +646,15 @@ out:
return err;
}
-asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
+asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
+ mode_t mode)
{
struct nameidata nd;
struct inode * inode;
int error;
struct iattr newattrs;
- error = user_path_walk(filename, &nd);
+ error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
if (error)
goto out;
inode = nd.dentry->d_inode;
@@ -653,13 +667,13 @@ asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
goto dput_and_out;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (mode == (mode_t) -1)
mode = inode->i_mode;
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
error = notify_change(nd.dentry, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
dput_and_out:
path_release(&nd);
@@ -667,6 +681,11 @@ out:
return error;
}
+asmlinkage long sys_chmod(const char __user *filename, mode_t mode)
+{
+ return sys_fchmodat(AT_FDCWD, filename, mode);
+}
+
static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
{
struct inode * inode;
@@ -695,9 +714,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
}
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out:
return error;
}
@@ -715,6 +734,26 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
return error;
}
+asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user,
+ gid_t group, int flag)
+{
+ struct nameidata nd;
+ int error = -EINVAL;
+ int follow;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+ error = __user_walk_fd(dfd, filename, follow, &nd);
+ if (!error) {
+ error = chown_common(nd.dentry, user, group);
+ path_release(&nd);
+ }
+out:
+ return error;
+}
+
asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
{
struct nameidata nd;
@@ -818,7 +857,8 @@ cleanup_file:
* 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 *do_filp_open(int dfd, const char *filename, int flags,
+ int mode)
{
int namei_flags, error;
struct nameidata nd;
@@ -827,12 +867,17 @@ struct file *filp_open(const char * filename, int flags, int mode)
if ((namei_flags+1) & O_ACCMODE)
namei_flags++;
- error = open_namei(filename, namei_flags, mode, &nd);
+ error = open_namei(dfd, filename, namei_flags, mode, &nd);
if (!error)
return nameidata_to_filp(&nd, flags);
return ERR_PTR(error);
}
+
+struct file *filp_open(const char *filename, int flags, int mode)
+{
+ return do_filp_open(AT_FDCWD, filename, flags, mode);
+}
EXPORT_SYMBOL(filp_open);
/**
@@ -970,7 +1015,7 @@ out:
EXPORT_SYMBOL(get_unused_fd);
-static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
+static void __put_unused_fd(struct files_struct *files, unsigned int fd)
{
struct fdtable *fdt = files_fdtable(files);
__FD_CLR(fd, fdt->open_fds);
@@ -989,7 +1034,7 @@ void fastcall put_unused_fd(unsigned int fd)
EXPORT_SYMBOL(put_unused_fd);
/*
- * Install a file pointer in the fd array.
+ * Install a file pointer in the fd array.
*
* The VFS is full of places where we drop the files lock between
* setting the open_fds bitmap and installing the file in the file
@@ -1014,7 +1059,7 @@ void fastcall fd_install(unsigned int fd, struct file * file)
EXPORT_SYMBOL(fd_install);
-long do_sys_open(const char __user *filename, int flags, int mode)
+long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
{
char *tmp = getname(filename);
int fd = PTR_ERR(tmp);
@@ -1022,7 +1067,7 @@ long do_sys_open(const char __user *filename, int flags, int mode)
if (!IS_ERR(tmp)) {
fd = get_unused_fd();
if (fd >= 0) {
- struct file *f = filp_open(tmp, flags, mode);
+ struct file *f = do_filp_open(dfd, tmp, flags, mode);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
@@ -1041,10 +1086,20 @@ 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);
+ return do_sys_open(AT_FDCWD, filename, flags, mode);
}
EXPORT_SYMBOL_GPL(sys_open);
+asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
+ int mode)
+{
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
+
+ return do_sys_open(dfd, filename, flags, mode);
+}
+EXPORT_SYMBOL_GPL(sys_openat);
+
#ifndef __alpha__
/*
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index 656bc43431b9..c9a478099281 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -21,26 +21,30 @@ config ACORN_PARTITION
Support hard disks partitioned under Acorn operating systems.
config ACORN_PARTITION_CUMANA
- bool "Cumana partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "Cumana partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
help
Say Y here if you would like to use hard disks under Linux which
were partitioned using the Cumana interface on Acorn machines.
config ACORN_PARTITION_EESOX
- bool "EESOX partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "EESOX partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
config ACORN_PARTITION_ICS
- bool "ICS partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "ICS partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
help
Say Y here if you would like to use hard disks under Linux which
were partitioned using the ICS interface on Acorn machines.
config ACORN_PARTITION_ADFS
- bool "Native filecore partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "Native filecore partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
help
The Acorn Disc Filing System is the standard file system of the
RiscOS operating system which runs on Acorn's ARM-based Risc PC
@@ -48,15 +52,17 @@ config ACORN_PARTITION_ADFS
`Y' here, Linux will support disk partitions created under ADFS.
config ACORN_PARTITION_POWERTEC
- bool "PowerTec partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "PowerTec partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
help
Support reading partition tables created on Acorn machines using
the PowerTec SCSI drive.
config ACORN_PARTITION_RISCIX
- bool "RISCiX partition support" if PARTITION_ADVANCED && ACORN_PARTITION
+ bool "RISCiX partition support" if PARTITION_ADVANCED
default y if ARCH_ACORN
+ depends on ACORN_PARTITION
help
Once upon a time, there was a native Unix port for the Acorn series
of machines called RISCiX. If you say 'Y' here, Linux will be able
@@ -85,7 +91,7 @@ config ATARI_PARTITION
config IBM_PARTITION
bool "IBM disk label and partition support"
- depends on PARTITION_ADVANCED && ARCH_S390
+ depends on PARTITION_ADVANCED && S390
help
Say Y here if you would like to be able to read the hard disk
partition table format used by IBM DASD disks operating under CMS.
@@ -216,6 +222,13 @@ config SUN_PARTITION
given by the tar program ("man tar" or preferably "info tar"). If
you don't know what all this is about, say N.
+config KARMA_PARTITION
+ bool "Karma Partition support"
+ depends on PARTITION_ADVANCED
+ help
+ Say Y here if you would like to mount the Rio Karma MP3 player, as it
+ uses a proprietary partition table.
+
config EFI_PARTITION
bool "EFI GUID Partition support"
depends on PARTITION_ADVANCED
@@ -224,5 +237,3 @@ config EFI_PARTITION
Say Y here if you would like to use hard disks under Linux which
were partitioned using EFI GPT. Presently only useful on the
IA-64 platform.
-
-# define_bool CONFIG_ACORN_PARTITION_CUMANA y
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile
index 66d5cc26fafb..42c7d3878ed0 100644
--- a/fs/partitions/Makefile
+++ b/fs/partitions/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SUN_PARTITION) += sun.o
obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
obj-$(CONFIG_IBM_PARTITION) += ibm.o
obj-$(CONFIG_EFI_PARTITION) += efi.o
+obj-$(CONFIG_KARMA_PARTITION) += karma.o
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 8dc1822a7022..f924f459bdb8 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -35,6 +35,7 @@
#include "ibm.h"
#include "ultrix.h"
#include "efi.h"
+#include "karma.h"
#ifdef CONFIG_BLK_DEV_MD
extern void md_autodetect_dev(dev_t dev);
@@ -103,6 +104,9 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
#ifdef CONFIG_IBM_PARTITION
ibm_partition,
#endif
+#ifdef CONFIG_KARMA_PARTITION
+ karma_partition,
+#endif
NULL
};
@@ -226,7 +230,7 @@ static struct sysfs_ops part_sysfs_ops = {
static ssize_t part_uevent_store(struct hd_struct * p,
const char *page, size_t count)
{
- kobject_hotplug(&p->kobj, KOBJ_ADD);
+ kobject_uevent(&p->kobj, KOBJ_ADD);
return count;
}
static ssize_t part_dev_read(struct hd_struct * p, char *page)
@@ -336,12 +340,31 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
disk->part[part-1] = p;
}
+static char *make_block_name(struct gendisk *disk)
+{
+ char *name;
+ static char *block_str = "block:";
+ int size;
+
+ size = strlen(block_str) + strlen(disk->disk_name) + 1;
+ name = kmalloc(size, GFP_KERNEL);
+ if (!name)
+ return NULL;
+ strcpy(name, block_str);
+ strcat(name, disk->disk_name);
+ return name;
+}
+
static void disk_sysfs_symlinks(struct gendisk *disk)
{
struct device *target = get_device(disk->driverfs_dev);
if (target) {
+ char *disk_name = make_block_name(disk);
sysfs_create_link(&disk->kobj,&target->kobj,"device");
- sysfs_create_link(&target->kobj,&disk->kobj,"block");
+ if (disk_name) {
+ sysfs_create_link(&target->kobj,&disk->kobj,disk_name);
+ kfree(disk_name);
+ }
}
}
@@ -360,7 +383,7 @@ void register_disk(struct gendisk *disk)
if ((err = kobject_add(&disk->kobj)))
return;
disk_sysfs_symlinks(disk);
- kobject_hotplug(&disk->kobj, KOBJ_ADD);
+ kobject_uevent(&disk->kobj, KOBJ_ADD);
/* No minors to use for partitions */
if (disk->minors == 1) {
@@ -461,10 +484,14 @@ void del_gendisk(struct gendisk *disk)
devfs_remove_disk(disk);
if (disk->driverfs_dev) {
+ char *disk_name = make_block_name(disk);
sysfs_remove_link(&disk->kobj, "device");
- sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
+ if (disk_name) {
+ sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name);
+ kfree(disk_name);
+ }
put_device(disk->driverfs_dev);
}
- kobject_hotplug(&disk->kobj, KOBJ_REMOVE);
+ kobject_uevent(&disk->kobj, KOBJ_REMOVE);
kobject_del(&disk->kobj);
}
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 6327bcb2d73d..78010ad60e47 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -56,7 +56,10 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
struct hd_geometry *geo;
char type[5] = {0,};
char name[7] = {0,};
- struct vtoc_volume_label *vlabel;
+ union label_t {
+ struct vtoc_volume_label vol;
+ struct vtoc_cms_label cms;
+ } *label;
unsigned char *data;
Sector sect;
@@ -64,9 +67,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
goto out_noinfo;
if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
goto out_nogeo;
- if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label),
- GFP_KERNEL)) == NULL)
- goto out_novlab;
+ if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
+ goto out_nolab;
if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
@@ -87,7 +89,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
strncpy(name, data + 8, 6);
else
strncpy(name, data + 4, 6);
- memcpy (vlabel, data, sizeof(struct vtoc_volume_label));
+ memcpy(label, data, sizeof(union label_t));
put_dev_sector(sect);
EBCASC(type, 4);
@@ -100,14 +102,12 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
/*
* VM style CMS1 labeled disk
*/
- int *label = (int *) vlabel;
-
- if (label[13] != 0) {
+ if (label->cms.disk_offset != 0) {
printk("CMS1/%8s(MDSK):", name);
/* disk is reserved minidisk */
- blocksize = label[3];
- offset = label[13];
- size = (label[7] - 1)*(blocksize >> 9);
+ blocksize = label->cms.block_size;
+ offset = label->cms.disk_offset;
+ size = (label->cms.block_count - 1) * (blocksize >> 9);
} else {
printk("CMS1/%8s:", name);
offset = (info->label_block + 1);
@@ -126,7 +126,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
printk("VOL1/%8s:", name);
/* get block number and read then go through format1 labels */
- blk = cchhb2blk(&vlabel->vtoc, geo) + 1;
+ blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
counter = 0;
while ((data = read_dev_sector(bdev, blk*(blocksize/512),
&sect)) != NULL) {
@@ -174,7 +174,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
}
printk("\n");
- kfree(vlabel);
+ kfree(label);
kfree(geo);
kfree(info);
return 1;
@@ -182,8 +182,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
out_readerr:
out_badsect:
out_noioctl:
- kfree(vlabel);
-out_novlab:
+ kfree(label);
+out_nolab:
kfree(geo);
out_nogeo:
kfree(info);
diff --git a/fs/partitions/karma.c b/fs/partitions/karma.c
new file mode 100644
index 000000000000..176d89bcf123
--- /dev/null
+++ b/fs/partitions/karma.c
@@ -0,0 +1,57 @@
+/*
+ * fs/partitions/karma.c
+ * Rio Karma partition info.
+ *
+ * Copyright (C) 2006 Bob Copeland (me@bobcopeland.com)
+ * based on osf.c
+ */
+
+#include "check.h"
+#include "karma.h"
+
+int karma_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+ int i;
+ int slot = 1;
+ Sector sect;
+ unsigned char *data;
+ struct disklabel {
+ u8 d_reserved[270];
+ struct d_partition {
+ __le32 p_res;
+ u8 p_fstype;
+ u8 p_res2[3];
+ __le32 p_offset;
+ __le32 p_size;
+ } d_partitions[2];
+ u8 d_blank[208];
+ __le16 d_magic;
+ } __attribute__((packed)) *label;
+ struct d_partition *p;
+
+ data = read_dev_sector(bdev, 0, &sect);
+ if (!data)
+ return -1;
+
+ label = (struct disklabel *)data;
+ if (le16_to_cpu(label->d_magic) != KARMA_LABEL_MAGIC) {
+ put_dev_sector(sect);
+ return 0;
+ }
+
+ p = label->d_partitions;
+ for (i = 0 ; i < 2; i++, p++) {
+ if (slot == state->limit)
+ break;
+
+ if (p->p_fstype == 0x4d && le32_to_cpu(p->p_size)) {
+ put_partition(state, slot, le32_to_cpu(p->p_offset),
+ le32_to_cpu(p->p_size));
+ }
+ slot++;
+ }
+ printk("\n");
+ put_dev_sector(sect);
+ return 1;
+}
+
diff --git a/fs/partitions/karma.h b/fs/partitions/karma.h
new file mode 100644
index 000000000000..ecf7d3f2a3d8
--- /dev/null
+++ b/fs/partitions/karma.h
@@ -0,0 +1,8 @@
+/*
+ * fs/partitions/karma.h
+ */
+
+#define KARMA_LABEL_MAGIC 0xAB56
+
+int karma_partition(struct parsed_partitions *state, struct block_device *bdev);
+
diff --git a/fs/pipe.c b/fs/pipe.c
index 66aa0b938d6a..d722579df79a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -44,13 +44,13 @@ void pipe_wait(struct inode * inode)
* is considered a noninteractive wait:
*/
prepare_to_wait(PIPE_WAIT(*inode), &wait, TASK_INTERRUPTIBLE|TASK_NONINTERACTIVE);
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
schedule();
finish_wait(PIPE_WAIT(*inode), &wait);
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
}
-static inline int
+static int
pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
{
unsigned long copy;
@@ -70,7 +70,7 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
return 0;
}
-static inline int
+static int
pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
{
unsigned long copy;
@@ -136,7 +136,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
info = inode->i_pipe;
for (;;) {
int bufs = info->nrbufs;
@@ -200,7 +200,7 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
}
pipe_wait(inode);
}
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
/* Signal writers asynchronously that there is more room. */
if (do_wakeup) {
wake_up_interruptible(PIPE_WAIT(*inode));
@@ -237,7 +237,7 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
do_wakeup = 0;
ret = 0;
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
info = inode->i_pipe;
if (!PIPE_READERS(*inode)) {
@@ -341,13 +341,13 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
PIPE_WAITING_WRITERS(*inode)--;
}
out:
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
if (do_wakeup) {
wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
}
if (ret > 0)
- inode_update_time(inode, 1); /* mtime and ctime */
+ file_update_time(filp);
return ret;
}
@@ -381,7 +381,7 @@ pipe_ioctl(struct inode *pino, struct file *filp,
switch (cmd) {
case FIONREAD:
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
info = inode->i_pipe;
count = 0;
buf = info->curbuf;
@@ -390,7 +390,7 @@ pipe_ioctl(struct inode *pino, struct file *filp,
count += info->bufs[buf].len;
buf = (buf+1) & (PIPE_BUFFERS-1);
}
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return put_user(count, (int __user *)arg);
default:
return -EINVAL;
@@ -433,7 +433,7 @@ pipe_poll(struct file *filp, poll_table *wait)
static int
pipe_release(struct inode *inode, int decr, int decw)
{
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
PIPE_READERS(*inode) -= decr;
PIPE_WRITERS(*inode) -= decw;
if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
@@ -443,7 +443,7 @@ pipe_release(struct inode *inode, int decr, int decw)
kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
}
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return 0;
}
@@ -454,9 +454,9 @@ pipe_read_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
if (retval < 0)
return retval;
@@ -471,9 +471,9 @@ pipe_write_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
if (retval < 0)
return retval;
@@ -488,14 +488,14 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on)
struct inode *inode = filp->f_dentry->d_inode;
int retval;
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
if (retval >= 0)
retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
if (retval < 0)
return retval;
@@ -534,9 +534,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
{
/* We could have perhaps used atomic_t, but this and friends
below are the only places. So it doesn't seem worthwhile. */
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
PIPE_READERS(*inode)++;
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return 0;
}
@@ -544,9 +544,9 @@ pipe_read_open(struct inode *inode, struct file *filp)
static int
pipe_write_open(struct inode *inode, struct file *filp)
{
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
PIPE_WRITERS(*inode)++;
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return 0;
}
@@ -554,12 +554,12 @@ pipe_write_open(struct inode *inode, struct file *filp)
static int
pipe_rdwr_open(struct inode *inode, struct file *filp)
{
- down(PIPE_SEM(*inode));
+ mutex_lock(PIPE_MUTEX(*inode));
if (filp->f_mode & FMODE_READ)
PIPE_READERS(*inode)++;
if (filp->f_mode & FMODE_WRITE)
PIPE_WRITERS(*inode)++;
- up(PIPE_SEM(*inode));
+ mutex_unlock(PIPE_MUTEX(*inode));
return 0;
}
diff --git a/fs/pnode.c b/fs/pnode.c
index aeeec8ba8dd2..f1871f773f64 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -103,7 +103,7 @@ static struct vfsmount *propagation_next(struct vfsmount *m,
struct vfsmount *next;
struct vfsmount *master = m->mnt_master;
- if ( master == origin->mnt_master ) {
+ if (master == origin->mnt_master) {
next = next_peer(m);
return ((next == origin) ? NULL : next);
} else if (m->mnt_slave.next != &master->mnt_slave_list)
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 3e1239e4b303..7eb1bd7f800c 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -308,7 +308,7 @@ int proc_pid_status(struct task_struct *task, char * buffer)
buffer = task_sig(task, buffer);
buffer = task_cap(task, buffer);
buffer = cpuset_task_status_allowed(task, buffer);
-#if defined(CONFIG_ARCH_S390)
+#if defined(CONFIG_S390)
buffer = task_show_regs(task, buffer);
#endif
return buffer - orig;
@@ -330,7 +330,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
unsigned long min_flt = 0, maj_flt = 0;
cputime_t cutime, cstime, utime, stime;
unsigned long rsslim = 0;
- unsigned long it_real_value = 0;
+ DEFINE_KTIME(it_real_value);
struct task_struct *t;
char tcomm[sizeof(task->comm)];
@@ -386,7 +386,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
utime = cputime_add(utime, task->signal->utime);
stime = cputime_add(stime, task->signal->stime);
}
- it_real_value = task->signal->it_real_value;
+ it_real_value = task->signal->real_timer.expires;
}
ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
read_unlock(&tasklist_lock);
@@ -435,7 +435,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
priority,
nice,
num_threads,
- jiffies_to_clock_t(it_real_value),
+ (long) ktime_to_clock_t(it_real_value),
start_time,
vsize,
mm ? get_mm_rss(mm) : 0,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 634355e16986..20feb7568deb 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -55,6 +55,7 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
+#include <linux/capability.h>
#include <linux/file.h>
#include <linux/string.h>
#include <linux/seq_file.h>
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 72b431d0a0a4..20e5c4509a43 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -21,6 +21,8 @@
#include <linux/bitops.h>
#include <asm/uaccess.h>
+#include "internal.h"
+
static ssize_t proc_file_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos);
static ssize_t proc_file_write(struct file *file, const char __user *buffer,
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index e6a818a93f3d..6573f31f1fd9 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -19,7 +19,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-extern void free_proc_entry(struct proc_dir_entry *);
+#include "internal.h"
static inline struct proc_dir_entry * de_get(struct proc_dir_entry *de)
{
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 3e55198f9806..95a1cf32b838 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -37,6 +37,10 @@ extern int proc_tgid_stat(struct task_struct *, char *);
extern int proc_pid_status(struct task_struct *, char *);
extern int proc_pid_statm(struct task_struct *, char *);
+void free_proc_entry(struct proc_dir_entry *de);
+
+int proc_init_inodecache(void);
+
static inline struct task_struct *proc_task(struct inode *inode)
{
return PROC_I(inode)->task;
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 1c7da988fcc3..adc2cd95169a 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -14,6 +14,7 @@
#include <linux/proc_fs.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/capability.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/vmalloc.h>
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index fb117b74809e..9bdd077d6f55 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -81,6 +81,30 @@ void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop
__proc_device_tree_add_prop(pde, prop);
}
+void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
+ struct property *prop)
+{
+ remove_proc_entry(prop->name, pde);
+}
+
+void proc_device_tree_update_prop(struct proc_dir_entry *pde,
+ struct property *newprop,
+ struct property *oldprop)
+{
+ struct proc_dir_entry *ent;
+
+ for (ent = pde->subdir; ent != NULL; ent = ent->next)
+ if (ent->data == oldprop)
+ break;
+ if (ent == NULL) {
+ printk(KERN_WARNING "device-tree: property \"%s\" "
+ " does not exist\n", oldprop->name);
+ } else {
+ ent->data = newprop;
+ ent->size = newprop->length;
+ }
+}
+
/*
* Process a node, adding entries for its children and its properties.
*/
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 5b6b0b6038a7..8f8014285a34 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -20,6 +20,7 @@
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
+#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/string.h>
#include <linux/mman.h>
@@ -62,7 +63,6 @@
*/
extern int get_hardware_list(char *);
extern int get_stram_list(char *);
-extern int get_chrdev_list(char *);
extern int get_filesystem_list(char *);
extern int get_exec_domain_list(char *);
extern int get_dma_list(char *);
@@ -248,6 +248,154 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &cpuinfo_op);
}
+
+enum devinfo_states {
+ CHR_HDR,
+ CHR_LIST,
+ BLK_HDR,
+ BLK_LIST,
+ DEVINFO_DONE
+};
+
+struct devinfo_state {
+ void *chrdev;
+ void *blkdev;
+ unsigned int num_records;
+ unsigned int cur_record;
+ enum devinfo_states state;
+};
+
+static void *devinfo_start(struct seq_file *f, loff_t *pos)
+{
+ struct devinfo_state *info = f->private;
+
+ if (*pos) {
+ if ((info) && (*pos <= info->num_records))
+ return info;
+ return NULL;
+ }
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ f->private = info;
+ info->chrdev = acquire_chrdev_list();
+ info->blkdev = acquire_blkdev_list();
+ info->state = CHR_HDR;
+ info->num_records = count_chrdev_list();
+ info->num_records += count_blkdev_list();
+ info->num_records += 2; /* Character and Block headers */
+ *pos = 1;
+ info->cur_record = *pos;
+ return info;
+}
+
+static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
+{
+ int idummy;
+ char *ndummy;
+ struct devinfo_state *info = f->private;
+
+ switch (info->state) {
+ case CHR_HDR:
+ info->state = CHR_LIST;
+ (*pos)++;
+ /*fallthrough*/
+ case CHR_LIST:
+ if (get_chrdev_info(info->chrdev,&idummy,&ndummy)) {
+ /*
+ * The character dev list is complete
+ */
+ info->state = BLK_HDR;
+ } else {
+ info->chrdev = get_next_chrdev(info->chrdev);
+ }
+ (*pos)++;
+ break;
+ case BLK_HDR:
+ info->state = BLK_LIST;
+ (*pos)++;
+ break;
+ case BLK_LIST:
+ if (get_blkdev_info(info->blkdev,&idummy,&ndummy)) {
+ /*
+ * The block dev list is complete
+ */
+ info->state = DEVINFO_DONE;
+ } else {
+ info->blkdev = get_next_blkdev(info->blkdev);
+ }
+ (*pos)++;
+ break;
+ case DEVINFO_DONE:
+ (*pos)++;
+ info->cur_record = *pos;
+ info = NULL;
+ break;
+ default:
+ break;
+ }
+ if (info)
+ info->cur_record = *pos;
+ return info;
+}
+
+static void devinfo_stop(struct seq_file *f, void *v)
+{
+ struct devinfo_state *info = f->private;
+
+ if (info) {
+ release_chrdev_list(info->chrdev);
+ release_blkdev_list(info->blkdev);
+ f->private = NULL;
+ kfree(info);
+ }
+}
+
+static int devinfo_show(struct seq_file *f, void *arg)
+{
+ int major;
+ char *name;
+ struct devinfo_state *info = f->private;
+
+ switch(info->state) {
+ case CHR_HDR:
+ seq_printf(f,"Character devices:\n");
+ /* fallthrough */
+ case CHR_LIST:
+ if (!get_chrdev_info(info->chrdev,&major,&name))
+ seq_printf(f,"%3d %s\n",major,name);
+ break;
+ case BLK_HDR:
+ seq_printf(f,"\nBlock devices:\n");
+ /* fallthrough */
+ case BLK_LIST:
+ if (!get_blkdev_info(info->blkdev,&major,&name))
+ seq_printf(f,"%3d %s\n",major,name);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct seq_operations devinfo_op = {
+ .start = devinfo_start,
+ .next = devinfo_next,
+ .stop = devinfo_stop,
+ .show = devinfo_show,
+};
+
+static int devinfo_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &devinfo_op);
+}
+
+static struct file_operations proc_devinfo_operations = {
+ .open = devinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static struct file_operations proc_cpuinfo_operations = {
.open = cpuinfo_open,
.read = seq_read,
@@ -323,6 +471,7 @@ static struct file_operations proc_modules_operations = {
};
#endif
+#ifdef CONFIG_SLAB
extern struct seq_operations slabinfo_op;
extern ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
static int slabinfo_open(struct inode *inode, struct file *file)
@@ -336,6 +485,7 @@ static struct file_operations proc_slabinfo_operations = {
.llseek = seq_lseek,
.release = seq_release,
};
+#endif
static int show_stat(struct seq_file *p, void *v)
{
@@ -448,14 +598,6 @@ static struct file_operations proc_stat_operations = {
.release = single_release,
};
-static int devices_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = get_chrdev_list(page);
- len += get_blkdev_list(page+len, len);
- return proc_calc_metrics(page, start, off, count, eof, len);
-}
-
/*
* /proc/interrupts
*/
@@ -580,7 +722,6 @@ void __init proc_misc_init(void)
#ifdef CONFIG_STRAM_PROC
{"stram", stram_read_proc},
#endif
- {"devices", devices_read_proc},
{"filesystems", filesystems_read_proc},
{"cmdline", cmdline_read_proc},
{"locks", locks_read_proc},
@@ -596,11 +737,14 @@ void __init proc_misc_init(void)
entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
if (entry)
entry->proc_fops = &proc_kmsg_operations;
+ create_seq_entry("devices", 0, &proc_devinfo_operations);
create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
create_seq_entry("partitions", 0, &proc_partitions_operations);
create_seq_entry("stat", 0, &proc_stat_operations);
create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+#ifdef CONFIG_SLAB
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
+#endif
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index aef148f099a2..68896283c8ae 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -18,6 +18,8 @@
#include <linux/bitops.h>
#include <linux/smp_lock.h>
+#include "internal.h"
+
struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
#ifdef CONFIG_SYSCTL
@@ -36,7 +38,6 @@ static struct file_system_type proc_fs_type = {
.kill_sb = kill_anon_super,
};
-extern int __init proc_init_inodecache(void);
void __init proc_root_init(void)
{
int err = proc_init_inodecache();
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 50bd5a8f0446..0eaad41f4658 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -390,129 +390,12 @@ struct seq_operations proc_pid_smaps_op = {
};
#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(struct vm_area_struct *vma)
-{
- int i;
- struct page *page;
- unsigned long vaddr;
- 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;
-
- for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) {
- page = follow_page(vma, 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)]++;
- }
- cond_resched();
- }
- 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 (node_isset(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;
-}
+extern int show_numa_map(struct seq_file *m, void *v);
struct seq_operations proc_pid_numa_maps_op = {
- .start = m_start,
- .next = m_next,
- .stop = m_stop,
- .show = show_numa_map
+ .start = m_start,
+ .next = m_next,
+ .stop = m_stop,
+ .show = show_numa_map
};
#endif
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 3b2e7b69e63a..4063fb32f78c 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -14,7 +14,6 @@
#include <linux/a.out.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
-#include <linux/proc_fs.h>
#include <linux/highmem.h>
#include <linux/bootmem.h>
#include <linux/init.h>
@@ -35,11 +34,14 @@ static size_t elfcorebuf_sz;
/* Total size of vmcore file. */
static u64 vmcore_size;
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
struct proc_dir_entry *proc_vmcore = NULL;
/* Reads a page from the oldmem device from given offset. */
static ssize_t read_from_oldmem(char *buf, size_t count,
- loff_t *ppos, int userbuf)
+ u64 *ppos, int userbuf)
{
unsigned long pfn, offset;
size_t nr_bytes;
diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
index 991253927658..46efbf52cbec 100644
--- a/fs/qnx4/bitmap.c
+++ b/fs/qnx4/bitmap.c
@@ -23,10 +23,12 @@
#include <linux/buffer_head.h>
#include <linux/bitops.h>
+#if 0
int qnx4_new_block(struct super_block *sb)
{
return 0;
}
+#endif /* 0 */
static void count_bits(register const char *bmPart, register int size,
int *const tf)
diff --git a/fs/quota.c b/fs/quota.c
index 612e04db4b93..ba9e0bf32f67 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -15,6 +15,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/buffer_head.h>
+#include <linux/capability.h>
#include <linux/quotaops.h>
/* Check validity of generic quotactl commands */
@@ -168,7 +169,7 @@ static void quota_sync_sb(struct super_block *sb, int type)
sync_blockdev(sb->s_bdev);
/* Now when everything is written we can discard the pagecache so
- * that userspace sees the changes. We need i_sem and so we could
+ * that userspace sees the changes. We need i_mutex and so we could
* not do it inside dqonoff_sem. Moreover we need to be carefull
* about races with quotaoff() (that is the reason why we have own
* reference to inode). */
@@ -184,9 +185,9 @@ static void quota_sync_sb(struct super_block *sb, int type)
up(&sb_dqopt(sb)->dqonoff_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (discard[cnt]) {
- down(&discard[cnt]->i_sem);
+ mutex_lock(&discard[cnt]->i_mutex);
truncate_inode_pages(&discard[cnt]->i_data, 0);
- up(&discard[cnt]->i_sem);
+ mutex_unlock(&discard[cnt]->i_mutex);
iput(discard[cnt]);
}
}
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index 7afcbb1b9376..a4ef91bb4f3b 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -35,7 +35,8 @@ static int v2_check_quota_file(struct super_block *sb, int type)
size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
if (size != sizeof(struct v2_disk_dqheader)) {
- printk("failed read\n");
+ printk("quota_v2: failed read expected=%d got=%d\n",
+ sizeof(struct v2_disk_dqheader), size);
return 0;
}
if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
diff --git a/fs/ramfs/Makefile b/fs/ramfs/Makefile
index f096f3007091..5a0236e02ee1 100644
--- a/fs/ramfs/Makefile
+++ b/fs/ramfs/Makefile
@@ -4,4 +4,6 @@
obj-$(CONFIG_RAMFS) += ramfs.o
-ramfs-objs := inode.o
+file-mmu-y := file-nommu.o
+file-mmu-$(CONFIG_MMU) := file-mmu.o
+ramfs-objs += inode.o $(file-mmu-y)
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
new file mode 100644
index 000000000000..2115383dcc8d
--- /dev/null
+++ b/fs/ramfs/file-mmu.c
@@ -0,0 +1,57 @@
+/* file-mmu.c: ramfs MMU-based file operations
+ *
+ * Resizable simple ram filesystem for Linux.
+ *
+ * Copyright (C) 2000 Linus Torvalds.
+ * 2000 Transmeta Corp.
+ *
+ * Usage limits added by David Gibson, Linuxcare Australia.
+ * This file is released under the GPL.
+ */
+
+/*
+ * NOTE! This filesystem is probably most useful
+ * not as a real filesystem, but as an example of
+ * how virtual filesystems can be written.
+ *
+ * It doesn't get much simpler than this. Consider
+ * that this file implements the full semantics of
+ * a POSIX-compliant read-write filesystem.
+ *
+ * Note in particular how the filesystem does not
+ * need to implement any data structures of its own
+ * to keep track of the virtual data: using the VFS
+ * caches is sufficient.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/backing-dev.h>
+#include <linux/ramfs.h>
+
+#include <asm/uaccess.h>
+#include "internal.h"
+
+struct address_space_operations ramfs_aops = {
+ .readpage = simple_readpage,
+ .prepare_write = simple_prepare_write,
+ .commit_write = simple_commit_write
+};
+
+struct file_operations ramfs_file_operations = {
+ .read = generic_file_read,
+ .write = generic_file_write,
+ .mmap = generic_file_mmap,
+ .fsync = simple_sync_file,
+ .sendfile = generic_file_sendfile,
+ .llseek = generic_file_llseek,
+};
+
+struct inode_operations ramfs_file_inode_operations = {
+ .getattr = simple_getattr,
+};
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
new file mode 100644
index 000000000000..3f810acd0bfa
--- /dev/null
+++ b/fs/ramfs/file-nommu.c
@@ -0,0 +1,292 @@
+/* file-nommu.c: no-MMU version of ramfs
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/smp_lock.h>
+#include <linux/backing-dev.h>
+#include <linux/ramfs.h>
+#include <linux/quotaops.h>
+#include <linux/pagevec.h>
+#include <linux/mman.h>
+
+#include <asm/uaccess.h>
+#include "internal.h"
+
+static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
+
+struct address_space_operations ramfs_aops = {
+ .readpage = simple_readpage,
+ .prepare_write = simple_prepare_write,
+ .commit_write = simple_commit_write
+};
+
+struct file_operations ramfs_file_operations = {
+ .mmap = ramfs_nommu_mmap,
+ .get_unmapped_area = ramfs_nommu_get_unmapped_area,
+ .read = generic_file_read,
+ .write = generic_file_write,
+ .fsync = simple_sync_file,
+ .sendfile = generic_file_sendfile,
+ .llseek = generic_file_llseek,
+};
+
+struct inode_operations ramfs_file_inode_operations = {
+ .setattr = ramfs_nommu_setattr,
+ .getattr = simple_getattr,
+};
+
+/*****************************************************************************/
+/*
+ * add a contiguous set of pages into a ramfs inode when it's truncated from
+ * size 0 on the assumption that it's going to be used for an mmap of shared
+ * memory
+ */
+static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
+{
+ struct pagevec lru_pvec;
+ unsigned long npages, xpages, loop, limit;
+ struct page *pages;
+ unsigned order;
+ void *data;
+ int ret;
+
+ /* make various checks */
+ order = get_order(newsize);
+ if (unlikely(order >= MAX_ORDER))
+ goto too_big;
+
+ limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit != RLIM_INFINITY && newsize > limit)
+ goto fsize_exceeded;
+
+ if (newsize > inode->i_sb->s_maxbytes)
+ goto too_big;
+
+ i_size_write(inode, newsize);
+
+ /* allocate enough contiguous pages to be able to satisfy the
+ * request */
+ pages = alloc_pages(mapping_gfp_mask(inode->i_mapping), order);
+ if (!pages)
+ return -ENOMEM;
+
+ /* split the high-order page into an array of single pages */
+ xpages = 1UL << order;
+ npages = (newsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ for (loop = 0; loop < npages; loop++)
+ set_page_count(pages + loop, 1);
+
+ /* trim off any pages we don't actually require */
+ for (loop = npages; loop < xpages; loop++)
+ __free_page(pages + loop);
+
+ /* clear the memory we allocated */
+ newsize = PAGE_SIZE * npages;
+ data = page_address(pages);
+ memset(data, 0, newsize);
+
+ /* attach all the pages to the inode's address space */
+ pagevec_init(&lru_pvec, 0);
+ for (loop = 0; loop < npages; loop++) {
+ struct page *page = pages + loop;
+
+ ret = add_to_page_cache(page, inode->i_mapping, loop, GFP_KERNEL);
+ if (ret < 0)
+ goto add_error;
+
+ if (!pagevec_add(&lru_pvec, page))
+ __pagevec_lru_add(&lru_pvec);
+
+ unlock_page(page);
+ }
+
+ pagevec_lru_add(&lru_pvec);
+ return 0;
+
+ fsize_exceeded:
+ send_sig(SIGXFSZ, current, 0);
+ too_big:
+ return -EFBIG;
+
+ add_error:
+ page_cache_release(pages + loop);
+ for (loop++; loop < npages; loop++)
+ __free_page(pages + loop);
+ return ret;
+}
+
+/*****************************************************************************/
+/*
+ * check that file shrinkage doesn't leave any VMAs dangling in midair
+ */
+static int ramfs_nommu_check_mappings(struct inode *inode,
+ size_t newsize, size_t size)
+{
+ struct vm_area_struct *vma;
+ struct prio_tree_iter iter;
+
+ /* search for VMAs that fall within the dead zone */
+ vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap,
+ newsize >> PAGE_SHIFT,
+ (size + PAGE_SIZE - 1) >> PAGE_SHIFT
+ ) {
+ /* found one - only interested if it's shared out of the page
+ * cache */
+ if (vma->vm_flags & VM_SHARED)
+ return -ETXTBSY; /* not quite true, but near enough */
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/*
+ *
+ */
+static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size)
+{
+ int ret;
+
+ /* assume a truncate from zero size is going to be for the purposes of
+ * shared mmap */
+ if (size == 0) {
+ if (unlikely(newsize >> 32))
+ return -EFBIG;
+
+ return ramfs_nommu_expand_for_mapping(inode, newsize);
+ }
+
+ /* check that a decrease in size doesn't cut off any shared mappings */
+ if (newsize < size) {
+ ret = ramfs_nommu_check_mappings(inode, newsize, size);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = vmtruncate(inode, size);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/*
+ * handle a change of attributes
+ * - we're specifically interested in a change of size
+ */
+static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
+{
+ struct inode *inode = dentry->d_inode;
+ unsigned int old_ia_valid = ia->ia_valid;
+ int ret = 0;
+
+ /* by providing our own setattr() method, we skip this quotaism */
+ if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) ||
+ (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid))
+ ret = DQUOT_TRANSFER(inode, ia) ? -EDQUOT : 0;
+
+ /* pick out size-changing events */
+ if (ia->ia_valid & ATTR_SIZE) {
+ loff_t size = i_size_read(inode);
+ if (ia->ia_size != size) {
+ ret = ramfs_nommu_resize(inode, ia->ia_size, size);
+ if (ret < 0 || ia->ia_valid == ATTR_SIZE)
+ goto out;
+ } else {
+ /* we skipped the truncate but must still update
+ * timestamps
+ */
+ ia->ia_valid |= ATTR_MTIME|ATTR_CTIME;
+ }
+ }
+
+ ret = inode_setattr(inode, ia);
+ out:
+ ia->ia_valid = old_ia_valid;
+ return ret;
+}
+
+/*****************************************************************************/
+/*
+ * try to determine where a shared mapping can be made
+ * - we require that:
+ * - the pages to be mapped must exist
+ * - the pages be physically contiguous in sequence
+ */
+unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
+ unsigned long addr, unsigned long len,
+ unsigned long pgoff, unsigned long flags)
+{
+ unsigned long maxpages, lpages, nr, loop, ret;
+ struct inode *inode = file->f_dentry->d_inode;
+ struct page **pages = NULL, **ptr, *page;
+ loff_t isize;
+
+ if (!(flags & MAP_SHARED))
+ return addr;
+
+ /* the mapping mustn't extend beyond the EOF */
+ lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ isize = i_size_read(inode);
+
+ ret = -EINVAL;
+ maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (pgoff >= maxpages)
+ goto out;
+
+ if (maxpages - pgoff < lpages)
+ goto out;
+
+ /* gang-find the pages */
+ ret = -ENOMEM;
+ pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ goto out;
+
+ nr = find_get_pages(inode->i_mapping, pgoff, lpages, pages);
+ if (nr != lpages)
+ goto out; /* leave if some pages were missing */
+
+ /* check the pages for physical adjacency */
+ ptr = pages;
+ page = *ptr++;
+ page++;
+ for (loop = lpages; loop > 1; loop--)
+ if (*ptr++ != page++)
+ goto out;
+
+ /* okay - all conditions fulfilled */
+ ret = (unsigned long) page_address(pages[0]);
+
+ out:
+ if (pages) {
+ ptr = pages;
+ for (loop = lpages; loop > 0; loop--)
+ put_page(*ptr++);
+ kfree(pages);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/*
+ * set up a mapping
+ */
+int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ return 0;
+}
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 0a88917605ae..c66bd5e4c05c 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -34,13 +34,12 @@
#include <linux/ramfs.h>
#include <asm/uaccess.h>
+#include "internal.h"
/* some random number */
#define RAMFS_MAGIC 0x858458f6
static struct super_operations ramfs_ops;
-static struct address_space_operations ramfs_aops;
-static struct inode_operations ramfs_file_inode_operations;
static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
@@ -142,25 +141,6 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char *
return error;
}
-static struct address_space_operations ramfs_aops = {
- .readpage = simple_readpage,
- .prepare_write = simple_prepare_write,
- .commit_write = simple_commit_write
-};
-
-struct file_operations ramfs_file_operations = {
- .read = generic_file_read,
- .write = generic_file_write,
- .mmap = generic_file_mmap,
- .fsync = simple_sync_file,
- .sendfile = generic_file_sendfile,
- .llseek = generic_file_llseek,
-};
-
-static struct inode_operations ramfs_file_inode_operations = {
- .getattr = simple_getattr,
-};
-
static struct inode_operations ramfs_dir_inode_operations = {
.create = ramfs_create,
.lookup = simple_lookup,
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
new file mode 100644
index 000000000000..272c8a7120b0
--- /dev/null
+++ b/fs/ramfs/internal.h
@@ -0,0 +1,15 @@
+/* internal.h: ramfs internal definitions
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+extern struct address_space_operations ramfs_aops;
+extern struct file_operations ramfs_file_operations;
+extern struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/read_write.c b/fs/read_write.c
index a091ee4f430d..3f7a1a62165f 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -14,6 +14,7 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/syscalls.h>
+#include <linux/pagemap.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -32,7 +33,7 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
long long retval;
struct inode *inode = file->f_mapping->host;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
switch (origin) {
case 2:
offset += inode->i_size;
@@ -48,7 +49,7 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
}
retval = offset;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return retval;
}
@@ -182,22 +183,33 @@ bad:
}
#endif
+/*
+ * rw_verify_area doesn't like huge counts. We limit
+ * them to something that fits in "int" so that others
+ * won't have to do range checks all the time.
+ */
+#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
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 > INT_MAX))
+ if (unlikely((ssize_t) count < 0))
goto Einval;
pos = *ppos;
if (unlikely((pos < 0) || (loff_t) (pos + count) < 0))
goto Einval;
inode = file->f_dentry->d_inode;
- if (inode->i_flock && MANDATORY_LOCK(inode))
- return locks_mandatory_area(read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, inode, file, pos, count);
- return 0;
+ if (inode->i_flock && MANDATORY_LOCK(inode)) {
+ int retval = locks_mandatory_area(
+ read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+ inode, file, pos, count);
+ if (retval < 0)
+ return retval;
+ }
+ return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
Einval:
return -EINVAL;
@@ -244,7 +256,8 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
return -EFAULT;
ret = rw_verify_area(READ, file, pos, count);
- if (!ret) {
+ if (ret >= 0) {
+ count = ret;
ret = security_file_permission (file, MAY_READ);
if (!ret) {
if (file->f_op->read)
@@ -295,7 +308,8 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
return -EFAULT;
ret = rw_verify_area(WRITE, file, pos, count);
- if (!ret) {
+ if (ret >= 0) {
+ count = ret;
ret = security_file_permission (file, MAY_WRITE);
if (!ret) {
if (file->f_op->write)
@@ -497,7 +511,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
}
ret = rw_verify_area(type, file, pos, tot_len);
- if (ret)
+ if (ret < 0)
goto out;
ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE);
if (ret)
@@ -653,8 +667,9 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
if (!(in_file->f_mode & FMODE_PREAD))
goto fput_in;
retval = rw_verify_area(READ, in_file, ppos, count);
- if (retval)
+ if (retval < 0)
goto fput_in;
+ count = retval;
retval = security_file_permission (in_file, MAY_READ);
if (retval)
@@ -674,8 +689,9 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
goto fput_out;
out_inode = out_file->f_dentry->d_inode;
retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
- if (retval)
+ if (retval < 0)
goto fput_out;
+ count = retval;
retval = security_file_permission (out_file, MAY_WRITE);
if (retval)
diff --git a/fs/readdir.c b/fs/readdir.c
index b03579bc0210..b6109329b607 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -30,13 +30,13 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf)
if (res)
goto out;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
res = file->f_op->readdir(file, buf, filler);
file_accessed(file);
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out:
return res;
}
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 7892a865b58a..ad6fa964b0e7 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -49,7 +49,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
}
reiserfs_write_lock(inode->i_sb);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
/* freeing preallocation only involves relogging blocks that
* are already in the current transaction. preallocation gets
* freed at the end of each transaction, so it is impossible for
@@ -100,7 +100,7 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
err = reiserfs_truncate_file(inode, 0);
}
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
reiserfs_write_unlock(inode->i_sb);
return err;
}
@@ -1342,7 +1342,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
if (unlikely(!access_ok(VERIFY_READ, buf, count)))
return -EFAULT;
- down(&inode->i_sem); // locks the entire file for just us
+ mutex_lock(&inode->i_mutex); // locks the entire file for just us
pos = *ppos;
@@ -1360,7 +1360,7 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
if (res)
goto out;
- inode_update_time(inode, 1); /* Both mtime and ctime */
+ file_update_time(file);
// Ok, we are done with all the checks.
@@ -1532,12 +1532,12 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t
generic_osync_inode(inode, file->f_mapping,
OSYNC_METADATA | OSYNC_DATA);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
reiserfs_async_progress_wait(inode->i_sb);
return (already_written != 0) ? already_written : res;
out:
- up(&inode->i_sem); // unlock the file on exit.
+ mutex_unlock(&inode->i_mutex); // unlock the file on exit.
return res;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index a5e3a0ddbe53..ffa34b861bdb 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -40,12 +40,12 @@ void reiserfs_delete_inode(struct inode *inode)
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
reiserfs_delete_xattrs(inode);
if (journal_begin(&th, inode->i_sb, jbegin_count)) {
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
goto out;
}
reiserfs_update_inode_transaction(inode);
@@ -59,11 +59,11 @@ void reiserfs_delete_inode(struct inode *inode)
DQUOT_FREE_INODE(inode);
if (journal_end(&th, inode->i_sb, jbegin_count)) {
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
goto out;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
/* check return value from reiserfs_delete_object after
* ending the transaction
@@ -551,7 +551,7 @@ static int convert_tail_for_hole(struct inode *inode,
/* we don't have to make sure the conversion did not happen while
** we were locking the page because anyone that could convert
- ** must first take i_sem.
+ ** must first take i_mutex.
**
** We must fix the tail page for writing because it might have buffers
** that are mapped, but have a block number of 0. This indicates tail
@@ -586,7 +586,7 @@ static inline int _allocate_block(struct reiserfs_transaction_handle *th,
BUG_ON(!th->t_trans_id);
#ifdef REISERFS_PREALLOCATE
- if (!(flags & GET_BLOCK_NO_ISEM)) {
+ if (!(flags & GET_BLOCK_NO_IMUX)) {
return reiserfs_new_unf_blocknrs2(th, inode, allocated_block_nr,
path, block);
}
@@ -2318,7 +2318,7 @@ static int map_block_for_writepage(struct inode *inode,
/* this is where we fill in holes in the file. */
if (use_get_block) {
retval = reiserfs_get_block(inode, block, bh_result,
- GET_BLOCK_CREATE | GET_BLOCK_NO_ISEM
+ GET_BLOCK_CREATE | GET_BLOCK_NO_IMUX
| GET_BLOCK_NO_DANGLE);
if (!retval) {
if (!buffer_mapped(bh_result)
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 81fc00285f60..745c88100895 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -2,6 +2,7 @@
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/reiserfs_fs.h>
#include <linux/time.h>
@@ -120,7 +121,7 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp)
/* we need to make sure nobody is changing the file size beneath
** us
*/
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
write_from = inode->i_size & (blocksize - 1);
/* if we are on a block boundary, we are already unpacked. */
@@ -156,7 +157,7 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp)
page_cache_release(page);
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
reiserfs_write_unlock(inode->i_sb);
return retval;
}
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3f17ef844fb6..4491fcf2a0e6 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -3925,10 +3925,13 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
flush = 1;
}
#ifdef REISERFS_PREALLOCATE
- /* quota ops might need to nest, setup the journal_info pointer for them */
+ /* quota ops might need to nest, setup the journal_info pointer for them
+ * and raise the refcount so that it is > 0. */
current->journal_info = th;
+ th->t_refcount++;
reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into
* the transaction */
+ th->t_refcount--;
current->journal_info = th->t_handle_save;
#endif
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 3549067c42d9..8f8d8d01107c 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -375,11 +375,7 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
return ERR_PTR(-EIO);
}
- if (inode)
- return d_splice_alias(inode, dentry);
-
- d_add(dentry, inode);
- return NULL;
+ return d_splice_alias(inode, dentry);
}
/*
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 42afb5bef111..397d9590c8f2 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -2211,7 +2211,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
size_t towrite = len;
struct buffer_head tmp_bh, *bh;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
while (towrite > 0) {
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
@@ -2250,7 +2250,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
inode->i_version++;
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
mark_inode_dirty(inode);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return len - towrite;
}
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index c92e124f628e..196e971c03c9 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -205,7 +205,7 @@ int indirect2direct(struct reiserfs_transaction_handle *th, struct inode *p_s_in
1) * p_s_sb->s_blocksize;
pos1 = pos;
- // we are protected by i_sem. The tail can not disapper, not
+ // we are protected by i_mutex. The tail can not disapper, not
// append can be done either
// we are in truncate or packing tail in file_release
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 72e120798677..cc061bfd437b 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -30,6 +30,7 @@
*/
#include <linux/reiserfs_fs.h>
+#include <linux/capability.h>
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/errno.h>
@@ -67,11 +68,11 @@ static struct dentry *create_xa_root(struct super_block *sb)
goto out;
} else if (!xaroot->d_inode) {
int err;
- down(&privroot->d_inode->i_sem);
+ mutex_lock(&privroot->d_inode->i_mutex);
err =
privroot->d_inode->i_op->mkdir(privroot->d_inode, xaroot,
0700);
- up(&privroot->d_inode->i_sem);
+ mutex_unlock(&privroot->d_inode->i_mutex);
if (err) {
dput(xaroot);
@@ -115,8 +116,8 @@ static struct dentry *__get_xa_root(struct super_block *s)
}
/* Returns the dentry (or NULL) referring to the root of the extended
- * attribute directory tree. If it has already been retreived, it is used.
- * Otherwise, we attempt to retreive it from disk. It may also return
+ * attribute directory tree. If it has already been retrieved, it is used.
+ * Otherwise, we attempt to retrieve it from disk. It may also return
* a pointer-encoded error.
*/
static inline struct dentry *get_xa_root(struct super_block *s)
@@ -219,7 +220,7 @@ static struct dentry *get_xa_file_dentry(const struct inode *inode,
} else if (flags & XATTR_REPLACE || flags & FL_READONLY) {
goto out;
} else {
- /* inode->i_sem is down, so nothing else can try to create
+ /* inode->i_mutex is down, so nothing else can try to create
* the same xattr */
err = xadir->d_inode->i_op->create(xadir->d_inode, xafile,
0700 | S_IFREG, NULL);
@@ -268,7 +269,7 @@ static struct file *open_xa_file(const struct inode *inode, const char *name,
* and don't mess with f->f_pos, but the idea is the same. Do some
* action on each and every entry in the directory.
*
- * we're called with i_sem held, so there are no worries about the directory
+ * we're called with i_mutex held, so there are no worries about the directory
* changing underneath us.
*/
static int __xattr_readdir(struct file *filp, void *dirent, filldir_t filldir)
@@ -426,7 +427,7 @@ int xattr_readdir(struct file *file, filldir_t filler, void *buf)
int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
goto out;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
// down(&inode->i_zombie);
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
@@ -435,7 +436,7 @@ int xattr_readdir(struct file *file, filldir_t filler, void *buf)
unlock_kernel();
}
// up(&inode->i_zombie);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out:
return res;
}
@@ -480,7 +481,7 @@ static inline __u32 xattr_hash(const char *msg, int len)
/* Generic extended attribute operations that can be used by xa plugins */
/*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
@@ -497,12 +498,6 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
struct iattr newattrs;
__u32 xahash = 0;
- if (IS_RDONLY(inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
- return -EPERM;
-
if (get_inode_sd_version(inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
@@ -535,7 +530,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
/* Resize it so we're ok to write there */
newattrs.ia_size = buffer_size;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- down(&xinode->i_sem);
+ mutex_lock(&xinode->i_mutex);
err = notify_change(fp->f_dentry, &newattrs);
if (err)
goto out_filp;
@@ -598,7 +593,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
}
out_filp:
- up(&xinode->i_sem);
+ mutex_unlock(&xinode->i_mutex);
fput(fp);
out:
@@ -606,7 +601,7 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer,
}
/*
- * inode->i_sem: down
+ * inode->i_mutex: down
*/
int
reiserfs_xattr_get(const struct inode *inode, const char *name, void *buffer,
@@ -758,9 +753,6 @@ int reiserfs_xattr_del(struct inode *inode, const char *name)
struct dentry *dir;
int err;
- if (IS_RDONLY(inode))
- return -EROFS;
-
dir = open_xa_dir(inode, FL_READONLY);
if (IS_ERR(dir)) {
err = PTR_ERR(dir);
@@ -793,7 +785,7 @@ reiserfs_delete_xattrs_filler(void *buf, const char *name, int namelen,
}
-/* This is called w/ inode->i_sem downed */
+/* This is called w/ inode->i_mutex downed */
int reiserfs_delete_xattrs(struct inode *inode)
{
struct file *fp;
@@ -946,7 +938,7 @@ int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs)
/*
* Inode operation getxattr()
- * Preliminary locking: we down dentry->d_inode->i_sem
+ * Preliminary locking: we down dentry->d_inode->i_mutex
*/
ssize_t
reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
@@ -970,7 +962,7 @@ reiserfs_getxattr(struct dentry * dentry, const char *name, void *buffer,
/*
* Inode operation setxattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_mutex down
*/
int
reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
@@ -984,12 +976,6 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- if (IS_RDONLY(dentry->d_inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
- return -EROFS;
-
reiserfs_write_lock_xattr_i(dentry->d_inode);
lock = !has_xattr_dir(dentry->d_inode);
if (lock)
@@ -1008,7 +994,7 @@ reiserfs_setxattr(struct dentry *dentry, const char *name, const void *value,
/*
* Inode operation removexattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_mutex down
*/
int reiserfs_removexattr(struct dentry *dentry, const char *name)
{
@@ -1019,12 +1005,6 @@ int reiserfs_removexattr(struct dentry *dentry, const char *name)
get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1)
return -EOPNOTSUPP;
- if (IS_RDONLY(dentry->d_inode))
- return -EROFS;
-
- if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode))
- return -EPERM;
-
reiserfs_write_lock_xattr_i(dentry->d_inode);
reiserfs_read_lock_xattrs(dentry->d_sb);
@@ -1091,7 +1071,7 @@ reiserfs_listxattr_filler(void *buf, const char *name, int namelen,
/*
* Inode operation listxattr()
*
- * Preliminary locking: we down dentry->d_inode->i_sem
+ * Preliminary locking: we down dentry->d_inode->i_mutex
*/
ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size)
{
@@ -1289,9 +1269,9 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
if (!IS_ERR(dentry)) {
if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) {
struct inode *inode = dentry->d_parent->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
err = inode->i_op->mkdir(inode, dentry, 0700);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (err) {
dput(dentry);
dentry = NULL;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index a47ac9aac8b2..43de3ba83332 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -1,3 +1,4 @@
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/posix_acl.h>
#include <linux/reiserfs_fs.h>
@@ -174,7 +175,7 @@ static void *posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
/*
* Inode operation get_posix_acl().
*
- * inode->i_sem: down
+ * inode->i_mutex: down
* BKL held [before 2.5.x]
*/
struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
@@ -237,7 +238,7 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
/*
* Inode operation set_posix_acl().
*
- * inode->i_sem: down
+ * inode->i_mutex: down
* BKL held [before 2.5.x]
*/
static int
@@ -312,7 +313,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return error;
}
-/* dir->i_sem: down,
+/* dir->i_mutex: locked,
* inode is new and not released into the wild yet */
int
reiserfs_inherit_default_acl(struct inode *dir, struct dentry *dentry,
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index 2501f7e66ab9..024a938ca60f 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -1,4 +1,5 @@
#include <linux/reiserfs_fs.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 51458048ca66..073f39364b11 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -16,18 +16,10 @@ static int
user_get(struct inode *inode, const char *name, void *buffer, size_t size)
{
- int error;
-
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
-
if (!reiserfs_xattrs_user(inode->i_sb))
return -EOPNOTSUPP;
-
- error = reiserfs_permission_locked(inode, MAY_READ, NULL);
- if (error)
- return error;
-
return reiserfs_xattr_get(inode, name, buffer, size);
}
@@ -36,43 +28,21 @@ user_set(struct inode *inode, const char *name, const void *buffer,
size_t size, int flags)
{
- int error;
-
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
if (!reiserfs_xattrs_user(inode->i_sb))
return -EOPNOTSUPP;
-
- if (!S_ISREG(inode->i_mode) &&
- (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
- return -EPERM;
-
- error = reiserfs_permission_locked(inode, MAY_WRITE, NULL);
- if (error)
- return error;
-
return reiserfs_xattr_set(inode, name, buffer, size, flags);
}
static int user_del(struct inode *inode, const char *name)
{
- int error;
-
if (strlen(name) < sizeof(XATTR_USER_PREFIX))
return -EINVAL;
if (!reiserfs_xattrs_user(inode->i_sb))
return -EOPNOTSUPP;
-
- if (!S_ISREG(inode->i_mode) &&
- (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
- return -EPERM;
-
- error = reiserfs_permission_locked(inode, MAY_WRITE, NULL);
- if (error)
- return error;
-
return 0;
}
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
index 84e21ffa5ca8..10187812771e 100644
--- a/fs/relayfs/buffers.c
+++ b/fs/relayfs/buffers.c
@@ -185,5 +185,6 @@ void relay_destroy_buf(struct rchan_buf *buf)
void relay_remove_buf(struct kref *kref)
{
struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
- relayfs_remove(buf->dentry);
+ buf->chan->cb->remove_buf_file(buf->dentry);
+ relay_destroy_buf(buf);
}
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
index 0f7f88d067ad..383523011aad 100644
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -26,31 +26,22 @@
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)
+static struct inode *relayfs_get_inode(struct super_block *sb,
+ int mode,
+ struct file_operations *fops,
+ void *data)
{
- 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);
+ if (!inode)
return NULL;
- }
inode->i_mode = mode;
inode->i_uid = 0;
@@ -61,8 +52,9 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
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;
+ inode->i_fop = fops;
+ if (data)
+ inode->u.generic_ip = data;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
@@ -83,7 +75,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
* @name: the name of the file to create
* @parent: parent directory
* @mode: mode
- * @chan: relay channel associated with the file
+ * @fops: file operations to use for the file
+ * @data: user-associated data for this file
*
* Returns the new dentry, NULL on failure
*
@@ -92,7 +85,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
static struct dentry *relayfs_create_entry(const char *name,
struct dentry *parent,
int mode,
- struct rchan *chan)
+ struct file_operations *fops,
+ void *data)
{
struct dentry *d;
struct inode *inode;
@@ -115,7 +109,7 @@ static struct dentry *relayfs_create_entry(const char *name,
}
parent = dget(parent);
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
d = lookup_one_len(name, parent, strlen(name));
if (IS_ERR(d)) {
d = NULL;
@@ -127,7 +121,7 @@ static struct dentry *relayfs_create_entry(const char *name,
goto release_mount;
}
- inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan);
+ inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data);
if (!inode) {
d = NULL;
goto release_mount;
@@ -145,7 +139,7 @@ release_mount:
simple_release_fs(&relayfs_mount, &relayfs_mount_count);
exit:
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
dput(parent);
return d;
}
@@ -155,20 +149,26 @@ exit:
* @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
+ * @fops: file operations to use for the file
+ * @data: user-associated data for this 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)
+struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct file_operations *fops,
+ void *data)
{
+ BUG_ON(!fops);
+
if (!mode)
mode = S_IRUSR;
mode = (mode & S_IALLUGO) | S_IFREG;
- return relayfs_create_entry(name, parent, mode, chan);
+ return relayfs_create_entry(name, parent, mode, fops, data);
}
/**
@@ -183,7 +183,7 @@ struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
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);
+ return relayfs_create_entry(name, parent, mode, NULL, NULL);
}
/**
@@ -204,7 +204,7 @@ int relayfs_remove(struct dentry *dentry)
return -EINVAL;
parent = dget(parent);
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
if (dentry->d_inode) {
if (S_ISDIR(dentry->d_inode->i_mode))
error = simple_rmdir(parent->d_inode, dentry);
@@ -215,7 +215,7 @@ int relayfs_remove(struct dentry *dentry)
}
if (!error)
dput(dentry);
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
dput(parent);
if (!error)
@@ -225,6 +225,17 @@ int relayfs_remove(struct dentry *dentry)
}
/**
+ * relayfs_remove_file - remove a file from relay filesystem
+ * @dentry: directory dentry
+ *
+ * Returns 0 if successful, negative otherwise.
+ */
+int relayfs_remove_file(struct dentry *dentry)
+{
+ return relayfs_remove(dentry);
+}
+
+/**
* relayfs_remove_dir - remove a directory in the relay filesystem
* @dentry: directory dentry
*
@@ -236,45 +247,45 @@ int relayfs_remove_dir(struct dentry *dentry)
}
/**
- * relayfs_open - open file op for relayfs files
+ * relay_file_open - open file op for relay files
* @inode: the inode
* @filp: the file
*
* Increments the channel buffer refcount.
*/
-static int relayfs_open(struct inode *inode, struct file *filp)
+static int relay_file_open(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = inode->u.generic_ip;
kref_get(&buf->kref);
+ filp->private_data = buf;
return 0;
}
/**
- * relayfs_mmap - mmap file op for relayfs files
+ * relay_file_mmap - mmap file op for relay 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)
+static int relay_file_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);
+ struct rchan_buf *buf = filp->private_data;
+ return relay_mmap_buf(buf, vma);
}
/**
- * relayfs_poll - poll file op for relayfs files
+ * relay_file_poll - poll file op for relay files
* @filp: the file
* @wait: poll table
*
* Poll implemention.
*/
-static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
+static unsigned int relay_file_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;
+ struct rchan_buf *buf = filp->private_data;
if (buf->finalized)
return POLLERR;
@@ -289,27 +300,27 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
}
/**
- * relayfs_release - release file op for relayfs files
+ * relay_file_release - release file op for relay 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)
+static int relay_file_release(struct inode *inode, struct file *filp)
{
- struct rchan_buf *buf = RELAYFS_I(inode)->buf;
+ struct rchan_buf *buf = filp->private_data;
kref_put(&buf->kref, relay_remove_buf);
return 0;
}
/**
- * relayfs_read_consume - update the consumed count for the buffer
+ * relay_file_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)
+static void relay_file_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;
@@ -332,9 +343,9 @@ static void relayfs_read_consume(struct rchan_buf *buf,
}
/**
- * relayfs_read_avail - boolean, are there unconsumed bytes available?
+ * relay_file_read_avail - boolean, are there unconsumed bytes available?
*/
-static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
+static int relay_file_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;
@@ -365,16 +376,16 @@ static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
if (bytes_produced == bytes_consumed)
return 0;
- relayfs_read_consume(buf, read_pos, 0);
+ relay_file_read_consume(buf, read_pos, 0);
return 1;
}
/**
- * relayfs_read_subbuf_avail - return bytes available in sub-buffer
+ * relay_file_read_subbuf_avail - return bytes available in sub-buffer
*/
-static size_t relayfs_read_subbuf_avail(size_t read_pos,
- struct rchan_buf *buf)
+static size_t relay_file_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;
@@ -396,14 +407,14 @@ static size_t relayfs_read_subbuf_avail(size_t read_pos,
}
/**
- * relayfs_read_start_pos - find the first available byte to read
+ * relay_file_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)
+static size_t relay_file_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;
@@ -422,11 +433,11 @@ static size_t relayfs_read_start_pos(size_t read_pos,
}
/**
- * relayfs_read_end_pos - return the new read position
+ * relay_file_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)
+static size_t relay_file_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;
@@ -445,7 +456,7 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf,
}
/**
- * relayfs_read - read file op for relayfs files
+ * relay_file_read - read file op for relay files
* @filp: the file
* @buffer: the userspace buffer
* @count: number of bytes to read
@@ -454,23 +465,23 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf,
* 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)
+static ssize_t relay_file_read(struct file *filp,
+ char __user *buffer,
+ size_t count,
+ loff_t *ppos)
{
+ struct rchan_buf *buf = filp->private_data;
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))
+ mutex_lock(&inode->i_mutex);
+ if(!relay_file_read_avail(buf, *ppos))
goto out;
- read_start = relayfs_read_start_pos(*ppos, buf);
- avail = relayfs_read_subbuf_avail(read_start, buf);
+ read_start = relay_file_read_start_pos(*ppos, buf);
+ avail = relay_file_read_subbuf_avail(read_start, buf);
if (!avail)
goto out;
@@ -480,58 +491,25 @@ static ssize_t relayfs_read(struct file *filp,
ret = -EFAULT;
goto out;
}
- relayfs_read_consume(buf, read_start, count);
- *ppos = relayfs_read_end_pos(buf, read_start, count);
+ relay_file_read_consume(buf, read_start, count);
+ *ppos = relay_file_read_end_pos(buf, read_start, count);
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
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,
+struct file_operations relay_file_operations = {
+ .open = relay_file_open,
+ .poll = relay_file_poll,
+ .mmap = relay_file_mmap,
+ .read = relay_file_read,
.llseek = no_llseek,
- .release = relayfs_release,
+ .release = relay_file_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)
@@ -544,7 +522,7 @@ static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = RELAYFS_MAGIC;
sb->s_op = &relayfs_ops;
- inode = relayfs_get_inode(sb, mode, NULL);
+ inode = relayfs_get_inode(sb, mode, NULL, NULL);
if (!inode)
return -ENOMEM;
@@ -575,33 +553,27 @@ static struct file_system_type relayfs_fs_type = {
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;
+ return register_filesystem(&relayfs_fs_type);
}
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(relay_file_operations);
EXPORT_SYMBOL_GPL(relayfs_create_dir);
EXPORT_SYMBOL_GPL(relayfs_remove_dir);
+EXPORT_SYMBOL_GPL(relayfs_create_file);
+EXPORT_SYMBOL_GPL(relayfs_remove_file);
MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
MODULE_DESCRIPTION("Relay Filesystem");
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index 2a6f7f12b7f9..abf3ceaace49 100644
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -80,11 +80,34 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf,
{
}
+/*
+ * create_buf_file_create() default callback. Creates file to represent buf.
+ */
+static struct dentry *create_buf_file_default_callback(const char *filename,
+ struct dentry *parent,
+ int mode,
+ struct rchan_buf *buf,
+ int *is_global)
+{
+ return relayfs_create_file(filename, parent, mode,
+ &relay_file_operations, buf);
+}
+
+/*
+ * remove_buf_file() default callback. Removes file representing relay buffer.
+ */
+static int remove_buf_file_default_callback(struct dentry *dentry)
+{
+ return relayfs_remove(dentry);
+}
+
/* 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,
+ .create_buf_file = create_buf_file_default_callback,
+ .remove_buf_file = remove_buf_file_default_callback,
};
/**
@@ -148,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
void relay_reset(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;
if (!chan)
return;
for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
__relay_reset(chan->buf[i], 0);
+ prev = chan->buf[i];
}
}
@@ -166,17 +191,27 @@ void relay_reset(struct rchan *chan)
*/
static struct rchan_buf *relay_open_buf(struct rchan *chan,
const char *filename,
- struct dentry *parent)
+ struct dentry *parent,
+ int *is_global)
{
struct rchan_buf *buf;
struct dentry *dentry;
+ if (*is_global)
+ return chan->buf[0];
+
+ buf = relay_create_buf(chan);
+ if (!buf)
+ return NULL;
+
/* Create file in fs */
- dentry = relayfs_create_file(filename, parent, S_IRUSR, chan);
- if (!dentry)
+ dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
+ buf, is_global);
+ if (!dentry) {
+ relay_destroy_buf(buf);
return NULL;
+ }
- buf = RELAYFS_I(dentry->d_inode)->buf;
buf->dentry = dentry;
__relay_reset(buf, 1);
@@ -214,6 +249,10 @@ static inline void setup_callbacks(struct rchan *chan,
cb->buf_mapped = buf_mapped_default_callback;
if (!cb->buf_unmapped)
cb->buf_unmapped = buf_unmapped_default_callback;
+ if (!cb->create_buf_file)
+ cb->create_buf_file = create_buf_file_default_callback;
+ if (!cb->remove_buf_file)
+ cb->remove_buf_file = remove_buf_file_default_callback;
chan->cb = cb;
}
@@ -241,6 +280,7 @@ struct rchan *relay_open(const char *base_filename,
unsigned int i;
struct rchan *chan;
char *tmpname;
+ int is_global = 0;
if (!base_filename)
return NULL;
@@ -265,7 +305,8 @@ struct rchan *relay_open(const char *base_filename,
for_each_online_cpu(i) {
sprintf(tmpname, "%s%d", base_filename, i);
- chan->buf[i] = relay_open_buf(chan, tmpname, parent);
+ chan->buf[i] = relay_open_buf(chan, tmpname, parent,
+ &is_global);
chan->buf[i]->cpu = i;
if (!chan->buf[i])
goto free_bufs;
@@ -279,6 +320,8 @@ free_bufs:
if (!chan->buf[i])
break;
relay_close_buf(chan->buf[i]);
+ if (is_global)
+ break;
}
kfree(tmpname);
@@ -388,14 +431,16 @@ void relay_destroy_channel(struct kref *kref)
void relay_close(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;
if (!chan)
return;
for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
relay_close_buf(chan->buf[i]);
+ prev = chan->buf[i];
}
if (chan->last_toobig)
@@ -415,14 +460,16 @@ void relay_close(struct rchan *chan)
void relay_flush(struct rchan *chan)
{
unsigned int i;
+ struct rchan_buf *prev = NULL;
if (!chan)
return;
for (i = 0; i < NR_CPUS; i++) {
- if (!chan->buf[i])
- continue;
+ if (!chan->buf[i] || chan->buf[i] == prev)
+ break;
relay_switch_subbuf(chan->buf[i], 0);
+ prev = chan->buf[i];
}
}
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
index 703503fa22b6..0993d3e5753b 100644
--- a/fs/relayfs/relay.h
+++ b/fs/relayfs/relay.h
@@ -1,10 +1,6 @@
#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);
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index c74f382dabba..0a13859fd57b 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -418,7 +418,7 @@ static int
romfs_readpage(struct file *file, struct page * page)
{
struct inode *inode = page->mapping->host;
- unsigned long offset, avail, readlen;
+ loff_t offset, avail, readlen;
void *buf;
int result = -EIO;
@@ -429,8 +429,8 @@ romfs_readpage(struct file *file, struct page * page)
goto err_out;
/* 32 bit warning -- but not for us :) */
- offset = page->index << PAGE_CACHE_SHIFT;
- if (offset < inode->i_size) {
+ offset = page_offset(page);
+ if (offset < i_size_read(inode)) {
avail = inode->i_size-offset;
readlen = min_t(unsigned long, avail, PAGE_SIZE);
if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) {
diff --git a/fs/select.c b/fs/select.c
index f10a10317d54..c0f02d36c60e 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -179,12 +179,11 @@ get_max:
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
-int do_select(int n, fd_set_bits *fds, long *timeout)
+int do_select(int n, fd_set_bits *fds, s64 *timeout)
{
struct poll_wqueues table;
poll_table *wait;
int retval, i;
- long __timeout = *timeout;
rcu_read_lock();
retval = max_select_fd(n, fds);
@@ -196,11 +195,12 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
poll_initwait(&table);
wait = &table.pt;
- if (!__timeout)
+ if (!*timeout)
wait = NULL;
retval = 0;
for (;;) {
unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;
+ long __timeout;
set_current_state(TASK_INTERRUPTIBLE);
@@ -255,22 +255,32 @@ int do_select(int n, fd_set_bits *fds, long *timeout)
*rexp = res_ex;
}
wait = NULL;
- if (retval || !__timeout || signal_pending(current))
+ if (retval || !*timeout || signal_pending(current))
break;
if(table.error) {
retval = table.error;
break;
}
+
+ if (*timeout < 0) {
+ /* Wait indefinitely */
+ __timeout = MAX_SCHEDULE_TIMEOUT;
+ } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT - 1)) {
+ /* Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in a loop */
+ __timeout = MAX_SCHEDULE_TIMEOUT - 1;
+ *timeout -= __timeout;
+ } else {
+ __timeout = *timeout;
+ *timeout = 0;
+ }
__timeout = schedule_timeout(__timeout);
+ if (*timeout >= 0)
+ *timeout += __timeout;
}
__set_current_state(TASK_RUNNING);
poll_freewait(&table);
- /*
- * Up-to-date the caller timeout.
- */
- *timeout = __timeout;
return retval;
}
@@ -295,36 +305,14 @@ static void select_bits_free(void *bits, int size)
#define MAX_SELECT_SECONDS \
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-asmlinkage long
-sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp)
+static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, s64 *timeout)
{
fd_set_bits fds;
char *bits;
- long timeout;
int ret, size, max_fdset;
struct fdtable *fdt;
- timeout = MAX_SCHEDULE_TIMEOUT;
- if (tvp) {
- time_t sec, usec;
-
- if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
- || __get_user(sec, &tvp->tv_sec)
- || __get_user(usec, &tvp->tv_usec)) {
- ret = -EFAULT;
- goto out_nofds;
- }
-
- ret = -EINVAL;
- if (sec < 0 || usec < 0)
- goto out_nofds;
-
- if ((unsigned long) sec < MAX_SELECT_SECONDS) {
- timeout = ROUND_UP(usec, 1000000/HZ);
- timeout += sec * (unsigned long) HZ;
- }
- }
-
ret = -EINVAL;
if (n < 0)
goto out_nofds;
@@ -362,18 +350,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
zero_fd_set(n, fds.res_out);
zero_fd_set(n, fds.res_ex);
- ret = do_select(n, &fds, &timeout);
-
- if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
- time_t sec = 0, usec = 0;
- if (timeout) {
- sec = timeout / HZ;
- usec = timeout % HZ;
- usec *= (1000000/HZ);
- }
- put_user(sec, &tvp->tv_sec);
- put_user(usec, &tvp->tv_usec);
- }
+ ret = do_select(n, &fds, timeout);
if (ret < 0)
goto out;
@@ -395,6 +372,154 @@ out_nofds:
return ret;
}
+asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timeval __user *tvp)
+{
+ s64 timeout = -1;
+ struct timeval tv;
+ int ret;
+
+ if (tvp) {
+ if (copy_from_user(&tv, tvp, sizeof(tv)))
+ return -EFAULT;
+
+ if (tv.tv_sec < 0 || tv.tv_usec < 0)
+ return -EINVAL;
+
+ /* Cast to u64 to make GCC stop complaining */
+ if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(tv.tv_usec, USEC_PER_SEC/HZ);
+ timeout += tv.tv_sec * HZ;
+ }
+ }
+
+ ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tvp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ tv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
+ tv.tv_sec = timeout;
+ if (copy_to_user(tvp, &tv, sizeof(tv))) {
+sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timespec __user *tsp,
+ const sigset_t __user *sigmask, size_t sigsetsize)
+{
+ s64 timeout = MAX_SCHEDULE_TIMEOUT;
+ sigset_t ksigmask, sigsaved;
+ struct timespec ts;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0)
+ return -EINVAL;
+
+ /* Cast to u64 to make GCC stop complaining */
+ if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+ }
+
+ if (sigmask) {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = core_sys_select(n, inp, outp, exp, &timeout);
+
+ if (tsp) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND)
+ ret = -EINTR;
+ }
+ }
+
+ if (ret == -ERESTARTNOHAND) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ return ret;
+}
+
+/*
+ * Most architectures can't handle 7-argument syscalls. So we provide a
+ * 6-argument version where the sixth argument is a pointer to a structure
+ * which has a pointer to the sigset_t itself followed by a size_t containing
+ * the sigset size.
+ */
+asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
+ fd_set __user *exp, struct timespec __user *tsp, void __user *sig)
+{
+ size_t sigsetsize = 0;
+ sigset_t __user *up = NULL;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
+ || __get_user(up, (sigset_t * __user *)sig)
+ || __get_user(sigsetsize,
+ (size_t * __user)(sig+sizeof(void *))))
+ return -EFAULT;
+ }
+
+ return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
+}
+#endif /* TIF_RESTORE_SIGMASK */
+
struct poll_list {
struct poll_list *next;
int len;
@@ -436,16 +561,19 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage,
}
static int do_poll(unsigned int nfds, struct poll_list *list,
- struct poll_wqueues *wait, long timeout)
+ struct poll_wqueues *wait, s64 *timeout)
{
int count = 0;
poll_table* pt = &wait->pt;
- if (!timeout)
+ /* Optimise the no-wait case */
+ if (!(*timeout))
pt = NULL;
for (;;) {
struct poll_list *walk;
+ long __timeout;
+
set_current_state(TASK_INTERRUPTIBLE);
walk = list;
while(walk != NULL) {
@@ -453,18 +581,36 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
walk = walk->next;
}
pt = NULL;
- if (count || !timeout || signal_pending(current))
+ if (count || !*timeout || signal_pending(current))
break;
count = wait->error;
if (count)
break;
- timeout = schedule_timeout(timeout);
+
+ if (*timeout < 0) {
+ /* Wait indefinitely */
+ __timeout = MAX_SCHEDULE_TIMEOUT;
+ } else if (unlikely(*timeout >= (s64)MAX_SCHEDULE_TIMEOUT-1)) {
+ /*
+ * Wait for longer than MAX_SCHEDULE_TIMEOUT. Do it in
+ * a loop
+ */
+ __timeout = MAX_SCHEDULE_TIMEOUT - 1;
+ *timeout -= __timeout;
+ } else {
+ __timeout = *timeout;
+ *timeout = 0;
+ }
+
+ __timeout = schedule_timeout(__timeout);
+ if (*timeout >= 0)
+ *timeout += __timeout;
}
__set_current_state(TASK_RUNNING);
return count;
}
-asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout)
+int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout)
{
struct poll_wqueues table;
int fdcount, err;
@@ -482,14 +628,6 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
if (nfds > max_fdset && nfds > OPEN_MAX)
return -EINVAL;
- if (timeout) {
- /* Careful about overflow in the intermediate values */
- if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
- timeout = (unsigned long)(timeout*HZ+999)/1000+1;
- else /* Negative or overflow */
- timeout = MAX_SCHEDULE_TIMEOUT;
- }
-
poll_initwait(&table);
head = NULL;
@@ -519,6 +657,7 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti
}
i -= pp->len;
}
+
fdcount = do_poll(nfds, head, &table, timeout);
/* OK, now copy the revents fields back to user space. */
@@ -547,3 +686,98 @@ out_fds:
poll_freewait(&table);
return err;
}
+
+asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
+ long timeout_msecs)
+{
+ s64 timeout_jiffies = 0;
+
+ if (timeout_msecs) {
+#if HZ > 1000
+ /* We can only overflow if HZ > 1000 */
+ if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ)
+ timeout_jiffies = -1;
+ else
+#endif
+ timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+ }
+
+ return do_sys_poll(ufds, nfds, &timeout_jiffies);
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+ struct timespec __user *tsp, const sigset_t __user *sigmask,
+ size_t sigsetsize)
+{
+ sigset_t ksigmask, sigsaved;
+ struct timespec ts;
+ s64 timeout = -1;
+ int ret;
+
+ if (tsp) {
+ if (copy_from_user(&ts, tsp, sizeof(ts)))
+ return -EFAULT;
+
+ /* Cast to u64 to make GCC stop complaining */
+ if ((u64)ts.tv_sec >= (u64)MAX_INT64_SECONDS)
+ timeout = -1; /* infinite */
+ else {
+ timeout = ROUND_UP(ts.tv_nsec, NSEC_PER_SEC/HZ);
+ timeout += ts.tv_sec * HZ;
+ }
+ }
+
+ if (sigmask) {
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ ret = do_sys_poll(ufds, nfds, &timeout);
+
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR) {
+ /*
+ * Don't restore the signal mask yet. Let do_signal() deliver
+ * the signal on the way back to userspace, before the signal
+ * mask is restored.
+ */
+ if (sigmask) {
+ memcpy(&current->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ ret = -ERESTARTNOHAND;
+ } else if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+
+ if (tsp && timeout >= 0) {
+ if (current->personality & STICKY_TIMEOUTS)
+ goto sticky;
+ /* Yes, we know it's actually an s64, but it's also positive. */
+ ts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) * 1000;
+ ts.tv_sec = timeout;
+ if (copy_to_user(tsp, &ts, sizeof(ts))) {
+ sticky:
+ /*
+ * If an application puts its timeval in read-only
+ * memory, we don't want the Linux-specific update to
+ * the timeval to cause a fault after the select has
+ * completed successfully. However, because we're not
+ * updating the timeval, we can't restart the system
+ * call.
+ */
+ if (ret == -ERESTARTNOHAND && timeout >= 0)
+ ret = -EINTR;
+ }
+ }
+
+ return ret;
+}
+#endif /* TIF_RESTORE_SIGMASK */
diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile
index 93246b7dd6fb..6673ee82cb4c 100644
--- a/fs/smbfs/Makefile
+++ b/fs/smbfs/Makefile
@@ -13,7 +13,6 @@ smbfs-objs := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \
EXTRA_CFLAGS += -DSMBFS_PARANOIA
#EXTRA_CFLAGS += -DSMBFS_DEBUG
#EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE
-#EXTRA_CFLAGS += -DDEBUG_SMB_MALLOC
#EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP
#EXTRA_CFLAGS += -Werror
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index f3e6b81288ab..74b86d9725a6 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -66,7 +66,7 @@ smb_invalidate_dircache_entries(struct dentry *parent)
spin_lock(&dcache_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dentry = list_entry(next, struct dentry, d_child);
+ dentry = list_entry(next, struct dentry, d_u.d_child);
dentry->d_fsdata = NULL;
smb_age_dentry(server, dentry);
next = next->next;
@@ -100,7 +100,7 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
spin_lock(&dcache_lock);
next = parent->d_subdirs.next;
while (next != &parent->d_subdirs) {
- dent = list_entry(next, struct dentry, d_child);
+ dent = list_entry(next, struct dentry, d_u.d_child);
if ((unsigned long)dent->d_fsdata == fpos) {
if (dent->d_inode)
dget_locked(dent);
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index b4fcfa8b55a1..7042e62726a4 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -209,8 +209,8 @@ smb_updatepage(struct file *file, struct page *page, unsigned long offset,
{
struct dentry *dentry = file->f_dentry;
- DEBUG1("(%s/%s %d@%ld)\n", DENTRY_PATH(dentry),
- count, (page->index << PAGE_CACHE_SHIFT)+offset);
+ DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
+ ((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
return smb_writepage_sync(dentry->d_inode, page, offset, count);
}
@@ -374,8 +374,7 @@ smb_file_release(struct inode *inode, struct file * file)
/* We must flush any dirty pages now as we won't be able to
write anything after close. mmap can trigger this.
"openers" should perhaps include mmap'ers ... */
- filemap_fdatawrite(inode->i_mapping);
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
smb_close(inode);
}
unlock_kernel();
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index 10b994428fef..02e3e82d465c 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -487,11 +487,11 @@ smb_put_super(struct super_block *sb)
if (server->conn_pid)
kill_proc(server->conn_pid, SIGTERM, 1);
- smb_kfree(server->ops);
+ kfree(server->ops);
smb_unload_nls(server);
sb->s_fs_info = NULL;
smb_unlock_server(server);
- smb_kfree(server);
+ kfree(server);
}
static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
@@ -519,11 +519,10 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
sb->s_op = &smb_sops;
sb->s_time_gran = 100;
- server = smb_kmalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
+ server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
if (!server)
goto out_no_server;
sb->s_fs_info = server;
- memset(server, 0, sizeof(struct smb_sb_info));
server->super_block = sb;
server->mnt = NULL;
@@ -542,8 +541,8 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
/* FIXME: move these to the smb_sb_info struct */
VERBOSE("alloc chunk = %d\n", sizeof(struct smb_ops) +
sizeof(struct smb_mount_data_kernel));
- mem = smb_kmalloc(sizeof(struct smb_ops) +
- sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
+ mem = kmalloc(sizeof(struct smb_ops) +
+ sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
if (!mem)
goto out_no_mem;
@@ -621,12 +620,12 @@ out_no_root:
out_no_smbiod:
smb_unload_nls(server);
out_bad_option:
- smb_kfree(mem);
+ kfree(mem);
out_no_mem:
if (!server->mnt)
printk(KERN_ERR "smb_fill_super: allocation failure\n");
sb->s_fs_info = NULL;
- smb_kfree(server);
+ kfree(server);
goto out_fail;
out_wrong_data:
printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
@@ -697,8 +696,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
DENTRY_PATH(dentry),
(long) inode->i_size, (long) attr->ia_size);
- filemap_fdatawrite(inode->i_mapping);
- filemap_fdatawait(inode->i_mapping);
+ filemap_write_and_wait(inode->i_mapping);
error = smb_open(dentry, O_WRONLY);
if (error)
@@ -783,12 +781,6 @@ out:
return error;
}
-#ifdef DEBUG_SMB_MALLOC
-int smb_malloced;
-int smb_current_kmalloced;
-int smb_current_vmalloced;
-#endif
-
static struct super_block *smb_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
@@ -808,12 +800,6 @@ static int __init init_smb_fs(void)
int err;
DEBUG1("registering ...\n");
-#ifdef DEBUG_SMB_MALLOC
- smb_malloced = 0;
- smb_current_kmalloced = 0;
- smb_current_vmalloced = 0;
-#endif
-
err = init_inodecache();
if (err)
goto out_inode;
@@ -838,11 +824,6 @@ static void __exit exit_smb_fs(void)
unregister_filesystem(&smb_fs_type);
smb_destroy_request_cache();
destroy_inodecache();
-#ifdef DEBUG_SMB_MALLOC
- printk(KERN_DEBUG "smb_malloced: %d\n", smb_malloced);
- printk(KERN_DEBUG "smb_current_kmalloced: %d\n",smb_current_kmalloced);
- printk(KERN_DEBUG "smb_current_vmalloced: %d\n",smb_current_vmalloced);
-#endif
}
module_init(init_smb_fs)
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 38ab558835c4..b1b878b81730 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -8,6 +8,7 @@
*/
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/fs.h>
@@ -3113,7 +3114,7 @@ smb_proc_setattr_unix(struct dentry *d, struct iattr *attr,
LSET(data, 32, SMB_TIME_NO_CHANGE);
LSET(data, 40, SMB_UID_NO_CHANGE);
LSET(data, 48, SMB_GID_NO_CHANGE);
- LSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
+ DSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
LSET(data, 60, major);
LSET(data, 68, minor);
LSET(data, 76, 0);
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index a0f296d9928a..c71c375863cc 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -68,7 +68,7 @@ static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
goto out;
if (bufsize > 0) {
- buf = smb_kmalloc(bufsize, GFP_NOFS);
+ buf = kmalloc(bufsize, GFP_NOFS);
if (!buf) {
kmem_cache_free(req_cachep, req);
return NULL;
@@ -124,9 +124,8 @@ static void smb_free_request(struct smb_request *req)
{
atomic_dec(&req->rq_server->nr_requests);
if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC))
- smb_kfree(req->rq_buffer);
- if (req->rq_trans2buffer)
- smb_kfree(req->rq_trans2buffer);
+ kfree(req->rq_buffer);
+ kfree(req->rq_trans2buffer);
kmem_cache_free(req_cachep, req);
}
@@ -183,8 +182,7 @@ static int smb_setup_request(struct smb_request *req)
req->rq_err = 0;
req->rq_errno = 0;
req->rq_fragment = 0;
- if (req->rq_trans2buffer)
- smb_kfree(req->rq_trans2buffer);
+ kfree(req->rq_trans2buffer);
return 0;
}
@@ -647,10 +645,9 @@ static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req)
goto out_too_long;
req->rq_trans2bufsize = buf_len;
- req->rq_trans2buffer = smb_kmalloc(buf_len, GFP_NOFS);
+ req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS);
if (!req->rq_trans2buffer)
goto out_no_mem;
- memset(req->rq_trans2buffer, 0, buf_len);
req->rq_parm = req->rq_trans2buffer;
req->rq_data = req->rq_trans2buffer + parm_tot;
diff --git a/fs/stat.c b/fs/stat.c
index b8a0e5110ab2..24211b030f39 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -63,12 +63,12 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
EXPORT_SYMBOL(vfs_getattr);
-int vfs_stat(char __user *name, struct kstat *stat)
+int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
{
struct nameidata nd;
int error;
- error = user_path_walk(name, &nd);
+ error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
if (!error) {
error = vfs_getattr(nd.mnt, nd.dentry, stat);
path_release(&nd);
@@ -76,14 +76,19 @@ int vfs_stat(char __user *name, struct kstat *stat)
return error;
}
+int vfs_stat(char __user *name, struct kstat *stat)
+{
+ return vfs_stat_fd(AT_FDCWD, name, stat);
+}
+
EXPORT_SYMBOL(vfs_stat);
-int vfs_lstat(char __user *name, struct kstat *stat)
+int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
{
struct nameidata nd;
int error;
- error = user_path_walk_link(name, &nd);
+ error = __user_walk_fd(dfd, name, 0, &nd);
if (!error) {
error = vfs_getattr(nd.mnt, nd.dentry, stat);
path_release(&nd);
@@ -91,6 +96,11 @@ int vfs_lstat(char __user *name, struct kstat *stat)
return error;
}
+int vfs_lstat(char __user *name, struct kstat *stat)
+{
+ return vfs_lstat_fd(AT_FDCWD, name, stat);
+}
+
EXPORT_SYMBOL(vfs_lstat);
int vfs_fstat(unsigned int fd, struct kstat *stat)
@@ -151,7 +161,7 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta
asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
{
struct kstat stat;
- int error = vfs_stat(filename, &stat);
+ int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_old_stat(&stat, statbuf);
@@ -161,7 +171,7 @@ asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user
asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
{
struct kstat stat;
- int error = vfs_lstat(filename, &stat);
+ int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_old_stat(&stat, statbuf);
@@ -229,27 +239,50 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
-asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf)
+asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_stat(filename, &stat);
+ int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_new_stat(&stat, statbuf);
return error;
}
-asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf)
+
+asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
{
struct kstat stat;
- int error = vfs_lstat(filename, &stat);
+ int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
if (!error)
error = cp_new_stat(&stat, statbuf);
return error;
}
-asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
+
+asmlinkage long sys_newfstatat(int dfd, char __user *filename,
+ struct stat __user *statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_fd(dfd, filename, &stat);
+
+ if (!error)
+ error = cp_new_stat(&stat, statbuf);
+
+out:
+ return error;
+}
+
+asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
{
struct kstat stat;
int error = vfs_fstat(fd, &stat);
@@ -260,7 +293,8 @@ asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
return error;
}
-asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz)
+asmlinkage long sys_readlinkat(int dfd, const char __user *path,
+ char __user *buf, int bufsiz)
{
struct nameidata nd;
int error;
@@ -268,7 +302,7 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu
if (bufsiz <= 0)
return -EINVAL;
- error = user_path_walk_link(path, &nd);
+ error = __user_walk_fd(dfd, path, 0, &nd);
if (!error) {
struct inode * inode = nd.dentry->d_inode;
@@ -285,6 +319,12 @@ asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bu
return error;
}
+asmlinkage long sys_readlink(const char __user *path, char __user *buf,
+ int bufsiz)
+{
+ return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
+}
+
/* ---------- LFS-64 ----------- */
#ifdef __ARCH_WANT_STAT64
diff --git a/fs/super.c b/fs/super.c
index 6689dded3c84..c177b92419c5 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -72,7 +72,7 @@ static struct super_block *alloc_super(void)
INIT_HLIST_HEAD(&s->s_anon);
INIT_LIST_HEAD(&s->s_inodes);
init_rwsem(&s->s_umount);
- sema_init(&s->s_lock, 1);
+ mutex_init(&s->s_lock);
down_write(&s->s_umount);
s->s_count = S_BIAS;
atomic_set(&s->s_active, 1);
@@ -665,16 +665,6 @@ static int test_bdev_super(struct super_block *s, void *data)
return (void *)s->s_bdev == data;
}
-static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
-{
- if (bdev->bd_disk) {
- if (bdev->bd_part)
- kobject_uevent(&bdev->bd_part->kobj, action, NULL);
- else
- kobject_uevent(&bdev->bd_disk->kobj, action, NULL);
- }
-}
-
struct super_block *get_sb_bdev(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
int (*fill_super)(struct super_block *, void *, int))
@@ -710,17 +700,14 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
s->s_flags = flags;
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
- s->s_old_blocksize = block_size(bdev);
- sb_set_blocksize(s, s->s_old_blocksize);
+ sb_set_blocksize(s, block_size(bdev));
error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
if (error) {
up_write(&s->s_umount);
deactivate_super(s);
s = ERR_PTR(error);
- } else {
+ } else
s->s_flags |= MS_ACTIVE;
- bdev_uevent(bdev, KOBJ_MOUNT);
- }
}
return s;
@@ -736,7 +723,6 @@ void kill_block_super(struct super_block *sb)
{
struct block_device *bdev = sb->s_bdev;
- bdev_uevent(bdev, KOBJ_UMOUNT);
generic_shutdown_super(sb);
sync_blockdev(bdev);
close_bdev_excl(bdev);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 59734ba1ee60..49bd219275db 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -99,7 +99,7 @@ static int create_dir(struct kobject * k, struct dentry * p,
int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
- down(&p->d_inode->i_sem);
+ mutex_lock(&p->d_inode->i_mutex);
*d = lookup_one_len(n, p, strlen(n));
if (!IS_ERR(*d)) {
error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
@@ -112,13 +112,17 @@ static int create_dir(struct kobject * k, struct dentry * p,
}
}
if (error && (error != -EEXIST)) {
- sysfs_put((*d)->d_fsdata);
+ struct sysfs_dirent *sd = (*d)->d_fsdata;
+ if (sd) {
+ list_del_init(&sd->s_sibling);
+ sysfs_put(sd);
+ }
d_drop(*d);
}
dput(*d);
} else
error = PTR_ERR(*d);
- up(&p->d_inode->i_sem);
+ mutex_unlock(&p->d_inode->i_mutex);
return error;
}
@@ -242,7 +246,7 @@ static void remove_dir(struct dentry * d)
struct dentry * parent = dget(d->d_parent);
struct sysfs_dirent * sd;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
d_delete(d);
sd = d->d_fsdata;
list_del_init(&sd->s_sibling);
@@ -253,7 +257,7 @@ static void remove_dir(struct dentry * d)
pr_debug(" o %s removing done (%d)\n",d->d_name.name,
atomic_read(&d->d_count));
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
dput(parent);
}
@@ -282,7 +286,7 @@ void sysfs_remove_dir(struct kobject * kobj)
return;
pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
parent_sd = dentry->d_fsdata;
list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
@@ -291,7 +295,7 @@ void sysfs_remove_dir(struct kobject * kobj)
sysfs_drop_dentry(sd, dentry);
sysfs_put(sd);
}
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
remove_dir(dentry);
/**
@@ -314,7 +318,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
down_write(&sysfs_rename_sem);
parent = kobj->parent->dentry;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
if (!IS_ERR(new_dentry)) {
@@ -330,7 +334,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
error = -EEXIST;
dput(new_dentry);
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
up_write(&sysfs_rename_sem);
return error;
@@ -341,9 +345,9 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
struct dentry * dentry = file->f_dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
file->private_data = sysfs_new_dirent(parent_sd, NULL);
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
return file->private_data ? 0 : -ENOMEM;
@@ -354,9 +358,9 @@ static int sysfs_dir_close(struct inode *inode, struct file *file)
struct dentry * dentry = file->f_dentry;
struct sysfs_dirent * cursor = file->private_data;
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
list_del_init(&cursor->s_sibling);
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
release_sysfs_dirent(cursor);
@@ -432,7 +436,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
struct dentry * dentry = file->f_dentry;
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += file->f_pos;
@@ -440,7 +444,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- up(&file->f_dentry->d_inode->i_sem);
+ mutex_unlock(&file->f_dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
@@ -464,7 +468,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
list_add_tail(&cursor->s_sibling, p);
}
}
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
return offset;
}
@@ -479,4 +483,3 @@ struct file_operations sysfs_dir_operations = {
EXPORT_SYMBOL_GPL(sysfs_create_dir);
EXPORT_SYMBOL_GPL(sysfs_remove_dir);
EXPORT_SYMBOL_GPL(sysfs_rename_dir);
-
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 4013d7905e84..d0e3d8495165 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -364,9 +364,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
int error = 0;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
error = sysfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type);
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return error;
}
@@ -398,7 +398,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
struct dentry * victim;
int res = -ENOENT;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
/* make sure dentry is really there */
@@ -420,7 +420,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
*/
dput(victim);
}
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return res;
}
@@ -441,22 +441,22 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
struct iattr newattrs;
int res = -ENOENT;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
inode = victim->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
newattrs.ia_mode = (mode & S_IALLUGO) |
(inode->i_mode & ~S_IALLUGO);
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
res = notify_change(victim, &newattrs);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
dput(victim);
}
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return res;
}
@@ -480,4 +480,3 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
EXPORT_SYMBOL_GPL(sysfs_create_file);
EXPORT_SYMBOL_GPL(sysfs_remove_file);
EXPORT_SYMBOL_GPL(sysfs_update_file);
-
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 970a33f03299..689f7bcfaf30 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -11,6 +11,7 @@
#include <linux/pagemap.h>
#include <linux/namei.h>
#include <linux/backing-dev.h>
+#include <linux/capability.h>
#include "sysfs.h"
extern struct super_block * sysfs_sb;
@@ -201,7 +202,7 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
/*
* Unhashes the dentry corresponding to given sysfs_dirent
- * Called with parent inode's i_sem held.
+ * Called with parent inode's i_mutex held.
*/
void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
{
@@ -232,7 +233,7 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
/* no inode means this hasn't been made visible yet */
return;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
if (!sd->s_element)
continue;
@@ -243,7 +244,5 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
break;
}
}
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
}
-
-
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index de402fa915f2..e38d6338a20d 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -86,9 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
BUG_ON(!kobj || !kobj->dentry || !name);
- down(&dentry->d_inode->i_sem);
+ mutex_lock(&dentry->d_inode->i_mutex);
error = sysfs_add_link(dentry, name, target);
- up(&dentry->d_inode->i_sem);
+ mutex_unlock(&dentry->d_inode->i_mutex);
return error;
}
@@ -177,4 +177,3 @@ struct inode_operations sysfs_symlink_inode_operations = {
EXPORT_SYMBOL_GPL(sysfs_create_link);
EXPORT_SYMBOL_GPL(sysfs_remove_link);
-
diff --git a/fs/sysv/ChangeLog b/fs/sysv/ChangeLog
index 18e3487debdb..f403f8b91b80 100644
--- a/fs/sysv/ChangeLog
+++ b/fs/sysv/ChangeLog
@@ -54,7 +54,7 @@ Fri Jan 4 2002 Alexander Viro <viro@parcelfarce.linux.theplanet.co.uk>
(sysv_read_super): Likewise.
(v7_read_super): Likewise.
-Sun Dec 30 2001 Manfred Spraul <manfreds@colorfullife.com>
+Sun Dec 30 2001 Manfred Spraul <manfred@colorfullife.com>
* dir.c (dir_commit_chunk): Do not set dir->i_version.
(sysv_readdir): Likewise.
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 69a085abad6f..cce8b05cba5a 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -103,7 +103,7 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
offset = (char *)de - kaddr;
over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN),
- (n<<PAGE_CACHE_SHIFT) | offset,
+ ((loff_t)n<<PAGE_CACHE_SHIFT) | offset,
fs16_to_cpu(SYSV_SB(sb), de->inode),
DT_UNKNOWN);
if (over) {
@@ -115,7 +115,7 @@ static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
}
done:
- filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
+ filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset;
unlock_kernel();
return 0;
}
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index b9ded26b10a9..4fae57d9d115 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -4,11 +4,6 @@
* PURPOSE
* Block allocation handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
@@ -46,7 +41,7 @@
#define uint(x) xuint(x)
#define xuint(x) __le ## x
-extern inline int find_next_one_bit (void * addr, int size, int offset)
+static inline int find_next_one_bit (void * addr, int size, int offset)
{
uintBPL_t * p = ((uintBPL_t *) addr) + (offset / BITS_PER_LONG);
int result = offset & ~(BITS_PER_LONG-1);
diff --git a/fs/udf/crc.c b/fs/udf/crc.c
index d95c6e38a455..1b82a4adc2f7 100644
--- a/fs/udf/crc.c
+++ b/fs/udf/crc.c
@@ -14,11 +14,6 @@
*
* AT&T gives permission for the free use of the CRC source code.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 82440b731142..f5222527fe39 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -4,11 +4,6 @@
* PURPOSE
* Directory handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 9a61ecc5451b..fe751a2a0e47 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -4,11 +4,6 @@
* PURPOSE
* Directory related functions
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 01f520c71dc1..a6f2acc1f15c 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -4,11 +4,6 @@
* PURPOSE
* File handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
@@ -36,6 +31,7 @@
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/string.h> /* memset */
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/pagemap.h>
diff --git a/fs/udf/fsync.c b/fs/udf/fsync.c
index 2dde6b888c2b..5887d78cde43 100644
--- a/fs/udf/fsync.c
+++ b/fs/udf/fsync.c
@@ -4,11 +4,6 @@
* PURPOSE
* Fsync handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index a7e5d40f1ebc..c9b707b470ca 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -4,11 +4,6 @@
* PURPOSE
* Inode allocation handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index b83890beaaac..395e582ee542 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -4,11 +4,6 @@
* PURPOSE
* Inode handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
@@ -1962,11 +1957,6 @@ int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t
printk(KERN_ERR "udf: inode_bmap: block < 0\n");
return -1;
}
- if (!inode)
- {
- printk(KERN_ERR "udf: inode_bmap: NULL inode\n");
- return -1;
- }
*extoffset = 0;
*elen = 0;
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index 2da5087dfe05..084216107667 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -4,11 +4,6 @@
* PURPOSE
* Low Level Device Routines for the UDF filesystem
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index fd321f9ace83..cc8ca3254db1 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -4,11 +4,6 @@
* PURPOSE
* Miscellaneous routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index ac191ed7df0a..ca732e79c48b 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -4,11 +4,6 @@
* PURPOSE
* Inode name handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index 4d36f264be0d..dabf2b841db8 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -4,11 +4,6 @@
* PURPOSE
* Partition handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 15bd4f24c5b7..4a6f49adc609 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -14,11 +14,6 @@
* http://www.ecma.ch/
* http://www.iso.org/
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 43f3051ef756..674bb40edc83 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -4,11 +4,6 @@
* PURPOSE
* Symlink handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 7dc8a5572ca1..e1b0e8cfecb4 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -4,11 +4,6 @@
* PURPOSE
* Truncate handling routines for the OSTA-UDF(tm) filesystem.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index 5a80efd8debc..706c92e1dcc9 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -11,11 +11,6 @@
* UTF-8 is explained in the IETF RFC XXXX.
* ftp://ftp.internic.net/rfc/rfcxxxx.txt
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team's mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index faf1512173eb..3ada9dcf55b8 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
+#include <linux/capability.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <asm/byteorder.h>
@@ -48,7 +49,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
@@ -80,8 +81,9 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count
for (i = bit; i < end_bit; i++) {
if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i))
ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i);
- else ufs_error (sb, "ufs_free_fragments",
- "bit already cleared for fragment %u", i);
+ else
+ ufs_error (sb, "ufs_free_fragments",
+ "bit already cleared for fragment %u", i);
}
DQUOT_FREE_BLOCK (inode, count);
@@ -142,7 +144,7 @@ void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) {
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
@@ -246,7 +248,7 @@ unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
*err = -ENOSPC;
lock_super (sb);
@@ -406,7 +408,7 @@ ufs_add_fragments (struct inode * inode, unsigned fragment,
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first (USPI_UBH);
+ usb1 = ubh_get_usb_first (uspi);
count = newcount - oldcount;
cgno = ufs_dtog(fragment);
@@ -489,7 +491,7 @@ static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
oldcg = cgno;
/*
@@ -605,7 +607,7 @@ static unsigned ufs_alloccg_block (struct inode * inode,
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
ucg = ubh_get_ucg(UCPI_UBH);
if (goal == 0) {
@@ -662,7 +664,7 @@ static unsigned ufs_bitmap_search (struct super_block * sb,
UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count))
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first (USPI_UBH);
+ usb1 = ubh_get_usb_first (uspi);
ucg = ubh_get_ucg(UCPI_UBH);
if (goal)
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index d0915fba155a..7c10c68902ae 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -491,7 +491,7 @@ int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
fs32_to_cpu(sb, de->d_ino),
- fs16to_cpu(sb, de->d_reclen),
+ fs16_to_cpu(sb, de->d_reclen),
ufs_get_de_namlen(sb, de), de->d_name))
while (i < bh->b_size) {
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index 0938945b9cbc..c7a47ed4f430 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -72,7 +72,7 @@ void ufs_free_inode (struct inode * inode)
sb = inode->i_sb;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
ino = inode->i_ino;
@@ -167,7 +167,7 @@ struct inode * ufs_new_inode(struct inode * dir, int mode)
ufsi = UFS_I(inode);
sbi = UFS_SB(sb);
uspi = sbi->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
lock_super (sb);
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 55f4aa16e3fc..e0c04e36a051 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -61,7 +61,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off
int n = 0;
- UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%d \n",ptrs,double_blocks));
+ UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks));
if (i_block < 0) {
ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0");
} else if (i_block < direct_blocks) {
@@ -104,7 +104,7 @@ u64 ufs_frag_map(struct inode *inode, sector_t frag)
unsigned flags = UFS_SB(sb)->s_flags;
u64 temp = 0L;
- UFSD((": frag = %lu depth = %d\n",frag,depth));
+ UFSD((": frag = %llu depth = %d\n", (unsigned long long)frag, depth));
UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask));
if (depth == 0)
@@ -365,9 +365,10 @@ repeat:
sync_dirty_buffer(bh);
inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
+ UFSD(("result %u\n", tmp + blockoff));
out:
brelse (bh);
- UFSD(("EXIT, result %u\n", tmp + blockoff))
+ UFSD(("EXIT\n"));
return result;
}
@@ -386,7 +387,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf
if (!create) {
phys64 = ufs_frag_map(inode, fragment);
- UFSD(("phys64 = %lu \n",phys64));
+ UFSD(("phys64 = %llu \n",phys64));
if (phys64)
map_bh(bh_result, sb, phys64);
return 0;
@@ -401,7 +402,7 @@ static int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buf
lock_kernel();
- UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
+ UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment))
if (fragment < 0)
goto abort_negative;
if (fragment >
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 54828ebcf1ba..d4aacee593ff 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -221,7 +221,7 @@ void ufs_error (struct super_block * sb, const char * function,
va_list args;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
if (!(sb->s_flags & MS_RDONLY)) {
usb1->fs_clean = UFS_FSBAD;
@@ -253,7 +253,7 @@ void ufs_panic (struct super_block * sb, const char * function,
va_list args;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
if (!(sb->s_flags & MS_RDONLY)) {
usb1->fs_clean = UFS_FSBAD;
@@ -420,21 +420,18 @@ static int ufs_read_cylinder_structures (struct super_block *sb) {
if (i + uspi->s_fpb > blks)
size = (blks - i) * uspi->s_fsize;
- if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+ if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
ubh = ubh_bread(sb,
fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
- if (!ubh)
- goto failed;
- ubh_ubhcpymem (space, ubh, size);
- sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
- }
- else {
+ else
ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
- if (!ubh)
- goto failed;
- ubh_ubhcpymem(space, ubh, size);
- sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
- }
+
+ if (!ubh)
+ goto failed;
+
+ ubh_ubhcpymem (space, ubh, size);
+ sbi->s_csp[ufs_fragstoblks(i)]=(struct ufs_csum *)space;
+
space += size;
ubh_brelse (ubh);
ubh = NULL;
@@ -539,6 +536,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
struct inode *inode;
unsigned block_size, super_block_size;
unsigned flags;
+ unsigned super_block_offset;
uspi = NULL;
ubh = NULL;
@@ -586,10 +584,11 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
if (!uspi)
goto failed;
+ super_block_offset=UFS_SBLOCK;
+
/* Keep 2Gig file limit. Some UFS variants need to override
this but as I don't know which I'll let those in the know loosen
the rules */
-
switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
case UFS_MOUNT_UFSTYPE_44BSD:
UFSD(("ufstype=44bsd\n"))
@@ -601,7 +600,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
break;
case UFS_MOUNT_UFSTYPE_UFS2:
- UFSD(("ufstype=ufs2\n"))
+ UFSD(("ufstype=ufs2\n"));
+ super_block_offset=SBLOCK_UFS2;
uspi->s_fsize = block_size = 512;
uspi->s_fmask = ~(512 - 1);
uspi->s_fshift = 9;
@@ -725,19 +725,16 @@ again:
/*
* read ufs super block from device
*/
- if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
- ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + SBLOCK_UFS2/block_size, super_block_size);
- }
- else {
- ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + UFS_SBLOCK/block_size, super_block_size);
- }
+
+ ubh = ubh_bread_uspi(uspi, sb, uspi->s_sbbase + super_block_offset/block_size, super_block_size);
+
if (!ubh)
goto failed;
- usb1 = ubh_get_usb_first(USPI_UBH);
- usb2 = ubh_get_usb_second(USPI_UBH);
- usb3 = ubh_get_usb_third(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
+ usb2 = ubh_get_usb_second(uspi);
+ usb3 = ubh_get_usb_third(uspi);
usb = (struct ufs_super_block *)
((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
@@ -1006,8 +1003,8 @@ static void ufs_write_super (struct super_block *sb) {
UFSD(("ENTER\n"))
flags = UFS_SB(sb)->s_flags;
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first(USPI_UBH);
- usb3 = ubh_get_usb_third(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
+ usb3 = ubh_get_usb_third(uspi);
if (!(sb->s_flags & MS_RDONLY)) {
usb1->fs_time = cpu_to_fs32(sb, get_seconds());
@@ -1049,8 +1046,8 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
uspi = UFS_SB(sb)->s_uspi;
flags = UFS_SB(sb)->s_flags;
- usb1 = ubh_get_usb_first(USPI_UBH);
- usb3 = ubh_get_usb_third(USPI_UBH);
+ usb1 = ubh_get_usb_first(uspi);
+ usb3 = ubh_get_usb_third(uspi);
/*
* Allow the "check" option to be passed as a remount option.
@@ -1124,7 +1121,7 @@ static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
lock_kernel();
uspi = UFS_SB(sb)->s_uspi;
- usb1 = ubh_get_usb_first (USPI_UBH);
+ usb1 = ubh_get_usb_first (uspi);
usb = (struct ufs_super_block *)
((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
@@ -1275,7 +1272,7 @@ static ssize_t ufs_quota_write(struct super_block *sb, int type,
size_t towrite = len;
struct buffer_head *bh;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
while (towrite > 0) {
tocopy = sb->s_blocksize - offset < towrite ?
sb->s_blocksize - offset : towrite;
@@ -1296,14 +1293,16 @@ static ssize_t ufs_quota_write(struct super_block *sb, int type,
blk++;
}
out:
- if (len == towrite)
+ if (len == towrite) {
+ mutex_unlock(&inode->i_mutex);
return err;
+ }
if (inode->i_size < off+len-towrite)
i_size_write(inode, off+len-towrite);
inode->i_version++;
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
mark_inode_dirty(inode);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return len - towrite;
}
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index b2640076679a..48d6d9bcc157 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -249,18 +249,28 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
/*
- * macros to get important structures from ufs_buffer_head
+ * macros and inline function to get important structures from ufs_sb_private_info
*/
-#define ubh_get_usb_first(ubh) \
- ((struct ufs_super_block_first *)((ubh)->bh[0]->b_data))
-#define ubh_get_usb_second(ubh) \
- ((struct ufs_super_block_second *)(ubh)-> \
- bh[UFS_SECTOR_SIZE >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE & ~uspi->s_fmask))
+static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
+ unsigned int offset)
+{
+ unsigned int index;
+
+ index = offset >> uspi->s_fshift;
+ offset &= ~uspi->s_fmask;
+ return uspi->s_ubh.bh[index]->b_data + offset;
+}
+
+#define ubh_get_usb_first(uspi) \
+ ((struct ufs_super_block_first *)get_usb_offset((uspi), 0))
+
+#define ubh_get_usb_second(uspi) \
+ ((struct ufs_super_block_second *)get_usb_offset((uspi), UFS_SECTOR_SIZE))
+
+#define ubh_get_usb_third(uspi) \
+ ((struct ufs_super_block_third *)get_usb_offset((uspi), 2*UFS_SECTOR_SIZE))
-#define ubh_get_usb_third(ubh) \
- ((struct ufs_super_block_third *)((ubh)-> \
- bh[UFS_SECTOR_SIZE*2 >> uspi->s_fshift]->b_data + (UFS_SECTOR_SIZE*2 & ~uspi->s_fmask)))
#define ubh_get_ucg(ubh) \
((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data))
diff --git a/fs/xattr.c b/fs/xattr.c
index bcc2156d4d28..80eca7d3d69f 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -19,6 +19,149 @@
#include <linux/fsnotify.h>
#include <asm/uaccess.h>
+
+/*
+ * Check permissions for extended attribute access. This is a bit complicated
+ * because different namespaces have very different rules.
+ */
+static int
+xattr_permission(struct inode *inode, const char *name, int mask)
+{
+ /*
+ * We can never set or remove an extended attribute on a read-only
+ * filesystem or on an immutable / append-only inode.
+ */
+ if (mask & MAY_WRITE) {
+ if (IS_RDONLY(inode))
+ return -EROFS;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ return -EPERM;
+ }
+
+ /*
+ * No restriction for security.* and system.* from the VFS. Decision
+ * on these is left to the underlying filesystem / security module.
+ */
+ if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
+ !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
+ return 0;
+
+ /*
+ * The trusted.* namespace can only accessed by a privilegued user.
+ */
+ if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+ return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
+
+ if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
+ if (!S_ISREG(inode->i_mode) &&
+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+ return -EPERM;
+ }
+
+ return permission(inode, mask, NULL);
+}
+
+int
+vfs_setxattr(struct dentry *dentry, char *name, void *value,
+ size_t size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = xattr_permission(inode, name, MAY_WRITE);
+ if (error)
+ return error;
+
+ mutex_lock(&inode->i_mutex);
+ error = security_inode_setxattr(dentry, name, value, size, flags);
+ if (error)
+ goto out;
+ error = -EOPNOTSUPP;
+ if (inode->i_op->setxattr) {
+ error = inode->i_op->setxattr(dentry, name, value, size, flags);
+ if (!error) {
+ fsnotify_xattr(dentry);
+ security_inode_post_setxattr(dentry, name, value,
+ size, flags);
+ }
+ } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ XATTR_SECURITY_PREFIX_LEN)) {
+ const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+ error = security_inode_setsecurity(inode, suffix, value,
+ size, flags);
+ if (!error)
+ fsnotify_xattr(dentry);
+ }
+out:
+ mutex_unlock(&inode->i_mutex);
+ return error;
+}
+EXPORT_SYMBOL_GPL(vfs_setxattr);
+
+ssize_t
+vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ error = xattr_permission(inode, name, MAY_READ);
+ if (error)
+ return error;
+
+ error = security_inode_getxattr(dentry, name);
+ if (error)
+ return error;
+
+ if (inode->i_op->getxattr)
+ error = inode->i_op->getxattr(dentry, name, value, size);
+ else
+ error = -EOPNOTSUPP;
+
+ if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ XATTR_SECURITY_PREFIX_LEN)) {
+ const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+ int ret = security_inode_getsecurity(inode, suffix, value,
+ size, error);
+ /*
+ * Only overwrite the return value if a security module
+ * is actually active.
+ */
+ if (ret != -EOPNOTSUPP)
+ error = ret;
+ }
+
+ return error;
+}
+EXPORT_SYMBOL_GPL(vfs_getxattr);
+
+int
+vfs_removexattr(struct dentry *dentry, char *name)
+{
+ struct inode *inode = dentry->d_inode;
+ int error;
+
+ if (!inode->i_op->removexattr)
+ return -EOPNOTSUPP;
+
+ error = xattr_permission(inode, name, MAY_WRITE);
+ if (error)
+ return error;
+
+ error = security_inode_removexattr(dentry, name);
+ if (error)
+ return error;
+
+ mutex_lock(&inode->i_mutex);
+ error = inode->i_op->removexattr(dentry, name);
+ mutex_unlock(&inode->i_mutex);
+
+ if (!error)
+ fsnotify_xattr(dentry);
+ return error;
+}
+EXPORT_SYMBOL_GPL(vfs_removexattr);
+
+
/*
* Extended attribute SET operations
*/
@@ -51,29 +194,7 @@ 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) {
- 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);
- }
- } 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);
+ error = vfs_setxattr(d, kname, kvalue, size, flags);
kfree(kvalue);
return error;
}
@@ -147,22 +268,7 @@ 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 = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
-
- if (!strncmp(kname, XATTR_SECURITY_PREFIX,
- sizeof XATTR_SECURITY_PREFIX - 1)) {
- const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
- int rv = security_inode_getsecurity(d->d_inode, suffix, kvalue,
- size, error);
- /* Security module active: overwrite error value */
- if (rv != -EOPNOTSUPP)
- error = rv;
- }
+ error = vfs_getxattr(d, kname, kvalue, size);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
@@ -171,7 +277,6 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
than XATTR_SIZE_MAX bytes. Not possible. */
error = -E2BIG;
}
-out:
kfree(kvalue);
return error;
}
@@ -318,19 +423,7 @@ removexattr(struct dentry *d, char __user *name)
if (error < 0)
return error;
- error = -EOPNOTSUPP;
- if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
- error = security_inode_removexattr(d, kname);
- if (error)
- goto out;
- 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;
+ return vfs_removexattr(d, kname);
}
asmlinkage long
diff --git a/fs/xfs/Kbuild b/fs/xfs/Kbuild
new file mode 100644
index 000000000000..2566e96706f1
--- /dev/null
+++ b/fs/xfs/Kbuild
@@ -0,0 +1,6 @@
+#
+# The xfs people like to share Makefile with 2.6 and 2.4.
+# Utilise file named Kbuild file which has precedence over Makefile.
+#
+
+include $(srctree)/$(obj)/Makefile-linux-2.6
diff --git a/fs/xfs/linux-2.6/mutex.h b/fs/xfs/linux-2.6/mutex.h
index ce773d89a923..2a88d56c4dc2 100644
--- a/fs/xfs/linux-2.6/mutex.h
+++ b/fs/xfs/linux-2.6/mutex.h
@@ -18,22 +18,8 @@
#ifndef __XFS_SUPPORT_MUTEX_H__
#define __XFS_SUPPORT_MUTEX_H__
-#include <linux/spinlock.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
-/*
- * Map the mutex'es from IRIX to Linux semaphores.
- *
- * Destroy just simply initializes to -99 which should block all other
- * callers.
- */
-#define MUTEX_DEFAULT 0x0
-typedef struct semaphore mutex_t;
-
-#define mutex_init(lock, type, name) sema_init(lock, 1)
-#define mutex_destroy(lock) sema_init(lock, -99)
-#define mutex_lock(lock, num) down(lock)
-#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1)
-#define mutex_unlock(lock) up(lock)
+typedef struct mutex mutex_t;
#endif /* __XFS_SUPPORT_MUTEX_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 94d3cdfbf9b8..120626789406 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -40,11 +40,10 @@
#include "xfs_rw.h"
#include "xfs_iomap.h"
#include <linux/mpage.h>
+#include <linux/pagevec.h>
#include <linux/writeback.h>
STATIC void xfs_count_page_state(struct page *, int *, int *, int *);
-STATIC void xfs_convert_page(struct inode *, struct page *, xfs_iomap_t *,
- struct writeback_control *wbc, void *, int, int);
#if defined(XFS_RW_TRACE)
void
@@ -55,17 +54,15 @@ xfs_page_trace(
int mask)
{
xfs_inode_t *ip;
- bhv_desc_t *bdp;
vnode_t *vp = LINVFS_GET_VP(inode);
loff_t isize = i_size_read(inode);
- loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+ loff_t offset = page_offset(page);
int delalloc = -1, unmapped = -1, unwritten = -1;
if (page_has_buffers(page))
xfs_count_page_state(page, &delalloc, &unmapped, &unwritten);
- bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
- ip = XFS_BHVTOI(bdp);
+ ip = xfs_vtoi(vp);
if (!ip->i_rwtrace)
return;
@@ -103,15 +100,56 @@ xfs_finish_ioend(
queue_work(xfsdatad_workqueue, &ioend->io_work);
}
+/*
+ * We're now finished for good with this ioend structure.
+ * Update the page state via the associated buffer_heads,
+ * release holds on the inode and bio, and finally free
+ * up memory. Do not use the ioend after this.
+ */
STATIC void
xfs_destroy_ioend(
xfs_ioend_t *ioend)
{
+ struct buffer_head *bh, *next;
+
+ for (bh = ioend->io_buffer_head; bh; bh = next) {
+ next = bh->b_private;
+ bh->b_end_io(bh, ioend->io_uptodate);
+ }
+
vn_iowake(ioend->io_vnode);
mempool_free(ioend, xfs_ioend_pool);
}
/*
+ * Buffered IO write completion for delayed allocate extents.
+ * TODO: Update ondisk isize now that we know the file data
+ * has been flushed (i.e. the notorious "NULL file" problem).
+ */
+STATIC void
+xfs_end_bio_delalloc(
+ void *data)
+{
+ xfs_ioend_t *ioend = data;
+
+ xfs_destroy_ioend(ioend);
+}
+
+/*
+ * Buffered IO write completion for regular, written extents.
+ */
+STATIC void
+xfs_end_bio_written(
+ void *data)
+{
+ xfs_ioend_t *ioend = data;
+
+ xfs_destroy_ioend(ioend);
+}
+
+/*
+ * IO write completion for unwritten extents.
+ *
* Issue transactions to convert a buffer range from unwritten
* to written extents.
*/
@@ -123,21 +161,10 @@ xfs_end_bio_unwritten(
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);
- }
-
xfs_destroy_ioend(ioend);
}
@@ -149,7 +176,8 @@ xfs_end_bio_unwritten(
*/
STATIC xfs_ioend_t *
xfs_alloc_ioend(
- struct inode *inode)
+ struct inode *inode,
+ unsigned int type)
{
xfs_ioend_t *ioend;
@@ -162,45 +190,25 @@ xfs_alloc_ioend(
*/
atomic_set(&ioend->io_remaining, 1);
ioend->io_uptodate = 1; /* cleared if any I/O fails */
+ ioend->io_list = NULL;
+ ioend->io_type = type;
ioend->io_vnode = LINVFS_GET_VP(inode);
ioend->io_buffer_head = NULL;
+ ioend->io_buffer_tail = 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);
+ if (type == IOMAP_UNWRITTEN)
+ INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend);
+ else if (type == IOMAP_DELAY)
+ INIT_WORK(&ioend->io_work, xfs_end_bio_delalloc, ioend);
+ else
+ INIT_WORK(&ioend->io_work, xfs_end_bio_written, 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
xfs_map_blocks(
struct inode *inode,
@@ -218,138 +226,283 @@ xfs_map_blocks(
return -error;
}
+STATIC inline int
+xfs_iomap_valid(
+ xfs_iomap_t *iomapp,
+ loff_t offset)
+{
+ return offset >= iomapp->iomap_offset &&
+ offset < iomapp->iomap_offset + iomapp->iomap_bsize;
+}
+
/*
- * Finds the corresponding mapping in block @map array of the
- * given @offset within a @page.
+ * BIO completion handler for buffered IO.
*/
-STATIC xfs_iomap_t *
-xfs_offset_to_map(
+STATIC int
+xfs_end_bio(
+ struct bio *bio,
+ unsigned int bytes_done,
+ int error)
+{
+ xfs_ioend_t *ioend = bio->bi_private;
+
+ if (bio->bi_size)
+ return 1;
+
+ ASSERT(ioend);
+ ASSERT(atomic_read(&bio->bi_cnt) >= 1);
+
+ /* Toss bio and pass work off to an xfsdatad thread */
+ if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+ ioend->io_uptodate = 0;
+ bio->bi_private = NULL;
+ bio->bi_end_io = NULL;
+
+ bio_put(bio);
+ xfs_finish_ioend(ioend);
+ return 0;
+}
+
+STATIC void
+xfs_submit_ioend_bio(
+ xfs_ioend_t *ioend,
+ struct bio *bio)
+{
+ atomic_inc(&ioend->io_remaining);
+
+ bio->bi_private = ioend;
+ bio->bi_end_io = xfs_end_bio;
+
+ submit_bio(WRITE, bio);
+ ASSERT(!bio_flagged(bio, BIO_EOPNOTSUPP));
+ bio_put(bio);
+}
+
+STATIC struct bio *
+xfs_alloc_ioend_bio(
+ struct buffer_head *bh)
+{
+ struct bio *bio;
+ int nvecs = bio_get_nr_vecs(bh->b_bdev);
+
+ do {
+ bio = bio_alloc(GFP_NOIO, nvecs);
+ nvecs >>= 1;
+ } while (!bio);
+
+ ASSERT(bio->bi_private == NULL);
+ bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+ bio->bi_bdev = bh->b_bdev;
+ bio_get(bio);
+ return bio;
+}
+
+STATIC void
+xfs_start_buffer_writeback(
+ struct buffer_head *bh)
+{
+ ASSERT(buffer_mapped(bh));
+ ASSERT(buffer_locked(bh));
+ ASSERT(!buffer_delay(bh));
+ ASSERT(!buffer_unwritten(bh));
+
+ mark_buffer_async_write(bh);
+ set_buffer_uptodate(bh);
+ clear_buffer_dirty(bh);
+}
+
+STATIC void
+xfs_start_page_writeback(
struct page *page,
- xfs_iomap_t *iomapp,
- unsigned long offset)
+ struct writeback_control *wbc,
+ int clear_dirty,
+ int buffers)
+{
+ ASSERT(PageLocked(page));
+ ASSERT(!PageWriteback(page));
+ set_page_writeback(page);
+ if (clear_dirty)
+ clear_page_dirty(page);
+ unlock_page(page);
+ if (!buffers) {
+ end_page_writeback(page);
+ wbc->pages_skipped++; /* We didn't write this page */
+ }
+}
+
+static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
+{
+ return bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh));
+}
+
+/*
+ * Submit all of the bios for all of the ioends we have saved up, covering the
+ * initial writepage page and also any probed pages.
+ *
+ * Because we may have multiple ioends spanning a page, we need to start
+ * writeback on all the buffers before we submit them for I/O. If we mark the
+ * buffers as we got, then we can end up with a page that only has buffers
+ * marked async write and I/O complete on can occur before we mark the other
+ * buffers async write.
+ *
+ * The end result of this is that we trip a bug in end_page_writeback() because
+ * we call it twice for the one page as the code in end_buffer_async_write()
+ * assumes that all buffers on the page are started at the same time.
+ *
+ * The fix is two passes across the ioend list - one to start writeback on the
+ * bufferheads, and then the second one submit them for I/O.
+ */
+STATIC void
+xfs_submit_ioend(
+ xfs_ioend_t *ioend)
+{
+ xfs_ioend_t *head = ioend;
+ xfs_ioend_t *next;
+ struct buffer_head *bh;
+ struct bio *bio;
+ sector_t lastblock = 0;
+
+ /* Pass 1 - start writeback */
+ do {
+ next = ioend->io_list;
+ for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
+ xfs_start_buffer_writeback(bh);
+ }
+ } while ((ioend = next) != NULL);
+
+ /* Pass 2 - submit I/O */
+ ioend = head;
+ do {
+ next = ioend->io_list;
+ bio = NULL;
+
+ for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
+
+ if (!bio) {
+ retry:
+ bio = xfs_alloc_ioend_bio(bh);
+ } else if (bh->b_blocknr != lastblock + 1) {
+ xfs_submit_ioend_bio(ioend, bio);
+ goto retry;
+ }
+
+ if (bio_add_buffer(bio, bh) != bh->b_size) {
+ xfs_submit_ioend_bio(ioend, bio);
+ goto retry;
+ }
+
+ lastblock = bh->b_blocknr;
+ }
+ if (bio)
+ xfs_submit_ioend_bio(ioend, bio);
+ xfs_finish_ioend(ioend);
+ } while ((ioend = next) != NULL);
+}
+
+/*
+ * Cancel submission of all buffer_heads so far in this endio.
+ * Toss the endio too. Only ever called for the initial page
+ * in a writepage request, so only ever one page.
+ */
+STATIC void
+xfs_cancel_ioend(
+ xfs_ioend_t *ioend)
+{
+ xfs_ioend_t *next;
+ struct buffer_head *bh, *next_bh;
+
+ do {
+ next = ioend->io_list;
+ bh = ioend->io_buffer_head;
+ do {
+ next_bh = bh->b_private;
+ clear_buffer_async_write(bh);
+ unlock_buffer(bh);
+ } while ((bh = next_bh) != NULL);
+
+ vn_iowake(ioend->io_vnode);
+ mempool_free(ioend, xfs_ioend_pool);
+ } while ((ioend = next) != NULL);
+}
+
+/*
+ * Test to see if we've been building up a completion structure for
+ * earlier buffers -- if so, we try to append to this ioend if we
+ * can, otherwise we finish off any current ioend and start another.
+ * Return true if we've finished the given ioend.
+ */
+STATIC void
+xfs_add_to_ioend(
+ struct inode *inode,
+ struct buffer_head *bh,
+ xfs_off_t offset,
+ unsigned int type,
+ xfs_ioend_t **result,
+ int need_ioend)
{
- loff_t full_offset; /* offset from start of file */
+ xfs_ioend_t *ioend = *result;
- ASSERT(offset < PAGE_CACHE_SIZE);
+ if (!ioend || need_ioend || type != ioend->io_type) {
+ xfs_ioend_t *previous = *result;
- full_offset = page->index; /* NB: using 64bit number */
- full_offset <<= PAGE_CACHE_SHIFT; /* offset from file start */
- full_offset += offset; /* offset from page start */
+ ioend = xfs_alloc_ioend(inode, type);
+ ioend->io_offset = offset;
+ ioend->io_buffer_head = bh;
+ ioend->io_buffer_tail = bh;
+ if (previous)
+ previous->io_list = ioend;
+ *result = ioend;
+ } else {
+ ioend->io_buffer_tail->b_private = bh;
+ ioend->io_buffer_tail = bh;
+ }
- if (full_offset < iomapp->iomap_offset)
- return NULL;
- if (iomapp->iomap_offset + (iomapp->iomap_bsize -1) >= full_offset)
- return iomapp;
- return NULL;
+ bh->b_private = NULL;
+ ioend->io_size += bh->b_size;
}
STATIC void
xfs_map_at_offset(
- struct page *page,
struct buffer_head *bh,
- unsigned long offset,
+ loff_t offset,
int block_bits,
xfs_iomap_t *iomapp)
{
xfs_daddr_t bn;
- loff_t delta;
int sector_shift;
ASSERT(!(iomapp->iomap_flags & IOMAP_HOLE));
ASSERT(!(iomapp->iomap_flags & IOMAP_DELAY));
ASSERT(iomapp->iomap_bn != IOMAP_DADDR_NULL);
- delta = page->index;
- delta <<= PAGE_CACHE_SHIFT;
- delta += offset;
- delta -= iomapp->iomap_offset;
- delta >>= block_bits;
-
sector_shift = block_bits - BBSHIFT;
- bn = iomapp->iomap_bn >> sector_shift;
- bn += delta;
- BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME));
+ bn = (iomapp->iomap_bn >> sector_shift) +
+ ((offset - iomapp->iomap_offset) >> block_bits);
+
+ ASSERT(bn || (iomapp->iomap_flags & IOMAP_REALTIME));
ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
lock_buffer(bh);
bh->b_blocknr = bn;
- bh->b_bdev = iomapp->iomap_target->pbr_bdev;
+ bh->b_bdev = iomapp->iomap_target->bt_bdev;
set_buffer_mapped(bh);
clear_buffer_delay(bh);
+ clear_buffer_unwritten(bh);
}
/*
- * Look for a page at index which is unlocked and contains our
- * unwritten extent flagged buffers at its head. Returns page
- * locked and with an extra reference count, and length of the
- * unwritten extent component on this page that we can write,
- * in units of filesystem blocks.
- */
-STATIC struct page *
-xfs_probe_unwritten_page(
- struct address_space *mapping,
- pgoff_t index,
- xfs_iomap_t *iomapp,
- xfs_ioend_t *ioend,
- unsigned long max_offset,
- unsigned long *fsbs,
- unsigned int bbits)
-{
- struct page *page;
-
- page = find_trylock_page(mapping, index);
- if (!page)
- return NULL;
- if (PageWriteback(page))
- goto out;
-
- if (page->mapping && page_has_buffers(page)) {
- struct buffer_head *bh, *head;
- unsigned long p_offset = 0;
-
- *fsbs = 0;
- bh = head = page_buffers(page);
- do {
- if (!buffer_unwritten(bh) || !buffer_uptodate(bh))
- break;
- if (!xfs_offset_to_map(page, iomapp, p_offset))
- break;
- if (p_offset >= max_offset)
- break;
- xfs_map_at_offset(page, bh, p_offset, bbits, iomapp);
- set_buffer_unwritten_io(bh);
- bh->b_private = ioend;
- p_offset += bh->b_size;
- (*fsbs)++;
- } while ((bh = bh->b_this_page) != head);
-
- if (p_offset)
- return page;
- }
-
-out:
- unlock_page(page);
- return NULL;
-}
-
-/*
- * Look for a page at index which is unlocked and not mapped
- * yet - clustering for mmap write case.
+ * Look for a page at index that is suitable for clustering.
*/
STATIC unsigned int
-xfs_probe_unmapped_page(
- struct address_space *mapping,
- pgoff_t index,
- unsigned int pg_offset)
+xfs_probe_page(
+ struct page *page,
+ unsigned int pg_offset,
+ int mapped)
{
- struct page *page;
int ret = 0;
- page = find_trylock_page(mapping, index);
- if (!page)
- return 0;
if (PageWriteback(page))
- goto out;
+ return 0;
if (page->mapping && PageDirty(page)) {
if (page_has_buffers(page)) {
@@ -357,79 +510,101 @@ xfs_probe_unmapped_page(
bh = head = page_buffers(page);
do {
- if (buffer_mapped(bh) || !buffer_uptodate(bh))
+ if (!buffer_uptodate(bh))
+ break;
+ if (mapped != buffer_mapped(bh))
break;
ret += bh->b_size;
if (ret >= pg_offset)
break;
} while ((bh = bh->b_this_page) != head);
} else
- ret = PAGE_CACHE_SIZE;
+ ret = mapped ? 0 : PAGE_CACHE_SIZE;
}
-out:
- unlock_page(page);
return ret;
}
-STATIC unsigned int
-xfs_probe_unmapped_cluster(
+STATIC size_t
+xfs_probe_cluster(
struct inode *inode,
struct page *startpage,
struct buffer_head *bh,
- struct buffer_head *head)
+ struct buffer_head *head,
+ int mapped)
{
+ struct pagevec pvec;
pgoff_t tindex, tlast, tloff;
- unsigned int pg_offset, len, total = 0;
- struct address_space *mapping = inode->i_mapping;
+ size_t total = 0;
+ int done = 0, i;
/* First sum forwards in this page */
do {
- if (buffer_mapped(bh))
- break;
+ if (mapped != buffer_mapped(bh))
+ return total;
total += bh->b_size;
} while ((bh = bh->b_this_page) != head);
- /* If we reached the end of the page, sum forwards in
- * following pages.
- */
- if (bh == head) {
- tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT;
- /* Prune this back to avoid pathological behavior */
- tloff = min(tlast, startpage->index + 64);
- for (tindex = startpage->index + 1; tindex < tloff; tindex++) {
- len = xfs_probe_unmapped_page(mapping, tindex,
- PAGE_CACHE_SIZE);
- if (!len)
- return total;
+ /* if we reached the end of the page, sum forwards in following pages */
+ tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT;
+ tindex = startpage->index + 1;
+
+ /* Prune this back to avoid pathological behavior */
+ tloff = min(tlast, startpage->index + 64);
+
+ pagevec_init(&pvec, 0);
+ while (!done && tindex <= tloff) {
+ unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1);
+
+ if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len))
+ break;
+
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ struct page *page = pvec.pages[i];
+ size_t pg_offset, len = 0;
+
+ if (tindex == tlast) {
+ pg_offset =
+ i_size_read(inode) & (PAGE_CACHE_SIZE - 1);
+ if (!pg_offset) {
+ done = 1;
+ break;
+ }
+ } else
+ pg_offset = PAGE_CACHE_SIZE;
+
+ if (page->index == tindex && !TestSetPageLocked(page)) {
+ len = xfs_probe_page(page, pg_offset, mapped);
+ unlock_page(page);
+ }
+
+ if (!len) {
+ done = 1;
+ break;
+ }
+
total += len;
+ tindex++;
}
- if (tindex == tlast &&
- (pg_offset = i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) {
- total += xfs_probe_unmapped_page(mapping,
- tindex, pg_offset);
- }
+
+ pagevec_release(&pvec);
+ cond_resched();
}
+
return total;
}
/*
- * Probe for a given page (index) in the inode and test if it is delayed
- * and without unwritten buffers. Returns page locked and with an extra
- * reference count.
+ * Test if a given page is suitable for writing as part of an unwritten
+ * or delayed allocate extent.
*/
-STATIC struct page *
-xfs_probe_delalloc_page(
- struct inode *inode,
- pgoff_t index)
+STATIC int
+xfs_is_delayed_page(
+ struct page *page,
+ unsigned int type)
{
- struct page *page;
-
- page = find_trylock_page(inode->i_mapping, index);
- if (!page)
- return NULL;
if (PageWriteback(page))
- goto out;
+ return 0;
if (page->mapping && page_has_buffers(page)) {
struct buffer_head *bh, *head;
@@ -437,243 +612,156 @@ xfs_probe_delalloc_page(
bh = head = page_buffers(page);
do {
- if (buffer_unwritten(bh)) {
- acceptable = 0;
+ if (buffer_unwritten(bh))
+ acceptable = (type == IOMAP_UNWRITTEN);
+ else if (buffer_delay(bh))
+ acceptable = (type == IOMAP_DELAY);
+ else if (buffer_mapped(bh))
+ acceptable = (type == 0);
+ else
break;
- } else if (buffer_delay(bh)) {
- acceptable = 1;
- }
} while ((bh = bh->b_this_page) != head);
if (acceptable)
- return page;
- }
-
-out:
- unlock_page(page);
- return NULL;
-}
-
-STATIC int
-xfs_map_unwritten(
- struct inode *inode,
- struct page *start_page,
- struct buffer_head *head,
- struct buffer_head *curr,
- unsigned long p_offset,
- int block_bits,
- xfs_iomap_t *iomapp,
- struct writeback_control *wbc,
- int startio,
- int all_bh)
-{
- struct buffer_head *bh = curr;
- xfs_iomap_t *tmp;
- xfs_ioend_t *ioend;
- loff_t offset;
- unsigned long nblocks = 0;
-
- offset = start_page->index;
- offset <<= PAGE_CACHE_SHIFT;
- offset += p_offset;
-
- ioend = xfs_alloc_ioend(inode);
-
- /* First map forwards in the page consecutive buffers
- * covering this unwritten extent
- */
- do {
- if (!buffer_unwritten(bh))
- break;
- tmp = xfs_offset_to_map(start_page, iomapp, p_offset);
- if (!tmp)
- break;
- xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp);
- set_buffer_unwritten_io(bh);
- bh->b_private = ioend;
- p_offset += bh->b_size;
- nblocks++;
- } while ((bh = bh->b_this_page) != head);
-
- 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.
- */
- if (bh == head) {
- struct address_space *mapping = inode->i_mapping;
- pgoff_t tindex, tloff, tlast;
- unsigned long bs;
- unsigned int pg_offset, bbits = inode->i_blkbits;
- struct page *page;
-
- tlast = i_size_read(inode) >> PAGE_CACHE_SHIFT;
- tloff = (iomapp->iomap_offset + iomapp->iomap_bsize) >> PAGE_CACHE_SHIFT;
- tloff = min(tlast, tloff);
- for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
- page = xfs_probe_unwritten_page(mapping,
- tindex, iomapp, ioend,
- PAGE_CACHE_SIZE, &bs, bbits);
- if (!page)
- break;
- nblocks += bs;
- 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
- * count won't fit in our ulong page buf length */
- if (nblocks >= ((ULONG_MAX - PAGE_SIZE) >> block_bits))
- goto enough;
- }
-
- if (tindex == tlast &&
- (pg_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)))) {
- page = xfs_probe_unwritten_page(mapping,
- tindex, iomapp, ioend,
- pg_offset, &bs, bbits);
- if (page) {
- nblocks += bs;
- 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;
- }
- }
+ return 1;
}
-enough:
- ioend->io_size = (xfs_off_t)nblocks << block_bits;
- ioend->io_offset = offset;
- xfs_finish_ioend(ioend);
return 0;
}
-STATIC void
-xfs_submit_page(
- struct page *page,
- struct writeback_control *wbc,
- struct buffer_head *bh_arr[],
- int bh_count,
- int probed_page,
- int clear_dirty)
-{
- struct buffer_head *bh;
- int i;
-
- BUG_ON(PageWriteback(page));
- if (bh_count)
- set_page_writeback(page);
- if (clear_dirty)
- clear_page_dirty(page);
- unlock_page(page);
-
- if (bh_count) {
- for (i = 0; i < bh_count; i++) {
- bh = bh_arr[i];
- mark_buffer_async_write(bh);
- if (buffer_unwritten(bh))
- set_buffer_unwritten_io(bh);
- set_buffer_uptodate(bh);
- clear_buffer_dirty(bh);
- }
-
- for (i = 0; i < bh_count; i++)
- submit_bh(WRITE, bh_arr[i]);
-
- if (probed_page && clear_dirty)
- wbc->nr_to_write--; /* Wrote an "extra" page */
- }
-}
-
/*
* Allocate & map buffers for page given the extent map. Write it out.
* except for the original page of a writepage, this is called on
* delalloc/unwritten pages only, for the original page it is possible
* that the page has no mapping at all.
*/
-STATIC void
+STATIC int
xfs_convert_page(
struct inode *inode,
struct page *page,
- xfs_iomap_t *iomapp,
+ loff_t tindex,
+ xfs_iomap_t *mp,
+ xfs_ioend_t **ioendp,
struct writeback_control *wbc,
- void *private,
int startio,
int all_bh)
{
- struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
- xfs_iomap_t *mp = iomapp, *tmp;
- unsigned long offset, end_offset;
- int index = 0;
+ struct buffer_head *bh, *head;
+ xfs_off_t end_offset;
+ unsigned long p_offset;
+ unsigned int type;
int bbits = inode->i_blkbits;
int len, page_dirty;
+ int count = 0, done = 0, uptodate = 1;
+ xfs_off_t offset = page_offset(page);
- end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1));
+ if (page->index != tindex)
+ goto fail;
+ if (TestSetPageLocked(page))
+ goto fail;
+ if (PageWriteback(page))
+ goto fail_unlock_page;
+ if (page->mapping != inode->i_mapping)
+ goto fail_unlock_page;
+ if (!xfs_is_delayed_page(page, (*ioendp)->io_type))
+ goto fail_unlock_page;
/*
* page_dirty is initially a count of buffers on the page before
* EOF and is decrememted as we move each into a cleanable state.
+ *
+ * Derivation:
+ *
+ * End offset is the highest offset that this page should represent.
+ * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1))
+ * will evaluate non-zero and be less than PAGE_CACHE_SIZE and
+ * hence give us the correct page_dirty count. On any other page,
+ * it will be zero and in that case we need page_dirty to be the
+ * count of buffers on the page.
*/
+ end_offset = min_t(unsigned long long,
+ (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT,
+ i_size_read(inode));
+
len = 1 << inode->i_blkbits;
- end_offset = max(end_offset, PAGE_CACHE_SIZE);
- end_offset = roundup(end_offset, len);
- page_dirty = end_offset / len;
+ p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1),
+ PAGE_CACHE_SIZE);
+ p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE;
+ page_dirty = p_offset / len;
- offset = 0;
bh = head = page_buffers(page);
do {
if (offset >= end_offset)
break;
- if (!(PageUptodate(page) || buffer_uptodate(bh)))
+ if (!buffer_uptodate(bh))
+ uptodate = 0;
+ if (!(PageUptodate(page) || buffer_uptodate(bh))) {
+ done = 1;
continue;
- if (buffer_mapped(bh) && all_bh &&
- !(buffer_unwritten(bh) || buffer_delay(bh))) {
+ }
+
+ if (buffer_unwritten(bh) || buffer_delay(bh)) {
+ if (buffer_unwritten(bh))
+ type = IOMAP_UNWRITTEN;
+ else
+ type = IOMAP_DELAY;
+
+ if (!xfs_iomap_valid(mp, offset)) {
+ done = 1;
+ continue;
+ }
+
+ ASSERT(!(mp->iomap_flags & IOMAP_HOLE));
+ ASSERT(!(mp->iomap_flags & IOMAP_DELAY));
+
+ xfs_map_at_offset(bh, offset, bbits, mp);
if (startio) {
+ xfs_add_to_ioend(inode, bh, offset,
+ type, ioendp, done);
+ } else {
+ set_buffer_dirty(bh);
+ unlock_buffer(bh);
+ mark_buffer_dirty(bh);
+ }
+ page_dirty--;
+ count++;
+ } else {
+ type = 0;
+ if (buffer_mapped(bh) && all_bh && startio) {
lock_buffer(bh);
- bh_arr[index++] = bh;
+ xfs_add_to_ioend(inode, bh, offset,
+ type, ioendp, done);
+ count++;
page_dirty--;
+ } else {
+ done = 1;
}
- continue;
}
- tmp = xfs_offset_to_map(page, mp, offset);
- if (!tmp)
- continue;
- ASSERT(!(tmp->iomap_flags & IOMAP_HOLE));
- ASSERT(!(tmp->iomap_flags & IOMAP_DELAY));
+ } while (offset += len, (bh = bh->b_this_page) != head);
- /* If this is a new unwritten extent buffer (i.e. one
- * that we haven't passed in private data for, we must
- * now map this buffer too.
- */
- if (buffer_unwritten(bh) && !bh->b_end_io) {
- ASSERT(tmp->iomap_flags & IOMAP_UNWRITTEN);
- xfs_map_unwritten(inode, page, head, bh, offset,
- bbits, tmp, wbc, startio, all_bh);
- } else if (! (buffer_unwritten(bh) && buffer_locked(bh))) {
- xfs_map_at_offset(page, bh, offset, bbits, tmp);
- if (buffer_unwritten(bh)) {
- set_buffer_unwritten_io(bh);
- bh->b_private = private;
- ASSERT(private);
+ if (uptodate && bh == head)
+ SetPageUptodate(page);
+
+ if (startio) {
+ if (count) {
+ struct backing_dev_info *bdi;
+
+ bdi = inode->i_mapping->backing_dev_info;
+ if (bdi_write_congested(bdi)) {
+ wbc->encountered_congestion = 1;
+ done = 1;
+ } else if (--wbc->nr_to_write <= 0) {
+ done = 1;
}
}
- if (startio) {
- bh_arr[index++] = bh;
- } else {
- set_buffer_dirty(bh);
- unlock_buffer(bh);
- mark_buffer_dirty(bh);
- }
- page_dirty--;
- } while (offset += len, (bh = bh->b_this_page) != head);
-
- if (startio && index) {
- xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty);
- } else {
- unlock_page(page);
+ xfs_start_page_writeback(page, wbc, !page_dirty, count);
}
+
+ return done;
+ fail_unlock_page:
+ unlock_page(page);
+ fail:
+ return 1;
}
/*
@@ -685,19 +773,31 @@ xfs_cluster_write(
struct inode *inode,
pgoff_t tindex,
xfs_iomap_t *iomapp,
+ xfs_ioend_t **ioendp,
struct writeback_control *wbc,
int startio,
int all_bh,
pgoff_t tlast)
{
- struct page *page;
+ struct pagevec pvec;
+ int done = 0, i;
+
+ pagevec_init(&pvec, 0);
+ while (!done && tindex <= tlast) {
+ unsigned len = min_t(pgoff_t, PAGEVEC_SIZE, tlast - tindex + 1);
- for (; tindex <= tlast; tindex++) {
- page = xfs_probe_delalloc_page(inode, tindex);
- if (!page)
+ if (!pagevec_lookup(&pvec, inode->i_mapping, tindex, len))
break;
- xfs_convert_page(inode, page, iomapp, wbc, NULL,
- startio, all_bh);
+
+ for (i = 0; i < pagevec_count(&pvec); i++) {
+ done = xfs_convert_page(inode, pvec.pages[i], tindex++,
+ iomapp, ioendp, wbc, startio, all_bh);
+ if (done)
+ break;
+ }
+
+ pagevec_release(&pvec);
+ cond_resched();
}
}
@@ -728,18 +828,22 @@ xfs_page_state_convert(
int startio,
int unmapped) /* also implies page uptodate */
{
- struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
- xfs_iomap_t *iomp, iomap;
+ struct buffer_head *bh, *head;
+ xfs_iomap_t iomap;
+ xfs_ioend_t *ioend = NULL, *iohead = NULL;
loff_t offset;
unsigned long p_offset = 0;
+ unsigned int type;
__uint64_t end_offset;
pgoff_t end_index, last_index, tlast;
- int len, err, i, cnt = 0, uptodate = 1;
- int flags;
- int page_dirty;
+ ssize_t size, len;
+ int flags, err, iomap_valid = 0, uptodate = 1;
+ int page_dirty, count = 0, trylock_flag = 0;
+ int all_bh = unmapped;
/* wait for other IO threads? */
- flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK;
+ if (startio && (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking))
+ trylock_flag |= BMAPI_TRYLOCK;
/* Is this page beyond the end of the file? */
offset = i_size_read(inode);
@@ -754,161 +858,173 @@ xfs_page_state_convert(
}
}
- end_offset = min_t(unsigned long long,
- (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset);
- offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-
/*
* page_dirty is initially a count of buffers on the page before
* EOF and is decrememted as we move each into a cleanable state.
- */
+ *
+ * Derivation:
+ *
+ * End offset is the highest offset that this page should represent.
+ * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1))
+ * will evaluate non-zero and be less than PAGE_CACHE_SIZE and
+ * hence give us the correct page_dirty count. On any other page,
+ * it will be zero and in that case we need page_dirty to be the
+ * count of buffers on the page.
+ */
+ end_offset = min_t(unsigned long long,
+ (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset);
len = 1 << inode->i_blkbits;
- p_offset = max(p_offset, PAGE_CACHE_SIZE);
- p_offset = roundup(p_offset, len);
+ p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1),
+ PAGE_CACHE_SIZE);
+ p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE;
page_dirty = p_offset / len;
- iomp = NULL;
- p_offset = 0;
bh = head = page_buffers(page);
+ offset = page_offset(page);
+ flags = -1;
+ type = 0;
+
+ /* TODO: cleanup count and page_dirty */
do {
if (offset >= end_offset)
break;
if (!buffer_uptodate(bh))
uptodate = 0;
- if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio)
+ if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) {
+ /*
+ * the iomap is actually still valid, but the ioend
+ * isn't. shouldn't happen too often.
+ */
+ iomap_valid = 0;
continue;
-
- if (iomp) {
- iomp = xfs_offset_to_map(page, &iomap, p_offset);
}
+ if (iomap_valid)
+ iomap_valid = xfs_iomap_valid(&iomap, offset);
+
/*
* First case, map an unwritten extent and prepare for
* extent state conversion transaction on completion.
- */
- if (buffer_unwritten(bh)) {
- if (!startio)
- continue;
- if (!iomp) {
- err = xfs_map_blocks(inode, offset, len, &iomap,
- BMAPI_WRITE|BMAPI_IGNSTATE);
- if (err) {
- goto error;
- }
- iomp = xfs_offset_to_map(page, &iomap,
- p_offset);
+ *
+ * Second case, allocate space for a delalloc buffer.
+ * We can return EAGAIN here in the release page case.
+ *
+ * Third case, an unmapped buffer was found, and we are
+ * in a path where we need to write the whole page out.
+ */
+ if (buffer_unwritten(bh) || buffer_delay(bh) ||
+ ((buffer_uptodate(bh) || PageUptodate(page)) &&
+ !buffer_mapped(bh) && (unmapped || startio))) {
+ /*
+ * Make sure we don't use a read-only iomap
+ */
+ if (flags == BMAPI_READ)
+ iomap_valid = 0;
+
+ if (buffer_unwritten(bh)) {
+ type = IOMAP_UNWRITTEN;
+ flags = BMAPI_WRITE|BMAPI_IGNSTATE;
+ } else if (buffer_delay(bh)) {
+ type = IOMAP_DELAY;
+ flags = BMAPI_ALLOCATE;
+ if (!startio)
+ flags |= trylock_flag;
+ } else {
+ type = IOMAP_NEW;
+ flags = BMAPI_WRITE|BMAPI_MMAP;
}
- if (iomp) {
- if (!bh->b_end_io) {
- err = xfs_map_unwritten(inode, page,
- head, bh, p_offset,
- inode->i_blkbits, iomp,
- wbc, startio, unmapped);
- if (err) {
- goto error;
- }
+
+ if (!iomap_valid) {
+ if (type == IOMAP_NEW) {
+ size = xfs_probe_cluster(inode,
+ page, bh, head, 0);
} else {
- set_bit(BH_Lock, &bh->b_state);
+ size = len;
}
- BUG_ON(!buffer_locked(bh));
- bh_arr[cnt++] = bh;
- page_dirty--;
- }
- /*
- * Second case, allocate space for a delalloc buffer.
- * We can return EAGAIN here in the release page case.
- */
- } else if (buffer_delay(bh)) {
- if (!iomp) {
- err = xfs_map_blocks(inode, offset, len, &iomap,
- BMAPI_ALLOCATE | flags);
- if (err) {
+
+ err = xfs_map_blocks(inode, offset, size,
+ &iomap, flags);
+ if (err)
goto error;
- }
- iomp = xfs_offset_to_map(page, &iomap,
- p_offset);
+ iomap_valid = xfs_iomap_valid(&iomap, offset);
}
- if (iomp) {
- xfs_map_at_offset(page, bh, p_offset,
- inode->i_blkbits, iomp);
+ if (iomap_valid) {
+ xfs_map_at_offset(bh, offset,
+ inode->i_blkbits, &iomap);
if (startio) {
- bh_arr[cnt++] = bh;
+ xfs_add_to_ioend(inode, bh, offset,
+ type, &ioend,
+ !iomap_valid);
} else {
set_buffer_dirty(bh);
unlock_buffer(bh);
mark_buffer_dirty(bh);
}
page_dirty--;
+ count++;
+ }
+ } else if (buffer_uptodate(bh) && startio) {
+ /*
+ * we got here because the buffer is already mapped.
+ * That means it must already have extents allocated
+ * underneath it. Map the extent by reading it.
+ */
+ if (!iomap_valid || type != 0) {
+ flags = BMAPI_READ;
+ size = xfs_probe_cluster(inode, page, bh,
+ head, 1);
+ err = xfs_map_blocks(inode, offset, size,
+ &iomap, flags);
+ if (err)
+ goto error;
+ iomap_valid = xfs_iomap_valid(&iomap, offset);
}
- } else if ((buffer_uptodate(bh) || PageUptodate(page)) &&
- (unmapped || startio)) {
- if (!buffer_mapped(bh)) {
- int size;
-
- /*
- * Getting here implies an unmapped buffer
- * was found, and we are in a path where we
- * need to write the whole page out.
- */
- if (!iomp) {
- size = xfs_probe_unmapped_cluster(
- inode, page, bh, head);
- err = xfs_map_blocks(inode, offset,
- size, &iomap,
- BMAPI_WRITE|BMAPI_MMAP);
- if (err) {
- goto error;
- }
- iomp = xfs_offset_to_map(page, &iomap,
- p_offset);
- }
- if (iomp) {
- xfs_map_at_offset(page,
- bh, p_offset,
- inode->i_blkbits, iomp);
- if (startio) {
- bh_arr[cnt++] = bh;
- } else {
- set_buffer_dirty(bh);
- unlock_buffer(bh);
- mark_buffer_dirty(bh);
- }
- page_dirty--;
- }
- } else if (startio) {
- if (buffer_uptodate(bh) &&
- !test_and_set_bit(BH_Lock, &bh->b_state)) {
- bh_arr[cnt++] = bh;
- page_dirty--;
- }
+ type = 0;
+ if (!test_and_set_bit(BH_Lock, &bh->b_state)) {
+ ASSERT(buffer_mapped(bh));
+ if (iomap_valid)
+ all_bh = 1;
+ xfs_add_to_ioend(inode, bh, offset, type,
+ &ioend, !iomap_valid);
+ page_dirty--;
+ count++;
+ } else {
+ iomap_valid = 0;
}
+ } else if ((buffer_uptodate(bh) || PageUptodate(page)) &&
+ (unmapped || startio)) {
+ iomap_valid = 0;
}
- } while (offset += len, p_offset += len,
- ((bh = bh->b_this_page) != head));
+
+ if (!iohead)
+ iohead = ioend;
+
+ } while (offset += len, ((bh = bh->b_this_page) != head));
if (uptodate && bh == head)
SetPageUptodate(page);
- if (startio) {
- xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
- }
+ if (startio)
+ xfs_start_page_writeback(page, wbc, 1, count);
- if (iomp) {
- offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
+ if (ioend && iomap_valid) {
+ offset = (iomap.iomap_offset + iomap.iomap_bsize - 1) >>
PAGE_CACHE_SHIFT;
tlast = min_t(pgoff_t, offset, last_index);
- xfs_cluster_write(inode, page->index + 1, iomp, wbc,
- startio, unmapped, tlast);
+ xfs_cluster_write(inode, page->index + 1, &iomap, &ioend,
+ wbc, startio, all_bh, tlast);
}
+ if (iohead)
+ xfs_submit_ioend(iohead);
+
return page_dirty;
error:
- for (i = 0; i < cnt; i++) {
- unlock_buffer(bh_arr[i]);
- }
+ if (iohead)
+ xfs_cancel_ioend(iohead);
/*
* If it's delalloc and we have nowhere to put it,
@@ -916,9 +1032,8 @@ error:
* us to try again.
*/
if (err != -EAGAIN) {
- if (!unmapped) {
+ if (!unmapped)
block_invalidatepage(page, 0);
- }
ClearPageUptodate(page);
}
return err;
@@ -982,7 +1097,7 @@ __linvfs_get_block(
}
/* If this is a realtime file, data might be on a new device */
- bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
+ bh_result->b_bdev = iomap.iomap_target->bt_bdev;
/* If we previously allocated a block out beyond eof and
* we are now coming back to use it then we will need to
@@ -1094,10 +1209,10 @@ linvfs_direct_IO(
if (error)
return -error;
- iocb->private = xfs_alloc_ioend(inode);
+ iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN);
ret = blockdev_direct_IO_own_locking(rw, iocb, inode,
- iomap.iomap_target->pbr_bdev,
+ iomap.iomap_target->bt_bdev,
iov, offset, nr_segs,
linvfs_get_blocks_direct,
linvfs_end_io_direct);
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 4720758a9ade..55339dd5a30d 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -23,14 +23,24 @@ extern mempool_t *xfs_ioend_pool;
typedef void (*xfs_ioend_func_t)(void *);
+/*
+ * xfs_ioend struct manages large extent writes for XFS.
+ * It can manage several multi-page bio's at once.
+ */
typedef struct xfs_ioend {
+ struct xfs_ioend *io_list; /* next ioend in chain */
+ unsigned int io_type; /* delalloc / unwritten */
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 */
+ struct buffer_head *io_buffer_tail;/* buffer linked list tail */
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;
+extern struct address_space_operations linvfs_aops;
+extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
+
#endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 6fe21d2b8847..e44b7c1a3a36 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -31,76 +31,77 @@
#include <linux/kthread.h>
#include "xfs_linux.h"
-STATIC kmem_cache_t *pagebuf_zone;
-STATIC kmem_shaker_t pagebuf_shake;
+STATIC kmem_zone_t *xfs_buf_zone;
+STATIC kmem_shaker_t xfs_buf_shake;
+STATIC int xfsbufd(void *);
STATIC int xfsbufd_wakeup(int, gfp_t);
-STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
+STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
STATIC struct workqueue_struct *xfslogd_workqueue;
struct workqueue_struct *xfsdatad_workqueue;
-#ifdef PAGEBUF_TRACE
+#ifdef XFS_BUF_TRACE
void
-pagebuf_trace(
- xfs_buf_t *pb,
+xfs_buf_trace(
+ xfs_buf_t *bp,
char *id,
void *data,
void *ra)
{
- ktrace_enter(pagebuf_trace_buf,
- pb, id,
- (void *)(unsigned long)pb->pb_flags,
- (void *)(unsigned long)pb->pb_hold.counter,
- (void *)(unsigned long)pb->pb_sema.count.counter,
+ ktrace_enter(xfs_buf_trace_buf,
+ bp, id,
+ (void *)(unsigned long)bp->b_flags,
+ (void *)(unsigned long)bp->b_hold.counter,
+ (void *)(unsigned long)bp->b_sema.count.counter,
(void *)current,
data, ra,
- (void *)(unsigned long)((pb->pb_file_offset>>32) & 0xffffffff),
- (void *)(unsigned long)(pb->pb_file_offset & 0xffffffff),
- (void *)(unsigned long)pb->pb_buffer_length,
+ (void *)(unsigned long)((bp->b_file_offset>>32) & 0xffffffff),
+ (void *)(unsigned long)(bp->b_file_offset & 0xffffffff),
+ (void *)(unsigned long)bp->b_buffer_length,
NULL, NULL, NULL, NULL, NULL);
}
-ktrace_t *pagebuf_trace_buf;
-#define PAGEBUF_TRACE_SIZE 4096
-#define PB_TRACE(pb, id, data) \
- pagebuf_trace(pb, id, (void *)data, (void *)__builtin_return_address(0))
+ktrace_t *xfs_buf_trace_buf;
+#define XFS_BUF_TRACE_SIZE 4096
+#define XB_TRACE(bp, id, data) \
+ xfs_buf_trace(bp, id, (void *)data, (void *)__builtin_return_address(0))
#else
-#define PB_TRACE(pb, id, data) do { } while (0)
+#define XB_TRACE(bp, id, data) do { } while (0)
#endif
-#ifdef PAGEBUF_LOCK_TRACKING
-# define PB_SET_OWNER(pb) ((pb)->pb_last_holder = current->pid)
-# define PB_CLEAR_OWNER(pb) ((pb)->pb_last_holder = -1)
-# define PB_GET_OWNER(pb) ((pb)->pb_last_holder)
+#ifdef XFS_BUF_LOCK_TRACKING
+# define XB_SET_OWNER(bp) ((bp)->b_last_holder = current->pid)
+# define XB_CLEAR_OWNER(bp) ((bp)->b_last_holder = -1)
+# define XB_GET_OWNER(bp) ((bp)->b_last_holder)
#else
-# define PB_SET_OWNER(pb) do { } while (0)
-# define PB_CLEAR_OWNER(pb) do { } while (0)
-# define PB_GET_OWNER(pb) do { } while (0)
+# define XB_SET_OWNER(bp) do { } while (0)
+# define XB_CLEAR_OWNER(bp) do { } while (0)
+# define XB_GET_OWNER(bp) do { } while (0)
#endif
-#define pb_to_gfp(flags) \
- ((((flags) & PBF_READ_AHEAD) ? __GFP_NORETRY : \
- ((flags) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) | __GFP_NOWARN)
+#define xb_to_gfp(flags) \
+ ((((flags) & XBF_READ_AHEAD) ? __GFP_NORETRY : \
+ ((flags) & XBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL) | __GFP_NOWARN)
-#define pb_to_km(flags) \
- (((flags) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
+#define xb_to_km(flags) \
+ (((flags) & XBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
-#define pagebuf_allocate(flags) \
- kmem_zone_alloc(pagebuf_zone, pb_to_km(flags))
-#define pagebuf_deallocate(pb) \
- kmem_zone_free(pagebuf_zone, (pb));
+#define xfs_buf_allocate(flags) \
+ kmem_zone_alloc(xfs_buf_zone, xb_to_km(flags))
+#define xfs_buf_deallocate(bp) \
+ kmem_zone_free(xfs_buf_zone, (bp));
/*
- * Page Region interfaces.
+ * Page Region interfaces.
*
- * For pages in filesystems where the blocksize is smaller than the
- * pagesize, we use the page->private field (long) to hold a bitmap
- * of uptodate regions within the page.
+ * For pages in filesystems where the blocksize is smaller than the
+ * pagesize, we use the page->private field (long) to hold a bitmap
+ * of uptodate regions within the page.
*
- * Each such region is "bytes per page / bits per long" bytes long.
+ * Each such region is "bytes per page / bits per long" bytes long.
*
- * NBPPR == number-of-bytes-per-page-region
- * BTOPR == bytes-to-page-region (rounded up)
- * BTOPRT == bytes-to-page-region-truncated (rounded down)
+ * NBPPR == number-of-bytes-per-page-region
+ * BTOPR == bytes-to-page-region (rounded up)
+ * BTOPRT == bytes-to-page-region-truncated (rounded down)
*/
#if (BITS_PER_LONG == 32)
#define PRSHIFT (PAGE_CACHE_SHIFT - 5) /* (32 == 1<<5) */
@@ -159,7 +160,7 @@ test_page_region(
}
/*
- * Mapping of multi-page buffers into contiguous virtual space
+ * Mapping of multi-page buffers into contiguous virtual space
*/
typedef struct a_list {
@@ -172,7 +173,7 @@ STATIC int as_list_len;
STATIC DEFINE_SPINLOCK(as_lock);
/*
- * Try to batch vunmaps because they are costly.
+ * Try to batch vunmaps because they are costly.
*/
STATIC void
free_address(
@@ -215,83 +216,83 @@ purge_addresses(void)
}
/*
- * Internal pagebuf object manipulation
+ * Internal xfs_buf_t object manipulation
*/
STATIC void
-_pagebuf_initialize(
- xfs_buf_t *pb,
+_xfs_buf_initialize(
+ xfs_buf_t *bp,
xfs_buftarg_t *target,
- loff_t range_base,
+ xfs_off_t range_base,
size_t range_length,
- page_buf_flags_t flags)
+ xfs_buf_flags_t flags)
{
/*
- * We don't want certain flags to appear in pb->pb_flags.
+ * We don't want certain flags to appear in b_flags.
*/
- flags &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD);
-
- memset(pb, 0, sizeof(xfs_buf_t));
- atomic_set(&pb->pb_hold, 1);
- init_MUTEX_LOCKED(&pb->pb_iodonesema);
- INIT_LIST_HEAD(&pb->pb_list);
- INIT_LIST_HEAD(&pb->pb_hash_list);
- init_MUTEX_LOCKED(&pb->pb_sema); /* held, no waiters */
- PB_SET_OWNER(pb);
- pb->pb_target = target;
- pb->pb_file_offset = range_base;
+ flags &= ~(XBF_LOCK|XBF_MAPPED|XBF_DONT_BLOCK|XBF_READ_AHEAD);
+
+ memset(bp, 0, sizeof(xfs_buf_t));
+ atomic_set(&bp->b_hold, 1);
+ init_MUTEX_LOCKED(&bp->b_iodonesema);
+ INIT_LIST_HEAD(&bp->b_list);
+ INIT_LIST_HEAD(&bp->b_hash_list);
+ init_MUTEX_LOCKED(&bp->b_sema); /* held, no waiters */
+ XB_SET_OWNER(bp);
+ bp->b_target = target;
+ bp->b_file_offset = range_base;
/*
* Set buffer_length and count_desired to the same value initially.
* I/O routines should use count_desired, which will be the same in
* most cases but may be reset (e.g. XFS recovery).
*/
- pb->pb_buffer_length = pb->pb_count_desired = range_length;
- pb->pb_flags = flags;
- pb->pb_bn = XFS_BUF_DADDR_NULL;
- atomic_set(&pb->pb_pin_count, 0);
- init_waitqueue_head(&pb->pb_waiters);
-
- XFS_STATS_INC(pb_create);
- PB_TRACE(pb, "initialize", target);
+ bp->b_buffer_length = bp->b_count_desired = range_length;
+ bp->b_flags = flags;
+ bp->b_bn = XFS_BUF_DADDR_NULL;
+ atomic_set(&bp->b_pin_count, 0);
+ init_waitqueue_head(&bp->b_waiters);
+
+ XFS_STATS_INC(xb_create);
+ XB_TRACE(bp, "initialize", target);
}
/*
- * Allocate a page array capable of holding a specified number
- * of pages, and point the page buf at it.
+ * Allocate a page array capable of holding a specified number
+ * of pages, and point the page buf at it.
*/
STATIC int
-_pagebuf_get_pages(
- xfs_buf_t *pb,
+_xfs_buf_get_pages(
+ xfs_buf_t *bp,
int page_count,
- page_buf_flags_t flags)
+ xfs_buf_flags_t flags)
{
/* Make sure that we have a page list */
- if (pb->pb_pages == NULL) {
- pb->pb_offset = page_buf_poff(pb->pb_file_offset);
- pb->pb_page_count = page_count;
- if (page_count <= PB_PAGES) {
- pb->pb_pages = pb->pb_page_array;
+ if (bp->b_pages == NULL) {
+ bp->b_offset = xfs_buf_poff(bp->b_file_offset);
+ bp->b_page_count = page_count;
+ if (page_count <= XB_PAGES) {
+ bp->b_pages = bp->b_page_array;
} else {
- pb->pb_pages = kmem_alloc(sizeof(struct page *) *
- page_count, pb_to_km(flags));
- if (pb->pb_pages == NULL)
+ bp->b_pages = kmem_alloc(sizeof(struct page *) *
+ page_count, xb_to_km(flags));
+ if (bp->b_pages == NULL)
return -ENOMEM;
}
- memset(pb->pb_pages, 0, sizeof(struct page *) * page_count);
+ memset(bp->b_pages, 0, sizeof(struct page *) * page_count);
}
return 0;
}
/*
- * Frees pb_pages if it was malloced.
+ * Frees b_pages if it was allocated.
*/
STATIC void
-_pagebuf_free_pages(
+_xfs_buf_free_pages(
xfs_buf_t *bp)
{
- if (bp->pb_pages != bp->pb_page_array) {
- kmem_free(bp->pb_pages,
- bp->pb_page_count * sizeof(struct page *));
+ if (bp->b_pages != bp->b_page_array) {
+ kmem_free(bp->b_pages,
+ bp->b_page_count * sizeof(struct page *));
}
}
@@ -299,79 +300,79 @@ _pagebuf_free_pages(
* Releases the specified buffer.
*
* The modification state of any associated pages is left unchanged.
- * The buffer most not be on any hash - use pagebuf_rele instead for
+ * The buffer most not be on any hash - use xfs_buf_rele instead for
* hashed and refcounted buffers
*/
void
-pagebuf_free(
+xfs_buf_free(
xfs_buf_t *bp)
{
- PB_TRACE(bp, "free", 0);
+ XB_TRACE(bp, "free", 0);
- ASSERT(list_empty(&bp->pb_hash_list));
+ ASSERT(list_empty(&bp->b_hash_list));
- if (bp->pb_flags & _PBF_PAGE_CACHE) {
+ if (bp->b_flags & _XBF_PAGE_CACHE) {
uint i;
- if ((bp->pb_flags & PBF_MAPPED) && (bp->pb_page_count > 1))
- free_address(bp->pb_addr - bp->pb_offset);
+ if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
+ free_address(bp->b_addr - bp->b_offset);
- for (i = 0; i < bp->pb_page_count; i++)
- page_cache_release(bp->pb_pages[i]);
- _pagebuf_free_pages(bp);
- } else if (bp->pb_flags & _PBF_KMEM_ALLOC) {
+ for (i = 0; i < bp->b_page_count; i++)
+ page_cache_release(bp->b_pages[i]);
+ _xfs_buf_free_pages(bp);
+ } else if (bp->b_flags & _XBF_KMEM_ALLOC) {
/*
- * XXX(hch): bp->pb_count_desired might be incorrect (see
- * pagebuf_associate_memory for details), but fortunately
+ * XXX(hch): bp->b_count_desired might be incorrect (see
+ * xfs_buf_associate_memory for details), but fortunately
* the Linux version of kmem_free ignores the len argument..
*/
- kmem_free(bp->pb_addr, bp->pb_count_desired);
- _pagebuf_free_pages(bp);
+ kmem_free(bp->b_addr, bp->b_count_desired);
+ _xfs_buf_free_pages(bp);
}
- pagebuf_deallocate(bp);
+ xfs_buf_deallocate(bp);
}
/*
* Finds all pages for buffer in question and builds it's page list.
*/
STATIC int
-_pagebuf_lookup_pages(
+_xfs_buf_lookup_pages(
xfs_buf_t *bp,
uint flags)
{
- struct address_space *mapping = bp->pb_target->pbr_mapping;
- size_t blocksize = bp->pb_target->pbr_bsize;
- size_t size = bp->pb_count_desired;
+ struct address_space *mapping = bp->b_target->bt_mapping;
+ size_t blocksize = bp->b_target->bt_bsize;
+ size_t size = bp->b_count_desired;
size_t nbytes, offset;
- gfp_t gfp_mask = pb_to_gfp(flags);
+ gfp_t gfp_mask = xb_to_gfp(flags);
unsigned short page_count, i;
pgoff_t first;
- loff_t end;
+ xfs_off_t end;
int error;
- end = bp->pb_file_offset + bp->pb_buffer_length;
- page_count = page_buf_btoc(end) - page_buf_btoct(bp->pb_file_offset);
+ end = bp->b_file_offset + bp->b_buffer_length;
+ page_count = xfs_buf_btoc(end) - xfs_buf_btoct(bp->b_file_offset);
- error = _pagebuf_get_pages(bp, page_count, flags);
+ error = _xfs_buf_get_pages(bp, page_count, flags);
if (unlikely(error))
return error;
- bp->pb_flags |= _PBF_PAGE_CACHE;
+ bp->b_flags |= _XBF_PAGE_CACHE;
- offset = bp->pb_offset;
- first = bp->pb_file_offset >> PAGE_CACHE_SHIFT;
+ offset = bp->b_offset;
+ first = bp->b_file_offset >> PAGE_CACHE_SHIFT;
- for (i = 0; i < bp->pb_page_count; i++) {
+ for (i = 0; i < bp->b_page_count; i++) {
struct page *page;
uint retries = 0;
retry:
page = find_or_create_page(mapping, first + i, gfp_mask);
if (unlikely(page == NULL)) {
- if (flags & PBF_READ_AHEAD) {
- bp->pb_page_count = i;
- for (i = 0; i < bp->pb_page_count; i++)
- unlock_page(bp->pb_pages[i]);
+ if (flags & XBF_READ_AHEAD) {
+ bp->b_page_count = i;
+ for (i = 0; i < bp->b_page_count; i++)
+ unlock_page(bp->b_pages[i]);
return -ENOMEM;
}
@@ -387,13 +388,13 @@ _pagebuf_lookup_pages(
"deadlock in %s (mode:0x%x)\n",
__FUNCTION__, gfp_mask);
- XFS_STATS_INC(pb_page_retries);
+ XFS_STATS_INC(xb_page_retries);
xfsbufd_wakeup(0, gfp_mask);
blk_congestion_wait(WRITE, HZ/50);
goto retry;
}
- XFS_STATS_INC(pb_page_found);
+ XFS_STATS_INC(xb_page_found);
nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset);
size -= nbytes;
@@ -401,27 +402,27 @@ _pagebuf_lookup_pages(
if (!PageUptodate(page)) {
page_count--;
if (blocksize >= PAGE_CACHE_SIZE) {
- if (flags & PBF_READ)
- bp->pb_locked = 1;
+ if (flags & XBF_READ)
+ bp->b_locked = 1;
} else if (!PagePrivate(page)) {
if (test_page_region(page, offset, nbytes))
page_count++;
}
}
- bp->pb_pages[i] = page;
+ bp->b_pages[i] = page;
offset = 0;
}
- if (!bp->pb_locked) {
- for (i = 0; i < bp->pb_page_count; i++)
- unlock_page(bp->pb_pages[i]);
+ if (!bp->b_locked) {
+ for (i = 0; i < bp->b_page_count; i++)
+ unlock_page(bp->b_pages[i]);
}
- if (page_count == bp->pb_page_count)
- bp->pb_flags |= PBF_DONE;
+ if (page_count == bp->b_page_count)
+ bp->b_flags |= XBF_DONE;
- PB_TRACE(bp, "lookup_pages", (long)page_count);
+ XB_TRACE(bp, "lookup_pages", (long)page_count);
return error;
}
@@ -429,23 +430,23 @@ _pagebuf_lookup_pages(
* Map buffer into kernel address-space if nessecary.
*/
STATIC int
-_pagebuf_map_pages(
+_xfs_buf_map_pages(
xfs_buf_t *bp,
uint flags)
{
/* A single page buffer is always mappable */
- if (bp->pb_page_count == 1) {
- bp->pb_addr = page_address(bp->pb_pages[0]) + bp->pb_offset;
- bp->pb_flags |= PBF_MAPPED;
- } else if (flags & PBF_MAPPED) {
+ if (bp->b_page_count == 1) {
+ bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
+ bp->b_flags |= XBF_MAPPED;
+ } else if (flags & XBF_MAPPED) {
if (as_list_len > 64)
purge_addresses();
- bp->pb_addr = vmap(bp->pb_pages, bp->pb_page_count,
- VM_MAP, PAGE_KERNEL);
- if (unlikely(bp->pb_addr == NULL))
+ bp->b_addr = vmap(bp->b_pages, bp->b_page_count,
+ VM_MAP, PAGE_KERNEL);
+ if (unlikely(bp->b_addr == NULL))
return -ENOMEM;
- bp->pb_addr += bp->pb_offset;
- bp->pb_flags |= PBF_MAPPED;
+ bp->b_addr += bp->b_offset;
+ bp->b_flags |= XBF_MAPPED;
}
return 0;
@@ -456,9 +457,7 @@ _pagebuf_map_pages(
*/
/*
- * _pagebuf_find
- *
- * Looks up, and creates if absent, a lockable buffer for
+ * Look up, and creates if absent, a lockable buffer for
* a given range of an inode. The buffer is returned
* locked. If other overlapping buffers exist, they are
* released before the new buffer is created and locked,
@@ -466,55 +465,55 @@ _pagebuf_map_pages(
* are unlocked. No I/O is implied by this call.
*/
xfs_buf_t *
-_pagebuf_find(
+_xfs_buf_find(
xfs_buftarg_t *btp, /* block device target */
- loff_t ioff, /* starting offset of range */
+ xfs_off_t ioff, /* starting offset of range */
size_t isize, /* length of range */
- page_buf_flags_t flags, /* PBF_TRYLOCK */
- xfs_buf_t *new_pb)/* newly allocated buffer */
+ xfs_buf_flags_t flags,
+ xfs_buf_t *new_bp)
{
- loff_t range_base;
+ xfs_off_t range_base;
size_t range_length;
xfs_bufhash_t *hash;
- xfs_buf_t *pb, *n;
+ xfs_buf_t *bp, *n;
range_base = (ioff << BBSHIFT);
range_length = (isize << BBSHIFT);
/* Check for IOs smaller than the sector size / not sector aligned */
- ASSERT(!(range_length < (1 << btp->pbr_sshift)));
- ASSERT(!(range_base & (loff_t)btp->pbr_smask));
+ ASSERT(!(range_length < (1 << btp->bt_sshift)));
+ ASSERT(!(range_base & (xfs_off_t)btp->bt_smask));
hash = &btp->bt_hash[hash_long((unsigned long)ioff, btp->bt_hashshift)];
spin_lock(&hash->bh_lock);
- list_for_each_entry_safe(pb, n, &hash->bh_list, pb_hash_list) {
- ASSERT(btp == pb->pb_target);
- if (pb->pb_file_offset == range_base &&
- pb->pb_buffer_length == range_length) {
+ list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
+ ASSERT(btp == bp->b_target);
+ if (bp->b_file_offset == range_base &&
+ bp->b_buffer_length == range_length) {
/*
- * If we look at something bring it to the
+ * If we look at something, bring it to the
* front of the list for next time.
*/
- atomic_inc(&pb->pb_hold);
- list_move(&pb->pb_hash_list, &hash->bh_list);
+ atomic_inc(&bp->b_hold);
+ list_move(&bp->b_hash_list, &hash->bh_list);
goto found;
}
}
/* No match found */
- if (new_pb) {
- _pagebuf_initialize(new_pb, btp, range_base,
+ if (new_bp) {
+ _xfs_buf_initialize(new_bp, btp, range_base,
range_length, flags);
- new_pb->pb_hash = hash;
- list_add(&new_pb->pb_hash_list, &hash->bh_list);
+ new_bp->b_hash = hash;
+ list_add(&new_bp->b_hash_list, &hash->bh_list);
} else {
- XFS_STATS_INC(pb_miss_locked);
+ XFS_STATS_INC(xb_miss_locked);
}
spin_unlock(&hash->bh_lock);
- return new_pb;
+ return new_bp;
found:
spin_unlock(&hash->bh_lock);
@@ -523,74 +522,72 @@ found:
* if this does not work then we need to drop the
* spinlock and do a hard attempt on the semaphore.
*/
- if (down_trylock(&pb->pb_sema)) {
- if (!(flags & PBF_TRYLOCK)) {
+ if (down_trylock(&bp->b_sema)) {
+ if (!(flags & XBF_TRYLOCK)) {
/* wait for buffer ownership */
- PB_TRACE(pb, "get_lock", 0);
- pagebuf_lock(pb);
- XFS_STATS_INC(pb_get_locked_waited);
+ XB_TRACE(bp, "get_lock", 0);
+ xfs_buf_lock(bp);
+ XFS_STATS_INC(xb_get_locked_waited);
} else {
/* We asked for a trylock and failed, no need
* to look at file offset and length here, we
- * know that this pagebuf at least overlaps our
- * pagebuf and is locked, therefore our buffer
- * either does not exist, or is this buffer
+ * know that this buffer at least overlaps our
+ * buffer and is locked, therefore our buffer
+ * either does not exist, or is this buffer.
*/
-
- pagebuf_rele(pb);
- XFS_STATS_INC(pb_busy_locked);
- return (NULL);
+ xfs_buf_rele(bp);
+ XFS_STATS_INC(xb_busy_locked);
+ return NULL;
}
} else {
/* trylock worked */
- PB_SET_OWNER(pb);
+ XB_SET_OWNER(bp);
}
- if (pb->pb_flags & PBF_STALE) {
- ASSERT((pb->pb_flags & _PBF_DELWRI_Q) == 0);
- pb->pb_flags &= PBF_MAPPED;
+ if (bp->b_flags & XBF_STALE) {
+ ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0);
+ bp->b_flags &= XBF_MAPPED;
}
- PB_TRACE(pb, "got_lock", 0);
- XFS_STATS_INC(pb_get_locked);
- return (pb);
+ XB_TRACE(bp, "got_lock", 0);
+ XFS_STATS_INC(xb_get_locked);
+ return bp;
}
/*
- * xfs_buf_get_flags assembles a buffer covering the specified range.
- *
+ * Assembles a buffer covering the specified range.
* Storage in memory for all portions of the buffer will be allocated,
* although backing storage may not be.
*/
xfs_buf_t *
-xfs_buf_get_flags( /* allocate a buffer */
+xfs_buf_get_flags(
xfs_buftarg_t *target,/* target for buffer */
- loff_t ioff, /* starting offset of range */
+ xfs_off_t ioff, /* starting offset of range */
size_t isize, /* length of range */
- page_buf_flags_t flags) /* PBF_TRYLOCK */
+ xfs_buf_flags_t flags)
{
- xfs_buf_t *pb, *new_pb;
+ xfs_buf_t *bp, *new_bp;
int error = 0, i;
- new_pb = pagebuf_allocate(flags);
- if (unlikely(!new_pb))
+ new_bp = xfs_buf_allocate(flags);
+ if (unlikely(!new_bp))
return NULL;
- pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
- if (pb == new_pb) {
- error = _pagebuf_lookup_pages(pb, flags);
+ bp = _xfs_buf_find(target, ioff, isize, flags, new_bp);
+ if (bp == new_bp) {
+ error = _xfs_buf_lookup_pages(bp, flags);
if (error)
goto no_buffer;
} else {
- pagebuf_deallocate(new_pb);
- if (unlikely(pb == NULL))
+ xfs_buf_deallocate(new_bp);
+ if (unlikely(bp == NULL))
return NULL;
}
- for (i = 0; i < pb->pb_page_count; i++)
- mark_page_accessed(pb->pb_pages[i]);
+ for (i = 0; i < bp->b_page_count; i++)
+ mark_page_accessed(bp->b_pages[i]);
- if (!(pb->pb_flags & PBF_MAPPED)) {
- error = _pagebuf_map_pages(pb, flags);
+ if (!(bp->b_flags & XBF_MAPPED)) {
+ error = _xfs_buf_map_pages(bp, flags);
if (unlikely(error)) {
printk(KERN_WARNING "%s: failed to map pages\n",
__FUNCTION__);
@@ -598,97 +595,97 @@ xfs_buf_get_flags( /* allocate a buffer */
}
}
- XFS_STATS_INC(pb_get);
+ XFS_STATS_INC(xb_get);
/*
* Always fill in the block number now, the mapped cases can do
* their own overlay of this later.
*/
- pb->pb_bn = ioff;
- pb->pb_count_desired = pb->pb_buffer_length;
+ bp->b_bn = ioff;
+ bp->b_count_desired = bp->b_buffer_length;
- PB_TRACE(pb, "get", (unsigned long)flags);
- return pb;
+ XB_TRACE(bp, "get", (unsigned long)flags);
+ return bp;
no_buffer:
- if (flags & (PBF_LOCK | PBF_TRYLOCK))
- pagebuf_unlock(pb);
- pagebuf_rele(pb);
+ if (flags & (XBF_LOCK | XBF_TRYLOCK))
+ xfs_buf_unlock(bp);
+ xfs_buf_rele(bp);
return NULL;
}
xfs_buf_t *
xfs_buf_read_flags(
xfs_buftarg_t *target,
- loff_t ioff,
+ xfs_off_t ioff,
size_t isize,
- page_buf_flags_t flags)
+ xfs_buf_flags_t flags)
{
- xfs_buf_t *pb;
-
- flags |= PBF_READ;
-
- pb = xfs_buf_get_flags(target, ioff, isize, flags);
- if (pb) {
- if (!XFS_BUF_ISDONE(pb)) {
- PB_TRACE(pb, "read", (unsigned long)flags);
- XFS_STATS_INC(pb_get_read);
- pagebuf_iostart(pb, flags);
- } else if (flags & PBF_ASYNC) {
- PB_TRACE(pb, "read_async", (unsigned long)flags);
+ xfs_buf_t *bp;
+
+ flags |= XBF_READ;
+
+ bp = xfs_buf_get_flags(target, ioff, isize, flags);
+ if (bp) {
+ if (!XFS_BUF_ISDONE(bp)) {
+ XB_TRACE(bp, "read", (unsigned long)flags);
+ XFS_STATS_INC(xb_get_read);
+ xfs_buf_iostart(bp, flags);
+ } else if (flags & XBF_ASYNC) {
+ XB_TRACE(bp, "read_async", (unsigned long)flags);
/*
* Read ahead call which is already satisfied,
* drop the buffer
*/
goto no_buffer;
} else {
- PB_TRACE(pb, "read_done", (unsigned long)flags);
+ XB_TRACE(bp, "read_done", (unsigned long)flags);
/* We do not want read in the flags */
- pb->pb_flags &= ~PBF_READ;
+ bp->b_flags &= ~XBF_READ;
}
}
- return pb;
+ return bp;
no_buffer:
- if (flags & (PBF_LOCK | PBF_TRYLOCK))
- pagebuf_unlock(pb);
- pagebuf_rele(pb);
+ if (flags & (XBF_LOCK | XBF_TRYLOCK))
+ xfs_buf_unlock(bp);
+ xfs_buf_rele(bp);
return NULL;
}
/*
- * If we are not low on memory then do the readahead in a deadlock
- * safe manner.
+ * If we are not low on memory then do the readahead in a deadlock
+ * safe manner.
*/
void
-pagebuf_readahead(
+xfs_buf_readahead(
xfs_buftarg_t *target,
- loff_t ioff,
+ xfs_off_t ioff,
size_t isize,
- page_buf_flags_t flags)
+ xfs_buf_flags_t flags)
{
struct backing_dev_info *bdi;
- bdi = target->pbr_mapping->backing_dev_info;
+ bdi = target->bt_mapping->backing_dev_info;
if (bdi_read_congested(bdi))
return;
- flags |= (PBF_TRYLOCK|PBF_ASYNC|PBF_READ_AHEAD);
+ flags |= (XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
xfs_buf_read_flags(target, ioff, isize, flags);
}
xfs_buf_t *
-pagebuf_get_empty(
+xfs_buf_get_empty(
size_t len,
xfs_buftarg_t *target)
{
- xfs_buf_t *pb;
+ xfs_buf_t *bp;
- pb = pagebuf_allocate(0);
- if (pb)
- _pagebuf_initialize(pb, target, 0, len, 0);
- return pb;
+ bp = xfs_buf_allocate(0);
+ if (bp)
+ _xfs_buf_initialize(bp, target, 0, len, 0);
+ return bp;
}
static inline struct page *
@@ -704,8 +701,8 @@ mem_to_page(
}
int
-pagebuf_associate_memory(
- xfs_buf_t *pb,
+xfs_buf_associate_memory(
+ xfs_buf_t *bp,
void *mem,
size_t len)
{
@@ -722,40 +719,40 @@ pagebuf_associate_memory(
page_count++;
/* Free any previous set of page pointers */
- if (pb->pb_pages)
- _pagebuf_free_pages(pb);
+ if (bp->b_pages)
+ _xfs_buf_free_pages(bp);
- pb->pb_pages = NULL;
- pb->pb_addr = mem;
+ bp->b_pages = NULL;
+ bp->b_addr = mem;
- rval = _pagebuf_get_pages(pb, page_count, 0);
+ rval = _xfs_buf_get_pages(bp, page_count, 0);
if (rval)
return rval;
- pb->pb_offset = offset;
+ bp->b_offset = offset;
ptr = (size_t) mem & PAGE_CACHE_MASK;
end = PAGE_CACHE_ALIGN((size_t) mem + len);
end_cur = end;
/* set up first page */
- pb->pb_pages[0] = mem_to_page(mem);
+ bp->b_pages[0] = mem_to_page(mem);
ptr += PAGE_CACHE_SIZE;
- pb->pb_page_count = ++i;
+ bp->b_page_count = ++i;
while (ptr < end) {
- pb->pb_pages[i] = mem_to_page((void *)ptr);
- pb->pb_page_count = ++i;
+ bp->b_pages[i] = mem_to_page((void *)ptr);
+ bp->b_page_count = ++i;
ptr += PAGE_CACHE_SIZE;
}
- pb->pb_locked = 0;
+ bp->b_locked = 0;
- pb->pb_count_desired = pb->pb_buffer_length = len;
- pb->pb_flags |= PBF_MAPPED;
+ bp->b_count_desired = bp->b_buffer_length = len;
+ bp->b_flags |= XBF_MAPPED;
return 0;
}
xfs_buf_t *
-pagebuf_get_no_daddr(
+xfs_buf_get_noaddr(
size_t len,
xfs_buftarg_t *target)
{
@@ -764,10 +761,10 @@ pagebuf_get_no_daddr(
void *data;
int error;
- bp = pagebuf_allocate(0);
+ bp = xfs_buf_allocate(0);
if (unlikely(bp == NULL))
goto fail;
- _pagebuf_initialize(bp, target, 0, len, 0);
+ _xfs_buf_initialize(bp, target, 0, len, 0);
try_again:
data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL);
@@ -776,78 +773,73 @@ pagebuf_get_no_daddr(
/* check whether alignment matches.. */
if ((__psunsigned_t)data !=
- ((__psunsigned_t)data & ~target->pbr_smask)) {
+ ((__psunsigned_t)data & ~target->bt_smask)) {
/* .. else double the size and try again */
kmem_free(data, malloc_len);
malloc_len <<= 1;
goto try_again;
}
- error = pagebuf_associate_memory(bp, data, len);
+ error = xfs_buf_associate_memory(bp, data, len);
if (error)
goto fail_free_mem;
- bp->pb_flags |= _PBF_KMEM_ALLOC;
+ bp->b_flags |= _XBF_KMEM_ALLOC;
- pagebuf_unlock(bp);
+ xfs_buf_unlock(bp);
- PB_TRACE(bp, "no_daddr", data);
+ XB_TRACE(bp, "no_daddr", data);
return bp;
fail_free_mem:
kmem_free(data, malloc_len);
fail_free_buf:
- pagebuf_free(bp);
+ xfs_buf_free(bp);
fail:
return NULL;
}
/*
- * pagebuf_hold
- *
* Increment reference count on buffer, to hold the buffer concurrently
* with another thread which may release (free) the buffer asynchronously.
- *
* Must hold the buffer already to call this function.
*/
void
-pagebuf_hold(
- xfs_buf_t *pb)
+xfs_buf_hold(
+ xfs_buf_t *bp)
{
- atomic_inc(&pb->pb_hold);
- PB_TRACE(pb, "hold", 0);
+ atomic_inc(&bp->b_hold);
+ XB_TRACE(bp, "hold", 0);
}
/*
- * pagebuf_rele
- *
- * pagebuf_rele releases a hold on the specified buffer. If the
- * the hold count is 1, pagebuf_rele calls pagebuf_free.
+ * Releases a hold on the specified buffer. If the
+ * the hold count is 1, calls xfs_buf_free.
*/
void
-pagebuf_rele(
- xfs_buf_t *pb)
+xfs_buf_rele(
+ xfs_buf_t *bp)
{
- xfs_bufhash_t *hash = pb->pb_hash;
+ xfs_bufhash_t *hash = bp->b_hash;
- PB_TRACE(pb, "rele", pb->pb_relse);
+ XB_TRACE(bp, "rele", bp->b_relse);
- if (atomic_dec_and_lock(&pb->pb_hold, &hash->bh_lock)) {
- if (pb->pb_relse) {
- atomic_inc(&pb->pb_hold);
+ if (atomic_dec_and_lock(&bp->b_hold, &hash->bh_lock)) {
+ if (bp->b_relse) {
+ atomic_inc(&bp->b_hold);
spin_unlock(&hash->bh_lock);
- (*(pb->pb_relse)) (pb);
- } else if (pb->pb_flags & PBF_FS_MANAGED) {
+ (*(bp->b_relse)) (bp);
+ } else if (bp->b_flags & XBF_FS_MANAGED) {
spin_unlock(&hash->bh_lock);
} else {
- ASSERT(!(pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q)));
- list_del_init(&pb->pb_hash_list);
+ ASSERT(!(bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)));
+ list_del_init(&bp->b_hash_list);
spin_unlock(&hash->bh_lock);
- pagebuf_free(pb);
+ xfs_buf_free(bp);
}
} else {
/*
* Catch reference count leaks
*/
- ASSERT(atomic_read(&pb->pb_hold) >= 0);
+ ASSERT(atomic_read(&bp->b_hold) >= 0);
}
}
@@ -863,168 +855,122 @@ pagebuf_rele(
*/
/*
- * pagebuf_cond_lock
- *
- * pagebuf_cond_lock locks a buffer object, if it is not already locked.
- * Note that this in no way
- * locks the underlying pages, so it is only useful for synchronizing
- * concurrent use of page buffer objects, not for synchronizing independent
- * access to the underlying pages.
+ * Locks a buffer object, if it is not already locked.
+ * Note that this in no way locks the underlying pages, so it is only
+ * useful for synchronizing concurrent use of buffer objects, not for
+ * synchronizing independent access to the underlying pages.
*/
int
-pagebuf_cond_lock( /* lock buffer, if not locked */
- /* returns -EBUSY if locked) */
- xfs_buf_t *pb)
+xfs_buf_cond_lock(
+ xfs_buf_t *bp)
{
int locked;
- locked = down_trylock(&pb->pb_sema) == 0;
+ locked = down_trylock(&bp->b_sema) == 0;
if (locked) {
- PB_SET_OWNER(pb);
+ XB_SET_OWNER(bp);
}
- PB_TRACE(pb, "cond_lock", (long)locked);
- return(locked ? 0 : -EBUSY);
+ XB_TRACE(bp, "cond_lock", (long)locked);
+ return locked ? 0 : -EBUSY;
}
#if defined(DEBUG) || defined(XFS_BLI_TRACE)
-/*
- * pagebuf_lock_value
- *
- * Return lock value for a pagebuf
- */
int
-pagebuf_lock_value(
- xfs_buf_t *pb)
+xfs_buf_lock_value(
+ xfs_buf_t *bp)
{
- return(atomic_read(&pb->pb_sema.count));
+ return atomic_read(&bp->b_sema.count);
}
#endif
/*
- * pagebuf_lock
- *
- * pagebuf_lock locks a buffer object. Note that this in no way
- * locks the underlying pages, so it is only useful for synchronizing
- * concurrent use of page buffer objects, not for synchronizing independent
- * access to the underlying pages.
+ * Locks a buffer object.
+ * Note that this in no way locks the underlying pages, so it is only
+ * useful for synchronizing concurrent use of buffer objects, not for
+ * synchronizing independent access to the underlying pages.
*/
-int
-pagebuf_lock(
- xfs_buf_t *pb)
+void
+xfs_buf_lock(
+ xfs_buf_t *bp)
{
- PB_TRACE(pb, "lock", 0);
- if (atomic_read(&pb->pb_io_remaining))
- blk_run_address_space(pb->pb_target->pbr_mapping);
- down(&pb->pb_sema);
- PB_SET_OWNER(pb);
- PB_TRACE(pb, "locked", 0);
- return 0;
+ XB_TRACE(bp, "lock", 0);
+ if (atomic_read(&bp->b_io_remaining))
+ blk_run_address_space(bp->b_target->bt_mapping);
+ down(&bp->b_sema);
+ XB_SET_OWNER(bp);
+ XB_TRACE(bp, "locked", 0);
}
/*
- * 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).
- *
+ * Releases the lock on the buffer object.
* 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
+ * 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 */
+xfs_buf_unlock(
+ xfs_buf_t *bp)
{
- 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);
+ if ((bp->b_flags & (XBF_DELWRI|_XBF_DELWRI_Q)) == XBF_DELWRI) {
+ atomic_inc(&bp->b_hold);
+ bp->b_flags |= XBF_ASYNC;
+ xfs_buf_delwri_queue(bp, 0);
}
- PB_CLEAR_OWNER(pb);
- up(&pb->pb_sema);
- PB_TRACE(pb, "unlock", 0);
+ XB_CLEAR_OWNER(bp);
+ up(&bp->b_sema);
+ XB_TRACE(bp, "unlock", 0);
}
/*
* Pinning Buffer Storage in Memory
- */
-
-/*
- * pagebuf_pin
- *
- * pagebuf_pin locks all of the memory represented by a buffer in
- * memory. Multiple calls to pagebuf_pin and pagebuf_unpin, for
- * the same or different buffers affecting a given page, will
- * properly count the number of outstanding "pin" requests. The
- * buffer may be released after the pagebuf_pin and a different
- * buffer used when calling pagebuf_unpin, if desired.
- * pagebuf_pin should be used by the file system when it wants be
- * assured that no attempt will be made to force the affected
- * memory to disk. It does not assure that a given logical page
- * will not be moved to a different physical page.
+ * Ensure that no attempt to force a buffer to disk will succeed.
*/
void
-pagebuf_pin(
- xfs_buf_t *pb)
+xfs_buf_pin(
+ xfs_buf_t *bp)
{
- atomic_inc(&pb->pb_pin_count);
- PB_TRACE(pb, "pin", (long)pb->pb_pin_count.counter);
+ atomic_inc(&bp->b_pin_count);
+ XB_TRACE(bp, "pin", (long)bp->b_pin_count.counter);
}
-/*
- * pagebuf_unpin
- *
- * pagebuf_unpin reverses the locking of memory performed by
- * pagebuf_pin. Note that both functions affected the logical
- * pages associated with the buffer, not the buffer itself.
- */
void
-pagebuf_unpin(
- xfs_buf_t *pb)
+xfs_buf_unpin(
+ xfs_buf_t *bp)
{
- if (atomic_dec_and_test(&pb->pb_pin_count)) {
- wake_up_all(&pb->pb_waiters);
- }
- PB_TRACE(pb, "unpin", (long)pb->pb_pin_count.counter);
+ if (atomic_dec_and_test(&bp->b_pin_count))
+ wake_up_all(&bp->b_waiters);
+ XB_TRACE(bp, "unpin", (long)bp->b_pin_count.counter);
}
int
-pagebuf_ispin(
- xfs_buf_t *pb)
+xfs_buf_ispin(
+ xfs_buf_t *bp)
{
- return atomic_read(&pb->pb_pin_count);
+ return atomic_read(&bp->b_pin_count);
}
-/*
- * pagebuf_wait_unpin
- *
- * pagebuf_wait_unpin waits until all of the memory associated
- * with the buffer is not longer locked in memory. It returns
- * immediately if none of the affected pages are locked.
- */
-static inline void
-_pagebuf_wait_unpin(
- xfs_buf_t *pb)
+STATIC void
+xfs_buf_wait_unpin(
+ xfs_buf_t *bp)
{
DECLARE_WAITQUEUE (wait, current);
- if (atomic_read(&pb->pb_pin_count) == 0)
+ if (atomic_read(&bp->b_pin_count) == 0)
return;
- add_wait_queue(&pb->pb_waiters, &wait);
+ add_wait_queue(&bp->b_waiters, &wait);
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (atomic_read(&pb->pb_pin_count) == 0)
+ if (atomic_read(&bp->b_pin_count) == 0)
break;
- if (atomic_read(&pb->pb_io_remaining))
- blk_run_address_space(pb->pb_target->pbr_mapping);
+ if (atomic_read(&bp->b_io_remaining))
+ blk_run_address_space(bp->b_target->bt_mapping);
schedule();
}
- remove_wait_queue(&pb->pb_waiters, &wait);
+ remove_wait_queue(&bp->b_waiters, &wait);
set_current_state(TASK_RUNNING);
}
@@ -1032,241 +978,216 @@ _pagebuf_wait_unpin(
* Buffer Utility Routines
*/
-/*
- * pagebuf_iodone
- *
- * pagebuf_iodone marks a buffer for which I/O is in progress
- * done with respect to that I/O. The pb_iodone routine, if
- * present, will be called as a side-effect.
- */
STATIC void
-pagebuf_iodone_work(
+xfs_buf_iodone_work(
void *v)
{
xfs_buf_t *bp = (xfs_buf_t *)v;
- if (bp->pb_iodone)
- (*(bp->pb_iodone))(bp);
- else if (bp->pb_flags & PBF_ASYNC)
+ if (bp->b_iodone)
+ (*(bp->b_iodone))(bp);
+ else if (bp->b_flags & XBF_ASYNC)
xfs_buf_relse(bp);
}
void
-pagebuf_iodone(
- xfs_buf_t *pb,
+xfs_buf_ioend(
+ xfs_buf_t *bp,
int schedule)
{
- pb->pb_flags &= ~(PBF_READ | PBF_WRITE);
- if (pb->pb_error == 0)
- pb->pb_flags |= PBF_DONE;
+ bp->b_flags &= ~(XBF_READ | XBF_WRITE);
+ if (bp->b_error == 0)
+ bp->b_flags |= XBF_DONE;
- PB_TRACE(pb, "iodone", pb->pb_iodone);
+ XB_TRACE(bp, "iodone", bp->b_iodone);
- if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
+ if ((bp->b_iodone) || (bp->b_flags & XBF_ASYNC)) {
if (schedule) {
- INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
- queue_work(xfslogd_workqueue, &pb->pb_iodone_work);
+ INIT_WORK(&bp->b_iodone_work, xfs_buf_iodone_work, bp);
+ queue_work(xfslogd_workqueue, &bp->b_iodone_work);
} else {
- pagebuf_iodone_work(pb);
+ xfs_buf_iodone_work(bp);
}
} else {
- up(&pb->pb_iodonesema);
+ up(&bp->b_iodonesema);
}
}
-/*
- * pagebuf_ioerror
- *
- * pagebuf_ioerror sets the error code for a buffer.
- */
void
-pagebuf_ioerror( /* mark/clear buffer error flag */
- xfs_buf_t *pb, /* buffer to mark */
- int error) /* error to store (0 if none) */
+xfs_buf_ioerror(
+ xfs_buf_t *bp,
+ int error)
{
ASSERT(error >= 0 && error <= 0xffff);
- pb->pb_error = (unsigned short)error;
- PB_TRACE(pb, "ioerror", (unsigned long)error);
+ bp->b_error = (unsigned short)error;
+ XB_TRACE(bp, "ioerror", (unsigned long)error);
}
/*
- * pagebuf_iostart
- *
- * pagebuf_iostart initiates I/O on a buffer, based on the flags supplied.
- * If necessary, it will arrange for any disk space allocation required,
- * and it will break up the request if the block mappings require it.
- * The pb_iodone routine in the buffer supplied will only be called
+ * Initiate I/O on a buffer, based on the flags supplied.
+ * The b_iodone routine in the buffer supplied will only be called
* when all of the subsidiary I/O requests, if any, have been completed.
- * pagebuf_iostart calls the pagebuf_ioinitiate routine or
- * pagebuf_iorequest, if the former routine is not defined, to start
- * the I/O on a given low-level request.
*/
int
-pagebuf_iostart( /* start I/O on a buffer */
- xfs_buf_t *pb, /* buffer to start */
- page_buf_flags_t flags) /* PBF_LOCK, PBF_ASYNC, PBF_READ, */
- /* PBF_WRITE, PBF_DELWRI, */
- /* PBF_DONT_BLOCK */
+xfs_buf_iostart(
+ xfs_buf_t *bp,
+ xfs_buf_flags_t flags)
{
int status = 0;
- PB_TRACE(pb, "iostart", (unsigned long)flags);
+ XB_TRACE(bp, "iostart", (unsigned long)flags);
- if (flags & PBF_DELWRI) {
- pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);
- pb->pb_flags |= flags & (PBF_DELWRI | PBF_ASYNC);
- pagebuf_delwri_queue(pb, 1);
+ if (flags & XBF_DELWRI) {
+ bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC);
+ bp->b_flags |= flags & (XBF_DELWRI | XBF_ASYNC);
+ xfs_buf_delwri_queue(bp, 1);
return status;
}
- pb->pb_flags &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \
- PBF_READ_AHEAD | _PBF_RUN_QUEUES);
- pb->pb_flags |= flags & (PBF_READ | PBF_WRITE | PBF_ASYNC | \
- PBF_READ_AHEAD | _PBF_RUN_QUEUES);
+ bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_ASYNC | XBF_DELWRI | \
+ XBF_READ_AHEAD | _XBF_RUN_QUEUES);
+ bp->b_flags |= flags & (XBF_READ | XBF_WRITE | XBF_ASYNC | \
+ XBF_READ_AHEAD | _XBF_RUN_QUEUES);
- BUG_ON(pb->pb_bn == XFS_BUF_DADDR_NULL);
+ BUG_ON(bp->b_bn == XFS_BUF_DADDR_NULL);
/* For writes allow an alternate strategy routine to precede
* the actual I/O request (which may not be issued at all in
* a shutdown situation, for example).
*/
- status = (flags & PBF_WRITE) ?
- pagebuf_iostrategy(pb) : pagebuf_iorequest(pb);
+ status = (flags & XBF_WRITE) ?
+ xfs_buf_iostrategy(bp) : xfs_buf_iorequest(bp);
/* Wait for I/O if we are not an async request.
* Note: async I/O request completion will release the buffer,
* and that can already be done by this point. So using the
* buffer pointer from here on, after async I/O, is invalid.
*/
- if (!status && !(flags & PBF_ASYNC))
- status = pagebuf_iowait(pb);
+ if (!status && !(flags & XBF_ASYNC))
+ status = xfs_buf_iowait(bp);
return status;
}
-/*
- * Helper routine for pagebuf_iorequest
- */
-
STATIC __inline__ int
-_pagebuf_iolocked(
- xfs_buf_t *pb)
+_xfs_buf_iolocked(
+ xfs_buf_t *bp)
{
- ASSERT(pb->pb_flags & (PBF_READ|PBF_WRITE));
- if (pb->pb_flags & PBF_READ)
- return pb->pb_locked;
+ ASSERT(bp->b_flags & (XBF_READ | XBF_WRITE));
+ if (bp->b_flags & XBF_READ)
+ return bp->b_locked;
return 0;
}
STATIC __inline__ void
-_pagebuf_iodone(
- xfs_buf_t *pb,
+_xfs_buf_ioend(
+ xfs_buf_t *bp,
int schedule)
{
- if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
- pb->pb_locked = 0;
- pagebuf_iodone(pb, schedule);
+ if (atomic_dec_and_test(&bp->b_io_remaining) == 1) {
+ bp->b_locked = 0;
+ xfs_buf_ioend(bp, schedule);
}
}
STATIC int
-bio_end_io_pagebuf(
+xfs_buf_bio_end_io(
struct bio *bio,
unsigned int bytes_done,
int error)
{
- xfs_buf_t *pb = (xfs_buf_t *)bio->bi_private;
- unsigned int blocksize = pb->pb_target->pbr_bsize;
+ xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private;
+ unsigned int blocksize = bp->b_target->bt_bsize;
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
if (bio->bi_size)
return 1;
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
- pb->pb_error = EIO;
+ bp->b_error = EIO;
do {
struct page *page = bvec->bv_page;
- if (unlikely(pb->pb_error)) {
- if (pb->pb_flags & PBF_READ)
+ if (unlikely(bp->b_error)) {
+ if (bp->b_flags & XBF_READ)
ClearPageUptodate(page);
SetPageError(page);
- } else if (blocksize == PAGE_CACHE_SIZE) {
+ } else if (blocksize >= PAGE_CACHE_SIZE) {
SetPageUptodate(page);
} else if (!PagePrivate(page) &&
- (pb->pb_flags & _PBF_PAGE_CACHE)) {
+ (bp->b_flags & _XBF_PAGE_CACHE)) {
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)) {
+ if (_xfs_buf_iolocked(bp)) {
unlock_page(page);
}
} while (bvec >= bio->bi_io_vec);
- _pagebuf_iodone(pb, 1);
+ _xfs_buf_ioend(bp, 1);
bio_put(bio);
return 0;
}
STATIC void
-_pagebuf_ioapply(
- xfs_buf_t *pb)
+_xfs_buf_ioapply(
+ xfs_buf_t *bp)
{
int i, rw, map_i, total_nr_pages, nr_pages;
struct bio *bio;
- int offset = pb->pb_offset;
- int size = pb->pb_count_desired;
- sector_t sector = pb->pb_bn;
- unsigned int blocksize = pb->pb_target->pbr_bsize;
- int locking = _pagebuf_iolocked(pb);
+ int offset = bp->b_offset;
+ int size = bp->b_count_desired;
+ sector_t sector = bp->b_bn;
+ unsigned int blocksize = bp->b_target->bt_bsize;
+ int locking = _xfs_buf_iolocked(bp);
- total_nr_pages = pb->pb_page_count;
+ total_nr_pages = bp->b_page_count;
map_i = 0;
- if (pb->pb_flags & _PBF_RUN_QUEUES) {
- pb->pb_flags &= ~_PBF_RUN_QUEUES;
- rw = (pb->pb_flags & PBF_READ) ? READ_SYNC : WRITE_SYNC;
+ if (bp->b_flags & _XBF_RUN_QUEUES) {
+ bp->b_flags &= ~_XBF_RUN_QUEUES;
+ rw = (bp->b_flags & XBF_READ) ? READ_SYNC : WRITE_SYNC;
} else {
- rw = (pb->pb_flags & PBF_READ) ? READ : WRITE;
+ rw = (bp->b_flags & XBF_READ) ? READ : WRITE;
}
- if (pb->pb_flags & PBF_ORDERED) {
- ASSERT(!(pb->pb_flags & PBF_READ));
+ if (bp->b_flags & XBF_ORDERED) {
+ ASSERT(!(bp->b_flags & XBF_READ));
rw = WRITE_BARRIER;
}
- /* Special code path for reading a sub page size pagebuf in --
+ /* Special code path for reading a sub page size buffer in --
* we populate up the whole page, and hence the other metadata
* in the same page. This optimization is only valid when the
- * filesystem block size and the page size are equal.
+ * filesystem block size is not smaller than the page size.
*/
- if ((pb->pb_buffer_length < PAGE_CACHE_SIZE) &&
- (pb->pb_flags & PBF_READ) && locking &&
- (blocksize == PAGE_CACHE_SIZE)) {
+ if ((bp->b_buffer_length < PAGE_CACHE_SIZE) &&
+ (bp->b_flags & XBF_READ) && locking &&
+ (blocksize >= PAGE_CACHE_SIZE)) {
bio = bio_alloc(GFP_NOIO, 1);
- bio->bi_bdev = pb->pb_target->pbr_bdev;
+ bio->bi_bdev = bp->b_target->bt_bdev;
bio->bi_sector = sector - (offset >> BBSHIFT);
- bio->bi_end_io = bio_end_io_pagebuf;
- bio->bi_private = pb;
+ bio->bi_end_io = xfs_buf_bio_end_io;
+ bio->bi_private = bp;
- bio_add_page(bio, pb->pb_pages[0], PAGE_CACHE_SIZE, 0);
+ bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0);
size = 0;
- atomic_inc(&pb->pb_io_remaining);
+ atomic_inc(&bp->b_io_remaining);
goto submit_io;
}
/* Lock down the pages which we need to for the request */
- if (locking && (pb->pb_flags & PBF_WRITE) && (pb->pb_locked == 0)) {
+ if (locking && (bp->b_flags & XBF_WRITE) && (bp->b_locked == 0)) {
for (i = 0; size; i++) {
int nbytes = PAGE_CACHE_SIZE - offset;
- struct page *page = pb->pb_pages[i];
+ struct page *page = bp->b_pages[i];
if (nbytes > size)
nbytes = size;
@@ -1276,30 +1197,30 @@ _pagebuf_ioapply(
size -= nbytes;
offset = 0;
}
- offset = pb->pb_offset;
- size = pb->pb_count_desired;
+ offset = bp->b_offset;
+ size = bp->b_count_desired;
}
next_chunk:
- atomic_inc(&pb->pb_io_remaining);
+ atomic_inc(&bp->b_io_remaining);
nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT);
if (nr_pages > total_nr_pages)
nr_pages = total_nr_pages;
bio = bio_alloc(GFP_NOIO, nr_pages);
- bio->bi_bdev = pb->pb_target->pbr_bdev;
+ bio->bi_bdev = bp->b_target->bt_bdev;
bio->bi_sector = sector;
- bio->bi_end_io = bio_end_io_pagebuf;
- bio->bi_private = pb;
+ bio->bi_end_io = xfs_buf_bio_end_io;
+ bio->bi_private = bp;
for (; size && nr_pages; nr_pages--, map_i++) {
- int nbytes = PAGE_CACHE_SIZE - offset;
+ int rbytes, nbytes = PAGE_CACHE_SIZE - offset;
if (nbytes > size)
nbytes = size;
- if (bio_add_page(bio, pb->pb_pages[map_i],
- nbytes, offset) < nbytes)
+ rbytes = bio_add_page(bio, bp->b_pages[map_i], nbytes, offset);
+ if (rbytes < nbytes)
break;
offset = 0;
@@ -1315,107 +1236,102 @@ submit_io:
goto next_chunk;
} else {
bio_put(bio);
- pagebuf_ioerror(pb, EIO);
+ xfs_buf_ioerror(bp, EIO);
}
}
-/*
- * pagebuf_iorequest -- the core I/O request routine.
- */
int
-pagebuf_iorequest( /* start real I/O */
- xfs_buf_t *pb) /* buffer to convey to device */
+xfs_buf_iorequest(
+ xfs_buf_t *bp)
{
- PB_TRACE(pb, "iorequest", 0);
+ XB_TRACE(bp, "iorequest", 0);
- if (pb->pb_flags & PBF_DELWRI) {
- pagebuf_delwri_queue(pb, 1);
+ if (bp->b_flags & XBF_DELWRI) {
+ xfs_buf_delwri_queue(bp, 1);
return 0;
}
- if (pb->pb_flags & PBF_WRITE) {
- _pagebuf_wait_unpin(pb);
+ if (bp->b_flags & XBF_WRITE) {
+ xfs_buf_wait_unpin(bp);
}
- pagebuf_hold(pb);
+ xfs_buf_hold(bp);
/* 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.
+ * all the I/O from calling xfs_buf_ioend too early.
*/
- atomic_set(&pb->pb_io_remaining, 1);
- _pagebuf_ioapply(pb);
- _pagebuf_iodone(pb, 0);
+ atomic_set(&bp->b_io_remaining, 1);
+ _xfs_buf_ioapply(bp);
+ _xfs_buf_ioend(bp, 0);
- pagebuf_rele(pb);
+ xfs_buf_rele(bp);
return 0;
}
/*
- * pagebuf_iowait
- *
- * pagebuf_iowait waits for I/O to complete on the buffer supplied.
- * It returns immediately if no I/O is pending. In any case, it returns
- * the error code, if any, or 0 if there is no error.
+ * Waits for I/O to complete on the buffer supplied.
+ * It returns immediately if no I/O is pending.
+ * It returns the I/O error code, if any, or 0 if there was no error.
*/
int
-pagebuf_iowait(
- xfs_buf_t *pb)
+xfs_buf_iowait(
+ xfs_buf_t *bp)
{
- PB_TRACE(pb, "iowait", 0);
- if (atomic_read(&pb->pb_io_remaining))
- blk_run_address_space(pb->pb_target->pbr_mapping);
- down(&pb->pb_iodonesema);
- PB_TRACE(pb, "iowaited", (long)pb->pb_error);
- return pb->pb_error;
+ XB_TRACE(bp, "iowait", 0);
+ if (atomic_read(&bp->b_io_remaining))
+ blk_run_address_space(bp->b_target->bt_mapping);
+ down(&bp->b_iodonesema);
+ XB_TRACE(bp, "iowaited", (long)bp->b_error);
+ return bp->b_error;
}
-caddr_t
-pagebuf_offset(
- xfs_buf_t *pb,
+xfs_caddr_t
+xfs_buf_offset(
+ xfs_buf_t *bp,
size_t offset)
{
struct page *page;
- offset += pb->pb_offset;
+ if (bp->b_flags & XBF_MAPPED)
+ return XFS_BUF_PTR(bp) + offset;
- page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT];
- return (caddr_t) page_address(page) + (offset & (PAGE_CACHE_SIZE - 1));
+ offset += bp->b_offset;
+ page = bp->b_pages[offset >> PAGE_CACHE_SHIFT];
+ return (xfs_caddr_t)page_address(page) + (offset & (PAGE_CACHE_SIZE-1));
}
/*
- * pagebuf_iomove
- *
* Move data into or out of a buffer.
*/
void
-pagebuf_iomove(
- xfs_buf_t *pb, /* buffer to process */
+xfs_buf_iomove(
+ xfs_buf_t *bp, /* buffer to process */
size_t boff, /* starting buffer offset */
size_t bsize, /* length to copy */
caddr_t data, /* data address */
- page_buf_rw_t mode) /* read/write flag */
+ xfs_buf_rw_t mode) /* read/write/zero flag */
{
size_t bend, cpoff, csize;
struct page *page;
bend = boff + bsize;
while (boff < bend) {
- page = pb->pb_pages[page_buf_btoct(boff + pb->pb_offset)];
- cpoff = page_buf_poff(boff + pb->pb_offset);
+ page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
+ cpoff = xfs_buf_poff(boff + bp->b_offset);
csize = min_t(size_t,
- PAGE_CACHE_SIZE-cpoff, pb->pb_count_desired-boff);
+ PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
switch (mode) {
- case PBRW_ZERO:
+ case XBRW_ZERO:
memset(page_address(page) + cpoff, 0, csize);
break;
- case PBRW_READ:
+ case XBRW_READ:
memcpy(data, page_address(page) + cpoff, csize);
break;
- case PBRW_WRITE:
+ case XBRW_WRITE:
memcpy(page_address(page) + cpoff, data, csize);
}
@@ -1425,12 +1341,12 @@ pagebuf_iomove(
}
/*
- * Handling of buftargs.
+ * Handling of buffer targets (buftargs).
*/
/*
- * Wait for any bufs with callbacks that have been submitted but
- * have not yet returned... walk the hash list for the target.
+ * Wait for any bufs with callbacks that have been submitted but
+ * have not yet returned... walk the hash list for the target.
*/
void
xfs_wait_buftarg(
@@ -1444,15 +1360,15 @@ xfs_wait_buftarg(
hash = &btp->bt_hash[i];
again:
spin_lock(&hash->bh_lock);
- list_for_each_entry_safe(bp, n, &hash->bh_list, pb_hash_list) {
- ASSERT(btp == bp->pb_target);
- if (!(bp->pb_flags & PBF_FS_MANAGED)) {
+ list_for_each_entry_safe(bp, n, &hash->bh_list, b_hash_list) {
+ ASSERT(btp == bp->b_target);
+ if (!(bp->b_flags & XBF_FS_MANAGED)) {
spin_unlock(&hash->bh_lock);
/*
* Catch superblock reference count leaks
* immediately
*/
- BUG_ON(bp->pb_bn == 0);
+ BUG_ON(bp->b_bn == 0);
delay(100);
goto again;
}
@@ -1462,9 +1378,9 @@ again:
}
/*
- * Allocate buffer hash table for a given target.
- * For devices containing metadata (i.e. not the log/realtime devices)
- * we need to allocate a much larger hash table.
+ * Allocate buffer hash table for a given target.
+ * For devices containing metadata (i.e. not the log/realtime devices)
+ * we need to allocate a much larger hash table.
*/
STATIC void
xfs_alloc_bufhash(
@@ -1487,11 +1403,34 @@ STATIC void
xfs_free_bufhash(
xfs_buftarg_t *btp)
{
- kmem_free(btp->bt_hash,
- (1 << btp->bt_hashshift) * sizeof(xfs_bufhash_t));
+ kmem_free(btp->bt_hash, (1<<btp->bt_hashshift) * sizeof(xfs_bufhash_t));
btp->bt_hash = NULL;
}
+/*
+ * buftarg list for delwrite queue processing
+ */
+STATIC LIST_HEAD(xfs_buftarg_list);
+STATIC DEFINE_SPINLOCK(xfs_buftarg_lock);
+
+STATIC void
+xfs_register_buftarg(
+ xfs_buftarg_t *btp)
+{
+ spin_lock(&xfs_buftarg_lock);
+ list_add(&btp->bt_list, &xfs_buftarg_list);
+ spin_unlock(&xfs_buftarg_lock);
+}
+
+STATIC void
+xfs_unregister_buftarg(
+ xfs_buftarg_t *btp)
+{
+ spin_lock(&xfs_buftarg_lock);
+ list_del(&btp->bt_list);
+ spin_unlock(&xfs_buftarg_lock);
+}
+
void
xfs_free_buftarg(
xfs_buftarg_t *btp,
@@ -1499,9 +1438,16 @@ xfs_free_buftarg(
{
xfs_flush_buftarg(btp, 1);
if (external)
- xfs_blkdev_put(btp->pbr_bdev);
+ xfs_blkdev_put(btp->bt_bdev);
xfs_free_bufhash(btp);
- iput(btp->pbr_mapping->host);
+ iput(btp->bt_mapping->host);
+
+ /* Unregister the buftarg first so that we don't get a
+ * wakeup finding a non-existent task
+ */
+ xfs_unregister_buftarg(btp);
+ kthread_stop(btp->bt_task);
+
kmem_free(btp, sizeof(*btp));
}
@@ -1512,11 +1458,11 @@ xfs_setsize_buftarg_flags(
unsigned int sectorsize,
int verbose)
{
- btp->pbr_bsize = blocksize;
- btp->pbr_sshift = ffs(sectorsize) - 1;
- btp->pbr_smask = sectorsize - 1;
+ btp->bt_bsize = blocksize;
+ btp->bt_sshift = ffs(sectorsize) - 1;
+ btp->bt_smask = sectorsize - 1;
- if (set_blocksize(btp->pbr_bdev, sectorsize)) {
+ if (set_blocksize(btp->bt_bdev, sectorsize)) {
printk(KERN_WARNING
"XFS: Cannot set_blocksize to %u on device %s\n",
sectorsize, XFS_BUFTARG_NAME(btp));
@@ -1536,10 +1482,10 @@ xfs_setsize_buftarg_flags(
}
/*
-* When allocating the initial buffer target we have not yet
-* read in the superblock, so don't know what sized sectors
-* are being used is at this early stage. Play safe.
-*/
+ * When allocating the initial buffer target we have not yet
+ * read in the superblock, so don't know what sized sectors
+ * are being used is at this early stage. Play safe.
+ */
STATIC int
xfs_setsize_buftarg_early(
xfs_buftarg_t *btp,
@@ -1587,10 +1533,30 @@ xfs_mapping_buftarg(
mapping->a_ops = &mapping_aops;
mapping->backing_dev_info = bdi;
mapping_set_gfp_mask(mapping, GFP_NOFS);
- btp->pbr_mapping = mapping;
+ btp->bt_mapping = mapping;
return 0;
}
+STATIC int
+xfs_alloc_delwrite_queue(
+ xfs_buftarg_t *btp)
+{
+ int error = 0;
+
+ INIT_LIST_HEAD(&btp->bt_list);
+ INIT_LIST_HEAD(&btp->bt_delwrite_queue);
+ spinlock_init(&btp->bt_delwrite_lock, "delwri_lock");
+ btp->bt_flags = 0;
+ btp->bt_task = kthread_run(xfsbufd, btp, "xfsbufd");
+ if (IS_ERR(btp->bt_task)) {
+ error = PTR_ERR(btp->bt_task);
+ goto out_error;
+ }
+ xfs_register_buftarg(btp);
+out_error:
+ return error;
+}
+
xfs_buftarg_t *
xfs_alloc_buftarg(
struct block_device *bdev,
@@ -1600,12 +1566,14 @@ xfs_alloc_buftarg(
btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
- btp->pbr_dev = bdev->bd_dev;
- btp->pbr_bdev = bdev;
+ btp->bt_dev = bdev->bd_dev;
+ btp->bt_bdev = bdev;
if (xfs_setsize_buftarg_early(btp, bdev))
goto error;
if (xfs_mapping_buftarg(btp, bdev))
goto error;
+ if (xfs_alloc_delwrite_queue(btp))
+ goto error;
xfs_alloc_bufhash(btp, external);
return btp;
@@ -1616,83 +1584,81 @@ error:
/*
- * Pagebuf delayed write buffer handling
+ * Delayed write buffer handling
*/
-
-STATIC LIST_HEAD(pbd_delwrite_queue);
-STATIC DEFINE_SPINLOCK(pbd_delwrite_lock);
-
STATIC void
-pagebuf_delwri_queue(
- xfs_buf_t *pb,
+xfs_buf_delwri_queue(
+ xfs_buf_t *bp,
int unlock)
{
- PB_TRACE(pb, "delwri_q", (long)unlock);
- ASSERT((pb->pb_flags & (PBF_DELWRI|PBF_ASYNC)) ==
- (PBF_DELWRI|PBF_ASYNC));
+ struct list_head *dwq = &bp->b_target->bt_delwrite_queue;
+ spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock;
+
+ XB_TRACE(bp, "delwri_q", (long)unlock);
+ ASSERT((bp->b_flags&(XBF_DELWRI|XBF_ASYNC)) == (XBF_DELWRI|XBF_ASYNC));
- spin_lock(&pbd_delwrite_lock);
+ spin_lock(dwlk);
/* 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);
+ if (!list_empty(&bp->b_list)) {
+ ASSERT(bp->b_flags & _XBF_DELWRI_Q);
+ if (unlock)
+ atomic_dec(&bp->b_hold);
+ list_del(&bp->b_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);
+ bp->b_flags |= _XBF_DELWRI_Q;
+ list_add_tail(&bp->b_list, dwq);
+ bp->b_queuetime = jiffies;
+ spin_unlock(dwlk);
if (unlock)
- pagebuf_unlock(pb);
+ xfs_buf_unlock(bp);
}
void
-pagebuf_delwri_dequeue(
- xfs_buf_t *pb)
+xfs_buf_delwri_dequeue(
+ xfs_buf_t *bp)
{
+ spinlock_t *dwlk = &bp->b_target->bt_delwrite_lock;
int dequeued = 0;
- 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);
+ spin_lock(dwlk);
+ if ((bp->b_flags & XBF_DELWRI) && !list_empty(&bp->b_list)) {
+ ASSERT(bp->b_flags & _XBF_DELWRI_Q);
+ list_del_init(&bp->b_list);
dequeued = 1;
}
- pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q);
- spin_unlock(&pbd_delwrite_lock);
+ bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+ spin_unlock(dwlk);
if (dequeued)
- pagebuf_rele(pb);
+ xfs_buf_rele(bp);
- PB_TRACE(pb, "delwri_dq", (long)dequeued);
+ XB_TRACE(bp, "delwri_dq", (long)dequeued);
}
STATIC void
-pagebuf_runall_queues(
+xfs_buf_runall_queues(
struct workqueue_struct *queue)
{
flush_workqueue(queue);
}
-/* Defines for pagebuf daemon */
-STATIC struct task_struct *xfsbufd_task;
-STATIC int xfsbufd_force_flush;
-STATIC int xfsbufd_force_sleep;
-
STATIC int
xfsbufd_wakeup(
int priority,
gfp_t mask)
{
- if (xfsbufd_force_sleep)
- return 0;
- xfsbufd_force_flush = 1;
- barrier();
- wake_up_process(xfsbufd_task);
+ xfs_buftarg_t *btp;
+
+ spin_lock(&xfs_buftarg_lock);
+ list_for_each_entry(btp, &xfs_buftarg_list, bt_list) {
+ if (test_bit(XBT_FORCE_SLEEP, &btp->bt_flags))
+ continue;
+ set_bit(XBT_FORCE_FLUSH, &btp->bt_flags);
+ wake_up_process(btp->bt_task);
+ }
+ spin_unlock(&xfs_buftarg_lock);
return 0;
}
@@ -1702,67 +1668,70 @@ xfsbufd(
{
struct list_head tmp;
unsigned long age;
- xfs_buftarg_t *target;
- xfs_buf_t *pb, *n;
+ xfs_buftarg_t *target = (xfs_buftarg_t *)data;
+ xfs_buf_t *bp, *n;
+ struct list_head *dwq = &target->bt_delwrite_queue;
+ spinlock_t *dwlk = &target->bt_delwrite_lock;
current->flags |= PF_MEMALLOC;
INIT_LIST_HEAD(&tmp);
do {
if (unlikely(freezing(current))) {
- xfsbufd_force_sleep = 1;
+ set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
refrigerator();
} else {
- xfsbufd_force_sleep = 0;
+ clear_bit(XBT_FORCE_SLEEP, &target->bt_flags);
}
schedule_timeout_interruptible(
xfs_buf_timer_centisecs * msecs_to_jiffies(10));
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));
- ASSERT(pb->pb_flags & PBF_DELWRI);
-
- if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
- if (!xfsbufd_force_flush &&
+ spin_lock(dwlk);
+ list_for_each_entry_safe(bp, n, dwq, b_list) {
+ XB_TRACE(bp, "walkq1", (long)xfs_buf_ispin(bp));
+ ASSERT(bp->b_flags & XBF_DELWRI);
+
+ if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) {
+ if (!test_bit(XBT_FORCE_FLUSH,
+ &target->bt_flags) &&
time_before(jiffies,
- pb->pb_queuetime + age)) {
- pagebuf_unlock(pb);
+ bp->b_queuetime + age)) {
+ xfs_buf_unlock(bp);
break;
}
- pb->pb_flags &= ~(PBF_DELWRI|_PBF_DELWRI_Q);
- pb->pb_flags |= PBF_WRITE;
- list_move(&pb->pb_list, &tmp);
+ bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+ bp->b_flags |= XBF_WRITE;
+ list_move(&bp->b_list, &tmp);
}
}
- spin_unlock(&pbd_delwrite_lock);
+ spin_unlock(dwlk);
while (!list_empty(&tmp)) {
- pb = list_entry(tmp.next, xfs_buf_t, pb_list);
- target = pb->pb_target;
+ bp = list_entry(tmp.next, xfs_buf_t, b_list);
+ ASSERT(target == bp->b_target);
- list_del_init(&pb->pb_list);
- pagebuf_iostrategy(pb);
+ list_del_init(&bp->b_list);
+ xfs_buf_iostrategy(bp);
- blk_run_address_space(target->pbr_mapping);
+ blk_run_address_space(target->bt_mapping);
}
if (as_list_len > 0)
purge_addresses();
- xfsbufd_force_flush = 0;
+ clear_bit(XBT_FORCE_FLUSH, &target->bt_flags);
} while (!kthread_should_stop());
return 0;
}
/*
- * Go through all incore buffers, and release buffers if they belong to
- * the given device. This is used in filesystem error handling to
- * preserve the consistency of its metadata.
+ * Go through all incore buffers, and release buffers if they belong to
+ * the given device. This is used in filesystem error handling to
+ * preserve the consistency of its metadata.
*/
int
xfs_flush_buftarg(
@@ -1770,73 +1739,72 @@ xfs_flush_buftarg(
int wait)
{
struct list_head tmp;
- xfs_buf_t *pb, *n;
+ xfs_buf_t *bp, *n;
int pincount = 0;
+ struct list_head *dwq = &target->bt_delwrite_queue;
+ spinlock_t *dwlk = &target->bt_delwrite_lock;
- pagebuf_runall_queues(xfsdatad_workqueue);
- pagebuf_runall_queues(xfslogd_workqueue);
+ xfs_buf_runall_queues(xfsdatad_workqueue);
+ xfs_buf_runall_queues(xfslogd_workqueue);
INIT_LIST_HEAD(&tmp);
- spin_lock(&pbd_delwrite_lock);
- list_for_each_entry_safe(pb, n, &pbd_delwrite_queue, pb_list) {
-
- if (pb->pb_target != target)
- continue;
-
- ASSERT(pb->pb_flags & (PBF_DELWRI|_PBF_DELWRI_Q));
- PB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
- if (pagebuf_ispin(pb)) {
+ spin_lock(dwlk);
+ list_for_each_entry_safe(bp, n, dwq, b_list) {
+ ASSERT(bp->b_target == target);
+ ASSERT(bp->b_flags & (XBF_DELWRI | _XBF_DELWRI_Q));
+ XB_TRACE(bp, "walkq2", (long)xfs_buf_ispin(bp));
+ if (xfs_buf_ispin(bp)) {
pincount++;
continue;
}
- list_move(&pb->pb_list, &tmp);
+ list_move(&bp->b_list, &tmp);
}
- spin_unlock(&pbd_delwrite_lock);
+ spin_unlock(dwlk);
/*
* 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;
+ list_for_each_entry_safe(bp, n, &tmp, b_list) {
+ xfs_buf_lock(bp);
+ bp->b_flags &= ~(XBF_DELWRI|_XBF_DELWRI_Q);
+ bp->b_flags |= XBF_WRITE;
if (wait)
- pb->pb_flags &= ~PBF_ASYNC;
+ bp->b_flags &= ~XBF_ASYNC;
else
- list_del_init(&pb->pb_list);
+ list_del_init(&bp->b_list);
- pagebuf_iostrategy(pb);
+ xfs_buf_iostrategy(bp);
}
/*
* Remaining list items must be flushed before returning
*/
while (!list_empty(&tmp)) {
- pb = list_entry(tmp.next, xfs_buf_t, pb_list);
+ bp = list_entry(tmp.next, xfs_buf_t, b_list);
- list_del_init(&pb->pb_list);
- xfs_iowait(pb);
- xfs_buf_relse(pb);
+ list_del_init(&bp->b_list);
+ xfs_iowait(bp);
+ xfs_buf_relse(bp);
}
if (wait)
- blk_run_address_space(target->pbr_mapping);
+ blk_run_address_space(target->bt_mapping);
return pincount;
}
int __init
-pagebuf_init(void)
+xfs_buf_init(void)
{
int error = -ENOMEM;
-#ifdef PAGEBUF_TRACE
- pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
+#ifdef XFS_BUF_TRACE
+ xfs_buf_trace_buf = ktrace_alloc(XFS_BUF_TRACE_SIZE, KM_SLEEP);
#endif
- pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
- if (!pagebuf_zone)
+ xfs_buf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
+ if (!xfs_buf_zone)
goto out_free_trace_buf;
xfslogd_workqueue = create_workqueue("xfslogd");
@@ -1847,42 +1815,33 @@ pagebuf_init(void)
if (!xfsdatad_workqueue)
goto out_destroy_xfslogd_workqueue;
- xfsbufd_task = kthread_run(xfsbufd, NULL, "xfsbufd");
- if (IS_ERR(xfsbufd_task)) {
- error = PTR_ERR(xfsbufd_task);
+ xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup);
+ if (!xfs_buf_shake)
goto out_destroy_xfsdatad_workqueue;
- }
-
- pagebuf_shake = kmem_shake_register(xfsbufd_wakeup);
- if (!pagebuf_shake)
- goto out_stop_xfsbufd;
return 0;
- out_stop_xfsbufd:
- kthread_stop(xfsbufd_task);
out_destroy_xfsdatad_workqueue:
destroy_workqueue(xfsdatad_workqueue);
out_destroy_xfslogd_workqueue:
destroy_workqueue(xfslogd_workqueue);
out_free_buf_zone:
- kmem_zone_destroy(pagebuf_zone);
+ kmem_zone_destroy(xfs_buf_zone);
out_free_trace_buf:
-#ifdef PAGEBUF_TRACE
- ktrace_free(pagebuf_trace_buf);
+#ifdef XFS_BUF_TRACE
+ ktrace_free(xfs_buf_trace_buf);
#endif
return error;
}
void
-pagebuf_terminate(void)
+xfs_buf_terminate(void)
{
- kmem_shake_deregister(pagebuf_shake);
- kthread_stop(xfsbufd_task);
+ kmem_shake_deregister(xfs_buf_shake);
destroy_workqueue(xfsdatad_workqueue);
destroy_workqueue(xfslogd_workqueue);
- kmem_zone_destroy(pagebuf_zone);
-#ifdef PAGEBUF_TRACE
- ktrace_free(pagebuf_trace_buf);
+ kmem_zone_destroy(xfs_buf_zone);
+#ifdef XFS_BUF_TRACE
+ ktrace_free(xfs_buf_trace_buf);
#endif
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 237a35b915d1..4dd6592d5a4c 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -32,44 +32,47 @@
* Base types
*/
-#define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL))
-
-#define page_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE)
-#define page_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
-#define page_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT)
-#define page_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK)
-
-typedef enum page_buf_rw_e {
- PBRW_READ = 1, /* transfer into target memory */
- PBRW_WRITE = 2, /* transfer from target memory */
- PBRW_ZERO = 3 /* Zero target memory */
-} page_buf_rw_t;
-
-
-typedef enum page_buf_flags_e { /* pb_flags values */
- PBF_READ = (1 << 0), /* buffer intended for reading from device */
- PBF_WRITE = (1 << 1), /* buffer intended for writing to device */
- PBF_MAPPED = (1 << 2), /* buffer mapped (pb_addr valid) */
- PBF_ASYNC = (1 << 4), /* initiator will not wait for completion */
- PBF_DONE = (1 << 5), /* all pages in the buffer uptodate */
- PBF_DELWRI = (1 << 6), /* buffer has dirty pages */
- PBF_STALE = (1 << 7), /* buffer has been staled, do not find it */
- PBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */
- PBF_ORDERED = (1 << 11), /* use ordered writes */
- PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */
+#define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL))
+
+#define xfs_buf_ctob(pp) ((pp) * PAGE_CACHE_SIZE)
+#define xfs_buf_btoc(dd) (((dd) + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT)
+#define xfs_buf_btoct(dd) ((dd) >> PAGE_CACHE_SHIFT)
+#define xfs_buf_poff(aa) ((aa) & ~PAGE_CACHE_MASK)
+
+typedef enum {
+ XBRW_READ = 1, /* transfer into target memory */
+ XBRW_WRITE = 2, /* transfer from target memory */
+ XBRW_ZERO = 3, /* Zero target memory */
+} xfs_buf_rw_t;
+
+typedef enum {
+ XBF_READ = (1 << 0), /* buffer intended for reading from device */
+ XBF_WRITE = (1 << 1), /* buffer intended for writing to device */
+ XBF_MAPPED = (1 << 2), /* buffer mapped (b_addr valid) */
+ XBF_ASYNC = (1 << 4), /* initiator will not wait for completion */
+ XBF_DONE = (1 << 5), /* all pages in the buffer uptodate */
+ XBF_DELWRI = (1 << 6), /* buffer has dirty pages */
+ XBF_STALE = (1 << 7), /* buffer has been staled, do not find it */
+ XBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */
+ XBF_ORDERED = (1 << 11), /* use ordered writes */
+ XBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */
/* flags used only as arguments to access routines */
- PBF_LOCK = (1 << 14), /* lock requested */
- PBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */
- PBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */
+ XBF_LOCK = (1 << 14), /* lock requested */
+ XBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */
+ XBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */
/* flags used only internally */
- _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;
+ _XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */
+ _XBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */
+ _XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */
+ _XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */
+} xfs_buf_flags_t;
+typedef enum {
+ XBT_FORCE_SLEEP = (0 << 1),
+ XBT_FORCE_FLUSH = (1 << 1),
+} xfs_buftarg_flags_t;
typedef struct xfs_bufhash {
struct list_head bh_list;
@@ -77,477 +80,350 @@ typedef struct xfs_bufhash {
} xfs_bufhash_t;
typedef struct xfs_buftarg {
- dev_t pbr_dev;
- struct block_device *pbr_bdev;
- struct address_space *pbr_mapping;
- unsigned int pbr_bsize;
- unsigned int pbr_sshift;
- size_t pbr_smask;
-
- /* per-device buffer hash table */
+ dev_t bt_dev;
+ struct block_device *bt_bdev;
+ struct address_space *bt_mapping;
+ unsigned int bt_bsize;
+ unsigned int bt_sshift;
+ size_t bt_smask;
+
+ /* per device buffer hash table */
uint bt_hashmask;
uint bt_hashshift;
xfs_bufhash_t *bt_hash;
+
+ /* per device delwri queue */
+ struct task_struct *bt_task;
+ struct list_head bt_list;
+ struct list_head bt_delwrite_queue;
+ spinlock_t bt_delwrite_lock;
+ unsigned long bt_flags;
} xfs_buftarg_t;
/*
- * xfs_buf_t: Buffer structure for page cache-based buffers
+ * xfs_buf_t: Buffer structure for pagecache-based buffers
+ *
+ * This buffer structure is used by the pagecache buffer management routines
+ * to refer to an assembly of pages forming a logical buffer.
*
- * This buffer structure is used by the page cache buffer management routines
- * to refer to an assembly of pages forming a logical buffer. The actual I/O
- * is performed with buffer_head structures, as required by drivers.
- *
- * The buffer structure is used on temporary basis only, and discarded when
- * released. The real data storage is recorded in the page cache. Metadata is
+ * The buffer structure is used on a temporary basis only, and discarded when
+ * released. The real data storage is recorded in the pagecache. Buffers are
* hashed to the block device on which the file system resides.
*/
struct xfs_buf;
+typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);
+typedef void (*xfs_buf_relse_t)(struct xfs_buf *);
+typedef int (*xfs_buf_bdstrat_t)(struct xfs_buf *);
-/* call-back function on I/O completion */
-typedef void (*page_buf_iodone_t)(struct xfs_buf *);
-/* call-back function on I/O completion */
-typedef void (*page_buf_relse_t)(struct xfs_buf *);
-/* pre-write function */
-typedef int (*page_buf_bdstrat_t)(struct xfs_buf *);
-
-#define PB_PAGES 2
+#define XB_PAGES 2
typedef struct xfs_buf {
- struct semaphore pb_sema; /* semaphore for lockables */
- unsigned long pb_queuetime; /* time buffer was queued */
- atomic_t pb_pin_count; /* pin count */
- wait_queue_head_t pb_waiters; /* unpin waiters */
- struct list_head pb_list;
- page_buf_flags_t pb_flags; /* status flags */
- struct list_head pb_hash_list; /* hash table list */
- xfs_bufhash_t *pb_hash; /* hash table list start */
- xfs_buftarg_t *pb_target; /* buffer target (device) */
- atomic_t pb_hold; /* reference count */
- xfs_daddr_t pb_bn; /* block number for I/O */
- loff_t pb_file_offset; /* offset in file */
- size_t pb_buffer_length; /* size of buffer in bytes */
- size_t pb_count_desired; /* desired transfer size */
- void *pb_addr; /* virtual address of buffer */
- struct work_struct pb_iodone_work;
- atomic_t pb_io_remaining;/* #outstanding I/O requests */
- page_buf_iodone_t pb_iodone; /* I/O completion function */
- page_buf_relse_t pb_relse; /* releasing function */
- page_buf_bdstrat_t pb_strat; /* pre-write function */
- struct semaphore pb_iodonesema; /* Semaphore for I/O waiters */
- void *pb_fspriv;
- void *pb_fspriv2;
- void *pb_fspriv3;
- unsigned short pb_error; /* error code on I/O */
- unsigned short pb_locked; /* page array is locked */
- unsigned int pb_page_count; /* size of page array */
- unsigned int pb_offset; /* page offset in first page */
- struct page **pb_pages; /* array of page pointers */
- struct page *pb_page_array[PB_PAGES]; /* inline pages */
-#ifdef PAGEBUF_LOCK_TRACKING
- int pb_last_holder;
+ struct semaphore b_sema; /* semaphore for lockables */
+ unsigned long b_queuetime; /* time buffer was queued */
+ atomic_t b_pin_count; /* pin count */
+ wait_queue_head_t b_waiters; /* unpin waiters */
+ struct list_head b_list;
+ xfs_buf_flags_t b_flags; /* status flags */
+ struct list_head b_hash_list; /* hash table list */
+ xfs_bufhash_t *b_hash; /* hash table list start */
+ xfs_buftarg_t *b_target; /* buffer target (device) */
+ atomic_t b_hold; /* reference count */
+ xfs_daddr_t b_bn; /* block number for I/O */
+ xfs_off_t b_file_offset; /* offset in file */
+ size_t b_buffer_length;/* size of buffer in bytes */
+ size_t b_count_desired;/* desired transfer size */
+ void *b_addr; /* virtual address of buffer */
+ struct work_struct b_iodone_work;
+ atomic_t b_io_remaining; /* #outstanding I/O requests */
+ xfs_buf_iodone_t b_iodone; /* I/O completion function */
+ xfs_buf_relse_t b_relse; /* releasing function */
+ xfs_buf_bdstrat_t b_strat; /* pre-write function */
+ struct semaphore b_iodonesema; /* Semaphore for I/O waiters */
+ void *b_fspriv;
+ void *b_fspriv2;
+ void *b_fspriv3;
+ unsigned short b_error; /* error code on I/O */
+ unsigned short b_locked; /* page array is locked */
+ unsigned int b_page_count; /* size of page array */
+ unsigned int b_offset; /* page offset in first page */
+ struct page **b_pages; /* array of page pointers */
+ struct page *b_page_array[XB_PAGES]; /* inline pages */
+#ifdef XFS_BUF_LOCK_TRACKING
+ int b_last_holder;
#endif
} xfs_buf_t;
/* Finding and Reading Buffers */
-
-extern xfs_buf_t *_pagebuf_find( /* find buffer for block if */
- /* the block is in memory */
- xfs_buftarg_t *, /* inode for block */
- loff_t, /* starting offset of range */
- size_t, /* length of range */
- page_buf_flags_t, /* PBF_LOCK */
- xfs_buf_t *); /* newly allocated buffer */
-
+extern xfs_buf_t *_xfs_buf_find(xfs_buftarg_t *, xfs_off_t, size_t,
+ xfs_buf_flags_t, xfs_buf_t *);
#define xfs_incore(buftarg,blkno,len,lockit) \
- _pagebuf_find(buftarg, blkno ,len, lockit, NULL)
-
-extern xfs_buf_t *xfs_buf_get_flags( /* allocate a buffer */
- xfs_buftarg_t *, /* inode for buffer */
- loff_t, /* starting offset of range */
- size_t, /* length of range */
- page_buf_flags_t); /* PBF_LOCK, PBF_READ, */
- /* PBF_ASYNC */
+ _xfs_buf_find(buftarg, blkno ,len, lockit, NULL)
+extern xfs_buf_t *xfs_buf_get_flags(xfs_buftarg_t *, xfs_off_t, size_t,
+ xfs_buf_flags_t);
#define xfs_buf_get(target, blkno, len, flags) \
- xfs_buf_get_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED)
-
-extern xfs_buf_t *xfs_buf_read_flags( /* allocate and read a buffer */
- xfs_buftarg_t *, /* inode for buffer */
- loff_t, /* starting offset of range */
- size_t, /* length of range */
- page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC */
+ xfs_buf_get_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED)
+extern xfs_buf_t *xfs_buf_read_flags(xfs_buftarg_t *, xfs_off_t, size_t,
+ xfs_buf_flags_t);
#define xfs_buf_read(target, blkno, len, flags) \
- xfs_buf_read_flags((target), (blkno), (len), PBF_LOCK | PBF_MAPPED)
-
-extern xfs_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */
- /* no memory or disk address */
- size_t len,
- xfs_buftarg_t *); /* mount point "fake" inode */
-
-extern xfs_buf_t *pagebuf_get_no_daddr(/* allocate pagebuf struct */
- /* without disk address */
- size_t len,
- xfs_buftarg_t *); /* mount point "fake" inode */
-
-extern int pagebuf_associate_memory(
- xfs_buf_t *,
- void *,
- size_t);
-
-extern void pagebuf_hold( /* increment reference count */
- xfs_buf_t *); /* buffer to hold */
+ xfs_buf_read_flags((target), (blkno), (len), XBF_LOCK | XBF_MAPPED)
-extern void pagebuf_readahead( /* read ahead into cache */
- xfs_buftarg_t *, /* target for buffer (or NULL) */
- loff_t, /* starting offset of range */
- size_t, /* length of range */
- page_buf_flags_t); /* additional read flags */
+extern xfs_buf_t *xfs_buf_get_empty(size_t, xfs_buftarg_t *);
+extern xfs_buf_t *xfs_buf_get_noaddr(size_t, xfs_buftarg_t *);
+extern int xfs_buf_associate_memory(xfs_buf_t *, void *, size_t);
+extern void xfs_buf_hold(xfs_buf_t *);
+extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t,
+ xfs_buf_flags_t);
/* Releasing Buffers */
-
-extern void pagebuf_free( /* deallocate a buffer */
- xfs_buf_t *); /* buffer to deallocate */
-
-extern void pagebuf_rele( /* release hold on a buffer */
- xfs_buf_t *); /* buffer to release */
+extern void xfs_buf_free(xfs_buf_t *);
+extern void xfs_buf_rele(xfs_buf_t *);
/* Locking and Unlocking Buffers */
-
-extern int pagebuf_cond_lock( /* lock buffer, if not locked */
- /* (returns -EBUSY if locked) */
- xfs_buf_t *); /* buffer to lock */
-
-extern int pagebuf_lock_value( /* return count on lock */
- xfs_buf_t *); /* buffer to check */
-
-extern int pagebuf_lock( /* lock buffer */
- xfs_buf_t *); /* buffer to lock */
-
-extern void pagebuf_unlock( /* unlock buffer */
- xfs_buf_t *); /* buffer to unlock */
+extern int xfs_buf_cond_lock(xfs_buf_t *);
+extern int xfs_buf_lock_value(xfs_buf_t *);
+extern void xfs_buf_lock(xfs_buf_t *);
+extern void xfs_buf_unlock(xfs_buf_t *);
/* Buffer Read and Write Routines */
-
-extern void pagebuf_iodone( /* mark buffer I/O complete */
- xfs_buf_t *, /* buffer to mark */
- int); /* run completion locally, or in
- * a helper thread. */
-
-extern void pagebuf_ioerror( /* mark buffer in error (or not) */
- xfs_buf_t *, /* buffer to mark */
- int); /* error to store (0 if none) */
-
-extern int pagebuf_iostart( /* start I/O on a buffer */
- xfs_buf_t *, /* buffer to start */
- page_buf_flags_t); /* PBF_LOCK, PBF_ASYNC, */
- /* PBF_READ, PBF_WRITE, */
- /* PBF_DELWRI */
-
-extern int pagebuf_iorequest( /* start real I/O */
- xfs_buf_t *); /* buffer to convey to device */
-
-extern int pagebuf_iowait( /* wait for buffer I/O done */
- xfs_buf_t *); /* buffer to wait on */
-
-extern void pagebuf_iomove( /* move data in/out of pagebuf */
- xfs_buf_t *, /* buffer to manipulate */
- size_t, /* starting buffer offset */
- size_t, /* length in buffer */
- caddr_t, /* data pointer */
- page_buf_rw_t); /* direction */
-
-static inline int pagebuf_iostrategy(xfs_buf_t *pb)
+extern void xfs_buf_ioend(xfs_buf_t *, int);
+extern void xfs_buf_ioerror(xfs_buf_t *, int);
+extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t);
+extern int xfs_buf_iorequest(xfs_buf_t *);
+extern int xfs_buf_iowait(xfs_buf_t *);
+extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t,
+ xfs_buf_rw_t);
+
+static inline int xfs_buf_iostrategy(xfs_buf_t *bp)
{
- return pb->pb_strat ? pb->pb_strat(pb) : pagebuf_iorequest(pb);
+ return bp->b_strat ? bp->b_strat(bp) : xfs_buf_iorequest(bp);
}
-static inline int pagebuf_geterror(xfs_buf_t *pb)
+static inline int xfs_buf_geterror(xfs_buf_t *bp)
{
- return pb ? pb->pb_error : ENOMEM;
+ return bp ? bp->b_error : ENOMEM;
}
/* Buffer Utility Routines */
-
-extern caddr_t pagebuf_offset( /* pointer at offset in buffer */
- xfs_buf_t *, /* buffer to offset into */
- size_t); /* offset */
+extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
/* Pinning Buffer Storage in Memory */
-
-extern void pagebuf_pin( /* pin buffer in memory */
- xfs_buf_t *); /* buffer to pin */
-
-extern void pagebuf_unpin( /* unpin buffered data */
- xfs_buf_t *); /* buffer to unpin */
-
-extern int pagebuf_ispin( /* check if buffer is pinned */
- xfs_buf_t *); /* buffer to check */
+extern void xfs_buf_pin(xfs_buf_t *);
+extern void xfs_buf_unpin(xfs_buf_t *);
+extern int xfs_buf_ispin(xfs_buf_t *);
/* Delayed Write Buffer Routines */
-
-extern void pagebuf_delwri_dequeue(xfs_buf_t *);
+extern void xfs_buf_delwri_dequeue(xfs_buf_t *);
/* Buffer Daemon Setup Routines */
+extern int xfs_buf_init(void);
+extern void xfs_buf_terminate(void);
-extern int pagebuf_init(void);
-extern void pagebuf_terminate(void);
-
-
-#ifdef PAGEBUF_TRACE
-extern ktrace_t *pagebuf_trace_buf;
-extern void pagebuf_trace(
- xfs_buf_t *, /* buffer being traced */
- char *, /* description of operation */
- void *, /* arbitrary diagnostic value */
- void *); /* return address */
+#ifdef XFS_BUF_TRACE
+extern ktrace_t *xfs_buf_trace_buf;
+extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *);
#else
-# define pagebuf_trace(pb, id, ptr, ra) do { } while (0)
+#define xfs_buf_trace(bp,id,ptr,ra) do { } while (0)
#endif
-#define pagebuf_target_name(target) \
- ({ char __b[BDEVNAME_SIZE]; bdevname((target)->pbr_bdev, __b); __b; })
+#define xfs_buf_target_name(target) \
+ ({ char __b[BDEVNAME_SIZE]; bdevname((target)->bt_bdev, __b); __b; })
+#define XFS_B_ASYNC XBF_ASYNC
+#define XFS_B_DELWRI XBF_DELWRI
+#define XFS_B_READ XBF_READ
+#define XFS_B_WRITE XBF_WRITE
+#define XFS_B_STALE XBF_STALE
-/* 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
- */
-#define XFS_B_ASYNC PBF_ASYNC
-#define XFS_B_DELWRI PBF_DELWRI
-#define XFS_B_READ PBF_READ
-#define XFS_B_WRITE PBF_WRITE
-#define XFS_B_STALE PBF_STALE
-
-#define XFS_BUF_TRYLOCK PBF_TRYLOCK
-#define XFS_INCORE_TRYLOCK PBF_TRYLOCK
-#define XFS_BUF_LOCK PBF_LOCK
-#define XFS_BUF_MAPPED PBF_MAPPED
-
-#define BUF_BUSY PBF_DONT_BLOCK
-
-#define XFS_BUF_BFLAGS(x) ((x)->pb_flags)
-#define XFS_BUF_ZEROFLAGS(x) \
- ((x)->pb_flags &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI))
-
-#define XFS_BUF_STALE(x) ((x)->pb_flags |= XFS_B_STALE)
-#define XFS_BUF_UNSTALE(x) ((x)->pb_flags &= ~XFS_B_STALE)
-#define XFS_BUF_ISSTALE(x) ((x)->pb_flags & XFS_B_STALE)
-#define XFS_BUF_SUPER_STALE(x) do { \
- XFS_BUF_STALE(x); \
- pagebuf_delwri_dequeue(x); \
- XFS_BUF_DONE(x); \
- } while (0)
+#define XFS_BUF_TRYLOCK XBF_TRYLOCK
+#define XFS_INCORE_TRYLOCK XBF_TRYLOCK
+#define XFS_BUF_LOCK XBF_LOCK
+#define XFS_BUF_MAPPED XBF_MAPPED
-#define XFS_BUF_MANAGE PBF_FS_MANAGED
-#define XFS_BUF_UNMANAGE(x) ((x)->pb_flags &= ~PBF_FS_MANAGED)
-
-#define XFS_BUF_DELAYWRITE(x) ((x)->pb_flags |= PBF_DELWRI)
-#define XFS_BUF_UNDELAYWRITE(x) pagebuf_delwri_dequeue(x)
-#define XFS_BUF_ISDELAYWRITE(x) ((x)->pb_flags & PBF_DELWRI)
-
-#define XFS_BUF_ERROR(x,no) pagebuf_ioerror(x,no)
-#define XFS_BUF_GETERROR(x) pagebuf_geterror(x)
-#define XFS_BUF_ISERROR(x) (pagebuf_geterror(x)?1:0)
-
-#define XFS_BUF_DONE(x) ((x)->pb_flags |= PBF_DONE)
-#define XFS_BUF_UNDONE(x) ((x)->pb_flags &= ~PBF_DONE)
-#define XFS_BUF_ISDONE(x) ((x)->pb_flags & PBF_DONE)
-
-#define XFS_BUF_BUSY(x) do { } while (0)
-#define XFS_BUF_UNBUSY(x) do { } while (0)
-#define XFS_BUF_ISBUSY(x) (1)
-
-#define XFS_BUF_ASYNC(x) ((x)->pb_flags |= PBF_ASYNC)
-#define XFS_BUF_UNASYNC(x) ((x)->pb_flags &= ~PBF_ASYNC)
-#define XFS_BUF_ISASYNC(x) ((x)->pb_flags & PBF_ASYNC)
-
-#define XFS_BUF_ORDERED(x) ((x)->pb_flags |= PBF_ORDERED)
-#define XFS_BUF_UNORDERED(x) ((x)->pb_flags &= ~PBF_ORDERED)
-#define XFS_BUF_ISORDERED(x) ((x)->pb_flags & PBF_ORDERED)
-
-#define XFS_BUF_SHUT(x) printk("XFS_BUF_SHUT not implemented yet\n")
-#define XFS_BUF_UNSHUT(x) printk("XFS_BUF_UNSHUT not implemented yet\n")
-#define XFS_BUF_ISSHUT(x) (0)
-
-#define XFS_BUF_HOLD(x) pagebuf_hold(x)
-#define XFS_BUF_READ(x) ((x)->pb_flags |= PBF_READ)
-#define XFS_BUF_UNREAD(x) ((x)->pb_flags &= ~PBF_READ)
-#define XFS_BUF_ISREAD(x) ((x)->pb_flags & PBF_READ)
-
-#define XFS_BUF_WRITE(x) ((x)->pb_flags |= PBF_WRITE)
-#define XFS_BUF_UNWRITE(x) ((x)->pb_flags &= ~PBF_WRITE)
-#define XFS_BUF_ISWRITE(x) ((x)->pb_flags & PBF_WRITE)
-
-#define XFS_BUF_ISUNINITIAL(x) (0)
-#define XFS_BUF_UNUNINITIAL(x) (0)
-
-#define XFS_BUF_BP_ISMAPPED(bp) 1
-
-#define XFS_BUF_IODONE_FUNC(buf) (buf)->pb_iodone
-#define XFS_BUF_SET_IODONE_FUNC(buf, func) \
- (buf)->pb_iodone = (func)
-#define XFS_BUF_CLR_IODONE_FUNC(buf) \
- (buf)->pb_iodone = NULL
-#define XFS_BUF_SET_BDSTRAT_FUNC(buf, func) \
- (buf)->pb_strat = (func)
-#define XFS_BUF_CLR_BDSTRAT_FUNC(buf) \
- (buf)->pb_strat = NULL
-
-#define XFS_BUF_FSPRIVATE(buf, type) \
- ((type)(buf)->pb_fspriv)
-#define XFS_BUF_SET_FSPRIVATE(buf, value) \
- (buf)->pb_fspriv = (void *)(value)
-#define XFS_BUF_FSPRIVATE2(buf, type) \
- ((type)(buf)->pb_fspriv2)
-#define XFS_BUF_SET_FSPRIVATE2(buf, value) \
- (buf)->pb_fspriv2 = (void *)(value)
-#define XFS_BUF_FSPRIVATE3(buf, type) \
- ((type)(buf)->pb_fspriv3)
-#define XFS_BUF_SET_FSPRIVATE3(buf, value) \
- (buf)->pb_fspriv3 = (void *)(value)
-#define XFS_BUF_SET_START(buf)
-
-#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \
- (buf)->pb_relse = (value)
-
-#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->pb_addr)
-
-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;
- return (xfs_caddr_t) pagebuf_offset(bp, offset);
-}
+#define BUF_BUSY XBF_DONT_BLOCK
+
+#define XFS_BUF_BFLAGS(bp) ((bp)->b_flags)
+#define XFS_BUF_ZEROFLAGS(bp) \
+ ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI))
+
+#define XFS_BUF_STALE(bp) ((bp)->b_flags |= XFS_B_STALE)
+#define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XFS_B_STALE)
+#define XFS_BUF_ISSTALE(bp) ((bp)->b_flags & XFS_B_STALE)
+#define XFS_BUF_SUPER_STALE(bp) do { \
+ XFS_BUF_STALE(bp); \
+ xfs_buf_delwri_dequeue(bp); \
+ XFS_BUF_DONE(bp); \
+ } while (0)
-#define XFS_BUF_SET_PTR(bp, val, count) \
- pagebuf_associate_memory(bp, val, count)
-#define XFS_BUF_ADDR(bp) ((bp)->pb_bn)
-#define XFS_BUF_SET_ADDR(bp, blk) \
- ((bp)->pb_bn = (xfs_daddr_t)(blk))
-#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset)
-#define XFS_BUF_SET_OFFSET(bp, off) \
- ((bp)->pb_file_offset = (off))
-#define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired)
-#define XFS_BUF_SET_COUNT(bp, cnt) \
- ((bp)->pb_count_desired = (cnt))
-#define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length)
-#define XFS_BUF_SET_SIZE(bp, cnt) \
- ((bp)->pb_buffer_length = (cnt))
-#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
-#define XFS_BUF_SET_VTYPE(bp, type)
-#define XFS_BUF_SET_REF(bp, ref)
-
-#define XFS_BUF_ISPINNED(bp) pagebuf_ispin(bp)
-
-#define XFS_BUF_VALUSEMA(bp) pagebuf_lock_value(bp)
-#define XFS_BUF_CPSEMA(bp) (pagebuf_cond_lock(bp) == 0)
-#define XFS_BUF_VSEMA(bp) pagebuf_unlock(bp)
-#define XFS_BUF_PSEMA(bp,x) pagebuf_lock(bp)
-#define XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iodonesema);
-
-/* setup the buffer target from a buftarg structure */
-#define XFS_BUF_SET_TARGET(bp, target) \
- (bp)->pb_target = (target)
-#define XFS_BUF_TARGET(bp) ((bp)->pb_target)
-#define XFS_BUFTARG_NAME(target) \
- pagebuf_target_name(target)
-
-#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
-#define XFS_BUF_SET_VTYPE(bp, type)
-#define XFS_BUF_SET_REF(bp, ref)
-
-static inline int xfs_bawrite(void *mp, xfs_buf_t *bp)
+#define XFS_BUF_MANAGE XBF_FS_MANAGED
+#define XFS_BUF_UNMANAGE(bp) ((bp)->b_flags &= ~XBF_FS_MANAGED)
+
+#define XFS_BUF_DELAYWRITE(bp) ((bp)->b_flags |= XBF_DELWRI)
+#define XFS_BUF_UNDELAYWRITE(bp) xfs_buf_delwri_dequeue(bp)
+#define XFS_BUF_ISDELAYWRITE(bp) ((bp)->b_flags & XBF_DELWRI)
+
+#define XFS_BUF_ERROR(bp,no) xfs_buf_ioerror(bp,no)
+#define XFS_BUF_GETERROR(bp) xfs_buf_geterror(bp)
+#define XFS_BUF_ISERROR(bp) (xfs_buf_geterror(bp) ? 1 : 0)
+
+#define XFS_BUF_DONE(bp) ((bp)->b_flags |= XBF_DONE)
+#define XFS_BUF_UNDONE(bp) ((bp)->b_flags &= ~XBF_DONE)
+#define XFS_BUF_ISDONE(bp) ((bp)->b_flags & XBF_DONE)
+
+#define XFS_BUF_BUSY(bp) do { } while (0)
+#define XFS_BUF_UNBUSY(bp) do { } while (0)
+#define XFS_BUF_ISBUSY(bp) (1)
+
+#define XFS_BUF_ASYNC(bp) ((bp)->b_flags |= XBF_ASYNC)
+#define XFS_BUF_UNASYNC(bp) ((bp)->b_flags &= ~XBF_ASYNC)
+#define XFS_BUF_ISASYNC(bp) ((bp)->b_flags & XBF_ASYNC)
+
+#define XFS_BUF_ORDERED(bp) ((bp)->b_flags |= XBF_ORDERED)
+#define XFS_BUF_UNORDERED(bp) ((bp)->b_flags &= ~XBF_ORDERED)
+#define XFS_BUF_ISORDERED(bp) ((bp)->b_flags & XBF_ORDERED)
+
+#define XFS_BUF_SHUT(bp) do { } while (0)
+#define XFS_BUF_UNSHUT(bp) do { } while (0)
+#define XFS_BUF_ISSHUT(bp) (0)
+
+#define XFS_BUF_HOLD(bp) xfs_buf_hold(bp)
+#define XFS_BUF_READ(bp) ((bp)->b_flags |= XBF_READ)
+#define XFS_BUF_UNREAD(bp) ((bp)->b_flags &= ~XBF_READ)
+#define XFS_BUF_ISREAD(bp) ((bp)->b_flags & XBF_READ)
+
+#define XFS_BUF_WRITE(bp) ((bp)->b_flags |= XBF_WRITE)
+#define XFS_BUF_UNWRITE(bp) ((bp)->b_flags &= ~XBF_WRITE)
+#define XFS_BUF_ISWRITE(bp) ((bp)->b_flags & XBF_WRITE)
+
+#define XFS_BUF_ISUNINITIAL(bp) (0)
+#define XFS_BUF_UNUNINITIAL(bp) (0)
+
+#define XFS_BUF_BP_ISMAPPED(bp) (1)
+
+#define XFS_BUF_IODONE_FUNC(bp) ((bp)->b_iodone)
+#define XFS_BUF_SET_IODONE_FUNC(bp, func) ((bp)->b_iodone = (func))
+#define XFS_BUF_CLR_IODONE_FUNC(bp) ((bp)->b_iodone = NULL)
+#define XFS_BUF_SET_BDSTRAT_FUNC(bp, func) ((bp)->b_strat = (func))
+#define XFS_BUF_CLR_BDSTRAT_FUNC(bp) ((bp)->b_strat = NULL)
+
+#define XFS_BUF_FSPRIVATE(bp, type) ((type)(bp)->b_fspriv)
+#define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val))
+#define XFS_BUF_FSPRIVATE2(bp, type) ((type)(bp)->b_fspriv2)
+#define XFS_BUF_SET_FSPRIVATE2(bp, val) ((bp)->b_fspriv2 = (void*)(val))
+#define XFS_BUF_FSPRIVATE3(bp, type) ((type)(bp)->b_fspriv3)
+#define XFS_BUF_SET_FSPRIVATE3(bp, val) ((bp)->b_fspriv3 = (void*)(val))
+#define XFS_BUF_SET_START(bp) do { } while (0)
+#define XFS_BUF_SET_BRELSE_FUNC(bp, func) ((bp)->b_relse = (func))
+
+#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->b_addr)
+#define XFS_BUF_SET_PTR(bp, val, cnt) xfs_buf_associate_memory(bp, val, cnt)
+#define XFS_BUF_ADDR(bp) ((bp)->b_bn)
+#define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_bn = (xfs_daddr_t)(bno))
+#define XFS_BUF_OFFSET(bp) ((bp)->b_file_offset)
+#define XFS_BUF_SET_OFFSET(bp, off) ((bp)->b_file_offset = (off))
+#define XFS_BUF_COUNT(bp) ((bp)->b_count_desired)
+#define XFS_BUF_SET_COUNT(bp, cnt) ((bp)->b_count_desired = (cnt))
+#define XFS_BUF_SIZE(bp) ((bp)->b_buffer_length)
+#define XFS_BUF_SET_SIZE(bp, cnt) ((bp)->b_buffer_length = (cnt))
+
+#define XFS_BUF_SET_VTYPE_REF(bp, type, ref) do { } while (0)
+#define XFS_BUF_SET_VTYPE(bp, type) do { } while (0)
+#define XFS_BUF_SET_REF(bp, ref) do { } while (0)
+
+#define XFS_BUF_ISPINNED(bp) xfs_buf_ispin(bp)
+
+#define XFS_BUF_VALUSEMA(bp) xfs_buf_lock_value(bp)
+#define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0)
+#define XFS_BUF_VSEMA(bp) xfs_buf_unlock(bp)
+#define XFS_BUF_PSEMA(bp,x) xfs_buf_lock(bp)
+#define XFS_BUF_V_IODONESEMA(bp) up(&bp->b_iodonesema);
+
+#define XFS_BUF_SET_TARGET(bp, target) ((bp)->b_target = (target))
+#define XFS_BUF_TARGET(bp) ((bp)->b_target)
+#define XFS_BUFTARG_NAME(target) xfs_buf_target_name(target)
+
+static inline int xfs_bawrite(void *mp, xfs_buf_t *bp)
{
- bp->pb_fspriv3 = mp;
- bp->pb_strat = xfs_bdstrat_cb;
- pagebuf_delwri_dequeue(bp);
- return pagebuf_iostart(bp, PBF_WRITE | PBF_ASYNC | _PBF_RUN_QUEUES);
+ bp->b_fspriv3 = mp;
+ bp->b_strat = xfs_bdstrat_cb;
+ xfs_buf_delwri_dequeue(bp);
+ return xfs_buf_iostart(bp, XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES);
}
-static inline void xfs_buf_relse(xfs_buf_t *bp)
+static inline void xfs_buf_relse(xfs_buf_t *bp)
{
- if (!bp->pb_relse)
- pagebuf_unlock(bp);
- pagebuf_rele(bp);
+ if (!bp->b_relse)
+ xfs_buf_unlock(bp);
+ xfs_buf_rele(bp);
}
-#define xfs_bpin(bp) pagebuf_pin(bp)
-#define xfs_bunpin(bp) pagebuf_unpin(bp)
+#define xfs_bpin(bp) xfs_buf_pin(bp)
+#define xfs_bunpin(bp) xfs_buf_unpin(bp)
#define xfs_buftrace(id, bp) \
- pagebuf_trace(bp, id, NULL, (void *)__builtin_return_address(0))
+ xfs_buf_trace(bp, id, NULL, (void *)__builtin_return_address(0))
-#define xfs_biodone(pb) \
- pagebuf_iodone(pb, 0)
+#define xfs_biodone(bp) xfs_buf_ioend(bp, 0)
-#define xfs_biomove(pb, off, len, data, rw) \
- pagebuf_iomove((pb), (off), (len), (data), \
- ((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ)
+#define xfs_biomove(bp, off, len, data, rw) \
+ xfs_buf_iomove((bp), (off), (len), (data), \
+ ((rw) == XFS_B_WRITE) ? XBRW_WRITE : XBRW_READ)
-#define xfs_biozero(pb, off, len) \
- pagebuf_iomove((pb), (off), (len), NULL, PBRW_ZERO)
+#define xfs_biozero(bp, off, len) \
+ xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
-static inline int XFS_bwrite(xfs_buf_t *pb)
+static inline int XFS_bwrite(xfs_buf_t *bp)
{
- int iowait = (pb->pb_flags & PBF_ASYNC) == 0;
+ int iowait = (bp->b_flags & XBF_ASYNC) == 0;
int error = 0;
if (!iowait)
- pb->pb_flags |= _PBF_RUN_QUEUES;
+ bp->b_flags |= _XBF_RUN_QUEUES;
- pagebuf_delwri_dequeue(pb);
- pagebuf_iostrategy(pb);
+ xfs_buf_delwri_dequeue(bp);
+ xfs_buf_iostrategy(bp);
if (iowait) {
- error = pagebuf_iowait(pb);
- xfs_buf_relse(pb);
+ error = xfs_buf_iowait(bp);
+ xfs_buf_relse(bp);
}
return error;
}
-#define XFS_bdwrite(pb) \
- pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC)
+#define XFS_bdwrite(bp) xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC)
static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
{
- bp->pb_strat = xfs_bdstrat_cb;
- bp->pb_fspriv3 = mp;
-
- return pagebuf_iostart(bp, PBF_DELWRI | PBF_ASYNC);
+ bp->b_strat = xfs_bdstrat_cb;
+ bp->b_fspriv3 = mp;
+ return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
}
-#define XFS_bdstrat(bp) pagebuf_iorequest(bp)
+#define XFS_bdstrat(bp) xfs_buf_iorequest(bp)
-#define xfs_iowait(pb) pagebuf_iowait(pb)
+#define xfs_iowait(bp) xfs_buf_iowait(bp)
#define xfs_baread(target, rablkno, ralen) \
- pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK)
-
-#define xfs_buf_get_empty(len, target) pagebuf_get_empty((len), (target))
-#define xfs_buf_get_noaddr(len, target) pagebuf_get_no_daddr((len), (target))
-#define xfs_buf_free(bp) pagebuf_free(bp)
+ xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK)
/*
* Handling of buftargs.
*/
-
extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
extern void xfs_free_buftarg(xfs_buftarg_t *, int);
extern void xfs_wait_buftarg(xfs_buftarg_t *);
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
-#define xfs_getsize_buftarg(buftarg) \
- block_size((buftarg)->pbr_bdev)
-#define xfs_readonly_buftarg(buftarg) \
- bdev_read_only((buftarg)->pbr_bdev)
-#define xfs_binval(buftarg) \
- xfs_flush_buftarg(buftarg, 1)
-#define XFS_bflush(buftarg) \
- xfs_flush_buftarg(buftarg, 1)
+#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev)
+#define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev)
+
+#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1)
+#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1)
#endif /* __XFS_BUF_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_cred.h b/fs/xfs/linux-2.6/xfs_cred.h
index 4af491024727..e7f3da61c6c3 100644
--- a/fs/xfs/linux-2.6/xfs_cred.h
+++ b/fs/xfs/linux-2.6/xfs_cred.h
@@ -18,6 +18,8 @@
#ifndef __XFS_CRED_H__
#define __XFS_CRED_H__
+#include <linux/capability.h>
+
/*
* Credentials
*/
@@ -27,7 +29,7 @@ typedef struct cred {
extern struct cred *sys_cred;
-/* this is a hack.. (assums sys_cred is the only cred_t in the system) */
+/* this is a hack.. (assumes sys_cred is the only cred_t in the system) */
static __inline int capable_cred(cred_t *cr, int cid)
{
return (cr == sys_cred) ? 1 : capable(cid);
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 06111d0bbae4..ced4404339c7 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -509,16 +509,14 @@ linvfs_open_exec(
vnode_t *vp = LINVFS_GET_VP(inode);
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
int error = 0;
- bhv_desc_t *bdp;
xfs_inode_t *ip;
if (vp->v_vfsp->vfs_flag & VFS_DMI) {
- bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
- if (!bdp) {
+ ip = xfs_vtoi(vp);
+ if (!ip) {
error = -EINVAL;
goto open_exec_out;
}
- ip = XFS_BHVTOI(bdp);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) {
error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
0, 0, 0, NULL);
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index f89340c61bf2..4fa4b1a5187e 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -79,8 +79,7 @@ fs_flushinval_pages(
struct inode *ip = LINVFS_GET_IP(vp);
if (VN_CACHED(vp)) {
- filemap_fdatawrite(ip->i_mapping);
- filemap_fdatawait(ip->i_mapping);
+ filemap_write_and_wait(ip->i_mapping);
truncate_inode_pages(ip->i_mapping, first);
}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index b78b5eb9e96c..4db47790415c 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -52,6 +52,7 @@
#include "xfs_dfrag.h"
#include "xfs_fsops.h"
+#include <linux/capability.h>
#include <linux/dcache.h>
#include <linux/mount.h>
#include <linux/namei.h>
@@ -145,13 +146,10 @@ xfs_find_handle(
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
xfs_inode_t *ip;
- bhv_desc_t *bhv;
int lock_mode;
/* need to get access to the xfs_inode to read the generation */
- bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops);
- ASSERT(bhv);
- ip = XFS_BHVTOI(bhv);
+ ip = xfs_vtoi(vp);
ASSERT(ip);
lock_mode = xfs_ilock_map_shared(ip);
@@ -530,6 +528,8 @@ xfs_attrmulti_attr_set(
char *kbuf;
int error = EFAULT;
+ if (IS_RDONLY(&vp->v_inode))
+ return -EROFS;
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
return EPERM;
if (len > XATTR_SIZE_MAX)
@@ -557,6 +557,9 @@ xfs_attrmulti_attr_remove(
{
int error;
+
+ if (IS_RDONLY(&vp->v_inode))
+ return -EROFS;
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
return EPERM;
@@ -745,9 +748,8 @@ xfs_ioctl(
(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
- da.d_mem = da.d_miniosz = 1 << target->pbr_sshift;
- /* The size dio will do in one go */
- da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
+ da.d_mem = da.d_miniosz = 1 << target->bt_sshift;
+ da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
if (copy_to_user(arg, &da, sizeof(da)))
return -XFS_ERROR(EFAULT);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index c83ae15bb0e6..a7c9ba1a9f7b 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -19,7 +19,6 @@
#include <linux/compat.h>
#include <linux/init.h>
#include <linux/ioctl.h>
-#include <linux/ioctl32.h>
#include <linux/syscalls.h>
#include <linux/types.h>
#include <linux/fs.h>
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 14215a7db59f..76c6df34d0db 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -51,8 +51,44 @@
#include "xfs_buf_item.h"
#include "xfs_utils.h"
+#include <linux/capability.h>
#include <linux/xattr.h>
#include <linux/namei.h>
+#include <linux/security.h>
+
+/*
+ * Get a XFS inode from a given vnode.
+ */
+xfs_inode_t *
+xfs_vtoi(
+ struct vnode *vp)
+{
+ bhv_desc_t *bdp;
+
+ bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
+ VNODE_POSITION_XFS, VNODE_POSITION_XFS);
+ if (unlikely(bdp == NULL))
+ return NULL;
+ return XFS_BHVTOI(bdp);
+}
+
+/*
+ * Bring the atime in the XFS inode uptodate.
+ * Used before logging the inode to disk or when the Linux inode goes away.
+ */
+void
+xfs_synchronize_atime(
+ xfs_inode_t *ip)
+{
+ vnode_t *vp;
+
+ vp = XFS_ITOV_NULL(ip);
+ if (vp) {
+ struct inode *inode = &vp->v_inode;
+ ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
+ ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
+ }
+}
/*
* Change the requested timestamp in the given inode.
@@ -73,23 +109,6 @@ xfs_ichgtime(
struct inode *inode = LINVFS_GET_IP(XFS_ITOV(ip));
timespec_t tv;
- /*
- * We're not supposed to change timestamps in readonly-mounted
- * filesystems. Throw it away if anyone asks us.
- */
- if (unlikely(IS_RDONLY(inode)))
- return;
-
- /*
- * Don't update access timestamps on reads if mounted "noatime".
- * Throw it away if anyone asks us.
- */
- if (unlikely(
- (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
- (flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) ==
- XFS_ICHGTIME_ACC))
- return;
-
nanotime(&tv);
if (flags & XFS_ICHGTIME_MOD) {
inode->i_mtime = tv;
@@ -126,8 +145,6 @@ xfs_ichgtime(
* Variant on the above which avoids querying the system clock
* in situations where we know the Linux inode timestamps have
* just been updated (and so we can update our inode cheaply).
- * We also skip the readonly and noatime checks here, they are
- * also catered for already.
*/
void
xfs_ichgtime_fast(
@@ -138,20 +155,16 @@ xfs_ichgtime_fast(
timespec_t *tvp;
/*
- * We're not supposed to change timestamps in readonly-mounted
- * filesystems. Throw it away if anyone asks us.
+ * Atime updates for read() & friends are handled lazily now, and
+ * explicit updates must go through xfs_ichgtime()
*/
- if (unlikely(IS_RDONLY(inode)))
- return;
+ ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
/*
- * Don't update access timestamps on reads if mounted "noatime".
- * Throw it away if anyone asks us.
+ * We're not supposed to change timestamps in readonly-mounted
+ * filesystems. Throw it away if anyone asks us.
*/
- if (unlikely(
- (ip->i_mount->m_flags & XFS_MOUNT_NOATIME || IS_NOATIME(inode)) &&
- ((flags & (XFS_ICHGTIME_ACC|XFS_ICHGTIME_MOD|XFS_ICHGTIME_CHG)) ==
- XFS_ICHGTIME_ACC)))
+ if (unlikely(IS_RDONLY(inode)))
return;
if (flags & XFS_ICHGTIME_MOD) {
@@ -159,11 +172,6 @@ xfs_ichgtime_fast(
ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
}
- if (flags & XFS_ICHGTIME_ACC) {
- tvp = &inode->i_atime;
- ip->i_d.di_atime.t_sec = (__int32_t)tvp->tv_sec;
- ip->i_d.di_atime.t_nsec = (__int32_t)tvp->tv_nsec;
- }
if (flags & XFS_ICHGTIME_CHG) {
tvp = &inode->i_ctime;
ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
@@ -203,13 +211,46 @@ validate_fields(
ip->i_nlink = va.va_nlink;
ip->i_blocks = va.va_nblocks;
- /* we're under i_sem so i_size can't change under us */
+ /* we're under i_mutex so i_size can't change under us */
if (i_size_read(ip) != va.va_size)
i_size_write(ip, va.va_size);
}
}
/*
+ * Hook in SELinux. This is not quite correct yet, what we really need
+ * here (as we do for default ACLs) is a mechanism by which creation of
+ * these attrs can be journalled at inode creation time (along with the
+ * inode, of course, such that log replay can't cause these to be lost).
+ */
+STATIC int
+linvfs_init_security(
+ struct vnode *vp,
+ struct inode *dir)
+{
+ struct inode *ip = LINVFS_GET_IP(vp);
+ size_t length;
+ void *value;
+ char *name;
+ int error;
+
+ error = security_inode_init_security(ip, dir, &name, &value, &length);
+ if (error) {
+ if (error == -EOPNOTSUPP)
+ return 0;
+ return -error;
+ }
+
+ VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error);
+ if (!error)
+ VMODIFY(vp);
+
+ kfree(name);
+ kfree(value);
+ return error;
+}
+
+/*
* Determine whether a process has a valid fs_struct (kernel daemons
* like knfsd don't have an fs_struct).
*
@@ -274,6 +315,9 @@ linvfs_mknod(
break;
}
+ if (!error)
+ error = linvfs_init_security(vp, dir);
+
if (default_acl) {
if (!error) {
error = _ACL_INHERIT(vp, &va, default_acl);
@@ -290,8 +334,6 @@ linvfs_mknod(
teardown.d_inode = ip = LINVFS_GET_IP(vp);
teardown.d_name = dentry->d_name;
- vn_mark_bad(vp);
-
if (S_ISDIR(mode))
VOP_RMDIR(dvp, &teardown, NULL, err2);
else
@@ -429,11 +471,14 @@ linvfs_symlink(
error = 0;
VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error);
- if (!error && cvp) {
- ip = LINVFS_GET_IP(cvp);
- d_instantiate(dentry, ip);
- validate_fields(dir);
- validate_fields(ip); /* size needs update */
+ if (likely(!error && cvp)) {
+ error = linvfs_init_security(cvp, dir);
+ if (likely(!error)) {
+ ip = LINVFS_GET_IP(cvp);
+ d_instantiate(dentry, ip);
+ validate_fields(dir);
+ validate_fields(ip);
+ }
}
return -error;
}
@@ -502,7 +547,7 @@ linvfs_follow_link(
ASSERT(dentry);
ASSERT(nd);
- link = (char *)kmalloc(MAXNAMELEN+1, GFP_KERNEL);
+ link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL);
if (!link) {
nd_set_link(nd, ERR_PTR(-ENOMEM));
return NULL;
@@ -518,12 +563,12 @@ linvfs_follow_link(
vp = LINVFS_GET_VP(dentry->d_inode);
iov.iov_base = link;
- iov.iov_len = MAXNAMELEN;
+ iov.iov_len = MAXPATHLEN;
uio->uio_iov = &iov;
uio->uio_offset = 0;
uio->uio_segflg = UIO_SYSSPACE;
- uio->uio_resid = MAXNAMELEN;
+ uio->uio_resid = MAXPATHLEN;
uio->uio_iovcnt = 1;
VOP_READLINK(vp, uio, 0, NULL, error);
@@ -531,7 +576,7 @@ linvfs_follow_link(
kfree(link);
link = ERR_PTR(-error);
} else {
- link[MAXNAMELEN - uio->uio_resid] = '\0';
+ link[MAXPATHLEN - uio->uio_resid] = '\0';
}
kfree(uio);
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index ee784b63acbf..6899a6b4a50a 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -26,11 +26,6 @@ extern struct file_operations linvfs_file_operations;
extern struct file_operations linvfs_invis_file_operations;
extern struct file_operations linvfs_dir_operations;
-extern struct address_space_operations linvfs_aops;
-
-extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
-extern void linvfs_unwritten_done(struct buffer_head *, int);
-
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, unsigned int, void __user *);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index d8e21ba0cccc..67389b745526 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -110,10 +110,6 @@
* delalloc and these ondisk-uninitialised buffers.
*/
BUFFER_FNS(PrivateStart, unwritten);
-static inline void set_buffer_unwritten_io(struct buffer_head *bh)
-{
- bh->b_end_io = linvfs_unwritten_done;
-}
#define restricted_chown xfs_params.restrict_chown.val
#define irix_sgid_inherit xfs_params.sgid_inherit.val
@@ -232,7 +228,7 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#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); \
+ ({ u64 id = huge_encode_dev((mp)->m_ddev_targp->bt_dev); \
__kernel_fsid_t *fsid = &(statp)->f_fsid; \
(fsid->val[0] = (u32)id, fsid->val[1] = (u32)(id >> 32)); })
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 279e9bc92aba..e0ab45fbfebd 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -233,8 +233,8 @@ xfs_read(
xfs_buftarg_t *target =
(ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
- if ((*offset & target->pbr_smask) ||
- (size & target->pbr_smask)) {
+ if ((*offset & target->bt_smask) ||
+ (size & target->bt_smask)) {
if (*offset == ip->i_d.di_size) {
return (0);
}
@@ -254,7 +254,7 @@ xfs_read(
}
if (unlikely(ioflags & IO_ISDIRECT))
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
@@ -281,12 +281,9 @@ xfs_read(
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- if (likely(!(ioflags & IO_INVIS)))
- xfs_ichgtime_fast(ip, inode, XFS_ICHGTIME_ACC);
-
unlock_isem:
if (unlikely(ioflags & IO_ISDIRECT))
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return ret;
}
@@ -346,9 +343,6 @@ xfs_sendfile(
if (ret > 0)
XFS_STATS_ADD(xs_read_bytes, ret);
- if (likely(!(ioflags & IO_INVIS)))
- xfs_ichgtime_fast(ip, LINVFS_GET_IP(vp), XFS_ICHGTIME_ACC);
-
return ret;
}
@@ -362,7 +356,6 @@ STATIC int /* error (positive) */
xfs_zero_last_block(
struct inode *ip,
xfs_iocore_t *io,
- xfs_off_t offset,
xfs_fsize_t isize,
xfs_fsize_t end_size)
{
@@ -371,19 +364,16 @@ xfs_zero_last_block(
int nimaps;
int zero_offset;
int zero_len;
- int isize_fsb_offset;
int error = 0;
xfs_bmbt_irec_t imap;
loff_t loff;
- size_t lsize;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
- ASSERT(offset > isize);
mp = io->io_mount;
- isize_fsb_offset = XFS_B_FSB_OFFSET(mp, isize);
- if (isize_fsb_offset == 0) {
+ zero_offset = XFS_B_FSB_OFFSET(mp, isize);
+ if (zero_offset == 0) {
/*
* There are no extra bytes in the last block on disk to
* zero, so return.
@@ -413,10 +403,8 @@ xfs_zero_last_block(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
loff = XFS_FSB_TO_B(mp, last_fsb);
- lsize = XFS_FSB_TO_B(mp, 1);
- zero_offset = isize_fsb_offset;
- zero_len = mp->m_sb.sb_blocksize - isize_fsb_offset;
+ zero_len = mp->m_sb.sb_blocksize - zero_offset;
error = xfs_iozero(ip, loff + zero_offset, zero_len, end_size);
@@ -447,20 +435,17 @@ xfs_zero_eof(
struct inode *ip = LINVFS_GET_IP(vp);
xfs_fileoff_t start_zero_fsb;
xfs_fileoff_t end_zero_fsb;
- xfs_fileoff_t prev_zero_fsb;
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb;
- xfs_extlen_t prev_zero_count;
xfs_mount_t *mp;
int nimaps;
int error = 0;
xfs_bmbt_irec_t imap;
- loff_t loff;
- size_t lsize;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
+ ASSERT(offset > isize);
mp = io->io_mount;
@@ -468,7 +453,7 @@ xfs_zero_eof(
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
*/
- error = xfs_zero_last_block(ip, io, offset, isize, end_size);
+ error = xfs_zero_last_block(ip, io, isize, end_size);
if (error) {
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -496,8 +481,6 @@ xfs_zero_eof(
}
ASSERT(start_zero_fsb <= end_zero_fsb);
- prev_zero_fsb = NULLFILEOFF;
- prev_zero_count = 0;
while (start_zero_fsb <= end_zero_fsb) {
nimaps = 1;
zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
@@ -519,10 +502,7 @@ xfs_zero_eof(
* that sits on a hole and sets the page as P_HOLE
* and calls remapf if it is a mapped file.
*/
- prev_zero_fsb = NULLFILEOFF;
- prev_zero_count = 0;
- start_zero_fsb = imap.br_startoff +
- imap.br_blockcount;
+ start_zero_fsb = imap.br_startoff + imap.br_blockcount;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
continue;
}
@@ -543,17 +523,15 @@ xfs_zero_eof(
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
- loff = XFS_FSB_TO_B(mp, start_zero_fsb);
- lsize = XFS_FSB_TO_B(mp, buf_len_fsb);
-
- error = xfs_iozero(ip, loff, lsize, end_size);
+ error = xfs_iozero(ip,
+ XFS_FSB_TO_B(mp, start_zero_fsb),
+ XFS_FSB_TO_B(mp, buf_len_fsb),
+ end_size);
if (error) {
goto out_lock;
}
- prev_zero_fsb = start_zero_fsb;
- prev_zero_count = buf_len_fsb;
start_zero_fsb = imap.br_startoff + buf_len_fsb;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
@@ -640,7 +618,7 @@ xfs_write(
(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
mp->m_rtdev_targp : mp->m_ddev_targp;
- if ((pos & target->pbr_smask) || (count & target->pbr_smask))
+ if ((pos & target->bt_smask) || (count & target->bt_smask))
return XFS_ERROR(-EINVAL);
if (!VN_CACHED(vp) && pos < i_size_read(inode))
@@ -655,7 +633,7 @@ relock:
iolock = XFS_IOLOCK_EXCL;
locktype = VRWLOCK_WRITE;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
} else {
iolock = XFS_IOLOCK_SHARED;
locktype = VRWLOCK_WRITE_DIRECT;
@@ -686,7 +664,7 @@ start:
int dmflags = FILP_DELAY_FLAG(file);
if (need_isem)
- dmflags |= DM_FLAGS_ISEM;
+ dmflags |= DM_FLAGS_IMUX;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
@@ -713,7 +691,7 @@ start:
}
if (likely(!(ioflags & IO_INVIS))) {
- inode_update_time(inode, 1);
+ file_update_time(file);
xfs_ichgtime_fast(xip, inode,
XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
}
@@ -772,7 +750,7 @@ retry:
if (need_isem) {
/* demote the lock now the cached pages are gone */
XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
iolock = XFS_IOLOCK_SHARED;
locktype = VRWLOCK_WRITE_DIRECT;
@@ -817,20 +795,24 @@ retry:
xfs_rwunlock(bdp, locktype);
if (need_isem)
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
0, 0, 0); /* Delay flag intentionally unused */
if (error)
goto out_nounlocks;
if (need_isem)
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
xfs_rwlock(bdp, locktype);
pos = xip->i_d.di_size;
ret = 0;
goto retry;
}
+ isize = i_size_read(inode);
+ if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
+ *offset = isize;
+
if (*offset > xip->i_d.di_size) {
xfs_ilock(xip, XFS_ILOCK_EXCL);
if (*offset > xip->i_d.di_size) {
@@ -926,7 +908,7 @@ retry:
xfs_rwunlock(bdp, locktype);
if (need_isem)
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
error = sync_page_range(inode, mapping, pos, ret);
if (!error)
@@ -938,7 +920,7 @@ retry:
xfs_rwunlock(bdp, locktype);
out_unlock_isem:
if (need_isem)
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
out_nounlocks:
return -error;
}
@@ -956,7 +938,7 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
if (!XFS_FORCED_SHUTDOWN(mp)) {
- pagebuf_iorequest(bp);
+ xfs_buf_iorequest(bp);
return 0;
} else {
xfs_buftrace("XFS__BDSTRAT IOERROR", bp);
@@ -1009,7 +991,7 @@ xfsbdstrat(
* if (XFS_BUF_IS_GRIO(bp)) {
*/
- pagebuf_iorequest(bp);
+ xfs_buf_iorequest(bp);
return 0;
}
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
index 6c40a74be7c8..8955720a2c6b 100644
--- a/fs/xfs/linux-2.6/xfs_stats.c
+++ b/fs/xfs/linux-2.6/xfs_stats.c
@@ -34,7 +34,7 @@ xfs_read_xfsstats(
__uint64_t xs_write_bytes = 0;
__uint64_t xs_read_bytes = 0;
- static struct xstats_entry {
+ static const struct xstats_entry {
char *desc;
int endpoint;
} xstats[] = {
diff --git a/fs/xfs/linux-2.6/xfs_stats.h b/fs/xfs/linux-2.6/xfs_stats.h
index 50027c4a5618..8ba7a2fa6c1d 100644
--- a/fs/xfs/linux-2.6/xfs_stats.h
+++ b/fs/xfs/linux-2.6/xfs_stats.h
@@ -109,15 +109,15 @@ struct xfsstats {
__uint32_t vn_remove; /* # times vn_remove called */
__uint32_t vn_free; /* # times vn_free called */
#define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9)
- __uint32_t pb_get;
- __uint32_t pb_create;
- __uint32_t pb_get_locked;
- __uint32_t pb_get_locked_waited;
- __uint32_t pb_busy_locked;
- __uint32_t pb_miss_locked;
- __uint32_t pb_page_retries;
- __uint32_t pb_page_found;
- __uint32_t pb_get_read;
+ __uint32_t xb_get;
+ __uint32_t xb_create;
+ __uint32_t xb_get_locked;
+ __uint32_t xb_get_locked_waited;
+ __uint32_t xb_busy_locked;
+ __uint32_t xb_miss_locked;
+ __uint32_t xb_page_retries;
+ __uint32_t xb_page_found;
+ __uint32_t xb_get_read;
/* Extra precision counters */
__uint64_t xs_xstrat_bytes;
__uint64_t xs_write_bytes;
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 6116b5bf433e..f22e426d9e42 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -306,13 +306,15 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)
xfs_fs_cmn_err(CE_NOTE, mp,
"Disabling barriers, not supported with external log device");
mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ return;
}
- if (mp->m_ddev_targp->pbr_bdev->bd_disk->queue->ordered ==
+ if (mp->m_ddev_targp->bt_bdev->bd_disk->queue->ordered ==
QUEUE_ORDERED_NONE) {
xfs_fs_cmn_err(CE_NOTE, mp,
"Disabling barriers, not supported by the underlying device");
mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ return;
}
error = xfs_barrier_test(mp);
@@ -320,6 +322,7 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)
xfs_fs_cmn_err(CE_NOTE, mp,
"Disabling barriers, trial barrier write failed");
mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ return;
}
}
@@ -327,7 +330,7 @@ void
xfs_blkdev_issue_flush(
xfs_buftarg_t *buftarg)
{
- blkdev_issue_flush(buftarg->pbr_bdev, NULL);
+ blkdev_issue_flush(buftarg->bt_bdev, NULL);
}
STATIC struct inode *
@@ -576,7 +579,7 @@ xfssyncd(
timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
- if (kthread_should_stop())
+ if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list))
break;
spin_lock(&vfsp->vfs_sync_lock);
@@ -966,9 +969,9 @@ init_xfs_fs( void )
if (error < 0)
goto undo_zones;
- error = pagebuf_init();
+ error = xfs_buf_init();
if (error < 0)
- goto undo_pagebuf;
+ goto undo_buffers;
vn_init();
xfs_init();
@@ -982,9 +985,9 @@ init_xfs_fs( void )
return 0;
undo_register:
- pagebuf_terminate();
+ xfs_buf_terminate();
-undo_pagebuf:
+undo_buffers:
linvfs_destroy_zones();
undo_zones:
@@ -998,7 +1001,7 @@ exit_xfs_fs( void )
XFS_DM_EXIT(&xfs_fs_type);
unregister_filesystem(&xfs_fs_type);
xfs_cleanup();
- pagebuf_terminate();
+ xfs_buf_terminate();
linvfs_destroy_zones();
ktrace_uninit();
}
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index e9bbcb4d6243..260dd8415dd7 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -106,7 +106,6 @@ vn_revalidate_core(
inode->i_blocks = vap->va_nblocks;
inode->i_mtime = vap->va_mtime;
inode->i_ctime = vap->va_ctime;
- inode->i_atime = vap->va_atime;
inode->i_blksize = vap->va_blocksize;
if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
inode->i_flags |= S_IMMUTABLE;
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index f2bbb327c081..0fe2419461d6 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -566,6 +566,25 @@ static inline int VN_BAD(struct vnode *vp)
}
/*
+ * Extracting atime values in various formats
+ */
+static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime)
+{
+ bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
+ bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
+}
+
+static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts)
+{
+ *ts = vp->v_inode.i_atime;
+}
+
+static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
+{
+ *tt = vp->v_inode.i_atime.tv_sec;
+}
+
+/*
* Some useful predicates.
*/
#define VN_MAPPED(vp) mapping_mapped(LINVFS_GET_IP(vp)->i_mapping)
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 00b5043dfa5a..772ac48329ea 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -104,7 +104,7 @@ xfs_qm_dqinit(
*/
if (brandnewdquot) {
dqp->dq_flnext = dqp->dq_flprev = dqp;
- mutex_init(&dqp->q_qlock, MUTEX_DEFAULT, "xdq");
+ mutex_init(&dqp->q_qlock);
initnsema(&dqp->q_flock, 1, "fdq");
sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
@@ -1382,7 +1382,7 @@ void
xfs_dqlock(
xfs_dquot_t *dqp)
{
- mutex_lock(&(dqp->q_qlock), PINOD);
+ mutex_lock(&(dqp->q_qlock));
}
void
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 2f69822344e5..2ec6b441849c 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -239,7 +239,7 @@ xfs_qm_dquot_logitem_pushbuf(
* trying to duplicate our effort.
*/
ASSERT(qip->qli_pushbuf_flag != 0);
- ASSERT(qip->qli_push_owner == get_thread_id());
+ ASSERT(qip->qli_push_owner == current_pid());
/*
* If flushlock isn't locked anymore, chances are that the
@@ -333,7 +333,7 @@ xfs_qm_dquot_logitem_trylock(
qip->qli_pushbuf_flag = 1;
ASSERT(qip->qli_format.qlf_blkno == dqp->q_blkno);
#ifdef DEBUG
- qip->qli_push_owner = get_thread_id();
+ qip->qli_push_owner = current_pid();
#endif
/*
* The dquot is left locked.
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 5328a2937127..53a00fb217fa 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -167,7 +167,7 @@ xfs_Gqm_init(void)
xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO;
xqm->qm_nrefs = 0;
#ifdef DEBUG
- mutex_init(&qcheck_lock, MUTEX_DEFAULT, "qchk");
+ mutex_init(&qcheck_lock);
#endif
return xqm;
}
@@ -497,7 +497,7 @@ xfs_qm_dqflush_all(
int error;
if (mp->m_quotainfo == NULL)
- return (0);
+ return 0;
niters = 0;
again:
xfs_qm_mplist_lock(mp);
@@ -528,7 +528,7 @@ again:
error = xfs_qm_dqflush(dqp, flags);
xfs_dqunlock(dqp);
if (error)
- return (error);
+ return error;
xfs_qm_mplist_lock(mp);
if (recl != XFS_QI_MPLRECLAIMS(mp)) {
@@ -540,7 +540,7 @@ again:
xfs_qm_mplist_unlock(mp);
/* return ! busy */
- return (0);
+ return 0;
}
/*
* Release the group dquot pointers the user dquots may be
@@ -599,7 +599,7 @@ xfs_qm_dqpurge_int(
int nmisses;
if (mp->m_quotainfo == NULL)
- return (0);
+ return 0;
dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
@@ -796,7 +796,7 @@ xfs_qm_dqattach_one(
ASSERT(XFS_DQ_IS_LOCKED(dqp));
}
#endif
- return (error);
+ return error;
}
@@ -897,7 +897,7 @@ xfs_qm_dqattach(
(! XFS_NOT_DQATTACHED(mp, ip)) ||
(ip->i_ino == mp->m_sb.sb_uquotino) ||
(ip->i_ino == mp->m_sb.sb_gquotino))
- return (0);
+ return 0;
ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 ||
XFS_ISLOCKED_INODE_EXCL(ip));
@@ -984,7 +984,7 @@ xfs_qm_dqattach(
else
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
#endif
- return (error);
+ return error;
}
/*
@@ -1049,7 +1049,7 @@ xfs_qm_sync(
*/
if (! XFS_IS_QUOTA_ON(mp)) {
xfs_qm_mplist_unlock(mp);
- return (0);
+ return 0;
}
FOREACH_DQUOT_IN_MP(dqp, mp) {
/*
@@ -1109,9 +1109,9 @@ xfs_qm_sync(
error = xfs_qm_dqflush(dqp, flush_flags);
xfs_dqunlock(dqp);
if (error && XFS_FORCED_SHUTDOWN(mp))
- return(0); /* Need to prevent umount failure */
+ return 0; /* Need to prevent umount failure */
else if (error)
- return (error);
+ return error;
xfs_qm_mplist_lock(mp);
if (recl != XFS_QI_MPLRECLAIMS(mp)) {
@@ -1124,7 +1124,7 @@ xfs_qm_sync(
}
xfs_qm_mplist_unlock(mp);
- return (0);
+ return 0;
}
@@ -1146,7 +1146,7 @@ xfs_qm_init_quotainfo(
* Tell XQM that we exist as soon as possible.
*/
if ((error = xfs_qm_hold_quotafs_ref(mp))) {
- return (error);
+ return error;
}
qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
@@ -1158,7 +1158,7 @@ xfs_qm_init_quotainfo(
if ((error = xfs_qm_init_quotainos(mp))) {
kmem_free(qinf, sizeof(xfs_quotainfo_t));
mp->m_quotainfo = NULL;
- return (error);
+ return error;
}
spinlock_init(&qinf->qi_pinlock, "xfs_qinf_pin");
@@ -1166,7 +1166,7 @@ xfs_qm_init_quotainfo(
qinf->qi_dqreclaims = 0;
/* mutex used to serialize quotaoffs */
- mutex_init(&qinf->qi_quotaofflock, MUTEX_DEFAULT, "qoff");
+ mutex_init(&qinf->qi_quotaofflock);
/* Precalc some constants */
qinf->qi_dqchunklen = XFS_FSB_TO_BB(mp, XFS_DQUOT_CLUSTER_SIZE_FSB);
@@ -1232,7 +1232,7 @@ xfs_qm_init_quotainfo(
qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
}
- return (0);
+ return 0;
}
@@ -1285,7 +1285,7 @@ xfs_qm_list_init(
char *str,
int n)
{
- mutex_init(&list->qh_lock, MUTEX_DEFAULT, str);
+ mutex_init(&list->qh_lock);
list->qh_next = NULL;
list->qh_version = 0;
list->qh_nelems = 0;
@@ -1332,7 +1332,7 @@ xfs_qm_dqget_noattach(
*/
ASSERT(error != ESRCH);
ASSERT(error != ENOENT);
- return (error);
+ return error;
}
ASSERT(udqp);
}
@@ -1355,7 +1355,7 @@ xfs_qm_dqget_noattach(
xfs_qm_dqrele(udqp);
ASSERT(error != ESRCH);
ASSERT(error != ENOENT);
- return (error);
+ return error;
}
ASSERT(gdqp);
@@ -1376,7 +1376,7 @@ xfs_qm_dqget_noattach(
if (udqp) ASSERT(XFS_DQ_IS_LOCKED(udqp));
if (gdqp) ASSERT(XFS_DQ_IS_LOCKED(gdqp));
#endif
- return (0);
+ return 0;
}
/*
@@ -1392,26 +1392,28 @@ xfs_qm_qino_alloc(
{
xfs_trans_t *tp;
int error;
- unsigned long s;
+ unsigned long s;
cred_t zerocr;
+ xfs_inode_t zeroino;
int committed;
- tp = xfs_trans_alloc(mp,XFS_TRANS_QM_QINOCREATE);
+ tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
if ((error = xfs_trans_reserve(tp,
XFS_QM_QINOCREATE_SPACE_RES(mp),
XFS_CREATE_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES,
XFS_CREATE_LOG_COUNT))) {
xfs_trans_cancel(tp, 0);
- return (error);
+ return error;
}
memset(&zerocr, 0, sizeof(zerocr));
+ memset(&zeroino, 0, sizeof(zeroino));
- if ((error = xfs_dir_ialloc(&tp, mp->m_rootip, S_IFREG, 1, 0,
+ if ((error = xfs_dir_ialloc(&tp, &zeroino, S_IFREG, 1, 0,
&zerocr, 0, 1, ip, &committed))) {
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
XFS_TRANS_ABORT);
- return (error);
+ return error;
}
/*
@@ -1459,9 +1461,9 @@ xfs_qm_qino_alloc(
if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
NULL))) {
xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!");
- return (error);
+ return error;
}
- return (0);
+ return 0;
}
@@ -1506,7 +1508,7 @@ xfs_qm_reset_dqcounts(
ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
}
- return (0);
+ return 0;
}
STATIC int
@@ -1555,7 +1557,7 @@ xfs_qm_dqiter_bufs(
bno++;
firstid += XFS_QM_DQPERBLK(mp);
}
- return (error);
+ return error;
}
/*
@@ -1584,7 +1586,7 @@ xfs_qm_dqiterate(
* happens only at mount time which is single threaded.
*/
if (qip->i_d.di_nblocks == 0)
- return (0);
+ return 0;
map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), KM_SLEEP);
@@ -1653,7 +1655,7 @@ xfs_qm_dqiterate(
kmem_free(map, XFS_DQITER_MAP_SIZE * sizeof(*map));
- return (error);
+ return error;
}
/*
@@ -1713,7 +1715,7 @@ xfs_qm_get_rtblks(
ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
if (!(ifp->if_flags & XFS_IFEXTENTS)) {
if ((error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK)))
- return (error);
+ return error;
}
rtblks = 0;
nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
@@ -1721,7 +1723,7 @@ xfs_qm_get_rtblks(
for (ep = base; ep < &base[nextents]; ep++)
rtblks += xfs_bmbt_get_blockcount(ep);
*O_rtblks = (xfs_qcnt_t)rtblks;
- return (0);
+ return 0;
}
/*
@@ -1765,7 +1767,7 @@ xfs_qm_dqusage_adjust(
*/
if ((error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_EXCL, &ip, bno))) {
*res = BULKSTAT_RV_NOTHING;
- return (error);
+ return error;
}
if (ip->i_d.di_mode == 0) {
@@ -1783,7 +1785,7 @@ xfs_qm_dqusage_adjust(
if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) {
xfs_iput(ip, XFS_ILOCK_EXCL);
*res = BULKSTAT_RV_GIVEUP;
- return (error);
+ return error;
}
rtblks = 0;
@@ -1800,7 +1802,7 @@ xfs_qm_dqusage_adjust(
if (gdqp)
xfs_qm_dqput(gdqp);
*res = BULKSTAT_RV_GIVEUP;
- return (error);
+ return error;
}
nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
}
@@ -1845,7 +1847,7 @@ xfs_qm_dqusage_adjust(
* Goto next inode.
*/
*res = BULKSTAT_RV_DIDONE;
- return (0);
+ return 0;
}
/*
@@ -1918,9 +1920,7 @@ xfs_qm_quotacheck(
* at this point (because we intentionally didn't in dqget_noattach).
*/
if (error) {
- xfs_qm_dqpurge_all(mp,
- XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
- XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
+ xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF);
goto error_return;
}
/*
@@ -2041,7 +2041,7 @@ xfs_qm_init_quotainos(
XFS_QI_UQIP(mp) = uip;
XFS_QI_GQIP(mp) = gip;
- return (0);
+ return 0;
}
@@ -2062,7 +2062,7 @@ xfs_qm_shake_freelist(
int nflushes;
if (howmany <= 0)
- return (0);
+ return 0;
nreclaimed = 0;
restarts = 0;
@@ -2088,7 +2088,7 @@ xfs_qm_shake_freelist(
xfs_dqunlock(dqp);
xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
- return (nreclaimed);
+ return nreclaimed;
XQM_STATS_INC(xqmstats.xs_qm_dqwants);
goto tryagain;
}
@@ -2163,7 +2163,7 @@ xfs_qm_shake_freelist(
XFS_DQ_HASH_UNLOCK(hash);
xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
- return (nreclaimed);
+ return nreclaimed;
goto tryagain;
}
xfs_dqtrace_entry(dqp, "DQSHAKE: UNLINKING");
@@ -2188,7 +2188,7 @@ xfs_qm_shake_freelist(
dqp = nextdqp;
}
xfs_qm_freelist_unlock(xfs_Gqm);
- return (nreclaimed);
+ return nreclaimed;
}
@@ -2202,9 +2202,9 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
int ndqused, nfree, n;
if (!kmem_shake_allow(gfp_mask))
- return (0);
+ return 0;
if (!xfs_Gqm)
- return (0);
+ return 0;
nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */
/* incore dquots in all f/s's */
@@ -2213,7 +2213,7 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
ASSERT(ndqused >= 0);
if (nfree <= ndqused && nfree < ndquot)
- return (0);
+ return 0;
ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */
n = nfree - ndqused - ndquot; /* # over target */
@@ -2257,7 +2257,7 @@ xfs_qm_dqreclaim_one(void)
xfs_dqunlock(dqp);
xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
- return (NULL);
+ return NULL;
XQM_STATS_INC(xqmstats.xs_qm_dqwants);
goto startagain;
}
@@ -2333,7 +2333,7 @@ xfs_qm_dqreclaim_one(void)
}
xfs_qm_freelist_unlock(xfs_Gqm);
- return (dqpout);
+ return dqpout;
}
@@ -2369,7 +2369,7 @@ xfs_qm_dqalloc_incore(
*/
memset(&dqp->q_core, 0, sizeof(dqp->q_core));
*O_dqpp = dqp;
- return (B_FALSE);
+ return B_FALSE;
}
XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);
}
@@ -2382,7 +2382,7 @@ xfs_qm_dqalloc_incore(
*O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
atomic_inc(&xfs_Gqm->qm_totaldquots);
- return (B_TRUE);
+ return B_TRUE;
}
@@ -2407,13 +2407,13 @@ xfs_qm_write_sb_changes(
0,
XFS_DEFAULT_LOG_COUNT))) {
xfs_trans_cancel(tp, 0);
- return (error);
+ return error;
}
xfs_mod_sb(tp, flags);
(void) xfs_trans_commit(tp, 0, NULL);
- return (0);
+ return 0;
}
@@ -2463,7 +2463,7 @@ xfs_qm_vop_dqalloc(
if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_DQALLOC |
XFS_QMOPT_ILOCKED))) {
xfs_iunlock(ip, lockflags);
- return (error);
+ return error;
}
}
@@ -2486,7 +2486,7 @@ xfs_qm_vop_dqalloc(
XFS_QMOPT_DOWARN,
&uq))) {
ASSERT(error != ENOENT);
- return (error);
+ return error;
}
/*
* Get the ilock in the right order.
@@ -2517,7 +2517,7 @@ xfs_qm_vop_dqalloc(
if (uq)
xfs_qm_dqrele(uq);
ASSERT(error != ENOENT);
- return (error);
+ return error;
}
xfs_dqunlock(gq);
lockflags = XFS_ILOCK_SHARED;
@@ -2565,7 +2565,7 @@ xfs_qm_vop_dqalloc(
*O_gdqpp = gq;
else if (gq)
xfs_qm_dqrele(gq);
- return (0);
+ return 0;
}
/*
@@ -2608,7 +2608,7 @@ xfs_qm_vop_chown(
xfs_dqunlock(newdq);
*IO_olddq = newdq;
- return (prevdq);
+ return prevdq;
}
/*
@@ -2702,12 +2702,12 @@ xfs_qm_vop_rename_dqattach(
ip = i_tab[0];
if (! XFS_IS_QUOTA_ON(ip->i_mount))
- return (0);
+ return 0;
if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) {
error = xfs_qm_dqattach(ip, 0);
if (error)
- return (error);
+ return error;
}
for (i = 1; (i < 4 && i_tab[i]); i++) {
/*
@@ -2717,11 +2717,11 @@ xfs_qm_vop_rename_dqattach(
if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) {
error = xfs_qm_dqattach(ip, 0);
if (error)
- return (error);
+ return error;
}
}
}
- return (0);
+ return 0;
}
void
@@ -2743,6 +2743,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
xfs_dqunlock(udqp);
ASSERT(ip->i_udquot == NULL);
ip->i_udquot = udqp;
+ ASSERT(XFS_IS_UQUOTA_ON(tp->t_mountp));
ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
}
@@ -2752,7 +2753,10 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
xfs_dqunlock(gdqp);
ASSERT(ip->i_gdquot == NULL);
ip->i_gdquot = gdqp;
- ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
+ ASSERT(XFS_IS_OQUOTA_ON(tp->t_mountp));
+ ASSERT((XFS_IS_GQUOTA_ON(tp->t_mountp) ?
+ ip->i_d.di_gid : ip->i_d.di_projid) ==
+ be32_to_cpu(gdqp->q_core.d_id));
xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
}
}
@@ -2762,7 +2766,7 @@ STATIC void
xfs_qm_freelist_init(xfs_frlist_t *ql)
{
ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
- mutex_init(&ql->qh_lock, MUTEX_DEFAULT, "dqf");
+ mutex_init(&ql->qh_lock);
ql->qh_version = 0;
ql->qh_nelems = 0;
}
@@ -2772,7 +2776,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql)
{
xfs_dquot_t *dqp, *nextdqp;
- mutex_lock(&ql->qh_lock, PINOD);
+ mutex_lock(&ql->qh_lock);
for (dqp = ql->qh_next;
dqp != (xfs_dquot_t *)ql; ) {
xfs_dqlock(dqp);
@@ -2830,7 +2834,7 @@ xfs_qm_dqhashlock_nowait(
int locked;
locked = mutex_trylock(&((dqp)->q_hash->qh_lock));
- return (locked);
+ return locked;
}
int
@@ -2840,7 +2844,7 @@ xfs_qm_freelist_lock_nowait(
int locked;
locked = mutex_trylock(&(xqm->qm_dqfreelist.qh_lock));
- return (locked);
+ return locked;
}
STATIC int
@@ -2851,5 +2855,5 @@ xfs_qm_mplist_nowait(
ASSERT(mp->m_quotainfo);
locked = mutex_trylock(&(XFS_QI_MPLLOCK(mp)));
- return (locked);
+ return locked;
}
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 12da259f2fcb..4568deb6da86 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -165,7 +165,7 @@ typedef struct xfs_dquot_acct {
#define XFS_QM_IWARNLIMIT 5
#define XFS_QM_RTBWARNLIMIT 5
-#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD))
+#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock))
#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock))
#define XFS_QM_HOLD(xqm) ((xqm)->qm_nrefs++)
#define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--)
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index d9d2993de435..90402a1c3983 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -363,7 +363,7 @@ xfs_qm_init(void)
KERN_INFO "SGI XFS Quota Management subsystem\n";
printk(message);
- mutex_init(&xfs_Gqm_lock, MUTEX_DEFAULT, "xfs_qmlock");
+ mutex_init(&xfs_Gqm_lock);
vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs);
xfs_qm_init_procfs();
}
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 24690e1af659..676884394aae 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -15,6 +15,9 @@
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#include <linux/capability.h>
+
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_bit.h"
@@ -233,7 +236,7 @@ xfs_qm_scall_quotaoff(
*/
ASSERT(mp->m_quotainfo);
if (mp->m_quotainfo)
- mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
+ mutex_lock(&(XFS_QI_QOFFLOCK(mp)));
ASSERT(mp->m_quotainfo);
@@ -508,7 +511,7 @@ xfs_qm_scall_quotaon(
/*
* Switch on quota enforcement in core.
*/
- mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
+ mutex_lock(&(XFS_QI_QOFFLOCK(mp)));
mp->m_qflags |= (flags & XFS_ALL_QUOTA_ENFD);
mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
@@ -617,7 +620,7 @@ xfs_qm_scall_setqlim(
* a quotaoff from happening). (XXXThis doesn't currently happen
* because we take the vfslock before calling xfs_qm_sysent).
*/
- mutex_lock(&(XFS_QI_QOFFLOCK(mp)), PINOD);
+ mutex_lock(&(XFS_QI_QOFFLOCK(mp)));
/*
* Get the dquot (locked), and join it to the transaction.
@@ -1426,7 +1429,7 @@ xfs_qm_internalqcheck(
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
XFS_bflush(mp->m_ddev_targp);
- mutex_lock(&qcheck_lock, PINOD);
+ mutex_lock(&qcheck_lock);
/* There should be absolutely no quota activity while this
is going on. */
qmtest_udqtab = kmem_zalloc(qmtest_hashmask *
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 7a9f3beb818c..b7ddd04aae32 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -51,7 +51,7 @@
#define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next)
#define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems)
-#define XQMLCK(h) (mutex_lock(&((h)->qh_lock), PINOD))
+#define XQMLCK(h) (mutex_lock(&((h)->qh_lock)))
#define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock)))
#ifdef DEBUG
struct xfs_dqhash;
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index bb6dc91ea261..b08b3d9345b7 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -27,45 +27,12 @@ static DEFINE_SPINLOCK(xfs_err_lock);
/* Translate from CE_FOO to KERN_FOO, err_level(CE_FOO) == KERN_FOO */
#define XFS_MAX_ERR_LEVEL 7
#define XFS_ERR_MASK ((1 << 3) - 1)
-static char *err_level[XFS_MAX_ERR_LEVEL+1] =
+static const char * const err_level[XFS_MAX_ERR_LEVEL+1] =
{KERN_EMERG, KERN_ALERT, KERN_CRIT,
KERN_ERR, KERN_WARNING, KERN_NOTICE,
KERN_INFO, KERN_DEBUG};
void
-assfail(char *a, char *f, int l)
-{
- printk("XFS assertion failed: %s, file: %s, line: %d\n", a, f, l);
- BUG();
-}
-
-#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM))
-
-unsigned long
-random(void)
-{
- static unsigned long RandomValue = 1;
- /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
- register long rv = RandomValue;
- register long lo;
- register long hi;
-
- hi = rv / 127773;
- lo = rv % 127773;
- rv = 16807 * lo - 2836 * hi;
- if( rv <= 0 ) rv += 2147483647;
- return( RandomValue = rv );
-}
-
-int
-get_thread_id(void)
-{
- return current->pid;
-}
-
-#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */
-
-void
cmn_err(register int level, char *fmt, ...)
{
char *fp = fmt;
@@ -90,7 +57,6 @@ cmn_err(register int level, char *fmt, ...)
BUG();
}
-
void
icmn_err(register int level, char *fmt, va_list ap)
{
@@ -109,3 +75,27 @@ icmn_err(register int level, char *fmt, va_list ap)
if (level == CE_PANIC)
BUG();
}
+
+void
+assfail(char *expr, char *file, int line)
+{
+ printk("Assertion failed: %s, file: %s, line: %d\n", expr, file, line);
+ BUG();
+}
+
+#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM))
+unsigned long random(void)
+{
+ static unsigned long RandomValue = 1;
+ /* cycles pseudo-randomly through all values between 1 and 2^31 - 2 */
+ register long rv = RandomValue;
+ register long lo;
+ register long hi;
+
+ hi = rv / 127773;
+ lo = rv % 127773;
+ rv = 16807 * lo - 2836 * hi;
+ if (rv <= 0) rv += 2147483647;
+ return RandomValue = rv;
+}
+#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index aff558664c32..e3bf58112e7e 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -31,24 +31,23 @@ extern void icmn_err(int, char *, va_list)
__attribute__ ((format (printf, 2, 0)));
extern void cmn_err(int, char *, ...)
__attribute__ ((format (printf, 2, 3)));
+extern void assfail(char *expr, char *f, int l);
-#ifndef STATIC
-# define STATIC static
-#endif
+#define prdev(fmt,targ,args...) \
+ printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
-#ifdef DEBUG
-# define ASSERT(EX) ((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__))
-#else
-# define ASSERT(x) ((void)0)
-#endif
+#define ASSERT_ALWAYS(expr) \
+ (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
-extern void assfail(char *, char *, int);
-#ifdef DEBUG
+#ifndef DEBUG
+# define ASSERT(expr) ((void)0)
+#else
+# define ASSERT(expr) ASSERT_ALWAYS(expr)
extern unsigned long random(void);
-extern int get_thread_id(void);
#endif
-#define ASSERT_ALWAYS(EX) ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__))
-#define debug_stop_all_cpus(param) /* param is "cpumask_t *" */
+#ifndef STATIC
+# define STATIC static
+#endif
#endif /* __XFS_SUPPORT_DEBUG_H__ */
diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c
index 70ce40914c8a..a3d565a67734 100644
--- a/fs/xfs/support/uuid.c
+++ b/fs/xfs/support/uuid.c
@@ -24,9 +24,19 @@ static uuid_t *uuid_table;
void
uuid_init(void)
{
- mutex_init(&uuid_monitor, MUTEX_DEFAULT, "uuid_monitor");
+ mutex_init(&uuid_monitor);
}
+
+/* IRIX interpretation of an uuid_t */
+typedef struct {
+ __be32 uu_timelow;
+ __be16 uu_timemid;
+ __be16 uu_timehi;
+ __be16 uu_clockseq;
+ __be16 uu_node[3];
+} xfs_uu_t;
+
/*
* uuid_getnodeuniq - obtain the node unique fields of a UUID.
*
@@ -36,16 +46,11 @@ uuid_init(void)
void
uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
{
- char *uu = (char *)uuid;
-
- /* on IRIX, this function assumes big-endian fields within
- * the uuid, so we use INT_GET to get the same result on
- * little-endian systems
- */
+ xfs_uu_t *uup = (xfs_uu_t *)uuid;
- fsid[0] = (INT_GET(*(u_int16_t*)(uu+8), ARCH_CONVERT) << 16) +
- INT_GET(*(u_int16_t*)(uu+4), ARCH_CONVERT);
- fsid[1] = INT_GET(*(u_int32_t*)(uu ), ARCH_CONVERT);
+ fsid[0] = (be16_to_cpu(uup->uu_clockseq) << 16) |
+ be16_to_cpu(uup->uu_timemid);
+ fsid[1] = be16_to_cpu(uup->uu_timelow);
}
void
@@ -94,7 +99,7 @@ uuid_table_insert(uuid_t *uuid)
{
int i, hole;
- mutex_lock(&uuid_monitor, PVFS);
+ mutex_lock(&uuid_monitor);
for (i = 0, hole = -1; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i])) {
hole = i;
@@ -122,7 +127,7 @@ uuid_table_remove(uuid_t *uuid)
{
int i;
- mutex_lock(&uuid_monitor, PVFS);
+ mutex_lock(&uuid_monitor);
for (i = 0; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i]))
continue;
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index cc9c91b9e771..4ff0f4e41c61 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -36,6 +36,7 @@
#include "xfs_mac.h"
#include "xfs_attr.h"
+#include <linux/capability.h>
#include <linux/posix_acl_xattr.h>
STATIC int xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *);
diff --git a/fs/xfs/xfs_arch.h b/fs/xfs/xfs_arch.h
index 68e5051d8e24..c4836890b726 100644
--- a/fs/xfs/xfs_arch.h
+++ b/fs/xfs/xfs_arch.h
@@ -40,6 +40,22 @@
#undef XFS_NATIVE_HOST
#endif
+#ifdef XFS_NATIVE_HOST
+#define cpu_to_be16(val) ((__be16)(val))
+#define cpu_to_be32(val) ((__be32)(val))
+#define cpu_to_be64(val) ((__be64)(val))
+#define be16_to_cpu(val) ((__uint16_t)(val))
+#define be32_to_cpu(val) ((__uint32_t)(val))
+#define be64_to_cpu(val) ((__uint64_t)(val))
+#else
+#define cpu_to_be16(val) (__swab16((__uint16_t)(val)))
+#define cpu_to_be32(val) (__swab32((__uint32_t)(val)))
+#define cpu_to_be64(val) (__swab64((__uint64_t)(val)))
+#define be16_to_cpu(val) (__swab16((__be16)(val)))
+#define be32_to_cpu(val) (__swab32((__be32)(val)))
+#define be64_to_cpu(val) (__swab64((__be64)(val)))
+#endif
+
#endif /* __KERNEL__ */
/* do we need conversion? */
@@ -186,7 +202,7 @@ static inline void be64_add(__be64 *a, __s64 b)
*/
#define XFS_GET_DIR_INO4(di) \
- (((u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
+ (((__u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
#define XFS_PUT_DIR_INO4(from, di) \
do { \
@@ -197,9 +213,9 @@ do { \
} while (0)
#define XFS_DI_HI(di) \
- (((u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
+ (((__u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
#define XFS_DI_LO(di) \
- (((u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7]))
+ (((__u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7]))
#define XFS_GET_DIR_INO8(di) \
(((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index 5484eeb460c8..e5e91e9c7e89 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -15,6 +15,9 @@
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#include <linux/capability.h>
+
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_types.h"
@@ -117,11 +120,6 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
ip->i_d.di_anextents == 0))
return(ENOATTR);
- if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) {
- if ((error = xfs_iaccess(ip, S_IRUSR, cred)))
- return(XFS_ERROR(error));
- }
-
/*
* Fill in the arg structure for this request.
*/
@@ -425,7 +423,7 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
struct cred *cred)
{
xfs_inode_t *dp;
- int namelen, error;
+ int namelen;
namelen = strlen(name);
if (namelen >= MAXNAMELEN)
@@ -437,14 +435,6 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
- xfs_ilock(dp, XFS_ILOCK_SHARED);
- if (!(flags & ATTR_SECURE) &&
- (error = xfs_iaccess(dp, S_IWUSR, cred))) {
- xfs_iunlock(dp, XFS_ILOCK_SHARED);
- return(XFS_ERROR(error));
- }
- xfs_iunlock(dp, XFS_ILOCK_SHARED);
-
return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
}
@@ -579,7 +569,7 @@ int
xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
{
xfs_inode_t *dp;
- int namelen, error;
+ int namelen;
namelen = strlen(name);
if (namelen >= MAXNAMELEN)
@@ -592,11 +582,7 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
return (EIO);
xfs_ilock(dp, XFS_ILOCK_SHARED);
- if (!(flags & ATTR_SECURE) &&
- (error = xfs_iaccess(dp, S_IWUSR, cred))) {
- xfs_iunlock(dp, XFS_ILOCK_SHARED);
- return(XFS_ERROR(error));
- } else if (XFS_IFORK_Q(dp) == 0 ||
+ if (XFS_IFORK_Q(dp) == 0 ||
(dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
dp->i_d.di_anextents == 0)) {
xfs_iunlock(dp, XFS_ILOCK_SHARED);
@@ -668,12 +654,6 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
return (EIO);
xfs_ilock(dp, XFS_ILOCK_SHARED);
- if (!(flags & ATTR_SECURE) &&
- (error = xfs_iaccess(dp, S_IRUSR, cred))) {
- xfs_iunlock(dp, XFS_ILOCK_SHARED);
- return(XFS_ERROR(error));
- }
-
/*
* Decide on what work routines to call based on the inode size.
*/
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 1c7421840c18..fe91eac4e2a7 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -128,7 +128,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
return (offset >= minforkoff) ? minforkoff : 0;
}
- if (unlikely(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) {
+ if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
if (bytes <= XFS_IFORK_ASIZE(dp))
return mp->m_attroffset >> 3;
return 0;
@@ -157,7 +157,7 @@ xfs_sbversion_add_attr2(xfs_mount_t *mp, xfs_trans_t *tp)
{
unsigned long s;
- if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR) &&
+ if ((mp->m_flags & XFS_MOUNT_ATTR2) &&
!(XFS_SB_VERSION_HASATTR2(&mp->m_sb))) {
s = XFS_SB_LOCK(mp);
if (!XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
@@ -311,7 +311,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
*/
totsize -= size;
if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname &&
- !(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) {
+ (mp->m_flags & XFS_MOUNT_ATTR2)) {
/*
* Last attribute now removed, revert to original
* inode format making all literal area available
@@ -330,7 +330,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args)
dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize);
ASSERT(dp->i_d.di_forkoff);
ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname ||
- (mp->m_flags & XFS_MOUNT_COMPAT_ATTR));
+ !(mp->m_flags & XFS_MOUNT_ATTR2));
dp->i_afp->if_ext_max =
XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t);
dp->i_df.if_ext_max =
@@ -739,7 +739,7 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp)
+ name_loc->namelen
+ INT_GET(name_loc->valuelen, ARCH_CONVERT);
}
- if (!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR) &&
+ if ((dp->i_mount->m_flags & XFS_MOUNT_ATTR2) &&
(bytes == sizeof(struct xfs_attr_sf_hdr)))
return(-1);
return(xfs_attr_shortform_bytesfit(dp, bytes));
@@ -778,7 +778,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff)
goto out;
if (forkoff == -1) {
- ASSERT(!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR));
+ ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2);
/*
* Last attribute was removed, revert to original
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index f6143ff251a0..541e34109bb9 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -63,7 +63,7 @@ struct xfs_trans;
* the leaf_entry. The namespaces are independent only because we also look
* at the namespace bit when we are looking for a matching attribute name.
*
- * We also store a "incomplete" bit in the leaf_entry. It shows that an
+ * We also store an "incomplete" bit in the leaf_entry. It shows that an
* attribute is in the middle of being created and should not be shown to
* the user if we crash during the time that the bit is set. We clear the
* bit when we have finished setting up the attribute. We do this because
@@ -72,42 +72,48 @@ struct xfs_trans;
*/
#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
+typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
+ __uint16_t base; /* base of free region */
+ __uint16_t size; /* length of free region */
+} xfs_attr_leaf_map_t;
+
+typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ __uint16_t count; /* count of active leaf_entry's */
+ __uint16_t usedbytes; /* num bytes of names/values stored */
+ __uint16_t firstused; /* first used byte in name area */
+ __uint8_t holes; /* != 0 if blk needs compaction */
+ __uint8_t pad1;
+ xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
+ /* N largest free regions */
+} xfs_attr_leaf_hdr_t;
+
+typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
+ xfs_dahash_t hashval; /* hash value of name */
+ __uint16_t nameidx; /* index into buffer of name/value */
+ __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
+ __uint8_t pad2; /* unused pad byte */
+} xfs_attr_leaf_entry_t;
+
+typedef struct xfs_attr_leaf_name_local {
+ __uint16_t valuelen; /* number of bytes in value */
+ __uint8_t namelen; /* length of name bytes */
+ __uint8_t nameval[1]; /* name/value bytes */
+} xfs_attr_leaf_name_local_t;
+
+typedef struct xfs_attr_leaf_name_remote {
+ xfs_dablk_t valueblk; /* block number of value bytes */
+ __uint32_t valuelen; /* number of bytes in value */
+ __uint8_t namelen; /* length of name bytes */
+ __uint8_t name[1]; /* name bytes */
+} xfs_attr_leaf_name_remote_t;
+
typedef struct xfs_attr_leafblock {
- struct xfs_attr_leaf_hdr { /* constant-structure header block */
- xfs_da_blkinfo_t info; /* block type, links, etc. */
- __uint16_t count; /* count of active leaf_entry's */
- __uint16_t usedbytes; /* num bytes of names/values stored */
- __uint16_t firstused; /* first used byte in name area */
- __uint8_t holes; /* != 0 if blk needs compaction */
- __uint8_t pad1;
- struct xfs_attr_leaf_map { /* RLE map of free bytes */
- __uint16_t base; /* base of free region */
- __uint16_t size; /* length of free region */
- } freemap[XFS_ATTR_LEAF_MAPSIZE]; /* N largest free regions */
- } hdr;
- struct xfs_attr_leaf_entry { /* sorted on key, not name */
- xfs_dahash_t hashval; /* hash value of name */
- __uint16_t nameidx; /* index into buffer of name/value */
- __uint8_t flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
- __uint8_t pad2; /* unused pad byte */
- } entries[1]; /* variable sized array */
- struct xfs_attr_leaf_name_local {
- __uint16_t valuelen; /* number of bytes in value */
- __uint8_t namelen; /* length of name bytes */
- __uint8_t nameval[1]; /* name/value bytes */
- } namelist; /* grows from bottom of buf */
- struct xfs_attr_leaf_name_remote {
- xfs_dablk_t valueblk; /* block number of value bytes */
- __uint32_t valuelen; /* number of bytes in value */
- __uint8_t namelen; /* length of name bytes */
- __uint8_t name[1]; /* name bytes */
- } valuelist; /* grows from bottom of buf */
+ xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
+ xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
+ xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
+ xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
} xfs_attr_leafblock_t;
-typedef struct xfs_attr_leaf_hdr xfs_attr_leaf_hdr_t;
-typedef struct xfs_attr_leaf_map xfs_attr_leaf_map_t;
-typedef struct xfs_attr_leaf_entry xfs_attr_leaf_entry_t;
-typedef struct xfs_attr_leaf_name_local xfs_attr_leaf_name_local_t;
-typedef struct xfs_attr_leaf_name_remote xfs_attr_leaf_name_remote_t;
/*
* Flags used in the leaf_entry[i].flags field.
@@ -150,7 +156,8 @@ xfs_attr_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
(leafp))[INT_GET((leafp)->entries[idx].nameidx, ARCH_CONVERT)];
}
-#define XFS_ATTR_LEAF_NAME(leafp,idx) xfs_attr_leaf_name(leafp,idx)
+#define XFS_ATTR_LEAF_NAME(leafp,idx) \
+ xfs_attr_leaf_name(leafp,idx)
static inline char *xfs_attr_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
{
return (&((char *)
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index e415a4698e9c..70625e577c70 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2146,13 +2146,176 @@ xfs_bmap_add_extent_hole_real(
return 0; /* keep gcc quite */
}
+/*
+ * Adjust the size of the new extent based on di_extsize and rt extsize.
+ */
+STATIC int
+xfs_bmap_extsize_align(
+ xfs_mount_t *mp,
+ xfs_bmbt_irec_t *gotp, /* next extent pointer */
+ xfs_bmbt_irec_t *prevp, /* previous extent pointer */
+ xfs_extlen_t extsz, /* align to this extent size */
+ int rt, /* is this a realtime inode? */
+ int eof, /* is extent at end-of-file? */
+ int delay, /* creating delalloc extent? */
+ int convert, /* overwriting unwritten extent? */
+ xfs_fileoff_t *offp, /* in/out: aligned offset */
+ xfs_extlen_t *lenp) /* in/out: aligned length */
+{
+ xfs_fileoff_t orig_off; /* original offset */
+ xfs_extlen_t orig_alen; /* original length */
+ xfs_fileoff_t orig_end; /* original off+len */
+ xfs_fileoff_t nexto; /* next file offset */
+ xfs_fileoff_t prevo; /* previous file offset */
+ xfs_fileoff_t align_off; /* temp for offset */
+ xfs_extlen_t align_alen; /* temp for length */
+ xfs_extlen_t temp; /* temp for calculations */
+
+ if (convert)
+ return 0;
+
+ orig_off = align_off = *offp;
+ orig_alen = align_alen = *lenp;
+ orig_end = orig_off + orig_alen;
+
+ /*
+ * If this request overlaps an existing extent, then don't
+ * attempt to perform any additional alignment.
+ */
+ if (!delay && !eof &&
+ (orig_off >= gotp->br_startoff) &&
+ (orig_end <= gotp->br_startoff + gotp->br_blockcount)) {
+ return 0;
+ }
+
+ /*
+ * If the file offset is unaligned vs. the extent size
+ * we need to align it. This will be possible unless
+ * the file was previously written with a kernel that didn't
+ * perform this alignment, or if a truncate shot us in the
+ * foot.
+ */
+ temp = do_mod(orig_off, extsz);
+ if (temp) {
+ align_alen += temp;
+ align_off -= temp;
+ }
+ /*
+ * Same adjustment for the end of the requested area.
+ */
+ if ((temp = (align_alen % extsz))) {
+ align_alen += extsz - temp;
+ }
+ /*
+ * If the previous block overlaps with this proposed allocation
+ * then move the start forward without adjusting the length.
+ */
+ if (prevp->br_startoff != NULLFILEOFF) {
+ if (prevp->br_startblock == HOLESTARTBLOCK)
+ prevo = prevp->br_startoff;
+ else
+ prevo = prevp->br_startoff + prevp->br_blockcount;
+ } else
+ prevo = 0;
+ if (align_off != orig_off && align_off < prevo)
+ align_off = prevo;
+ /*
+ * If the next block overlaps with this proposed allocation
+ * then move the start back without adjusting the length,
+ * but not before offset 0.
+ * This may of course make the start overlap previous block,
+ * and if we hit the offset 0 limit then the next block
+ * can still overlap too.
+ */
+ if (!eof && gotp->br_startoff != NULLFILEOFF) {
+ if ((delay && gotp->br_startblock == HOLESTARTBLOCK) ||
+ (!delay && gotp->br_startblock == DELAYSTARTBLOCK))
+ nexto = gotp->br_startoff + gotp->br_blockcount;
+ else
+ nexto = gotp->br_startoff;
+ } else
+ nexto = NULLFILEOFF;
+ if (!eof &&
+ align_off + align_alen != orig_end &&
+ align_off + align_alen > nexto)
+ align_off = nexto > align_alen ? nexto - align_alen : 0;
+ /*
+ * If we're now overlapping the next or previous extent that
+ * means we can't fit an extsz piece in this hole. Just move
+ * the start forward to the first valid spot and set
+ * the length so we hit the end.
+ */
+ if (align_off != orig_off && align_off < prevo)
+ align_off = prevo;
+ if (align_off + align_alen != orig_end &&
+ align_off + align_alen > nexto &&
+ nexto != NULLFILEOFF) {
+ ASSERT(nexto > prevo);
+ align_alen = nexto - align_off;
+ }
+
+ /*
+ * If realtime, and the result isn't a multiple of the realtime
+ * extent size we need to remove blocks until it is.
+ */
+ if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) {
+ /*
+ * We're not covering the original request, or
+ * we won't be able to once we fix the length.
+ */
+ if (orig_off < align_off ||
+ orig_end > align_off + align_alen ||
+ align_alen - temp < orig_alen)
+ return XFS_ERROR(EINVAL);
+ /*
+ * Try to fix it by moving the start up.
+ */
+ if (align_off + temp <= orig_off) {
+ align_alen -= temp;
+ align_off += temp;
+ }
+ /*
+ * Try to fix it by moving the end in.
+ */
+ else if (align_off + align_alen - temp >= orig_end)
+ align_alen -= temp;
+ /*
+ * Set the start to the minimum then trim the length.
+ */
+ else {
+ align_alen -= orig_off - align_off;
+ align_off = orig_off;
+ align_alen -= align_alen % mp->m_sb.sb_rextsize;
+ }
+ /*
+ * Result doesn't cover the request, fail it.
+ */
+ if (orig_off < align_off || orig_end > align_off + align_alen)
+ return XFS_ERROR(EINVAL);
+ } else {
+ ASSERT(orig_off >= align_off);
+ ASSERT(orig_end <= align_off + align_alen);
+ }
+
+#ifdef DEBUG
+ if (!eof && gotp->br_startoff != NULLFILEOFF)
+ ASSERT(align_off + align_alen <= gotp->br_startoff);
+ if (prevp->br_startoff != NULLFILEOFF)
+ ASSERT(align_off >= prevp->br_startoff + prevp->br_blockcount);
+#endif
+
+ *lenp = align_alen;
+ *offp = align_off;
+ return 0;
+}
+
#define XFS_ALLOC_GAP_UNITS 4
/*
* xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
* It figures out where to ask the underlying allocator to put the new extent.
*/
-STATIC int /* error */
+STATIC int
xfs_bmap_alloc(
xfs_bmalloca_t *ap) /* bmap alloc argument struct */
{
@@ -2163,10 +2326,10 @@ xfs_bmap_alloc(
xfs_mount_t *mp; /* mount point structure */
int nullfb; /* true if ap->firstblock isn't set */
int rt; /* true if inode is realtime */
-#ifdef __KERNEL__
- xfs_extlen_t prod=0; /* product factor for allocators */
- xfs_extlen_t ralen=0; /* realtime allocation length */
-#endif
+ xfs_extlen_t prod = 0; /* product factor for allocators */
+ xfs_extlen_t ralen = 0; /* realtime allocation length */
+ xfs_extlen_t align; /* minimum allocation alignment */
+ xfs_rtblock_t rtx;
#define ISVALID(x,y) \
(rt ? \
@@ -2182,125 +2345,25 @@ xfs_bmap_alloc(
nullfb = ap->firstblock == NULLFSBLOCK;
rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata;
fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
-#ifdef __KERNEL__
if (rt) {
- xfs_extlen_t extsz; /* file extent size for rt */
- xfs_fileoff_t nexto; /* next file offset */
- xfs_extlen_t orig_alen; /* original ap->alen */
- xfs_fileoff_t orig_end; /* original off+len */
- xfs_fileoff_t orig_off; /* original ap->off */
- xfs_extlen_t mod_off; /* modulus calculations */
- xfs_fileoff_t prevo; /* previous file offset */
- xfs_rtblock_t rtx; /* realtime extent number */
- xfs_extlen_t temp; /* temp for rt calculations */
-
- /*
- * Set prod to match the realtime extent size.
- */
- if (!(extsz = ap->ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- prod = extsz / mp->m_sb.sb_rextsize;
- orig_off = ap->off;
- orig_alen = ap->alen;
- orig_end = orig_off + orig_alen;
- /*
- * If the file offset is unaligned vs. the extent size
- * we need to align it. This will be possible unless
- * the file was previously written with a kernel that didn't
- * perform this alignment.
- */
- mod_off = do_mod(orig_off, extsz);
- if (mod_off) {
- ap->alen += mod_off;
- ap->off -= mod_off;
- }
- /*
- * Same adjustment for the end of the requested area.
- */
- if ((temp = (ap->alen % extsz)))
- ap->alen += extsz - temp;
- /*
- * If the previous block overlaps with this proposed allocation
- * then move the start forward without adjusting the length.
- */
- prevo =
- ap->prevp->br_startoff == NULLFILEOFF ?
- 0 :
- (ap->prevp->br_startoff +
- ap->prevp->br_blockcount);
- if (ap->off != orig_off && ap->off < prevo)
- ap->off = prevo;
- /*
- * If the next block overlaps with this proposed allocation
- * then move the start back without adjusting the length,
- * but not before offset 0.
- * This may of course make the start overlap previous block,
- * and if we hit the offset 0 limit then the next block
- * can still overlap too.
- */
- nexto = (ap->eof || ap->gotp->br_startoff == NULLFILEOFF) ?
- NULLFILEOFF : ap->gotp->br_startoff;
- if (!ap->eof &&
- ap->off + ap->alen != orig_end &&
- ap->off + ap->alen > nexto)
- ap->off = nexto > ap->alen ? nexto - ap->alen : 0;
- /*
- * If we're now overlapping the next or previous extent that
- * means we can't fit an extsz piece in this hole. Just move
- * the start forward to the first valid spot and set
- * the length so we hit the end.
- */
- if ((ap->off != orig_off && ap->off < prevo) ||
- (ap->off + ap->alen != orig_end &&
- ap->off + ap->alen > nexto)) {
- ap->off = prevo;
- ap->alen = nexto - prevo;
- }
- /*
- * If the result isn't a multiple of rtextents we need to
- * remove blocks until it is.
- */
- if ((temp = (ap->alen % mp->m_sb.sb_rextsize))) {
- /*
- * We're not covering the original request, or
- * we won't be able to once we fix the length.
- */
- if (orig_off < ap->off ||
- orig_end > ap->off + ap->alen ||
- ap->alen - temp < orig_alen)
- return XFS_ERROR(EINVAL);
- /*
- * Try to fix it by moving the start up.
- */
- if (ap->off + temp <= orig_off) {
- ap->alen -= temp;
- ap->off += temp;
- }
- /*
- * Try to fix it by moving the end in.
- */
- else if (ap->off + ap->alen - temp >= orig_end)
- ap->alen -= temp;
- /*
- * Set the start to the minimum then trim the length.
- */
- else {
- ap->alen -= orig_off - ap->off;
- ap->off = orig_off;
- ap->alen -= ap->alen % mp->m_sb.sb_rextsize;
- }
- /*
- * Result doesn't cover the request, fail it.
- */
- if (orig_off < ap->off || orig_end > ap->off + ap->alen)
- return XFS_ERROR(EINVAL);
- }
+ align = ap->ip->i_d.di_extsize ?
+ ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
+ /* Set prod to match the extent size */
+ prod = align / mp->m_sb.sb_rextsize;
+
+ error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
+ align, rt, ap->eof, 0,
+ ap->conv, &ap->off, &ap->alen);
+ if (error)
+ return error;
+ ASSERT(ap->alen);
ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0);
+
/*
* If the offset & length are not perfectly aligned
* then kill prod, it will just get us in trouble.
*/
- if (do_mod(ap->off, extsz) || ap->alen % extsz)
+ if (do_mod(ap->off, align) || ap->alen % align)
prod = 1;
/*
* Set ralen to be the actual requested length in rtextents.
@@ -2326,15 +2389,24 @@ xfs_bmap_alloc(
ap->rval = rtx * mp->m_sb.sb_rextsize;
} else
ap->rval = 0;
+ } else {
+ align = (ap->userdata && ap->ip->i_d.di_extsize &&
+ (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
+ ap->ip->i_d.di_extsize : 0;
+ if (unlikely(align)) {
+ error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
+ align, rt,
+ ap->eof, 0, ap->conv,
+ &ap->off, &ap->alen);
+ ASSERT(!error);
+ ASSERT(ap->alen);
+ }
+ if (nullfb)
+ ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
+ else
+ ap->rval = ap->firstblock;
}
-#else
- if (rt)
- ap->rval = 0;
-#endif /* __KERNEL__ */
- else if (nullfb)
- ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
- else
- ap->rval = ap->firstblock;
+
/*
* If allocating at eof, and there's a previous real block,
* try to use it's last block as our starting point.
@@ -2598,11 +2670,12 @@ xfs_bmap_alloc(
args.total = ap->total;
args.minlen = ap->minlen;
}
- if (ap->ip->i_d.di_extsize) {
+ if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
+ (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
args.prod = ap->ip->i_d.di_extsize;
if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
args.mod = (xfs_extlen_t)(args.prod - args.mod);
- } else if (mp->m_sb.sb_blocksize >= NBPP) {
+ } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) {
args.prod = 1;
args.mod = 0;
} else {
@@ -3580,14 +3653,16 @@ xfs_bmap_search_extents(
ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
lastxp, gotp, prevp);
- rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
- if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
+ rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
+ if (unlikely(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM))) {
cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
"start_block : %llx start_off : %llx blkcnt : %llx "
"extent-state : %x \n",
- (ip->i_mount)->m_fsname,(long long)ip->i_ino,
- gotp->br_startblock, gotp->br_startoff,
- gotp->br_blockcount,gotp->br_state);
+ (ip->i_mount)->m_fsname, (long long)ip->i_ino,
+ (unsigned long long)gotp->br_startblock,
+ (unsigned long long)gotp->br_startoff,
+ (unsigned long long)gotp->br_blockcount,
+ gotp->br_state);
}
return ep;
}
@@ -3875,7 +3950,7 @@ xfs_bmap_add_attrfork(
ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
if (!ip->i_d.di_forkoff)
ip->i_d.di_forkoff = mp->m_attroffset >> 3;
- else if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR))
+ else if (mp->m_flags & XFS_MOUNT_ATTR2)
version = 2;
break;
default:
@@ -4023,13 +4098,13 @@ xfs_bmap_compute_maxlevels(
*/
if (whichfork == XFS_DATA_FORK) {
maxleafents = MAXEXTNUM;
- sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
- mp->m_attroffset : XFS_BMDR_SPACE_CALC(MINDBTPTRS);
+ sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+ XFS_BMDR_SPACE_CALC(MINDBTPTRS) : mp->m_attroffset;
} else {
maxleafents = MAXAEXTNUM;
- sz = (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) ?
- mp->m_sb.sb_inodesize - mp->m_attroffset :
- XFS_BMDR_SPACE_CALC(MINABTPTRS);
+ sz = (mp->m_flags & XFS_MOUNT_ATTR2) ?
+ XFS_BMDR_SPACE_CALC(MINABTPTRS) :
+ mp->m_sb.sb_inodesize - mp->m_attroffset;
}
maxrootrecs = (int)XFS_BTREE_BLOCK_MAXRECS(sz, xfs_bmdr, 0);
minleafrecs = mp->m_bmap_dmnr[0];
@@ -4418,8 +4493,8 @@ xfs_bmap_read_extents(
num_recs = be16_to_cpu(block->bb_numrecs);
if (unlikely(i + num_recs > room)) {
ASSERT(i + num_recs <= room);
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt dinode %Lu, (btree extents). Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt dinode %Lu, (btree extents).",
(unsigned long long) ip->i_ino);
XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
XFS_ERRLEVEL_LOW,
@@ -4590,6 +4665,7 @@ xfs_bmapi(
char contig; /* allocation must be one extent */
char delay; /* this request is for delayed alloc */
char exact; /* don't do all of wasdelayed extent */
+ char convert; /* unwritten extent I/O completion */
xfs_bmbt_rec_t *ep; /* extent list entry pointer */
int error; /* error return */
xfs_bmbt_irec_t got; /* current extent list record */
@@ -4643,7 +4719,7 @@ xfs_bmapi(
}
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- rt = XFS_IS_REALTIME_INODE(ip);
+ rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(ifp->if_ext_max ==
XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4654,6 +4730,7 @@ xfs_bmapi(
delay = (flags & XFS_BMAPI_DELAY) != 0;
trim = (flags & XFS_BMAPI_ENTIRE) == 0;
userdata = (flags & XFS_BMAPI_METADATA) == 0;
+ convert = (flags & XFS_BMAPI_CONVERT) != 0;
exact = (flags & XFS_BMAPI_EXACT) != 0;
rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0;
contig = (flags & XFS_BMAPI_CONTIG) != 0;
@@ -4748,15 +4825,25 @@ xfs_bmapi(
}
minlen = contig ? alen : 1;
if (delay) {
- xfs_extlen_t extsz = 0;
+ xfs_extlen_t extsz;
/* Figure out the extent size, adjust alen */
if (rt) {
if (!(extsz = ip->i_d.di_extsize))
extsz = mp->m_sb.sb_rextsize;
- alen = roundup(alen, extsz);
- extsz = alen / mp->m_sb.sb_rextsize;
+ } else {
+ extsz = ip->i_d.di_extsize;
}
+ if (extsz) {
+ error = xfs_bmap_extsize_align(mp,
+ &got, &prev, extsz,
+ rt, eof, delay, convert,
+ &aoff, &alen);
+ ASSERT(!error);
+ }
+
+ if (rt)
+ extsz = alen / mp->m_sb.sb_rextsize;
/*
* Make a transaction-less quota reservation for
@@ -4785,32 +4872,33 @@ xfs_bmapi(
xfs_bmap_worst_indlen(ip, alen);
ASSERT(indlen > 0);
- if (rt)
+ if (rt) {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FREXTENTS,
-(extsz), rsvd);
- else
+ } else {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
-(alen), rsvd);
+ }
if (!error) {
error = xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
-(indlen), rsvd);
- if (error && rt) {
- xfs_mod_incore_sb(ip->i_mount,
+ if (error && rt)
+ xfs_mod_incore_sb(mp,
XFS_SBS_FREXTENTS,
extsz, rsvd);
- } else if (error) {
- xfs_mod_incore_sb(ip->i_mount,
+ else if (error)
+ xfs_mod_incore_sb(mp,
XFS_SBS_FDBLOCKS,
alen, rsvd);
- }
}
if (error) {
- if (XFS_IS_QUOTA_ON(ip->i_mount))
+ if (XFS_IS_QUOTA_ON(mp))
/* unreserve the blocks now */
+ (void)
XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
mp, NULL, ip,
(long)alen, 0, rt ?
@@ -4849,6 +4937,7 @@ xfs_bmapi(
bma.firstblock = *firstblock;
bma.alen = alen;
bma.off = aoff;
+ bma.conv = convert;
bma.wasdel = wasdelay;
bma.minlen = minlen;
bma.low = flist->xbf_low;
@@ -5270,8 +5359,7 @@ xfs_bunmapi(
return 0;
}
XFS_STATS_INC(xs_blk_unmap);
- isrt = (whichfork == XFS_DATA_FORK) &&
- (ip->i_d.di_flags & XFS_DIFLAG_REALTIME);
+ isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
start = bno;
bno = start + len - 1;
ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
@@ -5443,7 +5531,7 @@ xfs_bunmapi(
}
if (wasdel) {
ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
- /* Update realtim/data freespace, unreserve quota */
+ /* Update realtime/data freespace, unreserve quota */
if (isrt) {
xfs_filblks_t rtexts;
@@ -5451,14 +5539,14 @@ xfs_bunmapi(
do_div(rtexts, mp->m_sb.sb_rextsize);
xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
(int)rtexts, rsvd);
- XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
- -((long)del.br_blockcount), 0,
+ (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
+ NULL, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_RTBLKS);
} else {
xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
(int)del.br_blockcount, rsvd);
- XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
- -((long)del.br_blockcount), 0,
+ (void)XFS_TRANS_RESERVE_QUOTA_NBLKS(mp,
+ NULL, ip, -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_REGBLKS);
}
ip->i_delayed_blks -= del.br_blockcount;
@@ -5652,7 +5740,9 @@ xfs_getbmap(
ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
return XFS_ERROR(EINVAL);
if (whichfork == XFS_DATA_FORK) {
- if (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC) {
+ if ((ip->i_d.di_extsize && (ip->i_d.di_flags &
+ (XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) ||
+ ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
prealloced = 1;
fixlen = XFS_MAXIOFFSET(mp);
} else {
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 2e0717a01309..12cc63dfc2c4 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -62,6 +62,10 @@ typedef struct xfs_bmap_free
#define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */
/* combine contig. space */
#define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */
+/* XFS_BMAPI_DIRECT_IO 0x800 */
+#define XFS_BMAPI_CONVERT 0x1000 /* unwritten extent conversion - */
+ /* need write cache flushing and no */
+ /* additional allocation alignments */
#define XFS_BMAPI_AFLAG(w) xfs_bmapi_aflag(w)
static inline int xfs_bmapi_aflag(int w)
@@ -101,7 +105,8 @@ typedef struct xfs_bmalloca {
char wasdel; /* replacing a delayed allocation */
char userdata;/* set if is user data */
char low; /* low on space, using seq'l ags */
- char aeof; /* allocated space at eof */
+ char aeof; /* allocated space at eof */
+ char conv; /* overwriting unwritten extents */
} xfs_bmalloca_t;
#ifdef __KERNEL__
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 328a528b926d..f57cc9ac875e 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -57,7 +57,7 @@ struct xfs_mount_args {
/*
* XFS mount option flags -- args->flags1
*/
-#define XFSMNT_COMPAT_ATTR 0x00000001 /* do not use ATTR2 format */
+#define XFSMNT_ATTR2 0x00000001 /* allow ATTR2 EA format */
#define XFSMNT_WSYNC 0x00000002 /* safe mode nfs mount
* compatible */
#define XFSMNT_INO64 0x00000004 /* move inode numbers up
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 070259a4254c..c6191d00ad27 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -60,8 +60,6 @@ xfs_swapext(
xfs_bstat_t *sbp;
struct file *fp = NULL, *tfp = NULL;
vnode_t *vp, *tvp;
- bhv_desc_t *bdp, *tbdp;
- vn_bhv_head_t *bhp, *tbhp;
static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
int ilf_fields, tilf_fields;
int error = 0;
@@ -90,13 +88,10 @@ xfs_swapext(
goto error0;
}
- bhp = VN_BHV_HEAD(vp);
- bdp = vn_bhv_lookup(bhp, &xfs_vnodeops);
- if (bdp == NULL) {
+ ip = xfs_vtoi(vp);
+ if (ip == NULL) {
error = XFS_ERROR(EBADF);
goto error0;
- } else {
- ip = XFS_BHVTOI(bdp);
}
if (((tfp = fget((int)sxp->sx_fdtmp)) == NULL) ||
@@ -105,13 +100,10 @@ xfs_swapext(
goto error0;
}
- tbhp = VN_BHV_HEAD(tvp);
- tbdp = vn_bhv_lookup(tbhp, &xfs_vnodeops);
- if (tbdp == NULL) {
+ tip = xfs_vtoi(tvp);
+ if (tip == NULL) {
error = XFS_ERROR(EBADF);
goto error0;
- } else {
- tip = XFS_BHVTOI(tbdp);
}
if (ip->i_mount != tip->i_mount) {
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index c5a0e537ff1a..79d0d9e1fbab 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -199,10 +199,16 @@ typedef enum xfs_dinode_fmt
#define XFS_DFORK_DSIZE(dip,mp) \
XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp)
+#define XFS_DFORK_DSIZE_HOST(dip,mp) \
+ XFS_CFORK_DSIZE(&(dip)->di_core, mp)
#define XFS_DFORK_ASIZE(dip,mp) \
XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp)
+#define XFS_DFORK_ASIZE_HOST(dip,mp) \
+ XFS_CFORK_ASIZE(&(dip)->di_core, mp)
#define XFS_DFORK_SIZE(dip,mp,w) \
XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w)
+#define XFS_DFORK_SIZE_HOST(dip,mp,w) \
+ XFS_CFORK_SIZE(&(dip)->di_core, mp, w)
#define XFS_DFORK_Q(dip) XFS_CFORK_Q_DISK(&(dip)->di_core)
#define XFS_DFORK_BOFF(dip) XFS_CFORK_BOFF_DISK(&(dip)->di_core)
@@ -216,6 +222,7 @@ typedef enum xfs_dinode_fmt
#define XFS_CFORK_FMT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
((dcp)->di_format = (n)) : ((dcp)->di_aformat = (n)))
+#define XFS_DFORK_FORMAT(dip,w) XFS_CFORK_FORMAT(&(dip)->di_core, w)
#define XFS_CFORK_NEXTENTS_DISK(dcp,w) \
((w) == XFS_DATA_FORK ? \
@@ -223,13 +230,13 @@ typedef enum xfs_dinode_fmt
INT_GET((dcp)->di_anextents, ARCH_CONVERT))
#define XFS_CFORK_NEXTENTS(dcp,w) \
((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
+#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
+#define XFS_DFORK_NEXTENTS_HOST(dip,w) XFS_CFORK_NEXTENTS(&(dip)->di_core, w)
#define XFS_CFORK_NEXT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
((dcp)->di_nextents = (n)) : ((dcp)->di_anextents = (n)))
-#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
-
#define XFS_BUF_TO_DINODE(bp) ((xfs_dinode_t *)XFS_BUF_PTR(bp))
/*
@@ -246,8 +253,10 @@ typedef enum xfs_dinode_fmt
#define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */
#define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */
#define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */
-#define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */
-#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */
+#define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */
+#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */
+#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */
+#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */
#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -259,11 +268,14 @@ typedef enum xfs_dinode_fmt
#define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT)
#define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT)
#define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
+#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT)
+#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
#define XFS_DIFLAG_ANY \
(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
- XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS)
+ XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
+ XFS_DIFLAG_EXTSZINHERIT)
#endif /* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c
index 3dd30391f551..bb87d2a700a9 100644
--- a/fs/xfs/xfs_dir.c
+++ b/fs/xfs/xfs_dir.c
@@ -176,7 +176,7 @@ xfs_dir_mount(xfs_mount_t *mp)
uint shortcount, leafcount, count;
mp->m_dirversion = 1;
- if (mp->m_flags & XFS_MOUNT_COMPAT_ATTR) {
+ if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
shortcount = (mp->m_attroffset -
(uint)sizeof(xfs_dir_sf_hdr_t)) /
(uint)sizeof(xfs_dir_sf_entry_t);
diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h
index 488defe86ba6..8cc8afb9f6c0 100644
--- a/fs/xfs/xfs_dir.h
+++ b/fs/xfs/xfs_dir.h
@@ -135,6 +135,8 @@ void xfs_dir_startup(void); /* called exactly once */
((mp)->m_dirops.xd_shortform_to_single(args))
#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1)
+#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2)
extern xfs_dirops_t xfsv1_dirops;
+extern xfs_dirops_t xfsv2_dirops;
#endif /* __XFS_DIR_H__ */
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 7e24ffeda9e1..3158f5dc431f 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -72,9 +72,6 @@ typedef struct xfs_dir2_put_args {
struct uio *uio; /* uio control structure */
} xfs_dir2_put_args_t;
-#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2)
-extern xfs_dirops_t xfsv2_dirops;
-
/*
* Other interfaces used by the rest of the dir v2 code.
*/
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index 950df31efc46..e83074016abb 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -147,7 +147,7 @@ xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
hdr->count = 0;
dp->i_d.di_size = sizeof(*hdr);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
- return(0);
+ return 0;
}
/*
@@ -180,7 +180,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args)
if (sfe->namelen == args->namelen &&
args->name[0] == sfe->name[0] &&
memcmp(args->name, sfe->name, args->namelen) == 0)
- return(XFS_ERROR(EEXIST));
+ return XFS_ERROR(EEXIST);
sfe = XFS_DIR_SF_NEXTENTRY(sfe);
}
@@ -198,7 +198,7 @@ xfs_dir_shortform_addname(xfs_da_args_t *args)
dp->i_d.di_size += size;
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
- return(0);
+ return 0;
}
/*
@@ -238,7 +238,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args)
}
if (i < 0) {
ASSERT(args->oknoent);
- return(XFS_ERROR(ENOENT));
+ return XFS_ERROR(ENOENT);
}
if ((base + size) != dp->i_d.di_size) {
@@ -251,7 +251,7 @@ xfs_dir_shortform_removename(xfs_da_args_t *args)
dp->i_d.di_size -= size;
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
- return(0);
+ return 0;
}
/*
@@ -390,7 +390,7 @@ xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
out:
kmem_free(tmpbuffer, size);
- return(retval);
+ return retval;
}
STATIC int
@@ -596,7 +596,7 @@ xfs_dir_shortform_replace(xfs_da_args_t *args)
/* XXX - replace assert? */
XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
- return(0);
+ return 0;
}
ASSERT(args->namelen != 1 || args->name[0] != '.');
sfe = &sf->list[0];
@@ -608,12 +608,12 @@ xfs_dir_shortform_replace(xfs_da_args_t *args)
(char *)&sfe->inumber, sizeof(xfs_ino_t)));
XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
- return(0);
+ return 0;
}
sfe = XFS_DIR_SF_NEXTENTRY(sfe);
}
ASSERT(args->oknoent);
- return(XFS_ERROR(ENOENT));
+ return XFS_ERROR(ENOENT);
}
/*
@@ -695,7 +695,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
out:
kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
- return(retval);
+ return retval;
}
/*
@@ -715,17 +715,17 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
retval = xfs_da_grow_inode(args, &blkno);
ASSERT(blkno == 1);
if (retval)
- return(retval);
+ return retval;
retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
XFS_DATA_FORK);
if (retval)
- return(retval);
+ return retval;
ASSERT(bp1 != NULL);
retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2,
XFS_DATA_FORK);
if (retval) {
xfs_da_buf_done(bp1);
- return(retval);
+ return retval;
}
ASSERT(bp2 != NULL);
memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
@@ -738,7 +738,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK);
if (retval) {
xfs_da_buf_done(bp2);
- return(retval);
+ return retval;
}
node = bp1->data;
leaf = bp2->data;
@@ -751,7 +751,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0])));
xfs_da_buf_done(bp1);
- return(retval);
+ return retval;
}
@@ -776,7 +776,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
ASSERT(dp != NULL);
retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK);
if (retval)
- return(retval);
+ return retval;
ASSERT(bp != NULL);
leaf = bp->data;
memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
@@ -791,7 +791,7 @@ xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
*bpp = bp;
- return(0);
+ return 0;
}
/*
@@ -813,10 +813,10 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC);
error = xfs_da_grow_inode(args, &blkno);
if (error)
- return(error);
+ return error;
error = xfs_dir_leaf_create(args, blkno, &newblk->bp);
if (error)
- return(error);
+ return error;
newblk->blkno = blkno;
newblk->magic = XFS_DIR_LEAF_MAGIC;
@@ -826,7 +826,7 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
xfs_dir_leaf_rebalance(state, oldblk, newblk);
error = xfs_da_blk_link(state, oldblk, newblk);
if (error)
- return(error);
+ return error;
/*
* Insert the new entry in the correct block.
@@ -842,7 +842,7 @@ xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
*/
oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL);
newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL);
- return(error);
+ return error;
}
/*
@@ -885,7 +885,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
if (INT_GET(map->size, ARCH_CONVERT) >= tmp) {
if (!args->justcheck)
xfs_dir_leaf_add_work(bp, args, index, i);
- return(0);
+ return 0;
}
sum += INT_GET(map->size, ARCH_CONVERT);
}
@@ -896,7 +896,7 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
* no good and we should just give up.
*/
if (!hdr->holes && (sum < entsize))
- return(XFS_ERROR(ENOSPC));
+ return XFS_ERROR(ENOSPC);
/*
* Compact the entries to coalesce free space.
@@ -909,18 +909,18 @@ xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
(uint)sizeof(xfs_dir_leaf_entry_t) : 0,
args->justcheck);
if (error)
- return(error);
+ return error;
/*
* After compaction, the block is guaranteed to have only one
* free region, in freemap[0]. If it is not big enough, give up.
*/
if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) <
(entsize + (uint)sizeof(xfs_dir_leaf_entry_t)))
- return(XFS_ERROR(ENOSPC));
+ return XFS_ERROR(ENOSPC);
if (!args->justcheck)
xfs_dir_leaf_add_work(bp, args, index, 0);
- return(0);
+ return 0;
}
/*
@@ -1072,7 +1072,7 @@ xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
kmem_free(tmpbuffer, lbsize);
if (musthave || justcheck)
kmem_free(tmpbuffer2, lbsize);
- return(rval);
+ return rval;
}
/*
@@ -1292,7 +1292,7 @@ xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
*countarg = count;
*namebytesarg = totallen;
- return(foundit);
+ return foundit;
}
/*========================================================================
@@ -1334,7 +1334,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
if (bytes > (state->blocksize >> 1)) {
*action = 0; /* blk over 50%, don't try to join */
- return(0);
+ return 0;
}
/*
@@ -1353,13 +1353,13 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
error = xfs_da_path_shift(state, &state->altpath, forward,
0, &retval);
if (error)
- return(error);
+ return error;
if (retval) {
*action = 0;
} else {
*action = 2;
}
- return(0);
+ return 0;
}
/*
@@ -1381,7 +1381,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
blkno, -1, &bp,
XFS_DATA_FORK);
if (error)
- return(error);
+ return error;
ASSERT(bp != NULL);
leaf = (xfs_dir_leafblock_t *)info;
@@ -1402,7 +1402,7 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
}
if (i >= 2) {
*action = 0;
- return(0);
+ return 0;
}
xfs_da_buf_done(bp);
@@ -1419,13 +1419,13 @@ xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
0, &retval);
}
if (error)
- return(error);
+ return error;
if (retval) {
*action = 0;
} else {
*action = 1;
}
- return(0);
+ return 0;
}
/*
@@ -1575,8 +1575,8 @@ xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
if (tmp < mp->m_dir_magicpct)
- return(1); /* leaf is < 37% full */
- return(0);
+ return 1; /* leaf is < 37% full */
+ return 0;
}
/*
@@ -1732,7 +1732,7 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) {
*index = probe;
ASSERT(args->oknoent);
- return(XFS_ERROR(ENOENT));
+ return XFS_ERROR(ENOENT);
}
/*
@@ -1745,14 +1745,14 @@ xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
memcmp(args->name, namest->name, args->namelen) == 0) {
XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
*index = probe;
- return(XFS_ERROR(EEXIST));
+ return XFS_ERROR(EEXIST);
}
entry++;
probe++;
}
*index = probe;
ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent);
- return(XFS_ERROR(ENOENT));
+ return XFS_ERROR(ENOENT);
}
/*========================================================================
@@ -1890,9 +1890,9 @@ xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) ||
(INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
- return(1);
+ return 1;
}
- return(0);
+ return 0;
}
/*
@@ -1942,7 +1942,7 @@ xfs_dir_leaf_getdents_int(
leaf = bp->data;
if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) {
*eobp = 1;
- return(XFS_ERROR(ENOENT)); /* XXX wrong code */
+ return XFS_ERROR(ENOENT); /* XXX wrong code */
}
want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
@@ -2000,7 +2000,7 @@ xfs_dir_leaf_getdents_int(
* the node code will be setting uio_offset anyway.
*/
*eobp = 0;
- return(0);
+ return 0;
}
xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry);
@@ -2057,7 +2057,7 @@ xfs_dir_leaf_getdents_int(
retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
nextda, &bp2, XFS_DATA_FORK);
if (retval)
- return(retval);
+ return retval;
ASSERT(bp2 != NULL);
@@ -2073,7 +2073,7 @@ xfs_dir_leaf_getdents_int(
leaf2);
xfs_da_brelse(dp->i_transp, bp2);
- return(XFS_ERROR(EFSCORRUPTED));
+ return XFS_ERROR(EFSCORRUPTED);
}
nexthash = INT_GET(leaf2->entries[0].hashval,
@@ -2139,7 +2139,7 @@ xfs_dir_leaf_getdents_int(
xfs_dir_trace_g_du("leaf: E-O-B", dp, uio);
- return(retval);
+ return retval;
}
}
@@ -2149,7 +2149,7 @@ xfs_dir_leaf_getdents_int(
xfs_dir_trace_g_du("leaf: E-O-F", dp, uio);
- return(0);
+ return 0;
}
/*
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index ab6b09eef9ab..eb8cd9a4667f 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -67,34 +67,38 @@ struct xfs_trans;
*/
#define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */
+typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */
+ __uint16_t base; /* base of free region */
+ __uint16_t size; /* run length of free region */
+} xfs_dir_leaf_map_t;
+
+typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */
+ xfs_da_blkinfo_t info; /* block type, links, etc. */
+ __uint16_t count; /* count of active leaf_entry's */
+ __uint16_t namebytes; /* num bytes of name strings stored */
+ __uint16_t firstused; /* first used byte in name area */
+ __uint8_t holes; /* != 0 if blk needs compaction */
+ __uint8_t pad1;
+ xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE];
+} xfs_dir_leaf_hdr_t;
+
+typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */
+ xfs_dahash_t hashval; /* hash value of name */
+ __uint16_t nameidx; /* index into buffer of name */
+ __uint8_t namelen; /* length of name string */
+ __uint8_t pad2;
+} xfs_dir_leaf_entry_t;
+
+typedef struct xfs_dir_leaf_name {
+ xfs_dir_ino_t inumber; /* inode number for this key */
+ __uint8_t name[1]; /* name string itself */
+} xfs_dir_leaf_name_t;
+
typedef struct xfs_dir_leafblock {
- struct xfs_dir_leaf_hdr { /* constant-structure header block */
- xfs_da_blkinfo_t info; /* block type, links, etc. */
- __uint16_t count; /* count of active leaf_entry's */
- __uint16_t namebytes; /* num bytes of name strings stored */
- __uint16_t firstused; /* first used byte in name area */
- __uint8_t holes; /* != 0 if blk needs compaction */
- __uint8_t pad1;
- struct xfs_dir_leaf_map {/* RLE map of free bytes */
- __uint16_t base; /* base of free region */
- __uint16_t size; /* run length of free region */
- } freemap[XFS_DIR_LEAF_MAPSIZE]; /* N largest free regions */
- } hdr;
- struct xfs_dir_leaf_entry { /* sorted on key, not name */
- xfs_dahash_t hashval; /* hash value of name */
- __uint16_t nameidx; /* index into buffer of name */
- __uint8_t namelen; /* length of name string */
- __uint8_t pad2;
- } entries[1]; /* var sized array */
- struct xfs_dir_leaf_name {
- xfs_dir_ino_t inumber; /* inode number for this key */
- __uint8_t name[1]; /* name string itself */
- } namelist[1]; /* grows from bottom of buf */
+ xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */
+ xfs_dir_leaf_entry_t entries[1]; /* var sized array */
+ xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */
} xfs_dir_leafblock_t;
-typedef struct xfs_dir_leaf_hdr xfs_dir_leaf_hdr_t;
-typedef struct xfs_dir_leaf_map xfs_dir_leaf_map_t;
-typedef struct xfs_dir_leaf_entry xfs_dir_leaf_entry_t;
-typedef struct xfs_dir_leaf_name xfs_dir_leaf_name_t;
/*
* Length of name for which a 512-byte block filesystem
@@ -126,11 +130,10 @@ typedef union {
#define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \
((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash))
-typedef struct xfs_dir_put_args
-{
+typedef struct xfs_dir_put_args {
xfs_dircook_t cook; /* cookie of (next) entry */
xfs_intino_t ino; /* inode number */
- struct xfs_dirent *dbp; /* buffer pointer */
+ struct xfs_dirent *dbp; /* buffer pointer */
char *name; /* directory entry name */
int namelen; /* length of name */
int done; /* output: set if value was stored */
@@ -138,7 +141,8 @@ typedef struct xfs_dir_put_args
struct uio *uio; /* uio control structure */
} xfs_dir_put_args_t;
-#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) xfs_dir_leaf_entsize_byname(len)
+#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \
+ xfs_dir_leaf_entsize_byname(len)
static inline int xfs_dir_leaf_entsize_byname(int len)
{
return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len;
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 864bf6955689..b4c7f2bc55a0 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -152,7 +152,7 @@ typedef enum {
#define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */
#define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */
-#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */
+#define DM_FLAGS_IMUX 0x004 /* thread holds i_mutex */
#define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */
#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */
@@ -161,21 +161,21 @@ typedef enum {
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
- DM_FLAGS_ISEM : 0)
-#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+ DM_FLAGS_IMUX : 0)
+#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
- DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
-#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+ DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX)
+#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX)
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
- 0 : DM_FLAGS_ISEM)
-#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM)
+ 0 : DM_FLAGS_IMUX)
+#define DM_SEM_FLAG_WR (DM_FLAGS_IMUX)
#endif
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index d7b6b5d16704..2a21c5024017 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -54,7 +54,6 @@ xfs_error_trap(int e)
if (e != xfs_etrap[i])
continue;
cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
- debug_stop_all_cpus((void *)-1LL);
BUG();
break;
}
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 06d8a8426c16..26b8e709a569 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -18,9 +18,6 @@
#ifndef __XFS_ERROR_H__
#define __XFS_ERROR_H__
-#define prdev(fmt,targ,args...) \
- printk("XFS: device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
-
#define XFS_ERECOVER 1 /* Failure to recover log */
#define XFS_ELOGSTAT 2 /* Failure to stat log in user space */
#define XFS_ENOLOGSPACE 3 /* Reservation too large */
@@ -182,8 +179,11 @@ extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
struct xfs_mount;
/* PRINTFLIKE4 */
extern void xfs_cmn_err(int panic_tag, int level, struct xfs_mount *mp,
- char *fmt, ...);
+ char *fmt, ...);
/* PRINTFLIKE3 */
extern void xfs_fs_cmn_err(int level, struct xfs_mount *mp, char *fmt, ...);
+#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
+ xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args)
+
#endif /* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index ba096f80f48d..14010f1fa82f 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -3,15 +3,15 @@
* 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.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -65,6 +65,8 @@ struct fsxattr {
#define XFS_XFLAG_RTINHERIT 0x00000100 /* create with rt bit set */
#define XFS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
#define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */
+#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
+#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
/*
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index d1236d6f4045..b4d971b01588 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -501,7 +501,7 @@ xfs_reserve_blocks(
if (inval == (__uint64_t *)NULL) {
outval->resblks = mp->m_resblks;
outval->resblks_avail = mp->m_resblks_avail;
- return(0);
+ return 0;
}
request = *inval;
@@ -537,7 +537,33 @@ xfs_reserve_blocks(
outval->resblks = mp->m_resblks;
outval->resblks_avail = mp->m_resblks_avail;
XFS_SB_UNLOCK(mp, s);
- return(0);
+ return 0;
+}
+
+void
+xfs_fs_log_dummy(xfs_mount_t *mp)
+{
+ xfs_trans_t *tp;
+ xfs_inode_t *ip;
+
+
+ tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
+ atomic_inc(&mp->m_active_trans);
+ if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
+ xfs_trans_cancel(tp, 0);
+ return;
+ }
+
+ ip = mp->m_rootip;
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+ xfs_trans_ihold(tp, ip);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ xfs_trans_set_sync(tp);
+ xfs_trans_commit(tp, 0, NULL);
+
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
}
int
diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h
index f32713f14f9a..300d0c9d61ad 100644
--- a/fs/xfs/xfs_fsops.h
+++ b/fs/xfs/xfs_fsops.h
@@ -25,5 +25,6 @@ extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt);
extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval,
xfs_fsop_resblks_t *outval);
extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags);
+extern void xfs_fs_log_dummy(xfs_mount_t *mp);
#endif /* __XFS_FSOPS_H__ */
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index fc19eedbd11b..8e380a1fb79b 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -493,7 +493,6 @@ xfs_iget(
retry:
if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
- bhv_desc_t *bdp;
xfs_inode_t *ip;
vp = LINVFS_GET_VP(inode);
@@ -517,14 +516,12 @@ retry:
* to wait for the inode to go away.
*/
if (is_bad_inode(inode) ||
- ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp),
- &xfs_vnodeops)) == NULL)) {
+ ((ip = xfs_vtoi(vp)) == NULL)) {
iput(inode);
delay(1);
goto retry;
}
- ip = XFS_BHVTOI(bdp);
if (lock_flags != 0)
xfs_ilock(ip, lock_flags);
XFS_STATS_INC(xs_ig_found);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index df0d4572d70a..1d7f5a7e063e 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -404,9 +404,8 @@ xfs_iformat(
INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt dinode %Lu, extent total = %d, nblocks = %Lu."
- " Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
(unsigned long long)ip->i_ino,
(int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT)
+ INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
@@ -418,9 +417,8 @@ xfs_iformat(
}
if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt dinode %Lu, forkoff = 0x%x."
- " Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt dinode %Lu, forkoff = 0x%x.",
(unsigned long long)ip->i_ino,
(int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
@@ -451,8 +449,9 @@ xfs_iformat(
* no local regular files yet
*/
if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & S_IFMT) == S_IFREG)) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt inode (local format for regular file) %Lu. Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt inode %Lu "
+ "(local format for regular file).",
(unsigned long long) ip->i_ino);
XFS_CORRUPTION_ERROR("xfs_iformat(4)",
XFS_ERRLEVEL_LOW,
@@ -462,8 +461,9 @@ xfs_iformat(
di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt inode %Lu (bad size %Ld for local inode). Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt inode %Lu "
+ "(bad size %Ld for local inode).",
(unsigned long long) ip->i_ino,
(long long) di_size);
XFS_CORRUPTION_ERROR("xfs_iformat(5)",
@@ -551,8 +551,9 @@ xfs_iformat_local(
* kmem_alloc() or memcpy() below.
*/
if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt inode %Lu (bad size %d for local fork, size = %d). Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt inode %Lu "
+ "(bad size %d for local fork, size = %d).",
(unsigned long long) ip->i_ino, size,
XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
@@ -610,8 +611,8 @@ xfs_iformat_extents(
* kmem_alloc() or memcpy() below.
*/
if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt inode %Lu ((a)extents = %d). Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt inode %Lu ((a)extents = %d).",
(unsigned long long) ip->i_ino, nex);
XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
@@ -692,8 +693,8 @@ xfs_iformat_btree(
|| XFS_BMDR_SPACE_CALC(nrecs) >
XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
|| XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
- xfs_fs_cmn_err(CE_WARN, ip->i_mount,
- "corrupt inode %Lu (btree). Unmount and run xfs_repair.",
+ xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+ "corrupt inode %Lu (btree).",
(unsigned long long) ip->i_ino);
XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
ip->i_mount);
@@ -809,6 +810,10 @@ _xfs_dic2xflags(
flags |= XFS_XFLAG_PROJINHERIT;
if (di_flags & XFS_DIFLAG_NOSYMLINKS)
flags |= XFS_XFLAG_NOSYMLINKS;
+ if (di_flags & XFS_DIFLAG_EXTSIZE)
+ flags |= XFS_XFLAG_EXTSIZE;
+ if (di_flags & XFS_DIFLAG_EXTSZINHERIT)
+ flags |= XFS_XFLAG_EXTSZINHERIT;
}
return flags;
@@ -1192,11 +1197,19 @@ xfs_ialloc(
if ((mode & S_IFMT) == S_IFDIR) {
if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
di_flags |= XFS_DIFLAG_RTINHERIT;
- } else {
+ if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
+ di_flags |= XFS_DIFLAG_EXTSZINHERIT;
+ ip->i_d.di_extsize = pip->i_d.di_extsize;
+ }
+ } else if ((mode & S_IFMT) == S_IFREG) {
if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
di_flags |= XFS_DIFLAG_REALTIME;
ip->i_iocore.io_flags |= XFS_IOCORE_RT;
}
+ if (pip->i_d.di_flags & XFS_DIFLAG_EXTSZINHERIT) {
+ di_flags |= XFS_DIFLAG_EXTSIZE;
+ ip->i_d.di_extsize = pip->i_d.di_extsize;
+ }
}
if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
xfs_inherit_noatime)
@@ -1262,7 +1275,7 @@ xfs_isize_check(
if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
return;
- if ( ip->i_d.di_flags & XFS_DIFLAG_REALTIME )
+ if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE))
return;
nimaps = 2;
@@ -1765,22 +1778,19 @@ xfs_igrow_start(
xfs_fsize_t new_size,
cred_t *credp)
{
- xfs_fsize_t isize;
int error;
ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
ASSERT(new_size > ip->i_d.di_size);
- error = 0;
- isize = ip->i_d.di_size;
/*
* Zero any pages that may have been created by
* xfs_write_file() beyond the end of the file
* and any blocks between the old and new file sizes.
*/
- error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size, isize,
- new_size);
+ error = xfs_zero_eof(XFS_ITOV(ip), &ip->i_iocore, new_size,
+ ip->i_d.di_size, new_size);
return error;
}
@@ -3355,6 +3365,11 @@ xfs_iflush_int(
ip->i_update_core = 0;
SYNCHRONIZE();
+ /*
+ * Make sure to get the latest atime from the Linux inode.
+ */
+ xfs_synchronize_atime(ip);
+
if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC,
mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 124d30e6143b..1cfbcf18ce86 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -436,6 +436,10 @@ void xfs_ichgtime(xfs_inode_t *, int);
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
+xfs_inode_t *xfs_vtoi(struct vnode *vp);
+
+void xfs_synchronize_atime(xfs_inode_t *);
+
#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount))
#ifdef DEBUG
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7f3363c621e1..36aa1fcb90a5 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -271,6 +271,11 @@ xfs_inode_item_format(
if (ip->i_update_size)
ip->i_update_size = 0;
+ /*
+ * Make sure to get the latest atime from the Linux inode.
+ */
+ xfs_synchronize_atime(ip);
+
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);
@@ -603,7 +608,7 @@ xfs_inode_item_trylock(
if (iip->ili_pushbuf_flag == 0) {
iip->ili_pushbuf_flag = 1;
#ifdef DEBUG
- iip->ili_push_owner = get_thread_id();
+ iip->ili_push_owner = current_pid();
#endif
/*
* Inode is left locked in shared mode.
@@ -782,7 +787,7 @@ xfs_inode_item_pushbuf(
* trying to duplicate our effort.
*/
ASSERT(iip->ili_pushbuf_flag != 0);
- ASSERT(iip->ili_push_owner == get_thread_id());
+ ASSERT(iip->ili_push_owner == current_pid());
/*
* If flushlock isn't locked anymore, chances are that the
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 45a77a3a6c07..788917f355c4 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -40,7 +40,6 @@
#include "xfs_ialloc.h"
#include "xfs_btree.h"
#include "xfs_bmap.h"
-#include "xfs_bit.h"
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_itable.h"
@@ -263,7 +262,7 @@ phase2:
case BMAPI_WRITE:
/* If we found an extent, return it */
if (nimaps &&
- (imap.br_startblock != HOLESTARTBLOCK) &&
+ (imap.br_startblock != HOLESTARTBLOCK) &&
(imap.br_startblock != DELAYSTARTBLOCK)) {
xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
offset, count, iomapp, &imap, flags);
@@ -318,6 +317,58 @@ out:
}
STATIC int
+xfs_iomap_eof_align_last_fsb(
+ xfs_mount_t *mp,
+ xfs_iocore_t *io,
+ xfs_fsize_t isize,
+ xfs_extlen_t extsize,
+ xfs_fileoff_t *last_fsb)
+{
+ xfs_fileoff_t new_last_fsb = 0;
+ xfs_extlen_t align;
+ int eof, error;
+
+ if (io->io_flags & XFS_IOCORE_RT)
+ ;
+ /*
+ * If mounted with the "-o swalloc" option, roundup the allocation
+ * request to a stripe width boundary if the file size is >=
+ * stripe width and we are allocating past the allocation eof.
+ */
+ else if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) &&
+ (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)))
+ new_last_fsb = roundup_64(*last_fsb, mp->m_swidth);
+ /*
+ * Roundup the allocation request to a stripe unit (m_dalign) boundary
+ * if the file size is >= stripe unit size, and we are allocating past
+ * the allocation eof.
+ */
+ else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)))
+ new_last_fsb = roundup_64(*last_fsb, mp->m_dalign);
+
+ /*
+ * Always round up the allocation request to an extent boundary
+ * (when file on a real-time subvolume or has di_extsize hint).
+ */
+ if (extsize) {
+ if (new_last_fsb)
+ align = roundup_64(new_last_fsb, extsize);
+ else
+ align = extsize;
+ new_last_fsb = roundup_64(*last_fsb, align);
+ }
+
+ if (new_last_fsb) {
+ error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
+ if (error)
+ return error;
+ if (eof)
+ *last_fsb = new_last_fsb;
+ }
+ return 0;
+}
+
+STATIC int
xfs_flush_space(
xfs_inode_t *ip,
int *fsynced,
@@ -363,19 +414,20 @@ xfs_iomap_write_direct(
xfs_iocore_t *io = &ip->i_iocore;
xfs_fileoff_t offset_fsb;
xfs_fileoff_t last_fsb;
- xfs_filblks_t count_fsb;
+ xfs_filblks_t count_fsb, resaligned;
xfs_fsblock_t firstfsb;
+ xfs_extlen_t extsz, temp;
+ xfs_fsize_t isize;
int nimaps;
- int error;
int bmapi_flag;
int quota_flag;
int rt;
xfs_trans_t *tp;
xfs_bmbt_irec_t imap;
xfs_bmap_free_t free_list;
- xfs_filblks_t qblocks, resblks;
+ uint qblocks, resblks, resrtextents;
int committed;
- int resrtextents;
+ int error;
/*
* Make sure that the dquots are there. This doesn't hold
@@ -385,38 +437,53 @@ xfs_iomap_write_direct(
if (error)
return XFS_ERROR(error);
- offset_fsb = XFS_B_TO_FSBT(mp, offset);
- last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
- count_fsb = last_fsb - offset_fsb;
- if (found && (ret_imap->br_startblock == HOLESTARTBLOCK)) {
- xfs_fileoff_t map_last_fsb;
-
- map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
- if (map_last_fsb < last_fsb) {
- last_fsb = map_last_fsb;
- count_fsb = last_fsb - offset_fsb;
- }
- ASSERT(count_fsb > 0);
+ rt = XFS_IS_REALTIME_INODE(ip);
+ if (unlikely(rt)) {
+ if (!(extsz = ip->i_d.di_extsize))
+ extsz = mp->m_sb.sb_rextsize;
+ } else {
+ extsz = ip->i_d.di_extsize;
}
- /*
- * Determine if reserving space on the data or realtime partition.
- */
- if ((rt = XFS_IS_REALTIME_INODE(ip))) {
- xfs_extlen_t extsz;
+ isize = ip->i_d.di_size;
+ if (io->io_new_size > isize)
+ isize = io->io_new_size;
- if (!(extsz = ip->i_d.di_extsize))
- extsz = 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;
+ offset_fsb = XFS_B_TO_FSBT(mp, offset);
+ last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
+ if ((offset + count) > isize) {
+ error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
+ &last_fsb);
+ if (error)
+ goto error_out;
} else {
- resrtextents = 0;
- resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, count_fsb);
- quota_flag = XFS_QMOPT_RES_REGBLKS;
+ if (found && (ret_imap->br_startblock == HOLESTARTBLOCK))
+ last_fsb = MIN(last_fsb, (xfs_fileoff_t)
+ ret_imap->br_blockcount +
+ ret_imap->br_startoff);
+ }
+ count_fsb = last_fsb - offset_fsb;
+ ASSERT(count_fsb > 0);
+
+ resaligned = count_fsb;
+ if (unlikely(extsz)) {
+ if ((temp = do_mod(offset_fsb, extsz)))
+ resaligned += temp;
+ if ((temp = do_mod(resaligned, extsz)))
+ resaligned += extsz - temp;
}
+ if (unlikely(rt)) {
+ resrtextents = qblocks = resaligned;
+ resrtextents /= mp->m_sb.sb_rextsize;
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+ quota_flag = XFS_QMOPT_RES_RTBLKS;
+ } else {
+ resrtextents = 0;
+ resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
+ quota_flag = XFS_QMOPT_RES_REGBLKS;
+ }
+
/*
* Allocate and setup the transaction
*/
@@ -426,7 +493,6 @@ xfs_iomap_write_direct(
XFS_WRITE_LOG_RES(mp), resrtextents,
XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
-
/*
* Check for running out of space, note: need lock to return
*/
@@ -436,20 +502,20 @@ xfs_iomap_write_direct(
if (error)
goto error_out;
- if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
- error = (EDQUOT);
+ error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
+ qblocks, 0, quota_flag);
+ if (error)
goto error1;
- }
- bmapi_flag = XFS_BMAPI_WRITE;
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip);
- if (!(flags & BMAPI_MMAP) && (offset < ip->i_d.di_size || rt))
+ bmapi_flag = XFS_BMAPI_WRITE;
+ if ((flags & BMAPI_DIRECT) && (offset < ip->i_d.di_size || extsz))
bmapi_flag |= XFS_BMAPI_PREALLOC;
/*
- * Issue the bmapi() call to allocate the blocks
+ * Issue the xfs_bmapi() call to allocate the blocks
*/
XFS_BMAP_INIT(&free_list, &firstfsb);
nimaps = 1;
@@ -484,8 +550,10 @@ xfs_iomap_write_direct(
"extent-state : %x \n",
(ip->i_mount)->m_fsname,
(long long)ip->i_ino,
- ret_imap->br_startblock, ret_imap->br_startoff,
- ret_imap->br_blockcount,ret_imap->br_state);
+ (unsigned long long)ret_imap->br_startblock,
+ (unsigned long long)ret_imap->br_startoff,
+ (unsigned long long)ret_imap->br_blockcount,
+ ret_imap->br_state);
}
return 0;
@@ -501,6 +569,63 @@ error_out:
return XFS_ERROR(error);
}
+/*
+ * If the caller is doing a write at the end of the file,
+ * then extend the allocation out to the file system's write
+ * iosize. We clean up any extra space left over when the
+ * file is closed in xfs_inactive().
+ *
+ * For sync writes, we are flushing delayed allocate space to
+ * try to make additional space available for allocation near
+ * the filesystem full boundary - preallocation hurts in that
+ * situation, of course.
+ */
+STATIC int
+xfs_iomap_eof_want_preallocate(
+ xfs_mount_t *mp,
+ xfs_iocore_t *io,
+ xfs_fsize_t isize,
+ xfs_off_t offset,
+ size_t count,
+ int ioflag,
+ xfs_bmbt_irec_t *imap,
+ int nimaps,
+ int *prealloc)
+{
+ xfs_fileoff_t start_fsb;
+ xfs_filblks_t count_fsb;
+ xfs_fsblock_t firstblock;
+ int n, error, imaps;
+
+ *prealloc = 0;
+ if ((ioflag & BMAPI_SYNC) || (offset + count) <= isize)
+ return 0;
+
+ /*
+ * If there are any real blocks past eof, then don't
+ * do any speculative allocation.
+ */
+ start_fsb = XFS_B_TO_FSBT(mp, ((xfs_ufsize_t)(offset + count - 1)));
+ count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
+ while (count_fsb > 0) {
+ imaps = nimaps;
+ firstblock = NULLFSBLOCK;
+ error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb,
+ 0, &firstblock, 0, imap, &imaps, NULL);
+ if (error)
+ return error;
+ for (n = 0; n < imaps; n++) {
+ if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
+ (imap[n].br_startblock != DELAYSTARTBLOCK))
+ return 0;
+ start_fsb += imap[n].br_blockcount;
+ count_fsb -= imap[n].br_blockcount;
+ }
+ }
+ *prealloc = 1;
+ return 0;
+}
+
int
xfs_iomap_write_delay(
xfs_inode_t *ip,
@@ -514,13 +639,15 @@ xfs_iomap_write_delay(
xfs_iocore_t *io = &ip->i_iocore;
xfs_fileoff_t offset_fsb;
xfs_fileoff_t last_fsb;
- xfs_fsize_t isize;
+ xfs_off_t aligned_offset;
+ xfs_fileoff_t ioalign;
xfs_fsblock_t firstblock;
+ xfs_extlen_t extsz;
+ xfs_fsize_t isize;
int nimaps;
- int error;
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS];
- int aeof;
- int fsynced = 0;
+ int prealloc, fsynced = 0;
+ int error;
ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
@@ -528,152 +655,57 @@ xfs_iomap_write_delay(
* Make sure that the dquots are there. This doesn't hold
* the ilock across a disk read.
*/
-
error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
if (error)
return XFS_ERROR(error);
+ if (XFS_IS_REALTIME_INODE(ip)) {
+ if (!(extsz = ip->i_d.di_extsize))
+ extsz = mp->m_sb.sb_rextsize;
+ } else {
+ extsz = ip->i_d.di_extsize;
+ }
+
+ offset_fsb = XFS_B_TO_FSBT(mp, offset);
+
retry:
isize = ip->i_d.di_size;
- if (io->io_new_size > isize) {
+ if (io->io_new_size > isize)
isize = io->io_new_size;
- }
- aeof = 0;
- offset_fsb = XFS_B_TO_FSBT(mp, offset);
- last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
- /*
- * If the caller is doing a write at the end of the file,
- * then extend the allocation (and the buffer used for the write)
- * out to the file system's write iosize. We clean up any extra
- * space left over when the file is closed in xfs_inactive().
- *
- * For sync writes, we are flushing delayed allocate space to
- * try to make additional space available for allocation near
- * the filesystem full boundary - preallocation hurts in that
- * situation, of course.
- */
- if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
- xfs_off_t aligned_offset;
- xfs_filblks_t count_fsb;
- unsigned int iosize;
- xfs_fileoff_t ioalign;
- int n;
- xfs_fileoff_t start_fsb;
+ error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count,
+ ioflag, imap, XFS_WRITE_IMAPS, &prealloc);
+ if (error)
+ return error;
- /*
- * If there are any real blocks past eof, then don't
- * do any speculative allocation.
- */
- start_fsb = XFS_B_TO_FSBT(mp,
- ((xfs_ufsize_t)(offset + count - 1)));
- count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
- while (count_fsb > 0) {
- nimaps = XFS_WRITE_IMAPS;
- error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb,
- 0, &firstblock, 0, imap, &nimaps, NULL);
- if (error) {
- return error;
- }
- for (n = 0; n < nimaps; n++) {
- if ( !(io->io_flags & XFS_IOCORE_RT) &&
- !imap[n].br_startblock) {
- cmn_err(CE_PANIC,"Access to block "
- "zero: fs <%s> inode: %lld "
- "start_block : %llx start_off "
- ": %llx blkcnt : %llx "
- "extent-state : %x \n",
- (ip->i_mount)->m_fsname,
- (long long)ip->i_ino,
- imap[n].br_startblock,
- imap[n].br_startoff,
- imap[n].br_blockcount,
- imap[n].br_state);
- }
- if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
- (imap[n].br_startblock != DELAYSTARTBLOCK)) {
- goto write_map;
- }
- start_fsb += imap[n].br_blockcount;
- count_fsb -= imap[n].br_blockcount;
- }
- }
- iosize = mp->m_writeio_blocks;
+ if (prealloc) {
aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1));
ioalign = XFS_B_TO_FSBT(mp, aligned_offset);
- last_fsb = ioalign + iosize;
- aeof = 1;
+ last_fsb = ioalign + mp->m_writeio_blocks;
+ } else {
+ last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
}
-write_map:
- nimaps = XFS_WRITE_IMAPS;
- firstblock = NULLFSBLOCK;
- /*
- * If mounted with the "-o swalloc" option, roundup the allocation
- * request to a stripe width boundary if the file size is >=
- * stripe width and we are allocating past the allocation eof.
- */
- if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth
- && (mp->m_flags & XFS_MOUNT_SWALLOC)
- && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) {
- int eof;
- xfs_fileoff_t new_last_fsb;
-
- new_last_fsb = roundup_64(last_fsb, mp->m_swidth);
- error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
- if (error) {
- return error;
- }
- if (eof) {
- last_fsb = new_last_fsb;
- }
- /*
- * Roundup the allocation request to a stripe unit (m_dalign) boundary
- * if the file size is >= stripe unit size, and we are allocating past
- * the allocation eof.
- */
- } else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign &&
- (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) {
- int eof;
- xfs_fileoff_t new_last_fsb;
- new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
- error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof);
- if (error) {
- return error;
- }
- if (eof) {
- last_fsb = new_last_fsb;
- }
- /*
- * Round up the allocation request to a real-time extent boundary
- * if the file is on the real-time subvolume.
- */
- } else if (io->io_flags & XFS_IOCORE_RT && aeof) {
- int eof;
- xfs_fileoff_t new_last_fsb;
-
- new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize);
- error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
- if (error) {
+ if (prealloc || extsz) {
+ error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
+ &last_fsb);
+ if (error)
return error;
- }
- if (eof)
- last_fsb = new_last_fsb;
}
+
+ nimaps = XFS_WRITE_IMAPS;
+ firstblock = NULLFSBLOCK;
error = xfs_bmapi(NULL, ip, offset_fsb,
(xfs_filblks_t)(last_fsb - offset_fsb),
XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
&nimaps, NULL);
- /*
- * This can be EDQUOT, if nimaps == 0
- */
- if (error && (error != ENOSPC)) {
+ if (error && (error != ENOSPC))
return XFS_ERROR(error);
- }
+
/*
* If bmapi returned us nothing, and if we didn't get back EDQUOT,
- * then we must have run out of space.
+ * then we must have run out of space - flush delalloc, and retry..
*/
if (nimaps == 0) {
xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE,
@@ -685,17 +717,21 @@ write_map:
goto retry;
}
- *ret_imap = imap[0];
- *nmaps = 1;
- if ( !(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) {
+ if (!(io->io_flags & XFS_IOCORE_RT) && !ret_imap->br_startblock) {
cmn_err(CE_PANIC,"Access to block zero: fs <%s> inode: %lld "
"start_block : %llx start_off : %llx blkcnt : %llx "
"extent-state : %x \n",
(ip->i_mount)->m_fsname,
(long long)ip->i_ino,
- ret_imap->br_startblock, ret_imap->br_startoff,
- ret_imap->br_blockcount,ret_imap->br_state);
+ (unsigned long long)ret_imap->br_startblock,
+ (unsigned long long)ret_imap->br_startoff,
+ (unsigned long long)ret_imap->br_blockcount,
+ ret_imap->br_state);
}
+
+ *ret_imap = imap[0];
+ *nmaps = 1;
+
return 0;
}
@@ -821,17 +857,21 @@ xfs_iomap_write_allocate(
*/
for (i = 0; i < nimaps; i++) {
- if ( !(io->io_flags & XFS_IOCORE_RT) &&
- !imap[i].br_startblock) {
+ if (!(io->io_flags & XFS_IOCORE_RT) &&
+ !imap[i].br_startblock) {
cmn_err(CE_PANIC,"Access to block zero: "
"fs <%s> inode: %lld "
- "start_block : %llx start_off : %llx "
+ "start_block : %llx start_off : %llx "
"blkcnt : %llx extent-state : %x \n",
(ip->i_mount)->m_fsname,
(long long)ip->i_ino,
- imap[i].br_startblock,
- imap[i].br_startoff,
- imap[i].br_blockcount,imap[i].br_state);
+ (unsigned long long)
+ imap[i].br_startblock,
+ (unsigned long long)
+ imap[i].br_startoff,
+ (unsigned long long)
+ imap[i].br_blockcount,
+ imap[i].br_state);
}
if ((offset_fsb >= imap[i].br_startoff) &&
(offset_fsb < (imap[i].br_startoff +
@@ -868,17 +908,17 @@ xfs_iomap_write_unwritten(
{
xfs_mount_t *mp = ip->i_mount;
xfs_iocore_t *io = &ip->i_iocore;
- xfs_trans_t *tp;
xfs_fileoff_t offset_fsb;
xfs_filblks_t count_fsb;
xfs_filblks_t numblks_fsb;
- xfs_bmbt_irec_t imap;
+ xfs_fsblock_t firstfsb;
+ int nimaps;
+ xfs_trans_t *tp;
+ xfs_bmbt_irec_t imap;
+ xfs_bmap_free_t free_list;
+ uint resblks;
int committed;
int error;
- int nres;
- int nimaps;
- xfs_fsblock_t firstfsb;
- xfs_bmap_free_t free_list;
xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN,
&ip->i_iocore, offset, count);
@@ -887,9 +927,9 @@ xfs_iomap_write_unwritten(
count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
- do {
- nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1;
+ do {
/*
* set up a transaction to convert the range of extents
* from unwritten to real. Do allocations in a loop until
@@ -897,7 +937,7 @@ xfs_iomap_write_unwritten(
*/
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
- error = xfs_trans_reserve(tp, nres,
+ error = xfs_trans_reserve(tp, resblks,
XFS_WRITE_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
@@ -916,7 +956,7 @@ xfs_iomap_write_unwritten(
XFS_BMAP_INIT(&free_list, &firstfsb);
nimaps = 1;
error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
- XFS_BMAPI_WRITE, &firstfsb,
+ XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
1, &imap, &nimaps, &free_list);
if (error)
goto error_on_bmapi_transaction;
@@ -930,15 +970,17 @@ xfs_iomap_write_unwritten(
xfs_iunlock(ip, XFS_ILOCK_EXCL);
if (error)
goto error0;
-
+
if ( !(io->io_flags & XFS_IOCORE_RT) && !imap.br_startblock) {
cmn_err(CE_PANIC,"Access to block zero: fs <%s> "
"inode: %lld start_block : %llx start_off : "
"%llx blkcnt : %llx extent-state : %x \n",
(ip->i_mount)->m_fsname,
(long long)ip->i_ino,
- imap.br_startblock,imap.br_startoff,
- imap.br_blockcount,imap.br_state);
+ (unsigned long long)imap.br_startblock,
+ (unsigned long long)imap.br_startoff,
+ (unsigned long long)imap.br_blockcount,
+ imap.br_state);
}
if ((numblks_fsb = imap.br_blockcount) == 0) {
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index f63646ead816..c59450e1be40 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -56,6 +56,7 @@ xfs_bulkstat_one_iget(
{
xfs_dinode_core_t *dic; /* dinode core info pointer */
xfs_inode_t *ip; /* incore inode pointer */
+ vnode_t *vp;
int error;
error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
@@ -72,6 +73,7 @@ xfs_bulkstat_one_iget(
goto out_iput;
}
+ vp = XFS_ITOV(ip);
dic = &ip->i_d;
/* xfs_iget returns the following without needing
@@ -84,8 +86,7 @@ xfs_bulkstat_one_iget(
buf->bs_uid = dic->di_uid;
buf->bs_gid = dic->di_gid;
buf->bs_size = dic->di_size;
- buf->bs_atime.tv_sec = dic->di_atime.t_sec;
- buf->bs_atime.tv_nsec = dic->di_atime.t_nsec;
+ vn_atime_to_bstime(vp, &buf->bs_atime);
buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 29af51275ca9..9176995160ed 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -178,6 +178,83 @@ xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
#define xlog_trace_iclog(iclog,state)
#endif /* XFS_LOG_TRACE */
+
+static void
+xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
+{
+ if (*qp) {
+ tic->t_next = (*qp);
+ tic->t_prev = (*qp)->t_prev;
+ (*qp)->t_prev->t_next = tic;
+ (*qp)->t_prev = tic;
+ } else {
+ tic->t_prev = tic->t_next = tic;
+ *qp = tic;
+ }
+
+ tic->t_flags |= XLOG_TIC_IN_Q;
+}
+
+static void
+xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
+{
+ if (tic == tic->t_next) {
+ *qp = NULL;
+ } else {
+ *qp = tic->t_next;
+ tic->t_next->t_prev = tic->t_prev;
+ tic->t_prev->t_next = tic->t_next;
+ }
+
+ tic->t_next = tic->t_prev = NULL;
+ tic->t_flags &= ~XLOG_TIC_IN_Q;
+}
+
+static void
+xlog_grant_sub_space(struct log *log, int bytes)
+{
+ log->l_grant_write_bytes -= bytes;
+ if (log->l_grant_write_bytes < 0) {
+ log->l_grant_write_bytes += log->l_logsize;
+ log->l_grant_write_cycle--;
+ }
+
+ log->l_grant_reserve_bytes -= bytes;
+ if ((log)->l_grant_reserve_bytes < 0) {
+ log->l_grant_reserve_bytes += log->l_logsize;
+ log->l_grant_reserve_cycle--;
+ }
+
+}
+
+static void
+xlog_grant_add_space_write(struct log *log, int bytes)
+{
+ log->l_grant_write_bytes += bytes;
+ if (log->l_grant_write_bytes > log->l_logsize) {
+ log->l_grant_write_bytes -= log->l_logsize;
+ log->l_grant_write_cycle++;
+ }
+}
+
+static void
+xlog_grant_add_space_reserve(struct log *log, int bytes)
+{
+ log->l_grant_reserve_bytes += bytes;
+ if (log->l_grant_reserve_bytes > log->l_logsize) {
+ log->l_grant_reserve_bytes -= log->l_logsize;
+ log->l_grant_reserve_cycle++;
+ }
+}
+
+static inline void
+xlog_grant_add_space(struct log *log, int bytes)
+{
+ xlog_grant_add_space_write(log, bytes);
+ xlog_grant_add_space_reserve(log, bytes);
+}
+
+
/*
* NOTES:
*
@@ -326,7 +403,7 @@ xfs_log_release_iclog(xfs_mount_t *mp,
if (xlog_state_release_iclog(log, iclog)) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
- return(EIO);
+ return EIO;
}
return 0;
@@ -428,7 +505,7 @@ xfs_log_mount(xfs_mount_t *mp,
if (readonly)
vfsp->vfs_flag &= ~VFS_RDONLY;
- error = xlog_recover(mp->m_log, readonly);
+ error = xlog_recover(mp->m_log);
if (readonly)
vfsp->vfs_flag |= VFS_RDONLY;
@@ -479,7 +556,7 @@ xfs_log_unmount(xfs_mount_t *mp)
error = xfs_log_unmount_write(mp);
xfs_log_unmount_dealloc(mp);
- return (error);
+ return error;
}
/*
@@ -651,7 +728,7 @@ xfs_log_write(xfs_mount_t * mp,
if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
}
- return (error);
+ return error;
} /* xfs_log_write */
@@ -759,7 +836,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
needed = 1;
}
LOG_UNLOCK(log, s);
- return(needed);
+ return needed;
}
/******************************************************************************
@@ -926,7 +1003,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
XFS_BUF_ERROR(bp, EIO);
XFS_BUF_STALE(bp);
xfs_biodone(bp);
- return (XFS_ERROR(EIO));
+ return XFS_ERROR(EIO);
}
@@ -1186,7 +1263,7 @@ xlog_commit_record(xfs_mount_t *mp,
iclog, XLOG_COMMIT_TRANS))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
}
- return (error);
+ return error;
} /* xlog_commit_record */
@@ -1320,8 +1397,7 @@ xlog_sync(xlog_t *log,
/* move grant heads by roundoff in sync */
s = GRANT_LOCK(log);
- XLOG_GRANT_ADD_SPACE(log, roundoff, 'w');
- XLOG_GRANT_ADD_SPACE(log, roundoff, 'r');
+ xlog_grant_add_space(log, roundoff);
GRANT_UNLOCK(log, s);
/* put cycle number in every block */
@@ -1384,7 +1460,7 @@ xlog_sync(xlog_t *log,
if ((error = XFS_bwrite(bp))) {
xfs_ioerror_alert("xlog_sync", log->l_mp, bp,
XFS_BUF_ADDR(bp));
- return (error);
+ return error;
}
if (split) {
bp = iclog->ic_log->l_xbuf;
@@ -1422,10 +1498,10 @@ xlog_sync(xlog_t *log,
if ((error = XFS_bwrite(bp))) {
xfs_ioerror_alert("xlog_sync (split)", log->l_mp,
bp, XFS_BUF_ADDR(bp));
- return (error);
+ return error;
}
}
- return (0);
+ return 0;
} /* xlog_sync */
@@ -1515,7 +1591,6 @@ 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)
{
@@ -1605,11 +1680,11 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
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_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;
+ uint r_type = ticket->t_res_arr[i].r_type;
cmn_err(CE_WARN,
"region[%u]: %s - %u bytes\n",
i,
@@ -1618,9 +1693,6 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
ticket->t_res_arr[i].r_len);
}
}
-#else
-#define xlog_print_tic_res(mp, ticket)
-#endif
/*
* Write some region out to in-core log
@@ -1726,7 +1798,7 @@ xlog_write(xfs_mount_t * mp,
for (index = 0; index < nentries; ) {
if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
&contwr, &log_offset)))
- return (error);
+ return error;
ASSERT(log_offset <= iclog->ic_size - 1);
ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset);
@@ -1831,7 +1903,7 @@ xlog_write(xfs_mount_t * mp,
xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
record_cnt = data_cnt = 0;
if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
break; /* don't increment index */
} else { /* copied entire region */
index++;
@@ -1845,7 +1917,7 @@ xlog_write(xfs_mount_t * mp,
ASSERT(flags & XLOG_COMMIT_TRANS);
*commit_iclog = iclog;
} else if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
if (index == nentries)
return 0; /* we are done */
else
@@ -1862,7 +1934,7 @@ xlog_write(xfs_mount_t * mp,
*commit_iclog = iclog;
return 0;
}
- return (xlog_state_release_iclog(log, iclog));
+ return xlog_state_release_iclog(log, iclog);
} /* xlog_write */
@@ -1978,7 +2050,7 @@ xlog_get_lowest_lsn(
}
lsn_log = lsn_log->ic_next;
} while (lsn_log != log->l_iclog);
- return(lowest_lsn);
+ return lowest_lsn;
}
@@ -2330,7 +2402,7 @@ restart:
if (iclog->ic_refcnt == 1) {
LOG_UNLOCK(log, s);
if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
} else {
iclog->ic_refcnt--;
LOG_UNLOCK(log, s);
@@ -2389,7 +2461,7 @@ xlog_grant_log_space(xlog_t *log,
/* something is already sleeping; insert new transaction at end */
if (log->l_reserve_headq) {
- XLOG_INS_TICKETQ(log->l_reserve_headq, tic);
+ xlog_ins_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: sleep 1");
/*
@@ -2422,7 +2494,7 @@ redo:
log->l_grant_reserve_bytes);
if (free_bytes < need_bytes) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_reserve_headq, tic);
+ xlog_ins_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: sleep 2");
XFS_STATS_INC(xs_sleep_logspace);
@@ -2439,11 +2511,10 @@ redo:
s = GRANT_LOCK(log);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
/* we've got enough space */
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w');
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'r');
+ xlog_grant_add_space(log, need_bytes);
#ifdef DEBUG
tail_lsn = log->l_tail_lsn;
/*
@@ -2464,7 +2535,7 @@ redo:
error_return:
if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret");
/*
* If we are failing, make sure the ticket doesn't have any
@@ -2498,7 +2569,7 @@ xlog_regrant_write_log_space(xlog_t *log,
XLOG_TIC_RESET_RES(tic);
if (tic->t_cnt > 0)
- return (0);
+ return 0;
#ifdef DEBUG
if (log->l_flags & XLOG_ACTIVE_RECOVERY)
@@ -2533,7 +2604,7 @@ xlog_regrant_write_log_space(xlog_t *log,
if (ntic != log->l_write_headq) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_write_headq, tic);
+ xlog_ins_ticketq(&log->l_write_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_regrant_write_log_space: sleep 1");
@@ -2565,7 +2636,7 @@ redo:
log->l_grant_write_bytes);
if (free_bytes < need_bytes) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_write_headq, tic);
+ xlog_ins_ticketq(&log->l_write_headq, tic);
XFS_STATS_INC(xs_sleep_logspace);
sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
@@ -2581,9 +2652,10 @@ redo:
s = GRANT_LOCK(log);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_write_headq, tic);
+ xlog_del_ticketq(&log->l_write_headq, tic);
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w'); /* we've got enough space */
+ /* we've got enough space */
+ xlog_grant_add_space_write(log, need_bytes);
#ifdef DEBUG
tail_lsn = log->l_tail_lsn;
if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
@@ -2595,12 +2667,12 @@ redo:
xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
xlog_verify_grant_head(log, 1);
GRANT_UNLOCK(log, s);
- return (0);
+ return 0;
error_return:
if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret");
/*
* If we are failing, make sure the ticket doesn't have any
@@ -2633,8 +2705,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
ticket->t_cnt--;
s = GRANT_LOCK(log);
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r');
+ xlog_grant_sub_space(log, ticket->t_curr_res);
ticket->t_curr_res = ticket->t_unit_res;
XLOG_TIC_RESET_RES(ticket);
xlog_trace_loggrant(log, ticket,
@@ -2647,7 +2718,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
return;
}
- XLOG_GRANT_ADD_SPACE(log, ticket->t_unit_res, 'r');
+ xlog_grant_add_space_reserve(log, ticket->t_unit_res);
xlog_trace_loggrant(log, ticket,
"xlog_regrant_reserve_log_space: exit");
xlog_verify_grant_head(log, 0);
@@ -2683,8 +2754,7 @@ xlog_ungrant_log_space(xlog_t *log,
s = GRANT_LOCK(log);
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r');
+ xlog_grant_sub_space(log, ticket->t_curr_res);
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current");
@@ -2693,8 +2763,7 @@ xlog_ungrant_log_space(xlog_t *log,
*/
if (ticket->t_cnt > 0) {
ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV);
- XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'r');
+ xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt);
}
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
@@ -2768,7 +2837,7 @@ xlog_state_release_iclog(xlog_t *log,
if (sync) {
return xlog_sync(log, iclog);
}
- return (0);
+ return 0;
} /* xlog_state_release_iclog */
@@ -3058,7 +3127,7 @@ try_again:
} while (iclog != log->l_iclog);
LOG_UNLOCK(log, s);
- return (0);
+ return 0;
} /* xlog_state_sync */
@@ -3476,12 +3545,12 @@ xlog_state_ioerror(
ic->ic_state = XLOG_STATE_IOERROR;
ic = ic->ic_next;
} while (ic != iclog);
- return (0);
+ return 0;
}
/*
* Return non-zero, if state transition has already happened.
*/
- return (1);
+ return 1;
}
/*
@@ -3518,7 +3587,7 @@ xfs_log_force_umount(
log->l_flags & XLOG_ACTIVE_RECOVERY) {
mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
XFS_BUF_DONE(mp->m_sb_bp);
- return (0);
+ return 0;
}
/*
@@ -3527,7 +3596,7 @@ xfs_log_force_umount(
*/
if (logerror && log->l_iclog->ic_state & XLOG_STATE_IOERROR) {
ASSERT(XLOG_FORCED_SHUTDOWN(log));
- return (1);
+ return 1;
}
retval = 0;
/*
@@ -3609,7 +3678,7 @@ xfs_log_force_umount(
}
#endif
/* return non-zero if log IOERROR transition had already happened */
- return (retval);
+ return retval;
}
STATIC int
@@ -3623,8 +3692,8 @@ xlog_iclogs_empty(xlog_t *log)
* any language.
*/
if (iclog->ic_header.h_num_logops)
- return(0);
+ return 0;
iclog = iclog->ic_next;
} while (iclog != log->l_iclog);
- return(1);
+ return 1;
}
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 158829ca56f6..4b2ac88dbb83 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -30,13 +30,7 @@
* By comparing each compnent, we don't have to worry about extra
* endian issues in treating two 32 bit numbers as one 64 bit number
*/
-static
-#if defined(__GNUC__) && (__GNUC__ == 2) && ( (__GNUC_MINOR__ == 95) || (__GNUC_MINOR__ == 96))
-__attribute__((unused)) /* gcc 2.95, 2.96 miscompile this when inlined */
-#else
-__inline__
-#endif
-xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
+static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
{
if (CYCLE_LSN(lsn1) != CYCLE_LSN(lsn2))
return (CYCLE_LSN(lsn1)<CYCLE_LSN(lsn2))? -999 : 999;
@@ -102,7 +96,6 @@ xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
/* 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
@@ -123,21 +116,13 @@ xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
#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
+ uint i_type; /* type of region */
} xfs_log_iovec_t;
typedef void* xfs_log_ticket_t;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 4518b188ade6..34bcbf50789c 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -253,7 +253,6 @@ typedef __uint32_t xlog_tid_t;
/* 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)
@@ -278,15 +277,9 @@ typedef __uint32_t xlog_tid_t;
* we don't care about.
*/
typedef struct xlog_res {
- uint r_len;
- uint r_type;
+ uint r_len; /* region length :4 */
+ uint r_type; /* region's transaction type :4 */
} 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 */
@@ -301,14 +294,12 @@ typedef struct xlog_ticket {
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_res_t t_res_arr[XLOG_TIC_LEN_MAX]; /* array of res : 8 * 15 */
} xlog_ticket_t;
#endif
@@ -494,71 +485,13 @@ typedef struct log {
#define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR)
-#define XLOG_GRANT_SUB_SPACE(log,bytes,type) \
- { \
- if (type == 'w') { \
- (log)->l_grant_write_bytes -= (bytes); \
- if ((log)->l_grant_write_bytes < 0) { \
- (log)->l_grant_write_bytes += (log)->l_logsize; \
- (log)->l_grant_write_cycle--; \
- } \
- } else { \
- (log)->l_grant_reserve_bytes -= (bytes); \
- if ((log)->l_grant_reserve_bytes < 0) { \
- (log)->l_grant_reserve_bytes += (log)->l_logsize;\
- (log)->l_grant_reserve_cycle--; \
- } \
- } \
- }
-#define XLOG_GRANT_ADD_SPACE(log,bytes,type) \
- { \
- if (type == 'w') { \
- (log)->l_grant_write_bytes += (bytes); \
- if ((log)->l_grant_write_bytes > (log)->l_logsize) { \
- (log)->l_grant_write_bytes -= (log)->l_logsize; \
- (log)->l_grant_write_cycle++; \
- } \
- } else { \
- (log)->l_grant_reserve_bytes += (bytes); \
- if ((log)->l_grant_reserve_bytes > (log)->l_logsize) { \
- (log)->l_grant_reserve_bytes -= (log)->l_logsize;\
- (log)->l_grant_reserve_cycle++; \
- } \
- } \
- }
-#define XLOG_INS_TICKETQ(q, tic) \
- { \
- if (q) { \
- (tic)->t_next = (q); \
- (tic)->t_prev = (q)->t_prev; \
- (q)->t_prev->t_next = (tic); \
- (q)->t_prev = (tic); \
- } else { \
- (tic)->t_prev = (tic)->t_next = (tic); \
- (q) = (tic); \
- } \
- (tic)->t_flags |= XLOG_TIC_IN_Q; \
- }
-#define XLOG_DEL_TICKETQ(q, tic) \
- { \
- if ((tic) == (tic)->t_next) { \
- (q) = NULL; \
- } else { \
- (q) = (tic)->t_next; \
- (tic)->t_next->t_prev = (tic)->t_prev; \
- (tic)->t_prev->t_next = (tic)->t_next; \
- } \
- (tic)->t_next = (tic)->t_prev = NULL; \
- (tic)->t_flags &= ~XLOG_TIC_IN_Q; \
- }
/* common routines */
extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
extern int xlog_find_tail(xlog_t *log,
xfs_daddr_t *head_blk,
- xfs_daddr_t *tail_blk,
- int readonly);
-extern int xlog_recover(xlog_t *log, int readonly);
+ xfs_daddr_t *tail_blk);
+extern int xlog_recover(xlog_t *log);
extern int xlog_recover_finish(xlog_t *log, int mfsi_flags);
extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
extern void xlog_recover_process_iunlinks(xlog_t *log);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 8ab7df768063..7d46cbd6a07a 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -783,8 +783,7 @@ int
xlog_find_tail(
xlog_t *log,
xfs_daddr_t *head_blk,
- xfs_daddr_t *tail_blk,
- int readonly)
+ xfs_daddr_t *tail_blk)
{
xlog_rec_header_t *rhead;
xlog_op_header_t *op_head;
@@ -2563,10 +2562,12 @@ xlog_recover_do_quotaoff_trans(
/*
* The logitem format's flag tells us if this was user quotaoff,
- * group quotaoff or both.
+ * group/project quotaoff or both.
*/
if (qoff_f->qf_flags & XFS_UQUOTA_ACCT)
log->l_quotaoffs_flag |= XFS_DQ_USER;
+ if (qoff_f->qf_flags & XFS_PQUOTA_ACCT)
+ log->l_quotaoffs_flag |= XFS_DQ_PROJ;
if (qoff_f->qf_flags & XFS_GQUOTA_ACCT)
log->l_quotaoffs_flag |= XFS_DQ_GROUP;
@@ -3890,14 +3891,13 @@ xlog_do_recover(
*/
int
xlog_recover(
- xlog_t *log,
- int readonly)
+ xlog_t *log)
{
xfs_daddr_t head_blk, tail_blk;
int error;
/* find the tail of the log */
- if ((error = xlog_find_tail(log, &head_blk, &tail_blk, readonly)))
+ if ((error = xlog_find_tail(log, &head_blk, &tail_blk)))
return error;
if (tail_blk != head_blk) {
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 541d5dd474be..62188ea392c7 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -51,7 +51,7 @@ STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
STATIC void xfs_unmountfs_wait(xfs_mount_t *);
-static struct {
+static const struct {
short offset;
short type; /* 0 = integer
* 1 = binary / string (no translation)
@@ -117,7 +117,7 @@ xfs_mount_init(void)
AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
spinlock_init(&mp->m_sb_lock, "xfs_sb");
- mutex_init(&mp->m_ilock, MUTEX_DEFAULT, "xfs_ilock");
+ mutex_init(&mp->m_ilock);
initnsema(&mp->m_growlock, 1, "xfs_grow");
/*
* Initialize the AIL.
@@ -646,7 +646,7 @@ xfs_mountfs(
if (mp->m_sb_bp == NULL) {
if ((error = xfs_readsb(mp))) {
- return (error);
+ return error;
}
}
xfs_mount_common(mp, sbp);
@@ -889,7 +889,7 @@ xfs_mountfs(
* For client case we are done now
*/
if (mfsi_flags & XFS_MFSI_CLIENT) {
- return(0);
+ return 0;
}
/*
@@ -1077,8 +1077,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
xfs_iflush_all(mp);
- XFS_QM_DQPURGEALL(mp,
- XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);
+ XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
/*
* Flush out the log synchronously so that we know for sure
@@ -1183,7 +1182,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly");
}
xfs_buf_relse(sbp);
- return (error);
+ return error;
}
/*
@@ -1258,19 +1257,19 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
lcounter += delta;
if (lcounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_icount = lcounter;
- return (0);
+ return 0;
case XFS_SBS_IFREE:
lcounter = (long long)mp->m_sb.sb_ifree;
lcounter += delta;
if (lcounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_ifree = lcounter;
- return (0);
+ return 0;
case XFS_SBS_FDBLOCKS:
lcounter = (long long)mp->m_sb.sb_fdblocks;
@@ -1297,101 +1296,101 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
if (rsvd) {
lcounter = (long long)mp->m_resblks_avail + delta;
if (lcounter < 0) {
- return (XFS_ERROR(ENOSPC));
+ return XFS_ERROR(ENOSPC);
}
mp->m_resblks_avail = lcounter;
- return (0);
+ return 0;
} else { /* not reserved */
- return (XFS_ERROR(ENOSPC));
+ return XFS_ERROR(ENOSPC);
}
}
}
mp->m_sb.sb_fdblocks = lcounter;
- return (0);
+ return 0;
case XFS_SBS_FREXTENTS:
lcounter = (long long)mp->m_sb.sb_frextents;
lcounter += delta;
if (lcounter < 0) {
- return (XFS_ERROR(ENOSPC));
+ return XFS_ERROR(ENOSPC);
}
mp->m_sb.sb_frextents = lcounter;
- return (0);
+ return 0;
case XFS_SBS_DBLOCKS:
lcounter = (long long)mp->m_sb.sb_dblocks;
lcounter += delta;
if (lcounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_dblocks = lcounter;
- return (0);
+ return 0;
case XFS_SBS_AGCOUNT:
scounter = mp->m_sb.sb_agcount;
scounter += delta;
if (scounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_agcount = scounter;
- return (0);
+ return 0;
case XFS_SBS_IMAX_PCT:
scounter = mp->m_sb.sb_imax_pct;
scounter += delta;
if (scounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_imax_pct = scounter;
- return (0);
+ return 0;
case XFS_SBS_REXTSIZE:
scounter = mp->m_sb.sb_rextsize;
scounter += delta;
if (scounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_rextsize = scounter;
- return (0);
+ return 0;
case XFS_SBS_RBMBLOCKS:
scounter = mp->m_sb.sb_rbmblocks;
scounter += delta;
if (scounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_rbmblocks = scounter;
- return (0);
+ return 0;
case XFS_SBS_RBLOCKS:
lcounter = (long long)mp->m_sb.sb_rblocks;
lcounter += delta;
if (lcounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_rblocks = lcounter;
- return (0);
+ return 0;
case XFS_SBS_REXTENTS:
lcounter = (long long)mp->m_sb.sb_rextents;
lcounter += delta;
if (lcounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_rextents = lcounter;
- return (0);
+ return 0;
case XFS_SBS_REXTSLOG:
scounter = mp->m_sb.sb_rextslog;
scounter += delta;
if (scounter < 0) {
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
mp->m_sb.sb_rextslog = scounter;
- return (0);
+ return 0;
default:
ASSERT(0);
- return (XFS_ERROR(EINVAL));
+ return XFS_ERROR(EINVAL);
}
}
@@ -1410,7 +1409,7 @@ xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
s = XFS_SB_LOCK(mp);
status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
XFS_SB_UNLOCK(mp, s);
- return (status);
+ return status;
}
/*
@@ -1471,7 +1470,7 @@ xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
}
}
XFS_SB_UNLOCK(mp, s);
- return (status);
+ return status;
}
/*
@@ -1501,7 +1500,7 @@ xfs_getsb(
}
XFS_BUF_HOLD(bp);
ASSERT(XFS_BUF_ISDONE(bp));
- return (bp);
+ return bp;
}
/*
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 08b2e0a5d807..cd3cf9613a00 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -308,7 +308,6 @@ typedef struct xfs_mount {
xfs_buftarg_t *m_ddev_targp; /* saves taking the address */
xfs_buftarg_t *m_logdev_targp;/* ptr to log device */
xfs_buftarg_t *m_rtdev_targp; /* ptr to rt device */
-#define m_dev m_ddev_targp->pbr_dev
__uint8_t m_dircook_elog; /* log d-cookie entry bits */
__uint8_t m_blkbit_log; /* blocklog + NBBY */
__uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
@@ -393,7 +392,7 @@ typedef struct xfs_mount {
user */
#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
allocations */
-#define XFS_MOUNT_COMPAT_ATTR (1ULL << 8) /* do not use attr2 format */
+#define XFS_MOUNT_ATTR2 (1ULL << 8) /* allow use of attr2 format */
/* (1ULL << 9) -- currently unused */
#define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */
#define XFS_MOUNT_SHARED (1ULL << 11) /* shared mount */
@@ -533,7 +532,7 @@ typedef struct xfs_mod_sb {
int msb_delta; /* Change to make to specified field */
} xfs_mod_sb_t;
-#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock), PINOD)
+#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock))
#define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock))
#define XFS_SB_LOCK(mp) mutex_spinlock(&(mp)->m_sb_lock)
#define XFS_SB_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_sb_lock,(s))
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 4d4e8f4e768e..81a05cfd77d2 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -243,7 +243,6 @@ xfs_rename(
xfs_inode_t *inodes[4];
int target_ip_dropped = 0; /* dropped target_ip link? */
vnode_t *src_dir_vp;
- bhv_desc_t *target_dir_bdp;
int spaceres;
int target_link_zero = 0;
int num_inodes;
@@ -260,14 +259,12 @@ xfs_rename(
* Find the XFS behavior descriptor for the target directory
* vnode since it was not handed to us.
*/
- target_dir_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(target_dir_vp),
- &xfs_vnodeops);
- if (target_dir_bdp == NULL) {
+ target_dp = xfs_vtoi(target_dir_vp);
+ if (target_dp == NULL) {
return XFS_ERROR(EXDEV);
}
src_dp = XFS_BHVTOI(src_dir_bdp);
- target_dp = XFS_BHVTOI(target_dir_bdp);
mp = src_dp->i_mount;
if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) ||
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index c4b20872f07d..a59c102cf214 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -238,6 +238,7 @@ xfs_bioerror_relse(
}
return (EIO);
}
+
/*
* Prints out an ALERT message about I/O error.
*/
@@ -252,11 +253,9 @@ xfs_ioerror_alert(
"I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
" (\"%s\") error %d buf count %zd",
(!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
- XFS_BUFTARG_NAME(bp->pb_target),
- (__uint64_t)blkno,
- func,
- XFS_BUF_GETERROR(bp),
- XFS_BUF_COUNT(bp));
+ XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
+ (__uint64_t)blkno, func,
+ XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
}
/*
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 4a17d335f897..bf168a91ddb8 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -68,18 +68,6 @@ struct xfs_mount;
(XFS_SB_VERSION_NUMBITS | \
XFS_SB_VERSION_OKREALFBITS | \
XFS_SB_VERSION_OKSASHFBITS)
-#define XFS_SB_VERSION_MKFS(ia,dia,extflag,dirv2,na,sflag,morebits) \
- (((ia) || (dia) || (extflag) || (dirv2) || (na) || (sflag) || \
- (morebits)) ? \
- (XFS_SB_VERSION_4 | \
- ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \
- ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \
- ((extflag) ? XFS_SB_VERSION_EXTFLGBIT : 0) | \
- ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \
- ((na) ? XFS_SB_VERSION_LOGV2BIT : 0) | \
- ((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) | \
- ((morebits) ? XFS_SB_VERSION_MOREBITSBIT : 0)) : \
- XFS_SB_VERSION_1)
/*
* There are two words to hold XFS "feature" bits: the original
@@ -105,11 +93,6 @@ struct xfs_mount;
(XFS_SB_VERSION2_OKREALFBITS | \
XFS_SB_VERSION2_OKSASHFBITS )
-/*
- * mkfs macro to set up sb_features2 word
- */
-#define XFS_SB_VERSION2_MKFS(resvd1, sbcntr) 0
-
typedef struct xfs_sb
{
__uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 279e043d7323..d3d714e6b32a 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1014,6 +1014,7 @@ xfs_trans_cancel(
xfs_log_item_t *lip;
int i;
#endif
+ xfs_mount_t *mp = tp->t_mountp;
/*
* See if the caller is being too lazy to figure out if
@@ -1026,9 +1027,10 @@ xfs_trans_cancel(
* filesystem. This happens in paths where we detect
* corruption and decide to give up.
*/
- if ((tp->t_flags & XFS_TRANS_DIRTY) &&
- !XFS_FORCED_SHUTDOWN(tp->t_mountp))
- xfs_force_shutdown(tp->t_mountp, XFS_CORRUPT_INCORE);
+ if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
+ XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
+ xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+ }
#ifdef DEBUG
if (!(flags & XFS_TRANS_ABORT)) {
licp = &(tp->t_items);
@@ -1040,7 +1042,7 @@ xfs_trans_cancel(
}
lip = lidp->lid_item;
- if (!XFS_FORCED_SHUTDOWN(tp->t_mountp))
+ if (!XFS_FORCED_SHUTDOWN(mp))
ASSERT(!(lip->li_type == XFS_LI_EFD));
}
licp = licp->lic_next;
@@ -1048,7 +1050,7 @@ xfs_trans_cancel(
}
#endif
xfs_trans_unreserve_and_mod_sb(tp);
- XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(tp->t_mountp, tp);
+ XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp);
if (tp->t_ticket) {
if (flags & XFS_TRANS_RELEASE_LOG_RES) {
@@ -1057,7 +1059,7 @@ xfs_trans_cancel(
} else {
log_flags = 0;
}
- xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, log_flags);
+ xfs_log_done(mp, tp->t_ticket, NULL, log_flags);
}
/* mark this thread as no longer being in a transaction */
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index a889963fdd14..d77901c07f63 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -973,7 +973,6 @@ 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 *);
void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 486147ef0e3d..1117d600d741 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -78,7 +78,7 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
lidp->lid_size = 0;
lip->li_desc = lidp;
lip->li_mountp = tp->t_mountp;
- return (lidp);
+ return lidp;
}
/*
@@ -119,7 +119,7 @@ xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip)
lidp->lid_size = 0;
lip->li_desc = lidp;
lip->li_mountp = tp->t_mountp;
- return (lidp);
+ return lidp;
}
/*
@@ -180,7 +180,7 @@ xfs_trans_find_item(xfs_trans_t *tp, xfs_log_item_t *lip)
{
ASSERT(lip->li_desc != NULL);
- return (lip->li_desc);
+ return lip->li_desc;
}
@@ -219,10 +219,10 @@ xfs_trans_first_item(xfs_trans_t *tp)
continue;
}
- return (XFS_LIC_SLOT(licp, i));
+ return XFS_LIC_SLOT(licp, i);
}
cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item");
- return(NULL);
+ return NULL;
}
@@ -252,7 +252,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
continue;
}
- return (XFS_LIC_SLOT(licp, i));
+ return XFS_LIC_SLOT(licp, i);
}
/*
@@ -261,7 +261,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
* If there is no next chunk, return NULL.
*/
if (licp->lic_next == NULL) {
- return (NULL);
+ return NULL;
}
licp = licp->lic_next;
@@ -271,7 +271,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
continue;
}
- return (XFS_LIC_SLOT(licp, i));
+ return XFS_LIC_SLOT(licp, i);
}
ASSERT(0);
/* NOTREACHED */
@@ -425,7 +425,7 @@ xfs_trans_unlock_chunk(
}
}
- return (freed);
+ return freed;
}
@@ -478,7 +478,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx)
*/
lbsp->lbc_ag = ag;
lbsp->lbc_idx = idx;
- return (lbsp);
+ return lbsp;
}
/*
@@ -512,7 +512,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx)
tp->t_busy_free--;
lbsp->lbc_ag = ag;
lbsp->lbc_idx = idx;
- return (lbsp);
+ return lbsp;
}
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index fefe1d60377f..34654ec6ae10 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -55,16 +55,13 @@ xfs_get_dir_entry(
xfs_inode_t **ipp)
{
vnode_t *vp;
- bhv_desc_t *bdp;
vp = VNAME_TO_VNODE(dentry);
- bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops);
- if (!bdp) {
- *ipp = NULL;
+
+ *ipp = xfs_vtoi(vp);
+ if (!*ipp)
return XFS_ERROR(ENOENT);
- }
VN_HOLD(vp);
- *ipp = XFS_BHVTOI(bdp);
return 0;
}
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 7bdbd991ab1c..b6ad370fab3d 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -53,6 +53,7 @@
#include "xfs_acl.h"
#include "xfs_attr.h"
#include "xfs_clnt.h"
+#include "xfs_fsops.h"
STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
@@ -290,8 +291,8 @@ xfs_start_flags(
mp->m_flags |= XFS_MOUNT_IDELETE;
if (ap->flags & XFSMNT_DIRSYNC)
mp->m_flags |= XFS_MOUNT_DIRSYNC;
- if (ap->flags & XFSMNT_COMPAT_ATTR)
- mp->m_flags |= XFS_MOUNT_COMPAT_ATTR;
+ if (ap->flags & XFSMNT_ATTR2)
+ mp->m_flags |= XFS_MOUNT_ATTR2;
if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)
mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
@@ -312,6 +313,8 @@ xfs_start_flags(
mp->m_flags |= XFS_MOUNT_NOUUID;
if (ap->flags & XFSMNT_BARRIER)
mp->m_flags |= XFS_MOUNT_BARRIER;
+ else
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
return 0;
}
@@ -330,10 +333,11 @@ xfs_finish_flags(
/* Fail a mount where the logbuf is smaller then the log stripe */
if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
- if ((ap->logbufsize == -1) &&
+ if ((ap->logbufsize <= 0) &&
(mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
mp->m_logbsize = mp->m_sb.sb_logsunit;
- } else if (ap->logbufsize < mp->m_sb.sb_logsunit) {
+ } else if (ap->logbufsize > 0 &&
+ ap->logbufsize < mp->m_sb.sb_logsunit) {
cmn_err(CE_WARN,
"XFS: logbuf size must be greater than or equal to log stripe size");
return XFS_ERROR(EINVAL);
@@ -347,6 +351,10 @@ xfs_finish_flags(
}
}
+ if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
+ mp->m_flags |= XFS_MOUNT_ATTR2;
+ }
+
/*
* prohibit r/w mounts of read-only filesystems
*/
@@ -382,10 +390,6 @@ xfs_finish_flags(
return XFS_ERROR(EINVAL);
}
- if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
- mp->m_flags &= ~XFS_MOUNT_COMPAT_ATTR;
- }
-
return 0;
}
@@ -504,13 +508,13 @@ xfs_mount(
if (error)
goto error2;
+ if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY))
+ xfs_mountfs_check_barriers(mp);
+
error = XFS_IOINIT(vfsp, args, flags);
if (error)
goto error2;
- if ((args->flags & XFSMNT_BARRIER) &&
- !(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY))
- xfs_mountfs_check_barriers(mp);
return 0;
error2:
@@ -655,6 +659,11 @@ xfs_mntupdate(
else
mp->m_flags &= ~XFS_MOUNT_NOATIME;
+ if (args->flags & XFSMNT_BARRIER)
+ mp->m_flags |= XFS_MOUNT_BARRIER;
+ else
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
+
if ((vfsp->vfs_flag & VFS_RDONLY) &&
!(*flags & MS_RDONLY)) {
vfsp->vfs_flag &= ~VFS_RDONLY;
@@ -1634,6 +1643,7 @@ xfs_vget(
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and
* unwritten extent conversion */
+#define MNTOPT_NOBARRIER "nobarrier" /* .. disable */
#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
#define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */
#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
@@ -1680,7 +1690,6 @@ xfs_parseargs(
int iosize;
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
- args->flags |= XFSMNT_COMPAT_ATTR;
#if 0 /* XXX: off by default, until some remaining issues ironed out */
args->flags |= XFSMNT_IDELETE; /* default to on */
@@ -1806,6 +1815,8 @@ xfs_parseargs(
args->flags |= XFSMNT_NOUUID;
} else if (!strcmp(this_char, MNTOPT_BARRIER)) {
args->flags |= XFSMNT_BARRIER;
+ } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
+ args->flags &= ~XFSMNT_BARRIER;
} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
args->flags &= ~XFSMNT_IDELETE;
} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
@@ -1815,9 +1826,9 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
} else if (!strcmp(this_char, MNTOPT_ATTR2)) {
- args->flags &= ~XFSMNT_COMPAT_ATTR;
+ args->flags |= XFSMNT_ATTR2;
} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
- args->flags |= XFSMNT_COMPAT_ATTR;
+ args->flags &= ~XFSMNT_ATTR2;
} else if (!strcmp(this_char, "osyncisdsync")) {
/* no-op, this is now the default */
printk("XFS: osyncisdsync is now the default, option is deprecated.\n");
@@ -1892,7 +1903,6 @@ xfs_showargs(
{ XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
{ XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY },
{ XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC },
- { XFS_MOUNT_BARRIER, "," MNTOPT_BARRIER },
{ XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP },
{ 0, NULL }
};
@@ -1914,33 +1924,28 @@ xfs_showargs(
if (mp->m_logbufs > 0)
seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
-
if (mp->m_logbsize > 0)
seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
if (mp->m_logname)
seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
-
if (mp->m_rtname)
seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
if (mp->m_dalign > 0)
seq_printf(m, "," MNTOPT_SUNIT "=%d",
(int)XFS_FSB_TO_BB(mp, mp->m_dalign));
-
if (mp->m_swidth > 0)
seq_printf(m, "," MNTOPT_SWIDTH "=%d",
(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
- if (!(mp->m_flags & XFS_MOUNT_COMPAT_ATTR))
- seq_printf(m, "," MNTOPT_ATTR2);
-
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO);
+ if (mp->m_flags & XFS_MOUNT_BARRIER)
+ seq_printf(m, "," MNTOPT_BARRIER);
if (!(vfsp->vfs_flag & VFS_32BITINODES))
seq_printf(m, "," MNTOPT_64BITINODE);
-
if (vfsp->vfs_flag & VFS_GRPID)
seq_printf(m, "," MNTOPT_GRPID);
@@ -1959,6 +1964,7 @@ xfs_freeze(
/* Push the superblock and write an unmount record */
xfs_log_unmount_write(mp);
xfs_unmountfs_writesb(mp);
+ xfs_fs_log_dummy(mp);
}
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index e03fa2a3d5ed..eaab355f5a89 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -15,6 +15,9 @@
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#include <linux/capability.h>
+
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_types.h"
@@ -182,8 +185,7 @@ xfs_getattr(
break;
}
- vap->va_atime.tv_sec = ip->i_d.di_atime.t_sec;
- vap->va_atime.tv_nsec = ip->i_d.di_atime.t_nsec;
+ vn_atime_to_timespec(vp, &vap->va_atime);
vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
@@ -336,7 +338,7 @@ xfs_setattr(
code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
&udqp, &gdqp);
if (code)
- return (code);
+ return code;
}
/*
@@ -541,24 +543,6 @@ xfs_setattr(
}
/*
- * Can't set extent size unless the file is marked, or
- * about to be marked as a realtime file.
- *
- * This check will be removed when fixed size extents
- * with buffered data writes is implemented.
- *
- */
- if ((mask & XFS_AT_EXTSIZE) &&
- ((ip->i_d.di_extsize << mp->m_sb.sb_blocklog) !=
- vap->va_extsize) &&
- (!((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) ||
- ((mask & XFS_AT_XFLAGS) &&
- (vap->va_xflags & XFS_XFLAG_REALTIME))))) {
- code = XFS_ERROR(EINVAL);
- goto error_return;
- }
-
- /*
* Can't change realtime flag if any extents are allocated.
*/
if ((ip->i_d.di_nextents || ip->i_delayed_blks) &&
@@ -820,13 +804,17 @@ xfs_setattr(
di_flags |= XFS_DIFLAG_RTINHERIT;
if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
di_flags |= XFS_DIFLAG_NOSYMLINKS;
- } else {
+ if (vap->va_xflags & XFS_XFLAG_EXTSZINHERIT)
+ di_flags |= XFS_DIFLAG_EXTSZINHERIT;
+ } else if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
if (vap->va_xflags & XFS_XFLAG_REALTIME) {
di_flags |= XFS_DIFLAG_REALTIME;
ip->i_iocore.io_flags |= XFS_IOCORE_RT;
} else {
ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
}
+ if (vap->va_xflags & XFS_XFLAG_EXTSIZE)
+ di_flags |= XFS_DIFLAG_EXTSIZE;
}
ip->i_d.di_flags = di_flags;
}
@@ -996,10 +984,6 @@ xfs_readlink(
goto error_return;
}
- if (!(ioflags & IO_INVIS)) {
- xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
- }
-
/*
* See if the symlink is stored inline.
*/
@@ -1043,11 +1027,8 @@ xfs_readlink(
}
-
error_return:
-
xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
return error;
}
@@ -1222,7 +1203,7 @@ xfs_inactive_free_eofblocks(
last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp));
map_len = last_fsb - end_fsb;
if (map_len <= 0)
- return (0);
+ return 0;
nimaps = 1;
xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -1231,12 +1212,13 @@ xfs_inactive_free_eofblocks(
xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (!error && (nimaps != 0) &&
- (imap.br_startblock != HOLESTARTBLOCK)) {
+ (imap.br_startblock != HOLESTARTBLOCK ||
+ ip->i_delayed_blks)) {
/*
* Attach the dquots to the inode up front.
*/
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
- return (error);
+ return error;
/*
* There are blocks after the end of file.
@@ -1264,7 +1246,7 @@ xfs_inactive_free_eofblocks(
ASSERT(XFS_FORCED_SHUTDOWN(mp));
xfs_trans_cancel(tp, 0);
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return (error);
+ return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1292,7 +1274,7 @@ xfs_inactive_free_eofblocks(
}
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
}
- return (error);
+ return error;
}
/*
@@ -1470,7 +1452,7 @@ xfs_inactive_symlink_local(
if (error) {
xfs_trans_cancel(*tpp, 0);
*tpp = NULL;
- return (error);
+ return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1483,7 +1465,7 @@ xfs_inactive_symlink_local(
XFS_DATA_FORK);
ASSERT(ip->i_df.if_bytes == 0);
}
- return (0);
+ return 0;
}
/*
@@ -1509,7 +1491,7 @@ xfs_inactive_attrs(
if (error) {
*tpp = NULL;
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return (error); /* goto out*/
+ return error; /* goto out */
}
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
@@ -1522,7 +1504,7 @@ xfs_inactive_attrs(
xfs_trans_cancel(tp, 0);
*tpp = NULL;
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return (error);
+ return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1533,7 +1515,7 @@ xfs_inactive_attrs(
ASSERT(ip->i_d.di_anextents == 0);
*tpp = tp;
- return (0);
+ return 0;
}
STATIC int
@@ -1566,11 +1548,13 @@ xfs_release(
if (ip->i_d.di_nlink != 0) {
if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
- ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
+ ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+ ip->i_delayed_blks > 0)) &&
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
- (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)))) {
+ (!(ip->i_d.di_flags &
+ (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
- return (error);
+ return error;
/* Update linux inode block count after free above */
LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
ip->i_d.di_nblocks + ip->i_delayed_blks);
@@ -1625,7 +1609,8 @@ xfs_inactive(
* only one with a reference to the inode.
*/
truncate = ((ip->i_d.di_nlink == 0) &&
- ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0)) &&
+ ((ip->i_d.di_size != 0) || (ip->i_d.di_nextents > 0) ||
+ (ip->i_delayed_blks > 0)) &&
((ip->i_d.di_mode & S_IFMT) == S_IFREG));
mp = ip->i_mount;
@@ -1643,12 +1628,14 @@ xfs_inactive(
if (ip->i_d.di_nlink != 0) {
if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
- ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0)) &&
- (ip->i_df.if_flags & XFS_IFEXTENTS)) &&
- (!(ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)) ||
- (ip->i_delayed_blks != 0))) {
+ ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
+ ip->i_delayed_blks > 0)) &&
+ (ip->i_df.if_flags & XFS_IFEXTENTS) &&
+ (!(ip->i_d.di_flags &
+ (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
+ (ip->i_delayed_blks != 0)))) {
if ((error = xfs_inactive_free_eofblocks(mp, ip)))
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
/* Update linux inode block count after free above */
LINVFS_GET_IP(vp)->i_blocks = XFS_FSB_TO_BB(mp,
ip->i_d.di_nblocks + ip->i_delayed_blks);
@@ -1659,7 +1646,7 @@ xfs_inactive(
ASSERT(ip->i_d.di_nlink == 0);
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE);
if (truncate) {
@@ -1682,7 +1669,7 @@ xfs_inactive(
ASSERT(XFS_FORCED_SHUTDOWN(mp));
xfs_trans_cancel(tp, 0);
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -1703,7 +1690,7 @@ xfs_inactive(
xfs_trans_cancel(tp,
XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
}
} else if ((ip->i_d.di_mode & S_IFMT) == S_IFLNK) {
@@ -1717,7 +1704,7 @@ xfs_inactive(
if (error) {
ASSERT(tp == NULL);
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
}
xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
@@ -1730,7 +1717,7 @@ xfs_inactive(
if (error) {
ASSERT(XFS_FORCED_SHUTDOWN(mp));
xfs_trans_cancel(tp, 0);
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
}
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
@@ -1752,7 +1739,7 @@ xfs_inactive(
* cancelled, and the inode is unlocked. Just get out.
*/
if (error)
- return (VN_INACTIVE_CACHE);
+ return VN_INACTIVE_CACHE;
} else if (ip->i_afp) {
xfs_idestroy_fork(ip, XFS_ATTR_FORK);
}
@@ -2059,8 +2046,8 @@ std_return:
abort_return:
cancel_flags |= XFS_TRANS_ABORT;
/* FALLTHROUGH */
- error_return:
+ error_return:
if (tp != NULL)
xfs_trans_cancel(tp, cancel_flags);
@@ -2590,7 +2577,6 @@ xfs_link(
int cancel_flags;
int committed;
vnode_t *target_dir_vp;
- bhv_desc_t *src_bdp;
int resblks;
char *target_name = VNAME(dentry);
int target_namelen;
@@ -2603,8 +2589,7 @@ xfs_link(
if (VN_ISDIR(src_vp))
return XFS_ERROR(EPERM);
- src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
- sip = XFS_BHVTOI(src_bdp);
+ sip = xfs_vtoi(src_vp);
tdp = XFS_BHVTOI(target_dir_bdp);
mp = tdp->i_mount;
if (XFS_FORCED_SHUTDOWN(mp))
@@ -2736,9 +2721,9 @@ std_return:
abort_return:
cancel_flags |= XFS_TRANS_ABORT;
/* FALLTHROUGH */
+
error_return:
xfs_trans_cancel(tp, cancel_flags);
-
goto std_return;
}
/*
@@ -3211,10 +3196,12 @@ std_return:
}
return error;
- error1:
+error1:
xfs_bmap_cancel(&free_list);
cancel_flags |= XFS_TRANS_ABORT;
- error_return:
+ /* FALLTHROUGH */
+
+error_return:
xfs_trans_cancel(tp, cancel_flags);
goto std_return;
}
@@ -3237,7 +3224,6 @@ xfs_readdir(
xfs_trans_t *tp = NULL;
int error = 0;
uint lock_mode;
- xfs_off_t start_offset;
vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
(inst_t *)__return_address);
@@ -3248,11 +3234,7 @@ xfs_readdir(
}
lock_mode = xfs_ilock_map_shared(dp);
- start_offset = uiop->uio_offset;
error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
- if (start_offset != uiop->uio_offset) {
- xfs_ichgtime(dp, XFS_ICHGTIME_ACC);
- }
xfs_iunlock_map_shared(dp, lock_mode);
return error;
}
@@ -3635,9 +3617,9 @@ xfs_rwlock(
if (locktype == VRWLOCK_WRITE) {
xfs_ilock(ip, XFS_IOLOCK_EXCL);
} else if (locktype == VRWLOCK_TRY_READ) {
- return (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED));
+ return xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED);
} else if (locktype == VRWLOCK_TRY_WRITE) {
- return (xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL));
+ return xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL);
} else {
ASSERT((locktype == VRWLOCK_READ) ||
(locktype == VRWLOCK_WRITE_DIRECT));
@@ -3829,7 +3811,12 @@ xfs_reclaim(
vn_iowait(vp);
ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0);
- ASSERT(VN_CACHED(vp) == 0);
+
+ /*
+ * Make sure the atime in the XFS inode is correct before freeing the
+ * Linux inode.
+ */
+ xfs_synchronize_atime(ip);
/* If we have nothing to flush with this inode then complete the
* teardown now, otherwise break the link between the xfs inode
@@ -3880,7 +3867,7 @@ xfs_finish_reclaim(
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
}
- return(1);
+ return 1;
}
ip->i_flags |= XFS_IRECLAIM;
write_unlock(&ih->ih_lock);
@@ -3999,42 +3986,36 @@ xfs_alloc_file_space(
int alloc_type,
int attr_flags)
{
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_off_t count;
xfs_filblks_t allocated_fsb;
xfs_filblks_t allocatesize_fsb;
- int committed;
- xfs_off_t count;
- xfs_filblks_t datablocks;
- int error;
+ xfs_extlen_t extsz, temp;
+ xfs_fileoff_t startoffset_fsb;
xfs_fsblock_t firstfsb;
- xfs_bmap_free_t free_list;
- xfs_bmbt_irec_t *imapp;
- xfs_bmbt_irec_t imaps[1];
- xfs_mount_t *mp;
- int numrtextents;
- int reccount;
- uint resblks;
+ int nimaps;
+ int bmapi_flag;
+ int quota_flag;
int rt;
- int rtextsize;
- xfs_fileoff_t startoffset_fsb;
xfs_trans_t *tp;
- int xfs_bmapi_flags;
+ xfs_bmbt_irec_t imaps[1], *imapp;
+ xfs_bmap_free_t free_list;
+ uint qblocks, resblks, resrtextents;
+ int committed;
+ int error;
vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
- mp = ip->i_mount;
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- /*
- * determine if this is a realtime file
- */
- if ((rt = XFS_IS_REALTIME_INODE(ip)) != 0) {
- if (ip->i_d.di_extsize)
- rtextsize = ip->i_d.di_extsize;
- else
- rtextsize = mp->m_sb.sb_rextsize;
- } else
- rtextsize = 0;
+ rt = XFS_IS_REALTIME_INODE(ip);
+ if (unlikely(rt)) {
+ if (!(extsz = ip->i_d.di_extsize))
+ extsz = mp->m_sb.sb_rextsize;
+ } else {
+ extsz = ip->i_d.di_extsize;
+ }
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return error;
@@ -4045,8 +4026,8 @@ xfs_alloc_file_space(
count = len;
error = 0;
imapp = &imaps[0];
- reccount = 1;
- xfs_bmapi_flags = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
+ nimaps = 1;
+ bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
allocatesize_fsb = XFS_B_TO_FSB(mp, count);
@@ -4063,47 +4044,55 @@ xfs_alloc_file_space(
offset, end_dmi_offset - offset,
0, NULL);
if (error)
- return(error);
+ return error;
}
/*
- * allocate file space until done or until there is an error
+ * Allocate file space until done or until there is an error
*/
retry:
while (allocatesize_fsb && !error) {
+ xfs_fileoff_t s, e;
+
/*
- * determine if reserving space on
- * the data or realtime partition.
+ * Determine space reservations for data/realtime.
*/
- if (rt) {
- xfs_fileoff_t s, e;
-
+ if (unlikely(extsz)) {
s = startoffset_fsb;
- do_div(s, rtextsize);
- s *= rtextsize;
- e = roundup_64(startoffset_fsb + allocatesize_fsb,
- rtextsize);
- numrtextents = (int)(e - s) / mp->m_sb.sb_rextsize;
- datablocks = 0;
+ do_div(s, extsz);
+ s *= extsz;
+ e = startoffset_fsb + allocatesize_fsb;
+ if ((temp = do_mod(startoffset_fsb, extsz)))
+ e += temp;
+ if ((temp = do_mod(e, extsz)))
+ e += extsz - temp;
} else {
- datablocks = allocatesize_fsb;
- numrtextents = 0;
+ s = 0;
+ e = allocatesize_fsb;
+ }
+
+ if (unlikely(rt)) {
+ resrtextents = qblocks = (uint)(e - s);
+ resrtextents /= mp->m_sb.sb_rextsize;
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+ quota_flag = XFS_QMOPT_RES_RTBLKS;
+ } else {
+ resrtextents = 0;
+ resblks = qblocks = \
+ XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
+ quota_flag = XFS_QMOPT_RES_REGBLKS;
}
/*
- * allocate and setup the transaction
+ * Allocate and setup the transaction.
*/
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,
+ error = xfs_trans_reserve(tp, resblks,
+ XFS_WRITE_LOG_RES(mp), resrtextents,
XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
-
/*
- * check for running out of space
+ * Check for running out of space
*/
if (error) {
/*
@@ -4114,8 +4103,8 @@ retry:
break;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
- error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
- ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
+ error = XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip,
+ qblocks, 0, quota_flag);
if (error)
goto error1;
@@ -4123,19 +4112,19 @@ retry:
xfs_trans_ihold(tp, ip);
/*
- * issue the bmapi() call to allocate the blocks
+ * Issue the xfs_bmapi() call to allocate the blocks
*/
XFS_BMAP_INIT(&free_list, &firstfsb);
error = xfs_bmapi(tp, ip, startoffset_fsb,
- allocatesize_fsb, xfs_bmapi_flags,
- &firstfsb, 0, imapp, &reccount,
+ allocatesize_fsb, bmapi_flag,
+ &firstfsb, 0, imapp, &nimaps,
&free_list);
if (error) {
goto error0;
}
/*
- * complete the transaction
+ * Complete the transaction
*/
error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
if (error) {
@@ -4150,7 +4139,7 @@ retry:
allocated_fsb = imapp->br_blockcount;
- if (reccount == 0) {
+ if (nimaps == 0) {
error = XFS_ERROR(ENOSPC);
break;
}
@@ -4173,9 +4162,11 @@ dmapi_enospc_check:
return error;
- error0:
+error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
xfs_bmap_cancel(&free_list);
- error1:
+ XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
+
+error1: /* Just cancel transaction */
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
goto dmapi_enospc_check;
@@ -4313,7 +4304,7 @@ xfs_free_file_space(
offset, end_dmi_offset - offset,
AT_DELAY_FLAG(attr_flags), NULL);
if (error)
- return(error);
+ return error;
}
ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
@@ -4420,8 +4411,8 @@ xfs_free_file_space(
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
- ip->i_udquot, ip->i_gdquot, resblks, 0, rt ?
- XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+ ip->i_udquot, ip->i_gdquot, resblks, 0,
+ XFS_QMOPT_RES_REGBLKS);
if (error)
goto error1;
diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h
index 6183eab006d4..fc77f7413083 100644
--- a/include/asm-alpha/atomic.h
+++ b/include/asm-alpha/atomic.h
@@ -176,6 +176,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
}
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -216,4 +217,5 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
+#include <asm-generic/atomic.h>
#endif /* _ALPHA_ATOMIC_H */
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 578ed3f1a607..302201f1a097 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -321,6 +321,7 @@ static inline int fls(int word)
#else
#define fls generic_fls
#endif
+#define fls64 generic_fls64
/* Compute powers of two for the given integer. */
static inline long floor_log2(unsigned long word)
diff --git a/include/asm-alpha/cache.h b/include/asm-alpha/cache.h
index e69b29501a5f..e6d4d1695e25 100644
--- a/include/asm-alpha/cache.h
+++ b/include/asm-alpha/cache.h
@@ -20,6 +20,5 @@
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
#endif
diff --git a/include/asm-alpha/compiler.h b/include/asm-alpha/compiler.h
index 0a4a8b40dfcd..00c6f57ad9a7 100644
--- a/include/asm-alpha/compiler.h
+++ b/include/asm-alpha/compiler.h
@@ -98,9 +98,7 @@
#undef inline
#undef __inline__
#undef __inline
-#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3
#undef __always_inline
#define __always_inline inline __attribute__((always_inline))
-#endif
#endif /* __ALPHA_COMPILER_H */
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index 680f7ecbb28f..9dc7256cf979 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -16,7 +16,7 @@
#define dma_free_coherent(dev, size, va, addr) \
pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
#define dma_map_page(dev, page, off, size, dir) \
- pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir)
+ pci_map_page(alpha_gendev_to_pci(dev), page, off, size, dir)
#define dma_unmap_page(dev, addr, size, dir) \
pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
#define dma_map_sg(dev, sg, nents, dir) \
diff --git a/include/asm-alpha/futex.h b/include/asm-alpha/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-alpha/futex.h
+++ b/include/asm-alpha/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-alpha/hardirq.h b/include/asm-alpha/hardirq.h
index c0593f9b21e1..7bb6a36c96a1 100644
--- a/include/asm-alpha/hardirq.h
+++ b/include/asm-alpha/hardirq.h
@@ -13,6 +13,8 @@ typedef struct {
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+void ack_bad_irq(unsigned int irq);
+
#define HARDIRQ_BITS 12
/*
diff --git a/include/asm-alpha/mman.h b/include/asm-alpha/mman.h
index eb9c279045ef..f6439532a262 100644
--- a/include/asm-alpha/mman.h
+++ b/include/asm-alpha/mman.h
@@ -42,6 +42,7 @@
#define MADV_WILLNEED 3 /* will need these pages */
#define MADV_SPACEAVAIL 5 /* ensure resources are available */
#define MADV_DONTNEED 6 /* don't need these pages */
+#define MADV_REMOVE 7 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
index a714d0cdc204..6f92482cc96c 100644
--- a/include/asm-alpha/mmu_context.h
+++ b/include/asm-alpha/mmu_context.h
@@ -156,7 +156,7 @@ ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
/* Always update the PCB ASN. Another thread may have allocated
a new mm->context (via flush_tlb_mm) without the ASN serial
number wrapping. We have no way to detect when this is needed. */
- next->thread_info->pcb.asn = mmc & HARDWARE_ASN_MASK;
+ task_thread_info(next)->pcb.asn = mmc & HARDWARE_ASN_MASK;
}
__EXTERN_INLINE void
@@ -235,7 +235,7 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
if (cpu_online(i))
mm->context[i] = 0;
if (tsk != current)
- tsk->thread_info->pcb.ptbr
+ task_thread_info(tsk)->pcb.ptbr
= ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
return 0;
}
@@ -249,7 +249,7 @@ destroy_context(struct mm_struct *mm)
static inline void
enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
- tsk->thread_info->pcb.ptbr
+ task_thread_info(tsk)->pcb.ptbr
= ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
}
diff --git a/include/asm-alpha/mutex.h b/include/asm-alpha/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-alpha/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
index 059780a7d3d7..425b7b6d28cb 100644
--- a/include/asm-alpha/processor.h
+++ b/include/asm-alpha/processor.h
@@ -52,19 +52,10 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
unsigned long get_wchan(struct task_struct *p);
-/* See arch/alpha/kernel/ptrace.c for details. */
-#define PT_REG(reg) \
- (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg))
-
-#define SW_REG(reg) \
- (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
- + offsetof(struct switch_stack, reg))
-
-#define KSTK_EIP(tsk) \
- (*(unsigned long *)(PT_REG(pc) + (unsigned long) ((tsk)->thread_info)))
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
#define KSTK_ESP(tsk) \
- ((tsk) == current ? rdusp() : (tsk)->thread_info->pcb.usp)
+ ((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp)
#define cpu_relax() barrier()
@@ -77,7 +68,6 @@ unsigned long get_wchan(struct task_struct *p);
#define spin_lock_prefetch(lock) do { } while (0)
#endif
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
extern inline void prefetch(const void *ptr)
{
__builtin_prefetch(ptr, 0, 3);
@@ -95,24 +85,4 @@ extern inline void spin_lock_prefetch(const void *ptr)
}
#endif
-#else
-extern inline void prefetch(const void *ptr)
-{
- __asm__ ("ldl $31,%0" : : "m"(*(char *)ptr));
-}
-
-extern inline void prefetchw(const void *ptr)
-{
- __asm__ ("ldq $31,%0" : : "m"(*(char *)ptr));
-}
-
-#ifdef CONFIG_SMP
-extern inline void spin_lock_prefetch(const void *ptr)
-{
- __asm__ ("ldq $31,%0" : : "m"(*(char *)ptr));
-}
-#endif
-
-#endif /* GCC 3.1 */
-
#endif /* __ASM_ALPHA_PROCESSOR_H */
diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h
index 072375c135b4..9933b8b3612e 100644
--- a/include/asm-alpha/ptrace.h
+++ b/include/asm-alpha/ptrace.h
@@ -75,10 +75,10 @@ struct switch_stack {
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs *);
-#define alpha_task_regs(task) \
- ((struct pt_regs *) ((long) (task)->thread_info + 2*PAGE_SIZE) - 1)
+#define task_pt_regs(task) \
+ ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1)
-#define force_successful_syscall_return() (alpha_task_regs(current)->r0 = 0)
+#define force_successful_syscall_return() (task_pt_regs(current)->r0 = 0)
#endif
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index 050e86d12891..cc9c7e8cced5 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -131,15 +131,25 @@ struct el_common_EV6_mcheck {
extern void halt(void) __attribute__((noreturn));
#define __halt() __asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
-#define switch_to(P,N,L) \
- do { \
- (L) = alpha_switch_to(virt_to_phys(&(N)->thread_info->pcb), (P)); \
- check_mmu_context(); \
+#define switch_to(P,N,L) \
+ do { \
+ (L) = alpha_switch_to(virt_to_phys(&task_thread_info(N)->pcb), (P)); \
+ check_mmu_context(); \
} while (0)
struct task_struct;
extern struct task_struct *alpha_switch_to(unsigned long, struct task_struct*);
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
#define imb() \
__asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
index d51491ed00b8..69ffd93f8e22 100644
--- a/include/asm-alpha/thread_info.h
+++ b/include/asm-alpha/thread_info.h
@@ -54,8 +54,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
#define alloc_thread_info(tsk) \
((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h
index 28c890b4a1d3..e100b1e526fe 100644
--- a/include/asm-arm/arch-aaec2000/dma.h
+++ b/include/asm-arm/arch-aaec2000/dma.h
@@ -7,11 +7,3 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200.h b/include/asm-arm/arch-at91rm9200/at91rm9200.h
new file mode 100644
index 000000000000..58f40931a5c1
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200.h
@@ -0,0 +1,261 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Common definitions.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_H
+#define AT91RM9200_H
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
+#define AT91_ID_SYS 1 /* System Peripheral */
+#define AT91_ID_PIOA 2 /* Parallel IO Controller A */
+#define AT91_ID_PIOB 3 /* Parallel IO Controller B */
+#define AT91_ID_PIOC 4 /* Parallel IO Controller C */
+#define AT91_ID_PIOD 5 /* Parallel IO Controller D */
+#define AT91_ID_US0 6 /* USART 0 */
+#define AT91_ID_US1 7 /* USART 1 */
+#define AT91_ID_US2 8 /* USART 2 */
+#define AT91_ID_US3 9 /* USART 3 */
+#define AT91_ID_MCI 10 /* Multimedia Card Interface */
+#define AT91_ID_UDP 11 /* USB Device Port */
+#define AT91_ID_TWI 12 /* Two-Wire Interface */
+#define AT91_ID_SPI 13 /* Serial Peripheral Interface */
+#define AT91_ID_SSC0 14 /* Serial Synchronous Controller 0 */
+#define AT91_ID_SSC1 15 /* Serial Synchronous Controller 1 */
+#define AT91_ID_SSC2 16 /* Serial Synchronous Controller 2 */
+#define AT91_ID_TC0 17 /* Timer Counter 0 */
+#define AT91_ID_TC1 18 /* Timer Counter 1 */
+#define AT91_ID_TC2 19 /* Timer Counter 2 */
+#define AT91_ID_TC3 20 /* Timer Counter 3 */
+#define AT91_ID_TC4 21 /* Timer Counter 4 */
+#define AT91_ID_TC5 22 /* Timer Counter 5 */
+#define AT91_ID_UHP 23 /* USB Host port */
+#define AT91_ID_EMAC 24 /* Ethernet MAC */
+#define AT91_ID_IRQ0 25 /* Advanced Interrupt Controller (IRQ0) */
+#define AT91_ID_IRQ1 26 /* Advanced Interrupt Controller (IRQ1) */
+#define AT91_ID_IRQ2 27 /* Advanced Interrupt Controller (IRQ2) */
+#define AT91_ID_IRQ3 28 /* Advanced Interrupt Controller (IRQ3) */
+#define AT91_ID_IRQ4 29 /* Advanced Interrupt Controller (IRQ4) */
+#define AT91_ID_IRQ5 30 /* Advanced Interrupt Controller (IRQ5) */
+#define AT91_ID_IRQ6 31 /* Advanced Interrupt Controller (IRQ6) */
+
+
+/*
+ * Peripheral physical base addresses.
+ */
+#define AT91_BASE_TCB0 0xfffa0000
+#define AT91_BASE_TC0 0xfffa0000
+#define AT91_BASE_TC1 0xfffa0040
+#define AT91_BASE_TC2 0xfffa0080
+#define AT91_BASE_TCB1 0xfffa4000
+#define AT91_BASE_TC3 0xfffa4000
+#define AT91_BASE_TC4 0xfffa4040
+#define AT91_BASE_TC5 0xfffa4080
+#define AT91_BASE_UDP 0xfffb0000
+#define AT91_BASE_MCI 0xfffb4000
+#define AT91_BASE_TWI 0xfffb8000
+#define AT91_BASE_EMAC 0xfffbc000
+#define AT91_BASE_US0 0xfffc0000
+#define AT91_BASE_US1 0xfffc4000
+#define AT91_BASE_US2 0xfffc8000
+#define AT91_BASE_US3 0xfffcc000
+#define AT91_BASE_SSC0 0xfffd0000
+#define AT91_BASE_SSC1 0xfffd4000
+#define AT91_BASE_SSC2 0xfffd8000
+#define AT91_BASE_SPI 0xfffe0000
+#define AT91_BASE_SYS 0xfffff000
+
+
+/*
+ * PIO pin definitions (peripheral A/B multiplexing).
+ */
+#define AT91_PA0_MISO (1 << 0) /* A: SPI Master-In Slave-Out */
+#define AT91_PA0_PCK3 (1 << 0) /* B: PMC Programmable Clock Output 3 */
+#define AT91_PA1_MOSI (1 << 1) /* A: SPI Master-Out Slave-In */
+#define AT91_PA1_PCK0 (1 << 1) /* B: PMC Programmable Clock Output 0 */
+#define AT91_PA2_SPCK (1 << 2) /* A: SPI Serial Clock */
+#define AT91_PA2_IRQ4 (1 << 2) /* B: External Interrupt 4 */
+#define AT91_PA3_NPCS0 (1 << 3) /* A: SPI Peripheral Chip Select 0 */
+#define AT91_PA3_IRQ5 (1 << 3) /* B: External Interrupt 5 */
+#define AT91_PA4_NPCS1 (1 << 4) /* A: SPI Peripheral Chip Select 1 */
+#define AT91_PA4_PCK1 (1 << 4) /* B: PMC Programmable Clock Output 1 */
+#define AT91_PA5_NPCS2 (1 << 5) /* A: SPI Peripheral Chip Select 2 */
+#define AT91_PA5_TXD3 (1 << 5) /* B: USART Transmit Data 3 */
+#define AT91_PA6_NPCS3 (1 << 6) /* A: SPI Peripheral Chip Select 3 */
+#define AT91_PA6_RXD3 (1 << 6) /* B: USART Receive Data 3 */
+#define AT91_PA7_ETXCK_EREFCK (1 << 7) /* A: Ethernet Reference Clock / Transmit Clock */
+#define AT91_PA7_PCK2 (1 << 7) /* B: PMC Programmable Clock Output 2 */
+#define AT91_PA8_ETXEN (1 << 8) /* A: Ethernet Transmit Enable */
+#define AT91_PA8_MCCDB (1 << 8) /* B: MMC Multimedia Card B Command */
+#define AT91_PA9_ETX0 (1 << 9) /* A: Ethernet Transmit Data 0 */
+#define AT91_PA9_MCDB0 (1 << 9) /* B: MMC Multimedia Card B Data 0 */
+#define AT91_PA10_ETX1 (1 << 10) /* A: Ethernet Transmit Data 1 */
+#define AT91_PA10_MCDB1 (1 << 10) /* B: MMC Multimedia Card B Data 1 */
+#define AT91_PA11_ECRS_ECRSDV (1 << 11) /* A: Ethernet Carrier Sense / Data Valid */
+#define AT91_PA11_MCDB2 (1 << 11) /* B: MMC Multimedia Card B Data 2 */
+#define AT91_PA12_ERX0 (1 << 12) /* A: Ethernet Receive Data 0 */
+#define AT91_PA12_MCDB3 (1 << 12) /* B: MMC Multimedia Card B Data 3 */
+#define AT91_PA13_ERX1 (1 << 13) /* A: Ethernet Receive Data 1 */
+#define AT91_PA13_TCLK0 (1 << 13) /* B: TC External Clock Input 0 */
+#define AT91_PA14_ERXER (1 << 14) /* A: Ethernet Receive Error */
+#define AT91_PA14_TCLK1 (1 << 14) /* B: TC External Clock Input 1 */
+#define AT91_PA15_EMDC (1 << 15) /* A: Ethernet Management Data Clock */
+#define AT91_PA15_TCLK2 (1 << 15) /* B: TC External Clock Input 2 */
+#define AT91_PA16_EMDIO (1 << 16) /* A: Ethernet Management Data I/O */
+#define AT91_PA16_IRQ6 (1 << 16) /* B: External Interrupt 6 */
+#define AT91_PA17_TXD0 (1 << 17) /* A: USART Transmit Data 0 */
+#define AT91_PA17_TIOA0 (1 << 17) /* B: TC I/O Line A 0 */
+#define AT91_PA18_RXD0 (1 << 18) /* A: USART Receive Data 0 */
+#define AT91_PA18_TIOB0 (1 << 18) /* B: TC I/O Line B 0 */
+#define AT91_PA19_SCK0 (1 << 19) /* A: USART Serial Clock 0 */
+#define AT91_PA19_TIOA1 (1 << 19) /* B: TC I/O Line A 1 */
+#define AT91_PA20_CTS0 (1 << 20) /* A: USART Clear To Send 0 */
+#define AT91_PA20_TIOB1 (1 << 20) /* B: TC I/O Line B 1 */
+#define AT91_PA21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */
+#define AT91_PA21_TIOA2 (1 << 21) /* B: TC I/O Line A 2 */
+#define AT91_PA22_RXD2 (1 << 22) /* A: USART Receive Data 2 */
+#define AT91_PA22_TIOB2 (1 << 22) /* B: TC I/O Line B 2 */
+#define AT91_PA23_TXD2 (1 << 23) /* A: USART Transmit Data 2 */
+#define AT91_PA23_IRQ3 (1 << 23) /* B: External Interrupt 3 */
+#define AT91_PA24_SCK2 (1 << 24) /* A: USART Serial Clock 2 */
+#define AT91_PA24_PCK1 (1 << 24) /* B: PMC Programmable Clock Output 1 */
+#define AT91_PA25_TWD (1 << 25) /* A: TWI Two-wire Serial Data */
+#define AT91_PA25_IRQ2 (1 << 25) /* B: External Interrupt 2 */
+#define AT91_PA26_TWCK (1 << 26) /* A: TWI Two-wire Serial Clock */
+#define AT91_PA26_IRQ1 (1 << 26) /* B: External Interrupt 1 */
+#define AT91_PA27_MCCK (1 << 27) /* A: MMC Multimedia Card Clock */
+#define AT91_PA27_TCLK3 (1 << 27) /* B: TC External Clock Input 3 */
+#define AT91_PA28_MCCDA (1 << 28) /* A: MMC Multimedia Card A Command */
+#define AT91_PA28_TCLK4 (1 << 28) /* B: TC External Clock Input 4 */
+#define AT91_PA29_MCDA0 (1 << 29) /* A: MMC Multimedia Card A Data 0 */
+#define AT91_PA29_TCLK5 (1 << 29) /* B: TC External Clock Input 5 */
+#define AT91_PA30_DRXD (1 << 30) /* A: DBGU Receive Data */
+#define AT91_PA30_CTS2 (1 << 30) /* B: USART Clear To Send 2 */
+#define AT91_PA31_DTXD (1 << 31) /* A: DBGU Transmit Data */
+#define AT91_PA31_RTS2 (1 << 31) /* B: USART Ready To Send 2 */
+
+#define AT91_PB0_TF0 (1 << 0) /* A: SSC Transmit Frame Sync 0 */
+#define AT91_PB0_RTS3 (1 << 0) /* B: USART Ready To Send 3 */
+#define AT91_PB1_TK0 (1 << 1) /* A: SSC Transmit Clock 0 */
+#define AT91_PB1_CTS3 (1 << 1) /* B: USART Clear To Send 3 */
+#define AT91_PB2_TD0 (1 << 2) /* A: SSC Transmit Data 0 */
+#define AT91_PB2_SCK3 (1 << 2) /* B: USART Serial Clock 3 */
+#define AT91_PB3_RD0 (1 << 3) /* A: SSC Receive Data 0 */
+#define AT91_PB3_MCDA1 (1 << 3) /* B: MMC Multimedia Card A Data 1 */
+#define AT91_PB4_RK0 (1 << 4) /* A: SSC Receive Clock 0 */
+#define AT91_PB4_MCDA2 (1 << 4) /* B: MMC Multimedia Card A Data 2 */
+#define AT91_PB5_RF0 (1 << 5) /* A: SSC Receive Frame Sync 0 */
+#define AT91_PB5_MCDA3 (1 << 5) /* B: MMC Multimedia Card A Data 3 */
+#define AT91_PB6_TF1 (1 << 6) /* A: SSC Transmit Frame Sync 1 */
+#define AT91_PB6_TIOA3 (1 << 6) /* B: TC I/O Line A 3 */
+#define AT91_PB7_TK1 (1 << 7) /* A: SSC Transmit Clock 1 */
+#define AT91_PB7_TIOB3 (1 << 7) /* B: TC I/O Line B 3 */
+#define AT91_PB8_TD1 (1 << 8) /* A: SSC Transmit Data 1 */
+#define AT91_PB8_TIOA4 (1 << 8) /* B: TC I/O Line A 4 */
+#define AT91_PB9_RD1 (1 << 9) /* A: SSC Receive Data 1 */
+#define AT91_PB9_TIOB4 (1 << 9) /* B: TC I/O Line B 4 */
+#define AT91_PB10_RK1 (1 << 10) /* A: SSC Receive Clock 1 */
+#define AT91_PB10_TIOA5 (1 << 10) /* B: TC I/O Line A 5 */
+#define AT91_PB11_RF1 (1 << 11) /* A: SSC Receive Frame Sync 1 */
+#define AT91_PB11_TIOB5 (1 << 11) /* B: TC I/O Line B 5 */
+#define AT91_PB12_TF2 (1 << 12) /* A: SSC Transmit Frame Sync 2 */
+#define AT91_PB12_ETX2 (1 << 12) /* B: Ethernet Transmit Data 2 */
+#define AT91_PB13_TK2 (1 << 13) /* A: SSC Transmit Clock 3 */
+#define AT91_PB13_ETX3 (1 << 13) /* B: Ethernet Transmit Data 3 */
+#define AT91_PB14_TD2 (1 << 14) /* A: SSC Transmit Data 2 */
+#define AT91_PB14_ETXER (1 << 14) /* B: Ethernet Transmit Coding Error */
+#define AT91_PB15_RD2 (1 << 15) /* A: SSC Receive Data 2 */
+#define AT91_PB15_ERX2 (1 << 15) /* B: Ethernet Receive Data 2 */
+#define AT91_PB16_RK2 (1 << 16) /* A: SSC Receive Clock 2 */
+#define AT91_PB16_ERX3 (1 << 16) /* B: Ethernet Receive Data 3 */
+#define AT91_PB17_RF2 (1 << 17) /* A: SSC Receive Frame Sync 2 */
+#define AT91_PB17_ERXDV (1 << 17) /* B: Ethernet Receive Data Valid */
+#define AT91_PB18_RI1 (1 << 18) /* A: USART Ring Indicator 1 */
+#define AT91_PB18_ECOL (1 << 18) /* B: Ethernet Collision Detected */
+#define AT91_PB19_DTR1 (1 << 19) /* A: USART Data Terminal Ready 1 */
+#define AT91_PB19_ERXCK (1 << 19) /* B: Ethernet Receive Clock */
+#define AT91_PB20_TXD1 (1 << 20) /* A: USART Transmit Data 1 */
+#define AT91_PB21_RXD1 (1 << 21) /* A: USART Receive Data 1 */
+#define AT91_PB22_SCK1 (1 << 22) /* A: USART Serial Clock 1 */
+#define AT91_PB23_DCD1 (1 << 23) /* A: USART Data Carrier Detect 1 */
+#define AT91_PB24_CTS1 (1 << 24) /* A: USART Clear To Send 1 */
+#define AT91_PB25_DSR1 (1 << 25) /* A: USART Data Set Ready 1 */
+#define AT91_PB25_EF100 (1 << 25) /* B: Ethernet Force 100 Mbit */
+#define AT91_PB26_RTS1 (1 << 26) /* A: USART Ready To Send 1 */
+#define AT91_PB27_PCK0 (1 << 27) /* B: PMC Programmable Clock Output 0 */
+#define AT91_PB28_FIQ (1 << 28) /* A: Fast Interrupt */
+#define AT91_PB29_IRQ0 (1 << 29) /* A: External Interrupt 0 */
+
+#define AT91_PC0_BFCK (1 << 0) /* A: Burst Flash Clock */
+#define AT91_PC1_BFRDY_SMOE (1 << 1) /* A: Burst Flash Ready / SmartMedia Output Enable */
+#define AT91_PC2_BFAVD (1 << 2) /* A: Burst Flash Address Valid */
+#define AT91_PC3_BFBAA_SMWE (1 << 3) /* A: Burst Flash Address Advance / SmartMedia Write Enable */
+#define AT91_PC4_BFOE (1 << 4) /* A: Burst Flash Output Enable */
+#define AT91_PC5_BFWE (1 << 5) /* A: Burst Flash Write Enable */
+#define AT91_PC6_NWAIT (1 << 6) /* A: SMC Wait Signal */
+#define AT91_PC7_A23 (1 << 7) /* A: Address Bus 23 */
+#define AT91_PC8_A24 (1 << 8) /* A: Address Bus 24 */
+#define AT91_PC9_A25_CFRNW (1 << 9) /* A: Address Bus 25 / Compact Flash Read Not Write */
+#define AT91_PC10_NCS4_CFCS (1 << 10) /* A: SMC Chip Select 4 / Compact Flash Chip Select */
+#define AT91_PC11_NCS5_CFCE1 (1 << 11) /* A: SMC Chip Select 5 / Compact Flash Chip Enable 1 */
+#define AT91_PC12_NCS6_CFCE2 (1 << 12) /* A: SMC Chip Select 6 / Compact Flash Chip Enable 2 */
+#define AT91_PC13_NCS7 (1 << 13) /* A: Chip Select 7 */
+
+#define AT91_PD0_ETX0 (1 << 0) /* A: Ethernet Transmit Data 0 */
+#define AT91_PD1_ETX1 (1 << 1) /* A: Ethernet Transmit Data 1 */
+#define AT91_PD2_ETX2 (1 << 2) /* A: Ethernet Transmit Data 2 */
+#define AT91_PD3_ETX3 (1 << 3) /* A: Ethernet Transmit Data 3 */
+#define AT91_PD4_ETXEN (1 << 4) /* A: Ethernet Transmit Enable */
+#define AT91_PD5_ETXER (1 << 5) /* A: Ethernet Transmit Coding Error */
+#define AT91_PD6_DTXD (1 << 6) /* A: DBGU Transmit Data */
+#define AT91_PD7_PCK0 (1 << 7) /* A: PMC Programmable Clock Output 0 */
+#define AT91_PD7_TSYNC (1 << 7) /* B: ETM Trace Synchronization Signal */
+#define AT91_PD8_PCK1 (1 << 8) /* A: PMC Programmable Clock Output 1 */
+#define AT91_PD8_TCLK (1 << 8) /* B: ETM Trace Clock */
+#define AT91_PD9_PCK2 (1 << 9) /* A: PMC Programmable Clock Output 2 */
+#define AT91_PD9_TPS0 (1 << 9) /* B: ETM Trace ARM Pipeline Status 0 */
+#define AT91_PD10_PCK3 (1 << 10) /* A: PMC Programmable Clock Output 3 */
+#define AT91_PD10_TPS1 (1 << 10) /* B: ETM Trace ARM Pipeline Status 1 */
+#define AT91_PD11_TPS2 (1 << 11) /* B: ETM Trace ARM Pipeline Status 2 */
+#define AT91_PD12_TPK0 (1 << 12) /* B: ETM Trace Packet Port 0 */
+#define AT91_PD13_TPK1 (1 << 13) /* B: ETM Trace Packet Port 1 */
+#define AT91_PD14_TPK2 (1 << 14) /* B: ETM Trace Packet Port 2 */
+#define AT91_PD15_TD0 (1 << 15) /* A: SSC Transmit Data 0 */
+#define AT91_PD15_TPK3 (1 << 15) /* B: ETM Trace Packet Port 3 */
+#define AT91_PD16_TD1 (1 << 16) /* A: SSC Transmit Data 1 */
+#define AT91_PD16_TPK4 (1 << 16) /* B: ETM Trace Packet Port 4 */
+#define AT91_PD17_TD2 (1 << 17) /* A: SSC Transmit Data 2 */
+#define AT91_PD17_TPK5 (1 << 17) /* B: ETM Trace Packet Port 5 */
+#define AT91_PD18_NPCS1 (1 << 18) /* A: SPI Peripheral Chip Select 1 */
+#define AT91_PD18_TPK6 (1 << 18) /* B: ETM Trace Packet Port 6 */
+#define AT91_PD19_NPCS2 (1 << 19) /* A: SPI Peripheral Chip Select 2 */
+#define AT91_PD19_TPK7 (1 << 19) /* B: ETM Trace Packet Port 7 */
+#define AT91_PD20_NPCS3 (1 << 20) /* A: SPI Peripheral Chip Select 3 */
+#define AT91_PD20_TPK8 (1 << 20) /* B: ETM Trace Packet Port 8 */
+#define AT91_PD21_RTS0 (1 << 21) /* A: USART Ready To Send 0 */
+#define AT91_PD21_TPK9 (1 << 21) /* B: ETM Trace Packet Port 9 */
+#define AT91_PD22_RTS1 (1 << 22) /* A: USART Ready To Send 1 */
+#define AT91_PD22_TPK10 (1 << 22) /* B: ETM Trace Packet Port 10 */
+#define AT91_PD23_RTS2 (1 << 23) /* A: USART Ready To Send 2 */
+#define AT91_PD23_TPK11 (1 << 23) /* B: ETM Trace Packet Port 11 */
+#define AT91_PD24_RTS3 (1 << 24) /* A: USART Ready To Send 3 */
+#define AT91_PD24_TPK12 (1 << 24) /* B: ETM Trace Packet Port 12 */
+#define AT91_PD25_DTR1 (1 << 25) /* A: USART Data Terminal Ready 1 */
+#define AT91_PD25_TPK13 (1 << 25) /* B: ETM Trace Packet Port 13 */
+#define AT91_PD26_TPK14 (1 << 26) /* B: ETM Trace Packet Port 14 */
+#define AT91_PD27_TPK15 (1 << 27) /* B: ETM Trace Packet Port 15 */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
new file mode 100644
index 000000000000..ce1150d4438d
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
@@ -0,0 +1,36 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_pdc.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Peripheral Data Controller (PDC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_PDC_H
+#define AT91RM9200_PDC_H
+
+#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */
+#define AT91_PDC_RCR 0x104 /* Receive Counter Register */
+#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */
+#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */
+#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */
+#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */
+#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */
+#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */
+
+#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */
+#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */
+#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */
+#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */
+#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */
+
+#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
new file mode 100644
index 000000000000..9bfffdbf1e0b
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
@@ -0,0 +1,328 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * System peripherals registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_SYS_H
+#define AT91RM9200_SYS_H
+
+/*
+ * Advanced Interrupt Controller.
+ */
+#define AT91_AIC 0x000
+
+#define AT91_AIC_SMR(n) (AT91_AIC + ((n) * 4)) /* Source Mode Registers 0-31 */
+#define AT91_AIC_PRIOR (7 << 0) /* Priority Level */
+#define AT91_AIC_SRCTYPE (3 << 5) /* Interrupt Source Type */
+#define AT91_AIC_SRCTYPE_LOW (0 << 5)
+#define AT91_AIC_SRCTYPE_FALLING (1 << 5)
+#define AT91_AIC_SRCTYPE_HIGH (2 << 5)
+#define AT91_AIC_SRCTYPE_RISING (3 << 5)
+
+#define AT91_AIC_SVR(n) (AT91_AIC + 0x80 + ((n) * 4)) /* Source Vector Registers 0-31 */
+#define AT91_AIC_IVR (AT91_AIC + 0x100) /* Interrupt Vector Register */
+#define AT91_AIC_FVR (AT91_AIC + 0x104) /* Fast Interrupt Vector Register */
+#define AT91_AIC_ISR (AT91_AIC + 0x108) /* Interrupt Status Register */
+#define AT91_AIC_IRQID (0x1f << 0) /* Current Interrupt Identifier */
+
+#define AT91_AIC_IPR (AT91_AIC + 0x10c) /* Interrupt Pending Register */
+#define AT91_AIC_IMR (AT91_AIC + 0x110) /* Interrupt Mask Register */
+#define AT91_AIC_CISR (AT91_AIC + 0x114) /* Core Interrupt Status Register */
+#define AT91_AIC_NFIQ (1 << 0) /* nFIQ Status */
+#define AT91_AIC_NIRQ (1 << 1) /* nIRQ Status */
+
+#define AT91_AIC_IECR (AT91_AIC + 0x120) /* Interrupt Enable Command Register */
+#define AT91_AIC_IDCR (AT91_AIC + 0x124) /* Interrupt Disable Command Register */
+#define AT91_AIC_ICCR (AT91_AIC + 0x128) /* Interrupt Clear Command Register */
+#define AT91_AIC_ISCR (AT91_AIC + 0x12c) /* Interrupt Set Command Register */
+#define AT91_AIC_EOICR (AT91_AIC + 0x130) /* End of Interrupt Command Register */
+#define AT91_AIC_SPU (AT91_AIC + 0x134) /* Spurious Interrupt Vector Register */
+#define AT91_AIC_DCR (AT91_AIC + 0x138) /* Debug Control Register */
+#define AT91_AIC_DCR_PROT (1 << 0) /* Protection Mode */
+#define AT91_AIC_DCR_GMSK (1 << 1) /* General Mask */
+
+
+/*
+ * Debug Unit.
+ */
+#define AT91_DBGU 0x200
+
+#define AT91_DBGU_CR (AT91_DBGU + 0x00) /* Control Register */
+#define AT91_DBGU_MR (AT91_DBGU + 0x04) /* Mode Register */
+#define AT91_DBGU_IER (AT91_DBGU + 0x08) /* Interrupt Enable Register */
+#define AT91_DBGU_TXRDY (1 << 1) /* Transmitter Ready */
+#define AT91_DBGU_TXEMPTY (1 << 9) /* Transmitter Empty */
+#define AT91_DBGU_IDR (AT91_DBGU + 0x0c) /* Interrupt Disable Register */
+#define AT91_DBGU_IMR (AT91_DBGU + 0x10) /* Interrupt Mask Register */
+#define AT91_DBGU_SR (AT91_DBGU + 0x14) /* Status Register */
+#define AT91_DBGU_RHR (AT91_DBGU + 0x18) /* Receiver Holding Register */
+#define AT91_DBGU_THR (AT91_DBGU + 0x1c) /* Transmitter Holding Register */
+#define AT91_DBGU_BRGR (AT91_DBGU + 0x20) /* Baud Rate Generator Register */
+#define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */
+#define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */
+
+
+/*
+ * PIO Controllers.
+ */
+#define AT91_PIOA 0x400
+#define AT91_PIOB 0x600
+#define AT91_PIOC 0x800
+#define AT91_PIOD 0xa00
+
+#define PIO_PER 0x00 /* Enable Register */
+#define PIO_PDR 0x04 /* Disable Register */
+#define PIO_PSR 0x08 /* Status Register */
+#define PIO_OER 0x10 /* Output Enable Register */
+#define PIO_ODR 0x14 /* Output Disable Register */
+#define PIO_OSR 0x18 /* Output Status Register */
+#define PIO_IFER 0x20 /* Glitch Input Filter Enable */
+#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */
+#define PIO_IFSR 0x28 /* Glitch Input Filter Status */
+#define PIO_SODR 0x30 /* Set Output Data Register */
+#define PIO_CODR 0x34 /* Clear Output Data Register */
+#define PIO_ODSR 0x38 /* Output Data Status Register */
+#define PIO_PDSR 0x3c /* Pin Data Status Register */
+#define PIO_IER 0x40 /* Interrupt Enable Register */
+#define PIO_IDR 0x44 /* Interrupt Disable Register */
+#define PIO_IMR 0x48 /* Interrupt Mask Register */
+#define PIO_ISR 0x4c /* Interrupt Status Register */
+#define PIO_MDER 0x50 /* Multi-driver Enable Register */
+#define PIO_MDDR 0x54 /* Multi-driver Disable Register */
+#define PIO_MDSR 0x58 /* Multi-driver Status Register */
+#define PIO_PUDR 0x60 /* Pull-up Disable Register */
+#define PIO_PUER 0x64 /* Pull-up Enable Register */
+#define PIO_PUSR 0x68 /* Pull-up Status Register */
+#define PIO_ASR 0x70 /* Peripheral A Select Register */
+#define PIO_BSR 0x74 /* Peripheral B Select Register */
+#define PIO_ABSR 0x78 /* AB Status Register */
+#define PIO_OWER 0xa0 /* Output Write Enable Register */
+#define PIO_OWDR 0xa4 /* Output Write Disable Register */
+#define PIO_OWSR 0xa8 /* Output Write Status Register */
+
+#define AT91_PIO_P(n) (1 << (n))
+
+
+/*
+ * Power Management Controller.
+ */
+#define AT91_PMC 0xc00
+
+#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */
+#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */
+
+#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */
+#define AT91_PMC_PCK (1 << 0) /* Processor Clock */
+#define AT91_PMC_UDP (1 << 1) /* USB Devcice Port Clock */
+#define AT91_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend */
+#define AT91_PMC_UHP (1 << 4) /* USB Host Port Clock */
+#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */
+#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */
+#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */
+#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */
+
+#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */
+#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */
+#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */
+
+#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register */
+#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */
+#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */
+
+#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */
+#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */
+#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */
+
+#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */
+#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */
+#define AT91_PMC_DIV (0xff << 0) /* Divider */
+#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
+#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */
+#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */
+#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */
+
+#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */
+#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
+#define AT91_PMC_CSS_SLOW (0 << 0)
+#define AT91_PMC_CSS_MAIN (1 << 0)
+#define AT91_PMC_CSS_PLLA (2 << 0)
+#define AT91_PMC_CSS_PLLB (3 << 0)
+#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
+#define AT91_PMC_PRES_1 (0 << 2)
+#define AT91_PMC_PRES_2 (1 << 2)
+#define AT91_PMC_PRES_4 (2 << 2)
+#define AT91_PMC_PRES_8 (3 << 2)
+#define AT91_PMC_PRES_16 (4 << 2)
+#define AT91_PMC_PRES_32 (5 << 2)
+#define AT91_PMC_PRES_64 (6 << 2)
+#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */
+#define AT91_PMC_MDIV_1 (0 << 8)
+#define AT91_PMC_MDIV_2 (1 << 8)
+#define AT91_PMC_MDIV_3 (2 << 8)
+#define AT91_PMC_MDIV_4 (3 << 8)
+
+#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-3 Registers */
+#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
+#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
+#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */
+#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */
+#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */
+#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
+#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
+#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
+#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
+#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
+#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */
+#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */
+
+
+/*
+ * System Timer.
+ */
+#define AT91_ST 0xd00
+
+#define AT91_ST_CR (AT91_ST + 0x00) /* Control Register */
+#define AT91_ST_WDRST (1 << 0) /* Watchdog Timer Restart */
+#define AT91_ST_PIMR (AT91_ST + 0x04) /* Period Interval Mode Register */
+#define AT91_ST_PIV (0xffff << 0) /* Period Interval Value */
+#define AT91_ST_WDMR (AT91_ST + 0x08) /* Watchdog Mode Register */
+#define AT91_ST_WDV (0xffff << 0) /* Watchdog Counter Value */
+#define AT91_ST_RSTEN (1 << 16) /* Reset Enable */
+#define AT91_ST_EXTEN (1 << 17) /* External Signal Assertion Enable */
+#define AT91_ST_RTMR (AT91_ST + 0x0c) /* Real-time Mode Register */
+#define AT91_ST_RTPRES (0xffff << 0) /* Real-time Prescalar Value */
+#define AT91_ST_SR (AT91_ST + 0x10) /* Status Register */
+#define AT91_ST_PITS (1 << 0) /* Period Interval Timer Status */
+#define AT91_ST_WDOVF (1 << 1) /* Watchdog Overflow */
+#define AT91_ST_RTTINC (1 << 2) /* Real-time Timer Increment */
+#define AT91_ST_ALMS (1 << 3) /* Alarm Status */
+#define AT91_ST_IER (AT91_ST + 0x14) /* Interrupt Enable Register */
+#define AT91_ST_IDR (AT91_ST + 0x18) /* Interrupt Disable Register */
+#define AT91_ST_IMR (AT91_ST + 0x1c) /* Interrupt Mask Register */
+#define AT91_ST_RTAR (AT91_ST + 0x20) /* Real-time Alarm Register */
+#define AT91_ST_ALMV (0xfffff << 0) /* Alarm Value */
+#define AT91_ST_CRTR (AT91_ST + 0x24) /* Current Real-time Register */
+#define AT91_ST_CRTV (0xfffff << 0) /* Current Real-Time Value */
+
+
+/*
+ * Real-time Clock.
+ */
+#define AT91_RTC 0xe00
+
+#define AT91_RTC_CR (AT91_RTC + 0x00) /* Control Register */
+#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time Register */
+#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar Register */
+#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */
+#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8)
+#define AT91_RTC_TIMEVSEL_HOUR (1 << 8)
+#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8)
+#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8)
+#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */
+#define AT91_RTC_CALEVSEL_WEEK (0 << 16)
+#define AT91_RTC_CALEVSEL_MONTH (1 << 16)
+#define AT91_RTC_CALEVSEL_YEAR (2 << 16)
+
+#define AT91_RTC_MR (AT91_RTC + 0x04) /* Mode Register */
+#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */
+
+#define AT91_RTC_TIMR (AT91_RTC + 0x08) /* Time Register */
+#define AT91_RTC_SEC (0x7f << 0) /* Current Second */
+#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */
+#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */
+#define At91_RTC_AMPM (1 << 22) /* Ante Meridiem Post Meridiem Indicator */
+
+#define AT91_RTC_CALR (AT91_RTC + 0x0c) /* Calendar Register */
+#define AT91_RTC_CENT (0x7f << 0) /* Current Century */
+#define AT91_RTC_YEAR (0xff << 8) /* Current Year */
+#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */
+#define AT91_RTC_DAY (7 << 21) /* Current Day */
+#define AT91_RTC_DATE (0x3f << 24) /* Current Date */
+
+#define AT91_RTC_TIMALR (AT91_RTC + 0x10) /* Time Alarm Register */
+#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enable */
+#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enable */
+#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */
+
+#define AT91_RTC_CALALR (AT91_RTC + 0x14) /* Calendar Alarm Register */
+#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */
+#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */
+
+#define AT91_RTC_SR (AT91_RTC + 0x18) /* Status Register */
+#define AT91_RTC_ACKUPD (1 << 0) /* Acknowledge for Update */
+#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */
+#define AT91_RTC_SECEV (1 << 2) /* Second Event */
+#define AT91_RTC_TIMEV (1 << 3) /* Time Event */
+#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */
+
+#define AT91_RTC_SCCR (AT91_RTC + 0x1c) /* Status Clear Command Register */
+#define AT91_RTC_IER (AT91_RTC + 0x20) /* Interrupt Enable Register */
+#define AT91_RTC_IDR (AT91_RTC + 0x24) /* Interrupt Disable Register */
+#define AT91_RTC_IMR (AT91_RTC + 0x28) /* Interrupt Mask Register */
+
+#define AT91_RTC_VER (AT91_RTC + 0x2c) /* Valid Entry Register */
+#define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */
+#define AT91_RTC_NVCAL (1 << 1) /* Non valid Calendar */
+#define AT91_RTC_NVTIMALR (1 << 2) /* Non valid Time Alarm */
+#define AT91_RTC_NVCALALR (1 << 3) /* Non valid Calendar Alarm */
+
+
+/*
+ * Memory Controller.
+ */
+#define AT91_MC 0xf00
+
+#define AT91_MC_RCR (AT91_MC + 0x00) /* MC Remap Control Register */
+#define AT91_MC_RCB (1 << 0) /* Remap Command Bit */
+
+#define AT91_MC_ASR (AT91_MC + 0x04) /* MC Abort Status Register */
+#define AT91_MC_AASR (AT91_MC + 0x08) /* MC Abort Address Status Register */
+#define AT91_MC_MPR (AT91_MC + 0x0c) /* MC Master Priority Register */
+
+/* External Bus Interface (EBI) registers */
+#define AT91_EBI_CSA (AT91_MC + 0x60) /* Chip Select Assignment Register */
+#define AT91_EBI_CS0A (1 << 0) /* Chip Select 0 Assignment */
+#define AT91_EBI_CS0A_SMC (0 << 0)
+#define AT91_EBI_CS0A_BFC (1 << 0)
+#define AT91_EBI_CS1A (1 << 1) /* Chip Select 1 Assignment */
+#define AT91_EBI_CS1A_SMC (0 << 1)
+#define AT91_EBI_CS1A_SDRAMC (1 << 1)
+#define AT91_EBI_CS3A (1 << 3) /* Chip Select 2 Assignment */
+#define AT91_EBI_CS3A_SMC (0 << 3)
+#define AT91_EBI_CS3A_SMC_SMARTMEDIA (1 << 3)
+#define AT91_EBI_CS4A (1 << 4) /* Chip Select 3 Assignment */
+#define AT91_EBI_CS4A_SMC (0 << 4)
+#define AT91_EBI_CS4A_SMC_COMPACTFLASH (1 << 4)
+#define AT91_EBI_CFGR (AT91_MC + 0x64) /* Configuration Register */
+#define AT91_EBI_DBPUC (1 << 0) /* Data Bus Pull-Up Configuration */
+
+/* Static Memory Controller (SMC) registers */
+#define AT91_SMC_CSR(n) (AT91_MC + 0x70 + ((n) * 4))/* SMC Chip Select Register */
+#define AT91_SMC_NWS (0x7f << 0) /* Number of Wait States */
+#define AT91_SMC_WSEN (1 << 7) /* Wait State Enable */
+#define AT91_SMC_TDF (0xf << 8) /* Data Float Time */
+#define AT91_SMC_BAT (1 << 12) /* Byte Access Type */
+#define AT91_SMC_DBW (3 << 13) /* Data Bus Width */
+#define AT91_SMC_DBW_16 (1 << 13)
+#define AT91_SMC_DBW_8 (2 << 13)
+#define AT91_SMC_DPR (1 << 15) /* Data Read Protocol */
+#define AT91_SMC_ACSS (3 << 16) /* Address to Chip Select Setup */
+#define AT91_SMC_ACSS_STD (0 << 16)
+#define AT91_SMC_ACSS_1 (1 << 16)
+#define AT91_SMC_ACSS_2 (2 << 16)
+#define AT91_SMC_ACSS_3 (3 << 16)
+#define AT91_SMC_RWSETUP (7 << 24) /* Read & Write Signal Time Setup */
+#define AT91_SMC_RWHOLD (7 << 28) /* Read & Write Signal Hold Time */
+
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_usart.h b/include/asm-arm/arch-at91rm9200/at91rm9200_usart.h
new file mode 100644
index 000000000000..79f851e31b9c
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_usart.h
@@ -0,0 +1,123 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_usart.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * USART registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_USART_H
+#define AT91RM9200_USART_H
+
+#define AT91_US_CR 0x00 /* Control Register */
+#define AT91_US_RSTRX (1 << 2) /* Reset Receiver */
+#define AT91_US_RSTTX (1 << 3) /* Reset Transmitter */
+#define AT91_US_RXEN (1 << 4) /* Receiver Enable */
+#define AT91_US_RXDIS (1 << 5) /* Receiver Disable */
+#define AT91_US_TXEN (1 << 6) /* Transmitter Enable */
+#define AT91_US_TXDIS (1 << 7) /* Transmitter Disable */
+#define AT91_US_RSTSTA (1 << 8) /* Reset Status Bits */
+#define AT91_US_STTBRK (1 << 9) /* Start Break */
+#define AT91_US_STPBRK (1 << 10) /* Stop Break */
+#define AT91_US_STTTO (1 << 11) /* Start Time-out */
+#define AT91_US_SENDA (1 << 12) /* Send Address */
+#define AT91_US_RSTIT (1 << 13) /* Reset Iterations */
+#define AT91_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */
+#define AT91_US_RETTO (1 << 15) /* Rearm Time-out */
+#define AT91_US_DTREN (1 << 16) /* Data Terminal Ready Enable */
+#define AT91_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */
+#define AT91_US_RTSEN (1 << 18) /* Request To Send Enable */
+#define AT91_US_RTSDIS (1 << 19) /* Request To Send Disable */
+
+#define AT91_US_MR 0x04 /* Mode Register */
+#define AT91_US_USMODE (0xf << 0) /* Mode of the USART */
+#define AT91_US_USMODE_NORMAL 0
+#define AT91_US_USMODE_RS485 1
+#define AT91_US_USMODE_HWHS 2
+#define AT91_US_USMODE_MODEM 3
+#define AT91_US_USMODE_ISO7816_T0 4
+#define AT91_US_USMODE_ISO7816_T1 6
+#define AT91_US_USMODE_IRDA 8
+#define AT91_US_USCLKS (3 << 4) /* Clock Selection */
+#define AT91_US_CHRL (3 << 6) /* Character Length */
+#define AT91_US_CHRL_5 (0 << 6)
+#define AT91_US_CHRL_6 (1 << 6)
+#define AT91_US_CHRL_7 (2 << 6)
+#define AT91_US_CHRL_8 (3 << 6)
+#define AT91_US_SYNC (1 << 8) /* Synchronous Mode Select */
+#define AT91_US_PAR (7 << 9) /* Parity Type */
+#define AT91_US_PAR_EVEN (0 << 9)
+#define AT91_US_PAR_ODD (1 << 9)
+#define AT91_US_PAR_SPACE (2 << 9)
+#define AT91_US_PAR_MARK (3 << 9)
+#define AT91_US_PAR_NONE (4 << 9)
+#define AT91_US_PAR_MULTI_DROP (6 << 9)
+#define AT91_US_NBSTOP (3 << 12) /* Number of Stop Bits */
+#define AT91_US_NBSTOP_1 (0 << 12)
+#define AT91_US_NBSTOP_1_5 (1 << 12)
+#define AT91_US_NBSTOP_2 (2 << 12)
+#define AT91_US_CHMODE (3 << 14) /* Channel Mode */
+#define AT91_US_CHMODE_NORMAL (0 << 14)
+#define AT91_US_CHMODE_ECHO (1 << 14)
+#define AT91_US_CHMODE_LOC_LOOP (2 << 14)
+#define AT91_US_CHMODE_REM_LOOP (3 << 14)
+#define AT91_US_MSBF (1 << 16) /* Bit Order */
+#define AT91_US_MODE9 (1 << 17) /* 9-bit Character Length */
+#define AT91_US_CLKO (1 << 18) /* Clock Output Select */
+#define AT91_US_OVER (1 << 19) /* Oversampling Mode */
+#define AT91_US_INACK (1 << 20) /* Inhibit Non Acknowledge */
+#define AT91_US_DSNACK (1 << 21) /* Disable Successive NACK */
+#define AT91_US_MAX_ITER (7 << 24) /* Max Iterations */
+#define AT91_US_FILTER (1 << 28) /* Infrared Receive Line Filter */
+
+#define AT91_US_IER 0x08 /* Interrupt Enable Register */
+#define AT91_US_RXRDY (1 << 0) /* Receiver Ready */
+#define AT91_US_TXRDY (1 << 1) /* Transmitter Ready */
+#define AT91_US_RXBRK (1 << 2) /* Break Received / End of Break */
+#define AT91_US_ENDRX (1 << 3) /* End of Receiver Transfer */
+#define AT91_US_ENDTX (1 << 4) /* End of Transmitter Transfer */
+#define AT91_US_OVRE (1 << 5) /* Overrun Error */
+#define AT91_US_FRAME (1 << 6) /* Framing Error */
+#define AT91_US_PARE (1 << 7) /* Parity Error */
+#define AT91_US_TIMEOUT (1 << 8) /* Receiver Time-out */
+#define AT91_US_TXEMPTY (1 << 9) /* Transmitter Empty */
+#define AT91_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */
+#define AT91_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */
+#define AT91_US_RXBUFF (1 << 12) /* Reception Buffer Full */
+#define AT91_US_NACK (1 << 13) /* Non Acknowledge */
+#define AT91_US_RIIC (1 << 16) /* Ring Indicator Input Change */
+#define AT91_US_DSRIC (1 << 17) /* Data Set Ready Input Change */
+#define AT91_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */
+#define AT91_US_CTSIC (1 << 19) /* Clear to Send Input Change */
+#define AT91_US_RI (1 << 20) /* RI */
+#define AT91_US_DSR (1 << 21) /* DSR */
+#define AT91_US_DCD (1 << 22) /* DCD */
+#define AT91_US_CTS (1 << 23) /* CTS */
+
+#define AT91_US_IDR 0x0c /* Interrupt Disable Register */
+#define AT91_US_IMR 0x10 /* Interrupt Mask Register */
+#define AT91_US_CSR 0x14 /* Channel Status Register */
+#define AT91_US_RHR 0x18 /* Receiver Holding Register */
+#define AT91_US_THR 0x1c /* Transmitter Holding Register */
+
+#define AT91_US_BRGR 0x20 /* Baud Rate Generator Register */
+#define AT91_US_CD (0xffff << 0) /* Clock Divider */
+
+#define AT91_US_RTOR 0x24 /* Receiver Time-out Register */
+#define AT91_US_TO (0xffff << 0) /* Time-out Value */
+
+#define AT91_US_TTGR 0x28 /* Transmitter Timeguard Register */
+#define AT91_US_TG (0xff << 0) /* Timeguard Value */
+
+#define AT91_US_FIDI 0x40 /* FI DI Ratio Register */
+#define AT91_US_NER 0x44 /* Number of Errors Register */
+#define AT91_US_IF 0x4c /* IrDA Filter Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
new file mode 100644
index 000000000000..2e7d1139a799
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -0,0 +1,80 @@
+/*
+ * include/asm-arm/arch-at91rm9200/board.h
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * These are data structures found in platform_device.dev.platform_data,
+ * and describing board-specfic data needed by drivers. For example,
+ * which pin is used for a given GPIO role.
+ *
+ * In 2.6, drivers should strongly avoid board-specific knowledge so
+ * that supporting new boards normally won't require driver patches.
+ * Most board-specific knowledge should be in arch/.../board-*.c files.
+ */
+
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+ /* Clocks */
+extern unsigned long at91_master_clock;
+
+ /* Serial Port */
+extern int at91_serial_map[AT91_NR_UART];
+extern int at91_console_port;
+
+ /* USB Device */
+struct at91_udc_data {
+ u8 vbus_pin; /* high == host powering us */
+ u8 pullup_pin; /* high == D+ pulled up */
+};
+extern void __init at91_add_device_udc(struct at91_udc_data *data);
+
+ /* Compact Flash */
+struct at91_cf_data {
+ u8 irq_pin; /* I/O IRQ */
+ u8 det_pin; /* Card detect */
+ u8 vcc_pin; /* power switching */
+ u8 rst_pin; /* card reset */
+};
+extern void __init at91_add_device_cf(struct at91_cf_data *data);
+
+ /* MMC / SD */
+struct at91_mmc_data {
+ u8 det_pin; /* card detect IRQ */
+ unsigned is_b:1; /* uses B side (vs A) */
+ unsigned wire4:1; /* (SD) supports DAT0..DAT3 */
+ u8 wp_pin; /* (SD) writeprotect detect */
+ u8 vcc_pin; /* power switching (high == on) */
+};
+extern void __init at91_add_device_mmc(struct at91_mmc_data *data);
+
+ /* Ethernet */
+struct at91_eth_data {
+ u8 phy_irq_pin; /* PHY IRQ */
+ u8 is_rmii; /* using RMII interface? */
+};
+extern void __init at91_add_device_eth(struct at91_eth_data *data);
+
+ /* USB Host */
+struct at91_usbh_data {
+ u8 ports; /* number of ports on root hub */
+};
+extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/debug-macro.S b/include/asm-arm/arch-at91rm9200/debug-macro.S
new file mode 100644
index 000000000000..f496b54c4c3e
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/debug-macro.S
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-at91rm9200/debug-macro.S
+ *
+ * Copyright (C) 2003-2005 SAN People
+ *
+ * Debugging macro include header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <asm/hardware.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, =AT91_BASE_SYS @ System peripherals (phys address)
+ ldrne \rx, =AT91_VA_BASE_SYS @ System peripherals (virt address)
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx, #AT91_DBGU_THR] @ Write to Transmitter Holding Register
+ .endm
+
+ .macro waituart,rd,rx
+1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register
+ tst \rd, #AT91_DBGU_TXRDY @ DBGU_TXRDY = 1 when ready to transmit
+ beq 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001: ldr \rd, [\rx, #AT91_DBGU_SR] @ Read Status Register
+ tst \rd, #AT91_DBGU_TXEMPTY @ DBGU_TXEMPTY = 1 when transmission complete
+ beq 1001b
+ .endm
+
diff --git a/include/asm-arm/arch-epxa10db/dma.h b/include/asm-arm/arch-at91rm9200/dma.h
index 5d97734d1077..22c1dfdd8da3 100644
--- a/include/asm-arm/arch-epxa10db/dma.h
+++ b/include/asm-arm/arch-at91rm9200/dma.h
@@ -1,7 +1,7 @@
/*
- * linux/include/asm-arm/arch-camelot/dma.h
+ * include/asm-arm/arch-at91rm9200/dma.h
*
- * Copyright (C) 1997,1998 Russell King
+ * Copyright (C) 2003 SAN People
*
* This 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,12 +17,3 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/include/asm-arm/arch-at91rm9200/entry-macro.S b/include/asm-arm/arch-at91rm9200/entry-macro.S
new file mode 100644
index 000000000000..61a326e94909
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/entry-macro.S
@@ -0,0 +1,25 @@
+/*
+ * include/asm-arm/arch-at91rm9200/entry-macro.S
+ *
+ * Copyright (C) 2003-2005 SAN People
+ *
+ * Low-level IRQ helper macros for AT91RM9200 platforms
+ *
+ * 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 <asm/hardware.h>
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =(AT91_VA_BASE_SYS) @ base virtual address of SYS peripherals
+ ldr \irqnr, [\base, #AT91_AIC_IVR] @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
+ ldr \irqstat, [\base, #AT91_AIC_ISR] @ read interrupt source number
+ teq \irqstat, #0 @ ISR is 0 when no current interrupt, or spurious interrupt
+ streq \tmp, [\base, #AT91_AIC_EOICR] @ not going to be handled further, then ACK it now.
+ .endm
+
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h
new file mode 100644
index 000000000000..0f0a61e2f129
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/gpio.h
@@ -0,0 +1,193 @@
+/*
+ * include/asm-arm/arch-at91rm9200/gpio.h
+ *
+ * Copyright (C) 2005 HP Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef __ASM_ARCH_AT91RM9200_GPIO_H
+#define __ASM_ARCH_AT91RM9200_GPIO_H
+
+#define PIN_BASE NR_AIC_IRQS
+
+#define PQFP_GPIO_BANKS 3 /* PQFP package has 3 banks */
+#define BGA_GPIO_BANKS 4 /* BGA package has 4 banks */
+
+/* these pin numbers double as IRQ numbers, like AT91_ID_* values */
+
+#define AT91_PIN_PA0 (PIN_BASE + 0x00 + 0)
+#define AT91_PIN_PA1 (PIN_BASE + 0x00 + 1)
+#define AT91_PIN_PA2 (PIN_BASE + 0x00 + 2)
+#define AT91_PIN_PA3 (PIN_BASE + 0x00 + 3)
+#define AT91_PIN_PA4 (PIN_BASE + 0x00 + 4)
+
+#define AT91_PIN_PA5 (PIN_BASE + 0x00 + 5)
+#define AT91_PIN_PA6 (PIN_BASE + 0x00 + 6)
+#define AT91_PIN_PA7 (PIN_BASE + 0x00 + 7)
+#define AT91_PIN_PA8 (PIN_BASE + 0x00 + 8)
+#define AT91_PIN_PA9 (PIN_BASE + 0x00 + 9)
+
+#define AT91_PIN_PA10 (PIN_BASE + 0x00 + 10)
+#define AT91_PIN_PA11 (PIN_BASE + 0x00 + 11)
+#define AT91_PIN_PA12 (PIN_BASE + 0x00 + 12)
+#define AT91_PIN_PA13 (PIN_BASE + 0x00 + 13)
+#define AT91_PIN_PA14 (PIN_BASE + 0x00 + 14)
+
+#define AT91_PIN_PA15 (PIN_BASE + 0x00 + 15)
+#define AT91_PIN_PA16 (PIN_BASE + 0x00 + 16)
+#define AT91_PIN_PA17 (PIN_BASE + 0x00 + 17)
+#define AT91_PIN_PA18 (PIN_BASE + 0x00 + 18)
+#define AT91_PIN_PA19 (PIN_BASE + 0x00 + 19)
+
+#define AT91_PIN_PA20 (PIN_BASE + 0x00 + 20)
+#define AT91_PIN_PA21 (PIN_BASE + 0x00 + 21)
+#define AT91_PIN_PA22 (PIN_BASE + 0x00 + 22)
+#define AT91_PIN_PA23 (PIN_BASE + 0x00 + 23)
+#define AT91_PIN_PA24 (PIN_BASE + 0x00 + 24)
+
+#define AT91_PIN_PA25 (PIN_BASE + 0x00 + 25)
+#define AT91_PIN_PA26 (PIN_BASE + 0x00 + 26)
+#define AT91_PIN_PA27 (PIN_BASE + 0x00 + 27)
+#define AT91_PIN_PA28 (PIN_BASE + 0x00 + 28)
+#define AT91_PIN_PA29 (PIN_BASE + 0x00 + 29)
+
+#define AT91_PIN_PA30 (PIN_BASE + 0x00 + 30)
+#define AT91_PIN_PA31 (PIN_BASE + 0x00 + 31)
+
+#define AT91_PIN_PB0 (PIN_BASE + 0x20 + 0)
+#define AT91_PIN_PB1 (PIN_BASE + 0x20 + 1)
+#define AT91_PIN_PB2 (PIN_BASE + 0x20 + 2)
+#define AT91_PIN_PB3 (PIN_BASE + 0x20 + 3)
+#define AT91_PIN_PB4 (PIN_BASE + 0x20 + 4)
+
+#define AT91_PIN_PB5 (PIN_BASE + 0x20 + 5)
+#define AT91_PIN_PB6 (PIN_BASE + 0x20 + 6)
+#define AT91_PIN_PB7 (PIN_BASE + 0x20 + 7)
+#define AT91_PIN_PB8 (PIN_BASE + 0x20 + 8)
+#define AT91_PIN_PB9 (PIN_BASE + 0x20 + 9)
+
+#define AT91_PIN_PB10 (PIN_BASE + 0x20 + 10)
+#define AT91_PIN_PB11 (PIN_BASE + 0x20 + 11)
+#define AT91_PIN_PB12 (PIN_BASE + 0x20 + 12)
+#define AT91_PIN_PB13 (PIN_BASE + 0x20 + 13)
+#define AT91_PIN_PB14 (PIN_BASE + 0x20 + 14)
+
+#define AT91_PIN_PB15 (PIN_BASE + 0x20 + 15)
+#define AT91_PIN_PB16 (PIN_BASE + 0x20 + 16)
+#define AT91_PIN_PB17 (PIN_BASE + 0x20 + 17)
+#define AT91_PIN_PB18 (PIN_BASE + 0x20 + 18)
+#define AT91_PIN_PB19 (PIN_BASE + 0x20 + 19)
+
+#define AT91_PIN_PB20 (PIN_BASE + 0x20 + 20)
+#define AT91_PIN_PB21 (PIN_BASE + 0x20 + 21)
+#define AT91_PIN_PB22 (PIN_BASE + 0x20 + 22)
+#define AT91_PIN_PB23 (PIN_BASE + 0x20 + 23)
+#define AT91_PIN_PB24 (PIN_BASE + 0x20 + 24)
+
+#define AT91_PIN_PB25 (PIN_BASE + 0x20 + 25)
+#define AT91_PIN_PB26 (PIN_BASE + 0x20 + 26)
+#define AT91_PIN_PB27 (PIN_BASE + 0x20 + 27)
+#define AT91_PIN_PB28 (PIN_BASE + 0x20 + 28)
+#define AT91_PIN_PB29 (PIN_BASE + 0x20 + 29)
+
+#define AT91_PIN_PB30 (PIN_BASE + 0x20 + 30)
+#define AT91_PIN_PB31 (PIN_BASE + 0x20 + 31)
+
+#define AT91_PIN_PC0 (PIN_BASE + 0x40 + 0)
+#define AT91_PIN_PC1 (PIN_BASE + 0x40 + 1)
+#define AT91_PIN_PC2 (PIN_BASE + 0x40 + 2)
+#define AT91_PIN_PC3 (PIN_BASE + 0x40 + 3)
+#define AT91_PIN_PC4 (PIN_BASE + 0x40 + 4)
+
+#define AT91_PIN_PC5 (PIN_BASE + 0x40 + 5)
+#define AT91_PIN_PC6 (PIN_BASE + 0x40 + 6)
+#define AT91_PIN_PC7 (PIN_BASE + 0x40 + 7)
+#define AT91_PIN_PC8 (PIN_BASE + 0x40 + 8)
+#define AT91_PIN_PC9 (PIN_BASE + 0x40 + 9)
+
+#define AT91_PIN_PC10 (PIN_BASE + 0x40 + 10)
+#define AT91_PIN_PC11 (PIN_BASE + 0x40 + 11)
+#define AT91_PIN_PC12 (PIN_BASE + 0x40 + 12)
+#define AT91_PIN_PC13 (PIN_BASE + 0x40 + 13)
+#define AT91_PIN_PC14 (PIN_BASE + 0x40 + 14)
+
+#define AT91_PIN_PC15 (PIN_BASE + 0x40 + 15)
+#define AT91_PIN_PC16 (PIN_BASE + 0x40 + 16)
+#define AT91_PIN_PC17 (PIN_BASE + 0x40 + 17)
+#define AT91_PIN_PC18 (PIN_BASE + 0x40 + 18)
+#define AT91_PIN_PC19 (PIN_BASE + 0x40 + 19)
+
+#define AT91_PIN_PC20 (PIN_BASE + 0x40 + 20)
+#define AT91_PIN_PC21 (PIN_BASE + 0x40 + 21)
+#define AT91_PIN_PC22 (PIN_BASE + 0x40 + 22)
+#define AT91_PIN_PC23 (PIN_BASE + 0x40 + 23)
+#define AT91_PIN_PC24 (PIN_BASE + 0x40 + 24)
+
+#define AT91_PIN_PC25 (PIN_BASE + 0x40 + 25)
+#define AT91_PIN_PC26 (PIN_BASE + 0x40 + 26)
+#define AT91_PIN_PC27 (PIN_BASE + 0x40 + 27)
+#define AT91_PIN_PC28 (PIN_BASE + 0x40 + 28)
+#define AT91_PIN_PC29 (PIN_BASE + 0x40 + 29)
+
+#define AT91_PIN_PC30 (PIN_BASE + 0x40 + 30)
+#define AT91_PIN_PC31 (PIN_BASE + 0x40 + 31)
+
+#define AT91_PIN_PD0 (PIN_BASE + 0x60 + 0)
+#define AT91_PIN_PD1 (PIN_BASE + 0x60 + 1)
+#define AT91_PIN_PD2 (PIN_BASE + 0x60 + 2)
+#define AT91_PIN_PD3 (PIN_BASE + 0x60 + 3)
+#define AT91_PIN_PD4 (PIN_BASE + 0x60 + 4)
+
+#define AT91_PIN_PD5 (PIN_BASE + 0x60 + 5)
+#define AT91_PIN_PD6 (PIN_BASE + 0x60 + 6)
+#define AT91_PIN_PD7 (PIN_BASE + 0x60 + 7)
+#define AT91_PIN_PD8 (PIN_BASE + 0x60 + 8)
+#define AT91_PIN_PD9 (PIN_BASE + 0x60 + 9)
+
+#define AT91_PIN_PD10 (PIN_BASE + 0x60 + 10)
+#define AT91_PIN_PD11 (PIN_BASE + 0x60 + 11)
+#define AT91_PIN_PD12 (PIN_BASE + 0x60 + 12)
+#define AT91_PIN_PD13 (PIN_BASE + 0x60 + 13)
+#define AT91_PIN_PD14 (PIN_BASE + 0x60 + 14)
+
+#define AT91_PIN_PD15 (PIN_BASE + 0x60 + 15)
+#define AT91_PIN_PD16 (PIN_BASE + 0x60 + 16)
+#define AT91_PIN_PD17 (PIN_BASE + 0x60 + 17)
+#define AT91_PIN_PD18 (PIN_BASE + 0x60 + 18)
+#define AT91_PIN_PD19 (PIN_BASE + 0x60 + 19)
+
+#define AT91_PIN_PD20 (PIN_BASE + 0x60 + 20)
+#define AT91_PIN_PD21 (PIN_BASE + 0x60 + 21)
+#define AT91_PIN_PD22 (PIN_BASE + 0x60 + 22)
+#define AT91_PIN_PD23 (PIN_BASE + 0x60 + 23)
+#define AT91_PIN_PD24 (PIN_BASE + 0x60 + 24)
+
+#define AT91_PIN_PD25 (PIN_BASE + 0x60 + 25)
+#define AT91_PIN_PD26 (PIN_BASE + 0x60 + 26)
+#define AT91_PIN_PD27 (PIN_BASE + 0x60 + 27)
+#define AT91_PIN_PD28 (PIN_BASE + 0x60 + 28)
+#define AT91_PIN_PD29 (PIN_BASE + 0x60 + 29)
+
+#define AT91_PIN_PD30 (PIN_BASE + 0x60 + 30)
+#define AT91_PIN_PD31 (PIN_BASE + 0x60 + 31)
+
+#ifndef __ASSEMBLY__
+/* setup setup routines, called from board init or driver probe() */
+extern int at91_set_A_periph(unsigned pin, int use_pullup);
+extern int at91_set_B_periph(unsigned pin, int use_pullup);
+extern int at91_set_gpio_input(unsigned pin, int use_pullup);
+extern int at91_set_gpio_output(unsigned pin, int value);
+extern int at91_set_deglitch(unsigned pin, int is_on);
+
+/* callable at any time */
+extern int at91_set_gpio_value(unsigned pin, int value);
+extern int at91_get_gpio_value(unsigned pin);
+#endif
+
+#endif
+
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
new file mode 100644
index 000000000000..2646c01f8e97
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -0,0 +1,92 @@
+/*
+ * include/asm-arm/arch-at91rm9200/hardware.h
+ *
+ * Copyright (C) 2003 SAN People
+ * Copyright (C) 2003 ATMEL
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+
+#include <asm/arch/at91rm9200.h>
+#include <asm/arch/at91rm9200_sys.h>
+
+/*
+ * Remap the peripherals from address 0xFFFA0000 .. 0xFFFFFFFF
+ * to 0xFEFA0000 .. 0xFF000000. (384Kb)
+ */
+#define AT91_IO_PHYS_BASE 0xFFFA0000
+#define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
+#define AT91_IO_VIRT_BASE (0xFF000000 - AT91_IO_SIZE)
+
+ /* Convert a physical IO address to virtual IO address */
+#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
+
+/*
+ * Virtual to Physical Address mapping for IO devices.
+ */
+#define AT91_VA_BASE_SYS AT91_IO_P2V(AT91_BASE_SYS)
+#define AT91_VA_BASE_SPI AT91_IO_P2V(AT91_BASE_SPI)
+#define AT91_VA_BASE_SSC2 AT91_IO_P2V(AT91_BASE_SSC2)
+#define AT91_VA_BASE_SSC1 AT91_IO_P2V(AT91_BASE_SSC1)
+#define AT91_VA_BASE_SSC0 AT91_IO_P2V(AT91_BASE_SSC0)
+#define AT91_VA_BASE_US3 AT91_IO_P2V(AT91_BASE_US3)
+#define AT91_VA_BASE_US2 AT91_IO_P2V(AT91_BASE_US2)
+#define AT91_VA_BASE_US1 AT91_IO_P2V(AT91_BASE_US1)
+#define AT91_VA_BASE_US0 AT91_IO_P2V(AT91_BASE_US0)
+#define AT91_VA_BASE_EMAC AT91_IO_P2V(AT91_BASE_EMAC)
+#define AT91_VA_BASE_TWI AT91_IO_P2V(AT91_BASE_TWI)
+#define AT91_VA_BASE_MCI AT91_IO_P2V(AT91_BASE_MCI)
+#define AT91_VA_BASE_UDP AT91_IO_P2V(AT91_BASE_UDP)
+#define AT91_VA_BASE_TCB1 AT91_IO_P2V(AT91_BASE_TCB1)
+#define AT91_VA_BASE_TCB0 AT91_IO_P2V(AT91_BASE_TCB0)
+
+/* Internal SRAM */
+#define AT91_BASE_SRAM 0x00200000 /* Internal SRAM base address */
+#define AT91_SRAM_SIZE 0x00004000 /* Internal SRAM SIZE (16Kb) */
+
+/* Serial ports */
+#define AT91_NR_UART 5 /* 4 USART3's and one DBGU port */
+
+/* FLASH */
+#define AT91_FLASH_BASE 0x10000000 /* NCS0: Flash physical base address */
+
+/* SDRAM */
+#define AT91_SDRAM_BASE 0x20000000 /* NCS1: SDRAM physical base address */
+
+/* SmartMedia */
+#define AT91_SMARTMEDIA_BASE 0x40000000 /* NCS3: Smartmedia physical base address */
+
+/* Multi-Master Memory controller */
+#define AT91_UHP_BASE 0x00300000 /* USB Host controller */
+
+/* Clocks */
+#define AT91_SLOW_CLOCK 32768 /* slow clock */
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+static inline unsigned int at91_sys_read(unsigned int reg_offset)
+{
+ void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
+
+ return readl(addr + reg_offset);
+}
+
+static inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
+{
+ void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
+
+ writel(value, addr + reg_offset);
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-epxa10db/dma.c b/include/asm-arm/arch-at91rm9200/io.h
index 0151e9f1c066..23e670d85c9d 100644
--- a/arch/arm/mach-epxa10db/dma.c
+++ b/include/asm-arm/arch-at91rm9200/io.h
@@ -1,8 +1,7 @@
/*
- * linux/arch/arm/mach-epxa10db/dma.c
+ * include/asm-arm/arch-at91rm9200/io.h
*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2003 SAN People
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,11 +17,17 @@
* 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 <asm/dma.h>
-#include <asm/mach/dma.h>
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
-void __init arch_dma_init(dma_t *dma)
-{
-}
+#include <asm/arch/at91rm9200.h>
+#include <asm/io.h>
+
+#define IO_SPACE_LIMIT 0xFFFFFFFF
+
+#define __io(a) ((void __iomem *)(a))
+#define __mem_pci(a) (a)
+
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h
new file mode 100644
index 000000000000..27b0497f1b36
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/irqs.h
@@ -0,0 +1,52 @@
+/*
+ * include/asm-arm/arch-at91rm9200/irqs.h
+ *
+ * Copyright (C) 2004 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+#define NR_AIC_IRQS 32
+
+
+/*
+ * Acknowledge interrupt with AIC after interrupt has been handled.
+ * (by kernel/irq.c)
+ */
+#define irq_finish(irq) do { at91_sys_write(AT91_AIC_EOICR, 0); } while (0)
+
+
+/*
+ * IRQ interrupt symbols are the AT91_ID_* symbols in at91rm9200.h
+ * for IRQs handled directly through the AIC, or else the AT91_PIN_*
+ * symbols in gpio.h for ones handled indirectly as GPIOs.
+ * We make provision for 4 banks of GPIO.
+ */
+#include <asm/arch/gpio.h>
+
+#define NR_IRQS (NR_AIC_IRQS + (4 * 32))
+
+
+#ifndef __ASSEMBLY__
+/*
+ * Initialize the IRQ controller.
+ */
+extern void at91rm9200_init_irq(unsigned int priority[]);
+#endif
+
+#endif
diff --git a/include/asm-arm/arch-epxa10db/memory.h b/include/asm-arm/arch-at91rm9200/memory.h
index 999541b6a9f5..462f1f0ad67c 100644
--- a/include/asm-arm/arch-epxa10db/memory.h
+++ b/include/asm-arm/arch-at91rm9200/memory.h
@@ -1,7 +1,7 @@
/*
- * linux/include/asm-arm/arch-epxa10/memory.h
+ * include/asm-arm/arch-at91rm9200/memory.h
*
- * Copyright (C) 2001 Altera Corporation
+ * Copyright (C) 2004 SAN People
*
* This 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,13 +17,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef __ASM_ARCH_MEMORY_H
#define __ASM_ARCH_MEMORY_H
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET UL(0x00000000)
+#include <asm/arch/hardware.h>
+
+#define PHYS_OFFSET (AT91_SDRAM_BASE)
+
/*
* Virtual view <-> DMA view memory address translations
@@ -32,7 +33,9 @@
* bus_to_virt: Used to convert an address for DMA operations
* to an address that the kernel can use.
*/
-#define __virt_to_bus(x) (x - PAGE_OFFSET + /*SDRAM_BASE*/0)
-#define __bus_to_virt(x) (x - /*SDRAM_BASE*/0 + PAGE_OFFSET)
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
#endif
diff --git a/include/asm-arm/arch-epxa10db/param.h b/include/asm-arm/arch-at91rm9200/param.h
index 783dedd71c8f..9480f8446852 100644
--- a/include/asm-arm/arch-epxa10db/param.h
+++ b/include/asm-arm/arch-at91rm9200/param.h
@@ -1,7 +1,7 @@
/*
- * linux/include/asm-arm/arch-epxa10db/param.h
+ * include/asm-arm/arch-at91rm9200/param.h
*
- * Copyright (C) 1999 ARM Limited
+ * Copyright (C) 2003 SAN People
*
* This 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,3 +17,12 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+/*
+ * We use default params
+ */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/pio.h b/include/asm-arm/arch-at91rm9200/pio.h
new file mode 100644
index 000000000000..a89501b4a703
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/pio.h
@@ -0,0 +1,115 @@
+/*
+ * include/asm-arm/arch-at91rm9200/pio.h
+ *
+ * Copyright (C) 2003 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef __ASM_ARCH_PIO_H
+#define __ASM_ARCH_PIO_H
+
+#include <asm/arch/hardware.h>
+
+static inline void AT91_CfgPIO_USART0(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA17_TXD0 | AT91_PA18_RXD0 | AT91_PA20_CTS0);
+
+ /*
+ * Errata #39 - RTS0 is not internally connected to PA21. We need to drive
+ * the pin manually. Default is off (RTS is active low).
+ */
+ at91_sys_write(AT91_PIOA + PIO_PER, AT91_PA21_RTS0);
+ at91_sys_write(AT91_PIOA + PIO_OER, AT91_PA21_RTS0);
+ at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+}
+
+static inline void AT91_CfgPIO_USART1(void) {
+ at91_sys_write(AT91_PIOB + PIO_PDR, AT91_PB18_RI1 | AT91_PB19_DTR1
+ | AT91_PB20_TXD1 | AT91_PB21_RXD1 | AT91_PB23_DCD1
+ | AT91_PB24_CTS1 | AT91_PB25_DSR1 | AT91_PB26_RTS1);
+}
+
+static inline void AT91_CfgPIO_USART2(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA22_RXD2 | AT91_PA23_TXD2);
+}
+
+static inline void AT91_CfgPIO_USART3(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_TXD3 | AT91_PA6_RXD3);
+ at91_sys_write(AT91_PIOA + PIO_BSR, AT91_PA5_TXD3 | AT91_PA6_RXD3);
+}
+
+static inline void AT91_CfgPIO_DBGU(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA31_DTXD | AT91_PA30_DRXD);
+}
+
+/*
+ * Enable the Two-Wire interface.
+ */
+static inline void AT91_CfgPIO_TWI(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA25_TWD | AT91_PA26_TWCK);
+ at91_sys_write(AT91_PIOA + PIO_ASR, AT91_PA25_TWD | AT91_PA26_TWCK);
+ at91_sys_write(AT91_PIOA + PIO_MDER, AT91_PA25_TWD | AT91_PA26_TWCK); /* open drain */
+}
+
+/*
+ * Enable the Serial Peripheral Interface.
+ */
+static inline void AT91_CfgPIO_SPI(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA0_MISO | AT91_PA1_MOSI | AT91_PA2_SPCK);
+}
+
+static inline void AT91_CfgPIO_SPI_CS0(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA3_NPCS0);
+}
+
+static inline void AT91_CfgPIO_SPI_CS1(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA4_NPCS1);
+}
+
+static inline void AT91_CfgPIO_SPI_CS2(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_NPCS2);
+}
+
+static inline void AT91_CfgPIO_SPI_CS3(void) {
+ at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA6_NPCS3);
+}
+
+/*
+ * Select the DataFlash card.
+ */
+static inline void AT91_CfgPIO_DataFlashCard(void) {
+ at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(7));
+ at91_sys_write(AT91_PIOB + PIO_OER, AT91_PIO_P(7));
+ at91_sys_write(AT91_PIOB + PIO_CODR, AT91_PIO_P(7));
+}
+
+/*
+ * Enable NAND Flash (SmartMedia) interface.
+ */
+static inline void AT91_CfgPIO_SmartMedia(void) {
+ /* enable PC0=SMCE, PC1=SMOE, PC3=SMWE, A21=CLE, A22=ALE */
+ at91_sys_write(AT91_PIOC + PIO_ASR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE);
+ at91_sys_write(AT91_PIOC + PIO_PDR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE);
+
+ /* Configure PC2 as input (signal READY of the SmartMedia) */
+ at91_sys_write(AT91_PIOC + PIO_PER, AT91_PC2_BFAVD); /* enable direct output enable */
+ at91_sys_write(AT91_PIOC + PIO_ODR, AT91_PC2_BFAVD); /* disable output */
+
+ /* Configure PB1 as input (signal Card Detect of the SmartMedia) */
+ at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(1)); /* enable direct output enable */
+ at91_sys_write(AT91_PIOB + PIO_ODR, AT91_PIO_P(1)); /* disable output */
+}
+
+static inline int AT91_PIO_SmartMedia_RDY(void) {
+ return (at91_sys_read(AT91_PIOC + PIO_PDSR) & AT91_PIO_P(2)) ? 1 : 0;
+}
+
+static inline int AT91_PIO_SmartMedia_CardDetect(void) {
+ return (at91_sys_read(AT91_PIOB + PIO_PDSR) & AT91_PIO_P(1)) ? 1 : 0;
+}
+
+#endif
diff --git a/include/asm-arm/arch-epxa10db/system.h b/include/asm-arm/arch-at91rm9200/system.h
index 345b092a1ed5..29c42655f05c 100644
--- a/include/asm-arm/arch-epxa10db/system.h
+++ b/include/asm-arm/arch-at91rm9200/system.h
@@ -1,9 +1,7 @@
/*
- * linux/include/asm-arm/arch-epxa10db/system.h
+ * include/asm-arm/arch-at91rm9200/system.h
*
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd
- * Copyright (C) 2001 Altera Corporation
+ * Copyright (C) 2003 SAN People
*
* This 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,23 +17,35 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <asm/arch/platform.h>
+#include <asm/arch/hardware.h>
static inline void arch_idle(void)
{
/*
- * This should do all the clock switching
- * and wait for interrupt tricks
+ * Disable the processor clock. The processor will be automatically
+ * re-enabled by an interrupt or by a reset.
+ */
+// at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+
+ /*
+ * Set the processor (CP15) into 'Wait for Interrupt' mode.
+ * Unlike disabling the processor clock via the PMC (above)
+ * this allows the processor to be woken via JTAG.
*/
cpu_do_idle();
}
-extern __inline__ void arch_reset(char mode)
+static inline void arch_reset(char mode)
{
- /* Hmm... We can probably do something with the watchdog... */
+ /*
+ * Perform a hardware reset with the use of the Watchdog timer.
+ */
+ at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1);
+ at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
}
#endif
diff --git a/include/asm-arm/arch-epxa10db/timex.h b/include/asm-arm/arch-at91rm9200/timex.h
index b87a75fc9589..3f112dd12587 100644
--- a/include/asm-arm/arch-epxa10db/timex.h
+++ b/include/asm-arm/arch-at91rm9200/timex.h
@@ -1,9 +1,7 @@
/*
- * linux/include/asm-arm/arch-epxa10db/timex.h
+ * include/asm-arm/arch-at91rm9200/timex.h
*
- * Excalibur timex specifications
- *
- * Copyright (C) 2001 Altera Corporation
+ * Copyright (C) 2003 SAN People
*
* This 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,7 +18,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
- * ??
- */
-#define CLOCK_TICK_RATE (50000000 / 16)
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#include <asm/arch/hardware.h>
+
+#define CLOCK_TICK_RATE (AT91_SLOW_CLOCK)
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h
new file mode 100644
index 000000000000..b30dd5520713
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/uncompress.h
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91rm9200/uncompress.h
+ *
+ * Copyright (C) 2003 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include <asm/arch/hardware.h>
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader. We search for the first enabled
+ * port in the most probable order. If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+static void putstr(const char *s)
+{
+ void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
+
+ while (*s) {
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
+ __raw_writel(*s, sys + AT91_DBGU_THR);
+ if (*s == '\n') {
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); }
+ __raw_writel('\r', sys + AT91_DBGU_THR);
+ }
+ s++;
+ }
+ /* wait for transmission to complete */
+ while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) { barrier(); }
+}
+
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
+
+#endif
diff --git a/include/asm-arm/arch-epxa10db/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h
index 546fb7d2b6ad..34d9718feb90 100644
--- a/include/asm-arm/arch-epxa10db/vmalloc.h
+++ b/include/asm-arm/arch-at91rm9200/vmalloc.h
@@ -1,7 +1,7 @@
/*
- * linux/include/asm-arm/arch-epxa10db/vmalloc.h
+ * include/asm-arm/arch-at91rm9200/vmalloc.h
*
- * Copyright (C) 2000 Russell King.
+ * Copyright (C) 2003 SAN People
*
* This 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,4 +17,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END (AT91_IO_VIRT_BASE & PGDIR_MASK)
+
+#endif
diff --git a/include/asm-arm/arch-cl7500/dma.h b/include/asm-arm/arch-cl7500/dma.h
index 1d6a8829d327..591ed2551892 100644
--- a/include/asm-arm/arch-cl7500/dma.h
+++ b/include/asm-arm/arch-cl7500/dma.h
@@ -15,7 +15,6 @@
* bytes of RAM.
*/
#define MAX_DMA_ADDRESS 0xd0000000
-#define MAX_DMA_CHANNELS 0
#define DMA_S0 0
diff --git a/include/asm-arm/arch-cl7500/entry-macro.S b/include/asm-arm/arch-cl7500/entry-macro.S
index 686f413f82d6..c9e5395e5106 100644
--- a/include/asm-arm/arch-cl7500/entry-macro.S
+++ b/include/asm-arm/arch-cl7500/entry-macro.S
@@ -1,3 +1,3 @@
-
+#include <asm/hardware.h>
#include <asm/hardware/entry-macro-iomd.S>
diff --git a/include/asm-arm/arch-clps711x/dma.h b/include/asm-arm/arch-clps711x/dma.h
index 3c4c5c843252..610997938423 100644
--- a/include/asm-arm/arch-clps711x/dma.h
+++ b/include/asm-arm/arch-clps711x/dma.h
@@ -17,12 +17,3 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/include/asm-arm/arch-clps711x/entry-macro.S b/include/asm-arm/arch-clps711x/entry-macro.S
index b31079a1d4a9..21f6ee485819 100644
--- a/include/asm-arm/arch-clps711x/entry-macro.S
+++ b/include/asm-arm/arch-clps711x/entry-macro.S
@@ -7,6 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
#include <asm/hardware/clps7111.h>
.macro disable_fiq
diff --git a/include/asm-arm/arch-clps711x/system.h b/include/asm-arm/arch-clps711x/system.h
index 2ab981fee37f..11e1491535a8 100644
--- a/include/asm-arm/arch-clps711x/system.h
+++ b/include/asm-arm/arch-clps711x/system.h
@@ -20,7 +20,9 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
+#include <asm/hardware.h>
#include <asm/hardware/clps7111.h>
+#include <asm/io.h>
static inline void arch_idle(void)
{
diff --git a/include/asm-arm/arch-ebsa110/dma.h b/include/asm-arm/arch-ebsa110/dma.h
index d491776ac1cc..c52f9e2ab0bb 100644
--- a/include/asm-arm/arch-ebsa110/dma.h
+++ b/include/asm-arm/arch-ebsa110/dma.h
@@ -9,11 +9,3 @@
*
* EBSA110 DMA definitions
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/include/asm-arm/arch-ebsa285/dma.h b/include/asm-arm/arch-ebsa285/dma.h
index c43046eb8bc7..0259ad45d33c 100644
--- a/include/asm-arm/arch-ebsa285/dma.h
+++ b/include/asm-arm/arch-ebsa285/dma.h
@@ -10,11 +10,6 @@
#define __ASM_ARCH_DMA_H
/*
- * This is the maximum DMA address that can be DMAd to.
- */
-#define MAX_DMA_ADDRESS 0xffffffff
-
-/*
* The 21285 has two internal DMA channels; we call these 8 and 9.
* On CATS hardware we have an additional eight ISA dma channels
* numbered 0..7.
diff --git a/include/asm-arm/arch-ebsa285/entry-macro.S b/include/asm-arm/arch-ebsa285/entry-macro.S
index db5729ff6349..cf10ac96fdde 100644
--- a/include/asm-arm/arch-ebsa285/entry-macro.S
+++ b/include/asm-arm/arch-ebsa285/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
#include <asm/hardware/dec21285.h>
.macro disable_fiq
diff --git a/include/asm-arm/arch-epxa10db/debug-macro.S b/include/asm-arm/arch-epxa10db/debug-macro.S
deleted file mode 100644
index 1d11c51f498f..000000000000
--- a/include/asm-arm/arch-epxa10db/debug-macro.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linux/include/asm-arm/arch-epxa10db/debug-macro.S
- *
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-#include <asm/arch/excalibur.h>
-#define UART00_TYPE
-#include <asm/arch/uart00.h>
-
- .macro addruart,rx
- mrc p15, 0, \rx, c1, c0
- tst \rx, #1 @ MMU enabled?
- ldr \rx, =EXC_UART00_BASE @ physical base address
- orrne \rx, \rx, #0xff000000 @ virtual base
- orrne \rx, \rx, #0x00f00000
- .endm
-
- .macro senduart,rd,rx
- str \rd, [\rx, #UART_TD(0)]
- .endm
-
- .macro waituart,rd,rx
-1001: ldr \rd, [\rx, #UART_TSR(0)]
- and \rd, \rd, #UART_TSR_TX_LEVEL_MSK
- cmp \rd, #15
- beq 1001b
- .endm
-
- .macro busyuart,rd,rx
-1001: ldr \rd, [\rx, #UART_TSR(0)]
- ands \rd, \rd, #UART_TSR_TX_LEVEL_MSK
- bne 1001b
- .endm
diff --git a/include/asm-arm/arch-epxa10db/entry-macro.S b/include/asm-arm/arch-epxa10db/entry-macro.S
deleted file mode 100644
index de6ae08334e2..000000000000
--- a/include/asm-arm/arch-epxa10db/entry-macro.S
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * include/asm-arm/arch-epxa10db/entry-macro.S
- *
- * Low-level IRQ helper macros for epxa10db platform
- *
- * 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 <asm/arch/platform.h>
-#undef IRQ_MODE /* same name defined in asm/proc/ptrace.h */
-#include <asm/arch/int_ctrl00.h>
-
- .macro disable_fiq
- .endm
-
- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-
- ldr \irqstat, =INT_ID(IO_ADDRESS(EXC_INT_CTRL00_BASE))
- ldr \irqnr,[\irqstat]
- cmp \irqnr,#0
- subne \irqnr,\irqnr,#1
-
- .endm
-
diff --git a/include/asm-arm/arch-epxa10db/ether00.h b/include/asm-arm/arch-epxa10db/ether00.h
deleted file mode 100644
index b737b8aabe2f..000000000000
--- a/include/asm-arm/arch-epxa10db/ether00.h
+++ /dev/null
@@ -1,482 +0,0 @@
-#ifndef __ETHER00_H
-#define __ETHER00_H
-
-
-
-/*
- * Register definitions for the Ethernet MAC
- */
-
-/*
- * Copyright (c) Altera Corporation 2000.
- * All rights reserved.
- */
-
-/*
-* Structures for the DMA controller
-*/
-typedef struct fda_desc
- {
- struct fda_desc * FDNext;
- long FDSystem;
- long FDStat;
- short FDLength;
- short FDCtl;
- }FDA_DESC;
-
-typedef struct buf_desc
- {
- char * BuffData;
- short BuffLength;
- char BDStat;
- char BDCtl;
- }BUF_DESC;
-
-/*
-* Control masks for the DMA controller
-*/
-#define FDCTL_BDCOUNT_MSK (0x1F)
-#define FDCTL_BDCOUNT_OFST (0)
-#define FDCTL_FRMOPT_MSK (0x7C00)
-#define FDCTL_FRMOPT_OFST (10)
-#define FDCTL_COWNSFD_MSK (0x8000)
-#define FDCTL_COWNSFD_OFST (15)
-
-#define BDCTL_RXBDSEQN_MSK (0x7F)
-#define BDCTL_RXBDSEQN_OFST (0)
-#define BDCTL_COWNSBD_MSK (0x80)
-#define BDCTL_COWNSBD_OFST (7)
-
-#define FDNEXT_EOL_MSK (0x1)
-#define FDNEXT_EOL_OFST (0)
-#define FDNEXT_EOL_POINTER_MSK (0xFFFFFFF0)
-#define FDNEXT_EOL_POINTER_OFST (4)
-
-#define ETHER_ARC_SIZE (21)
-
-/*
-* Register definitions and masks
-*/
-#define ETHER_DMA_CTL(base) (ETHER00_TYPE (base + 0x100))
-#define ETHER_DMA_CTL_DMBURST_OFST (2)
-#define ETHER_DMA_CTL_DMBURST_MSK (0x1FC)
-#define ETHER_DMA_CTL_POWRMGMNT_OFST (11)
-#define ETHER_DMA_CTL_POWRMGMNT_MSK (0x1000)
-#define ETHER_DMA_CTL_TXBIGE_OFST (14)
-#define ETHER_DMA_CTL_TXBIGE_MSK (0x4000)
-#define ETHER_DMA_CTL_RXBIGE_OFST (15)
-#define ETHER_DMA_CTL_RXBIGE_MSK (0x8000)
-#define ETHER_DMA_CTL_TXWAKEUP_OFST (16)
-#define ETHER_DMA_CTL_TXWAKEUP_MSK (0x10000)
-#define ETHER_DMA_CTL_SWINTREQ_OFST (17)
-#define ETHER_DMA_CTL_SWINTREQ_MSK (0x20000)
-#define ETHER_DMA_CTL_INTMASK_OFST (18)
-#define ETHER_DMA_CTL_INTMASK_MSK (0x40000)
-#define ETHER_DMA_CTL_M66ENSTAT_OFST (19)
-#define ETHER_DMA_CTL_M66ENSTAT_MSK (0x80000)
-#define ETHER_DMA_CTL_RMTXINIT_OFST (20)
-#define ETHER_DMA_CTL_RMTXINIT_MSK (0x100000)
-#define ETHER_DMA_CTL_RMRXINIT_OFST (21)
-#define ETHER_DMA_CTL_RMRXINIT_MSK (0x200000)
-#define ETHER_DMA_CTL_RXALIGN_OFST (22)
-#define ETHER_DMA_CTL_RXALIGN_MSK (0xC00000)
-#define ETHER_DMA_CTL_RMSWRQ_OFST (24)
-#define ETHER_DMA_CTL_RMSWRQ_MSK (0x1000000)
-#define ETHER_DMA_CTL_RMEMBANK_OFST (25)
-#define ETHER_DMA_CTL_RMEMBANK_MSK (0x2000000)
-
-#define ETHER_TXFRMPTR(base) (ETHER00_TYPE (base + 0x104))
-
-#define ETHER_TXTHRSH(base) (ETHER00_TYPE (base + 0x308))
-
-#define ETHER_TXPOLLCTR(base) (ETHER00_TYPE (base + 0x30c))
-
-#define ETHER_BLFRMPTR(base) (ETHER00_TYPE (base + 0x110))
-#define ETHER_BLFFRMPTR_EOL_OFST (0)
-#define ETHER_BLFFRMPTR_EOL_MSK (0x1)
-#define ETHER_BLFFRMPTR_ADDRESS_OFST (4)
-#define ETHER_BLFFRMPTR_ADDRESS_MSK (0xFFFFFFF0)
-
-#define ETHER_RXFRAGSIZE(base) (ETHER00_TYPE (base + 0x114))
-#define ETHER_RXFRAGSIZE_MINFRAG_OFST (2)
-#define ETHER_RXFRAGSIZE_MINFRAG_MSK (0xFFC)
-#define ETHER_RXFRAGSIZE_ENPACK_OFST (15)
-#define ETHER_RXFRAGSIZE_ENPACK_MSK (0x8000)
-
-#define ETHER_INT_EN(base) (ETHER00_TYPE (base + 0x118))
-#define ETHER_INT_EN_FDAEXEN_OFST (0)
-#define ETHER_INT_EN_FDAEXEN_MSK (0x1)
-#define ETHER_INT_EN_BLEXEN_OFST (1)
-#define ETHER_INT_EN_BLEXN_MSK (0x2)
-#define ETHER_INT_EN_STARGABTEN_OFST (2)
-#define ETHER_INT_EN_STARGABTEN_MSK (0x4)
-#define ETHER_INT_EN_RTARGABTEN_OFST (3)
-#define ETHER_INT_EN_RTARGABTEN_MSK (0x8)
-#define ETHER_INT_EN_RMASABTEN_OFST (4)
-#define ETHER_INT_EN_RMASABTEN_MSK (0x10)
-#define ETHER_INT_EN_SSYSERREN_OFST (5)
-#define ETHER_INT_EN_SSYSERREN_MSK (0x20)
-#define ETHER_INT_EN_DPARERREN_OFST (6)
-#define ETHER_INT_EN_DPARERREN_MSK (0x40)
-#define ETHER_INT_EN_EARNOTEN_OFST (7)
-#define ETHER_INT_EN_EARNOTEN_MSK (0x80)
-#define ETHER_INT_EN_DPARDEN_OFST (8)
-#define ETHER_INT_EN_DPARDEN_MSK (0x100)
-#define ETHER_INT_EN_DMPARERREN_OFST (9)
-#define ETHER_INT_EN_DMPARERREN_MSK (0x200)
-#define ETHER_INT_EN_TXCTLCMPEN_OFST (10)
-#define ETHER_INT_EN_TXCTLCMPEN_MSK (0x400)
-#define ETHER_INT_EN_NRABTEN_OFST (11)
-#define ETHER_INT_EN_NRABTEN_MSK (0x800)
-
-#define ETHER_FDA_BAS(base) (ETHER00_TYPE (base + 0x11C))
-#define ETHER_FDA_BAS_ADDRESS_OFST (4)
-#define ETHER_FDA_BAS_ADDRESS_MSK (0xFFFFFFF0)
-
-#define ETHER_FDA_LIM(base) (ETHER00_TYPE (base + 0x120))
-#define ETHER_FDA_LIM_COUNT_OFST (4)
-#define ETHER_FDA_LIM_COUNT_MSK (0xFFF0)
-
-#define ETHER_INT_SRC(base) (ETHER00_TYPE (base + 0x124))
-#define ETHER_INT_SRC_INTMACTX_OFST (0)
-#define ETHER_INT_SRC_INTMACTX_MSK (0x1)
-#define ETHER_INT_SRC_INTMACRX_OFST (1)
-#define ETHER_INT_SRC_INTMACRX_MSK (0x2)
-#define ETHER_INT_SRC_INTSBUS_OFST (2)
-#define ETHER_INT_SRC_INTSBUS_MSK (0x4)
-#define ETHER_INT_SRC_INTFDAEX_OFST (3)
-#define ETHER_INT_SRC_INTFDAEX_MSK (0x8)
-#define ETHER_INT_SRC_INTBLEX_OFST (4)
-#define ETHER_INT_SRC_INTBLEX_MSK (0x10)
-#define ETHER_INT_SRC_SWINT_OFST (5)
-#define ETHER_INT_SRC_SWINT_MSK (0x20)
-#define ETHER_INT_SRC_INTEARNOT_OFST (6)
-#define ETHER_INT_SRC_INTEARNOT_MSK (0x40)
-#define ETHER_INT_SRC_DMPARERR_OFST (7)
-#define ETHER_INT_SRC_DMPARERR_MSK (0x80)
-#define ETHER_INT_SRC_INTEXBD_OFST (8)
-#define ETHER_INT_SRC_INTEXBD_MSK (0x100)
-#define ETHER_INT_SRC_INTTXCTLCMP_OFST (9)
-#define ETHER_INT_SRC_INTTXCTLCMP_MSK (0x200)
-#define ETHER_INT_SRC_INTNRABT_OFST (10)
-#define ETHER_INT_SRC_INTNRABT_MSK (0x400)
-#define ETHER_INT_SRC_FDAEX_OFST (11)
-#define ETHER_INT_SRC_FDAEX_MSK (0x800)
-#define ETHER_INT_SRC_BLEX_OFST (12)
-#define ETHER_INT_SRC_BLEX_MSK (0x1000)
-#define ETHER_INT_SRC_DMPARERRSTAT_OFST (13)
-#define ETHER_INT_SRC_DMPARERRSTAT_MSK (0x2000)
-#define ETHER_INT_SRC_NRABT_OFST (14)
-#define ETHER_INT_SRC_NRABT_MSK (0x4000)
-#define ETHER_INT_SRC_INTLINK_OFST (15)
-#define ETHER_INT_SRC_INTLINK_MSK (0x8000)
-#define ETHER_INT_SRC_INTEXDEFER_OFST (16)
-#define ETHER_INT_SRC_INTEXDEFER_MSK (0x10000)
-#define ETHER_INT_SRC_INTRMON_OFST (17)
-#define ETHER_INT_SRC_INTRMON_MSK (0x20000)
-#define ETHER_INT_SRC_IRQ_MSK (0x83FF)
-
-#define ETHER_PAUSECNT(base) (ETHER00_TYPE (base + 0x40))
-#define ETHER_PAUSECNT_COUNT_OFST (0)
-#define ETHER_PAUSECNT_COUNT_MSK (0xFFFF)
-
-#define ETHER_REMPAUCNT(base) (ETHER00_TYPE (base + 0x44))
-#define ETHER_REMPAUCNT_COUNT_OFST (0)
-#define ETHER_REMPAUCNT_COUNT_MSK (0xFFFF)
-
-#define ETHER_TXCONFRMSTAT(base) (ETHER00_TYPE (base + 0x348))
-#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_OFST (0)
-#define ETHER_TXCONFRMSTAT_TS_STAT_VALUE_MSK (0x3FFFFF)
-
-#define ETHER_MAC_CTL(base) (ETHER00_TYPE (base + 0))
-#define ETHER_MAC_CTL_HALTREQ_OFST (0)
-#define ETHER_MAC_CTL_HALTREQ_MSK (0x1)
-#define ETHER_MAC_CTL_HALTIMM_OFST (1)
-#define ETHER_MAC_CTL_HALTIMM_MSK (0x2)
-#define ETHER_MAC_CTL_RESET_OFST (2)
-#define ETHER_MAC_CTL_RESET_MSK (0x4)
-#define ETHER_MAC_CTL_FULLDUP_OFST (3)
-#define ETHER_MAC_CTL_FULLDUP_MSK (0x8)
-#define ETHER_MAC_CTL_MACLOOP_OFST (4)
-#define ETHER_MAC_CTL_MACLOOP_MSK (0x10)
-#define ETHER_MAC_CTL_CONN_OFST (5)
-#define ETHER_MAC_CTL_CONN_MSK (0x60)
-#define ETHER_MAC_CTL_LOOP10_OFST (7)
-#define ETHER_MAC_CTL_LOOP10_MSK (0x80)
-#define ETHER_MAC_CTL_LNKCHG_OFST (8)
-#define ETHER_MAC_CTL_LNKCHG_MSK (0x100)
-#define ETHER_MAC_CTL_MISSROLL_OFST (10)
-#define ETHER_MAC_CTL_MISSROLL_MSK (0x400)
-#define ETHER_MAC_CTL_ENMISSROLL_OFST (13)
-#define ETHER_MAC_CTL_ENMISSROLL_MSK (0x2000)
-#define ETHER_MAC_CTL_LINK10_OFST (15)
-#define ETHER_MAC_CTL_LINK10_MSK (0x8000)
-
-#define ETHER_ARC_CTL(base) (ETHER00_TYPE (base + 0x4))
-#define ETHER_ARC_CTL_STATIONACC_OFST (0)
-#define ETHER_ARC_CTL_STATIONACC_MSK (0x1)
-#define ETHER_ARC_CTL_GROUPACC_OFST (1)
-#define ETHER_ARC_CTL_GROUPACC_MSK (0x2)
-#define ETHER_ARC_CTL_BROADACC_OFST (2)
-#define ETHER_ARC_CTL_BROADACC_MSK (0x4)
-#define ETHER_ARC_CTL_NEGARC_OFST (3)
-#define ETHER_ARC_CTL_NEGARC_MSK (0x8)
-#define ETHER_ARC_CTL_COMPEN_OFST (4)
-#define ETHER_ARC_CTL_COMPEN_MSK (0x10)
-
-#define ETHER_TX_CTL(base) (ETHER00_TYPE (base + 0x8))
-#define ETHER_TX_CTL_TXEN_OFST (0)
-#define ETHER_TX_CTL_TXEN_MSK (0x1)
-#define ETHER_TX_CTL_TXHALT_OFST (1)
-#define ETHER_TX_CTL_TXHALT_MSK (0x2)
-#define ETHER_TX_CTL_NOPAD_OFST (2)
-#define ETHER_TX_CTL_NOPAD_MSK (0x4)
-#define ETHER_TX_CTL_NOCRC_OFST (3)
-#define ETHER_TX_CTL_NOCRC_MSK (0x8)
-#define ETHER_TX_CTL_FBACK_OFST (4)
-#define ETHER_TX_CTL_FBACK_MSK (0x10)
-#define ETHER_TX_CTL_NOEXDEF_OFST (5)
-#define ETHER_TX_CTL_NOEXDEF_MSK (0x20)
-#define ETHER_TX_CTL_SDPAUSE_OFST (6)
-#define ETHER_TX_CTL_SDPAUSE_MSK (0x40)
-#define ETHER_TX_CTL_MII10_OFST (7)
-#define ETHER_TX_CTL_MII10_MSK (0x80)
-#define ETHER_TX_CTL_ENUNDER_OFST (8)
-#define ETHER_TX_CTL_ENUNDER_MSK (0x100)
-#define ETHER_TX_CTL_ENEXDEFER_OFST (9)
-#define ETHER_TX_CTL_ENEXDEFER_MSK (0x200)
-#define ETHER_TX_CTL_ENLCARR_OFST (10)
-#define ETHER_TX_CTL_ENLCARR_MSK (0x400)
-#define ETHER_TX_CTL_ENEXCOLL_OFST (11)
-#define ETHER_TX_CTL_ENEXCOLL_MSK (0x800)
-#define ETHER_TX_CTL_ENLATECOLL_OFST (12)
-#define ETHER_TX_CTL_ENLATECOLL_MSK (0x1000)
-#define ETHER_TX_CTL_ENTXPAR_OFST (13)
-#define ETHER_TX_CTL_ENTXPAR_MSK (0x2000)
-#define ETHER_TX_CTL_ENCOMP_OFST (14)
-#define ETHER_TX_CTL_ENCOMP_MSK (0x4000)
-
-#define ETHER_TX_STAT(base) (ETHER00_TYPE (base + 0xc))
-#define ETHER_TX_STAT_TXCOLL_OFST (0)
-#define ETHER_TX_STAT_TXCOLL_MSK (0xF)
-#define ETHER_TX_STAT_EXCOLL_OFST (4)
-#define ETHER_TX_STAT_EXCOLL_MSK (0x10)
-#define ETHER_TX_STAT_TXDEFER_OFST (5)
-#define ETHER_TX_STAT_TXDEFER_MSK (0x20)
-#define ETHER_TX_STAT_PAUSED_OFST (6)
-#define ETHER_TX_STAT_PAUSED_MSK (0x40)
-#define ETHER_TX_STAT_INTTX_OFST (7)
-#define ETHER_TX_STAT_INTTX_MSK (0x80)
-#define ETHER_TX_STAT_UNDER_OFST (8)
-#define ETHER_TX_STAT_UNDER_MSK (0x100)
-#define ETHER_TX_STAT_EXDEFER_OFST (9)
-#define ETHER_TX_STAT_EXDEFER_MSK (0x200)
-#define ETHER_TX_STAT_LCARR_OFST (10)
-#define ETHER_TX_STAT_LCARR_MSK (0x400)
-#define ETHER_TX_STAT_TX10STAT_OFST (11)
-#define ETHER_TX_STAT_TX10STAT_MSK (0x800)
-#define ETHER_TX_STAT_LATECOLL_OFST (12)
-#define ETHER_TX_STAT_LATECOLL_MSK (0x1000)
-#define ETHER_TX_STAT_TXPAR_OFST (13)
-#define ETHER_TX_STAT_TXPAR_MSK (0x2000)
-#define ETHER_TX_STAT_COMP_OFST (14)
-#define ETHER_TX_STAT_COMP_MSK (0x4000)
-#define ETHER_TX_STAT_TXHALTED_OFST (15)
-#define ETHER_TX_STAT_TXHALTED_MSK (0x8000)
-#define ETHER_TX_STAT_SQERR_OFST (16)
-#define ETHER_TX_STAT_SQERR_MSK (0x10000)
-#define ETHER_TX_STAT_TXMCAST_OFST (17)
-#define ETHER_TX_STAT_TXMCAST_MSK (0x20000)
-#define ETHER_TX_STAT_TXBCAST_OFST (18)
-#define ETHER_TX_STAT_TXBCAST_MSK (0x40000)
-#define ETHER_TX_STAT_VLAN_OFST (19)
-#define ETHER_TX_STAT_VLAN_MSK (0x80000)
-#define ETHER_TX_STAT_MACC_OFST (20)
-#define ETHER_TX_STAT_MACC_MSK (0x100000)
-#define ETHER_TX_STAT_TXPAUSE_OFST (21)
-#define ETHER_TX_STAT_TXPAUSE_MSK (0x200000)
-
-#define ETHER_RX_CTL(base) (ETHER00_TYPE (base + 0x10))
-#define ETHER_RX_CTL_RXEN_OFST (0)
-#define ETHER_RX_CTL_RXEN_MSK (0x1)
-#define ETHER_RX_CTL_RXHALT_OFST (1)
-#define ETHER_RX_CTL_RXHALT_MSK (0x2)
-#define ETHER_RX_CTL_LONGEN_OFST (2)
-#define ETHER_RX_CTL_LONGEN_MSK (0x4)
-#define ETHER_RX_CTL_SHORTEN_OFST (3)
-#define ETHER_RX_CTL_SHORTEN_MSK (0x8)
-#define ETHER_RX_CTL_STRIPCRC_OFST (4)
-#define ETHER_RX_CTL_STRIPCRC_MSK (0x10)
-#define ETHER_RX_CTL_PASSCTL_OFST (5)
-#define ETHER_RX_CTL_PASSCTL_MSK (0x20)
-#define ETHER_RX_CTL_IGNORECRC_OFST (6)
-#define ETHER_RX_CTL_IGNORECRC_MSK (0x40)
-#define ETHER_RX_CTL_ENALIGN_OFST (8)
-#define ETHER_RX_CTL_ENALIGN_MSK (0x100)
-#define ETHER_RX_CTL_ENCRCERR_OFST (9)
-#define ETHER_RX_CTL_ENCRCERR_MSK (0x200)
-#define ETHER_RX_CTL_ENOVER_OFST (10)
-#define ETHER_RX_CTL_ENOVER_MSK (0x400)
-#define ETHER_RX_CTL_ENLONGERR_OFST (11)
-#define ETHER_RX_CTL_ENLONGERR_MSK (0x800)
-#define ETHER_RX_CTL_ENRXPAR_OFST (13)
-#define ETHER_RX_CTL_ENRXPAR_MSK (0x2000)
-#define ETHER_RX_CTL_ENGOOD_OFST (14)
-#define ETHER_RX_CTL_ENGOOD_MSK (0x4000)
-
-#define ETHER_RX_STAT(base) (ETHER00_TYPE (base + 0x14))
-#define ETHER_RX_STAT_LENERR_OFST (4)
-#define ETHER_RX_STAT_LENERR_MSK (0x10)
-#define ETHER_RX_STAT_CTLRECD_OFST (5)
-#define ETHER_RX_STAT_CTLRECD_MSK (0x20)
-#define ETHER_RX_STAT_INTRX_OFST (6)
-#define ETHER_RX_STAT_INTRX_MSK (0x40)
-#define ETHER_RX_STAT_RX10STAT_OFST (7)
-#define ETHER_RX_STAT_RX10STAT_MSK (0x80)
-#define ETHER_RX_STAT_ALIGNERR_OFST (8)
-#define ETHER_RX_STAT_ALIGNERR_MSK (0x100)
-#define ETHER_RX_STAT_CRCERR_OFST (9)
-#define ETHER_RX_STAT_CRCERR_MSK (0x200)
-#define ETHER_RX_STAT_OVERFLOW_OFST (10)
-#define ETHER_RX_STAT_OVERFLOW_MSK (0x400)
-#define ETHER_RX_STAT_LONGERR_OFST (11)
-#define ETHER_RX_STAT_LONGERR_MSK (0x800)
-#define ETHER_RX_STAT_RXPAR_OFST (13)
-#define ETHER_RX_STAT_RXPAR_MSK (0x2000)
-#define ETHER_RX_STAT_GOOD_OFST (14)
-#define ETHER_RX_STAT_GOOD_MSK (0x4000)
-#define ETHER_RX_STAT_RXHALTED_OFST (15)
-#define ETHER_RX_STAT_RXHALTED_MSK (0x8000)
-#define ETHER_RX_STAT_RXMCAST_OFST (17)
-#define ETHER_RX_STAT_RXMCAST_MSK (0x10000)
-#define ETHER_RX_STAT_RXBCAST_OFST (18)
-#define ETHER_RX_STAT_RXBCAST_MSK (0x20000)
-#define ETHER_RX_STAT_RXVLAN_OFST (19)
-#define ETHER_RX_STAT_RXVLAN_MSK (0x40000)
-#define ETHER_RX_STAT_RXPAUSE_OFST (20)
-#define ETHER_RX_STAT_RXPAUSE_MSK (0x80000)
-#define ETHER_RX_STAT_ARCSTATUS_OFST (21)
-#define ETHER_RX_STAT_ARCSTATUS_MSK (0xF00000)
-#define ETHER_RX_STAT_ARCENT_OFST (25)
-#define ETHER_RX_STAT_ARCENT_MSK (0x1F000000)
-
-#define ETHER_MD_DATA(base) (ETHER00_TYPE (base + 0x18))
-
-#define ETHER_MD_CA(base) (ETHER00_TYPE (base + 0x1c))
-#define ETHER_MD_CA_ADDR_OFST (0)
-#define ETHER_MD_CA_ADDR_MSK (0x1F)
-#define ETHER_MD_CA_PHY_OFST (5)
-#define ETHER_MD_CA_PHY_MSK (0x3E0)
-#define ETHER_MD_CA_WR_OFST (10)
-#define ETHER_MD_CA_WR_MSK (0x400)
-#define ETHER_MD_CA_BUSY_OFST (11)
-#define ETHER_MD_CA_BUSY_MSK (0x800)
-#define ETHER_MD_CA_PRESUPP_OFST (12)
-#define ETHER_MD_CA_PRESUPP_MSK (0x1000)
-
-#define ETHER_ARC_ADR(base) (ETHER00_TYPE (base + 0x160))
-#define ETHER_ARC_ADR_ARC_LOC_OFST (2)
-#define ETHER_ARC_ADR_ARC_LOC_MSK (0xFFC)
-
-#define ETHER_ARC_DATA(base) (ETHER00_TYPE (base + 0x364))
-
-#define ETHER_ARC_ENA(base) (ETHER00_TYPE (base + 0x28))
-#define ETHER_ARC_ENA_MSK (0x1FFFFF)
-
-#define ETHER_PROM_CTL(base) (ETHER00_TYPE (base + 0x2c))
-#define ETHER_PROM_CTL_PROM_ADDR_OFST (0)
-#define ETHER_PROM_CTL_PROM_ADDR_MSK (0x3F)
-#define ETHER_PROM_CTL_OPCODE_OFST (13)
-#define ETHER_PROM_CTL_OPCODE_MSK (0x6000)
-#define ETHER_PROM_CTL_OPCODE_READ_MSK (0x4000)
-#define ETHER_PROM_CTL_OPCODE_WRITE_MSK (0x2000)
-#define ETHER_PROM_CTL_OPCODE_ERASE_MSK (0x6000)
-#define ETHER_PROM_CTL_ENABLE_MSK (0x0030)
-#define ETHER_PROM_CTL_DISABLE_MSK (0x0000)
-#define ETHER_PROM_CTL_BUSY_OFST (15)
-#define ETHER_PROM_CTL_BUSY_MSK (0x8000)
-
-#define ETHER_PROM_DATA(base) (ETHER00_TYPE (base + 0x30))
-
-#define ETHER_MISS_CNT(base) (ETHER00_TYPE (base + 0x3c))
-#define ETHER_MISS_CNT_COUNT_OFST (0)
-#define ETHER_MISS_CNT_COUNT_MSK (0xFFFF)
-
-#define ETHER_CNTDATA(base) (ETHER00_TYPE (base + 0x80))
-
-#define ETHER_CNTACC(base) (ETHER00_TYPE (base + 0x84))
-#define ETHER_CNTACC_ADDR_OFST (0)
-#define ETHER_CNTACC_ADDR_MSK (0xFF)
-#define ETHER_CNTACC_WRRDN_OFST (8)
-#define ETHER_CNTACC_WRRDN_MSK (0x100)
-#define ETHER_CNTACC_CLEAR_OFST (9)
-#define ETHER_CNTACC_CLEAR_MSK (0x200)
-
-#define ETHER_TXRMINTEN(base) (ETHER00_TYPE (base + 0x88))
-#define ETHER_TXRMINTEN_MSK (0x3FFFFFFF)
-
-#define ETHER_RXRMINTEN(base) (ETHER00_TYPE (base + 0x8C))
-#define ETHER_RXRMINTEN_MSK (0xFFFFFF)
-
-/*
-* RMON Registers
-*/
-#define RMON_COLLISION0 0x0
-#define RMON_COLLISION1 0x1
-#define RMON_COLLISION2 0x2
-#define RMON_COLLISION3 0x3
-#define RMON_COLLISION4 0x4
-#define RMON_COLLISION5 0x5
-#define RMON_COLLISION6 0x6
-#define RMON_COLLISION7 0x7
-#define RMON_COLLISION8 0x8
-#define RMON_COLLISION9 0x9
-#define RMON_COLLISION10 0xa
-#define RMON_COLLISION11 0xb
-#define RMON_COLLISION12 0xc
-#define RMON_COLLISION13 0xd
-#define RMON_COLLISION14 0xe
-#define RMON_COLLISION15 0xf
-#define RMON_COLLISION16 0x10
-#define RMON_FRAMES_WITH_DEFERRED_XMISSIONS 0x11
-#define RMON_LATE_COLLISIONS 0x12
-#define RMON_FRAMES_LOST_DUE_TO_MAC_XMIT 0x13
-#define RMON_CARRIER_SENSE_ERRORS 0x14
-#define RMON_FRAMES_WITH_EXCESSIVE_DEFERAL 0x15
-#define RMON_UNICAST_FRAMES_TRANSMITTED_OK 0x16
-#define RMON_MULTICAST_FRAMES_XMITTED_OK 0x17
-#define RMON_BROADCAST_FRAMES_XMITTED_OK 0x18
-#define RMON_SQE_TEST_ERRORS 0x19
-#define RMON_PAUSE_MACCTRL_FRAMES_XMITTED 0x1A
-#define RMON_MACCTRL_FRAMES_XMITTED 0x1B
-#define RMON_VLAN_FRAMES_XMITTED 0x1C
-#define RMON_OCTETS_XMITTED_OK 0x1D
-#define RMON_OCTETS_XMITTED_OK_HI 0x1E
-
-#define RMON_RX_PACKET_SIZES0 0x40
-#define RMON_RX_PACKET_SIZES1 0x41
-#define RMON_RX_PACKET_SIZES2 0x42
-#define RMON_RX_PACKET_SIZES3 0x43
-#define RMON_RX_PACKET_SIZES4 0x44
-#define RMON_RX_PACKET_SIZES5 0x45
-#define RMON_RX_PACKET_SIZES6 0x46
-#define RMON_RX_PACKET_SIZES7 0x47
-#define RMON_FRAME_CHECK_SEQUENCE_ERRORS 0x48
-#define RMON_ALIGNMENT_ERRORS 0x49
-#define RMON_FRAGMENTS 0x4A
-#define RMON_JABBERS 0x4B
-#define RMON_FRAMES_LOST_TO_INTMACRCVERR 0x4C
-#define RMON_UNICAST_FRAMES_RCVD_OK 0x4D
-#define RMON_MULTICAST_FRAMES_RCVD_OK 0x4E
-#define RMON_BROADCAST_FRAMES_RCVD_OK 0x4F
-#define RMON_IN_RANGE_LENGTH_ERRORS 0x50
-#define RMON_OUT_OF_RANGE_LENGTH_ERRORS 0x51
-#define RMON_VLAN_FRAMES_RCVD 0x52
-#define RMON_PAUSE_MAC_CTRL_FRAMES_RCVD 0x53
-#define RMON_MAC_CTRL_FRAMES_RCVD 0x54
-#define RMON_OCTETS_RCVD_OK 0x55
-#define RMON_OCTETS_RCVD_OK_HI 0x56
-#define RMON_OCTETS_RCVD_OTHER 0x57
-#define RMON_OCTETS_RCVD_OTHER_HI 0x58
-
-#endif /* __ETHER00_H */
diff --git a/include/asm-arm/arch-epxa10db/excalibur.h b/include/asm-arm/arch-epxa10db/excalibur.h
deleted file mode 100644
index 5c91dd6d7822..000000000000
--- a/include/asm-arm/arch-epxa10db/excalibur.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* megafunction wizard: %ARM-Based Excalibur%
- GENERATION: STANDARD
- VERSION: WM1.0
- MODULE: ARM-Based Excalibur
- PROJECT: excalibur
- ============================================================
- File Name: v:\embedded\linux\bootldr\excalibur.h
- Megafunction Name(s): ARM-Based Excalibur
- ============================================================
-
- ************************************************************
- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
- ************************************************************/
-
-#ifndef EXCALIBUR_H_INCLUDED
-#define EXCALIBUR_H_INCLUDED
-
-#define EXC_DEFINE_PROCESSOR_LITTLE_ENDIAN
-#define EXC_DEFINE_BOOT_FROM_FLASH
-
-#define EXC_INPUT_CLK_FREQUENCY (50000000)
-#define EXC_AHB1_CLK_FREQUENCY (150000000)
-#define EXC_AHB2_CLK_FREQUENCY (75000000)
-#define EXC_SDRAM_CLK_FREQUENCY (75000000)
-
-/* Registers Block */
-#define EXC_REGISTERS_BASE (0x7fffc000)
-#define EXC_MODE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x000)
-#define EXC_IO_CTRL00_BASE (EXC_REGISTERS_BASE + 0x040)
-#define EXC_MMAP00_BASE (EXC_REGISTERS_BASE + 0x080)
-#define EXC_PLD_CONFIG00_BASE (EXC_REGISTERS_BASE + 0x140)
-#define EXC_TIMER00_BASE (EXC_REGISTERS_BASE + 0x200)
-#define EXC_INT_CTRL00_BASE (EXC_REGISTERS_BASE + 0xc00)
-#define EXC_CLOCK_CTRL00_BASE (EXC_REGISTERS_BASE + 0x300)
-#define EXC_WATCHDOG00_BASE (EXC_REGISTERS_BASE + 0xa00)
-#define EXC_UART00_BASE (EXC_REGISTERS_BASE + 0x280)
-#define EXC_EBI00_BASE (EXC_REGISTERS_BASE + 0x380)
-#define EXC_SDRAM00_BASE (EXC_REGISTERS_BASE + 0x400)
-#define EXC_AHB12_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x800)
-#define EXC_PLD_STRIPE_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x100)
-#define EXC_STRIPE_PLD_BRIDGE_CTRL00_BASE (EXC_REGISTERS_BASE + 0x100)
-
-#define EXC_REGISTERS_SIZE (0x00004000)
-
-/* EBI Block(s) */
-#define EXC_EBI_BLOCK0_BASE (0x40000000)
-#define EXC_EBI_BLOCK0_SIZE (0x00400000)
-#define EXC_EBI_BLOCK0_WIDTH (8)
-#define EXC_EBI_BLOCK0_NON_CACHEABLE
-#define EXC_EBI_BLOCK1_BASE (0x40400000)
-#define EXC_EBI_BLOCK1_SIZE (0x00400000)
-#define EXC_EBI_BLOCK1_WIDTH (16)
-#define EXC_EBI_BLOCK1_NON_CACHEABLE
-#define EXC_EBI_BLOCK2_BASE (0x40800000)
-#define EXC_EBI_BLOCK2_SIZE (0x00400000)
-#define EXC_EBI_BLOCK2_WIDTH (16)
-#define EXC_EBI_BLOCK2_NON_CACHEABLE
-#define EXC_EBI_BLOCK3_BASE (0x40c00000)
-#define EXC_EBI_BLOCK3_SIZE (0x00400000)
-#define EXC_EBI_BLOCK3_WIDTH (16)
-#define EXC_EBI_BLOCK3_NON_CACHEABLE
-
-/* SDRAM Block(s) */
-#define EXC_SDRAM_BLOCK0_BASE (0x00000000)
-#define EXC_SDRAM_BLOCK0_SIZE (0x04000000)
-#define EXC_SDRAM_BLOCK0_WIDTH (32)
-#define EXC_SDRAM_BLOCK1_BASE (0x04000000)
-#define EXC_SDRAM_BLOCK1_SIZE (0x04000000)
-#define EXC_SDRAM_BLOCK1_WIDTH (32)
-
-/* Single Port SRAM Block(s) */
-#define EXC_SPSRAM_BLOCK0_BASE (0x08000000)
-#define EXC_SPSRAM_BLOCK0_SIZE (0x00020000)
-#define EXC_SPSRAM_BLOCK1_BASE (0x08020000)
-#define EXC_SPSRAM_BLOCK1_SIZE (0x00020000)
-
-/* PLD Block(s) */
-#define EXC_PLD_BLOCK0_BASE (0x80000000)
-#define EXC_PLD_BLOCK0_SIZE (0x00004000)
-#define EXC_PLD_BLOCK0_NON_CACHEABLE
-#define EXC_PLD_BLOCK1_BASE (0xf000000)
-#define EXC_PLD_BLOCK1_SIZE (0x00004000)
-#define EXC_PLD_BLOCK1_NON_CACHEABLE
-#define EXC_PLD_BLOCK2_BASE (0x80008000)
-#define EXC_PLD_BLOCK2_SIZE (0x00004000)
-#define EXC_PLD_BLOCK2_NON_CACHEABLE
-#define EXC_PLD_BLOCK3_BASE (0x8000c000)
-#define EXC_PLD_BLOCK3_SIZE (0x00004000)
-#define EXC_PLD_BLOCK3_NON_CACHEABLE
-
-#endif
diff --git a/include/asm-arm/arch-epxa10db/hardware.h b/include/asm-arm/arch-epxa10db/hardware.h
deleted file mode 100644
index b992c2924a77..000000000000
--- a/include/asm-arm/arch-epxa10db/hardware.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * linux/include/asm-arm/arch-epxa10/hardware.h
- *
- * This file contains the hardware definitions of the Integrator.
- *
- * Copyright (C) 1999 ARM Limited.
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/arch/platform.h>
-
-/*
- * Where in virtual memory the IO devices (timers, system controllers
- * and so on)
- */
-#define IO_BASE 0xf0000000 // VA of IO
-#define IO_SIZE 0x10000000 // How much?
-#define IO_START EXC_REGISTERS_BASE // PA of IO
-/* macro to get at IO space when running virtually */
-#define IO_ADDRESS(x) ((x) | 0xf0000000)
-
-#define FLASH_VBASE 0xFE000000
-#define FLASH_SIZE 0x01000000
-#define FLASH_START EXC_EBI_BLOCK0_BASE
-#define FLASH_VADDR(x) ((x)|0xFE000000)
-/*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself). WARNING: this has to mirror definitions in platform.h
- */
-#if 0
-#define PCI_MEMORY_VADDR 0xe8000000
-#define PCI_CONFIG_VADDR 0xec000000
-#define PCI_V3_VADDR 0xed000000
-#define PCI_IO_VADDR 0xee000000
-
-#define PCIO_BASE PCI_IO_VADDR
-#define PCIMEM_BASE PCI_MEMORY_VADDR
-
-
-#define pcibios_assign_all_busses() 1
-
-#define PCIBIOS_MIN_IO 0x6000
-#define PCIBIOS_MIN_MEM 0x00100000
-#endif
-
-
-#endif
-
diff --git a/include/asm-arm/arch-epxa10db/int_ctrl00.h b/include/asm-arm/arch-epxa10db/int_ctrl00.h
deleted file mode 100644
index 23ec864c40bb..000000000000
--- a/include/asm-arm/arch-epxa10db/int_ctrl00.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- *
- * This file contains the register definitions for the Excalibur
- * Timer TIMER00.
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __INT_CTRL00_H
-#define __INT_CTRL00_H
-
-#define INT_MS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x00 ))
-#define INT_MS_FC_MSK (0x10000)
-#define INT_MS_FC_OFST (16)
-#define INT_MS_M1_MSK (0x8000)
-#define INT_MS_M1_OFST (15)
-#define INT_MS_M0_MSK (0x4000)
-#define INT_MS_M0_OFST (14)
-#define INT_MS_AE_MSK (0x2000)
-#define INT_MS_AE_OFST (13)
-#define INT_MS_PE_MSK (0x1000)
-#define INT_MS_PE_OFST (12)
-#define INT_MS_EE_MSK (0x0800)
-#define INT_MS_EE_OFST (11)
-#define INT_MS_PS_MSK (0x0400)
-#define INT_MS_PS_OFST (10)
-#define INT_MS_T1_MSK (0x0200)
-#define INT_MS_T1_OFST (9)
-#define INT_MS_T0_MSK (0x0100)
-#define INT_MS_T0_OFST (8)
-#define INT_MS_UA_MSK (0x0080)
-#define INT_MS_UA_OFST (7)
-#define INT_MS_IP_MSK (0x0040)
-#define INT_MS_IP_OFST (6)
-#define INT_MS_P5_MSK (0x0020)
-#define INT_MS_P5_OFST (5)
-#define INT_MS_P4_MSK (0x0010)
-#define INT_MS_P4_OFST (4)
-#define INT_MS_P3_MSK (0x0008)
-#define INT_MS_P3_OFST (3)
-#define INT_MS_P2_MSK (0x0004)
-#define INT_MS_P2_OFST (2)
-#define INT_MS_P1_MSK (0x0002)
-#define INT_MS_P1_OFST (1)
-#define INT_MS_P0_MSK (0x0001)
-#define INT_MS_P0_OFST (0)
-
-#define INT_MC(base_addr) (INT_CTRL00_TYPE (base_addr + 0x04 ))
-#define INT_MC_FC_MSK (0x10000)
-#define INT_MC_FC_OFST (16)
-#define INT_MC_M1_MSK (0x8000)
-#define INT_MC_M1_OFST (15)
-#define INT_MC_M0_MSK (0x4000)
-#define INT_MC_M0_OFST (14)
-#define INT_MC_AE_MSK (0x2000)
-#define INT_MC_AE_OFST (13)
-#define INT_MC_PE_MSK (0x1000)
-#define INT_MC_PE_OFST (12)
-#define INT_MC_EE_MSK (0x0800)
-#define INT_MC_EE_OFST (11)
-#define INT_MC_PS_MSK (0x0400)
-#define INT_MC_PS_OFST (10)
-#define INT_MC_T1_MSK (0x0200)
-#define INT_MC_T1_OFST (9)
-#define INT_MC_T0_MSK (0x0100)
-#define INT_MC_T0_OFST (8)
-#define INT_MC_UA_MSK (0x0080)
-#define INT_MC_UA_OFST (7)
-#define INT_MC_IP_MSK (0x0040)
-#define INT_MC_IP_OFST (6)
-#define INT_MC_P5_MSK (0x0020)
-#define INT_MC_P5_OFST (5)
-#define INT_MC_P4_MSK (0x0010)
-#define INT_MC_P4_OFST (4)
-#define INT_MC_P3_MSK (0x0008)
-#define INT_MC_P3_OFST (3)
-#define INT_MC_P2_MSK (0x0004)
-#define INT_MC_P2_OFST (2)
-#define INT_MC_P1_MSK (0x0002)
-#define INT_MC_P1_OFST (1)
-#define INT_MC_P0_MSK (0x0001)
-#define INT_MC_P0_OFST (0)
-
-#define INT_SS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x08 ))
-#define INT_SS_FC_SSK (0x8000)
-#define INT_SS_FC_OFST (15)
-#define INT_SS_M1_SSK (0x8000)
-#define INT_SS_M1_OFST (15)
-#define INT_SS_M0_SSK (0x4000)
-#define INT_SS_M0_OFST (14)
-#define INT_SS_AE_SSK (0x2000)
-#define INT_SS_AE_OFST (13)
-#define INT_SS_PE_SSK (0x1000)
-#define INT_SS_PE_OFST (12)
-#define INT_SS_EE_SSK (0x0800)
-#define INT_SS_EE_OFST (11)
-#define INT_SS_PS_SSK (0x0400)
-#define INT_SS_PS_OFST (10)
-#define INT_SS_T1_SSK (0x0200)
-#define INT_SS_T1_OFST (9)
-#define INT_SS_T0_SSK (0x0100)
-#define INT_SS_T0_OFST (8)
-#define INT_SS_UA_SSK (0x0080)
-#define INT_SS_UA_OFST (7)
-#define INT_SS_IP_SSK (0x0040)
-#define INT_SS_IP_OFST (6)
-#define INT_SS_P5_SSK (0x0020)
-#define INT_SS_P5_OFST (5)
-#define INT_SS_P4_SSK (0x0010)
-#define INT_SS_P4_OFST (4)
-#define INT_SS_P3_SSK (0x0008)
-#define INT_SS_P3_OFST (3)
-#define INT_SS_P2_SSK (0x0004)
-#define INT_SS_P2_OFST (2)
-#define INT_SS_P1_SSK (0x0002)
-#define INT_SS_P1_OFST (1)
-#define INT_SS_P0_SSK (0x0001)
-#define INT_SS_P0_OFST (0)
-
-#define INT_RS(base_addr) (INT_CTRL00_TYPE (base_addr + 0x0C ))
-#define INT_RS_FC_RSK (0x10000)
-#define INT_RS_FC_OFST (16)
-#define INT_RS_M1_RSK (0x8000)
-#define INT_RS_M1_OFST (15)
-#define INT_RS_M0_RSK (0x4000)
-#define INT_RS_M0_OFST (14)
-#define INT_RS_AE_RSK (0x2000)
-#define INT_RS_AE_OFST (13)
-#define INT_RS_PE_RSK (0x1000)
-#define INT_RS_PE_OFST (12)
-#define INT_RS_EE_RSK (0x0800)
-#define INT_RS_EE_OFST (11)
-#define INT_RS_PS_RSK (0x0400)
-#define INT_RS_PS_OFST (10)
-#define INT_RS_T1_RSK (0x0200)
-#define INT_RS_T1_OFST (9)
-#define INT_RS_T0_RSK (0x0100)
-#define INT_RS_T0_OFST (8)
-#define INT_RS_UA_RSK (0x0080)
-#define INT_RS_UA_OFST (7)
-#define INT_RS_IP_RSK (0x0040)
-#define INT_RS_IP_OFST (6)
-#define INT_RS_P5_RSK (0x0020)
-#define INT_RS_P5_OFST (5)
-#define INT_RS_P4_RSK (0x0010)
-#define INT_RS_P4_OFST (4)
-#define INT_RS_P3_RSK (0x0008)
-#define INT_RS_P3_OFST (3)
-#define INT_RS_P2_RSK (0x0004)
-#define INT_RS_P2_OFST (2)
-#define INT_RS_P1_RSK (0x0002)
-#define INT_RS_P1_OFST (1)
-#define INT_RS_P0_RSK (0x0001)
-#define INT_RS_P0_OFST (0)
-
-#define INT_ID(base_addr) (INT_CTRL00_TYPE (base_addr + 0x10 ))
-#define INT_ID_ID_MSK (0x3F)
-#define INT_ID_ID_OFST (0)
-
-#define INT_PLD_PRIORITY(base_addr) (INT_CTRL00_TYPE (base_addr + 0x14 ))
-#define INT_PLD_PRIORITY_PRI_MSK (0x3F)
-#define INT_PLD_PRIORITY_PRI_OFST (0)
-#define INT_PLD_PRIORITY_GA_MSK (0x40)
-#define INT_PLD_PRIORITY_GA_OFST (6)
-
-#define INT_MODE(base_addr) (INT_CTRL00_TYPE (base_addr + 0x18 ))
-#define INT_MODE_MODE_MSK (0x3)
-#define INT_MODE_MODE_OFST (0)
-
-#define INT_PRIORITY_P0(base_addr) (INT_CTRL00_TYPE (base_addr + 0x80 ))
-#define INT_PRIORITY_P0_PRI_MSK (0x3F)
-#define INT_PRIORITY_P0_PRI_OFST (0)
-#define INT_PRIORITY_P0_FQ_MSK (0x40)
-#define INT_PRIORITY_P0_FQ_OFST (6)
-
-#define INT_PRIORITY_P1(base_addr) (INT_CTRL00_TYPE (base_addr + 0x84 ))
-#define INT_PRIORITY_P1_PRI_MSK (0x3F)
-#define INT_PRIORITY_P1_PRI_OFST (0)
-#define INT_PRIORITY_P1_FQ_MSK (0x40)
-#define INT_PRIORITY_P1_FQ_OFST (6)
-
-#define INT_PRIORITY_P2(base_addr) (INT_CTRL00_TYPE (base_addr + 0x88 ))
-#define INT_PRIORITY_P2_PRI_MSK (0x3F)
-#define INT_PRIORITY_P2_PRI_OFST (0)
-#define INT_PRIORITY_P2_FQ_MSK (0x40)
-#define INT_PRIORITY_P2_FQ_OFST (6)
-
-#define INT_PRIORITY_P3(base_addr) (INT_CTRL00_TYPE (base_addr + 0x8C ))
-#define INT_PRIORITY_P3_PRI_MSK (0x3F)
-#define INT_PRIORITY_P3_PRI_OFST (0)
-#define INT_PRIORITY_P3_FQ_MSK (0x40)
-#define INT_PRIORITY_P3_FQ_OFST (6)
-
-#define INT_PRIORITY_P4(base_addr) (INT_CTRL00_TYPE (base_addr + 0x90 ))
-#define INT_PRIORITY_P4_PRI_MSK (0x3F)
-#define INT_PRIORITY_P4_PRI_OFST (0)
-#define INT_PRIORITY_P4_FQ_MSK (0x40)
-#define INT_PRIORITY_P4_FQ_OFST (6)
-
-#define INT_PRIORITY_P5(base_addr) (INT_CTRL00_TYPE (base_addr + 0x94 ))
-#define INT_PRIORITY_P5_PRI_MSK (0x3F)
-#define INT_PRIORITY_P5_PRI_OFST (0)
-#define INT_PRIORITY_P5_FQ_MSK (0x40)
-#define INT_PRIORITY_P5_FQ_OFST (6)
-
-#define INT_PRIORITY_IP(base_addr) (INT_CTRL00_TYPE (base_addr + 0x94 ))
-#define INT_PRIORITY_IP_PRI_MSK (0x3F)
-#define INT_PRIORITY_IP_PRI_OFST (0)
-#define INT_PRIORITY_IP_FQ_MSK (0x40)
-#define INT_PRIORITY_IP_FQ_OFST (6)
-
-#define INT_PRIORITY_UA(base_addr) (INT_CTRL00_TYPE (base_addr + 0x9C ))
-#define INT_PRIORITY_UA_PRI_MSK (0x3F)
-#define INT_PRIORITY_UA_PRI_OFST (0)
-#define INT_PRIORITY_UA_FQ_MSK (0x40)
-#define INT_PRIORITY_UA_FQ_OFST (6)
-
-#define INT_PRIORITY_T0(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA0 ))
-#define INT_PRIORITY_T0_PRI_MSK (0x3F)
-#define INT_PRIORITY_T0_PRI_OFST (0)
-#define INT_PRIORITY_T0_FQ_MSK (0x40)
-#define INT_PRIORITY_T0_FQ_OFST (6)
-
-#define INT_PRIORITY_T1(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA4 ))
-#define INT_PRIORITY_T1_PRI_MSK (0x3F)
-#define INT_PRIORITY_T1_PRI_OFST (0)
-#define INT_PRIORITY_T1_FQ_MSK (0x40)
-#define INT_PRIORITY_T1_FQ_OFST (6)
-
-#define INT_PRIORITY_PS(base_addr) (INT_CTRL00_TYPE (base_addr + 0xA8 ))
-#define INT_PRIORITY_PS_PRI_MSK (0x3F)
-#define INT_PRIORITY_PS_PRI_OFST (0)
-#define INT_PRIORITY_PS_FQ_MSK (0x40)
-#define INT_PRIORITY_PS_FQ_OFST (6)
-
-#define INT_PRIORITY_EE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xAC ))
-#define INT_PRIORITY_EE_PRI_MSK (0x3F)
-#define INT_PRIORITY_EE_PRI_OFST (0)
-#define INT_PRIORITY_EE_FQ_MSK (0x40)
-#define INT_PRIORITY_EE_FQ_OFST (6)
-
-#define INT_PRIORITY_PE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB0 ))
-#define INT_PRIORITY_PE_PRI_MSK (0x3F)
-#define INT_PRIORITY_PE_PRI_OFST (0)
-#define INT_PRIORITY_PE_FQ_MSK (0x40)
-#define INT_PRIORITY_PE_FQ_OFST (6)
-
-#define INT_PRIORITY_AE(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB4 ))
-#define INT_PRIORITY_AE_PRI_MSK (0x3F)
-#define INT_PRIORITY_AE_PRI_OFST (0)
-#define INT_PRIORITY_AE_FQ_MSK (0x40)
-#define INT_PRIORITY_AE_FQ_OFST (6)
-
-#define INT_PRIORITY_M0(base_addr) (INT_CTRL00_TYPE (base_addr + 0xB8 ))
-#define INT_PRIORITY_M0_PRI_MSK (0x3F)
-#define INT_PRIORITY_M0_PRI_OFST (0)
-#define INT_PRIORITY_M0_FQ_MSK (0x40)
-#define INT_PRIORITY_M0_FQ_OFST (6)
-
-#define INT_PRIORITY_M1(base_addr) (INT_CTRL00_TYPE (base_addr + 0xBC ))
-#define INT_PRIORITY_M1_PRI_MSK (0x3F)
-#define INT_PRIORITY_M1_PRI_OFST (0)
-#define INT_PRIORITY_M1_FQ_MSK (0x40)
-#define INT_PRIORITY_M1_FQ_OFST (6)
-
-#define INT_PRIORITY_FC(base_addr) (INT_CTRL00_TYPE (base_addr + 0xC0 ))
-#define INT_PRIORITY_FC_PRI_MSK (0x3F)
-#define INT_PRIORITY_FC_PRI_OFST (0)
-#define INT_PRIORITY_FC_FQ_MSK (0x40)
-#define INT_PRIORITY_FC_FQ_OFST (6)
-
-#endif /* __INT_CTRL00_H */
-
-
diff --git a/include/asm-arm/arch-epxa10db/io.h b/include/asm-arm/arch-epxa10db/io.h
deleted file mode 100644
index 9fe100c9d6be..000000000000
--- a/include/asm-arm/arch-epxa10db/io.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * linux/include/asm-arm/arch-epxa10db/io.h
- *
- * Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#include <asm/hardware.h>
-
-#define IO_SPACE_LIMIT 0xffff
-
-
-/*
- * Generic virtual read/write
- */
-/*#define outsw __arch_writesw
-#define outsl __arch_writesl
-#define outsb __arch_writesb
-#define insb __arch_readsb
-#define insw __arch_readsw
-#define insl __arch_readsl*/
-
-#define __io(a) ((void __iomem *)(a))
-#define __mem_pci(a) (a)
-
-#endif
diff --git a/include/asm-arm/arch-epxa10db/irqs.h b/include/asm-arm/arch-epxa10db/irqs.h
deleted file mode 100644
index c3758a3b5d9d..000000000000
--- a/include/asm-arm/arch-epxa10db/irqs.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * linux/include/asm-arm/arch-camelot/irqs.h
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* Use the Excalibur chip definitions */
-#define INT_CTRL00_TYPE
-#include "asm/arch/int_ctrl00.h"
-
-
-#define IRQ_PLD0 INT_MS_P0_OFST
-#define IRQ_PLD1 INT_MS_P1_OFST
-#define IRQ_PLD2 INT_MS_P2_OFST
-#define IRQ_PLD3 INT_MS_P3_OFST
-#define IRQ_PLD4 INT_MS_P4_OFST
-#define IRQ_PLD5 INT_MS_P5_OFST
-#define IRQ_EXT INT_MS_IP_OFST
-#define IRQ_UART INT_MS_UA_OFST
-#define IRQ_TIMER0 INT_MS_T0_OFST
-#define IRQ_TIMER1 INT_MS_T1_OFST
-#define IRQ_PLL INT_MS_PLL_OFST
-#define IRQ_EBI INT_MS_EBI_OFST
-#define IRQ_STRIPE_BRIDGE INT_MS_PLL_OFST
-#define IRQ_AHB_BRIDGE INT_MS_PLL_OFST
-#define IRQ_COMMRX INT_MS_CR_OFST
-#define IRQ_COMMTX INT_MS_CT_OFST
-#define IRQ_FAST_COMM INT_MS_FC_OFST
-
-#define NR_IRQS (INT_MS_FC_OFST + 1)
-
diff --git a/include/asm-arm/arch-epxa10db/mode_ctrl00.h b/include/asm-arm/arch-epxa10db/mode_ctrl00.h
deleted file mode 100644
index d8a7efa12e19..000000000000
--- a/include/asm-arm/arch-epxa10db/mode_ctrl00.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef __MODE_CTRL00_H
-#define __MODE_CTRL00_H
-
-/*
- * Register definitions for the reset and mode control
- */
-
-/*
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-
-#define BOOT_CR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR ))
-#define BOOT_CR_BF_MSK (0x1)
-#define BOOT_CR_BF_OFST (0)
-#define BOOT_CR_HM_MSK (0x2)
-#define BOOT_CR_HM_OFST (1)
-#define BOOT_CR_RE_MSK (0x4)
-#define BOOT_CR_RE_OFST (2)
-
-#define RESET_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x4 ))
-#define RESET_SR_WR_MSK (0x1)
-#define RESET_SR_WR_OFST (0)
-#define RESET_SR_CR_MSK (0x2)
-#define RESET_SR_CR_OFST (1)
-#define RESET_SR_JT_MSK (0x4)
-#define RESET_SR_JT_OFST (2)
-#define RESET_SR_ER_MSK (0x8)
-#define RESET_SR_ER_OFST (3)
-
-#define ID_CODE(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x08 ))
-
-#define SRAM0_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x20 ))
-#define SRAM0_SR_SIZE_MSK (0xFFFFF000)
-#define SRAM0_SR_SIZE_OFST (12)
-
-#define SRAM1_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x24 ))
-#define SRAM1_SR_SIZE_MSK (0xFFFFF000)
-#define SRAM1_SR_SIZE_OFST (12)
-
-#define DPSRAM0_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x30 ))
-
-#define DPSRAM0_SR_MODE_MSK (0xF)
-#define DPSRAM0_SR_MODE_OFST (0)
-#define DPSRAM0_SR_GLBL_MSK (0x30)
-#define DPSRAM0_SR_SIZE_MSK (0xFFFFF000)
-#define DPSRAM0_SR_SIZE_OFST (12)
-
-#define DPSRAM0_LCR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x34 ))
-#define DPSRAM0_LCR_LCKADDR_MSK (0x1FFE0)
-#define DPSRAM0_LCR_LCKADDR_OFST (4)
-
-#define DPSRAM1_SR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x38 ))
-#define DPSRAM1_SR_MODE_MSK (0xF)
-#define DPSRAM1_SR_MODE_OFST (0)
-#define DPSRAM1_SR_GLBL_MSK (0x30)
-#define DPSRAM1_SR_GLBL_OFST (4)
-#define DPSRAM1_SR_SIZE_MSK (0xFFFFF000)
-#define DPSRAM1_SR_SIZE_OFST (12)
-
-#define DPSRAM1_LCR(BASE_ADDR) (MODE_CTRL00_TYPE (BASE_ADDR + 0x3C ))
-#define DPSRAM1_LCR_LCKADDR_MSK (0x1FFE0)
-#define DPSRAM1_LCR_LCKADDR_OFST (4)
-
-#endif /* __MODE_CTRL00_H */
diff --git a/include/asm-arm/arch-epxa10db/platform.h b/include/asm-arm/arch-epxa10db/platform.h
deleted file mode 100644
index 129bb0f212a0..000000000000
--- a/include/asm-arm/arch-epxa10db/platform.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef PLATFORM_H
-#define PLATFORM_H
-#include "excalibur.h"
-
-#define MAXIRQNUM 15
-#endif
-
diff --git a/include/asm-arm/arch-epxa10db/pld_conf00.h b/include/asm-arm/arch-epxa10db/pld_conf00.h
deleted file mode 100644
index 7af2c38dacc6..000000000000
--- a/include/asm-arm/arch-epxa10db/pld_conf00.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __PLD_CONF00_H
-#define __PLD_CONF00_H
-
-/*
- * Register definitions for the PLD Configuration Logic
- */
-
-/*
- *
- * This file contains the register definitions for the Excalibur
- * Interrupt controller INT_CTRL00.
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define CONFIG_CONTROL(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR))
-#define CONFIG_CONTROL_LK_MSK (0x1)
-#define CONFIG_CONTROL_LK_OFST (0)
-#define CONFIG_CONTROL_CO_MSK (0x2)
-#define CONFIG_CONTROL_CO_OFST (1)
-#define CONFIG_CONTROL_B_MSK (0x4)
-#define CONFIG_CONTROL_B_OFST (2)
-#define CONFIG_CONTROL_PC_MSK (0x8)
-#define CONFIG_CONTROL_PC_OFST (3)
-#define CONFIG_CONTROL_E_MSK (0x10)
-#define CONFIG_CONTROL_E_OFST (4)
-#define CONFIG_CONTROL_ES_MSK (0xE0)
-#define CONFIG_CONTROL_ES_OFST (5)
-#define CONFIG_CONTROL_ES_0_MSK (0x20)
-#define CONFIG_CONTROL_ES_1_MSK (0x40)
-#define CONFIG_CONTROL_ES_2_MSK (0x80)
-
-#define CONFIG_CONTROL_CLOCK(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0x4 ))
-#define CONFIG_CONTROL_CLOCK_RATIO_MSK (0xFFFF)
-#define CONFIG_CONTROL_CLOCK_RATIO_OFST (0)
-
-#define CONFIG_CONTROL_DATA(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0x8 ))
-#define CONFIG_CONTROL_DATA_MSK (0xFFFFFFFF)
-#define CONFIG_CONTROL_DATA_OFST (0)
-
-#define CONFIG_UNLOCK(BASE_ADDR) (PLD_CONF00_TYPE (BASE_ADDR + 0xC ))
-#define CONFIG_UNLOCK_MSK (0xFFFFFFFF)
-#define CONFIG_UNLOCK_OFST (0)
-
-#define CONFIG_UNLOCK_MAGIC (0x554E4C4B)
-
-#endif /* __PLD_CONF00_H */
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/include/asm-arm/arch-epxa10db/tdkphy.h b/include/asm-arm/arch-epxa10db/tdkphy.h
deleted file mode 100644
index 5e107bd4e109..000000000000
--- a/include/asm-arm/arch-epxa10db/tdkphy.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * linux/drivers/tdkphy.h
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __TDKPHY_H
-#define __TDKPHY_H
-
-/*
- * Register definitions for the TDK 78Q2120 PHY
- * which is on the Camelot board
- */
-
-/*
- * Copyright (c) Altera Corporation 2000.
- * All rights reserved.
- */
-#define PHY_CONTROL (0)
-#define PHY_CONTROL_COLT_MSK (0x80)
-#define PHY_CONTROL_COLT_OFST (7)
-#define PHY_CONTROL_DUPLEX_MSK (0x100)
-#define PHY_CONTROL_DUPLEX_OFST (8)
-#define PHY_CONTROL_RANEG_MSK (0x200)
-#define PHY_CONTROL_RANEG_OFST (9)
-#define PHY_CONTROL_ISO_MSK (0x400)
-#define PHY_CONTROL_ISO_OFST (10)
-#define PHY_CONTROL_PWRDN_MSK (0x800)
-#define PHY_CONTROL_PWRDN_OFST (11)
-#define PHY_CONTROL_ANEGEN_MSK (0x1000)
-#define PHY_CONTROL_ANEGEN_OFST (12)
-#define PHY_CONTROL_SPEEDSL_MSK (0x2000)
-#define PHY_CONTROL_SPEEDSL_OFST (13)
-#define PHY_CONTROL_LOOPBK_MSK (0x4000)
-#define PHY_CONTROL_LOOPBK_OFST (14)
-#define PHY_CONTROL_RESET_MSK (0x8000)
-#define PHY_CONTROL_RESET_OFST (15)
-
-#define PHY_STATUS (1)
-#define PHY_STATUS_ETXD_MSK (0x1)
-#define PHY_STATUS_EXTD_OFST (0)
-#define PHY_STATUS_JAB_MSK (0x2)
-#define PHY_STATUS_JAB_OFST (1)
-#define PHY_STATUS_LINK_MSK (0x4)
-#define PHY_STATUS_LINK_OFST (2)
-#define PHY_STATUS_ANEGA_MSK (0x8)
-#define PHY_STATUS_ANEGA_OFST (3)
-#define PHY_STATUS_RFAULT_MSK (0x10)
-#define PHY_STATUS_RFAULT_OFST (4)
-#define PHY_STATUS_ANEGC_MSK (0x20)
-#define PHY_STATUS_ANEGC_OFST (5)
-#define PHY_STATUS_10T_H_MSK (0x800)
-#define PHY_STATUS_10T_H_OFST (11)
-#define PHY_STATUS_10T_F_MSK (0x1000)
-#define PHY_STATUS_10T_F_OFST (12)
-#define PHY_STATUS_100_X_H_MSK (0x2000)
-#define PHY_STATUS_100_X_H_OFST (13)
-#define PHY_STATUS_100_X_F_MSK (0x4000)
-#define PHY_STATUS_100_X_F_OFST (14)
-#define PHY_STATUS_100T4_MSK (0x8000)
-#define PHY_STATUS_100T4_OFST (15)
-
-#define PHY_ID1 (2)
-#define PHY_ID1_OUI_MSK (0xFFFF)
-#define PHY_ID1_OUI_OFST (0)
-
-#define PHY_ID2 (3)
-#define PHY_ID2_RN_MSK (0xF)
-#define PHY_ID2_RN_OFST (0)
-#define PHY_ID2_MN_MSK (0x3F0)
-#define PHY_ID2_MN_OFST (4)
-#define PHY_ID2_OUI_MSK (0xFC00)
-#define PHY_ID2_OUI_OFST (10)
-
-#define PHY_AUTO_NEG_ADVERTISEMENT (4)
-#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_MSK (0x1F)
-#define PHY_AUTO_NEG_ADVERTISEMENT_SELECTOR_OFST (0)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A0_MSK (0x20)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A0_OFST (5)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A1_MSK (0x40)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A1_OFST (6)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A2_MSK (0x80)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A2_OFST (7)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A3_MSK (0x100)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A3_OFST (8)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A4_MSK (0x200)
-#define PHY_AUTO_NEG_ADVERTISEMENT_A4_OFST (9)
-#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_MSK (0x1FE0)
-#define PHY_AUTO_NEG_ADVERTISEMENT_TAF_OFST (5)
-#define PHY_AUTO_NEG_ADVERTISEMENT_RF_MSK (0x2000)
-#define PHY_AUTO_NEG_ADVERTISEMENT_RF_OFST (13)
-#define PHY_AUTO_NEG_ADVERTISEMENT_RSVD_MSK (0x4000)
-#define PHY_AUTO_NEG_ADVERTISEMENT_RVSD_OFST (14)
-#define PHY_AUTO_NEG_ADVERTISEMENT_NP_MSK (0x8000)
-#define PHY_AUTO_NEG_ADVERTISEMENT_NP_OFST (15)
-
-#define PHY_AUTO_NEG_LINK_PARTNER (5)
-#define PHY_AUTO_NEG_LINK_PARTNER_S4_MSK (0x1F)
-#define PHY_AUTO_NEG_LINK_PARTNER_S4_OFST (0)
-#define PHY_AUTO_NEG_LINK_PARTNER_A7_MSK (0x1FE0)
-#define PHY_AUTO_NEG_LINK_PARTNER_A7_OFST (5)
-#define PHY_AUTO_NEG_LINK_PARTNER_RF_MSK (0x2000)
-#define PHY_AUTO_NEG_LINK_PARTNER_RF_OFST (13)
-#define PHY_AUTO_NEG_LINK_PARTNER_ACK_MSK (0x4000)
-#define PHY_AUTO_NEG_LINK_PARTNER_ACK_OFST (14)
-#define PHY_AUTO_NEG_LINK_PARTNER_NP_MSK (0x8000)
-#define PHY_AUTO_NEG_LINK_PARTNER_NP_OFST (15)
-
-#define PHY_AUTO_NEG_EXPANSION (6)
-#define PHY_AUTO_NEG_EXPANSION_LPANEGA_MSK (0x1)
-#define PHY_AUTO_NEG_EXPANSION_LPANEGA_OFST (0)
-#define PHY_AUTO_NEG_EXPANSION_PRX_MSK (0x2)
-#define PHY_AUTO_NEG_EXPANSION_PRX_OFST (1)
-#define PHY_AUTO_NEG_EXPANSION_NPA_MSK (0x4)
-#define PHY_AUTO_NEG_EXPANSION_NPA_OFST (2)
-#define PHY_AUTO_NEG_EXPANSION_LPNPA_MSK (0x8)
-#define PHY_AUTO_NEG_EXPANSION_LPNPA_OFST (3)
-#define PHY_AUTO_NEG_EXPANSION_PDF_MSK (0x10)
-#define PHY_AUTO_NEG_EXPANSION_PDF_OFST (4)
-
-#define PHY_VENDOR_SPECIFIC (16)
-#define PHY_VENDOR_SPECIFIC_RXCC_MSK (0x1)
-#define PHY_VENDOR_SPECIFIC_RXCC_OFST (0)
-#define PHY_VENDOR_SPECIFIC_PCSBP_MSK (0x2)
-#define PHY_VENDOR_SPECIFIC_PCSBP_OFST (1)
-#define PHY_VENDOR_SPECIFIC_RVSPOL_MSK (0x10)
-#define PHY_VENDOR_SPECIFIC_RVSPOL_OFST (4)
-#define PHY_VENDOR_SPECIFIC_APOL_MSK (0x20)
-#define PHY_VENDOR_SPECIFIC_APOL_OFST (5)
-#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_MSK (0x40)
-#define PHY_VENDOR_SPECIFIC_GPIO0_DIR_OFST (6)
-#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_MSK (0x80)
-#define PHY_VENDOR_SPECIFIC_GPIO0_DAT_OFST (7)
-#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_MSK (0x100)
-#define PHY_VENDOR_SPECIFIC_GPIO1_DIR_OFST (8)
-#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_MSK (0x200)
-#define PHY_VENDOR_SPECIFIC_GPIO1_DAT_OFST (9)
-#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_MSK (0x400)
-#define PHY_VENDOR_SPECIFIC_10BT_NATURAL_LOOPBACK_DAT_OFST (10)
-#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_MSK (0x800)
-#define PHY_VENDOR_SPECIFIC_10BT_SQE_TEST_INHIBIT_OFST (11)
-#define PHY_VENDOR_SPECIFIC_TXHIM_MSK (0x1000)
-#define PHY_VENDOR_SPECIFIC_TXHIM_OFST (12)
-#define PHY_VENDOR_SPECIFIC_INT_LEVEL_MSK (0x4000)
-#define PHY_VENDOR_SPECIFIC_INT_LEVEL_OFST (14)
-#define PHY_VENDOR_SPECIFIC_RPTR_MSK (0x8000)
-#define PHY_VENDOR_SPECIFIC_RPTR_OFST (15)
-
-#define PHY_IRQ_CONTROL (17)
-#define PHY_IRQ_CONTROL_ANEG_COMP_INT_MSK (0x1)
-#define PHY_IRQ_CONTROL_ANEG_COMP_INT_OFST (0)
-#define PHY_IRQ_CONTROL_RFAULT_INT_MSK (0x2)
-#define PHY_IRQ_CONTROL_RFAULT_INT_OFST (1)
-#define PHY_IRQ_CONTROL_LS_CHG_INT_MSK (0x4)
-#define PHY_IRQ_CONTROL_LS_CHG_INT_OFST (2)
-#define PHY_IRQ_CONTROL_LP_ACK_INT_MSK (0x8)
-#define PHY_IRQ_CONTROL_LP_ACK_INT_OFST (3)
-#define PHY_IRQ_CONTROL_PDF_INT_MSK (0x10)
-#define PHY_IRQ_CONTROL_PDF_INT_OFST (4)
-#define PHY_IRQ_CONTROL_PRX_INT_MSK (0x20)
-#define PHY_IRQ_CONTROL_PRX_INT_OFST (5)
-#define PHY_IRQ_CONTROL_RXER_INT_MSK (0x40)
-#define PHY_IRQ_CONTROL_RXER_INT_OFST (6)
-#define PHY_IRQ_CONTROL_JABBER_INT_MSK (0x80)
-#define PHY_IRQ_CONTROL_JABBER_INT_OFST (7)
-#define PHY_IRQ_CONTROL_ANEG_COMP_IE_MSK (0x100)
-#define PHY_IRQ_CONTROL_ANEG_COMP_IE_OFST (8)
-#define PHY_IRQ_CONTROL_RFAULT_IE_MSK (0x200)
-#define PHY_IRQ_CONTROL_RFAULT_IE_OFST (9)
-#define PHY_IRQ_CONTROL_LS_CHG_IE_MSK (0x400)
-#define PHY_IRQ_CONTROL_LS_CHG_IE_OFST (10)
-#define PHY_IRQ_CONTROL_LP_ACK_IE_MSK (0x800)
-#define PHY_IRQ_CONTROL_LP_ACK_IE_OFST (11)
-#define PHY_IRQ_CONTROL_PDF_IE_MSK (0x1000)
-#define PHY_IRQ_CONTROL_PDF_IE_OFST (12)
-#define PHY_IRQ_CONTROL_PRX_IE_MSK (0x2000)
-#define PHY_IRQ_CONTROL_PRX_IE_OFST (13)
-#define PHY_IRQ_CONTROL_RXER_IE_MSK (0x4000)
-#define PHY_IRQ_CONTROL_RXER_IE_OFST (14)
-#define PHY_IRQ_CONTROL_JABBER_IE_MSK (0x8000)
-#define PHY_IRQ_CONTROL_JABBER_IE_OFST (15)
-
-#define PHY_DIAGNOSTIC (18)
-#define PHY_DIAGNOSTIC_RX_LOCK_MSK (0x100)
-#define PHY_DIAGNOSTIC_RX_LOCK_OFST (8)
-#define PHY_DIAGNOSTIC_RX_PASS_MSK (0x200)
-#define PHY_DIAGNOSTIC_RX_PASS_OFST (9)
-#define PHY_DIAGNOSTIC_RATE_MSK (0x400)
-#define PHY_DIAGNOSTIC_RATE_OFST (10)
-#define PHY_DIAGNOSTIC_DPLX_MSK (0x800)
-#define PHY_DIAGNOSTIC_DPLX_OFST (11)
-#define PHY_DIAGNOSTIC_ANEGF_MSK (0x1000)
-#define PHY_DIAGNOSTIC_ANEGF_OFST (12)
-
-#endif /* __TDKPHY_H */
diff --git a/include/asm-arm/arch-epxa10db/timer00.h b/include/asm-arm/arch-epxa10db/timer00.h
deleted file mode 100644
index 52a3fb58b59d..000000000000
--- a/include/asm-arm/arch-epxa10db/timer00.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *
- * This file contains the register definitions for the Excalibur
- * Timer TIMER00.
- *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __TIMER00_H
-#define __TIMER00_H
-
-/*
- * Register definitions for the timers
- */
-
-
-#define TIMER0_CR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x00 ))
-#define TIMER0_CR_B_MSK (0x20)
-#define TIMER0_CR_B_OFST (0x5)
-#define TIMER0_CR_S_MSK (0x10)
-#define TIMER0_CR_S_OFST (0x4)
-#define TIMER0_CR_CI_MSK (0x08)
-#define TIMER0_CR_CI_OFST (0x3)
-#define TIMER0_CR_IE_MSK (0x04)
-#define TIMER0_CR_IE_OFST (0x2)
-#define TIMER0_CR_MODE_MSK (0x3)
-#define TIMER0_CR_MODE_OFST (0)
-#define TIMER0_CR_MODE_FREE (0)
-#define TIMER0_CR_MODE_ONE (1)
-#define TIMER0_CR_MODE_INTVL (2)
-
-#define TIMER0_SR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x00 ))
-#define TIMER0_SR_B_MSK (0x20)
-#define TIMER0_SR_B_OFST (0x5)
-#define TIMER0_SR_S_MSK (0x10)
-#define TIMER0_SR_S_OFST (0x4)
-#define TIMER0_SR_CI_MSK (0x08)
-#define TIMER0_SR_CI_OFST (0x3)
-#define TIMER0_SR_IE_MSK (0x04)
-#define TIMER0_SR_IE_OFST (0x2)
-#define TIMER0_SR_MODE_MSK (0x3)
-#define TIMER0_SR_MODE_OFST (0)
-#define TIMER0_SR_MODE_FREE (0)
-#define TIMER0_SR_MODE_ONE (1)
-#define TIMER0_SR_MODE_INTVL (2)
-
-#define TIMER0_PRESCALE(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x010 ))
-#define TIMER0_LIMIT(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x020 ))
-#define TIMER0_READ(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x030 ))
-
-#define TIMER1_CR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x40 ))
-#define TIMER1_CR_B_MSK (0x20)
-#define TIMER1_CR_B_OFST (0x5)
-#define TIMER1_CR_S_MSK (0x10)
-#define TIMER1_CR_S_OFST (0x4)
-#define TIMER1_CR_CI_MSK (0x08)
-#define TIMER1_CR_CI_OFST (0x3)
-#define TIMER1_CR_IE_MSK (0x04)
-#define TIMER1_CR_IE_OFST (0x2)
-#define TIMER1_CR_MODE_MSK (0x3)
-#define TIMER1_CR_MODE_OFST (0)
-#define TIMER1_CR_MODE_FREE (0)
-#define TIMER1_CR_MODE_ONE (1)
-#define TIMER1_CR_MODE_INTVL (2)
-
-#define TIMER1_SR(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x40 ))
-#define TIMER1_SR_B_MSK (0x20)
-#define TIMER1_SR_B_OFST (0x5)
-#define TIMER1_SR_S_MSK (0x10)
-#define TIMER1_SR_S_OFST (0x4)
-#define TIMER1_SR_CI_MSK (0x08)
-#define TIMER1_SR_CI_OFST (0x3)
-#define TIMER1_SR_IE_MSK (0x04)
-#define TIMER1_SR_IE_OFST (0x2)
-#define TIMER1_SR_MODE_MSK (0x3)
-#define TIMER1_SR_MODE_OFST (0)
-#define TIMER1_SR_MODE_FREE (0)
-#define TIMER1_SR_MODE_ONE (1)
-#define TIMER1_SR_MODE_INTVL (2)
-
-#define TIMER1_PRESCALE(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x050 ))
-#define TIMER1_LIMIT(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x060 ))
-#define TIMER1_READ(BASE_ADDR) (TIMER00_TYPE (BASE_ADDR + 0x070 ))
-
-#endif /* __TIMER00_H */
diff --git a/include/asm-arm/arch-epxa10db/uart00.h b/include/asm-arm/arch-epxa10db/uart00.h
deleted file mode 100644
index 5abd8914d68b..000000000000
--- a/include/asm-arm/arch-epxa10db/uart00.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* *
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#ifndef __UART00_H
-#define __UART00_H
-
-/*
- * Register definitions for the UART
- */
-
-#define UART_TX_FIFO_SIZE (15)
-
-#define UART_RSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x00 ))
-#define UART_RSR_RX_LEVEL_MSK (0x1f)
-#define UART_RSR_RX_LEVEL_OFST (0)
-#define UART_RSR_RE_MSK (0x80)
-#define UART_RSR_RE_OFST (7)
-
-#define UART_RDS(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x04 ))
-#define UART_RDS_BI_MSK (0x8)
-#define UART_RDS_BI_OFST (4)
-#define UART_RDS_FE_MSK (0x4)
-#define UART_RDS_FE_OFST (2)
-#define UART_RDS_PE_MSK (0x2)
-#define UART_RDS_PE_OFST (1)
-#define UART_RDS_OE_MSK (0x1)
-#define UART_RDS_OE_OFST (0)
-
-#define UART_RD(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x08 ))
-#define UART_RD_RX_DATA_MSK (0xff)
-#define UART_RD_RX_DATA_OFST (0)
-
-#define UART_TSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x0c ))
-#define UART_TSR_TX_LEVEL_MSK (0x1f)
-#define UART_TSR_TX_LEVEL_OFST (0)
-#define UART_TSR_TXI_MSK (0x80)
-#define UART_TSR_TXI_OFST (7)
-
-#define UART_TD(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x10 ))
-#define UART_TD_TX_DATA_MSK (0xff)
-#define UART_TD_TX_DATA_OFST (0)
-
-#define UART_FCR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x14 ))
-#define UART_FCR_RX_THR_MSK (0xd0)
-#define UART_FCR_RX_THR_OFST (5)
-#define UART_FCR_RX_THR_1 (0x00)
-#define UART_FCR_RX_THR_2 (0x20)
-#define UART_FCR_RX_THR_4 (0x40)
-#define UART_FCR_RX_THR_6 (0x60)
-#define UART_FCR_RX_THR_8 (0x80)
-#define UART_FCR_RX_THR_10 (0xa0)
-#define UART_FCR_RX_THR_12 (0xc0)
-#define UART_FCR_RX_THR_14 (0xd0)
-#define UART_FCR_TX_THR_MSK (0x1c)
-#define UART_FCR_TX_THR_OFST (2)
-#define UART_FCR_TX_THR_0 (0x00)
-#define UART_FCR_TX_THR_2 (0x04)
-#define UART_FCR_TX_THR_4 (0x08)
-#define UART_FCR_TX_THR_8 (0x0c)
-#define UART_FCR_TX_THR_10 (0x10)
-#define UART_FCR_TX_THR_12 (0x14)
-#define UART_FCR_TX_THR_14 (0x18)
-#define UART_FCR_TX_THR_15 (0x1c)
-#define UART_FCR_RC_MSK (0x02)
-#define UART_FCR_RC_OFST (1)
-#define UART_FCR_TC_MSK (0x01)
-#define UART_FCR_TC_OFST (0)
-
-#define UART_IES(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x18 ))
-#define UART_IES_ME_MSK (0x8)
-#define UART_IES_ME_OFST (3)
-#define UART_IES_TIE_MSK (0x4)
-#define UART_IES_TIE_OFST (2)
-#define UART_IES_TE_MSK (0x2)
-#define UART_IES_TE_OFST (1)
-#define UART_IES_RE_MSK (0x1)
-#define UART_IES_RE_OFST (0)
-
-#define UART_IEC(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x1c ))
-#define UART_IEC_ME_MSK (0x8)
-#define UART_IEC_ME_OFST (3)
-#define UART_IEC_TIE_MSK (0x4)
-#define UART_IEC_TIE_OFST (2)
-#define UART_IEC_TE_MSK (0x2)
-#define UART_IEC_TE_OFST (1)
-#define UART_IEC_RE_MSK (0x1)
-#define UART_IEC_RE_OFST (0)
-
-#define UART_ISR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x20 ))
-#define UART_ISR_MI_MSK (0x8)
-#define UART_ISR_MI_OFST (3)
-#define UART_ISR_TII_MSK (0x4)
-#define UART_ISR_TII_OFST (2)
-#define UART_ISR_TI_MSK (0x2)
-#define UART_ISR_TI_OFST (1)
-#define UART_ISR_RI_MSK (0x1)
-#define UART_ISR_RI_OFST (0)
-
-#define UART_IID(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x24 ))
-#define UART_IID_IID_MSK (0x7)
-#define UART_IID_IID_OFST (0)
-
-#define UART_MC(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x28 ))
-#define UART_MC_OE_MSK (0x40)
-#define UART_MC_OE_OFST (6)
-#define UART_MC_SP_MSK (0x20)
-#define UART_MC_SP_OFST (5)
-#define UART_MC_EP_MSK (0x10)
-#define UART_MC_EP_OFST (4)
-#define UART_MC_PE_MSK (0x08)
-#define UART_MC_PE_OFST (3)
-#define UART_MC_ST_MSK (0x04)
-#define UART_MC_ST_ONE (0x0)
-#define UART_MC_ST_TWO (0x04)
-#define UART_MC_ST_OFST (2)
-#define UART_MC_CLS_MSK (0x03)
-#define UART_MC_CLS_OFST (0)
-#define UART_MC_CLS_CHARLEN_5 (0)
-#define UART_MC_CLS_CHARLEN_6 (1)
-#define UART_MC_CLS_CHARLEN_7 (2)
-#define UART_MC_CLS_CHARLEN_8 (3)
-
-#define UART_MCR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x2c ))
-#define UART_MCR_AC_MSK (0x80)
-#define UART_MCR_AC_OFST (7)
-#define UART_MCR_AR_MSK (0x40)
-#define UART_MCR_AR_OFST (6)
-#define UART_MCR_BR_MSK (0x20)
-#define UART_MCR_BR_OFST (5)
-#define UART_MCR_LB_MSK (0x10)
-#define UART_MCR_LB_OFST (4)
-#define UART_MCR_DCD_MSK (0x08)
-#define UART_MCR_DCD_OFST (3)
-#define UART_MCR_RI_MSK (0x04)
-#define UART_MCR_RI_OFST (2)
-#define UART_MCR_DTR_MSK (0x02)
-#define UART_MCR_DTR_OFST (1)
-#define UART_MCR_RTS_MSK (0x01)
-#define UART_MCR_RTS_OFST (0)
-
-#define UART_MSR(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x30 ))
-#define UART_MSR_DCD_MSK (0x80)
-#define UART_MSR_DCD_OFST (7)
-#define UART_MSR_RI_MSK (0x40)
-#define UART_MSR_RI_OFST (6)
-#define UART_MSR_DSR_MSK (0x20)
-#define UART_MSR_DSR_OFST (5)
-#define UART_MSR_CTS_MSK (0x10)
-#define UART_MSR_CTS_OFST (4)
-#define UART_MSR_DDCD_MSK (0x08)
-#define UART_MSR_DDCD_OFST (3)
-#define UART_MSR_TERI_MSK (0x04)
-#define UART_MSR_TERI_OFST (2)
-#define UART_MSR_DDSR_MSK (0x02)
-#define UART_MSR_DDSR_OFST (1)
-#define UART_MSR_DCTS_MSK (0x01)
-#define UART_MSR_DCTS_OFST (0)
-
-#define UART_DIV_LO(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x34 ))
-#define UART_DIV_LO_DIV_MSK (0xff)
-#define UART_DIV_LO_DIV_OFST (0)
-
-#define UART_DIV_HI(BASE_ADDR) (UART00_TYPE (BASE_ADDR + 0x38 ))
-#define UART_DIV_HI_DIV_MSK (0xff)
-#define UART_DIV_HI_DIV_OFST (0)
-
-#endif /* __UART00_H */
diff --git a/include/asm-arm/arch-epxa10db/uncompress.h b/include/asm-arm/arch-epxa10db/uncompress.h
deleted file mode 100644
index fdfe0e6848f8..000000000000
--- a/include/asm-arm/arch-epxa10db/uncompress.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/include/asm-arm/arch-epxa10db/uncompress.h
- *
- * Copyright (C) 1999 ARM Limited
- * Copyright (C) 2001 Altera Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "asm/arch/platform.h"
-#include "asm/hardware.h"
-#define UART00_TYPE (volatile unsigned int*)
-#include "asm/arch/uart00.h"
-
-/*
- * This does not append a newline
- */
-static void putstr(const char *s)
-{
- while (*s) {
- while ((*UART_TSR(EXC_UART00_BASE) &
- UART_TSR_TX_LEVEL_MSK)==15)
- barrier();
-
- *UART_TD(EXC_UART00_BASE) = *s;
-
- if (*s == '\n') {
- while ((*UART_TSR(EXC_UART00_BASE) &
- UART_TSR_TX_LEVEL_MSK)==15)
- barrier();
-
- *UART_TD(EXC_UART00_BASE) = '\r';
- }
- s++;
- }
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-imx/dma.h b/include/asm-arm/arch-imx/dma.h
index dbdc01780413..b45fa367d71e 100644
--- a/include/asm-arm/arch-imx/dma.h
+++ b/include/asm-arm/arch-imx/dma.h
@@ -20,10 +20,6 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-#define MAX_DMA_ADDRESS 0xffffffff
-
-#define MAX_DMA_CHANNELS 0
-
/*
* DMA registration
*/
diff --git a/include/asm-arm/arch-imx/entry-macro.S b/include/asm-arm/arch-imx/entry-macro.S
index b40ea7cf88ec..3b9ef6914627 100644
--- a/include/asm-arm/arch-imx/entry-macro.S
+++ b/include/asm-arm/arch-imx/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+
.macro disable_fiq
.endm
#define AITC_NIVECSR 0x40
diff --git a/include/asm-arm/arch-integrator/debug-macro.S b/include/asm-arm/arch-integrator/debug-macro.S
index 484a1aa47098..031d30941791 100644
--- a/include/asm-arm/arch-integrator/debug-macro.S
+++ b/include/asm-arm/arch-integrator/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
-#include <asm/hardware/amba_serial.h>
+#include <linux/amba/serial.h>
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
diff --git a/include/asm-arm/arch-integrator/dma.h b/include/asm-arm/arch-integrator/dma.h
index 7171792290bd..83fd6bbaf9d3 100644
--- a/include/asm-arm/arch-integrator/dma.h
+++ b/include/asm-arm/arch-integrator/dma.h
@@ -17,12 +17,3 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
-
diff --git a/include/asm-arm/arch-integrator/entry-macro.S b/include/asm-arm/arch-integrator/entry-macro.S
index 44f7ee613194..69838d04f90b 100644
--- a/include/asm-arm/arch-integrator/entry-macro.S
+++ b/include/asm-arm/arch-integrator/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop3xx/dma.h
index 797f9e6fc745..1e808db8af2a 100644
--- a/include/asm-arm/arch-iop3xx/dma.h
+++ b/include/asm-arm/arch-iop3xx/dma.h
@@ -7,10 +7,3 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-
-#ifndef _IOP3XX_DMA_H_P
-#define _IOP3XX_DMA_H_P
-
-#define MAX_DMA_ADDRESS 0xffffffff
-
-#endif /* _ASM_ARCH_DMA_H_P */
diff --git a/include/asm-arm/arch-iop3xx/entry-macro.S b/include/asm-arm/arch-iop3xx/entry-macro.S
index e2ce7f5467c8..926668c098a5 100644
--- a/include/asm-arm/arch-iop3xx/entry-macro.S
+++ b/include/asm-arm/arch-iop3xx/entry-macro.S
@@ -7,6 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/arch/irqs.h>
#if defined(CONFIG_ARCH_IOP321)
.macro disable_fiq
diff --git a/include/asm-arm/arch-ixp2000/dma.h b/include/asm-arm/arch-ixp2000/dma.h
index 0fb3568a98dd..548d8dc507eb 100644
--- a/include/asm-arm/arch-ixp2000/dma.h
+++ b/include/asm-arm/arch-ixp2000/dma.h
@@ -7,12 +7,3 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-
-/* No DMA */
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ixp2000/enp2611.h b/include/asm-arm/arch-ixp2000/enp2611.h
index 95128d9f5026..42f3c28dc5c4 100644
--- a/include/asm-arm/arch-ixp2000/enp2611.h
+++ b/include/asm-arm/arch-ixp2000/enp2611.h
@@ -36,5 +36,11 @@
#define ENP2611_GPIO_SCL 7
#define ENP2611_GPIO_SDA 6
+#define IRQ_ENP2611_THERMAL IRQ_IXP2000_GPIO4
+#define IRQ_ENP2611_OPTION_BOARD IRQ_IXP2000_GPIO3
+#define IRQ_ENP2611_CALEB IRQ_IXP2000_GPIO2
+#define IRQ_ENP2611_PM3386_1 IRQ_IXP2000_GPIO1
+#define IRQ_ENP2611_PM3386_0 IRQ_IXP2000_GPIO0
+
#endif
diff --git a/include/asm-arm/arch-ixp2000/entry-macro.S b/include/asm-arm/arch-ixp2000/entry-macro.S
index e3a4e4121298..16e1e6124b31 100644
--- a/include/asm-arm/arch-ixp2000/entry-macro.S
+++ b/include/asm-arm/arch-ixp2000/entry-macro.S
@@ -7,6 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/arch/irqs.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
index 7fbcdf9931ee..c0ff2c6c66e7 100644
--- a/include/asm-arm/arch-ixp2000/io.h
+++ b/include/asm-arm/arch-ixp2000/io.h
@@ -131,102 +131,4 @@
#endif
-#ifdef CONFIG_ARCH_IXDP2X01
-/*
- * This is an ugly hack but the CS8900 on the 2x01's does not sit in any sort
- * of "I/O space" and is just direct mapped into a 32-bit-only addressable
- * bus. The address space for this bus is such that we can't really easily
- * make it contiguous to the PCI I/O address range, and it also does not
- * need swapping like PCI addresses do (IXDP2x01 is a BE platform).
- * B/C of this we can't use the standard in/out functions and need to
- * runtime check if the incoming address is a PCI address or for
- * the CS89x0.
- */
-#undef inw
-#undef outw
-#undef insw
-#undef outsw
-
-#include <asm/mach-types.h>
-
-static inline void insw(u32 ptr, void *buf, int length)
-{
- register volatile u32 *port = (volatile u32 *)ptr;
-
- /*
- * Is this cycle meant for the CS8900?
- */
- if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
- ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
- u8 *buf8 = (u8*)buf;
- register u32 tmp32;
-
- do {
- tmp32 = *port;
- *buf8++ = (u8)tmp32;
- *buf8++ = (u8)(tmp32 >> 8);
- } while(--length);
-
- return;
- }
-
- __raw_readsw(alignw(___io(ptr)),buf,length);
-}
-
-static inline void outsw(u32 ptr, void *buf, int length)
-{
- register volatile u32 *port = (volatile u32 *)ptr;
-
- /*
- * Is this cycle meant for the CS8900?
- */
- if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
- ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
- register u32 tmp32;
- u8 *buf8 = (u8*)buf;
- do {
- tmp32 = *buf8++;
- tmp32 |= (*buf8++) << 8;
- *port = tmp32;
- } while(--length);
- return;
- }
-
- __raw_writesw(alignw(___io(ptr)),buf,length);
-}
-
-
-static inline u16 inw(u32 ptr)
-{
- register volatile u32 *port = (volatile u32 *)ptr;
-
- /*
- * Is this cycle meant for the CS8900?
- */
- if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
- ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
- return (u16)(*port);
- }
-
- return __raw_readw(alignw(___io(ptr)));
-}
-
-static inline void outw(u16 value, u32 ptr)
-{
- register volatile u32 *port = (volatile u32 *)ptr;
-
- if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
- ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
- *port = value;
- return;
- }
-
- __raw_writew((value),alignw(___io(ptr)));
-}
-#endif /* IXDP2x01 */
-
#endif
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index fc5ac6aec4f2..2b57f91b4ebd 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -26,6 +26,8 @@
* fc000000 da000000 16M PCI CFG0
* fd000000 d8000000 16M PCI I/O
* fe[0-7]00000 8M per-platform mappings
+ * fe900000 80000000 1M SRAM #0 (first MB)
+ * fea00000 cb400000 1M SCRATCH ring get/put
* feb00000 c8000000 1M MSF
* fec00000 df000000 1M PCI CSRs
* fed00000 de000000 1M PCI CREG
@@ -91,6 +93,14 @@
#define IXP2000_MSF_VIRT_BASE 0xfeb00000
#define IXP2000_MSF_SIZE 0x00100000
+#define IXP2000_SCRATCH_RING_PHYS_BASE 0xcb400000
+#define IXP2000_SCRATCH_RING_VIRT_BASE 0xfea00000
+#define IXP2000_SCRATCH_RING_SIZE 0x00100000
+
+#define IXP2000_SRAM0_PHYS_BASE 0x80000000
+#define IXP2000_SRAM0_VIRT_BASE 0xfe900000
+#define IXP2000_SRAM0_SIZE 0x00100000
+
#define IXP2000_PCI_IO_PHYS_BASE 0xd8000000
#define IXP2000_PCI_IO_VIRT_BASE 0xfd000000
#define IXP2000_PCI_IO_SIZE 0x01000000
@@ -156,6 +166,14 @@
#define IXP2000_IRQ_THD_RAW_STATUS_B_1 IXP2000_INTCTL_REG(0x84)
#define IXP2000_IRQ_THD_RAW_STATUS_B_2 IXP2000_INTCTL_REG(0x88)
#define IXP2000_IRQ_THD_RAW_STATUS_B_3 IXP2000_INTCTL_REG(0x8c)
+#define IXP2000_IRQ_THD_STATUS_A_0 IXP2000_INTCTL_REG(0xe0)
+#define IXP2000_IRQ_THD_STATUS_A_1 IXP2000_INTCTL_REG(0xe4)
+#define IXP2000_IRQ_THD_STATUS_A_2 IXP2000_INTCTL_REG(0xe8)
+#define IXP2000_IRQ_THD_STATUS_A_3 IXP2000_INTCTL_REG(0xec)
+#define IXP2000_IRQ_THD_STATUS_B_0 IXP2000_INTCTL_REG(0x100)
+#define IXP2000_IRQ_THD_STATUS_B_1 IXP2000_INTCTL_REG(0x104)
+#define IXP2000_IRQ_THD_STATUS_B_2 IXP2000_INTCTL_REG(0x108)
+#define IXP2000_IRQ_THD_STATUS_B_3 IXP2000_INTCTL_REG(0x10c)
#define IXP2000_IRQ_THD_ENABLE_SET_A_0 IXP2000_INTCTL_REG(0x160)
#define IXP2000_IRQ_THD_ENABLE_SET_A_1 IXP2000_INTCTL_REG(0x164)
#define IXP2000_IRQ_THD_ENABLE_SET_A_2 IXP2000_INTCTL_REG(0x168)
diff --git a/include/asm-arm/arch-ixp4xx/coyote.h b/include/asm-arm/arch-ixp4xx/coyote.h
index dd0c2d2d8503..7ac9ba2c035c 100644
--- a/include/asm-arm/arch-ixp4xx/coyote.h
+++ b/include/asm-arm/arch-ixp4xx/coyote.h
@@ -16,9 +16,6 @@
#error "Do not include this directly, instead #include <asm/hardware.h>"
#endif
-#define COYOTE_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define COYOTE_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE * 2
-
/* PCI controller GPIO to IRQ pin mappings */
#define COYOTE_PCI_SLOT0_PIN 6
#define COYOTE_PCI_SLOT1_PIN 11
@@ -26,7 +23,7 @@
#define COYOTE_PCI_SLOT0_DEVID 14
#define COYOTE_PCI_SLOT1_DEVID 15
-#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_CS3_BASE_PHYS
+#define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_BASE(3)
#define COYOTE_IDE_BASE_VIRT 0xFFFE1000
#define COYOTE_IDE_REGION_SIZE 0x1000
diff --git a/include/asm-arm/arch-ixp4xx/dma.h b/include/asm-arm/arch-ixp4xx/dma.h
index 312065dc0e7a..b1a071ecebc8 100644
--- a/include/asm-arm/arch-ixp4xx/dma.h
+++ b/include/asm-arm/arch-ixp4xx/dma.h
@@ -20,7 +20,4 @@
#define MAX_DMA_ADDRESS (PAGE_OFFSET + SZ_64M)
-/* No DMA */
-#define MAX_DMA_CHANNELS 0
-
#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-ixp4xx/entry-macro.S b/include/asm-arm/arch-ixp4xx/entry-macro.S
index 323b0bc4a39c..27e124132e4c 100644
--- a/include/asm-arm/arch-ixp4xx/entry-macro.S
+++ b/include/asm-arm/arch-ixp4xx/entry-macro.S
@@ -7,6 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-ixp4xx/gtwx5715.h b/include/asm-arm/arch-ixp4xx/gtwx5715.h
index fc460af70627..c3069d67c00e 100644
--- a/include/asm-arm/arch-ixp4xx/gtwx5715.h
+++ b/include/asm-arm/arch-ixp4xx/gtwx5715.h
@@ -57,10 +57,6 @@
#define GTWX5715_GPIO13_IRQ IRQ_IXP4XX_SW_INT1
#define GTWX5715_GPIO14_IRQ IRQ_IXP4XX_SW_INT2
-
-#define GTWX5715_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define GTWX5715_FLASH_SIZE (0x00800000)
-
/* PCI controller GPIO to IRQ pin mappings
INTA INTB
diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h
index cfb413c845f7..6acb69c95ef9 100644
--- a/include/asm-arm/arch-ixp4xx/hardware.h
+++ b/include/asm-arm/arch-ixp4xx/hardware.h
@@ -45,5 +45,6 @@ extern unsigned int processor_id;
#include "coyote.h"
#include "prpmc1100.h"
#include "nslu2.h"
+#include "nas100d.h"
#endif /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-ixp4xx/irqs.h b/include/asm-arm/arch-ixp4xx/irqs.h
index 2cf4930372bc..f24b763ca18e 100644
--- a/include/asm-arm/arch-ixp4xx/irqs.h
+++ b/include/asm-arm/arch-ixp4xx/irqs.h
@@ -100,4 +100,13 @@
#define IRQ_NSLU2_PCI_INTB IRQ_IXP4XX_GPIO10
#define IRQ_NSLU2_PCI_INTC IRQ_IXP4XX_GPIO9
+/*
+ * NAS100D board IRQs
+ */
+#define IRQ_NAS100D_PCI_INTA IRQ_IXP4XX_GPIO11
+#define IRQ_NAS100D_PCI_INTB IRQ_IXP4XX_GPIO10
+#define IRQ_NAS100D_PCI_INTC IRQ_IXP4XX_GPIO9
+#define IRQ_NAS100D_PCI_INTD IRQ_IXP4XX_GPIO8
+#define IRQ_NAS100D_PCI_INTE IRQ_IXP4XX_GPIO7
+
#endif
diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h
index 7d21bf941379..3d3820d7ba09 100644
--- a/include/asm-arm/arch-ixp4xx/ixdp425.h
+++ b/include/asm-arm/arch-ixp4xx/ixdp425.h
@@ -16,9 +16,6 @@
#error "Do not include this directly, instead #include <asm/hardware.h>"
#endif
-#define IXDP425_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define IXDP425_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE
-
#define IXDP425_SDA_PIN 7
#define IXDP425_SCL_PIN 6
diff --git a/include/asm-arm/arch-ixp4xx/memory.h b/include/asm-arm/arch-ixp4xx/memory.h
index e024d0a1a669..ee211d28a3ef 100644
--- a/include/asm-arm/arch-ixp4xx/memory.h
+++ b/include/asm-arm/arch-ixp4xx/memory.h
@@ -16,31 +16,10 @@
#ifndef __ASSEMBLY__
-/*
- * Only first 64MB of memory can be accessed via PCI.
- * We use GFP_DMA to allocate safe buffers to do map/unmap.
- * This is really ugly and we need a better way of specifying
- * DMA-capable regions of memory.
- */
-static inline void __arch_adjust_zones(int node, unsigned long *zone_size,
- unsigned long *zhole_size)
-{
- unsigned int sz = SZ_64M >> PAGE_SHIFT;
-
- /*
- * Only adjust if > 64M on current system
- */
- if (node || (zone_size[0] <= sz))
- return;
-
- zone_size[1] = zone_size[0] - sz;
- zone_size[0] = sz;
- zhole_size[1] = zhole_size[0];
- zhole_size[0] = 0;
-}
+void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes);
#define arch_adjust_zones(node, size, holes) \
- __arch_adjust_zones(node, size, holes)
+ ixp4xx_adjust_zones(node, size, holes)
#define ISA_DMA_THRESHOLD (SZ_64M - 1)
diff --git a/include/asm-arm/arch-ixp4xx/nas100d.h b/include/asm-arm/arch-ixp4xx/nas100d.h
new file mode 100644
index 000000000000..51ac0180427c
--- /dev/null
+++ b/include/asm-arm/arch-ixp4xx/nas100d.h
@@ -0,0 +1,72 @@
+/*
+ * include/asm-arm/arch-ixp4xx/nas100d.h
+ *
+ * NAS100D platform specific definitions
+ *
+ * Copyright (c) 2005 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * based on ixdp425.h:
+ * Copyright 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H__
+#error "Do not include this directly, instead #include <asm/hardware.h>"
+#endif
+
+#define NAS100D_SDA_PIN 6
+#define NAS100D_SCL_PIN 5
+
+/*
+ * NAS100D PCI IRQs
+ */
+#define NAS100D_PCI_MAX_DEV 3
+#define NAS100D_PCI_IRQ_LINES 3
+
+
+/* PCI controller GPIO to IRQ pin mappings */
+#define NAS100D_PCI_INTA_PIN 11
+#define NAS100D_PCI_INTB_PIN 10
+#define NAS100D_PCI_INTC_PIN 9
+#define NAS100D_PCI_INTD_PIN 8
+#define NAS100D_PCI_INTE_PIN 7
+
+/* GPIO */
+
+#define NAS100D_GPIO0 0
+#define NAS100D_GPIO1 1
+#define NAS100D_GPIO2 2
+#define NAS100D_GPIO3 3
+#define NAS100D_GPIO4 4
+#define NAS100D_GPIO5 5
+#define NAS100D_GPIO6 6
+#define NAS100D_GPIO7 7
+#define NAS100D_GPIO8 8
+#define NAS100D_GPIO9 9
+#define NAS100D_GPIO10 10
+#define NAS100D_GPIO11 11
+#define NAS100D_GPIO12 12
+#define NAS100D_GPIO13 13
+#define NAS100D_GPIO14 14
+#define NAS100D_GPIO15 15
+
+
+/* Buttons */
+
+#define NAS100D_PB_GPIO NAS100D_GPIO14
+#define NAS100D_RB_GPIO NAS100D_GPIO4
+#define NAS100D_PO_GPIO NAS100D_GPIO12 /* power off */
+
+#define NAS100D_PB_IRQ IRQ_IXP4XX_GPIO14
+#define NAS100D_RB_IRQ IRQ_IXP4XX_GPIO4
+
+/*
+#define NAS100D_PB_BM (1L << NAS100D_PB_GPIO)
+#define NAS100D_PO_BM (1L << NAS100D_PO_GPIO)
+#define NAS100D_RB_BM (1L << NAS100D_RB_GPIO)
+*/
diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h
index b8b347a559c7..4281838873ef 100644
--- a/include/asm-arm/arch-ixp4xx/nslu2.h
+++ b/include/asm-arm/arch-ixp4xx/nslu2.h
@@ -18,9 +18,6 @@
#error "Do not include this directly, instead #include <asm/hardware.h>"
#endif
-#define NSLU2_FLASH_BASE IXP4XX_EXP_BUS_CS0_BASE_PHYS
-#define NSLU2_FLASH_SIZE IXP4XX_EXP_BUS_CSX_REGION_SIZE
-
#define NSLU2_SDA_PIN 7
#define NSLU2_SCL_PIN 6
diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
index f14ed63590c3..daf9790645ca 100644
--- a/include/asm-arm/arch-ixp4xx/platform.h
+++ b/include/asm-arm/arch-ixp4xx/platform.h
@@ -26,16 +26,17 @@
*/
#define IXP4XX_EXP_BUS_BASE_PHYS (0x50000000)
-#define IXP4XX_EXP_BUS_CSX_REGION_SIZE (0x01000000)
+/*
+ * The expansion bus on the IXP4xx can be configured for either 16 or
+ * 32MB windows and the CS offset for each region changes based on the
+ * current configuration. This means that we cannot simply hardcode
+ * each offset. ixp4xx_sys_init() looks at the expansion bus configuration
+ * as setup by the bootloader to determine our window size.
+ */
+extern unsigned long ixp4xx_exp_bus_size;
-#define IXP4XX_EXP_BUS_CS0_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x00000000)
-#define IXP4XX_EXP_BUS_CS1_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x01000000)
-#define IXP4XX_EXP_BUS_CS2_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x02000000)
-#define IXP4XX_EXP_BUS_CS3_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x03000000)
-#define IXP4XX_EXP_BUS_CS4_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x04000000)
-#define IXP4XX_EXP_BUS_CS5_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x05000000)
-#define IXP4XX_EXP_BUS_CS6_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x06000000)
-#define IXP4XX_EXP_BUS_CS7_BASE_PHYS (IXP4XX_EXP_BUS_BASE_PHYS + 0x07000000)
+#define IXP4XX_EXP_BUS_BASE(region)\
+ (IXP4XX_EXP_BUS_BASE_PHYS + ((region) * ixp4xx_exp_bus_size))
#define IXP4XX_FLASH_WRITABLE (0x2)
#define IXP4XX_FLASH_DEFAULT (0xbcd23c40)
@@ -112,10 +113,5 @@ static inline void gpio_line_set(u8 line, int value)
*IXP4XX_GPIO_GPOUTR &= ~(1 << line);
}
-static inline void gpio_line_isr_clear(u8 line)
-{
- *IXP4XX_GPIO_GPISR = (1 << line);
-}
-
#endif // __ASSEMBLY__
diff --git a/include/asm-arm/arch-l7200/dma.h b/include/asm-arm/arch-l7200/dma.h
index 6595b386cfc9..4c7eca63f035 100644
--- a/include/asm-arm/arch-l7200/dma.h
+++ b/include/asm-arm/arch-l7200/dma.h
@@ -17,7 +17,6 @@
* bytes of RAM.
*/
#define MAX_DMA_ADDRESS 0xd0000000
-#define MAX_DMA_CHANNELS 0
#define DMA_S0 0
diff --git a/include/asm-arm/arch-l7200/system.h b/include/asm-arm/arch-l7200/system.h
index cb4ff29059b8..18825cf071ba 100644
--- a/include/asm-arm/arch-l7200/system.h
+++ b/include/asm-arm/arch-l7200/system.h
@@ -12,6 +12,8 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
+#include <asm/hardware.h>
+
static inline void arch_idle(void)
{
*(unsigned long *)(IO_BASE + 0x50004) = 1; /* idle mode */
diff --git a/include/asm-arm/arch-lh7a40x/dma.h b/include/asm-arm/arch-lh7a40x/dma.h
index 5797f01e1844..15492e3253f6 100644
--- a/include/asm-arm/arch-lh7a40x/dma.h
+++ b/include/asm-arm/arch-lh7a40x/dma.h
@@ -7,11 +7,3 @@
* version 2 as published by the Free Software Foundation.
*
*/
-
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0 /* All DMA is internal to CPU */
-
-#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-lh7a40x/entry-macro.S b/include/asm-arm/arch-lh7a40x/entry-macro.S
index 865f396aa63c..a2f67c06d9c9 100644
--- a/include/asm-arm/arch-lh7a40x/entry-macro.S
+++ b/include/asm-arm/arch-lh7a40x/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
# if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
# error "LH7A400 and LH7A404 are mutually exclusive"
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 740c297eb11c..46a0402696de 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -38,8 +38,6 @@ struct clk {
struct clk_functions {
int (*clk_enable)(struct clk *clk);
void (*clk_disable)(struct clk *clk);
- int (*clk_use)(struct clk *clk);
- void (*clk_unuse)(struct clk *clk);
long (*clk_round_rate)(struct clk *clk, unsigned long rate);
int (*clk_set_rate)(struct clk *clk, unsigned long rate);
int (*clk_set_parent)(struct clk *clk, struct clk *parent);
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index ccbcb580a5c1..d4e73efcb816 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -21,9 +21,6 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0
-
/* Hardware registers for omap1 */
#define OMAP_DMA_BASE (0xfffed800)
#define OMAP_DMA_GCR (OMAP_DMA_BASE + 0x400)
diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S
index f8814a84910e..0ffb1185f1ac 100644
--- a/include/asm-arm/arch-omap/entry-macro.S
+++ b/include/asm-arm/arch-omap/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
#if defined(CONFIG_ARCH_OMAP1)
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h
index 9af415d2944a..6724a81bd10b 100644
--- a/include/asm-arm/arch-omap/system.h
+++ b/include/asm-arm/arch-omap/system.h
@@ -5,8 +5,9 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
#include <linux/config.h>
+#include <linux/clk.h>
+
#include <asm/mach-types.h>
-#include <asm/hardware/clock.h>
#include <asm/hardware.h>
#include <asm/arch/prcm.h>
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index 56db3d49bfc8..3e88a2a02a0f 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -12,11 +12,6 @@
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
-#define MAX_DMA_ADDRESS 0xffffffff
-
-/* No DMA as the rest of the world see it */
-#define MAX_DMA_CHANNELS 0
-
/*
* Descriptor structure for PXA's DMA engine
* Note: this structure must always be aligned to a 16-byte boundary.
diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S
index 2abfc8bb3ee5..4985e33afc12 100644
--- a/include/asm-arm/arch-pxa/entry-macro.S
+++ b/include/asm-arm/arch-pxa/entry-macro.S
@@ -7,6 +7,8 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-pxa/ohci.h b/include/asm-arm/arch-pxa/ohci.h
new file mode 100644
index 000000000000..7da89569061e
--- /dev/null
+++ b/include/asm-arm/arch-pxa/ohci.h
@@ -0,0 +1,18 @@
+#ifndef ASMARM_ARCH_OHCI_H
+#define ASMARM_ARCH_OHCI_H
+
+struct device;
+
+struct pxaohci_platform_data {
+ int (*init)(struct device *);
+ void (*exit)(struct device *);
+
+ int port_mode;
+#define PMM_NPS_MODE 1
+#define PMM_GLOBAL_MODE 2
+#define PMM_PERPORT_MODE 3
+};
+
+extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
+
+#endif
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index a75a2470f4f5..1409c5bd703f 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -108,6 +108,7 @@
#define DCSR_STARTINTR (1 << 1) /* Start Interrupt (read / write) */
#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt (read / write) */
+#define DALGN __REG(0x400000a0) /* DMA Alignment Register */
#define DINT __REG(0x400000f0) /* DMA Interrupt Register */
#define DRCMR(n) __REG2(0x40000100, (n)<<2)
@@ -1614,8 +1615,21 @@
#define SSCR0_National (0x2 << 4) /* National Microwire */
#define SSCR0_ECS (1 << 6) /* External clock select */
#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */
+#if defined(CONFIG_PXA25x)
#define SSCR0_SCR (0x0000ff00) /* Serial Clock Rate (mask) */
#define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */
+#elif defined(CONFIG_PXA27x)
+#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */
+#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */
+#define SSCR0_EDSS (1 << 20) /* Extended data size select */
+#define SSCR0_NCS (1 << 21) /* Network clock select */
+#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */
+#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */
+#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */
+#define SSCR0_SlotsPerFrm(c) ((x) - 1) /* Time slots per frame [1..8] */
+#define SSCR0_ADC (1 << 30) /* Audio clock select */
+#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */
+#endif
#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */
#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */
@@ -2042,6 +2056,18 @@
#ifdef CONFIG_PXA27x
+#define ARB_CNTRL __REG(0x48000048) /* Arbiter Control Register */
+
+#define ARB_DMA_SLV_PARK (1<<31) /* Be parked with DMA slave when idle */
+#define ARB_CI_PARK (1<<30) /* Be parked with Camera Interface when idle */
+#define ARB_EX_MEM_PARK (1<<29) /* Be parked with external MEMC when idle */
+#define ARB_INT_MEM_PARK (1<<28) /* Be parked with internal MEMC when idle */
+#define ARB_USB_PARK (1<<27) /* Be parked with USB when idle */
+#define ARB_LCD_PARK (1<<26) /* Be parked with LCD when idle */
+#define ARB_DMA_PARK (1<<25) /* Be parked with DMA when idle */
+#define ARB_CORE_PARK (1<<24) /* Be parked with core when idle */
+#define ARB_LOCK_FLAG (1<<23) /* Only Locking masters gain access to the bus */
+
/*
* Keypad
*/
diff --git a/include/asm-arm/arch-realview/debug-macro.S b/include/asm-arm/arch-realview/debug-macro.S
index ed28bd012236..017ad996848d 100644
--- a/include/asm-arm/arch-realview/debug-macro.S
+++ b/include/asm-arm/arch-realview/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
-#include <asm/hardware/amba_serial.h>
+#include <linux/amba/serial.h>
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
diff --git a/include/asm-arm/arch-realview/dma.h b/include/asm-arm/arch-realview/dma.h
index 744491a74bd9..8342e3f9d6ec 100644
--- a/include/asm-arm/arch-realview/dma.h
+++ b/include/asm-arm/arch-realview/dma.h
@@ -18,10 +18,3 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S
index 6288fad0dc41..1a6eec86bd47 100644
--- a/include/asm-arm/arch-realview/entry-macro.S
+++ b/include/asm-arm/arch-realview/entry-macro.S
@@ -7,7 +7,7 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
-
+#include <asm/hardware.h>
#include <asm/hardware/gic.h>
.macro disable_fiq
diff --git a/include/asm-arm/arch-rpc/entry-macro.S b/include/asm-arm/arch-rpc/entry-macro.S
index 686f413f82d6..c9e5395e5106 100644
--- a/include/asm-arm/arch-rpc/entry-macro.S
+++ b/include/asm-arm/arch-rpc/entry-macro.S
@@ -1,3 +1,3 @@
-
+#include <asm/hardware.h>
#include <asm/hardware/entry-macro-iomd.S>
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index e830a40e573a..b011e14f3bc6 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -31,14 +31,6 @@
#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
-/* according to the samsung port, we cannot use the regular
- * dma channels... we must therefore provide our own interface
- * for DMA, and allow our drivers to use that.
- */
-
-#define MAX_DMA_CHANNELS 0
-
-
/* we have 4 dma channels */
#define S3C2410_DMA_CHANNELS (4)
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index b7d4d7f4422d..cc06b1bd37b2 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -10,6 +10,8 @@
* Modifications:
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
*/
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
diff --git a/include/asm-arm/arch-sa1100/dma.h b/include/asm-arm/arch-sa1100/dma.h
index 3d60ed9f8c34..02575d72ac6b 100644
--- a/include/asm-arm/arch-sa1100/dma.h
+++ b/include/asm-arm/arch-sa1100/dma.h
@@ -15,20 +15,6 @@
/*
- * This is the maximum DMA address that can be DMAd to.
- */
-#define MAX_DMA_ADDRESS 0xffffffff
-
-
-/*
- * The regular generic DMA interface is inappropriate for the
- * SA1100 DMA model. None of the SA1100 specific drivers using
- * DMA are portable anyway so it's pointless to try to twist the
- * regular DMA API to accommodate them.
- */
-#define MAX_DMA_CHANNELS 0
-
-/*
* The SA1100 has six internal DMA channels.
*/
#define SA1100_DMA_CHANNELS 6
diff --git a/include/asm-arm/arch-versatile/debug-macro.S b/include/asm-arm/arch-versatile/debug-macro.S
index 89e38ac1444e..ef6167116dbb 100644
--- a/include/asm-arm/arch-versatile/debug-macro.S
+++ b/include/asm-arm/arch-versatile/debug-macro.S
@@ -11,7 +11,7 @@
*
*/
-#include <asm/hardware/amba_serial.h>
+#include <linux/amba/serial.h>
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
diff --git a/include/asm-arm/arch-versatile/dma.h b/include/asm-arm/arch-versatile/dma.h
index dcc8ac26eac0..642577348623 100644
--- a/include/asm-arm/arch-versatile/dma.h
+++ b/include/asm-arm/arch-versatile/dma.h
@@ -18,10 +18,3 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#define MAX_DMA_ADDRESS 0xffffffff
-#define MAX_DMA_CHANNELS 0
-
-#endif /* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-versatile/entry-macro.S b/include/asm-arm/arch-versatile/entry-macro.S
index 90e4e970d253..feff771c0a0a 100644
--- a/include/asm-arm/arch-versatile/entry-macro.S
+++ b/include/asm-arm/arch-versatile/entry-macro.S
@@ -7,7 +7,10 @@
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
- .macro disable_fiq
+#include <asm/hardware.h>
+#include <asm/hardware/vic.h>
+
+ .macro disable_fiq
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
index cbdd9fb96332..72ef874567d5 100644
--- a/include/asm-arm/arch-versatile/platform.h
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -293,26 +293,7 @@
* VERSATILE_SYS_IC
*
*/
-#define VIC_IRQ_STATUS 0
-#define VIC_FIQ_STATUS 0x04
-#define VIC_IRQ_RAW_STATUS 0x08
-#define VIC_INT_SELECT 0x0C /* 1 = FIQ, 0 = IRQ */
-#define VIC_IRQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
-#define VIC_IRQ_ENABLE_CLEAR 0x14
-#define VIC_IRQ_SOFT 0x18
-#define VIC_IRQ_SOFT_CLEAR 0x1C
-#define VIC_PROTECT 0x20
-#define VIC_VECT_ADDR 0x30
-#define VIC_DEF_VECT_ADDR 0x34
-#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */
-#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */
-#define VIC_ITCR 0x300 /* VIC test control register */
-
-#define VIC_FIQ_RAW_STATUS 0x08
-#define VIC_FIQ_ENABLE 0x10 /* 1 = enable, 0 = disable */
-#define VIC_FIQ_ENABLE_CLEAR 0x14
-#define VIC_FIQ_SOFT 0x18
-#define VIC_FIQ_SOFT_CLEAR 0x1C
+/* VIC definitions in include/asm-arm/hardware/vic.h */
#define SIC_IRQ_STATUS 0
#define SIC_IRQ_RAW_STATUS 0x04
@@ -325,8 +306,6 @@
#define SIC_INT_PIC_ENABLES 0x20 /* set interrupt pass through bits */
#define SIC_INT_PIC_ENABLEC 0x24 /* Clear interrupt pass through bits */
-#define VICVectCntl_Enable (1 << 5)
-
/* ------------------------------------------------------------------------
* Interrupts - bit assignment (primary)
* ------------------------------------------------------------------------
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index d586f65c8228..3d7283d84405 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -175,6 +175,8 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#endif /* __LINUX_ARM_ARCH__ */
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
@@ -205,5 +207,6 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif
#endif
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 7399d431edfe..d02de721ecc1 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -332,6 +332,7 @@ static inline unsigned long __ffs(unsigned long word)
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
/*
* ffs: find first bit set. This is defined the same way as
@@ -351,6 +352,7 @@ static inline unsigned long __ffs(unsigned long word)
#define fls(x) \
( __builtin_constant_p(x) ? generic_fls(x) : \
({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
+#define fls64(x) generic_fls64(x)
#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
#define __ffs(x) (ffs(x) - 1)
#define ffz(x) __ffs( ~(x) )
diff --git a/include/asm-arm/byteorder.h b/include/asm-arm/byteorder.h
index d648a1915c33..17eaf8bdf092 100644
--- a/include/asm-arm/byteorder.h
+++ b/include/asm-arm/byteorder.h
@@ -15,9 +15,32 @@
#ifndef __ASM_ARM_BYTEORDER_H
#define __ASM_ARM_BYTEORDER_H
-
+#include <linux/compiler.h>
#include <asm/types.h>
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+ __u32 t;
+
+ if (__builtin_constant_p(x)) {
+ t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */
+ } else {
+ /*
+ * The compiler needs a bit of a hint here to always do the
+ * right thing and not screw it up to different degrees
+ * depending on the gcc version.
+ */
+ asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
+ }
+ x = (x << 24) | (x >> 8); /* mov r0,r0,ror #8 */
+ t &= ~0x00FF0000; /* bic r1,r1,#0x00FF0000 */
+ x ^= (t >> 8); /* eor r0,r0,r1,lsr #8 */
+
+ return x;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+
#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
# define __BYTEORDER_HAS_U64__
# define __SWAB_64_THRU_32__
diff --git a/include/asm-arm/cache.h b/include/asm-arm/cache.h
index 8d161f7c87ff..31332c8ac04e 100644
--- a/include/asm-arm/cache.h
+++ b/include/asm-arm/cache.h
@@ -7,9 +7,4 @@
#define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-/*
- * largest L1 which this arch supports
- */
-#define L1_CACHE_SHIFT_MAX 5
-
#endif
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index e81baff4f54b..09e19a783a51 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -14,7 +14,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
-#include <asm/mman.h>
#include <asm/glue.h>
#include <asm/shmparam.h>
diff --git a/include/asm-arm/dma.h b/include/asm-arm/dma.h
index ef41df43a584..49c01e2bf7c8 100644
--- a/include/asm-arm/dma.h
+++ b/include/asm-arm/dma.h
@@ -10,6 +10,13 @@ typedef unsigned int dmach_t;
#include <asm/arch/dma.h>
/*
+ * This is the maximum virtual address which can be DMA'd from.
+ */
+#ifndef MAX_DMA_ADDRESS
+#define MAX_DMA_ADDRESS 0xffffffff
+#endif
+
+/*
* DMA modes
*/
typedef unsigned int dmamode_t;
@@ -91,7 +98,9 @@ extern void set_dma_sg(dmach_t channel, struct scatterlist *sg, int nr_sg);
* especially since some DMA architectures don't update the
* DMA address immediately, but defer it to the enable_dma().
*/
-extern void set_dma_addr(dmach_t channel, unsigned long physaddr);
+extern void __set_dma_addr(dmach_t channel, void *addr);
+#define set_dma_addr(channel, addr) \
+ __set_dma_addr(channel, bus_to_virt(addr))
/* Set the DMA byte count for this channel
*
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-arm/futex.h
+++ b/include/asm-arm/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-arm/hardware/sharpsl_pm.h b/include/asm-arm/hardware/sharpsl_pm.h
new file mode 100644
index 000000000000..36983e5f3665
--- /dev/null
+++ b/include/asm-arm/hardware/sharpsl_pm.h
@@ -0,0 +1,94 @@
+/*
+ * SharpSL Battery/PM Driver
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/interrupt.h>
+
+struct sharpsl_charger_machinfo {
+ void (*init)(void);
+ void (*exit)(void);
+ int gpio_acin;
+ int gpio_batfull;
+ int gpio_batlock;
+ int gpio_fatal;
+ void (*discharge)(int);
+ void (*discharge1)(int);
+ void (*charge)(int);
+ void (*measure_temp)(int);
+ void (*presuspend)(void);
+ void (*postsuspend)(void);
+ unsigned long (*read_devdata)(int);
+#define SHARPSL_BATT_VOLT 1
+#define SHARPSL_BATT_TEMP 2
+#define SHARPSL_ACIN_VOLT 3
+#define SHARPSL_STATUS_ACIN 4
+#define SHARPSL_STATUS_LOCK 5
+#define SHARPSL_STATUS_CHRGFULL 6
+#define SHARPSL_STATUS_FATAL 7
+ unsigned long (*charger_wakeup)(void);
+ int (*should_wakeup)(unsigned int resume_on_alarm);
+ int bat_levels;
+ struct battery_thresh *bat_levels_noac;
+ struct battery_thresh *bat_levels_acin;
+ int status_high_acin;
+ int status_low_acin;
+ int status_high_noac;
+ int status_low_noac;
+};
+
+struct battery_thresh {
+ int voltage;
+ int percentage;
+};
+
+struct battery_stat {
+ int ac_status; /* APM AC Present/Not Present */
+ int mainbat_status; /* APM Main Battery Status */
+ int mainbat_percent; /* Main Battery Percentage Charge */
+ int mainbat_voltage; /* Main Battery Voltage */
+};
+
+struct sharpsl_pm_status {
+ struct device *dev;
+ struct timer_list ac_timer;
+ struct timer_list chrg_full_timer;
+
+ int charge_mode;
+#define CHRG_ERROR (-1)
+#define CHRG_OFF (0)
+#define CHRG_ON (1)
+#define CHRG_DONE (2)
+
+ unsigned int flags;
+#define SHARPSL_SUSPENDED (1 << 0) /* Device is Suspended */
+#define SHARPSL_ALARM_ACTIVE (1 << 1) /* Alarm is for charging event (not user) */
+#define SHARPSL_BL_LIMIT (1 << 2) /* Backlight Intensity Limited */
+#define SHARPSL_APM_QUEUED (1 << 3) /* APM Event Queued */
+#define SHARPSL_DO_OFFLINE_CHRG (1 << 4) /* Trigger the offline charger */
+
+ int full_count;
+ unsigned long charge_start_time;
+ struct sharpsl_charger_machinfo *machinfo;
+ struct battery_stat battstat;
+};
+
+extern struct sharpsl_pm_status sharpsl_pm;
+
+
+#define SHARPSL_LED_ERROR 2
+#define SHARPSL_LED_ON 1
+#define SHARPSL_LED_OFF 0
+
+void sharpsl_battery_kick(void);
+void sharpsl_pm_led(int val);
+irqreturn_t sharpsl_ac_isr(int irq, void *dev_id, struct pt_regs *fp);
+irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id, struct pt_regs *fp);
+irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id, struct pt_regs *fp);
+
diff --git a/include/asm-arm/hardware/vic.h b/include/asm-arm/hardware/vic.h
new file mode 100644
index 000000000000..81825eb54c9e
--- /dev/null
+++ b/include/asm-arm/hardware/vic.h
@@ -0,0 +1,45 @@
+/*
+ * linux/include/asm-arm/hardware/vic.h
+ *
+ * Copyright (c) ARM Limited 2003. 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 __ASM_ARM_HARDWARE_VIC_H
+#define __ASM_ARM_HARDWARE_VIC_H
+
+#define VIC_IRQ_STATUS 0x00
+#define VIC_FIQ_STATUS 0x04
+#define VIC_RAW_STATUS 0x08
+#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */
+#define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */
+#define VIC_INT_ENABLE_CLEAR 0x14
+#define VIC_INT_SOFT 0x18
+#define VIC_INT_SOFT_CLEAR 0x1c
+#define VIC_PROTECT 0x20
+#define VIC_VECT_ADDR 0x30
+#define VIC_DEF_VECT_ADDR 0x34
+
+#define VIC_VECT_ADDR0 0x100 /* 0 to 15 */
+#define VIC_VECT_CNTL0 0x200 /* 0 to 15 */
+#define VIC_ITCR 0x300 /* VIC test control register */
+
+#define VIC_VECT_CNTL_ENABLE (1 << 5)
+
+#ifndef __ASSEMBLY__
+void vic_init(void __iomem *base, u32 vic_sources);
+#endif
+
+#endif
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 0cf4d4f99600..fd0147e52dbb 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -56,7 +56,12 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
/*
* Architecture ioremap implementation.
+ *
+ * __ioremap takes CPU physical address.
+ *
+ * __ioremap_pfn takes a Page Frame Number and an offset into that page
*/
+extern void __iomem * __ioremap_pfn(unsigned long, unsigned long, size_t, unsigned long);
extern void __iomem * __ioremap(unsigned long, size_t, unsigned long);
extern void __iounmap(void __iomem *addr);
@@ -261,6 +266,7 @@ out:
*
* ioremap takes a PCI memory address, as specified in
* Documentation/IO-mapping.txt.
+ *
*/
#ifndef __arch_ioremap
#define ioremap(cookie,size) __ioremap(cookie,size,0)
diff --git a/include/asm-arm/ioctl.h b/include/asm-arm/ioctl.h
index 2cbb7d0e9dc6..b279fe06dfe5 100644
--- a/include/asm-arm/ioctl.h
+++ b/include/asm-arm/ioctl.h
@@ -1,74 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMARM_IOCTL_H
-#define _ASMARM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASMARM_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
index 59975ee43cf1..7772432d3fd7 100644
--- a/include/asm-arm/irq.h
+++ b/include/asm-arm/irq.h
@@ -25,10 +25,14 @@ extern void disable_irq_nosync(unsigned int);
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
-#define __IRQT_FALEDGE (1 << 0)
-#define __IRQT_RISEDGE (1 << 1)
-#define __IRQT_LOWLVL (1 << 2)
-#define __IRQT_HIGHLVL (1 << 3)
+/*
+ * These correspond with the SA_TRIGGER_* defines, and therefore the
+ * IRQRESOURCE_IRQ_* defines.
+ */
+#define __IRQT_RISEDGE (1 << 0)
+#define __IRQT_FALEDGE (1 << 1)
+#define __IRQT_HIGHLVL (1 << 2)
+#define __IRQT_LOWLVL (1 << 3)
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE)
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h
index eb262e078c46..2cd57b4d64d9 100644
--- a/include/asm-arm/mach/arch.h
+++ b/include/asm-arm/mach/arch.h
@@ -10,6 +10,8 @@
#ifndef __ASSEMBLY__
+#include <linux/compiler.h>
+
struct tag;
struct meminfo;
struct sys_timer;
@@ -20,7 +22,7 @@ struct machine_desc {
* by assembler code in head-armv.S
*/
unsigned int nr; /* architecture number */
- unsigned int phys_ram; /* start of physical ram */
+ unsigned int __deprecated phys_ram; /* start of physical ram */
unsigned int phys_io; /* start of physical io */
unsigned int io_pg_offst; /* byte offset for io
* page tabe entry */
diff --git a/include/asm-arm/mach/dma.h b/include/asm-arm/mach/dma.h
index 31bf716106ee..e7c4a20aad53 100644
--- a/include/asm-arm/mach/dma.h
+++ b/include/asm-arm/mach/dma.h
@@ -25,13 +25,15 @@ struct dma_ops {
};
struct dma_struct {
+ void *addr; /* single DMA address */
+ unsigned long count; /* single DMA size */
struct scatterlist buf; /* single DMA */
int sgcount; /* number of DMA SG */
struct scatterlist *sg; /* DMA Scatter-Gather List */
unsigned int active:1; /* Transfer active */
unsigned int invalid:1; /* Address/Count changed */
- unsigned int using_sg:1; /* using scatter list? */
+
dmamode_t dma_mode; /* DMA mode */
int speed; /* DMA speed */
diff --git a/include/asm-arm/mach/map.h b/include/asm-arm/mach/map.h
index b338936bde4f..3351b77fab36 100644
--- a/include/asm-arm/mach/map.h
+++ b/include/asm-arm/mach/map.h
@@ -27,9 +27,6 @@ struct meminfo;
#define MT_ROM 6
#define MT_IXP2000_DEVICE 7
-#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
-#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
-
extern void create_memmap_holes(struct meminfo *);
extern void memtable_init(struct meminfo *);
extern void iotable_init(struct map_desc *, int);
diff --git a/include/asm-arm/mach/serial_at91rm9200.h b/include/asm-arm/mach/serial_at91rm9200.h
new file mode 100644
index 000000000000..98f4b0cb883c
--- /dev/null
+++ b/include/asm-arm/mach/serial_at91rm9200.h
@@ -0,0 +1,36 @@
+/*
+ * linux/include/asm-arm/mach/serial_at91rm9200.h
+ *
+ * Based on serial_sa1100.h by Nicolas Pitre
+ *
+ * Copyright (C) 2002 ATMEL Rousset
+ *
+ * Low level machine dependent UART functions.
+ */
+#include <linux/config.h>
+
+struct uart_port;
+
+/*
+ * This is a temporary structure for registering these
+ * functions; it is intended to be discarded after boot.
+ */
+struct at91rm9200_port_fns {
+ void (*set_mctrl)(struct uart_port *, u_int);
+ u_int (*get_mctrl)(struct uart_port *);
+ void (*enable_ms)(struct uart_port *);
+ void (*pm)(struct uart_port *, u_int, u_int);
+ int (*set_wake)(struct uart_port *, u_int);
+ int (*open)(struct uart_port *);
+ void (*close)(struct uart_port *);
+};
+
+#if defined(CONFIG_SERIAL_AT91)
+void at91_register_uart_fns(struct at91rm9200_port_fns *fns);
+void at91_register_uart(int idx, int port);
+#else
+#define at91_register_uart_fns(fns) do { } while (0)
+#define at91_register_uart(idx,port) do { } while (0)
+#endif
+
+
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index 3e572364ee73..b4e1146ab682 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -25,6 +25,7 @@
#include <linux/config.h>
#include <linux/compiler.h>
#include <asm/arch/memory.h>
+#include <asm/sizes.h>
#ifndef TASK_SIZE
/*
@@ -48,6 +49,14 @@
#endif
/*
+ * Size of DMA-consistent memory region. Must be multiple of 2M,
+ * between 2MB and 14MB inclusive.
+ */
+#ifndef CONSISTENT_DMA_SIZE
+#define CONSISTENT_DMA_SIZE SZ_2M
+#endif
+
+/*
* Physical vs virtual RAM address space conversion. These are
* private definitions which should NOT be used outside memory.h
* files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
@@ -58,6 +67,12 @@
#endif
/*
+ * Convert a physical address to a Page Frame Number and back
+ */
+#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT)
+#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
+
+/*
* The module space lives between the addresses given by TASK_SIZE
* and PAGE_OFFSET - it must be within 32MB of the kernel text.
*/
diff --git a/include/asm-arm/mman.h b/include/asm-arm/mman.h
index 8e4f69c4fa5f..f0bebca2ac21 100644
--- a/include/asm-arm/mman.h
+++ b/include/asm-arm/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-arm/mutex.h b/include/asm-arm/mutex.h
new file mode 100644
index 000000000000..6caa59f1f595
--- /dev/null
+++ b/include/asm-arm/mutex.h
@@ -0,0 +1,128 @@
+/*
+ * include/asm-arm/mutex.h
+ *
+ * ARM optimized mutex locking primitives
+ *
+ * Please look into asm-generic/mutex-xchg.h for a formal definition.
+ */
+#ifndef _ASM_MUTEX_H
+#define _ASM_MUTEX_H
+
+#if __LINUX_ARM_ARCH__ < 6
+/* On pre-ARMv6 hardware the swp based implementation is the most efficient. */
+# include <asm-generic/mutex-xchg.h>
+#else
+
+/*
+ * Attempting to lock a mutex on ARMv6+ can be done with a bastardized
+ * atomic decrement (it is not a reliable atomic decrement but it satisfies
+ * the defined semantics for our purpose, while being smaller and faster
+ * than a real atomic decrement or atomic swap. The idea is to attempt
+ * decrementing the lock value only once. If once decremented it isn't zero,
+ * or if its store-back fails due to a dispute on the exclusive store, we
+ * simply bail out immediately through the slow path where the lock will be
+ * reattempted until it succeeds.
+ */
+#define __mutex_fastpath_lock(count, fail_fn) \
+do { \
+ int __ex_flag, __res; \
+ \
+ typecheck(atomic_t *, count); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ ( \
+ "ldrex %0, [%2] \n" \
+ "sub %0, %0, #1 \n" \
+ "strex %1, %0, [%2] \n" \
+ \
+ : "=&r" (__res), "=&r" (__ex_flag) \
+ : "r" (&(count)->counter) \
+ : "cc","memory" ); \
+ \
+ if (unlikely(__res || __ex_flag)) \
+ fail_fn(count); \
+} while (0)
+
+#define __mutex_fastpath_lock_retval(count, fail_fn) \
+({ \
+ int __ex_flag, __res; \
+ \
+ typecheck(atomic_t *, count); \
+ typecheck_fn(fastcall int (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ ( \
+ "ldrex %0, [%2] \n" \
+ "sub %0, %0, #1 \n" \
+ "strex %1, %0, [%2] \n" \
+ \
+ : "=&r" (__res), "=&r" (__ex_flag) \
+ : "r" (&(count)->counter) \
+ : "cc","memory" ); \
+ \
+ __res |= __ex_flag; \
+ if (unlikely(__res != 0)) \
+ __res = fail_fn(count); \
+ __res; \
+})
+
+/*
+ * Same trick is used for the unlock fast path. However the original value,
+ * rather than the result, is used to test for success in order to have
+ * better generated assembly.
+ */
+#define __mutex_fastpath_unlock(count, fail_fn) \
+do { \
+ int __ex_flag, __res, __orig; \
+ \
+ typecheck(atomic_t *, count); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ ( \
+ "ldrex %0, [%3] \n" \
+ "add %1, %0, #1 \n" \
+ "strex %2, %1, [%3] \n" \
+ \
+ : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag) \
+ : "r" (&(count)->counter) \
+ : "cc","memory" ); \
+ \
+ if (unlikely(__orig || __ex_flag)) \
+ fail_fn(count); \
+} while (0)
+
+/*
+ * If the unlock was done on a contended lock, or if the unlock simply fails
+ * then the mutex remains locked.
+ */
+#define __mutex_slowpath_needs_to_unlock() 1
+
+/*
+ * For __mutex_fastpath_trylock we use another construct which could be
+ * described as a "single value cmpxchg".
+ *
+ * This provides the needed trylock semantics like cmpxchg would, but it is
+ * lighter and less generic than a true cmpxchg implementation.
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ int __ex_flag, __res, __orig;
+
+ __asm__ (
+
+ "1: ldrex %0, [%3] \n"
+ "subs %1, %0, #1 \n"
+ "strexeq %2, %1, [%3] \n"
+ "movlt %0, #0 \n"
+ "cmpeq %2, #0 \n"
+ "bgt 1b \n"
+
+ : "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
+ : "r" (&count->counter)
+ : "cc", "memory" );
+
+ return __orig;
+}
+
+#endif
+#endif
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 4da1d532cbeb..416320d95419 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -170,6 +170,13 @@ extern pmd_t *top_pmd;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+/*
+ * With EABI on ARMv5 and above we must have 64-bit aligned slab pointers.
+ */
+#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5)
+#define ARCH_SLAB_MINALIGN 8
+#endif
+
#endif /* __KERNEL__ */
#include <asm-generic/page.h>
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 7d4118e09054..04f4d34c6317 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -49,6 +49,12 @@ struct thread_struct {
#define INIT_THREAD { }
+#ifdef CONFIG_MMU
+#define nommu_start_thread(regs) do { } while (0)
+#else
+#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#endif
+
#define start_thread(regs,pc,sp) \
({ \
unsigned long *stack = (unsigned long *)sp; \
@@ -65,6 +71,7 @@ struct thread_struct {
regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
regs->ARM_r0 = stack[0]; /* r0 (argc) */ \
+ nommu_start_thread(regs); \
})
/* Forward declaration, a strange C thing */
@@ -85,9 +92,11 @@ unsigned long get_wchan(struct task_struct *p);
*/
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-#define KSTK_REGS(tsk) (((struct pt_regs *)(THREAD_START_SP + (unsigned long)(tsk)->thread_info)) - 1)
-#define KSTK_EIP(tsk) KSTK_REGS(tsk)->ARM_pc
-#define KSTK_ESP(tsk) KSTK_REGS(tsk)->ARM_sp
+#define task_pt_regs(p) \
+ ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
+
+#define KSTK_EIP(tsk) task_pt_regs(tsk)->ARM_pc
+#define KSTK_ESP(tsk) task_pt_regs(tsk)->ARM_sp
/*
* Prefetching support - only ARMv5.
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 4377e22b7e1a..77adb7fa169b 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -23,6 +23,9 @@
#define PTRACE_OLDSETOPTIONS 21
#define PTRACE_GET_THREAD_AREA 22
+
+#define PTRACE_SET_SYSCALL 23
+
/*
* PSR bits
*/
@@ -60,9 +63,11 @@
#ifndef __ASSEMBLY__
-/* this struct defines the way the registers are stored on the
- stack during a system call. */
-
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call. Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
struct pt_regs {
long uregs[18];
};
diff --git a/include/asm-arm/scatterlist.h b/include/asm-arm/scatterlist.h
index 83b876fb04cc..de2f65eb42ed 100644
--- a/include/asm-arm/scatterlist.h
+++ b/include/asm-arm/scatterlist.h
@@ -9,7 +9,6 @@ struct scatterlist {
unsigned int offset; /* buffer offset */
dma_addr_t dma_address; /* dma address */
unsigned int length; /* length */
- char *__address; /* for set_dma_addr */
};
/*
diff --git a/include/asm-arm/stat.h b/include/asm-arm/stat.h
index ec4e2c2e3b47..42c0c13999d5 100644
--- a/include/asm-arm/stat.h
+++ b/include/asm-arm/stat.h
@@ -70,14 +70,7 @@ struct stat64 {
long long st_size;
unsigned long st_blksize;
-
-#if defined(__ARMEB__)
- unsigned long __pad4; /* Future possible st_blocks hi bits */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
-#else /* Must be little */
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4; /* Future possible st_blocks hi bits */
-#endif
+ unsigned long long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
unsigned long st_atime_nsec;
@@ -89,6 +82,6 @@ struct stat64 {
unsigned long st_ctime_nsec;
unsigned long long st_ino;
-} __attribute__((packed));
+};
#endif
diff --git a/include/asm-arm/statfs.h b/include/asm-arm/statfs.h
index e81f82783b87..a02e6a8c3d70 100644
--- a/include/asm-arm/statfs.h
+++ b/include/asm-arm/statfs.h
@@ -1,6 +1,42 @@
#ifndef _ASMARM_STATFS_H
#define _ASMARM_STATFS_H
-#include <asm-generic/statfs.h>
+#ifndef __KERNEL_STRICT_NAMES
+# include <linux/types.h>
+typedef __kernel_fsid_t fsid_t;
+#endif
+
+struct statfs {
+ __u32 f_type;
+ __u32 f_bsize;
+ __u32 f_blocks;
+ __u32 f_bfree;
+ __u32 f_bavail;
+ __u32 f_files;
+ __u32 f_ffree;
+ __kernel_fsid_t f_fsid;
+ __u32 f_namelen;
+ __u32 f_frsize;
+ __u32 f_spare[5];
+};
+
+/*
+ * With EABI there is 4 bytes of padding added to this structure.
+ * Let's pack it so the padding goes away to simplify dual ABI support.
+ * Note that user space does NOT have to pack this structure.
+ */
+struct statfs64 {
+ __u32 f_type;
+ __u32 f_bsize;
+ __u64 f_blocks;
+ __u64 f_bfree;
+ __u64 f_bavail;
+ __u64 f_files;
+ __u64 f_ffree;
+ __kernel_fsid_t f_fsid;
+ __u32 f_namelen;
+ __u32 f_frsize;
+ __u32 f_spare[5];
+} __attribute__ ((packed,aligned(4)));
#endif
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 5621d61ebc07..eb2de8c10515 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -168,10 +168,20 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info
#define switch_to(prev,next,last) \
do { \
- last = __switch_to(prev,prev->thread_info,next->thread_info); \
+ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
} while (0)
/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
+/*
* CPU interrupt mask handling.
*/
#if __LINUX_ARM_ARCH__ >= 6
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index 7c98557b717f..33a33cbb6329 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -96,13 +96,10 @@ static inline struct thread_info *current_thread_info(void)
extern struct thread_info *alloc_thread_info(struct task_struct *task);
extern void free_thread_info(struct thread_info *);
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
#define thread_saved_pc(tsk) \
- ((unsigned long)(pc_pointer((tsk)->thread_info->cpu_context.pc)))
+ ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))
#define thread_saved_fp(tsk) \
- ((unsigned long)((tsk)->thread_info->cpu_context.fp))
+ ((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
extern void iwmmxt_task_disable(struct thread_info *);
extern void iwmmxt_task_copy(struct thread_info *, void *);
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index d626e70faded..77430d6178ae 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -15,10 +15,12 @@
#include <linux/linkage.h>
-#if defined(__thumb__)
+#define __NR_OABI_SYSCALL_BASE 0x900000
+
+#if defined(__thumb__) || defined(__ARM_EABI__)
#define __NR_SYSCALL_BASE 0
#else
-#define __NR_SYSCALL_BASE 0x900000
+#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
#endif
/*
@@ -373,13 +375,13 @@
#define __sys1(x) __sys2(x)
#ifndef __syscall
-#if defined(__thumb__)
-#define __syscall(name) \
- "push {r7}\n\t" \
- "mov r7, #" __sys1(__NR_##name) "\n\t" \
- "swi 0\n\t" \
- "pop {r7}"
+#if defined(__thumb__) || defined(__ARM_EABI__)
+#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name;
+#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
+#define __syscall(name) "swi\t0"
#else
+#define __SYS_REG(name)
+#define __SYS_REG_LIST(regs...) regs
#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
#endif
#endif
@@ -395,33 +397,34 @@ do { \
#define _syscall0(type,name) \
type name(void) { \
+ __SYS_REG(name) \
register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : \
- : "lr"); \
+ : __SYS_REG_LIST() ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \
register long __res_r0 __asm__("r0"); \
@@ -429,8 +432,7 @@ type name(type1 arg1,type2 arg2) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0),"r" (__r1) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -438,6 +440,7 @@ type name(type1 arg1,type2 arg2) { \
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \
@@ -446,8 +449,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0),"r" (__r1),"r" (__r2) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -455,6 +457,7 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \
@@ -464,8 +467,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -473,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \
@@ -483,14 +486,15 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3),"r" (__r4) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
+ "r" (__r3), "r" (__r4) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) { \
+ __SYS_REG(name) \
register long __r0 __asm__("r0") = (long)arg1; \
register long __r1 __asm__("r1") = (long)arg2; \
register long __r2 __asm__("r2") = (long)arg3; \
@@ -502,30 +506,33 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : "r" (__r0),"r" (__r1),"r" (__r2),"r" (__r3), "r" (__r4),"r" (__r5) \
- : "lr"); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
+ "r" (__r3), "r" (__r4), "r" (__r5) ) ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
#ifdef __KERNEL__
#define __ARCH_WANT_IPC_PARSE_VERSION
-#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_STAT64
-#define __ARCH_WANT_SYS_ALARM
#define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE
-#define __ARCH_WANT_SYS_TIME
-#define __ARCH_WANT_SYS_UTIME
-#define __ARCH_WANT_SYS_SOCKETCALL
#define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE
-#define __ARCH_WANT_SYS_OLD_GETRLIMIT
-#define __ARCH_WANT_SYS_OLDUMOUNT
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
+
+#if !defined(CONFIG_AEABI) || defined(CONFIG_OABI_COMPAT)
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_SYS_SOCKETCALL
+#endif
#endif
#ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-arm26/atomic.h b/include/asm-arm26/atomic.h
index a47cadc59686..1552c8653990 100644
--- a/include/asm-arm26/atomic.h
+++ b/include/asm-arm26/atomic.h
@@ -76,6 +76,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -118,5 +120,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif
#endif
diff --git a/include/asm-arm26/bitops.h b/include/asm-arm26/bitops.h
index 7d062fb2e343..15cc6f2da792 100644
--- a/include/asm-arm26/bitops.h
+++ b/include/asm-arm26/bitops.h
@@ -259,6 +259,7 @@ static inline unsigned long __ffs(unsigned long word)
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
/*
* ffs: find first bit set. This is defined the same way as
diff --git a/include/asm-arm26/cache.h b/include/asm-arm26/cache.h
index f52ca1b808cd..8c3abcf728fe 100644
--- a/include/asm-arm26/cache.h
+++ b/include/asm-arm26/cache.h
@@ -4,7 +4,8 @@
#ifndef __ASMARM_CACHE_H
#define __ASMARM_CACHE_H
-#define L1_CACHE_BYTES 32
+#define L1_CACHE_SHIFT 5
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
#define SMP_CACHE_BYTES L1_CACHE_BYTES
diff --git a/include/asm-arm26/futex.h b/include/asm-arm26/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-arm26/futex.h
+++ b/include/asm-arm26/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-arm26/ioctl.h b/include/asm-arm26/ioctl.h
index 2cbb7d0e9dc6..b279fe06dfe5 100644
--- a/include/asm-arm26/ioctl.h
+++ b/include/asm-arm26/ioctl.h
@@ -1,74 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMARM_IOCTL_H
-#define _ASMARM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASMARM_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-arm26/mman.h b/include/asm-arm26/mman.h
index cc27b8240265..0ed7780541fa 100644
--- a/include/asm-arm26/mman.h
+++ b/include/asm-arm26/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h
index f23fac1938f3..ca4ccfc4b578 100644
--- a/include/asm-arm26/system.h
+++ b/include/asm-arm26/system.h
@@ -111,10 +111,20 @@ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info
#define switch_to(prev,next,last) \
do { \
- last = __switch_to(prev,prev->thread_info,next->thread_info); \
+ last = __switch_to(prev,task_thread_info(prev),task_thread_info(next)); \
} while (0)
/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
+/*
* Save the current interrupt enable state & disable IRQs
*/
#define local_irq_save(x) \
diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
index aff3e5699c64..9b367ebe515d 100644
--- a/include/asm-arm26/thread_info.h
+++ b/include/asm-arm26/thread_info.h
@@ -80,20 +80,16 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *)(sp & ~0x1fff);
}
-/* FIXME - PAGE_SIZE < 32K */
-#define THREAD_SIZE (8*32768) // FIXME - this needs attention (see kernel/fork.c which gets a nice div by zero if this is lower than 8*32768
-#define __get_user_regs(x) (((struct pt_regs *)((unsigned long)(x) + THREAD_SIZE - 8)) - 1)
+#define THREAD_SIZE PAGE_SIZE
+#define task_pt_regs(task) ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE - 8) - 1)
extern struct thread_info *alloc_thread_info(struct task_struct *task);
extern void free_thread_info(struct thread_info *);
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
#define thread_saved_pc(tsk) \
- ((unsigned long)(pc_pointer((tsk)->thread_info->cpu_context.pc)))
+ ((unsigned long)(pc_pointer(task_thread_info(tsk)->cpu_context.pc)))
#define thread_saved_fp(tsk) \
- ((unsigned long)((tsk)->thread_info->cpu_context.fp))
+ ((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
#else /* !__ASSEMBLY__ */
diff --git a/include/asm-cris/arch-v10/cache.h b/include/asm-cris/arch-v10/cache.h
index 1d1d1ba65b1a..aea27184d2d2 100644
--- a/include/asm-cris/arch-v10/cache.h
+++ b/include/asm-cris/arch-v10/cache.h
@@ -4,6 +4,5 @@
/* Etrax 100LX have 32-byte cache-lines. */
#define L1_CACHE_BYTES 32
#define L1_CACHE_SHIFT 5
-#define L1_CACHE_SHIFT_MAX 5
#endif /* _ASM_ARCH_CACHE_H */
diff --git a/include/asm-cris/arch-v10/processor.h b/include/asm-cris/arch-v10/processor.h
index e23df8dc96e8..cc692c7a0660 100644
--- a/include/asm-cris/arch-v10/processor.h
+++ b/include/asm-cris/arch-v10/processor.h
@@ -40,7 +40,7 @@ struct thread_struct {
#define KSTK_EIP(tsk) \
({ \
unsigned long eip = 0; \
- unsigned long regs = (unsigned long)user_regs(tsk); \
+ unsigned long regs = (unsigned long)task_pt_regs(tsk); \
if (regs > PAGE_SIZE && \
virt_addr_valid(regs)) \
eip = ((struct pt_regs *)regs)->irp; \
diff --git a/include/asm-cris/arch-v32/cache.h b/include/asm-cris/arch-v32/cache.h
index 4fed8d62ccc8..80b236b15319 100644
--- a/include/asm-cris/arch-v32/cache.h
+++ b/include/asm-cris/arch-v32/cache.h
@@ -4,6 +4,5 @@
/* A cache-line is 32 bytes. */
#define L1_CACHE_BYTES 32
#define L1_CACHE_SHIFT 5
-#define L1_CACHE_SHIFT_MAX 5
#endif /* _ASM_CRIS_ARCH_CACHE_H */
diff --git a/include/asm-cris/arch-v32/processor.h b/include/asm-cris/arch-v32/processor.h
index 8c939bf27987..32bf2e538ced 100644
--- a/include/asm-cris/arch-v32/processor.h
+++ b/include/asm-cris/arch-v32/processor.h
@@ -36,7 +36,7 @@ struct thread_struct {
#define KSTK_EIP(tsk) \
({ \
unsigned long eip = 0; \
- unsigned long regs = (unsigned long)user_regs(tsk); \
+ unsigned long regs = (unsigned long)task_pt_regs(tsk); \
if (regs > PAGE_SIZE && virt_addr_valid(regs)) \
eip = ((struct pt_regs *)regs)->erp; \
eip; \
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h
index 683b05a57d88..0b51a87e5532 100644
--- a/include/asm-cris/atomic.h
+++ b/include/asm-cris/atomic.h
@@ -136,6 +136,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -156,4 +158,5 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index 1bddb3f3a289..d3eb0f1e4208 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -240,6 +240,7 @@ static inline int test_bit(int nr, const volatile unsigned long *addr)
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
/*
* hweightN - returns the hamming weight of a N-bit word
diff --git a/include/asm-cris/dma-mapping.h b/include/asm-cris/dma-mapping.h
index 8eff51349ae7..cbf1a98f0129 100644
--- a/include/asm-cris/dma-mapping.h
+++ b/include/asm-cris/dma-mapping.h
@@ -153,7 +153,7 @@ dma_set_mask(struct device *dev, u64 mask)
static inline int
dma_get_cache_alignment(void)
{
- return (1 << L1_CACHE_SHIFT_MAX);
+ return (1 << INTERNODE_CACHE_SHIFT);
}
#define dma_is_consistent(d) (1)
diff --git a/include/asm-cris/futex.h b/include/asm-cris/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-cris/futex.h
+++ b/include/asm-cris/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-cris/ioctl.h b/include/asm-cris/ioctl.h
index be2d8f667a38..b279fe06dfe5 100644
--- a/include/asm-cris/ioctl.h
+++ b/include/asm-cris/ioctl.h
@@ -1,83 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- *
- * This is the same as the i386 version.
- */
-
-#ifndef _ASMCRIS_IOCTL_H
-#define _ASMCRIS_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#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 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)))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASMCRIS_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-cris/mman.h b/include/asm-cris/mman.h
index 8570e72b9502..5a382b8bf3f7 100644
--- a/include/asm-cris/mman.h
+++ b/include/asm-cris/mman.h
@@ -37,6 +37,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-cris/mutex.h b/include/asm-cris/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-cris/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h
index dce41009eeb0..961e2bceadbc 100644
--- a/include/asm-cris/processor.h
+++ b/include/asm-cris/processor.h
@@ -45,7 +45,8 @@ struct task_struct;
* Dito but for the currently running task
*/
-#define current_regs() user_regs(current->thread_info)
+#define task_pt_regs(task) user_regs(task_thread_info(task))
+#define current_regs() task_pt_regs(current)
static inline void prepare_to_copy(struct task_struct *tsk)
{
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index cef0140fc104..7ad853c3f74e 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -69,8 +69,6 @@ struct thread_info {
/* thread information allocation */
#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h
index f6539ff569c5..a59f684b4f33 100644
--- a/include/asm-frv/atomic.h
+++ b/include/asm-frv/atomic.h
@@ -218,51 +218,12 @@ extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsig
__typeof__(*(ptr)) __xg_orig; \
\
switch (sizeof(__xg_orig)) { \
- case 1: \
- asm volatile( \
- "0: \n" \
- " orcc gr0,gr0,gr0,icc3 \n" \
- " ckeq icc3,cc7 \n" \
- " ldub.p %M0,%1 \n" \
- " orcr cc7,cc7,cc3 \n" \
- " cstb.p %2,%M0 ,cc3,#1 \n" \
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
- " beq icc3,#0,0b \n" \
- : "+U"(*__xg_ptr), "=&r"(__xg_orig) \
- : "r"(x) \
- : "memory", "cc7", "cc3", "icc3" \
- ); \
- break; \
- \
- case 2: \
- asm volatile( \
- "0: \n" \
- " orcc gr0,gr0,gr0,icc3 \n" \
- " ckeq icc3,cc7 \n" \
- " lduh.p %M0,%1 \n" \
- " orcr cc7,cc7,cc3 \n" \
- " csth.p %2,%M0 ,cc3,#1 \n" \
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
- " beq icc3,#0,0b \n" \
- : "+U"(*__xg_ptr), "=&r"(__xg_orig) \
- : "r"(x) \
- : "memory", "cc7", "cc3", "icc3" \
- ); \
- break; \
- \
case 4: \
asm volatile( \
- "0: \n" \
- " orcc gr0,gr0,gr0,icc3 \n" \
- " ckeq icc3,cc7 \n" \
- " ld.p %M0,%1 \n" \
- " orcr cc7,cc7,cc3 \n" \
- " cst.p %2,%M0 ,cc3,#1 \n" \
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
- " beq icc3,#0,0b \n" \
- : "+U"(*__xg_ptr), "=&r"(__xg_orig) \
+ "swap%I0 %2,%M0" \
+ : "+m"(*__xg_ptr), "=&r"(__xg_orig) \
: "r"(x) \
- : "memory", "cc7", "cc3", "icc3" \
+ : "memory" \
); \
break; \
\
@@ -277,8 +238,6 @@ extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsig
#else
-extern uint8_t __xchg_8 (uint8_t i, volatile void *v);
-extern uint16_t __xchg_16(uint16_t i, volatile void *v);
extern uint32_t __xchg_32(uint32_t i, volatile void *v);
#define xchg(ptr, x) \
@@ -287,8 +246,6 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
__typeof__(*(ptr)) __xg_orig; \
\
switch (sizeof(__xg_orig)) { \
- case 1: __xg_orig = (__typeof__(*(ptr))) __xchg_8 ((uint8_t) x, __xg_ptr); break; \
- case 2: __xg_orig = (__typeof__(*(ptr))) __xchg_16((uint16_t) x, __xg_ptr); break; \
case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr); break; \
default: \
__xg_orig = 0; \
@@ -318,46 +275,6 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
__typeof__(*(ptr)) __xg_new = (new); \
\
switch (sizeof(__xg_orig)) { \
- case 1: \
- asm volatile( \
- "0: \n" \
- " orcc gr0,gr0,gr0,icc3 \n" \
- " ckeq icc3,cc7 \n" \
- " ldub.p %M0,%1 \n" \
- " orcr cc7,cc7,cc3 \n" \
- " sub%I4 %1,%4,%2 \n" \
- " sllcc %2,#24,gr0,icc0 \n" \
- " bne icc0,#0,1f \n" \
- " cstb.p %3,%M0 ,cc3,#1 \n" \
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
- " beq icc3,#0,0b \n" \
- "1: \n" \
- : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
- : "r"(__xg_new), "NPr"(__xg_test) \
- : "memory", "cc7", "cc3", "icc3", "icc0" \
- ); \
- break; \
- \
- case 2: \
- asm volatile( \
- "0: \n" \
- " orcc gr0,gr0,gr0,icc3 \n" \
- " ckeq icc3,cc7 \n" \
- " lduh.p %M0,%1 \n" \
- " orcr cc7,cc7,cc3 \n" \
- " sub%I4 %1,%4,%2 \n" \
- " sllcc %2,#16,gr0,icc0 \n" \
- " bne icc0,#0,1f \n" \
- " csth.p %3,%M0 ,cc3,#1 \n" \
- " corcc gr29,gr29,gr0 ,cc3,#1 \n" \
- " beq icc3,#0,0b \n" \
- "1: \n" \
- : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \
- : "r"(__xg_new), "NPr"(__xg_test) \
- : "memory", "cc7", "cc3", "icc3", "icc0" \
- ); \
- break; \
- \
case 4: \
asm volatile( \
"0: \n" \
@@ -388,8 +305,6 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
#else
-extern uint8_t __cmpxchg_8 (uint8_t *v, uint8_t test, uint8_t new);
-extern uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new);
extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
#define cmpxchg(ptr, test, new) \
@@ -400,8 +315,6 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
__typeof__(*(ptr)) __xg_new = (new); \
\
switch (sizeof(__xg_orig)) { \
- case 1: __xg_orig = __cmpxchg_8 (__xg_ptr, __xg_test, __xg_new); break; \
- case 2: __xg_orig = __cmpxchg_16(__xg_ptr, __xg_test, __xg_new); break; \
case 4: __xg_orig = __cmpxchg_32(__xg_ptr, __xg_test, __xg_new); break; \
default: \
__xg_orig = 0; \
@@ -414,7 +327,8 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
#endif
-#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -424,6 +338,8 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);
c = old; \
c != (u); \
})
+
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+#include <asm-generic/atomic.h>
#endif /* _ASM_ATOMIC_H */
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index b664bd5b6663..02be7b3a8a83 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -228,6 +228,7 @@ found_middle:
\
bit ? 33 - bit : bit; \
})
+#define fls64(x) generic_fls64(x)
/*
* Every architecture must define this function. It's the fastest
diff --git a/include/asm-frv/bug.h b/include/asm-frv/bug.h
index 074c0d5770eb..451712cc3060 100644
--- a/include/asm-frv/bug.h
+++ b/include/asm-frv/bug.h
@@ -12,6 +12,7 @@
#define _ASM_BUG_H
#include <linux/config.h>
+#include <linux/linkage.h>
#ifdef CONFIG_BUG
/*
diff --git a/include/asm-frv/dma-mapping.h b/include/asm-frv/dma-mapping.h
index 5003e017fd1e..e9fc1d47797e 100644
--- a/include/asm-frv/dma-mapping.h
+++ b/include/asm-frv/dma-mapping.h
@@ -23,7 +23,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t
* returns, or alternatively stop on the first sg_dma_len(sg) which
* is 0.
*/
-#define sg_dma_address(sg) ((unsigned long) (page_to_phys((sg)->page) + (sg)->offset))
+#define sg_dma_address(sg) ((sg)->dma_address)
#define sg_dma_len(sg) ((sg)->length)
/*
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h
index 9feff4ce1424..fca9d90e32c9 100644
--- a/include/asm-frv/futex.h
+++ b/include/asm-frv/futex.h
@@ -7,47 +7,7 @@
#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;
-}
+extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
#endif
#endif
diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h
index 48829f727242..075369b1a34b 100644
--- a/include/asm-frv/io.h
+++ b/include/asm-frv/io.h
@@ -18,6 +18,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
+#include <linux/types.h>
#include <asm/virtconvert.h>
#include <asm/string.h>
#include <asm/mb-regs.h>
@@ -104,6 +105,8 @@ static inline void __insl(unsigned long addr, void *buf, int len, int swap)
__insl_sw(addr, buf, len);
}
+#define mmiowb() mb()
+
/*
* make the short names macros so specific devices
* can override them as required
@@ -209,6 +212,10 @@ static inline uint32_t readl(const volatile void __iomem *addr)
return ret;
}
+#define readb_relaxed readb
+#define readw_relaxed readw
+#define readl_relaxed readl
+
static inline void writeb(uint8_t datum, volatile void __iomem *addr)
{
__builtin_write8((volatile uint8_t __force *) addr, datum);
@@ -268,11 +275,106 @@ static inline void __iomem *ioremap_fullcache(unsigned long physaddr, unsigned l
extern void iounmap(void __iomem *addr);
+static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ return (void __iomem *) port;
+}
+
+static inline void ioport_unmap(void __iomem *p)
+{
+}
+
static inline void flush_write_buffers(void)
{
__asm__ __volatile__ ("membar" : : :"memory");
}
+/*
+ * do appropriate I/O accesses for token type
+ */
+static inline unsigned int ioread8(void __iomem *p)
+{
+ return __builtin_read8(p);
+}
+
+static inline unsigned int ioread16(void __iomem *p)
+{
+ uint16_t ret = __builtin_read16(p);
+ if (__is_PCI_addr(p))
+ ret = _swapw(ret);
+ return ret;
+}
+
+static inline unsigned int ioread32(void __iomem *p)
+{
+ uint32_t ret = __builtin_read32(p);
+ if (__is_PCI_addr(p))
+ ret = _swapl(ret);
+ return ret;
+}
+
+static inline void iowrite8(u8 val, void __iomem *p)
+{
+ __builtin_write8(p, val);
+ if (__is_PCI_MEM(p))
+ __flush_PCI_writes();
+}
+
+static inline void iowrite16(u16 val, void __iomem *p)
+{
+ if (__is_PCI_addr(p))
+ val = _swapw(val);
+ __builtin_write16(p, val);
+ if (__is_PCI_MEM(p))
+ __flush_PCI_writes();
+}
+
+static inline void iowrite32(u32 val, void __iomem *p)
+{
+ if (__is_PCI_addr(p))
+ val = _swapl(val);
+ __builtin_write32(p, val);
+ if (__is_PCI_MEM(p))
+ __flush_PCI_writes();
+}
+
+static inline void ioread8_rep(void __iomem *p, void *dst, unsigned long count)
+{
+ io_insb((unsigned long) p, dst, count);
+}
+
+static inline void ioread16_rep(void __iomem *p, void *dst, unsigned long count)
+{
+ io_insw((unsigned long) p, dst, count);
+}
+
+static inline void ioread32_rep(void __iomem *p, void *dst, unsigned long count)
+{
+ __insl_ns((unsigned long) p, dst, count);
+}
+
+static inline void iowrite8_rep(void __iomem *p, const void *src, unsigned long count)
+{
+ io_outsb((unsigned long) p, src, count);
+}
+
+static inline void iowrite16_rep(void __iomem *p, const void *src, unsigned long count)
+{
+ io_outsw((unsigned long) p, src, count);
+}
+
+static inline void iowrite32_rep(void __iomem *p, const void *src, unsigned long count)
+{
+ __outsl_ns((unsigned long) p, src, count);
+}
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p)
+{
+}
+
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
@@ -285,6 +387,27 @@ static inline void flush_write_buffers(void)
*/
#define xlate_dev_kmem_ptr(p) p
+/*
+ * Check BIOS signature
+ */
+static inline int check_signature(volatile void __iomem *io_addr,
+ const unsigned char *signature, int length)
+{
+ int retval = 0;
+
+ do {
+ if (readb(io_addr) != *signature)
+ goto out;
+ io_addr++;
+ signature++;
+ length--;
+ } while (length);
+
+ retval = 1;
+out:
+ return retval;
+}
+
#endif /* __KERNEL__ */
#endif /* _ASM_IO_H */
diff --git a/include/asm-frv/ioctl.h b/include/asm-frv/ioctl.h
index 8aee76905545..b279fe06dfe5 100644
--- a/include/asm-frv/ioctl.h
+++ b/include/asm-frv/ioctl.h
@@ -1,80 +1 @@
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASM_IOCTL_H
-#define _ASM_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASM_IOCTL_H */
-
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-frv/mb-regs.h b/include/asm-frv/mb-regs.h
index c8f575fc42fa..93fa732fb0cd 100644
--- a/include/asm-frv/mb-regs.h
+++ b/include/asm-frv/mb-regs.h
@@ -68,6 +68,9 @@ do { \
#define __is_PCI_MEM(addr) \
((unsigned long)(addr) - __region_PCI_MEM < 0x08000000UL)
+#define __is_PCI_addr(addr) \
+ ((unsigned long)(addr) - __region_PCI_IO < 0x0c000000UL)
+
#define __get_CLKSW() ({ *(volatile unsigned long *)(__region_CS2 + 0x0130000cUL) & 0xffUL; })
#define __get_CLKIN() (__get_CLKSW() * 125U * 100000U / 24U)
@@ -149,6 +152,7 @@ do { \
#define __is_PCI_IO(addr) 0 /* no PCI */
#define __is_PCI_MEM(addr) 0
+#define __is_PCI_addr(addr) 0
#define __region_PCI_IO 0
#define __region_PCI_MEM 0
#define __flush_PCI_writes() do { } while(0)
diff --git a/include/asm-frv/mc146818rtc.h b/include/asm-frv/mc146818rtc.h
new file mode 100644
index 000000000000..90dfb7a633d1
--- /dev/null
+++ b/include/asm-frv/mc146818rtc.h
@@ -0,0 +1,16 @@
+/* mc146818rtc.h: RTC defs
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_MC146818RTC_H
+#define _ASM_MC146818RTC_H
+
+
+#endif /* _ASM_MC146818RTC_H */
diff --git a/include/asm-frv/mman.h b/include/asm-frv/mman.h
index c684720dfbdd..8af4a41c255e 100644
--- a/include/asm-frv/mman.h
+++ b/include/asm-frv/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-frv/module.h b/include/asm-frv/module.h
index 3223cfaef743..3d5c6360289a 100644
--- a/include/asm-frv/module.h
+++ b/include/asm-frv/module.h
@@ -11,10 +11,18 @@
#ifndef _ASM_MODULE_H
#define _ASM_MODULE_H
-#define module_map(x) vmalloc(x)
-#define module_unmap(x) vfree(x)
-#define module_arch_init(x) (0)
-#define arch_init_modules(x) do { } while (0)
+struct mod_arch_specific
+{
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+/*
+ * Include the architecture version.
+ */
+#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " "
#endif /* _ASM_MODULE_H */
diff --git a/include/asm-frv/mutex.h b/include/asm-frv/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-frv/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-frv/pci.h b/include/asm-frv/pci.h
index 1168451c275f..598b0c6b695d 100644
--- a/include/asm-frv/pci.h
+++ b/include/asm-frv/pci.h
@@ -57,6 +57,14 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
*/
#define PCI_DMA_BUS_IS_PHYS (1)
+/* pci_unmap_{page,single} is a nop so... */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME) (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+#define pci_unmap_len(PTR, LEN_NAME) (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 844666377dcb..d1c3b182c691 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -421,6 +421,11 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
}
/*
+ * Macro to mark a page protection value as "uncacheable"
+ */
+#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NOCACHE))
+
+/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
diff --git a/include/asm-frv/signal.h b/include/asm-frv/signal.h
index d407bde57eca..67366894780f 100644
--- a/include/asm-frv/signal.h
+++ b/include/asm-frv/signal.h
@@ -151,7 +151,6 @@ typedef struct sigaltstack {
size_t ss_size;
} stack_t;
-extern int do_signal(struct pt_regs *regs, sigset_t *oldset);
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#ifdef __KERNEL__
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index 60f6b2aee76d..ea426abf01d3 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -110,8 +110,6 @@ register struct thread_info *__current_thread_info asm("gr15");
#endif
#define free_thread_info(info) kfree(info)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#else /* !__ASSEMBLY__ */
@@ -131,6 +129,7 @@ register struct thread_info *__current_thread_info asm("gr15");
#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_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* OOM killer killed process */
@@ -140,6 +139,7 @@ register struct thread_info *__current_thread_info asm("gr15");
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_IRET (1 << TIF_IRET)
+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
diff --git a/include/asm-frv/types.h b/include/asm-frv/types.h
index 50605df6d8ac..2560f596a75d 100644
--- a/include/asm-frv/types.h
+++ b/include/asm-frv/types.h
@@ -59,7 +59,6 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
-typedef u64 u_quad_t;
/* Dma addresses are 32-bits wide. */
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index 991b50fbba24..b6bcbe01f6ee 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -180,16 +180,16 @@ do { \
\
switch (sizeof(*(ptr))) { \
case 1: \
- __get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r"); \
+ __get_user_asm(__gu_err, *(u8*)&__gu_val, ptr, "ub", "=r"); \
break; \
case 2: \
- __get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r"); \
+ __get_user_asm(__gu_err, *(u16*)&__gu_val, ptr, "uh", "=r"); \
break; \
case 4: \
- __get_user_asm(__gu_err, __gu_val, ptr, "", "=r"); \
+ __get_user_asm(__gu_err, *(u32*)&__gu_val, ptr, "", "=r"); \
break; \
case 8: \
- __get_user_asm(__gu_err, __gu_val, ptr, "d", "=e"); \
+ __get_user_asm(__gu_err, *(u64*)&__gu_val, ptr, "d", "=e"); \
break; \
default: \
__gu_err = __get_user_bad(); \
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 5cf989b448d5..4d994d2e99e3 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -313,7 +313,7 @@ do { \
unsigned long __sr2 = (res); \
if (__builtin_expect(__sr2 >= (unsigned long)(-4095), 0)) { \
errno = (-__sr2); \
- __sr2 = ULONG_MAX; \
+ __sr2 = ~0UL; \
} \
return (type) __sr2; \
} while (0)
@@ -486,6 +486,7 @@ static inline pid_t wait(int * wait_stat)
/* #define __ARCH_WANT_SYS_SIGPENDING */
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#endif
/*
diff --git a/include/asm-frv/vga.h b/include/asm-frv/vga.h
new file mode 100644
index 000000000000..a702c800a229
--- /dev/null
+++ b/include/asm-frv/vga.h
@@ -0,0 +1,17 @@
+/* vga.h: VGA register stuff
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_VGA_H
+#define _ASM_VGA_H
+
+
+
+#endif /* _ASM_VGA_H */
diff --git a/include/asm-frv/xor.h b/include/asm-frv/xor.h
new file mode 100644
index 000000000000..c82eb12a5b18
--- /dev/null
+++ b/include/asm-frv/xor.h
@@ -0,0 +1 @@
+#include <asm-generic/xor.h>
diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h
new file mode 100644
index 000000000000..42a95d9a0641
--- /dev/null
+++ b/include/asm-generic/atomic.h
@@ -0,0 +1,117 @@
+#ifndef _ASM_GENERIC_ATOMIC_H
+#define _ASM_GENERIC_ATOMIC_H
+/*
+ * Copyright (C) 2005 Silicon Graphics, Inc.
+ * Christoph Lameter <clameter@sgi.com>
+ *
+ * Allows to provide arch independent atomic definitions without the need to
+ * edit all arch specific atomic.h files.
+ */
+
+#include <asm/types.h>
+
+/*
+ * Suppport for atomic_long_t
+ *
+ * Casts for parameters are avoided for existing atomic functions in order to
+ * avoid issues with cast-as-lval under gcc 4.x and other limitations that the
+ * macros of a platform may have.
+ */
+
+#if BITS_PER_LONG == 64
+
+typedef atomic64_t atomic_long_t;
+
+#define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i)
+
+static inline long atomic_long_read(atomic_long_t *l)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ return (long)atomic64_read(v);
+}
+
+static inline void atomic_long_set(atomic_long_t *l, long i)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ atomic64_set(v, i);
+}
+
+static inline void atomic_long_inc(atomic_long_t *l)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ atomic64_inc(v);
+}
+
+static inline void atomic_long_dec(atomic_long_t *l)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ atomic64_dec(v);
+}
+
+static inline void atomic_long_add(long i, atomic_long_t *l)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ atomic64_add(i, v);
+}
+
+static inline void atomic_long_sub(long i, atomic_long_t *l)
+{
+ atomic64_t *v = (atomic64_t *)l;
+
+ atomic64_sub(i, v);
+}
+
+#else
+
+typedef atomic_t atomic_long_t;
+
+#define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i)
+static inline long atomic_long_read(atomic_long_t *l)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ return (long)atomic_read(v);
+}
+
+static inline void atomic_long_set(atomic_long_t *l, long i)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ atomic_set(v, i);
+}
+
+static inline void atomic_long_inc(atomic_long_t *l)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ atomic_inc(v);
+}
+
+static inline void atomic_long_dec(atomic_long_t *l)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ atomic_dec(v);
+}
+
+static inline void atomic_long_add(long i, atomic_long_t *l)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ atomic_add(i, v);
+}
+
+static inline void atomic_long_sub(long i, atomic_long_t *l)
+{
+ atomic_t *v = (atomic_t *)l;
+
+ atomic_sub(i, v);
+}
+
+#endif
+#endif
diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h
index ce31b739fd80..0e6d9852008c 100644
--- a/include/asm-generic/bitops.h
+++ b/include/asm-generic/bitops.h
@@ -56,6 +56,7 @@ extern __inline__ int test_bit(int nr, const unsigned long * addr)
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#ifdef __KERNEL__
diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h
index 747d790295f3..1b356207712c 100644
--- a/include/asm-generic/dma-mapping.h
+++ b/include/asm-generic/dma-mapping.h
@@ -274,7 +274,7 @@ dma_get_cache_alignment(void)
{
/* no easy way to get cache size on all processors, so return
* the maximum possible, to be safe */
- return (1 << L1_CACHE_SHIFT_MAX);
+ return (1 << INTERNODE_CACHE_SHIFT);
}
static inline void
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
new file mode 100644
index 000000000000..3ae2c7347549
--- /dev/null
+++ b/include/asm-generic/futex.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_FUTEX_H
+#define _ASM_GENERIC_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-generic/ioctl.h b/include/asm-generic/ioctl.h
new file mode 100644
index 000000000000..cd027298beb1
--- /dev/null
+++ b/include/asm-generic/ioctl.h
@@ -0,0 +1,80 @@
+#ifndef _ASM_GENERIC_IOCTL_H
+#define _ASM_GENERIC_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms. The generic ioctl numbering scheme doesn't really enforce
+ * a type field. De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here. Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS 8
+#define _IOC_SIZEBITS 14
+#define _IOC_DIRBITS 2
+
+#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.
+ */
+#define _IOC_NONE 0U
+#define _IOC_WRITE 1U
+#define _IOC_READ 2U
+
+#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 ioctl numbers.. */
+#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)
+
+/* ...and for the drivers/sound files... */
+
+#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 /* _ASM_GENERIC_IOCTL_H */
diff --git a/include/asm-generic/mutex-dec.h b/include/asm-generic/mutex-dec.h
new file mode 100644
index 000000000000..40c6d1f86598
--- /dev/null
+++ b/include/asm-generic/mutex-dec.h
@@ -0,0 +1,110 @@
+/*
+ * asm-generic/mutex-dec.h
+ *
+ * Generic implementation of the mutex fastpath, based on atomic
+ * decrement/increment.
+ */
+#ifndef _ASM_GENERIC_MUTEX_DEC_H
+#define _ASM_GENERIC_MUTEX_DEC_H
+
+/**
+ * __mutex_fastpath_lock - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function MUST leave the value lower than
+ * 1 even when the "1" assertion wasn't true.
+ */
+#define __mutex_fastpath_lock(count, fail_fn) \
+do { \
+ if (unlikely(atomic_dec_return(count) < 0)) \
+ fail_fn(count); \
+ else \
+ smp_mb(); \
+} while (0)
+
+/**
+ * __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns.
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+ else {
+ smp_mb();
+ return 0;
+ }
+}
+
+/**
+ * __mutex_fastpath_unlock - try to promote the count from 0 to 1
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 0
+ *
+ * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
+ * In the failure case, this function is allowed to either set the value to
+ * 1, or to set it to a value lower than 1.
+ *
+ * If the implementation sets it to a value of lower than 1, then the
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+#define __mutex_fastpath_unlock(count, fail_fn) \
+do { \
+ smp_mb(); \
+ if (unlikely(atomic_inc_return(count) <= 0)) \
+ fail_fn(count); \
+} while (0)
+
+#define __mutex_slowpath_needs_to_unlock() 1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ * @count: pointer of type atomic_t
+ * @fail_fn: fallback function
+ *
+ * Change the count from 1 to a value lower than 1, and return 0 (failure)
+ * if it wasn't 1 originally, or return 1 (success) otherwise. This function
+ * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ *
+ * If the architecture has no effective trylock variant, it should call the
+ * <fail_fn> spinlock-based trylock variant unconditionally.
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ /*
+ * We have two variants here. The cmpxchg based one is the best one
+ * because it never induce a false contention state. It is included
+ * here because architectures using the inc/dec algorithms over the
+ * xchg ones are much more likely to support cmpxchg natively.
+ *
+ * If not we fall back to the spinlock based variant - that is
+ * just as efficient (and simpler) as a 'destructive' probing of
+ * the mutex state would be.
+ */
+#ifdef __HAVE_ARCH_CMPXCHG
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
+ smp_mb();
+ return 1;
+ }
+ return 0;
+#else
+ return fail_fn(count);
+#endif
+}
+
+#endif
diff --git a/include/asm-generic/mutex-null.h b/include/asm-generic/mutex-null.h
new file mode 100644
index 000000000000..5cf8b7ce0c45
--- /dev/null
+++ b/include/asm-generic/mutex-null.h
@@ -0,0 +1,24 @@
+/*
+ * asm-generic/mutex-null.h
+ *
+ * Generic implementation of the mutex fastpath, based on NOP :-)
+ *
+ * This is used by the mutex-debugging infrastructure, but it can also
+ * be used by architectures that (for whatever reason) want to use the
+ * spinlock based slowpath.
+ */
+#ifndef _ASM_GENERIC_MUTEX_NULL_H
+#define _ASM_GENERIC_MUTEX_NULL_H
+
+/* extra parameter only needed for mutex debugging: */
+#ifndef __IP__
+# define __IP__
+#endif
+
+#define __mutex_fastpath_lock(count, fail_fn) fail_fn(count __RET_IP__)
+#define __mutex_fastpath_lock_retval(count, fail_fn) fail_fn(count __RET_IP__)
+#define __mutex_fastpath_unlock(count, fail_fn) fail_fn(count __RET_IP__)
+#define __mutex_fastpath_trylock(count, fail_fn) fail_fn(count)
+#define __mutex_slowpath_needs_to_unlock() 1
+
+#endif
diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h
new file mode 100644
index 000000000000..1d24f47e6c48
--- /dev/null
+++ b/include/asm-generic/mutex-xchg.h
@@ -0,0 +1,117 @@
+/*
+ * asm-generic/mutex-xchg.h
+ *
+ * Generic implementation of the mutex fastpath, based on xchg().
+ *
+ * NOTE: An xchg based implementation is less optimal than an atomic
+ * decrement/increment based implementation. If your architecture
+ * has a reasonable atomic dec/inc then you should probably use
+ * asm-generic/mutex-dec.h instead, or you could open-code an
+ * optimized version in asm/mutex.h.
+ */
+#ifndef _ASM_GENERIC_MUTEX_XCHG_H
+#define _ASM_GENERIC_MUTEX_XCHG_H
+
+/**
+ * __mutex_fastpath_lock - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if it
+ * wasn't 1 originally. This function MUST leave the value lower than 1
+ * even when the "1" assertion wasn't true.
+ */
+#define __mutex_fastpath_lock(count, fail_fn) \
+do { \
+ if (unlikely(atomic_xchg(count, 0) != 1)) \
+ fail_fn(count); \
+ else \
+ smp_mb(); \
+} while (0)
+
+
+/**
+ * __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if it
+ * wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_xchg(count, 0) != 1))
+ return fail_fn(count);
+ else {
+ smp_mb();
+ return 0;
+ }
+}
+
+/**
+ * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 0
+ *
+ * try to promote the mutex from 0 to 1. if it wasn't 0, call <function>
+ * In the failure case, this function is allowed to either set the value to
+ * 1, or to set it to a value lower than one.
+ * If the implementation sets it to a value of lower than one, the
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+#define __mutex_fastpath_unlock(count, fail_fn) \
+do { \
+ smp_mb(); \
+ if (unlikely(atomic_xchg(count, 1) != 0)) \
+ fail_fn(count); \
+} while (0)
+
+#define __mutex_slowpath_needs_to_unlock() 0
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ * @count: pointer of type atomic_t
+ * @fail_fn: spinlock based trylock implementation
+ *
+ * Change the count from 1 to a value lower than 1, and return 0 (failure)
+ * if it wasn't 1 originally, or return 1 (success) otherwise. This function
+ * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ *
+ * If the architecture has no effective trylock variant, it should call the
+ * <fail_fn> spinlock-based trylock variant unconditionally.
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ int prev = atomic_xchg(count, 0);
+
+ if (unlikely(prev < 0)) {
+ /*
+ * The lock was marked contended so we must restore that
+ * state. If while doing so we get back a prev value of 1
+ * then we just own it.
+ *
+ * [ In the rare case of the mutex going to 1, to 0, to -1
+ * and then back to 0 in this few-instructions window,
+ * this has the potential to trigger the slowpath for the
+ * owner's unlock path needlessly, but that's not a problem
+ * in practice. ]
+ */
+ prev = atomic_xchg(count, prev);
+ if (prev < 0)
+ prev = 0;
+ }
+ smp_mb();
+
+ return prev;
+}
+
+#endif
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 094d4917c1a9..35de20cf8fac 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -10,6 +10,8 @@
#define ALIGN_FUNCTION() . = ALIGN(8)
#define RODATA \
+ . = ALIGN(4096); \
+ __start_rodata = .; \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
*(.rodata) *(.rodata.*) \
*(__vermagic) /* Kernel version magic */ \
@@ -74,6 +76,8 @@
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
*(__ksymtab_strings) \
} \
+ __end_rodata = .; \
+ . = ALIGN(4096); \
\
/* Built-in module parameters. */ \
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
diff --git a/include/asm-h8300/atomic.h b/include/asm-h8300/atomic.h
index f23d86819ea8..21f54428c86b 100644
--- a/include/asm-h8300/atomic.h
+++ b/include/asm-h8300/atomic.h
@@ -95,6 +95,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -137,4 +139,5 @@ static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __ARCH_H8300_ATOMIC __ */
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index 5036f595f8c9..c0411ec9d651 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -406,5 +406,6 @@ found_middle:
#endif /* __KERNEL__ */
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#endif /* _H8300_BITOPS_H */
diff --git a/include/asm-h8300/futex.h b/include/asm-h8300/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-h8300/futex.h
+++ b/include/asm-h8300/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-h8300/ioctl.h b/include/asm-h8300/ioctl.h
index 031c623478b3..b279fe06dfe5 100644
--- a/include/asm-h8300/ioctl.h
+++ b/include/asm-h8300/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.1 2002/11/19 02:09:26 gerg Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _H8300_IOCTL_H
-#define _H8300_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _H8300_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-h8300/irq.h b/include/asm-h8300/irq.h
index 5027181ed067..73065f5bda0e 100644
--- a/include/asm-h8300/irq.h
+++ b/include/asm-h8300/irq.h
@@ -61,11 +61,6 @@ static __inline__ int irq_canonicalize(int irq)
extern void enable_irq(unsigned int);
extern void disable_irq(unsigned int);
-
-/*
- * Some drivers want these entry points
- */
-#define enable_irq_nosync(x) enable_irq(x)
#define disable_irq_nosync(x) disable_irq(x)
struct irqaction;
diff --git a/include/asm-h8300/mman.h b/include/asm-h8300/mman.h
index 63f727a59850..744a8fb485c2 100644
--- a/include/asm-h8300/mman.h
+++ b/include/asm-h8300/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-h8300/mutex.h b/include/asm-h8300/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-h8300/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index e8c02b8c2d99..cd35b1cc6cde 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -13,12 +13,6 @@
#include <asm/setup.h>
-#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13
-#define KTHREAD_SIZE (8192)
-#else
-#define KTHREAD_SIZE PAGE_SIZE
-#endif
-
#ifndef __ASSEMBLY__
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index bfcc755c3bb1..45f09dc9caff 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -69,8 +69,6 @@ static inline struct thread_info *current_thread_info(void)
#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 8c454aa58ac6..d30b8571573f 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -132,6 +132,11 @@ extern unsigned int nmi_watchdog;
extern int disable_timer_pin_1;
+void smp_send_timer_broadcast_ipi(struct pt_regs *regs);
+void switch_APIC_timer_to_ipi(void *cpumask);
+void switch_ipi_to_APIC_timer(void *cpumask);
+#define ARCH_APICTIMER_STOPS_ON_C3 1
+
#else /* !CONFIG_X86_LOCAL_APIC */
static inline void lapic_shutdown(void) { }
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index c68557aa04b2..de649d3aa2d4 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -216,6 +216,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)
}
#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -254,4 +255,5 @@ __asm__ __volatile__(LOCK "orl %0,%1" \
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index ddf1739dc7fd..88e6ca248cd7 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -43,7 +43,7 @@ static inline void set_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
@@ -60,7 +60,7 @@ static inline void __set_bit(int nr, volatile unsigned long * addr)
{
__asm__(
"btsl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
@@ -78,7 +78,7 @@ static inline void clear_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
@@ -86,7 +86,7 @@ static inline void __clear_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__(
"btrl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
#define smp_mb__before_clear_bit() barrier()
@@ -105,7 +105,7 @@ static inline void __change_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__(
"btcl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
@@ -123,7 +123,7 @@ static inline void change_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"Ir" (nr));
}
@@ -142,7 +142,7 @@ static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
@@ -162,7 +162,7 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long * addr)
__asm__(
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr));
return oldbit;
}
@@ -182,7 +182,7 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
@@ -202,7 +202,7 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
__asm__(
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr));
return oldbit;
}
@@ -214,7 +214,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
__asm__ __volatile__(
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
@@ -233,7 +233,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long* addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"Ir" (nr) : "memory");
return oldbit;
}
@@ -247,7 +247,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long* addr)
static int test_bit(int nr, const volatile void * addr);
#endif
-static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
+static __always_inline int constant_test_bit(int nr, const volatile unsigned long *addr)
{
return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
}
@@ -332,9 +332,9 @@ static inline unsigned long __ffs(unsigned long word)
* Returns the bit-number of the first set bit, not the number of the byte
* containing a bit.
*/
-static inline int find_first_bit(const unsigned long *addr, unsigned size)
+static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
{
- int x = 0;
+ unsigned x = 0;
while (x < size) {
unsigned long val = *addr++;
@@ -367,11 +367,7 @@ static inline unsigned long ffz(unsigned long word)
return word;
}
-/*
- * fls: find last bit set.
- */
-
-#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#ifdef __KERNEL__
@@ -414,6 +410,23 @@ static inline int ffs(int x)
}
/**
+ * fls - find last bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ */
+static inline int fls(int x)
+{
+ int r;
+
+ __asm__("bsrl %1,%0\n\t"
+ "jnz 1f\n\t"
+ "movl $-1,%0\n"
+ "1:" : "=r" (r) : "rm" (x));
+ return r+1;
+}
+
+/**
* hweightN - returns the hamming weight of a N-bit word
* @x: the word to weigh
*
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
index ea54540638d2..50233e0345fb 100644
--- a/include/asm-i386/bugs.h
+++ b/include/asm-i386/bugs.h
@@ -8,9 +8,6 @@
* <rreilova@ececs.uc.edu>
* - Channing Corn (tests & fixes),
* - Andrew D. Balsa (code cleanup).
- *
- * Pentium III FXSR, SSE support
- * Gareth Hughes <gareth@valinux.com>, May 2000
*/
/*
@@ -76,25 +73,7 @@ static void __init check_fpu(void)
return;
}
-/* Enable FXSR and company _before_ testing for FP problems. */
- /*
- * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
- */
- if (offsetof(struct task_struct, thread.i387.fxsave) & 15) {
- extern void __buggy_fxsr_alignment(void);
- __buggy_fxsr_alignment();
- }
- if (cpu_has_fxsr) {
- printk(KERN_INFO "Enabling fast FPU save and restore... ");
- set_in_cr4(X86_CR4_OSFXSR);
- printk("done.\n");
- }
- if (cpu_has_xmm) {
- printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... ");
- set_in_cr4(X86_CR4_OSXMMEXCPT);
- printk("done.\n");
- }
-
+/* trap_init() enabled FXSR and company _before_ testing for FP problems here. */
/* Test for the divl bug.. */
__asm__("fninit\n\t"
"fldl %1\n\t"
diff --git a/include/asm-i386/cache.h b/include/asm-i386/cache.h
index 849788710feb..615911e5bd24 100644
--- a/include/asm-i386/cache.h
+++ b/include/asm-i386/cache.h
@@ -10,6 +10,4 @@
#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
-
#endif
diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
index 2ea36dea37d9..7199f7b326f1 100644
--- a/include/asm-i386/cacheflush.h
+++ b/include/asm-i386/cacheflush.h
@@ -31,4 +31,8 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot);
void kernel_map_pages(struct page *page, int numpages, int enable);
#endif
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
+#endif
+
#endif /* _I386_CACHEFLUSH_H */
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index ff1187e80c32..c4ec2a4d8fdf 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -69,6 +69,7 @@
#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */
#define X86_FEATURE_P3 (3*32+ 6) /* P3 */
#define X86_FEATURE_P4 (3*32+ 7) /* P4 */
+#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-i386/current.h b/include/asm-i386/current.h
index d97328951f5f..3cbbecd79016 100644
--- a/include/asm-i386/current.h
+++ b/include/asm-i386/current.h
@@ -5,7 +5,7 @@
struct task_struct;
-static inline struct task_struct * get_current(void)
+static __always_inline struct task_struct * get_current(void)
{
return current_thread_info()->task;
}
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 29b851a18c6e..494e73bca095 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -15,9 +15,6 @@
#include <asm/mmu.h>
extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
-
-#define get_cpu_gdt_table(_cpu) (per_cpu(cpu_gdt_table,_cpu))
DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
@@ -29,6 +26,11 @@ struct Xgt_desc_struct {
extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+ return ((struct desc_struct *)cpu_gdt_descr[cpu].address);
+}
+
#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))
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index e56c335f8ef9..9cf20cacf76e 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -6,6 +6,7 @@
#include <asm/cache.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
+#include <asm/bug.h>
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
@@ -20,7 +21,9 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(direction == DMA_NONE);
+ if (direction == DMA_NONE)
+ BUG();
+ WARN_ON(size == 0);
flush_write_buffers();
return virt_to_phys(ptr);
}
@@ -29,7 +32,8 @@ static inline void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(direction == DMA_NONE);
+ if (direction == DMA_NONE)
+ BUG();
}
static inline int
@@ -38,7 +42,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
{
int i;
- BUG_ON(direction == DMA_NONE);
+ if (direction == DMA_NONE)
+ BUG();
+ WARN_ON(nents == 0 || sg[0].length == 0);
for (i = 0; i < nents; i++ ) {
BUG_ON(!sg[i].page);
@@ -150,7 +156,7 @@ dma_get_cache_alignment(void)
{
/* no easy way to get cache size on all x86, so return the
* maximum possible, to be safe */
- return (1 << L1_CACHE_SHIFT_MAX);
+ return (1 << INTERNODE_CACHE_SHIFT);
}
#define dma_is_consistent(d) (1)
diff --git a/include/asm-i386/edac.h b/include/asm-i386/edac.h
new file mode 100644
index 000000000000..3e7dd0ab68ce
--- /dev/null
+++ b/include/asm-i386/edac.h
@@ -0,0 +1,18 @@
+#ifndef ASM_EDAC_H
+#define ASM_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+ unsigned long *virt_addr = va;
+ u32 i;
+
+ for (i = 0; i < size / 4; i++, virt_addr++)
+ /* Very carefully read and write to memory atomically
+ * so we are interrupt, DMA and SMP safe.
+ */
+ __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
+}
+
+#endif
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h
index e7a271d39309..44b9db806474 100644
--- a/include/asm-i386/futex.h
+++ b/include/asm-i386/futex.h
@@ -61,7 +61,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
if (op == FUTEX_OP_SET)
__futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
else {
-#if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML)
+#ifndef CONFIG_X86_BSWAP
if (boot_cpu_data.x86 == 3)
ret = -ENOSYS;
else
diff --git a/include/asm-i386/i387.h b/include/asm-i386/i387.h
index 6747006743f9..152d0baa576a 100644
--- a/include/asm-i386/i387.h
+++ b/include/asm-i386/i387.h
@@ -49,19 +49,19 @@ static inline void __save_init_fpu( struct task_struct *tsk )
X86_FEATURE_FXSR,
"m" (tsk->thread.i387.fxsave)
:"memory");
- tsk->thread_info->status &= ~TS_USEDFPU;
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
}
#define __unlazy_fpu( tsk ) do { \
- if ((tsk)->thread_info->status & TS_USEDFPU) \
+ if (task_thread_info(tsk)->status & TS_USEDFPU) \
save_init_fpu( tsk ); \
} while (0)
#define __clear_fpu( tsk ) \
do { \
- if ((tsk)->thread_info->status & TS_USEDFPU) { \
+ if (task_thread_info(tsk)->status & TS_USEDFPU) { \
asm volatile("fnclex ; fwait"); \
- (tsk)->thread_info->status &= ~TS_USEDFPU; \
+ task_thread_info(tsk)->status &= ~TS_USEDFPU; \
stts(); \
} \
} while (0)
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index 7babb97a02eb..03233c2ab820 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -131,6 +131,11 @@ extern void iounmap(volatile void __iomem *addr);
extern void *bt_ioremap(unsigned long offset, unsigned long size);
extern void bt_iounmap(void *addr, unsigned long size);
+/* Use early IO mappings for DMI because it's initialized early */
+#define dmi_ioremap bt_ioremap
+#define dmi_iounmap bt_iounmap
+#define dmi_alloc alloc_bootmem
+
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
diff --git a/include/asm-i386/ioctl.h b/include/asm-i386/ioctl.h
index 543f7843d553..b279fe06dfe5 100644
--- a/include/asm-i386/ioctl.h
+++ b/include/asm-i386/ioctl.h
@@ -1,85 +1 @@
-/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMI386_IOCTL_H
-#define _ASMI386_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#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 ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASMI386_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 270f1986b19f..5169d7af456f 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -21,8 +21,6 @@ static __inline__ int irq_canonicalize(int irq)
return ((irq == 2) ? 9 : irq);
}
-extern void release_vm86_irqs(struct task_struct *);
-
#ifdef CONFIG_X86_LOCAL_APIC
# define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
#endif
diff --git a/include/asm-i386/kexec.h b/include/asm-i386/kexec.h
index 6ed2a03e37b3..53f0e06672dc 100644
--- a/include/asm-i386/kexec.h
+++ b/include/asm-i386/kexec.h
@@ -2,6 +2,8 @@
#define _I386_KEXEC_H
#include <asm/fixmap.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
/*
* KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -26,8 +28,49 @@
#define KEXEC_ARCH KEXEC_ARCH_386
#define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
-extern note_buf_t crash_notes[];
+/* CPU does not save ss and esp on stack if execution is already
+ * running in kernel mode at the time of NMI occurrence. This code
+ * fixes it.
+ */
+static inline void crash_fixup_ss_esp(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ memcpy(newregs, oldregs, sizeof(*newregs));
+ newregs->esp = (unsigned long)&(oldregs->esp);
+ __asm__ __volatile__(
+ "xorl %%eax, %%eax\n\t"
+ "movw %%ss, %%ax\n\t"
+ :"=a"(newregs->xss));
+}
+
+/*
+ * This function is responsible for capturing register states if coming
+ * via panic otherwise just fix up the ss and esp if coming via kernel
+ * mode exception.
+ */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ if (oldregs)
+ crash_fixup_ss_esp(newregs, oldregs);
+ else {
+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(newregs->ebx));
+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(newregs->ecx));
+ __asm__ __volatile__("movl %%edx,%0" : "=m"(newregs->edx));
+ __asm__ __volatile__("movl %%esi,%0" : "=m"(newregs->esi));
+ __asm__ __volatile__("movl %%edi,%0" : "=m"(newregs->edi));
+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(newregs->ebp));
+ __asm__ __volatile__("movl %%eax,%0" : "=m"(newregs->eax));
+ __asm__ __volatile__("movl %%esp,%0" : "=m"(newregs->esp));
+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(newregs->xss));
+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(newregs->xcs));
+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(newregs->xds));
+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(newregs->xes));
+ __asm__ __volatile__("pushfl; popl %0" :"=m"(newregs->eflags));
+
+ newregs->eip = (unsigned long)current_text_addr();
+ }
+}
#endif /* _I386_KEXEC_H */
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index ca916a892877..27cac050a60e 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -40,6 +40,7 @@ typedef u8 kprobe_opcode_t;
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define ARCH_SUPPORTS_KRETPROBES
+#define arch_remove_kprobe(p) do {} while (0)
void kretprobe_trampoline(void);
@@ -76,14 +77,6 @@ static inline void restore_interrupts(struct pt_regs *regs)
local_irq_enable();
}
-#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
-#else /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
-#endif
#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index ba936d4daedb..18b19a773440 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -1,17 +1,10 @@
#ifndef __ASM_MACH_APIC_H
#define __ASM_MACH_APIC_H
-#include <asm/smp.h>
-
-#define SEQUENTIAL_APICID
-#ifdef SEQUENTIAL_APICID
-#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\
- ((phys_apic<<2) & (~0xf)) )
-#elif CLUSTERED_APICID
-#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\
- ((phys_apic) & (~0xf)) )
-#endif
-
-#define NO_BALANCE_IRQ (1)
+
+
+extern u8 bios_cpu_apicid[];
+
+#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu])
#define esr_disable (1)
static inline int apic_id_registered(void)
@@ -19,7 +12,6 @@ static inline int apic_id_registered(void)
return (1);
}
-#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
/* Round robin the irqs amoung the online cpus */
static inline cpumask_t target_cpus(void)
{
@@ -32,29 +24,34 @@ static inline cpumask_t target_cpus(void)
} while (cpu >= NR_CPUS);
return cpumask_of_cpu(cpu);
}
-#define TARGET_CPUS (target_cpus())
-#define INT_DELIVERY_MODE dest_Fixed
-#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
+#undef APIC_DEST_LOGICAL
+#define APIC_DEST_LOGICAL 0
+#define TARGET_CPUS (target_cpus())
+#define APIC_DFR_VALUE (APIC_DFR_FLAT)
+#define INT_DELIVERY_MODE (dest_Fixed)
+#define INT_DEST_MODE (0) /* phys delivery to target proc */
+#define NO_BALANCE_IRQ (0)
+#define WAKE_SECONDARY_VIA_INIT
+
static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
{
- return 0;
+ return (0);
}
-/* we don't use the phys_cpu_present_map to indicate apicid presence */
-static inline unsigned long check_apicid_present(int bit)
+static inline unsigned long check_apicid_present(int bit)
{
- return 1;
+ return (1);
}
-#define apicid_cluster(apicid) (apicid & 0xF0)
-
-static inline unsigned long calculate_ldr(unsigned long old)
+static inline unsigned long calculate_ldr(int cpu)
{
- unsigned long id;
- id = xapic_phys_to_log_apicid(hard_smp_processor_id());
- return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id));
+ unsigned long val, id;
+ val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
+ id = xapic_phys_to_log_apicid(cpu);
+ val |= SET_APIC_LOGICAL_ID(id);
+ return val;
}
/*
@@ -67,37 +64,35 @@ static inline unsigned long calculate_ldr(unsigned long old)
static inline void init_apic_ldr(void)
{
unsigned long val;
+ int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
- val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
- val = calculate_ldr(val);
+ val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val);
}
static inline void clustered_apic_check(void)
{
printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
- "Cluster", nr_ioapics);
+ "Physflat", nr_ioapics);
}
static inline int multi_timer_check(int apic, int irq)
{
- return 0;
+ return (0);
}
static inline int apicid_to_node(int logical_apicid)
{
- return 0;
+ return (0);
}
-extern u8 bios_cpu_apicid[];
-
static inline int cpu_present_to_apicid(int mps_cpu)
{
if (mps_cpu < NR_CPUS)
- return (int)bios_cpu_apicid[mps_cpu];
- else
- return BAD_APICID;
+ return (int) bios_cpu_apicid[mps_cpu];
+
+ return BAD_APICID;
}
static inline physid_mask_t apicid_to_cpu_present(int phys_apicid)
@@ -109,10 +104,10 @@ extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu)
{
- if (cpu >= NR_CPUS)
- return BAD_APICID;
- return (int)cpu_2_logical_apicid[cpu];
- }
+ if (cpu >= NR_CPUS)
+ return BAD_APICID;
+ return cpu_physical_id(cpu);
+}
static inline int mpc_apic_id(struct mpc_config_processor *m,
struct mpc_config_translation *translation_record)
@@ -128,11 +123,9 @@ static inline int mpc_apic_id(struct mpc_config_processor *m,
static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
{
/* For clustered we don't have a good way to do this yet - hack */
- return physids_promote(0xFUL);
+ return physids_promote(0xFFL);
}
-#define WAKE_SECONDARY_VIA_INIT
-
static inline void setup_portio_remap(void)
{
}
diff --git a/include/asm-i386/mach-bigsmp/mach_apicdef.h b/include/asm-i386/mach-bigsmp/mach_apicdef.h
index 23e58b317c79..a58ab5a75c8c 100644
--- a/include/asm-i386/mach-bigsmp/mach_apicdef.h
+++ b/include/asm-i386/mach-bigsmp/mach_apicdef.h
@@ -1,11 +1,11 @@
#ifndef __ASM_MACH_APICDEF_H
#define __ASM_MACH_APICDEF_H
-#define APIC_ID_MASK (0x0F<<24)
+#define APIC_ID_MASK (0xFF<<24)
static inline unsigned get_apic_id(unsigned long x)
{
- return (((x)>>24)&0x0F);
+ return (((x)>>24)&0xFF);
}
#define GET_APIC_ID(x) get_apic_id(x)
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index cc756a67cd63..a1d0072e36bc 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -15,11 +15,9 @@ static inline void __local_send_IPI_allbutself(int vector)
{
if (no_broadcast) {
cpumask_t mask = cpu_online_map;
- int this_cpu = get_cpu();
- cpu_clear(this_cpu, mask);
+ cpu_clear(smp_processor_id(), mask);
send_IPI_mask(mask, vector);
- put_cpu();
} else
__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
}
diff --git a/include/asm-i386/mman.h b/include/asm-i386/mman.h
index 196619a83854..ba4941e6f643 100644
--- a/include/asm-i386/mman.h
+++ b/include/asm-i386/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 620a90641ea8..74f595d80579 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -76,11 +76,6 @@ static inline int pfn_to_nid(unsigned long pfn)
* Following are macros that each numa implmentation must define.
*/
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
-
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) \
({ \
diff --git a/include/asm-i386/module.h b/include/asm-i386/module.h
index eb7f2b4234aa..424661d25bd3 100644
--- a/include/asm-i386/module.h
+++ b/include/asm-i386/module.h
@@ -52,8 +52,10 @@ struct mod_arch_specific
#define MODULE_PROC_FAMILY "CYRIXIII "
#elif defined CONFIG_MVIAC3_2
#define MODULE_PROC_FAMILY "VIAC3-2 "
-#elif CONFIG_MGEODEGX1
+#elif defined CONFIG_MGEODEGX1
#define MODULE_PROC_FAMILY "GEODEGX1 "
+#elif defined CONFIG_MGEODE_LX
+#define MODULE_PROC_FAMILY "GEODE "
#else
#error unknown processor family
#endif
diff --git a/include/asm-i386/mpspec_def.h b/include/asm-i386/mpspec_def.h
index a961093dbf88..76feedf85a8a 100644
--- a/include/asm-i386/mpspec_def.h
+++ b/include/asm-i386/mpspec_def.h
@@ -75,7 +75,7 @@ struct mpc_config_bus
{
unsigned char mpc_type;
unsigned char mpc_busid;
- unsigned char mpc_bustype[6] __attribute((packed));
+ unsigned char mpc_bustype[6];
};
/* List of Bus Type string values, Intel MP Spec. */
diff --git a/include/asm-i386/mutex.h b/include/asm-i386/mutex.h
new file mode 100644
index 000000000000..9b2199e829f3
--- /dev/null
+++ b/include/asm-i386/mutex.h
@@ -0,0 +1,136 @@
+/*
+ * Assembly implementation of the mutex fastpath, based on atomic
+ * decrement/increment.
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#ifndef _ASM_MUTEX_H
+#define _ASM_MUTEX_H
+
+/**
+ * __mutex_fastpath_lock - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fn> if it
+ * wasn't 1 originally. This function MUST leave the value lower than 1
+ * even when the "1" assertion wasn't true.
+ */
+#define __mutex_fastpath_lock(count, fail_fn) \
+do { \
+ unsigned int dummy; \
+ \
+ typecheck(atomic_t *, count); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ __volatile__( \
+ LOCK " decl (%%eax) \n" \
+ " js 2f \n" \
+ "1: \n" \
+ \
+ LOCK_SECTION_START("") \
+ "2: call "#fail_fn" \n" \
+ " jmp 1b \n" \
+ LOCK_SECTION_END \
+ \
+ :"=a" (dummy) \
+ : "a" (count) \
+ : "memory", "ecx", "edx"); \
+} while (0)
+
+
+/**
+ * __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if it
+ * wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count,
+ int fastcall (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+ else
+ return 0;
+}
+
+/**
+ * __mutex_fastpath_unlock - try to promote the mutex from 0 to 1
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 0
+ *
+ * try to promote the mutex from 0 to 1. if it wasn't 0, call <fail_fn>.
+ * In the failure case, this function is allowed to either set the value
+ * to 1, or to set it to a value lower than 1.
+ *
+ * If the implementation sets it to a value of lower than 1, the
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+#define __mutex_fastpath_unlock(count, fail_fn) \
+do { \
+ unsigned int dummy; \
+ \
+ typecheck(atomic_t *, count); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ __volatile__( \
+ LOCK " incl (%%eax) \n" \
+ " jle 2f \n" \
+ "1: \n" \
+ \
+ LOCK_SECTION_START("") \
+ "2: call "#fail_fn" \n" \
+ " jmp 1b \n" \
+ LOCK_SECTION_END \
+ \
+ :"=a" (dummy) \
+ : "a" (count) \
+ : "memory", "ecx", "edx"); \
+} while (0)
+
+#define __mutex_slowpath_needs_to_unlock() 1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ * @count: pointer of type atomic_t
+ * @fail_fn: fallback function
+ *
+ * Change the count from 1 to a value lower than 1, and return 0 (failure)
+ * if it wasn't 1 originally, or return 1 (success) otherwise. This function
+ * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ /*
+ * We have two variants here. The cmpxchg based one is the best one
+ * because it never induce a false contention state. It is included
+ * here because architectures using the inc/dec algorithms over the
+ * xchg ones are much more likely to support cmpxchg natively.
+ *
+ * If not we fall back to the spinlock based variant - that is
+ * just as efficient (and simpler) as a 'destructive' probing of
+ * the mutex state would be.
+ */
+#ifdef __HAVE_ARCH_CMPXCHG
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1))
+ return 1;
+ return 0;
+#else
+ return fail_fn(count);
+#endif
+}
+
+#endif
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 5c96cf6dcb39..feca5d961e2b 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -61,9 +61,11 @@ struct cpuinfo_x86 {
int x86_cache_size; /* in KB - valid for CPUS which support this
call */
int x86_cache_alignment; /* In bytes */
- int fdiv_bug;
- int f00f_bug;
- int coma_bug;
+ char fdiv_bug;
+ char f00f_bug;
+ char coma_bug;
+ char pad0;
+ int x86_power;
unsigned long loops_per_jiffy;
unsigned char x86_max_cores; /* cpuid returned max cores value */
unsigned char booted_cores; /* number of cores as seen by OS */
@@ -279,9 +281,11 @@ static inline void clear_in_cr4 (unsigned long mask)
outb((data), 0x23); \
} while (0)
-static inline void serialize_cpu(void)
+/* Stop speculative execution */
+static inline void sync_core(void)
{
- __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
+ int tmp;
+ asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
}
static inline void __monitor(const void *eax, unsigned long ecx,
@@ -557,10 +561,20 @@ unsigned long get_wchan(struct task_struct *p);
(unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
})
+/*
+ * The below -8 is to reserve 8 bytes on top of the ring0 stack.
+ * This is necessary to guarantee that the entire "struct pt_regs"
+ * is accessable even if the CPU haven't stored the SS/ESP registers
+ * on the stack (interrupt gate does not save these registers
+ * when switching to the same priv ring).
+ * Therefore beware: accessing the xss/esp fields of the
+ * "struct pt_regs" is possible, but they may contain the
+ * completely wrong values.
+ */
#define task_pt_regs(task) \
({ \
struct pt_regs *__regs__; \
- __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \
+ __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
__regs__ - 1; \
})
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index 7e0f2945d17d..f324c53b6f9a 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -54,6 +54,9 @@ struct pt_regs {
#define PTRACE_GET_THREAD_AREA 25
#define PTRACE_SET_THREAD_AREA 26
+#define PTRACE_SYSEMU 31
+#define PTRACE_SYSEMU_SINGLESTEP 32
+
#ifdef __KERNEL__
#include <asm/vm86.h>
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index bb5ff5b2c02e..faf995307b9e 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -91,6 +91,20 @@
#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+/* The PnP BIOS entries in the GDT */
+#define GDT_ENTRY_PNPBIOS_CS32 (GDT_ENTRY_PNPBIOS_BASE + 0)
+#define GDT_ENTRY_PNPBIOS_CS16 (GDT_ENTRY_PNPBIOS_BASE + 1)
+#define GDT_ENTRY_PNPBIOS_DS (GDT_ENTRY_PNPBIOS_BASE + 2)
+#define GDT_ENTRY_PNPBIOS_TS1 (GDT_ENTRY_PNPBIOS_BASE + 3)
+#define GDT_ENTRY_PNPBIOS_TS2 (GDT_ENTRY_PNPBIOS_BASE + 4)
+
+/* The PnP BIOS selectors */
+#define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */
+#define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */
+#define PNP_DS (GDT_ENTRY_PNPBIOS_DS * 8) /* data segment for BIOS */
+#define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */
+#define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */
+
/*
* The interrupt descriptor table has room for 256 idt's,
* the global descriptor table is dependent on the number
diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h
index 76524b4052ac..026fd231488d 100644
--- a/include/asm-i386/signal.h
+++ b/include/asm-i386/signal.h
@@ -218,7 +218,6 @@ static __inline__ int sigfindinword(unsigned long word)
}
struct pt_regs;
-extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
#define ptrace_signal_deliver(regs, cookie) \
do { \
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 02c8f5d22065..bb5f88a27f7a 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -201,7 +201,7 @@ __asm__ __volatile__(
return __res;
}
-static inline void * __memcpy(void * to, const void * from, size_t n)
+static __always_inline void * __memcpy(void * to, const void * from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__(
@@ -223,7 +223,7 @@ return (to);
* This looks ugly, but the compiler can optimize it totally,
* as the count is constant.
*/
-static inline void * __constant_memcpy(void * to, const void * from, size_t n)
+static __always_inline void * __constant_memcpy(void * to, const void * from, size_t n)
{
long esi, edi;
if (!n) return to;
@@ -367,7 +367,7 @@ return s;
* things 32 bits at a time even when we don't know the size of the
* area at compile-time..
*/
-static inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
+static __always_inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
{
int d0, d1;
__asm__ __volatile__(
@@ -416,7 +416,7 @@ extern char *strstr(const char *cs, const char *ct);
* This looks horribly ugly, but the compiler can optimize it totally,
* as we by now know that both pattern and count is constant..
*/
-static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
+static __always_inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
{
switch (count) {
case 0:
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 772f85da1206..36a92ed6a9d0 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -54,23 +54,7 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
); } while(0)
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
-#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 )
-
-static inline unsigned long _get_base(char * addr)
-{
- unsigned long __base;
- __asm__("movb %3,%%dh\n\t"
- "movb %2,%%dl\n\t"
- "shll $16,%%edx\n\t"
- "movw %1,%%dx"
- :"=&d" (__base)
- :"m" (*((addr)+2)),
- "m" (*((addr)+4)),
- "m" (*((addr)+7)));
- return __base;
-}
-
-#define get_base(ldt) _get_base( ((char *)&(ldt)) )
+#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1) )
/*
* Load a segment. Fall back on loading the zero
@@ -140,6 +124,19 @@ static inline unsigned long _get_base(char * addr)
:"=r" (__dummy)); \
__dummy; \
})
+
+#define read_cr4_safe() ({ \
+ unsigned int __dummy; \
+ /* 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" (__dummy): "0" (0)); \
+ __dummy; \
+})
+
#define write_cr4(x) \
__asm__ __volatile__("movl %0,%%cr4": :"r" (x));
#define stts() write_cr0(8 | read_cr0())
@@ -551,6 +548,15 @@ void enable_hlt(void);
extern int es7000_plat;
void cpu_idle_wait(void);
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible:
+ */
+static inline void sched_cacheflush(void)
+{
+ wbinvd();
+}
+
extern unsigned long arch_align_stack(unsigned long sp);
#endif
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 8fbf791651bf..e20e99551d71 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -111,8 +111,6 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#endif
#define free_thread_info(info) kfree(info)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#else /* !__ASSEMBLY__ */
@@ -142,6 +140,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SECCOMP 8 /* secure computing */
+#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17
@@ -154,6 +153,7 @@ register unsigned long current_stack_pointer asm("esp") __attribute_used__;
#define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* work to do on interrupt/exception return */
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 0ec27c9e8e45..d7e19eb344b7 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -72,7 +72,6 @@ static inline int node_to_first_cpu(int node)
.max_interval = 32, \
.busy_factor = 32, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000000), \
.cache_nice_tries = 1, \
.busy_idx = 3, \
.idle_idx = 1, \
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 89ab7e2bc5aa..3f1337c34208 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -411,7 +411,7 @@ unsigned long __must_check __copy_from_user_ll(void *to,
* Returns number of bytes that could not be copied.
* On success, this will be zero.
*/
-static inline unsigned long __must_check
+static __always_inline unsigned long __must_check
__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
{
if (__builtin_constant_p(n)) {
@@ -432,7 +432,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
return __copy_to_user_ll(to, from, n);
}
-static inline unsigned long __must_check
+static __always_inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
might_sleep();
@@ -456,7 +456,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
* If some data could not be copied, this function will pad the copied
* data to the requested size using zero bytes.
*/
-static inline unsigned long
+static __always_inline unsigned long
__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
{
if (__builtin_constant_p(n)) {
@@ -477,7 +477,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
return __copy_from_user_ll(to, from, n);
}
-static inline unsigned long
+static __always_inline unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
might_sleep();
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 0f92e78dfea1..597496ed2aee 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -256,7 +256,7 @@
#define __NR_io_submit 248
#define __NR_io_cancel 249
#define __NR_fadvise64 250
-#define __NR_set_zone_reclaim 251
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
#define __NR_epoll_create 254
@@ -299,8 +299,24 @@
#define __NR_inotify_init 291
#define __NR_inotify_add_watch 292
#define __NR_inotify_rm_watch 293
+#define __NR_migrate_pages 294
+#define __NR_openat 295
+#define __NR_mkdirat 296
+#define __NR_mknodat 297
+#define __NR_fchownat 298
+#define __NR_futimesat 299
+#define __NR_newfstatat 300
+#define __NR_unlinkat 301
+#define __NR_renameat 302
+#define __NR_linkat 303
+#define __NR_symlinkat 304
+#define __NR_readlinkat 305
+#define __NR_fchmodat 306
+#define __NR_faccessat 307
+#define __NR_pselect6 308
+#define __NR_ppoll 309
-#define NR_syscalls 294
+#define NR_syscalls 310
/*
* user-visible error numbers are in the range -1 - -128: see
@@ -416,6 +432,7 @@ __syscall_return(type,__res); \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#endif
#ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-i386/vm86.h b/include/asm-i386/vm86.h
index 40ec82c6914d..952fd6957380 100644
--- a/include/asm-i386/vm86.h
+++ b/include/asm-i386/vm86.h
@@ -16,7 +16,11 @@
#define IF_MASK 0x00000200
#define IOPL_MASK 0x00003000
#define NT_MASK 0x00004000
+#ifdef CONFIG_VM86
#define VM_MASK 0x00020000
+#else
+#define VM_MASK 0 /* ignored */
+#endif
#define AC_MASK 0x00040000
#define VIF_MASK 0x00080000 /* virtual interrupt flag */
#define VIP_MASK 0x00100000 /* virtual interrupt pending */
@@ -200,9 +204,25 @@ struct kernel_vm86_struct {
*/
};
+#ifdef CONFIG_VM86
+
void handle_vm86_fault(struct kernel_vm86_regs *, long);
int handle_vm86_trap(struct kernel_vm86_regs *, long, int);
+struct task_struct;
+void release_vm86_irqs(struct task_struct *);
+
+#else
+
+#define handle_vm86_fault(a, b)
+#define release_vm86_irqs(a)
+
+static inline int handle_vm86_trap(struct kernel_vm86_regs *a, long b, int c) {
+ return 0;
+}
+
+#endif /* CONFIG_VM86 */
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-ia64/atomic.h b/include/asm-ia64/atomic.h
index 2fbebf85c31d..d3e0dfa99e1f 100644
--- a/include/asm-ia64/atomic.h
+++ b/include/asm-ia64/atomic.h
@@ -89,6 +89,7 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)
}
#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -192,4 +193,5 @@ atomic64_add_negative (__s64 i, atomic64_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* _ASM_IA64_ATOMIC_H */
diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
index 7232528e2d0c..36d0fb95ea89 100644
--- a/include/asm-ia64/bitops.h
+++ b/include/asm-ia64/bitops.h
@@ -345,6 +345,7 @@ fls (int t)
x |= x >> 16;
return ia64_popcnt(x);
}
+#define fls64(x) generic_fls64(x)
/*
* ffs: find first bit set. This is defined the same way as the libc and compiler builtin
diff --git a/include/asm-ia64/bug.h b/include/asm-ia64/bug.h
index 3aa0a0a5474b..823616b5020b 100644
--- a/include/asm-ia64/bug.h
+++ b/include/asm-ia64/bug.h
@@ -2,11 +2,7 @@
#define _ASM_IA64_BUG_H
#ifdef CONFIG_BUG
-#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
-# define ia64_abort() __builtin_trap()
-#else
-# define ia64_abort() (*(volatile int *) 0 = 0)
-#endif
+#define ia64_abort() __builtin_trap()
#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
/* should this BUG be made generic? */
diff --git a/include/asm-ia64/cache.h b/include/asm-ia64/cache.h
index 666d8f175cb3..40dd25195d65 100644
--- a/include/asm-ia64/cache.h
+++ b/include/asm-ia64/cache.h
@@ -12,8 +12,6 @@
#define L1_CACHE_SHIFT CONFIG_IA64_L1_CACHE_SHIFT
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
-
#ifdef CONFIG_SMP
# define SMP_CACHE_SHIFT L1_CACHE_SHIFT
# define SMP_CACHE_BYTES L1_CACHE_BYTES
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index aaf11f4e9169..c0b19106665c 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -192,7 +192,7 @@ compat_ptr (compat_uptr_t uptr)
static __inline__ void __user *
compat_alloc_user_space (long len)
{
- struct pt_regs *regs = ia64_task_regs(current);
+ struct pt_regs *regs = task_pt_regs(current);
return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
}
diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-ia64/futex.h
+++ b/include/asm-ia64/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-ia64/io.h b/include/asm-ia64/io.h
index cf772a67f858..b64fdb985494 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -89,6 +89,7 @@ phys_to_virt (unsigned long address)
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
extern int valid_phys_addr_range (unsigned long addr, size_t *count); /* efi.c */
+extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count);
/*
* The following two macros are deprecated and scheduled for removal.
diff --git a/include/asm-ia64/ioctl.h b/include/asm-ia64/ioctl.h
index be9cc2403d2a..b279fe06dfe5 100644
--- a/include/asm-ia64/ioctl.h
+++ b/include/asm-ia64/ioctl.h
@@ -1,77 +1 @@
-#ifndef _ASM_IA64_IOCTL_H
-#define _ASM_IA64_IOCTL_H
-
-/*
- * Based on <asm-i386/ioctl.h>.
- *
- * Modified 1998, 1999
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The ia64 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASM_IA64_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 592abb000e29..8c0fc227f0fb 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -68,10 +68,14 @@ struct prev_kprobe {
unsigned long status;
};
+#define MAX_PARAM_RSE_SIZE (0x60+0x60/0x3f)
/* per-cpu kprobe control block */
struct kprobe_ctlblk {
unsigned long kprobe_status;
struct pt_regs jprobe_saved_regs;
+ unsigned long jprobes_saved_stacked_regs[MAX_PARAM_RSE_SIZE];
+ unsigned long *bsp;
+ unsigned long cfm;
struct prev_kprobe prev_kprobe;
};
@@ -89,6 +93,7 @@ struct kprobe_ctlblk {
#define IP_RELATIVE_PREDICT_OPCODE (7)
#define LONG_BRANCH_OPCODE (0xC)
#define LONG_CALL_OPCODE (0xD)
+#define arch_remove_kprobe(p) do {} while (0)
typedef struct kprobe_opcode {
bundle_t bundle;
@@ -110,12 +115,6 @@ struct arch_specific_insn {
unsigned short target_br_reg;
};
-/* ia64 does not need this */
-static inline void arch_copy_kprobe(struct kprobe *p)
-{
-}
-
-#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
@@ -123,12 +122,7 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
static inline void jprobe_return(void)
{
}
+extern void invalidate_stacked_regs(void);
+extern void flush_register_stack(void);
-#else /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
-#endif
#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/mman.h b/include/asm-ia64/mman.h
index 1c0a73af1461..828beb24a20e 100644
--- a/include/asm-ia64/mman.h
+++ b/include/asm-ia64/mman.h
@@ -43,6 +43,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-ia64/mutex.h b/include/asm-ia64/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-ia64/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index e828377ad295..7708ec669a33 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -927,7 +927,7 @@ static inline s64
ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress, u64 *vector)
{
struct ia64_pal_retval iprv;
- PAL_CALL_IC_OFF(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress);
+ PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress);
if (vector)
*vector = iprv.v0;
*progress = iprv.v1;
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 94e07e727395..09b99029ac1a 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -25,8 +25,8 @@
* Limits for PMC and PMD are set to less than maximum architected values
* but should be sufficient for a while
*/
-#define IA64_NUM_PMC_REGS 32
-#define IA64_NUM_PMD_REGS 32
+#define IA64_NUM_PMC_REGS 64
+#define IA64_NUM_PMD_REGS 64
#define DEFAULT_MAP_BASE __IA64_UL_CONST(0x2000000000000000)
#define DEFAULT_TASK_SIZE __IA64_UL_CONST(0xa000000000000000)
@@ -352,7 +352,7 @@ extern unsigned long get_wchan (struct task_struct *p);
/* Return instruction pointer of blocked task TSK. */
#define KSTK_EIP(tsk) \
({ \
- struct pt_regs *_regs = ia64_task_regs(tsk); \
+ struct pt_regs *_regs = task_pt_regs(tsk); \
_regs->cr_iip + ia64_psr(_regs)->ri; \
})
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index 2c703d6e0c86..9471cdc3f4c0 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -248,7 +248,7 @@ struct switch_stack {
})
/* given a pointer to a task_struct, return the user's pt_regs */
-# define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
+# define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
# define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr)
# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
# define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs))
@@ -271,7 +271,7 @@ struct switch_stack {
*
* On ia64, we can clear the user's pt_regs->r8 to force a successful syscall.
*/
-# define force_successful_syscall_return() (ia64_task_regs(current)->r8 = 0)
+# define force_successful_syscall_return() (task_pt_regs(current)->r8 = 0)
struct task_struct; /* forward decl */
struct unw_frame_info; /* forward decl */
diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h
index e35074f526d9..a3431372c6e7 100644
--- a/include/asm-ia64/sn/intr.h
+++ b/include/asm-ia64/sn/intr.h
@@ -40,7 +40,7 @@ struct sn_irq_info {
int irq_cpuid; /* kernel logical cpuid */
int irq_irq; /* the IRQ number */
int irq_int_bit; /* Bridge interrupt pin */
- uint64_t irq_xtalkaddr; /* xtalkaddr IRQ is sent to */
+ u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */
int irq_bridge_type;/* pciio asic type (pciio.h) */
void *irq_bridge; /* bridge generating irq */
void *irq_pciioinfo; /* associated pciio_info_t */
diff --git a/include/asm-ia64/sn/ioc3.h b/include/asm-ia64/sn/ioc3.h
new file mode 100644
index 000000000000..95ed6cc83cf1
--- /dev/null
+++ b/include/asm-ia64/sn/ioc3.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2005 Silicon Graphics, Inc.
+ */
+#ifndef IA64_SN_IOC3_H
+#define IA64_SN_IOC3_H
+
+/* serial port register map */
+struct ioc3_serialregs {
+ uint32_t sscr;
+ uint32_t stpir;
+ uint32_t stcir;
+ uint32_t srpir;
+ uint32_t srcir;
+ uint32_t srtr;
+ uint32_t shadow;
+};
+
+/* SUPERIO uart register map */
+struct ioc3_uartregs {
+ char iu_lcr;
+ union {
+ char iir; /* read only */
+ char fcr; /* write only */
+ } u3;
+ union {
+ char ier; /* DLAB == 0 */
+ char dlm; /* DLAB == 1 */
+ } u2;
+ union {
+ char rbr; /* read only, DLAB == 0 */
+ char thr; /* write only, DLAB == 0 */
+ char dll; /* DLAB == 1 */
+ } u1;
+ char iu_scr;
+ char iu_msr;
+ char iu_lsr;
+ char iu_mcr;
+};
+
+#define iu_rbr u1.rbr
+#define iu_thr u1.thr
+#define iu_dll u1.dll
+#define iu_ier u2.ier
+#define iu_dlm u2.dlm
+#define iu_iir u3.iir
+#define iu_fcr u3.fcr
+
+struct ioc3_sioregs {
+ char fill[0x170];
+ struct ioc3_uartregs uartb;
+ struct ioc3_uartregs uarta;
+};
+
+/* PCI IO/mem space register map */
+struct ioc3 {
+ uint32_t pci_id;
+ uint32_t pci_scr;
+ uint32_t pci_rev;
+ uint32_t pci_lat;
+ uint32_t pci_addr;
+ uint32_t pci_err_addr_l;
+ uint32_t pci_err_addr_h;
+
+ uint32_t sio_ir;
+ /* these registers are read-only for general kernel code. To
+ * modify them use the functions in ioc3.c
+ */
+ uint32_t sio_ies;
+ uint32_t sio_iec;
+ uint32_t sio_cr;
+ uint32_t int_out;
+ uint32_t mcr;
+ uint32_t gpcr_s;
+ uint32_t gpcr_c;
+ uint32_t gpdr;
+ uint32_t gppr[9];
+ char fill[0x4c];
+
+ /* serial port registers */
+ uint32_t sbbr_h;
+ uint32_t sbbr_l;
+
+ struct ioc3_serialregs port_a;
+ struct ioc3_serialregs port_b;
+ char fill1[0x1ff10];
+ /* superio registers */
+ struct ioc3_sioregs sregs;
+};
+
+/* These don't exist on the ioc3 serial card... */
+#define eier fill1[8]
+#define eisr fill1[4]
+
+#define PCI_LAT 0xc /* Latency Timer */
+#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */
+#define UARTA_BASE 0x178
+#define UARTB_BASE 0x170
+
+
+/* bitmasks for serial RX status byte */
+#define RXSB_OVERRUN 0x01 /* char(s) lost */
+#define RXSB_PAR_ERR 0x02 /* parity error */
+#define RXSB_FRAME_ERR 0x04 /* framing error */
+#define RXSB_BREAK 0x08 /* break character */
+#define RXSB_CTS 0x10 /* state of CTS */
+#define RXSB_DCD 0x20 /* state of DCD */
+#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */
+#define RXSB_DATA_VALID 0x80 /* FRAME_ERR PAR_ERR & BREAK valid */
+
+/* bitmasks for serial TX control byte */
+#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */
+#define TXCB_INVALID 0x00 /* byte is invalid */
+#define TXCB_VALID 0x40 /* byte is valid */
+#define TXCB_MCR 0x80 /* data<7:0> to modem cntrl register */
+#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */
+
+/* bitmasks for SBBR_L */
+#define SBBR_L_SIZE 0x00000001 /* 0 1KB rings, 1 4KB rings */
+
+/* bitmasks for SSCR_<A:B> */
+#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */
+#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */
+#define SSCR_HFC_EN 0x00020000 /* h/w flow cntrl enabled */
+#define SSCR_RX_RING_DCD 0x00040000 /* postRX record on delta-DCD */
+#define SSCR_RX_RING_CTS 0x00080000 /* postRX record on delta-CTS */
+#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */
+#define SSCR_DIAG 0x00200000 /* bypass clock divider */
+#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */
+#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */
+#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */
+#define SSCR_PAUSE_STATE 0x40000000 /* set when PAUSE takes effect*/
+#define SSCR_RESET 0x80000000 /* reset DMA channels */
+
+/* all producer/comsumer pointers are the same bitfield */
+#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */
+#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */
+#define PROD_CONS_PTR_OFF 3
+
+/* bitmasks for SRCIR_<A:B> */
+#define SRCIR_ARM 0x80000000 /* arm RX timer */
+
+/* bitmasks for SHADOW_<A:B> */
+#define SHADOW_DR 0x00000001 /* data ready */
+#define SHADOW_OE 0x00000002 /* overrun error */
+#define SHADOW_PE 0x00000004 /* parity error */
+#define SHADOW_FE 0x00000008 /* framing error */
+#define SHADOW_BI 0x00000010 /* break interrupt */
+#define SHADOW_THRE 0x00000020 /* transmit holding reg empty */
+#define SHADOW_TEMT 0x00000040 /* transmit shift reg empty */
+#define SHADOW_RFCE 0x00000080 /* char in RX fifo has error */
+#define SHADOW_DCTS 0x00010000 /* delta clear to send */
+#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */
+#define SHADOW_CTS 0x00100000 /* clear to send */
+#define SHADOW_DCD 0x00800000 /* data carrier detect */
+#define SHADOW_DTR 0x01000000 /* data terminal ready */
+#define SHADOW_RTS 0x02000000 /* request to send */
+#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */
+#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */
+#define SHADOW_LOOP 0x10000000 /* loopback enabled */
+
+/* bitmasks for SRTR_<A:B> */
+#define SRTR_CNT 0x00000fff /* reload value for RX timer */
+#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */
+#define SRTR_CNT_VAL_SHIFT 16
+#define SRTR_HZ 16000 /* SRTR clock frequency */
+
+/* bitmasks for SIO_IR, SIO_IEC and SIO_IES */
+#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */
+#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */
+#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */
+#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */
+#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */
+#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */
+#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */
+#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */
+#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */
+#define SIO_IR_SB_TX_MT 0x00000200
+#define SIO_IR_SB_RX_FULL 0x00000400
+#define SIO_IR_SB_RX_HIGH 0x00000800
+#define SIO_IR_SB_RX_TIMER 0x00001000
+#define SIO_IR_SB_DELTA_DCD 0x00002000
+#define SIO_IR_SB_DELTA_CTS 0x00004000
+#define SIO_IR_SB_INT 0x00008000
+#define SIO_IR_SB_TX_EXPLICIT 0x00010000
+#define SIO_IR_SB_MEMERR 0x00020000
+#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */
+#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */
+#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */
+#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */
+#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */
+#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */
+#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */
+#define SIO_IR_GEN_INT_SHIFT 28
+
+/* per device interrupt masks */
+#define SIO_IR_SA (SIO_IR_SA_TX_MT | \
+ SIO_IR_SA_RX_FULL | \
+ SIO_IR_SA_RX_HIGH | \
+ SIO_IR_SA_RX_TIMER | \
+ SIO_IR_SA_DELTA_DCD | \
+ SIO_IR_SA_DELTA_CTS | \
+ SIO_IR_SA_INT | \
+ SIO_IR_SA_TX_EXPLICIT | \
+ SIO_IR_SA_MEMERR)
+
+#define SIO_IR_SB (SIO_IR_SB_TX_MT | \
+ SIO_IR_SB_RX_FULL | \
+ SIO_IR_SB_RX_HIGH | \
+ SIO_IR_SB_RX_TIMER | \
+ SIO_IR_SB_DELTA_DCD | \
+ SIO_IR_SB_DELTA_CTS | \
+ SIO_IR_SB_INT | \
+ SIO_IR_SB_TX_EXPLICIT | \
+ SIO_IR_SB_MEMERR)
+
+#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \
+ SIO_IR_PP_INTB | SIO_IR_PP_MEMERR)
+#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1)
+
+/* bitmasks for SIO_CR */
+#define SIO_CR_CMD_PULSE_SHIFT 15
+#define SIO_CR_SER_A_BASE_SHIFT 1
+#define SIO_CR_SER_B_BASE_SHIFT 8
+#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */
+#define SIO_CR_ARB_DIAG_TXA 0x00000000
+#define SIO_CR_ARB_DIAG_RXA 0x00080000
+#define SIO_CR_ARB_DIAG_TXB 0x00100000
+#define SIO_CR_ARB_DIAG_RXB 0x00180000
+#define SIO_CR_ARB_DIAG_PP 0x00200000
+#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */
+
+/* defs for some of the generic I/O pins */
+#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */
+#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */
+#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */
+
+#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */
+#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin cntrling uartb modeselect */
+#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin cntrling uarta modeselect */
+
+#endif /* IA64_SN_IOC3_H */
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h
index 2b42d9ece26b..9334078b089a 100644
--- a/include/asm-ia64/sn/pcibr_provider.h
+++ b/include/asm-ia64/sn/pcibr_provider.h
@@ -44,9 +44,9 @@
#define PCI32_MAPPED_BASE 0x40000000
#define PCI32_DIRECT_BASE 0x80000000
-#define IS_PCI32_MAPPED(x) ((uint64_t)(x) < PCI32_DIRECT_BASE && \
- (uint64_t)(x) >= PCI32_MAPPED_BASE)
-#define IS_PCI32_DIRECT(x) ((uint64_t)(x) >= PCI32_MAPPED_BASE)
+#define IS_PCI32_MAPPED(x) ((u64)(x) < PCI32_DIRECT_BASE && \
+ (u64)(x) >= PCI32_MAPPED_BASE)
+#define IS_PCI32_DIRECT(x) ((u64)(x) >= PCI32_MAPPED_BASE)
/*
@@ -63,7 +63,7 @@
(IOPG(IOPGOFF(addr) + (size) - 1) == IOPG((size) - 1))
#define MINIMAL_ATE_FLAG(addr, size) \
- (MINIMAL_ATES_REQUIRED((uint64_t)addr, size) ? 1 : 0)
+ (MINIMAL_ATES_REQUIRED((u64)addr, size) ? 1 : 0)
/* bit 29 of the pci address is the SWAP bit */
#define ATE_SWAPSHIFT 29
@@ -90,27 +90,27 @@
* PMU resources.
*/
struct ate_resource{
- uint64_t *ate;
- uint64_t num_ate;
- uint64_t lowest_free_index;
+ u64 *ate;
+ u64 num_ate;
+ u64 lowest_free_index;
};
struct pcibus_info {
struct pcibus_bussoft pbi_buscommon; /* common header */
- uint32_t pbi_moduleid;
+ u32 pbi_moduleid;
short pbi_bridge_type;
short pbi_bridge_mode;
struct ate_resource pbi_int_ate_resource;
- uint64_t pbi_int_ate_size;
+ u64 pbi_int_ate_size;
- uint64_t pbi_dir_xbase;
+ u64 pbi_dir_xbase;
char pbi_hub_xid;
- uint64_t pbi_devreg[8];
+ u64 pbi_devreg[8];
- uint32_t pbi_valid_devices;
- uint32_t pbi_enabled_devices;
+ u32 pbi_valid_devices;
+ u32 pbi_enabled_devices;
spinlock_t pbi_lock;
};
@@ -136,22 +136,22 @@ extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
/*
* prototypes for the bridge asic register access routines in pcibr_reg.c
*/
-extern void pcireg_control_bit_clr(struct pcibus_info *, uint64_t);
-extern void pcireg_control_bit_set(struct pcibus_info *, uint64_t);
-extern uint64_t pcireg_tflush_get(struct pcibus_info *);
-extern uint64_t pcireg_intr_status_get(struct pcibus_info *);
-extern void pcireg_intr_enable_bit_clr(struct pcibus_info *, uint64_t);
-extern void pcireg_intr_enable_bit_set(struct pcibus_info *, uint64_t);
-extern void pcireg_intr_addr_addr_set(struct pcibus_info *, int, uint64_t);
+extern void pcireg_control_bit_clr(struct pcibus_info *, u64);
+extern void pcireg_control_bit_set(struct pcibus_info *, u64);
+extern u64 pcireg_tflush_get(struct pcibus_info *);
+extern u64 pcireg_intr_status_get(struct pcibus_info *);
+extern void pcireg_intr_enable_bit_clr(struct pcibus_info *, u64);
+extern void pcireg_intr_enable_bit_set(struct pcibus_info *, u64);
+extern void pcireg_intr_addr_addr_set(struct pcibus_info *, int, u64);
extern void pcireg_force_intr_set(struct pcibus_info *, int);
-extern uint64_t pcireg_wrb_flush_get(struct pcibus_info *, int);
-extern void pcireg_int_ate_set(struct pcibus_info *, int, uint64_t);
-extern uint64_t * pcireg_int_ate_addr(struct pcibus_info *, int);
+extern u64 pcireg_wrb_flush_get(struct pcibus_info *, int);
+extern void pcireg_int_ate_set(struct pcibus_info *, int, u64);
+extern u64 * pcireg_int_ate_addr(struct pcibus_info *, int);
extern void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info);
extern void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info);
extern int pcibr_ate_alloc(struct pcibus_info *, int);
extern void pcibr_ate_free(struct pcibus_info *, int);
-extern void ate_write(struct pcibus_info *, int, int, uint64_t);
+extern void ate_write(struct pcibus_info *, int, int, u64);
extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
void *resp);
extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h
index ad0e8e8ae53f..ce3f6c328241 100644
--- a/include/asm-ia64/sn/pcibus_provider_defs.h
+++ b/include/asm-ia64/sn/pcibus_provider_defs.h
@@ -29,13 +29,13 @@
*/
struct pcibus_bussoft {
- uint32_t bs_asic_type; /* chipset type */
- uint32_t bs_xid; /* xwidget id */
- 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 */
+ u32 bs_asic_type; /* chipset type */
+ u32 bs_xid; /* xwidget id */
+ u32 bs_persist_busnum; /* Persistent Bus Number */
+ u32 bs_persist_segment; /* Segment Number */
+ u64 bs_legacy_io; /* legacy io pio addr */
+ u64 bs_legacy_mem; /* legacy mem pio addr */
+ u64 bs_base; /* widget base */
struct xwidget_info *bs_xwidget_info;
};
diff --git a/include/asm-ia64/sn/pcidev.h b/include/asm-ia64/sn/pcidev.h
index f65d222ca5e8..38cdffbc4c7b 100644
--- a/include/asm-ia64/sn/pcidev.h
+++ b/include/asm-ia64/sn/pcidev.h
@@ -55,8 +55,8 @@ struct sn_pci_controller {
#define PCIIO_VENDOR_ID_NONE (-1)
struct pcidev_info {
- uint64_t pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */
- uint64_t pdi_slot_host_handle; /* Bus and devfn Host pci_dev */
+ u64 pdi_pio_mapped_addr[7]; /* 6 BARs PLUS 1 ROM */
+ u64 pdi_slot_host_handle; /* Bus and devfn Host pci_dev */
struct pcibus_bussoft *pdi_pcibus_info; /* Kernel common bus soft */
struct pcidev_info *pdi_host_pcidev_info; /* Kernel Host pci_dev */
diff --git a/include/asm-ia64/sn/pic.h b/include/asm-ia64/sn/pic.h
index 0de82e6b0893..5f9da5fd6e56 100644
--- a/include/asm-ia64/sn/pic.h
+++ b/include/asm-ia64/sn/pic.h
@@ -74,120 +74,120 @@ struct pic {
/* 0x000000-0x00FFFF -- Local Registers */
/* 0x000000-0x000057 -- Standard Widget Configuration */
- uint64_t p_wid_id; /* 0x000000 */
- uint64_t p_wid_stat; /* 0x000008 */
- uint64_t p_wid_err_upper; /* 0x000010 */
- uint64_t p_wid_err_lower; /* 0x000018 */
+ u64 p_wid_id; /* 0x000000 */
+ u64 p_wid_stat; /* 0x000008 */
+ u64 p_wid_err_upper; /* 0x000010 */
+ u64 p_wid_err_lower; /* 0x000018 */
#define p_wid_err p_wid_err_lower
- uint64_t p_wid_control; /* 0x000020 */
- uint64_t p_wid_req_timeout; /* 0x000028 */
- uint64_t p_wid_int_upper; /* 0x000030 */
- uint64_t p_wid_int_lower; /* 0x000038 */
+ u64 p_wid_control; /* 0x000020 */
+ u64 p_wid_req_timeout; /* 0x000028 */
+ u64 p_wid_int_upper; /* 0x000030 */
+ u64 p_wid_int_lower; /* 0x000038 */
#define p_wid_int p_wid_int_lower
- uint64_t p_wid_err_cmdword; /* 0x000040 */
- uint64_t p_wid_llp; /* 0x000048 */
- uint64_t p_wid_tflush; /* 0x000050 */
+ u64 p_wid_err_cmdword; /* 0x000040 */
+ u64 p_wid_llp; /* 0x000048 */
+ u64 p_wid_tflush; /* 0x000050 */
/* 0x000058-0x00007F -- Bridge-specific Widget Configuration */
- uint64_t p_wid_aux_err; /* 0x000058 */
- uint64_t p_wid_resp_upper; /* 0x000060 */
- uint64_t p_wid_resp_lower; /* 0x000068 */
+ u64 p_wid_aux_err; /* 0x000058 */
+ u64 p_wid_resp_upper; /* 0x000060 */
+ u64 p_wid_resp_lower; /* 0x000068 */
#define p_wid_resp p_wid_resp_lower
- uint64_t p_wid_tst_pin_ctrl; /* 0x000070 */
- uint64_t p_wid_addr_lkerr; /* 0x000078 */
+ u64 p_wid_tst_pin_ctrl; /* 0x000070 */
+ u64 p_wid_addr_lkerr; /* 0x000078 */
/* 0x000080-0x00008F -- PMU & MAP */
- uint64_t p_dir_map; /* 0x000080 */
- uint64_t _pad_000088; /* 0x000088 */
+ u64 p_dir_map; /* 0x000080 */
+ u64 _pad_000088; /* 0x000088 */
/* 0x000090-0x00009F -- SSRAM */
- uint64_t p_map_fault; /* 0x000090 */
- uint64_t _pad_000098; /* 0x000098 */
+ u64 p_map_fault; /* 0x000090 */
+ u64 _pad_000098; /* 0x000098 */
/* 0x0000A0-0x0000AF -- Arbitration */
- uint64_t p_arb; /* 0x0000A0 */
- uint64_t _pad_0000A8; /* 0x0000A8 */
+ u64 p_arb; /* 0x0000A0 */
+ u64 _pad_0000A8; /* 0x0000A8 */
/* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
- uint64_t p_ate_parity_err; /* 0x0000B0 */
- uint64_t _pad_0000B8; /* 0x0000B8 */
+ u64 p_ate_parity_err; /* 0x0000B0 */
+ u64 _pad_0000B8; /* 0x0000B8 */
/* 0x0000C0-0x0000FF -- PCI/GIO */
- uint64_t p_bus_timeout; /* 0x0000C0 */
- uint64_t p_pci_cfg; /* 0x0000C8 */
- uint64_t p_pci_err_upper; /* 0x0000D0 */
- uint64_t p_pci_err_lower; /* 0x0000D8 */
+ u64 p_bus_timeout; /* 0x0000C0 */
+ u64 p_pci_cfg; /* 0x0000C8 */
+ u64 p_pci_err_upper; /* 0x0000D0 */
+ u64 p_pci_err_lower; /* 0x0000D8 */
#define p_pci_err p_pci_err_lower
- uint64_t _pad_0000E0[4]; /* 0x0000{E0..F8} */
+ u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */
/* 0x000100-0x0001FF -- Interrupt */
- uint64_t p_int_status; /* 0x000100 */
- uint64_t p_int_enable; /* 0x000108 */
- uint64_t p_int_rst_stat; /* 0x000110 */
- uint64_t p_int_mode; /* 0x000118 */
- uint64_t p_int_device; /* 0x000120 */
- uint64_t p_int_host_err; /* 0x000128 */
- uint64_t p_int_addr[8]; /* 0x0001{30,,,68} */
- uint64_t p_err_int_view; /* 0x000170 */
- uint64_t p_mult_int; /* 0x000178 */
- uint64_t p_force_always[8]; /* 0x0001{80,,,B8} */
- uint64_t p_force_pin[8]; /* 0x0001{C0,,,F8} */
+ u64 p_int_status; /* 0x000100 */
+ u64 p_int_enable; /* 0x000108 */
+ u64 p_int_rst_stat; /* 0x000110 */
+ u64 p_int_mode; /* 0x000118 */
+ u64 p_int_device; /* 0x000120 */
+ u64 p_int_host_err; /* 0x000128 */
+ u64 p_int_addr[8]; /* 0x0001{30,,,68} */
+ u64 p_err_int_view; /* 0x000170 */
+ u64 p_mult_int; /* 0x000178 */
+ u64 p_force_always[8]; /* 0x0001{80,,,B8} */
+ u64 p_force_pin[8]; /* 0x0001{C0,,,F8} */
/* 0x000200-0x000298 -- Device */
- uint64_t p_device[4]; /* 0x0002{00,,,18} */
- uint64_t _pad_000220[4]; /* 0x0002{20,,,38} */
- uint64_t p_wr_req_buf[4]; /* 0x0002{40,,,58} */
- uint64_t _pad_000260[4]; /* 0x0002{60,,,78} */
- uint64_t p_rrb_map[2]; /* 0x0002{80,,,88} */
+ u64 p_device[4]; /* 0x0002{00,,,18} */
+ u64 _pad_000220[4]; /* 0x0002{20,,,38} */
+ u64 p_wr_req_buf[4]; /* 0x0002{40,,,58} */
+ u64 _pad_000260[4]; /* 0x0002{60,,,78} */
+ u64 p_rrb_map[2]; /* 0x0002{80,,,88} */
#define p_even_resp p_rrb_map[0] /* 0x000280 */
#define p_odd_resp p_rrb_map[1] /* 0x000288 */
- uint64_t p_resp_status; /* 0x000290 */
- uint64_t p_resp_clear; /* 0x000298 */
+ u64 p_resp_status; /* 0x000290 */
+ u64 p_resp_clear; /* 0x000298 */
- uint64_t _pad_0002A0[12]; /* 0x0002{A0..F8} */
+ u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */
/* 0x000300-0x0003F8 -- Buffer Address Match Registers */
struct {
- uint64_t upper; /* 0x0003{00,,,F0} */
- uint64_t lower; /* 0x0003{08,,,F8} */
+ u64 upper; /* 0x0003{00,,,F0} */
+ u64 lower; /* 0x0003{08,,,F8} */
} p_buf_addr_match[16];
/* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
struct {
- uint64_t flush_w_touch; /* 0x000{400,,,5C0} */
- uint64_t flush_wo_touch; /* 0x000{408,,,5C8} */
- uint64_t inflight; /* 0x000{410,,,5D0} */
- uint64_t prefetch; /* 0x000{418,,,5D8} */
- uint64_t total_pci_retry; /* 0x000{420,,,5E0} */
- uint64_t max_pci_retry; /* 0x000{428,,,5E8} */
- uint64_t max_latency; /* 0x000{430,,,5F0} */
- uint64_t clear_all; /* 0x000{438,,,5F8} */
+ u64 flush_w_touch; /* 0x000{400,,,5C0} */
+ u64 flush_wo_touch; /* 0x000{408,,,5C8} */
+ u64 inflight; /* 0x000{410,,,5D0} */
+ u64 prefetch; /* 0x000{418,,,5D8} */
+ u64 total_pci_retry; /* 0x000{420,,,5E0} */
+ u64 max_pci_retry; /* 0x000{428,,,5E8} */
+ u64 max_latency; /* 0x000{430,,,5F0} */
+ u64 clear_all; /* 0x000{438,,,5F8} */
} p_buf_count[8];
/* 0x000600-0x0009FF -- PCI/X registers */
- uint64_t p_pcix_bus_err_addr; /* 0x000600 */
- uint64_t p_pcix_bus_err_attr; /* 0x000608 */
- uint64_t p_pcix_bus_err_data; /* 0x000610 */
- uint64_t p_pcix_pio_split_addr; /* 0x000618 */
- uint64_t p_pcix_pio_split_attr; /* 0x000620 */
- uint64_t p_pcix_dma_req_err_attr; /* 0x000628 */
- uint64_t p_pcix_dma_req_err_addr; /* 0x000630 */
- uint64_t p_pcix_timeout; /* 0x000638 */
+ u64 p_pcix_bus_err_addr; /* 0x000600 */
+ u64 p_pcix_bus_err_attr; /* 0x000608 */
+ u64 p_pcix_bus_err_data; /* 0x000610 */
+ u64 p_pcix_pio_split_addr; /* 0x000618 */
+ u64 p_pcix_pio_split_attr; /* 0x000620 */
+ u64 p_pcix_dma_req_err_attr; /* 0x000628 */
+ u64 p_pcix_dma_req_err_addr; /* 0x000630 */
+ u64 p_pcix_timeout; /* 0x000638 */
- uint64_t _pad_000640[120]; /* 0x000{640,,,9F8} */
+ u64 _pad_000640[120]; /* 0x000{640,,,9F8} */
/* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
struct {
- uint64_t p_buf_addr; /* 0x000{A00,,,AF0} */
- uint64_t p_buf_attr; /* 0X000{A08,,,AF8} */
+ u64 p_buf_addr; /* 0x000{A00,,,AF0} */
+ u64 p_buf_attr; /* 0X000{A08,,,AF8} */
} p_pcix_read_buf_64[16];
struct {
- uint64_t p_buf_addr; /* 0x000{B00,,,BE0} */
- uint64_t p_buf_attr; /* 0x000{B08,,,BE8} */
- uint64_t p_buf_valid; /* 0x000{B10,,,BF0} */
- uint64_t __pad1; /* 0x000{B18,,,BF8} */
+ u64 p_buf_addr; /* 0x000{B00,,,BE0} */
+ u64 p_buf_attr; /* 0x000{B08,,,BE8} */
+ u64 p_buf_valid; /* 0x000{B10,,,BF0} */
+ u64 __pad1; /* 0x000{B18,,,BF8} */
} p_pcix_write_buf_64[8];
/* End of Local Registers -- Start of Address Map space */
@@ -195,45 +195,45 @@ struct pic {
char _pad_000c00[0x010000 - 0x000c00];
/* 0x010000-0x011fff -- Internal ATE RAM (Auto Parity Generation) */
- uint64_t p_int_ate_ram[1024]; /* 0x010000-0x011fff */
+ u64 p_int_ate_ram[1024]; /* 0x010000-0x011fff */
/* 0x012000-0x013fff -- Internal ATE RAM (Manual Parity Generation) */
- uint64_t p_int_ate_ram_mp[1024]; /* 0x012000-0x013fff */
+ u64 p_int_ate_ram_mp[1024]; /* 0x012000-0x013fff */
char _pad_014000[0x18000 - 0x014000];
/* 0x18000-0x197F8 -- PIC Write Request Ram */
- uint64_t p_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
- uint64_t p_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
- uint64_t p_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
+ u64 p_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
+ u64 p_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
+ u64 p_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
char _pad_019800[0x20000 - 0x019800];
/* 0x020000-0x027FFF -- PCI Device Configuration Spaces */
union {
- uint8_t c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
- uint16_t s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
- uint32_t l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
- uint64_t d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
+ u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
+ u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
+ u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
+ u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
union {
- uint8_t c[0x100 / 1];
- uint16_t s[0x100 / 2];
- uint32_t l[0x100 / 4];
- uint64_t d[0x100 / 8];
+ u8 c[0x100 / 1];
+ u16 s[0x100 / 2];
+ u32 l[0x100 / 4];
+ u64 d[0x100 / 8];
} f[8];
} p_type0_cfg_dev[8]; /* 0x02{0000,,,7FFF} */
/* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
union {
- uint8_t c[0x1000 / 1]; /* 0x028000-0x029000 */
- uint16_t s[0x1000 / 2]; /* 0x028000-0x029000 */
- uint32_t l[0x1000 / 4]; /* 0x028000-0x029000 */
- uint64_t d[0x1000 / 8]; /* 0x028000-0x029000 */
+ u8 c[0x1000 / 1]; /* 0x028000-0x029000 */
+ u16 s[0x1000 / 2]; /* 0x028000-0x029000 */
+ u32 l[0x1000 / 4]; /* 0x028000-0x029000 */
+ u64 d[0x1000 / 8]; /* 0x028000-0x029000 */
union {
- uint8_t c[0x100 / 1];
- uint16_t s[0x100 / 2];
- uint32_t l[0x100 / 4];
- uint64_t d[0x100 / 8];
+ u8 c[0x100 / 1];
+ u16 s[0x100 / 2];
+ u32 l[0x100 / 4];
+ u64 d[0x100 / 8];
} f[8];
} p_type1_cfg; /* 0x028000-0x029000 */
@@ -241,20 +241,20 @@ struct pic {
/* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
union {
- uint8_t c[8 / 1];
- uint16_t s[8 / 2];
- uint32_t l[8 / 4];
- uint64_t d[8 / 8];
+ u8 c[8 / 1];
+ u16 s[8 / 2];
+ u32 l[8 / 4];
+ u64 d[8 / 8];
} p_pci_iack; /* 0x030000-0x030007 */
char _pad_030007[0x040000-0x030008];
/* 0x040000-0x030007 -- PCIX Special Cycle */
union {
- uint8_t c[8 / 1];
- uint16_t s[8 / 2];
- uint32_t l[8 / 4];
- uint64_t d[8 / 8];
+ u8 c[8 / 1];
+ u16 s[8 / 2];
+ u32 l[8 / 4];
+ u64 d[8 / 8];
} p_pcix_cycle; /* 0x040000-0x040007 */
};
diff --git a/include/asm-ia64/sn/shubio.h b/include/asm-ia64/sn/shubio.h
index 831b72111fdc..22a6f18a5313 100644
--- a/include/asm-ia64/sn/shubio.h
+++ b/include/asm-ia64/sn/shubio.h
@@ -227,13 +227,13 @@
************************************************************************/
typedef union ii_wid_u {
- uint64_t ii_wid_regval;
+ u64 ii_wid_regval;
struct {
- uint64_t w_rsvd_1:1;
- uint64_t w_mfg_num:11;
- uint64_t w_part_num:16;
- uint64_t w_rev_num:4;
- uint64_t w_rsvd:32;
+ u64 w_rsvd_1:1;
+ u64 w_mfg_num:11;
+ u64 w_part_num:16;
+ u64 w_rev_num:4;
+ u64 w_rsvd:32;
} ii_wid_fld_s;
} ii_wid_u_t;
@@ -246,18 +246,18 @@ typedef union ii_wid_u {
************************************************************************/
typedef union ii_wstat_u {
- uint64_t ii_wstat_regval;
- struct {
- uint64_t w_pending:4;
- uint64_t w_xt_crd_to:1;
- uint64_t w_xt_tail_to:1;
- uint64_t w_rsvd_3:3;
- uint64_t w_tx_mx_rty:1;
- uint64_t w_rsvd_2:6;
- uint64_t w_llp_tx_cnt:8;
- uint64_t w_rsvd_1:8;
- uint64_t w_crazy:1;
- uint64_t w_rsvd:31;
+ u64 ii_wstat_regval;
+ struct {
+ u64 w_pending:4;
+ u64 w_xt_crd_to:1;
+ u64 w_xt_tail_to:1;
+ u64 w_rsvd_3:3;
+ u64 w_tx_mx_rty:1;
+ u64 w_rsvd_2:6;
+ u64 w_llp_tx_cnt:8;
+ u64 w_rsvd_1:8;
+ u64 w_crazy:1;
+ u64 w_rsvd:31;
} ii_wstat_fld_s;
} ii_wstat_u_t;
@@ -269,16 +269,16 @@ typedef union ii_wstat_u {
************************************************************************/
typedef union ii_wcr_u {
- uint64_t ii_wcr_regval;
- struct {
- uint64_t w_wid:4;
- uint64_t w_tag:1;
- uint64_t w_rsvd_1:8;
- uint64_t w_dst_crd:3;
- uint64_t w_f_bad_pkt:1;
- uint64_t w_dir_con:1;
- uint64_t w_e_thresh:5;
- uint64_t w_rsvd:41;
+ u64 ii_wcr_regval;
+ struct {
+ u64 w_wid:4;
+ u64 w_tag:1;
+ u64 w_rsvd_1:8;
+ u64 w_dst_crd:3;
+ u64 w_f_bad_pkt:1;
+ u64 w_dir_con:1;
+ u64 w_e_thresh:5;
+ u64 w_rsvd:41;
} ii_wcr_fld_s;
} ii_wcr_u_t;
@@ -310,9 +310,9 @@ typedef union ii_wcr_u {
************************************************************************/
typedef union ii_ilapr_u {
- uint64_t ii_ilapr_regval;
+ u64 ii_ilapr_regval;
struct {
- uint64_t i_region:64;
+ u64 i_region:64;
} ii_ilapr_fld_s;
} ii_ilapr_u_t;
@@ -330,9 +330,9 @@ typedef union ii_ilapr_u {
************************************************************************/
typedef union ii_ilapo_u {
- uint64_t ii_ilapo_regval;
+ u64 ii_ilapo_regval;
struct {
- uint64_t i_io_ovrride:64;
+ u64 i_io_ovrride:64;
} ii_ilapo_fld_s;
} ii_ilapo_u_t;
@@ -344,12 +344,12 @@ typedef union ii_ilapo_u {
************************************************************************/
typedef union ii_iowa_u {
- uint64_t ii_iowa_regval;
+ u64 ii_iowa_regval;
struct {
- uint64_t i_w0_oac:1;
- uint64_t i_rsvd_1:7;
- uint64_t i_wx_oac:8;
- uint64_t i_rsvd:48;
+ u64 i_w0_oac:1;
+ u64 i_rsvd_1:7;
+ u64 i_wx_oac:8;
+ u64 i_rsvd:48;
} ii_iowa_fld_s;
} ii_iowa_u_t;
@@ -363,12 +363,12 @@ typedef union ii_iowa_u {
************************************************************************/
typedef union ii_iiwa_u {
- uint64_t ii_iiwa_regval;
+ u64 ii_iiwa_regval;
struct {
- uint64_t i_w0_iac:1;
- uint64_t i_rsvd_1:7;
- uint64_t i_wx_iac:8;
- uint64_t i_rsvd:48;
+ u64 i_w0_iac:1;
+ u64 i_rsvd_1:7;
+ u64 i_wx_iac:8;
+ u64 i_rsvd:48;
} ii_iiwa_fld_s;
} ii_iiwa_u_t;
@@ -392,16 +392,16 @@ typedef union ii_iiwa_u {
************************************************************************/
typedef union ii_iidem_u {
- uint64_t ii_iidem_regval;
- struct {
- uint64_t i_w8_dxs:8;
- uint64_t i_w9_dxs:8;
- uint64_t i_wa_dxs:8;
- uint64_t i_wb_dxs:8;
- uint64_t i_wc_dxs:8;
- uint64_t i_wd_dxs:8;
- uint64_t i_we_dxs:8;
- uint64_t i_wf_dxs:8;
+ u64 ii_iidem_regval;
+ struct {
+ u64 i_w8_dxs:8;
+ u64 i_w9_dxs:8;
+ u64 i_wa_dxs:8;
+ u64 i_wb_dxs:8;
+ u64 i_wc_dxs:8;
+ u64 i_wd_dxs:8;
+ u64 i_we_dxs:8;
+ u64 i_wf_dxs:8;
} ii_iidem_fld_s;
} ii_iidem_u_t;
@@ -413,22 +413,22 @@ typedef union ii_iidem_u {
************************************************************************/
typedef union ii_ilcsr_u {
- uint64_t ii_ilcsr_regval;
- struct {
- uint64_t i_nullto:6;
- uint64_t i_rsvd_4:2;
- uint64_t i_wrmrst:1;
- uint64_t i_rsvd_3:1;
- uint64_t i_llp_en:1;
- uint64_t i_bm8:1;
- uint64_t i_llp_stat:2;
- uint64_t i_remote_power:1;
- uint64_t i_rsvd_2:1;
- uint64_t i_maxrtry:10;
- uint64_t i_d_avail_sel:2;
- uint64_t i_rsvd_1:4;
- uint64_t i_maxbrst:10;
- uint64_t i_rsvd:22;
+ u64 ii_ilcsr_regval;
+ struct {
+ u64 i_nullto:6;
+ u64 i_rsvd_4:2;
+ u64 i_wrmrst:1;
+ u64 i_rsvd_3:1;
+ u64 i_llp_en:1;
+ u64 i_bm8:1;
+ u64 i_llp_stat:2;
+ u64 i_remote_power:1;
+ u64 i_rsvd_2:1;
+ u64 i_maxrtry:10;
+ u64 i_d_avail_sel:2;
+ u64 i_rsvd_1:4;
+ u64 i_maxbrst:10;
+ u64 i_rsvd:22;
} ii_ilcsr_fld_s;
} ii_ilcsr_u_t;
@@ -441,11 +441,11 @@ typedef union ii_ilcsr_u {
************************************************************************/
typedef union ii_illr_u {
- uint64_t ii_illr_regval;
+ u64 ii_illr_regval;
struct {
- uint64_t i_sn_cnt:16;
- uint64_t i_cb_cnt:16;
- uint64_t i_rsvd:32;
+ u64 i_sn_cnt:16;
+ u64 i_cb_cnt:16;
+ u64 i_rsvd:32;
} ii_illr_fld_s;
} ii_illr_u_t;
@@ -464,19 +464,19 @@ typedef union ii_illr_u {
************************************************************************/
typedef union ii_iidsr_u {
- uint64_t ii_iidsr_regval;
- struct {
- uint64_t i_level:8;
- uint64_t i_pi_id:1;
- uint64_t i_node:11;
- uint64_t i_rsvd_3:4;
- uint64_t i_enable:1;
- uint64_t i_rsvd_2:3;
- uint64_t i_int_sent:2;
- uint64_t i_rsvd_1:2;
- uint64_t i_pi0_forward_int:1;
- uint64_t i_pi1_forward_int:1;
- uint64_t i_rsvd:30;
+ u64 ii_iidsr_regval;
+ struct {
+ u64 i_level:8;
+ u64 i_pi_id:1;
+ u64 i_node:11;
+ u64 i_rsvd_3:4;
+ u64 i_enable:1;
+ u64 i_rsvd_2:3;
+ u64 i_int_sent:2;
+ u64 i_rsvd_1:2;
+ u64 i_pi0_forward_int:1;
+ u64 i_pi1_forward_int:1;
+ u64 i_rsvd:30;
} ii_iidsr_fld_s;
} ii_iidsr_u_t;
@@ -492,13 +492,13 @@ typedef union ii_iidsr_u {
************************************************************************/
typedef union ii_igfx0_u {
- uint64_t ii_igfx0_regval;
+ u64 ii_igfx0_regval;
struct {
- uint64_t i_w_num:4;
- uint64_t i_pi_id:1;
- uint64_t i_n_num:12;
- uint64_t i_p_num:1;
- uint64_t i_rsvd:46;
+ u64 i_w_num:4;
+ u64 i_pi_id:1;
+ u64 i_n_num:12;
+ u64 i_p_num:1;
+ u64 i_rsvd:46;
} ii_igfx0_fld_s;
} ii_igfx0_u_t;
@@ -514,13 +514,13 @@ typedef union ii_igfx0_u {
************************************************************************/
typedef union ii_igfx1_u {
- uint64_t ii_igfx1_regval;
+ u64 ii_igfx1_regval;
struct {
- uint64_t i_w_num:4;
- uint64_t i_pi_id:1;
- uint64_t i_n_num:12;
- uint64_t i_p_num:1;
- uint64_t i_rsvd:46;
+ u64 i_w_num:4;
+ u64 i_pi_id:1;
+ u64 i_n_num:12;
+ u64 i_p_num:1;
+ u64 i_rsvd:46;
} ii_igfx1_fld_s;
} ii_igfx1_u_t;
@@ -532,9 +532,9 @@ typedef union ii_igfx1_u {
************************************************************************/
typedef union ii_iscr0_u {
- uint64_t ii_iscr0_regval;
+ u64 ii_iscr0_regval;
struct {
- uint64_t i_scratch:64;
+ u64 i_scratch:64;
} ii_iscr0_fld_s;
} ii_iscr0_u_t;
@@ -546,9 +546,9 @@ typedef union ii_iscr0_u {
************************************************************************/
typedef union ii_iscr1_u {
- uint64_t ii_iscr1_regval;
+ u64 ii_iscr1_regval;
struct {
- uint64_t i_scratch:64;
+ u64 i_scratch:64;
} ii_iscr1_fld_s;
} ii_iscr1_u_t;
@@ -580,13 +580,13 @@ typedef union ii_iscr1_u {
************************************************************************/
typedef union ii_itte1_u {
- uint64_t ii_itte1_regval;
+ u64 ii_itte1_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte1_fld_s;
} ii_itte1_u_t;
@@ -618,13 +618,13 @@ typedef union ii_itte1_u {
************************************************************************/
typedef union ii_itte2_u {
- uint64_t ii_itte2_regval;
+ u64 ii_itte2_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte2_fld_s;
} ii_itte2_u_t;
@@ -656,13 +656,13 @@ typedef union ii_itte2_u {
************************************************************************/
typedef union ii_itte3_u {
- uint64_t ii_itte3_regval;
+ u64 ii_itte3_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte3_fld_s;
} ii_itte3_u_t;
@@ -694,13 +694,13 @@ typedef union ii_itte3_u {
************************************************************************/
typedef union ii_itte4_u {
- uint64_t ii_itte4_regval;
+ u64 ii_itte4_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte4_fld_s;
} ii_itte4_u_t;
@@ -732,13 +732,13 @@ typedef union ii_itte4_u {
************************************************************************/
typedef union ii_itte5_u {
- uint64_t ii_itte5_regval;
+ u64 ii_itte5_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte5_fld_s;
} ii_itte5_u_t;
@@ -770,13 +770,13 @@ typedef union ii_itte5_u {
************************************************************************/
typedef union ii_itte6_u {
- uint64_t ii_itte6_regval;
+ u64 ii_itte6_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte6_fld_s;
} ii_itte6_u_t;
@@ -808,13 +808,13 @@ typedef union ii_itte6_u {
************************************************************************/
typedef union ii_itte7_u {
- uint64_t ii_itte7_regval;
+ u64 ii_itte7_regval;
struct {
- uint64_t i_offset:5;
- uint64_t i_rsvd_1:3;
- uint64_t i_w_num:4;
- uint64_t i_iosp:1;
- uint64_t i_rsvd:51;
+ u64 i_offset:5;
+ u64 i_rsvd_1:3;
+ u64 i_w_num:4;
+ u64 i_iosp:1;
+ u64 i_rsvd:51;
} ii_itte7_fld_s;
} ii_itte7_u_t;
@@ -843,22 +843,22 @@ typedef union ii_itte7_u {
************************************************************************/
typedef union ii_iprb0_u {
- uint64_t ii_iprb0_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprb0_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprb0_fld_s;
} ii_iprb0_u_t;
@@ -887,22 +887,22 @@ typedef union ii_iprb0_u {
************************************************************************/
typedef union ii_iprb8_u {
- uint64_t ii_iprb8_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprb8_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprb8_fld_s;
} ii_iprb8_u_t;
@@ -931,22 +931,22 @@ typedef union ii_iprb8_u {
************************************************************************/
typedef union ii_iprb9_u {
- uint64_t ii_iprb9_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprb9_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprb9_fld_s;
} ii_iprb9_u_t;
@@ -975,22 +975,22 @@ typedef union ii_iprb9_u {
************************************************************************/
typedef union ii_iprba_u {
- uint64_t ii_iprba_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprba_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprba_fld_s;
} ii_iprba_u_t;
@@ -1019,22 +1019,22 @@ typedef union ii_iprba_u {
************************************************************************/
typedef union ii_iprbb_u {
- uint64_t ii_iprbb_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprbb_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprbb_fld_s;
} ii_iprbb_u_t;
@@ -1063,22 +1063,22 @@ typedef union ii_iprbb_u {
************************************************************************/
typedef union ii_iprbc_u {
- uint64_t ii_iprbc_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprbc_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprbc_fld_s;
} ii_iprbc_u_t;
@@ -1107,22 +1107,22 @@ typedef union ii_iprbc_u {
************************************************************************/
typedef union ii_iprbd_u {
- uint64_t ii_iprbd_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprbd_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprbd_fld_s;
} ii_iprbd_u_t;
@@ -1151,22 +1151,22 @@ typedef union ii_iprbd_u {
************************************************************************/
typedef union ii_iprbe_u {
- uint64_t ii_iprbe_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprbe_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprbe_fld_s;
} ii_iprbe_u_t;
@@ -1195,22 +1195,22 @@ typedef union ii_iprbe_u {
************************************************************************/
typedef union ii_iprbf_u {
- uint64_t ii_iprbf_regval;
- struct {
- uint64_t i_c:8;
- uint64_t i_na:14;
- uint64_t i_rsvd_2:2;
- uint64_t i_nb:14;
- uint64_t i_rsvd_1:2;
- uint64_t i_m:2;
- uint64_t i_f:1;
- uint64_t i_of_cnt:5;
- uint64_t i_error:1;
- uint64_t i_rd_to:1;
- uint64_t i_spur_wr:1;
- uint64_t i_spur_rd:1;
- uint64_t i_rsvd:11;
- uint64_t i_mult_err:1;
+ u64 ii_iprbf_regval;
+ struct {
+ u64 i_c:8;
+ u64 i_na:14;
+ u64 i_rsvd_2:2;
+ u64 i_nb:14;
+ u64 i_rsvd_1:2;
+ u64 i_m:2;
+ u64 i_f:1;
+ u64 i_of_cnt:5;
+ u64 i_error:1;
+ u64 i_rd_to:1;
+ u64 i_spur_wr:1;
+ u64 i_spur_rd:1;
+ u64 i_rsvd:11;
+ u64 i_mult_err:1;
} ii_iprbe_fld_s;
} ii_iprbf_u_t;
@@ -1232,10 +1232,10 @@ typedef union ii_iprbf_u {
************************************************************************/
typedef union ii_ixcc_u {
- uint64_t ii_ixcc_regval;
+ u64 ii_ixcc_regval;
struct {
- uint64_t i_time_out:26;
- uint64_t i_rsvd:38;
+ u64 i_time_out:26;
+ u64 i_rsvd:38;
} ii_ixcc_fld_s;
} ii_ixcc_u_t;
@@ -1256,16 +1256,16 @@ typedef union ii_ixcc_u {
************************************************************************/
typedef union ii_imem_u {
- uint64_t ii_imem_regval;
- struct {
- uint64_t i_w0_esd:1;
- uint64_t i_rsvd_3:3;
- uint64_t i_b0_esd:1;
- uint64_t i_rsvd_2:3;
- uint64_t i_b1_esd:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_clr_precise:1;
- uint64_t i_rsvd:51;
+ u64 ii_imem_regval;
+ struct {
+ u64 i_w0_esd:1;
+ u64 i_rsvd_3:3;
+ u64 i_b0_esd:1;
+ u64 i_rsvd_2:3;
+ u64 i_b1_esd:1;
+ u64 i_rsvd_1:3;
+ u64 i_clr_precise:1;
+ u64 i_rsvd:51;
} ii_imem_fld_s;
} ii_imem_u_t;
@@ -1294,13 +1294,13 @@ typedef union ii_imem_u {
************************************************************************/
typedef union ii_ixtt_u {
- uint64_t ii_ixtt_regval;
+ u64 ii_ixtt_regval;
struct {
- uint64_t i_tail_to:26;
- uint64_t i_rsvd_1:6;
- uint64_t i_rrsp_ps:23;
- uint64_t i_rrsp_to:5;
- uint64_t i_rsvd:4;
+ u64 i_tail_to:26;
+ u64 i_rsvd_1:6;
+ u64 i_rrsp_ps:23;
+ u64 i_rrsp_to:5;
+ u64 i_rsvd:4;
} ii_ixtt_fld_s;
} ii_ixtt_u_t;
@@ -1316,37 +1316,37 @@ typedef union ii_ixtt_u {
************************************************************************/
typedef union ii_ieclr_u {
- uint64_t ii_ieclr_regval;
- struct {
- uint64_t i_e_prb_0:1;
- uint64_t i_rsvd:7;
- uint64_t i_e_prb_8:1;
- uint64_t i_e_prb_9:1;
- uint64_t i_e_prb_a:1;
- uint64_t i_e_prb_b:1;
- uint64_t i_e_prb_c:1;
- uint64_t i_e_prb_d:1;
- uint64_t i_e_prb_e:1;
- uint64_t i_e_prb_f:1;
- uint64_t i_e_crazy:1;
- uint64_t i_e_bte_0:1;
- uint64_t i_e_bte_1:1;
- uint64_t i_reserved_1:10;
- uint64_t i_spur_rd_hdr:1;
- uint64_t i_cam_intr_to:1;
- uint64_t i_cam_overflow:1;
- uint64_t i_cam_read_miss:1;
- uint64_t i_ioq_rep_underflow:1;
- uint64_t i_ioq_req_underflow:1;
- uint64_t i_ioq_rep_overflow:1;
- uint64_t i_ioq_req_overflow:1;
- uint64_t i_iiq_rep_overflow:1;
- uint64_t i_iiq_req_overflow:1;
- uint64_t i_ii_xn_rep_cred_overflow:1;
- uint64_t i_ii_xn_req_cred_overflow:1;
- uint64_t i_ii_xn_invalid_cmd:1;
- uint64_t i_xn_ii_invalid_cmd:1;
- uint64_t i_reserved_2:21;
+ u64 ii_ieclr_regval;
+ struct {
+ u64 i_e_prb_0:1;
+ u64 i_rsvd:7;
+ u64 i_e_prb_8:1;
+ u64 i_e_prb_9:1;
+ u64 i_e_prb_a:1;
+ u64 i_e_prb_b:1;
+ u64 i_e_prb_c:1;
+ u64 i_e_prb_d:1;
+ u64 i_e_prb_e:1;
+ u64 i_e_prb_f:1;
+ u64 i_e_crazy:1;
+ u64 i_e_bte_0:1;
+ u64 i_e_bte_1:1;
+ u64 i_reserved_1:10;
+ u64 i_spur_rd_hdr:1;
+ u64 i_cam_intr_to:1;
+ u64 i_cam_overflow:1;
+ u64 i_cam_read_miss:1;
+ u64 i_ioq_rep_underflow:1;
+ u64 i_ioq_req_underflow:1;
+ u64 i_ioq_rep_overflow:1;
+ u64 i_ioq_req_overflow:1;
+ u64 i_iiq_rep_overflow:1;
+ u64 i_iiq_req_overflow:1;
+ u64 i_ii_xn_rep_cred_overflow:1;
+ u64 i_ii_xn_req_cred_overflow:1;
+ u64 i_ii_xn_invalid_cmd:1;
+ u64 i_xn_ii_invalid_cmd:1;
+ u64 i_reserved_2:21;
} ii_ieclr_fld_s;
} ii_ieclr_u_t;
@@ -1360,12 +1360,12 @@ typedef union ii_ieclr_u {
************************************************************************/
typedef union ii_ibcr_u {
- uint64_t ii_ibcr_regval;
+ u64 ii_ibcr_regval;
struct {
- uint64_t i_count:4;
- uint64_t i_rsvd_1:4;
- uint64_t i_soft_reset:1;
- uint64_t i_rsvd:55;
+ u64 i_count:4;
+ u64 i_rsvd_1:4;
+ u64 i_soft_reset:1;
+ u64 i_rsvd:55;
} ii_ibcr_fld_s;
} ii_ibcr_u_t;
@@ -1399,22 +1399,22 @@ typedef union ii_ibcr_u {
************************************************************************/
typedef union ii_ixsm_u {
- uint64_t ii_ixsm_regval;
- struct {
- uint64_t i_byte_en:32;
- uint64_t i_reserved:1;
- uint64_t i_tag:3;
- uint64_t i_alt_pactyp:4;
- uint64_t i_bo:1;
- uint64_t i_error:1;
- uint64_t i_vbpm:1;
- uint64_t i_gbr:1;
- uint64_t i_ds:2;
- uint64_t i_ct:1;
- uint64_t i_tnum:5;
- uint64_t i_pactyp:4;
- uint64_t i_sidn:4;
- uint64_t i_didn:4;
+ u64 ii_ixsm_regval;
+ struct {
+ u64 i_byte_en:32;
+ u64 i_reserved:1;
+ u64 i_tag:3;
+ u64 i_alt_pactyp:4;
+ u64 i_bo:1;
+ u64 i_error:1;
+ u64 i_vbpm:1;
+ u64 i_gbr:1;
+ u64 i_ds:2;
+ u64 i_ct:1;
+ u64 i_tnum:5;
+ u64 i_pactyp:4;
+ u64 i_sidn:4;
+ u64 i_didn:4;
} ii_ixsm_fld_s;
} ii_ixsm_u_t;
@@ -1426,11 +1426,11 @@ typedef union ii_ixsm_u {
************************************************************************/
typedef union ii_ixss_u {
- uint64_t ii_ixss_regval;
+ u64 ii_ixss_regval;
struct {
- uint64_t i_sideband:8;
- uint64_t i_rsvd:55;
- uint64_t i_valid:1;
+ u64 i_sideband:8;
+ u64 i_rsvd:55;
+ u64 i_valid:1;
} ii_ixss_fld_s;
} ii_ixss_u_t;
@@ -1447,17 +1447,17 @@ typedef union ii_ixss_u {
************************************************************************/
typedef union ii_ilct_u {
- uint64_t ii_ilct_regval;
- struct {
- uint64_t i_test_seed:20;
- uint64_t i_test_mask:8;
- uint64_t i_test_data:20;
- uint64_t i_test_valid:1;
- uint64_t i_test_cberr:1;
- uint64_t i_test_flit:3;
- uint64_t i_test_clear:1;
- uint64_t i_test_err_capture:1;
- uint64_t i_rsvd:9;
+ u64 ii_ilct_regval;
+ struct {
+ u64 i_test_seed:20;
+ u64 i_test_mask:8;
+ u64 i_test_data:20;
+ u64 i_test_valid:1;
+ u64 i_test_cberr:1;
+ u64 i_test_flit:3;
+ u64 i_test_clear:1;
+ u64 i_test_err_capture:1;
+ u64 i_rsvd:9;
} ii_ilct_fld_s;
} ii_ilct_u_t;
@@ -1482,20 +1482,20 @@ typedef union ii_ilct_u {
************************************************************************/
typedef union ii_iieph1_u {
- uint64_t ii_iieph1_regval;
- struct {
- uint64_t i_command:7;
- uint64_t i_rsvd_5:1;
- uint64_t i_suppl:14;
- uint64_t i_rsvd_4:1;
- uint64_t i_source:14;
- uint64_t i_rsvd_3:1;
- uint64_t i_err_type:4;
- uint64_t i_rsvd_2:4;
- uint64_t i_overrun:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_valid:1;
- uint64_t i_rsvd:13;
+ u64 ii_iieph1_regval;
+ struct {
+ u64 i_command:7;
+ u64 i_rsvd_5:1;
+ u64 i_suppl:14;
+ u64 i_rsvd_4:1;
+ u64 i_source:14;
+ u64 i_rsvd_3:1;
+ u64 i_err_type:4;
+ u64 i_rsvd_2:4;
+ u64 i_overrun:1;
+ u64 i_rsvd_1:3;
+ u64 i_valid:1;
+ u64 i_rsvd:13;
} ii_iieph1_fld_s;
} ii_iieph1_u_t;
@@ -1511,13 +1511,13 @@ typedef union ii_iieph1_u {
************************************************************************/
typedef union ii_iieph2_u {
- uint64_t ii_iieph2_regval;
+ u64 ii_iieph2_regval;
struct {
- uint64_t i_rsvd_0:3;
- uint64_t i_address:47;
- uint64_t i_rsvd_1:10;
- uint64_t i_tail:1;
- uint64_t i_rsvd:3;
+ u64 i_rsvd_0:3;
+ u64 i_address:47;
+ u64 i_rsvd_1:10;
+ u64 i_tail:1;
+ u64 i_rsvd:3;
} ii_iieph2_fld_s;
} ii_iieph2_u_t;
@@ -1532,9 +1532,9 @@ typedef union ii_iieph2_u {
************************************************************************/
typedef union ii_islapr_u {
- uint64_t ii_islapr_regval;
+ u64 ii_islapr_regval;
struct {
- uint64_t i_region:64;
+ u64 i_region:64;
} ii_islapr_fld_s;
} ii_islapr_u_t;
@@ -1547,10 +1547,10 @@ typedef union ii_islapr_u {
************************************************************************/
typedef union ii_islapo_u {
- uint64_t ii_islapo_regval;
+ u64 ii_islapo_regval;
struct {
- uint64_t i_io_sbx_ovrride:56;
- uint64_t i_rsvd:8;
+ u64 i_io_sbx_ovrride:56;
+ u64 i_rsvd:8;
} ii_islapo_fld_s;
} ii_islapo_u_t;
@@ -1563,14 +1563,14 @@ typedef union ii_islapo_u {
************************************************************************/
typedef union ii_iwi_u {
- uint64_t ii_iwi_regval;
- struct {
- uint64_t i_prescale:24;
- uint64_t i_rsvd:8;
- uint64_t i_timeout:8;
- uint64_t i_rsvd1:8;
- uint64_t i_intrpt_retry_period:8;
- uint64_t i_rsvd2:8;
+ u64 ii_iwi_regval;
+ struct {
+ u64 i_prescale:24;
+ u64 i_rsvd:8;
+ u64 i_timeout:8;
+ u64 i_rsvd1:8;
+ u64 i_intrpt_retry_period:8;
+ u64 i_rsvd2:8;
} ii_iwi_fld_s;
} ii_iwi_u_t;
@@ -1582,26 +1582,26 @@ typedef union ii_iwi_u {
************************************************************************/
typedef union ii_iwel_u {
- uint64_t ii_iwel_regval;
- struct {
- uint64_t i_intr_timed_out:1;
- uint64_t i_rsvd:7;
- uint64_t i_cam_overflow:1;
- uint64_t i_cam_read_miss:1;
- uint64_t i_rsvd1:2;
- uint64_t i_ioq_rep_underflow:1;
- uint64_t i_ioq_req_underflow:1;
- uint64_t i_ioq_rep_overflow:1;
- uint64_t i_ioq_req_overflow:1;
- uint64_t i_iiq_rep_overflow:1;
- uint64_t i_iiq_req_overflow:1;
- uint64_t i_rsvd2:6;
- uint64_t i_ii_xn_rep_cred_over_under:1;
- uint64_t i_ii_xn_req_cred_over_under:1;
- uint64_t i_rsvd3:6;
- uint64_t i_ii_xn_invalid_cmd:1;
- uint64_t i_xn_ii_invalid_cmd:1;
- uint64_t i_rsvd4:30;
+ u64 ii_iwel_regval;
+ struct {
+ u64 i_intr_timed_out:1;
+ u64 i_rsvd:7;
+ u64 i_cam_overflow:1;
+ u64 i_cam_read_miss:1;
+ u64 i_rsvd1:2;
+ u64 i_ioq_rep_underflow:1;
+ u64 i_ioq_req_underflow:1;
+ u64 i_ioq_rep_overflow:1;
+ u64 i_ioq_req_overflow:1;
+ u64 i_iiq_rep_overflow:1;
+ u64 i_iiq_req_overflow:1;
+ u64 i_rsvd2:6;
+ u64 i_ii_xn_rep_cred_over_under:1;
+ u64 i_ii_xn_req_cred_over_under:1;
+ u64 i_rsvd3:6;
+ u64 i_ii_xn_invalid_cmd:1;
+ u64 i_xn_ii_invalid_cmd:1;
+ u64 i_rsvd4:30;
} ii_iwel_fld_s;
} ii_iwel_u_t;
@@ -1612,22 +1612,22 @@ typedef union ii_iwel_u {
************************************************************************/
typedef union ii_iwc_u {
- uint64_t ii_iwc_regval;
- struct {
- uint64_t i_dma_byte_swap:1;
- uint64_t i_rsvd:3;
- uint64_t i_cam_read_lines_reset:1;
- uint64_t i_rsvd1:3;
- uint64_t i_ii_xn_cred_over_under_log:1;
- uint64_t i_rsvd2:19;
- uint64_t i_xn_rep_iq_depth:5;
- uint64_t i_rsvd3:3;
- uint64_t i_xn_req_iq_depth:5;
- uint64_t i_rsvd4:3;
- uint64_t i_iiq_depth:6;
- uint64_t i_rsvd5:12;
- uint64_t i_force_rep_cred:1;
- uint64_t i_force_req_cred:1;
+ u64 ii_iwc_regval;
+ struct {
+ u64 i_dma_byte_swap:1;
+ u64 i_rsvd:3;
+ u64 i_cam_read_lines_reset:1;
+ u64 i_rsvd1:3;
+ u64 i_ii_xn_cred_over_under_log:1;
+ u64 i_rsvd2:19;
+ u64 i_xn_rep_iq_depth:5;
+ u64 i_rsvd3:3;
+ u64 i_xn_req_iq_depth:5;
+ u64 i_rsvd4:3;
+ u64 i_iiq_depth:6;
+ u64 i_rsvd5:12;
+ u64 i_force_rep_cred:1;
+ u64 i_force_req_cred:1;
} ii_iwc_fld_s;
} ii_iwc_u_t;
@@ -1638,12 +1638,12 @@ typedef union ii_iwc_u {
************************************************************************/
typedef union ii_iws_u {
- uint64_t ii_iws_regval;
+ u64 ii_iws_regval;
struct {
- uint64_t i_xn_rep_iq_credits:5;
- uint64_t i_rsvd:3;
- uint64_t i_xn_req_iq_credits:5;
- uint64_t i_rsvd1:51;
+ u64 i_xn_rep_iq_credits:5;
+ u64 i_rsvd:3;
+ u64 i_xn_req_iq_credits:5;
+ u64 i_rsvd1:51;
} ii_iws_fld_s;
} ii_iws_u_t;
@@ -1654,26 +1654,26 @@ typedef union ii_iws_u {
************************************************************************/
typedef union ii_iweim_u {
- uint64_t ii_iweim_regval;
- struct {
- uint64_t i_intr_timed_out:1;
- uint64_t i_rsvd:7;
- uint64_t i_cam_overflow:1;
- uint64_t i_cam_read_miss:1;
- uint64_t i_rsvd1:2;
- uint64_t i_ioq_rep_underflow:1;
- uint64_t i_ioq_req_underflow:1;
- uint64_t i_ioq_rep_overflow:1;
- uint64_t i_ioq_req_overflow:1;
- uint64_t i_iiq_rep_overflow:1;
- uint64_t i_iiq_req_overflow:1;
- uint64_t i_rsvd2:6;
- uint64_t i_ii_xn_rep_cred_overflow:1;
- uint64_t i_ii_xn_req_cred_overflow:1;
- uint64_t i_rsvd3:6;
- uint64_t i_ii_xn_invalid_cmd:1;
- uint64_t i_xn_ii_invalid_cmd:1;
- uint64_t i_rsvd4:30;
+ u64 ii_iweim_regval;
+ struct {
+ u64 i_intr_timed_out:1;
+ u64 i_rsvd:7;
+ u64 i_cam_overflow:1;
+ u64 i_cam_read_miss:1;
+ u64 i_rsvd1:2;
+ u64 i_ioq_rep_underflow:1;
+ u64 i_ioq_req_underflow:1;
+ u64 i_ioq_rep_overflow:1;
+ u64 i_ioq_req_overflow:1;
+ u64 i_iiq_rep_overflow:1;
+ u64 i_iiq_req_overflow:1;
+ u64 i_rsvd2:6;
+ u64 i_ii_xn_rep_cred_overflow:1;
+ u64 i_ii_xn_req_cred_overflow:1;
+ u64 i_rsvd3:6;
+ u64 i_ii_xn_invalid_cmd:1;
+ u64 i_xn_ii_invalid_cmd:1;
+ u64 i_rsvd4:30;
} ii_iweim_fld_s;
} ii_iweim_u_t;
@@ -1688,13 +1688,13 @@ typedef union ii_iweim_u {
************************************************************************/
typedef union ii_ipca_u {
- uint64_t ii_ipca_regval;
+ u64 ii_ipca_regval;
struct {
- uint64_t i_wid:4;
- uint64_t i_adjust:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_field:2;
- uint64_t i_rsvd:54;
+ u64 i_wid:4;
+ u64 i_adjust:1;
+ u64 i_rsvd_1:3;
+ u64 i_field:2;
+ u64 i_rsvd:54;
} ii_ipca_fld_s;
} ii_ipca_u_t;
@@ -1709,12 +1709,12 @@ typedef union ii_ipca_u {
************************************************************************/
typedef union ii_iprte0a_u {
- uint64_t ii_iprte0a_regval;
+ u64 ii_iprte0a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte0a_fld_s;
} ii_iprte0a_u_t;
@@ -1729,12 +1729,12 @@ typedef union ii_iprte0a_u {
************************************************************************/
typedef union ii_iprte1a_u {
- uint64_t ii_iprte1a_regval;
+ u64 ii_iprte1a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte1a_fld_s;
} ii_iprte1a_u_t;
@@ -1749,12 +1749,12 @@ typedef union ii_iprte1a_u {
************************************************************************/
typedef union ii_iprte2a_u {
- uint64_t ii_iprte2a_regval;
+ u64 ii_iprte2a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte2a_fld_s;
} ii_iprte2a_u_t;
@@ -1769,12 +1769,12 @@ typedef union ii_iprte2a_u {
************************************************************************/
typedef union ii_iprte3a_u {
- uint64_t ii_iprte3a_regval;
+ u64 ii_iprte3a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte3a_fld_s;
} ii_iprte3a_u_t;
@@ -1789,12 +1789,12 @@ typedef union ii_iprte3a_u {
************************************************************************/
typedef union ii_iprte4a_u {
- uint64_t ii_iprte4a_regval;
+ u64 ii_iprte4a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte4a_fld_s;
} ii_iprte4a_u_t;
@@ -1809,12 +1809,12 @@ typedef union ii_iprte4a_u {
************************************************************************/
typedef union ii_iprte5a_u {
- uint64_t ii_iprte5a_regval;
+ u64 ii_iprte5a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte5a_fld_s;
} ii_iprte5a_u_t;
@@ -1829,12 +1829,12 @@ typedef union ii_iprte5a_u {
************************************************************************/
typedef union ii_iprte6a_u {
- uint64_t ii_iprte6a_regval;
+ u64 ii_iprte6a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprte6a_fld_s;
} ii_iprte6a_u_t;
@@ -1849,12 +1849,12 @@ typedef union ii_iprte6a_u {
************************************************************************/
typedef union ii_iprte7a_u {
- uint64_t ii_iprte7a_regval;
+ u64 ii_iprte7a_regval;
struct {
- uint64_t i_rsvd_1:54;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 i_rsvd_1:54;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} ii_iprtea7_fld_s;
} ii_iprte7a_u_t;
@@ -1869,12 +1869,12 @@ typedef union ii_iprte7a_u {
************************************************************************/
typedef union ii_iprte0b_u {
- uint64_t ii_iprte0b_regval;
+ u64 ii_iprte0b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte0b_fld_s;
} ii_iprte0b_u_t;
@@ -1889,12 +1889,12 @@ typedef union ii_iprte0b_u {
************************************************************************/
typedef union ii_iprte1b_u {
- uint64_t ii_iprte1b_regval;
+ u64 ii_iprte1b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte1b_fld_s;
} ii_iprte1b_u_t;
@@ -1909,12 +1909,12 @@ typedef union ii_iprte1b_u {
************************************************************************/
typedef union ii_iprte2b_u {
- uint64_t ii_iprte2b_regval;
+ u64 ii_iprte2b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte2b_fld_s;
} ii_iprte2b_u_t;
@@ -1929,12 +1929,12 @@ typedef union ii_iprte2b_u {
************************************************************************/
typedef union ii_iprte3b_u {
- uint64_t ii_iprte3b_regval;
+ u64 ii_iprte3b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte3b_fld_s;
} ii_iprte3b_u_t;
@@ -1949,12 +1949,12 @@ typedef union ii_iprte3b_u {
************************************************************************/
typedef union ii_iprte4b_u {
- uint64_t ii_iprte4b_regval;
+ u64 ii_iprte4b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte4b_fld_s;
} ii_iprte4b_u_t;
@@ -1969,12 +1969,12 @@ typedef union ii_iprte4b_u {
************************************************************************/
typedef union ii_iprte5b_u {
- uint64_t ii_iprte5b_regval;
+ u64 ii_iprte5b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte5b_fld_s;
} ii_iprte5b_u_t;
@@ -1989,12 +1989,12 @@ typedef union ii_iprte5b_u {
************************************************************************/
typedef union ii_iprte6b_u {
- uint64_t ii_iprte6b_regval;
+ u64 ii_iprte6b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte6b_fld_s;
} ii_iprte6b_u_t;
@@ -2010,12 +2010,12 @@ typedef union ii_iprte6b_u {
************************************************************************/
typedef union ii_iprte7b_u {
- uint64_t ii_iprte7b_regval;
+ u64 ii_iprte7b_regval;
struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_address:47;
- uint64_t i_init:3;
- uint64_t i_source:11;
+ u64 i_rsvd_1:3;
+ u64 i_address:47;
+ u64 i_init:3;
+ u64 i_source:11;
} ii_iprte7b_fld_s;
} ii_iprte7b_u_t;
@@ -2038,13 +2038,13 @@ typedef union ii_iprte7b_u {
************************************************************************/
typedef union ii_ipdr_u {
- uint64_t ii_ipdr_regval;
+ u64 ii_ipdr_regval;
struct {
- uint64_t i_te:3;
- uint64_t i_rsvd_1:1;
- uint64_t i_pnd:1;
- uint64_t i_init_rpcnt:1;
- uint64_t i_rsvd:58;
+ u64 i_te:3;
+ u64 i_rsvd_1:1;
+ u64 i_pnd:1;
+ u64 i_init_rpcnt:1;
+ u64 i_rsvd:58;
} ii_ipdr_fld_s;
} ii_ipdr_u_t;
@@ -2066,11 +2066,11 @@ typedef union ii_ipdr_u {
************************************************************************/
typedef union ii_icdr_u {
- uint64_t ii_icdr_regval;
+ u64 ii_icdr_regval;
struct {
- uint64_t i_crb_num:4;
- uint64_t i_pnd:1;
- uint64_t i_rsvd:59;
+ u64 i_crb_num:4;
+ u64 i_pnd:1;
+ u64 i_rsvd:59;
} ii_icdr_fld_s;
} ii_icdr_u_t;
@@ -2092,13 +2092,13 @@ typedef union ii_icdr_u {
************************************************************************/
typedef union ii_ifdr_u {
- uint64_t ii_ifdr_regval;
+ u64 ii_ifdr_regval;
struct {
- uint64_t i_ioq_max_rq:7;
- uint64_t i_set_ioq_rq:1;
- uint64_t i_ioq_max_rp:7;
- uint64_t i_set_ioq_rp:1;
- uint64_t i_rsvd:48;
+ u64 i_ioq_max_rq:7;
+ u64 i_set_ioq_rq:1;
+ u64 i_ioq_max_rp:7;
+ u64 i_set_ioq_rp:1;
+ u64 i_rsvd:48;
} ii_ifdr_fld_s;
} ii_ifdr_u_t;
@@ -2114,12 +2114,12 @@ typedef union ii_ifdr_u {
************************************************************************/
typedef union ii_iiap_u {
- uint64_t ii_iiap_regval;
+ u64 ii_iiap_regval;
struct {
- uint64_t i_rq_mls:6;
- uint64_t i_rsvd_1:2;
- uint64_t i_rp_mls:6;
- uint64_t i_rsvd:50;
+ u64 i_rq_mls:6;
+ u64 i_rsvd_1:2;
+ u64 i_rp_mls:6;
+ u64 i_rsvd:50;
} ii_iiap_fld_s;
} ii_iiap_u_t;
@@ -2133,22 +2133,22 @@ typedef union ii_iiap_u {
************************************************************************/
typedef union ii_icmr_u {
- uint64_t ii_icmr_regval;
- struct {
- uint64_t i_sp_msg:1;
- uint64_t i_rd_hdr:1;
- uint64_t i_rsvd_4:2;
- uint64_t i_c_cnt:4;
- uint64_t i_rsvd_3:4;
- uint64_t i_clr_rqpd:1;
- uint64_t i_clr_rppd:1;
- uint64_t i_rsvd_2:2;
- uint64_t i_fc_cnt:4;
- uint64_t i_crb_vld:15;
- uint64_t i_crb_mark:15;
- uint64_t i_rsvd_1:2;
- uint64_t i_precise:1;
- uint64_t i_rsvd:11;
+ u64 ii_icmr_regval;
+ struct {
+ u64 i_sp_msg:1;
+ u64 i_rd_hdr:1;
+ u64 i_rsvd_4:2;
+ u64 i_c_cnt:4;
+ u64 i_rsvd_3:4;
+ u64 i_clr_rqpd:1;
+ u64 i_clr_rppd:1;
+ u64 i_rsvd_2:2;
+ u64 i_fc_cnt:4;
+ u64 i_crb_vld:15;
+ u64 i_crb_mark:15;
+ u64 i_rsvd_1:2;
+ u64 i_precise:1;
+ u64 i_rsvd:11;
} ii_icmr_fld_s;
} ii_icmr_u_t;
@@ -2161,13 +2161,13 @@ typedef union ii_icmr_u {
************************************************************************/
typedef union ii_iccr_u {
- uint64_t ii_iccr_regval;
+ u64 ii_iccr_regval;
struct {
- uint64_t i_crb_num:4;
- uint64_t i_rsvd_1:4;
- uint64_t i_cmd:8;
- uint64_t i_pending:1;
- uint64_t i_rsvd:47;
+ u64 i_crb_num:4;
+ u64 i_rsvd_1:4;
+ u64 i_cmd:8;
+ u64 i_pending:1;
+ u64 i_rsvd:47;
} ii_iccr_fld_s;
} ii_iccr_u_t;
@@ -2178,10 +2178,10 @@ typedef union ii_iccr_u {
************************************************************************/
typedef union ii_icto_u {
- uint64_t ii_icto_regval;
+ u64 ii_icto_regval;
struct {
- uint64_t i_timeout:8;
- uint64_t i_rsvd:56;
+ u64 i_timeout:8;
+ u64 i_rsvd:56;
} ii_icto_fld_s;
} ii_icto_u_t;
@@ -2197,10 +2197,10 @@ typedef union ii_icto_u {
************************************************************************/
typedef union ii_ictp_u {
- uint64_t ii_ictp_regval;
+ u64 ii_ictp_regval;
struct {
- uint64_t i_prescale:24;
- uint64_t i_rsvd:40;
+ u64 i_prescale:24;
+ u64 i_rsvd:40;
} ii_ictp_fld_s;
} ii_ictp_u_t;
@@ -2228,14 +2228,14 @@ typedef union ii_ictp_u {
************************************************************************/
typedef union ii_icrb0_a_u {
- uint64_t ii_icrb0_a_regval;
- struct {
- uint64_t ia_iow:1;
- uint64_t ia_vld:1;
- uint64_t ia_addr:47;
- uint64_t ia_tnum:5;
- uint64_t ia_sidn:4;
- uint64_t ia_rsvd:6;
+ u64 ii_icrb0_a_regval;
+ struct {
+ u64 ia_iow:1;
+ u64 ia_vld:1;
+ u64 ia_addr:47;
+ u64 ia_tnum:5;
+ u64 ia_sidn:4;
+ u64 ia_rsvd:6;
} ii_icrb0_a_fld_s;
} ii_icrb0_a_u_t;
@@ -2249,30 +2249,30 @@ typedef union ii_icrb0_a_u {
************************************************************************/
typedef union ii_icrb0_b_u {
- uint64_t ii_icrb0_b_regval;
- struct {
- uint64_t ib_xt_err:1;
- uint64_t ib_mark:1;
- uint64_t ib_ln_uce:1;
- uint64_t ib_errcode:3;
- uint64_t ib_error:1;
- uint64_t ib_stall__bte_1:1;
- uint64_t ib_stall__bte_0:1;
- uint64_t ib_stall__intr:1;
- uint64_t ib_stall_ib:1;
- uint64_t ib_intvn:1;
- uint64_t ib_wb:1;
- uint64_t ib_hold:1;
- uint64_t ib_ack:1;
- uint64_t ib_resp:1;
- uint64_t ib_ack_cnt:11;
- uint64_t ib_rsvd:7;
- uint64_t ib_exc:5;
- uint64_t ib_init:3;
- uint64_t ib_imsg:8;
- uint64_t ib_imsgtype:2;
- uint64_t ib_use_old:1;
- uint64_t ib_rsvd_1:11;
+ u64 ii_icrb0_b_regval;
+ struct {
+ u64 ib_xt_err:1;
+ u64 ib_mark:1;
+ u64 ib_ln_uce:1;
+ u64 ib_errcode:3;
+ u64 ib_error:1;
+ u64 ib_stall__bte_1:1;
+ u64 ib_stall__bte_0:1;
+ u64 ib_stall__intr:1;
+ u64 ib_stall_ib:1;
+ u64 ib_intvn:1;
+ u64 ib_wb:1;
+ u64 ib_hold:1;
+ u64 ib_ack:1;
+ u64 ib_resp:1;
+ u64 ib_ack_cnt:11;
+ u64 ib_rsvd:7;
+ u64 ib_exc:5;
+ u64 ib_init:3;
+ u64 ib_imsg:8;
+ u64 ib_imsgtype:2;
+ u64 ib_use_old:1;
+ u64 ib_rsvd_1:11;
} ii_icrb0_b_fld_s;
} ii_icrb0_b_u_t;
@@ -2286,17 +2286,17 @@ typedef union ii_icrb0_b_u {
************************************************************************/
typedef union ii_icrb0_c_u {
- uint64_t ii_icrb0_c_regval;
- struct {
- uint64_t ic_source:15;
- uint64_t ic_size:2;
- uint64_t ic_ct:1;
- uint64_t ic_bte_num:1;
- uint64_t ic_gbr:1;
- uint64_t ic_resprqd:1;
- uint64_t ic_bo:1;
- uint64_t ic_suppl:15;
- uint64_t ic_rsvd:27;
+ u64 ii_icrb0_c_regval;
+ struct {
+ u64 ic_source:15;
+ u64 ic_size:2;
+ u64 ic_ct:1;
+ u64 ic_bte_num:1;
+ u64 ic_gbr:1;
+ u64 ic_resprqd:1;
+ u64 ic_bo:1;
+ u64 ic_suppl:15;
+ u64 ic_rsvd:27;
} ii_icrb0_c_fld_s;
} ii_icrb0_c_u_t;
@@ -2310,14 +2310,14 @@ typedef union ii_icrb0_c_u {
************************************************************************/
typedef union ii_icrb0_d_u {
- uint64_t ii_icrb0_d_regval;
- struct {
- uint64_t id_pa_be:43;
- uint64_t id_bte_op:1;
- uint64_t id_pr_psc:4;
- uint64_t id_pr_cnt:4;
- uint64_t id_sleep:1;
- uint64_t id_rsvd:11;
+ u64 ii_icrb0_d_regval;
+ struct {
+ u64 id_pa_be:43;
+ u64 id_bte_op:1;
+ u64 id_pr_psc:4;
+ u64 id_pr_cnt:4;
+ u64 id_sleep:1;
+ u64 id_rsvd:11;
} ii_icrb0_d_fld_s;
} ii_icrb0_d_u_t;
@@ -2331,14 +2331,14 @@ typedef union ii_icrb0_d_u {
************************************************************************/
typedef union ii_icrb0_e_u {
- uint64_t ii_icrb0_e_regval;
- struct {
- uint64_t ie_timeout:8;
- uint64_t ie_context:15;
- uint64_t ie_rsvd:1;
- uint64_t ie_tvld:1;
- uint64_t ie_cvld:1;
- uint64_t ie_rsvd_0:38;
+ u64 ii_icrb0_e_regval;
+ struct {
+ u64 ie_timeout:8;
+ u64 ie_context:15;
+ u64 ie_rsvd:1;
+ u64 ie_tvld:1;
+ u64 ie_cvld:1;
+ u64 ie_rsvd_0:38;
} ii_icrb0_e_fld_s;
} ii_icrb0_e_u_t;
@@ -2351,12 +2351,12 @@ typedef union ii_icrb0_e_u {
************************************************************************/
typedef union ii_icsml_u {
- uint64_t ii_icsml_regval;
+ u64 ii_icsml_regval;
struct {
- uint64_t i_tt_addr:47;
- uint64_t i_newsuppl_ex:14;
- uint64_t i_reserved:2;
- uint64_t i_overflow:1;
+ u64 i_tt_addr:47;
+ u64 i_newsuppl_ex:14;
+ u64 i_reserved:2;
+ u64 i_overflow:1;
} ii_icsml_fld_s;
} ii_icsml_u_t;
@@ -2369,10 +2369,10 @@ typedef union ii_icsml_u {
************************************************************************/
typedef union ii_icsmm_u {
- uint64_t ii_icsmm_regval;
+ u64 ii_icsmm_regval;
struct {
- uint64_t i_tt_ack_cnt:11;
- uint64_t i_reserved:53;
+ u64 i_tt_ack_cnt:11;
+ u64 i_reserved:53;
} ii_icsmm_fld_s;
} ii_icsmm_u_t;
@@ -2385,48 +2385,48 @@ typedef union ii_icsmm_u {
************************************************************************/
typedef union ii_icsmh_u {
- uint64_t ii_icsmh_regval;
- struct {
- uint64_t i_tt_vld:1;
- uint64_t i_xerr:1;
- uint64_t i_ft_cwact_o:1;
- uint64_t i_ft_wact_o:1;
- uint64_t i_ft_active_o:1;
- uint64_t i_sync:1;
- uint64_t i_mnusg:1;
- uint64_t i_mnusz:1;
- uint64_t i_plusz:1;
- uint64_t i_plusg:1;
- uint64_t i_tt_exc:5;
- uint64_t i_tt_wb:1;
- uint64_t i_tt_hold:1;
- uint64_t i_tt_ack:1;
- uint64_t i_tt_resp:1;
- uint64_t i_tt_intvn:1;
- uint64_t i_g_stall_bte1:1;
- uint64_t i_g_stall_bte0:1;
- uint64_t i_g_stall_il:1;
- uint64_t i_g_stall_ib:1;
- uint64_t i_tt_imsg:8;
- uint64_t i_tt_imsgtype:2;
- uint64_t i_tt_use_old:1;
- uint64_t i_tt_respreqd:1;
- uint64_t i_tt_bte_num:1;
- uint64_t i_cbn:1;
- uint64_t i_match:1;
- uint64_t i_rpcnt_lt_34:1;
- uint64_t i_rpcnt_ge_34:1;
- uint64_t i_rpcnt_lt_18:1;
- uint64_t i_rpcnt_ge_18:1;
- uint64_t i_rpcnt_lt_2:1;
- uint64_t i_rpcnt_ge_2:1;
- uint64_t i_rqcnt_lt_18:1;
- uint64_t i_rqcnt_ge_18:1;
- uint64_t i_rqcnt_lt_2:1;
- uint64_t i_rqcnt_ge_2:1;
- uint64_t i_tt_device:7;
- uint64_t i_tt_init:3;
- uint64_t i_reserved:5;
+ u64 ii_icsmh_regval;
+ struct {
+ u64 i_tt_vld:1;
+ u64 i_xerr:1;
+ u64 i_ft_cwact_o:1;
+ u64 i_ft_wact_o:1;
+ u64 i_ft_active_o:1;
+ u64 i_sync:1;
+ u64 i_mnusg:1;
+ u64 i_mnusz:1;
+ u64 i_plusz:1;
+ u64 i_plusg:1;
+ u64 i_tt_exc:5;
+ u64 i_tt_wb:1;
+ u64 i_tt_hold:1;
+ u64 i_tt_ack:1;
+ u64 i_tt_resp:1;
+ u64 i_tt_intvn:1;
+ u64 i_g_stall_bte1:1;
+ u64 i_g_stall_bte0:1;
+ u64 i_g_stall_il:1;
+ u64 i_g_stall_ib:1;
+ u64 i_tt_imsg:8;
+ u64 i_tt_imsgtype:2;
+ u64 i_tt_use_old:1;
+ u64 i_tt_respreqd:1;
+ u64 i_tt_bte_num:1;
+ u64 i_cbn:1;
+ u64 i_match:1;
+ u64 i_rpcnt_lt_34:1;
+ u64 i_rpcnt_ge_34:1;
+ u64 i_rpcnt_lt_18:1;
+ u64 i_rpcnt_ge_18:1;
+ u64 i_rpcnt_lt_2:1;
+ u64 i_rpcnt_ge_2:1;
+ u64 i_rqcnt_lt_18:1;
+ u64 i_rqcnt_ge_18:1;
+ u64 i_rqcnt_lt_2:1;
+ u64 i_rqcnt_ge_2:1;
+ u64 i_tt_device:7;
+ u64 i_tt_init:3;
+ u64 i_reserved:5;
} ii_icsmh_fld_s;
} ii_icsmh_u_t;
@@ -2439,14 +2439,14 @@ typedef union ii_icsmh_u {
************************************************************************/
typedef union ii_idbss_u {
- uint64_t ii_idbss_regval;
- struct {
- uint64_t i_iioclk_core_submenu:3;
- uint64_t i_rsvd:5;
- uint64_t i_fsbclk_wrapper_submenu:3;
- uint64_t i_rsvd_1:5;
- uint64_t i_iioclk_menu:5;
- uint64_t i_rsvd_2:43;
+ u64 ii_idbss_regval;
+ struct {
+ u64 i_iioclk_core_submenu:3;
+ u64 i_rsvd:5;
+ u64 i_fsbclk_wrapper_submenu:3;
+ u64 i_rsvd_1:5;
+ u64 i_iioclk_menu:5;
+ u64 i_rsvd_2:43;
} ii_idbss_fld_s;
} ii_idbss_u_t;
@@ -2466,13 +2466,13 @@ typedef union ii_idbss_u {
************************************************************************/
typedef union ii_ibls0_u {
- uint64_t ii_ibls0_regval;
+ u64 ii_ibls0_regval;
struct {
- uint64_t i_length:16;
- uint64_t i_error:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_busy:1;
- uint64_t i_rsvd:43;
+ u64 i_length:16;
+ u64 i_error:1;
+ u64 i_rsvd_1:3;
+ u64 i_busy:1;
+ u64 i_rsvd:43;
} ii_ibls0_fld_s;
} ii_ibls0_u_t;
@@ -2487,11 +2487,11 @@ typedef union ii_ibls0_u {
************************************************************************/
typedef union ii_ibsa0_u {
- uint64_t ii_ibsa0_regval;
+ u64 ii_ibsa0_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:42;
- uint64_t i_rsvd:15;
+ u64 i_rsvd_1:7;
+ u64 i_addr:42;
+ u64 i_rsvd:15;
} ii_ibsa0_fld_s;
} ii_ibsa0_u_t;
@@ -2506,11 +2506,11 @@ typedef union ii_ibsa0_u {
************************************************************************/
typedef union ii_ibda0_u {
- uint64_t ii_ibda0_regval;
+ u64 ii_ibda0_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:42;
- uint64_t i_rsvd:15;
+ u64 i_rsvd_1:7;
+ u64 i_addr:42;
+ u64 i_rsvd:15;
} ii_ibda0_fld_s;
} ii_ibda0_u_t;
@@ -2527,14 +2527,14 @@ typedef union ii_ibda0_u {
************************************************************************/
typedef union ii_ibct0_u {
- uint64_t ii_ibct0_regval;
- struct {
- uint64_t i_zerofill:1;
- uint64_t i_rsvd_2:3;
- uint64_t i_notify:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_poison:1;
- uint64_t i_rsvd:55;
+ u64 ii_ibct0_regval;
+ struct {
+ u64 i_zerofill:1;
+ u64 i_rsvd_2:3;
+ u64 i_notify:1;
+ u64 i_rsvd_1:3;
+ u64 i_poison:1;
+ u64 i_rsvd:55;
} ii_ibct0_fld_s;
} ii_ibct0_u_t;
@@ -2546,11 +2546,11 @@ typedef union ii_ibct0_u {
************************************************************************/
typedef union ii_ibna0_u {
- uint64_t ii_ibna0_regval;
+ u64 ii_ibna0_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:42;
- uint64_t i_rsvd:15;
+ u64 i_rsvd_1:7;
+ u64 i_addr:42;
+ u64 i_rsvd:15;
} ii_ibna0_fld_s;
} ii_ibna0_u_t;
@@ -2563,13 +2563,13 @@ typedef union ii_ibna0_u {
************************************************************************/
typedef union ii_ibia0_u {
- uint64_t ii_ibia0_regval;
+ u64 ii_ibia0_regval;
struct {
- uint64_t i_rsvd_2:1;
- uint64_t i_node_id:11;
- uint64_t i_rsvd_1:4;
- uint64_t i_level:7;
- uint64_t i_rsvd:41;
+ u64 i_rsvd_2:1;
+ u64 i_node_id:11;
+ u64 i_rsvd_1:4;
+ u64 i_level:7;
+ u64 i_rsvd:41;
} ii_ibia0_fld_s;
} ii_ibia0_u_t;
@@ -2589,13 +2589,13 @@ typedef union ii_ibia0_u {
************************************************************************/
typedef union ii_ibls1_u {
- uint64_t ii_ibls1_regval;
+ u64 ii_ibls1_regval;
struct {
- uint64_t i_length:16;
- uint64_t i_error:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_busy:1;
- uint64_t i_rsvd:43;
+ u64 i_length:16;
+ u64 i_error:1;
+ u64 i_rsvd_1:3;
+ u64 i_busy:1;
+ u64 i_rsvd:43;
} ii_ibls1_fld_s;
} ii_ibls1_u_t;
@@ -2610,11 +2610,11 @@ typedef union ii_ibls1_u {
************************************************************************/
typedef union ii_ibsa1_u {
- uint64_t ii_ibsa1_regval;
+ u64 ii_ibsa1_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:33;
- uint64_t i_rsvd:24;
+ u64 i_rsvd_1:7;
+ u64 i_addr:33;
+ u64 i_rsvd:24;
} ii_ibsa1_fld_s;
} ii_ibsa1_u_t;
@@ -2629,11 +2629,11 @@ typedef union ii_ibsa1_u {
************************************************************************/
typedef union ii_ibda1_u {
- uint64_t ii_ibda1_regval;
+ u64 ii_ibda1_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:33;
- uint64_t i_rsvd:24;
+ u64 i_rsvd_1:7;
+ u64 i_addr:33;
+ u64 i_rsvd:24;
} ii_ibda1_fld_s;
} ii_ibda1_u_t;
@@ -2650,14 +2650,14 @@ typedef union ii_ibda1_u {
************************************************************************/
typedef union ii_ibct1_u {
- uint64_t ii_ibct1_regval;
- struct {
- uint64_t i_zerofill:1;
- uint64_t i_rsvd_2:3;
- uint64_t i_notify:1;
- uint64_t i_rsvd_1:3;
- uint64_t i_poison:1;
- uint64_t i_rsvd:55;
+ u64 ii_ibct1_regval;
+ struct {
+ u64 i_zerofill:1;
+ u64 i_rsvd_2:3;
+ u64 i_notify:1;
+ u64 i_rsvd_1:3;
+ u64 i_poison:1;
+ u64 i_rsvd:55;
} ii_ibct1_fld_s;
} ii_ibct1_u_t;
@@ -2669,11 +2669,11 @@ typedef union ii_ibct1_u {
************************************************************************/
typedef union ii_ibna1_u {
- uint64_t ii_ibna1_regval;
+ u64 ii_ibna1_regval;
struct {
- uint64_t i_rsvd_1:7;
- uint64_t i_addr:33;
- uint64_t i_rsvd:24;
+ u64 i_rsvd_1:7;
+ u64 i_addr:33;
+ u64 i_rsvd:24;
} ii_ibna1_fld_s;
} ii_ibna1_u_t;
@@ -2686,13 +2686,13 @@ typedef union ii_ibna1_u {
************************************************************************/
typedef union ii_ibia1_u {
- uint64_t ii_ibia1_regval;
+ u64 ii_ibia1_regval;
struct {
- uint64_t i_pi_id:1;
- uint64_t i_node_id:8;
- uint64_t i_rsvd_1:7;
- uint64_t i_level:7;
- uint64_t i_rsvd:41;
+ u64 i_pi_id:1;
+ u64 i_node_id:8;
+ u64 i_rsvd_1:7;
+ u64 i_level:7;
+ u64 i_rsvd:41;
} ii_ibia1_fld_s;
} ii_ibia1_u_t;
@@ -2712,12 +2712,12 @@ typedef union ii_ibia1_u {
************************************************************************/
typedef union ii_ipcr_u {
- uint64_t ii_ipcr_regval;
+ u64 ii_ipcr_regval;
struct {
- uint64_t i_ippr0_c:4;
- uint64_t i_ippr1_c:4;
- uint64_t i_icct:8;
- uint64_t i_rsvd:48;
+ u64 i_ippr0_c:4;
+ u64 i_ippr1_c:4;
+ u64 i_icct:8;
+ u64 i_rsvd:48;
} ii_ipcr_fld_s;
} ii_ipcr_u_t;
@@ -2728,10 +2728,10 @@ typedef union ii_ipcr_u {
************************************************************************/
typedef union ii_ippr_u {
- uint64_t ii_ippr_regval;
+ u64 ii_ippr_regval;
struct {
- uint64_t i_ippr0:32;
- uint64_t i_ippr1:32;
+ u64 i_ippr0:32;
+ u64 i_ippr1:32;
} ii_ippr_fld_s;
} ii_ippr_u_t;
@@ -3267,15 +3267,15 @@ typedef ii_icrb0_e_u_t icrbe_t;
#define IO_PERF_SETS 32
/* Bit for the widget in inbound access register */
-#define IIO_IIWA_WIDGET(_w) ((uint64_t)(1ULL << _w))
+#define IIO_IIWA_WIDGET(_w) ((u64)(1ULL << _w))
/* Bit for the widget in outbound access register */
-#define IIO_IOWA_WIDGET(_w) ((uint64_t)(1ULL << _w))
+#define IIO_IOWA_WIDGET(_w) ((u64)(1ULL << _w))
/* NOTE: The following define assumes that we are going to get
* widget numbers from 8 thru F and the device numbers within
* widget from 0 thru 7.
*/
-#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((uint64_t)(1ULL << (8 * ((w) - 8) + (d))))
+#define IIO_IIDEM_WIDGETDEV_MASK(w, d) ((u64)(1ULL << (8 * ((w) - 8) + (d))))
/* IO Interrupt Destination Register */
#define IIO_IIDSR_SENT_SHIFT 28
@@ -3302,9 +3302,9 @@ typedef ii_icrb0_e_u_t icrbe_t;
*/
typedef union hubii_wcr_u {
- uint64_t wcr_reg_value;
+ u64 wcr_reg_value;
struct {
- uint64_t wcr_widget_id:4, /* LLP crossbar credit */
+ u64 wcr_widget_id:4, /* LLP crossbar credit */
wcr_tag_mode:1, /* Tag mode */
wcr_rsvd1:8, /* Reserved */
wcr_xbar_crd:3, /* LLP crossbar credit */
@@ -3324,9 +3324,9 @@ performance registers */
performed */
typedef union io_perf_sel {
- uint64_t perf_sel_reg;
+ u64 perf_sel_reg;
struct {
- uint64_t perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48;
+ u64 perf_ippr0:4, perf_ippr1:4, perf_icct:8, perf_rsvd:48;
} perf_sel_bits;
} io_perf_sel_t;
@@ -3334,24 +3334,24 @@ typedef union io_perf_sel {
hardware problems there is only one counter, not two. */
typedef union io_perf_cnt {
- uint64_t perf_cnt;
+ u64 perf_cnt;
struct {
- uint64_t perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32;
+ u64 perf_cnt:20, perf_rsvd2:12, perf_rsvd1:32;
} perf_cnt_bits;
} io_perf_cnt_t;
typedef union iprte_a {
- uint64_t entry;
- struct {
- uint64_t i_rsvd_1:3;
- uint64_t i_addr:38;
- uint64_t i_init:3;
- uint64_t i_source:8;
- uint64_t i_rsvd:2;
- uint64_t i_widget:4;
- uint64_t i_to_cnt:5;
- uint64_t i_vld:1;
+ u64 entry;
+ struct {
+ u64 i_rsvd_1:3;
+ u64 i_addr:38;
+ u64 i_init:3;
+ u64 i_source:8;
+ u64 i_rsvd:2;
+ u64 i_widget:4;
+ u64 i_to_cnt:5;
+ u64 i_vld:1;
} iprte_fields;
} iprte_a_t;
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 2a8b0d92a5d6..e77f0c9b7d3d 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -75,7 +75,8 @@
#define SN_SAL_IOIF_GET_HUBDEV_INFO 0x02000055
#define SN_SAL_IOIF_GET_PCIBUS_INFO 0x02000056
#define SN_SAL_IOIF_GET_PCIDEV_INFO 0x02000057
-#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058
+#define SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST 0x02000058 // deprecated
+#define SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST 0x0200005a
#define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060
#define SN_SAL_BTE_RECOVER 0x02000061
@@ -272,7 +273,7 @@ ia64_sn_console_putc(char ch)
ret_stuff.v0 = 0;
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (uint64_t)ch, 0, 0, 0, 0, 0, 0);
+ SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTC, (u64)ch, 0, 0, 0, 0, 0, 0);
return ret_stuff.status;
}
@@ -289,7 +290,7 @@ ia64_sn_console_putb(const char *buf, int len)
ret_stuff.v0 = 0;
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (uint64_t)buf, (uint64_t)len, 0, 0, 0, 0, 0);
+ SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_PUTB, (u64)buf, (u64)len, 0, 0, 0, 0, 0);
if ( ret_stuff.status == 0 ) {
return ret_stuff.v0;
@@ -309,7 +310,7 @@ ia64_sn_plat_specific_err_print(int (*hook)(const char*, ...), char *rec)
ret_stuff.v0 = 0;
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
- SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (uint64_t)hook, (uint64_t)rec, 0, 0, 0, 0, 0);
+ SAL_CALL_REENTRANT(ret_stuff, SN_SAL_PRINT_ERROR, (u64)hook, (u64)rec, 0, 0, 0, 0, 0);
return ret_stuff.status;
}
@@ -397,7 +398,7 @@ ia64_sn_console_intr_status(void)
* Enable an interrupt on the SAL console device.
*/
static inline void
-ia64_sn_console_intr_enable(uint64_t intr)
+ia64_sn_console_intr_enable(u64 intr)
{
struct ia64_sal_retval ret_stuff;
@@ -414,7 +415,7 @@ ia64_sn_console_intr_enable(uint64_t intr)
* Disable an interrupt on the SAL console device.
*/
static inline void
-ia64_sn_console_intr_disable(uint64_t intr)
+ia64_sn_console_intr_disable(u64 intr)
{
struct ia64_sal_retval ret_stuff;
@@ -440,7 +441,7 @@ ia64_sn_console_xmit_chars(char *buf, int len)
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
SAL_CALL_NOLOCK(ret_stuff, SN_SAL_CONSOLE_XMIT_CHARS,
- (uint64_t)buf, (uint64_t)len,
+ (u64)buf, (u64)len,
0, 0, 0, 0, 0);
if (ret_stuff.status == 0) {
@@ -1100,7 +1101,7 @@ ia64_sn_bte_recovery(nasid_t nasid)
struct ia64_sal_retval rv;
rv.status = 0;
- SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, 0, 0, 0, 0, 0, 0, 0);
+ SAL_CALL_NOLOCK(rv, SN_SAL_BTE_RECOVER, (u64)nasid, 0, 0, 0, 0, 0, 0);
if (rv.status == SALRET_NOT_IMPLEMENTED)
return 0;
return (int) rv.status;
diff --git a/include/asm-ia64/sn/tioca.h b/include/asm-ia64/sn/tioca.h
index bc1aacfb9483..666222d7f0f6 100644
--- a/include/asm-ia64/sn/tioca.h
+++ b/include/asm-ia64/sn/tioca.h
@@ -19,47 +19,47 @@
*/
struct tioca {
- uint64_t ca_id; /* 0x000000 */
- uint64_t ca_control1; /* 0x000008 */
- uint64_t ca_control2; /* 0x000010 */
- uint64_t ca_status1; /* 0x000018 */
- uint64_t ca_status2; /* 0x000020 */
- uint64_t ca_gart_aperature; /* 0x000028 */
- uint64_t ca_gfx_detach; /* 0x000030 */
- uint64_t ca_inta_dest_addr; /* 0x000038 */
- uint64_t ca_intb_dest_addr; /* 0x000040 */
- uint64_t ca_err_int_dest_addr; /* 0x000048 */
- uint64_t ca_int_status; /* 0x000050 */
- uint64_t ca_int_status_alias; /* 0x000058 */
- uint64_t ca_mult_error; /* 0x000060 */
- uint64_t ca_mult_error_alias; /* 0x000068 */
- uint64_t ca_first_error; /* 0x000070 */
- uint64_t ca_int_mask; /* 0x000078 */
- uint64_t ca_crm_pkterr_type; /* 0x000080 */
- uint64_t ca_crm_pkterr_type_alias; /* 0x000088 */
- uint64_t ca_crm_ct_error_detail_1; /* 0x000090 */
- uint64_t ca_crm_ct_error_detail_2; /* 0x000098 */
- uint64_t ca_crm_tnumto; /* 0x0000A0 */
- uint64_t ca_gart_err; /* 0x0000A8 */
- uint64_t ca_pcierr_type; /* 0x0000B0 */
- uint64_t ca_pcierr_addr; /* 0x0000B8 */
-
- uint64_t ca_pad_0000C0[3]; /* 0x0000{C0..D0} */
-
- uint64_t ca_pci_rd_buf_flush; /* 0x0000D8 */
- uint64_t ca_pci_dma_addr_extn; /* 0x0000E0 */
- uint64_t ca_agp_dma_addr_extn; /* 0x0000E8 */
- uint64_t ca_force_inta; /* 0x0000F0 */
- uint64_t ca_force_intb; /* 0x0000F8 */
- uint64_t ca_debug_vector_sel; /* 0x000100 */
- uint64_t ca_debug_mux_core_sel; /* 0x000108 */
- uint64_t ca_debug_mux_pci_sel; /* 0x000110 */
- uint64_t ca_debug_domain_sel; /* 0x000118 */
-
- uint64_t ca_pad_000120[28]; /* 0x0001{20..F8} */
-
- uint64_t ca_gart_ptr_table; /* 0x200 */
- uint64_t ca_gart_tlb_addr[8]; /* 0x2{08..40} */
+ u64 ca_id; /* 0x000000 */
+ u64 ca_control1; /* 0x000008 */
+ u64 ca_control2; /* 0x000010 */
+ u64 ca_status1; /* 0x000018 */
+ u64 ca_status2; /* 0x000020 */
+ u64 ca_gart_aperature; /* 0x000028 */
+ u64 ca_gfx_detach; /* 0x000030 */
+ u64 ca_inta_dest_addr; /* 0x000038 */
+ u64 ca_intb_dest_addr; /* 0x000040 */
+ u64 ca_err_int_dest_addr; /* 0x000048 */
+ u64 ca_int_status; /* 0x000050 */
+ u64 ca_int_status_alias; /* 0x000058 */
+ u64 ca_mult_error; /* 0x000060 */
+ u64 ca_mult_error_alias; /* 0x000068 */
+ u64 ca_first_error; /* 0x000070 */
+ u64 ca_int_mask; /* 0x000078 */
+ u64 ca_crm_pkterr_type; /* 0x000080 */
+ u64 ca_crm_pkterr_type_alias; /* 0x000088 */
+ u64 ca_crm_ct_error_detail_1; /* 0x000090 */
+ u64 ca_crm_ct_error_detail_2; /* 0x000098 */
+ u64 ca_crm_tnumto; /* 0x0000A0 */
+ u64 ca_gart_err; /* 0x0000A8 */
+ u64 ca_pcierr_type; /* 0x0000B0 */
+ u64 ca_pcierr_addr; /* 0x0000B8 */
+
+ u64 ca_pad_0000C0[3]; /* 0x0000{C0..D0} */
+
+ u64 ca_pci_rd_buf_flush; /* 0x0000D8 */
+ u64 ca_pci_dma_addr_extn; /* 0x0000E0 */
+ u64 ca_agp_dma_addr_extn; /* 0x0000E8 */
+ u64 ca_force_inta; /* 0x0000F0 */
+ u64 ca_force_intb; /* 0x0000F8 */
+ u64 ca_debug_vector_sel; /* 0x000100 */
+ u64 ca_debug_mux_core_sel; /* 0x000108 */
+ u64 ca_debug_mux_pci_sel; /* 0x000110 */
+ u64 ca_debug_domain_sel; /* 0x000118 */
+
+ u64 ca_pad_000120[28]; /* 0x0001{20..F8} */
+
+ u64 ca_gart_ptr_table; /* 0x200 */
+ u64 ca_gart_tlb_addr[8]; /* 0x2{08..40} */
};
/*
diff --git a/include/asm-ia64/sn/tioca_provider.h b/include/asm-ia64/sn/tioca_provider.h
index b532ef6148ed..ab7fe2463468 100644
--- a/include/asm-ia64/sn/tioca_provider.h
+++ b/include/asm-ia64/sn/tioca_provider.h
@@ -56,31 +56,31 @@ struct tioca_kernel {
/*
* General GART stuff
*/
- uint64_t ca_ap_size; /* size of aperature in bytes */
- uint32_t ca_gart_entries; /* # uint64_t entries in gart */
- uint32_t ca_ap_pagesize; /* aperature page size in bytes */
- uint64_t ca_ap_bus_base; /* bus address of CA aperature */
- uint64_t ca_gart_size; /* gart size in bytes */
- uint64_t *ca_gart; /* gart table vaddr */
- uint64_t ca_gart_coretalk_addr; /* gart coretalk addr */
- uint8_t ca_gart_iscoherent; /* used in tioca_tlbflush */
+ u64 ca_ap_size; /* size of aperature in bytes */
+ u32 ca_gart_entries; /* # u64 entries in gart */
+ u32 ca_ap_pagesize; /* aperature page size in bytes */
+ u64 ca_ap_bus_base; /* bus address of CA aperature */
+ u64 ca_gart_size; /* gart size in bytes */
+ u64 *ca_gart; /* gart table vaddr */
+ u64 ca_gart_coretalk_addr; /* gart coretalk addr */
+ u8 ca_gart_iscoherent; /* used in tioca_tlbflush */
/* PCI GART convenience values */
- uint64_t ca_pciap_base; /* pci aperature bus base address */
- uint64_t ca_pciap_size; /* pci aperature size (bytes) */
- uint64_t ca_pcigart_base; /* gfx GART bus base address */
- uint64_t *ca_pcigart; /* gfx GART vm address */
- uint32_t ca_pcigart_entries;
- uint32_t ca_pcigart_start; /* PCI start index in ca_gart */
+ u64 ca_pciap_base; /* pci aperature bus base address */
+ u64 ca_pciap_size; /* pci aperature size (bytes) */
+ u64 ca_pcigart_base; /* gfx GART bus base address */
+ u64 *ca_pcigart; /* gfx GART vm address */
+ u32 ca_pcigart_entries;
+ u32 ca_pcigart_start; /* PCI start index in ca_gart */
void *ca_pcigart_pagemap;
/* AGP GART convenience values */
- uint64_t ca_gfxap_base; /* gfx aperature bus base address */
- uint64_t ca_gfxap_size; /* gfx aperature size (bytes) */
- uint64_t ca_gfxgart_base; /* gfx GART bus base address */
- uint64_t *ca_gfxgart; /* gfx GART vm address */
- uint32_t ca_gfxgart_entries;
- uint32_t ca_gfxgart_start; /* agpgart start index in ca_gart */
+ u64 ca_gfxap_base; /* gfx aperature bus base address */
+ u64 ca_gfxap_size; /* gfx aperature size (bytes) */
+ u64 ca_gfxgart_base; /* gfx GART bus base address */
+ u64 *ca_gfxgart; /* gfx GART vm address */
+ u32 ca_gfxgart_entries;
+ u32 ca_gfxgart_start; /* agpgart start index in ca_gart */
};
/*
@@ -93,11 +93,11 @@ struct tioca_kernel {
struct tioca_common {
struct pcibus_bussoft ca_common; /* common pciio header */
- uint32_t ca_rev;
- uint32_t ca_closest_nasid;
+ u32 ca_rev;
+ u32 ca_closest_nasid;
- uint64_t ca_prom_private;
- uint64_t ca_kernel_private;
+ u64 ca_prom_private;
+ u64 ca_kernel_private;
};
/**
@@ -139,9 +139,9 @@ tioca_paddr_to_gart(unsigned long paddr)
*/
static inline unsigned long
-tioca_physpage_to_gart(uint64_t page_addr)
+tioca_physpage_to_gart(u64 page_addr)
{
- uint64_t coretalk_addr;
+ u64 coretalk_addr;
coretalk_addr = PHYS_TO_TIODMA(page_addr);
if (!coretalk_addr) {
@@ -161,7 +161,7 @@ tioca_physpage_to_gart(uint64_t page_addr)
static inline void
tioca_tlbflush(struct tioca_kernel *tioca_kernel)
{
- volatile uint64_t tmp;
+ volatile u64 tmp;
volatile struct tioca *ca_base;
struct tioca_common *tioca_common;
@@ -200,7 +200,7 @@ tioca_tlbflush(struct tioca_kernel *tioca_kernel)
tmp = __sn_readq_relaxed(&ca_base->ca_control2);
}
-extern uint32_t tioca_gart_found;
+extern u32 tioca_gart_found;
extern struct list_head tioca_list;
extern int tioca_init_provider(void);
extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern);
diff --git a/include/asm-ia64/sn/tioce.h b/include/asm-ia64/sn/tioce.h
index ecaddf960086..d4c990712eac 100644
--- a/include/asm-ia64/sn/tioce.h
+++ b/include/asm-ia64/sn/tioce.h
@@ -35,72 +35,72 @@ 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 */
+ u64 ce_adm_id; /* 0x000000 */
+ u64 ce_pad_000008; /* 0x000008 */
+ u64 ce_adm_dyn_credit_status; /* 0x000010 */
+ u64 ce_adm_last_credit_status; /* 0x000018 */
+ u64 ce_adm_credit_limit; /* 0x000020 */
+ u64 ce_adm_force_credit; /* 0x000028 */
+ u64 ce_adm_control; /* 0x000030 */
+ u64 ce_adm_mmr_chn_timeout; /* 0x000038 */
+ u64 ce_adm_ssp_ure_timeout; /* 0x000040 */
+ u64 ce_adm_ssp_dre_timeout; /* 0x000048 */
+ u64 ce_adm_ssp_debug_sel; /* 0x000050 */
+ u64 ce_adm_int_status; /* 0x000058 */
+ u64 ce_adm_int_status_alias; /* 0x000060 */
+ u64 ce_adm_int_mask; /* 0x000068 */
+ u64 ce_adm_int_pending; /* 0x000070 */
+ u64 ce_adm_force_int; /* 0x000078 */
+ u64 ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */
+ u64 ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */
+ u64 ce_adm_error_summary; /* 0x000100 */
+ u64 ce_adm_error_summary_alias; /* 0x000108 */
+ u64 ce_adm_error_mask; /* 0x000110 */
+ u64 ce_adm_first_error; /* 0x000118 */
+ u64 ce_adm_error_overflow; /* 0x000120 */
+ u64 ce_adm_error_overflow_alias; /* 0x000128 */
+ u64 ce_pad_000130[2]; /* 0x000130 -- 0x000138 */
+ u64 ce_adm_tnum_error; /* 0x000140 */
+ u64 ce_adm_mmr_err_detail; /* 0x000148 */
+ u64 ce_adm_msg_sram_perr_detail; /* 0x000150 */
+ u64 ce_adm_bap_sram_perr_detail; /* 0x000158 */
+ u64 ce_adm_ce_sram_perr_detail; /* 0x000160 */
+ u64 ce_adm_ce_credit_oflow_detail; /* 0x000168 */
+ u64 ce_adm_tx_link_idle_max_timer; /* 0x000170 */
+ u64 ce_adm_pcie_debug_sel; /* 0x000178 */
+ u64 ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */
+
+ u64 ce_adm_pcie_debug_sel_top; /* 0x000200 */
+ u64 ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */
+ u64 ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */
+ u64 ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */
+ u64 ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */
+ u64 ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */
+ u64 ce_adm_pcie_trig_compare_top; /* 0x000230 */
+ u64 ce_adm_pcie_trig_compare_en_top; /* 0x000238 */
+ u64 ce_adm_ssp_debug_sel_top; /* 0x000240 */
+ u64 ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */
+ u64 ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */
+ u64 ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */
+ u64 ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */
+ u64 ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */
+ u64 ce_adm_ssp_trig_compare_top; /* 0x000270 */
+ u64 ce_adm_ssp_trig_compare_en_top; /* 0x000278 */
+ u64 ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */
+
+ u64 ce_adm_bap_ctrl; /* 0x000400 */
+ u64 ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */
+
+ u64 ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */
+ u64 ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */
+
+ u64 ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */
+ u64 ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */
+
+ u64 ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */
+ u64 ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */
+
+ u64 ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */
/*
* LSI : LSI's PCI Express Link Registers (Link#1 and Link#2)
@@ -109,141 +109,141 @@ typedef volatile struct tioce {
*/
#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 */
+ u64 ce_lsi_lpu_id; /* 0x00z000 */
+ u64 ce_lsi_rst; /* 0x00z008 */
+ u64 ce_lsi_dbg_stat; /* 0x00z010 */
+ u64 ce_lsi_dbg_cfg; /* 0x00z018 */
+ u64 ce_lsi_ltssm_ctrl; /* 0x00z020 */
+ u64 ce_lsi_lk_stat; /* 0x00z028 */
+ u64 ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */
+ u64 ce_lsi_int_and_stat; /* 0x00z040 */
+ u64 ce_lsi_int_mask; /* 0x00z048 */
+ u64 ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */
+ u64 ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */
+ u64 ce_pad_00z108; /* 0x00z108 */
+ u64 ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */
+ u64 ce_pad_00z118; /* 0x00z118 */
+ u64 ce_lsi_lk_perf_cnt1; /* 0x00z120 */
+ u64 ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */
+ u64 ce_lsi_lk_perf_cnt2; /* 0x00z130 */
+ u64 ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */
+ u64 ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */
+ u64 ce_lsi_lk_lyr_cfg; /* 0x00z200 */
+ u64 ce_lsi_lk_lyr_status; /* 0x00z208 */
+ u64 ce_lsi_lk_lyr_int_stat; /* 0x00z210 */
+ u64 ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */
+ u64 ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */
+ u64 ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */
+ u64 ce_lsi_fc_upd_ctl; /* 0x00z240 */
+ u64 ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */
+ u64 ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */
+ u64 ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */
+ u64 ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */
+ u64 ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */
+ u64 ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */
+ u64 ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */
+ u64 ce_lsi_rply_tmr_thr; /* 0x00z410 */
+ u64 ce_lsi_rply_tmr; /* 0x00z418 */
+ u64 ce_lsi_rply_num_stat; /* 0x00z420 */
+ u64 ce_lsi_rty_buf_max_addr; /* 0x00z428 */
+ u64 ce_lsi_rty_fifo_ptr; /* 0x00z430 */
+ u64 ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */
+ u64 ce_lsi_rty_fifo_cred; /* 0x00z440 */
+ u64 ce_lsi_seq_cnt; /* 0x00z448 */
+ u64 ce_lsi_ack_sent_seq_num; /* 0x00z450 */
+ u64 ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */
+ u64 ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */
+ u64 ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */
+ u64 ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */
+ u64 ce_pad_00z478; /* 0x00z478 */
+ u64 ce_lsi_mem_addr_ctl; /* 0x00z480 */
+ u64 ce_lsi_mem_d_ld0; /* 0x00z488 */
+ u64 ce_lsi_mem_d_ld1; /* 0x00z490 */
+ u64 ce_lsi_mem_d_ld2; /* 0x00z498 */
+ u64 ce_lsi_mem_d_ld3; /* 0x00z4A0 */
+ u64 ce_lsi_mem_d_ld4; /* 0x00z4A8 */
+ u64 ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */
+ u64 ce_lsi_rty_d_cnt; /* 0x00z4C0 */
+ u64 ce_lsi_seq_buf_cnt; /* 0x00z4C8 */
+ u64 ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */
+ u64 ce_pad_00z4D8; /* 0x00z4D8 */
+ u64 ce_lsi_ack_lat_thr; /* 0x00z4E0 */
+ u64 ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */
+ u64 ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */
+ u64 ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */
+ u64 ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */
+ u64 ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */
+ u64 ce_lsi_phy_lyr_cfg; /* 0x00z600 */
+ u64 ce_pad_00z608; /* 0x00z608 */
+ u64 ce_lsi_phy_lyr_int_stat; /* 0x00z610 */
+ u64 ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */
+ u64 ce_lsi_phy_lyr_int_mask; /* 0x00z620 */
+ u64 ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */
+ u64 ce_lsi_rcv_phy_cfg; /* 0x00z680 */
+ u64 ce_lsi_rcv_phy_stat1; /* 0x00z688 */
+ u64 ce_lsi_rcv_phy_stat2; /* 0x00z690 */
+ u64 ce_lsi_rcv_phy_stat3; /* 0x00z698 */
+ u64 ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */
+ u64 ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */
+ u64 ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */
+ u64 ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */
+ u64 ce_lsi_tx_phy_cfg; /* 0x00z700 */
+ u64 ce_lsi_tx_phy_stat; /* 0x00z708 */
+ u64 ce_lsi_tx_phy_int_stat; /* 0x00z710 */
+ u64 ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */
+ u64 ce_lsi_tx_phy_int_mask; /* 0x00z720 */
+ u64 ce_lsi_tx_phy_stat2; /* 0x00z728 */
+ u64 ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */
+ u64 ce_lsi_ltssm_cfg1; /* 0x00z780 */
+ u64 ce_lsi_ltssm_cfg2; /* 0x00z788 */
+ u64 ce_lsi_ltssm_cfg3; /* 0x00z790 */
+ u64 ce_lsi_ltssm_cfg4; /* 0x00z798 */
+ u64 ce_lsi_ltssm_cfg5; /* 0x00z7A0 */
+ u64 ce_lsi_ltssm_stat1; /* 0x00z7A8 */
+ u64 ce_lsi_ltssm_stat2; /* 0x00z7B0 */
+ u64 ce_lsi_ltssm_int_stat; /* 0x00z7B8 */
+ u64 ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */
+ u64 ce_lsi_ltssm_int_mask; /* 0x00z7C8 */
+ u64 ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */
+ u64 ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */
+ u64 ce_lsi_gb_cfg1; /* 0x00z800 */
+ u64 ce_lsi_gb_cfg2; /* 0x00z808 */
+ u64 ce_lsi_gb_cfg3; /* 0x00z810 */
+ u64 ce_lsi_gb_cfg4; /* 0x00z818 */
+ u64 ce_lsi_gb_stat; /* 0x00z820 */
+ u64 ce_lsi_gb_int_stat; /* 0x00z828 */
+ u64 ce_lsi_gb_int_stat_test; /* 0x00z830 */
+ u64 ce_lsi_gb_int_mask; /* 0x00z838 */
+ u64 ce_lsi_gb_pwr_dn1; /* 0x00z840 */
+ u64 ce_lsi_gb_pwr_dn2; /* 0x00z848 */
+ u64 ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */
} ce_lsi[2];
- uint64_t ce_pad_004000[10]; /* 0x004000 -- 0x004048 */
+ u64 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 */
+ u64 ce_crm_debug_mux; /* 0x004050 */
+ u64 ce_pad_004058; /* 0x004058 */
+ u64 ce_crm_ssp_err_cmd_wrd; /* 0x004060 */
+ u64 ce_crm_ssp_err_addr; /* 0x004068 */
+ u64 ce_crm_ssp_err_syn; /* 0x004070 */
- uint64_t ce_pad_004078[499]; /* 0x004078 -- 0x005008 */
+ u64 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 */
+ u64 ce_cxm_dyn_credit_status; /* 0x005010 */
+ u64 ce_cxm_last_credit_status; /* 0x005018 */
+ u64 ce_cxm_credit_limit; /* 0x005020 */
+ u64 ce_cxm_force_credit; /* 0x005028 */
+ u64 ce_cxm_disable_bypass; /* 0x005030 */
+ u64 ce_pad_005038[3]; /* 0x005038 -- 0x005048 */
+ u64 ce_cxm_debug_mux; /* 0x005050 */
- uint64_t ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */
+ u64 ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */
/*
* DTL: Downstream Transaction Layer Regs (Link#1 and Link#2)
@@ -258,209 +258,209 @@ typedef volatile struct tioce {
#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 */
+ u64 ce_dtl_dtdr_credit_limit; /* 0x00y000 */
+ u64 ce_dtl_dtdr_credit_force; /* 0x00y008 */
+ u64 ce_dtl_dyn_credit_status; /* 0x00y010 */
+ u64 ce_dtl_dtl_last_credit_stat; /* 0x00y018 */
+ u64 ce_dtl_dtl_ctrl; /* 0x00y020 */
+ u64 ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */
+ u64 ce_dtl_debug_sel; /* 0x00y050 */
+ u64 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 */
+ u64 ce_utl_utl_ctrl; /* 0x00z000 */
+ u64 ce_utl_debug_sel; /* 0x00z008 */
+ u64 ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */
} ce_dtl_utl[2];
- uint64_t ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */
+ u64 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 */
+ u64 ce_ure_dyn_credit_status; /* 0x00B010 */
+ u64 ce_ure_last_credit_status; /* 0x00B018 */
+ u64 ce_ure_credit_limit; /* 0x00B020 */
+ u64 ce_pad_00B028; /* 0x00B028 */
+ u64 ce_ure_control; /* 0x00B030 */
+ u64 ce_ure_status; /* 0x00B038 */
+ u64 ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */
+ u64 ce_ure_debug_sel; /* 0x00B050 */
+ u64 ce_ure_pcie_debug_sel; /* 0x00B058 */
+ u64 ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */
+ u64 ce_ure_ssp_err_addr; /* 0x00B068 */
+ u64 ce_ure_page_map; /* 0x00B070 */
+ u64 ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */
+ u64 ce_ure_pipe_sel1; /* 0x00B088 */
+ u64 ce_ure_pipe_mask1; /* 0x00B090 */
+ u64 ce_ure_pipe_sel2; /* 0x00B098 */
+ u64 ce_ure_pipe_mask2; /* 0x00B0A0 */
+ u64 ce_ure_pcie1_credits_sent; /* 0x00B0A8 */
+ u64 ce_ure_pcie1_credits_used; /* 0x00B0B0 */
+ u64 ce_ure_pcie1_credit_limit; /* 0x00B0B8 */
+ u64 ce_ure_pcie2_credits_sent; /* 0x00B0C0 */
+ u64 ce_ure_pcie2_credits_used; /* 0x00B0C8 */
+ u64 ce_ure_pcie2_credit_limit; /* 0x00B0D0 */
+ u64 ce_ure_pcie_force_credit; /* 0x00B0D8 */
+ u64 ce_ure_rd_tnum_val; /* 0x00B0E0 */
+ u64 ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */
+ u64 ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */
+ u64 ce_ure_rd_tnum_error; /* 0x00B0F8 */
+ u64 ce_ure_rd_tnum_first_cl; /* 0x00B100 */
+ u64 ce_ure_rd_tnum_link_buf; /* 0x00B108 */
+ u64 ce_ure_wr_tnum_val; /* 0x00B110 */
+ u64 ce_ure_sram_err_addr0; /* 0x00B118 */
+ u64 ce_ure_sram_err_addr1; /* 0x00B120 */
+ u64 ce_ure_sram_err_addr2; /* 0x00B128 */
+ u64 ce_ure_sram_rd_addr0; /* 0x00B130 */
+ u64 ce_ure_sram_rd_addr1; /* 0x00B138 */
+ u64 ce_ure_sram_rd_addr2; /* 0x00B140 */
+ u64 ce_ure_sram_wr_addr0; /* 0x00B148 */
+ u64 ce_ure_sram_wr_addr1; /* 0x00B150 */
+ u64 ce_ure_sram_wr_addr2; /* 0x00B158 */
+ u64 ce_ure_buf_flush10; /* 0x00B160 */
+ u64 ce_ure_buf_flush11; /* 0x00B168 */
+ u64 ce_ure_buf_flush12; /* 0x00B170 */
+ u64 ce_ure_buf_flush13; /* 0x00B178 */
+ u64 ce_ure_buf_flush20; /* 0x00B180 */
+ u64 ce_ure_buf_flush21; /* 0x00B188 */
+ u64 ce_ure_buf_flush22; /* 0x00B190 */
+ u64 ce_ure_buf_flush23; /* 0x00B198 */
+ u64 ce_ure_pcie_control1; /* 0x00B1A0 */
+ u64 ce_ure_pcie_control2; /* 0x00B1A8 */
+
+ u64 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 */
+ u64 data63_0[512]; /* 0x00C000 -- 0x00CFF8 */
+ u64 data127_64[512]; /* 0x00D000 -- 0x00DFF8 */
+ u64 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 */
+ u64 data63_0[512]; /* 0x00F000 -- 0x00FFF8 */
+ u64 data127_64[512]; /* 0x010000 -- 0x010FF8 */
+ u64 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 */
+ u64 data63_0[512]; /* 0x012000 -- 0x012FF8 */
+ u64 data127_64[512]; /* 0x013000 -- 0x013FF8 */
+ u64 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 */
+ u64 data63_0[512]; /* 0x015000 -- 0x015FF8 */
+ u64 data127_64[512]; /* 0x016000 -- 0x016FF8 */
+ u64 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 */
+ u64 data63_0[512]; /* 0x018000 -- 0x018FF8 */
+ u64 data127_64[512]; /* 0x019000 -- 0x019FF8 */
+ u64 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 */
+ u64 data31_0[64]; /* 0x01B000 -- 0x01B1F8 */
+ u64 data95_32[64]; /* 0x01B200 -- 0x01B3F8 */
+ u64 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 */
+ u64 data41_0[64]; /* 0x01B600 -- 0x01B7F8 */
+ u64 data69_42[64]; /* 0x01B800 -- 0x01B9F8 */
} ce_ure_maint_rci;
/* Response Queue */
- uint64_t ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */
+ u64 ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */
- uint64_t ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */
+ u64 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 */
+ u64 data63_0[258]; /* 0x024000 -- 0x024808 */
+ u64 data127_64[258]; /* 0x024810 -- 0x025018 */
+ u64 parity[258]; /* 0x025020 -- 0x025828 */
} ce_adm_maint_bap_buf;
- uint64_t ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */
+ u64 ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */
/* URE: 40bit PMU ATE Buffer */ /* 0x030000 -- 0x037FF8 */
- uint64_t ce_ure_ate40[TIOCE_NUM_M40_ATES];
+ u64 ce_ure_ate40[TIOCE_NUM_M40_ATES];
/* URE: 32/40bit PMU ATE Buffer */ /* 0x038000 -- 0x03BFF8 */
- uint64_t ce_ure_ate3240[TIOCE_NUM_M3240_ATES];
+ u64 ce_ure_ate3240[TIOCE_NUM_M3240_ATES];
- uint64_t ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */
+ u64 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 */
+ u64 ce_dre_dyn_credit_status1; /* 0x040010 */
+ u64 ce_dre_dyn_credit_status2; /* 0x040018 */
+ u64 ce_dre_last_credit_status1; /* 0x040020 */
+ u64 ce_dre_last_credit_status2; /* 0x040028 */
+ u64 ce_dre_credit_limit1; /* 0x040030 */
+ u64 ce_dre_credit_limit2; /* 0x040038 */
+ u64 ce_dre_force_credit1; /* 0x040040 */
+ u64 ce_dre_force_credit2; /* 0x040048 */
+ u64 ce_dre_debug_mux1; /* 0x040050 */
+ u64 ce_dre_debug_mux2; /* 0x040058 */
+ u64 ce_dre_ssp_err_cmd_wrd; /* 0x040060 */
+ u64 ce_dre_ssp_err_addr; /* 0x040068 */
+ u64 ce_dre_comp_err_cmd_wrd; /* 0x040070 */
+ u64 ce_dre_comp_err_addr; /* 0x040078 */
+ u64 ce_dre_req_status; /* 0x040080 */
+ u64 ce_dre_config1; /* 0x040088 */
+ u64 ce_dre_config2; /* 0x040090 */
+ u64 ce_dre_config_req_status; /* 0x040098 */
+ u64 ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */
+ u64 ce_dre_dyn_fifo; /* 0x040100 */
+ u64 ce_pad_040108[3]; /* 0x040108 -- 0x040118 */
+ u64 ce_dre_last_fifo; /* 0x040120 */
+
+ u64 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 */
+ u64 data63_0[32]; /* 0x040200 -- 0x0402F8 */
+ u64 data127_64[32]; /* 0x040300 -- 0x0403F8 */
+ u64 parity[32]; /* 0x040400 -- 0x0404F8 */
} ce_dre_maint_ds_head_q;
- uint64_t ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */
+ u64 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 */
+ u64 data63_0[256]; /* 0x041000 -- 0x0417F8 */
+ u64 ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */
+ u64 data127_64[256]; /* 0x042000 -- 0x0427F8 */
+ u64 ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */
+ u64 parity[256]; /* 0x043000 -- 0x0437F8 */
+ u64 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 */
+ u64 data63_0[8]; /* 0x044000 -- 0x044038 */
+ u64 ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */
+ u64 data127_64[8]; /* 0x044100 -- 0x044138 */
+ u64 ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */
+ u64 parity[8]; /* 0x044200 -- 0x044238 */
+ u64 ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */
} ce_dre_maint_ure_us_rsp_q;
- uint64_t ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */
+ u64 ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */
- uint64_t ce_end_of_struct; /* 0x044400 */
+ u64 ce_end_of_struct; /* 0x044400 */
} tioce_t;
@@ -625,11 +625,11 @@ typedef volatile struct tioce {
#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) & \
+#define CE_URE_PIPE_BUS(b) (((u64)(b) << BUS_SRC_ID_SHFT) & \
CE_URE_BUS_MASK)
-#define CE_URE_PIPE_DEV(d) (((uint64_t)(d) << DEV_SRC_ID_SHFT) & \
+#define CE_URE_PIPE_DEV(d) (((u64)(d) << DEV_SRC_ID_SHFT) & \
CE_URE_DEV_MASK)
-#define CE_URE_PIPE_FNC(f) (((uint64_t)(f) << FNC_SRC_ID_SHFT) & \
+#define CE_URE_PIPE_FNC(f) (((u64)(f) << FNC_SRC_ID_SHFT) & \
CE_URE_FNC_MASK)
#define CE_URE_SEL1_SHFT 0
@@ -660,9 +660,9 @@ typedef volatile struct tioce {
#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) & \
+#define CE_URE_PN1_SET(n) (((u64)(n) << CE_URE_PN1_SHFT) & \
CE_URE_PN1_MASK)
-#define CE_URE_PN2_SET(n) (((uint64_t)(n) << CE_URE_PN2_SHFT) & \
+#define CE_URE_PN2_SET(n) (((u64)(n) << CE_URE_PN2_SHFT) & \
CE_URE_PN2_MASK)
/* ce_ure_pcie_control2 register bit masks & shifts */
@@ -681,9 +681,9 @@ typedef volatile struct tioce {
#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) & \
+#define CE_URE_PSN1_SET(n) (((u64)(n) << CE_URE_PSN1_SHFT) & \
CE_URE_PSN1_MASK)
-#define CE_URE_PSN2_SET(n) (((uint64_t)(n) << CE_URE_PSN2_SHFT) & \
+#define CE_URE_PSN2_SET(n) (((u64)(n) << CE_URE_PSN2_SHFT) & \
CE_URE_PSN2_MASK)
/*
diff --git a/include/asm-ia64/sn/tioce_provider.h b/include/asm-ia64/sn/tioce_provider.h
index cb414908671d..6d62b13f7ae7 100644
--- a/include/asm-ia64/sn/tioce_provider.h
+++ b/include/asm-ia64/sn/tioce_provider.h
@@ -21,9 +21,9 @@
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;
+ u32 ce_rev;
+ u64 ce_kernel_private;
+ u64 ce_prom_private;
};
struct tioce_kernel {
@@ -31,31 +31,31 @@ struct tioce_kernel {
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;
+ u64 ce_ate40_shadow[TIOCE_NUM_M40_ATES];
+ u64 ce_ate3240_shadow[TIOCE_NUM_M3240_ATES];
+ u32 ce_ate3240_pagesize;
- uint8_t ce_port1_secondary;
+ u8 ce_port1_secondary;
/* per-port resources */
struct {
int dirmap_refcnt;
- uint64_t dirmap_shadow;
+ u64 dirmap_shadow;
} ce_port[TIOCE_NUM_PORTS];
};
struct tioce_dmamap {
struct list_head ce_dmamap_list; /* headed by tioce_kernel */
- uint32_t refcnt;
+ u32 refcnt;
- uint64_t nbytes; /* # bytes mapped */
+ u64 nbytes; /* # bytes mapped */
- uint64_t ct_start; /* coretalk start address */
- uint64_t pci_start; /* bus start address */
+ u64 ct_start; /* coretalk start address */
+ u64 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 */
+ u64 *ate_hw; /* hw ptr of first ate in map */
+ u64 *ate_shadow; /* shadow ptr of firat ate */
+ u16 ate_count; /* # ate's in the map */
};
extern int tioce_init_provider(void);
diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h
index 5f2489c9d2dd..f47c08ab483c 100644
--- a/include/asm-ia64/sn/tiocp.h
+++ b/include/asm-ia64/sn/tiocp.h
@@ -21,189 +21,189 @@ struct tiocp{
/* 0x000000-0x00FFFF -- Local Registers */
/* 0x000000-0x000057 -- (Legacy Widget Space) Configuration */
- uint64_t cp_id; /* 0x000000 */
- uint64_t cp_stat; /* 0x000008 */
- uint64_t cp_err_upper; /* 0x000010 */
- uint64_t cp_err_lower; /* 0x000018 */
+ u64 cp_id; /* 0x000000 */
+ u64 cp_stat; /* 0x000008 */
+ u64 cp_err_upper; /* 0x000010 */
+ u64 cp_err_lower; /* 0x000018 */
#define cp_err cp_err_lower
- uint64_t cp_control; /* 0x000020 */
- uint64_t cp_req_timeout; /* 0x000028 */
- uint64_t cp_intr_upper; /* 0x000030 */
- uint64_t cp_intr_lower; /* 0x000038 */
+ u64 cp_control; /* 0x000020 */
+ u64 cp_req_timeout; /* 0x000028 */
+ u64 cp_intr_upper; /* 0x000030 */
+ u64 cp_intr_lower; /* 0x000038 */
#define cp_intr cp_intr_lower
- uint64_t cp_err_cmdword; /* 0x000040 */
- uint64_t _pad_000048; /* 0x000048 */
- uint64_t cp_tflush; /* 0x000050 */
+ u64 cp_err_cmdword; /* 0x000040 */
+ u64 _pad_000048; /* 0x000048 */
+ u64 cp_tflush; /* 0x000050 */
/* 0x000058-0x00007F -- Bridge-specific Configuration */
- uint64_t cp_aux_err; /* 0x000058 */
- uint64_t cp_resp_upper; /* 0x000060 */
- uint64_t cp_resp_lower; /* 0x000068 */
+ u64 cp_aux_err; /* 0x000058 */
+ u64 cp_resp_upper; /* 0x000060 */
+ u64 cp_resp_lower; /* 0x000068 */
#define cp_resp cp_resp_lower
- uint64_t cp_tst_pin_ctrl; /* 0x000070 */
- uint64_t cp_addr_lkerr; /* 0x000078 */
+ u64 cp_tst_pin_ctrl; /* 0x000070 */
+ u64 cp_addr_lkerr; /* 0x000078 */
/* 0x000080-0x00008F -- PMU & MAP */
- uint64_t cp_dir_map; /* 0x000080 */
- uint64_t _pad_000088; /* 0x000088 */
+ u64 cp_dir_map; /* 0x000080 */
+ u64 _pad_000088; /* 0x000088 */
/* 0x000090-0x00009F -- SSRAM */
- uint64_t cp_map_fault; /* 0x000090 */
- uint64_t _pad_000098; /* 0x000098 */
+ u64 cp_map_fault; /* 0x000090 */
+ u64 _pad_000098; /* 0x000098 */
/* 0x0000A0-0x0000AF -- Arbitration */
- uint64_t cp_arb; /* 0x0000A0 */
- uint64_t _pad_0000A8; /* 0x0000A8 */
+ u64 cp_arb; /* 0x0000A0 */
+ u64 _pad_0000A8; /* 0x0000A8 */
/* 0x0000B0-0x0000BF -- Number In A Can or ATE Parity Error */
- uint64_t cp_ate_parity_err; /* 0x0000B0 */
- uint64_t _pad_0000B8; /* 0x0000B8 */
+ u64 cp_ate_parity_err; /* 0x0000B0 */
+ u64 _pad_0000B8; /* 0x0000B8 */
/* 0x0000C0-0x0000FF -- PCI/GIO */
- uint64_t cp_bus_timeout; /* 0x0000C0 */
- uint64_t cp_pci_cfg; /* 0x0000C8 */
- uint64_t cp_pci_err_upper; /* 0x0000D0 */
- uint64_t cp_pci_err_lower; /* 0x0000D8 */
+ u64 cp_bus_timeout; /* 0x0000C0 */
+ u64 cp_pci_cfg; /* 0x0000C8 */
+ u64 cp_pci_err_upper; /* 0x0000D0 */
+ u64 cp_pci_err_lower; /* 0x0000D8 */
#define cp_pci_err cp_pci_err_lower
- uint64_t _pad_0000E0[4]; /* 0x0000{E0..F8} */
+ u64 _pad_0000E0[4]; /* 0x0000{E0..F8} */
/* 0x000100-0x0001FF -- Interrupt */
- uint64_t cp_int_status; /* 0x000100 */
- uint64_t cp_int_enable; /* 0x000108 */
- uint64_t cp_int_rst_stat; /* 0x000110 */
- uint64_t cp_int_mode; /* 0x000118 */
- uint64_t cp_int_device; /* 0x000120 */
- uint64_t cp_int_host_err; /* 0x000128 */
- uint64_t cp_int_addr[8]; /* 0x0001{30,,,68} */
- uint64_t cp_err_int_view; /* 0x000170 */
- uint64_t cp_mult_int; /* 0x000178 */
- uint64_t cp_force_always[8]; /* 0x0001{80,,,B8} */
- uint64_t cp_force_pin[8]; /* 0x0001{C0,,,F8} */
+ u64 cp_int_status; /* 0x000100 */
+ u64 cp_int_enable; /* 0x000108 */
+ u64 cp_int_rst_stat; /* 0x000110 */
+ u64 cp_int_mode; /* 0x000118 */
+ u64 cp_int_device; /* 0x000120 */
+ u64 cp_int_host_err; /* 0x000128 */
+ u64 cp_int_addr[8]; /* 0x0001{30,,,68} */
+ u64 cp_err_int_view; /* 0x000170 */
+ u64 cp_mult_int; /* 0x000178 */
+ u64 cp_force_always[8]; /* 0x0001{80,,,B8} */
+ u64 cp_force_pin[8]; /* 0x0001{C0,,,F8} */
/* 0x000200-0x000298 -- Device */
- uint64_t cp_device[4]; /* 0x0002{00,,,18} */
- uint64_t _pad_000220[4]; /* 0x0002{20,,,38} */
- uint64_t cp_wr_req_buf[4]; /* 0x0002{40,,,58} */
- uint64_t _pad_000260[4]; /* 0x0002{60,,,78} */
- uint64_t cp_rrb_map[2]; /* 0x0002{80,,,88} */
+ u64 cp_device[4]; /* 0x0002{00,,,18} */
+ u64 _pad_000220[4]; /* 0x0002{20,,,38} */
+ u64 cp_wr_req_buf[4]; /* 0x0002{40,,,58} */
+ u64 _pad_000260[4]; /* 0x0002{60,,,78} */
+ u64 cp_rrb_map[2]; /* 0x0002{80,,,88} */
#define cp_even_resp cp_rrb_map[0] /* 0x000280 */
#define cp_odd_resp cp_rrb_map[1] /* 0x000288 */
- uint64_t cp_resp_status; /* 0x000290 */
- uint64_t cp_resp_clear; /* 0x000298 */
+ u64 cp_resp_status; /* 0x000290 */
+ u64 cp_resp_clear; /* 0x000298 */
- uint64_t _pad_0002A0[12]; /* 0x0002{A0..F8} */
+ u64 _pad_0002A0[12]; /* 0x0002{A0..F8} */
/* 0x000300-0x0003F8 -- Buffer Address Match Registers */
struct {
- uint64_t upper; /* 0x0003{00,,,F0} */
- uint64_t lower; /* 0x0003{08,,,F8} */
+ u64 upper; /* 0x0003{00,,,F0} */
+ u64 lower; /* 0x0003{08,,,F8} */
} cp_buf_addr_match[16];
/* 0x000400-0x0005FF -- Performance Monitor Registers (even only) */
struct {
- uint64_t flush_w_touch; /* 0x000{400,,,5C0} */
- uint64_t flush_wo_touch; /* 0x000{408,,,5C8} */
- uint64_t inflight; /* 0x000{410,,,5D0} */
- uint64_t prefetch; /* 0x000{418,,,5D8} */
- uint64_t total_pci_retry; /* 0x000{420,,,5E0} */
- uint64_t max_pci_retry; /* 0x000{428,,,5E8} */
- uint64_t max_latency; /* 0x000{430,,,5F0} */
- uint64_t clear_all; /* 0x000{438,,,5F8} */
+ u64 flush_w_touch; /* 0x000{400,,,5C0} */
+ u64 flush_wo_touch; /* 0x000{408,,,5C8} */
+ u64 inflight; /* 0x000{410,,,5D0} */
+ u64 prefetch; /* 0x000{418,,,5D8} */
+ u64 total_pci_retry; /* 0x000{420,,,5E0} */
+ u64 max_pci_retry; /* 0x000{428,,,5E8} */
+ u64 max_latency; /* 0x000{430,,,5F0} */
+ u64 clear_all; /* 0x000{438,,,5F8} */
} cp_buf_count[8];
/* 0x000600-0x0009FF -- PCI/X registers */
- uint64_t cp_pcix_bus_err_addr; /* 0x000600 */
- uint64_t cp_pcix_bus_err_attr; /* 0x000608 */
- uint64_t cp_pcix_bus_err_data; /* 0x000610 */
- uint64_t cp_pcix_pio_split_addr; /* 0x000618 */
- uint64_t cp_pcix_pio_split_attr; /* 0x000620 */
- uint64_t cp_pcix_dma_req_err_attr; /* 0x000628 */
- uint64_t cp_pcix_dma_req_err_addr; /* 0x000630 */
- uint64_t cp_pcix_timeout; /* 0x000638 */
+ u64 cp_pcix_bus_err_addr; /* 0x000600 */
+ u64 cp_pcix_bus_err_attr; /* 0x000608 */
+ u64 cp_pcix_bus_err_data; /* 0x000610 */
+ u64 cp_pcix_pio_split_addr; /* 0x000618 */
+ u64 cp_pcix_pio_split_attr; /* 0x000620 */
+ u64 cp_pcix_dma_req_err_attr; /* 0x000628 */
+ u64 cp_pcix_dma_req_err_addr; /* 0x000630 */
+ u64 cp_pcix_timeout; /* 0x000638 */
- uint64_t _pad_000640[24]; /* 0x000{640,,,6F8} */
+ u64 _pad_000640[24]; /* 0x000{640,,,6F8} */
/* 0x000700-0x000737 -- Debug Registers */
- uint64_t cp_ct_debug_ctl; /* 0x000700 */
- uint64_t cp_br_debug_ctl; /* 0x000708 */
- uint64_t cp_mux3_debug_ctl; /* 0x000710 */
- uint64_t cp_mux4_debug_ctl; /* 0x000718 */
- uint64_t cp_mux5_debug_ctl; /* 0x000720 */
- uint64_t cp_mux6_debug_ctl; /* 0x000728 */
- uint64_t cp_mux7_debug_ctl; /* 0x000730 */
+ u64 cp_ct_debug_ctl; /* 0x000700 */
+ u64 cp_br_debug_ctl; /* 0x000708 */
+ u64 cp_mux3_debug_ctl; /* 0x000710 */
+ u64 cp_mux4_debug_ctl; /* 0x000718 */
+ u64 cp_mux5_debug_ctl; /* 0x000720 */
+ u64 cp_mux6_debug_ctl; /* 0x000728 */
+ u64 cp_mux7_debug_ctl; /* 0x000730 */
- uint64_t _pad_000738[89]; /* 0x000{738,,,9F8} */
+ u64 _pad_000738[89]; /* 0x000{738,,,9F8} */
/* 0x000A00-0x000BFF -- PCI/X Read&Write Buffer */
struct {
- uint64_t cp_buf_addr; /* 0x000{A00,,,AF0} */
- uint64_t cp_buf_attr; /* 0X000{A08,,,AF8} */
+ u64 cp_buf_addr; /* 0x000{A00,,,AF0} */
+ u64 cp_buf_attr; /* 0X000{A08,,,AF8} */
} cp_pcix_read_buf_64[16];
struct {
- uint64_t cp_buf_addr; /* 0x000{B00,,,BE0} */
- uint64_t cp_buf_attr; /* 0x000{B08,,,BE8} */
- uint64_t cp_buf_valid; /* 0x000{B10,,,BF0} */
- uint64_t __pad1; /* 0x000{B18,,,BF8} */
+ u64 cp_buf_addr; /* 0x000{B00,,,BE0} */
+ u64 cp_buf_attr; /* 0x000{B08,,,BE8} */
+ u64 cp_buf_valid; /* 0x000{B10,,,BF0} */
+ u64 __pad1; /* 0x000{B18,,,BF8} */
} cp_pcix_write_buf_64[8];
/* End of Local Registers -- Start of Address Map space */
- char _pad_000c00[0x010000 - 0x000c00];
+ char _pad_000c00[0x010000 - 0x000c00];
/* 0x010000-0x011FF8 -- Internal ATE RAM (Auto Parity Generation) */
- uint64_t cp_int_ate_ram[1024]; /* 0x010000-0x011FF8 */
+ u64 cp_int_ate_ram[1024]; /* 0x010000-0x011FF8 */
- char _pad_012000[0x14000 - 0x012000];
+ char _pad_012000[0x14000 - 0x012000];
/* 0x014000-0x015FF8 -- Internal ATE RAM (Manual Parity Generation) */
- uint64_t cp_int_ate_ram_mp[1024]; /* 0x014000-0x015FF8 */
+ u64 cp_int_ate_ram_mp[1024]; /* 0x014000-0x015FF8 */
- char _pad_016000[0x18000 - 0x016000];
+ char _pad_016000[0x18000 - 0x016000];
/* 0x18000-0x197F8 -- TIOCP Write Request Ram */
- uint64_t cp_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
- uint64_t cp_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
- uint64_t cp_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
+ u64 cp_wr_req_lower[256]; /* 0x18000 - 0x187F8 */
+ u64 cp_wr_req_upper[256]; /* 0x18800 - 0x18FF8 */
+ u64 cp_wr_req_parity[256]; /* 0x19000 - 0x197F8 */
- char _pad_019800[0x1C000 - 0x019800];
+ char _pad_019800[0x1C000 - 0x019800];
/* 0x1C000-0x1EFF8 -- TIOCP Read Response Ram */
- uint64_t cp_rd_resp_lower[512]; /* 0x1C000 - 0x1CFF8 */
- uint64_t cp_rd_resp_upper[512]; /* 0x1D000 - 0x1DFF8 */
- uint64_t cp_rd_resp_parity[512]; /* 0x1E000 - 0x1EFF8 */
+ u64 cp_rd_resp_lower[512]; /* 0x1C000 - 0x1CFF8 */
+ u64 cp_rd_resp_upper[512]; /* 0x1D000 - 0x1DFF8 */
+ u64 cp_rd_resp_parity[512]; /* 0x1E000 - 0x1EFF8 */
- char _pad_01F000[0x20000 - 0x01F000];
+ char _pad_01F000[0x20000 - 0x01F000];
/* 0x020000-0x021FFF -- Host Device (CP) Configuration Space (not used) */
- char _pad_020000[0x021000 - 0x20000];
+ char _pad_020000[0x021000 - 0x20000];
/* 0x021000-0x027FFF -- PCI Device Configuration Spaces */
union {
- uint8_t c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
- uint16_t s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
- uint32_t l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
- uint64_t d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
+ u8 c[0x1000 / 1]; /* 0x02{0000,,,7FFF} */
+ u16 s[0x1000 / 2]; /* 0x02{0000,,,7FFF} */
+ u32 l[0x1000 / 4]; /* 0x02{0000,,,7FFF} */
+ u64 d[0x1000 / 8]; /* 0x02{0000,,,7FFF} */
union {
- uint8_t c[0x100 / 1];
- uint16_t s[0x100 / 2];
- uint32_t l[0x100 / 4];
- uint64_t d[0x100 / 8];
+ u8 c[0x100 / 1];
+ u16 s[0x100 / 2];
+ u32 l[0x100 / 4];
+ u64 d[0x100 / 8];
} f[8];
} cp_type0_cfg_dev[7]; /* 0x02{1000,,,7FFF} */
/* 0x028000-0x028FFF -- PCI Type 1 Configuration Space */
union {
- uint8_t c[0x1000 / 1]; /* 0x028000-0x029000 */
- uint16_t s[0x1000 / 2]; /* 0x028000-0x029000 */
- uint32_t l[0x1000 / 4]; /* 0x028000-0x029000 */
- uint64_t d[0x1000 / 8]; /* 0x028000-0x029000 */
+ u8 c[0x1000 / 1]; /* 0x028000-0x029000 */
+ u16 s[0x1000 / 2]; /* 0x028000-0x029000 */
+ u32 l[0x1000 / 4]; /* 0x028000-0x029000 */
+ u64 d[0x1000 / 8]; /* 0x028000-0x029000 */
union {
- uint8_t c[0x100 / 1];
- uint16_t s[0x100 / 2];
- uint32_t l[0x100 / 4];
- uint64_t d[0x100 / 8];
+ u8 c[0x100 / 1];
+ u16 s[0x100 / 2];
+ u32 l[0x100 / 4];
+ u64 d[0x100 / 8];
} f[8];
} cp_type1_cfg; /* 0x028000-0x029000 */
@@ -211,30 +211,30 @@ struct tiocp{
/* 0x030000-0x030007 -- PCI Interrupt Acknowledge Cycle */
union {
- uint8_t c[8 / 1];
- uint16_t s[8 / 2];
- uint32_t l[8 / 4];
- uint64_t d[8 / 8];
+ u8 c[8 / 1];
+ u16 s[8 / 2];
+ u32 l[8 / 4];
+ u64 d[8 / 8];
} cp_pci_iack; /* 0x030000-0x030007 */
char _pad_030007[0x040000-0x030008];
/* 0x040000-0x040007 -- PCIX Special Cycle */
union {
- uint8_t c[8 / 1];
- uint16_t s[8 / 2];
- uint32_t l[8 / 4];
- uint64_t d[8 / 8];
+ u8 c[8 / 1];
+ u16 s[8 / 2];
+ u32 l[8 / 4];
+ u64 d[8 / 8];
} cp_pcix_cycle; /* 0x040000-0x040007 */
char _pad_040007[0x200000-0x040008];
/* 0x200000-0x7FFFFF -- PCI/GIO Device Spaces */
union {
- uint8_t c[0x100000 / 1];
- uint16_t s[0x100000 / 2];
- uint32_t l[0x100000 / 4];
- uint64_t d[0x100000 / 8];
+ u8 c[0x100000 / 1];
+ u16 s[0x100000 / 2];
+ u32 l[0x100000 / 4];
+ u64 d[0x100000 / 8];
} cp_devio_raw[6]; /* 0x200000-0x7FFFFF */
#define cp_devio(n) cp_devio_raw[((n)<2)?(n*2):(n+2)]
@@ -243,10 +243,10 @@ struct tiocp{
/* 0xA00000-0xBFFFFF -- PCI/GIO Device Spaces w/flush */
union {
- uint8_t c[0x100000 / 1];
- uint16_t s[0x100000 / 2];
- uint32_t l[0x100000 / 4];
- uint64_t d[0x100000 / 8];
+ u8 c[0x100000 / 1];
+ u16 s[0x100000 / 2];
+ u32 l[0x100000 / 4];
+ u64 d[0x100000 / 8];
} cp_devio_raw_flush[6]; /* 0xA00000-0xBFFFFF */
#define cp_devio_flush(n) cp_devio_raw_flush[((n)<2)?(n*2):(n+2)]
diff --git a/include/asm-ia64/sn/tiocx.h b/include/asm-ia64/sn/tiocx.h
index 5699e75e5024..d29728492f36 100644
--- a/include/asm-ia64/sn/tiocx.h
+++ b/include/asm-ia64/sn/tiocx.h
@@ -40,10 +40,10 @@ struct cx_drv {
};
/* create DMA address by stripping AS bits */
-#define TIOCX_DMA_ADDR(a) (uint64_t)((uint64_t)(a) & 0xffffcfffffffffUL)
+#define TIOCX_DMA_ADDR(a) (u64)((u64)(a) & 0xffffcfffffffffUL)
-#define TIOCX_TO_TIOCX_DMA_ADDR(a) (uint64_t)(((uint64_t)(a) & 0xfffffffff) | \
- ((((uint64_t)(a)) & 0xffffc000000000UL) <<2))
+#define TIOCX_TO_TIOCX_DMA_ADDR(a) (u64)(((u64)(a) & 0xfffffffff) | \
+ ((((u64)(a)) & 0xffffc000000000UL) <<2))
#define TIO_CE_ASIC_PARTNUM 0xce00
#define TIOCX_CORELET 3
@@ -63,10 +63,10 @@ extern int cx_device_unregister(struct cx_dev *);
extern int cx_device_register(nasid_t, int, int, struct hubdev_info *, int);
extern int cx_driver_unregister(struct cx_drv *);
extern int cx_driver_register(struct cx_drv *);
-extern uint64_t tiocx_dma_addr(uint64_t addr);
-extern uint64_t tiocx_swin_base(int nasid);
-extern void tiocx_mmr_store(int nasid, uint64_t offset, uint64_t value);
-extern uint64_t tiocx_mmr_load(int nasid, uint64_t offset);
+extern u64 tiocx_dma_addr(u64 addr);
+extern u64 tiocx_swin_base(int nasid);
+extern void tiocx_mmr_store(int nasid, u64 offset, u64 value);
+extern u64 tiocx_mmr_load(int nasid, u64 offset);
#endif // __KERNEL__
#endif // _ASM_IA64_SN_TIO_TIOCX__
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 49faf8f26430..203945ae034e 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -227,7 +227,9 @@ enum xpc_retval {
xpcOpenCloseError, /* 50: channel open/close protocol error */
- xpcUnknownReason /* 51: unknown reason -- must be last in list */
+ xpcDisconnected, /* 51: channel disconnected (closed) */
+
+ xpcUnknownReason /* 52: unknown reason -- must be last in list */
};
diff --git a/arch/ia64/sn/kernel/xpc.h b/include/asm-ia64/sn/xpc.h
index 5483a9f227d4..87e9cd588510 100644
--- a/arch/ia64/sn/kernel/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2006 Silicon Graphics, Inc. All Rights Reserved.
*/
@@ -11,8 +11,8 @@
* Cross Partition Communication (XPC) structures and macros.
*/
-#ifndef _IA64_SN_KERNEL_XPC_H
-#define _IA64_SN_KERNEL_XPC_H
+#ifndef _ASM_IA64_SN_XPC_H
+#define _ASM_IA64_SN_XPC_H
#include <linux/config.h>
@@ -663,6 +663,7 @@ extern struct xpc_registration xpc_registrations[];
extern struct device *xpc_part;
extern struct device *xpc_chan;
extern int xpc_disengage_request_timelimit;
+extern int xpc_disengage_request_timedout;
extern irqreturn_t xpc_notify_IRQ_handler(int, void *, struct pt_regs *);
extern void xpc_dropped_IPI_check(struct xpc_partition *);
extern void xpc_activate_partition(struct xpc_partition *);
@@ -707,7 +708,7 @@ extern void xpc_connected_callout(struct xpc_channel *);
extern void xpc_deliver_msg(struct xpc_channel *);
extern void xpc_disconnect_channel(const int, struct xpc_channel *,
enum xpc_retval, unsigned long *);
-extern void xpc_disconnecting_callout(struct xpc_channel *);
+extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval);
extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval);
extern void xpc_teardown_infrastructure(struct xpc_partition *);
@@ -1269,5 +1270,5 @@ xpc_check_for_channel_activity(struct xpc_partition *part)
}
-#endif /* _IA64_SN_KERNEL_XPC_H */
+#endif /* _ASM_IA64_SN_XPC_H */
diff --git a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
index 0c91a76c5ea3..9e83210dc312 100644
--- a/include/asm-ia64/spinlock.h
+++ b/include/asm-ia64/spinlock.h
@@ -34,7 +34,7 @@ __raw_spin_lock_flags (raw_spinlock_t *lock, unsigned long flags)
{
register volatile unsigned int *ptr asm ("r31") = &lock->lock;
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
# ifdef CONFIG_ITANIUM
/* don't use brl on Itanium... */
asm volatile ("{\n\t"
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 635235fa1e32..80c5a234e259 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -219,14 +219,14 @@ extern void ia64_load_extra (struct task_struct *task);
#define IA64_HAS_EXTRA_STATE(t) \
((t)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID) \
- || IS_IA32_PROCESS(ia64_task_regs(t)) || PERFMON_IS_SYSWIDE())
+ || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE())
#define __switch_to(prev,next,last) do { \
if (IA64_HAS_EXTRA_STATE(prev)) \
ia64_save_extra(prev); \
if (IA64_HAS_EXTRA_STATE(next)) \
ia64_load_extra(next); \
- ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \
+ ia64_psr(task_pt_regs(next))->dfh = !ia64_is_local_fpu_owner(next); \
(last) = ia64_switch_to((next)); \
} while (0)
@@ -238,8 +238,8 @@ extern void ia64_load_extra (struct task_struct *task);
* the latest fph state from another CPU. In other words: eager save, lazy restore.
*/
# define switch_to(prev,next,last) do { \
- if (ia64_psr(ia64_task_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) { \
- ia64_psr(ia64_task_regs(prev))->mfh = 0; \
+ if (ia64_psr(task_pt_regs(prev))->mfh && ia64_is_local_fpu_owner(prev)) { \
+ ia64_psr(task_pt_regs(prev))->mfh = 0; \
(prev)->thread.flags |= IA64_THREAD_FPH_VALID; \
__ia64_save_fpu((prev)->thread.fph); \
} \
@@ -279,6 +279,7 @@ extern void ia64_load_extra (struct task_struct *task);
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
void cpu_idle_wait(void);
+void sched_cacheflush(void);
#define arch_align_stack(x) (x)
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 171b2207bde4..1d6518fe1f02 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -57,11 +57,20 @@ struct thread_info {
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
#define alloc_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
#else
#define current_thread_info() ((struct thread_info *) 0)
#define alloc_thread_info(tsk) ((struct thread_info *) 0)
+#define task_thread_info(tsk) ((struct thread_info *) 0)
#endif
#define free_thread_info(ti) /* nothing */
+#define task_stack_page(tsk) ((void *)(tsk))
+
+#define __HAVE_THREAD_FUNCTIONS
+#define setup_thread_stack(p, org) \
+ *task_thread_info(p) = *task_thread_info(org); \
+ task_thread_info(p)->task = (p);
+#define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
#define alloc_task_struct() ((task_t *)__get_free_pages(GFP_KERNEL, KERNEL_STACK_SIZE_ORDER))
@@ -84,6 +93,7 @@ struct thread_info {
#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_DB_DISABLED 19 /* debug trap disabled for fsyscall */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
@@ -91,9 +101,10 @@ struct thread_info {
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
-#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED)
+#define _TIF_SIGDELAYED (1 << TIF_SIGDELAYED)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_MCA_INIT (1 << TIF_MCA_INIT)
+#define _TIF_DB_DISABLED (1 << TIF_DB_DISABLED)
/* "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 f7c330467e7e..d8aae4da3978 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -55,7 +55,6 @@ void build_cpu_to_node_map(void);
.max_interval = 4, \
.busy_factor = 64, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000000), \
.per_cpu_gain = 100, \
.cache_nice_tries = 2, \
.busy_idx = 2, \
@@ -81,7 +80,6 @@ void build_cpu_to_node_map(void);
.max_interval = 8*(min(num_online_cpus(), 32)), \
.busy_factor = 64, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000000), \
.cache_nice_tries = 2, \
.busy_idx = 3, \
.idle_idx = 2, \
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 6d96a67439be..962f9bd1bdff 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -265,16 +265,17 @@
#define __NR_keyctl 1273
#define __NR_ioprio_set 1274
#define __NR_ioprio_get 1275
-#define __NR_set_zone_reclaim 1276
+/* 1276 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_inotify_init 1277
#define __NR_inotify_add_watch 1278
#define __NR_inotify_rm_watch 1279
+#define __NR_migrate_pages 1280
#ifdef __KERNEL__
#include <linux/config.h>
-#define NR_syscalls 256 /* length of syscall table */
+#define NR_syscalls 270 /* length of syscall table */
#define __ARCH_WANT_SYS_RT_SIGACTION
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index e1dff9d6baad..b7f4d8aaeb46 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -52,7 +52,7 @@
or3 \reg, \reg, #low(\x)
.endm
-#if !defined(CONFIG_CHIP_M32102)
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
#define STI(reg) STI_M reg
.macro STI_M reg
setpsw #0x40 -> nop
@@ -64,7 +64,7 @@
clrpsw #0x40 -> nop
; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
.endm
-#else /* CONFIG_CHIP_M32102 */
+#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#define STI(reg) STI_M reg
.macro STI_M reg
mvfc \reg, psw
@@ -191,12 +191,12 @@
and \reg, sp
.endm
-#if !defined(CONFIG_CHIP_M32102)
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
.macro SWITCH_TO_KERNEL_STACK
; switch to kernel stack (spi)
clrpsw #0x80 -> nop
.endm
-#else /* CONFIG_CHIP_M32102 */
+#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
.macro SWITCH_TO_KERNEL_STACK
push r0 ; save r0 for working
mvfc r0, psw
@@ -218,7 +218,7 @@
.fillinsn
2:
.endm
-#endif /* CONFIG_CHIP_M32102 */
+#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m32r/atomic.h b/include/asm-m32r/atomic.h
index ef1fb8ea4726..3122fe106f05 100644
--- a/include/asm-m32r/atomic.h
+++ b/include/asm-m32r/atomic.h
@@ -243,6 +243,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
#define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0)
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -313,4 +314,5 @@ static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *addr)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* _ASM_M32R_ATOMIC_H */
diff --git a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
index e78443981349..abea2fdd8689 100644
--- a/include/asm-m32r/bitops.h
+++ b/include/asm-m32r/bitops.h
@@ -465,6 +465,7 @@ static __inline__ unsigned long __ffs(unsigned long word)
* fls: find last bit set.
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#ifdef __KERNEL__
diff --git a/include/asm-m32r/cache.h b/include/asm-m32r/cache.h
index 724820596980..9c2b2d9998bc 100644
--- a/include/asm-m32r/cache.h
+++ b/include/asm-m32r/cache.h
@@ -7,6 +7,4 @@
#define L1_CACHE_SHIFT 4
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 4
-
#endif /* _ASM_M32R_CACHE_H */
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index 46fc4c325108..e57427b6e249 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -7,7 +7,7 @@
extern void _flush_cache_all(void);
extern void _flush_cache_copyback_all(void);
-#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP)
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
diff --git a/include/asm-m32r/futex.h b/include/asm-m32r/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-m32r/futex.h
+++ b/include/asm-m32r/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-m32r/ioctl.h b/include/asm-m32r/ioctl.h
index 87d8f7db6af1..b279fe06dfe5 100644
--- a/include/asm-m32r/ioctl.h
+++ b/include/asm-m32r/ioctl.h
@@ -1,78 +1 @@
-#ifndef _ASM_M32R_IOCTL_H
-#define _ASM_M32R_IOCTL_H
-
-/* $Id$ */
-
-/* orig : i386 2.4.18 */
-
-/*
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASM_M32R_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-m32r/irq.h b/include/asm-m32r/irq.h
index 8ed77968ecb4..ca943954572a 100644
--- a/include/asm-m32r/irq.h
+++ b/include/asm-m32r/irq.h
@@ -65,6 +65,22 @@
#define NR_IRQS \
(OPSPUT_NUM_CPU_IRQ + OPSPUT_NUM_PLD_IRQ \
+ OPSPUT_NUM_LCD_PLD_IRQ + OPSPUT_NUM_LAN_PLD_IRQ)
+
+#elif defined(CONFIG_PLAT_M32104UT)
+/*
+ * IRQ definitions for M32104UT
+ * M32104 Chip: 64 interrupts
+ * ICU of M32104UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin
+ */
+#define M32104UT_NUM_CPU_IRQ (64)
+#define M32104UT_NUM_PLD_IRQ (32)
+#define M32104UT_IRQ_BASE 0
+#define M32104UT_CPU_IRQ_BASE M32104UT_IRQ_BASE
+#define M32104UT_PLD_IRQ_BASE (M32104UT_CPU_IRQ_BASE + M32104UT_NUM_CPU_IRQ)
+
+#define NR_IRQS \
+ (M32104UT_NUM_CPU_IRQ + M32104UT_NUM_PLD_IRQ)
+
#else
#define NR_IRQS 64
#endif
diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
index cb98101f4f6e..a1f0d1fe9eb8 100644
--- a/include/asm-m32r/m32102.h
+++ b/include/asm-m32r/m32102.h
@@ -11,7 +11,11 @@
/*======================================================================*
* Special Function Register
*======================================================================*/
+#if !defined(CONFIG_CHIP_M32104)
#define M32R_SFR_OFFSET (0x00E00000) /* 0x00E00000-0x00EFFFFF 1[MB] */
+#else
+#define M32R_SFR_OFFSET (0x00700000) /* 0x00700000-0x007FFFFF 1[MB] */
+#endif
/*
* Clock and Power Management registers.
@@ -100,7 +104,7 @@
#define M32R_MFT5RLD_PORTL (0x0C+M32R_MFT5_OFFSET) /* MFT4 reload */
#define M32R_MFT5CMPRLD_PORTL (0x10+M32R_MFT5_OFFSET) /* MFT4 compare reload */
-#ifdef CONFIG_CHIP_M32700
+#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32104)
#define M32R_MFTCR_MFT0MSK (1UL<<31) /* b0 */
#define M32R_MFTCR_MFT1MSK (1UL<<30) /* b1 */
#define M32R_MFTCR_MFT2MSK (1UL<<29) /* b2 */
@@ -113,7 +117,7 @@
#define M32R_MFTCR_MFT3EN (1UL<<20) /* b11 */
#define M32R_MFTCR_MFT4EN (1UL<<19) /* b12 */
#define M32R_MFTCR_MFT5EN (1UL<<18) /* b13 */
-#else /* not CONFIG_CHIP_M32700 */
+#else /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
#define M32R_MFTCR_MFT0MSK (1UL<<15) /* b16 */
#define M32R_MFTCR_MFT1MSK (1UL<<14) /* b17 */
#define M32R_MFTCR_MFT2MSK (1UL<<13) /* b18 */
@@ -126,7 +130,7 @@
#define M32R_MFTCR_MFT3EN (1UL<<4) /* b27 */
#define M32R_MFTCR_MFT4EN (1UL<<3) /* b28 */
#define M32R_MFTCR_MFT5EN (1UL<<2) /* b29 */
-#endif /* not CONFIG_CHIP_M32700 */
+#endif /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */
#define M32R_MFTMOD_CC_MASK (1UL<<15) /* b16 */
#define M32R_MFTMOD_TCCR (1UL<<13) /* b18 */
@@ -241,8 +245,24 @@
#define M32R_IRQ_MFT1 (17) /* MFT1 */
#define M32R_IRQ_MFT2 (18) /* MFT2 */
#define M32R_IRQ_MFT3 (19) /* MFT3 */
-#define M32R_IRQ_MFT4 (20) /* MFT4 */
-#define M32R_IRQ_MFT5 (21) /* MFT5 */
+#ifdef CONFIG_CHIP_M32104
+#define M32R_IRQ_MFTX0 (24) /* MFTX0 */
+#define M32R_IRQ_MFTX1 (25) /* MFTX1 */
+#define M32R_IRQ_DMA0 (32) /* DMA0 */
+#define M32R_IRQ_DMA1 (33) /* DMA1 */
+#define M32R_IRQ_DMA2 (34) /* DMA2 */
+#define M32R_IRQ_DMA3 (35) /* DMA3 */
+#define M32R_IRQ_SIO0_R (40) /* SIO0 send */
+#define M32R_IRQ_SIO0_S (41) /* SIO0 receive */
+#define M32R_IRQ_SIO1_R (42) /* SIO1 send */
+#define M32R_IRQ_SIO1_S (43) /* SIO1 receive */
+#define M32R_IRQ_SIO2_R (44) /* SIO2 send */
+#define M32R_IRQ_SIO2_S (45) /* SIO2 receive */
+#define M32R_IRQ_SIO3_R (46) /* SIO3 send */
+#define M32R_IRQ_SIO3_S (47) /* SIO3 receive */
+#define M32R_IRQ_ADC (56) /* ADC */
+#define M32R_IRQ_PC (57) /* PC */
+#else /* ! M32104 */
#define M32R_IRQ_DMA0 (32) /* DMA0 */
#define M32R_IRQ_DMA1 (33) /* DMA1 */
#define M32R_IRQ_SIO0_R (48) /* SIO0 send */
@@ -255,6 +275,7 @@
#define M32R_IRQ_SIO3_S (55) /* SIO3 receive */
#define M32R_IRQ_SIO4_R (56) /* SIO4 send */
#define M32R_IRQ_SIO4_S (57) /* SIO4 receive */
+#endif /* ! M32104 */
#ifdef CONFIG_SMP
#define M32R_IRQ_IPI0 (56)
@@ -281,15 +302,12 @@
#define M32R_FPGA_VERSION0_PORTL (0x30+M32R_FPGA_TOP)
#define M32R_FPGA_VERSION1_PORTL (0x34+M32R_FPGA_TOP)
+#endif /* CONFIG_SMP */
+
#ifndef __ASSEMBLY__
-/* For NETDEV WATCHDOG */
typedef struct {
unsigned long icucr; /* ICU Control Register */
} icu_data_t;
-
-extern icu_data_t icu_data[];
#endif
-#endif /* CONFIG_SMP */
-
#endif /* _M32102_H_ */
diff --git a/include/asm-m32r/m32104ut/m32104ut_pld.h b/include/asm-m32r/m32104ut/m32104ut_pld.h
new file mode 100644
index 000000000000..a4eac20553df
--- /dev/null
+++ b/include/asm-m32r/m32104ut/m32104ut_pld.h
@@ -0,0 +1,163 @@
+/*
+ * include/asm/m32104ut/m32104ut_pld.h
+ *
+ * Definitions for Programable Logic Device(PLD) on M32104UT board.
+ * Based on m32700ut_pld.h
+ *
+ * Copyright (c) 2002 Takeo Takahashi
+ * Copyright (c) 2005 Naoto Sugai
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _M32104UT_M32104UT_PLD_H
+#define _M32104UT_M32104UT_PLD_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_PLAT_M32104UT)
+#define PLD_PLAT_BASE 0x02c00000
+#else
+#error "no platform configuration"
+#endif
+
+#ifndef __ASSEMBLY__
+/*
+ * C functions use non-cache address.
+ */
+#define PLD_BASE (PLD_PLAT_BASE /* + NONCACHE_OFFSET */)
+#define __reg8 (volatile unsigned char *)
+#define __reg16 (volatile unsigned short *)
+#define __reg32 (volatile unsigned int *)
+#else
+#define PLD_BASE (PLD_PLAT_BASE + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define PLD_CFRSTCR __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR __reg16(PLD_BASE + 0x0006)
+
+/* MMC */
+#define PLD_MMCCR __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA __reg16(PLD_BASE + 0x7006)
+
+/* ICU
+ * ICUISTS: status register
+ * ICUIREQ0: request register
+ * ICUIREQ1: request register
+ * ICUCR3: control register for CFIREQ# interrupt
+ * ICUCR4: control register for CFC Card insert interrupt
+ * ICUCR5: control register for CFC Card eject interrupt
+ * ICUCR6: control register for external interrupt
+ * ICUCR11: control register for MMC Card insert/eject interrupt
+ * ICUCR13: control register for SC error interrupt
+ * ICUCR14: control register for SC receive interrupt
+ * ICUCR15: control register for SC send interrupt
+ */
+
+#define PLD_IRQ_INT0 (M32104UT_PLD_IRQ_BASE + 0) /* None */
+#define PLD_IRQ_CFIREQ (M32104UT_PLD_IRQ_BASE + 3) /* CF IREQ */
+#define PLD_IRQ_CFC_INSERT (M32104UT_PLD_IRQ_BASE + 4) /* CF Insert */
+#define PLD_IRQ_CFC_EJECT (M32104UT_PLD_IRQ_BASE + 5) /* CF Eject */
+#define PLD_IRQ_EXINT (M32104UT_PLD_IRQ_BASE + 6) /* EXINT */
+#define PLD_IRQ_MMCCARD (M32104UT_PLD_IRQ_BASE + 11) /* MMC Insert/Eject */
+#define PLD_IRQ_SC_ERROR (M32104UT_PLD_IRQ_BASE + 13) /* SC error */
+#define PLD_IRQ_SC_RCV (M32104UT_PLD_IRQ_BASE + 14) /* SC receive */
+#define PLD_IRQ_SC_SND (M32104UT_PLD_IRQ_BASE + 15) /* SC send */
+
+#define PLD_ICUISTS __reg16(PLD_BASE + 0x8002)
+#define PLD_ICUISTS_VECB_MASK (0xf000)
+#define PLD_ICUISTS_VECB(x) ((x) & PLD_ICUISTS_VECB_MASK)
+#define PLD_ICUISTS_ISN_MASK (0x07c0)
+#define PLD_ICUISTS_ISN(x) ((x) & PLD_ICUISTS_ISN_MASK)
+#define PLD_ICUCR3 __reg16(PLD_BASE + 0x8104)
+#define PLD_ICUCR4 __reg16(PLD_BASE + 0x8106)
+#define PLD_ICUCR5 __reg16(PLD_BASE + 0x8108)
+#define PLD_ICUCR6 __reg16(PLD_BASE + 0x810a)
+#define PLD_ICUCR11 __reg16(PLD_BASE + 0x8114)
+#define PLD_ICUCR13 __reg16(PLD_BASE + 0x8118)
+#define PLD_ICUCR14 __reg16(PLD_BASE + 0x811a)
+#define PLD_ICUCR15 __reg16(PLD_BASE + 0x811c)
+#define PLD_ICUCR_IEN (0x1000)
+#define PLD_ICUCR_IREQ (0x0100)
+#define PLD_ICUCR_ISMOD00 (0x0000) /* Low edge */
+#define PLD_ICUCR_ISMOD01 (0x0010) /* Low level */
+#define PLD_ICUCR_ISMOD02 (0x0020) /* High edge */
+#define PLD_ICUCR_ISMOD03 (0x0030) /* High level */
+#define PLD_ICUCR_ILEVEL0 (0x0000)
+#define PLD_ICUCR_ILEVEL1 (0x0001)
+#define PLD_ICUCR_ILEVEL2 (0x0002)
+#define PLD_ICUCR_ILEVEL3 (0x0003)
+#define PLD_ICUCR_ILEVEL4 (0x0004)
+#define PLD_ICUCR_ILEVEL5 (0x0005)
+#define PLD_ICUCR_ILEVEL6 (0x0006)
+#define PLD_ICUCR_ILEVEL7 (0x0007)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR __reg16(PLD_BASE + 0x14000)
+#define PLD_CPCR_CDP 0x0001
+
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON 0x001
+#define PLD_IOLED_1_OFF 0x000
+#define PLD_IOLED_2_ON 0x002
+#define PLD_IOLED_2_OFF 0x000
+
+/* DIP Switch
+ * 0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ * 1: -
+ * 2: -
+ * 3: -
+ */
+#define PLD_IOSWSTS __reg16(PLD_BASE + 0x14004)
+#define PLD_IOSWSTS_IOSW2 0x0200
+#define PLD_IOSWSTS_IOSW1 0x0100
+#define PLD_IOSWSTS_IOWP0 0x0001
+
+/* CRC */
+#define PLD_CRC7DATA __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA __reg16(PLD_BASE + 0x1800a)
+
+/* RTC */
+#define PLD_RTCCR __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT __reg16(PLD_BASE + 0x1c008)
+
+/* SIM Card */
+#define PLD_SCCR __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB __reg16(PLD_BASE + 0x3800e)
+
+#endif /* _M32104UT_M32104UT_PLD_H */
diff --git a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
index ec142be00862..b133ca61acf1 100644
--- a/include/asm-m32r/m32r.h
+++ b/include/asm-m32r/m32r.h
@@ -14,7 +14,7 @@
#include <asm/m32r_mp_fpga.h>
#elif defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
- || defined(CONFIG_CHIP_OPSP)
+ || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
#include <asm/m32102.h>
#endif
@@ -43,6 +43,10 @@
#include <asm/m32700ut/m32700ut_pld.h>
#endif
+#if defined(CONFIG_PLAT_M32104UT)
+#include <asm/m32104ut/m32104ut_pld.h>
+#endif /* CONFIG_PLAT_M32104 */
+
/*
* M32R Register
*/
@@ -122,7 +126,7 @@
#include <asm/page.h>
#ifdef CONFIG_MMU
-#define NONCACHE_OFFSET __PAGE_OFFSET+0x20000000
+#define NONCACHE_OFFSET (__PAGE_OFFSET + 0x20000000)
#else
#define NONCACHE_OFFSET __PAGE_OFFSET
#endif /* CONFIG_MMU */
diff --git a/include/asm-m32r/mman.h b/include/asm-m32r/mman.h
index 011f6d9ec5cc..12e29747bc84 100644
--- a/include/asm-m32r/mman.h
+++ b/include/asm-m32r/mman.h
@@ -37,6 +37,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-m32r/mutex.h b/include/asm-m32r/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-m32r/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 55cd7ecfde43..0d058b2d844e 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -163,6 +163,9 @@ extern void show_regs(struct pt_regs *);
extern void withdraw_debug_trap(struct pt_regs *regs);
+#define task_pt_regs(task) \
+ ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1)
+
#endif /* __KERNEL */
#endif /* _ASM_M32R_PTRACE_H */
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index 5eee832b73a0..06c12a037cba 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -68,13 +68,23 @@
last = __last; \
} while(0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
/* Interrupt Control */
-#if !defined(CONFIG_CHIP_M32102)
+#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104)
#define local_irq_enable() \
__asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory")
#define local_irq_disable() \
__asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory")
-#else /* CONFIG_CHIP_M32102 */
+#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
static inline void local_irq_enable(void)
{
unsigned long tmpreg;
@@ -96,7 +106,7 @@ static inline void local_irq_disable(void)
"mvtc %0, psw \n\t"
: "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory");
}
-#endif /* CONFIG_CHIP_M32102 */
+#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#define local_save_flags(x) \
__asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */)
@@ -105,13 +115,13 @@ static inline void local_irq_disable(void)
__asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \
: "r" (x) : "cbit", "memory")
-#if !defined(CONFIG_CHIP_M32102)
+#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
#define local_irq_save(x) \
__asm__ __volatile__( \
"mvfc %0, psw; \n\t" \
"clrpsw #0x40 -> nop; \n\t" \
: "=r" (x) : /* no input */ : "memory")
-#else /* CONFIG_CHIP_M32102 */
+#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#define local_irq_save(x) \
({ \
unsigned long tmpreg; \
@@ -124,7 +134,7 @@ static inline void local_irq_disable(void)
: "=r" (x), "=&r" (tmpreg) \
: : "cbit", "memory"); \
})
-#endif /* CONFIG_CHIP_M32102 */
+#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#define irqs_disabled() \
({ \
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index 0f589363f619..22aff3222d22 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -110,8 +110,6 @@ static inline struct thread_info *current_thread_info(void)
#endif
#define free_thread_info(info) kfree(info)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#define TI_FLAG_FAULT_CODE_SHIFT 28
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index ac399e1f7bc0..39be87ca2a5a 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -319,7 +319,7 @@ type name(void) \
register long __scno __asm__ ("r7") = __NR_##name; \
register long __res __asm__("r0"); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno) \
: "memory"); \
@@ -332,7 +332,7 @@ type name(type1 arg1) \
register long __scno __asm__ ("r7") = __NR_##name; \
register long __res __asm__ ("r0") = (long)(arg1); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno), "0" (__res) \
: "memory"); \
@@ -346,7 +346,7 @@ register long __scno __asm__ ("r7") = __NR_##name; \
register long __arg2 __asm__ ("r1") = (long)(arg2); \
register long __res __asm__ ("r0") = (long)(arg1); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno), "0" (__res), "r" (__arg2) \
: "memory"); \
@@ -361,7 +361,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \
register long __arg2 __asm__ ("r1") = (long)(arg2); \
register long __res __asm__ ("r0") = (long)(arg1); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno), "0" (__res), "r" (__arg2), \
"r" (__arg3) \
@@ -378,7 +378,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \
register long __arg2 __asm__ ("r1") = (long)(arg2); \
register long __res __asm__ ("r0") = (long)(arg1); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno), "0" (__res), "r" (__arg2), \
"r" (__arg3), "r" (__arg4) \
@@ -397,7 +397,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \
register long __arg2 __asm__ ("r1") = (long)(arg2); \
register long __res __asm__ ("r0") = (long)(arg1); \
__asm__ __volatile__ (\
- "trap #" SYSCALL_VECTOR \
+ "trap #" SYSCALL_VECTOR "|| nop"\
: "=r" (__res) \
: "r" (__scno), "0" (__res), "r" (__arg2), \
"r" (__arg3), "r" (__arg4), "r" (__arg5) \
diff --git a/include/asm-m68k/amigahw.h b/include/asm-m68k/amigahw.h
index 3ae5d8d55ba9..a16fe4e5a28a 100644
--- a/include/asm-m68k/amigahw.h
+++ b/include/asm-m68k/amigahw.h
@@ -274,7 +274,7 @@ struct CIA {
#define ZTWO_VADDR(x) (((unsigned long)(x))+zTwoBase)
#define CUSTOM_PHYSADDR (0xdff000)
-#define custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR)))
+#define amiga_custom ((*(volatile struct CUSTOM *)(zTwoBase+CUSTOM_PHYSADDR)))
#define CIAA_PHYSADDR (0xbfe001)
#define CIAB_PHYSADDR (0xbfd000)
@@ -294,12 +294,12 @@ static inline void amifb_video_off(void)
{
if (amiga_chipset == CS_ECS || amiga_chipset == CS_AGA) {
/* program Denise/Lisa for a higher maximum play rate */
- custom.htotal = 113; /* 31 kHz */
- custom.vtotal = 223; /* 70 Hz */
- custom.beamcon0 = 0x4390; /* HARDDIS, VAR{BEAM,VSY,HSY,CSY}EN */
+ amiga_custom.htotal = 113; /* 31 kHz */
+ amiga_custom.vtotal = 223; /* 70 Hz */
+ amiga_custom.beamcon0 = 0x4390; /* HARDDIS, VAR{BEAM,VSY,HSY,CSY}EN */
/* suspend the monitor */
- custom.hsstrt = custom.hsstop = 116;
- custom.vsstrt = custom.vsstop = 226;
+ amiga_custom.hsstrt = amiga_custom.hsstop = 116;
+ amiga_custom.vsstrt = amiga_custom.vsstop = 226;
amiga_audio_min_period = 57;
}
}
diff --git a/include/asm-m68k/amigaints.h b/include/asm-m68k/amigaints.h
index 2aff4cfbf7b3..aa968d014bb6 100644
--- a/include/asm-m68k/amigaints.h
+++ b/include/asm-m68k/amigaints.h
@@ -109,8 +109,6 @@
extern void amiga_do_irq(int irq, struct pt_regs *fp);
extern void amiga_do_irq_list(int irq, struct pt_regs *fp);
-extern unsigned short amiga_intena_vals[];
-
/* CIA interrupt control register bits */
#define CIA_ICR_TA 0x01
diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h
index e3c962eeabf3..a4a84d5c65d5 100644
--- a/include/asm-m68k/atomic.h
+++ b/include/asm-m68k/atomic.h
@@ -140,6 +140,7 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
}
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -157,4 +158,5 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __ARCH_M68K_ATOMIC __ */
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
index b1bcf7c66516..13f4c0048463 100644
--- a/include/asm-m68k/bitops.h
+++ b/include/asm-m68k/bitops.h
@@ -310,6 +310,7 @@ static inline int fls(int x)
return 32 - cnt;
}
+#define fls64(x) generic_fls64(x)
/*
* Every architecture must define this function. It's the fastest
diff --git a/include/asm-m68k/cache.h b/include/asm-m68k/cache.h
index 6161fd3d8600..fed3fd30de7e 100644
--- a/include/asm-m68k/cache.h
+++ b/include/asm-m68k/cache.h
@@ -8,6 +8,4 @@
#define L1_CACHE_SHIFT 4
#define L1_CACHE_BYTES (1<< L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 4 /* largest L1 which this arch supports */
-
#endif
diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h
index 78860c20db01..17280ef719f5 100644
--- a/include/asm-m68k/checksum.h
+++ b/include/asm-m68k/checksum.h
@@ -25,7 +25,7 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
* better 64-bit) boundary
*/
-extern unsigned int csum_partial_copy_from_user(const unsigned char *src,
+extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
unsigned char *dst,
int len, int sum,
int *csum_err);
diff --git a/include/asm-m68k/dsp56k.h b/include/asm-m68k/dsp56k.h
index ab3dd33e23a1..2d8c0c9f794b 100644
--- a/include/asm-m68k/dsp56k.h
+++ b/include/asm-m68k/dsp56k.h
@@ -13,7 +13,7 @@
/* Used for uploading DSP binary code */
struct dsp56k_upload {
int len;
- char *bin;
+ char __user *bin;
};
/* For the DSP host flags */
diff --git a/include/asm-m68k/floppy.h b/include/asm-m68k/floppy.h
index c6e708dd9f62..63a05ed95c17 100644
--- a/include/asm-m68k/floppy.h
+++ b/include/asm-m68k/floppy.h
@@ -46,7 +46,7 @@ asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id,
static int virtual_dma_count=0;
static int virtual_dma_residue=0;
-static char *virtual_dma_addr=0;
+static char *virtual_dma_addr=NULL;
static int virtual_dma_mode=0;
static int doing_pdma=0;
diff --git a/include/asm-m68k/futex.h b/include/asm-m68k/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-m68k/futex.h
+++ b/include/asm-m68k/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-m68k/hardirq.h b/include/asm-m68k/hardirq.h
index 728318bf7f0e..5e1c5826c83d 100644
--- a/include/asm-m68k/hardirq.h
+++ b/include/asm-m68k/hardirq.h
@@ -14,13 +14,4 @@ typedef struct {
#define HARDIRQ_BITS 8
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
-
#endif
diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h
index 6bb8b0d8f99d..dcfaa352d34c 100644
--- a/include/asm-m68k/io.h
+++ b/include/asm-m68k/io.h
@@ -24,6 +24,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
+#include <linux/compiler.h>
#include <asm/raw_io.h>
#include <asm/virtconvert.h>
@@ -120,68 +121,68 @@ extern int isa_sex;
* be compiled in so the case statement will be optimised away
*/
-static inline u8 *isa_itb(unsigned long addr)
+static inline u8 __iomem *isa_itb(unsigned long addr)
{
switch(ISA_TYPE)
{
#ifdef CONFIG_Q40
- case Q40_ISA: return (u8 *)Q40_ISA_IO_B(addr);
+ case Q40_ISA: return (u8 __iomem *)Q40_ISA_IO_B(addr);
#endif
#ifdef CONFIG_GG2
- case GG2_ISA: return (u8 *)GG2_ISA_IO_B(addr);
+ case GG2_ISA: return (u8 __iomem *)GG2_ISA_IO_B(addr);
#endif
#ifdef CONFIG_AMIGA_PCMCIA
- case AG_ISA: return (u8 *)AG_ISA_IO_B(addr);
+ case AG_ISA: return (u8 __iomem *)AG_ISA_IO_B(addr);
#endif
- default: return 0; /* avoid warnings, just in case */
+ default: return NULL; /* avoid warnings, just in case */
}
}
-static inline u16 *isa_itw(unsigned long addr)
+static inline u16 __iomem *isa_itw(unsigned long addr)
{
switch(ISA_TYPE)
{
#ifdef CONFIG_Q40
- case Q40_ISA: return (u16 *)Q40_ISA_IO_W(addr);
+ case Q40_ISA: return (u16 __iomem *)Q40_ISA_IO_W(addr);
#endif
#ifdef CONFIG_GG2
- case GG2_ISA: return (u16 *)GG2_ISA_IO_W(addr);
+ case GG2_ISA: return (u16 __iomem *)GG2_ISA_IO_W(addr);
#endif
#ifdef CONFIG_AMIGA_PCMCIA
- case AG_ISA: return (u16 *)AG_ISA_IO_W(addr);
+ case AG_ISA: return (u16 __iomem *)AG_ISA_IO_W(addr);
#endif
- default: return 0; /* avoid warnings, just in case */
+ default: return NULL; /* avoid warnings, just in case */
}
}
-static inline u8 *isa_mtb(unsigned long addr)
+static inline u8 __iomem *isa_mtb(unsigned long addr)
{
switch(ISA_TYPE)
{
#ifdef CONFIG_Q40
- case Q40_ISA: return (u8 *)Q40_ISA_MEM_B(addr);
+ case Q40_ISA: return (u8 __iomem *)Q40_ISA_MEM_B(addr);
#endif
#ifdef CONFIG_GG2
- case GG2_ISA: return (u8 *)GG2_ISA_MEM_B(addr);
+ case GG2_ISA: return (u8 __iomem *)GG2_ISA_MEM_B(addr);
#endif
#ifdef CONFIG_AMIGA_PCMCIA
- case AG_ISA: return (u8 *)addr;
+ case AG_ISA: return (u8 __iomem *)addr;
#endif
- default: return 0; /* avoid warnings, just in case */
+ default: return NULL; /* avoid warnings, just in case */
}
}
-static inline u16 *isa_mtw(unsigned long addr)
+static inline u16 __iomem *isa_mtw(unsigned long addr)
{
switch(ISA_TYPE)
{
#ifdef CONFIG_Q40
- case Q40_ISA: return (u16 *)Q40_ISA_MEM_W(addr);
+ case Q40_ISA: return (u16 __iomem *)Q40_ISA_MEM_W(addr);
#endif
#ifdef CONFIG_GG2
- case GG2_ISA: return (u16 *)GG2_ISA_MEM_W(addr);
+ case GG2_ISA: return (u16 __iomem *)GG2_ISA_MEM_W(addr);
#endif
#ifdef CONFIG_AMIGA_PCMCIA
- case AG_ISA: return (u16 *)addr;
+ case AG_ISA: return (u16 __iomem *)addr;
#endif
- default: return 0; /* avoid warnings, just in case */
+ default: return NULL; /* avoid warnings, just in case */
}
}
@@ -326,20 +327,20 @@ static inline void isa_delay(void)
#define mmiowb()
-static inline void *ioremap(unsigned long physaddr, unsigned long size)
+static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-static inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
+static inline void __iomem *ioremap_nocache(unsigned long physaddr, unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-static inline void *ioremap_writethrough(unsigned long physaddr,
+static inline void __iomem *ioremap_writethrough(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-static inline void *ioremap_fullcache(unsigned long physaddr,
+static inline void __iomem *ioremap_fullcache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
diff --git a/include/asm-m68k/ioctl.h b/include/asm-m68k/ioctl.h
index fd68914ab292..b279fe06dfe5 100644
--- a/include/asm-m68k/ioctl.h
+++ b/include/asm-m68k/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.3 1997/04/16 15:10:07 jes Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _M68K_IOCTL_H
-#define _M68K_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _M68K_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h
index 1f569905cb74..325c86f8512d 100644
--- a/include/asm-m68k/irq.h
+++ b/include/asm-m68k/irq.h
@@ -23,6 +23,15 @@
#endif
/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+/*
* Interrupt source definitions
* General interrupt sources are the level 1-7.
* Adding an interrupt service routine for one of these sources
@@ -70,8 +79,6 @@ static __inline__ int irq_canonicalize(int irq)
extern void (*enable_irq)(unsigned int);
extern void (*disable_irq)(unsigned int);
-
-#define disable_irq_nosync disable_irq
#define enable_irq_nosync enable_irq
struct pt_regs;
diff --git a/include/asm-m68k/machdep.h b/include/asm-m68k/machdep.h
index a0dd5c47002c..7d3fee342369 100644
--- a/include/asm-m68k/machdep.h
+++ b/include/asm-m68k/machdep.h
@@ -34,7 +34,6 @@ extern void (*mach_power_off)( void );
extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
extern void (*mach_hd_setup)(char *, int *);
extern long mach_max_dma_address;
-extern void (*mach_floppy_setup)(char *, int *);
extern void (*mach_heartbeat) (int);
extern void (*mach_l2_flush) (int);
extern void (*mach_beep) (unsigned int, unsigned int);
diff --git a/include/asm-m68k/mman.h b/include/asm-m68k/mman.h
index f831c4eeae6e..ea262ab88b3b 100644
--- a/include/asm-m68k/mman.h
+++ b/include/asm-m68k/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-m68k/mutex.h b/include/asm-m68k/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-m68k/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-m68k/raw_io.h b/include/asm-m68k/raw_io.h
index 041f0a87b25d..5439bcaa57c6 100644
--- a/include/asm-m68k/raw_io.h
+++ b/include/asm-m68k/raw_io.h
@@ -19,9 +19,9 @@
#define IOMAP_NOCACHE_NONSER 2
#define IOMAP_WRITETHROUGH 3
-extern void iounmap(void *addr);
+extern void iounmap(void __iomem *addr);
-extern void *__ioremap(unsigned long physaddr, unsigned long size,
+extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size,
int cacheflag);
extern void __iounmap(void *addr, unsigned long size);
@@ -30,21 +30,21 @@ extern void __iounmap(void *addr, unsigned long size);
* two accesses to memory, which may be undesirable for some devices.
*/
#define in_8(addr) \
- ({ u8 __v = (*(volatile u8 *) (addr)); __v; })
+ ({ u8 __v = (*(__force volatile u8 *) (addr)); __v; })
#define in_be16(addr) \
- ({ u16 __v = (*(volatile u16 *) (addr)); __v; })
+ ({ u16 __v = (*(__force volatile u16 *) (addr)); __v; })
#define in_be32(addr) \
- ({ u32 __v = (*(volatile u32 *) (addr)); __v; })
+ ({ u32 __v = (*(__force volatile u32 *) (addr)); __v; })
#define in_le16(addr) \
- ({ u16 __v = le16_to_cpu(*(volatile u16 *) (addr)); __v; })
+ ({ u16 __v = le16_to_cpu(*(__force volatile u16 *) (addr)); __v; })
#define in_le32(addr) \
- ({ u32 __v = le32_to_cpu(*(volatile u32 *) (addr)); __v; })
+ ({ u32 __v = le32_to_cpu(*(__force volatile u32 *) (addr)); __v; })
-#define out_8(addr,b) (void)((*(volatile u8 *) (addr)) = (b))
-#define out_be16(addr,w) (void)((*(volatile u16 *) (addr)) = (w))
-#define out_be32(addr,l) (void)((*(volatile u32 *) (addr)) = (l))
-#define out_le16(addr,w) (void)((*(volatile u16 *) (addr)) = cpu_to_le16(w))
-#define out_le32(addr,l) (void)((*(volatile u32 *) (addr)) = cpu_to_le32(l))
+#define out_8(addr,b) (void)((*(__force volatile u8 *) (addr)) = (b))
+#define out_be16(addr,w) (void)((*(__force volatile u16 *) (addr)) = (w))
+#define out_be32(addr,l) (void)((*(__force volatile u32 *) (addr)) = (l))
+#define out_le16(addr,w) (void)((*(__force volatile u16 *) (addr)) = cpu_to_le16(w))
+#define out_le32(addr,l) (void)((*(__force volatile u32 *) (addr)) = cpu_to_le32(l))
#define raw_inb in_8
#define raw_inw in_be16
@@ -54,7 +54,7 @@ extern void __iounmap(void *addr, unsigned long size);
#define raw_outw(val,port) out_be16((port),(val))
#define raw_outl(val,port) out_be32((port),(val))
-static inline void raw_insb(volatile u8 *port, u8 *buf, unsigned int len)
+static inline void raw_insb(volatile u8 __iomem *port, u8 *buf, unsigned int len)
{
unsigned int i;
@@ -62,7 +62,7 @@ static inline void raw_insb(volatile u8 *port, u8 *buf, unsigned int len)
*buf++ = in_8(port);
}
-static inline void raw_outsb(volatile u8 *port, const u8 *buf,
+static inline void raw_outsb(volatile u8 __iomem *port, const u8 *buf,
unsigned int len)
{
unsigned int i;
@@ -71,7 +71,7 @@ static inline void raw_outsb(volatile u8 *port, const u8 *buf,
out_8(port, *buf++);
}
-static inline void raw_insw(volatile u16 *port, u16 *buf, unsigned int nr)
+static inline void raw_insw(volatile u16 __iomem *port, u16 *buf, unsigned int nr)
{
unsigned int tmp;
@@ -110,7 +110,7 @@ static inline void raw_insw(volatile u16 *port, u16 *buf, unsigned int nr)
}
}
-static inline void raw_outsw(volatile u16 *port, const u16 *buf,
+static inline void raw_outsw(volatile u16 __iomem *port, const u16 *buf,
unsigned int nr)
{
unsigned int tmp;
@@ -150,7 +150,7 @@ static inline void raw_outsw(volatile u16 *port, const u16 *buf,
}
}
-static inline void raw_insl(volatile u32 *port, u32 *buf, unsigned int nr)
+static inline void raw_insl(volatile u32 __iomem *port, u32 *buf, unsigned int nr)
{
unsigned int tmp;
@@ -189,7 +189,7 @@ static inline void raw_insl(volatile u32 *port, u32 *buf, unsigned int nr)
}
}
-static inline void raw_outsl(volatile u32 *port, const u32 *buf,
+static inline void raw_outsl(volatile u32 __iomem *port, const u32 *buf,
unsigned int nr)
{
unsigned int tmp;
@@ -230,7 +230,7 @@ static inline void raw_outsl(volatile u32 *port, const u32 *buf,
}
-static inline void raw_insw_swapw(volatile u16 *port, u16 *buf,
+static inline void raw_insw_swapw(volatile u16 __iomem *port, u16 *buf,
unsigned int nr)
{
if ((nr) % 8)
@@ -283,7 +283,7 @@ static inline void raw_insw_swapw(volatile u16 *port, u16 *buf,
: "d0", "a0", "a1", "d6");
}
-static inline void raw_outsw_swapw(volatile u16 *port, const u16 *buf,
+static inline void raw_outsw_swapw(volatile u16 __iomem *port, const u16 *buf,
unsigned int nr)
{
if ((nr) % 8)
diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h
index a0cdf9082372..b7b7ea20caab 100644
--- a/include/asm-m68k/signal.h
+++ b/include/asm-m68k/signal.h
@@ -144,7 +144,7 @@ struct sigaction {
#endif /* __KERNEL__ */
typedef struct sigaltstack {
- void *ss_sp;
+ void __user *ss_sp;
int ss_flags;
size_t ss_size;
} stack_t;
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index e974bb072047..5156a28a18d8 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -211,7 +211,7 @@ static inline unsigned long pte_to_pgoff(pte_t pte)
return pte.pte & SUN3_PAGE_PGNUM_MASK;
}
-static inline pte_t pgoff_to_pte(inline unsigned off)
+static inline pte_t pgoff_to_pte(unsigned off)
{
pte_t pte = { off + SUN3_PAGE_ACCESSED };
return pte;
diff --git a/include/asm-m68k/sun3ints.h b/include/asm-m68k/sun3ints.h
index fd838eb14213..bd038fccb64b 100644
--- a/include/asm-m68k/sun3ints.h
+++ b/include/asm-m68k/sun3ints.h
@@ -31,7 +31,6 @@ int sun3_request_irq(unsigned int irq,
);
extern void sun3_init_IRQ (void);
extern irqreturn_t (*sun3_default_handler[]) (int, void *, struct pt_regs *);
-extern irqreturn_t (*sun3_inthandler[]) (int, void *, struct pt_regs *);
extern void sun3_free_irq (unsigned int irq, void *dev_id);
extern void sun3_enable_interrupts (void);
extern void sun3_disable_interrupts (void);
diff --git a/include/asm-m68k/sun3xflop.h b/include/asm-m68k/sun3xflop.h
index fda1eccf10aa..98a9f79dab29 100644
--- a/include/asm-m68k/sun3xflop.h
+++ b/include/asm-m68k/sun3xflop.h
@@ -208,7 +208,7 @@ static int sun3xflop_request_irq(void)
if(!once) {
once = 1;
- error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", 0);
+ error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", NULL);
return ((error == 0) ? 0 : -1);
} else return 0;
}
@@ -238,7 +238,7 @@ static int sun3xflop_init(void)
*sun3x_fdc.fcr_r = 0;
/* Success... */
- floppy_set_flags(0, 1, FD_BROKEN_DCL); // I don't know how to detect this.
+ floppy_set_flags(NULL, 1, FD_BROKEN_DCL); // I don't know how to detect this.
allowed_drive_mask = 0x01;
return (int) SUN3X_FDC;
}
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 9532ca3c45cb..c4d622a57dfb 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -37,6 +37,7 @@ struct thread_info {
#define init_stack (init_thread_union.stack)
#define task_thread_info(tsk) (&(tsk)->thread.info)
+#define task_stack_page(tsk) ((void *)(tsk)->thread_info)
#define current_thread_info() task_thread_info(current)
#define __HAVE_THREAD_FUNCTIONS
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index f5cedf19cf68..2ffd87b0a769 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -42,6 +42,7 @@ struct exception_table_entry
({ \
int __pu_err; \
typeof(*(ptr)) __pu_val = (x); \
+ __chk_user_ptr(ptr); \
switch (sizeof (*(ptr))) { \
case 1: \
__put_user_asm(__pu_err, __pu_val, ptr, b); \
@@ -91,6 +92,7 @@ __asm__ __volatile__ \
({ \
int __gu_err; \
typeof(*(ptr)) __gu_val; \
+ __chk_user_ptr(ptr); \
switch (sizeof(*(ptr))) { \
case 1: \
__get_user_asm(__gu_err, __gu_val, ptr, b, "=d"); \
@@ -105,7 +107,7 @@ __asm__ __volatile__ \
__gu_err = __constant_copy_from_user(&__gu_val, ptr, 8); \
break; \
default: \
- __gu_val = 0; \
+ __gu_val = (typeof(*(ptr)))0; \
__gu_err = __get_user_bad(); \
break; \
} \
@@ -134,7 +136,7 @@ __asm__ __volatile__ \
: "m"(*(ptr)), "i" (-EFAULT), "0"(0))
static inline unsigned long
-__generic_copy_from_user(void *to, const void *from, unsigned long n)
+__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long tmp;
__asm__ __volatile__
@@ -189,7 +191,7 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
}
static inline unsigned long
-__generic_copy_to_user(void *to, const void *from, unsigned long n)
+__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{
unsigned long tmp;
__asm__ __volatile__
@@ -264,7 +266,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n)
: "d0", "memory")
static inline unsigned long
-__constant_copy_from_user(void *to, const void *from, unsigned long n)
+__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
{
switch (n) {
case 0:
@@ -520,7 +522,7 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n)
#define __copy_from_user_inatomic __copy_from_user
static inline unsigned long
-__constant_copy_to_user(void *to, const void *from, unsigned long n)
+__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
{
switch (n) {
case 0:
@@ -766,7 +768,7 @@ __constant_copy_to_user(void *to, const void *from, unsigned long n)
*/
static inline long
-strncpy_from_user(char *dst, const char *src, long count)
+strncpy_from_user(char *dst, const char __user *src, long count)
{
long res;
if (count == 0) return count;
@@ -799,11 +801,11 @@ strncpy_from_user(char *dst, const char *src, long count)
*
* Return 0 on exception, a value greater than N if too long
*/
-static inline long strnlen_user(const char *src, long n)
+static inline long strnlen_user(const char __user *src, long n)
{
long res;
- res = -(long)src;
+ res = -(unsigned long)src;
__asm__ __volatile__
("1:\n"
" tstl %2\n"
@@ -842,7 +844,7 @@ static inline long strnlen_user(const char *src, long n)
*/
static inline unsigned long
-clear_user(void *to, unsigned long n)
+clear_user(void __user *to, unsigned long n)
{
__asm__ __volatile__
(" tstl %1\n"
diff --git a/include/asm-m68k/zorro.h b/include/asm-m68k/zorro.h
index cf816588bedb..5ce97c22b582 100644
--- a/include/asm-m68k/zorro.h
+++ b/include/asm-m68k/zorro.h
@@ -15,24 +15,24 @@
#define z_memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
#define z_memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
-static inline void *z_remap_nocache_ser(unsigned long physaddr,
+static inline void __iomem *z_remap_nocache_ser(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-static inline void *z_remap_nocache_nonser(unsigned long physaddr,
+static inline void __iomem *z_remap_nocache_nonser(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_NONSER);
}
-static inline void *z_remap_writethrough(unsigned long physaddr,
+static inline void __iomem *z_remap_writethrough(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-static inline void *z_remap_fullcache(unsigned long physaddr,
+static inline void __iomem *z_remap_fullcache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
diff --git a/include/asm-m68knommu/atomic.h b/include/asm-m68knommu/atomic.h
index 3c1cc153c415..6c4e4b63e454 100644
--- a/include/asm-m68knommu/atomic.h
+++ b/include/asm-m68knommu/atomic.h
@@ -129,6 +129,7 @@ static inline int atomic_sub_return(int i, atomic_t * v)
}
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -143,4 +144,5 @@ static inline int atomic_sub_return(int i, atomic_t * v)
#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))
+#include <asm-generic/atomic.h>
#endif /* __ARCH_M68KNOMMU_ATOMIC __ */
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index c42f88a9b9f9..25d8a3cfef90 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -290,7 +290,7 @@ static __inline__ int find_next_zero_bit (const void * addr, int size, int offse
tmp = *p;
found_first:
- tmp |= ~0UL >> size;
+ tmp |= ~0UL << size;
found_middle:
return result + ffz(tmp);
}
@@ -499,5 +499,6 @@ found_middle:
* fls: find last bit set.
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#endif /* _M68KNOMMU_BITOPS_H */
diff --git a/include/asm-m68knommu/futex.h b/include/asm-m68knommu/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-m68knommu/futex.h
+++ b/include/asm-m68knommu/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-m68knommu/ioctl.h b/include/asm-m68knommu/ioctl.h
index cff72f33350f..b279fe06dfe5 100644
--- a/include/asm-m68knommu/ioctl.h
+++ b/include/asm-m68knommu/ioctl.h
@@ -1 +1 @@
-#include <asm-m68k/ioctl.h>
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h
index a08fa9b958da..20c48ec858a4 100644
--- a/include/asm-m68knommu/irq.h
+++ b/include/asm-m68knommu/irq.h
@@ -84,10 +84,8 @@ extern void (*mach_disable_irq)(unsigned int);
/*
* Some drivers want these entry points
*/
-#define enable_irq(x) (mach_enable_irq ? (*mach_enable_irq)(x) : 0)
-#define disable_irq(x) (mach_disable_irq ? (*mach_disable_irq)(x) : 0)
-
-#define enable_irq_nosync(x) enable_irq(x)
+#define enable_irq(x) 0
+#define disable_irq(x) do { } while (0)
#define disable_irq_nosync(x) disable_irq(x)
struct irqaction;
diff --git a/include/asm-m68knommu/machdep.h b/include/asm-m68knommu/machdep.h
index 5a9f9c297f79..27c90afd3339 100644
--- a/include/asm-m68knommu/machdep.h
+++ b/include/asm-m68knommu/machdep.h
@@ -38,7 +38,6 @@ extern void (*mach_power_off)( void );
extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
extern void (*mach_hd_setup)(char *, int *);
extern long mach_max_dma_address;
-extern void (*mach_floppy_setup)(char *, int *);
extern void (*mach_floppy_eject)(void);
extern void (*mach_heartbeat) (int);
extern void (*mach_l2_flush) (int);
diff --git a/include/asm-m68knommu/mutex.h b/include/asm-m68knommu/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-m68knommu/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-m68knommu/sigcontext.h b/include/asm-m68knommu/sigcontext.h
index 84bf36dc7a83..36c293fc133d 100644
--- a/include/asm-m68knommu/sigcontext.h
+++ b/include/asm-m68knommu/sigcontext.h
@@ -8,6 +8,7 @@ struct sigcontext {
unsigned long sc_d1;
unsigned long sc_a0;
unsigned long sc_a1;
+ unsigned long sc_a5;
unsigned short sc_sr;
unsigned long sc_pc;
unsigned short sc_formatvec;
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index 7b9a3fa3af5d..b8f009edf2b2 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -75,8 +75,6 @@ static inline struct thread_info *current_thread_info(void)
#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_SIZE_ORDER)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
#define PREEMPT_ACTIVE 0x4000000
diff --git a/include/asm-mips/.gitignore b/include/asm-mips/.gitignore
deleted file mode 100644
index 4ec57ad5bc3c..000000000000
--- a/include/asm-mips/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-asm_offsets.h
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 55c37c106ef0..654b97d3e13a 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -24,10 +24,9 @@
#define _ASM_ATOMIC_H
#include <asm/cpu-features.h>
+#include <asm/interrupt.h>
#include <asm/war.h>
-extern spinlock_t atomic_lock;
-
typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
@@ -85,9 +84,9 @@ static __inline__ void atomic_add(int i, atomic_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
v->counter += i;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
}
@@ -127,9 +126,9 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
v->counter -= i;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
}
@@ -173,11 +172,11 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result += i;
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
@@ -220,11 +219,11 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result -= i;
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
@@ -277,18 +276,19 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result -= i;
if (result >= 0)
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
}
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -432,9 +432,9 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
v->counter += i;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
}
@@ -474,9 +474,9 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
v->counter -= i;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
}
@@ -520,11 +520,11 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result += i;
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
@@ -567,11 +567,11 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result -= i;
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
@@ -624,12 +624,12 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
} else {
unsigned long flags;
- spin_lock_irqsave(&atomic_lock, flags);
+ local_irq_save(flags);
result = v->counter;
result -= i;
if (result >= 0)
v->counter = result;
- spin_unlock_irqrestore(&atomic_lock, flags);
+ local_irq_restore(flags);
}
return result;
@@ -713,4 +713,5 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
+#include <asm-generic/atomic.h>
#endif /* _ASM_ATOMIC_H */
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index 5496f9064a6a..3b0c8aaf6e8b 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -695,7 +695,7 @@ static inline unsigned long fls(unsigned long word)
return flz(~word) + 1;
}
-
+#define fls64(x) generic_fls64(x)
/*
* find_next_zero_bit - find the first zero bit in a memory region
diff --git a/include/asm-mips/cache.h b/include/asm-mips/cache.h
index 1a5d1a669db3..55e19f2ff0e0 100644
--- a/include/asm-mips/cache.h
+++ b/include/asm-mips/cache.h
@@ -15,7 +15,6 @@
#define L1_CACHE_SHIFT CONFIG_MIPS_L1_CACHE_SHIFT
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 6
#define SMP_CACHE_SHIFT L1_CACHE_SHIFT
#define SMP_CACHE_BYTES L1_CACHE_BYTES
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 03627cfb3e45..78c9cc2735d5 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -116,6 +116,27 @@
#endif
#endif
+# ifndef cpu_has_mips32r1
+# define cpu_has_mips32r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R1)
+# endif
+# ifndef cpu_has_mips32r2
+# define cpu_has_mips32r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M32R2)
+# endif
+# ifndef cpu_has_mips64r1
+# define cpu_has_mips64r1 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R1)
+# endif
+# ifndef cpu_has_mips64r2
+# define cpu_has_mips64r2 (cpu_data[0].isa_level & MIPS_CPU_ISA_M64R2)
+# endif
+
+/*
+ * Shortcuts ...
+ */
+#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2)
+#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
+#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
+#define cpu_has_mips_r2 (cpu_has_mips32r2 | cpu_has_mips64r2)
+
#ifndef cpu_has_dsp
#define cpu_has_dsp (cpu_data[0].ases & MIPS_ASE_DSP)
#endif
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index 48eac296060f..934e063e79f1 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -204,16 +204,18 @@
*/
#define MIPS_CPU_ISA_I 0x00000001
#define MIPS_CPU_ISA_II 0x00000002
-#define MIPS_CPU_ISA_III 0x00008003
-#define MIPS_CPU_ISA_IV 0x00008004
-#define MIPS_CPU_ISA_V 0x00008005
-#define MIPS_CPU_ISA_M32 0x00000020
-#define MIPS_CPU_ISA_M64 0x00008040
+#define MIPS_CPU_ISA_III 0x00000003
+#define MIPS_CPU_ISA_IV 0x00000004
+#define MIPS_CPU_ISA_V 0x00000005
+#define MIPS_CPU_ISA_M32R1 0x00000020
+#define MIPS_CPU_ISA_M32R2 0x00000040
+#define MIPS_CPU_ISA_M64R1 0x00000080
+#define MIPS_CPU_ISA_M64R2 0x00000100
-/*
- * Bit 15 encodes if an ISA level supports 64-bit operations.
- */
-#define MIPS_CPU_ISA_64BIT 0x00008000
+#define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | \
+ MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 )
+#define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
+ MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
/*
* CPU Option encodings
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index 48d00cccdafa..64dd45150f64 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -52,13 +52,11 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj)
unsigned long lo;
/*
- * The common rates of 1000 and 128 are rounded wrongly by the
- * catchall case for 64-bit. Excessive precission? Probably ...
+ * The rates of 128 is rounded wrongly by the catchall case
+ * for 64-bit. Excessive precission? Probably ...
*/
#if defined(CONFIG_64BIT) && (HZ == 128)
usecs *= 0x0008637bd05af6c7UL; /* 2**64 / (1000000 / HZ) */
-#elif defined(CONFIG_64BIT) && (HZ == 1000)
- usecs *= 0x004189374BC6A7f0UL; /* 2**64 / (1000000 / HZ) */
#elif defined(CONFIG_64BIT)
usecs *= (0x8000000000000000UL / (500000 / HZ));
#else /* 32-bit junk follows here */
diff --git a/include/asm-mips/dsp.h b/include/asm-mips/dsp.h
index 50f556bb4978..e9bfc0813c72 100644
--- a/include/asm-mips/dsp.h
+++ b/include/asm-mips/dsp.h
@@ -16,7 +16,7 @@
#include <asm/mipsregs.h>
#define DSP_DEFAULT 0x00000000
-#define DSP_MASK 0x1f
+#define DSP_MASK 0x3ff
#define __enable_dsp_hazard() \
do { \
@@ -48,6 +48,7 @@ do { \
tsk->thread.dsp.dspr[3] = mflo2(); \
tsk->thread.dsp.dspr[4] = mfhi3(); \
tsk->thread.dsp.dspr[5] = mflo3(); \
+ tsk->thread.dsp.dspcontrol = rddsp(DSP_MASK); \
} while (0)
#define save_dsp(tsk) \
@@ -64,6 +65,7 @@ do { \
mtlo2(tsk->thread.dsp.dspr[3]); \
mthi3(tsk->thread.dsp.dspr[4]); \
mtlo3(tsk->thread.dsp.dspr[5]); \
+ wrdsp(tsk->thread.dsp.dspcontrol, DSP_MASK); \
} while (0)
#define restore_dsp(tsk) \
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index d2c9a25f8459..851f013adad3 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -277,12 +277,12 @@ do { \
struct task_struct;
-extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
+extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_CORE_COPY_REGS(elf_regs, regs) \
- dump_regs((elf_greg_t *)&(elf_regs), regs);
+ elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) \
dump_task_fpu(tsk, elf_fpregs)
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 7517189e469f..2fc90632f88c 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -233,15 +233,25 @@ __asm__(
#endif
#ifdef CONFIG_CPU_MIPSR2
+/*
+ * gcc has a tradition of misscompiling the previous construct using the
+ * address of a label as argument to inline assembler. Gas otoh has the
+ * annoying difference between la and dla which are only usable for 32-bit
+ * rsp. 64-bit code, so can't be used without conditional compilation.
+ * The alterantive is switching the assembler to 64-bit code which happens
+ * to work right even for 32-bit code ...
+ */
#define instruction_hazard() \
do { \
-__label__ __next; \
+ unsigned long tmp; \
+ \
__asm__ __volatile__( \
+ " .set mips64r2 \n" \
+ " dla %0, 1f \n" \
" jr.hb %0 \n" \
- : \
- : "r" (&&__next)); \
-__next: \
- ; \
+ " .set mips0 \n" \
+ "1: \n" \
+ : "=r" (tmp)); \
} while (0)
#else
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index a5735761f5e5..abdf54ee64cf 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -93,6 +93,7 @@ __asm__ (
" .set noat \n"
#ifdef CONFIG_CPU_MIPSR2
" di \\result \n"
+ " andi \\result, 1 \n"
#else
" mfc0 \\result, $12 \n"
" ori $1, \\result, 1 \n"
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 8327ec341c18..8e1d7ed7d8e3 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -838,6 +838,7 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#define UART3_ADDR 0xB1400000
#define USB_OHCI_BASE 0x14020000 // phys addr for ioremap
+#define USB_OHCI_LEN 0x00060000
#define USB_HOST_CONFIG 0xB4027ffc
#define AU1550_ETH0_BASE 0xB0500000
@@ -1017,10 +1018,12 @@ extern au1xxx_irq_map_t au1xxx_irq_map[];
#define I2S_CONTROL_D (1<<1)
#define I2S_CONTROL_CE (1<<0)
-#ifndef CONFIG_SOC_AU1200
-
/* USB Host Controller */
+#ifndef USB_OHCI_LEN
#define USB_OHCI_LEN 0x00100000
+#endif
+
+#ifndef CONFIG_SOC_AU1200
/* USB Device Controller */
#define USBD_EP0RD 0xB0200000
diff --git a/include/asm-mips/mach-ip22/cpu-feature-overrides.h b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
index ab9714668177..2a37bedb4053 100644
--- a/include/asm-mips/mach-ip22/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
@@ -34,4 +34,9 @@
#define cpu_has_nofpuex 0
#define cpu_has_64bits 1
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_IP22_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
index 4c8a90051fd0..2d2f5b91e47f 100644
--- a/include/asm-mips/mach-ip27/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
@@ -37,4 +37,9 @@
#define cpu_icache_line_size() 64
#define cpu_scache_line_size() 128
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_IP27_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ip27/topology.h b/include/asm-mips/mach-ip27/topology.h
index 82141c711c33..59d26b52ba32 100644
--- a/include/asm-mips/mach-ip27/topology.h
+++ b/include/asm-mips/mach-ip27/topology.h
@@ -27,7 +27,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
.max_interval = 32, \
.busy_factor = 32, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000), \
.cache_nice_tries = 1, \
.per_cpu_gain = 100, \
.flags = SD_LOAD_BALANCE \
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index ab37fc1842ba..b80c30725cf6 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -39,4 +39,9 @@
#define cpu_has_ic_fills_f_dc 0
#define cpu_has_dsp 0
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
index a0fde405d4c4..90ff087083b9 100644
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ja/cpu-feature-overrides.h
@@ -37,4 +37,9 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
index 825c5f674dfc..782b986241dd 100644
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
@@ -40,4 +40,9 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-rm200/cpu-feature-overrides.h b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
index 79f9b064c864..91e7cf5f2bfe 100644
--- a/include/asm-mips/mach-rm200/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
@@ -40,4 +40,9 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 0 /* No S-cache on R5000 I think ... */
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
index 463d051f4683..3073542c93c7 100644
--- a/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-yosemite/cpu-feature-overrides.h
@@ -37,4 +37,9 @@
#define cpu_icache_line_size() 32
#define cpu_scache_line_size() 32
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 0
+
#endif /* __ASM_MACH_YOSEMITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 80370e0a5589..035ba0a9b0df 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -1059,7 +1059,7 @@ do { \
" .set noat \n" \
" move $1, %0 \n" \
" # wrdsp $1, %x1 \n" \
- " .word 0x7c2004f8 | (%x1 << 15) \n" \
+ " .word 0x7c2004f8 | (%x1 << 11) \n" \
" .set pop \n" \
: \
: "r" (val), "i" (mask)); \
diff --git a/include/asm-mips/mman.h b/include/asm-mips/mman.h
index 62060957ba93..dd17c8bd62a1 100644
--- a/include/asm-mips/mman.h
+++ b/include/asm-mips/mman.h
@@ -65,6 +65,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-mips/mutex.h b/include/asm-mips/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-mips/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index f1980c6c3bcc..39d2bd50fece 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -103,7 +103,6 @@ typedef __u32 dspreg_t;
struct mips_dsp_state {
dspreg_t dspr[NUM_DSP_REGS];
unsigned int dspcontrol;
- unsigned short used_dsp;
};
#define INIT_DSP {{0,},}
@@ -201,11 +200,11 @@ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long
unsigned long get_wchan(struct task_struct *p);
-#define __PT_REG(reg) ((long)&((struct pt_regs *)0)->reg - sizeof(struct pt_regs))
-#define __KSTK_TOS(tsk) ((unsigned long)(tsk->thread_info) + THREAD_SIZE - 32)
-#define KSTK_EIP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_epc)))
-#define KSTK_ESP(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(regs[29])))
-#define KSTK_STATUS(tsk) (*(unsigned long *)(__KSTK_TOS(tsk) + __PT_REG(cp0_status)))
+#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32)
+#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk) - 1)
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc)
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29])
+#define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
#define cpu_relax() barrier()
diff --git a/include/asm-mips/riscos-syscall.h b/include/asm-mips/riscos-syscall.h
deleted file mode 100644
index 4d8eb15461eb..000000000000
--- a/include/asm-mips/riscos-syscall.h
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
- */
-#ifndef _ASM_RISCOS_SYSCALL_H
-#define _ASM_RISCOS_SYSCALL_H
-
-/*
- * The syscalls 0 - 3999 are reserved for a down to the root syscall
- * compatibility with RISC/os and IRIX. We'll see how to deal with the
- * various "real" BSD variants like Ultrix, NetBSD ...
- */
-
-/*
- * SVR4 syscalls are in the range from 1 to 999
- */
-#define __NR_SVR4 0
-#define __NR_SVR4_syscall (__NR_SVR4 + 0)
-#define __NR_SVR4_exit (__NR_SVR4 + 1)
-#define __NR_SVR4_fork (__NR_SVR4 + 2)
-#define __NR_SVR4_read (__NR_SVR4 + 3)
-#define __NR_SVR4_write (__NR_SVR4 + 4)
-#define __NR_SVR4_open (__NR_SVR4 + 5)
-#define __NR_SVR4_close (__NR_SVR4 + 6)
-#define __NR_SVR4_wait (__NR_SVR4 + 7)
-#define __NR_SVR4_creat (__NR_SVR4 + 8)
-#define __NR_SVR4_link (__NR_SVR4 + 9)
-#define __NR_SVR4_unlink (__NR_SVR4 + 10)
-#define __NR_SVR4_exec (__NR_SVR4 + 11)
-#define __NR_SVR4_chdir (__NR_SVR4 + 12)
-#define __NR_SVR4_gtime (__NR_SVR4 + 13)
-#define __NR_SVR4_mknod (__NR_SVR4 + 14)
-#define __NR_SVR4_chmod (__NR_SVR4 + 15)
-#define __NR_SVR4_chown (__NR_SVR4 + 16)
-#define __NR_SVR4_sbreak (__NR_SVR4 + 17)
-#define __NR_SVR4_stat (__NR_SVR4 + 18)
-#define __NR_SVR4_lseek (__NR_SVR4 + 19)
-#define __NR_SVR4_getpid (__NR_SVR4 + 20)
-#define __NR_SVR4_mount (__NR_SVR4 + 21)
-#define __NR_SVR4_umount (__NR_SVR4 + 22)
-#define __NR_SVR4_setuid (__NR_SVR4 + 23)
-#define __NR_SVR4_getuid (__NR_SVR4 + 24)
-#define __NR_SVR4_stime (__NR_SVR4 + 25)
-#define __NR_SVR4_ptrace (__NR_SVR4 + 26)
-#define __NR_SVR4_alarm (__NR_SVR4 + 27)
-#define __NR_SVR4_fstat (__NR_SVR4 + 28)
-#define __NR_SVR4_pause (__NR_SVR4 + 29)
-#define __NR_SVR4_utime (__NR_SVR4 + 30)
-#define __NR_SVR4_stty (__NR_SVR4 + 31)
-#define __NR_SVR4_gtty (__NR_SVR4 + 32)
-#define __NR_SVR4_access (__NR_SVR4 + 33)
-#define __NR_SVR4_nice (__NR_SVR4 + 34)
-#define __NR_SVR4_statfs (__NR_SVR4 + 35)
-#define __NR_SVR4_sync (__NR_SVR4 + 36)
-#define __NR_SVR4_kill (__NR_SVR4 + 37)
-#define __NR_SVR4_fstatfs (__NR_SVR4 + 38)
-#define __NR_SVR4_setpgrp (__NR_SVR4 + 39)
-#define __NR_SVR4_cxenix (__NR_SVR4 + 40)
-#define __NR_SVR4_dup (__NR_SVR4 + 41)
-#define __NR_SVR4_pipe (__NR_SVR4 + 42)
-#define __NR_SVR4_times (__NR_SVR4 + 43)
-#define __NR_SVR4_profil (__NR_SVR4 + 44)
-#define __NR_SVR4_plock (__NR_SVR4 + 45)
-#define __NR_SVR4_setgid (__NR_SVR4 + 46)
-#define __NR_SVR4_getgid (__NR_SVR4 + 47)
-#define __NR_SVR4_sig (__NR_SVR4 + 48)
-#define __NR_SVR4_msgsys (__NR_SVR4 + 49)
-#define __NR_SVR4_sysmips (__NR_SVR4 + 50)
-#define __NR_SVR4_sysacct (__NR_SVR4 + 51)
-#define __NR_SVR4_shmsys (__NR_SVR4 + 52)
-#define __NR_SVR4_semsys (__NR_SVR4 + 53)
-#define __NR_SVR4_ioctl (__NR_SVR4 + 54)
-#define __NR_SVR4_uadmin (__NR_SVR4 + 55)
-#define __NR_SVR4_exch (__NR_SVR4 + 56)
-#define __NR_SVR4_utssys (__NR_SVR4 + 57)
-#define __NR_SVR4_fsync (__NR_SVR4 + 58)
-#define __NR_SVR4_exece (__NR_SVR4 + 59)
-#define __NR_SVR4_umask (__NR_SVR4 + 60)
-#define __NR_SVR4_chroot (__NR_SVR4 + 61)
-#define __NR_SVR4_fcntl (__NR_SVR4 + 62)
-#define __NR_SVR4_ulimit (__NR_SVR4 + 63)
-#define __NR_SVR4_reserved1 (__NR_SVR4 + 64)
-#define __NR_SVR4_reserved2 (__NR_SVR4 + 65)
-#define __NR_SVR4_reserved3 (__NR_SVR4 + 66)
-#define __NR_SVR4_reserved4 (__NR_SVR4 + 67)
-#define __NR_SVR4_reserved5 (__NR_SVR4 + 68)
-#define __NR_SVR4_reserved6 (__NR_SVR4 + 69)
-#define __NR_SVR4_advfs (__NR_SVR4 + 70)
-#define __NR_SVR4_unadvfs (__NR_SVR4 + 71)
-#define __NR_SVR4_unused1 (__NR_SVR4 + 72)
-#define __NR_SVR4_unused2 (__NR_SVR4 + 73)
-#define __NR_SVR4_rfstart (__NR_SVR4 + 74)
-#define __NR_SVR4_unused3 (__NR_SVR4 + 75)
-#define __NR_SVR4_rdebug (__NR_SVR4 + 76)
-#define __NR_SVR4_rfstop (__NR_SVR4 + 77)
-#define __NR_SVR4_rfsys (__NR_SVR4 + 78)
-#define __NR_SVR4_rmdir (__NR_SVR4 + 79)
-#define __NR_SVR4_mkdir (__NR_SVR4 + 80)
-#define __NR_SVR4_getdents (__NR_SVR4 + 81)
-#define __NR_SVR4_libattach (__NR_SVR4 + 82)
-#define __NR_SVR4_libdetach (__NR_SVR4 + 83)
-#define __NR_SVR4_sysfs (__NR_SVR4 + 84)
-#define __NR_SVR4_getmsg (__NR_SVR4 + 85)
-#define __NR_SVR4_putmsg (__NR_SVR4 + 86)
-#define __NR_SVR4_poll (__NR_SVR4 + 87)
-#define __NR_SVR4_lstat (__NR_SVR4 + 88)
-#define __NR_SVR4_symlink (__NR_SVR4 + 89)
-#define __NR_SVR4_readlink (__NR_SVR4 + 90)
-#define __NR_SVR4_setgroups (__NR_SVR4 + 91)
-#define __NR_SVR4_getgroups (__NR_SVR4 + 92)
-#define __NR_SVR4_fchmod (__NR_SVR4 + 93)
-#define __NR_SVR4_fchown (__NR_SVR4 + 94)
-#define __NR_SVR4_sigprocmask (__NR_SVR4 + 95)
-#define __NR_SVR4_sigsuspend (__NR_SVR4 + 96)
-#define __NR_SVR4_sigaltstack (__NR_SVR4 + 97)
-#define __NR_SVR4_sigaction (__NR_SVR4 + 98)
-#define __NR_SVR4_sigpending (__NR_SVR4 + 99)
-#define __NR_SVR4_setcontext (__NR_SVR4 + 100)
-#define __NR_SVR4_evsys (__NR_SVR4 + 101)
-#define __NR_SVR4_evtrapret (__NR_SVR4 + 102)
-#define __NR_SVR4_statvfs (__NR_SVR4 + 103)
-#define __NR_SVR4_fstatvfs (__NR_SVR4 + 104)
-#define __NR_SVR4_reserved7 (__NR_SVR4 + 105)
-#define __NR_SVR4_nfssys (__NR_SVR4 + 106)
-#define __NR_SVR4_waitid (__NR_SVR4 + 107)
-#define __NR_SVR4_sigsendset (__NR_SVR4 + 108)
-#define __NR_SVR4_hrtsys (__NR_SVR4 + 109)
-#define __NR_SVR4_acancel (__NR_SVR4 + 110)
-#define __NR_SVR4_async (__NR_SVR4 + 111)
-#define __NR_SVR4_priocntlset (__NR_SVR4 + 112)
-#define __NR_SVR4_pathconf (__NR_SVR4 + 113)
-#define __NR_SVR4_mincore (__NR_SVR4 + 114)
-#define __NR_SVR4_mmap (__NR_SVR4 + 115)
-#define __NR_SVR4_mprotect (__NR_SVR4 + 116)
-#define __NR_SVR4_munmap (__NR_SVR4 + 117)
-#define __NR_SVR4_fpathconf (__NR_SVR4 + 118)
-#define __NR_SVR4_vfork (__NR_SVR4 + 119)
-#define __NR_SVR4_fchdir (__NR_SVR4 + 120)
-#define __NR_SVR4_readv (__NR_SVR4 + 121)
-#define __NR_SVR4_writev (__NR_SVR4 + 122)
-#define __NR_SVR4_xstat (__NR_SVR4 + 123)
-#define __NR_SVR4_lxstat (__NR_SVR4 + 124)
-#define __NR_SVR4_fxstat (__NR_SVR4 + 125)
-#define __NR_SVR4_xmknod (__NR_SVR4 + 126)
-#define __NR_SVR4_clocal (__NR_SVR4 + 127)
-#define __NR_SVR4_setrlimit (__NR_SVR4 + 128)
-#define __NR_SVR4_getrlimit (__NR_SVR4 + 129)
-#define __NR_SVR4_lchown (__NR_SVR4 + 130)
-#define __NR_SVR4_memcntl (__NR_SVR4 + 131)
-#define __NR_SVR4_getpmsg (__NR_SVR4 + 132)
-#define __NR_SVR4_putpmsg (__NR_SVR4 + 133)
-#define __NR_SVR4_rename (__NR_SVR4 + 134)
-#define __NR_SVR4_nuname (__NR_SVR4 + 135)
-#define __NR_SVR4_setegid (__NR_SVR4 + 136)
-#define __NR_SVR4_sysconf (__NR_SVR4 + 137)
-#define __NR_SVR4_adjtime (__NR_SVR4 + 138)
-#define __NR_SVR4_sysinfo (__NR_SVR4 + 139)
-#define __NR_SVR4_reserved8 (__NR_SVR4 + 140)
-#define __NR_SVR4_seteuid (__NR_SVR4 + 141)
-#define __NR_SVR4_PYRAMID_statis (__NR_SVR4 + 142)
-#define __NR_SVR4_PYRAMID_tuning (__NR_SVR4 + 143)
-#define __NR_SVR4_PYRAMID_forcerr (__NR_SVR4 + 144)
-#define __NR_SVR4_PYRAMID_mpcntl (__NR_SVR4 + 145)
-#define __NR_SVR4_reserved9 (__NR_SVR4 + 146)
-#define __NR_SVR4_reserved10 (__NR_SVR4 + 147)
-#define __NR_SVR4_reserved11 (__NR_SVR4 + 148)
-#define __NR_SVR4_reserved12 (__NR_SVR4 + 149)
-#define __NR_SVR4_reserved13 (__NR_SVR4 + 150)
-#define __NR_SVR4_reserved14 (__NR_SVR4 + 151)
-#define __NR_SVR4_reserved15 (__NR_SVR4 + 152)
-#define __NR_SVR4_reserved16 (__NR_SVR4 + 153)
-#define __NR_SVR4_reserved17 (__NR_SVR4 + 154)
-#define __NR_SVR4_reserved18 (__NR_SVR4 + 155)
-#define __NR_SVR4_reserved19 (__NR_SVR4 + 156)
-#define __NR_SVR4_reserved20 (__NR_SVR4 + 157)
-#define __NR_SVR4_reserved21 (__NR_SVR4 + 158)
-#define __NR_SVR4_reserved22 (__NR_SVR4 + 159)
-#define __NR_SVR4_reserved23 (__NR_SVR4 + 160)
-#define __NR_SVR4_reserved24 (__NR_SVR4 + 161)
-#define __NR_SVR4_reserved25 (__NR_SVR4 + 162)
-#define __NR_SVR4_reserved26 (__NR_SVR4 + 163)
-#define __NR_SVR4_reserved27 (__NR_SVR4 + 164)
-#define __NR_SVR4_reserved28 (__NR_SVR4 + 165)
-#define __NR_SVR4_reserved29 (__NR_SVR4 + 166)
-#define __NR_SVR4_reserved30 (__NR_SVR4 + 167)
-#define __NR_SVR4_reserved31 (__NR_SVR4 + 168)
-#define __NR_SVR4_reserved32 (__NR_SVR4 + 169)
-#define __NR_SVR4_reserved33 (__NR_SVR4 + 170)
-#define __NR_SVR4_reserved34 (__NR_SVR4 + 171)
-#define __NR_SVR4_reserved35 (__NR_SVR4 + 172)
-#define __NR_SVR4_reserved36 (__NR_SVR4 + 173)
-#define __NR_SVR4_reserved37 (__NR_SVR4 + 174)
-#define __NR_SVR4_reserved38 (__NR_SVR4 + 175)
-#define __NR_SVR4_reserved39 (__NR_SVR4 + 176)
-#define __NR_SVR4_reserved40 (__NR_SVR4 + 177)
-#define __NR_SVR4_reserved41 (__NR_SVR4 + 178)
-#define __NR_SVR4_reserved42 (__NR_SVR4 + 179)
-#define __NR_SVR4_reserved43 (__NR_SVR4 + 180)
-#define __NR_SVR4_reserved44 (__NR_SVR4 + 181)
-#define __NR_SVR4_reserved45 (__NR_SVR4 + 182)
-#define __NR_SVR4_reserved46 (__NR_SVR4 + 183)
-#define __NR_SVR4_reserved47 (__NR_SVR4 + 184)
-#define __NR_SVR4_reserved48 (__NR_SVR4 + 185)
-#define __NR_SVR4_reserved49 (__NR_SVR4 + 186)
-#define __NR_SVR4_reserved50 (__NR_SVR4 + 187)
-#define __NR_SVR4_reserved51 (__NR_SVR4 + 188)
-#define __NR_SVR4_reserved52 (__NR_SVR4 + 189)
-#define __NR_SVR4_reserved53 (__NR_SVR4 + 190)
-#define __NR_SVR4_reserved54 (__NR_SVR4 + 191)
-#define __NR_SVR4_reserved55 (__NR_SVR4 + 192)
-#define __NR_SVR4_reserved56 (__NR_SVR4 + 193)
-#define __NR_SVR4_reserved57 (__NR_SVR4 + 194)
-#define __NR_SVR4_reserved58 (__NR_SVR4 + 195)
-#define __NR_SVR4_reserved59 (__NR_SVR4 + 196)
-#define __NR_SVR4_reserved60 (__NR_SVR4 + 197)
-#define __NR_SVR4_reserved61 (__NR_SVR4 + 198)
-#define __NR_SVR4_reserved62 (__NR_SVR4 + 199)
-#define __NR_SVR4_reserved63 (__NR_SVR4 + 200)
-#define __NR_SVR4_aread (__NR_SVR4 + 201)
-#define __NR_SVR4_awrite (__NR_SVR4 + 202)
-#define __NR_SVR4_listio (__NR_SVR4 + 203)
-#define __NR_SVR4_mips_acancel (__NR_SVR4 + 204)
-#define __NR_SVR4_astatus (__NR_SVR4 + 205)
-#define __NR_SVR4_await (__NR_SVR4 + 206)
-#define __NR_SVR4_areadv (__NR_SVR4 + 207)
-#define __NR_SVR4_awritev (__NR_SVR4 + 208)
-#define __NR_SVR4_MIPS_reserved1 (__NR_SVR4 + 209)
-#define __NR_SVR4_MIPS_reserved2 (__NR_SVR4 + 210)
-#define __NR_SVR4_MIPS_reserved3 (__NR_SVR4 + 211)
-#define __NR_SVR4_MIPS_reserved4 (__NR_SVR4 + 212)
-#define __NR_SVR4_MIPS_reserved5 (__NR_SVR4 + 213)
-#define __NR_SVR4_MIPS_reserved6 (__NR_SVR4 + 214)
-#define __NR_SVR4_MIPS_reserved7 (__NR_SVR4 + 215)
-#define __NR_SVR4_MIPS_reserved8 (__NR_SVR4 + 216)
-#define __NR_SVR4_MIPS_reserved9 (__NR_SVR4 + 217)
-#define __NR_SVR4_MIPS_reserved10 (__NR_SVR4 + 218)
-#define __NR_SVR4_MIPS_reserved11 (__NR_SVR4 + 219)
-#define __NR_SVR4_MIPS_reserved12 (__NR_SVR4 + 220)
-#define __NR_SVR4_CDC_reserved1 (__NR_SVR4 + 221)
-#define __NR_SVR4_CDC_reserved2 (__NR_SVR4 + 222)
-#define __NR_SVR4_CDC_reserved3 (__NR_SVR4 + 223)
-#define __NR_SVR4_CDC_reserved4 (__NR_SVR4 + 224)
-#define __NR_SVR4_CDC_reserved5 (__NR_SVR4 + 225)
-#define __NR_SVR4_CDC_reserved6 (__NR_SVR4 + 226)
-#define __NR_SVR4_CDC_reserved7 (__NR_SVR4 + 227)
-#define __NR_SVR4_CDC_reserved8 (__NR_SVR4 + 228)
-#define __NR_SVR4_CDC_reserved9 (__NR_SVR4 + 229)
-#define __NR_SVR4_CDC_reserved10 (__NR_SVR4 + 230)
-#define __NR_SVR4_CDC_reserved11 (__NR_SVR4 + 231)
-#define __NR_SVR4_CDC_reserved12 (__NR_SVR4 + 232)
-#define __NR_SVR4_CDC_reserved13 (__NR_SVR4 + 233)
-#define __NR_SVR4_CDC_reserved14 (__NR_SVR4 + 234)
-#define __NR_SVR4_CDC_reserved15 (__NR_SVR4 + 235)
-#define __NR_SVR4_CDC_reserved16 (__NR_SVR4 + 236)
-#define __NR_SVR4_CDC_reserved17 (__NR_SVR4 + 237)
-#define __NR_SVR4_CDC_reserved18 (__NR_SVR4 + 238)
-#define __NR_SVR4_CDC_reserved19 (__NR_SVR4 + 239)
-#define __NR_SVR4_CDC_reserved20 (__NR_SVR4 + 240)
-
-/*
- * SYS V syscalls are in the range from 1000 to 1999
- */
-#define __NR_SYSV 1000
-#define __NR_SYSV_syscall (__NR_SYSV + 0)
-#define __NR_SYSV_exit (__NR_SYSV + 1)
-#define __NR_SYSV_fork (__NR_SYSV + 2)
-#define __NR_SYSV_read (__NR_SYSV + 3)
-#define __NR_SYSV_write (__NR_SYSV + 4)
-#define __NR_SYSV_open (__NR_SYSV + 5)
-#define __NR_SYSV_close (__NR_SYSV + 6)
-#define __NR_SYSV_wait (__NR_SYSV + 7)
-#define __NR_SYSV_creat (__NR_SYSV + 8)
-#define __NR_SYSV_link (__NR_SYSV + 9)
-#define __NR_SYSV_unlink (__NR_SYSV + 10)
-#define __NR_SYSV_execv (__NR_SYSV + 11)
-#define __NR_SYSV_chdir (__NR_SYSV + 12)
-#define __NR_SYSV_time (__NR_SYSV + 13)
-#define __NR_SYSV_mknod (__NR_SYSV + 14)
-#define __NR_SYSV_chmod (__NR_SYSV + 15)
-#define __NR_SYSV_chown (__NR_SYSV + 16)
-#define __NR_SYSV_brk (__NR_SYSV + 17)
-#define __NR_SYSV_stat (__NR_SYSV + 18)
-#define __NR_SYSV_lseek (__NR_SYSV + 19)
-#define __NR_SYSV_getpid (__NR_SYSV + 20)
-#define __NR_SYSV_mount (__NR_SYSV + 21)
-#define __NR_SYSV_umount (__NR_SYSV + 22)
-#define __NR_SYSV_setuid (__NR_SYSV + 23)
-#define __NR_SYSV_getuid (__NR_SYSV + 24)
-#define __NR_SYSV_stime (__NR_SYSV + 25)
-#define __NR_SYSV_ptrace (__NR_SYSV + 26)
-#define __NR_SYSV_alarm (__NR_SYSV + 27)
-#define __NR_SYSV_fstat (__NR_SYSV + 28)
-#define __NR_SYSV_pause (__NR_SYSV + 29)
-#define __NR_SYSV_utime (__NR_SYSV + 30)
-#define __NR_SYSV_stty (__NR_SYSV + 31)
-#define __NR_SYSV_gtty (__NR_SYSV + 32)
-#define __NR_SYSV_access (__NR_SYSV + 33)
-#define __NR_SYSV_nice (__NR_SYSV + 34)
-#define __NR_SYSV_statfs (__NR_SYSV + 35)
-#define __NR_SYSV_sync (__NR_SYSV + 36)
-#define __NR_SYSV_kill (__NR_SYSV + 37)
-#define __NR_SYSV_fstatfs (__NR_SYSV + 38)
-#define __NR_SYSV_setpgrp (__NR_SYSV + 39)
-#define __NR_SYSV_syssgi (__NR_SYSV + 40)
-#define __NR_SYSV_dup (__NR_SYSV + 41)
-#define __NR_SYSV_pipe (__NR_SYSV + 42)
-#define __NR_SYSV_times (__NR_SYSV + 43)
-#define __NR_SYSV_profil (__NR_SYSV + 44)
-#define __NR_SYSV_plock (__NR_SYSV + 45)
-#define __NR_SYSV_setgid (__NR_SYSV + 46)
-#define __NR_SYSV_getgid (__NR_SYSV + 47)
-#define __NR_SYSV_sig (__NR_SYSV + 48)
-#define __NR_SYSV_msgsys (__NR_SYSV + 49)
-#define __NR_SYSV_sysmips (__NR_SYSV + 50)
-#define __NR_SYSV_acct (__NR_SYSV + 51)
-#define __NR_SYSV_shmsys (__NR_SYSV + 52)
-#define __NR_SYSV_semsys (__NR_SYSV + 53)
-#define __NR_SYSV_ioctl (__NR_SYSV + 54)
-#define __NR_SYSV_uadmin (__NR_SYSV + 55)
-#define __NR_SYSV_sysmp (__NR_SYSV + 56)
-#define __NR_SYSV_utssys (__NR_SYSV + 57)
-#define __NR_SYSV_USG_reserved1 (__NR_SYSV + 58)
-#define __NR_SYSV_execve (__NR_SYSV + 59)
-#define __NR_SYSV_umask (__NR_SYSV + 60)
-#define __NR_SYSV_chroot (__NR_SYSV + 61)
-#define __NR_SYSV_fcntl (__NR_SYSV + 62)
-#define __NR_SYSV_ulimit (__NR_SYSV + 63)
-#define __NR_SYSV_SAFARI4_reserved1 (__NR_SYSV + 64)
-#define __NR_SYSV_SAFARI4_reserved2 (__NR_SYSV + 65)
-#define __NR_SYSV_SAFARI4_reserved3 (__NR_SYSV + 66)
-#define __NR_SYSV_SAFARI4_reserved4 (__NR_SYSV + 67)
-#define __NR_SYSV_SAFARI4_reserved5 (__NR_SYSV + 68)
-#define __NR_SYSV_SAFARI4_reserved6 (__NR_SYSV + 69)
-#define __NR_SYSV_advfs (__NR_SYSV + 70)
-#define __NR_SYSV_unadvfs (__NR_SYSV + 71)
-#define __NR_SYSV_rmount (__NR_SYSV + 72)
-#define __NR_SYSV_rumount (__NR_SYSV + 73)
-#define __NR_SYSV_rfstart (__NR_SYSV + 74)
-#define __NR_SYSV_getrlimit64 (__NR_SYSV + 75)
-#define __NR_SYSV_setrlimit64 (__NR_SYSV + 76)
-#define __NR_SYSV_nanosleep (__NR_SYSV + 77)
-#define __NR_SYSV_lseek64 (__NR_SYSV + 78)
-#define __NR_SYSV_rmdir (__NR_SYSV + 79)
-#define __NR_SYSV_mkdir (__NR_SYSV + 80)
-#define __NR_SYSV_getdents (__NR_SYSV + 81)
-#define __NR_SYSV_sginap (__NR_SYSV + 82)
-#define __NR_SYSV_sgikopt (__NR_SYSV + 83)
-#define __NR_SYSV_sysfs (__NR_SYSV + 84)
-#define __NR_SYSV_getmsg (__NR_SYSV + 85)
-#define __NR_SYSV_putmsg (__NR_SYSV + 86)
-#define __NR_SYSV_poll (__NR_SYSV + 87)
-#define __NR_SYSV_sigreturn (__NR_SYSV + 88)
-#define __NR_SYSV_accept (__NR_SYSV + 89)
-#define __NR_SYSV_bind (__NR_SYSV + 90)
-#define __NR_SYSV_connect (__NR_SYSV + 91)
-#define __NR_SYSV_gethostid (__NR_SYSV + 92)
-#define __NR_SYSV_getpeername (__NR_SYSV + 93)
-#define __NR_SYSV_getsockname (__NR_SYSV + 94)
-#define __NR_SYSV_getsockopt (__NR_SYSV + 95)
-#define __NR_SYSV_listen (__NR_SYSV + 96)
-#define __NR_SYSV_recv (__NR_SYSV + 97)
-#define __NR_SYSV_recvfrom (__NR_SYSV + 98)
-#define __NR_SYSV_recvmsg (__NR_SYSV + 99)
-#define __NR_SYSV_select (__NR_SYSV + 100)
-#define __NR_SYSV_send (__NR_SYSV + 101)
-#define __NR_SYSV_sendmsg (__NR_SYSV + 102)
-#define __NR_SYSV_sendto (__NR_SYSV + 103)
-#define __NR_SYSV_sethostid (__NR_SYSV + 104)
-#define __NR_SYSV_setsockopt (__NR_SYSV + 105)
-#define __NR_SYSV_shutdown (__NR_SYSV + 106)
-#define __NR_SYSV_socket (__NR_SYSV + 107)
-#define __NR_SYSV_gethostname (__NR_SYSV + 108)
-#define __NR_SYSV_sethostname (__NR_SYSV + 109)
-#define __NR_SYSV_getdomainname (__NR_SYSV + 110)
-#define __NR_SYSV_setdomainname (__NR_SYSV + 111)
-#define __NR_SYSV_truncate (__NR_SYSV + 112)
-#define __NR_SYSV_ftruncate (__NR_SYSV + 113)
-#define __NR_SYSV_rename (__NR_SYSV + 114)
-#define __NR_SYSV_symlink (__NR_SYSV + 115)
-#define __NR_SYSV_readlink (__NR_SYSV + 116)
-#define __NR_SYSV_lstat (__NR_SYSV + 117)
-#define __NR_SYSV_nfsmount (__NR_SYSV + 118)
-#define __NR_SYSV_nfssvc (__NR_SYSV + 119)
-#define __NR_SYSV_getfh (__NR_SYSV + 120)
-#define __NR_SYSV_async_daemon (__NR_SYSV + 121)
-#define __NR_SYSV_exportfs (__NR_SYSV + 122)
-#define __NR_SYSV_setregid (__NR_SYSV + 123)
-#define __NR_SYSV_setreuid (__NR_SYSV + 124)
-#define __NR_SYSV_getitimer (__NR_SYSV + 125)
-#define __NR_SYSV_setitimer (__NR_SYSV + 126)
-#define __NR_SYSV_adjtime (__NR_SYSV + 127)
-#define __NR_SYSV_BSD_getime (__NR_SYSV + 128)
-#define __NR_SYSV_sproc (__NR_SYSV + 129)
-#define __NR_SYSV_prctl (__NR_SYSV + 130)
-#define __NR_SYSV_procblk (__NR_SYSV + 131)
-#define __NR_SYSV_sprocsp (__NR_SYSV + 132)
-#define __NR_SYSV_sgigsc (__NR_SYSV + 133)
-#define __NR_SYSV_mmap (__NR_SYSV + 134)
-#define __NR_SYSV_munmap (__NR_SYSV + 135)
-#define __NR_SYSV_mprotect (__NR_SYSV + 136)
-#define __NR_SYSV_msync (__NR_SYSV + 137)
-#define __NR_SYSV_madvise (__NR_SYSV + 138)
-#define __NR_SYSV_pagelock (__NR_SYSV + 139)
-#define __NR_SYSV_getpagesize (__NR_SYSV + 140)
-#define __NR_SYSV_quotactl (__NR_SYSV + 141)
-#define __NR_SYSV_libdetach (__NR_SYSV + 142)
-#define __NR_SYSV_BSDgetpgrp (__NR_SYSV + 143)
-#define __NR_SYSV_BSDsetpgrp (__NR_SYSV + 144)
-#define __NR_SYSV_vhangup (__NR_SYSV + 145)
-#define __NR_SYSV_fsync (__NR_SYSV + 146)
-#define __NR_SYSV_fchdir (__NR_SYSV + 147)
-#define __NR_SYSV_getrlimit (__NR_SYSV + 148)
-#define __NR_SYSV_setrlimit (__NR_SYSV + 149)
-#define __NR_SYSV_cacheflush (__NR_SYSV + 150)
-#define __NR_SYSV_cachectl (__NR_SYSV + 151)
-#define __NR_SYSV_fchown (__NR_SYSV + 152)
-#define __NR_SYSV_fchmod (__NR_SYSV + 153)
-#define __NR_SYSV_wait3 (__NR_SYSV + 154)
-#define __NR_SYSV_socketpair (__NR_SYSV + 155)
-#define __NR_SYSV_sysinfo (__NR_SYSV + 156)
-#define __NR_SYSV_nuname (__NR_SYSV + 157)
-#define __NR_SYSV_xstat (__NR_SYSV + 158)
-#define __NR_SYSV_lxstat (__NR_SYSV + 159)
-#define __NR_SYSV_fxstat (__NR_SYSV + 160)
-#define __NR_SYSV_xmknod (__NR_SYSV + 161)
-#define __NR_SYSV_ksigaction (__NR_SYSV + 162)
-#define __NR_SYSV_sigpending (__NR_SYSV + 163)
-#define __NR_SYSV_sigprocmask (__NR_SYSV + 164)
-#define __NR_SYSV_sigsuspend (__NR_SYSV + 165)
-#define __NR_SYSV_sigpoll (__NR_SYSV + 166)
-#define __NR_SYSV_swapctl (__NR_SYSV + 167)
-#define __NR_SYSV_getcontext (__NR_SYSV + 168)
-#define __NR_SYSV_setcontext (__NR_SYSV + 169)
-#define __NR_SYSV_waitsys (__NR_SYSV + 170)
-#define __NR_SYSV_sigstack (__NR_SYSV + 171)
-#define __NR_SYSV_sigaltstack (__NR_SYSV + 172)
-#define __NR_SYSV_sigsendset (__NR_SYSV + 173)
-#define __NR_SYSV_statvfs (__NR_SYSV + 174)
-#define __NR_SYSV_fstatvfs (__NR_SYSV + 175)
-#define __NR_SYSV_getpmsg (__NR_SYSV + 176)
-#define __NR_SYSV_putpmsg (__NR_SYSV + 177)
-#define __NR_SYSV_lchown (__NR_SYSV + 178)
-#define __NR_SYSV_priocntl (__NR_SYSV + 179)
-#define __NR_SYSV_ksigqueue (__NR_SYSV + 180)
-#define __NR_SYSV_readv (__NR_SYSV + 181)
-#define __NR_SYSV_writev (__NR_SYSV + 182)
-#define __NR_SYSV_truncate64 (__NR_SYSV + 183)
-#define __NR_SYSV_ftruncate64 (__NR_SYSV + 184)
-#define __NR_SYSV_mmap64 (__NR_SYSV + 185)
-#define __NR_SYSV_dmi (__NR_SYSV + 186)
-#define __NR_SYSV_pread (__NR_SYSV + 187)
-#define __NR_SYSV_pwrite (__NR_SYSV + 188)
-
-/*
- * BSD 4.3 syscalls are in the range from 2000 to 2999
- */
-#define __NR_BSD43 2000
-#define __NR_BSD43_syscall (__NR_BSD43 + 0)
-#define __NR_BSD43_exit (__NR_BSD43 + 1)
-#define __NR_BSD43_fork (__NR_BSD43 + 2)
-#define __NR_BSD43_read (__NR_BSD43 + 3)
-#define __NR_BSD43_write (__NR_BSD43 + 4)
-#define __NR_BSD43_open (__NR_BSD43 + 5)
-#define __NR_BSD43_close (__NR_BSD43 + 6)
-#define __NR_BSD43_wait (__NR_BSD43 + 7)
-#define __NR_BSD43_creat (__NR_BSD43 + 8)
-#define __NR_BSD43_link (__NR_BSD43 + 9)
-#define __NR_BSD43_unlink (__NR_BSD43 + 10)
-#define __NR_BSD43_exec (__NR_BSD43 + 11)
-#define __NR_BSD43_chdir (__NR_BSD43 + 12)
-#define __NR_BSD43_time (__NR_BSD43 + 13)
-#define __NR_BSD43_mknod (__NR_BSD43 + 14)
-#define __NR_BSD43_chmod (__NR_BSD43 + 15)
-#define __NR_BSD43_chown (__NR_BSD43 + 16)
-#define __NR_BSD43_sbreak (__NR_BSD43 + 17)
-#define __NR_BSD43_oldstat (__NR_BSD43 + 18)
-#define __NR_BSD43_lseek (__NR_BSD43 + 19)
-#define __NR_BSD43_getpid (__NR_BSD43 + 20)
-#define __NR_BSD43_oldmount (__NR_BSD43 + 21)
-#define __NR_BSD43_umount (__NR_BSD43 + 22)
-#define __NR_BSD43_setuid (__NR_BSD43 + 23)
-#define __NR_BSD43_getuid (__NR_BSD43 + 24)
-#define __NR_BSD43_stime (__NR_BSD43 + 25)
-#define __NR_BSD43_ptrace (__NR_BSD43 + 26)
-#define __NR_BSD43_alarm (__NR_BSD43 + 27)
-#define __NR_BSD43_oldfstat (__NR_BSD43 + 28)
-#define __NR_BSD43_pause (__NR_BSD43 + 29)
-#define __NR_BSD43_utime (__NR_BSD43 + 30)
-#define __NR_BSD43_stty (__NR_BSD43 + 31)
-#define __NR_BSD43_gtty (__NR_BSD43 + 32)
-#define __NR_BSD43_access (__NR_BSD43 + 33)
-#define __NR_BSD43_nice (__NR_BSD43 + 34)
-#define __NR_BSD43_ftime (__NR_BSD43 + 35)
-#define __NR_BSD43_sync (__NR_BSD43 + 36)
-#define __NR_BSD43_kill (__NR_BSD43 + 37)
-#define __NR_BSD43_stat (__NR_BSD43 + 38)
-#define __NR_BSD43_oldsetpgrp (__NR_BSD43 + 39)
-#define __NR_BSD43_lstat (__NR_BSD43 + 40)
-#define __NR_BSD43_dup (__NR_BSD43 + 41)
-#define __NR_BSD43_pipe (__NR_BSD43 + 42)
-#define __NR_BSD43_times (__NR_BSD43 + 43)
-#define __NR_BSD43_profil (__NR_BSD43 + 44)
-#define __NR_BSD43_msgsys (__NR_BSD43 + 45)
-#define __NR_BSD43_setgid (__NR_BSD43 + 46)
-#define __NR_BSD43_getgid (__NR_BSD43 + 47)
-#define __NR_BSD43_ssig (__NR_BSD43 + 48)
-#define __NR_BSD43_reserved1 (__NR_BSD43 + 49)
-#define __NR_BSD43_reserved2 (__NR_BSD43 + 50)
-#define __NR_BSD43_sysacct (__NR_BSD43 + 51)
-#define __NR_BSD43_phys (__NR_BSD43 + 52)
-#define __NR_BSD43_lock (__NR_BSD43 + 53)
-#define __NR_BSD43_ioctl (__NR_BSD43 + 54)
-#define __NR_BSD43_reboot (__NR_BSD43 + 55)
-#define __NR_BSD43_mpxchan (__NR_BSD43 + 56)
-#define __NR_BSD43_symlink (__NR_BSD43 + 57)
-#define __NR_BSD43_readlink (__NR_BSD43 + 58)
-#define __NR_BSD43_execve (__NR_BSD43 + 59)
-#define __NR_BSD43_umask (__NR_BSD43 + 60)
-#define __NR_BSD43_chroot (__NR_BSD43 + 61)
-#define __NR_BSD43_fstat (__NR_BSD43 + 62)
-#define __NR_BSD43_reserved3 (__NR_BSD43 + 63)
-#define __NR_BSD43_getpagesize (__NR_BSD43 + 64)
-#define __NR_BSD43_mremap (__NR_BSD43 + 65)
-#define __NR_BSD43_vfork (__NR_BSD43 + 66)
-#define __NR_BSD43_vread (__NR_BSD43 + 67)
-#define __NR_BSD43_vwrite (__NR_BSD43 + 68)
-#define __NR_BSD43_sbrk (__NR_BSD43 + 69)
-#define __NR_BSD43_sstk (__NR_BSD43 + 70)
-#define __NR_BSD43_mmap (__NR_BSD43 + 71)
-#define __NR_BSD43_vadvise (__NR_BSD43 + 72)
-#define __NR_BSD43_munmap (__NR_BSD43 + 73)
-#define __NR_BSD43_mprotect (__NR_BSD43 + 74)
-#define __NR_BSD43_madvise (__NR_BSD43 + 75)
-#define __NR_BSD43_vhangup (__NR_BSD43 + 76)
-#define __NR_BSD43_vlimit (__NR_BSD43 + 77)
-#define __NR_BSD43_mincore (__NR_BSD43 + 78)
-#define __NR_BSD43_getgroups (__NR_BSD43 + 79)
-#define __NR_BSD43_setgroups (__NR_BSD43 + 80)
-#define __NR_BSD43_getpgrp (__NR_BSD43 + 81)
-#define __NR_BSD43_setpgrp (__NR_BSD43 + 82)
-#define __NR_BSD43_setitimer (__NR_BSD43 + 83)
-#define __NR_BSD43_wait3 (__NR_BSD43 + 84)
-#define __NR_BSD43_swapon (__NR_BSD43 + 85)
-#define __NR_BSD43_getitimer (__NR_BSD43 + 86)
-#define __NR_BSD43_gethostname (__NR_BSD43 + 87)
-#define __NR_BSD43_sethostname (__NR_BSD43 + 88)
-#define __NR_BSD43_getdtablesize (__NR_BSD43 + 89)
-#define __NR_BSD43_dup2 (__NR_BSD43 + 90)
-#define __NR_BSD43_getdopt (__NR_BSD43 + 91)
-#define __NR_BSD43_fcntl (__NR_BSD43 + 92)
-#define __NR_BSD43_select (__NR_BSD43 + 93)
-#define __NR_BSD43_setdopt (__NR_BSD43 + 94)
-#define __NR_BSD43_fsync (__NR_BSD43 + 95)
-#define __NR_BSD43_setpriority (__NR_BSD43 + 96)
-#define __NR_BSD43_socket (__NR_BSD43 + 97)
-#define __NR_BSD43_connect (__NR_BSD43 + 98)
-#define __NR_BSD43_oldaccept (__NR_BSD43 + 99)
-#define __NR_BSD43_getpriority (__NR_BSD43 + 100)
-#define __NR_BSD43_send (__NR_BSD43 + 101)
-#define __NR_BSD43_recv (__NR_BSD43 + 102)
-#define __NR_BSD43_sigreturn (__NR_BSD43 + 103)
-#define __NR_BSD43_bind (__NR_BSD43 + 104)
-#define __NR_BSD43_setsockopt (__NR_BSD43 + 105)
-#define __NR_BSD43_listen (__NR_BSD43 + 106)
-#define __NR_BSD43_vtimes (__NR_BSD43 + 107)
-#define __NR_BSD43_sigvec (__NR_BSD43 + 108)
-#define __NR_BSD43_sigblock (__NR_BSD43 + 109)
-#define __NR_BSD43_sigsetmask (__NR_BSD43 + 110)
-#define __NR_BSD43_sigpause (__NR_BSD43 + 111)
-#define __NR_BSD43_sigstack (__NR_BSD43 + 112)
-#define __NR_BSD43_oldrecvmsg (__NR_BSD43 + 113)
-#define __NR_BSD43_oldsendmsg (__NR_BSD43 + 114)
-#define __NR_BSD43_vtrace (__NR_BSD43 + 115)
-#define __NR_BSD43_gettimeofday (__NR_BSD43 + 116)
-#define __NR_BSD43_getrusage (__NR_BSD43 + 117)
-#define __NR_BSD43_getsockopt (__NR_BSD43 + 118)
-#define __NR_BSD43_reserved4 (__NR_BSD43 + 119)
-#define __NR_BSD43_readv (__NR_BSD43 + 120)
-#define __NR_BSD43_writev (__NR_BSD43 + 121)
-#define __NR_BSD43_settimeofday (__NR_BSD43 + 122)
-#define __NR_BSD43_fchown (__NR_BSD43 + 123)
-#define __NR_BSD43_fchmod (__NR_BSD43 + 124)
-#define __NR_BSD43_oldrecvfrom (__NR_BSD43 + 125)
-#define __NR_BSD43_setreuid (__NR_BSD43 + 126)
-#define __NR_BSD43_setregid (__NR_BSD43 + 127)
-#define __NR_BSD43_rename (__NR_BSD43 + 128)
-#define __NR_BSD43_truncate (__NR_BSD43 + 129)
-#define __NR_BSD43_ftruncate (__NR_BSD43 + 130)
-#define __NR_BSD43_flock (__NR_BSD43 + 131)
-#define __NR_BSD43_semsys (__NR_BSD43 + 132)
-#define __NR_BSD43_sendto (__NR_BSD43 + 133)
-#define __NR_BSD43_shutdown (__NR_BSD43 + 134)
-#define __NR_BSD43_socketpair (__NR_BSD43 + 135)
-#define __NR_BSD43_mkdir (__NR_BSD43 + 136)
-#define __NR_BSD43_rmdir (__NR_BSD43 + 137)
-#define __NR_BSD43_utimes (__NR_BSD43 + 138)
-#define __NR_BSD43_sigcleanup (__NR_BSD43 + 139)
-#define __NR_BSD43_adjtime (__NR_BSD43 + 140)
-#define __NR_BSD43_oldgetpeername (__NR_BSD43 + 141)
-#define __NR_BSD43_gethostid (__NR_BSD43 + 142)
-#define __NR_BSD43_sethostid (__NR_BSD43 + 143)
-#define __NR_BSD43_getrlimit (__NR_BSD43 + 144)
-#define __NR_BSD43_setrlimit (__NR_BSD43 + 145)
-#define __NR_BSD43_killpg (__NR_BSD43 + 146)
-#define __NR_BSD43_shmsys (__NR_BSD43 + 147)
-#define __NR_BSD43_quota (__NR_BSD43 + 148)
-#define __NR_BSD43_qquota (__NR_BSD43 + 149)
-#define __NR_BSD43_oldgetsockname (__NR_BSD43 + 150)
-#define __NR_BSD43_sysmips (__NR_BSD43 + 151)
-#define __NR_BSD43_cacheflush (__NR_BSD43 + 152)
-#define __NR_BSD43_cachectl (__NR_BSD43 + 153)
-#define __NR_BSD43_debug (__NR_BSD43 + 154)
-#define __NR_BSD43_reserved5 (__NR_BSD43 + 155)
-#define __NR_BSD43_reserved6 (__NR_BSD43 + 156)
-#define __NR_BSD43_nfs_mount (__NR_BSD43 + 157)
-#define __NR_BSD43_nfs_svc (__NR_BSD43 + 158)
-#define __NR_BSD43_getdirentries (__NR_BSD43 + 159)
-#define __NR_BSD43_statfs (__NR_BSD43 + 160)
-#define __NR_BSD43_fstatfs (__NR_BSD43 + 161)
-#define __NR_BSD43_unmount (__NR_BSD43 + 162)
-#define __NR_BSD43_async_daemon (__NR_BSD43 + 163)
-#define __NR_BSD43_nfs_getfh (__NR_BSD43 + 164)
-#define __NR_BSD43_getdomainname (__NR_BSD43 + 165)
-#define __NR_BSD43_setdomainname (__NR_BSD43 + 166)
-#define __NR_BSD43_pcfs_mount (__NR_BSD43 + 167)
-#define __NR_BSD43_quotactl (__NR_BSD43 + 168)
-#define __NR_BSD43_oldexportfs (__NR_BSD43 + 169)
-#define __NR_BSD43_smount (__NR_BSD43 + 170)
-#define __NR_BSD43_mipshwconf (__NR_BSD43 + 171)
-#define __NR_BSD43_exportfs (__NR_BSD43 + 172)
-#define __NR_BSD43_nfsfh_open (__NR_BSD43 + 173)
-#define __NR_BSD43_libattach (__NR_BSD43 + 174)
-#define __NR_BSD43_libdetach (__NR_BSD43 + 175)
-#define __NR_BSD43_accept (__NR_BSD43 + 176)
-#define __NR_BSD43_reserved7 (__NR_BSD43 + 177)
-#define __NR_BSD43_reserved8 (__NR_BSD43 + 178)
-#define __NR_BSD43_recvmsg (__NR_BSD43 + 179)
-#define __NR_BSD43_recvfrom (__NR_BSD43 + 180)
-#define __NR_BSD43_sendmsg (__NR_BSD43 + 181)
-#define __NR_BSD43_getpeername (__NR_BSD43 + 182)
-#define __NR_BSD43_getsockname (__NR_BSD43 + 183)
-#define __NR_BSD43_aread (__NR_BSD43 + 184)
-#define __NR_BSD43_awrite (__NR_BSD43 + 185)
-#define __NR_BSD43_listio (__NR_BSD43 + 186)
-#define __NR_BSD43_acancel (__NR_BSD43 + 187)
-#define __NR_BSD43_astatus (__NR_BSD43 + 188)
-#define __NR_BSD43_await (__NR_BSD43 + 189)
-#define __NR_BSD43_areadv (__NR_BSD43 + 190)
-#define __NR_BSD43_awritev (__NR_BSD43 + 191)
-
-/*
- * POSIX syscalls are in the range from 3000 to 3999
- */
-#define __NR_POSIX 3000
-#define __NR_POSIX_syscall (__NR_POSIX + 0)
-#define __NR_POSIX_exit (__NR_POSIX + 1)
-#define __NR_POSIX_fork (__NR_POSIX + 2)
-#define __NR_POSIX_read (__NR_POSIX + 3)
-#define __NR_POSIX_write (__NR_POSIX + 4)
-#define __NR_POSIX_open (__NR_POSIX + 5)
-#define __NR_POSIX_close (__NR_POSIX + 6)
-#define __NR_POSIX_wait (__NR_POSIX + 7)
-#define __NR_POSIX_creat (__NR_POSIX + 8)
-#define __NR_POSIX_link (__NR_POSIX + 9)
-#define __NR_POSIX_unlink (__NR_POSIX + 10)
-#define __NR_POSIX_exec (__NR_POSIX + 11)
-#define __NR_POSIX_chdir (__NR_POSIX + 12)
-#define __NR_POSIX_gtime (__NR_POSIX + 13)
-#define __NR_POSIX_mknod (__NR_POSIX + 14)
-#define __NR_POSIX_chmod (__NR_POSIX + 15)
-#define __NR_POSIX_chown (__NR_POSIX + 16)
-#define __NR_POSIX_sbreak (__NR_POSIX + 17)
-#define __NR_POSIX_stat (__NR_POSIX + 18)
-#define __NR_POSIX_lseek (__NR_POSIX + 19)
-#define __NR_POSIX_getpid (__NR_POSIX + 20)
-#define __NR_POSIX_mount (__NR_POSIX + 21)
-#define __NR_POSIX_umount (__NR_POSIX + 22)
-#define __NR_POSIX_setuid (__NR_POSIX + 23)
-#define __NR_POSIX_getuid (__NR_POSIX + 24)
-#define __NR_POSIX_stime (__NR_POSIX + 25)
-#define __NR_POSIX_ptrace (__NR_POSIX + 26)
-#define __NR_POSIX_alarm (__NR_POSIX + 27)
-#define __NR_POSIX_fstat (__NR_POSIX + 28)
-#define __NR_POSIX_pause (__NR_POSIX + 29)
-#define __NR_POSIX_utime (__NR_POSIX + 30)
-#define __NR_POSIX_stty (__NR_POSIX + 31)
-#define __NR_POSIX_gtty (__NR_POSIX + 32)
-#define __NR_POSIX_access (__NR_POSIX + 33)
-#define __NR_POSIX_nice (__NR_POSIX + 34)
-#define __NR_POSIX_statfs (__NR_POSIX + 35)
-#define __NR_POSIX_sync (__NR_POSIX + 36)
-#define __NR_POSIX_kill (__NR_POSIX + 37)
-#define __NR_POSIX_fstatfs (__NR_POSIX + 38)
-#define __NR_POSIX_getpgrp (__NR_POSIX + 39)
-#define __NR_POSIX_syssgi (__NR_POSIX + 40)
-#define __NR_POSIX_dup (__NR_POSIX + 41)
-#define __NR_POSIX_pipe (__NR_POSIX + 42)
-#define __NR_POSIX_times (__NR_POSIX + 43)
-#define __NR_POSIX_profil (__NR_POSIX + 44)
-#define __NR_POSIX_lock (__NR_POSIX + 45)
-#define __NR_POSIX_setgid (__NR_POSIX + 46)
-#define __NR_POSIX_getgid (__NR_POSIX + 47)
-#define __NR_POSIX_sig (__NR_POSIX + 48)
-#define __NR_POSIX_msgsys (__NR_POSIX + 49)
-#define __NR_POSIX_sysmips (__NR_POSIX + 50)
-#define __NR_POSIX_sysacct (__NR_POSIX + 51)
-#define __NR_POSIX_shmsys (__NR_POSIX + 52)
-#define __NR_POSIX_semsys (__NR_POSIX + 53)
-#define __NR_POSIX_ioctl (__NR_POSIX + 54)
-#define __NR_POSIX_uadmin (__NR_POSIX + 55)
-#define __NR_POSIX_exch (__NR_POSIX + 56)
-#define __NR_POSIX_utssys (__NR_POSIX + 57)
-#define __NR_POSIX_USG_reserved1 (__NR_POSIX + 58)
-#define __NR_POSIX_exece (__NR_POSIX + 59)
-#define __NR_POSIX_umask (__NR_POSIX + 60)
-#define __NR_POSIX_chroot (__NR_POSIX + 61)
-#define __NR_POSIX_fcntl (__NR_POSIX + 62)
-#define __NR_POSIX_ulimit (__NR_POSIX + 63)
-#define __NR_POSIX_SAFARI4_reserved1 (__NR_POSIX + 64)
-#define __NR_POSIX_SAFARI4_reserved2 (__NR_POSIX + 65)
-#define __NR_POSIX_SAFARI4_reserved3 (__NR_POSIX + 66)
-#define __NR_POSIX_SAFARI4_reserved4 (__NR_POSIX + 67)
-#define __NR_POSIX_SAFARI4_reserved5 (__NR_POSIX + 68)
-#define __NR_POSIX_SAFARI4_reserved6 (__NR_POSIX + 69)
-#define __NR_POSIX_advfs (__NR_POSIX + 70)
-#define __NR_POSIX_unadvfs (__NR_POSIX + 71)
-#define __NR_POSIX_rmount (__NR_POSIX + 72)
-#define __NR_POSIX_rumount (__NR_POSIX + 73)
-#define __NR_POSIX_rfstart (__NR_POSIX + 74)
-#define __NR_POSIX_reserved1 (__NR_POSIX + 75)
-#define __NR_POSIX_rdebug (__NR_POSIX + 76)
-#define __NR_POSIX_rfstop (__NR_POSIX + 77)
-#define __NR_POSIX_rfsys (__NR_POSIX + 78)
-#define __NR_POSIX_rmdir (__NR_POSIX + 79)
-#define __NR_POSIX_mkdir (__NR_POSIX + 80)
-#define __NR_POSIX_getdents (__NR_POSIX + 81)
-#define __NR_POSIX_sginap (__NR_POSIX + 82)
-#define __NR_POSIX_sgikopt (__NR_POSIX + 83)
-#define __NR_POSIX_sysfs (__NR_POSIX + 84)
-#define __NR_POSIX_getmsg (__NR_POSIX + 85)
-#define __NR_POSIX_putmsg (__NR_POSIX + 86)
-#define __NR_POSIX_poll (__NR_POSIX + 87)
-#define __NR_POSIX_sigreturn (__NR_POSIX + 88)
-#define __NR_POSIX_accept (__NR_POSIX + 89)
-#define __NR_POSIX_bind (__NR_POSIX + 90)
-#define __NR_POSIX_connect (__NR_POSIX + 91)
-#define __NR_POSIX_gethostid (__NR_POSIX + 92)
-#define __NR_POSIX_getpeername (__NR_POSIX + 93)
-#define __NR_POSIX_getsockname (__NR_POSIX + 94)
-#define __NR_POSIX_getsockopt (__NR_POSIX + 95)
-#define __NR_POSIX_listen (__NR_POSIX + 96)
-#define __NR_POSIX_recv (__NR_POSIX + 97)
-#define __NR_POSIX_recvfrom (__NR_POSIX + 98)
-#define __NR_POSIX_recvmsg (__NR_POSIX + 99)
-#define __NR_POSIX_select (__NR_POSIX + 100)
-#define __NR_POSIX_send (__NR_POSIX + 101)
-#define __NR_POSIX_sendmsg (__NR_POSIX + 102)
-#define __NR_POSIX_sendto (__NR_POSIX + 103)
-#define __NR_POSIX_sethostid (__NR_POSIX + 104)
-#define __NR_POSIX_setsockopt (__NR_POSIX + 105)
-#define __NR_POSIX_shutdown (__NR_POSIX + 106)
-#define __NR_POSIX_socket (__NR_POSIX + 107)
-#define __NR_POSIX_gethostname (__NR_POSIX + 108)
-#define __NR_POSIX_sethostname (__NR_POSIX + 109)
-#define __NR_POSIX_getdomainname (__NR_POSIX + 110)
-#define __NR_POSIX_setdomainname (__NR_POSIX + 111)
-#define __NR_POSIX_truncate (__NR_POSIX + 112)
-#define __NR_POSIX_ftruncate (__NR_POSIX + 113)
-#define __NR_POSIX_rename (__NR_POSIX + 114)
-#define __NR_POSIX_symlink (__NR_POSIX + 115)
-#define __NR_POSIX_readlink (__NR_POSIX + 116)
-#define __NR_POSIX_lstat (__NR_POSIX + 117)
-#define __NR_POSIX_nfs_mount (__NR_POSIX + 118)
-#define __NR_POSIX_nfs_svc (__NR_POSIX + 119)
-#define __NR_POSIX_nfs_getfh (__NR_POSIX + 120)
-#define __NR_POSIX_async_daemon (__NR_POSIX + 121)
-#define __NR_POSIX_exportfs (__NR_POSIX + 122)
-#define __NR_POSIX_SGI_setregid (__NR_POSIX + 123)
-#define __NR_POSIX_SGI_setreuid (__NR_POSIX + 124)
-#define __NR_POSIX_getitimer (__NR_POSIX + 125)
-#define __NR_POSIX_setitimer (__NR_POSIX + 126)
-#define __NR_POSIX_adjtime (__NR_POSIX + 127)
-#define __NR_POSIX_SGI_bsdgettime (__NR_POSIX + 128)
-#define __NR_POSIX_SGI_sproc (__NR_POSIX + 129)
-#define __NR_POSIX_SGI_prctl (__NR_POSIX + 130)
-#define __NR_POSIX_SGI_blkproc (__NR_POSIX + 131)
-#define __NR_POSIX_SGI_reserved1 (__NR_POSIX + 132)
-#define __NR_POSIX_SGI_sgigsc (__NR_POSIX + 133)
-#define __NR_POSIX_SGI_mmap (__NR_POSIX + 134)
-#define __NR_POSIX_SGI_munmap (__NR_POSIX + 135)
-#define __NR_POSIX_SGI_mprotect (__NR_POSIX + 136)
-#define __NR_POSIX_SGI_msync (__NR_POSIX + 137)
-#define __NR_POSIX_SGI_madvise (__NR_POSIX + 138)
-#define __NR_POSIX_SGI_mpin (__NR_POSIX + 139)
-#define __NR_POSIX_SGI_getpagesize (__NR_POSIX + 140)
-#define __NR_POSIX_SGI_libattach (__NR_POSIX + 141)
-#define __NR_POSIX_SGI_libdetach (__NR_POSIX + 142)
-#define __NR_POSIX_SGI_getpgrp (__NR_POSIX + 143)
-#define __NR_POSIX_SGI_setpgrp (__NR_POSIX + 144)
-#define __NR_POSIX_SGI_reserved2 (__NR_POSIX + 145)
-#define __NR_POSIX_SGI_reserved3 (__NR_POSIX + 146)
-#define __NR_POSIX_SGI_reserved4 (__NR_POSIX + 147)
-#define __NR_POSIX_SGI_reserved5 (__NR_POSIX + 148)
-#define __NR_POSIX_SGI_reserved6 (__NR_POSIX + 149)
-#define __NR_POSIX_cacheflush (__NR_POSIX + 150)
-#define __NR_POSIX_cachectl (__NR_POSIX + 151)
-#define __NR_POSIX_fchown (__NR_POSIX + 152)
-#define __NR_POSIX_fchmod (__NR_POSIX + 153)
-#define __NR_POSIX_wait3 (__NR_POSIX + 154)
-#define __NR_POSIX_mmap (__NR_POSIX + 155)
-#define __NR_POSIX_munmap (__NR_POSIX + 156)
-#define __NR_POSIX_madvise (__NR_POSIX + 157)
-#define __NR_POSIX_BSD_getpagesize (__NR_POSIX + 158)
-#define __NR_POSIX_setreuid (__NR_POSIX + 159)
-#define __NR_POSIX_setregid (__NR_POSIX + 160)
-#define __NR_POSIX_setpgid (__NR_POSIX + 161)
-#define __NR_POSIX_getgroups (__NR_POSIX + 162)
-#define __NR_POSIX_setgroups (__NR_POSIX + 163)
-#define __NR_POSIX_gettimeofday (__NR_POSIX + 164)
-#define __NR_POSIX_getrusage (__NR_POSIX + 165)
-#define __NR_POSIX_getrlimit (__NR_POSIX + 166)
-#define __NR_POSIX_setrlimit (__NR_POSIX + 167)
-#define __NR_POSIX_waitpid (__NR_POSIX + 168)
-#define __NR_POSIX_dup2 (__NR_POSIX + 169)
-#define __NR_POSIX_reserved2 (__NR_POSIX + 170)
-#define __NR_POSIX_reserved3 (__NR_POSIX + 171)
-#define __NR_POSIX_reserved4 (__NR_POSIX + 172)
-#define __NR_POSIX_reserved5 (__NR_POSIX + 173)
-#define __NR_POSIX_reserved6 (__NR_POSIX + 174)
-#define __NR_POSIX_reserved7 (__NR_POSIX + 175)
-#define __NR_POSIX_reserved8 (__NR_POSIX + 176)
-#define __NR_POSIX_reserved9 (__NR_POSIX + 177)
-#define __NR_POSIX_reserved10 (__NR_POSIX + 178)
-#define __NR_POSIX_reserved11 (__NR_POSIX + 179)
-#define __NR_POSIX_reserved12 (__NR_POSIX + 180)
-#define __NR_POSIX_reserved13 (__NR_POSIX + 181)
-#define __NR_POSIX_reserved14 (__NR_POSIX + 182)
-#define __NR_POSIX_reserved15 (__NR_POSIX + 183)
-#define __NR_POSIX_reserved16 (__NR_POSIX + 184)
-#define __NR_POSIX_reserved17 (__NR_POSIX + 185)
-#define __NR_POSIX_reserved18 (__NR_POSIX + 186)
-#define __NR_POSIX_reserved19 (__NR_POSIX + 187)
-#define __NR_POSIX_reserved20 (__NR_POSIX + 188)
-#define __NR_POSIX_reserved21 (__NR_POSIX + 189)
-#define __NR_POSIX_reserved22 (__NR_POSIX + 190)
-#define __NR_POSIX_reserved23 (__NR_POSIX + 191)
-#define __NR_POSIX_reserved24 (__NR_POSIX + 192)
-#define __NR_POSIX_reserved25 (__NR_POSIX + 193)
-#define __NR_POSIX_reserved26 (__NR_POSIX + 194)
-#define __NR_POSIX_reserved27 (__NR_POSIX + 195)
-#define __NR_POSIX_reserved28 (__NR_POSIX + 196)
-#define __NR_POSIX_reserved29 (__NR_POSIX + 197)
-#define __NR_POSIX_reserved30 (__NR_POSIX + 198)
-#define __NR_POSIX_reserved31 (__NR_POSIX + 199)
-#define __NR_POSIX_reserved32 (__NR_POSIX + 200)
-#define __NR_POSIX_reserved33 (__NR_POSIX + 201)
-#define __NR_POSIX_reserved34 (__NR_POSIX + 202)
-#define __NR_POSIX_reserved35 (__NR_POSIX + 203)
-#define __NR_POSIX_reserved36 (__NR_POSIX + 204)
-#define __NR_POSIX_reserved37 (__NR_POSIX + 205)
-#define __NR_POSIX_reserved38 (__NR_POSIX + 206)
-#define __NR_POSIX_reserved39 (__NR_POSIX + 207)
-#define __NR_POSIX_reserved40 (__NR_POSIX + 208)
-#define __NR_POSIX_reserved41 (__NR_POSIX + 209)
-#define __NR_POSIX_reserved42 (__NR_POSIX + 210)
-#define __NR_POSIX_reserved43 (__NR_POSIX + 211)
-#define __NR_POSIX_reserved44 (__NR_POSIX + 212)
-#define __NR_POSIX_reserved45 (__NR_POSIX + 213)
-#define __NR_POSIX_reserved46 (__NR_POSIX + 214)
-#define __NR_POSIX_reserved47 (__NR_POSIX + 215)
-#define __NR_POSIX_reserved48 (__NR_POSIX + 216)
-#define __NR_POSIX_reserved49 (__NR_POSIX + 217)
-#define __NR_POSIX_reserved50 (__NR_POSIX + 218)
-#define __NR_POSIX_reserved51 (__NR_POSIX + 219)
-#define __NR_POSIX_reserved52 (__NR_POSIX + 220)
-#define __NR_POSIX_reserved53 (__NR_POSIX + 221)
-#define __NR_POSIX_reserved54 (__NR_POSIX + 222)
-#define __NR_POSIX_reserved55 (__NR_POSIX + 223)
-#define __NR_POSIX_reserved56 (__NR_POSIX + 224)
-#define __NR_POSIX_reserved57 (__NR_POSIX + 225)
-#define __NR_POSIX_reserved58 (__NR_POSIX + 226)
-#define __NR_POSIX_reserved59 (__NR_POSIX + 227)
-#define __NR_POSIX_reserved60 (__NR_POSIX + 228)
-#define __NR_POSIX_reserved61 (__NR_POSIX + 229)
-#define __NR_POSIX_reserved62 (__NR_POSIX + 230)
-#define __NR_POSIX_reserved63 (__NR_POSIX + 231)
-#define __NR_POSIX_reserved64 (__NR_POSIX + 232)
-#define __NR_POSIX_reserved65 (__NR_POSIX + 233)
-#define __NR_POSIX_reserved66 (__NR_POSIX + 234)
-#define __NR_POSIX_reserved67 (__NR_POSIX + 235)
-#define __NR_POSIX_reserved68 (__NR_POSIX + 236)
-#define __NR_POSIX_reserved69 (__NR_POSIX + 237)
-#define __NR_POSIX_reserved70 (__NR_POSIX + 238)
-#define __NR_POSIX_reserved71 (__NR_POSIX + 239)
-#define __NR_POSIX_reserved72 (__NR_POSIX + 240)
-#define __NR_POSIX_reserved73 (__NR_POSIX + 241)
-#define __NR_POSIX_reserved74 (__NR_POSIX + 242)
-#define __NR_POSIX_reserved75 (__NR_POSIX + 243)
-#define __NR_POSIX_reserved76 (__NR_POSIX + 244)
-#define __NR_POSIX_reserved77 (__NR_POSIX + 245)
-#define __NR_POSIX_reserved78 (__NR_POSIX + 246)
-#define __NR_POSIX_reserved79 (__NR_POSIX + 247)
-#define __NR_POSIX_reserved80 (__NR_POSIX + 248)
-#define __NR_POSIX_reserved81 (__NR_POSIX + 249)
-#define __NR_POSIX_reserved82 (__NR_POSIX + 250)
-#define __NR_POSIX_reserved83 (__NR_POSIX + 251)
-#define __NR_POSIX_reserved84 (__NR_POSIX + 252)
-#define __NR_POSIX_reserved85 (__NR_POSIX + 253)
-#define __NR_POSIX_reserved86 (__NR_POSIX + 254)
-#define __NR_POSIX_reserved87 (__NR_POSIX + 255)
-#define __NR_POSIX_reserved88 (__NR_POSIX + 256)
-#define __NR_POSIX_reserved89 (__NR_POSIX + 257)
-#define __NR_POSIX_reserved90 (__NR_POSIX + 258)
-#define __NR_POSIX_reserved91 (__NR_POSIX + 259)
-#define __NR_POSIX_netboot (__NR_POSIX + 260)
-#define __NR_POSIX_netunboot (__NR_POSIX + 261)
-#define __NR_POSIX_rdump (__NR_POSIX + 262)
-#define __NR_POSIX_setsid (__NR_POSIX + 263)
-#define __NR_POSIX_getmaxsig (__NR_POSIX + 264)
-#define __NR_POSIX_sigpending (__NR_POSIX + 265)
-#define __NR_POSIX_sigprocmask (__NR_POSIX + 266)
-#define __NR_POSIX_sigsuspend (__NR_POSIX + 267)
-#define __NR_POSIX_sigaction (__NR_POSIX + 268)
-#define __NR_POSIX_MIPS_reserved1 (__NR_POSIX + 269)
-#define __NR_POSIX_MIPS_reserved2 (__NR_POSIX + 270)
-#define __NR_POSIX_MIPS_reserved3 (__NR_POSIX + 271)
-#define __NR_POSIX_MIPS_reserved4 (__NR_POSIX + 272)
-#define __NR_POSIX_MIPS_reserved5 (__NR_POSIX + 273)
-#define __NR_POSIX_MIPS_reserved6 (__NR_POSIX + 274)
-#define __NR_POSIX_MIPS_reserved7 (__NR_POSIX + 275)
-#define __NR_POSIX_MIPS_reserved8 (__NR_POSIX + 276)
-#define __NR_POSIX_MIPS_reserved9 (__NR_POSIX + 277)
-#define __NR_POSIX_MIPS_reserved10 (__NR_POSIX + 278)
-#define __NR_POSIX_MIPS_reserved11 (__NR_POSIX + 279)
-#define __NR_POSIX_TANDEM_reserved1 (__NR_POSIX + 280)
-#define __NR_POSIX_TANDEM_reserved2 (__NR_POSIX + 281)
-#define __NR_POSIX_TANDEM_reserved3 (__NR_POSIX + 282)
-#define __NR_POSIX_TANDEM_reserved4 (__NR_POSIX + 283)
-#define __NR_POSIX_TANDEM_reserved5 (__NR_POSIX + 284)
-#define __NR_POSIX_TANDEM_reserved6 (__NR_POSIX + 285)
-#define __NR_POSIX_TANDEM_reserved7 (__NR_POSIX + 286)
-#define __NR_POSIX_TANDEM_reserved8 (__NR_POSIX + 287)
-#define __NR_POSIX_TANDEM_reserved9 (__NR_POSIX + 288)
-#define __NR_POSIX_TANDEM_reserved10 (__NR_POSIX + 289)
-#define __NR_POSIX_TANDEM_reserved11 (__NR_POSIX + 290)
-#define __NR_POSIX_TANDEM_reserved12 (__NR_POSIX + 291)
-#define __NR_POSIX_TANDEM_reserved13 (__NR_POSIX + 292)
-#define __NR_POSIX_TANDEM_reserved14 (__NR_POSIX + 293)
-#define __NR_POSIX_TANDEM_reserved15 (__NR_POSIX + 294)
-#define __NR_POSIX_TANDEM_reserved16 (__NR_POSIX + 295)
-#define __NR_POSIX_TANDEM_reserved17 (__NR_POSIX + 296)
-#define __NR_POSIX_TANDEM_reserved18 (__NR_POSIX + 297)
-#define __NR_POSIX_TANDEM_reserved19 (__NR_POSIX + 298)
-#define __NR_POSIX_TANDEM_reserved20 (__NR_POSIX + 299)
-#define __NR_POSIX_SGI_reserved7 (__NR_POSIX + 300)
-#define __NR_POSIX_SGI_reserved8 (__NR_POSIX + 301)
-#define __NR_POSIX_SGI_reserved9 (__NR_POSIX + 302)
-#define __NR_POSIX_SGI_reserved10 (__NR_POSIX + 303)
-#define __NR_POSIX_SGI_reserved11 (__NR_POSIX + 304)
-#define __NR_POSIX_SGI_reserved12 (__NR_POSIX + 305)
-#define __NR_POSIX_SGI_reserved13 (__NR_POSIX + 306)
-#define __NR_POSIX_SGI_reserved14 (__NR_POSIX + 307)
-#define __NR_POSIX_SGI_reserved15 (__NR_POSIX + 308)
-#define __NR_POSIX_SGI_reserved16 (__NR_POSIX + 309)
-#define __NR_POSIX_SGI_reserved17 (__NR_POSIX + 310)
-#define __NR_POSIX_SGI_reserved18 (__NR_POSIX + 311)
-#define __NR_POSIX_SGI_reserved19 (__NR_POSIX + 312)
-#define __NR_POSIX_SGI_reserved20 (__NR_POSIX + 313)
-#define __NR_POSIX_SGI_reserved21 (__NR_POSIX + 314)
-#define __NR_POSIX_SGI_reserved22 (__NR_POSIX + 315)
-#define __NR_POSIX_SGI_reserved23 (__NR_POSIX + 316)
-#define __NR_POSIX_SGI_reserved24 (__NR_POSIX + 317)
-#define __NR_POSIX_SGI_reserved25 (__NR_POSIX + 318)
-#define __NR_POSIX_SGI_reserved26 (__NR_POSIX + 319)
-
-#endif /* _ASM_RISCOS_SYSCALL_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 330c4e497af3..e8e5d4143377 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -159,11 +159,21 @@ struct task_struct;
do { \
if (cpu_has_dsp) \
__save_dsp(prev); \
- (last) = resume(prev, next, next->thread_info); \
+ (last) = resume(prev, next, task_thread_info(next)); \
if (cpu_has_dsp) \
__restore_dsp(current); \
} while(0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
{
__u32 retval;
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index e6c24472e03f..1612b3fe1080 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -97,8 +97,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
#endif
#define free_thread_info(info) kfree(info)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-mips/vr41xx/capcella.h b/include/asm-mips/vr41xx/capcella.h
index 5b55083c5281..d10ffda50de7 100644
--- a/include/asm-mips/vr41xx/capcella.h
+++ b/include/asm-mips/vr41xx/capcella.h
@@ -1,7 +1,7 @@
/*
* capcella.h, Include file for ZAO Networks Capcella.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/e55.h b/include/asm-mips/vr41xx/e55.h
index ea37b56fc66d..558f2269bf37 100644
--- a/include/asm-mips/vr41xx/e55.h
+++ b/include/asm-mips/vr41xx/e55.h
@@ -1,7 +1,7 @@
/*
* e55.h, Include file for CASIO CASSIOPEIA E-10/15/55/65.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
index 8590885a7638..8109cda557dc 100644
--- a/include/asm-mips/vr41xx/giu.h
+++ b/include/asm-mips/vr41xx/giu.h
@@ -1,7 +1,7 @@
/*
* Include file for NEC VR4100 series General-purpose I/O Unit.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/mpc30x.h b/include/asm-mips/vr41xx/mpc30x.h
index e6ac3c8e8bae..a6cbe4da6667 100644
--- a/include/asm-mips/vr41xx/mpc30x.h
+++ b/include/asm-mips/vr41xx/mpc30x.h
@@ -1,7 +1,7 @@
/*
* mpc30x.h, Include file for Victor MP-C303/304.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/pci.h b/include/asm-mips/vr41xx/pci.h
index c473aa78d1d4..6fc01ce19777 100644
--- a/include/asm-mips/vr41xx/pci.h
+++ b/include/asm-mips/vr41xx/pci.h
@@ -1,7 +1,7 @@
/*
* Include file for NEC VR4100 series PCI Control Unit.
*
- * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
index 865cc07ddd7f..1fcf6e8082b4 100644
--- a/include/asm-mips/vr41xx/siu.h
+++ b/include/asm-mips/vr41xx/siu.h
@@ -1,7 +1,7 @@
/*
* Include file for NEC VR4100 series Serial Interface Unit.
*
- * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/tb0219.h b/include/asm-mips/vr41xx/tb0219.h
index 273c6392688f..b318b9612a83 100644
--- a/include/asm-mips/vr41xx/tb0219.h
+++ b/include/asm-mips/vr41xx/tb0219.h
@@ -1,7 +1,7 @@
/*
* tb0219.h, Include file for TANBAC TB0219.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* Modified for TANBAC TB0219:
* Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp>
diff --git a/include/asm-mips/vr41xx/tb0226.h b/include/asm-mips/vr41xx/tb0226.h
index 0ff9a60ecacc..2513f450e2d6 100644
--- a/include/asm-mips/vr41xx/tb0226.h
+++ b/include/asm-mips/vr41xx/tb0226.h
@@ -1,7 +1,7 @@
/*
* tb0226.h, Include file for TANBAC TB0226.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index bd2723c30901..70828d5fae9c 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-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
diff --git a/include/asm-mips/vr41xx/vrc4173.h b/include/asm-mips/vr41xx/vrc4173.h
index bb7a85c186e4..4d41a9c091d4 100644
--- a/include/asm-mips/vr41xx/vrc4173.h
+++ b/include/asm-mips/vr41xx/vrc4173.h
@@ -4,7 +4,7 @@
* Copyright (C) 2000 Michael R. McDonald
* Copyright (C) 2001-2003 Montavista Software Inc.
* Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
* Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-mips/vr41xx/workpad.h b/include/asm-mips/vr41xx/workpad.h
index dfe01b43fb79..6bfa9c009a9b 100644
--- a/include/asm-mips/vr41xx/workpad.h
+++ b/include/asm-mips/vr41xx/workpad.h
@@ -1,7 +1,7 @@
/*
* workpad.h, Include file for IBM WorkPad z50.
*
- * Copyright (C) 2002-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2002-2004 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index 983e9a2b6042..2ca56d34aaad 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -165,6 +165,7 @@ static __inline__ int atomic_read(const atomic_t *v)
/* exported interface */
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -216,4 +217,5 @@ static __inline__ int atomic_read(const atomic_t *v)
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
+#include <asm-generic/atomic.h>
#endif
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 55b98c67fd82..15d8c2b51584 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -263,6 +263,7 @@ static __inline__ int fls(int x)
return ret;
}
+#define fls64(x) generic_fls64(x)
/*
* hweightN: returns the hamming weight (i.e. the number
diff --git a/include/asm-parisc/cache.h b/include/asm-parisc/cache.h
index 5da72e38bdde..93f179f13ce8 100644
--- a/include/asm-parisc/cache.h
+++ b/include/asm-parisc/cache.h
@@ -28,16 +28,15 @@
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX 5 /* largest L1 which this arch supports */
-extern void flush_data_cache_local(void); /* flushes local data-cache only */
-extern void flush_instruction_cache_local(void); /* flushes local code-cache only */
+extern void flush_data_cache_local(void *); /* flushes local data-cache only */
+extern void flush_instruction_cache_local(void *); /* flushes local code-cache only */
#ifdef CONFIG_SMP
extern void flush_data_cache(void); /* flushes data-cache only (all processors) */
extern void flush_instruction_cache(void); /* flushes i-cache only (all processors) */
#else
-#define flush_data_cache flush_data_cache_local
-#define flush_instruction_cache flush_instruction_cache_local
+#define flush_data_cache() flush_data_cache_local(NULL)
+#define flush_instruction_cache() flush_instruction_cache_local(NULL)
#endif
extern void parisc_cache_init(void); /* initializes cache-flushing */
diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-parisc/futex.h
+++ b/include/asm-parisc/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-parisc/io.h b/include/asm-parisc/io.h
index b9bb5946ecc9..0db00adc942a 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -41,7 +41,7 @@ extern void __raw_bad_addr(const volatile void __iomem *addr);
#define __raw_check_addr(addr) \
if (((unsigned long)addr >> NYBBLE_SHIFT) != 0xe) \
__raw_bad_addr(addr); \
- addr = (void *)((unsigned long)addr | (0xfUL << NYBBLE_SHIFT));
+ addr = (void __iomem *)((unsigned long)addr | (0xfUL << NYBBLE_SHIFT));
#else
#define gsc_check_addr(addr)
#define __raw_check_addr(addr)
diff --git a/include/asm-parisc/mman.h b/include/asm-parisc/mman.h
index e829607eb8bc..736b0abcac05 100644
--- a/include/asm-parisc/mman.h
+++ b/include/asm-parisc/mman.h
@@ -38,6 +38,7 @@
#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */
#define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */
#define MADV_VPS_INHERIT 7 /* Inherit parents page size */
+#define MADV_REMOVE 8 /* remove these pages & resources */
/* The range 12-64 is reserved for page size specification. */
#define MADV_4K_PAGES 12 /* Use 4K pages */
diff --git a/include/asm-parisc/mutex.h b/include/asm-parisc/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-parisc/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index 44eae9f8274d..4a6752b0afed 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -135,6 +135,13 @@ extern int npmem_ranges;
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#endif /* CONFIG_DISCONTIGMEM */
+#ifdef CONFIG_HUGETLB_PAGE
+#define HPAGE_SHIFT 22 /* 4MB (is this fixed?) */
+#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#endif
+
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index fa39d07d49e9..f277254159b7 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -84,11 +84,17 @@ static __inline__ int pci_is_lmmio(struct pci_hba_data *hba, unsigned long a)
/*
** Convert between PCI (IO_VIEW) addresses and processor (PA_VIEW) addresses.
** See pcibios.c for more conversions used by Generic PCI code.
+**
+** Platform characteristics/firmware guarantee that
+** (1) PA_VIEW - IO_VIEW = lmmio_offset for both LMMIO and ELMMIO
+** (2) PA_VIEW == IO_VIEW for GMMIO
*/
#define PCI_BUS_ADDR(hba,a) (PCI_IS_LMMIO(hba,a) \
? ((a) - hba->lmmio_space_offset) /* mangle LMMIO */ \
: (a)) /* GMMIO */
-#define PCI_HOST_ADDR(hba,a) ((a) + hba->lmmio_space_offset)
+#define PCI_HOST_ADDR(hba,a) (((a) & PCI_F_EXTEND) == 0 \
+ ? (a) + hba->lmmio_space_offset \
+ : (a))
#else /* !CONFIG_64BIT */
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index aae40e8c3aa8..89f2f1c16c12 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -144,16 +144,16 @@ struct thread_struct {
})
#define INIT_THREAD { \
- regs: { gr: { 0, }, \
- fr: { 0, }, \
- sr: { 0, }, \
- iasq: { 0, }, \
- iaoq: { 0, }, \
- cr27: 0, \
+ .regs = { .gr = { 0, }, \
+ .fr = { 0, }, \
+ .sr = { 0, }, \
+ .iasq = { 0, }, \
+ .iaoq = { 0, }, \
+ .cr27 = 0, \
}, \
- task_size: DEFAULT_TASK_SIZE, \
- map_base: DEFAULT_MAP_BASE, \
- flags: 0 \
+ .task_size = DEFAULT_TASK_SIZE, \
+ .map_base = DEFAULT_MAP_BASE, \
+ .flags = 0 \
}
/*
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index f3928d3a80cb..a5a973c0c07f 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -49,6 +49,15 @@ extern struct task_struct *_switch_to(struct task_struct *, struct task_struct *
(last) = _switch_to(prev, next); \
} while(0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
/* interrupt control */
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index 57bbb76cb6c1..ac32f140b83a 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -43,9 +43,6 @@ struct thread_info {
#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
/* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *)mfctl(30))
diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
index c9ec39c6fc6c..825994a90e2d 100644
--- a/include/asm-parisc/tlbflush.h
+++ b/include/asm-parisc/tlbflush.h
@@ -22,6 +22,7 @@ extern spinlock_t pa_tlb_lock;
#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
extern void flush_tlb_all(void);
+extern void flush_tlb_all_local(void *);
/*
* flush_tlb_mm()
diff --git a/include/asm-powerpc/abs_addr.h b/include/asm-powerpc/abs_addr.h
index 18415108fc56..c5c3259e0f86 100644
--- a/include/asm-powerpc/abs_addr.h
+++ b/include/asm-powerpc/abs_addr.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_ABS_ADDR_H
#define _ASM_POWERPC_ABS_ADDR_H
+#ifdef __KERNEL__
#include <linux/config.h>
@@ -70,4 +71,5 @@ static inline unsigned long phys_to_abs(unsigned long pa)
#define iseries_hv_addr(virtaddr) \
(0x8000000000000000 | virt_to_abs(virtaddr))
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_ABS_ADDR_H */
diff --git a/include/asm-powerpc/agp.h b/include/asm-powerpc/agp.h
index 885b4631a6cf..e5ccaca2f5a4 100644
--- a/include/asm-powerpc/agp.h
+++ b/include/asm-powerpc/agp.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_AGP_H
#define _ASM_POWERPC_AGP_H
+#ifdef __KERNEL__
#include <asm/io.h>
@@ -18,4 +19,5 @@
#define free_gatt_pages(table, order) \
free_pages((unsigned long)(table), (order))
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_AGP_H */
diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h
index 8b133efc9f79..8e64be0cc47d 100644
--- a/include/asm-powerpc/asm-compat.h
+++ b/include/asm-powerpc/asm-compat.h
@@ -1,7 +1,6 @@
#ifndef _ASM_POWERPC_ASM_COMPAT_H
#define _ASM_POWERPC_ASM_COMPAT_H
-#include <linux/config.h>
#include <asm/types.h>
#ifdef __ASSEMBLY__
@@ -41,6 +40,7 @@
#endif
+#ifdef __KERNEL__
#ifdef CONFIG_IBM405_ERR77
/* Erratum #77 on the 405 means we need a sync or dcbt before every
* stwcx. The old ATOMIC_SYNC_FIX covered some but not all of this.
@@ -51,5 +51,6 @@
#define PPC405_ERR77(ra,rb)
#define PPC405_ERR77_SYNC
#endif
+#endif
#endif /* _ASM_POWERPC_ASM_COMPAT_H */
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index ec4b14468959..147a38dcc766 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -36,7 +36,7 @@ static __inline__ int atomic_add_return(int a, atomic_t *v)
int t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%2 # atomic_add_return\n\
add %0,%1,%0\n"
PPC405_ERR77(0,%2)
@@ -72,7 +72,7 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v)
int t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%2 # atomic_sub_return\n\
subf %0,%1,%0\n"
PPC405_ERR77(0,%2)
@@ -106,7 +106,7 @@ static __inline__ int atomic_inc_return(atomic_t *v)
int t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%1 # atomic_inc_return\n\
addic %0,%0,1\n"
PPC405_ERR77(0,%1)
@@ -150,7 +150,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
int t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%1 # atomic_dec_return\n\
addic %0,%0,-1\n"
PPC405_ERR77(0,%1)
@@ -165,6 +165,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
}
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -175,19 +176,19 @@ static __inline__ int atomic_dec_return(atomic_t *v)
* Atomically adds @a to @v, so long as it was not @u.
* Returns non-zero if @v was not @u, and zero otherwise.
*/
-#define atomic_add_unless(v, a, u) \
-({ \
- int c, old; \
- c = atomic_read(v); \
- for (;;) { \
- if (unlikely(c == (u))) \
- break; \
- old = atomic_cmpxchg((v), c, c + (a)); \
- if (likely(old == c)) \
- break; \
- c = old; \
- } \
- c != (u); \
+#define atomic_add_unless(v, a, u) \
+({ \
+ int c, old; \
+ c = atomic_read(v); \
+ for (;;) { \
+ if (unlikely(c == (u))) \
+ break; \
+ old = atomic_cmpxchg((v), c, c + (a)); \
+ if (likely(old == c)) \
+ break; \
+ c = old; \
+ } \
+ c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
@@ -203,7 +204,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
int t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\
addic. %0,%0,-1\n\
blt- 2f\n"
@@ -252,7 +253,7 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v)
long t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%2 # atomic64_add_return\n\
add %0,%1,%0\n\
stdcx. %0,0,%2 \n\
@@ -286,7 +287,7 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v)
long t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%2 # atomic64_sub_return\n\
subf %0,%1,%0\n\
stdcx. %0,0,%2 \n\
@@ -318,7 +319,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
long t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%1 # atomic64_inc_return\n\
addic %0,%0,1\n\
stdcx. %0,0,%1 \n\
@@ -360,7 +361,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v)
long t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%1 # atomic64_dec_return\n\
addic %0,%0,-1\n\
stdcx. %0,0,%1\n\
@@ -385,7 +386,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
long t;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%1 # atomic64_dec_if_positive\n\
addic. %0,%0,-1\n\
blt- 2f\n\
@@ -402,5 +403,6 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
#endif /* __powerpc64__ */
+#include <asm-generic/atomic.h>
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_ATOMIC_H_ */
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index 5727229b0444..bf6941a810b8 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -112,7 +112,7 @@ static __inline__ int test_and_set_bit(unsigned long nr,
unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1:" PPC_LLARX "%0,0,%3 # test_and_set_bit\n"
"or %1,%0,%2 \n"
PPC405_ERR77(0,%3)
@@ -134,7 +134,7 @@ static __inline__ int test_and_clear_bit(unsigned long nr,
unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1:" PPC_LLARX "%0,0,%3 # test_and_clear_bit\n"
"andc %1,%0,%2 \n"
PPC405_ERR77(0,%3)
@@ -156,7 +156,7 @@ static __inline__ int test_and_change_bit(unsigned long nr,
unsigned long *p = ((unsigned long *)addr) + BITOP_WORD(nr);
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1:" PPC_LLARX "%0,0,%3 # test_and_change_bit\n"
"xor %1,%0,%2 \n"
PPC405_ERR77(0,%3)
@@ -310,6 +310,7 @@ static __inline__ int fls(unsigned int x)
asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
return 32 - lz;
}
+#define fls64(x) generic_fls64(x)
/*
* hweightN: returns the hamming weight (i.e. the number
diff --git a/include/asm-powerpc/bootx.h b/include/asm-powerpc/bootx.h
new file mode 100644
index 000000000000..57b82e3f89ce
--- /dev/null
+++ b/include/asm-powerpc/bootx.h
@@ -0,0 +1,171 @@
+/*
+ * This file describes the structure passed from the BootX application
+ * (for MacOS) when it is used to boot Linux.
+ *
+ * Written by Benjamin Herrenschmidt.
+ */
+
+
+#ifndef __ASM_BOOTX_H__
+#define __ASM_BOOTX_H__
+
+#include <asm/types.h>
+
+#ifdef macintosh
+#include <Types.h>
+#include "linux_type_defs.h"
+#endif
+
+#ifdef macintosh
+/* All this requires PowerPC alignment */
+#pragma options align=power
+#endif
+
+/* On kernel entry:
+ *
+ * r3 = 0x426f6f58 ('BooX')
+ * r4 = pointer to boot_infos
+ * r5 = NULL
+ *
+ * Data and instruction translation disabled, interrupts
+ * disabled, kernel loaded at physical 0x00000000 on PCI
+ * machines (will be different on NuBus).
+ */
+
+#define BOOT_INFO_VERSION 5
+#define BOOT_INFO_COMPATIBLE_VERSION 1
+
+/* Bit in the architecture flag mask. More to be defined in
+ future versions. Note that either BOOT_ARCH_PCI or
+ BOOT_ARCH_NUBUS is set. The other BOOT_ARCH_NUBUS_xxx are
+ set additionally when BOOT_ARCH_NUBUS is set.
+ */
+#define BOOT_ARCH_PCI 0x00000001UL
+#define BOOT_ARCH_NUBUS 0x00000002UL
+#define BOOT_ARCH_NUBUS_PDM 0x00000010UL
+#define BOOT_ARCH_NUBUS_PERFORMA 0x00000020UL
+#define BOOT_ARCH_NUBUS_POWERBOOK 0x00000040UL
+
+/* Maximum number of ranges in phys memory map */
+#define MAX_MEM_MAP_SIZE 26
+
+/* This is the format of an element in the physical memory map. Note that
+ the map is optional and current BootX will only build it for pre-PCI
+ machines */
+typedef struct boot_info_map_entry
+{
+ __u32 physAddr; /* Physical starting address */
+ __u32 size; /* Size in bytes */
+} boot_info_map_entry_t;
+
+
+/* Here are the boot informations that are passed to the bootstrap
+ * Note that the kernel arguments and the device tree are appended
+ * at the end of this structure. */
+typedef struct boot_infos
+{
+ /* Version of this structure */
+ __u32 version;
+ /* backward compatible down to version: */
+ __u32 compatible_version;
+
+ /* NEW (vers. 2) this holds the current _logical_ base addr of
+ the frame buffer (for use by early boot message) */
+ __u8* logicalDisplayBase;
+
+ /* NEW (vers. 4) Apple's machine identification */
+ __u32 machineID;
+
+ /* NEW (vers. 4) Detected hw architecture */
+ __u32 architecture;
+
+ /* The device tree (internal addresses relative to the beginning of the tree,
+ * device tree offset relative to the beginning of this structure).
+ * On pre-PCI macintosh (BOOT_ARCH_PCI bit set to 0 in architecture), this
+ * field is 0.
+ */
+ __u32 deviceTreeOffset; /* Device tree offset */
+ __u32 deviceTreeSize; /* Size of the device tree */
+
+ /* Some infos about the current MacOS display */
+ __u32 dispDeviceRect[4]; /* left,top,right,bottom */
+ __u32 dispDeviceDepth; /* (8, 16 or 32) */
+ __u8* dispDeviceBase; /* base address (physical) */
+ __u32 dispDeviceRowBytes; /* rowbytes (in bytes) */
+ __u32 dispDeviceColorsOffset; /* Colormap (8 bits only) or 0 (*) */
+ /* Optional offset in the registry to the current
+ * MacOS display. (Can be 0 when not detected) */
+ __u32 dispDeviceRegEntryOffset;
+
+ /* Optional pointer to boot ramdisk (offset from this structure) */
+ __u32 ramDisk;
+ __u32 ramDiskSize; /* size of ramdisk image */
+
+ /* Kernel command line arguments (offset from this structure) */
+ __u32 kernelParamsOffset;
+
+ /* ALL BELOW NEW (vers. 4) */
+
+ /* This defines the physical memory. Valid with BOOT_ARCH_NUBUS flag
+ (non-PCI) only. On PCI, memory is contiguous and it's size is in the
+ device-tree. */
+ boot_info_map_entry_t
+ physMemoryMap[MAX_MEM_MAP_SIZE]; /* Where the phys memory is */
+ __u32 physMemoryMapSize; /* How many entries in map */
+
+
+ /* The framebuffer size (optional, currently 0) */
+ __u32 frameBufferSize; /* Represents a max size, can be 0. */
+
+ /* NEW (vers. 5) */
+
+ /* Total params size (args + colormap + device tree + ramdisk) */
+ __u32 totalParamsSize;
+
+} boot_infos_t;
+
+#ifdef __KERNEL__
+/* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index
+ * is represented by 3 short words containing a 16 bits (unsigned) color
+ * component. Later versions may contain the gamma table for direct-color
+ * devices here.
+ */
+#define BOOTX_COLORTABLE_SIZE (256UL*3UL*2UL)
+
+/* BootX passes the device-tree using a format that comes from earlier
+ * ppc32 kernels. This used to match what is in prom.h, but not anymore
+ * so we now define it here
+ */
+struct bootx_dt_prop {
+ u32 name;
+ int length;
+ u32 value;
+ u32 next;
+};
+
+struct bootx_dt_node {
+ u32 unused0;
+ u32 unused1;
+ u32 phandle; /* not really available */
+ u32 unused2;
+ u32 unused3;
+ u32 unused4;
+ u32 unused5;
+ u32 full_name;
+ u32 properties;
+ u32 parent;
+ u32 child;
+ u32 sibling;
+ u32 next;
+ u32 allnext;
+};
+
+extern void bootx_init(unsigned long r4, unsigned long phys);
+
+#endif /* __KERNEL__ */
+
+#ifdef macintosh
+#pragma options align=reset
+#endif
+
+#endif
diff --git a/include/asm-powerpc/btext.h b/include/asm-powerpc/btext.h
index 71cce36bc630..906f46e31006 100644
--- a/include/asm-powerpc/btext.h
+++ b/include/asm-powerpc/btext.h
@@ -7,21 +7,22 @@
#define __PPC_BTEXT_H
#ifdef __KERNEL__
-extern void btext_clearscreen(void);
-extern void btext_flushscreen(void);
-
-extern int boot_text_mapped;
-
-extern int btext_initialize(struct device_node *np);
-
-extern void map_boot_text(void);
-extern void init_boot_display(void);
+extern int btext_find_display(int allow_nonstdout);
extern void btext_update_display(unsigned long phys, int width, int height,
int depth, int pitch);
+extern void btext_setup_display(int width, int height, int depth, int pitch,
+ unsigned long address);
+extern void btext_prepare_BAT(void);
+extern void btext_unmap(void);
extern void btext_drawchar(char c);
extern void btext_drawstring(const char *str);
extern void btext_drawhex(unsigned long v);
+extern void btext_drawtext(const char *c, unsigned int len);
+
+extern void btext_clearscreen(void);
+extern void btext_flushscreen(void);
+extern void btext_flushline(void);
#endif /* __KERNEL__ */
#endif /* __PPC_BTEXT_H */
diff --git a/include/asm-powerpc/bug.h b/include/asm-powerpc/bug.h
index b001ecb3cd99..99817a802ca4 100644
--- a/include/asm-powerpc/bug.h
+++ b/include/asm-powerpc/bug.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_BUG_H
#define _ASM_POWERPC_BUG_H
+#ifdef __KERNEL__
#include <asm/asm-compat.h>
/*
@@ -67,4 +68,5 @@ struct bug_entry *find_bug(unsigned long bugaddr);
#include <asm-generic/bug.h>
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_BUG_H */
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 26ce502e76e8..6379c2df5c40 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -19,7 +19,6 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
#if defined(__powerpc64__) && !defined(__ASSEMBLY__)
struct ppc64_caches {
diff --git a/include/asm-powerpc/checksum.h b/include/asm-powerpc/checksum.h
index d8354d8a49ce..609ecbbd7210 100644
--- a/include/asm-powerpc/checksum.h
+++ b/include/asm-powerpc/checksum.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_CHECKSUM_H
#define _ASM_POWERPC_CHECKSUM_H
+#ifdef __KERNEL__
/*
* This program is free software; you can redistribute it and/or
@@ -129,4 +130,5 @@ static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
}
#endif
+#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
index 4db4360c4d4a..accb80c9a339 100644
--- a/include/asm-powerpc/compat.h
+++ b/include/asm-powerpc/compat.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_COMPAT_H
#define _ASM_POWERPC_COMPAT_H
+#ifdef __KERNEL__
/*
* Architecture specific compatibility types
*/
@@ -202,4 +203,5 @@ struct compat_shmid64_ds {
compat_ulong_t __unused6;
};
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_COMPAT_H */
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index d1cfa3f515ea..64210549f56b 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -1,7 +1,6 @@
#ifndef __ASM_POWERPC_CPUTABLE_H
#define __ASM_POWERPC_CPUTABLE_H
-#include <linux/config.h>
#include <asm/asm-compat.h>
#define PPC_FEATURE_32 0x80000000
@@ -20,6 +19,7 @@
#define PPC_FEATURE_POWER5 0x00040000
#define PPC_FEATURE_POWER5_PLUS 0x00020000
#define PPC_FEATURE_CELL 0x00010000
+#define PPC_FEATURE_BOOKE 0x00008000
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -28,10 +28,17 @@
* via the mkdefs mechanism.
*/
struct cpu_spec;
-struct op_powerpc_model;
typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
+enum powerpc_oprofile_type {
+ PPC_OPROFILE_INVALID = 0,
+ PPC_OPROFILE_RS64 = 1,
+ PPC_OPROFILE_POWER4 = 2,
+ PPC_OPROFILE_G4 = 3,
+ PPC_OPROFILE_BOOKE = 4,
+};
+
struct cpu_spec {
/* CPU is matched via (PVR & pvr_mask) == pvr_value */
unsigned int pvr_mask;
@@ -57,7 +64,10 @@ struct cpu_spec {
char *oprofile_cpu_type;
/* Processor specific oprofile operations */
- struct op_powerpc_model *oprofile_model;
+ enum powerpc_oprofile_type oprofile_type;
+
+ /* Name of processor class, for the ELF AT_PLATFORM entry */
+ char *platform;
};
extern struct cpu_spec *cur_cpu_spec;
@@ -106,6 +116,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000)
#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000)
#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000)
+#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000)
#else
/* ensure on 32b processors the flags are available for compiling but
* don't do anything */
@@ -305,12 +316,18 @@ enum {
CPU_FTR_MMCRA_SIHV,
CPU_FTRS_CELL = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 |
- CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT,
+ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT |
+ CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO,
CPU_FTRS_COMPATIBLE = CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2,
#endif
CPU_FTRS_POSSIBLE =
+#ifdef __powerpc64__
+ CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
+ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
+ CPU_FTR_CI_LARGE_PAGE |
+#else
#if CLASSIC_PPC
CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU |
CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 |
@@ -344,14 +361,14 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 | CPU_FTRS_E500_2 |
#endif
-#ifdef __powerpc64__
- CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |
- CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL |
- CPU_FTR_CI_LARGE_PAGE |
-#endif
+#endif /* __powerpc64__ */
0,
CPU_FTRS_ALWAYS =
+#ifdef __powerpc64__
+ CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
+ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
+#else
#if CLASSIC_PPC
CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU &
CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 &
@@ -385,10 +402,7 @@ enum {
#ifdef CONFIG_E500
CPU_FTRS_E500 & CPU_FTRS_E500_2 &
#endif
-#ifdef __powerpc64__
- CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &
- CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL &
-#endif
+#endif /* __powerpc64__ */
CPU_FTRS_POSSIBLE,
};
diff --git a/include/asm-powerpc/current.h b/include/asm-powerpc/current.h
index 82cd4a9ca99a..1938d6abd255 100644
--- a/include/asm-powerpc/current.h
+++ b/include/asm-powerpc/current.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_CURRENT_H
#define _ASM_POWERPC_CURRENT_H
+#ifdef __KERNEL__
/*
* This program is free software; you can redistribute it and/or
@@ -24,4 +25,5 @@ register struct task_struct *current asm ("r2");
#endif
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_CURRENT_H */
diff --git a/include/asm-powerpc/delay.h b/include/asm-powerpc/delay.h
index 54fe1f4f8fd0..057a60955474 100644
--- a/include/asm-powerpc/delay.h
+++ b/include/asm-powerpc/delay.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_DELAY_H
#define _ASM_POWERPC_DELAY_H
+#ifdef __KERNEL__
/*
* Copyright 1996, Paul Mackerras.
@@ -16,4 +17,5 @@
extern void __delay(unsigned long loops);
extern void udelay(unsigned long usecs);
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DELAY_H */
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index 59a80163f75f..837756ab7dc7 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -6,6 +6,7 @@
*/
#ifndef _ASM_DMA_MAPPING_H
#define _ASM_DMA_MAPPING_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h>
@@ -229,7 +230,7 @@ static inline int dma_get_cache_alignment(void)
#ifdef CONFIG_PPC64
/* no easy way to get cache size on all processors, so return
* the maximum possible, to be safe */
- return (1 << L1_CACHE_SHIFT_MAX);
+ return (1 << INTERNODE_CACHE_SHIFT);
#else
/*
* Each processor family will define its own L1_CACHE_SHIFT,
@@ -282,4 +283,5 @@ struct dma_mapping_ops {
int (*dac_dma_supported)(struct device *dev, u64 mask);
};
+#endif /* __KERNEL__ */
#endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h
index 926378d2cd94..4bb57fe37097 100644
--- a/include/asm-powerpc/dma.h
+++ b/include/asm-powerpc/dma.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_DMA_H
#define _ASM_POWERPC_DMA_H
+#ifdef __KERNEL__
/*
* Defines for using and allocating dma channels.
@@ -387,4 +388,5 @@ extern int isa_dma_bridge_buggy;
#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DMA_H */
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index f8633aafe4ba..b263fb2fa6e4 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -19,6 +19,7 @@
#ifndef _PPC64_EEH_H
#define _PPC64_EEH_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/init.h>
@@ -33,9 +34,11 @@ struct device_node;
extern int eeh_subsystem_enabled;
/* Values for eeh_mode bits in device_node */
-#define EEH_MODE_SUPPORTED (1<<0)
-#define EEH_MODE_NOCHECK (1<<1)
-#define EEH_MODE_ISOLATED (1<<2)
+#define EEH_MODE_SUPPORTED (1<<0)
+#define EEH_MODE_NOCHECK (1<<1)
+#define EEH_MODE_ISOLATED (1<<2)
+#define EEH_MODE_RECOVERING (1<<3)
+#define EEH_MODE_IRQ_DISABLED (1<<4)
/* Max number of EEH freezes allowed before we consider the device
* to be permanently disabled. */
@@ -57,6 +60,7 @@ void __init pci_addr_cache_build(void);
* to finish the eeh setup for this device.
*/
void eeh_add_device_early(struct device_node *);
+void eeh_add_device_tree_early(struct device_node *);
void eeh_add_device_late(struct pci_dev *);
/**
@@ -72,6 +76,15 @@ void eeh_add_device_late(struct pci_dev *);
void eeh_remove_device(struct pci_dev *);
/**
+ * eeh_remove_device_recursive - undo EEH for device & children.
+ * @dev: pci device to be removed
+ *
+ * As above, this removes the device; it also removes child
+ * pci devices as well.
+ */
+void eeh_remove_bus_device(struct pci_dev *);
+
+/**
* EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
*
* If this macro yields TRUE, the caller relays to eeh_check_failure()
@@ -107,6 +120,9 @@ static inline void eeh_add_device_late(struct pci_dev *dev) { }
static inline void eeh_remove_device(struct pci_dev *dev) { }
+static inline void eeh_add_device_tree_early(struct device_node *dn) { }
+
+static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
#define EEH_POSSIBLE_ERROR(val, type) (0)
#define EEH_IO_ERROR_VALUE(size) (-1UL)
#endif /* CONFIG_EEH */
@@ -363,4 +379,5 @@ static inline void eeh_insl_ns(unsigned long port, void * buf, int nl)
eeh_check_failure((void __iomem *)(port), *(u32*)buf);
}
+#endif /* __KERNEL__ */
#endif /* _PPC64_EEH_H */
diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h
index d168a30b3866..93d55a2bebfd 100644
--- a/include/asm-powerpc/eeh_event.h
+++ b/include/asm-powerpc/eeh_event.h
@@ -20,6 +20,7 @@
#ifndef ASM_PPC64_EEH_EVENT_H
#define ASM_PPC64_EEH_EVENT_H
+#ifdef __KERNEL__
/** EEH event -- structure holding pci controller data that describes
* a change in the isolation status of a PCI slot. A pointer
@@ -29,7 +30,7 @@ struct eeh_event {
struct list_head list;
struct device_node *dn; /* struct device node */
struct pci_dev *dev; /* affected device */
- int state;
+ enum pci_channel_state state; /* PCI bus state for the affected device */
int time_unavail; /* milliseconds until device might be available */
};
@@ -46,7 +47,11 @@ struct eeh_event {
*/
int eeh_send_failure_event (struct device_node *dn,
struct pci_dev *dev,
- int reset_state,
+ enum pci_channel_state state,
int time_unavail);
+/* Main recovery function */
+void handle_eeh_events (struct eeh_event *);
+
+#endif /* __KERNEL__ */
#endif /* ASM_PPC64_EEH_EVENT_H */
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 3dcd65edf978..94d228f9c6ac 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -1,7 +1,10 @@
#ifndef _ASM_POWERPC_ELF_H
#define _ASM_POWERPC_ELF_H
+#ifdef __KERNEL__
#include <linux/sched.h> /* for task_struct */
+#endif
+
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/cputable.h>
@@ -89,7 +92,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#include <asm/ptrace.h>
#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
#define ELF_NFPREG 33 /* includes fpscr */
@@ -219,20 +221,18 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
instruction set this cpu supports. This could be done in userspace,
but it's not easy, and we've already done it here. */
# define ELF_HWCAP (cur_cpu_spec->cpu_user_features)
-#ifdef __powerpc64__
-# define ELF_PLAT_INIT(_r, load_addr) do { \
- _r->gpr[2] = load_addr; \
-} while (0)
-#endif /* __powerpc64__ */
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
- intent than poking at uname or /proc/cpuinfo.
+ intent than poking at uname or /proc/cpuinfo. */
- For the moment, we have only optimizations for the Intel generations,
- but that could change... */
+#define ELF_PLATFORM (cur_cpu_spec->platform)
-#define ELF_PLATFORM (NULL)
+#ifdef __powerpc64__
+# define ELF_PLAT_INIT(_r, load_addr) do { \
+ _r->gpr[2] = load_addr; \
+} while (0)
+#endif /* __powerpc64__ */
#ifdef __KERNEL__
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index 12fabbcb04f0..f804b34cf06a 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -98,6 +98,12 @@ typedef struct {
extern firmware_feature_t firmware_features_table[];
#endif
+extern void system_reset_fwnmi(void);
+extern void machine_check_fwnmi(void);
+
+/* This is true if we are using the firmware NMI handler (typically LPAR) */
+extern int fwnmi_active;
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_FIRMWARE_H */
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index 64276a3f6153..e258778ca429 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -9,6 +9,7 @@
*/
#ifndef __ASM_POWERPC_FLOPPY_H
#define __ASM_POWERPC_FLOPPY_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <asm/machdep.h>
@@ -102,4 +103,5 @@ static int FDC2 = -1;
#define EXTRA_FLOPPY_PARAMS
+#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_FLOPPY_H */
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h
index f0319d50b129..39e85f320a76 100644
--- a/include/asm-powerpc/futex.h
+++ b/include/asm-powerpc/futex.h
@@ -11,7 +11,7 @@
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
__asm__ __volatile ( \
- SYNC_ON_SMP \
+ LWSYNC_ON_SMP \
"1: lwarx %0,0,%2\n" \
insn \
PPC405_ERR77(0, %2) \
diff --git a/include/asm-powerpc/grackle.h b/include/asm-powerpc/grackle.h
index 563c7a5e64c9..bd7812a519d4 100644
--- a/include/asm-powerpc/grackle.h
+++ b/include/asm-powerpc/grackle.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_POWERPC_GRACKLE_H
+#define _ASM_POWERPC_GRACKLE_H
+#ifdef __KERNEL__
/*
* Functions for setting up and using a MPC106 northbridge
*/
@@ -5,3 +8,5 @@
#include <asm/pci-bridge.h>
extern void setup_grackle(struct pci_controller *hose);
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_GRACKLE_H */
diff --git a/include/asm-powerpc/hardirq.h b/include/asm-powerpc/hardirq.h
index 3b3e3b49ec12..288e14d53b7f 100644
--- a/include/asm-powerpc/hardirq.h
+++ b/include/asm-powerpc/hardirq.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_HARDIRQ_H
#define _ASM_POWERPC_HARDIRQ_H
+#ifdef __KERNEL__
#include <asm/irq.h>
#include <asm/bug.h>
@@ -24,4 +25,5 @@ static inline void ack_bad_irq(int irq)
BUG();
}
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HARDIRQ_H */
diff --git a/include/asm-powerpc/heathrow.h b/include/asm-powerpc/heathrow.h
index 22ac179856b9..93f54958a9d1 100644
--- a/include/asm-powerpc/heathrow.h
+++ b/include/asm-powerpc/heathrow.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_POWERPC_HEATHROW_H
+#define _ASM_POWERPC_HEATHROW_H
+#ifdef __KERNEL__
/*
* heathrow.h: definitions for using the "Heathrow" I/O controller chip.
*
@@ -60,3 +63,5 @@
/* Looks like Heathrow has some sort of GPIOs as well... */
#define HRW_GPIO_MODEM_RESET 0x6d
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_HEATHROW_H */
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index d36da61dbc53..38ca9ad6110d 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -1,11 +1,15 @@
#ifndef _ASM_POWERPC_HVCALL_H
#define _ASM_POWERPC_HVCALL_H
+#ifdef __KERNEL__
#define HVSC .long 0x44000022
#define H_Success 0
#define H_Busy 1 /* Hardware busy -- retry later */
+#define H_Closed 2 /* Resource closed */
#define H_Constrained 4 /* Resource request constrained to max allowed */
+#define H_InProgress 14 /* Kind of like busy */
+#define H_Continue 18 /* Returned from H_Join on success */
#define H_LongBusyStartRange 9900 /* Start of long busy range */
#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */
#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */
@@ -113,6 +117,8 @@
#define H_REGISTER_VTERM 0x154
#define H_FREE_VTERM 0x158
#define H_POLL_PENDING 0x1D8
+#define H_JOIN 0x298
+#define H_ENABLE_CRQ 0x2B0
#ifndef __ASSEMBLY__
@@ -170,4 +176,5 @@ long plpar_hcall_4out(unsigned long opcode,
unsigned long *out4);
#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_HVCALL_H */
diff --git a/include/asm-powerpc/hvconsole.h b/include/asm-powerpc/hvconsole.h
index 6da93ce74dc0..34daf7b9b62f 100644
--- a/include/asm-powerpc/hvconsole.h
+++ b/include/asm-powerpc/hvconsole.h
@@ -21,6 +21,7 @@
#ifndef _PPC64_HVCONSOLE_H
#define _PPC64_HVCONSOLE_H
+#ifdef __KERNEL__
/*
* This is the max number of console adapters that can/will be found as
@@ -46,4 +47,5 @@ extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq,
struct hv_ops *ops);
/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */
extern int __devexit hvc_remove(struct hvc_struct *hp);
+#endif /* __KERNEL__ */
#endif /* _PPC64_HVCONSOLE_H */
diff --git a/include/asm-powerpc/hvcserver.h b/include/asm-powerpc/hvcserver.h
index aecba9665796..67d7da3a4da4 100644
--- a/include/asm-powerpc/hvcserver.h
+++ b/include/asm-powerpc/hvcserver.h
@@ -21,6 +21,7 @@
#ifndef _PPC64_HVCSERVER_H
#define _PPC64_HVCSERVER_H
+#ifdef __KERNEL__
#include <linux/list.h>
@@ -54,4 +55,5 @@ extern int hvcs_register_connection(uint32_t unit_address,
uint32_t p_partition_ID, uint32_t p_unit_address);
extern int hvcs_free_connection(uint32_t unit_address);
+#endif /* __KERNEL__ */
#endif /* _PPC64_HVCSERVER_H */
diff --git a/include/asm-powerpc/i8259.h b/include/asm-powerpc/i8259.h
index fc4bfee124d7..0392159e16e4 100644
--- a/include/asm-powerpc/i8259.h
+++ b/include/asm-powerpc/i8259.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_I8259_H
#define _ASM_POWERPC_I8259_H
+#ifdef __KERNEL__
#include <linux/irq.h>
@@ -9,4 +10,5 @@ extern void i8259_init(unsigned long intack_addr, int offset);
extern int i8259_irq(struct pt_regs *regs);
extern int i8259_irq_cascade(struct pt_regs *regs, void *unused);
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_I8259_H */
diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h
new file mode 100644
index 000000000000..7a42723d107c
--- /dev/null
+++ b/include/asm-powerpc/ibmebus.h
@@ -0,0 +1,85 @@
+/*
+ * IBM PowerPC eBus Infrastructure Support.
+ *
+ * Copyright (c) 2005 IBM Corporation
+ * Heiko J Schick <schickhj@de.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ * BSD.
+ *
+ * OpenIB BSD License
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ASM_EBUS_H
+#define _ASM_EBUS_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <asm/of_device.h>
+
+extern struct dma_mapping_ops ibmebus_dma_ops;
+extern struct bus_type ibmebus_bus_type;
+
+struct ibmebus_dev {
+ char *name;
+ struct of_device ofdev;
+};
+
+struct ibmebus_driver {
+ char *name;
+ struct of_device_id *id_table;
+ int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id);
+ int (*remove) (struct ibmebus_dev *dev);
+ struct device_driver driver;
+};
+
+int ibmebus_register_driver(struct ibmebus_driver *drv);
+void ibmebus_unregister_driver(struct ibmebus_driver *drv);
+
+int ibmebus_request_irq(struct ibmebus_dev *dev,
+ u32 ist,
+ irqreturn_t (*handler)(int, void*, struct pt_regs *),
+ unsigned long irq_flags, const char * devname,
+ void *dev_id);
+void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id);
+
+static inline struct ibmebus_driver *to_ibmebus_driver(struct device_driver *drv)
+{
+ return container_of(drv, struct ibmebus_driver, driver);
+}
+
+static inline struct ibmebus_dev *to_ibmebus_dev(struct device *dev)
+{
+ return container_of(dev, struct ibmebus_dev, ofdev.dev);
+}
+
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_IBMEBUS_H */
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 48938d84d055..68efbea379c9 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_IO_H
#define _ASM_POWERPC_IO_H
+#ifdef __KERNEL__
/*
* This program is free software; you can redistribute it and/or
@@ -186,7 +187,6 @@ extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl);
#define IO_SPACE_LIMIT ~(0UL)
-#ifdef __KERNEL__
extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
unsigned long size, unsigned long flags);
extern void __iomem *__ioremap(unsigned long address, unsigned long size,
@@ -256,8 +256,6 @@ static inline void * phys_to_virt(unsigned long address)
*/
#define BIO_VMERGE_BOUNDARY 0
-#endif /* __KERNEL__ */
-
static inline void iosync(void)
{
__asm__ __volatile__ ("sync" : : : "memory");
@@ -405,8 +403,6 @@ static inline void out_be64(volatile unsigned long __iomem *addr, unsigned long
#include <asm/eeh.h>
#endif
-#ifdef __KERNEL__
-
/**
* check_signature - find BIOS signatures
* @io_addr: mmio address to check
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index f89f06050893..d5677cbec200 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -20,6 +20,7 @@
#ifndef _ASM_IOMMU_H
#define _ASM_IOMMU_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <asm/types.h>
@@ -56,32 +57,13 @@ struct device_node;
/* Walks all buses and creates iommu tables */
extern void iommu_setup_pSeries(void);
-extern void iommu_setup_u3(void);
+extern void iommu_setup_dart(void);
/* Frees table for an individual device node */
extern void iommu_free_table(struct device_node *dn);
#endif /* CONFIG_PPC_MULTIPLATFORM */
-#ifdef CONFIG_PPC_PSERIES
-
-/* Creates table for an individual device node */
-extern void iommu_devnode_init_pSeries(struct device_node *dn);
-
-#endif /* CONFIG_PPC_PSERIES */
-
-#ifdef CONFIG_PPC_ISERIES
-
-/* Creates table for an individual device node */
-extern void iommu_devnode_init_iSeries(struct device_node *dn);
-/* Get table parameters from HV */
-extern void iommu_table_getparms_iSeries(unsigned long busno,
- unsigned char slotno,
- unsigned char virtbus,
- struct iommu_table* tbl);
-
-#endif /* CONFIG_PPC_ISERIES */
-
/* Initializes an iommu_table based in values set in the passed-in
* structure
*/
@@ -104,7 +86,7 @@ extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
extern void iommu_init_early_pSeries(void);
extern void iommu_init_early_iSeries(void);
-extern void iommu_init_early_u3(void);
+extern void iommu_init_early_dart(void);
#ifdef CONFIG_PCI
extern void pci_iommu_init(void);
@@ -113,6 +95,7 @@ extern void pci_direct_iommu_init(void);
static inline void pci_iommu_init(void) { }
#endif
-extern void alloc_u3_dart_table(void);
+extern void alloc_dart_table(void);
+#endif /* __KERNEL__ */
#endif /* _ASM_IOMMU_H */
diff --git a/include/asm-ppc/ipic.h b/include/asm-powerpc/ipic.h
index 0fe396a2b666..0fe396a2b666 100644
--- a/include/asm-ppc/ipic.h
+++ b/include/asm-powerpc/ipic.h
diff --git a/include/asm-powerpc/iseries/hv_call.h b/include/asm-powerpc/iseries/hv_call.h
index e9f831c9a5e5..162d653ad51f 100644
--- a/include/asm-powerpc/iseries/hv_call.h
+++ b/include/asm-powerpc/iseries/hv_call.h
@@ -1,5 +1,4 @@
/*
- * HvCall.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@@ -15,8 +14,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, MA 02111-1307 USA
- */
-/*
+ *
* This file contains the "hypervisor call" interface which is used to
* drive the hypervisor from the OS.
*/
diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h
index 46763a30590a..4cec4762076d 100644
--- a/include/asm-powerpc/iseries/hv_call_event.h
+++ b/include/asm-powerpc/iseries/hv_call_event.h
@@ -1,5 +1,4 @@
/*
- * HvCallEvent.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@@ -15,8 +14,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, MA 02111-1307 USA
- */
-/*
+ *
* This file contains the "hypervisor call" interface which is used to
* drive the hypervisor from the OS.
*/
@@ -33,32 +31,9 @@ typedef u8 HvLpEvent_Type;
typedef u8 HvLpEvent_AckInd;
typedef u8 HvLpEvent_AckType;
-struct HvCallEvent_PackedParms {
- u8 xAckType:1;
- u8 xAckInd:1;
- u8 xRsvd:1;
- u8 xTargetLp:5;
- u8 xType;
- u16 xSubtype;
- HvLpInstanceId xSourceInstId;
- HvLpInstanceId xTargetInstId;
-};
-
typedef u8 HvLpDma_Direction;
typedef u8 HvLpDma_AddressType;
-struct HvCallEvent_PackedDmaParms {
- u8 xDirection:1;
- u8 xLocalAddrType:1;
- u8 xRemoteAddrType:1;
- u8 xRsvd1:5;
- HvLpIndex xRemoteLp;
- u8 xType;
- u8 xRsvd2;
- HvLpInstanceId xLocalInstId;
- HvLpInstanceId xRemoteInstId;
-};
-
typedef u64 HvLpEvent_Rc;
typedef u64 HvLpDma_Rc;
@@ -92,11 +67,8 @@ static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex)
static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
char *eventStackAddr, u32 eventStackSize)
{
- u64 abs_addr;
-
- abs_addr = virt_to_abs(eventStackAddr);
- HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr,
- eventStackSize);
+ HvCall3(HvCallEventSetLpEventStack, queueIndex,
+ virt_to_abs(eventStackAddr), eventStackSize);
}
static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
@@ -108,14 +80,7 @@ static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event)
{
- u64 abs_addr;
-
-#ifdef DEBUG_SENDEVENT
- printk("HvCallEvent_signalLpEvent: *event = %016lx\n ",
- (unsigned long)event);
-#endif
- abs_addr = virt_to_abs(event);
- return HvCall1(HvCallEventSignalLpEvent, abs_addr);
+ return HvCall1(HvCallEventSignalLpEvent, virt_to_abs(event));
}
static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
@@ -127,17 +92,21 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
{
/* Pack the misc bits into a single Dword to pass to PLIC */
union {
- struct HvCallEvent_PackedParms parms;
+ struct {
+ u8 ack_and_target;
+ u8 type;
+ u16 subtype;
+ HvLpInstanceId src_inst;
+ HvLpInstanceId target_inst;
+ } parms;
u64 dword;
} packed;
- packed.parms.xAckType = ackType;
- packed.parms.xAckInd = ackInd;
- packed.parms.xRsvd = 0;
- packed.parms.xTargetLp = targetLp;
- packed.parms.xType = type;
- packed.parms.xSubtype = subtype;
- packed.parms.xSourceInstId = sourceInstanceId;
- packed.parms.xTargetInstId = targetInstanceId;
+
+ packed.parms.ack_and_target = (ackType << 7) | (ackInd << 6) | targetLp;
+ packed.parms.type = type;
+ packed.parms.subtype = subtype;
+ packed.parms.src_inst = sourceInstanceId;
+ packed.parms.target_inst = targetInstanceId;
return HvCall7(HvCallEventSignalLpEventParms, packed.dword,
correlationToken, eventData1, eventData2,
@@ -146,18 +115,12 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
{
- u64 abs_addr;
-
- abs_addr = virt_to_abs(event);
- return HvCall1(HvCallEventAckLpEvent, abs_addr);
+ return HvCall1(HvCallEventAckLpEvent, virt_to_abs(event));
}
static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event)
{
- u64 abs_addr;
-
- abs_addr = virt_to_abs(event);
- return HvCall1(HvCallEventCancelLpEvent, abs_addr);
+ return HvCall1(HvCallEventCancelLpEvent, virt_to_abs(event));
}
static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId(
@@ -195,59 +158,34 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
{
/* Pack the misc bits into a single Dword to pass to PLIC */
union {
- struct HvCallEvent_PackedDmaParms parms;
+ struct {
+ u8 flags;
+ HvLpIndex remote;
+ u8 type;
+ u8 reserved;
+ HvLpInstanceId local_inst;
+ HvLpInstanceId remote_inst;
+ } parms;
u64 dword;
} packed;
- packed.parms.xDirection = direction;
- packed.parms.xLocalAddrType = localAddressType;
- packed.parms.xRemoteAddrType = remoteAddressType;
- packed.parms.xRsvd1 = 0;
- packed.parms.xRemoteLp = remoteLp;
- packed.parms.xType = type;
- packed.parms.xRsvd2 = 0;
- packed.parms.xLocalInstId = localInstanceId;
- packed.parms.xRemoteInstId = remoteInstanceId;
+ packed.parms.flags = (direction << 7) |
+ (localAddressType << 6) | (remoteAddressType << 5);
+ packed.parms.remote = remoteLp;
+ packed.parms.type = type;
+ packed.parms.reserved = 0;
+ packed.parms.local_inst = localInstanceId;
+ packed.parms.remote_inst = remoteInstanceId;
return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList,
remoteBufList, transferLength);
}
-static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
- HvLpIndex remoteLp, HvLpDma_Direction direction,
- HvLpInstanceId localInstanceId,
- HvLpInstanceId remoteInstanceId,
- HvLpDma_AddressType localAddressType,
- HvLpDma_AddressType remoteAddressType,
- u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength)
-{
- /* Pack the misc bits into a single Dword to pass to PLIC */
- union {
- struct HvCallEvent_PackedDmaParms parms;
- u64 dword;
- } packed;
-
- packed.parms.xDirection = direction;
- packed.parms.xLocalAddrType = localAddressType;
- packed.parms.xRemoteAddrType = remoteAddressType;
- packed.parms.xRsvd1 = 0;
- packed.parms.xRemoteLp = remoteLp;
- packed.parms.xType = type;
- packed.parms.xRsvd2 = 0;
- packed.parms.xLocalInstId = localInstanceId;
- packed.parms.xRemoteInstId = remoteInstanceId;
-
- return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword,
- localAddrOrTce, remoteAddrOrTce, transferLength);
-}
-
static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote,
u32 length, HvLpDma_Direction dir)
{
- u64 abs_addr;
-
- abs_addr = virt_to_abs(local);
- return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir);
+ return HvCall4(HvCallEventDmaToSp, virt_to_abs(local), remote,
+ length, dir);
}
#endif /* _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H */
diff --git a/include/asm-powerpc/iseries/hv_call_sc.h b/include/asm-powerpc/iseries/hv_call_sc.h
index dec7e9d9ab78..f5d210959250 100644
--- a/include/asm-powerpc/iseries/hv_call_sc.h
+++ b/include/asm-powerpc/iseries/hv_call_sc.h
@@ -1,5 +1,4 @@
/*
- * HvCallSc.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/hv_lp_config.h b/include/asm-powerpc/iseries/hv_lp_config.h
index bc00f036bca0..df8b20739719 100644
--- a/include/asm-powerpc/iseries/hv_lp_config.h
+++ b/include/asm-powerpc/iseries/hv_lp_config.h
@@ -1,5 +1,4 @@
/*
- * HvLpConfig.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/hv_lp_event.h b/include/asm-powerpc/iseries/hv_lp_event.h
index 499ab1ad0185..4065a4de4935 100644
--- a/include/asm-powerpc/iseries/hv_lp_event.h
+++ b/include/asm-powerpc/iseries/hv_lp_event.h
@@ -1,5 +1,4 @@
/*
- * HvLpEvent.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@@ -32,17 +31,8 @@
* partitions through PLIC.
*/
-struct HvEventFlags {
- u8 xValid:1; /* Indicates a valid request x00-x00 */
- u8 xRsvd1:4; /* Reserved ... */
- u8 xAckType:1; /* Immediate or deferred ... */
- u8 xAckInd:1; /* Indicates if ACK required ... */
- u8 xFunction:1; /* Interrupt or Acknowledge ... */
-};
-
-
struct HvLpEvent {
- struct HvEventFlags xFlags; /* Event flags x00-x00 */
+ u8 flags; /* Event flags x00-x00 */
u8 xType; /* Type of message x01-x01 */
u16 xSubtype; /* Subtype for event x02-x03 */
u8 xSourceLp; /* Source LP x04-x04 */
@@ -126,6 +116,11 @@ extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
#define HvLpEvent_AckType_ImmediateAck 0
#define HvLpEvent_AckType_DeferredAck 1
+#define HV_LP_EVENT_INT 0x01
+#define HV_LP_EVENT_DO_ACK 0x02
+#define HV_LP_EVENT_DEFERRED_ACK 0x04
+#define HV_LP_EVENT_VALID 0x80
+
#define HvLpDma_Direction_LocalToRemote 0
#define HvLpDma_Direction_RemoteToLocal 1
@@ -139,4 +134,29 @@ extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
#define HvLpDma_Rc_InvalidAddress 4
#define HvLpDma_Rc_InvalidLength 5
+static inline int hvlpevent_is_valid(struct HvLpEvent *h)
+{
+ return h->flags & HV_LP_EVENT_VALID;
+}
+
+static inline void hvlpevent_invalidate(struct HvLpEvent *h)
+{
+ h->flags &= ~ HV_LP_EVENT_VALID;
+}
+
+static inline int hvlpevent_is_int(struct HvLpEvent *h)
+{
+ return h->flags & HV_LP_EVENT_INT;
+}
+
+static inline int hvlpevent_is_ack(struct HvLpEvent *h)
+{
+ return !hvlpevent_is_int(h);
+}
+
+static inline int hvlpevent_need_ack(struct HvLpEvent *h)
+{
+ return h->flags & HV_LP_EVENT_DO_ACK;
+}
+
#endif /* _ASM_POWERPC_ISERIES_HV_LP_EVENT_H */
diff --git a/include/asm-powerpc/iseries/hv_types.h b/include/asm-powerpc/iseries/hv_types.h
index c38f7e3d01dc..c3e6d2a1d1c3 100644
--- a/include/asm-powerpc/iseries/hv_types.h
+++ b/include/asm-powerpc/iseries/hv_types.h
@@ -1,5 +1,4 @@
/*
- * HvTypes.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h
index 56b2113ff0f5..496aa852b617 100644
--- a/include/asm-powerpc/iseries/iseries_io.h
+++ b/include/asm-powerpc/iseries/iseries_io.h
@@ -6,7 +6,7 @@
#ifdef CONFIG_PPC_ISERIES
#include <linux/types.h>
/*
- * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.
+ * Created by Allan Trautman on Thu Dec 28 2000.
*
* Remaps the io.h for the iSeries Io
* Copyright (C) 2000 Allan H Trautman, IBM Corporation
@@ -32,6 +32,7 @@
* End Change Activity
*/
+#ifdef CONFIG_PCI
extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress);
extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress);
extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress);
@@ -44,6 +45,17 @@ extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source,
size_t n);
extern void iSeries_memcpy_fromio(void *dest,
const volatile void __iomem *source, size_t n);
+#else
+static inline u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
+{
+ return 0xff;
+}
+
+static inline void iSeries_Write_Byte(u8 IoData,
+ volatile void __iomem *IoAddress)
+{
+}
+#endif /* CONFIG_PCI */
#endif /* CONFIG_PPC_ISERIES */
#endif /* _ASM_POWERPC_ISERIES_ISERIES_IO_H */
diff --git a/include/asm-powerpc/iseries/it_exp_vpd_panel.h b/include/asm-powerpc/iseries/it_exp_vpd_panel.h
index 66a17a230c52..304a609ae21a 100644
--- a/include/asm-powerpc/iseries/it_exp_vpd_panel.h
+++ b/include/asm-powerpc/iseries/it_exp_vpd_panel.h
@@ -1,5 +1,4 @@
/*
- * ItExtVpdPanel.h
* Copyright (C) 2002 Dave Boutcher IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/it_lp_naca.h b/include/asm-powerpc/iseries/it_lp_naca.h
index c3ef1de45d82..4fdcf052927f 100644
--- a/include/asm-powerpc/iseries/it_lp_naca.h
+++ b/include/asm-powerpc/iseries/it_lp_naca.h
@@ -1,5 +1,4 @@
/*
- * ItLpNaca.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@@ -37,17 +36,13 @@ struct ItLpNaca {
u8 xLpIndex; // LP Index x0B-x0B
u16 xMaxLpQueues; // Number of allocated queues x0C-x0D
u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F
- u8 xPirEnvironMode:8; // Piranha or hardware x10-x10
- u8 xPirConsoleMode:8; // Piranha console indicator x11-x11
- u8 xPirDasdMode:8; // Piranha dasd indicator x12-x12
+ u8 xPirEnvironMode; // Piranha or hardware x10-x10
+ u8 xPirConsoleMode; // Piranha console indicator x11-x11
+ u8 xPirDasdMode; // Piranha dasd indicator x12-x12
u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17
- u8 xLparInstalled:1; // Is LPAR installed on system x18-x1F
- u8 xSysPartitioned:1; // Is the system partitioned ...
- u8 xHwSyncedTBs:1; // Hardware synced TBs ...
- u8 xIntProcUtilHmt:1; // Utilize HMT for interrupts ...
- u8 xRsvd1_1:4; // Reserved ...
- u8 xSpVpdFormat:8; // VPD areas are in CSP format ...
- u8 xIntProcRatio:8; // Ratio of int procs to procs ...
+ u8 flags; // flags, see below x18-x1F
+ u8 xSpVpdFormat; // VPD areas are in CSP format ...
+ u8 xIntProcRatio; // Ratio of int procs to procs ...
u8 xRsvd1_2[5]; // Reserved ...
u16 xRsvd1_3; // Reserved x20-x21
u16 xPlicVrmIndex; // VRM index of PLIC x22-x23
@@ -77,4 +72,9 @@ struct ItLpNaca {
extern struct ItLpNaca itLpNaca;
+#define ITLPNACA_LPAR 0x80 /* Is LPAR installed on the system */
+#define ITLPNACA_PARTITIONED 0x40 /* Is the system partitioned */
+#define ITLPNACA_HWSYNCEDTBS 0x20 /* Hardware synced TBs */
+#define ITLPNACA_HMTINT 0x10 /* Utilize MHT for interrupts */
+
#endif /* _ASM_POWERPC_ISERIES_IT_LP_NACA_H */
diff --git a/include/asm-powerpc/iseries/it_lp_queue.h b/include/asm-powerpc/iseries/it_lp_queue.h
index a60d03afbf95..b7c6fc12cce2 100644
--- a/include/asm-powerpc/iseries/it_lp_queue.h
+++ b/include/asm-powerpc/iseries/it_lp_queue.h
@@ -1,5 +1,4 @@
/*
- * ItLpQueue.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/it_lp_reg_save.h b/include/asm-powerpc/iseries/it_lp_reg_save.h
index 288044b702de..5403b756f654 100644
--- a/include/asm-powerpc/iseries/it_lp_reg_save.h
+++ b/include/asm-powerpc/iseries/it_lp_reg_save.h
@@ -1,5 +1,4 @@
/*
- * ItLpRegSave.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@@ -81,4 +80,6 @@ struct ItLpRegSave {
u8 xRsvd3[176]; // Reserved 350-3FF
};
-#endif /* _ITLPREGSAVE_H */
+extern struct ItLpRegSave iseries_reg_save[];
+
+#endif /* _ASM_POWERPC_ISERIES_IT_LP_REG_SAVE_H */
diff --git a/include/asm-powerpc/iseries/lpar_map.h b/include/asm-powerpc/iseries/lpar_map.h
index 84fc321615bf..2ec384d66abb 100644
--- a/include/asm-powerpc/iseries/lpar_map.h
+++ b/include/asm-powerpc/iseries/lpar_map.h
@@ -1,5 +1,4 @@
/*
- * LparMap.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
diff --git a/include/asm-powerpc/iseries/mf.h b/include/asm-powerpc/iseries/mf.h
index e7bd57a03fb1..857e5202fc78 100644
--- a/include/asm-powerpc/iseries/mf.h
+++ b/include/asm-powerpc/iseries/mf.h
@@ -1,5 +1,4 @@
/*
- * mf.h
* Copyright (C) 2001 Troy D. Armstrong IBM Corporation
* Copyright (C) 2004 Stephen Rothwell IBM Corporation
*
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 7e3a469420dd..72a97d37aac3 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -1,5 +1,4 @@
/* -*- linux-c -*-
- * drivers/char/vio.h
*
* iSeries Virtual I/O Message Path header
*
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 9dcbac674811..7c16265568e0 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_KDEBUG_H
#define _ASM_POWERPC_KDEBUG_H
+#ifdef __KERNEL__
/* nearly identical to x86_64/i386 code */
@@ -39,4 +40,5 @@ static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,lon
return notifier_call_chain(&powerpc_die_chain, val, &args);
}
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_KDEBUG_H */
diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h
new file mode 100644
index 000000000000..a87aed00d61f
--- /dev/null
+++ b/include/asm-powerpc/kdump.h
@@ -0,0 +1,13 @@
+#ifndef _PPC64_KDUMP_H
+#define _PPC64_KDUMP_H
+
+/* How many bytes to reserve at zero for kdump. The reserve limit should
+ * be greater or equal to the trampoline's end address. */
+#define KDUMP_RESERVE_LIMIT 0x8000
+
+#define KDUMP_TRAMPOLINE_START 0x0100
+#define KDUMP_TRAMPOLINE_END 0x3000
+
+extern void kdump_setup(void);
+
+#endif /* __PPC64_KDUMP_H */
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h
index c72ffc709ea8..640a6459f2f4 100644
--- a/include/asm-powerpc/kexec.h
+++ b/include/asm-powerpc/kexec.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_KEXEC_H
#define _ASM_POWERPC_KEXEC_H
+#ifdef __KERNEL__
/*
* Maximum page that is mapped directly into kernel memory.
@@ -30,21 +31,97 @@
#define KEXEC_ARCH KEXEC_ARCH_PPC
#endif
-#ifndef __ASSEMBLY__
+#ifdef CONFIG_KEXEC
-#define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES / sizeof(u32)];
+#ifdef __powerpc64__
+/*
+ * This function is responsible for capturing register states if coming
+ * via panic or invoking dump using sysrq-trigger.
+ */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ if (oldregs)
+ memcpy(newregs, oldregs, sizeof(*newregs));
+ else {
+ /* FIXME Merge this with xmon_save_regs ?? */
+ unsigned long tmp1, tmp2;
+ __asm__ __volatile__ (
+ "std 0,0(%2)\n"
+ "std 1,8(%2)\n"
+ "std 2,16(%2)\n"
+ "std 3,24(%2)\n"
+ "std 4,32(%2)\n"
+ "std 5,40(%2)\n"
+ "std 6,48(%2)\n"
+ "std 7,56(%2)\n"
+ "std 8,64(%2)\n"
+ "std 9,72(%2)\n"
+ "std 10,80(%2)\n"
+ "std 11,88(%2)\n"
+ "std 12,96(%2)\n"
+ "std 13,104(%2)\n"
+ "std 14,112(%2)\n"
+ "std 15,120(%2)\n"
+ "std 16,128(%2)\n"
+ "std 17,136(%2)\n"
+ "std 18,144(%2)\n"
+ "std 19,152(%2)\n"
+ "std 20,160(%2)\n"
+ "std 21,168(%2)\n"
+ "std 22,176(%2)\n"
+ "std 23,184(%2)\n"
+ "std 24,192(%2)\n"
+ "std 25,200(%2)\n"
+ "std 26,208(%2)\n"
+ "std 27,216(%2)\n"
+ "std 28,224(%2)\n"
+ "std 29,232(%2)\n"
+ "std 30,240(%2)\n"
+ "std 31,248(%2)\n"
+ "mfmsr %0\n"
+ "std %0, 264(%2)\n"
+ "mfctr %0\n"
+ "std %0, 280(%2)\n"
+ "mflr %0\n"
+ "std %0, 288(%2)\n"
+ "bl 1f\n"
+ "1: mflr %1\n"
+ "std %1, 256(%2)\n"
+ "mtlr %0\n"
+ "mfxer %0\n"
+ "std %0, 296(%2)\n"
+ : "=&r" (tmp1), "=&r" (tmp2)
+ : "b" (newregs));
+ }
+}
+#else
+/*
+ * Provide a dummy definition to avoid build failures. Will remain
+ * empty till crash dump support is enabled.
+ */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs) { }
+#endif /* !__powerpc64 __ */
-extern note_buf_t crash_notes[];
+#ifndef __ASSEMBLY__
+#define MAX_NOTE_BYTES 1024
#ifdef __powerpc64__
extern void kexec_smp_wait(void); /* get and clear naca physid, wait for
master to copy new code to 0 */
extern void __init kexec_setup(void);
-#else
+extern int crashing_cpu;
+extern void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *));
+#endif /* __powerpc64 __ */
+
struct kimage;
-extern void machine_kexec_simple(struct kimage *image);
-#endif
+struct pt_regs;
+extern void default_machine_kexec(struct kimage *image);
+extern int default_machine_kexec_prepare(struct kimage *image);
+extern void default_machine_crash_shutdown(struct pt_regs *regs);
#endif /* ! __ASSEMBLY__ */
+#endif /* CONFIG_KEXEC */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_KEXEC_H */
diff --git a/include/asm-powerpc/keylargo.h b/include/asm-powerpc/keylargo.h
index a669a3f0f5a2..d8520ef121f9 100644
--- a/include/asm-powerpc/keylargo.h
+++ b/include/asm-powerpc/keylargo.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_POWERPC_KEYLARGO_H
+#define _ASM_POWERPC_KEYLARGO_H
+#ifdef __KERNEL__
/*
* keylargo.h: definitions for using the "KeyLargo" I/O controller chip.
*
@@ -232,10 +235,12 @@
#define K2_FCR1_I2S0_RESET 0x00000800
#define K2_FCR1_I2S0_CLK_ENABLE_BIT 0x00001000
#define K2_FCR1_I2S0_ENABLE 0x00002000
-
#define K2_FCR1_PCI1_CLK_ENABLE 0x00004000
#define K2_FCR1_FW_CLK_ENABLE 0x00008000
#define K2_FCR1_FW_RESET_N 0x00010000
+#define K2_FCR1_I2S1_CELL_ENABLE 0x00020000
+#define K2_FCR1_I2S1_CLK_ENABLE_BIT 0x00080000
+#define K2_FCR1_I2S1_ENABLE 0x00100000
#define K2_FCR1_GMAC_CLK_ENABLE 0x00400000
#define K2_FCR1_GMAC_POWER_DOWN 0x00800000
#define K2_FCR1_GMAC_RESET_N 0x01000000
@@ -246,3 +251,11 @@
#define K2_FCR1_UATA_RESET_N 0x40000000
#define K2_FCR1_UATA_CHOOSE_CLK66 0x80000000
+/* Shasta definitions */
+#define SH_FCR1_I2S2_CELL_ENABLE 0x00000010
+#define SH_FCR1_I2S2_CLK_ENABLE_BIT 0x00000040
+#define SH_FCR1_I2S2_ENABLE 0x00000080
+#define SH_FCR3_I2S2_CLK18_ENABLE 0x00008000
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_KEYLARGO_H */
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 6cd0a3bfa280..f466bc804f41 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_KPROBES_H
#define _ASM_POWERPC_KPROBES_H
+#ifdef __KERNEL__
/*
* Kernel Probes (KProbes)
*
@@ -29,7 +30,10 @@
#include <linux/ptrace.h>
#include <linux/percpu.h>
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+
struct pt_regs;
+struct kprobe;
typedef unsigned int kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
@@ -47,6 +51,7 @@ typedef unsigned int kprobe_opcode_t;
#define ARCH_SUPPORTS_KRETPROBES
void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
/* Architecture specific copy of original instruction */
struct arch_specific_insn {
@@ -68,14 +73,7 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
-#else /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
-#endif
+ unsigned long val, void *data);
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_KPROBES_H */
diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
index ea0afe343545..d3546c4c9f46 100644
--- a/include/asm-powerpc/lmb.h
+++ b/include/asm-powerpc/lmb.h
@@ -1,5 +1,6 @@
#ifndef _PPC64_LMB_H
#define _PPC64_LMB_H
+#ifdef __KERNEL__
/*
* Definitions for talking to the Open Firmware PROM on
@@ -78,4 +79,5 @@ lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
lmb_size_pages(type, region_nr);
}
+#endif /* __KERNEL__ */
#endif /* _PPC64_LMB_H */
diff --git a/include/asm-powerpc/lppaca.h b/include/asm-powerpc/lppaca.h
index c1bedab1515b..4dc514aabfe7 100644
--- a/include/asm-powerpc/lppaca.h
+++ b/include/asm-powerpc/lppaca.h
@@ -18,6 +18,7 @@
*/
#ifndef _ASM_POWERPC_LPPACA_H
#define _ASM_POWERPC_LPPACA_H
+#ifdef __KERNEL__
//=============================================================================
//
@@ -28,6 +29,8 @@
//----------------------------------------------------------------------------
#include <asm/types.h>
+/* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k
+ * alignment is sufficient to prevent this */
struct lppaca {
//=============================================================================
// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
@@ -126,6 +129,9 @@ struct lppaca {
// CACHE_LINE_4-5 0x0100 - 0x01FF Contains PMC interrupt data
//=============================================================================
u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF
-};
+} __attribute__((__aligned__(0x400)));
+extern struct lppaca lppaca[];
+
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_LPPACA_H */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index c011abb8b600..5348b820788c 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -27,6 +27,9 @@ struct device_node;
struct iommu_table;
struct rtc_time;
struct file;
+#ifdef CONFIG_KEXEC
+struct kimage;
+#endif
#ifdef CONFIG_SMP
struct smp_ops_t {
@@ -131,7 +134,7 @@ struct machdep_calls {
void (*nvram_sync)(void);
/* Exception handlers */
- void (*system_reset_exception)(struct pt_regs *regs);
+ int (*system_reset_exception)(struct pt_regs *regs);
int (*machine_check_exception)(struct pt_regs *regs);
/* Motherboard/chipset features. This is a kind of general purpose
@@ -207,19 +210,19 @@ struct machdep_calls {
/* this is for modules, since _machine can be a define -- Cort */
int ppc_machine;
+#endif /* CONFIG_PPC32 */
-#ifdef CONFIG_KEXEC
/* Called to shutdown machine specific hardware not already controlled
* by other drivers.
- * XXX Should we move this one out of kexec scope?
*/
void (*machine_shutdown)(void);
+#ifdef CONFIG_KEXEC
/* Called to do the minimal shutdown needed to run a kexec'd kernel
* to run successfully.
* XXX Should we move this one out of kexec scope?
*/
- void (*machine_crash_shutdown)(void);
+ void (*machine_crash_shutdown)(struct pt_regs *regs);
/* Called to do what every setup is needed on image and the
* reboot code buffer. Returns 0 on success.
@@ -237,7 +240,6 @@ struct machdep_calls {
*/
void (*machine_kexec)(struct kimage *image);
#endif /* CONFIG_KEXEC */
-#endif /* CONFIG_PPC32 */
};
extern void default_idle(void);
diff --git a/include/asm-powerpc/macio.h b/include/asm-powerpc/macio.h
index b553dd4b139e..3a6cb1a513b7 100644
--- a/include/asm-powerpc/macio.h
+++ b/include/asm-powerpc/macio.h
@@ -1,5 +1,6 @@
#ifndef __MACIO_ASIC_H__
#define __MACIO_ASIC_H__
+#ifdef __KERNEL__
#include <asm/of_device.h>
@@ -137,4 +138,5 @@ struct macio_driver
extern int macio_register_driver(struct macio_driver *);
extern void macio_unregister_driver(struct macio_driver *);
+#endif /* __KERNEL__ */
#endif /* __MACIO_ASIC_H__ */
diff --git a/include/asm-powerpc/mman.h b/include/asm-powerpc/mman.h
index f5e5342fcac5..a2e34c21b44f 100644
--- a/include/asm-powerpc/mman.h
+++ b/include/asm-powerpc/mman.h
@@ -44,6 +44,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index 29b0bb0086d3..d096d9e76ad7 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_MMU_H_
#define _ASM_POWERPC_MMU_H_
+#ifdef __KERNEL__
#ifndef CONFIG_PPC64
#include <asm-ppc/mmu.h>
@@ -33,7 +34,8 @@
/* Location of cpu0's segment table */
#define STAB0_PAGE 0x6
-#define STAB0_PHYS_ADDR (STAB0_PAGE<<12)
+#define STAB0_OFFSET (STAB0_PAGE << 12)
+#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START)
#ifndef __ASSEMBLY__
extern char initial_stab[];
@@ -394,7 +396,12 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS)
#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea))
+/* Physical address used by some IO functions */
+typedef unsigned long phys_addr_t;
+
+
#endif /* __ASSEMBLY */
#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MMU_H_ */
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index ea6798c7d5fc..1b8a25fd48f3 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -1,5 +1,6 @@
#ifndef __ASM_POWERPC_MMU_CONTEXT_H
#define __ASM_POWERPC_MMU_CONTEXT_H
+#ifdef __KERNEL__
#ifndef CONFIG_PPC64
#include <asm-ppc/mmu_context.h>
@@ -86,4 +87,5 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
}
#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_MMU_CONTEXT_H */
diff --git a/include/asm-powerpc/mmzone.h b/include/asm-powerpc/mmzone.h
index 54958d6cae04..88d70bae7769 100644
--- a/include/asm-powerpc/mmzone.h
+++ b/include/asm-powerpc/mmzone.h
@@ -6,6 +6,7 @@
*/
#ifndef _ASM_MMZONE_H_
#define _ASM_MMZONE_H_
+#ifdef __KERNEL__
#include <linux/config.h>
@@ -47,4 +48,5 @@ extern unsigned long max_pfn;
extern int __init early_pfn_to_nid(unsigned long pfn);
#endif
+#endif /* __KERNEL__ */
#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-powerpc/module.h b/include/asm-powerpc/module.h
index 7ecd05e03051..584fabfb4f08 100644
--- a/include/asm-powerpc/module.h
+++ b/include/asm-powerpc/module.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_MODULE_H
#define _ASM_POWERPC_MODULE_H
+#ifdef __KERNEL__
/*
* This program is free software; you can redistribute it and/or
@@ -74,4 +75,5 @@ struct exception_table_entry;
void sort_ex_table(struct exception_table_entry *start,
struct exception_table_entry *finish);
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MODULE_H */
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index 7083d1f74260..6b9e78142f4f 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_MPIC_H
#define _ASM_POWERPC_MPIC_H
+#ifdef __KERNEL__
#include <linux/irq.h>
@@ -117,7 +118,9 @@ typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data);
struct mpic_irq_fixup
{
u8 __iomem *base;
- unsigned int irq;
+ u8 __iomem *applebase;
+ u32 data;
+ unsigned int index;
};
#endif /* CONFIG_MPIC_BROKEN_U3 */
@@ -284,4 +287,5 @@ extern int mpic_get_irq(struct pt_regs *regs);
/* global mpic for pSeries */
extern struct mpic *pSeries_mpic;
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MPIC_H */
diff --git a/include/asm-powerpc/mutex.h b/include/asm-powerpc/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-powerpc/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-powerpc/numnodes.h b/include/asm-powerpc/numnodes.h
index 795533aca095..e138edae09dd 100644
--- a/include/asm-powerpc/numnodes.h
+++ b/include/asm-powerpc/numnodes.h
@@ -1,7 +1,9 @@
#ifndef _ASM_POWERPC_MAX_NUMNODES_H
#define _ASM_POWERPC_MAX_NUMNODES_H
+#ifdef __KERNEL__
/* Max 16 Nodes */
#define NODES_SHIFT 4
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MAX_NUMNODES_H */
diff --git a/include/asm-powerpc/nvram.h b/include/asm-powerpc/nvram.h
index 24bd8c2388ea..f3563e11e260 100644
--- a/include/asm-powerpc/nvram.h
+++ b/include/asm-powerpc/nvram.h
@@ -55,6 +55,7 @@ struct nvram_header {
char name[12];
};
+#ifdef __KERNEL__
struct nvram_partition {
struct list_head partition;
struct nvram_header header;
@@ -69,6 +70,7 @@ extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
extern int pSeries_nvram_init(void);
extern int mmio_nvram_init(void);
+#endif /* __KERNEL__ */
/* PowerMac specific nvram stuffs */
@@ -78,6 +80,7 @@ enum {
pmac_nvram_NR /* MacOS Name Registry partition */
};
+#ifdef __KERNEL__
/* Return partition offset in nvram */
extern int pmac_get_partition(int partition);
@@ -91,6 +94,7 @@ extern void nvram_sync(void);
/* Normal access to NVRAM */
extern unsigned char nvram_read_byte(int i);
extern void nvram_write_byte(unsigned char c, int i);
+#endif
/* Some offsets in XPRAM */
#define PMAC_XPRAM_MACHINE_LOC 0xe4
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index ddb16aae0bd6..6249a7c39639 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_OF_DEVICE_H
#define _ASM_POWERPC_OF_DEVICE_H
+#ifdef __KERNEL__
#include <linux/device.h>
#include <linux/mod_devicetable.h>
@@ -61,4 +62,5 @@ extern struct of_device *of_platform_device_create(struct device_node *np,
struct device *parent);
extern void of_release_dev(struct device *dev);
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OF_DEVICE_H */
diff --git a/include/asm-powerpc/ohare.h b/include/asm-powerpc/ohare.h
index 023b59772231..0d030f9dea24 100644
--- a/include/asm-powerpc/ohare.h
+++ b/include/asm-powerpc/ohare.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_POWERPC_OHARE_H
+#define _ASM_POWERPC_OHARE_H
+#ifdef __KERNEL__
/*
* ohare.h: definitions for using the "O'Hare" I/O controller chip.
*
@@ -46,3 +49,6 @@
* Contributed by Harry Eaton.
*/
#define STARMAX_FEATURES 0xbeff7a
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_OHARE_H */
diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h
index 8013cd273ced..338e6a7cff4a 100644
--- a/include/asm-powerpc/oprofile_impl.h
+++ b/include/asm-powerpc/oprofile_impl.h
@@ -11,6 +11,7 @@
#ifndef _ASM_POWERPC_OPROFILE_IMPL_H
#define _ASM_POWERPC_OPROFILE_IMPL_H
+#ifdef __KERNEL__
#define OP_MAX_COUNTER 8
@@ -22,24 +23,22 @@ struct op_counter_config {
unsigned long enabled;
unsigned long event;
unsigned long count;
+ /* Classic doesn't support per-counter user/kernel selection */
unsigned long kernel;
-#ifdef __powerpc64__
- /* We dont support per counter user/kernel selection */
-#endif
unsigned long user;
unsigned long unit_mask;
};
/* System-wide configuration as set via oprofilefs. */
struct op_system_config {
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
unsigned long mmcr0;
unsigned long mmcr1;
unsigned long mmcra;
#endif
unsigned long enable_kernel;
unsigned long enable_user;
-#ifdef __powerpc64__
+#ifdef CONFIG_PPC64
unsigned long backtrace_spinlocks;
#endif
};
@@ -49,9 +48,7 @@ struct op_powerpc_model {
void (*reg_setup) (struct op_counter_config *,
struct op_system_config *,
int num_counters);
-#ifdef __powerpc64__
void (*cpu_setup) (void *);
-#endif
void (*start) (struct op_counter_config *);
void (*stop) (void);
void (*handle_interrupt) (struct pt_regs *,
@@ -59,10 +56,19 @@ struct op_powerpc_model {
int num_counters;
};
-#ifdef __powerpc64__
+#ifdef CONFIG_FSL_BOOKE
+extern struct op_powerpc_model op_model_fsl_booke;
+#else /* Otherwise, it's classic */
+
+#ifdef CONFIG_PPC64
extern struct op_powerpc_model op_model_rs64;
extern struct op_powerpc_model op_model_power4;
+#else /* Otherwise, CONFIG_PPC32 */
+extern struct op_powerpc_model op_model_7450;
+#endif
+
+/* All the classic PPC parts use these */
static inline unsigned int ctr_read(unsigned int i)
{
switch(i) {
@@ -78,10 +84,14 @@ static inline unsigned int ctr_read(unsigned int i)
return mfspr(SPRN_PMC5);
case 5:
return mfspr(SPRN_PMC6);
+
+/* No PPC32 chip has more than 6 so far */
+#ifdef CONFIG_PPC64
case 6:
return mfspr(SPRN_PMC7);
case 7:
return mfspr(SPRN_PMC8);
+#endif
default:
return 0;
}
@@ -108,16 +118,21 @@ static inline void ctr_write(unsigned int i, unsigned int val)
case 5:
mtspr(SPRN_PMC6, val);
break;
+
+/* No PPC32 chip has more than 6, yet */
+#ifdef CONFIG_PPC64
case 6:
mtspr(SPRN_PMC7, val);
break;
case 7:
mtspr(SPRN_PMC8, val);
break;
+#endif
default:
break;
}
}
-#endif /* __powerpc64__ */
+#endif /* !CONFIG_FSL_BOOKE */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OPROFILE_IMPL_H */
diff --git a/include/asm-powerpc/pSeries_reconfig.h b/include/asm-powerpc/pSeries_reconfig.h
index c0db1ea7f7d1..ea6cfb8efb84 100644
--- a/include/asm-powerpc/pSeries_reconfig.h
+++ b/include/asm-powerpc/pSeries_reconfig.h
@@ -1,5 +1,6 @@
#ifndef _PPC64_PSERIES_RECONFIG_H
#define _PPC64_PSERIES_RECONFIG_H
+#ifdef __KERNEL__
#include <linux/notifier.h>
@@ -22,4 +23,5 @@ static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
#endif /* CONFIG_PPC_PSERIES */
+#endif /* __KERNEL__ */
#endif /* _PPC64_PSERIES_RECONFIG_H */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 92c765c35bd0..c9add8f1ad94 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -14,15 +14,16 @@
*/
#ifndef _ASM_POWERPC_PACA_H
#define _ASM_POWERPC_PACA_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <asm/types.h>
#include <asm/lppaca.h>
-#include <asm/iseries/it_lp_reg_save.h>
#include <asm/mmu.h>
register struct paca_struct *local_paca asm("r13");
#define get_paca() local_paca
+#define get_lppaca() (get_paca()->lppaca_ptr)
struct task_struct;
@@ -31,9 +32,9 @@ struct task_struct;
*
* This structure is not directly accessed by firmware or the service
* processor except for the first two pointers that point to the
- * lppaca area and the ItLpRegSave area for this CPU. Both the
- * lppaca and ItLpRegSave objects are currently contained within the
- * PACA but they do not need to be.
+ * lppaca area and the ItLpRegSave area for this CPU. The lppaca
+ * object is currently contained within the PACA but it doesn't need
+ * to be.
*/
struct paca_struct {
/*
@@ -48,7 +49,9 @@ struct paca_struct {
* accessed by the firmware
*/
struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */
- struct ItLpRegSave *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
+#ifdef CONFIG_PPC_ISERIES
+ void *reg_save_ptr; /* Pointer to LpRegSave for PLIC */
+#endif /* CONFIG_PPC_ISERIES */
/*
* MAGIC: the spinlock functions in arch/ppc64/lib/locks.c
@@ -59,11 +62,11 @@ struct paca_struct {
u16 lock_token; /* Constant 0x8000, used in locks */
u16 paca_index; /* Logical processor number */
- u32 default_decr; /* Default decrementer value */
u64 kernel_toc; /* Kernel TOC address */
u64 stab_real; /* Absolute address of segment table */
u64 stab_addr; /* Virtual address of segment table */
void *emergency_sp; /* pointer to emergency stack */
+ u64 data_offset; /* per cpu data offset */
s16 hw_cpu_id; /* Physical processor number */
u8 cpu_start; /* At startup, processor spins until */
/* this becomes non-zero. */
@@ -90,31 +93,12 @@ struct paca_struct {
struct task_struct *__current; /* Pointer to current */
u64 kstack; /* Saved Kernel stack addr */
u64 stab_rr; /* stab/slb round-robin counter */
- u64 next_jiffy_update_tb; /* TB value for next jiffy update */
u64 saved_r1; /* r1 save for RTAS calls */
u64 saved_msr; /* MSR saved here by enter_rtas */
u8 proc_enabled; /* irq soft-enable flag */
-
- /* not yet used */
- u64 exdsi[8]; /* used for linear mapping hash table misses */
-
- /*
- * iSeries structure which the hypervisor knows about -
- * this structure should not cross a page boundary.
- * The vpa_init/register_vpa call is now known to fail if the
- * lppaca structure crosses a page boundary.
- * The lppaca is also used on POWER5 pSeries boxes.
- * The lppaca is 640 bytes long, and cannot readily change
- * since the hypervisor knows its layout, so a 1kB
- * alignment will suffice to ensure that it doesn't
- * cross a page boundary.
- */
- struct lppaca lppaca __attribute__((__aligned__(0x400)));
-#ifdef CONFIG_PPC_ISERIES
- struct ItLpRegSave reg_save;
-#endif
};
extern struct paca_struct paca[];
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PACA_H */
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index 18c1e5ee81a3..0b82df483f7f 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -37,8 +37,30 @@
*/
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
+/*
+ * KERNELBASE is the virtual address of the start of the kernel, it's often
+ * the same as PAGE_OFFSET, but _might not be_.
+ *
+ * The kdump dump kernel is one example where KERNELBASE != PAGE_OFFSET.
+ *
+ * To get a physical address from a virtual one you subtract PAGE_OFFSET,
+ * _not_ KERNELBASE.
+ *
+ * If you want to know something's offset from the start of the kernel you
+ * should subtract KERNELBASE.
+ *
+ * If you want to test if something's a kernel address, use is_kernel_addr().
+ */
+
+#ifdef CONFIG_CRASH_DUMP
+/* Kdump kernel runs at 32 MB, change at your peril. */
+#define PHYSICAL_START 0x2000000
+#else
+#define PHYSICAL_START 0x0
+#endif
+
#define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START)
-#define KERNELBASE PAGE_OFFSET
+#define KERNELBASE (PAGE_OFFSET + PHYSICAL_START)
#ifdef CONFIG_DISCONTIGMEM
#define page_to_pfn(page) discontigmem_page_to_pfn(page)
@@ -56,7 +78,7 @@
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
-#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE))
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
/*
@@ -86,6 +108,12 @@
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
+/*
+ * Don't compare things with KERNELBASE or PAGE_OFFSET to test for
+ * "kernelness", use is_kernel_addr() - it should do what you want.
+ */
+#define is_kernel_addr(x) ((x) >= PAGE_OFFSET)
+
#ifndef __ASSEMBLY__
#undef STRICT_MM_TYPECHECKS
@@ -150,7 +178,7 @@ typedef unsigned long pmd_t;
#define pmd_val(x) (x)
#define __pmd(x) (x)
-#ifndef CONFIG_PPC_64K_PAGES
+#if defined(CONFIG_PPC64) && !defined(CONFIG_PPC_64K_PAGES)
typedef unsigned long pud_t;
#define pud_val(x) (x)
#define __pud(x) (x)
diff --git a/include/asm-powerpc/page_32.h b/include/asm-powerpc/page_32.h
index 7259cfd85da9..2677bad70f40 100644
--- a/include/asm-powerpc/page_32.h
+++ b/include/asm-powerpc/page_32.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_PAGE_32_H
#define _ASM_POWERPC_PAGE_32_H
+#ifdef __KERNEL__
#define VM_DATA_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS32
@@ -37,4 +38,5 @@ extern __inline__ int get_order(unsigned long size)
#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PAGE_32_H */
diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h
index 6642c0125001..3fb061bab9ec 100644
--- a/include/asm-powerpc/page_64.h
+++ b/include/asm-powerpc/page_64.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_PAGE_64_H
#define _ASM_POWERPC_PAGE_64_H
+#ifdef __KERNEL__
/*
* Copyright (C) 2001 PPC64 Team, IBM Corp
@@ -25,16 +26,6 @@
*/
#define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT)
-#define REGION_SIZE 4UL
-#define REGION_SHIFT 60UL
-#define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
-
-#define VMALLOCBASE ASM_CONST(0xD000000000000000)
-#define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT)
-#define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT)
-#define USER_REGION_ID (0UL)
-#define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
-
/* Segment size */
#define SID_SHIFT 28
#define SID_MASK 0xfffffffffUL
@@ -180,4 +171,5 @@ extern unsigned int HPAGE_SHIFT;
#include <asm-generic/page.h>
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PAGE_64_H */
diff --git a/include/asm-powerpc/param.h b/include/asm-powerpc/param.h
index bdc724f70884..094f63d4d5ca 100644
--- a/include/asm-powerpc/param.h
+++ b/include/asm-powerpc/param.h
@@ -1,8 +1,6 @@
#ifndef _ASM_POWERPC_PARAM_H
#define _ASM_POWERPC_PARAM_H
-#include <linux/config.h>
-
#ifdef __KERNEL__
#define HZ CONFIG_HZ /* internal kernel timer frequency */
#define USER_HZ 100 /* for user interfaces in "ticks" */
diff --git a/include/asm-powerpc/parport.h b/include/asm-powerpc/parport.h
index d86b410a6f8b..3fca21ddf546 100644
--- a/include/asm-powerpc/parport.h
+++ b/include/asm-powerpc/parport.h
@@ -8,11 +8,37 @@
#ifndef _ASM_POWERPC_PARPORT_H
#define _ASM_POWERPC_PARPORT_H
+#ifdef __KERNEL__
+
+#include <asm/prom.h>
+
+extern struct parport *parport_pc_probe_port (unsigned long int base,
+ unsigned long int base_hi,
+ int irq, int dma,
+ struct pci_dev *dev);
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
{
- return parport_pc_find_isa_ports (autoirq, autodma);
+ struct device_node *np;
+ u32 *prop;
+ u32 io1, io2;
+ int propsize;
+ int count = 0;
+ for (np = NULL; (np = of_find_compatible_node(np,
+ "parallel",
+ "pnpPNP,400")) != NULL;) {
+ prop = (u32 *)get_property(np, "reg", &propsize);
+ if (!prop || propsize > 6*sizeof(u32))
+ continue;
+ io1 = prop[1]; io2 = prop[2];
+ prop = (u32 *)get_property(np, "interrupts", NULL);
+ if (!prop)
+ continue;
+ if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL)
+ count++;
+ }
+ return count;
}
+#endif /* __KERNEL__ */
#endif /* !(_ASM_POWERPC_PARPORT_H) */
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 223ec7bd81da..38de92d41a14 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_PCI_BRIDGE_H
#define _ASM_POWERPC_PCI_BRIDGE_H
+#ifdef __KERNEL__
#ifndef CONFIG_PPC64
#include <asm-ppc/pci-bridge.h>
@@ -60,16 +61,17 @@ 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 busno; /* pci bus number */
+ int bussubno; /* pci subordinate bus number */
+ int devfn; /* pci device and function number */
+ int class_code; /* pci device class */
#ifdef CONFIG_PPC_PSERIES
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
+ int eeh_pe_config_addr; /* new-style partition endpoint address */
int eeh_check_count; /* # times driver ignored error */
int eeh_freeze_count; /* # times this device froze up. */
- int eeh_is_bridge; /* device is pci-to-pci bridge */
#endif
int pci_ext_config_space; /* for pci devices */
struct pci_controller *phb; /* for pci devices */
@@ -125,12 +127,20 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
return bus->sysdata; /* Must be root bus (PHB) */
}
+/** Find the bus corresponding to the indicated device node */
+struct pci_bus * pcibios_find_pci_bus(struct device_node *dn);
+
extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
struct device_node *dev, int primary);
-extern int pcibios_remove_root_bus(struct pci_controller *phb);
+/** Remove all of the PCI devices under this bus */
+void pcibios_remove_pci_devices(struct pci_bus *bus);
-extern void phbs_remap_io(void);
+/** Discover new pci devices under this bus, and add them */
+void pcibios_add_pci_devices(struct pci_bus * bus);
+void pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus);
+
+extern int pcibios_remove_root_bus(struct pci_controller *phb);
static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
{
@@ -140,14 +150,27 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
return PCI_DN(busdn)->phb;
}
+extern struct pci_controller*
+pci_find_hose_for_OF_device(struct device_node* node);
+
extern struct pci_controller *
pcibios_alloc_controller(struct device_node *dev);
extern void pcibios_free_controller(struct pci_controller *phb);
+#ifdef CONFIG_PCI
+extern unsigned long pci_address_to_pio(phys_addr_t address);
+#else
+static inline unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ return (unsigned long)-1;
+}
+#endif
+
/* Return values for ppc_md.pci_probe_mode function */
#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */
#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index d5934a076bd0..5d2c9e6c4be2 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -216,6 +216,8 @@ extern int remap_bus_range(struct pci_bus *bus);
extern void pcibios_fixup_device_resources(struct pci_dev *dev,
struct pci_bus *bus);
+extern void pcibios_claim_one_bus(struct pci_bus *b);
+
extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
extern struct pci_dev *of_create_pci_dev(struct device_node *node,
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 06a959d67234..e31922c50e53 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -1 +1,57 @@
+#ifndef _ASM_POWERPC_PERCPU_H_
+#define _ASM_POWERPC_PERCPU_H_
+#ifdef __powerpc64__
+#include <linux/compiler.h>
+
+/*
+ * Same as asm-generic/percpu.h, except that we store the per cpu offset
+ * in the paca. Based on the x86-64 implementation.
+ */
+
+#ifdef CONFIG_SMP
+
+#include <asm/paca.h>
+
+#define __per_cpu_offset(cpu) (paca[cpu].data_offset)
+#define __my_cpu_offset() get_paca()->data_offset
+
+/* Separate out the type, so (int[3], foo) works. */
+#define DEFINE_PER_CPU(type, name) \
+ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
+
+/* var is in discarded region: offset to particular copy we want */
+#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
+#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
+
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size) \
+do { \
+ unsigned int __i; \
+ for (__i = 0; __i < NR_CPUS; __i++) \
+ if (cpu_possible(__i)) \
+ memcpy((pcpudst)+__per_cpu_offset(__i), \
+ (src), (size)); \
+} while (0)
+
+extern void setup_per_cpu_areas(void);
+
+#else /* ! SMP */
+
+#define DEFINE_PER_CPU(type, name) \
+ __typeof__(type) per_cpu__##name
+
+#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
+#define __get_cpu_var(var) per_cpu__##var
+
+#endif /* SMP */
+
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
+
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
+
+#else
#include <asm-generic/percpu.h>
+#endif
+
+#endif /* _ASM_POWERPC_PERCPU_H_ */
diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h
index bfc2113b3630..9f5b052784a5 100644
--- a/include/asm-powerpc/pgalloc.h
+++ b/include/asm-powerpc/pgalloc.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_PGALLOC_H
#define _ASM_POWERPC_PGALLOC_H
+#ifdef __KERNEL__
#ifndef CONFIG_PPC64
#include <asm-ppc/pgalloc.h>
@@ -153,4 +154,5 @@ extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
#define check_pgt_cache() do { } while (0)
#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PGALLOC_H */
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
index 154f1840ece4..653915014dcd 100644
--- a/include/asm-powerpc/pgtable-64k.h
+++ b/include/asm-powerpc/pgtable-64k.h
@@ -1,3 +1,7 @@
+#ifndef _ASM_POWERPC_PGTABLE_64K_H
+#define _ASM_POWERPC_PGTABLE_64K_H
+#ifdef __KERNEL__
+
#include <asm-generic/pgtable-nopud.h>
@@ -88,3 +92,5 @@
#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_PGTABLE_64K_H */
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index 0303f57366c1..e38931379a72 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_PGTABLE_H
#define _ASM_POWERPC_PGTABLE_H
+#ifdef __KERNEL__
#ifndef CONFIG_PPC64
#include <asm-ppc/pgtable.h>
@@ -58,6 +59,17 @@ struct mm_struct;
#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE)
/*
+ * Region IDs
+ */
+#define REGION_SHIFT 60UL
+#define REGION_MASK (0xfUL << REGION_SHIFT)
+#define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
+
+#define VMALLOC_REGION_ID (REGION_ID(VMALLOC_START))
+#define KERNEL_REGION_ID (REGION_ID(PAGE_OFFSET))
+#define USER_REGION_ID (0UL)
+
+/*
* Common bits in a linux-style PTE. These match the bits in the
* (hardware-defined) PowerPC PTE as closely as possible. Additional
* bits may be defined in pgtable-*.h
@@ -521,4 +533,5 @@ void pgtable_cache_init(void);
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_PPC64 */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PGTABLE_H */
diff --git a/include/asm-powerpc/pmac_feature.h b/include/asm-powerpc/pmac_feature.h
index e9683bcff19b..3221628130c4 100644
--- a/include/asm-powerpc/pmac_feature.h
+++ b/include/asm-powerpc/pmac_feature.h
@@ -121,6 +121,7 @@
#define PMAC_TYPE_IMAC_G5 0x152 /* iMac G5 */
#define PMAC_TYPE_XSERVE_G5 0x153 /* Xserve G5 */
#define PMAC_TYPE_UNKNOWN_K2 0x19f /* Any other K2 based */
+#define PMAC_TYPE_UNKNOWN_SHASTA 0x19e /* Any other Shasta based */
/*
* Motherboard flags
@@ -317,10 +318,6 @@ extern void pmac_register_agp_pm(struct pci_dev *bridge,
extern void pmac_suspend_agp_for_card(struct pci_dev *dev);
extern void pmac_resume_agp_for_card(struct pci_dev *dev);
-/* Used by the via-pmu driver for suspend/resume
- */
-extern void pmac_tweak_clock_spreading(int enable);
-
/*
* The part below is for use by macio_asic.c only, do not rely
* on the data structures or constants below in a normal driver
@@ -341,6 +338,7 @@ enum {
macio_pangea,
macio_intrepid,
macio_keylargo2,
+ macio_shasta,
};
struct macio_chip
@@ -376,5 +374,24 @@ extern struct macio_chip* macio_find(struct device_node* child, int type);
#define MACIO_IN8(r) (in_8(MACIO_FCR8(macio,r)))
#define MACIO_OUT8(r,v) (out_8(MACIO_FCR8(macio,r), (v)))
+/*
+ * Those are exported by pmac feature for internal use by arch code
+ * only like the platform function callbacks, do not use directly in drivers
+ */
+extern spinlock_t feature_lock;
+extern struct device_node *uninorth_node;
+extern u32 __iomem *uninorth_base;
+
+/*
+ * Uninorth reg. access. Note that Uni-N regs are big endian
+ */
+
+#define UN_REG(r) (uninorth_base + ((r) >> 2))
+#define UN_IN(r) (in_be32(UN_REG(r)))
+#define UN_OUT(r,v) (out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v)))
+
+
#endif /* __PPC_ASM_PMAC_FEATURE_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pmac_low_i2c.h b/include/asm-powerpc/pmac_low_i2c.h
index 809a5963d5e7..131011bd7e76 100644
--- a/include/asm-powerpc/pmac_low_i2c.h
+++ b/include/asm-powerpc/pmac_low_i2c.h
@@ -11,33 +11,97 @@
*/
#ifndef __PMAC_LOW_I2C_H__
#define __PMAC_LOW_I2C_H__
+#ifdef __KERNEL__
/* i2c mode (based on the platform functions format) */
enum {
- pmac_low_i2c_mode_dumb = 1,
- pmac_low_i2c_mode_std = 2,
- pmac_low_i2c_mode_stdsub = 3,
- pmac_low_i2c_mode_combined = 4,
+ pmac_i2c_mode_dumb = 1,
+ pmac_i2c_mode_std = 2,
+ pmac_i2c_mode_stdsub = 3,
+ pmac_i2c_mode_combined = 4,
};
/* RW bit in address */
enum {
- pmac_low_i2c_read = 0x01,
- pmac_low_i2c_write = 0x00
+ pmac_i2c_read = 0x01,
+ pmac_i2c_write = 0x00
};
+/* i2c bus type */
+enum {
+ pmac_i2c_bus_keywest = 0,
+ pmac_i2c_bus_pmu = 1,
+ pmac_i2c_bus_smu = 2,
+};
+
+/* i2c bus features */
+enum {
+ /* can_largesub : supports >1 byte subaddresses (SMU only) */
+ pmac_i2c_can_largesub = 0x00000001u,
+
+ /* multibus : device node holds multiple busses, bus number is
+ * encoded in bits 0xff00 of "reg" of a given device
+ */
+ pmac_i2c_multibus = 0x00000002u,
+};
+
+/* i2c busses in the system */
+struct pmac_i2c_bus;
+struct i2c_adapter;
+
/* Init, called early during boot */
-extern void pmac_init_low_i2c(void);
+extern int pmac_i2c_init(void);
+
+/* Lookup an i2c bus for a device-node. The node can be either the bus
+ * node itself or a device below it. In the case of a multibus, the bus
+ * node itself is the controller node, else, it's a child of the controller
+ * node
+ */
+extern struct pmac_i2c_bus *pmac_i2c_find_bus(struct device_node *node);
+
+/* Get the address for an i2c device. This strips the bus number if
+ * necessary. The 7 bits address is returned 1 bit right shifted so that the
+ * direction can be directly ored in
+ */
+extern u8 pmac_i2c_get_dev_addr(struct device_node *device);
+
+/* Get infos about a bus */
+extern struct device_node *pmac_i2c_get_controller(struct pmac_i2c_bus *bus);
+extern struct device_node *pmac_i2c_get_bus_node(struct pmac_i2c_bus *bus);
+extern int pmac_i2c_get_type(struct pmac_i2c_bus *bus);
+extern int pmac_i2c_get_flags(struct pmac_i2c_bus *bus);
+extern int pmac_i2c_get_channel(struct pmac_i2c_bus *bus);
+
+/* i2c layer adapter attach/detach */
+extern void pmac_i2c_attach_adapter(struct pmac_i2c_bus *bus,
+ struct i2c_adapter *adapter);
+extern void pmac_i2c_detach_adapter(struct pmac_i2c_bus *bus,
+ struct i2c_adapter *adapter);
+extern struct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus);
+extern struct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter);
+
+/* March a device or bus with an i2c adapter structure, to be used by drivers
+ * to match device-tree nodes with i2c adapters during adapter discovery
+ * callbacks
+ */
+extern int pmac_i2c_match_adapter(struct device_node *dev,
+ struct i2c_adapter *adapter);
+
-/* Locking functions exposed to i2c-keywest */
-int pmac_low_i2c_lock(struct device_node *np);
-int pmac_low_i2c_unlock(struct device_node *np);
+/* (legacy) Locking functions exposed to i2c-keywest */
+extern int pmac_low_i2c_lock(struct device_node *np);
+extern int pmac_low_i2c_unlock(struct device_node *np);
/* Access functions for platform code */
-int pmac_low_i2c_open(struct device_node *np, int channel);
-int pmac_low_i2c_close(struct device_node *np);
-int pmac_low_i2c_setmode(struct device_node *np, int mode);
-int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len);
+extern int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled);
+extern void pmac_i2c_close(struct pmac_i2c_bus *bus);
+extern int pmac_i2c_setmode(struct pmac_i2c_bus *bus, int mode);
+extern int pmac_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize,
+ u32 subaddr, u8 *data, int len);
+/* Suspend/resume code called by via-pmu directly for now */
+extern void pmac_pfunc_i2c_suspend(void);
+extern void pmac_pfunc_i2c_resume(void);
+#endif /* __KERNEL__ */
#endif /* __PMAC_LOW_I2C_H__ */
diff --git a/include/asm-powerpc/pmac_pfunc.h b/include/asm-powerpc/pmac_pfunc.h
new file mode 100644
index 000000000000..d9728c80f86d
--- /dev/null
+++ b/include/asm-powerpc/pmac_pfunc.h
@@ -0,0 +1,253 @@
+#ifndef __PMAC_PFUNC_H__
+#define __PMAC_PFUNC_H__
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+/* Flags in command lists */
+#define PMF_FLAGS_ON_INIT 0x80000000u
+#define PMF_FLGAS_ON_TERM 0x40000000u
+#define PMF_FLAGS_ON_SLEEP 0x20000000u
+#define PMF_FLAGS_ON_WAKE 0x10000000u
+#define PMF_FLAGS_ON_DEMAND 0x08000000u
+#define PMF_FLAGS_INT_GEN 0x04000000u
+#define PMF_FLAGS_HIGH_SPEED 0x02000000u
+#define PMF_FLAGS_LOW_SPEED 0x01000000u
+#define PMF_FLAGS_SIDE_EFFECTS 0x00800000u
+
+/*
+ * Arguments to a platform function call.
+ *
+ * NOTE: By convention, pointer arguments point to an u32
+ */
+struct pmf_args {
+ union {
+ u32 v;
+ u32 *p;
+ } u[4];
+ unsigned int count;
+};
+
+/*
+ * A driver capable of interpreting commands provides a handlers
+ * structure filled with whatever handlers are implemented by this
+ * driver. Non implemented handlers are left NULL.
+ *
+ * PMF_STD_ARGS are the same arguments that are passed to the parser
+ * and that gets passed back to the various handlers.
+ *
+ * Interpreting a given function always start with a begin() call which
+ * returns an instance data to be passed around subsequent calls, and
+ * ends with an end() call. This allows the low level driver to implement
+ * locking policy or per-function instance data.
+ *
+ * For interrupt capable functions, irq_enable() is called when a client
+ * registers, and irq_disable() is called when the last client unregisters
+ * Note that irq_enable & irq_disable are called within a semaphore held
+ * by the core, thus you should not try to register yourself to some other
+ * pmf interrupt during those calls.
+ */
+
+#define PMF_STD_ARGS struct pmf_function *func, void *instdata, \
+ struct pmf_args *args
+
+struct pmf_function;
+
+struct pmf_handlers {
+ void * (*begin)(struct pmf_function *func, struct pmf_args *args);
+ void (*end)(struct pmf_function *func, void *instdata);
+
+ int (*irq_enable)(struct pmf_function *func);
+ int (*irq_disable)(struct pmf_function *func);
+
+ int (*write_gpio)(PMF_STD_ARGS, u8 value, u8 mask);
+ int (*read_gpio)(PMF_STD_ARGS, u8 mask, int rshift, u8 xor);
+
+ int (*write_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
+ int (*read_reg32)(PMF_STD_ARGS, u32 offset);
+ int (*write_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
+ int (*read_reg16)(PMF_STD_ARGS, u32 offset);
+ int (*write_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
+ int (*read_reg8)(PMF_STD_ARGS, u32 offset);
+
+ int (*delay)(PMF_STD_ARGS, u32 duration);
+
+ int (*wait_reg32)(PMF_STD_ARGS, u32 offset, u32 value, u32 mask);
+ int (*wait_reg16)(PMF_STD_ARGS, u32 offset, u16 value, u16 mask);
+ int (*wait_reg8)(PMF_STD_ARGS, u32 offset, u8 value, u8 mask);
+
+ int (*read_i2c)(PMF_STD_ARGS, u32 len);
+ int (*write_i2c)(PMF_STD_ARGS, u32 len, const u8 *data);
+ int (*rmw_i2c)(PMF_STD_ARGS, u32 masklen, u32 valuelen, u32 totallen,
+ const u8 *maskdata, const u8 *valuedata);
+
+ int (*read_cfg)(PMF_STD_ARGS, u32 offset, u32 len);
+ int (*write_cfg)(PMF_STD_ARGS, u32 offset, u32 len, const u8 *data);
+ int (*rmw_cfg)(PMF_STD_ARGS, u32 offset, u32 masklen, u32 valuelen,
+ u32 totallen, const u8 *maskdata, const u8 *valuedata);
+
+ int (*read_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len);
+ int (*write_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 len, const u8 *data);
+ int (*set_i2c_mode)(PMF_STD_ARGS, int mode);
+ int (*rmw_i2c_sub)(PMF_STD_ARGS, u8 subaddr, u32 masklen, u32 valuelen,
+ u32 totallen, const u8 *maskdata,
+ const u8 *valuedata);
+
+ int (*read_reg32_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
+ u32 xor);
+ int (*read_reg16_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
+ u32 xor);
+ int (*read_reg8_msrx)(PMF_STD_ARGS, u32 offset, u32 mask, u32 shift,
+ u32 xor);
+
+ int (*write_reg32_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
+ int (*write_reg16_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
+ int (*write_reg8_slm)(PMF_STD_ARGS, u32 offset, u32 shift, u32 mask);
+
+ int (*mask_and_compare)(PMF_STD_ARGS, u32 len, const u8 *maskdata,
+ const u8 *valuedata);
+
+ struct module *owner;
+};
+
+
+/*
+ * Drivers who expose platform functions register at init time, this
+ * causes the platform functions for that device node to be parsed in
+ * advance and associated with the device. The data structures are
+ * partially public so a driver can walk the list of platform functions
+ * and eventually inspect the flags
+ */
+struct pmf_device;
+
+struct pmf_function {
+ /* All functions for a given driver are linked */
+ struct list_head link;
+
+ /* Function node & driver data */
+ struct device_node *node;
+ void *driver_data;
+
+ /* For internal use by core */
+ struct pmf_device *dev;
+
+ /* The name is the "xxx" in "platform-do-xxx", this is how
+ * platform functions are identified by this code. Some functions
+ * only operate for a given target, in which case the phandle is
+ * here (or 0 if the filter doesn't apply)
+ */
+ const char *name;
+ u32 phandle;
+
+ /* The flags for that function. You can have several functions
+ * with the same name and different flag
+ */
+ u32 flags;
+
+ /* The actual tokenized function blob */
+ const void *data;
+ unsigned int length;
+
+ /* Interrupt clients */
+ struct list_head irq_clients;
+
+ /* Refcounting */
+ struct kref ref;
+};
+
+/*
+ * For platform functions that are interrupts, one can register
+ * irq_client structures. You canNOT use the same structure twice
+ * as it contains a link member. Also, the callback is called with
+ * a spinlock held, you must not call back into any of the pmf_* functions
+ * from within that callback
+ */
+struct pmf_irq_client {
+ void (*handler)(void *data);
+ void *data;
+ struct module *owner;
+ struct list_head link;
+};
+
+
+/*
+ * Register/Unregister a function-capable driver and its handlers
+ */
+extern int pmf_register_driver(struct device_node *np,
+ struct pmf_handlers *handlers,
+ void *driverdata);
+
+extern void pmf_unregister_driver(struct device_node *np);
+
+
+/*
+ * Register/Unregister interrupt clients
+ */
+extern int pmf_register_irq_client(struct device_node *np,
+ const char *name,
+ struct pmf_irq_client *client);
+
+extern void pmf_unregister_irq_client(struct device_node *np,
+ const char *name,
+ struct pmf_irq_client *client);
+
+/*
+ * Called by the handlers when an irq happens
+ */
+extern void pmf_do_irq(struct pmf_function *func);
+
+
+/*
+ * Low level call to platform functions.
+ *
+ * The phandle can filter on the target object for functions that have
+ * multiple targets, the flags allow you to restrict the call to a given
+ * combination of flags.
+ *
+ * The args array contains as many arguments as is required by the function,
+ * this is dependent on the function you are calling, unfortunately Apple
+ * mecanism provides no way to encode that so you have to get it right at
+ * the call site. Some functions require no args, in which case, you can
+ * pass NULL.
+ *
+ * You can also pass NULL to the name. This will match any function that has
+ * the appropriate combination of flags & phandle or you can pass 0 to the
+ * phandle to match any
+ */
+extern int pmf_do_functions(struct device_node *np, const char *name,
+ u32 phandle, u32 flags, struct pmf_args *args);
+
+
+
+/*
+ * High level call to a platform function.
+ *
+ * This one looks for the platform-xxx first so you should call it to the
+ * actual target if any. It will fallback to platform-do-xxx if it can't
+ * find one. It will also exclusively target functions that have
+ * the "OnDemand" flag.
+ */
+
+extern int pmf_call_function(struct device_node *target, const char *name,
+ struct pmf_args *args);
+
+
+/*
+ * For low latency interrupt usage, you can lookup for on-demand functions
+ * using the functions below
+ */
+
+extern struct pmf_function *pmf_find_function(struct device_node *target,
+ const char *name);
+
+extern struct pmf_function * pmf_get_function(struct pmf_function *func);
+extern void pmf_put_function(struct pmf_function *func);
+
+extern int pmf_call_one(struct pmf_function *func, struct pmf_args *args);
+
+
+/* Suspend/resume code called by via-pmu directly for now */
+extern void pmac_pfunc_base_suspend(void);
+extern void pmac_pfunc_base_resume(void);
+
+#endif /* __PMAC_PFUNC_H__ */
diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h
index 5f41f3a2b293..07d6a4279319 100644
--- a/include/asm-powerpc/pmc.h
+++ b/include/asm-powerpc/pmc.h
@@ -18,6 +18,7 @@
*/
#ifndef _POWERPC_PMC_H
#define _POWERPC_PMC_H
+#ifdef __KERNEL__
#include <asm/ptrace.h>
@@ -44,4 +45,5 @@ void dump_pmcs(void);
extern struct op_powerpc_model op_model_fsl_booke;
#endif
+#endif /* __KERNEL__ */
#endif /* _POWERPC_PMC_H */
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 36cdc869e580..f80482c7231f 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -8,6 +8,7 @@
*/
#ifndef _ASM_POWERPC_PPC_PCI_H
#define _ASM_POWERPC_PPC_PCI_H
+#ifdef __KERNEL__
#include <linux/pci.h>
#include <asm/pci-bridge.h>
@@ -51,6 +52,21 @@ extern unsigned long pci_probe_only;
/* ---- EEH internal-use-only related routines ---- */
#ifdef CONFIG_EEH
+
+void pci_addr_cache_insert_device(struct pci_dev *dev);
+void pci_addr_cache_remove_device(struct pci_dev *dev);
+void pci_addr_cache_build(void);
+struct pci_dev *pci_get_device_by_addr(unsigned long addr);
+
+/**
+ * eeh_slot_error_detail -- record and EEH error condition to the log
+ * @severity: 1 if temporary, 2 if permanent failure.
+ *
+ * Obtains the the EEH error details from the RTAS subsystem,
+ * and then logs these details with the RTAS error log system.
+ */
+void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
+
/**
* rtas_set_slot_reset -- unfreeze a frozen slot
*
@@ -58,8 +74,10 @@ extern unsigned long pci_probe_only;
* does this by asserting the PCI #RST line for 1/8th of
* a second; this routine will sleep while the adapter is
* being reset.
+ *
+ * Returns a non-zero value if the reset failed.
*/
-void rtas_set_slot_reset (struct pci_dn *);
+int rtas_set_slot_reset (struct pci_dn *);
/**
* eeh_restore_bars - Restore device configuration info.
@@ -83,6 +101,7 @@ void eeh_restore_bars(struct pci_dn *);
void rtas_configure_bridge(struct pci_dn *);
int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
+int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
/**
* mark and clear slots: find "partition endpoint" PE and set or
@@ -91,6 +110,10 @@ int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
void eeh_mark_slot (struct device_node *dn, int mode_flag);
void eeh_clear_slot (struct device_node *dn, int mode_flag);
+/* Find the associated "Partiationable Endpoint" PE */
+struct device_node * find_device_pe(struct device_node *dn);
+
#endif
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_PPC_PCI_H */
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h
index c27baa0563fe..ab8688d39024 100644
--- a/include/asm-powerpc/ppc_asm.h
+++ b/include/asm-powerpc/ppc_asm.h
@@ -94,6 +94,7 @@
#define RFDI .long 0x4c00004e /* rfdi instruction */
#define RFMCI .long 0x4c00004c /* rfmci instruction */
+#ifdef __KERNEL__
#ifdef CONFIG_PPC64
#define XGLUE(a,b) a##b
@@ -155,52 +156,56 @@ n:
#endif
/*
- * LOADADDR( rn, name )
- * loads the address of 'name' into 'rn'
+ * LOAD_REG_IMMEDIATE(rn, expr)
+ * Loads the value of the constant expression 'expr' into register 'rn'
+ * using immediate instructions only. Use this when it's important not
+ * to reference other data (i.e. on ppc64 when the TOC pointer is not
+ * valid).
*
- * LOADBASE( rn, name )
- * loads the address (possibly without the low 16 bits) of 'name' into 'rn'
- * suitable for base+disp addressing
+ * LOAD_REG_ADDR(rn, name)
+ * Loads the address of label 'name' into register 'rn'. Use this when
+ * you don't particularly need immediate instructions only, but you need
+ * the whole address in one register (e.g. it's a structure address and
+ * you want to access various offsets within it). On ppc32 this is
+ * identical to LOAD_REG_IMMEDIATE.
+ *
+ * LOAD_REG_ADDRBASE(rn, name)
+ * ADDROFF(name)
+ * LOAD_REG_ADDRBASE loads part of the address of label 'name' into
+ * register 'rn'. ADDROFF(name) returns the remainder of the address as
+ * a constant expression. ADDROFF(name) is a signed expression < 16 bits
+ * in size, so is suitable for use directly as an offset in load and store
+ * instructions. Use this when loading/storing a single word or less as:
+ * LOAD_REG_ADDRBASE(rX, name)
+ * ld rY,ADDROFF(name)(rX)
*/
#ifdef __powerpc64__
-#define LOADADDR(rn,name) \
- lis rn,name##@highest; \
- ori rn,rn,name##@higher; \
- rldicr rn,rn,32,31; \
- oris rn,rn,name##@h; \
- ori rn,rn,name##@l
-
-#define LOADBASE(rn,name) \
- ld rn,name@got(r2)
-
-#define OFF(name) 0
-
-#define SET_REG_TO_CONST(reg, value) \
- lis reg,(((value)>>48)&0xFFFF); \
- ori reg,reg,(((value)>>32)&0xFFFF); \
- rldicr reg,reg,32,31; \
- oris reg,reg,(((value)>>16)&0xFFFF); \
- ori reg,reg,((value)&0xFFFF);
-
-#define SET_REG_TO_LABEL(reg, label) \
- lis reg,(label)@highest; \
- ori reg,reg,(label)@higher; \
- rldicr reg,reg,32,31; \
- oris reg,reg,(label)@h; \
- ori reg,reg,(label)@l;
+#define LOAD_REG_IMMEDIATE(reg,expr) \
+ lis (reg),(expr)@highest; \
+ ori (reg),(reg),(expr)@higher; \
+ rldicr (reg),(reg),32,31; \
+ oris (reg),(reg),(expr)@h; \
+ ori (reg),(reg),(expr)@l;
+
+#define LOAD_REG_ADDR(reg,name) \
+ ld (reg),name@got(r2)
+
+#define LOAD_REG_ADDRBASE(reg,name) LOAD_REG_ADDR(reg,name)
+#define ADDROFF(name) 0
/* offsets for stack frame layout */
#define LRSAVE 16
#else /* 32-bit */
-#define LOADADDR(rn,name) \
- lis rn,name@ha; \
- addi rn,rn,name@l
-#define LOADBASE(rn,name) \
- lis rn,name@ha
+#define LOAD_REG_IMMEDIATE(reg,expr) \
+ lis (reg),(expr)@ha; \
+ addi (reg),(reg),(expr)@l;
-#define OFF(name) name@l
+#define LOAD_REG_ADDR(reg,name) LOAD_REG_IMMEDIATE(reg, name)
+
+#define LOAD_REG_ADDRBASE(reg, name) lis (reg),name@ha
+#define ADDROFF(name) name@l
/* offsets for stack frame layout */
#define LRSAVE 4
@@ -325,6 +330,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#define CLR_TOP32(r)
#endif
+#endif /* __KERNEL__ */
+
/* The boring bits... */
/* Condition Register Bit Fields */
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index d12382d292d4..415fa393b00c 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -10,7 +10,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/config.h>
#include <asm/reg.h>
#ifndef __ASSEMBLY__
@@ -50,6 +49,7 @@
#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */
+#ifdef __KERNEL__
#define platform_is_pseries() (_machine == PLATFORM_PSERIES || \
_machine == PLATFORM_PSERIES_LPAR)
#define platform_is_lpar() (!!(_machine & PLATFORM_LPAR))
@@ -68,7 +68,6 @@ extern int _chrp_type;
* vendor. Board revision is also made available. This will be moved
* elsewhere soon
*/
-extern unsigned char ucSystemType;
extern unsigned char ucBoardRev;
extern unsigned char ucBoardRevMaj, ucBoardRevMin;
@@ -82,7 +81,7 @@ extern unsigned char ucBoardRevMaj, ucBoardRevMin;
#else
#define _machine 0
#endif /* CONFIG_PPC_MULTIPLATFORM */
-
+#endif /* __KERNEL__ */
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index f999df1c5c90..5b2bd4eefb01 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -65,49 +65,11 @@ struct boot_param_header
typedef u32 phandle;
typedef u32 ihandle;
-struct address_range {
- unsigned long space;
- unsigned long address;
- unsigned long size;
-};
-
struct interrupt_info {
int line;
int sense; /* +ve/-ve logic, edge or level, etc. */
};
-struct pci_address {
- u32 a_hi;
- u32 a_mid;
- u32 a_lo;
-};
-
-struct isa_address {
- u32 a_hi;
- u32 a_lo;
-};
-
-struct isa_range {
- struct isa_address isa_addr;
- struct pci_address pci_addr;
- unsigned int size;
-};
-
-struct reg_property {
- unsigned long address;
- unsigned long size;
-};
-
-struct reg_property32 {
- unsigned int address;
- unsigned int size;
-};
-
-struct reg_property64 {
- u64 address;
- u64 size;
-};
-
struct property {
char *name;
int length;
@@ -120,13 +82,12 @@ struct device_node {
char *type;
phandle node;
phandle linux_phandle;
- int n_addrs;
- struct address_range *addrs;
int n_intrs;
struct interrupt_info *intrs;
char *full_name;
struct property *properties;
+ struct property *deadprops; /* removed properties */
struct device_node *parent;
struct device_node *child;
struct device_node *sibling;
@@ -175,6 +136,9 @@ extern struct device_node *of_find_all_nodes(struct device_node *prev);
extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
+extern struct property *of_find_property(struct device_node *np,
+ const char *name,
+ int *lenp);
extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
@@ -204,6 +168,10 @@ extern int prom_n_size_cells(struct device_node* np);
extern int prom_n_intr_cells(struct device_node* np);
extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
extern int prom_add_property(struct device_node* np, struct property* prop);
+extern int prom_remove_property(struct device_node *np, struct property *prop);
+extern int prom_update_property(struct device_node *np,
+ struct property *newprop,
+ struct property *oldprop);
#ifdef CONFIG_PPC32
/*
@@ -223,5 +191,36 @@ extern struct resource *request_OF_resource(struct device_node* node,
int index, const char* name_postfix);
extern int release_OF_resource(struct device_node* node, int index);
+
+/*
+ * OF address retreival & translation
+ */
+
+
+/* Translate an OF address block into a CPU physical address
+ */
+#define OF_BAD_ADDR ((u64)-1)
+extern u64 of_translate_address(struct device_node *np, u32 *addr);
+
+/* Extract an address from a device, returns the region size and
+ * the address space flags too. The PCI version uses a BAR number
+ * instead of an absolute index
+ */
+extern u32 *of_get_address(struct device_node *dev, int index,
+ u64 *size, unsigned int *flags);
+extern u32 *of_get_pci_address(struct device_node *dev, int bar_no,
+ u64 *size, unsigned int *flags);
+
+/* Get an address as a resource. Note that if your address is
+ * a PIO address, the conversion will fail if the physical address
+ * can't be internally converted to an IO token with
+ * pci_address_to_pio(), that is because it's either called to early
+ * or it can't be matched to any host bridge IO space
+ */
+extern int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r);
+extern int of_pci_address_to_resource(struct device_node *dev, int bar,
+ struct resource *r);
+
#endif /* __KERNEL__ */
#endif /* _POWERPC_PROM_H */
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 1f7ecdb0b6ce..9c550b314823 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -87,7 +87,7 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define force_successful_syscall_return() \
do { \
- current_thread_info()->syscall_noerror = 1; \
+ set_thread_flag(TIF_NOERROR); \
} while(0)
/*
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index eb392d038ed7..12ecc9b9f285 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -145,6 +145,10 @@
#define SPRN_CTR 0x009 /* Count Register */
#define SPRN_CTRLF 0x088
#define SPRN_CTRLT 0x098
+#define CTRL_CT 0xc0000000 /* current thread */
+#define CTRL_CT0 0x80000000 /* thread 0 */
+#define CTRL_CT1 0x40000000 /* thread 1 */
+#define CTRL_TE 0x00c00000 /* thread enable */
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define DABR_TRANSLATION (1UL << 2)
@@ -257,11 +261,11 @@
#define SPRN_HID6 0x3F9 /* BE HID 6 */
#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
-#define SPRN_TSCR 0x399 /* Thread switch control on BE */
-#define SPRN_TTR 0x39A /* Thread switch timeout on BE */
-#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */
-#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */
-#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */
+#define SPRN_TSC_CELL 0x399 /* Thread switch control on Cell */
+#define TSC_CELL_DEC_ENABLE_0 0x400000 /* Decrementer Interrupt */
+#define TSC_CELL_DEC_ENABLE_1 0x200000 /* Decrementer Interrupt */
+#define TSC_CELL_EE_ENABLE 0x100000 /* External Interrupt */
+#define TSC_CELL_EE_BOOST 0x080000 /* External Interrupt Boost */
#define SPRN_TSC 0x3FD /* Thread switch control on others */
#define SPRN_TST 0x3FC /* Thread switch timeout on others */
#if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
@@ -375,6 +379,14 @@
#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+#define SRR1_WAKEMASK 0x00380000 /* reason for wakeup */
+#define SRR1_WAKERESET 0x00380000 /* System reset */
+#define SRR1_WAKESYSERR 0x00300000 /* System error */
+#define SRR1_WAKEEE 0x00200000 /* External interrupt */
+#define SRR1_WAKEMT 0x00280000 /* mtctrl */
+#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */
+#define SRR1_WAKETHERM 0x00100000 /* Thermal management interrupt */
+
#ifndef SPRN_SVR
#define SPRN_SVR 0x11E /* System Version Register */
#endif
@@ -443,12 +455,35 @@
#define SPRN_SDAR 781
#else /* 32-bit */
-#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
-#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
-#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
-#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
-#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
-#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+#define SPRN_MMCR0 952 /* Monitor Mode Control Register 0 */
+#define MMCR0_FC 0x80000000UL /* freeze counters */
+#define MMCR0_FCS 0x40000000UL /* freeze in supervisor state */
+#define MMCR0_FCP 0x20000000UL /* freeze in problem state */
+#define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */
+#define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */
+#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */
+#define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */
+#define MMCR0_TBEE 0x00400000UL /* time base exception enable */
+#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
+#define MMCR0_PMCnCE 0x00004000UL /* count enable for all but PMC 1*/
+#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
+#define MMCR0_PMC1SEL 0x00001fc0UL /* PMC 1 Event */
+#define MMCR0_PMC2SEL 0x0000003fUL /* PMC 2 Event */
+
+#define SPRN_MMCR1 956
+#define MMCR1_PMC3SEL 0xf8000000UL /* PMC 3 Event */
+#define MMCR1_PMC4SEL 0x07c00000UL /* PMC 4 Event */
+#define MMCR1_PMC5SEL 0x003e0000UL /* PMC 5 Event */
+#define MMCR1_PMC6SEL 0x0001f800UL /* PMC 6 Event */
+#define SPRN_MMCR2 944
+#define SPRN_PMC1 953 /* Performance Counter Register 1 */
+#define SPRN_PMC2 954 /* Performance Counter Register 2 */
+#define SPRN_PMC3 957 /* Performance Counter Register 3 */
+#define SPRN_PMC4 958 /* Performance Counter Register 4 */
+#define SPRN_PMC5 945 /* Performance Counter Register 5 */
+#define SPRN_PMC6 946 /* Performance Counter Register 6 */
+
+#define SPRN_SIAR 955 /* Sampled Instruction Address Register */
/* Bit definitions for MMCR0 and PMC1 / PMC2. */
#define MMCR0_PMC1_CYCLES (1 << 7)
@@ -458,7 +493,6 @@
#define MMCR0_PMC2_CYCLES 0x1
#define MMCR0_PMC2_ITLB 0x7
#define MMCR0_PMC2_LOADMISSTIME 0x5
-#define MMCR0_PMXE (1 << 26)
#endif
/* Processor Version Register (PVR) field extraction */
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
index d1bb611ea626..f43c6835e62a 100644
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -1,5 +1,6 @@
#ifndef _POWERPC_RTAS_H
#define _POWERPC_RTAS_H
+#ifdef __KERNEL__
#include <linux/spinlock.h>
#include <asm/page.h>
@@ -160,7 +161,6 @@ extern struct rtas_t rtas;
extern void enter_rtas(unsigned long);
extern int rtas_token(const char *service);
extern int rtas_call(int token, int, int, int *, ...);
-extern void call_rtas_display_status(unsigned char);
extern void rtas_restart(char *cmd);
extern void rtas_power_off(void);
extern void rtas_halt(void);
@@ -229,4 +229,5 @@ extern unsigned long rtas_rmo_buf;
#define GLOBAL_INTERRUPT_QUEUE 9005
+#endif /* __KERNEL__ */
#endif /* _POWERPC_RTAS_H */
diff --git a/include/asm-powerpc/seccomp.h b/include/asm-powerpc/seccomp.h
index 1e1cfe12882b..853765eb1f65 100644
--- a/include/asm-powerpc/seccomp.h
+++ b/include/asm-powerpc/seccomp.h
@@ -1,6 +1,10 @@
#ifndef _ASM_POWERPC_SECCOMP_H
+#define _ASM_POWERPC_SECCOMP_H
+#ifdef __KERNEL__
#include <linux/thread_info.h>
+#endif
+
#include <linux/unistd.h>
#define __NR_seccomp_read __NR_read
diff --git a/include/asm-powerpc/sections.h b/include/asm-powerpc/sections.h
index 47be2ac2a925..916018e425c4 100644
--- a/include/asm-powerpc/sections.h
+++ b/include/asm-powerpc/sections.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_SECTIONS_H
#define _ASM_POWERPC_SECTIONS_H
+#ifdef __KERNEL__
#include <asm-generic/sections.h>
@@ -17,4 +18,5 @@ static inline int in_kernel_text(unsigned long addr)
#endif
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SECTIONS_H */
diff --git a/include/asm-powerpc/serial.h b/include/asm-powerpc/serial.h
index b273d630b32f..3e8589b43cb2 100644
--- a/include/asm-powerpc/serial.h
+++ b/include/asm-powerpc/serial.h
@@ -15,4 +15,10 @@
/* Default baud base if not found in device-tree */
#define BASE_BAUD ( 1843200 / 16 )
+#ifdef CONFIG_PPC_UDBG_16550
+extern void find_legacy_serial_ports(void);
+#else
+#define find_legacy_serial_ports() do { } while (0)
+#endif
+
#endif /* _PPC64_SERIAL_H */
diff --git a/include/asm-powerpc/signal.h b/include/asm-powerpc/signal.h
index 694c8d2dab87..a4d8f8648541 100644
--- a/include/asm-powerpc/signal.h
+++ b/include/asm-powerpc/signal.h
@@ -2,10 +2,13 @@
#define _ASM_POWERPC_SIGNAL_H
#include <linux/types.h>
-#include <linux/config.h>
#define _NSIG 64
-#define _NSIG_BPW BITS_PER_LONG
+#ifdef __powerpc64__
+#define _NSIG_BPW 64
+#else
+#define _NSIG_BPW 32
+#endif
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
typedef unsigned long old_sigset_t; /* at least 32 bits */
diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h
index 76c29a9784dd..82ce47607774 100644
--- a/include/asm-powerpc/smu.h
+++ b/include/asm-powerpc/smu.h
@@ -4,9 +4,11 @@
/*
* Definitions for talking to the SMU chip in newer G5 PowerMacs
*/
-
+#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/list.h>
+#endif
+#include <linux/types.h>
/*
* Known SMU commands
@@ -20,7 +22,7 @@
/*
* Partition info commands
*
- * These commands are used to retreive the sdb-partition-XX datas from
+ * These commands are used to retrieve the sdb-partition-XX datas from
* the SMU. The lenght is always 2. First byte is the subcommand code
* and second byte is the partition ID.
*
@@ -223,7 +225,7 @@
*
* SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to
* transfer blocks of data from the SMU. So far, I've decrypted it's
- * usage to retreive partition data. In order to do that, you have to
+ * usage to retrieve partition data. In order to do that, you have to
* break your transfer in "chunks" since that command cannot transfer
* more than a chunk at a time. The chunk size used by OF is 0xe bytes,
* but it seems that the darwin driver will let you do 0x1e bytes if
@@ -356,6 +358,9 @@ extern unsigned long smu_cmdbuf_abs;
* Kenrel asynchronous i2c interface
*/
+#define SMU_I2C_READ_MAX 0x1d
+#define SMU_I2C_WRITE_MAX 0x15
+
/* SMU i2c header, exactly matches i2c header on wire */
struct smu_i2c_param
{
@@ -366,12 +371,9 @@ struct smu_i2c_param
u8 subaddr[3]; /* subaddress */
u8 caddr; /* combined address, filled by SMU driver */
u8 datalen; /* length of transfer */
- u8 data[7]; /* data */
+ u8 data[SMU_I2C_READ_MAX]; /* data */
};
-#define SMU_I2C_READ_MAX 0x0d
-#define SMU_I2C_WRITE_MAX 0x05
-
struct smu_i2c_cmd
{
/* public */
@@ -385,7 +387,7 @@ struct smu_i2c_cmd
int read;
int stage;
int retries;
- u8 pdata[0x10];
+ u8 pdata[32];
struct list_head link;
};
@@ -487,8 +489,8 @@ struct smu_sdbp_slotspow {
#define SMU_SDB_SENSORTREE_ID 0x25
struct smu_sdbp_sensortree {
- u8 model_id;
- u8 unknown[3];
+ __u8 model_id;
+ __u8 unknown[3];
};
/* This partition contains CPU thermal control PID informations. So far
@@ -498,13 +500,13 @@ struct smu_sdbp_sensortree {
#define SMU_SDB_CPUPIDDATA_ID 0x17
struct smu_sdbp_cpupiddata {
- u8 unknown1;
- u8 target_temp_delta;
- u8 unknown2;
- u8 history_len;
- s16 power_adj;
- u16 max_power;
- s32 gp,gr,gd;
+ __u8 unknown1;
+ __u8 target_temp_delta;
+ __u8 unknown2;
+ __u8 history_len;
+ __s16 power_adj;
+ __u16 max_power;
+ __s32 gp,gr,gd;
};
@@ -517,7 +519,7 @@ struct smu_sdbp_cpupiddata {
* if not found. The data format is described below
*/
extern struct smu_sdbp_header *smu_get_sdb_partition(int id,
- unsigned int *size);
+ unsigned int *size);
#endif /* __KERNEL__ */
@@ -554,7 +556,7 @@ struct smu_user_cmd_hdr
__u32 cmdtype;
#define SMU_CMDTYPE_SMU 0 /* SMU command */
#define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */
-#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */
+#define SMU_CMDTYPE_GET_PARTITION 2 /* retrieve an sdb partition */
__u8 cmd; /* SMU command byte */
__u8 pad[3]; /* padding */
diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h
index ba1b34fdb967..38b1ea3b58fd 100644
--- a/include/asm-powerpc/sparsemem.h
+++ b/include/asm-powerpc/sparsemem.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_SPARSEMEM_H
#define _ASM_POWERPC_SPARSEMEM_H 1
+#ifdef __KERNEL__
#ifdef CONFIG_SPARSEMEM
/*
@@ -13,8 +14,17 @@
#ifdef CONFIG_MEMORY_HOTPLUG
extern void create_section_mapping(unsigned long start, unsigned long end);
+#ifdef CONFIG_NUMA
+extern int hot_add_scn_to_nid(unsigned long scn_addr);
+#else
+static inline int hot_add_scn_to_nid(unsigned long scn_addr)
+{
+ return 0;
+}
+#endif /* CONFIG_NUMA */
#endif /* CONFIG_MEMORY_HOTPLUG */
#endif /* CONFIG_SPARSEMEM */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SPARSEMEM_H */
diff --git a/include/asm-powerpc/spinlock.h b/include/asm-powerpc/spinlock.h
index caa4b14e0e94..895cb6d3a42a 100644
--- a/include/asm-powerpc/spinlock.h
+++ b/include/asm-powerpc/spinlock.h
@@ -1,5 +1,6 @@
#ifndef __ASM_SPINLOCK_H
#define __ASM_SPINLOCK_H
+#ifdef __KERNEL__
/*
* Simple spin lock operations.
@@ -45,7 +46,7 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock)
token = LOCK_TOKEN;
__asm__ __volatile__(
-"1: lwarx %0,0,%2 # __spin_trylock\n\
+"1: lwarx %0,0,%2\n\
cmpwi 0,%0,0\n\
bne- 2f\n\
stwcx. %1,0,%2\n\
@@ -79,7 +80,7 @@ static int __inline__ __raw_spin_trylock(raw_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)
+#define SHARED_PROCESSOR (get_lppaca()->shared_proc)
extern void __spin_yield(raw_spinlock_t *lock);
extern void __rw_yield(raw_rwlock_t *lock);
#else /* SPLPAR || ISERIES */
@@ -123,8 +124,8 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long
static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock)
{
- __asm__ __volatile__(SYNC_ON_SMP" # __raw_spin_unlock"
- : : :"memory");
+ __asm__ __volatile__("# __raw_spin_unlock\n\t"
+ LWSYNC_ON_SMP: : :"memory");
lock->slock = 0;
}
@@ -166,7 +167,7 @@ static long __inline__ __read_trylock(raw_rwlock_t *rw)
long tmp;
__asm__ __volatile__(
-"1: lwarx %0,0,%1 # read_trylock\n"
+"1: lwarx %0,0,%1\n"
__DO_SIGN_EXTEND
" addic. %0,%0,1\n\
ble- 2f\n"
@@ -191,7 +192,7 @@ static __inline__ long __write_trylock(raw_rwlock_t *rw)
token = WRLOCK_TOKEN;
__asm__ __volatile__(
-"1: lwarx %0,0,%2 # write_trylock\n\
+"1: lwarx %0,0,%2\n\
cmpwi 0,%0,0\n\
bne- 2f\n"
PPC405_ERR77(0,%1)
@@ -248,8 +249,9 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
long tmp;
__asm__ __volatile__(
- "eieio # read_unlock\n\
-1: lwarx %0,0,%1\n\
+ "# read_unlock\n\t"
+ LWSYNC_ON_SMP
+"1: lwarx %0,0,%1\n\
addic %0,%0,-1\n"
PPC405_ERR77(0,%1)
" stwcx. %0,0,%1\n\
@@ -261,9 +263,10 @@ static void __inline__ __raw_read_unlock(raw_rwlock_t *rw)
static __inline__ void __raw_write_unlock(raw_rwlock_t *rw)
{
- __asm__ __volatile__(SYNC_ON_SMP" # write_unlock"
- : : :"memory");
+ __asm__ __volatile__("# write_unlock\n\t"
+ LWSYNC_ON_SMP: : :"memory");
rw->lock = 0;
}
+#endif /* __KERNEL__ */
#endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
new file mode 100644
index 000000000000..38bacf2f6e0c
--- /dev/null
+++ b/include/asm-powerpc/spu.h
@@ -0,0 +1,600 @@
+/*
+ * SPU core / file system interface and HW structures
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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 _SPU_H
+#define _SPU_H
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/kref.h>
+#include <linux/workqueue.h>
+
+#define LS_SIZE (256 * 1024)
+#define LS_ADDR_MASK (LS_SIZE - 1)
+
+#define MFC_PUT_CMD 0x20
+#define MFC_PUTS_CMD 0x28
+#define MFC_PUTR_CMD 0x30
+#define MFC_PUTF_CMD 0x22
+#define MFC_PUTB_CMD 0x21
+#define MFC_PUTFS_CMD 0x2A
+#define MFC_PUTBS_CMD 0x29
+#define MFC_PUTRF_CMD 0x32
+#define MFC_PUTRB_CMD 0x31
+#define MFC_PUTL_CMD 0x24
+#define MFC_PUTRL_CMD 0x34
+#define MFC_PUTLF_CMD 0x26
+#define MFC_PUTLB_CMD 0x25
+#define MFC_PUTRLF_CMD 0x36
+#define MFC_PUTRLB_CMD 0x35
+
+#define MFC_GET_CMD 0x40
+#define MFC_GETS_CMD 0x48
+#define MFC_GETF_CMD 0x42
+#define MFC_GETB_CMD 0x41
+#define MFC_GETFS_CMD 0x4A
+#define MFC_GETBS_CMD 0x49
+#define MFC_GETL_CMD 0x44
+#define MFC_GETLF_CMD 0x46
+#define MFC_GETLB_CMD 0x45
+
+#define MFC_SDCRT_CMD 0x80
+#define MFC_SDCRTST_CMD 0x81
+#define MFC_SDCRZ_CMD 0x89
+#define MFC_SDCRS_CMD 0x8D
+#define MFC_SDCRF_CMD 0x8F
+
+#define MFC_GETLLAR_CMD 0xD0
+#define MFC_PUTLLC_CMD 0xB4
+#define MFC_PUTLLUC_CMD 0xB0
+#define MFC_PUTQLLUC_CMD 0xB8
+#define MFC_SNDSIG_CMD 0xA0
+#define MFC_SNDSIGB_CMD 0xA1
+#define MFC_SNDSIGF_CMD 0xA2
+#define MFC_BARRIER_CMD 0xC0
+#define MFC_EIEIO_CMD 0xC8
+#define MFC_SYNC_CMD 0xCC
+
+#define MFC_MIN_DMA_SIZE_SHIFT 4 /* 16 bytes */
+#define MFC_MAX_DMA_SIZE_SHIFT 14 /* 16384 bytes */
+#define MFC_MIN_DMA_SIZE (1 << MFC_MIN_DMA_SIZE_SHIFT)
+#define MFC_MAX_DMA_SIZE (1 << MFC_MAX_DMA_SIZE_SHIFT)
+#define MFC_MIN_DMA_SIZE_MASK (MFC_MIN_DMA_SIZE - 1)
+#define MFC_MAX_DMA_SIZE_MASK (MFC_MAX_DMA_SIZE - 1)
+#define MFC_MIN_DMA_LIST_SIZE 0x0008 /* 8 bytes */
+#define MFC_MAX_DMA_LIST_SIZE 0x4000 /* 16K bytes */
+
+#define MFC_TAGID_TO_TAGMASK(tag_id) (1 << (tag_id & 0x1F))
+
+/* Events for Channels 0-2 */
+#define MFC_DMA_TAG_STATUS_UPDATE_EVENT 0x00000001
+#define MFC_DMA_TAG_CMD_STALL_NOTIFY_EVENT 0x00000002
+#define MFC_DMA_QUEUE_AVAILABLE_EVENT 0x00000008
+#define MFC_SPU_MAILBOX_WRITTEN_EVENT 0x00000010
+#define MFC_DECREMENTER_EVENT 0x00000020
+#define MFC_PU_INT_MAILBOX_AVAILABLE_EVENT 0x00000040
+#define MFC_PU_MAILBOX_AVAILABLE_EVENT 0x00000080
+#define MFC_SIGNAL_2_EVENT 0x00000100
+#define MFC_SIGNAL_1_EVENT 0x00000200
+#define MFC_LLR_LOST_EVENT 0x00000400
+#define MFC_PRIV_ATTN_EVENT 0x00000800
+#define MFC_MULTI_SRC_EVENT 0x00001000
+
+/* Flags indicating progress during context switch. */
+#define SPU_CONTEXT_SWITCH_PENDING 0UL
+#define SPU_CONTEXT_SWITCH_ACTIVE 1UL
+
+struct spu_context;
+struct spu_runqueue;
+
+struct spu {
+ char *name;
+ unsigned long local_store_phys;
+ u8 *local_store;
+ struct spu_problem __iomem *problem;
+ struct spu_priv1 __iomem *priv1;
+ struct spu_priv2 __iomem *priv2;
+ struct list_head list;
+ struct list_head sched_list;
+ int number;
+ u32 isrc;
+ u32 node;
+ u64 flags;
+ u64 dar;
+ u64 dsisr;
+ struct kref kref;
+ size_t ls_size;
+ unsigned int slb_replace;
+ struct mm_struct *mm;
+ struct spu_context *ctx;
+ struct spu_runqueue *rq;
+ unsigned long long timestamp;
+ pid_t pid;
+ int prio;
+ int class_0_pending;
+ spinlock_t register_lock;
+
+ u32 stop_code;
+ void (* wbox_callback)(struct spu *spu);
+ void (* ibox_callback)(struct spu *spu);
+ void (* stop_callback)(struct spu *spu);
+
+ char irq_c0[8];
+ char irq_c1[8];
+ char irq_c2[8];
+};
+
+struct spu *spu_alloc(void);
+void spu_free(struct spu *spu);
+int spu_irq_class_0_bottom(struct spu *spu);
+int spu_irq_class_1_bottom(struct spu *spu);
+void spu_irq_setaffinity(struct spu *spu, int cpu);
+
+extern struct spufs_calls {
+ asmlinkage long (*create_thread)(const char __user *name,
+ unsigned int flags, mode_t mode);
+ asmlinkage long (*spu_run)(struct file *filp, __u32 __user *unpc,
+ __u32 __user *ustatus);
+ struct module *owner;
+} spufs_calls;
+
+#ifdef CONFIG_SPU_FS_MODULE
+int register_spu_syscalls(struct spufs_calls *calls);
+void unregister_spu_syscalls(struct spufs_calls *calls);
+#else
+static inline int register_spu_syscalls(struct spufs_calls *calls)
+{
+ return 0;
+}
+static inline void unregister_spu_syscalls(struct spufs_calls *calls)
+{
+}
+#endif /* MODULE */
+
+
+/* access to priv1 registers */
+void spu_int_mask_and(struct spu *spu, int class, u64 mask);
+void spu_int_mask_or(struct spu *spu, int class, u64 mask);
+void spu_int_mask_set(struct spu *spu, int class, u64 mask);
+u64 spu_int_mask_get(struct spu *spu, int class);
+void spu_int_stat_clear(struct spu *spu, int class, u64 stat);
+u64 spu_int_stat_get(struct spu *spu, int class);
+void spu_int_route_set(struct spu *spu, u64 route);
+u64 spu_mfc_dar_get(struct spu *spu);
+u64 spu_mfc_dsisr_get(struct spu *spu);
+void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr);
+void spu_mfc_sdr_set(struct spu *spu, u64 sdr);
+void spu_mfc_sr1_set(struct spu *spu, u64 sr1);
+u64 spu_mfc_sr1_get(struct spu *spu);
+void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id);
+u64 spu_mfc_tclass_id_get(struct spu *spu);
+void spu_tlb_invalidate(struct spu *spu);
+void spu_resource_allocation_groupID_set(struct spu *spu, u64 id);
+u64 spu_resource_allocation_groupID_get(struct spu *spu);
+void spu_resource_allocation_enable_set(struct spu *spu, u64 enable);
+u64 spu_resource_allocation_enable_get(struct spu *spu);
+
+
+/*
+ * This defines the Local Store, Problem Area and Privlege Area of an SPU.
+ */
+
+union mfc_tag_size_class_cmd {
+ struct {
+ u16 mfc_size;
+ u16 mfc_tag;
+ u8 pad;
+ u8 mfc_rclassid;
+ u16 mfc_cmd;
+ } u;
+ struct {
+ u32 mfc_size_tag32;
+ u32 mfc_class_cmd32;
+ } by32;
+ u64 all64;
+};
+
+struct mfc_cq_sr {
+ u64 mfc_cq_data0_RW;
+ u64 mfc_cq_data1_RW;
+ u64 mfc_cq_data2_RW;
+ u64 mfc_cq_data3_RW;
+};
+
+struct spu_problem {
+#define MS_SYNC_PENDING 1L
+ u64 spc_mssync_RW; /* 0x0000 */
+ u8 pad_0x0008_0x3000[0x3000 - 0x0008];
+
+ /* DMA Area */
+ u8 pad_0x3000_0x3004[0x4]; /* 0x3000 */
+ u32 mfc_lsa_W; /* 0x3004 */
+ u64 mfc_ea_W; /* 0x3008 */
+ union mfc_tag_size_class_cmd mfc_union_W; /* 0x3010 */
+ u8 pad_0x3018_0x3104[0xec]; /* 0x3018 */
+ u32 dma_qstatus_R; /* 0x3104 */
+ u8 pad_0x3108_0x3204[0xfc]; /* 0x3108 */
+ u32 dma_querytype_RW; /* 0x3204 */
+ u8 pad_0x3208_0x321c[0x14]; /* 0x3208 */
+ u32 dma_querymask_RW; /* 0x321c */
+ u8 pad_0x3220_0x322c[0xc]; /* 0x3220 */
+ u32 dma_tagstatus_R; /* 0x322c */
+#define DMA_TAGSTATUS_INTR_ANY 1u
+#define DMA_TAGSTATUS_INTR_ALL 2u
+ u8 pad_0x3230_0x4000[0x4000 - 0x3230]; /* 0x3230 */
+
+ /* SPU Control Area */
+ u8 pad_0x4000_0x4004[0x4]; /* 0x4000 */
+ u32 pu_mb_R; /* 0x4004 */
+ u8 pad_0x4008_0x400c[0x4]; /* 0x4008 */
+ u32 spu_mb_W; /* 0x400c */
+ u8 pad_0x4010_0x4014[0x4]; /* 0x4010 */
+ u32 mb_stat_R; /* 0x4014 */
+ u8 pad_0x4018_0x401c[0x4]; /* 0x4018 */
+ u32 spu_runcntl_RW; /* 0x401c */
+#define SPU_RUNCNTL_STOP 0L
+#define SPU_RUNCNTL_RUNNABLE 1L
+ u8 pad_0x4020_0x4024[0x4]; /* 0x4020 */
+ u32 spu_status_R; /* 0x4024 */
+#define SPU_STOP_STATUS_SHIFT 16
+#define SPU_STATUS_STOPPED 0x0
+#define SPU_STATUS_RUNNING 0x1
+#define SPU_STATUS_STOPPED_BY_STOP 0x2
+#define SPU_STATUS_STOPPED_BY_HALT 0x4
+#define SPU_STATUS_WAITING_FOR_CHANNEL 0x8
+#define SPU_STATUS_SINGLE_STEP 0x10
+#define SPU_STATUS_INVALID_INSTR 0x20
+#define SPU_STATUS_INVALID_CH 0x40
+#define SPU_STATUS_ISOLATED_STATE 0x80
+#define SPU_STATUS_ISOLATED_LOAD_STAUTUS 0x200
+#define SPU_STATUS_ISOLATED_EXIT_STAUTUS 0x400
+ u8 pad_0x4028_0x402c[0x4]; /* 0x4028 */
+ u32 spu_spe_R; /* 0x402c */
+ u8 pad_0x4030_0x4034[0x4]; /* 0x4030 */
+ u32 spu_npc_RW; /* 0x4034 */
+ u8 pad_0x4038_0x14000[0x14000 - 0x4038]; /* 0x4038 */
+
+ /* Signal Notification Area */
+ u8 pad_0x14000_0x1400c[0xc]; /* 0x14000 */
+ u32 signal_notify1; /* 0x1400c */
+ u8 pad_0x14010_0x1c00c[0x7ffc]; /* 0x14010 */
+ u32 signal_notify2; /* 0x1c00c */
+} __attribute__ ((aligned(0x20000)));
+
+/* SPU Privilege 2 State Area */
+struct spu_priv2 {
+ /* MFC Registers */
+ u8 pad_0x0000_0x1100[0x1100 - 0x0000]; /* 0x0000 */
+
+ /* SLB Management Registers */
+ u8 pad_0x1100_0x1108[0x8]; /* 0x1100 */
+ u64 slb_index_W; /* 0x1108 */
+#define SLB_INDEX_MASK 0x7L
+ u64 slb_esid_RW; /* 0x1110 */
+ u64 slb_vsid_RW; /* 0x1118 */
+#define SLB_VSID_SUPERVISOR_STATE (0x1ull << 11)
+#define SLB_VSID_SUPERVISOR_STATE_MASK (0x1ull << 11)
+#define SLB_VSID_PROBLEM_STATE (0x1ull << 10)
+#define SLB_VSID_PROBLEM_STATE_MASK (0x1ull << 10)
+#define SLB_VSID_EXECUTE_SEGMENT (0x1ull << 9)
+#define SLB_VSID_NO_EXECUTE_SEGMENT (0x1ull << 9)
+#define SLB_VSID_EXECUTE_SEGMENT_MASK (0x1ull << 9)
+#define SLB_VSID_4K_PAGE (0x0 << 8)
+#define SLB_VSID_LARGE_PAGE (0x1ull << 8)
+#define SLB_VSID_PAGE_SIZE_MASK (0x1ull << 8)
+#define SLB_VSID_CLASS_MASK (0x1ull << 7)
+#define SLB_VSID_VIRTUAL_PAGE_SIZE_MASK (0x1ull << 6)
+ u64 slb_invalidate_entry_W; /* 0x1120 */
+ u64 slb_invalidate_all_W; /* 0x1128 */
+ u8 pad_0x1130_0x2000[0x2000 - 0x1130]; /* 0x1130 */
+
+ /* Context Save / Restore Area */
+ struct mfc_cq_sr spuq[16]; /* 0x2000 */
+ struct mfc_cq_sr puq[8]; /* 0x2200 */
+ u8 pad_0x2300_0x3000[0x3000 - 0x2300]; /* 0x2300 */
+
+ /* MFC Control */
+ u64 mfc_control_RW; /* 0x3000 */
+#define MFC_CNTL_RESUME_DMA_QUEUE (0ull << 0)
+#define MFC_CNTL_SUSPEND_DMA_QUEUE (1ull << 0)
+#define MFC_CNTL_SUSPEND_DMA_QUEUE_MASK (1ull << 0)
+#define MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION (0ull << 8)
+#define MFC_CNTL_SUSPEND_IN_PROGRESS (1ull << 8)
+#define MFC_CNTL_SUSPEND_COMPLETE (3ull << 8)
+#define MFC_CNTL_SUSPEND_DMA_STATUS_MASK (3ull << 8)
+#define MFC_CNTL_DMA_QUEUES_EMPTY (1ull << 14)
+#define MFC_CNTL_DMA_QUEUES_EMPTY_MASK (1ull << 14)
+#define MFC_CNTL_PURGE_DMA_REQUEST (1ull << 15)
+#define MFC_CNTL_PURGE_DMA_IN_PROGRESS (1ull << 24)
+#define MFC_CNTL_PURGE_DMA_COMPLETE (3ull << 24)
+#define MFC_CNTL_PURGE_DMA_STATUS_MASK (3ull << 24)
+#define MFC_CNTL_RESTART_DMA_COMMAND (1ull << 32)
+#define MFC_CNTL_DMA_COMMAND_REISSUE_PENDING (1ull << 32)
+#define MFC_CNTL_DMA_COMMAND_REISSUE_STATUS_MASK (1ull << 32)
+#define MFC_CNTL_MFC_PRIVILEGE_STATE (2ull << 33)
+#define MFC_CNTL_MFC_PROBLEM_STATE (3ull << 33)
+#define MFC_CNTL_MFC_KEY_PROTECTION_STATE_MASK (3ull << 33)
+#define MFC_CNTL_DECREMENTER_HALTED (1ull << 35)
+#define MFC_CNTL_DECREMENTER_RUNNING (1ull << 40)
+#define MFC_CNTL_DECREMENTER_STATUS_MASK (1ull << 40)
+ u8 pad_0x3008_0x4000[0x4000 - 0x3008]; /* 0x3008 */
+
+ /* Interrupt Mailbox */
+ u64 puint_mb_R; /* 0x4000 */
+ u8 pad_0x4008_0x4040[0x4040 - 0x4008]; /* 0x4008 */
+
+ /* SPU Control */
+ u64 spu_privcntl_RW; /* 0x4040 */
+#define SPU_PRIVCNTL_MODE_NORMAL (0x0ull << 0)
+#define SPU_PRIVCNTL_MODE_SINGLE_STEP (0x1ull << 0)
+#define SPU_PRIVCNTL_MODE_MASK (0x1ull << 0)
+#define SPU_PRIVCNTL_NO_ATTENTION_EVENT (0x0ull << 1)
+#define SPU_PRIVCNTL_ATTENTION_EVENT (0x1ull << 1)
+#define SPU_PRIVCNTL_ATTENTION_EVENT_MASK (0x1ull << 1)
+#define SPU_PRIVCNT_LOAD_REQUEST_NORMAL (0x0ull << 2)
+#define SPU_PRIVCNT_LOAD_REQUEST_ENABLE_MASK (0x1ull << 2)
+ u8 pad_0x4048_0x4058[0x10]; /* 0x4048 */
+ u64 spu_lslr_RW; /* 0x4058 */
+ u64 spu_chnlcntptr_RW; /* 0x4060 */
+ u64 spu_chnlcnt_RW; /* 0x4068 */
+ u64 spu_chnldata_RW; /* 0x4070 */
+ u64 spu_cfg_RW; /* 0x4078 */
+ u8 pad_0x4080_0x5000[0x5000 - 0x4080]; /* 0x4080 */
+
+ /* PV2_ImplRegs: Implementation-specific privileged-state 2 regs */
+ u64 spu_pm_trace_tag_status_RW; /* 0x5000 */
+ u64 spu_tag_status_query_RW; /* 0x5008 */
+#define TAG_STATUS_QUERY_CONDITION_BITS (0x3ull << 32)
+#define TAG_STATUS_QUERY_MASK_BITS (0xffffffffull)
+ u64 spu_cmd_buf1_RW; /* 0x5010 */
+#define SPU_COMMAND_BUFFER_1_LSA_BITS (0x7ffffull << 32)
+#define SPU_COMMAND_BUFFER_1_EAH_BITS (0xffffffffull)
+ u64 spu_cmd_buf2_RW; /* 0x5018 */
+#define SPU_COMMAND_BUFFER_2_EAL_BITS ((0xffffffffull) << 32)
+#define SPU_COMMAND_BUFFER_2_TS_BITS (0xffffull << 16)
+#define SPU_COMMAND_BUFFER_2_TAG_BITS (0x3full)
+ u64 spu_atomic_status_RW; /* 0x5020 */
+} __attribute__ ((aligned(0x20000)));
+
+/* SPU Privilege 1 State Area */
+struct spu_priv1 {
+ /* Control and Configuration Area */
+ u64 mfc_sr1_RW; /* 0x000 */
+#define MFC_STATE1_LOCAL_STORAGE_DECODE_MASK 0x01ull
+#define MFC_STATE1_BUS_TLBIE_MASK 0x02ull
+#define MFC_STATE1_REAL_MODE_OFFSET_ENABLE_MASK 0x04ull
+#define MFC_STATE1_PROBLEM_STATE_MASK 0x08ull
+#define MFC_STATE1_RELOCATE_MASK 0x10ull
+#define MFC_STATE1_MASTER_RUN_CONTROL_MASK 0x20ull
+ u64 mfc_lpid_RW; /* 0x008 */
+ u64 spu_idr_RW; /* 0x010 */
+ u64 mfc_vr_RO; /* 0x018 */
+#define MFC_VERSION_BITS (0xffff << 16)
+#define MFC_REVISION_BITS (0xffff)
+#define MFC_GET_VERSION_BITS(vr) (((vr) & MFC_VERSION_BITS) >> 16)
+#define MFC_GET_REVISION_BITS(vr) ((vr) & MFC_REVISION_BITS)
+ u64 spu_vr_RO; /* 0x020 */
+#define SPU_VERSION_BITS (0xffff << 16)
+#define SPU_REVISION_BITS (0xffff)
+#define SPU_GET_VERSION_BITS(vr) (vr & SPU_VERSION_BITS) >> 16
+#define SPU_GET_REVISION_BITS(vr) (vr & SPU_REVISION_BITS)
+ u8 pad_0x28_0x100[0x100 - 0x28]; /* 0x28 */
+
+
+ /* Interrupt Area */
+ u64 int_mask_RW[3]; /* 0x100 */
+#define CLASS0_ENABLE_DMA_ALIGNMENT_INTR 0x1L
+#define CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR 0x2L
+#define CLASS0_ENABLE_SPU_ERROR_INTR 0x4L
+#define CLASS0_ENABLE_MFC_FIR_INTR 0x8L
+#define CLASS1_ENABLE_SEGMENT_FAULT_INTR 0x1L
+#define CLASS1_ENABLE_STORAGE_FAULT_INTR 0x2L
+#define CLASS1_ENABLE_LS_COMPARE_SUSPEND_ON_GET_INTR 0x4L
+#define CLASS1_ENABLE_LS_COMPARE_SUSPEND_ON_PUT_INTR 0x8L
+#define CLASS2_ENABLE_MAILBOX_INTR 0x1L
+#define CLASS2_ENABLE_SPU_STOP_INTR 0x2L
+#define CLASS2_ENABLE_SPU_HALT_INTR 0x4L
+#define CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR 0x8L
+ u8 pad_0x118_0x140[0x28]; /* 0x118 */
+ u64 int_stat_RW[3]; /* 0x140 */
+ u8 pad_0x158_0x180[0x28]; /* 0x158 */
+ u64 int_route_RW; /* 0x180 */
+
+ /* Interrupt Routing */
+ u8 pad_0x188_0x200[0x200 - 0x188]; /* 0x188 */
+
+ /* Atomic Unit Control Area */
+ u64 mfc_atomic_flush_RW; /* 0x200 */
+#define mfc_atomic_flush_enable 0x1L
+ u8 pad_0x208_0x280[0x78]; /* 0x208 */
+ u64 resource_allocation_groupID_RW; /* 0x280 */
+ u64 resource_allocation_enable_RW; /* 0x288 */
+ u8 pad_0x290_0x3c8[0x3c8 - 0x290]; /* 0x290 */
+
+ /* SPU_Cache_ImplRegs: Implementation-dependent cache registers */
+
+ u64 smf_sbi_signal_sel; /* 0x3c8 */
+#define smf_sbi_mask_lsb 56
+#define smf_sbi_shift (63 - smf_sbi_mask_lsb)
+#define smf_sbi_mask (0x301LL << smf_sbi_shift)
+#define smf_sbi_bus0_bits (0x001LL << smf_sbi_shift)
+#define smf_sbi_bus2_bits (0x100LL << smf_sbi_shift)
+#define smf_sbi2_bus0_bits (0x201LL << smf_sbi_shift)
+#define smf_sbi2_bus2_bits (0x300LL << smf_sbi_shift)
+ u64 smf_ato_signal_sel; /* 0x3d0 */
+#define smf_ato_mask_lsb 35
+#define smf_ato_shift (63 - smf_ato_mask_lsb)
+#define smf_ato_mask (0x3LL << smf_ato_shift)
+#define smf_ato_bus0_bits (0x2LL << smf_ato_shift)
+#define smf_ato_bus2_bits (0x1LL << smf_ato_shift)
+ u8 pad_0x3d8_0x400[0x400 - 0x3d8]; /* 0x3d8 */
+
+ /* TLB Management Registers */
+ u64 mfc_sdr_RW; /* 0x400 */
+ u8 pad_0x408_0x500[0xf8]; /* 0x408 */
+ u64 tlb_index_hint_RO; /* 0x500 */
+ u64 tlb_index_W; /* 0x508 */
+ u64 tlb_vpn_RW; /* 0x510 */
+ u64 tlb_rpn_RW; /* 0x518 */
+ u8 pad_0x520_0x540[0x20]; /* 0x520 */
+ u64 tlb_invalidate_entry_W; /* 0x540 */
+ u64 tlb_invalidate_all_W; /* 0x548 */
+ u8 pad_0x550_0x580[0x580 - 0x550]; /* 0x550 */
+
+ /* SPU_MMU_ImplRegs: Implementation-dependent MMU registers */
+ u64 smm_hid; /* 0x580 */
+#define PAGE_SIZE_MASK 0xf000000000000000ull
+#define PAGE_SIZE_16MB_64KB 0x2000000000000000ull
+ u8 pad_0x588_0x600[0x600 - 0x588]; /* 0x588 */
+
+ /* MFC Status/Control Area */
+ u64 mfc_accr_RW; /* 0x600 */
+#define MFC_ACCR_EA_ACCESS_GET (1 << 0)
+#define MFC_ACCR_EA_ACCESS_PUT (1 << 1)
+#define MFC_ACCR_LS_ACCESS_GET (1 << 3)
+#define MFC_ACCR_LS_ACCESS_PUT (1 << 4)
+ u8 pad_0x608_0x610[0x8]; /* 0x608 */
+ u64 mfc_dsisr_RW; /* 0x610 */
+#define MFC_DSISR_PTE_NOT_FOUND (1 << 30)
+#define MFC_DSISR_ACCESS_DENIED (1 << 27)
+#define MFC_DSISR_ATOMIC (1 << 26)
+#define MFC_DSISR_ACCESS_PUT (1 << 25)
+#define MFC_DSISR_ADDR_MATCH (1 << 22)
+#define MFC_DSISR_LS (1 << 17)
+#define MFC_DSISR_L (1 << 16)
+#define MFC_DSISR_ADDRESS_OVERFLOW (1 << 0)
+ u8 pad_0x618_0x620[0x8]; /* 0x618 */
+ u64 mfc_dar_RW; /* 0x620 */
+ u8 pad_0x628_0x700[0x700 - 0x628]; /* 0x628 */
+
+ /* Replacement Management Table (RMT) Area */
+ u64 rmt_index_RW; /* 0x700 */
+ u8 pad_0x708_0x710[0x8]; /* 0x708 */
+ u64 rmt_data1_RW; /* 0x710 */
+ u8 pad_0x718_0x800[0x800 - 0x718]; /* 0x718 */
+
+ /* Control/Configuration Registers */
+ u64 mfc_dsir_R; /* 0x800 */
+#define MFC_DSIR_Q (1 << 31)
+#define MFC_DSIR_SPU_QUEUE MFC_DSIR_Q
+ u64 mfc_lsacr_RW; /* 0x808 */
+#define MFC_LSACR_COMPARE_MASK ((~0ull) << 32)
+#define MFC_LSACR_COMPARE_ADDR ((~0ull) >> 32)
+ u64 mfc_lscrr_R; /* 0x810 */
+#define MFC_LSCRR_Q (1 << 31)
+#define MFC_LSCRR_SPU_QUEUE MFC_LSCRR_Q
+#define MFC_LSCRR_QI_SHIFT 32
+#define MFC_LSCRR_QI_MASK ((~0ull) << MFC_LSCRR_QI_SHIFT)
+ u8 pad_0x818_0x820[0x8]; /* 0x818 */
+ u64 mfc_tclass_id_RW; /* 0x820 */
+#define MFC_TCLASS_ID_ENABLE (1L << 0L)
+#define MFC_TCLASS_SLOT2_ENABLE (1L << 5L)
+#define MFC_TCLASS_SLOT1_ENABLE (1L << 6L)
+#define MFC_TCLASS_SLOT0_ENABLE (1L << 7L)
+#define MFC_TCLASS_QUOTA_2_SHIFT 8L
+#define MFC_TCLASS_QUOTA_1_SHIFT 16L
+#define MFC_TCLASS_QUOTA_0_SHIFT 24L
+#define MFC_TCLASS_QUOTA_2_MASK (0x1FL << MFC_TCLASS_QUOTA_2_SHIFT)
+#define MFC_TCLASS_QUOTA_1_MASK (0x1FL << MFC_TCLASS_QUOTA_1_SHIFT)
+#define MFC_TCLASS_QUOTA_0_MASK (0x1FL << MFC_TCLASS_QUOTA_0_SHIFT)
+ u8 pad_0x828_0x900[0x900 - 0x828]; /* 0x828 */
+
+ /* Real Mode Support Registers */
+ u64 mfc_rm_boundary; /* 0x900 */
+ u8 pad_0x908_0x938[0x30]; /* 0x908 */
+ u64 smf_dma_signal_sel; /* 0x938 */
+#define mfc_dma1_mask_lsb 41
+#define mfc_dma1_shift (63 - mfc_dma1_mask_lsb)
+#define mfc_dma1_mask (0x3LL << mfc_dma1_shift)
+#define mfc_dma1_bits (0x1LL << mfc_dma1_shift)
+#define mfc_dma2_mask_lsb 43
+#define mfc_dma2_shift (63 - mfc_dma2_mask_lsb)
+#define mfc_dma2_mask (0x3LL << mfc_dma2_shift)
+#define mfc_dma2_bits (0x1LL << mfc_dma2_shift)
+ u8 pad_0x940_0xa38[0xf8]; /* 0x940 */
+ u64 smm_signal_sel; /* 0xa38 */
+#define smm_sig_mask_lsb 12
+#define smm_sig_shift (63 - smm_sig_mask_lsb)
+#define smm_sig_mask (0x3LL << smm_sig_shift)
+#define smm_sig_bus0_bits (0x2LL << smm_sig_shift)
+#define smm_sig_bus2_bits (0x1LL << smm_sig_shift)
+ u8 pad_0xa40_0xc00[0xc00 - 0xa40]; /* 0xa40 */
+
+ /* DMA Command Error Area */
+ u64 mfc_cer_R; /* 0xc00 */
+#define MFC_CER_Q (1 << 31)
+#define MFC_CER_SPU_QUEUE MFC_CER_Q
+ u8 pad_0xc08_0x1000[0x1000 - 0xc08]; /* 0xc08 */
+
+ /* PV1_ImplRegs: Implementation-dependent privileged-state 1 regs */
+ /* DMA Command Error Area */
+ u64 spu_ecc_cntl_RW; /* 0x1000 */
+#define SPU_ECC_CNTL_E (1ull << 0ull)
+#define SPU_ECC_CNTL_ENABLE SPU_ECC_CNTL_E
+#define SPU_ECC_CNTL_DISABLE (~SPU_ECC_CNTL_E & 1L)
+#define SPU_ECC_CNTL_S (1ull << 1ull)
+#define SPU_ECC_STOP_AFTER_ERROR SPU_ECC_CNTL_S
+#define SPU_ECC_CONTINUE_AFTER_ERROR (~SPU_ECC_CNTL_S & 2L)
+#define SPU_ECC_CNTL_B (1ull << 2ull)
+#define SPU_ECC_BACKGROUND_ENABLE SPU_ECC_CNTL_B
+#define SPU_ECC_BACKGROUND_DISABLE (~SPU_ECC_CNTL_B & 4L)
+#define SPU_ECC_CNTL_I_SHIFT 3ull
+#define SPU_ECC_CNTL_I_MASK (3ull << SPU_ECC_CNTL_I_SHIFT)
+#define SPU_ECC_WRITE_ALWAYS (~SPU_ECC_CNTL_I & 12L)
+#define SPU_ECC_WRITE_CORRECTABLE (1ull << SPU_ECC_CNTL_I_SHIFT)
+#define SPU_ECC_WRITE_UNCORRECTABLE (3ull << SPU_ECC_CNTL_I_SHIFT)
+#define SPU_ECC_CNTL_D (1ull << 5ull)
+#define SPU_ECC_DETECTION_ENABLE SPU_ECC_CNTL_D
+#define SPU_ECC_DETECTION_DISABLE (~SPU_ECC_CNTL_D & 32L)
+ u64 spu_ecc_stat_RW; /* 0x1008 */
+#define SPU_ECC_CORRECTED_ERROR (1ull << 0ul)
+#define SPU_ECC_UNCORRECTED_ERROR (1ull << 1ul)
+#define SPU_ECC_SCRUB_COMPLETE (1ull << 2ul)
+#define SPU_ECC_SCRUB_IN_PROGRESS (1ull << 3ul)
+#define SPU_ECC_INSTRUCTION_ERROR (1ull << 4ul)
+#define SPU_ECC_DATA_ERROR (1ull << 5ul)
+#define SPU_ECC_DMA_ERROR (1ull << 6ul)
+#define SPU_ECC_STATUS_CNT_MASK (256ull << 8)
+ u64 spu_ecc_addr_RW; /* 0x1010 */
+ u64 spu_err_mask_RW; /* 0x1018 */
+#define SPU_ERR_ILLEGAL_INSTR (1ull << 0ul)
+#define SPU_ERR_ILLEGAL_CHANNEL (1ull << 1ul)
+ u8 pad_0x1020_0x1028[0x1028 - 0x1020]; /* 0x1020 */
+
+ /* SPU Debug-Trace Bus (DTB) Selection Registers */
+ u64 spu_trig0_sel; /* 0x1028 */
+ u64 spu_trig1_sel; /* 0x1030 */
+ u64 spu_trig2_sel; /* 0x1038 */
+ u64 spu_trig3_sel; /* 0x1040 */
+ u64 spu_trace_sel; /* 0x1048 */
+#define spu_trace_sel_mask 0x1f1fLL
+#define spu_trace_sel_bus0_bits 0x1000LL
+#define spu_trace_sel_bus2_bits 0x0010LL
+ u64 spu_event0_sel; /* 0x1050 */
+ u64 spu_event1_sel; /* 0x1058 */
+ u64 spu_event2_sel; /* 0x1060 */
+ u64 spu_event3_sel; /* 0x1068 */
+ u64 spu_trace_cntl; /* 0x1070 */
+} __attribute__ ((aligned(0x2000)));
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h
new file mode 100644
index 000000000000..ba18d7d4dde2
--- /dev/null
+++ b/include/asm-powerpc/spu_csa.h
@@ -0,0 +1,255 @@
+/*
+ * spu_csa.h: Definitions for SPU context save area (CSA).
+ *
+ * (C) Copyright IBM 2005
+ *
+ * Author: Mark Nutter <mnutter@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, 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 _SPU_CSA_H_
+#define _SPU_CSA_H_
+#ifdef __KERNEL__
+
+/*
+ * Total number of 128-bit registers.
+ */
+#define NR_SPU_GPRS 128
+#define NR_SPU_SPRS 9
+#define NR_SPU_REGS_PAD 7
+#define NR_SPU_SPILL_REGS 144 /* GPRS + SPRS + PAD */
+#define SIZEOF_SPU_SPILL_REGS NR_SPU_SPILL_REGS * 16
+
+#define SPU_SAVE_COMPLETE 0x3FFB
+#define SPU_RESTORE_COMPLETE 0x3FFC
+
+/*
+ * Definitions for various 'stopped' status conditions,
+ * to be recreated during context restore.
+ */
+#define SPU_STOPPED_STATUS_P 1
+#define SPU_STOPPED_STATUS_I 2
+#define SPU_STOPPED_STATUS_H 3
+#define SPU_STOPPED_STATUS_S 4
+#define SPU_STOPPED_STATUS_S_I 5
+#define SPU_STOPPED_STATUS_S_P 6
+#define SPU_STOPPED_STATUS_P_H 7
+#define SPU_STOPPED_STATUS_P_I 8
+#define SPU_STOPPED_STATUS_R 9
+
+#ifndef __ASSEMBLY__
+/**
+ * spu_reg128 - generic 128-bit register definition.
+ */
+struct spu_reg128 {
+ u32 slot[4];
+};
+
+/**
+ * struct spu_lscsa - Local Store Context Save Area.
+ * @gprs: Array of saved registers.
+ * @fpcr: Saved floating point status control register.
+ * @decr: Saved decrementer value.
+ * @decr_status: Indicates decrementer run status.
+ * @ppu_mb: Saved PPU mailbox data.
+ * @ppuint_mb: Saved PPU interrupting mailbox data.
+ * @tag_mask: Saved tag group mask.
+ * @event_mask: Saved event mask.
+ * @srr0: Saved SRR0.
+ * @stopped_status: Conditions to be recreated by restore.
+ * @ls: Saved contents of Local Storage Area.
+ *
+ * The LSCSA represents state that is primarily saved and
+ * restored by SPU-side code.
+ */
+struct spu_lscsa {
+ struct spu_reg128 gprs[128];
+ struct spu_reg128 fpcr;
+ struct spu_reg128 decr;
+ struct spu_reg128 decr_status;
+ struct spu_reg128 ppu_mb;
+ struct spu_reg128 ppuint_mb;
+ struct spu_reg128 tag_mask;
+ struct spu_reg128 event_mask;
+ struct spu_reg128 srr0;
+ struct spu_reg128 stopped_status;
+ struct spu_reg128 pad[119]; /* 'ls' must be page-aligned. */
+ unsigned char ls[LS_SIZE];
+};
+
+/*
+ * struct spu_problem_collapsed - condensed problem state area, w/o pads.
+ */
+struct spu_problem_collapsed {
+ u64 spc_mssync_RW;
+ u32 mfc_lsa_W;
+ u32 unused_pad0;
+ u64 mfc_ea_W;
+ union mfc_tag_size_class_cmd mfc_union_W;
+ u32 dma_qstatus_R;
+ u32 dma_querytype_RW;
+ u32 dma_querymask_RW;
+ u32 dma_tagstatus_R;
+ u32 pu_mb_R;
+ u32 spu_mb_W;
+ u32 mb_stat_R;
+ u32 spu_runcntl_RW;
+ u32 spu_status_R;
+ u32 spu_spc_R;
+ u32 spu_npc_RW;
+ u32 signal_notify1;
+ u32 signal_notify2;
+ u32 unused_pad1;
+};
+
+/*
+ * struct spu_priv1_collapsed - condensed privileged 1 area, w/o pads.
+ */
+struct spu_priv1_collapsed {
+ u64 mfc_sr1_RW;
+ u64 mfc_lpid_RW;
+ u64 spu_idr_RW;
+ u64 mfc_vr_RO;
+ u64 spu_vr_RO;
+ u64 int_mask_class0_RW;
+ u64 int_mask_class1_RW;
+ u64 int_mask_class2_RW;
+ u64 int_stat_class0_RW;
+ u64 int_stat_class1_RW;
+ u64 int_stat_class2_RW;
+ u64 int_route_RW;
+ u64 mfc_atomic_flush_RW;
+ u64 resource_allocation_groupID_RW;
+ u64 resource_allocation_enable_RW;
+ u64 mfc_fir_R;
+ u64 mfc_fir_status_or_W;
+ u64 mfc_fir_status_and_W;
+ u64 mfc_fir_mask_R;
+ u64 mfc_fir_mask_or_W;
+ u64 mfc_fir_mask_and_W;
+ u64 mfc_fir_chkstp_enable_RW;
+ u64 smf_sbi_signal_sel;
+ u64 smf_ato_signal_sel;
+ u64 mfc_sdr_RW;
+ u64 tlb_index_hint_RO;
+ u64 tlb_index_W;
+ u64 tlb_vpn_RW;
+ u64 tlb_rpn_RW;
+ u64 tlb_invalidate_entry_W;
+ u64 tlb_invalidate_all_W;
+ u64 smm_hid;
+ u64 mfc_accr_RW;
+ u64 mfc_dsisr_RW;
+ u64 mfc_dar_RW;
+ u64 rmt_index_RW;
+ u64 rmt_data1_RW;
+ u64 mfc_dsir_R;
+ u64 mfc_lsacr_RW;
+ u64 mfc_lscrr_R;
+ u64 mfc_tclass_id_RW;
+ u64 mfc_rm_boundary;
+ u64 smf_dma_signal_sel;
+ u64 smm_signal_sel;
+ u64 mfc_cer_R;
+ u64 pu_ecc_cntl_RW;
+ u64 pu_ecc_stat_RW;
+ u64 spu_ecc_addr_RW;
+ u64 spu_err_mask_RW;
+ u64 spu_trig0_sel;
+ u64 spu_trig1_sel;
+ u64 spu_trig2_sel;
+ u64 spu_trig3_sel;
+ u64 spu_trace_sel;
+ u64 spu_event0_sel;
+ u64 spu_event1_sel;
+ u64 spu_event2_sel;
+ u64 spu_event3_sel;
+ u64 spu_trace_cntl;
+};
+
+/*
+ * struct spu_priv2_collapsed - condensed priviliged 2 area, w/o pads.
+ */
+struct spu_priv2_collapsed {
+ u64 slb_index_W;
+ u64 slb_esid_RW;
+ u64 slb_vsid_RW;
+ u64 slb_invalidate_entry_W;
+ u64 slb_invalidate_all_W;
+ struct mfc_cq_sr spuq[16];
+ struct mfc_cq_sr puq[8];
+ u64 mfc_control_RW;
+ u64 puint_mb_R;
+ u64 spu_privcntl_RW;
+ u64 spu_lslr_RW;
+ u64 spu_chnlcntptr_RW;
+ u64 spu_chnlcnt_RW;
+ u64 spu_chnldata_RW;
+ u64 spu_cfg_RW;
+ u64 spu_tag_status_query_RW;
+ u64 spu_cmd_buf1_RW;
+ u64 spu_cmd_buf2_RW;
+ u64 spu_atomic_status_RW;
+};
+
+/**
+ * struct spu_state
+ * @lscsa: Local Store Context Save Area.
+ * @prob: Collapsed Problem State Area, w/o pads.
+ * @priv1: Collapsed Privileged 1 Area, w/o pads.
+ * @priv2: Collapsed Privileged 2 Area, w/o pads.
+ * @spu_chnlcnt_RW: Array of saved channel counts.
+ * @spu_chnldata_RW: Array of saved channel data.
+ * @suspend_time: Time stamp when decrementer disabled.
+ * @slb_esid_RW: Array of saved SLB esid entries.
+ * @slb_vsid_RW: Array of saved SLB vsid entries.
+ *
+ * Structure representing the whole of the SPU
+ * context save area (CSA). This struct contains
+ * all of the state necessary to suspend and then
+ * later optionally resume execution of an SPU
+ * context.
+ *
+ * The @lscsa region is by far the largest, and is
+ * allocated separately so that it may either be
+ * pinned or mapped to/from application memory, as
+ * appropriate for the OS environment.
+ */
+struct spu_state {
+ struct spu_lscsa *lscsa;
+ struct spu_problem_collapsed prob;
+ struct spu_priv1_collapsed priv1;
+ struct spu_priv2_collapsed priv2;
+ u64 spu_chnlcnt_RW[32];
+ u64 spu_chnldata_RW[32];
+ u32 spu_mailbox_data[4];
+ u32 pu_mailbox_data[1];
+ unsigned long suspend_time;
+ u64 slb_esid_RW[8];
+ u64 slb_vsid_RW[8];
+ spinlock_t register_lock;
+};
+
+extern void spu_init_csa(struct spu_state *csa);
+extern void spu_fini_csa(struct spu_state *csa);
+extern int spu_save(struct spu_state *prev, struct spu *spu);
+extern int spu_restore(struct spu_state *new, struct spu *spu);
+extern int spu_switch(struct spu_state *prev, struct spu_state *new,
+ struct spu *spu);
+
+#endif /* __KERNEL__ */
+#endif /* !__ASSEMBLY__ */
+#endif /* _SPU_CSA_H_ */
diff --git a/include/asm-powerpc/synch.h b/include/asm-powerpc/synch.h
index 4660c0394a77..c90d9d9aae72 100644
--- a/include/asm-powerpc/synch.h
+++ b/include/asm-powerpc/synch.h
@@ -1,7 +1,8 @@
#ifndef _ASM_POWERPC_SYNCH_H
#define _ASM_POWERPC_SYNCH_H
+#ifdef __KERNEL__
-#include <linux/config.h>
+#include <linux/stringify.h>
#ifdef __powerpc64__
#define __SUBARCH_HAS_LWSYNC
@@ -13,20 +14,12 @@
# define LWSYNC sync
#endif
-
-/*
- * Arguably the bitops and *xchg operations don't imply any memory barrier
- * or SMP ordering, but in fact a lot of drivers expect them to imply
- * both, since they do on x86 cpus.
- */
#ifdef CONFIG_SMP
-#define EIEIO_ON_SMP "eieio\n"
#define ISYNC_ON_SMP "\n\tisync"
-#define SYNC_ON_SMP __stringify(LWSYNC) "\n"
+#define LWSYNC_ON_SMP __stringify(LWSYNC) "\n"
#else
-#define EIEIO_ON_SMP
#define ISYNC_ON_SMP
-#define SYNC_ON_SMP
+#define LWSYNC_ON_SMP
#endif
static inline void eieio(void)
@@ -39,13 +32,5 @@ static inline void isync(void)
__asm__ __volatile__ ("isync" : : : "memory");
}
-#ifdef CONFIG_SMP
-#define eieio_on_smp() eieio()
-#define isync_on_smp() isync()
-#else
-#define eieio_on_smp() __asm__ __volatile__("": : :"memory")
-#define isync_on_smp() __asm__ __volatile__("": : :"memory")
-#endif
-
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SYNCH_H */
-
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 5341b75c75cb..d9bf53653b10 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -4,7 +4,6 @@
#ifndef _ASM_POWERPC_SYSTEM_H
#define _ASM_POWERPC_SYSTEM_H
-#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/hw_irq.h>
@@ -42,6 +41,7 @@
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+#ifdef __KERNEL__
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
@@ -54,7 +54,6 @@
#define smp_read_barrier_depends() do { } while(0)
#endif /* CONFIG_SMP */
-#ifdef __KERNEL__
struct task_struct;
struct pt_regs;
@@ -134,6 +133,14 @@ extern int fix_alignment(struct pt_regs *);
extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+#ifndef CONFIG_SMP
+extern void discard_lazy_cpu_state(void);
+#else
+static inline void discard_lazy_cpu_state(void)
+{
+}
+#endif
+
#ifdef CONFIG_ALTIVEC
extern void flush_altivec_to_thread(struct task_struct *);
#else
@@ -176,6 +183,16 @@ struct thread_struct;
extern struct task_struct *_switch(struct thread_struct *prev,
struct thread_struct *next);
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
extern unsigned int rtas_data;
extern int mem_init_done; /* set on boot once kmalloc can be called */
extern unsigned long memory_limit;
@@ -195,7 +212,7 @@ __xchg_u32(volatile void *p, unsigned long val)
unsigned long prev;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%2 \n"
PPC405_ERR77(0,%2)
" stwcx. %3,0,%2 \n\
@@ -215,7 +232,7 @@ __xchg_u64(volatile void *p, unsigned long val)
unsigned long prev;
__asm__ __volatile__(
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%2 \n"
PPC405_ERR77(0,%2)
" stdcx. %3,0,%2 \n\
@@ -270,7 +287,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
unsigned int prev;
__asm__ __volatile__ (
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: lwarx %0,0,%2 # __cmpxchg_u32\n\
cmpw 0,%0,%3\n\
bne- 2f\n"
@@ -294,7 +311,7 @@ __cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
unsigned long prev;
__asm__ __volatile__ (
- EIEIO_ON_SMP
+ LWSYNC_ON_SMP
"1: ldarx %0,0,%2 # __cmpxchg_u64\n\
cmpd 0,%0,%3\n\
bne- 2f\n\
diff --git a/include/asm-powerpc/tce.h b/include/asm-powerpc/tce.h
index 980a094fd5a7..6fa200ad7a7f 100644
--- a/include/asm-powerpc/tce.h
+++ b/include/asm-powerpc/tce.h
@@ -20,6 +20,7 @@
#ifndef _ASM_POWERPC_TCE_H
#define _ASM_POWERPC_TCE_H
+#ifdef __KERNEL__
/*
* Tces come in two formats, one for the virtual bus and a different
@@ -61,4 +62,5 @@ union tce_entry {
};
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_TCE_H */
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index e525f49bd179..67cdaf3ae9fc 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,8 +37,7 @@ struct thread_info {
int preempt_count; /* 0 => preemptable,
<0 => BUG */
struct restart_block restart_block;
- /* set by force_successful_syscall_return */
- unsigned char syscall_noerror;
+ void *nvgprs_frame;
/* low level flags - has atomic operations done on it */
unsigned long flags ____cacheline_aligned_in_smp;
};
@@ -90,9 +89,6 @@ struct thread_info {
#endif /* THREAD_SHIFT < PAGE_SHIFT */
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
/* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void)
{
@@ -123,6 +119,10 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
#define TIF_SECCOMP 11 /* secure computing */
+#define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */
+#define TIF_SAVE_NVGPRS 13 /* Save r14-r31 in signal frame */
+#define TIF_NOERROR 14 /* Force successful syscall return */
+#define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -136,10 +136,16 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
+#define _TIF_SAVE_NVGPRS (1<<TIF_SAVE_NVGPRS)
+#define _TIF_NOERROR (1<<TIF_NOERROR)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
- _TIF_NEED_RESCHED)
+ _TIF_NEED_RESCHED | _TIF_RESTOREALL | \
+ _TIF_RESTORE_SIGMASK)
+#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS)
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index d9b86a17271b..baddc9ab57ad 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -175,11 +175,10 @@ static inline void set_dec(int val)
set_dec_cpu6(val);
#else
#ifdef CONFIG_PPC_ISERIES
- struct paca_struct *lpaca = get_paca();
int cur_dec;
- if (lpaca->lppaca.shared_proc) {
- lpaca->lppaca.virtual_decr = val;
+ if (get_lppaca()->shared_proc) {
+ get_lppaca()->virtual_decr = val;
cur_dec = get_dec();
if (cur_dec > val)
HvCall_setVirtualDecr();
diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h
index 56659f121779..601a53cf96d5 100644
--- a/include/asm-powerpc/tlb.h
+++ b/include/asm-powerpc/tlb.h
@@ -11,6 +11,7 @@
*/
#ifndef _ASM_POWERPC_TLB_H
#define _ASM_POWERPC_TLB_H
+#ifdef __KERNEL__
#include <linux/config.h>
#ifndef __powerpc64__
@@ -67,4 +68,5 @@ static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
}
#endif
+#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_TLB_H */
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index db8095cbe09b..1e19cd00af25 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -1,5 +1,6 @@
#ifndef _ASM_POWERPC_TOPOLOGY_H
#define _ASM_POWERPC_TOPOLOGY_H
+#ifdef __KERNEL__
#include <linux/config.h>
@@ -38,7 +39,6 @@ static inline int node_to_first_cpu(int node)
.max_interval = 32, \
.busy_factor = 32, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000000), \
.cache_nice_tries = 1, \
.per_cpu_gain = 100, \
.busy_idx = 3, \
@@ -55,10 +55,15 @@ static inline int node_to_first_cpu(int node)
.nr_balance_failed = 0, \
}
+extern void __init dump_numa_cpu_topology(void);
+
#else
+static inline void dump_numa_cpu_topology(void) {}
+
#include <asm-generic/topology.h>
#endif /* CONFIG_NUMA */
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_TOPOLOGY_H */
diff --git a/include/asm-powerpc/udbg.h b/include/asm-powerpc/udbg.h
index a383383bc4d4..5c4236c342bb 100644
--- a/include/asm-powerpc/udbg.h
+++ b/include/asm-powerpc/udbg.h
@@ -1,5 +1,5 @@
/*
- * c 2001 PPC 64 Team, IBM Corp
+ * (c) 2001, 2006 IBM Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -9,12 +9,13 @@
#ifndef _ASM_POWERPC_UDBG_H
#define _ASM_POWERPC_UDBG_H
+#ifdef __KERNEL__
#include <linux/compiler.h>
#include <linux/init.h>
-extern void (*udbg_putc)(unsigned char c);
-extern unsigned char (*udbg_getc)(void);
+extern void (*udbg_putc)(char c);
+extern int (*udbg_getc)(void);
extern int (*udbg_getc_poll)(void);
extern void udbg_puts(const char *s);
@@ -23,9 +24,24 @@ 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_progress(char *s, unsigned short hex);
-extern void udbg_init_uart(void __iomem *comport, unsigned int speed);
+extern void udbg_init_uart(void __iomem *comport, unsigned int speed,
+ unsigned int clock);
+extern unsigned int udbg_probe_uart_speed(void __iomem *comport,
+ unsigned int clock);
struct device_node;
-extern void udbg_init_scc(struct device_node *np);
+extern void udbg_scc_init(int force_scc);
+extern int udbg_adb_init(int force_btext);
+extern void udbg_adb_init_early(void);
+
+extern void __init udbg_early_init(void);
+extern void __init udbg_init_debug_lpar(void);
+extern void __init udbg_init_pmac_realmode(void);
+extern void __init udbg_init_maple_realmode(void);
+extern void __init udbg_init_iseries(void);
+extern void __init udbg_init_rtas(void);
+
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_UDBG_H */
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 0991dfceef1d..a40cdff21a88 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -296,8 +296,12 @@
#define __NR_inotify_init 275
#define __NR_inotify_add_watch 276
#define __NR_inotify_rm_watch 277
+#define __NR_spu_run 278
+#define __NR_spu_create 279
+#define __NR_pselect6 280
+#define __NR_ppoll 281
-#define __NR_syscalls 278
+#define __NR_syscalls 282
#ifdef __KERNEL__
#define __NR__exit __NR_exit
@@ -442,11 +446,13 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#ifdef CONFIG_PPC32
#define __ARCH_WANT_OLD_STAT
#endif
#ifdef CONFIG_PPC64
#define __ARCH_WANT_COMPAT_SYS_TIME
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
#endif
/*
diff --git a/include/asm-powerpc/vdso_datapage.h b/include/asm-powerpc/vdso_datapage.h
index 411832d5bbdb..7aa92086c3fb 100644
--- a/include/asm-powerpc/vdso_datapage.h
+++ b/include/asm-powerpc/vdso_datapage.h
@@ -1,5 +1,6 @@
#ifndef _VDSO_DATAPAGE_H
#define _VDSO_DATAPAGE_H
+#ifdef __KERNEL__
/*
* Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM
@@ -105,4 +106,5 @@ extern struct vdso_data *vdso_data;
#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
#endif /* _SYSTEMCFG_H */
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h
index e0ccf108277c..0544ece51761 100644
--- a/include/asm-powerpc/vio.h
+++ b/include/asm-powerpc/vio.h
@@ -13,6 +13,7 @@
#ifndef _ASM_POWERPC_VIO_H
#define _ASM_POWERPC_VIO_H
+#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/init.h>
@@ -103,4 +104,5 @@ static inline struct vio_dev *to_vio_dev(struct device *dev)
return container_of(dev, struct vio_dev, dev);
}
+#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_VIO_H */
diff --git a/include/asm-ppc/bseip.h b/include/asm-ppc/bseip.h
deleted file mode 100644
index 691f4a52b0a5..000000000000
--- a/include/asm-ppc/bseip.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * A collection of structures, addresses, and values associated with
- * the Bright Star Engineering ip-Engine board. Copied from the MBX stuff.
- *
- * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
- */
-#ifndef __MACH_BSEIP_DEFS
-#define __MACH_BSEIP_DEFS
-
-#ifndef __ASSEMBLY__
-/* A Board Information structure that is given to a program when
- * prom starts it up.
- */
-typedef struct bd_info {
- unsigned int bi_memstart; /* Memory start address */
- unsigned int bi_memsize; /* Memory (end) size in bytes */
- unsigned int bi_intfreq; /* Internal Freq, in Hz */
- unsigned int bi_busfreq; /* Bus Freq, in Hz */
- unsigned char bi_enetaddr[6];
- unsigned int bi_baudrate;
-} bd_t;
-
-extern bd_t m8xx_board_info;
-
-/* Memory map is configured by the PROM startup.
- * All we need to get started is the IMMR.
- */
-#define IMAP_ADDR ((uint)0xff000000)
-#define IMAP_SIZE ((uint)(64 * 1024))
-#define PCMCIA_MEM_ADDR ((uint)0x04000000)
-#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
-#endif /* !__ASSEMBLY__ */
-
-/* We don't use the 8259.
-*/
-#define NR_8259_INTS 0
-
-#endif
diff --git a/include/asm-ppc/btext.h b/include/asm-ppc/btext.h
index ccaefabe0bf5..ed3630251b3b 100644
--- a/include/asm-ppc/btext.h
+++ b/include/asm-ppc/btext.h
@@ -17,7 +17,7 @@ extern unsigned long disp_BAT[2];
extern boot_infos_t disp_bi;
extern int boot_text_mapped;
-extern void init_boot_display(void);
+extern void btext_init(boot_infos_t *bi);
extern void btext_welcome(void);
extern void btext_prepare_BAT(void);
extern void btext_setup_display(int width, int height, int depth, int pitch,
diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h
index 9c21de1ff4ed..ddce616f765a 100644
--- a/include/asm-ppc/ibm_ocp.h
+++ b/include/asm-ppc/ibm_ocp.h
@@ -63,7 +63,6 @@ struct ocp_func_emac_data {
int wol_irq; /* WOL interrupt */
int mdio_idx; /* EMAC idx of MDIO master or -1 */
int tah_idx; /* TAH device index or -1 */
- int jumbo; /* Jumbo frames capable flag */
int phy_mode; /* PHY type or configurable mode */
u8 mac_addr[6]; /* EMAC mac address */
u32 phy_map; /* EMAC phy map */
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index 84ac6e258eef..df9cf6ed189d 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -27,6 +27,8 @@
#if defined(CONFIG_4xx)
#include <asm/ibm4xx.h>
+#elif defined(CONFIG_PPC_MPC52xx)
+#include <asm/mpc52xx.h>
#elif defined(CONFIG_8xx)
#include <asm/mpc8xx.h>
#elif defined(CONFIG_8260)
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index f01255bd1dc3..39200def8d11 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -35,8 +35,10 @@ struct machdep_calls {
int (*get_irq)(struct pt_regs *);
/* A general init function, called by ppc_init in init/main.c.
- May be NULL. */
+ May be NULL. DEPRECATED ! */
void (*init)(void);
+ /* For compatibility with merged platforms */
+ void (*init_early)(void);
void (*restart)(char *cmd);
void (*power_off)(void);
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index e5f80c22fbfc..a055e0756b9d 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -29,6 +29,17 @@ struct pt_regs;
#endif /* __ASSEMBLY__ */
+#ifdef CONFIG_PCI
+#define _IO_BASE isa_io_base
+#define _ISA_MEM_BASE isa_mem_base
+#define PCI_DRAM_OFFSET pci_dram_offset
+#else
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+#endif
+
+
/* ======================================================================== */
/* PPC Sys devices definition */
/* ======================================================================== */
@@ -107,7 +118,7 @@ enum ppc_sys_devices {
#define MPC52xx_SDMA_IRQ_NUM 17
#define MPC52xx_PERP_IRQ_NUM 23
-#define MPC52xx_CRIT_IRQ_BASE 0
+#define MPC52xx_CRIT_IRQ_BASE 1
#define MPC52xx_MAIN_IRQ_BASE (MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM)
#define MPC52xx_SDMA_IRQ_BASE (MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM)
#define MPC52xx_PERP_IRQ_BASE (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 9d14baea3d71..c8a96aa44fb7 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -37,6 +37,10 @@
#ifdef CONFIG_STX_GP3
#include <platforms/85xx/stx_gp3.h>
#endif
+#if defined(CONFIG_TQM8540) || defined(CONFIG_TQM8541) || \
+ defined(CONFIG_TQM8555) || defined(CONFIG_TQM8560)
+#include <platforms/85xx/tqm85xx.h>
+#endif
#define _IO_BASE isa_io_base
#define _ISA_MEM_BASE isa_mem_base
diff --git a/include/asm-ppc/pci-bridge.h b/include/asm-ppc/pci-bridge.h
index e58c78f90a5a..9d5230689b31 100644
--- a/include/asm-ppc/pci-bridge.h
+++ b/include/asm-ppc/pci-bridge.h
@@ -137,5 +137,14 @@ static inline unsigned char bridge_swizzle(unsigned char pin,
*/
extern int pciauto_bus_scan(struct pci_controller *, int);
+#ifdef CONFIG_PCI
+extern unsigned long pci_address_to_pio(phys_addr_t address);
+#else
+static inline unsigned long pci_address_to_pio(phys_addr_t address)
+{
+ return (unsigned long)-1;
+}
+#endif
+
#endif
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h
index 3e39827ed566..6d431d6fb022 100644
--- a/include/asm-ppc/prom.h
+++ b/include/asm-ppc/prom.h
@@ -136,5 +136,45 @@ extern unsigned long sub_reloc_offset(unsigned long);
#define PTRRELOC(x) ((typeof(x))add_reloc_offset((unsigned long)(x)))
#define PTRUNRELOC(x) ((typeof(x))sub_reloc_offset((unsigned long)(x)))
+
+/*
+ * OF address retreival & translation
+ */
+
+
+/* Translate an OF address block into a CPU physical address
+ */
+#define OF_BAD_ADDR ((u64)-1)
+extern u64 of_translate_address(struct device_node *np, u32 *addr);
+
+/* Extract an address from a device, returns the region size and
+ * the address space flags too. The PCI version uses a BAR number
+ * instead of an absolute index
+ */
+extern u32 *of_get_address(struct device_node *dev, int index,
+ u64 *size, unsigned int *flags);
+extern u32 *of_get_pci_address(struct device_node *dev, int bar_no,
+ u64 *size, unsigned int *flags);
+
+/* Get an address as a resource. Note that if your address is
+ * a PIO address, the conversion will fail if the physical address
+ * can't be internally converted to an IO token with
+ * pci_address_to_pio(), that is because it's either called to early
+ * or it can't be matched to any host bridge IO space
+ */
+extern int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r);
+extern int of_pci_address_to_resource(struct device_node *dev, int bar,
+ struct resource *r);
+
+#ifndef CONFIG_PPC_OF
+/*
+ * Fallback definitions for builds where we don't have prom.c included.
+ */
+#define machine_is_compatible(x) 0
+#define of_find_compatible_node(f, t, c) NULL
+#define get_property(p, n, l) NULL
+#endif
+
#endif /* _PPC_PROM_H */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h
index bd99cb53a19f..fb49c0c49ea1 100644
--- a/include/asm-ppc/system.h
+++ b/include/asm-ppc/system.h
@@ -4,7 +4,6 @@
#ifndef __PPC_SYSTEM_H
#define __PPC_SYSTEM_H
-#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/atomic.h>
@@ -39,7 +38,7 @@
#ifdef CONFIG_SMP
#define smp_mb() mb()
#define smp_rmb() rmb()
-#define smp_wmb() wmb()
+#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory")
#define smp_read_barrier_depends() read_barrier_depends()
#else
#define smp_mb() barrier()
@@ -74,6 +73,7 @@ extern void chrp_nvram_init(void);
extern void read_rtc_time(void);
extern void pmac_find_display(void);
extern void giveup_fpu(struct task_struct *);
+extern void disable_kernel_fp(void);
extern void enable_kernel_fp(void);
extern void flush_fp_to_thread(struct task_struct *);
extern void enable_kernel_altivec(void);
@@ -86,6 +86,14 @@ extern int fix_alignment(struct pt_regs *);
extern void cvt_fd(float *from, double *to, struct thread_struct *thread);
extern void cvt_df(double *from, float *to, struct thread_struct *thread);
+#ifndef CONFIG_SMP
+extern void discard_lazy_cpu_state(void);
+#else
+static inline void discard_lazy_cpu_state(void)
+{
+}
+#endif
+
#ifdef CONFIG_ALTIVEC
extern void flush_altivec_to_thread(struct task_struct *);
#else
@@ -123,6 +131,16 @@ extern struct task_struct *__switch_to(struct task_struct *,
struct task_struct *);
#define switch_to(prev, next, last) ((last) = __switch_to((prev), (next)))
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
struct thread_struct;
extern struct task_struct *_switch(struct thread_struct *prev,
struct thread_struct *next);
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index b3bd4f679f72..be6fefe223d6 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -5,7 +5,7 @@
* include/asm-s390/atomic.h
*
* S390 version
- * Copyright (C) 1999-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 1999-2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Denis Joseph Barrow,
* Arnd Bergmann (arndb@de.ibm.com)
@@ -45,59 +45,59 @@ typedef struct {
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
-static __inline__ void atomic_add(int i, atomic_t * v)
-{
- __CS_LOOP(v, i, "ar");
-}
static __inline__ int atomic_add_return(int i, atomic_t * v)
{
return __CS_LOOP(v, i, "ar");
}
-static __inline__ int atomic_add_negative(int i, atomic_t * v)
-{
- return __CS_LOOP(v, i, "ar") < 0;
-}
-static __inline__ void atomic_sub(int i, atomic_t * v)
-{
- __CS_LOOP(v, i, "sr");
-}
+#define atomic_add(_i, _v) atomic_add_return(_i, _v)
+#define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0)
+#define atomic_inc(_v) atomic_add_return(1, _v)
+#define atomic_inc_return(_v) atomic_add_return(1, _v)
+#define atomic_inc_and_test(_v) (atomic_add_return(1, _v) == 0)
+
static __inline__ int atomic_sub_return(int i, atomic_t * v)
{
return __CS_LOOP(v, i, "sr");
}
-static __inline__ void atomic_inc(volatile atomic_t * v)
-{
- __CS_LOOP(v, 1, "ar");
-}
-static __inline__ int atomic_inc_return(volatile atomic_t * v)
-{
- return __CS_LOOP(v, 1, "ar");
-}
+#define atomic_sub(_i, _v) atomic_sub_return(_i, _v)
+#define atomic_sub_and_test(_i, _v) (atomic_sub_return(_i, _v) == 0)
+#define atomic_dec(_v) atomic_sub_return(1, _v)
+#define atomic_dec_return(_v) atomic_sub_return(1, _v)
+#define atomic_dec_and_test(_v) (atomic_sub_return(1, _v) == 0)
-static __inline__ int atomic_inc_and_test(volatile atomic_t * v)
-{
- return __CS_LOOP(v, 1, "ar") == 0;
-}
-static __inline__ void atomic_dec(volatile atomic_t * v)
-{
- __CS_LOOP(v, 1, "sr");
-}
-static __inline__ int atomic_dec_return(volatile atomic_t * v)
-{
- return __CS_LOOP(v, 1, "sr");
-}
-static __inline__ int atomic_dec_and_test(volatile atomic_t * v)
-{
- return __CS_LOOP(v, 1, "sr") == 0;
-}
static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t * v)
{
__CS_LOOP(v, ~mask, "nr");
}
+
static __inline__ void atomic_set_mask(unsigned long mask, atomic_t * v)
{
__CS_LOOP(v, mask, "or");
}
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ __asm__ __volatile__(" cs %0,%3,0(%2)\n"
+ : "+d" (old), "=m" (v->counter)
+ : "a" (v), "d" (new), "m" (v->counter)
+ : "cc", "memory" );
+ return old;
+}
+
+static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
+ c = old;
+ return c != u;
+}
+
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
#undef __CS_LOOP
#ifdef __s390x__
@@ -123,97 +123,67 @@ typedef struct {
#define atomic64_read(v) ((v)->counter)
#define atomic64_set(v,i) (((v)->counter) = (i))
-static __inline__ void atomic64_add(long long i, atomic64_t * v)
-{
- __CSG_LOOP(v, i, "agr");
-}
static __inline__ long long atomic64_add_return(long long i, atomic64_t * v)
{
return __CSG_LOOP(v, i, "agr");
}
-static __inline__ long long atomic64_add_negative(long long i, atomic64_t * v)
-{
- return __CSG_LOOP(v, i, "agr") < 0;
-}
-static __inline__ void atomic64_sub(long long i, atomic64_t * v)
-{
- __CSG_LOOP(v, i, "sgr");
-}
-static __inline__ void atomic64_inc(volatile atomic64_t * v)
-{
- __CSG_LOOP(v, 1, "agr");
-}
-static __inline__ long long atomic64_inc_return(volatile atomic64_t * v)
-{
- return __CSG_LOOP(v, 1, "agr");
-}
-static __inline__ long long atomic64_inc_and_test(volatile atomic64_t * v)
-{
- return __CSG_LOOP(v, 1, "agr") == 0;
-}
-static __inline__ void atomic64_dec(volatile atomic64_t * v)
-{
- __CSG_LOOP(v, 1, "sgr");
-}
-static __inline__ long long atomic64_dec_return(volatile atomic64_t * v)
-{
- return __CSG_LOOP(v, 1, "sgr");
-}
-static __inline__ long long atomic64_dec_and_test(volatile atomic64_t * v)
+#define atomic64_add(_i, _v) atomic64_add_return(_i, _v)
+#define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0)
+#define atomic64_inc(_v) atomic64_add_return(1, _v)
+#define atomic64_inc_return(_v) atomic64_add_return(1, _v)
+#define atomic64_inc_and_test(_v) (atomic64_add_return(1, _v) == 0)
+
+static __inline__ long long atomic64_sub_return(long long i, atomic64_t * v)
{
- return __CSG_LOOP(v, 1, "sgr") == 0;
+ return __CSG_LOOP(v, i, "sgr");
}
+#define atomic64_sub(_i, _v) atomic64_sub_return(_i, _v)
+#define atomic64_sub_and_test(_i, _v) (atomic64_sub_return(_i, _v) == 0)
+#define atomic64_dec(_v) atomic64_sub_return(1, _v)
+#define atomic64_dec_return(_v) atomic64_sub_return(1, _v)
+#define atomic64_dec_and_test(_v) (atomic64_sub_return(1, _v) == 0)
+
static __inline__ void atomic64_clear_mask(unsigned long mask, atomic64_t * v)
{
__CSG_LOOP(v, ~mask, "ngr");
}
+
static __inline__ void atomic64_set_mask(unsigned long mask, atomic64_t * v)
{
__CSG_LOOP(v, mask, "ogr");
}
-#undef __CSG_LOOP
-#endif
-
-/*
- returns 0 if expected_oldval==value in *v ( swap was successful )
- returns 1 if unsuccessful.
+static __inline__ long long atomic64_cmpxchg(atomic64_t *v,
+ long long old, long long new)
+{
+ __asm__ __volatile__(" csg %0,%3,0(%2)\n"
+ : "+d" (old), "=m" (v->counter)
+ : "a" (v), "d" (new), "m" (v->counter)
+ : "cc", "memory" );
+ return old;
+}
- This is non-portable, use bitops or spinlocks instead!
-*/
-static __inline__ int
-atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
+static __inline__ int atomic64_add_unless(atomic64_t *v,
+ long long a, long long u)
{
- int retval;
-
- __asm__ __volatile__(
- " lr %0,%3\n"
- " cs %0,%4,0(%2)\n"
- " ipm %0\n"
- " srl %0,28\n"
- "0:"
- : "=&d" (retval), "=m" (v->counter)
- : "a" (v), "d" (expected_oldval) , "d" (new_val),
- "m" (v->counter) : "cc", "memory" );
- return retval;
+ long long c, old;
+
+ c = atomic64_read(v);
+ while (c != u && (old = atomic64_cmpxchg(v, c, c + a)) != c)
+ c = old;
+ return c != u;
}
-#define atomic_cmpxchg(v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter)))
+#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
-#define atomic_add_unless(v, a, u) \
-({ \
- int c, old; \
- c = atomic_read(v); \
- while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
- c = old; \
- c != (u); \
-})
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+#undef __CSG_LOOP
+#endif
#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()
#define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb()
+#include <asm-generic/atomic.h>
#endif /* __KERNEL__ */
#endif /* __ARCH_S390_ATOMIC__ */
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index b07c578b22ea..61232760cc3b 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -839,6 +839,7 @@ static inline int sched_find_first_bit(unsigned long *b)
* fls: find last bit set.
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
/*
* hweightN: returns the hamming weight (i.e. the number
diff --git a/include/asm-s390/cache.h b/include/asm-s390/cache.h
index 29845378b206..e20cdd9074db 100644
--- a/include/asm-s390/cache.h
+++ b/include/asm-s390/cache.h
@@ -13,7 +13,6 @@
#define L1_CACHE_BYTES 256
#define L1_CACHE_SHIFT 8
-#define L1_CACHE_SHIFT_MAX 8 /* largest L1 which this arch supports */
#define ARCH_KMALLOC_MINALIGN 8
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index 3eb231af5d51..12456cb2f882 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -185,8 +185,5 @@ extern struct ccw_device *ccw_device_probe_console(void);
extern int _ccw_device_get_device_number(struct ccw_device *);
extern int _ccw_device_get_subchannel_number(struct ccw_device *);
-extern struct device *s390_root_dev_register(const char *);
-extern void s390_root_dev_unregister(struct device *);
-
extern void *ccw_device_get_chp_desc(struct ccw_device *, int);
#endif /* _S390_CCWDEV_H_ */
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 372d51cccd53..710646e64f7d 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -163,7 +163,7 @@ static inline int dump_regs(struct pt_regs *ptregs, elf_gregset_t *regs)
static inline int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{
- struct pt_regs *ptregs = __KSTK_PTREGS(tsk);
+ struct pt_regs *ptregs = task_pt_regs(tsk);
memcpy(&regs->psw, &ptregs->psw, sizeof(regs->psw)+sizeof(regs->gprs));
memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
regs->orig_gpr2 = ptregs->orig_gpr2;
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-s390/futex.h
+++ b/include/asm-s390/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-s390/ioctl.h b/include/asm-s390/ioctl.h
index df7394345ac4..b279fe06dfe5 100644
--- a/include/asm-s390/ioctl.h
+++ b/include/asm-s390/ioctl.h
@@ -1,88 +1 @@
-/*
- * include/asm-s390/ioctl.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/ioctl.h"
- */
-
-#ifndef _S390_IOCTL_H
-#define _S390_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#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 long __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 ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _S390_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-s390/kexec.h b/include/asm-s390/kexec.h
index 54cf7d9f251c..ce28ddda0f50 100644
--- a/include/asm-s390/kexec.h
+++ b/include/asm-s390/kexec.h
@@ -35,8 +35,9 @@
#define KEXEC_ARCH KEXEC_ARCH_S390
#define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
-extern note_buf_t crash_notes[];
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs) { }
#endif /*_S390_KEXEC_H */
diff --git a/include/asm-s390/mman.h b/include/asm-s390/mman.h
index ea86bd12204f..c8d5409b5d56 100644
--- a/include/asm-s390/mman.h
+++ b/include/asm-s390/mman.h
@@ -43,6 +43,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-s390/mutex.h b/include/asm-s390/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-s390/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 4ec652ebb3b1..c5cbc4bd8414 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -191,10 +191,10 @@ extern void show_registers(struct pt_regs *regs);
extern void show_trace(struct task_struct *task, unsigned long *sp);
unsigned long get_wchan(struct task_struct *p);
-#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \
- ((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)))
-#define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr)
-#define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15])
+#define task_pt_regs(tsk) ((struct pt_regs *) \
+ (task_stack_page(tsk) + THREAD_SIZE) - 1)
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->psw.addr)
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->gprs[15])
/*
* Give up the time slice of the virtual PU.
diff --git a/include/asm-s390/qdio.h b/include/asm-s390/qdio.h
index 0ddf0a8ef8de..7bc15f0231db 100644
--- a/include/asm-s390/qdio.h
+++ b/include/asm-s390/qdio.h
@@ -195,12 +195,14 @@ struct qdr {
/*
* queue information block (QIB)
*/
-#define QIB_AC_INBOUND_PCI_SUPPORTED 0x80
-#define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40
+#define QIB_AC_INBOUND_PCI_SUPPORTED 0x80
+#define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40
+#define QIB_RFLAGS_ENABLE_QEBSM 0x80
+
struct qib {
unsigned int qfmt : 8; /* queue format */
unsigned int pfmt : 8; /* impl. dep. parameter format */
- unsigned int res1 : 8; /* reserved */
+ unsigned int rflags : 8; /* QEBSM */
unsigned int ac : 8; /* adapter characteristics */
unsigned int res2; /* reserved */
#ifdef QDIO_32_BIT
diff --git a/include/asm-s390/s390_rdev.h b/include/asm-s390/s390_rdev.h
new file mode 100644
index 000000000000..6fa20442a48c
--- /dev/null
+++ b/include/asm-s390/s390_rdev.h
@@ -0,0 +1,15 @@
+/*
+ * include/asm-s390/ccwdev.h
+ *
+ * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ * Carsten Otte <cotte@de.ibm.com>
+ *
+ * Interface for s390 root device
+ */
+
+#ifndef _S390_RDEV_H_
+#define _S390_RDEV_H_
+extern struct device *s390_root_dev_register(const char *);
+extern void s390_root_dev_unregister(struct device *);
+#endif /* _S390_RDEV_H_ */
diff --git a/include/asm-s390/sigcontext.h b/include/asm-s390/sigcontext.h
index 803545351dd8..aeb6e0b13329 100644
--- a/include/asm-s390/sigcontext.h
+++ b/include/asm-s390/sigcontext.h
@@ -8,6 +8,8 @@
#ifndef _ASM_S390_SIGCONTEXT_H
#define _ASM_S390_SIGCONTEXT_H
+#include <linux/compiler.h>
+
#define __NUM_GPRS 16
#define __NUM_FPRS 16
#define __NUM_ACRS 16
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 864cae7e1fd6..b2e65e8bf812 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -104,14 +104,25 @@ static inline void restore_access_regs(unsigned int *acrs)
prev = __switch_to(prev,next); \
} while (0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void account_user_vtime(struct task_struct *);
+extern void account_vtime(struct task_struct *);
+extern void account_tick_vtime(struct task_struct *);
extern void account_system_vtime(struct task_struct *);
#endif
#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
- account_system_vtime(prev); \
+ account_vtime(prev); \
} while (0)
#define nop() __asm__ __volatile__ ("nop")
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index 6c18a3f24316..f3797a52c4ea 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -81,8 +81,6 @@ static inline struct thread_info *current_thread_info(void)
#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL,THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti),THREAD_ORDER)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index 10a619da4761..be104f21c70a 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -61,8 +61,10 @@
#define segment_eq(a,b) ((a).ar4 == (b).ar4)
-#define __access_ok(addr,size) (1)
-
+static inline int __access_ok(const void *addr, unsigned long size)
+{
+ return 1;
+}
#define access_ok(type,addr,size) __access_ok(addr,size)
/*
@@ -206,25 +208,25 @@ extern int __put_user_bad(void) __attribute__((noreturn));
case 1: { \
unsigned char __x; \
__get_user_asm(__x, ptr, __gu_err); \
- (x) = (__typeof__(*(ptr))) __x; \
+ (x) = *(__typeof__(*(ptr)) *) &__x; \
break; \
}; \
case 2: { \
unsigned short __x; \
__get_user_asm(__x, ptr, __gu_err); \
- (x) = (__typeof__(*(ptr))) __x; \
+ (x) = *(__typeof__(*(ptr)) *) &__x; \
break; \
}; \
case 4: { \
unsigned int __x; \
__get_user_asm(__x, ptr, __gu_err); \
- (x) = (__typeof__(*(ptr))) __x; \
+ (x) = *(__typeof__(*(ptr)) *) &__x; \
break; \
}; \
case 8: { \
unsigned long long __x; \
__get_user_asm(__x, ptr, __gu_err); \
- (x) = (__typeof__(*(ptr))) __x; \
+ (x) = *(__typeof__(*(ptr)) *) &__x; \
break; \
}; \
default: \
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index f97d92691f17..2861cdc243ad 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -539,7 +539,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
-# ifdef CONFIG_ARCH_S390_31
+# ifndef CONFIG_64BIT
# define __ARCH_WANT_STAT64
# define __ARCH_WANT_SYS_TIME
# endif
diff --git a/include/asm-s390/vtoc.h b/include/asm-s390/vtoc.h
index 41d369f38b0e..d1de5b7ebb0b 100644
--- a/include/asm-s390/vtoc.h
+++ b/include/asm-s390/vtoc.h
@@ -176,4 +176,28 @@ struct vtoc_format7_label
struct vtoc_cchhb DS7PTRDS; /* pointer to next FMT7 DSCB */
} __attribute__ ((packed));
+struct vtoc_cms_label {
+ u8 label_id[4]; /* Label identifier */
+ u8 vol_id[6]; /* Volid */
+ u16 version_id; /* Version identifier */
+ u32 block_size; /* Disk block size */
+ u32 origin_ptr; /* Disk origin pointer */
+ u32 usable_count; /* Number of usable cylinders/blocks */
+ u32 formatted_count; /* Maximum number of formatted cylinders/
+ * blocks */
+ u32 block_count; /* Disk size in CMS blocks */
+ u32 used_count; /* Number of CMS blocks in use */
+ u32 fst_size; /* File Status Table (FST) size */
+ u32 fst_count; /* Number of FSTs per CMS block */
+ u8 format_date[6]; /* Disk FORMAT date */
+ u8 reserved1[2];
+ u32 disk_offset; /* Disk offset when reserved*/
+ u32 map_block; /* Allocation Map Block with next hole */
+ u32 hblk_disp; /* Displacement into HBLK data of next hole */
+ u32 user_disp; /* Displacement into user part of Allocation
+ * map */
+ u8 reserved2[4];
+ u8 segment_name[8]; /* Name of shared segment */
+} __attribute__ ((packed));
+
#endif /* _ASM_S390_VTOC_H */
diff --git a/include/asm-sh/atomic.h b/include/asm-sh/atomic.h
index aabfd334462c..fb627de217f2 100644
--- a/include/asm-sh/atomic.h
+++ b/include/asm-sh/atomic.h
@@ -101,6 +101,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -140,4 +142,5 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __ASM_SH_ATOMIC_H */
diff --git a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
index 5163d1ff2f1b..1c5260860045 100644
--- a/include/asm-sh/bitops.h
+++ b/include/asm-sh/bitops.h
@@ -470,6 +470,7 @@ found_middle:
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#endif /* __KERNEL__ */
diff --git a/include/asm-sh/bus-sh.h b/include/asm-sh/bus-sh.h
index 83c5d2fd057f..e42d63b65cb5 100644
--- a/include/asm-sh/bus-sh.h
+++ b/include/asm-sh/bus-sh.h
@@ -21,6 +21,7 @@ struct sh_dev {
void *mapbase;
unsigned int irq[6];
u64 *dma_mask;
+ u64 coherent_dma_mask;
};
#define to_sh_dev(d) container_of((d), struct sh_dev, dev)
diff --git a/include/asm-sh/cache.h b/include/asm-sh/cache.h
index 9b4dd6d8212e..656fdfe9e8b4 100644
--- a/include/asm-sh/cache.h
+++ b/include/asm-sh/cache.h
@@ -22,8 +22,6 @@
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-#define L1_CACHE_SHIFT_MAX 5 /* largest L1 which this arch supports */
-
struct cache_info {
unsigned int ways;
unsigned int sets;
diff --git a/include/asm-sh/clock.h b/include/asm-sh/clock.h
new file mode 100644
index 000000000000..fdfb75b30f0d
--- /dev/null
+++ b/include/asm-sh/clock.h
@@ -0,0 +1,61 @@
+#ifndef __ASM_SH_CLOCK_H
+#define __ASM_SH_CLOCK_H
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+
+struct clk;
+
+struct clk_ops {
+ void (*init)(struct clk *clk);
+ void (*enable)(struct clk *clk);
+ void (*disable)(struct clk *clk);
+ void (*recalc)(struct clk *clk);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+};
+
+struct clk {
+ struct list_head node;
+ const char *name;
+
+ struct module *owner;
+
+ struct clk *parent;
+ struct clk_ops *ops;
+
+ struct kref kref;
+
+ unsigned long rate;
+ unsigned long flags;
+};
+
+#define CLK_ALWAYS_ENABLED (1 << 0)
+#define CLK_RATE_PROPAGATES (1 << 1)
+
+/* Should be defined by processor-specific code */
+void arch_init_clk_ops(struct clk_ops **, int type);
+
+/* arch/sh/kernel/cpu/clock.c */
+int clk_init(void);
+
+int __clk_enable(struct clk *);
+int clk_enable(struct clk *);
+
+void __clk_disable(struct clk *);
+void clk_disable(struct clk *);
+
+int clk_set_rate(struct clk *, unsigned long rate);
+unsigned long clk_get_rate(struct clk *);
+void clk_recalc_rate(struct clk *);
+
+struct clk *clk_get(const char *id);
+void clk_put(struct clk *);
+
+int clk_register(struct clk *);
+void clk_unregister(struct clk *);
+
+int show_clocks(struct seq_file *m);
+
+#endif /* __ASM_SH_CLOCK_H */
+
diff --git a/include/asm-sh/cpu-sh3/dma.h b/include/asm-sh/cpu-sh3/dma.h
index b972e715f9ee..954801b46022 100644
--- a/include/asm-sh/cpu-sh3/dma.h
+++ b/include/asm-sh/cpu-sh3/dma.h
@@ -3,5 +3,34 @@
#define SH_DMAC_BASE 0xa4000020
-#endif /* __ASM_CPU_SH3_DMA_H */
+/* Definitions for the SuperH DMAC */
+#define TM_BURST 0x00000020
+#define TS_8 0x00000000
+#define TS_16 0x00000008
+#define TS_32 0x00000010
+#define TS_128 0x00000018
+
+#define CHCR_TS_MASK 0x18
+#define CHCR_TS_SHIFT 3
+
+#define DMAOR_INIT DMAOR_DME
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ */
+enum {
+ XMIT_SZ_8BIT,
+ XMIT_SZ_16BIT,
+ XMIT_SZ_32BIT,
+ XMIT_SZ_128BIT,
+};
+
+static unsigned int ts_shift[] __attribute__ ((used)) = {
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ [XMIT_SZ_128BIT] = 4,
+};
+
+#endif /* __ASM_CPU_SH3_DMA_H */
diff --git a/include/asm-sh/cpu-sh4/dma.h b/include/asm-sh/cpu-sh4/dma.h
index e2b91adf821a..0dfe61f14802 100644
--- a/include/asm-sh/cpu-sh4/dma.h
+++ b/include/asm-sh/cpu-sh4/dma.h
@@ -1,17 +1,49 @@
#ifndef __ASM_CPU_SH4_DMA_H
#define __ASM_CPU_SH4_DMA_H
+#ifdef CONFIG_CPU_SH4A
+#define SH_DMAC_BASE 0xfc808020
+#else
#define SH_DMAC_BASE 0xffa00000
+#endif
-#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \
- SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30})
-#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \
- SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34})
-#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \
- SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38})
-#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \
- SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c})
-#define DMAOR (SH_DMAC_BASE + 0x40)
+/* Definitions for the SuperH DMAC */
+#define TM_BURST 0x0000080
+#define TS_8 0x00000010
+#define TS_16 0x00000020
+#define TS_32 0x00000030
+#define TS_64 0x00000000
-#endif /* __ASM_CPU_SH4_DMA_H */
+#define CHCR_TS_MASK 0x30
+#define CHCR_TS_SHIFT 4
+
+#define DMAOR_COD 0x00000008
+
+#define DMAOR_INIT ( 0x8000 | DMAOR_DME )
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+ XMIT_SZ_64BIT,
+ XMIT_SZ_8BIT,
+ XMIT_SZ_16BIT,
+ XMIT_SZ_32BIT,
+ XMIT_SZ_256BIT,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int ts_shift[] __attribute__ ((used)) = {
+ [XMIT_SZ_64BIT] = 3,
+ [XMIT_SZ_8BIT] = 0,
+ [XMIT_SZ_16BIT] = 1,
+ [XMIT_SZ_32BIT] = 2,
+ [XMIT_SZ_256BIT] = 5,
+};
+
+#endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index 201d94fd214f..ef2b9b1ae41f 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -12,6 +12,8 @@
#if defined(CONFIG_CPU_SUBTYPE_SH73180)
#define FRQCR 0xa4150000
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define FRQCR 0xffc80000
#else
#define FRQCR 0xffc00000
#endif
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index d3fa5c2b889d..48f1f42c5d14 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -4,6 +4,7 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <asm/scatterlist.h>
+#include <asm/cacheflush.h>
#include <asm/io.h>
extern struct bus_type pci_bus_type;
@@ -141,24 +142,24 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
}
}
-static inline void dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
+static void dma_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
__attribute__ ((alias("dma_sync_single")));
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction dir)
+static void dma_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
__attribute__ ((alias("dma_sync_single")));
-static inline void dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction dir)
+static void dma_sync_sg_for_cpu(struct device *dev,
+ struct scatterlist *sg, int nelems,
+ enum dma_data_direction dir)
__attribute__ ((alias("dma_sync_sg")));
-static inline void dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction dir)
+static void dma_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nelems,
+ enum dma_data_direction dir)
__attribute__ ((alias("dma_sync_sg")));
static inline int dma_get_cache_alignment(void)
diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h
index 8e9436093ca8..a118a0d43053 100644
--- a/include/asm-sh/dma.h
+++ b/include/asm-sh/dma.h
@@ -15,6 +15,7 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/sysdev.h>
+#include <linux/device.h>
#include <asm/cpu/dma.h>
#include <asm/semaphore.h>
@@ -54,8 +55,8 @@ enum {
* DMA channel capabilities / flags
*/
enum {
- DMA_CONFIGURED = 0x00,
DMA_TEI_CAPABLE = 0x01,
+ DMA_CONFIGURED = 0x02,
};
extern spinlock_t dma_spin_lock;
@@ -74,7 +75,8 @@ struct dma_ops {
struct dma_channel {
char dev_id[16];
- unsigned int chan;
+ unsigned int chan; /* Physical channel number */
+ unsigned int vchan; /* Virtual channel number */
unsigned int mode;
unsigned int count;
@@ -91,6 +93,8 @@ struct dma_channel {
};
struct dma_info {
+ struct platform_device *pdev;
+
const char *name;
unsigned int nr_channels;
unsigned long flags;
@@ -130,7 +134,11 @@ extern void unregister_dmac(struct dma_info *info);
#ifdef CONFIG_SYSFS
/* arch/sh/drivers/dma/dma-sysfs.c */
-extern int dma_create_sysfs_files(struct dma_channel *);
+extern int dma_create_sysfs_files(struct dma_channel *, struct dma_info *);
+extern void dma_remove_sysfs_files(struct dma_channel *, struct dma_info *);
+#else
+#define dma_create_sysfs_file(channel, info) do { } while (0)
+#define dma_remove_sysfs_file(channel, info) do { } while (0)
#endif
#ifdef CONFIG_PCI
diff --git a/include/asm-sh/freq.h b/include/asm-sh/freq.h
index 2c0fde46a0ed..39c0e091cf58 100644
--- a/include/asm-sh/freq.h
+++ b/include/asm-sh/freq.h
@@ -14,16 +14,5 @@
#include <asm/cpu/freq.h>
-/* arch/sh/kernel/time.c */
-extern void get_current_frequency_divisors(unsigned int *ifc, unsigned int *pfc, unsigned int *bfc);
-
-extern unsigned int get_ifc_divisor(unsigned int value);
-extern unsigned int get_ifc_divisor(unsigned int value);
-extern unsigned int get_ifc_divisor(unsigned int value);
-
-extern unsigned int get_ifc_value(unsigned int divisor);
-extern unsigned int get_pfc_value(unsigned int divisor);
-extern unsigned int get_bfc_value(unsigned int divisor);
-
#endif /* __KERNEL__ */
#endif /* __ASM_SH_FREQ_H */
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-sh/futex.h
+++ b/include/asm-sh/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-sh/io.h b/include/asm-sh/io.h
index 6bc343fee7a0..b0b2937b6f83 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -11,7 +11,7 @@
* For read{b,w,l} and write{b,w,l} there are also __raw versions, which
* do not have a memory barrier after them.
*
- * In addition, we have
+ * In addition, we have
* ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O.
* which are processor specific.
*/
@@ -23,19 +23,27 @@
* inb by default expands to _inb, but the machine specific code may
* define it to __inb if it chooses.
*/
-
+#include <linux/config.h>
#include <asm/cache.h>
#include <asm/system.h>
#include <asm/addrspace.h>
#include <asm/machvec.h>
-#include <linux/config.h>
+#include <asm/pgtable.h>
+#include <asm-generic/iomap.h>
+
+#ifdef __KERNEL__
/*
* Depending on which platform we are running on, we need different
* I/O functions.
*/
+#define __IO_PREFIX generic
+#include <asm/io_generic.h>
+
+#define maybebadio(port) \
+ printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
+ __FUNCTION__, __LINE__, (port), (u32)__builtin_return_address(0))
-#ifdef __KERNEL__
/*
* Since boards are able to define their own set of I/O routines through
* their respective machine vector, we always wrap through the mv.
@@ -44,113 +52,120 @@
* a given routine, it will be wrapped to generic code at run-time.
*/
-# define __inb(p) sh_mv.mv_inb((p))
-# define __inw(p) sh_mv.mv_inw((p))
-# define __inl(p) sh_mv.mv_inl((p))
-# define __outb(x,p) sh_mv.mv_outb((x),(p))
-# define __outw(x,p) sh_mv.mv_outw((x),(p))
-# define __outl(x,p) sh_mv.mv_outl((x),(p))
-
-# define __inb_p(p) sh_mv.mv_inb_p((p))
-# define __inw_p(p) sh_mv.mv_inw_p((p))
-# define __inl_p(p) sh_mv.mv_inl_p((p))
-# define __outb_p(x,p) sh_mv.mv_outb_p((x),(p))
-# define __outw_p(x,p) sh_mv.mv_outw_p((x),(p))
-# define __outl_p(x,p) sh_mv.mv_outl_p((x),(p))
-
-# define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c))
-# define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c))
-# define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c))
-# define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c))
-# define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c))
-# define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c))
-
-# define __readb(a) sh_mv.mv_readb((a))
-# define __readw(a) sh_mv.mv_readw((a))
-# define __readl(a) sh_mv.mv_readl((a))
-# define __writeb(v,a) sh_mv.mv_writeb((v),(a))
-# define __writew(v,a) sh_mv.mv_writew((v),(a))
-# define __writel(v,a) sh_mv.mv_writel((v),(a))
-
-# define __ioremap(a,s) sh_mv.mv_ioremap((a), (s))
-# define __iounmap(a) sh_mv.mv_iounmap((a))
-
-# define __isa_port2addr(a) sh_mv.mv_isa_port2addr(a)
-
-# define inb __inb
-# define inw __inw
-# define inl __inl
-# define outb __outb
-# define outw __outw
-# define outl __outl
-
-# define inb_p __inb_p
-# define inw_p __inw_p
-# define inl_p __inl_p
-# define outb_p __outb_p
-# define outw_p __outw_p
-# define outl_p __outl_p
-
-# define insb __insb
-# define insw __insw
-# define insl __insl
-# define outsb __outsb
-# define outsw __outsw
-# define outsl __outsl
-
-# define __raw_readb __readb
-# define __raw_readw __readw
-# define __raw_readl __readl
-# define __raw_writeb __writeb
-# define __raw_writew __writew
-# define __raw_writel __writel
+#define __inb(p) sh_mv.mv_inb((p))
+#define __inw(p) sh_mv.mv_inw((p))
+#define __inl(p) sh_mv.mv_inl((p))
+#define __outb(x,p) sh_mv.mv_outb((x),(p))
+#define __outw(x,p) sh_mv.mv_outw((x),(p))
+#define __outl(x,p) sh_mv.mv_outl((x),(p))
+
+#define __inb_p(p) sh_mv.mv_inb_p((p))
+#define __inw_p(p) sh_mv.mv_inw_p((p))
+#define __inl_p(p) sh_mv.mv_inl_p((p))
+#define __outb_p(x,p) sh_mv.mv_outb_p((x),(p))
+#define __outw_p(x,p) sh_mv.mv_outw_p((x),(p))
+#define __outl_p(x,p) sh_mv.mv_outl_p((x),(p))
+
+#define __insb(p,b,c) sh_mv.mv_insb((p), (b), (c))
+#define __insw(p,b,c) sh_mv.mv_insw((p), (b), (c))
+#define __insl(p,b,c) sh_mv.mv_insl((p), (b), (c))
+#define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c))
+#define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c))
+#define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c))
+
+#define __readb(a) sh_mv.mv_readb((a))
+#define __readw(a) sh_mv.mv_readw((a))
+#define __readl(a) sh_mv.mv_readl((a))
+#define __writeb(v,a) sh_mv.mv_writeb((v),(a))
+#define __writew(v,a) sh_mv.mv_writew((v),(a))
+#define __writel(v,a) sh_mv.mv_writel((v),(a))
+
+#define inb __inb
+#define inw __inw
+#define inl __inl
+#define outb __outb
+#define outw __outw
+#define outl __outl
+
+#define inb_p __inb_p
+#define inw_p __inw_p
+#define inl_p __inl_p
+#define outb_p __outb_p
+#define outw_p __outw_p
+#define outl_p __outl_p
+
+#define insb __insb
+#define insw __insw
+#define insl __insl
+#define outsb __outsb
+#define outsw __outsw
+#define outsl __outsl
+
+#define __raw_readb(a) __readb((void __iomem *)(a))
+#define __raw_readw(a) __readw((void __iomem *)(a))
+#define __raw_readl(a) __readl((void __iomem *)(a))
+#define __raw_writeb(v, a) __writeb(v, (void __iomem *)(a))
+#define __raw_writew(v, a) __writew(v, (void __iomem *)(a))
+#define __raw_writel(v, a) __writel(v, (void __iomem *)(a))
/*
* The platform header files may define some of these macros to use
* the inlined versions where appropriate. These macros may also be
* redefined by userlevel programs.
*/
-#ifdef __raw_readb
-# define readb(a) ({ unsigned long r_ = __raw_readb((unsigned long)a); mb(); r_; })
+#ifdef __readb
+# define readb(a) ({ unsigned long r_ = __raw_readb(a); mb(); r_; })
#endif
#ifdef __raw_readw
-# define readw(a) ({ unsigned long r_ = __raw_readw((unsigned long)a); mb(); r_; })
+# define readw(a) ({ unsigned long r_ = __raw_readw(a); mb(); r_; })
#endif
#ifdef __raw_readl
-# define readl(a) ({ unsigned long r_ = __raw_readl((unsigned long)a); mb(); r_; })
+# define readl(a) ({ unsigned long r_ = __raw_readl(a); mb(); r_; })
#endif
#ifdef __raw_writeb
-# define writeb(v,a) ({ __raw_writeb((v),(unsigned long)(a)); mb(); })
+# define writeb(v,a) ({ __raw_writeb((v),(a)); mb(); })
#endif
#ifdef __raw_writew
-# define writew(v,a) ({ __raw_writew((v),(unsigned long)(a)); mb(); })
+# define writew(v,a) ({ __raw_writew((v),(a)); mb(); })
#endif
#ifdef __raw_writel
-# define writel(v,a) ({ __raw_writel((v),(unsigned long)(a)); mb(); })
+# define writel(v,a) ({ __raw_writel((v),(a)); mb(); })
#endif
#define readb_relaxed(a) readb(a)
#define readw_relaxed(a) readw(a)
#define readl_relaxed(a) readl(a)
-#define mmiowb()
+/* Simple MMIO */
+#define ioread8(a) readb(a)
+#define ioread16(a) readw(a)
+#define ioread16be(a) be16_to_cpu(__raw_readw((a)))
+#define ioread32(a) readl(a)
+#define ioread32be(a) be32_to_cpu(__raw_readl((a)))
-/*
- * If the platform has PC-like I/O, this function converts the offset into
- * an address.
- */
-static __inline__ unsigned long isa_port2addr(unsigned long offset)
-{
- return __isa_port2addr(offset);
-}
+#define iowrite8(v,a) writeb((v),(a))
+#define iowrite16(v,a) writew((v),(a))
+#define iowrite16be(v,a) __raw_writew(cpu_to_be16((v)),(a))
+#define iowrite32(v,a) writel((v),(a))
+#define iowrite32be(v,a) __raw_writel(cpu_to_be32((v)),(a))
+
+#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))
+
+#define mmiowb() wmb() /* synco on SH-4A, otherwise a nop */
/*
* This function provides a method for the generic case where a board-specific
- * isa_port2addr simply needs to return the port + some arbitrary port base.
+ * ioport_map simply needs to return the port + some arbitrary port base.
*
* We use this at board setup time to implicitly set the port base, and
- * as a result, we can use the generic isa_port2addr.
+ * as a result, we can use the generic ioport_map.
*/
static inline void __set_io_port_base(unsigned long pbase)
{
@@ -159,51 +174,52 @@ static inline void __set_io_port_base(unsigned long pbase)
generic_io_base = pbase;
}
-#define isa_readb(a) readb(isa_port2addr(a))
-#define isa_readw(a) readw(isa_port2addr(a))
-#define isa_readl(a) readl(isa_port2addr(a))
-#define isa_writeb(b,a) writeb(b,isa_port2addr(a))
-#define isa_writew(w,a) writew(w,isa_port2addr(a))
-#define isa_writel(l,a) writel(l,isa_port2addr(a))
+#define isa_readb(a) readb(ioport_map(a, 1))
+#define isa_readw(a) readw(ioport_map(a, 2))
+#define isa_readl(a) readl(ioport_map(a, 4))
+#define isa_writeb(b,a) writeb(b,ioport_map(a, 1))
+#define isa_writew(w,a) writew(w,ioport_map(a, 2))
+#define isa_writel(l,a) writel(l,ioport_map(a, 4))
+
#define isa_memset_io(a,b,c) \
- memset((void *)(isa_port2addr((unsigned long)a)),(b),(c))
+ memset((void *)(ioport_map((unsigned long)(a), 1)),(b),(c))
#define isa_memcpy_fromio(a,b,c) \
- memcpy((a),(void *)(isa_port2addr((unsigned long)(b))),(c))
+ memcpy((a),(void *)(ioport_map((unsigned long)(b), 1)),(c))
#define isa_memcpy_toio(a,b,c) \
- memcpy((void *)(isa_port2addr((unsigned long)(a))),(b),(c))
+ memcpy((void *)(ioport_map((unsigned long)(a), 1)),(b),(c))
/* We really want to try and get these to memcpy etc */
-extern void memcpy_fromio(void *, unsigned long, unsigned long);
-extern void memcpy_toio(unsigned long, const void *, unsigned long);
-extern void memset_io(unsigned long, int, unsigned long);
+extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long);
+extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
+extern void memset_io(volatile void __iomem *, int, unsigned long);
/* SuperH on-chip I/O functions */
-static __inline__ unsigned char ctrl_inb(unsigned long addr)
+static inline unsigned char ctrl_inb(unsigned long addr)
{
return *(volatile unsigned char*)addr;
}
-static __inline__ unsigned short ctrl_inw(unsigned long addr)
+static inline unsigned short ctrl_inw(unsigned long addr)
{
return *(volatile unsigned short*)addr;
}
-static __inline__ unsigned int ctrl_inl(unsigned long addr)
+static inline unsigned int ctrl_inl(unsigned long addr)
{
return *(volatile unsigned long*)addr;
}
-static __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
+static inline void ctrl_outb(unsigned char b, unsigned long addr)
{
*(volatile unsigned char*)addr = b;
}
-static __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
+static inline void ctrl_outw(unsigned short b, unsigned long addr)
{
*(volatile unsigned short*)addr = b;
}
-static __inline__ void ctrl_outl(unsigned int b, unsigned long addr)
+static inline void ctrl_outl(unsigned int b, unsigned long addr)
{
*(volatile unsigned long*)addr = b;
}
@@ -214,12 +230,12 @@ static __inline__ void ctrl_outl(unsigned int b, unsigned long addr)
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/SuperH mapping
*/
-static __inline__ unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void *address)
{
return PHYSADDR(address);
}
-static __inline__ void * phys_to_virt(unsigned long address)
+static inline void *phys_to_virt(unsigned long address)
{
return (void *)P1SEGADDR(address);
}
@@ -234,27 +250,60 @@ static __inline__ void * phys_to_virt(unsigned long address)
* differently. On the x86 architecture, we just read/write the
* memory location directly.
*
- * On SH, we have the whole physical address space mapped at all times
- * (as MIPS does), so "ioremap()" and "iounmap()" do not need to do
- * anything. (This isn't true for all machines but we still handle
- * these cases with wired TLB entries anyway ...)
+ * On SH, we traditionally have the whole physical address space mapped
+ * at all times (as MIPS does), so "ioremap()" and "iounmap()" do not
+ * need to do anything but place the address in the proper segment. This
+ * is true for P1 and P2 addresses, as well as some P3 ones. However,
+ * most of the P3 addresses and newer cores using extended addressing
+ * need to map through page tables, so the ioremap() implementation
+ * becomes a bit more complicated. See arch/sh/mm/ioremap.c for
+ * additional notes on this.
*
* We cheat a bit and always return uncachable areas until we've fixed
- * the drivers to handle caching properly.
+ * the drivers to handle caching properly.
*/
-static __inline__ void * ioremap(unsigned long offset, unsigned long size)
+#ifdef CONFIG_MMU
+void __iomem *__ioremap(unsigned long offset, unsigned long size,
+ unsigned long flags);
+void __iounmap(void __iomem *addr);
+#else
+#define __ioremap(offset, size, flags) ((void __iomem *)(offset))
+#define __iounmap(addr) do { } while (0)
+#endif /* CONFIG_MMU */
+
+static inline void __iomem *
+__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
{
- return __ioremap(offset, size);
+ unsigned long last_addr = offset + size - 1;
+
+ /*
+ * For P1 and P2 space this is trivial, as everything is already
+ * mapped. Uncached access for P1 addresses are done through P2.
+ * In the P3 case or for addresses outside of the 29-bit space,
+ * mapping must be done by the PMB or by using page tables.
+ */
+ if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) {
+ if (unlikely(flags & _PAGE_CACHABLE))
+ return (void __iomem *)P1SEGADDR(offset);
+
+ return (void __iomem *)P2SEGADDR(offset);
+ }
+
+ return __ioremap(offset, size, flags);
}
-static __inline__ void iounmap(void *addr)
-{
- return __iounmap(addr);
-}
-
-#define ioremap_nocache(off,size) ioremap(off,size)
-
-static __inline__ int check_signature(unsigned long io_addr,
+#define ioremap(offset, size) \
+ __ioremap_mode((offset), (size), 0)
+#define ioremap_nocache(offset, size) \
+ __ioremap_mode((offset), (size), 0)
+#define ioremap_cache(offset, size) \
+ __ioremap_mode((offset), (size), _PAGE_CACHABLE)
+#define p3_ioremap(offset, size, flags) \
+ __ioremap((offset), (size), (flags))
+#define iounmap(addr) \
+ __iounmap((addr))
+
+static inline int check_signature(char __iomem *io_addr,
const unsigned char *signature, int length)
{
int retval = 0;
diff --git a/include/asm-sh/io_generic.h b/include/asm-sh/io_generic.h
index be14587342f7..92fc6070d7b3 100644
--- a/include/asm-sh/io_generic.h
+++ b/include/asm-sh/io_generic.h
@@ -1,51 +1,49 @@
/*
- * include/asm-sh/io_generic.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Generic IO functions
+ * Trivial I/O routine definitions, intentionally meant to be included
+ * multiple times. Ugly I/O routine concatenation helpers taken from
+ * alpha. Must be included _before_ io.h to avoid preprocessor-induced
+ * routine mismatch.
*/
-
-#ifndef _ASM_SH_IO_GENERIC_H
-#define _ASM_SH_IO_GENERIC_H
-
-extern unsigned long generic_io_base;
-
-extern unsigned char generic_inb(unsigned long port);
-extern unsigned short generic_inw(unsigned long port);
-extern unsigned int generic_inl(unsigned long port);
-
-extern void generic_outb(unsigned char value, unsigned long port);
-extern void generic_outw(unsigned short value, unsigned long port);
-extern void generic_outl(unsigned int value, unsigned long port);
-
-extern unsigned char generic_inb_p(unsigned long port);
-extern unsigned short generic_inw_p(unsigned long port);
-extern unsigned int generic_inl_p(unsigned long port);
-extern void generic_outb_p(unsigned char value, unsigned long port);
-extern void generic_outw_p(unsigned short value, unsigned long port);
-extern void generic_outl_p(unsigned int value, unsigned long port);
-
-extern void generic_insb(unsigned long port, void *addr, unsigned long count);
-extern void generic_insw(unsigned long port, void *addr, unsigned long count);
-extern void generic_insl(unsigned long port, void *addr, unsigned long count);
-extern void generic_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void generic_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void generic_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char generic_readb(unsigned long addr);
-extern unsigned short generic_readw(unsigned long addr);
-extern unsigned int generic_readl(unsigned long addr);
-extern void generic_writeb(unsigned char b, unsigned long addr);
-extern void generic_writew(unsigned short b, unsigned long addr);
-extern void generic_writel(unsigned int b, unsigned long addr);
-
-extern void *generic_ioremap(unsigned long offset, unsigned long size);
-extern void generic_iounmap(void *addr);
-
-extern unsigned long generic_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_GENERIC_H */
+#define IO_CONCAT(a,b) _IO_CONCAT(a,b)
+#define _IO_CONCAT(a,b) a ## _ ## b
+
+#ifndef __IO_PREFIX
+#error "Don't include this header without a valid system prefix"
+#endif
+
+u8 IO_CONCAT(__IO_PREFIX,inb)(unsigned long);
+u16 IO_CONCAT(__IO_PREFIX,inw)(unsigned long);
+u32 IO_CONCAT(__IO_PREFIX,inl)(unsigned long);
+
+void IO_CONCAT(__IO_PREFIX,outb)(u8, unsigned long);
+void IO_CONCAT(__IO_PREFIX,outw)(u16, unsigned long);
+void IO_CONCAT(__IO_PREFIX,outl)(u32, unsigned long);
+
+u8 IO_CONCAT(__IO_PREFIX,inb_p)(unsigned long);
+u16 IO_CONCAT(__IO_PREFIX,inw_p)(unsigned long);
+u32 IO_CONCAT(__IO_PREFIX,inl_p)(unsigned long);
+void IO_CONCAT(__IO_PREFIX,outb_p)(u8, unsigned long);
+void IO_CONCAT(__IO_PREFIX,outw_p)(u16, unsigned long);
+void IO_CONCAT(__IO_PREFIX,outl_p)(u32, unsigned long);
+
+void IO_CONCAT(__IO_PREFIX,insb)(unsigned long, void *dst, unsigned long count);
+void IO_CONCAT(__IO_PREFIX,insw)(unsigned long, void *dst, unsigned long count);
+void IO_CONCAT(__IO_PREFIX,insl)(unsigned long, void *dst, unsigned long count);
+void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long count);
+void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count);
+void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count);
+
+u8 IO_CONCAT(__IO_PREFIX,readb)(void __iomem *);
+u16 IO_CONCAT(__IO_PREFIX,readw)(void __iomem *);
+u32 IO_CONCAT(__IO_PREFIX,readl)(void __iomem *);
+void IO_CONCAT(__IO_PREFIX,writeb)(u8, void __iomem *);
+void IO_CONCAT(__IO_PREFIX,writew)(u16, void __iomem *);
+void IO_CONCAT(__IO_PREFIX,writel)(u32, void __iomem *);
+
+void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size);
+void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr);
+
+void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size);
+void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr);
+
+#undef __IO_PREFIX
diff --git a/include/asm-sh/ioctl.h b/include/asm-sh/ioctl.h
index 524700e84acd..b279fe06dfe5 100644
--- a/include/asm-sh/ioctl.h
+++ b/include/asm-sh/ioctl.h
@@ -1,75 +1 @@
-/* $Id: ioctl.h,v 1.1.1.1 2001/10/15 20:45:09 mrbrown Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef __ASM_SH_IOCTL_H
-#define __ASM_SH_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* __ASM_SH_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-sh/irq-sh7780.h b/include/asm-sh/irq-sh7780.h
new file mode 100644
index 000000000000..8c8ca1281084
--- /dev/null
+++ b/include/asm-sh/irq-sh7780.h
@@ -0,0 +1,349 @@
+#ifndef __ASM_SH_IRQ_SH7780_H
+#define __ASM_SH_IRQ_SH7780_H
+
+/*
+ * linux/include/asm-sh/irq-sh7780.h
+ *
+ * Copyright (C) 2004 Takashi SHUDO <shudo@hitachi-ul.co.jp>
+ */
+
+#ifdef CONFIG_IDE
+# ifndef IRQ_CFCARD
+# define IRQ_CFCARD 14
+# endif
+# ifndef IRQ_PCMCIA
+# define IRQ_PCMCIA 15
+# endif
+#endif
+
+#define INTC_BASE 0xffd00000
+#define INTC_ICR0 (INTC_BASE+0x0)
+#define INTC_ICR1 (INTC_BASE+0x1c)
+#define INTC_INTPRI (INTC_BASE+0x10)
+#define INTC_INTREQ (INTC_BASE+0x24)
+#define INTC_INTMSK0 (INTC_BASE+0x44)
+#define INTC_INTMSK1 (INTC_BASE+0x48)
+#define INTC_INTMSK2 (INTC_BASE+0x40080)
+#define INTC_INTMSKCLR0 (INTC_BASE+0x64)
+#define INTC_INTMSKCLR1 (INTC_BASE+0x68)
+#define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
+#define INTC_NMIFCR (INTC_BASE+0xc0)
+#define INTC_USERIMASK (INTC_BASE+0x30000)
+
+#define INTC_INT2PRI0 (INTC_BASE+0x40000)
+#define INTC_INT2PRI1 (INTC_BASE+0x40004)
+#define INTC_INT2PRI2 (INTC_BASE+0x40008)
+#define INTC_INT2PRI3 (INTC_BASE+0x4000c)
+#define INTC_INT2PRI4 (INTC_BASE+0x40010)
+#define INTC_INT2PRI5 (INTC_BASE+0x40014)
+#define INTC_INT2PRI6 (INTC_BASE+0x40018)
+#define INTC_INT2PRI7 (INTC_BASE+0x4001c)
+#define INTC_INT2A0 (INTC_BASE+0x40030)
+#define INTC_INT2A1 (INTC_BASE+0x40034)
+#define INTC_INT2MSKR (INTC_BASE+0x40038)
+#define INTC_INT2MSKCR (INTC_BASE+0x4003c)
+#define INTC_INT2B0 (INTC_BASE+0x40040)
+#define INTC_INT2B1 (INTC_BASE+0x40044)
+#define INTC_INT2B2 (INTC_BASE+0x40048)
+#define INTC_INT2B3 (INTC_BASE+0x4004c)
+#define INTC_INT2B4 (INTC_BASE+0x40050)
+#define INTC_INT2B5 (INTC_BASE+0x40054)
+#define INTC_INT2B6 (INTC_BASE+0x40058)
+#define INTC_INT2B7 (INTC_BASE+0x4005c)
+#define INTC_INT2GPIC (INTC_BASE+0x40090)
+/*
+ NOTE:
+ *_IRQ = (INTEVT2 - 0x200)/0x20
+*/
+/* IRQ 0-7 line external int*/
+#define IRQ0_IRQ 2
+#define IRQ0_IPR_ADDR INTC_INTPRI
+#define IRQ0_IPR_POS 7
+#define IRQ0_PRIORITY 2
+
+#define IRQ1_IRQ 4
+#define IRQ1_IPR_ADDR INTC_INTPRI
+#define IRQ1_IPR_POS 6
+#define IRQ1_PRIORITY 2
+
+#define IRQ2_IRQ 6
+#define IRQ2_IPR_ADDR INTC_INTPRI
+#define IRQ2_IPR_POS 5
+#define IRQ2_PRIORITY 2
+
+#define IRQ3_IRQ 8
+#define IRQ3_IPR_ADDR INTC_INTPRI
+#define IRQ3_IPR_POS 4
+#define IRQ3_PRIORITY 2
+
+#define IRQ4_IRQ 10
+#define IRQ4_IPR_ADDR INTC_INTPRI
+#define IRQ4_IPR_POS 3
+#define IRQ4_PRIORITY 2
+
+#define IRQ5_IRQ 12
+#define IRQ5_IPR_ADDR INTC_INTPRI
+#define IRQ5_IPR_POS 2
+#define IRQ5_PRIORITY 2
+
+#define IRQ6_IRQ 14
+#define IRQ6_IPR_ADDR INTC_INTPRI
+#define IRQ6_IPR_POS 1
+#define IRQ6_PRIORITY 2
+
+#define IRQ7_IRQ 0
+#define IRQ7_IPR_ADDR INTC_INTPRI
+#define IRQ7_IPR_POS 0
+#define IRQ7_PRIORITY 2
+
+/* TMU */
+/* ch0 */
+#define TMU_IRQ 28
+#define TMU_IPR_ADDR INTC_INT2PRI0
+#define TMU_IPR_POS 3
+#define TMU_PRIORITY 2
+
+#define TIMER_IRQ 28
+#define TIMER_IPR_ADDR INTC_INT2PRI0
+#define TIMER_IPR_POS 3
+#define TIMER_PRIORITY 2
+
+/* ch 1*/
+#define TMU_CH1_IRQ 29
+#define TMU_CH1_IPR_ADDR INTC_INT2PRI0
+#define TMU_CH1_IPR_POS 2
+#define TMU_CH1_PRIORITY 2
+
+#define TIMER1_IRQ 29
+#define TIMER1_IPR_ADDR INTC_INT2PRI0
+#define TIMER1_IPR_POS 2
+#define TIMER1_PRIORITY 2
+
+/* ch 2*/
+#define TMU_CH2_IRQ 30
+#define TMU_CH2_IPR_ADDR INTC_INT2PRI0
+#define TMU_CH2_IPR_POS 1
+#define TMU_CH2_PRIORITY 2
+/* ch 2 Input capture */
+#define TMU_CH2IC_IRQ 31
+#define TMU_CH2IC_IPR_ADDR INTC_INT2PRI0
+#define TMU_CH2IC_IPR_POS 0
+#define TMU_CH2IC_PRIORITY 2
+/* ch 3 */
+#define TMU_CH3_IRQ 96
+#define TMU_CH3_IPR_ADDR INTC_INT2PRI1
+#define TMU_CH3_IPR_POS 3
+#define TMU_CH3_PRIORITY 2
+/* ch 4 */
+#define TMU_CH4_IRQ 97
+#define TMU_CH4_IPR_ADDR INTC_INT2PRI1
+#define TMU_CH4_IPR_POS 2
+#define TMU_CH4_PRIORITY 2
+/* ch 5*/
+#define TMU_CH5_IRQ 98
+#define TMU_CH5_IPR_ADDR INTC_INT2PRI1
+#define TMU_CH5_IPR_POS 1
+#define TMU_CH5_PRIORITY 2
+
+#define RTC_IRQ 22
+#define RTC_IPR_ADDR INTC_INT2PRI1
+#define RTC_IPR_POS 0
+#define RTC_PRIORITY TIMER_PRIORITY
+
+/* SCIF0 */
+#define SCIF0_ERI_IRQ 40
+#define SCIF0_RXI_IRQ 41
+#define SCIF0_BRI_IRQ 42
+#define SCIF0_TXI_IRQ 43
+#define SCIF0_IPR_ADDR INTC_INT2PRI2
+#define SCIF0_IPR_POS 3
+#define SCIF0_PRIORITY 3
+
+/* SCIF1 */
+#define SCIF1_ERI_IRQ 76
+#define SCIF1_RXI_IRQ 77
+#define SCIF1_BRI_IRQ 78
+#define SCIF1_TXI_IRQ 79
+#define SCIF1_IPR_ADDR INTC_INT2PRI2
+#define SCIF1_IPR_POS 2
+#define SCIF1_PRIORITY 3
+
+#define WDT_IRQ 27
+#define WDT_IPR_ADDR INTC_INT2PRI2
+#define WDT_IPR_POS 1
+#define WDT_PRIORITY 2
+
+/* DMAC(0) */
+#define DMINT0_IRQ 34
+#define DMINT1_IRQ 35
+#define DMINT2_IRQ 36
+#define DMINT3_IRQ 37
+#define DMINT4_IRQ 44
+#define DMINT5_IRQ 45
+#define DMINT6_IRQ 46
+#define DMINT7_IRQ 47
+#define DMAE_IRQ 38
+#define DMA0_IPR_ADDR INTC_INT2PRI3
+#define DMA0_IPR_POS 2
+#define DMA0_PRIORITY 7
+
+/* DMAC(1) */
+#define DMINT8_IRQ 92
+#define DMINT9_IRQ 93
+#define DMINT10_IRQ 94
+#define DMINT11_IRQ 95
+#define DMA1_IPR_ADDR INTC_INT2PRI3
+#define DMA1_IPR_POS 1
+#define DMA1_PRIORITY 7
+
+#define DMTE0_IRQ DMINT0_IRQ
+#define DMTE4_IRQ DMINT4_IRQ
+#define DMA_IPR_ADDR DMA0_IPR_ADDR
+#define DMA_IPR_POS DMA0_IPR_POS
+#define DMA_PRIORITY DMA0_PRIORITY
+
+/* CMT */
+#define CMT_IRQ 56
+#define CMT_IPR_ADDR INTC_INT2PRI4
+#define CMT_IPR_POS 3
+#define CMT_PRIORITY 0
+
+/* HAC */
+#define HAC_IRQ 60
+#define HAC_IPR_ADDR INTC_INT2PRI4
+#define HAC_IPR_POS 2
+#define CMT_PRIORITY 0
+
+/* PCIC(0) */
+#define PCIC0_IRQ 64
+#define PCIC0_IPR_ADDR INTC_INT2PRI4
+#define PCIC0_IPR_POS 1
+#define PCIC0_PRIORITY 2
+
+/* PCIC(1) */
+#define PCIC1_IRQ 65
+#define PCIC1_IPR_ADDR INTC_INT2PRI4
+#define PCIC1_IPR_POS 0
+#define PCIC1_PRIORITY 2
+
+/* PCIC(2) */
+#define PCIC2_IRQ 66
+#define PCIC2_IPR_ADDR INTC_INT2PRI5
+#define PCIC2_IPR_POS 3
+#define PCIC2_PRIORITY 2
+
+/* PCIC(3) */
+#define PCIC3_IRQ 67
+#define PCIC3_IPR_ADDR INTC_INT2PRI5
+#define PCIC3_IPR_POS 2
+#define PCIC3_PRIORITY 2
+
+/* PCIC(4) */
+#define PCIC4_IRQ 68
+#define PCIC4_IPR_ADDR INTC_INT2PRI5
+#define PCIC4_IPR_POS 1
+#define PCIC4_PRIORITY 2
+
+/* PCIC(5) */
+#define PCICERR_IRQ 69
+#define PCICPWD3_IRQ 70
+#define PCICPWD2_IRQ 71
+#define PCICPWD1_IRQ 72
+#define PCICPWD0_IRQ 73
+#define PCIC5_IPR_ADDR INTC_INT2PRI5
+#define PCIC5_IPR_POS 0
+#define PCIC5_PRIORITY 2
+
+/* SIOF */
+#define SIOF_IRQ 80
+#define SIOF_IPR_ADDR INTC_INT2PRI6
+#define SIOF_IPR_POS 3
+#define SIOF_PRIORITY 3
+
+/* HSPI */
+#define HSPI_IRQ 84
+#define HSPI_IPR_ADDR INTC_INT2PRI6
+#define HSPI_IPR_POS 2
+#define HSPI_PRIORITY 3
+
+/* MMCIF */
+#define MMCIF_FSTAT_IRQ 88
+#define MMCIF_TRAN_IRQ 89
+#define MMCIF_ERR_IRQ 90
+#define MMCIF_FRDY_IRQ 91
+#define MMCIF_IPR_ADDR INTC_INT2PRI6
+#define MMCIF_IPR_POS 1
+#define HSPI_PRIORITY 3
+
+/* SSI */
+#define SSI_IRQ 100
+#define SSI_IPR_ADDR INTC_INT2PRI6
+#define SSI_IPR_POS 0
+#define SSI_PRIORITY 3
+
+/* FLCTL */
+#define FLCTL_FLSTE_IRQ 104
+#define FLCTL_FLTEND_IRQ 105
+#define FLCTL_FLTRQ0_IRQ 106
+#define FLCTL_FLTRQ1_IRQ 107
+#define FLCTL_IPR_ADDR INTC_INT2PRI7
+#define FLCTL_IPR_POS 3
+#define FLCTL_PRIORITY 3
+
+/* GPIO */
+#define GPIO0_IRQ 108
+#define GPIO1_IRQ 109
+#define GPIO2_IRQ 110
+#define GPIO3_IRQ 111
+#define GPIO_IPR_ADDR INTC_INT2PRI7
+#define GPIO_IPR_POS 2
+#define GPIO_PRIORITY 3
+
+/* ONCHIP_NR_IRQS */
+#define NR_IRQS 150 /* 111 + 16 */
+
+/* In a generic kernel, NR_IRQS is an upper bound, and we should use
+ * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
+ */
+#define ACTUAL_NR_IRQS NR_IRQS
+
+extern void disable_irq(unsigned int);
+extern void disable_irq_nosync(unsigned int);
+extern void enable_irq(unsigned int);
+
+/*
+ * Simple Mask Register Support
+ */
+extern void make_maskreg_irq(unsigned int irq);
+extern unsigned short *irq_mask_register;
+
+/*
+ * Function for "on chip support modules".
+ */
+extern void make_imask_irq(unsigned int irq);
+
+#define INTC_TMU0_MSK 0
+#define INTC_TMU3_MSK 1
+#define INTC_RTC_MSK 2
+#define INTC_SCIF0_MSK 3
+#define INTC_SCIF1_MSK 4
+#define INTC_WDT_MSK 5
+#define INTC_HUID_MSK 7
+#define INTC_DMAC0_MSK 8
+#define INTC_DMAC1_MSK 9
+#define INTC_CMT_MSK 12
+#define INTC_HAC_MSK 13
+#define INTC_PCIC0_MSK 14
+#define INTC_PCIC1_MSK 15
+#define INTC_PCIC2_MSK 16
+#define INTC_PCIC3_MSK 17
+#define INTC_PCIC4_MSK 18
+#define INTC_PCIC5_MSK 19
+#define INTC_SIOF_MSK 20
+#define INTC_HSPI_MSK 21
+#define INTC_MMCIF_MSK 22
+#define INTC_SSI_MSK 23
+#define INTC_FLCTL_MSK 24
+#define INTC_GPIO_MSK 25
+
+#endif /* __ASM_SH_IRQ_SH7780_H */
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 614a8c13b721..060ec3c27207 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -15,13 +15,20 @@
#include <asm/machvec.h>
#include <asm/ptrace.h> /* for pt_regs */
-#if defined(CONFIG_SH_HP600) || \
+#if defined(CONFIG_SH_HP6XX) || \
defined(CONFIG_SH_RTS7751R2D) || \
defined(CONFIG_SH_HS7751RVOIP) || \
- defined(CONFIG_SH_SH03)
+ defined(CONFIG_SH_HS7751RVOIP) || \
+ defined(CONFIG_SH_SH03) || \
+ defined(CONFIG_SH_R7780RP) || \
+ defined(CONFIG_SH_LANDISK)
#include <asm/mach/ide.h>
#endif
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
+
+#define INTC_DMAC0_MSK 0
+
#if defined(CONFIG_CPU_SH3)
#define INTC_IPRA 0xfffffee2UL
#define INTC_IPRB 0xfffffee4UL
@@ -235,8 +242,9 @@
#define SCIF1_IPR_ADDR INTC_IPRB
#define SCIF1_IPR_POS 1
#define SCIF1_PRIORITY 3
-#endif
-#endif
+#endif /* ST40STB1 */
+
+#endif /* 775x / SH4-202 / ST40STB1 */
/* NR_IRQS is made from three components:
* 1. ONCHIP_NR_IRQS - number of IRLS + on-chip peripherial modules
@@ -245,37 +253,35 @@
*/
/* 1. ONCHIP_NR_IRQS */
-#ifdef CONFIG_SH_GENERIC
+#if defined(CONFIG_CPU_SUBTYPE_SH7604)
+# define ONCHIP_NR_IRQS 24 // Actually 21
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707)
+# define ONCHIP_NR_IRQS 64
+# define PINT_NR_IRQS 16
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+# define ONCHIP_NR_IRQS 32
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7705)
+# define ONCHIP_NR_IRQS 64 // Actually 61
+# define PINT_NR_IRQS 16
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750)
+# define ONCHIP_NR_IRQS 48 // Actually 44
+#elif defined(CONFIG_CPU_SUBTYPE_SH7751)
+# define ONCHIP_NR_IRQS 72
+#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
+# define ONCHIP_NR_IRQS 112 /* XXX */
+#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
+# define ONCHIP_NR_IRQS 72
+#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+# define ONCHIP_NR_IRQS 144
+#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
+# define ONCHIP_NR_IRQS 109
+#elif defined(CONFIG_SH_UNKNOWN) /* Most be last */
# define ONCHIP_NR_IRQS 144
-#else
-# if defined(CONFIG_CPU_SUBTYPE_SH7604)
-# define ONCHIP_NR_IRQS 24 // Actually 21
-# elif defined(CONFIG_CPU_SUBTYPE_SH7707)
-# define ONCHIP_NR_IRQS 64
-# define PINT_NR_IRQS 16
-# elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-# define ONCHIP_NR_IRQS 32
-# elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \
- defined(CONFIG_CPU_SUBTYPE_SH7705)
-# define ONCHIP_NR_IRQS 64 // Actually 61
-# define PINT_NR_IRQS 16
-# elif defined(CONFIG_CPU_SUBTYPE_SH7750)
-# define ONCHIP_NR_IRQS 48 // Actually 44
-# elif defined(CONFIG_CPU_SUBTYPE_SH7751)
-# define ONCHIP_NR_IRQS 72
-# elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-# define ONCHIP_NR_IRQS 110
-# elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-# define ONCHIP_NR_IRQS 72
-# elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-# define ONCHIP_NR_IRQS 144
-# elif defined(CONFIG_CPU_SUBTYPE_SH7300)
-# define ONCHIP_NR_IRQS 109
-# endif
#endif
/* 2. PINT_NR_IRQS */
-#ifdef CONFIG_SH_GENERIC
+#ifdef CONFIG_SH_UNKNOWN
# define PINT_NR_IRQS 16
#else
# ifndef PINT_NR_IRQS
@@ -288,22 +294,22 @@
#endif
/* 3. OFFCHIP_NR_IRQS */
-#ifdef CONFIG_SH_GENERIC
+#if defined(CONFIG_HD64461)
+# define OFFCHIP_NR_IRQS 18
+#elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */
+# define OFFCHIP_NR_IRQS 48
+#elif defined(CONFIG_HD64465)
# define OFFCHIP_NR_IRQS 16
+#elif defined (CONFIG_SH_EC3104)
+# define OFFCHIP_NR_IRQS 16
+#elif defined (CONFIG_SH_DREAMCAST)
+# define OFFCHIP_NR_IRQS 96
+#elif defined (CONFIG_SH_TITAN)
+# define OFFCHIP_NR_IRQS 4
+#elif defined(CONFIG_SH_UNKNOWN)
+# define OFFCHIP_NR_IRQS 16 /* Must also be last */
#else
-# if defined(CONFIG_HD64461)
-# define OFFCHIP_NR_IRQS 18
-# elif defined (CONFIG_SH_BIGSUR) /* must be before CONFIG_HD64465 */
-# define OFFCHIP_NR_IRQS 48
-# elif defined(CONFIG_HD64465)
-# define OFFCHIP_NR_IRQS 16
-# elif defined (CONFIG_SH_EC3104)
-# define OFFCHIP_NR_IRQS 16
-# elif defined (CONFIG_SH_DREAMCAST)
-# define OFFCHIP_NR_IRQS 96
-# else
-# define OFFCHIP_NR_IRQS 0
-# endif
+# define OFFCHIP_NR_IRQS 0
#endif
#if OFFCHIP_NR_IRQS > 0
@@ -313,16 +319,6 @@
/* NR_IRQS. 1+2+3 */
#define NR_IRQS (ONCHIP_NR_IRQS + PINT_NR_IRQS + OFFCHIP_NR_IRQS)
-/* In a generic kernel, NR_IRQS is an upper bound, and we should use
- * ACTUAL_NR_IRQS (which uses the machine vector) to get the correct value.
- */
-#ifdef CONFIG_SH_GENERIC
-# define ACTUAL_NR_IRQS (sh_mv.mv_nr_irqs)
-#else
-# define ACTUAL_NR_IRQS NR_IRQS
-#endif
-
-
extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
@@ -542,9 +538,6 @@ extern int ipr_irq_demux(int irq);
extern int ipr_irq_demux(int irq);
#define __irq_demux(irq) ipr_irq_demux(irq)
-
-#else
-#define __irq_demux(irq) irq
#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
#if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \
@@ -557,18 +550,35 @@ extern int ipr_irq_demux(int irq);
#define INTC_ICR_IRLM (1<<7)
#endif
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#else
+#include <asm/irq-sh7780.h>
+#endif
+/* SH with INTC2-style interrupts */
+#ifdef CONFIG_CPU_HAS_INTC2_IRQ
+#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+#define INTC2_BASE 0xfe080000
#define INTC2_FIRST_IRQ 64
-#define NR_INTC2_IRQS 25
-
+#define INTC2_INTREQ_OFFSET 0x20
+#define INTC2_INTMSK_OFFSET 0x40
+#define INTC2_INTMSKCLR_OFFSET 0x60
+#define NR_INTC2_IRQS 25
+#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
#define INTC2_BASE 0xfe080000
-#define INTC2_INTC2MODE (INTC2_BASE+0x80)
-
-#define INTC2_INTPRI_OFFSET 0x00
+#define INTC2_FIRST_IRQ 48 /* INTEVT 0x800 */
#define INTC2_INTREQ_OFFSET 0x20
#define INTC2_INTMSK_OFFSET 0x40
#define INTC2_INTMSKCLR_OFFSET 0x60
+#define NR_INTC2_IRQS 64
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define INTC2_BASE 0xffd40000
+#define INTC2_FIRST_IRQ 22
+#define INTC2_INTMSK_OFFSET (0x38)
+#define INTC2_INTMSKCLR_OFFSET (0x3c)
+#define NR_INTC2_IRQS 60
+#endif
+
+#define INTC2_INTPRI_OFFSET 0x00
void make_intc2_irq(unsigned int irq,
unsigned int ipr_offset, unsigned int ipr_shift,
@@ -577,13 +587,16 @@ void make_intc2_irq(unsigned int irq,
void init_IRQ_intc2(void);
void intc2_add_clear_irq(int irq, int (*fn)(int));
-#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
+#endif
static inline int generic_irq_demux(int irq)
{
return irq;
}
+#ifndef __irq_demux
+#define __irq_demux(irq) (irq)
+#endif
#define irq_canonicalize(irq) (irq)
#define irq_demux(irq) __irq_demux(sh_mv.mv_irq_demux(irq))
diff --git a/include/asm-sh/kexec.h b/include/asm-sh/kexec.h
new file mode 100644
index 000000000000..9dfe59f6fcb5
--- /dev/null
+++ b/include/asm-sh/kexec.h
@@ -0,0 +1,33 @@
+#ifndef _SH_KEXEC_H
+#define _SH_KEXEC_H
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_SH
+
+#ifndef __ASSEMBLY__
+
+extern void machine_shutdown(void);
+extern void *crash_notes;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _SH_KEXEC_H */
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 3f18aa180516..550c50a7359e 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -18,44 +18,37 @@
#include <asm/machvec_init.h>
struct device;
-struct timeval;
-struct sh_machine_vector
-{
+struct sh_machine_vector {
int mv_nr_irqs;
- unsigned char (*mv_inb)(unsigned long);
- unsigned short (*mv_inw)(unsigned long);
- unsigned int (*mv_inl)(unsigned long);
- void (*mv_outb)(unsigned char, unsigned long);
- void (*mv_outw)(unsigned short, unsigned long);
- void (*mv_outl)(unsigned int, unsigned long);
-
- unsigned char (*mv_inb_p)(unsigned long);
- unsigned short (*mv_inw_p)(unsigned long);
- unsigned int (*mv_inl_p)(unsigned long);
- void (*mv_outb_p)(unsigned char, unsigned long);
- void (*mv_outw_p)(unsigned short, unsigned long);
- void (*mv_outl_p)(unsigned int, unsigned long);
-
- void (*mv_insb)(unsigned long port, void *addr, unsigned long count);
- void (*mv_insw)(unsigned long port, void *addr, unsigned long count);
- void (*mv_insl)(unsigned long port, void *addr, unsigned long count);
- void (*mv_outsb)(unsigned long port, const void *addr, unsigned long count);
- void (*mv_outsw)(unsigned long port, const void *addr, unsigned long count);
- void (*mv_outsl)(unsigned long port, const void *addr, unsigned long count);
-
- unsigned char (*mv_readb)(unsigned long);
- unsigned short (*mv_readw)(unsigned long);
- unsigned int (*mv_readl)(unsigned long);
- void (*mv_writeb)(unsigned char, unsigned long);
- void (*mv_writew)(unsigned short, unsigned long);
- void (*mv_writel)(unsigned int, unsigned long);
-
- void* (*mv_ioremap)(unsigned long offset, unsigned long size);
- void (*mv_iounmap)(void *addr);
-
- unsigned long (*mv_isa_port2addr)(unsigned long offset);
+ u8 (*mv_inb)(unsigned long);
+ u16 (*mv_inw)(unsigned long);
+ u32 (*mv_inl)(unsigned long);
+ void (*mv_outb)(u8, unsigned long);
+ void (*mv_outw)(u16, unsigned long);
+ void (*mv_outl)(u32, unsigned long);
+
+ u8 (*mv_inb_p)(unsigned long);
+ u16 (*mv_inw_p)(unsigned long);
+ u32 (*mv_inl_p)(unsigned long);
+ void (*mv_outb_p)(u8, unsigned long);
+ void (*mv_outw_p)(u16, unsigned long);
+ void (*mv_outl_p)(u32, unsigned long);
+
+ void (*mv_insb)(unsigned long, void *dst, unsigned long count);
+ void (*mv_insw)(unsigned long, void *dst, unsigned long count);
+ void (*mv_insl)(unsigned long, void *dst, unsigned long count);
+ void (*mv_outsb)(unsigned long, const void *src, unsigned long count);
+ void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
+ void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
+
+ u8 (*mv_readb)(void __iomem *);
+ u16 (*mv_readw)(void __iomem *);
+ u32 (*mv_readl)(void __iomem *);
+ void (*mv_writeb)(u8, void __iomem *);
+ void (*mv_writew)(u16, void __iomem *);
+ void (*mv_writel)(u32, void __iomem *);
int (*mv_irq_demux)(int irq);
@@ -66,6 +59,9 @@ struct sh_machine_vector
void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, gfp_t);
int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
+
+ void __iomem *(*mv_ioport_map)(unsigned long port, unsigned int size);
+ void (*mv_ioport_unmap)(void __iomem *);
};
extern struct sh_machine_vector sh_mv;
diff --git a/include/asm-sh/mman.h b/include/asm-sh/mman.h
index 3ebab5f79db7..693bd55a3710 100644
--- a/include/asm-sh/mman.h
+++ b/include/asm-sh/mman.h
@@ -35,6 +35,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-sh/mutex.h b/include/asm-sh/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-sh/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
index 0f75e16a7415..792fc35bd624 100644
--- a/include/asm-sh/ptrace.h
+++ b/include/asm-sh/ptrace.h
@@ -91,6 +91,16 @@ struct pt_dspregs {
#define instruction_pointer(regs) ((regs)->pc)
extern void show_regs(struct pt_regs *);
+#ifdef CONFIG_SH_DSP
+#define task_pt_regs(task) \
+ ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
+ - sizeof(struct pt_dspregs) - sizeof(unsigned long)) - 1)
+#else
+#define task_pt_regs(task) \
+ ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
+ - sizeof(unsigned long)) - 1)
+#endif
+
static inline unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index 28a3c2d8bcd7..bb0330499bdf 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -57,6 +57,16 @@
last = __last; \
} while (0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
#define nop() __asm__ __volatile__ ("nop")
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 46080cefaff8..85f0c11b4319 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -60,8 +60,6 @@ static inline struct thread_info *current_thread_info(void)
#define THREAD_SIZE (2*PAGE_SIZE)
#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#else /* !__ASSEMBLY__ */
diff --git a/include/asm-sh/timer.h b/include/asm-sh/timer.h
new file mode 100644
index 000000000000..dd6579c0b04c
--- /dev/null
+++ b/include/asm-sh/timer.h
@@ -0,0 +1,42 @@
+#ifndef __ASM_SH_TIMER_H
+#define __ASM_SH_TIMER_H
+
+#include <linux/sysdev.h>
+#include <asm/cpu/timer.h>
+
+struct sys_timer_ops {
+ int (*init)(void);
+ unsigned long (*get_offset)(void);
+ unsigned long (*get_frequency)(void);
+};
+
+struct sys_timer {
+ const char *name;
+
+ struct sys_device dev;
+ struct sys_timer_ops *ops;
+};
+
+#define TICK_SIZE (tick_nsec / 1000)
+
+extern struct sys_timer tmu_timer;
+extern struct sys_timer *sys_timer;
+
+static inline unsigned long get_timer_offset(void)
+{
+ return sys_timer->ops->get_offset();
+}
+
+static inline unsigned long get_timer_frequency(void)
+{
+ return sys_timer->ops->get_frequency();
+}
+
+/* arch/sh/kernel/timers/timer.c */
+struct sys_timer *get_sys_timer(void);
+
+/* arch/sh/kernel/time.c */
+void handle_timer_tick(struct pt_regs *);
+
+#endif /* __ASM_SH_TIMER_H */
+
diff --git a/include/asm-sh64/atomic.h b/include/asm-sh64/atomic.h
index 927a2bc27b30..28f2ea9b567b 100644
--- a/include/asm-sh64/atomic.h
+++ b/include/asm-sh64/atomic.h
@@ -113,6 +113,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -152,4 +154,5 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __ASM_SH64_ATOMIC_H */
diff --git a/include/asm-sh64/bitops.h b/include/asm-sh64/bitops.h
index e1ff63e09227..ce9c3ad45fe0 100644
--- a/include/asm-sh64/bitops.h
+++ b/include/asm-sh64/bitops.h
@@ -510,6 +510,7 @@ found_middle:
#define ffs(x) generic_ffs(x)
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#endif /* __KERNEL__ */
diff --git a/include/asm-sh64/cache.h b/include/asm-sh64/cache.h
index f54e85e8a470..a4f36f0036e1 100644
--- a/include/asm-sh64/cache.h
+++ b/include/asm-sh64/cache.h
@@ -20,8 +20,6 @@
#define L1_CACHE_ALIGN_MASK (~(L1_CACHE_BYTES - 1))
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES - 1)) & L1_CACHE_ALIGN_MASK)
#define L1_CACHE_SIZE_BYTES (L1_CACHE_BYTES << 10)
-/* Largest L1 which this arch supports */
-#define L1_CACHE_SHIFT_MAX 5
#ifdef MODULE
#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
diff --git a/include/asm-sh64/futex.h b/include/asm-sh64/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-sh64/futex.h
+++ b/include/asm-sh64/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-sh64/io.h b/include/asm-sh64/io.h
index cfafaa73b2b0..dee4f77929a4 100644
--- a/include/asm-sh64/io.h
+++ b/include/asm-sh64/io.h
@@ -143,12 +143,12 @@ extern unsigned long pciio_virt;
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/SuperH mapping
*/
-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);
}
@@ -156,12 +156,12 @@ extern __inline__ void * phys_to_virt(unsigned long address)
extern void * __ioremap(unsigned long phys_addr, unsigned long size,
unsigned long flags);
-extern __inline__ void * ioremap(unsigned long phys_addr, unsigned long size)
+static inline void * ioremap(unsigned long phys_addr, unsigned long size)
{
return __ioremap(phys_addr, size, 1);
}
-extern __inline__ void * ioremap_nocache (unsigned long phys_addr, unsigned long size)
+static inline void * ioremap_nocache (unsigned long phys_addr, unsigned long size)
{
return __ioremap(phys_addr, size, 0);
}
diff --git a/include/asm-sh64/ioctl.h b/include/asm-sh64/ioctl.h
index c089a6fb78e0..b279fe06dfe5 100644
--- a/include/asm-sh64/ioctl.h
+++ b/include/asm-sh64/ioctl.h
@@ -1,83 +1 @@
-#ifndef __ASM_SH64_IOCTL_H
-#define __ASM_SH64_IOCTL_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.
- *
- * include/asm-sh64/ioctl.h
- *
- * Copyright (C) 2000, 2001 Paolo Alberelli
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- *
- */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* __ASM_SH64_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-sh64/mmu_context.h b/include/asm-sh64/mmu_context.h
index f062e1513272..991cfda4cdf6 100644
--- a/include/asm-sh64/mmu_context.h
+++ b/include/asm-sh64/mmu_context.h
@@ -50,7 +50,7 @@ extern pgd_t *mmu_pdtp_cache;
*/
#define MMU_VPN_MASK 0xfffff000
-extern __inline__ void
+static inline void
get_new_mmu_context(struct mm_struct *mm)
{
extern void flush_tlb_all(void);
diff --git a/include/asm-sh64/mutex.h b/include/asm-sh64/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-sh64/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-sh64/pgalloc.h b/include/asm-sh64/pgalloc.h
index b25f5df5535c..678251ac1db8 100644
--- a/include/asm-sh64/pgalloc.h
+++ b/include/asm-sh64/pgalloc.h
@@ -38,14 +38,14 @@ static inline void pgd_init(unsigned long page)
* if any.
*/
-extern __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
{
unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
pgd_t *ret = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
return ret;
}
-extern __inline__ pgd_t *get_pgd_fast(void)
+static inline pgd_t *get_pgd_fast(void)
{
unsigned long *ret;
@@ -62,14 +62,14 @@ extern __inline__ pgd_t *get_pgd_fast(void)
return (pgd_t *)ret;
}
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+static inline void free_pgd_fast(pgd_t *pgd)
{
*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
pgd_quicklist = (unsigned long *) pgd;
pgtable_cache_size++;
}
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
+static inline void free_pgd_slow(pgd_t *pgd)
{
kfree((void *)pgd);
}
@@ -77,7 +77,7 @@ extern __inline__ void free_pgd_slow(pgd_t *pgd)
extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
-extern __inline__ pte_t *get_pte_fast(void)
+static inline pte_t *get_pte_fast(void)
{
unsigned long *ret;
@@ -89,7 +89,7 @@ extern __inline__ pte_t *get_pte_fast(void)
return (pte_t *)ret;
}
-extern __inline__ void free_pte_fast(pte_t *pte)
+static inline void free_pte_fast(pte_t *pte)
{
*(unsigned long *)pte = (unsigned long) pte_quicklist;
pte_quicklist = (unsigned long *) pte;
@@ -167,7 +167,7 @@ static __inline__ void pmd_free(pmd_t *pmd)
extern int do_check_pgt_cache(int, int);
-extern inline void set_pgdir(unsigned long address, pgd_t entry)
+static inline void set_pgdir(unsigned long address, pgd_t entry)
{
struct task_struct * p;
pgd_t *pgd;
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index a1906a772df9..57af6b3eb271 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -421,18 +421,18 @@ static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; }
-extern inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
-extern inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_READ)); return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; }
+static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_EXECUTE)); return pte; }
+static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
-extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_READ)); return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; }
+static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
/*
@@ -456,7 +456,7 @@ extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
#define mk_pte_phys(physpage, pgprot) \
({ pte_t __pte; set_pte(&__pte, __pte(physpage | pgprot_val(pgprot))); __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)
{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; }
typedef pte_t *pte_addr_t;
diff --git a/include/asm-sh64/processor.h b/include/asm-sh64/processor.h
index a51bd41e6fbc..1bf252dad824 100644
--- a/include/asm-sh64/processor.h
+++ b/include/asm-sh64/processor.h
@@ -228,7 +228,7 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
* FPU lazy state save handling.
*/
-extern __inline__ void release_fpu(void)
+static inline void release_fpu(void)
{
unsigned long long __dummy;
@@ -240,7 +240,7 @@ extern __inline__ void release_fpu(void)
: "r" (SR_FD));
}
-extern __inline__ void grab_fpu(void)
+static inline void grab_fpu(void)
{
unsigned long long __dummy;
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h
index 42510e496eb5..3002e988180c 100644
--- a/include/asm-sh64/system.h
+++ b/include/asm-sh64/system.h
@@ -132,7 +132,7 @@ static __inline__ void local_irq_disable(void)
(flags != 0); \
})
-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 flags, retval;
@@ -143,7 +143,7 @@ extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
return retval;
}
-extern __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
+static inline unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
{
unsigned long flags, retval;
diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
index 10f024c6a2e3..1f825cb163c3 100644
--- a/include/asm-sh64/thread_info.h
+++ b/include/asm-sh64/thread_info.h
@@ -66,8 +66,6 @@ static inline struct thread_info *current_thread_info(void)
#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-sh64/tlbflush.h b/include/asm-sh64/tlbflush.h
index 15c0719eecc3..e45beadc29ee 100644
--- a/include/asm-sh64/tlbflush.h
+++ b/include/asm-sh64/tlbflush.h
@@ -20,7 +20,7 @@ extern void flush_tlb_mm(struct mm_struct *mm);
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
-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)
{
}
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
index 56aa3cf0f273..f4936d8fa617 100644
--- a/include/asm-sh64/uaccess.h
+++ b/include/asm-sh64/uaccess.h
@@ -287,7 +287,7 @@ __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count);
*/
extern long __strnlen_user(const char *__s, long __n);
-extern __inline__ long strnlen_user(const char *s, long n)
+static inline long strnlen_user(const char *s, long n)
{
if (!__addr_ok(s))
return 0;
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h
index 62bec7ad271c..e1033170bd3a 100644
--- a/include/asm-sparc/atomic.h
+++ b/include/asm-sparc/atomic.h
@@ -20,6 +20,7 @@ typedef struct { volatile int counter; } atomic_t;
extern int __atomic_add_return(int, atomic_t *);
extern int atomic_cmpxchg(atomic_t *, int, int);
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
extern int atomic_add_unless(atomic_t *, int, int);
extern void atomic_set(atomic_t *, int);
@@ -159,4 +160,5 @@ static inline int __atomic24_sub(int i, atomic24_t *v)
#endif /* !(__KERNEL__) */
+#include <asm-generic/atomic.h>
#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/include/asm-sparc/bitops.h b/include/asm-sparc/bitops.h
index bfbd795a0a80..41722b5e45ef 100644
--- a/include/asm-sparc/bitops.h
+++ b/include/asm-sparc/bitops.h
@@ -298,6 +298,7 @@ static inline int ffs(int x)
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
/*
* hweightN: returns the hamming weight (i.e. the number
diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h
index a10522cb21b7..cb971e88aea4 100644
--- a/include/asm-sparc/cache.h
+++ b/include/asm-sparc/cache.h
@@ -13,7 +13,6 @@
#define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES 32
#define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))
-#define L1_CACHE_SHIFT_MAX 5 /* largest L1 which this arch supports */
#define SMP_CACHE_BYTES 32
diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-sparc/futex.h
+++ b/include/asm-sparc/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-sparc/mman.h b/include/asm-sparc/mman.h
index 138eb81dd70d..98435ad8619e 100644
--- a/include/asm-sparc/mman.h
+++ b/include/asm-sparc/mman.h
@@ -54,6 +54,7 @@
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
#define MADV_FREE 0x5 /* (Solaris) contents can be freed */
+#define MADV_REMOVE 0x6 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-sparc/mutex.h b/include/asm-sparc/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-sparc/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 1f6b71f9e1b6..58dd162927bb 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -155,7 +155,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
"here:\n" \
: "=&r" (last) \
: "r" (&(current_set[hard_smp_processor_id()])), \
- "r" ((next)->thread_info), \
+ "r" (task_thread_info(next)), \
"i" (TI_KPSR), \
"i" (TI_KSP), \
"i" (TI_TASK) \
@@ -166,6 +166,16 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
} while(0)
/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
+/*
* Changing the IRQ level on the Sparc.
*/
extern void local_irq_restore(unsigned long);
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index ff6ccb3d24c6..65f060b040ab 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -92,9 +92,6 @@ BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
#define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index 3789fe315992..25256bdc8aae 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -72,6 +72,7 @@ extern int atomic64_sub_ret(int, atomic64_t *);
#define atomic64_add_negative(i, v) (atomic64_add_ret(i, v) < 0)
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
#define atomic_add_unless(v, a, u) \
({ \
@@ -96,4 +97,5 @@ extern int atomic64_sub_ret(int, atomic64_t *);
#define smp_mb__after_atomic_inc() barrier()
#endif
+#include <asm-generic/atomic.h>
#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 6388b8376c50..6efc0162fb09 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -119,6 +119,7 @@ static inline unsigned long __ffs(unsigned long word)
*/
#define fls(x) generic_fls(x)
+#define fls64(x) generic_fls64(x)
#ifdef __KERNEL__
diff --git a/include/asm-sparc64/cache.h b/include/asm-sparc64/cache.h
index ade5ec3bfd5a..f7d35a2ae9b8 100644
--- a/include/asm-sparc64/cache.h
+++ b/include/asm-sparc64/cache.h
@@ -9,7 +9,6 @@
#define L1_CACHE_BYTES 32 /* Two 16-byte sub-blocks per line. */
#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-#define L1_CACHE_SHIFT_MAX 5 /* largest L1 which this arch supports */
#define SMP_CACHE_BYTES_SHIFT 6
#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 91458118277e..69539a8ab833 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -119,7 +119,7 @@ typedef struct {
#endif
#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \
- ({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread_info->kregs); 1; })
+ ({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; })
/*
* This is used to ensure we don't load something for the wrong architecture.
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-sparc64/futex.h
+++ b/include/asm-sparc64/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 7ba845320f5c..e4efe652b54b 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -12,6 +12,7 @@ typedef u32 kprobe_opcode_t;
#define MAX_INSN_SIZE 2
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
+#define arch_remove_kprobe(p) do {} while (0)
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
@@ -38,15 +39,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
-#else /* !CONFIG_KPROBES */
-static inline int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return 0;
-}
-#endif
-
#endif /* _SPARC64_KPROBES_H */
diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
index 01cecf54357b..cb4b6156194d 100644
--- a/include/asm-sparc64/mman.h
+++ b/include/asm-sparc64/mman.h
@@ -54,6 +54,7 @@
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
#define MADV_FREE 0x5 /* (Solaris) contents can be freed */
+#define MADV_REMOVE 0x6 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index 08ba72d7722c..57ee7b306189 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -60,7 +60,7 @@ do { \
register unsigned long pgd_cache asm("o4"); \
paddr = __pa((__mm)->pgd); \
pgd_cache = 0UL; \
- if ((__tsk)->thread_info->flags & _TIF_32BIT) \
+ if (task_thread_info(__tsk)->flags & _TIF_32BIT) \
pgd_cache = get_pgd_cache((__mm)->pgd); \
__asm__ __volatile__("wrpr %%g0, 0x494, %%pstate\n\t" \
"mov %3, %%g4\n\t" \
diff --git a/include/asm-sparc64/mutex.h b/include/asm-sparc64/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-sparc64/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index d02f1e8ae1a6..3c59b2693fb9 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -163,6 +163,7 @@ enum prom_input_device {
PROMDEV_IKBD, /* input from keyboard */
PROMDEV_ITTYA, /* input from ttya */
PROMDEV_ITTYB, /* input from ttyb */
+ PROMDEV_IRSC, /* input from rsc */
PROMDEV_I_UNK,
};
@@ -174,6 +175,7 @@ enum prom_output_device {
PROMDEV_OSCREEN, /* to screen */
PROMDEV_OTTYA, /* to ttya */
PROMDEV_OTTYB, /* to ttyb */
+ PROMDEV_ORSC, /* to rsc */
PROMDEV_O_UNK,
};
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index 3169f3e2237e..cd8d9b4c8658 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -186,8 +186,9 @@ extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern unsigned long get_wchan(struct task_struct *task);
-#define KSTK_EIP(tsk) ((tsk)->thread_info->kregs->tpc)
-#define KSTK_ESP(tsk) ((tsk)->thread_info->kregs->u_regs[UREG_FP])
+#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc)
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP])
#define cpu_relax() barrier()
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index b5417529f6f1..af254e581834 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -193,11 +193,7 @@ do { \
* not preserve it's value. Hairy, but it lets us remove 2 loads
* and 2 stores in this critical code path. -DaveM
*/
-#if __GNUC__ >= 3
#define EXTRA_CLOBBER ,"%l1"
-#else
-#define EXTRA_CLOBBER
-#endif
#define switch_to(prev, next, last) \
do { if (test_thread_flag(TIF_PERFCTR)) { \
unsigned long __tmp; \
@@ -212,7 +208,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
/* If you are tempted to conditionalize the following */ \
/* so that ASI is only written if it changes, think again. */ \
__asm__ __volatile__("wr %%g0, %0, %%asi" \
- : : "r" (__thread_flag_byte_ptr(next->thread_info)[TI_FLAG_BYTE_CURRENT_DS]));\
+ : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\
__asm__ __volatile__( \
"mov %%g4, %%g7\n\t" \
"wrpr %%g0, 0x95, %%pstate\n\t" \
@@ -242,7 +238,7 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
"b,a ret_from_syscall\n\t" \
"1:\n\t" \
: "=&r" (last) \
- : "0" (next->thread_info), \
+ : "0" (task_thread_info(next)), \
"i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD), \
"i" (TI_CWP), "i" (TI_TASK) \
: "cc", \
@@ -257,6 +253,16 @@ do { if (test_thread_flag(TIF_PERFCTR)) { \
} \
} while(0)
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ *
+ * TODO: fill this in!
+ */
+static inline void sched_cacheflush(void)
+{
+}
+
static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
{
unsigned long tmp1, tmp2;
diff --git a/include/asm-um/cache.h b/include/asm-um/cache.h
index a10602a5b2d6..3d0587075521 100644
--- a/include/asm-um/cache.h
+++ b/include/asm-um/cache.h
@@ -13,9 +13,6 @@
# define L1_CACHE_SHIFT 5
#endif
-/* XXX: this is valid for x86 and x86_64. */
-#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
-
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#endif
diff --git a/include/asm-um/futex.h b/include/asm-um/futex.h
index 142ee2d8e0fd..6a332a9f099c 100644
--- a/include/asm-um/futex.h
+++ b/include/asm-um/futex.h
@@ -1,12 +1,6 @@
-#ifndef __UM_FUTEX_H
-#define __UM_FUTEX_H
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
-#include <linux/futex.h>
-#include <asm/errno.h>
-#include <asm/system.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include "asm/arch/futex.h"
+#include <asm-generic/futex.h>
#endif
diff --git a/include/asm-um/io.h b/include/asm-um/io.h
index 90674056dcef..1934d9340e2c 100644
--- a/include/asm-um/io.h
+++ b/include/asm-um/io.h
@@ -33,4 +33,20 @@ static inline void * phys_to_virt(unsigned long address)
*/
#define xlate_dev_kmem_ptr(p) p
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+ *(volatile unsigned char __force *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void __iomem *addr)
+{
+ *(volatile unsigned short __force *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void __iomem *addr)
+{
+ *(volatile unsigned int __force *) addr = b;
+}
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
#endif
diff --git a/include/asm-um/mutex.h b/include/asm-um/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-um/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index 075771c371f6..da07a69ce82a 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -89,7 +89,6 @@ extern struct task_struct *alloc_task_struct(void);
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-extern void dump_thread(struct pt_regs *regs, struct user *u);
static inline void prepare_to_copy(struct task_struct *tsk)
{
diff --git a/include/asm-um/rwsem.h b/include/asm-um/rwsem.h
index 661c0e54702b..b5fc449dc86b 100644
--- a/include/asm-um/rwsem.h
+++ b/include/asm-um/rwsem.h
@@ -1,10 +1,6 @@
#ifndef __UM_RWSEM_H__
#define __UM_RWSEM_H__
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
-#define __builtin_expect(exp,c) (exp)
-#endif
-
#include "asm/arch/rwsem.h"
#endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 97267f059ef5..17b6b07c4332 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -56,9 +56,6 @@ static inline struct thread_info *current_thread_info(void)
((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
#define free_thread_info(ti) kfree(ti)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
-
#endif
#define PREEMPT_ACTIVE 0x10000000
@@ -72,6 +69,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTART_BLOCK 4
#define TIF_MEMDIE 5
#define TIF_SYSCALL_AUDIT 6
+#define TIF_RESTORE_SIGMASK 7
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
@@ -79,16 +77,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h
index 6fdde45cc053..afccfcaa9ea9 100644
--- a/include/asm-um/unistd.h
+++ b/include/asm-um/unistd.h
@@ -34,6 +34,7 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]);
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#endif
#ifdef __KERNEL_SYSCALLS__
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h
index bede3172ce7f..166df00457ea 100644
--- a/include/asm-v850/atomic.h
+++ b/include/asm-v850/atomic.h
@@ -104,6 +104,8 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
@@ -126,4 +128,5 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __V850_ATOMIC_H__ */
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
index b91e799763fd..8955d2376ac8 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -276,6 +276,7 @@ found_middle:
#define ffs(x) generic_ffs (x)
#define fls(x) generic_fls (x)
+#define fls64(x) generic_fls64(x)
#define __ffs(x) ffs(x)
diff --git a/include/asm-v850/cache.h b/include/asm-v850/cache.h
index cbf9096e8517..8832c7ea3242 100644
--- a/include/asm-v850/cache.h
+++ b/include/asm-v850/cache.h
@@ -23,6 +23,4 @@
#define L1_CACHE_SHIFT 4
#endif
-#define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
-
#endif /* __V850_CACHE_H__ */
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h
index 9feff4ce1424..6a332a9f099c 100644
--- a/include/asm-v850/futex.h
+++ b/include/asm-v850/futex.h
@@ -1,53 +1,6 @@
#ifndef _ASM_FUTEX_H
#define _ASM_FUTEX_H
-#ifdef __KERNEL__
+#include <asm-generic/futex.h>
-#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-v850/ioctl.h b/include/asm-v850/ioctl.h
index 1765df6c7b87..b279fe06dfe5 100644
--- a/include/asm-v850/ioctl.h
+++ b/include/asm-v850/ioctl.h
@@ -1,80 +1 @@
-/* $Id: ioctl.h,v 1.1 2002/09/28 14:58:41 gerg Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _V850_IOCTL_H
-#define _V850_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * I don't really have any idea about what this should look like, so
- * for the time being, this is heavily based on the PC definitions.
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* __V850_IOCTL_H__ */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-v850/mman.h b/include/asm-v850/mman.h
index e2b90081b56f..edc79965193a 100644
--- a/include/asm-v850/mman.h
+++ b/include/asm-v850/mman.h
@@ -32,6 +32,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-v850/mutex.h b/include/asm-v850/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-v850/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h
index 98f929427d3d..2d31308935a0 100644
--- a/include/asm-v850/processor.h
+++ b/include/asm-v850/processor.h
@@ -98,10 +98,10 @@ unsigned long get_wchan (struct task_struct *p);
/* Return some info about the user process TASK. */
-#define task_tos(task) ((unsigned long)(task)->thread_info + THREAD_SIZE)
-#define task_regs(task) ((struct pt_regs *)task_tos (task) - 1)
-#define task_sp(task) (task_regs (task)->gpr[GPR_SP])
-#define task_pc(task) (task_regs (task)->pc)
+#define task_tos(task) ((unsigned long)task_stack_page(task) + THREAD_SIZE)
+#define task_pt_regs(task) ((struct pt_regs *)task_tos (task) - 1)
+#define task_sp(task) (task_pt_regs (task)->gpr[GPR_SP])
+#define task_pc(task) (task_pt_regs (task)->pc)
/* Grotty old names for some. */
#define KSTK_EIP(task) task_pc (task)
#define KSTK_ESP(task) task_sp (task)
diff --git a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
index 7bf72bb5078c..4f35cf2cd641 100644
--- a/include/asm-v850/ptrace.h
+++ b/include/asm-v850/ptrace.h
@@ -92,7 +92,7 @@ struct pt_regs
/* The number of bytes used to store each register. */
#define _PT_REG_SIZE 4
-/* Offset of a general purpose register in a stuct pt_regs. */
+/* Offset of a general purpose register in a struct pt_regs. */
#define PT_GPR(num) ((num) * _PT_REG_SIZE)
/* Offsets of various special registers & fields in a struct pt_regs. */
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
index e4cfad94a553..82b8f2846207 100644
--- a/include/asm-v850/thread_info.h
+++ b/include/asm-v850/thread_info.h
@@ -58,8 +58,6 @@ struct thread_info {
#define alloc_thread_info(tsk) ((struct thread_info *) \
__get_free_pages(GFP_KERNEL, 1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
index 5a86f8e976ec..82460a7bb233 100644
--- a/include/asm-v850/unistd.h
+++ b/include/asm-v850/unistd.h
@@ -241,9 +241,6 @@
/* User programs sometimes end up including this header file
(indirectly, via uClibc header files), so I'm a bit nervous just
including <linux/compiler.h>. */
-#if !defined(__builtin_expect) && __GNUC__ == 2 && __GNUC_MINOR__ < 96
-#define __builtin_expect(x, expected_value) (x)
-#endif
#define __syscall_return(type, res) \
do { \
@@ -346,20 +343,6 @@ type name (atype a, btype b, ctype c, dtype d, etype e) \
__syscall_return (type, __ret); \
}
-#if __GNUC__ < 3
-/* In older versions of gcc, `asm' statements with more than 10
- input/output arguments produce a fatal error. To work around this
- problem, we use two versions, one for gcc-3.x and one for earlier
- versions of gcc (the `earlier gcc' version doesn't work with gcc-3.x
- because gcc-3.x doesn't allow clobbers to also be input arguments). */
-#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f) \
- __asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \
- : "=r" (ret), "=r" (syscall) \
- : "1" (syscall), \
- "r" (a), "r" (b), "r" (c), "r" (d), \
- "r" (e), "r" (f) \
- : SYSCALL_CLOBBERS, SYSCALL_ARG4, SYSCALL_ARG5);
-#else /* __GNUC__ >= 3 */
#define __SYSCALL6_TRAP(syscall, ret, a, b, c, d, e, f) \
__asm__ __volatile__ ("trap " SYSCALL_LONG_TRAP \
: "=r" (ret), "=r" (syscall), \
@@ -368,7 +351,6 @@ type name (atype a, btype b, ctype c, dtype d, etype e) \
"r" (a), "r" (b), "r" (c), "r" (d), \
"2" (e), "3" (f) \
: SYSCALL_CLOBBERS);
-#endif
#define _syscall6(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \
type name (atype a, btype b, ctype c, dtype d, etype e, ftype f) \
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 5647b7de1749..4f6a4dc455bb 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -42,11 +42,6 @@ static __inline void apic_write(unsigned long reg, unsigned int v)
*((volatile unsigned int *)(APIC_BASE+reg)) = v;
}
-static __inline void apic_write_atomic(unsigned long reg, unsigned int v)
-{
- xchg((volatile unsigned int *)(APIC_BASE+reg), v);
-}
-
static __inline unsigned int apic_read(unsigned long reg)
{
return *((volatile unsigned int *)(APIC_BASE+reg));
@@ -57,10 +52,6 @@ static __inline__ void apic_wait_icr_idle(void)
while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
}
-#define FORCE_READ_AROUND_WRITE 0
-#define apic_read_around(x)
-#define apic_write_around(x,y) apic_write((x),(y))
-
static inline void ack_APIC_irq(void)
{
/*
@@ -71,7 +62,7 @@ static inline void ack_APIC_irq(void)
*/
/* Docs say use 0 for future compatibility */
- apic_write_around(APIC_EOI, 0);
+ apic_write(APIC_EOI, 0);
}
extern int get_maxlvt (void);
@@ -113,6 +104,12 @@ extern int disable_timer_pin_1;
extern void setup_threshold_lvt(unsigned long lvt_off);
+void smp_send_timer_broadcast_ipi(void);
+void switch_APIC_timer_to_ipi(void *cpumask);
+void switch_ipi_to_APIC_timer(void *cpumask);
+
+#define ARCH_APICTIMER_STOPS_ON_C3 1
+
#endif /* CONFIG_X86_LOCAL_APIC */
extern unsigned boot_cpu_id;
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index fb1c99ac669f..decaa2d540e8 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -13,6 +13,7 @@
#define APIC_ID 0x20
#define APIC_ID_MASK (0xFFu<<24)
#define GET_APIC_ID(x) (((x)>>24)&0xFFu)
+#define SET_APIC_ID(x) (((x)<<24))
#define APIC_LVR 0x30
#define APIC_LVR_MASK 0xFF00FF
#define GET_APIC_VERSION(x) ((x)&0xFFu)
diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h
index 50db9f39274f..4b5cd553e772 100644
--- a/include/asm-x86_64/atomic.h
+++ b/include/asm-x86_64/atomic.h
@@ -2,6 +2,7 @@
#define __ARCH_X86_64_ATOMIC__
#include <linux/config.h>
+#include <asm/types.h>
/* atomic_t should be 32 bit signed type */
@@ -389,6 +390,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
#define atomic64_dec_return(v) (atomic64_sub_return(1,v))
#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -424,4 +426,5 @@ __asm__ __volatile__(LOCK "orl %0,%1" \
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 05a0d374404b..eb4df23e1e41 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -29,7 +29,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr) : "memory");
}
@@ -46,7 +46,7 @@ static __inline__ void __set_bit(int nr, volatile void * addr)
{
__asm__ volatile(
"btsl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr) : "memory");
}
@@ -64,7 +64,7 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btrl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr));
}
@@ -72,7 +72,7 @@ static __inline__ void __clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
"btrl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr));
}
@@ -92,7 +92,7 @@ static __inline__ void __change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
"btcl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr));
}
@@ -109,7 +109,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btcl %1,%0"
- :"=m" (ADDR)
+ :"+m" (ADDR)
:"dIr" (nr));
}
@@ -127,7 +127,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -147,7 +147,7 @@ static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
__asm__(
"btsl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr));
return oldbit;
}
@@ -166,7 +166,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -186,7 +186,7 @@ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
__asm__(
"btrl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr));
return oldbit;
}
@@ -198,7 +198,7 @@ static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__(
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -217,7 +217,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
__asm__ __volatile__( LOCK_PREFIX
"btcl %2,%1\n\tsbbl %0,%0"
- :"=r" (oldbit),"=m" (ADDR)
+ :"=r" (oldbit),"+m" (ADDR)
:"dIr" (nr) : "memory");
return oldbit;
}
@@ -340,6 +340,20 @@ static __inline__ unsigned long __ffs(unsigned long word)
return word;
}
+/*
+ * __fls: find last bit set.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static __inline__ unsigned long __fls(unsigned long word)
+{
+ __asm__("bsrq %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+}
+
#ifdef __KERNEL__
static inline int sched_find_first_bit(const unsigned long *b)
@@ -370,6 +384,35 @@ static __inline__ int ffs(int x)
}
/**
+ * fls64 - find last bit set in 64 bit word
+ * @x: the word to search
+ *
+ * This is defined the same way as fls.
+ */
+static __inline__ int fls64(__u64 x)
+{
+ if (x == 0)
+ return 0;
+ return __fls(x) + 1;
+}
+
+/**
+ * fls - find last bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as ffs.
+ */
+static __inline__ int fls(int x)
+{
+ int r;
+
+ __asm__("bsrl %1,%0\n\t"
+ "cmovzl %2,%0"
+ : "=&r" (r) : "rm" (x), "rm" (-1));
+ return r+1;
+}
+
+/**
* hweightN - returns the hamming weight of a N-bit word
* @x: the word to weigh
*
@@ -407,9 +450,6 @@ static __inline__ int ffs(int x)
#define minix_find_first_zero_bit(addr,size) \
find_first_zero_bit((void*)addr,size)
-/* find last set bit */
-#define fls(x) generic_fls(x)
-
#endif /* __KERNEL__ */
#endif /* _X86_64_BITOPS_H */
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index 33e53424128b..263f0a211ed7 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -9,6 +9,17 @@
/* L1 cache line size */
#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT)
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
-#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */
+
+#ifdef CONFIG_X86_VSMP
+
+/* vSMP Internode cacheline shift */
+#define INTERNODE_CACHE_SHIFT (12)
+#ifdef CONFIG_SMP
+#define __cacheline_aligned_in_smp \
+ __attribute__((__aligned__(1 << (INTERNODE_CACHE_SHIFT)))) \
+ __attribute__((__section__(".data.page_aligned")))
+#endif
+
+#endif
#endif
diff --git a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h
index b3189fb229d1..d32f7f58752a 100644
--- a/include/asm-x86_64/cacheflush.h
+++ b/include/asm-x86_64/cacheflush.h
@@ -27,4 +27,8 @@ void global_flush_tlb(void);
int change_page_attr(struct page *page, int numpages, pgprot_t prot);
int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot);
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
+#endif
+
#endif /* _X8664_CACHEFLUSH_H */
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index f0155c38f639..b37ab8218ef0 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -198,8 +198,13 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
static __inline__ void __user *compat_alloc_user_space(long len)
{
- struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs);
+ struct pt_regs *regs = task_pt_regs(current);
return (void __user *)regs->rsp - len;
}
+static inline int is_compat_task(void)
+{
+ return current_thread_info()->status & TS_COMPAT;
+}
+
#endif /* _ASM_X86_64_COMPAT_H */
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index aea308c65709..41c0ac8559be 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -61,8 +61,9 @@
#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */
#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */
-#define X86_FEATURE_K8_C (3*32+ 4) /* C stepping K8 */
+/* 4 free */
#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
+#define X86_FEATURE_SYNC_RDTSC (3*32+6) /* RDTSC syncs CPU core */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index 33764869387b..eb7723a46790 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -25,7 +25,7 @@ struct n_desc_struct {
unsigned int a,b;
};
-extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
enum {
GATE_INTERRUPT = 0xE,
@@ -79,6 +79,9 @@ extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[];
extern struct desc_ptr cpu_gdt_descr[];
+/* the cpu gdt accessor */
+#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+
static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)
{
struct gate_struct s;
@@ -114,6 +117,11 @@ static inline void set_system_gate(int nr, void *func)
_set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
}
+static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
+{
+ _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
+}
+
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type,
unsigned size)
{
@@ -139,20 +147,20 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}
static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (unsigned long)addr,
+ set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
DESC_LDT, size * 8 - 1);
}
static inline void set_seg_base(unsigned cpu, int entry, void *base)
{
- struct desc_struct *d = &cpu_gdt_table[cpu][entry];
+ struct desc_struct *d = &cpu_gdt(cpu)[entry];
u32 addr = (u32)(u64)base;
BUG_ON((u64)base >> 32);
d->base0 = addr & 0xffff;
@@ -194,7 +202,7 @@ static inline void set_seg_base(unsigned cpu, int entry, void *base)
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
- u64 *gdt = (u64 *)(cpu_gdt_table[cpu] + GDT_ENTRY_TLS_MIN);
+ u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
gdt[0] = t->tls_array[0];
gdt[1] = t->tls_array[1];
gdt[2] = t->tls_array[2];
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index 36d16dfbac88..49a81a66516e 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -12,155 +12,176 @@
#include <asm/io.h>
#include <asm/swiotlb.h>
-extern dma_addr_t bad_dma_address;
-#define dma_mapping_error(x) \
- (swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
-
-void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp);
-void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle);
+struct dma_mapping_ops {
+ int (*mapping_error)(dma_addr_t dma_addr);
+ void* (*alloc_coherent)(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp);
+ void (*free_coherent)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+ dma_addr_t (*map_single)(struct device *hwdev, void *ptr,
+ size_t size, int direction);
+ /* like map_single, but doesn't check the device mask */
+ dma_addr_t (*map_simple)(struct device *hwdev, char *ptr,
+ size_t size, int direction);
+ void (*unmap_single)(struct device *dev, dma_addr_t addr,
+ size_t size, int direction);
+ void (*sync_single_for_cpu)(struct device *hwdev,
+ dma_addr_t dma_handle, size_t size,
+ int direction);
+ void (*sync_single_for_device)(struct device *hwdev,
+ dma_addr_t dma_handle, size_t size,
+ int direction);
+ void (*sync_single_range_for_cpu)(struct device *hwdev,
+ dma_addr_t dma_handle, unsigned long offset,
+ size_t size, int direction);
+ void (*sync_single_range_for_device)(struct device *hwdev,
+ dma_addr_t dma_handle, unsigned long offset,
+ size_t size, int direction);
+ void (*sync_sg_for_cpu)(struct device *hwdev,
+ struct scatterlist *sg, int nelems,
+ int direction);
+ void (*sync_sg_for_device)(struct device *hwdev,
+ struct scatterlist *sg, int nelems,
+ int direction);
+ int (*map_sg)(struct device *hwdev, struct scatterlist *sg,
+ int nents, int direction);
+ void (*unmap_sg)(struct device *hwdev,
+ struct scatterlist *sg, int nents,
+ int direction);
+ int (*dma_supported)(struct device *hwdev, u64 mask);
+ int is_phys;
+};
-#ifdef CONFIG_GART_IOMMU
+extern dma_addr_t bad_dma_address;
+extern struct dma_mapping_ops* dma_ops;
+extern int iommu_merge;
-extern dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size,
- int direction);
-extern void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
- int direction);
+static inline int dma_mapping_error(dma_addr_t dma_addr)
+{
+ if (dma_ops->mapping_error)
+ return dma_ops->mapping_error(dma_addr);
-#else
+ return (dma_addr == bad_dma_address);
+}
-/* No IOMMU */
+extern void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp);
+extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle);
-static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr,
- size_t size, int direction)
+static inline dma_addr_t
+dma_map_single(struct device *hwdev, void *ptr, size_t size,
+ int direction)
{
- dma_addr_t addr;
-
- if (direction == DMA_NONE)
- out_of_line_bug();
- addr = virt_to_bus(ptr);
-
- if ((addr+size) & ~*hwdev->dma_mask)
- out_of_line_bug();
- return addr;
+ return dma_ops->map_single(hwdev, ptr, size, direction);
}
-static inline void dma_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
- size_t size, int direction)
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+ int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
- /* Nothing to do */
+ dma_ops->unmap_single(dev, addr, size, direction);
}
-#endif
-
#define dma_map_page(dev,page,offset,size,dir) \
dma_map_single((dev), page_address(page)+(offset), (size), (dir))
-static inline void dma_sync_single_for_cpu(struct device *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_single_for_cpu(hwdev,dma_handle,size,direction);
+#define dma_unmap_page dma_unmap_single
+static inline void
+dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+ size_t size, int direction)
+{
+ if (dma_ops->sync_single_for_cpu)
+ dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
+ direction);
flush_write_buffers();
}
-static inline void dma_sync_single_for_device(struct device *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
+static inline void
+dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
+ size_t size, int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_single_for_device(hwdev,dma_handle,size,direction);
-
+ if (dma_ops->sync_single_for_device)
+ dma_ops->sync_single_for_device(hwdev, dma_handle, size,
+ direction);
flush_write_buffers();
}
-static inline void dma_sync_single_range_for_cpu(struct device *hwdev,
- dma_addr_t dma_handle,
- unsigned long offset,
- size_t size, int direction)
+static inline void
+dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_single_range_for_cpu(hwdev,dma_handle,offset,size,direction);
+ if (dma_ops->sync_single_range_for_cpu) {
+ dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction);
+ }
flush_write_buffers();
}
-static inline void dma_sync_single_range_for_device(struct device *hwdev,
- dma_addr_t dma_handle,
- unsigned long offset,
- size_t size, int direction)
+static inline void
+dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size, int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_single_range_for_device(hwdev,dma_handle,offset,size,direction);
+ if (dma_ops->sync_single_range_for_device)
+ dma_ops->sync_single_range_for_device(hwdev, dma_handle,
+ offset, size, direction);
flush_write_buffers();
}
-static inline void dma_sync_sg_for_cpu(struct device *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
+static inline void
+dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
+ int nelems, int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_sg_for_cpu(hwdev,sg,nelems,direction);
-
+ if (dma_ops->sync_sg_for_cpu)
+ dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
flush_write_buffers();
}
-static inline void dma_sync_sg_for_device(struct device *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
+static inline void
+dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
+ int nelems, int direction)
{
- if (direction == DMA_NONE)
- out_of_line_bug();
-
- if (swiotlb)
- return swiotlb_sync_sg_for_device(hwdev,sg,nelems,direction);
+ if (dma_ops->sync_sg_for_device) {
+ dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
+ }
flush_write_buffers();
}
-extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
-extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
+static inline int
+dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction)
+{
+ return dma_ops->map_sg(hwdev, sg, nents, direction);
+}
-#define dma_unmap_page dma_unmap_single
+static inline void
+dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+ int direction)
+{
+ dma_ops->unmap_sg(hwdev, sg, nents, direction);
+}
extern int dma_supported(struct device *hwdev, u64 mask);
-extern int dma_get_cache_alignment(void);
-#define dma_is_consistent(h) 1
-static inline int dma_set_mask(struct device *dev, u64 mask)
+/* same for gart, swiotlb, and nommu */
+static inline int dma_get_cache_alignment(void)
{
- if (!dev->dma_mask || !dma_supported(dev, mask))
- return -EIO;
- *dev->dma_mask = mask;
- return 0;
+ return boot_cpu_data.x86_clflush_size;
}
-static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
+#define dma_is_consistent(h) 1
+
+extern int dma_set_mask(struct device *dev, u64 mask);
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
{
flush_write_buffers();
}
-#endif
+extern struct device fallback_dev;
+extern int panic_on_overflow;
+
+#endif /* _X8664_DMA_MAPPING_H */
diff --git a/include/asm-x86_64/dwarf2.h b/include/asm-x86_64/dwarf2.h
index 582757fc0365..07654bd155bf 100644
--- a/include/asm-x86_64/dwarf2.h
+++ b/include/asm-x86_64/dwarf2.h
@@ -14,7 +14,7 @@
away for older version.
*/
-#ifdef CONFIG_DEBUG_INFO
+#ifdef CONFIG_UNWIND_INFO
#define CFI_STARTPROC .cfi_startproc
#define CFI_ENDPROC .cfi_endproc
@@ -28,6 +28,7 @@
#define CFI_RESTORE .cfi_restore
#define CFI_REMEMBER_STATE .cfi_remember_state
#define CFI_RESTORE_STATE .cfi_restore_state
+#define CFI_UNDEFINED .cfi_undefined
#else
@@ -44,6 +45,7 @@
#define CFI_RESTORE #
#define CFI_REMEMBER_STATE #
#define CFI_RESTORE_STATE #
+#define CFI_UNDEFINED #
#endif
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index e682edc24a68..8dcc32665240 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -55,6 +55,7 @@ extern unsigned long e820_hole_size(unsigned long start_pfn,
unsigned long end_pfn);
extern void __init parse_memopt(char *p, char **end);
+extern void __init parse_memmapopt(char *p, char **end);
extern struct e820map e820;
#endif/*!__ASSEMBLY__*/
diff --git a/include/asm-x86_64/edac.h b/include/asm-x86_64/edac.h
new file mode 100644
index 000000000000..cad1cd42b4ee
--- /dev/null
+++ b/include/asm-x86_64/edac.h
@@ -0,0 +1,18 @@
+#ifndef ASM_EDAC_H
+#define ASM_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static __inline__ void atomic_scrub(void *va, u32 size)
+{
+ unsigned int *virt_addr = va;
+ u32 i;
+
+ for (i = 0; i < size / 4; i++, virt_addr++)
+ /* Very carefully read and write to memory atomically
+ * so we are interrupt, DMA and SMP safe.
+ */
+ __asm__ __volatile__("lock; addl $0, %0"::"m"(*virt_addr));
+}
+
+#endif
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index a582cfcf2231..7b286bd21d1d 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.
*/
-static inline unsigned long fix_to_virt(const unsigned int idx)
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
{
/*
* this branch gets completely eliminated after inlining,
diff --git a/include/asm-x86_64/gart-mapping.h b/include/asm-x86_64/gart-mapping.h
new file mode 100644
index 000000000000..ada497b0b55b
--- /dev/null
+++ b/include/asm-x86_64/gart-mapping.h
@@ -0,0 +1,16 @@
+#ifndef _X8664_GART_MAPPING_H
+#define _X8664_GART_MAPPING_H 1
+
+#include <linux/types.h>
+#include <asm/types.h>
+
+struct device;
+
+extern void*
+gart_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp);
+
+extern int
+gart_dma_supported(struct device *hwdev, u64 mask);
+
+#endif /* _X8664_GART_MAPPING_H */
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index c14a8c7267a6..0df1715dee71 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -46,18 +46,18 @@ struct hw_interrupt_type;
* some of the following vectors are 'rare', they are merged
* into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
* TLB, reschedule and local APIC vectors are performance-critical.
- *
- * Vectors 0xf0-0xf9 are free (reserved for future Linux use).
*/
#define SPURIOUS_APIC_VECTOR 0xff
#define ERROR_APIC_VECTOR 0xfe
#define RESCHEDULE_VECTOR 0xfd
#define CALL_FUNCTION_VECTOR 0xfc
-#define KDB_VECTOR 0xfb /* reserved for KDB */
+/* fb free - please don't readd KDB here because it's useless
+ (hint - think what a NMI bit does to a vector) */
#define THERMAL_APIC_VECTOR 0xfa
#define THRESHOLD_APIC_VECTOR 0xf9
-#define INVALIDATE_TLB_VECTOR_END 0xf8
-#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f8 used for TLB flush */
+/* f8 free */
+#define INVALIDATE_TLB_VECTOR_END 0xf7
+#define INVALIDATE_TLB_VECTOR_START 0xf0 /* f0-f7 used for TLB flush */
#define NUM_INVALIDATE_TLB_VECTORS 8
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index aa39cfd0e001..876eb9a2fe78 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -30,7 +30,7 @@ extern int save_i387(struct _fpstate __user *buf);
*/
#define unlazy_fpu(tsk) do { \
- if ((tsk)->thread_info->status & TS_USEDFPU) \
+ if (task_thread_info(tsk)->status & TS_USEDFPU) \
save_init_fpu(tsk); \
} while (0)
@@ -46,9 +46,9 @@ static inline void tolerant_fwait(void)
}
#define clear_fpu(tsk) do { \
- if ((tsk)->thread_info->status & TS_USEDFPU) { \
+ if (task_thread_info(tsk)->status & TS_USEDFPU) { \
tolerant_fwait(); \
- (tsk)->thread_info->status &= ~TS_USEDFPU; \
+ task_thread_info(tsk)->status &= ~TS_USEDFPU; \
stts(); \
} \
} while (0)
@@ -75,7 +75,8 @@ extern int set_fpregs(struct task_struct *tsk,
static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
{
int err;
- asm volatile("1: rex64 ; fxrstor (%[fx])\n\t"
+
+ asm volatile("1: rex64/fxrstor (%[fx])\n\t"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl $-1,%[err]\n"
@@ -86,7 +87,11 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
" .quad 1b,3b\n"
".previous"
: [err] "=r" (err)
- : [fx] "r" (fx), "0" (0));
+#if 0 /* See comment in __fxsave_clear() below. */
+ : [fx] "r" (fx), "m" (*fx), "0" (0));
+#else
+ : [fx] "cdaSDb" (fx), "m" (*fx), "0" (0));
+#endif
if (unlikely(err))
init_fpu(current);
return err;
@@ -95,7 +100,8 @@ static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
{
int err;
- asm volatile("1: rex64 ; fxsave (%[fx])\n\t"
+
+ asm volatile("1: rex64/fxsave (%[fx])\n\t"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl $-1,%[err]\n"
@@ -105,20 +111,53 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
" .align 8\n"
" .quad 1b,3b\n"
".previous"
- : [err] "=r" (err)
- : [fx] "r" (fx), "0" (0));
+ : [err] "=r" (err), "=m" (*fx)
+#if 0 /* See comment in __fxsave_clear() below. */
+ : [fx] "r" (fx), "0" (0));
+#else
+ : [fx] "cdaSDb" (fx), "0" (0));
+#endif
if (unlikely(err))
__clear_user(fx, sizeof(struct i387_fxsave_struct));
return err;
}
+static inline void __fxsave_clear(struct task_struct *tsk)
+{
+ /* Using "rex64; fxsave %0" is broken because, if the memory operand
+ uses any extended registers for addressing, a second REX prefix
+ will be generated (to the assembler, rex64 followed by semicolon
+ is a separate instruction), and hence the 64-bitness is lost. */
+#if 0
+ /* Using "fxsaveq %0" would be the ideal choice, but is only supported
+ starting with gas 2.16. */
+ __asm__ __volatile__("fxsaveq %0"
+ : "=m" (tsk->thread.i387.fxsave));
+#elif 0
+ /* Using, as a workaround, the properly prefixed form below isn't
+ accepted by any binutils version so far released, complaining that
+ the same type of prefix is used twice if an extended register is
+ needed for addressing (fix submitted to mainline 2005-11-21). */
+ __asm__ __volatile__("rex64/fxsave %0"
+ : "=m" (tsk->thread.i387.fxsave));
+#else
+ /* This, however, we can work around by forcing the compiler to select
+ an addressing mode that doesn't require extended registers. */
+ __asm__ __volatile__("rex64/fxsave %P2(%1)"
+ : "=m" (tsk->thread.i387.fxsave)
+ : "cdaSDb" (tsk),
+ "i" (offsetof(__typeof__(*tsk),
+ thread.i387.fxsave)));
+#endif
+ __asm__ __volatile__("fnclex");
+}
+
static inline void kernel_fpu_begin(void)
{
struct thread_info *me = current_thread_info();
preempt_disable();
- if (me->status & TS_USEDFPU) {
- asm volatile("rex64 ; fxsave %0 ; fnclex"
- : "=m" (me->task->thread.i387.fxsave));
+ if (me->status & TS_USEDFPU) {
+ __fxsave_clear(me->task);
me->status &= ~TS_USEDFPU;
return;
}
@@ -131,11 +170,10 @@ static inline void kernel_fpu_end(void)
preempt_enable();
}
-static inline void save_init_fpu( struct task_struct *tsk )
+static inline void save_init_fpu(struct task_struct *tsk)
{
- asm volatile( "rex64 ; fxsave %0 ; fnclex"
- : "=m" (tsk->thread.i387.fxsave));
- tsk->thread_info->status &= ~TS_USEDFPU;
+ __fxsave_clear(tsk);
+ task_thread_info(tsk)->status &= ~TS_USEDFPU;
stts();
}
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index c7bc9c0525ba..e6b7f2234e43 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -169,6 +169,8 @@ int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
struct linux_binprm;
extern int ia32_setup_arg_pages(struct linux_binprm *bprm,
unsigned long stack_top, int exec_stack);
+struct mm_struct;
+extern void ia32_pick_mmap_layout(struct mm_struct *mm);
#endif
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index d5166ec3868d..e87cd83a0e86 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -299,7 +299,21 @@
#define __NR_ia32_inotify_init 291
#define __NR_ia32_inotify_add_watch 292
#define __NR_ia32_inotify_rm_watch 293
+#define __NR_ia32_migrate_pages 294
+#define __NR_ia32_opanat 295
+#define __NR_ia32_mkdirat 296
+#define __NR_ia32_mknodat 297
+#define __NR_ia32_fchownat 298
+#define __NR_ia32_futimesat 299
+#define __NR_ia32_newfstatat 300
+#define __NR_ia32_unlinkat 301
+#define __NR_ia32_renameat 302
+#define __NR_ia32_linkat 303
+#define __NR_ia32_symlinkat 304
+#define __NR_ia32_readlinkat 305
+#define __NR_ia32_fchmodat 306
+#define __NR_ia32_faccessat 307
-#define IA32_NR_syscalls 294 /* must be > than biggest syscall! */
+#define IA32_NR_syscalls 308 /* must be > than biggest syscall! */
#endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/idle.h b/include/asm-x86_64/idle.h
new file mode 100644
index 000000000000..6bd47dcf2067
--- /dev/null
+++ b/include/asm-x86_64/idle.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_X86_64_IDLE_H
+#define _ASM_X86_64_IDLE_H 1
+
+#define IDLE_START 1
+#define IDLE_END 2
+
+struct notifier_block;
+void idle_notifier_register(struct notifier_block *n);
+void idle_notifier_unregister(struct notifier_block *n);
+
+void enter_idle(void);
+void exit_idle(void);
+
+#endif
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 52ff269fe054..9dac18db8291 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -143,6 +143,11 @@ static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
extern void iounmap(volatile void __iomem *addr);
+/* Use normal IO mappings for DMI */
+#define dmi_ioremap ioremap
+#define dmi_iounmap(x,l) iounmap(x)
+#define dmi_alloc(l) kmalloc(l, GFP_ATOMIC)
+
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
diff --git a/include/asm-x86_64/ioctl.h b/include/asm-x86_64/ioctl.h
index 609b663b6bf4..b279fe06dfe5 100644
--- a/include/asm-x86_64/ioctl.h
+++ b/include/asm-x86_64/ioctl.h
@@ -1,75 +1 @@
-/* $Id: ioctl.h,v 1.2 2001/07/04 09:08:13 ak Exp $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
-#ifndef _ASMX8664_IOCTL_H
-#define _ASMX8664_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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 /* _ASMX8664_IOCTL_H */
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-x86_64/ipi.h b/include/asm-x86_64/ipi.h
index 022e9d340ad7..2a5c162b7d92 100644
--- a/include/asm-x86_64/ipi.h
+++ b/include/asm-x86_64/ipi.h
@@ -38,10 +38,6 @@ static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, uns
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;
}
diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
index fb724ba37ae6..9db5a1b4f7b1 100644
--- a/include/asm-x86_64/irq.h
+++ b/include/asm-x86_64/irq.h
@@ -36,7 +36,7 @@
#define NR_IRQ_VECTORS NR_IRQS
#else
#define NR_IRQS 224
-#define NR_IRQ_VECTORS 1024
+#define NR_IRQ_VECTORS (32 * NR_CPUS)
#endif
static __inline__ int irq_canonicalize(int irq)
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index f604e84c5303..b9ed4c0c8783 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -35,9 +35,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)
-{
- struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=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
+ };
return notifier_call_chain(&die_chain, val, &args);
}
diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h
index 42d2ff15c592..ae28cd44bcd3 100644
--- a/include/asm-x86_64/kexec.h
+++ b/include/asm-x86_64/kexec.h
@@ -3,6 +3,7 @@
#include <asm/page.h>
#include <asm/proto.h>
+#include <asm/ptrace.h>
/*
* KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
@@ -26,8 +27,40 @@
#define KEXEC_ARCH KEXEC_ARCH_X86_64
#define MAX_NOTE_BYTES 1024
-typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
-extern note_buf_t crash_notes[];
+/*
+ * Saving the registers of the cpu on which panic occured in
+ * crash_kexec to save a valid sp. The registers of other cpus
+ * will be saved in machine_crash_shutdown while shooting down them.
+ */
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+ struct pt_regs *oldregs)
+{
+ if (oldregs)
+ memcpy(newregs, oldregs, sizeof(*newregs));
+ else {
+ __asm__ __volatile__("movq %%rbx,%0" : "=m"(newregs->rbx));
+ __asm__ __volatile__("movq %%rcx,%0" : "=m"(newregs->rcx));
+ __asm__ __volatile__("movq %%rdx,%0" : "=m"(newregs->rdx));
+ __asm__ __volatile__("movq %%rsi,%0" : "=m"(newregs->rsi));
+ __asm__ __volatile__("movq %%rdi,%0" : "=m"(newregs->rdi));
+ __asm__ __volatile__("movq %%rbp,%0" : "=m"(newregs->rbp));
+ __asm__ __volatile__("movq %%rax,%0" : "=m"(newregs->rax));
+ __asm__ __volatile__("movq %%rsp,%0" : "=m"(newregs->rsp));
+ __asm__ __volatile__("movq %%r8,%0" : "=m"(newregs->r8));
+ __asm__ __volatile__("movq %%r9,%0" : "=m"(newregs->r9));
+ __asm__ __volatile__("movq %%r10,%0" : "=m"(newregs->r10));
+ __asm__ __volatile__("movq %%r11,%0" : "=m"(newregs->r11));
+ __asm__ __volatile__("movq %%r12,%0" : "=m"(newregs->r12));
+ __asm__ __volatile__("movq %%r13,%0" : "=m"(newregs->r13));
+ __asm__ __volatile__("movq %%r14,%0" : "=m"(newregs->r14));
+ __asm__ __volatile__("movq %%r15,%0" : "=m"(newregs->r15));
+ __asm__ __volatile__("movl %%ss, %%eax;" :"=a"(newregs->ss));
+ __asm__ __volatile__("movl %%cs, %%eax;" :"=a"(newregs->cs));
+ __asm__ __volatile__("pushfq; popq %0" :"=m"(newregs->eflags));
+ newregs->rip = (unsigned long)current_text_addr();
+ }
+}
#endif /* _X86_64_KEXEC_H */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index 4dd7a7e148d4..98a1e95ddb98 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -27,7 +27,10 @@
#include <linux/ptrace.h>
#include <linux/percpu.h>
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+
struct pt_regs;
+struct kprobe;
typedef u8 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0xcc
@@ -42,6 +45,7 @@ typedef u8 kprobe_opcode_t;
#define ARCH_SUPPORTS_KRETPROBES
void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
diff --git a/include/asm-x86_64/mman.h b/include/asm-x86_64/mman.h
index 78e60a4fd4ee..d0e97b74f735 100644
--- a/include/asm-x86_64/mman.h
+++ b/include/asm-x86_64/mman.h
@@ -36,6 +36,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h
index b630d52bdfb1..16e4be4de0c5 100644
--- a/include/asm-x86_64/mmu_context.h
+++ b/include/asm-x86_64/mmu_context.h
@@ -15,18 +15,13 @@
int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
void destroy_context(struct mm_struct *mm);
-#ifdef CONFIG_SMP
-
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
+#ifdef CONFIG_SMP
if (read_pda(mmu_state) == TLBSTATE_OK)
write_pda(mmu_state, TLBSTATE_LAZY);
-}
-#else
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
#endif
+}
static inline void load_cr3(pgd_t *pgd)
{
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 69baaa8a3ce0..972c9359f7d7 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -36,22 +36,12 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
NODE_DATA(nid)->node_spanned_pages)
#ifdef CONFIG_DISCONTIGMEM
-
#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
-/* Requires pfn_valid(pfn) to be true */
-#define pfn_to_page(pfn) ({ \
- int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); \
- ((pfn) - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; \
-})
-
-#define page_to_pfn(page) \
- (long)(((page) - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn)
-
-#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__); }))
+extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long page_to_pfn(struct page *page);
+extern int pfn_valid(unsigned long pfn);
#endif
#define local_mapnr(kvaddr) \
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
index 6f8a17d105ab..10248a9a0582 100644
--- a/include/asm-x86_64/mpspec.h
+++ b/include/asm-x86_64/mpspec.h
@@ -76,7 +76,7 @@ struct mpc_config_bus
{
unsigned char mpc_type;
unsigned char mpc_busid;
- unsigned char mpc_bustype[6] __attribute((packed));
+ unsigned char mpc_bustype[6];
};
/* List of Bus Type string values, Intel MP Spec. */
diff --git a/include/asm-x86_64/mutex.h b/include/asm-x86_64/mutex.h
new file mode 100644
index 000000000000..11fbee2bd6c0
--- /dev/null
+++ b/include/asm-x86_64/mutex.h
@@ -0,0 +1,113 @@
+/*
+ * Assembly implementation of the mutex fastpath, based on atomic
+ * decrement/increment.
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ */
+#ifndef _ASM_MUTEX_H
+#define _ASM_MUTEX_H
+
+/**
+ * __mutex_fastpath_lock - decrement and call function if negative
+ * @v: pointer of type atomic_t
+ * @fail_fn: function to call if the result is negative
+ *
+ * Atomically decrements @v and calls <fail_fn> if the result is negative.
+ */
+#define __mutex_fastpath_lock(v, fail_fn) \
+do { \
+ unsigned long dummy; \
+ \
+ typecheck(atomic_t *, v); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ __volatile__( \
+ LOCK " decl (%%rdi) \n" \
+ " js 2f \n" \
+ "1: \n" \
+ \
+ LOCK_SECTION_START("") \
+ "2: call "#fail_fn" \n" \
+ " jmp 1b \n" \
+ LOCK_SECTION_END \
+ \
+ :"=D" (dummy) \
+ : "D" (v) \
+ : "rax", "rsi", "rdx", "rcx", \
+ "r8", "r9", "r10", "r11", "memory"); \
+} while (0)
+
+/**
+ * __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count,
+ int fastcall (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+ else
+ return 0;
+}
+
+/**
+ * __mutex_fastpath_unlock - increment and call function if nonpositive
+ * @v: pointer of type atomic_t
+ * @fail_fn: function to call if the result is nonpositive
+ *
+ * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
+ */
+#define __mutex_fastpath_unlock(v, fail_fn) \
+do { \
+ unsigned long dummy; \
+ \
+ typecheck(atomic_t *, v); \
+ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \
+ \
+ __asm__ __volatile__( \
+ LOCK " incl (%%rdi) \n" \
+ " jle 2f \n" \
+ "1: \n" \
+ \
+ LOCK_SECTION_START("") \
+ "2: call "#fail_fn" \n" \
+ " jmp 1b \n" \
+ LOCK_SECTION_END \
+ \
+ :"=D" (dummy) \
+ : "D" (v) \
+ : "rax", "rsi", "rdx", "rcx", \
+ "r8", "r9", "r10", "r11", "memory"); \
+} while (0)
+
+#define __mutex_slowpath_needs_to_unlock() 1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ * @count: pointer of type atomic_t
+ * @fail_fn: fallback function
+ *
+ * Change the count from 1 to 0 and return 1 (success), or return 0 (failure)
+ * if it wasn't 1 originally. [the fallback function is never used on
+ * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.]
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1))
+ return 1;
+ else
+ return 0;
+}
+
+#endif
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index d51e56fdc3da..34e434ce3268 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -20,6 +20,11 @@ extern int numa_off;
extern void numa_set_node(int cpu, int node);
extern unsigned char apicid_to_node[256];
+#ifdef CONFIG_NUMA
+extern void __init init_cpu_to_node(void);
+#else
+#define init_cpu_to_node() do {} while (0)
+#endif
#define NUMA_NO_NODE 0xff
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 06e489f32472..615e3e494929 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -14,13 +14,25 @@
#define PHYSICAL_PAGE_MASK (~(PAGE_SIZE-1) & __PHYSICAL_MASK)
#define THREAD_ORDER 1
-#ifdef __ASSEMBLY__
-#define THREAD_SIZE (1 << (PAGE_SHIFT + THREAD_ORDER))
-#else
-#define THREAD_SIZE (1UL << (PAGE_SHIFT + THREAD_ORDER))
-#endif
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define CURRENT_MASK (~(THREAD_SIZE-1))
+#define EXCEPTION_STACK_ORDER 0
+#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
+
+#define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER
+#define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)
+
+#define IRQSTACK_ORDER 2
+#define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER)
+
+#define STACKFAULT_STACK 1
+#define DOUBLEFAULT_STACK 2
+#define NMI_STACK 3
+#define DEBUG_STACK 4
+#define MCE_STACK 5
+#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */
+
#define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index eeb3088a1c9e..fd03e15d7ea6 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -42,18 +42,20 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
#include <asm/scatterlist.h>
#include <linux/string.h>
#include <asm/page.h>
+#include <linux/dma-mapping.h> /* for have_iommu */
extern int iommu_setup(char *opt);
-#ifdef CONFIG_GART_IOMMU
/* The PCI address space does equal the physical memory
* 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 AMD64 it mostly equals, but we set it to zero if a hardware
+ * IOMMU (gart) of sotware IOMMU (swiotlb) is available.
*/
-#define PCI_DMA_BUS_IS_PHYS (no_iommu ? 1 : 0)
+#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
+
+#ifdef CONFIG_GART_IOMMU
/*
* x86-64 always supports DAC, but sometimes it is useful to force
@@ -79,7 +81,6 @@ extern int iommu_sac_force;
#else
/* No IOMMU */
-#define PCI_DMA_BUS_IS_PHYS 1
#define pci_dac_dma_supported(pci_dev, mask) 1
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
diff --git a/include/asm-x86_64/pda.h b/include/asm-x86_64/pda.h
index 8733ccfa442e..c7ab38a601af 100644
--- a/include/asm-x86_64/pda.h
+++ b/include/asm-x86_64/pda.h
@@ -5,6 +5,7 @@
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/cache.h>
+#include <asm/page.h>
/* Per processor datastructure. %gs points to it while the kernel runs */
struct x8664_pda {
@@ -12,6 +13,9 @@ struct x8664_pda {
unsigned long data_offset; /* Per cpu data offset from linker address */
unsigned long kernelstack; /* top of kernel stack for current */
unsigned long oldrsp; /* user rsp for system call */
+#if DEBUG_STKSZ > EXCEPTION_STKSZ
+ unsigned long debugstack; /* #DB/#BP stack. */
+#endif
int irqcount; /* Irq nesting counter. Starts with -1 */
int cpunumber; /* Logical CPU number */
char *irqstackptr; /* top of irqstack */
@@ -23,11 +27,10 @@ struct x8664_pda {
unsigned apic_timer_irqs;
} ____cacheline_aligned_in_smp;
+extern struct x8664_pda *_cpu_pda[];
+extern struct x8664_pda boot_cpu_pda[];
-#define IRQSTACK_ORDER 2
-#define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER)
-
-extern struct x8664_pda cpu_pda[];
+#define cpu_pda(i) (_cpu_pda[i])
/*
* There is no fast way to get the base address of the PDA, all the accesses
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 9c71855736fb..29a6b0408f75 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -11,7 +11,7 @@
#include <asm/pda.h>
-#define __per_cpu_offset(cpu) (cpu_pda[cpu].data_offset)
+#define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset)
#define __my_cpu_offset() read_pda(data_offset)
/* Separate out the type, so (int[3], foo) works. */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index ecf58c7c1650..8fbf4dd72115 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -122,6 +122,8 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
#define pte_same(a, b) ((a).pte == (b).pte)
+#define pte_pgprot(a) (__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
+
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define PUD_SIZE (1UL << PUD_SHIFT)
@@ -265,25 +267,25 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
*/
#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; }
-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_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_huge(pte_t pte) { return (pte_val(pte) & __LARGE_PTE) == __LARGE_PTE; }
-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; }
-extern inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
-extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
+static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
+static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
+static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
+static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
+static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
struct vm_area_struct;
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 4861246548f7..8c8d88c036ed 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -227,7 +227,13 @@ struct tss_struct {
extern struct cpuinfo_x86 boot_cpu_data;
DECLARE_PER_CPU(struct tss_struct,init_tss);
+#ifdef CONFIG_X86_VSMP
+#define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT)
+#define ARCH_MIN_MMSTRUCT_ALIGN (1 << INTERNODE_CACHE_SHIFT)
+#else
#define ARCH_MIN_TASKALIGN 16
+#define ARCH_MIN_MMSTRUCT_ALIGN 0
+#endif
struct thread_struct {
unsigned long rsp0;
@@ -267,15 +273,6 @@ struct thread_struct {
#define INIT_MMAP \
{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
-#define STACKFAULT_STACK 1
-#define DOUBLEFAULT_STACK 2
-#define NMI_STACK 3
-#define DEBUG_STACK 4
-#define MCE_STACK 5
-#define N_EXCEPTION_STACKS 5 /* hw limit: 7 */
-#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
-#define EXCEPTION_STACK_ORDER 0
-
#define start_thread(regs,new_rip,new_rsp) do { \
asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0)); \
load_gs_index(0); \
@@ -317,8 +314,8 @@ extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#define thread_saved_pc(t) (*(unsigned long *)((t)->thread.rsp - 8))
extern unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk) \
- (((struct pt_regs *)(tsk->thread.rsp0 - sizeof(struct pt_regs)))->rip)
+#define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.rsp0 - 1)
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->rip)
#define KSTK_ESP(tsk) -1 /* sorry. doesn't work for syscall. */
@@ -480,4 +477,6 @@ extern unsigned long boot_option_idle_override;
/* Boot loader type from the setup header */
extern int bootloader_type;
+#define HAVE_ARCH_PICK_MMAP_LAYOUT 1
+
#endif /* __ASM_X86_64_PROCESSOR_H */
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 34501086afef..115e496c6139 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -67,8 +67,6 @@ extern void load_gs_index(unsigned gs);
extern unsigned long end_pfn_map;
-extern cpumask_t cpu_initialized;
-
extern void show_trace(unsigned long * rsp);
extern void show_registers(struct pt_regs *regs);
@@ -91,8 +89,12 @@ extern void check_efer(void);
extern int unhandled_signal(struct task_struct *tsk, int sig);
+extern int unsynchronized_tsc(void);
+
extern void select_idle_routine(const struct cpuinfo_x86 *c);
-extern void swiotlb_init(void);
+
+extern void gart_parse_options(char *);
+extern void __init no_iommu_init(void);
extern unsigned long table_start, table_end;
@@ -106,12 +108,17 @@ extern int skip_ioapic_setup;
extern int acpi_ht;
extern int acpi_disabled;
+#ifdef CONFIG_GART_IOMMU
extern int fallback_aper_order;
extern int fallback_aper_force;
extern int iommu_aperture;
-extern int iommu_aperture_disabled;
extern int iommu_aperture_allowed;
+extern int iommu_aperture_disabled;
extern int fix_aperture;
+#else
+#define iommu_aperture 0
+#define iommu_aperture_allowed 0
+#endif
extern int force_iommu;
extern int reboot_force;
diff --git a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
index 44adaf18c11e..d4bed33fb32c 100644
--- a/include/asm-x86_64/segment.h
+++ b/include/asm-x86_64/segment.h
@@ -19,15 +19,13 @@
#define __USER_DS 0x2b /* 5*8+3 */
#define __USER_CS 0x33 /* 6*8+3 */
#define __USER32_DS __USER_DS
-#define __KERNEL16_CS (GDT_ENTRY_KERNELCS16 * 8)
-#define __KERNEL_COMPAT32_CS 0x8
#define GDT_ENTRY_TLS 1
#define GDT_ENTRY_TSS 8 /* needs two entries */
#define GDT_ENTRY_LDT 10 /* needs two entries */
#define GDT_ENTRY_TLS_MIN 12
#define GDT_ENTRY_TLS_MAX 14
-#define GDT_ENTRY_KERNELCS16 15
+/* 15 free */
#define GDT_ENTRY_TLS_ENTRIES 3
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index d030409a8fb5..9ccbb2cfd5c0 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -35,6 +35,7 @@ extern cpumask_t cpu_present_mask;
extern cpumask_t cpu_possible_map;
extern cpumask_t cpu_online_map;
extern cpumask_t cpu_callout_map;
+extern cpumask_t cpu_initialized;
/*
* Private routines/data
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index dddf1b218681..60757efd1353 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/include/asm-x86_64/swiotlb.h
@@ -3,10 +3,14 @@
#include <linux/config.h>
+#include <asm/dma-mapping.h>
+
/* SWIOTLB interface */
-extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size,
- int dir);
+extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
+ size_t size, int dir);
+extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags);
extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir);
extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
@@ -34,10 +38,10 @@ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction);
extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
-extern void *swiotlb_alloc_coherent (struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags);
extern void swiotlb_free_coherent (struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
+extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
+extern void swiotlb_init(void);
#ifdef CONFIG_SWIOTLB
extern int swiotlb;
@@ -45,4 +49,6 @@ extern int swiotlb;
#define swiotlb 0
#endif
-#endif
+extern void pci_swiotlb_init(void);
+
+#endif /* _ASM_SWTIOLB_H */
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 85348e02ad2e..a73f0c789d8b 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -20,8 +20,8 @@
#define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
/* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT "pushfq ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popfq\n\t"
+#define SAVE_CONTEXT "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\n\t"
#define __EXTRA_CLOBBER \
,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
@@ -137,6 +137,21 @@ struct alt_instr {
"663:\n\t" newinstr "\n664:\n" /* replacement */ \
".previous" :: "i" (feature), ##input)
+/* Like alternative_input, but with a single output argument */
+#define alternative_io(oldinstr, newinstr, feature, output, input...) \
+ asm volatile ("661:\n\t" oldinstr "\n662:\n" \
+ ".section .altinstructions,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 661b\n" /* label */ \
+ " .quad 663f\n" /* new instruction */ \
+ " .byte %c[feat]\n" /* feature bit */ \
+ " .byte 662b-661b\n" /* sourcelen */ \
+ " .byte 664f-663f\n" /* replacementlen */ \
+ ".previous\n" \
+ ".section .altinstr_replacement,\"ax\"\n" \
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \
+ ".previous" : output : [feat] "i" (feature), ##input)
+
/*
* Clear and set 'TS' bit respectively
*/
@@ -178,6 +193,15 @@ static inline void write_cr4(unsigned long val)
#define wbinvd() \
__asm__ __volatile__ ("wbinvd": : :"memory");
+/*
+ * On SMP systems, when the scheduler does migration-cost autodetection,
+ * it needs a way to flush as much of the CPU's caches as possible.
+ */
+static inline void sched_cacheflush(void)
+{
+ wbinvd();
+}
+
#endif /* __KERNEL__ */
#define nop() __asm__ __volatile__ ("nop")
@@ -311,10 +335,24 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
/* interrupt control.. */
#define local_save_flags(x) do { warn_if_not_ulong(x); __asm__ __volatile__("# save_flags \n\t pushfq ; popq %q0":"=g" (x): /* no input */ :"memory"); } while (0)
#define local_irq_restore(x) __asm__ __volatile__("# restore_flags \n\t pushq %0 ; popfq": /* no output */ :"g" (x):"memory", "cc")
+
+#ifdef CONFIG_X86_VSMP
+/* Interrupt control for VSMP architecture */
+#define local_irq_disable() do { unsigned long flags; local_save_flags(flags); local_irq_restore((flags & ~(1 << 9)) | (1 << 18)); } while (0)
+#define local_irq_enable() do { unsigned long flags; local_save_flags(flags); local_irq_restore((flags | (1 << 9)) & ~(1 << 18)); } while (0)
+
+#define irqs_disabled() \
+({ \
+ unsigned long flags; \
+ local_save_flags(flags); \
+ (flags & (1<<18)) || !(flags & (1<<9)); \
+})
+
+/* For spinlocks etc */
+#define local_irq_save(x) do { local_save_flags(x); local_irq_restore((x & ~(1 << 9)) | (1 << 18)); } while (0)
+#else /* CONFIG_X86_VSMP */
#define local_irq_disable() __asm__ __volatile__("cli": : :"memory")
#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")
#define irqs_disabled() \
({ \
@@ -325,15 +363,14 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
/* For spinlocks etc */
#define local_irq_save(x) do { warn_if_not_ulong(x); __asm__ __volatile__("# local_irq_save \n\t pushfq ; popq %0 ; cli":"=g" (x): /* no input */ :"memory"); } while (0)
+#endif
-void cpu_idle_wait(void);
+/* 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")
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-void disable_hlt(void);
-void enable_hlt(void);
+void cpu_idle_wait(void);
extern unsigned long arch_align_stack(unsigned long sp);
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 08eb6e4f3737..4ac0e0a36934 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -76,8 +76,6 @@ static inline struct thread_info *stack_thread_info(void)
#define alloc_thread_info(tsk) \
((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
#define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#else /* !__ASSEMBLY__ */
@@ -138,6 +136,7 @@ static inline struct thread_info *stack_thread_info(void)
* have to worry about atomic accesses.
*/
#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
+#define TS_COMPAT 0x0002 /* 32bit syscall active */
#endif /* __KERNEL__ */
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index f971f45d6d78..f18443fcdf04 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -10,6 +10,9 @@
#include <asm/msr.h>
#include <asm/vsyscall.h>
#include <asm/hpet.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <linux/compiler.h>
#define CLOCK_TICK_RATE PIT_TICK_RATE /* Underlying HZ */
@@ -23,6 +26,19 @@ static inline cycles_t get_cycles (void)
return ret;
}
+/* Like get_cycles, but make sure the CPU is synchronized. */
+static __always_inline cycles_t get_cycles_sync(void)
+{
+ unsigned long long ret;
+ unsigned eax;
+ /* Don't do an additional sync on CPUs where we know
+ RDTSC is already synchronous. */
+ alternative_io(ASM_NOP2, "cpuid", X86_FEATURE_SYNC_RDTSC,
+ "=a" (eax), "0" (1) : "ebx","ecx","edx","memory");
+ rdtscll(ret);
+ return ret;
+}
+
extern unsigned int cpu_khz;
extern int read_current_timer(unsigned long *timer_value);
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 7d82bc56b9fa..2fa7f27381b4 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -39,7 +39,6 @@ extern int __node_distance(int, int);
.max_interval = 32, \
.busy_factor = 32, \
.imbalance_pct = 125, \
- .cache_hot_time = (10*1000000), \
.cache_nice_tries = 2, \
.busy_idx = 3, \
.idle_idx = 2, \
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 1bb8b8a24436..bddffcb591b8 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -244,7 +244,7 @@ extern unsigned long copy_to_user(void __user *to, const void *from, unsigned le
extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len);
extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len);
-static inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
+static __always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
@@ -273,7 +273,7 @@ static inline int __copy_from_user(void *dst, const void __user *src, unsigned s
}
}
-static inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
+static __always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
@@ -305,7 +305,7 @@ static inline int __copy_to_user(void __user *dst, const void *src, unsigned siz
}
-static inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
{
int ret = 0;
if (!__builtin_constant_p(size))
@@ -348,6 +348,7 @@ static inline int __copy_in_user(void __user *dst, const void __user *src, unsig
long strncpy_from_user(char *dst, const char __user *src, long count);
long __strncpy_from_user(char *dst, const char __user *src, long count);
long strnlen_user(const char __user *str, long n);
+long __strnlen_user(const char __user *str, long n);
long strlen_user(const char __user *str);
unsigned long clear_user(void __user *mem, unsigned long len);
unsigned long __clear_user(void __user *mem, unsigned long len);
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 2c42150bce0c..436d099b5b6b 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -571,8 +571,37 @@ __SYSCALL(__NR_inotify_init, sys_inotify_init)
__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
#define __NR_inotify_rm_watch 255
__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
+#define __NR_migrate_pages 256
+__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
+#define __NR_openat 257
+__SYSCALL(__NR_openat, sys_openat)
+#define __NR_mkdirat 258
+__SYSCALL(__NR_mkdirat, sys_mkdirat)
+#define __NR_mknodat 259
+__SYSCALL(__NR_mknodat, sys_mknodat)
+#define __NR_fchownat 260
+__SYSCALL(__NR_fchownat, sys_fchownat)
+#define __NR_futimesat 261
+__SYSCALL(__NR_futimesat, sys_futimesat)
+#define __NR_newfstatat 262
+__SYSCALL(__NR_newfstatat, sys_newfstatat)
+#define __NR_unlinkat 263
+__SYSCALL(__NR_unlinkat, sys_unlinkat)
+#define __NR_renameat 264
+__SYSCALL(__NR_renameat, sys_renameat)
+#define __NR_linkat 265
+__SYSCALL(__NR_linkat, sys_linkat)
+#define __NR_symlinkat 266
+__SYSCALL(__NR_symlinkat, sys_symlinkat)
+#define __NR_readlinkat 267
+__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#define __NR_fchmodat 268
+__SYSCALL(__NR_fchmodat, sys_fchmodat)
+#define __NR_faccessat 269
+__SYSCALL(__NR_faccessat, sys_faccessat)
+
+#define __NR_syscall_max __NR_faccessat
-#define __NR_syscall_max __NR_inotify_rm_watch
#ifndef __NO_STUBS
/* user-visible error numbers are in the range -1 - -4095 */
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index 438a3f52f839..a85e16f56d73 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -36,8 +36,8 @@ struct vxtime_data {
int mode;
};
-#define hpet_readl(a) readl((void *)fix_to_virt(FIX_HPET_BASE) + a)
-#define hpet_writel(d,a) writel(d, (void *)fix_to_virt(FIX_HPET_BASE) + a)
+#define hpet_readl(a) readl((const void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
+#define hpet_writel(d,a) writel(d, (void __iomem *)fix_to_virt(FIX_HPET_BASE) + a)
/* vsyscall space (readonly) */
extern struct vxtime_data __vxtime;
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
index 3670cc7695da..fe105a123924 100644
--- a/include/asm-xtensa/atomic.h
+++ b/include/asm-xtensa/atomic.h
@@ -224,6 +224,7 @@ static inline int atomic_sub_return(int i, atomic_t * v)
#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
/**
* atomic_add_unless - add unless the number is a given value
@@ -286,6 +287,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#include <asm-generic/atomic.h>
#endif /* __KERNEL__ */
#endif /* _XTENSA_ATOMIC_H */
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index e76ee889e21d..0a2065f1a372 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -245,6 +245,7 @@ static __inline__ int fls (unsigned int x)
{
return __cntlz(x);
}
+#define fls64(x) generic_fls64(x)
static __inline__ int
find_next_bit(const unsigned long *addr, int size, int offset)
diff --git a/include/asm-xtensa/ioctl.h b/include/asm-xtensa/ioctl.h
index 856c605d62b1..b279fe06dfe5 100644
--- a/include/asm-xtensa/ioctl.h
+++ b/include/asm-xtensa/ioctl.h
@@ -1,83 +1 @@
-/*
- * include/asm-xtensa/ioctl.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) 2003 - 2005 Tensilica Inc.
- *
- * Derived from "include/asm-i386/ioctl.h"
- */
-
-#ifndef _XTENSA_IOCTL_H
-#define _XTENSA_IOCTL_H
-
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * The following is for compatibility across the various Linux
- * platforms. The i386 ioctl numbering scheme doesn't really enforce
- * a type field. De facto, however, the top 8 bits of the lower 16
- * bits are indeed used as a type field, so we might just as well make
- * this explicit here. Please be sure to use the decoding macros
- * below from now on.
- */
-#define _IOC_NRBITS 8
-#define _IOC_TYPEBITS 8
-#define _IOC_SIZEBITS 14
-#define _IOC_DIRBITS 2
-
-#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.
- */
-#define _IOC_NONE 0U
-#define _IOC_WRITE 1U
-#define _IOC_READ 2U
-
-#define _IOC(dir,type,nr,size) \
- (((dir) << _IOC_DIRSHIFT) | \
- ((type) << _IOC_TYPESHIFT) | \
- ((nr) << _IOC_NRSHIFT) | \
- ((size) << _IOC_SIZESHIFT))
-
-/* used to create numbers */
-#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
-
-/* used to decode ioctl numbers.. */
-#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)
-
-/* ...and for the drivers/sound files... */
-
-#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
+#include <asm-generic/ioctl.h>
diff --git a/include/asm-xtensa/mman.h b/include/asm-xtensa/mman.h
index 9a95a45df996..082a7504925e 100644
--- a/include/asm-xtensa/mman.h
+++ b/include/asm-xtensa/mman.h
@@ -72,6 +72,7 @@
#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
#define MADV_WILLNEED 0x3 /* pre-fault pages */
#define MADV_DONTNEED 0x4 /* discard these pages */
+#define MADV_REMOVE 0x5 /* remove these pages & resources */
/* compatibility flags */
#define MAP_ANON MAP_ANONYMOUS
diff --git a/include/asm-xtensa/mutex.h b/include/asm-xtensa/mutex.h
new file mode 100644
index 000000000000..458c1f7fbc18
--- /dev/null
+++ b/include/asm-xtensa/mutex.h
@@ -0,0 +1,9 @@
+/*
+ * Pull in the generic implementation for the mutex fastpath.
+ *
+ * TODO: implement optimized primitives instead, or leave the generic
+ * implementation in place, or pick the atomic_xchg() based generic
+ * implementation. (see asm-generic/mutex-xchg.h for details)
+ */
+
+#include <asm-generic/mutex-dec.h>
diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h
index 9cab5e4298b9..d1d72ad36f08 100644
--- a/include/asm-xtensa/processor.h
+++ b/include/asm-xtensa/processor.h
@@ -184,12 +184,12 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
#define release_segments(mm) do { } while(0)
#define forget_segments() do { } while (0)
-#define thread_saved_pc(tsk) (xtensa_pt_regs(tsk)->pc)
+#define thread_saved_pc(tsk) (task_pt_regs(tsk)->pc)
extern unsigned long get_wchan(struct task_struct *p);
-#define KSTK_EIP(tsk) (xtensa_pt_regs(tsk)->pc)
-#define KSTK_ESP(tsk) (xtensa_pt_regs(tsk)->areg[1])
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->areg[1])
#define cpu_relax() do { } while (0)
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index aa4fd7fb3ce7..a5ac71a5205c 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -113,8 +113,8 @@ struct pt_regs {
};
#ifdef __KERNEL__
-# define xtensa_pt_regs(tsk) ((struct pt_regs*) \
- (((long)(tsk)->thread_info + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4)) - 1)
+# define task_pt_regs(tsk) ((struct pt_regs*) \
+ (task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
# define instruction_pointer(regs) ((regs)->pc)
extern void show_regs(struct pt_regs *);
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
index af208d41fd82..5ae34ab71597 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/include/asm-xtensa/thread_info.h
@@ -93,8 +93,6 @@ static inline struct thread_info *current_thread_info(void)
/* thread information allocation */
#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
-#define get_thread_info(ti) get_task_struct((ti)->task)
-#define put_thread_info(ti) put_task_struct((ti)->task)
#else /* !__ASSEMBLY__ */
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index 26f6ec38577a..a3dae1803f45 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -35,7 +35,6 @@ struct user_key_payload {
extern struct key_type key_type_user;
extern int user_instantiate(struct key *key, const void *data, size_t datalen);
-extern int user_duplicate(struct key *key, const struct key *source);
extern int user_update(struct key *key, const void *data, size_t datalen);
extern int user_match(const struct key *key, const void *criterion);
extern void user_destroy(struct key *key);
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 49fd37629ee4..00c8efa95cc3 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -94,26 +94,27 @@ struct kiocb {
ssize_t (*ki_retry)(struct kiocb *);
void (*ki_dtor)(struct kiocb *);
- struct list_head ki_list; /* the aio core uses this
- * for cancellation */
-
union {
void __user *user;
struct task_struct *tsk;
} ki_obj;
+
__u64 ki_user_data; /* user's data for completion */
+ wait_queue_t ki_wait;
loff_t ki_pos;
+
+ void *private;
/* State that we remember to be able to restart/retry */
unsigned short ki_opcode;
size_t ki_nbytes; /* copy of iocb->aio_nbytes */
char __user *ki_buf; /* remaining iocb->aio_buf */
size_t ki_left; /* remaining bytes */
- wait_queue_t ki_wait;
long ki_retried; /* just for testing */
long ki_kicked; /* just for testing */
long ki_queued; /* just for testing */
- void *private;
+ struct list_head ki_list; /* the aio core uses this
+ * for cancellation */
};
#define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY)
@@ -126,6 +127,7 @@ struct kiocb {
(x)->ki_filp = (filp); \
(x)->ki_ctx = NULL; \
(x)->ki_cancel = NULL; \
+ (x)->ki_retry = NULL; \
(x)->ki_dtor = NULL; \
(x)->ki_obj.tsk = tsk; \
(x)->ki_user_data = 0; \
diff --git a/include/asm-arm/hardware/amba.h b/include/linux/amba/bus.h
index 51e6e54b2aa1..51e6e54b2aa1 100644
--- a/include/asm-arm/hardware/amba.h
+++ b/include/linux/amba/bus.h
diff --git a/include/asm-arm/hardware/amba_clcd.h b/include/linux/amba/clcd.h
index 6b8d73dc1ab0..6b8d73dc1ab0 100644
--- a/include/asm-arm/hardware/amba_clcd.h
+++ b/include/linux/amba/clcd.h
diff --git a/include/asm-arm/hardware/amba_kmi.h b/include/linux/amba/kmi.h
index a39e5be751b3..a39e5be751b3 100644
--- a/include/asm-arm/hardware/amba_kmi.h
+++ b/include/linux/amba/kmi.h
diff --git a/include/asm-arm/hardware/amba_serial.h b/include/linux/amba/serial.h
index dc726ffccebd..dc726ffccebd 100644
--- a/include/asm-arm/hardware/amba_serial.h
+++ b/include/linux/amba/serial.h
diff --git a/include/linux/ata.h b/include/linux/ata.h
index d2873b732bb1..94f77cce27fa 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -129,6 +129,7 @@ enum {
ATA_CMD_READ_EXT = 0x25,
ATA_CMD_WRITE = 0xCA,
ATA_CMD_WRITE_EXT = 0x35,
+ ATA_CMD_WRITE_FUA_EXT = 0x3D,
ATA_CMD_PIO_READ = 0x20,
ATA_CMD_PIO_READ_EXT = 0x24,
ATA_CMD_PIO_WRITE = 0x30,
@@ -137,10 +138,13 @@ enum {
ATA_CMD_READ_MULTI_EXT = 0x29,
ATA_CMD_WRITE_MULTI = 0xC5,
ATA_CMD_WRITE_MULTI_EXT = 0x39,
+ ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
ATA_CMD_SET_FEATURES = 0xEF,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
+ ATA_CMD_STANDBYNOW1 = 0xE0,
+ ATA_CMD_IDLEIMMEDIATE = 0xE1,
ATA_CMD_INIT_DEV_PARAMS = 0x91,
/* SETFEATURES stuff */
@@ -192,6 +196,7 @@ enum {
ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */
ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
+ ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
};
enum ata_tf_protocols {
@@ -245,7 +250,8 @@ struct ata_taskfile {
#define ata_id_is_sata(id) ((id)[93] == 0)
#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
-#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
+#define ata_id_has_fua(id) ((id)[84] & (1 << 6))
+#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
#define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13))
#define ata_id_has_lba48(id) ((id)[83] & (1 << 10))
#define ata_id_has_wcache(id) ((id)[82] & (1 << 5))
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 911c09cb9bf9..6ba3aa8a81f4 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -155,15 +155,15 @@ struct elapaarp {
#define AARP_REQUEST 1
#define AARP_REPLY 2
#define AARP_PROBE 3
- __u8 hw_src[ETH_ALEN] __attribute__ ((packed));
- __u8 pa_src_zero __attribute__ ((packed));
- __be16 pa_src_net __attribute__ ((packed));
- __u8 pa_src_node __attribute__ ((packed));
- __u8 hw_dst[ETH_ALEN] __attribute__ ((packed));
- __u8 pa_dst_zero __attribute__ ((packed));
- __be16 pa_dst_net __attribute__ ((packed));
- __u8 pa_dst_node __attribute__ ((packed));
-};
+ __u8 hw_src[ETH_ALEN];
+ __u8 pa_src_zero;
+ __be16 pa_src_net;
+ __u8 pa_src_node;
+ __u8 hw_dst[ETH_ALEN];
+ __u8 pa_dst_zero;
+ __be16 pa_dst_net;
+ __u8 pa_dst_node;
+} __attribute__ ((packed));
static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb)
{
diff --git a/include/linux/auxvec.h b/include/linux/auxvec.h
index 9a7b374c9fb4..d2bc0d66e65d 100644
--- a/include/linux/auxvec.h
+++ b/include/linux/auxvec.h
@@ -26,6 +26,6 @@
#define AT_SECURE 23 /* secure mode boolean */
-#define AT_VECTOR_SIZE 42 /* Size of auxiliary table. */
+#define AT_VECTOR_SIZE 44 /* Size of auxiliary table. */
#endif /* _LINUX_AUXVEC_H */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 685fd3720df5..b60ffe32cd21 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -292,6 +292,8 @@ extern struct bio *bio_clone(struct bio *, gfp_t);
extern void bio_init(struct bio *);
extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
+extern int bio_add_pc_page(struct request_queue *, 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);
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 38c2fb7ebe09..6a2a19f14bb2 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -76,6 +76,15 @@ static __inline__ int generic_fls(int x)
*/
#include <asm/bitops.h>
+
+static inline int generic_fls64(__u64 x)
+{
+ __u32 h = x >> 32;
+ if (h)
+ return fls(x) + 32;
+ return fls(x);
+}
+
static __inline__ int get_bitmask_order(unsigned int count)
{
int order;
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index a33a31e71bbc..02a585faa62c 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -102,7 +102,7 @@ void copy_io_context(struct io_context **pdst, struct io_context **psrc);
void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
struct request;
-typedef void (rq_end_io_fn)(struct request *);
+typedef void (rq_end_io_fn)(struct request *, int);
struct request_list {
int count[2];
@@ -118,9 +118,9 @@ struct request_list {
* try to put the fields that are referenced together in the same cacheline
*/
struct request {
- struct list_head queuelist; /* looking for ->queue? you must _not_
- * access it directly, use
- * blkdev_dequeue_request! */
+ struct list_head queuelist;
+ struct list_head donelist;
+
unsigned long flags; /* see REQ_ bits below */
/* Maintain bio traversal state for part by part I/O submission.
@@ -141,6 +141,7 @@ struct request {
struct bio *biotail;
void *elevator_private;
+ void *completion_data;
unsigned short ioprio;
@@ -184,6 +185,7 @@ struct request {
void *sense;
unsigned int timeout;
+ int retries;
/*
* For Power Management requests
@@ -206,6 +208,7 @@ enum rq_flag_bits {
__REQ_SORTED, /* elevator knows about this request */
__REQ_SOFTBARRIER, /* may not be passed by ioscheduler */
__REQ_HARDBARRIER, /* may not be passed by drive either */
+ __REQ_FUA, /* forced unit access */
__REQ_CMD, /* is a regular fs rw request */
__REQ_NOMERGE, /* don't touch this for merging */
__REQ_STARTED, /* drive already may have started this one */
@@ -229,9 +232,7 @@ enum rq_flag_bits {
__REQ_PM_SUSPEND, /* suspend request */
__REQ_PM_RESUME, /* resume request */
__REQ_PM_SHUTDOWN, /* shutdown request */
- __REQ_BAR_PREFLUSH, /* barrier pre-flush done */
- __REQ_BAR_POSTFLUSH, /* barrier post-flush */
- __REQ_BAR_FLUSH, /* rq is the flush request */
+ __REQ_ORDERED_COLOR, /* is before or after barrier */
__REQ_NR_BITS, /* stops here */
};
@@ -240,6 +241,7 @@ enum rq_flag_bits {
#define REQ_SORTED (1 << __REQ_SORTED)
#define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER)
#define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER)
+#define REQ_FUA (1 << __REQ_FUA)
#define REQ_CMD (1 << __REQ_CMD)
#define REQ_NOMERGE (1 << __REQ_NOMERGE)
#define REQ_STARTED (1 << __REQ_STARTED)
@@ -259,9 +261,7 @@ enum rq_flag_bits {
#define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND)
#define REQ_PM_RESUME (1 << __REQ_PM_RESUME)
#define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN)
-#define REQ_BAR_PREFLUSH (1 << __REQ_BAR_PREFLUSH)
-#define REQ_BAR_POSTFLUSH (1 << __REQ_BAR_POSTFLUSH)
-#define REQ_BAR_FLUSH (1 << __REQ_BAR_FLUSH)
+#define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR)
/*
* State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -291,8 +291,8 @@ struct bio_vec;
typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
typedef void (activity_fn) (void *data, int rw);
typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
-typedef int (prepare_flush_fn) (request_queue_t *, struct request *);
-typedef void (end_flush_fn) (request_queue_t *, struct request *);
+typedef void (prepare_flush_fn) (request_queue_t *, struct request *);
+typedef void (softirq_done_fn)(struct request *);
enum blk_queue_state {
Queue_down,
@@ -334,7 +334,7 @@ struct request_queue
activity_fn *activity_fn;
issue_flush_fn *issue_flush_fn;
prepare_flush_fn *prepare_flush_fn;
- end_flush_fn *end_flush_fn;
+ softirq_done_fn *softirq_done_fn;
/*
* Dispatch queue sorting
@@ -419,14 +419,11 @@ struct request_queue
/*
* reserved for flush operations
*/
- struct request *flush_rq;
- unsigned char ordered;
-};
-
-enum {
- QUEUE_ORDERED_NONE,
- QUEUE_ORDERED_TAG,
- QUEUE_ORDERED_FLUSH,
+ unsigned int ordered, next_ordered, ordseq;
+ int orderr, ordcolor;
+ struct request pre_flush_rq, bar_rq, post_flush_rq;
+ struct request *orig_bar_rq;
+ unsigned int bi_size;
};
#define RQ_INACTIVE (-1)
@@ -444,12 +441,51 @@ enum {
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
#define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */
-#define QUEUE_FLAG_FLUSH 9 /* doing barrier flush sequence */
+
+enum {
+ /*
+ * Hardbarrier is supported with one of the following methods.
+ *
+ * NONE : hardbarrier unsupported
+ * DRAIN : ordering by draining is enough
+ * DRAIN_FLUSH : ordering by draining w/ pre and post flushes
+ * DRAIN_FUA : ordering by draining w/ pre flush and FUA write
+ * TAG : ordering by tag is enough
+ * TAG_FLUSH : ordering by tag w/ pre and post flushes
+ * TAG_FUA : ordering by tag w/ pre flush and FUA write
+ */
+ QUEUE_ORDERED_NONE = 0x00,
+ QUEUE_ORDERED_DRAIN = 0x01,
+ QUEUE_ORDERED_TAG = 0x02,
+
+ QUEUE_ORDERED_PREFLUSH = 0x10,
+ QUEUE_ORDERED_POSTFLUSH = 0x20,
+ QUEUE_ORDERED_FUA = 0x40,
+
+ QUEUE_ORDERED_DRAIN_FLUSH = QUEUE_ORDERED_DRAIN |
+ QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH,
+ QUEUE_ORDERED_DRAIN_FUA = QUEUE_ORDERED_DRAIN |
+ QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA,
+ QUEUE_ORDERED_TAG_FLUSH = QUEUE_ORDERED_TAG |
+ QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH,
+ QUEUE_ORDERED_TAG_FUA = QUEUE_ORDERED_TAG |
+ QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA,
+
+ /*
+ * Ordered operation sequence
+ */
+ QUEUE_ORDSEQ_STARTED = 0x01, /* flushing in progress */
+ QUEUE_ORDSEQ_DRAIN = 0x02, /* waiting for the queue to be drained */
+ QUEUE_ORDSEQ_PREFLUSH = 0x04, /* pre-flushing in progress */
+ QUEUE_ORDSEQ_BAR = 0x08, /* original barrier req in progress */
+ QUEUE_ORDSEQ_POSTFLUSH = 0x10, /* post-flushing in progress */
+ QUEUE_ORDSEQ_DONE = 0x20,
+};
#define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
#define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
#define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
-#define blk_queue_flushing(q) test_bit(QUEUE_FLAG_FLUSH, &(q)->queue_flags)
+#define blk_queue_flushing(q) ((q)->ordseq)
#define blk_fs_request(rq) ((rq)->flags & REQ_CMD)
#define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC)
@@ -465,8 +501,7 @@ enum {
#define blk_sorted_rq(rq) ((rq)->flags & REQ_SORTED)
#define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER)
-#define blk_barrier_preflush(rq) ((rq)->flags & REQ_BAR_PREFLUSH)
-#define blk_barrier_postflush(rq) ((rq)->flags & REQ_BAR_POSTFLUSH)
+#define blk_fua_rq(rq) ((rq)->flags & REQ_FUA)
#define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist)
@@ -558,8 +593,8 @@ extern void blk_unregister_queue(struct gendisk *disk);
extern void register_disk(struct gendisk *dev);
extern void generic_make_request(struct bio *bio);
extern void blk_put_request(struct request *);
-extern void blk_end_sync_rq(struct request *rq);
-extern void blk_attempt_remerge(request_queue_t *, struct request *);
+extern void __blk_put_request(request_queue_t *, struct request *);
+extern void blk_end_sync_rq(struct request *rq, int error);
extern struct request *blk_get_request(request_queue_t *, int, gfp_t);
extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
extern void blk_requeue_request(request_queue_t *, struct request *);
@@ -579,6 +614,9 @@ extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned
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);
+extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *,
+ struct request *, int, rq_end_io_fn *);
+
static inline request_queue_t *bdev_get_queue(struct block_device *bdev)
{
return bdev->bd_disk->queue;
@@ -608,8 +646,19 @@ static inline void blk_run_address_space(struct address_space *mapping)
*/
extern int end_that_request_first(struct request *, int, int);
extern int end_that_request_chunk(struct request *, int, int);
-extern void end_that_request_last(struct request *);
+extern void end_that_request_last(struct request *, int);
extern void end_request(struct request *req, int uptodate);
+extern void blk_complete_request(struct request *);
+
+static inline int rq_all_done(struct request *rq, unsigned int nr_bytes)
+{
+ if (blk_fs_request(rq))
+ return (nr_bytes >= (rq->hard_nr_sectors << 9));
+ else if (blk_pc_request(rq))
+ return nr_bytes >= rq->data_len;
+
+ return 0;
+}
/*
* end_that_request_first/chunk() takes an uptodate argument. we account
@@ -658,12 +707,14 @@ extern void blk_queue_segment_boundary(request_queue_t *, unsigned long);
extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn);
extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
extern void blk_queue_dma_alignment(request_queue_t *, int);
+extern void blk_queue_softirq_done(request_queue_t *, softirq_done_fn *);
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
-extern void blk_queue_ordered(request_queue_t *, int);
+extern int blk_queue_ordered(request_queue_t *, unsigned, prepare_flush_fn *);
extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
-extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
-extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
-extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
+extern int blk_do_ordered(request_queue_t *, struct request **);
+extern unsigned blk_ordered_cur_seq(request_queue_t *);
+extern unsigned blk_ordered_req_seq(struct request *);
+extern void blk_ordered_complete_seq(request_queue_t *, unsigned, int);
extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
extern void blk_dump_rq_flags(struct request *, char *);
@@ -696,7 +747,8 @@ extern int blkdev_issue_flush(struct block_device *, sector_t *);
#define MAX_PHYS_SEGMENTS 128
#define MAX_HW_SEGMENTS 128
-#define MAX_SECTORS 255
+#define SAFE_MAX_SECTORS 255
+#define BLK_DEF_MAX_SECTORS 1024
#define MAX_SEGMENT_SIZE 65536
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 3b03b0b868dd..993da8cc9706 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -43,50 +43,38 @@ typedef struct bootmem_data {
extern unsigned long __init bootmem_bootmap_pages (unsigned long);
extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend);
extern void __init free_bootmem (unsigned long addr, unsigned long size);
-extern void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal, unsigned long limit);
+extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal);
+extern void * __init __alloc_bootmem_low(unsigned long size,
+ unsigned long align,
+ unsigned long goal);
+extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat,
+ unsigned long size,
+ unsigned long align,
+ unsigned long goal);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void __init reserve_bootmem (unsigned long addr, unsigned long size);
#define alloc_bootmem(x) \
__alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low(x) \
- __alloc_bootmem((x), SMP_CACHE_BYTES, 0)
+ __alloc_bootmem_low((x), SMP_CACHE_BYTES, 0)
#define alloc_bootmem_pages(x) \
__alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low_pages(x) \
- __alloc_bootmem((x), PAGE_SIZE, 0)
-
-#define alloc_bootmem_limit(x, limit) \
- __alloc_bootmem_limit((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit))
-#define alloc_bootmem_low_limit(x, limit) \
- __alloc_bootmem_limit((x), SMP_CACHE_BYTES, 0, (limit))
-#define alloc_bootmem_pages_limit(x, limit) \
- __alloc_bootmem_limit((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit))
-#define alloc_bootmem_low_pages_limit(x, limit) \
- __alloc_bootmem_limit((x), PAGE_SIZE, 0, (limit))
-
+ __alloc_bootmem_low((x), PAGE_SIZE, 0)
#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
extern unsigned long __init free_all_bootmem (void);
-
+extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal);
extern unsigned long __init init_bootmem_node (pg_data_t *pgdat, unsigned long freepfn, unsigned long startpfn, unsigned long endpfn);
extern void __init reserve_bootmem_node (pg_data_t *pgdat, unsigned long physaddr, unsigned long size);
extern void __init free_bootmem_node (pg_data_t *pgdat, unsigned long addr, unsigned long size);
extern unsigned long __init free_all_bootmem_node (pg_data_t *pgdat);
-extern void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
#define alloc_bootmem_node(pgdat, x) \
__alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_pages_node(pgdat, x) \
__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
#define alloc_bootmem_low_pages_node(pgdat, x) \
- __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
-
-#define alloc_bootmem_node_limit(pgdat, x, limit) \
- __alloc_bootmem_node_limit((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit))
-#define alloc_bootmem_pages_node_limit(pgdat, x, limit) \
- __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit))
-#define alloc_bootmem_low_pages_node_limit(pgdat, x, limit) \
- __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, 0, (limit))
-
+ __alloc_bootmem_low_node((pgdat), (x), PAGE_SIZE, 0)
#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
@@ -123,15 +111,5 @@ extern void *__init alloc_large_system_hash(const char *tablename,
#endif
extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */
-static inline void *__alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal)
-{
- return __alloc_bootmem_limit(size, align, goal, 0);
-}
-
-static inline void *__alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align,
- unsigned long goal)
-{
- return __alloc_bootmem_node_limit(pgdat, size, align, goal, 0);
-}
#endif /* _LINUX_BOOTMEM_H */
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 1db061bb6b08..9f159baf153f 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -197,7 +197,8 @@ int block_read_full_page(struct page*, get_block_t*);
int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
loff_t *);
-int generic_cont_expand(struct inode *inode, loff_t size) ;
+int generic_cont_expand(struct inode *inode, loff_t size);
+int generic_cont_expand_simple(struct inode *inode, loff_t size);
int block_commit_write(struct page *page, unsigned from, unsigned to);
int block_sync_page(struct page *);
sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
index 04bd756efc67..e86e4a938373 100644
--- a/include/linux/byteorder/generic.h
+++ b/include/linux/byteorder/generic.h
@@ -156,7 +156,7 @@ extern __be32 htonl(__u32);
extern __u16 ntohs(__be16);
extern __be16 htons(__u16);
-#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
#define ___htonl(x) __cpu_to_be32(x)
#define ___htons(x) __cpu_to_be16(x)
diff --git a/include/linux/byteorder/swab.h b/include/linux/byteorder/swab.h
index 2f1cb775125a..25f7f32883ec 100644
--- a/include/linux/byteorder/swab.h
+++ b/include/linux/byteorder/swab.h
@@ -110,7 +110,7 @@
/*
* Allow constant folding
*/
-#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
# define __swab16(x) \
(__builtin_constant_p((__u16)(x)) ? \
___swab16((x)) : \
diff --git a/include/linux/byteorder/swabb.h b/include/linux/byteorder/swabb.h
index d5f2a3205109..ae5e5f914bf4 100644
--- a/include/linux/byteorder/swabb.h
+++ b/include/linux/byteorder/swabb.h
@@ -77,7 +77,7 @@
/*
* Allow constant folding
*/
-#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
# define __swahw32(x) \
(__builtin_constant_p((__u32)(x)) ? \
___swahw32((x)) : \
diff --git a/include/linux/cache.h b/include/linux/cache.h
index 0b7ecf3af78a..d22e632f41fb 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -13,7 +13,7 @@
#define SMP_CACHE_BYTES L1_CACHE_BYTES
#endif
-#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_IA64)
+#if defined(CONFIG_X86) || defined(CONFIG_SPARC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC)
#define __read_mostly __attribute__((__section__(".data.read_mostly")))
#else
#define __read_mostly
@@ -45,12 +45,21 @@
#endif /* CONFIG_SMP */
#endif
-#if !defined(____cacheline_maxaligned_in_smp)
+/*
+ * The maximum alignment needed for some critical structures
+ * These could be inter-node cacheline sizes/L3 cacheline
+ * size etc. Define this in asm/cache.h for your arch
+ */
+#ifndef INTERNODE_CACHE_SHIFT
+#define INTERNODE_CACHE_SHIFT L1_CACHE_SHIFT
+#endif
+
+#if !defined(____cacheline_internodealigned_in_smp)
#if defined(CONFIG_SMP)
-#define ____cacheline_maxaligned_in_smp \
- __attribute__((__aligned__(1 << (L1_CACHE_SHIFT_MAX))))
+#define ____cacheline_internodealigned_in_smp \
+ __attribute__((__aligned__(1 << (INTERNODE_CACHE_SHIFT))))
#else
-#define ____cacheline_maxaligned_in_smp
+#define ____cacheline_internodealigned_in_smp
#endif
#endif
diff --git a/include/linux/calc64.h b/include/linux/calc64.h
new file mode 100644
index 000000000000..ebf4b8f38d88
--- /dev/null
+++ b/include/linux/calc64.h
@@ -0,0 +1,49 @@
+#ifndef _LINUX_CALC64_H
+#define _LINUX_CALC64_H
+
+#include <linux/types.h>
+#include <asm/div64.h>
+
+/*
+ * This is a generic macro which is used when the architecture
+ * specific div64.h does not provide a optimized one.
+ *
+ * The 64bit dividend is divided by the divisor (data type long), the
+ * result is returned and the remainder stored in the variable
+ * referenced by remainder (data type long *). In contrast to the
+ * do_div macro the dividend is kept intact.
+ */
+#ifndef div_long_long_rem
+#define div_long_long_rem(dividend, divisor, remainder) \
+ do_div_llr((dividend), divisor, remainder)
+
+static inline unsigned long do_div_llr(const long long dividend,
+ const long divisor, long *remainder)
+{
+ u64 result = dividend;
+
+ *(remainder) = do_div(result, divisor);
+ return (unsigned long) result;
+}
+#endif
+
+/*
+ * Sign aware variation of the above. On some architectures a
+ * negative dividend leads to an divide overflow exception, which
+ * is avoided by the sign check.
+ */
+static inline long div_long_long_rem_signed(const long long dividend,
+ const long divisor, long *remainder)
+{
+ long res;
+
+ if (unlikely(dividend < 0)) {
+ res = -div_long_long_rem(-dividend, divisor, remainder);
+ *remainder = -(*remainder);
+ } else
+ res = div_long_long_rem(dividend, divisor, remainder);
+
+ return res;
+}
+
+#endif
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 6b4618902d3d..5a23ce752629 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -43,6 +43,7 @@ typedef struct __user_cap_data_struct {
#ifdef __KERNEL__
#include <linux/spinlock.h>
+#include <asm/current.h>
/* #define STRICT_CAP_T_TYPECHECKS */
@@ -356,6 +357,8 @@ static inline kernel_cap_t cap_invert(kernel_cap_t c)
#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
+extern int capable(int cap);
+
#endif /* __KERNEL__ */
#endif /* !_LINUX_CAPABILITY_H */
diff --git a/include/asm-arm/hardware/clock.h b/include/linux/clk.h
index 19da861e523d..12848f81bb37 100644
--- a/include/asm-arm/hardware/clock.h
+++ b/include/linux/clk.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-arm/hardware/clock.h
+ * linux/include/linux/clk.h
*
* Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
@@ -33,6 +33,8 @@ struct clk;
* uses @dev and @id to determine the clock consumer, and thereby
* the clock producer. (IOW, @id may be identical strings, but
* clk_get may return different clock producers depending on @dev.)
+ *
+ * Drivers must assume that the clock source is not enabled.
*/
struct clk *clk_get(struct device *dev, const char *id);
@@ -49,22 +51,16 @@ int clk_enable(struct clk *clk);
/**
* clk_disable - inform the system when the clock source is no longer required.
* @clk: clock source
- */
-void clk_disable(struct clk *clk);
-
-/**
- * clk_use - increment the use count
- * @clk: clock source
*
- * Returns success (0) or negative errno.
- */
-int clk_use(struct clk *clk);
-
-/**
- * clk_unuse - decrement the use count
- * @clk: clock source
+ * Inform the system that a clock source is no longer required by
+ * a driver and may be shut down.
+ *
+ * Implementation detail: if the clock source is shared between
+ * multiple drivers, clk_enable() calls must be balanced by the
+ * same number of clk_disable() calls for the clock source to be
+ * disabled.
*/
-void clk_unuse(struct clk *clk);
+void clk_disable(struct clk *clk);
/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
@@ -76,6 +72,10 @@ unsigned long clk_get_rate(struct clk *clk);
/**
* clk_put - "free" the clock source
* @clk: clock source
+ *
+ * Note: drivers must ensure that all clk_enable calls made on this
+ * clock source are balanced by clk_disable calls prior to calling
+ * this function.
*/
void clk_put(struct clk *clk);
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 119f9d064cc6..8fad50f8e389 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -2,14 +2,6 @@
* compatible types passed or none at all... Please include
* only stuff that is compatible on *all architectures*.
*/
-#ifndef COMPATIBLE_IOCTL /* pointer to compatible structure or no argument */
-#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
-#endif
-
-#ifndef ULONG_IOCTL /* argument is an unsigned long integer, not a pointer */
-#define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
-#endif
-
COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */
COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */
@@ -218,32 +210,6 @@ COMPATIBLE_IOCTL(VT_RESIZE)
COMPATIBLE_IOCTL(VT_RESIZEX)
COMPATIBLE_IOCTL(VT_LOCKSWITCH)
COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
-/* Little v */
-/* Little v, the video4linux ioctls (conflict?) */
-COMPATIBLE_IOCTL(VIDIOCGCAP)
-COMPATIBLE_IOCTL(VIDIOCGCHAN)
-COMPATIBLE_IOCTL(VIDIOCSCHAN)
-COMPATIBLE_IOCTL(VIDIOCGPICT)
-COMPATIBLE_IOCTL(VIDIOCSPICT)
-COMPATIBLE_IOCTL(VIDIOCCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCKEY)
-COMPATIBLE_IOCTL(VIDIOCGAUDIO)
-COMPATIBLE_IOCTL(VIDIOCSAUDIO)
-COMPATIBLE_IOCTL(VIDIOCSYNC)
-COMPATIBLE_IOCTL(VIDIOCMCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCGMBUF)
-COMPATIBLE_IOCTL(VIDIOCGUNIT)
-COMPATIBLE_IOCTL(VIDIOCGCAPTURE)
-COMPATIBLE_IOCTL(VIDIOCSCAPTURE)
-/* BTTV specific... */
-COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256]))
-COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256]))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int))
-COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int))
-COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int))
/* Little p (/dev/rtc, /dev/envctrl, etc.) */
COMPATIBLE_IOCTL(RTC_AIE_ON)
COMPATIBLE_IOCTL(RTC_AIE_OFF)
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 152734055403..6e1c44a935d4 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -11,7 +11,22 @@
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
+/*
+ * Versions of the ppc64 compiler before 4.1 had a bug where use of
+ * RELOC_HIDE could trash r30. The bug can be worked around by changing
+ * the inline assembly constraint from =g to =r, in this particular
+ * case either is valid.
+ */
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
- __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \
+ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })
+
+
+#define inline inline __attribute__((always_inline))
+#define __inline__ __inline__ __attribute__((always_inline))
+#define __inline __inline __attribute__((always_inline))
+#define __deprecated __attribute__((deprecated))
+#define noinline __attribute__((noinline))
+#define __attribute_pure__ __attribute__((pure))
+#define __attribute_const__ __attribute__((__const__))
diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h
deleted file mode 100644
index ebed17660c5f..000000000000
--- a/include/linux/compiler-gcc2.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Never include this file directly. Include <linux/compiler.h> instead. */
-
-/* These definitions are for GCC v2.x. */
-
-/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented
- a mechanism by which the user can annotate likely branch directions and
- expect the blocks to be reordered appropriately. Define __builtin_expect
- to nothing for earlier compilers. */
-#include <linux/compiler-gcc.h>
-
-#if __GNUC_MINOR__ < 96
-# define __builtin_expect(x, expected_value) (x)
-#endif
-
-#define __attribute_used__ __attribute__((__unused__))
-
-/*
- * The attribute `pure' is not implemented in GCC versions earlier
- * than 2.96.
- */
-#if __GNUC_MINOR__ >= 96
-# define __attribute_pure__ __attribute__((pure))
-# define __attribute_const__ __attribute__((__const__))
-#endif
-
-/* GCC 2.95.x/2.96 recognize __va_copy, but not va_copy. Actually later GCC's
- * define both va_copy and __va_copy, but the latter may go away, so limit this
- * to this header */
-#define va_copy __va_copy
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index a6fa615afab5..1698b845761f 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -3,30 +3,14 @@
/* These definitions are for GCC v3.x. */
#include <linux/compiler-gcc.h>
-#if __GNUC_MINOR__ >= 1
-# define inline inline __attribute__((always_inline))
-# define __inline__ __inline__ __attribute__((always_inline))
-# define __inline __inline __attribute__((always_inline))
-#endif
-
-#if __GNUC_MINOR__ > 0
-# define __deprecated __attribute__((deprecated))
-#endif
-
#if __GNUC_MINOR__ >= 3
# define __attribute_used__ __attribute__((__used__))
#else
# define __attribute_used__ __attribute__((__unused__))
#endif
-#define __attribute_pure__ __attribute__((pure))
-#define __attribute_const__ __attribute__((__const__))
-
-#if __GNUC_MINOR__ >= 1
-#define noinline __attribute__((noinline))
-#endif
-
#if __GNUC_MINOR__ >= 4
#define __must_check __attribute__((warn_unused_result))
#endif
+#define __always_inline inline __attribute__((always_inline))
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 53686c037a06..6f5cc6f0e7a6 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -3,14 +3,16 @@
/* These definitions are for GCC v4.x. */
#include <linux/compiler-gcc.h>
-#define inline inline __attribute__((always_inline))
-#define __inline__ __inline__ __attribute__((always_inline))
-#define __inline __inline __attribute__((always_inline))
-#define __deprecated __attribute__((deprecated))
+#ifdef CONFIG_FORCED_INLINING
+# undef inline
+# undef __inline__
+# undef __inline
+# define inline inline __attribute__((always_inline))
+# define __inline__ __inline__ __attribute__((always_inline))
+# define __inline __inline __attribute__((always_inline))
+#endif
+
#define __attribute_used__ __attribute__((__used__))
-#define __attribute_pure__ __attribute__((pure))
-#define __attribute_const__ __attribute__((__const__))
-#define noinline __attribute__((noinline))
#define __must_check __attribute__((warn_unused_result))
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
-
+#define __always_inline inline __attribute__((always_inline))
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index d7378215b851..f23d3c6fc2c0 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -42,8 +42,6 @@ extern void __chk_io_ptr(void __iomem *);
# include <linux/compiler-gcc4.h>
#elif __GNUC__ == 3
# include <linux/compiler-gcc3.h>
-#elif __GNUC__ == 2
-# include <linux/compiler-gcc2.h>
#else
# error Sorry, your compiler is too old/not recognized.
#endif
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
new file mode 100644
index 000000000000..acffb8c9073a
--- /dev/null
+++ b/include/linux/configfs.h
@@ -0,0 +1,205 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * configfs.h - definitions for the device driver filesystem
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 021110-1307, USA.
+ *
+ * Based on sysfs:
+ * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
+ *
+ * Based on kobject.h:
+ * Copyright (c) 2002-2003 Patrick Mochel
+ * Copyright (c) 2002-2003 Open Source Development Labs
+ *
+ * configfs Copyright (C) 2005 Oracle. All rights reserved.
+ *
+ * Please read Documentation/filesystems/configfs.txt before using the
+ * configfs interface, ESPECIALLY the parts about reference counts and
+ * item destructors.
+ */
+
+#ifndef _CONFIGFS_H_
+#define _CONFIGFS_H_
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+#define CONFIGFS_ITEM_NAME_LEN 20
+
+struct module;
+
+struct configfs_item_operations;
+struct configfs_group_operations;
+struct configfs_attribute;
+struct configfs_subsystem;
+
+struct config_item {
+ char *ci_name;
+ char ci_namebuf[CONFIGFS_ITEM_NAME_LEN];
+ struct kref ci_kref;
+ struct list_head ci_entry;
+ struct config_item *ci_parent;
+ struct config_group *ci_group;
+ struct config_item_type *ci_type;
+ struct dentry *ci_dentry;
+};
+
+extern int config_item_set_name(struct config_item *, const char *, ...);
+
+static inline char *config_item_name(struct config_item * item)
+{
+ return item->ci_name;
+}
+
+extern void config_item_init(struct config_item *);
+extern void config_item_init_type_name(struct config_item *item,
+ const char *name,
+ struct config_item_type *type);
+extern void config_item_cleanup(struct config_item *);
+
+extern struct config_item * config_item_get(struct config_item *);
+extern void config_item_put(struct config_item *);
+
+struct config_item_type {
+ struct module *ct_owner;
+ struct configfs_item_operations *ct_item_ops;
+ struct configfs_group_operations *ct_group_ops;
+ struct configfs_attribute **ct_attrs;
+};
+
+
+/**
+ * group - a group of config_items of a specific type, belonging
+ * to a specific subsystem.
+ */
+
+struct config_group {
+ struct config_item cg_item;
+ struct list_head cg_children;
+ struct configfs_subsystem *cg_subsys;
+ struct config_group **default_groups;
+};
+
+
+extern void config_group_init(struct config_group *group);
+extern void config_group_init_type_name(struct config_group *group,
+ const char *name,
+ struct config_item_type *type);
+
+
+static inline struct config_group *to_config_group(struct config_item *item)
+{
+ return item ? container_of(item,struct config_group,cg_item) : NULL;
+}
+
+static inline struct config_group *config_group_get(struct config_group *group)
+{
+ return group ? to_config_group(config_item_get(&group->cg_item)) : NULL;
+}
+
+static inline void config_group_put(struct config_group *group)
+{
+ config_item_put(&group->cg_item);
+}
+
+extern struct config_item *config_group_find_obj(struct config_group *, const char *);
+
+
+struct configfs_attribute {
+ char *ca_name;
+ struct module *ca_owner;
+ mode_t ca_mode;
+};
+
+
+/*
+ * If allow_link() exists, the item can symlink(2) out to other
+ * items. If the item is a group, it may support mkdir(2).
+ * Groups supply one of make_group() and make_item(). If the
+ * group supports make_group(), one can create group children. If it
+ * supports make_item(), one can create config_item children. If it has
+ * default_groups on group->default_groups, it has automatically created
+ * group children. default_groups may coexist alongsize make_group() or
+ * make_item(), but if the group wishes to have only default_groups
+ * children (disallowing mkdir(2)), it need not provide either function.
+ * If the group has commit(), it supports pending and commited (active)
+ * items.
+ */
+struct configfs_item_operations {
+ void (*release)(struct config_item *);
+ ssize_t (*show_attribute)(struct config_item *, struct configfs_attribute *,char *);
+ ssize_t (*store_attribute)(struct config_item *,struct configfs_attribute *,const char *, size_t);
+ int (*allow_link)(struct config_item *src, struct config_item *target);
+ int (*drop_link)(struct config_item *src, struct config_item *target);
+};
+
+struct configfs_group_operations {
+ struct config_item *(*make_item)(struct config_group *group, const char *name);
+ struct config_group *(*make_group)(struct config_group *group, const char *name);
+ int (*commit_item)(struct config_item *item);
+ void (*drop_item)(struct config_group *group, struct config_item *item);
+};
+
+
+
+/**
+ * Use these macros to make defining attributes easier. See include/linux/device.h
+ * for examples..
+ */
+
+#if 0
+#define __ATTR(_name,_mode,_show,_store) { \
+ .attr = {.ca_name = __stringify(_name), .ca_mode = _mode, .ca_owner = THIS_MODULE }, \
+ .show = _show, \
+ .store = _store, \
+}
+
+#define __ATTR_RO(_name) { \
+ .attr = { .ca_name = __stringify(_name), .ca_mode = 0444, .ca_owner = THIS_MODULE }, \
+ .show = _name##_show, \
+}
+
+#define __ATTR_NULL { .attr = { .name = NULL } }
+
+#define attr_name(_attr) (_attr).attr.name
+#endif
+
+
+struct configfs_subsystem {
+ struct config_group su_group;
+ struct semaphore su_sem;
+};
+
+static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group)
+{
+ return group ?
+ container_of(group, struct configfs_subsystem, su_group) :
+ NULL;
+}
+
+int configfs_register_subsystem(struct configfs_subsystem *subsys);
+void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
+
+#endif /* __KERNEL__ */
+
+#endif /* _CONFIGFS_H_ */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index d068176b7ad7..c31650df9241 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -256,6 +256,16 @@ int cpufreq_update_policy(unsigned int cpu);
/* query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it */
unsigned int cpufreq_get(unsigned int cpu);
+/* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */
+#ifdef CONFIG_CPU_FREQ
+unsigned int cpufreq_quick_get(unsigned int cpu);
+#else
+static inline unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+ return 0;
+}
+#endif
+
/*********************************************************************
* CPUFREQ DEFAULT GOVERNOR *
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 6e2deef96b34..3bc606927116 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -14,22 +14,46 @@
#ifdef CONFIG_CPUSETS
+extern int number_of_cpusets; /* How many cpusets are defined in system? */
+
+extern int cpuset_init_early(void);
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
extern void cpuset_fork(struct task_struct *p);
extern void cpuset_exit(struct task_struct *p);
-extern cpumask_t cpuset_cpus_allowed(const struct task_struct *p);
+extern cpumask_t cpuset_cpus_allowed(struct task_struct *p);
+extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
void cpuset_init_current_mems_allowed(void);
-void cpuset_update_current_mems_allowed(void);
-void cpuset_restrict_to_mems_allowed(unsigned long *nodes);
+void cpuset_update_task_memory_state(void);
+#define cpuset_nodes_subset_current_mems_allowed(nodes) \
+ nodes_subset((nodes), current->mems_allowed)
int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
-extern int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask);
+
+extern int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask);
+static int inline cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+{
+ return number_of_cpusets <= 1 || __cpuset_zone_allowed(z, gfp_mask);
+}
+
extern int cpuset_excl_nodes_overlap(const struct task_struct *p);
+
+#define cpuset_memory_pressure_bump() \
+ do { \
+ if (cpuset_memory_pressure_enabled) \
+ __cpuset_memory_pressure_bump(); \
+ } while (0)
+extern int cpuset_memory_pressure_enabled;
+extern void __cpuset_memory_pressure_bump(void);
+
extern struct file_operations proc_cpuset_operations;
extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
+extern void cpuset_lock(void);
+extern void cpuset_unlock(void);
+
#else /* !CONFIG_CPUSETS */
+static inline int cpuset_init_early(void) { return 0; }
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
static inline void cpuset_fork(struct task_struct *p) {}
@@ -40,9 +64,14 @@ static inline cpumask_t cpuset_cpus_allowed(struct task_struct *p)
return cpu_possible_map;
}
+static inline nodemask_t cpuset_mems_allowed(struct task_struct *p)
+{
+ return node_possible_map;
+}
+
static inline void cpuset_init_current_mems_allowed(void) {}
-static inline void cpuset_update_current_mems_allowed(void) {}
-static inline void cpuset_restrict_to_mems_allowed(unsigned long *nodes) {}
+static inline void cpuset_update_task_memory_state(void) {}
+#define cpuset_nodes_subset_current_mems_allowed(nodes) (1)
static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
{
@@ -59,12 +88,17 @@ static inline int cpuset_excl_nodes_overlap(const struct task_struct *p)
return 1;
}
+static inline void cpuset_memory_pressure_bump(void) {}
+
static inline char *cpuset_task_status_allowed(struct task_struct *task,
char *buffer)
{
return buffer;
}
+static inline void cpuset_lock(void) {}
+static inline void cpuset_unlock(void) {}
+
#endif /* !CONFIG_CPUSETS */
#endif /* _LINUX_CPUSET_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 3c89df6e7768..d88bf8aa8b47 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -3,6 +3,7 @@
*
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
*
* Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
* and Nettle, by Niels Möller.
@@ -126,7 +127,11 @@ struct crypto_alg {
unsigned int cra_blocksize;
unsigned int cra_ctxsize;
unsigned int cra_alignmask;
+
+ int cra_priority;
+
const char cra_name[CRYPTO_MAX_ALG_NAME];
+ const char cra_driver_name[CRYPTO_MAX_ALG_NAME];
union {
struct cipher_alg cipher;
diff --git a/include/linux/cycx_x25.h b/include/linux/cycx_x25.h
index b10a7f3a8cac..f7a906583463 100644
--- a/include/linux/cycx_x25.h
+++ b/include/linux/cycx_x25.h
@@ -38,11 +38,11 @@ extern unsigned int cycx_debug;
/* Data Structures */
/* X.25 Command Block. */
struct cycx_x25_cmd {
- u16 command PACKED;
- u16 link PACKED; /* values: 0 or 1 */
- u16 len PACKED; /* values: 0 thru 0x205 (517) */
- u32 buf PACKED;
-};
+ u16 command;
+ u16 link; /* values: 0 or 1 */
+ u16 len; /* values: 0 thru 0x205 (517) */
+ u32 buf;
+} PACKED;
/* Defines for the 'command' field. */
#define X25_CONNECT_REQUEST 0x4401
@@ -92,34 +92,34 @@ struct cycx_x25_cmd {
* @flags - see dosx25.doc, in portuguese, for details
*/
struct cycx_x25_config {
- u8 link PACKED;
- u8 speed PACKED;
- u8 clock PACKED;
- u8 n2 PACKED;
- u8 n2win PACKED;
- u8 n3win PACKED;
- u8 nvc PACKED;
- u8 pktlen PACKED;
- u8 locaddr PACKED;
- u8 remaddr PACKED;
- u16 t1 PACKED;
- u16 t2 PACKED;
- u8 t21 PACKED;
- u8 npvc PACKED;
- u8 t23 PACKED;
- u8 flags PACKED;
-};
+ u8 link;
+ u8 speed;
+ u8 clock;
+ u8 n2;
+ u8 n2win;
+ u8 n3win;
+ u8 nvc;
+ u8 pktlen;
+ u8 locaddr;
+ u8 remaddr;
+ u16 t1;
+ u16 t2;
+ u8 t21;
+ u8 npvc;
+ u8 t23;
+ u8 flags;
+} PACKED;
struct cycx_x25_stats {
- u16 rx_crc_errors PACKED;
- u16 rx_over_errors PACKED;
- u16 n2_tx_frames PACKED;
- u16 n2_rx_frames PACKED;
- u16 tx_timeouts PACKED;
- u16 rx_timeouts PACKED;
- u16 n3_tx_packets PACKED;
- u16 n3_rx_packets PACKED;
- u16 tx_aborts PACKED;
- u16 rx_aborts PACKED;
-};
+ u16 rx_crc_errors;
+ u16 rx_over_errors;
+ u16 n2_tx_frames;
+ u16 n2_rx_frames;
+ u16 tx_timeouts;
+ u16 rx_timeouts;
+ u16 n3_tx_packets;
+ u16 n3_rx_packets;
+ u16 tx_aborts;
+ u16 rx_aborts;
+} PACKED;
#endif /* _CYCX_X25_H */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 46a2ba617595..a3ed5e059d47 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -95,14 +95,19 @@ struct dentry {
struct qstr d_name;
struct list_head d_lru; /* LRU list */
- struct list_head d_child; /* child of parent list */
+ /*
+ * d_child and d_rcu can share memory
+ */
+ union {
+ struct list_head d_child; /* child of parent list */
+ struct rcu_head d_rcu;
+ } d_u;
struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
struct super_block *d_sb; /* The root of the dentry tree */
void *d_fsdata; /* fs-specific data */
- struct rcu_head d_rcu;
struct dcookie_struct *d_cookie; /* cookie, if any */
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
index 71fab4311e92..088529f54965 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -192,10 +192,9 @@ enum {
#include <linux/workqueue.h>
#include <net/inet_connection_sock.h>
+#include <net/inet_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,
@@ -408,8 +407,6 @@ struct dccp_ackvec;
* @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
@@ -434,8 +431,6 @@ struct dccp_sock {
__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_ackvec *dccps_hc_rx_ackvec;
diff --git a/include/linux/device.h b/include/linux/device.h
index 17cbc6db67b4..58df18d9cd3e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -47,8 +47,11 @@ struct bus_type {
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
- int (*hotplug) (struct device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size);
+ int (*uevent)(struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
+ int (*probe)(struct device * dev);
+ int (*remove)(struct device * dev);
+ void (*shutdown)(struct device * dev);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
@@ -151,7 +154,7 @@ struct class {
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
- int (*hotplug)(struct class_device *dev, char **envp,
+ int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
void (*release)(struct class_device *dev);
@@ -209,9 +212,9 @@ extern int class_device_create_file(struct class_device *,
* set, this will be called instead of the class specific release function.
* Only use this if you want to override the default release function, like
* when you are nesting class_device structures.
- * @hotplug: pointer to a hotplug function for this struct class_device. If
- * set, this will be called instead of the class specific hotplug function.
- * Only use this if you want to override the default hotplug function, like
+ * @uevent: pointer to a uevent function for this struct class_device. If
+ * set, this will be called instead of the class specific uevent function.
+ * Only use this if you want to override the default uevent function, like
* when you are nesting class_device structures.
*/
struct class_device {
@@ -227,7 +230,7 @@ struct class_device {
struct class_device *parent; /* parent of this child device, if there is one */
void (*release)(struct class_device *dev);
- int (*hotplug)(struct class_device *dev, char **envp,
+ int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
char class_id[BUS_ID_SIZE]; /* unique to this class */
};
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index f5eb6b6cd109..fa75ba0d635e 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -272,9 +272,9 @@ typedef char ioctl_struct[308];
#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 4
+#define DM_VERSION_MINOR 5
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2005-01-12)"
+#define DM_VERSION_EXTRA "-ioctl (2005-10-04)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -301,8 +301,13 @@ typedef char ioctl_struct[308];
#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */
/*
- * Set this to improve performance when you aren't going to use open_count
+ * Set this to improve performance when you aren't going to use open_count.
*/
#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */
+/*
+ * Set this to avoid attempting to freeze any filesystem when suspending.
+ */
+#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */
+
#endif /* _LINUX_DM_IOCTL_H */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 05f4132622fc..2e6bbe014157 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -2,6 +2,7 @@
#define __DMI_H__
#include <linux/list.h>
+#include <linux/config.h>
enum dmi_field {
DMI_NONE,
@@ -60,12 +61,14 @@ struct dmi_device {
void *device_data; /* Type specific data */
};
-#if defined(CONFIG_X86_32)
+#ifdef CONFIG_DMI
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);
+extern void dmi_scan_machine(void);
+
#else
static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
index d41df7047ed7..c8cbd90ba375 100644
--- a/include/linux/dvb/frontend.h
+++ b/include/linux/dvb/frontend.h
@@ -240,6 +240,15 @@ struct dvb_frontend_event {
};
+/**
+ * When set, this flag will disable any zigzagging or other "normal" tuning
+ * behaviour. Additionally, there will be no automatic monitoring of the lock
+ * status, and hence no frontend events will be generated. If a frontend device
+ * is closed, this flag will be automatically turned off when the device is
+ * reopened read-write.
+ */
+#define FE_TUNE_MODE_ONESHOT 0x01
+
#define FE_GET_INFO _IOR('o', 61, struct dvb_frontend_info)
@@ -260,6 +269,7 @@ struct dvb_frontend_event {
#define FE_SET_FRONTEND _IOW('o', 76, struct dvb_frontend_parameters)
#define FE_GET_FRONTEND _IOR('o', 77, struct dvb_frontend_parameters)
+#define FE_SET_FRONTEND_TUNE_MODE _IO('o', 81) /* unsigned int */
#define FE_GET_EVENT _IOR('o', 78, struct dvb_frontend_event)
#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index a74c27e460ba..23fe746a1d51 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -66,7 +66,7 @@ struct elevator_type
};
/*
- * each queue has an elevator_queue assoicated with it
+ * each queue has an elevator_queue associated with it
*/
struct elevator_queue
{
@@ -114,8 +114,6 @@ extern ssize_t elv_iosched_store(request_queue_t *, const char *, size_t);
extern int elevator_init(request_queue_t *, char *);
extern void elevator_exit(elevator_t *);
extern int elv_rq_merge_ok(struct request *, struct bio *);
-extern int elv_try_merge(struct request *, struct bio *);
-extern int elv_try_last_merge(request_queue_t *, struct bio *);
/*
* Return values from elevator merger
@@ -130,6 +128,7 @@ extern int elv_try_last_merge(request_queue_t *, struct bio *);
#define ELEVATOR_INSERT_FRONT 1
#define ELEVATOR_INSERT_BACK 2
#define ELEVATOR_INSERT_SORT 3
+#define ELEVATOR_INSERT_REQUEUE 4
/*
* return values from elevator_may_queue_fn
diff --git a/include/linux/elf.h b/include/linux/elf.h
index ff955dbf510d..d3bfacb24496 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -151,6 +151,8 @@ typedef __s64 Elf64_Sxword;
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
+#define STT_COMMON 5
+#define STT_TLS 6
#define ELF_ST_BIND(x) ((x) >> 4)
#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 5f49a30eb6f2..745c988359c0 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -63,10 +63,11 @@ static inline int is_zero_ether_addr(const u8 *addr)
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Return true if the address is a multicast address.
+ * By definition the broadcast address is also a multicast address.
*/
static inline int is_multicast_ether_addr(const u8 *addr)
{
- return ((addr[0] != 0xff) && (0x01 & addr[0]));
+ return (0x01 & addr[0]);
}
/**
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index 2914f7b07156..e71dd98dbcae 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -87,7 +87,7 @@ struct ext3_inode_info {
#ifdef CONFIG_EXT3_FS_XATTR
/*
* Extended attributes can be read independently of the main file
- * data. Taking i_sem even when reading would cause contention
+ * data. Taking i_mutex even when reading would cause contention
* between readers of EAs and writers of regular file data, so
* instead we synchronize on xattr_sem when reading or changing
* EAs.
diff --git a/include/linux/fb.h b/include/linux/fb.h
index a973be2cfe61..2cb19e6503aa 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -608,15 +608,15 @@ struct fb_ops {
int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */
- int (*fb_ioctl)(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg, struct fb_info *info);
+ int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
+ unsigned long arg);
/* Handle 32bit compat ioctl (optional) */
- long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg,
- struct fb_info *info);
+ int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
+ unsigned long arg);
/* perform fb specific mmap */
- int (*fb_mmap)(struct fb_info *info, struct file *file, struct vm_area_struct *vma);
+ int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
/* save current hardware state */
void (*fb_save_state)(struct fb_info *info);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 8a7c82151de9..c52a63755fdd 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -23,6 +23,13 @@
#define DN_ATTRIB 0x00000020 /* File changed attibutes */
#define DN_MULTISHOT 0x80000000 /* Don't remove notifier */
+#define AT_FDCWD -100 /* Special value used to indicate
+ openat should use the current
+ working directory. */
+#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
+#define AT_REMOVEDIR 0x200 /* Remove directory instead of
+ unlinking file. */
+
#ifdef __KERNEL__
#ifndef force_o_largefile
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3ba843c46382..c6cb8f095088 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -143,7 +143,7 @@ static inline unsigned int sk_filter_len(struct sk_filter *fp)
struct sk_buff;
struct sock;
-extern int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
+extern unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen);
extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
extern int sk_chk_filter(struct sock_filter *filter, int flen);
#endif /* __KERNEL__ */
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 2063c0839d4f..2d716080be4a 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -14,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, int hotplug,
+ struct module *module, int uevent,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context));
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cc35b6ac778d..84bb449b9b01 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -9,7 +9,6 @@
#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
@@ -104,19 +103,18 @@ extern int dir_notify_enable;
#define MS_MOVE 8192
#define MS_REC 16384
#define MS_VERBOSE 32768
+#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
#define MS_UNBINDABLE (1<<17) /* change to unbindable */
#define MS_PRIVATE (1<<18) /* change to private */
#define MS_SLAVE (1<<19) /* change to slave */
#define MS_SHARED (1<<20) /* change to shared */
-#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
/*
* Superblock flags that can be altered by MS_REMOUNT
*/
-#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|\
- MS_NODIRATIME)
+#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK)
/*
* Old magic mount flag and mask
@@ -162,8 +160,6 @@ extern int dir_notify_enable;
#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA)
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
-#define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
-#define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
@@ -220,11 +216,13 @@ extern int dir_notify_enable;
#include <linux/prio_tree.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/mutex.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
+struct hd_geometry;
struct iovec;
struct nameidata;
struct kiocb;
@@ -234,9 +232,6 @@ struct kstatfs;
struct vm_area_struct;
struct vfsmount;
-/* Used to be a macro which just called the function, now just a function */
-extern void update_atime (struct inode *);
-
extern void __init inode_init(unsigned long);
extern void __init inode_init_early(void);
extern void __init mnt_init(unsigned long);
@@ -302,6 +297,37 @@ struct iattr {
*/
#include <linux/quota.h>
+/**
+ * enum positive_aop_returns - aop return codes with specific semantics
+ *
+ * @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has
+ * completed, that the page is still locked, and
+ * should be considered active. The VM uses this hint
+ * to return the page to the active list -- it won't
+ * be a candidate for writeback again in the near
+ * future. Other callers must be careful to unlock
+ * the page if they get this return. Returned by
+ * writepage();
+ *
+ * @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has
+ * unlocked it and the page might have been truncated.
+ * The caller should back up to acquiring a new page and
+ * trying again. The aop will be taking reasonable
+ * precautions not to livelock. If the caller held a page
+ * reference, it should drop it before retrying. Returned
+ * by readpage(), prepare_write(), and commit_write().
+ *
+ * address_space_operation functions return these large constants to indicate
+ * special semantics to the caller. These are much larger than the bytes in a
+ * page to allow for functions that return the number of bytes operated on in a
+ * given page.
+ */
+
+enum positive_aop_returns {
+ AOP_WRITEPAGE_ACTIVATE = 0x80000,
+ AOP_TRUNCATED_PAGE = 0x80001,
+};
+
/*
* oh the beauties of C type declarations.
*/
@@ -453,7 +479,7 @@ struct inode {
unsigned long i_blocks;
unsigned short i_bytes;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
- struct semaphore i_sem;
+ struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
struct inode_operations *i_op;
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
@@ -622,7 +648,7 @@ 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) rcuref_inc(&(x)->f_count)
+#define get_file(x) atomic_inc(&(x)->f_count)
#define file_count(x) atomic_read(&(x)->f_count)
#define MAX_NON_LFS ((1UL<<31) - 1)
@@ -729,7 +755,7 @@ extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
extern int posix_lock_file(struct file *, struct file_lock *);
extern int posix_lock_file_wait(struct file *, struct file_lock *);
extern void posix_block_lock(struct file_lock *, struct file_lock *);
-extern void posix_unblock_lock(struct file *, struct file_lock *);
+extern int posix_unblock_lock(struct file *, struct file_lock *);
extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
extern int __break_lease(struct inode *inode, unsigned int flags);
@@ -777,7 +803,6 @@ struct super_block {
struct list_head s_list; /* Keep this first */
dev_t s_dev; /* search index; _not_ kdev_t */
unsigned long s_blocksize;
- unsigned long s_old_blocksize;
unsigned char s_blocksize_bits;
unsigned char s_dirt;
unsigned long long s_maxbytes; /* Max file size */
@@ -790,7 +815,7 @@ struct super_block {
unsigned long s_magic;
struct dentry *s_root;
struct rw_semaphore s_umount;
- struct semaphore s_lock;
+ struct mutex s_lock;
int s_count;
int s_syncing;
int s_need_sync_fs;
@@ -862,13 +887,13 @@ static inline int has_fs_excl(void)
static inline void lock_super(struct super_block * sb)
{
get_fs_excl();
- down(&sb->s_lock);
+ mutex_lock(&sb->s_lock);
}
static inline void unlock_super(struct super_block * sb)
{
put_fs_excl();
- up(&sb->s_lock);
+ mutex_unlock(&sb->s_lock);
}
/*
@@ -932,6 +957,7 @@ struct block_device_operations {
int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
+ int (*getgeo)(struct block_device *, struct hd_geometry *);
struct module *owner;
};
@@ -1019,6 +1045,7 @@ struct inode_operations {
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
+ void (*truncate_range)(struct inode *, loff_t, loff_t);
};
struct seq_file;
@@ -1085,12 +1112,7 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
__mark_inode_dirty(inode, I_DIRTY_SYNC);
}
-static inline void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
-{
- /* per-mountpoint checks will go here */
- update_atime(dentry->d_inode);
-}
-
+extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
static inline void file_accessed(struct file *file)
{
if (!(file->f_flags & O_NOATIME))
@@ -1159,7 +1181,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc);
* directory. The name should be stored in the @name (with the
* understanding that it is already pointing to a a %NAME_MAX+1 sized
* buffer. get_name() should return %0 on success, a negative error code
- * or error. @get_name will be called without @parent->i_sem held.
+ * or error. @get_name will be called without @parent->i_mutex held.
*
* get_parent:
* @get_parent should find the parent directory for the given @child which
@@ -1181,7 +1203,7 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc);
* nfsd_find_fh_dentry() in either the @obj or @parent parameters.
*
* Locking rules:
- * get_parent is called with child->d_inode->i_sem down
+ * get_parent is called with child->d_inode->i_mutex down
* get_name is not (which is possibly inconsistent)
*/
@@ -1268,6 +1290,9 @@ extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
extern int vfs_statfs(struct super_block *, struct kstatfs *);
+/* /sys/fs */
+extern struct subsystem fs_subsys;
+
#define FLOCK_VERIFY_READ 1
#define FLOCK_VERIFY_WRITE 2
@@ -1313,8 +1338,10 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
/* fs/open.c */
-extern int do_truncate(struct dentry *, loff_t start, struct file *filp);
-extern long do_sys_open(const char __user *filename, int flags, int mode);
+extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
+ struct file *filp);
+extern long do_sys_open(int fdf, 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);
@@ -1360,6 +1387,12 @@ extern int register_chrdev(unsigned int, const char *,
extern int unregister_chrdev(unsigned int, const char *);
extern void unregister_chrdev_region(dev_t, unsigned);
extern int chrdev_open(struct inode *, struct file *);
+extern int get_chrdev_list(char *);
+extern void *acquire_chrdev_list(void);
+extern int count_chrdev_list(void);
+extern void *get_next_chrdev(void *);
+extern int get_chrdev_info(void *, int *, char **);
+extern void release_chrdev_list(void *);
/* fs/block_dev.c */
#define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */
@@ -1368,6 +1401,11 @@ extern const char *bdevname(struct block_device *bdev, char *buffer);
extern struct block_device *lookup_bdev(const char *);
extern struct block_device *open_bdev_excl(const char *, int, void *);
extern void close_bdev_excl(struct block_device *);
+extern void *acquire_blkdev_list(void);
+extern int count_blkdev_list(void);
+extern void *get_next_blkdev(void *);
+extern int get_blkdev_info(void *, int *, char **);
+extern void release_blkdev_list(void *);
extern void init_special_inode(struct inode *, umode_t, dev_t);
@@ -1442,7 +1480,7 @@ static inline void allow_write_access(struct file *file)
}
extern int do_pipe(int *);
-extern int open_namei(const char *, int, int, struct nameidata *);
+extern int open_namei(int dfd, const char *, int, int, struct nameidata *);
extern int may_open(struct nameidata *, int, int);
extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
@@ -1640,6 +1678,8 @@ extern int vfs_readdir(struct file *, filldir_t, void *);
extern int vfs_stat(char __user *, struct kstat *);
extern int vfs_lstat(char __user *, struct kstat *);
+extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
+extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
extern int vfs_fstat(unsigned int, struct kstat *);
extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long);
@@ -1682,7 +1722,7 @@ extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const vo
extern int inode_change_ok(struct inode *, struct iattr *);
extern int __must_check inode_setattr(struct inode *, struct iattr *);
-extern void inode_update_time(struct inode *inode, int ctime_too);
+extern void file_update_time(struct file *file);
static inline ino_t parent_ino(struct dentry *dentry)
{
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 934aa9bda481..a9f1cfd096ff 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -50,14 +50,12 @@ struct gianfar_platform_data {
/* board specific information */
u32 board_flags;
- const char *bus_id;
+ u32 bus_id;
+ u32 phy_id;
u8 mac_addr[6];
};
struct gianfar_mdio_data {
- /* device specific information */
- u32 paddr;
-
/* board specific information */
int irq[32];
};
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index b76b558b03d4..528959c52f1b 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -14,7 +14,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 3
+#define FUSE_KERNEL_MINOR_VERSION 5
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -53,6 +53,9 @@ struct fuse_kstatfs {
__u64 ffree;
__u32 bsize;
__u32 namelen;
+ __u32 frsize;
+ __u32 padding;
+ __u32 spare[6];
};
#define FATTR_MODE (1 << 0)
@@ -105,12 +108,8 @@ enum fuse_opcode {
FUSE_CREATE = 35
};
-/* 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
+/* The read buffer is required to be at least 8k, but may be much larger */
+#define FUSE_MIN_READ_BUFFER 8192
struct fuse_entry_out {
__u64 nodeid; /* Inode ID */
@@ -213,6 +212,8 @@ struct fuse_write_out {
__u32 padding;
};
+#define FUSE_COMPAT_STATFS_SIZE 48
+
struct fuse_statfs_out {
struct fuse_kstatfs st;
};
@@ -243,9 +244,16 @@ struct fuse_access_in {
__u32 padding;
};
-struct fuse_init_in_out {
+struct fuse_init_in {
+ __u32 major;
+ __u32 minor;
+};
+
+struct fuse_init_out {
__u32 major;
__u32 minor;
+ __u32 unused[3];
+ __u32 max_write;
};
struct fuse_in_header {
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 8b2eab90abb6..20f9148e38d9 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -57,6 +57,7 @@ struct vm_area_struct;
__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
__GFP_NOMEMALLOC|__GFP_HARDWALL)
+/* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */
#define GFP_ATOMIC (__GFP_HIGH)
#define GFP_NOIO (__GFP_WAIT)
#define GFP_NOFS (__GFP_WAIT | __GFP_IO)
@@ -109,6 +110,10 @@ static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
if (unlikely(order >= MAX_ORDER))
return NULL;
+ /* Unknown node is current node */
+ if (nid < 0)
+ nid = numa_node_id();
+
return __alloc_pages(gfp_mask, order,
NODE_DATA(nid)->node_zonelists + gfp_zone(gfp_mask));
}
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 71d2b8a723b9..eab537091f2a 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -93,10 +93,6 @@ extern void synchronize_irq(unsigned int irq);
struct task_struct;
#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-static inline void account_user_vtime(struct task_struct *tsk)
-{
-}
-
static inline void account_system_vtime(struct task_struct *tsk)
{
}
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
new file mode 100644
index 000000000000..089bfb1fa01a
--- /dev/null
+++ b/include/linux/hrtimer.h
@@ -0,0 +1,139 @@
+/*
+ * include/linux/hrtimer.h
+ *
+ * hrtimers - High-resolution kernel timers
+ *
+ * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ * data type definitions, declarations, prototypes
+ *
+ * Started by: Thomas Gleixner and Ingo Molnar
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_HRTIMER_H
+#define _LINUX_HRTIMER_H
+
+#include <linux/rbtree.h>
+#include <linux/ktime.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+
+/*
+ * Mode arguments of xxx_hrtimer functions:
+ */
+enum hrtimer_mode {
+ HRTIMER_ABS, /* Time value is absolute */
+ HRTIMER_REL, /* Time value is relative to now */
+};
+
+enum hrtimer_restart {
+ HRTIMER_NORESTART,
+ HRTIMER_RESTART,
+};
+
+/*
+ * Timer states:
+ */
+enum hrtimer_state {
+ HRTIMER_INACTIVE, /* Timer is inactive */
+ HRTIMER_EXPIRED, /* Timer is expired */
+ HRTIMER_PENDING, /* Timer is pending */
+};
+
+struct hrtimer_base;
+
+/**
+ * struct hrtimer - the basic hrtimer structure
+ *
+ * @node: red black tree node for time ordered insertion
+ * @expires: the absolute expiry time in the hrtimers internal
+ * representation. The time is related to the clock on
+ * which the timer is based.
+ * @state: state of the timer
+ * @function: timer expiry callback function
+ * @data: argument for the callback function
+ * @base: pointer to the timer base (per cpu and per clock)
+ *
+ * The hrtimer structure must be initialized by init_hrtimer_#CLOCKTYPE()
+ */
+struct hrtimer {
+ struct rb_node node;
+ ktime_t expires;
+ enum hrtimer_state state;
+ int (*function)(void *);
+ void *data;
+ struct hrtimer_base *base;
+};
+
+/**
+ * struct hrtimer_base - the timer base for a specific clock
+ *
+ * @index: clock type index for per_cpu support when moving a timer
+ * to a base on another cpu.
+ * @lock: lock protecting the base and associated timers
+ * @active: red black tree root node for the active timers
+ * @first: pointer to the timer node which expires first
+ * @resolution: the resolution of the clock, in nanoseconds
+ * @get_time: function to retrieve the current time of the clock
+ * @curr_timer: the timer which is executing a callback right now
+ */
+struct hrtimer_base {
+ clockid_t index;
+ spinlock_t lock;
+ struct rb_root active;
+ struct rb_node *first;
+ ktime_t resolution;
+ ktime_t (*get_time)(void);
+ struct hrtimer *curr_timer;
+};
+
+/*
+ * clock_was_set() is a NOP for non- high-resolution systems. The
+ * time-sorted order guarantees that a timer does not expire early and
+ * is expired in the next softirq when the clock was advanced.
+ */
+#define clock_was_set() do { } while (0)
+
+/* Exported timer functions: */
+
+/* Initialize timers: */
+extern void hrtimer_init(struct hrtimer *timer, const clockid_t which_clock);
+extern void hrtimer_rebase(struct hrtimer *timer, const clockid_t which_clock);
+
+
+/* Basic timer operations: */
+extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
+ const enum hrtimer_mode mode);
+extern int hrtimer_cancel(struct hrtimer *timer);
+extern int hrtimer_try_to_cancel(struct hrtimer *timer);
+
+#define hrtimer_restart(timer) hrtimer_start((timer), (timer)->expires, HRTIMER_ABS)
+
+/* Query timers: */
+extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
+extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
+
+static inline int hrtimer_active(const struct hrtimer *timer)
+{
+ return timer->state == HRTIMER_PENDING;
+}
+
+/* Forward a hrtimer so it expires after now: */
+extern unsigned long hrtimer_forward(struct hrtimer *timer, ktime_t interval);
+
+/* Precise sleep: */
+extern long hrtimer_nanosleep(struct timespec *rqtp,
+ struct timespec __user *rmtp,
+ const enum hrtimer_mode mode,
+ const clockid_t clockid);
+
+/* Soft interrupt function to run the hrtimer queues: */
+extern void hrtimer_run_queues(void);
+
+/* Bootup initialization: */
+extern void __init hrtimers_init(void);
+
+#endif
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 1056717ee501..68d82ad6b17c 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -22,7 +22,7 @@ int hugetlb_report_meminfo(char *);
int hugetlb_report_node_meminfo(int, char *);
int is_hugepage_mem_enough(size_t);
unsigned long hugetlb_total_pages(void);
-struct page *alloc_huge_page(void);
+struct page *alloc_huge_page(struct vm_area_struct *, unsigned long);
void free_huge_page(struct page *);
int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long address, int write_access);
@@ -97,7 +97,7 @@ static inline unsigned long hugetlb_total_pages(void)
#define is_hugepage_only_range(mm, addr, len) 0
#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
do { } while (0)
-#define alloc_huge_page() ({ NULL; })
+#define alloc_huge_page(vma, addr) ({ NULL; })
#define free_huge_page(p) ({ (void)(p); BUG(); })
#define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; })
diff --git a/include/linux/hwmon-vid.h b/include/linux/hwmon-vid.h
index cd4b7a042b86..f346e4d5381c 100644
--- a/include/linux/hwmon-vid.h
+++ b/include/linux/hwmon-vid.h
@@ -23,14 +23,14 @@
#ifndef _LINUX_HWMON_VID_H
#define _LINUX_HWMON_VID_H
-int vid_from_reg(int val, int vrm);
-int vid_which_vrm(void);
+int vid_from_reg(int val, u8 vrm);
+u8 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)
+static inline int vid_to_reg(int val, u8 vrm)
{
switch (vrm) {
case 91: /* VRM 9.1 */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 006c81ef4d50..474c8f4f5d4f 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -25,12 +25,6 @@
/*
* ---- Driver types -----------------------------------------------------
- * device id name + number function description, i2c address(es)
- *
- * Range 1000-1999 range is defined in sensors/sensors.h
- * Range 0x100 - 0x1ff is for V4L2 Common Components
- * Range 0xf000 - 0xffff is reserved for local experimentation, and should
- * never be used in official drivers
*/
#define I2C_DRIVERID_MSP3400 1
@@ -109,14 +103,13 @@
#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */
#define I2C_DRIVERID_AKITAIOEXP 74 /* IO Expander on Sharp SL-C1000 */
#define I2C_DRIVERID_INFRARED 75 /* I2C InfraRed on Video boards */
-
-#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
-#define I2C_DRIVERID_EXP1 0xF1
-#define I2C_DRIVERID_EXP2 0xF2
-#define I2C_DRIVERID_EXP3 0xF3
+#define I2C_DRIVERID_TVP5150 76 /* TVP5150 video decoder */
+#define I2C_DRIVERID_WM8739 77 /* wm8739 audio processor */
+#define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */
+#define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */
+#define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */
#define I2C_DRIVERID_I2CDEV 900
-#define I2C_DRIVERID_I2CPROC 901
#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
#define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */
@@ -131,15 +124,12 @@
#define I2C_DRIVERID_ADM1021 1008
#define I2C_DRIVERID_ADM9240 1009
#define I2C_DRIVERID_LTC1710 1010
-#define I2C_DRIVERID_SIS5595 1011
#define I2C_DRIVERID_ICSPLL 1012
#define I2C_DRIVERID_BT869 1013
#define I2C_DRIVERID_MAXILIFE 1014
#define I2C_DRIVERID_MATORB 1015
#define I2C_DRIVERID_GL520 1016
#define I2C_DRIVERID_THMC50 1017
-#define I2C_DRIVERID_DDCMON 1018
-#define I2C_DRIVERID_VIA686A 1019
#define I2C_DRIVERID_ADM1025 1020
#define I2C_DRIVERID_LM87 1021
#define I2C_DRIVERID_PCF8574 1022
@@ -151,21 +141,16 @@
#define I2C_DRIVERID_FSCPOS 1028
#define I2C_DRIVERID_FSCSCY 1029
#define I2C_DRIVERID_PCF8591 1030
-#define I2C_DRIVERID_SMSC47M1 1031
-#define I2C_DRIVERID_VT1211 1032
#define I2C_DRIVERID_LM92 1033
-#define I2C_DRIVERID_VT8231 1034
#define I2C_DRIVERID_SMARTBATT 1035
#define I2C_DRIVERID_BMCSENSORS 1036
#define I2C_DRIVERID_FS451 1037
-#define I2C_DRIVERID_W83627HF 1038
#define I2C_DRIVERID_LM85 1039
#define I2C_DRIVERID_LM83 1040
#define I2C_DRIVERID_LM90 1042
#define I2C_DRIVERID_ASB100 1043
#define I2C_DRIVERID_FSCHER 1046
#define I2C_DRIVERID_W83L785TS 1047
-#define I2C_DRIVERID_SMSC47B397 1050
/*
* ---- Adapter types ----------------------------------------------------
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 5e19a7ba69b2..7863a59bd598 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -105,14 +105,14 @@ extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
* A driver is capable of handling one or more physical devices present on
* I2C adapters. This information is used to inform the driver of adapter
* events.
+ *
+ * The driver.owner field should be set to the module owner of this driver.
+ * The driver.name field should be set to the name of this driver.
*/
struct i2c_driver {
- struct module *owner;
- char name[32];
int id;
unsigned int class;
- unsigned int flags; /* div., see below */
/* Notifies the driver that a new bus has appeared. This routine
* can be used by the driver to test if the bus meets its conditions
@@ -250,18 +250,7 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
dev_set_drvdata (&dev->dev, data);
}
-/*flags for the driver struct: */
-#define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */
-#if 0
-/* this flag is gone -- there is a (optional) driver->detach_adapter
- * callback now which can be used instead */
-# define I2C_DF_DUMMY 0x02
-#endif
-
/*flags for the client struct: */
-#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
-#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */
- /* on an i2c_client */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
@@ -302,26 +291,20 @@ struct i2c_client_address_data {
extern int i2c_add_adapter(struct i2c_adapter *);
extern int i2c_del_adapter(struct i2c_adapter *);
-extern int i2c_add_driver(struct i2c_driver *);
+extern int i2c_register_driver(struct module *, struct i2c_driver *);
extern int i2c_del_driver(struct i2c_driver *);
+static inline int i2c_add_driver(struct i2c_driver *driver)
+{
+ return i2c_register_driver(THIS_MODULE, driver);
+}
+
extern int i2c_attach_client(struct i2c_client *);
extern int i2c_detach_client(struct i2c_client *);
-/* New function: This is to get an i2c_client-struct for controlling the
- client either by using i2c_control-function or having the
- client-module export functions that can be used with the i2c_client
- -struct. */
-extern struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
- struct i2c_client *prev);
-
-/* Should be used with new function
- extern struct i2c_client *i2c_get_client(int,int,struct i2c_client *);
- to make sure that client-struct is valid and that it is okay to access
- the i2c-client.
- returns -EACCES if client doesn't allow use (default)
- returns -EBUSY if client doesn't allow multiple use (default) and
- usage_count >0 */
+/* Should be used to make sure that client-struct is valid and that it
+ is okay to access the i2c-client.
+ returns -ENODEV if client has gone in the meantime */
extern int i2c_use_client(struct i2c_client *);
extern int i2c_release_client(struct i2c_client *);
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index d79c8a4bc4f8..9ba806796667 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -30,6 +30,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/workqueue.h> /* work_struct */
+#include <linux/mempool.h>
#include <asm/io.h>
#include <asm/semaphore.h> /* Needed for MUTEX init macros */
@@ -38,6 +39,355 @@
#define I2O_QUEUE_EMPTY 0xffffffff
/*
+ * Cache strategies
+ */
+
+/* The NULL strategy leaves everything up to the controller. This tends to be a
+ * pessimal but functional choice.
+ */
+#define CACHE_NULL 0
+/* Prefetch data when reading. We continually attempt to load the next 32 sectors
+ * into the controller cache.
+ */
+#define CACHE_PREFETCH 1
+/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors
+ * into the controller cache. When an I/O is less <= 8K we assume its probably
+ * not sequential and don't prefetch (default)
+ */
+#define CACHE_SMARTFETCH 2
+/* Data is written to the cache and then out on to the disk. The I/O must be
+ * physically on the medium before the write is acknowledged (default without
+ * NVRAM)
+ */
+#define CACHE_WRITETHROUGH 17
+/* Data is written to the cache and then out on to the disk. The controller
+ * is permitted to write back the cache any way it wants. (default if battery
+ * backed NVRAM is present). It can be useful to set this for swap regardless of
+ * battery state.
+ */
+#define CACHE_WRITEBACK 18
+/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
+ * write large I/O's directly to disk bypassing the cache to avoid the extra
+ * memory copy hits. Small writes are writeback cached
+ */
+#define CACHE_SMARTBACK 19
+/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
+ * write large I/O's directly to disk bypassing the cache to avoid the extra
+ * memory copy hits. Small writes are writethrough cached. Suitable for devices
+ * lacking battery backup
+ */
+#define CACHE_SMARTTHROUGH 20
+
+/*
+ * Ioctl structures
+ */
+
+#define BLKI2OGRSTRAT _IOR('2', 1, int)
+#define BLKI2OGWSTRAT _IOR('2', 2, int)
+#define BLKI2OSRSTRAT _IOW('2', 3, int)
+#define BLKI2OSWSTRAT _IOW('2', 4, int)
+
+/*
+ * I2O Function codes
+ */
+
+/*
+ * Executive Class
+ */
+#define I2O_CMD_ADAPTER_ASSIGN 0xB3
+#define I2O_CMD_ADAPTER_READ 0xB2
+#define I2O_CMD_ADAPTER_RELEASE 0xB5
+#define I2O_CMD_BIOS_INFO_SET 0xA5
+#define I2O_CMD_BOOT_DEVICE_SET 0xA7
+#define I2O_CMD_CONFIG_VALIDATE 0xBB
+#define I2O_CMD_CONN_SETUP 0xCA
+#define I2O_CMD_DDM_DESTROY 0xB1
+#define I2O_CMD_DDM_ENABLE 0xD5
+#define I2O_CMD_DDM_QUIESCE 0xC7
+#define I2O_CMD_DDM_RESET 0xD9
+#define I2O_CMD_DDM_SUSPEND 0xAF
+#define I2O_CMD_DEVICE_ASSIGN 0xB7
+#define I2O_CMD_DEVICE_RELEASE 0xB9
+#define I2O_CMD_HRT_GET 0xA8
+#define I2O_CMD_ADAPTER_CLEAR 0xBE
+#define I2O_CMD_ADAPTER_CONNECT 0xC9
+#define I2O_CMD_ADAPTER_RESET 0xBD
+#define I2O_CMD_LCT_NOTIFY 0xA2
+#define I2O_CMD_OUTBOUND_INIT 0xA1
+#define I2O_CMD_PATH_ENABLE 0xD3
+#define I2O_CMD_PATH_QUIESCE 0xC5
+#define I2O_CMD_PATH_RESET 0xD7
+#define I2O_CMD_STATIC_MF_CREATE 0xDD
+#define I2O_CMD_STATIC_MF_RELEASE 0xDF
+#define I2O_CMD_STATUS_GET 0xA0
+#define I2O_CMD_SW_DOWNLOAD 0xA9
+#define I2O_CMD_SW_UPLOAD 0xAB
+#define I2O_CMD_SW_REMOVE 0xAD
+#define I2O_CMD_SYS_ENABLE 0xD1
+#define I2O_CMD_SYS_MODIFY 0xC1
+#define I2O_CMD_SYS_QUIESCE 0xC3
+#define I2O_CMD_SYS_TAB_SET 0xA3
+
+/*
+ * Utility Class
+ */
+#define I2O_CMD_UTIL_NOP 0x00
+#define I2O_CMD_UTIL_ABORT 0x01
+#define I2O_CMD_UTIL_CLAIM 0x09
+#define I2O_CMD_UTIL_RELEASE 0x0B
+#define I2O_CMD_UTIL_PARAMS_GET 0x06
+#define I2O_CMD_UTIL_PARAMS_SET 0x05
+#define I2O_CMD_UTIL_EVT_REGISTER 0x13
+#define I2O_CMD_UTIL_EVT_ACK 0x14
+#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10
+#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D
+#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F
+#define I2O_CMD_UTIL_LOCK 0x17
+#define I2O_CMD_UTIL_LOCK_RELEASE 0x19
+#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15
+
+/*
+ * SCSI Host Bus Adapter Class
+ */
+#define I2O_CMD_SCSI_EXEC 0x81
+#define I2O_CMD_SCSI_ABORT 0x83
+#define I2O_CMD_SCSI_BUSRESET 0x27
+
+/*
+ * Bus Adapter Class
+ */
+#define I2O_CMD_BUS_ADAPTER_RESET 0x85
+#define I2O_CMD_BUS_RESET 0x87
+#define I2O_CMD_BUS_SCAN 0x89
+#define I2O_CMD_BUS_QUIESCE 0x8b
+
+/*
+ * Random Block Storage Class
+ */
+#define I2O_CMD_BLOCK_READ 0x30
+#define I2O_CMD_BLOCK_WRITE 0x31
+#define I2O_CMD_BLOCK_CFLUSH 0x37
+#define I2O_CMD_BLOCK_MLOCK 0x49
+#define I2O_CMD_BLOCK_MUNLOCK 0x4B
+#define I2O_CMD_BLOCK_MMOUNT 0x41
+#define I2O_CMD_BLOCK_MEJECT 0x43
+#define I2O_CMD_BLOCK_POWER 0x70
+
+#define I2O_CMD_PRIVATE 0xFF
+
+/* Command status values */
+
+#define I2O_CMD_IN_PROGRESS 0x01
+#define I2O_CMD_REJECTED 0x02
+#define I2O_CMD_FAILED 0x03
+#define I2O_CMD_COMPLETED 0x04
+
+/* I2O API function return values */
+
+#define I2O_RTN_NO_ERROR 0
+#define I2O_RTN_NOT_INIT 1
+#define I2O_RTN_FREE_Q_EMPTY 2
+#define I2O_RTN_TCB_ERROR 3
+#define I2O_RTN_TRANSACTION_ERROR 4
+#define I2O_RTN_ADAPTER_ALREADY_INIT 5
+#define I2O_RTN_MALLOC_ERROR 6
+#define I2O_RTN_ADPTR_NOT_REGISTERED 7
+#define I2O_RTN_MSG_REPLY_TIMEOUT 8
+#define I2O_RTN_NO_STATUS 9
+#define I2O_RTN_NO_FIRM_VER 10
+#define I2O_RTN_NO_LINK_SPEED 11
+
+/* Reply message status defines for all messages */
+
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
+#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
+#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
+#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
+#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08
+#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09
+#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B
+#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
+
+/* Status codes and Error Information for Parameter functions */
+
+#define I2O_PARAMS_STATUS_SUCCESS 0x00
+#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
+#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
+#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
+#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
+#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
+#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06
+#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07
+#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08
+#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09
+#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A
+#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B
+#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C
+#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D
+#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E
+#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F
+#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10
+
+/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error
+ * messages: Table 3-2 Detailed Status Codes.*/
+
+#define I2O_DSC_SUCCESS 0x0000
+#define I2O_DSC_BAD_KEY 0x0002
+#define I2O_DSC_TCL_ERROR 0x0003
+#define I2O_DSC_REPLY_BUFFER_FULL 0x0004
+#define I2O_DSC_NO_SUCH_PAGE 0x0005
+#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006
+#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007
+#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009
+#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A
+#define I2O_DSC_DEVICE_LOCKED 0x000B
+#define I2O_DSC_DEVICE_RESET 0x000C
+#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D
+#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E
+#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F
+#define I2O_DSC_INVALID_OFFSET 0x0010
+#define I2O_DSC_INVALID_PARAMETER 0x0011
+#define I2O_DSC_INVALID_REQUEST 0x0012
+#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013
+#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014
+#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015
+#define I2O_DSC_MISSING_PARAMETER 0x0016
+#define I2O_DSC_TIMEOUT 0x0017
+#define I2O_DSC_UNKNOWN_ERROR 0x0018
+#define I2O_DSC_UNKNOWN_FUNCTION 0x0019
+#define I2O_DSC_UNSUPPORTED_VERSION 0x001A
+#define I2O_DSC_DEVICE_BUSY 0x001B
+#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C
+
+/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed
+ Status Codes.*/
+
+#define I2O_BSA_DSC_SUCCESS 0x0000
+#define I2O_BSA_DSC_MEDIA_ERROR 0x0001
+#define I2O_BSA_DSC_ACCESS_ERROR 0x0002
+#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003
+#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004
+#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005
+#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006
+#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007
+#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008
+#define I2O_BSA_DSC_BUS_FAILURE 0x0009
+#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A
+#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B
+#define I2O_BSA_DSC_DEVICE_RESET 0x000C
+#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D
+#define I2O_BSA_DSC_TIMEOUT 0x000E
+
+/* FailureStatusCodes, Table 3-3 Message Failure Codes */
+
+#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81
+#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82
+#define I2O_FSC_TRANSPORT_CONGESTION 0x83
+#define I2O_FSC_TRANSPORT_FAILURE 0x84
+#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85
+#define I2O_FSC_TRANSPORT_TIME_OUT 0x86
+#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87
+#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88
+#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89
+#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A
+#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B
+#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C
+#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D
+#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E
+#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F
+#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF
+
+/* Device Claim Types */
+#define I2O_CLAIM_PRIMARY 0x01000000
+#define I2O_CLAIM_MANAGEMENT 0x02000000
+#define I2O_CLAIM_AUTHORIZED 0x03000000
+#define I2O_CLAIM_SECONDARY 0x04000000
+
+/* Message header defines for VersionOffset */
+#define I2OVER15 0x0001
+#define I2OVER20 0x0002
+
+/* Default is 1.5 */
+#define I2OVERSION I2OVER15
+
+#define SGL_OFFSET_0 I2OVERSION
+#define SGL_OFFSET_4 (0x0040 | I2OVERSION)
+#define SGL_OFFSET_5 (0x0050 | I2OVERSION)
+#define SGL_OFFSET_6 (0x0060 | I2OVERSION)
+#define SGL_OFFSET_7 (0x0070 | I2OVERSION)
+#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
+#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
+#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
+#define SGL_OFFSET_11 (0x00B0 | I2OVERSION)
+#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
+#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION)
+
+/* Transaction Reply Lists (TRL) Control Word structure */
+#define TRL_SINGLE_FIXED_LENGTH 0x00
+#define TRL_SINGLE_VARIABLE_LENGTH 0x40
+#define TRL_MULTIPLE_FIXED_LENGTH 0x80
+
+ /* msg header defines for MsgFlags */
+#define MSG_STATIC 0x0100
+#define MSG_64BIT_CNTXT 0x0200
+#define MSG_MULTI_TRANS 0x1000
+#define MSG_FAIL 0x2000
+#define MSG_FINAL 0x4000
+#define MSG_REPLY 0x8000
+
+ /* minimum size msg */
+#define THREE_WORD_MSG_SIZE 0x00030000
+#define FOUR_WORD_MSG_SIZE 0x00040000
+#define FIVE_WORD_MSG_SIZE 0x00050000
+#define SIX_WORD_MSG_SIZE 0x00060000
+#define SEVEN_WORD_MSG_SIZE 0x00070000
+#define EIGHT_WORD_MSG_SIZE 0x00080000
+#define NINE_WORD_MSG_SIZE 0x00090000
+#define TEN_WORD_MSG_SIZE 0x000A0000
+#define ELEVEN_WORD_MSG_SIZE 0x000B0000
+#define I2O_MESSAGE_SIZE(x) ((x)<<16)
+
+/* special TID assignments */
+#define ADAPTER_TID 0
+#define HOST_TID 1
+
+/* outbound queue defines */
+#define I2O_MAX_OUTBOUND_MSG_FRAMES 128
+#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
+
+/* inbound queue definitions */
+#define I2O_MSG_INPOOL_MIN 32
+#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
+
+#define I2O_POST_WAIT_OK 0
+#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
+
+#define I2O_CONTEXT_LIST_MIN_LENGTH 15
+#define I2O_CONTEXT_LIST_USED 0x01
+#define I2O_CONTEXT_LIST_DELETED 0x02
+
+/* timeouts */
+#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15
+#define I2O_TIMEOUT_MESSAGE_GET 5
+#define I2O_TIMEOUT_RESET 30
+#define I2O_TIMEOUT_STATUS_GET 5
+#define I2O_TIMEOUT_LCT_GET 360
+#define I2O_TIMEOUT_SCSI_SCB_ABORT 240
+
+/* retries */
+#define I2O_HRT_GET_TRIES 3
+#define I2O_LCT_GET_TRIES 3
+
+/* defines for max_sectors and max_phys_segments */
+#define I2O_MAX_SECTORS 1024
+#define I2O_MAX_SECTORS_LIMITED 128
+#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
+
+/*
* Message structures
*/
struct i2o_message {
@@ -58,6 +408,12 @@ struct i2o_message {
u32 body[0];
};
+/* MFA and I2O message used by mempool */
+struct i2o_msg_mfa {
+ u32 mfa; /* MFA returned by the controller */
+ struct i2o_message msg; /* I2O message */
+};
+
/*
* Each I2O device entity has one of these. There is one per device.
*/
@@ -130,6 +486,15 @@ struct i2o_dma {
};
/*
+ * Contains slab cache and mempool information
+ */
+struct i2o_pool {
+ char *name;
+ kmem_cache_t *slab;
+ mempool_t *mempool;
+};
+
+/*
* Contains IO mapped address information
*/
struct i2o_io {
@@ -174,8 +539,6 @@ struct i2o_controller {
void __iomem *irq_status; /* Interrupt status register address */
void __iomem *irq_mask; /* Interrupt mask register address */
- /* Dynamic LCT related data */
-
struct i2o_dma status; /* IOP status block */
struct i2o_dma hrt; /* HW Resource Table */
@@ -188,6 +551,8 @@ struct i2o_controller {
struct i2o_io in_queue; /* inbound message queue Host->IOP */
struct i2o_dma out_queue; /* outbound message queue IOP->Host */
+ struct i2o_pool in_msg; /* mempool for inbound messages */
+
unsigned int battery:1; /* Has a battery backup */
unsigned int io_alloc:1; /* An I/O resource was allocated */
unsigned int mem_alloc:1; /* A memory resource was allocated */
@@ -196,7 +561,6 @@ struct i2o_controller {
struct resource mem_resource; /* Mem resource allocated to the IOP */
struct device device;
- struct class_device *classdev; /* I2O controller class device */
struct i2o_device *exec; /* Executive */
#if BITS_PER_LONG == 64
spinlock_t context_list_lock; /* lock for context_list */
@@ -247,16 +611,13 @@ struct i2o_sys_tbl {
extern struct list_head i2o_controllers;
/* Message functions */
-static inline u32 i2o_msg_get(struct i2o_controller *,
- struct i2o_message __iomem **);
-extern u32 i2o_msg_get_wait(struct i2o_controller *,
- struct i2o_message __iomem **, int);
-static inline void i2o_msg_post(struct i2o_controller *, u32);
-static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
- unsigned long);
-extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
- struct i2o_dma *);
-extern void i2o_msg_nop(struct i2o_controller *, u32);
+static inline struct i2o_message *i2o_msg_get(struct i2o_controller *);
+extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int);
+static inline void i2o_msg_post(struct i2o_controller *, struct i2o_message *);
+static inline int i2o_msg_post_wait(struct i2o_controller *,
+ struct i2o_message *, unsigned long);
+extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *,
+ unsigned long, struct i2o_dma *);
static inline void i2o_flush_reply(struct i2o_controller *, u32);
/* IOP functions */
@@ -384,10 +745,10 @@ static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
size_t size,
enum dma_data_direction direction,
- u32 __iomem ** sg_ptr)
+ u32 ** sg_ptr)
{
u32 sg_flags;
- u32 __iomem *mptr = *sg_ptr;
+ u32 *mptr = *sg_ptr;
dma_addr_t dma_addr;
switch (direction) {
@@ -405,16 +766,16 @@ static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
if (!dma_mapping_error(dma_addr)) {
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
- writel(0x7C020002, mptr++);
- writel(PAGE_SIZE, mptr++);
+ *mptr++ = cpu_to_le32(0x7C020002);
+ *mptr++ = cpu_to_le32(PAGE_SIZE);
}
#endif
- writel(sg_flags | size, mptr++);
- writel(i2o_dma_low(dma_addr), mptr++);
+ *mptr++ = cpu_to_le32(sg_flags | size);
+ *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
if ((sizeof(dma_addr_t) > 4) && c->pae_support)
- writel(i2o_dma_high(dma_addr), mptr++);
+ *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));
#endif
*sg_ptr = mptr;
}
@@ -439,10 +800,10 @@ static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
static inline int i2o_dma_map_sg(struct i2o_controller *c,
struct scatterlist *sg, int sg_count,
enum dma_data_direction direction,
- u32 __iomem ** sg_ptr)
+ u32 ** sg_ptr)
{
u32 sg_flags;
- u32 __iomem *mptr = *sg_ptr;
+ u32 *mptr = *sg_ptr;
switch (direction) {
case DMA_TO_DEVICE:
@@ -461,19 +822,19 @@ static inline int i2o_dma_map_sg(struct i2o_controller *c,
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
- writel(0x7C020002, mptr++);
- writel(PAGE_SIZE, mptr++);
+ *mptr++ = cpu_to_le32(0x7C020002);
+ *mptr++ = cpu_to_le32(PAGE_SIZE);
}
#endif
while (sg_count-- > 0) {
if (!sg_count)
sg_flags |= 0xC0000000;
- writel(sg_flags | sg_dma_len(sg), mptr++);
- writel(i2o_dma_low(sg_dma_address(sg)), mptr++);
+ *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));
+ *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
if ((sizeof(dma_addr_t) > 4) && c->pae_support)
- writel(i2o_dma_high(sg_dma_address(sg)), mptr++);
+ *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
#endif
sg++;
}
@@ -563,6 +924,64 @@ static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
return 0;
};
+/*
+ * i2o_pool_alloc - Allocate an slab cache and mempool
+ * @mempool: pointer to struct i2o_pool to write data into.
+ * @name: name which is used to identify cache
+ * @size: size of each object
+ * @min_nr: minimum number of objects
+ *
+ * First allocates a slab cache with name and size. Then allocates a
+ * mempool which uses the slab cache for allocation and freeing.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static inline int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
+ size_t size, int min_nr)
+{
+ pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (!pool->name)
+ goto exit;
+ strcpy(pool->name, name);
+
+ pool->slab =
+ kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL,
+ NULL);
+ if (!pool->slab)
+ goto free_name;
+
+ pool->mempool =
+ mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab,
+ pool->slab);
+ if (!pool->mempool)
+ goto free_slab;
+
+ return 0;
+
+ free_slab:
+ kmem_cache_destroy(pool->slab);
+
+ free_name:
+ kfree(pool->name);
+
+ exit:
+ return -ENOMEM;
+};
+
+/*
+ * i2o_pool_free - Free slab cache and mempool again
+ * @mempool: pointer to struct i2o_pool which should be freed
+ *
+ * Note that you have to return all objects to the mempool again before
+ * calling i2o_pool_free().
+ */
+static inline void i2o_pool_free(struct i2o_pool *pool)
+{
+ mempool_destroy(pool->mempool);
+ kmem_cache_destroy(pool->slab);
+ kfree(pool->name);
+};
+
/* I2O driver (OSM) functions */
extern int i2o_driver_register(struct i2o_driver *);
extern void i2o_driver_unregister(struct i2o_driver *);
@@ -638,39 +1057,89 @@ extern int i2o_exec_lct_get(struct i2o_controller *);
#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj))
/**
+ * i2o_out_to_virt - Turn an I2O message to a virtual address
+ * @c: controller
+ * @m: message engine value
+ *
+ * Turn a receive message from an I2O controller bus address into
+ * a Linux virtual address. The shared page frame is a linear block
+ * so we simply have to shift the offset. This function does not
+ * work for sender side messages as they are ioremap objects
+ * provided by the I2O controller.
+ */
+static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
+ u32 m)
+{
+ BUG_ON(m < c->out_queue.phys
+ || m >= c->out_queue.phys + c->out_queue.len);
+
+ return c->out_queue.virt + (m - c->out_queue.phys);
+};
+
+/**
+ * i2o_msg_in_to_virt - Turn an I2O message to a virtual address
+ * @c: controller
+ * @m: message engine value
+ *
+ * Turn a send message from an I2O controller bus address into
+ * a Linux virtual address. The shared page frame is a linear block
+ * so we simply have to shift the offset. This function does not
+ * work for receive side messages as they are kmalloc objects
+ * in a different pool.
+ */
+static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
+ i2o_controller *c,
+ u32 m)
+{
+ return c->in_queue.virt + m;
+};
+
+/**
* i2o_msg_get - obtain an I2O message from the IOP
* @c: I2O controller
- * @msg: pointer to a I2O message pointer
*
- * This function tries to get a message slot. If no message slot is
+ * This function tries to get a message frame. If no message frame is
* available do not wait until one is availabe (see also i2o_msg_get_wait).
+ * The returned pointer to the message frame is not in I/O memory, it is
+ * allocated from a mempool. But because a MFA is allocated from the
+ * controller too it is guaranteed that i2o_msg_post() will never fail.
*
- * On a success the message is returned and the pointer to the message is
- * set in msg. The returned message is the physical page frame offset
- * address from the read port (see the i2o spec). If no message is
- * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
+ * On a success a pointer to the message frame is returned. If the message
+ * queue is empty -EBUSY is returned and if no memory is available -ENOMEM
+ * is returned.
*/
-static inline u32 i2o_msg_get(struct i2o_controller *c,
- struct i2o_message __iomem ** msg)
+static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c)
{
- u32 m = readl(c->in_port);
-
- if (m != I2O_QUEUE_EMPTY)
- *msg = c->in_queue.virt + m;
+ struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC);
+ if (!mmsg)
+ return ERR_PTR(-ENOMEM);
+
+ mmsg->mfa = readl(c->in_port);
+ if (mmsg->mfa == I2O_QUEUE_EMPTY) {
+ mempool_free(mmsg, c->in_msg.mempool);
+ return ERR_PTR(-EBUSY);
+ }
- return m;
+ return &mmsg->msg;
};
/**
* i2o_msg_post - Post I2O message to I2O controller
* @c: I2O controller to which the message should be send
- * @m: the message identifier
+ * @msg: message returned by i2o_msg_get()
*
- * Post the message to the I2O controller.
+ * Post the message to the I2O controller and return immediately.
*/
-static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
+static inline void i2o_msg_post(struct i2o_controller *c,
+ struct i2o_message *msg)
{
- writel(m, c->in_port);
+ struct i2o_msg_mfa *mmsg;
+
+ mmsg = container_of(msg, struct i2o_msg_mfa, msg);
+ memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg,
+ (le32_to_cpu(msg->u.head[0]) >> 16) << 2);
+ writel(mmsg->mfa, c->in_port);
+ mempool_free(mmsg, c->in_msg.mempool);
};
/**
@@ -685,62 +1154,66 @@ static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
*
* Returns 0 on success or negative error code on failure.
*/
-static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
+static inline int i2o_msg_post_wait(struct i2o_controller *c,
+ struct i2o_message *msg,
unsigned long timeout)
{
- return i2o_msg_post_wait_mem(c, m, timeout, NULL);
+ return i2o_msg_post_wait_mem(c, msg, timeout, NULL);
};
/**
- * i2o_flush_reply - Flush reply from I2O controller
- * @c: I2O controller
- * @m: the message identifier
+ * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller
+ * @c: I2O controller from which the MFA was fetched
+ * @mfa: MFA which should be returned
*
- * The I2O controller must be informed that the reply message is not needed
- * anymore. If you forget to flush the reply, the message frame can't be
- * used by the controller anymore and is therefore lost.
+ * This function must be used for preserved messages, because i2o_msg_nop()
+ * also returns the allocated memory back to the msg_pool mempool.
*/
-static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
+static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa)
{
- writel(m, c->out_port);
+ struct i2o_message __iomem *msg;
+ u32 nop[3] = {
+ THREE_WORD_MSG_SIZE | SGL_OFFSET_0,
+ I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
+ 0x00000000
+ };
+
+ msg = i2o_msg_in_to_virt(c, mfa);
+ memcpy_toio(msg, nop, sizeof(nop));
+ writel(mfa, c->in_port);
};
/**
- * i2o_out_to_virt - Turn an I2O message to a virtual address
- * @c: controller
- * @m: message engine value
+ * i2o_msg_nop - Returns a message which is not used
+ * @c: I2O controller from which the message was created
+ * @msg: message which should be returned
*
- * Turn a receive message from an I2O controller bus address into
- * a Linux virtual address. The shared page frame is a linear block
- * so we simply have to shift the offset. This function does not
- * work for sender side messages as they are ioremap objects
- * provided by the I2O controller.
+ * If you fetch a message via i2o_msg_get, and can't use it, you must
+ * return the message with this function. Otherwise the MFA is lost as well
+ * as the allocated memory from the mempool.
*/
-static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
- u32 m)
+static inline void i2o_msg_nop(struct i2o_controller *c,
+ struct i2o_message *msg)
{
- BUG_ON(m < c->out_queue.phys
- || m >= c->out_queue.phys + c->out_queue.len);
+ struct i2o_msg_mfa *mmsg;
+ mmsg = container_of(msg, struct i2o_msg_mfa, msg);
- return c->out_queue.virt + (m - c->out_queue.phys);
+ i2o_msg_nop_mfa(c, mmsg->mfa);
+ mempool_free(mmsg, c->in_msg.mempool);
};
/**
- * i2o_msg_in_to_virt - Turn an I2O message to a virtual address
- * @c: controller
- * @m: message engine value
+ * i2o_flush_reply - Flush reply from I2O controller
+ * @c: I2O controller
+ * @m: the message identifier
*
- * Turn a send message from an I2O controller bus address into
- * a Linux virtual address. The shared page frame is a linear block
- * so we simply have to shift the offset. This function does not
- * work for receive side messages as they are kmalloc objects
- * in a different pool.
+ * The I2O controller must be informed that the reply message is not needed
+ * anymore. If you forget to flush the reply, the message frame can't be
+ * used by the controller anymore and is therefore lost.
*/
-static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
- i2o_controller *c,
- u32 m)
+static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
{
- return c->in_queue.virt + m;
+ writel(m, c->out_port);
};
/*
@@ -779,350 +1252,5 @@ extern void i2o_dump_message(struct i2o_message *);
extern void i2o_dump_hrt(struct i2o_controller *c);
extern void i2o_debug_state(struct i2o_controller *c);
-/*
- * Cache strategies
- */
-
-/* The NULL strategy leaves everything up to the controller. This tends to be a
- * pessimal but functional choice.
- */
-#define CACHE_NULL 0
-/* Prefetch data when reading. We continually attempt to load the next 32 sectors
- * into the controller cache.
- */
-#define CACHE_PREFETCH 1
-/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors
- * into the controller cache. When an I/O is less <= 8K we assume its probably
- * not sequential and don't prefetch (default)
- */
-#define CACHE_SMARTFETCH 2
-/* Data is written to the cache and then out on to the disk. The I/O must be
- * physically on the medium before the write is acknowledged (default without
- * NVRAM)
- */
-#define CACHE_WRITETHROUGH 17
-/* Data is written to the cache and then out on to the disk. The controller
- * is permitted to write back the cache any way it wants. (default if battery
- * backed NVRAM is present). It can be useful to set this for swap regardless of
- * battery state.
- */
-#define CACHE_WRITEBACK 18
-/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
- * write large I/O's directly to disk bypassing the cache to avoid the extra
- * memory copy hits. Small writes are writeback cached
- */
-#define CACHE_SMARTBACK 19
-/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
- * write large I/O's directly to disk bypassing the cache to avoid the extra
- * memory copy hits. Small writes are writethrough cached. Suitable for devices
- * lacking battery backup
- */
-#define CACHE_SMARTTHROUGH 20
-
-/*
- * Ioctl structures
- */
-
-#define BLKI2OGRSTRAT _IOR('2', 1, int)
-#define BLKI2OGWSTRAT _IOR('2', 2, int)
-#define BLKI2OSRSTRAT _IOW('2', 3, int)
-#define BLKI2OSWSTRAT _IOW('2', 4, int)
-
-/*
- * I2O Function codes
- */
-
-/*
- * Executive Class
- */
-#define I2O_CMD_ADAPTER_ASSIGN 0xB3
-#define I2O_CMD_ADAPTER_READ 0xB2
-#define I2O_CMD_ADAPTER_RELEASE 0xB5
-#define I2O_CMD_BIOS_INFO_SET 0xA5
-#define I2O_CMD_BOOT_DEVICE_SET 0xA7
-#define I2O_CMD_CONFIG_VALIDATE 0xBB
-#define I2O_CMD_CONN_SETUP 0xCA
-#define I2O_CMD_DDM_DESTROY 0xB1
-#define I2O_CMD_DDM_ENABLE 0xD5
-#define I2O_CMD_DDM_QUIESCE 0xC7
-#define I2O_CMD_DDM_RESET 0xD9
-#define I2O_CMD_DDM_SUSPEND 0xAF
-#define I2O_CMD_DEVICE_ASSIGN 0xB7
-#define I2O_CMD_DEVICE_RELEASE 0xB9
-#define I2O_CMD_HRT_GET 0xA8
-#define I2O_CMD_ADAPTER_CLEAR 0xBE
-#define I2O_CMD_ADAPTER_CONNECT 0xC9
-#define I2O_CMD_ADAPTER_RESET 0xBD
-#define I2O_CMD_LCT_NOTIFY 0xA2
-#define I2O_CMD_OUTBOUND_INIT 0xA1
-#define I2O_CMD_PATH_ENABLE 0xD3
-#define I2O_CMD_PATH_QUIESCE 0xC5
-#define I2O_CMD_PATH_RESET 0xD7
-#define I2O_CMD_STATIC_MF_CREATE 0xDD
-#define I2O_CMD_STATIC_MF_RELEASE 0xDF
-#define I2O_CMD_STATUS_GET 0xA0
-#define I2O_CMD_SW_DOWNLOAD 0xA9
-#define I2O_CMD_SW_UPLOAD 0xAB
-#define I2O_CMD_SW_REMOVE 0xAD
-#define I2O_CMD_SYS_ENABLE 0xD1
-#define I2O_CMD_SYS_MODIFY 0xC1
-#define I2O_CMD_SYS_QUIESCE 0xC3
-#define I2O_CMD_SYS_TAB_SET 0xA3
-
-/*
- * Utility Class
- */
-#define I2O_CMD_UTIL_NOP 0x00
-#define I2O_CMD_UTIL_ABORT 0x01
-#define I2O_CMD_UTIL_CLAIM 0x09
-#define I2O_CMD_UTIL_RELEASE 0x0B
-#define I2O_CMD_UTIL_PARAMS_GET 0x06
-#define I2O_CMD_UTIL_PARAMS_SET 0x05
-#define I2O_CMD_UTIL_EVT_REGISTER 0x13
-#define I2O_CMD_UTIL_EVT_ACK 0x14
-#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10
-#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D
-#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F
-#define I2O_CMD_UTIL_LOCK 0x17
-#define I2O_CMD_UTIL_LOCK_RELEASE 0x19
-#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15
-
-/*
- * SCSI Host Bus Adapter Class
- */
-#define I2O_CMD_SCSI_EXEC 0x81
-#define I2O_CMD_SCSI_ABORT 0x83
-#define I2O_CMD_SCSI_BUSRESET 0x27
-
-/*
- * Bus Adapter Class
- */
-#define I2O_CMD_BUS_ADAPTER_RESET 0x85
-#define I2O_CMD_BUS_RESET 0x87
-#define I2O_CMD_BUS_SCAN 0x89
-#define I2O_CMD_BUS_QUIESCE 0x8b
-
-/*
- * Random Block Storage Class
- */
-#define I2O_CMD_BLOCK_READ 0x30
-#define I2O_CMD_BLOCK_WRITE 0x31
-#define I2O_CMD_BLOCK_CFLUSH 0x37
-#define I2O_CMD_BLOCK_MLOCK 0x49
-#define I2O_CMD_BLOCK_MUNLOCK 0x4B
-#define I2O_CMD_BLOCK_MMOUNT 0x41
-#define I2O_CMD_BLOCK_MEJECT 0x43
-#define I2O_CMD_BLOCK_POWER 0x70
-
-#define I2O_CMD_PRIVATE 0xFF
-
-/* Command status values */
-
-#define I2O_CMD_IN_PROGRESS 0x01
-#define I2O_CMD_REJECTED 0x02
-#define I2O_CMD_FAILED 0x03
-#define I2O_CMD_COMPLETED 0x04
-
-/* I2O API function return values */
-
-#define I2O_RTN_NO_ERROR 0
-#define I2O_RTN_NOT_INIT 1
-#define I2O_RTN_FREE_Q_EMPTY 2
-#define I2O_RTN_TCB_ERROR 3
-#define I2O_RTN_TRANSACTION_ERROR 4
-#define I2O_RTN_ADAPTER_ALREADY_INIT 5
-#define I2O_RTN_MALLOC_ERROR 6
-#define I2O_RTN_ADPTR_NOT_REGISTERED 7
-#define I2O_RTN_MSG_REPLY_TIMEOUT 8
-#define I2O_RTN_NO_STATUS 9
-#define I2O_RTN_NO_FIRM_VER 10
-#define I2O_RTN_NO_LINK_SPEED 11
-
-/* Reply message status defines for all messages */
-
-#define I2O_REPLY_STATUS_SUCCESS 0x00
-#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
-#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
-#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
-#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
-#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
-#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
-#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08
-#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09
-#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A
-#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B
-#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
-
-/* Status codes and Error Information for Parameter functions */
-
-#define I2O_PARAMS_STATUS_SUCCESS 0x00
-#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
-#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
-#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
-#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
-#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
-#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06
-#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07
-#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08
-#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09
-#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A
-#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B
-#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C
-#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D
-#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E
-#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F
-#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10
-
-/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error
- * messages: Table 3-2 Detailed Status Codes.*/
-
-#define I2O_DSC_SUCCESS 0x0000
-#define I2O_DSC_BAD_KEY 0x0002
-#define I2O_DSC_TCL_ERROR 0x0003
-#define I2O_DSC_REPLY_BUFFER_FULL 0x0004
-#define I2O_DSC_NO_SUCH_PAGE 0x0005
-#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006
-#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007
-#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009
-#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A
-#define I2O_DSC_DEVICE_LOCKED 0x000B
-#define I2O_DSC_DEVICE_RESET 0x000C
-#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D
-#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E
-#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F
-#define I2O_DSC_INVALID_OFFSET 0x0010
-#define I2O_DSC_INVALID_PARAMETER 0x0011
-#define I2O_DSC_INVALID_REQUEST 0x0012
-#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013
-#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014
-#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015
-#define I2O_DSC_MISSING_PARAMETER 0x0016
-#define I2O_DSC_TIMEOUT 0x0017
-#define I2O_DSC_UNKNOWN_ERROR 0x0018
-#define I2O_DSC_UNKNOWN_FUNCTION 0x0019
-#define I2O_DSC_UNSUPPORTED_VERSION 0x001A
-#define I2O_DSC_DEVICE_BUSY 0x001B
-#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C
-
-/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed
- Status Codes.*/
-
-#define I2O_BSA_DSC_SUCCESS 0x0000
-#define I2O_BSA_DSC_MEDIA_ERROR 0x0001
-#define I2O_BSA_DSC_ACCESS_ERROR 0x0002
-#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003
-#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004
-#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005
-#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006
-#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007
-#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008
-#define I2O_BSA_DSC_BUS_FAILURE 0x0009
-#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A
-#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B
-#define I2O_BSA_DSC_DEVICE_RESET 0x000C
-#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D
-#define I2O_BSA_DSC_TIMEOUT 0x000E
-
-/* FailureStatusCodes, Table 3-3 Message Failure Codes */
-
-#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81
-#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82
-#define I2O_FSC_TRANSPORT_CONGESTION 0x83
-#define I2O_FSC_TRANSPORT_FAILURE 0x84
-#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85
-#define I2O_FSC_TRANSPORT_TIME_OUT 0x86
-#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87
-#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88
-#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89
-#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A
-#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B
-#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C
-#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D
-#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E
-#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F
-#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF
-
-/* Device Claim Types */
-#define I2O_CLAIM_PRIMARY 0x01000000
-#define I2O_CLAIM_MANAGEMENT 0x02000000
-#define I2O_CLAIM_AUTHORIZED 0x03000000
-#define I2O_CLAIM_SECONDARY 0x04000000
-
-/* Message header defines for VersionOffset */
-#define I2OVER15 0x0001
-#define I2OVER20 0x0002
-
-/* Default is 1.5 */
-#define I2OVERSION I2OVER15
-
-#define SGL_OFFSET_0 I2OVERSION
-#define SGL_OFFSET_4 (0x0040 | I2OVERSION)
-#define SGL_OFFSET_5 (0x0050 | I2OVERSION)
-#define SGL_OFFSET_6 (0x0060 | I2OVERSION)
-#define SGL_OFFSET_7 (0x0070 | I2OVERSION)
-#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
-#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
-#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
-#define SGL_OFFSET_11 (0x00B0 | I2OVERSION)
-#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
-#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION)
-
-/* Transaction Reply Lists (TRL) Control Word structure */
-#define TRL_SINGLE_FIXED_LENGTH 0x00
-#define TRL_SINGLE_VARIABLE_LENGTH 0x40
-#define TRL_MULTIPLE_FIXED_LENGTH 0x80
-
- /* msg header defines for MsgFlags */
-#define MSG_STATIC 0x0100
-#define MSG_64BIT_CNTXT 0x0200
-#define MSG_MULTI_TRANS 0x1000
-#define MSG_FAIL 0x2000
-#define MSG_FINAL 0x4000
-#define MSG_REPLY 0x8000
-
- /* minimum size msg */
-#define THREE_WORD_MSG_SIZE 0x00030000
-#define FOUR_WORD_MSG_SIZE 0x00040000
-#define FIVE_WORD_MSG_SIZE 0x00050000
-#define SIX_WORD_MSG_SIZE 0x00060000
-#define SEVEN_WORD_MSG_SIZE 0x00070000
-#define EIGHT_WORD_MSG_SIZE 0x00080000
-#define NINE_WORD_MSG_SIZE 0x00090000
-#define TEN_WORD_MSG_SIZE 0x000A0000
-#define ELEVEN_WORD_MSG_SIZE 0x000B0000
-#define I2O_MESSAGE_SIZE(x) ((x)<<16)
-
-/* special TID assignments */
-#define ADAPTER_TID 0
-#define HOST_TID 1
-
-/* outbound queue defines */
-#define I2O_MAX_OUTBOUND_MSG_FRAMES 128
-#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
-
-#define I2O_POST_WAIT_OK 0
-#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
-
-#define I2O_CONTEXT_LIST_MIN_LENGTH 15
-#define I2O_CONTEXT_LIST_USED 0x01
-#define I2O_CONTEXT_LIST_DELETED 0x02
-
-/* timeouts */
-#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15
-#define I2O_TIMEOUT_MESSAGE_GET 5
-#define I2O_TIMEOUT_RESET 30
-#define I2O_TIMEOUT_STATUS_GET 5
-#define I2O_TIMEOUT_LCT_GET 360
-#define I2O_TIMEOUT_SCSI_SCB_ABORT 240
-
-/* retries */
-#define I2O_HRT_GET_TRIES 3
-#define I2O_LCT_GET_TRIES 3
-
-/* defines for max_sectors and max_phys_segments */
-#define I2O_MAX_SECTORS 1024
-#define I2O_MAX_SECTORS_LIMITED 256
-#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
-
#endif /* __KERNEL__ */
#endif /* _I2O_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 7b6a6a58e465..110b3cfac021 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -18,6 +18,7 @@
#include <linux/bio.h>
#include <linux/device.h>
#include <linux/pci.h>
+#include <linux/completion.h>
#include <asm/byteorder.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -638,7 +639,7 @@ typedef struct ide_drive_s {
int crc_count; /* crc counter to reduce drive speed */
struct list_head list;
struct device gendev;
- struct semaphore gendev_rel_sem; /* to deal with device release() */
+ struct completion gendev_rel_comp; /* to deal with device release() */
} ide_drive_t;
#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
@@ -794,14 +795,14 @@ typedef struct hwif_s {
unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */
struct device gendev;
- struct semaphore gendev_rel_sem; /* To deal with device release() */
+ struct completion gendev_rel_comp; /* To deal with device release() */
void *hwif_data; /* extra hwif data */
unsigned dma;
void (*led_act)(void *data, int rw);
-} ____cacheline_maxaligned_in_smp ide_hwif_t;
+} ____cacheline_internodealigned_in_smp ide_hwif_t;
/*
* internal ide interrupt handler type
@@ -982,8 +983,13 @@ typedef struct ide_driver_s {
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
ide_proc_entry_t *proc;
struct device_driver gen_driver;
+ int (*probe)(ide_drive_t *);
+ void (*remove)(ide_drive_t *);
+ void (*shutdown)(ide_drive_t *);
} ide_driver_t;
+#define to_ide_driver(drv) container_of(drv, ide_driver_t, gen_driver)
+
int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
/*
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index fe26d431de87..7a92c1ce1457 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -72,6 +72,7 @@
* over Ethernet
*/
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
+#define ETH_P_TIPC 0x88CA /* TIPC */
/*
* Non DIX types. Won't clash for 1500 types.
diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h
index 511999c7eeda..395f0aad9cbf 100644
--- a/include/linux/if_frad.h
+++ b/include/linux/if_frad.h
@@ -131,17 +131,17 @@ struct frad_conf
/* these are the fields of an RFC 1490 header */
struct frhdr
{
- unsigned char control __attribute__((packed));
+ unsigned char control;
/* for IP packets, this can be the NLPID */
- unsigned char pad __attribute__((packed));
+ unsigned char pad;
- unsigned char NLPID __attribute__((packed));
- unsigned char OUI[3] __attribute__((packed));
- unsigned short PID __attribute__((packed));
+ unsigned char NLPID;
+ unsigned char OUI[3];
+ unsigned short PID;
#define IP_NLPID pad
-};
+} __attribute__((packed));
/* see RFC 1490 for the definition of the following */
#define FRAD_I_UI 0x03
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index e677f73f13dd..4fab3d0a4bce 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -157,8 +157,7 @@ struct pppox_proto {
extern int register_pppox_proto(int proto_num, struct pppox_proto *pp);
extern void unregister_pppox_proto(int proto_num);
extern void pppox_unbind_sock(struct sock *sk);/* delete ppp-channel binding */
-extern int pppox_channel_ioctl(struct ppp_channel *pc, unsigned int cmd,
- unsigned long arg);
+extern int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
/* PPPoX socket states */
enum {
diff --git a/include/linux/inet.h b/include/linux/inet.h
index 3b5e9fdff872..6c5587af118d 100644
--- a/include/linux/inet.h
+++ b/include/linux/inet.h
@@ -45,6 +45,6 @@
#ifdef __KERNEL__
#include <linux/types.h>
-extern __u32 in_aton(const char *str);
+extern __be32 in_aton(const char *str);
#endif
#endif /* _LINUX_INET_H */
diff --git a/include/linux/init.h b/include/linux/init.h
index 59008c3826cf..ff8d8b8632f4 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -241,6 +241,18 @@ void __init parse_early_param(void);
#define __cpuexitdata __exitdata
#endif
+#ifdef CONFIG_MEMORY_HOTPLUG
+#define __meminit
+#define __meminitdata
+#define __memexit
+#define __memexitdata
+#else
+#define __meminit __init
+#define __meminitdata __initdata
+#define __memexit __exit
+#define __memexitdata __exitdata
+#endif
+
/* Functions marked as __devexit may be discarded at kernel link time, depending
on config options. Newer versions of binutils detect references from
retained sections to discarded sections and flag an error. Pointers to
diff --git a/include/linux/input.h b/include/linux/input.h
index 3c5823368ddb..6d4cc3c110d6 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -13,6 +13,7 @@
#include <linux/time.h>
#include <linux/list.h>
#include <linux/device.h>
+#include <linux/mod_devicetable.h>
#else
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -511,6 +512,8 @@ struct input_absinfo {
#define KEY_FN_S 0x1e3
#define KEY_FN_B 0x1e4
+/* We avoid low common keys in module aliases so they don't get huge. */
+#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x1ff
/*
@@ -793,6 +796,44 @@ struct ff_effect {
#define FF_MAX 0x7f
+struct input_device_id {
+
+ kernel_ulong_t flags;
+
+ struct input_id id;
+
+ kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
+ kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
+
+ kernel_ulong_t driver_info;
+};
+
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
+#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
+
#ifdef __KERNEL__
/*
@@ -901,49 +942,11 @@ struct input_dev {
};
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
-/*
- * Structure for hotplug & device<->driver matching.
- */
-
-#define INPUT_DEVICE_ID_MATCH_BUS 1
-#define INPUT_DEVICE_ID_MATCH_VENDOR 2
-#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
-#define INPUT_DEVICE_ID_MATCH_VERSION 8
-
-#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
-#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
-#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
-#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
-#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
-#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
-#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
-#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
-#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
-
#define INPUT_DEVICE_ID_MATCH_DEVICE\
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
-struct input_device_id {
-
- unsigned long flags;
-
- struct input_id id;
-
- unsigned long evbit[NBITS(EV_MAX)];
- unsigned long keybit[NBITS(KEY_MAX)];
- unsigned long relbit[NBITS(REL_MAX)];
- unsigned long absbit[NBITS(ABS_MAX)];
- unsigned long mscbit[NBITS(MSC_MAX)];
- 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;
-};
-
struct input_handle;
struct input_handler {
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 41f150a3d2dd..2c08fdc2bdf7 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -79,7 +79,7 @@ static inline void __deprecated save_flags(unsigned long *x)
{
local_save_flags(*x);
}
-#define save_flags(x) save_flags(&x);
+#define save_flags(x) save_flags(&x)
static inline void __deprecated restore_flags(unsigned long x)
{
local_irq_restore(x);
@@ -112,7 +112,7 @@ enum
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
- SCSI_SOFTIRQ,
+ BLOCK_SOFTIRQ,
TASKLET_SOFTIRQ
};
diff --git a/include/linux/ioc3.h b/include/linux/ioc3.h
new file mode 100644
index 000000000000..e7906a72a4f1
--- /dev/null
+++ b/include/linux/ioc3.h
@@ -0,0 +1,93 @@
+/*
+ * 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 Stanislaw Skowronek <skylark@linux-mips.org>
+ */
+
+#ifndef _LINUX_IOC3_H
+#define _LINUX_IOC3_H
+
+#include <asm/sn/ioc3.h>
+
+#define IOC3_MAX_SUBMODULES 32
+
+#define IOC3_CLASS_NONE 0
+#define IOC3_CLASS_BASE_IP27 1
+#define IOC3_CLASS_BASE_IP30 2
+#define IOC3_CLASS_MENET_123 3
+#define IOC3_CLASS_MENET_4 4
+#define IOC3_CLASS_CADDUO 5
+#define IOC3_CLASS_SERIAL 6
+
+/* One of these per IOC3 */
+struct ioc3_driver_data {
+ struct list_head list;
+ int id; /* IOC3 sequence number */
+ /* PCI mapping */
+ unsigned long pma; /* physical address */
+ struct __iomem ioc3 *vma; /* pointer to registers */
+ struct pci_dev *pdev; /* PCI device */
+ /* IRQ stuff */
+ int dual_irq; /* set if separate IRQs are used */
+ int irq_io, irq_eth; /* IRQ numbers */
+ /* GPIO magic */
+ spinlock_t gpio_lock;
+ unsigned int gpdr_shadow;
+ /* NIC identifiers */
+ char nic_part[32];
+ char nic_serial[16];
+ char nic_mac[6];
+ /* submodule set */
+ int class;
+ void *data[IOC3_MAX_SUBMODULES]; /* for submodule use */
+ int active[IOC3_MAX_SUBMODULES]; /* set if probe succeeds */
+ /* is_ir_lock must be held while
+ * modifying sio_ie values, so
+ * we can be sure that sio_ie is
+ * not changing when we read it
+ * along with sio_ir.
+ */
+ spinlock_t ir_lock; /* SIO_IE[SC] mod lock */
+};
+
+/* One per submodule */
+struct ioc3_submodule {
+ char *name; /* descriptive submodule name */
+ struct module *owner; /* owning kernel module */
+ int ethernet; /* set for ethernet drivers */
+ int (*probe) (struct ioc3_submodule *, struct ioc3_driver_data *);
+ int (*remove) (struct ioc3_submodule *, struct ioc3_driver_data *);
+ int id; /* assigned by IOC3, index for the "data" array */
+ /* IRQ stuff */
+ unsigned int irq_mask; /* IOC3 IRQ mask, leave clear for Ethernet */
+ int reset_mask; /* non-zero if you want the ioc3.c module to reset interrupts */
+ int (*intr) (struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int, struct pt_regs *);
+ /* private submodule data */
+ void *data; /* assigned by submodule */
+};
+
+/**********************************
+ * Functions needed by submodules *
+ **********************************/
+
+#define IOC3_W_IES 0
+#define IOC3_W_IEC 1
+
+/* registers a submodule for all existing and future IOC3 chips */
+extern int ioc3_register_submodule(struct ioc3_submodule *);
+/* unregisters a submodule */
+extern void ioc3_unregister_submodule(struct ioc3_submodule *);
+/* enables IRQs indicated by irq_mask for a specified IOC3 chip */
+extern void ioc3_enable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
+/* ackowledges specified IRQs */
+extern void ioc3_ack(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
+/* disables IRQs indicated by irq_mask for a specified IOC3 chip */
+extern void ioc3_disable(struct ioc3_submodule *, struct ioc3_driver_data *, unsigned int);
+/* atomically sets GPCR bits */
+extern void ioc3_gpcr_set(struct ioc3_driver_data *, unsigned int);
+/* general ireg writer */
+extern void ioc3_write_ireg(struct ioc3_driver_data *idd, uint32_t value, int reg);
+
+#endif
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 33e8a19a1a0f..4b55cf1df732 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -16,6 +16,7 @@
*/
#ifndef _LINUX_IP_H
#define _LINUX_IP_H
+#include <linux/types.h>
#include <asm/byteorder.h>
#define IPTOS_TOS_MASK 0x1E
@@ -78,126 +79,6 @@
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
-#ifdef __KERNEL__
-#include <linux/config.h>
-#include <linux/types.h>
-#include <net/request_sock.h>
-#include <net/sock.h>
-#include <linux/igmp.h>
-#include <net/flow.h>
-
-struct ip_options {
- __u32 faddr; /* Saved first hop address */
- unsigned char optlen;
- unsigned char srr;
- unsigned char rr;
- unsigned char ts;
- unsigned char is_setbyuser:1, /* Set by setsockopt? */
- is_data:1, /* Options in __data, rather than skb */
- is_strictroute:1, /* Strict source route */
- srr_is_hit:1, /* Packet destination addr was our one */
- is_changed:1, /* IP checksum more not valid */
- rr_needaddr:1, /* Need to record addr of outgoing dev */
- ts_needtime:1, /* Need to record timestamp */
- ts_needaddr:1; /* Need to record addr of outgoing dev */
- unsigned char router_alert;
- unsigned char __pad1;
- unsigned char __pad2;
- unsigned char __data[0];
-};
-
-#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
-
-struct inet_request_sock {
- struct request_sock req;
- u32 loc_addr;
- u32 rmt_addr;
- u16 rmt_port;
- u16 snd_wscale : 4,
- rcv_wscale : 4,
- tstamp_ok : 1,
- sack_ok : 1,
- wscale_ok : 1,
- ecn_ok : 1,
- acked : 1;
- struct ip_options *opt;
-};
-
-static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
-{
- return (struct inet_request_sock *)sk;
-}
-
-struct ipv6_pinfo;
-
-struct inet_sock {
- /* sk and pinet6 has to be the first two members of inet_sock */
- struct sock sk;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct ipv6_pinfo *pinet6;
-#endif
- /* Socket demultiplex comparisons on incoming packets. */
- __u32 daddr; /* Foreign IPv4 addr */
- __u32 rcv_saddr; /* Bound local IPv4 addr */
- __u16 dport; /* Destination port */
- __u16 num; /* Local port */
- __u32 saddr; /* Sending source */
- __s16 uc_ttl; /* Unicast TTL */
- __u16 cmsg_flags;
- struct ip_options *opt;
- __u16 sport; /* Source port */
- __u16 id; /* ID counter for DF pkts */
- __u8 tos; /* TOS */
- __u8 mc_ttl; /* Multicasting TTL */
- __u8 pmtudisc;
- unsigned recverr : 1,
- freebind : 1,
- hdrincl : 1,
- mc_loop : 1;
- int mc_index; /* Multicast device index */
- __u32 mc_addr;
- struct ip_mc_socklist *mc_list; /* Group array */
- /*
- * Following members are used to retain the infomation to build
- * an ip header on each ip fragmentation while the socket is corked.
- */
- struct {
- unsigned int flags;
- unsigned int fragsize;
- struct ip_options *opt;
- struct rtable *rt;
- int length; /* Total length of all frames */
- u32 addr;
- struct flowi fl;
- } cork;
-};
-
-#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
-#define IPCORK_ALLFRAG 2 /* always fragment (for ipv6 for now) */
-
-static inline struct inet_sock *inet_sk(const struct sock *sk)
-{
- return (struct inet_sock *)sk;
-}
-
-static inline void __inet_sk_copy_descendant(struct sock *sk_to,
- const struct sock *sk_from,
- const int ancestor_size)
-{
- memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
- sk_from->sk_prot->obj_size - ancestor_size);
-}
-#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
-static inline void inet_sk_copy_descendant(struct sock *sk_to,
- const struct sock *sk_from)
-{
- __inet_sk_copy_descendant(sk_to, sk_from, sizeof(struct inet_sock));
-}
-#endif
-#endif
-
-extern int inet_sk_rebuild_header(struct sock *sk);
-
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
@@ -209,14 +90,14 @@ struct iphdr {
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
- __u16 tot_len;
- __u16 id;
- __u16 frag_off;
+ __be16 tot_len;
+ __be16 id;
+ __be16 frag_off;
__u8 ttl;
__u8 protocol;
__u16 check;
- __u32 saddr;
- __u32 daddr;
+ __be32 saddr;
+ __be32 daddr;
/*The options start here. */
};
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index e0b922785d98..9c8f4c9ed429 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -171,12 +171,13 @@ enum {
};
#ifdef __KERNEL__
-#include <linux/in6.h> /* struct sockaddr_in6 */
#include <linux/icmpv6.h>
-#include <net/if_inet6.h> /* struct ipv6_mc_socklist */
#include <linux/tcp.h>
#include <linux/udp.h>
+#include <net/if_inet6.h> /* struct ipv6_mc_socklist */
+#include <net/inet_sock.h>
+
/*
This structure contains results of exthdrs parsing
as offsets from skb->nh.
@@ -190,6 +191,10 @@ struct inet6_skb_parm {
__u16 srcrt;
__u16 dst1;
__u16 lastopt;
+ __u32 nhoff;
+ __u16 flags;
+
+#define IP6SKB_XFRM_TRANSFORMED 1
};
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
@@ -199,18 +204,17 @@ static inline int inet6_iif(const struct sk_buff *skb)
return IP6CB(skb)->iif;
}
-struct tcp6_request_sock {
- struct tcp_request_sock req;
+struct inet6_request_sock {
struct in6_addr loc_addr;
struct in6_addr rmt_addr;
struct sk_buff *pktopts;
int iif;
};
-static inline struct tcp6_request_sock *tcp6_rsk(const struct request_sock *sk)
-{
- return (struct tcp6_request_sock *)sk;
-}
+struct tcp6_request_sock {
+ struct tcp_request_sock tcp6rsk_tcp;
+ struct inet6_request_sock tcp6rsk_inet6;
+};
/**
* struct ipv6_pinfo - ipv6 private area
@@ -298,12 +302,36 @@ struct tcp6_sock {
struct ipv6_pinfo inet6;
};
+extern int inet6_sk_rebuild_header(struct sock *sk);
+
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
{
return inet_sk(__sk)->pinet6;
}
+static inline struct inet6_request_sock *
+ inet6_rsk(const struct request_sock *rsk)
+{
+ return (struct inet6_request_sock *)(((u8 *)rsk) +
+ inet_rsk(rsk)->inet6_rsk_offset);
+}
+
+static inline u32 inet6_rsk_offset(struct request_sock *rsk)
+{
+ return rsk->rsk_ops->obj_size - sizeof(struct inet6_request_sock);
+}
+
+static inline struct request_sock *inet6_reqsk_alloc(struct request_sock_ops *ops)
+{
+ struct request_sock *req = reqsk_alloc(ops);
+
+ if (req != NULL)
+ inet_rsk(req)->inet6_rsk_offset = inet6_rsk_offset(req);
+
+ return req;
+}
+
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
{
return (struct raw6_sock *)sk;
@@ -323,28 +351,37 @@ 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 inet6_timewait_sock {
+ struct in6_addr tw_v6_daddr;
+ struct in6_addr tw_v6_rcv_saddr;
+};
struct tcp6_timewait_sock {
- struct tcp_timewait_sock tw_v6_sk;
- struct in6_addr tw_v6_daddr;
- struct in6_addr tw_v6_rcv_saddr;
+ struct tcp_timewait_sock tcp6tw_tcp;
+ struct inet6_timewait_sock tcp6tw_inet6;
};
-static inline struct tcp6_timewait_sock *tcp6_twsk(const struct sock *sk)
+static inline u16 inet6_tw_offset(const struct proto *prot)
{
- return (struct tcp6_timewait_sock *)sk;
+ return prot->twsk_prot->twsk_obj_size -
+ sizeof(struct inet6_timewait_sock);
}
-static inline struct in6_addr *__tcp_v6_rcv_saddr(const struct sock *sk)
+static inline struct inet6_timewait_sock *inet6_twsk(const struct sock *sk)
+{
+ return (struct inet6_timewait_sock *)(((u8 *)sk) +
+ inet_twsk(sk)->tw_ipv6_offset);
+}
+
+static inline struct in6_addr *__inet6_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;
+ &inet6_sk(sk)->rcv_saddr : &inet6_twsk(sk)->tw_v6_rcv_saddr;
}
-static inline struct in6_addr *tcp_v6_rcv_saddr(const struct sock *sk)
+static inline struct in6_addr *inet6_rcv_saddr(const struct sock *sk)
{
- return sk->sk_family == AF_INET6 ? __tcp_v6_rcv_saddr(sk) : NULL;
+ return sk->sk_family == AF_INET6 ? __inet6_rcv_saddr(sk) : NULL;
}
static inline int inet_v6_ipv6only(const struct sock *sk)
@@ -361,13 +398,19 @@ static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
return NULL;
}
+static inline struct inet6_request_sock *
+ inet6_rsk(const struct request_sock *rsk)
+{
+ return NULL;
+}
+
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
{
return NULL;
}
-#define __tcp_v6_rcv_saddr(__sk) NULL
-#define tcp_v6_rcv_saddr(__sk) NULL
+#define __inet6_rcv_saddr(__sk) NULL
+#define inet6_rcv_saddr(__sk) NULL
#define tcp_twsk_ipv6only(__sk) 0
#define inet_v6_ipv6only(__sk) 0
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
diff --git a/include/linux/irq.h b/include/linux/irq.h
index f04ba20712a2..6c5d4c898ccb 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -12,7 +12,7 @@
#include <linux/config.h>
#include <linux/smp.h>
-#if !defined(CONFIG_ARCH_S390)
+#if !defined(CONFIG_S390)
#include <linux/linkage.h>
#include <linux/cache.h>
@@ -221,6 +221,17 @@ extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
extern void init_irq_proc(void);
+
+#ifdef CONFIG_AUTO_IRQ_AFFINITY
+extern int select_smp_affinity(unsigned int irq);
+#else
+static inline int
+select_smp_affinity(unsigned int irq)
+{
+ return 1;
+}
+#endif
+
#endif
extern hw_irq_controller no_irq_type; /* needed in every arch ? */
diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h
index 7a4eacd77cb2..04e10f9f14f8 100644
--- a/include/linux/isdnif.h
+++ b/include/linux/isdnif.h
@@ -282,43 +282,43 @@ typedef struct setup_parm {
typedef struct T30_s {
/* session parameters */
- __u8 resolution __attribute__ ((packed));
- __u8 rate __attribute__ ((packed));
- __u8 width __attribute__ ((packed));
- __u8 length __attribute__ ((packed));
- __u8 compression __attribute__ ((packed));
- __u8 ecm __attribute__ ((packed));
- __u8 binary __attribute__ ((packed));
- __u8 scantime __attribute__ ((packed));
- __u8 id[FAXIDLEN] __attribute__ ((packed));
+ __u8 resolution;
+ __u8 rate;
+ __u8 width;
+ __u8 length;
+ __u8 compression;
+ __u8 ecm;
+ __u8 binary;
+ __u8 scantime;
+ __u8 id[FAXIDLEN];
/* additional parameters */
- __u8 phase __attribute__ ((packed));
- __u8 direction __attribute__ ((packed));
- __u8 code __attribute__ ((packed));
- __u8 badlin __attribute__ ((packed));
- __u8 badmul __attribute__ ((packed));
- __u8 bor __attribute__ ((packed));
- __u8 fet __attribute__ ((packed));
- __u8 pollid[FAXIDLEN] __attribute__ ((packed));
- __u8 cq __attribute__ ((packed));
- __u8 cr __attribute__ ((packed));
- __u8 ctcrty __attribute__ ((packed));
- __u8 minsp __attribute__ ((packed));
- __u8 phcto __attribute__ ((packed));
- __u8 rel __attribute__ ((packed));
- __u8 nbc __attribute__ ((packed));
+ __u8 phase;
+ __u8 direction;
+ __u8 code;
+ __u8 badlin;
+ __u8 badmul;
+ __u8 bor;
+ __u8 fet;
+ __u8 pollid[FAXIDLEN];
+ __u8 cq;
+ __u8 cr;
+ __u8 ctcrty;
+ __u8 minsp;
+ __u8 phcto;
+ __u8 rel;
+ __u8 nbc;
/* remote station parameters */
- __u8 r_resolution __attribute__ ((packed));
- __u8 r_rate __attribute__ ((packed));
- __u8 r_width __attribute__ ((packed));
- __u8 r_length __attribute__ ((packed));
- __u8 r_compression __attribute__ ((packed));
- __u8 r_ecm __attribute__ ((packed));
- __u8 r_binary __attribute__ ((packed));
- __u8 r_scantime __attribute__ ((packed));
- __u8 r_id[FAXIDLEN] __attribute__ ((packed));
- __u8 r_code __attribute__ ((packed));
-} T30_s;
+ __u8 r_resolution;
+ __u8 r_rate;
+ __u8 r_width;
+ __u8 r_length;
+ __u8 r_compression;
+ __u8 r_ecm;
+ __u8 r_binary;
+ __u8 r_scantime;
+ __u8 r_id[FAXIDLEN];
+ __u8 r_code;
+} __attribute__((packed)) T30_s;
#define ISDN_TTY_FAX_CONN_IN 0
#define ISDN_TTY_FAX_CONN_OUT 1
diff --git a/include/linux/isicom.h b/include/linux/isicom.h
index 7c6eae7f6ed7..45b3d48f0978 100644
--- a/include/linux/isicom.h
+++ b/include/linux/isicom.h
@@ -4,47 +4,12 @@
/*#define ISICOM_DEBUG*/
/*#define ISICOM_DEBUG_DTR_RTS*/
-
-/*
- * Firmware Loader definitions ...
- */
-
-#define __MultiTech ('M'<<8)
-#define MIOCTL_LOAD_FIRMWARE (__MultiTech | 0x01)
-#define MIOCTL_READ_FIRMWARE (__MultiTech | 0x02)
-#define MIOCTL_XFER_CTRL (__MultiTech | 0x03)
-#define MIOCTL_RESET_CARD (__MultiTech | 0x04)
-
-#define DATA_SIZE 16
-
-typedef struct {
- unsigned short exec_segment;
- unsigned short exec_addr;
-} exec_record;
-
-typedef struct {
- int board; /* Board to load */
- unsigned short addr;
- unsigned short count;
-} bin_header;
-
-typedef struct {
- int board; /* Board to load */
- unsigned short addr;
- unsigned short count;
- unsigned short segment;
- unsigned char bin_data[DATA_SIZE];
-} bin_frame;
-
#ifdef __KERNEL__
#define YES 1
#define NO 0
-#define ISILOAD_MISC_MINOR 155 /* /dev/isctl */
-#define ISILOAD_NAME "ISILoad"
-
-/*
+/*
* ISICOM Driver definitions ...
*
*/
@@ -55,8 +20,8 @@ typedef struct {
* PCI definitions
*/
- #define DEVID_COUNT 9
- #define VENDOR_ID 0x10b5
+#define DEVID_COUNT 9
+#define VENDOR_ID 0x10b5
/*
* These are now officially allocated numbers
@@ -66,9 +31,9 @@ typedef struct {
#define ISICOM_CMAJOR 113 /* callout */
#define ISICOM_MAGIC (('M' << 8) | 'T')
-#define WAKEUP_CHARS 256 /* hard coded for now */
-#define TX_SIZE 254
-
+#define WAKEUP_CHARS 256 /* hard coded for now */
+#define TX_SIZE 254
+
#define BOARD_COUNT 4
#define PORT_COUNT (BOARD_COUNT*16)
@@ -98,18 +63,15 @@ typedef struct {
#define ISICOM_INITIATE_XONXOFF 0x04
#define ISICOM_RESPOND_XONXOFF 0x08
-#define InterruptTheCard(base) (outw(0,(base)+0xc))
-#define ClearInterrupt(base) (inw((base)+0x0a))
-
#define BOARD(line) (((line) >> 4) & 0x3)
/* isi kill queue bitmap */
-
+
#define ISICOM_KILLTX 0x01
#define ISICOM_KILLRX 0x02
/* isi_board status bitmap */
-
+
#define FIRMWARE_LOADED 0x0001
#define BOARD_ACTIVE 0x0002
@@ -123,9 +85,8 @@ typedef struct {
#define ISI_RTS 0x0200
-#define ISI_TXOK 0x0001
-
+#define ISI_TXOK 0x0001
+
#endif /* __KERNEL__ */
#endif /* ISICOM_H */
-
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index dcde7adfdce5..558cb4c26ec9 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -498,6 +498,12 @@ struct transaction_s
struct journal_head *t_checkpoint_list;
/*
+ * Doubly-linked circular list of all buffers submitted for IO while
+ * checkpointing. [j_list_lock]
+ */
+ struct journal_head *t_checkpoint_io_list;
+
+ /*
* Doubly-linked circular list of temporary buffers currently undergoing
* IO in the log [j_list_lock]
*/
@@ -843,7 +849,7 @@ extern void journal_commit_transaction(journal_t *);
/* Checkpoint list management */
int __journal_clean_checkpoint_list(journal_t *journal);
-void __journal_remove_checkpoint(struct journal_head *);
+int __journal_remove_checkpoint(struct journal_head *);
void __journal_insert_checkpoint(struct journal_head *, transaction_t *);
/* Buffer IO */
diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h
index ef85ab56302b..ad565bf9dcc1 100644
--- a/include/linux/jffs2_fs_i.h
+++ b/include/linux/jffs2_fs_i.h
@@ -8,11 +8,11 @@
#include <asm/semaphore.h>
struct jffs2_inode_info {
- /* We need an internal semaphore similar to inode->i_sem.
+ /* We need an internal mutex similar to inode->i_mutex.
Unfortunately, we can't used the existing one, because
either the GC would deadlock, or we'd have to release it
before letting GC proceed. Or we'd have to put ugliness
- into the GC code so it didn't attempt to obtain the i_sem
+ into the GC code so it didn't attempt to obtain the i_mutex
for the inode(s) which are already locked */
struct semaphore sem;
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 6acfdbba734b..99905e180532 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -1,21 +1,12 @@
#ifndef _LINUX_JIFFIES_H
#define _LINUX_JIFFIES_H
+#include <linux/calc64.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <asm/param.h> /* for HZ */
-#include <asm/div64.h>
-
-#ifndef div_long_long_rem
-#define div_long_long_rem(dividend,divisor,remainder) \
-({ \
- u64 result = dividend; \
- *remainder = do_div(result,divisor); \
- result; \
-})
-#endif
/*
* The following defines establish the engineering parameters of the PLL
@@ -373,8 +364,11 @@ jiffies_to_timeval(const unsigned long jiffies, struct timeval *value)
* one divide.
*/
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;
+ long tv_usec;
+
+ value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &tv_usec);
+ tv_usec /= NSEC_PER_USEC;
+ value->tv_usec = tv_usec;
}
/*
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 7428198111eb..45f625d7d0b2 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -151,7 +151,7 @@ extern unsigned int keymap_count;
static inline void con_schedule_flip(struct tty_struct *t)
{
- schedule_work(&t->flip.work);
+ schedule_work(&t->buf.work);
}
#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index b1e407a4fbda..a5363324cf95 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -47,6 +47,8 @@ extern int console_printk[];
#define default_console_loglevel (console_printk[3])
struct completion;
+struct pt_regs;
+struct user;
/**
* might_sleep - annotation for functions that can sleep
@@ -123,6 +125,8 @@ extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
+extern void dump_thread(struct pt_regs *regs, struct user *dump);
+
#ifdef CONFIG_PRINTK
asmlinkage int vprintk(const char *fmt, va_list args)
__attribute__ ((format (printf, 1, 0)));
@@ -212,6 +216,7 @@ extern void dump_stack(void);
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
+#define NIPQUAD_FMT "%u.%u.%u.%u"
#define NIP6(addr) \
ntohs((addr).s6_addr16[0]), \
@@ -222,6 +227,8 @@ extern void dump_stack(void);
ntohs((addr).s6_addr16[5]), \
ntohs((addr).s6_addr16[6]), \
ntohs((addr).s6_addr16[7])
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIP6_SEQFMT "%04x%04x%04x%04x%04x%04x%04x%04x"
#if defined(__LITTLE_ENDIAN)
#define HIPQUAD(addr) \
@@ -286,6 +293,15 @@ extern void dump_stack(void);
1; \
})
+/*
+ * Check at compile time that 'function' is a certain type, or is a pointer
+ * to that type (needs to use typedef for the function type.)
+ */
+#define typecheck_fn(type,function) \
+({ typeof(type) __tmp = function; \
+ (void)__tmp; \
+})
+
#endif /* __KERNEL__ */
#define SI_LOAD_SHIFT 16
@@ -316,8 +332,6 @@ extern int randomize_va_space;
#endif
/* Trap pasters of __FUNCTION__ at compile-time */
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
#define __FUNCTION__ (__func__)
-#endif
#endif
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index c8468472aec0..a311f58c8a7c 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -41,7 +41,7 @@ typedef unsigned long kimage_entry_t;
#define IND_DONE 0x4
#define IND_SOURCE 0x8
-#define KEXEC_SEGMENT_MAX 8
+#define KEXEC_SEGMENT_MAX 16
struct kexec_segment {
void __user *buf;
size_t bufsz;
@@ -119,12 +119,15 @@ extern struct kimage *kexec_image;
#define KEXEC_ARCH_PPC64 (21 << 16)
#define KEXEC_ARCH_IA_64 (50 << 16)
#define KEXEC_ARCH_S390 (22 << 16)
+#define KEXEC_ARCH_SH (42 << 16)
#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
/* Location of a reserved region to hold the crash kernel.
*/
extern struct resource crashk_res;
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+extern note_buf_t *crash_notes;
#else /* !CONFIG_KEXEC */
struct pt_regs;
diff --git a/include/linux/key.h b/include/linux/key.h
index 53513a3be53b..cbf464ad9589 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -177,6 +177,8 @@ struct key {
/*
* kernel managed key type definition
*/
+typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, const char *op);
+
struct key_type {
/* name of the type */
const char *name;
@@ -193,14 +195,6 @@ struct key_type {
*/
int (*instantiate)(struct key *key, const void *data, size_t datalen);
- /* duplicate a key of this type (optional)
- * - the source key will be locked against change
- * - the new description will be attached
- * - the quota will have been adjusted automatically from
- * source->quotalen
- */
- int (*duplicate)(struct key *key, const struct key *source);
-
/* update a key of this type (optional)
* - this method should call key_payload_reserve() to recalculate the
* quota consumption
@@ -226,6 +220,16 @@ struct key_type {
*/
long (*read)(const struct key *key, char __user *buffer, size_t buflen);
+ /* handle request_key() for this type instead of invoking
+ * /sbin/request-key (optional)
+ * - key is the key to instantiate
+ * - authkey is the authority to assume when instantiating this key
+ * - op is the operation to be done, usually "create"
+ * - the call must not return until the instantiation process has run
+ * its course
+ */
+ request_key_actor_t request_key;
+
/* internal fields */
struct list_head link; /* link in types list */
};
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 8d7c59a29e09..3365945640c9 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -19,6 +19,7 @@
#define KEY_SPEC_USER_KEYRING -4 /* - key ID for UID-specific keyring */
#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
+#define KEY_SPEC_REQKEY_AUTH_KEY -7 /* - key ID for assumed request_key auth key */
/* request-key default keyrings */
#define KEY_REQKEY_DEFL_NO_CHANGE -1
@@ -46,5 +47,7 @@
#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */
#define KEYCTL_NEGATE 13 /* negate a partially constructed key */
#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
+#define KEYCTL_SET_TIMEOUT 15 /* set key timeout */
+#define KEYCTL_ASSUME_AUTHORITY 16 /* assume request_key() authorisation */
#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 7f7403aa4a41..2a8d8da70961 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -23,14 +23,27 @@
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/kref.h>
-#include <linux/kobject_uevent.h>
#include <linux/kernel.h>
#include <asm/atomic.h>
-#define KOBJ_NAME_LEN 20
+#define KOBJ_NAME_LEN 20
+#define UEVENT_HELPER_PATH_LEN 256
-/* counter to tag the hotplug event, read only except for the kobject core */
-extern u64 hotplug_seqnum;
+/* path to the userspace helper executed on an event */
+extern char uevent_helper[];
+
+/* counter to tag the uevent, read only except for the kobject core */
+extern u64 uevent_seqnum;
+
+/* the actions here must match the proper string in lib/kobject_uevent.c */
+typedef int __bitwise kobject_action_t;
+enum kobject_action {
+ KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */
+ KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */
+ KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */
+ KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */
+ KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */
+};
struct kobject {
const char * k_name;
@@ -87,15 +100,14 @@ struct kobj_type {
* of object; multiple ksets can belong to one subsystem. All
* ksets of a subsystem share the subsystem's lock.
*
- * Each kset can support hotplugging; if it does, it will be given
- * the opportunity to filter out specific kobjects from being
- * reported, as well as to add its own "data" elements to the
- * environment being passed to the hotplug helper.
+ * Each kset can support specific event variables; it can
+ * supress the event generation or add subsystem specific
+ * variables carried with the event.
*/
-struct kset_hotplug_ops {
+struct kset_uevent_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);
const char *(*name)(struct kset *kset, struct kobject *kobj);
- int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
+ int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size);
};
@@ -105,7 +117,7 @@ struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
- struct kset_hotplug_ops * hotplug_ops;
+ struct kset_uevent_ops * uevent_ops;
};
@@ -153,20 +165,20 @@ struct subsystem {
struct rw_semaphore rwsem;
};
-#define decl_subsys(_name,_type,_hotplug_ops) \
+#define decl_subsys(_name,_type,_uevent_ops) \
struct subsystem _name##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
- .hotplug_ops =_hotplug_ops, \
+ .uevent_ops =_uevent_ops, \
} \
}
-#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
+#define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
struct subsystem _varname##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
- .hotplug_ops =_hotplug_ops, \
+ .uevent_ops =_uevent_ops, \
} \
}
@@ -241,15 +253,17 @@ struct subsys_attribute {
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
-#ifdef CONFIG_HOTPLUG
-void kobject_hotplug(struct kobject *kobj, enum kobject_action action);
-int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
+#if defined(CONFIG_HOTPLUG) & defined(CONFIG_NET)
+void kobject_uevent(struct kobject *kobj, enum kobject_action action);
+
+int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
__attribute__((format (printf, 7, 8)));
#else
-static inline void kobject_hotplug(struct kobject *kobj, enum kobject_action action) { }
-static inline int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
+static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
+
+static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
const char *format, ...)
{ return 0; }
diff --git a/include/linux/kobject_uevent.h b/include/linux/kobject_uevent.h
deleted file mode 100644
index aa664fe7e561..000000000000
--- a/include/linux/kobject_uevent.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * kobject_uevent.h - list of kobject user events that can be generated
- *
- * Copyright (C) 2004 IBM Corp.
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
- *
- * This file is released under the GPLv2.
- *
- */
-
-#ifndef _KOBJECT_EVENT_H_
-#define _KOBJECT_EVENT_H_
-
-#define HOTPLUG_PATH_LEN 256
-
-/* path to the hotplug userspace helper executed on an event */
-extern char hotplug_path[];
-
-/*
- * If you add an action here, you must also add the proper string to the
- * lib/kobject_uevent.c file.
- */
-typedef int __bitwise kobject_action_t;
-enum kobject_action {
- KOBJ_ADD = (__force kobject_action_t) 0x01, /* add event, for hotplug */
- KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* remove event, for hotplug */
- KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* a sysfs attribute file has changed */
- KOBJ_MOUNT = (__force kobject_action_t) 0x04, /* mount event for block devices */
- KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices */
- KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* offline event for hotplug devices */
- KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* online event for hotplug devices */
-};
-
-
-#ifdef CONFIG_KOBJECT_UEVENT
-int kobject_uevent(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr);
-int kobject_uevent_atomic(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr);
-#else
-static inline int kobject_uevent(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr)
-{
- return 0;
-}
-static inline int kobject_uevent_atomic(struct kobject *kobj,
- enum kobject_action action,
- struct attribute *attr)
-{
- return 0;
-}
-#endif
-
-#endif
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index c03f2dc933de..669756bc20a2 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -68,6 +68,9 @@ struct kprobe {
/* list of kprobes for multi-handler support */
struct list_head list;
+ /* Indicates that the corresponding module has been ref counted */
+ unsigned int mod_refcounted;
+
/*count the number of times this probe was temporarily disarmed */
unsigned long nmissed;
@@ -149,11 +152,10 @@ struct kretprobe_instance {
};
extern spinlock_t kretprobe_lock;
+extern struct semaphore kprobe_mutex;
extern int arch_prepare_kprobe(struct kprobe *p);
-extern void arch_copy_kprobe(struct kprobe *p);
extern void arch_arm_kprobe(struct kprobe *p);
extern void arch_disarm_kprobe(struct kprobe *p);
-extern void arch_remove_kprobe(struct kprobe *p);
extern int arch_init_kprobes(void);
extern void show_registers(struct pt_regs *regs);
extern kprobe_opcode_t *get_insn_slot(void);
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
new file mode 100644
index 000000000000..1bd6552cc341
--- /dev/null
+++ b/include/linux/ktime.h
@@ -0,0 +1,284 @@
+/*
+ * include/linux/ktime.h
+ *
+ * ktime_t - nanosecond-resolution time format.
+ *
+ * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ * data type definitions, declarations, prototypes and macros.
+ *
+ * Started by: Thomas Gleixner and Ingo Molnar
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#ifndef _LINUX_KTIME_H
+#define _LINUX_KTIME_H
+
+#include <linux/time.h>
+#include <linux/jiffies.h>
+
+/*
+ * ktime_t:
+ *
+ * On 64-bit CPUs a single 64-bit variable is used to store the hrtimers
+ * internal representation of time values in scalar nanoseconds. The
+ * design plays out best on 64-bit CPUs, where most conversions are
+ * NOPs and most arithmetic ktime_t operations are plain arithmetic
+ * operations.
+ *
+ * On 32-bit CPUs an optimized representation of the timespec structure
+ * is used to avoid expensive conversions from and to timespecs. The
+ * endian-aware order of the tv struct members is choosen to allow
+ * mathematical operations on the tv64 member of the union too, which
+ * for certain operations produces better code.
+ *
+ * For architectures with efficient support for 64/32-bit conversions the
+ * plain scalar nanosecond based representation can be selected by the
+ * config switch CONFIG_KTIME_SCALAR.
+ */
+typedef union {
+ s64 tv64;
+#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
+ struct {
+# ifdef __BIG_ENDIAN
+ s32 sec, nsec;
+# else
+ s32 nsec, sec;
+# endif
+ } tv;
+#endif
+} ktime_t;
+
+#define KTIME_MAX (~((u64)1 << 63))
+
+/*
+ * ktime_t definitions when using the 64-bit scalar representation:
+ */
+
+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
+
+/* Define a ktime_t variable and initialize it to zero: */
+#define DEFINE_KTIME(kt) ktime_t kt = { .tv64 = 0 }
+
+/**
+ * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
+ *
+ * @secs: seconds to set
+ * @nsecs: nanoseconds to set
+ *
+ * Return the ktime_t representation of the value
+ */
+static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+ return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
+}
+
+/* Subtract two ktime_t variables. rem = lhs -rhs: */
+#define ktime_sub(lhs, rhs) \
+ ({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; })
+
+/* Add two ktime_t variables. res = lhs + rhs: */
+#define ktime_add(lhs, rhs) \
+ ({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; })
+
+/*
+ * Add a ktime_t variable and a scalar nanosecond value.
+ * res = kt + nsval:
+ */
+#define ktime_add_ns(kt, nsval) \
+ ({ (ktime_t){ .tv64 = (kt).tv64 + (nsval) }; })
+
+/* convert a timespec to ktime_t format: */
+#define timespec_to_ktime(ts) ktime_set((ts).tv_sec, (ts).tv_nsec)
+
+/* convert a timeval to ktime_t format: */
+#define timeval_to_ktime(tv) ktime_set((tv).tv_sec, (tv).tv_usec * 1000)
+
+/* Map the ktime_t to timespec conversion to ns_to_timespec function */
+#define ktime_to_timespec(kt) ns_to_timespec((kt).tv64)
+
+/* Map the ktime_t to timeval conversion to ns_to_timeval function */
+#define ktime_to_timeval(kt) ns_to_timeval((kt).tv64)
+
+/* Map the ktime_t to clock_t conversion to the inline in jiffies.h: */
+#define ktime_to_clock_t(kt) nsec_to_clock_t((kt).tv64)
+
+/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
+#define ktime_to_ns(kt) ((kt).tv64)
+
+#else
+
+/*
+ * Helper macros/inlines to get the ktime_t math right in the timespec
+ * representation. The macros are sometimes ugly - their actual use is
+ * pretty okay-ish, given the circumstances. We do all this for
+ * performance reasons. The pure scalar nsec_t based code was nice and
+ * simple, but created too many 64-bit / 32-bit conversions and divisions.
+ *
+ * Be especially aware that negative values are represented in a way
+ * that the tv.sec field is negative and the tv.nsec field is greater
+ * or equal to zero but less than nanoseconds per second. This is the
+ * same representation which is used by timespecs.
+ *
+ * tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC
+ */
+
+/* Define a ktime_t variable and initialize it to zero: */
+#define DEFINE_KTIME(kt) ktime_t kt = { .tv64 = 0 }
+
+/* Set a ktime_t variable to a value in sec/nsec representation: */
+static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+ return (ktime_t) { .tv = { .sec = secs, .nsec = nsecs } };
+}
+
+/**
+ * ktime_sub - subtract two ktime_t variables
+ *
+ * @lhs: minuend
+ * @rhs: subtrahend
+ *
+ * Returns the remainder of the substraction
+ */
+static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
+{
+ ktime_t res;
+
+ res.tv64 = lhs.tv64 - rhs.tv64;
+ if (res.tv.nsec < 0)
+ res.tv.nsec += NSEC_PER_SEC;
+
+ return res;
+}
+
+/**
+ * ktime_add - add two ktime_t variables
+ *
+ * @add1: addend1
+ * @add2: addend2
+ *
+ * Returns the sum of addend1 and addend2
+ */
+static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
+{
+ ktime_t res;
+
+ res.tv64 = add1.tv64 + add2.tv64;
+ /*
+ * performance trick: the (u32) -NSEC gives 0x00000000Fxxxxxxx
+ * so we subtract NSEC_PER_SEC and add 1 to the upper 32 bit.
+ *
+ * it's equivalent to:
+ * tv.nsec -= NSEC_PER_SEC
+ * tv.sec ++;
+ */
+ if (res.tv.nsec >= NSEC_PER_SEC)
+ res.tv64 += (u32)-NSEC_PER_SEC;
+
+ return res;
+}
+
+/**
+ * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
+ *
+ * @kt: addend
+ * @nsec: the scalar nsec value to add
+ *
+ * Returns the sum of kt and nsec in ktime_t format
+ */
+extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
+
+/**
+ * timespec_to_ktime - convert a timespec to ktime_t format
+ *
+ * @ts: the timespec variable to convert
+ *
+ * Returns a ktime_t variable with the converted timespec value
+ */
+static inline ktime_t timespec_to_ktime(const struct timespec ts)
+{
+ return (ktime_t) { .tv = { .sec = (s32)ts.tv_sec,
+ .nsec = (s32)ts.tv_nsec } };
+}
+
+/**
+ * timeval_to_ktime - convert a timeval to ktime_t format
+ *
+ * @tv: the timeval variable to convert
+ *
+ * Returns a ktime_t variable with the converted timeval value
+ */
+static inline ktime_t timeval_to_ktime(const struct timeval tv)
+{
+ return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec,
+ .nsec = (s32)tv.tv_usec * 1000 } };
+}
+
+/**
+ * ktime_to_timespec - convert a ktime_t variable to timespec format
+ *
+ * @kt: the ktime_t variable to convert
+ *
+ * Returns the timespec representation of the ktime value
+ */
+static inline struct timespec ktime_to_timespec(const ktime_t kt)
+{
+ return (struct timespec) { .tv_sec = (time_t) kt.tv.sec,
+ .tv_nsec = (long) kt.tv.nsec };
+}
+
+/**
+ * ktime_to_timeval - convert a ktime_t variable to timeval format
+ *
+ * @kt: the ktime_t variable to convert
+ *
+ * Returns the timeval representation of the ktime value
+ */
+static inline struct timeval ktime_to_timeval(const ktime_t kt)
+{
+ return (struct timeval) {
+ .tv_sec = (time_t) kt.tv.sec,
+ .tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) };
+}
+
+/**
+ * ktime_to_clock_t - convert a ktime_t variable to clock_t format
+ * @kt: the ktime_t variable to convert
+ *
+ * Returns a clock_t variable with the converted value
+ */
+static inline clock_t ktime_to_clock_t(const ktime_t kt)
+{
+ return nsec_to_clock_t( (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec);
+}
+
+/**
+ * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
+ * @kt: the ktime_t variable to convert
+ *
+ * Returns the scalar nanoseconds representation of kt
+ */
+static inline u64 ktime_to_ns(const ktime_t kt)
+{
+ return (u64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
+}
+
+#endif
+
+/*
+ * The resolution of the clocks. The resolution value is returned in
+ * the clock_getres() system call to give application programmers an
+ * idea of the (in)accuracy of timers. Timer values are rounded up to
+ * this resolution values.
+ */
+#define KTIME_REALTIME_RES (ktime_t){ .tv64 = TICK_NSEC }
+#define KTIME_MONOTONIC_RES (ktime_t){ .tv64 = TICK_NSEC }
+
+/* Get the monotonic time in timespec format: */
+extern void ktime_get_ts(struct timespec *ts);
+
+/* Get the real (wall-) time in timespec format: */
+#define ktime_get_real_ts(ts) getnstimeofday(ts)
+
+#endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 41ea7dbc1755..9e5db2949c58 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -124,18 +124,25 @@ enum {
ATA_FLAG_DEBUGMSG = (1 << 10),
ATA_FLAG_NO_ATAPI = (1 << 11), /* No ATAPI support */
+ ATA_FLAG_SUSPENDED = (1 << 12), /* port is suspended */
+
+ ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */
+ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */
+
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */
ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */
ATA_QCFLAG_DMAMAP = ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
/* various lengths of time */
- ATA_TMOUT_EDD = 5 * HZ, /* hueristic */
+ ATA_TMOUT_EDD = 5 * HZ, /* heuristic */
ATA_TMOUT_PIO = 30 * HZ,
- ATA_TMOUT_BOOT = 30 * HZ, /* hueristic */
- ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* hueristic */
+ ATA_TMOUT_BOOT = 30 * HZ, /* heuristic */
+ ATA_TMOUT_BOOT_QUICK = 7 * HZ, /* heuristic */
ATA_TMOUT_CDB = 30 * HZ,
ATA_TMOUT_CDB_QUICK = 5 * HZ,
+ ATA_TMOUT_INTERNAL = 30 * HZ,
+ ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
/* ATA bus states */
BUS_UNKNOWN = 0,
@@ -195,7 +202,7 @@ struct ata_port;
struct ata_queued_cmd;
/* typedefs */
-typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc, unsigned int err_mask);
+typedef int (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
struct ata_ioports {
unsigned long cmd_addr;
@@ -280,9 +287,9 @@ struct ata_queued_cmd {
/* DO NOT iterate over __sg manually, use ata_for_each_sg() */
struct scatterlist *__sg;
- ata_qc_cb_t complete_fn;
+ unsigned int err_mask;
- struct completion *waiting;
+ ata_qc_cb_t complete_fn;
void *private_data;
};
@@ -331,8 +338,6 @@ struct ata_port {
u8 ctl; /* cache of ATA control register */
u8 last_ctl; /* Cache last written value */
- unsigned int bus_state;
- unsigned int port_state;
unsigned int pio_mask;
unsigned int mwdma_mask;
unsigned int udma_mask;
@@ -436,6 +441,8 @@ extern void ata_std_ports(struct ata_ioports *ioaddr);
extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports);
extern void ata_pci_remove_one (struct pci_dev *pdev);
+extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int ata_pci_device_resume(struct pci_dev *pdev);
#endif /* CONFIG_PCI */
extern int ata_device_add(const struct ata_probe_ent *ent);
extern void ata_host_set_remove(struct ata_host_set *host_set);
@@ -445,6 +452,10 @@ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmn
extern int ata_scsi_error(struct Scsi_Host *host);
extern int ata_scsi_release(struct Scsi_Host *host);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+extern int ata_scsi_device_resume(struct scsi_device *);
+extern int ata_scsi_device_suspend(struct scsi_device *);
+extern int ata_device_resume(struct ata_port *, struct ata_device *);
+extern int ata_device_suspend(struct ata_port *, struct ata_device *);
extern int ata_ratelimit(void);
/*
@@ -478,9 +489,10 @@ extern void ata_bmdma_start (struct ata_queued_cmd *qc);
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, unsigned int err_mask);
+extern void ata_qc_complete(struct ata_queued_cmd *qc);
extern void ata_eng_timeout(struct ata_port *ap);
-extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd,
+extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+ struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *));
extern int ata_std_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
@@ -490,6 +502,8 @@ extern int ata_scsi_slave_config(struct scsi_device *sdev);
/*
* Timing helpers
*/
+
+extern unsigned int ata_pio_need_iordy(const struct ata_device *);
extern int ata_timing_compute(struct ata_device *, unsigned short,
struct ata_timing *, int, int);
extern void ata_timing_merge(const struct ata_timing *,
@@ -670,6 +684,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
qc->cursect = qc->cursg = qc->cursg_ofs = 0;
qc->nsect = 0;
qc->nbytes = qc->curbytes = 0;
+ qc->err_mask = 0;
ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
}
diff --git a/include/linux/list.h b/include/linux/list.h
index 8e3388284530..945daa1f13dd 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -436,6 +436,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_reverse - iterate backwards over list of given type 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_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, 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.
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 16d4e5a08e1d..95c8fea293ba 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -172,7 +172,7 @@ extern struct nlm_host *nlm_find_client(void);
/*
* Server-side lock handling
*/
-int nlmsvc_async_call(struct nlm_rqst *, u32, rpc_action);
+int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *);
u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
struct nlm_lock *, int, struct nlm_cookie *);
u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 40f63c9879d2..f96506782ebe 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -58,9 +58,9 @@ struct loop_device {
struct bio *lo_bio;
struct bio *lo_biotail;
int lo_state;
- struct semaphore lo_sem;
+ struct completion lo_done;
+ struct completion lo_bh_done;
struct semaphore lo_ctl_mutex;
- struct semaphore lo_bh_mutex;
int lo_pending;
request_queue_t *lo_queue;
diff --git a/include/linux/memory.h b/include/linux/memory.h
index dc4081b6f161..e251dc43d0f5 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -70,21 +70,15 @@ static inline void unregister_memory_notifier(struct notifier_block *nb)
{
}
#else
-extern int register_memory(struct memory_block *, struct mem_section *section, struct node *);
extern int register_new_memory(struct mem_section *);
extern int unregister_memory_section(struct mem_section *);
extern int memory_dev_init(void);
-extern int register_memory_notifier(struct notifier_block *nb);
-extern void unregister_memory_notifier(struct notifier_block *nb);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
-extern int invalidate_phys_mapping(unsigned long, unsigned long);
struct notifier_block;
-extern int register_memory_notifier(struct notifier_block *nb);
-extern void unregister_memory_notifier(struct notifier_block *nb);
-
#endif /* CONFIG_MEMORY_HOTPLUG */
#define hotplug_memory_notifier(fn, pri) { \
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 8b67cf837ca9..bbd2221923c3 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -22,6 +22,9 @@
/* Flags for mbind */
#define MPOL_MF_STRICT (1<<0) /* Verify existing pages in the mapping */
+#define MPOL_MF_MOVE (1<<1) /* Move pages owned by this process to conform to mapping */
+#define MPOL_MF_MOVE_ALL (1<<2) /* Move every page to conform to mapping */
+#define MPOL_MF_INTERNAL (1<<3) /* Internal flags start here */
#ifdef __KERNEL__
@@ -65,6 +68,7 @@ struct mempolicy {
nodemask_t nodes; /* interleave */
/* undefined for default */
} v;
+ nodemask_t cpuset_mems_allowed; /* mempolicy relative to these nodes */
};
/*
@@ -110,14 +114,6 @@ static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b)
#define mpol_set_vma_default(vma) ((vma)->vm_policy = NULL)
/*
- * Hugetlb policy. i386 hugetlb so far works with node numbers
- * instead of zone lists, so give it special interfaces for now.
- */
-extern int mpol_first_node(struct vm_area_struct *vma, unsigned long addr);
-extern int mpol_node_valid(int nid, struct vm_area_struct *vma,
- unsigned long addr);
-
-/*
* Tree of shared policies for a shared memory region.
* Maintain the policies in a pseudo mm that contains vmas. The vmas
* carry the policy. As a special twist the pseudo mm is indexed in pages, not
@@ -136,12 +132,8 @@ struct shared_policy {
spinlock_t lock;
};
-static inline void mpol_shared_policy_init(struct shared_policy *info)
-{
- info->root = RB_ROOT;
- spin_lock_init(&info->lock);
-}
-
+void mpol_shared_policy_init(struct shared_policy *info, int policy,
+ nodemask_t *nodes);
int mpol_set_shared_policy(struct shared_policy *info,
struct vm_area_struct *vma,
struct mempolicy *new);
@@ -149,13 +141,38 @@ 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 void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new);
+extern void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *new);
+extern void mpol_rebind_task(struct task_struct *tsk,
+ const nodemask_t *new);
+extern void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new);
+#define set_cpuset_being_rebound(x) (cpuset_being_rebound = (x))
+
+#ifdef CONFIG_CPUSET
+#define current_cpuset_is_being_rebound() \
+ (cpuset_being_rebound == current->cpuset)
+#else
+#define current_cpuset_is_being_rebound() 0
+#endif
+
extern struct mempolicy default_policy;
+extern struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+ unsigned long addr);
+extern unsigned slab_node(struct mempolicy *policy);
+
+extern int policy_zone;
+
+static inline void check_highest_zone(int k)
+{
+ if (k > policy_zone)
+ policy_zone = k;
+}
+
+int do_migrate_pages(struct mm_struct *mm,
+ const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags);
+
+extern void *cpuset_being_rebound; /* Trigger mpol_copy vma rebind */
#else
@@ -182,17 +199,6 @@ static inline struct mempolicy *mpol_copy(struct mempolicy *old)
return NULL;
}
-static inline int mpol_first_node(struct vm_area_struct *vma, unsigned long a)
-{
- return numa_node_id();
-}
-
-static inline int
-mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long a)
-{
- return 1;
-}
-
struct shared_policy {};
static inline int mpol_set_shared_policy(struct shared_policy *info,
@@ -202,7 +208,8 @@ static inline int mpol_set_shared_policy(struct shared_policy *info,
return -EINVAL;
}
-static inline void mpol_shared_policy_init(struct shared_policy *info)
+static inline void mpol_shared_policy_init(struct shared_policy *info,
+ int policy, nodemask_t *nodes)
{
}
@@ -227,11 +234,38 @@ static inline void numa_default_policy(void)
{
}
-static inline void numa_policy_rebind(const nodemask_t *old,
+static inline void mpol_rebind_policy(struct mempolicy *pol,
+ const nodemask_t *new)
+{
+}
+
+static inline void mpol_rebind_task(struct task_struct *tsk,
const nodemask_t *new)
{
}
+static inline void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
+{
+}
+
+#define set_cpuset_being_rebound(x) do {} while (0)
+
+static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+}
+
+static inline int do_migrate_pages(struct mm_struct *mm,
+ const nodemask_t *from_nodes,
+ const nodemask_t *to_nodes, int flags)
+{
+ return 0;
+}
+
+static inline void check_highest_zone(int k)
+{
+}
#endif /* CONFIG_NUMA */
#endif /* __KERNEL__ */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a06a84d347fb..85854b867463 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3,6 +3,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/capability.h>
#ifdef __KERNEL__
@@ -13,6 +14,7 @@
#include <linux/rbtree.h>
#include <linux/prio_tree.h>
#include <linux/fs.h>
+#include <linux/mutex.h>
struct mempolicy;
struct anon_vma;
@@ -223,24 +225,27 @@ struct page {
* & limit reverse map searches.
*/
union {
- unsigned long private; /* Mapping-private opaque data:
- * usually used for buffer_heads
- * if PagePrivate set; used for
- * swp_entry_t if PageSwapCache
- * When page is free, this indicates
- * order in the buddy system.
- */
+ struct {
+ unsigned long private; /* Mapping-private opaque data:
+ * usually used for buffer_heads
+ * if PagePrivate set; used for
+ * swp_entry_t if PageSwapCache.
+ * When page is free, this
+ * indicates order in the buddy
+ * system.
+ */
+ struct address_space *mapping; /* If low bit clear, points to
+ * inode address_space, or NULL.
+ * If page mapped as anonymous
+ * memory, low bit is set, and
+ * it points to anon_vma object:
+ * see PAGE_MAPPING_ANON below.
+ */
+ };
#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
- spinlock_t ptl;
+ spinlock_t ptl;
#endif
- } u;
- struct address_space *mapping; /* If low bit clear, points to
- * inode address_space, or NULL.
- * If page mapped as anonymous
- * memory, low bit is set, and
- * it points to anon_vma object:
- * see PAGE_MAPPING_ANON below.
- */
+ };
pgoff_t index; /* Our offset within mapping. */
struct list_head lru; /* Pageout list, eg. active_list
* protected by zone->lru_lock !
@@ -261,8 +266,8 @@ struct page {
#endif /* WANT_PAGE_VIRTUAL */
};
-#define page_private(page) ((page)->u.private)
-#define set_page_private(page, v) ((page)->u.private = (v))
+#define page_private(page) ((page)->private)
+#define set_page_private(page, v) ((page)->private = (v))
/*
* FIXME: take this include out, include page-flags.h in
@@ -308,7 +313,7 @@ struct page {
*/
#define get_page_testone(p) atomic_inc_and_test(&(p)->_count)
-#define set_page_count(p,v) atomic_set(&(p)->_count, v - 1)
+#define set_page_count(p,v) atomic_set(&(p)->_count, (v) - 1)
#define __put_page(p) atomic_dec(&(p)->_count)
extern void FASTCALL(__page_cache_release(struct page *));
@@ -507,7 +512,7 @@ static inline void set_page_links(struct page *page, unsigned long zone,
extern struct page *mem_map;
#endif
-static inline void *lowmem_page_address(struct page *page)
+static __always_inline void *lowmem_page_address(struct page *page)
{
return __va(page_to_pfn(page) << PAGE_SHIFT);
}
@@ -634,14 +639,38 @@ struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
int shmem_lock(struct file *file, int lock, struct user_struct *user);
#else
#define shmem_nopage filemap_nopage
-#define shmem_lock(a, b, c) ({0;}) /* always in memory, no need to lock */
-#define shmem_set_policy(a, b) (0)
-#define shmem_get_policy(a, b) (NULL)
+
+static inline int shmem_lock(struct file *file, int lock,
+ struct user_struct *user)
+{
+ return 0;
+}
+
+static inline int shmem_set_policy(struct vm_area_struct *vma,
+ struct mempolicy *new)
+{
+ return 0;
+}
+
+static inline struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
+ unsigned long addr)
+{
+ return NULL;
+}
#endif
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
+extern int shmem_mmap(struct file *file, struct vm_area_struct *vma);
int shmem_zero_setup(struct vm_area_struct *);
+#ifndef CONFIG_MMU
+extern unsigned long shmem_get_unmapped_area(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags);
+#endif
+
static inline int can_do_mlock(void)
{
if (capable(CAP_IPC_LOCK))
@@ -690,14 +719,31 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
}
extern int vmtruncate(struct inode * inode, loff_t offset);
+extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end);
extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
-extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
-static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access)
+#ifdef CONFIG_MMU
+extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma,
+ unsigned long address, int write_access);
+
+static inline int handle_mm_fault(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long address,
+ int write_access)
{
- return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE);
+ return __handle_mm_fault(mm, vma, address, write_access) &
+ (~VM_FAULT_WRITE);
}
+#else
+static inline int handle_mm_fault(struct mm_struct *mm,
+ struct vm_area_struct *vma, unsigned long address,
+ int write_access)
+{
+ /* should never happen if there's no MMU */
+ BUG();
+ return VM_FAULT_SIGBUS;
+}
+#endif
extern int make_pages_present(unsigned long addr, unsigned long end);
extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
@@ -774,7 +820,7 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long a
* overflow into the next struct page (as it might with DEBUG_SPINLOCK).
* When freeing, reset page->mapping so free_pages_check won't complain.
*/
-#define __pte_lockptr(page) &((page)->u.ptl)
+#define __pte_lockptr(page) &((page)->ptl)
#define pte_lock_init(_page) do { \
spin_lock_init(__pte_lockptr(_page)); \
} while (0)
@@ -896,6 +942,8 @@ extern unsigned long do_brk(unsigned long, unsigned long);
/* filemap.c */
extern unsigned long page_unuse(struct page *);
extern void truncate_inode_pages(struct address_space *, loff_t);
+extern void truncate_inode_pages_range(struct address_space *,
+ loff_t lstart, loff_t lend);
/* generic vm_area_ops exported for stackable file systems */
extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
@@ -978,6 +1026,9 @@ static inline void vm_stat_account(struct mm_struct *mm,
static inline void
kernel_map_pages(struct page *page, int numpages, int enable)
{
+ if (!PageHighMem(page) && !enable)
+ mutex_debug_check_no_locks_freed(page_address(page),
+ numpages * PAGE_SIZE);
}
#endif
@@ -993,5 +1044,12 @@ int in_gate_area_no_task(unsigned long addr);
/* /proc/<pid>/oom_adj set to -17 protects from the oom-killer */
#define OOM_DISABLE -17
+int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
+int shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+ unsigned long lru_pages);
+void drop_pagecache(void);
+void drop_slab(void);
+
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 47762ca695a5..8ac854f7f190 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -38,3 +38,4 @@ del_page_from_lru(struct zone *zone, struct page *page)
zone->nr_inactive--;
}
}
+
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 18fc77f682de..30dd978c1ec8 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -30,7 +30,12 @@ struct mmc_csd {
unsigned int tacc_ns;
unsigned int max_dtr;
unsigned int read_blkbits;
+ unsigned int write_blkbits;
unsigned int capacity;
+ unsigned int read_partial:1,
+ read_misalign:1,
+ write_partial:1,
+ write_misalign:1;
};
struct sd_scr {
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index aef6042f8f0b..ccd3e13de1e8 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -27,14 +27,15 @@ struct mmc_command {
#define MMC_RSP_MASK (3 << 0)
#define MMC_RSP_CRC (1 << 3) /* expect valid crc */
#define MMC_RSP_BUSY (1 << 4) /* card may send busy */
+#define MMC_RSP_OPCODE (1 << 5) /* response contains opcode */
/*
* These are the response types, and correspond to valid bit
* patterns of the above flags. One additional valid pattern
* is all zeros, which means we don't expect a response.
*/
-#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC)
-#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_BUSY)
+#define MMC_RSP_R1 (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R1B (MMC_RSP_SHORT|MMC_RSP_CRC|MMC_RSP_OPCODE|MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_LONG|MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_SHORT)
#define MMC_RSP_R6 (MMC_RSP_SHORT|MMC_RSP_CRC)
@@ -64,6 +65,7 @@ struct mmc_data {
#define MMC_DATA_WRITE (1 << 8)
#define MMC_DATA_READ (1 << 9)
#define MMC_DATA_STREAM (1 << 10)
+#define MMC_DATA_MULTI (1 << 11)
unsigned int bytes_xfered;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 9f22090df7dd..93a849f742db 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -38,7 +38,7 @@ struct pglist_data;
#if defined(CONFIG_SMP)
struct zone_padding {
char x[0];
-} ____cacheline_maxaligned_in_smp;
+} ____cacheline_internodealigned_in_smp;
#define ZONE_PADDING(name) struct zone_padding name;
#else
#define ZONE_PADDING(name)
@@ -46,7 +46,6 @@ struct zone_padding {
struct per_cpu_pages {
int count; /* number of pages in the list */
- int low; /* low watermark, refill needed */
int high; /* high watermark, emptying needed */
int batch; /* chunk size for buddy add/remove */
struct list_head list; /* the list of pages */
@@ -99,7 +98,7 @@ struct per_cpu_pageset {
/*
* On machines where it is needed (eg PCs) we divide physical memory
- * into multiple physical zones. On a PC we have 4 zones:
+ * into multiple physical zones. On a 32bit PC we have 4 zones:
*
* ZONE_DMA < 16 MB ISA DMA capable memory
* ZONE_DMA32 0 MB Empty
@@ -150,15 +149,17 @@ struct zone {
unsigned long pages_scanned; /* since last reclaim */
int all_unreclaimable; /* All pages pinned */
- /*
- * Does the allocator try to reclaim pages from the zone as soon
- * as it fails a watermark_ok() in __alloc_pages?
- */
- int reclaim_pages;
/* A count of how many reclaimers are scanning this zone */
atomic_t reclaim_in_progress;
/*
+ * timestamp (in jiffies) of the last zone reclaim that did not
+ * result in freeing of pages. This is used to avoid repeated scans
+ * if all memory in the zone is in use.
+ */
+ unsigned long last_unsuccessful_zone_reclaim;
+
+ /*
* prev_priority holds the scanning priority for this zone. It is
* defined as the scanning priority at which we achieved our reclaim
* target at the previous try_to_free_pages() or balance_pgdat()
@@ -234,7 +235,7 @@ struct zone {
* rarely used fields:
*/
char *name;
-} ____cacheline_maxaligned_in_smp;
+} ____cacheline_internodealigned_in_smp;
/*
@@ -389,6 +390,11 @@ static inline struct zone *next_zone(struct zone *zone)
#define for_each_zone(zone) \
for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
+static inline int populated_zone(struct zone *zone)
+{
+ return (!!zone->present_pages);
+}
+
static inline int is_highmem_idx(int idx)
{
return (idx == ZONE_HIGHMEM);
@@ -398,6 +404,7 @@ static inline int is_normal_idx(int idx)
{
return (idx == ZONE_NORMAL);
}
+
/**
* is_highmem - helper function to quickly check if a struct zone is a
* highmem zone or not. This is an attempt to keep references
@@ -414,6 +421,16 @@ static inline int is_normal(struct zone *zone)
return zone == zone->zone_pgdat->node_zones + ZONE_NORMAL;
}
+static inline int is_dma32(struct zone *zone)
+{
+ return zone == zone->zone_pgdat->node_zones + ZONE_DMA32;
+}
+
+static inline int is_dma(struct zone *zone)
+{
+ return zone == zone->zone_pgdat->node_zones + ZONE_DMA;
+}
+
/* These two functions are used to setup the per zone pages min values */
struct ctl_table;
struct file;
@@ -422,6 +439,8 @@ int min_free_kbytes_sysctl_handler(struct ctl_table *, int, struct file *,
extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1];
int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *,
void __user *, size_t *, loff_t *);
+int percpu_pagelist_fraction_sysctl_handler(struct ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
#include <linux/topology.h>
/* Returns the number of the current Node. */
@@ -435,7 +454,6 @@ extern struct pglist_data contig_page_data;
#define NODE_DATA(nid) (&contig_page_data)
#define NODE_MEM_MAP(nid) mem_map
#define MAX_NODES_SHIFT 1
-#define pfn_to_nid(pfn) (0)
#else /* CONFIG_NEED_MULTIPLE_NODES */
@@ -470,6 +488,10 @@ extern struct pglist_data contig_page_data;
#define early_pfn_to_nid(nid) (0UL)
#endif
+#ifdef CONFIG_FLATMEM
+#define pfn_to_nid(pfn) (0)
+#endif
+
#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
@@ -564,11 +586,6 @@ static inline int valid_section_nr(unsigned long nr)
return valid_section(__nr_to_section(nr));
}
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
-
static inline struct mem_section *__pfn_to_section(unsigned long pfn)
{
return __nr_to_section(pfn_to_section_nr(pfn));
@@ -598,13 +615,14 @@ static inline int pfn_valid(unsigned long pfn)
* this restriction.
*/
#ifdef CONFIG_NUMA
-#define pfn_to_nid early_pfn_to_nid
-#endif
-
-#define pfn_to_pgdat(pfn) \
+#define pfn_to_nid(pfn) \
({ \
- NODE_DATA(pfn_to_nid(pfn)); \
+ unsigned long __pfn_to_nid_pfn = (pfn); \
+ page_to_nid(pfn_to_page(__pfn_to_nid_pfn)); \
})
+#else
+#define pfn_to_nid(pfn) (0)
+#endif
#define early_pfn_valid(pfn) pfn_valid(pfn)
void sparse_init(void);
@@ -613,12 +631,6 @@ void sparse_init(void);
#define sparse_index_init(_sec, _nid) do {} while (0)
#endif /* CONFIG_SPARSEMEM */
-#ifdef CONFIG_NODES_SPAN_OTHER_NODES
-#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))
-#else
-#define early_pfn_in_nid(pfn, nid) (1)
-#endif
-
#ifndef early_pfn_valid
#define early_pfn_valid(pfn) (1)
#endif
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 368ec8e45bd0..b5c98c43779e 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -10,7 +10,7 @@
#ifdef MODULE
#define MODULE_PARAM_PREFIX /* empty */
#else
-#define MODULE_PARAM_PREFIX __stringify(KBUILD_MODNAME) "."
+#define MODULE_PARAM_PREFIX KBUILD_MODNAME "."
#endif
#ifdef MODULE
diff --git a/include/linux/mount.h b/include/linux/mount.h
index dd4e83eba933..b7472ae91fa4 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -20,9 +20,12 @@
#define MNT_NOSUID 0x01
#define MNT_NODEV 0x02
#define MNT_NOEXEC 0x04
-#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */
-#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */
-#define MNT_PNODE_MASK 0x30 /* propogation flag mask */
+#define MNT_NOATIME 0x08
+#define MNT_NODIRATIME 0x10
+
+#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
+#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
+#define MNT_PNODE_MASK 0x3000 /* propogation flag mask */
struct vfsmount {
struct list_head mnt_hash;
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 941da5c016a0..e933e2a355ad 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -329,7 +329,8 @@ static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
extern void fat_cache_inval_inode(struct inode *inode);
extern int fat_get_cluster(struct inode *inode, int cluster,
int *fclus, int *dclus);
-extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
+extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+ unsigned long *mapped_blocks);
/* fat/dir.c */
extern struct file_operations fat_dir_operations;
diff --git a/include/linux/mutex-debug.h b/include/linux/mutex-debug.h
new file mode 100644
index 000000000000..8b5769f00467
--- /dev/null
+++ b/include/linux/mutex-debug.h
@@ -0,0 +1,23 @@
+#ifndef __LINUX_MUTEX_DEBUG_H
+#define __LINUX_MUTEX_DEBUG_H
+
+#include <linux/linkage.h>
+
+/*
+ * Mutexes - debugging helpers:
+ */
+
+#define __DEBUG_MUTEX_INITIALIZER(lockname) \
+ , .held_list = LIST_HEAD_INIT(lockname.held_list), \
+ .name = #lockname , .magic = &lockname
+
+#define mutex_init(sem) __mutex_init(sem, __FUNCTION__)
+
+extern void FASTCALL(mutex_destroy(struct mutex *lock));
+
+extern void mutex_debug_show_all_locks(void);
+extern void mutex_debug_show_held_locks(struct task_struct *filter);
+extern void mutex_debug_check_no_locks_held(struct task_struct *task);
+extern void mutex_debug_check_no_locks_freed(const void *from, unsigned long len);
+
+#endif
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
new file mode 100644
index 000000000000..f1ac507fa20d
--- /dev/null
+++ b/include/linux/mutex.h
@@ -0,0 +1,120 @@
+/*
+ * Mutexes: blocking mutual exclusion locks
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * This file contains the main data structure and API definitions.
+ */
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <linux/list.h>
+#include <linux/spinlock_types.h>
+#include <linux/linkage.h>
+
+#include <asm/atomic.h>
+
+/*
+ * Simple, straightforward mutexes with strict semantics:
+ *
+ * - only one task can hold the mutex at a time
+ * - only the owner can unlock the mutex
+ * - multiple unlocks are not permitted
+ * - recursive locking is not permitted
+ * - a mutex object must be initialized via the API
+ * - a mutex object must not be initialized via memset or copying
+ * - task may not exit with mutex held
+ * - memory areas where held locks reside must not be freed
+ * - held mutexes must not be reinitialized
+ * - mutexes may not be used in irq contexts
+ *
+ * These semantics are fully enforced when DEBUG_MUTEXES is
+ * enabled. Furthermore, besides enforcing the above rules, the mutex
+ * debugging code also implements a number of additional features
+ * that make lock debugging easier and faster:
+ *
+ * - uses symbolic names of mutexes, whenever they are printed in debug output
+ * - point-of-acquire tracking, symbolic lookup of function names
+ * - list of all locks held in the system, printout of them
+ * - owner tracking
+ * - detects self-recursing locks and prints out all relevant info
+ * - detects multi-task circular deadlocks and prints out all affected
+ * locks and tasks (and only those tasks)
+ */
+struct mutex {
+ /* 1: unlocked, 0: locked, negative: locked, possible waiters */
+ atomic_t count;
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+#ifdef CONFIG_DEBUG_MUTEXES
+ struct thread_info *owner;
+ struct list_head held_list;
+ unsigned long acquire_ip;
+ const char *name;
+ void *magic;
+#endif
+};
+
+/*
+ * This is the control structure for tasks blocked on mutex,
+ * which resides on the blocked task's kernel stack:
+ */
+struct mutex_waiter {
+ struct list_head list;
+ struct task_struct *task;
+#ifdef CONFIG_DEBUG_MUTEXES
+ struct mutex *lock;
+ void *magic;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_MUTEXES
+# include <linux/mutex-debug.h>
+#else
+# define __DEBUG_MUTEX_INITIALIZER(lockname)
+# define mutex_init(mutex) __mutex_init(mutex, NULL)
+# define mutex_destroy(mutex) do { } while (0)
+# define mutex_debug_show_all_locks() do { } while (0)
+# define mutex_debug_show_held_locks(p) do { } while (0)
+# define mutex_debug_check_no_locks_held(task) do { } while (0)
+# define mutex_debug_check_no_locks_freed(from, len) do { } while (0)
+#endif
+
+#define __MUTEX_INITIALIZER(lockname) \
+ { .count = ATOMIC_INIT(1) \
+ , .wait_lock = SPIN_LOCK_UNLOCKED \
+ , .wait_list = LIST_HEAD_INIT(lockname.wait_list) \
+ __DEBUG_MUTEX_INITIALIZER(lockname) }
+
+#define DEFINE_MUTEX(mutexname) \
+ struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+extern void fastcall __mutex_init(struct mutex *lock, const char *name);
+
+/***
+ * mutex_is_locked - is the mutex locked
+ * @lock: the mutex to be queried
+ *
+ * Returns 1 if the mutex is locked, 0 if unlocked.
+ */
+static inline int fastcall mutex_is_locked(struct mutex *lock)
+{
+ return atomic_read(&lock->count) != 1;
+}
+
+/*
+ * See kernel/mutex.c for detailed documentation of these APIs.
+ * Also see Documentation/mutex-design.txt.
+ */
+extern void fastcall mutex_lock(struct mutex *lock);
+extern int fastcall mutex_lock_interruptible(struct mutex *lock);
+/*
+ * NOTE: mutex_trylock() follows the spin_trylock() convention,
+ * not the down_trylock() convention!
+ */
+extern int fastcall mutex_trylock(struct mutex *lock);
+extern void fastcall mutex_unlock(struct mutex *lock);
+
+#endif
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 455660eafba9..e6698013e4d0 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -56,10 +56,11 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_ACCESS (0x0400)
extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
+extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *));
#define user_path_walk(name,nd) \
- __user_walk(name, LOOKUP_FOLLOW, nd)
+ __user_walk_fd(AT_FDCWD, name, LOOKUP_FOLLOW, nd)
#define user_path_walk_link(name,nd) \
- __user_walk(name, 0, nd)
+ __user_walk_fd(AT_FDCWD, name, 0, nd)
extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
extern int FASTCALL(path_walk(const char *, struct nameidata *));
extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
@@ -67,14 +68,14 @@ extern void path_release(struct nameidata *);
extern void path_release_on_umount(struct nameidata *);
extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags);
-extern int path_lookup_open(const char *, unsigned lookup_flags, struct nameidata *, int open_flags);
+extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags);
extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
int (*open)(struct inode *, struct file *));
extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
extern void release_open_intent(struct nameidata *);
extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern struct dentry * lookup_hash(struct nameidata *);
+extern __deprecated_for_modules struct dentry * lookup_hash(struct nameidata *);
extern int follow_down(struct vfsmount **, struct dentry **);
extern int follow_up(struct vfsmount **, struct dentry **);
diff --git a/include/linux/nbd.h b/include/linux/nbd.h
index 090e210e98f0..f95d51fae733 100644
--- a/include/linux/nbd.h
+++ b/include/linux/nbd.h
@@ -37,18 +37,26 @@ enum {
/* userspace doesn't need the nbd_device structure */
#ifdef __KERNEL__
+#include <linux/wait.h>
+
/* values for flags field */
#define NBD_READ_ONLY 0x0001
#define NBD_WRITE_NOCHK 0x0002
+struct request;
+
struct nbd_device {
int flags;
int harderror; /* Code of hard error */
struct socket * sock;
struct file * file; /* If == NULL, device is not ready, yet */
int magic;
+
spinlock_t queue_lock;
struct list_head queue_head;/* Requests are added here... */
+ struct request *active_req;
+ wait_queue_head_t active_wq;
+
struct semaphore tx_lock;
struct gendisk *disk;
int blksize;
diff --git a/include/linux/ncp.h b/include/linux/ncp.h
index 99f77876b716..99f0adeeb3f3 100644
--- a/include/linux/ncp.h
+++ b/include/linux/ncp.h
@@ -20,29 +20,29 @@
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
struct ncp_request_header {
- __u16 type __attribute__((packed));
- __u8 sequence __attribute__((packed));
- __u8 conn_low __attribute__((packed));
- __u8 task __attribute__((packed));
- __u8 conn_high __attribute__((packed));
- __u8 function __attribute__((packed));
- __u8 data[0] __attribute__((packed));
-};
+ __u16 type;
+ __u8 sequence;
+ __u8 conn_low;
+ __u8 task;
+ __u8 conn_high;
+ __u8 function;
+ __u8 data[0];
+} __attribute__((packed));
#define NCP_REPLY (0x3333)
#define NCP_WATCHDOG (0x3E3E)
#define NCP_POSITIVE_ACK (0x9999)
struct ncp_reply_header {
- __u16 type __attribute__((packed));
- __u8 sequence __attribute__((packed));
- __u8 conn_low __attribute__((packed));
- __u8 task __attribute__((packed));
- __u8 conn_high __attribute__((packed));
- __u8 completion_code __attribute__((packed));
- __u8 connection_state __attribute__((packed));
- __u8 data[0] __attribute__((packed));
-};
+ __u16 type;
+ __u8 sequence;
+ __u8 conn_low;
+ __u8 task;
+ __u8 conn_high;
+ __u8 completion_code;
+ __u8 connection_state;
+ __u8 data[0];
+} __attribute__((packed));
#define NCP_VOLNAME_LEN (16)
#define NCP_NUMBER_OF_VOLUMES (256)
@@ -128,37 +128,37 @@ struct nw_nfs_info {
};
struct nw_info_struct {
- __u32 spaceAlloc __attribute__((packed));
- __le32 attributes __attribute__((packed));
- __u16 flags __attribute__((packed));
- __le32 dataStreamSize __attribute__((packed));
- __le32 totalStreamSize __attribute__((packed));
- __u16 numberOfStreams __attribute__((packed));
- __le16 creationTime __attribute__((packed));
- __le16 creationDate __attribute__((packed));
- __u32 creatorID __attribute__((packed));
- __le16 modifyTime __attribute__((packed));
- __le16 modifyDate __attribute__((packed));
- __u32 modifierID __attribute__((packed));
- __le16 lastAccessDate __attribute__((packed));
- __u16 archiveTime __attribute__((packed));
- __u16 archiveDate __attribute__((packed));
- __u32 archiverID __attribute__((packed));
- __u16 inheritedRightsMask __attribute__((packed));
- __le32 dirEntNum __attribute__((packed));
- __le32 DosDirNum __attribute__((packed));
- __u32 volNumber __attribute__((packed));
- __u32 EADataSize __attribute__((packed));
- __u32 EAKeyCount __attribute__((packed));
- __u32 EAKeySize __attribute__((packed));
- __u32 NSCreator __attribute__((packed));
- __u8 nameLen __attribute__((packed));
- __u8 entryName[256] __attribute__((packed));
+ __u32 spaceAlloc;
+ __le32 attributes;
+ __u16 flags;
+ __le32 dataStreamSize;
+ __le32 totalStreamSize;
+ __u16 numberOfStreams;
+ __le16 creationTime;
+ __le16 creationDate;
+ __u32 creatorID;
+ __le16 modifyTime;
+ __le16 modifyDate;
+ __u32 modifierID;
+ __le16 lastAccessDate;
+ __u16 archiveTime;
+ __u16 archiveDate;
+ __u32 archiverID;
+ __u16 inheritedRightsMask;
+ __le32 dirEntNum;
+ __le32 DosDirNum;
+ __u32 volNumber;
+ __u32 EADataSize;
+ __u32 EAKeyCount;
+ __u32 EAKeySize;
+ __u32 NSCreator;
+ __u8 nameLen;
+ __u8 entryName[256];
/* libncp may depend on there being nothing after entryName */
#ifdef __KERNEL__
struct nw_nfs_info nfs;
#endif
-};
+} __attribute__((packed));
/* modify mask - use with MODIFY_DOS_INFO structure */
#define DM_ATTRIBUTES (cpu_to_le32(0x02))
@@ -176,26 +176,26 @@ struct nw_info_struct {
#define DM_MAXIMUM_SPACE (cpu_to_le32(0x2000))
struct nw_modify_dos_info {
- __le32 attributes __attribute__((packed));
- __le16 creationDate __attribute__((packed));
- __le16 creationTime __attribute__((packed));
- __u32 creatorID __attribute__((packed));
- __le16 modifyDate __attribute__((packed));
- __le16 modifyTime __attribute__((packed));
- __u32 modifierID __attribute__((packed));
- __u16 archiveDate __attribute__((packed));
- __u16 archiveTime __attribute__((packed));
- __u32 archiverID __attribute__((packed));
- __le16 lastAccessDate __attribute__((packed));
- __u16 inheritanceGrantMask __attribute__((packed));
- __u16 inheritanceRevokeMask __attribute__((packed));
- __u32 maximumSpace __attribute__((packed));
-};
+ __le32 attributes;
+ __le16 creationDate;
+ __le16 creationTime;
+ __u32 creatorID;
+ __le16 modifyDate;
+ __le16 modifyTime;
+ __u32 modifierID;
+ __u16 archiveDate;
+ __u16 archiveTime;
+ __u32 archiverID;
+ __le16 lastAccessDate;
+ __u16 inheritanceGrantMask;
+ __u16 inheritanceRevokeMask;
+ __u32 maximumSpace;
+} __attribute__((packed));
struct nw_search_sequence {
- __u8 volNumber __attribute__((packed));
- __u32 dirBase __attribute__((packed));
- __u32 sequence __attribute__((packed));
-};
+ __u8 volNumber;
+ __u32 dirBase;
+ __u32 sequence;
+} __attribute__((packed));
#endif /* _LINUX_NCP_H */
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 7297e4372c0f..e01342568530 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -201,34 +201,6 @@ static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode)
return container_of(inode, struct ncp_inode_info, vfs_inode);
}
-#ifdef DEBUG_NCP_MALLOC
-
-#include <linux/slab.h>
-
-extern int ncp_malloced;
-extern int ncp_current_malloced;
-
-static inline void *
- ncp_kmalloc(unsigned int size, int priority)
-{
- ncp_malloced += 1;
- ncp_current_malloced += 1;
- return kmalloc(size, priority);
-}
-
-static inline void ncp_kfree_s(void *obj, int size)
-{
- ncp_current_malloced -= 1;
- kfree(obj);
-}
-
-#else /* DEBUG_NCP_MALLOC */
-
-#define ncp_kmalloc(s,p) kmalloc(s,p)
-#define ncp_kfree_s(o,s) kfree(o)
-
-#endif /* DEBUG_NCP_MALLOC */
-
/* linux/fs/ncpfs/inode.c */
int ncp_notify_change(struct dentry *, struct iattr *);
struct inode *ncp_iget(struct super_block *, struct ncp_entry_info *);
diff --git a/include/linux/net.h b/include/linux/net.h
index d6a41e6577f6..28195a2d8ff0 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -107,7 +107,7 @@ enum sock_type {
struct socket {
socket_state state;
unsigned long flags;
- struct proto_ops *ops;
+ const struct proto_ops *ops;
struct fasync_struct *fasync_list;
struct file *file;
struct sock *sk;
@@ -260,7 +260,7 @@ SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct ms
SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
(file, sock, vma)) \
\
-static struct proto_ops name##_ops = { \
+static const struct proto_ops name##_ops = { \
.family = fam, \
.owner = THIS_MODULE, \
.release = __lock_##name##_release, \
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 936f8b76114e..7fda03d338d1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -684,6 +684,7 @@ extern int netif_rx(struct sk_buff *skb);
extern int netif_rx_ni(struct sk_buff *skb);
#define HAVE_NETIF_RECEIVE_SKB 1
extern int netif_receive_skb(struct sk_buff *skb);
+extern int dev_valid_name(const char *name);
extern int dev_ioctl(unsigned int cmd, void __user *);
extern int dev_ethtool(struct ifreq *);
extern unsigned dev_get_flags(const struct net_device *);
@@ -801,12 +802,16 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits)
return (1 << debug_value) - 1;
}
-/* Schedule rx intr now? */
+/* Test if receive needs to be scheduled */
+static inline int __netif_rx_schedule_prep(struct net_device *dev)
+{
+ return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+/* Test if receive needs to be scheduled but only if up */
static inline int netif_rx_schedule_prep(struct net_device *dev)
{
- return netif_running(dev) &&
- !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state);
+ return netif_running(dev) && __netif_rx_schedule_prep(dev);
}
/* Add interface to tail of rx poll list. This assumes that _prep has
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index be365e70ee99..4cf6088625c1 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -168,6 +168,37 @@ void nf_log_packet(int pf,
const struct net_device *out,
struct nf_loginfo *li,
const char *fmt, ...);
+
+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 thresh);
+
+/**
+ * nf_hook_thresh - call a netfilter hook
+ *
+ * Returns 1 if the hook has allowed the packet to pass. The function
+ * okfn must be invoked by the caller in this case. Any other return
+ * value indicates the packet has been consumed by the hook.
+ */
+static inline int nf_hook_thresh(int pf, unsigned int hook,
+ struct sk_buff **pskb,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *), int thresh)
+{
+#ifndef CONFIG_NETFILTER_DEBUG
+ if (list_empty(&nf_hooks[pf][hook]))
+ return 1;
+#endif
+ return nf_hook_slow(pf, hook, pskb, indev, outdev, okfn, thresh);
+}
+
+static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
+ struct net_device *indev, struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
+{
+ return nf_hook_thresh(pf, hook, pskb, indev, outdev, okfn, INT_MIN);
+}
/* Activate hook; either okfn or kfree_skb called, unless a hook
returns NF_STOLEN (in which case, it's up to the hook to deal with
@@ -188,35 +219,17 @@ void nf_log_packet(int pf,
/* This is gross, but inline doesn't cut it for avoiding the function
call in fast path: gcc doesn't inline (needs value tracking?). --RR */
-#ifdef CONFIG_NETFILTER_DEBUG
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
-({int __ret; \
-if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
- __ret = (okfn)(skb); \
-__ret;})
-#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
-({int __ret; \
-if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1) \
- __ret = (okfn)(skb); \
-__ret;})
-#else
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
-({int __ret; \
-if (list_empty(&nf_hooks[pf][hook]) || \
- (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
- __ret = (okfn)(skb); \
-__ret;})
+
+/* HX: It's slightly less gross now. */
+
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
({int __ret; \
-if (list_empty(&nf_hooks[pf][hook]) || \
- (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1) \
+if ((__ret=nf_hook_thresh(pf, hook, &(skb), indev, outdev, okfn, thresh)) == 1)\
__ret = (okfn)(skb); \
__ret;})
-#endif
-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 thresh);
+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
+ NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)
/* Call setsockopt() */
int nf_setsockopt(struct sock *sk, int pf, int optval, char __user *opt,
@@ -261,6 +274,20 @@ struct nf_queue_rerouter {
extern int nf_register_queue_rerouter(int pf, struct nf_queue_rerouter *rer);
extern int nf_unregister_queue_rerouter(int pf);
+#include <net/flow.h>
+extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
+
+static inline void
+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
+{
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+ void (*decodefn)(struct sk_buff *, struct flowi *);
+
+ if (family == AF_INET && (decodefn = ip_nat_decode_session) != NULL)
+ decodefn(skb, fl);
+#endif
+}
+
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
extern struct proc_dir_entry *proc_net_netfilter;
@@ -268,7 +295,24 @@ extern struct proc_dir_entry *proc_net_netfilter;
#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
+static inline int nf_hook_thresh(int pf, unsigned int hook,
+ struct sk_buff **pskb,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *), int thresh)
+{
+ return okfn(*pskb);
+}
+static inline int nf_hook(int pf, unsigned int hook, struct sk_buff **pskb,
+ struct net_device *indev, struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
+{
+ return okfn(*pskb);
+}
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+struct flowi;
+static inline void
+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) {}
#endif /*CONFIG_NETFILTER*/
#endif /*__KERNEL__*/
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 6d39b518486b..3ff88c878308 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -154,6 +154,9 @@ struct ip_conntrack_stat
unsigned int expect_delete;
};
+/* call to create an explicit dependency on nf_conntrack. */
+extern void need_conntrack(void);
+
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_COMMON_H */
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 116fcaced909..668ec946c8e2 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -64,6 +64,9 @@ enum ctattr_l4proto {
CTA_PROTO_ICMP_ID,
CTA_PROTO_ICMP_TYPE,
CTA_PROTO_ICMP_CODE,
+ CTA_PROTO_ICMPV6_ID,
+ CTA_PROTO_ICMPV6_TYPE,
+ CTA_PROTO_ICMPV6_CODE,
__CTA_PROTO_MAX
};
#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
@@ -128,6 +131,4 @@ enum ctattr_help {
};
#define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
-#define CTA_HELP_MAXNAMESIZE 32
-
#endif /* _IPCONNTRACK_NETLINK_H */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
new file mode 100644
index 000000000000..472f04834809
--- /dev/null
+++ b/include/linux/netfilter/x_tables.h
@@ -0,0 +1,224 @@
+#ifndef _X_TABLES_H
+#define _X_TABLES_H
+
+#define XT_FUNCTION_MAXNAMELEN 30
+#define XT_TABLE_MAXNAMELEN 32
+
+/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
+ * kernel supports, if >= revision. */
+struct xt_get_revision
+{
+ char name[XT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t revision;
+};
+
+/* CONTINUE verdict for targets */
+#define XT_CONTINUE 0xFFFFFFFF
+
+/* For standard target */
+#define XT_RETURN (-NF_REPEAT - 1)
+
+#define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1))
+
+/* Standard return verdict, or do jump. */
+#define XT_STANDARD_TARGET ""
+/* Error verdict. */
+#define XT_ERROR_TARGET "ERROR"
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use a raw
+ * socket for this. Instead we check rights in the calls. */
+#define XT_BASE_CTL 64 /* base for firewall socket options */
+
+#define XT_SO_SET_REPLACE (XT_BASE_CTL)
+#define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1)
+#define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS
+
+#define XT_SO_GET_INFO (XT_BASE_CTL)
+#define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1)
+#define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2)
+#define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3)
+#define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET
+
+#define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0)
+#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
+
+struct xt_counters
+{
+ u_int64_t pcnt, bcnt; /* Packet and byte counters */
+};
+
+/* The argument to IPT_SO_ADD_COUNTERS. */
+struct xt_counters_info
+{
+ /* Which table. */
+ char name[XT_TABLE_MAXNAMELEN];
+
+ unsigned int num_counters;
+
+ /* The counters (actually `number' of these). */
+ struct xt_counters counters[0];
+};
+
+#define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
+
+#ifdef __KERNEL__
+
+#include <linux/netdevice.h>
+
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
+#include <linux/netfilter_ipv4/listhelp.h>
+
+struct xt_match
+{
+ struct list_head list;
+
+ const char name[XT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t revision;
+
+ /* Return true or false: return FALSE and set *hotdrop = 1 to
+ force immediate packet drop. */
+ /* Arguments changed since 2.6.9, as this must now handle
+ non-linear skb, using skb_header_pointer and
+ skb_ip_make_writable. */
+ int (*match)(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop);
+
+ /* Called when user tries to insert an entry of this type. */
+ /* Should return true or false. */
+ int (*checkentry)(const char *tablename,
+ const void *ip,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask);
+
+ /* Called when entry of this type deleted. */
+ void (*destroy)(void *matchinfo, unsigned int matchinfosize);
+
+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
+ struct module *me;
+};
+
+/* Registration hooks for targets. */
+struct xt_target
+{
+ struct list_head list;
+
+ const char name[XT_FUNCTION_MAXNAMELEN-1];
+
+ u_int8_t revision;
+
+ /* Returns verdict. Argument order changed since 2.6.9, as this
+ must now handle non-linear skbs, using skb_copy_bits and
+ skb_ip_make_writable. */
+ unsigned int (*target)(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const void *targinfo,
+ void *userdata);
+
+ /* Called when user tries to insert an entry of this type:
+ hook_mask is a bitmask of hooks from which it can be
+ called. */
+ /* Should return true or false. */
+ int (*checkentry)(const char *tablename,
+ const void *entry,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask);
+
+ /* Called when entry of this type deleted. */
+ void (*destroy)(void *targinfo, unsigned int targinfosize);
+
+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
+ struct module *me;
+};
+
+/* Furniture shopping... */
+struct xt_table
+{
+ struct list_head list;
+
+ /* A unique name... */
+ char name[XT_TABLE_MAXNAMELEN];
+
+ /* What hooks you will enter on */
+ unsigned int valid_hooks;
+
+ /* Lock for the curtain */
+ rwlock_t lock;
+
+ /* Man behind the curtain... */
+ //struct ip6t_table_info *private;
+ void *private;
+
+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
+ struct module *me;
+
+ int af; /* address/protocol family */
+};
+
+#include <linux/netfilter_ipv4.h>
+
+/* The table itself */
+struct xt_table_info
+{
+ /* Size per table */
+ unsigned int size;
+ /* Number of entries: FIXME. --RR */
+ unsigned int number;
+ /* Initial number of entries. Needed for module usage count */
+ unsigned int initial_entries;
+
+ /* Entry points and underflows */
+ unsigned int hook_entry[NF_IP_NUMHOOKS];
+ unsigned int underflow[NF_IP_NUMHOOKS];
+
+ /* ipt_entry tables: one per CPU */
+ char *entries[NR_CPUS];
+};
+
+extern int xt_register_target(int af, struct xt_target *target);
+extern void xt_unregister_target(int af, struct xt_target *target);
+extern int xt_register_match(int af, struct xt_match *target);
+extern void xt_unregister_match(int af, struct xt_match *target);
+
+extern int xt_register_table(struct xt_table *table,
+ struct xt_table_info *bootstrap,
+ struct xt_table_info *newinfo);
+extern void *xt_unregister_table(struct xt_table *table);
+
+extern struct xt_table_info *xt_replace_table(struct xt_table *table,
+ unsigned int num_counters,
+ struct xt_table_info *newinfo,
+ int *error);
+
+extern struct xt_match *xt_find_match(int af, const char *name, u8 revision);
+extern struct xt_target *xt_find_target(int af, const char *name, u8 revision);
+extern struct xt_target *xt_request_find_target(int af, const char *name,
+ u8 revision);
+extern int xt_find_revision(int af, const char *name, u8 revision, int target,
+ int *err);
+
+extern struct xt_table *xt_find_table_lock(int af, const char *name);
+extern void xt_table_unlock(struct xt_table *t);
+
+extern int xt_proto_init(int af);
+extern void xt_proto_fini(int af);
+
+extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
+extern void xt_free_table_info(struct xt_table_info *info);
+
+#endif /* __KERNEL__ */
+
+#endif /* _X_TABLES_H */
diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h
new file mode 100644
index 000000000000..58111355255d
--- /dev/null
+++ b/include/linux/netfilter/xt_CLASSIFY.h
@@ -0,0 +1,8 @@
+#ifndef _XT_CLASSIFY_H
+#define _XT_CLASSIFY_H
+
+struct xt_classify_target_info {
+ u_int32_t priority;
+};
+
+#endif /*_XT_CLASSIFY_H */
diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h
new file mode 100644
index 000000000000..9f744689fffc
--- /dev/null
+++ b/include/linux/netfilter/xt_CONNMARK.h
@@ -0,0 +1,25 @@
+#ifndef _XT_CONNMARK_H_target
+#define _XT_CONNMARK_H_target
+
+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.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.
+ */
+
+enum {
+ XT_CONNMARK_SET = 0,
+ XT_CONNMARK_SAVE,
+ XT_CONNMARK_RESTORE
+};
+
+struct xt_connmark_target_info {
+ unsigned long mark;
+ unsigned long mask;
+ u_int8_t mode;
+};
+
+#endif /*_XT_CONNMARK_H_target*/
diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h
new file mode 100644
index 000000000000..b021e93ee5d6
--- /dev/null
+++ b/include/linux/netfilter/xt_MARK.h
@@ -0,0 +1,21 @@
+#ifndef _XT_MARK_H_target
+#define _XT_MARK_H_target
+
+/* Version 0 */
+struct xt_mark_target_info {
+ unsigned long mark;
+};
+
+/* Version 1 */
+enum {
+ XT_MARK_SET=0,
+ XT_MARK_AND,
+ XT_MARK_OR,
+};
+
+struct xt_mark_target_info_v1 {
+ unsigned long mark;
+ u_int8_t mode;
+};
+
+#endif /*_XT_MARK_H_target */
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h
new file mode 100644
index 000000000000..9a9af79f74d2
--- /dev/null
+++ b/include/linux/netfilter/xt_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 _XT_NFQ_TARGET_H
+#define _XT_NFQ_TARGET_H
+
+/* target info */
+struct xt_NFQ_info {
+ u_int16_t queuenum;
+};
+
+#endif /* _XT_NFQ_TARGET_H */
diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h
new file mode 100644
index 000000000000..eacfedc6b5d0
--- /dev/null
+++ b/include/linux/netfilter/xt_comment.h
@@ -0,0 +1,10 @@
+#ifndef _XT_COMMENT_H
+#define _XT_COMMENT_H
+
+#define XT_MAX_COMMENT_LEN 256
+
+struct xt_comment_info {
+ unsigned char comment[XT_MAX_COMMENT_LEN];
+};
+
+#endif /* XT_COMMENT_H */
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h
new file mode 100644
index 000000000000..c022c989754d
--- /dev/null
+++ b/include/linux/netfilter/xt_connbytes.h
@@ -0,0 +1,25 @@
+#ifndef _XT_CONNBYTES_H
+#define _XT_CONNBYTES_H
+
+enum xt_connbytes_what {
+ XT_CONNBYTES_PKTS,
+ XT_CONNBYTES_BYTES,
+ XT_CONNBYTES_AVGPKT,
+};
+
+enum xt_connbytes_direction {
+ XT_CONNBYTES_DIR_ORIGINAL,
+ XT_CONNBYTES_DIR_REPLY,
+ XT_CONNBYTES_DIR_BOTH,
+};
+
+struct xt_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/xt_connmark.h b/include/linux/netfilter/xt_connmark.h
new file mode 100644
index 000000000000..c592f6ae0883
--- /dev/null
+++ b/include/linux/netfilter/xt_connmark.h
@@ -0,0 +1,18 @@
+#ifndef _XT_CONNMARK_H
+#define _XT_CONNMARK_H
+
+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.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.
+ */
+
+struct xt_connmark_info {
+ unsigned long mark, mask;
+ u_int8_t invert;
+};
+
+#endif /*_XT_CONNMARK_H*/
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
new file mode 100644
index 000000000000..34f63cf2e293
--- /dev/null
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -0,0 +1,63 @@
+/* Header file for kernel module to match connection tracking information.
+ * GPL (C) 2001 Marc Boucher (marc@mbsi.ca).
+ */
+
+#ifndef _XT_CONNTRACK_H
+#define _XT_CONNTRACK_H
+
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <linux/in.h>
+
+#define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
+#define XT_CONNTRACK_STATE_INVALID (1 << 0)
+
+#define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
+#define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
+#define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
+
+/* flags, invflags: */
+#define XT_CONNTRACK_STATE 0x01
+#define XT_CONNTRACK_PROTO 0x02
+#define XT_CONNTRACK_ORIGSRC 0x04
+#define XT_CONNTRACK_ORIGDST 0x08
+#define XT_CONNTRACK_REPLSRC 0x10
+#define XT_CONNTRACK_REPLDST 0x20
+#define XT_CONNTRACK_STATUS 0x40
+#define XT_CONNTRACK_EXPIRES 0x80
+
+/* This is exposed to userspace, so remains frozen in time. */
+struct ip_conntrack_old_tuple
+{
+ struct {
+ __u32 ip;
+ union {
+ __u16 all;
+ } u;
+ } src;
+
+ struct {
+ __u32 ip;
+ union {
+ __u16 all;
+ } u;
+
+ /* The protocol. */
+ u16 protonum;
+ } dst;
+};
+
+struct xt_conntrack_info
+{
+ unsigned int statemask, statusmask;
+
+ struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
+ struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
+
+ unsigned long expires_min, expires_max;
+
+ /* Flags word */
+ u_int8_t flags;
+ /* Inverse flags */
+ u_int8_t invflags;
+};
+#endif /*_XT_CONNTRACK_H*/
diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h
new file mode 100644
index 000000000000..e0221b9d32cb
--- /dev/null
+++ b/include/linux/netfilter/xt_dccp.h
@@ -0,0 +1,23 @@
+#ifndef _XT_DCCP_H_
+#define _XT_DCCP_H_
+
+#define XT_DCCP_SRC_PORTS 0x01
+#define XT_DCCP_DEST_PORTS 0x02
+#define XT_DCCP_TYPE 0x04
+#define XT_DCCP_OPTION 0x08
+
+#define XT_DCCP_VALID_FLAGS 0x0f
+
+struct xt_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 /* _XT_DCCP_H_ */
+
diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h
new file mode 100644
index 000000000000..6b42763f999d
--- /dev/null
+++ b/include/linux/netfilter/xt_helper.h
@@ -0,0 +1,8 @@
+#ifndef _XT_HELPER_H
+#define _XT_HELPER_H
+
+struct xt_helper_info {
+ int invert;
+ char name[30];
+};
+#endif /* _XT_HELPER_H */
diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h
new file mode 100644
index 000000000000..7c2b439f73fe
--- /dev/null
+++ b/include/linux/netfilter/xt_length.h
@@ -0,0 +1,9 @@
+#ifndef _XT_LENGTH_H
+#define _XT_LENGTH_H
+
+struct xt_length_info {
+ u_int16_t min, max;
+ u_int8_t invert;
+};
+
+#endif /*_XT_LENGTH_H*/
diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h
new file mode 100644
index 000000000000..b3ce65375ecb
--- /dev/null
+++ b/include/linux/netfilter/xt_limit.h
@@ -0,0 +1,21 @@
+#ifndef _XT_RATE_H
+#define _XT_RATE_H
+
+/* timings are in milliseconds. */
+#define XT_LIMIT_SCALE 10000
+
+/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
+ seconds, or one every 59 hours. */
+struct xt_rateinfo {
+ u_int32_t avg; /* Average secs between packets * scale */
+ u_int32_t burst; /* Period multiplier for upper limit. */
+
+ /* Used internally by the kernel */
+ unsigned long prev;
+ u_int32_t credit;
+ u_int32_t credit_cap, cost;
+
+ /* Ugly, ugly fucker. */
+ struct xt_rateinfo *master;
+};
+#endif /*_XT_RATE_H*/
diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h
new file mode 100644
index 000000000000..b892cdc67e06
--- /dev/null
+++ b/include/linux/netfilter/xt_mac.h
@@ -0,0 +1,8 @@
+#ifndef _XT_MAC_H
+#define _XT_MAC_H
+
+struct xt_mac_info {
+ unsigned char srcaddr[ETH_ALEN];
+ int invert;
+};
+#endif /*_XT_MAC_H*/
diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h
new file mode 100644
index 000000000000..802dd4842caf
--- /dev/null
+++ b/include/linux/netfilter/xt_mark.h
@@ -0,0 +1,9 @@
+#ifndef _XT_MARK_H
+#define _XT_MARK_H
+
+struct xt_mark_info {
+ unsigned long mark, mask;
+ u_int8_t invert;
+};
+
+#endif /*_XT_MARK_H*/
diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h
new file mode 100644
index 000000000000..25a7a1815b5b
--- /dev/null
+++ b/include/linux/netfilter/xt_physdev.h
@@ -0,0 +1,24 @@
+#ifndef _XT_PHYSDEV_H
+#define _XT_PHYSDEV_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+
+#define XT_PHYSDEV_OP_IN 0x01
+#define XT_PHYSDEV_OP_OUT 0x02
+#define XT_PHYSDEV_OP_BRIDGED 0x04
+#define XT_PHYSDEV_OP_ISIN 0x08
+#define XT_PHYSDEV_OP_ISOUT 0x10
+#define XT_PHYSDEV_OP_MASK (0x20 - 1)
+
+struct xt_physdev_info {
+ char physindev[IFNAMSIZ];
+ char in_mask[IFNAMSIZ];
+ char physoutdev[IFNAMSIZ];
+ char out_mask[IFNAMSIZ];
+ u_int8_t invert;
+ u_int8_t bitmask;
+};
+
+#endif /*_XT_PHYSDEV_H*/
diff --git a/include/linux/netfilter/xt_pkttype.h b/include/linux/netfilter/xt_pkttype.h
new file mode 100644
index 000000000000..f265cf52faea
--- /dev/null
+++ b/include/linux/netfilter/xt_pkttype.h
@@ -0,0 +1,8 @@
+#ifndef _XT_PKTTYPE_H
+#define _XT_PKTTYPE_H
+
+struct xt_pkttype_info {
+ int pkttype;
+ int invert;
+};
+#endif /*_XT_PKTTYPE_H*/
diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h
new file mode 100644
index 000000000000..220e87245716
--- /dev/null
+++ b/include/linux/netfilter/xt_realm.h
@@ -0,0 +1,10 @@
+#ifndef _XT_REALM_H
+#define _XT_REALM_H
+
+struct xt_realm_info {
+ u_int32_t id;
+ u_int32_t mask;
+ u_int8_t invert;
+};
+
+#endif /* _XT_REALM_H */
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h
new file mode 100644
index 000000000000..b157897e7792
--- /dev/null
+++ b/include/linux/netfilter/xt_sctp.h
@@ -0,0 +1,107 @@
+#ifndef _XT_SCTP_H_
+#define _XT_SCTP_H_
+
+#define XT_SCTP_SRC_PORTS 0x01
+#define XT_SCTP_DEST_PORTS 0x02
+#define XT_SCTP_CHUNK_TYPES 0x04
+
+#define XT_SCTP_VALID_FLAGS 0x07
+
+#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
+
+
+struct xt_sctp_flag_info {
+ u_int8_t chunktype;
+ u_int8_t flag;
+ u_int8_t flag_mask;
+};
+
+#define XT_NUM_SCTP_FLAGS 4
+
+struct xt_sctp_info {
+ u_int16_t dpts[2]; /* Min, Max */
+ u_int16_t spts[2]; /* Min, Max */
+
+ u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
+
+#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
+
+ u_int32_t chunk_match_type;
+ struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS];
+ int flag_count;
+
+ u_int32_t flags;
+ u_int32_t invflags;
+};
+
+#define bytes(type) (sizeof(type) * 8)
+
+#define SCTP_CHUNKMAP_SET(chunkmap, type) \
+ do { \
+ chunkmap[type / bytes(u_int32_t)] |= \
+ 1 << (type % bytes(u_int32_t)); \
+ } while (0)
+
+#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
+ do { \
+ chunkmap[type / bytes(u_int32_t)] &= \
+ ~(1 << (type % bytes(u_int32_t))); \
+ } while (0)
+
+#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
+({ \
+ (chunkmap[type / bytes (u_int32_t)] & \
+ (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
+})
+
+#define SCTP_CHUNKMAP_RESET(chunkmap) \
+ do { \
+ int i; \
+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ chunkmap[i] = 0; \
+ } while (0)
+
+#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
+ do { \
+ int i; \
+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ chunkmap[i] = ~0; \
+ } while (0)
+
+#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
+ do { \
+ int i; \
+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
+ destmap[i] = srcmap[i]; \
+ } while (0)
+
+#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
+({ \
+ int i; \
+ int flag = 1; \
+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
+ if (chunkmap[i]) { \
+ flag = 0; \
+ break; \
+ } \
+ } \
+ flag; \
+})
+
+#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
+({ \
+ int i; \
+ int flag = 1; \
+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
+ if (chunkmap[i] != ~0) { \
+ flag = 0; \
+ break; \
+ } \
+ } \
+ flag; \
+})
+
+#endif /* _XT_SCTP_H_ */
+
diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h
new file mode 100644
index 000000000000..c06f32edee07
--- /dev/null
+++ b/include/linux/netfilter/xt_state.h
@@ -0,0 +1,13 @@
+#ifndef _XT_STATE_H
+#define _XT_STATE_H
+
+#define XT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
+#define XT_STATE_INVALID (1 << 0)
+
+#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
+
+struct xt_state_info
+{
+ unsigned int statemask;
+};
+#endif /*_XT_STATE_H*/
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h
new file mode 100644
index 000000000000..3b3419f2637d
--- /dev/null
+++ b/include/linux/netfilter/xt_string.h
@@ -0,0 +1,18 @@
+#ifndef _XT_STRING_H
+#define _XT_STRING_H
+
+#define XT_STRING_MAX_PATTERN_SIZE 128
+#define XT_STRING_MAX_ALGO_NAME_SIZE 16
+
+struct xt_string_info
+{
+ u_int16_t from_offset;
+ u_int16_t to_offset;
+ char algo[XT_STRING_MAX_ALGO_NAME_SIZE];
+ char pattern[XT_STRING_MAX_PATTERN_SIZE];
+ u_int8_t patlen;
+ u_int8_t invert;
+ struct ts_config __attribute__((aligned(8))) *config;
+};
+
+#endif /*_XT_STRING_H*/
diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h
new file mode 100644
index 000000000000..e03274c4c790
--- /dev/null
+++ b/include/linux/netfilter/xt_tcpmss.h
@@ -0,0 +1,9 @@
+#ifndef _XT_TCPMSS_MATCH_H
+#define _XT_TCPMSS_MATCH_H
+
+struct xt_tcpmss_match_info {
+ u_int16_t mss_min, mss_max;
+ u_int8_t invert;
+};
+
+#endif /*_XT_TCPMSS_MATCH_H*/
diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h
new file mode 100644
index 000000000000..78bc65f11adf
--- /dev/null
+++ b/include/linux/netfilter/xt_tcpudp.h
@@ -0,0 +1,36 @@
+#ifndef _XT_TCPUDP_H
+#define _XT_TCPUDP_H
+
+/* TCP matching stuff */
+struct xt_tcp
+{
+ u_int16_t spts[2]; /* Source port range. */
+ u_int16_t dpts[2]; /* Destination port range. */
+ u_int8_t option; /* TCP Option iff non-zero*/
+ u_int8_t flg_mask; /* TCP flags mask byte */
+ u_int8_t flg_cmp; /* TCP flags compare byte */
+ u_int8_t invflags; /* Inverse flags */
+};
+
+/* Values for "inv" field in struct ipt_tcp. */
+#define XT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
+#define XT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
+#define XT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
+#define XT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
+#define XT_TCP_INV_MASK 0x0F /* All possible flags. */
+
+/* UDP matching stuff */
+struct xt_udp
+{
+ u_int16_t spts[2]; /* Source port range. */
+ u_int16_t dpts[2]; /* Destination port range. */
+ u_int8_t invflags; /* Inverse flags */
+};
+
+/* Values for "invflags" field in struct ipt_udp. */
+#define XT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
+#define XT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
+#define XT_UDP_INV_MASK 0x03 /* All possible flags. */
+
+
+#endif
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index e98a870a20be..fd21796e5131 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -19,8 +19,12 @@
#include <linux/compiler.h>
#include <linux/netfilter_arp.h>
-#define ARPT_FUNCTION_MAXNAMELEN 30
-#define ARPT_TABLE_MAXNAMELEN 32
+#include <linux/netfilter/x_tables.h>
+
+#define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+#define arpt_target xt_target
+#define arpt_table xt_table
#define ARPT_DEV_ADDR_LEN_MAX 16
@@ -91,11 +95,6 @@ struct arpt_standard_target
int verdict;
};
-struct arpt_counters
-{
- u_int64_t pcnt, bcnt; /* Packet and byte counters */
-};
-
/* Values for "flag" field in struct arpt_ip (general arp structure).
* No flags defined yet.
*/
@@ -130,7 +129,7 @@ struct arpt_entry
unsigned int comefrom;
/* Packet and byte counters. */
- struct arpt_counters counters;
+ struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
@@ -141,23 +140,24 @@ struct arpt_entry
* Unlike BSD Linux inherits IP options so you don't have to use a raw
* socket for this. Instead we check rights in the calls.
*/
-#define ARPT_BASE_CTL 96 /* base for firewall socket options */
+#define ARPT_CTL_OFFSET 32
+#define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET)
-#define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL)
-#define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1)
-#define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS
+#define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET)
+#define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET)
+#define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET)
-#define ARPT_SO_GET_INFO (ARPT_BASE_CTL)
-#define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1)
-/* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/
-#define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3)
-#define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET
+#define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET)
+#define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET)
+/* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */
+#define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET)
+#define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET)
/* CONTINUE verdict for targets */
-#define ARPT_CONTINUE 0xFFFFFFFF
+#define ARPT_CONTINUE XT_CONTINUE
/* For standard target */
-#define ARPT_RETURN (-NF_REPEAT - 1)
+#define ARPT_RETURN XT_RETURN
/* The argument to ARPT_SO_GET_INFO */
struct arpt_getinfo
@@ -208,23 +208,14 @@ struct arpt_replace
/* Number of counters (must be equal to current number of entries). */
unsigned int num_counters;
/* The old entries' counters. */
- struct arpt_counters __user *counters;
+ struct xt_counters __user *counters;
/* The entries (hang off end: not really an array). */
struct arpt_entry entries[0];
};
/* The argument to ARPT_SO_ADD_COUNTERS. */
-struct arpt_counters_info
-{
- /* Which table. */
- char name[ARPT_TABLE_MAXNAMELEN];
-
- unsigned int num_counters;
-
- /* The counters (actually `number' of these). */
- struct arpt_counters counters[0];
-};
+#define arpt_counters_info xt_counters_info
/* The argument to ARPT_SO_GET_ENTRIES. */
struct arpt_get_entries
@@ -239,19 +230,10 @@ struct arpt_get_entries
struct arpt_entry entrytable[0];
};
-/* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision
- * kernel supports, if >= revision. */
-struct arpt_get_revision
-{
- char name[ARPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-};
-
/* Standard return verdict, or do jump. */
-#define ARPT_STANDARD_TARGET ""
+#define ARPT_STANDARD_TARGET XT_STANDARD_TARGET
/* Error verdict. */
-#define ARPT_ERROR_TARGET "ERROR"
+#define ARPT_ERROR_TARGET XT_ERROR_TARGET
/* Helper functions */
static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e)
@@ -281,63 +263,8 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
*/
#ifdef __KERNEL__
-/* Registration hooks for targets. */
-struct arpt_target
-{
- struct list_head list;
-
- const char name[ARPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-
- /* Returns verdict. */
- unsigned int (*target)(struct sk_buff **pskb,
- unsigned int hooknum,
- const struct net_device *in,
- const struct net_device *out,
- const void *targinfo,
- void *userdata);
-
- /* Called when user tries to insert an entry of this type:
- hook_mask is a bitmask of hooks from which it can be
- called. */
- /* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const struct arpt_entry *e,
- void *targinfo,
- unsigned int targinfosize,
- unsigned int hook_mask);
-
- /* Called when entry of this type deleted. */
- void (*destroy)(void *targinfo, unsigned int targinfosize);
-
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
-};
-
-extern int arpt_register_target(struct arpt_target *target);
-extern void arpt_unregister_target(struct arpt_target *target);
-
-/* Furniture shopping... */
-struct arpt_table
-{
- struct list_head list;
-
- /* A unique name... */
- char name[ARPT_TABLE_MAXNAMELEN];
-
- /* What hooks you will enter on */
- unsigned int valid_hooks;
-
- /* Lock for the curtain */
- rwlock_t lock;
-
- /* Man behind the curtain... */
- struct arpt_table_info *private;
-
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
-};
+#define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt)
+#define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt)
extern int arpt_register_table(struct arpt_table *table,
const struct arpt_replace *repl);
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index b3432ab59a17..215765f043e6 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -199,9 +199,6 @@ ip_conntrack_put(struct ip_conntrack *ct)
nf_conntrack_put(&ct->ct_general);
}
-/* call to create an explicit dependency on ip_conntrack. */
-extern void need_ip_conntrack(void);
-
extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig);
diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
index ef63aa991a06..612a43614e7b 100644
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h
+++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h
@@ -42,13 +42,6 @@ struct ip_nat_protocol
enum ip_nat_manip_type maniptype,
const struct ip_conntrack *conntrack);
- unsigned int (*print)(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask);
-
- unsigned int (*print_range)(char *buffer,
- const struct ip_nat_range *range);
-
int (*range_to_nfattr)(struct sk_buff *skb,
const struct ip_nat_range *range);
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index d19d65cf4530..76ba24b68515 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -25,8 +25,14 @@
#include <linux/compiler.h>
#include <linux/netfilter_ipv4.h>
-#define IPT_FUNCTION_MAXNAMELEN 30
-#define IPT_TABLE_MAXNAMELEN 32
+#include <linux/netfilter/x_tables.h>
+
+#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define ipt_match xt_match
+#define ipt_target xt_target
+#define ipt_table xt_table
+#define ipt_get_revision xt_get_revision
/* Yes, Virginia, you have to zero the padding. */
struct ipt_ip {
@@ -102,10 +108,7 @@ struct ipt_standard_target
int verdict;
};
-struct ipt_counters
-{
- u_int64_t pcnt, bcnt; /* Packet and byte counters */
-};
+#define ipt_counters xt_counters
/* Values for "flag" field in struct ipt_ip (general ip structure). */
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
@@ -119,7 +122,7 @@ struct ipt_counters
#define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
#define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
#define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */
-#define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
+#define IPT_INV_PROTO XT_INV_PROTO
#define IPT_INV_MASK 0x7F /* All possible flag bits mask. */
/* This structure defines each of the firewall rules. Consists of 3
@@ -141,7 +144,7 @@ struct ipt_entry
unsigned int comefrom;
/* Packet and byte counters. */
- struct ipt_counters counters;
+ struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
@@ -151,54 +154,34 @@ struct ipt_entry
* New IP firewall options for [gs]etsockopt at the RAW IP level.
* Unlike BSD Linux inherits IP options so you don't have to use a raw
* socket for this. Instead we check rights in the calls. */
-#define IPT_BASE_CTL 64 /* base for firewall socket options */
+#define IPT_BASE_CTL XT_BASE_CTL
-#define IPT_SO_SET_REPLACE (IPT_BASE_CTL)
-#define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1)
-#define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS
+#define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE
+#define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS
+#define IPT_SO_SET_MAX XT_SO_SET_MAX
-#define IPT_SO_GET_INFO (IPT_BASE_CTL)
-#define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1)
-#define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2)
-#define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3)
-#define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET
+#define IPT_SO_GET_INFO XT_SO_GET_INFO
+#define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES
+#define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH
+#define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET
+#define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET
-/* CONTINUE verdict for targets */
-#define IPT_CONTINUE 0xFFFFFFFF
+#define IPT_CONTINUE XT_CONTINUE
+#define IPT_RETURN XT_RETURN
-/* For standard target */
-#define IPT_RETURN (-NF_REPEAT - 1)
+#include <linux/netfilter/xt_tcpudp.h>
+#define ipt_udp xt_udp
+#define ipt_tcp xt_tcp
-/* TCP matching stuff */
-struct ipt_tcp
-{
- u_int16_t spts[2]; /* Source port range. */
- u_int16_t dpts[2]; /* Destination port range. */
- u_int8_t option; /* TCP Option iff non-zero*/
- u_int8_t flg_mask; /* TCP flags mask byte */
- u_int8_t flg_cmp; /* TCP flags compare byte */
- u_int8_t invflags; /* Inverse flags */
-};
-
-/* Values for "inv" field in struct ipt_tcp. */
-#define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
-#define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
-#define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
-#define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
-#define IPT_TCP_INV_MASK 0x0F /* All possible flags. */
-
-/* UDP matching stuff */
-struct ipt_udp
-{
- u_int16_t spts[2]; /* Source port range. */
- u_int16_t dpts[2]; /* Destination port range. */
- u_int8_t invflags; /* Inverse flags */
-};
+#define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT
+#define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT
+#define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS
+#define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION
+#define IPT_TCP_INV_MASK XT_TCP_INV_MASK
-/* Values for "invflags" field in struct ipt_udp. */
-#define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
-#define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
-#define IPT_UDP_INV_MASK 0x03 /* All possible flags. */
+#define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT
+#define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT
+#define IPT_UDP_INV_MASK XT_UDP_INV_MASK
/* ICMP matching stuff */
struct ipt_icmp
@@ -260,23 +243,14 @@ struct ipt_replace
/* Number of counters (must be equal to current number of entries). */
unsigned int num_counters;
/* The old entries' counters. */
- struct ipt_counters __user *counters;
+ struct xt_counters __user *counters;
/* The entries (hang off end: not really an array). */
struct ipt_entry entries[0];
};
/* The argument to IPT_SO_ADD_COUNTERS. */
-struct ipt_counters_info
-{
- /* Which table. */
- char name[IPT_TABLE_MAXNAMELEN];
-
- unsigned int num_counters;
-
- /* The counters (actually `number' of these). */
- struct ipt_counters counters[0];
-};
+#define ipt_counters_info xt_counters_info
/* The argument to IPT_SO_GET_ENTRIES. */
struct ipt_get_entries
@@ -291,19 +265,10 @@ struct ipt_get_entries
struct ipt_entry entrytable[0];
};
-/* The argument to IPT_SO_GET_REVISION_*. Returns highest revision
- * kernel supports, if >= revision. */
-struct ipt_get_revision
-{
- char name[IPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-};
-
/* Standard return verdict, or do jump. */
-#define IPT_STANDARD_TARGET ""
+#define IPT_STANDARD_TARGET XT_STANDARD_TARGET
/* Error verdict. */
-#define IPT_ERROR_TARGET "ERROR"
+#define IPT_ERROR_TARGET XT_ERROR_TARGET
/* Helper functions */
static __inline__ struct ipt_entry_target *
@@ -356,103 +321,18 @@ ipt_get_target(struct ipt_entry *e)
#include <linux/init.h>
extern void ipt_init(void) __init;
-struct ipt_match
-{
- struct list_head list;
-
- const char name[IPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-
- /* Return true or false: return FALSE and set *hotdrop = 1 to
- force immediate packet drop. */
- /* Arguments changed since 2.4, as this must now handle
- non-linear skbs, using skb_copy_bits and
- skb_ip_make_writable. */
- int (*match)(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- int *hotdrop);
-
- /* Called when user tries to insert an entry of this type. */
- /* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const struct ipt_ip *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask);
-
- /* Called when entry of this type deleted. */
- void (*destroy)(void *matchinfo, unsigned int matchinfosize);
-
- /* Set this to THIS_MODULE. */
- struct module *me;
-};
-
-/* Registration hooks for targets. */
-struct ipt_target
-{
- struct list_head list;
-
- const char name[IPT_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-
- /* Called when user tries to insert an entry of this type:
- hook_mask is a bitmask of hooks from which it can be
- called. */
- /* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const struct ipt_entry *e,
- void *targinfo,
- unsigned int targinfosize,
- unsigned int hook_mask);
-
- /* Called when entry of this type deleted. */
- void (*destroy)(void *targinfo, unsigned int targinfosize);
-
- /* Returns verdict. Argument order changed since 2.4, as this
- must now handle non-linear skbs, using skb_copy_bits and
- skb_ip_make_writable. */
- unsigned int (*target)(struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const void *targinfo,
- void *userdata);
-
- /* Set this to THIS_MODULE. */
- struct module *me;
-};
+#define ipt_register_target(tgt) xt_register_target(AF_INET, tgt)
+#define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt)
-extern int ipt_register_target(struct ipt_target *target);
-extern void ipt_unregister_target(struct ipt_target *target);
+#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch)
+#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch)
-extern int ipt_register_match(struct ipt_match *match);
-extern void ipt_unregister_match(struct ipt_match *match);
+//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
+//#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl)
-/* Furniture shopping... */
-struct ipt_table
-{
- struct list_head list;
-
- /* A unique name... */
- char name[IPT_TABLE_MAXNAMELEN];
-
- /* What hooks you will enter on */
- unsigned int valid_hooks;
-
- /* Lock for the curtain */
- rwlock_t lock;
-
- /* Man behind the curtain... */
- struct ipt_table_info *private;
-
- /* Set to THIS_MODULE. */
- struct module *me;
-};
+extern int ipt_register_table(struct ipt_table *table,
+ const struct ipt_replace *repl);
+extern void ipt_unregister_table(struct ipt_table *table);
/* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */
extern struct ipt_target *ipt_find_target(const char *name, u8 revision);
@@ -476,9 +356,6 @@ struct ipt_error
struct ipt_error_target target;
};
-extern int ipt_register_table(struct ipt_table *table,
- const struct ipt_replace *repl);
-extern void ipt_unregister_table(struct ipt_table *table);
extern unsigned int ipt_do_table(struct sk_buff **pskb,
unsigned int hook,
const struct net_device *in,
@@ -486,6 +363,6 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb,
struct ipt_table *table,
void *userdata);
-#define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1))
+#define IPT_ALIGN(s) XT_ALIGN(s)
#endif /*__KERNEL__*/
#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
index 7596e3dd00ca..a46d511b5c36 100644
--- a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
+++ b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
@@ -1,8 +1,7 @@
#ifndef _IPT_CLASSIFY_H
#define _IPT_CLASSIFY_H
-struct ipt_classify_target_info {
- u_int32_t priority;
-};
+#include <linux/netfilter/xt_CLASSIFY.h>
+#define ipt_classify_target_info xt_classify_target_info
#endif /*_IPT_CLASSIFY_H */
diff --git a/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/include/linux/netfilter_ipv4/ipt_CONNMARK.h
index d3c02536fc4c..9ecfee0a9e33 100644
--- a/include/linux/netfilter_ipv4/ipt_CONNMARK.h
+++ b/include/linux/netfilter_ipv4/ipt_CONNMARK.h
@@ -9,17 +9,11 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
+#include <linux/netfilter/xt_CONNMARK.h>
+#define IPT_CONNMARK_SET XT_CONNMARK_SET
+#define IPT_CONNMARK_SAVE XT_CONNMARK_SAVE
+#define IPT_CONNMARK_RESTORE XT_CONNMARK_RESTORE
-enum {
- IPT_CONNMARK_SET = 0,
- IPT_CONNMARK_SAVE,
- IPT_CONNMARK_RESTORE
-};
-
-struct ipt_connmark_target_info {
- unsigned long mark;
- unsigned long mask;
- u_int8_t mode;
-};
+#define ipt_connmark_target_info xt_connmark_target_info
#endif /*_IPT_CONNMARK_H_target*/
diff --git a/include/linux/netfilter_ipv4/ipt_MARK.h b/include/linux/netfilter_ipv4/ipt_MARK.h
index f47485790ed4..697a486a96d3 100644
--- a/include/linux/netfilter_ipv4/ipt_MARK.h
+++ b/include/linux/netfilter_ipv4/ipt_MARK.h
@@ -1,20 +1,18 @@
#ifndef _IPT_MARK_H_target
#define _IPT_MARK_H_target
+/* Backwards compatibility for old userspace */
+
+#include <linux/netfilter/xt_MARK.h>
+
/* Version 0 */
-struct ipt_mark_target_info {
- unsigned long mark;
-};
+#define ipt_mark_target_info xt_mark_target_info
/* Version 1 */
-enum {
- IPT_MARK_SET=0,
- IPT_MARK_AND,
- IPT_MARK_OR
-};
+#define IPT_MARK_SET XT_MARK_SET
+#define IPT_MARK_AND XT_MARK_AND
+#define IPT_MARK_OR XT_MARK_OR
+
+#define ipt_mark_target_info_v1 xt_mark_target_info_v1
-struct ipt_mark_target_info_v1 {
- unsigned long mark;
- u_int8_t mode;
-};
#endif /*_IPT_MARK_H_target*/
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
index b5b2943b0c66..97a2a7557cb9 100644
--- a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
+++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h
@@ -8,9 +8,9 @@
#ifndef _IPT_NFQ_TARGET_H
#define _IPT_NFQ_TARGET_H
-/* target info */
-struct ipt_NFQ_info {
- u_int16_t queuenum;
-};
+/* Backwards compatibility for old userspace */
+#include <linux/netfilter/xt_NFQUEUE.h>
+
+#define ipt_NFQ_info xt_NFQ_info
#endif /* _IPT_DSCP_TARGET_H */
diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h
index 85c1123c29ce..ae2afc2f7481 100644
--- a/include/linux/netfilter_ipv4/ipt_comment.h
+++ b/include/linux/netfilter_ipv4/ipt_comment.h
@@ -1,10 +1,10 @@
#ifndef _IPT_COMMENT_H
#define _IPT_COMMENT_H
-#define IPT_MAX_COMMENT_LEN 256
+#include <linux/netfilter/xt_comment.h>
-struct ipt_comment_info {
- unsigned char comment[IPT_MAX_COMMENT_LEN];
-};
+#define IPT_MAX_COMMENT_LEN XT_MAX_COMMENT_LEN
+
+#define ipt_comment_info xt_comment_info
#endif /* _IPT_COMMENT_H */
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h
index 9e5532f8d8ac..b04dfa3083c9 100644
--- a/include/linux/netfilter_ipv4/ipt_connbytes.h
+++ b/include/linux/netfilter_ipv4/ipt_connbytes.h
@@ -1,25 +1,18 @@
#ifndef _IPT_CONNBYTES_H
#define _IPT_CONNBYTES_H
-enum ipt_connbytes_what {
- IPT_CONNBYTES_PKTS,
- IPT_CONNBYTES_BYTES,
- IPT_CONNBYTES_AVGPKT,
-};
+#include <net/netfilter/xt_connbytes.h>
+#define ipt_connbytes_what xt_connbytes_what
-enum ipt_connbytes_direction {
- IPT_CONNBYTES_DIR_ORIGINAL,
- IPT_CONNBYTES_DIR_REPLY,
- IPT_CONNBYTES_DIR_BOTH,
-};
+#define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS
+#define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES
+#define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT
+
+#define ipt_connbytes_direction xt_connbytes_direction
+#define IPT_CONNBYTES_DIR_ORIGINAL XT_CONNBYTES_DIR_ORIGINAL
+#define IPT_CONNBYTES_DIR_REPLY XT_CONNBYTES_DIR_REPLY
+#define IPT_CONNBYTES_DIR_BOTH XT_CONNBYTES_DIR_BOTH
+
+#define ipt_connbytes_info xt_connbytes_info
-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_connmark.h b/include/linux/netfilter_ipv4/ipt_connmark.h
index 46573270d9aa..c7ba6560d44c 100644
--- a/include/linux/netfilter_ipv4/ipt_connmark.h
+++ b/include/linux/netfilter_ipv4/ipt_connmark.h
@@ -1,18 +1,7 @@
#ifndef _IPT_CONNMARK_H
#define _IPT_CONNMARK_H
-/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.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.
- */
-
-struct ipt_connmark_info {
- unsigned long mark, mask;
- u_int8_t invert;
-};
+#include <linux/netfilter/xt_connmark.h>
+#define ipt_connmark_info xt_connmark_info
#endif /*_IPT_CONNMARK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_conntrack.h b/include/linux/netfilter_ipv4/ipt_conntrack.h
index 413c5658bd3a..cde6762949c5 100644
--- a/include/linux/netfilter_ipv4/ipt_conntrack.h
+++ b/include/linux/netfilter_ipv4/ipt_conntrack.h
@@ -5,56 +5,24 @@
#ifndef _IPT_CONNTRACK_H
#define _IPT_CONNTRACK_H
-#define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
-#define IPT_CONNTRACK_STATE_INVALID (1 << 0)
+#include <linux/netfilter/xt_conntrack.h>
-#define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
-#define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
-#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
+#define IPT_CONNTRACK_STATE_BIT(ctinfo) XT_CONNTRACK_STATE_BIT(ctinfo)
+#define IPT_CONNTRACK_STATE_INVALID XT_CONNTRACK_STATE_INVALID
-/* flags, invflags: */
-#define IPT_CONNTRACK_STATE 0x01
-#define IPT_CONNTRACK_PROTO 0x02
-#define IPT_CONNTRACK_ORIGSRC 0x04
-#define IPT_CONNTRACK_ORIGDST 0x08
-#define IPT_CONNTRACK_REPLSRC 0x10
-#define IPT_CONNTRACK_REPLDST 0x20
-#define IPT_CONNTRACK_STATUS 0x40
-#define IPT_CONNTRACK_EXPIRES 0x80
-
-/* This is exposed to userspace, so remains frozen in time. */
-struct ip_conntrack_old_tuple
-{
- struct {
- __u32 ip;
- union {
- __u16 all;
- } u;
- } src;
-
- struct {
- __u32 ip;
- union {
- __u16 all;
- } u;
-
- /* The protocol. */
- u16 protonum;
- } dst;
-};
+#define IPT_CONNTRACK_STATE_SNAT XT_CONNTRACK_STATE_SNAT
+#define IPT_CONNTRACK_STATE_DNAT XT_CONNTRACK_STATE_DNAT
+#define IPT_CONNTRACK_STATE_UNTRACKED XT_CONNTRACK_STATE_UNTRACKED
-struct ipt_conntrack_info
-{
- unsigned int statemask, statusmask;
-
- struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
- struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
-
- unsigned long expires_min, expires_max;
-
- /* Flags word */
- u_int8_t flags;
- /* Inverse flags */
- u_int8_t invflags;
-};
+/* flags, invflags: */
+#define IPT_CONNTRACK_STATE XT_CONNTRACK_STATE
+#define IPT_CONNTRACK_PROTO XT_CONNTRACK_PROTO
+#define IPT_CONNTRACK_ORIGSRC XT_CONNTRACK_ORIGSRC
+#define IPT_CONNTRACK_ORIGDST XT_CONNTRACK_ORIGDST
+#define IPT_CONNTRACK_REPLSRC XT_CONNTRACK_REPLSRC
+#define IPT_CONNTRACK_REPLDST XT_CONNTRACK_REPLDST
+#define IPT_CONNTRACK_STATUS XT_CONNTRACK_STATUS
+#define IPT_CONNTRACK_EXPIRES XT_CONNTRACK_EXPIRES
+
+#define ipt_conntrack_info xt_conntrack_info
#endif /*_IPT_CONNTRACK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h
index 3cb3a522e62b..e70d11e1f53c 100644
--- a/include/linux/netfilter_ipv4/ipt_dccp.h
+++ b/include/linux/netfilter_ipv4/ipt_dccp.h
@@ -1,23 +1,15 @@
#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
+#include <linux/netfilter/xt_dccp.h>
+#define IPT_DCCP_SRC_PORTS XT_DCCP_SRC_PORTS
+#define IPT_DCCP_DEST_PORTS XT_DCCP_DEST_PORTS
+#define IPT_DCCP_TYPE XT_DCCP_TYPE
+#define IPT_DCCP_OPTION XT_DCCP_OPTION
-#define IPT_DCCP_VALID_FLAGS 0x0f
+#define IPT_DCCP_VALID_FLAGS XT_DCCP_VALID_FLAGS
-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;
-};
+#define ipt_dccp_info xt_dccp_info
#endif /* _IPT_DCCP_H_ */
diff --git a/include/linux/netfilter_ipv4/ipt_helper.h b/include/linux/netfilter_ipv4/ipt_helper.h
index 6f12ecb8c93d..80452c218551 100644
--- a/include/linux/netfilter_ipv4/ipt_helper.h
+++ b/include/linux/netfilter_ipv4/ipt_helper.h
@@ -1,8 +1,7 @@
#ifndef _IPT_HELPER_H
#define _IPT_HELPER_H
-struct ipt_helper_info {
- int invert;
- char name[30];
-};
+#include <linux/netfilter/xt_helper.h>
+#define ipt_helper_info xt_helper_info
+
#endif /* _IPT_HELPER_H */
diff --git a/include/linux/netfilter_ipv4/ipt_length.h b/include/linux/netfilter_ipv4/ipt_length.h
index 6e0885229615..9b45206ffcef 100644
--- a/include/linux/netfilter_ipv4/ipt_length.h
+++ b/include/linux/netfilter_ipv4/ipt_length.h
@@ -1,9 +1,7 @@
#ifndef _IPT_LENGTH_H
#define _IPT_LENGTH_H
-struct ipt_length_info {
- u_int16_t min, max;
- u_int8_t invert;
-};
+#include <linux/netfilter/xt_length.h>
+#define ipt_length_info xt_length_info
#endif /*_IPT_LENGTH_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_limit.h b/include/linux/netfilter_ipv4/ipt_limit.h
index 256453409e21..92f5cd07bbc4 100644
--- a/include/linux/netfilter_ipv4/ipt_limit.h
+++ b/include/linux/netfilter_ipv4/ipt_limit.h
@@ -1,21 +1,8 @@
#ifndef _IPT_RATE_H
#define _IPT_RATE_H
-/* timings are in milliseconds. */
-#define IPT_LIMIT_SCALE 10000
+#include <linux/netfilter/xt_limit.h>
+#define IPT_LIMIT_SCALE XT_LIMIT_SCALE
+#define ipt_rateinfo xt_rateinfo
-/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
- seconds, or one every 59 hours. */
-struct ipt_rateinfo {
- u_int32_t avg; /* Average secs between packets * scale */
- u_int32_t burst; /* Period multiplier for upper limit. */
-
- /* Used internally by the kernel */
- unsigned long prev;
- u_int32_t credit;
- u_int32_t credit_cap, cost;
-
- /* Ugly, ugly fucker. */
- struct ipt_rateinfo *master;
-};
#endif /*_IPT_RATE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_mac.h b/include/linux/netfilter_ipv4/ipt_mac.h
index f8d5b8e7ccdb..b186008a3c47 100644
--- a/include/linux/netfilter_ipv4/ipt_mac.h
+++ b/include/linux/netfilter_ipv4/ipt_mac.h
@@ -1,8 +1,7 @@
#ifndef _IPT_MAC_H
#define _IPT_MAC_H
-struct ipt_mac_info {
- unsigned char srcaddr[ETH_ALEN];
- int invert;
-};
+#include <linux/netfilter/xt_mac.h>
+#define ipt_mac_info xt_mac_info
+
#endif /*_IPT_MAC_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_mark.h b/include/linux/netfilter_ipv4/ipt_mark.h
index f3952b563d4c..bfde67c61224 100644
--- a/include/linux/netfilter_ipv4/ipt_mark.h
+++ b/include/linux/netfilter_ipv4/ipt_mark.h
@@ -1,9 +1,9 @@
#ifndef _IPT_MARK_H
#define _IPT_MARK_H
-struct ipt_mark_info {
- unsigned long mark, mask;
- u_int8_t invert;
-};
+/* Backwards compatibility for old userspace */
+#include <linux/netfilter/xt_mark.h>
+
+#define ipt_mark_info xt_mark_info
#endif /*_IPT_MARK_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h
index 7538c8655ec0..2400e7140f26 100644
--- a/include/linux/netfilter_ipv4/ipt_physdev.h
+++ b/include/linux/netfilter_ipv4/ipt_physdev.h
@@ -1,24 +1,17 @@
#ifndef _IPT_PHYSDEV_H
#define _IPT_PHYSDEV_H
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
+/* Backwards compatibility for old userspace */
-#define IPT_PHYSDEV_OP_IN 0x01
-#define IPT_PHYSDEV_OP_OUT 0x02
-#define IPT_PHYSDEV_OP_BRIDGED 0x04
-#define IPT_PHYSDEV_OP_ISIN 0x08
-#define IPT_PHYSDEV_OP_ISOUT 0x10
-#define IPT_PHYSDEV_OP_MASK (0x20 - 1)
+#include <linux/netfilter/xt_physdev.h>
-struct ipt_physdev_info {
- char physindev[IFNAMSIZ];
- char in_mask[IFNAMSIZ];
- char physoutdev[IFNAMSIZ];
- char out_mask[IFNAMSIZ];
- u_int8_t invert;
- u_int8_t bitmask;
-};
+#define IPT_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN
+#define IPT_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT
+#define IPT_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED
+#define IPT_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN
+#define IPT_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT
+#define IPT_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK
+
+#define ipt_physdev_info xt_physdev_info
#endif /*_IPT_PHYSDEV_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_pkttype.h b/include/linux/netfilter_ipv4/ipt_pkttype.h
index d53a65848683..ff1fbc949a0c 100644
--- a/include/linux/netfilter_ipv4/ipt_pkttype.h
+++ b/include/linux/netfilter_ipv4/ipt_pkttype.h
@@ -1,8 +1,7 @@
#ifndef _IPT_PKTTYPE_H
#define _IPT_PKTTYPE_H
-struct ipt_pkttype_info {
- int pkttype;
- int invert;
-};
+#include <linux/netfilter/xt_pkttype.h>
+#define ipt_pkttype_info xt_pkttype_info
+
#endif /*_IPT_PKTTYPE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_policy.h b/include/linux/netfilter_ipv4/ipt_policy.h
new file mode 100644
index 000000000000..7fd1bec453f1
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_policy.h
@@ -0,0 +1,52 @@
+#ifndef _IPT_POLICY_H
+#define _IPT_POLICY_H
+
+#define IPT_POLICY_MAX_ELEM 4
+
+enum ipt_policy_flags
+{
+ IPT_POLICY_MATCH_IN = 0x1,
+ IPT_POLICY_MATCH_OUT = 0x2,
+ IPT_POLICY_MATCH_NONE = 0x4,
+ IPT_POLICY_MATCH_STRICT = 0x8,
+};
+
+enum ipt_policy_modes
+{
+ IPT_POLICY_MODE_TRANSPORT,
+ IPT_POLICY_MODE_TUNNEL
+};
+
+struct ipt_policy_spec
+{
+ u_int8_t saddr:1,
+ daddr:1,
+ proto:1,
+ mode:1,
+ spi:1,
+ reqid:1;
+};
+
+struct ipt_policy_elem
+{
+ u_int32_t saddr;
+ u_int32_t smask;
+ u_int32_t daddr;
+ u_int32_t dmask;
+ u_int32_t spi;
+ u_int32_t reqid;
+ u_int8_t proto;
+ u_int8_t mode;
+
+ struct ipt_policy_spec match;
+ struct ipt_policy_spec invert;
+};
+
+struct ipt_policy_info
+{
+ struct ipt_policy_elem pol[IPT_POLICY_MAX_ELEM];
+ u_int16_t flags;
+ u_int16_t len;
+};
+
+#endif /* _IPT_POLICY_H */
diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h
index a4d6698723ac..b3996eaa0188 100644
--- a/include/linux/netfilter_ipv4/ipt_realm.h
+++ b/include/linux/netfilter_ipv4/ipt_realm.h
@@ -1,10 +1,7 @@
#ifndef _IPT_REALM_H
#define _IPT_REALM_H
-struct ipt_realm_info {
- u_int32_t id;
- u_int32_t mask;
- u_int8_t invert;
-};
+#include <linux/netfilter/xt_realm.h>
+#define ipt_realm_info xt_realm_info
#endif /* _IPT_REALM_H */
diff --git a/include/linux/netfilter_ipv4/ipt_state.h b/include/linux/netfilter_ipv4/ipt_state.h
index 5df37868933d..a44a99cc28cc 100644
--- a/include/linux/netfilter_ipv4/ipt_state.h
+++ b/include/linux/netfilter_ipv4/ipt_state.h
@@ -1,13 +1,15 @@
#ifndef _IPT_STATE_H
#define _IPT_STATE_H
-#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
-#define IPT_STATE_INVALID (1 << 0)
+/* Backwards compatibility for old userspace */
-#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
+#include <linux/netfilter/xt_state.h>
+
+#define IPT_STATE_BIT XT_STATE_BIT
+#define IPT_STATE_INVALID XT_STATE_INVALID
+
+#define IPT_STATE_UNTRACKED XT_STATE_UNTRACKED
+
+#define ipt_state_info xt_state_info
-struct ipt_state_info
-{
- unsigned int statemask;
-};
#endif /*_IPT_STATE_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h
index a265f6e44eab..c26de3059903 100644
--- a/include/linux/netfilter_ipv4/ipt_string.h
+++ b/include/linux/netfilter_ipv4/ipt_string.h
@@ -1,18 +1,10 @@
#ifndef _IPT_STRING_H
#define _IPT_STRING_H
-#define IPT_STRING_MAX_PATTERN_SIZE 128
-#define IPT_STRING_MAX_ALGO_NAME_SIZE 16
+#include <linux/netfilter/xt_string.h>
-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;
-};
+#define IPT_STRING_MAX_PATTERN_SIZE XT_STRING_MAX_PATTERN_SIZE
+#define IPT_STRING_MAX_ALGO_NAME_SIZE XT_STRING_MAX_ALGO_NAME_SIZE
+#define ipt_string_info xt_string_info
#endif /*_IPT_STRING_H*/
diff --git a/include/linux/netfilter_ipv4/ipt_tcpmss.h b/include/linux/netfilter_ipv4/ipt_tcpmss.h
index e2b14397f701..18bbc8e8e009 100644
--- a/include/linux/netfilter_ipv4/ipt_tcpmss.h
+++ b/include/linux/netfilter_ipv4/ipt_tcpmss.h
@@ -1,9 +1,7 @@
#ifndef _IPT_TCPMSS_MATCH_H
#define _IPT_TCPMSS_MATCH_H
-struct ipt_tcpmss_match_info {
- u_int16_t mss_min, mss_max;
- u_int8_t invert;
-};
+#include <linux/netfilter/xt_tcpmss.h>
+#define ipt_tcpmss_match_info xt_tcpmss_match_info
#endif /*_IPT_TCPMSS_MATCH_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index 53b2983f6278..14f2bd010884 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -72,7 +72,12 @@ enum nf_ip6_hook_priorities {
NF_IP6_PRI_LAST = INT_MAX,
};
+#ifdef CONFIG_NETFILTER
extern int ipv6_netfilter_init(void);
extern void ipv6_netfilter_fini(void);
+#else /* CONFIG_NETFILTER */
+static inline int ipv6_netfilter_init(void) { return 0; }
+static inline void ipv6_netfilter_fini(void) { return; }
+#endif /* CONFIG_NETFILTER */
#endif /*__LINUX_IP6_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 2efc046d9e94..f249b574f0fa 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -25,8 +25,15 @@
#include <linux/compiler.h>
#include <linux/netfilter_ipv6.h>
-#define IP6T_FUNCTION_MAXNAMELEN 30
-#define IP6T_TABLE_MAXNAMELEN 32
+#include <linux/netfilter/x_tables.h>
+
+#define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
+
+#define ip6t_match xt_match
+#define ip6t_target xt_target
+#define ip6t_table xt_table
+#define ip6t_get_revision xt_get_revision
/* Yes, Virginia, you have to zero the padding. */
struct ip6t_ip6 {
@@ -104,10 +111,7 @@ struct ip6t_standard_target
int verdict;
};
-struct ip6t_counters
-{
- u_int64_t pcnt, bcnt; /* Packet and byte counters */
-};
+#define ip6t_counters xt_counters
/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
#define IP6T_F_PROTO 0x01 /* Set if rule cares about upper
@@ -123,7 +127,7 @@ struct ip6t_counters
#define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */
#define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */
#define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */
-#define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */
+#define IP6T_INV_PROTO XT_INV_PROTO
#define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */
/* This structure defines each of the firewall rules. Consists of 3
@@ -145,7 +149,7 @@ struct ip6t_entry
unsigned int comefrom;
/* Packet and byte counters. */
- struct ip6t_counters counters;
+ struct xt_counters counters;
/* The matches (if any), then the target. */
unsigned char elems[0];
@@ -155,54 +159,41 @@ struct ip6t_entry
* New IP firewall options for [gs]etsockopt at the RAW IP level.
* Unlike BSD Linux inherits IP options so you don't have to use
* a raw socket for this. Instead we check rights in the calls. */
-#define IP6T_BASE_CTL 64 /* base for firewall socket options */
+#define IP6T_BASE_CTL XT_BASE_CTL
-#define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL)
-#define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1)
-#define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS
+#define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE
+#define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS
+#define IP6T_SO_SET_MAX XT_SO_SET_MAX
-#define IP6T_SO_GET_INFO (IP6T_BASE_CTL)
-#define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1)
-#define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2)
-#define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3)
-#define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET
+#define IP6T_SO_GET_INFO XT_SO_GET_INFO
+#define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES
+#define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH
+#define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET
+#define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET
/* CONTINUE verdict for targets */
-#define IP6T_CONTINUE 0xFFFFFFFF
+#define IP6T_CONTINUE XT_CONTINUE
/* For standard target */
-#define IP6T_RETURN (-NF_REPEAT - 1)
+#define IP6T_RETURN XT_RETURN
-/* TCP matching stuff */
-struct ip6t_tcp
-{
- u_int16_t spts[2]; /* Source port range. */
- u_int16_t dpts[2]; /* Destination port range. */
- u_int8_t option; /* TCP Option iff non-zero*/
- u_int8_t flg_mask; /* TCP flags mask byte */
- u_int8_t flg_cmp; /* TCP flags compare byte */
- u_int8_t invflags; /* Inverse flags */
-};
+/* TCP/UDP matching stuff */
+#include <linux/netfilter/xt_tcpudp.h>
+
+#define ip6t_tcp xt_tcp
+#define ip6t_udp xt_udp
/* Values for "inv" field in struct ipt_tcp. */
-#define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
-#define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
-#define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */
-#define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */
-#define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */
-
-/* UDP matching stuff */
-struct ip6t_udp
-{
- u_int16_t spts[2]; /* Source port range. */
- u_int16_t dpts[2]; /* Destination port range. */
- u_int8_t invflags; /* Inverse flags */
-};
+#define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT
+#define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT
+#define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS
+#define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION
+#define IP6T_TCP_INV_MASK XT_TCP_INV_MASK
/* Values for "invflags" field in struct ipt_udp. */
-#define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */
-#define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */
-#define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */
+#define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT
+#define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT
+#define IP6T_UDP_INV_MASK XT_UDP_INV_MASK
/* ICMP matching stuff */
struct ip6t_icmp
@@ -264,23 +255,14 @@ struct ip6t_replace
/* Number of counters (must be equal to current number of entries). */
unsigned int num_counters;
/* The old entries' counters. */
- struct ip6t_counters __user *counters;
+ struct xt_counters __user *counters;
/* The entries (hang off end: not really an array). */
struct ip6t_entry entries[0];
};
/* The argument to IP6T_SO_ADD_COUNTERS. */
-struct ip6t_counters_info
-{
- /* Which table. */
- char name[IP6T_TABLE_MAXNAMELEN];
-
- unsigned int num_counters;
-
- /* The counters (actually `number' of these). */
- struct ip6t_counters counters[0];
-};
+#define ip6t_counters_info xt_counters_info
/* The argument to IP6T_SO_GET_ENTRIES. */
struct ip6t_get_entries
@@ -295,19 +277,10 @@ struct ip6t_get_entries
struct ip6t_entry entrytable[0];
};
-/* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision
- * kernel supports, if >= revision. */
-struct ip6t_get_revision
-{
- char name[IP6T_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-};
-
/* Standard return verdict, or do jump. */
-#define IP6T_STANDARD_TARGET ""
+#define IP6T_STANDARD_TARGET XT_STANDARD_TARGET
/* Error verdict. */
-#define IP6T_ERROR_TARGET "ERROR"
+#define IP6T_ERROR_TARGET XT_ERROR_TARGET
/* Helper functions */
static __inline__ struct ip6t_entry_target *
@@ -361,104 +334,11 @@ ip6t_get_target(struct ip6t_entry *e)
#include <linux/init.h>
extern void ip6t_init(void) __init;
-struct ip6t_match
-{
- struct list_head list;
-
- const char name[IP6T_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-
- /* Return true or false: return FALSE and set *hotdrop = 1 to
- force immediate packet drop. */
- /* Arguments changed since 2.6.9, as this must now handle
- non-linear skb, using skb_header_pointer and
- skb_ip_make_writable. */
- int (*match)(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop);
-
- /* Called when user tries to insert an entry of this type. */
- /* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask);
-
- /* Called when entry of this type deleted. */
- void (*destroy)(void *matchinfo, unsigned int matchinfosize);
-
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
-};
-
-/* Registration hooks for targets. */
-struct ip6t_target
-{
- struct list_head list;
-
- const char name[IP6T_FUNCTION_MAXNAMELEN-1];
-
- u_int8_t revision;
-
- /* Returns verdict. Argument order changed since 2.6.9, as this
- must now handle non-linear skbs, using skb_copy_bits and
- skb_ip_make_writable. */
- unsigned int (*target)(struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- unsigned int hooknum,
- const void *targinfo,
- void *userdata);
-
- /* Called when user tries to insert an entry of this type:
- hook_mask is a bitmask of hooks from which it can be
- called. */
- /* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const struct ip6t_entry *e,
- void *targinfo,
- unsigned int targinfosize,
- unsigned int hook_mask);
-
- /* Called when entry of this type deleted. */
- void (*destroy)(void *targinfo, unsigned int targinfosize);
-
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
-};
-
-extern int ip6t_register_target(struct ip6t_target *target);
-extern void ip6t_unregister_target(struct ip6t_target *target);
+#define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt)
+#define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt)
-extern int ip6t_register_match(struct ip6t_match *match);
-extern void ip6t_unregister_match(struct ip6t_match *match);
-
-/* Furniture shopping... */
-struct ip6t_table
-{
- struct list_head list;
-
- /* A unique name... */
- char name[IP6T_TABLE_MAXNAMELEN];
-
- /* What hooks you will enter on */
- unsigned int valid_hooks;
-
- /* Lock for the curtain */
- rwlock_t lock;
-
- /* Man behind the curtain... */
- struct ip6t_table_info *private;
-
- /* Set this to THIS_MODULE if you are a module, otherwise NULL */
- struct module *me;
-};
+#define ip6t_register_match(match) xt_register_match(AF_INET6, match)
+#define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match)
extern int ip6t_register_table(struct ip6t_table *table,
const struct ip6t_replace *repl);
@@ -474,7 +354,11 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb,
extern int ip6t_ext_hdr(u8 nexthdr);
/* find specified header and get offset to it */
extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
- u8 target);
+ int target, unsigned short *fragoff);
+
+extern int ip6_masked_addrcmp(const struct in6_addr *addr1,
+ const struct in6_addr *mask,
+ const struct in6_addr *addr2);
#define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
diff --git a/include/linux/netfilter_ipv6/ip6t_MARK.h b/include/linux/netfilter_ipv6/ip6t_MARK.h
index 7ade8d8f5246..7cf629a8ab92 100644
--- a/include/linux/netfilter_ipv6/ip6t_MARK.h
+++ b/include/linux/netfilter_ipv6/ip6t_MARK.h
@@ -1,8 +1,9 @@
#ifndef _IP6T_MARK_H_target
#define _IP6T_MARK_H_target
-struct ip6t_mark_target_info {
- unsigned long mark;
-};
+/* Backwards compatibility for old userspace */
+#include <linux/netfilter/xt_MARK.h>
-#endif /*_IPT_MARK_H_target*/
+#define ip6t_mark_target_info xt_mark_target_info
+
+#endif /*_IP6T_MARK_H_target*/
diff --git a/include/linux/netfilter_ipv6/ip6t_ah.h b/include/linux/netfilter_ipv6/ip6t_ah.h
index c4f0793a0a98..8531879eb464 100644
--- a/include/linux/netfilter_ipv6/ip6t_ah.h
+++ b/include/linux/netfilter_ipv6/ip6t_ah.h
@@ -18,13 +18,4 @@ struct ip6t_ah
#define IP6T_AH_INV_LEN 0x02 /* Invert the sense of length. */
#define IP6T_AH_INV_MASK 0x03 /* All possible flags. */
-#define MASK_HOPOPTS 128
-#define MASK_DSTOPTS 64
-#define MASK_ROUTING 32
-#define MASK_FRAGMENT 16
-#define MASK_AH 8
-#define MASK_ESP 4
-#define MASK_NONE 2
-#define MASK_PROTO 1
-
#endif /*_IP6T_AH_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_esp.h b/include/linux/netfilter_ipv6/ip6t_esp.h
index 01142b98a231..a91b6abc8079 100644
--- a/include/linux/netfilter_ipv6/ip6t_esp.h
+++ b/include/linux/netfilter_ipv6/ip6t_esp.h
@@ -7,15 +7,6 @@ struct ip6t_esp
u_int8_t invflags; /* Inverse flags */
};
-#define MASK_HOPOPTS 128
-#define MASK_DSTOPTS 64
-#define MASK_ROUTING 32
-#define MASK_FRAGMENT 16
-#define MASK_AH 8
-#define MASK_ESP 4
-#define MASK_NONE 2
-#define MASK_PROTO 1
-
/* Values for "invflags" field in struct ip6t_esp. */
#define IP6T_ESP_INV_SPI 0x01 /* Invert the sense of spi. */
#define IP6T_ESP_INV_MASK 0x01 /* All possible flags. */
diff --git a/include/linux/netfilter_ipv6/ip6t_frag.h b/include/linux/netfilter_ipv6/ip6t_frag.h
index 449a57eca7dd..66070a0d6dfc 100644
--- a/include/linux/netfilter_ipv6/ip6t_frag.h
+++ b/include/linux/netfilter_ipv6/ip6t_frag.h
@@ -21,13 +21,4 @@ struct ip6t_frag
#define IP6T_FRAG_INV_LEN 0x02 /* Invert the sense of length. */
#define IP6T_FRAG_INV_MASK 0x03 /* All possible flags. */
-#define MASK_HOPOPTS 128
-#define MASK_DSTOPTS 64
-#define MASK_ROUTING 32
-#define MASK_FRAGMENT 16
-#define MASK_AH 8
-#define MASK_ESP 4
-#define MASK_NONE 2
-#define MASK_PROTO 1
-
#endif /*_IP6T_FRAG_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_length.h b/include/linux/netfilter_ipv6/ip6t_length.h
index 7fc09f9f9d63..9e9689d03ed7 100644
--- a/include/linux/netfilter_ipv6/ip6t_length.h
+++ b/include/linux/netfilter_ipv6/ip6t_length.h
@@ -1,10 +1,8 @@
#ifndef _IP6T_LENGTH_H
#define _IP6T_LENGTH_H
-struct ip6t_length_info {
- u_int16_t min, max;
- u_int8_t invert;
-};
+#include <linux/netfilter/xt_length.h>
+#define ip6t_length_info xt_length_info
#endif /*_IP6T_LENGTH_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_limit.h b/include/linux/netfilter_ipv6/ip6t_limit.h
index f2866e50f3b4..487e5ea342c6 100644
--- a/include/linux/netfilter_ipv6/ip6t_limit.h
+++ b/include/linux/netfilter_ipv6/ip6t_limit.h
@@ -1,21 +1,8 @@
#ifndef _IP6T_RATE_H
#define _IP6T_RATE_H
-/* timings are in milliseconds. */
-#define IP6T_LIMIT_SCALE 10000
+#include <linux/netfilter/xt_limit.h>
+#define IP6T_LIMIT_SCALE XT_LIMIT_SCALE
+#define ip6t_rateinfo xt_rateinfo
-/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
- seconds, or one every 59 hours. */
-struct ip6t_rateinfo {
- u_int32_t avg; /* Average secs between packets * scale */
- u_int32_t burst; /* Period multiplier for upper limit. */
-
- /* Used internally by the kernel */
- unsigned long prev;
- u_int32_t credit;
- u_int32_t credit_cap, cost;
-
- /* Ugly, ugly fucker. */
- struct ip6t_rateinfo *master;
-};
-#endif /*_IPT_RATE_H*/
+#endif /*_IP6T_RATE_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_mac.h b/include/linux/netfilter_ipv6/ip6t_mac.h
index 87c088c21848..ac58e83e9423 100644
--- a/include/linux/netfilter_ipv6/ip6t_mac.h
+++ b/include/linux/netfilter_ipv6/ip6t_mac.h
@@ -1,8 +1,7 @@
#ifndef _IP6T_MAC_H
#define _IP6T_MAC_H
-struct ip6t_mac_info {
- unsigned char srcaddr[ETH_ALEN];
- int invert;
-};
-#endif /*_IPT_MAC_H*/
+#include <linux/netfilter/xt_mac.h>
+#define ip6t_mac_info xt_mac_info
+
+#endif /*_IP6T_MAC_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_mark.h b/include/linux/netfilter_ipv6/ip6t_mark.h
index a734441e1c19..ff204951ddc3 100644
--- a/include/linux/netfilter_ipv6/ip6t_mark.h
+++ b/include/linux/netfilter_ipv6/ip6t_mark.h
@@ -1,9 +1,9 @@
#ifndef _IP6T_MARK_H
#define _IP6T_MARK_H
-struct ip6t_mark_info {
- unsigned long mark, mask;
- u_int8_t invert;
-};
+/* Backwards compatibility for old userspace */
+#include <linux/netfilter/xt_mark.h>
+
+#define ip6t_mark_info xt_mark_info
#endif /*_IPT_MARK_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_opts.h b/include/linux/netfilter_ipv6/ip6t_opts.h
index e259b6275bd2..a07e36380ae8 100644
--- a/include/linux/netfilter_ipv6/ip6t_opts.h
+++ b/include/linux/netfilter_ipv6/ip6t_opts.h
@@ -20,13 +20,4 @@ struct ip6t_opts
#define IP6T_OPTS_INV_LEN 0x01 /* Invert the sense of length. */
#define IP6T_OPTS_INV_MASK 0x01 /* All possible flags. */
-#define MASK_HOPOPTS 128
-#define MASK_DSTOPTS 64
-#define MASK_ROUTING 32
-#define MASK_FRAGMENT 16
-#define MASK_AH 8
-#define MASK_ESP 4
-#define MASK_NONE 2
-#define MASK_PROTO 1
-
#endif /*_IP6T_OPTS_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h
index c234731cd66b..c161c0a81b55 100644
--- a/include/linux/netfilter_ipv6/ip6t_physdev.h
+++ b/include/linux/netfilter_ipv6/ip6t_physdev.h
@@ -1,24 +1,17 @@
#ifndef _IP6T_PHYSDEV_H
#define _IP6T_PHYSDEV_H
-#ifdef __KERNEL__
-#include <linux/if.h>
-#endif
+/* Backwards compatibility for old userspace */
-#define IP6T_PHYSDEV_OP_IN 0x01
-#define IP6T_PHYSDEV_OP_OUT 0x02
-#define IP6T_PHYSDEV_OP_BRIDGED 0x04
-#define IP6T_PHYSDEV_OP_ISIN 0x08
-#define IP6T_PHYSDEV_OP_ISOUT 0x10
-#define IP6T_PHYSDEV_OP_MASK (0x20 - 1)
+#include <linux/netfilter/xt_physdev.h>
-struct ip6t_physdev_info {
- char physindev[IFNAMSIZ];
- char in_mask[IFNAMSIZ];
- char physoutdev[IFNAMSIZ];
- char out_mask[IFNAMSIZ];
- u_int8_t invert;
- u_int8_t bitmask;
-};
+#define IP6T_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN
+#define IP6T_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT
+#define IP6T_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED
+#define IP6T_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN
+#define IP6T_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT
+#define IP6T_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK
+
+#define ip6t_physdev_info xt_physdev_info
#endif /*_IP6T_PHYSDEV_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_policy.h b/include/linux/netfilter_ipv6/ip6t_policy.h
new file mode 100644
index 000000000000..5a93afcd2ff1
--- /dev/null
+++ b/include/linux/netfilter_ipv6/ip6t_policy.h
@@ -0,0 +1,52 @@
+#ifndef _IP6T_POLICY_H
+#define _IP6T_POLICY_H
+
+#define IP6T_POLICY_MAX_ELEM 4
+
+enum ip6t_policy_flags
+{
+ IP6T_POLICY_MATCH_IN = 0x1,
+ IP6T_POLICY_MATCH_OUT = 0x2,
+ IP6T_POLICY_MATCH_NONE = 0x4,
+ IP6T_POLICY_MATCH_STRICT = 0x8,
+};
+
+enum ip6t_policy_modes
+{
+ IP6T_POLICY_MODE_TRANSPORT,
+ IP6T_POLICY_MODE_TUNNEL
+};
+
+struct ip6t_policy_spec
+{
+ u_int8_t saddr:1,
+ daddr:1,
+ proto:1,
+ mode:1,
+ spi:1,
+ reqid:1;
+};
+
+struct ip6t_policy_elem
+{
+ struct in6_addr saddr;
+ struct in6_addr smask;
+ struct in6_addr daddr;
+ struct in6_addr dmask;
+ u_int32_t spi;
+ u_int32_t reqid;
+ u_int8_t proto;
+ u_int8_t mode;
+
+ struct ip6t_policy_spec match;
+ struct ip6t_policy_spec invert;
+};
+
+struct ip6t_policy_info
+{
+ struct ip6t_policy_elem pol[IP6T_POLICY_MAX_ELEM];
+ u_int16_t flags;
+ u_int16_t len;
+};
+
+#endif /* _IP6T_POLICY_H */
diff --git a/include/linux/netfilter_ipv6/ip6t_rt.h b/include/linux/netfilter_ipv6/ip6t_rt.h
index f1070fbf2757..52156023e8db 100644
--- a/include/linux/netfilter_ipv6/ip6t_rt.h
+++ b/include/linux/netfilter_ipv6/ip6t_rt.h
@@ -30,13 +30,4 @@ struct ip6t_rt
#define IP6T_RT_INV_LEN 0x04 /* Invert the sense of length. */
#define IP6T_RT_INV_MASK 0x07 /* All possible flags. */
-#define MASK_HOPOPTS 128
-#define MASK_DSTOPTS 64
-#define MASK_ROUTING 32
-#define MASK_FRAGMENT 16
-#define MASK_AH 8
-#define MASK_ESP 4
-#define MASK_NONE 2
-#define MASK_PROTO 1
-
#endif /*_IP6T_RT_H*/
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 2516adeccecf..547d649b274e 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -38,9 +38,6 @@
# define NFS_DEBUG
#endif
-#define NFS_MAX_FILE_IO_BUFFER_SIZE 32768
-#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096
-
/* Default timeout values */
#define NFS_MAX_UDP_TIMEOUT (60*HZ)
#define NFS_MAX_TCP_TIMEOUT (600*HZ)
@@ -65,6 +62,7 @@
#define FLUSH_STABLE 4 /* commit to stable storage */
#define FLUSH_LOWPRI 8 /* low priority background flush */
#define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */
+#define FLUSH_NOCOMMIT 32 /* Don't send the NFSv3/v4 COMMIT */
#ifdef __KERNEL__
@@ -394,6 +392,17 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_
extern struct inode_operations nfs_symlink_inode_operations;
/*
+ * linux/fs/nfs/sysctl.c
+ */
+#ifdef CONFIG_SYSCTL
+extern int nfs_register_sysctl(void);
+extern void nfs_unregister_sysctl(void);
+#else
+#define nfs_register_sysctl() do { } while(0)
+#define nfs_unregister_sysctl() do { } while(0)
+#endif
+
+/*
* linux/fs/nfs/unlink.c
*/
extern int nfs_async_unlink(struct dentry *);
@@ -406,10 +415,12 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc);
extern int nfs_writepages(struct address_space *, struct writeback_control *);
extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
-extern void nfs_writeback_done(struct rpc_task *task);
+extern void nfs_writeback_done(struct rpc_task *task, void *data);
+extern void nfs_writedata_release(void *data);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-extern void nfs_commit_done(struct rpc_task *);
+extern void nfs_commit_done(struct rpc_task *, void *data);
+extern void nfs_commit_release(void *data);
#endif
/*
@@ -460,18 +471,33 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
*/
extern mempool_t *nfs_wdata_mempool;
-static inline struct nfs_write_data *nfs_writedata_alloc(void)
+static inline struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
{
struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
+
if (p) {
memset(p, 0, sizeof(*p));
INIT_LIST_HEAD(&p->pages);
+ if (pagecount < NFS_PAGEVEC_SIZE)
+ p->pagevec = &p->page_array[0];
+ else {
+ size_t size = ++pagecount * sizeof(struct page *);
+ p->pagevec = kmalloc(size, GFP_NOFS);
+ if (p->pagevec) {
+ memset(p->pagevec, 0, size);
+ } else {
+ mempool_free(p, nfs_wdata_mempool);
+ p = NULL;
+ }
+ }
}
return p;
}
static inline void nfs_writedata_free(struct nfs_write_data *p)
{
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
mempool_free(p, nfs_wdata_mempool);
}
@@ -481,28 +507,45 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
extern int nfs_readpage(struct file *, struct page *);
extern int nfs_readpages(struct file *, struct address_space *,
struct list_head *, unsigned);
-extern void nfs_readpage_result(struct rpc_task *);
+extern void nfs_readpage_result(struct rpc_task *, void *);
+extern void nfs_readdata_release(void *data);
+
/*
* Allocate and free nfs_read_data structures
*/
extern mempool_t *nfs_rdata_mempool;
-static inline struct nfs_read_data *nfs_readdata_alloc(void)
+static inline struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
{
struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
- if (p)
+
+ if (p) {
memset(p, 0, sizeof(*p));
+ INIT_LIST_HEAD(&p->pages);
+ if (pagecount < NFS_PAGEVEC_SIZE)
+ p->pagevec = &p->page_array[0];
+ else {
+ size_t size = ++pagecount * sizeof(struct page *);
+ p->pagevec = kmalloc(size, GFP_NOFS);
+ if (p->pagevec) {
+ memset(p->pagevec, 0, size);
+ } else {
+ mempool_free(p, nfs_rdata_mempool);
+ p = NULL;
+ }
+ }
+ }
return p;
}
static inline void nfs_readdata_free(struct nfs_read_data *p)
{
+ if (p && (p->pagevec != &p->page_array[0]))
+ kfree(p->pagevec);
mempool_free(p, nfs_rdata_mempool);
}
-extern void nfs_readdata_release(struct rpc_task *task);
-
/*
* linux/fs/nfs3proc.c
*/
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index a0f1f25e0ead..102e56094296 100644
--- a/include/linux/nfs_idmap.h
+++ b/include/linux/nfs_idmap.h
@@ -71,6 +71,8 @@ int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *);
int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *);
int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *);
int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *);
+
+extern unsigned int nfs_idmap_cache_timeout;
#endif /* __KERNEL__ */
#endif /* NFS_IDMAP_H */
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index da2e077b65e2..66e2ed658527 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -79,9 +79,7 @@ extern void nfs_clear_page_writeback(struct nfs_page *req);
static inline int
nfs_lock_request_dontget(struct nfs_page *req)
{
- if (test_and_set_bit(PG_BUSY, &req->wb_flags))
- return 0;
- return 1;
+ return !test_and_set_bit(PG_BUSY, &req->wb_flags);
}
/*
@@ -125,9 +123,7 @@ nfs_list_remove_request(struct nfs_page *req)
static inline int
nfs_defer_commit(struct nfs_page *req)
{
- if (test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags))
- return 0;
- return 1;
+ return !test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags);
}
static inline void
@@ -141,9 +137,7 @@ nfs_clear_commit(struct nfs_page *req)
static inline int
nfs_defer_reschedule(struct nfs_page *req)
{
- if (test_and_set_bit(PG_NEED_RESCHED, &req->wb_flags))
- return 0;
- return 1;
+ return !test_and_set_bit(PG_NEED_RESCHED, &req->wb_flags);
}
static inline void
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 40718669b9c8..6d6f69ec5675 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -4,6 +4,16 @@
#include <linux/sunrpc/xprt.h>
#include <linux/nfsacl.h>
+/*
+ * To change the maximum rsize and wsize supported by the NFS client, adjust
+ * NFS_MAX_FILE_IO_SIZE. 64KB is a typical maximum, but some servers can
+ * support a megabyte or more. The default is left at 4096 bytes, which is
+ * reasonable for NFS over UDP.
+ */
+#define NFS_MAX_FILE_IO_SIZE (1048576U)
+#define NFS_DEF_FILE_IO_SIZE (4096U)
+#define NFS_MIN_FILE_IO_SIZE (1024U)
+
struct nfs4_fsid {
__u64 major;
__u64 minor;
@@ -137,7 +147,7 @@ struct nfs_openres {
*/
struct nfs_open_confirmargs {
const struct nfs_fh * fh;
- nfs4_stateid stateid;
+ nfs4_stateid * stateid;
struct nfs_seqid * seqid;
};
@@ -165,66 +175,62 @@ struct nfs_closeres {
* * Arguments to the lock,lockt, and locku call.
* */
struct nfs_lowner {
- __u64 clientid;
- u32 id;
+ __u64 clientid;
+ u32 id;
};
-struct nfs_lock_opargs {
+struct nfs_lock_args {
+ struct nfs_fh * fh;
+ struct file_lock * fl;
struct nfs_seqid * lock_seqid;
nfs4_stateid * lock_stateid;
struct nfs_seqid * open_seqid;
nfs4_stateid * open_stateid;
- struct nfs_lowner lock_owner;
- __u32 reclaim;
- __u32 new_lock_owner;
+ struct nfs_lowner lock_owner;
+ unsigned char block : 1;
+ unsigned char reclaim : 1;
+ unsigned char new_lock_owner : 1;
};
-struct nfs_locku_opargs {
+struct nfs_lock_res {
+ nfs4_stateid stateid;
+};
+
+struct nfs_locku_args {
+ struct nfs_fh * fh;
+ struct file_lock * fl;
struct nfs_seqid * seqid;
nfs4_stateid * stateid;
};
-struct nfs_lockargs {
- struct nfs_fh * fh;
- __u32 type;
- __u64 offset;
- __u64 length;
- union {
- struct nfs_lock_opargs *lock; /* LOCK */
- struct nfs_lowner *lockt; /* LOCKT */
- struct nfs_locku_opargs *locku; /* LOCKU */
- } u;
+struct nfs_locku_res {
+ nfs4_stateid stateid;
};
-struct nfs_lock_denied {
- __u64 offset;
- __u64 length;
- __u32 type;
- struct nfs_lowner owner;
+struct nfs_lockt_args {
+ struct nfs_fh * fh;
+ struct file_lock * fl;
+ struct nfs_lowner lock_owner;
};
-struct nfs_lockres {
- union {
- nfs4_stateid stateid;/* LOCK success, LOCKU */
- struct nfs_lock_denied denied; /* LOCK failed, LOCKT success */
- } u;
- const struct nfs_server * server;
+struct nfs_lockt_res {
+ struct file_lock * denied; /* LOCK, LOCKT failed */
};
struct nfs4_delegreturnargs {
const struct nfs_fh *fhandle;
const nfs4_stateid *stateid;
+ const u32 * bitmask;
+};
+
+struct nfs4_delegreturnres {
+ struct nfs_fattr * fattr;
+ const struct nfs_server *server;
};
/*
* Arguments to the read call.
*/
-
-#define NFS_READ_MAXIOV (9U)
-#if (NFS_READ_MAXIOV > (MAX_IOVEC -2))
-#error "NFS_READ_MAXIOV is too large"
-#endif
-
struct nfs_readargs {
struct nfs_fh * fh;
struct nfs_open_context *context;
@@ -243,11 +249,6 @@ struct nfs_readres {
/*
* Arguments to the write call.
*/
-#define NFS_WRITE_MAXIOV (9U)
-#if (NFS_WRITE_MAXIOV > (MAX_IOVEC -2))
-#error "NFS_WRITE_MAXIOV is too large"
-#endif
-
struct nfs_writeargs {
struct nfs_fh * fh;
struct nfs_open_context *context;
@@ -678,6 +679,8 @@ struct nfs4_server_caps_res {
struct nfs_page;
+#define NFS_PAGEVEC_SIZE (8U)
+
struct nfs_read_data {
int flags;
struct rpc_task task;
@@ -686,13 +689,14 @@ struct nfs_read_data {
struct nfs_fattr fattr; /* fattr storage */
struct list_head pages; /* Coalesced read requests */
struct nfs_page *req; /* multi ops per nfs_page */
- struct page *pagevec[NFS_READ_MAXIOV];
+ struct page **pagevec;
struct nfs_readargs args;
struct nfs_readres res;
#ifdef CONFIG_NFS_V4
unsigned long timestamp; /* For lease renewal */
#endif
void (*complete) (struct nfs_read_data *, int);
+ struct page *page_array[NFS_PAGEVEC_SIZE + 1];
};
struct nfs_write_data {
@@ -704,13 +708,14 @@ struct nfs_write_data {
struct nfs_writeverf verf;
struct list_head pages; /* Coalesced requests we wish to flush */
struct nfs_page *req; /* multi ops per nfs_page */
- struct page *pagevec[NFS_WRITE_MAXIOV];
+ struct page **pagevec;
struct nfs_writeargs args; /* argument struct */
struct nfs_writeres res; /* result struct */
#ifdef CONFIG_NFS_V4
unsigned long timestamp; /* For lease renewal */
#endif
void (*complete) (struct nfs_write_data *, int);
+ struct page *page_array[NFS_PAGEVEC_SIZE + 1];
};
struct nfs_access_entry;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 51c231a1e5a6..ec7c2e872d72 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -124,7 +124,7 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *,
int nfsd_notify_change(struct inode *, struct iattr *);
int nfsd_permission(struct svc_export *, struct dentry *, int);
-void nfsd_sync_dir(struct dentry *dp);
+int nfsd_sync_dir(struct dentry *dp);
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
#ifdef CONFIG_NFSD_V2_ACL
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index bb842ea41033..0798b7781a6e 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -294,7 +294,7 @@ fill_post_wcc(struct svc_fh *fhp)
/*
* Lock a file handle/inode
* NOTE: both fh_lock and fh_unlock are done "by hand" in
- * vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once
+ * vfs.c:nfsd_rename as it needs to grab 2 i_mutex's at once
* so, any changes here should be reflected there.
*/
static inline void
@@ -317,7 +317,7 @@ fh_lock(struct svc_fh *fhp)
}
inode = dentry->d_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
fill_pre_wcc(fhp);
fhp->fh_locked = 1;
}
@@ -333,7 +333,7 @@ fh_unlock(struct svc_fh *fhp)
if (fhp->fh_locked) {
fill_post_wcc(fhp);
- up(&fhp->fh_dentry->d_inode->i_sem);
+ mutex_unlock(&fhp->fh_dentry->d_inode->i_mutex);
fhp->fh_locked = 0;
}
}
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index 130d4f588a37..3f4f7142bbe3 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -88,10 +88,12 @@ struct nfsd_readdirargs {
struct nfsd_attrstat {
struct svc_fh fh;
+ struct kstat stat;
};
struct nfsd_diropres {
struct svc_fh fh;
+ struct kstat stat;
};
struct nfsd_readlinkres {
@@ -101,6 +103,7 @@ struct nfsd_readlinkres {
struct nfsd_readres {
struct svc_fh fh;
unsigned long count;
+ struct kstat stat;
};
struct nfsd_readdirres {
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 3c2a71b43bac..a4322741f8b9 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -126,6 +126,7 @@ struct nfsd3_setaclargs {
struct nfsd3_attrstat {
__u32 status;
struct svc_fh fh;
+ struct kstat stat;
};
/* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 8903688890ce..77adba7d2281 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -145,8 +145,9 @@ struct nfsd4_lock {
} ok;
struct nfsd4_lock_denied denied;
} u;
-
- struct nfs4_stateowner *lk_stateowner;
+ /* The lk_replay_owner is the open owner in the open_to_lock_owner
+ * case and the lock owner otherwise: */
+ struct nfs4_stateowner *lk_replay_owner;
};
#define lk_new_open_seqid v.new.open_seqid
#define lk_new_open_stateid v.new.open_stateid
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 343083fec258..d52999c43336 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -79,13 +79,23 @@
/*
* Global page accounting. One instance per CPU. Only unsigned longs are
* allowed.
+ *
+ * - Fields can be modified with xxx_page_state and xxx_page_state_zone at
+ * any time safely (which protects the instance from modification by
+ * interrupt.
+ * - The __xxx_page_state variants can be used safely when interrupts are
+ * disabled.
+ * - The __xxx_page_state variants can be used if the field is only
+ * modified from process context, or only modified from interrupt context.
+ * In this case, the field should be commented here.
*/
struct page_state {
unsigned long nr_dirty; /* Dirty writeable pages */
unsigned long nr_writeback; /* Pages under writeback */
unsigned long nr_unstable; /* NFS unstable pages */
unsigned long nr_page_table_pages;/* Pages used for pagetables */
- unsigned long nr_mapped; /* mapped into pagetables */
+ unsigned long nr_mapped; /* mapped into pagetables.
+ * only modified from process context */
unsigned long nr_slab; /* In slab */
#define GET_PAGE_STATE_LAST nr_slab
@@ -97,32 +107,40 @@ struct page_state {
unsigned long pgpgout; /* Disk writes */
unsigned long pswpin; /* swap reads */
unsigned long pswpout; /* swap writes */
- unsigned long pgalloc_high; /* page allocations */
+ unsigned long pgalloc_high; /* page allocations */
unsigned long pgalloc_normal;
+ unsigned long pgalloc_dma32;
unsigned long pgalloc_dma;
+
unsigned long pgfree; /* page freeings */
unsigned long pgactivate; /* pages moved inactive->active */
unsigned long pgdeactivate; /* pages moved active->inactive */
unsigned long pgfault; /* faults (major+minor) */
unsigned long pgmajfault; /* faults (major only) */
+
unsigned long pgrefill_high; /* inspected in refill_inactive_zone */
unsigned long pgrefill_normal;
+ unsigned long pgrefill_dma32;
unsigned long pgrefill_dma;
unsigned long pgsteal_high; /* total highmem pages reclaimed */
unsigned long pgsteal_normal;
+ unsigned long pgsteal_dma32;
unsigned long pgsteal_dma;
+
unsigned long pgscan_kswapd_high;/* total highmem pages scanned */
unsigned long pgscan_kswapd_normal;
-
+ unsigned long pgscan_kswapd_dma32;
unsigned long pgscan_kswapd_dma;
+
unsigned long pgscan_direct_high;/* total highmem pages scanned */
unsigned long pgscan_direct_normal;
+ unsigned long pgscan_direct_dma32;
unsigned long pgscan_direct_dma;
- unsigned long pginodesteal; /* pages reclaimed via inode freeing */
+ unsigned long pginodesteal; /* pages reclaimed via inode freeing */
unsigned long slabs_scanned; /* slab objects scanned */
unsigned long kswapd_steal; /* pages reclaimed by kswapd */
unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */
@@ -136,31 +154,54 @@ 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);
+extern unsigned long read_page_state_offset(unsigned long offset);
+extern void mod_page_state_offset(unsigned long offset, unsigned long delta);
+extern void __mod_page_state_offset(unsigned long offset, unsigned long delta);
#define read_page_state(member) \
- __read_page_state(offsetof(struct page_state, member))
+ read_page_state_offset(offsetof(struct page_state, member))
#define mod_page_state(member, delta) \
- __mod_page_state(offsetof(struct page_state, member), (delta))
-
-#define inc_page_state(member) mod_page_state(member, 1UL)
-#define dec_page_state(member) mod_page_state(member, 0UL - 1)
-#define add_page_state(member,delta) mod_page_state(member, (delta))
-#define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta))
-
-#define mod_page_state_zone(zone, member, delta) \
- do { \
- unsigned offset; \
- if (is_highmem(zone)) \
- offset = offsetof(struct page_state, member##_high); \
- else if (is_normal(zone)) \
- offset = offsetof(struct page_state, member##_normal); \
- else \
- offset = offsetof(struct page_state, member##_dma); \
- __mod_page_state(offset, (delta)); \
- } while (0)
+ mod_page_state_offset(offsetof(struct page_state, member), (delta))
+
+#define __mod_page_state(member, delta) \
+ __mod_page_state_offset(offsetof(struct page_state, member), (delta))
+
+#define inc_page_state(member) mod_page_state(member, 1UL)
+#define dec_page_state(member) mod_page_state(member, 0UL - 1)
+#define add_page_state(member,delta) mod_page_state(member, (delta))
+#define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta))
+
+#define __inc_page_state(member) __mod_page_state(member, 1UL)
+#define __dec_page_state(member) __mod_page_state(member, 0UL - 1)
+#define __add_page_state(member,delta) __mod_page_state(member, (delta))
+#define __sub_page_state(member,delta) __mod_page_state(member, 0UL - (delta))
+
+#define page_state(member) (*__page_state(offsetof(struct page_state, member)))
+
+#define state_zone_offset(zone, member) \
+({ \
+ unsigned offset; \
+ if (is_highmem(zone)) \
+ offset = offsetof(struct page_state, member##_high); \
+ else if (is_normal(zone)) \
+ offset = offsetof(struct page_state, member##_normal); \
+ else if (is_dma32(zone)) \
+ offset = offsetof(struct page_state, member##_dma32); \
+ else \
+ offset = offsetof(struct page_state, member##_dma); \
+ offset; \
+})
+
+#define __mod_page_state_zone(zone, member, delta) \
+ do { \
+ __mod_page_state_offset(state_zone_offset(zone, member), (delta)); \
+ } while (0)
+
+#define mod_page_state_zone(zone, member, delta) \
+ do { \
+ mod_page_state_offset(state_zone_offset(zone, member), (delta)); \
+ } while (0)
/*
* Manipulation of page state flags
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h
index def32c5715be..8eb7fa76c1d0 100644
--- a/include/linux/pagevec.h
+++ b/include/linux/pagevec.h
@@ -5,6 +5,9 @@
* pages. A pagevec is a multipage container which is used for that.
*/
+#ifndef _LINUX_PAGEVEC_H
+#define _LINUX_PAGEVEC_H
+
/* 14 pointers + two long's align the pagevec structure to a power of two */
#define PAGEVEC_SIZE 14
@@ -83,3 +86,5 @@ static inline void pagevec_lru_add(struct pagevec *pvec)
if (pagevec_count(pvec))
__pagevec_lru_add(pvec);
}
+
+#endif /* _LINUX_PAGEVEC_H */
diff --git a/include/linux/parport.h b/include/linux/parport.h
index d2a4d9e1e6d1..f67f838a3a1f 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -236,7 +236,8 @@ struct pardevice {
/* IEEE1284 information */
-/* IEEE1284 phases */
+/* IEEE1284 phases. These are exposed to userland through ppdev IOCTL
+ * PP[GS]ETPHASE, so do not change existing values. */
enum ieee1284_phase {
IEEE1284_PH_FWD_DATA,
IEEE1284_PH_FWD_IDLE,
diff --git a/include/linux/parport_pc.h b/include/linux/parport_pc.h
index c6f762470879..1cc0f6b1a49a 100644
--- a/include/linux/parport_pc.h
+++ b/include/linux/parport_pc.h
@@ -79,13 +79,13 @@ static __inline__ unsigned char parport_pc_read_data(struct parport *p)
}
#ifdef DEBUG_PARPORT
-extern __inline__ void dump_parport_state (char *str, struct parport *p)
+static inline void dump_parport_state (char *str, struct parport *p)
{
/* here's hoping that reading these ports won't side-effect anything underneath */
unsigned char ecr = inb (ECONTROL (p));
unsigned char dcr = inb (CONTROL (p));
unsigned char dsr = inb (STATUS (p));
- static char *ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"};
+ static const char *const ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"};
const struct parport_pc_private *priv = p->physport->private_data;
int i;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index de690ca73d58..0a44072383ec 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -78,6 +78,23 @@ typedef int __bitwise pci_power_t;
#define PCI_UNKNOWN ((pci_power_t __force) 5)
#define PCI_POWER_ERROR ((pci_power_t __force) -1)
+/** The pci_channel state describes connectivity between the CPU and
+ * the pci device. If some PCI bus between here and the pci device
+ * has crashed or locked up, this info is reflected here.
+ */
+typedef unsigned int __bitwise pci_channel_state_t;
+
+enum pci_channel_state {
+ /* I/O channel is in normal state */
+ pci_channel_io_normal = (__force pci_channel_state_t) 1,
+
+ /* I/O to channel is blocked */
+ pci_channel_io_frozen = (__force pci_channel_state_t) 2,
+
+ /* PCI card is dead */
+ pci_channel_io_perm_failure = (__force pci_channel_state_t) 3,
+};
+
/*
* The pci_dev structure is used to describe PCI devices.
*/
@@ -98,6 +115,7 @@ struct pci_dev {
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
u8 rom_base_reg; /* which config register controls the ROM */
+ u8 pin; /* which interrupt pin this device uses */
struct pci_driver *driver; /* which driver has allocated this device */
u64 dma_mask; /* Mask of the bits of bus address this
@@ -110,6 +128,7 @@ struct pci_dev {
this is D0-D3, D0 being fully functional,
and D3 being off. */
+ pci_channel_state_t error_state; /* current connectivity state */
struct device dev; /* Generic device interface */
/* device is compatible with these IDs */
@@ -232,6 +251,54 @@ struct pci_dynids {
unsigned int use_driver_data:1; /* pci_driver->driver_data is used */
};
+/* ---------------------------------------------------------------- */
+/** PCI Error Recovery System (PCI-ERS). If a PCI device driver provides
+ * a set fof callbacks in struct pci_error_handlers, then that device driver
+ * will be notified of PCI bus errors, and will be driven to recovery
+ * when an error occurs.
+ */
+
+typedef unsigned int __bitwise pci_ers_result_t;
+
+enum pci_ers_result {
+ /* no result/none/not supported in device driver */
+ PCI_ERS_RESULT_NONE = (__force pci_ers_result_t) 1,
+
+ /* Device driver can recover without slot reset */
+ PCI_ERS_RESULT_CAN_RECOVER = (__force pci_ers_result_t) 2,
+
+ /* Device driver wants slot to be reset. */
+ PCI_ERS_RESULT_NEED_RESET = (__force pci_ers_result_t) 3,
+
+ /* Device has completely failed, is unrecoverable */
+ PCI_ERS_RESULT_DISCONNECT = (__force pci_ers_result_t) 4,
+
+ /* Device driver is fully recovered and operational */
+ PCI_ERS_RESULT_RECOVERED = (__force pci_ers_result_t) 5,
+};
+
+/* PCI bus error event callbacks */
+struct pci_error_handlers
+{
+ /* PCI bus error detected on this device */
+ pci_ers_result_t (*error_detected)(struct pci_dev *dev,
+ enum pci_channel_state error);
+
+ /* MMIO has been re-enabled, but not DMA */
+ pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
+
+ /* PCI Express link has been reset */
+ pci_ers_result_t (*link_reset)(struct pci_dev *dev);
+
+ /* PCI slot has been reset */
+ pci_ers_result_t (*slot_reset)(struct pci_dev *dev);
+
+ /* Device driver may resume normal operations */
+ void (*resume)(struct pci_dev *dev);
+};
+
+/* ---------------------------------------------------------------- */
+
struct module;
struct pci_driver {
struct list_head node;
@@ -244,6 +311,7 @@ struct pci_driver {
int (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable); /* Enable wake event */
void (*shutdown) (struct pci_dev *dev);
+ struct pci_error_handlers *err_handler;
struct device_driver driver;
struct pci_dynids dynids;
};
@@ -448,6 +516,7 @@ 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);
+int pci_cfg_space_size(struct pci_dev *dev);
/* kmem_cache style wrapper around pci_alloc_consistent() */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4db67b3b05cc..ecc1fc1f0f04 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -15,6 +15,7 @@
#define PCI_CLASS_STORAGE_FLOPPY 0x0102
#define PCI_CLASS_STORAGE_IPI 0x0103
#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_SAS 0x0107
#define PCI_CLASS_STORAGE_OTHER 0x0180
#define PCI_BASE_CLASS_NETWORK 0x02
@@ -180,6 +181,7 @@
#define PCI_DEVICE_ID_LSI_FC929X 0x0626
#define PCI_DEVICE_ID_LSI_FC939X 0x0642
#define PCI_DEVICE_ID_LSI_FC949X 0x0640
+#define PCI_DEVICE_ID_LSI_FC949ES 0x0646
#define PCI_DEVICE_ID_LSI_FC919X 0x0628
#define PCI_DEVICE_ID_NCR_YELLOWFIN 0x0701
#define PCI_DEVICE_ID_LSI_61C102 0x0901
@@ -376,6 +378,11 @@
#define PCI_DEVICE_ID_NS_87560_USB 0x0012
#define PCI_DEVICE_ID_NS_83815 0x0020
#define PCI_DEVICE_ID_NS_83820 0x0022
+#define PCI_DEVICE_ID_NS_CS5535_ISA 0x002b
+#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d
+#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e
+#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f
+#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030
#define PCI_DEVICE_ID_NS_SATURN 0x0035
#define PCI_DEVICE_ID_NS_SCx200_BRIDGE 0x0500
#define PCI_DEVICE_ID_NS_SCx200_SMI 0x0501
@@ -389,6 +396,13 @@
#define PCI_DEVICE_ID_NS_87410 0xd001
#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d
+#define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE 0x0028
+#define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE 0x002b
+#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d
+#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e
+#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f
+#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030
+
#define PCI_VENDOR_ID_TSENG 0x100c
#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202
#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205
@@ -488,9 +502,20 @@
#define PCI_DEVICE_ID_AMD_8111_AUDIO 0x746d
#define PCI_DEVICE_ID_AMD_8151_0 0x7454
#define PCI_DEVICE_ID_AMD_8131_APIC 0x7450
+#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090
+#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091
+#define PCI_DEVICE_ID_AMD_CS5536_AUDIO 0x2093
+#define PCI_DEVICE_ID_AMD_CS5536_OHC 0x2094
+#define PCI_DEVICE_ID_AMD_CS5536_EHC 0x2095
+#define PCI_DEVICE_ID_AMD_CS5536_UDC 0x2096
+#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097
+#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A
#define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A
+#define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081
+#define PCI_DEVICE_ID_AMD_LX_AES 0x2082
+
#define PCI_VENDOR_ID_TRIDENT 0x1023
#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001
@@ -971,6 +996,7 @@
#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN 0x002a
#define PCI_DEVICE_ID_NVIDIA_VTNT2 0x002C
#define PCI_DEVICE_ID_NVIDIA_UVTNT2 0x002D
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS 0x0034
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE 0x0035
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA 0x0036
#define PCI_DEVICE_ID_NVIDIA_NVENET_10 0x0037
@@ -1025,6 +1051,11 @@
#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 PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
+#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101
#define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103
@@ -1567,6 +1598,23 @@
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6 0x0009
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1 0x000A
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1 0x000B
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ 0x000C
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM 0x000D
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI 0x0100
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2 0x0201
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4 0x0202
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232 0x0300
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232 0x0301
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232 0x0302
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1 0x0310
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2 0x0311
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4 0x0312
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2 0x0320
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4 0x0321
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8 0x0322
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485 0x0330
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 0x0331
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 0x0332
#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
@@ -1944,6 +1992,7 @@
#define PCI_VENDOR_ID_DCI 0x6666
#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001
#define PCI_DEVICE_ID_DCI_PCCOM8 0x0002
+#define PCI_DEVICE_ID_DCI_PCCOM2 0x0004
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_EESSC 0x0008
@@ -2105,6 +2154,9 @@
#define PCI_DEVICE_ID_INTEL_IXP2800 0x9004
#define PCI_DEVICE_ID_INTEL_S21152BB 0xb152
+#define PCI_VENDOR_ID_SCALEMP 0x8686
+#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL 0x1010
+
#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291
#define PCI_DEVICE_ID_COMPUTONE_PG 0x0302
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index e2a089b051ed..d27a78b71297 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -196,6 +196,7 @@
#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_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */
#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 */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index fb8d2d24e4bb..cb9039a21f2a 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -19,7 +19,6 @@
struct percpu_data {
void *ptrs[NR_CPUS];
- void *blkp;
};
/*
@@ -33,14 +32,14 @@ struct percpu_data {
(__typeof__(ptr))__p->ptrs[(cpu)]; \
})
-extern void *__alloc_percpu(size_t size, size_t align);
+extern void *__alloc_percpu(size_t size);
extern void free_percpu(const void *);
#else /* CONFIG_SMP */
#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); })
-static inline void *__alloc_percpu(size_t size, size_t align)
+static inline void *__alloc_percpu(size_t size)
{
void *ret = kmalloc(size, GFP_KERNEL);
if (ret)
@@ -55,7 +54,6 @@ static inline void free_percpu(const void *ptr)
#endif /* CONFIG_SMP */
/* Simple wrapper for the common case: zeros memory. */
-#define alloc_percpu(type) \
- ((type *)(__alloc_percpu(sizeof(type), __alignof__(type))))
+#define alloc_percpu(type) ((type *)(__alloc_percpu(sizeof(type))))
#endif /* __LINUX_PERCPU_H */
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index 724066778aff..bac0fb389cf1 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -104,7 +104,7 @@ struct sadb_prop {
/* followed by:
struct sadb_comb sadb_combs[(sadb_prop_len +
sizeof(uint64_t) - sizeof(struct sadb_prop)) /
- sizeof(strut sadb_comb)]; */
+ sizeof(struct sadb_comb)]; */
struct sadb_comb {
uint8_t sadb_comb_auth;
@@ -216,6 +216,16 @@ struct sadb_x_nat_t_port {
} __attribute__((packed));
/* sizeof(struct sadb_x_nat_t_port) == 8 */
+/* Generic LSM security context */
+struct sadb_x_sec_ctx {
+ uint16_t sadb_x_sec_len;
+ uint16_t sadb_x_sec_exttype;
+ uint8_t sadb_x_ctx_alg; /* LSMs: e.g., selinux == 1 */
+ uint8_t sadb_x_ctx_doi;
+ uint16_t sadb_x_ctx_len;
+} __attribute__((packed));
+/* sizeof(struct sadb_sec_ctx) = 8 */
+
/* Message types */
#define SADB_RESERVED 0
#define SADB_GETSPI 1
@@ -325,7 +335,8 @@ struct sadb_x_nat_t_port {
#define SADB_X_EXT_NAT_T_SPORT 21
#define SADB_X_EXT_NAT_T_DPORT 22
#define SADB_X_EXT_NAT_T_OA 23
-#define SADB_EXT_MAX 23
+#define SADB_X_EXT_SEC_CTX 24
+#define SADB_EXT_MAX 24
/* Identity Extension values */
#define SADB_IDENTTYPE_RESERVED 0
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 92a9696fdebe..331521a10a2d 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -53,6 +53,9 @@
#define PHY_MAX_ADDR 32
+/* Used when trying to connect to a specific phy (mii bus id:phy device id) */
+#define PHY_ID_FMT "%x:%02x"
+
/* The Bus class for PHYs. Devices which provide access to
* PHYs should register using this structure */
struct mii_bus {
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 1767073df26f..b12e59c75752 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -37,7 +37,7 @@ struct pipe_inode_info {
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE
-#define PIPE_SEM(inode) (&(inode).i_sem)
+#define PIPE_MUTEX(inode) (&(inode).i_mutex)
#define PIPE_WAIT(inode) (&(inode).i_pipe->wait)
#define PIPE_READERS(inode) ((inode).i_pipe->readers)
#define PIPE_WRITERS(inode) ((inode).i_pipe->writers)
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index e87b233615b3..d10f35338507 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -429,6 +429,7 @@ enum
TCA_NETEM_CORR,
TCA_NETEM_DELAY_DIST,
TCA_NETEM_REORDER,
+ TCA_NETEM_CORRUPT,
__TCA_NETEM_MAX,
};
@@ -457,6 +458,12 @@ struct tc_netem_reorder
__u32 correlation;
};
+struct tc_netem_corrupt
+{
+ __u32 probability;
+ __u32 correlation;
+};
+
#define NETEM_DIST_SCALE 8192
#endif
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 17e336f40b47..782090c68932 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -41,6 +41,7 @@ extern struct platform_device *platform_device_alloc(const char *name, unsigned
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
extern int platform_device_add(struct platform_device *pdev);
+extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
struct platform_driver {
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index 373bd3b9b330..217d3daf7336 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -140,7 +140,7 @@ extern int find_via_pmu(void);
extern int pmu_request(struct adb_request *req,
void (*done)(struct adb_request *), int nbytes, ...);
-
+extern int pmu_queue_request(struct adb_request *req);
extern void pmu_poll(void);
extern void pmu_poll_adb(void); /* For use by xmon */
extern void pmu_wait_complete(struct adb_request *req);
@@ -160,12 +160,6 @@ extern void pmu_unlock(void);
extern int pmu_present(void);
extern int pmu_get_model(void);
-extern int pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len);
-extern int pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len);
-extern int pmu_i2c_simple_read(int bus, int addr, u8* data, int len);
-extern int pmu_i2c_simple_write(int bus, int addr, u8* data, int len);
-
-
#ifdef CONFIG_PM
/*
* Stuff for putting the powerbook to sleep and waking it again.
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index 584d57cb393a..93b0959eb40f 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -162,6 +162,7 @@ struct pnp_card_link {
struct pnp_card * card;
struct pnp_card_driver * driver;
void * driver_data;
+ pm_message_t pm_state;
};
static inline void *pnp_get_card_drvdata (struct pnp_card_link *pcard)
@@ -294,6 +295,8 @@ struct pnp_driver {
unsigned int flags;
int (*probe) (struct pnp_dev *dev, const struct pnp_device_id *dev_id);
void (*remove) (struct pnp_dev *dev);
+ int (*suspend) (struct pnp_dev *dev, pm_message_t state);
+ int (*resume) (struct pnp_dev *dev);
struct device_driver driver;
};
@@ -306,6 +309,8 @@ struct pnp_card_driver {
unsigned int flags;
int (*probe) (struct pnp_card_link *card, const struct pnp_card_device_id *card_id);
void (*remove) (struct pnp_card_link *card);
+ int (*suspend) (struct pnp_card_link *card, pm_message_t state);
+ int (*resume) (struct pnp_card_link *card);
struct pnp_driver link;
};
@@ -380,6 +385,8 @@ void pnp_init_resource_table(struct pnp_resource_table *table);
int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode);
int pnp_auto_config_dev(struct pnp_dev *dev);
int pnp_validate_config(struct pnp_dev *dev);
+int pnp_start_dev(struct pnp_dev *dev);
+int pnp_stop_dev(struct pnp_dev *dev);
int pnp_activate_dev(struct pnp_dev *dev);
int pnp_disable_dev(struct pnp_dev *dev);
void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size);
@@ -423,6 +430,8 @@ static inline void pnp_init_resource_table(struct pnp_resource_table *table) { }
static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; }
static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; }
+static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; }
static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { }
diff --git a/include/linux/poll.h b/include/linux/poll.h
index f6da702088f4..8e8f6098508a 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -92,7 +92,11 @@ void zero_fd_set(unsigned long nr, unsigned long *fdset)
memset(fdset, 0, FDS_BYTES(nr));
}
-extern int do_select(int n, fd_set_bits *fds, long *timeout);
+#define MAX_INT64_SECONDS (((s64)(~((u64)0)>>1)/HZ)-1)
+
+extern int do_select(int n, fd_set_bits *fds, s64 *timeout);
+extern int do_sys_poll(struct pollfd __user * ufds, unsigned int nfds,
+ s64 *timeout);
#endif /* KERNEL */
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index f942e2bad8e3..54faf5236da0 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -42,7 +42,7 @@ struct k_itimer {
timer_t it_id; /* timer id */
int it_overrun; /* overrun on pending signal */
int it_overrun_last; /* overrun on last delivered signal */
- int it_requeue_pending; /* waiting to requeue this timer */
+ int it_requeue_pending; /* waiting to requeue this timer */
#define REQUEUE_PENDING 1
int it_sigev_notify; /* notify word of sigevent struct */
int it_sigev_signo; /* signo word of sigevent struct */
@@ -51,10 +51,8 @@ struct k_itimer {
struct sigqueue *sigq; /* signal queue entry. */
union {
struct {
- struct timer_list timer;
- struct list_head abs_timer_entry; /* clock abs_timer_list */
- struct timespec wall_to_prev; /* wall_to_monotonic used when set */
- unsigned long incr; /* interval in jiffies */
+ struct hrtimer timer;
+ ktime_t interval;
} real;
struct cpu_timer_list cpu;
struct {
@@ -66,18 +64,14 @@ struct k_itimer {
} it;
};
-struct k_clock_abs {
- struct list_head list;
- spinlock_t lock;
-};
struct k_clock {
- int res; /* in nano seconds */
- int (*clock_getres) (clockid_t which_clock, struct timespec *tp);
- struct k_clock_abs *abs_struct;
- int (*clock_set) (clockid_t which_clock, struct timespec * tp);
- int (*clock_get) (clockid_t which_clock, struct timespec * tp);
+ int res; /* in nanoseconds */
+ int (*clock_getres) (const clockid_t which_clock, struct timespec *tp);
+ int (*clock_set) (const clockid_t which_clock, struct timespec * tp);
+ int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
int (*timer_create) (struct k_itimer *timer);
- int (*nsleep) (clockid_t which_clock, int flags, struct timespec *);
+ int (*nsleep) (const clockid_t which_clock, int flags,
+ struct timespec *, struct timespec __user *);
int (*timer_set) (struct k_itimer * timr, int flags,
struct itimerspec * new_setting,
struct itimerspec * old_setting);
@@ -87,53 +81,35 @@ struct k_clock {
struct itimerspec * cur_setting);
};
-void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock);
+void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
-/* Error handlers for timer_create, nanosleep and settime */
+/* error handlers for timer_create, nanosleep and settime */
int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(clockid_t, int flags, struct timespec *);
-int do_posix_clock_nosettime(clockid_t, struct timespec *tp);
+int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
+ struct timespec __user *);
+int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
/* function to call to trigger timer event */
int posix_timer_event(struct k_itimer *timr, int si_private);
-struct now_struct {
- unsigned long jiffies;
-};
-
-#define posix_get_now(now) (now)->jiffies = jiffies;
-#define posix_time_before(timer, now) \
- time_before((timer)->expires, (now)->jiffies)
-
-#define posix_bump_timer(timr, now) \
- do { \
- long delta, orun; \
- delta = now.jiffies - (timr)->it.real.timer.expires; \
- if (delta >= 0) { \
- orun = 1 + (delta / (timr)->it.real.incr); \
- (timr)->it.real.timer.expires += \
- orun * (timr)->it.real.incr; \
- (timr)->it_overrun += orun; \
- } \
- }while (0)
-
-int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *);
-int posix_cpu_clock_get(clockid_t which_clock, struct timespec *);
-int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp);
-int posix_cpu_timer_create(struct k_itimer *);
-int posix_cpu_nsleep(clockid_t, int, struct timespec *);
-int posix_cpu_timer_set(struct k_itimer *, int,
- struct itimerspec *, struct itimerspec *);
-int posix_cpu_timer_del(struct k_itimer *);
-void posix_cpu_timer_get(struct k_itimer *, struct itimerspec *);
-
-void posix_cpu_timer_schedule(struct k_itimer *);
-
-void run_posix_cpu_timers(struct task_struct *);
-void posix_cpu_timers_exit(struct task_struct *);
-void posix_cpu_timers_exit_group(struct task_struct *);
-
-void set_process_cpu_timer(struct task_struct *, unsigned int,
- cputime_t *, cputime_t *);
+int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *ts);
+int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
+int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
+int posix_cpu_timer_create(struct k_itimer *timer);
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+ struct timespec *rqtp, struct timespec __user *rmtp);
+int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+ struct itimerspec *new, struct itimerspec *old);
+int posix_cpu_timer_del(struct k_itimer *timer);
+void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp);
+
+void posix_cpu_timer_schedule(struct k_itimer *timer);
+
+void run_posix_cpu_timers(struct task_struct *task);
+void posix_cpu_timers_exit(struct task_struct *task);
+void posix_cpu_timers_exit_group(struct task_struct *task);
+
+void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
+ cputime_t *newval, cputime_t *oldval);
#endif
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 74488e49166d..aa6322d45198 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -146,6 +146,11 @@ struct property;
extern void proc_device_tree_init(void);
extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *);
extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop);
+extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde,
+ struct property *prop);
+extern void proc_device_tree_update_prop(struct proc_dir_entry *pde,
+ struct property *newprop,
+ struct property *oldprop);
#endif /* CONFIG_PROC_DEVICETREE */
extern struct proc_dir_entry *proc_symlink(const char *,
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index b2b3dba1298d..9d5cd106b344 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -20,8 +20,6 @@
#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
@@ -80,6 +78,8 @@
extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
+extern struct task_struct *ptrace_get_task_struct(pid_t pid);
+extern int ptrace_traceme(void);
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
extern int ptrace_attach(struct task_struct *tsk);
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 36e5d269612f..c57ff2fcb30a 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -19,6 +19,7 @@
#ifndef _LINUX_RADIX_TREE_H
#define _LINUX_RADIX_TREE_H
+#include <linux/sched.h>
#include <linux/preempt.h>
#include <linux/types.h>
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 13e7c4b62367..b6e0bcad84e1 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -71,8 +71,8 @@
*/
#define MD_PATCHLEVEL_VERSION 3
-extern int register_md_personality (int p_num, mdk_personality_t *p);
-extern int unregister_md_personality (int p_num);
+extern int register_md_personality (struct mdk_personality *p);
+extern int unregister_md_personality (struct mdk_personality *p);
extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
mddev_t *mddev, const char *name);
extern void md_unregister_thread (mdk_thread_t *thread);
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 46629a275ba9..617b9506c760 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -18,62 +18,19 @@
/* and dm-bio-list.h is not under include/linux because.... ??? */
#include "../../../drivers/md/dm-bio-list.h"
-#define MD_RESERVED 0UL
-#define LINEAR 1UL
-#define RAID0 2UL
-#define RAID1 3UL
-#define RAID5 4UL
-#define TRANSLUCENT 5UL
-#define HSM 6UL
-#define MULTIPATH 7UL
-#define RAID6 8UL
-#define RAID10 9UL
-#define FAULTY 10UL
-#define MAX_PERSONALITY 11UL
-
#define LEVEL_MULTIPATH (-4)
#define LEVEL_LINEAR (-1)
#define LEVEL_FAULTY (-5)
+/* we need a value for 'no level specified' and 0
+ * means 'raid0', so we need something else. This is
+ * for internal use only
+ */
+#define LEVEL_NONE (-1000000)
+
#define MaxSector (~(sector_t)0)
#define MD_THREAD_NAME_MAX 14
-static inline int pers_to_level (int pers)
-{
- switch (pers) {
- case FAULTY: return LEVEL_FAULTY;
- case MULTIPATH: return LEVEL_MULTIPATH;
- case HSM: return -3;
- case TRANSLUCENT: return -2;
- case LINEAR: return LEVEL_LINEAR;
- case RAID0: return 0;
- case RAID1: return 1;
- case RAID5: return 5;
- case RAID6: return 6;
- case RAID10: return 10;
- }
- BUG();
- return MD_RESERVED;
-}
-
-static inline int level_to_pers (int level)
-{
- switch (level) {
- case LEVEL_FAULTY: return FAULTY;
- case LEVEL_MULTIPATH: return MULTIPATH;
- case -3: return HSM;
- case -2: return TRANSLUCENT;
- case LEVEL_LINEAR: return LINEAR;
- case 0: return RAID0;
- case 1: return RAID1;
- case 4:
- case 5: return RAID5;
- case 6: return RAID6;
- case 10: return RAID10;
- }
- return MD_RESERVED;
-}
-
typedef struct mddev_s mddev_t;
typedef struct mdk_rdev_s mdk_rdev_t;
@@ -138,14 +95,16 @@ struct mdk_rdev_s
atomic_t read_errors; /* number of consecutive read errors that
* we have tried to ignore.
*/
+ atomic_t corrected_errors; /* number of corrected read errors,
+ * for reporting to userspace and storing
+ * in superblock.
+ */
};
-typedef struct mdk_personality_s mdk_personality_t;
-
struct mddev_s
{
void *private;
- mdk_personality_t *pers;
+ struct mdk_personality *pers;
dev_t unit;
int md_minor;
struct list_head disks;
@@ -164,6 +123,7 @@ struct mddev_s
int chunk_size;
time_t ctime, utime;
int level, layout;
+ char clevel[16];
int raid_disks;
int max_disks;
sector_t size; /* used size of component devices */
@@ -183,6 +143,11 @@ struct mddev_s
sector_t resync_mismatches; /* count of sectors where
* parity/replica mismatch found
*/
+ /* if zero, use the system-wide default */
+ int sync_speed_min;
+ int sync_speed_max;
+
+ int ok_start_degraded;
/* recovery/resync flags
* NEEDED: we might need to start a resync/recover
* RUNNING: a thread is running, or about to be started
@@ -265,9 +230,11 @@ static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sect
atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
}
-struct mdk_personality_s
+struct mdk_personality
{
char *name;
+ int level;
+ struct list_head list;
struct module *owner;
int (*make_request)(request_queue_t *q, struct bio *bio);
int (*run)(mddev_t *mddev);
@@ -305,8 +272,6 @@ static inline char * mdname (mddev_t * mddev)
return mddev->gendisk ? mddev->gendisk->disk_name : "mdX";
}
-extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr);
-
/*
* iterates through some rdev ringlist. It's safe to remove the
* current 'rdev'. Dont touch 'tmp' though.
@@ -366,5 +331,10 @@ do { \
__wait_event_lock_irq(wq, condition, lock, cmd); \
} while (0)
+static inline void safe_put_page(struct page *p)
+{
+ if (p) put_page(p);
+}
+
#endif
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
index 292b98f2b408..9d5494aaac0f 100644
--- a/include/linux/raid/raid1.h
+++ b/include/linux/raid/raid1.h
@@ -45,6 +45,8 @@ struct r1_private_data_s {
spinlock_t resync_lock;
int nr_pending;
+ int nr_waiting;
+ int nr_queued;
int barrier;
sector_t next_resync;
int fullsync; /* set to 1 if a full sync is needed,
@@ -52,11 +54,12 @@ struct r1_private_data_s {
* Cleared when a sync completes.
*/
- wait_queue_head_t wait_idle;
- wait_queue_head_t wait_resume;
+ wait_queue_head_t wait_barrier;
struct pool_info *poolinfo;
+ struct page *tmppage;
+
mempool_t *r1bio_pool;
mempool_t *r1buf_pool;
};
@@ -106,6 +109,13 @@ struct r1bio_s {
/* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
};
+/* when we get a read error on a read-only array, we redirect to another
+ * device without failing the first device, or trying to over-write to
+ * correct the read error. To keep track of bad blocks on a per-bio
+ * level, we store IO_BLOCKED in the appropriate 'bios' pointer
+ */
+#define IO_BLOCKED ((struct bio*)1)
+
/* bits for r1bio.state */
#define R1BIO_Uptodate 0
#define R1BIO_IsSync 1
diff --git a/include/linux/raid/raid10.h b/include/linux/raid/raid10.h
index 60708789c8f9..b1103298a8c2 100644
--- a/include/linux/raid/raid10.h
+++ b/include/linux/raid/raid10.h
@@ -35,18 +35,26 @@ struct r10_private_data_s {
sector_t chunk_mask;
struct list_head retry_list;
- /* for use when syncing mirrors: */
+ /* queue pending writes and submit them on unplug */
+ struct bio_list pending_bio_list;
+
spinlock_t resync_lock;
int nr_pending;
+ int nr_waiting;
+ int nr_queued;
int barrier;
sector_t next_resync;
+ int fullsync; /* set to 1 if a full sync is needed,
+ * (fresh device added).
+ * Cleared when a sync completes.
+ */
- wait_queue_head_t wait_idle;
- wait_queue_head_t wait_resume;
+ wait_queue_head_t wait_barrier;
mempool_t *r10bio_pool;
mempool_t *r10buf_pool;
+ struct page *tmppage;
};
typedef struct r10_private_data_s conf_t;
@@ -96,8 +104,16 @@ struct r10bio_s {
} devs[0];
};
+/* when we get a read error on a read-only array, we redirect to another
+ * device without failing the first device, or trying to over-write to
+ * correct the read error. To keep track of bad blocks on a per-bio
+ * level, we store IO_BLOCKED in the appropriate 'bios' pointer
+ */
+#define IO_BLOCKED ((struct bio*)1)
+
/* bits for r10bio.state */
#define R10BIO_Uptodate 0
#define R10BIO_IsSync 1
#define R10BIO_IsRecover 2
+#define R10BIO_Degraded 3
#endif
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index f025ba6fb14c..394da8207b34 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -126,7 +126,7 @@
*/
struct stripe_head {
- struct stripe_head *hash_next, **hash_pprev; /* hash pointers */
+ struct hlist_node hash;
struct list_head lru; /* inactive_list or handle_list */
struct raid5_private_data *raid_conf;
sector_t sector; /* sector of this row */
@@ -152,7 +152,6 @@ struct stripe_head {
#define R5_Insync 3 /* rdev && rdev->in_sync at start */
#define R5_Wantread 4 /* want to schedule a read */
#define R5_Wantwrite 5
-#define R5_Syncio 6 /* this io need to be accounted as resync io */
#define R5_Overlap 7 /* There is a pending overlapping request on this block */
#define R5_ReadError 8 /* seen a read error here recently */
#define R5_ReWrite 9 /* have tried to over-write the readerror */
@@ -205,7 +204,7 @@ struct disk_info {
};
struct raid5_private_data {
- struct stripe_head **stripe_hashtbl;
+ struct hlist_head *stripe_hashtbl;
mddev_t *mddev;
struct disk_info *spare;
int chunk_size, level, algorithm;
@@ -228,6 +227,8 @@ struct raid5_private_data {
* Cleared when a sync completes.
*/
+ struct page *spare_page; /* Used when checking P/Q in raid6 */
+
/*
* Free stripes pool
*/
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h
index 48831eac2910..d0dd38b3a2fd 100644
--- a/include/linux/raid_class.h
+++ b/include/linux/raid_class.h
@@ -31,9 +31,11 @@ enum raid_level {
RAID_LEVEL_LINEAR,
RAID_LEVEL_0,
RAID_LEVEL_1,
+ RAID_LEVEL_10,
RAID_LEVEL_3,
RAID_LEVEL_4,
RAID_LEVEL_5,
+ RAID_LEVEL_50,
RAID_LEVEL_6,
};
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index e0a4faa9610c..953b6df5d037 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -5,6 +5,16 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data);
+#ifndef CONFIG_MMU
+extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags);
+
+extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma);
+#endif
+
extern struct file_operations ramfs_file_operations;
extern struct vm_operations_struct generic_file_vm_ops;
diff --git a/include/linux/random.h b/include/linux/random.h
index 7b2adb3322d5..5d6456bcdeba 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -52,9 +52,9 @@ extern void get_random_bytes(void *buf, int nbytes);
void generate_random_uuid(unsigned char uuid_out[16]);
extern __u32 secure_ip_id(__u32 daddr);
-extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
-extern u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr,
- __u16 dport);
+extern u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
+extern u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr,
+ __u16 dport);
extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
__u16 sport, __u16 dport);
extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index a471f3bb713e..981f9aa43353 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -65,7 +65,11 @@ struct rcu_ctrlblk {
long cur; /* Current batch number. */
long completed; /* Number of the last completed batch */
int next_pending; /* Is the next batch already waiting? */
-} ____cacheline_maxaligned_in_smp;
+
+ spinlock_t lock ____cacheline_internodealigned_in_smp;
+ cpumask_t cpumask; /* CPUs that need to switch in order */
+ /* for current batch to proceed. */
+} ____cacheline_internodealigned_in_smp;
/* Is batch a before batch b ? */
static inline int rcu_batch_before(long a, long b)
@@ -125,36 +129,7 @@ static inline void rcu_bh_qsctr_inc(int cpu)
rdp->passed_quiesc = 1;
}
-static inline int __rcu_pending(struct rcu_ctrlblk *rcp,
- struct rcu_data *rdp)
-{
- /* This cpu has pending rcu entries and the grace period
- * for them has completed.
- */
- if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch))
- return 1;
-
- /* This cpu has no pending entries, but there are new entries */
- if (!rdp->curlist && rdp->nxtlist)
- return 1;
-
- /* This cpu has finished callbacks to invoke */
- if (rdp->donelist)
- return 1;
-
- /* The rcu core waits for a quiescent state from the cpu */
- if (rdp->quiescbatch != rcp->cur || rdp->qs_pending)
- return 1;
-
- /* nothing to do */
- return 0;
-}
-
-static inline int rcu_pending(int cpu)
-{
- return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
- __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
-}
+extern int rcu_pending(int cpu);
/**
* rcu_read_lock - mark the beginning of an RCU read-side critical section.
diff --git a/include/linux/rcuref.h b/include/linux/rcuref.h
deleted file mode 100644
index e1adbba14b67..000000000000
--- a/include/linux/rcuref.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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 001ab82df051..e276c5ba2bb7 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1857,7 +1857,7 @@ void padd_item(char *item, int total_length, int length);
#define GET_BLOCK_CREATE 1 /* add anything you need to find block */
#define GET_BLOCK_NO_HOLE 2 /* return -ENOENT for file holes */
#define GET_BLOCK_READ_DIRECT 4 /* read the tail if indirect item not found */
-#define GET_BLOCK_NO_ISEM 8 /* i_sem is not held, don't preallocate */
+#define GET_BLOCK_NO_IMUX 8 /* i_mutex is not held, don't preallocate */
#define GET_BLOCK_NO_DANGLE 16 /* don't leave any transactions running */
int restart_transaction(struct reiserfs_transaction_handle *th,
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
index fb7e80737325..7342e66247fb 100644
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -65,20 +65,6 @@ struct rchan
};
/*
- * 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
@@ -124,6 +110,46 @@ struct rchan_callbacks
*/
void (*buf_unmapped)(struct rchan_buf *buf,
struct file *filp);
+ /*
+ * create_buf_file - create file to represent a relayfs channel buffer
+ * @filename: the name of the file to create
+ * @parent: the parent of the file to create
+ * @mode: the mode of the file to create
+ * @buf: the channel buffer
+ * @is_global: outparam - set non-zero if the buffer should be global
+ *
+ * Called during relay_open(), once for each per-cpu buffer,
+ * to allow the client to create a file to be used to
+ * represent the corresponding channel buffer. If the file is
+ * created outside of relayfs, the parent must also exist in
+ * that filesystem.
+ *
+ * The callback should return the dentry of the file created
+ * to represent the relay buffer.
+ *
+ * Setting the is_global outparam to a non-zero value will
+ * cause relay_open() to create a single global buffer rather
+ * than the default set of per-cpu buffers.
+ *
+ * See Documentation/filesystems/relayfs.txt for more info.
+ */
+ struct dentry *(*create_buf_file)(const char *filename,
+ struct dentry *parent,
+ int mode,
+ struct rchan_buf *buf,
+ int *is_global);
+
+ /*
+ * remove_buf_file - remove file representing a relayfs channel buffer
+ * @dentry: the dentry of the file to remove
+ *
+ * Called during relay_close(), once for each per-cpu buffer,
+ * to allow the client to remove a file used to represent a
+ * channel buffer.
+ *
+ * The callback should return 0 if successful, negative if not.
+ */
+ int (*remove_buf_file)(struct dentry *dentry);
};
/*
@@ -148,6 +174,12 @@ extern size_t relay_switch_subbuf(struct rchan_buf *buf,
extern struct dentry *relayfs_create_dir(const char *name,
struct dentry *parent);
extern int relayfs_remove_dir(struct dentry *dentry);
+extern struct dentry *relayfs_create_file(const char *name,
+ struct dentry *parent,
+ int mode,
+ struct file_operations *fops,
+ void *data);
+extern int relayfs_remove_file(struct dentry *dentry);
/**
* relay_write - write data into the channel
@@ -247,10 +279,9 @@ static inline void subbuf_start_reserve(struct rchan_buf *buf,
}
/*
- * exported relayfs file operations, fs/relayfs/inode.c
+ * exported relay file operations, fs/relayfs/inode.c
*/
-
-extern struct file_operations relayfs_file_operations;
+extern struct file_operations relay_file_operations;
#endif /* _LINUX_RELAYFS_FS_H */
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
index 3bd7cce19e26..f54772d0e7f8 100644
--- a/include/linux/rio_drv.h
+++ b/include/linux/rio_drv.h
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/device.h>
+#include <linux/string.h>
#include <linux/rio.h>
extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset,
@@ -336,8 +337,8 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end)
/**
* RIO_DEVICE - macro used to describe a specific RIO device
- * @vid: the 16 bit RIO vendor ID
- * @did: the 16 bit RIO device ID
+ * @dev: the 16 bit RIO device ID
+ * @ven: the 16 bit RIO vendor ID
*
* This macro is used to create a struct rio_device_id that matches a
* specific device. The assembly vendor and assembly device fields
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 33261f1d2239..9d6fbeef2104 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -71,6 +71,7 @@ void __anon_vma_link(struct vm_area_struct *);
* rmap interfaces called when adding or removing pte of page
*/
void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
+void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_file_rmap(struct page *);
void page_remove_rmap(struct page *);
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index e1aaf1fac8e0..0b2ba67ff13c 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -11,6 +11,8 @@
#ifndef _LINUX_RTC_H_
#define _LINUX_RTC_H_
+#include <linux/interrupt.h>
+
/*
* The struct used to pass data via the following ioctl. Similar to the
* struct tm in <time.h>, but it needs to be here so that the kernel
@@ -102,6 +104,7 @@ int rtc_register(rtc_task_t *task);
int rtc_unregister(rtc_task_t *task);
int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
void rtc_get_rtc_time(struct rtc_time *rtc_tm);
+irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
#endif /* __KERNEL__ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b0ad6f30679e..0cfcd1c7865e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -34,6 +34,7 @@
#include <linux/percpu.h>
#include <linux/topology.h>
#include <linux/seccomp.h>
+#include <linux/rcupdate.h>
#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
@@ -104,6 +105,7 @@ extern unsigned long nr_iowait(void);
#include <linux/param.h>
#include <linux/resource.h>
#include <linux/timer.h>
+#include <linux/hrtimer.h>
#include <asm/processor.h>
@@ -158,6 +160,7 @@ extern unsigned long nr_iowait(void);
#define SCHED_NORMAL 0
#define SCHED_FIFO 1
#define SCHED_RR 2
+#define SCHED_BATCH 3
struct sched_param {
int sched_priority;
@@ -254,25 +257,12 @@ extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
* The mm counters are not protected by its page_table_lock,
* so must be incremented atomically.
*/
-#ifdef ATOMIC64_INIT
-#define set_mm_counter(mm, member, value) atomic64_set(&(mm)->_##member, value)
-#define get_mm_counter(mm, member) ((unsigned long)atomic64_read(&(mm)->_##member))
-#define add_mm_counter(mm, member, value) atomic64_add(value, &(mm)->_##member)
-#define inc_mm_counter(mm, member) atomic64_inc(&(mm)->_##member)
-#define dec_mm_counter(mm, member) atomic64_dec(&(mm)->_##member)
-typedef atomic64_t mm_counter_t;
-#else /* !ATOMIC64_INIT */
-/*
- * The counters wrap back to 0 at 2^32 * PAGE_SIZE,
- * that is, at 16TB if using 4kB page size.
- */
-#define set_mm_counter(mm, member, value) atomic_set(&(mm)->_##member, value)
-#define get_mm_counter(mm, member) ((unsigned long)atomic_read(&(mm)->_##member))
-#define add_mm_counter(mm, member, value) atomic_add(value, &(mm)->_##member)
-#define inc_mm_counter(mm, member) atomic_inc(&(mm)->_##member)
-#define dec_mm_counter(mm, member) atomic_dec(&(mm)->_##member)
-typedef atomic_t mm_counter_t;
-#endif /* !ATOMIC64_INIT */
+#define set_mm_counter(mm, member, value) atomic_long_set(&(mm)->_##member, value)
+#define get_mm_counter(mm, member) ((unsigned long)atomic_long_read(&(mm)->_##member))
+#define add_mm_counter(mm, member, value) atomic_long_add(value, &(mm)->_##member)
+#define inc_mm_counter(mm, member) atomic_long_inc(&(mm)->_##member)
+#define dec_mm_counter(mm, member) atomic_long_dec(&(mm)->_##member)
+typedef atomic_long_t mm_counter_t;
#else /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
/*
@@ -363,8 +353,16 @@ struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
+ struct rcu_head rcu;
};
+extern void sighand_free_cb(struct rcu_head *rhp);
+
+static inline void sighand_free(struct sighand_struct *sp)
+{
+ call_rcu(&sp->rcu, sighand_free_cb);
+}
+
/*
* NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always
@@ -402,8 +400,8 @@ struct signal_struct {
struct list_head posix_timers;
/* ITIMER_REAL timer for the process */
- struct timer_list real_timer;
- unsigned long it_real_value, it_real_incr;
+ struct hrtimer real_timer;
+ ktime_t it_real_incr;
/* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
cputime_t it_prof_expires, it_virt_expires;
@@ -473,9 +471,9 @@ struct signal_struct {
/*
* Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL tasks are
- * in the range MAX_RT_PRIO..MAX_PRIO-1. Priority values
- * are inverted: lower p->prio value means higher priority.
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
*
* The MAX_USER_RT_PRIO value allows the actual maximum
* RT priority to be separate from the value exported to
@@ -634,7 +632,14 @@ struct sched_domain {
extern void partition_sched_domains(cpumask_t *partition1,
cpumask_t *partition2);
-#endif /* CONFIG_SMP */
+
+/*
+ * Maximum cache size the migration-costs auto-tuning code will
+ * search from:
+ */
+extern unsigned int max_cache_size;
+
+#endif /* CONFIG_SMP */
struct io_context; /* See blkdev.h */
@@ -692,9 +697,12 @@ struct task_struct {
int lock_depth; /* BKL lock depth */
-#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+#if defined(CONFIG_SMP)
+ int last_waker_cpu; /* CPU that last woke this task up */
+#if defined(__ARCH_WANT_UNLOCKED_CTXSW)
int oncpu;
#endif
+#endif
int prio, static_prio;
struct list_head run_list;
prio_array_t *array;
@@ -775,6 +783,7 @@ struct task_struct {
unsigned keep_capabilities:1;
struct user_struct *user;
#ifdef CONFIG_KEYS
+ struct key *request_key_auth; /* assumed request_key authority */
struct key *thread_keyring; /* keyring private to this thread */
unsigned char jit_keyring; /* default keyring to attach requested keys to */
#endif
@@ -800,6 +809,7 @@ struct task_struct {
struct sighand_struct *sighand;
sigset_t blocked, real_blocked;
+ sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
struct sigpending pending;
unsigned long sas_ss_sp;
@@ -820,6 +830,11 @@ struct task_struct {
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
spinlock_t proc_lock;
+#ifdef CONFIG_DEBUG_MUTEXES
+ /* mutex deadlock detection */
+ struct mutex_waiter *blocked_on;
+#endif
+
/* journalling filesystem info */
void *journal_info;
@@ -857,6 +872,7 @@ struct task_struct {
int cpuset_mems_generation;
#endif
atomic_t fs_excl; /* holding fs exclusive resources */
+ struct rcu_head rcu;
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -880,8 +896,14 @@ static inline int pid_alive(struct task_struct *p)
extern void free_task(struct task_struct *tsk);
extern void __put_task_struct(struct task_struct *tsk);
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
-#define put_task_struct(tsk) \
-do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
+
+extern void __put_task_struct_cb(struct rcu_head *rhp);
+
+static inline void put_task_struct(struct task_struct *t)
+{
+ if (atomic_dec_and_test(&t->usage))
+ call_rcu(&t->rcu, __put_task_struct_cb);
+}
/*
* Per process flags
@@ -908,6 +930,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */
#define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */
#define PF_RANDOMIZE 0x00800000 /* randomize virtual address space */
+#define PF_SWAPWRITE 0x01000000 /* Allowed to write to swap */
/*
* Only the _current_ task can read/write to tsk->flags, but other
@@ -1101,21 +1124,6 @@ static inline int sas_ss_flags(unsigned long sp)
: on_sig_stack(sp) ? SS_ONSTACK : 0);
}
-
-#ifdef CONFIG_SECURITY
-/* code is in security.c */
-extern int capable(int cap);
-#else
-static inline int capable(int cap)
-{
- if (cap_raised(current->cap_effective, cap)) {
- current->flags |= PF_SUPERPRIV;
- return 1;
- }
- return 0;
-}
-#endif
-
/*
* Routines for handling mm_structs
*/
@@ -1234,6 +1242,7 @@ static inline void task_unlock(struct task_struct *p)
#ifndef __HAVE_THREAD_FUNCTIONS
#define task_thread_info(task) (task)->thread_info
+#define task_stack_page(task) ((void*)((task)->thread_info))
static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
{
@@ -1379,12 +1388,8 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
-#ifdef CONFIG_MAGIC_SYSRQ
-
extern void normalize_rt_tasks(void);
-#endif
-
#ifdef CONFIG_PM
/*
* Check if a process has been frozen
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
new file mode 100644
index 000000000000..6336987dae62
--- /dev/null
+++ b/include/linux/screen_info.h
@@ -0,0 +1,76 @@
+#ifndef _SCREEN_INFO_H
+#define _SCREEN_INFO_H
+
+#include <linux/types.h>
+
+/*
+ * These are set up by the setup-routine at boot-time:
+ */
+
+struct screen_info {
+ u8 orig_x; /* 0x00 */
+ u8 orig_y; /* 0x01 */
+ u16 dontuse1; /* 0x02 -- EXT_MEM_K sits here */
+ u16 orig_video_page; /* 0x04 */
+ u8 orig_video_mode; /* 0x06 */
+ u8 orig_video_cols; /* 0x07 */
+ u16 unused2; /* 0x08 */
+ u16 orig_video_ega_bx; /* 0x0a */
+ u16 unused3; /* 0x0c */
+ u8 orig_video_lines; /* 0x0e */
+ u8 orig_video_isVGA; /* 0x0f */
+ u16 orig_video_points; /* 0x10 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ u16 lfb_width; /* 0x12 */
+ u16 lfb_height; /* 0x14 */
+ u16 lfb_depth; /* 0x16 */
+ u32 lfb_base; /* 0x18 */
+ u32 lfb_size; /* 0x1c */
+ u16 dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
+ u16 lfb_linelength; /* 0x24 */
+ u8 red_size; /* 0x26 */
+ u8 red_pos; /* 0x27 */
+ u8 green_size; /* 0x28 */
+ u8 green_pos; /* 0x29 */
+ u8 blue_size; /* 0x2a */
+ u8 blue_pos; /* 0x2b */
+ u8 rsvd_size; /* 0x2c */
+ u8 rsvd_pos; /* 0x2d */
+ u16 vesapm_seg; /* 0x2e */
+ u16 vesapm_off; /* 0x30 */
+ u16 pages; /* 0x32 */
+ u16 vesa_attributes; /* 0x34 */
+ /* 0x36 -- 0x3f reserved for future expansion */
+};
+
+extern struct screen_info screen_info;
+
+#define ORIG_X (screen_info.orig_x)
+#define ORIG_Y (screen_info.orig_y)
+#define ORIG_VIDEO_MODE (screen_info.orig_video_mode)
+#define ORIG_VIDEO_COLS (screen_info.orig_video_cols)
+#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx)
+#define ORIG_VIDEO_LINES (screen_info.orig_video_lines)
+#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA)
+#define ORIG_VIDEO_POINTS (screen_info.orig_video_points)
+
+#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
+#define VIDEO_TYPE_CGA 0x11 /* CGA Display */
+#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */
+#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */
+#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */
+#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
+
+#define VIDEO_TYPE_PICA_S3 0x30 /* ACER PICA-61 local S3 video */
+#define VIDEO_TYPE_MIPS_G364 0x31 /* MIPS Magnum 4000 G364 video */
+#define VIDEO_TYPE_SGI 0x33 /* Various SGI graphics hardware */
+
+#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */
+
+#define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */
+#define VIDEO_TYPE_SUNPCI 0x51 /* Sun PCI based frame buffer. */
+
+#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */
+
+#endif /* _SCREEN_INFO_H */
diff --git a/include/linux/sdla.h b/include/linux/sdla.h
index 3b6afb8caa42..564acd3a71c1 100644
--- a/include/linux/sdla.h
+++ b/include/linux/sdla.h
@@ -293,46 +293,46 @@ void sdla(void *cfg_info, char *dev, struct frad_conf *conf, int quiet);
#define SDLA_S508_INTEN 0x10
struct sdla_cmd {
- char opp_flag __attribute__((packed));
- char cmd __attribute__((packed));
- short length __attribute__((packed));
- char retval __attribute__((packed));
- short dlci __attribute__((packed));
- char flags __attribute__((packed));
- short rxlost_int __attribute__((packed));
- long rxlost_app __attribute__((packed));
- char reserve[2] __attribute__((packed));
- char data[SDLA_MAX_DATA] __attribute__((packed)); /* transfer data buffer */
-};
+ char opp_flag;
+ char cmd;
+ short length;
+ char retval;
+ short dlci;
+ char flags;
+ short rxlost_int;
+ long rxlost_app;
+ char reserve[2];
+ char data[SDLA_MAX_DATA]; /* transfer data buffer */
+} __attribute__((packed));
struct intr_info {
- char flags __attribute__((packed));
- short txlen __attribute__((packed));
- char irq __attribute__((packed));
- char flags2 __attribute__((packed));
- short timeout __attribute__((packed));
-};
+ char flags;
+ short txlen;
+ char irq;
+ char flags2;
+ short timeout;
+} __attribute__((packed));
/* found in the 508's control window at RXBUF_INFO */
struct buf_info {
- unsigned short rse_num __attribute__((packed));
- unsigned long rse_base __attribute__((packed));
- unsigned long rse_next __attribute__((packed));
- unsigned long buf_base __attribute__((packed));
- unsigned short reserved __attribute__((packed));
- unsigned long buf_top __attribute__((packed));
-};
+ unsigned short rse_num;
+ unsigned long rse_base;
+ unsigned long rse_next;
+ unsigned long buf_base;
+ unsigned short reserved;
+ unsigned long buf_top;
+} __attribute__((packed));
/* structure pointed to by rse_base in RXBUF_INFO struct */
struct buf_entry {
- char opp_flag __attribute__((packed));
- short length __attribute__((packed));
- short dlci __attribute__((packed));
- char flags __attribute__((packed));
- short timestamp __attribute__((packed));
- short reserved[2] __attribute__((packed));
- long buf_addr __attribute__((packed));
-};
+ char opp_flag;
+ short length;
+ short dlci;
+ char flags;
+ short timestamp;
+ short reserved[2];
+ long buf_addr;
+} __attribute__((packed));
#endif
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index dc89116bb1ca..cd2773b29a64 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -26,11 +26,7 @@ static inline int has_secure_computing(struct thread_info *ti)
#else /* CONFIG_SECCOMP */
-#if (__GNUC__ > 2)
- typedef struct { } seccomp_t;
-#else
- typedef struct { int gcc_is_buggy; } seccomp_t;
-#endif
+typedef struct { } seccomp_t;
#define secure_computing(x) do { } while (0)
/* static inline to preserve typechecking */
diff --git a/include/linux/security.h b/include/linux/security.h
index f7e0ae018712..ef753654daa5 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -59,6 +59,12 @@ struct sk_buff;
struct sock;
struct sockaddr;
struct socket;
+struct flowi;
+struct dst_entry;
+struct xfrm_selector;
+struct xfrm_policy;
+struct xfrm_state;
+struct xfrm_user_sec_ctx;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb);
@@ -788,6 +794,52 @@ struct swap_info_struct;
* which is used to copy security attributes between local stream sockets.
* @sk_free_security:
* Deallocate security structure.
+ * @sk_getsid:
+ * Retrieve the LSM-specific sid for the sock to enable caching of network
+ * authorizations.
+ *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ * @xp contains the xfrm_policy being added to Security Policy Database
+ * used by the XFRM system.
+ * @sec_ctx contains the security context information being provided by
+ * the user-level policy update program (e.g., setkey).
+ * Allocate a security structure to the xp->selector.security field.
+ * The security field is initialized to NULL when the xfrm_policy is
+ * allocated.
+ * Return 0 if operation was successful (memory to allocate, legal context)
+ * @xfrm_policy_clone_security:
+ * @old contains an existing xfrm_policy in the SPD.
+ * @new contains a new xfrm_policy being cloned from old.
+ * Allocate a security structure to the new->selector.security field
+ * that contains the information from the old->selector.security field.
+ * Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ * @xp contains the xfrm_policy
+ * Deallocate xp->selector.security.
+ * @xfrm_state_alloc_security:
+ * @x contains the xfrm_state being added to the Security Association
+ * Database by the XFRM system.
+ * @sec_ctx contains the security context information being provided by
+ * the user-level SA generation program (e.g., setkey or racoon).
+ * Allocate a security structure to the x->sel.security field. The
+ * security field is initialized to NULL when the xfrm_state is
+ * allocated.
+ * Return 0 if operation was successful (memory to allocate, legal context).
+ * @xfrm_state_free_security:
+ * @x contains the xfrm_state.
+ * Deallocate x>sel.security.
+ * @xfrm_policy_lookup:
+ * @xp contains the xfrm_policy for which the access control is being
+ * checked.
+ * @sk_sid contains the sock security label that is used to authorize
+ * access to the policy xp.
+ * @dir contains the direction of the flow (input or output).
+ * Check permission when a sock selects a xfrm_policy for processing
+ * XFRMs on a packet. The hook is called when selecting either a
+ * per-socket policy or a generic xfrm policy.
+ * Return 0 if permission is granted.
*
* Security hooks affecting all Key Management operations
*
@@ -1237,8 +1289,18 @@ struct security_operations {
int (*socket_getpeersec) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
void (*sk_free_security) (struct sock *sk);
+ unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
+ int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
+ void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+ int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
+ void (*xfrm_state_free_security) (struct xfrm_state *x);
+ int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
/* key management security hooks */
#ifdef CONFIG_KEYS
int (*key_alloc)(struct key *key);
@@ -2679,6 +2741,11 @@ static inline void security_sk_free(struct sock *sk)
{
return security_ops->sk_free_security(sk);
}
+
+static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
+{
+ return security_ops->sk_getsid(sk, fl, dir);
+}
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket * sock,
struct socket * other,
@@ -2795,8 +2862,73 @@ static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
static inline void security_sk_free(struct sock *sk)
{
}
+
+static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+ return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+ security_ops->xfrm_policy_free_security(xp);
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+ security_ops->xfrm_state_free_security(x);
+}
+
+static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+{
+ return security_ops->xfrm_policy_lookup(xp, sk_sid, dir);
+}
+#else /* CONFIG_SECURITY_NETWORK_XFRM */
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return 0;
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+ return 0;
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return 0;
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+}
+
+static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
+
#ifdef CONFIG_KEYS
#ifdef CONFIG_SECURITY
static inline int security_key_alloc(struct key *key)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e3710d7e260a..ec351005bf9d 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -67,6 +67,9 @@
/* Parisc type numbers. */
#define PORT_MUX 48
+/* Atmel AT91RM9200 SoC */
+#define PORT_AT91RM9200 49
+
/* Macintosh Zilog type numbers */
#define PORT_MAC_ZILOG 50 /* m68k : not yet implemented */
#define PORT_PMAC_ZILOG 51
@@ -133,6 +136,7 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/tty.h>
+#include <linux/mutex.h>
struct uart_port;
struct uart_info;
@@ -281,7 +285,7 @@ struct uart_state {
struct uart_info *info;
struct uart_port *port;
- struct semaphore sem;
+ struct mutex mutex;
};
#define UART_XMIT_SIZE PAGE_SIZE
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index c3e598276e78..c057f0b32318 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -26,6 +26,8 @@ struct shmem_sb_info {
unsigned long free_blocks; /* How many are left for allocation */
unsigned long max_inodes; /* How many inodes are allowed */
unsigned long free_inodes; /* How many are left for allocation */
+ int policy; /* Default NUMA memory alloc policy */
+ nodemask_t policy_nodes; /* nodemask for preferred and bind */
spinlock_t stat_lock;
};
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 5dd5f02c5c5f..b7d093520bb6 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -18,6 +18,19 @@
#define SA_PROBE SA_ONESHOT
#define SA_SAMPLE_RANDOM SA_RESTART
#define SA_SHIRQ 0x04000000
+/*
+ * As above, these correspond to the IORESOURCE_IRQ_* defines in
+ * linux/ioport.h to select the interrupt line behaviour. When
+ * requesting an interrupt without specifying a SA_TRIGGER, the
+ * setting should be assumed to be "as already configured", which
+ * may be as per machine or firmware initialisation.
+ */
+#define SA_TRIGGER_LOW 0x00000008
+#define SA_TRIGGER_HIGH 0x00000004
+#define SA_TRIGGER_FALLING 0x00000002
+#define SA_TRIGGER_RISING 0x00000001
+#define SA_TRIGGER_MASK (SA_TRIGGER_HIGH|SA_TRIGGER_LOW|\
+ SA_TRIGGER_RISING|SA_TRIGGER_FALLING)
/*
* Real Time signals may be queued.
@@ -81,6 +94,23 @@ static inline int sigfindinword(unsigned long word)
#endif /* __HAVE_ARCH_SIG_BITOPS */
+static inline int sigisemptyset(sigset_t *set)
+{
+ extern void _NSIG_WORDS_is_unsupported_size(void);
+ switch (_NSIG_WORDS) {
+ case 4:
+ return (set->sig[3] | set->sig[2] |
+ set->sig[1] | set->sig[0]) == 0;
+ case 2:
+ return (set->sig[1] | set->sig[0]) == 0;
+ case 1:
+ return set->sig[0] == 0;
+ default:
+ _NSIG_WORDS_is_unsupported_size();
+ return 0;
+ }
+}
+
#define sigmask(sig) (1UL << ((sig) - 1))
#ifndef __HAVE_ARCH_SIG_SETOPS
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8c5d6001a923..ad7cc22bd424 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -32,7 +32,6 @@
#define HAVE_ALLOC_SKB /* For the drivers to know */
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */
-#define SLAB_SKB /* Slabified skbuffs */
#define CHECKSUM_NONE 0
#define CHECKSUM_HW 1
@@ -134,7 +133,7 @@ struct skb_frag_struct {
*/
struct skb_shared_info {
atomic_t dataref;
- unsigned int nr_frags;
+ unsigned short nr_frags;
unsigned short tso_size;
unsigned short tso_segs;
unsigned short ufo_size;
@@ -252,7 +251,7 @@ struct sk_buff {
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever has the skb queued ATM.
*/
- char cb[40];
+ char cb[48];
unsigned int len,
data_len,
@@ -927,7 +926,7 @@ static inline int skb_tailroom(const struct sk_buff *skb)
* Increase the headroom of an empty &sk_buff by reducing the tail
* room. This is only allowed for an empty buffer.
*/
-static inline void skb_reserve(struct sk_buff *skb, unsigned int len)
+static inline void skb_reserve(struct sk_buff *skb, int len)
{
skb->data += len;
skb->tail += len;
@@ -1239,6 +1238,8 @@ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
int hlen,
struct iovec *iov);
extern void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
+extern void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
+ unsigned int flags);
extern unsigned int skb_checksum(const struct sk_buff *skb, int offset,
int len, unsigned int csum);
extern int skb_copy_bits(const struct sk_buff *skb, int offset,
diff --git a/include/linux/slab.h b/include/linux/slab.h
index d1ea4051b996..1fb77a9cc148 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -53,6 +53,8 @@ typedef struct kmem_cache kmem_cache_t;
#define SLAB_CTOR_ATOMIC 0x002UL /* tell constructor it can't sleep */
#define SLAB_CTOR_VERIFY 0x004UL /* tell constructor it's a verify call */
+#ifndef CONFIG_SLOB
+
/* prototypes */
extern void __init kmem_cache_init(void);
@@ -134,6 +136,39 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
extern int FASTCALL(kmem_cache_reap(int));
extern int FASTCALL(kmem_ptr_validate(kmem_cache_t *cachep, void *ptr));
+#else /* CONFIG_SLOB */
+
+/* SLOB allocator routines */
+
+void kmem_cache_init(void);
+struct kmem_cache *kmem_find_general_cachep(size_t, gfp_t gfpflags);
+struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
+ unsigned long,
+ void (*)(void *, struct kmem_cache *, unsigned long),
+ void (*)(void *, struct kmem_cache *, unsigned long));
+int kmem_cache_destroy(struct kmem_cache *c);
+void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
+void kmem_cache_free(struct kmem_cache *c, void *b);
+const char *kmem_cache_name(struct kmem_cache *);
+void *kmalloc(size_t size, gfp_t flags);
+void *kzalloc(size_t size, gfp_t flags);
+void kfree(const void *m);
+unsigned int ksize(const void *m);
+unsigned int kmem_cache_size(struct kmem_cache *c);
+
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+ return kzalloc(n * size, flags);
+}
+
+#define kmem_cache_shrink(d) (0)
+#define kmem_cache_reap(a)
+#define kmem_ptr_validate(a, b) (0)
+#define kmem_cache_alloc_node(c, f, n) kmem_cache_alloc(c, f)
+#define kmalloc_node(s, f, n) kmalloc(s, f)
+
+#endif /* CONFIG_SLOB */
+
/* System wide caches */
extern kmem_cache_t *vm_area_cachep;
extern kmem_cache_t *names_cachep;
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index c4153120ade6..621a3d3662f3 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -58,53 +58,6 @@ static inline struct smb_inode_info *SMB_I(struct inode *inode)
/* where to find the base of the SMB packet proper */
#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
-#ifdef DEBUG_SMB_MALLOC
-
-#include <linux/slab.h>
-
-extern int smb_malloced;
-extern int smb_current_vmalloced;
-extern int smb_current_kmalloced;
-
-static inline void *
-smb_vmalloc(unsigned int size)
-{
- smb_malloced += 1;
- smb_current_vmalloced += 1;
- return vmalloc(size);
-}
-
-static inline void
-smb_vfree(void *obj)
-{
- smb_current_vmalloced -= 1;
- vfree(obj);
-}
-
-static inline void *
-smb_kmalloc(size_t size, int flags)
-{
- smb_malloced += 1;
- smb_current_kmalloced += 1;
- return kmalloc(size, flags);
-}
-
-static inline void
-smb_kfree(void *obj)
-{
- smb_current_kmalloced -= 1;
- kfree(obj);
-}
-
-#else /* DEBUG_SMB_MALLOC */
-
-#define smb_kmalloc(s,p) kmalloc(s,p)
-#define smb_kfree(o) kfree(o)
-#define smb_vmalloc(s) vmalloc(s)
-#define smb_vfree(o) vfree(o)
-
-#endif /* DEBUG_SMB_MALLOC */
-
/*
* Flags for the in-memory inode
*/
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 1739c2d5b95b..b02dda4ee83d 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -27,7 +27,6 @@ struct __kernel_sockaddr_storage {
#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);
@@ -187,6 +186,7 @@ struct ucred {
#define AF_PPPOX 24 /* PPPoX sockets */
#define AF_WANPIPE 25 /* Wanpipe API Sockets */
#define AF_LLC 26 /* Linux LLC */
+#define AF_TIPC 30 /* TIPC sockets */
#define AF_BLUETOOTH 31 /* Bluetooth sockets */
#define AF_MAX 32 /* For now.. */
@@ -219,6 +219,7 @@ struct ucred {
#define PF_PPPOX AF_PPPOX
#define PF_WANPIPE AF_WANPIPE
#define PF_LLC AF_LLC
+#define PF_TIPC AF_TIPC
#define PF_BLUETOOTH AF_BLUETOOTH
#define PF_MAX AF_MAX
@@ -280,6 +281,7 @@ struct ucred {
#define SOL_LLC 268
#define SOL_DCCP 269
#define SOL_NETLINK 270
+#define SOL_TIPC 271
/* IPX options */
#define IPX_TYPE 1
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
new file mode 100644
index 000000000000..72261e0f2ac1
--- /dev/null
+++ b/include/linux/spi/ads7846.h
@@ -0,0 +1,18 @@
+/* linux/spi/ads7846.h */
+
+/* Touchscreen characteristics vary between boards and models. The
+ * platform_data for the device's "struct device" holds this information.
+ *
+ * It's OK if the min/max values are zero.
+ */
+struct ads7846_platform_data {
+ u16 model; /* 7843, 7845, 7846. */
+ u16 vref_delay_usecs; /* 0 for external vref; etc */
+ u16 x_plate_ohms;
+ u16 y_plate_ohms;
+
+ u16 x_min, x_max;
+ u16 y_min, y_max;
+ u16 pressure_min, pressure_max;
+};
+
diff --git a/include/linux/spi/flash.h b/include/linux/spi/flash.h
new file mode 100644
index 000000000000..3f22932e67a4
--- /dev/null
+++ b/include/linux/spi/flash.h
@@ -0,0 +1,31 @@
+#ifndef LINUX_SPI_FLASH_H
+#define LINUX_SPI_FLASH_H
+
+struct mtd_partition;
+
+/**
+ * struct flash_platform_data: board-specific flash data
+ * @name: optional flash device name (eg, as used with mtdparts=)
+ * @parts: optional array of mtd_partitions for static partitioning
+ * @nr_parts: number of mtd_partitions for static partitoning
+ * @type: optional flash device type (e.g. m25p80 vs m25p64), for use
+ * with chips that can't be queried for JEDEC or other IDs
+ *
+ * Board init code (in arch/.../mach-xxx/board-yyy.c files) can
+ * provide information about SPI flash parts (such as DataFlash) to
+ * help set up the device and its appropriate default partitioning.
+ *
+ * Note that for DataFlash, sizes for pages, blocks, and sectors are
+ * rarely powers of two; and partitions should be sector-aligned.
+ */
+struct flash_platform_data {
+ char *name;
+ struct mtd_partition *parts;
+ unsigned int nr_parts;
+
+ char *type;
+
+ /* we'll likely add more ... use JEDEC IDs, etc */
+};
+
+#endif
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
new file mode 100644
index 000000000000..b05f1463a267
--- /dev/null
+++ b/include/linux/spi/spi.h
@@ -0,0 +1,668 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public 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_SPI_H
+#define __LINUX_SPI_H
+
+/*
+ * INTERFACES between SPI master-side drivers and SPI infrastructure.
+ * (There's no SPI slave support for Linux yet...)
+ */
+extern struct bus_type spi_bus_type;
+
+/**
+ * struct spi_device - Master side proxy for an SPI slave device
+ * @dev: Driver model representation of the device.
+ * @master: SPI controller used with the device.
+ * @max_speed_hz: Maximum clock rate to be used with this chip
+ * (on this board); may be changed by the device's driver.
+ * @chip-select: Chipselect, distinguishing chips handled by "master".
+ * @mode: The spi mode defines how data is clocked out and in.
+ * This may be changed by the device's driver.
+ * @bits_per_word: Data transfers involve one or more words; word sizes
+ * like eight or 12 bits are common. In-memory wordsizes are
+ * powers of two bytes (e.g. 20 bit samples use 32 bits).
+ * This may be changed by the device's driver.
+ * @irq: Negative, or the number passed to request_irq() to receive
+ * interrupts from this device.
+ * @controller_state: Controller's runtime state
+ * @controller_data: Board-specific definitions for controller, such as
+ * FIFO initialization parameters; from board_info.controller_data
+ *
+ * An spi_device is used to interchange data between an SPI slave
+ * (usually a discrete chip) and CPU memory.
+ *
+ * In "dev", the platform_data is used to hold information about this
+ * device that's meaningful to the device's protocol driver, but not
+ * to its controller. One example might be an identifier for a chip
+ * variant with slightly different functionality.
+ */
+struct spi_device {
+ struct device dev;
+ struct spi_master *master;
+ u32 max_speed_hz;
+ u8 chip_select;
+ u8 mode;
+#define SPI_CPHA 0x01 /* clock phase */
+#define SPI_CPOL 0x02 /* clock polarity */
+#define SPI_MODE_0 (0|0) /* (original MicroWire) */
+#define SPI_MODE_1 (0|SPI_CPHA)
+#define SPI_MODE_2 (SPI_CPOL|0)
+#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
+#define SPI_CS_HIGH 0x04 /* chipselect active high? */
+ u8 bits_per_word;
+ int irq;
+ void *controller_state;
+ void *controller_data;
+ const char *modalias;
+
+ // likely need more hooks for more protocol options affecting how
+ // the controller talks to each chip, like:
+ // - bit order (default is wordwise msb-first)
+ // - memory packing (12 bit samples into low bits, others zeroed)
+ // - priority
+ // - drop chipselect after each word
+ // - chipselect delays
+ // - ...
+};
+
+static inline struct spi_device *to_spi_device(struct device *dev)
+{
+ return dev ? container_of(dev, struct spi_device, dev) : NULL;
+}
+
+/* most drivers won't need to care about device refcounting */
+static inline struct spi_device *spi_dev_get(struct spi_device *spi)
+{
+ return (spi && get_device(&spi->dev)) ? spi : NULL;
+}
+
+static inline void spi_dev_put(struct spi_device *spi)
+{
+ if (spi)
+ put_device(&spi->dev);
+}
+
+/* ctldata is for the bus_master driver's runtime state */
+static inline void *spi_get_ctldata(struct spi_device *spi)
+{
+ return spi->controller_state;
+}
+
+static inline void spi_set_ctldata(struct spi_device *spi, void *state)
+{
+ spi->controller_state = state;
+}
+
+
+struct spi_message;
+
+
+
+struct spi_driver {
+ int (*probe)(struct spi_device *spi);
+ int (*remove)(struct spi_device *spi);
+ void (*shutdown)(struct spi_device *spi);
+ int (*suspend)(struct spi_device *spi, pm_message_t mesg);
+ int (*resume)(struct spi_device *spi);
+ struct device_driver driver;
+};
+
+static inline struct spi_driver *to_spi_driver(struct device_driver *drv)
+{
+ return drv ? container_of(drv, struct spi_driver, driver) : NULL;
+}
+
+extern int spi_register_driver(struct spi_driver *sdrv);
+
+static inline void spi_unregister_driver(struct spi_driver *sdrv)
+{
+ if (!sdrv)
+ return;
+ driver_unregister(&sdrv->driver);
+}
+
+
+
+/**
+ * struct spi_master - interface to SPI master controller
+ * @cdev: class interface to this driver
+ * @bus_num: board-specific (and often SOC-specific) identifier for a
+ * given SPI controller.
+ * @num_chipselect: chipselects are used to distinguish individual
+ * SPI slaves, and are numbered from zero to num_chipselects.
+ * each slave has a chipselect signal, but it's common that not
+ * every chipselect is connected to a slave.
+ * @setup: updates the device mode and clocking records used by a
+ * device's SPI controller; protocol code may call this.
+ * @transfer: adds a message to the controller's transfer queue.
+ * @cleanup: frees controller-specific state
+ *
+ * Each SPI master controller can communicate with one or more spi_device
+ * children. These make a small bus, sharing MOSI, MISO and SCK signals
+ * but not chip select signals. Each device may be configured to use a
+ * different clock rate, since those shared signals are ignored unless
+ * the chip is selected.
+ *
+ * The driver for an SPI controller manages access to those devices through
+ * a queue of spi_message transactions, copyin data between CPU memory and
+ * an SPI slave device). For each such message it queues, it calls the
+ * message's completion function when the transaction completes.
+ */
+struct spi_master {
+ struct class_device cdev;
+
+ /* other than zero (== assign one dynamically), bus_num is fully
+ * board-specific. usually that simplifies to being SOC-specific.
+ * example: one SOC has three SPI controllers, numbered 1..3,
+ * and one board's schematics might show it using SPI-2. software
+ * would normally use bus_num=2 for that controller.
+ */
+ u16 bus_num;
+
+ /* chipselects will be integral to many controllers; some others
+ * might use board-specific GPIOs.
+ */
+ u16 num_chipselect;
+
+ /* setup mode and clock, etc (spi driver may call many times) */
+ int (*setup)(struct spi_device *spi);
+
+ /* bidirectional bulk transfers
+ *
+ * + The transfer() method may not sleep; its main role is
+ * just to add the message to the queue.
+ * + For now there's no remove-from-queue operation, or
+ * any other request management
+ * + To a given spi_device, message queueing is pure fifo
+ *
+ * + The master's main job is to process its message queue,
+ * selecting a chip then transferring data
+ * + If there are multiple spi_device children, the i/o queue
+ * arbitration algorithm is unspecified (round robin, fifo,
+ * priority, reservations, preemption, etc)
+ *
+ * + Chipselect stays active during the entire message
+ * (unless modified by spi_transfer.cs_change != 0).
+ * + The message transfers use clock and SPI mode parameters
+ * previously established by setup() for this device
+ */
+ int (*transfer)(struct spi_device *spi,
+ struct spi_message *mesg);
+
+ /* called on release() to free memory provided by spi_master */
+ void (*cleanup)(const struct spi_device *spi);
+};
+
+static inline void *spi_master_get_devdata(struct spi_master *master)
+{
+ return class_get_devdata(&master->cdev);
+}
+
+static inline void spi_master_set_devdata(struct spi_master *master, void *data)
+{
+ class_set_devdata(&master->cdev, data);
+}
+
+static inline struct spi_master *spi_master_get(struct spi_master *master)
+{
+ if (!master || !class_device_get(&master->cdev))
+ return NULL;
+ return master;
+}
+
+static inline void spi_master_put(struct spi_master *master)
+{
+ if (master)
+ class_device_put(&master->cdev);
+}
+
+
+/* the spi driver core manages memory for the spi_master classdev */
+extern struct spi_master *
+spi_alloc_master(struct device *host, unsigned size);
+
+extern int spi_register_master(struct spi_master *master);
+extern void spi_unregister_master(struct spi_master *master);
+
+extern struct spi_master *spi_busnum_to_master(u16 busnum);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * I/O INTERFACE between SPI controller and protocol drivers
+ *
+ * Protocol drivers use a queue of spi_messages, each transferring data
+ * between the controller and memory buffers.
+ *
+ * The spi_messages themselves consist of a series of read+write transfer
+ * segments. Those segments always read the same number of bits as they
+ * write; but one or the other is easily ignored by passing a null buffer
+ * pointer. (This is unlike most types of I/O API, because SPI hardware
+ * is full duplex.)
+ *
+ * NOTE: Allocation of spi_transfer and spi_message memory is entirely
+ * up to the protocol driver, which guarantees the integrity of both (as
+ * well as the data buffers) for as long as the message is queued.
+ */
+
+/**
+ * struct spi_transfer - a read/write buffer pair
+ * @tx_buf: data to be written (dma-safe memory), or NULL
+ * @rx_buf: data to be read (dma-safe memory), or NULL
+ * @tx_dma: DMA address of tx_buf, if spi_message.is_dma_mapped
+ * @rx_dma: DMA address of rx_buf, if spi_message.is_dma_mapped
+ * @len: size of rx and tx buffers (in bytes)
+ * @cs_change: affects chipselect after this transfer completes
+ * @delay_usecs: microseconds to delay after this transfer before
+ * (optionally) changing the chipselect status, then starting
+ * the next transfer or completing this spi_message.
+ * @transfer_list: transfers are sequenced through spi_message.transfers
+ *
+ * SPI transfers always write the same number of bytes as they read.
+ * Protocol drivers should always provide rx_buf and/or tx_buf.
+ * In some cases, they may also want to provide DMA addresses for
+ * the data being transferred; that may reduce overhead, when the
+ * underlying driver uses dma.
+ *
+ * If the transmit buffer is null, undefined data will be shifted out
+ * while filling rx_buf. If the receive buffer is null, the data
+ * shifted in will be discarded. Only "len" bytes shift out (or in).
+ * It's an error to try to shift out a partial word. (For example, by
+ * shifting out three bytes with word size of sixteen or twenty bits;
+ * the former uses two bytes per word, the latter uses four bytes.)
+ *
+ * All SPI transfers start with the relevant chipselect active. Normally
+ * it stays selected until after the last transfer in a message. Drivers
+ * can affect the chipselect signal using cs_change:
+ *
+ * (i) If the transfer isn't the last one in the message, this flag is
+ * used to make the chipselect briefly go inactive in the middle of the
+ * message. Toggling chipselect in this way may be needed to terminate
+ * a chip command, letting a single spi_message perform all of group of
+ * chip transactions together.
+ *
+ * (ii) When the transfer is the last one in the message, the chip may
+ * stay selected until the next transfer. This is purely a performance
+ * hint; the controller driver may need to select a different device
+ * for the next message.
+ *
+ * The code that submits an spi_message (and its spi_transfers)
+ * to the lower layers is responsible for managing its memory.
+ * Zero-initialize every field you don't set up explicitly, to
+ * insulate against future API updates. After you submit a message
+ * and its transfers, ignore them until its completion callback.
+ */
+struct spi_transfer {
+ /* it's ok if tx_buf == rx_buf (right?)
+ * for MicroWire, one buffer must be null
+ * buffers must work with dma_*map_single() calls, unless
+ * spi_message.is_dma_mapped reports a pre-existing mapping
+ */
+ const void *tx_buf;
+ void *rx_buf;
+ unsigned len;
+
+ dma_addr_t tx_dma;
+ dma_addr_t rx_dma;
+
+ unsigned cs_change:1;
+ u16 delay_usecs;
+
+ struct list_head transfer_list;
+};
+
+/**
+ * struct spi_message - one multi-segment SPI transaction
+ * @transfers: list of transfer segments in this transaction
+ * @spi: SPI device to which the transaction is queued
+ * @is_dma_mapped: if true, the caller provided both dma and cpu virtual
+ * addresses for each transfer buffer
+ * @complete: called to report transaction completions
+ * @context: the argument to complete() when it's called
+ * @actual_length: the total number of bytes that were transferred in all
+ * successful segments
+ * @status: zero for success, else negative errno
+ * @queue: for use by whichever driver currently owns the message
+ * @state: for use by whichever driver currently owns the message
+ *
+ * An spi_message is used to execute an atomic sequence of data transfers,
+ * each represented by a struct spi_transfer. The sequence is "atomic"
+ * in the sense that no other spi_message may use that SPI bus until that
+ * sequence completes. On some systems, many such sequences can execute as
+ * as single programmed DMA transfer. On all systems, these messages are
+ * queued, and might complete after transactions to other devices. Messages
+ * sent to a given spi_device are alway executed in FIFO order.
+ *
+ * The code that submits an spi_message (and its spi_transfers)
+ * to the lower layers is responsible for managing its memory.
+ * Zero-initialize every field you don't set up explicitly, to
+ * insulate against future API updates. After you submit a message
+ * and its transfers, ignore them until its completion callback.
+ */
+struct spi_message {
+ struct list_head transfers;
+
+ struct spi_device *spi;
+
+ unsigned is_dma_mapped:1;
+
+ /* REVISIT: we might want a flag affecting the behavior of the
+ * last transfer ... allowing things like "read 16 bit length L"
+ * immediately followed by "read L bytes". Basically imposing
+ * a specific message scheduling algorithm.
+ *
+ * Some controller drivers (message-at-a-time queue processing)
+ * could provide that as their default scheduling algorithm. But
+ * others (with multi-message pipelines) could need a flag to
+ * tell them about such special cases.
+ */
+
+ /* completion is reported through a callback */
+ void (*complete)(void *context);
+ void *context;
+ unsigned actual_length;
+ int status;
+
+ /* for optional use by whatever driver currently owns the
+ * spi_message ... between calls to spi_async and then later
+ * complete(), that's the spi_master controller driver.
+ */
+ struct list_head queue;
+ void *state;
+};
+
+static inline void spi_message_init(struct spi_message *m)
+{
+ memset(m, 0, sizeof *m);
+ INIT_LIST_HEAD(&m->transfers);
+}
+
+static inline void
+spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
+{
+ list_add_tail(&t->transfer_list, &m->transfers);
+}
+
+static inline void
+spi_transfer_del(struct spi_transfer *t)
+{
+ list_del(&t->transfer_list);
+}
+
+/* It's fine to embed message and transaction structures in other data
+ * structures so long as you don't free them while they're in use.
+ */
+
+static inline struct spi_message *spi_message_alloc(unsigned ntrans, gfp_t flags)
+{
+ struct spi_message *m;
+
+ m = kzalloc(sizeof(struct spi_message)
+ + ntrans * sizeof(struct spi_transfer),
+ flags);
+ if (m) {
+ int i;
+ struct spi_transfer *t = (struct spi_transfer *)(m + 1);
+
+ INIT_LIST_HEAD(&m->transfers);
+ for (i = 0; i < ntrans; i++, t++)
+ spi_message_add_tail(t, m);
+ }
+ return m;
+}
+
+static inline void spi_message_free(struct spi_message *m)
+{
+ kfree(m);
+}
+
+/**
+ * spi_setup -- setup SPI mode and clock rate
+ * @spi: the device whose settings are being modified
+ *
+ * SPI protocol drivers may need to update the transfer mode if the
+ * device doesn't work with the mode 0 default. They may likewise need
+ * to update clock rates or word sizes from initial values. This function
+ * changes those settings, and must be called from a context that can sleep.
+ * The changes take effect the next time the device is selected and data
+ * is transferred to or from it.
+ */
+static inline int
+spi_setup(struct spi_device *spi)
+{
+ return spi->master->setup(spi);
+}
+
+
+/**
+ * spi_async -- asynchronous SPI transfer
+ * @spi: device with which data will be exchanged
+ * @message: describes the data transfers, including completion callback
+ *
+ * This call may be used in_irq and other contexts which can't sleep,
+ * as well as from task contexts which can sleep.
+ *
+ * The completion callback is invoked in a context which can't sleep.
+ * Before that invocation, the value of message->status is undefined.
+ * When the callback is issued, message->status holds either zero (to
+ * indicate complete success) or a negative error code. After that
+ * callback returns, the driver which issued the transfer request may
+ * deallocate the associated memory; it's no longer in use by any SPI
+ * core or controller driver code.
+ *
+ * Note that although all messages to a spi_device are handled in
+ * FIFO order, messages may go to different devices in other orders.
+ * Some device might be higher priority, or have various "hard" access
+ * time requirements, for example.
+ *
+ * On detection of any fault during the transfer, processing of
+ * the entire message is aborted, and the device is deselected.
+ * Until returning from the associated message completion callback,
+ * no other spi_message queued to that device will be processed.
+ * (This rule applies equally to all the synchronous transfer calls,
+ * which are wrappers around this core asynchronous primitive.)
+ */
+static inline int
+spi_async(struct spi_device *spi, struct spi_message *message)
+{
+ message->spi = spi;
+ return spi->master->transfer(spi, message);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/* All these synchronous SPI transfer routines are utilities layered
+ * over the core async transfer primitive. Here, "synchronous" means
+ * they will sleep uninterruptibly until the async transfer completes.
+ */
+
+extern int spi_sync(struct spi_device *spi, struct spi_message *message);
+
+/**
+ * spi_write - SPI synchronous write
+ * @spi: device to which data will be written
+ * @buf: data buffer
+ * @len: data buffer size
+ *
+ * This writes the buffer and returns zero or a negative error code.
+ * Callable only from contexts that can sleep.
+ */
+static inline int
+spi_write(struct spi_device *spi, const u8 *buf, size_t len)
+{
+ struct spi_transfer t = {
+ .tx_buf = buf,
+ .len = len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ return spi_sync(spi, &m);
+}
+
+/**
+ * spi_read - SPI synchronous read
+ * @spi: device from which data will be read
+ * @buf: data buffer
+ * @len: data buffer size
+ *
+ * This writes the buffer and returns zero or a negative error code.
+ * Callable only from contexts that can sleep.
+ */
+static inline int
+spi_read(struct spi_device *spi, u8 *buf, size_t len)
+{
+ struct spi_transfer t = {
+ .rx_buf = buf,
+ .len = len,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ return spi_sync(spi, &m);
+}
+
+/* this copies txbuf and rxbuf data; for small transfers only! */
+extern int spi_write_then_read(struct spi_device *spi,
+ const u8 *txbuf, unsigned n_tx,
+ u8 *rxbuf, unsigned n_rx);
+
+/**
+ * spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read
+ * @spi: device with which data will be exchanged
+ * @cmd: command to be written before data is read back
+ *
+ * This returns the (unsigned) eight bit number returned by the
+ * device, or else a negative error code. Callable only from
+ * contexts that can sleep.
+ */
+static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
+{
+ ssize_t status;
+ u8 result;
+
+ status = spi_write_then_read(spi, &cmd, 1, &result, 1);
+
+ /* return negative errno or unsigned value */
+ return (status < 0) ? status : result;
+}
+
+/**
+ * spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read
+ * @spi: device with which data will be exchanged
+ * @cmd: command to be written before data is read back
+ *
+ * This returns the (unsigned) sixteen bit number returned by the
+ * device, or else a negative error code. Callable only from
+ * contexts that can sleep.
+ *
+ * The number is returned in wire-order, which is at least sometimes
+ * big-endian.
+ */
+static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
+{
+ ssize_t status;
+ u16 result;
+
+ status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
+
+ /* return negative errno or unsigned value */
+ return (status < 0) ? status : result;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * INTERFACE between board init code and SPI infrastructure.
+ *
+ * No SPI driver ever sees these SPI device table segments, but
+ * it's how the SPI core (or adapters that get hotplugged) grows
+ * the driver model tree.
+ *
+ * As a rule, SPI devices can't be probed. Instead, board init code
+ * provides a table listing the devices which are present, with enough
+ * information to bind and set up the device's driver. There's basic
+ * support for nonstatic configurations too; enough to handle adding
+ * parport adapters, or microcontrollers acting as USB-to-SPI bridges.
+ */
+
+/* board-specific information about each SPI device */
+struct spi_board_info {
+ /* the device name and module name are coupled, like platform_bus;
+ * "modalias" is normally the driver name.
+ *
+ * platform_data goes to spi_device.dev.platform_data,
+ * controller_data goes to spi_device.controller_data,
+ * irq is copied too
+ */
+ char modalias[KOBJ_NAME_LEN];
+ const void *platform_data;
+ void *controller_data;
+ int irq;
+
+ /* slower signaling on noisy or low voltage boards */
+ u32 max_speed_hz;
+
+
+ /* bus_num is board specific and matches the bus_num of some
+ * spi_master that will probably be registered later.
+ *
+ * chip_select reflects how this chip is wired to that master;
+ * it's less than num_chipselect.
+ */
+ u16 bus_num;
+ u16 chip_select;
+
+ /* ... may need additional spi_device chip config data here.
+ * avoid stuff protocol drivers can set; but include stuff
+ * needed to behave without being bound to a driver:
+ * - chipselect polarity
+ * - quirks like clock rate mattering when not selected
+ */
+};
+
+#ifdef CONFIG_SPI
+extern int
+spi_register_board_info(struct spi_board_info const *info, unsigned n);
+#else
+/* board init code may ignore whether SPI is configured or not */
+static inline int
+spi_register_board_info(struct spi_board_info const *info, unsigned n)
+ { return 0; }
+#endif
+
+
+/* If you're hotplugging an adapter with devices (parport, usb, etc)
+ * use spi_new_device() to describe each device. You can also call
+ * spi_unregister_device() to start making that device vanish, but
+ * normally that would be handled by spi_unregister_master().
+ */
+extern struct spi_device *
+spi_new_device(struct spi_master *, struct spi_board_info *);
+
+static inline void
+spi_unregister_device(struct spi_device *spi)
+{
+ if (spi)
+ device_unregister(&spi->dev);
+}
+
+#endif /* __LINUX_SPI_H */
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
new file mode 100644
index 000000000000..c961fe9bf3eb
--- /dev/null
+++ b/include/linux/spi/spi_bitbang.h
@@ -0,0 +1,135 @@
+#ifndef __SPI_BITBANG_H
+#define __SPI_BITBANG_H
+
+/*
+ * Mix this utility code with some glue code to get one of several types of
+ * simple SPI master driver. Two do polled word-at-a-time I/O:
+ *
+ * - GPIO/parport bitbangers. Provide chipselect() and txrx_word[](),
+ * expanding the per-word routines from the inline templates below.
+ *
+ * - Drivers for controllers resembling bare shift registers. Provide
+ * chipselect() and txrx_word[](), with custom setup()/cleanup() methods
+ * that use your controller's clock and chipselect registers.
+ *
+ * Some hardware works well with requests at spi_transfer scope:
+ *
+ * - Drivers leveraging smarter hardware, with fifos or DMA; or for half
+ * duplex (MicroWire) controllers. Provide chipslect() and txrx_bufs(),
+ * and custom setup()/cleanup() methods.
+ */
+struct spi_bitbang {
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+
+ spinlock_t lock;
+ struct list_head queue;
+ u8 busy;
+ u8 shutdown;
+ u8 use_dma;
+
+ struct spi_master *master;
+
+ void (*chipselect)(struct spi_device *spi, int is_on);
+#define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */
+#define BITBANG_CS_INACTIVE 0
+
+ /* txrx_bufs() may handle dma mapping for transfers that don't
+ * already have one (transfer.{tx,rx}_dma is zero), or use PIO
+ */
+ int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
+
+ /* txrx_word[SPI_MODE_*]() just looks like a shift register */
+ u32 (*txrx_word[4])(struct spi_device *spi,
+ unsigned nsecs,
+ u32 word, u8 bits);
+};
+
+/* you can call these default bitbang->master methods from your custom
+ * methods, if you like.
+ */
+extern int spi_bitbang_setup(struct spi_device *spi);
+extern void spi_bitbang_cleanup(const struct spi_device *spi);
+extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
+
+/* start or stop queue processing */
+extern int spi_bitbang_start(struct spi_bitbang *spi);
+extern int spi_bitbang_stop(struct spi_bitbang *spi);
+
+#endif /* __SPI_BITBANG_H */
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef EXPAND_BITBANG_TXRX
+
+/*
+ * The code that knows what GPIO pins do what should have declared four
+ * functions, ideally as inlines, before #defining EXPAND_BITBANG_TXRX
+ * and including this header:
+ *
+ * void setsck(struct spi_device *, int is_on);
+ * void setmosi(struct spi_device *, int is_on);
+ * int getmiso(struct spi_device *);
+ * void spidelay(unsigned);
+ *
+ * A non-inlined routine would call bitbang_txrx_*() routines. The
+ * main loop could easily compile down to a handful of instructions,
+ * especially if the delay is a NOP (to run at peak speed).
+ *
+ * Since this is software, the timings may not be exactly what your board's
+ * chips need ... there may be several reasons you'd need to tweak timings
+ * in these routines, not just make to make it faster or slower to match a
+ * particular CPU clock rate.
+ */
+
+static inline u32
+bitbang_txrx_be_cpha0(struct spi_device *spi,
+ unsigned nsecs, unsigned cpol,
+ u32 word, u8 bits)
+{
+ /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
+
+ /* clock starts at inactive polarity */
+ for (word <<= (32 - bits); likely(bits); bits--) {
+
+ /* setup MSB (to slave) on trailing edge */
+ setmosi(spi, word & (1 << 31));
+ spidelay(nsecs); /* T(setup) */
+
+ setsck(spi, !cpol);
+ spidelay(nsecs);
+
+ /* sample MSB (from slave) on leading edge */
+ word <<= 1;
+ word |= getmiso(spi);
+ setsck(spi, cpol);
+ }
+ return word;
+}
+
+static inline u32
+bitbang_txrx_be_cpha1(struct spi_device *spi,
+ unsigned nsecs, unsigned cpol,
+ u32 word, u8 bits)
+{
+ /* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */
+
+ /* clock starts at inactive polarity */
+ for (word <<= (32 - bits); likely(bits); bits--) {
+
+ /* setup MSB (to slave) on leading edge */
+ setsck(spi, !cpol);
+ setmosi(spi, word & (1 << 31));
+ spidelay(nsecs); /* T(setup) */
+
+ setsck(spi, cpol);
+ spidelay(nsecs);
+
+ /* sample MSB (from slave) on trailing edge */
+ word <<= 1;
+ word |= getmiso(spi);
+ }
+ return word;
+}
+
+#endif /* EXPAND_BITBANG_TXRX */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 0e9682c9def5..799be6747944 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -59,8 +59,7 @@
/*
* Must define these before including other files, inline functions need them
*/
-#define LOCK_SECTION_NAME \
- ".text.lock." __stringify(KBUILD_BASENAME)
+#define LOCK_SECTION_NAME ".text.lock."KBUILD_BASENAME
#define LOCK_SECTION_START(extra) \
".subsection 1\n\t" \
diff --git a/include/linux/spinlock_types_up.h b/include/linux/spinlock_types_up.h
index def2d173a8db..04135b0e198e 100644
--- a/include/linux/spinlock_types_up.h
+++ b/include/linux/spinlock_types_up.h
@@ -22,30 +22,16 @@ typedef struct {
#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/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ab151bbb66df..f147e6b84332 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -49,7 +49,6 @@ struct rpc_clnt {
unsigned int cl_softrtry : 1,/* soft timeouts */
cl_intr : 1,/* interruptible */
- cl_chatty : 1,/* be verbose */
cl_autobind : 1,/* use getport() */
cl_oneshot : 1,/* dispose after use */
cl_dead : 1;/* abandoned */
@@ -126,7 +125,8 @@ int rpc_register(u32, u32, int, unsigned short, int *);
void rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
- int flags, rpc_action callback, void *clntdata);
+ int flags, const struct rpc_call_ops *tk_ops,
+ void *calldata);
int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
int flags);
void rpc_restart_call(struct rpc_task *);
@@ -134,6 +134,7 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
size_t rpc_max_payload(struct rpc_clnt *);
+void rpc_force_rebind(struct rpc_clnt *);
int rpc_ping(struct rpc_clnt *clnt, int flags);
static __inline__
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
index 0beb2cf00a84..336e218c2782 100644
--- a/include/linux/sunrpc/gss_spkm3.h
+++ b/include/linux/sunrpc/gss_spkm3.h
@@ -48,7 +48,7 @@ u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struc
#define CKSUMTYPE_RSA_MD5 0x0007
s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
- struct xdr_netobj *cksum);
+ int body_offset, struct xdr_netobj *cksum);
void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen,
int explen);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 4d77e90d0b30..8b25629accd8 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -27,6 +27,7 @@ struct rpc_message {
struct rpc_cred * rpc_cred; /* Credentials */
};
+struct rpc_call_ops;
struct rpc_wait_queue;
struct rpc_wait {
struct list_head list; /* wait queue links */
@@ -41,6 +42,7 @@ struct rpc_task {
#ifdef RPC_DEBUG
unsigned long tk_magic; /* 0xf00baa */
#endif
+ atomic_t tk_count; /* Reference count */
struct list_head tk_task; /* global list of tasks */
struct rpc_clnt * tk_client; /* RPC client */
struct rpc_rqst * tk_rqstp; /* RPC request */
@@ -50,8 +52,6 @@ struct rpc_task {
* RPC call state
*/
struct rpc_message tk_msg; /* RPC call info */
- __u32 * tk_buffer; /* XDR buffer */
- size_t tk_bufsize;
__u8 tk_garb_retry;
__u8 tk_cred_retry;
@@ -61,13 +61,12 @@ struct rpc_task {
* timeout_fn to be executed by timer bottom half
* callback to be executed after waking up
* action next procedure for async tasks
- * exit exit async task and report to caller
+ * tk_ops caller callbacks
*/
void (*tk_timeout_fn)(struct rpc_task *);
void (*tk_callback)(struct rpc_task *);
void (*tk_action)(struct rpc_task *);
- void (*tk_exit)(struct rpc_task *);
- void (*tk_release)(struct rpc_task *);
+ const struct rpc_call_ops *tk_ops;
void * tk_calldata;
/*
@@ -78,7 +77,6 @@ struct rpc_task {
struct timer_list tk_timer; /* kernel timer */
unsigned long tk_timeout; /* timeout for rpc_sleep() */
unsigned short tk_flags; /* misc flags */
- unsigned char tk_active : 1;/* Task has been activated */
unsigned char tk_priority : 2;/* Task priority */
unsigned long tk_runstate; /* Task run status */
struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could
@@ -111,6 +109,13 @@ struct rpc_task {
typedef void (*rpc_action)(struct rpc_task *);
+struct rpc_call_ops {
+ void (*rpc_call_prepare)(struct rpc_task *, void *);
+ void (*rpc_call_done)(struct rpc_task *, void *);
+ void (*rpc_release)(void *);
+};
+
+
/*
* RPC task flags
*/
@@ -129,7 +134,6 @@ typedef void (*rpc_action)(struct rpc_task *);
#define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER)
#define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
#define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED)
-#define RPC_IS_ACTIVATED(t) ((t)->tk_active)
#define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL)
#define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT)
#define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR)
@@ -138,6 +142,7 @@ typedef void (*rpc_action)(struct rpc_task *);
#define RPC_TASK_QUEUED 1
#define RPC_TASK_WAKEUP 2
#define RPC_TASK_HAS_TIMER 3
+#define RPC_TASK_ACTIVE 4
#define RPC_IS_RUNNING(t) (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
#define rpc_set_running(t) (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate))
@@ -168,6 +173,15 @@ typedef void (*rpc_action)(struct rpc_task *);
smp_mb__after_clear_bit(); \
} while (0)
+#define RPC_IS_ACTIVATED(t) (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
+#define rpc_set_active(t) (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate))
+#define rpc_clear_active(t) \
+ do { \
+ smp_mb__before_clear_bit(); \
+ clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \
+ smp_mb__after_clear_bit(); \
+ } while(0)
+
/*
* Task priorities.
* Note: if you change these, you must also change
@@ -228,11 +242,16 @@ struct rpc_wait_queue {
/*
* Function prototypes
*/
-struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags);
+struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags,
+ const struct rpc_call_ops *ops, void *data);
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+ const struct rpc_call_ops *ops, void *data);
struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
-void rpc_init_task(struct rpc_task *, struct rpc_clnt *,
- rpc_action exitfunc, int flags);
+void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt,
+ int flags, const struct rpc_call_ops *ops,
+ void *data);
void rpc_release_task(struct rpc_task *);
+void rpc_exit_task(struct rpc_task *);
void rpc_killall_tasks(struct rpc_clnt *);
int rpc_execute(struct rpc_task *);
void rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
@@ -247,9 +266,11 @@ struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
void rpc_wake_up_status(struct rpc_wait_queue *, int);
void rpc_delay(struct rpc_task *, unsigned long);
void * rpc_malloc(struct rpc_task *, size_t);
+void rpc_free(struct rpc_task *);
int rpciod_up(void);
void rpciod_down(void);
void rpciod_wake_up(void);
+int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *));
#ifdef RPC_DEBUG
void rpc_show_tasks(void);
#endif
@@ -259,7 +280,12 @@ void rpc_destroy_mempool(void);
static inline void rpc_exit(struct rpc_task *task, int status)
{
task->tk_status = status;
- task->tk_action = NULL;
+ task->tk_action = rpc_exit_task;
+}
+
+static inline int rpc_wait_for_completion_task(struct rpc_task *task)
+{
+ return __rpc_wait_for_completion_task(task, NULL);
}
#ifdef RPC_DEBUG
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index e4086ec8b952..50cab2a09f28 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -246,6 +246,7 @@ struct svc_deferred_req {
u32 prot; /* protocol (UDP or TCP) */
struct sockaddr_in addr;
struct svc_sock *svsk; /* where reply must go */
+ u32 daddr; /* where reply must come from */
struct cache_deferred_req handle;
int argslen;
u32 args[0];
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 5da968729cf8..84c35d42d250 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -91,7 +91,6 @@ struct xdr_buf {
u32 * xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int len);
u32 * xdr_encode_opaque(u32 *p, const void *ptr, unsigned int len);
u32 * xdr_encode_string(u32 *p, const char *s);
-u32 * xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen);
u32 * xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen);
u32 * xdr_encode_netobj(u32 *p, const struct xdr_netobj *);
u32 * xdr_decode_netobj(u32 *p, struct xdr_netobj *);
@@ -135,11 +134,6 @@ xdr_adjust_iovec(struct kvec *iov, u32 *p)
}
/*
- * Maximum number of iov's we use.
- */
-#define MAX_IOVEC (12)
-
-/*
* XDR buffer helper functions
*/
extern void xdr_shift_buf(struct xdr_buf *, size_t);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 3b8b6e823c70..6ef99b14ff09 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -79,21 +79,19 @@ struct rpc_rqst {
void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
struct list_head rq_list;
+ __u32 * rq_buffer; /* XDR encode buffer */
+ size_t rq_bufsize;
+
struct xdr_buf rq_private_buf; /* The receive buffer
* used in the softirq.
*/
unsigned long rq_majortimeo; /* major timeout alarm */
unsigned long rq_timeout; /* Current timeout value */
unsigned int rq_retries; /* # of retries */
- /*
- * For authentication (e.g. auth_des)
- */
- u32 rq_creddata[2];
/*
* Partial send handling
*/
-
u32 rq_bytes_sent; /* Bytes we have sent */
unsigned long rq_xtime; /* when transmitted */
@@ -106,7 +104,10 @@ struct rpc_xprt_ops {
void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
int (*reserve_xprt)(struct rpc_task *task);
void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
+ void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
void (*connect)(struct rpc_task *task);
+ void * (*buf_alloc)(struct rpc_task *task, size_t size);
+ void (*buf_free)(struct rpc_task *task);
int (*send_request)(struct rpc_task *task);
void (*set_retrans_timeout)(struct rpc_task *task);
void (*timer)(struct rpc_task *task);
@@ -253,6 +254,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to);
#define XPRT_LOCKED (0)
#define XPRT_CONNECTED (1)
#define XPRT_CONNECTING (2)
+#define XPRT_CLOSE_WAIT (3)
static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index a61c04f804b2..5dc94e777fab 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -14,11 +14,7 @@
typedef struct pbe {
unsigned long address; /* address of the copy */
unsigned long orig_address; /* original address of page */
- swp_entry_t swap_address;
-
- struct pbe *next; /* also used as scratch space at
- * end of page (see link, diskpage)
- */
+ struct pbe *next;
} suspend_pagedir_t;
#define for_each_pbe(pbe, pblist) \
@@ -77,6 +73,6 @@ unsigned long get_safe_page(gfp_t gfp_mask);
* XXX: We try to keep some more pages free so that I/O operations succeed
* without paging. Might this be more?
*/
-#define PAGES_FOR_IO 512
+#define PAGES_FOR_IO 1024
#endif /* _LINUX_SWSUSP_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 508668f840b6..4a99e4a7fbf3 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -167,15 +167,38 @@ extern void FASTCALL(lru_cache_add_active(struct page *));
extern void FASTCALL(activate_page(struct page *));
extern void FASTCALL(mark_page_accessed(struct page *));
extern void lru_add_drain(void);
+extern int lru_add_drain_all(void);
extern int rotate_reclaimable_page(struct page *page);
extern void swap_setup(void);
/* linux/mm/vmscan.c */
extern int try_to_free_pages(struct zone **, gfp_t);
-extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
extern int shrink_all_memory(int);
extern int vm_swappiness;
+#ifdef CONFIG_NUMA
+extern int zone_reclaim_mode;
+extern int zone_reclaim(struct zone *, gfp_t, unsigned int);
+#else
+#define zone_reclaim_mode 0
+static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MIGRATION
+extern int isolate_lru_page(struct page *p);
+extern int putback_lru_pages(struct list_head *l);
+extern int migrate_pages(struct list_head *l, struct list_head *t,
+ struct list_head *moved, struct list_head *failed);
+#else
+static inline int isolate_lru_page(struct page *p) { return -ENOSYS; }
+static inline int putback_lru_pages(struct list_head *l) { return 0; }
+static inline int migrate_pages(struct list_head *l, struct list_head *t,
+ struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
+#endif
+
#ifdef CONFIG_MMU
/* linux/mm/shmem.c */
extern int shmem_unuse(swp_entry_t entry, struct page *page);
@@ -193,7 +216,7 @@ extern int rw_swap_page_sync(int, swp_entry_t, struct page *);
extern struct address_space swapper_space;
#define total_swapcache_pages swapper_space.nrpages
extern void show_swap_cache_info(void);
-extern int add_to_swap(struct page *);
+extern int add_to_swap(struct page *, gfp_t);
extern void __delete_from_swap_cache(struct page *);
extern void delete_from_swap_cache(struct page *);
extern int move_to_swap_cache(struct page *, swp_entry_t);
@@ -210,6 +233,7 @@ extern unsigned int nr_swapfiles;
extern struct swap_info_struct swap_info[];
extern void si_swapinfo(struct sysinfo *);
extern swp_entry_t get_swap_page(void);
+extern swp_entry_t get_swap_page_of_type(int type);
extern int swap_duplicate(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
extern void swap_free(swp_entry_t);
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 763bd290f28d..1b7cd8d1a71b 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -1,7 +1,7 @@
/*
* SyncLink Multiprotocol Serial Adapter Driver
*
- * $Id: synclink.h,v 3.6 2002/02/20 21:58:20 paulkf Exp $
+ * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $
*
* Copyright (C) 1998-2000 by Microgate Corporation
*
@@ -128,10 +128,14 @@
#define MGSL_BUS_TYPE_EISA 2
#define MGSL_BUS_TYPE_PCI 5
+#define MGSL_INTERFACE_MASK 0xf
#define MGSL_INTERFACE_DISABLE 0
#define MGSL_INTERFACE_RS232 1
#define MGSL_INTERFACE_V35 2
#define MGSL_INTERFACE_RS422 3
+#define MGSL_INTERFACE_RTS_EN 0x10
+#define MGSL_INTERFACE_LL 0x20
+#define MGSL_INTERFACE_RL 0x40
typedef struct _MGSL_PARAMS
{
@@ -163,6 +167,9 @@ typedef struct _MGSL_PARAMS
#define SYNCLINK_DEVICE_ID 0x0010
#define MGSCC_DEVICE_ID 0x0020
#define SYNCLINK_SCA_DEVICE_ID 0x0030
+#define SYNCLINK_GT_DEVICE_ID 0x0070
+#define SYNCLINK_GT4_DEVICE_ID 0x0080
+#define SYNCLINK_AC_DEVICE_ID 0x0090
#define MGSL_MAX_SERIAL_NUMBER 30
/*
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c7007b1db91d..e666d6070569 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -510,6 +510,28 @@ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3,
asmlinkage long sys_ioprio_set(int which, int who, int ioprio);
asmlinkage long sys_ioprio_get(int which, int who);
asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
- unsigned long maxnode);
+ unsigned long maxnode);
+asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
+ const unsigned long __user *from,
+ const unsigned long __user *to);
+asmlinkage long sys_mbind(unsigned long start, unsigned long len,
+ unsigned long mode,
+ unsigned long __user *nmask,
+ unsigned long maxnode,
+ unsigned flags);
+asmlinkage long sys_get_mempolicy(int __user *policy,
+ unsigned long __user *nmask,
+ unsigned long maxnode,
+ unsigned long addr, unsigned long flags);
+
+asmlinkage long sys_inotify_init(void);
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *path,
+ u32 mask);
+asmlinkage long sys_inotify_rm_watch(int fd, u32 wd);
+
+asmlinkage long sys_spu_run(int fd, __u32 __user *unpc,
+ __u32 __user *ustatus);
+asmlinkage long sys_spu_create(const char __user *name,
+ unsigned int flags, mode_t mode);
#endif
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 4be34ef8c2f7..8352a7ce5895 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -124,7 +124,7 @@ enum
KERN_OVERFLOWUID=46, /* int: overflow UID */
KERN_OVERFLOWGID=47, /* int: overflow GID */
KERN_SHMPATH=48, /* string: path to shm fs */
- KERN_HOTPLUG=49, /* string: path to hotplug policy agent */
+ KERN_HOTPLUG=49, /* string: path to uevent helper (deprecated) */
KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */
KERN_S390_USER_DEBUG_LOGGING=51, /* int: dumps of user faults */
KERN_CORE_USES_PID=52, /* int: use core or core.%pid */
@@ -180,6 +180,9 @@ enum
VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */
VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */
VM_SWAP_TOKEN_TIMEOUT=28, /* default time for token time out */
+ VM_DROP_PAGECACHE=29, /* int: nuke lots of pagecache */
+ VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */
+ VM_ZONE_RECLAIM_MODE=31,/* reclaim local zone memory before going off node */
};
@@ -390,6 +393,7 @@ enum
NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109,
NET_TCP_CONG_CONTROL=110,
NET_TCP_ABC=111,
+ NET_IPV4_IPFRAG_MAX_DIST=112,
};
enum {
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 0e1da6602e05..f2bb2396853f 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -55,22 +55,6 @@ struct tcphdr {
__u16 urg_ptr;
};
-#define TCP_ACTION_FIN (1 << 7)
-
-enum {
- TCPF_ESTABLISHED = (1 << 1),
- TCPF_SYN_SENT = (1 << 2),
- TCPF_SYN_RECV = (1 << 3),
- TCPF_FIN_WAIT1 = (1 << 4),
- TCPF_FIN_WAIT2 = (1 << 5),
- TCPF_TIME_WAIT = (1 << 6),
- TCPF_CLOSE = (1 << 7),
- TCPF_CLOSE_WAIT = (1 << 8),
- TCPF_LAST_ACK = (1 << 9),
- TCPF_LISTEN = (1 << 10),
- TCPF_CLOSING = (1 << 11)
-};
-
/*
* The union cast uses a gcc extension to avoid aliasing problems
* (union is compatible to any of its members)
@@ -254,10 +238,9 @@ struct tcp_sock {
__u32 snd_wl1; /* Sequence for window update */
__u32 snd_wnd; /* The window we expect to receive */
__u32 max_window; /* Maximal window ever seen from peer */
- __u32 pmtu_cookie; /* Last pmtu seen by socket */
__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) */
+ /* XXX Two bytes hole, try to pack */
__u32 window_clamp; /* Maximal window to advertise */
__u32 rcv_ssthresh; /* Current window clamp */
@@ -295,8 +278,6 @@ struct tcp_sock {
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 */
-
__u32 rcv_wnd; /* Current receiver window */
__u32 rcv_wup; /* rcv_nxt on last window update sent */
__u32 write_seq; /* Tail(+1) of data held in tcp send buffer */
diff --git a/include/linux/time.h b/include/linux/time.h
index 797ccd813bb0..614dd8465839 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -4,7 +4,7 @@
#include <linux/types.h>
#ifdef __KERNEL__
-#include <linux/seqlock.h>
+# include <linux/seqlock.h>
#endif
#ifndef _STRUCT_TIMESPEC
@@ -13,7 +13,7 @@ struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
-#endif /* _STRUCT_TIMESPEC */
+#endif
struct timeval {
time_t tv_sec; /* seconds */
@@ -27,93 +27,103 @@ struct timezone {
#ifdef __KERNEL__
-/* Parameters used to convert the timespec values */
-#define MSEC_PER_SEC (1000L)
-#define USEC_PER_SEC (1000000L)
-#define NSEC_PER_SEC (1000000000L)
-#define NSEC_PER_USEC (1000L)
+/* Parameters used to convert the timespec values: */
+#define MSEC_PER_SEC 1000L
+#define USEC_PER_SEC 1000000L
+#define NSEC_PER_SEC 1000000000L
+#define NSEC_PER_USEC 1000L
-static __inline__ int timespec_equal(struct timespec *a, struct timespec *b)
-{
+static __inline__ int timespec_equal(struct timespec *a, struct timespec *b)
+{
return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
-}
+}
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
+extern unsigned long mktime(const unsigned int year, const unsigned int mon,
+ const unsigned int day, const unsigned int hour,
+ const unsigned int min, const unsigned int sec);
+
+extern void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec);
+
+/*
+ * Returns true if the timespec is norm, false if denorm:
*/
-static inline unsigned long
-mktime (unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
-
- return (((
- (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
+#define timespec_valid(ts) \
+ (((ts)->tv_sec >= 0) && (((unsigned) (ts)->tv_nsec) < NSEC_PER_SEC))
+
+/*
+ * 64-bit nanosec type. Large enough to span 292+ years in nanosecond
+ * resolution. Ought to be enough for a while.
+ */
+typedef s64 nsec_t;
extern struct timespec xtime;
extern struct timespec wall_to_monotonic;
extern seqlock_t xtime_lock;
static inline unsigned long get_seconds(void)
-{
+{
return xtime.tv_sec;
}
struct timespec current_kernel_time(void);
-#define CURRENT_TIME (current_kernel_time())
-#define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
+#define CURRENT_TIME (current_kernel_time())
+#define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday(struct timespec *tv);
extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
-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_utimes(char __user * filename, struct timeval * times);
+#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
+extern long do_utimes(int dfd, char __user *filename, struct timeval *times);
struct itimerval;
-extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
+extern int do_setitimer(int which, struct itimerval *value,
+ struct itimerval *ovalue);
extern int do_getitimer(int which, struct itimerval *value);
-extern void getnstimeofday (struct timespec *tv);
-extern void getnstimestamp(struct timespec *ts);
+extern void getnstimeofday(struct timespec *tv);
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
-static inline void
-set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
+/**
+ * timespec_to_ns - Convert timespec to nanoseconds
+ * @ts: pointer to the timespec variable to be converted
+ *
+ * Returns the scalar nanosecond representation of the timespec
+ * parameter.
+ */
+static inline nsec_t timespec_to_ns(const struct timespec *ts)
{
- while (nsec >= NSEC_PER_SEC) {
- nsec -= NSEC_PER_SEC;
- ++sec;
- }
- while (nsec < 0) {
- nsec += NSEC_PER_SEC;
- --sec;
- }
- ts->tv_sec = sec;
- ts->tv_nsec = nsec;
+ return ((nsec_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
}
+/**
+ * timeval_to_ns - Convert timeval to nanoseconds
+ * @ts: pointer to the timeval variable to be converted
+ *
+ * Returns the scalar nanosecond representation of the timeval
+ * parameter.
+ */
+static inline nsec_t timeval_to_ns(const struct timeval *tv)
+{
+ return ((nsec_t) tv->tv_sec * NSEC_PER_SEC) +
+ tv->tv_usec * NSEC_PER_USEC;
+}
+
+/**
+ * ns_to_timespec - Convert nanoseconds to timespec
+ * @nsec: the nanoseconds value to be converted
+ *
+ * Returns the timespec representation of the nsec parameter.
+ */
+extern struct timespec ns_to_timespec(const nsec_t nsec);
+
+/**
+ * ns_to_timeval - Convert nanoseconds to timeval
+ * @nsec: the nanoseconds value to be converted
+ *
+ * Returns the timeval representation of the nsec parameter.
+ */
+extern struct timeval ns_to_timeval(const nsec_t nsec);
+
#endif /* __KERNEL__ */
#define NFDBITS __NFDBITS
@@ -126,49 +136,41 @@ set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
/*
* Names of the interval timers, and structure
- * defining a timer setting.
+ * defining a timer setting:
*/
-#define ITIMER_REAL 0
-#define ITIMER_VIRTUAL 1
-#define ITIMER_PROF 2
+#define ITIMER_REAL 0
+#define ITIMER_VIRTUAL 1
+#define ITIMER_PROF 2
-struct itimerspec {
- struct timespec it_interval; /* timer period */
- struct timespec it_value; /* timer expiration */
+struct itimerspec {
+ struct timespec it_interval; /* timer period */
+ struct timespec it_value; /* timer expiration */
};
-struct itimerval {
- struct timeval it_interval; /* timer interval */
- struct timeval it_value; /* current value */
+struct itimerval {
+ struct timeval it_interval; /* timer interval */
+ struct timeval it_value; /* current value */
};
-
/*
- * The IDs of the various system clocks (for POSIX.1b interval timers).
+ * The IDs of the various system clocks (for POSIX.1b interval timers):
*/
-#define CLOCK_REALTIME 0
-#define CLOCK_MONOTONIC 1
-#define CLOCK_PROCESS_CPUTIME_ID 2
-#define CLOCK_THREAD_CPUTIME_ID 3
-#define CLOCK_REALTIME_HR 4
-#define CLOCK_MONOTONIC_HR 5
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+#define CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOCK_THREAD_CPUTIME_ID 3
/*
- * The IDs of various hardware clocks
+ * The IDs of various hardware clocks:
*/
-
-
-#define CLOCK_SGI_CYCLE 10
-#define MAX_CLOCKS 16
-#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC | \
- CLOCK_REALTIME_HR | CLOCK_MONOTONIC_HR)
-#define CLOCKS_MONO (CLOCK_MONOTONIC & CLOCK_MONOTONIC_HR)
+#define CLOCK_SGI_CYCLE 10
+#define MAX_CLOCKS 16
+#define CLOCKS_MASK (CLOCK_REALTIME | CLOCK_MONOTONIC)
+#define CLOCKS_MONO CLOCK_MONOTONIC
/*
- * The various flags for setting POSIX.1b interval timers.
+ * The various flags for setting POSIX.1b interval timers:
*/
-
-#define TIMER_ABSTIME 0x01
-
+#define TIMER_ABSTIME 0x01
#endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 72f3a7781106..9b9877fd2505 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -96,6 +96,6 @@ static inline void add_timer(struct timer_list *timer)
extern void init_timers(void);
extern void run_local_timers(void);
-extern void it_real_fn(unsigned long);
+extern int it_real_fn(void *);
#endif
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
new file mode 100644
index 000000000000..243a15f54002
--- /dev/null
+++ b/include/linux/tipc.h
@@ -0,0 +1,212 @@
+/*
+ * include/linux/tipc.h: Include file for TIPC socket interface
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_TIPC_H_
+#define _LINUX_TIPC_H_
+
+#include <linux/types.h>
+
+/*
+ * TIPC addressing primitives
+ */
+
+struct tipc_portid {
+ __u32 ref;
+ __u32 node;
+};
+
+struct tipc_name {
+ __u32 type;
+ __u32 instance;
+};
+
+struct tipc_name_seq {
+ __u32 type;
+ __u32 lower;
+ __u32 upper;
+};
+
+static inline __u32 tipc_addr(unsigned int zone,
+ unsigned int cluster,
+ unsigned int node)
+{
+ return (zone << 24) | (cluster << 12) | node;
+}
+
+static inline unsigned int tipc_zone(__u32 addr)
+{
+ return addr >> 24;
+}
+
+static inline unsigned int tipc_cluster(__u32 addr)
+{
+ return (addr >> 12) & 0xfff;
+}
+
+static inline unsigned int tipc_node(__u32 addr)
+{
+ return addr & 0xfff;
+}
+
+/*
+ * Application-accessible port name types
+ */
+
+#define TIPC_CFG_SRV 0 /* configuration service name type */
+#define TIPC_TOP_SRV 1 /* topology service name type */
+#define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */
+
+/*
+ * Publication scopes when binding port names and port name sequences
+ */
+
+#define TIPC_ZONE_SCOPE 1
+#define TIPC_CLUSTER_SCOPE 2
+#define TIPC_NODE_SCOPE 3
+
+/*
+ * Limiting values for messages
+ */
+
+#define TIPC_MAX_USER_MSG_SIZE 66000
+
+/*
+ * Message importance levels
+ */
+
+#define TIPC_LOW_IMPORTANCE 0 /* default */
+#define TIPC_MEDIUM_IMPORTANCE 1
+#define TIPC_HIGH_IMPORTANCE 2
+#define TIPC_CRITICAL_IMPORTANCE 3
+
+/*
+ * Msg rejection/connection shutdown reasons
+ */
+
+#define TIPC_OK 0
+#define TIPC_ERR_NO_NAME 1
+#define TIPC_ERR_NO_PORT 2
+#define TIPC_ERR_NO_NODE 3
+#define TIPC_ERR_OVERLOAD 4
+#define TIPC_CONN_SHUTDOWN 5
+
+/*
+ * TIPC topology subscription service definitions
+ */
+
+#define TIPC_SUB_PORTS 0x01 /* filter for port availability */
+#define TIPC_SUB_SERVICE 0x02 /* filter for service availability */
+#if 0
+/* The following filter options are not currently implemented */
+#define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */
+#define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */
+#define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */
+#endif
+
+#define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */
+
+struct tipc_subscr {
+ struct tipc_name_seq seq; /* name sequence of interest */
+ __u32 timeout; /* subscription duration (in ms) */
+ __u32 filter; /* bitmask of filter options */
+ char usr_handle[8]; /* available for subscriber use */
+};
+
+#define TIPC_PUBLISHED 1 /* publication event */
+#define TIPC_WITHDRAWN 2 /* withdraw event */
+#define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */
+
+struct tipc_event {
+ __u32 event; /* event type */
+ __u32 found_lower; /* matching name seq instances */
+ __u32 found_upper; /* " " " " */
+ struct tipc_portid port; /* associated port */
+ struct tipc_subscr s; /* associated subscription */
+};
+
+/*
+ * Socket API
+ */
+
+#ifndef AF_TIPC
+#define AF_TIPC 30
+#endif
+
+#ifndef PF_TIPC
+#define PF_TIPC AF_TIPC
+#endif
+
+#ifndef SOL_TIPC
+#define SOL_TIPC 271
+#endif
+
+#define TIPC_ADDR_NAMESEQ 1
+#define TIPC_ADDR_MCAST 1
+#define TIPC_ADDR_NAME 2
+#define TIPC_ADDR_ID 3
+
+struct sockaddr_tipc {
+ unsigned short family;
+ unsigned char addrtype;
+ signed char scope;
+ union {
+ struct tipc_portid id;
+ struct tipc_name_seq nameseq;
+ struct {
+ struct tipc_name name;
+ __u32 domain; /* 0: own zone */
+ } name;
+ } addr;
+};
+
+/*
+ * Ancillary data objects supported by recvmsg()
+ */
+
+#define TIPC_ERRINFO 1 /* error info */
+#define TIPC_RETDATA 2 /* returned data */
+#define TIPC_DESTNAME 3 /* destination name */
+
+/*
+ * TIPC-specific socket option values
+ */
+
+#define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */
+#define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */
+#define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */
+#define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */
+
+#endif
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h
new file mode 100644
index 000000000000..33a653913d94
--- /dev/null
+++ b/include/linux/tipc_config.h
@@ -0,0 +1,410 @@
+/*
+ * include/linux/tipc_config.h: Include file for TIPC configuration interface
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LINUX_TIPC_CONFIG_H_
+#define _LINUX_TIPC_CONFIG_H_
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+/*
+ * Configuration
+ *
+ * All configuration management messaging involves sending a request message
+ * to the TIPC configuration service on a node, which sends a reply message
+ * back. (In the future multi-message replies may be supported.)
+ *
+ * Both request and reply messages consist of a transport header and payload.
+ * The transport header contains info about the desired operation;
+ * the payload consists of zero or more type/length/value (TLV) items
+ * which specify parameters or results for the operation.
+ *
+ * For many operations, the request and reply messages have a fixed number
+ * of TLVs (usually zero or one); however, some reply messages may return
+ * a variable number of TLVs. A failed request is denoted by the presence
+ * of an "error string" TLV in the reply message instead of the TLV(s) the
+ * reply should contain if the request succeeds.
+ */
+
+/*
+ * Public commands:
+ * May be issued by any process.
+ * Accepted by own node, or by remote node only if remote management enabled.
+ */
+
+#define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */
+#define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */
+#define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */
+#define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */
+#define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */
+#define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */
+#define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */
+#define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */
+
+#if 0
+#define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */
+#define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */
+#define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */
+#define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */
+#endif
+
+/*
+ * Protected commands:
+ * May only be issued by "network administration capable" process.
+ * Accepted by own node, or by remote node only if remote management enabled
+ * and this node is zone manager.
+ */
+
+#define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */
+#define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */
+#define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */
+
+#define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */
+#define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */
+#define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */
+#define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */
+#define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */
+#define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */
+#define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */
+#define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */
+
+#if 0
+#define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */
+#define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */
+#define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */
+#define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */
+#endif
+
+/*
+ * Private commands:
+ * May only be issued by "network administration capable" process.
+ * Accepted by own node only; cannot be used on a remote node.
+ */
+
+#define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */
+#if 0
+#define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */
+#endif
+#define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */
+#define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */
+#define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */
+
+/*
+ * TLV types defined for TIPC
+ */
+
+#define TIPC_TLV_NONE 0 /* no TLV present */
+#define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/
+#define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */
+#define TIPC_TLV_STRING 3 /* char[128] (max) */
+#define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */
+#define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */
+
+#define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */
+#define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */
+#define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */
+#define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */
+#define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */
+#define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */
+#define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */
+#define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */
+#define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */
+#define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */
+#define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */
+
+/*
+ * Maximum sizes of TIPC bearer-related names (including terminating NUL)
+ */
+
+#define TIPC_MAX_MEDIA_NAME 16 /* format = media */
+#define TIPC_MAX_IF_NAME 16 /* format = interface */
+#define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */
+#define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */
+
+/*
+ * Link priority limits (min, default, max, media default)
+ */
+
+#define TIPC_MIN_LINK_PRI 0
+#define TIPC_DEF_LINK_PRI 10
+#define TIPC_MAX_LINK_PRI 31
+#define TIPC_MEDIA_LINK_PRI (TIPC_MAX_LINK_PRI + 1)
+
+/*
+ * Link tolerance limits (min, default, max), in ms
+ */
+
+#define TIPC_MIN_LINK_TOL 50
+#define TIPC_DEF_LINK_TOL 1500
+#define TIPC_MAX_LINK_TOL 30000
+
+/*
+ * Link window limits (min, default, max), in packets
+ */
+
+#define TIPC_MIN_LINK_WIN 16
+#define TIPC_DEF_LINK_WIN 50
+#define TIPC_MAX_LINK_WIN 150
+
+
+struct tipc_node_info {
+ __u32 addr; /* network address of node */
+ __u32 up; /* 0=down, 1= up */
+};
+
+struct tipc_link_info {
+ __u32 dest; /* network address of peer node */
+ __u32 up; /* 0=down, 1=up */
+ char str[TIPC_MAX_LINK_NAME]; /* link name */
+};
+
+struct tipc_bearer_config {
+ __u32 priority; /* Range [1,31]. Override per link */
+ __u32 detect_scope;
+ char name[TIPC_MAX_BEARER_NAME];
+};
+
+struct tipc_link_config {
+ __u32 value;
+ char name[TIPC_MAX_LINK_NAME];
+};
+
+#define TIPC_NTQ_ALLTYPES 0x80000000
+
+struct tipc_name_table_query {
+ __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */
+ __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */
+ __u32 lowbound; /* (i.e. displays all entries of name table) */
+ __u32 upbound;
+};
+
+/*
+ * The error string TLV is a null-terminated string describing the cause
+ * of the request failure. To simplify error processing (and to save space)
+ * the first character of the string can be a special error code character
+ * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason.
+ */
+
+#define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */
+#define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */
+#define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */
+#define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */
+#define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */
+#define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */
+
+#if 0
+/* prototypes TLV structures for proposed commands */
+struct tipc_link_create {
+ __u32 domain;
+ struct tipc_media_addr peer_addr;
+ char bearer_name[TIPC_MAX_BEARER_NAME];
+};
+
+struct tipc_route_info {
+ __u32 dest;
+ __u32 router;
+};
+#endif
+
+/*
+ * A TLV consists of a descriptor, followed by the TLV value.
+ * TLV descriptor fields are stored in network byte order;
+ * TLV values must also be stored in network byte order (where applicable).
+ * TLV descriptors must be aligned to addresses which are multiple of 4,
+ * so up to 3 bytes of padding may exist at the end of the TLV value area.
+ * There must not be any padding between the TLV descriptor and its value.
+ */
+
+struct tlv_desc {
+ __u16 tlv_len; /* TLV length (descriptor + value) */
+ __u16 tlv_type; /* TLV identifier */
+};
+
+#define TLV_ALIGNTO 4
+
+#define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1))
+#define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen))
+#define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen)))
+#define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0)))
+
+static inline int TLV_OK(const void *tlv, __u16 space)
+{
+ /*
+ * Would also like to check that "tlv" is a multiple of 4,
+ * but don't know how to do this in a portable way.
+ * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler
+ * won't allow binary "&" with a pointer.
+ * - Tried casting "tlv" to integer type, but causes warning about size
+ * mismatch when pointer is bigger than chosen type (int, long, ...).
+ */
+
+ return (space >= TLV_SPACE(0)) &&
+ (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space);
+}
+
+static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type)
+{
+ return TLV_OK(tlv, space) &&
+ (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type);
+}
+
+static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len)
+{
+ struct tlv_desc *tlv_ptr;
+ int tlv_len;
+
+ tlv_len = TLV_LENGTH(len);
+ tlv_ptr = (struct tlv_desc *)tlv;
+ tlv_ptr->tlv_type = htons(type);
+ tlv_ptr->tlv_len = htons(tlv_len);
+ if (len && data)
+ memcpy(TLV_DATA(tlv_ptr), data, tlv_len);
+ return TLV_SPACE(len);
+}
+
+/*
+ * A TLV list descriptor simplifies processing of messages
+ * containing multiple TLVs.
+ */
+
+struct tlv_list_desc {
+ struct tlv_desc *tlv_ptr; /* ptr to current TLV */
+ __u32 tlv_space; /* # bytes from curr TLV to list end */
+};
+
+static inline void TLV_LIST_INIT(struct tlv_list_desc *list,
+ void *data, __u32 space)
+{
+ list->tlv_ptr = (struct tlv_desc *)data;
+ list->tlv_space = space;
+}
+
+static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
+{
+ return (list->tlv_space == 0);
+}
+
+static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type)
+{
+ return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type);
+}
+
+static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
+{
+ return TLV_DATA(list->tlv_ptr);
+}
+
+static inline void TLV_LIST_STEP(struct tlv_list_desc *list)
+{
+ __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len));
+
+ list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space);
+ list->tlv_space -= tlv_space;
+}
+
+/*
+ * Configuration messages exchanged via NETLINK_GENERIC use the following
+ * family id, name, version and command.
+ */
+#define TIPC_GENL_NAME "TIPC"
+#define TIPC_GENL_VERSION 0x1
+#define TIPC_GENL_CMD 0x1
+
+/*
+ * TIPC specific header used in NETLINK_GENERIC requests.
+ */
+struct tipc_genlmsghdr {
+ __u32 dest; /* Destination address */
+ __u16 cmd; /* Command */
+ __u16 reserved; /* Unused */
+};
+
+#define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr))
+
+/*
+ * Configuration messages exchanged via TIPC sockets use the TIPC configuration
+ * message header, which is defined below. This structure is analogous
+ * to the Netlink message header, but fields are stored in network byte order
+ * and no padding is permitted between the header and the message data
+ * that follows.
+ */
+
+struct tipc_cfg_msg_hdr
+{
+ __u32 tcm_len; /* Message length (including header) */
+ __u16 tcm_type; /* Command type */
+ __u16 tcm_flags; /* Additional flags */
+ char tcm_reserved[8]; /* Unused */
+};
+
+#define TCM_F_REQUEST 0x1 /* Flag: Request message */
+#define TCM_F_MORE 0x2 /* Flag: Message to be continued */
+
+#define TCM_ALIGN(datalen) (((datalen)+3) & ~3)
+#define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen)
+#define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen)))
+#define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0)))
+
+static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags,
+ void *data, __u16 data_len)
+{
+ struct tipc_cfg_msg_hdr *tcm_hdr;
+ int msg_len;
+
+ msg_len = TCM_LENGTH(data_len);
+ tcm_hdr = (struct tipc_cfg_msg_hdr *)msg;
+ tcm_hdr->tcm_len = htonl(msg_len);
+ tcm_hdr->tcm_type = htons(cmd);
+ tcm_hdr->tcm_flags = htons(flags);
+ if (data_len && data)
+ memcpy(TCM_DATA(msg), data, data_len);
+ return TCM_SPACE(data_len);
+}
+
+#endif
diff --git a/include/linux/topology.h b/include/linux/topology.h
index 3df1d474e5c5..e8eb0040ce3a 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -56,6 +56,14 @@
#define REMOTE_DISTANCE 20
#define node_distance(from,to) ((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
#endif
+#ifndef RECLAIM_DISTANCE
+/*
+ * If the distance between nodes in a system is larger than RECLAIM_DISTANCE
+ * (in whatever arch specific measurement units returned by node_distance())
+ * then switch on zone reclaim on boot.
+ */
+#define RECLAIM_DISTANCE 20
+#endif
#ifndef PENALTY_FOR_NODE_WITH_CPUS
#define PENALTY_FOR_NODE_WITH_CPUS (1)
#endif
@@ -86,7 +94,6 @@
.max_interval = 2, \
.busy_factor = 8, \
.imbalance_pct = 110, \
- .cache_hot_time = 0, \
.cache_nice_tries = 0, \
.per_cpu_gain = 25, \
.busy_idx = 0, \
@@ -117,7 +124,6 @@
.max_interval = 4, \
.busy_factor = 64, \
.imbalance_pct = 125, \
- .cache_hot_time = (5*1000000/2), \
.cache_nice_tries = 1, \
.per_cpu_gain = 100, \
.busy_idx = 2, \
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 1267f88ece6e..3787102e4b12 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -23,6 +23,7 @@
#include <linux/workqueue.h>
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
+#include <linux/screen_info.h>
#include <asm/system.h>
@@ -37,77 +38,6 @@
#define NR_LDISCS 16
/*
- * These are set up by the setup-routine at boot-time:
- */
-
-struct screen_info {
- u8 orig_x; /* 0x00 */
- u8 orig_y; /* 0x01 */
- u16 dontuse1; /* 0x02 -- EXT_MEM_K sits here */
- u16 orig_video_page; /* 0x04 */
- u8 orig_video_mode; /* 0x06 */
- u8 orig_video_cols; /* 0x07 */
- u16 unused2; /* 0x08 */
- u16 orig_video_ega_bx; /* 0x0a */
- u16 unused3; /* 0x0c */
- u8 orig_video_lines; /* 0x0e */
- u8 orig_video_isVGA; /* 0x0f */
- u16 orig_video_points; /* 0x10 */
-
- /* VESA graphic mode -- linear frame buffer */
- u16 lfb_width; /* 0x12 */
- u16 lfb_height; /* 0x14 */
- u16 lfb_depth; /* 0x16 */
- u32 lfb_base; /* 0x18 */
- u32 lfb_size; /* 0x1c */
- u16 dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
- u16 lfb_linelength; /* 0x24 */
- u8 red_size; /* 0x26 */
- u8 red_pos; /* 0x27 */
- u8 green_size; /* 0x28 */
- u8 green_pos; /* 0x29 */
- u8 blue_size; /* 0x2a */
- u8 blue_pos; /* 0x2b */
- u8 rsvd_size; /* 0x2c */
- u8 rsvd_pos; /* 0x2d */
- u16 vesapm_seg; /* 0x2e */
- u16 vesapm_off; /* 0x30 */
- u16 pages; /* 0x32 */
- u16 vesa_attributes; /* 0x34 */
- u32 capabilities; /* 0x36 */
- /* 0x3a -- 0x3f reserved for future expansion */
-};
-
-extern struct screen_info screen_info;
-
-#define ORIG_X (screen_info.orig_x)
-#define ORIG_Y (screen_info.orig_y)
-#define ORIG_VIDEO_MODE (screen_info.orig_video_mode)
-#define ORIG_VIDEO_COLS (screen_info.orig_video_cols)
-#define ORIG_VIDEO_EGA_BX (screen_info.orig_video_ega_bx)
-#define ORIG_VIDEO_LINES (screen_info.orig_video_lines)
-#define ORIG_VIDEO_ISVGA (screen_info.orig_video_isVGA)
-#define ORIG_VIDEO_POINTS (screen_info.orig_video_points)
-
-#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
-#define VIDEO_TYPE_CGA 0x11 /* CGA Display */
-#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */
-#define VIDEO_TYPE_EGAC 0x21 /* EGA in Color Mode */
-#define VIDEO_TYPE_VGAC 0x22 /* VGA+ in Color Mode */
-#define VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */
-
-#define VIDEO_TYPE_PICA_S3 0x30 /* ACER PICA-61 local S3 video */
-#define VIDEO_TYPE_MIPS_G364 0x31 /* MIPS Magnum 4000 G364 video */
-#define VIDEO_TYPE_SGI 0x33 /* Various SGI graphics hardware */
-
-#define VIDEO_TYPE_TGAC 0x40 /* DEC TGA */
-
-#define VIDEO_TYPE_SUN 0x50 /* Sun frame buffer. */
-#define VIDEO_TYPE_SUNPCI 0x51 /* Sun PCI based frame buffer. */
-
-#define VIDEO_TYPE_PMAC 0x60 /* PowerMacintosh frame buffer. */
-
-/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
* a c_cc[] character, but indicates that a particular special character
* isn't in use (eg VINTR has no character etc)
@@ -121,16 +51,22 @@ extern struct screen_info screen_info;
*/
#define TTY_FLIPBUF_SIZE 512
-struct tty_flip_buffer {
+struct tty_buffer {
+ struct tty_buffer *next;
+ char *char_buf_ptr;
+ unsigned char *flag_buf_ptr;
+ int used;
+ int size;
+ /* Data points here */
+ unsigned long data[0];
+};
+
+struct tty_bufhead {
struct work_struct work;
struct semaphore pty_sem;
- char *char_buf_ptr;
- unsigned char *flag_buf_ptr;
- int count;
- int buf_num;
- unsigned char char_buf[2*TTY_FLIPBUF_SIZE];
- char flag_buf[2*TTY_FLIPBUF_SIZE];
- unsigned char slop[4]; /* N.B. bug overwrites buffer by 1 */
+ struct tty_buffer *head; /* Queue head */
+ struct tty_buffer *tail; /* Active buffer */
+ struct tty_buffer *free; /* Free queue head */
};
/*
* The pty uses char_buf and flag_buf as a contiguous buffer
@@ -256,10 +192,11 @@ struct tty_struct {
unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
unsigned char low_latency:1, warned:1;
unsigned char ctrl_status;
+ unsigned int receive_room; /* Bytes free for queue */
struct tty_struct *link;
struct fasync_struct *fasync;
- struct tty_flip_buffer flip;
+ struct tty_bufhead buf;
int max_flip_cnt;
int alt_speed; /* For magic substitution of 38400 bps */
wait_queue_head_t write_wait;
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index abe9bfcf226c..be1400e82482 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -1,25 +1,33 @@
#ifndef _LINUX_TTY_FLIP_H
#define _LINUX_TTY_FLIP_H
+extern int tty_buffer_request_room(struct tty_struct *tty, size_t size);
+extern int tty_insert_flip_string(struct tty_struct *tty, unsigned char *chars, size_t size);
+extern int tty_insert_flip_string_flags(struct tty_struct *tty, unsigned char *chars, char *flags, size_t size);
+extern int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size);
+extern int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size);
+
#ifdef INCLUDE_INLINE_FUNCS
#define _INLINE_ extern
#else
#define _INLINE_ static __inline__
#endif
-_INLINE_ void tty_insert_flip_char(struct tty_struct *tty,
+_INLINE_ int tty_insert_flip_char(struct tty_struct *tty,
unsigned char ch, char flag)
{
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- *tty->flip.flag_buf_ptr++ = flag;
- *tty->flip.char_buf_ptr++ = ch;
+ struct tty_buffer *tb = tty->buf.tail;
+ if (tb && tb->used < tb->size) {
+ tb->flag_buf_ptr[tb->used] = flag;
+ tb->char_buf_ptr[tb->used++] = ch;
+ return 1;
}
+ return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
}
_INLINE_ void tty_schedule_flip(struct tty_struct *tty)
{
- schedule_delayed_work(&tty->flip.work, 1);
+ schedule_delayed_work(&tty->buf.work, 1);
}
#undef _INLINE_
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index 6066afde5ce4..83c6e6c10ebb 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -81,14 +81,6 @@
* pointer of flag bytes which indicate whether a character was
* received with a parity error, etc.
*
- * int (*receive_room)(struct tty_struct *);
- *
- * This function is called by the low-level tty driver to
- * determine how many characters the line discpline can accept.
- * The low-level driver must not send more characters than was
- * indicated by receive_room, or the line discpline may drop
- * those characters.
- *
* void (*write_wakeup)(struct tty_struct *);
*
* This function is called by the low-level tty driver to signal
@@ -136,7 +128,6 @@ struct tty_ldisc {
*/
void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
char *fp, int count);
- int (*receive_room)(struct tty_struct *);
void (*write_wakeup)(struct tty_struct *);
struct module *owner;
diff --git a/include/linux/udf_fs.h b/include/linux/udf_fs.h
index 46e2bb945353..36c684e1b110 100644
--- a/include/linux/udf_fs.h
+++ b/include/linux/udf_fs.h
@@ -13,11 +13,6 @@
* http://www.osta.org/ * http://www.ecma.ch/
* http://www.iso.org/
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
index 62b15a4214e6..1e7508420fcf 100644
--- a/include/linux/udf_fs_i.h
+++ b/include/linux/udf_fs_i.h
@@ -3,11 +3,6 @@
*
* This file is intended for the Linux kernel/module.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/include/linux/udf_fs_sb.h b/include/linux/udf_fs_sb.h
index 1966a6dbb4b6..b15ff2e99c91 100644
--- a/include/linux/udf_fs_sb.h
+++ b/include/linux/udf_fs_sb.h
@@ -3,11 +3,6 @@
*
* This include file is for the Linux kernel/module.
*
- * CONTACTS
- * E-mail regarding any portion of the Linux UDF file system should be
- * directed to the development team mailing list (run by majordomo):
- * linux_udf@hpesjro.fc.hp.com
- *
* COPYRIGHT
* This file is distributed under the terms of the GNU General Public
* License (GPL). Copies of the GPL can be obtained from:
diff --git a/include/linux/udp.h b/include/linux/udp.h
index b60e0b4a25c4..85a55658831c 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -35,10 +35,10 @@ struct udphdr {
#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
#ifdef __KERNEL__
-
#include <linux/config.h>
-#include <net/sock.h>
-#include <linux/ip.h>
+#include <linux/types.h>
+
+#include <net/inet_sock.h>
struct udp_sock {
/* inet_sock has to be the first member */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d81b050e5955..827cc6de5f5c 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -225,7 +225,7 @@ struct usb_interface_cache {
* Device drivers should not attempt to activate configurations. The choice
* of which configuration to install is a policy decision based on such
* considerations as available power, functionality provided, and the user's
- * desires (expressed through hotplug scripts). However, drivers can call
+ * desires (expressed through userspace tools). However, drivers can call
* usb_reset_configuration() to reinitialize the current configuration and
* all its interfaces.
*/
@@ -329,8 +329,6 @@ struct usb_device {
struct usb_tt *tt; /* low/full speed dev, highspeed hub */
int ttport; /* device port on that tt hub */
- struct semaphore serialize;
-
unsigned int toggle[2]; /* one bit for each endpoint
* ([0] = IN, [1] = OUT) */
@@ -349,6 +347,9 @@ struct usb_device {
char **rawdescriptors; /* Raw descriptors for each config */
+ unsigned short bus_mA; /* Current available from the bus */
+ u8 portnum; /* Parent port number (origin 1) */
+
int have_langid; /* whether string_langid is valid */
int string_langid; /* language ID for strings */
@@ -377,11 +378,12 @@ struct usb_device {
extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
-extern void usb_lock_device(struct usb_device *udev);
-extern int usb_trylock_device(struct usb_device *udev);
+/* USB device locking */
+#define usb_lock_device(udev) down(&(udev)->dev.sem)
+#define usb_unlock_device(udev) up(&(udev)->dev.sem)
+#define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem)
extern int usb_lock_device_for_reset(struct usb_device *udev,
struct usb_interface *iface);
-extern void usb_unlock_device(struct usb_device *udev);
/* USB port reset for device reinitialization */
extern int usb_reset_device(struct usb_device *dev);
@@ -529,10 +531,13 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
/* ----------------------------------------------------------------------- */
+struct usb_dynids {
+ spinlock_t lock;
+ struct list_head list;
+};
+
/**
* struct usb_driver - identifies USB driver to usbcore
- * @owner: Pointer to the module owner of this driver; initialize
- * it using THIS_MODULE.
* @name: The driver name should be unique among USB drivers,
* and should normally be the same as the module name.
* @probe: Called to see if the driver is willing to manage a particular
@@ -553,7 +558,11 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
* @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
* or your driver's probe function will never get called.
+ * @dynids: used internally to hold the list of dynamically added device
+ * ids for this driver.
* @driver: the driver model core driver structure.
+ * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
+ * added to this driver by preventing the sysfs file from being created.
*
* USB drivers must provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional.
@@ -571,8 +580,6 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
* them as necessary, and blocking until the unlinks complete).
*/
struct usb_driver {
- struct module *owner;
-
const char *name;
int (*probe) (struct usb_interface *intf,
@@ -588,7 +595,9 @@ struct usb_driver {
const struct usb_device_id *id_table;
+ struct usb_dynids dynids;
struct device_driver driver;
+ unsigned int no_dynamic_id:1;
};
#define to_usb_driver(d) container_of(d, struct usb_driver, driver)
@@ -614,7 +623,11 @@ struct usb_class_driver {
* use these in module_init()/module_exit()
* and don't forget MODULE_DEVICE_TABLE(usb, ...)
*/
-extern int usb_register(struct usb_driver *);
+int usb_register_driver(struct usb_driver *, struct module *);
+static inline int usb_register(struct usb_driver *driver)
+{
+ return usb_register_driver(driver, THIS_MODULE);
+}
extern void usb_deregister(struct usb_driver *);
extern int usb_register_dev(struct usb_interface *intf,
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
new file mode 100644
index 000000000000..b2d08984a9f7
--- /dev/null
+++ b/include/linux/usb_usual.h
@@ -0,0 +1,126 @@
+/*
+ * Interface to the libusual.
+ *
+ * Copyright (c) 2005 Pete Zaitcev <zaitcev@redhat.com>
+ * Copyright (c) 1999-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * Copyright (c) 1999 Michael Gee (michael@linuxspecific.com)
+ */
+
+#ifndef __LINUX_USB_USUAL_H
+#define __LINUX_USB_USUAL_H
+
+#include <linux/config.h>
+
+/* We should do this for cleanliness... But other usb_foo.h do not do this. */
+/* #include <linux/usb.h> */
+
+/*
+ * The flags field, which we store in usb_device_id.driver_info.
+ * It is compatible with the old usb-storage flags in lower 24 bits.
+ */
+
+/*
+ * Static flag definitions. We use this roundabout technique so that the
+ * proc_info() routine can automatically display a message for each flag.
+ */
+#define US_DO_ALL_FLAGS \
+ US_FLAG(SINGLE_LUN, 0x00000001) \
+ /* allow access to only LUN 0 */ \
+ US_FLAG(NEED_OVERRIDE, 0x00000002) \
+ /* unusual_devs entry is necessary */ \
+ US_FLAG(SCM_MULT_TARG, 0x00000004) \
+ /* supports multiple targets */ \
+ US_FLAG(FIX_INQUIRY, 0x00000008) \
+ /* INQUIRY response needs faking */ \
+ US_FLAG(FIX_CAPACITY, 0x00000010) \
+ /* READ CAPACITY response too big */ \
+ US_FLAG(IGNORE_RESIDUE, 0x00000020) \
+ /* reported residue is wrong */ \
+ US_FLAG(BULK32, 0x00000040) \
+ /* Uses 32-byte CBW length */ \
+ US_FLAG(NOT_LOCKABLE, 0x00000080) \
+ /* PREVENT/ALLOW not supported */ \
+ US_FLAG(GO_SLOW, 0x00000100) \
+ /* Need delay after Command phase */ \
+ US_FLAG(NO_WP_DETECT, 0x00000200) \
+ /* Don't check for write-protect */ \
+
+#define US_FLAG(name, value) US_FL_##name = value ,
+enum { US_DO_ALL_FLAGS };
+#undef US_FLAG
+
+/*
+ * The bias field for libusual and friends.
+ */
+#define USB_US_TYPE_NONE 0
+#define USB_US_TYPE_STOR 1 /* usb-storage */
+#define USB_US_TYPE_UB 2 /* ub */
+
+#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF)
+#define USB_US_ORIG_FLAGS(flags) ((flags) & 0x00FFFFFF)
+
+/*
+ * This is probably not the best place to keep these constants, conceptually.
+ * But it's the only header included into all places which need them.
+ */
+
+/* Sub Classes */
+
+#define US_SC_RBC 0x01 /* Typically, flash devices */
+#define US_SC_8020 0x02 /* CD-ROM */
+#define US_SC_QIC 0x03 /* QIC-157 Tapes */
+#define US_SC_UFI 0x04 /* Floppy */
+#define US_SC_8070 0x05 /* Removable media */
+#define US_SC_SCSI 0x06 /* Transparent */
+#define US_SC_ISD200 0x07 /* ISD200 ATA */
+#define US_SC_MIN US_SC_RBC
+#define US_SC_MAX US_SC_ISD200
+
+#define US_SC_DEVICE 0xff /* Use device's value */
+
+/* Protocols */
+
+#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
+#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
+#define US_PR_BULK 0x50 /* bulk only */
+#ifdef CONFIG_USB_STORAGE_USBAT
+#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR09
+#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR55
+#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */
+#endif
+#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
+#ifdef CONFIG_USB_STORAGE_FREECOM
+#define US_PR_FREECOM 0xf1 /* Freecom */
+#endif
+#ifdef CONFIG_USB_STORAGE_DATAFAB
+#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
+#endif
+#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
+#endif
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+#define US_PR_ALAUDA 0xf4 /* Alauda chipsets */
+#endif
+
+#define US_PR_DEVICE 0xff /* Use device's value */
+
+/*
+ */
+#ifdef CONFIG_USB_LIBUSUAL
+
+extern struct usb_device_id storage_usb_ids[];
+extern void usb_usual_set_present(int type);
+extern void usb_usual_clear_present(int type);
+extern int usb_usual_check_type(const struct usb_device_id *, int type);
+#else
+
+#define usb_usual_set_present(t) do { } while(0)
+#define usb_usual_clear_present(t) do { } while(0)
+#define usb_usual_check_type(id, t) (0)
+#endif /* CONFIG_USB_LIBUSUAL */
+
+#endif /* __LINUX_USB_USUAL_H */
diff --git a/include/linux/video_decoder.h b/include/linux/video_decoder.h
index 0e9e48b83e3b..121e26da2c18 100644
--- a/include/linux/video_decoder.h
+++ b/include/linux/video_decoder.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_VIDEO_DECODER_H
#define _LINUX_VIDEO_DECODER_H
+#define HAVE_VIDEO_DECODER 1
+
struct video_decoder_capability { /* this name is too long */
__u32 flags;
#define VIDEO_DECODER_PAL 1 /* can decode PAL signal */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 1cded681eb6d..ce40675324bd 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -642,6 +642,12 @@ typedef __u64 v4l2_std_id;
#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
+/* some merged standards */
+#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
+#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
+#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
+#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
+
/* some common needed stuff */
#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\
V4L2_STD_PAL_B1 |\
@@ -662,7 +668,8 @@ typedef __u64 v4l2_std_id;
V4L2_STD_SECAM_G |\
V4L2_STD_SECAM_H |\
V4L2_STD_SECAM_DK |\
- V4L2_STD_SECAM_L)
+ V4L2_STD_SECAM_L |\
+ V4L2_STD_SECAM_LC)
#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\
V4L2_STD_PAL_60 |\
@@ -888,7 +895,6 @@ struct v4l2_audio
/* Flags for the 'mode' field */
#define V4L2_AUDMODE_AVL 0x00001
-#define V4L2_AUDMODE_32BITS 0x00002
struct v4l2_audioout
{
@@ -1110,7 +1116,6 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
/* names for fancy debug output */
extern char *v4l2_field_names[];
extern char *v4l2_type_names[];
-extern char *v4l2_ioctl_names[];
/* Compatibility layer interface -- v4l1-compat module */
typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
@@ -1118,6 +1123,11 @@ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
int cmd, void *arg, v4l2_kioctl driver_ioctl);
+/* 32 Bits compatibility layer for 64 bits processors */
+extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+ unsigned long arg);
+
+
#endif /* __KERNEL__ */
#endif /* __LINUX_VIDEODEV2_H */
diff --git a/include/linux/wavefront.h b/include/linux/wavefront.h
index 61bd0fd35240..51ab3c933acd 100644
--- a/include/linux/wavefront.h
+++ b/include/linux/wavefront.h
@@ -434,22 +434,22 @@ typedef struct wf_multisample {
} wavefront_multisample;
typedef struct wf_alias {
- INT16 OriginalSample __attribute__ ((packed));
-
- struct wf_sample_offset sampleStartOffset __attribute__ ((packed));
- struct wf_sample_offset loopStartOffset __attribute__ ((packed));
- struct wf_sample_offset sampleEndOffset __attribute__ ((packed));
- struct wf_sample_offset loopEndOffset __attribute__ ((packed));
-
- INT16 FrequencyBias __attribute__ ((packed));
-
- UCHAR8 SampleResolution:2 __attribute__ ((packed));
- UCHAR8 Unused1:1 __attribute__ ((packed));
- UCHAR8 Loop:1 __attribute__ ((packed));
- UCHAR8 Bidirectional:1 __attribute__ ((packed));
- UCHAR8 Unused2:1 __attribute__ ((packed));
- UCHAR8 Reverse:1 __attribute__ ((packed));
- UCHAR8 Unused3:1 __attribute__ ((packed));
+ INT16 OriginalSample;
+
+ struct wf_sample_offset sampleStartOffset;
+ struct wf_sample_offset loopStartOffset;
+ struct wf_sample_offset sampleEndOffset;
+ struct wf_sample_offset loopEndOffset;
+
+ INT16 FrequencyBias;
+
+ UCHAR8 SampleResolution:2;
+ UCHAR8 Unused1:1;
+ UCHAR8 Loop:1;
+ UCHAR8 Bidirectional:1;
+ UCHAR8 Unused2:1;
+ UCHAR8 Reverse:1;
+ UCHAR8 Unused3:1;
/* This structure is meant to be padded only to 16 bits on their
original. Of course, whoever wrote their documentation didn't
@@ -460,8 +460,8 @@ typedef struct wf_alias {
standard 16->32 bit issues.
*/
- UCHAR8 sixteen_bit_padding __attribute__ ((packed));
-} wavefront_alias;
+ UCHAR8 sixteen_bit_padding;
+} __attribute__((packed)) wavefront_alias;
typedef struct wf_drum {
UCHAR8 PatchNumber;
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index ac39d04d027c..86b111300231 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -65,6 +65,7 @@ extern int FASTCALL(schedule_work(struct work_struct *work));
extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay);
+extern int schedule_on_each_cpu(void (*func)(void *info), void *info);
extern void flush_scheduled_work(void);
extern int current_is_keventd(void);
extern int keventd_up(void);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 343d883d69c5..beaef5c7a0ea 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -53,19 +53,14 @@ struct writeback_control {
loff_t start;
loff_t end;
- unsigned nonblocking:1; /* Don't get stuck on request queues */
- unsigned encountered_congestion:1; /* An output: a queue is full */
- unsigned for_kupdate:1; /* A kupdate writeback */
- unsigned for_reclaim:1; /* Invoked from the page allocator */
+ unsigned nonblocking:1; /* Don't get stuck on request queues */
+ unsigned encountered_congestion:1; /* An output: a queue is full */
+ unsigned for_kupdate:1; /* A kupdate writeback */
+ unsigned for_reclaim:1; /* Invoked from the page allocator */
+ unsigned for_writepages:1; /* This is a writepages() call */
};
/*
- * ->writepage() return values (make these much larger than a pagesize, in
- * case some fs is returning number-of-bytes-written from writepage)
- */
-#define WRITEPAGE_ACTIVATE 0x80000 /* IO was not started: activate page */
-
-/*
* fs/fs-writeback.c
*/
void writeback_inodes(struct writeback_control *wbc);
@@ -108,7 +103,9 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping);
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);
+ loff_t pos, loff_t count);
+int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
+ loff_t pos, loff_t count);
/* pdflush.c */
extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 23f9c61d9546..cda8a96e2fa0 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -13,7 +13,22 @@
#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
+/* Namespaces */
+#define XATTR_OS2_PREFIX "os2."
+#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
+
#define XATTR_SECURITY_PREFIX "security."
+#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
+
+#define XATTR_SYSTEM_PREFIX "system."
+#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
+
+#define XATTR_USER_PREFIX "user."
+#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
+
struct xattr_handler {
char *prefix;
@@ -25,6 +40,10 @@ struct xattr_handler {
size_t size, int flags);
};
+ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
+int vfs_removexattr(struct dentry *, char *);
+
ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 0fb077d68441..82fbb758e28f 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -27,6 +27,22 @@ struct xfrm_id
__u8 proto;
};
+struct xfrm_sec_ctx {
+ __u8 ctx_doi;
+ __u8 ctx_alg;
+ __u16 ctx_len;
+ __u32 ctx_sid;
+ char ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
/* Selector, used as selector both on policy rules (SPD) and SAs. */
struct xfrm_selector
@@ -146,6 +162,18 @@ enum {
#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+ __u16 len;
+ __u16 exttype;
+ __u8 ctx_alg; /* LSMs: e.g., selinux == 1 */
+ __u8 ctx_doi;
+ __u16 ctx_len;
+};
+
struct xfrm_user_tmpl {
struct xfrm_id id;
__u16 family;
@@ -176,6 +204,7 @@ enum xfrm_attr_type_t {
XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
XFRMA_SA,
XFRMA_POLICY,
+ XFRMA_SEC_CTX, /* struct xfrm_sec_ctx */
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 74f7b78c22d2..4fa32f0d4df8 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -442,9 +442,11 @@ extern int deflateInit2 (z_streamp strm,
not perform any compression: this will be done by deflate().
*/
+#if 0
extern int zlib_deflateSetDictionary (z_streamp strm,
const Byte *dictionary,
uInt dictLength);
+#endif
/*
Initializes the compression dictionary from the given byte sequence
without producing any compressed output. This function must be called
@@ -478,7 +480,10 @@ extern int zlib_deflateSetDictionary (z_streamp strm,
perform any compression: this will be done by deflate().
*/
+#if 0
extern int zlib_deflateCopy (z_streamp dest, z_streamp source);
+#endif
+
/*
Sets the destination stream as a complete copy of the source stream.
@@ -511,7 +516,9 @@ static inline unsigned long deflateBound(unsigned long s)
return s + ((s + 7) >> 3) + ((s + 63) >> 6) + 11;
}
+#if 0
extern int zlib_deflateParams (z_streamp strm, int level, int strategy);
+#endif
/*
Dynamically update the compression level and compression strategy. The
interpretation of level and strategy is as in deflateInit2. This can be
@@ -571,7 +578,9 @@ extern int zlib_inflateSetDictionary (z_streamp strm,
inflate().
*/
+#if 0
extern int zlib_inflateSync (z_streamp strm);
+#endif
/*
Skips invalid compressed data until a full flush point (see above the
description of deflate with Z_FULL_FLUSH) can be found, or until all
@@ -636,7 +645,9 @@ extern int zlib_inflateInit2_ (z_streamp strm, int windowBits,
#endif
extern const char * zlib_zError (int err);
+#if 0
extern int zlib_inflateSyncPoint (z_streamp z);
+#endif
extern const uLong * zlib_get_crc_table (void);
#endif /* _ZLIB_H */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index b7d4b0930408..295d256ee811 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -23,11 +23,6 @@ enum audiochip {
/* ---------------------------------------------------------------------- */
-/* v4l device was opened in Radio mode */
-#define AUDC_SET_RADIO _IO('m',2)
-/* select from TV,radio,extern,MUTE */
-#define AUDC_SET_INPUT _IOW('m',17,int)
-
/* audio inputs */
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
@@ -40,15 +35,4 @@ enum audiochip {
#define AUDIO_MUTE 0x80
#define AUDIO_UNMUTE 0x81
-/* all the stuff below is obsolete and just here for reference. I'll
- * remove it once the driver is tested and works fine.
- *
- * Instead creating alot of tiny API's for all kinds of different
- * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not
- * yet...). It is a bit less flexible, but most/all used i2c chips
- * make sense in v4l context only. So I think that's acceptable...
- */
-
-/* misc stuff to pass around config info to i2c chips */
-#define AUDC_CONFIG_PINNACLE _IOW('m',32,int)
#endif /* AUDIOCHIP_H */
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index e5be2b9b846b..2bc634fcb7bb 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -21,14 +21,14 @@
extern unsigned int saa7146_debug;
-//#define DEBUG_PROLOG printk("(0x%08x)(0x%08x) %s: %s(): ",(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,RPS_ADDR0))),(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,IER))),__stringify(KBUILD_MODNAME),__FUNCTION__)
+//#define DEBUG_PROLOG printk("(0x%08x)(0x%08x) %s: %s(): ",(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,RPS_ADDR0))),(dev==0?-1:(dev->mem==0?-1:saa7146_read(dev,IER))),KBUILD_MODNAME,__FUNCTION__)
#ifndef DEBUG_VARIABLE
#define DEBUG_VARIABLE saa7146_debug
#endif
-#define DEBUG_PROLOG printk("%s: %s(): ",__stringify(KBUILD_MODNAME),__FUNCTION__)
-#define INFO(x) { printk("%s: ",__stringify(KBUILD_MODNAME)); printk x; }
+#define DEBUG_PROLOG printk("%s: %s(): ",KBUILD_MODNAME,__FUNCTION__)
+#define INFO(x) { printk("%s: ",KBUILD_MODNAME); printk x; }
#define ERR(x) { DEBUG_PROLOG; printk x; }
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index 16af9299315f..e5e749e984ee 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -178,6 +178,8 @@ struct saa7146_ext_vv
struct saa7146_extension_ioctls *ioctls;
int (*ioctl)(struct saa7146_fh*, unsigned int cmd, void *arg);
+
+ struct file_operations vbi_fops;
};
struct saa7146_use_ops {
diff --git a/include/media/tuner-types.h b/include/media/tuner-types.h
new file mode 100644
index 000000000000..15821ab14a9e
--- /dev/null
+++ b/include/media/tuner-types.h
@@ -0,0 +1,55 @@
+/*
+ * descriptions for simple tuners.
+ */
+
+#ifndef __TUNER_TYPES_H__
+#define __TUNER_TYPES_H__
+
+enum param_type {
+ TUNER_PARAM_TYPE_RADIO, \
+ TUNER_PARAM_TYPE_PAL, \
+ TUNER_PARAM_TYPE_SECAM, \
+ TUNER_PARAM_TYPE_NTSC
+};
+
+struct tuner_range {
+ unsigned short limit;
+ unsigned char cb;
+};
+
+struct tuner_params {
+ enum param_type type;
+ /* Many Philips based tuners have a comment like this in their
+ * datasheet:
+ *
+ * For channel selection involving band switching, and to ensure
+ * smooth tuning to the desired channel without causing
+ * unnecessary charge pump action, it is recommended to consider
+ * the difference between wanted channel frequency and the
+ * current channel frequency. Unnecessary charge pump action
+ * will result in very low tuning voltage which may drive the
+ * oscillator to extreme conditions.
+ *
+ * Set cb_first_if_lower_freq to 1, if this check is
+ * required for this tuner.
+ *
+ * I tested this for PAL by first setting the TV frequency to
+ * 203 MHz and then switching to 96.6 MHz FM radio. The result was
+ * static unless the control byte was sent first.
+ */
+ unsigned int cb_first_if_lower_freq:1;
+ unsigned char config; /* to be moved into struct tuner_range for dvb-pll merge */
+
+ unsigned int count;
+ struct tuner_range *ranges;
+};
+
+struct tunertype {
+ char *name;
+ struct tuner_params *params;
+};
+
+extern struct tunertype tuners[];
+extern unsigned const int tuner_count;
+
+#endif
diff --git a/include/media/tuner.h b/include/media/tuner.h
index faa0f8e3091b..a5beeac495c7 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -23,6 +23,7 @@
#define _TUNER_H
#include <linux/videodev2.h>
+#include <media/tuner-types.h>
#define ADDR_UNSET (255)
@@ -82,9 +83,9 @@
#define TUNER_PHILIPS_FM1236_MK3 43
#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 */
+/* Microtune merged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
#define TUNER_MICROTUNE_4049FM5 45
-#define TUNER_MICROTUNE_4042_FI5 46
+#define TUNER_PANASONIC_VP27 46
#define TUNER_LG_NTSC_TAPE 47
#define TUNER_TNF_8831BGFF 48
@@ -102,7 +103,7 @@
#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_THOMSON_DTT761X 60 /* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
#define TUNER_TENA_9533_DI 61
#define TUNER_TEA5767 62 /* Only FM Radio Tuner */
#define TUNER_PHILIPS_FMD1216ME_MK3 63
@@ -114,48 +115,28 @@
#define TUNER_PHILIPS_TUV1236D 68 /* ATI HDTV Wonder */
#define TUNER_TNF_5335MF 69 /* Sabrent Bt848 */
-
-#define NOTUNER 0
-#define PAL 1 /* PAL_BG */
-#define PAL_I 2
-#define NTSC 3
-#define SECAM 4
-#define ATSC 5
-#define RADIO 6
-
-#define NoTuner 0
-#define Philips 1
-#define TEMIC 2
-#define Sony 3
-#define Alps 4
-#define LGINNOTEK 5
-#define SHARP 6
-#define Samsung 7
-#define Microtune 8
-#define HITACHI 9
-#define Panasonic 10
-#define TCL 11
-#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)
+#define TUNER_SAMSUNG_TCPN_2121P30A 70 /* Hauppauge PVR-500MCE NTSC */
/* tv card specific */
-# define TDA9887_PRESENT (1<<0)
-# define TDA9887_PORT1_INACTIVE (1<<1)
-# define TDA9887_PORT2_INACTIVE (1<<2)
-# define TDA9887_QSS (1<<3)
-# define TDA9887_INTERCARRIER (1<<4)
-# define TDA9887_PORT1_ACTIVE (1<<5)
-# define TDA9887_PORT2_ACTIVE (1<<6)
-# define TDA9887_INTERCARRIER_NTSC (1<<7)
+#define TDA9887_PRESENT (1<<0)
+#define TDA9887_PORT1_INACTIVE (1<<1)
+#define TDA9887_PORT2_INACTIVE (1<<2)
+#define TDA9887_QSS (1<<3)
+#define TDA9887_INTERCARRIER (1<<4)
+#define TDA9887_PORT1_ACTIVE (1<<5)
+#define TDA9887_PORT2_ACTIVE (1<<6)
+#define TDA9887_INTERCARRIER_NTSC (1<<7)
+/* Tuner takeover point adjustment, in dB, -16 <= top <= 15 */
+#define TDA9887_TOP_MASK (0x3f << 8)
+#define TDA9887_TOP_SET (1 << 13)
+#define TDA9887_TOP(top) (TDA9887_TOP_SET | (((16 + (top)) & 0x1f) << 8))
+
/* config options */
-# define TDA9887_DEEMPHASIS_MASK (3<<16)
-# define TDA9887_DEEMPHASIS_NONE (1<<16)
-# define TDA9887_DEEMPHASIS_50 (2<<16)
-# define TDA9887_DEEMPHASIS_75 (3<<16)
-# define TDA9887_AUTOMUTE (1<<18)
+#define TDA9887_DEEMPHASIS_MASK (3<<16)
+#define TDA9887_DEEMPHASIS_NONE (1<<16)
+#define TDA9887_DEEMPHASIS_50 (2<<16)
+#define TDA9887_DEEMPHASIS_75 (3<<16)
+#define TDA9887_AUTOMUTE (1<<18)
#ifdef __KERNEL__
@@ -167,10 +148,26 @@ enum tuner_mode {
T_STANDBY = 1 << 31
};
+/* Older boards only had a single tuner device. Nowadays multiple tuner
+ devices may be present on a single board. Using TUNER_SET_TYPE_ADDR
+ to pass the tuner_setup structure it is possible to setup each tuner
+ device in turn.
+
+ Since multiple devices may be present it is no longer sufficient to
+ send a command to a single i2c device. Instead you should broadcast
+ the command to all i2c devices.
+
+ By setting the mode_mask correctly you can select which commands are
+ accepted by a specific tuner device. For example, set mode_mask to
+ T_RADIO if the device is a radio-only tuner. That specific tuner will
+ only accept commands when the tuner is in radio mode and ignore them
+ when the tuner is set to TV mode.
+ */
+
struct tuner_setup {
- unsigned short addr;
- unsigned int type;
- unsigned int mode_mask;
+ unsigned short addr; /* I2C address */
+ unsigned int type; /* Tuner type */
+ unsigned int mode_mask; /* Allowed tuner modes */
};
struct tuner {
@@ -182,7 +179,9 @@ struct tuner {
unsigned int mode;
unsigned int mode_mask; /* Combination of allowable modes */
- unsigned int freq; /* keep track of the current settings */
+ unsigned int tv_freq; /* keep track of the current settings */
+ unsigned int radio_freq;
+ u16 last_div;
unsigned int audmode;
v4l2_std_id std;
@@ -200,14 +199,13 @@ struct tuner {
unsigned int sgIF;
/* function ptrs */
- void (*tv_freq)(struct i2c_client *c, unsigned int freq);
- void (*radio_freq)(struct i2c_client *c, unsigned int freq);
+ void (*set_tv_freq)(struct i2c_client *c, unsigned int freq);
+ void (*set_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;
extern unsigned const int tuner_count;
extern int microtune_init(struct i2c_client *c);
@@ -218,15 +216,16 @@ extern int default_tuner_init(struct i2c_client *c);
extern int tea5767_autodetection(struct i2c_client *c);
#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)
+ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), 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)
+ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
#define tuner_dbg(fmt, arg...) do {\
+ extern int tuner_debug; \
if (tuner_debug) \
- printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \
- t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0)
+ printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
+ i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
#endif /* __KERNEL__ */
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index d3fd48157eb8..d4030a7e16e0 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -26,12 +26,56 @@
#ifndef V4L2_COMMON_H_
#define V4L2_COMMON_H_
-/* VIDIOC_INT_AUDIO_CLOCK_FREQ */
-enum v4l2_audio_clock_freq {
- V4L2_AUDCLK_32_KHZ = 32000,
- V4L2_AUDCLK_441_KHZ = 44100,
- V4L2_AUDCLK_48_KHZ = 48000,
-};
+/* v4l debugging and diagnostics */
+
+/* Common printk constucts for v4l-i2c drivers. These macros create a unique
+ prefix consisting of the driver name, the adapter number and the i2c
+ address. */
+#define v4l_printk(level, name, adapter, addr, fmt, arg...) \
+ printk(level "%s %d-%04x: " fmt, name, i2c_adapter_id(adapter), addr , ## arg)
+
+#define v4l_client_printk(level, client, fmt, arg...) \
+ v4l_printk(level, (client)->driver->driver.name, (client)->adapter, \
+ (client)->addr, fmt , ## arg)
+
+#define v4l_err(client, fmt, arg...) \
+ v4l_client_printk(KERN_ERR, client, fmt , ## arg)
+
+#define v4l_warn(client, fmt, arg...) \
+ v4l_client_printk(KERN_WARNING, client, fmt , ## arg)
+
+#define v4l_info(client, fmt, arg...) \
+ v4l_client_printk(KERN_INFO, client, fmt , ## arg)
+
+/* These three macros assume that the debug level is set with a module
+ parameter called 'debug'. */
+#define v4l_dbg(level, debug, client, fmt, arg...) \
+ do { \
+ if (debug >= (level)) \
+ v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \
+ } while (0)
+
+/* Prints the ioctl in a human-readable format */
+extern void v4l_printk_ioctl(unsigned int cmd);
+
+/* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */
+#define v4l_print_ioctl(name, cmd) \
+ do { \
+ printk(KERN_DEBUG "%s: ", name); \
+ v4l_printk_ioctl(cmd); \
+ } while (0)
+
+/* Use this macro in I2C drivers where 'client' is the struct i2c_client
+ pointer */
+#define v4l_i2c_print_ioctl(client, cmd) \
+ do { \
+ v4l_client_printk(KERN_DEBUG, client, ""); \
+ v4l_printk_ioctl(cmd); \
+ } while (0)
+
+/* ------------------------------------------------------------------------- */
+
+/* Internal ioctls */
/* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
struct v4l2_register {
@@ -70,6 +114,27 @@ enum v4l2_chip_ident {
V4L2_IDENT_CX25843 = 243,
};
+/* audio ioctls */
+/* v4l device was opened in Radio mode */
+#define AUDC_SET_RADIO _IO('d',88)
+/* select from TV,radio,extern,MUTE */
+#define AUDC_SET_INPUT _IOW('d',89,int)
+
+/* msp3400 ioctl: will be removed in the near future */
+struct msp_matrix {
+ int input;
+ int output;
+};
+#define MSP_SET_MATRIX _IOW('m',17,struct msp_matrix)
+
+/* tuner ioctls */
+/* Sets tuner type and its I2C addr */
+#define TUNER_SET_TYPE_ADDR _IOW('d',90,int)
+/* Puts tuner on powersaving state, disabling it, except for i2c */
+#define TUNER_SET_STANDBY _IOW('d',91,int)
+/* Sets tda9887 specific stuff, like port1, port2 and qss */
+#define TDA9887_SET_CONFIG _IOW('d',92,int)
+
/* only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */
#define VIDIOC_INT_S_REGISTER _IOR ('d', 100, struct v4l2_register)
#define VIDIOC_INT_G_REGISTER _IOWR('d', 101, struct v4l2_register)
@@ -77,10 +142,12 @@ enum v4l2_chip_ident {
/* Reset the I2C chip */
#define VIDIOC_INT_RESET _IO ('d', 102)
-/* Set the frequency of the audio clock output.
+/* Set the frequency (in Hz) of the audio clock output.
Used to slave an audio processor to the video decoder, ensuring that audio
- and video remain synchronized. */
-#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOR ('d', 103, enum v4l2_audio_clock_freq)
+ and video remain synchronized.
+ Usual values for the frequency are 48000, 44100 or 32000 Hz.
+ If the frequency is not supported, then -EINVAL is returned. */
+#define VIDIOC_INT_AUDIO_CLOCK_FREQ _IOW ('d', 103, u32)
/* Video decoders that support sliced VBI need to implement this ioctl.
Field p of the v4l2_sliced_vbi_line struct is set to the start of the VBI
@@ -107,4 +174,10 @@ enum v4l2_chip_ident {
be made. */
#define VIDIOC_INT_G_CHIP_IDENT _IOR ('d', 107, enum v4l2_chip_ident *)
+/* Sets I2S speed in bps. This is used to provide a standard way to select I2S
+ clock used by driving digital audio streams at some board designs.
+ Usual values for the frequency are 1024000 and 2048000.
+ If the frequency is not supported, then -EINVAL is returned. */
+#define VIDIOC_INT_I2S_CLOCK_FREQ _IOW ('d', 108, u32)
+
#endif /* V4L2_COMMON_H_ */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index b55eb7c7f033..11e9eaf79f5a 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 *, struct tcf_result *);
+ 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/af_unix.h b/include/net/af_unix.h
index b5d785ab4a0e..bfc1779fc753 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -13,7 +13,7 @@ extern void unix_gc(void);
#define UNIX_HASH_SIZE 256
extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
-extern rwlock_t unix_table_lock;
+extern spinlock_t unix_table_lock;
extern atomic_t unix_tot_inflight;
@@ -58,10 +58,10 @@ struct unix_skb_parms {
#define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb))
#define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
-#define unix_state_rlock(s) read_lock(&unix_sk(s)->lock)
-#define unix_state_runlock(s) read_unlock(&unix_sk(s)->lock)
-#define unix_state_wlock(s) write_lock(&unix_sk(s)->lock)
-#define unix_state_wunlock(s) write_unlock(&unix_sk(s)->lock)
+#define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock)
+#define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock)
+#define unix_state_wlock(s) spin_lock(&unix_sk(s)->lock)
+#define unix_state_wunlock(s) spin_unlock(&unix_sk(s)->lock)
#ifdef __KERNEL__
/* The AF_UNIX socket */
@@ -76,7 +76,7 @@ struct unix_sock {
struct sock *other;
struct sock *gc_tree;
atomic_t inflight;
- rwlock_t lock;
+ spinlock_t lock;
wait_queue_head_t peer_wait;
};
#define unix_sk(__sk) ((struct unix_sock *)__sk)
diff --git a/include/net/atmclip.h b/include/net/atmclip.h
index 47048b1d179a..90fcc98e676f 100644
--- a/include/net/atmclip.h
+++ b/include/net/atmclip.h
@@ -7,7 +7,6 @@
#define _ATMCLIP_H
#include <linux/netdevice.h>
-#include <linux/skbuff.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmarp.h>
@@ -18,6 +17,7 @@
#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back))
#define NEIGH2ENTRY(neigh) ((struct atmarp_entry *) (neigh)->primary_key)
+struct sk_buff;
struct clip_vcc {
struct atm_vcc *vcc; /* VCC descriptor */
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index 86e8e86e624a..5a86e78081bf 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -88,8 +88,8 @@ struct dn_dev {
struct net_device *dev;
struct dn_dev_parms parms;
char use_long;
- struct timer_list timer;
- unsigned long t3;
+ struct timer_list timer;
+ unsigned long t3;
struct neigh_parms *neigh_parms;
unsigned char addr[ETH_ALEN];
struct neighbour *router; /* Default router on circuit */
@@ -99,57 +99,57 @@ struct dn_dev {
struct dn_short_packet
{
- unsigned char msgflg __attribute__((packed));
- unsigned short dstnode __attribute__((packed));
- unsigned short srcnode __attribute__((packed));
- unsigned char forward __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned short dstnode;
+ unsigned short srcnode;
+ unsigned char forward;
+} __attribute__((packed));
struct dn_long_packet
{
- unsigned char msgflg __attribute__((packed));
- unsigned char d_area __attribute__((packed));
- unsigned char d_subarea __attribute__((packed));
- unsigned char d_id[6] __attribute__((packed));
- unsigned char s_area __attribute__((packed));
- unsigned char s_subarea __attribute__((packed));
- unsigned char s_id[6] __attribute__((packed));
- unsigned char nl2 __attribute__((packed));
- unsigned char visit_ct __attribute__((packed));
- unsigned char s_class __attribute__((packed));
- unsigned char pt __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned char d_area;
+ unsigned char d_subarea;
+ unsigned char d_id[6];
+ unsigned char s_area;
+ unsigned char s_subarea;
+ unsigned char s_id[6];
+ unsigned char nl2;
+ unsigned char visit_ct;
+ unsigned char s_class;
+ unsigned char pt;
+} __attribute__((packed));
/*------------------------- DRP - Routing messages ---------------------*/
struct endnode_hello_message
{
- unsigned char msgflg __attribute__((packed));
- unsigned char tiver[3] __attribute__((packed));
- unsigned char id[6] __attribute__((packed));
- unsigned char iinfo __attribute__((packed));
- unsigned short blksize __attribute__((packed));
- unsigned char area __attribute__((packed));
- unsigned char seed[8] __attribute__((packed));
- unsigned char neighbor[6] __attribute__((packed));
- unsigned short timer __attribute__((packed));
- unsigned char mpd __attribute__((packed));
- unsigned char datalen __attribute__((packed));
- unsigned char data[2] __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned char tiver[3];
+ unsigned char id[6];
+ unsigned char iinfo;
+ unsigned short blksize;
+ unsigned char area;
+ unsigned char seed[8];
+ unsigned char neighbor[6];
+ unsigned short timer;
+ unsigned char mpd;
+ unsigned char datalen;
+ unsigned char data[2];
+} __attribute__((packed));
struct rtnode_hello_message
{
- unsigned char msgflg __attribute__((packed));
- unsigned char tiver[3] __attribute__((packed));
- unsigned char id[6] __attribute__((packed));
- unsigned char iinfo __attribute__((packed));
- unsigned short blksize __attribute__((packed));
- unsigned char priority __attribute__((packed));
- unsigned char area __attribute__((packed));
- unsigned short timer __attribute__((packed));
- unsigned char mpd __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned char tiver[3];
+ unsigned char id[6];
+ unsigned char iinfo;
+ unsigned short blksize;
+ unsigned char priority;
+ unsigned char area;
+ unsigned short timer;
+ unsigned char mpd;
+} __attribute__((packed));
extern void dn_dev_init(void);
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
index 1ba03be0af3a..e6182b86262b 100644
--- a/include/net/dn_nsp.h
+++ b/include/net/dn_nsp.h
@@ -72,78 +72,78 @@ extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int nobl
struct nsp_data_seg_msg
{
- unsigned char msgflg __attribute__((packed));
- unsigned short dstaddr __attribute__((packed));
- unsigned short srcaddr __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned short dstaddr;
+ unsigned short srcaddr;
+} __attribute__((packed));
struct nsp_data_opt_msg
{
- unsigned short acknum __attribute__((packed));
- unsigned short segnum __attribute__((packed));
- unsigned short lsflgs __attribute__((packed));
-};
+ unsigned short acknum;
+ unsigned short segnum;
+ unsigned short lsflgs;
+} __attribute__((packed));
struct nsp_data_opt_msg1
{
- unsigned short acknum __attribute__((packed));
- unsigned short segnum __attribute__((packed));
-};
+ unsigned short acknum;
+ unsigned short segnum;
+} __attribute__((packed));
/* Acknowledgment Message (data/other data) */
struct nsp_data_ack_msg
{
- unsigned char msgflg __attribute__((packed));
- unsigned short dstaddr __attribute__((packed));
- unsigned short srcaddr __attribute__((packed));
- unsigned short acknum __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned short dstaddr;
+ unsigned short srcaddr;
+ unsigned short acknum;
+} __attribute__((packed));
/* Connect Acknowledgment Message */
struct nsp_conn_ack_msg
{
- unsigned char msgflg __attribute__((packed));
- unsigned short dstaddr __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned short dstaddr;
+} __attribute__((packed));
/* Connect Initiate/Retransmit Initiate/Connect Confirm */
struct nsp_conn_init_msg
{
- unsigned char msgflg __attribute__((packed));
+ unsigned char msgflg;
#define NSP_CI 0x18 /* Connect Initiate */
#define NSP_RCI 0x68 /* Retrans. Conn Init */
- unsigned short dstaddr __attribute__((packed));
- unsigned short srcaddr __attribute__((packed));
- unsigned char services __attribute__((packed));
+ unsigned short dstaddr;
+ unsigned short srcaddr;
+ unsigned char services;
#define NSP_FC_NONE 0x00 /* Flow Control None */
#define NSP_FC_SRC 0x04 /* Seg Req. Count */
#define NSP_FC_SCMC 0x08 /* Sess. Control Mess */
#define NSP_FC_MASK 0x0c /* FC type mask */
- unsigned char info __attribute__((packed));
- unsigned short segsize __attribute__((packed));
-};
+ unsigned char info;
+ unsigned short segsize;
+} __attribute__((packed));
/* Disconnect Initiate/Disconnect Confirm */
struct nsp_disconn_init_msg
{
- unsigned char msgflg __attribute__((packed));
- unsigned short dstaddr __attribute__((packed));
- unsigned short srcaddr __attribute__((packed));
- unsigned short reason __attribute__((packed));
-};
+ unsigned char msgflg;
+ unsigned short dstaddr;
+ unsigned short srcaddr;
+ unsigned short reason;
+} __attribute__((packed));
struct srcobj_fmt
{
- char format __attribute__((packed));
- unsigned char task __attribute__((packed));
- unsigned short grpcode __attribute__((packed));
- unsigned short usrcode __attribute__((packed));
- char dlen __attribute__((packed));
-};
+ char format;
+ unsigned char task;
+ unsigned short grpcode;
+ unsigned short usrcode;
+ char dlen;
+} __attribute__((packed));
/*
* A collection of functions for manipulating the sequence
diff --git a/include/net/dst.h b/include/net/dst.h
index 6c196a5baf24..5161e89017f9 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -9,6 +9,7 @@
#define _NET_DST_H
#include <linux/config.h>
+#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <linux/jiffies.h>
@@ -224,16 +225,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
/* Output packet to network from transport. */
static inline int dst_output(struct sk_buff *skb)
{
- int err;
-
- for (;;) {
- err = skb->dst->output(skb);
-
- if (likely(err == 0))
- return err;
- if (unlikely(err != NET_XMIT_BYPASS))
- return err;
- }
+ return skb->dst->output(skb);
}
/* Input packet from network to transport. */
diff --git a/include/net/flow.h b/include/net/flow.h
index 9a5c94b1a0ec..ec7eb86eb203 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -84,11 +84,12 @@ struct flowi {
#define FLOW_DIR_OUT 1
#define FLOW_DIR_FWD 2
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+struct sock;
+typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
void **objp, atomic_t **obj_refp);
-extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
- flow_resolve_t resolver);
+extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
+ flow_resolve_t resolver);
extern void flow_cache_flush(void);
extern atomic_t flow_cache_genid;
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 52d8b1a73d52..805de50df00d 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -22,7 +22,6 @@ struct genl_family
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
- struct module * owner;
struct nlattr ** attrbuf; /* private */
struct list_head ops_list; /* private */
struct list_head family_list; /* private */
@@ -60,7 +59,7 @@ struct genl_info
*/
struct genl_ops
{
- unsigned int cmd;
+ u8 cmd;
unsigned int flags;
struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 6cdebeee5f96..e7c3f20fbafc 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -20,12 +20,9 @@
#include <linux/config.h>
#include <linux/icmp.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/protocol.h>
+#include <net/inet_sock.h>
#include <net/snmp.h>
-#include <linux/ip.h>
struct icmp_err {
int errno;
@@ -38,6 +35,10 @@ DECLARE_SNMP_STAT(struct icmp_mib, icmp_statistics);
#define ICMP_INC_STATS_BH(field) SNMP_INC_STATS_BH(icmp_statistics, field)
#define ICMP_INC_STATS_USER(field) SNMP_INC_STATS_USER(icmp_statistics, field)
+struct dst_entry;
+struct net_proto_family;
+struct sk_buff;
+
extern void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info);
extern int icmp_rcv(struct sk_buff *skb);
extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index cde2f4f4f501..df05f468fa5c 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -363,8 +363,9 @@ enum ieee80211_reasoncode {
#define IEEE80211_OFDM_SHIFT_MASK_A 4
/* NOTE: This data is for statistical purposes; not all hardware provides this
- * information for frames received. Not setting these will not cause
- * any adverse affects. */
+ * information for frames received.
+ * For ieee80211_rx_mgt, you need to set at least the 'len' parameter.
+ */
struct ieee80211_rx_stats {
u32 mac_time;
s8 rssi;
@@ -1088,6 +1089,7 @@ extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
/* ieee80211_rx.c */
extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats);
+/* make sure to set stats->len */
extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
struct ieee80211_hdr_4addr *header,
struct ieee80211_rx_stats *stats);
diff --git a/include/net/ieee80211_crypt.h b/include/net/ieee80211_crypt.h
index 225fc751d464..cd82c3e998e4 100644
--- a/include/net/ieee80211_crypt.h
+++ b/include/net/ieee80211_crypt.h
@@ -23,12 +23,18 @@
#ifndef IEEE80211_CRYPT_H
#define IEEE80211_CRYPT_H
-#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <net/ieee80211.h>
+#include <asm/atomic.h>
enum {
IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
};
+struct sk_buff;
+struct module;
+
struct ieee80211_crypto_ops {
const char *name;
struct list_head list;
@@ -87,6 +93,8 @@ struct ieee80211_crypt_data {
atomic_t refcnt;
};
+struct ieee80211_device;
+
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);
diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h
new file mode 100644
index 000000000000..b33b438bffcc
--- /dev/null
+++ b/include/net/inet6_connection_sock.h
@@ -0,0 +1,42 @@
+/*
+ * NET Generic infrastructure for INET6 connection oriented protocols.
+ *
+ * Authors: Many people, see the TCPv6 sources
+ *
+ * From code originally in TCPv6
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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_CONNECTION_SOCK_H
+#define _INET6_CONNECTION_SOCK_H
+
+#include <linux/types.h>
+
+struct in6_addr;
+struct inet_bind_bucket;
+struct request_sock;
+struct sk_buff;
+struct sock;
+struct sockaddr;
+
+extern int inet6_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
+
+extern struct request_sock *inet6_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __u16 rport,
+ const struct in6_addr *raddr,
+ const struct in6_addr *laddr,
+ const int iif);
+
+extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
+ struct request_sock *req,
+ const unsigned long timeout);
+
+extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+
+extern int inet6_csk_xmit(struct sk_buff *skb, int ipfragok);
+#endif /* _INET6_CONNECTION_SOCK_H */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 5a2beed5a770..25f708ff020e 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -48,6 +48,32 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}
+static inline void __inet6_hash(struct inet_hashinfo *hashinfo,
+ struct sock *sk)
+{
+ struct hlist_head *list;
+ rwlock_t *lock;
+
+ BUG_TRAP(sk_unhashed(sk));
+
+ if (sk->sk_state == TCP_LISTEN) {
+ list = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
+ lock = &hashinfo->lhash_lock;
+ inet_listen_wlock(hashinfo);
+ } else {
+ unsigned int hash;
+ sk->sk_hash = hash = inet6_sk_ehashfn(sk);
+ hash &= (hashinfo->ehash_size - 1);
+ list = &hashinfo->ehash[hash].chain;
+ lock = &hashinfo->ehash[hash].lock;
+ write_lock(lock);
+ }
+
+ __sk_add_node(sk, list);
+ sock_prot_inc_use(sk->sk_prot);
+ write_unlock(lock);
+}
+
/*
* 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
@@ -84,10 +110,10 @@ static inline struct sock *
if(*((__u32 *)&(tw->tw_dport)) == ports &&
sk->sk_family == PF_INET6) {
- const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk);
+ const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
- if (ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
- ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr) &&
+ if (ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
(!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif))
goto hit;
}
diff --git a/include/net/inet_common.h b/include/net/inet_common.h
index f943306ce5ff..227adcbdfec8 100644
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -1,8 +1,8 @@
#ifndef _INET_COMMON_H
#define _INET_COMMON_H
-extern struct proto_ops inet_stream_ops;
-extern struct proto_ops inet_dgram_ops;
+extern const struct proto_ops inet_stream_ops;
+extern const struct proto_ops inet_dgram_ops;
/*
* INET4 prototypes used by INET6
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index b0c99060b78d..fa587c94e9d0 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -15,9 +15,11 @@
#ifndef _INET_CONNECTION_SOCK_H
#define _INET_CONNECTION_SOCK_H
-#include <linux/ip.h>
+#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/timer.h>
+
+#include <net/inet_sock.h>
#include <net/request_sock.h>
#define INET_CSK_DEBUG 1
@@ -29,6 +31,29 @@ struct inet_bind_bucket;
struct inet_hashinfo;
struct tcp_congestion_ops;
+/*
+ * Pointers to address related TCP functions
+ * (i.e. things that depend on the address family)
+ */
+struct inet_connection_sock_af_ops {
+ int (*queue_xmit)(struct sk_buff *skb, int ipfragok);
+ void (*send_check)(struct sock *sk, int len,
+ struct sk_buff *skb);
+ int (*rebuild_header)(struct sock *sk);
+ int (*conn_request)(struct sock *sk, struct sk_buff *skb);
+ struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst);
+ int (*remember_stamp)(struct sock *sk);
+ __u16 net_header_len;
+ int (*setsockopt)(struct sock *sk, int level, int optname,
+ char __user *optval, int optlen);
+ int (*getsockopt)(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+ void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
+ int sockaddr_len;
+};
+
/** inet_connection_sock - INET connection oriented sock
*
* @icsk_accept_queue: FIFO of established children
@@ -36,13 +61,16 @@ struct tcp_congestion_ops;
* @icsk_timeout: Timeout
* @icsk_retransmit_timer: Resend (no ack)
* @icsk_rto: Retransmit timeout
+ * @icsk_pmtu_cookie Last pmtu seen by socket
* @icsk_ca_ops Pluggable congestion control hook
+ * @icsk_af_ops Operations which are AF_INET{4,6} specific
* @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_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
* @icsk_ack: Delayed ACK control data
*/
struct inet_connection_sock {
@@ -54,14 +82,17 @@ struct inet_connection_sock {
struct timer_list icsk_retransmit_timer;
struct timer_list icsk_delack_timer;
__u32 icsk_rto;
- struct tcp_congestion_ops *icsk_ca_ops;
+ __u32 icsk_pmtu_cookie;
+ const struct tcp_congestion_ops *icsk_ca_ops;
+ const struct inet_connection_sock_af_ops *icsk_af_ops;
+ unsigned int (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
__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! */
+ __u16 icsk_ext_hdr_len;
struct {
__u8 pending; /* ACK is pending */
__u8 quick; /* Scheduled number of quick acks */
@@ -192,8 +223,12 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
const __u16 rport,
const __u32 raddr,
const __u32 laddr);
+extern int inet_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
- struct sock *sk, unsigned short snum);
+ struct sock *sk, unsigned short snum,
+ int (*bind_conflict)(const struct sock *sk,
+ const struct inet_bind_bucket *tb));
extern struct dst_entry* inet_csk_route_req(struct sock *sk,
const struct request_sock *req);
@@ -207,7 +242,7 @@ static inline void inet_csk_reqsk_queue_add(struct sock *sk,
extern void inet_csk_reqsk_queue_hash_add(struct sock *sk,
struct request_sock *req,
- const unsigned timeout);
+ unsigned long timeout);
static inline void inet_csk_reqsk_queue_removed(struct sock *sk,
struct request_sock *req)
@@ -273,4 +308,6 @@ static inline unsigned int inet_csk_listen_poll(const struct sock *sk)
extern int inet_csk_listen_start(struct sock *sk, const int nr_table_entries);
extern void inet_csk_listen_stop(struct sock *sk);
+extern void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
+
#endif /* _INET_CONNECTION_SOCK_H */
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index b0c47e2eccf1..d599c6bfbb86 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -3,6 +3,8 @@
#include <linux/ip.h>
#include <linux/skbuff.h>
+
+#include <net/inet_sock.h>
#include <net/dsfield.h>
enum {
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 07840baa9341..135d80fd658e 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -26,6 +26,7 @@
#include <linux/wait.h>
#include <net/inet_connection_sock.h>
+#include <net/inet_sock.h>
#include <net/route.h>
#include <net/sock.h>
#include <net/tcp_states.h>
@@ -128,26 +129,6 @@ struct inet_hashinfo {
kmem_cache_t *bind_bucket_cachep;
};
-static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
- const __u32 faddr, const __u16 fport)
-{
- unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
- h ^= h >> 16;
- h ^= h >> 8;
- return h;
-}
-
-static inline int inet_sk_ehashfn(const struct sock *sk)
-{
- 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);
-}
-
static inline struct inet_ehash_bucket *inet_ehash_bucket(
struct inet_hashinfo *hashinfo,
unsigned int hash)
@@ -434,4 +415,7 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
return sk;
}
+
+extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk);
#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
new file mode 100644
index 000000000000..883eb529ef8e
--- /dev/null
+++ b/include/net/inet_sock.h
@@ -0,0 +1,193 @@
+/*
+ * 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 inet_sock
+ *
+ * Authors: Many, reorganised here by
+ * 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
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _INET_SOCK_H
+#define _INET_SOCK_H
+
+#include <linux/config.h>
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <net/flow.h>
+#include <net/sock.h>
+#include <net/request_sock.h>
+
+/** struct ip_options - IP Options
+ *
+ * @faddr - Saved first hop address
+ * @is_setbyuser - Set by setsockopt?
+ * @is_data - Options in __data, rather than skb
+ * @is_strictroute - Strict source route
+ * @srr_is_hit - Packet destination addr was our one
+ * @is_changed - IP checksum more not valid
+ * @rr_needaddr - Need to record addr of outgoing dev
+ * @ts_needtime - Need to record timestamp
+ * @ts_needaddr - Need to record addr of outgoing dev
+ */
+struct ip_options {
+ __u32 faddr;
+ unsigned char optlen;
+ unsigned char srr;
+ unsigned char rr;
+ unsigned char ts;
+ unsigned char is_setbyuser:1,
+ is_data:1,
+ is_strictroute:1,
+ srr_is_hit:1,
+ is_changed:1,
+ rr_needaddr:1,
+ ts_needtime:1,
+ ts_needaddr:1;
+ unsigned char router_alert;
+ unsigned char __pad1;
+ unsigned char __pad2;
+ unsigned char __data[0];
+};
+
+#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
+
+struct inet_request_sock {
+ struct request_sock req;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ u16 inet6_rsk_offset;
+ /* 2 bytes hole, try to pack */
+#endif
+ u32 loc_addr;
+ u32 rmt_addr;
+ u16 rmt_port;
+ u16 snd_wscale : 4,
+ rcv_wscale : 4,
+ tstamp_ok : 1,
+ sack_ok : 1,
+ wscale_ok : 1,
+ ecn_ok : 1,
+ acked : 1;
+ struct ip_options *opt;
+};
+
+static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
+{
+ return (struct inet_request_sock *)sk;
+}
+
+struct ip_mc_socklist;
+struct ipv6_pinfo;
+struct rtable;
+
+/** struct inet_sock - representation of INET sockets
+ *
+ * @sk - ancestor class
+ * @pinet6 - pointer to IPv6 control block
+ * @daddr - Foreign IPv4 addr
+ * @rcv_saddr - Bound local IPv4 addr
+ * @dport - Destination port
+ * @num - Local port
+ * @saddr - Sending source
+ * @uc_ttl - Unicast TTL
+ * @sport - Source port
+ * @id - ID counter for DF pkts
+ * @tos - TOS
+ * @mc_ttl - Multicasting TTL
+ * @is_icsk - is this an inet_connection_sock?
+ * @mc_index - Multicast device index
+ * @mc_list - Group array
+ * @cork - info to build ip hdr on each ip frag while socket is corked
+ */
+struct inet_sock {
+ /* sk and pinet6 has to be the first two members of inet_sock */
+ struct sock sk;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct ipv6_pinfo *pinet6;
+#endif
+ /* Socket demultiplex comparisons on incoming packets. */
+ __u32 daddr;
+ __u32 rcv_saddr;
+ __u16 dport;
+ __u16 num;
+ __u32 saddr;
+ __s16 uc_ttl;
+ __u16 cmsg_flags;
+ struct ip_options *opt;
+ __u16 sport;
+ __u16 id;
+ __u8 tos;
+ __u8 mc_ttl;
+ __u8 pmtudisc;
+ __u8 recverr:1,
+ is_icsk:1,
+ freebind:1,
+ hdrincl:1,
+ mc_loop:1;
+ int mc_index;
+ __u32 mc_addr;
+ struct ip_mc_socklist *mc_list;
+ struct {
+ unsigned int flags;
+ unsigned int fragsize;
+ struct ip_options *opt;
+ struct rtable *rt;
+ int length; /* Total length of all frames */
+ u32 addr;
+ struct flowi fl;
+ } cork;
+};
+
+#define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
+#define IPCORK_ALLFRAG 2 /* always fragment (for ipv6 for now) */
+
+static inline struct inet_sock *inet_sk(const struct sock *sk)
+{
+ return (struct inet_sock *)sk;
+}
+
+static inline void __inet_sk_copy_descendant(struct sock *sk_to,
+ const struct sock *sk_from,
+ const int ancestor_size)
+{
+ memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
+ sk_from->sk_prot->obj_size - ancestor_size);
+}
+#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
+static inline void inet_sk_copy_descendant(struct sock *sk_to,
+ const struct sock *sk_from)
+{
+ __inet_sk_copy_descendant(sk_to, sk_from, sizeof(struct inet_sock));
+}
+#endif
+
+extern int inet_sk_rebuild_header(struct sock *sk);
+
+static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
+ const __u32 faddr, const __u16 fport)
+{
+ unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
+ h ^= h >> 16;
+ h ^= h >> 8;
+ return h;
+}
+
+static inline int inet_sk_ehashfn(const struct sock *sk)
+{
+ 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);
+}
+
+#endif /* _INET_SOCK_H */
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 28f7b2103505..1da294c47522 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -17,15 +17,16 @@
#include <linux/config.h>
-#include <linux/ip.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
+#include <net/inet_sock.h>
#include <net/sock.h>
#include <net/tcp_states.h>
+#include <net/timewait_sock.h>
#include <asm/atomic.h>
@@ -127,7 +128,8 @@ struct inet_timewait_sock {
__u16 tw_num;
/* And these are ours. */
__u8 tw_ipv6only:1;
- /* 31 bits hole, try to pack */
+ /* 15 bits hole, try to pack */
+ __u16 tw_ipv6_offset;
int tw_timeout;
unsigned long tw_ttd;
struct inet_bind_bucket *tw_tb;
@@ -199,7 +201,7 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw)
printk(KERN_DEBUG "%s timewait_sock %p released\n",
tw->tw_prot->name, tw);
#endif
- kmem_cache_free(tw->tw_prot->twsk_slab, tw);
+ kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
module_put(owner);
}
}
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 7fda471002b6..0965515f40cf 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -25,6 +25,7 @@ struct inet_peer
__u32 v4daddr; /* peer's address */
__u16 avl_height;
__u16 ip_id_count; /* IP ID for the next packet */
+ atomic_t rid; /* Frag reception counter */
__u32 tcp_ts;
unsigned long tcp_ts_stamp;
};
diff --git a/include/net/ip.h b/include/net/ip.h
index e4563bbee6ea..8de0697b364c 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -24,14 +24,10 @@
#include <linux/config.h>
#include <linux/types.h>
-#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/in.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/in_route.h>
-#include <net/route.h>
-#include <net/arp.h>
+
+#include <net/inet_sock.h>
#include <net/snmp.h>
struct sock;
@@ -41,10 +37,10 @@ struct inet_skb_parm
struct ip_options opt; /* Compiled IP options */
unsigned char flags;
-#define IPSKB_MASQUERADED 1
-#define IPSKB_TRANSLATED 2
-#define IPSKB_FORWARDED 4
-#define IPSKB_XFRM_TUNNEL_SIZE 8
+#define IPSKB_FORWARDED 1
+#define IPSKB_XFRM_TUNNEL_SIZE 2
+#define IPSKB_XFRM_TRANSFORMED 4
+#define IPSKB_FRAG_COMPLETE 8
};
struct ipcm_cookie
@@ -74,6 +70,13 @@ extern rwlock_t ip_ra_lock;
#define IP_FRAG_TIME (30 * HZ) /* fragment lifetime */
+struct msghdr;
+struct net_device;
+struct packet_type;
+struct rtable;
+struct sk_buff;
+struct sockaddr;
+
extern void ip_mc_dropsocket(struct sock *);
extern void ip_mc_dropdevice(struct net_device *dev);
extern int igmp_mc_proc_init(void);
@@ -91,7 +94,6 @@ extern int ip_local_deliver(struct sk_buff *skb);
extern int ip_mr_input(struct sk_buff *skb);
extern int ip_output(struct sk_buff *skb);
extern int ip_mc_output(struct sk_buff *skb);
-extern int ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
@@ -168,6 +170,7 @@ extern int sysctl_ipfrag_high_thresh;
extern int sysctl_ipfrag_low_thresh;
extern int sysctl_ipfrag_time;
extern int sysctl_ipfrag_secret_interval;
+extern int sysctl_ipfrag_max_dist;
/* From inetpeer.c */
extern int inet_peer_threshold;
@@ -182,6 +185,8 @@ extern int sysctl_ip_dynaddr;
extern void ipfrag_init(void);
#ifdef CONFIG_INET
+#include <net/dst.h>
+
/* The function in 2.2 was invalid, producing wrong result for
* check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
static inline
@@ -310,7 +315,6 @@ enum ip_defrag_users
IP_DEFRAG_CALL_RA_CHAIN,
IP_DEFRAG_CONNTRACK_IN,
IP_DEFRAG_CONNTRACK_OUT,
- IP_DEFRAG_NAT_OUT,
IP_DEFRAG_VS_IN,
IP_DEFRAG_VS_OUT,
IP_DEFRAG_VS_FWD
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 14de4ebd1211..e000fa2cd5f6 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -238,6 +238,8 @@ extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
struct net_device *dev, u32 *spec_dst, u32 *itag);
extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
+struct rtentry;
+
/* Exported by fib_semantics.c */
extern int ip_fib_check_default(u32 gw, struct net_device *dev);
extern int fib_sync_down(u32 local, struct net_device *dev, int force);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 3b5559a023a4..7d2674fde19a 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -251,16 +251,15 @@ struct ip_vs_daemon_user {
#include <linux/config.h>
#include <linux/list.h> /* for struct list_head */
#include <linux/spinlock.h> /* for struct rwlock_t */
-#include <linux/skbuff.h> /* for struct sk_buff */
-#include <linux/ip.h> /* for struct iphdr */
#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/udp.h>
#include <linux/compiler.h>
+#include <linux/timer.h>
+#include <net/checksum.h>
#ifdef CONFIG_IP_VS_DEBUG
+#include <linux/net.h>
+
extern int ip_vs_get_debug_level(void);
#define IP_VS_DBG(level, msg...) \
do { \
@@ -429,8 +428,11 @@ struct ip_vs_stats
spinlock_t lock; /* spin lock */
};
+struct dst_entry;
+struct iphdr;
struct ip_vs_conn;
struct ip_vs_app;
+struct sk_buff;
struct ip_vs_protocol {
struct ip_vs_protocol *next;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 0a2ad51cff82..3b1d963d396c 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -240,6 +240,8 @@ extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_t
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt);
+extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
+
extern int ip6_frag_nqueues;
extern atomic_t ip6_frag_mem;
@@ -416,6 +418,8 @@ extern int ipv6_rcv(struct sk_buff *skb,
struct packet_type *pt,
struct net_device *orig_dev);
+extern int ip6_rcv_finish(struct sk_buff *skb);
+
/*
* upper-layer output functions
*/
@@ -525,6 +529,9 @@ extern int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
extern int inet6_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg);
+extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk);
+
/*
* reassembly.c
*/
@@ -533,8 +540,11 @@ extern int sysctl_ip6frag_low_thresh;
extern int sysctl_ip6frag_time;
extern int sysctl_ip6frag_secret_interval;
-extern struct proto_ops inet6_stream_ops;
-extern struct proto_ops inet6_dgram_ops;
+extern const struct proto_ops inet6_stream_ops;
+extern const struct proto_ops inet6_dgram_ops;
+
+struct group_source_req;
+struct group_filter;
extern int ip6_mc_source(int add, int omode, struct sock *sk,
struct group_source_req *pgsr);
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index d67c8393a343..a2c5e0b88422 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -327,7 +327,7 @@ struct iw_handler_def
__u16 num_private_args;
/* Array of handlers for standard ioctls
- * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
+ * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
*/
const iw_handler * standard;
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index f85d6e4b7442..bbac87eeb422 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -35,11 +35,20 @@ enum {
#ifdef __KERNEL__
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
+#include <linux/config.h>
+#include <linux/compiler.h>
#include <linux/icmpv6.h>
+#include <linux/in6.h>
+#include <linux/types.h>
+
#include <net/neighbour.h>
-#include <asm/atomic.h>
+
+struct ctl_table;
+struct file;
+struct inet6_dev;
+struct net_device;
+struct net_proto_family;
+struct sk_buff;
extern struct neigh_table nd_tbl;
@@ -108,7 +117,7 @@ extern int igmp6_event_report(struct sk_buff *skb);
extern void igmp6_cleanup(void);
#ifdef CONFIG_SYSCTL
-extern int ndisc_ifinfo_sysctl_change(ctl_table *ctl,
+extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl,
int write,
struct file * filp,
void __user *buffer,
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 34c07731933d..6fa9ae190741 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -49,8 +49,8 @@
#ifdef __KERNEL__
#include <asm/atomic.h>
-#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/skbuff.h>
#include <linux/rcupdate.h>
#include <linux/seq_file.h>
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 25b081a730e6..91684436af8e 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -37,7 +37,4 @@ struct nf_conntrack_ipv4 {
struct sk_buff *
nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
-/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */
-extern void need_ip_conntrack(void);
-
#endif /*_NF_CONNTRACK_IPV4_H*/
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index cc4825610795..6d075ca16e6e 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -94,6 +94,9 @@ struct nf_conn
/* Current number of expected connections */
unsigned int expecting;
+ /* Unique ID that identifies this conntrack*/
+ unsigned int id;
+
/* Helper. if any */
struct nf_conntrack_helper *helper;
@@ -140,6 +143,9 @@ struct nf_conntrack_expect
/* Usage count. */
atomic_t use;
+ /* Unique ID */
+ unsigned int id;
+
/* Flags */
unsigned int flags;
@@ -190,8 +196,30 @@ static inline void nf_ct_put(struct nf_conn *ct)
nf_conntrack_put(&ct->ct_general);
}
-/* call to create an explicit dependency on nf_conntrack. */
-extern void need_nf_conntrack(void);
+extern struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
+ const struct nf_conn *ignored_conntrack);
+
+extern void nf_conntrack_hash_insert(struct nf_conn *ct);
+
+extern struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern struct nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+
+extern void nf_ct_remove_expectations(struct nf_conn *ct);
+
+extern void nf_conntrack_flush(void);
+
+extern struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
+extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
+
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name);
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 5a66b2a3a623..86ec8174ad02 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -33,6 +33,8 @@ struct nf_conntrack_helper
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
+
+ int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
};
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 01663e5b33df..67856eb93b43 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -14,6 +14,8 @@
#include <linux/seq_file.h>
#include <net/netfilter/nf_conntrack.h>
+struct nfattr;
+
struct nf_conntrack_l3proto
{
/* Next pointer. */
@@ -70,6 +72,12 @@ struct nf_conntrack_l3proto
u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
+ int (*tuple_to_nfattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+
+ int (*nfattr_to_tuple)(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t);
+
/* Module (if any) which this is connected to. */
struct module *me;
};
@@ -81,11 +89,16 @@ extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
static inline struct nf_conntrack_l3proto *
-nf_ct_find_l3proto(u_int16_t l3proto)
+__nf_ct_l3proto_find(u_int16_t l3proto)
{
return nf_ct_l3protos[l3proto];
}
+extern struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto);
+
+extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
+
/* Existing built-in protocols */
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
diff --git a/include/net/netfilter/nf_conntrack_protocol.h b/include/net/netfilter/nf_conntrack_protocol.h
index b3afda35397a..1f33737fcea5 100644
--- a/include/net/netfilter/nf_conntrack_protocol.h
+++ b/include/net/netfilter/nf_conntrack_protocol.h
@@ -12,6 +12,7 @@
#include <net/netfilter/nf_conntrack.h>
struct seq_file;
+struct nfattr;
struct nf_conntrack_protocol
{
@@ -66,6 +67,18 @@ struct nf_conntrack_protocol
enum ip_conntrack_info *ctinfo,
int pf, unsigned int hooknum);
+ /* convert protoinfo to nfnetink attributes */
+ int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
+ const struct nf_conn *ct);
+
+ /* convert nfnetlink attributes to protoinfo */
+ int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
+
+ int (*tuple_to_nfattr)(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t);
+ int (*nfattr_to_tuple)(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t);
+
/* Module (if any) which this is connected to. */
struct module *me;
};
@@ -80,12 +93,23 @@ extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
extern struct nf_conntrack_protocol *
-nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
+__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
+
+extern struct nf_conntrack_protocol *
+nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
+
+extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
/* Protocol registration. */
extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
+/* Generic netlink helpers */
+extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple);
+extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t);
+
/* Log invalid packets */
extern unsigned int nf_ct_log_invalid;
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 14ce790e5c65..530ef1f75283 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -111,7 +111,7 @@ struct nf_conntrack_tuple
#ifdef __KERNEL__
#define NF_CT_DUMP_TUPLE(tp) \
-DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \
+DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
(tp), (tp)->src.l3num, (tp)->dst.protonum, \
NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h
index bd08964b72c0..b225d8472b7e 100644
--- a/include/net/pkt_act.h
+++ b/include/net/pkt_act.h
@@ -15,7 +15,6 @@
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 6492e7363d84..b94d1ad92c4d 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -1,6 +1,7 @@
#ifndef __NET_PKT_SCHED_H
#define __NET_PKT_SCHED_H
+#include <linux/jiffies.h>
#include <net/sch_generic.h>
struct qdisc_walker
@@ -59,8 +60,8 @@ typedef struct timeval psched_time_t;
typedef long psched_tdiff_t;
#define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp))
-#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ))
-#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ))
+#define PSCHED_US2JIFFIE(usecs) usecs_to_jiffies(usecs)
+#define PSCHED_JIFFIE2US(delay) jiffies_to_usecs(delay)
#else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */
@@ -123,9 +124,9 @@ do { \
default: \
__delta = 0; \
case 2: \
- __delta += 1000000; \
+ __delta += USEC_PER_SEC; \
case 1: \
- __delta += 1000000; \
+ __delta += USEC_PER_SEC; \
} \
} \
__delta; \
@@ -136,9 +137,9 @@ psched_tod_diff(int delta_sec, int bound)
{
int delta;
- if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1)
+ if (bound <= USEC_PER_SEC || delta_sec > (0x7FFFFFFF/USEC_PER_SEC)-1)
return bound;
- delta = delta_sec * 1000000;
+ delta = delta_sec * USEC_PER_SEC;
if (delta > bound || delta < 0)
delta = bound;
return delta;
@@ -152,9 +153,9 @@ psched_tod_diff(int delta_sec, int bound)
default: \
__delta = psched_tod_diff(__delta_sec, bound); break; \
case 2: \
- __delta += 1000000; \
+ __delta += USEC_PER_SEC; \
case 1: \
- __delta += 1000000; \
+ __delta += USEC_PER_SEC; \
case 0: \
if (__delta > bound || __delta < 0) \
__delta = bound; \
@@ -170,15 +171,15 @@ psched_tod_diff(int delta_sec, int bound)
({ \
int __delta = (tv).tv_usec + (delta); \
(tv_res).tv_sec = (tv).tv_sec; \
- if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \
+ if (__delta > USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \
(tv_res).tv_usec = __delta; \
})
#define PSCHED_TADD(tv, delta) \
({ \
(tv).tv_usec += (delta); \
- if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \
- (tv).tv_usec -= 1000000; } \
+ if ((tv).tv_usec > USEC_PER_SEC) { (tv).tv_sec++; \
+ (tv).tv_usec -= USEC_PER_SEC; } \
})
/* Set/check that time is in the "past perfect";
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 357691f6a45f..6dc5970612d7 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -43,7 +43,7 @@ struct net_protocol {
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_protocol
{
- int (*handler)(struct sk_buff **skb, unsigned int *nhoffp);
+ int (*handler)(struct sk_buff **skb);
void (*err_handler)(struct sk_buff *skb,
struct inet6_skb_parm *opt,
@@ -65,7 +65,7 @@ struct inet_protosw {
int protocol; /* This is the L4 protocol number. */
struct proto *prot;
- struct proto_ops *ops;
+ const struct proto_ops *ops;
int capability; /* Which (if any) capability do
* we need to use this socket
@@ -76,6 +76,7 @@ struct inet_protosw {
};
#define INET_PROTOSW_REUSE 0x01 /* Are ports automatically reusable? */
#define INET_PROTOSW_PERMANENT 0x02 /* Permanent protocols are unremovable. */
+#define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? */
extern struct net_protocol *inet_protocol_base;
extern struct net_protocol *inet_protos[MAX_INET_PROTOS];
diff --git a/include/net/raw.h b/include/net/raw.h
index f47917469b12..e67b28a0248c 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -19,6 +19,8 @@
#include <linux/config.h>
+#include <net/protocol.h>
+
extern struct proto raw_prot;
extern void raw_err(struct sock *, struct sk_buff *, u32 info);
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index b52cc52ffe39..11641c9384f7 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -244,7 +244,7 @@ static inline int reqsk_queue_is_full(const struct request_sock_queue *queue)
static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
u32 hash, struct request_sock *req,
- unsigned timeout)
+ unsigned long timeout)
{
struct listen_sock *lopt = queue->listen_opt;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8f241216f46b..a553f39f6aee 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -225,13 +225,13 @@ extern int sctp_debug_flag;
if (sctp_debug_flag) { \
if (saddr->sa.sa_family == AF_INET6) { \
printk(KERN_DEBUG \
- lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
+ lead NIP6_FMT trail, \
leadparm, \
NIP6(saddr->v6.sin6_addr), \
otherparms); \
} else { \
printk(KERN_DEBUG \
- lead "%u.%u.%u.%u" trail, \
+ lead NIPQUAD_FMT trail, \
leadparm, \
NIPQUAD(saddr->v4.sin_addr.s_addr), \
otherparms); \
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 8e7794ee27ff..f5c22d77feab 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -277,6 +277,24 @@ struct sctp_sock {
__u32 default_context;
__u32 default_timetolive;
+ /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
+ * the destination address every heartbeat interval. This value
+ * will be inherited by all new associations.
+ */
+ __u32 hbinterval;
+
+ /* This is the max_retrans value for new associations. */
+ __u16 pathmaxrxt;
+
+ /* The initial Path MTU to use for new associations. */
+ __u32 pathmtu;
+
+ /* The default SACK delay timeout for new associations. */
+ __u32 sackdelay;
+
+ /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
+
struct sctp_initmsg initmsg;
struct sctp_rtoinfo rtoinfo;
struct sctp_paddrparams paddrparam;
@@ -845,9 +863,6 @@ struct sctp_transport {
/* Data that has been sent, but not acknowledged. */
__u32 flight_size;
- /* PMTU : The current known path MTU. */
- __u32 pmtu;
-
/* Destination */
struct dst_entry *dst;
/* Source address. */
@@ -862,7 +877,22 @@ struct sctp_transport {
/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
* the destination address every heartbeat interval.
*/
- int hb_interval;
+ __u32 hbinterval;
+
+ /* This is the max_retrans value for the transport and will
+ * be initialized from the assocs value. This can be changed
+ * using SCTP_SET_PEER_ADDR_PARAMS socket option.
+ */
+ __u16 pathmaxrxt;
+
+ /* PMTU : The current known path MTU. */
+ __u32 pathmtu;
+
+ /* SACK delay timeout */
+ __u32 sackdelay;
+
+ /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
/* When was the last time (in jiffies) that we heard from this
* transport? We use this to pick new active and retran paths.
@@ -882,22 +912,11 @@ struct sctp_transport {
*/
int state;
- /* hb_allowed : The current heartbeat state of this destination,
- * : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
- */
- int hb_allowed;
-
/* These are the error stats for this destination. */
/* Error count : The current error count for this destination. */
unsigned short error_count;
- /* This is the max_retrans value for the transport and will
- * be initialized to proto.max_retrans.path. This can be changed
- * using SCTP_SET_PEER_ADDR_PARAMS socket option.
- */
- int max_retrans;
-
/* Per : A timer used by each destination.
* Destination :
* Timer :
@@ -1502,6 +1521,28 @@ struct sctp_association {
/* The largest timeout or RTO value to use in attempting an INIT */
__u16 max_init_timeo;
+ /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
+ * the destination address every heartbeat interval. This value
+ * will be inherited by all new transports.
+ */
+ __u32 hbinterval;
+
+ /* This is the max_retrans value for new transports in the
+ * association.
+ */
+ __u16 pathmaxrxt;
+
+ /* Association : The smallest PMTU discovered for all of the
+ * PMTU : peer's transport addresses.
+ */
+ __u32 pathmtu;
+
+ /* SACK delay timeout */
+ __u32 sackdelay;
+
+ /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+ __u32 param_flags;
+
int timeouts[SCTP_NUM_TIMEOUT_TYPES];
struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
@@ -1571,11 +1612,6 @@ struct sctp_association {
*/
wait_queue_head_t wait;
- /* Association : The smallest PMTU discovered for all of the
- * PMTU : peer's transport addresses.
- */
- __u32 pmtu;
-
/* The message size at which SCTP fragmentation will occur. */
__u32 frag_point;
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index f1c3bc54526a..8a6bef6f91eb 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -93,6 +93,8 @@ enum sctp_optname {
#define SCTP_STATUS SCTP_STATUS
SCTP_GET_PEER_ADDR_INFO,
#define SCTP_GET_PEER_ADDR_INFO SCTP_GET_PEER_ADDR_INFO
+ SCTP_DELAYED_ACK_TIME,
+#define SCTP_DELAYED_ACK_TIME SCTP_DELAYED_ACK_TIME
/* Internal Socket Options. Some of the sctp library functions are
* implemented using these socket options.
@@ -503,13 +505,41 @@ struct sctp_setadaption {
* unreachable. The following structure is used to access and modify an
* address's parameters:
*/
+enum sctp_spp_flags {
+ SPP_HB_ENABLE = 1, /*Enable heartbeats*/
+ SPP_HB_DISABLE = 2, /*Disable heartbeats*/
+ SPP_HB = SPP_HB_ENABLE | SPP_HB_DISABLE,
+ SPP_HB_DEMAND = 4, /*Send heartbeat immediately*/
+ SPP_PMTUD_ENABLE = 8, /*Enable PMTU discovery*/
+ SPP_PMTUD_DISABLE = 16, /*Disable PMTU discovery*/
+ SPP_PMTUD = SPP_PMTUD_ENABLE | SPP_PMTUD_DISABLE,
+ SPP_SACKDELAY_ENABLE = 32, /*Enable SACK*/
+ SPP_SACKDELAY_DISABLE = 64, /*Disable SACK*/
+ SPP_SACKDELAY = SPP_SACKDELAY_ENABLE | SPP_SACKDELAY_DISABLE,
+};
+
struct sctp_paddrparams {
sctp_assoc_t spp_assoc_id;
struct sockaddr_storage spp_address;
__u32 spp_hbinterval;
__u16 spp_pathmaxrxt;
+ __u32 spp_pathmtu;
+ __u32 spp_sackdelay;
+ __u32 spp_flags;
} __attribute__((packed, aligned(4)));
+/* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
+ *
+ * This options will get or set the delayed ack timer. The time is set
+ * in milliseconds. If the assoc_id is 0, then this sets or gets the
+ * endpoints default delayed ack timer value. If the assoc_id field is
+ * non-zero, then the set or get effects the specified association.
+ */
+struct sctp_assoc_value {
+ sctp_assoc_t assoc_id;
+ uint32_t assoc_value;
+};
+
/*
* 7.2.2 Peer Address Information
*
diff --git a/include/net/sock.h b/include/net/sock.h
index 982b4ecd187b..1806e5b61419 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -493,6 +493,7 @@ extern void sk_stream_kill_queues(struct sock *sk);
extern int sk_wait_data(struct sock *sk, long *timeo);
struct request_sock_ops;
+struct timewait_sock_ops;
/* Networking protocol blocks we attach to sockets.
* socket layer -> transport layer interface
@@ -557,11 +558,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 timewait_sock_ops *twsk_prot;
struct module *owner;
@@ -856,8 +856,8 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
filter = sk->sk_filter;
if (filter) {
- int pkt_len = sk_run_filter(skb, filter->insns,
- filter->len);
+ unsigned int pkt_len = sk_run_filter(skb, filter->insns,
+ filter->len);
if (!pkt_len)
err = -EPERM;
else
@@ -926,6 +926,29 @@ static inline void sock_put(struct sock *sk)
sk_free(sk);
}
+static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = NET_RX_SUCCESS;
+
+ if (sk_filter(sk, skb, 0))
+ goto discard_and_relse;
+
+ skb->dev = NULL;
+
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk))
+ rc = sk->sk_backlog_rcv(sk, skb);
+ else
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+out:
+ sock_put(sk);
+ return rc;
+discard_and_relse:
+ kfree_skb(skb);
+ goto out;
+}
+
/* Detach socket from process context.
* Announce socket dead, detach it from wait queue and inode.
* Note that parent inode held reference count on this struct sock,
@@ -1166,7 +1189,10 @@ static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
static inline int sock_error(struct sock *sk)
{
- int err = xchg(&sk->sk_err, 0);
+ int err;
+ if (likely(!sk->sk_err))
+ return 0;
+ err = xchg(&sk->sk_err, 0);
return -err;
}
diff --git a/include/net/tcp.h b/include/net/tcp.h
index d78025f9fbea..77f21c65bbca 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -225,53 +225,6 @@ extern atomic_t tcp_sockets_allocated;
extern int tcp_memory_pressure;
/*
- * Pointers to address related TCP functions
- * (i.e. things that depend on the address family)
- */
-
-struct tcp_func {
- int (*queue_xmit) (struct sk_buff *skb,
- int ipfragok);
-
- void (*send_check) (struct sock *sk,
- struct tcphdr *th,
- int len,
- struct sk_buff *skb);
-
- int (*rebuild_header) (struct sock *sk);
-
- int (*conn_request) (struct sock *sk,
- struct sk_buff *skb);
-
- struct sock * (*syn_recv_sock) (struct sock *sk,
- struct sk_buff *skb,
- struct request_sock *req,
- struct dst_entry *dst);
-
- int (*remember_stamp) (struct sock *sk);
-
- __u16 net_header_len;
-
- int (*setsockopt) (struct sock *sk,
- int level,
- int optname,
- char __user *optval,
- int optlen);
-
- int (*getsockopt) (struct sock *sk,
- int level,
- int optname,
- char __user *optval,
- int __user *optlen);
-
-
- void (*addr2sockaddr) (struct sock *sk,
- struct sockaddr *);
-
- int sockaddr_len;
-};
-
-/*
* The next routines deal with comparing 32 bit unsigned ints
* and worry about wraparound (automatic with unsigned arithmetic).
*/
@@ -334,6 +287,9 @@ extern int tcp_rcv_established(struct sock *sk,
extern void tcp_rcv_space_adjust(struct sock *sk);
+extern int tcp_twsk_unique(struct sock *sk,
+ struct sock *sktw, void *twp);
+
static inline void tcp_dec_quickack_mode(struct sock *sk,
const unsigned int pkts)
{
@@ -405,8 +361,7 @@ extern void tcp_parse_options(struct sk_buff *skb,
* TCP v4 functions exported for the inet6 API
*/
-extern void tcp_v4_send_check(struct sock *sk,
- struct tcphdr *th, int len,
+extern void tcp_v4_send_check(struct sock *sk, int len,
struct sk_buff *skb);
extern int tcp_v4_conn_request(struct sock *sk,
@@ -490,34 +445,16 @@ 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);
-/* 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.
- * It's better to underestimate the RCV_MSS rather than overestimate.
- * Overestimations make us ACKing less frequently than needed.
- * Underestimations are more easy to detect and fix by tcp_measure_rcv_mss().
- */
+extern void tcp_initialize_rcv_mss(struct sock *sk);
-static inline void tcp_initialize_rcv_mss(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- unsigned int hint = min_t(unsigned int, tp->advmss, tp->mss_cache);
-
- hint = min(hint, tp->rcv_wnd/2);
- hint = min(hint, TCP_MIN_RCVMSS);
- hint = max(hint, TCP_MIN_MSS);
-
- inet_csk(sk)->icsk_ack.rcv_mss = hint;
-}
-
-static __inline__ void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
+static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
{
tp->pred_flags = htonl((tp->tcp_header_len << 26) |
ntohl(TCP_FLAG_ACK) |
snd_wnd);
}
-static __inline__ void tcp_fast_path_on(struct tcp_sock *tp)
+static inline void tcp_fast_path_on(struct tcp_sock *tp)
{
__tcp_fast_path_on(tp, tp->snd_wnd >> tp->rx_opt.snd_wscale);
}
@@ -535,7 +472,7 @@ static inline void tcp_fast_path_check(struct sock *sk, struct tcp_sock *tp)
* Rcv_nxt can be after the window if our peer push more data
* than the offered window.
*/
-static __inline__ u32 tcp_receive_window(const struct tcp_sock *tp)
+static inline u32 tcp_receive_window(const struct tcp_sock *tp)
{
s32 win = tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt;
@@ -707,6 +644,7 @@ 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 sock *sk, const char *name);
+extern void tcp_slow_start(struct tcp_sock *tp);
extern struct tcp_congestion_ops tcp_init_congestion_ops;
extern u32 tcp_reno_ssthresh(struct sock *sk);
@@ -746,7 +684,7 @@ static inline void tcp_ca_event(struct sock *sk, const enum tcp_ca_event event)
* "Packets left network, but not honestly ACKed yet" PLUS
* "Packets fast retransmitted"
*/
-static __inline__ unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
+static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
{
return (tp->packets_out - tp->left_out + tp->retrans_out);
}
@@ -766,33 +704,6 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk)
(tp->snd_cwnd >> 2)));
}
-/*
- * Linear increase during slow start
- */
-static inline void tcp_slow_start(struct tcp_sock *tp)
-{
- if (sysctl_tcp_abc) {
- /* RFC3465: Slow Start
- * TCP sender SHOULD increase cwnd by the number of
- * previously unacknowledged bytes ACKed by each incoming
- * acknowledgment, provided the increase is not more than L
- */
- if (tp->bytes_acked < tp->mss_cache)
- return;
-
- /* We MAY increase by 2 if discovered delayed ack */
- if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) {
- if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- tp->snd_cwnd++;
- }
- }
- tp->bytes_acked = 0;
-
- if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- tp->snd_cwnd++;
-}
-
-
static inline void tcp_sync_left_out(struct tcp_sock *tp)
{
if (tp->rx_opt.sack_ok &&
@@ -801,34 +712,7 @@ static inline void tcp_sync_left_out(struct tcp_sock *tp)
tp->left_out = tp->sacked_out + tp->lost_out;
}
-/* Set slow start threshold and cwnd not falling to slow start */
-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 = icsk->icsk_ca_ops->ssthresh(sk);
- tp->snd_cwnd = min(tp->snd_cwnd,
- tcp_packets_in_flight(tp) + 1U);
- tp->snd_cwnd_cnt = 0;
- tp->high_seq = tp->snd_nxt;
- tp->snd_cwnd_stamp = tcp_time_stamp;
- TCP_ECN_queue_cwr(tp);
-}
-
-static inline void tcp_enter_cwr(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->prior_ssthresh = 0;
- tp->bytes_acked = 0;
- if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {
- __tcp_enter_cwr(sk);
- tcp_set_ca_state(sk, TCP_CA_CWR);
- }
-}
-
+extern void tcp_enter_cwr(struct sock *sk);
extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst);
/* Slow start with delack produces 3 packets of burst, so that
@@ -860,14 +744,14 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
return left <= tcp_max_burst(tp);
}
-static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss,
- const struct sk_buff *skb)
+static inline void tcp_minshall_update(struct tcp_sock *tp, int mss,
+ const struct sk_buff *skb)
{
if (skb->len < mss)
tp->snd_sml = TCP_SKB_CB(skb)->end_seq;
}
-static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp)
+static inline void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *tp)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
if (!tp->packets_out && !icsk->icsk_pending)
@@ -875,18 +759,18 @@ static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_sock *t
icsk->icsk_rto, TCP_RTO_MAX);
}
-static __inline__ void tcp_push_pending_frames(struct sock *sk,
- struct tcp_sock *tp)
+static inline void tcp_push_pending_frames(struct sock *sk,
+ struct tcp_sock *tp)
{
__tcp_push_pending_frames(sk, tp, tcp_current_mss(sk, 1), tp->nonagle);
}
-static __inline__ void tcp_init_wl(struct tcp_sock *tp, u32 ack, u32 seq)
+static inline void tcp_init_wl(struct tcp_sock *tp, u32 ack, u32 seq)
{
tp->snd_wl1 = seq;
}
-static __inline__ void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
+static inline void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
{
tp->snd_wl1 = seq;
}
@@ -894,19 +778,19 @@ static __inline__ void tcp_update_wl(struct tcp_sock *tp, u32 ack, u32 seq)
/*
* Calculate(/check) TCP checksum
*/
-static __inline__ u16 tcp_v4_check(struct tcphdr *th, int len,
- unsigned long saddr, unsigned long daddr,
- unsigned long base)
+static inline u16 tcp_v4_check(struct tcphdr *th, int len,
+ unsigned long saddr, unsigned long daddr,
+ unsigned long base)
{
return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base);
}
-static __inline__ int __tcp_checksum_complete(struct sk_buff *skb)
+static inline int __tcp_checksum_complete(struct sk_buff *skb)
{
return __skb_checksum_complete(skb);
}
-static __inline__ int tcp_checksum_complete(struct sk_buff *skb)
+static inline int tcp_checksum_complete(struct sk_buff *skb)
{
return skb->ip_summed != CHECKSUM_UNNECESSARY &&
__tcp_checksum_complete(skb);
@@ -914,7 +798,7 @@ static __inline__ int tcp_checksum_complete(struct sk_buff *skb)
/* Prequeue for VJ style copy to user, combined with checksumming. */
-static __inline__ void tcp_prequeue_init(struct tcp_sock *tp)
+static inline void tcp_prequeue_init(struct tcp_sock *tp)
{
tp->ucopy.task = NULL;
tp->ucopy.len = 0;
@@ -930,7 +814,7 @@ static __inline__ void tcp_prequeue_init(struct tcp_sock *tp)
*
* NOTE: is this not too big to inline?
*/
-static __inline__ int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
+static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -971,7 +855,7 @@ static const char *statename[]={
};
#endif
-static __inline__ void tcp_set_state(struct sock *sk, int state)
+static inline void tcp_set_state(struct sock *sk, int state)
{
int oldstate = sk->sk_state;
@@ -1005,7 +889,7 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
#endif
}
-static __inline__ void tcp_done(struct sock *sk)
+static inline void tcp_done(struct sock *sk)
{
tcp_set_state(sk, TCP_CLOSE);
tcp_clear_xmit_timers(sk);
@@ -1018,81 +902,13 @@ static __inline__ void tcp_done(struct sock *sk)
inet_csk_destroy_sock(sk);
}
-static __inline__ void tcp_sack_reset(struct tcp_options_received *rx_opt)
+static inline void tcp_sack_reset(struct tcp_options_received *rx_opt)
{
rx_opt->dsack = 0;
rx_opt->eff_sacks = 0;
rx_opt->num_sacks = 0;
}
-static __inline__ void tcp_build_and_update_options(__u32 *ptr, struct tcp_sock *tp, __u32 tstamp)
-{
- if (tp->rx_opt.tstamp_ok) {
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
- (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) |
- TCPOLEN_TIMESTAMP);
- *ptr++ = htonl(tstamp);
- *ptr++ = htonl(tp->rx_opt.ts_recent);
- }
- if (tp->rx_opt.eff_sacks) {
- struct tcp_sack_block *sp = tp->rx_opt.dsack ? tp->duplicate_sack : tp->selective_acks;
- int this_sack;
-
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
- (TCPOPT_NOP << 16) |
- (TCPOPT_SACK << 8) |
- (TCPOLEN_SACK_BASE +
- (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK)));
- for(this_sack = 0; this_sack < tp->rx_opt.eff_sacks; this_sack++) {
- *ptr++ = htonl(sp[this_sack].start_seq);
- *ptr++ = htonl(sp[this_sack].end_seq);
- }
- if (tp->rx_opt.dsack) {
- tp->rx_opt.dsack = 0;
- tp->rx_opt.eff_sacks--;
- }
- }
-}
-
-/* Construct a tcp options header for a SYN or SYN_ACK packet.
- * If this is every changed make sure to change the definition of
- * MAX_SYN_SIZE to match the new maximum number of options that you
- * can generate.
- */
-static inline void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
- int offer_wscale, int wscale, __u32 tstamp, __u32 ts_recent)
-{
- /* We always get an MSS option.
- * The option bytes which will be seen in normal data
- * packets should timestamps be used, must be in the MSS
- * advertised. But we subtract them from tp->mss_cache so
- * that calculations in tcp_sendmsg are simpler etc.
- * So account for this fact here if necessary. If we
- * don't do this correctly, as a receiver we won't
- * recognize data packets as being full sized when we
- * should, and thus we won't abide by the delayed ACK
- * rules correctly.
- * SACKs don't matter, we never delay an ACK when we
- * have any of those going out.
- */
- *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
- if (ts) {
- if(sack)
- *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
- else
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
- *ptr++ = htonl(tstamp); /* TSVAL */
- *ptr++ = htonl(ts_recent); /* TSECR */
- } else if(sack)
- *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
- (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
- if (offer_wscale)
- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
-}
-
/* Determine a window scaling and initial window to offer. */
extern void tcp_select_initial_window(int __space, __u32 mss,
__u32 *rcv_wnd, __u32 *window_clamp,
@@ -1117,9 +933,9 @@ static inline int tcp_full_space(const struct sock *sk)
return tcp_win_from_space(sk->sk_rcvbuf);
}
-static __inline__ void tcp_openreq_init(struct request_sock *req,
- struct tcp_options_received *rx_opt,
- struct sk_buff *skb)
+static inline void tcp_openreq_init(struct request_sock *req,
+ struct tcp_options_received *rx_opt,
+ struct sk_buff *skb)
{
struct inet_request_sock *ireq = inet_rsk(req);
diff --git a/include/net/tcp_states.h b/include/net/tcp_states.h
index b9d4176b2d15..b0b645988bd8 100644
--- a/include/net/tcp_states.h
+++ b/include/net/tcp_states.h
@@ -31,4 +31,20 @@ enum {
#define TCP_STATE_MASK 0xF
+#define TCP_ACTION_FIN (1 << 7)
+
+enum {
+ TCPF_ESTABLISHED = (1 << 1),
+ TCPF_SYN_SENT = (1 << 2),
+ TCPF_SYN_RECV = (1 << 3),
+ TCPF_FIN_WAIT1 = (1 << 4),
+ TCPF_FIN_WAIT2 = (1 << 5),
+ TCPF_TIME_WAIT = (1 << 6),
+ TCPF_CLOSE = (1 << 7),
+ TCPF_CLOSE_WAIT = (1 << 8),
+ TCPF_LAST_ACK = (1 << 9),
+ TCPF_LISTEN = (1 << 10),
+ TCPF_CLOSING = (1 << 11)
+};
+
#endif /* _LINUX_TCP_STATES_H */
diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h
new file mode 100644
index 000000000000..2544281e1d5e
--- /dev/null
+++ b/include/net/timewait_sock.h
@@ -0,0 +1,31 @@
+/*
+ * NET Generic infrastructure for Network protocols.
+ *
+ * Authors: 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.
+ */
+#ifndef _TIMEWAIT_SOCK_H
+#define _TIMEWAIT_SOCK_H
+
+#include <linux/slab.h>
+#include <net/sock.h>
+
+struct timewait_sock_ops {
+ kmem_cache_t *twsk_slab;
+ unsigned int twsk_obj_size;
+ int (*twsk_unique)(struct sock *sk,
+ struct sock *sktw, void *twp);
+};
+
+static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+{
+ if (sk->sk_prot->twsk_prot->twsk_unique != NULL)
+ return sk->sk_prot->twsk_prot->twsk_unique(sk, sktw, twp);
+ return 0;
+}
+
+#endif /* _TIMEWAIT_SOCK_H */
diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h
new file mode 100644
index 000000000000..9566608c88cf
--- /dev/null
+++ b/include/net/tipc/tipc.h
@@ -0,0 +1,257 @@
+/*
+ * include/net/tipc/tipc.h: Main include file for TIPC users
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_TIPC_H_
+#define _NET_TIPC_H_
+
+#ifdef __KERNEL__
+
+#include <linux/tipc.h>
+#include <linux/skbuff.h>
+
+/*
+ * Native API
+ */
+
+/*
+ * TIPC operating mode routines
+ */
+
+u32 tipc_get_addr(void);
+
+#define TIPC_NOT_RUNNING 0
+#define TIPC_NODE_MODE 1
+#define TIPC_NET_MODE 2
+
+typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr);
+
+int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle);
+
+void tipc_detach(unsigned int userref);
+
+int tipc_get_mode(void);
+
+/*
+ * TIPC port manipulation routines
+ */
+
+typedef void (*tipc_msg_err_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ int reason,
+ struct tipc_portid const *attmpt_destid);
+
+typedef void (*tipc_named_msg_err_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ int reason,
+ struct tipc_name_seq const *attmpt_dest);
+
+typedef void (*tipc_conn_shutdown_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ int reason);
+
+typedef void (*tipc_msg_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ unsigned int importance,
+ struct tipc_portid const *origin);
+
+typedef void (*tipc_named_msg_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ unsigned int importance,
+ struct tipc_portid const *orig,
+ struct tipc_name_seq const *dest);
+
+typedef void (*tipc_conn_msg_event) (void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size);
+
+typedef void (*tipc_continue_event) (void *usr_handle,
+ u32 portref);
+
+int tipc_createport(unsigned int tipc_user,
+ void *usr_handle,
+ unsigned int importance,
+ tipc_msg_err_event error_cb,
+ tipc_named_msg_err_event named_error_cb,
+ tipc_conn_shutdown_event conn_error_cb,
+ tipc_msg_event message_cb,
+ tipc_named_msg_event named_message_cb,
+ tipc_conn_msg_event conn_message_cb,
+ tipc_continue_event continue_event_cb,/* May be zero */
+ u32 *portref);
+
+int tipc_deleteport(u32 portref);
+
+int tipc_ownidentity(u32 portref, struct tipc_portid *port);
+
+int tipc_portimportance(u32 portref, unsigned int *importance);
+int tipc_set_portimportance(u32 portref, unsigned int importance);
+
+int tipc_portunreliable(u32 portref, unsigned int *isunreliable);
+int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
+
+int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
+int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
+
+int tipc_publish(u32 portref, unsigned int scope,
+ struct tipc_name_seq const *name_seq);
+int tipc_withdraw(u32 portref, unsigned int scope,
+ struct tipc_name_seq const *name_seq); /* 0: all */
+
+int tipc_connect2port(u32 portref, struct tipc_portid const *port);
+
+int tipc_disconnect(u32 portref);
+
+int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */
+
+int tipc_isconnected(u32 portref, int *isconnected);
+
+int tipc_peer(u32 portref, struct tipc_portid *peer);
+
+int tipc_ref_valid(u32 portref);
+
+/*
+ * TIPC messaging routines
+ */
+
+#define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */
+
+
+int tipc_send(u32 portref,
+ unsigned int num_sect,
+ struct iovec const *msg_sect);
+
+int tipc_send_buf(u32 portref,
+ struct sk_buff *buf,
+ unsigned int dsz);
+
+int tipc_send2name(u32 portref,
+ struct tipc_name const *name,
+ u32 domain, /* 0:own zone */
+ unsigned int num_sect,
+ struct iovec const *msg_sect);
+
+int tipc_send_buf2name(u32 portref,
+ struct tipc_name const *name,
+ u32 domain,
+ struct sk_buff *buf,
+ unsigned int dsz);
+
+int tipc_forward2name(u32 portref,
+ struct tipc_name const *name,
+ u32 domain, /*0: own zone */
+ unsigned int section_count,
+ struct iovec const *msg_sect,
+ struct tipc_portid const *origin,
+ unsigned int importance);
+
+int tipc_forward_buf2name(u32 portref,
+ struct tipc_name const *name,
+ u32 domain,
+ struct sk_buff *buf,
+ unsigned int dsz,
+ struct tipc_portid const *orig,
+ unsigned int importance);
+
+int tipc_send2port(u32 portref,
+ struct tipc_portid const *dest,
+ unsigned int num_sect,
+ struct iovec const *msg_sect);
+
+int tipc_send_buf2port(u32 portref,
+ struct tipc_portid const *dest,
+ struct sk_buff *buf,
+ unsigned int dsz);
+
+int tipc_forward2port(u32 portref,
+ struct tipc_portid const *dest,
+ unsigned int num_sect,
+ struct iovec const *msg_sect,
+ struct tipc_portid const *origin,
+ unsigned int importance);
+
+int tipc_forward_buf2port(u32 portref,
+ struct tipc_portid const *dest,
+ struct sk_buff *buf,
+ unsigned int dsz,
+ struct tipc_portid const *orig,
+ unsigned int importance);
+
+int tipc_multicast(u32 portref,
+ struct tipc_name_seq const *seq,
+ u32 domain, /* 0:own zone */
+ unsigned int section_count,
+ struct iovec const *msg);
+
+#if 0
+int tipc_multicast_buf(u32 portref,
+ struct tipc_name_seq const *seq,
+ u32 domain, /* 0:own zone */
+ void *buf,
+ unsigned int size);
+#endif
+
+/*
+ * TIPC subscription routines
+ */
+
+int tipc_ispublished(struct tipc_name const *name);
+
+/*
+ * Get number of available nodes within specified domain (excluding own node)
+ */
+
+unsigned int tipc_available_nodes(const u32 domain);
+
+#endif
+
+#endif
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
new file mode 100644
index 000000000000..098607cd4b78
--- /dev/null
+++ b/include/net/tipc/tipc_bearer.h
@@ -0,0 +1,121 @@
+/*
+ * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_TIPC_BEARER_H_
+#define _NET_TIPC_BEARER_H_
+
+#ifdef __KERNEL__
+
+#include <linux/tipc_config.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+/*
+ * Identifiers of supported TIPC media types
+ */
+
+#define TIPC_MEDIA_TYPE_ETH 1
+
+struct tipc_media_addr {
+ __u32 type;
+ union {
+ __u8 eth_addr[6]; /* Ethernet bearer */
+#if 0
+ /* Prototypes for other possible bearer types */
+
+ struct {
+ __u16 sin_family;
+ __u16 sin_port;
+ struct {
+ __u32 s_addr;
+ } sin_addr;
+ char pad[4];
+ } addr_in; /* IP-based bearer */
+ __u16 sock_descr; /* generic socket bearer */
+#endif
+ } dev_addr;
+};
+
+/**
+ * struct tipc_bearer - TIPC bearer info available to privileged users
+ * @usr_handle: pointer to additional user-defined information about bearer
+ * @mtu: max packet size bearer can support
+ * @blocked: non-zero if bearer is blocked
+ * @lock: spinlock for controlling access to bearer
+ * @addr: media-specific address associated with bearer
+ * @name: bearer name (format = media:interface)
+ *
+ * Note: TIPC initializes "name" and "lock" fields; user is responsible for
+ * initialization all other fields when a bearer is enabled.
+ */
+
+struct tipc_bearer {
+ void *usr_handle;
+ u32 mtu;
+ int blocked;
+ spinlock_t lock;
+ struct tipc_media_addr addr;
+ char name[TIPC_MAX_BEARER_NAME];
+};
+
+
+int tipc_register_media(u32 media_type,
+ char *media_name,
+ int (*enable)(struct tipc_bearer *),
+ void (*disable)(struct tipc_bearer *),
+ int (*send_msg)(struct sk_buff *,
+ struct tipc_bearer *,
+ struct tipc_media_addr *),
+ char *(*addr2str)(struct tipc_media_addr *a,
+ char *str_buf,
+ int str_size),
+ struct tipc_media_addr *bcast_addr,
+ const u32 bearer_priority,
+ const u32 link_tolerance, /* [ms] */
+ const u32 send_window_limit);
+
+void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
+
+int tipc_block_bearer(const char *name);
+void tipc_continue(struct tipc_bearer *tb_ptr);
+
+int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
+int tipc_disable_bearer(const char *name);
+
+
+#endif
+
+#endif
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h
new file mode 100644
index 000000000000..4d096eebc93f
--- /dev/null
+++ b/include/net/tipc/tipc_msg.h
@@ -0,0 +1,223 @@
+/*
+ * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_TIPC_MSG_H_
+#define _NET_TIPC_MSG_H_
+
+#ifdef __KERNEL__
+
+struct tipc_msg {
+ u32 hdr[15];
+};
+
+
+/*
+ TIPC user data message header format, version 2:
+
+
+ 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w0:|vers | user |hdr sz |n|d|s|-| message size |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w2:| link level ack no | broadcast/link level seq no |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w3:| previous node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w4:| originating port |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w5:| destination port |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w6:| originating node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w7:| destination node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w8:| name type / transport sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w9:| name instance/multicast lower bound |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ wA:| multicast upper bound |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / /
+ \ options \
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+*/
+
+#define TIPC_CONN_MSG 0
+#define TIPC_MCAST_MSG 1
+#define TIPC_NAMED_MSG 2
+#define TIPC_DIRECT_MSG 3
+
+
+static inline u32 msg_word(struct tipc_msg *m, u32 pos)
+{
+ return ntohl(m->hdr[pos]);
+}
+
+static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask)
+{
+ return (msg_word(m, w) >> pos) & mask;
+}
+
+static inline u32 msg_importance(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 25, 0xf);
+}
+
+static inline u32 msg_hdr_sz(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 21, 0xf) << 2;
+}
+
+static inline int msg_short(struct tipc_msg *m)
+{
+ return (msg_hdr_sz(m) == 24);
+}
+
+static inline u32 msg_size(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 0, 0x1ffff);
+}
+
+static inline u32 msg_data_sz(struct tipc_msg *m)
+{
+ return (msg_size(m) - msg_hdr_sz(m));
+}
+
+static inline unchar *msg_data(struct tipc_msg *m)
+{
+ return ((unchar *)m) + msg_hdr_sz(m);
+}
+
+static inline u32 msg_type(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 29, 0x7);
+}
+
+static inline u32 msg_direct(struct tipc_msg *m)
+{
+ return (msg_type(m) == TIPC_DIRECT_MSG);
+}
+
+static inline u32 msg_named(struct tipc_msg *m)
+{
+ return (msg_type(m) == TIPC_NAMED_MSG);
+}
+
+static inline u32 msg_mcast(struct tipc_msg *m)
+{
+ return (msg_type(m) == TIPC_MCAST_MSG);
+}
+
+static inline u32 msg_connected(struct tipc_msg *m)
+{
+ return (msg_type(m) == TIPC_CONN_MSG);
+}
+
+static inline u32 msg_errcode(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 25, 0xf);
+}
+
+static inline u32 msg_prevnode(struct tipc_msg *m)
+{
+ return msg_word(m, 3);
+}
+
+static inline u32 msg_origport(struct tipc_msg *m)
+{
+ return msg_word(m, 4);
+}
+
+static inline u32 msg_destport(struct tipc_msg *m)
+{
+ return msg_word(m, 5);
+}
+
+static inline u32 msg_mc_netid(struct tipc_msg *m)
+{
+ return msg_word(m, 5);
+}
+
+static inline u32 msg_orignode(struct tipc_msg *m)
+{
+ if (likely(msg_short(m)))
+ return msg_prevnode(m);
+ return msg_word(m, 6);
+}
+
+static inline u32 msg_destnode(struct tipc_msg *m)
+{
+ return msg_word(m, 7);
+}
+
+static inline u32 msg_nametype(struct tipc_msg *m)
+{
+ return msg_word(m, 8);
+}
+
+static inline u32 msg_nameinst(struct tipc_msg *m)
+{
+ return msg_word(m, 9);
+}
+
+static inline u32 msg_namelower(struct tipc_msg *m)
+{
+ return msg_nameinst(m);
+}
+
+static inline u32 msg_nameupper(struct tipc_msg *m)
+{
+ return msg_word(m, 10);
+}
+
+static inline char *msg_options(struct tipc_msg *m, u32 *len)
+{
+ u32 pos = msg_bits(m, 1, 16, 0x7);
+
+ if (!pos)
+ return 0;
+ pos = (pos * 4) + 28;
+ *len = msg_hdr_sz(m) - pos;
+ return (char *)&m->hdr[pos/4];
+}
+
+#endif
+
+#endif
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
new file mode 100644
index 000000000000..333bba6dc522
--- /dev/null
+++ b/include/net/tipc/tipc_port.h
@@ -0,0 +1,108 @@
+/*
+ * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
+ *
+ * Copyright (c) 1994-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NET_TIPC_PORT_H_
+#define _NET_TIPC_PORT_H_
+
+#ifdef __KERNEL__
+
+#include <linux/tipc.h>
+#include <linux/skbuff.h>
+#include <net/tipc/tipc_msg.h>
+
+#define TIPC_FLOW_CONTROL_WIN 512
+
+/**
+ * struct tipc_port - native TIPC port info available to privileged users
+ * @usr_handle: pointer to additional user-defined information about port
+ * @lock: pointer to spinlock for controlling access to port
+ * @connected: non-zero if port is currently connected to a peer port
+ * @conn_type: TIPC type used when connection was established
+ * @conn_instance: TIPC instance used when connection was established
+ * @conn_unacked: number of unacknowledged messages received from peer port
+ * @published: non-zero if port has one or more associated names
+ * @congested: non-zero if cannot send because of link or port congestion
+ * @ref: unique reference to port in TIPC object registry
+ * @phdr: preformatted message header used when sending messages
+ */
+
+struct tipc_port {
+ void *usr_handle;
+ spinlock_t *lock;
+ int connected;
+ u32 conn_type;
+ u32 conn_instance;
+ u32 conn_unacked;
+ int published;
+ u32 congested;
+ u32 ref;
+ struct tipc_msg phdr;
+};
+
+
+/**
+ * tipc_createport_raw - create a native TIPC port and return it's reference
+ *
+ * Note: 'dispatcher' and 'wakeup' deliver a locked port.
+ */
+
+u32 tipc_createport_raw(void *usr_handle,
+ u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
+ void (*wakeup)(struct tipc_port *),
+ const u32 importance);
+
+/*
+ * tipc_set_msg_option(): port must be locked.
+ */
+int tipc_set_msg_option(struct tipc_port *tp_ptr,
+ const char *opt,
+ const u32 len);
+
+int tipc_reject_msg(struct sk_buff *buf, u32 err);
+
+int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
+
+void tipc_acknowledge(u32 port_ref,u32 ack);
+
+struct tipc_port *tipc_get_port(const u32 ref);
+
+void *tipc_get_handle(const u32 ref);
+
+
+#endif
+
+#endif
+
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 4e86f2de6638..61f724c1036f 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -44,7 +44,7 @@ extern int datagram_send_ctl(struct msghdr *msg,
/*
* address family specific functions
*/
-extern struct tcp_func ipv4_specific;
+extern struct inet_connection_sock_af_ops ipv4_specific;
extern int inet6_destroy_sock(struct sock *sk);
diff --git a/include/net/udp.h b/include/net/udp.h
index 107b9d791a1f..766fba1369ce 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -22,9 +22,8 @@
#ifndef _UDP_H
#define _UDP_H
-#include <linux/udp.h>
-#include <linux/ip.h>
#include <linux/list.h>
+#include <net/inet_sock.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <linux/seq_file.h>
@@ -62,6 +61,7 @@ static inline int udp_lport_inuse(u16 num)
extern struct proto udp_prot;
+struct sk_buff;
extern void udp_err(struct sk_buff *, u32);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1cdb87912137..d09ca0e7d139 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -2,11 +2,12 @@
#define _NET_XFRM_H
#include <linux/compiler.h>
+#include <linux/in.h>
#include <linux/xfrm.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/skbuff.h>
-#include <linux/netdevice.h>
+#include <linux/socket.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
#include <linux/in6.h>
@@ -144,6 +145,9 @@ struct xfrm_state
* transformer. */
struct xfrm_type *type;
+ /* Security context */
+ struct xfrm_sec_ctx *security;
+
/* Private data of this transformer, format is opaque,
* interpreted by xfrm_type methods. */
void *data;
@@ -298,6 +302,7 @@ struct xfrm_policy
__u8 flags;
__u8 dead;
__u8 xfrm_nr;
+ struct xfrm_sec_ctx *security;
struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH];
};
@@ -510,6 +515,25 @@ xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
return 0;
}
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+/* If neither has a context --> match
+ * Otherwise, both must have a context and the sids, doi, alg must match
+ */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+ return ((!s1 && !s2) ||
+ (s1 && s2 &&
+ (s1->ctx_sid == s2->ctx_sid) &&
+ (s1->ctx_doi == s2->ctx_doi) &&
+ (s1->ctx_alg == s2->ctx_alg)));
+}
+#else
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+ return 1;
+}
+#endif
+
/* A struct encoding bundle of transformations to apply to some set of flow.
*
* dst->child points to the next element of bundle.
@@ -644,7 +668,7 @@ static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *s
return xfrm_policy_check(sk, dir, skb, AF_INET6);
}
-
+extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
@@ -807,7 +831,7 @@ struct xfrm_tunnel {
};
struct xfrm6_tunnel {
- int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp);
+ int (*handler)(struct sk_buff **pskb);
void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __u32 info);
};
@@ -842,10 +866,11 @@ extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
+extern int xfrm4_output_finish(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
-extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
-extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+extern int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi);
+extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
@@ -878,8 +903,8 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig
struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp);
extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
-struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
- int delete);
+struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
+ struct xfrm_sec_ctx *ctx, int delete);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete);
void xfrm_policy_flush(void);
u32 xfrm_get_acqseq(void);
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 2cab39f49eb2..52660f32663d 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -382,7 +382,6 @@ enum service {
struct pcmcia_socket;
int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg);
-int pcmcia_deregister_client(struct pcmcia_device *p_dev);
int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config);
int pcmcia_get_first_window(window_handle_t *win, win_req_t *req);
int pcmcia_get_next_window(window_handle_t *win, win_req_t *req);
@@ -390,7 +389,6 @@ int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
-int pcmcia_register_client(client_handle_t *handle, client_reg_t *req);
int pcmcia_release_configuration(struct pcmcia_device *p_dev);
int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index cb8b6e6ce66c..8e2a96396478 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -133,10 +133,12 @@ typedef struct dev_link_t {
struct pcmcia_socket;
struct pcmcia_driver {
- dev_link_t *(*attach)(void);
- int (*event) (event_t event, int priority,
- event_callback_args_t *);
- void (*detach)(dev_link_t *);
+ int (*probe) (struct pcmcia_device *dev);
+ void (*remove) (struct pcmcia_device *dev);
+
+ int (*suspend) (struct pcmcia_device *dev);
+ int (*resume) (struct pcmcia_device *dev);
+
struct module *owner;
struct pcmcia_device_id *id_table;
struct device_driver drv;
@@ -164,7 +166,6 @@ struct pcmcia_device {
/* deprecated, a cleaned up version will be moved into this
struct soon */
dev_link_t *instance;
- event_callback_args_t event_callback_args;
u_int state;
/* information about this device */
@@ -193,6 +194,8 @@ struct pcmcia_device {
#define handle_to_pdev(handle) (handle)
#define handle_to_dev(handle) (handle->dev)
+#define dev_to_instance(dev) (dev->instance)
+
/* error reporting */
void cs_error(client_handle_t handle, int func, int ret);
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index e788bbc5657d..2889a69a7a8f 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -118,16 +118,14 @@ struct pcmcia_socket;
struct pccard_operations {
int (*init)(struct pcmcia_socket *sock);
int (*suspend)(struct pcmcia_socket *sock);
- int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
int (*get_status)(struct pcmcia_socket *sock, u_int *value);
- int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state);
int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
};
struct pccard_resource_ops {
- void (*validate_mem) (struct pcmcia_socket *s);
+ int (*validate_mem) (struct pcmcia_socket *s);
int (*adjust_io_region) (struct resource *res,
unsigned long r_start,
unsigned long r_end,
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index a7f4c355a91f..22fc886b9695 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -88,7 +88,6 @@ enum ib_atomic_cap {
struct ib_device_attr {
u64 fw_ver;
- __be64 node_guid;
__be64 sys_image_guid;
u64 max_mr_size;
u64 page_size_cap;
@@ -951,6 +950,7 @@ struct ib_device {
u64 uverbs_cmd_mask;
int uverbs_abi_ver;
+ __be64 node_guid;
u8 node_type;
u8 phys_port_cnt;
};
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index be1bc792ab18..3e5cb5ab2d34 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -168,6 +168,12 @@ typedef uint64_t iscsi_connh_t; /* iSCSI Data-Path connection handle */
#define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
#define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_hostdata - get LLD hostdata from scsi_host
+ * @_hostdata: pointer to scsi host's hostdata
+ **/
#define iscsi_hostdata(_hostdata) ((void*)_hostdata + sizeof(unsigned long))
/*
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 6cb1e2788d8b..c60b8ff2f5e4 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -32,6 +32,12 @@ extern const unsigned char scsi_command_size[8];
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
/*
+ * Special value for scanning to specify scanning or rescanning of all
+ * possible channels, (target) ids, or luns on a given shost.
+ */
+#define SCAN_WILD_CARD ~0
+
+/*
* SCSI opcodes
*/
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 20da282d4abb..7529f4388bb4 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -151,6 +151,5 @@ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
extern void scsi_put_command(struct scsi_cmnd *);
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
extern void scsi_finish_command(struct scsi_cmnd *cmd);
-extern void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd, int retries);
#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index b090a11d7e1c..4d69dee66d4d 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -16,7 +16,6 @@ extern void __scsi_print_sense(const char *name,
extern void scsi_print_driverbyte(int);
extern void scsi_print_hostbyte(int);
extern void scsi_print_status(unsigned char);
-extern int scsi_print_msg(const unsigned char *);
extern const char *scsi_sense_key_string(unsigned char);
extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 85cfd88461c8..e94ca4d36035 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -79,9 +79,9 @@ struct scsi_device {
char inq_periph_qual; /* PQ from INQUIRY data */
unsigned char inquiry_len; /* valid bytes in 'inquiry' */
unsigned char * inquiry; /* INQUIRY response data */
- char * vendor; /* [back_compat] point into 'inquiry' ... */
- char * model; /* ... after scan; point to static string */
- char * rev; /* ... "nullnullnullnull" before scan */
+ const char * vendor; /* [back_compat] point into 'inquiry' ... */
+ const char * model; /* ... after scan; point to static string */
+ const char * rev; /* ... "nullnullnullnull" before scan */
unsigned char current_tag; /* current tag */
struct scsi_target *sdev_target; /* used only for single_lun */
@@ -274,6 +274,12 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
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);
+extern int scsi_execute_async(struct scsi_device *sdev,
+ const unsigned char *cmd, int data_direction,
+ void *buffer, unsigned bufflen, int use_sg,
+ int timeout, int retries, void *privdata,
+ void (*done)(void *, char *, int, int),
+ gfp_t gfp);
static inline unsigned int sdev_channel(struct scsi_device *sdev)
{
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 850dfa877fda..02e26c1672bf 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -15,7 +15,6 @@ struct scsi_driver {
void (*rescan)(struct device *);
int (*issue_flush)(struct device *, sector_t *);
int (*prepare_flush)(struct request_queue *, struct request *);
- void (*end_flush)(struct request_queue *, struct request *);
};
#define to_scsi_driver(drv) \
container_of((drv), struct scsi_driver, gendrv)
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 6cbb1982ed03..467274a764d1 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -5,6 +5,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/workqueue.h>
+#include <linux/mutex.h>
struct block_device;
struct completion;
@@ -296,6 +297,12 @@ struct scsi_host_template {
int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
/*
+ * suspend support
+ */
+ int (*resume)(struct scsi_device *);
+ int (*suspend)(struct scsi_device *);
+
+ /*
* Name of proc directory
*/
char *proc_name;
@@ -392,7 +399,6 @@ struct scsi_host_template {
/*
* ordered write support
*/
- unsigned ordered_flush:1;
unsigned ordered_tag:1;
/*
@@ -464,7 +470,7 @@ struct Scsi_Host {
spinlock_t default_lock;
spinlock_t *host_lock;
- struct semaphore scan_mutex;/* serialize scanning activity */
+ struct mutex scan_mutex;/* serialize scanning activity */
struct list_head eh_cmd_q;
struct task_struct * ehandler; /* Error recovery thread. */
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index f6e0bb484c63..e7b1054adf86 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -30,12 +30,9 @@ struct scsi_transport_template {
struct transport_container device_attrs;
/*
- * If set, call target_parent prior to allocating a scsi_target,
- * so we get the appropriate parent for the target. This function
- * is required for transports like FC and iSCSI that do not put the
- * scsi_target under scsi_host.
+ * If set, called from sysfs and legacy procfs rescanning code.
*/
- struct device *(*target_parent)(struct Scsi_Host *, int, uint);
+ int (*user_scan)(struct Scsi_Host *, uint, uint, uint);
/* The size of the specific transport attribute structure (a
* space of this size will be left at the end of the
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 394f14a5b7cb..cf3fec8be1e3 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -303,6 +303,7 @@ struct fc_host_attrs {
/* Fixed Attributes */
u64 node_name;
u64 port_name;
+ u64 permanent_port_name;
u32 supported_classes;
u8 supported_fc4s[FC_FC4_LIST_SIZE];
char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
@@ -338,6 +339,8 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->node_name)
#define fc_host_port_name(x) \
(((struct fc_host_attrs *)(x)->shost_data)->port_name)
+#define fc_host_permanent_port_name(x) \
+ (((struct fc_host_attrs *)(x)->shost_data)->permanent_port_name)
#define fc_host_supported_classes(x) \
(((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
#define fc_host_supported_fc4s(x) \
@@ -426,6 +429,7 @@ struct fc_function_template {
/* host fixed attributes */
unsigned long show_host_node_name:1;
unsigned long show_host_port_name:1;
+ unsigned long show_host_permanent_port_name:1;
unsigned long show_host_supported_classes:1;
unsigned long show_host_supported_fc4s:1;
unsigned long show_host_symbolic_name:1;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index f25041c386ec..16602a547a63 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -23,8 +23,14 @@
#ifndef SCSI_TRANSPORT_ISCSI_H
#define SCSI_TRANSPORT_ISCSI_H
+#include <linux/device.h>
#include <scsi/iscsi_if.h>
+struct scsi_transport_template;
+struct Scsi_Host;
+struct mempool_zone;
+struct iscsi_cls_conn;
+
/**
* struct iscsi_transport - iSCSI Transport template
*
@@ -48,23 +54,31 @@ struct iscsi_transport {
char *name;
unsigned int caps;
struct scsi_host_template *host_template;
+ /* LLD session/scsi_host data size */
int hostdata_size;
+ /* LLD iscsi_host data size */
+ int ihostdata_size;
+ /* LLD connection data size */
+ int conndata_size;
int max_lun;
unsigned int max_conn;
unsigned int max_cmd_len;
- iscsi_sessionh_t (*create_session) (uint32_t initial_cmdsn,
- struct Scsi_Host *shost);
- void (*destroy_session) (iscsi_sessionh_t session);
- iscsi_connh_t (*create_conn) (iscsi_sessionh_t session, uint32_t cid);
+ struct Scsi_Host *(*create_session) (struct scsi_transport_template *t,
+ uint32_t initial_cmdsn);
+ void (*destroy_session) (struct Scsi_Host *shost);
+ struct iscsi_cls_conn *(*create_conn) (struct Scsi_Host *shost,
+ uint32_t cid);
int (*bind_conn) (iscsi_sessionh_t session, iscsi_connh_t conn,
uint32_t transport_fd, int is_leading);
int (*start_conn) (iscsi_connh_t conn);
void (*stop_conn) (iscsi_connh_t conn, int flag);
- void (*destroy_conn) (iscsi_connh_t conn);
+ void (*destroy_conn) (struct iscsi_cls_conn *conn);
int (*set_param) (iscsi_connh_t conn, enum iscsi_param param,
uint32_t value);
- int (*get_param) (iscsi_connh_t conn, enum iscsi_param param,
- uint32_t *value);
+ int (*get_conn_param) (void *conndata, enum iscsi_param param,
+ uint32_t *value);
+ int (*get_session_param) (struct Scsi_Host *shost,
+ enum iscsi_param param, uint32_t *value);
int (*send_pdu) (iscsi_connh_t conn, struct iscsi_hdr *hdr,
char *data, uint32_t data_size);
void (*get_stats) (iscsi_connh_t conn, struct iscsi_stats *stats);
@@ -73,7 +87,7 @@ struct iscsi_transport {
/*
* transport registration upcalls
*/
-extern int iscsi_register_transport(struct iscsi_transport *tt);
+extern struct scsi_transport_template *iscsi_register_transport(struct iscsi_transport *tt);
extern int iscsi_unregister_transport(struct iscsi_transport *tt);
/*
@@ -83,4 +97,49 @@ extern void iscsi_conn_error(iscsi_connh_t conn, enum iscsi_err error);
extern int iscsi_recv_pdu(iscsi_connh_t conn, struct iscsi_hdr *hdr,
char *data, uint32_t data_size);
+struct iscsi_cls_conn {
+ struct list_head conn_list; /* item in connlist */
+ void *dd_data; /* LLD private data */
+ struct iscsi_transport *transport;
+ iscsi_connh_t connh;
+ int active; /* must be accessed with the connlock */
+ struct device dev; /* sysfs transport/container device */
+ struct mempool_zone *z_error;
+ struct mempool_zone *z_pdu;
+ struct list_head freequeue;
+};
+
+#define iscsi_dev_to_conn(_dev) \
+ container_of(_dev, struct iscsi_cls_conn, dev)
+
+struct iscsi_cls_session {
+ struct list_head list; /* item in session_list */
+ struct iscsi_transport *transport;
+ struct device dev; /* sysfs transport/container device */
+};
+
+#define iscsi_dev_to_session(_dev) \
+ container_of(_dev, struct iscsi_cls_session, dev)
+
+#define iscsi_session_to_shost(_session) \
+ dev_to_shost(_session->dev.parent)
+
+/*
+ * session and connection functions that can be used by HW iSCSI LLDs
+ */
+extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
+ struct iscsi_transport *t);
+extern int iscsi_destroy_session(struct iscsi_cls_session *session);
+extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
+ uint32_t cid);
+extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
+
+/*
+ * session functions used by software iscsi
+ */
+extern struct Scsi_Host *
+iscsi_transport_create_session(struct scsi_transport_template *scsit,
+ struct iscsi_transport *transport);
+extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
+
#endif
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 6bdc4afb2483..fb5a2ffae939 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -22,8 +22,12 @@
#include <linux/config.h>
#include <linux/transport_class.h>
+#include <linux/mutex.h>
struct scsi_transport_template;
+struct scsi_target;
+struct scsi_device;
+struct Scsi_Host;
struct spi_transport_attrs {
int period; /* value in the PPR/SDTR command */
@@ -51,7 +55,7 @@ struct spi_transport_attrs {
unsigned int support_qas; /* supports quick arbitration and selection */
/* Private Fields */
unsigned int dv_pending:1; /* Internal flag */
- struct semaphore dv_sem; /* semaphore to serialise dv */
+ struct mutex dv_mutex; /* semaphore to serialise dv */
};
enum spi_signal_type {
@@ -143,5 +147,6 @@ void spi_release_transport(struct scsi_transport_template *);
void spi_schedule_dv_device(struct scsi_device *);
void spi_dv_device(struct scsi_device *);
void spi_display_xfer_agreement(struct scsi_target *);
+int spi_print_msg(const unsigned char *);
#endif /* SCSI_TRANSPORT_SPI_H */
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 7f0ca79d6c98..b0b3ea7b365e 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -391,65 +391,35 @@
*
*/
-typedef struct _snd_ac97_bus ac97_bus_t;
-typedef struct _snd_ac97_bus_ops ac97_bus_ops_t;
-typedef struct _snd_ac97_template ac97_template_t;
-typedef struct _snd_ac97 ac97_t;
-
-enum ac97_pcm_cfg {
- AC97_PCM_CFG_FRONT = 2,
- AC97_PCM_CFG_REAR = 10, /* alias surround */
- AC97_PCM_CFG_LFE = 11, /* center + lfe */
- AC97_PCM_CFG_40 = 4, /* front + rear */
- AC97_PCM_CFG_51 = 6, /* front + rear + center/lfe */
- AC97_PCM_CFG_SPDIF = 20
-};
-
-/* PCM allocation */
-struct ac97_pcm {
- ac97_bus_t *bus;
- unsigned int stream: 1, /* stream type: 1 = capture */
- exclusive: 1, /* exclusive mode, don't override with other pcms */
- copy_flag: 1, /* lowlevel driver must fill all entries */
- spdif: 1; /* spdif pcm */
- unsigned short aslots; /* active slots */
- unsigned int rates; /* available rates */
- struct {
- unsigned short slots; /* driver input: requested AC97 slot numbers */
- unsigned short rslots[4]; /* allocated slots per codecs */
- unsigned char rate_table[4];
- ac97_t *codec[4]; /* allocated codecs */
- } r[2]; /* 0 = standard rates, 1 = double rates */
- unsigned long private_value; /* used by the hardware driver */
-};
+struct snd_ac97;
struct snd_ac97_build_ops {
- int (*build_3d) (ac97_t *ac97);
- int (*build_specific) (ac97_t *ac97);
- int (*build_spdif) (ac97_t *ac97);
- int (*build_post_spdif) (ac97_t *ac97);
+ int (*build_3d) (struct snd_ac97 *ac97);
+ int (*build_specific) (struct snd_ac97 *ac97);
+ int (*build_spdif) (struct snd_ac97 *ac97);
+ int (*build_post_spdif) (struct snd_ac97 *ac97);
#ifdef CONFIG_PM
- void (*suspend) (ac97_t *ac97);
- void (*resume) (ac97_t *ac97);
+ void (*suspend) (struct snd_ac97 *ac97);
+ void (*resume) (struct snd_ac97 *ac97);
#endif
- void (*update_jacks) (ac97_t *ac97); /* for jack-sharing */
+ void (*update_jacks) (struct snd_ac97 *ac97); /* for jack-sharing */
};
-struct _snd_ac97_bus_ops {
- void (*reset) (ac97_t *ac97);
- void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val);
- unsigned short (*read) (ac97_t *ac97, unsigned short reg);
- void (*wait) (ac97_t *ac97);
- void (*init) (ac97_t *ac97);
+struct snd_ac97_bus_ops {
+ void (*reset) (struct snd_ac97 *ac97);
+ void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
+ unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);
+ void (*wait) (struct snd_ac97 *ac97);
+ void (*init) (struct snd_ac97 *ac97);
};
-struct _snd_ac97_bus {
+struct snd_ac97_bus {
/* -- lowlevel (hardware) driver specific -- */
- ac97_bus_ops_t *ops;
+ struct snd_ac97_bus_ops *ops;
void *private_data;
- void (*private_free) (ac97_bus_t *bus);
+ void (*private_free) (struct snd_ac97_bus *bus);
/* --- */
- snd_card_t *card;
+ struct snd_card *card;
unsigned short num; /* bus number */
unsigned short no_vra: 1, /* bridge doesn't support VRA */
dra: 1, /* bridge supports double rate */
@@ -459,13 +429,13 @@ struct _snd_ac97_bus {
unsigned short used_slots[2][4]; /* actually used PCM slots */
unsigned short pcms_count; /* count of PCMs */
struct ac97_pcm *pcms;
- ac97_t *codec[4];
- snd_info_entry_t *proc;
+ struct snd_ac97 *codec[4];
+ struct snd_info_entry *proc;
};
-struct _snd_ac97_template {
+struct snd_ac97_template {
void *private_data;
- void (*private_free) (ac97_t *ac97);
+ void (*private_free) (struct snd_ac97 *ac97);
struct pci_dev *pci; /* assigned PCI device - used for quirks */
unsigned short num; /* number of codec: 0 = primary, 1 = secondary */
unsigned short addr; /* physical address of codec [0-3] */
@@ -474,16 +444,16 @@ struct _snd_ac97_template {
DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */
};
-struct _snd_ac97 {
+struct snd_ac97 {
/* -- lowlevel (hardware) driver specific -- */
struct snd_ac97_build_ops * build_ops;
void *private_data;
- void (*private_free) (ac97_t *ac97);
+ void (*private_free) (struct snd_ac97 *ac97);
/* --- */
- ac97_bus_t *bus;
+ struct snd_ac97_bus *bus;
struct pci_dev *pci; /* assigned PCI device - used for quirks */
- snd_info_entry_t *proc;
- snd_info_entry_t *proc_regs;
+ struct snd_info_entry *proc;
+ struct snd_info_entry *proc_regs;
unsigned short subsystem_vendor;
unsigned short subsystem_device;
struct semaphore reg_mutex;
@@ -517,43 +487,47 @@ struct _snd_ac97 {
struct device dev;
};
-#define to_ac97_t(d) container_of(d, struct _snd_ac97, dev)
+#define to_ac97_t(d) container_of(d, struct snd_ac97, dev)
/* conditions */
-static inline int ac97_is_audio(ac97_t * ac97)
+static inline int ac97_is_audio(struct snd_ac97 * ac97)
{
return (ac97->scaps & AC97_SCAP_AUDIO);
}
-static inline int ac97_is_modem(ac97_t * ac97)
+static inline int ac97_is_modem(struct snd_ac97 * ac97)
{
return (ac97->scaps & AC97_SCAP_MODEM);
}
-static inline int ac97_is_rev22(ac97_t * ac97)
+static inline int ac97_is_rev22(struct snd_ac97 * ac97)
{
return (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_22;
}
-static inline int ac97_can_amap(ac97_t * ac97)
+static inline int ac97_can_amap(struct snd_ac97 * ac97)
{
return (ac97->ext_id & AC97_EI_AMAP) != 0;
}
-static inline int ac97_can_spdif(ac97_t * ac97)
+static inline int ac97_can_spdif(struct snd_ac97 * ac97)
{
return (ac97->ext_id & AC97_EI_SPDIF) != 0;
}
/* functions */
-int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, void *private_data, ac97_bus_t **rbus); /* create new AC97 bus */
-int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97); /* create mixer controls */
-const char *snd_ac97_get_short_name(ac97_t *ac97);
-
-void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value);
-unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg);
-void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value);
-int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value);
-int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value);
+/* create new AC97 bus */
+int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
+ void *private_data, struct snd_ac97_bus **rbus);
+/* create mixer controls */
+int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
+ struct snd_ac97 **rac97);
+const char *snd_ac97_get_short_name(struct snd_ac97 *ac97);
+
+void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);
+unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg);
+void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);
+int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value);
+int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value);
#ifdef CONFIG_PM
-void snd_ac97_suspend(ac97_t *ac97);
-void snd_ac97_resume(ac97_t *ac97);
+void snd_ac97_suspend(struct snd_ac97 *ac97);
+void snd_ac97_resume(struct snd_ac97 *ac97);
#endif
/* quirk types */
@@ -567,6 +541,7 @@ enum {
AC97_TUNE_ALC_JACK, /* for Realtek, enable JACK detection */
AC97_TUNE_INV_EAPD, /* inverted EAPD implementation */
AC97_TUNE_MUTE_LED, /* EAPD bit works as mute LED */
+ AC97_TUNE_HP_MUTE_LED, /* EAPD bit works as mute LED, use headphone control as master */
};
struct ac97_quirk {
@@ -578,24 +553,46 @@ struct ac97_quirk {
int type; /* quirk type above */
};
-int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *override);
-int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate);
+int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override);
+int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate);
+
+/*
+ * PCM allocation
+ */
+
+enum ac97_pcm_cfg {
+ AC97_PCM_CFG_FRONT = 2,
+ AC97_PCM_CFG_REAR = 10, /* alias surround */
+ AC97_PCM_CFG_LFE = 11, /* center + lfe */
+ AC97_PCM_CFG_40 = 4, /* front + rear */
+ AC97_PCM_CFG_51 = 6, /* front + rear + center/lfe */
+ AC97_PCM_CFG_SPDIF = 20
+};
+
+struct ac97_pcm {
+ struct snd_ac97_bus *bus;
+ unsigned int stream: 1, /* stream type: 1 = capture */
+ exclusive: 1, /* exclusive mode, don't override with other pcms */
+ copy_flag: 1, /* lowlevel driver must fill all entries */
+ spdif: 1; /* spdif pcm */
+ unsigned short aslots; /* active slots */
+ unsigned int rates; /* available rates */
+ struct {
+ unsigned short slots; /* driver input: requested AC97 slot numbers */
+ unsigned short rslots[4]; /* allocated slots per codecs */
+ unsigned char rate_table[4];
+ struct snd_ac97 *codec[4]; /* allocated codecs */
+ } r[2]; /* 0 = standard rates, 1 = double rates */
+ unsigned long private_value; /* used by the hardware driver */
+};
-int snd_ac97_pcm_assign(ac97_bus_t *ac97,
+int snd_ac97_pcm_assign(struct snd_ac97_bus *ac97,
unsigned short pcms_count,
const struct ac97_pcm *pcms);
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
enum ac97_pcm_cfg cfg, unsigned short slots);
int snd_ac97_pcm_close(struct ac97_pcm *pcm);
-int snd_ac97_pcm_double_rate_rules(snd_pcm_runtime_t *runtime);
-
-struct ac97_enum {
- unsigned char reg;
- unsigned char shift_l;
- unsigned char shift_r;
- unsigned short mask;
- const char **texts;
-};
+int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime);
/* ad hoc AC97 device driver access */
extern struct bus_type ac97_bus_type;
diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h
index ca2e0e4fa937..b3aa62ee3c8d 100644
--- a/include/sound/ad1816a.h
+++ b/include/sound/ad1816a.h
@@ -123,9 +123,7 @@
#define AD1816A_CAPTURE_NOT_EQUAL 0x1000
#define AD1816A_WSS_ENABLE 0x8000
-typedef struct _snd_ad1816a ad1816a_t;
-
-struct _snd_ad1816a {
+struct snd_ad1816a {
unsigned long port;
struct resource *res_port;
int irq;
@@ -140,15 +138,15 @@ struct _snd_ad1816a {
unsigned short mode;
unsigned int clock_freq;
- snd_card_t *card;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int p_dma_size;
unsigned int c_dma_size;
- snd_timer_t *timer;
+ struct snd_timer *timer;
};
@@ -165,11 +163,11 @@ struct _snd_ad1816a {
AD1816A_MODE_TIMER)
-extern int snd_ad1816a_create(snd_card_t *card, unsigned long port,
+extern int snd_ad1816a_create(struct snd_card *card, unsigned long port,
int irq, int dma1, int dma2,
- ad1816a_t **chip);
+ struct snd_ad1816a **chip);
-extern int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm);
-extern int snd_ad1816a_mixer(ad1816a_t *chip);
+extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm);
+extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
#endif /* __SOUND_AD1816A_H */
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index 7e33b11037f2..1a2759f3a292 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -127,7 +127,7 @@
#define AD1848_THINKPAD_CTL_PORT2 0x15e9
#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
-struct _snd_ad1848 {
+struct snd_ad1848 {
unsigned long port; /* i/o port */
struct resource *res_port;
int irq; /* IRQ line */
@@ -137,10 +137,10 @@ struct _snd_ad1848 {
unsigned short hardware; /* see to AD1848_HW_XXXX */
unsigned short single_dma:1; /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
- snd_card_t *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_card *card;
unsigned char image[32]; /* SGalaxy needs an access to extended registers */
int mce_bit;
@@ -148,25 +148,28 @@ struct _snd_ad1848 {
int dma_size;
int thinkpad_flag; /* Thinkpad CS4248 needs some extra help */
+#ifdef CONFIG_PM
+ void (*suspend)(struct snd_ad1848 *chip);
+ void (*resume)(struct snd_ad1848 *chip);
+#endif
+
spinlock_t reg_lock;
struct semaphore open_mutex;
};
-typedef struct _snd_ad1848 ad1848_t;
-
/* exported functions */
-void snd_ad1848_out(ad1848_t *chip, unsigned char reg, unsigned char value);
+void snd_ad1848_out(struct snd_ad1848 *chip, unsigned char reg, unsigned char value);
-int snd_ad1848_create(snd_card_t * card,
+int snd_ad1848_create(struct snd_card *card,
unsigned long port,
int irq, int dma,
unsigned short hardware,
- ad1848_t ** chip);
+ struct snd_ad1848 ** chip);
-int snd_ad1848_pcm(ad1848_t * chip, int device, snd_pcm_t **rpcm);
-const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction);
-int snd_ad1848_mixer(ad1848_t * chip);
+int snd_ad1848_pcm(struct snd_ad1848 * chip, int device, struct snd_pcm **rpcm);
+const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction);
+int snd_ad1848_mixer(struct snd_ad1848 * chip);
/* exported mixer stuffs */
enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE };
@@ -176,7 +179,7 @@ enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE };
#define AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) \
((left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22))
-int snd_ad1848_add_ctl(ad1848_t *chip, const char *name, int index, int type, unsigned long value);
+int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value);
/* for ease of use */
struct ad1848_mix_elem {
@@ -198,7 +201,7 @@ struct ad1848_mix_elem {
.type = AD1848_MIX_DOUBLE, \
.private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) }
-static inline int snd_ad1848_add_ctl_elem(ad1848_t *chip, const struct ad1848_mix_elem *c)
+static inline int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c)
{
return snd_ad1848_add_ctl(chip, c->name, c->index, c->type, c->private_value);
}
diff --git a/include/sound/ainstr_fm.h b/include/sound/ainstr_fm.h
index 0ec02953815a..c4afb1f121fe 100644
--- a/include/sound/ainstr_fm.h
+++ b/include/sound/ainstr_fm.h
@@ -39,13 +39,13 @@
* FM operator
*/
-typedef struct fm_operator {
+struct fm_operator {
unsigned char am_vib;
unsigned char ksl_level;
unsigned char attack_decay;
unsigned char sustain_release;
unsigned char wave_select;
-} fm_operator_t;
+};
/*
* Instrument
@@ -54,11 +54,11 @@ typedef struct fm_operator {
#define FM_PATCH_OPL2 0x01 /* OPL2 2 operators FM instrument */
#define FM_PATCH_OPL3 0x02 /* OPL3 4 operators FM instrument */
-typedef struct {
+struct fm_instrument {
unsigned int share_id[4]; /* share id - zero = no sharing */
unsigned char type; /* instrument type */
- fm_operator_t op[4];
+ struct fm_operator op[4];
unsigned char feedback_connection[2];
unsigned char echo_delay;
@@ -68,7 +68,7 @@ typedef struct {
unsigned char fix_dur;
unsigned char modes;
unsigned char fix_key;
-} fm_instrument_t;
+};
/*
*
@@ -88,25 +88,25 @@ typedef struct {
* FM operator
*/
-typedef struct fm_xoperator {
+struct fm_xoperator {
__u8 am_vib;
__u8 ksl_level;
__u8 attack_decay;
__u8 sustain_release;
__u8 wave_select;
-} fm_xoperator_t;
+};
/*
* Instrument
*/
-typedef struct fm_xinstrument {
+struct fm_xinstrument {
__u32 stype; /* structure type */
__u32 share_id[4]; /* share id - zero = no sharing */
__u8 type; /* instrument type */
- fm_xoperator_t op[4]; /* fm operators */
+ struct fm_xoperator op[4]; /* fm operators */
__u8 feedback_connection[2];
__u8 echo_delay;
@@ -116,15 +116,19 @@ typedef struct fm_xinstrument {
__u8 fix_dur;
__u8 modes;
__u8 fix_key;
-} fm_xinstrument_t;
+};
#ifdef __KERNEL__
#include "seq_instr.h"
-int snd_seq_fm_init(snd_seq_kinstr_ops_t * ops,
- snd_seq_kinstr_ops_t * next);
+int snd_seq_fm_init(struct snd_seq_kinstr_ops * ops,
+ struct snd_seq_kinstr_ops * next);
#endif
+/* typedefs for compatibility to user-space */
+typedef struct fm_xoperator fm_xoperator_t;
+typedef struct fm_xinstrument fm_xinstrument_t;
+
#endif /* __SOUND_AINSTR_FM_H */
diff --git a/include/sound/ainstr_gf1.h b/include/sound/ainstr_gf1.h
index ae2ddda63971..47726fe0f46d 100644
--- a/include/sound/ainstr_gf1.h
+++ b/include/sound/ainstr_gf1.h
@@ -52,7 +52,7 @@
* Wavetable definitions
*/
-typedef struct gf1_wave {
+struct gf1_wave {
unsigned int share_id[4]; /* share id - zero = no sharing */
unsigned int format; /* wave format */
@@ -88,7 +88,7 @@ typedef struct gf1_wave {
unsigned short scale_factor; /* 0-2048 or 0-2 */
struct gf1_wave *next;
-} gf1_wave_t;
+};
/*
* Instrument
@@ -103,7 +103,7 @@ typedef struct gf1_wave {
#define IWFFFF_EFFECT_CHORUS 2
#define IWFFFF_EFFECT_ECHO 3
-typedef struct {
+struct gf1_instrument {
unsigned short exclusion;
unsigned short exclusion_group; /* 0 - none, 1-65535 */
@@ -112,8 +112,8 @@ typedef struct {
unsigned char effect2; /* effect 2 */
unsigned char effect2_depth; /* 0-127 */
- gf1_wave_t *wave; /* first waveform */
-} gf1_instrument_t;
+ struct gf1_wave *wave; /* first waveform */
+};
/*
*
@@ -135,7 +135,7 @@ typedef struct {
* Wavetable definitions
*/
-typedef struct gf1_xwave {
+struct gf1_xwave {
__u32 stype; /* structure type */
__u32 share_id[4]; /* share id - zero = no sharing */
@@ -165,13 +165,13 @@ typedef struct gf1_xwave {
__u8 vibrato_depth;
__u16 scale_frequency;
__u16 scale_factor; /* 0-2048 or 0-2 */
-} gf1_xwave_t;
+};
/*
* Instrument
*/
-typedef struct gf1_xinstrument {
+struct gf1_xinstrument {
__u32 stype;
__u16 exclusion;
@@ -181,7 +181,7 @@ typedef struct gf1_xinstrument {
__u8 effect1_depth; /* 0-127 */
__u8 effect2; /* effect 2 */
__u8 effect2_depth; /* 0-127 */
-} gf1_xinstrument_t;
+};
/*
* Instrument info
@@ -191,35 +191,39 @@ typedef struct gf1_xinstrument {
#define GF1_INFO_TREMOLO (1<<1)
#define GF1_INFO_VIBRATO (1<<2)
-typedef struct gf1_info {
+struct gf1_info {
unsigned char flags; /* supported wave flags */
unsigned char pad[3];
unsigned int features; /* supported features */
unsigned int max8_len; /* maximum 8-bit wave length */
unsigned int max16_len; /* maximum 16-bit wave length */
-} gf1_info_t;
+};
#ifdef __KERNEL__
#include "seq_instr.h"
-typedef struct {
+struct snd_gf1_ops {
void *private_data;
- int (*info)(void *private_data, gf1_info_t *info);
- int (*put_sample)(void *private_data, gf1_wave_t *wave,
+ int (*info)(void *private_data, struct gf1_info *info);
+ int (*put_sample)(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic);
- int (*get_sample)(void *private_data, gf1_wave_t *wave,
+ int (*get_sample)(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic);
- int (*remove_sample)(void *private_data, gf1_wave_t *wave,
+ int (*remove_sample)(void *private_data, struct gf1_wave *wave,
int atomic);
- void (*notify)(void *private_data, snd_seq_kinstr_t *instr, int what);
- snd_seq_kinstr_ops_t kops;
-} snd_gf1_ops_t;
+ void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
+ struct snd_seq_kinstr_ops kops;
+};
-int snd_seq_gf1_init(snd_gf1_ops_t *ops,
+int snd_seq_gf1_init(struct snd_gf1_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next);
+ struct snd_seq_kinstr_ops *next);
#endif
+/* typedefs for compatibility to user-space */
+typedef struct gf1_xwave gf1_xwave_t;
+typedef struct gf1_xinstrument gf1_xinstrument_t;
+
#endif /* __SOUND_AINSTR_GF1_H */
diff --git a/include/sound/ainstr_iw.h b/include/sound/ainstr_iw.h
index 8adf744926ff..251feaf1b388 100644
--- a/include/sound/ainstr_iw.h
+++ b/include/sound/ainstr_iw.h
@@ -54,7 +54,7 @@
* Wavetable definitions
*/
-typedef struct iwffff_wave {
+struct iwffff_wave {
unsigned int share_id[4]; /* share id - zero = no sharing */
unsigned int format; /* wave format */
@@ -76,7 +76,7 @@ typedef struct iwffff_wave {
unsigned char pad;
struct iwffff_wave *next;
-} iwffff_wave_t;
+};
/*
* Layer
@@ -85,13 +85,13 @@ typedef struct iwffff_wave {
#define IWFFFF_LFO_SHAPE_TRIANGLE 0
#define IWFFFF_LFO_SHAPE_POSTRIANGLE 1
-typedef struct iwffff_lfo {
+struct iwffff_lfo {
unsigned short freq; /* (0-2047) 0.01Hz - 21.5Hz */
signed short depth; /* volume +- (0-255) 0.48675dB/step */
signed short sweep; /* 0 - 950 deciseconds */
unsigned char shape; /* see to IWFFFF_LFO_SHAPE_XXXX */
unsigned char delay; /* 0 - 255 deciseconds */
-} iwffff_lfo_t;
+};
#define IWFFFF_ENV_FLAG_RETRIGGER 0x0001 /* flag - retrigger */
@@ -102,12 +102,12 @@ typedef struct iwffff_lfo {
#define IWFFFF_ENV_INDEX_VELOCITY 0x0001 /* index - velocity */
#define IWFFFF_ENV_INDEX_FREQUENCY 0x0002 /* index - frequency */
-typedef struct iwffff_env_point {
+struct iwffff_env_point {
unsigned short offset;
unsigned short rate;
-} iwffff_env_point_t;
+};
-typedef struct iwffff_env_record {
+struct iwffff_env_record {
unsigned short nattack;
unsigned short nrelease;
unsigned short sustain_offset;
@@ -118,15 +118,15 @@ typedef struct iwffff_env_record {
struct iwffff_env_record *next;
/* points are stored here */
/* count of points = nattack + nrelease */
-} iwffff_env_record_t;
+};
-typedef struct iwffff_env {
+struct iwffff_env {
unsigned char flags;
unsigned char mode;
unsigned char index;
unsigned char pad;
struct iwffff_env_record *record;
-} iwffff_env_t;
+};
#define IWFFFF_LAYER_FLAG_RETRIGGER 0x0001 /* retrigger */
@@ -138,7 +138,7 @@ typedef struct iwffff_env {
#define IWFFFF_LAYER_EVENT_RETRIG 0x0002 /* layer event - retrigger */
#define IWFFFF_LAYER_EVENT_LEGATO 0x0003 /* layer event - legato */
-typedef struct iwffff_layer {
+struct iwffff_layer {
unsigned char flags;
unsigned char velocity_mode;
unsigned char layer_event;
@@ -147,17 +147,17 @@ typedef struct iwffff_layer {
unsigned char pan; /* pan offset from CC1 (0 left - 127 right) */
unsigned char pan_freq_scale; /* position based on frequency (0-127) */
unsigned char attenuation; /* 0-127 (no corresponding midi controller) */
- iwffff_lfo_t tremolo; /* tremolo effect */
- iwffff_lfo_t vibrato; /* vibrato effect */
+ struct iwffff_lfo tremolo; /* tremolo effect */
+ struct iwffff_lfo vibrato; /* vibrato effect */
unsigned short freq_scale; /* 0-2048, 1024 is equal to semitone scaling */
unsigned char freq_center; /* center for keyboard frequency scaling */
unsigned char pad;
- iwffff_env_t penv; /* pitch envelope */
- iwffff_env_t venv; /* volume envelope */
+ struct iwffff_env penv; /* pitch envelope */
+ struct iwffff_env venv; /* volume envelope */
- iwffff_wave_t *wave;
+ struct iwffff_wave *wave;
struct iwffff_layer *next;
-} iwffff_layer_t;
+};
/*
* Instrument
@@ -177,7 +177,7 @@ typedef struct iwffff_layer {
#define IWFFFF_EFFECT_CHORUS 2
#define IWFFFF_EFFECT_ECHO 3
-typedef struct {
+struct iwffff_instrument {
unsigned short exclusion;
unsigned short layer_type;
unsigned short exclusion_group; /* 0 - none, 1-65535 */
@@ -187,8 +187,8 @@ typedef struct {
unsigned char effect2; /* effect 2 */
unsigned char effect2_depth; /* 0-127 */
- iwffff_layer_t *layer; /* first layer */
-} iwffff_instrument_t;
+ struct iwffff_layer *layer; /* first layer */
+};
/*
*
@@ -216,7 +216,7 @@ typedef struct {
* Wavetable definitions
*/
-typedef struct iwffff_xwave {
+struct iwffff_xwave {
__u32 stype; /* structure type */
__u32 share_id[4]; /* share id - zero = no sharing */
@@ -234,26 +234,26 @@ typedef struct iwffff_xwave {
__u8 low_note; /* lower frequency range for this waveform */
__u8 high_note; /* higher frequency range for this waveform */
__u8 pad;
-} iwffff_xwave_t;
+};
/*
* Layer
*/
-typedef struct iwffff_xlfo {
+struct iwffff_xlfo {
__u16 freq; /* (0-2047) 0.01Hz - 21.5Hz */
__s16 depth; /* volume +- (0-255) 0.48675dB/step */
__s16 sweep; /* 0 - 950 deciseconds */
__u8 shape; /* see to ULTRA_IW_LFO_SHAPE_XXXX */
__u8 delay; /* 0 - 255 deciseconds */
-} iwffff_xlfo_t;
+};
-typedef struct iwffff_xenv_point {
+struct iwffff_xenv_point {
__u16 offset;
__u16 rate;
-} iwffff_xenv_point_t;
+};
-typedef struct iwffff_xenv_record {
+struct iwffff_xenv_record {
__u32 stype;
__u16 nattack;
__u16 nrelease;
@@ -264,16 +264,16 @@ typedef struct iwffff_xenv_record {
__u8 pad;
/* points are stored here.. */
/* count of points = nattack + nrelease */
-} iwffff_xenv_record_t;
+};
-typedef struct iwffff_xenv {
+struct iwffff_xenv {
__u8 flags;
__u8 mode;
__u8 index;
__u8 pad;
-} iwffff_xenv_t;
+};
-typedef struct iwffff_xlayer {
+struct iwffff_xlayer {
__u32 stype;
__u8 flags;
__u8 velocity_mode;
@@ -283,20 +283,20 @@ typedef struct iwffff_xlayer {
__u8 pan; /* pan offset from CC1 (0 left - 127 right) */
__u8 pan_freq_scale; /* position based on frequency (0-127) */
__u8 attenuation; /* 0-127 (no corresponding midi controller) */
- iwffff_xlfo_t tremolo; /* tremolo effect */
- iwffff_xlfo_t vibrato; /* vibrato effect */
+ struct iwffff_xlfo tremolo; /* tremolo effect */
+ struct iwffff_xlfo vibrato; /* vibrato effect */
__u16 freq_scale; /* 0-2048, 1024 is equal to semitone scaling */
__u8 freq_center; /* center for keyboard frequency scaling */
__u8 pad;
- iwffff_xenv_t penv; /* pitch envelope */
- iwffff_xenv_t venv; /* volume envelope */
-} iwffff_xlayer_t;
+ struct iwffff_xenv penv; /* pitch envelope */
+ struct iwffff_xenv venv; /* volume envelope */
+};
/*
* Instrument
*/
-typedef struct iwffff_xinstrument {
+struct iwffff_xinstrument {
__u32 stype;
__u16 exclusion;
@@ -307,7 +307,7 @@ typedef struct iwffff_xinstrument {
__u8 effect1_depth; /* 0-127 */
__u8 effect2; /* effect 2 */
__u8 effect2_depth; /* 0-127 */
-} iwffff_xinstrument_t;
+};
/*
* ROM support
@@ -316,7 +316,7 @@ typedef struct iwffff_xinstrument {
#define IWFFFF_ROM_HDR_SIZE 512
-typedef struct {
+struct iwffff_rom_header {
__u8 iwave[8];
__u8 revision;
__u8 series_number;
@@ -328,7 +328,7 @@ typedef struct {
__u8 copyright[128];
__u8 vendor_name[64];
__u8 description[128];
-} iwffff_rom_header_t;
+};
/*
* Instrument info
@@ -339,35 +339,46 @@ typedef struct {
#define IWFFFF_INFO_LFO_TREMOLO (1<<2)
#define IWFFFF_INFO_LFO_TREMOLO_SHAPE (1<<3)
-typedef struct iwffff_info {
+struct iwffff_info {
unsigned int format; /* supported format bits */
unsigned int effects; /* supported effects (1 << IWFFFF_EFFECT*) */
unsigned int lfos; /* LFO effects */
unsigned int max8_len; /* maximum 8-bit wave length */
unsigned int max16_len; /* maximum 16-bit wave length */
-} iwffff_info_t;
+};
#ifdef __KERNEL__
#include "seq_instr.h"
-typedef struct {
+struct snd_iwffff_ops {
void *private_data;
- int (*info)(void *private_data, iwffff_info_t *info);
- int (*put_sample)(void *private_data, iwffff_wave_t *wave,
+ int (*info)(void *private_data, struct iwffff_info *info);
+ int (*put_sample)(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic);
- int (*get_sample)(void *private_data, iwffff_wave_t *wave,
+ int (*get_sample)(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic);
- int (*remove_sample)(void *private_data, iwffff_wave_t *wave,
+ int (*remove_sample)(void *private_data, struct iwffff_wave *wave,
int atomic);
- void (*notify)(void *private_data, snd_seq_kinstr_t *instr, int what);
- snd_seq_kinstr_ops_t kops;
-} snd_iwffff_ops_t;
+ void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
+ struct snd_seq_kinstr_ops kops;
+};
-int snd_seq_iwffff_init(snd_iwffff_ops_t *ops,
+int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next);
+ struct snd_seq_kinstr_ops *next);
#endif
+/* typedefs for compatibility to user-space */
+typedef struct iwffff_xwave iwffff_xwave_t;
+typedef struct iwffff_xlfo iwffff_xlfo_t;
+typedef struct iwffff_xenv_point iwffff_xenv_point_t;
+typedef struct iwffff_xenv_record iwffff_xenv_record_t;
+typedef struct iwffff_xenv iwffff_xenv_t;
+typedef struct iwffff_xlayer iwffff_xlayer_t;
+typedef struct iwffff_xinstrument iwffff_xinstrument_t;
+typedef struct iwffff_rom_header iwffff_rom_header_t;
+typedef struct iwffff_info iwffff_info_t;
+
#endif /* __SOUND_AINSTR_IW_H */
diff --git a/include/sound/ainstr_simple.h b/include/sound/ainstr_simple.h
index 40824b4ab23d..5eead12e58ae 100644
--- a/include/sound/ainstr_simple.h
+++ b/include/sound/ainstr_simple.h
@@ -61,18 +61,18 @@
* instrument info
*/
-typedef struct simple_instrument_info {
+struct simple_instrument_info {
unsigned int format; /* supported format bits */
unsigned int effects; /* supported effects (1 << SIMPLE_EFFECT_*) */
unsigned int max8_len; /* maximum 8-bit wave length */
unsigned int max16_len; /* maximum 16-bit wave length */
-} simple_instrument_info_t;
+};
/*
* Instrument
*/
-typedef struct {
+struct simple_instrument {
unsigned int share_id[4]; /* share id - zero = no sharing */
unsigned int format; /* wave format */
@@ -92,7 +92,7 @@ typedef struct {
unsigned char effect1_depth; /* 0-127 */
unsigned char effect2; /* effect 2 */
unsigned char effect2_depth; /* 0-127 */
-} simple_instrument_t;
+};
/*
*
@@ -112,7 +112,7 @@ typedef struct {
* Instrument
*/
-typedef struct simple_xinstrument {
+struct simple_xinstrument {
__u32 stype;
__u32 share_id[4]; /* share id - zero = no sharing */
@@ -128,29 +128,32 @@ typedef struct simple_xinstrument {
__u8 effect1_depth; /* 0-127 */
__u8 effect2; /* effect 2 */
__u8 effect2_depth; /* 0-127 */
-} simple_xinstrument_t;
+};
#ifdef __KERNEL__
#include "seq_instr.h"
-typedef struct {
+struct snd_simple_ops {
void *private_data;
- int (*info)(void *private_data, simple_instrument_info_t *info);
- int (*put_sample)(void *private_data, simple_instrument_t *instr,
+ int (*info)(void *private_data, struct simple_instrument_info *info);
+ int (*put_sample)(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic);
- int (*get_sample)(void *private_data, simple_instrument_t *instr,
+ int (*get_sample)(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic);
- int (*remove_sample)(void *private_data, simple_instrument_t *instr,
+ int (*remove_sample)(void *private_data, struct simple_instrument *instr,
int atomic);
- void (*notify)(void *private_data, snd_seq_kinstr_t *instr, int what);
- snd_seq_kinstr_ops_t kops;
-} snd_simple_ops_t;
+ void (*notify)(void *private_data, struct snd_seq_kinstr *instr, int what);
+ struct snd_seq_kinstr_ops kops;
+};
-int snd_seq_simple_init(snd_simple_ops_t *ops,
+int snd_seq_simple_init(struct snd_simple_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next);
+ struct snd_seq_kinstr_ops *next);
#endif
+/* typedefs for compatibility to user-space */
+typedef struct simple_xinstrument simple_xinstrument_t;
+
#endif /* __SOUND_AINSTR_SIMPLE_H */
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index f3f2c3e5ae51..11702aa0bea9 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -163,10 +163,8 @@
typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data);
typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr);
-typedef struct ak4114 ak4114_t;
-
struct ak4114 {
- snd_card_t * card;
+ struct snd_card *card;
ak4114_write_t * write;
ak4114_read_t * read;
void * private_data;
@@ -174,9 +172,9 @@ struct ak4114 {
spinlock_t lock;
unsigned char regmap[7];
unsigned char txcsb[5];
- snd_kcontrol_t *kctls[AK4114_CONTROLS];
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_kcontrol *kctls[AK4114_CONTROLS];
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned long parity_errors;
unsigned long v_bit_errors;
unsigned long qcrc_errors;
@@ -186,20 +184,20 @@ struct ak4114 {
struct workqueue_struct *workqueue;
struct work_struct work;
void *change_callback_private;
- void (*change_callback)(ak4114_t *ak4114, unsigned char c0, unsigned char c1);
+ void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
};
-int snd_ak4114_create(snd_card_t *card,
+int snd_ak4114_create(struct snd_card *card,
ak4114_read_t *read, ak4114_write_t *write,
unsigned char pgm[7], unsigned char txcsb[5],
- void *private_data, ak4114_t **r_ak4114);
-void snd_ak4114_reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
-void snd_ak4114_reinit(ak4114_t *ak4114);
-int snd_ak4114_build(ak4114_t *ak4114,
- snd_pcm_substream_t *playback_substream,
- snd_pcm_substream_t *capture_substream);
-int snd_ak4114_external_rate(ak4114_t *ak4114);
-int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags);
+ void *private_data, struct ak4114 **r_ak4114);
+void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
+void snd_ak4114_reinit(struct ak4114 *ak4114);
+int snd_ak4114_build(struct ak4114 *ak4114,
+ struct snd_pcm_substream *playback_substream,
+ struct snd_pcm_substream *capture_substream);
+int snd_ak4114_external_rate(struct ak4114 *ak4114);
+int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags);
#endif /* __SOUND_AK4114_H */
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h
index 9e1dab17c33e..2b96c32f06fd 100644
--- a/include/sound/ak4117.h
+++ b/include/sound/ak4117.h
@@ -155,18 +155,16 @@
typedef void (ak4117_write_t)(void *private_data, unsigned char addr, unsigned char data);
typedef unsigned char (ak4117_read_t)(void *private_data, unsigned char addr);
-typedef struct ak4117 ak4117_t;
-
struct ak4117 {
- snd_card_t * card;
+ struct snd_card *card;
ak4117_write_t * write;
ak4117_read_t * read;
void * private_data;
unsigned int init: 1;
spinlock_t lock;
unsigned char regmap[5];
- snd_kcontrol_t *kctls[AK4117_CONTROLS];
- snd_pcm_substream_t *substream;
+ struct snd_kcontrol *kctls[AK4117_CONTROLS];
+ struct snd_pcm_substream *substream;
unsigned long parity_errors;
unsigned long v_bit_errors;
unsigned long qcrc_errors;
@@ -176,16 +174,16 @@ struct ak4117 {
unsigned char rcs2;
struct timer_list timer; /* statistic timer */
void *change_callback_private;
- void (*change_callback)(ak4117_t *ak4117, unsigned char c0, unsigned char c1);
+ void (*change_callback)(struct ak4117 *ak4117, unsigned char c0, unsigned char c1);
};
-int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write,
- unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117);
-void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
-void snd_ak4117_reinit(ak4117_t *ak4117);
-int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream);
-int snd_ak4117_external_rate(ak4117_t *ak4117);
-int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags);
+int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
+ unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
+void snd_ak4117_reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
+void snd_ak4117_reinit(struct ak4117 *ak4117);
+int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *capture_substream);
+int snd_ak4117_external_rate(struct ak4117 *ak4117);
+int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags);
#endif /* __SOUND_AK4117_H */
diff --git a/include/sound/ak4531_codec.h b/include/sound/ak4531_codec.h
index 8b18992376d5..edf04070ce7c 100644
--- a/include/sound/ak4531_codec.h
+++ b/include/sound/ak4531_codec.h
@@ -64,17 +64,22 @@
#define AK4531_AD_IN 0x18 /* AD input select */
#define AK4531_MIC_GAIN 0x19 /* MIC amplified gain */
-typedef struct _snd_ak4531 ak4531_t;
-
-struct _snd_ak4531 {
- void (*write) (ak4531_t *ak4531, unsigned short reg, unsigned short val);
+struct snd_ak4531 {
+ void (*write) (struct snd_ak4531 *ak4531, unsigned short reg,
+ unsigned short val);
void *private_data;
- void (*private_free) (ak4531_t *ak4531);
+ void (*private_free) (struct snd_ak4531 *ak4531);
/* --- */
unsigned char regs[0x20];
struct semaphore reg_mutex;
};
-int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531);
+int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531,
+ struct snd_ak4531 **rak4531);
+
+#ifdef CONFIG_PM
+void snd_ak4531_suspend(struct snd_ak4531 *ak4531);
+void snd_ak4531_resume(struct snd_ak4531 *ak4531);
+#endif
#endif /* __SOUND_AK4531_CODEC_H */
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index e94ac0282318..3bf5911fe827 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -27,20 +27,20 @@
#define AK4XXX_MAX_CHIPS 4
#endif
-typedef struct snd_akm4xxx akm4xxx_t;
+struct snd_akm4xxx;
struct snd_ak4xxx_ops {
- void (*lock)(akm4xxx_t *ak, int chip);
- void (*unlock)(akm4xxx_t *ak, int chip);
- void (*write)(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char val);
- // unsigned char (*read)(akm4xxx_t *ak, int chip, unsigned char reg);
- void (*set_rate_val)(akm4xxx_t *ak, unsigned int rate);
+ void (*lock)(struct snd_akm4xxx *ak, int chip);
+ void (*unlock)(struct snd_akm4xxx *ak, int chip);
+ void (*write)(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val);
+ // unsigned char (*read)(struct snd_akm4xxx *ak, int chip, unsigned char reg);
+ void (*set_rate_val)(struct snd_akm4xxx *ak, unsigned int rate);
};
#define AK4XXX_IMAGE_SIZE (AK4XXX_MAX_CHIPS * 16) /* 64 bytes */
struct snd_akm4xxx {
- snd_card_t *card;
+ struct snd_card *card;
unsigned int num_adcs; /* AK4524 or AK4528 ADCs */
unsigned int num_dacs; /* AK4524 or AK4528 DACs */
unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */
@@ -56,10 +56,10 @@ struct snd_akm4xxx {
struct snd_ak4xxx_ops ops;
};
-void snd_akm4xxx_write(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char val);
-void snd_akm4xxx_reset(akm4xxx_t *ak, int state);
-void snd_akm4xxx_init(akm4xxx_t *ak);
-int snd_akm4xxx_build_controls(akm4xxx_t *ak);
+void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val);
+void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state);
+void snd_akm4xxx_init(struct snd_akm4xxx *ak);
+int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak);
#define snd_akm4xxx_get(ak,chip,reg) (ak)->images[(chip) * 16 + (reg)]
#define snd_akm4xxx_set(ak,chip,reg,val) ((ak)->images[(chip) * 16 + (reg)] = (val))
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 728efd504262..6691e4aa4ea7 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -22,11 +22,10 @@
#ifndef __SOUND_ASEQUENCER_H
#define __SOUND_ASEQUENCER_H
-#ifndef __KERNEL__
+#ifdef __KERNEL__
#include <linux/ioctl.h>
-#endif
-
#include <sound/asound.h>
+#endif
/** version of the sequencer */
#define SNDRV_SEQ_VERSION SNDRV_PROTOCOL_VERSION (1, 0, 1)
@@ -36,13 +35,13 @@
*/
/** system messages
- * event data type = #sndrv_seq_result_t
+ * event data type = #snd_seq_result
*/
#define SNDRV_SEQ_EVENT_SYSTEM 0
#define SNDRV_SEQ_EVENT_RESULT 1
/** note messages (channel specific)
- * event data type = #sndrv_seq_ev_note
+ * event data type = #snd_seq_ev_note
*/
#define SNDRV_SEQ_EVENT_NOTE 5
#define SNDRV_SEQ_EVENT_NOTEON 6
@@ -50,7 +49,7 @@
#define SNDRV_SEQ_EVENT_KEYPRESS 8
/** control messages (channel specific)
- * event data type = #sndrv_seq_ev_ctrl
+ * event data type = #snd_seq_ev_ctrl
*/
#define SNDRV_SEQ_EVENT_CONTROLLER 10
#define SNDRV_SEQ_EVENT_PGMCHANGE 11
@@ -61,7 +60,7 @@
#define SNDRV_SEQ_EVENT_REGPARAM 16 /**< 14 bit RPN address + 14 bit unsigned value */
/** synchronisation messages
- * event data type = #sndrv_seq_ev_ctrl
+ * event data type = #snd_seq_ev_ctrl
*/
#define SNDRV_SEQ_EVENT_SONGPOS 20 /* Song Position Pointer with LSB and MSB values */
#define SNDRV_SEQ_EVENT_SONGSEL 21 /* Song Select with song ID number */
@@ -70,7 +69,7 @@
#define SNDRV_SEQ_EVENT_KEYSIGN 24 /* SMF Key Signature event */
/** timer messages
- * event data type = sndrv_seq_ev_queue_control_t
+ * event data type = snd_seq_ev_queue_control
*/
#define SNDRV_SEQ_EVENT_START 30 /* midi Real Time Start message */
#define SNDRV_SEQ_EVENT_CONTINUE 31 /* midi Real Time Continue message */
@@ -96,7 +95,7 @@
#define SNDRV_SEQ_EVENT_OSS 51 /* OSS raw event */
/** system status messages (broadcast for subscribers)
- * event data type = sndrv_seq_addr_t
+ * event data type = snd_seq_addr
*/
#define SNDRV_SEQ_EVENT_CLIENT_START 60 /* new client has connected */
#define SNDRV_SEQ_EVENT_CLIENT_EXIT 61 /* client has left the system */
@@ -106,13 +105,13 @@
#define SNDRV_SEQ_EVENT_PORT_CHANGE 65 /* port status/info has changed */
/** port connection changes
- * event data type = sndrv_seq_connect_t
+ * event data type = snd_seq_connect
*/
#define SNDRV_SEQ_EVENT_PORT_SUBSCRIBED 66 /* ports connected */
#define SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED 67 /* ports disconnected */
/** synthesizer events
- * event data type = sndrv_seq_eve_sample_control_t
+ * event data type = snd_seq_eve_sample_control
*/
#define SNDRV_SEQ_EVENT_SAMPLE 70 /* sample select */
#define SNDRV_SEQ_EVENT_SAMPLE_CLUSTER 71 /* sample cluster select */
@@ -163,7 +162,7 @@
/* 119-129: reserved */
/* 130-139: variable length events
- * event data type = sndrv_seq_ev_ext
+ * event data type = snd_seq_ev_ext
* (SNDRV_SEQ_EVENT_LENGTH_VARIABLE must be set)
*/
#define SNDRV_SEQ_EVENT_SYSEX 130 /* system exclusive data (variable length) */
@@ -187,18 +186,18 @@
#define SNDRV_SEQ_EVENT_NONE 255
-typedef unsigned char sndrv_seq_event_type_t;
+typedef unsigned char snd_seq_event_type_t;
/** event address */
-struct sndrv_seq_addr {
+struct snd_seq_addr {
unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */
unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */
};
/** port connection */
-struct sndrv_seq_connect {
- struct sndrv_seq_addr sender;
- struct sndrv_seq_addr dest;
+struct snd_seq_connect {
+ struct snd_seq_addr sender;
+ struct snd_seq_addr dest;
};
@@ -227,7 +226,7 @@ struct sndrv_seq_connect {
/* note event */
-struct sndrv_seq_ev_note {
+struct snd_seq_ev_note {
unsigned char channel;
unsigned char note;
unsigned char velocity;
@@ -236,7 +235,7 @@ struct sndrv_seq_ev_note {
};
/* controller event */
-struct sndrv_seq_ev_ctrl {
+struct snd_seq_ev_ctrl {
unsigned char channel;
unsigned char unused1, unused2, unused3; /* pad */
unsigned int param;
@@ -244,59 +243,59 @@ struct sndrv_seq_ev_ctrl {
};
/* generic set of bytes (12x8 bit) */
-struct sndrv_seq_ev_raw8 {
+struct snd_seq_ev_raw8 {
unsigned char d[12]; /* 8 bit value */
};
/* generic set of integers (3x32 bit) */
-struct sndrv_seq_ev_raw32 {
+struct snd_seq_ev_raw32 {
unsigned int d[3]; /* 32 bit value */
};
/* external stored data */
-struct sndrv_seq_ev_ext {
+struct snd_seq_ev_ext {
unsigned int len; /* length of data */
void *ptr; /* pointer to data (note: maybe 64-bit) */
} __attribute__((packed));
/* Instrument cluster type */
-typedef unsigned int sndrv_seq_instr_cluster_t;
+typedef unsigned int snd_seq_instr_cluster_t;
/* Instrument type */
-struct sndrv_seq_instr {
- sndrv_seq_instr_cluster_t cluster;
+struct snd_seq_instr {
+ snd_seq_instr_cluster_t cluster;
unsigned int std; /* the upper byte means a private instrument (owner - client #) */
unsigned short bank;
unsigned short prg;
};
/* sample number */
-struct sndrv_seq_ev_sample {
+struct snd_seq_ev_sample {
unsigned int std;
unsigned short bank;
unsigned short prg;
};
/* sample cluster */
-struct sndrv_seq_ev_cluster {
- sndrv_seq_instr_cluster_t cluster;
+struct snd_seq_ev_cluster {
+ snd_seq_instr_cluster_t cluster;
};
/* sample position */
-typedef unsigned int sndrv_seq_position_t; /* playback position (in samples) * 16 */
+typedef unsigned int snd_seq_position_t; /* playback position (in samples) * 16 */
/* sample stop mode */
-enum sndrv_seq_stop_mode {
+enum {
SAMPLE_STOP_IMMEDIATELY = 0, /* terminate playing immediately */
SAMPLE_STOP_VENVELOPE = 1, /* finish volume envelope */
SAMPLE_STOP_LOOP = 2 /* terminate loop and finish wave */
};
/* sample frequency */
-typedef int sndrv_seq_frequency_t; /* playback frequency in HZ * 16 */
+typedef int snd_seq_frequency_t; /* playback frequency in HZ * 16 */
/* sample volume control; if any value is set to -1 == do not change */
-struct sndrv_seq_ev_volume {
+struct snd_seq_ev_volume {
signed short volume; /* range: 0-16383 */
signed short lr; /* left-right balance; range: 0-16383 */
signed short fr; /* front-rear balance; range: 0-16383 */
@@ -304,22 +303,22 @@ struct sndrv_seq_ev_volume {
};
/* simple loop redefinition */
-struct sndrv_seq_ev_loop {
+struct snd_seq_ev_loop {
unsigned int start; /* loop start (in samples) * 16 */
unsigned int end; /* loop end (in samples) * 16 */
};
-struct sndrv_seq_ev_sample_control {
+struct snd_seq_ev_sample_control {
unsigned char channel;
unsigned char unused1, unused2, unused3; /* pad */
union {
- struct sndrv_seq_ev_sample sample;
- struct sndrv_seq_ev_cluster cluster;
- sndrv_seq_position_t position;
- enum sndrv_seq_stop_mode stop_mode;
- sndrv_seq_frequency_t frequency;
- struct sndrv_seq_ev_volume volume;
- struct sndrv_seq_ev_loop loop;
+ struct snd_seq_ev_sample sample;
+ struct snd_seq_ev_cluster cluster;
+ snd_seq_position_t position;
+ int stop_mode;
+ snd_seq_frequency_t frequency;
+ struct snd_seq_ev_volume volume;
+ struct snd_seq_ev_loop loop;
unsigned char raw8[8];
} param;
};
@@ -327,82 +326,82 @@ struct sndrv_seq_ev_sample_control {
/* INSTR_BEGIN event */
-struct sndrv_seq_ev_instr_begin {
+struct snd_seq_ev_instr_begin {
int timeout; /* zero = forever, otherwise timeout in ms */
};
-struct sndrv_seq_result {
+struct snd_seq_result {
int event; /* processed event type */
int result;
};
-struct sndrv_seq_real_time {
+struct snd_seq_real_time {
unsigned int tv_sec; /* seconds */
unsigned int tv_nsec; /* nanoseconds */
};
-typedef unsigned int sndrv_seq_tick_time_t; /* midi ticks */
+typedef unsigned int snd_seq_tick_time_t; /* midi ticks */
-union sndrv_seq_timestamp {
- sndrv_seq_tick_time_t tick;
- struct sndrv_seq_real_time time;
+union snd_seq_timestamp {
+ snd_seq_tick_time_t tick;
+ struct snd_seq_real_time time;
};
-struct sndrv_seq_queue_skew {
+struct snd_seq_queue_skew {
unsigned int value;
unsigned int base;
};
/* queue timer control */
-struct sndrv_seq_ev_queue_control {
+struct snd_seq_ev_queue_control {
unsigned char queue; /* affected queue */
unsigned char pad[3]; /* reserved */
union {
signed int value; /* affected value (e.g. tempo) */
- union sndrv_seq_timestamp time; /* time */
+ union snd_seq_timestamp time; /* time */
unsigned int position; /* sync position */
- struct sndrv_seq_queue_skew skew;
+ struct snd_seq_queue_skew skew;
unsigned int d32[2];
unsigned char d8[8];
} param;
};
/* quoted event - inside the kernel only */
-struct sndrv_seq_ev_quote {
- struct sndrv_seq_addr origin; /* original sender */
+struct snd_seq_ev_quote {
+ struct snd_seq_addr origin; /* original sender */
unsigned short value; /* optional data */
- struct sndrv_seq_event *event; /* quoted event */
+ struct snd_seq_event *event; /* quoted event */
} __attribute__((packed));
/* sequencer event */
-struct sndrv_seq_event {
- sndrv_seq_event_type_t type; /* event type */
+struct snd_seq_event {
+ snd_seq_event_type_t type; /* event type */
unsigned char flags; /* event flags */
char tag;
unsigned char queue; /* schedule queue */
- union sndrv_seq_timestamp time; /* schedule time */
+ union snd_seq_timestamp time; /* schedule time */
- struct sndrv_seq_addr source; /* source address */
- struct sndrv_seq_addr dest; /* destination address */
+ struct snd_seq_addr source; /* source address */
+ struct snd_seq_addr dest; /* destination address */
union { /* event data... */
- struct sndrv_seq_ev_note note;
- struct sndrv_seq_ev_ctrl control;
- struct sndrv_seq_ev_raw8 raw8;
- struct sndrv_seq_ev_raw32 raw32;
- struct sndrv_seq_ev_ext ext;
- struct sndrv_seq_ev_queue_control queue;
- union sndrv_seq_timestamp time;
- struct sndrv_seq_addr addr;
- struct sndrv_seq_connect connect;
- struct sndrv_seq_result result;
- struct sndrv_seq_ev_instr_begin instr_begin;
- struct sndrv_seq_ev_sample_control sample;
- struct sndrv_seq_ev_quote quote;
+ struct snd_seq_ev_note note;
+ struct snd_seq_ev_ctrl control;
+ struct snd_seq_ev_raw8 raw8;
+ struct snd_seq_ev_raw32 raw32;
+ struct snd_seq_ev_ext ext;
+ struct snd_seq_ev_queue_control queue;
+ union snd_seq_timestamp time;
+ struct snd_seq_addr addr;
+ struct snd_seq_connect connect;
+ struct snd_seq_result result;
+ struct snd_seq_ev_instr_begin instr_begin;
+ struct snd_seq_ev_sample_control sample;
+ struct snd_seq_ev_quote quote;
} data;
};
@@ -410,72 +409,77 @@ struct sndrv_seq_event {
/*
* bounce event - stored as variable size data
*/
-struct sndrv_seq_event_bounce {
+struct snd_seq_event_bounce {
int err;
- struct sndrv_seq_event event;
+ struct snd_seq_event event;
/* external data follows here. */
};
-#define sndrv_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(sndrv_seq_event_bounce_t)))
+#ifdef __KERNEL__
+
+/* helper macro */
+#define snd_seq_event_bounce_ext_data(ev) ((void*)((char *)(ev)->data.ext.ptr + sizeof(struct snd_seq_event_bounce)))
/*
* type check macros
*/
/* result events: 0-4 */
-#define sndrv_seq_ev_is_result_type(ev) ((ev)->type < 5)
+#define snd_seq_ev_is_result_type(ev) ((ev)->type < 5)
/* channel specific events: 5-19 */
-#define sndrv_seq_ev_is_channel_type(ev) ((ev)->type >= 5 && (ev)->type < 20)
+#define snd_seq_ev_is_channel_type(ev) ((ev)->type >= 5 && (ev)->type < 20)
/* note events: 5-9 */
-#define sndrv_seq_ev_is_note_type(ev) ((ev)->type >= 5 && (ev)->type < 10)
+#define snd_seq_ev_is_note_type(ev) ((ev)->type >= 5 && (ev)->type < 10)
/* control events: 10-19 */
-#define sndrv_seq_ev_is_control_type(ev) ((ev)->type >= 10 && (ev)->type < 20)
+#define snd_seq_ev_is_control_type(ev) ((ev)->type >= 10 && (ev)->type < 20)
/* queue control events: 30-39 */
-#define sndrv_seq_ev_is_queue_type(ev) ((ev)->type >= 30 && (ev)->type < 40)
+#define snd_seq_ev_is_queue_type(ev) ((ev)->type >= 30 && (ev)->type < 40)
/* system status messages */
-#define sndrv_seq_ev_is_message_type(ev) ((ev)->type >= 60 && (ev)->type < 69)
+#define snd_seq_ev_is_message_type(ev) ((ev)->type >= 60 && (ev)->type < 69)
/* sample messages */
-#define sndrv_seq_ev_is_sample_type(ev) ((ev)->type >= 70 && (ev)->type < 79)
+#define snd_seq_ev_is_sample_type(ev) ((ev)->type >= 70 && (ev)->type < 79)
/* user-defined messages */
-#define sndrv_seq_ev_is_user_type(ev) ((ev)->type >= 90 && (ev)->type < 99)
+#define snd_seq_ev_is_user_type(ev) ((ev)->type >= 90 && (ev)->type < 99)
/* fixed length events: 0-99 */
-#define sndrv_seq_ev_is_fixed_type(ev) ((ev)->type < 100)
+#define snd_seq_ev_is_fixed_type(ev) ((ev)->type < 100)
/* instrument layer events: 100-129 */
-#define sndrv_seq_ev_is_instr_type(ev) ((ev)->type >= 100 && (ev)->type < 130)
+#define snd_seq_ev_is_instr_type(ev) ((ev)->type >= 100 && (ev)->type < 130)
/* variable length events: 130-139 */
-#define sndrv_seq_ev_is_variable_type(ev) ((ev)->type >= 130 && (ev)->type < 140)
+#define snd_seq_ev_is_variable_type(ev) ((ev)->type >= 130 && (ev)->type < 140)
/* reserved for kernel */
-#define sndrv_seq_ev_is_reserved(ev) ((ev)->type >= 150)
+#define snd_seq_ev_is_reserved(ev) ((ev)->type >= 150)
/* direct dispatched events */
-#define sndrv_seq_ev_is_direct(ev) ((ev)->queue == SNDRV_SEQ_QUEUE_DIRECT)
+#define snd_seq_ev_is_direct(ev) ((ev)->queue == SNDRV_SEQ_QUEUE_DIRECT)
/*
* macros to check event flags
*/
/* prior events */
-#define sndrv_seq_ev_is_prior(ev) (((ev)->flags & SNDRV_SEQ_PRIORITY_MASK) == SNDRV_SEQ_PRIORITY_HIGH)
+#define snd_seq_ev_is_prior(ev) (((ev)->flags & SNDRV_SEQ_PRIORITY_MASK) == SNDRV_SEQ_PRIORITY_HIGH)
/* event length type */
-#define sndrv_seq_ev_length_type(ev) ((ev)->flags & SNDRV_SEQ_EVENT_LENGTH_MASK)
-#define sndrv_seq_ev_is_fixed(ev) (sndrv_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_FIXED)
-#define sndrv_seq_ev_is_variable(ev) (sndrv_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
-#define sndrv_seq_ev_is_varusr(ev) (sndrv_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_VARUSR)
+#define snd_seq_ev_length_type(ev) ((ev)->flags & SNDRV_SEQ_EVENT_LENGTH_MASK)
+#define snd_seq_ev_is_fixed(ev) (snd_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_FIXED)
+#define snd_seq_ev_is_variable(ev) (snd_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
+#define snd_seq_ev_is_varusr(ev) (snd_seq_ev_length_type(ev) == SNDRV_SEQ_EVENT_LENGTH_VARUSR)
/* time-stamp type */
-#define sndrv_seq_ev_timestamp_type(ev) ((ev)->flags & SNDRV_SEQ_TIME_STAMP_MASK)
-#define sndrv_seq_ev_is_tick(ev) (sndrv_seq_ev_timestamp_type(ev) == SNDRV_SEQ_TIME_STAMP_TICK)
-#define sndrv_seq_ev_is_real(ev) (sndrv_seq_ev_timestamp_type(ev) == SNDRV_SEQ_TIME_STAMP_REAL)
+#define snd_seq_ev_timestamp_type(ev) ((ev)->flags & SNDRV_SEQ_TIME_STAMP_MASK)
+#define snd_seq_ev_is_tick(ev) (snd_seq_ev_timestamp_type(ev) == SNDRV_SEQ_TIME_STAMP_TICK)
+#define snd_seq_ev_is_real(ev) (snd_seq_ev_timestamp_type(ev) == SNDRV_SEQ_TIME_STAMP_REAL)
/* time-mode type */
-#define sndrv_seq_ev_timemode_type(ev) ((ev)->flags & SNDRV_SEQ_TIME_MODE_MASK)
-#define sndrv_seq_ev_is_abstime(ev) (sndrv_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_ABS)
-#define sndrv_seq_ev_is_reltime(ev) (sndrv_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_REL)
+#define snd_seq_ev_timemode_type(ev) ((ev)->flags & SNDRV_SEQ_TIME_MODE_MASK)
+#define snd_seq_ev_is_abstime(ev) (snd_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_ABS)
+#define snd_seq_ev_is_reltime(ev) (snd_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_REL)
/* queue sync port */
-#define sndrv_seq_queue_sync_port(q) ((q) + 16)
+#define snd_seq_queue_sync_port(q) ((q) + 16)
+
+#endif /* __KERNEL__ */
/* system information */
-struct sndrv_seq_system_info {
+struct snd_seq_system_info {
int queues; /* maximum queues count */
int clients; /* maximum clients count */
int ports; /* maximum ports per client */
@@ -487,7 +491,7 @@ struct sndrv_seq_system_info {
/* system running information */
-struct sndrv_seq_running_info {
+struct snd_seq_running_info {
unsigned char client; /* client id */
unsigned char big_endian; /* 1 = big-endian */
unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */
@@ -498,16 +502,16 @@ struct sndrv_seq_running_info {
/* known client numbers */
#define SNDRV_SEQ_CLIENT_SYSTEM 0
-#define SNDRV_SEQ_CLIENT_DUMMY 62 /* dummy ports */
-#define SNDRV_SEQ_CLIENT_OSS 63 /* oss sequencer emulator */
+ /* internal client numbers */
+#define SNDRV_SEQ_CLIENT_DUMMY 14 /* midi through */
+#define SNDRV_SEQ_CLIENT_OSS 15 /* oss sequencer emulator */
/* client types */
-enum sndrv_seq_client_type {
- NO_CLIENT = 0,
- USER_CLIENT = 1,
- KERNEL_CLIENT = 2
-};
+typedef int __bitwise snd_seq_client_type_t;
+#define NO_CLIENT ((__force snd_seq_client_type_t) 0)
+#define USER_CLIENT ((__force snd_seq_client_type_t) 1)
+#define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2)
/* event filter flags */
#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */
@@ -515,9 +519,9 @@ enum sndrv_seq_client_type {
#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */
#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */
-struct sndrv_seq_client_info {
+struct snd_seq_client_info {
int client; /* client number to inquire */
- enum sndrv_seq_client_type type; /* client type */
+ snd_seq_client_type_t type; /* client type */
char name[64]; /* client name */
unsigned int filter; /* filter flags */
unsigned char multicast_filter[8]; /* multicast filter bitmap */
@@ -529,7 +533,7 @@ struct sndrv_seq_client_info {
/* client pool size */
-struct sndrv_seq_client_pool {
+struct snd_seq_client_pool {
int client; /* client number to inquire */
int output_pool; /* outgoing (write) pool size */
int input_pool; /* incoming (read) pool size */
@@ -553,13 +557,13 @@ struct sndrv_seq_client_pool {
#define SNDRV_SEQ_REMOVE_IGNORE_OFF (1<<8) /* Do not flush off events */
#define SNDRV_SEQ_REMOVE_TAG_MATCH (1<<9) /* Restrict to events with given tag */
-struct sndrv_seq_remove_events {
+struct snd_seq_remove_events {
unsigned int remove_mode; /* Flags that determine what gets removed */
- union sndrv_seq_timestamp time;
+ union snd_seq_timestamp time;
unsigned char queue; /* Queue for REMOVE_DEST */
- struct sndrv_seq_addr dest; /* Address for REMOVE_DEST */
+ struct snd_seq_addr dest; /* Address for REMOVE_DEST */
unsigned char channel; /* Channel for REMOVE_DEST */
int type; /* For REMOVE_EVENT_TYPE */
@@ -608,8 +612,8 @@ struct sndrv_seq_remove_events {
#define SNDRV_SEQ_PORT_FLG_TIMESTAMP (1<<1)
#define SNDRV_SEQ_PORT_FLG_TIME_REAL (1<<2)
-struct sndrv_seq_port_info {
- struct sndrv_seq_addr addr; /* client/port numbers */
+struct snd_seq_port_info {
+ struct snd_seq_addr addr; /* client/port numbers */
char name[64]; /* port name */
unsigned int capability; /* port capability bits */
@@ -632,7 +636,7 @@ struct sndrv_seq_port_info {
#define SNDRV_SEQ_QUEUE_FLG_SYNC (1<<0) /* sync enabled */
/* queue information */
-struct sndrv_seq_queue_info {
+struct snd_seq_queue_info {
int queue; /* queue id */
/*
@@ -648,11 +652,11 @@ struct sndrv_seq_queue_info {
};
/* queue info/status */
-struct sndrv_seq_queue_status {
+struct snd_seq_queue_status {
int queue; /* queue id */
int events; /* read-only - queue size */
- sndrv_seq_tick_time_t tick; /* current tick */
- struct sndrv_seq_real_time time; /* current time */
+ snd_seq_tick_time_t tick; /* current tick */
+ struct snd_seq_real_time time; /* current time */
int running; /* running state of queue */
int flags; /* various flags */
char reserved[64]; /* for the future */
@@ -660,7 +664,7 @@ struct sndrv_seq_queue_status {
/* queue tempo */
-struct sndrv_seq_queue_tempo {
+struct snd_seq_queue_tempo {
int queue; /* sequencer queue */
unsigned int tempo; /* current tempo, us/tick */
int ppq; /* time resolution, ticks/quarter */
@@ -676,12 +680,12 @@ struct sndrv_seq_queue_tempo {
#define SNDRV_SEQ_TIMER_MIDI_TICK 2 /* Midi Timer Tick (TICK event) */
/* queue timer info */
-struct sndrv_seq_queue_timer {
+struct snd_seq_queue_timer {
int queue; /* sequencer queue */
int type; /* source timer type */
union {
struct {
- struct sndrv_timer_id id; /* ALSA's timer ID */
+ struct snd_timer_id id; /* ALSA's timer ID */
unsigned int resolution; /* resolution in Hz */
} alsa;
} u;
@@ -689,7 +693,7 @@ struct sndrv_seq_queue_timer {
};
-struct sndrv_seq_queue_client {
+struct snd_seq_queue_client {
int queue; /* sequencer queue */
int client; /* sequencer client */
int used; /* queue is used with this client
@@ -703,9 +707,9 @@ struct sndrv_seq_queue_client {
#define SNDRV_SEQ_PORT_SUBS_TIMESTAMP (1<<1)
#define SNDRV_SEQ_PORT_SUBS_TIME_REAL (1<<2)
-struct sndrv_seq_port_subscribe {
- struct sndrv_seq_addr sender; /* sender address */
- struct sndrv_seq_addr dest; /* destination address */
+struct snd_seq_port_subscribe {
+ struct snd_seq_addr sender; /* sender address */
+ struct snd_seq_addr dest; /* destination address */
unsigned int voices; /* number of voices to be allocated (0 = don't care) */
unsigned int flags; /* modes */
unsigned char queue; /* input time-stamp queue (optional) */
@@ -717,12 +721,12 @@ struct sndrv_seq_port_subscribe {
#define SNDRV_SEQ_QUERY_SUBS_READ 0
#define SNDRV_SEQ_QUERY_SUBS_WRITE 1
-struct sndrv_seq_query_subs {
- struct sndrv_seq_addr root; /* client/port id to be searched */
+struct snd_seq_query_subs {
+ struct snd_seq_addr root; /* client/port id to be searched */
int type; /* READ or WRITE */
int index; /* 0..N-1 */
int num_subs; /* R/O: number of subscriptions on this port */
- struct sndrv_seq_addr addr; /* R/O: result */
+ struct snd_seq_addr addr; /* R/O: result */
unsigned char queue; /* R/O: result */
unsigned int flags; /* R/O: result */
char reserved[64]; /* for future use */
@@ -779,72 +783,72 @@ struct sndrv_seq_query_subs {
#define SNDRV_SEQ_INSTR_FREE_CMD_SINGLE 3
/* size of ROM/RAM */
-typedef unsigned int sndrv_seq_instr_size_t;
+typedef unsigned int snd_seq_instr_size_t;
/* INSTR_INFO */
-struct sndrv_seq_instr_info {
+struct snd_seq_instr_info {
int result; /* operation result */
unsigned int formats[8]; /* bitmap of supported formats */
int ram_count; /* count of RAM banks */
- sndrv_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */
+ snd_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */
int rom_count; /* count of ROM banks */
- sndrv_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */
+ snd_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */
char reserved[128];
};
/* INSTR_STATUS */
-struct sndrv_seq_instr_status {
+struct snd_seq_instr_status {
int result; /* operation result */
- sndrv_seq_instr_size_t free_ram[16]; /* free RAM in banks */
+ snd_seq_instr_size_t free_ram[16]; /* free RAM in banks */
int instrument_count; /* count of downloaded instruments */
char reserved[128];
};
/* INSTR_FORMAT_INFO */
-struct sndrv_seq_instr_format_info {
+struct snd_seq_instr_format_info {
char format[16]; /* format identifier - SNDRV_SEQ_INSTR_ID_* */
unsigned int len; /* max data length (without this structure) */
};
-struct sndrv_seq_instr_format_info_result {
+struct snd_seq_instr_format_info_result {
int result; /* operation result */
char format[16]; /* format identifier */
unsigned int len; /* filled data length (without this structure) */
};
/* instrument data */
-struct sndrv_seq_instr_data {
+struct snd_seq_instr_data {
char name[32]; /* instrument name */
char reserved[16]; /* for the future use */
int type; /* instrument type */
union {
char format[16]; /* format identifier */
- struct sndrv_seq_instr alias;
+ struct snd_seq_instr alias;
} data;
};
/* INSTR_PUT/GET, data are stored in one block (extended), header + data */
-struct sndrv_seq_instr_header {
+struct snd_seq_instr_header {
union {
- struct sndrv_seq_instr instr;
- sndrv_seq_instr_cluster_t cluster;
+ struct snd_seq_instr instr;
+ snd_seq_instr_cluster_t cluster;
} id; /* instrument identifier */
unsigned int cmd; /* get/put/free command */
unsigned int flags; /* query flags (only for get) */
unsigned int len; /* real instrument data length (without header) */
int result; /* operation result */
char reserved[16]; /* for the future */
- struct sndrv_seq_instr_data data; /* instrument data (for put/get result) */
+ struct snd_seq_instr_data data; /* instrument data (for put/get result) */
};
/* INSTR_CLUSTER_SET */
-struct sndrv_seq_instr_cluster_set {
- sndrv_seq_instr_cluster_t cluster; /* cluster identifier */
+struct snd_seq_instr_cluster_set {
+ snd_seq_instr_cluster_t cluster; /* cluster identifier */
char name[32]; /* cluster name */
int priority; /* cluster priority */
char reserved[64]; /* for the future use */
@@ -852,8 +856,8 @@ struct sndrv_seq_instr_cluster_set {
/* INSTR_CLUSTER_GET */
-struct sndrv_seq_instr_cluster_get {
- sndrv_seq_instr_cluster_t cluster; /* cluster identifier */
+struct snd_seq_instr_cluster_get {
+ snd_seq_instr_cluster_t cluster; /* cluster identifier */
char name[32]; /* cluster name */
int priority; /* cluster priority */
char reserved[64]; /* for the future use */
@@ -865,44 +869,44 @@ struct sndrv_seq_instr_cluster_get {
#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int)
#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)
-#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct sndrv_seq_system_info)
-#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct sndrv_seq_running_info)
-
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct sndrv_seq_client_info)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct sndrv_seq_client_info)
-
-#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct sndrv_seq_port_info)
-#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct sndrv_seq_port_info)
-#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct sndrv_seq_port_info)
-#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct sndrv_seq_port_info)
-
-#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct sndrv_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct sndrv_seq_port_subscribe)
-
-#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct sndrv_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct sndrv_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct sndrv_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct sndrv_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct sndrv_seq_queue_info)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct sndrv_seq_queue_status)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct sndrv_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct sndrv_seq_queue_tempo)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct sndrv_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct sndrv_seq_queue_owner)
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct sndrv_seq_queue_timer)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct sndrv_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)
+#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info)
+
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
+
+#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct snd_seq_port_info)
+#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct snd_seq_port_info)
+
+#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct snd_seq_port_subscribe)
+
+#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct snd_seq_queue_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct snd_seq_queue_status)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct snd_seq_queue_tempo)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct snd_seq_queue_owner)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct snd_seq_queue_timer)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct snd_seq_queue_timer)
/* XXX
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct sndrv_seq_queue_sync)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct sndrv_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct snd_seq_queue_sync)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct snd_seq_queue_sync)
*/
-#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct sndrv_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct sndrv_seq_queue_client)
-#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct sndrv_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct sndrv_seq_client_pool)
-#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct sndrv_seq_remove_events)
-#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct sndrv_seq_query_subs)
-#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct sndrv_seq_port_subscribe)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct sndrv_seq_client_info)
-#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct sndrv_seq_port_info)
+#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct snd_seq_queue_client)
+#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct snd_seq_client_pool)
+#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct snd_seq_remove_events)
+#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct snd_seq_query_subs)
+#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct snd_seq_port_subscribe)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct snd_seq_client_info)
+#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct snd_seq_port_info)
#endif /* __SOUND_ASEQUENCER_H */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 8e552d627fa5..9cc021c7ee11 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -23,12 +23,8 @@
#ifndef __SOUND_ASOUND_H
#define __SOUND_ASOUND_H
-#if defined(LINUX) || defined(__LINUX__) || defined(__linux__)
-
-#include <linux/ioctl.h>
-
#ifdef __KERNEL__
-
+#include <linux/ioctl.h>
#include <linux/types.h>
#include <linux/time.h>
#include <asm/byteorder.h>
@@ -43,25 +39,7 @@
#endif
#endif
-#else /* !__KERNEL__ */
-
-#include <endian.h>
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define SNDRV_LITTLE_ENDIAN
-#elif __BYTE_ORDER == __BIG_ENDIAN
-#define SNDRV_BIG_ENDIAN
-#else
-#error "Unsupported endian..."
-#endif
-
-#endif /* __KERNEL **/
-
-#endif /* LINUX */
-
-#ifndef __KERNEL__
-#include <sys/time.h>
-#include <sys/types.h>
-#endif
+#endif /* __KERNEL__ **/
/*
* protocol version
@@ -82,7 +60,7 @@
* *
****************************************************************************/
-struct sndrv_aes_iec958 {
+struct snd_aes_iec958 {
unsigned char status[24]; /* AES/IEC958 channel status bits */
unsigned char subcode[147]; /* AES/IEC958 subcode bits */
unsigned char pad; /* nothing */
@@ -97,7 +75,7 @@ struct sndrv_aes_iec958 {
#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
-enum sndrv_hwdep_iface {
+enum {
SNDRV_HWDEP_IFACE_OPL2 = 0,
SNDRV_HWDEP_IFACE_OPL3,
SNDRV_HWDEP_IFACE_OPL4,
@@ -119,17 +97,17 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
};
-struct sndrv_hwdep_info {
+struct snd_hwdep_info {
unsigned int device; /* WR: device number */
int card; /* R: card number */
unsigned char id[64]; /* ID (user selectable) */
unsigned char name[80]; /* hwdep name */
- enum sndrv_hwdep_iface iface; /* hwdep interface */
+ int iface; /* hwdep interface */
unsigned char reserved[64]; /* reserved for future */
};
/* generic DSP loader */
-struct sndrv_hwdep_dsp_status {
+struct snd_hwdep_dsp_status {
unsigned int version; /* R: driver-specific version */
unsigned char id[32]; /* R: driver-specific ID string */
unsigned int num_dsps; /* R: number of DSP images to transfer */
@@ -138,7 +116,7 @@ struct sndrv_hwdep_dsp_status {
unsigned char reserved[16]; /* reserved for future use */
};
-struct sndrv_hwdep_dsp_image {
+struct snd_hwdep_dsp_image {
unsigned int index; /* W: DSP index */
unsigned char name[64]; /* W: ID (e.g. file name) */
unsigned char __user *image; /* W: binary image */
@@ -148,9 +126,9 @@ struct sndrv_hwdep_dsp_image {
enum {
SNDRV_HWDEP_IOCTL_PVERSION = _IOR ('H', 0x00, int),
- SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct sndrv_hwdep_info),
- SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct sndrv_hwdep_dsp_status),
- SNDRV_HWDEP_IOCTL_DSP_LOAD = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image)
+ SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct snd_hwdep_info),
+ SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct snd_hwdep_dsp_status),
+ SNDRV_HWDEP_IOCTL_DSP_LOAD = _IOW('H', 0x03, struct snd_hwdep_dsp_image)
};
/*****************************************************************************
@@ -161,10 +139,10 @@ enum {
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7)
-typedef unsigned long sndrv_pcm_uframes_t;
-typedef long sndrv_pcm_sframes_t;
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
-enum sndrv_pcm_class {
+enum {
SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */
SNDRV_PCM_CLASS_MULTI, /* multichannel device */
SNDRV_PCM_CLASS_MODEM, /* software modem class */
@@ -173,97 +151,94 @@ enum sndrv_pcm_class {
SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
};
-enum sndrv_pcm_subclass {
+enum {
SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */
SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */
/* Don't forget to change the following: */
SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
};
-enum sndrv_pcm_stream {
+enum {
SNDRV_PCM_STREAM_PLAYBACK = 0,
SNDRV_PCM_STREAM_CAPTURE,
SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
};
-enum sndrv_pcm_access {
- SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0, /* interleaved mmap */
- SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED, /* noninterleaved mmap */
- SNDRV_PCM_ACCESS_MMAP_COMPLEX, /* complex mmap */
- SNDRV_PCM_ACCESS_RW_INTERLEAVED, /* readi/writei */
- SNDRV_PCM_ACCESS_RW_NONINTERLEAVED, /* readn/writen */
- SNDRV_PCM_ACCESS_LAST = SNDRV_PCM_ACCESS_RW_NONINTERLEAVED,
-};
-
-enum sndrv_pcm_format {
- SNDRV_PCM_FORMAT_S8 = 0,
- SNDRV_PCM_FORMAT_U8,
- SNDRV_PCM_FORMAT_S16_LE,
- SNDRV_PCM_FORMAT_S16_BE,
- SNDRV_PCM_FORMAT_U16_LE,
- SNDRV_PCM_FORMAT_U16_BE,
- SNDRV_PCM_FORMAT_S24_LE, /* low three bytes */
- SNDRV_PCM_FORMAT_S24_BE, /* low three bytes */
- SNDRV_PCM_FORMAT_U24_LE, /* low three bytes */
- SNDRV_PCM_FORMAT_U24_BE, /* low three bytes */
- SNDRV_PCM_FORMAT_S32_LE,
- SNDRV_PCM_FORMAT_S32_BE,
- SNDRV_PCM_FORMAT_U32_LE,
- SNDRV_PCM_FORMAT_U32_BE,
- SNDRV_PCM_FORMAT_FLOAT_LE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
- SNDRV_PCM_FORMAT_FLOAT_BE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
- SNDRV_PCM_FORMAT_FLOAT64_LE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
- SNDRV_PCM_FORMAT_FLOAT64_BE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
- SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE, /* IEC-958 subframe, Little Endian */
- SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, /* IEC-958 subframe, Big Endian */
- SNDRV_PCM_FORMAT_MU_LAW,
- SNDRV_PCM_FORMAT_A_LAW,
- SNDRV_PCM_FORMAT_IMA_ADPCM,
- SNDRV_PCM_FORMAT_MPEG,
- SNDRV_PCM_FORMAT_GSM,
- SNDRV_PCM_FORMAT_SPECIAL = 31,
- SNDRV_PCM_FORMAT_S24_3LE = 32, /* in three bytes */
- SNDRV_PCM_FORMAT_S24_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_U24_3LE, /* in three bytes */
- SNDRV_PCM_FORMAT_U24_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_S20_3LE, /* in three bytes */
- SNDRV_PCM_FORMAT_S20_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_U20_3LE, /* in three bytes */
- SNDRV_PCM_FORMAT_U20_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_S18_3LE, /* in three bytes */
- SNDRV_PCM_FORMAT_S18_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_U18_3LE, /* in three bytes */
- SNDRV_PCM_FORMAT_U18_3BE, /* in three bytes */
- SNDRV_PCM_FORMAT_LAST = SNDRV_PCM_FORMAT_U18_3BE,
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0) /* interleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1) /* noninterleaved mmap */
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2) /* complex mmap */
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3) /* readi/writei */
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4) /* readn/writen */
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8) /* low three bytes */
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9) /* low three bytes */
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15) /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17) /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18) /* IEC-958 subframe, Little Endian */
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19) /* IEC-958 subframe, Big Endian */
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40) /* in three bytes */
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42) /* in three bytes */
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43) /* in three bytes */
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_U18_3BE
#ifdef SNDRV_LITTLE_ENDIAN
- SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE,
- SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_LE,
- SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_LE,
- SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_LE,
- SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_LE,
- SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_LE,
- SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_LE,
- SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_LE,
- SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE,
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
#endif
#ifdef SNDRV_BIG_ENDIAN
- SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_BE,
- SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_BE,
- SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_BE,
- SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_BE,
- SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_BE,
- SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_BE,
- SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_BE,
- SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_BE,
- SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE,
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
#endif
-};
-enum sndrv_pcm_subformat {
- SNDRV_PCM_SUBFORMAT_STD = 0,
- SNDRV_PCM_SUBFORMAT_LAST = SNDRV_PCM_SUBFORMAT_STD,
-};
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
#define SNDRV_PCM_INFO_MMAP 0x00000001 /* hardware supports mmap */
#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002 /* period data are valid during transfer */
@@ -280,18 +255,17 @@ enum sndrv_pcm_subformat {
#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */
#define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */
-enum sndrv_pcm_state {
- SNDRV_PCM_STATE_OPEN = 0, /* stream is open */
- SNDRV_PCM_STATE_SETUP, /* stream has a setup */
- SNDRV_PCM_STATE_PREPARED, /* stream is ready to start */
- SNDRV_PCM_STATE_RUNNING, /* stream is running */
- SNDRV_PCM_STATE_XRUN, /* stream reached an xrun */
- SNDRV_PCM_STATE_DRAINING, /* stream is draining */
- SNDRV_PCM_STATE_PAUSED, /* stream is paused */
- SNDRV_PCM_STATE_SUSPENDED, /* hardware is suspended */
- SNDRV_PCM_STATE_DISCONNECTED, /* hardware is disconnected */
- SNDRV_PCM_STATE_LAST = SNDRV_PCM_STATE_DISCONNECTED,
-};
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0) /* stream is open */
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1) /* stream has a setup */
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2) /* stream is ready to start */
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3) /* stream is running */
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4) /* stream reached an xrun */
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5) /* stream is draining */
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6) /* stream is paused */
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7) /* hardware is suspended */
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8) /* hardware is disconnected */
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
enum {
SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
@@ -299,55 +273,53 @@ enum {
SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
};
-union sndrv_pcm_sync_id {
+union snd_pcm_sync_id {
unsigned char id[16];
unsigned short id16[8];
unsigned int id32[4];
};
-struct sndrv_pcm_info {
+struct snd_pcm_info {
unsigned int device; /* RO/WR (control): device number */
unsigned int subdevice; /* RO/WR (control): subdevice number */
- enum sndrv_pcm_stream stream; /* RO/WR (control): stream number */
+ int stream; /* RO/WR (control): stream direction */
int card; /* R: card number */
unsigned char id[64]; /* ID (user selectable) */
unsigned char name[80]; /* name of this device */
unsigned char subname[32]; /* subdevice name */
- enum sndrv_pcm_class dev_class; /* SNDRV_PCM_CLASS_* */
- enum sndrv_pcm_subclass dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
+ int dev_class; /* SNDRV_PCM_CLASS_* */
+ int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */
unsigned int subdevices_count;
unsigned int subdevices_avail;
- union sndrv_pcm_sync_id sync; /* hardware synchronization ID */
+ union snd_pcm_sync_id sync; /* hardware synchronization ID */
unsigned char reserved[64]; /* reserved for future... */
};
-enum sndrv_pcm_hw_param {
- SNDRV_PCM_HW_PARAM_ACCESS = 0, /* Access type */
- SNDRV_PCM_HW_PARAM_FIRST_MASK = SNDRV_PCM_HW_PARAM_ACCESS,
- SNDRV_PCM_HW_PARAM_FORMAT, /* Format */
- SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */
- SNDRV_PCM_HW_PARAM_LAST_MASK = SNDRV_PCM_HW_PARAM_SUBFORMAT,
-
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8, /* Bits per sample */
- SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */
- SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */
- SNDRV_PCM_HW_PARAM_RATE, /* Approx rate */
- SNDRV_PCM_HW_PARAM_PERIOD_TIME, /* Approx distance between interrupts
- in us */
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, /* Approx frames between interrupts */
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, /* Approx bytes between interrupts */
- SNDRV_PCM_HW_PARAM_PERIODS, /* Approx interrupts per buffer */
- SNDRV_PCM_HW_PARAM_BUFFER_TIME, /* Approx duration of buffer in us */
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, /* Size of buffer in frames */
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, /* Size of buffer in bytes */
- SNDRV_PCM_HW_PARAM_TICK_TIME, /* Approx tick duration in us */
- SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
-};
+typedef int __bitwise snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS ((__force snd_pcm_hw_param_t) 0) /* Access type */
+#define SNDRV_PCM_HW_PARAM_FORMAT ((__force snd_pcm_hw_param_t) 1) /* Format */
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT ((__force snd_pcm_hw_param_t) 2) /* Subformat */
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS ((__force snd_pcm_hw_param_t) 8) /* Bits per sample */
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS ((__force snd_pcm_hw_param_t) 9) /* Bits per frame */
+#define SNDRV_PCM_HW_PARAM_CHANNELS ((__force snd_pcm_hw_param_t) 10) /* Channels */
+#define SNDRV_PCM_HW_PARAM_RATE ((__force snd_pcm_hw_param_t) 11) /* Approx rate */
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME ((__force snd_pcm_hw_param_t) 12) /* Approx distance between interrupts in us */
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE ((__force snd_pcm_hw_param_t) 13) /* Approx frames between interrupts */
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES ((__force snd_pcm_hw_param_t) 14) /* Approx bytes between interrupts */
+#define SNDRV_PCM_HW_PARAM_PERIODS ((__force snd_pcm_hw_param_t) 15) /* Approx interrupts per buffer */
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME ((__force snd_pcm_hw_param_t) 16) /* Approx duration of buffer in us */
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE ((__force snd_pcm_hw_param_t) 17) /* Size of buffer in frames */
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES ((__force snd_pcm_hw_param_t) 18) /* Size of buffer in bytes */
+#define SNDRV_PCM_HW_PARAM_TICK_TIME ((__force snd_pcm_hw_param_t) 19) /* Approx tick duration in us */
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
-struct sndrv_interval {
+struct snd_interval {
unsigned int min, max;
unsigned int openmin:1,
openmax:1,
@@ -357,137 +329,137 @@ struct sndrv_interval {
#define SNDRV_MASK_MAX 256
-struct sndrv_mask {
+struct snd_mask {
u_int32_t bits[(SNDRV_MASK_MAX+31)/32];
};
-struct sndrv_pcm_hw_params {
+struct snd_pcm_hw_params {
unsigned int flags;
- struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
- struct sndrv_mask mres[5]; /* reserved masks */
- struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ struct snd_mask mres[5]; /* reserved masks */
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct sndrv_interval ires[9]; /* reserved intervals */
+ struct snd_interval ires[9]; /* reserved intervals */
unsigned int rmask; /* W: requested masks */
unsigned int cmask; /* R: changed masks */
unsigned int info; /* R: Info flags for returned setup */
unsigned int msbits; /* R: used most significant bits */
unsigned int rate_num; /* R: rate numerator */
unsigned int rate_den; /* R: rate denominator */
- sndrv_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
+ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */
unsigned char reserved[64]; /* reserved for future */
};
-enum sndrv_pcm_tstamp {
+enum {
SNDRV_PCM_TSTAMP_NONE = 0,
SNDRV_PCM_TSTAMP_MMAP,
SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_MMAP,
};
-struct sndrv_pcm_sw_params {
- enum sndrv_pcm_tstamp tstamp_mode; /* timestamp mode */
+struct snd_pcm_sw_params {
+ int tstamp_mode; /* timestamp mode */
unsigned int period_step;
unsigned int sleep_min; /* min ticks to sleep */
- sndrv_pcm_uframes_t avail_min; /* min avail frames for wakeup */
- sndrv_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
- sndrv_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
- sndrv_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
- sndrv_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
- sndrv_pcm_uframes_t silence_size; /* silence block size */
- sndrv_pcm_uframes_t boundary; /* pointers wrap point */
+ snd_pcm_uframes_t avail_min; /* min avail frames for wakeup */
+ snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
+ snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
+ snd_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */
+ snd_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */
+ snd_pcm_uframes_t silence_size; /* silence block size */
+ snd_pcm_uframes_t boundary; /* pointers wrap point */
unsigned char reserved[64]; /* reserved for future */
};
-struct sndrv_pcm_channel_info {
+struct snd_pcm_channel_info {
unsigned int channel;
off_t offset; /* mmap offset */
unsigned int first; /* offset to first sample in bits */
unsigned int step; /* samples distance in bits */
};
-struct sndrv_pcm_status {
- enum sndrv_pcm_state state; /* stream state */
+struct snd_pcm_status {
+ snd_pcm_state_t state; /* stream state */
struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
struct timespec tstamp; /* reference timestamp */
- sndrv_pcm_uframes_t appl_ptr; /* appl ptr */
- sndrv_pcm_uframes_t hw_ptr; /* hw ptr */
- sndrv_pcm_sframes_t delay; /* current delay in frames */
- sndrv_pcm_uframes_t avail; /* number of frames available */
- sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */
- sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
- enum sndrv_pcm_state suspended_state; /* suspended stream state */
+ snd_pcm_uframes_t appl_ptr; /* appl ptr */
+ snd_pcm_uframes_t hw_ptr; /* hw ptr */
+ snd_pcm_sframes_t delay; /* current delay in frames */
+ snd_pcm_uframes_t avail; /* number of frames available */
+ snd_pcm_uframes_t avail_max; /* max frames available on hw since last status */
+ snd_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */
+ snd_pcm_state_t suspended_state; /* suspended stream state */
unsigned char reserved[60]; /* must be filled with zero */
};
-struct sndrv_pcm_mmap_status {
- enum sndrv_pcm_state state; /* RO: state - SNDRV_PCM_STATE_XXXX */
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state; /* RO: state - SNDRV_PCM_STATE_XXXX */
int pad1; /* Needed for 64 bit alignment */
- sndrv_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
+ snd_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */
struct timespec tstamp; /* Timestamp */
- enum sndrv_pcm_state suspended_state; /* RO: suspended stream state */
+ snd_pcm_state_t suspended_state; /* RO: suspended stream state */
};
-struct sndrv_pcm_mmap_control {
- sndrv_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
- sndrv_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */
+ snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
};
#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0) /* execute hwsync */
#define SNDRV_PCM_SYNC_PTR_APPL (1<<1) /* get appl_ptr from driver (r/w op) */
#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2) /* get avail_min from driver */
-struct sndrv_pcm_sync_ptr {
+struct snd_pcm_sync_ptr {
unsigned int flags;
union {
- struct sndrv_pcm_mmap_status status;
+ struct snd_pcm_mmap_status status;
unsigned char reserved[64];
} s;
union {
- struct sndrv_pcm_mmap_control control;
+ struct snd_pcm_mmap_control control;
unsigned char reserved[64];
} c;
};
-struct sndrv_xferi {
- sndrv_pcm_sframes_t result;
+struct snd_xferi {
+ snd_pcm_sframes_t result;
void __user *buf;
- sndrv_pcm_uframes_t frames;
+ snd_pcm_uframes_t frames;
};
-struct sndrv_xfern {
- sndrv_pcm_sframes_t result;
+struct snd_xfern {
+ snd_pcm_sframes_t result;
void __user * __user *bufs;
- sndrv_pcm_uframes_t frames;
+ snd_pcm_uframes_t frames;
};
enum {
SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
- SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct sndrv_pcm_info),
+ SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
- SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct sndrv_pcm_hw_params),
- SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct sndrv_pcm_hw_params),
+ SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params),
+ SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params),
SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12),
- SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct sndrv_pcm_sw_params),
- SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct sndrv_pcm_status),
- SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, sndrv_pcm_sframes_t),
+ SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct snd_pcm_sw_params),
+ SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct snd_pcm_status),
+ SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, snd_pcm_sframes_t),
SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
- SNDRV_PCM_IOCTL_SYNC_PTR = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr),
- SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct sndrv_pcm_channel_info),
+ SNDRV_PCM_IOCTL_SYNC_PTR = _IOWR('A', 0x23, struct snd_pcm_sync_ptr),
+ SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct snd_pcm_channel_info),
SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
SNDRV_PCM_IOCTL_START = _IO('A', 0x42),
SNDRV_PCM_IOCTL_DROP = _IO('A', 0x43),
SNDRV_PCM_IOCTL_DRAIN = _IO('A', 0x44),
SNDRV_PCM_IOCTL_PAUSE = _IOW('A', 0x45, int),
- SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, sndrv_pcm_uframes_t),
+ SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, snd_pcm_uframes_t),
SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47),
SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48),
- SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, sndrv_pcm_uframes_t),
- SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct sndrv_xferi),
- SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct sndrv_xferi),
- SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct sndrv_xfern),
- SNDRV_PCM_IOCTL_READN_FRAMES = _IOR('A', 0x53, struct sndrv_xfern),
+ SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, snd_pcm_uframes_t),
+ SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct snd_xferi),
+ SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct snd_xferi),
+ SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct snd_xfern),
+ SNDRV_PCM_IOCTL_READN_FRAMES = _IOR('A', 0x53, struct snd_xfern),
SNDRV_PCM_IOCTL_LINK = _IOW('A', 0x60, int),
SNDRV_PCM_IOCTL_UNLINK = _IO('A', 0x61),
};
@@ -507,7 +479,7 @@ enum {
#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
-enum sndrv_rawmidi_stream {
+enum {
SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
SNDRV_RAWMIDI_STREAM_INPUT,
SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
@@ -517,10 +489,10 @@ enum sndrv_rawmidi_stream {
#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
-struct sndrv_rawmidi_info {
+struct snd_rawmidi_info {
unsigned int device; /* RO/WR (control): device number */
unsigned int subdevice; /* RO/WR (control): subdevice number */
- enum sndrv_rawmidi_stream stream; /* WR: stream */
+ int stream; /* WR: stream */
int card; /* R: card number */
unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */
unsigned char id[64]; /* ID (user selectable) */
@@ -531,16 +503,16 @@ struct sndrv_rawmidi_info {
unsigned char reserved[64]; /* reserved for future use */
};
-struct sndrv_rawmidi_params {
- enum sndrv_rawmidi_stream stream;
+struct snd_rawmidi_params {
+ int stream;
size_t buffer_size; /* queue size in bytes */
size_t avail_min; /* minimum avail bytes for wakeup */
unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */
unsigned char reserved[16]; /* reserved for future use */
};
-struct sndrv_rawmidi_status {
- enum sndrv_rawmidi_stream stream;
+struct snd_rawmidi_status {
+ int stream;
struct timespec tstamp; /* Timestamp */
size_t avail; /* available bytes */
size_t xruns; /* count of overruns since last status (in bytes) */
@@ -549,9 +521,9 @@ struct sndrv_rawmidi_status {
enum {
SNDRV_RAWMIDI_IOCTL_PVERSION = _IOR('W', 0x00, int),
- SNDRV_RAWMIDI_IOCTL_INFO = _IOR('W', 0x01, struct sndrv_rawmidi_info),
- SNDRV_RAWMIDI_IOCTL_PARAMS = _IOWR('W', 0x10, struct sndrv_rawmidi_params),
- SNDRV_RAWMIDI_IOCTL_STATUS = _IOWR('W', 0x20, struct sndrv_rawmidi_status),
+ SNDRV_RAWMIDI_IOCTL_INFO = _IOR('W', 0x01, struct snd_rawmidi_info),
+ SNDRV_RAWMIDI_IOCTL_PARAMS = _IOWR('W', 0x10, struct snd_rawmidi_params),
+ SNDRV_RAWMIDI_IOCTL_STATUS = _IOWR('W', 0x20, struct snd_rawmidi_status),
SNDRV_RAWMIDI_IOCTL_DROP = _IOW('W', 0x30, int),
SNDRV_RAWMIDI_IOCTL_DRAIN = _IOW('W', 0x31, int),
};
@@ -562,7 +534,7 @@ enum {
#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
-enum sndrv_timer_class {
+enum {
SNDRV_TIMER_CLASS_NONE = -1,
SNDRV_TIMER_CLASS_SLAVE = 0,
SNDRV_TIMER_CLASS_GLOBAL,
@@ -572,7 +544,7 @@ enum sndrv_timer_class {
};
/* slave timer classes */
-enum sndrv_timer_slave_class {
+enum {
SNDRV_TIMER_SCLASS_NONE = 0,
SNDRV_TIMER_SCLASS_APPLICATION,
SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */
@@ -588,16 +560,16 @@ enum sndrv_timer_slave_class {
/* info flags */
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
-struct sndrv_timer_id {
- enum sndrv_timer_class dev_class;
- enum sndrv_timer_slave_class dev_sclass;
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
int card;
int device;
int subdevice;
};
-struct sndrv_timer_ginfo {
- struct sndrv_timer_id tid; /* requested timer ID */
+struct snd_timer_ginfo {
+ struct snd_timer_id tid; /* requested timer ID */
unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
int card; /* card number */
unsigned char id[64]; /* timer identification */
@@ -610,27 +582,27 @@ struct sndrv_timer_ginfo {
unsigned char reserved[32];
};
-struct sndrv_timer_gparams {
- struct sndrv_timer_id tid; /* requested timer ID */
+struct snd_timer_gparams {
+ struct snd_timer_id tid; /* requested timer ID */
unsigned long period_num; /* requested precise period duration (in seconds) - numerator */
unsigned long period_den; /* requested precise period duration (in seconds) - denominator */
unsigned char reserved[32];
};
-struct sndrv_timer_gstatus {
- struct sndrv_timer_id tid; /* requested timer ID */
+struct snd_timer_gstatus {
+ struct snd_timer_id tid; /* requested timer ID */
unsigned long resolution; /* current period resolution in ns */
unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */
unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */
unsigned char reserved[32];
};
-struct sndrv_timer_select {
- struct sndrv_timer_id id; /* bind to timer ID */
+struct snd_timer_select {
+ struct snd_timer_id id; /* bind to timer ID */
unsigned char reserved[32]; /* reserved */
};
-struct sndrv_timer_info {
+struct snd_timer_info {
unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */
int card; /* card number */
unsigned char id[64]; /* timer identificator */
@@ -644,7 +616,7 @@ struct sndrv_timer_info {
#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1) /* exclusive use, precise start/stop/pause/continue */
#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2) /* write early event to the poll queue */
-struct sndrv_timer_params {
+struct snd_timer_params {
unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */
unsigned int ticks; /* requested resolution in ticks */
unsigned int queue_size; /* total size of queue (32-1024) */
@@ -653,7 +625,7 @@ struct sndrv_timer_params {
unsigned char reserved[60]; /* reserved */
};
-struct sndrv_timer_status {
+struct snd_timer_status {
struct timespec tstamp; /* Timestamp - last update */
unsigned int resolution; /* current period resolution in ns */
unsigned int lost; /* counter of master tick lost */
@@ -664,15 +636,15 @@ struct sndrv_timer_status {
enum {
SNDRV_TIMER_IOCTL_PVERSION = _IOR('T', 0x00, int),
- SNDRV_TIMER_IOCTL_NEXT_DEVICE = _IOWR('T', 0x01, struct sndrv_timer_id),
+ SNDRV_TIMER_IOCTL_NEXT_DEVICE = _IOWR('T', 0x01, struct snd_timer_id),
SNDRV_TIMER_IOCTL_TREAD = _IOW('T', 0x02, int),
- SNDRV_TIMER_IOCTL_GINFO = _IOWR('T', 0x03, struct sndrv_timer_ginfo),
- SNDRV_TIMER_IOCTL_GPARAMS = _IOW('T', 0x04, struct sndrv_timer_gparams),
- SNDRV_TIMER_IOCTL_GSTATUS = _IOWR('T', 0x05, struct sndrv_timer_gstatus),
- SNDRV_TIMER_IOCTL_SELECT = _IOW('T', 0x10, struct sndrv_timer_select),
- SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct sndrv_timer_info),
- SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct sndrv_timer_params),
- SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct sndrv_timer_status),
+ SNDRV_TIMER_IOCTL_GINFO = _IOWR('T', 0x03, struct snd_timer_ginfo),
+ SNDRV_TIMER_IOCTL_GPARAMS = _IOW('T', 0x04, struct snd_timer_gparams),
+ SNDRV_TIMER_IOCTL_GSTATUS = _IOWR('T', 0x05, struct snd_timer_gstatus),
+ SNDRV_TIMER_IOCTL_SELECT = _IOW('T', 0x10, struct snd_timer_select),
+ SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct snd_timer_info),
+ SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct snd_timer_params),
+ SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct snd_timer_status),
/* The following four ioctls are changed since 1.0.9 due to confliction */
SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
@@ -680,12 +652,12 @@ enum {
SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
};
-struct sndrv_timer_read {
+struct snd_timer_read {
unsigned int resolution;
unsigned int ticks;
};
-enum sndrv_timer_event {
+enum {
SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */
SNDRV_TIMER_EVENT_TICK, /* val = ticks */
SNDRV_TIMER_EVENT_START, /* val = resolution in ns */
@@ -704,8 +676,8 @@ enum sndrv_timer_event {
SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
};
-struct sndrv_timer_tread {
- enum sndrv_timer_event event;
+struct snd_timer_tread {
+ int event;
struct timespec tstamp;
unsigned int val;
};
@@ -718,7 +690,7 @@ struct sndrv_timer_tread {
#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
-struct sndrv_ctl_card_info {
+struct snd_ctl_card_info {
int card; /* card number */
int pad; /* reserved for future (was type) */
unsigned char id[16]; /* ID of card (user selectable) */
@@ -731,27 +703,25 @@ struct sndrv_ctl_card_info {
unsigned char reserved[48]; /* reserved for future */
};
-enum sndrv_ctl_elem_type {
- SNDRV_CTL_ELEM_TYPE_NONE = 0, /* invalid */
- SNDRV_CTL_ELEM_TYPE_BOOLEAN, /* boolean type */
- SNDRV_CTL_ELEM_TYPE_INTEGER, /* integer type */
- SNDRV_CTL_ELEM_TYPE_ENUMERATED, /* enumerated type */
- SNDRV_CTL_ELEM_TYPE_BYTES, /* byte array */
- SNDRV_CTL_ELEM_TYPE_IEC958, /* IEC958 (S/PDIF) setup */
- SNDRV_CTL_ELEM_TYPE_INTEGER64, /* 64-bit integer type */
- SNDRV_CTL_ELEM_TYPE_LAST = SNDRV_CTL_ELEM_TYPE_INTEGER64,
-};
-
-enum sndrv_ctl_elem_iface {
- SNDRV_CTL_ELEM_IFACE_CARD = 0, /* global control */
- SNDRV_CTL_ELEM_IFACE_HWDEP, /* hardware dependent device */
- SNDRV_CTL_ELEM_IFACE_MIXER, /* virtual mixer device */
- SNDRV_CTL_ELEM_IFACE_PCM, /* PCM device */
- SNDRV_CTL_ELEM_IFACE_RAWMIDI, /* RawMidi device */
- SNDRV_CTL_ELEM_IFACE_TIMER, /* timer device */
- SNDRV_CTL_ELEM_IFACE_SEQUENCER, /* sequencer client */
- SNDRV_CTL_ELEM_IFACE_LAST = SNDRV_CTL_ELEM_IFACE_SEQUENCER,
-};
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0) /* invalid */
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1) /* boolean type */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2) /* integer type */
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3) /* enumerated type */
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4) /* byte array */
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5) /* IEC958 (S/PDIF) setup */
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6) /* 64-bit integer type */
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0) /* global control */
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1) /* hardware dependent device */
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2) /* virtual mixer device */
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3) /* PCM device */
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4) /* RawMidi device */
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5) /* timer device */
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6) /* sequencer client */
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
@@ -773,27 +743,27 @@ enum sndrv_ctl_elem_iface {
#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000) /* Off, with power */
#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001) /* Off, without power */
-struct sndrv_ctl_elem_id {
+struct snd_ctl_elem_id {
unsigned int numid; /* numeric identifier, zero = invalid */
- enum sndrv_ctl_elem_iface iface; /* interface identifier */
+ snd_ctl_elem_iface_t iface; /* interface identifier */
unsigned int device; /* device/client number */
unsigned int subdevice; /* subdevice (substream) number */
unsigned char name[44]; /* ASCII name of item */
unsigned int index; /* index of item */
};
-struct sndrv_ctl_elem_list {
+struct snd_ctl_elem_list {
unsigned int offset; /* W: first element ID to get */
unsigned int space; /* W: count of element IDs to get */
unsigned int used; /* R: count of element IDs set */
unsigned int count; /* R: count of all elements */
- struct sndrv_ctl_elem_id __user *pids; /* R: IDs */
+ struct snd_ctl_elem_id __user *pids; /* R: IDs */
unsigned char reserved[50];
};
-struct sndrv_ctl_elem_info {
- struct sndrv_ctl_elem_id id; /* W: element ID */
- enum sndrv_ctl_elem_type type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id; /* W: element ID */
+ snd_ctl_elem_type_t type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */
unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */
unsigned int count; /* count of values */
pid_t owner; /* owner's PID of this control */
@@ -822,8 +792,8 @@ struct sndrv_ctl_elem_info {
unsigned char reserved[64-4*sizeof(unsigned short)];
};
-struct sndrv_ctl_elem_value {
- struct sndrv_ctl_elem_id id; /* W: element ID */
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id; /* W: element ID */
unsigned int indirect: 1; /* W: use indirect pointer (xxx_ptr member) */
union {
union {
@@ -842,7 +812,7 @@ struct sndrv_ctl_elem_value {
unsigned char data[512];
unsigned char *data_ptr;
} bytes;
- struct sndrv_aes_iec958 iec958;
+ struct snd_aes_iec958 iec958;
} value; /* RO */
struct timespec tstamp;
unsigned char reserved[128-sizeof(struct timespec)];
@@ -850,24 +820,24 @@ struct sndrv_ctl_elem_value {
enum {
SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
- SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct sndrv_ctl_card_info),
- SNDRV_CTL_IOCTL_ELEM_LIST = _IOWR('U', 0x10, struct sndrv_ctl_elem_list),
- SNDRV_CTL_IOCTL_ELEM_INFO = _IOWR('U', 0x11, struct sndrv_ctl_elem_info),
- SNDRV_CTL_IOCTL_ELEM_READ = _IOWR('U', 0x12, struct sndrv_ctl_elem_value),
- SNDRV_CTL_IOCTL_ELEM_WRITE = _IOWR('U', 0x13, struct sndrv_ctl_elem_value),
- SNDRV_CTL_IOCTL_ELEM_LOCK = _IOW('U', 0x14, struct sndrv_ctl_elem_id),
- SNDRV_CTL_IOCTL_ELEM_UNLOCK = _IOW('U', 0x15, struct sndrv_ctl_elem_id),
+ SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
+ SNDRV_CTL_IOCTL_ELEM_LIST = _IOWR('U', 0x10, struct snd_ctl_elem_list),
+ SNDRV_CTL_IOCTL_ELEM_INFO = _IOWR('U', 0x11, struct snd_ctl_elem_info),
+ SNDRV_CTL_IOCTL_ELEM_READ = _IOWR('U', 0x12, struct snd_ctl_elem_value),
+ SNDRV_CTL_IOCTL_ELEM_WRITE = _IOWR('U', 0x13, struct snd_ctl_elem_value),
+ SNDRV_CTL_IOCTL_ELEM_LOCK = _IOW('U', 0x14, struct snd_ctl_elem_id),
+ SNDRV_CTL_IOCTL_ELEM_UNLOCK = _IOW('U', 0x15, struct snd_ctl_elem_id),
SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS = _IOWR('U', 0x16, int),
- SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct sndrv_ctl_elem_info),
- SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct sndrv_ctl_elem_info),
- SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct sndrv_ctl_elem_id),
+ SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
+ SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
+ SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
- SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct sndrv_hwdep_info),
+ SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
- SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct sndrv_pcm_info),
+ SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct snd_pcm_info),
SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int),
SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE = _IOWR('U', 0x40, int),
- SNDRV_CTL_IOCTL_RAWMIDI_INFO = _IOWR('U', 0x41, struct sndrv_rawmidi_info),
+ SNDRV_CTL_IOCTL_RAWMIDI_INFO = _IOWR('U', 0x41, struct snd_rawmidi_info),
SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE = _IOW('U', 0x42, int),
SNDRV_CTL_IOCTL_POWER = _IOWR('U', 0xd0, int),
SNDRV_CTL_IOCTL_POWER_STATE = _IOR('U', 0xd1, int),
@@ -887,12 +857,12 @@ enum sndrv_ctl_event_type {
#define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */
#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */
-struct sndrv_ctl_event {
- enum sndrv_ctl_event_type type; /* event type - SNDRV_CTL_EVENT_* */
+struct snd_ctl_event {
+ int type; /* event type - SNDRV_CTL_EVENT_* */
union {
struct {
unsigned int mask;
- struct sndrv_ctl_elem_id id;
+ struct snd_ctl_elem_id id;
} elem;
unsigned char data8[60];
} data;
@@ -920,14 +890,14 @@ struct sndrv_ctl_event {
*
*/
-struct sndrv_xferv {
+struct snd_xferv {
const struct iovec *vector;
unsigned long count;
};
enum {
- SNDRV_IOCTL_READV = _IOW('K', 0x00, struct sndrv_xferv),
- SNDRV_IOCTL_WRITEV = _IOW('K', 0x01, struct sndrv_xferv),
+ SNDRV_IOCTL_READV = _IOW('K', 0x00, struct snd_xferv),
+ SNDRV_IOCTL_WRITEV = _IOW('K', 0x01, struct snd_xferv),
};
#endif /* __SOUND_ASOUND_H */
diff --git a/include/sound/asound_fm.h b/include/sound/asound_fm.h
index b0da677f8f75..956fdc23c595 100644
--- a/include/sound/asound_fm.h
+++ b/include/sound/asound_fm.h
@@ -29,16 +29,16 @@
#define SNDRV_DM_FM_MODE_OPL2 0x00
#define SNDRV_DM_FM_MODE_OPL3 0x01
-typedef struct snd_dm_fm_info {
+struct snd_dm_fm_info {
unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
unsigned char rhythm; /* percussion mode flag */
-} snd_dm_fm_info_t;
+};
/*
* Data structure composing an FM "note" or sound event.
*/
-typedef struct snd_dm_fm_voice {
+struct snd_dm_fm_voice {
unsigned char op; /* operator cell (0 or 1) */
unsigned char voice; /* FM voice (0 to 17) */
@@ -60,25 +60,25 @@ typedef struct snd_dm_fm_voice {
unsigned char left; /* stereo left */
unsigned char right; /* stereo right */
unsigned char waveform; /* 3 bits: waveform shape */
-} snd_dm_fm_voice_t;
+};
/*
* This describes an FM note by its voice, octave, frequency number (10bit)
* and key on/off.
*/
-typedef struct snd_dm_fm_note {
+struct snd_dm_fm_note {
unsigned char voice; /* 0-17 voice channel */
unsigned char octave; /* 3 bits: what octave to play */
unsigned int fnum; /* 10 bits: frequency number */
unsigned char key_on; /* set for active, clear for silent */
-} snd_dm_fm_note_t;
+};
/*
* FM parameters that apply globally to all voices, and thus are not "notes"
*/
-typedef struct snd_dm_fm_params {
+struct snd_dm_fm_params {
unsigned char am_depth; /* amplitude modulation depth (1=hi) */
unsigned char vib_depth; /* vibrato depth (1=hi) */
unsigned char kbd_split; /* keyboard split */
@@ -90,17 +90,17 @@ typedef struct snd_dm_fm_params {
unsigned char tomtom;
unsigned char cymbal;
unsigned char hihat;
-} snd_dm_fm_params_t;
+};
/*
* FM mode ioctl settings
*/
-#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, snd_dm_fm_info_t)
+#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, struct snd_dm_fm_info)
#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21)
-#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, snd_dm_fm_note_t)
-#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, snd_dm_fm_voice_t)
-#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, snd_dm_fm_params_t)
+#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, struct snd_dm_fm_note)
+#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, struct snd_dm_fm_voice)
+#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, struct snd_dm_fm_params)
#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int)
/* for OPL3 only */
#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int)
diff --git a/include/sound/control.h b/include/sound/control.h
index ef7903c7a327..2489b1eb0110 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -24,24 +24,14 @@
#include <sound/asound.h>
-typedef struct sndrv_aes_iec958 snd_aes_iec958_t;
-typedef struct sndrv_ctl_card_info snd_ctl_card_info_t;
-typedef enum sndrv_ctl_elem_type snd_ctl_elem_type_t;
-typedef enum sndrv_ctl_elem_iface snd_ctl_elem_iface_t;
-typedef struct sndrv_ctl_elem_id snd_ctl_elem_id_t;
-typedef struct sndrv_ctl_elem_list snd_ctl_elem_list_t;
-typedef struct sndrv_ctl_elem_info snd_ctl_elem_info_t;
-typedef struct sndrv_ctl_elem_value snd_ctl_elem_value_t;
-typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
-typedef struct sndrv_ctl_event snd_ctl_event_t;
-
#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
-typedef int (snd_kcontrol_info_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
-typedef int (snd_kcontrol_get_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-typedef int (snd_kcontrol_put_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+struct snd_kcontrol;
+typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo);
+typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
+typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
-typedef struct _snd_kcontrol_new {
+struct snd_kcontrol_new {
snd_ctl_elem_iface_t iface; /* interface identifier */
unsigned int device; /* device/client number */
unsigned int subdevice; /* subdevice (substream) number */
@@ -53,40 +43,40 @@ typedef struct _snd_kcontrol_new {
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
unsigned long private_value;
-} snd_kcontrol_new_t;
+};
-typedef struct _snd_kcontrol_volatile {
- snd_ctl_file_t *owner; /* locked */
+struct snd_kcontrol_volatile {
+ struct snd_ctl_file *owner; /* locked */
pid_t owner_pid;
unsigned int access; /* access rights */
-} snd_kcontrol_volatile_t;
+};
-struct _snd_kcontrol {
+struct snd_kcontrol {
struct list_head list; /* list of controls */
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
unsigned int count; /* count of same elements */
snd_kcontrol_info_t *info;
snd_kcontrol_get_t *get;
snd_kcontrol_put_t *put;
unsigned long private_value;
void *private_data;
- void (*private_free)(snd_kcontrol_t *kcontrol);
- snd_kcontrol_volatile_t vd[0]; /* volatile data */
+ void (*private_free)(struct snd_kcontrol *kcontrol);
+ struct snd_kcontrol_volatile vd[0]; /* volatile data */
};
-#define snd_kcontrol(n) list_entry(n, snd_kcontrol_t, list)
+#define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list)
-typedef struct _snd_kctl_event {
+struct snd_kctl_event {
struct list_head list; /* list of events */
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
unsigned int mask;
-} snd_kctl_event_t;
+};
-#define snd_kctl_event(n) list_entry(n, snd_kctl_event_t, list)
+#define snd_kctl_event(n) list_entry(n, struct snd_kctl_event, list)
-struct _snd_ctl_file {
+struct snd_ctl_file {
struct list_head list; /* list of all control files */
- snd_card_t *card;
+ struct snd_card *card;
pid_t pid;
int prefer_pcm_subdevice;
int prefer_rawmidi_subdevice;
@@ -97,25 +87,25 @@ struct _snd_ctl_file {
struct list_head events; /* waiting events for read */
};
-#define snd_ctl_file(n) list_entry(n, snd_ctl_file_t, list)
+#define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list)
-typedef int (*snd_kctl_ioctl_func_t) (snd_card_t * card,
- snd_ctl_file_t * control,
- unsigned int cmd, unsigned long arg);
+typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
+ struct snd_ctl_file * control,
+ unsigned int cmd, unsigned long arg);
-void snd_ctl_notify(snd_card_t * card, unsigned int mask, snd_ctl_elem_id_t * id);
+void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
-snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * kcontrol, unsigned int access);
-snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * kcontrolnew, void * private_data);
-void snd_ctl_free_one(snd_kcontrol_t * kcontrol);
-int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol);
-int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol);
-int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id);
-int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id);
-snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid);
-snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id);
+struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol * kcontrol, unsigned int access);
+struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
+void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
+int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
+int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
+int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
+int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
+struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
+struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
-int snd_ctl_create(snd_card_t *card);
+int snd_ctl_create(struct snd_card *card);
int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
@@ -127,20 +117,20 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
#define snd_ctl_unregister_ioctl_compat(fcn)
#endif
-int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control);
-int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
+int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control);
+int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, struct snd_ctl_elem_value *control);
-static inline unsigned int snd_ctl_get_ioffnum(snd_kcontrol_t *kctl, snd_ctl_elem_id_t *id)
+static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{
return id->numid - kctl->id.numid;
}
-static inline unsigned int snd_ctl_get_ioffidx(snd_kcontrol_t *kctl, snd_ctl_elem_id_t *id)
+static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{
return id->index - kctl->id.index;
}
-static inline unsigned int snd_ctl_get_ioff(snd_kcontrol_t *kctl, snd_ctl_elem_id_t *id)
+static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{
if (id->numid) {
return snd_ctl_get_ioffnum(kctl, id);
@@ -149,8 +139,8 @@ static inline unsigned int snd_ctl_get_ioff(snd_kcontrol_t *kctl, snd_ctl_elem_i
}
}
-static inline snd_ctl_elem_id_t *snd_ctl_build_ioff(snd_ctl_elem_id_t *dst_id,
- snd_kcontrol_t *src_kctl,
+static inline struct snd_ctl_elem_id *snd_ctl_build_ioff(struct snd_ctl_elem_id *dst_id,
+ struct snd_kcontrol *src_kctl,
unsigned int offset)
{
*dst_id = src_kctl->id;
diff --git a/include/sound/core.h b/include/sound/core.h
index 2be65ad2fd83..3093e3ddcf36 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -28,13 +28,6 @@
#include <linux/workqueue.h> /* struct workqueue_struct */
#include <linux/pm.h> /* pm_message_t */
-/* Typedef's */
-typedef struct sndrv_interval snd_interval_t;
-typedef enum sndrv_card_type snd_card_type;
-typedef struct sndrv_xferi snd_xferi_t;
-typedef struct sndrv_xfern snd_xfern_t;
-typedef struct sndrv_xferv snd_xferv_t;
-
/* forward declarations */
#ifdef CONFIG_PCI
struct pci_dev;
@@ -47,76 +40,50 @@ struct sbus_dev;
#define SNDRV_DEV_TYPE_RANGE_SIZE 0x1000
-typedef enum {
- SNDRV_DEV_TOPLEVEL = (0*SNDRV_DEV_TYPE_RANGE_SIZE),
- SNDRV_DEV_CONTROL,
- SNDRV_DEV_LOWLEVEL_PRE,
- SNDRV_DEV_LOWLEVEL_NORMAL = (1*SNDRV_DEV_TYPE_RANGE_SIZE),
- SNDRV_DEV_PCM,
- SNDRV_DEV_RAWMIDI,
- SNDRV_DEV_TIMER,
- SNDRV_DEV_SEQUENCER,
- SNDRV_DEV_HWDEP,
- SNDRV_DEV_INFO,
- SNDRV_DEV_BUS,
- SNDRV_DEV_CODEC,
- SNDRV_DEV_LOWLEVEL = (2*SNDRV_DEV_TYPE_RANGE_SIZE)
-} snd_device_type_t;
-
-typedef enum {
- SNDRV_DEV_BUILD,
- SNDRV_DEV_REGISTERED,
- SNDRV_DEV_DISCONNECTED
-} snd_device_state_t;
-
-typedef enum {
- SNDRV_DEV_CMD_PRE = 0,
- SNDRV_DEV_CMD_NORMAL = 1,
- SNDRV_DEV_CMD_POST = 2
-} snd_device_cmd_t;
-
-typedef struct _snd_card snd_card_t;
-typedef struct _snd_device snd_device_t;
-
-typedef int (snd_dev_free_t)(snd_device_t *device);
-typedef int (snd_dev_register_t)(snd_device_t *device);
-typedef int (snd_dev_disconnect_t)(snd_device_t *device);
-typedef int (snd_dev_unregister_t)(snd_device_t *device);
-
-typedef struct {
- snd_dev_free_t *dev_free;
- snd_dev_register_t *dev_register;
- snd_dev_disconnect_t *dev_disconnect;
- snd_dev_unregister_t *dev_unregister;
-} snd_device_ops_t;
-
-struct _snd_device {
+typedef int __bitwise snd_device_type_t;
+#define SNDRV_DEV_TOPLEVEL ((__force snd_device_type_t) 0)
+#define SNDRV_DEV_CONTROL ((__force snd_device_type_t) 1)
+#define SNDRV_DEV_LOWLEVEL_PRE ((__force snd_device_type_t) 2)
+#define SNDRV_DEV_LOWLEVEL_NORMAL ((__force snd_device_type_t) 0x1000)
+#define SNDRV_DEV_PCM ((__force snd_device_type_t) 0x1001)
+#define SNDRV_DEV_RAWMIDI ((__force snd_device_type_t) 0x1002)
+#define SNDRV_DEV_TIMER ((__force snd_device_type_t) 0x1003)
+#define SNDRV_DEV_SEQUENCER ((__force snd_device_type_t) 0x1004)
+#define SNDRV_DEV_HWDEP ((__force snd_device_type_t) 0x1005)
+#define SNDRV_DEV_INFO ((__force snd_device_type_t) 0x1006)
+#define SNDRV_DEV_BUS ((__force snd_device_type_t) 0x1007)
+#define SNDRV_DEV_CODEC ((__force snd_device_type_t) 0x1008)
+#define SNDRV_DEV_LOWLEVEL ((__force snd_device_type_t) 0x2000)
+
+typedef int __bitwise snd_device_state_t;
+#define SNDRV_DEV_BUILD ((__force snd_device_state_t) 0)
+#define SNDRV_DEV_REGISTERED ((__force snd_device_state_t) 1)
+#define SNDRV_DEV_DISCONNECTED ((__force snd_device_state_t) 2)
+
+typedef int __bitwise snd_device_cmd_t;
+#define SNDRV_DEV_CMD_PRE ((__force snd_device_cmd_t) 0)
+#define SNDRV_DEV_CMD_NORMAL ((__force snd_device_cmd_t) 1)
+#define SNDRV_DEV_CMD_POST ((__force snd_device_cmd_t) 2)
+
+struct snd_device;
+
+struct snd_device_ops {
+ int (*dev_free)(struct snd_device *dev);
+ int (*dev_register)(struct snd_device *dev);
+ int (*dev_disconnect)(struct snd_device *dev);
+ int (*dev_unregister)(struct snd_device *dev);
+};
+
+struct snd_device {
struct list_head list; /* list of registered devices */
- snd_card_t *card; /* card which holds this device */
+ struct snd_card *card; /* card which holds this device */
snd_device_state_t state; /* state of the device */
snd_device_type_t type; /* device type */
void *device_data; /* device structure */
- snd_device_ops_t *ops; /* operations */
+ struct snd_device_ops *ops; /* operations */
};
-#define snd_device(n) list_entry(n, snd_device_t, list)
-
-/* various typedefs */
-
-typedef struct snd_info_entry snd_info_entry_t;
-typedef struct _snd_pcm snd_pcm_t;
-typedef struct _snd_pcm_str snd_pcm_str_t;
-typedef struct _snd_pcm_substream snd_pcm_substream_t;
-typedef struct _snd_mixer snd_kmixer_t;
-typedef struct _snd_rawmidi snd_rawmidi_t;
-typedef struct _snd_ctl_file snd_ctl_file_t;
-typedef struct _snd_kcontrol snd_kcontrol_t;
-typedef struct _snd_timer snd_timer_t;
-typedef struct _snd_timer_instance snd_timer_instance_t;
-typedef struct _snd_hwdep snd_hwdep_t;
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-typedef struct _snd_oss_mixer snd_mixer_oss_t;
-#endif
+#define snd_device(n) list_entry(n, struct snd_device, list)
/* monitor files for graceful shutdown (hotplug) */
@@ -129,7 +96,7 @@ struct snd_shutdown_f_ops; /* define it later in init.c */
/* main structure for soundcard */
-struct _snd_card {
+struct snd_card {
int number; /* number of soundcard (index to
snd_cards) */
@@ -143,7 +110,7 @@ struct _snd_card {
struct module *module; /* top-level module */
void *private_data; /* private data for soundcard */
- void (*private_free) (snd_card_t *card); /* callback for freeing of
+ void (*private_free) (struct snd_card *card); /* callback for freeing of
private data */
struct list_head devices; /* devices */
@@ -155,8 +122,8 @@ struct _snd_card {
struct list_head controls; /* all controls for this card */
struct list_head ctl_files; /* active control files */
- snd_info_entry_t *proc_root; /* root for soundcard specific files */
- snd_info_entry_t *proc_id; /* the card id */
+ struct snd_info_entry *proc_root; /* root for soundcard specific files */
+ struct snd_info_entry *proc_id; /* the card id */
struct proc_dir_entry *proc_root_link; /* number link to real id */
struct snd_monitor_file *files; /* all files associated to this card */
@@ -167,92 +134,64 @@ 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);
- int (*pm_resume)(snd_card_t *card);
- void *pm_private_data;
unsigned int power_state; /* power state */
struct semaphore power_lock; /* power lock */
wait_queue_head_t power_sleep;
#endif
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
- snd_mixer_oss_t *mixer_oss;
+ struct snd_mixer_oss *mixer_oss;
int mixer_oss_change_count;
#endif
};
#ifdef CONFIG_PM
-static inline void snd_power_lock(snd_card_t *card)
+static inline void snd_power_lock(struct snd_card *card)
{
down(&card->power_lock);
}
-static inline void snd_power_unlock(snd_card_t *card)
+static inline void snd_power_unlock(struct snd_card *card)
{
up(&card->power_lock);
}
-static inline unsigned int snd_power_get_state(snd_card_t *card)
+static inline unsigned int snd_power_get_state(struct snd_card *card)
{
return card->power_state;
}
-static inline void snd_power_change_state(snd_card_t *card, unsigned int state)
+static inline void snd_power_change_state(struct snd_card *card, unsigned int state)
{
card->power_state = state;
wake_up(&card->power_sleep);
}
/* init.c */
-int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file);
-
-int snd_card_set_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, pm_message_t),
- int (*resume)(snd_card_t *),
- void *private_data);
-int snd_card_set_generic_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, pm_message_t),
- int (*resume)(snd_card_t *),
- void *private_data);
-#define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
- snd_card_set_generic_pm_callback(card, suspend, resume, data)
-struct pci_dev;
-int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state);
-int snd_card_pci_resume(struct pci_dev *dev);
-#define SND_PCI_PM_CALLBACKS \
- .suspend = snd_card_pci_suspend, .resume = snd_card_pci_resume
+int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file);
#else /* ! CONFIG_PM */
#define snd_power_lock(card) do { (void)(card); } while (0)
#define snd_power_unlock(card) do { (void)(card); } while (0)
-static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
+static inline int snd_power_wait(struct snd_card *card, unsigned int state, struct file *file) { return 0; }
#define snd_power_get_state(card) SNDRV_CTL_POWER_D0
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
-#define snd_card_set_pm_callback(card,suspend,resume,data)
-#define snd_card_set_generic_pm_callback(card,suspend,resume,data)
-#define snd_card_set_isa_pm_callback(card,suspend,resume,data)
-#define SND_PCI_PM_CALLBACKS
#endif /* CONFIG_PM */
-struct _snd_minor {
- struct list_head list; /* list of all minors per card */
- int number; /* minor number */
+struct snd_minor {
+ int type; /* SNDRV_DEVICE_TYPE_XXX */
+ int card; /* card number */
int device; /* device number */
- const char *comment; /* for /proc/asound/devices */
struct file_operations *f_ops; /* file operations */
+ void *private_data; /* private data for f_ops->open */
char name[0]; /* device name (keep at the end of
structure) */
};
-typedef struct _snd_minor snd_minor_t;
-
/* sound.c */
extern int snd_major;
@@ -260,12 +199,18 @@ extern int snd_ecards_limit;
void snd_request_card(int card);
-int snd_register_device(int type, snd_card_t *card, int dev, snd_minor_t *reg, const char *name);
-int snd_unregister_device(int type, snd_card_t *card, int dev);
+int snd_register_device(int type, struct snd_card *card, int dev,
+ struct file_operations *f_ops, void *private_data,
+ const char *name);
+int snd_unregister_device(int type, struct snd_card *card, int dev);
+void *snd_lookup_minor_data(unsigned int minor, int type);
#ifdef CONFIG_SND_OSSEMUL
-int snd_register_oss_device(int type, snd_card_t *card, int dev, snd_minor_t *reg, const char *name);
-int snd_unregister_oss_device(int type, snd_card_t *card, int dev);
+int snd_register_oss_device(int type, struct snd_card *card, int dev,
+ struct file_operations *f_ops, void *private_data,
+ const char *name);
+int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
+void *snd_lookup_oss_minor_data(unsigned int minor, int type);
#endif
int snd_minor_info_init(void);
@@ -276,11 +221,9 @@ int snd_minor_info_done(void);
#ifdef CONFIG_SND_OSSEMUL
int snd_minor_info_oss_init(void);
int snd_minor_info_oss_done(void);
-int snd_oss_init_module(void);
#else
#define snd_minor_info_oss_init() /*NOP*/
#define snd_minor_info_oss_done() /*NOP*/
-#define snd_oss_init_module() 0
#endif
/* memory.c */
@@ -291,43 +234,41 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size
/* init.c */
extern unsigned int snd_cards_lock;
-extern snd_card_t *snd_cards[SNDRV_CARDS];
+extern struct snd_card *snd_cards[SNDRV_CARDS];
extern rwlock_t snd_card_rwlock;
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
#define SND_MIXER_OSS_NOTIFY_REGISTER 0
#define SND_MIXER_OSS_NOTIFY_DISCONNECT 1
#define SND_MIXER_OSS_NOTIFY_FREE 2
-extern int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int cmd);
+extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
#endif
-snd_card_t *snd_card_new(int idx, const char *id,
+struct snd_card *snd_card_new(int idx, const char *id,
struct module *module, int extra_size);
-int snd_card_disconnect(snd_card_t *card);
-int snd_card_free(snd_card_t *card);
-int snd_card_free_in_thread(snd_card_t *card);
-int snd_card_register(snd_card_t *card);
+int snd_card_disconnect(struct snd_card *card);
+int snd_card_free(struct snd_card *card);
+int snd_card_free_in_thread(struct snd_card *card);
+int snd_card_register(struct snd_card *card);
int snd_card_info_init(void);
int snd_card_info_done(void);
-int snd_component_add(snd_card_t *card, const char *component);
-int snd_card_file_add(snd_card_t *card, struct file *file);
-int snd_card_file_remove(snd_card_t *card, struct file *file);
+int snd_component_add(struct snd_card *card, const char *component);
+int snd_card_file_add(struct snd_card *card, struct file *file);
+int snd_card_file_remove(struct snd_card *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 */
-int snd_device_new(snd_card_t *card, snd_device_type_t type,
- void *device_data, snd_device_ops_t *ops);
-int snd_device_register(snd_card_t *card, void *device_data);
-int snd_device_register_all(snd_card_t *card);
-int snd_device_disconnect(snd_card_t *card, void *device_data);
-int snd_device_disconnect_all(snd_card_t *card);
-int snd_device_free(snd_card_t *card, void *device_data);
-int snd_device_free_all(snd_card_t *card, snd_device_cmd_t cmd);
+int snd_device_new(struct snd_card *card, snd_device_type_t type,
+ void *device_data, struct snd_device_ops *ops);
+int snd_device_register(struct snd_card *card, void *device_data);
+int snd_device_register_all(struct snd_card *card);
+int snd_device_disconnect(struct snd_card *card, void *device_data);
+int snd_device_disconnect_all(struct snd_card *card);
+int snd_device_free(struct snd_card *card, void *device_data);
+int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd);
/* isadma.c */
@@ -376,7 +317,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
#ifdef CONFIG_SND_VERBOSE_PRINTK
/**
* snd_printd - debug printk
- * @format: format string
+ * @fmt: format string
*
* Compiled only when Works like snd_printk() for debugging purpose.
* Ignored when CONFIG_SND_DEBUG is not set.
@@ -390,7 +331,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
/**
* snd_assert - run-time assertion macro
* @expr: expression
- * @args...: the action
*
* This macro checks the expression in run-time and invokes the commands
* given in the rest arguments if the assertion is failed.
@@ -443,4 +383,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
#endif
#endif
+#include "typedefs.h"
+
#endif /* __SOUND_CORE_H */
diff --git a/include/sound/cs4231.h b/include/sound/cs4231.h
index d7f90823778a..ac6a5d882088 100644
--- a/include/sound/cs4231.h
+++ b/include/sound/cs4231.h
@@ -26,21 +26,6 @@
#include "pcm.h"
#include "timer.h"
-#ifdef CONFIG_SBUS
-#define SBUS_SUPPORT
-#include <asm/sbus.h>
-#endif
-
-#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)
-#define EBUS_SUPPORT
-#include <linux/pci.h>
-#include <asm/ebus.h>
-#endif
-
-#if !defined(SBUS_SUPPORT) && !defined(EBUS_SUPPORT)
-#define LEGACY_SUPPORT
-#endif
-
/* IO ports */
#define CS4231P(x) (c_d_c_CS4231##x)
@@ -232,18 +217,14 @@
#define CS4231_HWSHARE_DMA1 (1<<1)
#define CS4231_HWSHARE_DMA2 (1<<2)
-typedef struct _snd_cs4231 cs4231_t;
-
-struct _snd_cs4231 {
+struct snd_cs4231 {
unsigned long port; /* base i/o port */
-#ifdef LEGACY_SUPPORT
struct resource *res_port;
unsigned long cport; /* control base i/o port (CS4236) */
struct resource *res_cport;
int irq; /* IRQ line */
int dma1; /* playback DMA */
int dma2; /* record DMA */
-#endif
unsigned short version; /* version of CODEC chip */
unsigned short mode; /* see to CS4231_MODE_XXXX */
unsigned short hardware; /* see to CS4231_HW_XXXX */
@@ -251,29 +232,11 @@ struct _snd_cs4231 {
unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit daughter board) or dma1 == dma2 */
ebus_flag:1; /* SPARC: EBUS present */
-#ifdef EBUS_SUPPORT
- struct ebus_dma_info eb2c;
- struct ebus_dma_info eb2p;
-#endif
-
-#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
- union {
-#ifdef SBUS_SUPPORT
- struct sbus_dev *sdev;
-#endif
-#ifdef EBUS_SUPPORT
- struct pci_dev *pdev;
-#endif
- } dev_u;
- unsigned int p_periods_sent;
- unsigned int c_periods_sent;
-#endif
-
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
- snd_timer_t *timer;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_timer *timer;
unsigned char image[32]; /* registers image */
unsigned char eimage[32]; /* extended registers image */
@@ -281,63 +244,59 @@ struct _snd_cs4231 {
int mce_bit;
int calibrate_mute;
int sw_3d_bit;
-#ifdef LEGACY_SUPPORT
unsigned int p_dma_size;
unsigned int c_dma_size;
-#endif
spinlock_t reg_lock;
struct semaphore mce_mutex;
struct semaphore open_mutex;
- int (*rate_constraint) (snd_pcm_runtime_t *runtime);
- void (*set_playback_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char pdfr);
- void (*set_capture_format) (cs4231_t *chip, snd_pcm_hw_params_t *hw_params, unsigned char cdfr);
- void (*trigger) (cs4231_t *chip, unsigned int what, int start);
+ int (*rate_constraint) (struct snd_pcm_runtime *runtime);
+ void (*set_playback_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char pdfr);
+ void (*set_capture_format) (struct snd_cs4231 *chip, struct snd_pcm_hw_params *hw_params, unsigned char cdfr);
+ void (*trigger) (struct snd_cs4231 *chip, unsigned int what, int start);
#ifdef CONFIG_PM
- void (*suspend) (cs4231_t *chip);
- void (*resume) (cs4231_t *chip);
+ void (*suspend) (struct snd_cs4231 *chip);
+ void (*resume) (struct snd_cs4231 *chip);
#endif
void *dma_private_data;
-#ifdef LEGACY_SUPPORT
- int (*claim_dma) (cs4231_t *chip, void *dma_private_data, int dma);
- int (*release_dma) (cs4231_t *chip, void *dma_private_data, int dma);
-#endif
+ int (*claim_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma);
+ int (*release_dma) (struct snd_cs4231 *chip, void *dma_private_data, int dma);
};
/* exported functions */
-void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char val);
-unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg);
-void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val);
-unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg);
-void snd_cs4231_mce_up(cs4231_t *chip);
-void snd_cs4231_mce_down(cs4231_t *chip);
+void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val);
+unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg);
+void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val);
+unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg);
+void snd_cs4231_mce_up(struct snd_cs4231 *chip);
+void snd_cs4231_mce_down(struct snd_cs4231 *chip);
irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-const char *snd_cs4231_chip_id(cs4231_t *chip);
+const char *snd_cs4231_chip_id(struct snd_cs4231 *chip);
-int snd_cs4231_create(snd_card_t * card,
+int snd_cs4231_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
int irq, int dma1, int dma2,
unsigned short hardware,
unsigned short hwshare,
- cs4231_t ** rchip);
-int snd_cs4231_pcm(cs4231_t * chip, int device, snd_pcm_t **rpcm);
-int snd_cs4231_timer(cs4231_t * chip, int device, snd_timer_t **rtimer);
-int snd_cs4231_mixer(cs4231_t * chip);
+ struct snd_cs4231 ** rchip);
+int snd_cs4231_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm);
+int snd_cs4231_timer(struct snd_cs4231 * chip, int device, struct snd_timer **rtimer);
+int snd_cs4231_mixer(struct snd_cs4231 * chip);
-int snd_cs4236_create(snd_card_t * card,
+int snd_cs4236_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
int irq, int dma1, int dma2,
unsigned short hardware,
unsigned short hwshare,
- cs4231_t ** rchip);
-int snd_cs4236_pcm(cs4231_t * chip, int device, snd_pcm_t **rpcm);
-int snd_cs4236_mixer(cs4231_t * chip);
+ struct snd_cs4231 ** rchip);
+int snd_cs4236_pcm(struct snd_cs4231 * chip, int device, struct snd_pcm **rpcm);
+int snd_cs4236_mixer(struct snd_cs4231 * chip);
/*
* mixer library
@@ -349,9 +308,9 @@ int snd_cs4236_mixer(cs4231_t * chip);
.get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
-int snd_cs4231_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -359,8 +318,8 @@ int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
.get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
-int snd_cs4231_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
#endif /* __SOUND_CS4231_H */
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index b0c0e192eb56..199b5098ff7e 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -1631,42 +1631,41 @@
#define CS46XX_MIXER_SPDIF_INPUT_ELEMENT 1
#define CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT 2
-typedef struct _snd_cs46xx cs46xx_t;
-typedef struct _snd_cs46xx_pcm_t {
+struct snd_cs46xx_pcm {
struct snd_dma_buffer hw_buf;
unsigned int ctl;
unsigned int shift; /* Shift count to trasform frames in bytes */
- snd_pcm_indirect_t pcm_rec;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_indirect pcm_rec;
+ struct snd_pcm_substream *substream;
- pcm_channel_descriptor_t * pcm_channel;
+ struct dsp_pcm_channel_descriptor * pcm_channel;
int pcm_channel_id; /* Fron Rear, Center Lfe ... */
-} cs46xx_pcm_t;
+};
-typedef struct {
+struct snd_cs46xx_region {
char name[24];
unsigned long base;
void __iomem *remap_addr;
unsigned long size;
struct resource *resource;
-} snd_cs46xx_region_t;
+};
-struct _snd_cs46xx {
+struct snd_cs46xx {
int irq;
unsigned long ba0_addr;
unsigned long ba1_addr;
union {
struct {
- snd_cs46xx_region_t ba0;
- snd_cs46xx_region_t data0;
- snd_cs46xx_region_t data1;
- snd_cs46xx_region_t pmem;
- snd_cs46xx_region_t reg;
+ struct snd_cs46xx_region ba0;
+ struct snd_cs46xx_region data0;
+ struct snd_cs46xx_region data1;
+ struct snd_cs46xx_region pmem;
+ struct snd_cs46xx_region reg;
} name;
- snd_cs46xx_region_t idx[5];
+ struct snd_cs46xx_region idx[5];
} region;
unsigned int mode;
@@ -1676,34 +1675,34 @@ struct _snd_cs46xx {
unsigned int ctl;
unsigned int shift; /* Shift count to trasform frames in bytes */
- snd_pcm_indirect_t pcm_rec;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_indirect pcm_rec;
+ struct snd_pcm_substream *substream;
} capt;
int nr_ac97_codecs;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97[MAX_NR_AC97];
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97[MAX_NR_AC97];
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *midi_input;
- snd_rawmidi_substream_t *midi_output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_input;
+ struct snd_rawmidi_substream *midi_output;
spinlock_t reg_lock;
unsigned int midcr;
unsigned int uartm;
int amplifier;
- void (*amplifier_ctrl)(cs46xx_t *, int);
- void (*active_ctrl)(cs46xx_t *, int);
- void (*mixer_init)(cs46xx_t *);
+ void (*amplifier_ctrl)(struct snd_cs46xx *, int);
+ void (*active_ctrl)(struct snd_cs46xx *, int);
+ void (*mixer_init)(struct snd_cs46xx *);
int acpi_port;
- snd_kcontrol_t *eapd_switch; /* for amplifier hack */
+ struct snd_kcontrol *eapd_switch; /* for amplifier hack */
int accept_valid; /* accept mmap valid (for OSS) */
struct gameport *gameport;
@@ -1714,29 +1713,31 @@ struct _snd_cs46xx {
#ifdef CONFIG_SND_CS46XX_NEW_DSP
struct semaphore spos_mutex;
- dsp_spos_instance_t * dsp_spos_instance;
+ struct dsp_spos_instance * dsp_spos_instance;
- snd_pcm_t *pcm_rear;
- snd_pcm_t *pcm_center_lfe;
- snd_pcm_t *pcm_iec958;
+ struct snd_pcm *pcm_rear;
+ struct snd_pcm *pcm_center_lfe;
+ struct snd_pcm *pcm_iec958;
#else /* for compatibility */
- cs46xx_pcm_t *playback_pcm;
+ struct snd_cs46xx_pcm *playback_pcm;
unsigned int play_ctl;
#endif
};
-int snd_cs46xx_create(snd_card_t *card,
+int snd_cs46xx_create(struct snd_card *card,
struct pci_dev *pci,
int external_amp, int thinkpad,
- cs46xx_t **rcodec);
-
-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 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);
+ struct snd_cs46xx **rcodec);
+int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state);
+int snd_cs46xx_resume(struct pci_dev *pci);
+
+int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
+int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
+int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
+int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
+int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device);
+int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rmidi);
+int snd_cs46xx_start_dsp(struct snd_cs46xx *chip);
+int snd_cs46xx_gameport(struct snd_cs46xx *chip);
#endif /* __SOUND_CS46XX_H */
diff --git a/include/sound/cs46xx_dsp_scb_types.h b/include/sound/cs46xx_dsp_scb_types.h
index 3f990a3a6903..9cb6c7d09567 100644
--- a/include/sound/cs46xx_dsp_scb_types.h
+++ b/include/sound/cs46xx_dsp_scb_types.h
@@ -41,7 +41,7 @@
/* This structs are used internally by the SP */
-typedef struct _basic_dma_req_t {
+struct dsp_basic_dma_req {
/* DMA Requestor Word 0 (DCW) fields:
31 [30-28]27 [26:24] 23 22 21 20 [19:18] [17:16] 15 14 13 12 11 10 9 8 7 6 [5:0]
@@ -53,9 +53,9 @@ typedef struct _basic_dma_req_t {
u32 dmw; /* DMA Mode Word */
u32 saw; /* Source Address Word */
u32 daw; /* Destination Address Word */
-} basic_dma_req_t;
+};
-typedef struct _scatter_gather_ext_t {
+struct dsp_scatter_gather_ext {
u32 npaw; /* Next-Page Address Word */
/* DMA Requestor Word 5 (NPCW) fields:
@@ -69,9 +69,9 @@ typedef struct _scatter_gather_ext_t {
u32 lbaw; /* Loop-Begin Address Word */
u32 nplbaw; /* Next-Page after Loop-Begin Address Word */
u32 sgaw; /* Scatter/Gather Address Word */
-} scatter_gather_ext_t;
+};
-typedef struct _volume_control_t {
+struct dsp_volume_control {
___DSP_DUAL_16BIT_ALLOC(
rightTarg, /* Target volume for left & right channels */
leftTarg
@@ -80,10 +80,10 @@ typedef struct _volume_control_t {
rightVol, /* Current left & right channel volumes */
leftVol
)
-} volume_control_t;
+};
/* Generic stream control block (SCB) structure definition */
-typedef struct _generic_scb_t {
+struct dsp_generic_scb {
/* For streaming I/O, the DSP should never alter any words in the DMA
requestor or the scatter/gather extension. Only ad hoc DMA request
streams are free to alter the requestor (currently only occur in the
@@ -99,13 +99,13 @@ typedef struct _generic_scb_t {
/* Initialized by the host, only modified by DMA
R/O for the DSP task */
- basic_dma_req_t basic_req; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
/* Scatter/gather DMA requestor extension (5 ints)
Initialized by the host, only modified by DMA
DSP task never needs to even read these.
*/
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
/* Sublist pointer & next stream control block (SCB) link.
Initialized & modified by the host R/O for the DSP task
@@ -179,11 +179,11 @@ typedef struct _generic_scb_t {
These two 32-bit words are redefined for wavetable & 3-D voices.
*/
- volume_control_t vol_ctrl_t; /* Optional */
-} generic_scb_t;
+ struct dsp_volume_control vol_ctrl_t; /* Optional */
+};
-typedef struct _spos_control_block_t {
+struct dsp_spos_control_block {
/* WARNING: Certain items in this structure are modified by the host
Any dword that can be modified by the host, must not be
modified by the SP as the host can only do atomic dword
@@ -273,10 +273,10 @@ typedef struct _spos_control_block_t {
u32 r32_save_for_spurious_int;
u32 r32_save_for_trap;
u32 r32_save_for_HFG;
-} spos_control_block_t;
+};
/* SPB for MIX_TO_OSTREAM algorithm family */
-typedef struct _mix2_ostream_spb_t
+struct dsp_mix2_ostream_spb
{
/* 16b.16b integer.frac approximation to the
number of 3 sample triplets to output each
@@ -290,13 +290,13 @@ typedef struct _mix2_ostream_spb_t
output triplets since the start of group
*/
u32 accumOutTriplets;
-} mix2_ostream_spb_t;
+};
/* SCB for Timing master algorithm */
-typedef struct _timing_master_scb_t {
+struct dsp_timing_master_scb {
/* First 12 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -358,13 +358,13 @@ typedef struct _timing_master_scb_t {
number of samples to output each frame.
(approximation must be floor, to insure */
u32 nsamp_per_frm_q15;
-} timing_master_scb_t;
+};
/* SCB for CODEC output algorithm */
-typedef struct _codec_output_scb_t {
+struct dsp_codec_output_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -422,13 +422,13 @@ typedef struct _codec_output_scb_t {
reserved,
last_sub_ptr
)
-} codec_output_scb_t;
+};
/* SCB for CODEC input algorithm */
-typedef struct _codec_input_scb_t {
+struct dsp_codec_input_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -479,13 +479,13 @@ typedef struct _codec_input_scb_t {
)
u32 reserved2;
-} codec_input_scb_t;
+};
-typedef struct _pcm_serial_input_scb_t {
+struct dsp_pcm_serial_input_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -512,11 +512,11 @@ typedef struct _pcm_serial_input_scb_t {
)
/* Initialized by the host (host updates target volumes) */
- volume_control_t psi_vol_ctrl;
+ struct dsp_volume_control psi_vol_ctrl;
-} pcm_serial_input_scb_t;
+};
-typedef struct _src_task_scb_t {
+struct dsp_src_task_scb {
___DSP_DUAL_16BIT_ALLOC(
frames_left_in_gof,
gofs_left_in_sec
@@ -571,10 +571,10 @@ typedef struct _src_task_scb_t {
u32 phiIncr6int_26frac;
- volume_control_t src_vol_ctrl;
-} src_task_scb_t;
+ struct dsp_volume_control src_vol_ctrl;
+};
-typedef struct _decimate_by_pow2_scb_t {
+struct dsp_decimate_by_pow2_scb {
/* decimationFactor = 2, 4, or 8 (larger factors waste too much memory
when compared to cascading decimators)
*/
@@ -648,10 +648,10 @@ typedef struct _decimate_by_pow2_scb_t {
u32 dec2_reserved4;
- volume_control_t dec2_vol_ctrl; /* Not used! */
-} decimate_by_pow2_scb_t;
+ struct dsp_volume_control dec2_vol_ctrl; /* Not used! */
+};
-typedef struct _vari_decimate_scb_t {
+struct dsp_vari_decimate_scb {
___DSP_DUAL_16BIT_ALLOC(
vdec_frames_left_in_gof,
vdec_gofs_left_in_sec
@@ -711,15 +711,15 @@ typedef struct _vari_decimate_scb_t {
u32 vdec_phi_incr_6int_26frac;
- volume_control_t vdec_vol_ctrl;
-} vari_decimate_scb_t;
+ struct dsp_volume_control vdec_vol_ctrl;
+};
/* SCB for MIX_TO_OSTREAM algorithm family */
-typedef struct _mix2_ostream_scb_t {
+struct dsp_mix2_ostream_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -758,14 +758,14 @@ typedef struct _mix2_ostream_scb_t {
const_FFFF,
const_zero
)
-} mix2_ostream_scb_t;
+};
/* SCB for S16_MIX algorithm */
-typedef struct _mix_only_scb_t {
+struct dsp_mix_only_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -780,11 +780,11 @@ typedef struct _mix_only_scb_t {
u32 strm_buf_ptr; /* REQUIRED */
u32 reserved;
- volume_control_t vol_ctrl;
-} mix_only_scb_t;
+ struct dsp_volume_control vol_ctrl;
+};
/* SCB for the async. CODEC input algorithm */
-typedef struct _async_codec_input_scb_t {
+struct dsp_async_codec_input_scb {
u32 io_free2;
u32 io_current_total;
@@ -837,11 +837,11 @@ typedef struct _async_codec_input_scb_t {
)
u32 i_free;
-} async_codec_input_scb_t;
+};
/* SCB for the SP/DIF CODEC input and output */
-typedef struct _spdifiscb_t {
+struct dsp_spdifiscb {
___DSP_DUAL_16BIT_ALLOC(
status_ptr,
status_start_ptr
@@ -895,12 +895,11 @@ typedef struct _spdifiscb_t {
)
u32 free1;
-} spdifiscb_t;
+};
/* SCB for the SP/DIF CODEC input and output */
-typedef struct _spdifoscb_t {
-
+struct dsp_spdifoscb {
u32 free2;
@@ -941,11 +940,10 @@ typedef struct _spdifoscb_t {
)
u32 free1;
-} spdifoscb_t;
-
+};
-typedef struct _asynch_fg_rx_scb_t {
+struct dsp_asynch_fg_rx_scb {
___DSP_DUAL_16BIT_ALLOC(
bot_buf_mask,
buf_Mask
@@ -993,11 +991,10 @@ typedef struct _asynch_fg_rx_scb_t {
right_vol,
left_vol
)
-} asynch_fg_rx_scb_t;
-
+};
-typedef struct _asynch_fg_tx_scb_t {
+struct dsp_asynch_fg_tx_scb {
___DSP_DUAL_16BIT_ALLOC(
not_buf_mask,
buf_mask
@@ -1052,13 +1049,13 @@ typedef struct _asynch_fg_tx_scb_t {
unused_right_vol,
unused_left_vol
)
-} asynch_fg_tx_scb_t;
+};
-typedef struct _output_snoop_scb_t {
+struct dsp_output_snoop_scb {
/* First 13 dwords from generic_scb_t */
- basic_dma_req_t basic_req; /* Optional */
- scatter_gather_ext_t sg_ext; /* Optional */
+ struct dsp_basic_dma_req basic_req; /* Optional */
+ struct dsp_scatter_gather_ext sg_ext; /* Optional */
___DSP_DUAL_16BIT_ALLOC(
next_scb, /* REQUIRED */
sub_list_ptr /* REQUIRED */
@@ -1083,9 +1080,9 @@ typedef struct _output_snoop_scb_t {
reserved,
input_scb
)
-} output_snoop_scb_t;
+};
-typedef struct _spio_write_scb_t {
+struct dsp_spio_write_scb {
___DSP_DUAL_16BIT_ALLOC(
address1,
address2
@@ -1122,9 +1119,9 @@ typedef struct _spio_write_scb_t {
)
u32 unused3[5];
-} spio_write_scb_t;
+};
-typedef struct _magic_snoop_task_t {
+struct dsp_magic_snoop_task {
u32 i0;
u32 i1;
@@ -1155,11 +1152,11 @@ typedef struct _magic_snoop_task_t {
u32 i8;
- volume_control_t vdec_vol_ctrl;
-} magic_snoop_task_t;
+ struct dsp_volume_control vdec_vol_ctrl;
+};
-typedef struct _filter_scb_t {
+struct dsp_filter_scb {
___DSP_DUAL_16BIT_ALLOC(
a0_right, /* 0x00 */
a0_left
@@ -1212,5 +1209,5 @@ typedef struct _filter_scb_t {
b2_right, /* 0x0F */
b2_left
)
-} filter_scb_t;
+};
#endif /* __DSP_SCB_TYPES_H__ */
diff --git a/include/sound/cs46xx_dsp_spos.h b/include/sound/cs46xx_dsp_spos.h
index 10014cb62423..da934def31e9 100644
--- a/include/sound/cs46xx_dsp_spos.h
+++ b/include/sound/cs46xx_dsp_spos.h
@@ -65,133 +65,130 @@
#define DSP_SPDIF_STATUS_HW_ENABLED 4
#define DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED 8
-struct _dsp_module_desc_t;
-
-typedef struct _symbol_entry_t {
+struct dsp_symbol_entry {
u32 address;
char symbol_name[DSP_MAX_SYMBOL_NAME];
int symbol_type;
/* initialized by driver */
- struct _dsp_module_desc_t * module;
+ struct dsp_module_desc * module;
int deleted;
-} symbol_entry_t;
+};
-typedef struct _symbol_desc_t {
+struct dsp_symbol_desc {
int nsymbols;
- symbol_entry_t * symbols;
+ struct dsp_symbol_entry *symbols;
/* initialized by driver */
int highest_frag_index;
-} symbol_desc_t;
-
+};
-typedef struct _segment_desc_t {
+struct dsp_segment_desc {
int segment_type;
u32 offset;
u32 size;
u32 * data;
-} segment_desc_t;
+};
-typedef struct _dsp_module_desc_t {
+struct dsp_module_desc {
char * module_name;
- symbol_desc_t symbol_table;
+ struct dsp_symbol_desc symbol_table;
int nsegments;
- segment_desc_t * segments;
+ struct dsp_segment_desc * segments;
/* initialized by driver */
u32 overlay_begin_address;
u32 load_address;
int nfixups;
-} dsp_module_desc_t;
+};
-typedef struct _dsp_scb_descriptor_t {
+struct dsp_scb_descriptor {
char scb_name[DSP_MAX_SCB_NAME];
u32 address;
int index;
- struct _dsp_scb_descriptor_t * sub_list_ptr;
- struct _dsp_scb_descriptor_t * next_scb_ptr;
- struct _dsp_scb_descriptor_t * parent_scb_ptr;
+ struct dsp_scb_descriptor * sub_list_ptr;
+ struct dsp_scb_descriptor * next_scb_ptr;
+ struct dsp_scb_descriptor * parent_scb_ptr;
- symbol_entry_t * task_entry;
- symbol_entry_t * scb_symbol;
+ struct dsp_symbol_entry * task_entry;
+ struct dsp_symbol_entry * scb_symbol;
- snd_info_entry_t *proc_info;
+ struct snd_info_entry *proc_info;
int ref_count;
spinlock_t lock;
int deleted;
-} dsp_scb_descriptor_t;
+};
-typedef struct _dsp_task_descriptor_t {
+struct dsp_task_descriptor {
char task_name[DSP_MAX_TASK_NAME];
int size;
u32 address;
int index;
-} dsp_task_descriptor_t;
+};
-typedef struct _pcm_channel_descriptor_t {
+struct dsp_pcm_channel_descriptor {
int active;
int src_slot;
int pcm_slot;
u32 sample_rate;
u32 unlinked;
- dsp_scb_descriptor_t * pcm_reader_scb;
- dsp_scb_descriptor_t * src_scb;
- dsp_scb_descriptor_t * mixer_scb;
+ struct dsp_scb_descriptor * pcm_reader_scb;
+ struct dsp_scb_descriptor * src_scb;
+ struct dsp_scb_descriptor * mixer_scb;
void * private_data;
-} pcm_channel_descriptor_t;
+};
-typedef struct _dsp_spos_instance_t {
- symbol_desc_t symbol_table; /* currently availble loaded symbols in SP */
+struct dsp_spos_instance {
+ struct dsp_symbol_desc symbol_table; /* currently availble loaded symbols in SP */
int nmodules;
- dsp_module_desc_t * modules; /* modules loaded into SP */
+ struct dsp_module_desc * modules; /* modules loaded into SP */
- segment_desc_t code;
+ struct dsp_segment_desc code;
/* Main PCM playback mixer */
- dsp_scb_descriptor_t * master_mix_scb;
+ struct dsp_scb_descriptor * master_mix_scb;
u16 dac_volume_right;
u16 dac_volume_left;
/* Rear/surround PCM playback mixer */
- dsp_scb_descriptor_t * rear_mix_scb;
+ struct dsp_scb_descriptor * rear_mix_scb;
/* Center/LFE mixer */
- dsp_scb_descriptor_t * center_lfe_mix_scb;
+ struct dsp_scb_descriptor * center_lfe_mix_scb;
int npcm_channels;
int nsrc_scb;
- pcm_channel_descriptor_t pcm_channels[DSP_MAX_PCM_CHANNELS];
+ struct dsp_pcm_channel_descriptor pcm_channels[DSP_MAX_PCM_CHANNELS];
int src_scb_slots[DSP_MAX_SRC_NR];
/* cache this symbols */
- symbol_entry_t * null_algorithm; /* used by PCMreaderSCB's */
- symbol_entry_t * s16_up; /* used by SRCtaskSCB's */
+ struct dsp_symbol_entry * null_algorithm; /* used by PCMreaderSCB's */
+ struct dsp_symbol_entry * s16_up; /* used by SRCtaskSCB's */
/* proc fs */
- snd_card_t * snd_card;
- snd_info_entry_t * proc_dsp_dir;
- snd_info_entry_t * proc_sym_info_entry;
- snd_info_entry_t * proc_modules_info_entry;
- snd_info_entry_t * proc_parameter_dump_info_entry;
- snd_info_entry_t * proc_sample_dump_info_entry;
+ struct snd_card *snd_card;
+ struct snd_info_entry * proc_dsp_dir;
+ struct snd_info_entry * proc_sym_info_entry;
+ struct snd_info_entry * proc_modules_info_entry;
+ struct snd_info_entry * proc_parameter_dump_info_entry;
+ struct snd_info_entry * proc_sample_dump_info_entry;
/* SCB's descriptors */
int nscb;
int scb_highest_frag_index;
- dsp_scb_descriptor_t scbs[DSP_MAX_SCB_DESC];
- snd_info_entry_t * proc_scb_info_entry;
- dsp_scb_descriptor_t * the_null_scb;
+ struct dsp_scb_descriptor scbs[DSP_MAX_SCB_DESC];
+ struct snd_info_entry * proc_scb_info_entry;
+ struct dsp_scb_descriptor * the_null_scb;
/* Task's descriptors */
int ntask;
- dsp_task_descriptor_t tasks[DSP_MAX_TASK_DESC];
- snd_info_entry_t * proc_task_info_entry;
+ struct dsp_task_descriptor tasks[DSP_MAX_TASK_DESC];
+ struct snd_info_entry * proc_task_info_entry;
/* SPDIF status */
int spdif_status_out;
@@ -204,30 +201,30 @@ typedef struct _dsp_spos_instance_t {
unsigned int spdif_csuv_stream;
/* SPDIF input sample rate converter */
- dsp_scb_descriptor_t * spdif_in_src;
+ struct dsp_scb_descriptor * spdif_in_src;
/* SPDIF input asynch. receiver */
- dsp_scb_descriptor_t * asynch_rx_scb;
+ struct dsp_scb_descriptor * asynch_rx_scb;
/* Capture record mixer SCB */
- dsp_scb_descriptor_t * record_mixer_scb;
+ struct dsp_scb_descriptor * record_mixer_scb;
/* CODEC input SCB */
- dsp_scb_descriptor_t * codec_in_scb;
+ struct dsp_scb_descriptor * codec_in_scb;
/* reference snooper */
- dsp_scb_descriptor_t * ref_snoop_scb;
+ struct dsp_scb_descriptor * ref_snoop_scb;
/* SPDIF output PCM reference */
- dsp_scb_descriptor_t * spdif_pcm_input_scb;
+ struct dsp_scb_descriptor * spdif_pcm_input_scb;
/* asynch TX task */
- dsp_scb_descriptor_t * asynch_tx_scb;
+ struct dsp_scb_descriptor * asynch_tx_scb;
/* record sources */
- dsp_scb_descriptor_t * pcm_input;
- dsp_scb_descriptor_t * adc_input;
+ struct dsp_scb_descriptor * pcm_input;
+ struct dsp_scb_descriptor * adc_input;
int spdif_in_sample_rate;
-} dsp_spos_instance_t;
+};
#endif /* __DSP_SPOS_H__ */
diff --git a/include/sound/cs46xx_dsp_task_types.h b/include/sound/cs46xx_dsp_task_types.h
index 5dd3bf69cb03..b3076c487de6 100644
--- a/include/sound/cs46xx_dsp_task_types.h
+++ b/include/sound/cs46xx_dsp_task_types.h
@@ -71,7 +71,7 @@ Ptr____Call (c)
at the end of BG */
/* Minimal context save area for Hyper Forground */
-typedef struct _hf_save_area_t {
+struct dsp_hf_save_area {
u32 r10_save;
u32 r54_save;
u32 r98_save;
@@ -96,11 +96,11 @@ typedef struct _hf_save_area_t {
rsa2Save
)
/* saved as part of HFG context */
-} hf_save_area_t;
+};
/* Task link data structure */
-typedef struct _tree_link_t {
+struct dsp_tree_link {
___DSP_DUAL_16BIT_ALLOC(
/* Pointer to sibling task control block */
next_scb,
@@ -114,10 +114,10 @@ typedef struct _tree_link_t {
/* Pointer to local data */
this_spb
)
-} tree_link_t;
+};
-typedef struct _task_tree_data_t {
+struct dsp_task_tree_data {
___DSP_DUAL_16BIT_ALLOC(
/* Initial tock count; controls task tree execution rate */
tock_count_limit,
@@ -155,11 +155,10 @@ typedef struct _task_tree_data_t {
data_stack_base_ptr
)
-} task_tree_data_t;
+};
-
-typedef struct _interval_timer_data_t
+struct dsp_interval_timer_data
{
/* These data items have the same relative locations to those */
___DSP_DUAL_16BIT_ALLOC(
@@ -172,12 +171,12 @@ typedef struct _interval_timer_data_t
num_FG_ticks_this_interval,
num_intervals
)
-} interval_timer_data_t;
+};
/* This structure contains extra storage for the task tree
Currently, this additional data is related only to a full context save */
-typedef struct _task_tree_context_block_t {
+struct dsp_task_tree_context_block {
/* Up to 10 values are saved onto the stack. 8 for the task tree, 1 for
The access to the context switch (call or interrupt), and 1 spare that
users should never use. This last may be required by the system */
@@ -238,16 +237,16 @@ typedef struct _task_tree_context_block_t {
u32 saveaux2xaux3x;
u32 savershouthl;
u32 savershoutxmacmode;
-} task_tree_context_block_t;
+};
-typedef struct _task_tree_control_block_t {
- hf_save_area_t context;
- tree_link_t links;
- task_tree_data_t data;
- task_tree_context_block_t context_blk;
- interval_timer_data_t int_timer;
-} task_tree_control_block_t;
+struct dsp_task_tree_control_block {
+ struct dsp_hf_save_area context;
+ struct dsp_tree_link links;
+ struct dsp_task_tree_data data;
+ struct dsp_task_tree_context_block context_blk;
+ struct dsp_interval_timer_data int_timer;
+};
#endif /* __DSP_TASK_TYPES_H__ */
diff --git a/include/sound/cs8403.h b/include/sound/cs8403.h
index 0b7d216e24f1..c6c3f9f0da78 100644
--- a/include/sound/cs8403.h
+++ b/include/sound/cs8403.h
@@ -36,7 +36,7 @@
#endif
-SND_CS8403_DECL void SND_CS8403_DECODE(snd_aes_iec958_t *diga, unsigned char bits)
+SND_CS8403_DECL void SND_CS8403_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
{
if (bits & 0x01) { /* consumer */
if (!(bits & 0x02))
@@ -79,7 +79,7 @@ SND_CS8403_DECL void SND_CS8403_DECODE(snd_aes_iec958_t *diga, unsigned char bit
}
}
-SND_CS8403_DECL unsigned char SND_CS8403_ENCODE(snd_aes_iec958_t *diga)
+SND_CS8403_DECL unsigned char SND_CS8403_ENCODE(struct snd_aes_iec958 *diga)
{
unsigned char bits;
@@ -166,7 +166,7 @@ SND_CS8403_DECL unsigned char SND_CS8403_ENCODE(snd_aes_iec958_t *diga)
#endif
-SND_CS8404_DECL void SND_CS8404_DECODE(snd_aes_iec958_t *diga, unsigned char bits)
+SND_CS8404_DECL void SND_CS8404_DECODE(struct snd_aes_iec958 *diga, unsigned char bits)
{
if (bits & 0x10) { /* consumer */
if (!(bits & 0x20))
@@ -205,7 +205,7 @@ SND_CS8404_DECL void SND_CS8404_DECODE(snd_aes_iec958_t *diga, unsigned char bit
}
}
-SND_CS8404_DECL unsigned char SND_CS8404_ENCODE(snd_aes_iec958_t *diga)
+SND_CS8404_DECL unsigned char SND_CS8404_ENCODE(struct snd_aes_iec958 *diga)
{
unsigned char bits;
diff --git a/include/sound/cs8427.h b/include/sound/cs8427.h
index e725b7049a53..97fd9acf8028 100644
--- a/include/sound/cs8427.h
+++ b/include/sound/cs8427.h
@@ -186,11 +186,16 @@
#define CS8427_VERSHIFT 0
#define CS8427_VER8427A 0x71
-int snd_cs8427_create(snd_i2c_bus_t *bus, unsigned char addr,
- unsigned int reset_timeout, snd_i2c_device_t **r_cs8427);
-int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned char val);
-int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427, snd_pcm_substream_t *playback_substream, snd_pcm_substream_t *capture_substream);
-int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active);
-int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate);
+struct snd_pcm_substream;
+
+int snd_cs8427_create(struct snd_i2c_bus *bus, unsigned char addr,
+ unsigned int reset_timeout, struct snd_i2c_device **r_cs8427);
+int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
+ unsigned char val);
+int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
+ struct snd_pcm_substream *playback_substream,
+ struct snd_pcm_substream *capture_substream);
+int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active);
+int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate);
#endif /* __SOUND_CS8427_H */
diff --git a/include/sound/driver.h b/include/sound/driver.h
index 3f0416ac24d9..89c6a73f3920 100644
--- a/include/sound/driver.h
+++ b/include/sound/driver.h
@@ -28,7 +28,12 @@
#include <linux/config.h>
-#define SNDRV_CARDS 8 /* number of supported soundcards - don't change - minor numbers */
+/* number of supported soundcards */
+#ifdef CONFIG_SND_DYNAMIC_MINORS
+#define SNDRV_CARDS 32
+#else
+#define SNDRV_CARDS 8 /* don't change - minor numbers */
+#endif
#ifndef CONFIG_SND_MAJOR /* standard configuration */
#define CONFIG_SND_MAJOR 116
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 8411c7ef6f11..951e40d720d9 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -887,47 +887,45 @@
/* ------------------- STRUCTURES -------------------- */
-typedef struct _snd_emu10k1 emu10k1_t;
-typedef struct _snd_emu10k1_voice emu10k1_voice_t;
-typedef struct _snd_emu10k1_pcm emu10k1_pcm_t;
-
-typedef enum {
+enum {
EMU10K1_EFX,
EMU10K1_PCM,
EMU10K1_SYNTH,
EMU10K1_MIDI
-} emu10k1_voice_type_t;
+};
+
+struct snd_emu10k1;
-struct _snd_emu10k1_voice {
- emu10k1_t *emu;
+struct snd_emu10k1_voice {
+ struct snd_emu10k1 *emu;
int number;
unsigned int use: 1,
pcm: 1,
efx: 1,
synth: 1,
midi: 1;
- void (*interrupt)(emu10k1_t *emu, emu10k1_voice_t *pvoice);
+ void (*interrupt)(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *pvoice);
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1_pcm *epcm;
};
-typedef enum {
+enum {
PLAYBACK_EMUVOICE,
PLAYBACK_EFX,
CAPTURE_AC97ADC,
CAPTURE_AC97MIC,
CAPTURE_EFX
-} snd_emu10k1_pcm_type_t;
-
-struct _snd_emu10k1_pcm {
- emu10k1_t *emu;
- snd_emu10k1_pcm_type_t type;
- snd_pcm_substream_t *substream;
- emu10k1_voice_t *voices[NUM_EFX_PLAYBACK];
- emu10k1_voice_t *extra;
+};
+
+struct snd_emu10k1_pcm {
+ struct snd_emu10k1 *emu;
+ int type;
+ struct snd_pcm_substream *substream;
+ struct snd_emu10k1_voice *voices[NUM_EFX_PLAYBACK];
+ struct snd_emu10k1_voice *extra;
unsigned short running;
unsigned short first_ptr;
- snd_util_memblk_t *memblk;
+ struct snd_util_memblk *memblk;
unsigned int start_addr;
unsigned int ccca_start_addr;
unsigned int capture_ipr; /* interrupt acknowledge mask */
@@ -941,13 +939,13 @@ struct _snd_emu10k1_pcm {
unsigned int capture_bufsize; /* buffer size in bytes */
};
-typedef struct {
+struct snd_emu10k1_pcm_mixer {
/* mono, left, right x 8 sends (4 on emu10k1) */
unsigned char send_routing[3][8];
unsigned char send_volume[3][8];
unsigned short attn[3];
- emu10k1_pcm_t *epcm;
-} emu10k1_pcm_mixer_t;
+ struct snd_emu10k1_pcm *epcm;
+};
#define snd_emu10k1_compose_send_routing(route) \
((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16)
@@ -958,20 +956,20 @@ typedef struct {
#define snd_emu10k1_compose_audigy_fxrt2(route) \
((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24))
-typedef struct snd_emu10k1_memblk {
- snd_util_memblk_t mem;
+struct snd_emu10k1_memblk {
+ struct snd_util_memblk mem;
/* private part */
int first_page, last_page, pages, mapped_page;
unsigned int map_locked;
struct list_head mapped_link;
struct list_head mapped_order_link;
-} emu10k1_memblk_t;
+};
#define snd_emu10k1_memblk_offset(blk) (((blk)->mapped_page << PAGE_SHIFT) | ((blk)->mem.offset & (PAGE_SIZE - 1)))
#define EMU10K1_MAX_TRAM_BLOCKS_PER_CODE 16
-typedef struct {
+struct snd_emu10k1_fx8010_ctl {
struct list_head list; /* list link container */
unsigned int vcount;
unsigned int count; /* count of GPR (1..16) */
@@ -980,19 +978,19 @@ typedef struct {
unsigned int min; /* minimum range */
unsigned int max; /* maximum range */
unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
- snd_kcontrol_t *kcontrol;
-} snd_emu10k1_fx8010_ctl_t;
+ struct snd_kcontrol *kcontrol;
+};
-typedef void (snd_fx8010_irq_handler_t)(emu10k1_t *emu, void *private_data);
+typedef void (snd_fx8010_irq_handler_t)(struct snd_emu10k1 *emu, void *private_data);
-typedef struct _snd_emu10k1_fx8010_irq {
- struct _snd_emu10k1_fx8010_irq *next;
+struct snd_emu10k1_fx8010_irq {
+ struct snd_emu10k1_fx8010_irq *next;
snd_fx8010_irq_handler_t *handler;
unsigned short gpr_running;
void *private_data;
-} snd_emu10k1_fx8010_irq_t;
+};
-typedef struct {
+struct snd_emu10k1_fx8010_pcm {
unsigned int valid: 1,
opened: 1,
active: 1;
@@ -1006,13 +1004,13 @@ typedef struct {
unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */
unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */
unsigned char etram[32]; /* external TRAM address & data */
- snd_pcm_indirect_t pcm_rec;
+ struct snd_pcm_indirect pcm_rec;
unsigned int tram_pos;
unsigned int tram_shift;
- snd_emu10k1_fx8010_irq_t *irq;
-} snd_emu10k1_fx8010_pcm_t;
+ struct snd_emu10k1_fx8010_irq *irq;
+};
-typedef struct {
+struct snd_emu10k1_fx8010 {
unsigned short fxbus_mask; /* used FX buses (bitmask) */
unsigned short extin_mask; /* used external inputs (bitmask) */
unsigned short extout_mask; /* used external outputs (bitmask) */
@@ -1025,18 +1023,18 @@ typedef struct {
int gpr_count; /* count of used kcontrols */
struct list_head gpr_ctl; /* GPR controls */
struct semaphore lock;
- snd_emu10k1_fx8010_pcm_t pcm[8];
+ struct snd_emu10k1_fx8010_pcm pcm[8];
spinlock_t irq_lock;
- snd_emu10k1_fx8010_irq_t *irq_handlers;
-} snd_emu10k1_fx8010_t;
+ struct snd_emu10k1_fx8010_irq *irq_handlers;
+};
-#define emu10k1_gpr_ctl(n) list_entry(n, snd_emu10k1_fx8010_ctl_t, list)
+#define emu10k1_gpr_ctl(n) list_entry(n, struct snd_emu10k1_fx8010_ctl, list)
-typedef struct {
- struct _snd_emu10k1 *emu;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *substream_input;
- snd_rawmidi_substream_t *substream_output;
+struct snd_emu10k1_midi {
+ struct snd_emu10k1 *emu;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *substream_input;
+ struct snd_rawmidi_substream *substream_output;
unsigned int midi_mode;
spinlock_t input_lock;
spinlock_t output_lock;
@@ -1044,10 +1042,10 @@ typedef struct {
int tx_enable, rx_enable;
int port;
int ipr_tx, ipr_rx;
- void (*interrupt)(emu10k1_t *emu, unsigned int status);
-} emu10k1_midi_t;
+ void (*interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+};
-typedef struct {
+struct snd_emu_chip_details {
u32 vendor;
u32 device;
u32 subsystem;
@@ -1063,18 +1061,23 @@ typedef struct {
unsigned char spdif_bug; /* Has Spdif phasing bug */
unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */
unsigned char ecard; /* APS EEPROM */
+ unsigned char emu1212m; /* EMU 1212m card */
+ unsigned char spi_dac; /* SPI interface for DAC */
+ unsigned char i2c_adc; /* I2C interface for ADC */
const char *driver;
const char *name;
const char *id; /* for backward compatibility - can be NULL if not needed */
-} emu_chip_details_t;
+};
-struct _snd_emu10k1 {
+struct snd_emu10k1 {
int irq;
unsigned long port; /* I/O port number */
unsigned int tos_link: 1, /* tos link detected */
- rear_ac97: 1; /* rear channels are on AC'97 */
- const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */
+ rear_ac97: 1, /* rear channels are on AC'97 */
+ enable_ir: 1;
+ /* Contains profile of card capabilities */
+ const struct snd_emu_chip_details *card_capabilities;
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
unsigned int serial; /* serial number */
@@ -1088,8 +1091,8 @@ struct _snd_emu10k1 {
struct snd_dma_device p16v_dma_dev;
struct snd_dma_buffer p16v_buffer;
- snd_util_memhdr_t *memhdr; /* page allocation list */
- emu10k1_memblk_t *reserved_page; /* reserved page */
+ struct snd_util_memhdr *memhdr; /* page allocation list */
+ struct snd_emu10k1_memblk *reserved_page; /* reserved page */
struct list_head mapped_link_head;
struct list_head mapped_order_link_head;
@@ -1099,142 +1102,169 @@ struct _snd_emu10k1 {
unsigned int spdif_bits[3]; /* s/pdif out setup */
- snd_emu10k1_fx8010_t fx8010; /* FX8010 info */
+ struct snd_emu10k1_fx8010 fx8010; /* FX8010 info */
int gpr_base;
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_t *pcm_mic;
- snd_pcm_t *pcm_efx;
- snd_pcm_t *pcm_p16v;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm_mic;
+ struct snd_pcm *pcm_efx;
+ struct snd_pcm *pcm_multi;
+ struct snd_pcm *pcm_p16v;
spinlock_t synth_lock;
void *synth;
- int (*get_synth_voice)(emu10k1_t *emu);
+ int (*get_synth_voice)(struct snd_emu10k1 *emu);
spinlock_t reg_lock;
spinlock_t emu_lock;
spinlock_t voice_lock;
struct semaphore ptb_lock;
- emu10k1_voice_t voices[NUM_G];
- emu10k1_voice_t p16v_voices[4];
- emu10k1_voice_t p16v_capture_voice;
+ struct snd_emu10k1_voice voices[NUM_G];
+ struct snd_emu10k1_voice p16v_voices[4];
+ struct snd_emu10k1_voice p16v_capture_voice;
int p16v_device_offset;
u32 p16v_capture_source;
u32 p16v_capture_channel;
- emu10k1_pcm_mixer_t pcm_mixer[32];
- emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
- snd_kcontrol_t *ctl_send_routing;
- snd_kcontrol_t *ctl_send_volume;
- snd_kcontrol_t *ctl_attn;
- snd_kcontrol_t *ctl_efx_send_routing;
- snd_kcontrol_t *ctl_efx_send_volume;
- snd_kcontrol_t *ctl_efx_attn;
-
- void (*hwvol_interrupt)(emu10k1_t *emu, unsigned int status);
- void (*capture_interrupt)(emu10k1_t *emu, unsigned int status);
- void (*capture_mic_interrupt)(emu10k1_t *emu, unsigned int status);
- void (*capture_efx_interrupt)(emu10k1_t *emu, unsigned int status);
- void (*spdif_interrupt)(emu10k1_t *emu, unsigned int status);
- void (*dsp_interrupt)(emu10k1_t *emu);
-
- snd_pcm_substream_t *pcm_capture_substream;
- snd_pcm_substream_t *pcm_capture_mic_substream;
- snd_pcm_substream_t *pcm_capture_efx_substream;
- snd_pcm_substream_t *pcm_playback_efx_substream;
-
- snd_timer_t *timer;
-
- emu10k1_midi_t midi;
- emu10k1_midi_t midi2; /* for audigy */
+ struct snd_emu10k1_pcm_mixer pcm_mixer[32];
+ struct snd_emu10k1_pcm_mixer efx_pcm_mixer[NUM_EFX_PLAYBACK];
+ struct snd_kcontrol *ctl_send_routing;
+ struct snd_kcontrol *ctl_send_volume;
+ struct snd_kcontrol *ctl_attn;
+ struct snd_kcontrol *ctl_efx_send_routing;
+ struct snd_kcontrol *ctl_efx_send_volume;
+ struct snd_kcontrol *ctl_efx_attn;
+
+ void (*hwvol_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+ void (*capture_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+ void (*capture_mic_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+ void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+ void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status);
+ void (*dsp_interrupt)(struct snd_emu10k1 *emu);
+
+ struct snd_pcm_substream *pcm_capture_substream;
+ struct snd_pcm_substream *pcm_capture_mic_substream;
+ struct snd_pcm_substream *pcm_capture_efx_substream;
+ struct snd_pcm_substream *pcm_playback_efx_substream;
+
+ struct snd_timer *timer;
+
+ struct snd_emu10k1_midi midi;
+ struct snd_emu10k1_midi midi2; /* for audigy */
unsigned int efx_voices_mask[2];
unsigned int next_free_voice;
+
+#ifdef CONFIG_PM
+ unsigned int *saved_ptr;
+ unsigned int *saved_gpr;
+ unsigned int *tram_val_saved;
+ unsigned int *tram_addr_saved;
+ unsigned int *saved_icode;
+ unsigned int *p16v_saved;
+ unsigned int saved_a_iocfg, saved_hcfg;
+#endif
+
};
-int snd_emu10k1_create(snd_card_t * card,
+int snd_emu10k1_create(struct snd_card *card,
struct pci_dev *pci,
unsigned short extin_mask,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
- emu10k1_t ** remu);
-
-int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
-int snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
-int snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
-int snd_p16v_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
-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 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);
+ struct snd_emu10k1 ** remu);
+
+int snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_p16v_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_p16v_free(struct snd_emu10k1 * emu);
+int snd_p16v_mixer(struct snd_emu10k1 * emu);
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_mixer(struct snd_emu10k1 * emu, int pcm_device, int multi_device);
+int snd_emu10k1_timer(struct snd_emu10k1 * emu, int device);
+int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep);
irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-/* initialization */
-void snd_emu10k1_voice_init(emu10k1_t * emu, int voice);
-int snd_emu10k1_init_efx(emu10k1_t *emu);
-void snd_emu10k1_free_efx(emu10k1_t *emu);
-int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size);
+void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int voice);
+int snd_emu10k1_init_efx(struct snd_emu10k1 *emu);
+void snd_emu10k1_free_efx(struct snd_emu10k1 *emu);
+int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size);
+int snd_emu10k1_done(struct snd_emu10k1 * emu);
/* I/O functions */
-unsigned int snd_emu10k1_ptr_read(emu10k1_t * emu, unsigned int reg, unsigned int chn);
-void snd_emu10k1_ptr_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, unsigned int data);
-unsigned int snd_emu10k1_ptr20_read(emu10k1_t * emu, unsigned int reg, unsigned int chn);
-void snd_emu10k1_ptr20_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, unsigned int data);
-unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc);
-void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb);
-void snd_emu10k1_intr_disable(emu10k1_t *emu, unsigned int intrenb);
-void snd_emu10k1_voice_intr_enable(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_intr_disable(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_intr_ack(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_voice_clear_loop_stop(emu10k1_t *emu, unsigned int voicenum);
-void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait);
-static inline unsigned int snd_emu10k1_wc(emu10k1_t *emu) { return (inl(emu->port + WC) >> 6) & 0xfffff; }
-unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg);
-void snd_emu10k1_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short data);
+unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
+void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
+unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
+void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
+int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
+unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
+void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
+void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
+void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum);
+void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait);
+static inline unsigned int snd_emu10k1_wc(struct snd_emu10k1 *emu) { return (inl(emu->port + WC) >> 6) & 0xfffff; }
+unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg);
+void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data);
unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate);
+#ifdef CONFIG_PM
+void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu);
+void snd_emu10k1_resume_init(struct snd_emu10k1 *emu);
+void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu);
+int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu);
+void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu);
+void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu);
+void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu);
+int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu);
+void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu);
+void snd_p16v_suspend(struct snd_emu10k1 *emu);
+void snd_p16v_resume(struct snd_emu10k1 *emu);
+#endif
+
/* memory allocation */
-snd_util_memblk_t *snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream);
-int snd_emu10k1_free_pages(emu10k1_t *emu, snd_util_memblk_t *blk);
-snd_util_memblk_t *snd_emu10k1_synth_alloc(emu10k1_t *emu, unsigned int size);
-int snd_emu10k1_synth_free(emu10k1_t *emu, snd_util_memblk_t *blk);
-int snd_emu10k1_synth_bzero(emu10k1_t *emu, snd_util_memblk_t *blk, int offset, int size);
-int snd_emu10k1_synth_copy_from_user(emu10k1_t *emu, snd_util_memblk_t *blk, int offset, const char __user *data, int size);
-int snd_emu10k1_memblk_map(emu10k1_t *emu, emu10k1_memblk_t *blk);
+struct snd_util_memblk *snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream);
+int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
+struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size);
+int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk);
+int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size);
+int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, const char __user *data, int size);
+int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk);
/* voice allocation */
-int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice);
-int snd_emu10k1_voice_free(emu10k1_t *emu, emu10k1_voice_t *pvoice);
+int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int pair, struct snd_emu10k1_voice **rvoice);
+int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *pvoice);
/* MIDI uart */
-int snd_emu10k1_midi(emu10k1_t * emu);
-int snd_emu10k1_audigy_midi(emu10k1_t * emu);
+int snd_emu10k1_midi(struct snd_emu10k1 * emu);
+int snd_emu10k1_audigy_midi(struct snd_emu10k1 * emu);
/* proc interface */
-int snd_emu10k1_proc_init(emu10k1_t * emu);
+int snd_emu10k1_proc_init(struct snd_emu10k1 * emu);
/* fx8010 irq handler */
-int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
snd_fx8010_irq_handler_t *handler,
unsigned char gpr_running,
void *private_data,
- snd_emu10k1_fx8010_irq_t **r_irq);
-int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
- snd_emu10k1_fx8010_irq_t *irq);
+ struct snd_emu10k1_fx8010_irq **r_irq);
+int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_irq *irq);
#endif /* __KERNEL__ */
@@ -1469,14 +1499,14 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
#define TANKMEMADDRREG_READ 0x00100000 /* Read from tank memory */
#endif
-typedef struct {
+struct snd_emu10k1_fx8010_info {
unsigned int internal_tram_size; /* in samples */
unsigned int external_tram_size; /* in samples */
char fxbus_names[16][32]; /* names of FXBUSes */
char extin_names[16][32]; /* names of external inputs */
char extout_names[32][32]; /* names of external outputs */
unsigned int gpr_controls; /* count of GPR controls */
-} emu10k1_fx8010_info_t;
+};
#define EMU10K1_GPR_TRANSLATION_NONE 0
#define EMU10K1_GPR_TRANSLATION_TABLE100 1
@@ -1484,8 +1514,8 @@ typedef struct {
#define EMU10K1_GPR_TRANSLATION_TREBLE 3
#define EMU10K1_GPR_TRANSLATION_ONOFF 4
-typedef struct {
- snd_ctl_elem_id_t id; /* full control ID definition */
+struct snd_emu10k1_fx8010_control_gpr {
+ struct snd_ctl_elem_id id; /* full control ID definition */
unsigned int vcount; /* visible count */
unsigned int count; /* count of GPR (1..16) */
unsigned short gpr[32]; /* GPR number(s) */
@@ -1493,23 +1523,23 @@ typedef struct {
unsigned int min; /* minimum range */
unsigned int max; /* maximum range */
unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
-} emu10k1_fx8010_control_gpr_t;
+};
-typedef struct {
+struct snd_emu10k1_fx8010_code {
char name[128];
DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
u_int32_t __user *gpr_map; /* initializers */
unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
- emu10k1_fx8010_control_gpr_t __user *gpr_add_controls; /* GPR controls to add/replace */
+ struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
unsigned int gpr_del_control_count; /* count of GPR controls to remove */
- snd_ctl_elem_id_t __user *gpr_del_controls; /* IDs of GPR controls to remove */
+ struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
unsigned int gpr_list_control_count; /* count of GPR controls to list */
unsigned int gpr_list_control_total; /* total count of GPR controls */
- emu10k1_fx8010_control_gpr_t __user *gpr_list_controls; /* listed GPR controls */
+ struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
u_int32_t __user *tram_data_map; /* data initializers */
@@ -1517,16 +1547,16 @@ typedef struct {
DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
u_int32_t __user *code; /* one instruction - 64 bits */
-} emu10k1_fx8010_code_t;
+};
-typedef struct {
+struct snd_emu10k1_fx8010_tram {
unsigned int address; /* 31.bit == 1 -> external TRAM */
unsigned int size; /* size in samples (4 bytes) */
unsigned int *samples; /* pointer to samples (20-bit) */
/* NULL->clear memory */
-} emu10k1_fx8010_tram_t;
+};
-typedef struct {
+struct snd_emu10k1_fx8010_pcm_rec {
unsigned int substream; /* substream number */
unsigned int res1; /* reserved */
unsigned int channels; /* 16-bit channels count, zero = remove this substream */
@@ -1541,20 +1571,27 @@ typedef struct {
unsigned char pad; /* reserved */
unsigned char etram[32]; /* external TRAM address & data (one per channel) */
unsigned int res2; /* reserved */
-} emu10k1_fx8010_pcm_t;
+};
-#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, emu10k1_fx8010_info_t)
-#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, emu10k1_fx8010_code_t)
-#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, emu10k1_fx8010_code_t)
+#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
+#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
+#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int)
-#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, emu10k1_fx8010_tram_t)
-#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, emu10k1_fx8010_tram_t)
-#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, emu10k1_fx8010_pcm_t)
-#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, emu10k1_fx8010_pcm_t)
+#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
+#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
+#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int)
#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int)
+/* typedefs for compatibility to user-space */
+typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
+typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
+typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
+typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
+typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
+
#endif /* __SOUND_EMU10K1_H */
diff --git a/include/sound/emu10k1_synth.h b/include/sound/emu10k1_synth.h
index df0df1d09552..6ef61c420935 100644
--- a/include/sound/emu10k1_synth.h
+++ b/include/sound/emu10k1_synth.h
@@ -27,12 +27,12 @@
#define SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH "emu10k1-synth"
/* argument for snd_seq_device_new */
-typedef struct snd_emu10k1_synth_arg {
- emu10k1_t *hwptr; /* chip */
+struct snd_emu10k1_synth_arg {
+ struct snd_emu10k1 *hwptr; /* chip */
int index; /* sequencer client index */
int seq_ports; /* number of sequencer ports to be created */
int max_voices; /* maximum number of voices for wavetable */
-} snd_emu10k1_synth_arg_t;
+};
#define EMU10K1_MAX_MEMSIZE (32 * 1024 * 1024) /* 32MB */
diff --git a/include/sound/emu8000.h b/include/sound/emu8000.h
index 4362c54e09d0..c8f66bde6d95 100644
--- a/include/sound/emu8000.h
+++ b/include/sound/emu8000.h
@@ -56,9 +56,9 @@ enum {
* some of the channels may be used for other things so max_channels is
* the number in use for wave voices.
*/
-typedef struct snd_emu8000 {
+struct snd_emu8000 {
- snd_emux_t *emu;
+ struct snd_emux *emu;
int index; /* sequencer client index */
int seq_ports; /* number of sequencer ports */
@@ -77,44 +77,45 @@ typedef struct snd_emu8000 {
int dram_checked;
- snd_card_t *card; /* The card that this belongs to */
+ struct snd_card *card; /* The card that this belongs to */
int chorus_mode;
int reverb_mode;
int bass_level;
int treble_level;
- snd_util_memhdr_t *memhdr;
+ struct snd_util_memhdr *memhdr;
spinlock_t control_lock;
- snd_kcontrol_t *controls[EMU8000_NUM_CONTROLS];
+ struct snd_kcontrol *controls[EMU8000_NUM_CONTROLS];
- snd_pcm_t *pcm; /* pcm on emu8000 wavetable */
+ struct snd_pcm *pcm; /* pcm on emu8000 wavetable */
-} emu8000_t;
+};
/* sequencer device id */
#define SNDRV_SEQ_DEV_ID_EMU8000 "emu8000-synth"
/* exported functions */
-int snd_emu8000_new(snd_card_t *card, int device, long port, int seq_ports, snd_seq_device_t **ret);
-void snd_emu8000_poke(emu8000_t *emu, unsigned int port, unsigned int reg,
+int snd_emu8000_new(struct snd_card *card, int device, long port, int seq_ports,
+ struct snd_seq_device **ret);
+void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg,
unsigned int val);
-unsigned short snd_emu8000_peek(emu8000_t *emu, unsigned int port,
+unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port,
unsigned int reg);
-void snd_emu8000_poke_dw(emu8000_t *emu, unsigned int port, unsigned int reg,
+void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg,
unsigned int val);
-unsigned int snd_emu8000_peek_dw(emu8000_t *emu, unsigned int port,
+unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port,
unsigned int reg);
-void snd_emu8000_dma_chan(emu8000_t *emu, int ch, int mode);
+void snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode);
-void snd_emu8000_init_fm(emu8000_t *emu);
+void snd_emu8000_init_fm(struct snd_emu8000 *emu);
-void snd_emu8000_update_chorus_mode(emu8000_t *emu);
-void snd_emu8000_update_reverb_mode(emu8000_t *emu);
-void snd_emu8000_update_equalizer(emu8000_t *emu);
-int snd_emu8000_load_chorus_fx(emu8000_t *emu, int mode, const void __user *buf, long len);
-int snd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, long len);
+void snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu);
+void snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu);
+void snd_emu8000_update_equalizer(struct snd_emu8000 *emu);
+int snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len);
+int snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len);
#endif /* __SOUND_EMU8000_H */
diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h
index c6970aac9bdc..b2d6b2acc7c7 100644
--- a/include/sound/emux_synth.h
+++ b/include/sound/emux_synth.h
@@ -36,39 +36,40 @@
*/
#define SNDRV_EMUX_USE_RAW_EFFECT
-
-/*
- * typedefs
- */
-typedef struct snd_emux_effect_table snd_emux_effect_table_t;
-typedef struct snd_emux_port snd_emux_port_t;
-typedef struct snd_emux_voice snd_emux_voice_t;
-typedef struct snd_emux snd_emux_t;
-
+struct snd_emux;
+struct snd_emux_port;
+struct snd_emux_voice;
+struct snd_emux_effect_table;
/*
* operators
*/
-typedef struct snd_emux_operators {
+struct snd_emux_operators {
struct module *owner;
- snd_emux_voice_t *(*get_voice)(snd_emux_t *emu, snd_emux_port_t *port);
- int (*prepare)(snd_emux_voice_t *vp);
- void (*trigger)(snd_emux_voice_t *vp);
- void (*release)(snd_emux_voice_t *vp);
- void (*update)(snd_emux_voice_t *vp, int update);
- void (*terminate)(snd_emux_voice_t *vp);
- void (*free_voice)(snd_emux_voice_t *vp);
- void (*reset)(snd_emux_t *emu, int ch);
- /* the first parameters are snd_emux_t */
- int (*sample_new)(snd_emux_t *emu, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
- int (*sample_free)(snd_emux_t *emu, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
- void (*sample_reset)(snd_emux_t *emu);
- int (*load_fx)(snd_emux_t *emu, int type, int arg, const void __user *data, long count);
- void (*sysex)(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
+ struct snd_emux_voice *(*get_voice)(struct snd_emux *emu,
+ struct snd_emux_port *port);
+ int (*prepare)(struct snd_emux_voice *vp);
+ void (*trigger)(struct snd_emux_voice *vp);
+ void (*release)(struct snd_emux_voice *vp);
+ void (*update)(struct snd_emux_voice *vp, int update);
+ void (*terminate)(struct snd_emux_voice *vp);
+ void (*free_voice)(struct snd_emux_voice *vp);
+ void (*reset)(struct snd_emux *emu, int ch);
+ /* the first parameters are struct snd_emux */
+ int (*sample_new)(struct snd_emux *emu, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *data, long count);
+ int (*sample_free)(struct snd_emux *emu, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr);
+ void (*sample_reset)(struct snd_emux *emu);
+ int (*load_fx)(struct snd_emux *emu, int type, int arg,
+ const void __user *data, long count);
+ void (*sysex)(struct snd_emux *emu, char *buf, int len, int parsed,
+ struct snd_midi_channel_set *chset);
#ifdef CONFIG_SND_SEQUENCER_OSS
- int (*oss_ioctl)(snd_emux_t *emu, int cmd, int p1, int p2);
+ int (*oss_ioctl)(struct snd_emux *emu, int cmd, int p1, int p2);
#endif
-} snd_emux_operators_t;
+};
/*
@@ -90,46 +91,46 @@ typedef struct snd_emux_operators {
*/
struct snd_emux {
- snd_card_t *card; /* assigned card */
+ struct snd_card *card; /* assigned card */
/* following should be initialized before registration */
int max_voices; /* Number of voices */
int mem_size; /* memory size (in byte) */
int num_ports; /* number of ports to be created */
int pitch_shift; /* pitch shift value (for Emu10k1) */
- snd_emux_operators_t ops; /* operators */
+ struct snd_emux_operators ops; /* operators */
void *hw; /* hardware */
unsigned long flags; /* other conditions */
int midi_ports; /* number of virtual midi devices */
int midi_devidx; /* device offset of virtual midi */
unsigned int linear_panning: 1; /* panning is linear (sbawe = 1, emu10k1 = 0) */
int hwdep_idx; /* hwdep device index */
- snd_hwdep_t *hwdep; /* hwdep device */
+ struct snd_hwdep *hwdep; /* hwdep device */
/* private */
int num_voices; /* current number of voices */
- snd_sf_list_t *sflist; /* root of SoundFont list */
- snd_emux_voice_t *voices; /* Voices (EMU 'channel') */
+ struct snd_sf_list *sflist; /* root of SoundFont list */
+ struct snd_emux_voice *voices; /* Voices (EMU 'channel') */
int use_time; /* allocation counter */
spinlock_t voice_lock; /* Lock for voice access */
struct semaphore register_mutex;
int client; /* For the sequencer client */
int ports[SNDRV_EMUX_MAX_PORTS]; /* The ports for this device */
- snd_emux_port_t *portptrs[SNDRV_EMUX_MAX_PORTS];
+ struct snd_emux_port *portptrs[SNDRV_EMUX_MAX_PORTS];
int used; /* use counter */
char *name; /* name of the device (internal) */
- snd_rawmidi_t **vmidi;
+ struct snd_rawmidi **vmidi;
struct timer_list tlist; /* for pending note-offs */
int timer_active;
- snd_util_memhdr_t *memhdr; /* memory chunk information */
+ struct snd_util_memhdr *memhdr; /* memory chunk information */
#ifdef CONFIG_PROC_FS
- snd_info_entry_t *proc;
+ struct snd_info_entry *proc;
#endif
#ifdef CONFIG_SND_SEQUENCER_OSS
- snd_seq_device_t *oss_synth;
+ struct snd_seq_device *oss_synth;
#endif
};
@@ -139,18 +140,18 @@ struct snd_emux {
*/
struct snd_emux_port {
- snd_midi_channel_set_t chset;
- snd_emux_t *emu;
+ struct snd_midi_channel_set chset;
+ struct snd_emux *emu;
char port_mode; /* operation mode */
int volume_atten; /* emuX raw attenuation */
unsigned long drum_flags; /* drum bitmaps */
int ctrls[EMUX_MD_END]; /* control parameters */
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
- snd_emux_effect_table_t *effect;
+ struct snd_emux_effect_table *effect;
#endif
#ifdef CONFIG_SND_SEQUENCER_OSS
- snd_seq_oss_arg_t *oss_arg;
+ struct snd_seq_oss_arg *oss_arg;
#endif
};
@@ -179,16 +180,16 @@ struct snd_emux_voice {
unsigned char key;
unsigned char velocity; /* Velocity of current note */
- snd_sf_zone_t *zone; /* Zone assigned to this note */
+ struct snd_sf_zone *zone; /* Zone assigned to this note */
void *block; /* sample block pointer (optional) */
- snd_midi_channel_t *chan; /* Midi channel for this note */
- snd_emux_port_t *port; /* associated port */
- snd_emux_t *emu; /* assigned root info */
- void *hw; /* hardware pointer (emu8000_t or emu10k1_t) */
+ struct snd_midi_channel *chan; /* Midi channel for this note */
+ struct snd_emux_port *port; /* associated port */
+ struct snd_emux *emu; /* assigned root info */
+ void *hw; /* hardware pointer (emu8000 or emu10k1) */
unsigned long ontime; /* jiffies at note triggered */
/* Emu8k/Emu10k1 registers */
- soundfont_voice_info_t reg;
+ struct soundfont_voice_info reg;
/* additional registers */
int avol; /* volume attenuation */
@@ -229,15 +230,15 @@ struct snd_emux_effect_table {
/*
* prototypes - interface to Emu10k1 and Emu8k routines
*/
-int snd_emux_new(snd_emux_t **remu);
-int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name);
-int snd_emux_free(snd_emux_t *emu);
+int snd_emux_new(struct snd_emux **remu);
+int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name);
+int snd_emux_free(struct snd_emux *emu);
/*
* exported functions
*/
-void snd_emux_terminate_all(snd_emux_t *emu);
-void snd_emux_lock_voice(snd_emux_t *emu, int voice);
-void snd_emux_unlock_voice(snd_emux_t *emu, int voice);
+void snd_emux_terminate_all(struct snd_emux *emu);
+void snd_emux_lock_voice(struct snd_emux *emu, int voice);
+void snd_emux_unlock_voice(struct snd_emux *emu, int voice);
#endif /* __SOUND_EMUX_SYNTH_H */
diff --git a/include/sound/es1688.h b/include/sound/es1688.h
index 604f495bc8b1..fc1c47dae3da 100644
--- a/include/sound/es1688.h
+++ b/include/sound/es1688.h
@@ -30,7 +30,7 @@
#define ES1688_HW_688 0x0001
#define ES1688_HW_1688 0x0002
-struct _snd_es1688 {
+struct snd_es1688 {
unsigned long port; /* port of ESS chip */
struct resource *res_port;
unsigned long mpu_port; /* MPU-401 port of ESS chip */
@@ -44,17 +44,15 @@ struct _snd_es1688 {
unsigned char pad;
unsigned int dma_size;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
spinlock_t reg_lock;
spinlock_t mixer_lock;
};
-typedef struct _snd_es1688 es1688_t;
-
/* I/O ports */
#define ES1688P(codec, x) ((codec)->port + e_s_s_ESS1688##x)
@@ -107,17 +105,17 @@ typedef struct _snd_es1688 es1688_t;
*/
-void snd_es1688_mixer_write(es1688_t *chip, unsigned char reg, unsigned char data);
+void snd_es1688_mixer_write(struct snd_es1688 *chip, unsigned char reg, unsigned char data);
-int snd_es1688_create(snd_card_t * card,
+int snd_es1688_create(struct snd_card *card,
unsigned long port,
unsigned long mpu_port,
int irq,
int mpu_irq,
int dma8,
unsigned short hardware,
- es1688_t ** rchip);
-int snd_es1688_pcm(es1688_t *chip, int device, snd_pcm_t ** rpcm);
-int snd_es1688_mixer(es1688_t *chip);
+ struct snd_es1688 ** rchip);
+int snd_es1688_pcm(struct snd_es1688 *chip, int device, struct snd_pcm ** rpcm);
+int snd_es1688_mixer(struct snd_es1688 *chip);
#endif /* __SOUND_ES1688_H */
diff --git a/include/sound/gus.h b/include/sound/gus.h
index 7000d9d9199d..63da50fae773 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -49,32 +49,32 @@
#define SNDRV_g_u_s_IRQSTAT (0x226-0x220)
#define SNDRV_g_u_s_TIMERCNTRL (0x228-0x220)
#define SNDRV_g_u_s_TIMERDATA (0x229-0x220)
-#define SNDRV_g_u_s_DRAM (0x327-0x220)
+#define SNDRV_g_u_s_DRAM (0x327-0x220)
#define SNDRV_g_u_s_MIXCNTRLREG (0x220-0x220)
#define SNDRV_g_u_s_IRQDMACNTRLREG (0x22b-0x220)
#define SNDRV_g_u_s_REGCNTRLS (0x22f-0x220)
-#define SNDRV_g_u_s_BOARDVERSION (0x726-0x220)
-#define SNDRV_g_u_s_MIXCNTRLPORT (0x726-0x220)
-#define SNDRV_g_u_s_IVER (0x325-0x220)
+#define SNDRV_g_u_s_BOARDVERSION (0x726-0x220)
+#define SNDRV_g_u_s_MIXCNTRLPORT (0x726-0x220)
+#define SNDRV_g_u_s_IVER (0x325-0x220)
#define SNDRV_g_u_s_MIXDATAPORT (0x326-0x220)
-#define SNDRV_g_u_s_MAXCNTRLPORT (0x326-0x220)
+#define SNDRV_g_u_s_MAXCNTRLPORT (0x326-0x220)
/* GF1 registers */
/* global registers */
#define SNDRV_GF1_GB_ACTIVE_VOICES 0x0e
#define SNDRV_GF1_GB_VOICES_IRQ 0x0f
-#define SNDRV_GF1_GB_GLOBAL_MODE 0x19
+#define SNDRV_GF1_GB_GLOBAL_MODE 0x19
#define SNDRV_GF1_GW_LFO_BASE 0x1a
#define SNDRV_GF1_GB_VOICES_IRQ_READ 0x1f
#define SNDRV_GF1_GB_DRAM_DMA_CONTROL 0x41
-#define SNDRV_GF1_GW_DRAM_DMA_LOW 0x42
-#define SNDRV_GF1_GW_DRAM_IO_LOW 0x43
-#define SNDRV_GF1_GB_DRAM_IO_HIGH 0x44
+#define SNDRV_GF1_GW_DRAM_DMA_LOW 0x42
+#define SNDRV_GF1_GW_DRAM_IO_LOW 0x43
+#define SNDRV_GF1_GB_DRAM_IO_HIGH 0x44
#define SNDRV_GF1_GB_SOUND_BLASTER_CONTROL 0x45
#define SNDRV_GF1_GB_ADLIB_TIMER_1 0x46
#define SNDRV_GF1_GB_ADLIB_TIMER_2 0x47
-#define SNDRV_GF1_GB_RECORD_RATE 0x48
+#define SNDRV_GF1_GB_RECORD_RATE 0x48
#define SNDRV_GF1_GB_REC_DMA_CONTROL 0x49
#define SNDRV_GF1_GB_JOYSTICK_DAC_LEVEL 0x4b
#define SNDRV_GF1_GB_RESET 0x4c
@@ -83,7 +83,7 @@
#define SNDRV_GF1_GW_MEMORY_CONFIG 0x52
#define SNDRV_GF1_GB_MEMORY_CONTROL 0x53
#define SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR 0x54
-#define SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR 0x55
+#define SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR 0x55
#define SNDRV_GF1_GW_FIFO_SIZE 0x56
#define SNDRV_GF1_GW_INTERLEAVE 0x57
#define SNDRV_GF1_GB_COMPATIBILITY 0x59
@@ -100,39 +100,39 @@
#define SNDRV_GF1_VA_START SNDRV_GF1_VW_START_HIGH
#define SNDRV_GF1_VW_END_HIGH 0x04
#define SNDRV_GF1_VW_END_LOW 0x05
-#define SNDRV_GF1_VA_END SNDRV_GF1_VW_END_HIGH
-#define SNDRV_GF1_VB_VOLUME_RATE 0x06
-#define SNDRV_GF1_VB_VOLUME_START 0x07
+#define SNDRV_GF1_VA_END SNDRV_GF1_VW_END_HIGH
+#define SNDRV_GF1_VB_VOLUME_RATE 0x06
+#define SNDRV_GF1_VB_VOLUME_START 0x07
#define SNDRV_GF1_VB_VOLUME_END 0x08
#define SNDRV_GF1_VW_VOLUME 0x09
-#define SNDRV_GF1_VW_CURRENT_HIGH 0x0a
-#define SNDRV_GF1_VW_CURRENT_LOW 0x0b
+#define SNDRV_GF1_VW_CURRENT_HIGH 0x0a
+#define SNDRV_GF1_VW_CURRENT_LOW 0x0b
#define SNDRV_GF1_VA_CURRENT SNDRV_GF1_VW_CURRENT_HIGH
-#define SNDRV_GF1_VB_PAN 0x0c
-#define SNDRV_GF1_VW_OFFSET_RIGHT 0x0c
+#define SNDRV_GF1_VB_PAN 0x0c
+#define SNDRV_GF1_VW_OFFSET_RIGHT 0x0c
#define SNDRV_GF1_VB_VOLUME_CONTROL 0x0d
#define SNDRV_GF1_VB_UPPER_ADDRESS 0x10
-#define SNDRV_GF1_VW_EFFECT_HIGH 0x11
+#define SNDRV_GF1_VW_EFFECT_HIGH 0x11
#define SNDRV_GF1_VW_EFFECT_LOW 0x12
#define SNDRV_GF1_VA_EFFECT SNDRV_GF1_VW_EFFECT_HIGH
-#define SNDRV_GF1_VW_OFFSET_LEFT 0x13
-#define SNDRV_GF1_VB_ACCUMULATOR 0x14
-#define SNDRV_GF1_VB_MODE 0x15
+#define SNDRV_GF1_VW_OFFSET_LEFT 0x13
+#define SNDRV_GF1_VB_ACCUMULATOR 0x14
+#define SNDRV_GF1_VB_MODE 0x15
#define SNDRV_GF1_VW_EFFECT_VOLUME 0x16
#define SNDRV_GF1_VB_FREQUENCY_LFO 0x17
#define SNDRV_GF1_VB_VOLUME_LFO 0x18
#define SNDRV_GF1_VW_OFFSET_RIGHT_FINAL 0x1b
#define SNDRV_GF1_VW_OFFSET_LEFT_FINAL 0x1c
-#define SNDRV_GF1_VW_EFFECT_VOLUME_FINAL 0x1d
+#define SNDRV_GF1_VW_EFFECT_VOLUME_FINAL 0x1d
/* ICS registers */
#define SNDRV_ICS_MIC_DEV 0
-#define SNDRV_ICS_LINE_DEV 1
+#define SNDRV_ICS_LINE_DEV 1
#define SNDRV_ICS_CD_DEV 2
#define SNDRV_ICS_GF1_DEV 3
-#define SNDRV_ICS_NONE_DEV 4
-#define SNDRV_ICS_MASTER_DEV 5
+#define SNDRV_ICS_NONE_DEV 4
+#define SNDRV_ICS_MASTER_DEV 5
/* LFO */
@@ -143,7 +143,7 @@
#define SNDRV_GF1_DMA_UNSIGNED 0x80
#define SNDRV_GF1_DMA_16BIT 0x40
-#define SNDRV_GF1_DMA_IRQ 0x20
+#define SNDRV_GF1_DMA_IRQ 0x20
#define SNDRV_GF1_DMA_WIDTH16 0x04
#define SNDRV_GF1_DMA_READ 0x02 /* read from GUS's DRAM */
#define SNDRV_GF1_DMA_ENABLE 0x01
@@ -159,7 +159,7 @@
/* defines for memory manager */
-#define SNDRV_GF1_MEM_BLOCK_16BIT 0x0001
+#define SNDRV_GF1_MEM_BLOCK_16BIT 0x0001
#define SNDRV_GF1_MEM_OWNER_DRIVER 0x0001
#define SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE 0x0002
@@ -169,9 +169,9 @@
/* constants for interrupt handlers */
#define SNDRV_GF1_HANDLER_MIDI_OUT 0x00010000
-#define SNDRV_GF1_HANDLER_MIDI_IN 0x00020000
-#define SNDRV_GF1_HANDLER_TIMER1 0x00040000
-#define SNDRV_GF1_HANDLER_TIMER2 0x00080000
+#define SNDRV_GF1_HANDLER_MIDI_IN 0x00020000
+#define SNDRV_GF1_HANDLER_TIMER1 0x00040000
+#define SNDRV_GF1_HANDLER_TIMER2 0x00080000
#define SNDRV_GF1_HANDLER_VOICE 0x00100000
#define SNDRV_GF1_HANDLER_DMA_WRITE 0x00200000
#define SNDRV_GF1_HANDLER_DMA_READ 0x00400000
@@ -183,17 +183,16 @@
/* --- */
-struct _snd_gus_card;
-typedef struct _snd_gus_card snd_gus_card_t;
+struct snd_gus_card;
/* GF1 specific structure */
-typedef struct _snd_gf1_bank_info {
+struct snd_gf1_bank_info {
unsigned int address;
unsigned int size;
-} snd_gf1_bank_info_t;
+};
-typedef struct _snd_gf1_mem_block {
+struct snd_gf1_mem_block {
unsigned short flags; /* flags - SNDRV_GF1_MEM_BLOCK_XXXX */
unsigned short owner; /* owner - SNDRV_GF1_MEM_OWNER_XXXX */
unsigned int share; /* share count */
@@ -201,68 +200,68 @@ typedef struct _snd_gf1_mem_block {
unsigned int ptr;
unsigned int size;
char *name;
- struct _snd_gf1_mem_block *next;
- struct _snd_gf1_mem_block *prev;
-} snd_gf1_mem_block_t;
-
-typedef struct _snd_gf1_mem {
- snd_gf1_bank_info_t banks_8[4];
- snd_gf1_bank_info_t banks_16[4];
- snd_gf1_mem_block_t *first;
- snd_gf1_mem_block_t *last;
+ struct snd_gf1_mem_block *next;
+ struct snd_gf1_mem_block *prev;
+};
+
+struct snd_gf1_mem {
+ struct snd_gf1_bank_info banks_8[4];
+ struct snd_gf1_bank_info banks_16[4];
+ struct snd_gf1_mem_block *first;
+ struct snd_gf1_mem_block *last;
struct semaphore memory_mutex;
-} snd_gf1_mem_t;
+};
-typedef struct snd_gf1_dma_block {
+struct snd_gf1_dma_block {
void *buffer; /* buffer in computer's RAM */
unsigned long buf_addr; /* buffer address */
unsigned int addr; /* address in onboard memory */
unsigned int count; /* count in bytes */
unsigned int cmd; /* DMA command (format) */
- void (*ack)(snd_gus_card_t * gus, void *private_data);
+ void (*ack)(struct snd_gus_card * gus, void *private_data);
void *private_data;
struct snd_gf1_dma_block *next;
-} snd_gf1_dma_block_t;
+};
-typedef struct {
- snd_midi_channel_set_t * chset;
- snd_gus_card_t * gus;
+struct snd_gus_port {
+ struct snd_midi_channel_set * chset;
+ struct snd_gus_card * gus;
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
unsigned int midi_has_voices: 1;
-} snd_gus_port_t;
+};
-typedef struct _snd_gus_voice snd_gus_voice_t;
+struct snd_gus_voice;
-typedef struct {
- void (*sample_start)(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position);
- void (*sample_stop)(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode);
- void (*sample_freq)(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq);
- void (*sample_volume)(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume);
- void (*sample_loop)(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop);
- void (*sample_pos)(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_position_t position);
- void (*sample_private1)(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data);
-} snd_gus_sample_ops_t;
+struct snd_gus_sample_ops {
+ void (*sample_start)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position);
+ void (*sample_stop)(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode);
+ void (*sample_freq)(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq);
+ void (*sample_volume)(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume);
+ void (*sample_loop)(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop);
+ void (*sample_pos)(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position);
+ void (*sample_private1)(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data);
+};
-#define SNDRV_GF1_VOICE_TYPE_PCM 0
+#define SNDRV_GF1_VOICE_TYPE_PCM 0
#define SNDRV_GF1_VOICE_TYPE_SYNTH 1
-#define SNDRV_GF1_VOICE_TYPE_MIDI 2
+#define SNDRV_GF1_VOICE_TYPE_MIDI 2
#define SNDRV_GF1_VFLG_RUNNING (1<<0)
#define SNDRV_GF1_VFLG_EFFECT_TIMER1 (1<<1)
#define SNDRV_GF1_VFLG_PAN (1<<2)
-typedef enum {
+enum snd_gus_volume_state {
VENV_BEFORE,
VENV_ATTACK,
VENV_SUSTAIN,
VENV_RELEASE,
VENV_DONE,
VENV_VOLUME
-} snd_gus_volume_state_t;
+};
-struct _snd_gus_voice {
+struct snd_gus_voice {
int number;
unsigned int use: 1,
pcm: 1,
@@ -278,18 +277,18 @@ struct _snd_gus_voice {
unsigned int interrupt_stat_wave;
unsigned int interrupt_stat_volume;
#endif
- void (*handler_wave) (snd_gus_card_t * gus, snd_gus_voice_t * voice);
- void (*handler_volume) (snd_gus_card_t * gus, snd_gus_voice_t * voice);
- void (*handler_effect) (snd_gus_card_t * gus, snd_gus_voice_t * voice);
- void (*volume_change) (snd_gus_card_t * gus);
+ void (*handler_wave) (struct snd_gus_card * gus, struct snd_gus_voice * voice);
+ void (*handler_volume) (struct snd_gus_card * gus, struct snd_gus_voice * voice);
+ void (*handler_effect) (struct snd_gus_card * gus, struct snd_gus_voice * voice);
+ void (*volume_change) (struct snd_gus_card * gus);
- snd_gus_sample_ops_t *sample_ops;
+ struct snd_gus_sample_ops *sample_ops;
- snd_seq_instr_t instr;
+ struct snd_seq_instr instr;
/* running status / registers */
- snd_seq_ev_volume_t sample_volume;
+ struct snd_seq_ev_volume sample_volume;
unsigned short fc_register;
unsigned short fc_lfo;
@@ -300,8 +299,8 @@ struct _snd_gus_voice {
unsigned char effect_accumulator;
unsigned char volume_control;
unsigned char venv_value_next;
- snd_gus_volume_state_t venv_state;
- snd_gus_volume_state_t venv_state_prev;
+ enum snd_gus_volume_state venv_state;
+ enum snd_gus_volume_state venv_state_prev;
unsigned short vlo;
unsigned short vro;
unsigned short gf1_effect_volume;
@@ -309,10 +308,10 @@ struct _snd_gus_voice {
/* --- */
void *private_data;
- void (*private_free)(snd_gus_voice_t *voice);
+ void (*private_free)(struct snd_gus_voice *voice);
};
-struct _snd_gf1 {
+struct snd_gf1 {
unsigned int enh_mode:1, /* enhanced mode (GFA1) */
hw_lfo:1, /* use hardware LFO */
@@ -330,7 +329,7 @@ struct _snd_gf1 {
unsigned int rom_present; /* bitmask */
unsigned int rom_banks; /* GUS's ROM banks */
- snd_gf1_mem_t mem_alloc;
+ struct snd_gf1_mem mem_alloc;
/* registers */
unsigned short reg_page;
@@ -347,7 +346,7 @@ struct _snd_gf1 {
unsigned char active_voices; /* active voices */
unsigned char active_voice; /* selected voice (GF1PAGE register) */
- snd_gus_voice_t voices[32]; /* GF1 voices */
+ struct snd_gus_voice voices[32]; /* GF1 voices */
unsigned int default_voice_address;
@@ -362,12 +361,12 @@ struct _snd_gf1 {
/* interrupt handlers */
- void (*interrupt_handler_midi_out) (snd_gus_card_t * gus);
- void (*interrupt_handler_midi_in) (snd_gus_card_t * gus);
- void (*interrupt_handler_timer1) (snd_gus_card_t * gus);
- void (*interrupt_handler_timer2) (snd_gus_card_t * gus);
- void (*interrupt_handler_dma_write) (snd_gus_card_t * gus);
- void (*interrupt_handler_dma_read) (snd_gus_card_t * gus);
+ void (*interrupt_handler_midi_out) (struct snd_gus_card * gus);
+ void (*interrupt_handler_midi_in) (struct snd_gus_card * gus);
+ void (*interrupt_handler_timer1) (struct snd_gus_card * gus);
+ void (*interrupt_handler_timer2) (struct snd_gus_card * gus);
+ void (*interrupt_handler_dma_write) (struct snd_gus_card * gus);
+ void (*interrupt_handler_dma_read) (struct snd_gus_card * gus);
#ifdef CONFIG_SND_DEBUG
unsigned int interrupt_stat_midi_out;
@@ -382,17 +381,17 @@ struct _snd_gf1 {
/* synthesizer */
int seq_client;
- snd_gus_port_t seq_ports[4];
- snd_seq_kinstr_list_t *ilist;
- snd_iwffff_ops_t iwffff_ops;
- snd_gf1_ops_t gf1_ops;
- snd_simple_ops_t simple_ops;
+ struct snd_gus_port seq_ports[4];
+ struct snd_seq_kinstr_list *ilist;
+ struct snd_iwffff_ops iwffff_ops;
+ struct snd_gf1_ops gf1_ops;
+ struct snd_simple_ops simple_ops;
/* timer */
unsigned short timer_enabled;
- snd_timer_t *timer1;
- snd_timer_t *timer2;
+ struct snd_timer *timer1;
+ struct snd_timer *timer2;
/* midi */
@@ -404,11 +403,11 @@ struct _snd_gf1 {
unsigned int dma_flags;
unsigned int dma_shared;
- snd_gf1_dma_block_t *dma_data_pcm;
- snd_gf1_dma_block_t *dma_data_pcm_last;
- snd_gf1_dma_block_t *dma_data_synth;
- snd_gf1_dma_block_t *dma_data_synth_last;
- void (*dma_ack)(snd_gus_card_t * gus, void *private_data);
+ struct snd_gf1_dma_block *dma_data_pcm;
+ struct snd_gf1_dma_block *dma_data_pcm_last;
+ struct snd_gf1_dma_block *dma_data_synth;
+ struct snd_gf1_dma_block *dma_data_synth_last;
+ void (*dma_ack)(struct snd_gus_card * gus, void *private_data);
void *dma_private_data;
/* pcm */
@@ -425,8 +424,8 @@ struct _snd_gf1 {
/* main structure for GUS card */
-struct _snd_gus_card {
- snd_card_t *card;
+struct snd_gus_card {
+ struct snd_card *card;
unsigned int
initialized: 1, /* resources were initialized */
@@ -448,18 +447,18 @@ struct _snd_gus_card {
unsigned short joystick_dac; /* joystick DAC level */
int timer_dev; /* timer device */
- struct _snd_gf1 gf1; /* gf1 specific variables */
- snd_pcm_t *pcm;
- snd_pcm_substream_t *pcm_cap_substream;
+ struct snd_gf1 gf1; /* gf1 specific variables */
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *pcm_cap_substream;
unsigned int c_dma_size;
unsigned int c_period_size;
unsigned int c_pos;
- snd_rawmidi_t *midi_uart;
- snd_rawmidi_substream_t *midi_substream_output;
- snd_rawmidi_substream_t *midi_substream_input;
+ struct snd_rawmidi *midi_uart;
+ struct snd_rawmidi_substream *midi_substream_output;
+ struct snd_rawmidi_substream *midi_substream_input;
- snd_seq_device_t *seq_dev;
+ struct snd_seq_device *seq_dev;
spinlock_t reg_lock;
spinlock_t voice_alloc;
@@ -474,7 +473,7 @@ struct _snd_gus_card {
/* I/O functions for GF1/InterWave chip - gus_io.c */
-static inline void snd_gf1_select_voice(snd_gus_card_t * gus, int voice)
+static inline void snd_gf1_select_voice(struct snd_gus_card * gus, int voice)
{
unsigned long flags;
@@ -486,63 +485,63 @@ static inline void snd_gf1_select_voice(snd_gus_card_t * gus, int voice)
spin_unlock_irqrestore(&gus->active_voice_lock, flags);
}
-static inline void snd_gf1_uart_cmd(snd_gus_card_t * gus, unsigned char b)
+static inline void snd_gf1_uart_cmd(struct snd_gus_card * gus, unsigned char b)
{
outb(gus->gf1.uart_cmd = b, GUSP(gus, MIDICTRL));
}
-static inline unsigned char snd_gf1_uart_stat(snd_gus_card_t * gus)
+static inline unsigned char snd_gf1_uart_stat(struct snd_gus_card * gus)
{
return inb(GUSP(gus, MIDISTAT));
}
-static inline void snd_gf1_uart_put(snd_gus_card_t * gus, unsigned char b)
+static inline void snd_gf1_uart_put(struct snd_gus_card * gus, unsigned char b)
{
outb(b, GUSP(gus, MIDIDATA));
}
-static inline unsigned char snd_gf1_uart_get(snd_gus_card_t * gus)
+static inline unsigned char snd_gf1_uart_get(struct snd_gus_card * gus)
{
return inb(GUSP(gus, MIDIDATA));
}
-extern void snd_gf1_delay(snd_gus_card_t * gus);
+extern void snd_gf1_delay(struct snd_gus_card * gus);
-extern void snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
+extern void snd_gf1_ctrl_stop(struct snd_gus_card * 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);
-static inline unsigned char snd_gf1_read8(snd_gus_card_t * gus, unsigned char reg)
+extern void snd_gf1_write8(struct snd_gus_card * gus, unsigned char reg, unsigned char data);
+extern unsigned char snd_gf1_look8(struct snd_gus_card * gus, unsigned char reg);
+static inline unsigned char snd_gf1_read8(struct snd_gus_card * 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);
-static inline unsigned short snd_gf1_read16(snd_gus_card_t * gus, unsigned char reg)
+extern void snd_gf1_write16(struct snd_gus_card * gus, unsigned char reg, unsigned int data);
+extern unsigned short snd_gf1_look16(struct snd_gus_card * gus, unsigned char reg);
+static inline unsigned short snd_gf1_read16(struct snd_gus_card * gus, unsigned char reg)
{
return snd_gf1_look16(gus, reg | 0x80);
}
-extern void snd_gf1_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
-extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data);
-extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
-extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
-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);
-static inline unsigned char snd_gf1_i_read8(snd_gus_card_t * gus, unsigned char reg)
+extern void snd_gf1_adlib_write(struct snd_gus_card * gus, unsigned char reg, unsigned char data);
+extern void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr);
+extern void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data);
+extern unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr);
+extern void snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg, unsigned int addr, short w_16bit);
+extern unsigned int snd_gf1_read_addr(struct snd_gus_card * gus, unsigned char reg, short w_16bit);
+extern void snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg);
+extern void snd_gf1_i_write8(struct snd_gus_card * gus, unsigned char reg, unsigned char data);
+extern unsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg);
+extern void snd_gf1_i_write16(struct snd_gus_card * gus, unsigned char reg, unsigned int data);
+static inline unsigned char snd_gf1_i_read8(struct snd_gus_card * 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);
-static inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned char reg)
+extern unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg);
+static inline unsigned short snd_gf1_i_read16(struct snd_gus_card * gus, unsigned char reg)
{
return snd_gf1_i_look16(gus, reg | 0x80);
}
-extern void snd_gf1_select_active_voices(snd_gus_card_t * gus);
+extern void snd_gf1_select_active_voices(struct snd_gus_card * gus);
/* gus_lfo.c */
@@ -555,98 +554,98 @@ struct _SND_IW_LFO_PROGRAM {
};
#if 0
-extern irqreturn_t snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice);
+extern irqreturn_t snd_gf1_lfo_effect_interrupt(struct snd_gus_card * gus, snd_gf1_voice_t * voice);
#endif
-extern void snd_gf1_lfo_init(snd_gus_card_t * gus);
-extern void snd_gf1_lfo_done(snd_gus_card_t * gus);
-extern void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type, struct _SND_IW_LFO_PROGRAM *program);
-extern void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type);
-extern void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type);
-extern void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice, int lfo_type, int freq);
-extern void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice, int lfo_type, int depth);
-extern void snd_gf1_lfo_setup(snd_gus_card_t * gus, int voice, int lfo_type, int freq, int current_depth, int depth, int sweep, int shape);
-extern void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type);
+extern void snd_gf1_lfo_init(struct snd_gus_card * gus);
+extern void snd_gf1_lfo_done(struct snd_gus_card * gus);
+extern void snd_gf1_lfo_program(struct snd_gus_card * gus, int voice, int lfo_type, struct _SND_IW_LFO_PROGRAM *program);
+extern void snd_gf1_lfo_enable(struct snd_gus_card * gus, int voice, int lfo_type);
+extern void snd_gf1_lfo_disable(struct snd_gus_card * gus, int voice, int lfo_type);
+extern void snd_gf1_lfo_change_freq(struct snd_gus_card * gus, int voice, int lfo_type, int freq);
+extern void snd_gf1_lfo_change_depth(struct snd_gus_card * gus, int voice, int lfo_type, int depth);
+extern void snd_gf1_lfo_setup(struct snd_gus_card * gus, int voice, int lfo_type, int freq, int current_depth, int depth, int sweep, int shape);
+extern void snd_gf1_lfo_shutdown(struct snd_gus_card * gus, int voice, int lfo_type);
#if 0
-extern void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *command);
+extern void snd_gf1_lfo_command(struct snd_gus_card * gus, int voice, unsigned char *command);
#endif
/* gus_mem.c */
-void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup);
-int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block);
-snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
+void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup);
+int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block);
+struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner,
char *name, int size, int w_16,
int align, unsigned int *share_id);
-int snd_gf1_mem_free(snd_gf1_mem_t * alloc, unsigned int address);
-int snd_gf1_mem_free_owner(snd_gf1_mem_t * alloc, int owner);
-int snd_gf1_mem_init(snd_gus_card_t * gus);
-int snd_gf1_mem_done(snd_gus_card_t * gus);
+int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address);
+int snd_gf1_mem_free_owner(struct snd_gf1_mem * alloc, int owner);
+int snd_gf1_mem_init(struct snd_gus_card * gus);
+int snd_gf1_mem_done(struct snd_gus_card * gus);
/* gus_mem_proc.c */
-int snd_gf1_mem_proc_init(snd_gus_card_t * gus);
+int snd_gf1_mem_proc_init(struct snd_gus_card * gus);
/* gus_dma.c */
-int snd_gf1_dma_init(snd_gus_card_t * gus);
-int snd_gf1_dma_done(snd_gus_card_t * gus);
-int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
- snd_gf1_dma_block_t * block,
+int snd_gf1_dma_init(struct snd_gus_card * gus);
+int snd_gf1_dma_done(struct snd_gus_card * gus);
+int snd_gf1_dma_transfer_block(struct snd_gus_card * gus,
+ struct snd_gf1_dma_block * block,
int atomic,
int synth);
/* gus_volume.c */
unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol);
-unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2);
+unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq2);
/* gus_reset.c */
-void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what);
-void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice);
-void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice);
-void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
-snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port);
-void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice);
-int snd_gf1_start(snd_gus_card_t * gus);
-int snd_gf1_stop(snd_gus_card_t * gus);
+void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what);
+void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice);
+void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice);
+void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max);
+struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port);
+void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice);
+int snd_gf1_start(struct snd_gus_card * gus);
+int snd_gf1_stop(struct snd_gus_card * gus);
/* gus_mixer.c */
-int snd_gf1_new_mixer(snd_gus_card_t * gus);
+int snd_gf1_new_mixer(struct snd_gus_card * gus);
/* gus_pcm.c */
-int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pcm_t ** rpcm);
+int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm);
#ifdef CONFIG_SND_DEBUG
-extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus);
+extern void snd_gf1_print_voice_registers(struct snd_gus_card * gus);
#endif
/* gus.c */
-int snd_gus_use_inc(snd_gus_card_t * gus);
-void snd_gus_use_dec(snd_gus_card_t * gus);
-int snd_gus_create(snd_card_t * card,
+int snd_gus_use_inc(struct snd_gus_card * gus);
+void snd_gus_use_dec(struct snd_gus_card * gus);
+int snd_gus_create(struct snd_card *card,
unsigned long port,
int irq, int dma1, int dma2,
int timer_dev,
int voices,
int pcm_channels,
int effect,
- snd_gus_card_t ** rgus);
-int snd_gus_initialize(snd_gus_card_t * gus);
+ struct snd_gus_card ** rgus);
+int snd_gus_initialize(struct snd_gus_card * gus);
/* gus_irq.c */
irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs);
#ifdef CONFIG_SND_DEBUG
-void snd_gus_irq_profile_init(snd_gus_card_t *gus);
+void snd_gus_irq_profile_init(struct snd_gus_card *gus);
#endif
/* gus_uart.c */
-int snd_gf1_rawmidi_new(snd_gus_card_t * gus, int device, snd_rawmidi_t **rrawmidi);
+int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi **rrawmidi);
#if 0
extern void snd_engine_instrument_register(unsigned short mode,
@@ -657,37 +656,37 @@ extern int snd_engine_instrument_register_ask(unsigned short mode);
#endif
/* gus_dram.c */
-int snd_gus_dram_write(snd_gus_card_t *gus, char __user *ptr,
+int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr,
unsigned int addr, unsigned int size);
-int snd_gus_dram_read(snd_gus_card_t *gus, char __user *ptr,
+int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr,
unsigned int addr, unsigned int size, int rom);
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
/* gus_sample.c */
-void snd_gus_sample_event(snd_seq_event_t *ev, snd_gus_port_t *p);
+void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p);
/* gus_simple.c */
-void snd_gf1_simple_init(snd_gus_voice_t *voice);
+void snd_gf1_simple_init(struct snd_gus_voice *voice);
/* gus_instr.c */
-int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic);
-int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic);
-int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave,
int atomic);
-int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic);
-int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic);
-int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave,
int atomic);
-int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic);
-int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic);
-int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr,
int atomic);
#endif /* CONFIG_SND_SEQUENCER */
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
index 7ce3aa67e5d6..25e1951a9955 100644
--- a/include/sound/hdsp.h
+++ b/include/sound/hdsp.h
@@ -21,17 +21,15 @@
#define HDSP_MATRIX_MIXER_SIZE 2048
-typedef enum {
+enum HDSP_IO_Type {
Digiface,
Multiface,
H9652,
H9632,
Undefined,
-} HDSP_IO_Type;
-
-typedef struct _snd_hdsp_peak_rms hdsp_peak_rms_t;
+};
-struct _snd_hdsp_peak_rms {
+struct hdsp_peak_rms {
u32 input_peaks[26];
u32 playback_peaks[26];
u32 output_peaks[28];
@@ -41,11 +39,9 @@ struct _snd_hdsp_peak_rms {
u64 output_rms[26];
};
-#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, hdsp_peak_rms_t)
+#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
-typedef struct _snd_hdsp_config_info hdsp_config_info_t;
-
-struct _snd_hdsp_config_info {
+struct hdsp_config_info {
unsigned char pref_sync_ref;
unsigned char wordclock_sync_check;
unsigned char spdif_sync_check;
@@ -71,40 +67,41 @@ struct _snd_hdsp_config_info {
unsigned char analog_extension_board;
};
-#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdsp_config_info_t)
-
-typedef struct _snd_hdsp_firmware hdsp_firmware_t;
+#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
-struct _snd_hdsp_firmware {
+struct hdsp_firmware {
void __user *firmware_data; /* 24413 x 4 bytes */
};
-#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, hdsp_firmware_t)
+#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
-typedef struct _snd_hdsp_version hdsp_version_t;
-
-struct _snd_hdsp_version {
- HDSP_IO_Type io_type;
+struct hdsp_version {
+ enum HDSP_IO_Type io_type;
unsigned short firmware_rev;
};
-#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, hdsp_version_t)
-
-typedef struct _snd_hdsp_mixer hdsp_mixer_t;
+#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdsp_version)
-struct _snd_hdsp_mixer {
+struct hdsp_mixer {
unsigned short matrix[HDSP_MATRIX_MIXER_SIZE];
};
-#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, hdsp_mixer_t)
+#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdsp_mixer)
-typedef struct _snd_hdsp_9632_aeb hdsp_9632_aeb_t;
-
-struct _snd_hdsp_9632_aeb {
+struct hdsp_9632_aeb {
int aebi;
int aebo;
};
-#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, hdsp_9632_aeb_t)
+#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
+
+/* typedefs for compatibility to user-space */
+typedef enum HDSP_IO_Type HDSP_IO_Type;
+typedef struct hdsp_peak_rms hdsp_peak_rms_t;
+typedef struct hdsp_config_info hdsp_config_info_t;
+typedef struct hdsp_firmware hdsp_firmware_t;
+typedef struct hdsp_version hdsp_version_t;
+typedef struct hdsp_mixer hdsp_mixer_t;
+typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
#endif /* __SOUND_HDSP_H */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index c34427ccd0b3..c3c854d99c28 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -25,8 +25,6 @@
/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
-
/* peam rms level structure like we get from hardware
maybe in future we can memory map it so I just copy it
@@ -36,7 +34,7 @@ typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
(i asume so from the code)
*/
-struct _snd_hdspm_peak_rms {
+struct hdspm_peak_rms {
unsigned int level_offset[1024];
@@ -58,18 +56,16 @@ struct _snd_hdspm_peak_rms {
unsigned int xxx_rms_h[64]; /* not used */
};
-struct sndrv_hdspm_peak_rms_ioctl {
- hdspm_peak_rms_t *peak;
+struct hdspm_peak_rms_ioctl {
+ struct hdspm_peak_rms *peak;
};
/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl)
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdspm_peak_rms_ioctl)
/* ------------ CONFIG block IOCTL ---------------------- */
-typedef struct _snd_hdspm_config_info hdspm_config_info_t;
-
-struct _snd_hdspm_config_info {
+struct hdspm_config_info {
unsigned char pref_sync_ref;
unsigned char wordclock_sync_check;
unsigned char madi_sync_check;
@@ -83,18 +79,16 @@ struct _snd_hdspm_config_info {
unsigned int analog_out;
};
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t)
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdspm_config_info)
/* get Soundcard Version */
-typedef struct _snd_hdspm_version hdspm_version_t;
-
-struct _snd_hdspm_version {
+struct hdspm_version {
unsigned short firmware_rev;
};
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t)
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdspm_version)
/* ------------- get Matrix Mixer IOCTL --------------- */
@@ -108,24 +102,27 @@ struct _snd_hdspm_version {
#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
-typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t;
-
-struct _snd_hdspm_channelfader {
+struct hdspm_channelfader {
unsigned int in[HDSPM_MIXER_CHANNELS];
unsigned int pb[HDSPM_MIXER_CHANNELS];
};
-typedef struct _snd_hdspm_mixer hdspm_mixer_t;
-
-struct _snd_hdspm_mixer {
- snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS];
+struct hdspm_mixer {
+ struct hdspm_channelfader ch[HDSPM_MIXER_CHANNELS];
};
-struct sndrv_hdspm_mixer_ioctl {
- hdspm_mixer_t *mixer;
+struct hdspm_mixer_ioctl {
+ struct hdspm_mixer *mixer;
};
/* use indirect access due to the limit of ioctl bit size */
-#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl)
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
+
+/* typedefs for compatibility to user-space */
+typedef struct hdspm_peak_rms hdspm_peak_rms_t;
+typedef struct hdspm_config_info hdspm_config_info_t;
+typedef struct hdspm_version hdspm_version_t;
+typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
+typedef struct hdspm_mixer hdspm_mixer_t;
#endif /* __SOUND_HDSPM_H */
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index 043876348fa1..c679e5b31111 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -25,27 +25,25 @@
#include <sound/asound.h>
#include <linux/poll.h>
-typedef enum sndrv_hwdep_iface snd_hwdep_iface_t;
-typedef struct sndrv_hwdep_info snd_hwdep_info_t;
-typedef struct sndrv_hwdep_dsp_status snd_hwdep_dsp_status_t;
-typedef struct sndrv_hwdep_dsp_image snd_hwdep_dsp_image_t;
+struct snd_hwdep;
-typedef struct _snd_hwdep_ops {
- long long (*llseek) (snd_hwdep_t *hw, struct file * file, long long offset, int orig);
- long (*read) (snd_hwdep_t * hw, char __user *buf, long count, loff_t *offset);
- long (*write) (snd_hwdep_t * hw, const char __user *buf, long count, loff_t *offset);
- int (*open) (snd_hwdep_t * hw, struct file * file);
- int (*release) (snd_hwdep_t * hw, struct file * file);
- unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait);
- int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
- int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
- int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma);
- int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status);
- int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image);
-} snd_hwdep_ops_t;
+struct snd_hwdep_ops {
+ long long (*llseek) (struct snd_hwdep *hw, struct file * file, long long offset, int orig);
+ long (*read) (struct snd_hwdep *hw, char __user *buf, long count, loff_t *offset);
+ long (*write) (struct snd_hwdep *hw, const char __user *buf, long count, loff_t *offset);
+ int (*open) (struct snd_hwdep * hw, struct file * file);
+ int (*release) (struct snd_hwdep *hw, struct file * file);
+ unsigned int (*poll) (struct snd_hwdep *hw, struct file * file, poll_table * wait);
+ int (*ioctl) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
+ int (*ioctl_compat) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
+ int (*mmap) (struct snd_hwdep *hw, struct file * file, struct vm_area_struct * vma);
+ int (*dsp_status) (struct snd_hwdep *hw, struct snd_hwdep_dsp_status *status);
+ int (*dsp_load) (struct snd_hwdep *hw, struct snd_hwdep_dsp_image *image);
+};
-struct _snd_hwdep {
- snd_card_t *card;
+struct snd_hwdep {
+ struct snd_card *card;
+ struct list_head list;
int device;
char id[32];
char name[80];
@@ -57,10 +55,10 @@ struct _snd_hwdep {
int ossreg;
#endif
- snd_hwdep_ops_t ops;
+ struct snd_hwdep_ops ops;
wait_queue_head_t open_wait;
void *private_data;
- void (*private_free) (snd_hwdep_t *hwdep);
+ void (*private_free) (struct snd_hwdep *hwdep);
struct semaphore open_mutex;
int used;
@@ -68,6 +66,7 @@ struct _snd_hwdep {
unsigned int exclusive: 1;
};
-extern int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep);
+extern int snd_hwdep_new(struct snd_card *card, char *id, int device,
+ struct snd_hwdep **rhwdep);
#endif /* __SOUND_HWDEP_H */
diff --git a/include/sound/i2c.h b/include/sound/i2c.h
index a665ddf9c146..81eb23ed761f 100644
--- a/include/sound/i2c.h
+++ b/include/sound/i2c.h
@@ -21,82 +21,84 @@
*
*/
-typedef struct _snd_i2c_device snd_i2c_device_t;
-typedef struct _snd_i2c_bus snd_i2c_bus_t;
-
#define SND_I2C_DEVICE_ADDRTEN (1<<0) /* 10-bit I2C address */
-struct _snd_i2c_device {
+struct snd_i2c_device {
struct list_head list;
- snd_i2c_bus_t *bus; /* I2C bus */
+ struct snd_i2c_bus *bus; /* I2C bus */
char name[32]; /* some useful device name */
unsigned short flags; /* device flags */
unsigned short addr; /* device address (might be 10-bit) */
unsigned long private_value;
void *private_data;
- void (*private_free)(snd_i2c_device_t *device);
+ void (*private_free)(struct snd_i2c_device *device);
+};
+
+#define snd_i2c_device(n) list_entry(n, struct snd_i2c_device, list)
+
+struct snd_i2c_bit_ops {
+ void (*start)(struct snd_i2c_bus *bus); /* transfer start */
+ void (*stop)(struct snd_i2c_bus *bus); /* transfer stop */
+ void (*direction)(struct snd_i2c_bus *bus, int clock, int data); /* set line direction (0 = write, 1 = read) */
+ void (*setlines)(struct snd_i2c_bus *bus, int clock, int data);
+ int (*getclock)(struct snd_i2c_bus *bus);
+ int (*getdata)(struct snd_i2c_bus *bus, int ack);
};
-#define snd_i2c_device(n) list_entry(n, snd_i2c_device_t, list)
-
-typedef struct _snd_i2c_bit_ops {
- void (*start)(snd_i2c_bus_t *bus); /* transfer start */
- void (*stop)(snd_i2c_bus_t *bus); /* transfer stop */
- void (*direction)(snd_i2c_bus_t *bus, int clock, int data); /* set line direction (0 = write, 1 = read) */
- void (*setlines)(snd_i2c_bus_t *bus, int clock, int data);
- int (*getclock)(snd_i2c_bus_t *bus);
- int (*getdata)(snd_i2c_bus_t *bus, int ack);
-} snd_i2c_bit_ops_t;
-
-typedef struct _snd_i2c_ops {
- int (*sendbytes)(snd_i2c_device_t *device, unsigned char *bytes, int count);
- int (*readbytes)(snd_i2c_device_t *device, unsigned char *bytes, int count);
- int (*probeaddr)(snd_i2c_bus_t *bus, unsigned short addr);
-} snd_i2c_ops_t;
-
-struct _snd_i2c_bus {
- snd_card_t *card; /* card which I2C belongs to */
+struct snd_i2c_ops {
+ int (*sendbytes)(struct snd_i2c_device *device, unsigned char *bytes, int count);
+ int (*readbytes)(struct snd_i2c_device *device, unsigned char *bytes, int count);
+ int (*probeaddr)(struct snd_i2c_bus *bus, unsigned short addr);
+};
+
+struct snd_i2c_bus {
+ struct snd_card *card; /* card which I2C belongs to */
char name[32]; /* some useful label */
struct semaphore lock_mutex;
- snd_i2c_bus_t *master; /* master bus when SCK/SCL is shared */
+ struct snd_i2c_bus *master; /* master bus when SCK/SCL is shared */
struct list_head buses; /* master: slave buses sharing SCK/SCL, slave: link list */
struct list_head devices; /* attached devices to this bus */
union {
- snd_i2c_bit_ops_t *bit;
+ struct snd_i2c_bit_ops *bit;
void *ops;
} hw_ops; /* lowlevel operations */
- snd_i2c_ops_t *ops; /* midlevel operations */
+ struct snd_i2c_ops *ops; /* midlevel operations */
unsigned long private_value;
void *private_data;
- void (*private_free)(snd_i2c_bus_t *bus);
+ void (*private_free)(struct snd_i2c_bus *bus);
};
-#define snd_i2c_slave_bus(n) list_entry(n, snd_i2c_bus_t, buses)
+#define snd_i2c_slave_bus(n) list_entry(n, struct snd_i2c_bus, buses)
-int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master, snd_i2c_bus_t **ri2c);
-int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char addr, snd_i2c_device_t **rdevice);
-int snd_i2c_device_free(snd_i2c_device_t *device);
+int snd_i2c_bus_create(struct snd_card *card, const char *name,
+ struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c);
+int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
+ unsigned char addr, struct snd_i2c_device **rdevice);
+int snd_i2c_device_free(struct snd_i2c_device *device);
-static inline void snd_i2c_lock(snd_i2c_bus_t *bus) {
+static inline void snd_i2c_lock(struct snd_i2c_bus *bus)
+{
if (bus->master)
down(&bus->master->lock_mutex);
else
down(&bus->lock_mutex);
}
-static inline void snd_i2c_unlock(snd_i2c_bus_t *bus) {
+
+static inline void snd_i2c_unlock(struct snd_i2c_bus *bus)
+{
if (bus->master)
up(&bus->master->lock_mutex);
else
up(&bus->lock_mutex);
}
-int snd_i2c_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count);
-int snd_i2c_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count);
-int snd_i2c_probeaddr(snd_i2c_bus_t *bus, unsigned short addr);
+int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count);
+int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count);
+int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr);
#endif /* __SOUND_I2C_H */
diff --git a/include/sound/info.h b/include/sound/info.h
index 1d76bf3cb05e..8ea5c7497c03 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -34,8 +34,6 @@ struct snd_info_buffer {
int error; /* error code */
};
-typedef struct snd_info_buffer snd_info_buffer_t;
-
#define SNDRV_INFO_CONTENT_TEXT 0
#define SNDRV_INFO_CONTENT_DATA 1
@@ -44,28 +42,28 @@ struct snd_info_entry;
struct snd_info_entry_text {
unsigned long read_size;
unsigned long write_size;
- void (*read) (snd_info_entry_t *entry, snd_info_buffer_t * buffer);
- void (*write) (snd_info_entry_t *entry, snd_info_buffer_t * buffer);
+ void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
+ void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
};
struct snd_info_entry_ops {
- int (*open) (snd_info_entry_t *entry,
+ int (*open) (struct snd_info_entry *entry,
unsigned short mode, void **file_private_data);
- int (*release) (snd_info_entry_t * entry,
+ int (*release) (struct snd_info_entry * entry,
unsigned short mode, void *file_private_data);
- long (*read) (snd_info_entry_t *entry, void *file_private_data,
+ long (*read) (struct snd_info_entry *entry, void *file_private_data,
struct file * file, char __user *buf,
unsigned long count, unsigned long pos);
- long (*write) (snd_info_entry_t *entry, void *file_private_data,
+ long (*write) (struct snd_info_entry *entry, void *file_private_data,
struct file * file, const char __user *buf,
unsigned long count, unsigned long pos);
- long long (*llseek) (snd_info_entry_t *entry, void *file_private_data,
+ long long (*llseek) (struct snd_info_entry *entry, void *file_private_data,
struct file * file, long long offset, int orig);
- unsigned int (*poll) (snd_info_entry_t *entry, void *file_private_data,
+ unsigned int (*poll) (struct snd_info_entry *entry, void *file_private_data,
struct file * file, poll_table * wait);
- int (*ioctl) (snd_info_entry_t *entry, void *file_private_data,
+ int (*ioctl) (struct snd_info_entry *entry, void *file_private_data,
struct file * file, unsigned int cmd, unsigned long arg);
- int (*mmap) (snd_info_entry_t *entry, void *file_private_data,
+ int (*mmap) (struct snd_info_entry *entry, void *file_private_data,
struct inode * inode, struct file * file,
struct vm_area_struct * vma);
};
@@ -80,20 +78,18 @@ struct snd_info_entry {
struct snd_info_entry_text text;
struct snd_info_entry_ops *ops;
} c;
- snd_info_entry_t *parent;
- snd_card_t *card;
+ struct snd_info_entry *parent;
+ struct snd_card *card;
struct module *module;
void *private_data;
- void (*private_free)(snd_info_entry_t *entry);
+ void (*private_free)(struct snd_info_entry *entry);
struct proc_dir_entry *p;
struct semaphore access;
};
-extern int snd_info_check_reserved_words(const char *str);
-
#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
-extern int snd_info_minor_register(void);
-extern int snd_info_minor_unregister(void);
+int snd_info_minor_register(void);
+int snd_info_minor_unregister(void);
#else
#define snd_info_minor_register() /* NOP */
#define snd_info_minor_unregister() /* NOP */
@@ -102,72 +98,79 @@ extern int snd_info_minor_unregister(void);
#ifdef CONFIG_PROC_FS
-extern snd_info_entry_t *snd_seq_root;
+extern struct snd_info_entry *snd_seq_root;
#ifdef CONFIG_SND_OSSEMUL
-extern snd_info_entry_t *snd_oss_root;
+extern struct snd_info_entry *snd_oss_root;
#else
#define snd_oss_root NULL
#endif
-int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...) __attribute__ ((format (printf, 2, 3)));
+int snd_iprintf(struct snd_info_buffer * buffer, char *fmt,...) __attribute__ ((format (printf, 2, 3)));
int snd_info_init(void);
int snd_info_done(void);
-int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len);
+int snd_info_get_line(struct snd_info_buffer * buffer, char *line, int len);
char *snd_info_get_str(char *dest, char *src, int len);
-snd_info_entry_t *snd_info_create_module_entry(struct module * module,
+struct snd_info_entry *snd_info_create_module_entry(struct module * module,
const char *name,
- snd_info_entry_t * parent);
-snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card,
+ struct snd_info_entry * parent);
+struct snd_info_entry *snd_info_create_card_entry(struct snd_card * card,
const char *name,
- snd_info_entry_t * parent);
-void snd_info_free_entry(snd_info_entry_t * entry);
-int snd_info_store_text(snd_info_entry_t * entry);
-int snd_info_restore_text(snd_info_entry_t * entry);
+ struct snd_info_entry * parent);
+void snd_info_free_entry(struct snd_info_entry * entry);
+int snd_info_store_text(struct snd_info_entry * entry);
+int snd_info_restore_text(struct snd_info_entry * entry);
-int snd_info_card_create(snd_card_t * card);
-int snd_info_card_register(snd_card_t * card);
-int snd_info_card_free(snd_card_t * card);
-int snd_info_register(snd_info_entry_t * entry);
-int snd_info_unregister(snd_info_entry_t * entry);
+int snd_info_card_create(struct snd_card * card);
+int snd_info_card_register(struct snd_card * card);
+int snd_info_card_free(struct snd_card * card);
+int snd_info_register(struct snd_info_entry * entry);
+int snd_info_unregister(struct snd_info_entry * entry);
/* for card drivers */
-int snd_card_proc_new(snd_card_t *card, const char *name, snd_info_entry_t **entryp);
+int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp);
-static inline void snd_info_set_text_ops(snd_info_entry_t *entry,
+static inline void snd_info_set_text_ops(struct snd_info_entry *entry,
void *private_data,
long read_size,
- void (*read)(snd_info_entry_t *, snd_info_buffer_t *))
+ void (*read)(struct snd_info_entry *, struct snd_info_buffer *))
{
entry->private_data = private_data;
entry->c.text.read_size = read_size;
entry->c.text.read = read;
}
+int snd_info_check_reserved_words(const char *str);
#else
#define snd_seq_root NULL
#define snd_oss_root NULL
-static inline int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...) { return 0; }
+static inline int snd_iprintf(struct snd_info_buffer * buffer, char *fmt,...) { return 0; }
static inline int snd_info_init(void) { return 0; }
static inline int snd_info_done(void) { return 0; }
-static inline int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len) { return 0; }
+static inline int snd_info_get_line(struct snd_info_buffer * buffer, char *line, int len) { return 0; }
static inline char *snd_info_get_str(char *dest, char *src, int len) { return NULL; }
-static inline snd_info_entry_t *snd_info_create_module_entry(struct module * module, const char *name, snd_info_entry_t * parent) { return NULL; }
-static inline snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card, const char *name, snd_info_entry_t * parent) { return NULL; }
-static inline void snd_info_free_entry(snd_info_entry_t * entry) { ; }
-
-static inline int snd_info_card_create(snd_card_t * card) { return 0; }
-static inline int snd_info_card_register(snd_card_t * card) { return 0; }
-static inline int snd_info_card_free(snd_card_t * card) { return 0; }
-static inline int snd_info_register(snd_info_entry_t * entry) { return 0; }
-static inline int snd_info_unregister(snd_info_entry_t * entry) { return 0; }
+static inline struct snd_info_entry *snd_info_create_module_entry(struct module * module, const char *name, struct snd_info_entry * parent) { return NULL; }
+static inline struct snd_info_entry *snd_info_create_card_entry(struct snd_card * card, const char *name, struct snd_info_entry * parent) { return NULL; }
+static inline void snd_info_free_entry(struct snd_info_entry * entry) { ; }
+
+static inline int snd_info_card_create(struct snd_card * card) { return 0; }
+static inline int snd_info_card_register(struct snd_card * card) { return 0; }
+static inline int snd_info_card_free(struct snd_card * card) { return 0; }
+static inline int snd_info_register(struct snd_info_entry * entry) { return 0; }
+static inline int snd_info_unregister(struct snd_info_entry * entry) { return 0; }
+
+static inline int snd_card_proc_new(struct snd_card *card, const char *name,
+ struct snd_info_entry **entryp) { return -EINVAL; }
+static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)),
+ void *private_data,
+ long read_size,
+ void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {}
-#define snd_card_proc_new(card,name,entryp) 0 /* always success */
-#define snd_info_set_text_ops(entry,private_data,read_size,read) /*NOP*/
+static inline int snd_info_check_reserved_words(const char *str) { return 1; }
#endif
@@ -185,7 +188,7 @@ static inline int snd_info_unregister(snd_info_entry_t * entry) { return 0; }
#define SNDRV_OSS_INFO_DEV_COUNT 6
-extern int snd_oss_info_register(int dev, int num, char *string);
+int snd_oss_info_register(int dev, int num, char *string);
#define snd_oss_info_unregister(dev, num) snd_oss_info_register(dev, num, NULL)
#endif /* CONFIG_SND_OSSEMUL && CONFIG_PROC_FS */
diff --git a/include/sound/initval.h b/include/sound/initval.h
index 2bf1508825a4..d29e3d31d149 100644
--- a/include/sound/initval.h
+++ b/include/sound/initval.h
@@ -50,20 +50,6 @@
#define SNDRV_DEFAULT_DMA_SIZE { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA_SIZE }
#define SNDRV_DEFAULT_PTR SNDRV_DEFAULT_STR
-#ifdef SNDRV_LEGACY_AUTO_PROBE
-static int snd_legacy_auto_probe(unsigned long *ports, int (*probe)(unsigned long port))
-{
- int result = 0; /* number of detected cards */
-
- while ((signed long)*ports != -1) {
- if (probe(*ports) >= 0)
- result++;
- ports++;
- }
- return result;
-}
-#endif
-
#ifdef SNDRV_LEGACY_FIND_FREE_IRQ
#include <linux/interrupt.h>
diff --git a/include/sound/minors.h b/include/sound/minors.h
index a17b5c9961bb..46bcd2023ed8 100644
--- a/include/sound/minors.h
+++ b/include/sound/minors.h
@@ -26,18 +26,20 @@
#define SNDRV_MINOR_DEVICE(minor) ((minor) & 0x001f)
#define SNDRV_MINOR(card, dev) (((card) << 5) | (dev))
-#define SNDRV_MINOR_CONTROL 0 /* 0 - 0 */
+/* these minors can still be used for autoloading devices (/dev/aload*) */
+#define SNDRV_MINOR_CONTROL 0 /* 0 */
#define SNDRV_MINOR_GLOBAL 1 /* 1 */
#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32)
#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32)
+
+#ifndef CONFIG_SND_DYNAMIC_MINORS
+ /* 2 - 3 (reserved) */
#define SNDRV_MINOR_HWDEP 4 /* 4 - 7 */
-#define SNDRV_MINOR_HWDEPS 4
#define SNDRV_MINOR_RAWMIDI 8 /* 8 - 15 */
-#define SNDRV_MINOR_RAWMIDIS 8
#define SNDRV_MINOR_PCM_PLAYBACK 16 /* 16 - 23 */
#define SNDRV_MINOR_PCM_CAPTURE 24 /* 24 - 31 */
-#define SNDRV_MINOR_PCMS 8
+/* same as first respective minor number to make minor allocation easier */
#define SNDRV_DEVICE_TYPE_CONTROL SNDRV_MINOR_CONTROL
#define SNDRV_DEVICE_TYPE_HWDEP SNDRV_MINOR_HWDEP
#define SNDRV_DEVICE_TYPE_RAWMIDI SNDRV_MINOR_RAWMIDI
@@ -46,6 +48,25 @@
#define SNDRV_DEVICE_TYPE_SEQUENCER SNDRV_MINOR_SEQUENCER
#define SNDRV_DEVICE_TYPE_TIMER SNDRV_MINOR_TIMER
+#else /* CONFIG_SND_DYNAMIC_MINORS */
+
+enum {
+ SNDRV_DEVICE_TYPE_CONTROL,
+ SNDRV_DEVICE_TYPE_SEQUENCER,
+ SNDRV_DEVICE_TYPE_TIMER,
+ SNDRV_DEVICE_TYPE_HWDEP,
+ SNDRV_DEVICE_TYPE_RAWMIDI,
+ SNDRV_DEVICE_TYPE_PCM_PLAYBACK,
+ SNDRV_DEVICE_TYPE_PCM_CAPTURE,
+};
+
+#endif /* CONFIG_SND_DYNAMIC_MINORS */
+
+#define SNDRV_MINOR_HWDEPS 4
+#define SNDRV_MINOR_RAWMIDIS 8
+#define SNDRV_MINOR_PCMS 8
+
+
#ifdef CONFIG_SND_OSSEMUL
#define SNDRV_MINOR_OSS_DEVICES 16
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
index ed75b2fb00ab..ca5b4822b62c 100644
--- a/include/sound/mixer_oss.h
+++ b/include/sound/mixer_oss.h
@@ -24,51 +24,53 @@
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-typedef struct _snd_oss_mixer_slot snd_mixer_oss_slot_t;
-typedef struct _snd_oss_file snd_mixer_oss_file_t;
-
-typedef int (*snd_mixer_oss_get_volume_t)(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *chn, int *left, int *right);
-typedef int (*snd_mixer_oss_put_volume_t)(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *chn, int left, int right);
-typedef int (*snd_mixer_oss_get_recsrc_t)(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *chn, int *active);
-typedef int (*snd_mixer_oss_put_recsrc_t)(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *chn, int active);
-typedef int (*snd_mixer_oss_get_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigned int *active_index);
-typedef int (*snd_mixer_oss_put_recsrce_t)(snd_mixer_oss_file_t *fmixer, unsigned int active_index);
-
#define SNDRV_OSS_MAX_MIXERS 32
-struct _snd_oss_mixer_slot {
+struct snd_mixer_oss_file;
+
+struct snd_mixer_oss_slot {
int number;
unsigned int stereo: 1;
- snd_mixer_oss_get_volume_t get_volume;
- snd_mixer_oss_put_volume_t put_volume;
- snd_mixer_oss_get_recsrc_t get_recsrc;
- snd_mixer_oss_put_recsrc_t put_recsrc;
+ int (*get_volume)(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *chn,
+ int *left, int *right);
+ int (*put_volume)(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *chn,
+ int left, int right);
+ int (*get_recsrc)(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *chn,
+ int *active);
+ int (*put_recsrc)(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *chn,
+ int active);
unsigned long private_value;
void *private_data;
- void (*private_free)(snd_mixer_oss_slot_t *slot);
+ void (*private_free)(struct snd_mixer_oss_slot *slot);
int volume[2];
};
-struct _snd_oss_mixer {
- snd_card_t *card;
+struct snd_mixer_oss {
+ struct snd_card *card;
char id[16];
char name[32];
- snd_mixer_oss_slot_t slots[SNDRV_OSS_MAX_MIXERS]; /* OSS mixer slots */
+ struct snd_mixer_oss_slot slots[SNDRV_OSS_MAX_MIXERS]; /* OSS mixer slots */
unsigned int mask_recsrc; /* exclusive recsrc mask */
- snd_mixer_oss_get_recsrce_t get_recsrc;
- snd_mixer_oss_put_recsrce_t put_recsrc;
+ int (*get_recsrc)(struct snd_mixer_oss_file *fmixer,
+ unsigned int *active_index);
+ int (*put_recsrc)(struct snd_mixer_oss_file *fmixer,
+ unsigned int active_index);
void *private_data_recsrc;
- void (*private_free_recsrc)(snd_mixer_oss_t *mixer);
+ void (*private_free_recsrc)(struct snd_mixer_oss *mixer);
struct semaphore reg_mutex;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
int oss_dev_alloc;
/* --- */
int oss_recsrc;
};
-struct _snd_oss_file {
- snd_card_t *card;
- snd_mixer_oss_t *mixer;
+struct snd_mixer_oss_file {
+ struct snd_card *card;
+ struct snd_mixer_oss *mixer;
};
#endif /* CONFIG_SND_MIXER_OSS */
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index ae39e38bf996..8e97ace78f16 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -58,10 +58,8 @@
#define MPU401_MODE_INPUT_TIMER (1<<0)
#define MPU401_MODE_OUTPUT_TIMER (1<<1)
-typedef struct _snd_mpu401 mpu401_t;
-
-struct _snd_mpu401 {
- snd_rawmidi_t *rmidi;
+struct snd_mpu401 {
+ struct snd_rawmidi *rmidi;
unsigned short hardware; /* MPU401_HW_XXXX */
unsigned long port; /* base port of MPU-401 chip */
@@ -73,14 +71,14 @@ struct _snd_mpu401 {
unsigned long mode; /* MPU401_MODE_XXXX */
int timer_invoked;
- int (*open_input) (mpu401_t * mpu);
- void (*close_input) (mpu401_t * mpu);
- int (*open_output) (mpu401_t * mpu);
- void (*close_output) (mpu401_t * mpu);
+ int (*open_input) (struct snd_mpu401 * mpu);
+ void (*close_input) (struct snd_mpu401 * mpu);
+ int (*open_output) (struct snd_mpu401 * mpu);
+ void (*close_output) (struct snd_mpu401 * mpu);
void *private_data;
- snd_rawmidi_substream_t *substream_input;
- snd_rawmidi_substream_t *substream_output;
+ struct snd_rawmidi_substream *substream_input;
+ struct snd_rawmidi_substream *substream_output;
spinlock_t input_lock;
spinlock_t output_lock;
@@ -88,8 +86,8 @@ struct _snd_mpu401 {
struct timer_list timer;
- void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
- unsigned char (*read) (mpu401_t * mpu, unsigned long addr);
+ void (*write) (struct snd_mpu401 * mpu, unsigned char data, unsigned long addr);
+ unsigned char (*read) (struct snd_mpu401 *mpu, unsigned long addr);
};
/* I/O ports */
@@ -103,13 +101,13 @@ struct _snd_mpu401 {
irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int snd_mpu401_uart_new(snd_card_t * card,
+int snd_mpu401_uart_new(struct snd_card *card,
int device,
unsigned short hardware,
unsigned long port,
int integrated,
int irq,
int irq_flags,
- snd_rawmidi_t ** rrawmidi);
+ struct snd_rawmidi ** rrawmidi);
#endif /* __SOUND_MPU401_H */
diff --git a/include/sound/opl3.h b/include/sound/opl3.h
index 19f657d4fc06..83392641cb47 100644
--- a/include/sound/opl3.h
+++ b/include/sound/opl3.h
@@ -237,12 +237,12 @@
#define MAX_OPL2_VOICES 9
#define MAX_OPL3_VOICES 18
-typedef struct snd_opl3 opl3_t;
+struct snd_opl3;
/*
* A structure to keep track of each hardware voice
*/
-typedef struct snd_opl3_voice {
+struct snd_opl3_voice {
int state; /* status */
#define SNDRV_OPL3_ST_OFF 0 /* Not playing */
#define SNDRV_OPL3_ST_ON_2OP 1 /* 2op voice is allocated */
@@ -257,8 +257,8 @@ typedef struct snd_opl3_voice {
unsigned char keyon_reg; /* KON register shadow */
- snd_midi_channel_t *chan; /* Midi channel for this note */
-} snd_opl3_voice_t;
+ struct snd_midi_channel *chan; /* Midi channel for this note */
+};
struct snd_opl3 {
unsigned long l_port;
@@ -267,18 +267,18 @@ struct snd_opl3 {
struct resource *res_r_port;
unsigned short hardware;
/* hardware access */
- void (*command) (opl3_t * opl3, unsigned short cmd, unsigned char val);
+ void (*command) (struct snd_opl3 * opl3, unsigned short cmd, unsigned char val);
unsigned short timer_enable;
int seq_dev_num; /* sequencer device number */
- snd_timer_t *timer1;
- snd_timer_t *timer2;
+ struct snd_timer *timer1;
+ struct snd_timer *timer2;
spinlock_t timer_lock;
void *private_data;
- void (*private_free)(opl3_t *);
+ void (*private_free)(struct snd_opl3 *);
spinlock_t reg_lock;
- snd_card_t *card; /* The card that this belongs to */
+ struct snd_card *card; /* The card that this belongs to */
int used; /* usage flag - exclusive */
unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */
unsigned char rhythm; /* percussion mode flag */
@@ -289,18 +289,18 @@ struct snd_opl3 {
int synth_mode; /* synth mode */
int seq_client;
- snd_seq_device_t *seq_dev; /* sequencer device */
- snd_midi_channel_set_t * chset;
+ struct snd_seq_device *seq_dev; /* sequencer device */
+ struct snd_midi_channel_set * chset;
#ifdef CONFIG_SND_SEQUENCER_OSS
- snd_seq_device_t *oss_seq_dev; /* OSS sequencer device */
- snd_midi_channel_set_t * oss_chset;
+ struct snd_seq_device *oss_seq_dev; /* OSS sequencer device */
+ struct snd_midi_channel_set * oss_chset;
#endif
- snd_seq_kinstr_ops_t fm_ops;
- snd_seq_kinstr_list_t *ilist;
+ struct snd_seq_kinstr_ops fm_ops;
+ struct snd_seq_kinstr_list *ilist;
- snd_opl3_voice_t voices[MAX_OPL3_VOICES]; /* Voices (OPL3 'channel') */
+ struct snd_opl3_voice voices[MAX_OPL3_VOICES]; /* Voices (OPL3 'channel') */
int use_time; /* allocation counter */
unsigned short connection_reg; /* connection reg shadow */
@@ -316,24 +316,25 @@ struct snd_opl3 {
};
/* opl3.c */
-void snd_opl3_interrupt(snd_hwdep_t * hw);
-int snd_opl3_new(snd_card_t *card, unsigned short hardware, opl3_t **ropl3);
-int snd_opl3_init(opl3_t *opl3);
-int snd_opl3_create(snd_card_t * card,
+void snd_opl3_interrupt(struct snd_hwdep * hw);
+int snd_opl3_new(struct snd_card *card, unsigned short hardware,
+ struct snd_opl3 **ropl3);
+int snd_opl3_init(struct snd_opl3 *opl3);
+int snd_opl3_create(struct snd_card *card,
unsigned long l_port, unsigned long r_port,
unsigned short hardware,
int integrated,
- opl3_t ** opl3);
-int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev);
-int snd_opl3_hwdep_new(opl3_t * opl3, int device, int seq_device,
- snd_hwdep_t ** rhwdep);
+ struct snd_opl3 ** opl3);
+int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev);
+int snd_opl3_hwdep_new(struct snd_opl3 * opl3, int device, int seq_device,
+ struct snd_hwdep ** rhwdep);
/* opl3_synth */
-int snd_opl3_open(snd_hwdep_t * hw, struct file *file);
-int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
+int snd_opl3_open(struct snd_hwdep * hw, struct file *file);
+int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg);
-int snd_opl3_release(snd_hwdep_t * hw, struct file *file);
+int snd_opl3_release(struct snd_hwdep * hw, struct file *file);
-void snd_opl3_reset(opl3_t * opl3);
+void snd_opl3_reset(struct snd_opl3 * opl3);
#endif /* __SOUND_OPL3_H */
diff --git a/include/sound/opl4.h b/include/sound/opl4.h
index 20c04428b139..60ae8454b3ce 100644
--- a/include/sound/opl4.h
+++ b/include/sound/opl4.h
@@ -22,11 +22,11 @@
#include <sound/opl3.h>
-typedef struct opl4 opl4_t;
+struct snd_opl4;
-extern int snd_opl4_create(snd_card_t *card,
+extern int snd_opl4_create(struct snd_card *card,
unsigned long fm_port, unsigned long pcm_port,
int seq_device,
- opl3_t **opl3, opl4_t **opl4);
+ struct snd_opl3 **opl3, struct snd_opl4 **opl4);
#endif /* __SOUND_OPL4_H */
diff --git a/include/sound/pcm-indirect.h b/include/sound/pcm-indirect.h
index 31fa7a54508a..7003d7702e26 100644
--- a/include/sound/pcm-indirect.h
+++ b/include/sound/pcm-indirect.h
@@ -24,7 +24,7 @@
#include <sound/pcm.h>
-typedef struct sndrv_pcm_indirect {
+struct snd_pcm_indirect {
unsigned int hw_buffer_size; /* Byte size of hardware buffer */
unsigned int hw_queue_size; /* Max queue size of hw buffer (0 = buffer size) */
unsigned int hw_data; /* Offset to next dst (or src) in hw ring buffer */
@@ -35,20 +35,20 @@ typedef struct sndrv_pcm_indirect {
unsigned int sw_io; /* Current software pointer in bytes */
int sw_ready; /* Bytes ready to be transferred to/from hw */
snd_pcm_uframes_t appl_ptr; /* Last seen appl_ptr */
-} snd_pcm_indirect_t;
+};
-typedef void (*snd_pcm_indirect_copy_t)(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes);
+typedef void (*snd_pcm_indirect_copy_t)(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes);
/*
* helper function for playback ack callback
*/
static inline void
-snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec,
+snd_pcm_indirect_playback_transfer(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec,
snd_pcm_indirect_copy_t copy)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
int qsize;
@@ -89,8 +89,8 @@ snd_pcm_indirect_playback_transfer(snd_pcm_substream_t *substream,
* ptr = current byte pointer
*/
static inline snd_pcm_uframes_t
-snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, unsigned int ptr)
+snd_pcm_indirect_playback_pointer(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, unsigned int ptr)
{
int bytes = ptr - rec->hw_io;
if (bytes < 0)
@@ -110,11 +110,11 @@ snd_pcm_indirect_playback_pointer(snd_pcm_substream_t *substream,
* helper function for capture ack callback
*/
static inline void
-snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec,
+snd_pcm_indirect_capture_transfer(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec,
snd_pcm_indirect_copy_t copy)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
snd_pcm_sframes_t diff = appl_ptr - rec->appl_ptr;
@@ -154,8 +154,8 @@ snd_pcm_indirect_capture_transfer(snd_pcm_substream_t *substream,
* ptr = current byte pointer
*/
static inline snd_pcm_uframes_t
-snd_pcm_indirect_capture_pointer(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, unsigned int ptr)
+snd_pcm_indirect_capture_pointer(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, unsigned int ptr)
{
int qsize;
int bytes = ptr - rec->hw_io;
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index acc4fa9d5abe..314268a11048 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -28,36 +28,9 @@
#include <linux/poll.h>
#include <linux/bitops.h>
-typedef sndrv_pcm_uframes_t snd_pcm_uframes_t;
-typedef sndrv_pcm_sframes_t snd_pcm_sframes_t;
-typedef enum sndrv_pcm_class snd_pcm_class_t;
-typedef enum sndrv_pcm_subclass snd_pcm_subclass_t;
-typedef enum sndrv_pcm_stream snd_pcm_stream_t;
-typedef enum sndrv_pcm_access snd_pcm_access_t;
-typedef enum sndrv_pcm_format snd_pcm_format_t;
-typedef enum sndrv_pcm_subformat snd_pcm_subformat_t;
-typedef enum sndrv_pcm_state snd_pcm_state_t;
-typedef union sndrv_pcm_sync_id snd_pcm_sync_id_t;
-typedef struct sndrv_pcm_info snd_pcm_info_t;
-typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t;
-typedef struct sndrv_pcm_hw_params snd_pcm_hw_params_t;
-typedef enum sndrv_pcm_start snd_pcm_start_t;
-typedef enum sndrv_pcm_xrun snd_pcm_xrun_t;
-typedef enum sndrv_pcm_tstamp snd_pcm_tstamp_t;
-typedef struct sndrv_pcm_sw_params snd_pcm_sw_params_t;
-typedef struct sndrv_pcm_channel_info snd_pcm_channel_info_t;
-typedef struct sndrv_pcm_status snd_pcm_status_t;
-typedef struct sndrv_pcm_mmap_status snd_pcm_mmap_status_t;
-typedef struct sndrv_pcm_mmap_control snd_pcm_mmap_control_t;
-typedef struct sndrv_mask snd_mask_t;
-typedef struct snd_sg_buf snd_pcm_sgbuf_t;
-
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
#define snd_pcm_chip(pcm) ((pcm)->private_data)
-typedef struct _snd_pcm_file snd_pcm_file_t;
-typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
-
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
#include "pcm_oss.h"
#endif
@@ -66,7 +39,7 @@ typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
* Hardware (lowlevel) section
*/
-typedef struct _snd_pcm_hardware {
+struct snd_pcm_hardware {
unsigned int info; /* SNDRV_PCM_INFO_* */
u64 formats; /* SNDRV_PCM_FMTBIT_* */
unsigned int rates; /* SNDRV_PCM_RATE_* */
@@ -80,26 +53,29 @@ typedef struct _snd_pcm_hardware {
unsigned int periods_min; /* min # of periods */
unsigned int periods_max; /* max # of periods */
size_t fifo_size; /* fifo size in bytes */
-} snd_pcm_hardware_t;
+};
-typedef struct _snd_pcm_ops {
- int (*open)(snd_pcm_substream_t *substream);
- int (*close)(snd_pcm_substream_t *substream);
- int (*ioctl)(snd_pcm_substream_t * substream,
+struct snd_pcm_ops {
+ int (*open)(struct snd_pcm_substream *substream);
+ int (*close)(struct snd_pcm_substream *substream);
+ int (*ioctl)(struct snd_pcm_substream * substream,
unsigned int cmd, void *arg);
- int (*hw_params)(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * params);
- int (*hw_free)(snd_pcm_substream_t *substream);
- int (*prepare)(snd_pcm_substream_t * substream);
- int (*trigger)(snd_pcm_substream_t * substream, int cmd);
- snd_pcm_uframes_t (*pointer)(snd_pcm_substream_t * substream);
- int (*copy)(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t pos,
+ int (*hw_params)(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+ int (*hw_free)(struct snd_pcm_substream *substream);
+ int (*prepare)(struct snd_pcm_substream *substream);
+ int (*trigger)(struct snd_pcm_substream *substream, int cmd);
+ snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
+ int (*copy)(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos,
void __user *buf, snd_pcm_uframes_t count);
- int (*silence)(snd_pcm_substream_t *substream, int channel,
+ int (*silence)(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
- struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
- int (*mmap)(snd_pcm_substream_t *substream, struct vm_area_struct *vma);
- int (*ack)(snd_pcm_substream_t *substream);
-} snd_pcm_ops_t;
+ struct page *(*page)(struct snd_pcm_substream *substream,
+ unsigned long offset);
+ int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
+ int (*ack)(struct snd_pcm_substream *substream);
+};
/*
*
@@ -212,17 +188,16 @@ typedef struct _snd_pcm_ops {
#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE
#endif
-struct _snd_pcm_file {
- snd_pcm_substream_t * substream;
- struct _snd_pcm_file * next;
+struct snd_pcm_file {
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_file *next;
};
-typedef struct _snd_pcm_hw_rule snd_pcm_hw_rule_t;
+struct snd_pcm_hw_rule;
+typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule);
-typedef int (*snd_pcm_hw_rule_func_t)(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule);
-
-struct _snd_pcm_hw_rule {
+struct snd_pcm_hw_rule {
unsigned int cond;
snd_pcm_hw_rule_func_t func;
int var;
@@ -230,57 +205,57 @@ struct _snd_pcm_hw_rule {
void *private;
};
-typedef struct _snd_pcm_hw_constraints {
- snd_mask_t masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+struct snd_pcm_hw_constraints {
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
- snd_interval_t intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
unsigned int rules_num;
unsigned int rules_all;
- snd_pcm_hw_rule_t *rules;
-} snd_pcm_hw_constraints_t;
+ struct snd_pcm_hw_rule *rules;
+};
-static inline snd_mask_t *constrs_mask(snd_pcm_hw_constraints_t *constrs,
- snd_pcm_hw_param_t var)
+static inline struct snd_mask *constrs_mask(struct snd_pcm_hw_constraints *constrs,
+ snd_pcm_hw_param_t var)
{
return &constrs->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
}
-static inline snd_interval_t *constrs_interval(snd_pcm_hw_constraints_t *constrs,
- snd_pcm_hw_param_t var)
+static inline struct snd_interval *constrs_interval(struct snd_pcm_hw_constraints *constrs,
+ snd_pcm_hw_param_t var)
{
return &constrs->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
}
-typedef struct {
+struct snd_ratnum {
unsigned int num;
unsigned int den_min, den_max, den_step;
-} ratnum_t;
+};
-typedef struct {
+struct snd_ratden {
unsigned int num_min, num_max, num_step;
unsigned int den;
-} ratden_t;
+};
-typedef struct {
+struct snd_pcm_hw_constraint_ratnums {
int nrats;
- ratnum_t *rats;
-} snd_pcm_hw_constraint_ratnums_t;
+ struct snd_ratnum *rats;
+};
-typedef struct {
+struct snd_pcm_hw_constraint_ratdens {
int nrats;
- ratden_t *rats;
-} snd_pcm_hw_constraint_ratdens_t;
+ struct snd_ratden *rats;
+};
-typedef struct {
+struct snd_pcm_hw_constraint_list {
unsigned int count;
unsigned int *list;
unsigned int mask;
-} snd_pcm_hw_constraint_list_t;
+};
-struct _snd_pcm_runtime {
+struct snd_pcm_runtime {
/* -- Status -- */
- snd_pcm_substream_t *trigger_master;
+ struct snd_pcm_substream *trigger_master;
struct timespec trigger_tstamp; /* trigger timestamp */
int overrange;
snd_pcm_uframes_t avail_max;
@@ -306,7 +281,7 @@ struct _snd_pcm_runtime {
unsigned int rate_den;
/* -- SW params -- */
- snd_pcm_tstamp_t tstamp_mode; /* mmap timestamp is updated */
+ int tstamp_mode; /* mmap timestamp is updated */
unsigned int period_step;
unsigned int sleep_min; /* min ticks to sleep */
snd_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */
@@ -320,11 +295,11 @@ struct _snd_pcm_runtime {
snd_pcm_uframes_t silence_start; /* starting pointer to silence area */
snd_pcm_uframes_t silence_filled; /* size filled with silence */
- snd_pcm_sync_id_t sync; /* hardware synchronization ID */
+ union snd_pcm_sync_id sync; /* hardware synchronization ID */
/* -- mmap -- */
- volatile snd_pcm_mmap_status_t *status;
- volatile snd_pcm_mmap_control_t *control;
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
atomic_t mmap_count;
/* -- locking / scheduling -- */
@@ -334,15 +309,15 @@ struct _snd_pcm_runtime {
/* -- private section -- */
void *private_data;
- void (*private_free)(snd_pcm_runtime_t *runtime);
+ void (*private_free)(struct snd_pcm_runtime *runtime);
/* -- hardware description -- */
- snd_pcm_hardware_t hw;
- snd_pcm_hw_constraints_t hw_constraints;
+ struct snd_pcm_hardware hw;
+ struct snd_pcm_hw_constraints hw_constraints;
/* -- interrupt callbacks -- */
- void (*transfer_ack_begin)(snd_pcm_substream_t *substream);
- void (*transfer_ack_end)(snd_pcm_substream_t *substream);
+ void (*transfer_ack_begin)(struct snd_pcm_substream *substream);
+ void (*transfer_ack_end)(struct snd_pcm_substream *substream);
/* -- timer -- */
unsigned int timer_resolution; /* timer resolution */
@@ -356,19 +331,19 @@ struct _snd_pcm_runtime {
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
- snd_pcm_oss_runtime_t oss;
+ struct snd_pcm_oss_runtime oss;
#endif
};
-typedef struct _snd_pcm_group { /* keep linked substreams */
+struct snd_pcm_group { /* keep linked substreams */
spinlock_t lock;
struct list_head substreams;
int count;
-} snd_pcm_group_t;
+};
-struct _snd_pcm_substream {
- snd_pcm_t *pcm;
- snd_pcm_str_t *pstr;
+struct snd_pcm_substream {
+ struct snd_pcm *pcm;
+ struct snd_pcm_str *pstr;
void *private_data; /* copied from pcm->private_data */
int number;
char name[32]; /* substream name */
@@ -378,32 +353,32 @@ struct _snd_pcm_substream {
unsigned int dma_buf_id;
size_t dma_max;
/* -- hardware operations -- */
- snd_pcm_ops_t *ops;
+ struct snd_pcm_ops *ops;
/* -- runtime information -- */
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
/* -- timer section -- */
- snd_timer_t *timer; /* timer */
+ struct snd_timer *timer; /* timer */
unsigned timer_running: 1; /* time is running */
spinlock_t timer_lock;
/* -- next substream -- */
- snd_pcm_substream_t *next;
+ struct snd_pcm_substream *next;
/* -- linked substreams -- */
struct list_head link_list; /* linked list member */
- snd_pcm_group_t self_group; /* fake group for non linked substream (with substream lock inside) */
- snd_pcm_group_t *group; /* pointer to current group */
+ struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */
+ struct snd_pcm_group *group; /* pointer to current group */
/* -- assigned files -- */
- snd_pcm_file_t *file;
+ struct snd_pcm_file *file;
struct file *ffile;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
- snd_pcm_oss_substream_t oss;
+ struct snd_pcm_oss_substream oss;
#endif
- snd_info_entry_t *proc_root;
- snd_info_entry_t *proc_info_entry;
- snd_info_entry_t *proc_hw_params_entry;
- snd_info_entry_t *proc_sw_params_entry;
- snd_info_entry_t *proc_status_entry;
- snd_info_entry_t *proc_prealloc_entry;
+ struct snd_info_entry *proc_root;
+ struct snd_info_entry *proc_info_entry;
+ struct snd_info_entry *proc_hw_params_entry;
+ struct snd_info_entry *proc_sw_params_entry;
+ struct snd_info_entry *proc_status_entry;
+ struct snd_info_entry *proc_prealloc_entry;
/* misc flags */
unsigned int no_mmap_ctrl: 1;
};
@@ -415,65 +390,64 @@ struct _snd_pcm_substream {
#endif
-struct _snd_pcm_str {
+struct snd_pcm_str {
int stream; /* stream (direction) */
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
/* -- substreams -- */
unsigned int substream_count;
unsigned int substream_opened;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
/* -- OSS things -- */
- snd_pcm_oss_stream_t oss;
+ struct snd_pcm_oss_stream oss;
#endif
- snd_pcm_file_t *files;
- snd_minor_t *reg;
- snd_info_entry_t *proc_root;
- snd_info_entry_t *proc_info_entry;
+ struct snd_pcm_file *files;
+ struct snd_info_entry *proc_root;
+ struct snd_info_entry *proc_info_entry;
#ifdef CONFIG_SND_DEBUG
unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */
- snd_info_entry_t *proc_xrun_debug_entry;
+ struct snd_info_entry *proc_xrun_debug_entry;
#endif
};
-struct _snd_pcm {
- snd_card_t *card;
+struct snd_pcm {
+ struct snd_card *card;
+ struct list_head list;
unsigned int device; /* device number */
unsigned int info_flags;
unsigned short dev_class;
unsigned short dev_subclass;
char id[64];
char name[80];
- snd_pcm_str_t streams[2];
+ struct snd_pcm_str streams[2];
struct semaphore open_mutex;
wait_queue_head_t open_wait;
void *private_data;
- void (*private_free) (snd_pcm_t *pcm);
+ void (*private_free) (struct snd_pcm *pcm);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- snd_pcm_oss_t oss;
+ struct snd_pcm_oss oss;
#endif
};
-typedef struct _snd_pcm_notify {
- int (*n_register) (snd_pcm_t * pcm);
- int (*n_disconnect) (snd_pcm_t * pcm);
- int (*n_unregister) (snd_pcm_t * pcm);
+struct snd_pcm_notify {
+ int (*n_register) (struct snd_pcm * pcm);
+ int (*n_disconnect) (struct snd_pcm * pcm);
+ int (*n_unregister) (struct snd_pcm * pcm);
struct list_head list;
-} snd_pcm_notify_t;
+};
/*
* Registering
*/
-extern snd_pcm_t *snd_pcm_devices[];
-extern snd_minor_t snd_pcm_reg[2];
+extern struct file_operations snd_pcm_f_ops[2];
-int snd_pcm_new(snd_card_t * card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, char *id, int device,
int playback_count, int capture_count,
- snd_pcm_t **rpcm);
-int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count);
+ struct snd_pcm **rpcm);
+int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
-int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree);
+int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
/*
* Native I/O
@@ -481,24 +455,26 @@ int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree);
extern rwlock_t snd_pcm_link_rwlock;
-int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info);
-int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t __user *info);
-int snd_pcm_status(snd_pcm_substream_t * substream, snd_pcm_status_t *status);
-int snd_pcm_prepare(snd_pcm_substream_t *substream);
-int snd_pcm_start(snd_pcm_substream_t *substream);
-int snd_pcm_stop(snd_pcm_substream_t *substream, int status);
-int snd_pcm_drain_done(snd_pcm_substream_t *substream);
+int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info);
+int snd_pcm_info_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_info __user *info);
+int snd_pcm_status(struct snd_pcm_substream *substream,
+ struct snd_pcm_status *status);
+int snd_pcm_prepare(struct snd_pcm_substream *substream);
+int snd_pcm_start(struct snd_pcm_substream *substream);
+int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
+int snd_pcm_drain_done(struct snd_pcm_substream *substream);
#ifdef CONFIG_PM
-int snd_pcm_suspend(snd_pcm_substream_t *substream);
-int snd_pcm_suspend_all(snd_pcm_t *pcm);
+int snd_pcm_suspend(struct snd_pcm_substream *substream);
+int snd_pcm_suspend_all(struct snd_pcm *pcm);
#endif
-int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream, unsigned int cmd, void *arg);
-int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream, unsigned int cmd, void *arg);
-int snd_pcm_kernel_ioctl(snd_pcm_substream_t *substream, unsigned int cmd, void *arg);
-int snd_pcm_open_substream(snd_pcm_t *pcm, int stream, snd_pcm_substream_t **rsubstream);
-void snd_pcm_release_substream(snd_pcm_substream_t *substream);
+int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
+int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
+int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg);
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct snd_pcm_substream **rsubstream);
+void snd_pcm_release_substream(struct snd_pcm_substream *substream);
void snd_pcm_vma_notify_data(void *client, void *data);
-int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file, struct vm_area_struct *area);
+int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
#if BITS_PER_LONG >= 64
@@ -578,30 +554,30 @@ static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
* PCM library
*/
-static inline int snd_pcm_stream_linked(snd_pcm_substream_t *substream)
+static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream)
{
return substream->group != &substream->self_group;
}
-static inline void snd_pcm_stream_lock(snd_pcm_substream_t *substream)
+static inline void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
read_lock(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
-static inline void snd_pcm_stream_unlock(snd_pcm_substream_t *substream)
+static inline void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
spin_unlock(&substream->self_group.lock);
read_unlock(&snd_pcm_link_rwlock);
}
-static inline void snd_pcm_stream_lock_irq(snd_pcm_substream_t *substream)
+static inline void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
read_lock_irq(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
-static inline void snd_pcm_stream_unlock_irq(snd_pcm_substream_t *substream)
+static inline void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
spin_unlock(&substream->self_group.lock);
read_unlock_irq(&snd_pcm_link_rwlock);
@@ -623,56 +599,56 @@ do { \
list_for_each(pos, &substream->group->substreams)
#define snd_pcm_group_substream_entry(pos) \
- list_entry(pos, snd_pcm_substream_t, link_list)
+ list_entry(pos, struct snd_pcm_substream, link_list)
-static inline int snd_pcm_running(snd_pcm_substream_t *substream)
+static inline int snd_pcm_running(struct snd_pcm_substream *substream)
{
return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
(substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
substream->stream == SNDRV_PCM_STREAM_PLAYBACK));
}
-static inline ssize_t bytes_to_samples(snd_pcm_runtime_t *runtime, ssize_t size)
+static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t size)
{
return size * 8 / runtime->sample_bits;
}
-static inline snd_pcm_sframes_t bytes_to_frames(snd_pcm_runtime_t *runtime, ssize_t size)
+static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, ssize_t size)
{
return size * 8 / runtime->frame_bits;
}
-static inline ssize_t samples_to_bytes(snd_pcm_runtime_t *runtime, ssize_t size)
+static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t size)
{
return size * runtime->sample_bits / 8;
}
-static inline ssize_t frames_to_bytes(snd_pcm_runtime_t *runtime, snd_pcm_sframes_t size)
+static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size)
{
return size * runtime->frame_bits / 8;
}
-static inline int frame_aligned(snd_pcm_runtime_t *runtime, ssize_t bytes)
+static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes)
{
return bytes % runtime->byte_align == 0;
}
-static inline size_t snd_pcm_lib_buffer_bytes(snd_pcm_substream_t *substream)
+static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return frames_to_bytes(runtime, runtime->buffer_size);
}
-static inline size_t snd_pcm_lib_period_bytes(snd_pcm_substream_t *substream)
+static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return frames_to_bytes(runtime, runtime->period_size);
}
/*
* result is: 0 ... (boundary - 1)
*/
-static inline snd_pcm_uframes_t snd_pcm_playback_avail(snd_pcm_runtime_t *runtime)
+static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *runtime)
{
snd_pcm_sframes_t avail = runtime->status->hw_ptr + runtime->buffer_size - runtime->control->appl_ptr;
if (avail < 0)
@@ -685,7 +661,7 @@ static inline snd_pcm_uframes_t snd_pcm_playback_avail(snd_pcm_runtime_t *runtim
/*
* result is: 0 ... (boundary - 1)
*/
-static inline snd_pcm_uframes_t snd_pcm_capture_avail(snd_pcm_runtime_t *runtime)
+static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *runtime)
{
snd_pcm_sframes_t avail = runtime->status->hw_ptr - runtime->control->appl_ptr;
if (avail < 0)
@@ -693,12 +669,12 @@ static inline snd_pcm_uframes_t snd_pcm_capture_avail(snd_pcm_runtime_t *runtime
return avail;
}
-static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(snd_pcm_runtime_t *runtime)
+static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime *runtime)
{
return runtime->buffer_size - snd_pcm_playback_avail(runtime);
}
-static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(snd_pcm_runtime_t *runtime)
+static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime *runtime)
{
return runtime->buffer_size - snd_pcm_capture_avail(runtime);
}
@@ -711,9 +687,9 @@ static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(snd_pcm_runtime_t *runt
*
* Returns non-zero if available, or zero if not.
*/
-static inline int snd_pcm_playback_ready(snd_pcm_substream_t *substream)
+static inline int snd_pcm_playback_ready(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return snd_pcm_playback_avail(runtime) >= runtime->control->avail_min;
}
@@ -725,9 +701,9 @@ static inline int snd_pcm_playback_ready(snd_pcm_substream_t *substream)
*
* Returns non-zero if available, or zero if not.
*/
-static inline int snd_pcm_capture_ready(snd_pcm_substream_t *substream)
+static inline int snd_pcm_capture_ready(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return snd_pcm_capture_avail(runtime) >= runtime->control->avail_min;
}
@@ -740,9 +716,9 @@ static inline int snd_pcm_capture_ready(snd_pcm_substream_t *substream)
*
* Returns non-zero if exists, or zero if not.
*/
-static inline int snd_pcm_playback_data(snd_pcm_substream_t *substream)
+static inline int snd_pcm_playback_data(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->stop_threshold >= runtime->boundary)
return 1;
@@ -757,9 +733,9 @@ static inline int snd_pcm_playback_data(snd_pcm_substream_t *substream)
*
* Returns non-zero if empty, or zero if not.
*/
-static inline int snd_pcm_playback_empty(snd_pcm_substream_t *substream)
+static inline int snd_pcm_playback_empty(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return snd_pcm_playback_avail(runtime) >= runtime->buffer_size;
}
@@ -771,14 +747,14 @@ static inline int snd_pcm_playback_empty(snd_pcm_substream_t *substream)
*
* Returns non-zero if empty, or zero if not.
*/
-static inline int snd_pcm_capture_empty(snd_pcm_substream_t *substream)
+static inline int snd_pcm_capture_empty(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return snd_pcm_capture_avail(runtime) == 0;
}
-static inline void snd_pcm_trigger_done(snd_pcm_substream_t *substream,
- snd_pcm_substream_t *master)
+static inline void snd_pcm_trigger_done(struct snd_pcm_substream *substream,
+ struct snd_pcm_substream *master)
{
substream->runtime->trigger_master = master;
}
@@ -795,28 +771,28 @@ static inline int hw_is_interval(int var)
var <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL;
}
-static inline snd_mask_t *hw_param_mask(snd_pcm_hw_params_t *params,
+static inline struct snd_mask *hw_param_mask(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
return &params->masks[var - SNDRV_PCM_HW_PARAM_FIRST_MASK];
}
-static inline snd_interval_t *hw_param_interval(snd_pcm_hw_params_t *params,
+static inline struct snd_interval *hw_param_interval(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
}
-static inline const snd_mask_t *hw_param_mask_c(const snd_pcm_hw_params_t *params,
+static inline const struct snd_mask *hw_param_mask_c(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
- return (const snd_mask_t *)hw_param_mask((snd_pcm_hw_params_t*) params, var);
+ return (const struct snd_mask *)hw_param_mask((struct snd_pcm_hw_params*) params, var);
}
-static inline const snd_interval_t *hw_param_interval_c(const snd_pcm_hw_params_t *params,
+static inline const struct snd_interval *hw_param_interval_c(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
- return (const snd_interval_t *)hw_param_interval((snd_pcm_hw_params_t*) params, var);
+ return (const struct snd_interval *)hw_param_interval((struct snd_pcm_hw_params*) params, var);
}
#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
@@ -832,66 +808,66 @@ static inline const snd_interval_t *hw_param_interval_c(const snd_pcm_hw_params_
#define params_tick_time(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_TICK_TIME)->min
-int snd_interval_refine(snd_interval_t *i, const snd_interval_t *v);
-void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
-void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c);
-void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
- unsigned int k, snd_interval_t *c);
-void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
- const snd_interval_t *b, snd_interval_t *c);
-int snd_interval_list(snd_interval_t *i, unsigned int count, unsigned int *list, unsigned int mask);
-int snd_interval_ratnum(snd_interval_t *i,
- unsigned int rats_count, ratnum_t *rats,
+int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v);
+void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b,
+ unsigned int k, struct snd_interval *c);
+void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+ const struct snd_interval *b, struct snd_interval *c);
+int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask);
+int snd_interval_ratnum(struct snd_interval *i,
+ unsigned int rats_count, struct snd_ratnum *rats,
unsigned int *nump, unsigned int *denp);
-void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
-void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_near(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
+void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
+void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var);
+int snd_pcm_hw_param_near(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
unsigned int val, int *dir);
-int snd_pcm_hw_param_set(snd_pcm_substream_t *pcm,
- snd_pcm_hw_params_t *params,
+int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var,
unsigned int val, int dir);
-int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
-int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
+int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
-int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
-int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
+int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
+int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
-int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
+int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int32_t mask);
-int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
+int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int64_t mask);
-int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var,
+int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max);
-int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t var);
-int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var);
+int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_list_t *l);
-int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime,
+ struct snd_pcm_hw_constraint_list *l);
+int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_ratnums_t *r);
-int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime,
+ struct snd_pcm_hw_constraint_ratnums *r);
+int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_ratdens_t *r);
-int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime,
+ struct snd_pcm_hw_constraint_ratdens *r);
+int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
unsigned int cond,
unsigned int width,
unsigned int msbits);
-int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
unsigned long step);
-int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var);
-int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime,
unsigned int cond,
int var,
snd_pcm_hw_rule_func_t func, void *private,
@@ -925,37 +901,37 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
const char *snd_pcm_format_name(snd_pcm_format_t format);
-void snd_pcm_set_ops(snd_pcm_t * pcm, int direction, snd_pcm_ops_t *ops);
-void snd_pcm_set_sync(snd_pcm_substream_t * substream);
-int snd_pcm_lib_interleave_len(snd_pcm_substream_t *substream);
-int snd_pcm_lib_ioctl(snd_pcm_substream_t *substream,
+void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, struct snd_pcm_ops *ops);
+void snd_pcm_set_sync(struct snd_pcm_substream *substream);
+int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream);
+int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
-int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream);
-int snd_pcm_playback_xrun_check(snd_pcm_substream_t *substream);
-int snd_pcm_capture_xrun_check(snd_pcm_substream_t *substream);
-int snd_pcm_playback_xrun_asap(snd_pcm_substream_t *substream);
-int snd_pcm_capture_xrun_asap(snd_pcm_substream_t *substream);
-void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr);
-void snd_pcm_tick_prepare(snd_pcm_substream_t *substream);
-void snd_pcm_tick_set(snd_pcm_substream_t *substream, unsigned long ticks);
-void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream);
-void snd_pcm_period_elapsed(snd_pcm_substream_t *substream);
-snd_pcm_sframes_t snd_pcm_lib_write(snd_pcm_substream_t *substream,
+int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream);
+int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream);
+int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream);
+int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream);
+void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr);
+void snd_pcm_tick_prepare(struct snd_pcm_substream *substream);
+void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks);
+void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream);
+void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
+snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
const void __user *buf,
snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_read(snd_pcm_substream_t *substream,
+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
void __user *buf, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_writev(snd_pcm_substream_t *substream,
+snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
void __user **bufs, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
+snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
void __user **bufs, snd_pcm_uframes_t frames);
-int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime);
+int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
-static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
+static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substream,
struct snd_dma_buffer *bufp)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (bufp) {
runtime->dma_buffer_p = bufp;
runtime->dma_area = bufp->area;
@@ -973,47 +949,47 @@ static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
* Timer interface
*/
-void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream);
-void snd_pcm_timer_init(snd_pcm_substream_t * substream);
-void snd_pcm_timer_done(snd_pcm_substream_t * substream);
+void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
+void snd_pcm_timer_init(struct snd_pcm_substream *substream);
+void snd_pcm_timer_done(struct snd_pcm_substream *substream);
/*
* Memory
*/
-int snd_pcm_lib_preallocate_free(snd_pcm_substream_t *substream);
-int snd_pcm_lib_preallocate_free_for_all(snd_pcm_t *pcm);
-int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
+int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream);
+int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm);
+int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
int type, struct device *data,
size_t size, size_t max);
-int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t *pcm,
+int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
int type, void *data,
size_t size, size_t max);
-int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size);
-int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream);
+int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
+int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
#define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
#define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
-struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
+struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset);
/* handle mmap counter - PCM mmap callback should handle this counter properly */
static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data;
atomic_inc(&substream->runtime->mmap_count);
}
static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+ struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data;
atomic_dec(&substream->runtime->mmap_count);
}
/* mmap for io-memory area */
#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
#define SNDRV_PCM_INFO_MMAP_IOMEM SNDRV_PCM_INFO_MMAP
-int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area);
+int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area);
#else
#define SNDRV_PCM_INFO_MMAP_IOMEM 0
#define snd_pcm_lib_mmap_iomem NULL
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 0b67c9d105af..fddaddde47b4 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -22,10 +22,7 @@
*
*/
-typedef struct _snd_pcm_plugin snd_pcm_plugin_t;
-typedef struct _snd_pcm_oss_setup snd_pcm_oss_setup_t;
-
-struct _snd_pcm_oss_setup {
+struct snd_pcm_oss_setup {
char *task_name;
unsigned int disable:1,
direct:1,
@@ -36,10 +33,10 @@ struct _snd_pcm_oss_setup {
buggyptr:1;
unsigned int periods;
unsigned int period_size;
- snd_pcm_oss_setup_t *next;
+ struct snd_pcm_oss_setup *next;
};
-typedef struct _snd_pcm_oss_runtime {
+struct snd_pcm_oss_runtime {
unsigned params: 1, /* format/parameter change */
prepare: 1, /* need to prepare the operation */
trigger: 1, /* trigger flag */
@@ -59,30 +56,30 @@ typedef struct _snd_pcm_oss_runtime {
size_t mmap_bytes;
char *buffer; /* vmallocated period */
size_t buffer_used; /* used length from period buffer */
- snd_pcm_plugin_t *plugin_first;
- snd_pcm_plugin_t *plugin_last;
+ struct snd_pcm_plugin *plugin_first;
+ struct snd_pcm_plugin *plugin_last;
unsigned int prev_hw_ptr_interrupt;
-} snd_pcm_oss_runtime_t;
+};
-typedef struct _snd_pcm_oss_file {
- snd_pcm_substream_t *streams[2];
-} snd_pcm_oss_file_t;
+struct snd_pcm_oss_file {
+ struct snd_pcm_substream *streams[2];
+};
-typedef struct _snd_pcm_oss_substream {
+struct snd_pcm_oss_substream {
unsigned oss: 1; /* oss mode */
- snd_pcm_oss_setup_t *setup; /* active setup */
- snd_pcm_oss_file_t *file;
-} snd_pcm_oss_substream_t;
+ struct snd_pcm_oss_setup *setup; /* active setup */
+ struct snd_pcm_oss_file *file;
+};
-typedef struct _snd_pcm_oss_stream {
- snd_pcm_oss_setup_t *setup_list; /* setup list */
+struct snd_pcm_oss_stream {
+ struct snd_pcm_oss_setup *setup_list; /* setup list */
struct semaphore setup_mutex;
- snd_info_entry_t *proc_entry;
-} snd_pcm_oss_stream_t;
+ struct snd_info_entry *proc_entry;
+};
-typedef struct _snd_pcm_oss {
+struct snd_pcm_oss {
int reg;
unsigned int reg_mask;
-} snd_pcm_oss_t;
+};
#endif /* __SOUND_PCM_OSS_H */
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h
index 60b0e92e26f3..fb18aef77341 100644
--- a/include/sound/pcm_params.h
+++ b/include/sound/pcm_params.h
@@ -22,17 +22,17 @@
*
*/
-extern int snd_pcm_hw_param_mask(snd_pcm_substream_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, const snd_mask_t *val);
-extern unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
+extern int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
+ snd_pcm_hw_param_t var, const struct snd_mask *val);
+extern unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir);
-extern unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
+extern unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir);
-extern int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
+extern int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir);
-extern int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
+extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var);
-extern int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
+extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir);
/* To share the same code we have alsa-lib */
@@ -71,20 +71,20 @@ INLINE unsigned int ld2(u_int32_t v)
INLINE size_t snd_mask_sizeof(void)
{
- return sizeof(snd_mask_t);
+ return sizeof(struct snd_mask);
}
-INLINE void snd_mask_none(snd_mask_t *mask)
+INLINE void snd_mask_none(struct snd_mask *mask)
{
memset(mask, 0, sizeof(*mask));
}
-INLINE void snd_mask_any(snd_mask_t *mask)
+INLINE void snd_mask_any(struct snd_mask *mask)
{
memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}
-INLINE int snd_mask_empty(const snd_mask_t *mask)
+INLINE int snd_mask_empty(const struct snd_mask *mask)
{
int i;
for (i = 0; i < SNDRV_MASK_SIZE; i++)
@@ -93,7 +93,7 @@ INLINE int snd_mask_empty(const snd_mask_t *mask)
return 1;
}
-INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
+INLINE unsigned int snd_mask_min(const struct snd_mask *mask)
{
int i;
assert(!snd_mask_empty(mask));
@@ -104,7 +104,7 @@ INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
return 0;
}
-INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
+INLINE unsigned int snd_mask_max(const struct snd_mask *mask)
{
int i;
assert(!snd_mask_empty(mask));
@@ -115,19 +115,19 @@ INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
return 0;
}
-INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val)
+INLINE void snd_mask_set(struct snd_mask *mask, unsigned int val)
{
assert(val <= SNDRV_MASK_BITS);
mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
}
-INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val)
+INLINE void snd_mask_reset(struct snd_mask *mask, unsigned int val)
{
assert(val <= SNDRV_MASK_BITS);
mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
}
-INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to)
+INLINE void snd_mask_set_range(struct snd_mask *mask, unsigned int from, unsigned int to)
{
unsigned int i;
assert(to <= SNDRV_MASK_BITS && from <= to);
@@ -135,7 +135,7 @@ INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int
mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
}
-INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to)
+INLINE void snd_mask_reset_range(struct snd_mask *mask, unsigned int from, unsigned int to)
{
unsigned int i;
assert(to <= SNDRV_MASK_BITS && from <= to);
@@ -143,7 +143,7 @@ INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned i
mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
}
-INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
+INLINE void snd_mask_leave(struct snd_mask *mask, unsigned int val)
{
unsigned int v;
assert(val <= SNDRV_MASK_BITS);
@@ -152,30 +152,30 @@ INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
mask->bits[MASK_OFS(val)] = v;
}
-INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v)
+INLINE void snd_mask_intersect(struct snd_mask *mask, const struct snd_mask *v)
{
int i;
for (i = 0; i < SNDRV_MASK_SIZE; i++)
mask->bits[i] &= v->bits[i];
}
-INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v)
+INLINE int snd_mask_eq(const struct snd_mask *mask, const struct snd_mask *v)
{
return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
}
-INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v)
+INLINE void snd_mask_copy(struct snd_mask *mask, const struct snd_mask *v)
{
*mask = *v;
}
-INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val)
+INLINE int snd_mask_test(const struct snd_mask *mask, unsigned int val)
{
assert(val <= SNDRV_MASK_BITS);
return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
}
-INLINE int snd_mask_single(const snd_mask_t *mask)
+INLINE int snd_mask_single(const struct snd_mask *mask)
{
int i, c = 0;
assert(!snd_mask_empty(mask));
@@ -191,9 +191,9 @@ INLINE int snd_mask_single(const snd_mask_t *mask)
return 1;
}
-INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v)
+INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v)
{
- snd_mask_t old;
+ struct snd_mask old;
assert(!snd_mask_empty(mask));
snd_mask_copy(&old, mask);
snd_mask_intersect(mask, v);
@@ -202,7 +202,7 @@ INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v)
return !snd_mask_eq(mask, &old);
}
-INLINE int snd_mask_refine_first(snd_mask_t *mask)
+INLINE int snd_mask_refine_first(struct snd_mask *mask)
{
assert(!snd_mask_empty(mask));
if (snd_mask_single(mask))
@@ -211,7 +211,7 @@ INLINE int snd_mask_refine_first(snd_mask_t *mask)
return 1;
}
-INLINE int snd_mask_refine_last(snd_mask_t *mask)
+INLINE int snd_mask_refine_last(struct snd_mask *mask)
{
assert(!snd_mask_empty(mask));
if (snd_mask_single(mask))
@@ -220,7 +220,7 @@ INLINE int snd_mask_refine_last(snd_mask_t *mask)
return 1;
}
-INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val)
+INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
{
assert(!snd_mask_empty(mask));
if (snd_mask_min(mask) >= val)
@@ -231,7 +231,7 @@ INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val)
return 1;
}
-INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
+INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
{
assert(!snd_mask_empty(mask));
if (snd_mask_max(mask) <= val)
@@ -242,7 +242,7 @@ INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
return 1;
}
-INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val)
+INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
{
int changed;
assert(!snd_mask_empty(mask));
@@ -253,13 +253,13 @@ INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val)
return changed;
}
-INLINE int snd_mask_value(const snd_mask_t *mask)
+INLINE int snd_mask_value(const struct snd_mask *mask)
{
assert(!snd_mask_empty(mask));
return snd_mask_min(mask);
}
-INLINE void snd_interval_any(snd_interval_t *i)
+INLINE void snd_interval_any(struct snd_interval *i)
{
i->min = 0;
i->openmin = 0;
@@ -269,42 +269,42 @@ INLINE void snd_interval_any(snd_interval_t *i)
i->empty = 0;
}
-INLINE void snd_interval_none(snd_interval_t *i)
+INLINE void snd_interval_none(struct snd_interval *i)
{
i->empty = 1;
}
-INLINE int snd_interval_checkempty(const snd_interval_t *i)
+INLINE int snd_interval_checkempty(const struct snd_interval *i)
{
return (i->min > i->max ||
(i->min == i->max && (i->openmin || i->openmax)));
}
-INLINE int snd_interval_empty(const snd_interval_t *i)
+INLINE int snd_interval_empty(const struct snd_interval *i)
{
return i->empty;
}
-INLINE int snd_interval_single(const snd_interval_t *i)
+INLINE int snd_interval_single(const struct snd_interval *i)
{
assert(!snd_interval_empty(i));
return (i->min == i->max ||
(i->min + 1 == i->max && i->openmax));
}
-INLINE int snd_interval_value(const snd_interval_t *i)
+INLINE int snd_interval_value(const struct snd_interval *i)
{
assert(snd_interval_single(i));
return i->min;
}
-INLINE int snd_interval_min(const snd_interval_t *i)
+INLINE int snd_interval_min(const struct snd_interval *i)
{
assert(!snd_interval_empty(i));
return i->min;
}
-INLINE int snd_interval_max(const snd_interval_t *i)
+INLINE int snd_interval_max(const struct snd_interval *i)
{
unsigned int v;
assert(!snd_interval_empty(i));
@@ -314,18 +314,18 @@ INLINE int snd_interval_max(const snd_interval_t *i)
return v;
}
-INLINE int snd_interval_test(const snd_interval_t *i, unsigned int val)
+INLINE int snd_interval_test(const struct snd_interval *i, unsigned int val)
{
return !((i->min > val || (i->min == val && i->openmin) ||
i->max < val || (i->max == val && i->openmax)));
}
-INLINE void snd_interval_copy(snd_interval_t *d, const snd_interval_t *s)
+INLINE void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
{
*d = *s;
}
-INLINE int snd_interval_setinteger(snd_interval_t *i)
+INLINE int snd_interval_setinteger(struct snd_interval *i)
{
if (i->integer)
return 0;
@@ -335,7 +335,7 @@ INLINE int snd_interval_setinteger(snd_interval_t *i)
return 1;
}
-INLINE int snd_interval_eq(const snd_interval_t *i1, const snd_interval_t *i2)
+INLINE int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
{
if (i1->empty)
return i2->empty;
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 3f9db510dee3..d19bddfbf995 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -36,11 +36,6 @@
* Raw MIDI interface
*/
-typedef enum sndrv_rawmidi_stream snd_rawmidi_stream_t;
-typedef struct sndrv_rawmidi_info snd_rawmidi_info_t;
-typedef struct sndrv_rawmidi_params snd_rawmidi_params_t;
-typedef struct sndrv_rawmidi_status snd_rawmidi_status_t;
-
#define SNDRV_RAWMIDI_DEVICES 8
#define SNDRV_RAWMIDI_LFLG_OUTPUT (1<<0)
@@ -49,23 +44,22 @@ typedef struct sndrv_rawmidi_status snd_rawmidi_status_t;
#define SNDRV_RAWMIDI_LFLG_APPEND (1<<2)
#define SNDRV_RAWMIDI_LFLG_NOOPENLOCK (1<<3)
-typedef struct _snd_rawmidi_runtime snd_rawmidi_runtime_t;
-typedef struct _snd_rawmidi_substream snd_rawmidi_substream_t;
-typedef struct _snd_rawmidi_str snd_rawmidi_str_t;
+struct snd_rawmidi;
+struct snd_rawmidi_substream;
-typedef struct _snd_rawmidi_ops {
- int (*open) (snd_rawmidi_substream_t * substream);
- int (*close) (snd_rawmidi_substream_t * substream);
- void (*trigger) (snd_rawmidi_substream_t * substream, int up);
- void (*drain) (snd_rawmidi_substream_t * substream);
-} snd_rawmidi_ops_t;
+struct snd_rawmidi_ops {
+ int (*open) (struct snd_rawmidi_substream * substream);
+ int (*close) (struct snd_rawmidi_substream * substream);
+ void (*trigger) (struct snd_rawmidi_substream * substream, int up);
+ void (*drain) (struct snd_rawmidi_substream * substream);
+};
-typedef struct _snd_rawmidi_global_ops {
- int (*dev_register) (snd_rawmidi_t * rmidi);
- int (*dev_unregister) (snd_rawmidi_t * rmidi);
-} snd_rawmidi_global_ops_t;
+struct snd_rawmidi_global_ops {
+ int (*dev_register) (struct snd_rawmidi * rmidi);
+ int (*dev_unregister) (struct snd_rawmidi * rmidi);
+};
-struct _snd_rawmidi_runtime {
+struct snd_rawmidi_runtime {
unsigned int drain: 1, /* drain stage */
oss: 1; /* OSS compatible mode */
/* midi stream buffer */
@@ -80,15 +74,15 @@ struct _snd_rawmidi_runtime {
spinlock_t lock;
wait_queue_head_t sleep;
/* event handler (new bytes, input only) */
- void (*event)(snd_rawmidi_substream_t *substream);
+ void (*event)(struct snd_rawmidi_substream *substream);
/* defers calls to event [input] or ops->trigger [output] */
struct tasklet_struct tasklet;
/* private data */
void *private_data;
- void (*private_free)(snd_rawmidi_substream_t *substream);
+ void (*private_free)(struct snd_rawmidi_substream *substream);
};
-struct _snd_rawmidi_substream {
+struct snd_rawmidi_substream {
struct list_head list; /* list of all substream for given stream */
int stream; /* direction */
int number; /* substream number */
@@ -97,29 +91,29 @@ struct _snd_rawmidi_substream {
active_sensing: 1; /* send active sensing when close */
int use_count; /* use counter (for output) */
size_t bytes;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_str_t *pstr;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_str *pstr;
char name[32];
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi_runtime *runtime;
/* hardware layer */
- snd_rawmidi_ops_t *ops;
+ struct snd_rawmidi_ops *ops;
};
-typedef struct _snd_rawmidi_file {
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *input;
- snd_rawmidi_substream_t *output;
-} snd_rawmidi_file_t;
+struct snd_rawmidi_file {
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *input;
+ struct snd_rawmidi_substream *output;
+};
-struct _snd_rawmidi_str {
+struct snd_rawmidi_str {
unsigned int substream_count;
unsigned int substream_opened;
struct list_head substreams;
};
-struct _snd_rawmidi {
- snd_card_t *card;
-
+struct snd_rawmidi {
+ struct snd_card *card;
+ struct list_head list;
unsigned int device; /* device number */
unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */
char id[64];
@@ -129,52 +123,61 @@ struct _snd_rawmidi {
int ossreg;
#endif
- snd_rawmidi_global_ops_t *ops;
+ struct snd_rawmidi_global_ops *ops;
- snd_rawmidi_str_t streams[2];
+ struct snd_rawmidi_str streams[2];
void *private_data;
- void (*private_free) (snd_rawmidi_t *rmidi);
+ void (*private_free) (struct snd_rawmidi *rmidi);
struct semaphore open_mutex;
wait_queue_head_t open_wait;
- snd_info_entry_t *dev;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *dev;
+ struct snd_info_entry *proc_entry;
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- snd_seq_device_t *seq_dev;
+ struct snd_seq_device *seq_dev;
#endif
};
/* main rawmidi functions */
-int snd_rawmidi_new(snd_card_t * card, char *id, int device,
+int snd_rawmidi_new(struct snd_card *card, char *id, int device,
int output_count, int input_count,
- snd_rawmidi_t ** rmidi);
-void snd_rawmidi_set_ops(snd_rawmidi_t * rmidi, int stream, snd_rawmidi_ops_t * ops);
+ struct snd_rawmidi **rmidi);
+void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
+ struct snd_rawmidi_ops *ops);
/* callbacks */
-void snd_rawmidi_receive_reset(snd_rawmidi_substream_t * substream);
-int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char *buffer, int count);
-void snd_rawmidi_transmit_reset(snd_rawmidi_substream_t * substream);
-int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream);
-int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char *buffer, int count);
-int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count);
-int snd_rawmidi_transmit(snd_rawmidi_substream_t * substream, unsigned char *buffer, int count);
+void snd_rawmidi_receive_reset(struct snd_rawmidi_substream *substream);
+int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
+ const unsigned char *buffer, int count);
+void snd_rawmidi_transmit_reset(struct snd_rawmidi_substream *substream);
+int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream);
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count);
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
+int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count);
/* main midi functions */
-int snd_rawmidi_info_select(snd_card_t *card, snd_rawmidi_info_t *info);
-int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int mode, snd_rawmidi_file_t * rfile);
-int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile);
-int snd_rawmidi_output_params(snd_rawmidi_substream_t * substream, snd_rawmidi_params_t * params);
-int snd_rawmidi_input_params(snd_rawmidi_substream_t * substream, snd_rawmidi_params_t * params);
-int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream);
-int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream);
-int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream);
-long snd_rawmidi_kernel_read(snd_rawmidi_substream_t * substream, unsigned char *buf, long count);
-long snd_rawmidi_kernel_write(snd_rawmidi_substream_t * substream, const unsigned char *buf, long count);
+int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
+int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
+ int mode, struct snd_rawmidi_file *rfile);
+int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
+int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_params *params);
+int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_params *params);
+int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream);
+int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream);
+int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream);
+long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
+ unsigned char *buf, long count);
+long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
+ const unsigned char *buf, long count);
#endif /* __SOUND_RAWMIDI_H */
diff --git a/include/sound/sb.h b/include/sound/sb.h
index 7960452445e6..431d06675e36 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -60,7 +60,7 @@ enum sb_hw_type {
#define SB_MPU_INPUT 1
-struct _snd_sb {
+struct snd_sb {
unsigned long port; /* base port of DSP chip */
struct resource *res_port;
unsigned long mpu_port; /* MPU port for SB DSP 4.0+ */
@@ -92,24 +92,26 @@ struct _snd_sb {
void *csp; /* used only when CONFIG_SND_SB16_CSP is set */
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *midi_substream_input;
- snd_rawmidi_substream_t *midi_substream_output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_substream_input;
+ struct snd_rawmidi_substream *midi_substream_output;
irqreturn_t (*rmidi_callback)(int irq, void *dev_id, struct pt_regs *regs);
spinlock_t reg_lock;
spinlock_t open_lock;
spinlock_t midi_input_lock;
- snd_info_entry_t *proc_entry;
-};
+ struct snd_info_entry *proc_entry;
-typedef struct _snd_sb sb_t;
+#ifdef CONFIG_PM
+ unsigned char saved_regs[0x20];
+#endif
+};
/* I/O ports */
@@ -267,48 +269,52 @@ typedef struct _snd_sb sb_t;
*
*/
-static inline void snd_sb_ack_8bit(sb_t *chip)
+static inline void snd_sb_ack_8bit(struct snd_sb *chip)
{
inb(SBP(chip, DATA_AVAIL));
}
-static inline void snd_sb_ack_16bit(sb_t *chip)
+static inline void snd_sb_ack_16bit(struct snd_sb *chip)
{
inb(SBP(chip, DATA_AVAIL_16));
}
/* sb_common.c */
-int snd_sbdsp_command(sb_t *chip, unsigned char val);
-int snd_sbdsp_get_byte(sb_t *chip);
-int snd_sbdsp_reset(sb_t *chip);
-int snd_sbdsp_create(snd_card_t *card,
+int snd_sbdsp_command(struct snd_sb *chip, unsigned char val);
+int snd_sbdsp_get_byte(struct snd_sb *chip);
+int snd_sbdsp_reset(struct snd_sb *chip);
+int snd_sbdsp_create(struct snd_card *card,
unsigned long port,
int irq,
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
int dma8, int dma16,
unsigned short hardware,
- sb_t **r_chip);
+ struct snd_sb **r_chip);
/* sb_mixer.c */
-void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data);
-unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg);
-int snd_sbmixer_new(sb_t *chip);
+void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data);
+unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg);
+int snd_sbmixer_new(struct snd_sb *chip);
+#ifdef CONFIG_PM
+void snd_sbmixer_suspend(struct snd_sb *chip);
+void snd_sbmixer_resume(struct snd_sb *chip);
+#endif
/* sb8_init.c */
-int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm);
+int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm);
/* sb8.c */
-irqreturn_t snd_sb8dsp_interrupt(sb_t *chip);
-int snd_sb8_playback_open(snd_pcm_substream_t *substream);
-int snd_sb8_capture_open(snd_pcm_substream_t *substream);
-int snd_sb8_playback_close(snd_pcm_substream_t *substream);
-int snd_sb8_capture_close(snd_pcm_substream_t *substream);
+irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip);
+int snd_sb8_playback_open(struct snd_pcm_substream *substream);
+int snd_sb8_capture_open(struct snd_pcm_substream *substream);
+int snd_sb8_playback_close(struct snd_pcm_substream *substream);
+int snd_sb8_capture_close(struct snd_pcm_substream *substream);
/* midi8.c */
-irqreturn_t snd_sb8dsp_midi_interrupt(sb_t *chip);
-int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi);
+irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip);
+int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi);
/* sb16_init.c */
-int snd_sb16dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm);
-const snd_pcm_ops_t *snd_sb16dsp_get_pcm_ops(int direction);
-int snd_sb16dsp_configure(sb_t *chip);
+int snd_sb16dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm);
+const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction);
+int snd_sb16dsp_configure(struct snd_sb *chip);
/* sb16.c */
irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -328,7 +334,7 @@ enum {
#define SB_MIXVAL_INPUT_SW(reg1, reg2, left_shift, right_shift) \
((reg1) | ((reg2) << 8) | ((left_shift) << 16) | ((right_shift) << 24))
-int snd_sbmixer_add_ctl(sb_t *chip, const char *name, int index, int type, unsigned long value);
+int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value);
/* for ease of use */
struct sbmix_elem {
@@ -352,7 +358,7 @@ struct sbmix_elem {
.type = SB_MIX_INPUT_SW, \
.private_value = SB_MIXVAL_INPUT_SW(reg1, reg2, left_shift, right_shift) }
-static inline int snd_sbmixer_add_ctl_elem(sb_t *chip, const struct sbmix_elem *c)
+static inline int snd_sbmixer_add_ctl_elem(struct snd_sb *chip, const struct sbmix_elem *c)
{
return snd_sbmixer_add_ctl(chip, c->name, 0, c->type, c->private_value);
}
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index eb8368b56b16..3b44d4b370f5 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -63,25 +63,25 @@
#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000
/* microcode header */
-typedef struct snd_sb_csp_mc_header {
+struct snd_sb_csp_mc_header {
char codec_name[16]; /* id name of codec */
unsigned short func_req; /* requested function */
-} snd_sb_csp_mc_header_t;
+};
/* microcode to be loaded */
-typedef struct snd_sb_csp_microcode {
- snd_sb_csp_mc_header_t info;
+struct snd_sb_csp_microcode {
+ struct snd_sb_csp_mc_header info;
unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE];
-} snd_sb_csp_microcode_t;
+};
/* start CSP with sample_width in mono/stereo */
-typedef struct snd_sb_csp_start {
+struct snd_sb_csp_start {
int sample_width; /* sample width, look above */
int channels; /* channels, look above */
-} snd_sb_csp_start_t;
+};
/* CSP information */
-typedef struct snd_sb_csp_info {
+struct snd_sb_csp_info {
char codec_name[16]; /* id name of codec */
unsigned short func_nr; /* function number */
unsigned int acc_format; /* accepted PCM formats */
@@ -93,17 +93,17 @@ typedef struct snd_sb_csp_info {
unsigned short run_width; /* current sample width */
unsigned short version; /* version id: 0x10 - 0x1f */
unsigned short state; /* state bits */
-} snd_sb_csp_info_t;
+};
/* HWDEP controls */
/* get CSP information */
-#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, snd_sb_csp_info_t)
+#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, struct snd_sb_csp_info)
/* load microcode to CSP */
-#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, snd_sb_csp_microcode_t)
+#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, struct snd_sb_csp_microcode)
/* unload microcode from CSP */
#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12)
/* start CSP */
-#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, snd_sb_csp_start_t)
+#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, struct snd_sb_csp_start)
/* stop CSP */
#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14)
/* pause CSP and DMA transfer */
@@ -115,25 +115,25 @@ typedef struct snd_sb_csp_info {
#include "sb.h"
#include "hwdep.h"
-typedef struct snd_sb_csp snd_sb_csp_t;
+struct snd_sb_csp;
/*
* CSP operators
*/
-typedef struct {
- int (*csp_use) (snd_sb_csp_t * p);
- int (*csp_unuse) (snd_sb_csp_t * p);
- int (*csp_autoload) (snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode);
- int (*csp_start) (snd_sb_csp_t * p, int sample_width, int channels);
- int (*csp_stop) (snd_sb_csp_t * p);
- int (*csp_qsound_transfer) (snd_sb_csp_t * p);
-} snd_sb_csp_ops_t;
+struct snd_sb_csp_ops {
+ int (*csp_use) (struct snd_sb_csp * p);
+ int (*csp_unuse) (struct snd_sb_csp * p);
+ int (*csp_autoload) (struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode);
+ int (*csp_start) (struct snd_sb_csp * p, int sample_width, int channels);
+ int (*csp_stop) (struct snd_sb_csp * p);
+ int (*csp_qsound_transfer) (struct snd_sb_csp * p);
+};
/*
* CSP private data
*/
struct snd_sb_csp {
- sb_t *chip; /* SB16 DSP */
+ struct snd_sb *chip; /* SB16 DSP */
int used; /* usage flag - exclusive */
char codec_name[16]; /* name of codec */
unsigned short func_nr; /* function number */
@@ -147,7 +147,7 @@ struct snd_sb_csp {
int version; /* CSP version (0x10 - 0x1f) */
int running; /* running state */
- snd_sb_csp_ops_t ops; /* operators */
+ struct snd_sb_csp_ops ops; /* operators */
spinlock_t q_lock; /* locking */
int q_enabled; /* enabled flag */
@@ -155,13 +155,13 @@ struct snd_sb_csp {
int qpos_right; /* right position */
int qpos_changed; /* position changed flag */
- snd_kcontrol_t *qsound_switch;
- snd_kcontrol_t *qsound_space;
+ struct snd_kcontrol *qsound_switch;
+ struct snd_kcontrol *qsound_space;
struct semaphore access_mutex; /* locking */
};
-int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep);
+int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
#endif
#endif /* __SOUND_SB16_CSP */
diff --git a/include/sound/seq_device.h b/include/sound/seq_device.h
index 204ca540c28e..2b5f24cc7548 100644
--- a/include/sound/seq_device.h
+++ b/include/sound/seq_device.h
@@ -21,9 +21,6 @@
*
*/
-typedef struct snd_seq_device snd_seq_device_t;
-typedef struct snd_seq_dev_ops snd_seq_dev_ops_t;
-
/*
* registered device information
*/
@@ -36,7 +33,7 @@ typedef struct snd_seq_dev_ops snd_seq_dev_ops_t;
struct snd_seq_device {
/* device info */
- snd_card_t *card; /* sound card */
+ struct snd_card *card; /* sound card */
int device; /* device number */
char id[ID_LEN]; /* driver id */
char name[80]; /* device name */
@@ -44,7 +41,7 @@ struct snd_seq_device {
void *driver_data; /* private data for driver */
int status; /* flag - read only */
void *private_data; /* private data for the caller */
- void (*private_free)(snd_seq_device_t *device);
+ void (*private_free)(struct snd_seq_device *device);
struct list_head list; /* link to next device */
};
@@ -63,19 +60,19 @@ struct snd_seq_device {
* Typically, call snd_device_free(dev->card, dev->driver_data)
*/
struct snd_seq_dev_ops {
- int (*init_device)(snd_seq_device_t *dev);
- int (*free_device)(snd_seq_device_t *dev);
+ int (*init_device)(struct snd_seq_device *dev);
+ int (*free_device)(struct snd_seq_device *dev);
};
/*
* prototypes
*/
void snd_seq_device_load_drivers(void);
-int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize, snd_seq_device_t **result);
-int snd_seq_device_register_driver(char *id, snd_seq_dev_ops_t *entry, int argsize);
+int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, struct snd_seq_device **result);
+int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, int argsize);
int snd_seq_device_unregister_driver(char *id);
-#define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(snd_seq_device_t))
+#define SNDRV_SEQ_DEVICE_ARGPTR(dev) (void *)((char *)(dev) + sizeof(struct snd_seq_device))
/*
@@ -84,5 +81,4 @@ int snd_seq_device_unregister_driver(char *id);
#define SNDRV_SEQ_DEV_ID_MIDISYNTH "seq-midi"
#define SNDRV_SEQ_DEV_ID_OPL3 "opl3-synth"
-
#endif /* __SOUND_SEQ_DEVICE_H */
diff --git a/include/sound/seq_instr.h b/include/sound/seq_instr.h
index 1a654df4aa97..db764f09efb7 100644
--- a/include/sound/seq_instr.h
+++ b/include/sound/seq_instr.h
@@ -24,29 +24,27 @@
#include "seq_kernel.h"
/* Instrument cluster */
-typedef struct _snd_seq_kcluster {
+struct snd_seq_kcluster {
snd_seq_instr_cluster_t cluster;
char name[32];
int priority;
- struct _snd_seq_kcluster *next;
-} snd_seq_kcluster_t;
+ struct snd_seq_kcluster *next;
+};
/* return pointer to private data */
-#define KINSTR_DATA(kinstr) (void *)(((char *)kinstr) + sizeof(snd_seq_kinstr_t))
-
-typedef struct snd_seq_kinstr_ops snd_seq_kinstr_ops_t;
+#define KINSTR_DATA(kinstr) (void *)(((char *)kinstr) + sizeof(struct snd_seq_kinstr))
/* Instrument structure */
-typedef struct _snd_seq_kinstr {
- snd_seq_instr_t instr;
+struct snd_seq_kinstr {
+ struct snd_seq_instr instr;
char name[32];
int type; /* instrument type */
int use; /* use count */
int busy; /* not useable */
int add_len; /* additional length */
- snd_seq_kinstr_ops_t *ops; /* operations */
- struct _snd_seq_kinstr *next;
-} snd_seq_kinstr_t;
+ struct snd_seq_kinstr_ops *ops; /* operations */
+ struct snd_seq_kinstr *next;
+};
#define SNDRV_SEQ_INSTR_HASH_SIZE 32
@@ -54,11 +52,11 @@ typedef struct _snd_seq_kinstr {
#define SNDRV_SEQ_INSTR_FLG_DIRECT (1<<0) /* accept only direct events */
/* List of all instruments */
-typedef struct {
- snd_seq_kinstr_t *hash[SNDRV_SEQ_INSTR_HASH_SIZE];
+struct snd_seq_kinstr_list {
+ struct snd_seq_kinstr *hash[SNDRV_SEQ_INSTR_HASH_SIZE];
int count; /* count of all instruments */
- snd_seq_kcluster_t *chash[SNDRV_SEQ_INSTR_HASH_SIZE];
+ struct snd_seq_kcluster *chash[SNDRV_SEQ_INSTR_HASH_SIZE];
int ccount; /* count of all clusters */
int owner; /* current owner of the instrument list */
@@ -68,7 +66,7 @@ typedef struct {
spinlock_t ops_lock;
struct semaphore ops_mutex;
unsigned long ops_flags;
-} snd_seq_kinstr_list_t;
+};
#define SNDRV_SEQ_INSTR_NOTIFY_REMOVE 0
#define SNDRV_SEQ_INSTR_NOTIFY_CHANGE 1
@@ -78,33 +76,33 @@ struct snd_seq_kinstr_ops {
long add_len; /* additional length */
char *instr_type;
int (*info)(void *private_data, char *info_data, long len);
- int (*put)(void *private_data, snd_seq_kinstr_t *kinstr,
+ int (*put)(void *private_data, struct snd_seq_kinstr *kinstr,
char __user *instr_data, long len, int atomic, int cmd);
- int (*get)(void *private_data, snd_seq_kinstr_t *kinstr,
+ int (*get)(void *private_data, struct snd_seq_kinstr *kinstr,
char __user *instr_data, long len, int atomic, int cmd);
- int (*get_size)(void *private_data, snd_seq_kinstr_t *kinstr, long *size);
- int (*remove)(void *private_data, snd_seq_kinstr_t *kinstr, int atomic);
- void (*notify)(void *private_data, snd_seq_kinstr_t *kinstr, int what);
+ int (*get_size)(void *private_data, struct snd_seq_kinstr *kinstr, long *size);
+ int (*remove)(void *private_data, struct snd_seq_kinstr *kinstr, int atomic);
+ void (*notify)(void *private_data, struct snd_seq_kinstr *kinstr, int what);
struct snd_seq_kinstr_ops *next;
};
/* instrument operations */
-snd_seq_kinstr_list_t *snd_seq_instr_list_new(void);
-void snd_seq_instr_list_free(snd_seq_kinstr_list_t **list);
-int snd_seq_instr_list_free_cond(snd_seq_kinstr_list_t *list,
- snd_seq_instr_header_t *ifree,
+struct snd_seq_kinstr_list *snd_seq_instr_list_new(void);
+void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list);
+int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
+ struct snd_seq_instr_header *ifree,
int client,
int atomic);
-snd_seq_kinstr_t *snd_seq_instr_find(snd_seq_kinstr_list_t *list,
- snd_seq_instr_t *instr,
- int exact,
- int follow_alias);
-void snd_seq_instr_free_use(snd_seq_kinstr_list_t *list,
- snd_seq_kinstr_t *instr);
-int snd_seq_instr_event(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
+ struct snd_seq_instr *instr,
+ int exact,
+ int follow_alias);
+void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
+ struct snd_seq_kinstr *instr);
+int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int client,
int atomic,
int hop);
diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
index 4beca1952c76..f023c1b97f8c 100644
--- a/include/sound/seq_kernel.h
+++ b/include/sound/seq_kernel.h
@@ -24,62 +24,8 @@
#include <linux/time.h>
#include "asequencer.h"
-typedef sndrv_seq_tick_time_t snd_seq_tick_time_t;
-typedef sndrv_seq_position_t snd_seq_position_t;
-typedef sndrv_seq_frequency_t snd_seq_frequency_t;
-typedef sndrv_seq_instr_cluster_t snd_seq_instr_cluster_t;
-typedef enum sndrv_seq_client_type snd_seq_client_type_t;
-typedef enum sndrv_seq_stop_mode snd_seq_stop_mode_t;
-typedef struct sndrv_seq_port_info snd_seq_port_info_t;
-typedef struct sndrv_seq_port_subscribe snd_seq_port_subscribe_t;
-typedef struct sndrv_seq_event snd_seq_event_t;
-typedef struct sndrv_seq_addr snd_seq_addr_t;
-typedef struct sndrv_seq_ev_volume snd_seq_ev_volume_t;
-typedef struct sndrv_seq_ev_loop snd_seq_ev_loop_t;
-typedef struct sndrv_seq_remove_events snd_seq_remove_events_t;
-typedef struct sndrv_seq_query_subs snd_seq_query_subs_t;
-typedef struct sndrv_seq_real_time snd_seq_real_time_t;
-typedef struct sndrv_seq_system_info snd_seq_system_info_t;
-typedef struct sndrv_seq_client_info snd_seq_client_info_t;
-typedef struct sndrv_seq_queue_info snd_seq_queue_info_t;
-typedef struct sndrv_seq_queue_status snd_seq_queue_status_t;
-typedef struct sndrv_seq_queue_tempo snd_seq_queue_tempo_t;
-typedef struct sndrv_seq_queue_owner snd_seq_queue_owner_t;
-typedef struct sndrv_seq_queue_timer snd_seq_queue_timer_t;
-typedef struct sndrv_seq_queue_client snd_seq_queue_client_t;
-typedef struct sndrv_seq_client_pool snd_seq_client_pool_t;
-typedef struct sndrv_seq_instr snd_seq_instr_t;
-typedef struct sndrv_seq_instr_data snd_seq_instr_data_t;
-typedef struct sndrv_seq_instr_header snd_seq_instr_header_t;
-typedef union sndrv_seq_timestamp snd_seq_timestamp_t;
-
-#define snd_seq_event_bounce_ext_data sndrv_seq_event_bounce_ext_data
-#define snd_seq_ev_is_result_type sndrv_seq_ev_is_result_type
-#define snd_seq_ev_is_channel_type sndrv_seq_ev_is_channel_type
-#define snd_seq_ev_is_note_type sndrv_seq_ev_is_note_type
-#define snd_seq_ev_is_control_type sndrv_seq_ev_is_control_type
-#define snd_seq_ev_is_queue_type sndrv_seq_ev_is_queue_type
-#define snd_seq_ev_is_message_type sndrv_seq_ev_is_message_type
-#define snd_seq_ev_is_sample_type sndrv_seq_ev_is_sample_type
-#define snd_seq_ev_is_user_type sndrv_seq_ev_is_user_type
-#define snd_seq_ev_is_fixed_type sndrv_seq_ev_is_fixed_type
-#define snd_seq_ev_is_instr_type sndrv_seq_ev_is_instr_type
-#define snd_seq_ev_is_variable_type sndrv_seq_ev_is_variable_type
-#define snd_seq_ev_is_reserved sndrv_seq_ev_is_reserved
-#define snd_seq_ev_is_direct sndrv_seq_ev_is_direct
-#define snd_seq_ev_is_prior sndrv_seq_ev_is_prior
-#define snd_seq_ev_length_type sndrv_seq_ev_length_type
-#define snd_seq_ev_is_fixed sndrv_seq_ev_is_fixed
-#define snd_seq_ev_is_variable sndrv_seq_ev_is_variable
-#define snd_seq_ev_is_varusr sndrv_seq_ev_is_varusr
-#define snd_seq_ev_timestamp_type sndrv_seq_ev_timestamp_type
-#define snd_seq_ev_is_tick sndrv_seq_ev_is_tick
-#define snd_seq_ev_is_real sndrv_seq_ev_is_real
-#define snd_seq_ev_timemode_type sndrv_seq_ev_timemode_type
-#define snd_seq_ev_is_abstime sndrv_seq_ev_is_abstime
-#define snd_seq_ev_is_reltime sndrv_seq_ev_is_reltime
-#define snd_seq_queue_sync_port sndrv_seq_queue_sync_port
-#define snd_seq_queue_owner sndrv_seq_queue_owner
+typedef struct snd_seq_real_time snd_seq_real_time_t;
+typedef union snd_seq_timestamp snd_seq_timestamp_t;
/* maximum number of events dequeued per schedule interval */
#define SNDRV_SEQ_MAX_DEQUEUE 50
@@ -114,69 +60,48 @@ typedef union sndrv_seq_timestamp snd_seq_timestamp_t;
/* max size of event size */
#define SNDRV_SEQ_MAX_EVENT_LEN 0x3fffffff
-/* typedefs */
-struct _snd_seq_user_client;
-struct _snd_seq_kernel_client;
-struct _snd_seq_client;
-struct _snd_seq_queue;
-
-typedef struct _snd_seq_user_client user_client_t;
-typedef struct _snd_seq_kernel_client kernel_client_t;
-typedef struct _snd_seq_client client_t;
-typedef struct _snd_seq_queue queue_t;
-
-/* call-backs for kernel client */
-
-typedef struct {
- void *private_data;
- unsigned allow_input: 1,
- allow_output: 1;
- /*...*/
-} snd_seq_client_callback_t;
-
/* call-backs for kernel port */
-typedef int (snd_seq_kernel_port_open_t)(void *private_data, snd_seq_port_subscribe_t *info);
-typedef int (snd_seq_kernel_port_close_t)(void *private_data, snd_seq_port_subscribe_t *info);
-typedef int (snd_seq_kernel_port_input_t)(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop);
-typedef void (snd_seq_kernel_port_private_free_t)(void *private_data);
-
-typedef struct {
+struct snd_seq_port_callback {
struct module *owner;
void *private_data;
- snd_seq_kernel_port_open_t *subscribe;
- snd_seq_kernel_port_close_t *unsubscribe;
- snd_seq_kernel_port_open_t *use;
- snd_seq_kernel_port_close_t *unuse;
- snd_seq_kernel_port_input_t *event_input;
- snd_seq_kernel_port_private_free_t *private_free;
+ int (*subscribe)(void *private_data, struct snd_seq_port_subscribe *info);
+ int (*unsubscribe)(void *private_data, struct snd_seq_port_subscribe *info);
+ int (*use)(void *private_data, struct snd_seq_port_subscribe *info);
+ int (*unuse)(void *private_data, struct snd_seq_port_subscribe *info);
+ int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop);
+ void (*private_free)(void *private_data);
unsigned int callback_all; /* call subscribe callbacks at each connection/disconnection */
/*...*/
-} snd_seq_port_callback_t;
+};
/* interface for kernel client */
-extern int snd_seq_create_kernel_client(snd_card_t *card, int client_index, snd_seq_client_callback_t *callback);
-extern int snd_seq_delete_kernel_client(int client);
-extern int snd_seq_kernel_client_enqueue(int client, snd_seq_event_t *ev, int atomic, int hop);
-extern int snd_seq_kernel_client_dispatch(int client, snd_seq_event_t *ev, int atomic, int hop);
-extern int snd_seq_kernel_client_ctl(int client, unsigned int cmd, void *arg);
+int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
+ const char *name_fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+int snd_seq_delete_kernel_client(int client);
+int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, int atomic, int hop);
+int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event *ev, int atomic, int hop);
+int snd_seq_kernel_client_ctl(int client, unsigned int cmd, void *arg);
#define SNDRV_SEQ_EXT_MASK 0xc0000000
#define SNDRV_SEQ_EXT_USRPTR 0x80000000
#define SNDRV_SEQ_EXT_CHAINED 0x40000000
typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count);
-int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned);
-int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data);
+int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
+ int in_kernel, int size_aligned);
+int snd_seq_dump_var_event(const struct snd_seq_event *event,
+ snd_seq_dump_func_t func, void *private_data);
/* interface for OSS emulation */
-int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo);
+int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo);
/* port callback routines */
-void snd_port_init_callback(snd_seq_port_callback_t *p);
-snd_seq_port_callback_t *snd_port_alloc_callback(void);
+void snd_port_init_callback(struct snd_seq_port_callback *p);
+struct snd_seq_port_callback *snd_port_alloc_callback(void);
/* port attach/detach */
-int snd_seq_event_port_attach(int client, snd_seq_port_callback_t *pcbp,
+int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp,
int cap, int type, int midi_channels, int midi_voices, char *portname);
int snd_seq_event_port_detach(int client, int port);
diff --git a/include/sound/seq_midi_emul.h b/include/sound/seq_midi_emul.h
index e58ca45bc73b..d6c4615901b9 100644
--- a/include/sound/seq_midi_emul.h
+++ b/include/sound/seq_midi_emul.h
@@ -29,7 +29,7 @@
* channel. All drivers for hardware that does not understand midi
* directly will probably need to use this structure.
*/
-typedef struct snd_midi_channel {
+struct snd_midi_channel {
void *private; /* A back pointer to driver data */
int number; /* The channel number */
int client; /* The client associated with this channel */
@@ -53,41 +53,43 @@ typedef struct snd_midi_channel {
short gm_rpn_fine_tuning; /* Master fine tuning */
short gm_rpn_coarse_tuning; /* Master coarse tuning */
-} snd_midi_channel_t;
+};
/*
* A structure that represets a set of channels bound to a port. There
* would usually be 16 channels per port. But fewer could be used for
* particular cases.
* The channel set consists of information describing the client and
- * port for this midi synth and an array of snd_midi_channel_t structures.
- * A driver that had no need for snd_midi_channel_t could still use the
+ * port for this midi synth and an array of snd_midi_channel structures.
+ * A driver that had no need for snd_midi_channel could still use the
* channel set type if it wished with the channel array null.
*/
-typedef struct snd_midi_channel_set {
+struct snd_midi_channel_set {
void *private_data; /* Driver data */
int client; /* Client for this port */
int port; /* The port number */
int max_channels; /* Size of the channels array */
- snd_midi_channel_t *channels;
+ struct snd_midi_channel *channels;
unsigned char midi_mode; /* MIDI operating mode */
unsigned char gs_master_volume; /* SYSEX master volume: 0-127 */
unsigned char gs_chorus_mode;
unsigned char gs_reverb_mode;
-} snd_midi_channel_set_t;
+};
-typedef struct snd_seq_midi_op {
- void (*note_on)(void *private_data, int note, int vel, snd_midi_channel_t *chan);
- void (*note_off)(void *private_data,int note, int vel, snd_midi_channel_t *chan); /* release note */
- void (*key_press)(void *private_data, int note, int vel, snd_midi_channel_t *chan);
- void (*note_terminate)(void *private_data, int note, snd_midi_channel_t *chan); /* terminate note immediately */
- void (*control)(void *private_data, int type, snd_midi_channel_t *chan);
- void (*nrpn)(void *private_data, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
- void (*sysex)(void *private_data, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
-} snd_midi_op_t;
+struct snd_midi_op {
+ void (*note_on)(void *private_data, int note, int vel, struct snd_midi_channel *chan);
+ void (*note_off)(void *private_data,int note, int vel, struct snd_midi_channel *chan); /* release note */
+ void (*key_press)(void *private_data, int note, int vel, struct snd_midi_channel *chan);
+ void (*note_terminate)(void *private_data, int note, struct snd_midi_channel *chan); /* terminate note immediately */
+ void (*control)(void *private_data, int type, struct snd_midi_channel *chan);
+ void (*nrpn)(void *private_data, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset);
+ void (*sysex)(void *private_data, unsigned char *buf, int len, int parsed,
+ struct snd_midi_channel_set *chset);
+};
/*
* These defines are used so that pitchbend, aftertouch etc, can be
@@ -186,10 +188,10 @@ enum {
};
/* Prototypes for midi_process.c */
-void snd_midi_process_event(snd_midi_op_t *ops, snd_seq_event_t *ev,
- snd_midi_channel_set_t *chanset);
-void snd_midi_channel_set_clear(snd_midi_channel_set_t *chset);
-snd_midi_channel_set_t *snd_midi_channel_alloc_set(int n);
-void snd_midi_channel_free_set(snd_midi_channel_set_t *chset);
+void snd_midi_process_event(struct snd_midi_op *ops, struct snd_seq_event *ev,
+ struct snd_midi_channel_set *chanset);
+void snd_midi_channel_set_clear(struct snd_midi_channel_set *chset);
+struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n);
+void snd_midi_channel_free_set(struct snd_midi_channel_set *chset);
#endif /* __SOUND_SEQ_MIDI_EMUL_H */
diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h
index 8857e2bd31a5..dd789e7cdb20 100644
--- a/include/sound/seq_midi_event.h
+++ b/include/sound/seq_midi_event.h
@@ -26,10 +26,8 @@
#define MAX_MIDI_EVENT_BUF 256
-typedef struct snd_midi_event_t snd_midi_event_t;
-
/* midi status */
-struct snd_midi_event_t {
+struct snd_midi_event {
int qlen; /* queue length */
int read; /* chars read */
int type; /* current event type */
@@ -40,15 +38,17 @@ struct snd_midi_event_t {
spinlock_t lock;
};
-int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
-void snd_midi_event_free(snd_midi_event_t *dev);
-void snd_midi_event_reset_encode(snd_midi_event_t *dev);
-void snd_midi_event_reset_decode(snd_midi_event_t *dev);
-void snd_midi_event_no_status(snd_midi_event_t *dev, int on);
+int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev);
+void snd_midi_event_free(struct snd_midi_event *dev);
+void snd_midi_event_reset_encode(struct snd_midi_event *dev);
+void snd_midi_event_reset_decode(struct snd_midi_event *dev);
+void snd_midi_event_no_status(struct snd_midi_event *dev, int on);
/* encode from byte stream - return number of written bytes if success */
-long snd_midi_event_encode(snd_midi_event_t *dev, unsigned char *buf, long count, snd_seq_event_t *ev);
-int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev);
+long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev);
+int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, struct snd_seq_event *ev);
/* decode from event to bytes - return number of written bytes if success */
-long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count, snd_seq_event_t *ev);
+long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev);
#endif /* __SOUND_SEQ_MIDI_EVENT_H */
diff --git a/include/sound/seq_oss.h b/include/sound/seq_oss.h
index bd7e57322ab6..9b060bbd6e02 100644
--- a/include/sound/seq_oss.h
+++ b/include/sound/seq_oss.h
@@ -25,22 +25,16 @@
#include "seq_kernel.h"
/*
- * type definitions
- */
-typedef struct snd_seq_oss_arg_t snd_seq_oss_arg_t;
-typedef struct snd_seq_oss_callback_t snd_seq_oss_callback_t;
-
-/*
* argument structure for synthesizer operations
*/
-struct snd_seq_oss_arg_t {
+struct snd_seq_oss_arg {
/* given by OSS sequencer */
int app_index; /* application unique index */
int file_mode; /* file mode - see below */
int seq_mode; /* sequencer mode - see below */
/* following must be initialized in open callback */
- snd_seq_addr_t addr; /* opened port address */
+ struct snd_seq_addr addr; /* opened port address */
void *private_data; /* private data for lowlevel drivers */
/* note-on event passing mode: initially given by OSS seq,
@@ -53,14 +47,14 @@ struct snd_seq_oss_arg_t {
/*
* synthesizer operation callbacks
*/
-struct snd_seq_oss_callback_t {
+struct snd_seq_oss_callback {
struct module *owner;
- int (*open)(snd_seq_oss_arg_t *p, void *closure);
- int (*close)(snd_seq_oss_arg_t *p);
- int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
- int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char __user *buf, int offs, int count);
- int (*reset)(snd_seq_oss_arg_t *p);
- int (*raw_event)(snd_seq_oss_arg_t *p, unsigned char *data);
+ int (*open)(struct snd_seq_oss_arg *p, void *closure);
+ int (*close)(struct snd_seq_oss_arg *p);
+ int (*ioctl)(struct snd_seq_oss_arg *p, unsigned int cmd, unsigned long arg);
+ int (*load_patch)(struct snd_seq_oss_arg *p, int format, const char __user *buf, int offs, int count);
+ int (*reset)(struct snd_seq_oss_arg *p);
+ int (*raw_event)(struct snd_seq_oss_arg *p, unsigned char *data);
};
/* flag: file_mode */
@@ -88,13 +82,13 @@ struct snd_seq_oss_callback_t {
/*
* data pointer to snd_seq_register_device
*/
-typedef struct snd_seq_oss_reg {
+struct snd_seq_oss_reg {
int type;
int subtype;
int nvoices;
- snd_seq_oss_callback_t oper;
+ struct snd_seq_oss_callback oper;
void *private_data;
-} snd_seq_oss_reg_t;
+};
/* device id */
#define SNDRV_SEQ_DEV_ID_OSS "seq-oss"
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index 1ad27e859af3..8d5aea76d7c3 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -25,25 +25,23 @@
#include "rawmidi.h"
#include "seq_midi_event.h"
-typedef struct _snd_virmidi_dev snd_virmidi_dev_t;
-
/*
* device file instance:
* This instance is created at each time the midi device file is
* opened. Each instance has its own input buffer and MIDI parser
* (buffer), and is associated with the device instance.
*/
-typedef struct _snd_virmidi {
+struct snd_virmidi {
struct list_head list;
int seq_mode;
int client;
int port;
unsigned int trigger: 1;
- snd_midi_event_t *parser;
- snd_seq_event_t event;
- snd_virmidi_dev_t *rdev;
- snd_rawmidi_substream_t *substream;
-} snd_virmidi_t;
+ struct snd_midi_event *parser;
+ struct snd_seq_event event;
+ struct snd_virmidi_dev *rdev;
+ struct snd_rawmidi_substream *substream;
+};
#define SNDRV_VIRMIDI_SUBSCRIBE (1<<0)
#define SNDRV_VIRMIDI_USE (1<<1)
@@ -53,9 +51,9 @@ typedef struct _snd_virmidi {
* Each virtual midi device has one device instance. It contains
* common information and the linked-list of opened files,
*/
-struct _snd_virmidi_dev {
- snd_card_t *card; /* associated card */
- snd_rawmidi_t *rmidi; /* rawmidi device */
+struct snd_virmidi_dev {
+ struct snd_card *card; /* associated card */
+ struct snd_rawmidi *rmidi; /* rawmidi device */
int seq_mode; /* SNDRV_VIRMIDI_XXX */
int device; /* sequencer device */
int client; /* created/attached client */
@@ -78,6 +76,6 @@ struct _snd_virmidi_dev {
#define SNDRV_VIRMIDI_SEQ_ATTACH 1
#define SNDRV_VIRMIDI_SEQ_DISPATCH 2
-int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
+int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmidi);
#endif /* __SOUND_SEQ_VIRMIDI */
diff --git a/include/sound/sfnt_info.h b/include/sound/sfnt_info.h
index 674585f88a31..5d1ab9c4950f 100644
--- a/include/sound/sfnt_info.h
+++ b/include/sound/sfnt_info.h
@@ -35,7 +35,7 @@
#endif
/* patch interface header: 16 bytes */
-typedef struct soundfont_patch_info_t {
+struct soundfont_patch_info {
unsigned short key; /* use the key below */
#define SNDRV_OSS_SOUNDFONT_PATCH SNDRV_OSS_PATCHKEY(0x07)
@@ -59,7 +59,7 @@ typedef struct soundfont_patch_info_t {
short reserved; /* word alignment data */
/* the actual patch data begins after this */
-} soundfont_patch_info_t;
+};
/*
@@ -68,7 +68,7 @@ typedef struct soundfont_patch_info_t {
#define SNDRV_SFNT_PATCH_NAME_LEN 32
-typedef struct soundfont_open_parm_t {
+struct soundfont_open_parm {
unsigned short type; /* sample type */
#define SNDRV_SFNT_PAT_TYPE_MISC 0
#define SNDRV_SFNT_PAT_TYPE_GUS 6
@@ -78,7 +78,7 @@ typedef struct soundfont_open_parm_t {
short reserved;
char name[SNDRV_SFNT_PATCH_NAME_LEN];
-} soundfont_open_parm_t;
+};
/*
@@ -86,7 +86,7 @@ typedef struct soundfont_open_parm_t {
*/
/* wave table envelope & effect parameters to control EMU8000 */
-typedef struct soundfont_voice_parm_t {
+struct soundfont_voice_parm {
unsigned short moddelay; /* modulation delay (0x8000) */
unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */
unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */
@@ -108,11 +108,11 @@ typedef struct soundfont_voice_parm_t {
unsigned char chorus; /* chorus send (0x00) */
unsigned char reverb; /* reverb send (0x00) */
unsigned short reserved[4]; /* not used */
-} soundfont_voice_parm_t;
+};
/* wave table parameters: 92 bytes */
-typedef struct soundfont_voice_info_t {
+struct soundfont_voice_info {
unsigned short sf_id; /* file id (should be zero) */
unsigned short sample; /* sample id */
int start, end; /* sample offset correction */
@@ -135,13 +135,13 @@ typedef struct soundfont_voice_info_t {
unsigned char amplitude; /* sample volume (127 max) */
unsigned char attenuation; /* attenuation (0.375dB) */
short scaleTuning; /* pitch scale tuning(%), normally 100 */
- soundfont_voice_parm_t parm; /* voice envelope parameters */
+ struct soundfont_voice_parm parm; /* voice envelope parameters */
unsigned short sample_mode; /* sample mode_flag (set by driver) */
-} soundfont_voice_info_t;
+};
/* instrument info header: 4 bytes */
-typedef struct soundfont_voice_rec_hdr_t {
+struct soundfont_voice_rec_hdr {
unsigned char bank; /* midi bank number */
unsigned char instr; /* midi preset number */
char nvoices; /* number of voices */
@@ -149,7 +149,7 @@ typedef struct soundfont_voice_rec_hdr_t {
#define SNDRV_SFNT_WR_APPEND 0 /* append anyway */
#define SNDRV_SFNT_WR_EXCLUSIVE 1 /* skip if already exists */
#define SNDRV_SFNT_WR_REPLACE 2 /* replace if already exists */
-} soundfont_voice_rec_hdr_t;
+};
/*
@@ -157,7 +157,7 @@ typedef struct soundfont_voice_rec_hdr_t {
*/
/* wave table sample header: 32 bytes */
-typedef struct soundfont_sample_info_t {
+struct soundfont_sample_info {
unsigned short sf_id; /* file id (should be zero) */
unsigned short sample; /* sample id */
int start, end; /* start & end offset */
@@ -174,17 +174,17 @@ typedef struct soundfont_sample_info_t {
#define SNDRV_SFNT_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */
#define SNDRV_SFNT_SAMPLE_REVERSE_LOOP 128 /* reverse looping */
unsigned int truesize; /* used memory size (set by driver) */
-} soundfont_sample_info_t;
+};
/*
* voice preset mapping (aliasing)
*/
-typedef struct soundfont_voice_map_t {
+struct soundfont_voice_map {
int map_bank, map_instr, map_key; /* key = -1 means all keys */
int src_bank, src_instr, src_key;
-} soundfont_voice_map_t;
+};
/*
@@ -195,7 +195,7 @@ typedef struct soundfont_voice_map_t {
#define SNDRV_EMUX_VERSION ((1 << 16) | (0 << 8) | 0) /* 1.0.0 */
-struct sndrv_emux_misc_mode {
+struct snd_emux_misc_mode {
int port; /* -1 = all */
int mode;
int value;
@@ -204,11 +204,11 @@ struct sndrv_emux_misc_mode {
enum {
SNDRV_EMUX_IOCTL_VERSION = _IOR('H', 0x80, unsigned int),
- SNDRV_EMUX_IOCTL_LOAD_PATCH = _IOWR('H', 0x81, soundfont_patch_info_t),
+ SNDRV_EMUX_IOCTL_LOAD_PATCH = _IOWR('H', 0x81, struct soundfont_patch_info),
SNDRV_EMUX_IOCTL_RESET_SAMPLES = _IO('H', 0x82),
SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES = _IO('H', 0x83),
SNDRV_EMUX_IOCTL_MEM_AVAIL = _IOW('H', 0x84, int),
- SNDRV_EMUX_IOCTL_MISC_MODE = _IOWR('H', 0x84, struct sndrv_emux_misc_mode),
+ SNDRV_EMUX_IOCTL_MISC_MODE = _IOWR('H', 0x84, struct snd_emux_misc_mode),
};
#endif /* __SOUND_SFNT_INFO_H */
diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h
index 4b0b2b9370b9..0b9e5de94ff1 100644
--- a/include/sound/snd_wavefront.h
+++ b/include/sound/snd_wavefront.h
@@ -26,8 +26,8 @@ struct _snd_wavefront_midi {
snd_wavefront_mpu_id output_mpu; /* most-recently-used */
snd_wavefront_mpu_id input_mpu; /* most-recently-used */
unsigned int mode[2]; /* MPU401_MODE_XXX */
- snd_rawmidi_substream_t *substream_output[2];
- snd_rawmidi_substream_t *substream_input[2];
+ struct snd_rawmidi_substream *substream_output[2];
+ struct snd_rawmidi_substream *substream_input[2];
struct timer_list timer;
spinlock_t open;
spinlock_t virtual; /* protects isvirtual */
@@ -38,8 +38,8 @@ struct _snd_wavefront_midi {
#define MPU_ACK 0xFE
#define UART_MODE_ON 0x3F
-extern snd_rawmidi_ops_t snd_wavefront_midi_output;
-extern snd_rawmidi_ops_t snd_wavefront_midi_input;
+extern struct snd_rawmidi_ops snd_wavefront_midi_output;
+extern struct snd_rawmidi_ops snd_wavefront_midi_input;
extern void snd_wavefront_midi_enable_virtual (snd_wavefront_card_t *);
extern void snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *);
@@ -116,23 +116,23 @@ extern int snd_wavefront_config_midi (snd_wavefront_t *dev) ;
extern int snd_wavefront_cmd (snd_wavefront_t *, int, unsigned char *,
unsigned char *);
-extern int snd_wavefront_synth_ioctl (snd_hwdep_t *,
+extern int snd_wavefront_synth_ioctl (struct snd_hwdep *,
struct file *,
unsigned int cmd,
unsigned long arg);
-extern int snd_wavefront_synth_open (snd_hwdep_t *, struct file *);
-extern int snd_wavefront_synth_release (snd_hwdep_t *, struct file *);
+extern int snd_wavefront_synth_open (struct snd_hwdep *, struct file *);
+extern int snd_wavefront_synth_release (struct snd_hwdep *, struct file *);
/* FX processor - see also yss225.[ch] */
extern int snd_wavefront_fx_start (snd_wavefront_t *);
extern int snd_wavefront_fx_detect (snd_wavefront_t *);
-extern int snd_wavefront_fx_ioctl (snd_hwdep_t *,
+extern int snd_wavefront_fx_ioctl (struct snd_hwdep *,
struct file *,
unsigned int cmd,
unsigned long arg);
-extern int snd_wavefront_fx_open (snd_hwdep_t *, struct file *);
-extern int snd_wavefront_fx_release (snd_hwdep_t *, struct file *);
+extern int snd_wavefront_fx_open (struct snd_hwdep *, struct file *);
+extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *);
/* prefix in all snd_printk() delivered messages */
diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h
index c992958f5e3c..61a010c65d02 100644
--- a/include/sound/soundfont.h
+++ b/include/sound/soundfont.h
@@ -29,94 +29,93 @@
#define SF_MAX_PRESETS 256 /* drums are mapped from 128 to 256 */
#define SF_IS_DRUM_BANK(z) ((z) == 128)
-typedef struct snd_sf_zone {
+struct snd_sf_zone {
struct snd_sf_zone *next; /* Link to next */
unsigned char bank; /* Midi bank for this zone */
unsigned char instr; /* Midi program for this zone */
unsigned char mapped; /* True if mapped to something else */
- soundfont_voice_info_t v; /* All the soundfont parameters */
+ struct soundfont_voice_info v; /* All the soundfont parameters */
int counter;
struct snd_sf_sample *sample; /* Link to sample */
/* The following deals with preset numbers (programs) */
struct snd_sf_zone *next_instr; /* Next zone of this instrument */
struct snd_sf_zone *next_zone; /* Next zone in play list */
-} snd_sf_zone_t;
+};
-typedef struct snd_sf_sample {
- soundfont_sample_info_t v;
+struct snd_sf_sample {
+ struct soundfont_sample_info v;
int counter;
- snd_util_memblk_t *block; /* allocated data block */
+ struct snd_util_memblk *block; /* allocated data block */
struct snd_sf_sample *next;
-} snd_sf_sample_t;
+};
/*
* This represents all the information relating to a soundfont.
*/
-typedef struct snd_soundfont {
+struct snd_soundfont {
struct snd_soundfont *next; /* Link to next */
/*struct snd_soundfont *prev;*/ /* Link to previous */
short id; /* file id */
short type; /* font type */
unsigned char name[SNDRV_SFNT_PATCH_NAME_LEN]; /* identifier */
- snd_sf_zone_t *zones; /* Font information */
- snd_sf_sample_t *samples; /* The sample headers */
-} snd_soundfont_t;
+ struct snd_sf_zone *zones; /* Font information */
+ struct snd_sf_sample *samples; /* The sample headers */
+};
/*
* Type of the sample access callback
*/
-typedef int (*snd_sf_sample_new_t)(void *private_data, snd_sf_sample_t *sp,
- snd_util_memhdr_t *hdr, const void __user *buf, long count);
-typedef int (*snd_sf_sample_free_t)(void *private_data, snd_sf_sample_t *sp,
- snd_util_memhdr_t *hdr);
-typedef void (*snd_sf_sample_reset_t)(void *private);
-
-typedef struct snd_sf_callback {
+struct snd_sf_callback {
void *private_data;
- snd_sf_sample_new_t sample_new;
- snd_sf_sample_free_t sample_free;
- snd_sf_sample_reset_t sample_reset;
-} snd_sf_callback_t;
+ int (*sample_new)(void *private_data, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *buf, long count);
+ int (*sample_free)(void *private_data, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr);
+ void (*sample_reset)(void *private);
+};
/*
* List of soundfonts.
*/
-typedef struct snd_sf_list {
- snd_soundfont_t *currsf; /* The currently open soundfont */
+struct snd_sf_list {
+ struct snd_soundfont *currsf; /* The currently open soundfont */
int open_client; /* client pointer for lock */
int mem_used; /* used memory size */
- snd_sf_zone_t *presets[SF_MAX_PRESETS];
- snd_soundfont_t *fonts; /* The list of soundfonts */
+ struct snd_sf_zone *presets[SF_MAX_PRESETS];
+ struct snd_soundfont *fonts; /* The list of soundfonts */
int fonts_size; /* number of fonts allocated */
int zone_counter; /* last allocated time for zone */
int sample_counter; /* last allocated time for sample */
int zone_locked; /* locked time for zone */
int sample_locked; /* locked time for sample */
- snd_sf_callback_t callback; /* callback functions */
+ struct snd_sf_callback callback; /* callback functions */
int presets_locked;
struct semaphore presets_mutex;
spinlock_t lock;
- snd_util_memhdr_t *memhdr;
-} snd_sf_list_t;
+ struct snd_util_memhdr *memhdr;
+};
/* Prototypes for soundfont.c */
-int snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, int client);
-int snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
+int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
+ long count, int client);
+int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client);
-int snd_soundfont_close_check(snd_sf_list_t *sflist, int client);
+int snd_soundfont_close_check(struct snd_sf_list *sflist, int client);
-snd_sf_list_t *snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr);
-void snd_sf_free(snd_sf_list_t *sflist);
+struct snd_sf_list *snd_sf_new(struct snd_sf_callback *callback,
+ struct snd_util_memhdr *hdr);
+void snd_sf_free(struct snd_sf_list *sflist);
-int snd_soundfont_remove_samples(snd_sf_list_t *sflist);
-int snd_soundfont_remove_unlocked(snd_sf_list_t *sflist);
+int snd_soundfont_remove_samples(struct snd_sf_list *sflist);
+int snd_soundfont_remove_unlocked(struct snd_sf_list *sflist);
-int snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
+int snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
int preset, int bank,
int def_preset, int def_bank,
- snd_sf_zone_t **table, int max_layers);
+ struct snd_sf_zone **table, int max_layers);
/* Parameter conversions */
int snd_sf_calc_parm_hold(int msec);
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index b82e408e758f..a4f554520197 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -24,15 +24,15 @@
#include <linux/videodev.h>
-typedef struct snd_tea575x tea575x_t;
+struct snd_tea575x;
struct snd_tea575x_ops {
- void (*write)(tea575x_t *tea, unsigned int val);
- unsigned int (*read)(tea575x_t *tea);
+ void (*write)(struct snd_tea575x *tea, unsigned int val);
+ unsigned int (*read)(struct snd_tea575x *tea);
};
struct snd_tea575x {
- snd_card_t *card;
+ struct snd_card *card;
struct video_device vd; /* video device */
struct file_operations fops;
int dev_nr; /* requested device number + 1 */
@@ -45,7 +45,7 @@ struct snd_tea575x {
void *private_data;
};
-void snd_tea575x_init(tea575x_t *tea);
-void snd_tea575x_exit(tea575x_t *tea);
+void snd_tea575x_init(struct snd_tea575x *tea);
+void snd_tea575x_exit(struct snd_tea575x *tea);
#endif /* __SOUND_TEA575X_TUNER_H */
diff --git a/include/sound/tea6330t.h b/include/sound/tea6330t.h
index 3896c0a50907..51b282b76896 100644
--- a/include/sound/tea6330t.h
+++ b/include/sound/tea6330t.h
@@ -22,21 +22,10 @@
*
*/
-#include "control.h"
#include "i2c.h" /* generic i2c support */
-typedef struct {
- snd_i2c_device_t *device;
- snd_i2c_bus_t *bus;
- int equalizer;
- int fader;
- unsigned char regs[8];
- unsigned char mleft, mright;
- unsigned char bass, treble;
- unsigned char max_bass, max_treble;
-} tea6330t_t;
-
-extern int snd_tea6330t_detect(snd_i2c_bus_t *bus, int equalizer);
-extern int snd_tea6330t_update_mixer(snd_card_t * card, snd_i2c_bus_t * bus, int equalizer, int fader);
+int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer);
+int snd_tea6330t_update_mixer(struct snd_card *card, struct snd_i2c_bus *bus,
+ int equalizer, int fader);
#endif /* __SOUND_TEA6330T_H */
diff --git a/include/sound/timer.h b/include/sound/timer.h
index b55f38ae56e1..5ece2bf541dc 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -26,20 +26,6 @@
#include <sound/asound.h>
#include <linux/interrupt.h>
-typedef enum sndrv_timer_class snd_timer_class_t;
-typedef enum sndrv_timer_slave_class snd_timer_slave_class_t;
-typedef enum sndrv_timer_global snd_timer_global_t;
-typedef struct sndrv_timer_id snd_timer_id_t;
-typedef struct sndrv_timer_ginfo snd_timer_ginfo_t;
-typedef struct sndrv_timer_gparams snd_timer_gparams_t;
-typedef struct sndrv_timer_gstatus snd_timer_gstatus_t;
-typedef struct sndrv_timer_select snd_timer_select_t;
-typedef struct sndrv_timer_info snd_timer_info_t;
-typedef struct sndrv_timer_params snd_timer_params_t;
-typedef struct sndrv_timer_status snd_timer_status_t;
-typedef struct sndrv_timer_read snd_timer_read_t;
-typedef struct sndrv_timer_tread snd_timer_tread_t;
-
#define snd_timer_chip(timer) ((timer)->private_data)
#define SNDRV_TIMER_DEVICES 16
@@ -64,11 +50,9 @@ typedef struct sndrv_timer_tread snd_timer_tread_t;
#define SNDRV_TIMER_FLG_CHANGE 0x00000001
#define SNDRV_TIMER_FLG_RESCHED 0x00000002 /* need reschedule */
-typedef void (*snd_timer_callback_t) (snd_timer_instance_t * timeri, unsigned long ticks, unsigned long resolution);
-typedef void (*snd_timer_ccallback_t) (snd_timer_instance_t * timeri, enum sndrv_timer_event event,
- struct timespec * tstamp, unsigned long resolution);
+struct snd_timer;
-struct _snd_timer_hardware {
+struct snd_timer_hardware {
/* -- must be filled with low-level driver */
unsigned int flags; /* various flags */
unsigned long resolution; /* average timer resolution for one tick in nsec */
@@ -76,18 +60,18 @@ struct _snd_timer_hardware {
unsigned long resolution_max; /* maximal resolution */
unsigned long ticks; /* max timer ticks per interrupt */
/* -- low-level functions -- */
- int (*open) (snd_timer_t * timer);
- int (*close) (snd_timer_t * timer);
- unsigned long (*c_resolution) (snd_timer_t * timer);
- int (*start) (snd_timer_t * timer);
- int (*stop) (snd_timer_t * timer);
- int (*set_period) (snd_timer_t * timer, unsigned long period_num, unsigned long period_den);
- int (*precise_resolution) (snd_timer_t * timer, unsigned long *num, unsigned long *den);
+ int (*open) (struct snd_timer * timer);
+ int (*close) (struct snd_timer * timer);
+ unsigned long (*c_resolution) (struct snd_timer * timer);
+ int (*start) (struct snd_timer * timer);
+ int (*stop) (struct snd_timer * timer);
+ int (*set_period) (struct snd_timer * timer, unsigned long period_num, unsigned long period_den);
+ int (*precise_resolution) (struct snd_timer * timer, unsigned long *num, unsigned long *den);
};
-struct _snd_timer {
- snd_timer_class_t tmr_class;
- snd_card_t *card;
+struct snd_timer {
+ int tmr_class;
+ struct snd_card *card;
struct module *module;
int tmr_device;
int tmr_subdevice;
@@ -97,8 +81,8 @@ struct _snd_timer {
int running; /* running instances */
unsigned long sticks; /* schedule ticks */
void *private_data;
- void (*private_free) (snd_timer_t *timer);
- struct _snd_timer_hardware hw;
+ void (*private_free) (struct snd_timer *timer);
+ struct snd_timer_hardware hw;
spinlock_t lock;
struct list_head device_list;
struct list_head open_list_head;
@@ -108,49 +92,53 @@ struct _snd_timer {
struct tasklet_struct task_queue;
};
-struct _snd_timer_instance {
- snd_timer_t * timer;
+struct snd_timer_instance {
+ struct snd_timer *timer;
char *owner;
unsigned int flags;
void *private_data;
- void (*private_free) (snd_timer_instance_t *ti);
- snd_timer_callback_t callback;
- snd_timer_ccallback_t ccallback;
+ void (*private_free) (struct snd_timer_instance *ti);
+ void (*callback) (struct snd_timer_instance *timeri,
+ unsigned long ticks, unsigned long resolution);
+ void (*ccallback) (struct snd_timer_instance * timeri,
+ int event,
+ struct timespec * tstamp,
+ unsigned long resolution);
void *callback_data;
unsigned long ticks; /* auto-load ticks when expired */
unsigned long cticks; /* current ticks */
unsigned long pticks; /* accumulated ticks for callback */
unsigned long resolution; /* current resolution for tasklet */
unsigned long lost; /* lost ticks */
- snd_timer_slave_class_t slave_class;
+ int slave_class;
unsigned int slave_id;
struct list_head open_list;
struct list_head active_list;
struct list_head ack_list;
struct list_head slave_list_head;
struct list_head slave_active_head;
- snd_timer_instance_t *master;
+ struct snd_timer_instance *master;
};
/*
* Registering
*/
-extern int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t ** rtimer);
-extern void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event, struct timespec *tstamp);
-extern int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer);
-extern int snd_timer_global_free(snd_timer_t *timer);
-extern int snd_timer_global_register(snd_timer_t *timer);
-extern int snd_timer_global_unregister(snd_timer_t *timer);
-
-extern int snd_timer_open(snd_timer_instance_t ** ti, char *owner, snd_timer_id_t *tid, unsigned int slave_id);
-extern int snd_timer_close(snd_timer_instance_t * timeri);
-extern unsigned long snd_timer_resolution(snd_timer_instance_t * timeri);
-extern int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks);
-extern int snd_timer_stop(snd_timer_instance_t * timeri);
-extern int snd_timer_continue(snd_timer_instance_t * timeri);
-extern int snd_timer_pause(snd_timer_instance_t * timeri);
-
-extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left);
+int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer);
+void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp);
+int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
+int snd_timer_global_free(struct snd_timer *timer);
+int snd_timer_global_register(struct snd_timer *timer);
+int snd_timer_global_unregister(struct snd_timer *timer);
+
+int snd_timer_open(struct snd_timer_instance **ti, char *owner, struct snd_timer_id *tid, unsigned int slave_id);
+int snd_timer_close(struct snd_timer_instance *timeri);
+unsigned long snd_timer_resolution(struct snd_timer_instance *timeri);
+int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks);
+int snd_timer_stop(struct snd_timer_instance *timeri);
+int snd_timer_continue(struct snd_timer_instance *timeri);
+int snd_timer_pause(struct snd_timer_instance *timeri);
+
+void snd_timer_interrupt(struct snd_timer *timer, unsigned long ticks_left);
#endif /* __SOUND_TIMER_H */
diff --git a/include/sound/trident.h b/include/sound/trident.h
index a408d3925050..9752243241e5 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -253,43 +253,43 @@ enum serial_intf_ctrl_bits {
#define T4D_DEFAULT_PCM_RVOL 127 /* 0 - 127 */
#define T4D_DEFAULT_PCM_CVOL 127 /* 0 - 127 */
-typedef struct _snd_trident trident_t;
-typedef struct _snd_trident_voice snd_trident_voice_t;
-typedef struct _snd_trident_pcm_mixer snd_trident_pcm_mixer_t;
-
-typedef struct {
- void (*sample_start)(trident_t *gus, snd_trident_voice_t *voice, snd_seq_position_t position);
- void (*sample_stop)(trident_t *gus, snd_trident_voice_t *voice, snd_seq_stop_mode_t mode);
- void (*sample_freq)(trident_t *gus, snd_trident_voice_t *voice, snd_seq_frequency_t freq);
- void (*sample_volume)(trident_t *gus, snd_trident_voice_t *voice, snd_seq_ev_volume_t *volume);
- void (*sample_loop)(trident_t *card, snd_trident_voice_t *voice, snd_seq_ev_loop_t *loop);
- void (*sample_pos)(trident_t *card, snd_trident_voice_t *voice, snd_seq_position_t position);
- void (*sample_private1)(trident_t *card, snd_trident_voice_t *voice, unsigned char *data);
-} snd_trident_sample_ops_t;
-
-typedef struct {
- snd_midi_channel_set_t * chset;
- trident_t * trident;
+struct snd_trident;
+struct snd_trident_voice;
+struct snd_trident_pcm_mixer;
+
+struct snd_trident_sample_ops {
+ void (*sample_start)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_position_t position);
+ void (*sample_stop)(struct snd_trident *gus, struct snd_trident_voice *voice, int mode);
+ void (*sample_freq)(struct snd_trident *gus, struct snd_trident_voice *voice, snd_seq_frequency_t freq);
+ void (*sample_volume)(struct snd_trident *gus, struct snd_trident_voice *voice, struct snd_seq_ev_volume *volume);
+ void (*sample_loop)(struct snd_trident *card, struct snd_trident_voice *voice, struct snd_seq_ev_loop *loop);
+ void (*sample_pos)(struct snd_trident *card, struct snd_trident_voice *voice, snd_seq_position_t position);
+ void (*sample_private1)(struct snd_trident *card, struct snd_trident_voice *voice, unsigned char *data);
+};
+
+struct snd_trident_port {
+ struct snd_midi_channel_set * chset;
+ struct snd_trident * trident;
int mode; /* operation mode */
int client; /* sequencer client number */
int port; /* sequencer port number */
unsigned int midi_has_voices: 1;
-} snd_trident_port_t;
+};
-typedef struct snd_trident_memblk_arg {
+struct snd_trident_memblk_arg {
short first_page, last_page;
-} snd_trident_memblk_arg_t;
+};
-typedef struct {
+struct snd_trident_tlb {
unsigned int * entries; /* 16k-aligned TLB table */
dma_addr_t entries_dmaaddr; /* 16k-aligned PCI address to TLB table */
unsigned long * shadow_entries; /* shadow entries with virtual addresses */
struct snd_dma_buffer buffer;
- snd_util_memhdr_t * memhdr; /* page allocation list */
+ struct snd_util_memhdr * memhdr; /* page allocation list */
struct snd_dma_buffer silent_page;
-} snd_trident_tlb_t;
+};
-struct _snd_trident_voice {
+struct snd_trident_voice {
unsigned int number;
unsigned int use: 1,
pcm: 1,
@@ -300,8 +300,8 @@ struct _snd_trident_voice {
unsigned char port;
unsigned char index;
- snd_seq_instr_t instr;
- snd_trident_sample_ops_t *sample_ops;
+ struct snd_seq_instr instr;
+ struct snd_trident_sample_ops *sample_ops;
/* channel parameters */
unsigned int CSO; /* 24 bits (16 on DX) */
@@ -323,13 +323,13 @@ struct _snd_trident_voice {
unsigned int negCSO; /* nonzero - use negative CSO */
- snd_util_memblk_t *memblk; /* memory block if TLB enabled */
+ struct snd_util_memblk *memblk; /* memory block if TLB enabled */
/* PCM data */
- trident_t *trident;
- snd_pcm_substream_t *substream;
- snd_trident_voice_t *extra; /* extra PCM voice (acts as interrupt generator) */
+ struct snd_trident *trident;
+ struct snd_pcm_substream *substream;
+ struct snd_trident_voice *extra; /* extra PCM voice (acts as interrupt generator) */
unsigned int running: 1,
capture: 1,
spdif: 1,
@@ -347,25 +347,25 @@ struct _snd_trident_voice {
/* --- */
void *private_data;
- void (*private_free)(snd_trident_voice_t *voice);
+ void (*private_free)(struct snd_trident_voice *voice);
};
-struct _snd_4dwave {
+struct snd_4dwave {
int seq_client;
- snd_trident_port_t seq_ports[4];
- snd_simple_ops_t simple_ops;
- snd_seq_kinstr_list_t *ilist;
+ struct snd_trident_port seq_ports[4];
+ struct snd_simple_ops simple_ops;
+ struct snd_seq_kinstr_list *ilist;
- snd_trident_voice_t voices[64];
+ struct snd_trident_voice voices[64];
int ChanSynthCount; /* number of allocated synth channels */
int max_size; /* maximum synth memory size in bytes */
int current_size; /* current allocated synth mem in bytes */
};
-struct _snd_trident_pcm_mixer {
- snd_trident_voice_t *voice; /* active voice */
+struct snd_trident_pcm_mixer {
+ struct snd_trident_voice *voice; /* active voice */
unsigned short vol; /* front volume */
unsigned char pan; /* pan control */
unsigned char rvol; /* rear volume */
@@ -373,7 +373,7 @@ struct _snd_trident_pcm_mixer {
unsigned char pad;
};
-struct _snd_trident {
+struct snd_trident {
int irq;
unsigned int device; /* device ID */
@@ -386,13 +386,13 @@ struct _snd_trident {
unsigned int spurious_irq_count;
unsigned int spurious_irq_max_delta;
- snd_trident_tlb_t tlb; /* TLB entries for NX cards */
+ struct snd_trident_tlb tlb; /* TLB entries for NX cards */
unsigned char spdif_ctrl;
unsigned char spdif_pcm_ctrl;
unsigned int spdif_bits;
unsigned int spdif_pcm_bits;
- snd_kcontrol_t *spdif_pcm_ctl; /* S/PDIF settings */
+ struct snd_kcontrol *spdif_pcm_ctl; /* S/PDIF settings */
unsigned int ac97_ctrl;
unsigned int ChanMap[2]; /* allocation map for hardware channels */
@@ -403,7 +403,7 @@ struct _snd_trident {
unsigned int ac97_detect: 1; /* 1 = AC97 in detection phase */
unsigned int in_suspend: 1; /* 1 during suspend/resume */
- struct _snd_4dwave synth; /* synth specific variables */
+ struct snd_4dwave synth; /* synth specific variables */
spinlock_t event_lock;
spinlock_t voice_alloc;
@@ -411,52 +411,57 @@ struct _snd_trident {
struct snd_dma_device dma_dev;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm; /* ADC/DAC PCM */
- snd_pcm_t *foldback; /* Foldback PCM */
- snd_pcm_t *spdif; /* SPDIF PCM */
- snd_rawmidi_t *rmidi;
- snd_seq_device_t *seq_dev;
+ struct snd_card *card;
+ struct snd_pcm *pcm; /* ADC/DAC PCM */
+ struct snd_pcm *foldback; /* Foldback PCM */
+ struct snd_pcm *spdif; /* SPDIF PCM */
+ struct snd_rawmidi *rmidi;
+ struct snd_seq_device *seq_dev;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
- ac97_t *ac97_sec;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
+ struct snd_ac97 *ac97_sec;
unsigned int musicvol_wavevol;
- snd_trident_pcm_mixer_t pcm_mixer[32];
- snd_kcontrol_t *ctl_vol; /* front volume */
- snd_kcontrol_t *ctl_pan; /* pan */
- snd_kcontrol_t *ctl_rvol; /* rear volume */
- snd_kcontrol_t *ctl_cvol; /* center volume */
+ struct snd_trident_pcm_mixer pcm_mixer[32];
+ struct snd_kcontrol *ctl_vol; /* front volume */
+ struct snd_kcontrol *ctl_pan; /* pan */
+ struct snd_kcontrol *ctl_rvol; /* rear volume */
+ struct snd_kcontrol *ctl_cvol; /* center volume */
spinlock_t reg_lock;
struct gameport *gameport;
};
-int snd_trident_create(snd_card_t * card,
+int snd_trident_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
int max_wavetable_size,
- trident_t ** rtrident);
-int snd_trident_create_gameport(trident_t *trident);
-
-int snd_trident_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
-int snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
-int snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
-int snd_trident_attach_synthesizer(trident_t * trident);
-snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int client, int port);
-void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice);
-void snd_trident_start_voice(trident_t * trident, unsigned int voice);
-void snd_trident_stop_voice(trident_t * trident, unsigned int voice);
-void snd_trident_write_voice_regs(trident_t * trident, snd_trident_voice_t *voice);
+ struct snd_trident ** rtrident);
+int snd_trident_create_gameport(struct snd_trident *trident);
+
+int snd_trident_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
+int snd_trident_foldback_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
+int snd_trident_spdif_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
+int snd_trident_attach_synthesizer(struct snd_trident * trident);
+struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type,
+ int client, int port);
+void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice);
+void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice);
+void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice);
+void snd_trident_write_voice_regs(struct snd_trident * trident, struct snd_trident_voice *voice);
+int snd_trident_suspend(struct pci_dev *pci, pm_message_t state);
+int snd_trident_resume(struct pci_dev *pci);
/* TLB memory allocation */
-snd_util_memblk_t *snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream);
-int snd_trident_free_pages(trident_t *trident, snd_util_memblk_t *blk);
-snd_util_memblk_t *snd_trident_synth_alloc(trident_t *trident, unsigned int size);
-int snd_trident_synth_free(trident_t *trident, snd_util_memblk_t *blk);
-int snd_trident_synth_copy_from_user(trident_t *trident, snd_util_memblk_t *blk, int offset, const char __user *data, int size);
+struct snd_util_memblk *snd_trident_alloc_pages(struct snd_trident *trident,
+ struct snd_pcm_substream *substream);
+int snd_trident_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk);
+struct snd_util_memblk *snd_trident_synth_alloc(struct snd_trident *trident, unsigned int size);
+int snd_trident_synth_free(struct snd_trident *trident, struct snd_util_memblk *blk);
+int snd_trident_synth_copy_from_user(struct snd_trident *trident, struct snd_util_memblk *blk,
+ int offset, const char __user *data, int size);
#endif /* __SOUND_TRIDENT_H */
diff --git a/include/sound/typedefs.h b/include/sound/typedefs.h
new file mode 100644
index 000000000000..f454b0206b93
--- /dev/null
+++ b/include/sound/typedefs.h
@@ -0,0 +1,173 @@
+/*
+ * Typedef's for backward compatibility (for out-of-kernel drivers)
+ *
+ * This file will be removed soon in future
+ */
+
+/* core stuff */
+typedef struct snd_card snd_card_t;
+typedef struct snd_device snd_device_t;
+typedef struct snd_device_ops snd_device_ops_t;
+typedef enum snd_card_type snd_card_type_t;
+typedef struct snd_minor snd_minor_t;
+
+/* info */
+typedef struct snd_info_entry snd_info_entry_t;
+typedef struct snd_info_buffer snd_info_buffer_t;
+
+/* control */
+typedef struct snd_ctl_file snd_ctl_file_t;
+typedef struct snd_kcontrol snd_kcontrol_t;
+typedef struct snd_kcontrol_new snd_kcontrol_new_t;
+typedef struct snd_kcontrol_volatile snd_kcontrol_volatile_t;
+typedef struct snd_kctl_event snd_kctl_event_t;
+typedef struct snd_aes_iec958 snd_aes_iec958_t;
+typedef struct snd_ctl_card_info snd_ctl_card_info_t;
+typedef struct snd_ctl_elem_id snd_ctl_elem_id_t;
+typedef struct snd_ctl_elem_list snd_ctl_elem_list_t;
+typedef struct snd_ctl_elem_info snd_ctl_elem_info_t;
+typedef struct snd_ctl_elem_value snd_ctl_elem_value_t;
+typedef struct snd_ctl_event snd_ctl_event_t;
+#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
+typedef struct snd_mixer_oss snd_mixer_oss_t;
+#endif
+
+/* timer */
+typedef struct snd_timer snd_timer_t;
+typedef struct snd_timer_instance snd_timer_instance_t;
+typedef struct snd_timer_id snd_timer_id_t;
+typedef struct snd_timer_ginfo snd_timer_ginfo_t;
+typedef struct snd_timer_gparams snd_timer_gparams_t;
+typedef struct snd_timer_gstatus snd_timer_gstatus_t;
+typedef struct snd_timer_select snd_timer_select_t;
+typedef struct snd_timer_info snd_timer_info_t;
+typedef struct snd_timer_params snd_timer_params_t;
+typedef struct snd_timer_status snd_timer_status_t;
+typedef struct snd_timer_read snd_timer_read_t;
+typedef struct snd_timer_tread snd_timer_tread_t;
+
+/* PCM */
+typedef struct snd_pcm snd_pcm_t;
+typedef struct snd_pcm_str snd_pcm_str_t;
+typedef struct snd_pcm_substream snd_pcm_substream_t;
+typedef struct snd_pcm_info snd_pcm_info_t;
+typedef struct snd_pcm_hw_params snd_pcm_hw_params_t;
+typedef struct snd_pcm_sw_params snd_pcm_sw_params_t;
+typedef struct snd_pcm_channel_info snd_pcm_channel_info_t;
+typedef struct snd_pcm_status snd_pcm_status_t;
+typedef struct snd_pcm_mmap_status snd_pcm_mmap_status_t;
+typedef struct snd_pcm_mmap_control snd_pcm_mmap_control_t;
+typedef struct snd_mask snd_mask_t;
+typedef struct snd_sg_buf snd_pcm_sgbuf_t;
+
+typedef struct snd_interval snd_interval_t;
+typedef struct snd_xferi snd_xferi_t;
+typedef struct snd_xfern snd_xfern_t;
+typedef struct snd_xferv snd_xferv_t;
+
+typedef struct snd_pcm_file snd_pcm_file_t;
+typedef struct snd_pcm_runtime snd_pcm_runtime_t;
+typedef struct snd_pcm_hardware snd_pcm_hardware_t;
+typedef struct snd_pcm_ops snd_pcm_ops_t;
+typedef struct snd_pcm_hw_rule snd_pcm_hw_rule_t;
+typedef struct snd_pcm_hw_constraints snd_pcm_hw_constraints_t;
+typedef struct snd_ratnum ratnum_t;
+typedef struct snd_ratden ratden_t;
+typedef struct snd_pcm_hw_constraint_ratnums snd_pcm_hw_constraint_ratnums_t;
+typedef struct snd_pcm_hw_constraint_ratdens snd_pcm_hw_constraint_ratdens_t;
+typedef struct snd_pcm_hw_constraint_list snd_pcm_hw_constraint_list_t;
+typedef struct snd_pcm_group snd_pcm_group_t;
+typedef struct snd_pcm_notify snd_pcm_notify_t;
+
+/* rawmidi */
+typedef struct snd_rawmidi snd_rawmidi_t;
+typedef struct snd_rawmidi_info snd_rawmidi_info_t;
+typedef struct snd_rawmidi_params snd_rawmidi_params_t;
+typedef struct snd_rawmidi_status snd_rawmidi_status_t;
+typedef struct snd_rawmidi_runtime snd_rawmidi_runtime_t;
+typedef struct snd_rawmidi_substream snd_rawmidi_substream_t;
+typedef struct snd_rawmidi_str snd_rawmidi_str_t;
+typedef struct snd_rawmidi_ops snd_rawmidi_ops_t;
+typedef struct snd_rawmidi_global_ops snd_rawmidi_global_ops_t;
+typedef struct snd_rawmidi_file snd_rawmidi_file_t;
+
+/* hwdep */
+typedef struct snd_hwdep snd_hwdep_t;
+typedef struct snd_hwdep_info snd_hwdep_info_t;
+typedef struct snd_hwdep_dsp_status snd_hwdep_dsp_status_t;
+typedef struct snd_hwdep_dsp_image snd_hwdep_dsp_image_t;
+typedef struct snd_hwdep_ops snd_hwdep_ops_t;
+
+/* sequencer */
+typedef struct snd_seq_port_info snd_seq_port_info_t;
+typedef struct snd_seq_port_subscribe snd_seq_port_subscribe_t;
+typedef struct snd_seq_event snd_seq_event_t;
+typedef struct snd_seq_addr snd_seq_addr_t;
+typedef struct snd_seq_ev_volume snd_seq_ev_volume_t;
+typedef struct snd_seq_ev_loop snd_seq_ev_loop_t;
+typedef struct snd_seq_remove_events snd_seq_remove_events_t;
+typedef struct snd_seq_query_subs snd_seq_query_subs_t;
+typedef struct snd_seq_system_info snd_seq_system_info_t;
+typedef struct snd_seq_client_info snd_seq_client_info_t;
+typedef struct snd_seq_queue_info snd_seq_queue_info_t;
+typedef struct snd_seq_queue_status snd_seq_queue_status_t;
+typedef struct snd_seq_queue_tempo snd_seq_queue_tempo_t;
+typedef struct snd_seq_queue_owner snd_seq_queue_owner_t;
+typedef struct snd_seq_queue_timer snd_seq_queue_timer_t;
+typedef struct snd_seq_queue_client snd_seq_queue_client_t;
+typedef struct snd_seq_client_pool snd_seq_client_pool_t;
+typedef struct snd_seq_instr snd_seq_instr_t;
+typedef struct snd_seq_instr_data snd_seq_instr_data_t;
+typedef struct snd_seq_instr_header snd_seq_instr_header_t;
+
+typedef struct snd_seq_user_client user_client_t;
+typedef struct snd_seq_kernel_client kernel_client_t;
+typedef struct snd_seq_client client_t;
+typedef struct snd_seq_queue queue_t;
+
+/* seq_device */
+typedef struct snd_seq_device snd_seq_device_t;
+typedef struct snd_seq_dev_ops snd_seq_dev_ops_t;
+
+/* seq_midi */
+typedef struct snd_midi_event snd_midi_event_t;
+
+/* seq_midi_emul */
+typedef struct snd_midi_channel snd_midi_channel_t;
+typedef struct snd_midi_channel_set snd_midi_channel_set_t;
+typedef struct snd_midi_op snd_midi_op_t;
+
+/* seq_oss */
+typedef struct snd_seq_oss_arg snd_seq_oss_arg_t;
+typedef struct snd_seq_oss_callback snd_seq_oss_callback_t;
+typedef struct snd_seq_oss_reg snd_seq_oss_reg_t;
+
+/* virmidi */
+typedef struct snd_virmidi_dev snd_virmidi_dev_t;
+typedef struct snd_virmidi snd_virmidi_t;
+
+/* seq_instr */
+typedef struct snd_seq_kcluster snd_seq_kcluster_t;
+typedef struct snd_seq_kinstr_ops snd_seq_kinstr_ops_t;
+typedef struct snd_seq_kinstr snd_seq_kinstr_t;
+typedef struct snd_seq_kinstr_list snd_seq_kinstr_list_t;
+
+/* ac97 */
+typedef struct snd_ac97_bus ac97_bus_t;
+typedef struct snd_ac97_bus_ops ac97_bus_ops_t;
+typedef struct snd_ac97_template ac97_template_t;
+typedef struct snd_ac97 ac97_t;
+
+/* opl3/4 */
+typedef struct snd_opl3 opl3_t;
+typedef struct snd_opl4 opl4_t;
+
+/* mpu401 */
+typedef struct snd_mpu401 mpu401_t;
+
+/* i2c */
+typedef struct snd_i2c_device snd_i2c_device_t;
+typedef struct snd_i2c_bus snd_i2c_bus_t;
+
+typedef struct snd_ak4531 ak4531_t;
+
diff --git a/include/sound/uda1341.h b/include/sound/uda1341.h
index 61ff65a628bc..2e564bfb37fe 100644
--- a/include/sound/uda1341.h
+++ b/include/sound/uda1341.h
@@ -15,7 +15,7 @@
* features support
*/
-/* $Id: uda1341.h,v 1.6 2004/05/03 17:36:50 tiwai Exp $ */
+/* $Id: uda1341.h,v 1.8 2005/11/17 14:17:21 tiwai Exp $ */
#define UDA1341_ALSA_NAME "snd-uda1341"
@@ -37,11 +37,6 @@ enum uda1341_onoff {
ON,
};
-const char *onoff_names[] = {
- "Off",
- "On",
-};
-
enum uda1341_format {
I2S=0,
LSB16,
@@ -53,17 +48,6 @@ enum uda1341_format {
LSB20MSB,
};
-const char *format_names[] = {
- "I2S-bus",
- "LSB 16bits",
- "LSB 18bits",
- "LSB 20bits",
- "MSB",
- "in LSB 16bits/out MSB",
- "in LSB 18bits/out MSB",
- "in LSB 20bits/out MSB",
-};
-
enum uda1341_fs {
F512=0,
F384,
@@ -71,23 +55,11 @@ enum uda1341_fs {
Funused,
};
-const char *fs_names[] = {
- "512*fs",
- "384*fs",
- "256*fs",
- "Unused - bad value!",
-};
-
enum uda1341_peak {
BEFORE=0,
AFTER,
};
-const char *peak_names[] = {
- "before",
- "after",
-};
-
enum uda1341_filter {
FLAT=0,
MIN,
@@ -95,24 +67,6 @@ enum uda1341_filter {
MAX,
};
-const char *filter_names[] = {
- "flat",
- "min",
- "min",
- "max",
-};
-
-const char*bass_values[][16] = {
- {"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB",
- "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
- "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
- "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
- {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB",
- "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max
-};
-
enum uda1341_mixer {
DOUBLE,
LINE,
@@ -120,13 +74,6 @@ enum uda1341_mixer {
MIXER,
};
-const char *mixer_names[] = {
- "double differential",
- "input channel 1 (line in)",
- "input channel 2 (microphone)",
- "digital mixer",
-};
-
enum uda1341_deemp {
NONE,
D32,
@@ -134,58 +81,6 @@ enum uda1341_deemp {
D48,
};
-const char *deemp_names[] = {
- "none",
- "32 kHz",
- "44.1 kHz",
- "48 kHz",
-};
-
-const char *mic_sens_value[] = {
- "-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used",
-};
-
-const unsigned short AGC_atime[] = {
- 11, 16, 11, 16, 21, 11, 16, 21,
-};
-
-const unsigned short AGC_dtime[] = {
- 100, 100, 200, 200, 200, 400, 400, 400,
-};
-
-const char *AGC_level[] = {
- "-9.0", "-11.5", "-15.0", "-17.5",
-};
-
-const char *ig_small_value[] = {
- "-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5",
-};
-
-/*
- * this was computed as peak_value[i] = pow((63-i)*1.42,1.013)
- *
- * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2
- * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29
- * [61]=-2.78, [62] = -1.48, [63] = 0.0
- * I tried to compute it, but using but even using logarithm with base either 10 or 2
- * i was'n able to get values in the table from the formula. So I constructed another
- * formula (see above) to interpolate the values as good as possible. If there is some
- * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks.
- * UDA1341TS datasheet is available at:
- * http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf
- */
-const char *peak_value[] = {
- "-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB",
- "-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB",
- "-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB",
- "-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB",
- "-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB",
- "-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB",
- "-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB",
- "-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB",
- "-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB",
-};
-
enum uda1341_config {
CMD_READ_REG = 0,
CMD_RESET,
@@ -224,7 +119,7 @@ enum write_through {
FLUSH,
};
-int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt);
+int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clnt);
/*
* Local variables:
diff --git a/include/sound/util_mem.h b/include/sound/util_mem.h
index 9d2cdfa0c42a..69944bbb5445 100644
--- a/include/sound/util_mem.h
+++ b/include/sound/util_mem.h
@@ -20,29 +20,25 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-typedef struct snd_util_memblk snd_util_memblk_t;
-typedef struct snd_util_memhdr snd_util_memhdr_t;
-typedef unsigned int snd_util_unit_t;
-
/*
* memory block
*/
struct snd_util_memblk {
- snd_util_unit_t size; /* size of this block */
- snd_util_unit_t offset; /* zero-offset of this block */
+ unsigned int size; /* size of this block */
+ unsigned int offset; /* zero-offset of this block */
struct list_head list; /* link */
};
-#define snd_util_memblk_argptr(blk) (void*)((char*)(blk) + sizeof(snd_util_memblk_t))
+#define snd_util_memblk_argptr(blk) (void*)((char*)(blk) + sizeof(struct snd_util_memblk))
/*
* memory management information
*/
struct snd_util_memhdr {
- snd_util_unit_t size; /* size of whole data */
+ unsigned int size; /* size of whole data */
struct list_head block; /* block linked-list header */
int nblocks; /* # of allocated blocks */
- snd_util_unit_t used; /* used memory size */
+ unsigned int used; /* used memory size */
int block_extra_size; /* extra data size of chunk */
struct semaphore block_mutex; /* lock */
};
@@ -50,15 +46,17 @@ struct snd_util_memhdr {
/*
* prototypes
*/
-snd_util_memhdr_t *snd_util_memhdr_new(int memsize);
-void snd_util_memhdr_free(snd_util_memhdr_t *hdr);
-snd_util_memblk_t *snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size);
-int snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk);
-int snd_util_mem_avail(snd_util_memhdr_t *hdr);
+struct snd_util_memhdr *snd_util_memhdr_new(int memsize);
+void snd_util_memhdr_free(struct snd_util_memhdr *hdr);
+struct snd_util_memblk *snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size);
+int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk);
+int snd_util_mem_avail(struct snd_util_memhdr *hdr);
/* functions without mutex */
-snd_util_memblk_t *__snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size);
-void __snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk);
-snd_util_memblk_t *__snd_util_memblk_new(snd_util_memhdr_t *hdr, snd_util_unit_t units, struct list_head *prev);
+struct snd_util_memblk *__snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size);
+void __snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk);
+struct snd_util_memblk *__snd_util_memblk_new(struct snd_util_memhdr *hdr,
+ unsigned int units,
+ struct list_head *prev);
#endif /* __SOUND_UTIL_MEM_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index d1bd3b723967..919da0dd001c 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.10rc3"
-#define CONFIG_SND_DATE " (Mon Nov 07 13:30:21 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.11rc2"
+#define CONFIG_SND_DATE " (Wed Jan 04 08:57:20 2006 UTC)"
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 7a60a3888667..5fd6f3305e0d 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -36,9 +36,6 @@
struct firmware;
struct device;
-typedef struct snd_vx_core vx_core_t;
-typedef struct vx_pipe vx_pipe_t;
-
#define VX_DRIVER_VERSION 0x010000 /* 1.0.0 */
/*
@@ -76,7 +73,7 @@ struct vx_pipe {
int channels;
unsigned int differed_type;
pcx_time_t pcx_time;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int hbuf_size; /* H-buffer size in bytes */
int buffer_bytes; /* the ALSA pcm buffer size in bytes */
@@ -88,36 +85,38 @@ struct vx_pipe {
u64 cur_count; /* current sample position (for playback) */
unsigned int references; /* an output pipe may be used for monitoring and/or playback */
- vx_pipe_t *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/
+ struct vx_pipe *monitoring_pipe; /* pointer to the monitoring pipe (capture pipe only)*/
struct tasklet_struct start_tq;
};
+struct vx_core;
+
struct snd_vx_ops {
/* low-level i/o */
- unsigned char (*in8)(vx_core_t *chip, int reg);
- unsigned int (*in32)(vx_core_t *chip, int reg);
- void (*out8)(vx_core_t *chip, int reg, unsigned char val);
- void (*out32)(vx_core_t *chip, int reg, unsigned int val);
+ unsigned char (*in8)(struct vx_core *chip, int reg);
+ unsigned int (*in32)(struct vx_core *chip, int reg);
+ void (*out8)(struct vx_core *chip, int reg, unsigned char val);
+ void (*out32)(struct vx_core *chip, int reg, unsigned int val);
/* irq */
- int (*test_and_ack)(vx_core_t *chip);
- void (*validate_irq)(vx_core_t *chip, int enable);
+ int (*test_and_ack)(struct vx_core *chip);
+ void (*validate_irq)(struct vx_core *chip, int enable);
/* codec */
- void (*write_codec)(vx_core_t *chip, int codec, unsigned int data);
- void (*akm_write)(vx_core_t *chip, int reg, unsigned int data);
- void (*reset_codec)(vx_core_t *chip);
- void (*change_audio_source)(vx_core_t *chip, int src);
- void (*set_clock_source)(vx_core_t *chp, int src);
+ void (*write_codec)(struct vx_core *chip, int codec, unsigned int data);
+ void (*akm_write)(struct vx_core *chip, int reg, unsigned int data);
+ void (*reset_codec)(struct vx_core *chip);
+ void (*change_audio_source)(struct vx_core *chip, int src);
+ void (*set_clock_source)(struct vx_core *chp, int src);
/* chip init */
- int (*load_dsp)(vx_core_t *chip, int idx, const struct firmware *fw);
- void (*reset_dsp)(vx_core_t *chip);
- void (*reset_board)(vx_core_t *chip, int cold_reset);
- int (*add_controls)(vx_core_t *chip);
+ int (*load_dsp)(struct vx_core *chip, int idx, const struct firmware *fw);
+ void (*reset_dsp)(struct vx_core *chip);
+ void (*reset_board)(struct vx_core *chip, int cold_reset);
+ int (*add_controls)(struct vx_core *chip);
/* pcm */
- void (*dma_write)(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count);
- void (*dma_read)(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count);
+ void (*dma_write)(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count);
+ void (*dma_read)(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count);
};
struct snd_vx_hardware {
@@ -158,10 +157,10 @@ enum {
/* min/max values for analog output for old codecs */
#define VX_ANALOG_OUT_LEVEL_MAX 0xe3
-struct snd_vx_core {
+struct vx_core {
/* ALSA stuff */
- snd_card_t *card;
- snd_pcm_t *pcm[VX_MAX_CODECS];
+ struct snd_card *card;
+ struct snd_pcm *pcm[VX_MAX_CODECS];
int type; /* VX_TYPE_XXX */
int irq;
@@ -179,7 +178,7 @@ struct snd_vx_core {
unsigned int pcm_running;
struct device *dev;
- snd_hwdep_t *hwdep;
+ struct snd_hwdep *hwdep;
struct vx_rmh irq_rmh; /* RMH used in interrupts */
@@ -216,14 +215,14 @@ struct snd_vx_core {
/*
* constructor
*/
-vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
- struct snd_vx_ops *ops, int extra_size);
-int snd_vx_setup_firmware(vx_core_t *chip);
-int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *dsp);
-int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *dsp);
-int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp);
+struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
+ struct snd_vx_ops *ops, int extra_size);
+int snd_vx_setup_firmware(struct vx_core *chip);
+int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *dsp);
+int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *dsp);
+int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp);
-void snd_vx_free_firmware(vx_core_t *chip);
+void snd_vx_free_firmware(struct vx_core *chip);
/*
* interrupt handler; exported for pcmcia
@@ -233,37 +232,37 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs);
/*
* lowlevel functions
*/
-static inline int vx_test_and_ack(vx_core_t *chip)
+static inline int vx_test_and_ack(struct vx_core *chip)
{
snd_assert(chip->ops->test_and_ack, return -ENXIO);
return chip->ops->test_and_ack(chip);
}
-static inline void vx_validate_irq(vx_core_t *chip, int enable)
+static inline void vx_validate_irq(struct vx_core *chip, int enable)
{
snd_assert(chip->ops->validate_irq, return);
chip->ops->validate_irq(chip, enable);
}
-static inline unsigned char snd_vx_inb(vx_core_t *chip, int reg)
+static inline unsigned char snd_vx_inb(struct vx_core *chip, int reg)
{
snd_assert(chip->ops->in8, return 0);
return chip->ops->in8(chip, reg);
}
-static inline unsigned int snd_vx_inl(vx_core_t *chip, int reg)
+static inline unsigned int snd_vx_inl(struct vx_core *chip, int reg)
{
snd_assert(chip->ops->in32, return 0);
return chip->ops->in32(chip, reg);
}
-static inline void snd_vx_outb(vx_core_t *chip, int reg, unsigned char val)
+static inline void snd_vx_outb(struct vx_core *chip, int reg, unsigned char val)
{
snd_assert(chip->ops->out8, return);
chip->ops->out8(chip, reg, val);
}
-static inline void snd_vx_outl(vx_core_t *chip, int reg, unsigned int val)
+static inline void snd_vx_outl(struct vx_core *chip, int reg, unsigned int val)
{
snd_assert(chip->ops->out32, return);
chip->ops->out32(chip, reg, val);
@@ -274,27 +273,25 @@ static inline void snd_vx_outl(vx_core_t *chip, int reg, unsigned int val)
#define vx_inl(chip,reg) snd_vx_inl(chip, VX_##reg)
#define vx_outl(chip,reg,val) snd_vx_outl(chip, VX_##reg,val)
-void snd_vx_delay(vx_core_t *chip, int msec);
-
-static inline void vx_reset_dsp(vx_core_t *chip)
+static inline void vx_reset_dsp(struct vx_core *chip)
{
snd_assert(chip->ops->reset_dsp, return);
chip->ops->reset_dsp(chip);
}
-int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh);
-int vx_send_msg_nolock(vx_core_t *chip, struct vx_rmh *rmh);
-int vx_send_rih(vx_core_t *chip, int cmd);
-int vx_send_rih_nolock(vx_core_t *chip, int cmd);
+int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh);
+int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh);
+int vx_send_rih(struct vx_core *chip, int cmd);
+int vx_send_rih_nolock(struct vx_core *chip, int cmd);
-void vx_reset_codec(vx_core_t *chip, int cold_reset);
+void vx_reset_codec(struct vx_core *chip, int cold_reset);
/*
* check the bit on the specified register
* returns zero if a bit matches, or a negative error code.
* exported for vxpocket driver
*/
-int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time);
+int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time);
#define vx_check_isr(chip,mask,bit,time) snd_vx_check_reg_bit(chip, VX_ISR, mask, bit, time)
#define vx_wait_isr_bit(chip,bit) vx_check_isr(chip, bit, bit, 200)
#define vx_wait_for_rx_full(chip) vx_wait_isr_bit(chip, ISR_RX_FULL)
@@ -303,15 +300,15 @@ int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time);
/*
* pseudo-DMA transfer
*/
-static inline void vx_pseudo_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static inline void vx_pseudo_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
snd_assert(chip->ops->dma_write, return);
chip->ops->dma_write(chip, runtime, pipe, count);
}
-static inline void vx_pseudo_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static inline void vx_pseudo_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
snd_assert(chip->ops->dma_read, return);
chip->ops->dma_read(chip, runtime, pipe, count);
@@ -329,27 +326,33 @@ static inline void vx_pseudo_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtim
/*
* pcm stuff
*/
-int snd_vx_pcm_new(vx_core_t *chip);
-void vx_pcm_update_intr(vx_core_t *chip, unsigned int events);
+int snd_vx_pcm_new(struct vx_core *chip);
+void vx_pcm_update_intr(struct vx_core *chip, unsigned int events);
/*
* mixer stuff
*/
-int snd_vx_mixer_new(vx_core_t *chip);
-void vx_toggle_dac_mute(vx_core_t *chip, int mute);
-int vx_sync_audio_source(vx_core_t *chip);
-int vx_set_monitor_level(vx_core_t *chip, int audio, int level, int active);
+int snd_vx_mixer_new(struct vx_core *chip);
+void vx_toggle_dac_mute(struct vx_core *chip, int mute);
+int vx_sync_audio_source(struct vx_core *chip);
+int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active);
/*
* IEC958 & clock stuff
*/
-void vx_set_iec958_status(vx_core_t *chip, unsigned int bits);
-int vx_set_clock(vx_core_t *chip, unsigned int freq);
-void vx_set_internal_clock(vx_core_t *chip, unsigned int freq);
-int vx_change_frequency(vx_core_t *chip);
+void vx_set_iec958_status(struct vx_core *chip, unsigned int bits);
+int vx_set_clock(struct vx_core *chip, unsigned int freq);
+void vx_set_internal_clock(struct vx_core *chip, unsigned int freq);
+int vx_change_frequency(struct vx_core *chip);
/*
+ * PM
+ */
+int snd_vx_suspend(struct vx_core *card, pm_message_t state);
+int snd_vx_resume(struct vx_core *card);
+
+/*
* hardware constants
*/
diff --git a/include/sound/wavefront.h b/include/sound/wavefront.h
index 9e572aed2435..15d82e594b56 100644
--- a/include/sound/wavefront.h
+++ b/include/sound/wavefront.h
@@ -454,22 +454,22 @@ typedef struct wf_multisample {
} wavefront_multisample;
typedef struct wf_alias {
- s16 OriginalSample __attribute__ ((packed));
-
- struct wf_sample_offset sampleStartOffset __attribute__ ((packed));
- struct wf_sample_offset loopStartOffset __attribute__ ((packed));
- struct wf_sample_offset sampleEndOffset __attribute__ ((packed));
- struct wf_sample_offset loopEndOffset __attribute__ ((packed));
-
- s16 FrequencyBias __attribute__ ((packed));
-
- u8 SampleResolution:2 __attribute__ ((packed));
- u8 Unused1:1 __attribute__ ((packed));
- u8 Loop:1 __attribute__ ((packed));
- u8 Bidirectional:1 __attribute__ ((packed));
- u8 Unused2:1 __attribute__ ((packed));
- u8 Reverse:1 __attribute__ ((packed));
- u8 Unused3:1 __attribute__ ((packed));
+ s16 OriginalSample;
+
+ struct wf_sample_offset sampleStartOffset;
+ struct wf_sample_offset loopStartOffset;
+ struct wf_sample_offset sampleEndOffset;
+ struct wf_sample_offset loopEndOffset;
+
+ s16 FrequencyBias;
+
+ u8 SampleResolution:2;
+ u8 Unused1:1;
+ u8 Loop:1;
+ u8 Bidirectional:1;
+ u8 Unused2:1;
+ u8 Reverse:1;
+ u8 Unused3:1;
/* This structure is meant to be padded only to 16 bits on their
original. Of course, whoever wrote their documentation didn't
@@ -480,8 +480,8 @@ typedef struct wf_alias {
standard 16->32 bit issues.
*/
- u8 sixteen_bit_padding __attribute__ ((packed));
-} wavefront_alias;
+ u8 sixteen_bit_padding;
+} __attribute__((packed)) wavefront_alias;
typedef struct wf_drum {
u8 PatchNumber;
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index c3bccbfd8d4c..d567bfdbf513 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -184,7 +184,7 @@
*
*/
-typedef struct _snd_ymfpci_playback_bank {
+struct snd_ymfpci_playback_bank {
u32 format;
u32 loop_default;
u32 base; /* 32-bit address */
@@ -215,46 +215,45 @@ typedef struct _snd_ymfpci_playback_bank {
u32 eff3_gain;
u32 lpfD1;
u32 lpfD2;
-} snd_ymfpci_playback_bank_t;
+ };
-typedef struct _snd_ymfpci_capture_bank {
+struct snd_ymfpci_capture_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 num_of_loops; /* counter */
-} snd_ymfpci_capture_bank_t;
+};
-typedef struct _snd_ymfpci_effect_bank {
+struct snd_ymfpci_effect_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 temp;
-} snd_ymfpci_effect_bank_t;
+};
-typedef struct _snd_ymfpci_voice ymfpci_voice_t;
-typedef struct _snd_ymfpci_pcm ymfpci_pcm_t;
-typedef struct _snd_ymfpci ymfpci_t;
+struct snd_ymfpci_pcm;
+struct snd_ymfpci;
-typedef enum {
+enum snd_ymfpci_voice_type {
YMFPCI_PCM,
YMFPCI_SYNTH,
YMFPCI_MIDI
-} ymfpci_voice_type_t;
+};
-struct _snd_ymfpci_voice {
- ymfpci_t *chip;
+struct snd_ymfpci_voice {
+ struct snd_ymfpci *chip;
int number;
unsigned int use: 1,
pcm: 1,
synth: 1,
midi: 1;
- snd_ymfpci_playback_bank_t *bank;
+ struct snd_ymfpci_playback_bank *bank;
dma_addr_t bank_addr;
- void (*interrupt)(ymfpci_t *chip, ymfpci_voice_t *voice);
- ymfpci_pcm_t *ypcm;
+ void (*interrupt)(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice);
+ struct snd_ymfpci_pcm *ypcm;
};
-typedef enum {
+enum snd_ymfpci_pcm_type {
PLAYBACK_VOICE,
CAPTURE_REC,
CAPTURE_AC97,
@@ -263,13 +262,13 @@ typedef enum {
EFFECT_EFF1,
EFFECT_EFF2,
EFFECT_EFF3
-} snd_ymfpci_pcm_type_t;
+};
-struct _snd_ymfpci_pcm {
- ymfpci_t *chip;
- snd_ymfpci_pcm_type_t type;
- snd_pcm_substream_t *substream;
- ymfpci_voice_t *voices[2]; /* playback only */
+struct snd_ymfpci_pcm {
+ struct snd_ymfpci *chip;
+ enum snd_ymfpci_pcm_type type;
+ struct snd_pcm_substream *substream;
+ struct snd_ymfpci_voice *voices[2]; /* playback only */
unsigned int running: 1;
unsigned int output_front: 1;
unsigned int output_rear: 1;
@@ -282,7 +281,7 @@ struct _snd_ymfpci_pcm {
u32 shift;
};
-struct _snd_ymfpci {
+struct snd_ymfpci {
int irq;
unsigned int device_id; /* PCI device ID */
@@ -316,47 +315,47 @@ struct _snd_ymfpci {
struct snd_dma_buffer ac3_tmp_base;
u32 *ctrl_playback;
- snd_ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
- snd_ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2];
- snd_ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
+ struct snd_ymfpci_playback_bank *bank_playback[YDSXG_PLAYBACK_VOICES][2];
+ struct snd_ymfpci_capture_bank *bank_capture[YDSXG_CAPTURE_VOICES][2];
+ struct snd_ymfpci_effect_bank *bank_effect[YDSXG_EFFECT_VOICES][2];
int start_count;
u32 active_bank;
- ymfpci_voice_t voices[64];
+ struct snd_ymfpci_voice voices[64];
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
- snd_rawmidi_t *rawmidi;
- snd_timer_t *timer;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
+ struct snd_rawmidi *rawmidi;
+ struct snd_timer *timer;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_t *pcm2;
- snd_pcm_t *pcm_spdif;
- snd_pcm_t *pcm_4ch;
- snd_pcm_substream_t *capture_substream[YDSXG_CAPTURE_VOICES];
- snd_pcm_substream_t *effect_substream[YDSXG_EFFECT_VOICES];
- snd_kcontrol_t *ctl_vol_recsrc;
- snd_kcontrol_t *ctl_vol_adcrec;
- snd_kcontrol_t *ctl_vol_spdifrec;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm2;
+ struct snd_pcm *pcm_spdif;
+ struct snd_pcm *pcm_4ch;
+ struct snd_pcm_substream *capture_substream[YDSXG_CAPTURE_VOICES];
+ struct snd_pcm_substream *effect_substream[YDSXG_EFFECT_VOICES];
+ struct snd_kcontrol *ctl_vol_recsrc;
+ struct snd_kcontrol *ctl_vol_adcrec;
+ struct snd_kcontrol *ctl_vol_spdifrec;
unsigned short spdif_bits, spdif_pcm_bits;
- snd_kcontrol_t *spdif_pcm_ctl;
+ struct snd_kcontrol *spdif_pcm_ctl;
int mode_dup4ch;
int rear_opened;
int spdif_opened;
struct {
u16 left;
u16 right;
- snd_kcontrol_t *ctl;
+ struct snd_kcontrol *ctl;
} pcm_mixer[32];
spinlock_t reg_lock;
spinlock_t voice_lock;
wait_queue_head_t interrupt_sleep;
atomic_t interrupt_sleep_count;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
#ifdef CONFIG_PM
u32 *saved_regs;
@@ -364,17 +363,20 @@ struct _snd_ymfpci {
#endif
};
-int snd_ymfpci_create(snd_card_t * card,
+int snd_ymfpci_create(struct snd_card *card,
struct pci_dev *pci,
unsigned short old_legacy_ctrl,
- ymfpci_t ** rcodec);
-void snd_ymfpci_free_gameport(ymfpci_t *chip);
-
-int snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
-int snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
-int snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
-int snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
-int snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch);
-int snd_ymfpci_timer(ymfpci_t *chip, int device);
+ struct snd_ymfpci ** rcodec);
+void snd_ymfpci_free_gameport(struct snd_ymfpci *chip);
+
+int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state);
+int snd_ymfpci_resume(struct pci_dev *pci);
+
+int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
+int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
+int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
+int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
+int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch);
+int snd_ymfpci_timer(struct snd_ymfpci *chip, int device);
#endif /* __SOUND_YMFPCI_H */
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
index a9948232b131..717440575380 100644
--- a/include/video/cyblafb.h
+++ b/include/video/cyblafb.h
@@ -153,6 +153,10 @@
#define GE04 (GEBase+0x04) // source 2, p 111
#define GE08 (GEBase+0x08) // destination 1, p 111
#define GE0C (GEBase+0x0C) // destination 2, p 112
+#define GE10 (GEBase+0x10) // right view base & enable, p 112
+#define GE13 (GEBase+0x13) // left view base & enable, p 112
+#define GE18 (GEBase+0x18) // block write start address, p 112
+#define GE1C (GEBase+0x1C) // block write end address, p 112
#define GE20 (GEBase+0x20) // engine status, p 113
#define GE24 (GEBase+0x24) // reset all GE pointers
#define GE44 (GEBase+0x44) // command register, p 126
diff --git a/include/video/kyro.h b/include/video/kyro.h
index 1bed37cfa68c..dba7de2ee4a8 100644
--- a/include/video/kyro.h
+++ b/include/video/kyro.h
@@ -15,6 +15,7 @@
struct kyrofb_info {
void __iomem *regbase;
+ u32 palette[16];
u32 HTot; /* Hor Total Time */
u32 HFP; /* Hor Front Porch */
u32 HST; /* Hor Sync Time */
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index bdaee70868dd..1d69049bd4c1 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -196,6 +196,7 @@ struct neofb_par {
int internal_display;
int external_display;
int libretto;
+ u32 palette[16];
};
typedef struct {
diff --git a/include/video/newport.h b/include/video/newport.h
index 812dac5b55f4..1f5ebeaa818f 100644
--- a/include/video/newport.h
+++ b/include/video/newport.h
@@ -382,7 +382,8 @@ typedef struct {
#define VC2_IREG_CONTROL 0x10
#define VC2_IREG_CONFIG 0x20
-extern __inline__ void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg,
+static inline void newport_vc2_set(struct newport_regs *regs,
+ unsigned char vc2ireg,
unsigned short val)
{
regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 |
@@ -390,7 +391,7 @@ extern __inline__ void newport_vc2_set(struct newport_regs *regs, unsigned char
regs->set.dcbdata0.byword = (vc2ireg << 24) | (val << 8);
}
-extern __inline__ unsigned short newport_vc2_get(struct newport_regs *regs,
+static inline unsigned short newport_vc2_get(struct newport_regs *regs,
unsigned char vc2ireg)
{
regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 |
diff --git a/include/video/sstfb.h b/include/video/sstfb.h
index 0d77b5205372..3570f9c9b111 100644
--- a/include/video/sstfb.h
+++ b/include/video/sstfb.h
@@ -334,6 +334,7 @@ struct sst_spec {
};
struct sstfb_par {
+ u32 palette[16];
unsigned int yDim;
unsigned int hSyncOn; /* hsync_len */
unsigned int hSyncOff; /* left_margin + xres + right_margin */
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index 04237676b17c..c1cc94ba3fdd 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -140,52 +140,52 @@
#ifdef __KERNEL__
struct banshee_reg {
- /* VGA rubbish */
- unsigned char att[21];
- unsigned char crt[25];
- unsigned char gra[ 9];
- unsigned char misc[1];
- unsigned char seq[ 5];
-
- /* Banshee extensions */
- unsigned char ext[2];
- unsigned long vidcfg;
- unsigned long vidpll;
- unsigned long mempll;
- unsigned long gfxpll;
- unsigned long dacmode;
- unsigned long vgainit0;
- unsigned long vgainit1;
- unsigned long screensize;
- unsigned long stride;
- unsigned long cursloc;
- unsigned long curspataddr;
- unsigned long cursc0;
- unsigned long cursc1;
- unsigned long startaddr;
- unsigned long clip0min;
- unsigned long clip0max;
- unsigned long clip1min;
- unsigned long clip1max;
- unsigned long srcbase;
- unsigned long dstbase;
- unsigned long miscinit0;
+ /* VGA rubbish */
+ unsigned char att[21];
+ unsigned char crt[25];
+ unsigned char gra[ 9];
+ unsigned char misc[1];
+ unsigned char seq[ 5];
+
+ /* Banshee extensions */
+ unsigned char ext[2];
+ unsigned long vidcfg;
+ unsigned long vidpll;
+ unsigned long mempll;
+ unsigned long gfxpll;
+ unsigned long dacmode;
+ unsigned long vgainit0;
+ unsigned long vgainit1;
+ unsigned long screensize;
+ unsigned long stride;
+ unsigned long cursloc;
+ unsigned long curspataddr;
+ unsigned long cursc0;
+ unsigned long cursc1;
+ unsigned long startaddr;
+ unsigned long clip0min;
+ unsigned long clip0max;
+ unsigned long clip1min;
+ unsigned long clip1max;
+ unsigned long srcbase;
+ unsigned long dstbase;
+ unsigned long miscinit0;
};
struct tdfx_par {
- u32 max_pixclock;
-
- void __iomem *regbase_virt;
- unsigned long iobase;
- u32 baseline;
-
- struct {
- int w,u,d;
- unsigned long enable,disable;
- struct timer_list timer;
- } hwcursor;
-
- spinlock_t DAClock;
+ u32 max_pixclock;
+ u32 palette[16];
+ void __iomem *regbase_virt;
+ unsigned long iobase;
+ u32 baseline;
+
+ struct {
+ int w,u,d;
+ unsigned long enable,disable;
+ struct timer_list timer;
+ } hwcursor;
+
+ spinlock_t DAClock;
};
#endif /* __KERNEL__ */
diff --git a/init/Kconfig b/init/Kconfig
index 9fc0759fa942..b9923b1434a2 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -99,13 +99,12 @@ config SWAP
default y
help
This option allows you to choose whether you want to have support
- for socalled swap devices or swap files in your kernel that are
+ for so called swap devices or swap files in your kernel that are
used to provide more virtual memory than the actual RAM present
in your computer. If unsure say Y.
config SYSVIPC
bool "System V IPC"
- depends on MMU
---help---
Inter Process Communication is a suite of library functions and
system calls which let processes (running programs) synchronize and
@@ -190,40 +189,13 @@ config AUDIT
config AUDITSYSCALL
bool "Enable system-call auditing support"
- depends on AUDIT && (X86 || PPC || PPC64 || ARCH_S390 || IA64 || UML || SPARC64)
+ depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64)
default y if SECURITY_SELINUX
help
Enable low-overhead system-call auditing infrastructure that
can be used independently or with another kernel subsystem,
such as SELinux.
-config HOTPLUG
- bool "Support for hot-pluggable devices" if !ARCH_S390
- default ARCH_S390
- help
- This option is provided for the case where no in-kernel-tree
- modules require HOTPLUG functionality, but a module built
- outside the kernel tree does. Such modules require Y here.
-
-config KOBJECT_UEVENT
- bool "Kernel Userspace Events" if EMBEDDED
- depends on NET
- default y
- help
- This option enables the kernel userspace event layer, which is a
- simple mechanism for kernel-to-user communication over a netlink
- socket.
- The goal of the kernel userspace events layer is to provide a simple
- and efficient events system, that notifies userspace about kobject
- state changes. This will enable applications to just listen for
- events instead of polling system devices and files.
- Hotplug events (kobject addition and removal) are also available on
- the netlink socket in addition to the execution of /sbin/hotplug if
- CONFIG_HOTPLUG is enabled.
-
- Say Y, unless you are building a system requiring minimal memory
- consumption.
-
config IKCONFIG
bool "Kernel .config support"
---help---
@@ -256,6 +228,23 @@ config CPUSETS
source "usr/Kconfig"
+config UID16
+ bool "Enable 16-bit UID system calls" if EMBEDDED
+ depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION)
+ default y
+ help
+ This enables the legacy 16-bit UID syscall wrappers.
+
+config VM86
+ depends X86
+ default y
+ bool "Enable VM86 support" if EMBEDDED
+ help
+ This option is required by programs like DOSEMU to run 16-bit legacy
+ code on X86 processors. It also may be needed by software like
+ XFree86 to initialize some video cards via BIOS. Disabling this
+ option saves about 6k.
+
config CC_OPTIMIZE_FOR_SIZE
bool "Optimize for size (Look out for broken compilers!)"
default y
@@ -308,6 +297,15 @@ config KALLSYMS_EXTRA_PASS
you wait for kallsyms to be fixed.
+config HOTPLUG
+ bool "Support for hot-pluggable devices" if EMBEDDED
+ default y
+ help
+ This option is provided for the case where no hotplug or uevent
+ capabilities is wanted by the kernel. You should only consider
+ disabling this option for embedded systems that do not use modules, a
+ dynamic /dev tree, or dynamic device discovery. Just say Y.
+
config PRINTK
default y
bool "Enable support for printk" if EMBEDDED
@@ -328,6 +326,12 @@ config BUG
option for embedded systems with no facilities for reporting errors.
Just say Y.
+config ELF_CORE
+ default y
+ bool "Enable ELF core dumps" if EMBEDDED
+ help
+ Enable support for generating core dumps. Disabling saves about 4k.
+
config BASE_FULL
default y
bool "Enable full-sized data structures for core" if EMBEDDED
@@ -399,6 +403,15 @@ config CC_ALIGN_JUMPS
no dummy operations need be executed.
Zero means use compiler's default.
+config SLAB
+ default y
+ bool "Use full SLAB allocator" if EMBEDDED
+ help
+ Disabling this replaces the advanced SLAB allocator and
+ kmalloc support with the drastically simpler SLOB allocator.
+ SLOB is more space efficient but does not scale well and is
+ more susceptible to fragmentation.
+
endmenu # General setup
config TINY_SHMEM
@@ -410,6 +423,13 @@ config BASE_SMALL
default 0 if BASE_FULL
default 1 if !BASE_FULL
+config SLOB
+ default !SLAB
+ bool
+
+config OBSOLETE_INTERMODULE
+ tristate
+
menu "Loadable module support"
config MODULES
@@ -461,8 +481,8 @@ config OBSOLETE_MODPARM
If unsure, say Y.
config MODVERSIONS
- bool "Module versioning support (EXPERIMENTAL)"
- depends on MODULES && EXPERIMENTAL
+ bool "Module versioning support"
+ depends on MODULES
help
Usually, you have to use modules compiled with your kernel.
Saying Y here makes it sometimes possible to use modules
diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
index 3fbc3555ce96..f6f36806f84a 100644
--- a/init/do_mounts_md.c
+++ b/init/do_mounts_md.c
@@ -17,7 +17,7 @@ static int __initdata raid_noautodetect, raid_autopart;
static struct {
int minor;
int partitioned;
- int pers;
+ int level;
int chunk;
char *device_names;
} md_setup_args[MAX_MD_DEVS] __initdata;
@@ -47,7 +47,7 @@ extern int mdp_major;
*/
static int __init md_setup(char *str)
{
- int minor, level, factor, fault, pers, partitioned = 0;
+ int minor, level, factor, fault, partitioned = 0;
char *pername = "";
char *str1;
int ent;
@@ -78,7 +78,7 @@ static int __init md_setup(char *str)
}
if (ent >= md_setup_ents)
md_setup_ents++;
- switch (get_option(&str, &level)) { /* RAID Personality */
+ switch (get_option(&str, &level)) { /* RAID level */
case 2: /* could be 0 or -1.. */
if (level == 0 || level == LEVEL_LINEAR) {
if (get_option(&str, &factor) != 2 || /* Chunk Size */
@@ -86,16 +86,12 @@ static int __init md_setup(char *str)
printk(KERN_WARNING "md: Too few arguments supplied to md=.\n");
return 0;
}
- md_setup_args[ent].pers = level;
+ md_setup_args[ent].level = level;
md_setup_args[ent].chunk = 1 << (factor+12);
- if (level == LEVEL_LINEAR) {
- pers = LINEAR;
+ if (level == LEVEL_LINEAR)
pername = "linear";
- } else {
- pers = RAID0;
+ else
pername = "raid0";
- }
- md_setup_args[ent].pers = pers;
break;
}
/* FALL THROUGH */
@@ -103,7 +99,7 @@ static int __init md_setup(char *str)
str = str1;
/* FALL THROUGH */
case 0:
- md_setup_args[ent].pers = 0;
+ md_setup_args[ent].level = LEVEL_NONE;
pername="super-block";
}
@@ -190,10 +186,10 @@ static void __init md_setup_drive(void)
continue;
}
- if (md_setup_args[ent].pers) {
+ if (md_setup_args[ent].level != LEVEL_NONE) {
/* non-persistent */
mdu_array_info_t ainfo;
- ainfo.level = pers_to_level(md_setup_args[ent].pers);
+ ainfo.level = md_setup_args[ent].level;
ainfo.size = 0;
ainfo.nr_disks =0;
ainfo.raid_disks =0;
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index c10b08a80982..c2683fcd792d 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -145,7 +145,7 @@ int __init rd_load_image(char *from)
int nblocks, i, disk;
char *buf = NULL;
unsigned short rotate = 0;
-#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
+#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
char rotator[4] = { '|' , '/' , '-' , '\\' };
#endif
@@ -237,7 +237,7 @@ int __init rd_load_image(char *from)
}
sys_read(in_fd, buf, BLOCK_SIZE);
sys_write(out_fd, buf, BLOCK_SIZE);
-#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
+#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES)
if (!(i % 16)) {
printk("%c\b", rotator[rotate & 0x3]);
rotate++;
diff --git a/init/main.c b/init/main.c
index 27f97f9b4636..7c79da57d3a2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -47,34 +47,27 @@
#include <linux/rmap.h>
#include <linux/mempolicy.h>
#include <linux/key.h>
-#include <net/sock.h>
#include <asm/io.h>
#include <asm/bugs.h>
#include <asm/setup.h>
#include <asm/sections.h>
-
-/*
- * This is one of the first .c files built. Error out early
- * if we have compiler trouble..
- */
-#if __GNUC__ == 2 && __GNUC_MINOR__ == 96
-#ifdef CONFIG_FRAME_POINTER
-#error This compiler cannot compile correctly with frame pointers enabled
-#endif
-#endif
+#include <asm/cacheflush.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/smp.h>
#endif
/*
- * Versions of gcc older than that listed below may actually compile
- * and link okay, but the end product can have subtle run time bugs.
- * To avoid associated bogus bug reports, we flatly refuse to compile
- * with a gcc that is known to be too old from the very beginning.
+ * This is one of the first .c files built. Error out early if we have compiler
+ * trouble.
+ *
+ * Versions of gcc older than that listed below may actually compile and link
+ * okay, but the end product can have subtle run time bugs. To avoid associated
+ * bogus bug reports, we flatly refuse to compile with a gcc that is known to be
+ * too old from the very beginning.
*/
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95)
+#if (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 2)
#error Sorry, your GCC is too old. It builds incorrect kernels.
#endif
@@ -100,6 +93,9 @@ extern void acpi_early_init(void);
#else
static inline void acpi_early_init(void) { }
#endif
+#ifndef CONFIG_DEBUG_RODATA
+static inline void mark_rodata_ro(void) { }
+#endif
#ifdef CONFIG_TC
extern void tc_init(void);
@@ -487,6 +483,7 @@ asmlinkage void __init start_kernel(void)
init_IRQ();
pidhash_init();
init_timers();
+ hrtimers_init();
softirq_init();
time_init();
@@ -509,6 +506,7 @@ asmlinkage void __init start_kernel(void)
}
#endif
vfs_caches_init_early();
+ cpuset_init_early();
mem_init();
kmem_cache_init();
setup_per_cpu_pageset();
@@ -614,9 +612,6 @@ static void __init do_basic_setup(void)
sysctl_init();
#endif
- /* Networking initialization needs a process context */
- sock_init();
-
do_initcalls();
}
@@ -712,6 +707,7 @@ static int init(void * unused)
*/
free_initmem();
unlock_kernel();
+ mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c8943b53d8e6..59302fc3643b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -11,6 +11,7 @@
* This file is released under the GPL.
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/file.h>
@@ -598,15 +599,16 @@ static int mq_attr_ok(struct mq_attr *attr)
static struct file *do_create(struct dentry *dir, struct dentry *dentry,
int oflag, mode_t mode, struct mq_attr __user *u_attr)
{
- struct file *filp;
struct mq_attr attr;
int ret;
- if (u_attr != NULL) {
+ if (u_attr) {
+ ret = -EFAULT;
if (copy_from_user(&attr, u_attr, sizeof(attr)))
- return ERR_PTR(-EFAULT);
+ goto out;
+ ret = -EINVAL;
if (!mq_attr_ok(&attr))
- return ERR_PTR(-EINVAL);
+ goto out;
/* store for use during create */
dentry->d_fsdata = &attr;
}
@@ -615,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
ret = vfs_create(dir->d_inode, dentry, mode, NULL);
dentry->d_fsdata = NULL;
if (ret)
- return ERR_PTR(ret);
+ goto out;
- filp = dentry_open(dentry, mqueue_mnt, oflag);
- if (!IS_ERR(filp))
- dget(dentry);
+ return dentry_open(dentry, mqueue_mnt, oflag);
- return filp;
+out:
+ dput(dentry);
+ mntput(mqueue_mnt);
+ return ERR_PTR(ret);
}
/* Opens existing queue */
@@ -629,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag)
{
static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
MAY_READ | MAY_WRITE };
- struct file *filp;
- if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
+ if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
+ dput(dentry);
+ mntput(mqueue_mnt);
return ERR_PTR(-EINVAL);
+ }
- if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL))
+ if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
+ dput(dentry);
+ mntput(mqueue_mnt);
return ERR_PTR(-EACCES);
+ }
- filp = dentry_open(dentry, mqueue_mnt, oflag);
-
- if (!IS_ERR(filp))
- dget(dentry);
-
- return filp;
+ return dentry_open(dentry, mqueue_mnt, oflag);
}
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
@@ -660,7 +663,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (fd < 0)
goto out_putname;
- down(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
@@ -670,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */
- filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) :
- do_open(dentry, oflag);
+ error = -EEXIST;
+ if (oflag & O_EXCL)
+ goto out;
+ filp = do_open(dentry, oflag);
} else {
filp = do_create(mqueue_mnt->mnt_root, dentry,
oflag, mode, u_attr);
}
- } else
- filp = (dentry->d_inode) ? do_open(dentry, oflag) :
- ERR_PTR(-ENOENT);
-
- dput(dentry);
+ } else {
+ error = -ENOENT;
+ if (!dentry->d_inode)
+ goto out;
+ filp = do_open(dentry, oflag);
+ }
if (IS_ERR(filp)) {
error = PTR_ERR(filp);
@@ -691,13 +697,15 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
fd_install(fd, filp);
goto out_upsem;
-out_putfd:
+out:
+ dput(dentry);
mntput(mqueue_mnt);
+out_putfd:
put_unused_fd(fd);
out_err:
fd = error;
out_upsem:
- up(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
out_putname:
putname(name);
return fd;
@@ -714,7 +722,7 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
if (IS_ERR(name))
return PTR_ERR(name);
- down(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
@@ -735,7 +743,7 @@ out_err:
dput(dentry);
out_unlock:
- up(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
putname(name);
if (inode)
iput(inode);
diff --git a/ipc/msg.c b/ipc/msg.c
index d035bd2aba96..fbf757064a32 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -12,9 +12,10 @@
*
* mostly rewritten, threaded and wake-one semantics added
* MSGMAX limit removed, sysctl's added
- * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/msg.h>
diff --git a/ipc/sem.c b/ipc/sem.c
index cb5bb2a5df96..31fd4027d2b5 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -56,7 +56,7 @@
* /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
*
* SMP-threaded, sysctl's added
- * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
* Enforced range limit on SEM_UNDO
* (c) 2001 Red Hat Inc <alan@redhat.com>
* Lockless wakeup
@@ -73,6 +73,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include "util.h"
diff --git a/ipc/shm.c b/ipc/shm.c
index 587d836d80d9..4c28d2d8e305 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -27,6 +27,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
@@ -34,8 +35,6 @@
#include "util.h"
-#define shm_flags shm_perm.mode
-
static struct file_operations shm_file_operations;
static struct vm_operations_struct shm_vm_ops;
@@ -148,7 +147,7 @@ static void shm_close (struct vm_area_struct *shmd)
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
- shp->shm_flags & SHM_DEST)
+ shp->shm_perm.mode & SHM_DEST)
shm_destroy (shp);
else
shm_unlock(shp);
@@ -157,14 +156,22 @@ static void shm_close (struct vm_area_struct *shmd)
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
{
- file_accessed(file);
- vma->vm_ops = &shm_vm_ops;
- shm_inc(file->f_dentry->d_inode->i_ino);
- return 0;
+ int ret;
+
+ ret = shmem_mmap(file, vma);
+ if (ret == 0) {
+ vma->vm_ops = &shm_vm_ops;
+ shm_inc(file->f_dentry->d_inode->i_ino);
+ }
+
+ return ret;
}
static struct file_operations shm_file_operations = {
- .mmap = shm_mmap
+ .mmap = shm_mmap,
+#ifndef CONFIG_MMU
+ .get_unmapped_area = shmem_get_unmapped_area,
+#endif
};
static struct vm_operations_struct shm_vm_ops = {
@@ -197,7 +204,7 @@ static int newseg (key_t key, int shmflg, size_t size)
return -ENOMEM;
shp->shm_perm.key = key;
- shp->shm_flags = (shmflg & S_IRWXUGO);
+ shp->shm_perm.mode = (shmflg & S_IRWXUGO);
shp->mlock_user = NULL;
shp->shm_perm.security = NULL;
@@ -337,7 +344,7 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
out->uid = tbuf.shm_perm.uid;
out->gid = tbuf.shm_perm.gid;
- out->mode = tbuf.shm_flags;
+ out->mode = tbuf.shm_perm.mode;
return 0;
}
@@ -350,7 +357,7 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
out->uid = tbuf_old.shm_perm.uid;
out->gid = tbuf_old.shm_perm.gid;
- out->mode = tbuf_old.shm_flags;
+ out->mode = tbuf_old.shm_perm.mode;
return 0;
}
@@ -552,13 +559,13 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if (!is_file_hugepages(shp->shm_file)) {
err = shmem_lock(shp->shm_file, 1, user);
if (!err) {
- shp->shm_flags |= SHM_LOCKED;
+ shp->shm_perm.mode |= SHM_LOCKED;
shp->mlock_user = user;
}
}
} else if (!is_file_hugepages(shp->shm_file)) {
shmem_lock(shp->shm_file, 0, shp->mlock_user);
- shp->shm_flags &= ~SHM_LOCKED;
+ shp->shm_perm.mode &= ~SHM_LOCKED;
shp->mlock_user = NULL;
}
shm_unlock(shp);
@@ -597,7 +604,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
goto out_unlock_up;
if (shp->shm_nattch){
- shp->shm_flags |= SHM_DEST;
+ shp->shm_perm.mode |= SHM_DEST;
/* Do not find it any more */
shp->shm_perm.key = IPC_PRIVATE;
shm_unlock(shp);
@@ -636,7 +643,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
shp->shm_perm.uid = setbuf.uid;
shp->shm_perm.gid = setbuf.gid;
- shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)
+ shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
| (setbuf.mode & S_IRWXUGO);
shp->shm_ctim = get_seconds();
break;
@@ -769,7 +776,7 @@ invalid:
BUG();
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
- shp->shm_flags & SHM_DEST)
+ shp->shm_perm.mode & SHM_DEST)
shm_destroy (shp);
else
shm_unlock(shp);
@@ -894,7 +901,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
return seq_printf(s, format,
shp->shm_perm.key,
shp->id,
- shp->shm_flags,
+ shp->shm_perm.mode,
shp->shm_segsz,
shp->shm_cprid,
shp->shm_lprid,
diff --git a/ipc/util.c b/ipc/util.c
index 23f1cec150c1..862621980b01 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -7,7 +7,7 @@
* Occurs in several places in the IPC code.
* Chris Evans, <chris@ferret.lmh.ox.ac.uk>
* Nov 1999 - ipc helper functions, unified SMP locking
- * Manfred Spraul <manfreds@colorfullife.com>
+ * Manfred Spraul <manfred@colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm@us.ibm.com>
*/
@@ -20,6 +20,7 @@
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/highuid.h>
#include <linux/security.h>
#include <linux/rcupdate.h>
diff --git a/ipc/util.h b/ipc/util.h
index fc9a28be0797..efaff3ee7de7 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -2,7 +2,7 @@
* linux/ipc/util.h
* Copyright (C) 1999 Christoph Rohland
*
- * ipc helper functions (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com>
*/
#ifndef _IPC_UTIL_H
diff --git a/kernel/.gitignore b/kernel/.gitignore
new file mode 100644
index 000000000000..f2ab70073bd4
--- /dev/null
+++ b/kernel/.gitignore
@@ -0,0 +1,5 @@
+#
+# Generated files
+#
+config_data.h
+config_data.gz
diff --git a/kernel/Makefile b/kernel/Makefile
index 4f5a1453093a..4ae0fbde815d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -6,15 +6,18 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
- rcupdate.o intermodule.o extable.o params.o posix-timers.o \
- kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
+ rcupdate.o extable.o params.o posix-timers.o \
+ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+ hrtimer.o
+obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.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_OBSOLETE_INTERMODULE) += intermodule.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
@@ -29,7 +32,6 @@ 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
obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
diff --git a/kernel/acct.c b/kernel/acct.c
index 6312d6bd43e3..065d8b4e51ef 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -47,6 +47,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/acct.h>
+#include <linux/capability.h>
#include <linux/file.h>
#include <linux/tty.h>
#include <linux/security.h>
@@ -427,6 +428,7 @@ static void do_acct_process(long exitcode, struct file *file)
u64 elapsed;
u64 run_time;
struct timespec uptime;
+ unsigned long jiffies;
/*
* First check to see if there is enough free_space to continue
@@ -467,12 +469,12 @@ static void do_acct_process(long exitcode, struct file *file)
#endif
do_div(elapsed, AHZ);
ac.ac_btime = xtime.tv_sec - elapsed;
- ac.ac_utime = encode_comp_t(jiffies_to_AHZ(
- current->signal->utime +
- current->group_leader->utime));
- ac.ac_stime = encode_comp_t(jiffies_to_AHZ(
- current->signal->stime +
- current->group_leader->stime));
+ jiffies = cputime_to_jiffies(cputime_add(current->group_leader->utime,
+ current->signal->utime));
+ ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies));
+ jiffies = cputime_to_jiffies(cputime_add(current->group_leader->stime,
+ current->signal->stime));
+ ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies));
/* we really need to bite the bullet and change layout */
ac.ac_uid = current->uid;
ac.ac_gid = current->gid;
@@ -580,7 +582,8 @@ void acct_process(long exitcode)
void acct_update_integrals(struct task_struct *tsk)
{
if (likely(tsk->mm)) {
- long delta = tsk->stime - tsk->acct_stimexpd;
+ long delta =
+ cputime_to_jiffies(tsk->stime) - tsk->acct_stimexpd;
if (delta == 0)
return;
diff --git a/kernel/audit.c b/kernel/audit.c
index 32fa03ad1984..0a813d2883e5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -42,8 +42,8 @@
*/
#include <linux/init.h>
-#include <asm/atomic.h>
#include <asm/types.h>
+#include <asm/atomic.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -267,7 +267,7 @@ static int audit_set_failure(int state, uid_t loginuid)
return old;
}
-int kauditd_thread(void *dummy)
+static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d8a68509e729..685c25175d96 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -30,8 +30,8 @@
*/
#include <linux/init.h>
-#include <asm/atomic.h>
#include <asm/types.h>
+#include <asm/atomic.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mount.h>
diff --git a/kernel/capability.c b/kernel/capability.c
index 8986a37a67ea..bfa3c92e16f2 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -7,6 +7,7 @@
* 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net>
*/
+#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/security.h>
diff --git a/kernel/compat.c b/kernel/compat.c
index 102296e21ea8..1867290c37e3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -514,6 +514,24 @@ static int put_compat_itimerspec(struct compat_itimerspec __user *dst,
return 0;
}
+long compat_sys_timer_create(clockid_t which_clock,
+ struct compat_sigevent __user *timer_event_spec,
+ timer_t __user *created_timer_id)
+{
+ struct sigevent __user *event = NULL;
+
+ if (timer_event_spec) {
+ struct sigevent kevent;
+
+ event = compat_alloc_user_space(sizeof(*event));
+ if (get_compat_sigevent(&kevent, timer_event_spec) ||
+ copy_to_user(event, &kevent, sizeof(*event)))
+ return -EFAULT;
+ }
+
+ return sys_timer_create(which_clock, event, created_timer_id);
+}
+
long compat_sys_timer_settime(timer_t timer_id, int flags,
struct compat_itimerspec __user *new,
struct compat_itimerspec __user *old)
@@ -649,8 +667,6 @@ int get_compat_sigevent(struct sigevent *event,
? -EFAULT : 0;
}
-/* timer_create is architecture specific because it needs sigevent conversion */
-
long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
unsigned long bitmap_size)
{
@@ -855,3 +871,31 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
}
#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
+
+#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
+{
+ sigset_t newset;
+ compat_sigset_t newset32;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
+ return -EFAULT;
+ sigset_from_compat(&newset, &newset32);
+ sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/configs.c b/kernel/configs.c
index 986f7af31e0a..009e1ebdcb88 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -3,7 +3,7 @@
* Echo the kernel .config file used to build the kernel
*
* Copyright (C) 2002 Khalid Aziz <khalid_aziz@hp.com>
- * Copyright (C) 2002 Randy Dunlap <rddunlap@osdl.org>
+ * Copyright (C) 2002 Randy Dunlap <rdunlap@xenotime.net>
* Copyright (C) 2002 Al Stone <ahs3@fc.hp.com>
* Copyright (C) 2002 Hewlett-Packard Company
*
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 7430640f9816..fe2f71f92ae0 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -39,6 +39,7 @@
#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/proc_fs.h>
+#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -54,7 +55,23 @@
#include <asm/atomic.h>
#include <asm/semaphore.h>
-#define CPUSET_SUPER_MAGIC 0x27e0eb
+#define CPUSET_SUPER_MAGIC 0x27e0eb
+
+/*
+ * Tracks how many cpusets are currently defined in system.
+ * When there is only one cpuset (the root cpuset) we can
+ * short circuit some hooks.
+ */
+int number_of_cpusets __read_mostly;
+
+/* See "Frequency meter" comments, below. */
+
+struct fmeter {
+ int cnt; /* unprocessed events count */
+ int val; /* most recent output value */
+ time_t time; /* clock (secs) when val computed */
+ spinlock_t lock; /* guards read or write of above */
+};
struct cpuset {
unsigned long flags; /* "unsigned long" so bitops work */
@@ -80,13 +97,16 @@ struct cpuset {
* Copy of global cpuset_mems_generation as of the most
* recent time this cpuset changed its mems_allowed.
*/
- int mems_generation;
+ int mems_generation;
+
+ struct fmeter fmeter; /* memory_pressure filter */
};
/* bits in struct cpuset flags field */
typedef enum {
CS_CPU_EXCLUSIVE,
CS_MEM_EXCLUSIVE,
+ CS_MEMORY_MIGRATE,
CS_REMOVED,
CS_NOTIFY_ON_RELEASE
} cpuset_flagbits_t;
@@ -112,6 +132,11 @@ static inline int notify_on_release(const struct cpuset *cs)
return !!test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
}
+static inline int is_memory_migrate(const struct cpuset *cs)
+{
+ return !!test_bit(CS_MEMORY_MIGRATE, &cs->flags);
+}
+
/*
* Increment this atomic integer everytime any cpuset changes its
* mems_allowed value. Users of cpusets can track this generation
@@ -137,13 +162,10 @@ static struct cpuset top_cpuset = {
.count = ATOMIC_INIT(0),
.sibling = LIST_HEAD_INIT(top_cpuset.sibling),
.children = LIST_HEAD_INIT(top_cpuset.children),
- .parent = NULL,
- .dentry = NULL,
- .mems_generation = 0,
};
static struct vfsmount *cpuset_mount;
-static struct super_block *cpuset_sb = NULL;
+static struct super_block *cpuset_sb;
/*
* We have two global cpuset semaphores below. They can nest.
@@ -227,6 +249,11 @@ static struct super_block *cpuset_sb = NULL;
* a tasks cpuset pointer we use task_lock(), which acts on a spinlock
* (task->alloc_lock) already in the task_struct routinely used for
* such matters.
+ *
+ * P.S. One more locking exception. RCU is used to guard the
+ * update of a tasks cpuset pointer by attach_task() and the
+ * access of task->cpuset->mems_generation via that pointer in
+ * the routine cpuset_update_task_memory_state().
*/
static DECLARE_MUTEX(manage_sem);
@@ -304,7 +331,7 @@ static void cpuset_d_remove_dir(struct dentry *dentry)
spin_lock(&dcache_lock);
node = dentry->d_subdirs.next;
while (node != &dentry->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_child);
+ struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
list_del_init(node);
if (d->d_inode) {
d = dget_locked(d);
@@ -316,7 +343,7 @@ static void cpuset_d_remove_dir(struct dentry *dentry)
}
node = dentry->d_subdirs.next;
}
- list_del_init(&dentry->d_child);
+ list_del_init(&dentry->d_u.d_child);
spin_unlock(&dcache_lock);
remove_dir(dentry);
}
@@ -570,20 +597,43 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
BUG_ON(!nodes_intersects(*pmask, node_online_map));
}
-/*
- * Refresh current tasks mems_allowed and mems_generation from current
- * tasks cpuset.
+/**
+ * cpuset_update_task_memory_state - update task memory placement
+ *
+ * If the current tasks cpusets mems_allowed changed behind our
+ * backs, update current->mems_allowed, mems_generation and task NUMA
+ * mempolicy to the new value.
*
- * Call without callback_sem or task_lock() held. May be called with
- * or without manage_sem held. Will acquire task_lock() and might
- * acquire callback_sem during call.
+ * Task mempolicy is updated by rebinding it relative to the
+ * current->cpuset if a task has its memory placement changed.
+ * Do not call this routine if in_interrupt().
*
- * The task_lock() is required to dereference current->cpuset safely.
- * Without it, we could pick up the pointer value of current->cpuset
- * in one instruction, and then attach_task could give us a different
- * cpuset, and then the cpuset we had could be removed and freed,
- * and then on our next instruction, we could dereference a no longer
- * valid cpuset pointer to get its mems_generation field.
+ * Call without callback_sem or task_lock() held. May be called
+ * with or without manage_sem held. Doesn't need task_lock to guard
+ * against another task changing a non-NULL cpuset pointer to NULL,
+ * as that is only done by a task on itself, and if the current task
+ * is here, it is not simultaneously in the exit code NULL'ing its
+ * cpuset pointer. This routine also might acquire callback_sem and
+ * current->mm->mmap_sem during call.
+ *
+ * Reading current->cpuset->mems_generation doesn't need task_lock
+ * to guard the current->cpuset derefence, because it is guarded
+ * from concurrent freeing of current->cpuset by attach_task(),
+ * using RCU.
+ *
+ * The rcu_dereference() is technically probably not needed,
+ * as I don't actually mind if I see a new cpuset pointer but
+ * an old value of mems_generation. However this really only
+ * matters on alpha systems using cpusets heavily. If I dropped
+ * that rcu_dereference(), it would save them a memory barrier.
+ * For all other arch's, rcu_dereference is a no-op anyway, and for
+ * alpha systems not using cpusets, another planned optimization,
+ * avoiding the rcu critical section for tasks in the root cpuset
+ * which is statically allocated, so can't vanish, will make this
+ * irrelevant. Better to use RCU as intended, than to engage in
+ * some cute trick to save a memory barrier that is impossible to
+ * test, for alpha systems using cpusets heavily, which might not
+ * even exist.
*
* This routine is needed to update the per-task mems_allowed data,
* within the tasks context, when it is trying to allocate memory
@@ -591,27 +641,31 @@ static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
* task has been modifying its cpuset.
*/
-static void refresh_mems(void)
+void cpuset_update_task_memory_state()
{
int my_cpusets_mem_gen;
+ struct task_struct *tsk = current;
+ struct cpuset *cs;
- task_lock(current);
- my_cpusets_mem_gen = current->cpuset->mems_generation;
- task_unlock(current);
-
- if (current->cpuset_mems_generation != my_cpusets_mem_gen) {
- struct cpuset *cs;
- nodemask_t oldmem = current->mems_allowed;
+ if (tsk->cpuset == &top_cpuset) {
+ /* Don't need rcu for top_cpuset. It's never freed. */
+ my_cpusets_mem_gen = top_cpuset.mems_generation;
+ } else {
+ rcu_read_lock();
+ cs = rcu_dereference(tsk->cpuset);
+ my_cpusets_mem_gen = cs->mems_generation;
+ rcu_read_unlock();
+ }
+ if (my_cpusets_mem_gen != tsk->cpuset_mems_generation) {
down(&callback_sem);
- task_lock(current);
- cs = current->cpuset;
- guarantee_online_mems(cs, &current->mems_allowed);
- current->cpuset_mems_generation = cs->mems_generation;
- task_unlock(current);
+ task_lock(tsk);
+ cs = tsk->cpuset; /* Maybe changed when task not locked */
+ guarantee_online_mems(cs, &tsk->mems_allowed);
+ tsk->cpuset_mems_generation = cs->mems_generation;
+ task_unlock(tsk);
up(&callback_sem);
- if (!nodes_equal(oldmem, current->mems_allowed))
- numa_policy_rebind(&oldmem, &current->mems_allowed);
+ mpol_rebind_task(tsk, &tsk->mems_allowed);
}
}
@@ -766,36 +820,150 @@ static int update_cpumask(struct cpuset *cs, char *buf)
}
/*
+ * Handle user request to change the 'mems' memory placement
+ * of a cpuset. Needs to validate the request, update the
+ * cpusets mems_allowed and mems_generation, and for each
+ * task in the cpuset, rebind any vma mempolicies and if
+ * the cpuset is marked 'memory_migrate', migrate the tasks
+ * pages to the new memory.
+ *
* Call with manage_sem held. May take callback_sem during call.
+ * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
+ * lock each such tasks mm->mmap_sem, scan its vma's and rebind
+ * their mempolicies to the cpusets new mems_allowed.
*/
static int update_nodemask(struct cpuset *cs, char *buf)
{
struct cpuset trialcs;
+ nodemask_t oldmem;
+ struct task_struct *g, *p;
+ struct mm_struct **mmarray;
+ int i, n, ntasks;
+ int migrate;
+ int fudge;
int retval;
trialcs = *cs;
retval = nodelist_parse(buf, trialcs.mems_allowed);
if (retval < 0)
- return retval;
+ goto done;
nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map);
- if (nodes_empty(trialcs.mems_allowed))
- return -ENOSPC;
+ oldmem = cs->mems_allowed;
+ if (nodes_equal(oldmem, trialcs.mems_allowed)) {
+ retval = 0; /* Too easy - nothing to do */
+ goto done;
+ }
+ if (nodes_empty(trialcs.mems_allowed)) {
+ retval = -ENOSPC;
+ goto done;
+ }
retval = validate_change(cs, &trialcs);
- if (retval == 0) {
- down(&callback_sem);
- cs->mems_allowed = trialcs.mems_allowed;
- atomic_inc(&cpuset_mems_generation);
- cs->mems_generation = atomic_read(&cpuset_mems_generation);
- up(&callback_sem);
+ if (retval < 0)
+ goto done;
+
+ down(&callback_sem);
+ cs->mems_allowed = trialcs.mems_allowed;
+ atomic_inc(&cpuset_mems_generation);
+ cs->mems_generation = atomic_read(&cpuset_mems_generation);
+ up(&callback_sem);
+
+ set_cpuset_being_rebound(cs); /* causes mpol_copy() rebind */
+
+ fudge = 10; /* spare mmarray[] slots */
+ fudge += cpus_weight(cs->cpus_allowed); /* imagine one fork-bomb/cpu */
+ retval = -ENOMEM;
+
+ /*
+ * Allocate mmarray[] to hold mm reference for each task
+ * in cpuset cs. Can't kmalloc GFP_KERNEL while holding
+ * tasklist_lock. We could use GFP_ATOMIC, but with a
+ * few more lines of code, we can retry until we get a big
+ * enough mmarray[] w/o using GFP_ATOMIC.
+ */
+ while (1) {
+ ntasks = atomic_read(&cs->count); /* guess */
+ ntasks += fudge;
+ mmarray = kmalloc(ntasks * sizeof(*mmarray), GFP_KERNEL);
+ if (!mmarray)
+ goto done;
+ write_lock_irq(&tasklist_lock); /* block fork */
+ if (atomic_read(&cs->count) <= ntasks)
+ break; /* got enough */
+ write_unlock_irq(&tasklist_lock); /* try again */
+ kfree(mmarray);
}
+
+ n = 0;
+
+ /* Load up mmarray[] with mm reference for each task in cpuset. */
+ do_each_thread(g, p) {
+ struct mm_struct *mm;
+
+ if (n >= ntasks) {
+ printk(KERN_WARNING
+ "Cpuset mempolicy rebind incomplete.\n");
+ continue;
+ }
+ if (p->cpuset != cs)
+ continue;
+ mm = get_task_mm(p);
+ if (!mm)
+ continue;
+ mmarray[n++] = mm;
+ } while_each_thread(g, p);
+ write_unlock_irq(&tasklist_lock);
+
+ /*
+ * Now that we've dropped the tasklist spinlock, we can
+ * rebind the vma mempolicies of each mm in mmarray[] to their
+ * new cpuset, and release that mm. The mpol_rebind_mm()
+ * call takes mmap_sem, which we couldn't take while holding
+ * tasklist_lock. Forks can happen again now - the mpol_copy()
+ * cpuset_being_rebound check will catch such forks, and rebind
+ * their vma mempolicies too. Because we still hold the global
+ * cpuset manage_sem, we know that no other rebind effort will
+ * be contending for the global variable cpuset_being_rebound.
+ * It's ok if we rebind the same mm twice; mpol_rebind_mm()
+ * is idempotent. Also migrate pages in each mm to new nodes.
+ */
+ migrate = is_memory_migrate(cs);
+ for (i = 0; i < n; i++) {
+ struct mm_struct *mm = mmarray[i];
+
+ mpol_rebind_mm(mm, &cs->mems_allowed);
+ if (migrate) {
+ do_migrate_pages(mm, &oldmem, &cs->mems_allowed,
+ MPOL_MF_MOVE_ALL);
+ }
+ mmput(mm);
+ }
+
+ /* We're done rebinding vma's to this cpusets new mems_allowed. */
+ kfree(mmarray);
+ set_cpuset_being_rebound(NULL);
+ retval = 0;
+done:
return retval;
}
/*
+ * Call with manage_sem held.
+ */
+
+static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
+{
+ if (simple_strtoul(buf, NULL, 10) != 0)
+ cpuset_memory_pressure_enabled = 1;
+ else
+ cpuset_memory_pressure_enabled = 0;
+ return 0;
+}
+
+/*
* update_flag - read a 0 or a 1 in a file and update associated flag
* bit: the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
- * CS_NOTIFY_ON_RELEASE)
+ * CS_NOTIFY_ON_RELEASE, CS_MEMORY_MIGRATE)
* cs: the cpuset to update
* buf: the buffer where we read the 0 or 1
*
@@ -834,6 +1002,104 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
}
/*
+ * Frequency meter - How fast is some event occuring?
+ *
+ * These routines manage a digitally filtered, constant time based,
+ * event frequency meter. There are four routines:
+ * fmeter_init() - initialize a frequency meter.
+ * fmeter_markevent() - called each time the event happens.
+ * fmeter_getrate() - returns the recent rate of such events.
+ * fmeter_update() - internal routine used to update fmeter.
+ *
+ * A common data structure is passed to each of these routines,
+ * which is used to keep track of the state required to manage the
+ * frequency meter and its digital filter.
+ *
+ * The filter works on the number of events marked per unit time.
+ * The filter is single-pole low-pass recursive (IIR). The time unit
+ * is 1 second. Arithmetic is done using 32-bit integers scaled to
+ * simulate 3 decimal digits of precision (multiplied by 1000).
+ *
+ * With an FM_COEF of 933, and a time base of 1 second, the filter
+ * has a half-life of 10 seconds, meaning that if the events quit
+ * happening, then the rate returned from the fmeter_getrate()
+ * will be cut in half each 10 seconds, until it converges to zero.
+ *
+ * It is not worth doing a real infinitely recursive filter. If more
+ * than FM_MAXTICKS ticks have elapsed since the last filter event,
+ * just compute FM_MAXTICKS ticks worth, by which point the level
+ * will be stable.
+ *
+ * Limit the count of unprocessed events to FM_MAXCNT, so as to avoid
+ * arithmetic overflow in the fmeter_update() routine.
+ *
+ * Given the simple 32 bit integer arithmetic used, this meter works
+ * best for reporting rates between one per millisecond (msec) and
+ * one per 32 (approx) seconds. At constant rates faster than one
+ * per msec it maxes out at values just under 1,000,000. At constant
+ * rates between one per msec, and one per second it will stabilize
+ * to a value N*1000, where N is the rate of events per second.
+ * At constant rates between one per second and one per 32 seconds,
+ * it will be choppy, moving up on the seconds that have an event,
+ * and then decaying until the next event. At rates slower than
+ * about one in 32 seconds, it decays all the way back to zero between
+ * each event.
+ */
+
+#define FM_COEF 933 /* coefficient for half-life of 10 secs */
+#define FM_MAXTICKS ((time_t)99) /* useless computing more ticks than this */
+#define FM_MAXCNT 1000000 /* limit cnt to avoid overflow */
+#define FM_SCALE 1000 /* faux fixed point scale */
+
+/* Initialize a frequency meter */
+static void fmeter_init(struct fmeter *fmp)
+{
+ fmp->cnt = 0;
+ fmp->val = 0;
+ fmp->time = 0;
+ spin_lock_init(&fmp->lock);
+}
+
+/* Internal meter update - process cnt events and update value */
+static void fmeter_update(struct fmeter *fmp)
+{
+ time_t now = get_seconds();
+ time_t ticks = now - fmp->time;
+
+ if (ticks == 0)
+ return;
+
+ ticks = min(FM_MAXTICKS, ticks);
+ while (ticks-- > 0)
+ fmp->val = (FM_COEF * fmp->val) / FM_SCALE;
+ fmp->time = now;
+
+ fmp->val += ((FM_SCALE - FM_COEF) * fmp->cnt) / FM_SCALE;
+ fmp->cnt = 0;
+}
+
+/* Process any previous ticks, then bump cnt by one (times scale). */
+static void fmeter_markevent(struct fmeter *fmp)
+{
+ spin_lock(&fmp->lock);
+ fmeter_update(fmp);
+ fmp->cnt = min(FM_MAXCNT, fmp->cnt + FM_SCALE);
+ spin_unlock(&fmp->lock);
+}
+
+/* Process any previous ticks, then return current value. */
+static int fmeter_getrate(struct fmeter *fmp)
+{
+ int val;
+
+ spin_lock(&fmp->lock);
+ fmeter_update(fmp);
+ val = fmp->val;
+ spin_unlock(&fmp->lock);
+ return val;
+}
+
+/*
* Attack task specified by pid in 'pidbuf' to cpuset 'cs', possibly
* writing the path of the old cpuset in 'ppathbuf' if it needs to be
* notified on release.
@@ -848,6 +1114,8 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
struct task_struct *tsk;
struct cpuset *oldcs;
cpumask_t cpus;
+ nodemask_t from, to;
+ struct mm_struct *mm;
if (sscanf(pidbuf, "%d", &pid) != 1)
return -EIO;
@@ -887,14 +1155,27 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
return -ESRCH;
}
atomic_inc(&cs->count);
- tsk->cpuset = cs;
+ rcu_assign_pointer(tsk->cpuset, cs);
task_unlock(tsk);
guarantee_online_cpus(cs, &cpus);
set_cpus_allowed(tsk, cpus);
+ from = oldcs->mems_allowed;
+ to = cs->mems_allowed;
+
up(&callback_sem);
+
+ mm = get_task_mm(tsk);
+ if (mm) {
+ mpol_rebind_mm(mm, &to);
+ mmput(mm);
+ }
+
+ if (is_memory_migrate(cs))
+ do_migrate_pages(tsk->mm, &from, &to, MPOL_MF_MOVE_ALL);
put_task_struct(tsk);
+ synchronize_rcu();
if (atomic_dec_and_test(&oldcs->count))
check_for_release(oldcs, ppathbuf);
return 0;
@@ -905,11 +1186,14 @@ static int attach_task(struct cpuset *cs, char *pidbuf, char **ppathbuf)
typedef enum {
FILE_ROOT,
FILE_DIR,
+ FILE_MEMORY_MIGRATE,
FILE_CPULIST,
FILE_MEMLIST,
FILE_CPU_EXCLUSIVE,
FILE_MEM_EXCLUSIVE,
FILE_NOTIFY_ON_RELEASE,
+ FILE_MEMORY_PRESSURE_ENABLED,
+ FILE_MEMORY_PRESSURE,
FILE_TASKLIST,
} cpuset_filetype_t;
@@ -960,6 +1244,15 @@ static ssize_t cpuset_common_file_write(struct file *file, const char __user *us
case FILE_NOTIFY_ON_RELEASE:
retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
break;
+ case FILE_MEMORY_MIGRATE:
+ retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
+ break;
+ case FILE_MEMORY_PRESSURE_ENABLED:
+ retval = update_memory_pressure_enabled(cs, buffer);
+ break;
+ case FILE_MEMORY_PRESSURE:
+ retval = -EACCES;
+ break;
case FILE_TASKLIST:
retval = attach_task(cs, buffer, &pathbuf);
break;
@@ -1060,6 +1353,15 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
case FILE_NOTIFY_ON_RELEASE:
*s++ = notify_on_release(cs) ? '1' : '0';
break;
+ case FILE_MEMORY_MIGRATE:
+ *s++ = is_memory_migrate(cs) ? '1' : '0';
+ break;
+ case FILE_MEMORY_PRESSURE_ENABLED:
+ *s++ = cpuset_memory_pressure_enabled ? '1' : '0';
+ break;
+ case FILE_MEMORY_PRESSURE:
+ s += sprintf(s, "%d", fmeter_getrate(&cs->fmeter));
+ break;
default:
retval = -EINVAL;
goto out;
@@ -1178,7 +1480,7 @@ static int cpuset_create_file(struct dentry *dentry, int mode)
/*
* cpuset_create_dir - create a directory for an object.
- * cs: the cpuset we create the directory for.
+ * cs: the cpuset we create the directory for.
* It must have a valid ->parent field
* And we are going to fill its ->dentry field.
* name: The name to give to the cpuset directory. Will be copied.
@@ -1211,7 +1513,7 @@ static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
struct dentry *dentry;
int error;
- down(&dir->d_inode->i_sem);
+ mutex_lock(&dir->d_inode->i_mutex);
dentry = cpuset_get_dentry(dir, cft->name);
if (!IS_ERR(dentry)) {
error = cpuset_create_file(dentry, 0644 | S_IFREG);
@@ -1220,7 +1522,7 @@ static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
dput(dentry);
} else
error = PTR_ERR(dentry);
- up(&dir->d_inode->i_sem);
+ mutex_unlock(&dir->d_inode->i_mutex);
return error;
}
@@ -1252,7 +1554,7 @@ struct ctr_struct {
* when reading out p->cpuset, as we don't really care if it changes
* on the next cycle, and we are not going to try to dereference it.
*/
-static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
+static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
{
int n = 0;
struct task_struct *g, *p;
@@ -1408,6 +1710,21 @@ static struct cftype cft_notify_on_release = {
.private = FILE_NOTIFY_ON_RELEASE,
};
+static struct cftype cft_memory_migrate = {
+ .name = "memory_migrate",
+ .private = FILE_MEMORY_MIGRATE,
+};
+
+static struct cftype cft_memory_pressure_enabled = {
+ .name = "memory_pressure_enabled",
+ .private = FILE_MEMORY_PRESSURE_ENABLED,
+};
+
+static struct cftype cft_memory_pressure = {
+ .name = "memory_pressure",
+ .private = FILE_MEMORY_PRESSURE,
+};
+
static int cpuset_populate_dir(struct dentry *cs_dentry)
{
int err;
@@ -1422,6 +1739,10 @@ static int cpuset_populate_dir(struct dentry *cs_dentry)
return err;
if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_memory_migrate)) < 0)
+ return err;
+ if ((err = cpuset_add_file(cs_dentry, &cft_memory_pressure)) < 0)
+ return err;
if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
return err;
return 0;
@@ -1446,7 +1767,7 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
return -ENOMEM;
down(&manage_sem);
- refresh_mems();
+ cpuset_update_task_memory_state();
cs->flags = 0;
if (notify_on_release(parent))
set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
@@ -1457,11 +1778,13 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
INIT_LIST_HEAD(&cs->children);
atomic_inc(&cpuset_mems_generation);
cs->mems_generation = atomic_read(&cpuset_mems_generation);
+ fmeter_init(&cs->fmeter);
cs->parent = parent;
down(&callback_sem);
list_add(&cs->sibling, &cs->parent->children);
+ number_of_cpusets++;
up(&callback_sem);
err = cpuset_create_dir(cs, name, mode);
@@ -1470,7 +1793,7 @@ static long cpuset_create(struct cpuset *parent, const char *name, int mode)
/*
* Release manage_sem before cpuset_populate_dir() because it
- * will down() this new directory's i_sem and if we race with
+ * will down() this new directory's i_mutex and if we race with
* another mkdir, we might deadlock.
*/
up(&manage_sem);
@@ -1489,7 +1812,7 @@ static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
struct cpuset *c_parent = dentry->d_parent->d_fsdata;
- /* the vfs holds inode->i_sem already */
+ /* the vfs holds inode->i_mutex already */
return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
}
@@ -1500,10 +1823,10 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
struct cpuset *parent;
char *pathbuf = NULL;
- /* the vfs holds both inode->i_sem already */
+ /* the vfs holds both inode->i_mutex already */
down(&manage_sem);
- refresh_mems();
+ cpuset_update_task_memory_state();
if (atomic_read(&cs->count) > 0) {
up(&manage_sem);
return -EBUSY;
@@ -1524,6 +1847,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
spin_unlock(&d->d_lock);
cpuset_d_remove_dir(d);
dput(d);
+ number_of_cpusets--;
up(&callback_sem);
if (list_empty(&parent->children))
check_for_release(parent, &pathbuf);
@@ -1532,6 +1856,21 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
return 0;
}
+/*
+ * cpuset_init_early - just enough so that the calls to
+ * cpuset_update_task_memory_state() in early init code
+ * are harmless.
+ */
+
+int __init cpuset_init_early(void)
+{
+ struct task_struct *tsk = current;
+
+ tsk->cpuset = &top_cpuset;
+ tsk->cpuset->mems_generation = atomic_read(&cpuset_mems_generation);
+ return 0;
+}
+
/**
* cpuset_init - initialize cpusets at system boot
*
@@ -1546,6 +1885,7 @@ int __init cpuset_init(void)
top_cpuset.cpus_allowed = CPU_MASK_ALL;
top_cpuset.mems_allowed = NODE_MASK_ALL;
+ fmeter_init(&top_cpuset.fmeter);
atomic_inc(&cpuset_mems_generation);
top_cpuset.mems_generation = atomic_read(&cpuset_mems_generation);
@@ -1566,7 +1906,11 @@ int __init cpuset_init(void)
root->d_inode->i_nlink++;
top_cpuset.dentry = root;
root->d_inode->i_op = &cpuset_dir_inode_operations;
+ number_of_cpusets = 1;
err = cpuset_populate_dir(root);
+ /* memory_pressure_enabled is in root cpuset only */
+ if (err == 0)
+ err = cpuset_add_file(root, &cft_memory_pressure_enabled);
out:
return err;
}
@@ -1632,15 +1976,13 @@ void cpuset_fork(struct task_struct *child)
*
* We don't need to task_lock() this reference to tsk->cpuset,
* because tsk is already marked PF_EXITING, so attach_task() won't
- * mess with it.
+ * mess with it, or task is a failed fork, never visible to attach_task.
**/
void cpuset_exit(struct task_struct *tsk)
{
struct cpuset *cs;
- BUG_ON(!(tsk->flags & PF_EXITING));
-
cs = tsk->cpuset;
tsk->cpuset = NULL;
@@ -1667,14 +2009,14 @@ void cpuset_exit(struct task_struct *tsk)
* tasks cpuset.
**/
-cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk)
+cpumask_t cpuset_cpus_allowed(struct task_struct *tsk)
{
cpumask_t mask;
down(&callback_sem);
- task_lock((struct task_struct *)tsk);
+ task_lock(tsk);
guarantee_online_cpus(tsk->cpuset, &mask);
- task_unlock((struct task_struct *)tsk);
+ task_unlock(tsk);
up(&callback_sem);
return mask;
@@ -1686,43 +2028,26 @@ void cpuset_init_current_mems_allowed(void)
}
/**
- * cpuset_update_current_mems_allowed - update mems parameters to new values
- *
- * If the current tasks cpusets mems_allowed changed behind our backs,
- * update current->mems_allowed and mems_generation to the new value.
- * Do not call this routine if in_interrupt().
+ * cpuset_mems_allowed - return mems_allowed mask from a tasks cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->mems_allowed.
*
- * Call without callback_sem or task_lock() held. May be called
- * with or without manage_sem held. Unless exiting, it will acquire
- * task_lock(). Also might acquire callback_sem during call to
- * refresh_mems().
- */
+ * Description: Returns the nodemask_t mems_allowed of the cpuset
+ * attached to the specified @tsk. Guaranteed to return some non-empty
+ * subset of node_online_map, even if this means going outside the
+ * tasks cpuset.
+ **/
-void cpuset_update_current_mems_allowed(void)
+nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
{
- struct cpuset *cs;
- int need_to_refresh = 0;
+ nodemask_t mask;
- task_lock(current);
- cs = current->cpuset;
- if (!cs)
- goto done;
- if (current->cpuset_mems_generation != cs->mems_generation)
- need_to_refresh = 1;
-done:
- task_unlock(current);
- if (need_to_refresh)
- refresh_mems();
-}
+ down(&callback_sem);
+ task_lock(tsk);
+ guarantee_online_mems(tsk->cpuset, &mask);
+ task_unlock(tsk);
+ up(&callback_sem);
-/**
- * cpuset_restrict_to_mems_allowed - limit nodes to current mems_allowed
- * @nodes: pointer to a node bitmap that is and-ed with mems_allowed
- */
-void cpuset_restrict_to_mems_allowed(unsigned long *nodes)
-{
- bitmap_and(nodes, nodes, nodes_addr(current->mems_allowed),
- MAX_NUMNODES);
+ return mask;
}
/**
@@ -1795,7 +2120,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
* GFP_USER - only nodes in current tasks mems allowed ok.
**/
-int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
+int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
{
int node; /* node that zone z is on */
const struct cpuset *cs; /* current cpuset ancestors */
@@ -1825,6 +2150,33 @@ int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
}
/**
+ * cpuset_lock - lock out any changes to cpuset structures
+ *
+ * The out of memory (oom) code needs to lock down cpusets
+ * from being changed while it scans the tasklist looking for a
+ * task in an overlapping cpuset. Expose callback_sem via this
+ * cpuset_lock() routine, so the oom code can lock it, before
+ * locking the task list. The tasklist_lock is a spinlock, so
+ * must be taken inside callback_sem.
+ */
+
+void cpuset_lock(void)
+{
+ down(&callback_sem);
+}
+
+/**
+ * cpuset_unlock - release lock on cpuset changes
+ *
+ * Undo the lock taken in a previous cpuset_lock() call.
+ */
+
+void cpuset_unlock(void)
+{
+ up(&callback_sem);
+}
+
+/**
* cpuset_excl_nodes_overlap - Do we overlap @p's mem_exclusive ancestors?
* @p: pointer to task_struct of some other task.
*
@@ -1833,7 +2185,7 @@ int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask)
* determine if task @p's memory usage might impact the memory
* available to the current task.
*
- * Acquires callback_sem - not suitable for calling from a fast path.
+ * Call while holding callback_sem.
**/
int cpuset_excl_nodes_overlap(const struct task_struct *p)
@@ -1841,8 +2193,6 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */
int overlap = 0; /* do cpusets overlap? */
- down(&callback_sem);
-
task_lock(current);
if (current->flags & PF_EXITING) {
task_unlock(current);
@@ -1861,12 +2211,46 @@ int cpuset_excl_nodes_overlap(const struct task_struct *p)
overlap = nodes_intersects(cs1->mems_allowed, cs2->mems_allowed);
done:
- up(&callback_sem);
-
return overlap;
}
/*
+ * Collection of memory_pressure is suppressed unless
+ * this flag is enabled by writing "1" to the special
+ * cpuset file 'memory_pressure_enabled' in the root cpuset.
+ */
+
+int cpuset_memory_pressure_enabled __read_mostly;
+
+/**
+ * cpuset_memory_pressure_bump - keep stats of per-cpuset reclaims.
+ *
+ * Keep a running average of the rate of synchronous (direct)
+ * page reclaim efforts initiated by tasks in each cpuset.
+ *
+ * This represents the rate at which some task in the cpuset
+ * ran low on memory on all nodes it was allowed to use, and
+ * had to enter the kernels page reclaim code in an effort to
+ * create more free memory by tossing clean pages or swapping
+ * or writing dirty pages.
+ *
+ * Display to user space in the per-cpuset read-only file
+ * "memory_pressure". Value displayed is an integer
+ * representing the recent rate of entry into the synchronous
+ * (direct) page reclaim by any task attached to the cpuset.
+ **/
+
+void __cpuset_memory_pressure_bump(void)
+{
+ struct cpuset *cs;
+
+ task_lock(current);
+ cs = current->cpuset;
+ fmeter_markevent(&cs->fmeter);
+ task_unlock(current);
+}
+
+/*
* proc_cpuset_show()
* - Print tasks cpuset path into seq_file.
* - Used for /proc/<pid>/cpuset.
diff --git a/kernel/exit.c b/kernel/exit.c
index ee515683b92d..93cee3671332 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/completion.h>
#include <linux/personality.h>
#include <linux/tty.h>
@@ -29,6 +30,7 @@
#include <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/cn_proc.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -72,7 +74,6 @@ repeat:
__ptrace_unlink(p);
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
__exit_signal(p);
- __exit_sighand(p);
/*
* Note that the fastpath in sys_times depends on __exit_signal having
* updated the counters before a task is removed from the tasklist of
@@ -192,7 +193,7 @@ int is_orphaned_pgrp(int pgrp)
return retval;
}
-static inline int has_stopped_jobs(int pgrp)
+static int has_stopped_jobs(int pgrp)
{
int retval = 0;
struct task_struct *p;
@@ -229,7 +230,7 @@ static inline int has_stopped_jobs(int pgrp)
*
* NOTE that reparent_to_init() gives the caller full capabilities.
*/
-static inline void reparent_to_init(void)
+static void reparent_to_init(void)
{
write_lock_irq(&tasklist_lock);
@@ -243,7 +244,9 @@ static inline void reparent_to_init(void)
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
- if ((current->policy == SCHED_NORMAL) && (task_nice(current) < 0))
+ if ((current->policy == SCHED_NORMAL ||
+ current->policy == SCHED_BATCH)
+ && (task_nice(current) < 0))
set_user_nice(current, 0);
/* cpus_allowed? */
/* rt_priority? */
@@ -258,7 +261,7 @@ static inline void reparent_to_init(void)
void __set_special_pids(pid_t session, pid_t pgrp)
{
- struct task_struct *curr = current;
+ struct task_struct *curr = current->group_leader;
if (curr->signal->session != session) {
detach_pid(curr, PIDTYPE_SID);
@@ -366,7 +369,7 @@ void daemonize(const char *name, ...)
EXPORT_SYMBOL(daemonize);
-static inline void close_files(struct files_struct * files)
+static void close_files(struct files_struct * files)
{
int i, j;
struct fdtable *fdt;
@@ -540,7 +543,7 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re
p->real_parent = reaper;
}
-static inline void reparent_thread(task_t *p, task_t *father, int traced)
+static void reparent_thread(task_t *p, task_t *father, int traced)
{
/* We don't want people slaying init. */
if (p->exit_signal != -1)
@@ -604,7 +607,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
* group, and if no such member exists, give it to
* the global child reaper process (ie "init")
*/
-static inline void forget_original_parent(struct task_struct * father,
+static void forget_original_parent(struct task_struct * father,
struct list_head *to_release)
{
struct task_struct *p, *reaper = father;
@@ -842,7 +845,7 @@ fastcall NORET_TYPE void do_exit(long code)
}
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
- del_timer_sync(&tsk->signal->real_timer);
+ hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
acct_process(code);
}
@@ -870,6 +873,10 @@ fastcall NORET_TYPE void do_exit(long code)
mpol_free(tsk->mempolicy);
tsk->mempolicy = NULL;
#endif
+ /*
+ * If DEBUG_MUTEXES is on, make sure we are holding no locks:
+ */
+ mutex_debug_check_no_locks_held(tsk);
/* PF_DEAD causes final put_task_struct after we schedule. */
preempt_disable();
@@ -926,7 +933,6 @@ do_group_exit(int exit_code)
/* Another thread got here before we took the lock. */
exit_code = sig->group_exit_code;
else {
- sig->flags = SIGNAL_GROUP_EXIT;
sig->group_exit_code = exit_code;
zap_other_threads(current);
}
@@ -1068,6 +1074,9 @@ static int wait_task_zombie(task_t *p, int noreap,
}
if (likely(p->real_parent == p->parent) && likely(p->signal)) {
+ struct signal_struct *psig;
+ struct signal_struct *sig;
+
/*
* The resource counters for the group leader are in its
* own task_struct. Those for dead threads in the group
@@ -1084,24 +1093,26 @@ static int wait_task_zombie(task_t *p, int noreap,
* here reaping other children at the same time.
*/
spin_lock_irq(&p->parent->sighand->siglock);
- p->parent->signal->cutime =
- cputime_add(p->parent->signal->cutime,
+ psig = p->parent->signal;
+ sig = p->signal;
+ psig->cutime =
+ cputime_add(psig->cutime,
cputime_add(p->utime,
- cputime_add(p->signal->utime,
- p->signal->cutime)));
- p->parent->signal->cstime =
- cputime_add(p->parent->signal->cstime,
+ cputime_add(sig->utime,
+ sig->cutime)));
+ psig->cstime =
+ cputime_add(psig->cstime,
cputime_add(p->stime,
- cputime_add(p->signal->stime,
- p->signal->cstime)));
- p->parent->signal->cmin_flt +=
- p->min_flt + p->signal->min_flt + p->signal->cmin_flt;
- p->parent->signal->cmaj_flt +=
- p->maj_flt + p->signal->maj_flt + p->signal->cmaj_flt;
- p->parent->signal->cnvcsw +=
- p->nvcsw + p->signal->nvcsw + p->signal->cnvcsw;
- p->parent->signal->cnivcsw +=
- p->nivcsw + p->signal->nivcsw + p->signal->cnivcsw;
+ cputime_add(sig->stime,
+ sig->cstime)));
+ psig->cmin_flt +=
+ p->min_flt + sig->min_flt + sig->cmin_flt;
+ psig->cmaj_flt +=
+ p->maj_flt + sig->maj_flt + sig->cmaj_flt;
+ psig->cnvcsw +=
+ p->nvcsw + sig->nvcsw + sig->cnvcsw;
+ psig->cnivcsw +=
+ p->nivcsw + sig->nivcsw + sig->cnivcsw;
spin_unlock_irq(&p->parent->sighand->siglock);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index fb8572a42297..4ae8cfc1c89c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -28,6 +28,7 @@
#include <linux/binfmts.h>
#include <linux/mman.h>
#include <linux/fs.h>
+#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/cpuset.h>
#include <linux/security.h>
@@ -743,6 +744,14 @@ int unshare_files(void)
EXPORT_SYMBOL(unshare_files);
+void sighand_free_cb(struct rcu_head *rhp)
+{
+ struct sighand_struct *sp;
+
+ sp = container_of(rhp, struct sighand_struct, rcu);
+ kmem_cache_free(sighand_cachep, sp);
+}
+
static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
{
struct sighand_struct *sig;
@@ -752,7 +761,7 @@ static inline int copy_sighand(unsigned long clone_flags, struct task_struct * t
return 0;
}
sig = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
- tsk->sighand = sig;
+ rcu_assign_pointer(tsk->sighand, sig);
if (!sig)
return -ENOMEM;
spin_lock_init(&sig->siglock);
@@ -793,19 +802,16 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
init_sigpending(&sig->shared_pending);
INIT_LIST_HEAD(&sig->posix_timers);
- sig->it_real_value = sig->it_real_incr = 0;
+ hrtimer_init(&sig->real_timer, CLOCK_MONOTONIC);
+ sig->it_real_incr.tv64 = 0;
sig->real_timer.function = it_real_fn;
- sig->real_timer.data = (unsigned long) tsk;
- init_timer(&sig->real_timer);
+ sig->real_timer.data = tsk;
sig->it_virt_expires = cputime_zero;
sig->it_virt_incr = cputime_zero;
sig->it_prof_expires = cputime_zero;
sig->it_prof_incr = cputime_zero;
- sig->tty = current->signal->tty;
- sig->pgrp = process_group(current);
- sig->session = current->signal->session;
sig->leader = 0; /* session leadership doesn't inherit */
sig->tty_old_pgrp = 0;
@@ -964,15 +970,20 @@ static task_t *copy_process(unsigned long clone_flags,
p->io_context = NULL;
p->io_wait = NULL;
p->audit_context = NULL;
+ cpuset_fork(p);
#ifdef CONFIG_NUMA
p->mempolicy = mpol_copy(p->mempolicy);
if (IS_ERR(p->mempolicy)) {
retval = PTR_ERR(p->mempolicy);
p->mempolicy = NULL;
- goto bad_fork_cleanup;
+ goto bad_fork_cleanup_cpuset;
}
#endif
+#ifdef CONFIG_DEBUG_MUTEXES
+ p->blocked_on = NULL; /* not blocked yet */
+#endif
+
p->tgid = p->pid;
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
@@ -1127,25 +1138,19 @@ static task_t *copy_process(unsigned long clone_flags,
attach_pid(p, PIDTYPE_PID, p->pid);
attach_pid(p, PIDTYPE_TGID, p->tgid);
if (thread_group_leader(p)) {
+ p->signal->tty = current->signal->tty;
+ p->signal->pgrp = process_group(current);
+ p->signal->session = current->signal->session;
attach_pid(p, PIDTYPE_PGID, process_group(p));
attach_pid(p, PIDTYPE_SID, p->signal->session);
if (p->pid)
__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);
proc_fork_connector(p);
- cpuset_fork(p);
- retval = 0;
-
-fork_out:
- if (retval)
- return ERR_PTR(retval);
return p;
bad_fork_cleanup_namespace:
@@ -1172,7 +1177,9 @@ bad_fork_cleanup_security:
bad_fork_cleanup_policy:
#ifdef CONFIG_NUMA
mpol_free(p->mempolicy);
+bad_fork_cleanup_cpuset:
#endif
+ cpuset_exit(p);
bad_fork_cleanup:
if (p->binfmt)
module_put(p->binfmt->module);
@@ -1184,7 +1191,8 @@ bad_fork_cleanup_count:
free_uid(p->user);
bad_fork_free:
free_task(p);
- goto fork_out;
+fork_out:
+ return ERR_PTR(retval);
}
struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
@@ -1290,6 +1298,10 @@ long do_fork(unsigned long clone_flags,
return pid;
}
+#ifndef ARCH_MIN_MMSTRUCT_ALIGN
+#define ARCH_MIN_MMSTRUCT_ALIGN 0
+#endif
+
void __init proc_caches_init(void)
{
sighand_cachep = kmem_cache_create("sighand_cache",
@@ -1308,6 +1320,6 @@ void __init proc_caches_init(void)
sizeof(struct vm_area_struct), 0,
SLAB_PANIC, NULL, NULL);
mm_cachep = kmem_cache_create("mm_struct",
- sizeof(struct mm_struct), 0,
+ sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
}
diff --git a/kernel/futex.c b/kernel/futex.c
index 5e71a6bf6f6b..5efa2f978032 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -356,6 +356,13 @@ retry:
if (bh1 != bh2)
spin_unlock(&bh2->lock);
+#ifndef CONFIG_MMU
+ /* we don't get EFAULT from MMU faults if we don't have an MMU,
+ * but we might get them from range checking */
+ ret = op_ret;
+ goto out;
+#endif
+
if (unlikely(op_ret != -EFAULT)) {
ret = op_ret;
goto out;
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
new file mode 100644
index 000000000000..f1c4155b49ac
--- /dev/null
+++ b/kernel/hrtimer.c
@@ -0,0 +1,826 @@
+/*
+ * linux/kernel/hrtimer.c
+ *
+ * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
+ * Copyright(C) 2005, Red Hat, Inc., Ingo Molnar
+ *
+ * High-resolution kernel timers
+ *
+ * In contrast to the low-resolution timeout API implemented in
+ * kernel/timer.c, hrtimers provide finer resolution and accuracy
+ * depending on system configuration and capabilities.
+ *
+ * These timers are currently used for:
+ * - itimers
+ * - POSIX timers
+ * - nanosleep
+ * - precise in-kernel timing
+ *
+ * Started by: Thomas Gleixner and Ingo Molnar
+ *
+ * Credits:
+ * based on kernel/timer.c
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
+#include <linux/hrtimer.h>
+#include <linux/notifier.h>
+#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
+
+/**
+ * ktime_get - get the monotonic time in ktime_t format
+ *
+ * returns the time in ktime_t format
+ */
+static ktime_t ktime_get(void)
+{
+ struct timespec now;
+
+ ktime_get_ts(&now);
+
+ return timespec_to_ktime(now);
+}
+
+/**
+ * ktime_get_real - get the real (wall-) time in ktime_t format
+ *
+ * returns the time in ktime_t format
+ */
+static ktime_t ktime_get_real(void)
+{
+ struct timespec now;
+
+ getnstimeofday(&now);
+
+ return timespec_to_ktime(now);
+}
+
+EXPORT_SYMBOL_GPL(ktime_get_real);
+
+/*
+ * The timer bases:
+ */
+
+#define MAX_HRTIMER_BASES 2
+
+static DEFINE_PER_CPU(struct hrtimer_base, hrtimer_bases[MAX_HRTIMER_BASES]) =
+{
+ {
+ .index = CLOCK_REALTIME,
+ .get_time = &ktime_get_real,
+ .resolution = KTIME_REALTIME_RES,
+ },
+ {
+ .index = CLOCK_MONOTONIC,
+ .get_time = &ktime_get,
+ .resolution = KTIME_MONOTONIC_RES,
+ },
+};
+
+/**
+ * ktime_get_ts - get the monotonic clock in timespec format
+ *
+ * @ts: pointer to timespec variable
+ *
+ * The function calculates the monotonic clock from the realtime
+ * clock and the wall_to_monotonic offset and stores the result
+ * in normalized timespec format in the variable pointed to by ts.
+ */
+void ktime_get_ts(struct timespec *ts)
+{
+ struct timespec tomono;
+ unsigned long seq;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+ getnstimeofday(ts);
+ tomono = wall_to_monotonic;
+
+ } while (read_seqretry(&xtime_lock, seq));
+
+ set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
+ ts->tv_nsec + tomono.tv_nsec);
+}
+EXPORT_SYMBOL_GPL(ktime_get_ts);
+
+/*
+ * Functions and macros which are different for UP/SMP systems are kept in a
+ * single place
+ */
+#ifdef CONFIG_SMP
+
+#define set_curr_timer(b, t) do { (b)->curr_timer = (t); } while (0)
+
+/*
+ * We are using hashed locking: holding per_cpu(hrtimer_bases)[n].lock
+ * means that all timers which are tied to this base via timer->base are
+ * locked, and the base itself is locked too.
+ *
+ * So __run_timers/migrate_timers can safely modify all timers which could
+ * be found on the lists/queues.
+ *
+ * When the timer's base is locked, and the timer removed from list, it is
+ * possible to set timer->base = NULL and drop the lock: the timer remains
+ * locked.
+ */
+static struct hrtimer_base *lock_hrtimer_base(const struct hrtimer *timer,
+ unsigned long *flags)
+{
+ struct hrtimer_base *base;
+
+ for (;;) {
+ base = timer->base;
+ if (likely(base != NULL)) {
+ spin_lock_irqsave(&base->lock, *flags);
+ if (likely(base == timer->base))
+ return base;
+ /* The timer has migrated to another CPU: */
+ spin_unlock_irqrestore(&base->lock, *flags);
+ }
+ cpu_relax();
+ }
+}
+
+/*
+ * Switch the timer base to the current CPU when possible.
+ */
+static inline struct hrtimer_base *
+switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base)
+{
+ struct hrtimer_base *new_base;
+
+ new_base = &__get_cpu_var(hrtimer_bases[base->index]);
+
+ if (base != new_base) {
+ /*
+ * We are trying to schedule the timer on the local CPU.
+ * However we can't change timer's base while it is running,
+ * so we keep it on the same CPU. No hassle vs. reprogramming
+ * the event source in the high resolution case. The softirq
+ * code will take care of this when the timer function has
+ * completed. There is no conflict as we hold the lock until
+ * the timer is enqueued.
+ */
+ if (unlikely(base->curr_timer == timer))
+ return base;
+
+ /* See the comment in lock_timer_base() */
+ timer->base = NULL;
+ spin_unlock(&base->lock);
+ spin_lock(&new_base->lock);
+ timer->base = new_base;
+ }
+ return new_base;
+}
+
+#else /* CONFIG_SMP */
+
+#define set_curr_timer(b, t) do { } while (0)
+
+static inline struct hrtimer_base *
+lock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
+{
+ struct hrtimer_base *base = timer->base;
+
+ spin_lock_irqsave(&base->lock, *flags);
+
+ return base;
+}
+
+#define switch_hrtimer_base(t, b) (b)
+
+#endif /* !CONFIG_SMP */
+
+/*
+ * Functions for the union type storage format of ktime_t which are
+ * too large for inlining:
+ */
+#if BITS_PER_LONG < 64
+# ifndef CONFIG_KTIME_SCALAR
+/**
+ * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
+ *
+ * @kt: addend
+ * @nsec: the scalar nsec value to add
+ *
+ * Returns the sum of kt and nsec in ktime_t format
+ */
+ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
+{
+ ktime_t tmp;
+
+ if (likely(nsec < NSEC_PER_SEC)) {
+ tmp.tv64 = nsec;
+ } else {
+ unsigned long rem = do_div(nsec, NSEC_PER_SEC);
+
+ tmp = ktime_set((long)nsec, rem);
+ }
+
+ return ktime_add(kt, tmp);
+}
+
+#else /* CONFIG_KTIME_SCALAR */
+
+# endif /* !CONFIG_KTIME_SCALAR */
+
+/*
+ * Divide a ktime value by a nanosecond value
+ */
+static unsigned long ktime_divns(const ktime_t kt, nsec_t div)
+{
+ u64 dclc, inc, dns;
+ int sft = 0;
+
+ dclc = dns = ktime_to_ns(kt);
+ inc = div;
+ /* Make sure the divisor is less than 2^32: */
+ while (div >> 32) {
+ sft++;
+ div >>= 1;
+ }
+ dclc >>= sft;
+ do_div(dclc, (unsigned long) div);
+
+ return (unsigned long) dclc;
+}
+
+#else /* BITS_PER_LONG < 64 */
+# define ktime_divns(kt, div) (unsigned long)((kt).tv64 / (div))
+#endif /* BITS_PER_LONG >= 64 */
+
+/*
+ * Counterpart to lock_timer_base above:
+ */
+static inline
+void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
+{
+ spin_unlock_irqrestore(&timer->base->lock, *flags);
+}
+
+/**
+ * hrtimer_forward - forward the timer expiry
+ *
+ * @timer: hrtimer to forward
+ * @interval: the interval to forward
+ *
+ * Forward the timer expiry so it will expire in the future.
+ * Returns the number of overruns.
+ */
+unsigned long
+hrtimer_forward(struct hrtimer *timer, ktime_t interval)
+{
+ unsigned long orun = 1;
+ ktime_t delta, now;
+
+ now = timer->base->get_time();
+
+ delta = ktime_sub(now, timer->expires);
+
+ if (delta.tv64 < 0)
+ return 0;
+
+ if (interval.tv64 < timer->base->resolution.tv64)
+ interval.tv64 = timer->base->resolution.tv64;
+
+ if (unlikely(delta.tv64 >= interval.tv64)) {
+ nsec_t incr = ktime_to_ns(interval);
+
+ orun = ktime_divns(delta, incr);
+ timer->expires = ktime_add_ns(timer->expires, incr * orun);
+ if (timer->expires.tv64 > now.tv64)
+ return orun;
+ /*
+ * This (and the ktime_add() below) is the
+ * correction for exact:
+ */
+ orun++;
+ }
+ timer->expires = ktime_add(timer->expires, interval);
+
+ return orun;
+}
+
+/*
+ * enqueue_hrtimer - internal function to (re)start a timer
+ *
+ * The timer is inserted in expiry order. Insertion into the
+ * red black tree is O(log(n)). Must hold the base lock.
+ */
+static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+ struct rb_node **link = &base->active.rb_node;
+ struct rb_node *parent = NULL;
+ struct hrtimer *entry;
+
+ /*
+ * Find the right place in the rbtree:
+ */
+ while (*link) {
+ parent = *link;
+ entry = rb_entry(parent, struct hrtimer, node);
+ /*
+ * We dont care about collisions. Nodes with
+ * the same expiry time stay together.
+ */
+ if (timer->expires.tv64 < entry->expires.tv64)
+ link = &(*link)->rb_left;
+ else
+ link = &(*link)->rb_right;
+ }
+
+ /*
+ * Insert the timer to the rbtree and check whether it
+ * replaces the first pending timer
+ */
+ rb_link_node(&timer->node, parent, link);
+ rb_insert_color(&timer->node, &base->active);
+
+ timer->state = HRTIMER_PENDING;
+
+ if (!base->first || timer->expires.tv64 <
+ rb_entry(base->first, struct hrtimer, node)->expires.tv64)
+ base->first = &timer->node;
+}
+
+/*
+ * __remove_hrtimer - internal function to remove a timer
+ *
+ * Caller must hold the base lock.
+ */
+static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+ /*
+ * Remove the timer from the rbtree and replace the
+ * first entry pointer if necessary.
+ */
+ if (base->first == &timer->node)
+ base->first = rb_next(&timer->node);
+ rb_erase(&timer->node, &base->active);
+}
+
+/*
+ * remove hrtimer, called with base lock held
+ */
+static inline int
+remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base)
+{
+ if (hrtimer_active(timer)) {
+ __remove_hrtimer(timer, base);
+ timer->state = HRTIMER_INACTIVE;
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * hrtimer_start - (re)start an relative timer on the current CPU
+ *
+ * @timer: the timer to be added
+ * @tim: expiry time
+ * @mode: expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
+ *
+ * Returns:
+ * 0 on success
+ * 1 when the timer was active
+ */
+int
+hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
+{
+ struct hrtimer_base *base, *new_base;
+ unsigned long flags;
+ int ret;
+
+ base = lock_hrtimer_base(timer, &flags);
+
+ /* Remove an active timer from the queue: */
+ ret = remove_hrtimer(timer, base);
+
+ /* Switch the timer base, if necessary: */
+ new_base = switch_hrtimer_base(timer, base);
+
+ if (mode == HRTIMER_REL)
+ tim = ktime_add(tim, new_base->get_time());
+ timer->expires = tim;
+
+ enqueue_hrtimer(timer, new_base);
+
+ unlock_hrtimer_base(timer, &flags);
+
+ return ret;
+}
+
+/**
+ * hrtimer_try_to_cancel - try to deactivate a timer
+ *
+ * @timer: hrtimer to stop
+ *
+ * Returns:
+ * 0 when the timer was not active
+ * 1 when the timer was active
+ * -1 when the timer is currently excuting the callback function and
+ * can not be stopped
+ */
+int hrtimer_try_to_cancel(struct hrtimer *timer)
+{
+ struct hrtimer_base *base;
+ unsigned long flags;
+ int ret = -1;
+
+ base = lock_hrtimer_base(timer, &flags);
+
+ if (base->curr_timer != timer)
+ ret = remove_hrtimer(timer, base);
+
+ unlock_hrtimer_base(timer, &flags);
+
+ return ret;
+
+}
+
+/**
+ * hrtimer_cancel - cancel a timer and wait for the handler to finish.
+ *
+ * @timer: the timer to be cancelled
+ *
+ * Returns:
+ * 0 when the timer was not active
+ * 1 when the timer was active
+ */
+int hrtimer_cancel(struct hrtimer *timer)
+{
+ for (;;) {
+ int ret = hrtimer_try_to_cancel(timer);
+
+ if (ret >= 0)
+ return ret;
+ }
+}
+
+/**
+ * hrtimer_get_remaining - get remaining time for the timer
+ *
+ * @timer: the timer to read
+ */
+ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+{
+ struct hrtimer_base *base;
+ unsigned long flags;
+ ktime_t rem;
+
+ base = lock_hrtimer_base(timer, &flags);
+ rem = ktime_sub(timer->expires, timer->base->get_time());
+ unlock_hrtimer_base(timer, &flags);
+
+ return rem;
+}
+
+/**
+ * hrtimer_rebase - rebase an initialized hrtimer to a different base
+ *
+ * @timer: the timer to be rebased
+ * @clock_id: the clock to be used
+ */
+void hrtimer_rebase(struct hrtimer *timer, const clockid_t clock_id)
+{
+ struct hrtimer_base *bases;
+
+ bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+ timer->base = &bases[clock_id];
+}
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ *
+ * @timer: the timer to be initialized
+ * @clock_id: the clock to be used
+ */
+void hrtimer_init(struct hrtimer *timer, const clockid_t clock_id)
+{
+ memset(timer, 0, sizeof(struct hrtimer));
+ hrtimer_rebase(timer, clock_id);
+}
+
+/**
+ * hrtimer_get_res - get the timer resolution for a clock
+ *
+ * @which_clock: which clock to query
+ * @tp: pointer to timespec variable to store the resolution
+ *
+ * Store the resolution of the clock selected by which_clock in the
+ * variable pointed to by tp.
+ */
+int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+{
+ struct hrtimer_base *bases;
+
+ bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+ *tp = ktime_to_timespec(bases[which_clock].resolution);
+
+ return 0;
+}
+
+/*
+ * Expire the per base hrtimer-queue:
+ */
+static inline void run_hrtimer_queue(struct hrtimer_base *base)
+{
+ ktime_t now = base->get_time();
+ struct rb_node *node;
+
+ spin_lock_irq(&base->lock);
+
+ while ((node = base->first)) {
+ struct hrtimer *timer;
+ int (*fn)(void *);
+ int restart;
+ void *data;
+
+ timer = rb_entry(node, struct hrtimer, node);
+ if (now.tv64 <= timer->expires.tv64)
+ break;
+
+ fn = timer->function;
+ data = timer->data;
+ set_curr_timer(base, timer);
+ __remove_hrtimer(timer, base);
+ spin_unlock_irq(&base->lock);
+
+ /*
+ * fn == NULL is special case for the simplest timer
+ * variant - wake up process and do not restart:
+ */
+ if (!fn) {
+ wake_up_process(data);
+ restart = HRTIMER_NORESTART;
+ } else
+ restart = fn(data);
+
+ spin_lock_irq(&base->lock);
+
+ if (restart == HRTIMER_RESTART)
+ enqueue_hrtimer(timer, base);
+ else
+ timer->state = HRTIMER_EXPIRED;
+ }
+ set_curr_timer(base, NULL);
+ spin_unlock_irq(&base->lock);
+}
+
+/*
+ * Called from timer softirq every jiffy, expire hrtimers:
+ */
+void hrtimer_run_queues(void)
+{
+ struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
+ int i;
+
+ for (i = 0; i < MAX_HRTIMER_BASES; i++)
+ run_hrtimer_queue(&base[i]);
+}
+
+/*
+ * Sleep related functions:
+ */
+
+/**
+ * schedule_hrtimer - sleep until timeout
+ *
+ * @timer: hrtimer variable initialized with the correct clock base
+ * @mode: timeout value is abs/rel
+ *
+ * Make the current task sleep until @timeout is
+ * elapsed.
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout is guaranteed to
+ * pass before the routine returns. The routine will return 0
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task. In this case the remaining time
+ * will be returned
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ */
+static ktime_t __sched
+schedule_hrtimer(struct hrtimer *timer, const enum hrtimer_mode mode)
+{
+ /* fn stays NULL, meaning single-shot wakeup: */
+ timer->data = current;
+
+ hrtimer_start(timer, timer->expires, mode);
+
+ schedule();
+ hrtimer_cancel(timer);
+
+ /* Return the remaining time: */
+ if (timer->state != HRTIMER_EXPIRED)
+ return ktime_sub(timer->expires, timer->base->get_time());
+ else
+ return (ktime_t) {.tv64 = 0 };
+}
+
+static inline ktime_t __sched
+schedule_hrtimer_interruptible(struct hrtimer *timer,
+ const enum hrtimer_mode mode)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ return schedule_hrtimer(timer, mode);
+}
+
+static long __sched
+nanosleep_restart(struct restart_block *restart, clockid_t clockid)
+{
+ struct timespec __user *rmtp;
+ struct timespec tu;
+ void *rfn_save = restart->fn;
+ struct hrtimer timer;
+ ktime_t rem;
+
+ restart->fn = do_no_restart_syscall;
+
+ hrtimer_init(&timer, clockid);
+
+ timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0;
+
+ rem = schedule_hrtimer_interruptible(&timer, HRTIMER_ABS);
+
+ if (rem.tv64 <= 0)
+ return 0;
+
+ rmtp = (struct timespec __user *) restart->arg2;
+ tu = ktime_to_timespec(rem);
+ if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+
+ restart->fn = rfn_save;
+
+ /* The other values in restart are already filled in */
+ return -ERESTART_RESTARTBLOCK;
+}
+
+static long __sched nanosleep_restart_mono(struct restart_block *restart)
+{
+ return nanosleep_restart(restart, CLOCK_MONOTONIC);
+}
+
+static long __sched nanosleep_restart_real(struct restart_block *restart)
+{
+ return nanosleep_restart(restart, CLOCK_REALTIME);
+}
+
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
+ const enum hrtimer_mode mode, const clockid_t clockid)
+{
+ struct restart_block *restart;
+ struct hrtimer timer;
+ struct timespec tu;
+ ktime_t rem;
+
+ hrtimer_init(&timer, clockid);
+
+ timer.expires = timespec_to_ktime(*rqtp);
+
+ rem = schedule_hrtimer_interruptible(&timer, mode);
+ if (rem.tv64 <= 0)
+ return 0;
+
+ /* Absolute timers do not update the rmtp value: */
+ if (mode == HRTIMER_ABS)
+ return -ERESTARTNOHAND;
+
+ tu = ktime_to_timespec(rem);
+
+ if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu)))
+ return -EFAULT;
+
+ restart = &current_thread_info()->restart_block;
+ restart->fn = (clockid == CLOCK_MONOTONIC) ?
+ nanosleep_restart_mono : nanosleep_restart_real;
+ restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF;
+ restart->arg1 = timer.expires.tv64 >> 32;
+ restart->arg2 = (unsigned long) rmtp;
+
+ return -ERESTART_RESTARTBLOCK;
+}
+
+asmlinkage long
+sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
+{
+ struct timespec tu;
+
+ if (copy_from_user(&tu, rqtp, sizeof(tu)))
+ return -EFAULT;
+
+ if (!timespec_valid(&tu))
+ return -EINVAL;
+
+ return hrtimer_nanosleep(&tu, rmtp, HRTIMER_REL, CLOCK_MONOTONIC);
+}
+
+/*
+ * Functions related to boot-time initialization:
+ */
+static void __devinit init_hrtimers_cpu(int cpu)
+{
+ struct hrtimer_base *base = per_cpu(hrtimer_bases, cpu);
+ int i;
+
+ for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+ spin_lock_init(&base->lock);
+ base++;
+ }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void migrate_hrtimer_list(struct hrtimer_base *old_base,
+ struct hrtimer_base *new_base)
+{
+ struct hrtimer *timer;
+ struct rb_node *node;
+
+ while ((node = rb_first(&old_base->active))) {
+ timer = rb_entry(node, struct hrtimer, node);
+ __remove_hrtimer(timer, old_base);
+ timer->base = new_base;
+ enqueue_hrtimer(timer, new_base);
+ }
+}
+
+static void migrate_hrtimers(int cpu)
+{
+ struct hrtimer_base *old_base, *new_base;
+ int i;
+
+ BUG_ON(cpu_online(cpu));
+ old_base = per_cpu(hrtimer_bases, cpu);
+ new_base = get_cpu_var(hrtimer_bases);
+
+ local_irq_disable();
+
+ for (i = 0; i < MAX_HRTIMER_BASES; i++) {
+
+ spin_lock(&new_base->lock);
+ spin_lock(&old_base->lock);
+
+ BUG_ON(old_base->curr_timer);
+
+ migrate_hrtimer_list(old_base, new_base);
+
+ spin_unlock(&old_base->lock);
+ spin_unlock(&new_base->lock);
+ old_base++;
+ new_base++;
+ }
+
+ local_irq_enable();
+ put_cpu_var(hrtimer_bases);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ long cpu = (long)hcpu;
+
+ switch (action) {
+
+ case CPU_UP_PREPARE:
+ init_hrtimers_cpu(cpu);
+ break;
+
+#ifdef CONFIG_HOTPLUG_CPU
+ case CPU_DEAD:
+ migrate_hrtimers(cpu);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __devinitdata hrtimers_nb = {
+ .notifier_call = hrtimer_cpu_notify,
+};
+
+void __init hrtimers_init(void)
+{
+ hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
+ (void *)(long)smp_processor_id());
+ register_cpu_notifier(&hrtimers_nb);
+}
+
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 81c49a4d679e..97d5559997d2 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -366,6 +366,8 @@ int request_irq(unsigned int irq,
action->next = NULL;
action->dev_id = dev_id;
+ select_smp_affinity(irq);
+
retval = setup_irq(irq, action);
if (retval)
kfree(action);
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index f26e534c6585..d03b5eef8ce0 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -10,6 +10,8 @@
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
+#include "internals.h"
+
static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS];
#ifdef CONFIG_SMP
@@ -68,7 +70,9 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
*/
cpus_and(tmp, new_value, cpu_online_map);
if (cpus_empty(tmp))
- return -EINVAL;
+ /* Special case for empty set - allow the architecture
+ code to set default SMP affinity. */
+ return select_smp_affinity(irq) ? -EINVAL : full_count;
proc_set_irq_affinity(irq, new_value);
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 7c1b25e25e47..c2c05c4ff28d 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -12,36 +12,46 @@
#include <linux/syscalls.h>
#include <linux/time.h>
#include <linux/posix-timers.h>
+#include <linux/hrtimer.h>
#include <asm/uaccess.h>
-static unsigned long it_real_value(struct signal_struct *sig)
+/**
+ * itimer_get_remtime - get remaining time for the timer
+ *
+ * @timer: the timer to read
+ *
+ * Returns the delta between the expiry time and now, which can be
+ * less than zero or 1usec for an pending expired timer
+ */
+static struct timeval itimer_get_remtime(struct hrtimer *timer)
{
- unsigned long val = 0;
- if (timer_pending(&sig->real_timer)) {
- val = sig->real_timer.expires - jiffies;
+ ktime_t rem = hrtimer_get_remaining(timer);
- /* look out for negative/zero itimer.. */
- if ((long) val <= 0)
- val = 1;
- }
- return val;
+ /*
+ * Racy but safe: if the itimer expires after the above
+ * hrtimer_get_remtime() call but before this condition
+ * then we return 0 - which is correct.
+ */
+ if (hrtimer_active(timer)) {
+ if (rem.tv64 <= 0)
+ rem.tv64 = NSEC_PER_USEC;
+ } else
+ rem.tv64 = 0;
+
+ return ktime_to_timeval(rem);
}
int do_getitimer(int which, struct itimerval *value)
{
struct task_struct *tsk = current;
- unsigned long interval, val;
cputime_t cinterval, cval;
switch (which) {
case ITIMER_REAL:
- spin_lock_irq(&tsk->sighand->siglock);
- interval = tsk->signal->it_real_incr;
- val = it_real_value(tsk->signal);
- spin_unlock_irq(&tsk->sighand->siglock);
- jiffies_to_timeval(val, &value->it_value);
- jiffies_to_timeval(interval, &value->it_interval);
+ value->it_value = itimer_get_remtime(&tsk->signal->real_timer);
+ value->it_interval =
+ ktime_to_timeval(tsk->signal->it_real_incr);
break;
case ITIMER_VIRTUAL:
read_lock(&tasklist_lock);
@@ -113,59 +123,45 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
}
-void it_real_fn(unsigned long __data)
+/*
+ * The timer is automagically restarted, when interval != 0
+ */
+int it_real_fn(void *data)
{
- struct task_struct * p = (struct task_struct *) __data;
- unsigned long inc = p->signal->it_real_incr;
+ struct task_struct *tsk = (struct task_struct *) data;
- send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
+ send_group_sig_info(SIGALRM, SEND_SIG_PRIV, tsk);
- /*
- * Now restart the timer if necessary. We don't need any locking
- * here because do_setitimer makes sure we have finished running
- * before it touches anything.
- * Note, we KNOW we are (or should be) at a jiffie edge here so
- * we don't need the +1 stuff. Also, we want to use the prior
- * expire value so as to not "slip" a jiffie if we are late.
- * Deal with requesting a time prior to "now" here rather than
- * in add_timer.
- */
- if (!inc)
- return;
- while (time_before_eq(p->signal->real_timer.expires, jiffies))
- p->signal->real_timer.expires += inc;
- add_timer(&p->signal->real_timer);
+ if (tsk->signal->it_real_incr.tv64 != 0) {
+ hrtimer_forward(&tsk->signal->real_timer,
+ tsk->signal->it_real_incr);
+
+ return HRTIMER_RESTART;
+ }
+ return HRTIMER_NORESTART;
}
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
struct task_struct *tsk = current;
- unsigned long val, interval, expires;
+ struct hrtimer *timer;
+ ktime_t expires;
cputime_t cval, cinterval, nval, ninterval;
switch (which) {
case ITIMER_REAL:
-again:
- spin_lock_irq(&tsk->sighand->siglock);
- interval = tsk->signal->it_real_incr;
- val = it_real_value(tsk->signal);
- /* We are sharing ->siglock with it_real_fn() */
- if (try_to_del_timer_sync(&tsk->signal->real_timer) < 0) {
- spin_unlock_irq(&tsk->sighand->siglock);
- goto again;
- }
- tsk->signal->it_real_incr =
- timeval_to_jiffies(&value->it_interval);
- expires = timeval_to_jiffies(&value->it_value);
- if (expires)
- mod_timer(&tsk->signal->real_timer,
- jiffies + 1 + expires);
- spin_unlock_irq(&tsk->sighand->siglock);
+ timer = &tsk->signal->real_timer;
+ hrtimer_cancel(timer);
if (ovalue) {
- jiffies_to_timeval(val, &ovalue->it_value);
- jiffies_to_timeval(interval,
- &ovalue->it_interval);
+ ovalue->it_value = itimer_get_remtime(timer);
+ ovalue->it_interval
+ = ktime_to_timeval(tsk->signal->it_real_incr);
}
+ tsk->signal->it_real_incr =
+ timeval_to_ktime(value->it_interval);
+ expires = timeval_to_ktime(value->it_value);
+ if (expires.tv64 != 0)
+ hrtimer_start(timer, expires, HRTIMER_REL);
break;
case ITIMER_VIRTUAL:
nval = timeval_to_cputime(&value->it_value);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 2c95848fbce8..bf39d28e4c0e 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -6,6 +6,7 @@
* Version 2. See the file COPYING for more details.
*/
+#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/slab.h>
@@ -26,6 +27,9 @@
#include <asm/system.h>
#include <asm/semaphore.h>
+/* Per cpu memory for storing cpu states in case of system crash. */
+note_buf_t* crash_notes;
+
/* Location of the reserved area for the crash kernel */
struct resource crashk_res = {
.name = "Crash kernel",
@@ -1054,9 +1058,24 @@ void crash_kexec(struct pt_regs *regs)
if (!locked) {
image = xchg(&kexec_crash_image, NULL);
if (image) {
- machine_crash_shutdown(regs);
+ struct pt_regs fixed_regs;
+ crash_setup_regs(&fixed_regs, regs);
+ machine_crash_shutdown(&fixed_regs);
machine_kexec(image);
}
xchg(&kexec_lock, 0);
}
}
+
+static int __init crash_notes_memory_init(void)
+{
+ /* Allocate memory for saving cpu registers. */
+ crash_notes = alloc_percpu(note_buf_t);
+ if (!crash_notes) {
+ printk("Kexec: Memory allocation for saving cpu register"
+ " states failed\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+module_init(crash_notes_memory_init)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 3bb71e63a37e..3ea6325228da 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -48,10 +48,11 @@
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
-static DEFINE_SPINLOCK(kprobe_lock); /* Protects kprobe_table */
+DECLARE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
+#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
/*
* kprobe->ainsn.insn points to the copy of the instruction to be
* single-stepped. x86_64, POWER4 and above have no-exec support and
@@ -151,6 +152,7 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot)
}
}
}
+#endif
/* We have preemption disabled.. so it is safe to use __ versions */
static inline void set_kprobe_instance(struct kprobe *kp)
@@ -165,7 +167,7 @@ static inline void reset_kprobe_instance(void)
/*
* This routine is called either:
- * - under the kprobe_lock spinlock - during kprobe_[un]register()
+ * - under the kprobe_mutex - during kprobe_[un]register()
* OR
* - with preemption disabled - from arch/xxx/kernel/kprobes.c
*/
@@ -418,7 +420,6 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
/*
* This is the second or subsequent kprobe at the address - handle
* the intricacies
- * TODO: Move kcalloc outside the spin_lock
*/
static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
struct kprobe *p)
@@ -430,7 +431,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
copy_kprobe(old_p, p);
ret = add_new_kprobe(old_p, p);
} else {
- ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
+ ap = kzalloc(sizeof(struct kprobe), GFP_KERNEL);
if (!ap)
return -ENOMEM;
add_aggr_kprobe(ap, old_p);
@@ -440,25 +441,6 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
return ret;
}
-/* kprobe removal house-keeping routines */
-static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
-{
- arch_disarm_kprobe(p);
- hlist_del_rcu(&p->hlist);
- spin_unlock_irqrestore(&kprobe_lock, flags);
- arch_remove_kprobe(p);
-}
-
-static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
- struct kprobe *p, unsigned long flags)
-{
- list_del_rcu(&p->list);
- if (list_empty(&old_p->list))
- cleanup_kprobe(old_p, flags);
- else
- spin_unlock_irqrestore(&kprobe_lock, flags);
-}
-
static int __kprobes in_kprobes_functions(unsigned long addr)
{
if (addr >= (unsigned long)__kprobes_text_start
@@ -467,33 +449,44 @@ static int __kprobes in_kprobes_functions(unsigned long addr)
return 0;
}
-int __kprobes register_kprobe(struct kprobe *p)
+static int __kprobes __register_kprobe(struct kprobe *p,
+ unsigned long called_from)
{
int ret = 0;
- unsigned long flags = 0;
struct kprobe *old_p;
- struct module *mod;
+ struct module *probed_mod;
if ((!kernel_text_address((unsigned long) p->addr)) ||
in_kprobes_functions((unsigned long) p->addr))
return -EINVAL;
- if ((mod = module_text_address((unsigned long) p->addr)) &&
- (unlikely(!try_module_get(mod))))
- return -EINVAL;
-
- if ((ret = arch_prepare_kprobe(p)) != 0)
- goto rm_kprobe;
+ p->mod_refcounted = 0;
+ /* Check are we probing a module */
+ if ((probed_mod = module_text_address((unsigned long) p->addr))) {
+ struct module *calling_mod = module_text_address(called_from);
+ /* We must allow modules to probe themself and
+ * in this case avoid incrementing the module refcount,
+ * so as to allow unloading of self probing modules.
+ */
+ if (calling_mod && (calling_mod != probed_mod)) {
+ if (unlikely(!try_module_get(probed_mod)))
+ return -EINVAL;
+ p->mod_refcounted = 1;
+ } else
+ probed_mod = NULL;
+ }
p->nmissed = 0;
- spin_lock_irqsave(&kprobe_lock, flags);
+ down(&kprobe_mutex);
old_p = get_kprobe(p->addr);
if (old_p) {
ret = register_aggr_kprobe(old_p, p);
goto out;
}
- arch_copy_kprobe(p);
+ if ((ret = arch_prepare_kprobe(p)) != 0)
+ goto out;
+
INIT_HLIST_NODE(&p->hlist);
hlist_add_head_rcu(&p->hlist,
&kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
@@ -501,40 +494,66 @@ int __kprobes register_kprobe(struct kprobe *p)
arch_arm_kprobe(p);
out:
- spin_unlock_irqrestore(&kprobe_lock, flags);
-rm_kprobe:
- if (ret == -EEXIST)
- arch_remove_kprobe(p);
- if (ret && mod)
- module_put(mod);
+ up(&kprobe_mutex);
+
+ if (ret && probed_mod)
+ module_put(probed_mod);
return ret;
}
+int __kprobes register_kprobe(struct kprobe *p)
+{
+ return __register_kprobe(p,
+ (unsigned long)__builtin_return_address(0));
+}
+
void __kprobes unregister_kprobe(struct kprobe *p)
{
- unsigned long flags;
- struct kprobe *old_p;
struct module *mod;
+ struct kprobe *old_p, *list_p;
+ int cleanup_p;
- spin_lock_irqsave(&kprobe_lock, flags);
+ down(&kprobe_mutex);
old_p = get_kprobe(p->addr);
- if (old_p) {
- /* cleanup_*_kprobe() does the spin_unlock_irqrestore */
- if (old_p->pre_handler == aggr_pre_handler)
- cleanup_aggr_kprobe(old_p, p, flags);
- else
- cleanup_kprobe(p, flags);
+ if (unlikely(!old_p)) {
+ up(&kprobe_mutex);
+ return;
+ }
+ if (p != old_p) {
+ list_for_each_entry_rcu(list_p, &old_p->list, list)
+ if (list_p == p)
+ /* kprobe p is a valid probe */
+ goto valid_p;
+ up(&kprobe_mutex);
+ return;
+ }
+valid_p:
+ if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
+ (p->list.next == &old_p->list) &&
+ (p->list.prev == &old_p->list))) {
+ /* Only probe on the hash list */
+ arch_disarm_kprobe(p);
+ hlist_del_rcu(&old_p->hlist);
+ cleanup_p = 1;
+ } else {
+ list_del_rcu(&p->list);
+ cleanup_p = 0;
+ }
- synchronize_sched();
+ up(&kprobe_mutex);
- if ((mod = module_text_address((unsigned long)p->addr)))
- module_put(mod);
+ synchronize_sched();
+ if (p->mod_refcounted &&
+ (mod = module_text_address((unsigned long)p->addr)))
+ module_put(mod);
- if (old_p->pre_handler == aggr_pre_handler &&
- list_empty(&old_p->list))
+ if (cleanup_p) {
+ if (p != old_p) {
+ list_del_rcu(&p->list);
kfree(old_p);
- } else
- spin_unlock_irqrestore(&kprobe_lock, flags);
+ }
+ arch_remove_kprobe(p);
+ }
}
static struct notifier_block kprobe_exceptions_nb = {
@@ -548,7 +567,8 @@ int __kprobes register_jprobe(struct jprobe *jp)
jp->kp.pre_handler = setjmp_pre_handler;
jp->kp.break_handler = longjmp_break_handler;
- return register_kprobe(&jp->kp);
+ return __register_kprobe(&jp->kp,
+ (unsigned long)__builtin_return_address(0));
}
void __kprobes unregister_jprobe(struct jprobe *jp)
@@ -588,7 +608,8 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
rp->nmissed = 0;
/* Establish function entry probe point */
- if ((ret = register_kprobe(&rp->kp)) != 0)
+ if ((ret = __register_kprobe(&rp->kp,
+ (unsigned long)__builtin_return_address(0))) != 0)
free_rp_inst(rp);
return ret;
}
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 015fb69ad94d..d5eeae0fa5bc 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -15,6 +15,9 @@
#include <linux/module.h>
#include <linux/init.h>
+u64 uevent_seqnum;
+char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
+
#define KERNEL_ATTR_RO(_name) \
static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
@@ -23,21 +26,29 @@ static struct subsys_attribute _name##_attr = \
__ATTR(_name, 0644, _name##_show, _name##_store)
#ifdef CONFIG_HOTPLUG
-static ssize_t hotplug_seqnum_show(struct subsystem *subsys, char *page)
+/* current uevent sequence number */
+static ssize_t uevent_seqnum_show(struct subsystem *subsys, char *page)
{
- return sprintf(page, "%llu\n", (unsigned long long)hotplug_seqnum);
+ return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum);
}
-KERNEL_ATTR_RO(hotplug_seqnum);
-#endif
-
-#ifdef CONFIG_KEXEC
-#include <asm/kexec.h>
+KERNEL_ATTR_RO(uevent_seqnum);
-static ssize_t crash_notes_show(struct subsystem *subsys, char *page)
+/* uevent helper program, used during early boo */
+static ssize_t uevent_helper_show(struct subsystem *subsys, char *page)
{
- return sprintf(page, "%p\n", (void *)crash_notes);
+ return sprintf(page, "%s\n", uevent_helper);
}
-KERNEL_ATTR_RO(crash_notes);
+static ssize_t uevent_helper_store(struct subsystem *subsys, const char *page, size_t count)
+{
+ if (count+1 > UEVENT_HELPER_PATH_LEN)
+ return -ENOENT;
+ memcpy(uevent_helper, page, count);
+ uevent_helper[count] = '\0';
+ if (count && uevent_helper[count-1] == '\n')
+ uevent_helper[count-1] = '\0';
+ return count;
+}
+KERNEL_ATTR_RW(uevent_helper);
#endif
decl_subsys(kernel, NULL, NULL);
@@ -45,10 +56,8 @@ EXPORT_SYMBOL_GPL(kernel_subsys);
static struct attribute * kernel_attrs[] = {
#ifdef CONFIG_HOTPLUG
- &hotplug_seqnum_attr.attr,
-#endif
-#ifdef CONFIG_KEXEC
- &crash_notes_attr.attr,
+ &uevent_seqnum_attr.attr,
+ &uevent_helper_attr.attr,
#endif
NULL
};
diff --git a/kernel/module.c b/kernel/module.c
index 2ea929d51ad0..618ed6e23ecc 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -28,6 +28,7 @@
#include <linux/syscalls.h>
#include <linux/fcntl.h>
#include <linux/rcupdate.h>
+#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
@@ -496,15 +497,15 @@ static void module_unload_free(struct module *mod)
}
#ifdef CONFIG_MODULE_FORCE_UNLOAD
-static inline int try_force(unsigned int flags)
+static inline int try_force_unload(unsigned int flags)
{
int ret = (flags & O_TRUNC);
if (ret)
- add_taint(TAINT_FORCED_MODULE);
+ add_taint(TAINT_FORCED_RMMOD);
return ret;
}
#else
-static inline int try_force(unsigned int flags)
+static inline int try_force_unload(unsigned int flags)
{
return 0;
}
@@ -524,7 +525,7 @@ static int __try_stop_module(void *_sref)
/* If it's not unused, quit unless we are told to block. */
if ((sref->flags & O_NONBLOCK) && module_refcount(sref->mod) != 0) {
- if (!(*sref->forced = try_force(sref->flags)))
+ if (!(*sref->forced = try_force_unload(sref->flags)))
return -EWOULDBLOCK;
}
@@ -609,7 +610,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
/* If it has an init func, it must have an exit func to unload */
if ((mod->init != NULL && mod->exit == NULL)
|| mod->unsafe) {
- forced = try_force(flags);
+ forced = try_force_unload(flags);
if (!forced) {
/* This module can't be removed */
ret = -EBUSY;
@@ -958,7 +959,6 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
unsigned long ret;
const unsigned long *crc;
- spin_lock_irq(&modlist_lock);
ret = __find_symbol(name, &owner, &crc, mod->license_gplok);
if (ret) {
/* use_module can fail due to OOM, or module unloading */
@@ -966,7 +966,6 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
!use_module(mod, owner))
ret = 0;
}
- spin_unlock_irq(&modlist_lock);
return ret;
}
@@ -1204,6 +1203,39 @@ void *__symbol_get(const char *symbol)
}
EXPORT_SYMBOL_GPL(__symbol_get);
+/*
+ * Ensure that an exported symbol [global namespace] does not already exist
+ * in the Kernel or in some other modules exported symbol table.
+ */
+static int verify_export_symbols(struct module *mod)
+{
+ const char *name = NULL;
+ unsigned long i, ret = 0;
+ struct module *owner;
+ const unsigned long *crc;
+
+ for (i = 0; i < mod->num_syms; i++)
+ if (__find_symbol(mod->syms[i].name, &owner, &crc, 1)) {
+ name = mod->syms[i].name;
+ ret = -ENOEXEC;
+ goto dup;
+ }
+
+ for (i = 0; i < mod->num_gpl_syms; i++)
+ if (__find_symbol(mod->gpl_syms[i].name, &owner, &crc, 1)) {
+ name = mod->gpl_syms[i].name;
+ ret = -ENOEXEC;
+ goto dup;
+ }
+
+dup:
+ if (ret)
+ printk(KERN_ERR "%s: exports duplicate symbol %s (owned by %s)\n",
+ mod->name, name, module_name(owner));
+
+ return ret;
+}
+
/* Change all symbols so that sh_value encodes the pointer directly. */
static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned int symindex,
@@ -1715,6 +1747,11 @@ static struct module *load_module(void __user *umod,
/* Set up license info based on the info section */
set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
+ if (strcmp(mod->name, "ndiswrapper") == 0)
+ add_taint(TAINT_PROPRIETARY_MODULE);
+ if (strcmp(mod->name, "driverloader") == 0)
+ add_taint(TAINT_PROPRIETARY_MODULE);
+
#ifdef CONFIG_MODULE_UNLOAD
/* Set up MODINFO_ATTR fields */
setup_modinfo(mod, sechdrs, infoindex);
@@ -1767,6 +1804,12 @@ static struct module *load_module(void __user *umod,
goto cleanup;
}
+ /* Find duplicate symbols */
+ err = verify_export_symbols(mod);
+
+ if (err < 0)
+ goto cleanup;
+
/* Set up and sort exception table */
mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
@@ -1854,8 +1897,7 @@ static struct module *load_module(void __user *umod,
kfree(args);
free_hdr:
vfree(hdr);
- if (err < 0) return ERR_PTR(err);
- else return ptr;
+ return ERR_PTR(err);
truncated:
printk(KERN_ERR "Module len %lu truncated\n", len);
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c
new file mode 100644
index 000000000000..f4913c376950
--- /dev/null
+++ b/kernel/mutex-debug.c
@@ -0,0 +1,462 @@
+/*
+ * kernel/mutex-debug.c
+ *
+ * Debugging code for mutexes
+ *
+ * Started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * lock debugging, locking tree, deadlock detection started by:
+ *
+ * Copyright (C) 2004, LynuxWorks, Inc., Igor Manyilov, Bill Huey
+ * Released under the General Public License (GPL).
+ */
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+
+#include "mutex-debug.h"
+
+/*
+ * We need a global lock when we walk through the multi-process
+ * lock tree. Only used in the deadlock-debugging case.
+ */
+DEFINE_SPINLOCK(debug_mutex_lock);
+
+/*
+ * All locks held by all tasks, in a single global list:
+ */
+LIST_HEAD(debug_mutex_held_locks);
+
+/*
+ * In the debug case we carry the caller's instruction pointer into
+ * other functions, but we dont want the function argument overhead
+ * in the nondebug case - hence these macros:
+ */
+#define __IP_DECL__ , unsigned long ip
+#define __IP__ , ip
+#define __RET_IP__ , (unsigned long)__builtin_return_address(0)
+
+/*
+ * "mutex debugging enabled" flag. We turn it off when we detect
+ * the first problem because we dont want to recurse back
+ * into the tracing code when doing error printk or
+ * executing a BUG():
+ */
+int debug_mutex_on = 1;
+
+static void printk_task(struct task_struct *p)
+{
+ if (p)
+ printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
+ else
+ printk("<none>");
+}
+
+static void printk_ti(struct thread_info *ti)
+{
+ if (ti)
+ printk_task(ti->task);
+ else
+ printk("<none>");
+}
+
+static void printk_task_short(struct task_struct *p)
+{
+ if (p)
+ printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio);
+ else
+ printk("<none>");
+}
+
+static void printk_lock(struct mutex *lock, int print_owner)
+{
+ printk(" [%p] {%s}\n", lock, lock->name);
+
+ if (print_owner && lock->owner) {
+ printk(".. held by: ");
+ printk_ti(lock->owner);
+ printk("\n");
+ }
+ if (lock->owner) {
+ printk("... acquired at: ");
+ print_symbol("%s\n", lock->acquire_ip);
+ }
+}
+
+/*
+ * printk locks held by a task:
+ */
+static void show_task_locks(struct task_struct *p)
+{
+ switch (p->state) {
+ case TASK_RUNNING: printk("R"); break;
+ case TASK_INTERRUPTIBLE: printk("S"); break;
+ case TASK_UNINTERRUPTIBLE: printk("D"); break;
+ case TASK_STOPPED: printk("T"); break;
+ case EXIT_ZOMBIE: printk("Z"); break;
+ case EXIT_DEAD: printk("X"); break;
+ default: printk("?"); break;
+ }
+ printk_task(p);
+ if (p->blocked_on) {
+ struct mutex *lock = p->blocked_on->lock;
+
+ printk(" blocked on mutex:");
+ printk_lock(lock, 1);
+ } else
+ printk(" (not blocked on mutex)\n");
+}
+
+/*
+ * printk all locks held in the system (if filter == NULL),
+ * or all locks belonging to a single task (if filter != NULL):
+ */
+void show_held_locks(struct task_struct *filter)
+{
+ struct list_head *curr, *cursor = NULL;
+ struct mutex *lock;
+ struct thread_info *t;
+ unsigned long flags;
+ int count = 0;
+
+ if (filter) {
+ printk("------------------------------\n");
+ printk("| showing all locks held by: | (");
+ printk_task_short(filter);
+ printk("):\n");
+ printk("------------------------------\n");
+ } else {
+ printk("---------------------------\n");
+ printk("| showing all locks held: |\n");
+ printk("---------------------------\n");
+ }
+
+ /*
+ * Play safe and acquire the global trace lock. We
+ * cannot printk with that lock held so we iterate
+ * very carefully:
+ */
+next:
+ debug_spin_lock_save(&debug_mutex_lock, flags);
+ list_for_each(curr, &debug_mutex_held_locks) {
+ if (cursor && curr != cursor)
+ continue;
+ lock = list_entry(curr, struct mutex, held_list);
+ t = lock->owner;
+ if (filter && (t != filter->thread_info))
+ continue;
+ count++;
+ cursor = curr->next;
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+
+ printk("\n#%03d: ", count);
+ printk_lock(lock, filter ? 0 : 1);
+ goto next;
+ }
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+ printk("\n");
+}
+
+void mutex_debug_show_all_locks(void)
+{
+ struct task_struct *g, *p;
+ int count = 10;
+ int unlock = 1;
+
+ printk("\nShowing all blocking locks in the system:\n");
+
+ /*
+ * Here we try to get the tasklist_lock as hard as possible,
+ * if not successful after 2 seconds we ignore it (but keep
+ * trying). This is to enable a debug printout even if a
+ * tasklist_lock-holding task deadlocks or crashes.
+ */
+retry:
+ if (!read_trylock(&tasklist_lock)) {
+ if (count == 10)
+ printk("hm, tasklist_lock locked, retrying... ");
+ if (count) {
+ count--;
+ printk(" #%d", 10-count);
+ mdelay(200);
+ goto retry;
+ }
+ printk(" ignoring it.\n");
+ unlock = 0;
+ }
+ if (count != 10)
+ printk(" locked it.\n");
+
+ do_each_thread(g, p) {
+ show_task_locks(p);
+ if (!unlock)
+ if (read_trylock(&tasklist_lock))
+ unlock = 1;
+ } while_each_thread(g, p);
+
+ printk("\n");
+ show_held_locks(NULL);
+ printk("=============================================\n\n");
+
+ if (unlock)
+ read_unlock(&tasklist_lock);
+}
+
+static void report_deadlock(struct task_struct *task, struct mutex *lock,
+ struct mutex *lockblk, unsigned long ip)
+{
+ printk("\n%s/%d is trying to acquire this lock:\n",
+ current->comm, current->pid);
+ printk_lock(lock, 1);
+ printk("... trying at: ");
+ print_symbol("%s\n", ip);
+ show_held_locks(current);
+
+ if (lockblk) {
+ printk("but %s/%d is deadlocking current task %s/%d!\n\n",
+ task->comm, task->pid, current->comm, current->pid);
+ printk("\n%s/%d is blocked on this lock:\n",
+ task->comm, task->pid);
+ printk_lock(lockblk, 1);
+
+ show_held_locks(task);
+
+ printk("\n%s/%d's [blocked] stackdump:\n\n",
+ task->comm, task->pid);
+ show_stack(task, NULL);
+ }
+
+ printk("\n%s/%d's [current] stackdump:\n\n",
+ current->comm, current->pid);
+ dump_stack();
+ mutex_debug_show_all_locks();
+ printk("[ turning off deadlock detection. Please report this. ]\n\n");
+ local_irq_disable();
+}
+
+/*
+ * Recursively check for mutex deadlocks:
+ */
+static int check_deadlock(struct mutex *lock, int depth,
+ struct thread_info *ti, unsigned long ip)
+{
+ struct mutex *lockblk;
+ struct task_struct *task;
+
+ if (!debug_mutex_on)
+ return 0;
+
+ ti = lock->owner;
+ if (!ti)
+ return 0;
+
+ task = ti->task;
+ lockblk = NULL;
+ if (task->blocked_on)
+ lockblk = task->blocked_on->lock;
+
+ /* Self-deadlock: */
+ if (current == task) {
+ DEBUG_OFF();
+ if (depth)
+ return 1;
+ printk("\n==========================================\n");
+ printk( "[ BUG: lock recursion deadlock detected! |\n");
+ printk( "------------------------------------------\n");
+ report_deadlock(task, lock, NULL, ip);
+ return 0;
+ }
+
+ /* Ugh, something corrupted the lock data structure? */
+ if (depth > 20) {
+ DEBUG_OFF();
+ printk("\n===========================================\n");
+ printk( "[ BUG: infinite lock dependency detected!? |\n");
+ printk( "-------------------------------------------\n");
+ report_deadlock(task, lock, lockblk, ip);
+ return 0;
+ }
+
+ /* Recursively check for dependencies: */
+ if (lockblk && check_deadlock(lockblk, depth+1, ti, ip)) {
+ printk("\n============================================\n");
+ printk( "[ BUG: circular locking deadlock detected! ]\n");
+ printk( "--------------------------------------------\n");
+ report_deadlock(task, lock, lockblk, ip);
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Called when a task exits, this function checks whether the
+ * task is holding any locks, and reports the first one if so:
+ */
+void mutex_debug_check_no_locks_held(struct task_struct *task)
+{
+ struct list_head *curr, *next;
+ struct thread_info *t;
+ unsigned long flags;
+ struct mutex *lock;
+
+ if (!debug_mutex_on)
+ return;
+
+ debug_spin_lock_save(&debug_mutex_lock, flags);
+ list_for_each_safe(curr, next, &debug_mutex_held_locks) {
+ lock = list_entry(curr, struct mutex, held_list);
+ t = lock->owner;
+ if (t != task->thread_info)
+ continue;
+ list_del_init(curr);
+ DEBUG_OFF();
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+
+ printk("BUG: %s/%d, lock held at task exit time!\n",
+ task->comm, task->pid);
+ printk_lock(lock, 1);
+ if (lock->owner != task->thread_info)
+ printk("exiting task is not even the owner??\n");
+ return;
+ }
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+}
+
+/*
+ * Called when kernel memory is freed (or unmapped), or if a mutex
+ * is destroyed or reinitialized - this code checks whether there is
+ * any held lock in the memory range of <from> to <to>:
+ */
+void mutex_debug_check_no_locks_freed(const void *from, unsigned long len)
+{
+ struct list_head *curr, *next;
+ const void *to = from + len;
+ unsigned long flags;
+ struct mutex *lock;
+ void *lock_addr;
+
+ if (!debug_mutex_on)
+ return;
+
+ debug_spin_lock_save(&debug_mutex_lock, flags);
+ list_for_each_safe(curr, next, &debug_mutex_held_locks) {
+ lock = list_entry(curr, struct mutex, held_list);
+ lock_addr = lock;
+ if (lock_addr < from || lock_addr >= to)
+ continue;
+ list_del_init(curr);
+ DEBUG_OFF();
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+
+ printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n",
+ current->comm, current->pid, lock, from, to);
+ dump_stack();
+ printk_lock(lock, 1);
+ if (lock->owner != current_thread_info())
+ printk("freeing task is not even the owner??\n");
+ return;
+ }
+ debug_spin_lock_restore(&debug_mutex_lock, flags);
+}
+
+/*
+ * Must be called with lock->wait_lock held.
+ */
+void debug_mutex_set_owner(struct mutex *lock,
+ struct thread_info *new_owner __IP_DECL__)
+{
+ lock->owner = new_owner;
+ DEBUG_WARN_ON(!list_empty(&lock->held_list));
+ if (debug_mutex_on) {
+ list_add_tail(&lock->held_list, &debug_mutex_held_locks);
+ lock->acquire_ip = ip;
+ }
+}
+
+void debug_mutex_init_waiter(struct mutex_waiter *waiter)
+{
+ memset(waiter, 0x11, sizeof(*waiter));
+ waiter->magic = waiter;
+ INIT_LIST_HEAD(&waiter->list);
+}
+
+void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter)
+{
+ SMP_DEBUG_WARN_ON(!spin_is_locked(&lock->wait_lock));
+ DEBUG_WARN_ON(list_empty(&lock->wait_list));
+ DEBUG_WARN_ON(waiter->magic != waiter);
+ DEBUG_WARN_ON(list_empty(&waiter->list));
+}
+
+void debug_mutex_free_waiter(struct mutex_waiter *waiter)
+{
+ DEBUG_WARN_ON(!list_empty(&waiter->list));
+ memset(waiter, 0x22, sizeof(*waiter));
+}
+
+void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+ struct thread_info *ti __IP_DECL__)
+{
+ SMP_DEBUG_WARN_ON(!spin_is_locked(&lock->wait_lock));
+ check_deadlock(lock, 0, ti, ip);
+ /* Mark the current thread as blocked on the lock: */
+ ti->task->blocked_on = waiter;
+ waiter->lock = lock;
+}
+
+void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+ struct thread_info *ti)
+{
+ DEBUG_WARN_ON(list_empty(&waiter->list));
+ DEBUG_WARN_ON(waiter->task != ti->task);
+ DEBUG_WARN_ON(ti->task->blocked_on != waiter);
+ ti->task->blocked_on = NULL;
+
+ list_del_init(&waiter->list);
+ waiter->task = NULL;
+}
+
+void debug_mutex_unlock(struct mutex *lock)
+{
+ DEBUG_WARN_ON(lock->magic != lock);
+ DEBUG_WARN_ON(!lock->wait_list.prev && !lock->wait_list.next);
+ DEBUG_WARN_ON(lock->owner != current_thread_info());
+ if (debug_mutex_on) {
+ DEBUG_WARN_ON(list_empty(&lock->held_list));
+ list_del_init(&lock->held_list);
+ }
+}
+
+void debug_mutex_init(struct mutex *lock, const char *name)
+{
+ /*
+ * Make sure we are not reinitializing a held lock:
+ */
+ mutex_debug_check_no_locks_freed((void *)lock, sizeof(*lock));
+ lock->owner = NULL;
+ INIT_LIST_HEAD(&lock->held_list);
+ lock->name = name;
+ lock->magic = lock;
+}
+
+/***
+ * mutex_destroy - mark a mutex unusable
+ * @lock: the mutex to be destroyed
+ *
+ * This function marks the mutex uninitialized, and any subsequent
+ * use of the mutex is forbidden. The mutex must not be locked when
+ * this function is called.
+ */
+void fastcall mutex_destroy(struct mutex *lock)
+{
+ DEBUG_WARN_ON(mutex_is_locked(lock));
+ lock->magic = NULL;
+}
+
+EXPORT_SYMBOL_GPL(mutex_destroy);
diff --git a/kernel/mutex-debug.h b/kernel/mutex-debug.h
new file mode 100644
index 000000000000..fd384050acb1
--- /dev/null
+++ b/kernel/mutex-debug.h
@@ -0,0 +1,134 @@
+/*
+ * Mutexes: blocking mutual exclusion locks
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * This file contains mutex debugging related internal declarations,
+ * prototypes and inline functions, for the CONFIG_DEBUG_MUTEXES case.
+ * More details are in kernel/mutex-debug.c.
+ */
+
+extern spinlock_t debug_mutex_lock;
+extern struct list_head debug_mutex_held_locks;
+extern int debug_mutex_on;
+
+/*
+ * In the debug case we carry the caller's instruction pointer into
+ * other functions, but we dont want the function argument overhead
+ * in the nondebug case - hence these macros:
+ */
+#define __IP_DECL__ , unsigned long ip
+#define __IP__ , ip
+#define __RET_IP__ , (unsigned long)__builtin_return_address(0)
+
+/*
+ * This must be called with lock->wait_lock held.
+ */
+extern void debug_mutex_set_owner(struct mutex *lock,
+ struct thread_info *new_owner __IP_DECL__);
+
+static inline void debug_mutex_clear_owner(struct mutex *lock)
+{
+ lock->owner = NULL;
+}
+
+extern void debug_mutex_init_waiter(struct mutex_waiter *waiter);
+extern void debug_mutex_wake_waiter(struct mutex *lock,
+ struct mutex_waiter *waiter);
+extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
+extern void debug_mutex_add_waiter(struct mutex *lock,
+ struct mutex_waiter *waiter,
+ struct thread_info *ti __IP_DECL__);
+extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+ struct thread_info *ti);
+extern void debug_mutex_unlock(struct mutex *lock);
+extern void debug_mutex_init(struct mutex *lock, const char *name);
+
+#define debug_spin_lock(lock) \
+ do { \
+ local_irq_disable(); \
+ if (debug_mutex_on) \
+ spin_lock(lock); \
+ } while (0)
+
+#define debug_spin_unlock(lock) \
+ do { \
+ if (debug_mutex_on) \
+ spin_unlock(lock); \
+ local_irq_enable(); \
+ preempt_check_resched(); \
+ } while (0)
+
+#define debug_spin_lock_save(lock, flags) \
+ do { \
+ local_irq_save(flags); \
+ if (debug_mutex_on) \
+ spin_lock(lock); \
+ } while (0)
+
+#define debug_spin_lock_restore(lock, flags) \
+ do { \
+ if (debug_mutex_on) \
+ spin_unlock(lock); \
+ local_irq_restore(flags); \
+ preempt_check_resched(); \
+ } while (0)
+
+#define spin_lock_mutex(lock) \
+ do { \
+ struct mutex *l = container_of(lock, struct mutex, wait_lock); \
+ \
+ DEBUG_WARN_ON(in_interrupt()); \
+ debug_spin_lock(&debug_mutex_lock); \
+ spin_lock(lock); \
+ DEBUG_WARN_ON(l->magic != l); \
+ } while (0)
+
+#define spin_unlock_mutex(lock) \
+ do { \
+ spin_unlock(lock); \
+ debug_spin_unlock(&debug_mutex_lock); \
+ } while (0)
+
+#define DEBUG_OFF() \
+do { \
+ if (debug_mutex_on) { \
+ debug_mutex_on = 0; \
+ console_verbose(); \
+ if (spin_is_locked(&debug_mutex_lock)) \
+ spin_unlock(&debug_mutex_lock); \
+ } \
+} while (0)
+
+#define DEBUG_BUG() \
+do { \
+ if (debug_mutex_on) { \
+ DEBUG_OFF(); \
+ BUG(); \
+ } \
+} while (0)
+
+#define DEBUG_WARN_ON(c) \
+do { \
+ if (unlikely(c && debug_mutex_on)) { \
+ DEBUG_OFF(); \
+ WARN_ON(1); \
+ } \
+} while (0)
+
+# define DEBUG_BUG_ON(c) \
+do { \
+ if (unlikely(c)) \
+ DEBUG_BUG(); \
+} while (0)
+
+#ifdef CONFIG_SMP
+# define SMP_DEBUG_WARN_ON(c) DEBUG_WARN_ON(c)
+# define SMP_DEBUG_BUG_ON(c) DEBUG_BUG_ON(c)
+#else
+# define SMP_DEBUG_WARN_ON(c) do { } while (0)
+# define SMP_DEBUG_BUG_ON(c) do { } while (0)
+#endif
+
diff --git a/kernel/mutex.c b/kernel/mutex.c
new file mode 100644
index 000000000000..5449b210d9ed
--- /dev/null
+++ b/kernel/mutex.c
@@ -0,0 +1,315 @@
+/*
+ * kernel/mutex.c
+ *
+ * Mutexes: blocking mutual exclusion locks
+ *
+ * Started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * Many thanks to Arjan van de Ven, Thomas Gleixner, Steven Rostedt and
+ * David Howells for suggestions and improvements.
+ *
+ * Also see Documentation/mutex-design.txt.
+ */
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+/*
+ * In the DEBUG case we are using the "NULL fastpath" for mutexes,
+ * which forces all calls into the slowpath:
+ */
+#ifdef CONFIG_DEBUG_MUTEXES
+# include "mutex-debug.h"
+# include <asm-generic/mutex-null.h>
+#else
+# include "mutex.h"
+# include <asm/mutex.h>
+#endif
+
+/***
+ * mutex_init - initialize the mutex
+ * @lock: the mutex to be initialized
+ *
+ * Initialize the mutex to unlocked state.
+ *
+ * It is not allowed to initialize an already locked mutex.
+ */
+void fastcall __mutex_init(struct mutex *lock, const char *name)
+{
+ atomic_set(&lock->count, 1);
+ spin_lock_init(&lock->wait_lock);
+ INIT_LIST_HEAD(&lock->wait_list);
+
+ debug_mutex_init(lock, name);
+}
+
+EXPORT_SYMBOL(__mutex_init);
+
+/*
+ * We split the mutex lock/unlock logic into separate fastpath and
+ * slowpath functions, to reduce the register pressure on the fastpath.
+ * We also put the fastpath first in the kernel image, to make sure the
+ * branch is predicted by the CPU as default-untaken.
+ */
+static void fastcall noinline __sched
+__mutex_lock_slowpath(atomic_t *lock_count __IP_DECL__);
+
+/***
+ * mutex_lock - acquire the mutex
+ * @lock: the mutex to be acquired
+ *
+ * Lock the mutex exclusively for this task. If the mutex is not
+ * available right now, it will sleep until it can get it.
+ *
+ * The mutex must later on be released by the same task that
+ * acquired it. Recursive locking is not allowed. The task
+ * may not exit without first unlocking the mutex. Also, kernel
+ * memory where the mutex resides mutex must not be freed with
+ * the mutex still locked. The mutex must first be initialized
+ * (or statically defined) before it can be locked. memset()-ing
+ * the mutex to 0 is not allowed.
+ *
+ * ( The CONFIG_DEBUG_MUTEXES .config option turns on debugging
+ * checks that will enforce the restrictions and will also do
+ * deadlock debugging. )
+ *
+ * This function is similar to (but not equivalent to) down().
+ */
+void fastcall __sched mutex_lock(struct mutex *lock)
+{
+ might_sleep();
+ /*
+ * The locking fastpath is the 1->0 transition from
+ * 'unlocked' into 'locked' state.
+ */
+ __mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
+}
+
+EXPORT_SYMBOL(mutex_lock);
+
+static void fastcall noinline __sched
+__mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__);
+
+/***
+ * mutex_unlock - release the mutex
+ * @lock: the mutex to be released
+ *
+ * Unlock a mutex that has been locked by this task previously.
+ *
+ * This function must not be used in interrupt context. Unlocking
+ * of a not locked mutex is not allowed.
+ *
+ * This function is similar to (but not equivalent to) up().
+ */
+void fastcall __sched mutex_unlock(struct mutex *lock)
+{
+ /*
+ * The unlocking fastpath is the 0->1 transition from 'locked'
+ * into 'unlocked' state:
+ */
+ __mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
+}
+
+EXPORT_SYMBOL(mutex_unlock);
+
+/*
+ * Lock a mutex (possibly interruptible), slowpath:
+ */
+static inline int __sched
+__mutex_lock_common(struct mutex *lock, long state __IP_DECL__)
+{
+ struct task_struct *task = current;
+ struct mutex_waiter waiter;
+ unsigned int old_val;
+
+ debug_mutex_init_waiter(&waiter);
+
+ spin_lock_mutex(&lock->wait_lock);
+
+ debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip);
+
+ /* add waiting tasks to the end of the waitqueue (FIFO): */
+ list_add_tail(&waiter.list, &lock->wait_list);
+ waiter.task = task;
+
+ for (;;) {
+ /*
+ * Lets try to take the lock again - this is needed even if
+ * we get here for the first time (shortly after failing to
+ * acquire the lock), to make sure that we get a wakeup once
+ * it's unlocked. Later on, if we sleep, this is the
+ * operation that gives us the lock. We xchg it to -1, so
+ * that when we release the lock, we properly wake up the
+ * other waiters:
+ */
+ old_val = atomic_xchg(&lock->count, -1);
+ if (old_val == 1)
+ break;
+
+ /*
+ * got a signal? (This code gets eliminated in the
+ * TASK_UNINTERRUPTIBLE case.)
+ */
+ if (unlikely(state == TASK_INTERRUPTIBLE &&
+ signal_pending(task))) {
+ mutex_remove_waiter(lock, &waiter, task->thread_info);
+ spin_unlock_mutex(&lock->wait_lock);
+
+ debug_mutex_free_waiter(&waiter);
+ return -EINTR;
+ }
+ __set_task_state(task, state);
+
+ /* didnt get the lock, go to sleep: */
+ spin_unlock_mutex(&lock->wait_lock);
+ schedule();
+ spin_lock_mutex(&lock->wait_lock);
+ }
+
+ /* got the lock - rejoice! */
+ mutex_remove_waiter(lock, &waiter, task->thread_info);
+ debug_mutex_set_owner(lock, task->thread_info __IP__);
+
+ /* set it to 0 if there are no waiters left: */
+ if (likely(list_empty(&lock->wait_list)))
+ atomic_set(&lock->count, 0);
+
+ spin_unlock_mutex(&lock->wait_lock);
+
+ debug_mutex_free_waiter(&waiter);
+
+ DEBUG_WARN_ON(list_empty(&lock->held_list));
+ DEBUG_WARN_ON(lock->owner != task->thread_info);
+
+ return 0;
+}
+
+static void fastcall noinline __sched
+__mutex_lock_slowpath(atomic_t *lock_count __IP_DECL__)
+{
+ struct mutex *lock = container_of(lock_count, struct mutex, count);
+
+ __mutex_lock_common(lock, TASK_UNINTERRUPTIBLE __IP__);
+}
+
+/*
+ * Release the lock, slowpath:
+ */
+static fastcall noinline void
+__mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__)
+{
+ struct mutex *lock = container_of(lock_count, struct mutex, count);
+
+ DEBUG_WARN_ON(lock->owner != current_thread_info());
+
+ spin_lock_mutex(&lock->wait_lock);
+
+ /*
+ * some architectures leave the lock unlocked in the fastpath failure
+ * case, others need to leave it locked. In the later case we have to
+ * unlock it here
+ */
+ if (__mutex_slowpath_needs_to_unlock())
+ atomic_set(&lock->count, 1);
+
+ debug_mutex_unlock(lock);
+
+ if (!list_empty(&lock->wait_list)) {
+ /* get the first entry from the wait-list: */
+ struct mutex_waiter *waiter =
+ list_entry(lock->wait_list.next,
+ struct mutex_waiter, list);
+
+ debug_mutex_wake_waiter(lock, waiter);
+
+ wake_up_process(waiter->task);
+ }
+
+ debug_mutex_clear_owner(lock);
+
+ spin_unlock_mutex(&lock->wait_lock);
+}
+
+/*
+ * Here come the less common (and hence less performance-critical) APIs:
+ * mutex_lock_interruptible() and mutex_trylock().
+ */
+static int fastcall noinline __sched
+__mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__);
+
+/***
+ * mutex_lock_interruptible - acquire the mutex, interruptable
+ * @lock: the mutex to be acquired
+ *
+ * Lock the mutex like mutex_lock(), and return 0 if the mutex has
+ * been acquired or sleep until the mutex becomes available. If a
+ * signal arrives while waiting for the lock then this function
+ * returns -EINTR.
+ *
+ * This function is similar to (but not equivalent to) down_interruptible().
+ */
+int fastcall __sched mutex_lock_interruptible(struct mutex *lock)
+{
+ might_sleep();
+ return __mutex_fastpath_lock_retval
+ (&lock->count, __mutex_lock_interruptible_slowpath);
+}
+
+EXPORT_SYMBOL(mutex_lock_interruptible);
+
+static int fastcall noinline __sched
+__mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__)
+{
+ struct mutex *lock = container_of(lock_count, struct mutex, count);
+
+ return __mutex_lock_common(lock, TASK_INTERRUPTIBLE __IP__);
+}
+
+/*
+ * Spinlock based trylock, we take the spinlock and check whether we
+ * can get the lock:
+ */
+static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
+{
+ struct mutex *lock = container_of(lock_count, struct mutex, count);
+ int prev;
+
+ spin_lock_mutex(&lock->wait_lock);
+
+ prev = atomic_xchg(&lock->count, -1);
+ if (likely(prev == 1))
+ debug_mutex_set_owner(lock, current_thread_info() __RET_IP__);
+ /* Set it back to 0 if there are no waiters: */
+ if (likely(list_empty(&lock->wait_list)))
+ atomic_set(&lock->count, 0);
+
+ spin_unlock_mutex(&lock->wait_lock);
+
+ return prev == 1;
+}
+
+/***
+ * mutex_trylock - try acquire the mutex, without waiting
+ * @lock: the mutex to be acquired
+ *
+ * Try to acquire the mutex atomically. Returns 1 if the mutex
+ * has been acquired successfully, and 0 on contention.
+ *
+ * NOTE: this function follows the spin_trylock() convention, so
+ * it is negated to the down_trylock() return values! Be careful
+ * about this when converting semaphore users to mutexes.
+ *
+ * This function must not be used in interrupt context. The
+ * mutex must be released by the same task that acquired it.
+ */
+int fastcall mutex_trylock(struct mutex *lock)
+{
+ return __mutex_fastpath_trylock(&lock->count,
+ __mutex_trylock_slowpath);
+}
+
+EXPORT_SYMBOL(mutex_trylock);
diff --git a/kernel/mutex.h b/kernel/mutex.h
new file mode 100644
index 000000000000..00fe84e7b672
--- /dev/null
+++ b/kernel/mutex.h
@@ -0,0 +1,35 @@
+/*
+ * Mutexes: blocking mutual exclusion locks
+ *
+ * started by Ingo Molnar:
+ *
+ * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * This file contains mutex debugging related internal prototypes, for the
+ * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
+ */
+
+#define spin_lock_mutex(lock) spin_lock(lock)
+#define spin_unlock_mutex(lock) spin_unlock(lock)
+#define mutex_remove_waiter(lock, waiter, ti) \
+ __list_del((waiter)->list.prev, (waiter)->list.next)
+
+#define DEBUG_WARN_ON(c) do { } while (0)
+#define debug_mutex_set_owner(lock, new_owner) do { } while (0)
+#define debug_mutex_clear_owner(lock) do { } while (0)
+#define debug_mutex_init_waiter(waiter) do { } while (0)
+#define debug_mutex_wake_waiter(lock, waiter) do { } while (0)
+#define debug_mutex_free_waiter(waiter) do { } while (0)
+#define debug_mutex_add_waiter(lock, waiter, ti, ip) do { } while (0)
+#define debug_mutex_unlock(lock) do { } while (0)
+#define debug_mutex_init(lock, name) do { } while (0)
+
+/*
+ * Return-address parameters/declarations. They are very useful for
+ * debugging, but add overhead in the !DEBUG case - so we go the
+ * trouble of using this not too elegant but zero-cost solution:
+ */
+#define __IP_DECL__
+#define __IP__
+#define __RET_IP__
+
diff --git a/kernel/panic.c b/kernel/panic.c
index aabc5f86fa3f..c5c4ab255834 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -60,7 +60,7 @@ NORET_TYPE void panic(const char * fmt, ...)
long i;
static char buf[1024];
va_list args;
-#if defined(CONFIG_ARCH_S390)
+#if defined(CONFIG_S390)
unsigned long caller = (unsigned long) __builtin_return_address(0);
#endif
@@ -125,7 +125,7 @@ NORET_TYPE void panic(const char * fmt, ...)
printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n");
}
#endif
-#if defined(CONFIG_ARCH_S390)
+#if defined(CONFIG_S390)
disabled_wait(caller);
#endif
local_irq_enable();
diff --git a/kernel/pid.c b/kernel/pid.c
index edba31c681ac..1acc07246991 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -136,7 +136,7 @@ struct pid * fastcall find_pid(enum pid_type type, int nr)
struct hlist_node *elem;
struct pid *pid;
- hlist_for_each_entry(pid, elem,
+ hlist_for_each_entry_rcu(pid, elem,
&pid_hash[type][pid_hashfn(nr)], pid_chain) {
if (pid->nr == nr)
return pid;
@@ -150,15 +150,15 @@ int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
task_pid = &task->pids[type];
pid = find_pid(type, nr);
+ task_pid->nr = nr;
if (pid == NULL) {
- hlist_add_head(&task_pid->pid_chain,
- &pid_hash[type][pid_hashfn(nr)]);
INIT_LIST_HEAD(&task_pid->pid_list);
+ hlist_add_head_rcu(&task_pid->pid_chain,
+ &pid_hash[type][pid_hashfn(nr)]);
} else {
INIT_HLIST_NODE(&task_pid->pid_chain);
- list_add_tail(&task_pid->pid_list, &pid->pid_list);
+ list_add_tail_rcu(&task_pid->pid_list, &pid->pid_list);
}
- task_pid->nr = nr;
return 0;
}
@@ -170,20 +170,20 @@ static fastcall int __detach_pid(task_t *task, enum pid_type type)
pid = &task->pids[type];
if (!hlist_unhashed(&pid->pid_chain)) {
- hlist_del(&pid->pid_chain);
- if (list_empty(&pid->pid_list))
+ if (list_empty(&pid->pid_list)) {
nr = pid->nr;
- else {
+ hlist_del_rcu(&pid->pid_chain);
+ } else {
pid_next = list_entry(pid->pid_list.next,
struct pid, pid_list);
/* insert next pid from pid_list to hash */
- hlist_add_head(&pid_next->pid_chain,
- &pid_hash[type][pid_hashfn(pid_next->nr)]);
+ hlist_replace_rcu(&pid->pid_chain,
+ &pid_next->pid_chain);
}
}
- list_del(&pid->pid_list);
+ list_del_rcu(&pid->pid_list);
pid->nr = 0;
return nr;
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index cae4f5728997..520f6c59948d 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -7,7 +7,7 @@
#include <asm/uaccess.h>
#include <linux/errno.h>
-static int check_clock(clockid_t which_clock)
+static int check_clock(const clockid_t which_clock)
{
int error = 0;
struct task_struct *p;
@@ -31,7 +31,7 @@ static int check_clock(clockid_t which_clock)
}
static inline union cpu_time_count
-timespec_to_sample(clockid_t which_clock, const struct timespec *tp)
+timespec_to_sample(const clockid_t which_clock, const struct timespec *tp)
{
union cpu_time_count ret;
ret.sched = 0; /* high half always zero when .cpu used */
@@ -43,7 +43,7 @@ timespec_to_sample(clockid_t which_clock, const struct timespec *tp)
return ret;
}
-static void sample_to_timespec(clockid_t which_clock,
+static void sample_to_timespec(const clockid_t which_clock,
union cpu_time_count cpu,
struct timespec *tp)
{
@@ -55,7 +55,7 @@ static void sample_to_timespec(clockid_t which_clock,
}
}
-static inline int cpu_time_before(clockid_t which_clock,
+static inline int cpu_time_before(const clockid_t which_clock,
union cpu_time_count now,
union cpu_time_count then)
{
@@ -65,7 +65,7 @@ static inline int cpu_time_before(clockid_t which_clock,
return cputime_lt(now.cpu, then.cpu);
}
}
-static inline void cpu_time_add(clockid_t which_clock,
+static inline void cpu_time_add(const clockid_t which_clock,
union cpu_time_count *acc,
union cpu_time_count val)
{
@@ -75,7 +75,7 @@ static inline void cpu_time_add(clockid_t which_clock,
acc->cpu = cputime_add(acc->cpu, val.cpu);
}
}
-static inline union cpu_time_count cpu_time_sub(clockid_t which_clock,
+static inline union cpu_time_count cpu_time_sub(const clockid_t which_clock,
union cpu_time_count a,
union cpu_time_count b)
{
@@ -151,7 +151,7 @@ static inline unsigned long long sched_ns(struct task_struct *p)
return (p == current) ? current_sched_time(p) : p->sched_time;
}
-int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
{
int error = check_clock(which_clock);
if (!error) {
@@ -169,7 +169,7 @@ int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
return error;
}
-int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp)
+int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
{
/*
* You can never reset a CPU clock, but we check for other errors
@@ -186,7 +186,7 @@ int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp)
/*
* Sample a per-thread clock for the given task.
*/
-static int cpu_clock_sample(clockid_t which_clock, struct task_struct *p,
+static int cpu_clock_sample(const clockid_t which_clock, struct task_struct *p,
union cpu_time_count *cpu)
{
switch (CPUCLOCK_WHICH(which_clock)) {
@@ -238,18 +238,7 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx,
while ((t = next_thread(t)) != p) {
cpu->sched += t->sched_time;
}
- if (p->tgid == current->tgid) {
- /*
- * We're sampling ourselves, so include the
- * cycles not yet banked. We still omit
- * other threads running on other CPUs,
- * so the total can always be behind as
- * much as max(nthreads-1,ncpus) * (NSEC_PER_SEC/HZ).
- */
- cpu->sched += current_sched_time(current);
- } else {
- cpu->sched += p->sched_time;
- }
+ cpu->sched += sched_ns(p);
break;
}
return 0;
@@ -259,7 +248,7 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx,
* Sample a process (thread group) clock for the given group_leader task.
* Must be called with tasklist_lock held for reading.
*/
-static int cpu_clock_sample_group(clockid_t which_clock,
+static int cpu_clock_sample_group(const clockid_t which_clock,
struct task_struct *p,
union cpu_time_count *cpu)
{
@@ -273,7 +262,7 @@ static int cpu_clock_sample_group(clockid_t which_clock,
}
-int posix_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
{
const pid_t pid = CPUCLOCK_PID(which_clock);
int error = -EINVAL;
@@ -1410,8 +1399,8 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
-int posix_cpu_nsleep(clockid_t which_clock, int flags,
- struct timespec *rqtp)
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+ struct timespec *rqtp, struct timespec __user *rmtp)
{
struct restart_block *restart_block =
&current_thread_info()->restart_block;
@@ -1436,7 +1425,6 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags,
error = posix_cpu_timer_create(&timer);
timer.it_process = current;
if (!error) {
- struct timespec __user *rmtp;
static struct itimerspec zero_it;
struct itimerspec it = { .it_value = *rqtp,
.it_interval = {} };
@@ -1483,7 +1471,6 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags,
/*
* Report back to the user the time still remaining.
*/
- rmtp = (struct timespec __user *) restart_block->arg1;
if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
return -EFAULT;
@@ -1491,6 +1478,7 @@ int posix_cpu_nsleep(clockid_t which_clock, int flags,
restart_block->fn = posix_cpu_clock_nanosleep_restart;
/* Caller already set restart_block->arg1 */
restart_block->arg0 = which_clock;
+ restart_block->arg1 = (unsigned long) rmtp;
restart_block->arg2 = rqtp->tv_sec;
restart_block->arg3 = rqtp->tv_nsec;
@@ -1504,21 +1492,28 @@ static long
posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
{
clockid_t which_clock = restart_block->arg0;
- struct timespec t = { .tv_sec = restart_block->arg2,
- .tv_nsec = restart_block->arg3 };
+ struct timespec __user *rmtp;
+ struct timespec t;
+
+ rmtp = (struct timespec __user *) restart_block->arg1;
+ t.tv_sec = restart_block->arg2;
+ t.tv_nsec = restart_block->arg3;
+
restart_block->fn = do_no_restart_syscall;
- return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+ return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
}
#define PROCESS_CLOCK MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
#define THREAD_CLOCK MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
-static int process_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+static int process_cpu_clock_getres(const clockid_t which_clock,
+ struct timespec *tp)
{
return posix_cpu_clock_getres(PROCESS_CLOCK, tp);
}
-static int process_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+static int process_cpu_clock_get(const clockid_t which_clock,
+ struct timespec *tp)
{
return posix_cpu_clock_get(PROCESS_CLOCK, tp);
}
@@ -1527,16 +1522,19 @@ static int process_cpu_timer_create(struct k_itimer *timer)
timer->it_clock = PROCESS_CLOCK;
return posix_cpu_timer_create(timer);
}
-static int process_cpu_nsleep(clockid_t which_clock, int flags,
- struct timespec *rqtp)
+static int process_cpu_nsleep(const clockid_t which_clock, int flags,
+ struct timespec *rqtp,
+ struct timespec __user *rmtp)
{
- return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+ return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp, rmtp);
}
-static int thread_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+static int thread_cpu_clock_getres(const clockid_t which_clock,
+ struct timespec *tp)
{
return posix_cpu_clock_getres(THREAD_CLOCK, tp);
}
-static int thread_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+static int thread_cpu_clock_get(const clockid_t which_clock,
+ struct timespec *tp)
{
return posix_cpu_clock_get(THREAD_CLOCK, tp);
}
@@ -1545,8 +1543,8 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
timer->it_clock = THREAD_CLOCK;
return posix_cpu_timer_create(timer);
}
-static int thread_cpu_nsleep(clockid_t which_clock, int flags,
- struct timespec *rqtp)
+static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
+ struct timespec *rqtp, struct timespec __user *rmtp)
{
return -EINVAL;
}
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 5870efb3e200..197208b3aa2a 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -48,21 +48,6 @@
#include <linux/workqueue.h>
#include <linux/module.h>
-#ifndef div_long_long_rem
-#include <asm/div64.h>
-
-#define div_long_long_rem(dividend,divisor,remainder) ({ \
- u64 result = dividend; \
- *remainder = do_div(result,divisor); \
- result; })
-
-#endif
-#define CLOCK_REALTIME_RES TICK_NSEC /* In nano seconds. */
-
-static inline u64 mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2)
-{
- return (u64)mpy1 * mpy2;
-}
/*
* Management arrays for POSIX timers. Timers are kept in slab memory
* Timer ids are allocated by an external routine that keeps track of the
@@ -148,18 +133,18 @@ static DEFINE_SPINLOCK(idr_lock);
*/
static struct k_clock posix_clocks[MAX_CLOCKS];
+
/*
- * We only have one real clock that can be set so we need only one abs list,
- * even if we should want to have several clocks with differing resolutions.
+ * These ones are defined below.
*/
-static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
- .lock = SPIN_LOCK_UNLOCKED};
+static int common_nsleep(const clockid_t, int flags, struct timespec *t,
+ struct timespec __user *rmtp);
+static void common_timer_get(struct k_itimer *, struct itimerspec *);
+static int common_timer_set(struct k_itimer *, int,
+ struct itimerspec *, struct itimerspec *);
+static int common_timer_del(struct k_itimer *timer);
-static void posix_timer_fn(unsigned long);
-static u64 do_posix_clock_monotonic_gettime_parts(
- struct timespec *tp, struct timespec *mo);
-int do_posix_clock_monotonic_gettime(struct timespec *tp);
-static int do_posix_clock_monotonic_get(clockid_t, struct timespec *tp);
+static int posix_timer_fn(void *data);
static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
@@ -184,7 +169,7 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
* the function pointer CALL in struct k_clock.
*/
-static inline int common_clock_getres(clockid_t which_clock,
+static inline int common_clock_getres(const clockid_t which_clock,
struct timespec *tp)
{
tp->tv_sec = 0;
@@ -192,39 +177,33 @@ static inline int common_clock_getres(clockid_t which_clock,
return 0;
}
-static inline int common_clock_get(clockid_t which_clock, struct timespec *tp)
+/*
+ * Get real time for posix timers
+ */
+static int common_clock_get(clockid_t which_clock, struct timespec *tp)
{
- getnstimeofday(tp);
+ ktime_get_real_ts(tp);
return 0;
}
-static inline int common_clock_set(clockid_t which_clock, struct timespec *tp)
+static inline int common_clock_set(const clockid_t which_clock,
+ struct timespec *tp)
{
return do_sys_settimeofday(tp, NULL);
}
-static inline int common_timer_create(struct k_itimer *new_timer)
+static int common_timer_create(struct k_itimer *new_timer)
{
- INIT_LIST_HEAD(&new_timer->it.real.abs_timer_entry);
- init_timer(&new_timer->it.real.timer);
- new_timer->it.real.timer.data = (unsigned long) new_timer;
+ hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock);
+ new_timer->it.real.timer.data = new_timer;
new_timer->it.real.timer.function = posix_timer_fn;
return 0;
}
/*
- * These ones are defined below.
- */
-static int common_nsleep(clockid_t, int flags, struct timespec *t);
-static void common_timer_get(struct k_itimer *, struct itimerspec *);
-static int common_timer_set(struct k_itimer *, int,
- struct itimerspec *, struct itimerspec *);
-static int common_timer_del(struct k_itimer *timer);
-
-/*
- * Return nonzero iff we know a priori this clockid_t value is bogus.
+ * Return nonzero if we know a priori this clockid_t value is bogus.
*/
-static inline int invalid_clockid(clockid_t which_clock)
+static inline int invalid_clockid(const clockid_t which_clock)
{
if (which_clock < 0) /* CPU clock, posix_cpu_* will check it */
return 0;
@@ -232,26 +211,32 @@ static inline int invalid_clockid(clockid_t which_clock)
return 1;
if (posix_clocks[which_clock].clock_getres != NULL)
return 0;
-#ifndef CLOCK_DISPATCH_DIRECT
if (posix_clocks[which_clock].res != 0)
return 0;
-#endif
return 1;
}
+/*
+ * Get monotonic time for posix timers
+ */
+static int posix_ktime_get_ts(clockid_t which_clock, struct timespec *tp)
+{
+ ktime_get_ts(tp);
+ return 0;
+}
/*
* Initialize everything, well, just everything in Posix clocks/timers ;)
*/
static __init int init_posix_timers(void)
{
- struct k_clock clock_realtime = {.res = CLOCK_REALTIME_RES,
- .abs_struct = &abs_list
+ struct k_clock clock_realtime = {
+ .clock_getres = hrtimer_get_res,
};
- struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
- .abs_struct = NULL,
- .clock_get = do_posix_clock_monotonic_get,
- .clock_set = do_posix_clock_nosettime
+ struct k_clock clock_monotonic = {
+ .clock_getres = hrtimer_get_res,
+ .clock_get = posix_ktime_get_ts,
+ .clock_set = do_posix_clock_nosettime,
};
register_posix_clock(CLOCK_REALTIME, &clock_realtime);
@@ -265,117 +250,17 @@ static __init int init_posix_timers(void)
__initcall(init_posix_timers);
-static void tstojiffie(struct timespec *tp, int res, u64 *jiff)
-{
- long sec = tp->tv_sec;
- long nsec = tp->tv_nsec + res - 1;
-
- if (nsec >= NSEC_PER_SEC) {
- sec++;
- nsec -= NSEC_PER_SEC;
- }
-
- /*
- * The scaling constants are defined in <linux/time.h>
- * The difference between there and here is that we do the
- * res rounding and compute a 64-bit result (well so does that
- * but it then throws away the high bits).
- */
- *jiff = (mpy_l_X_l_ll(sec, SEC_CONVERSION) +
- (mpy_l_X_l_ll(nsec, NSEC_CONVERSION) >>
- (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
-}
-
-/*
- * This function adjusts the timer as needed as a result of the clock
- * being set. It should only be called for absolute timers, and then
- * under the abs_list lock. It computes the time difference and sets
- * the new jiffies value in the timer. It also updates the timers
- * reference wall_to_monotonic value. It is complicated by the fact
- * that tstojiffies() only handles positive times and it needs to work
- * with both positive and negative times. Also, for negative offsets,
- * we need to defeat the res round up.
- *
- * Return is true if there is a new time, else false.
- */
-static long add_clockset_delta(struct k_itimer *timr,
- struct timespec *new_wall_to)
-{
- struct timespec delta;
- int sign = 0;
- u64 exp;
-
- set_normalized_timespec(&delta,
- new_wall_to->tv_sec -
- timr->it.real.wall_to_prev.tv_sec,
- new_wall_to->tv_nsec -
- timr->it.real.wall_to_prev.tv_nsec);
- if (likely(!(delta.tv_sec | delta.tv_nsec)))
- return 0;
- if (delta.tv_sec < 0) {
- set_normalized_timespec(&delta,
- -delta.tv_sec,
- 1 - delta.tv_nsec -
- posix_clocks[timr->it_clock].res);
- sign++;
- }
- tstojiffie(&delta, posix_clocks[timr->it_clock].res, &exp);
- timr->it.real.wall_to_prev = *new_wall_to;
- timr->it.real.timer.expires += (sign ? -exp : exp);
- return 1;
-}
-
-static void remove_from_abslist(struct k_itimer *timr)
-{
- if (!list_empty(&timr->it.real.abs_timer_entry)) {
- spin_lock(&abs_list.lock);
- list_del_init(&timr->it.real.abs_timer_entry);
- spin_unlock(&abs_list.lock);
- }
-}
-
static void schedule_next_timer(struct k_itimer *timr)
{
- struct timespec new_wall_to;
- struct now_struct now;
- unsigned long seq;
-
- /*
- * Set up the timer for the next interval (if there is one).
- * Note: this code uses the abs_timer_lock to protect
- * it.real.wall_to_prev and must hold it until exp is set, not exactly
- * obvious...
-
- * This function is used for CLOCK_REALTIME* and
- * CLOCK_MONOTONIC* timers. If we ever want to handle other
- * CLOCKs, the calling code (do_schedule_next_timer) would need
- * to pull the "clock" info from the timer and dispatch the
- * "other" CLOCKs "next timer" code (which, I suppose should
- * also be added to the k_clock structure).
- */
- if (!timr->it.real.incr)
+ if (timr->it.real.interval.tv64 == 0)
return;
- do {
- seq = read_seqbegin(&xtime_lock);
- new_wall_to = wall_to_monotonic;
- posix_get_now(&now);
- } while (read_seqretry(&xtime_lock, seq));
-
- if (!list_empty(&timr->it.real.abs_timer_entry)) {
- spin_lock(&abs_list.lock);
- add_clockset_delta(timr, &new_wall_to);
-
- posix_bump_timer(timr, now);
-
- spin_unlock(&abs_list.lock);
- } else {
- posix_bump_timer(timr, now);
- }
+ timr->it_overrun += hrtimer_forward(&timr->it.real.timer,
+ timr->it.real.interval);
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1;
++timr->it_requeue_pending;
- add_timer(&timr->it.real.timer);
+ hrtimer_restart(&timr->it.real.timer);
}
/*
@@ -396,31 +281,23 @@ void do_schedule_next_timer(struct siginfo *info)
timr = lock_timer(info->si_tid, &flags);
- if (!timr || timr->it_requeue_pending != info->si_sys_private)
- goto exit;
+ if (timr && timr->it_requeue_pending == info->si_sys_private) {
+ if (timr->it_clock < 0)
+ posix_cpu_timer_schedule(timr);
+ else
+ schedule_next_timer(timr);
- if (timr->it_clock < 0) /* CPU clock */
- posix_cpu_timer_schedule(timr);
- else
- schedule_next_timer(timr);
- info->si_overrun = timr->it_overrun_last;
-exit:
- if (timr)
- unlock_timer(timr, flags);
+ info->si_overrun = timr->it_overrun_last;
+ }
+
+ unlock_timer(timr, flags);
}
int posix_timer_event(struct k_itimer *timr,int si_private)
{
memset(&timr->sigq->info, 0, sizeof(siginfo_t));
timr->sigq->info.si_sys_private = si_private;
- /*
- * Send signal to the process that owns this timer.
-
- * This code assumes that all the possible abs_lists share the
- * same lock (there is only one list at this time). If this is
- * not the case, the CLOCK info would need to be used to find
- * the proper abs list lock.
- */
+ /* Send signal to the process that owns this timer.*/
timr->sigq->info.si_signo = timr->it_sigev_signo;
timr->sigq->info.si_errno = 0;
@@ -454,66 +331,37 @@ EXPORT_SYMBOL_GPL(posix_timer_event);
* This code is for CLOCK_REALTIME* and CLOCK_MONOTONIC* timers.
*/
-static void posix_timer_fn(unsigned long __data)
+static int posix_timer_fn(void *data)
{
- struct k_itimer *timr = (struct k_itimer *) __data;
+ struct k_itimer *timr = data;
unsigned long flags;
- unsigned long seq;
- struct timespec delta, new_wall_to;
- u64 exp = 0;
- int do_notify = 1;
+ int si_private = 0;
+ int ret = HRTIMER_NORESTART;
spin_lock_irqsave(&timr->it_lock, flags);
- if (!list_empty(&timr->it.real.abs_timer_entry)) {
- spin_lock(&abs_list.lock);
- do {
- seq = read_seqbegin(&xtime_lock);
- new_wall_to = wall_to_monotonic;
- } while (read_seqretry(&xtime_lock, seq));
- set_normalized_timespec(&delta,
- new_wall_to.tv_sec -
- timr->it.real.wall_to_prev.tv_sec,
- new_wall_to.tv_nsec -
- timr->it.real.wall_to_prev.tv_nsec);
- if (likely((delta.tv_sec | delta.tv_nsec ) == 0)) {
- /* do nothing, timer is on time */
- } else if (delta.tv_sec < 0) {
- /* do nothing, timer is already late */
- } else {
- /* timer is early due to a clock set */
- tstojiffie(&delta,
- posix_clocks[timr->it_clock].res,
- &exp);
- timr->it.real.wall_to_prev = new_wall_to;
- timr->it.real.timer.expires += exp;
- add_timer(&timr->it.real.timer);
- do_notify = 0;
- }
- spin_unlock(&abs_list.lock);
- }
- if (do_notify) {
- int si_private=0;
+ if (timr->it.real.interval.tv64 != 0)
+ si_private = ++timr->it_requeue_pending;
- if (timr->it.real.incr)
- si_private = ++timr->it_requeue_pending;
- else {
- remove_from_abslist(timr);
+ if (posix_timer_event(timr, si_private)) {
+ /*
+ * signal was not sent because of sig_ignor
+ * we will not get a call back to restart it AND
+ * it should be restarted.
+ */
+ if (timr->it.real.interval.tv64 != 0) {
+ timr->it_overrun +=
+ hrtimer_forward(&timr->it.real.timer,
+ timr->it.real.interval);
+ ret = HRTIMER_RESTART;
}
-
- if (posix_timer_event(timr, si_private))
- /*
- * signal was not sent because of sig_ignor
- * we will not get a call back to restart it AND
- * it should be restarted.
- */
- schedule_next_timer(timr);
}
- unlock_timer(timr, flags); /* hold thru abs lock to keep irq off */
-}
+ unlock_timer(timr, flags);
+ return ret;
+}
-static inline struct task_struct * good_sigevent(sigevent_t * event)
+static struct task_struct * good_sigevent(sigevent_t * event)
{
struct task_struct *rtn = current->group_leader;
@@ -530,7 +378,7 @@ static inline struct task_struct * good_sigevent(sigevent_t * event)
return rtn;
}
-void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock)
+void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock)
{
if ((unsigned) clock_id >= MAX_CLOCKS) {
printk("POSIX clock register failed for clock_id %d\n",
@@ -576,7 +424,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
/* Create a POSIX.1b interval timer. */
asmlinkage long
-sys_timer_create(clockid_t which_clock,
+sys_timer_create(const clockid_t which_clock,
struct sigevent __user *timer_event_spec,
timer_t __user * created_timer_id)
{
@@ -602,8 +450,7 @@ sys_timer_create(clockid_t which_clock,
goto out;
}
spin_lock_irq(&idr_lock);
- error = idr_get_new(&posix_timers_id,
- (void *) new_timer,
+ error = idr_get_new(&posix_timers_id, (void *) new_timer,
&new_timer_id);
spin_unlock_irq(&idr_lock);
if (error == -EAGAIN)
@@ -704,27 +551,6 @@ out:
}
/*
- * good_timespec
- *
- * This function checks the elements of a timespec structure.
- *
- * Arguments:
- * ts : Pointer to the timespec structure to check
- *
- * Return value:
- * If a NULL pointer was passed in, or the tv_nsec field was less than 0
- * or greater than NSEC_PER_SEC, or the tv_sec field was less than 0,
- * this function returns 0. Otherwise it returns 1.
- */
-static int good_timespec(const struct timespec *ts)
-{
- if ((!ts) || (ts->tv_sec < 0) ||
- ((unsigned) ts->tv_nsec >= NSEC_PER_SEC))
- return 0;
- return 1;
-}
-
-/*
* Locking issues: We need to protect the result of the id look up until
* we get the timer locked down so it is not deleted under us. The
* removal is done under the idr spinlock so we use that here to bridge
@@ -776,39 +602,39 @@ static struct k_itimer * lock_timer(timer_t timer_id, unsigned long *flags)
static void
common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
{
- unsigned long expires;
- struct now_struct now;
-
- do
- expires = timr->it.real.timer.expires;
- while ((volatile long) (timr->it.real.timer.expires) != expires);
-
- posix_get_now(&now);
-
- if (expires &&
- ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) &&
- !timr->it.real.incr &&
- posix_time_before(&timr->it.real.timer, &now))
- timr->it.real.timer.expires = expires = 0;
- if (expires) {
- if (timr->it_requeue_pending & REQUEUE_PENDING ||
- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
- posix_bump_timer(timr, now);
- expires = timr->it.real.timer.expires;
- }
- else
- if (!timer_pending(&timr->it.real.timer))
- expires = 0;
- if (expires)
- expires -= now.jiffies;
- }
- jiffies_to_timespec(expires, &cur_setting->it_value);
- jiffies_to_timespec(timr->it.real.incr, &cur_setting->it_interval);
+ ktime_t remaining;
+ struct hrtimer *timer = &timr->it.real.timer;
+
+ memset(cur_setting, 0, sizeof(struct itimerspec));
+ remaining = hrtimer_get_remaining(timer);
- if (cur_setting->it_value.tv_sec < 0) {
+ /* Time left ? or timer pending */
+ if (remaining.tv64 > 0 || hrtimer_active(timer))
+ goto calci;
+ /* interval timer ? */
+ if (timr->it.real.interval.tv64 == 0)
+ return;
+ /*
+ * When a requeue is pending or this is a SIGEV_NONE timer
+ * move the expiry time forward by intervals, so expiry is >
+ * now.
+ */
+ if (timr->it_requeue_pending & REQUEUE_PENDING ||
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
+ timr->it_overrun +=
+ hrtimer_forward(timer, timr->it.real.interval);
+ remaining = hrtimer_get_remaining(timer);
+ }
+ calci:
+ /* interval timer ? */
+ if (timr->it.real.interval.tv64 != 0)
+ cur_setting->it_interval =
+ ktime_to_timespec(timr->it.real.interval);
+ /* Return 0 only, when the timer is expired and not pending */
+ if (remaining.tv64 <= 0)
cur_setting->it_value.tv_nsec = 1;
- cur_setting->it_value.tv_sec = 0;
- }
+ else
+ cur_setting->it_value = ktime_to_timespec(remaining);
}
/* Get the time remaining on a POSIX.1b interval timer. */
@@ -832,6 +658,7 @@ sys_timer_gettime(timer_t timer_id, struct itimerspec __user *setting)
return 0;
}
+
/*
* Get the number of overruns of a POSIX.1b interval timer. This is to
* be the overrun of the timer last delivered. At the same time we are
@@ -841,7 +668,6 @@ sys_timer_gettime(timer_t timer_id, struct itimerspec __user *setting)
* the call back to do_schedule_next_timer(). So all we need to do is
* to pick up the frozen overrun.
*/
-
asmlinkage long
sys_timer_getoverrun(timer_t timer_id)
{
@@ -858,153 +684,55 @@ sys_timer_getoverrun(timer_t timer_id)
return overrun;
}
-/*
- * Adjust for absolute time
- *
- * If absolute time is given and it is not CLOCK_MONOTONIC, we need to
- * adjust for the offset between the timer clock (CLOCK_MONOTONIC) and
- * what ever clock he is using.
- *
- * If it is relative time, we need to add the current (CLOCK_MONOTONIC)
- * time to it to get the proper time for the timer.
- */
-static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
- int abs, u64 *exp, struct timespec *wall_to)
-{
- struct timespec now;
- struct timespec oc = *tp;
- u64 jiffies_64_f;
- int rtn =0;
-
- if (abs) {
- /*
- * The mask pick up the 4 basic clocks
- */
- if (!((clock - &posix_clocks[0]) & ~CLOCKS_MASK)) {
- jiffies_64_f = do_posix_clock_monotonic_gettime_parts(
- &now, wall_to);
- /*
- * If we are doing a MONOTONIC clock
- */
- if((clock - &posix_clocks[0]) & CLOCKS_MONO){
- now.tv_sec += wall_to->tv_sec;
- now.tv_nsec += wall_to->tv_nsec;
- }
- } else {
- /*
- * Not one of the basic clocks
- */
- clock->clock_get(clock - posix_clocks, &now);
- jiffies_64_f = get_jiffies_64();
- }
- /*
- * Take away now to get delta and normalize
- */
- set_normalized_timespec(&oc, oc.tv_sec - now.tv_sec,
- oc.tv_nsec - now.tv_nsec);
- }else{
- jiffies_64_f = get_jiffies_64();
- }
- /*
- * Check if the requested time is prior to now (if so set now)
- */
- if (oc.tv_sec < 0)
- oc.tv_sec = oc.tv_nsec = 0;
-
- if (oc.tv_sec | oc.tv_nsec)
- set_normalized_timespec(&oc, oc.tv_sec,
- oc.tv_nsec + clock->res);
- tstojiffie(&oc, clock->res, exp);
-
- /*
- * Check if the requested time is more than the timer code
- * can handle (if so we error out but return the value too).
- */
- if (*exp > ((u64)MAX_JIFFY_OFFSET))
- /*
- * This is a considered response, not exactly in
- * line with the standard (in fact it is silent on
- * possible overflows). We assume such a large
- * value is ALMOST always a programming error and
- * try not to compound it by setting a really dumb
- * value.
- */
- rtn = -EINVAL;
- /*
- * return the actual jiffies expire time, full 64 bits
- */
- *exp += jiffies_64_f;
- return rtn;
-}
/* Set a POSIX.1b interval timer. */
/* timr->it_lock is taken. */
-static inline int
+static int
common_timer_set(struct k_itimer *timr, int flags,
struct itimerspec *new_setting, struct itimerspec *old_setting)
{
- struct k_clock *clock = &posix_clocks[timr->it_clock];
- u64 expire_64;
+ struct hrtimer *timer = &timr->it.real.timer;
if (old_setting)
common_timer_get(timr, old_setting);
/* disable the timer */
- timr->it.real.incr = 0;
+ timr->it.real.interval.tv64 = 0;
/*
* careful here. If smp we could be in the "fire" routine which will
* be spinning as we hold the lock. But this is ONLY an SMP issue.
*/
- if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
-#ifdef CONFIG_SMP
- /*
- * It can only be active if on an other cpu. Since
- * we have cleared the interval stuff above, it should
- * clear once we release the spin lock. Of course once
- * we do that anything could happen, including the
- * complete melt down of the timer. So return with
- * a "retry" exit status.
- */
+ if (hrtimer_try_to_cancel(timer) < 0)
return TIMER_RETRY;
-#endif
- }
-
- remove_from_abslist(timr);
timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
~REQUEUE_PENDING;
timr->it_overrun_last = 0;
- timr->it_overrun = -1;
- /*
- *switch off the timer when it_value is zero
- */
- if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
- timr->it.real.timer.expires = 0;
- return 0;
- }
- if (adjust_abs_time(clock,
- &new_setting->it_value, flags & TIMER_ABSTIME,
- &expire_64, &(timr->it.real.wall_to_prev))) {
- return -EINVAL;
- }
- timr->it.real.timer.expires = (unsigned long)expire_64;
- tstojiffie(&new_setting->it_interval, clock->res, &expire_64);
- timr->it.real.incr = (unsigned long)expire_64;
+ /* switch off the timer when it_value is zero */
+ if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec)
+ return 0;
- /*
- * We do not even queue SIGEV_NONE timers! But we do put them
- * in the abs list so we can do that right.
+ /* Posix madness. Only absolute CLOCK_REALTIME timers
+ * are affected by clock sets. So we must reiniatilize
+ * the timer.
*/
- if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE))
- add_timer(&timr->it.real.timer);
-
- if (flags & TIMER_ABSTIME && clock->abs_struct) {
- spin_lock(&clock->abs_struct->lock);
- list_add_tail(&(timr->it.real.abs_timer_entry),
- &(clock->abs_struct->list));
- spin_unlock(&clock->abs_struct->lock);
- }
+ if (timr->it_clock == CLOCK_REALTIME && (flags & TIMER_ABSTIME))
+ hrtimer_rebase(timer, CLOCK_REALTIME);
+ else
+ hrtimer_rebase(timer, CLOCK_MONOTONIC);
+
+ timer->expires = timespec_to_ktime(new_setting->it_value);
+
+ /* Convert interval */
+ timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
+
+ /* SIGEV_NONE timers are not queued ! See common_timer_get */
+ if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+ return 0;
+
+ hrtimer_start(timer, timer->expires, (flags & TIMER_ABSTIME) ?
+ HRTIMER_ABS : HRTIMER_REL);
return 0;
}
@@ -1026,8 +754,8 @@ sys_timer_settime(timer_t timer_id, int flags,
if (copy_from_user(&new_spec, new_setting, sizeof (new_spec)))
return -EFAULT;
- if ((!good_timespec(&new_spec.it_interval)) ||
- (!good_timespec(&new_spec.it_value)))
+ if (!timespec_valid(&new_spec.it_interval) ||
+ !timespec_valid(&new_spec.it_value))
return -EINVAL;
retry:
timr = lock_timer(timer_id, &flag);
@@ -1043,8 +771,8 @@ retry:
goto retry;
}
- if (old_setting && !error && copy_to_user(old_setting,
- &old_spec, sizeof (old_spec)))
+ if (old_setting && !error &&
+ copy_to_user(old_setting, &old_spec, sizeof (old_spec)))
error = -EFAULT;
return error;
@@ -1052,24 +780,10 @@ retry:
static inline int common_timer_del(struct k_itimer *timer)
{
- timer->it.real.incr = 0;
+ timer->it.real.interval.tv64 = 0;
- if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
-#ifdef CONFIG_SMP
- /*
- * It can only be active if on an other cpu. Since
- * we have cleared the interval stuff above, it should
- * clear once we release the spin lock. Of course once
- * we do that anything could happen, including the
- * complete melt down of the timer. So return with
- * a "retry" exit status.
- */
+ if (hrtimer_try_to_cancel(&timer->it.real.timer) < 0)
return TIMER_RETRY;
-#endif
- }
-
- remove_from_abslist(timer);
-
return 0;
}
@@ -1085,24 +799,16 @@ sys_timer_delete(timer_t timer_id)
struct k_itimer *timer;
long flags;
-#ifdef CONFIG_SMP
- int error;
retry_delete:
-#endif
timer = lock_timer(timer_id, &flags);
if (!timer)
return -EINVAL;
-#ifdef CONFIG_SMP
- error = timer_delete_hook(timer);
-
- if (error == TIMER_RETRY) {
+ if (timer_delete_hook(timer) == TIMER_RETRY) {
unlock_timer(timer, flags);
goto retry_delete;
}
-#else
- timer_delete_hook(timer);
-#endif
+
spin_lock(&current->sighand->siglock);
list_del(&timer->list);
spin_unlock(&current->sighand->siglock);
@@ -1119,29 +825,21 @@ retry_delete:
release_posix_timer(timer, IT_ID_SET);
return 0;
}
+
/*
* return timer owned by the process, used by exit_itimers
*/
-static inline void itimer_delete(struct k_itimer *timer)
+static void itimer_delete(struct k_itimer *timer)
{
unsigned long flags;
-#ifdef CONFIG_SMP
- int error;
retry_delete:
-#endif
spin_lock_irqsave(&timer->it_lock, flags);
-#ifdef CONFIG_SMP
- error = timer_delete_hook(timer);
-
- if (error == TIMER_RETRY) {
+ if (timer_delete_hook(timer) == TIMER_RETRY) {
unlock_timer(timer, flags);
goto retry_delete;
}
-#else
- timer_delete_hook(timer);
-#endif
list_del(&timer->list);
/*
* This keeps any tasks waiting on the spin lock from thinking
@@ -1170,57 +868,8 @@ void exit_itimers(struct signal_struct *sig)
}
}
-/*
- * And now for the "clock" calls
- *
- * These functions are called both from timer functions (with the timer
- * spin_lock_irq() held and from clock calls with no locking. They must
- * use the save flags versions of locks.
- */
-
-/*
- * We do ticks here to avoid the irq lock ( they take sooo long).
- * The seqlock is great here. Since we a reader, we don't really care
- * if we are interrupted since we don't take lock that will stall us or
- * any other cpu. Voila, no irq lock is needed.
- *
- */
-
-static u64 do_posix_clock_monotonic_gettime_parts(
- struct timespec *tp, struct timespec *mo)
-{
- u64 jiff;
- unsigned int seq;
-
- do {
- seq = read_seqbegin(&xtime_lock);
- getnstimeofday(tp);
- *mo = wall_to_monotonic;
- jiff = jiffies_64;
-
- } while(read_seqretry(&xtime_lock, seq));
-
- return jiff;
-}
-
-static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp)
-{
- struct timespec wall_to_mono;
-
- do_posix_clock_monotonic_gettime_parts(tp, &wall_to_mono);
-
- set_normalized_timespec(tp, tp->tv_sec + wall_to_mono.tv_sec,
- tp->tv_nsec + wall_to_mono.tv_nsec);
-
- return 0;
-}
-
-int do_posix_clock_monotonic_gettime(struct timespec *tp)
-{
- return do_posix_clock_monotonic_get(CLOCK_MONOTONIC, tp);
-}
-
-int do_posix_clock_nosettime(clockid_t clockid, struct timespec *tp)
+/* Not available / possible... functions */
+int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp)
{
return -EINVAL;
}
@@ -1232,7 +881,8 @@ int do_posix_clock_notimer_create(struct k_itimer *timer)
}
EXPORT_SYMBOL_GPL(do_posix_clock_notimer_create);
-int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
+int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
+ struct timespec *t, struct timespec __user *r)
{
#ifndef ENOTSUP
return -EOPNOTSUPP; /* aka ENOTSUP in userland for POSIX */
@@ -1242,8 +892,8 @@ int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
}
EXPORT_SYMBOL_GPL(do_posix_clock_nonanosleep);
-asmlinkage long
-sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
+asmlinkage long sys_clock_settime(const clockid_t which_clock,
+ const struct timespec __user *tp)
{
struct timespec new_tp;
@@ -1256,7 +906,7 @@ sys_clock_settime(clockid_t which_clock, const struct timespec __user *tp)
}
asmlinkage long
-sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp)
+sys_clock_gettime(const clockid_t which_clock, struct timespec __user *tp)
{
struct timespec kernel_tp;
int error;
@@ -1273,7 +923,7 @@ sys_clock_gettime(clockid_t which_clock, struct timespec __user *tp)
}
asmlinkage long
-sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
+sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
{
struct timespec rtn_tp;
int error;
@@ -1292,117 +942,34 @@ sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
}
/*
- * The standard says that an absolute nanosleep call MUST wake up at
- * the requested time in spite of clock settings. Here is what we do:
- * For each nanosleep call that needs it (only absolute and not on
- * CLOCK_MONOTONIC* (as it can not be set)) we thread a little structure
- * into the "nanosleep_abs_list". All we need is the task_struct pointer.
- * When ever the clock is set we just wake up all those tasks. The rest
- * is done by the while loop in clock_nanosleep().
- *
- * On locking, clock_was_set() is called from update_wall_clock which
- * holds (or has held for it) a write_lock_irq( xtime_lock) and is
- * called from the timer bh code. Thus we need the irq save locks.
- *
- * Also, on the call from update_wall_clock, that is done as part of a
- * softirq thing. We don't want to delay the system that much (possibly
- * long list of timers to fix), so we defer that work to keventd.
+ * nanosleep for monotonic and realtime clocks
*/
-
-static DECLARE_WAIT_QUEUE_HEAD(nanosleep_abs_wqueue);
-static DECLARE_WORK(clock_was_set_work, (void(*)(void*))clock_was_set, NULL);
-
-static DECLARE_MUTEX(clock_was_set_lock);
-
-void clock_was_set(void)
-{
- struct k_itimer *timr;
- struct timespec new_wall_to;
- LIST_HEAD(cws_list);
- unsigned long seq;
-
-
- if (unlikely(in_interrupt())) {
- schedule_work(&clock_was_set_work);
- return;
+static int common_nsleep(const clockid_t which_clock, int flags,
+ struct timespec *tsave, struct timespec __user *rmtp)
+{
+ int mode = flags & TIMER_ABSTIME ? HRTIMER_ABS : HRTIMER_REL;
+ int clockid = which_clock;
+
+ switch (which_clock) {
+ case CLOCK_REALTIME:
+ /* Posix madness. Only absolute timers on clock realtime
+ are affected by clock set. */
+ if (mode != HRTIMER_ABS)
+ clockid = CLOCK_MONOTONIC;
+ case CLOCK_MONOTONIC:
+ break;
+ default:
+ return -EINVAL;
}
- wake_up_all(&nanosleep_abs_wqueue);
-
- /*
- * Check if there exist TIMER_ABSTIME timers to correct.
- *
- * Notes on locking: This code is run in task context with irq
- * on. We CAN be interrupted! All other usage of the abs list
- * lock is under the timer lock which holds the irq lock as
- * well. We REALLY don't want to scan the whole list with the
- * interrupt system off, AND we would like a sequence lock on
- * this code as well. Since we assume that the clock will not
- * be set often, it seems ok to take and release the irq lock
- * for each timer. In fact add_timer will do this, so this is
- * not an issue. So we know when we are done, we will move the
- * whole list to a new location. Then as we process each entry,
- * we will move it to the actual list again. This way, when our
- * copy is empty, we are done. We are not all that concerned
- * about preemption so we will use a semaphore lock to protect
- * aginst reentry. This way we will not stall another
- * processor. It is possible that this may delay some timers
- * that should have expired, given the new clock, but even this
- * will be minimal as we will always update to the current time,
- * even if it was set by a task that is waiting for entry to
- * this code. Timers that expire too early will be caught by
- * the expire code and restarted.
-
- * Absolute timers that repeat are left in the abs list while
- * waiting for the task to pick up the signal. This means we
- * may find timers that are not in the "add_timer" list, but are
- * in the abs list. We do the same thing for these, save
- * putting them back in the "add_timer" list. (Note, these are
- * left in the abs list mainly to indicate that they are
- * ABSOLUTE timers, a fact that is used by the re-arm code, and
- * for which we have no other flag.)
-
- */
-
- down(&clock_was_set_lock);
- spin_lock_irq(&abs_list.lock);
- list_splice_init(&abs_list.list, &cws_list);
- spin_unlock_irq(&abs_list.lock);
- do {
- do {
- seq = read_seqbegin(&xtime_lock);
- new_wall_to = wall_to_monotonic;
- } while (read_seqretry(&xtime_lock, seq));
-
- spin_lock_irq(&abs_list.lock);
- if (list_empty(&cws_list)) {
- spin_unlock_irq(&abs_list.lock);
- break;
- }
- timr = list_entry(cws_list.next, struct k_itimer,
- it.real.abs_timer_entry);
-
- list_del_init(&timr->it.real.abs_timer_entry);
- if (add_clockset_delta(timr, &new_wall_to) &&
- del_timer(&timr->it.real.timer)) /* timer run yet? */
- add_timer(&timr->it.real.timer);
- list_add(&timr->it.real.abs_timer_entry, &abs_list.list);
- spin_unlock_irq(&abs_list.lock);
- } while (1);
-
- up(&clock_was_set_lock);
+ return hrtimer_nanosleep(tsave, rmtp, mode, clockid);
}
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
asmlinkage long
-sys_clock_nanosleep(clockid_t which_clock, int flags,
+sys_clock_nanosleep(const clockid_t which_clock, int flags,
const struct timespec __user *rqtp,
struct timespec __user *rmtp)
{
struct timespec t;
- struct restart_block *restart_block =
- &(current_thread_info()->restart_block);
- int ret;
if (invalid_clockid(which_clock))
return -EINVAL;
@@ -1410,125 +977,9 @@ sys_clock_nanosleep(clockid_t which_clock, int flags,
if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
return -EFAULT;
- if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
+ if (!timespec_valid(&t))
return -EINVAL;
- /*
- * Do this here as nsleep function does not have the real address.
- */
- restart_block->arg1 = (unsigned long)rmtp;
-
- ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
-
- if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
- copy_to_user(rmtp, &t, sizeof (t)))
- return -EFAULT;
- return ret;
-}
-
-
-static int common_nsleep(clockid_t which_clock,
- int flags, struct timespec *tsave)
-{
- struct timespec t, dum;
- DECLARE_WAITQUEUE(abs_wqueue, current);
- u64 rq_time = (u64)0;
- s64 left;
- int abs;
- struct restart_block *restart_block =
- &current_thread_info()->restart_block;
-
- abs_wqueue.flags = 0;
- abs = flags & TIMER_ABSTIME;
-
- if (restart_block->fn == clock_nanosleep_restart) {
- /*
- * Interrupted by a non-delivered signal, pick up remaining
- * time and continue. Remaining time is in arg2 & 3.
- */
- restart_block->fn = do_no_restart_syscall;
-
- rq_time = restart_block->arg3;
- rq_time = (rq_time << 32) + restart_block->arg2;
- if (!rq_time)
- return -EINTR;
- left = rq_time - get_jiffies_64();
- if (left <= (s64)0)
- return 0; /* Already passed */
- }
-
- if (abs && (posix_clocks[which_clock].clock_get !=
- posix_clocks[CLOCK_MONOTONIC].clock_get))
- add_wait_queue(&nanosleep_abs_wqueue, &abs_wqueue);
-
- do {
- t = *tsave;
- if (abs || !rq_time) {
- adjust_abs_time(&posix_clocks[which_clock], &t, abs,
- &rq_time, &dum);
- }
-
- left = rq_time - get_jiffies_64();
- if (left >= (s64)MAX_JIFFY_OFFSET)
- left = (s64)MAX_JIFFY_OFFSET;
- if (left < (s64)0)
- break;
-
- schedule_timeout_interruptible(left);
-
- left = rq_time - get_jiffies_64();
- } while (left > (s64)0 && !test_thread_flag(TIF_SIGPENDING));
-
- if (abs_wqueue.task_list.next)
- finish_wait(&nanosleep_abs_wqueue, &abs_wqueue);
-
- if (left > (s64)0) {
-
- /*
- * Always restart abs calls from scratch to pick up any
- * clock shifting that happened while we are away.
- */
- if (abs)
- return -ERESTARTNOHAND;
-
- left *= TICK_NSEC;
- tsave->tv_sec = div_long_long_rem(left,
- NSEC_PER_SEC,
- &tsave->tv_nsec);
- /*
- * Restart works by saving the time remaing in
- * arg2 & 3 (it is 64-bits of jiffies). The other
- * info we need is the clock_id (saved in arg0).
- * The sys_call interface needs the users
- * timespec return address which _it_ saves in arg1.
- * Since we have cast the nanosleep call to a clock_nanosleep
- * both can be restarted with the same code.
- */
- restart_block->fn = clock_nanosleep_restart;
- restart_block->arg0 = which_clock;
- /*
- * Caller sets arg1
- */
- restart_block->arg2 = rq_time & 0xffffffffLL;
- restart_block->arg3 = rq_time >> 32;
-
- return -ERESTART_RESTARTBLOCK;
- }
-
- return 0;
-}
-/*
- * This will restart clock_nanosleep.
- */
-long
-clock_nanosleep_restart(struct restart_block *restart_block)
-{
- struct timespec t;
- int ret = common_nsleep(restart_block->arg0, 0, &t);
-
- if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
- copy_to_user((struct timespec __user *)(restart_block->arg1), &t,
- sizeof (t)))
- return -EFAULT;
- return ret;
+ return CLOCK_DISPATCH(which_clock, nsleep,
+ (which_clock, flags, &t, rmtp));
}
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 5ec248cb7f4a..9fd8d4f03595 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -38,7 +38,7 @@ config PM_DEBUG
config SOFTWARE_SUSPEND
bool "Software Suspend"
- depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FVR || PPC32) && !SMP)
+ depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
---help---
Enable the possibility of suspending the machine.
It doesn't need APM.
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 027322a564f4..e24446f8d8cd 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -24,10 +24,11 @@
extern suspend_disk_method_t pm_disk_mode;
+extern int swsusp_shrink_memory(void);
extern int swsusp_suspend(void);
-extern int swsusp_write(void);
+extern int swsusp_write(struct pbe *pblist, unsigned int nr_pages);
extern int swsusp_check(void);
-extern int swsusp_read(void);
+extern int swsusp_read(struct pbe **pblist_ptr);
extern void swsusp_close(void);
extern int swsusp_resume(void);
@@ -73,31 +74,6 @@ static void power_down(suspend_disk_method_t mode)
static int in_suspend __nosavedata = 0;
-/**
- * free_some_memory - Try to free as much memory as possible
- *
- * ... but do not OOM-kill anyone
- *
- * Notice: all userland should be stopped at this point, or
- * livelock is possible.
- */
-
-static void free_some_memory(void)
-{
- unsigned int i = 0;
- unsigned int tmp;
- unsigned long pages = 0;
- char *p = "-\\|/";
-
- printk("Freeing memory... ");
- while ((tmp = shrink_all_memory(10000))) {
- pages += tmp;
- printk("\b%c", p[i++ % 4]);
- }
- printk("\bdone (%li pages freed)\n", pages);
-}
-
-
static inline void platform_finish(void)
{
if (pm_disk_mode == PM_DISK_PLATFORM) {
@@ -127,8 +103,8 @@ static int prepare_processes(void)
}
/* Free memory before shutting down devices. */
- free_some_memory();
- return 0;
+ if (!(error = swsusp_shrink_memory()))
+ return 0;
thaw:
thaw_processes();
enable_nonboot_cpus();
@@ -176,7 +152,7 @@ int pm_suspend_disk(void)
if (in_suspend) {
device_resume();
pr_debug("PM: writing image.\n");
- error = swsusp_write();
+ error = swsusp_write(pagedir_nosave, nr_copy_pages);
if (!error)
power_down(pm_disk_mode);
else {
@@ -247,7 +223,7 @@ static int software_resume(void)
pr_debug("PM: Reading swsusp image.\n");
- if ((error = swsusp_read())) {
+ if ((error = swsusp_read(&pagedir_nosave))) {
swsusp_free();
goto Thaw;
}
@@ -363,37 +339,55 @@ static ssize_t resume_show(struct subsystem * subsys, char *buf)
MINOR(swsusp_resume_device));
}
-static ssize_t resume_store(struct subsystem * subsys, const char * buf, size_t n)
+static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n)
{
- int len;
- char *p;
unsigned int maj, min;
- int error = -EINVAL;
dev_t res;
+ int ret = -EINVAL;
- p = memchr(buf, '\n', n);
- len = p ? p - buf : n;
+ if (sscanf(buf, "%u:%u", &maj, &min) != 2)
+ goto out;
- 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();
- }
- }
+ res = MKDEV(maj,min);
+ if (maj != MAJOR(res) || min != MINOR(res))
+ goto out;
- return error >= 0 ? n : error;
+ down(&pm_sem);
+ swsusp_resume_device = res;
+ up(&pm_sem);
+ printk("Attempting manual resume\n");
+ noresume = 0;
+ software_resume();
+ ret = n;
+out:
+ return ret;
}
power_attr(resume);
+static ssize_t image_size_show(struct subsystem * subsys, char *buf)
+{
+ return sprintf(buf, "%u\n", image_size);
+}
+
+static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n)
+{
+ unsigned int size;
+
+ if (sscanf(buf, "%u", &size) == 1) {
+ image_size = size;
+ return n;
+ }
+
+ return -EINVAL;
+}
+
+power_attr(image_size);
+
static struct attribute * g[] = {
&disk_attr.attr,
&resume_attr.attr,
+ &image_size_attr.attr,
NULL,
};
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 6c042b5ee14b..7e8492fd1423 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -9,19 +9,13 @@
#define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
#endif
-#define MAX_PBES ((PAGE_SIZE - sizeof(struct new_utsname) \
- - 4 - 3*sizeof(unsigned long) - sizeof(int) \
- - sizeof(void *)) / sizeof(swp_entry_t))
-
struct swsusp_info {
struct new_utsname uts;
u32 version_code;
unsigned long num_physpages;
int cpus;
unsigned long image_pages;
- unsigned long pagedir_pages;
- suspend_pagedir_t * suspend_pagedir;
- swp_entry_t pagedir[MAX_PBES];
+ unsigned long pages;
} __attribute__((aligned(PAGE_SIZE)));
@@ -48,25 +42,27 @@ static struct subsys_attribute _name##_attr = { \
extern struct subsystem power_subsys;
-extern int freeze_processes(void);
-extern void thaw_processes(void);
-
extern int pm_prepare_console(void);
extern void pm_restore_console(void);
-
/* References to section boundaries */
extern const void __nosave_begin, __nosave_end;
extern unsigned int nr_copy_pages;
-extern suspend_pagedir_t *pagedir_nosave;
-extern suspend_pagedir_t *pagedir_save;
+extern struct pbe *pagedir_nosave;
+
+/* Preferred image size in MB (default 500) */
+extern unsigned int image_size;
extern asmlinkage int swsusp_arch_suspend(void);
extern asmlinkage int swsusp_arch_resume(void);
+extern unsigned int count_data_pages(void);
extern void free_pagedir(struct pbe *pblist);
+extern void release_eaten_pages(void);
extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed);
-extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages);
extern void swsusp_free(void);
extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed);
+extern unsigned int snapshot_nr_pages(void);
+extern struct pbe *snapshot_pblist(void);
+extern void snapshot_pblist_set(struct pbe *pblist);
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 4a6dbcefd378..41f66365f0d8 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -33,7 +33,35 @@
#include "power.h"
+struct pbe *pagedir_nosave;
+unsigned int nr_copy_pages;
+
#ifdef CONFIG_HIGHMEM
+unsigned int count_highmem_pages(void)
+{
+ struct zone *zone;
+ unsigned long zone_pfn;
+ unsigned int n = 0;
+
+ for_each_zone (zone)
+ if (is_highmem(zone)) {
+ mark_free_pages(zone);
+ for (zone_pfn = 0; zone_pfn < zone->spanned_pages; zone_pfn++) {
+ struct page *page;
+ unsigned long pfn = zone_pfn + zone->zone_start_pfn;
+ if (!pfn_valid(pfn))
+ continue;
+ page = pfn_to_page(pfn);
+ if (PageReserved(page))
+ continue;
+ if (PageNosaveFree(page))
+ continue;
+ n++;
+ }
+ }
+ return n;
+}
+
struct highmem_page {
char *data;
struct page *page;
@@ -149,17 +177,15 @@ static int saveable(struct zone *zone, unsigned long *zone_pfn)
BUG_ON(PageReserved(page) && PageNosave(page));
if (PageNosave(page))
return 0;
- if (PageReserved(page) && pfn_is_nosave(pfn)) {
- pr_debug("[nosave pfn 0x%lx]", pfn);
+ if (PageReserved(page) && pfn_is_nosave(pfn))
return 0;
- }
if (PageNosaveFree(page))
return 0;
return 1;
}
-static unsigned count_data_pages(void)
+unsigned int count_data_pages(void)
{
struct zone *zone;
unsigned long zone_pfn;
@@ -244,7 +270,7 @@ static inline void fill_pb_page(struct pbe *pbpage)
* of memory pages allocated with alloc_pagedir()
*/
-void create_pbe_list(struct pbe *pblist, unsigned int nr_pages)
+static inline void create_pbe_list(struct pbe *pblist, unsigned int nr_pages)
{
struct pbe *pbpage, *p;
unsigned int num = PBES_PER_PAGE;
@@ -261,7 +287,35 @@ void create_pbe_list(struct pbe *pblist, unsigned int nr_pages)
p->next = p + 1;
p->next = NULL;
}
- pr_debug("create_pbe_list(): initialized %d PBEs\n", num);
+}
+
+/**
+ * On resume it is necessary to trace and eventually free the unsafe
+ * pages that have been allocated, because they are needed for I/O
+ * (on x86-64 we likely will "eat" these pages once again while
+ * creating the temporary page translation tables)
+ */
+
+struct eaten_page {
+ struct eaten_page *next;
+ char padding[PAGE_SIZE - sizeof(void *)];
+};
+
+static struct eaten_page *eaten_pages = NULL;
+
+void release_eaten_pages(void)
+{
+ struct eaten_page *p, *q;
+
+ p = eaten_pages;
+ while (p) {
+ q = p->next;
+ /* We don't want swsusp_free() to free this page again */
+ ClearPageNosave(virt_to_page(p));
+ free_page((unsigned long)p);
+ p = q;
+ }
+ eaten_pages = NULL;
}
/**
@@ -282,9 +336,12 @@ static inline void *alloc_image_page(gfp_t gfp_mask, int safe_needed)
if (safe_needed)
do {
res = (void *)get_zeroed_page(gfp_mask);
- if (res && PageNosaveFree(virt_to_page(res)))
+ if (res && PageNosaveFree(virt_to_page(res))) {
/* This is for swsusp_free() */
SetPageNosave(virt_to_page(res));
+ ((struct eaten_page *)res)->next = eaten_pages;
+ eaten_pages = res;
+ }
} while (res && PageNosaveFree(virt_to_page(res)));
else
res = (void *)get_zeroed_page(gfp_mask);
@@ -332,7 +389,8 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed
if (!pbe) { /* get_zeroed_page() failed */
free_pagedir(pblist);
pblist = NULL;
- }
+ } else
+ create_pbe_list(pblist, nr_pages);
return pblist;
}
@@ -370,8 +428,14 @@ void swsusp_free(void)
static int enough_free_mem(unsigned int nr_pages)
{
- pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
- return nr_free_pages() > (nr_pages + PAGES_FOR_IO +
+ struct zone *zone;
+ unsigned int n = 0;
+
+ for_each_zone (zone)
+ if (!is_highmem(zone))
+ n += zone->free_pages;
+ pr_debug("swsusp: available memory: %u pages\n", n);
+ return n > (nr_pages + PAGES_FOR_IO +
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
}
@@ -395,7 +459,6 @@ static struct pbe *swsusp_alloc(unsigned int nr_pages)
printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
return NULL;
}
- create_pbe_list(pblist, nr_pages);
if (alloc_data_pages(pblist, GFP_ATOMIC | __GFP_COLD, 0)) {
printk(KERN_ERR "suspend: Allocating image pages failed.\n");
@@ -421,10 +484,6 @@ asmlinkage int swsusp_save(void)
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE,
PAGES_FOR_IO, nr_free_pages());
- /* This is needed because of the fixed size of swsusp_info */
- if (MAX_PBES < (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE)
- return -ENOSPC;
-
if (!enough_free_mem(nr_pages)) {
printk(KERN_ERR "swsusp: Not enough free memory\n");
return -ENOMEM;
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index c05f46e7348f..55a18d26abed 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -30,8 +30,8 @@
* Alex Badea <vampire@go.ro>:
* Fixed runaway init
*
- * Andreas Steinmetz <ast@domdv.de>:
- * Added encrypted suspend option
+ * Rafael J. Wysocki <rjw@sisk.pl>
+ * Added the swap map data structure and reworked the handling of swap
*
* More state savers are welcome. Especially for the scsi layer...
*
@@ -67,44 +67,33 @@
#include <asm/tlbflush.h>
#include <asm/io.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
-#include <asm/scatterlist.h>
-
#include "power.h"
+/*
+ * Preferred image size in MB (tunable via /sys/power/image_size).
+ * When it is set to N, swsusp will do its best to ensure the image
+ * size will not exceed N MB, but if that is impossible, it will
+ * try to create the smallest image possible.
+ */
+unsigned int image_size = 500;
+
#ifdef CONFIG_HIGHMEM
+unsigned int count_highmem_pages(void);
int save_highmem(void);
int restore_highmem(void);
#else
static int save_highmem(void) { return 0; }
static int restore_highmem(void) { return 0; }
+static unsigned int count_highmem_pages(void) { return 0; }
#endif
-#define CIPHER "aes"
-#define MAXKEY 32
-#define MAXIV 32
-
extern char resume_file[];
-/* Local variables that should not be affected by save */
-unsigned int nr_copy_pages __nosavedata = 0;
-
-/* Suspend pagedir is allocated before final copy, therefore it
- must be freed after resume
-
- Warning: this is even more evil than it seems. Pagedirs this file
- talks about are completely different from page directories used by
- MMU hardware.
- */
-suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
-
#define SWSUSP_SIG "S1SUSPEND"
static struct swsusp_header {
- char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)];
- u8 key_iv[MAXKEY+MAXIV];
- swp_entry_t swsusp_info;
+ char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
+ swp_entry_t image;
char orig_sig[10];
char sig[10];
} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
@@ -115,140 +104,9 @@ static struct swsusp_info swsusp_info;
* Saving part...
*/
-/* We memorize in swapfile_used what swap devices are used for suspension */
-#define SWAPFILE_UNUSED 0
-#define SWAPFILE_SUSPEND 1 /* This is the suspending device */
-#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */
-
-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 unsigned short root_swap = 0xffff;
-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)
+static int mark_swapfiles(swp_entry_t start)
{
int error;
@@ -259,8 +117,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;
+ swsusp_header.image = start;
error = rw_swap_page_sync(WRITE,
swp_entry(root_swap, 0),
virt_to_page((unsigned long)
@@ -283,7 +140,7 @@ static int mark_swapfiles(swp_entry_t prev)
* devfs, since the resume code can only recognize the form /dev/hda4,
* but the suspend code would see the long name.)
*/
-static int is_resume_device(const struct swap_info_struct *swap_info)
+static inline int is_resume_device(const struct swap_info_struct *swap_info)
{
struct file *file = swap_info->swap_file;
struct inode *inode = file->f_dentry->d_inode;
@@ -294,54 +151,22 @@ static int is_resume_device(const struct swap_info_struct *swap_info)
static int swsusp_swap_check(void) /* This is called before saving image */
{
- int i, len;
-
- len=strlen(resume_file);
- root_swap = 0xFFFF;
-
- spin_lock(&swap_lock);
- for (i=0; i<MAX_SWAPFILES; i++) {
- if (!(swap_info[i].flags & SWP_WRITEOK)) {
- swapfile_used[i]=SWAPFILE_UNUSED;
- } else {
- if (!len) {
- printk(KERN_WARNING "resume= option should be used to set suspend device" );
- if (root_swap == 0xFFFF) {
- swapfile_used[i] = SWAPFILE_SUSPEND;
- root_swap = i;
- } else
- swapfile_used[i] = SWAPFILE_IGNORED;
- } else {
- /* we ignore all swap devices that are not the resume_file */
- if (is_resume_device(&swap_info[i])) {
- swapfile_used[i] = SWAPFILE_SUSPEND;
- root_swap = i;
- } else {
- swapfile_used[i] = SWAPFILE_IGNORED;
- }
- }
- }
- }
- spin_unlock(&swap_lock);
- return (root_swap != 0xffff) ? 0 : -ENODEV;
-}
-
-/**
- * This is called after saving image so modification
- * will be lost after resume... and that's what we want.
- * we make the device unusable. A new call to
- * lock_swapdevices can unlock the devices.
- */
-static void lock_swapdevices(void)
-{
int i;
+ if (!swsusp_resume_device)
+ return -ENODEV;
spin_lock(&swap_lock);
- for (i = 0; i< MAX_SWAPFILES; i++)
- if (swapfile_used[i] == SWAPFILE_IGNORED) {
- swap_info[i].flags ^= SWP_WRITEOK;
+ for (i = 0; i < MAX_SWAPFILES; i++) {
+ if (!(swap_info[i].flags & SWP_WRITEOK))
+ continue;
+ if (is_resume_device(swap_info + i)) {
+ spin_unlock(&swap_lock);
+ root_swap = i;
+ return 0;
}
+ }
spin_unlock(&swap_lock);
+ return -ENODEV;
}
/**
@@ -359,72 +184,217 @@ static void lock_swapdevices(void)
static int write_page(unsigned long addr, swp_entry_t *loc)
{
swp_entry_t entry;
- int error = 0;
+ int error = -ENOSPC;
- entry = get_swap_page();
- if (swp_offset(entry) &&
- swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
- error = rw_swap_page_sync(WRITE, entry,
- virt_to_page(addr));
- if (error == -EIO)
- error = 0;
- if (!error)
+ entry = get_swap_page_of_type(root_swap);
+ if (swp_offset(entry)) {
+ error = rw_swap_page_sync(WRITE, entry, virt_to_page(addr));
+ if (!error || error == -EIO)
*loc = entry;
- } else
- error = -ENOSPC;
+ }
return error;
}
/**
- * data_free - Free the swap entries used by the saved image.
+ * Swap map-handling functions
+ *
+ * The swap map is a data structure used for keeping track of each page
+ * written to the swap. It consists of many swap_map_page structures
+ * that contain each an array of MAP_PAGE_SIZE swap entries.
+ * These structures are linked together with the help of either the
+ * .next (in memory) or the .next_swap (in swap) member.
*
- * Walk the list of used swap entries and free each one.
- * This is only used for cleanup when suspend fails.
+ * The swap map is created during suspend. At that time we need to keep
+ * it in memory, because we have to free all of the allocated swap
+ * entries if an error occurs. The memory needed is preallocated
+ * so that we know in advance if there's enough of it.
+ *
+ * The first swap_map_page structure is filled with the swap entries that
+ * correspond to the first MAP_PAGE_SIZE data pages written to swap and
+ * so on. After the all of the data pages have been written, the order
+ * of the swap_map_page structures in the map is reversed so that they
+ * can be read from swap in the original order. This causes the data
+ * pages to be loaded in exactly the same order in which they have been
+ * saved.
+ *
+ * During resume we only need to use one swap_map_page structure
+ * at a time, which means that we only need to use two memory pages for
+ * reading the image - one for reading the swap_map_page structures
+ * and the second for reading the data pages from swap.
*/
-static void data_free(void)
+
+#define MAP_PAGE_SIZE ((PAGE_SIZE - sizeof(swp_entry_t) - sizeof(void *)) \
+ / sizeof(swp_entry_t))
+
+struct swap_map_page {
+ swp_entry_t entries[MAP_PAGE_SIZE];
+ swp_entry_t next_swap;
+ struct swap_map_page *next;
+};
+
+static inline void free_swap_map(struct swap_map_page *swap_map)
{
- swp_entry_t entry;
- struct pbe *p;
+ struct swap_map_page *swp;
- for_each_pbe (p, pagedir_nosave) {
- entry = p->swap_address;
- if (entry.val)
- swap_free(entry);
- else
- break;
+ while (swap_map) {
+ swp = swap_map->next;
+ free_page((unsigned long)swap_map);
+ swap_map = swp;
}
}
+static struct swap_map_page *alloc_swap_map(unsigned int nr_pages)
+{
+ struct swap_map_page *swap_map, *swp;
+ unsigned n = 0;
+
+ if (!nr_pages)
+ return NULL;
+
+ pr_debug("alloc_swap_map(): nr_pages = %d\n", nr_pages);
+ swap_map = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
+ swp = swap_map;
+ for (n = MAP_PAGE_SIZE; n < nr_pages; n += MAP_PAGE_SIZE) {
+ swp->next = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
+ swp = swp->next;
+ if (!swp) {
+ free_swap_map(swap_map);
+ return NULL;
+ }
+ }
+ return swap_map;
+}
+
/**
- * data_write - Write saved image to swap.
- *
- * Walk the list of pages in the image and sync each one to swap.
+ * reverse_swap_map - reverse the order of pages in the swap map
+ * @swap_map
*/
-static int data_write(void)
+
+static inline struct swap_map_page *reverse_swap_map(struct swap_map_page *swap_map)
{
- int error = 0, i = 0;
- unsigned int mod = nr_copy_pages / 100;
- struct pbe *p;
- void *tfm;
+ struct swap_map_page *prev, *next;
+
+ prev = NULL;
+ while (swap_map) {
+ next = swap_map->next;
+ swap_map->next = prev;
+ prev = swap_map;
+ swap_map = next;
+ }
+ return prev;
+}
- if ((error = crypto_init(1, &tfm)))
- return error;
+/**
+ * free_swap_map_entries - free the swap entries allocated to store
+ * the swap map @swap_map (this is only called in case of an error)
+ */
+static inline void free_swap_map_entries(struct swap_map_page *swap_map)
+{
+ while (swap_map) {
+ if (swap_map->next_swap.val)
+ swap_free(swap_map->next_swap);
+ swap_map = swap_map->next;
+ }
+}
- if (!mod)
- mod = 1;
+/**
+ * save_swap_map - save the swap map used for tracing the data pages
+ * stored in the swap
+ */
- printk( "Writing data to swap (%d pages)... ", nr_copy_pages );
- for_each_pbe (p, pagedir_nosave) {
- if (!(i%mod))
- printk( "\b\b\b\b%3d%%", i / mod );
- if ((error = crypto_write(p, tfm))) {
- crypto_exit(tfm);
+static int save_swap_map(struct swap_map_page *swap_map, swp_entry_t *start)
+{
+ swp_entry_t entry = (swp_entry_t){0};
+ int error;
+
+ while (swap_map) {
+ swap_map->next_swap = entry;
+ if ((error = write_page((unsigned long)swap_map, &entry)))
return error;
- }
- i++;
+ swap_map = swap_map->next;
}
- printk("\b\b\b\bdone\n");
- crypto_exit(tfm);
+ *start = entry;
+ return 0;
+}
+
+/**
+ * free_image_entries - free the swap entries allocated to store
+ * the image data pages (this is only called in case of an error)
+ */
+
+static inline void free_image_entries(struct swap_map_page *swp)
+{
+ unsigned k;
+
+ while (swp) {
+ for (k = 0; k < MAP_PAGE_SIZE; k++)
+ if (swp->entries[k].val)
+ swap_free(swp->entries[k]);
+ swp = swp->next;
+ }
+}
+
+/**
+ * The swap_map_handle structure is used for handling the swap map in
+ * a file-alike way
+ */
+
+struct swap_map_handle {
+ struct swap_map_page *cur;
+ unsigned int k;
+};
+
+static inline void init_swap_map_handle(struct swap_map_handle *handle,
+ struct swap_map_page *map)
+{
+ handle->cur = map;
+ handle->k = 0;
+}
+
+static inline int swap_map_write_page(struct swap_map_handle *handle,
+ unsigned long addr)
+{
+ int error;
+
+ error = write_page(addr, handle->cur->entries + handle->k);
+ if (error)
+ return error;
+ if (++handle->k >= MAP_PAGE_SIZE) {
+ handle->cur = handle->cur->next;
+ handle->k = 0;
+ }
+ return 0;
+}
+
+/**
+ * save_image_data - save the data pages pointed to by the PBEs
+ * from the list @pblist using the swap map handle @handle
+ * (assume there are @nr_pages data pages to save)
+ */
+
+static int save_image_data(struct pbe *pblist,
+ struct swap_map_handle *handle,
+ unsigned int nr_pages)
+{
+ unsigned int m;
+ struct pbe *p;
+ int error = 0;
+
+ printk("Saving image data pages (%u pages) ... ", nr_pages);
+ m = nr_pages / 100;
+ if (!m)
+ m = 1;
+ nr_pages = 0;
+ for_each_pbe (p, pblist) {
+ error = swap_map_write_page(handle, p->address);
+ if (error)
+ break;
+ if (!(nr_pages % m))
+ printk("\b\b\b\b%3d%%", nr_pages / m);
+ nr_pages++;
+ }
+ if (!error)
+ printk("\b\b\b\bdone\n");
return error;
}
@@ -440,70 +410,70 @@ static void dump_info(void)
pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname);
pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus);
pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages);
- pr_debug(" swsusp: Pagedir: %ld Pages\n",swsusp_info.pagedir_pages);
+ pr_debug(" swsusp: Total: %ld Pages\n", swsusp_info.pages);
}
-static void init_header(void)
+static void init_header(unsigned int nr_pages)
{
memset(&swsusp_info, 0, sizeof(swsusp_info));
swsusp_info.version_code = LINUX_VERSION_CODE;
swsusp_info.num_physpages = num_physpages;
memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname));
- swsusp_info.suspend_pagedir = pagedir_nosave;
swsusp_info.cpus = num_online_cpus();
- swsusp_info.image_pages = nr_copy_pages;
-}
-
-static int close_swap(void)
-{
- swp_entry_t entry;
- int error;
-
- dump_info();
- error = write_page((unsigned long)&swsusp_info, &entry);
- if (!error) {
- printk( "S" );
- error = mark_swapfiles(entry);
- printk( "|\n" );
- }
- return error;
+ swsusp_info.image_pages = nr_pages;
+ swsusp_info.pages = nr_pages +
+ ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
}
/**
- * free_pagedir_entries - Free pages used by the page directory.
- *
- * This is used during suspend for error recovery.
+ * pack_orig_addresses - the .orig_address fields of the PBEs from the
+ * list starting at @pbe are stored in the array @buf[] (1 page)
*/
-static void free_pagedir_entries(void)
+static inline struct pbe *pack_orig_addresses(unsigned long *buf,
+ struct pbe *pbe)
{
- int i;
+ int j;
- for (i = 0; i < swsusp_info.pagedir_pages; i++)
- swap_free(swsusp_info.pagedir[i]);
+ for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) {
+ buf[j] = pbe->orig_address;
+ pbe = pbe->next;
+ }
+ if (!pbe)
+ for (; j < PAGE_SIZE / sizeof(long); j++)
+ buf[j] = 0;
+ return pbe;
}
-
/**
- * write_pagedir - Write the array of pages holding the page directory.
- * @last: Last swap entry we write (needed for header).
+ * save_image_metadata - save the .orig_address fields of the PBEs
+ * from the list @pblist using the swap map handle @handle
*/
-static int write_pagedir(void)
+static int save_image_metadata(struct pbe *pblist,
+ struct swap_map_handle *handle)
{
- int error = 0;
+ unsigned long *buf;
unsigned int n = 0;
- struct pbe *pbe;
+ struct pbe *p;
+ int error = 0;
- printk( "Writing pagedir...");
- for_each_pb_page (pbe, pagedir_nosave) {
- if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++])))
- return error;
+ printk("Saving image metadata ... ");
+ buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC);
+ if (!buf)
+ return -ENOMEM;
+ p = pblist;
+ while (p) {
+ p = pack_orig_addresses(buf, p);
+ error = swap_map_write_page(handle, (unsigned long)buf);
+ if (error)
+ break;
+ n++;
}
-
- swsusp_info.pagedir_pages = n;
- printk("done (%u pages)\n", n);
+ free_page((unsigned long)buf);
+ if (!error)
+ printk("done (%u pages saved)\n", n);
return error;
}
@@ -511,75 +481,125 @@ static int write_pagedir(void)
* enough_swap - Make sure we have enough swap to save the image.
*
* Returns TRUE or FALSE after checking the total amount of swap
- * space avaiable.
- *
- * FIXME: si_swapinfo(&i) returns all swap devices information.
- * We should only consider resume_device.
+ * space avaiable from the resume partition.
*/
static int enough_swap(unsigned int nr_pages)
{
- struct sysinfo i;
+ unsigned int free_swap = swap_info[root_swap].pages -
+ swap_info[root_swap].inuse_pages;
- si_swapinfo(&i);
- pr_debug("swsusp: available swap: %lu pages\n", i.freeswap);
- return i.freeswap > (nr_pages + PAGES_FOR_IO +
+ pr_debug("swsusp: free swap pages: %u\n", free_swap);
+ return free_swap > (nr_pages + PAGES_FOR_IO +
(nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE);
}
/**
- * write_suspend_image - Write entire image and metadata.
+ * swsusp_write - Write entire image and metadata.
*
+ * It is important _NOT_ to umount filesystems at this point. We want
+ * them synced (in case something goes wrong) but we DO not want to mark
+ * filesystem clean: it is not. (And it does not matter, if we resume
+ * correctly, we'll mark system clean, anyway.)
*/
-static int write_suspend_image(void)
+
+int swsusp_write(struct pbe *pblist, unsigned int nr_pages)
{
+ struct swap_map_page *swap_map;
+ struct swap_map_handle handle;
+ swp_entry_t start;
int error;
- if (!enough_swap(nr_copy_pages)) {
+ if ((error = swsusp_swap_check())) {
+ printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n");
+ return error;
+ }
+ if (!enough_swap(nr_pages)) {
printk(KERN_ERR "swsusp: Not enough free swap\n");
return -ENOSPC;
}
- init_header();
- if ((error = data_write()))
- goto FreeData;
+ init_header(nr_pages);
+ swap_map = alloc_swap_map(swsusp_info.pages);
+ if (!swap_map)
+ return -ENOMEM;
+ init_swap_map_handle(&handle, swap_map);
+
+ error = swap_map_write_page(&handle, (unsigned long)&swsusp_info);
+ if (!error)
+ error = save_image_metadata(pblist, &handle);
+ if (!error)
+ error = save_image_data(pblist, &handle, nr_pages);
+ if (error)
+ goto Free_image_entries;
- if ((error = write_pagedir()))
- goto FreePagedir;
+ swap_map = reverse_swap_map(swap_map);
+ error = save_swap_map(swap_map, &start);
+ if (error)
+ goto Free_map_entries;
- if ((error = close_swap()))
- goto FreePagedir;
- Done:
- memset(key_iv, 0, MAXKEY+MAXIV);
+ dump_info();
+ printk( "S" );
+ error = mark_swapfiles(start);
+ printk( "|\n" );
+ if (error)
+ goto Free_map_entries;
+
+Free_swap_map:
+ free_swap_map(swap_map);
return error;
- FreePagedir:
- free_pagedir_entries();
- FreeData:
- data_free();
- goto Done;
+
+Free_map_entries:
+ free_swap_map_entries(swap_map);
+Free_image_entries:
+ free_image_entries(swap_map);
+ goto Free_swap_map;
}
-/* It is important _NOT_ to umount filesystems at this point. We want
- * them synced (in case something goes wrong) but we DO not want to mark
- * filesystem clean: it is not. (And it does not matter, if we resume
- * correctly, we'll mark system clean, anyway.)
+/**
+ * swsusp_shrink_memory - Try to free as much memory as needed
+ *
+ * ... but do not OOM-kill anyone
+ *
+ * Notice: all userland should be stopped before it is called, or
+ * livelock is possible.
*/
-int swsusp_write(void)
-{
- int error;
- if ((error = swsusp_swap_check())) {
- printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n");
- return error;
- }
- lock_swapdevices();
- error = write_suspend_image();
- /* This will unlock ignored swap devices since writing is finished */
- lock_swapdevices();
- return error;
-}
+#define SHRINK_BITE 10000
+int swsusp_shrink_memory(void)
+{
+ long size, tmp;
+ struct zone *zone;
+ unsigned long pages = 0;
+ unsigned int i = 0;
+ char *p = "-\\|/";
+
+ printk("Shrinking memory... ");
+ do {
+ size = 2 * count_highmem_pages();
+ size += size / 50 + count_data_pages();
+ size += (size + PBES_PER_PAGE - 1) / PBES_PER_PAGE +
+ PAGES_FOR_IO;
+ tmp = size;
+ for_each_zone (zone)
+ if (!is_highmem(zone))
+ tmp -= zone->free_pages;
+ if (tmp > 0) {
+ tmp = shrink_all_memory(SHRINK_BITE);
+ if (!tmp)
+ return -ENOMEM;
+ pages += tmp;
+ } else if (size > (image_size * 1024 * 1024) / PAGE_SIZE) {
+ tmp = shrink_all_memory(SHRINK_BITE);
+ pages += tmp;
+ }
+ printk("\b%c", p[i++%4]);
+ } while (tmp > 0);
+ printk("\bdone (%lu pages freed)\n", pages);
+ return 0;
+}
int swsusp_suspend(void)
{
@@ -677,7 +697,6 @@ static void copy_page_backup_list(struct pbe *dst, struct pbe *src)
/* We assume both lists contain the same number of elements */
while (src) {
dst->orig_address = src->orig_address;
- dst->swap_address = src->swap_address;
dst = dst->next;
src = src->next;
}
@@ -757,198 +776,224 @@ static int bio_write_page(pgoff_t page_off, void *page)
return submit(WRITE, page_off, page);
}
-/*
- * Sanity check if this image makes sense with this kernel/swap context
- * I really don't think that it's foolproof but more than nothing..
+/**
+ * The following functions allow us to read data using a swap map
+ * in a file-alike way
*/
-static const char *sanity_check(void)
+static inline void release_swap_map_reader(struct swap_map_handle *handle)
{
- dump_info();
- if (swsusp_info.version_code != LINUX_VERSION_CODE)
- return "kernel version";
- if (swsusp_info.num_physpages != num_physpages)
- return "memory size";
- if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
- return "system type";
- if (strcmp(swsusp_info.uts.release,system_utsname.release))
- return "kernel release";
- if (strcmp(swsusp_info.uts.version,system_utsname.version))
- return "version";
- if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
- return "machine";
-#if 0
- /* 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;
+ if (handle->cur)
+ free_page((unsigned long)handle->cur);
+ handle->cur = NULL;
}
-
-static int check_header(void)
+static inline int get_swap_map_reader(struct swap_map_handle *handle,
+ swp_entry_t start)
{
- const char *reason = NULL;
int error;
- if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
+ if (!swp_offset(start))
+ return -EINVAL;
+ handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC);
+ if (!handle->cur)
+ return -ENOMEM;
+ error = bio_read_page(swp_offset(start), handle->cur);
+ if (error) {
+ release_swap_map_reader(handle);
return error;
-
- /* Is this same machine? */
- if ((reason = sanity_check())) {
- printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason);
- return -EPERM;
}
- nr_copy_pages = swsusp_info.image_pages;
- return error;
+ handle->k = 0;
+ return 0;
}
-static int check_sig(void)
+static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf)
{
+ unsigned long offset;
int error;
- memset(&swsusp_header, 0, sizeof(swsusp_header));
- if ((error = bio_read_page(0, &swsusp_header)))
- 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 {
+ if (!handle->cur)
+ return -EINVAL;
+ offset = swp_offset(handle->cur->entries[handle->k]);
+ if (!offset)
return -EINVAL;
+ error = bio_read_page(offset, buf);
+ if (error)
+ return error;
+ if (++handle->k >= MAP_PAGE_SIZE) {
+ handle->k = 0;
+ offset = swp_offset(handle->cur->next_swap);
+ if (!offset)
+ release_swap_map_reader(handle);
+ else
+ error = bio_read_page(offset, handle->cur);
}
- if (!error)
- pr_debug("swsusp: Signature found, resuming\n");
return error;
}
-/**
- * data_read - Read image pages from swap.
- *
- * You do not need to check for overlaps, check_pagedir()
- * already did that.
- */
-
-static int data_read(struct pbe *pblist)
+static int check_header(void)
{
- struct pbe *p;
- 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;
-
- printk("swsusp: Reading image data (%lu pages): ",
- swsusp_info.image_pages);
-
- for_each_pbe (p, pblist) {
- if (!(i % mod))
- printk("\b\b\b\b%3d%%", i / mod);
+ char *reason = NULL;
- if ((error = crypto_read(p, tfm))) {
- crypto_exit(tfm);
- return error;
- }
-
- i++;
+ dump_info();
+ if (swsusp_info.version_code != LINUX_VERSION_CODE)
+ reason = "kernel version";
+ if (swsusp_info.num_physpages != num_physpages)
+ reason = "memory size";
+ if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
+ reason = "system type";
+ if (strcmp(swsusp_info.uts.release,system_utsname.release))
+ reason = "kernel release";
+ if (strcmp(swsusp_info.uts.version,system_utsname.version))
+ reason = "version";
+ if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
+ reason = "machine";
+ if (reason) {
+ printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason);
+ return -EPERM;
}
- printk("\b\b\b\bdone\n");
- crypto_exit(tfm);
- return error;
+ return 0;
}
/**
- * read_pagedir - Read page backup list pages from swap
+ * load_image_data - load the image data using the swap map handle
+ * @handle and store them using the page backup list @pblist
+ * (assume there are @nr_pages pages to load)
*/
-static int read_pagedir(struct pbe *pblist)
+static int load_image_data(struct pbe *pblist,
+ struct swap_map_handle *handle,
+ unsigned int nr_pages)
{
- struct pbe *pbpage, *p;
- unsigned int i = 0;
int error;
+ unsigned int m;
+ struct pbe *p;
if (!pblist)
- return -EFAULT;
-
- printk("swsusp: Reading pagedir (%lu pages)\n",
- swsusp_info.pagedir_pages);
-
- for_each_pb_page (pbpage, pblist) {
- unsigned long offset = swp_offset(swsusp_info.pagedir[i++]);
-
- error = -EFAULT;
- if (offset) {
- p = (pbpage + PB_PAGE_SKIP)->next;
- error = bio_read_page(offset, (void *)pbpage);
- (pbpage + PB_PAGE_SKIP)->next = p;
- }
+ return -EINVAL;
+ printk("Loading image data pages (%u pages) ... ", nr_pages);
+ m = nr_pages / 100;
+ if (!m)
+ m = 1;
+ nr_pages = 0;
+ p = pblist;
+ while (p) {
+ error = swap_map_read_page(handle, (void *)p->address);
if (error)
break;
+ p = p->next;
+ if (!(nr_pages % m))
+ printk("\b\b\b\b%3d%%", nr_pages / m);
+ nr_pages++;
}
-
if (!error)
- BUG_ON(i != swsusp_info.pagedir_pages);
-
+ printk("\b\b\b\bdone\n");
return error;
}
+/**
+ * unpack_orig_addresses - copy the elements of @buf[] (1 page) to
+ * the PBEs in the list starting at @pbe
+ */
-static int check_suspend_image(void)
+static inline struct pbe *unpack_orig_addresses(unsigned long *buf,
+ struct pbe *pbe)
{
- int error = 0;
+ int j;
- if ((error = check_sig()))
- return error;
-
- if ((error = check_header()))
- return error;
-
- return 0;
+ for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) {
+ pbe->orig_address = buf[j];
+ pbe = pbe->next;
+ }
+ return pbe;
}
-static int read_suspend_image(void)
+/**
+ * load_image_metadata - load the image metadata using the swap map
+ * handle @handle and put them into the PBEs in the list @pblist
+ */
+
+static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handle)
{
- int error = 0;
struct pbe *p;
+ unsigned long *buf;
+ unsigned int n = 0;
+ int error = 0;
- if (!(p = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 0)))
+ printk("Loading image metadata ... ");
+ buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC);
+ if (!buf)
return -ENOMEM;
-
- if ((error = read_pagedir(p)))
- return error;
- create_pbe_list(p, nr_copy_pages);
- mark_unsafe_pages(p);
- pagedir_nosave = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
- if (pagedir_nosave) {
- create_pbe_list(pagedir_nosave, nr_copy_pages);
- copy_page_backup_list(pagedir_nosave, p);
+ p = pblist;
+ while (p) {
+ error = swap_map_read_page(handle, buf);
+ if (error)
+ break;
+ p = unpack_orig_addresses(buf, p);
+ n++;
}
- free_pagedir(p);
- if (!pagedir_nosave)
- return -ENOMEM;
+ free_page((unsigned long)buf);
+ if (!error)
+ printk("done (%u pages loaded)\n", n);
+ return error;
+}
- /* Allocate memory for the image and read the data from swap */
+int swsusp_read(struct pbe **pblist_ptr)
+{
+ int error;
+ struct pbe *p, *pblist;
+ struct swap_map_handle handle;
+ unsigned int nr_pages;
- error = alloc_data_pages(pagedir_nosave, GFP_ATOMIC, 1);
+ if (IS_ERR(resume_bdev)) {
+ pr_debug("swsusp: block device not initialised\n");
+ return PTR_ERR(resume_bdev);
+ }
+ error = get_swap_map_reader(&handle, swsusp_header.image);
if (!error)
- error = data_read(pagedir_nosave);
+ error = swap_map_read_page(&handle, &swsusp_info);
+ if (!error)
+ error = check_header();
+ if (error)
+ return error;
+ nr_pages = swsusp_info.image_pages;
+ p = alloc_pagedir(nr_pages, GFP_ATOMIC, 0);
+ if (!p)
+ return -ENOMEM;
+ error = load_image_metadata(p, &handle);
+ if (!error) {
+ mark_unsafe_pages(p);
+ pblist = alloc_pagedir(nr_pages, GFP_ATOMIC, 1);
+ if (pblist)
+ copy_page_backup_list(pblist, p);
+ free_pagedir(p);
+ if (!pblist)
+ error = -ENOMEM;
+
+ /* Allocate memory for the image and read the data from swap */
+ if (!error)
+ error = alloc_data_pages(pblist, GFP_ATOMIC, 1);
+ if (!error) {
+ release_eaten_pages();
+ error = load_image_data(pblist, &handle, nr_pages);
+ }
+ if (!error)
+ *pblist_ptr = pblist;
+ }
+ release_swap_map_reader(&handle);
+ blkdev_put(resume_bdev);
+
+ if (!error)
+ pr_debug("swsusp: Reading resume file was successful\n");
+ else
+ pr_debug("swsusp: Error %d resuming\n", error);
return error;
}
/**
- * swsusp_check - Check for saved image in swap
+ * swsusp_check - Check for swsusp signature in the resume device
*/
int swsusp_check(void)
@@ -958,40 +1003,27 @@ int swsusp_check(void)
resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
if (!IS_ERR(resume_bdev)) {
set_blocksize(resume_bdev, PAGE_SIZE);
- error = check_suspend_image();
+ memset(&swsusp_header, 0, sizeof(swsusp_header));
+ if ((error = bio_read_page(0, &swsusp_header)))
+ return error;
+ if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
+ memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
+ /* Reset swap signature now */
+ error = bio_write_page(0, &swsusp_header);
+ } else {
+ return -EINVAL;
+ }
if (error)
- blkdev_put(resume_bdev);
- } else
+ blkdev_put(resume_bdev);
+ else
+ pr_debug("swsusp: Signature found, resuming\n");
+ } else {
error = PTR_ERR(resume_bdev);
-
- if (!error)
- pr_debug("swsusp: resume file found\n");
- else
- pr_debug("swsusp: Error %d check for resume file\n", error);
- return error;
-}
-
-/**
- * swsusp_read - Read saved image from swap.
- */
-
-int swsusp_read(void)
-{
- int error;
-
- if (IS_ERR(resume_bdev)) {
- pr_debug("swsusp: block device not initialised\n");
- return PTR_ERR(resume_bdev);
}
- error = read_suspend_image();
- blkdev_put(resume_bdev);
- memset(key_iv, 0, MAXKEY+MAXIV);
+ if (error)
+ pr_debug("swsusp: Error %d check for resume file\n", error);
- if (!error)
- pr_debug("swsusp: Reading resume file was successful\n");
- else
- pr_debug("swsusp: Error %d resuming\n", error);
return error;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index 5287be83e3e7..13ced0f7828f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -11,7 +11,7 @@
* Ted Ts'o, 2/11/93.
* Modified for sysctl support, 1/8/97, Chris Horn.
* Fixed SMP synchronization, 08/08/99, Manfred Spraul
- * manfreds@colorfullife.com
+ * manfred@colorfullife.com
* Rewrote bits to get rid of console_lock
* 01Mar01 Andrew Morton <andrewm@uow.edu.au>
*/
@@ -569,7 +569,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
p[1] <= '7' && p[2] == '>') {
loglev_char = p[1];
p += 3;
- printed_len += 3;
+ printed_len -= 3;
} else {
loglev_char = default_message_loglevel
+ '0';
@@ -584,7 +584,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
for (tp = tbuf; tp < tbuf + tlen; tp++)
emit_log_char(*tp);
- printed_len += tlen - 3;
+ printed_len += tlen;
} else {
if (p[0] != '<' || p[1] < '0' ||
p[1] > '7' || p[2] != '>') {
@@ -592,8 +592,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
emit_log_char(default_message_loglevel
+ '0');
emit_log_char('>');
+ printed_len += 3;
}
- printed_len += 3;
}
log_level_unknown = 0;
if (!*p)
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 656476eedb1b..5f33cdb6fff5 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -7,6 +7,7 @@
* to continually duplicate across every architecture.
*/
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/errno.h>
@@ -408,54 +409,62 @@ int ptrace_request(struct task_struct *child, long request,
return ret;
}
-#ifndef __ARCH_SYS_PTRACE
-static int ptrace_get_task_struct(long request, long pid,
- struct task_struct **childp)
+/**
+ * ptrace_traceme -- helper for PTRACE_TRACEME
+ *
+ * Performs checks and sets PT_PTRACED.
+ * Should be used by all ptrace implementations for PTRACE_TRACEME.
+ */
+int ptrace_traceme(void)
{
- struct task_struct *child;
int ret;
/*
- * Callers use child == NULL as an indication to exit early even
- * when the return value is 0, so make sure it is non-NULL here.
+ * Are we already being traced?
+ */
+ if (current->ptrace & PT_PTRACED)
+ return -EPERM;
+ ret = security_ptrace(current->parent, current);
+ if (ret)
+ return -EPERM;
+ /*
+ * Set the ptrace bit in the process ptrace flags.
*/
- *childp = NULL;
+ current->ptrace |= PT_PTRACED;
+ return 0;
+}
- if (request == PTRACE_TRACEME) {
- /*
- * Are we already being traced?
- */
- if (current->ptrace & PT_PTRACED)
- return -EPERM;
- ret = security_ptrace(current->parent, current);
- if (ret)
- return -EPERM;
- /*
- * Set the ptrace bit in the process ptrace flags.
- */
- current->ptrace |= PT_PTRACED;
- return 0;
- }
+/**
+ * ptrace_get_task_struct -- grab a task struct reference for ptrace
+ * @pid: process id to grab a task_struct reference of
+ *
+ * This function is a helper for ptrace implementations. It checks
+ * permissions and then grabs a task struct for use of the actual
+ * ptrace implementation.
+ *
+ * Returns the task_struct for @pid or an ERR_PTR() on failure.
+ */
+struct task_struct *ptrace_get_task_struct(pid_t pid)
+{
+ struct task_struct *child;
/*
- * You may not mess with init
+ * Tracing init is not allowed.
*/
if (pid == 1)
- return -EPERM;
+ return ERR_PTR(-EPERM);
- ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
- return -ESRCH;
-
- *childp = child;
- return 0;
+ return ERR_PTR(-ESRCH);
+ return child;
}
+#ifndef __ARCH_SYS_PTRACE
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -465,9 +474,16 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
* This lock_kernel fixes a subtle race with suid exec
*/
lock_kernel();
- ret = ptrace_get_task_struct(request, pid, &child);
- if (!child)
+ if (request == PTRACE_TRACEME) {
+ ret = ptrace_traceme();
goto out;
+ }
+
+ child = ptrace_get_task_struct(pid);
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
+ goto out;
+ }
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 48d3bce465b8..0cf8146bd585 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/smp.h>
+#include <linux/rcupdate.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/atomic.h>
@@ -45,26 +46,21 @@
#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. */
-struct rcu_ctrlblk rcu_ctrlblk =
- { .cur = -300, .completed = -300 };
-struct rcu_ctrlblk rcu_bh_ctrlblk =
- { .cur = -300, .completed = -300 };
-
-/* Bookkeeping of the progress of the grace period */
-struct rcu_state {
- spinlock_t lock; /* Guard this struct and writes to rcu_ctrlblk */
- cpumask_t cpumask; /* CPUs that need to switch in order */
- /* for current batch to proceed. */
+struct rcu_ctrlblk rcu_ctrlblk = {
+ .cur = -300,
+ .completed = -300,
+ .lock = SPIN_LOCK_UNLOCKED,
+ .cpumask = CPU_MASK_NONE,
+};
+struct rcu_ctrlblk rcu_bh_ctrlblk = {
+ .cur = -300,
+ .completed = -300,
+ .lock = SPIN_LOCK_UNLOCKED,
+ .cpumask = CPU_MASK_NONE,
};
-
-static struct rcu_state rcu_state ____cacheline_maxaligned_in_smp =
- {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
-static struct rcu_state rcu_bh_state ____cacheline_maxaligned_in_smp =
- {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
@@ -73,19 +69,6 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
static int maxbatch = 10000;
-#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.
@@ -233,13 +216,13 @@ static void rcu_do_batch(struct rcu_data *rdp)
* This is done by rcu_start_batch. The start is not broadcasted to
* all cpus, they must pick this up by comparing rcp->cur with
* rdp->quiescbatch. All cpus are recorded in the
- * rcu_state.cpumask bitmap.
+ * rcu_ctrlblk.cpumask bitmap.
* - All cpus must go through a quiescent state.
* Since the start of the grace period is not broadcasted, at least two
* calls to rcu_check_quiescent_state are required:
* The first call just notices that a new grace period is running. The
* following calls check if there was a quiescent state since the beginning
- * of the grace period. If so, it updates rcu_state.cpumask. If
+ * of the grace period. If so, it updates rcu_ctrlblk.cpumask. If
* the bitmap is empty, then the grace period is completed.
* rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace
* period (if necessary).
@@ -247,14 +230,10 @@ static void rcu_do_batch(struct rcu_data *rdp)
/*
* Register a new batch of callbacks, and start it up if there is currently no
* active batch and the batch to be registered has not already occurred.
- * Caller must hold rcu_state.lock.
+ * Caller must hold rcu_ctrlblk.lock.
*/
-static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
- int next_pending)
+static void rcu_start_batch(struct rcu_ctrlblk *rcp)
{
- if (next_pending)
- rcp->next_pending = 1;
-
if (rcp->next_pending &&
rcp->completed == rcp->cur) {
rcp->next_pending = 0;
@@ -268,11 +247,11 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
/*
* Accessing nohz_cpu_mask before incrementing rcp->cur needs a
* Barrier Otherwise it can cause tickless idle CPUs to be
- * included in rsp->cpumask, which will extend graceperiods
+ * included in rcp->cpumask, which will extend graceperiods
* unnecessarily.
*/
smp_mb();
- cpus_andnot(rsp->cpumask, cpu_online_map, nohz_cpu_mask);
+ cpus_andnot(rcp->cpumask, cpu_online_map, nohz_cpu_mask);
}
}
@@ -282,13 +261,13 @@ static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
* Clear it from the cpu mask and complete the grace period if it was the last
* cpu. Start another grace period if someone has further entries pending
*/
-static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
+static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp)
{
- cpu_clear(cpu, rsp->cpumask);
- if (cpus_empty(rsp->cpumask)) {
+ cpu_clear(cpu, rcp->cpumask);
+ if (cpus_empty(rcp->cpumask)) {
/* batch completed ! */
rcp->completed = rcp->cur;
- rcu_start_batch(rcp, rsp, 0);
+ rcu_start_batch(rcp);
}
}
@@ -298,7 +277,7 @@ static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
* quiescent cycle, then indicate that it has done so.
*/
static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,
- struct rcu_state *rsp, struct rcu_data *rdp)
+ struct rcu_data *rdp)
{
if (rdp->quiescbatch != rcp->cur) {
/* start new grace period: */
@@ -323,15 +302,15 @@ static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,
return;
rdp->qs_pending = 0;
- spin_lock(&rsp->lock);
+ spin_lock(&rcp->lock);
/*
* rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync
* during cpu startup. Ignore the quiescent state.
*/
if (likely(rdp->quiescbatch == rcp->cur))
- cpu_quiet(rdp->cpu, rcp, rsp);
+ cpu_quiet(rdp->cpu, rcp);
- spin_unlock(&rsp->lock);
+ spin_unlock(&rcp->lock);
}
@@ -352,28 +331,29 @@ static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list,
}
static void __rcu_offline_cpu(struct rcu_data *this_rdp,
- struct rcu_ctrlblk *rcp, struct rcu_state *rsp, struct rcu_data *rdp)
+ struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
{
/* if the cpu going offline owns the grace period
* we can block indefinitely waiting for it, so flush
* it here
*/
- spin_lock_bh(&rsp->lock);
+ spin_lock_bh(&rcp->lock);
if (rcp->cur != rcp->completed)
- cpu_quiet(rdp->cpu, rcp, rsp);
- spin_unlock_bh(&rsp->lock);
+ cpu_quiet(rdp->cpu, rcp);
+ spin_unlock_bh(&rcp->lock);
rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail);
rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);
-
+ rcu_move_batch(this_rdp, rdp->donelist, rdp->donetail);
}
+
static void rcu_offline_cpu(int cpu)
{
struct rcu_data *this_rdp = &get_cpu_var(rcu_data);
struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data);
- __rcu_offline_cpu(this_rdp, &rcu_ctrlblk, &rcu_state,
+ __rcu_offline_cpu(this_rdp, &rcu_ctrlblk,
&per_cpu(rcu_data, cpu));
- __rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, &rcu_bh_state,
+ __rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk,
&per_cpu(rcu_bh_data, cpu));
put_cpu_var(rcu_data);
put_cpu_var(rcu_bh_data);
@@ -392,7 +372,7 @@ static void rcu_offline_cpu(int cpu)
* This does the RCU processing work from tasklet context.
*/
static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
- struct rcu_state *rsp, struct rcu_data *rdp)
+ struct rcu_data *rdp)
{
if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) {
*rdp->donetail = rdp->curlist;
@@ -422,24 +402,53 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
if (!rcp->next_pending) {
/* and start it/schedule start if it's a new batch */
- spin_lock(&rsp->lock);
- rcu_start_batch(rcp, rsp, 1);
- spin_unlock(&rsp->lock);
+ spin_lock(&rcp->lock);
+ rcp->next_pending = 1;
+ rcu_start_batch(rcp);
+ spin_unlock(&rcp->lock);
}
} else {
local_irq_enable();
}
- rcu_check_quiescent_state(rcp, rsp, rdp);
+ rcu_check_quiescent_state(rcp, rdp);
if (rdp->donelist)
rcu_do_batch(rdp);
}
static void rcu_process_callbacks(unsigned long unused)
{
- __rcu_process_callbacks(&rcu_ctrlblk, &rcu_state,
- &__get_cpu_var(rcu_data));
- __rcu_process_callbacks(&rcu_bh_ctrlblk, &rcu_bh_state,
- &__get_cpu_var(rcu_bh_data));
+ __rcu_process_callbacks(&rcu_ctrlblk, &__get_cpu_var(rcu_data));
+ __rcu_process_callbacks(&rcu_bh_ctrlblk, &__get_cpu_var(rcu_bh_data));
+}
+
+static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
+{
+ /* This cpu has pending rcu entries and the grace period
+ * for them has completed.
+ */
+ if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch))
+ return 1;
+
+ /* This cpu has no pending entries, but there are new entries */
+ if (!rdp->curlist && rdp->nxtlist)
+ return 1;
+
+ /* This cpu has finished callbacks to invoke */
+ if (rdp->donelist)
+ return 1;
+
+ /* The rcu core waits for a quiescent state from the cpu */
+ if (rdp->quiescbatch != rcp->cur || rdp->qs_pending)
+ return 1;
+
+ /* nothing to do */
+ return 0;
+}
+
+int rcu_pending(int cpu)
+{
+ return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
+ __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
}
void rcu_check_callbacks(int cpu, int user)
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 49fbbeff201c..773219907dd8 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -39,7 +39,6 @@
#include <linux/moduleparam.h>
#include <linux/percpu.h>
#include <linux/notifier.h>
-#include <linux/rcuref.h>
#include <linux/cpu.h>
#include <linux/random.h>
#include <linux/delay.h>
@@ -49,9 +48,11 @@
MODULE_LICENSE("GPL");
static int nreaders = -1; /* # reader threads, defaults to 4*ncpus */
-static int stat_interval = 0; /* Interval between stats, in seconds. */
+static int stat_interval; /* Interval between stats, in seconds. */
/* Defaults to "only at end of test". */
-static int verbose = 0; /* Print more debug info. */
+static int verbose; /* Print more debug info. */
+static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
+static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/
MODULE_PARM(nreaders, "i");
MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
@@ -59,6 +60,10 @@ MODULE_PARM(stat_interval, "i");
MODULE_PARM_DESC(stat_interval, "Number of seconds between stats printk()s");
MODULE_PARM(verbose, "i");
MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
+MODULE_PARM(test_no_idle_hz, "i");
+MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
+MODULE_PARM(shuffle_interval, "i");
+MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
#define TORTURE_FLAG "rcutorture: "
#define PRINTK_STRING(s) \
do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
@@ -73,6 +78,7 @@ static int nrealreaders;
static struct task_struct *writer_task;
static struct task_struct **reader_tasks;
static struct task_struct *stats_task;
+static struct task_struct *shuffler_task;
#define RCU_TORTURE_PIPE_LEN 10
@@ -103,7 +109,7 @@ atomic_t n_rcu_torture_error;
/*
* Allocate an element from the rcu_tortures pool.
*/
-struct rcu_torture *
+static struct rcu_torture *
rcu_torture_alloc(void)
{
struct list_head *p;
@@ -376,12 +382,77 @@ rcu_torture_stats(void *arg)
return 0;
}
+static int rcu_idle_cpu; /* Force all torture tasks off this CPU */
+
+/* Shuffle tasks such that we allow @rcu_idle_cpu to become idle. A special case
+ * is when @rcu_idle_cpu = -1, when we allow the tasks to run on all CPUs.
+ */
+void rcu_torture_shuffle_tasks(void)
+{
+ cpumask_t tmp_mask = CPU_MASK_ALL;
+ int i;
+
+ lock_cpu_hotplug();
+
+ /* No point in shuffling if there is only one online CPU (ex: UP) */
+ if (num_online_cpus() == 1) {
+ unlock_cpu_hotplug();
+ return;
+ }
+
+ if (rcu_idle_cpu != -1)
+ cpu_clear(rcu_idle_cpu, tmp_mask);
+
+ set_cpus_allowed(current, tmp_mask);
+
+ if (reader_tasks != NULL) {
+ for (i = 0; i < nrealreaders; i++)
+ if (reader_tasks[i])
+ set_cpus_allowed(reader_tasks[i], tmp_mask);
+ }
+
+ if (writer_task)
+ set_cpus_allowed(writer_task, tmp_mask);
+
+ if (stats_task)
+ set_cpus_allowed(stats_task, tmp_mask);
+
+ if (rcu_idle_cpu == -1)
+ rcu_idle_cpu = num_online_cpus() - 1;
+ else
+ rcu_idle_cpu--;
+
+ unlock_cpu_hotplug();
+}
+
+/* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
+ * system to become idle at a time and cut off its timer ticks. This is meant
+ * to test the support for such tickless idle CPU in RCU.
+ */
+static int
+rcu_torture_shuffle(void *arg)
+{
+ VERBOSE_PRINTK_STRING("rcu_torture_shuffle task started");
+ do {
+ schedule_timeout_interruptible(shuffle_interval * HZ);
+ rcu_torture_shuffle_tasks();
+ } while (!kthread_should_stop());
+ VERBOSE_PRINTK_STRING("rcu_torture_shuffle task stopping");
+ return 0;
+}
+
static void
rcu_torture_cleanup(void)
{
int i;
fullstop = 1;
+ if (shuffler_task != NULL) {
+ VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
+ kthread_stop(shuffler_task);
+ }
+ shuffler_task = NULL;
+
if (writer_task != NULL) {
VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
kthread_stop(writer_task);
@@ -430,9 +501,11 @@ rcu_torture_init(void)
nrealreaders = nreaders;
else
nrealreaders = 2 * num_online_cpus();
- printk(KERN_ALERT TORTURE_FLAG
- "--- Start of test: nreaders=%d stat_interval=%d verbose=%d\n",
- nrealreaders, stat_interval, verbose);
+ printk(KERN_ALERT TORTURE_FLAG "--- Start of test: nreaders=%d "
+ "stat_interval=%d verbose=%d test_no_idle_hz=%d "
+ "shuffle_interval = %d\n",
+ nrealreaders, stat_interval, verbose, test_no_idle_hz,
+ shuffle_interval);
fullstop = 0;
/* Set up the freelist. */
@@ -502,6 +575,18 @@ rcu_torture_init(void)
goto unwind;
}
}
+ if (test_no_idle_hz) {
+ rcu_idle_cpu = num_online_cpus() - 1;
+ /* Create the shuffler thread */
+ shuffler_task = kthread_run(rcu_torture_shuffle, NULL,
+ "rcu_torture_shuffle");
+ if (IS_ERR(shuffler_task)) {
+ firsterr = PTR_ERR(shuffler_task);
+ VERBOSE_PRINTK_ERRSTRING("Failed to create shuffler");
+ shuffler_task = NULL;
+ goto unwind;
+ }
+ }
return 0;
unwind:
diff --git a/kernel/resource.c b/kernel/resource.c
index 92285d822de6..e3080fcc66a3 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -464,7 +464,7 @@ struct resource * __request_region(struct resource *parent, unsigned long start,
EXPORT_SYMBOL(__request_region);
-int __deprecated __check_region(struct resource *parent, unsigned long start, unsigned long n)
+int __check_region(struct resource *parent, unsigned long start, unsigned long n)
{
struct resource * res;
diff --git a/kernel/sched.c b/kernel/sched.c
index 6f46c94cc29e..3ee2ae45125f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -27,12 +27,14 @@
#include <linux/smp_lock.h>
#include <asm/mmu_context.h>
#include <linux/interrupt.h>
+#include <linux/capability.h>
#include <linux/completion.h>
#include <linux/kernel_stat.h>
#include <linux/security.h>
#include <linux/notifier.h>
#include <linux/profile.h>
#include <linux/suspend.h>
+#include <linux/vmalloc.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/smp.h>
@@ -176,6 +178,13 @@ static unsigned int task_timeslice(task_t *p)
#define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran) \
< (long long) (sd)->cache_hot_time)
+void __put_task_struct_cb(struct rcu_head *rhp)
+{
+ __put_task_struct(container_of(rhp, struct task_struct, rcu));
+}
+
+EXPORT_SYMBOL_GPL(__put_task_struct_cb);
+
/*
* These are the runqueue data structures:
*/
@@ -512,7 +521,7 @@ static inline void sched_info_dequeued(task_t *t)
* long it was waiting to run. We also note when it began so that we
* can keep stats on how long its timeslice is.
*/
-static inline void sched_info_arrive(task_t *t)
+static void sched_info_arrive(task_t *t)
{
unsigned long now = jiffies, diff = 0;
struct runqueue *rq = task_rq(t);
@@ -739,10 +748,14 @@ static int recalc_task_prio(task_t *p, unsigned long long now)
unsigned long long __sleep_time = now - p->timestamp;
unsigned long sleep_time;
- if (__sleep_time > NS_MAX_SLEEP_AVG)
- sleep_time = NS_MAX_SLEEP_AVG;
- else
- sleep_time = (unsigned long)__sleep_time;
+ if (unlikely(p->policy == SCHED_BATCH))
+ sleep_time = 0;
+ else {
+ if (__sleep_time > NS_MAX_SLEEP_AVG)
+ sleep_time = NS_MAX_SLEEP_AVG;
+ else
+ sleep_time = (unsigned long)__sleep_time;
+ }
if (likely(sleep_time > 0)) {
/*
@@ -994,7 +1007,7 @@ void kick_process(task_t *p)
* We want to under-estimate the load of migration sources, to
* balance conservatively.
*/
-static inline unsigned long __source_load(int cpu, int type, enum idle_type idle)
+static unsigned long __source_load(int cpu, int type, enum idle_type idle)
{
runqueue_t *rq = cpu_rq(cpu);
unsigned long running = rq->nr_running;
@@ -1281,6 +1294,9 @@ static int try_to_wake_up(task_t *p, unsigned int state, int sync)
}
}
+ if (p->last_waker_cpu != this_cpu)
+ goto out_set_cpu;
+
if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
goto out_set_cpu;
@@ -1351,6 +1367,8 @@ out_set_cpu:
cpu = task_cpu(p);
}
+ p->last_waker_cpu = this_cpu;
+
out_activate:
#endif /* CONFIG_SMP */
if (old_state == TASK_UNINTERRUPTIBLE) {
@@ -1432,9 +1450,12 @@ void fastcall sched_fork(task_t *p, int clone_flags)
#ifdef CONFIG_SCHEDSTATS
memset(&p->sched_info, 0, sizeof(p->sched_info));
#endif
-#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+#if defined(CONFIG_SMP)
+ p->last_waker_cpu = cpu;
+#if defined(__ARCH_WANT_UNLOCKED_CTXSW)
p->oncpu = 0;
#endif
+#endif
#ifdef CONFIG_PREEMPT
/* Want to start with kernel preemption disabled. */
task_thread_info(p)->preempt_count = 1;
@@ -1849,7 +1870,7 @@ void sched_exec(void)
* pull_task - move a task from a remote runqueue to the local runqueue.
* Both runqueues must be locked.
*/
-static inline
+static
void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
runqueue_t *this_rq, prio_array_t *this_array, int this_cpu)
{
@@ -1871,7 +1892,7 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
/*
* can_migrate_task - may task p from runqueue rq be migrated to this_cpu?
*/
-static inline
+static
int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
struct sched_domain *sd, enum idle_type idle,
int *all_pinned)
@@ -2357,7 +2378,7 @@ out_balanced:
* idle_balance is called by schedule() if this_cpu is about to become
* idle. Attempts to pull tasks from other CPUs.
*/
-static inline void idle_balance(int this_cpu, runqueue_t *this_rq)
+static void idle_balance(int this_cpu, runqueue_t *this_rq)
{
struct sched_domain *sd;
@@ -2741,7 +2762,7 @@ static inline void wakeup_busy_runqueue(runqueue_t *rq)
resched_task(rq->idle);
}
-static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
+static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
{
struct sched_domain *tmp, *sd = NULL;
cpumask_t sibling_map;
@@ -2795,7 +2816,7 @@ 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)
+static int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
{
struct sched_domain *tmp, *sd = NULL;
cpumask_t sibling_map;
@@ -3543,7 +3564,7 @@ void set_user_nice(task_t *p, long nice)
* The RT priorities are set via sched_setscheduler(), but we still
* allow the 'normal' nice value to be set - but as expected
* it wont have any effect on scheduling until the task is
- * not SCHED_NORMAL:
+ * not SCHED_NORMAL/SCHED_BATCH:
*/
if (rt_task(p)) {
p->static_prio = NICE_TO_PRIO(nice);
@@ -3689,10 +3710,16 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
BUG_ON(p->array);
p->policy = policy;
p->rt_priority = prio;
- if (policy != SCHED_NORMAL)
+ if (policy != SCHED_NORMAL && policy != SCHED_BATCH) {
p->prio = MAX_RT_PRIO-1 - p->rt_priority;
- else
+ } else {
p->prio = p->static_prio;
+ /*
+ * SCHED_BATCH tasks are treated as perpetual CPU hogs:
+ */
+ if (policy == SCHED_BATCH)
+ p->sleep_avg = 0;
+ }
}
/**
@@ -3716,29 +3743,35 @@ recheck:
if (policy < 0)
policy = oldpolicy = p->policy;
else if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_NORMAL)
- return -EINVAL;
+ policy != SCHED_NORMAL && policy != SCHED_BATCH)
+ return -EINVAL;
/*
* Valid priorities for SCHED_FIFO and SCHED_RR are
- * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL is 0.
+ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
+ * SCHED_BATCH is 0.
*/
if (param->sched_priority < 0 ||
(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))
+ if ((policy == SCHED_NORMAL || policy == SCHED_BATCH)
+ != (param->sched_priority == 0))
return -EINVAL;
/*
* Allow unprivileged RT tasks to decrease priority:
*/
if (!capable(CAP_SYS_NICE)) {
- /* can't change policy */
- if (policy != p->policy &&
- !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
+ /*
+ * can't change policy, except between SCHED_NORMAL
+ * and SCHED_BATCH:
+ */
+ if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
+ (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
+ !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
return -EPERM;
/* can't increase priority */
- if (policy != SCHED_NORMAL &&
+ if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
param->sched_priority > p->rt_priority &&
param->sched_priority >
p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
@@ -3817,6 +3850,10 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
struct sched_param __user *param)
{
+ /* negative values for policy are not valid */
+ if (policy < 0)
+ return -EINVAL;
+
return do_sched_setscheduler(pid, policy, param);
}
@@ -3972,12 +4009,12 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
* method, such as ACPI for e.g.
*/
-cpumask_t cpu_present_map;
+cpumask_t cpu_present_map __read_mostly;
EXPORT_SYMBOL(cpu_present_map);
#ifndef CONFIG_SMP
-cpumask_t cpu_online_map = CPU_MASK_ALL;
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
+cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;
#endif
long sched_getaffinity(pid_t pid, cpumask_t *mask)
@@ -4216,6 +4253,7 @@ asmlinkage long sys_sched_get_priority_max(int policy)
ret = MAX_USER_RT_PRIO-1;
break;
case SCHED_NORMAL:
+ case SCHED_BATCH:
ret = 0;
break;
}
@@ -4239,6 +4277,7 @@ asmlinkage long sys_sched_get_priority_min(int policy)
ret = 1;
break;
case SCHED_NORMAL:
+ case SCHED_BATCH:
ret = 0;
}
return ret;
@@ -4379,6 +4418,7 @@ void show_state(void)
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
+ mutex_debug_show_all_locks();
}
/**
@@ -5073,7 +5113,470 @@ static void init_sched_build_groups(struct sched_group groups[], cpumask_t span,
#define SD_NODES_PER_DOMAIN 16
+/*
+ * Self-tuning task migration cost measurement between source and target CPUs.
+ *
+ * This is done by measuring the cost of manipulating buffers of varying
+ * sizes. For a given buffer-size here are the steps that are taken:
+ *
+ * 1) the source CPU reads+dirties a shared buffer
+ * 2) the target CPU reads+dirties the same shared buffer
+ *
+ * We measure how long they take, in the following 4 scenarios:
+ *
+ * - source: CPU1, target: CPU2 | cost1
+ * - source: CPU2, target: CPU1 | cost2
+ * - source: CPU1, target: CPU1 | cost3
+ * - source: CPU2, target: CPU2 | cost4
+ *
+ * We then calculate the cost3+cost4-cost1-cost2 difference - this is
+ * the cost of migration.
+ *
+ * We then start off from a small buffer-size and iterate up to larger
+ * buffer sizes, in 5% steps - measuring each buffer-size separately, and
+ * doing a maximum search for the cost. (The maximum cost for a migration
+ * normally occurs when the working set size is around the effective cache
+ * size.)
+ */
+#define SEARCH_SCOPE 2
+#define MIN_CACHE_SIZE (64*1024U)
+#define DEFAULT_CACHE_SIZE (5*1024*1024U)
+#define ITERATIONS 2
+#define SIZE_THRESH 130
+#define COST_THRESH 130
+
+/*
+ * The migration cost is a function of 'domain distance'. Domain
+ * distance is the number of steps a CPU has to iterate down its
+ * domain tree to share a domain with the other CPU. The farther
+ * two CPUs are from each other, the larger the distance gets.
+ *
+ * Note that we use the distance only to cache measurement results,
+ * the distance value is not used numerically otherwise. When two
+ * CPUs have the same distance it is assumed that the migration
+ * cost is the same. (this is a simplification but quite practical)
+ */
+#define MAX_DOMAIN_DISTANCE 32
+
+static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
+ { [ 0 ... MAX_DOMAIN_DISTANCE-1 ] = -1LL };
+
+/*
+ * Allow override of migration cost - in units of microseconds.
+ * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
+ * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
+ */
+static int __init migration_cost_setup(char *str)
+{
+ int ints[MAX_DOMAIN_DISTANCE+1], i;
+
+ str = get_options(str, ARRAY_SIZE(ints), ints);
+
+ printk("#ints: %d\n", ints[0]);
+ for (i = 1; i <= ints[0]; i++) {
+ migration_cost[i-1] = (unsigned long long)ints[i]*1000;
+ printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
+ }
+ return 1;
+}
+
+__setup ("migration_cost=", migration_cost_setup);
+
+/*
+ * Global multiplier (divisor) for migration-cutoff values,
+ * in percentiles. E.g. use a value of 150 to get 1.5 times
+ * longer cache-hot cutoff times.
+ *
+ * (We scale it from 100 to 128 to long long handling easier.)
+ */
+
+#define MIGRATION_FACTOR_SCALE 128
+
+static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
+
+static int __init setup_migration_factor(char *str)
+{
+ get_option(&str, &migration_factor);
+ migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
+ return 1;
+}
+
+__setup("migration_factor=", setup_migration_factor);
+
+/*
+ * Estimated distance of two CPUs, measured via the number of domains
+ * we have to pass for the two CPUs to be in the same span:
+ */
+static unsigned long domain_distance(int cpu1, int cpu2)
+{
+ unsigned long distance = 0;
+ struct sched_domain *sd;
+
+ for_each_domain(cpu1, sd) {
+ WARN_ON(!cpu_isset(cpu1, sd->span));
+ if (cpu_isset(cpu2, sd->span))
+ return distance;
+ distance++;
+ }
+ if (distance >= MAX_DOMAIN_DISTANCE) {
+ WARN_ON(1);
+ distance = MAX_DOMAIN_DISTANCE-1;
+ }
+
+ return distance;
+}
+
+static unsigned int migration_debug;
+
+static int __init setup_migration_debug(char *str)
+{
+ get_option(&str, &migration_debug);
+ return 1;
+}
+
+__setup("migration_debug=", setup_migration_debug);
+
+/*
+ * Maximum cache-size that the scheduler should try to measure.
+ * Architectures with larger caches should tune this up during
+ * bootup. Gets used in the domain-setup code (i.e. during SMP
+ * bootup).
+ */
+unsigned int max_cache_size;
+
+static int __init setup_max_cache_size(char *str)
+{
+ get_option(&str, &max_cache_size);
+ return 1;
+}
+
+__setup("max_cache_size=", setup_max_cache_size);
+
+/*
+ * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
+ * is the operation that is timed, so we try to generate unpredictable
+ * cachemisses that still end up filling the L2 cache:
+ */
+static void touch_cache(void *__cache, unsigned long __size)
+{
+ unsigned long size = __size/sizeof(long), chunk1 = size/3,
+ chunk2 = 2*size/3;
+ unsigned long *cache = __cache;
+ int i;
+
+ for (i = 0; i < size/6; i += 8) {
+ switch (i % 6) {
+ case 0: cache[i]++;
+ case 1: cache[size-1-i]++;
+ case 2: cache[chunk1-i]++;
+ case 3: cache[chunk1+i]++;
+ case 4: cache[chunk2-i]++;
+ case 5: cache[chunk2+i]++;
+ }
+ }
+}
+
+/*
+ * Measure the cache-cost of one task migration. Returns in units of nsec.
+ */
+static unsigned long long measure_one(void *cache, unsigned long size,
+ int source, int target)
+{
+ cpumask_t mask, saved_mask;
+ unsigned long long t0, t1, t2, t3, cost;
+
+ saved_mask = current->cpus_allowed;
+
+ /*
+ * Flush source caches to RAM and invalidate them:
+ */
+ sched_cacheflush();
+
+ /*
+ * Migrate to the source CPU:
+ */
+ mask = cpumask_of_cpu(source);
+ set_cpus_allowed(current, mask);
+ WARN_ON(smp_processor_id() != source);
+
+ /*
+ * Dirty the working set:
+ */
+ t0 = sched_clock();
+ touch_cache(cache, size);
+ t1 = sched_clock();
+
+ /*
+ * Migrate to the target CPU, dirty the L2 cache and access
+ * the shared buffer. (which represents the working set
+ * of a migrated task.)
+ */
+ mask = cpumask_of_cpu(target);
+ set_cpus_allowed(current, mask);
+ WARN_ON(smp_processor_id() != target);
+
+ t2 = sched_clock();
+ touch_cache(cache, size);
+ t3 = sched_clock();
+
+ cost = t1-t0 + t3-t2;
+
+ if (migration_debug >= 2)
+ printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
+ source, target, t1-t0, t1-t0, t3-t2, cost);
+ /*
+ * Flush target caches to RAM and invalidate them:
+ */
+ sched_cacheflush();
+
+ set_cpus_allowed(current, saved_mask);
+
+ return cost;
+}
+
+/*
+ * Measure a series of task migrations and return the average
+ * result. Since this code runs early during bootup the system
+ * is 'undisturbed' and the average latency makes sense.
+ *
+ * The algorithm in essence auto-detects the relevant cache-size,
+ * so it will properly detect different cachesizes for different
+ * cache-hierarchies, depending on how the CPUs are connected.
+ *
+ * Architectures can prime the upper limit of the search range via
+ * max_cache_size, otherwise the search range defaults to 20MB...64K.
+ */
+static unsigned long long
+measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
+{
+ unsigned long long cost1, cost2;
+ int i;
+
+ /*
+ * Measure the migration cost of 'size' bytes, over an
+ * average of 10 runs:
+ *
+ * (We perturb the cache size by a small (0..4k)
+ * value to compensate size/alignment related artifacts.
+ * We also subtract the cost of the operation done on
+ * the same CPU.)
+ */
+ cost1 = 0;
+
+ /*
+ * dry run, to make sure we start off cache-cold on cpu1,
+ * and to get any vmalloc pagefaults in advance:
+ */
+ measure_one(cache, size, cpu1, cpu2);
+ for (i = 0; i < ITERATIONS; i++)
+ cost1 += measure_one(cache, size - i*1024, cpu1, cpu2);
+
+ measure_one(cache, size, cpu2, cpu1);
+ for (i = 0; i < ITERATIONS; i++)
+ cost1 += measure_one(cache, size - i*1024, cpu2, cpu1);
+
+ /*
+ * (We measure the non-migrating [cached] cost on both
+ * cpu1 and cpu2, to handle CPUs with different speeds)
+ */
+ cost2 = 0;
+
+ measure_one(cache, size, cpu1, cpu1);
+ for (i = 0; i < ITERATIONS; i++)
+ cost2 += measure_one(cache, size - i*1024, cpu1, cpu1);
+
+ measure_one(cache, size, cpu2, cpu2);
+ for (i = 0; i < ITERATIONS; i++)
+ cost2 += measure_one(cache, size - i*1024, cpu2, cpu2);
+
+ /*
+ * Get the per-iteration migration cost:
+ */
+ do_div(cost1, 2*ITERATIONS);
+ do_div(cost2, 2*ITERATIONS);
+
+ return cost1 - cost2;
+}
+
+static unsigned long long measure_migration_cost(int cpu1, int cpu2)
+{
+ unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
+ unsigned int max_size, size, size_found = 0;
+ long long cost = 0, prev_cost;
+ void *cache;
+
+ /*
+ * Search from max_cache_size*5 down to 64K - the real relevant
+ * cachesize has to lie somewhere inbetween.
+ */
+ if (max_cache_size) {
+ max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
+ size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
+ } else {
+ /*
+ * Since we have no estimation about the relevant
+ * search range
+ */
+ max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
+ size = MIN_CACHE_SIZE;
+ }
+
+ if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
+ printk("cpu %d and %d not both online!\n", cpu1, cpu2);
+ return 0;
+ }
+
+ /*
+ * Allocate the working set:
+ */
+ cache = vmalloc(max_size);
+ if (!cache) {
+ printk("could not vmalloc %d bytes for cache!\n", 2*max_size);
+ return 1000000; // return 1 msec on very small boxen
+ }
+
+ while (size <= max_size) {
+ prev_cost = cost;
+ cost = measure_cost(cpu1, cpu2, cache, size);
+
+ /*
+ * Update the max:
+ */
+ if (cost > 0) {
+ if (max_cost < cost) {
+ max_cost = cost;
+ size_found = size;
+ }
+ }
+ /*
+ * Calculate average fluctuation, we use this to prevent
+ * noise from triggering an early break out of the loop:
+ */
+ fluct = abs(cost - prev_cost);
+ avg_fluct = (avg_fluct + fluct)/2;
+
+ if (migration_debug)
+ printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): (%8Ld %8Ld)\n",
+ cpu1, cpu2, size,
+ (long)cost / 1000000,
+ ((long)cost / 100000) % 10,
+ (long)max_cost / 1000000,
+ ((long)max_cost / 100000) % 10,
+ domain_distance(cpu1, cpu2),
+ cost, avg_fluct);
+
+ /*
+ * If we iterated at least 20% past the previous maximum,
+ * and the cost has dropped by more than 20% already,
+ * (taking fluctuations into account) then we assume to
+ * have found the maximum and break out of the loop early:
+ */
+ if (size_found && (size*100 > size_found*SIZE_THRESH))
+ if (cost+avg_fluct <= 0 ||
+ max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
+
+ if (migration_debug)
+ printk("-> found max.\n");
+ break;
+ }
+ /*
+ * Increase the cachesize in 5% steps:
+ */
+ size = size * 20 / 19;
+ }
+
+ if (migration_debug)
+ printk("[%d][%d] working set size found: %d, cost: %Ld\n",
+ cpu1, cpu2, size_found, max_cost);
+
+ vfree(cache);
+
+ /*
+ * A task is considered 'cache cold' if at least 2 times
+ * the worst-case cost of migration has passed.
+ *
+ * (this limit is only listened to if the load-balancing
+ * situation is 'nice' - if there is a large imbalance we
+ * ignore it for the sake of CPU utilization and
+ * processing fairness.)
+ */
+ return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
+}
+
+static void calibrate_migration_costs(const cpumask_t *cpu_map)
+{
+ int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
+ unsigned long j0, j1, distance, max_distance = 0;
+ struct sched_domain *sd;
+
+ j0 = jiffies;
+
+ /*
+ * First pass - calculate the cacheflush times:
+ */
+ for_each_cpu_mask(cpu1, *cpu_map) {
+ for_each_cpu_mask(cpu2, *cpu_map) {
+ if (cpu1 == cpu2)
+ continue;
+ distance = domain_distance(cpu1, cpu2);
+ max_distance = max(max_distance, distance);
+ /*
+ * No result cached yet?
+ */
+ if (migration_cost[distance] == -1LL)
+ migration_cost[distance] =
+ measure_migration_cost(cpu1, cpu2);
+ }
+ }
+ /*
+ * Second pass - update the sched domain hierarchy with
+ * the new cache-hot-time estimations:
+ */
+ for_each_cpu_mask(cpu, *cpu_map) {
+ distance = 0;
+ for_each_domain(cpu, sd) {
+ sd->cache_hot_time = migration_cost[distance];
+ distance++;
+ }
+ }
+ /*
+ * Print the matrix:
+ */
+ if (migration_debug)
+ printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
+ max_cache_size,
+#ifdef CONFIG_X86
+ cpu_khz/1000
+#else
+ -1
+#endif
+ );
+ printk("migration_cost=");
+ for (distance = 0; distance <= max_distance; distance++) {
+ if (distance)
+ printk(",");
+ printk("%ld", (long)migration_cost[distance] / 1000);
+ }
+ printk("\n");
+ j1 = jiffies;
+ if (migration_debug)
+ printk("migration: %ld seconds\n", (j1-j0)/HZ);
+
+ /*
+ * Move back to the original CPU. NUMA-Q gets confused
+ * if we migrate to another quad during bootup.
+ */
+ if (raw_smp_processor_id() != orig_cpu) {
+ cpumask_t mask = cpumask_of_cpu(orig_cpu),
+ saved_mask = current->cpus_allowed;
+
+ set_cpus_allowed(current, mask);
+ set_cpus_allowed(current, saved_mask);
+ }
+}
+
#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
@@ -5439,6 +5942,10 @@ next_sg:
#endif
cpu_attach_domain(sd, i);
}
+ /*
+ * Tune cache-hot values:
+ */
+ calibrate_migration_costs(cpu_map);
}
/*
* Set up scheduler domains and groups. Callers must hold the hotplug lock.
@@ -5505,7 +6012,7 @@ next_sg:
* Detach sched domains from a group of cpus specified in cpu_map
* These cpus will now be attached to the NULL domain
*/
-static inline void detach_destroy_domains(const cpumask_t *cpu_map)
+static void detach_destroy_domains(const cpumask_t *cpu_map)
{
int i;
diff --git a/kernel/signal.c b/kernel/signal.c
index d7611f189ef7..d3efafd8109a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -25,6 +25,7 @@
#include <linux/posix-timers.h>
#include <linux/signal.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -329,13 +330,20 @@ void __exit_sighand(struct task_struct *tsk)
/* Ok, we're done with the signal handlers */
tsk->sighand = NULL;
if (atomic_dec_and_test(&sighand->count))
- kmem_cache_free(sighand_cachep, sighand);
+ sighand_free(sighand);
}
void exit_sighand(struct task_struct *tsk)
{
write_lock_irq(&tasklist_lock);
- __exit_sighand(tsk);
+ rcu_read_lock();
+ if (tsk->sighand != NULL) {
+ struct sighand_struct *sighand = rcu_dereference(tsk->sighand);
+ spin_lock(&sighand->siglock);
+ __exit_sighand(tsk);
+ spin_unlock(&sighand->siglock);
+ }
+ rcu_read_unlock();
write_unlock_irq(&tasklist_lock);
}
@@ -345,19 +353,20 @@ void exit_sighand(struct task_struct *tsk)
void __exit_signal(struct task_struct *tsk)
{
struct signal_struct * sig = tsk->signal;
- struct sighand_struct * sighand = tsk->sighand;
+ struct sighand_struct * sighand;
if (!sig)
BUG();
if (!atomic_read(&sig->count))
BUG();
+ rcu_read_lock();
+ sighand = rcu_dereference(tsk->sighand);
spin_lock(&sighand->siglock);
posix_cpu_timers_exit(tsk);
if (atomic_dec_and_test(&sig->count)) {
posix_cpu_timers_exit_group(tsk);
- if (tsk == sig->curr_target)
- sig->curr_target = next_thread(tsk);
tsk->signal = NULL;
+ __exit_sighand(tsk);
spin_unlock(&sighand->siglock);
flush_sigqueue(&sig->shared_pending);
} else {
@@ -389,9 +398,11 @@ void __exit_signal(struct task_struct *tsk)
sig->nvcsw += tsk->nvcsw;
sig->nivcsw += tsk->nivcsw;
sig->sched_time += tsk->sched_time;
+ __exit_sighand(tsk);
spin_unlock(&sighand->siglock);
sig = NULL; /* Marker for below. */
}
+ rcu_read_unlock();
clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
flush_sigqueue(&tsk->pending);
if (sig) {
@@ -465,7 +476,7 @@ unblock_all_signals(void)
spin_unlock_irqrestore(&current->sighand->siglock, flags);
}
-static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
+static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
{
struct sigqueue *q, *first = NULL;
int still_pending = 0;
@@ -613,6 +624,33 @@ void signal_wake_up(struct task_struct *t, int resume)
* Returns 1 if any signals were found.
*
* All callers must be holding the siglock.
+ *
+ * This version takes a sigset mask and looks at all signals,
+ * not just those in the first mask word.
+ */
+static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)
+{
+ struct sigqueue *q, *n;
+ sigset_t m;
+
+ sigandsets(&m, mask, &s->signal);
+ if (sigisemptyset(&m))
+ return 0;
+
+ signandsets(&s->signal, &s->signal, mask);
+ list_for_each_entry_safe(q, n, &s->list, list) {
+ if (sigismember(mask, q->info.si_signo)) {
+ list_del_init(&q->list);
+ __sigqueue_free(q);
+ }
+ }
+ return 1;
+}
+/*
+ * Remove signals in mask from the pending set and queue.
+ * Returns 1 if any signals were found.
+ *
+ * All callers must be holding the siglock.
*/
static int rm_from_queue(unsigned long mask, struct sigpending *s)
{
@@ -1080,18 +1118,29 @@ void zap_other_threads(struct task_struct *p)
}
/*
- * Must be called with the tasklist_lock held for reading!
+ * Must be called under rcu_read_lock() or with tasklist_lock read-held.
*/
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
unsigned long flags;
+ struct sighand_struct *sp;
int ret;
+retry:
ret = check_kill_permission(sig, info, p);
- if (!ret && sig && p->sighand) {
- spin_lock_irqsave(&p->sighand->siglock, flags);
+ if (!ret && sig && (sp = rcu_dereference(p->sighand))) {
+ spin_lock_irqsave(&sp->siglock, flags);
+ if (p->sighand != sp) {
+ spin_unlock_irqrestore(&sp->siglock, flags);
+ goto retry;
+ }
+ if ((atomic_read(&sp->count) == 0) ||
+ (atomic_read(&p->usage) == 0)) {
+ spin_unlock_irqrestore(&sp->siglock, flags);
+ return -ESRCH;
+ }
ret = __group_send_sig_info(sig, info, p);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ spin_unlock_irqrestore(&sp->siglock, flags);
}
return ret;
@@ -1136,14 +1185,21 @@ int
kill_proc_info(int sig, struct siginfo *info, pid_t pid)
{
int error;
+ int acquired_tasklist_lock = 0;
struct task_struct *p;
- read_lock(&tasklist_lock);
+ rcu_read_lock();
+ if (unlikely(sig_kernel_stop(sig) || sig == SIGCONT)) {
+ read_lock(&tasklist_lock);
+ acquired_tasklist_lock = 1;
+ }
p = find_task_by_pid(pid);
error = -ESRCH;
if (p)
error = group_send_sig_info(sig, info, p);
- read_unlock(&tasklist_lock);
+ if (unlikely(acquired_tasklist_lock))
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return error;
}
@@ -1163,8 +1219,7 @@ int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid,
ret = -ESRCH;
goto out_unlock;
}
- if ((!info || ((unsigned long)info != 1 &&
- (unsigned long)info != 2 && SI_FROMUSER(info)))
+ if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
&& (euid != p->suid) && (euid != p->uid)
&& (uid != p->suid) && (uid != p->uid)) {
ret = -EPERM;
@@ -1355,16 +1410,54 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
{
unsigned long flags;
int ret = 0;
+ struct sighand_struct *sh;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
- read_lock(&tasklist_lock);
+
+ /*
+ * The rcu based delayed sighand destroy makes it possible to
+ * run this without tasklist lock held. The task struct itself
+ * cannot go away as create_timer did get_task_struct().
+ *
+ * We return -1, when the task is marked exiting, so
+ * posix_timer_event can redirect it to the group leader
+ */
+ rcu_read_lock();
if (unlikely(p->flags & PF_EXITING)) {
ret = -1;
goto out_err;
}
- spin_lock_irqsave(&p->sighand->siglock, flags);
+retry:
+ sh = rcu_dereference(p->sighand);
+
+ spin_lock_irqsave(&sh->siglock, flags);
+ if (p->sighand != sh) {
+ /* We raced with exec() in a multithreaded process... */
+ spin_unlock_irqrestore(&sh->siglock, flags);
+ goto retry;
+ }
+
+ /*
+ * We do the check here again to handle the following scenario:
+ *
+ * CPU 0 CPU 1
+ * send_sigqueue
+ * check PF_EXITING
+ * interrupt exit code running
+ * __exit_signal
+ * lock sighand->siglock
+ * unlock sighand->siglock
+ * lock sh->siglock
+ * add(tsk->pending) flush_sigqueue(tsk->pending)
+ *
+ */
+
+ if (unlikely(p->flags & PF_EXITING)) {
+ ret = -1;
+ goto out;
+ }
if (unlikely(!list_empty(&q->list))) {
/*
@@ -1388,9 +1481,9 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
signal_wake_up(p, sig == SIGKILL);
out:
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
+ spin_unlock_irqrestore(&sh->siglock, flags);
out_err:
- read_unlock(&tasklist_lock);
+ rcu_read_unlock();
return ret;
}
@@ -1402,7 +1495,9 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
int ret = 0;
BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
+
read_lock(&tasklist_lock);
+ /* Since it_lock is held, p->sighand cannot be NULL. */
spin_lock_irqsave(&p->sighand->siglock, flags);
handle_stop_signal(sig, p);
@@ -1436,7 +1531,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
out:
spin_unlock_irqrestore(&p->sighand->siglock, flags);
read_unlock(&tasklist_lock);
- return(ret);
+ return ret;
}
/*
@@ -1786,7 +1881,7 @@ do_signal_stop(int signr)
* We return zero if we still hold the siglock and should look
* for another signal without checking group_stop_count again.
*/
-static inline int handle_group_stop(void)
+static int handle_group_stop(void)
{
int stop_count;
@@ -2338,6 +2433,7 @@ int
do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
{
struct k_sigaction *k;
+ sigset_t mask;
if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
return -EINVAL;
@@ -2385,9 +2481,11 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
*k = *act;
sigdelsetmask(&k->sa.sa_mask,
sigmask(SIGKILL) | sigmask(SIGSTOP));
- rm_from_queue(sigmask(sig), &t->signal->shared_pending);
+ sigemptyset(&mask);
+ sigaddset(&mask, sig);
+ rm_from_queue_full(&mask, &t->signal->shared_pending);
do {
- rm_from_queue(sigmask(sig), &t->pending);
+ rm_from_queue_full(&mask, &t->pending);
recalc_sigpending_tsk(t);
t = next_thread(t);
} while (t != current);
@@ -2623,6 +2721,32 @@ sys_pause(void)
#endif
+#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
+asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
+{
+ sigset_t newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
+}
+#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
+
void __init signals_init(void)
{
sigqueue_cachep =
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index b3d4dc858e35..dcfb5d731466 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -87,13 +87,9 @@ static int stop_machine(void)
{
int i, ret = 0;
struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
- mm_segment_t old_fs = get_fs();
/* One high-prio thread per cpu. We'll do this one. */
- set_fs(KERNEL_DS);
- sys_sched_setscheduler(current->pid, SCHED_FIFO,
- (struct sched_param __user *)&param);
- set_fs(old_fs);
+ sched_setscheduler(current, SCHED_FIFO, &param);
atomic_set(&stopmachine_thread_ack, 0);
stopmachine_num_threads = 0;
diff --git a/kernel/sys.c b/kernel/sys.c
index eecf84526afe..d09cac23fdfd 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/kexec.h>
#include <linux/workqueue.h>
+#include <linux/capability.h>
#include <linux/device.h>
#include <linux/key.h>
#include <linux/times.h>
@@ -223,6 +224,18 @@ int unregister_reboot_notifier(struct notifier_block * nb)
EXPORT_SYMBOL(unregister_reboot_notifier);
+#ifndef CONFIG_SECURITY
+int capable(int cap)
+{
+ if (cap_raised(current->cap_effective, cap)) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(capable);
+#endif
+
static int set_one_prio(struct task_struct *p, int niceval, int error)
{
int no_nice;
@@ -489,6 +502,12 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
magic2 != LINUX_REBOOT_MAGIC2C))
return -EINVAL;
+ /* Instead of trying to make the power_off code look like
+ * halt when pm_power_off is not set do it the easy way.
+ */
+ if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
+ cmd = LINUX_REBOOT_CMD_HALT;
+
lock_kernel();
switch (cmd) {
case LINUX_REBOOT_CMD_RESTART:
@@ -1084,10 +1103,11 @@ asmlinkage long sys_times(struct tms __user * tbuf)
asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
{
struct task_struct *p;
+ struct task_struct *group_leader = current->group_leader;
int err = -EINVAL;
if (!pid)
- pid = current->pid;
+ pid = group_leader->pid;
if (!pgid)
pgid = pid;
if (pgid < 0)
@@ -1107,16 +1127,16 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
if (!thread_group_leader(p))
goto out;
- if (p->parent == current || p->real_parent == current) {
+ if (p->real_parent == group_leader) {
err = -EPERM;
- if (p->signal->session != current->signal->session)
+ if (p->signal->session != group_leader->signal->session)
goto out;
err = -EACCES;
if (p->did_exec)
goto out;
} else {
err = -ESRCH;
- if (p != current)
+ if (p != group_leader)
goto out;
}
@@ -1128,7 +1148,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
struct task_struct *p;
do_each_task_pid(pgid, PIDTYPE_PGID, p) {
- if (p->signal->session == current->signal->session)
+ if (p->signal->session == group_leader->signal->session)
goto ok_pgid;
} while_each_task_pid(pgid, PIDTYPE_PGID, p);
goto out;
@@ -1208,24 +1228,22 @@ asmlinkage long sys_getsid(pid_t pid)
asmlinkage long sys_setsid(void)
{
+ struct task_struct *group_leader = current->group_leader;
struct pid *pid;
int err = -EPERM;
- if (!thread_group_leader(current))
- return -EINVAL;
-
down(&tty_sem);
write_lock_irq(&tasklist_lock);
- pid = find_pid(PIDTYPE_PGID, current->pid);
+ pid = find_pid(PIDTYPE_PGID, group_leader->pid);
if (pid)
goto out;
- current->signal->leader = 1;
- __set_special_pids(current->pid, current->pid);
- current->signal->tty = NULL;
- current->signal->tty_old_pgrp = 0;
- err = process_group(current);
+ group_leader->signal->leader = 1;
+ __set_special_pids(group_leader->pid, group_leader->pid);
+ group_leader->signal->tty = NULL;
+ group_leader->signal->tty_old_pgrp = 0;
+ err = process_group(group_leader);
out:
write_unlock_irq(&tasklist_lock);
up(&tty_sem);
@@ -1687,7 +1705,10 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
if (unlikely(!p->signal))
return;
+ utime = stime = cputime_zero;
+
switch (who) {
+ case RUSAGE_BOTH:
case RUSAGE_CHILDREN:
spin_lock_irqsave(&p->sighand->siglock, flags);
utime = p->signal->cutime;
@@ -1697,22 +1718,11 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
r->ru_minflt = p->signal->cmin_flt;
r->ru_majflt = p->signal->cmaj_flt;
spin_unlock_irqrestore(&p->sighand->siglock, flags);
- cputime_to_timeval(utime, &r->ru_utime);
- cputime_to_timeval(stime, &r->ru_stime);
- break;
+
+ if (who == RUSAGE_CHILDREN)
+ break;
+
case RUSAGE_SELF:
- spin_lock_irqsave(&p->sighand->siglock, flags);
- utime = stime = cputime_zero;
- goto sum_group;
- case RUSAGE_BOTH:
- spin_lock_irqsave(&p->sighand->siglock, flags);
- utime = p->signal->cutime;
- stime = p->signal->cstime;
- r->ru_nvcsw = p->signal->cnvcsw;
- r->ru_nivcsw = p->signal->cnivcsw;
- r->ru_minflt = p->signal->cmin_flt;
- r->ru_majflt = p->signal->cmaj_flt;
- sum_group:
utime = cputime_add(utime, p->signal->utime);
stime = cputime_add(stime, p->signal->stime);
r->ru_nvcsw += p->signal->nvcsw;
@@ -1729,13 +1739,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
r->ru_majflt += t->maj_flt;
t = next_thread(t);
} while (t != p);
- spin_unlock_irqrestore(&p->sighand->siglock, flags);
- cputime_to_timeval(utime, &r->ru_utime);
- cputime_to_timeval(stime, &r->ru_stime);
break;
+
default:
BUG();
}
+
+ cputime_to_timeval(utime, &r->ru_utime);
+ cputime_to_timeval(stime, &r->ru_stime);
}
int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 1ab2370e2efa..17313b99e53d 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -82,6 +82,28 @@ cond_syscall(compat_sys_socketcall);
cond_syscall(sys_inotify_init);
cond_syscall(sys_inotify_add_watch);
cond_syscall(sys_inotify_rm_watch);
+cond_syscall(sys_migrate_pages);
+cond_syscall(sys_chown16);
+cond_syscall(sys_fchown16);
+cond_syscall(sys_getegid16);
+cond_syscall(sys_geteuid16);
+cond_syscall(sys_getgid16);
+cond_syscall(sys_getgroups16);
+cond_syscall(sys_getresgid16);
+cond_syscall(sys_getresuid16);
+cond_syscall(sys_getuid16);
+cond_syscall(sys_lchown16);
+cond_syscall(sys_setfsgid16);
+cond_syscall(sys_setfsuid16);
+cond_syscall(sys_setgid16);
+cond_syscall(sys_setgroups16);
+cond_syscall(sys_setregid16);
+cond_syscall(sys_setresgid16);
+cond_syscall(sys_setresuid16);
+cond_syscall(sys_setreuid16);
+cond_syscall(sys_setuid16);
+cond_syscall(sys_vm86old);
+cond_syscall(sys_vm86);
/* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read);
@@ -90,3 +112,5 @@ cond_syscall(sys_pciconfig_iobase);
cond_syscall(sys32_ipc);
cond_syscall(sys32_sysctl);
cond_syscall(ppc_rtas);
+cond_syscall(sys_spu_run);
+cond_syscall(sys_spu_create);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b53115b882e1..cb99a42f8b37 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -25,12 +25,14 @@
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
+#include <linux/capability.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/kobject.h>
#include <linux/net.h>
#include <linux/sysrq.h>
#include <linux/highuid.h>
@@ -67,6 +69,8 @@ extern int min_free_kbytes;
extern int printk_ratelimit_jiffies;
extern int printk_ratelimit_burst;
extern int pid_max_min, pid_max_max;
+extern int sysctl_drop_caches;
+extern int percpu_pagelist_fraction;
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
int unknown_nmi_panic;
@@ -77,15 +81,13 @@ extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;
+static int min_percpu_pagelist_fract = 8;
static int ngroups_max = NGROUPS_MAX;
#ifdef CONFIG_KMOD
extern char modprobe_path[];
#endif
-#ifdef CONFIG_HOTPLUG
-extern char hotplug_path[];
-#endif
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
#endif
@@ -110,7 +112,7 @@ extern int pwrsw_enabled;
extern int unaligned_enabled;
#endif
-#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_S390
#ifdef CONFIG_MATHEMU
extern int sysctl_ieee_emulation_warnings;
#endif
@@ -397,8 +399,8 @@ static ctl_table kern_table[] = {
{
.ctl_name = KERN_HOTPLUG,
.procname = "hotplug",
- .data = &hotplug_path,
- .maxlen = HOTPLUG_PATH_LEN,
+ .data = &uevent_helper,
+ .maxlen = UEVENT_HELPER_PATH_LEN,
.mode = 0644,
.proc_handler = &proc_dostring,
.strategy = &sysctl_string,
@@ -544,7 +546,7 @@ static ctl_table kern_table[] = {
.extra1 = &minolduid,
.extra2 = &maxolduid,
},
-#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_S390
#ifdef CONFIG_MATHEMU
{
.ctl_name = KERN_IEEE_EMULATION_WARNINGS,
@@ -646,7 +648,7 @@ static ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec,
},
-#if defined(CONFIG_ARCH_S390)
+#if defined(CONFIG_S390) && defined(CONFIG_SMP)
{
.ctl_name = KERN_SPIN_RETRY,
.procname = "spin_retry",
@@ -777,6 +779,15 @@ static ctl_table vm_table[] = {
.strategy = &sysctl_intvec,
},
{
+ .ctl_name = VM_DROP_PAGECACHE,
+ .procname = "drop_caches",
+ .data = &sysctl_drop_caches,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = drop_caches_sysctl_handler,
+ .strategy = &sysctl_intvec,
+ },
+ {
.ctl_name = VM_MIN_FREE_KBYTES,
.procname = "min_free_kbytes",
.data = &min_free_kbytes,
@@ -786,6 +797,16 @@ static ctl_table vm_table[] = {
.strategy = &sysctl_intvec,
.extra1 = &zero,
},
+ {
+ .ctl_name = VM_PERCPU_PAGELIST_FRACTION,
+ .procname = "percpu_pagelist_fraction",
+ .data = &percpu_pagelist_fraction,
+ .maxlen = sizeof(percpu_pagelist_fraction),
+ .mode = 0644,
+ .proc_handler = &percpu_pagelist_fraction_sysctl_handler,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_percpu_pagelist_fract,
+ },
#ifdef CONFIG_MMU
{
.ctl_name = VM_MAX_MAP_COUNT,
@@ -849,6 +870,17 @@ static ctl_table vm_table[] = {
.strategy = &sysctl_jiffies,
},
#endif
+#ifdef CONFIG_NUMA
+ {
+ .ctl_name = VM_ZONE_RECLAIM_MODE,
+ .procname = "zone_reclaim_mode",
+ .data = &zone_reclaim_mode,
+ .maxlen = sizeof(zone_reclaim_mode),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ .strategy = &zero,
+ },
+#endif
{ .ctl_name = 0 }
};
diff --git a/kernel/time.c b/kernel/time.c
index b94bfa8c03e0..7477b1d2079e 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/timex.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
@@ -154,6 +155,9 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
static int firsttime = 1;
int error = 0;
+ if (!timespec_valid(tv))
+ return -EINVAL;
+
error = security_settime(tv, tz);
if (error)
return error;
@@ -561,27 +565,107 @@ void getnstimeofday(struct timespec *tv)
EXPORT_SYMBOL_GPL(getnstimeofday);
#endif
-void getnstimestamp(struct timespec *ts)
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+unsigned long
+mktime(const unsigned int year0, const unsigned int mon0,
+ const unsigned int day, const unsigned int hour,
+ const unsigned int min, const unsigned int sec)
{
- unsigned int seq;
- struct timespec wall2mono;
+ unsigned int mon = mon0, year = year0;
- /* synchronize with settimeofday() changes */
- do {
- seq = read_seqbegin(&xtime_lock);
- getnstimeofday(ts);
- wall2mono = wall_to_monotonic;
- } while(unlikely(read_seqretry(&xtime_lock, seq)));
-
- /* adjust to monotonicaly-increasing values */
- ts->tv_sec += wall2mono.tv_sec;
- ts->tv_nsec += wall2mono.tv_nsec;
- while (unlikely(ts->tv_nsec >= NSEC_PER_SEC)) {
- ts->tv_nsec -= NSEC_PER_SEC;
- ts->tv_sec++;
+ /* 1..12 -> 11,12,1..10 */
+ if (0 >= (int) (mon -= 2)) {
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
}
+
+ return ((((unsigned long)
+ (year/4 - year/100 + year/400 + 367*mon/12 + day) +
+ year*365 - 719499
+ )*24 + hour /* now have hours */
+ )*60 + min /* now have minutes */
+ )*60 + sec; /* finally seconds */
+}
+
+EXPORT_SYMBOL(mktime);
+
+/**
+ * set_normalized_timespec - set timespec sec and nsec parts and normalize
+ *
+ * @ts: pointer to timespec variable to be set
+ * @sec: seconds to set
+ * @nsec: nanoseconds to set
+ *
+ * Set seconds and nanoseconds field of a timespec variable and
+ * normalize to the timespec storage format
+ *
+ * Note: The tv_nsec part is always in the range of
+ * 0 <= tv_nsec < NSEC_PER_SEC
+ * For negative values only the tv_sec field is negative !
+ */
+void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
+{
+ while (nsec >= NSEC_PER_SEC) {
+ nsec -= NSEC_PER_SEC;
+ ++sec;
+ }
+ while (nsec < 0) {
+ nsec += NSEC_PER_SEC;
+ --sec;
+ }
+ ts->tv_sec = sec;
+ ts->tv_nsec = nsec;
+}
+
+/**
+ * ns_to_timespec - Convert nanoseconds to timespec
+ * @nsec: the nanoseconds value to be converted
+ *
+ * Returns the timespec representation of the nsec parameter.
+ */
+inline struct timespec ns_to_timespec(const nsec_t nsec)
+{
+ struct timespec ts;
+
+ if (nsec)
+ ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC,
+ &ts.tv_nsec);
+ else
+ ts.tv_sec = ts.tv_nsec = 0;
+
+ return ts;
+}
+
+/**
+ * ns_to_timeval - Convert nanoseconds to timeval
+ * @nsec: the nanoseconds value to be converted
+ *
+ * Returns the timeval representation of the nsec parameter.
+ */
+struct timeval ns_to_timeval(const nsec_t nsec)
+{
+ struct timespec ts = ns_to_timespec(nsec);
+ struct timeval tv;
+
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000;
+
+ return tv;
}
-EXPORT_SYMBOL_GPL(getnstimestamp);
#if (BITS_PER_LONG < 64)
u64 get_jiffies_64(void)
diff --git a/kernel/timer.c b/kernel/timer.c
index fd74268d8663..4f1cb0ab5251 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -33,6 +33,7 @@
#include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -857,6 +858,7 @@ static void run_timer_softirq(struct softirq_action *h)
{
tvec_base_t *base = &__get_cpu_var(tvec_bases);
+ hrtimer_run_queues();
if (time_after_eq(jiffies, base->timer_jiffies))
__run_timers(base);
}
@@ -1118,62 +1120,6 @@ asmlinkage long sys_gettid(void)
return current->pid;
}
-static long __sched nanosleep_restart(struct restart_block *restart)
-{
- unsigned long expire = restart->arg0, now = jiffies;
- struct timespec __user *rmtp = (struct timespec __user *) restart->arg1;
- long ret;
-
- /* Did it expire while we handled signals? */
- if (!time_after(expire, now))
- return 0;
-
- expire = schedule_timeout_interruptible(expire - now);
-
- ret = 0;
- if (expire) {
- struct timespec t;
- jiffies_to_timespec(expire, &t);
-
- ret = -ERESTART_RESTARTBLOCK;
- if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
- ret = -EFAULT;
- /* The 'restart' block is already filled in */
- }
- return ret;
-}
-
-asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
-{
- struct timespec t;
- unsigned long expire;
- long ret;
-
- if (copy_from_user(&t, rqtp, sizeof(t)))
- return -EFAULT;
-
- if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
- return -EINVAL;
-
- expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
- expire = schedule_timeout_interruptible(expire);
-
- ret = 0;
- if (expire) {
- struct restart_block *restart;
- jiffies_to_timespec(expire, &t);
- if (rmtp && copy_to_user(rmtp, &t, sizeof(t)))
- return -EFAULT;
-
- restart = &current_thread_info()->restart_block;
- restart->fn = nanosleep_restart;
- restart->arg0 = jiffies + expire;
- restart->arg1 = (unsigned long) rmtp;
- ret = -ERESTART_RESTARTBLOCK;
- }
- return ret;
-}
-
/*
* sys_sysinfo - fill in sysinfo struct
*/
diff --git a/kernel/uid16.c b/kernel/uid16.c
index f669941e8b26..aa25605027c8 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -10,6 +10,7 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/prctl.h>
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/highuid.h>
#include <linux/security.h>
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 2bd5aee1c736..b052e2c4c710 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -29,7 +29,8 @@
#include <linux/kthread.h>
/*
- * The per-CPU workqueue (if single thread, we always use cpu 0's).
+ * The per-CPU workqueue (if single thread, we always use the first
+ * possible cpu).
*
* The sequence counters are for flush_scheduled_work(). It wants to wait
* until until all currently-scheduled works are completed, but it doesn't
@@ -69,6 +70,8 @@ struct workqueue_struct {
static DEFINE_SPINLOCK(workqueue_lock);
static LIST_HEAD(workqueues);
+static int singlethread_cpu;
+
/* If it's single threaded, it isn't in the list of workqueues. */
static inline int is_single_threaded(struct workqueue_struct *wq)
{
@@ -102,7 +105,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work)
if (!test_and_set_bit(0, &work->pending)) {
if (unlikely(is_single_threaded(wq)))
- cpu = any_online_cpu(cpu_online_map);
+ cpu = singlethread_cpu;
BUG_ON(!list_empty(&work->entry));
__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
ret = 1;
@@ -118,7 +121,7 @@ static void delayed_work_timer_fn(unsigned long __data)
int cpu = smp_processor_id();
if (unlikely(is_single_threaded(wq)))
- cpu = any_online_cpu(cpu_online_map);
+ cpu = singlethread_cpu;
__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
}
@@ -144,7 +147,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq,
return ret;
}
-static inline void run_workqueue(struct cpu_workqueue_struct *cwq)
+static void run_workqueue(struct cpu_workqueue_struct *cwq)
{
unsigned long flags;
@@ -267,7 +270,7 @@ void fastcall flush_workqueue(struct workqueue_struct *wq)
if (is_single_threaded(wq)) {
/* Always use first cpu's area. */
- flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, any_online_cpu(cpu_online_map)));
+ flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
} else {
int cpu;
@@ -315,12 +318,17 @@ struct workqueue_struct *__create_workqueue(const char *name,
return NULL;
wq->cpu_wq = alloc_percpu(struct cpu_workqueue_struct);
+ if (!wq->cpu_wq) {
+ kfree(wq);
+ return NULL;
+ }
+
wq->name = name;
/* We don't need the distraction of CPUs appearing and vanishing. */
lock_cpu_hotplug();
if (singlethread) {
INIT_LIST_HEAD(&wq->list);
- p = create_workqueue_thread(wq, any_online_cpu(cpu_online_map));
+ p = create_workqueue_thread(wq, singlethread_cpu);
if (!p)
destroy = 1;
else
@@ -374,7 +382,7 @@ void destroy_workqueue(struct workqueue_struct *wq)
/* We don't need the distraction of CPUs appearing and vanishing. */
lock_cpu_hotplug();
if (is_single_threaded(wq))
- cleanup_workqueue_thread(wq, any_online_cpu(cpu_online_map));
+ cleanup_workqueue_thread(wq, singlethread_cpu);
else {
for_each_online_cpu(cpu)
cleanup_workqueue_thread(wq, cpu);
@@ -419,6 +427,25 @@ int schedule_delayed_work_on(int cpu,
return ret;
}
+int schedule_on_each_cpu(void (*func) (void *info), void *info)
+{
+ int cpu;
+ struct work_struct *work;
+
+ work = kmalloc(NR_CPUS * sizeof(struct work_struct), GFP_KERNEL);
+
+ if (!work)
+ return -ENOMEM;
+ for_each_online_cpu(cpu) {
+ INIT_WORK(work + cpu, func, info);
+ __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
+ work + cpu);
+ }
+ flush_workqueue(keventd_wq);
+ kfree(work);
+ return 0;
+}
+
void flush_scheduled_work(void)
{
flush_workqueue(keventd_wq);
@@ -543,6 +570,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
void init_workqueues(void)
{
+ singlethread_cpu = first_cpu(cpu_possible_map);
hotcpu_notifier(workqueue_cpu_callback, 0);
keventd_wq = create_workqueue("events");
BUG_ON(!keventd_wq);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 156822e3cc79..a314e663d517 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -9,15 +9,9 @@ config PRINTK_TIME
in kernel startup.
-config DEBUG_KERNEL
- bool "Kernel debugging"
- help
- Say Y here if you are developing drivers or trying to debug and
- identify kernel problems.
-
config MAGIC_SYSRQ
bool "Magic SysRq key"
- depends on DEBUG_KERNEL && !UML
+ depends on !UML
help
If you say Y here, you will have some control over the system even
if the system crashes for example during kernel debugging (e.g., you
@@ -29,10 +23,16 @@ config MAGIC_SYSRQ
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
unless you really know what this hack does.
+config DEBUG_KERNEL
+ bool "Kernel debugging"
+ help
+ Say Y here if you are developing drivers or trying to debug and
+ identify kernel problems.
+
config LOG_BUF_SHIFT
int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
range 12 21
- default 17 if ARCH_S390
+ default 17 if S390
default 16 if X86_NUMAQ || IA64
default 15 if SMP
default 14
@@ -79,7 +79,7 @@ config SCHEDSTATS
config DEBUG_SLAB
bool "Debug memory allocations"
- depends on DEBUG_KERNEL
+ depends on DEBUG_KERNEL && SLAB
help
Say Y here to have the kernel do limited verification on memory
allocation as well as poisoning memory on free to catch use of freed
@@ -95,6 +95,14 @@ config DEBUG_PREEMPT
if kernel code uses it in a preemption-unsafe way. Also, the kernel
will detect preemption count underflows.
+config DEBUG_MUTEXES
+ bool "Mutex debugging, deadlock detection"
+ default y
+ depends on DEBUG_KERNEL
+ help
+ This allows mutex semantics violations and mutex related deadlocks
+ (lockups) to be detected and reported automatically.
+
config DEBUG_SPINLOCK
bool "Spinlock debugging"
depends on DEBUG_KERNEL
@@ -172,7 +180,8 @@ config DEBUG_VM
bool "Debug VM"
depends on DEBUG_KERNEL
help
- Enable this to debug the virtual-memory system.
+ Enable this to turn on extended checks in the virtual-memory system
+ that may impact performance.
If unsure, say N.
@@ -186,6 +195,20 @@ config FRAME_POINTER
some architectures or if you use external debuggers.
If you don't debug the kernel, you can say N.
+config FORCED_INLINING
+ bool "Force gcc to inline functions marked 'inline'"
+ depends on DEBUG_KERNEL
+ default y
+ help
+ This option determines if the kernel forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable for the gcc 3.x series of
+ compilers. The gcc 4.x series have a rewritten inlining algorithm and
+ disabling this option will generate a smaller kernel there. Hopefully
+ this algorithm is so good that allowing gcc4 to make the decision can
+ become the default in the future, until then this option is there to
+ test gcc for this.
+
config RCU_TORTURE_TEST
tristate "torture tests for RCU"
depends on DEBUG_KERNEL
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 23d3b1147fe9..48e708381d44 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -519,7 +519,7 @@ EXPORT_SYMBOL(bitmap_parselist);
*
* Map the bit at position @pos in @buf (of length @bits) to the
* ordinal of which set bit it is. If it is not set or if @pos
- * is not a valid bit position, map to zero (0).
+ * is not a valid bit position, map to -1.
*
* If for example, just bits 4 through 7 are set in @buf, then @pos
* values 4 through 7 will get mapped to 0 through 3, respectively,
@@ -531,18 +531,19 @@ EXPORT_SYMBOL(bitmap_parselist);
*/
static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
{
- int ord = 0;
+ int i, ord;
- if (pos >= 0 && pos < bits) {
- int i;
+ if (pos < 0 || pos >= bits || !test_bit(pos, buf))
+ return -1;
- for (i = find_first_bit(buf, bits);
- i < pos;
- i = find_next_bit(buf, bits, i + 1))
- ord++;
- if (i > pos)
- ord = 0;
+ i = find_first_bit(buf, bits);
+ ord = 0;
+ while (i < pos) {
+ i = find_next_bit(buf, bits, i + 1);
+ ord++;
}
+ BUG_ON(i != pos);
+
return ord;
}
@@ -553,11 +554,12 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
* @bits: number of valid bit positions in @buf
*
* Map the ordinal offset of bit @ord in @buf to its position in @buf.
- * If @ord is not the ordinal offset of a set bit in @buf, map to zero (0).
+ * Value of @ord should be in range 0 <= @ord < weight(buf), else
+ * results are undefined.
*
* If for example, just bits 4 through 7 are set in @buf, then @ord
* values 0 through 3 will get mapped to 4 through 7, respectively,
- * and all other @ord valuds will get mapped to 0. When @ord value 3
+ * and all other @ord values return undefined values. When @ord value 3
* gets mapped to (returns) @pos value 7 in this example, that means
* that the 3rd set bit (starting with 0th) is at position 7 in @buf.
*
@@ -583,8 +585,8 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
/**
* bitmap_remap - Apply map defined by a pair of bitmaps to another bitmap
- * @src: subset to be remapped
* @dst: remapped result
+ * @src: subset to be remapped
* @old: defines domain of map
* @new: defines range of map
* @bits: number of bits in each of these bitmaps
@@ -596,49 +598,42 @@ static int bitmap_ord_to_pos(const unsigned long *buf, int ord, int bits)
* weight of @old, map the position of the n-th set bit in @old to
* the position of the m-th set bit in @new, where m == n % w.
*
- * If either of the @old and @new bitmaps are empty, or if@src and @dst
- * point to the same location, then this routine does nothing.
+ * If either of the @old and @new bitmaps are empty, or if @src and
+ * @dst point to the same location, then this routine copies @src
+ * to @dst.
*
- * The positions of unset bits in @old are mapped to the position of
- * the first set bit in @new.
+ * The positions of unset bits in @old are mapped to themselves
+ * (the identify map).
*
* Apply the above specified mapping to @src, placing the result in
* @dst, clearing any bits previously set in @dst.
*
- * The resulting value of @dst will have either the same weight as
- * @src, or less weight in the general case that the mapping wasn't
- * injective due to the weight of @new being less than that of @old.
- * The resulting value of @dst will never have greater weight than
- * that of @src, except perhaps in the case that one of the above
- * conditions was not met and this routine just returned.
- *
* For example, lets say that @old has bits 4 through 7 set, and
* @new has bits 12 through 15 set. This defines the mapping of bit
* position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
- * bit positions to 12 (the first set bit in @new. So if say @src
- * comes into this routine with bits 1, 5 and 7 set, then @dst should
- * leave with bits 12, 13 and 15 set.
+ * bit positions unchanged. So if say @src comes into this routine
+ * with bits 1, 5 and 7 set, then @dst should leave with bits 1,
+ * 13 and 15 set.
*/
void bitmap_remap(unsigned long *dst, const unsigned long *src,
const unsigned long *old, const unsigned long *new,
int bits)
{
- int s;
+ int oldbit, w;
- if (bitmap_weight(old, bits) == 0)
- return;
- if (bitmap_weight(new, bits) == 0)
- return;
if (dst == src) /* following doesn't handle inplace remaps */
return;
-
bitmap_zero(dst, bits);
- for (s = find_first_bit(src, bits);
- s < bits;
- s = find_next_bit(src, bits, s + 1)) {
- int x = bitmap_pos_to_ord(old, s, bits);
- int y = bitmap_ord_to_pos(new, x, bits);
- set_bit(y, dst);
+
+ w = bitmap_weight(new, bits);
+ for (oldbit = find_first_bit(src, bits);
+ oldbit < bits;
+ oldbit = find_next_bit(src, bits, oldbit + 1)) {
+ int n = bitmap_pos_to_ord(old, oldbit, bits);
+ if (n < 0 || w == 0)
+ set_bit(oldbit, dst); /* identity map */
+ else
+ set_bit(bitmap_ord_to_pos(new, n % w, bits), dst);
}
}
EXPORT_SYMBOL(bitmap_remap);
@@ -657,8 +652,8 @@ EXPORT_SYMBOL(bitmap_remap);
* weight of @old, map the position of the n-th set bit in @old to
* the position of the m-th set bit in @new, where m == n % w.
*
- * The positions of unset bits in @old are mapped to the position of
- * the first set bit in @new.
+ * The positions of unset bits in @old are mapped to themselves
+ * (the identify map).
*
* Apply the above specified mapping to bit position @oldbit, returning
* the new bit position.
@@ -666,14 +661,18 @@ EXPORT_SYMBOL(bitmap_remap);
* For example, lets say that @old has bits 4 through 7 set, and
* @new has bits 12 through 15 set. This defines the mapping of bit
* position 4 to 12, 5 to 13, 6 to 14 and 7 to 15, and of all other
- * bit positions to 12 (the first set bit in @new. So if say @oldbit
- * is 5, then this routine returns 13.
+ * bit positions unchanged. So if say @oldbit is 5, then this routine
+ * returns 13.
*/
int bitmap_bitremap(int oldbit, const unsigned long *old,
const unsigned long *new, int bits)
{
- int x = bitmap_pos_to_ord(old, oldbit, bits);
- return bitmap_ord_to_pos(new, x, bits);
+ int w = bitmap_weight(new, bits);
+ int n = bitmap_pos_to_ord(old, oldbit, bits);
+ if (n < 0 || w == 0)
+ return oldbit;
+ else
+ return bitmap_ord_to_pos(new, n % w, bits);
}
EXPORT_SYMBOL(bitmap_bitremap);
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 305a9663aee3..a65c31455541 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -1,47 +1,11 @@
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/atomic.h>
-#include <asm/system.h>
-#ifdef __HAVE_ARCH_CMPXCHG
/*
* This is an implementation of the notion of "decrement a
* reference count, and return locked if it decremented to zero".
*
- * This implementation can be used on any architecture that
- * 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).
- */
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
- int counter;
- int newcount;
-
- for (;;) {
- counter = atomic_read(atomic);
- newcount = counter - 1;
- if (!newcount)
- break; /* do it the slow way */
-
- newcount = cmpxchg(&atomic->counter, counter, newcount);
- if (newcount == counter)
- return 0;
- }
-
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-#else
-/*
- * This is an architecture-neutral, but slow,
- * implementation of the notion of "decrement
- * a reference count, and return locked if it
- * decremented to zero".
- *
* NOTE NOTE NOTE! This is _not_ equivalent to
*
* if (atomic_dec_and_test(&atomic)) {
@@ -52,21 +16,20 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
*
* because the spin-lock and the decrement must be
* "atomic".
- *
- * This slow version gets the spinlock unconditionally,
- * and releases it if it isn't needed. Architectures
- * are encouraged to come up with better approaches,
- * this is trivially done efficiently using a load-locked
- * store-conditional approach, for example.
*/
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
+#ifdef CONFIG_SMP
+ /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
+ if (atomic_add_unless(atomic, -1, 1))
+ return 0;
+#endif
+ /* Otherwise do it the slow way */
spin_lock(lock);
if (atomic_dec_and_test(atomic))
return 1;
spin_unlock(lock);
return 0;
}
-#endif
EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
index d08302d2a42c..c05b4b19cf6c 100644
--- a/lib/find_next_bit.c
+++ b/lib/find_next_bit.c
@@ -10,6 +10,7 @@
*/
#include <linux/bitops.h>
+#include <linux/module.h>
int find_next_bit(const unsigned long *addr, int size, int offset)
{
@@ -53,3 +54,5 @@ int find_next_bit(const unsigned long *addr, int size, int offset)
return offset;
}
+
+EXPORT_SYMBOL(find_next_bit);
diff --git a/lib/klist.c b/lib/klist.c
index bb2f3551d50a..9c94f0b163a1 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -199,6 +199,8 @@ void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_
i->i_klist = k;
i->i_head = &k->k_list;
i->i_cur = n;
+ if (n)
+ kref_get(&n->n_ref);
}
EXPORT_SYMBOL_GPL(klist_iter_init_node);
diff --git a/lib/kobject.c b/lib/kobject.c
index a181abed89f6..7a0e6809490d 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -207,7 +207,7 @@ int kobject_register(struct kobject * kobj)
kobject_name(kobj),error);
dump_stack();
} else
- kobject_hotplug(kobj, KOBJ_ADD);
+ kobject_uevent(kobj, KOBJ_ADD);
} else
error = -EINVAL;
return error;
@@ -312,7 +312,7 @@ void kobject_del(struct kobject * kobj)
void kobject_unregister(struct kobject * kobj)
{
pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
- kobject_hotplug(kobj, KOBJ_REMOVE);
+ kobject_uevent(kobj, KOBJ_REMOVE);
kobject_del(kobj);
kobject_put(kobj);
}
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 3ab375411e38..f56e27ae9d52 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -19,14 +19,16 @@
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/string.h>
-#include <linux/kobject_uevent.h>
#include <linux/kobject.h>
#include <net/sock.h>
-#define BUFFER_SIZE 1024 /* buffer for the hotplug env */
+#define BUFFER_SIZE 1024 /* buffer for the variables */
#define NUM_ENVP 32 /* number of env pointers */
-#if defined(CONFIG_KOBJECT_UEVENT) || defined(CONFIG_HOTPLUG)
+#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
+static DEFINE_SPINLOCK(sequence_lock);
+static struct sock *uevent_sock;
+
static char *action_to_string(enum kobject_action action)
{
switch (action) {
@@ -36,10 +38,6 @@ static char *action_to_string(enum kobject_action action)
return "remove";
case KOBJ_CHANGE:
return "change";
- case KOBJ_MOUNT:
- return "mount";
- case KOBJ_UMOUNT:
- return "umount";
case KOBJ_OFFLINE:
return "offline";
case KOBJ_ONLINE:
@@ -48,306 +46,183 @@ static char *action_to_string(enum kobject_action action)
return NULL;
}
}
-#endif
-
-#ifdef CONFIG_KOBJECT_UEVENT
-static struct sock *uevent_sock;
/**
- * send_uevent - notify userspace by sending event through netlink socket
+ * kobject_uevent - notify userspace by ending an uevent
*
- * @signal: signal name
- * @obj: object path (kobject)
- * @envp: possible hotplug environment to pass with the message
- * @gfp_mask:
- */
-static int send_uevent(const char *signal, const char *obj,
- char **envp, gfp_t gfp_mask)
-{
- struct sk_buff *skb;
- char *pos;
- int len;
-
- if (!uevent_sock)
- return -EIO;
-
- len = strlen(signal) + 1;
- len += strlen(obj) + 1;
-
- /* allocate buffer with the maximum possible message size */
- skb = alloc_skb(len + BUFFER_SIZE, gfp_mask);
- if (!skb)
- return -ENOMEM;
-
- pos = skb_put(skb, len);
- sprintf(pos, "%s@%s", signal, obj);
-
- /* copy the environment key by key to our continuous buffer */
- if (envp) {
- int i;
-
- for (i = 2; envp[i]; i++) {
- len = strlen(envp[i]) + 1;
- pos = skb_put(skb, len);
- strcpy(pos, envp[i]);
- }
- }
-
- NETLINK_CB(skb).dst_group = 1;
- return netlink_broadcast(uevent_sock, skb, 0, 1, gfp_mask);
-}
-
-static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr, gfp_t gfp_mask)
-{
- char *path;
- char *attrpath;
- char *signal;
- int len;
- int rc = -ENOMEM;
-
- path = kobject_get_path(kobj, gfp_mask);
- if (!path)
- return -ENOMEM;
-
- signal = action_to_string(action);
- if (!signal)
- return -EINVAL;
-
- if (attr) {
- len = strlen(path);
- len += strlen(attr->name) + 2;
- attrpath = kmalloc(len, gfp_mask);
- if (!attrpath)
- goto exit;
- sprintf(attrpath, "%s/%s", path, attr->name);
- rc = send_uevent(signal, attrpath, NULL, gfp_mask);
- kfree(attrpath);
- } else
- rc = send_uevent(signal, path, NULL, gfp_mask);
-
-exit:
- kfree(path);
- return rc;
-}
-
-/**
- * kobject_uevent - notify userspace by sending event through netlink socket
- *
- * @signal: signal name
- * @kobj: struct kobject that the event is happening to
- * @attr: optional struct attribute the event belongs to
- */
-int kobject_uevent(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr)
-{
- return do_kobject_uevent(kobj, action, attr, GFP_KERNEL);
-}
-EXPORT_SYMBOL_GPL(kobject_uevent);
-
-int kobject_uevent_atomic(struct kobject *kobj, enum kobject_action action,
- struct attribute *attr)
-{
- return do_kobject_uevent(kobj, action, attr, GFP_ATOMIC);
-}
-EXPORT_SYMBOL_GPL(kobject_uevent_atomic);
-
-static int __init kobject_uevent_init(void)
-{
- uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
- THIS_MODULE);
-
- if (!uevent_sock) {
- printk(KERN_ERR
- "kobject_uevent: unable to create netlink socket!\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-postcore_initcall(kobject_uevent_init);
-
-#else
-static inline int send_uevent(const char *signal, const char *obj,
- char **envp, int gfp_mask)
-{
- return 0;
-}
-
-#endif /* CONFIG_KOBJECT_UEVENT */
-
-
-#ifdef CONFIG_HOTPLUG
-char hotplug_path[HOTPLUG_PATH_LEN] = "/sbin/hotplug";
-u64 hotplug_seqnum;
-static DEFINE_SPINLOCK(sequence_lock);
-
-/**
- * kobject_hotplug - notify userspace by executing /sbin/hotplug
- *
- * @action: action that is happening (usually "ADD" or "REMOVE")
+ * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
* @kobj: struct kobject that the action is happening to
*/
-void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
+void kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
- char *argv [3];
- char **envp = NULL;
- char *buffer = NULL;
- char *seq_buff;
+ char **envp;
+ char *buffer;
char *scratch;
+ const char *action_string;
+ const char *devpath = NULL;
+ const char *subsystem;
+ struct kobject *top_kobj;
+ struct kset *kset;
+ struct kset_uevent_ops *uevent_ops;
+ u64 seq;
+ char *seq_buff;
int i = 0;
int retval;
- char *kobj_path = NULL;
- const char *name = NULL;
- char *action_string;
- u64 seq;
- struct kobject *top_kobj = kobj;
- struct kset *kset;
- static struct kset_hotplug_ops null_hotplug_ops;
- struct kset_hotplug_ops *hotplug_ops = &null_hotplug_ops;
- /* If this kobj does not belong to a kset,
- try to find a parent that does. */
+ pr_debug("%s\n", __FUNCTION__);
+
+ action_string = action_to_string(action);
+ if (!action_string)
+ return;
+
+ /* search the kset we belong to */
+ top_kobj = kobj;
if (!top_kobj->kset && top_kobj->parent) {
do {
top_kobj = top_kobj->parent;
} while (!top_kobj->kset && top_kobj->parent);
}
-
- if (top_kobj->kset)
- kset = top_kobj->kset;
- else
+ if (!top_kobj->kset)
return;
- if (kset->hotplug_ops)
- hotplug_ops = kset->hotplug_ops;
+ kset = top_kobj->kset;
+ uevent_ops = kset->uevent_ops;
- /* If the kset has a filter operation, call it.
- Skip the event, if the filter returns zero. */
- if (hotplug_ops->filter) {
- if (!hotplug_ops->filter(kset, kobj))
+ /* skip the event, if the filter returns zero. */
+ if (uevent_ops && uevent_ops->filter)
+ if (!uevent_ops->filter(kset, kobj))
return;
- }
- pr_debug ("%s\n", __FUNCTION__);
-
- action_string = action_to_string(action);
- if (!action_string)
- return;
-
- envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
+ /* environment index */
+ envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
if (!envp)
return;
- memset (envp, 0x00, NUM_ENVP * sizeof (char *));
+ /* environment values */
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
if (!buffer)
goto exit;
- if (hotplug_ops->name)
- name = hotplug_ops->name(kset, kobj);
- if (name == NULL)
- name = kobject_name(&kset->kobj);
+ /* complete object path */
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath)
+ goto exit;
- argv [0] = hotplug_path;
- argv [1] = (char *)name; /* won't be changed but 'const' has to go */
- argv [2] = NULL;
+ /* originating subsystem */
+ if (uevent_ops && uevent_ops->name)
+ subsystem = uevent_ops->name(kset, kobj);
+ else
+ subsystem = kobject_name(&kset->kobj);
- /* minimal command environment */
- envp [i++] = "HOME=/";
- envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ /* event environemnt for helper process only */
+ envp[i++] = "HOME=/";
+ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ /* default keys */
scratch = buffer;
-
envp [i++] = scratch;
scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
-
- kobj_path = kobject_get_path(kobj, GFP_KERNEL);
- if (!kobj_path)
- goto exit;
-
envp [i++] = scratch;
- scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
-
+ scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp [i++] = scratch;
- scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
+ scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
- /* reserve space for the sequence,
- * put the real one in after the hotplug call */
+ /* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
- if (hotplug_ops->hotplug) {
- /* have the kset specific function add its stuff */
- retval = hotplug_ops->hotplug (kset, kobj,
+ /* let the kset specific function add its stuff */
+ if (uevent_ops && uevent_ops->uevent) {
+ retval = uevent_ops->uevent(kset, kobj,
&envp[i], NUM_ENVP - i, scratch,
BUFFER_SIZE - (scratch - buffer));
if (retval) {
- pr_debug ("%s - hotplug() returned %d\n",
+ pr_debug ("%s - uevent() returned %d\n",
__FUNCTION__, retval);
goto exit;
}
}
+ /* we will send an event, request a new sequence number */
spin_lock(&sequence_lock);
- seq = ++hotplug_seqnum;
+ seq = ++uevent_seqnum;
spin_unlock(&sequence_lock);
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
- pr_debug ("%s: %s %s seq=%llu %s %s %s %s %s\n",
- __FUNCTION__, argv[0], argv[1], (unsigned long long)seq,
- envp[0], envp[1], envp[2], envp[3], envp[4]);
-
- send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
+ /* send netlink message */
+ if (uevent_sock) {
+ struct sk_buff *skb;
+ size_t len;
+
+ /* allocate message with the maximum possible size */
+ len = strlen(action_string) + strlen(devpath) + 2;
+ skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL);
+ if (skb) {
+ /* add header */
+ scratch = skb_put(skb, len);
+ sprintf(scratch, "%s@%s", action_string, devpath);
+
+ /* copy keys to our continuous event payload buffer */
+ for (i = 2; envp[i]; i++) {
+ len = strlen(envp[i]) + 1;
+ scratch = skb_put(skb, len);
+ strcpy(scratch, envp[i]);
+ }
+
+ NETLINK_CB(skb).dst_group = 1;
+ netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
+ }
+ }
- if (!hotplug_path[0])
- goto exit;
+ /* call uevent_helper, usually only enabled during early boot */
+ if (uevent_helper[0]) {
+ char *argv [3];
- retval = call_usermodehelper (argv[0], argv, envp, 0);
- if (retval)
- pr_debug ("%s - call_usermodehelper returned %d\n",
- __FUNCTION__, retval);
+ argv [0] = uevent_helper;
+ argv [1] = (char *)subsystem;
+ argv [2] = NULL;
+ call_usermodehelper (argv[0], argv, envp, 0);
+ }
exit:
- kfree(kobj_path);
+ kfree(devpath);
kfree(buffer);
kfree(envp);
return;
}
-EXPORT_SYMBOL(kobject_hotplug);
+EXPORT_SYMBOL_GPL(kobject_uevent);
/**
- * add_hotplug_env_var - helper for creating hotplug environment variables
+ * add_uevent_var - helper for creating event variables
* @envp: Pointer to table of environment variables, as passed into
- * hotplug() method.
+ * uevent() method.
* @num_envp: Number of environment variable slots available, as
- * passed into hotplug() method.
+ * passed into uevent() method.
* @cur_index: Pointer to current index into @envp. It should be
- * initialized to 0 before the first call to add_hotplug_env_var(),
+ * initialized to 0 before the first call to add_uevent_var(),
* and will be incremented on success.
* @buffer: Pointer to buffer for environment variables, as passed
- * into hotplug() method.
- * @buffer_size: Length of @buffer, as passed into hotplug() method.
+ * into uevent() method.
+ * @buffer_size: Length of @buffer, as passed into uevent() method.
* @cur_len: Pointer to current length of space used in @buffer.
* Should be initialized to 0 before the first call to
- * add_hotplug_env_var(), and will be incremented on success.
+ * add_uevent_var(), and will be incremented on success.
* @format: Format for creating environment variable (of the form
* "XXX=%x") for snprintf().
*
* Returns 0 if environment variable was added successfully or -ENOMEM
* if no space was available.
*/
-int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size, int *cur_len,
- const char *format, ...)
+int add_uevent_var(char **envp, int num_envp, int *cur_index,
+ char *buffer, int buffer_size, int *cur_len,
+ const char *format, ...)
{
va_list args;
/*
* We check against num_envp - 1 to make sure there is at
- * least one slot left after we return, since the hotplug
- * method needs to set the last slot to NULL.
+ * least one slot left after we return, since kobject_uevent()
+ * needs to set the last slot to NULL.
*/
if (*cur_index >= num_envp - 1)
return -ENOMEM;
@@ -366,6 +241,22 @@ int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
(*cur_index)++;
return 0;
}
-EXPORT_SYMBOL(add_hotplug_env_var);
+EXPORT_SYMBOL_GPL(add_uevent_var);
+
+static int __init kobject_uevent_init(void)
+{
+ uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
+ THIS_MODULE);
+
+ if (!uevent_sock) {
+ printk(KERN_ERR
+ "kobject_uevent: unable to create netlink socket!\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+postcore_initcall(kobject_uevent_init);
#endif /* CONFIG_HOTPLUG */
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 88511c3805ad..c0bd4a914803 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -137,18 +137,31 @@ out:
static inline void tag_set(struct radix_tree_node *node, int tag, int offset)
{
- if (!test_bit(offset, &node->tags[tag][0]))
- __set_bit(offset, &node->tags[tag][0]);
+ __set_bit(offset, node->tags[tag]);
}
static inline void tag_clear(struct radix_tree_node *node, int tag, int offset)
{
- __clear_bit(offset, &node->tags[tag][0]);
+ __clear_bit(offset, node->tags[tag]);
}
static inline int tag_get(struct radix_tree_node *node, int tag, int offset)
{
- return test_bit(offset, &node->tags[tag][0]);
+ return test_bit(offset, node->tags[tag]);
+}
+
+/*
+ * Returns 1 if any slot in the node has this tag set.
+ * Otherwise returns 0.
+ */
+static inline int any_tag_set(struct radix_tree_node *node, int tag)
+{
+ int idx;
+ for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
+ if (node->tags[tag][idx])
+ return 1;
+ }
+ return 0;
}
/*
@@ -185,15 +198,9 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
* into the newly-pushed top-level node(s)
*/
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
- int idx;
-
tags[tag] = 0;
- for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (root->rnode->tags[tag][idx]) {
- tags[tag] = 1;
- break;
- }
- }
+ if (any_tag_set(root->rnode, tag))
+ tags[tag] = 1;
}
do {
@@ -246,7 +253,7 @@ int radix_tree_insert(struct radix_tree_root *root,
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
offset = 0; /* uninitialised var warning */
- while (height > 0) {
+ do {
if (slot == NULL) {
/* Have to add a child node. */
if (!(slot = radix_tree_node_alloc(root)))
@@ -264,18 +271,16 @@ int radix_tree_insert(struct radix_tree_root *root,
slot = node->slots[offset];
shift -= RADIX_TREE_MAP_SHIFT;
height--;
- }
+ } while (height > 0);
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;
+ BUG_ON(!node);
+ node->count++;
+ node->slots[offset] = item;
+ BUG_ON(tag_get(node, 0, offset));
+ BUG_ON(tag_get(node, 1, offset));
return 0;
}
@@ -367,7 +372,8 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
int offset;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
- tag_set(slot, tag, offset);
+ if (!tag_get(slot, tag, offset))
+ tag_set(slot, tag, offset);
slot = slot->slots[offset];
BUG_ON(slot == NULL);
shift -= RADIX_TREE_MAP_SHIFT;
@@ -427,13 +433,11 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
goto out;
do {
- int idx;
-
+ if (!tag_get(pathp->node, tag, pathp->offset))
+ goto out;
tag_clear(pathp->node, tag, pathp->offset);
- for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (pathp->node->tags[tag][idx])
- goto out;
- }
+ if (any_tag_set(pathp->node, tag))
+ goto out;
pathp--;
} while (pathp->node);
out:
@@ -674,6 +678,29 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
EXPORT_SYMBOL(radix_tree_gang_lookup_tag);
/**
+ * radix_tree_shrink - shrink height of a radix tree to minimal
+ * @root radix tree root
+ */
+static inline void radix_tree_shrink(struct radix_tree_root *root)
+{
+ /* try to shrink tree height */
+ while (root->height > 1 &&
+ root->rnode->count == 1 &&
+ root->rnode->slots[0]) {
+ struct radix_tree_node *to_free = root->rnode;
+
+ root->rnode = to_free->slots[0];
+ root->height--;
+ /* must only free zeroed nodes into the slab */
+ tag_clear(to_free, 0, 0);
+ tag_clear(to_free, 1, 0);
+ to_free->slots[0] = NULL;
+ to_free->count = 0;
+ radix_tree_node_free(to_free);
+ }
+}
+
+/**
* radix_tree_delete - delete an item from a radix tree
* @root: radix tree root
* @index: index key
@@ -691,6 +718,8 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
void *ret = NULL;
char tags[RADIX_TREE_TAGS];
int nr_cleared_tags;
+ int tag;
+ int offset;
height = root->height;
if (index > radix_tree_maxindex(height))
@@ -701,16 +730,14 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
slot = root->rnode;
for ( ; height > 0; height--) {
- int offset;
-
if (slot == NULL)
goto out;
+ pathp++;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
- pathp[1].offset = offset;
- pathp[1].node = slot;
+ pathp->offset = offset;
+ pathp->node = slot;
slot = slot->slots[offset];
- pathp++;
shift -= RADIX_TREE_MAP_SHIFT;
}
@@ -723,35 +750,39 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
/*
* Clear all tags associated with the just-deleted item
*/
- memset(tags, 0, sizeof(tags));
- do {
- int tag;
+ nr_cleared_tags = 0;
+ for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
+ if (tag_get(pathp->node, tag, pathp->offset)) {
+ tag_clear(pathp->node, tag, pathp->offset);
+ tags[tag] = 0;
+ nr_cleared_tags++;
+ } else
+ tags[tag] = 1;
+ }
- nr_cleared_tags = RADIX_TREE_TAGS;
+ for (pathp--; nr_cleared_tags && pathp->node; pathp--) {
for (tag = 0; tag < RADIX_TREE_TAGS; tag++) {
- int idx;
-
if (tags[tag])
continue;
tag_clear(pathp->node, tag, pathp->offset);
-
- for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (pathp->node->tags[tag][idx]) {
- tags[tag] = 1;
- nr_cleared_tags--;
- break;
- }
+ if (any_tag_set(pathp->node, tag)) {
+ tags[tag] = 1;
+ nr_cleared_tags--;
}
}
- pathp--;
- } while (pathp->node && nr_cleared_tags);
+ }
/* 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)
+ pathp->node->count--;
+
+ if (pathp->node->count) {
+ if (pathp->node == root->rnode)
+ radix_tree_shrink(root);
goto out;
+ }
/* Node with zero slots in use so free it */
radix_tree_node_free(pathp->node);
@@ -770,15 +801,11 @@ EXPORT_SYMBOL(radix_tree_delete);
*/
int radix_tree_tagged(struct radix_tree_root *root, int tag)
{
- int idx;
-
- if (!root->rnode)
- return 0;
- for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) {
- if (root->rnode->tags[tag][idx])
- return 1;
- }
- return 0;
+ struct radix_tree_node *rnode;
+ rnode = root->rnode;
+ if (!rnode)
+ return 0;
+ return any_tag_set(rnode, tag);
}
EXPORT_SYMBOL(radix_tree_tagged);
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index dcd4be9bd4e5..c8bb8cc899d7 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -19,10 +19,11 @@ static void spin_bug(spinlock_t *lock, const char *msg)
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",
+ printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
msg, raw_smp_processor_id(),
current->comm, current->pid);
- printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n",
+ printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
+ ".owner_cpu: %d\n",
lock, lock->magic,
owner ? owner->comm : "<none>",
owner ? owner->pid : -1,
@@ -78,7 +79,8 @@ static void __spin_lock_debug(spinlock_t *lock)
/* lockup suspected: */
if (print_once) {
print_once = 0;
- printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n",
+ printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
+ "%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
@@ -120,8 +122,8 @@ 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,
- raw_smp_processor_id(), current->comm,
+ printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
+ msg, raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
#ifdef CONFIG_SMP
@@ -149,7 +151,8 @@ static void __read_lock_debug(rwlock_t *lock)
/* lockup suspected: */
if (print_once) {
print_once = 0;
- printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n",
+ printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
+ "%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
@@ -221,7 +224,8 @@ static void __write_lock_debug(rwlock_t *lock)
/* lockup suspected: */
if (print_once) {
print_once = 0;
- printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n",
+ printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
+ "%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1ff8dcebf7c6..0af497b6b9a8 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -142,8 +142,7 @@ swiotlb_init_with_default_size (size_t default_size)
/*
* Get IO TLB memory from the low pages
*/
- io_tlb_start = alloc_bootmem_low_pages_limit(io_tlb_nslabs *
- (1 << IO_TLB_SHIFT), 0x100000000);
+ io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
if (!io_tlb_start)
panic("Cannot allocate SWIOTLB buffer");
io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
@@ -464,7 +463,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
*/
dma_addr_t handle;
handle = swiotlb_map_single(NULL, NULL, size, DMA_FROM_DEVICE);
- if (dma_mapping_error(handle))
+ if (swiotlb_dma_mapping_error(handle))
return NULL;
ret = phys_to_virt(handle);
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index ad9a1bf4fc63..1653dd9bb01a 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -255,6 +255,7 @@ int zlib_deflateInit2_(
}
/* ========================================================================= */
+#if 0
int zlib_deflateSetDictionary(
z_streamp strm,
const Byte *dictionary,
@@ -297,6 +298,7 @@ int zlib_deflateSetDictionary(
if (hash_head) hash_head = 0; /* to make compiler happy */
return Z_OK;
}
+#endif /* 0 */
/* ========================================================================= */
int zlib_deflateReset(
@@ -330,6 +332,7 @@ int zlib_deflateReset(
}
/* ========================================================================= */
+#if 0
int zlib_deflateParams(
z_streamp strm,
int level,
@@ -365,6 +368,7 @@ int zlib_deflateParams(
s->strategy = strategy;
return err;
}
+#endif /* 0 */
/* =========================================================================
* Put a short in the pending buffer. The 16-bit value is put in MSB order.
@@ -572,6 +576,7 @@ int zlib_deflateEnd(
/* =========================================================================
* Copy the source state to the destination state.
*/
+#if 0
int zlib_deflateCopy (
z_streamp dest,
z_streamp source
@@ -624,6 +629,7 @@ int zlib_deflateCopy (
return Z_OK;
#endif
}
+#endif /* 0 */
/* ===========================================================================
* Read a new buffer from the current input stream, update the adler32
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
index 5985b28c8e30..767b573d1ef6 100644
--- a/lib/zlib_deflate/deflate_syms.c
+++ b/lib/zlib_deflate/deflate_syms.c
@@ -16,6 +16,4 @@ EXPORT_SYMBOL(zlib_deflateInit_);
EXPORT_SYMBOL(zlib_deflateInit2_);
EXPORT_SYMBOL(zlib_deflateEnd);
EXPORT_SYMBOL(zlib_deflateReset);
-EXPORT_SYMBOL(zlib_deflateCopy);
-EXPORT_SYMBOL(zlib_deflateParams);
MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c
index 50f21ca4ef7f..c16cdeff51aa 100644
--- a/lib/zlib_inflate/infblock.c
+++ b/lib/zlib_inflate/infblock.c
@@ -338,6 +338,7 @@ int zlib_inflate_blocks_free(
}
+#if 0
void zlib_inflate_set_dictionary(
inflate_blocks_statef *s,
const Byte *d,
@@ -347,15 +348,18 @@ void zlib_inflate_set_dictionary(
memcpy(s->window, d, n);
s->read = s->write = s->window + n;
}
+#endif /* 0 */
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH.
* IN assertion: s != NULL
*/
+#if 0
int zlib_inflate_blocks_sync_point(
inflate_blocks_statef *s
)
{
return s->mode == LENS;
}
+#endif /* 0 */
diff --git a/lib/zlib_inflate/infblock.h b/lib/zlib_inflate/infblock.h
index f5221ddf6054..ceee60b5107c 100644
--- a/lib/zlib_inflate/infblock.h
+++ b/lib/zlib_inflate/infblock.h
@@ -33,12 +33,16 @@ extern int zlib_inflate_blocks_free (
inflate_blocks_statef *,
z_streamp);
+#if 0
extern void zlib_inflate_set_dictionary (
inflate_blocks_statef *s,
const Byte *d, /* dictionary */
uInt n); /* dictionary length */
+#endif /* 0 */
+#if 0
extern int zlib_inflate_blocks_sync_point (
inflate_blocks_statef *s);
+#endif /* 0 */
#endif /* _INFBLOCK_H */
diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
index aa1b08189121..ef49738f57ec 100644
--- a/lib/zlib_inflate/inflate_syms.c
+++ b/lib/zlib_inflate/inflate_syms.c
@@ -15,8 +15,6 @@ EXPORT_SYMBOL(zlib_inflate);
EXPORT_SYMBOL(zlib_inflateInit_);
EXPORT_SYMBOL(zlib_inflateInit2_);
EXPORT_SYMBOL(zlib_inflateEnd);
-EXPORT_SYMBOL(zlib_inflateSync);
EXPORT_SYMBOL(zlib_inflateReset);
-EXPORT_SYMBOL(zlib_inflateSyncPoint);
EXPORT_SYMBOL(zlib_inflateIncomp);
MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c
index e07bdb21f55c..61411ff89d61 100644
--- a/lib/zlib_inflate/inflate_sync.c
+++ b/lib/zlib_inflate/inflate_sync.c
@@ -7,6 +7,7 @@
#include "infblock.h"
#include "infutil.h"
+#if 0
int zlib_inflateSync(
z_streamp z
)
@@ -57,6 +58,7 @@ int zlib_inflateSync(
z->state->mode = BLOCKS;
return Z_OK;
}
+#endif /* 0 */
/* Returns true if inflate is currently at the end of a block generated
@@ -66,6 +68,7 @@ int zlib_inflateSync(
* decompressing, PPP checks that at the end of input packet, inflate is
* waiting for these length bytes.
*/
+#if 0
int zlib_inflateSyncPoint(
z_streamp z
)
@@ -74,6 +77,7 @@ int zlib_inflateSyncPoint(
return Z_STREAM_ERROR;
return zlib_inflate_blocks_sync_point(z->state->blocks);
}
+#endif /* 0 */
/*
* This subroutine adds the data at next_in/avail_in to the output history
diff --git a/mm/Kconfig b/mm/Kconfig
index 21eb51d4da8f..a9cb80ae6409 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -11,7 +11,7 @@ choice
config FLATMEM_MANUAL
bool "Flat Memory"
- depends on !ARCH_DISCONTIGMEM_ENABLE || ARCH_FLATMEM_ENABLE
+ depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || ARCH_FLATMEM_ENABLE
help
This option allows you to change some of the ways that
Linux manages its memory internally. Most users will
@@ -132,3 +132,10 @@ config SPLIT_PTLOCK_CPUS
default "4096" if ARM && !CPU_CACHE_VIPT
default "4096" if PARISC && !PA20
default "4"
+
+#
+# support for page migration
+#
+config MIGRATION
+ def_bool y if NUMA || SPARSEMEM || DISCONTIGMEM
+ depends on SWAP
diff --git a/mm/Makefile b/mm/Makefile
index 2fa6d2ca9f28..9aa03fa1dcc3 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -9,8 +9,8 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
page_alloc.o page-writeback.o pdflush.o \
- readahead.o slab.o swap.o truncate.o vmscan.o \
- prio_tree.o $(mmu-y)
+ readahead.o swap.o truncate.o vmscan.o \
+ prio_tree.o util.o $(mmu-y)
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
@@ -18,5 +18,7 @@ obj-$(CONFIG_NUMA) += mempolicy.o
obj-$(CONFIG_SPARSEMEM) += sparse.o
obj-$(CONFIG_SHMEM) += shmem.o
obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
+obj-$(CONFIG_SLOB) += slob.o
+obj-$(CONFIG_SLAB) += slab.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
obj-$(CONFIG_FS_XIP) += filemap_xip.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 16b9465eb4eb..35c32290f717 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -296,20 +296,12 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
unsigned long v = ~map[i / BITS_PER_LONG];
if (gofast && v == ~0UL) {
- int j, order;
+ int order;
page = pfn_to_page(pfn);
count += BITS_PER_LONG;
- __ClearPageReserved(page);
order = ffs(BITS_PER_LONG) - 1;
- set_page_refs(page, order);
- for (j = 1; j < BITS_PER_LONG; j++) {
- if (j + 16 < BITS_PER_LONG)
- prefetchw(page + j + 16);
- __ClearPageReserved(page + j);
- set_page_count(page + j, 0);
- }
- __free_pages(page, order);
+ __free_pages_bootmem(page, order);
i += BITS_PER_LONG;
page += BITS_PER_LONG;
} else if (v) {
@@ -319,9 +311,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
for (m = 1; m && i < idx; m<<=1, page++, i++) {
if (v & m) {
count++;
- __ClearPageReserved(page);
- set_page_refs(page, 0);
- __free_page(page);
+ __free_pages_bootmem(page, 0);
}
}
} else {
@@ -339,9 +329,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
count = 0;
for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
count++;
- __ClearPageReserved(page);
- set_page_count(page, 1);
- __free_page(page);
+ __free_pages_bootmem(page, 0);
}
total += count;
bdata->node_bootmem_map = NULL;
@@ -393,15 +381,14 @@ unsigned long __init free_all_bootmem (void)
return(free_all_bootmem_core(NODE_DATA(0)));
}
-void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal,
- unsigned long limit)
+void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal)
{
pg_data_t *pgdat = pgdat_list;
void *ptr;
for_each_pgdat(pgdat)
if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
- align, goal, limit)))
+ align, goal, 0)))
return(ptr);
/*
@@ -413,15 +400,40 @@ void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, un
}
-void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align,
- unsigned long goal, unsigned long limit)
+void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigned long align,
+ unsigned long goal)
{
void *ptr;
- ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit);
+ ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
if (ptr)
return (ptr);
- return __alloc_bootmem_limit(size, align, goal, limit);
+ return __alloc_bootmem(size, align, goal);
+}
+
+#define LOW32LIMIT 0xffffffff
+
+void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal)
+{
+ pg_data_t *pgdat = pgdat_list;
+ void *ptr;
+
+ for_each_pgdat(pgdat)
+ if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
+ align, goal, LOW32LIMIT)))
+ return(ptr);
+
+ /*
+ * Whoops, we cannot satisfy the allocation request.
+ */
+ printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size);
+ panic("Out of low memory");
+ return NULL;
}
+void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
+ unsigned long align, unsigned long goal)
+{
+ return __alloc_bootmem_core(pgdat->bdata, size, align, goal, LOW32LIMIT);
+}
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 5f19e87bc5af..d257c89e7704 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -37,6 +37,11 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
if (!file)
return -EBADF;
+ if (S_ISFIFO(file->f_dentry->d_inode->i_mode)) {
+ ret = -ESPIPE;
+ goto out;
+ }
+
mapping = file->f_mapping;
if (!mapping || len < 0) {
ret = -EINVAL;
diff --git a/mm/filemap.c b/mm/filemap.c
index 33a28bfde158..44da3d476994 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/fs.h>
#include <linux/aio.h>
+#include <linux/capability.h>
#include <linux/kernel_stat.h>
#include <linux/mm.h>
#include <linux/swap.h>
@@ -61,7 +62,7 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* ->swap_lock (exclusive_swap_page, others)
* ->mapping->tree_lock
*
- * ->i_sem
+ * ->i_mutex
* ->i_mmap_lock (truncate->unmap_mapping_range)
*
* ->mmap_sem
@@ -73,9 +74,9 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* ->lock_page (access_process_vm)
*
* ->mmap_sem
- * ->i_sem (msync)
+ * ->i_mutex (msync)
*
- * ->i_sem
+ * ->i_mutex
* ->i_alloc_sem (various)
*
* ->inode_lock
@@ -93,6 +94,7 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
* ->private_lock (try_to_unmap_one)
* ->tree_lock (try_to_unmap_one)
* ->zone.lru_lock (follow_page->mark_page_accessed)
+ * ->zone.lru_lock (check_pte_range->isolate_lru_page)
* ->private_lock (page_remove_rmap->set_page_dirty)
* ->tree_lock (page_remove_rmap->set_page_dirty)
* ->inode_lock (page_remove_rmap->set_page_dirty)
@@ -276,11 +278,11 @@ static int wait_on_page_writeback_range(struct address_space *mapping,
* integrity" operation. It waits upon in-flight writeout before starting and
* waiting upon new writeout. If there was an IO error, return it.
*
- * We need to re-take i_sem during the generic_osync_inode list walk because
+ * We need to re-take i_mutex during the generic_osync_inode list walk because
* it is otherwise livelockable.
*/
int sync_page_range(struct inode *inode, struct address_space *mapping,
- loff_t pos, size_t count)
+ loff_t pos, loff_t count)
{
pgoff_t start = pos >> PAGE_CACHE_SHIFT;
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
@@ -290,9 +292,9 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0) {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = generic_osync_inode(inode, mapping, OSYNC_METADATA);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
if (ret == 0)
ret = wait_on_page_writeback_range(mapping, start, end);
@@ -301,13 +303,12 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
EXPORT_SYMBOL(sync_page_range);
/*
- * Note: Holding i_sem across sync_page_range_nolock is not a good idea
+ * Note: Holding i_mutex across sync_page_range_nolock is not a good idea
* as it forces O_SYNC writers to different parts of the same file
* to be serialised right until io completion.
*/
-static int sync_page_range_nolock(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, loff_t count)
{
pgoff_t start = pos >> PAGE_CACHE_SHIFT;
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
@@ -322,6 +323,7 @@ static int sync_page_range_nolock(struct inode *inode,
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
@@ -343,30 +345,44 @@ EXPORT_SYMBOL(filemap_fdatawait);
int filemap_write_and_wait(struct address_space *mapping)
{
- int retval = 0;
+ int err = 0;
if (mapping->nrpages) {
- retval = filemap_fdatawrite(mapping);
- if (retval == 0)
- retval = filemap_fdatawait(mapping);
+ err = filemap_fdatawrite(mapping);
+ /*
+ * Even if the above returned error, the pages may be
+ * written partially (e.g. -ENOSPC), so we wait for it.
+ * But the -EIO is special case, it may indicate the worst
+ * thing (e.g. bug) happened, so we avoid waiting for it.
+ */
+ if (err != -EIO) {
+ int err2 = filemap_fdatawait(mapping);
+ if (!err)
+ err = err2;
+ }
}
- return retval;
+ return err;
}
+EXPORT_SYMBOL(filemap_write_and_wait);
int filemap_write_and_wait_range(struct address_space *mapping,
loff_t lstart, loff_t lend)
{
- int retval = 0;
+ int err = 0;
if (mapping->nrpages) {
- retval = __filemap_fdatawrite_range(mapping, lstart, lend,
- WB_SYNC_ALL);
- if (retval == 0)
- retval = wait_on_page_writeback_range(mapping,
- lstart >> PAGE_CACHE_SHIFT,
- lend >> PAGE_CACHE_SHIFT);
+ err = __filemap_fdatawrite_range(mapping, lstart, lend,
+ WB_SYNC_ALL);
+ /* See comment of filemap_write_and_wait() */
+ if (err != -EIO) {
+ int err2 = wait_on_page_writeback_range(mapping,
+ lstart >> PAGE_CACHE_SHIFT,
+ lend >> PAGE_CACHE_SHIFT);
+ if (!err)
+ err = err2;
+ }
}
- return retval;
+ return err;
}
/*
@@ -555,11 +571,12 @@ repeat:
page_cache_get(page);
if (TestSetPageLocked(page)) {
read_unlock_irq(&mapping->tree_lock);
- lock_page(page);
+ __lock_page(page);
read_lock_irq(&mapping->tree_lock);
/* Has the page been truncated while we slept? */
- if (page->mapping != mapping || page->index != offset) {
+ if (unlikely(page->mapping != mapping ||
+ page->index != offset)) {
unlock_page(page);
page_cache_release(page);
goto repeat;
@@ -831,8 +848,13 @@ readpage:
/* Start the actual read. The read will unlock the page. */
error = mapping->a_ops->readpage(filp, page);
- if (unlikely(error))
+ if (unlikely(error)) {
+ if (error == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto find_page;
+ }
goto readpage_error;
+ }
if (!PageUptodate(page)) {
lock_page(page);
@@ -1152,26 +1174,24 @@ static int fastcall page_cache_read(struct file * file, unsigned long offset)
{
struct address_space *mapping = file->f_mapping;
struct page *page;
- int error;
+ int ret;
- page = page_cache_alloc_cold(mapping);
- if (!page)
- return -ENOMEM;
+ do {
+ page = page_cache_alloc_cold(mapping);
+ if (!page)
+ return -ENOMEM;
+
+ ret = add_to_page_cache_lru(page, mapping, offset, GFP_KERNEL);
+ if (ret == 0)
+ ret = mapping->a_ops->readpage(file, page);
+ else if (ret == -EEXIST)
+ ret = 0; /* losing race to add is OK */
- error = add_to_page_cache_lru(page, mapping, offset, GFP_KERNEL);
- if (!error) {
- error = mapping->a_ops->readpage(file, page);
page_cache_release(page);
- return error;
- }
- /*
- * We arrive here in the unlikely event that someone
- * raced with us and added our page to the cache first
- * or we are out of memory for radix-tree nodes.
- */
- page_cache_release(page);
- return error == -EEXIST ? 0 : error;
+ } while (ret == AOP_TRUNCATED_PAGE);
+
+ return ret;
}
#define MMAP_LOTSAMISS (100)
@@ -1331,10 +1351,14 @@ page_not_uptodate:
goto success;
}
- if (!mapping->a_ops->readpage(file, page)) {
+ error = mapping->a_ops->readpage(file, page);
+ if (!error) {
wait_on_page_locked(page);
if (PageUptodate(page))
goto success;
+ } else if (error == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry_find;
}
/*
@@ -1358,10 +1382,14 @@ page_not_uptodate:
goto success;
}
ClearPageError(page);
- if (!mapping->a_ops->readpage(file, page)) {
+ error = mapping->a_ops->readpage(file, page);
+ if (!error) {
wait_on_page_locked(page);
if (PageUptodate(page))
goto success;
+ } else if (error == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry_find;
}
/*
@@ -1444,10 +1472,14 @@ page_not_uptodate:
goto success;
}
- if (!mapping->a_ops->readpage(file, page)) {
+ error = mapping->a_ops->readpage(file, page);
+ if (!error) {
wait_on_page_locked(page);
if (PageUptodate(page))
goto success;
+ } else if (error == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry_find;
}
/*
@@ -1470,10 +1502,14 @@ page_not_uptodate:
}
ClearPageError(page);
- if (!mapping->a_ops->readpage(file, page)) {
+ error = mapping->a_ops->readpage(file, page);
+ if (!error) {
wait_on_page_locked(page);
if (PageUptodate(page))
goto success;
+ } else if (error == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ goto retry_find;
}
/*
@@ -1858,7 +1894,7 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
/*
* Sync the fs metadata but not the minor inode changes and
* of course not the data as we did direct DMA for the IO.
- * i_sem is held, which protects generic_osync_inode() from
+ * i_mutex is held, which protects generic_osync_inode() from
* livelocking.
*/
if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
@@ -1934,12 +1970,16 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
status = a_ops->prepare_write(file, page, offset, offset+bytes);
if (unlikely(status)) {
loff_t isize = i_size_read(inode);
+
+ if (status != AOP_TRUNCATED_PAGE)
+ unlock_page(page);
+ page_cache_release(page);
+ if (status == AOP_TRUNCATED_PAGE)
+ continue;
/*
* prepare_write() may have instantiated a few blocks
* outside i_size. Trim these off again.
*/
- unlock_page(page);
- page_cache_release(page);
if (pos + bytes > isize)
vmtruncate(inode, isize);
break;
@@ -1952,6 +1992,10 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
cur_iov, iov_base, bytes);
flush_dcache_page(page);
status = a_ops->commit_write(file, page, offset, offset+bytes);
+ if (status == AOP_TRUNCATED_PAGE) {
+ page_cache_release(page);
+ continue;
+ }
if (likely(copied > 0)) {
if (!status)
status = copied;
@@ -2066,7 +2110,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
if (err)
goto out;
- inode_update_time(inode, 1);
+ file_update_time(file);
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (unlikely(file->f_flags & O_DIRECT)) {
@@ -2153,10 +2197,10 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
BUG_ON(iocb->ki_pos != pos);
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = __generic_file_aio_write_nolock(iocb, &local_iov, 1,
&iocb->ki_pos);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
ssize_t err;
@@ -2178,9 +2222,9 @@ ssize_t generic_file_write(struct file *file, const char __user *buf,
struct iovec local_iov = { .iov_base = (void __user *)buf,
.iov_len = count };
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = __generic_file_write_nolock(file, &local_iov, 1, ppos);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
ssize_t err;
@@ -2214,9 +2258,9 @@ ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
struct inode *inode = mapping->host;
ssize_t ret;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
ret = __generic_file_write_nolock(file, iov, nr_segs, ppos);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
int err;
@@ -2230,7 +2274,7 @@ ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
EXPORT_SYMBOL(generic_file_writev);
/*
- * Called under i_sem for writes to S_ISREG files. Returns -EIO if something
+ * Called under i_mutex for writes to S_ISREG files. Returns -EIO if something
* went wrong during pagecache shootdown.
*/
static ssize_t
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 9cf687e4a29a..b960ac8e5918 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -338,7 +338,7 @@ __xip_file_write(struct file *filp, const char __user *buf,
*ppos = pos;
/*
* No need to use i_size_read() here, the i_size
- * cannot change under us because we hold i_sem.
+ * cannot change under us because we hold i_mutex.
*/
if (pos > inode->i_size) {
i_size_write(inode, pos);
@@ -358,7 +358,7 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
loff_t pos;
ssize_t ret;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (!access_ok(VERIFY_READ, buf, len)) {
ret=-EFAULT;
@@ -383,14 +383,14 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,
if (ret)
goto out_backing;
- inode_update_time(inode, 1);
+ file_update_time(filp);
ret = __xip_file_write (filp, buf, count, pos, ppos);
out_backing:
current->backing_dev_info = NULL;
out_up:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(xip_file_write);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 3e52df7c471b..b21d78c941b5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -11,6 +11,9 @@
#include <linux/highmem.h>
#include <linux/nodemask.h>
#include <linux/pagemap.h>
+#include <linux/mempolicy.h>
+#include <linux/cpuset.h>
+
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -36,18 +39,22 @@ static void enqueue_huge_page(struct page *page)
free_huge_pages_node[nid]++;
}
-static struct page *dequeue_huge_page(void)
+static struct page *dequeue_huge_page(struct vm_area_struct *vma,
+ unsigned long address)
{
int nid = numa_node_id();
struct page *page = NULL;
+ struct zonelist *zonelist = huge_zonelist(vma, address);
+ struct zone **z;
- if (list_empty(&hugepage_freelists[nid])) {
- for (nid = 0; nid < MAX_NUMNODES; ++nid)
- if (!list_empty(&hugepage_freelists[nid]))
- break;
+ for (z = zonelist->zones; *z; z++) {
+ nid = (*z)->zone_pgdat->node_id;
+ if (cpuset_zone_allowed(*z, GFP_HIGHUSER) &&
+ !list_empty(&hugepage_freelists[nid]))
+ break;
}
- if (nid >= 0 && nid < MAX_NUMNODES &&
- !list_empty(&hugepage_freelists[nid])) {
+
+ if (*z) {
page = list_entry(hugepage_freelists[nid].next,
struct page, lru);
list_del(&page->lru);
@@ -85,13 +92,13 @@ void free_huge_page(struct page *page)
spin_unlock(&hugetlb_lock);
}
-struct page *alloc_huge_page(void)
+struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr)
{
struct page *page;
int i;
spin_lock(&hugetlb_lock);
- page = dequeue_huge_page();
+ page = dequeue_huge_page(vma, addr);
if (!page) {
spin_unlock(&hugetlb_lock);
return NULL;
@@ -194,7 +201,7 @@ static unsigned long set_max_huge_pages(unsigned long count)
spin_lock(&hugetlb_lock);
try_to_free_low(count);
while (count < nr_huge_pages) {
- struct page *page = dequeue_huge_page();
+ struct page *page = dequeue_huge_page(NULL, 0);
if (!page)
break;
update_and_free_page(page);
@@ -261,11 +268,12 @@ struct vm_operations_struct hugetlb_vm_ops = {
.nopage = hugetlb_nopage,
};
-static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page)
+static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page,
+ int writable)
{
pte_t entry;
- if (vma->vm_flags & VM_WRITE) {
+ if (writable) {
entry =
pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
} else {
@@ -277,12 +285,27 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page)
return entry;
}
+static void set_huge_ptep_writable(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+{
+ pte_t entry;
+
+ entry = pte_mkwrite(pte_mkdirty(*ptep));
+ ptep_set_access_flags(vma, address, ptep, entry, 1);
+ update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
+}
+
+
int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma)
{
pte_t *src_pte, *dst_pte, entry;
struct page *ptepage;
unsigned long addr;
+ int cow;
+
+ cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
src_pte = huge_pte_offset(src, addr);
@@ -294,6 +317,8 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
spin_lock(&dst->page_table_lock);
spin_lock(&src->page_table_lock);
if (!pte_none(*src_pte)) {
+ if (cow)
+ ptep_set_wrprotect(src, addr, src_pte);
entry = *src_pte;
ptepage = pte_page(entry);
get_page(ptepage);
@@ -345,57 +370,63 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
flush_tlb_range(vma, start, end);
}
-static struct page *find_lock_huge_page(struct address_space *mapping,
- unsigned long idx)
+static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep, pte_t pte)
{
- struct page *page;
- int err;
- struct inode *inode = mapping->host;
- unsigned long size;
+ struct page *old_page, *new_page;
+ int i, avoidcopy;
-retry:
- page = find_lock_page(mapping, idx);
- if (page)
- goto out;
+ old_page = pte_page(pte);
- /* Check to make sure the mapping hasn't been truncated */
- size = i_size_read(inode) >> HPAGE_SHIFT;
- if (idx >= size)
- goto out;
+ /* If no-one else is actually using this page, avoid the copy
+ * and just make the page writable */
+ avoidcopy = (page_count(old_page) == 1);
+ if (avoidcopy) {
+ set_huge_ptep_writable(vma, address, ptep);
+ return VM_FAULT_MINOR;
+ }
- if (hugetlb_get_quota(mapping))
- goto out;
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- goto out;
+ page_cache_get(old_page);
+ new_page = alloc_huge_page(vma, address);
+
+ if (!new_page) {
+ page_cache_release(old_page);
+
+ /* Logically this is OOM, not a SIGBUS, but an OOM
+ * could cause the kernel to go killing other
+ * processes which won't help the hugepage situation
+ * at all (?) */
+ return VM_FAULT_SIGBUS;
}
- err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
- if (err) {
- put_page(page);
- hugetlb_put_quota(mapping);
- if (err == -EEXIST)
- goto retry;
- page = NULL;
+ spin_unlock(&mm->page_table_lock);
+ for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++)
+ copy_user_highpage(new_page + i, old_page + i,
+ address + i*PAGE_SIZE);
+ spin_lock(&mm->page_table_lock);
+
+ ptep = huge_pte_offset(mm, address & HPAGE_MASK);
+ if (likely(pte_same(*ptep, pte))) {
+ /* Break COW */
+ set_huge_pte_at(mm, address, ptep,
+ make_huge_pte(vma, new_page, 1));
+ /* Make the old page be freed below */
+ new_page = old_page;
}
-out:
- return page;
+ page_cache_release(new_page);
+ page_cache_release(old_page);
+ return VM_FAULT_MINOR;
}
-int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long address, int write_access)
+int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep, int write_access)
{
int ret = VM_FAULT_SIGBUS;
unsigned long idx;
unsigned long size;
- pte_t *pte;
struct page *page;
struct address_space *mapping;
-
- pte = huge_pte_alloc(mm, address);
- if (!pte)
- goto out;
+ pte_t new_pte;
mapping = vma->vm_file->f_mapping;
idx = ((address - vma->vm_start) >> HPAGE_SHIFT)
@@ -405,9 +436,31 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
* Use page lock to guard against racing truncation
* before we get page_table_lock.
*/
- page = find_lock_huge_page(mapping, idx);
- if (!page)
- goto out;
+retry:
+ page = find_lock_page(mapping, idx);
+ if (!page) {
+ if (hugetlb_get_quota(mapping))
+ goto out;
+ page = alloc_huge_page(vma, address);
+ if (!page) {
+ hugetlb_put_quota(mapping);
+ goto out;
+ }
+
+ if (vma->vm_flags & VM_SHARED) {
+ int err;
+
+ err = add_to_page_cache(page, mapping, idx, GFP_KERNEL);
+ if (err) {
+ put_page(page);
+ hugetlb_put_quota(mapping);
+ if (err == -EEXIST)
+ goto retry;
+ goto out;
+ }
+ } else
+ lock_page(page);
+ }
spin_lock(&mm->page_table_lock);
size = i_size_read(mapping->host) >> HPAGE_SHIFT;
@@ -415,11 +468,19 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
goto backout;
ret = VM_FAULT_MINOR;
- if (!pte_none(*pte))
+ if (!pte_none(*ptep))
goto backout;
add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE);
- set_huge_pte_at(mm, address, pte, make_huge_pte(vma, page));
+ new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
+ && (vma->vm_flags & VM_SHARED)));
+ set_huge_pte_at(mm, address, ptep, new_pte);
+
+ if (write_access && !(vma->vm_flags & VM_SHARED)) {
+ /* Optimization, do the COW without a second fault */
+ ret = hugetlb_cow(mm, vma, address, ptep, new_pte);
+ }
+
spin_unlock(&mm->page_table_lock);
unlock_page(page);
out:
@@ -433,6 +494,33 @@ backout:
goto out;
}
+int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long address, int write_access)
+{
+ pte_t *ptep;
+ pte_t entry;
+ int ret;
+
+ ptep = huge_pte_alloc(mm, address);
+ if (!ptep)
+ return VM_FAULT_OOM;
+
+ entry = *ptep;
+ if (pte_none(entry))
+ return hugetlb_no_page(mm, vma, address, ptep, write_access);
+
+ ret = VM_FAULT_MINOR;
+
+ spin_lock(&mm->page_table_lock);
+ /* Check for a racing update before calling hugetlb_cow */
+ if (likely(pte_same(entry, *ptep)))
+ if (write_access && !pte_write(entry))
+ ret = hugetlb_cow(mm, vma, address, ptep, entry);
+ spin_unlock(&mm->page_table_lock);
+
+ return ret;
+}
+
int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
struct page **pages, struct vm_area_struct **vmas,
unsigned long *position, int *length, int i)
diff --git a/mm/internal.h b/mm/internal.h
index 6bf134e8fb3d..17256bb2f4ef 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -9,5 +9,22 @@
* 2 of the License, or (at your option) any later version.
*/
-/* page_alloc.c */
-extern void set_page_refs(struct page *page, int order);
+static inline void set_page_refs(struct page *page, int order)
+{
+#ifdef CONFIG_MMU
+ set_page_count(page, 1);
+#else
+ int i;
+
+ /*
+ * We need to reference all the pages for this order, otherwise if
+ * anyone accesses one of the pages with (get/put) it will be freed.
+ * - eg: access_process_vm()
+ */
+ for (i = 0; i < (1 << order); i++)
+ set_page_count(page + i, 1);
+#endif /* CONFIG_MMU */
+}
+
+extern void fastcall __init __free_pages_bootmem(struct page *page,
+ unsigned int order);
diff --git a/mm/madvise.c b/mm/madvise.c
index 2b7cf0400a21..ae0ae3ea299a 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -140,6 +140,36 @@ static long madvise_dontneed(struct vm_area_struct * vma,
return 0;
}
+/*
+ * Application wants to free up the pages and associated backing store.
+ * This is effectively punching a hole into the middle of a file.
+ *
+ * NOTE: Currently, only shmfs/tmpfs is supported for this operation.
+ * Other filesystems return -ENOSYS.
+ */
+static long madvise_remove(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ struct address_space *mapping;
+ loff_t offset, endoff;
+
+ if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
+ return -EINVAL;
+
+ if (!vma->vm_file || !vma->vm_file->f_mapping
+ || !vma->vm_file->f_mapping->host) {
+ return -EINVAL;
+ }
+
+ mapping = vma->vm_file->f_mapping;
+
+ offset = (loff_t)(start - vma->vm_start)
+ + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+ endoff = (loff_t)(end - vma->vm_start - 1)
+ + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+ return vmtruncate_range(mapping->host, offset, endoff);
+}
+
static long
madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
unsigned long start, unsigned long end, int behavior)
@@ -152,6 +182,9 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
case MADV_RANDOM:
error = madvise_behavior(vma, prev, start, end, behavior);
break;
+ case MADV_REMOVE:
+ error = madvise_remove(vma, start, end);
+ break;
case MADV_WILLNEED:
error = madvise_willneed(vma, prev, start, end);
@@ -190,6 +223,8 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
* some pages ahead.
* MADV_DONTNEED - the application is finished with the given range,
* so the kernel can free resources associated with it.
+ * MADV_REMOVE - the application wants to free up the given range of
+ * pages and associated backing store.
*
* return values:
* zero - success
diff --git a/mm/memory.c b/mm/memory.c
index d8dde07a3656..7a11ddd5060f 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1498,7 +1498,7 @@ gotten:
update_mmu_cache(vma, address, entry);
lazy_mmu_prot_update(entry);
lru_cache_add_active(new_page);
- page_add_anon_rmap(new_page, vma, address);
+ page_add_new_anon_rmap(new_page, vma, address);
/* Free the old page.. */
new_page = old_page;
@@ -1770,9 +1770,32 @@ out_big:
out_busy:
return -ETXTBSY;
}
-
EXPORT_SYMBOL(vmtruncate);
+int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
+{
+ struct address_space *mapping = inode->i_mapping;
+
+ /*
+ * If the underlying filesystem is not going to provide
+ * a way to truncate a range of blocks (punch a hole) -
+ * we should return failure right now.
+ */
+ if (!inode->i_op || !inode->i_op->truncate_range)
+ return -ENOSYS;
+
+ mutex_lock(&inode->i_mutex);
+ down_write(&inode->i_alloc_sem);
+ unmap_mapping_range(mapping, offset, (end - offset), 1);
+ truncate_inode_pages_range(mapping, offset, end);
+ inode->i_op->truncate_range(inode, offset, end);
+ up_write(&inode->i_alloc_sem);
+ mutex_unlock(&inode->i_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(vmtruncate_range);
+
/*
* Primitive swap readahead code. We simply read an aligned block of
* (1 << page_cluster) entries in the swap area. This method is chosen
@@ -1954,8 +1977,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
goto release;
inc_mm_counter(mm, anon_rss);
lru_cache_add_active(page);
- SetPageReferenced(page);
- page_add_anon_rmap(page, vma, address);
+ page_add_new_anon_rmap(page, vma, address);
} else {
/* Map the ZERO_PAGE - vm_page_prot is readonly */
page = ZERO_PAGE(address);
@@ -2086,7 +2108,7 @@ retry:
if (anon) {
inc_mm_counter(mm, anon_rss);
lru_cache_add_active(new_page);
- page_add_anon_rmap(new_page, vma, address);
+ page_add_new_anon_rmap(new_page, vma, address);
} else {
inc_mm_counter(mm, file_rss);
page_add_file_rmap(new_page);
@@ -2245,6 +2267,8 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
}
+EXPORT_SYMBOL_GPL(__handle_mm_fault);
+
#ifndef __PAGETABLE_PUD_FOLDED
/*
* Allocate page upper directory.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index f6d4af8af8a8..a918f77f02f3 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -42,7 +42,6 @@ extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
int nr_pages);
static int __add_section(struct zone *zone, unsigned long phys_start_pfn)
{
- struct pglist_data *pgdat = zone->zone_pgdat;
int nr_pages = PAGES_PER_SECTION;
int ret;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 72f402cc9c9a..73790188b0eb 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -83,9 +83,18 @@
#include <linux/init.h>
#include <linux/compat.h>
#include <linux/mempolicy.h>
+#include <linux/swap.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
+/* Internal flags */
+#define MPOL_MF_DISCONTIG_OK (MPOL_MF_INTERNAL << 0) /* Skip checks for continuous vmas */
+#define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1) /* Invert check for nodemask */
+#define MPOL_MF_STATS (MPOL_MF_INTERNAL << 2) /* Gather statistics */
+
static kmem_cache_t *policy_cache;
static kmem_cache_t *sn_cache;
@@ -93,7 +102,7 @@ static kmem_cache_t *sn_cache;
/* Highest zone. An specific allocation for a zone below that is not
policied. */
-static int policy_zone;
+int policy_zone = ZONE_DMA;
struct mempolicy default_policy = {
.refcnt = ATOMIC_INIT(1), /* never free it */
@@ -131,17 +140,8 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes)
if (!zl)
return NULL;
num = 0;
- for_each_node_mask(nd, *nodes) {
- int k;
- for (k = MAX_NR_ZONES-1; k >= 0; k--) {
- struct zone *z = &NODE_DATA(nd)->node_zones[k];
- if (!z->present_pages)
- continue;
- zl->zones[num++] = z;
- if (k > policy_zone)
- policy_zone = k;
- }
- }
+ for_each_node_mask(nd, *nodes)
+ zl->zones[num++] = &NODE_DATA(nd)->node_zones[policy_zone];
zl->zones[num] = NULL;
return zl;
}
@@ -180,12 +180,19 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes)
break;
}
policy->policy = mode;
+ policy->cpuset_mems_allowed = cpuset_mems_allowed(current);
return policy;
}
-/* Ensure all existing pages follow the policy. */
+static void gather_stats(struct page *, void *);
+static void migrate_page_add(struct page *page, struct list_head *pagelist,
+ unsigned long flags);
+
+/* Scan through pages checking if pages follow certain conditions. */
static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
- unsigned long addr, unsigned long end, nodemask_t *nodes)
+ unsigned long addr, unsigned long end,
+ const nodemask_t *nodes, unsigned long flags,
+ void *private)
{
pte_t *orig_pte;
pte_t *pte;
@@ -201,8 +208,28 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
page = vm_normal_page(vma, addr, *pte);
if (!page)
continue;
+ /*
+ * The check for PageReserved here is important to avoid
+ * handling zero pages and other pages that may have been
+ * marked special by the system.
+ *
+ * If the PageReserved would not be checked here then f.e.
+ * the location of the zero page could have an influence
+ * on MPOL_MF_STRICT, zero pages would be counted for
+ * the per node stats, and there would be useless attempts
+ * to put zero pages on the migration list.
+ */
+ if (PageReserved(page))
+ continue;
nid = page_to_nid(page);
- if (!node_isset(nid, *nodes))
+ if (node_isset(nid, *nodes) == !!(flags & MPOL_MF_INVERT))
+ continue;
+
+ if (flags & MPOL_MF_STATS)
+ gather_stats(page, private);
+ else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+ migrate_page_add(page, private, flags);
+ else
break;
} while (pte++, addr += PAGE_SIZE, addr != end);
pte_unmap_unlock(orig_pte, ptl);
@@ -210,7 +237,9 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
}
static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
- unsigned long addr, unsigned long end, nodemask_t *nodes)
+ unsigned long addr, unsigned long end,
+ const nodemask_t *nodes, unsigned long flags,
+ void *private)
{
pmd_t *pmd;
unsigned long next;
@@ -220,14 +249,17 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
next = pmd_addr_end(addr, end);
if (pmd_none_or_clear_bad(pmd))
continue;
- if (check_pte_range(vma, pmd, addr, next, nodes))
+ if (check_pte_range(vma, pmd, addr, next, nodes,
+ flags, private))
return -EIO;
} while (pmd++, addr = next, addr != end);
return 0;
}
static inline int check_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
- unsigned long addr, unsigned long end, nodemask_t *nodes)
+ unsigned long addr, unsigned long end,
+ const nodemask_t *nodes, unsigned long flags,
+ void *private)
{
pud_t *pud;
unsigned long next;
@@ -237,14 +269,17 @@ static inline int check_pud_range(struct vm_area_struct *vma, pgd_t *pgd,
next = pud_addr_end(addr, end);
if (pud_none_or_clear_bad(pud))
continue;
- if (check_pmd_range(vma, pud, addr, next, nodes))
+ if (check_pmd_range(vma, pud, addr, next, nodes,
+ flags, private))
return -EIO;
} while (pud++, addr = next, addr != end);
return 0;
}
static inline int check_pgd_range(struct vm_area_struct *vma,
- unsigned long addr, unsigned long end, nodemask_t *nodes)
+ unsigned long addr, unsigned long end,
+ const nodemask_t *nodes, unsigned long flags,
+ void *private)
{
pgd_t *pgd;
unsigned long next;
@@ -254,36 +289,61 @@ static inline int check_pgd_range(struct vm_area_struct *vma,
next = pgd_addr_end(addr, end);
if (pgd_none_or_clear_bad(pgd))
continue;
- if (check_pud_range(vma, pgd, addr, next, nodes))
+ if (check_pud_range(vma, pgd, addr, next, nodes,
+ flags, private))
return -EIO;
} while (pgd++, addr = next, addr != end);
return 0;
}
-/* Step 1: check the range */
+/* Check if a vma is migratable */
+static inline int vma_migratable(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & (
+ VM_LOCKED|VM_IO|VM_HUGETLB|VM_PFNMAP|VM_RESERVED))
+ return 0;
+ return 1;
+}
+
+/*
+ * Check if all pages in a range are on a set of nodes.
+ * If pagelist != NULL then isolate pages from the LRU and
+ * put them on the pagelist.
+ */
static struct vm_area_struct *
check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
- nodemask_t *nodes, unsigned long flags)
+ const nodemask_t *nodes, unsigned long flags, void *private)
{
int err;
struct vm_area_struct *first, *vma, *prev;
+ /* Clear the LRU lists so pages can be isolated */
+ if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+ lru_add_drain_all();
+
first = find_vma(mm, start);
if (!first)
return ERR_PTR(-EFAULT);
prev = NULL;
for (vma = first; vma && vma->vm_start < end; vma = vma->vm_next) {
- if (!vma->vm_next && vma->vm_end < end)
- return ERR_PTR(-EFAULT);
- if (prev && prev->vm_end < vma->vm_start)
- return ERR_PTR(-EFAULT);
- if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
+ if (!(flags & MPOL_MF_DISCONTIG_OK)) {
+ if (!vma->vm_next && vma->vm_end < end)
+ return ERR_PTR(-EFAULT);
+ if (prev && prev->vm_end < vma->vm_start)
+ return ERR_PTR(-EFAULT);
+ }
+ if (!is_vm_hugetlb_page(vma) &&
+ ((flags & MPOL_MF_STRICT) ||
+ ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
+ vma_migratable(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, start, endvma, nodes);
+ err = check_pgd_range(vma, start, endvma, nodes,
+ flags, private);
if (err) {
first = ERR_PTR(err);
break;
@@ -342,51 +402,10 @@ static int contextualize_policy(int mode, nodemask_t *nodes)
if (!nodes)
return 0;
- /* Update current mems_allowed */
- cpuset_update_current_mems_allowed();
- /* Ignore nodes not set in current->mems_allowed */
- cpuset_restrict_to_mems_allowed(nodes->bits);
- return mpol_check_policy(mode, nodes);
-}
-
-long do_mbind(unsigned long start, unsigned long len,
- unsigned long mode, nodemask_t *nmask, unsigned long flags)
-{
- struct vm_area_struct *vma;
- struct mm_struct *mm = current->mm;
- struct mempolicy *new;
- unsigned long end;
- int err;
-
- if ((flags & ~(unsigned long)(MPOL_MF_STRICT)) || mode > MPOL_MAX)
- return -EINVAL;
- if (start & ~PAGE_MASK)
- return -EINVAL;
- if (mode == MPOL_DEFAULT)
- flags &= ~MPOL_MF_STRICT;
- len = (len + PAGE_SIZE - 1) & PAGE_MASK;
- end = start + len;
- if (end < start)
+ cpuset_update_task_memory_state();
+ if (!cpuset_nodes_subset_current_mems_allowed(*nodes))
return -EINVAL;
- if (end == start)
- return 0;
- if (mpol_check_policy(mode, nmask))
- return -EINVAL;
- new = mpol_new(mode, nmask);
- if (IS_ERR(new))
- return PTR_ERR(new);
-
- PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
- mode,nodes_addr(nodes)[0]);
-
- down_write(&mm->mmap_sem);
- vma = check_range(mm, start, end, nmask, flags);
- err = PTR_ERR(vma);
- if (!IS_ERR(vma))
- err = mbind_range(vma, start, end, new);
- up_write(&mm->mmap_sem);
- mpol_free(new);
- return err;
+ return mpol_check_policy(mode, nodes);
}
/* Set the process memory policy */
@@ -457,7 +476,7 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask,
struct vm_area_struct *vma = NULL;
struct mempolicy *pol = current->mempolicy;
- cpuset_update_current_mems_allowed();
+ cpuset_update_task_memory_state();
if (flags & ~(unsigned long)(MPOL_F_NODE|MPOL_F_ADDR))
return -EINVAL;
if (flags & MPOL_F_ADDR) {
@@ -509,11 +528,141 @@ long do_get_mempolicy(int *policy, nodemask_t *nmask,
}
/*
+ * page migration
+ */
+
+static void migrate_page_add(struct page *page, struct list_head *pagelist,
+ unsigned long flags)
+{
+ /*
+ * Avoid migrating a page that is shared with others.
+ */
+ if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) {
+ if (isolate_lru_page(page))
+ list_add(&page->lru, pagelist);
+ }
+}
+
+static int swap_pages(struct list_head *pagelist)
+{
+ LIST_HEAD(moved);
+ LIST_HEAD(failed);
+ int n;
+
+ n = migrate_pages(pagelist, NULL, &moved, &failed);
+ putback_lru_pages(&failed);
+ putback_lru_pages(&moved);
+
+ return n;
+}
+
+/*
+ * For now migrate_pages simply swaps out the pages from nodes that are in
+ * the source set but not in the target set. In the future, we would
+ * want a function that moves pages between the two nodesets in such
+ * a way as to preserve the physical layout as much as possible.
+ *
+ * Returns the number of page that could not be moved.
+ */
+int do_migrate_pages(struct mm_struct *mm,
+ const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
+{
+ LIST_HEAD(pagelist);
+ int count = 0;
+ nodemask_t nodes;
+
+ nodes_andnot(nodes, *from_nodes, *to_nodes);
+
+ down_read(&mm->mmap_sem);
+ check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nodes,
+ flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+
+ if (!list_empty(&pagelist)) {
+ count = swap_pages(&pagelist);
+ putback_lru_pages(&pagelist);
+ }
+
+ up_read(&mm->mmap_sem);
+ return count;
+}
+
+long do_mbind(unsigned long start, unsigned long len,
+ unsigned long mode, nodemask_t *nmask, unsigned long flags)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = current->mm;
+ struct mempolicy *new;
+ unsigned long end;
+ int err;
+ LIST_HEAD(pagelist);
+
+ if ((flags & ~(unsigned long)(MPOL_MF_STRICT |
+ MPOL_MF_MOVE | MPOL_MF_MOVE_ALL))
+ || mode > MPOL_MAX)
+ return -EINVAL;
+ if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_RESOURCE))
+ return -EPERM;
+
+ if (start & ~PAGE_MASK)
+ return -EINVAL;
+
+ if (mode == MPOL_DEFAULT)
+ flags &= ~MPOL_MF_STRICT;
+
+ len = (len + PAGE_SIZE - 1) & PAGE_MASK;
+ end = start + len;
+
+ if (end < start)
+ return -EINVAL;
+ if (end == start)
+ return 0;
+
+ if (mpol_check_policy(mode, nmask))
+ return -EINVAL;
+
+ new = mpol_new(mode, nmask);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+
+ /*
+ * If we are using the default policy then operation
+ * on discontinuous address spaces is okay after all
+ */
+ if (!new)
+ flags |= MPOL_MF_DISCONTIG_OK;
+
+ PDprintk("mbind %lx-%lx mode:%ld nodes:%lx\n",start,start+len,
+ mode,nodes_addr(nodes)[0]);
+
+ down_write(&mm->mmap_sem);
+ vma = check_range(mm, start, end, nmask,
+ flags | MPOL_MF_INVERT, &pagelist);
+
+ err = PTR_ERR(vma);
+ if (!IS_ERR(vma)) {
+ int nr_failed = 0;
+
+ err = mbind_range(vma, start, end, new);
+ if (!list_empty(&pagelist))
+ nr_failed = swap_pages(&pagelist);
+
+ if (!err && nr_failed && (flags & MPOL_MF_STRICT))
+ err = -EIO;
+ }
+ if (!list_empty(&pagelist))
+ putback_lru_pages(&pagelist);
+
+ up_write(&mm->mmap_sem);
+ mpol_free(new);
+ return err;
+}
+
+/*
* User space interface with variable sized bitmaps for nodelists.
*/
/* Copy a node mask from user space. */
-static int get_nodes(nodemask_t *nodes, unsigned long __user *nmask,
+static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask,
unsigned long maxnode)
{
unsigned long k;
@@ -602,6 +751,65 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
return do_set_mempolicy(mode, &nodes);
}
+asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
+ const unsigned long __user *old_nodes,
+ const unsigned long __user *new_nodes)
+{
+ struct mm_struct *mm;
+ struct task_struct *task;
+ nodemask_t old;
+ nodemask_t new;
+ nodemask_t task_nodes;
+ int err;
+
+ err = get_nodes(&old, old_nodes, maxnode);
+ if (err)
+ return err;
+
+ err = get_nodes(&new, new_nodes, maxnode);
+ if (err)
+ return err;
+
+ /* Find the mm_struct */
+ read_lock(&tasklist_lock);
+ task = pid ? find_task_by_pid(pid) : current;
+ if (!task) {
+ read_unlock(&tasklist_lock);
+ return -ESRCH;
+ }
+ mm = get_task_mm(task);
+ read_unlock(&tasklist_lock);
+
+ if (!mm)
+ return -EINVAL;
+
+ /*
+ * Check if this process has the right to modify the specified
+ * process. The right exists if the process has administrative
+ * capabilities, superuser priviledges or the same
+ * userid as the target process.
+ */
+ if ((current->euid != task->suid) && (current->euid != task->uid) &&
+ (current->uid != task->suid) && (current->uid != task->uid) &&
+ !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
+ task_nodes = cpuset_mems_allowed(task);
+ /* Is the user allowed to access the target nodes? */
+ if (!nodes_subset(new, task_nodes) && !capable(CAP_SYS_ADMIN)) {
+ err = -EPERM;
+ goto out;
+ }
+
+ err = do_migrate_pages(mm, &old, &new, MPOL_MF_MOVE);
+out:
+ mmput(mm);
+ return err;
+}
+
+
/* Retrieve NUMA policy */
asmlinkage long sys_get_mempolicy(int __user *policy,
unsigned long __user *nmask,
@@ -708,8 +916,8 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
#endif
/* Return effective policy for a VMA */
-struct mempolicy *
-get_vma_policy(struct task_struct *task, struct vm_area_struct *vma, unsigned long addr)
+static struct mempolicy * get_vma_policy(struct task_struct *task,
+ struct vm_area_struct *vma, unsigned long addr)
{
struct mempolicy *pol = task->mempolicy;
@@ -768,6 +976,33 @@ static unsigned interleave_nodes(struct mempolicy *policy)
return nid;
}
+/*
+ * Depending on the memory policy provide a node from which to allocate the
+ * next slab entry.
+ */
+unsigned slab_node(struct mempolicy *policy)
+{
+ switch (policy->policy) {
+ case MPOL_INTERLEAVE:
+ return interleave_nodes(policy);
+
+ case MPOL_BIND:
+ /*
+ * Follow bind policy behavior and start allocation at the
+ * first node.
+ */
+ return policy->v.zonelist->zones[0]->zone_pgdat->node_id;
+
+ case MPOL_PREFERRED:
+ if (policy->v.preferred_node >= 0)
+ return policy->v.preferred_node;
+ /* Fall through */
+
+ default:
+ return numa_node_id();
+ }
+}
+
/* Do static interleaving for a VMA with known offset. */
static unsigned offset_il_node(struct mempolicy *pol,
struct vm_area_struct *vma, unsigned long off)
@@ -785,6 +1020,34 @@ static unsigned offset_il_node(struct mempolicy *pol,
return nid;
}
+/* Determine a node number for interleave */
+static inline unsigned interleave_nid(struct mempolicy *pol,
+ struct vm_area_struct *vma, unsigned long addr, int shift)
+{
+ if (vma) {
+ unsigned long off;
+
+ off = vma->vm_pgoff;
+ off += (addr - vma->vm_start) >> shift;
+ return offset_il_node(pol, vma, off);
+ } else
+ return interleave_nodes(pol);
+}
+
+/* Return a zonelist suitable for a huge page allocation. */
+struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr)
+{
+ struct mempolicy *pol = get_vma_policy(current, vma, addr);
+
+ if (pol->policy == MPOL_INTERLEAVE) {
+ unsigned nid;
+
+ nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT);
+ return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER);
+ }
+ return zonelist_policy(GFP_HIGHUSER, pol);
+}
+
/* Allocate a page in interleaved policy.
Own path because it needs to do special accounting. */
static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
@@ -829,19 +1092,12 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr)
{
struct mempolicy *pol = get_vma_policy(current, vma, addr);
- cpuset_update_current_mems_allowed();
+ cpuset_update_task_memory_state();
if (unlikely(pol->policy == MPOL_INTERLEAVE)) {
unsigned nid;
- if (vma) {
- unsigned long off;
- off = vma->vm_pgoff;
- off += (addr - vma->vm_start) >> PAGE_SHIFT;
- nid = offset_il_node(pol, vma, off);
- } else {
- /* fall back to process interleaving */
- nid = interleave_nodes(pol);
- }
+
+ nid = interleave_nid(pol, vma, addr, PAGE_SHIFT);
return alloc_page_interleave(gfp, 0, nid);
}
return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol));
@@ -862,7 +1118,7 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr)
* interrupt context and apply the current process NUMA policy.
* Returns NULL when no page can be allocated.
*
- * Don't call cpuset_update_current_mems_allowed() unless
+ * Don't call cpuset_update_task_memory_state() unless
* 1) it's ok to take cpuset_sem (can WAIT), and
* 2) allocating for current task (not interrupt).
*/
@@ -871,7 +1127,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
struct mempolicy *pol = current->mempolicy;
if ((gfp & __GFP_WAIT) && !in_interrupt())
- cpuset_update_current_mems_allowed();
+ cpuset_update_task_memory_state();
if (!pol || in_interrupt())
pol = &default_policy;
if (pol->policy == MPOL_INTERLEAVE)
@@ -880,6 +1136,15 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
}
EXPORT_SYMBOL(alloc_pages_current);
+/*
+ * If mpol_copy() sees current->cpuset == cpuset_being_rebound, then it
+ * rebinds the mempolicy its copying by calling mpol_rebind_policy()
+ * with the mems_allowed returned by cpuset_mems_allowed(). This
+ * keeps mempolicies cpuset relative after its cpuset moves. See
+ * further kernel/cpuset.c update_nodemask().
+ */
+void *cpuset_being_rebound;
+
/* Slow path of a mempolicy copy */
struct mempolicy *__mpol_copy(struct mempolicy *old)
{
@@ -887,6 +1152,10 @@ struct mempolicy *__mpol_copy(struct mempolicy *old)
if (!new)
return ERR_PTR(-ENOMEM);
+ if (current_cpuset_is_being_rebound()) {
+ nodemask_t mems = cpuset_mems_allowed(current);
+ mpol_rebind_policy(old, &mems);
+ }
*new = *old;
atomic_set(&new->refcnt, 1);
if (new->policy == MPOL_BIND) {
@@ -940,54 +1209,6 @@ void __mpol_free(struct mempolicy *p)
}
/*
- * Hugetlb policy. Same as above, just works with node numbers instead of
- * zonelists.
- */
-
-/* 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(current, vma, addr);
-
- switch (pol->policy) {
- case MPOL_DEFAULT:
- return numa_node_id();
- case MPOL_BIND:
- return pol->v.zonelist->zones[0]->zone_pgdat->node_id;
- case MPOL_INTERLEAVE:
- return interleave_nodes(pol);
- case MPOL_PREFERRED:
- return pol->v.preferred_node >= 0 ?
- pol->v.preferred_node : numa_node_id();
- }
- BUG();
- return 0;
-}
-
-/* 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(current, vma, addr);
-
- switch (pol->policy) {
- case MPOL_PREFERRED:
- case MPOL_DEFAULT:
- case MPOL_INTERLEAVE:
- return 1;
- case MPOL_BIND: {
- struct zone **z;
- for (z = pol->v.zonelist->zones; *z; z++)
- if ((*z)->zone_pgdat->node_id == nid)
- return 1;
- return 0;
- }
- default:
- BUG();
- return 0;
- }
-}
-
-/*
* Shared memory backing store policy support.
*
* Remember policies even when nobody has shared memory mapped.
@@ -1141,6 +1362,30 @@ restart:
return 0;
}
+void mpol_shared_policy_init(struct shared_policy *info, int policy,
+ nodemask_t *policy_nodes)
+{
+ info->root = RB_ROOT;
+ spin_lock_init(&info->lock);
+
+ if (policy != MPOL_DEFAULT) {
+ struct mempolicy *newpol;
+
+ /* Falls back to MPOL_DEFAULT on any error */
+ newpol = mpol_new(policy, policy_nodes);
+ if (!IS_ERR(newpol)) {
+ /* Create pseudo-vma that contains just the policy */
+ struct vm_area_struct pvma;
+
+ memset(&pvma, 0, sizeof(struct vm_area_struct));
+ /* Policy covers entire file */
+ pvma.vm_end = TASK_SIZE;
+ mpol_set_shared_policy(info, &pvma, newpol);
+ mpol_free(newpol);
+ }
+ }
+}
+
int mpol_set_shared_policy(struct shared_policy *info,
struct vm_area_struct *vma, struct mempolicy *npol)
{
@@ -1209,25 +1454,31 @@ void numa_default_policy(void)
}
/* Migrate a policy to a different set of nodes */
-static void rebind_policy(struct mempolicy *pol, const nodemask_t *old,
- const nodemask_t *new)
+void mpol_rebind_policy(struct mempolicy *pol, const nodemask_t *newmask)
{
+ nodemask_t *mpolmask;
nodemask_t tmp;
if (!pol)
return;
+ mpolmask = &pol->cpuset_mems_allowed;
+ if (nodes_equal(*mpolmask, *newmask))
+ return;
switch (pol->policy) {
case MPOL_DEFAULT:
break;
case MPOL_INTERLEAVE:
- nodes_remap(tmp, pol->v.nodes, *old, *new);
+ nodes_remap(tmp, pol->v.nodes, *mpolmask, *newmask);
pol->v.nodes = tmp;
- current->il_next = node_remap(current->il_next, *old, *new);
+ *mpolmask = *newmask;
+ current->il_next = node_remap(current->il_next,
+ *mpolmask, *newmask);
break;
case MPOL_PREFERRED:
pol->v.preferred_node = node_remap(pol->v.preferred_node,
- *old, *new);
+ *mpolmask, *newmask);
+ *mpolmask = *newmask;
break;
case MPOL_BIND: {
nodemask_t nodes;
@@ -1237,7 +1488,7 @@ static void rebind_policy(struct mempolicy *pol, const nodemask_t *old,
nodes_clear(nodes);
for (z = pol->v.zonelist->zones; *z; z++)
node_set((*z)->zone_pgdat->node_id, nodes);
- nodes_remap(tmp, nodes, *old, *new);
+ nodes_remap(tmp, nodes, *mpolmask, *newmask);
nodes = tmp;
zonelist = bind_zonelist(&nodes);
@@ -1252,6 +1503,7 @@ static void rebind_policy(struct mempolicy *pol, const nodemask_t *old,
kfree(pol->v.zonelist);
pol->v.zonelist = zonelist;
}
+ *mpolmask = *newmask;
break;
}
default:
@@ -1261,12 +1513,156 @@ static void rebind_policy(struct mempolicy *pol, const nodemask_t *old,
}
/*
- * Someone moved this task to different nodes. Fixup mempolicies.
+ * Wrapper for mpol_rebind_policy() that just requires task
+ * pointer, and updates task mempolicy.
+ */
+
+void mpol_rebind_task(struct task_struct *tsk, const nodemask_t *new)
+{
+ mpol_rebind_policy(tsk->mempolicy, new);
+}
+
+/*
+ * Rebind each vma in mm to new nodemask.
*
- * TODO - fixup current->mm->vma and shmfs/tmpfs/hugetlbfs policies as well,
- * once we have a cpuset mechanism to mark which cpuset subtree is migrating.
+ * Call holding a reference to mm. Takes mm->mmap_sem during call.
+ */
+
+void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
+{
+ struct vm_area_struct *vma;
+
+ down_write(&mm->mmap_sem);
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
+ mpol_rebind_policy(vma->vm_policy, new);
+ up_write(&mm->mmap_sem);
+}
+
+/*
+ * Display pages allocated per node and memory policy via /proc.
+ */
+
+static const char *policy_types[] = { "default", "prefer", "bind",
+ "interleave" };
+
+/*
+ * Convert a mempolicy into a string.
+ * Returns the number of characters in buffer (if positive)
+ * or an error (negative)
*/
-void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new)
+static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol)
+{
+ char *p = buffer;
+ int l;
+ nodemask_t nodes;
+ int mode = pol ? pol->policy : MPOL_DEFAULT;
+
+ switch (mode) {
+ case MPOL_DEFAULT:
+ nodes_clear(nodes);
+ break;
+
+ case MPOL_PREFERRED:
+ nodes_clear(nodes);
+ node_set(pol->v.preferred_node, nodes);
+ break;
+
+ case MPOL_BIND:
+ get_zonemask(pol, &nodes);
+ break;
+
+ case MPOL_INTERLEAVE:
+ nodes = pol->v.nodes;
+ break;
+
+ default:
+ BUG();
+ return -EFAULT;
+ }
+
+ l = strlen(policy_types[mode]);
+ if (buffer + maxlen < p + l + 1)
+ return -ENOSPC;
+
+ strcpy(p, policy_types[mode]);
+ p += l;
+
+ if (!nodes_empty(nodes)) {
+ if (buffer + maxlen < p + 2)
+ return -ENOSPC;
+ *p++ = '=';
+ p += nodelist_scnprintf(p, buffer + maxlen - p, nodes);
+ }
+ return p - buffer;
+}
+
+struct numa_maps {
+ unsigned long pages;
+ unsigned long anon;
+ unsigned long mapped;
+ unsigned long mapcount_max;
+ unsigned long node[MAX_NUMNODES];
+};
+
+static void gather_stats(struct page *page, void *private)
+{
+ struct numa_maps *md = private;
+ 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)]++;
+ cond_resched();
+}
+
+int show_numa_map(struct seq_file *m, void *v)
{
- rebind_policy(current->mempolicy, old, new);
+ struct task_struct *task = m->private;
+ struct vm_area_struct *vma = v;
+ struct numa_maps *md;
+ int n;
+ char buffer[50];
+
+ if (!vma->vm_mm)
+ return 0;
+
+ md = kzalloc(sizeof(struct numa_maps), GFP_KERNEL);
+ if (!md)
+ return 0;
+
+ check_pgd_range(vma, vma->vm_start, vma->vm_end,
+ &node_online_map, MPOL_MF_STATS, md);
+
+ if (md->pages) {
+ mpol_to_str(buffer, sizeof(buffer),
+ get_vma_policy(task, vma, vma->vm_start));
+
+ seq_printf(m, "%08lx %s pages=%lu mapped=%lu maxref=%lu",
+ vma->vm_start, buffer, md->pages,
+ md->mapped, md->mapcount_max);
+
+ 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)
+ m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0;
+ return 0;
}
+
diff --git a/mm/mlock.c b/mm/mlock.c
index 4ae3a46ff768..b90c59573abf 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -5,6 +5,7 @@
* (C) Copyright 2002 Christoph Hellwig
*/
+#include <linux/capability.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/mempolicy.h>
diff --git a/mm/mmap.c b/mm/mmap.c
index 64ba4dbcb7de..47556d2b3e90 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -13,6 +13,7 @@
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/syscalls.h>
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/file.h>
#include <linux/fs.h>
diff --git a/mm/mremap.c b/mm/mremap.c
index ddaeee9a0b69..1903bdf65e42 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -13,6 +13,7 @@
#include <linux/shm.h>
#include <linux/mman.h>
#include <linux/swap.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/highmem.h>
#include <linux/security.h>
diff --git a/mm/msync.c b/mm/msync.c
index 1b5b6f662dcf..3563a56e1a51 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -137,7 +137,7 @@ static int msync_interval(struct vm_area_struct *vma,
ret = filemap_fdatawrite(mapping);
if (file->f_op && file->f_op->fsync) {
/*
- * We don't take i_sem here because mmap_sem
+ * We don't take i_mutex here because mmap_sem
* is already held.
*/
err = file->f_op->fsync(file,file->f_dentry,1);
diff --git a/mm/nommu.c b/mm/nommu.c
index c1196812876b..c10262d68232 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1177,3 +1177,10 @@ int in_gate_area_no_task(unsigned long addr)
{
return 0;
}
+
+struct page *filemap_nopage(struct vm_area_struct *area,
+ unsigned long address, int *type)
+{
+ BUG();
+ return NULL;
+}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index d348b9035955..14bd4ec79597 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -274,6 +274,7 @@ void out_of_memory(gfp_t gfp_mask, int order)
show_mem();
}
+ cpuset_lock();
read_lock(&tasklist_lock);
retry:
p = select_bad_process();
@@ -284,6 +285,7 @@ retry:
/* Found nothing?!?! Either we hang forever, or we panic. */
if (!p) {
read_unlock(&tasklist_lock);
+ cpuset_unlock();
panic("Out of memory and no killable processes...\n");
}
@@ -293,12 +295,14 @@ retry:
out:
read_unlock(&tasklist_lock);
+ cpuset_unlock();
if (mm)
mmput(mm);
/*
* Give "p" a good chance of killing itself before we
- * retry to allocate memory.
+ * retry to allocate memory unless "p" is current
*/
- schedule_timeout_interruptible(1);
+ if (!test_thread_flag(TIF_MEMDIE))
+ schedule_timeout_interruptible(1);
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 0166ea15c9ee..945559fb63d2 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -46,7 +46,7 @@
static long ratelimit_pages = 32;
static long total_pages; /* The total number of pages in the machine. */
-static int dirty_exceeded; /* Dirty mem may be over limit */
+static int dirty_exceeded __cacheline_aligned_in_smp; /* Dirty mem may be over limit */
/*
* When balance_dirty_pages decides that the caller needs to perform some
@@ -212,7 +212,8 @@ static void balance_dirty_pages(struct address_space *mapping)
if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh)
break;
- dirty_exceeded = 1;
+ if (!dirty_exceeded)
+ dirty_exceeded = 1;
/* Note: nr_reclaimable denotes nr_dirty + nr_unstable.
* Unstable writes are a feature of certain networked
@@ -234,7 +235,7 @@ static void balance_dirty_pages(struct address_space *mapping)
blk_congestion_wait(WRITE, HZ/10);
}
- if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh)
+ if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh && dirty_exceeded)
dirty_exceeded = 0;
if (writeback_in_progress(bdi))
@@ -550,11 +551,17 @@ void __init page_writeback_init(void)
int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
+ int ret;
+
if (wbc->nr_to_write <= 0)
return 0;
+ wbc->for_writepages = 1;
if (mapping->a_ops->writepages)
- return mapping->a_ops->writepages(mapping, wbc);
- return generic_writepages(mapping, wbc);
+ ret = mapping->a_ops->writepages(mapping, wbc);
+ else
+ ret = generic_writepages(mapping, wbc);
+ wbc->for_writepages = 0;
+ return ret;
}
/**
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index fe14a8c87fc2..df54e2fc8ee0 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -36,6 +36,7 @@
#include <linux/memory_hotplug.h>
#include <linux/nodemask.h>
#include <linux/vmalloc.h>
+#include <linux/mempolicy.h>
#include <asm/tlbflush.h>
#include "internal.h"
@@ -52,6 +53,9 @@ struct pglist_data *pgdat_list __read_mostly;
unsigned long totalram_pages __read_mostly;
unsigned long totalhigh_pages __read_mostly;
long nr_swap_pages;
+int percpu_pagelist_fraction;
+
+static void fastcall free_hot_cold_page(struct page *page, int cold);
/*
* results with 256, 32 in the lowmem_reserve sysctl:
@@ -81,6 +85,7 @@ int min_free_kbytes = 1024;
unsigned long __initdata nr_kernel_pages;
unsigned long __initdata nr_all_pages;
+#ifdef CONFIG_DEBUG_VM
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
{
int ret = 0;
@@ -122,16 +127,23 @@ static int bad_range(struct zone *zone, struct page *page)
return 0;
}
-static void bad_page(const char *function, struct page *page)
+#else
+static inline int bad_range(struct zone *zone, struct page *page)
{
- printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
- function, current->comm, page);
- printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n",
- (int)(2*sizeof(unsigned long)), (unsigned long)page->flags,
- page->mapping, page_mapcount(page), page_count(page));
- printk(KERN_EMERG "Backtrace:\n");
+ return 0;
+}
+#endif
+
+static void bad_page(struct page *page)
+{
+ printk(KERN_EMERG "Bad page state in process '%s'\n"
+ KERN_EMERG "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
+ KERN_EMERG "Trying to fix it up, but a reboot is needed\n"
+ KERN_EMERG "Backtrace:\n",
+ current->comm, page, (int)(2*sizeof(unsigned long)),
+ (unsigned long)page->flags, page->mapping,
+ page_mapcount(page), page_count(page));
dump_stack();
- printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
page->flags &= ~(1 << PG_lru |
1 << PG_private |
1 << PG_locked |
@@ -184,19 +196,15 @@ static void destroy_compound_page(struct page *page, unsigned long order)
int i;
int nr_pages = 1 << order;
- if (!PageCompound(page))
- return;
-
- if (page[1].index != order)
- bad_page(__FUNCTION__, page);
+ if (unlikely(page[1].index != order))
+ bad_page(page);
for (i = 0; i < nr_pages; i++) {
struct page *p = page + i;
- if (!PageCompound(p))
- bad_page(__FUNCTION__, page);
- if (page_private(p) != (unsigned long)page)
- bad_page(__FUNCTION__, page);
+ if (unlikely(!PageCompound(p) |
+ (page_private(p) != (unsigned long)page)))
+ bad_page(page);
ClearPageCompound(p);
}
}
@@ -255,14 +263,20 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
/*
* This function checks whether a page is free && is the buddy
* we can do coalesce a page and its buddy if
- * (a) the buddy is free &&
- * (b) the buddy is on the buddy system &&
- * (c) a page and its buddy have the same order.
+ * (a) the buddy is not in a hole &&
+ * (b) the buddy is free &&
+ * (c) the buddy is on the buddy system &&
+ * (d) a page and its buddy have the same order.
* for recording page's order, we use page_private(page) and PG_private.
*
*/
static inline int page_is_buddy(struct page *page, int order)
{
+#ifdef CONFIG_HOLES_IN_ZONE
+ if (!pfn_valid(page_to_pfn(page)))
+ return 0;
+#endif
+
if (PagePrivate(page) &&
(page_order(page) == order) &&
page_count(page) == 0)
@@ -294,13 +308,13 @@ static inline int page_is_buddy(struct page *page, int order)
* -- wli
*/
-static inline void __free_pages_bulk (struct page *page,
+static inline void __free_one_page(struct page *page,
struct zone *zone, unsigned int order)
{
unsigned long page_idx;
int order_size = 1 << order;
- if (unlikely(order))
+ if (unlikely(PageCompound(page)))
destroy_compound_page(page, order);
page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);
@@ -314,17 +328,15 @@ static inline void __free_pages_bulk (struct page *page,
struct free_area *area;
struct page *buddy;
- combined_idx = __find_combined_index(page_idx, order);
buddy = __page_find_buddy(page, page_idx, order);
-
- if (bad_range(zone, buddy))
- break;
if (!page_is_buddy(buddy, order))
break; /* Move the buddy up one level. */
+
list_del(&buddy->lru);
area = zone->free_area + order;
area->nr_free--;
rmv_page_order(buddy);
+ combined_idx = __find_combined_index(page_idx, order);
page = page + (combined_idx - page_idx);
page_idx = combined_idx;
order++;
@@ -334,11 +346,11 @@ static inline void __free_pages_bulk (struct page *page,
zone->free_area[order].nr_free++;
}
-static inline int free_pages_check(const char *function, struct page *page)
+static inline int free_pages_check(struct page *page)
{
- if ( page_mapcount(page) ||
- page->mapping != NULL ||
- page_count(page) != 0 ||
+ if (unlikely(page_mapcount(page) |
+ (page->mapping != NULL) |
+ (page_count(page) != 0) |
(page->flags & (
1 << PG_lru |
1 << PG_private |
@@ -348,8 +360,8 @@ static inline int free_pages_check(const char *function, struct page *page)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved )))
- bad_page(function, page);
+ 1 << PG_reserved ))))
+ bad_page(page);
if (PageDirty(page))
__ClearPageDirty(page);
/*
@@ -371,51 +383,90 @@ static inline int free_pages_check(const char *function, struct page *page)
* And clear the zone's pages_scanned counter, to hold off the "all pages are
* pinned" detection logic.
*/
-static int
-free_pages_bulk(struct zone *zone, int count,
- struct list_head *list, unsigned int order)
+static void free_pages_bulk(struct zone *zone, int count,
+ struct list_head *list, int order)
{
- unsigned long flags;
- struct page *page = NULL;
- int ret = 0;
-
- spin_lock_irqsave(&zone->lock, flags);
+ spin_lock(&zone->lock);
zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
- while (!list_empty(list) && count--) {
+ while (count--) {
+ struct page *page;
+
+ BUG_ON(list_empty(list));
page = list_entry(list->prev, struct page, lru);
- /* have to delete it as __free_pages_bulk list manipulates */
+ /* have to delete it as __free_one_page list manipulates */
list_del(&page->lru);
- __free_pages_bulk(page, zone, order);
- ret++;
+ __free_one_page(page, zone, order);
}
- spin_unlock_irqrestore(&zone->lock, flags);
- return ret;
+ spin_unlock(&zone->lock);
}
-void __free_pages_ok(struct page *page, unsigned int order)
+static void free_one_page(struct zone *zone, struct page *page, int order)
{
LIST_HEAD(list);
+ list_add(&page->lru, &list);
+ free_pages_bulk(zone, 1, &list, order);
+}
+
+static void __free_pages_ok(struct page *page, unsigned int order)
+{
+ unsigned long flags;
int i;
int reserved = 0;
arch_free_page(page, order);
+ if (!PageHighMem(page))
+ mutex_debug_check_no_locks_freed(page_address(page),
+ PAGE_SIZE<<order);
#ifndef CONFIG_MMU
- if (order > 0)
- for (i = 1 ; i < (1 << order) ; ++i)
- __put_page(page + i);
+ for (i = 1 ; i < (1 << order) ; ++i)
+ __put_page(page + i);
#endif
for (i = 0 ; i < (1 << order) ; ++i)
- reserved += free_pages_check(__FUNCTION__, page + i);
+ reserved += free_pages_check(page + i);
if (reserved)
return;
- list_add(&page->lru, &list);
- mod_page_state(pgfree, 1 << order);
- kernel_map_pages(page, 1<<order, 0);
- free_pages_bulk(page_zone(page), 1, &list, order);
+ kernel_map_pages(page, 1 << order, 0);
+ local_irq_save(flags);
+ __mod_page_state(pgfree, 1 << order);
+ free_one_page(page_zone(page), page, order);
+ local_irq_restore(flags);
+}
+
+/*
+ * permit the bootmem allocator to evade page validation on high-order frees
+ */
+void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order)
+{
+ if (order == 0) {
+ __ClearPageReserved(page);
+ set_page_count(page, 0);
+
+ free_hot_cold_page(page, 0);
+ } else {
+ LIST_HEAD(list);
+ int loop;
+
+ for (loop = 0; loop < BITS_PER_LONG; loop++) {
+ struct page *p = &page[loop];
+
+ if (loop + 16 < BITS_PER_LONG)
+ prefetchw(p + 16);
+ __ClearPageReserved(p);
+ set_page_count(p, 0);
+ }
+
+ arch_free_page(page, order);
+
+ mod_page_state(pgfree, 1 << order);
+
+ list_add(&page->lru, &list);
+ kernel_map_pages(page, 1 << order, 0);
+ free_pages_bulk(page_zone(page), 1, &list, order);
+ }
}
@@ -433,8 +484,7 @@ void __free_pages_ok(struct page *page, unsigned int order)
*
* -- wli
*/
-static inline struct page *
-expand(struct zone *zone, struct page *page,
+static inline void expand(struct zone *zone, struct page *page,
int low, int high, struct free_area *area)
{
unsigned long size = 1 << high;
@@ -448,24 +498,6 @@ expand(struct zone *zone, struct page *page,
area->nr_free++;
set_page_order(&page[size], high);
}
- return page;
-}
-
-void set_page_refs(struct page *page, int order)
-{
-#ifdef CONFIG_MMU
- set_page_count(page, 1);
-#else
- int i;
-
- /*
- * We need to reference all the pages for this order, otherwise if
- * anyone accesses one of the pages with (get/put) it will be freed.
- * - eg: access_process_vm()
- */
- for (i = 0; i < (1 << order); i++)
- set_page_count(page + i, 1);
-#endif /* CONFIG_MMU */
}
/*
@@ -473,9 +505,9 @@ void set_page_refs(struct page *page, int order)
*/
static int prep_new_page(struct page *page, int order)
{
- if ( page_mapcount(page) ||
- page->mapping != NULL ||
- page_count(page) != 0 ||
+ if (unlikely(page_mapcount(page) |
+ (page->mapping != NULL) |
+ (page_count(page) != 0) |
(page->flags & (
1 << PG_lru |
1 << PG_private |
@@ -486,8 +518,8 @@ static int prep_new_page(struct page *page, int order)
1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback |
- 1 << PG_reserved )))
- bad_page(__FUNCTION__, page);
+ 1 << PG_reserved ))))
+ bad_page(page);
/*
* For now, we report if PG_reserved was found set, but do not
@@ -525,7 +557,8 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order)
rmv_page_order(page);
area->nr_free--;
zone->free_pages -= 1UL << order;
- return expand(zone, page, order, current_order, area);
+ expand(zone, page, order, current_order, area);
+ return page;
}
return NULL;
@@ -539,21 +572,17 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order)
static int rmqueue_bulk(struct zone *zone, unsigned int order,
unsigned long count, struct list_head *list)
{
- unsigned long flags;
int i;
- int allocated = 0;
- struct page *page;
- spin_lock_irqsave(&zone->lock, flags);
+ spin_lock(&zone->lock);
for (i = 0; i < count; ++i) {
- page = __rmqueue(zone, order);
- if (page == NULL)
+ struct page *page = __rmqueue(zone, order);
+ if (unlikely(page == NULL))
break;
- allocated++;
list_add_tail(&page->lru, list);
}
- spin_unlock_irqrestore(&zone->lock, flags);
- return allocated;
+ spin_unlock(&zone->lock);
+ return i;
}
#ifdef CONFIG_NUMA
@@ -572,14 +601,13 @@ void drain_remote_pages(void)
if (zone->zone_pgdat->node_id == numa_node_id())
continue;
- pset = zone->pageset[smp_processor_id()];
+ pset = zone_pcp(zone, smp_processor_id());
for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
struct per_cpu_pages *pcp;
pcp = &pset->pcp[i];
- if (pcp->count)
- pcp->count -= free_pages_bulk(zone, pcp->count,
- &pcp->list, 0);
+ free_pages_bulk(zone, pcp->count, &pcp->list, 0);
+ pcp->count = 0;
}
}
local_irq_restore(flags);
@@ -589,6 +617,7 @@ void drain_remote_pages(void)
#if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
static void __drain_pages(unsigned int cpu)
{
+ unsigned long flags;
struct zone *zone;
int i;
@@ -600,8 +629,10 @@ static void __drain_pages(unsigned int cpu)
struct per_cpu_pages *pcp;
pcp = &pset->pcp[i];
- pcp->count -= free_pages_bulk(zone, pcp->count,
- &pcp->list, 0);
+ local_irq_save(flags);
+ free_pages_bulk(zone, pcp->count, &pcp->list, 0);
+ pcp->count = 0;
+ local_irq_restore(flags);
}
}
}
@@ -647,18 +678,14 @@ void drain_local_pages(void)
}
#endif /* CONFIG_PM */
-static void zone_statistics(struct zonelist *zonelist, struct zone *z)
+static void zone_statistics(struct zonelist *zonelist, struct zone *z, int cpu)
{
#ifdef CONFIG_NUMA
- unsigned long flags;
- int cpu;
pg_data_t *pg = z->zone_pgdat;
pg_data_t *orig = zonelist->zones[0]->zone_pgdat;
struct per_cpu_pageset *p;
- local_irq_save(flags);
- cpu = smp_processor_id();
- p = zone_pcp(z,cpu);
+ p = zone_pcp(z, cpu);
if (pg == orig) {
p->numa_hit++;
} else {
@@ -669,14 +696,12 @@ static void zone_statistics(struct zonelist *zonelist, struct zone *z)
p->local_node++;
else
p->other_node++;
- local_irq_restore(flags);
#endif
}
/*
* Free a 0-order page
*/
-static void FASTCALL(free_hot_cold_page(struct page *page, int cold));
static void fastcall free_hot_cold_page(struct page *page, int cold)
{
struct zone *zone = page_zone(page);
@@ -687,18 +712,20 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
if (PageAnon(page))
page->mapping = NULL;
- if (free_pages_check(__FUNCTION__, page))
+ if (free_pages_check(page))
return;
- inc_page_state(pgfree);
kernel_map_pages(page, 1, 0);
pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
local_irq_save(flags);
+ __inc_page_state(pgfree);
list_add(&page->lru, &pcp->list);
pcp->count++;
- if (pcp->count >= pcp->high)
- pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
+ if (pcp->count >= pcp->high) {
+ free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
+ pcp->count -= pcp->batch;
+ }
local_irq_restore(flags);
put_cpu();
}
@@ -727,49 +754,58 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
* we cheat by calling it from here, in the order > 0 path. Saves a branch
* or two.
*/
-static struct page *
-buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags)
+static struct page *buffered_rmqueue(struct zonelist *zonelist,
+ struct zone *zone, int order, gfp_t gfp_flags)
{
unsigned long flags;
struct page *page;
int cold = !!(gfp_flags & __GFP_COLD);
+ int cpu;
again:
- if (order == 0) {
+ cpu = get_cpu();
+ if (likely(order == 0)) {
struct per_cpu_pages *pcp;
- page = NULL;
- pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
+ pcp = &zone_pcp(zone, cpu)->pcp[cold];
local_irq_save(flags);
- if (pcp->count <= pcp->low)
+ if (!pcp->count) {
pcp->count += rmqueue_bulk(zone, 0,
pcp->batch, &pcp->list);
- if (pcp->count) {
- page = list_entry(pcp->list.next, struct page, lru);
- list_del(&page->lru);
- pcp->count--;
+ if (unlikely(!pcp->count))
+ goto failed;
}
- local_irq_restore(flags);
- put_cpu();
+ page = list_entry(pcp->list.next, struct page, lru);
+ list_del(&page->lru);
+ pcp->count--;
} else {
spin_lock_irqsave(&zone->lock, flags);
page = __rmqueue(zone, order);
- spin_unlock_irqrestore(&zone->lock, flags);
+ spin_unlock(&zone->lock);
+ if (!page)
+ goto failed;
}
- if (page != NULL) {
- BUG_ON(bad_range(zone, page));
- mod_page_state_zone(zone, pgalloc, 1 << order);
- if (prep_new_page(page, order))
- goto again;
+ __mod_page_state_zone(zone, pgalloc, 1 << order);
+ zone_statistics(zonelist, zone, cpu);
+ local_irq_restore(flags);
+ put_cpu();
+
+ BUG_ON(bad_range(zone, page));
+ if (prep_new_page(page, order))
+ goto again;
- if (gfp_flags & __GFP_ZERO)
- prep_zero_page(page, order, gfp_flags);
+ if (gfp_flags & __GFP_ZERO)
+ prep_zero_page(page, order, gfp_flags);
- if (order && (gfp_flags & __GFP_COMP))
- prep_compound_page(page, order);
- }
+ if (order && (gfp_flags & __GFP_COMP))
+ prep_compound_page(page, order);
return page;
+
+failed:
+ local_irq_restore(flags);
+ put_cpu();
+ return NULL;
}
#define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */
@@ -842,12 +878,13 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
mark = (*z)->pages_high;
if (!zone_watermark_ok(*z, order, mark,
classzone_idx, alloc_flags))
- continue;
+ if (!zone_reclaim_mode ||
+ !zone_reclaim(*z, gfp_mask, order))
+ continue;
}
- page = buffered_rmqueue(*z, order, gfp_mask);
+ page = buffered_rmqueue(zonelist, *z, order, gfp_mask);
if (page) {
- zone_statistics(zonelist, *z);
break;
}
} while (*(++z) != NULL);
@@ -896,15 +933,15 @@ restart:
*
* The caller may dip into page reserves a bit more if the caller
* cannot run direct reclaim, or if the caller has realtime scheduling
- * policy.
+ * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will
+ * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH).
*/
alloc_flags = ALLOC_WMARK_MIN;
if ((unlikely(rt_task(p)) && !in_interrupt()) || !wait)
alloc_flags |= ALLOC_HARDER;
if (gfp_mask & __GFP_HIGH)
alloc_flags |= ALLOC_HIGH;
- if (wait)
- alloc_flags |= ALLOC_CPUSET;
+ alloc_flags |= ALLOC_CPUSET;
/*
* Go through the zonelist again. Let __GFP_HIGH and allocations
@@ -926,7 +963,7 @@ restart:
nofail_alloc:
/* go through the zonelist yet again, ignoring mins */
page = get_page_from_freelist(gfp_mask, order,
- zonelist, ALLOC_NO_WATERMARKS|ALLOC_CPUSET);
+ zonelist, ALLOC_NO_WATERMARKS);
if (page)
goto got_pg;
if (gfp_mask & __GFP_NOFAIL) {
@@ -945,6 +982,7 @@ rebalance:
cond_resched();
/* We now go into synchronous reclaim */
+ cpuset_memory_pressure_bump();
p->flags |= PF_MEMALLOC;
reclaim_state.reclaimed_slab = 0;
p->reclaim_state = &reclaim_state;
@@ -1171,7 +1209,7 @@ EXPORT_SYMBOL(nr_pagecache);
DEFINE_PER_CPU(long, nr_pagecache_local) = 0;
#endif
-void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask)
+static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask)
{
int cpu = 0;
@@ -1224,7 +1262,7 @@ void get_full_page_state(struct page_state *ret)
__get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask);
}
-unsigned long __read_page_state(unsigned long offset)
+unsigned long read_page_state_offset(unsigned long offset)
{
unsigned long ret = 0;
int cpu;
@@ -1238,18 +1276,26 @@ unsigned long __read_page_state(unsigned long offset)
return ret;
}
-void __mod_page_state(unsigned long offset, unsigned long delta)
+void __mod_page_state_offset(unsigned long offset, unsigned long delta)
+{
+ void *ptr;
+
+ ptr = &__get_cpu_var(page_states);
+ *(unsigned long *)(ptr + offset) += delta;
+}
+EXPORT_SYMBOL(__mod_page_state_offset);
+
+void mod_page_state_offset(unsigned long offset, unsigned long delta)
{
unsigned long flags;
- void* ptr;
+ void *ptr;
local_irq_save(flags);
ptr = &__get_cpu_var(page_states);
- *(unsigned long*)(ptr + offset) += delta;
+ *(unsigned long *)(ptr + offset) += delta;
local_irq_restore(flags);
}
-
-EXPORT_SYMBOL(__mod_page_state);
+EXPORT_SYMBOL(mod_page_state_offset);
void __get_zone_counts(unsigned long *active, unsigned long *inactive,
unsigned long *free, struct pglist_data *pgdat)
@@ -1335,7 +1381,7 @@ void show_free_areas(void)
show_node(zone);
printk("%s per-cpu:", zone->name);
- if (!zone->present_pages) {
+ if (!populated_zone(zone)) {
printk(" empty\n");
continue;
} else
@@ -1347,10 +1393,9 @@ void show_free_areas(void)
pageset = zone_pcp(zone, cpu);
for (temperature = 0; temperature < 2; temperature++)
- printk("cpu %d %s: low %d, high %d, batch %d used:%d\n",
+ printk("cpu %d %s: high %d, batch %d used:%d\n",
cpu,
temperature ? "cold" : "hot",
- pageset->pcp[temperature].low,
pageset->pcp[temperature].high,
pageset->pcp[temperature].batch,
pageset->pcp[temperature].count);
@@ -1413,7 +1458,7 @@ void show_free_areas(void)
show_node(zone);
printk("%s: ", zone->name);
- if (!zone->present_pages) {
+ if (!populated_zone(zone)) {
printk("empty\n");
continue;
}
@@ -1433,36 +1478,29 @@ void show_free_areas(void)
/*
* Builds allocation fallback zone lists.
+ *
+ * Add all populated zones of a node to the zonelist.
*/
-static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist, int j, int k)
-{
- switch (k) {
- struct zone *zone;
- default:
- BUG();
- case ZONE_HIGHMEM:
- zone = pgdat->node_zones + ZONE_HIGHMEM;
- if (zone->present_pages) {
+static int __init build_zonelists_node(pg_data_t *pgdat,
+ struct zonelist *zonelist, int nr_zones, int zone_type)
+{
+ struct zone *zone;
+
+ BUG_ON(zone_type > ZONE_HIGHMEM);
+
+ do {
+ zone = pgdat->node_zones + zone_type;
+ if (populated_zone(zone)) {
#ifndef CONFIG_HIGHMEM
- BUG();
+ BUG_ON(zone_type > ZONE_NORMAL);
#endif
- zonelist->zones[j++] = zone;
+ zonelist->zones[nr_zones++] = zone;
+ check_highest_zone(zone_type);
}
- case ZONE_NORMAL:
- zone = pgdat->node_zones + ZONE_NORMAL;
- if (zone->present_pages)
- zonelist->zones[j++] = zone;
- case ZONE_DMA32:
- zone = pgdat->node_zones + ZONE_DMA32;
- if (zone->present_pages)
- zonelist->zones[j++] = zone;
- case ZONE_DMA:
- zone = pgdat->node_zones + ZONE_DMA;
- if (zone->present_pages)
- zonelist->zones[j++] = zone;
- }
+ zone_type--;
- return j;
+ } while (zone_type >= 0);
+ return nr_zones;
}
static inline int highest_zone(int zone_bits)
@@ -1559,13 +1597,22 @@ static void __init build_zonelists(pg_data_t *pgdat)
prev_node = local_node;
nodes_clear(used_mask);
while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
+ int distance = node_distance(local_node, node);
+
+ /*
+ * If another node is sufficiently far away then it is better
+ * to reclaim pages in a zone before going off node.
+ */
+ if (distance > RECLAIM_DISTANCE)
+ zone_reclaim_mode = 1;
+
/*
* We don't want to pressure a particular node.
* So adding penalty to the first node in same
* distance group to make it round-robin.
*/
- if (node_distance(local_node, node) !=
- node_distance(local_node, prev_node))
+
+ if (distance != node_distance(local_node, prev_node))
node_load[node] += load;
prev_node = node;
load--;
@@ -1699,18 +1746,16 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
* up by free_all_bootmem() once the early boot process is
* done. Non-atomic initialization, single-pass.
*/
-void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
struct page *page;
unsigned long end_pfn = start_pfn + size;
unsigned long pfn;
- for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) {
+ for (pfn = start_pfn; pfn < end_pfn; pfn++) {
if (!early_pfn_valid(pfn))
continue;
- if (!early_pfn_in_nid(pfn, nid))
- continue;
page = pfn_to_page(pfn);
set_page_links(page, zone, nid, pfn);
set_page_count(page, 1);
@@ -1754,7 +1799,7 @@ void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
memmap_init_zone((size), (nid), (zone), (start_pfn))
#endif
-static int __devinit zone_batchsize(struct zone *zone)
+static int __meminit zone_batchsize(struct zone *zone)
{
int batch;
@@ -1794,19 +1839,35 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
pcp = &p->pcp[0]; /* hot */
pcp->count = 0;
- pcp->low = 0;
pcp->high = 6 * batch;
pcp->batch = max(1UL, 1 * batch);
INIT_LIST_HEAD(&pcp->list);
pcp = &p->pcp[1]; /* cold*/
pcp->count = 0;
- pcp->low = 0;
pcp->high = 2 * batch;
pcp->batch = max(1UL, batch/2);
INIT_LIST_HEAD(&pcp->list);
}
+/*
+ * setup_pagelist_highmark() sets the high water mark for hot per_cpu_pagelist
+ * to the value high for the pageset p.
+ */
+
+static void setup_pagelist_highmark(struct per_cpu_pageset *p,
+ unsigned long high)
+{
+ struct per_cpu_pages *pcp;
+
+ pcp = &p->pcp[0]; /* hot list */
+ pcp->high = high;
+ pcp->batch = max(1UL, high/4);
+ if ((high/4) > (PAGE_SHIFT * 8))
+ pcp->batch = PAGE_SHIFT * 8;
+}
+
+
#ifdef CONFIG_NUMA
/*
* Boot pageset table. One per cpu which is going to be used for all
@@ -1832,18 +1893,22 @@ static struct per_cpu_pageset
* Dynamically allocate memory for the
* per cpu pageset array in struct zone.
*/
-static int __devinit process_zones(int cpu)
+static int __meminit process_zones(int cpu)
{
struct zone *zone, *dzone;
for_each_zone(zone) {
- zone->pageset[cpu] = kmalloc_node(sizeof(struct per_cpu_pageset),
+ zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset),
GFP_KERNEL, cpu_to_node(cpu));
- if (!zone->pageset[cpu])
+ if (!zone_pcp(zone, cpu))
goto bad;
- setup_pageset(zone->pageset[cpu], zone_batchsize(zone));
+ setup_pageset(zone_pcp(zone, cpu), zone_batchsize(zone));
+
+ if (percpu_pagelist_fraction)
+ setup_pagelist_highmark(zone_pcp(zone, cpu),
+ (zone->present_pages / percpu_pagelist_fraction));
}
return 0;
@@ -1851,15 +1916,14 @@ bad:
for_each_zone(dzone) {
if (dzone == zone)
break;
- kfree(dzone->pageset[cpu]);
- dzone->pageset[cpu] = NULL;
+ kfree(zone_pcp(dzone, cpu));
+ zone_pcp(dzone, cpu) = NULL;
}
return -ENOMEM;
}
static inline void free_zone_pagesets(int cpu)
{
-#ifdef CONFIG_NUMA
struct zone *zone;
for_each_zone(zone) {
@@ -1868,10 +1932,9 @@ static inline void free_zone_pagesets(int cpu)
zone_pcp(zone, cpu) = NULL;
kfree(pset);
}
-#endif
}
-static int __devinit pageset_cpuup_callback(struct notifier_block *nfb,
+static int __meminit pageset_cpuup_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
@@ -1911,7 +1974,7 @@ void __init setup_per_cpu_pageset(void)
#endif
-static __devinit
+static __meminit
void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
{
int i;
@@ -1931,7 +1994,7 @@ void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
init_waitqueue_head(zone->wait_table + i);
}
-static __devinit void zone_pcp_init(struct zone *zone)
+static __meminit void zone_pcp_init(struct zone *zone)
{
int cpu;
unsigned long batch = zone_batchsize(zone);
@@ -1939,7 +2002,7 @@ static __devinit void zone_pcp_init(struct zone *zone)
for (cpu = 0; cpu < NR_CPUS; cpu++) {
#ifdef CONFIG_NUMA
/* Early boot. Slab allocator not functional yet */
- zone->pageset[cpu] = &boot_pageset[cpu];
+ zone_pcp(zone, cpu) = &boot_pageset[cpu];
setup_pageset(&boot_pageset[cpu],0);
#else
setup_pageset(zone_pcp(zone,cpu), batch);
@@ -1949,7 +2012,7 @@ static __devinit void zone_pcp_init(struct zone *zone)
zone->name, zone->present_pages, batch);
}
-static __devinit void init_currently_empty_zone(struct zone *zone,
+static __meminit void init_currently_empty_zone(struct zone *zone,
unsigned long zone_start_pfn, unsigned long size)
{
struct pglist_data *pgdat = zone->zone_pgdat;
@@ -2116,7 +2179,7 @@ static int frag_show(struct seq_file *m, void *arg)
int order;
for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
- if (!zone->present_pages)
+ if (!populated_zone(zone))
continue;
spin_lock_irqsave(&zone->lock, flags);
@@ -2149,7 +2212,7 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
int i;
- if (!zone->present_pages)
+ if (!populated_zone(zone))
continue;
spin_lock_irqsave(&zone->lock, flags);
@@ -2182,7 +2245,7 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
seq_printf(m,
")"
"\n pagesets");
- for (i = 0; i < ARRAY_SIZE(zone->pageset); i++) {
+ for_each_online_cpu(i) {
struct per_cpu_pageset *pageset;
int j;
@@ -2197,12 +2260,10 @@ static int zoneinfo_show(struct seq_file *m, void *arg)
seq_printf(m,
"\n cpu: %i pcp: %i"
"\n count: %i"
- "\n low: %i"
"\n high: %i"
"\n batch: %i",
i, j,
pageset->pcp[j].count,
- pageset->pcp[j].low,
pageset->pcp[j].high,
pageset->pcp[j].batch);
}
@@ -2257,32 +2318,40 @@ static char *vmstat_text[] = {
"pgpgout",
"pswpin",
"pswpout",
- "pgalloc_high",
+ "pgalloc_high",
"pgalloc_normal",
+ "pgalloc_dma32",
"pgalloc_dma",
+
"pgfree",
"pgactivate",
"pgdeactivate",
"pgfault",
"pgmajfault",
+
"pgrefill_high",
"pgrefill_normal",
+ "pgrefill_dma32",
"pgrefill_dma",
"pgsteal_high",
"pgsteal_normal",
+ "pgsteal_dma32",
"pgsteal_dma",
+
"pgscan_kswapd_high",
"pgscan_kswapd_normal",
-
+ "pgscan_kswapd_dma32",
"pgscan_kswapd_dma",
+
"pgscan_direct_high",
"pgscan_direct_normal",
+ "pgscan_direct_dma32",
"pgscan_direct_dma",
- "pginodesteal",
+ "pginodesteal",
"slabs_scanned",
"kswapd_steal",
"kswapd_inodesteal",
@@ -2539,6 +2608,32 @@ int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
return 0;
}
+/*
+ * percpu_pagelist_fraction - changes the pcp->high for each zone on each
+ * cpu. It is the fraction of total pages in each zone that a hot per cpu pagelist
+ * can have before it gets flushed back to buddy allocator.
+ */
+
+int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write,
+ struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+{
+ struct zone *zone;
+ unsigned int cpu;
+ int ret;
+
+ ret = proc_dointvec_minmax(table, write, file, buffer, length, ppos);
+ if (!write || (ret == -EINVAL))
+ return ret;
+ for_each_zone(zone) {
+ for_each_online_cpu(cpu) {
+ unsigned long high;
+ high = zone->present_pages / percpu_pagelist_fraction;
+ setup_pagelist_highmark(zone_pcp(zone, cpu), high);
+ }
+ }
+ return 0;
+}
+
__initdata int hashdist = HASHDIST_DEFAULT;
#ifdef CONFIG_NUMA
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 52822c98c489..c4b6d0afd736 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -90,7 +90,7 @@ struct pdflush_work {
static int __pdflush(struct pdflush_work *my_work)
{
- current->flags |= PF_FLUSHER;
+ current->flags |= PF_FLUSHER | PF_SWAPWRITE;
my_work->fn = NULL;
my_work->who = current;
INIT_LIST_HEAD(&my_work->list);
diff --git a/mm/readahead.c b/mm/readahead.c
index 72e7adbb87c7..8d6eeaaa6296 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -158,7 +158,7 @@ static int read_pages(struct address_space *mapping, struct file *filp,
{
unsigned page_idx;
struct pagevec lru_pvec;
- int ret = 0;
+ int ret;
if (mapping->a_ops->readpages) {
ret = mapping->a_ops->readpages(filp, mapping, pages, nr_pages);
@@ -171,14 +171,17 @@ static int read_pages(struct address_space *mapping, struct file *filp,
list_del(&page->lru);
if (!add_to_page_cache(page, mapping,
page->index, GFP_KERNEL)) {
- mapping->a_ops->readpage(filp, page);
- if (!pagevec_add(&lru_pvec, page))
- __pagevec_lru_add(&lru_pvec);
- } else {
- page_cache_release(page);
+ ret = mapping->a_ops->readpage(filp, page);
+ if (ret != AOP_TRUNCATED_PAGE) {
+ if (!pagevec_add(&lru_pvec, page))
+ __pagevec_lru_add(&lru_pvec);
+ continue;
+ } /* else fall through to release */
}
+ page_cache_release(page);
}
pagevec_lru_add(&lru_pvec);
+ ret = 0;
out:
return ret;
}
diff --git a/mm/rmap.c b/mm/rmap.c
index f853c6def159..d85a99d28c03 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -20,20 +20,20 @@
/*
* Lock ordering in mm:
*
- * inode->i_sem (while writing or truncating, not reading or faulting)
+ * inode->i_mutex (while writing or truncating, not reading or faulting)
* inode->i_alloc_sem
*
* When a page fault occurs in writing from user to file, down_read
- * of mmap_sem nests within i_sem; in sys_msync, i_sem nests within
- * down_read of mmap_sem; i_sem and down_write of mmap_sem are never
- * taken together; in truncation, i_sem is taken outermost.
+ * of mmap_sem nests within i_mutex; in sys_msync, i_mutex nests within
+ * down_read of mmap_sem; i_mutex and down_write of mmap_sem are never
+ * taken together; in truncation, i_mutex is taken outermost.
*
* mm->mmap_sem
* page->flags PG_locked (lock_page)
* mapping->i_mmap_lock
* anon_vma->lock
* mm->page_table_lock or pte_lock
- * zone->lru_lock (in mark_page_accessed)
+ * zone->lru_lock (in mark_page_accessed, isolate_lru_page)
* swap_lock (in swap_duplicate, swap_info_get)
* mmlist_lock (in mmput, drain_mmlist and others)
* mapping->private_lock (in __set_page_dirty_buffers)
@@ -435,6 +435,30 @@ int page_referenced(struct page *page, int is_locked)
}
/**
+ * page_set_anon_rmap - setup new anonymous rmap
+ * @page: the page to add the mapping to
+ * @vma: the vm area in which the mapping is added
+ * @address: the user virtual address mapped
+ */
+static void __page_set_anon_rmap(struct page *page,
+ struct vm_area_struct *vma, unsigned long address)
+{
+ 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);
+
+ /*
+ * nr_mapped state can be updated without turning off
+ * interrupts because it is not modified via interrupt.
+ */
+ __inc_page_state(nr_mapped);
+}
+
+/**
* page_add_anon_rmap - add pte mapping to an anonymous page
* @page: the page to add the mapping to
* @vma: the vm area in which the mapping is added
@@ -445,20 +469,27 @@ int page_referenced(struct page *page, int is_locked)
void page_add_anon_rmap(struct page *page,
struct vm_area_struct *vma, unsigned long address)
{
- if (atomic_inc_and_test(&page->_mapcount)) {
- 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);
- }
+ if (atomic_inc_and_test(&page->_mapcount))
+ __page_set_anon_rmap(page, vma, address);
/* else checking page index and mapping is racy */
}
+/*
+ * page_add_new_anon_rmap - add pte mapping to a new anonymous page
+ * @page: the page to add the mapping to
+ * @vma: the vm area in which the mapping is added
+ * @address: the user virtual address mapped
+ *
+ * Same as page_add_anon_rmap but must only be called on *new* pages.
+ * This means the inc-and-test can be bypassed.
+ */
+void page_add_new_anon_rmap(struct page *page,
+ struct vm_area_struct *vma, unsigned long address)
+{
+ atomic_set(&page->_mapcount, 0); /* elevate count by 1 (starts at -1) */
+ __page_set_anon_rmap(page, vma, address);
+}
+
/**
* page_add_file_rmap - add pte mapping to a file page
* @page: the page to add the mapping to
@@ -471,7 +502,7 @@ void page_add_file_rmap(struct page *page)
BUG_ON(!pfn_valid(page_to_pfn(page)));
if (atomic_inc_and_test(&page->_mapcount))
- inc_page_state(nr_mapped);
+ __inc_page_state(nr_mapped);
}
/**
@@ -483,6 +514,13 @@ void page_add_file_rmap(struct page *page)
void page_remove_rmap(struct page *page)
{
if (atomic_add_negative(-1, &page->_mapcount)) {
+ if (page_mapcount(page) < 0) {
+ printk (KERN_EMERG "Eeek! page_mapcount(page) went negative! (%d)\n", page_mapcount(page));
+ printk (KERN_EMERG " page->flags = %lx\n", page->flags);
+ printk (KERN_EMERG " page->count = %x\n", page_count(page));
+ printk (KERN_EMERG " page->mapping = %p\n", page->mapping);
+ }
+
BUG_ON(page_mapcount(page) < 0);
/*
* It would be tidy to reset the PageAnon mapping here,
@@ -495,7 +533,7 @@ void page_remove_rmap(struct page *page)
*/
if (page_test_and_clear_dirty(page))
set_page_dirty(page);
- dec_page_state(nr_mapped);
+ __dec_page_state(nr_mapped);
}
}
diff --git a/mm/shmem.c b/mm/shmem.c
index dc25565a61e9..ce501bce1c2e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -457,7 +457,7 @@ static void shmem_free_pages(struct list_head *next)
} while (next);
}
-static void shmem_truncate(struct inode *inode)
+static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
{
struct shmem_inode_info *info = SHMEM_I(inode);
unsigned long idx;
@@ -475,18 +475,27 @@ static void shmem_truncate(struct inode *inode)
long nr_swaps_freed = 0;
int offset;
int freed;
+ int punch_hole = 0;
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- idx = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
if (idx >= info->next_index)
return;
spin_lock(&info->lock);
info->flags |= SHMEM_TRUNCATE;
- limit = info->next_index;
- info->next_index = idx;
+ if (likely(end == (loff_t) -1)) {
+ limit = info->next_index;
+ info->next_index = idx;
+ } else {
+ limit = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ if (limit > info->next_index)
+ limit = info->next_index;
+ punch_hole = 1;
+ }
+
topdir = info->i_indirect;
- if (topdir && idx <= SHMEM_NR_DIRECT) {
+ if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) {
info->i_indirect = NULL;
nr_pages_to_free++;
list_add(&topdir->lru, &pages_to_free);
@@ -573,11 +582,12 @@ static void shmem_truncate(struct inode *inode)
set_page_private(subdir, page_private(subdir) - freed);
if (offset)
spin_unlock(&info->lock);
- BUG_ON(page_private(subdir) > offset);
+ if (!punch_hole)
+ BUG_ON(page_private(subdir) > offset);
}
if (offset)
offset = 0;
- else if (subdir) {
+ else if (subdir && !page_private(subdir)) {
dir[diroff] = NULL;
nr_pages_to_free++;
list_add(&subdir->lru, &pages_to_free);
@@ -594,7 +604,7 @@ done2:
* Also, though shmem_getpage checks i_size before adding to
* cache, no recheck after: so fix the narrow window there too.
*/
- truncate_inode_pages(inode->i_mapping, inode->i_size);
+ truncate_inode_pages_range(inode->i_mapping, start, end);
}
spin_lock(&info->lock);
@@ -614,6 +624,11 @@ done2:
}
}
+static void shmem_truncate(struct inode *inode)
+{
+ shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
+}
+
static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
@@ -855,7 +870,7 @@ unlock:
swap_free(swap);
redirty:
set_page_dirty(page);
- return WRITEPAGE_ACTIVATE; /* Return with the page locked */
+ return AOP_WRITEPAGE_ACTIVATE; /* Return with the page locked */
}
#ifdef CONFIG_NUMA
@@ -1255,7 +1270,7 @@ out_nomem:
return retval;
}
-static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+int shmem_mmap(struct file *file, struct vm_area_struct *vma)
{
file_accessed(file);
vma->vm_ops = &shmem_vm_ops;
@@ -1301,7 +1316,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
case S_IFREG:
inode->i_op = &shmem_inode_operations;
inode->i_fop = &shmem_file_operations;
- mpol_shared_policy_init(&info->policy);
+ mpol_shared_policy_init(&info->policy, sbinfo->policy,
+ &sbinfo->policy_nodes);
break;
case S_IFDIR:
inode->i_nlink++;
@@ -1315,7 +1331,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
* Must not load anything in the rbtree,
* mpol_free_shared_policy will not be called.
*/
- mpol_shared_policy_init(&info->policy);
+ mpol_shared_policy_init(&info->policy, MPOL_DEFAULT,
+ NULL);
break;
}
} else if (sbinfo->max_inodes) {
@@ -1355,7 +1372,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
pos = *ppos;
written = 0;
@@ -1440,7 +1457,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
if (written)
err = written;
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return err;
}
@@ -1476,7 +1493,7 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
/*
* We must evaluate after, since reads (unlike writes)
- * are called without i_sem protection against truncate
+ * are called without i_mutex protection against truncate
*/
nr = PAGE_CACHE_SIZE;
i_size = i_size_read(inode);
@@ -1828,7 +1845,9 @@ static struct inode_operations shmem_symlink_inode_operations = {
.put_link = shmem_put_link,
};
-static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes)
+static int shmem_parse_options(char *options, int *mode, uid_t *uid,
+ gid_t *gid, unsigned long *blocks, unsigned long *inodes,
+ int *policy, nodemask_t *policy_nodes)
{
char *this_char, *value, *rest;
@@ -1882,6 +1901,19 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid,
*gid = simple_strtoul(value,&rest,0);
if (*rest)
goto bad_val;
+ } else if (!strcmp(this_char,"mpol")) {
+ if (!strcmp(value,"default"))
+ *policy = MPOL_DEFAULT;
+ else if (!strcmp(value,"preferred"))
+ *policy = MPOL_PREFERRED;
+ else if (!strcmp(value,"bind"))
+ *policy = MPOL_BIND;
+ else if (!strcmp(value,"interleave"))
+ *policy = MPOL_INTERLEAVE;
+ else
+ goto bad_val;
+ } else if (!strcmp(this_char,"mpol_nodelist")) {
+ nodelist_parse(value, *policy_nodes);
} else {
printk(KERN_ERR "tmpfs: Bad mount option %s\n",
this_char);
@@ -1902,12 +1934,14 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
unsigned long max_blocks = sbinfo->max_blocks;
unsigned long max_inodes = sbinfo->max_inodes;
+ int policy = sbinfo->policy;
+ nodemask_t policy_nodes = sbinfo->policy_nodes;
unsigned long blocks;
unsigned long inodes;
int error = -EINVAL;
- if (shmem_parse_options(data, NULL, NULL, NULL,
- &max_blocks, &max_inodes))
+ if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks,
+ &max_inodes, &policy, &policy_nodes))
return error;
spin_lock(&sbinfo->stat_lock);
@@ -1933,6 +1967,8 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
sbinfo->free_blocks = max_blocks - blocks;
sbinfo->max_inodes = max_inodes;
sbinfo->free_inodes = max_inodes - inodes;
+ sbinfo->policy = policy;
+ sbinfo->policy_nodes = policy_nodes;
out:
spin_unlock(&sbinfo->stat_lock);
return error;
@@ -1957,6 +1993,8 @@ static int shmem_fill_super(struct super_block *sb,
struct shmem_sb_info *sbinfo;
unsigned long blocks = 0;
unsigned long inodes = 0;
+ int policy = MPOL_DEFAULT;
+ nodemask_t policy_nodes = node_online_map;
#ifdef CONFIG_TMPFS
/*
@@ -1969,8 +2007,8 @@ static int shmem_fill_super(struct super_block *sb,
inodes = totalram_pages - totalhigh_pages;
if (inodes > blocks)
inodes = blocks;
- if (shmem_parse_options(data, &mode, &uid, &gid,
- &blocks, &inodes))
+ if (shmem_parse_options(data, &mode, &uid, &gid, &blocks,
+ &inodes, &policy, &policy_nodes))
return -EINVAL;
}
#else
@@ -1988,6 +2026,8 @@ static int shmem_fill_super(struct super_block *sb,
sbinfo->free_blocks = blocks;
sbinfo->max_inodes = inodes;
sbinfo->free_inodes = inodes;
+ sbinfo->policy = policy;
+ sbinfo->policy_nodes = policy_nodes;
sb->s_fs_info = sbinfo;
sb->s_maxbytes = SHMEM_MAX_BYTES;
@@ -2083,6 +2123,7 @@ static struct file_operations shmem_file_operations = {
static struct inode_operations shmem_inode_operations = {
.truncate = shmem_truncate,
.setattr = shmem_notify_change,
+ .truncate_range = shmem_truncate_range,
};
static struct inode_operations shmem_dir_inode_operations = {
diff --git a/mm/slab.c b/mm/slab.c
index e5ec26e0c460..6f8495e2185b 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -68,7 +68,7 @@
* Further notes from the original documentation:
*
* 11 April '97. Started multi-threading - markhe
- * The global cache-chain is protected by the semaphore 'cache_chain_sem'.
+ * The global cache-chain is protected by the mutex 'cache_chain_mutex'.
* The sem is only needed when accessing/extending the cache-chain, which
* can never happen inside an interrupt (kmem_cache_create(),
* kmem_cache_shrink() and kmem_cache_reap()).
@@ -103,6 +103,8 @@
#include <linux/rcupdate.h>
#include <linux/string.h>
#include <linux/nodemask.h>
+#include <linux/mempolicy.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
@@ -130,7 +132,6 @@
#define FORCED_DEBUG 0
#endif
-
/* Shouldn't this be in a header file somewhere? */
#define BYTES_PER_WORD sizeof(void *)
@@ -217,12 +218,12 @@ static unsigned long offslab_limit;
* Slabs are chained into three list: fully used, partial, fully free slabs.
*/
struct slab {
- struct list_head list;
- unsigned long colouroff;
- void *s_mem; /* including colour offset */
- unsigned int inuse; /* num of objs active in slab */
- kmem_bufctl_t free;
- unsigned short nodeid;
+ struct list_head list;
+ unsigned long colouroff;
+ void *s_mem; /* including colour offset */
+ unsigned int inuse; /* num of objs active in slab */
+ kmem_bufctl_t free;
+ unsigned short nodeid;
};
/*
@@ -242,9 +243,9 @@ struct slab {
* We assume struct slab_rcu can overlay struct slab when destroying.
*/
struct slab_rcu {
- struct rcu_head head;
- kmem_cache_t *cachep;
- void *addr;
+ struct rcu_head head;
+ kmem_cache_t *cachep;
+ void *addr;
};
/*
@@ -279,23 +280,23 @@ struct array_cache {
#define BOOT_CPUCACHE_ENTRIES 1
struct arraycache_init {
struct array_cache cache;
- void * entries[BOOT_CPUCACHE_ENTRIES];
+ void *entries[BOOT_CPUCACHE_ENTRIES];
};
/*
* 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;
- unsigned long next_reap;
- 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 */
+ 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;
+ unsigned long next_reap;
+ 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 */
};
/*
@@ -367,63 +368,63 @@ static inline void kmem_list3_init(struct kmem_list3 *parent)
*
* manages a cache.
*/
-
+
struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
- struct array_cache *array[NR_CPUS];
- unsigned int batchcount;
- unsigned int limit;
- unsigned int shared;
- unsigned int objsize;
+ struct array_cache *array[NR_CPUS];
+ unsigned int batchcount;
+ unsigned int limit;
+ 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 */
- spinlock_t spinlock;
+ struct kmem_list3 *nodelists[MAX_NUMNODES];
+ unsigned int flags; /* constant flags */
+ unsigned int num; /* # of objs per slab */
+ spinlock_t spinlock;
/* 3) cache_grow/shrink */
/* order of pgs per slab (2^n) */
- unsigned int gfporder;
+ unsigned int gfporder;
/* force GFP flags, e.g. GFP_DMA */
- gfp_t gfpflags;
+ gfp_t gfpflags;
- size_t colour; /* cache colouring range */
- unsigned int colour_off; /* colour offset */
- unsigned int colour_next; /* cache colouring */
- kmem_cache_t *slabp_cache;
- unsigned int slab_size;
- unsigned int dflags; /* dynamic flags */
+ size_t colour; /* cache colouring range */
+ unsigned int colour_off; /* colour offset */
+ unsigned int colour_next; /* cache colouring */
+ kmem_cache_t *slabp_cache;
+ unsigned int slab_size;
+ unsigned int dflags; /* dynamic flags */
/* constructor func */
- void (*ctor)(void *, kmem_cache_t *, unsigned long);
+ void (*ctor) (void *, kmem_cache_t *, unsigned long);
/* de-constructor func */
- void (*dtor)(void *, kmem_cache_t *, unsigned long);
+ void (*dtor) (void *, kmem_cache_t *, unsigned long);
/* 4) cache creation/removal */
- const char *name;
- struct list_head next;
+ const char *name;
+ struct list_head next;
/* 5) statistics */
#if STATS
- unsigned long num_active;
- unsigned long num_allocations;
- unsigned long high_mark;
- unsigned long grown;
- unsigned long reaped;
- unsigned long errors;
- unsigned long max_freeable;
- unsigned long node_allocs;
- unsigned long node_frees;
- atomic_t allochit;
- atomic_t allocmiss;
- atomic_t freehit;
- atomic_t freemiss;
+ unsigned long num_active;
+ unsigned long num_allocations;
+ unsigned long high_mark;
+ unsigned long grown;
+ unsigned long reaped;
+ unsigned long errors;
+ unsigned long max_freeable;
+ unsigned long node_allocs;
+ unsigned long node_frees;
+ atomic_t allochit;
+ atomic_t allocmiss;
+ atomic_t freehit;
+ atomic_t freemiss;
#endif
#if DEBUG
- int dbghead;
- int reallen;
+ int dbghead;
+ int reallen;
#endif
};
@@ -523,14 +524,15 @@ static unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp)
{
BUG_ON(!(cachep->flags & SLAB_RED_ZONE));
if (cachep->flags & SLAB_STORE_USER)
- return (unsigned long*) (objp+cachep->objsize-2*BYTES_PER_WORD);
- return (unsigned long*) (objp+cachep->objsize-BYTES_PER_WORD);
+ return (unsigned long *)(objp + cachep->objsize -
+ 2 * BYTES_PER_WORD);
+ return (unsigned long *)(objp + cachep->objsize - BYTES_PER_WORD);
}
static void **dbg_userword(kmem_cache_t *cachep, void *objp)
{
BUG_ON(!(cachep->flags & SLAB_STORE_USER));
- return (void**)(objp+cachep->objsize-BYTES_PER_WORD);
+ return (void **)(objp + cachep->objsize - BYTES_PER_WORD);
}
#else
@@ -607,31 +609,31 @@ struct cache_names {
static struct cache_names __initdata cache_names[] = {
#define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" },
#include <linux/kmalloc_sizes.h>
- { NULL, }
+ {NULL,}
#undef CACHE
};
static struct arraycache_init initarray_cache __initdata =
- { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
static struct arraycache_init initarray_generic =
- { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
/* internal cache of cache description objs */
static kmem_cache_t cache_cache = {
- .batchcount = 1,
- .limit = BOOT_CPUCACHE_ENTRIES,
- .shared = 1,
- .objsize = sizeof(kmem_cache_t),
- .flags = SLAB_NO_REAP,
- .spinlock = SPIN_LOCK_UNLOCKED,
- .name = "kmem_cache",
+ .batchcount = 1,
+ .limit = BOOT_CPUCACHE_ENTRIES,
+ .shared = 1,
+ .objsize = sizeof(kmem_cache_t),
+ .flags = SLAB_NO_REAP,
+ .spinlock = SPIN_LOCK_UNLOCKED,
+ .name = "kmem_cache",
#if DEBUG
- .reallen = sizeof(kmem_cache_t),
+ .reallen = sizeof(kmem_cache_t),
#endif
};
/* Guard access to the cache-chain. */
-static struct semaphore cache_chain_sem;
+static DEFINE_MUTEX(cache_chain_mutex);
static struct list_head cache_chain;
/*
@@ -655,9 +657,9 @@ static enum {
static DEFINE_PER_CPU(struct work_struct, reap_work);
-static void free_block(kmem_cache_t* cachep, void** objpp, int len, int node);
-static void enable_cpucache (kmem_cache_t *cachep);
-static void cache_reap (void *unused);
+static void free_block(kmem_cache_t *cachep, void **objpp, int len, int node);
+static void enable_cpucache(kmem_cache_t *cachep);
+static void cache_reap(void *unused);
static int __node_shrink(kmem_cache_t *cachep, int node);
static inline struct array_cache *ac_data(kmem_cache_t *cachep)
@@ -671,9 +673,9 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, gfp_t gfpflags)
#if DEBUG
/* This happens if someone tries to call
- * kmem_cache_create(), or __kmalloc(), before
- * the generic caches are initialized.
- */
+ * kmem_cache_create(), or __kmalloc(), before
+ * the generic caches are initialized.
+ */
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
#endif
while (size > csizep->cs_size)
@@ -697,10 +699,10 @@ EXPORT_SYMBOL(kmem_find_general_cachep);
/* Cal the num objs, wastage, and bytes left over for a given slab size. */
static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
- int flags, size_t *left_over, unsigned int *num)
+ int flags, size_t *left_over, unsigned int *num)
{
int i;
- size_t wastage = PAGE_SIZE<<gfporder;
+ size_t wastage = PAGE_SIZE << gfporder;
size_t extra = 0;
size_t base = 0;
@@ -709,7 +711,7 @@ static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
extra = sizeof(kmem_bufctl_t);
}
i = 0;
- while (i*size + ALIGN(base+i*extra, align) <= wastage)
+ while (i * size + ALIGN(base + i * extra, align) <= wastage)
i++;
if (i > 0)
i--;
@@ -718,8 +720,8 @@ static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
i = SLAB_LIMIT;
*num = i;
- wastage -= i*size;
- wastage -= ALIGN(base+i*extra, align);
+ wastage -= i * size;
+ wastage -= ALIGN(base + i * extra, align);
*left_over = wastage;
}
@@ -728,7 +730,7 @@ static void cache_estimate(unsigned long gfporder, size_t size, size_t align,
static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
{
printk(KERN_ERR "slab error in %s(): cache `%s': %s\n",
- function, cachep->name, msg);
+ function, cachep->name, msg);
dump_stack();
}
@@ -755,9 +757,9 @@ static void __devinit start_cpu_timer(int cpu)
}
static struct array_cache *alloc_arraycache(int node, int entries,
- int batchcount)
+ int batchcount)
{
- int memsize = sizeof(void*)*entries+sizeof(struct array_cache);
+ int memsize = sizeof(void *) * entries + sizeof(struct array_cache);
struct array_cache *nc = NULL;
nc = kmalloc_node(memsize, GFP_KERNEL, node);
@@ -772,10 +774,12 @@ static struct array_cache *alloc_arraycache(int node, int entries,
}
#ifdef CONFIG_NUMA
+static void *__cache_alloc_node(kmem_cache_t *, gfp_t, int);
+
static inline struct array_cache **alloc_alien_cache(int node, int limit)
{
struct array_cache **ac_ptr;
- int memsize = sizeof(void*)*MAX_NUMNODES;
+ int memsize = sizeof(void *) * MAX_NUMNODES;
int i;
if (limit > 1)
@@ -789,7 +793,7 @@ static inline struct array_cache **alloc_alien_cache(int node, int limit)
}
ac_ptr[i] = alloc_arraycache(node, limit, 0xbaadf00d);
if (!ac_ptr[i]) {
- for (i--; i <=0; i--)
+ for (i--; i <= 0; i--)
kfree(ac_ptr[i]);
kfree(ac_ptr);
return NULL;
@@ -807,12 +811,13 @@ static inline void free_alien_cache(struct array_cache **ac_ptr)
return;
for_each_node(i)
- kfree(ac_ptr[i]);
+ kfree(ac_ptr[i]);
kfree(ac_ptr);
}
-static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache *ac, int node)
+static inline void __drain_alien_cache(kmem_cache_t *cachep,
+ struct array_cache *ac, int node)
{
struct kmem_list3 *rl3 = cachep->nodelists[node];
@@ -826,7 +831,7 @@ static inline void __drain_alien_cache(kmem_cache_t *cachep, struct array_cache
static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
{
- int i=0;
+ int i = 0;
struct array_cache *ac;
unsigned long flags;
@@ -846,18 +851,17 @@ static void drain_alien_cache(kmem_cache_t *cachep, struct kmem_list3 *l3)
#endif
static int __devinit cpuup_callback(struct notifier_block *nfb,
- unsigned long action, void *hcpu)
+ unsigned long action, void *hcpu)
{
long cpu = (long)hcpu;
- kmem_cache_t* cachep;
+ 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);
+ mutex_lock(&cache_chain_mutex);
/* 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
@@ -871,27 +875,29 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
*/
if (!cachep->nodelists[node]) {
if (!(l3 = kmalloc_node(memsize,
- GFP_KERNEL, node)))
+ GFP_KERNEL, node)))
goto bad;
kmem_list3_init(l3);
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+ ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
cachep->nodelists[node] = l3;
}
spin_lock_irq(&cachep->nodelists[node]->list_lock);
cachep->nodelists[node]->free_limit =
- (1 + nr_cpus_node(node)) *
- cachep->batchcount + cachep->num;
+ (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 */
+ & array cache's */
list_for_each_entry(cachep, &cache_chain, next) {
+ struct array_cache *nc;
+
nc = alloc_arraycache(node, cachep->limit,
- cachep->batchcount);
+ cachep->batchcount);
if (!nc)
goto bad;
cachep->array[cpu] = nc;
@@ -900,16 +906,17 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
BUG_ON(!l3);
if (!l3->shared) {
if (!(nc = alloc_arraycache(node,
- cachep->shared*cachep->batchcount,
- 0xbaadf00d)))
- goto bad;
+ cachep->shared *
+ cachep->batchcount,
+ 0xbaadf00d)))
+ goto bad;
/* we are serialised from CPU_DEAD or
- CPU_UP_CANCELLED by the cpucontrol lock */
+ CPU_UP_CANCELLED by the cpucontrol lock */
l3->shared = nc;
}
}
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
break;
case CPU_ONLINE:
start_cpu_timer(cpu);
@@ -918,7 +925,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
case CPU_DEAD:
/* fall thru */
case CPU_UP_CANCELED:
- down(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
list_for_each_entry(cachep, &cache_chain, next) {
struct array_cache *nc;
@@ -942,13 +949,13 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
free_block(cachep, nc->entry, nc->avail, node);
if (!cpus_empty(mask)) {
- spin_unlock(&l3->list_lock);
- goto unlock_cache;
- }
+ spin_unlock(&l3->list_lock);
+ goto unlock_cache;
+ }
if (l3->shared) {
free_block(cachep, l3->shared->entry,
- l3->shared->avail, node);
+ l3->shared->avail, node);
kfree(l3->shared);
l3->shared = NULL;
}
@@ -966,17 +973,17 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
} else {
spin_unlock(&l3->list_lock);
}
-unlock_cache:
+ unlock_cache:
spin_unlock_irq(&cachep->spinlock);
kfree(nc);
}
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
break;
#endif
}
return NOTIFY_OK;
-bad:
- up(&cache_chain_sem);
+ bad:
+ mutex_unlock(&cache_chain_mutex);
return NOTIFY_BAD;
}
@@ -985,8 +992,7 @@ 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)
+static void init_list(kmem_cache_t *cachep, struct kmem_list3 *list, int nodeid)
{
struct kmem_list3 *ptr;
@@ -1045,7 +1051,6 @@ void __init kmem_cache_init(void)
*/
/* 1) create the cache_cache */
- init_MUTEX(&cache_chain_sem);
INIT_LIST_HEAD(&cache_chain);
list_add(&cache_cache.next, &cache_chain);
cache_cache.colour_off = cache_line_size();
@@ -1055,14 +1060,14 @@ void __init kmem_cache_init(void)
cache_cache.objsize = ALIGN(cache_cache.objsize, cache_line_size());
cache_estimate(0, cache_cache.objsize, cache_line_size(), 0,
- &left_over, &cache_cache.num);
+ &left_over, &cache_cache.num);
if (!cache_cache.num)
BUG();
- cache_cache.colour = left_over/cache_cache.colour_off;
+ cache_cache.colour = left_over / cache_cache.colour_off;
cache_cache.colour_next = 0;
- cache_cache.slab_size = ALIGN(cache_cache.num*sizeof(kmem_bufctl_t) +
- sizeof(struct slab), cache_line_size());
+ cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) +
+ sizeof(struct slab), cache_line_size());
/* 2+3) create the kmalloc caches */
sizes = malloc_sizes;
@@ -1074,14 +1079,18 @@ void __init kmem_cache_init(void)
*/
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);
+ 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);
+ 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) {
/*
@@ -1091,35 +1100,41 @@ void __init kmem_cache_init(void)
* Note for systems short on memory removing the alignment will
* allow tighter packing of the smaller caches.
*/
- if(!sizes->cs_cachep)
+ 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);
+ 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))) {
- offslab_limit = sizes->cs_size-sizeof(struct slab);
+ offslab_limit = sizes->cs_size - sizeof(struct slab);
offslab_limit /= sizeof(kmem_bufctl_t);
}
sizes->cs_dmacachep = kmem_cache_create(names->name_dma,
- sizes->cs_size, ARCH_KMALLOC_MINALIGN,
- (ARCH_KMALLOC_FLAGS | SLAB_CACHE_DMA | SLAB_PANIC),
- NULL, NULL);
+ sizes->cs_size,
+ ARCH_KMALLOC_MINALIGN,
+ (ARCH_KMALLOC_FLAGS |
+ SLAB_CACHE_DMA |
+ SLAB_PANIC), NULL,
+ NULL);
sizes++;
names++;
}
/* 4) Replace the bootstrap head arrays */
{
- void * ptr;
+ 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));
+ sizeof(struct arraycache_init));
cache_cache.array[smp_processor_id()] = ptr;
local_irq_enable();
@@ -1127,11 +1142,11 @@ void __init kmem_cache_init(void)
local_irq_disable();
BUG_ON(ac_data(malloc_sizes[INDEX_AC].cs_cachep)
- != &initarray_generic.cache);
+ != &initarray_generic.cache);
memcpy(ptr, ac_data(malloc_sizes[INDEX_AC].cs_cachep),
- sizeof(struct arraycache_init));
+ sizeof(struct arraycache_init));
malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] =
- ptr;
+ ptr;
local_irq_enable();
}
/* 5) Replace the bootstrap kmem_list3's */
@@ -1139,16 +1154,16 @@ void __init kmem_cache_init(void)
int node;
/* Replace the static kmem_list3 structures for the boot cpu */
init_list(&cache_cache, &initkmem_list3[CACHE_CACHE],
- numa_node_id());
+ numa_node_id());
for_each_online_node(node) {
init_list(malloc_sizes[INDEX_AC].cs_cachep,
- &initkmem_list3[SIZE_AC+node], node);
+ &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);
+ &initkmem_list3[SIZE_L3 + node],
+ node);
}
}
}
@@ -1156,10 +1171,10 @@ void __init kmem_cache_init(void)
/* 6) resize the head arrays to their final sizes */
{
kmem_cache_t *cachep;
- down(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
list_for_each_entry(cachep, &cache_chain, next)
- enable_cpucache(cachep);
- up(&cache_chain_sem);
+ enable_cpucache(cachep);
+ mutex_unlock(&cache_chain_mutex);
}
/* Done! */
@@ -1184,7 +1199,7 @@ static int __init cpucache_init(void)
* pages to gfp.
*/
for_each_online_cpu(cpu)
- start_cpu_timer(cpu);
+ start_cpu_timer(cpu);
return 0;
}
@@ -1226,7 +1241,7 @@ static void *kmem_getpages(kmem_cache_t *cachep, gfp_t flags, int nodeid)
*/
static void kmem_freepages(kmem_cache_t *cachep, void *addr)
{
- unsigned long i = (1<<cachep->gfporder);
+ unsigned long i = (1 << cachep->gfporder);
struct page *page = virt_to_page(addr);
const unsigned long nr_freed = i;
@@ -1239,13 +1254,13 @@ static void kmem_freepages(kmem_cache_t *cachep, void *addr)
if (current->reclaim_state)
current->reclaim_state->reclaimed_slab += nr_freed;
free_pages((unsigned long)addr, cachep->gfporder);
- if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
- atomic_sub(1<<cachep->gfporder, &slab_reclaim_pages);
+ if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
+ atomic_sub(1 << cachep->gfporder, &slab_reclaim_pages);
}
static void kmem_rcu_free(struct rcu_head *head)
{
- struct slab_rcu *slab_rcu = (struct slab_rcu *) head;
+ struct slab_rcu *slab_rcu = (struct slab_rcu *)head;
kmem_cache_t *cachep = slab_rcu->cachep;
kmem_freepages(cachep, slab_rcu->addr);
@@ -1257,19 +1272,19 @@ static void kmem_rcu_free(struct rcu_head *head)
#ifdef CONFIG_DEBUG_PAGEALLOC
static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
- unsigned long caller)
+ unsigned long caller)
{
int size = obj_reallen(cachep);
- addr = (unsigned long *)&((char*)addr)[obj_dbghead(cachep)];
+ addr = (unsigned long *)&((char *)addr)[obj_dbghead(cachep)];
- if (size < 5*sizeof(unsigned long))
+ if (size < 5 * sizeof(unsigned long))
return;
- *addr++=0x12345678;
- *addr++=caller;
- *addr++=smp_processor_id();
- size -= 3*sizeof(unsigned long);
+ *addr++ = 0x12345678;
+ *addr++ = caller;
+ *addr++ = smp_processor_id();
+ size -= 3 * sizeof(unsigned long);
{
unsigned long *sptr = &caller;
unsigned long svalue;
@@ -1277,7 +1292,7 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
while (!kstack_end(sptr)) {
svalue = *sptr++;
if (kernel_text_address(svalue)) {
- *addr++=svalue;
+ *addr++ = svalue;
size -= sizeof(unsigned long);
if (size <= sizeof(unsigned long))
break;
@@ -1285,25 +1300,25 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr,
}
}
- *addr++=0x87654321;
+ *addr++ = 0x87654321;
}
#endif
static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
{
int size = obj_reallen(cachep);
- addr = &((char*)addr)[obj_dbghead(cachep)];
+ addr = &((char *)addr)[obj_dbghead(cachep)];
memset(addr, val, size);
- *(unsigned char *)(addr+size-1) = POISON_END;
+ *(unsigned char *)(addr + size - 1) = POISON_END;
}
static void dump_line(char *data, int offset, int limit)
{
int i;
printk(KERN_ERR "%03x:", offset);
- for (i=0;i<limit;i++) {
- printk(" %02x", (unsigned char)data[offset+i]);
+ for (i = 0; i < limit; i++) {
+ printk(" %02x", (unsigned char)data[offset + i]);
}
printk("\n");
}
@@ -1318,24 +1333,24 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
if (cachep->flags & SLAB_RED_ZONE) {
printk(KERN_ERR "Redzone: 0x%lx/0x%lx.\n",
- *dbg_redzone1(cachep, objp),
- *dbg_redzone2(cachep, objp));
+ *dbg_redzone1(cachep, objp),
+ *dbg_redzone2(cachep, objp));
}
if (cachep->flags & SLAB_STORE_USER) {
printk(KERN_ERR "Last user: [<%p>]",
- *dbg_userword(cachep, objp));
+ *dbg_userword(cachep, objp));
print_symbol("(%s)",
- (unsigned long)*dbg_userword(cachep, objp));
+ (unsigned long)*dbg_userword(cachep, objp));
printk("\n");
}
- realobj = (char*)objp+obj_dbghead(cachep);
+ realobj = (char *)objp + obj_dbghead(cachep);
size = obj_reallen(cachep);
- for (i=0; i<size && lines;i+=16, lines--) {
+ for (i = 0; i < size && lines; i += 16, lines--) {
int limit;
limit = 16;
- if (i+limit > size)
- limit = size-i;
+ if (i + limit > size)
+ limit = size - i;
dump_line(realobj, i, limit);
}
}
@@ -1346,27 +1361,28 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
int size, i;
int lines = 0;
- realobj = (char*)objp+obj_dbghead(cachep);
+ realobj = (char *)objp + obj_dbghead(cachep);
size = obj_reallen(cachep);
- for (i=0;i<size;i++) {
+ for (i = 0; i < size; i++) {
char exp = POISON_FREE;
- if (i == size-1)
+ if (i == size - 1)
exp = POISON_END;
if (realobj[i] != exp) {
int limit;
/* Mismatch ! */
/* Print header */
if (lines == 0) {
- printk(KERN_ERR "Slab corruption: start=%p, len=%d\n",
- realobj, size);
+ printk(KERN_ERR
+ "Slab corruption: start=%p, len=%d\n",
+ realobj, size);
print_objinfo(cachep, objp, 0);
}
/* Hexdump the affected line */
- i = (i/16)*16;
+ i = (i / 16) * 16;
limit = 16;
- if (i+limit > size)
- limit = size-i;
+ if (i + limit > size)
+ limit = size - i;
dump_line(realobj, i, limit);
i += 16;
lines++;
@@ -1382,19 +1398,19 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
struct slab *slabp = page_get_slab(virt_to_page(objp));
int objnr;
- objnr = (objp-slabp->s_mem)/cachep->objsize;
+ objnr = (objp - slabp->s_mem) / cachep->objsize;
if (objnr) {
- objp = slabp->s_mem+(objnr-1)*cachep->objsize;
- realobj = (char*)objp+obj_dbghead(cachep);
+ objp = slabp->s_mem + (objnr - 1) * cachep->objsize;
+ realobj = (char *)objp + obj_dbghead(cachep);
printk(KERN_ERR "Prev obj: start=%p, len=%d\n",
- realobj, size);
+ realobj, size);
print_objinfo(cachep, objp, 2);
}
- if (objnr+1 < cachep->num) {
- objp = slabp->s_mem+(objnr+1)*cachep->objsize;
- realobj = (char*)objp+obj_dbghead(cachep);
+ if (objnr + 1 < cachep->num) {
+ objp = slabp->s_mem + (objnr + 1) * cachep->objsize;
+ realobj = (char *)objp + obj_dbghead(cachep);
printk(KERN_ERR "Next obj: start=%p, len=%d\n",
- realobj, size);
+ realobj, size);
print_objinfo(cachep, objp, 2);
}
}
@@ -1405,7 +1421,7 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
* Before calling the slab must have been unlinked from the cache.
* The cache-lock is not held/needed.
*/
-static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
+static void slab_destroy(kmem_cache_t *cachep, struct slab *slabp)
{
void *addr = slabp->s_mem - slabp->colouroff;
@@ -1416,8 +1432,11 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
if (cachep->flags & SLAB_POISON) {
#ifdef CONFIG_DEBUG_PAGEALLOC
- if ((cachep->objsize%PAGE_SIZE)==0 && OFF_SLAB(cachep))
- kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE,1);
+ if ((cachep->objsize % PAGE_SIZE) == 0
+ && OFF_SLAB(cachep))
+ kernel_map_pages(virt_to_page(objp),
+ cachep->objsize / PAGE_SIZE,
+ 1);
else
check_poison_obj(cachep, objp);
#else
@@ -1427,20 +1446,20 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
if (cachep->flags & SLAB_RED_ZONE) {
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "start of a freed object "
- "was overwritten");
+ "was overwritten");
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "end of a freed object "
- "was overwritten");
+ "was overwritten");
}
if (cachep->dtor && !(cachep->flags & SLAB_POISON))
- (cachep->dtor)(objp+obj_dbghead(cachep), cachep, 0);
+ (cachep->dtor) (objp + obj_dbghead(cachep), cachep, 0);
}
#else
if (cachep->dtor) {
int i;
for (i = 0; i < cachep->num; i++) {
- void* objp = slabp->s_mem+cachep->objsize*i;
- (cachep->dtor)(objp, cachep, 0);
+ void *objp = slabp->s_mem + cachep->objsize * i;
+ (cachep->dtor) (objp, cachep, 0);
}
}
#endif
@@ -1448,7 +1467,7 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
struct slab_rcu *slab_rcu;
- slab_rcu = (struct slab_rcu *) slabp;
+ slab_rcu = (struct slab_rcu *)slabp;
slab_rcu->cachep = cachep;
slab_rcu->addr = addr;
call_rcu(&slab_rcu->head, kmem_rcu_free);
@@ -1466,11 +1485,58 @@ 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] = &initkmem_list3[index + node];
cachep->nodelists[node]->next_reap = jiffies +
- REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+ REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
+ }
+}
+
+/**
+ * calculate_slab_order - calculate size (page order) of slabs and the number
+ * of objects per slab.
+ *
+ * This could be made much more intelligent. For now, try to avoid using
+ * high order pages for slabs. When the gfp() functions are more friendly
+ * towards high-order requests, this should be changed.
+ */
+static inline size_t calculate_slab_order(kmem_cache_t *cachep, size_t size,
+ size_t align, gfp_t flags)
+{
+ size_t left_over = 0;
+
+ for (;; cachep->gfporder++) {
+ unsigned int num;
+ size_t remainder;
+
+ if (cachep->gfporder > MAX_GFP_ORDER) {
+ cachep->num = 0;
+ break;
+ }
+
+ cache_estimate(cachep->gfporder, size, align, flags,
+ &remainder, &num);
+ if (!num)
+ continue;
+ /* More than offslab_limit objects will cause problems */
+ if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit)
+ break;
+
+ cachep->num = num;
+ left_over = remainder;
+
+ /*
+ * Large number of objects is good, but very large slabs are
+ * currently bad for the gfp()s.
+ */
+ if (cachep->gfporder >= slab_break_gfp_order)
+ break;
+
+ if ((left_over * 8) <= (PAGE_SIZE << cachep->gfporder))
+ /* Acceptable internal fragmentation */
+ break;
}
+ return left_over;
}
/**
@@ -1519,16 +1585,15 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* Sanity checks... these are all serious usage bugs.
*/
if ((!name) ||
- in_interrupt() ||
- (size < BYTES_PER_WORD) ||
- (size > (1<<MAX_OBJ_ORDER)*PAGE_SIZE) ||
- (dtor && !ctor)) {
- printk(KERN_ERR "%s: Early error in slab %s\n",
- __FUNCTION__, name);
- BUG();
- }
+ in_interrupt() ||
+ (size < BYTES_PER_WORD) ||
+ (size > (1 << MAX_OBJ_ORDER) * PAGE_SIZE) || (dtor && !ctor)) {
+ printk(KERN_ERR "%s: Early error in slab %s\n",
+ __FUNCTION__, name);
+ BUG();
+ }
- down(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
list_for_each(p, &cache_chain) {
kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
@@ -1546,11 +1611,11 @@ kmem_cache_create (const char *name, size_t size, size_t align,
set_fs(old_fs);
if (res) {
printk("SLAB: cache with size %d has lost its name\n",
- pc->objsize);
+ pc->objsize);
continue;
}
- if (!strcmp(pc->name,name)) {
+ if (!strcmp(pc->name, name)) {
printk("kmem_cache_create: duplicate cache %s\n", name);
dump_stack();
goto oops;
@@ -1562,10 +1627,9 @@ kmem_cache_create (const char *name, size_t size, size_t align,
if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
/* No constructor, but inital state check requested */
printk(KERN_ERR "%s: No con, but init state check "
- "requested - %s\n", __FUNCTION__, name);
+ "requested - %s\n", __FUNCTION__, name);
flags &= ~SLAB_DEBUG_INITIAL;
}
-
#if FORCED_DEBUG
/*
* Enable redzoning and last user accounting, except for caches with
@@ -1573,8 +1637,9 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* above the next power of two: caches with object sizes just above a
* power of two have a significant amount of internal fragmentation.
*/
- if ((size < 4096 || fls(size-1) == fls(size-1+3*BYTES_PER_WORD)))
- flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
+ if ((size < 4096
+ || fls(size - 1) == fls(size - 1 + 3 * BYTES_PER_WORD)))
+ flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
if (!(flags & SLAB_DESTROY_BY_RCU))
flags |= SLAB_POISON;
#endif
@@ -1595,9 +1660,9 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* unaligned accesses for some archs when redzoning is used, and makes
* sure any on-slab bufctl's are also correctly aligned.
*/
- if (size & (BYTES_PER_WORD-1)) {
- size += (BYTES_PER_WORD-1);
- size &= ~(BYTES_PER_WORD-1);
+ if (size & (BYTES_PER_WORD - 1)) {
+ size += (BYTES_PER_WORD - 1);
+ size &= ~(BYTES_PER_WORD - 1);
}
/* calculate out the final buffer alignment: */
@@ -1608,7 +1673,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* objects into one cacheline.
*/
ralign = cache_line_size();
- while (size <= ralign/2)
+ while (size <= ralign / 2)
ralign /= 2;
} else {
ralign = BYTES_PER_WORD;
@@ -1617,13 +1682,13 @@ kmem_cache_create (const char *name, size_t size, size_t align,
if (ralign < ARCH_SLAB_MINALIGN) {
ralign = ARCH_SLAB_MINALIGN;
if (ralign > BYTES_PER_WORD)
- flags &= ~(SLAB_RED_ZONE|SLAB_STORE_USER);
+ flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
}
/* 3) caller mandated alignment: disables debug if necessary */
if (ralign < align) {
ralign = align;
if (ralign > BYTES_PER_WORD)
- flags &= ~(SLAB_RED_ZONE|SLAB_STORE_USER);
+ flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
}
/* 4) Store it. Note that the debug code below can reduce
* the alignment to BYTES_PER_WORD.
@@ -1645,7 +1710,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
/* add space for red zone words */
cachep->dbghead += BYTES_PER_WORD;
- size += 2*BYTES_PER_WORD;
+ size += 2 * BYTES_PER_WORD;
}
if (flags & SLAB_STORE_USER) {
/* user store requires word alignment and
@@ -1656,7 +1721,8 @@ 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 >= malloc_sizes[INDEX_L3+1].cs_size && 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;
}
@@ -1664,7 +1730,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
#endif
/* Determine if the slab management is 'on' or 'off' slab. */
- if (size >= (PAGE_SIZE>>3))
+ if (size >= (PAGE_SIZE >> 3))
/*
* Size is large, assume best to place the slab management obj
* off-slab (should allow better packing of objs).
@@ -1681,47 +1747,9 @@ kmem_cache_create (const char *name, size_t size, size_t align,
*/
cachep->gfporder = 0;
cache_estimate(cachep->gfporder, size, align, flags,
- &left_over, &cachep->num);
- } else {
- /*
- * Calculate size (in pages) of slabs, and the num of objs per
- * slab. This could be made much more intelligent. For now,
- * try to avoid using high page-orders for slabs. When the
- * gfp() funcs are more friendly towards high-order requests,
- * this should be changed.
- */
- do {
- unsigned int break_flag = 0;
-cal_wastage:
- cache_estimate(cachep->gfporder, size, align, flags,
- &left_over, &cachep->num);
- if (break_flag)
- break;
- if (cachep->gfporder >= MAX_GFP_ORDER)
- break;
- if (!cachep->num)
- goto next;
- if (flags & CFLGS_OFF_SLAB &&
- cachep->num > offslab_limit) {
- /* This num of objs will cause problems. */
- cachep->gfporder--;
- break_flag++;
- goto cal_wastage;
- }
-
- /*
- * Large num of objs is good, but v. large slabs are
- * currently bad for the gfp()s.
- */
- if (cachep->gfporder >= slab_break_gfp_order)
- break;
-
- if ((left_over*8) <= (PAGE_SIZE<<cachep->gfporder))
- break; /* Acceptable internal fragmentation. */
-next:
- cachep->gfporder++;
- } while (1);
- }
+ &left_over, &cachep->num);
+ } else
+ left_over = calculate_slab_order(cachep, size, align, flags);
if (!cachep->num) {
printk("kmem_cache_create: couldn't create cache %s.\n", name);
@@ -1729,8 +1757,8 @@ next:
cachep = NULL;
goto oops;
}
- slab_size = ALIGN(cachep->num*sizeof(kmem_bufctl_t)
- + sizeof(struct slab), align);
+ slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
+ + sizeof(struct slab), align);
/*
* If the slab has been placed off-slab, and we have enough space then
@@ -1743,14 +1771,15 @@ next:
if (flags & CFLGS_OFF_SLAB) {
/* really off slab. No need for manual alignment */
- slab_size = cachep->num*sizeof(kmem_bufctl_t)+sizeof(struct slab);
+ slab_size =
+ cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
}
cachep->colour_off = cache_line_size();
/* Offset must be a multiple of the alignment. */
if (cachep->colour_off < align)
cachep->colour_off = align;
- cachep->colour = left_over/cachep->colour_off;
+ cachep->colour = left_over / cachep->colour_off;
cachep->slab_size = slab_size;
cachep->flags = flags;
cachep->gfpflags = 0;
@@ -1777,7 +1806,7 @@ next:
* the creation of further caches will BUG().
*/
cachep->array[smp_processor_id()] =
- &initarray_generic.cache;
+ &initarray_generic.cache;
/* If the cache that's used by
* kmalloc(sizeof(kmem_list3)) is the first cache,
@@ -1791,8 +1820,7 @@ next:
g_cpucache_up = PARTIAL_AC;
} else {
cachep->array[smp_processor_id()] =
- kmalloc(sizeof(struct arraycache_init),
- GFP_KERNEL);
+ kmalloc(sizeof(struct arraycache_init), GFP_KERNEL);
if (g_cpucache_up == PARTIAL_AC) {
set_up_list3s(cachep, SIZE_L3);
@@ -1802,16 +1830,18 @@ next:
for_each_online_node(node) {
cachep->nodelists[node] =
- kmalloc_node(sizeof(struct kmem_list3),
- GFP_KERNEL, node);
+ kmalloc_node(sizeof
+ (struct kmem_list3),
+ GFP_KERNEL, node);
BUG_ON(!cachep->nodelists[node]);
- kmem_list3_init(cachep->nodelists[node]);
+ kmem_list3_init(cachep->
+ nodelists[node]);
}
}
}
cachep->nodelists[numa_node_id()]->next_reap =
- jiffies + REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep)%REAPTIMEOUT_LIST3;
+ jiffies + REAPTIMEOUT_LIST3 +
+ ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
BUG_ON(!ac_data(cachep));
ac_data(cachep)->avail = 0;
@@ -1820,16 +1850,16 @@ next:
ac_data(cachep)->touched = 0;
cachep->batchcount = 1;
cachep->limit = BOOT_CPUCACHE_ENTRIES;
- }
+ }
/* cache setup completed, link it into the list */
list_add(&cachep->next, &cache_chain);
unlock_cpu_hotplug();
-oops:
+ oops:
if (!cachep && (flags & SLAB_PANIC))
panic("kmem_cache_create(): failed to create slab `%s'\n",
- name);
- up(&cache_chain_sem);
+ name);
+ mutex_unlock(&cache_chain_mutex);
return cachep;
}
EXPORT_SYMBOL(kmem_cache_create);
@@ -1871,7 +1901,7 @@ static inline void check_spinlock_acquired_node(kmem_cache_t *cachep, int node)
/*
* Waits for all CPUs to execute func().
*/
-static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
+static void smp_call_function_all_cpus(void (*func)(void *arg), void *arg)
{
check_irq_on();
preempt_disable();
@@ -1886,12 +1916,12 @@ static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
preempt_enable();
}
-static void drain_array_locked(kmem_cache_t* cachep,
- struct array_cache *ac, int force, int node);
+static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+ int force, int node);
static void do_drain(void *arg)
{
- kmem_cache_t *cachep = (kmem_cache_t*)arg;
+ kmem_cache_t *cachep = (kmem_cache_t *) arg;
struct array_cache *ac;
int node = numa_node_id();
@@ -1911,7 +1941,7 @@ static void drain_cpu_caches(kmem_cache_t *cachep)
smp_call_function_all_cpus(do_drain, cachep);
check_irq_on();
spin_lock_irq(&cachep->spinlock);
- for_each_online_node(node) {
+ for_each_online_node(node) {
l3 = cachep->nodelists[node];
if (l3) {
spin_lock(&l3->list_lock);
@@ -1949,8 +1979,7 @@ static int __node_shrink(kmem_cache_t *cachep, int node)
slab_destroy(cachep, slabp);
spin_lock_irq(&l3->list_lock);
}
- ret = !list_empty(&l3->slabs_full) ||
- !list_empty(&l3->slabs_partial);
+ ret = !list_empty(&l3->slabs_full) || !list_empty(&l3->slabs_partial);
return ret;
}
@@ -2006,7 +2035,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
* The caller must guarantee that noone will allocate memory from the cache
* during the kmem_cache_destroy().
*/
-int kmem_cache_destroy(kmem_cache_t * cachep)
+int kmem_cache_destroy(kmem_cache_t *cachep)
{
int i;
struct kmem_list3 *l3;
@@ -2018,18 +2047,18 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
lock_cpu_hotplug();
/* Find the cache in the chain of caches. */
- down(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
/*
* the chain is never empty, cache_cache is never destroyed
*/
list_del(&cachep->next);
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
if (__cache_shrink(cachep)) {
slab_error(cachep, "Can't free all objects");
- down(&cache_chain_sem);
- list_add(&cachep->next,&cache_chain);
- up(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
+ list_add(&cachep->next, &cache_chain);
+ mutex_unlock(&cache_chain_mutex);
unlock_cpu_hotplug();
return 1;
}
@@ -2038,7 +2067,7 @@ int kmem_cache_destroy(kmem_cache_t * cachep)
synchronize_rcu();
for_each_online_cpu(i)
- kfree(cachep->array[i]);
+ kfree(cachep->array[i]);
/* NUMA: free the list3 structures */
for_each_online_node(i) {
@@ -2057,39 +2086,39 @@ 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, gfp_t local_flags)
+static struct slab *alloc_slabmgmt(kmem_cache_t *cachep, void *objp,
+ int colour_off, gfp_t local_flags)
{
struct slab *slabp;
-
+
if (OFF_SLAB(cachep)) {
/* Slab management obj is off-slab. */
slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);
if (!slabp)
return NULL;
} else {
- slabp = objp+colour_off;
+ slabp = objp + colour_off;
colour_off += cachep->slab_size;
}
slabp->inuse = 0;
slabp->colouroff = colour_off;
- slabp->s_mem = objp+colour_off;
+ slabp->s_mem = objp + colour_off;
return slabp;
}
static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)
{
- return (kmem_bufctl_t *)(slabp+1);
+ return (kmem_bufctl_t *) (slabp + 1);
}
static void cache_init_objs(kmem_cache_t *cachep,
- struct slab *slabp, unsigned long ctor_flags)
+ struct slab *slabp, unsigned long ctor_flags)
{
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)
@@ -2107,25 +2136,28 @@ static void cache_init_objs(kmem_cache_t *cachep,
* Otherwise, deadlock. They must also be threaded.
*/
if (cachep->ctor && !(cachep->flags & SLAB_POISON))
- cachep->ctor(objp+obj_dbghead(cachep), cachep, ctor_flags);
+ cachep->ctor(objp + obj_dbghead(cachep), cachep,
+ ctor_flags);
if (cachep->flags & SLAB_RED_ZONE) {
if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
- " end of an object");
+ " end of an object");
if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
slab_error(cachep, "constructor overwrote the"
- " start of an object");
+ " start of an object");
}
- if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
- kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
+ if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)
+ && cachep->flags & SLAB_POISON)
+ kernel_map_pages(virt_to_page(objp),
+ cachep->objsize / PAGE_SIZE, 0);
#else
if (cachep->ctor)
cachep->ctor(objp, cachep, ctor_flags);
#endif
- slab_bufctl(slabp)[i] = i+1;
+ slab_bufctl(slabp)[i] = i + 1;
}
- slab_bufctl(slabp)[i-1] = BUFCTL_END;
+ slab_bufctl(slabp)[i - 1] = BUFCTL_END;
slabp->free = 0;
}
@@ -2161,17 +2193,17 @@ static void set_slab_attr(kmem_cache_t *cachep, struct slab *slabp, void *objp)
*/
static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid)
{
- struct slab *slabp;
- void *objp;
- size_t offset;
- gfp_t local_flags;
- unsigned long ctor_flags;
+ struct slab *slabp;
+ void *objp;
+ size_t offset;
+ gfp_t 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().
+ * keeping it out of the critical path in kmem_cache_alloc().
*/
- if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW))
+ if (flags & ~(SLAB_DMA | SLAB_LEVEL_MASK | SLAB_NO_GROW))
BUG();
if (flags & SLAB_NO_GROW)
return 0;
@@ -2237,9 +2269,9 @@ static int cache_grow(kmem_cache_t *cachep, gfp_t flags, int nodeid)
l3->free_objects += cachep->num;
spin_unlock(&l3->list_lock);
return 1;
-opps1:
+ opps1:
kmem_freepages(cachep, objp);
-failed:
+ failed:
if (local_flags & __GFP_WAIT)
local_irq_disable();
return 0;
@@ -2259,18 +2291,19 @@ static void kfree_debugcheck(const void *objp)
if (!virt_addr_valid(objp)) {
printk(KERN_ERR "kfree_debugcheck: out of range ptr %lxh.\n",
- (unsigned long)objp);
- BUG();
+ (unsigned long)objp);
+ BUG();
}
page = virt_to_page(objp);
if (!PageSlab(page)) {
- printk(KERN_ERR "kfree_debugcheck: bad ptr %lxh.\n", (unsigned long)objp);
+ printk(KERN_ERR "kfree_debugcheck: bad ptr %lxh.\n",
+ (unsigned long)objp);
BUG();
}
}
static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
- void *caller)
+ void *caller)
{
struct page *page;
unsigned int objnr;
@@ -2281,20 +2314,26 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
page = virt_to_page(objp);
if (page_get_cache(page) != cachep) {
- printk(KERN_ERR "mismatch in kmem_cache_free: expected cache %p, got %p\n",
- page_get_cache(page),cachep);
+ printk(KERN_ERR
+ "mismatch in kmem_cache_free: expected cache %p, got %p\n",
+ page_get_cache(page), cachep);
printk(KERN_ERR "%p is %s.\n", cachep, cachep->name);
- printk(KERN_ERR "%p is %s.\n", page_get_cache(page), page_get_cache(page)->name);
+ printk(KERN_ERR "%p is %s.\n", page_get_cache(page),
+ page_get_cache(page)->name);
WARN_ON(1);
}
slabp = page_get_slab(page);
if (cachep->flags & SLAB_RED_ZONE) {
- if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) {
- slab_error(cachep, "double free, or memory outside"
- " object was overwritten");
- printk(KERN_ERR "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n",
- objp, *dbg_redzone1(cachep, objp), *dbg_redzone2(cachep, objp));
+ if (*dbg_redzone1(cachep, objp) != RED_ACTIVE
+ || *dbg_redzone2(cachep, objp) != RED_ACTIVE) {
+ slab_error(cachep,
+ "double free, or memory outside"
+ " object was overwritten");
+ printk(KERN_ERR
+ "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n",
+ objp, *dbg_redzone1(cachep, objp),
+ *dbg_redzone2(cachep, objp));
}
*dbg_redzone1(cachep, objp) = RED_INACTIVE;
*dbg_redzone2(cachep, objp) = RED_INACTIVE;
@@ -2302,30 +2341,31 @@ static void *cache_free_debugcheck(kmem_cache_t *cachep, void *objp,
if (cachep->flags & SLAB_STORE_USER)
*dbg_userword(cachep, objp) = caller;
- objnr = (objp-slabp->s_mem)/cachep->objsize;
+ objnr = (objp - slabp->s_mem) / cachep->objsize;
BUG_ON(objnr >= cachep->num);
- BUG_ON(objp != slabp->s_mem + objnr*cachep->objsize);
+ BUG_ON(objp != slabp->s_mem + objnr * cachep->objsize);
if (cachep->flags & SLAB_DEBUG_INITIAL) {
/* Need to call the slab's constructor so the
* caller can perform a verify of its state (debugging).
* Called without the cache-lock held.
*/
- cachep->ctor(objp+obj_dbghead(cachep),
- cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
+ cachep->ctor(objp + obj_dbghead(cachep),
+ cachep, SLAB_CTOR_CONSTRUCTOR | SLAB_CTOR_VERIFY);
}
if (cachep->flags & SLAB_POISON && cachep->dtor) {
/* we want to cache poison the object,
* call the destruction callback
*/
- cachep->dtor(objp+obj_dbghead(cachep), cachep, 0);
+ cachep->dtor(objp + obj_dbghead(cachep), cachep, 0);
}
if (cachep->flags & SLAB_POISON) {
#ifdef CONFIG_DEBUG_PAGEALLOC
if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
store_stackinfo(cachep, objp, (unsigned long)caller);
- kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
+ kernel_map_pages(virt_to_page(objp),
+ cachep->objsize / PAGE_SIZE, 0);
} else {
poison_obj(cachep, objp, POISON_FREE);
}
@@ -2340,7 +2380,7 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
{
kmem_bufctl_t i;
int entries = 0;
-
+
/* Check slab's freelist to see if this obj is there. */
for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
entries++;
@@ -2348,13 +2388,16 @@ static void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
goto bad;
}
if (entries != cachep->num - slabp->inuse) {
-bad:
- printk(KERN_ERR "slab: Internal list corruption detected in cache '%s'(%d), slabp %p(%d). Hexdump:\n",
- cachep->name, cachep->num, slabp, slabp->inuse);
- for (i=0;i<sizeof(slabp)+cachep->num*sizeof(kmem_bufctl_t);i++) {
- if ((i%16)==0)
+ bad:
+ printk(KERN_ERR
+ "slab: Internal list corruption detected in cache '%s'(%d), slabp %p(%d). Hexdump:\n",
+ cachep->name, cachep->num, slabp, slabp->inuse);
+ for (i = 0;
+ i < sizeof(slabp) + cachep->num * sizeof(kmem_bufctl_t);
+ i++) {
+ if ((i % 16) == 0)
printk("\n%03x:", i);
- printk(" %02x", ((unsigned char*)slabp)[i]);
+ printk(" %02x", ((unsigned char *)slabp)[i]);
}
printk("\n");
BUG();
@@ -2374,7 +2417,7 @@ static void *cache_alloc_refill(kmem_cache_t *cachep, gfp_t flags)
check_irq_off();
ac = ac_data(cachep);
-retry:
+ retry:
batchcount = ac->batchcount;
if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
/* if there was little recent activity on this
@@ -2396,8 +2439,8 @@ retry:
shared_array->avail -= batchcount;
ac->avail = batchcount;
memcpy(ac->entry,
- &(shared_array->entry[shared_array->avail]),
- sizeof(void*)*batchcount);
+ &(shared_array->entry[shared_array->avail]),
+ sizeof(void *) * batchcount);
shared_array->touched = 1;
goto alloc_done;
}
@@ -2425,7 +2468,7 @@ retry:
/* get obj pointer */
ac->entry[ac->avail++] = slabp->s_mem +
- slabp->free*cachep->objsize;
+ slabp->free * cachep->objsize;
slabp->inuse++;
next = slab_bufctl(slabp)[slabp->free];
@@ -2433,7 +2476,7 @@ retry:
slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;
WARN_ON(numa_node_id() != slabp->nodeid);
#endif
- slabp->free = next;
+ slabp->free = next;
}
check_slabp(cachep, slabp);
@@ -2445,9 +2488,9 @@ retry:
list_add(&slabp->list, &l3->slabs_partial);
}
-must_grow:
+ must_grow:
l3->free_objects -= ac->avail;
-alloc_done:
+ alloc_done:
spin_unlock(&l3->list_lock);
if (unlikely(!ac->avail)) {
@@ -2459,7 +2502,7 @@ alloc_done:
if (!x && ac->avail == 0) // no objects in sight? abort
return NULL;
- if (!ac->avail) // objects refilled by interrupt?
+ if (!ac->avail) // objects refilled by interrupt?
goto retry;
}
ac->touched = 1;
@@ -2476,16 +2519,16 @@ cache_alloc_debugcheck_before(kmem_cache_t *cachep, gfp_t flags)
}
#if DEBUG
-static void *
-cache_alloc_debugcheck_after(kmem_cache_t *cachep,
- gfp_t flags, void *objp, void *caller)
+static void *cache_alloc_debugcheck_after(kmem_cache_t *cachep, gfp_t flags,
+ void *objp, void *caller)
{
- if (!objp)
+ if (!objp)
return objp;
- if (cachep->flags & SLAB_POISON) {
+ if (cachep->flags & SLAB_POISON) {
#ifdef CONFIG_DEBUG_PAGEALLOC
if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
- kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 1);
+ kernel_map_pages(virt_to_page(objp),
+ cachep->objsize / PAGE_SIZE, 1);
else
check_poison_obj(cachep, objp);
#else
@@ -2497,24 +2540,28 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
*dbg_userword(cachep, objp) = caller;
if (cachep->flags & SLAB_RED_ZONE) {
- if (*dbg_redzone1(cachep, objp) != RED_INACTIVE || *dbg_redzone2(cachep, objp) != RED_INACTIVE) {
- slab_error(cachep, "double free, or memory outside"
- " object was overwritten");
- printk(KERN_ERR "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n",
- objp, *dbg_redzone1(cachep, objp), *dbg_redzone2(cachep, objp));
+ if (*dbg_redzone1(cachep, objp) != RED_INACTIVE
+ || *dbg_redzone2(cachep, objp) != RED_INACTIVE) {
+ slab_error(cachep,
+ "double free, or memory outside"
+ " object was overwritten");
+ printk(KERN_ERR
+ "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n",
+ objp, *dbg_redzone1(cachep, objp),
+ *dbg_redzone2(cachep, objp));
}
*dbg_redzone1(cachep, objp) = RED_ACTIVE;
*dbg_redzone2(cachep, objp) = RED_ACTIVE;
}
objp += obj_dbghead(cachep);
if (cachep->ctor && cachep->flags & SLAB_POISON) {
- unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
+ unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR;
if (!(flags & __GFP_WAIT))
ctor_flags |= SLAB_CTOR_ATOMIC;
cachep->ctor(objp, cachep, ctor_flags);
- }
+ }
return objp;
}
#else
@@ -2523,9 +2570,18 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
{
- void* objp;
+ void *objp;
struct array_cache *ac;
+#ifdef CONFIG_NUMA
+ if (unlikely(current->mempolicy && !in_interrupt())) {
+ int nid = slab_node(current->mempolicy);
+
+ if (nid != numa_node_id())
+ return __cache_alloc_node(cachep, flags, nid);
+ }
+#endif
+
check_irq_off();
ac = ac_data(cachep);
if (likely(ac->avail)) {
@@ -2542,7 +2598,7 @@ static inline void *____cache_alloc(kmem_cache_t *cachep, gfp_t flags)
static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
{
unsigned long save_flags;
- void* objp;
+ void *objp;
cache_alloc_debugcheck_before(cachep, flags);
@@ -2550,7 +2606,7 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
objp = ____cache_alloc(cachep, flags);
local_irq_restore(save_flags);
objp = cache_alloc_debugcheck_after(cachep, flags, objp,
- __builtin_return_address(0));
+ __builtin_return_address(0));
prefetchw(objp);
return objp;
}
@@ -2562,74 +2618,75 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, gfp_t flags)
static void *__cache_alloc_node(kmem_cache_t *cachep, gfp_t 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];
+ 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;
+ 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);
- }
+ 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;
+ spin_unlock(&l3->list_lock);
+ goto done;
-must_grow:
- spin_unlock(&l3->list_lock);
- x = cache_grow(cachep, flags, nodeid);
+ must_grow:
+ spin_unlock(&l3->list_lock);
+ x = cache_grow(cachep, flags, nodeid);
- if (!x)
- return NULL;
+ if (!x)
+ return NULL;
- goto retry;
-done:
- return obj;
+ 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 node)
+static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects,
+ int node)
{
int i;
struct kmem_list3 *l3;
@@ -2652,7 +2709,7 @@ static void free_block(kmem_cache_t *cachep, void **objpp, int nr_objects, int n
if (slab_bufctl(slabp)[objnr] != BUFCTL_FREE) {
printk(KERN_ERR "slab: double free detected in cache "
- "'%s', objp %p\n", cachep->name, objp);
+ "'%s', objp %p\n", cachep->name, objp);
BUG();
}
#endif
@@ -2696,20 +2753,19 @@ static void cache_flusharray(kmem_cache_t *cachep, struct array_cache *ac)
spin_lock(&l3->list_lock);
if (l3->shared) {
struct array_cache *shared_array = l3->shared;
- int max = shared_array->limit-shared_array->avail;
+ int max = shared_array->limit - shared_array->avail;
if (max) {
if (batchcount > max)
batchcount = max;
memcpy(&(shared_array->entry[shared_array->avail]),
- ac->entry,
- sizeof(void*)*batchcount);
+ ac->entry, sizeof(void *) * batchcount);
shared_array->avail += batchcount;
goto free_done;
}
}
free_block(cachep, ac->entry, batchcount, node);
-free_done:
+ free_done:
#if STATS
{
int i = 0;
@@ -2731,10 +2787,9 @@ free_done:
spin_unlock(&l3->list_lock);
ac->avail -= batchcount;
memmove(ac->entry, &(ac->entry[batchcount]),
- sizeof(void*)*ac->avail);
+ sizeof(void *) * ac->avail);
}
-
/*
* __cache_free
* Release an obj back to its cache. If the obj has a constructed
@@ -2759,7 +2814,8 @@ static inline void __cache_free(kmem_cache_t *cachep, void *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()];
+ struct kmem_list3 *l3 =
+ cachep->nodelists[numa_node_id()];
STATS_INC_NODEFREES(cachep);
if (l3->alien && l3->alien[nodeid]) {
@@ -2767,15 +2823,15 @@ static inline void __cache_free(kmem_cache_t *cachep, void *objp)
spin_lock(&alien->lock);
if (unlikely(alien->avail == alien->limit))
__drain_alien_cache(cachep,
- alien, nodeid);
+ alien, nodeid);
alien->entry[alien->avail++] = objp;
spin_unlock(&alien->lock);
} else {
spin_lock(&(cachep->nodelists[nodeid])->
- list_lock);
+ list_lock);
free_block(cachep, &objp, 1, nodeid);
spin_unlock(&(cachep->nodelists[nodeid])->
- list_lock);
+ list_lock);
}
return;
}
@@ -2822,9 +2878,9 @@ EXPORT_SYMBOL(kmem_cache_alloc);
*/
int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)
{
- unsigned long addr = (unsigned long) ptr;
+ unsigned long addr = (unsigned long)ptr;
unsigned long min_addr = PAGE_OFFSET;
- unsigned long align_mask = BYTES_PER_WORD-1;
+ unsigned long align_mask = BYTES_PER_WORD - 1;
unsigned long size = cachep->objsize;
struct page *page;
@@ -2844,7 +2900,7 @@ int fastcall kmem_ptr_validate(kmem_cache_t *cachep, void *ptr)
if (unlikely(page_get_cache(page) != cachep))
goto out;
return 1;
-out:
+ out:
return 0;
}
@@ -2871,8 +2927,10 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
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);
+ printk(KERN_WARNING
+ "slab: not allocating in inactive node %d for cache %s\n",
+ nodeid, cachep->name);
+ return __cache_alloc(cachep, flags);
}
cache_alloc_debugcheck_before(cachep, flags);
@@ -2882,7 +2940,9 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, gfp_t flags, int nodeid)
else
ptr = __cache_alloc_node(cachep, flags, nodeid);
local_irq_restore(save_flags);
- ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0));
+ ptr =
+ cache_alloc_debugcheck_after(cachep, flags, ptr,
+ __builtin_return_address(0));
return ptr;
}
@@ -2944,12 +3004,11 @@ EXPORT_SYMBOL(__kmalloc);
* Objects should be dereferenced using the per_cpu_ptr macro only.
*
* @size: how many bytes of memory are required.
- * @align: the alignment, which can't be greater than SMP_CACHE_BYTES.
*/
-void *__alloc_percpu(size_t size, size_t align)
+void *__alloc_percpu(size_t size)
{
int i;
- struct percpu_data *pdata = kmalloc(sizeof (*pdata), GFP_KERNEL);
+ struct percpu_data *pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return NULL;
@@ -2973,9 +3032,9 @@ void *__alloc_percpu(size_t size, size_t align)
}
/* Catch derefs w/o wrappers */
- return (void *) (~(unsigned long) pdata);
+ return (void *)(~(unsigned long)pdata);
-unwind_oom:
+ unwind_oom:
while (--i >= 0) {
if (!cpu_possible(i))
continue;
@@ -3006,20 +3065,6 @@ void kmem_cache_free(kmem_cache_t *cachep, void *objp)
EXPORT_SYMBOL(kmem_cache_free);
/**
- * kzalloc - allocate memory. The memory is set to zero.
- * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- */
-void *kzalloc(size_t size, gfp_t flags)
-{
- void *ret = kmalloc(size, flags);
- if (ret)
- memset(ret, 0, size);
- return ret;
-}
-EXPORT_SYMBOL(kzalloc);
-
-/**
* kfree - free previously allocated memory
* @objp: pointer returned by kmalloc.
*
@@ -3038,7 +3083,8 @@ void kfree(const void *objp)
local_irq_save(flags);
kfree_debugcheck(objp);
c = page_get_cache(virt_to_page(objp));
- __cache_free(c, (void*)objp);
+ mutex_debug_check_no_locks_freed(objp, obj_reallen(c));
+ __cache_free(c, (void *)objp);
local_irq_restore(flags);
}
EXPORT_SYMBOL(kfree);
@@ -3051,17 +3097,16 @@ EXPORT_SYMBOL(kfree);
* Don't free memory not originally allocated by alloc_percpu()
* The complemented objp is to check for that.
*/
-void
-free_percpu(const void *objp)
+void free_percpu(const void *objp)
{
int i;
- struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
+ struct percpu_data *p = (struct percpu_data *)(~(unsigned long)objp);
/*
* We allocate for all cpus so we cannot use for online cpu here.
*/
for_each_cpu(i)
- kfree(p->ptrs[i]);
+ kfree(p->ptrs[i]);
kfree(p);
}
EXPORT_SYMBOL(free_percpu);
@@ -3095,44 +3140,44 @@ static int alloc_kmemlist(kmem_cache_t *cachep)
if (!(new_alien = alloc_alien_cache(node, cachep->limit)))
goto fail;
#endif
- if (!(new = alloc_arraycache(node, (cachep->shared*
- cachep->batchcount), 0xbaadf00d)))
+ 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, node);
+ free_block(cachep, nc->entry, nc->avail, node);
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;
+ 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)))
+ GFP_KERNEL, node)))
goto fail;
kmem_list3_init(l3);
l3->next_reap = jiffies + REAPTIMEOUT_LIST3 +
- ((unsigned long)cachep)%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;
+ l3->free_limit = (1 + nr_cpus_node(node)) *
+ cachep->batchcount + cachep->num;
cachep->nodelists[node] = l3;
}
return err;
-fail:
+ fail:
err = -ENOMEM;
return err;
}
@@ -3154,18 +3199,19 @@ static void do_ccupdate_local(void *info)
new->new[smp_processor_id()] = old;
}
-
static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
- int shared)
+ int shared)
{
struct ccupdate_struct new;
int i, err;
- memset(&new.new,0,sizeof(new.new));
+ memset(&new.new, 0, sizeof(new.new));
for_each_online_cpu(i) {
- new.new[i] = alloc_arraycache(cpu_to_node(i), limit, batchcount);
+ new.new[i] =
+ alloc_arraycache(cpu_to_node(i), limit, batchcount);
if (!new.new[i]) {
- for (i--; i >= 0; i--) kfree(new.new[i]);
+ for (i--; i >= 0; i--)
+ kfree(new.new[i]);
return -ENOMEM;
}
}
@@ -3193,13 +3239,12 @@ static int do_tune_cpucache(kmem_cache_t *cachep, int limit, int batchcount,
err = alloc_kmemlist(cachep);
if (err) {
printk(KERN_ERR "alloc_kmemlist failed for %s, error %d.\n",
- cachep->name, -err);
+ cachep->name, -err);
BUG();
}
return 0;
}
-
static void enable_cpucache(kmem_cache_t *cachep)
{
int err;
@@ -3246,14 +3291,14 @@ static void enable_cpucache(kmem_cache_t *cachep)
if (limit > 32)
limit = 32;
#endif
- err = do_tune_cpucache(cachep, limit, (limit+1)/2, shared);
+ err = do_tune_cpucache(cachep, limit, (limit + 1) / 2, shared);
if (err)
printk(KERN_ERR "enable_cpucache failed for %s, error %d.\n",
- cachep->name, -err);
+ cachep->name, -err);
}
-static void drain_array_locked(kmem_cache_t *cachep,
- struct array_cache *ac, int force, int node)
+static void drain_array_locked(kmem_cache_t *cachep, struct array_cache *ac,
+ int force, int node)
{
int tofree;
@@ -3261,14 +3306,14 @@ static void drain_array_locked(kmem_cache_t *cachep,
if (ac->touched && !force) {
ac->touched = 0;
} else if (ac->avail) {
- tofree = force ? ac->avail : (ac->limit+4)/5;
+ tofree = force ? ac->avail : (ac->limit + 4) / 5;
if (tofree > ac->avail) {
- tofree = (ac->avail+1)/2;
+ tofree = (ac->avail + 1) / 2;
}
free_block(cachep, ac->entry, tofree, node);
ac->avail -= tofree;
memmove(ac->entry, &(ac->entry[tofree]),
- sizeof(void*)*ac->avail);
+ sizeof(void *) * ac->avail);
}
}
@@ -3281,7 +3326,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
* - clear the per-cpu caches for this CPU.
* - return freeable pages to the main free memory pool.
*
- * If we cannot acquire the cache chain semaphore then just give up - we'll
+ * If we cannot acquire the cache chain mutex then just give up - we'll
* try again on the next iteration.
*/
static void cache_reap(void *unused)
@@ -3289,15 +3334,16 @@ static void cache_reap(void *unused)
struct list_head *walk;
struct kmem_list3 *l3;
- if (down_trylock(&cache_chain_sem)) {
+ if (!mutex_trylock(&cache_chain_mutex)) {
/* Give up. Setup the next iteration. */
- schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
+ schedule_delayed_work(&__get_cpu_var(reap_work),
+ REAPTIMEOUT_CPUC);
return;
}
list_for_each(walk, &cache_chain) {
kmem_cache_t *searchp;
- struct list_head* p;
+ struct list_head *p;
int tofree;
struct slab *slabp;
@@ -3314,7 +3360,7 @@ static void cache_reap(void *unused)
spin_lock_irq(&l3->list_lock);
drain_array_locked(searchp, ac_data(searchp), 0,
- numa_node_id());
+ numa_node_id());
if (time_after(l3->next_reap, jiffies))
goto next_unlock;
@@ -3323,14 +3369,16 @@ static void cache_reap(void *unused)
if (l3->shared)
drain_array_locked(searchp, l3->shared, 0,
- numa_node_id());
+ numa_node_id());
if (l3->free_touched) {
l3->free_touched = 0;
goto next_unlock;
}
- tofree = (l3->free_limit+5*searchp->num-1)/(5*searchp->num);
+ tofree =
+ (l3->free_limit + 5 * searchp->num -
+ 1) / (5 * searchp->num);
do {
p = l3->slabs_free.next;
if (p == &(l3->slabs_free))
@@ -3350,14 +3398,14 @@ static void cache_reap(void *unused)
spin_unlock_irq(&l3->list_lock);
slab_destroy(searchp, slabp);
spin_lock_irq(&l3->list_lock);
- } while(--tofree > 0);
-next_unlock:
+ } while (--tofree > 0);
+ next_unlock:
spin_unlock_irq(&l3->list_lock);
-next:
+ next:
cond_resched();
}
check_irq_on();
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
drain_remote_pages();
/* Setup the next iteration */
schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
@@ -3365,32 +3413,37 @@ next:
#ifdef CONFIG_PROC_FS
-static void *s_start(struct seq_file *m, loff_t *pos)
+static void print_slabinfo_header(struct seq_file *m)
{
- loff_t n = *pos;
- struct list_head *p;
-
- down(&cache_chain_sem);
- if (!n) {
- /*
- * Output format version, so at least we can change it
- * without _too_ many complaints.
- */
+ /*
+ * Output format version, so at least we can change it
+ * without _too_ many complaints.
+ */
#if STATS
- seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
+ seq_puts(m, "slabinfo - version: 2.1 (statistics)\n");
#else
- seq_puts(m, "slabinfo - version: 2.1\n");
+ seq_puts(m, "slabinfo - version: 2.1\n");
#endif
- seq_puts(m, "# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab>");
- seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
- seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
+ seq_puts(m, "# name <active_objs> <num_objs> <objsize> "
+ "<objperslab> <pagesperslab>");
+ seq_puts(m, " : tunables <limit> <batchcount> <sharedfactor>");
+ seq_puts(m, " : slabdata <active_slabs> <num_slabs> <sharedavail>");
#if STATS
- seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped>"
- " <error> <maxfreeable> <nodeallocs> <remotefrees>");
- seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
+ seq_puts(m, " : globalstat <listallocs> <maxobjs> <grown> <reaped> "
+ "<error> <maxfreeable> <nodeallocs> <remotefrees>");
+ seq_puts(m, " : cpustat <allochit> <allocmiss> <freehit> <freemiss>");
#endif
- seq_putc(m, '\n');
- }
+ seq_putc(m, '\n');
+}
+
+static void *s_start(struct seq_file *m, loff_t *pos)
+{
+ loff_t n = *pos;
+ struct list_head *p;
+
+ mutex_lock(&cache_chain_mutex);
+ if (!n)
+ print_slabinfo_header(m);
p = cache_chain.next;
while (n--) {
p = p->next;
@@ -3405,23 +3458,23 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos)
kmem_cache_t *cachep = p;
++*pos;
return cachep->next.next == &cache_chain ? NULL
- : list_entry(cachep->next.next, kmem_cache_t, next);
+ : list_entry(cachep->next.next, kmem_cache_t, next);
}
static void s_stop(struct seq_file *m, void *p)
{
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
}
static int s_show(struct seq_file *m, void *p)
{
kmem_cache_t *cachep = p;
struct list_head *q;
- struct slab *slabp;
- unsigned long active_objs;
- unsigned long num_objs;
- unsigned long active_slabs = 0;
- unsigned long num_slabs, free_objects = 0, shared_avail = 0;
+ struct slab *slabp;
+ unsigned long active_objs;
+ unsigned long num_objs;
+ unsigned long active_slabs = 0;
+ unsigned long num_slabs, free_objects = 0, shared_avail = 0;
const char *name;
char *error = NULL;
int node;
@@ -3438,14 +3491,14 @@ static int s_show(struct seq_file *m, void *p)
spin_lock(&l3->list_lock);
- list_for_each(q,&l3->slabs_full) {
+ 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) {
+ 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";
@@ -3454,7 +3507,7 @@ static int s_show(struct seq_file *m, void *p)
active_objs += slabp->inuse;
active_slabs++;
}
- list_for_each(q,&l3->slabs_free) {
+ list_for_each(q, &l3->slabs_free) {
slabp = list_entry(q, struct slab, list);
if (slabp->inuse && !error)
error = "slabs_free/inuse accounting error";
@@ -3465,25 +3518,24 @@ static int s_show(struct seq_file *m, void *p)
spin_unlock(&l3->list_lock);
}
- num_slabs+=active_slabs;
- num_objs = num_slabs*cachep->num;
+ num_slabs += active_slabs;
+ num_objs = num_slabs * cachep->num;
if (num_objs - active_objs != free_objects && !error)
error = "free_objects accounting error";
- name = cachep->name;
+ name = cachep->name;
if (error)
printk(KERN_ERR "slab: cache %s error: %s\n", name, error);
seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d",
- name, active_objs, num_objs, cachep->objsize,
- cachep->num, (1<<cachep->gfporder));
+ name, active_objs, num_objs, cachep->objsize,
+ cachep->num, (1 << cachep->gfporder));
seq_printf(m, " : tunables %4u %4u %4u",
- cachep->limit, cachep->batchcount,
- cachep->shared);
+ cachep->limit, cachep->batchcount, cachep->shared);
seq_printf(m, " : slabdata %6lu %6lu %6lu",
- active_slabs, num_slabs, shared_avail);
+ active_slabs, num_slabs, shared_avail);
#if STATS
- { /* list3 stats */
+ { /* list3 stats */
unsigned long high = cachep->high_mark;
unsigned long allocs = cachep->num_allocations;
unsigned long grown = cachep->grown;
@@ -3494,9 +3546,7 @@ static int s_show(struct seq_file *m, void *p)
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, node_allocs, node_frees);
+ %4lu %4lu %4lu %4lu", allocs, high, grown, reaped, errors, max_freeable, node_allocs, node_frees);
}
/* cpu stats */
{
@@ -3506,7 +3556,7 @@ static int s_show(struct seq_file *m, void *p)
unsigned long freemiss = atomic_read(&cachep->freemiss);
seq_printf(m, " : cpustat %6lu %6lu %6lu %6lu",
- allochit, allocmiss, freehit, freemiss);
+ allochit, allocmiss, freehit, freemiss);
}
#endif
seq_putc(m, '\n');
@@ -3529,10 +3579,10 @@ static int s_show(struct seq_file *m, void *p)
*/
struct seq_operations slabinfo_op = {
- .start = s_start,
- .next = s_next,
- .stop = s_stop,
- .show = s_show,
+ .start = s_start,
+ .next = s_next,
+ .stop = s_stop,
+ .show = s_show,
};
#define MAX_SLABINFO_WRITE 128
@@ -3543,18 +3593,18 @@ struct seq_operations slabinfo_op = {
* @count: data length
* @ppos: unused
*/
-ssize_t slabinfo_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *ppos)
+ssize_t slabinfo_write(struct file *file, const char __user * buffer,
+ size_t count, loff_t *ppos)
{
- char kbuf[MAX_SLABINFO_WRITE+1], *tmp;
+ char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
int limit, batchcount, shared, res;
struct list_head *p;
-
+
if (count > MAX_SLABINFO_WRITE)
return -EINVAL;
if (copy_from_user(&kbuf, buffer, count))
return -EFAULT;
- kbuf[MAX_SLABINFO_WRITE] = '\0';
+ kbuf[MAX_SLABINFO_WRITE] = '\0';
tmp = strchr(kbuf, ' ');
if (!tmp)
@@ -3565,25 +3615,24 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
return -EINVAL;
/* Find the cache in the chain of caches. */
- down(&cache_chain_sem);
+ mutex_lock(&cache_chain_mutex);
res = -EINVAL;
- list_for_each(p,&cache_chain) {
+ list_for_each(p, &cache_chain) {
kmem_cache_t *cachep = list_entry(p, kmem_cache_t, next);
if (!strcmp(cachep->name, kbuf)) {
if (limit < 1 ||
batchcount < 1 ||
- batchcount > limit ||
- shared < 0) {
+ batchcount > limit || shared < 0) {
res = 0;
} else {
res = do_tune_cpucache(cachep, limit,
- batchcount, shared);
+ batchcount, shared);
}
break;
}
}
- up(&cache_chain_sem);
+ mutex_unlock(&cache_chain_mutex);
if (res >= 0)
res = count;
return res;
@@ -3609,26 +3658,3 @@ unsigned int ksize(const void *objp)
return obj_reallen(page_get_cache(virt_to_page(objp)));
}
-
-
-/*
- * kstrdup - allocate space for and copy an existing string
- *
- * @s: the string to duplicate
- * @gfp: the GFP mask used in the kmalloc() call when allocating memory
- */
-char *kstrdup(const char *s, gfp_t gfp)
-{
- size_t len;
- char *buf;
-
- if (!s)
- return NULL;
-
- len = strlen(s) + 1;
- buf = kmalloc(len, gfp);
- if (buf)
- memcpy(buf, s, len);
- return buf;
-}
-EXPORT_SYMBOL(kstrdup);
diff --git a/mm/slob.c b/mm/slob.c
new file mode 100644
index 000000000000..1c240c4b71d9
--- /dev/null
+++ b/mm/slob.c
@@ -0,0 +1,385 @@
+/*
+ * SLOB Allocator: Simple List Of Blocks
+ *
+ * Matt Mackall <mpm@selenic.com> 12/30/03
+ *
+ * How SLOB works:
+ *
+ * The core of SLOB is a traditional K&R style heap allocator, with
+ * support for returning aligned objects. The granularity of this
+ * allocator is 8 bytes on x86, though it's perhaps possible to reduce
+ * this to 4 if it's deemed worth the effort. The slob heap is a
+ * singly-linked list of pages from __get_free_page, grown on demand
+ * and allocation from the heap is currently first-fit.
+ *
+ * Above this is an implementation of kmalloc/kfree. Blocks returned
+ * from kmalloc are 8-byte aligned and prepended with a 8-byte header.
+ * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls
+ * __get_free_pages directly so that it can return page-aligned blocks
+ * and keeps a linked list of such pages and their orders. These
+ * objects are detected in kfree() by their page alignment.
+ *
+ * SLAB is emulated on top of SLOB by simply calling constructors and
+ * destructors for every SLAB allocation. Objects are returned with
+ * the 8-byte alignment unless the SLAB_MUST_HWCACHE_ALIGN flag is
+ * set, in which case the low-level allocator will fragment blocks to
+ * create the proper alignment. Again, objects of page-size or greater
+ * are allocated by calling __get_free_pages. As SLAB objects know
+ * their size, no separate size bookkeeping is necessary and there is
+ * essentially no allocation space overhead.
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/cache.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+
+struct slob_block {
+ int units;
+ struct slob_block *next;
+};
+typedef struct slob_block slob_t;
+
+#define SLOB_UNIT sizeof(slob_t)
+#define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT)
+#define SLOB_ALIGN L1_CACHE_BYTES
+
+struct bigblock {
+ int order;
+ void *pages;
+ struct bigblock *next;
+};
+typedef struct bigblock bigblock_t;
+
+static slob_t arena = { .next = &arena, .units = 1 };
+static slob_t *slobfree = &arena;
+static bigblock_t *bigblocks;
+static DEFINE_SPINLOCK(slob_lock);
+static DEFINE_SPINLOCK(block_lock);
+
+static void slob_free(void *b, int size);
+
+static void *slob_alloc(size_t size, gfp_t gfp, int align)
+{
+ slob_t *prev, *cur, *aligned = 0;
+ int delta = 0, units = SLOB_UNITS(size);
+ unsigned long flags;
+
+ spin_lock_irqsave(&slob_lock, flags);
+ prev = slobfree;
+ for (cur = prev->next; ; prev = cur, cur = cur->next) {
+ if (align) {
+ aligned = (slob_t *)ALIGN((unsigned long)cur, align);
+ delta = aligned - cur;
+ }
+ if (cur->units >= units + delta) { /* room enough? */
+ if (delta) { /* need to fragment head to align? */
+ aligned->units = cur->units - delta;
+ aligned->next = cur->next;
+ cur->next = aligned;
+ cur->units = delta;
+ prev = cur;
+ cur = aligned;
+ }
+
+ if (cur->units == units) /* exact fit? */
+ prev->next = cur->next; /* unlink */
+ else { /* fragment */
+ prev->next = cur + units;
+ prev->next->units = cur->units - units;
+ prev->next->next = cur->next;
+ cur->units = units;
+ }
+
+ slobfree = prev;
+ spin_unlock_irqrestore(&slob_lock, flags);
+ return cur;
+ }
+ if (cur == slobfree) {
+ spin_unlock_irqrestore(&slob_lock, flags);
+
+ if (size == PAGE_SIZE) /* trying to shrink arena? */
+ return 0;
+
+ cur = (slob_t *)__get_free_page(gfp);
+ if (!cur)
+ return 0;
+
+ slob_free(cur, PAGE_SIZE);
+ spin_lock_irqsave(&slob_lock, flags);
+ cur = slobfree;
+ }
+ }
+}
+
+static void slob_free(void *block, int size)
+{
+ slob_t *cur, *b = (slob_t *)block;
+ unsigned long flags;
+
+ if (!block)
+ return;
+
+ if (size)
+ b->units = SLOB_UNITS(size);
+
+ /* Find reinsertion point */
+ spin_lock_irqsave(&slob_lock, flags);
+ for (cur = slobfree; !(b > cur && b < cur->next); cur = cur->next)
+ if (cur >= cur->next && (b > cur || b < cur->next))
+ break;
+
+ if (b + b->units == cur->next) {
+ b->units += cur->next->units;
+ b->next = cur->next->next;
+ } else
+ b->next = cur->next;
+
+ if (cur + cur->units == b) {
+ cur->units += b->units;
+ cur->next = b->next;
+ } else
+ cur->next = b;
+
+ slobfree = cur;
+
+ spin_unlock_irqrestore(&slob_lock, flags);
+}
+
+static int FASTCALL(find_order(int size));
+static int fastcall find_order(int size)
+{
+ int order = 0;
+ for ( ; size > 4096 ; size >>=1)
+ order++;
+ return order;
+}
+
+void *kmalloc(size_t size, gfp_t gfp)
+{
+ slob_t *m;
+ bigblock_t *bb;
+ unsigned long flags;
+
+ if (size < PAGE_SIZE - SLOB_UNIT) {
+ m = slob_alloc(size + SLOB_UNIT, gfp, 0);
+ return m ? (void *)(m + 1) : 0;
+ }
+
+ bb = slob_alloc(sizeof(bigblock_t), gfp, 0);
+ if (!bb)
+ return 0;
+
+ bb->order = find_order(size);
+ bb->pages = (void *)__get_free_pages(gfp, bb->order);
+
+ if (bb->pages) {
+ spin_lock_irqsave(&block_lock, flags);
+ bb->next = bigblocks;
+ bigblocks = bb;
+ spin_unlock_irqrestore(&block_lock, flags);
+ return bb->pages;
+ }
+
+ slob_free(bb, sizeof(bigblock_t));
+ return 0;
+}
+
+EXPORT_SYMBOL(kmalloc);
+
+void kfree(const void *block)
+{
+ bigblock_t *bb, **last = &bigblocks;
+ unsigned long flags;
+
+ if (!block)
+ return;
+
+ if (!((unsigned long)block & (PAGE_SIZE-1))) {
+ /* might be on the big block list */
+ spin_lock_irqsave(&block_lock, flags);
+ for (bb = bigblocks; bb; last = &bb->next, bb = bb->next) {
+ if (bb->pages == block) {
+ *last = bb->next;
+ spin_unlock_irqrestore(&block_lock, flags);
+ free_pages((unsigned long)block, bb->order);
+ slob_free(bb, sizeof(bigblock_t));
+ return;
+ }
+ }
+ spin_unlock_irqrestore(&block_lock, flags);
+ }
+
+ slob_free((slob_t *)block - 1, 0);
+ return;
+}
+
+EXPORT_SYMBOL(kfree);
+
+unsigned int ksize(const void *block)
+{
+ bigblock_t *bb;
+ unsigned long flags;
+
+ if (!block)
+ return 0;
+
+ if (!((unsigned long)block & (PAGE_SIZE-1))) {
+ spin_lock_irqsave(&block_lock, flags);
+ for (bb = bigblocks; bb; bb = bb->next)
+ if (bb->pages == block) {
+ spin_unlock_irqrestore(&slob_lock, flags);
+ return PAGE_SIZE << bb->order;
+ }
+ spin_unlock_irqrestore(&block_lock, flags);
+ }
+
+ return ((slob_t *)block - 1)->units * SLOB_UNIT;
+}
+
+struct kmem_cache {
+ unsigned int size, align;
+ const char *name;
+ void (*ctor)(void *, struct kmem_cache *, unsigned long);
+ void (*dtor)(void *, struct kmem_cache *, unsigned long);
+};
+
+struct kmem_cache *kmem_cache_create(const char *name, size_t size,
+ size_t align, unsigned long flags,
+ void (*ctor)(void*, struct kmem_cache *, unsigned long),
+ void (*dtor)(void*, struct kmem_cache *, unsigned long))
+{
+ struct kmem_cache *c;
+
+ c = slob_alloc(sizeof(struct kmem_cache), flags, 0);
+
+ if (c) {
+ c->name = name;
+ c->size = size;
+ c->ctor = ctor;
+ c->dtor = dtor;
+ /* ignore alignment unless it's forced */
+ c->align = (flags & SLAB_MUST_HWCACHE_ALIGN) ? SLOB_ALIGN : 0;
+ if (c->align < align)
+ c->align = align;
+ }
+
+ return c;
+}
+EXPORT_SYMBOL(kmem_cache_create);
+
+int kmem_cache_destroy(struct kmem_cache *c)
+{
+ slob_free(c, sizeof(struct kmem_cache));
+ return 0;
+}
+EXPORT_SYMBOL(kmem_cache_destroy);
+
+void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags)
+{
+ void *b;
+
+ if (c->size < PAGE_SIZE)
+ b = slob_alloc(c->size, flags, c->align);
+ else
+ b = (void *)__get_free_pages(flags, find_order(c->size));
+
+ if (c->ctor)
+ c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR);
+
+ return b;
+}
+EXPORT_SYMBOL(kmem_cache_alloc);
+
+void kmem_cache_free(struct kmem_cache *c, void *b)
+{
+ if (c->dtor)
+ c->dtor(b, c, 0);
+
+ if (c->size < PAGE_SIZE)
+ slob_free(b, c->size);
+ else
+ free_pages((unsigned long)b, find_order(c->size));
+}
+EXPORT_SYMBOL(kmem_cache_free);
+
+unsigned int kmem_cache_size(struct kmem_cache *c)
+{
+ return c->size;
+}
+EXPORT_SYMBOL(kmem_cache_size);
+
+const char *kmem_cache_name(struct kmem_cache *c)
+{
+ return c->name;
+}
+EXPORT_SYMBOL(kmem_cache_name);
+
+static struct timer_list slob_timer = TIMER_INITIALIZER(
+ (void (*)(unsigned long))kmem_cache_init, 0, 0);
+
+void kmem_cache_init(void)
+{
+ void *p = slob_alloc(PAGE_SIZE, 0, PAGE_SIZE-1);
+
+ if (p)
+ free_page((unsigned long)p);
+
+ mod_timer(&slob_timer, jiffies + HZ);
+}
+
+atomic_t slab_reclaim_pages = ATOMIC_INIT(0);
+EXPORT_SYMBOL(slab_reclaim_pages);
+
+#ifdef CONFIG_SMP
+
+void *__alloc_percpu(size_t size, size_t align)
+{
+ int i;
+ struct percpu_data *pdata = kmalloc(sizeof (*pdata), GFP_KERNEL);
+
+ if (!pdata)
+ return NULL;
+
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_possible(i))
+ continue;
+ pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
+ if (!pdata->ptrs[i])
+ goto unwind_oom;
+ memset(pdata->ptrs[i], 0, size);
+ }
+
+ /* Catch derefs w/o wrappers */
+ return (void *) (~(unsigned long) pdata);
+
+unwind_oom:
+ while (--i >= 0) {
+ if (!cpu_possible(i))
+ continue;
+ kfree(pdata->ptrs[i]);
+ }
+ kfree(pdata);
+ return NULL;
+}
+EXPORT_SYMBOL(__alloc_percpu);
+
+void
+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;
+ kfree(p->ptrs[i]);
+ }
+ kfree(p);
+}
+EXPORT_SYMBOL(free_percpu);
+
+#endif
diff --git a/mm/sparse.c b/mm/sparse.c
index 72079b538e2d..0a51f36ba3a1 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -18,10 +18,10 @@
*/
#ifdef CONFIG_SPARSEMEM_EXTREME
struct mem_section *mem_section[NR_SECTION_ROOTS]
- ____cacheline_maxaligned_in_smp;
+ ____cacheline_internodealigned_in_smp;
#else
struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT]
- ____cacheline_maxaligned_in_smp;
+ ____cacheline_internodealigned_in_smp;
#endif
EXPORT_SYMBOL(mem_section);
diff --git a/mm/swap.c b/mm/swap.c
index 73d351439ef6..bc2442a7b0ee 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -156,18 +156,50 @@ void fastcall lru_cache_add_active(struct page *page)
put_cpu_var(lru_add_active_pvecs);
}
-void lru_add_drain(void)
+static void __lru_add_drain(int cpu)
{
- struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
+ struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
+ /* CPU is dead, so no locking needed. */
if (pagevec_count(pvec))
__pagevec_lru_add(pvec);
- pvec = &__get_cpu_var(lru_add_active_pvecs);
+ pvec = &per_cpu(lru_add_active_pvecs, cpu);
if (pagevec_count(pvec))
__pagevec_lru_add_active(pvec);
- put_cpu_var(lru_add_pvecs);
}
+void lru_add_drain(void)
+{
+ __lru_add_drain(get_cpu());
+ put_cpu();
+}
+
+#ifdef CONFIG_NUMA
+static void lru_add_drain_per_cpu(void *dummy)
+{
+ lru_add_drain();
+}
+
+/*
+ * Returns 0 for success
+ */
+int lru_add_drain_all(void)
+{
+ return schedule_on_each_cpu(lru_add_drain_per_cpu, NULL);
+}
+
+#else
+
+/*
+ * Returns 0 for success
+ */
+int lru_add_drain_all(void)
+{
+ lru_add_drain();
+ return 0;
+}
+#endif
+
/*
* This path almost never happens for VM activity - pages are normally
* freed via pagevecs. But it gets used by networking.
@@ -378,6 +410,8 @@ unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
return pagevec_count(pvec);
}
+EXPORT_SYMBOL(pagevec_lookup);
+
unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping,
pgoff_t *index, int tag, unsigned nr_pages)
{
@@ -412,17 +446,6 @@ void vm_acct_memory(long pages)
}
#ifdef CONFIG_HOTPLUG_CPU
-static void lru_drain_cache(unsigned int cpu)
-{
- struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
-
- /* CPU is dead, so no locking needed. */
- if (pagevec_count(pvec))
- __pagevec_lru_add(pvec);
- pvec = &per_cpu(lru_add_active_pvecs, cpu);
- if (pagevec_count(pvec))
- __pagevec_lru_add_active(pvec);
-}
/* Drop the CPU's cached committed space back into the central pool. */
static int cpu_swap_callback(struct notifier_block *nfb,
@@ -435,7 +458,7 @@ static int cpu_swap_callback(struct notifier_block *nfb,
if (action == CPU_DEAD) {
atomic_add(*committed, &vm_committed_space);
*committed = 0;
- lru_drain_cache((long)hcpu);
+ __lru_add_drain((long)hcpu);
}
return NOTIFY_OK;
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 0df9a57b1de8..7b09ac503fec 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -14,6 +14,7 @@
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/backing-dev.h>
+#include <linux/pagevec.h>
#include <asm/pgtable.h>
@@ -140,7 +141,7 @@ void __delete_from_swap_cache(struct page *page)
* Allocate swap space for the page and add the page to the
* swap cache. Caller needs to hold the page lock.
*/
-int add_to_swap(struct page * page)
+int add_to_swap(struct page * page, gfp_t gfp_mask)
{
swp_entry_t entry;
int err;
@@ -165,7 +166,7 @@ int add_to_swap(struct page * page)
* Add it to the swap cache and mark it dirty
*/
err = __add_to_swap_cache(page, entry,
- GFP_ATOMIC|__GFP_NOMEMALLOC|__GFP_NOWARN);
+ gfp_mask|__GFP_NOMEMALLOC|__GFP_NOWARN);
switch (err) {
case 0: /* Success */
@@ -272,12 +273,11 @@ void free_page_and_swap_cache(struct page *page)
*/
void free_pages_and_swap_cache(struct page **pages, int nr)
{
- int chunk = 16;
struct page **pagep = pages;
lru_add_drain();
while (nr) {
- int todo = min(chunk, nr);
+ int todo = min(nr, PAGEVEC_SIZE);
int i;
for (i = 0; i < todo; i++)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index edafeace301f..f1e69c30d203 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -25,6 +25,8 @@
#include <linux/rmap.h>
#include <linux/security.h>
#include <linux/backing-dev.h>
+#include <linux/mutex.h>
+#include <linux/capability.h>
#include <linux/syscalls.h>
#include <asm/pgtable.h>
@@ -45,12 +47,12 @@ struct swap_list_t swap_list = {-1, -1};
struct swap_info_struct swap_info[MAX_SWAPFILES];
-static DECLARE_MUTEX(swapon_sem);
+static DEFINE_MUTEX(swapon_mutex);
/*
* We need this because the bdev->unplug_fn can sleep and we cannot
* hold swap_lock while calling the unplug_fn. And swap_lock
- * cannot be turned into a semaphore.
+ * cannot be turned into a mutex.
*/
static DECLARE_RWSEM(swap_unplug_sem);
@@ -211,6 +213,26 @@ noswap:
return (swp_entry_t) {0};
}
+swp_entry_t get_swap_page_of_type(int type)
+{
+ struct swap_info_struct *si;
+ pgoff_t offset;
+
+ spin_lock(&swap_lock);
+ si = swap_info + type;
+ if (si->flags & SWP_WRITEOK) {
+ nr_swap_pages--;
+ offset = scan_swap_map(si);
+ if (offset) {
+ spin_unlock(&swap_lock);
+ return swp_entry(type, offset);
+ }
+ nr_swap_pages++;
+ }
+ spin_unlock(&swap_lock);
+ return (swp_entry_t) {0};
+}
+
static struct swap_info_struct * swap_info_get(swp_entry_t entry)
{
struct swap_info_struct * p;
@@ -1140,7 +1162,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
up_write(&swap_unplug_sem);
destroy_swap_extents(p);
- down(&swapon_sem);
+ mutex_lock(&swapon_mutex);
spin_lock(&swap_lock);
drain_mmlist();
@@ -1159,7 +1181,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
p->swap_map = NULL;
p->flags = 0;
spin_unlock(&swap_lock);
- up(&swapon_sem);
+ mutex_unlock(&swapon_mutex);
vfree(swap_map);
inode = mapping->host;
if (S_ISBLK(inode->i_mode)) {
@@ -1167,9 +1189,9 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
set_blocksize(bdev, p->old_block_size);
bd_release(bdev);
} else {
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
inode->i_flags &= ~S_SWAPFILE;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
filp_close(swap_file, NULL);
err = 0;
@@ -1188,7 +1210,7 @@ static void *swap_start(struct seq_file *swap, loff_t *pos)
int i;
loff_t l = *pos;
- down(&swapon_sem);
+ mutex_lock(&swapon_mutex);
for (i = 0; i < nr_swapfiles; i++, ptr++) {
if (!(ptr->flags & SWP_USED) || !ptr->swap_map)
@@ -1217,7 +1239,7 @@ static void *swap_next(struct seq_file *swap, void *v, loff_t *pos)
static void swap_stop(struct seq_file *swap, void *v)
{
- up(&swapon_sem);
+ mutex_unlock(&swapon_mutex);
}
static int swap_show(struct seq_file *swap, void *v)
@@ -1386,7 +1408,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
p->bdev = bdev;
} else if (S_ISREG(inode->i_mode)) {
p->bdev = inode->i_sb->s_bdev;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
did_down = 1;
if (IS_SWAPFILE(inode)) {
error = -EBUSY;
@@ -1422,7 +1444,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
else if (!memcmp("SWAPSPACE2",swap_header->magic.magic,10))
swap_header_version = 2;
else {
- printk("Unable to find swap-space signature\n");
+ printk(KERN_ERR "Unable to find swap-space signature\n");
error = -EINVAL;
goto bad_swap;
}
@@ -1473,7 +1495,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
goto bad_swap;
if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
goto bad_swap;
-
+
/* OK, set up the swap map and apply the bad block list */
if (!(p->swap_map = vmalloc(maxpages * sizeof(short)))) {
error = -ENOMEM;
@@ -1482,17 +1504,17 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
error = 0;
memset(p->swap_map, 0, maxpages * sizeof(short));
- for (i=0; i<swap_header->info.nr_badpages; i++) {
- int page = swap_header->info.badpages[i];
- if (page <= 0 || page >= swap_header->info.last_page)
+ for (i = 0; i < swap_header->info.nr_badpages; i++) {
+ int page_nr = swap_header->info.badpages[i];
+ if (page_nr <= 0 || page_nr >= swap_header->info.last_page)
error = -EINVAL;
else
- p->swap_map[page] = SWAP_MAP_BAD;
+ p->swap_map[page_nr] = SWAP_MAP_BAD;
}
nr_good_pages = swap_header->info.last_page -
swap_header->info.nr_badpages -
1 /* header page */;
- if (error)
+ if (error)
goto bad_swap;
}
@@ -1519,7 +1541,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
goto bad_swap;
}
- down(&swapon_sem);
+ mutex_lock(&swapon_mutex);
spin_lock(&swap_lock);
p->flags = SWP_ACTIVE;
nr_swap_pages += nr_good_pages;
@@ -1545,7 +1567,7 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
swap_info[prev].next = p - swap_info;
}
spin_unlock(&swap_lock);
- up(&swapon_sem);
+ mutex_unlock(&swapon_mutex);
error = 0;
goto out;
bad_swap:
@@ -1576,7 +1598,7 @@ out:
if (did_down) {
if (!error)
inode->i_flags |= S_SWAPFILE;
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
return error;
}
diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
index b58abcf44ed6..f9d6a9cc91c4 100644
--- a/mm/tiny-shmem.c
+++ b/mm/tiny-shmem.c
@@ -81,13 +81,19 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
goto close_file;
d_instantiate(dentry, inode);
- inode->i_size = size;
inode->i_nlink = 0; /* It is unlinked */
+
file->f_vfsmnt = mntget(shm_mnt);
file->f_dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_op = &ramfs_file_operations;
file->f_mode = FMODE_WRITE | FMODE_READ;
+
+ /* notify everyone as to the change of file size */
+ error = do_truncate(dentry, size, 0, file);
+ if (error < 0)
+ goto close_file;
+
return file;
close_file:
@@ -123,3 +129,24 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
{
return 0;
}
+
+int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ file_accessed(file);
+#ifndef CONFIG_MMU
+ return ramfs_nommu_mmap(file, vma);
+#else
+ return 0;
+#endif
+}
+
+#ifndef CONFIG_MMU
+unsigned long shmem_get_unmapped_area(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags)
+{
+ return ramfs_nommu_get_unmapped_area(file, addr, len, pgoff, flags);
+}
+#endif
diff --git a/mm/truncate.c b/mm/truncate.c
index 9173ab500604..6cb3fff25f67 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -82,12 +82,15 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
}
/**
- * truncate_inode_pages - truncate *all* the pages from an offset
+ * truncate_inode_pages - truncate range of pages specified by start and
+ * end byte offsets
* @mapping: mapping to truncate
* @lstart: offset from which to truncate
+ * @lend: offset to which to truncate
*
- * Truncate the page cache at a set offset, removing the pages that are beyond
- * that offset (and zeroing out partial pages).
+ * Truncate the page cache, removing the pages that are between
+ * specified offsets (and zeroing out partial page
+ * (if lstart is not page aligned)).
*
* Truncate takes two passes - the first pass is nonblocking. It will not
* block on page locks and it will not block on writeback. The second pass
@@ -101,12 +104,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
* We pass down the cache-hot hint to the page freeing code. Even if the
* mapping is large, it is probably the case that the final pages are the most
* recently touched, and freeing happens in ascending file offset order.
- *
- * Called under (and serialised by) inode->i_sem.
*/
-void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
+void truncate_inode_pages_range(struct address_space *mapping,
+ loff_t lstart, loff_t lend)
{
const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
+ pgoff_t end;
const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1);
struct pagevec pvec;
pgoff_t next;
@@ -115,13 +118,22 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
if (mapping->nrpages == 0)
return;
+ BUG_ON((lend & (PAGE_CACHE_SIZE - 1)) != (PAGE_CACHE_SIZE - 1));
+ end = (lend >> PAGE_CACHE_SHIFT);
+
pagevec_init(&pvec, 0);
next = start;
- while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+ while (next <= end &&
+ pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
for (i = 0; i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i];
pgoff_t page_index = page->index;
+ if (page_index > end) {
+ next = page_index;
+ break;
+ }
+
if (page_index > next)
next = page_index;
next++;
@@ -157,9 +169,15 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
next = start;
continue;
}
+ if (pvec.pages[0]->index > end) {
+ pagevec_release(&pvec);
+ break;
+ }
for (i = 0; i < pagevec_count(&pvec); i++) {
struct page *page = pvec.pages[i];
+ if (page->index > end)
+ break;
lock_page(page);
wait_on_page_writeback(page);
if (page->index > next)
@@ -171,7 +189,19 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
pagevec_release(&pvec);
}
}
+EXPORT_SYMBOL(truncate_inode_pages_range);
+/**
+ * truncate_inode_pages - truncate *all* the pages from an offset
+ * @mapping: mapping to truncate
+ * @lstart: offset from which to truncate
+ *
+ * Called under (and serialised by) inode->i_mutex.
+ */
+void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
+{
+ truncate_inode_pages_range(mapping, lstart, (loff_t)-1);
+}
EXPORT_SYMBOL(truncate_inode_pages);
/**
@@ -219,7 +249,6 @@ unlock:
break;
}
pagevec_release(&pvec);
- cond_resched();
}
return ret;
}
diff --git a/mm/util.c b/mm/util.c
new file mode 100644
index 000000000000..5f4bb59da63c
--- /dev/null
+++ b/mm/util.c
@@ -0,0 +1,39 @@
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ */
+void *kzalloc(size_t size, gfp_t flags)
+{
+ void *ret = kmalloc(size, flags);
+ if (ret)
+ memset(ret, 0, size);
+ return ret;
+}
+EXPORT_SYMBOL(kzalloc);
+
+/*
+ * kstrdup - allocate space for and copy an existing string
+ *
+ * @s: the string to duplicate
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ */
+char *kstrdup(const char *s, gfp_t gfp)
+{
+ size_t len;
+ char *buf;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s) + 1;
+ buf = kmalloc(len, gfp);
+ if (buf)
+ memcpy(buf, s, len);
+ return buf;
+}
+EXPORT_SYMBOL(kstrdup);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b0cd81c32de6..2e34b61a70c7 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -63,9 +63,6 @@ struct scan_control {
unsigned long nr_mapped; /* From page_state */
- /* How many pages shrink_cache() should reclaim */
- int nr_to_reclaim;
-
/* Ask shrink_caches, or shrink_zone to scan at this priority */
unsigned int priority;
@@ -186,8 +183,7 @@ EXPORT_SYMBOL(remove_shrinker);
*
* Returns the number of slab objects which we shrunk.
*/
-static int shrink_slab(unsigned long scanned, gfp_t gfp_mask,
- unsigned long lru_pages)
+int shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages)
{
struct shrinker *shrinker;
int ret = 0;
@@ -275,9 +271,7 @@ static inline int is_page_cache_freeable(struct page *page)
static int may_write_to_queue(struct backing_dev_info *bdi)
{
- if (current_is_kswapd())
- return 1;
- if (current_is_pdflush()) /* This is unlikely, but why not... */
+ if (current->flags & PF_SWAPWRITE)
return 1;
if (!bdi_write_congested(bdi))
return 1;
@@ -367,7 +361,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
res = mapping->a_ops->writepage(page, &wbc);
if (res < 0)
handle_write_error(mapping, page, res);
- if (res == WRITEPAGE_ACTIVATE) {
+ if (res == AOP_WRITEPAGE_ACTIVATE) {
ClearPageReclaim(page);
return PAGE_ACTIVATE;
}
@@ -382,6 +376,43 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
return PAGE_CLEAN;
}
+static int remove_mapping(struct address_space *mapping, struct page *page)
+{
+ if (!mapping)
+ return 0; /* truncate got there first */
+
+ write_lock_irq(&mapping->tree_lock);
+
+ /*
+ * The non-racy check for busy page. It is critical to check
+ * PageDirty _after_ making sure that the page is freeable and
+ * not in use by anybody. (pagecache + us == 2)
+ */
+ if (unlikely(page_count(page) != 2))
+ goto cannot_free;
+ smp_rmb();
+ if (unlikely(PageDirty(page)))
+ goto cannot_free;
+
+ if (PageSwapCache(page)) {
+ swp_entry_t swap = { .val = page_private(page) };
+ __delete_from_swap_cache(page);
+ write_unlock_irq(&mapping->tree_lock);
+ swap_free(swap);
+ __put_page(page); /* The pagecache ref */
+ return 1;
+ }
+
+ __remove_from_page_cache(page);
+ write_unlock_irq(&mapping->tree_lock);
+ __put_page(page);
+ return 1;
+
+cannot_free:
+ write_unlock_irq(&mapping->tree_lock);
+ return 0;
+}
+
/*
* shrink_list adds the number of reclaimed pages to sc->nr_reclaimed
*/
@@ -432,7 +463,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
if (PageAnon(page) && !PageSwapCache(page)) {
if (!sc->may_swap)
goto keep_locked;
- if (!add_to_swap(page))
+ if (!add_to_swap(page, GFP_ATOMIC))
goto activate_locked;
}
#endif /* CONFIG_SWAP */
@@ -515,36 +546,8 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
goto free_it;
}
- if (!mapping)
- goto keep_locked; /* truncate got there first */
-
- write_lock_irq(&mapping->tree_lock);
-
- /*
- * The non-racy check for busy page. It is critical to check
- * PageDirty _after_ making sure that the page is freeable and
- * not in use by anybody. (pagecache + us == 2)
- */
- if (unlikely(page_count(page) != 2))
- goto cannot_free;
- smp_rmb();
- if (unlikely(PageDirty(page)))
- goto cannot_free;
-
-#ifdef CONFIG_SWAP
- if (PageSwapCache(page)) {
- swp_entry_t swap = { .val = page_private(page) };
- __delete_from_swap_cache(page);
- write_unlock_irq(&mapping->tree_lock);
- swap_free(swap);
- __put_page(page); /* The pagecache ref */
- goto free_it;
- }
-#endif /* CONFIG_SWAP */
-
- __remove_from_page_cache(page);
- write_unlock_irq(&mapping->tree_lock);
- __put_page(page);
+ if (!remove_mapping(mapping, page))
+ goto keep_locked;
free_it:
unlock_page(page);
@@ -553,10 +556,6 @@ free_it:
__pagevec_release_nonlru(&freed_pvec);
continue;
-cannot_free:
- write_unlock_irq(&mapping->tree_lock);
- goto keep_locked;
-
activate_locked:
SetPageActive(page);
pgactivate++;
@@ -574,6 +573,228 @@ keep:
return reclaimed;
}
+#ifdef CONFIG_MIGRATION
+static inline void move_to_lru(struct page *page)
+{
+ list_del(&page->lru);
+ if (PageActive(page)) {
+ /*
+ * lru_cache_add_active checks that
+ * the PG_active bit is off.
+ */
+ ClearPageActive(page);
+ lru_cache_add_active(page);
+ } else {
+ lru_cache_add(page);
+ }
+ put_page(page);
+}
+
+/*
+ * Add isolated pages on the list back to the LRU.
+ *
+ * returns the number of pages put back.
+ */
+int putback_lru_pages(struct list_head *l)
+{
+ struct page *page;
+ struct page *page2;
+ int count = 0;
+
+ list_for_each_entry_safe(page, page2, l, lru) {
+ move_to_lru(page);
+ count++;
+ }
+ return count;
+}
+
+/*
+ * swapout a single page
+ * page is locked upon entry, unlocked on exit
+ */
+static int swap_page(struct page *page)
+{
+ struct address_space *mapping = page_mapping(page);
+
+ if (page_mapped(page) && mapping)
+ if (try_to_unmap(page) != SWAP_SUCCESS)
+ goto unlock_retry;
+
+ if (PageDirty(page)) {
+ /* Page is dirty, try to write it out here */
+ switch(pageout(page, mapping)) {
+ case PAGE_KEEP:
+ case PAGE_ACTIVATE:
+ goto unlock_retry;
+
+ case PAGE_SUCCESS:
+ goto retry;
+
+ case PAGE_CLEAN:
+ ; /* try to free the page below */
+ }
+ }
+
+ if (PagePrivate(page)) {
+ if (!try_to_release_page(page, GFP_KERNEL) ||
+ (!mapping && page_count(page) == 1))
+ goto unlock_retry;
+ }
+
+ if (remove_mapping(mapping, page)) {
+ /* Success */
+ unlock_page(page);
+ return 0;
+ }
+
+unlock_retry:
+ unlock_page(page);
+
+retry:
+ return -EAGAIN;
+}
+/*
+ * migrate_pages
+ *
+ * Two lists are passed to this function. The first list
+ * contains the pages isolated from the LRU to be migrated.
+ * The second list contains new pages that the pages isolated
+ * can be moved to. If the second list is NULL then all
+ * pages are swapped out.
+ *
+ * The function returns after 10 attempts or if no pages
+ * are movable anymore because t has become empty
+ * or no retryable pages exist anymore.
+ *
+ * SIMPLIFIED VERSION: This implementation of migrate_pages
+ * is only swapping out pages and never touches the second
+ * list. The direct migration patchset
+ * extends this function to avoid the use of swap.
+ *
+ * Return: Number of pages not migrated when "to" ran empty.
+ */
+int migrate_pages(struct list_head *from, struct list_head *to,
+ struct list_head *moved, struct list_head *failed)
+{
+ int retry;
+ int nr_failed = 0;
+ int pass = 0;
+ struct page *page;
+ struct page *page2;
+ int swapwrite = current->flags & PF_SWAPWRITE;
+ int rc;
+
+ if (!swapwrite)
+ current->flags |= PF_SWAPWRITE;
+
+redo:
+ retry = 0;
+
+ list_for_each_entry_safe(page, page2, from, lru) {
+ cond_resched();
+
+ rc = 0;
+ if (page_count(page) == 1)
+ /* page was freed from under us. So we are done. */
+ goto next;
+
+ /*
+ * Skip locked pages during the first two passes to give the
+ * functions holding the lock time to release the page. Later we
+ * use lock_page() to have a higher chance of acquiring the
+ * lock.
+ */
+ rc = -EAGAIN;
+ if (pass > 2)
+ lock_page(page);
+ else
+ if (TestSetPageLocked(page))
+ goto next;
+
+ /*
+ * Only wait on writeback if we have already done a pass where
+ * we we may have triggered writeouts for lots of pages.
+ */
+ if (pass > 0) {
+ wait_on_page_writeback(page);
+ } else {
+ if (PageWriteback(page))
+ goto unlock_page;
+ }
+
+ /*
+ * Anonymous pages must have swap cache references otherwise
+ * the information contained in the page maps cannot be
+ * preserved.
+ */
+ if (PageAnon(page) && !PageSwapCache(page)) {
+ if (!add_to_swap(page, GFP_KERNEL)) {
+ rc = -ENOMEM;
+ goto unlock_page;
+ }
+ }
+
+ /*
+ * Page is properly locked and writeback is complete.
+ * Try to migrate the page.
+ */
+ rc = swap_page(page);
+ goto next;
+
+unlock_page:
+ unlock_page(page);
+
+next:
+ if (rc == -EAGAIN) {
+ retry++;
+ } else if (rc) {
+ /* Permanent failure */
+ list_move(&page->lru, failed);
+ nr_failed++;
+ } else {
+ /* Success */
+ list_move(&page->lru, moved);
+ }
+ }
+ if (retry && pass++ < 10)
+ goto redo;
+
+ if (!swapwrite)
+ current->flags &= ~PF_SWAPWRITE;
+
+ return nr_failed + retry;
+}
+
+/*
+ * Isolate one page from the LRU lists and put it on the
+ * indicated list with elevated refcount.
+ *
+ * Result:
+ * 0 = page not on LRU list
+ * 1 = page removed from LRU list and added to the specified list.
+ */
+int isolate_lru_page(struct page *page)
+{
+ int ret = 0;
+
+ if (PageLRU(page)) {
+ struct zone *zone = page_zone(page);
+ spin_lock_irq(&zone->lru_lock);
+ if (TestClearPageLRU(page)) {
+ ret = 1;
+ get_page(page);
+ if (PageActive(page))
+ del_page_from_active_list(zone, page);
+ else
+ del_page_from_inactive_list(zone, page);
+ }
+ spin_unlock_irq(&zone->lru_lock);
+ }
+
+ return ret;
+}
+#endif
+
/*
* zone->lru_lock is heavily contended. Some of the functions that
* shrink the lists perform better by taking out a batch of pages
@@ -653,17 +874,17 @@ static void shrink_cache(struct zone *zone, struct scan_control *sc)
goto done;
max_scan -= nr_scan;
- if (current_is_kswapd())
- mod_page_state_zone(zone, pgscan_kswapd, nr_scan);
- else
- mod_page_state_zone(zone, pgscan_direct, nr_scan);
nr_freed = shrink_list(&page_list, sc);
- if (current_is_kswapd())
- mod_page_state(kswapd_steal, nr_freed);
- mod_page_state_zone(zone, pgsteal, nr_freed);
- sc->nr_to_reclaim -= nr_freed;
- spin_lock_irq(&zone->lru_lock);
+ local_irq_disable();
+ if (current_is_kswapd()) {
+ __mod_page_state_zone(zone, pgscan_kswapd, nr_scan);
+ __mod_page_state(kswapd_steal, nr_freed);
+ } else
+ __mod_page_state_zone(zone, pgscan_direct, nr_scan);
+ __mod_page_state_zone(zone, pgsteal, nr_freed);
+
+ spin_lock(&zone->lru_lock);
/*
* Put back any unfreeable pages.
*/
@@ -825,11 +1046,13 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc)
}
}
zone->nr_active += pgmoved;
- spin_unlock_irq(&zone->lru_lock);
- pagevec_release(&pvec);
+ spin_unlock(&zone->lru_lock);
+
+ __mod_page_state_zone(zone, pgrefill, pgscanned);
+ __mod_page_state(pgdeactivate, pgdeactivate);
+ local_irq_enable();
- mod_page_state_zone(zone, pgrefill, pgscanned);
- mod_page_state(pgdeactivate, pgdeactivate);
+ pagevec_release(&pvec);
}
/*
@@ -861,8 +1084,6 @@ shrink_zone(struct zone *zone, struct scan_control *sc)
else
nr_inactive = 0;
- sc->nr_to_reclaim = sc->swap_cluster_max;
-
while (nr_active || nr_inactive) {
if (nr_active) {
sc->nr_to_scan = min(nr_active,
@@ -876,8 +1097,6 @@ shrink_zone(struct zone *zone, struct scan_control *sc)
(unsigned long)sc->swap_cluster_max);
nr_inactive -= sc->nr_to_scan;
shrink_cache(zone, sc);
- if (sc->nr_to_reclaim <= 0)
- break;
}
}
@@ -910,7 +1129,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
for (i = 0; zones[i] != NULL; i++) {
struct zone *zone = zones[i];
- if (zone->present_pages == 0)
+ if (!populated_zone(zone))
continue;
if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
@@ -1084,7 +1303,7 @@ loop_again:
for (i = pgdat->nr_zones - 1; i >= 0; i--) {
struct zone *zone = pgdat->node_zones + i;
- if (zone->present_pages == 0)
+ if (!populated_zone(zone))
continue;
if (zone->all_unreclaimable &&
@@ -1121,7 +1340,7 @@ scan:
struct zone *zone = pgdat->node_zones + i;
int nr_slab;
- if (zone->present_pages == 0)
+ if (!populated_zone(zone))
continue;
if (zone->all_unreclaimable && priority != DEF_PRIORITY)
@@ -1238,7 +1457,7 @@ static int kswapd(void *p)
* us from recursively trying to free more memory as we're
* trying to free the first piece of memory in the first place).
*/
- tsk->flags |= PF_MEMALLOC|PF_KSWAPD;
+ tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
order = 0;
for ( ; ; ) {
@@ -1273,7 +1492,7 @@ void wakeup_kswapd(struct zone *zone, int order)
{
pg_data_t *pgdat;
- if (zone->present_pages == 0)
+ if (!populated_zone(zone))
return;
pgdat = zone->zone_pgdat;
@@ -1354,30 +1573,51 @@ static int __init kswapd_init(void)
module_init(kswapd_init)
+#ifdef CONFIG_NUMA
+/*
+ * Zone reclaim mode
+ *
+ * If non-zero call zone_reclaim when the number of free pages falls below
+ * the watermarks.
+ *
+ * In the future we may add flags to the mode. However, the page allocator
+ * should only have to check that zone_reclaim_mode != 0 before calling
+ * zone_reclaim().
+ */
+int zone_reclaim_mode __read_mostly;
/*
+ * Mininum time between zone reclaim scans
+ */
+#define ZONE_RECLAIM_INTERVAL HZ/2
+/*
* Try to free up some pages from this zone through reclaim.
*/
int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
{
- struct scan_control sc;
int nr_pages = 1 << order;
- int total_reclaimed = 0;
+ struct task_struct *p = current;
+ struct reclaim_state reclaim_state;
+ struct scan_control sc = {
+ .gfp_mask = gfp_mask,
+ .may_writepage = 0,
+ .may_swap = 0,
+ .nr_mapped = read_page_state(nr_mapped),
+ .nr_scanned = 0,
+ .nr_reclaimed = 0,
+ .priority = 0
+ };
- /* The reclaim may sleep, so don't do it if sleep isn't allowed */
- if (!(gfp_mask & __GFP_WAIT))
- return 0;
- if (zone->all_unreclaimable)
- return 0;
+ if (!(gfp_mask & __GFP_WAIT) ||
+ zone->zone_pgdat->node_id != numa_node_id() ||
+ zone->all_unreclaimable ||
+ atomic_read(&zone->reclaim_in_progress) > 0)
+ return 0;
+
+ if (time_before(jiffies,
+ zone->last_unsuccessful_zone_reclaim + ZONE_RECLAIM_INTERVAL))
+ return 0;
- sc.gfp_mask = gfp_mask;
- sc.may_writepage = 0;
- sc.may_swap = 0;
- sc.nr_mapped = read_page_state(nr_mapped);
- sc.nr_scanned = 0;
- sc.nr_reclaimed = 0;
- /* scan at the highest priority */
- sc.priority = 0;
disable_swap_token();
if (nr_pages > SWAP_CLUSTER_MAX)
@@ -1385,44 +1625,18 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
else
sc.swap_cluster_max = SWAP_CLUSTER_MAX;
- /* Don't reclaim the zone if there are other reclaimers active */
- if (atomic_read(&zone->reclaim_in_progress) > 0)
- goto out;
-
+ cond_resched();
+ p->flags |= PF_MEMALLOC;
+ reclaim_state.reclaimed_slab = 0;
+ p->reclaim_state = &reclaim_state;
shrink_zone(zone, &sc);
- total_reclaimed = sc.nr_reclaimed;
-
- out:
- return total_reclaimed;
-}
-
-asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone,
- unsigned int state)
-{
- struct zone *z;
- int i;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
+ p->reclaim_state = NULL;
+ current->flags &= ~PF_MEMALLOC;
- if (node >= MAX_NUMNODES || !node_online(node))
- return -EINVAL;
+ if (sc.nr_reclaimed == 0)
+ zone->last_unsuccessful_zone_reclaim = jiffies;
- /* This will break if we ever add more zones */
- if (!(zone & (1<<ZONE_DMA|1<<ZONE_NORMAL|1<<ZONE_HIGHMEM)))
- return -EINVAL;
-
- for (i = 0; i < MAX_NR_ZONES; i++) {
- if (!(zone & 1<<i))
- continue;
-
- z = &NODE_DATA(node)->node_zones[i];
-
- if (state)
- z->reclaim_pages = 1;
- else
- z->reclaim_pages = 0;
- }
-
- return 0;
+ return sc.nr_reclaimed > nr_pages;
}
+#endif
+
diff --git a/net/802/Makefile b/net/802/Makefile
index 01861929591a..977704a54f68 100644
--- a/net/802/Makefile
+++ b/net/802/Makefile
@@ -2,8 +2,6 @@
# Makefile for the Linux 802.x protocol layers.
#
-obj-y := p8023.o
-
# Check the p8022 selections against net/core/Makefile.
obj-$(CONFIG_SYSCTL) += sysctl_net_802.o
obj-$(CONFIG_LLC) += p8022.o psnap.o
@@ -11,5 +9,5 @@ obj-$(CONFIG_TR) += p8022.o psnap.o tr.o sysctl_net_802.o
obj-$(CONFIG_NET_FC) += fc.o
obj-$(CONFIG_FDDI) += fddi.o
obj-$(CONFIG_HIPPI) += hippi.o
-obj-$(CONFIG_IPX) += p8022.o psnap.o
+obj-$(CONFIG_IPX) += p8022.o psnap.o p8023.o
obj-$(CONFIG_ATALK) += p8022.o psnap.o
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 67465b65abe4..fa76220708ce 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -19,6 +19,7 @@
*/
#include <asm/uaccess.h> /* for copy_from_user */
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index f2a8750bbf1d..0f604d227da2 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -214,7 +214,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
* This allows the VLAN to have a different MAC than the underlying
* device, and still route correctly.
*/
- if (memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
+ if (!compare_ether_addr(eth_hdr(skb)->h_dest, skb->dev->dev_addr)) {
/* It is for our (changed) MAC-address! */
skb->pkt_type = PACKET_HOST;
}
diff --git a/net/Kconfig b/net/Kconfig
index 60f6f321bd76..bc603d9aea56 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -150,6 +150,7 @@ endif
source "net/dccp/Kconfig"
source "net/sctp/Kconfig"
+source "net/tipc/Kconfig"
source "net/atm/Kconfig"
source "net/bridge/Kconfig"
source "net/8021q/Kconfig"
diff --git a/net/Makefile b/net/Makefile
index f5141b9d4f38..065796f5fb17 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/
obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
obj-$(CONFIG_IEEE80211) += ieee80211/
+obj-$(CONFIG_TIPC) += tipc/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 7982656b9c83..697ac55e29dc 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -52,6 +52,7 @@
*/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/termios.h> /* For TIOCOUTQ/INQ */
@@ -63,7 +64,7 @@
#include <linux/atalk.h>
struct datalink_proto *ddp_dl, *aarp_dl;
-static struct proto_ops atalk_dgram_ops;
+static const struct proto_ops atalk_dgram_ops;
/**************************************************************************\
* *
@@ -1763,7 +1764,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
*/
static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
- int rc = -EINVAL;
+ int rc = -ENOIOCTLCMD;
struct sock *sk = sock->sk;
void __user *argp = (void __user *)arg;
@@ -1813,23 +1814,6 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = atif_ioctl(cmd, argp);
rtnl_unlock();
break;
- /* Physical layer ioctl calls */
- case SIOCSIFLINK:
- case SIOCGIFHWADDR:
- case SIOCSIFHWADDR:
- case SIOCGIFFLAGS:
- case SIOCSIFFLAGS:
- case SIOCGIFTXQLEN:
- case SIOCSIFTXQLEN:
- case SIOCGIFMTU:
- case SIOCGIFCONF:
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- case SIOCGIFCOUNT:
- case SIOCGIFINDEX:
- case SIOCGIFNAME:
- rc = dev_ioctl(cmd, argp);
- break;
}
return rc;
@@ -1841,7 +1825,7 @@ static struct net_proto_family atalk_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
.family = PF_APPLETALK,
.owner = THIS_MODULE,
.release = atalk_release,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 72f3f7b8de80..680ccb12aae8 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -18,6 +18,7 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary
#include <net/arp.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
+#include <linux/capability.h>
#include <linux/seq_file.h>
#include <linux/atmbr2684.h>
@@ -295,14 +296,14 @@ static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev)
unsigned char *rawp;
eth = eth_hdr(skb);
- if (*eth->h_dest & 1) {
- if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
+ if (is_multicast_ether_addr(eth->h_dest)) {
+ if (!compare_ether_addr(eth->h_dest, dev->broadcast))
skb->pkt_type = PACKET_BROADCAST;
else
skb->pkt_type = PACKET_MULTICAST;
}
- else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+ else if (compare_ether_addr(eth->h_dest, dev->dev_addr))
skb->pkt_type = PACKET_OTHERHOST;
if (ntohs(eth->h_proto) >= 1536)
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 4f54c9a5e84a..73370de97539 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -19,6 +19,7 @@
#include <linux/atmdev.h>
#include <linux/atmclip.h>
#include <linux/atmarp.h>
+#include <linux/capability.h>
#include <linux/ip.h> /* for net/route.h */
#include <linux/in.h> /* for struct sockaddr_in */
#include <linux/if.h> /* for IFF_UP */
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c
index a150198b05a3..eb109af7eb4a 100644
--- a/net/atm/ioctl.c
+++ b/net/atm/ioctl.c
@@ -12,6 +12,7 @@
#include <linux/atmdev.h>
#include <linux/atmclip.h> /* CLIP_*ENCAP */
#include <linux/atmarp.h> /* manifest constants */
+#include <linux/capability.h>
#include <linux/sonet.h> /* for ioctls */
#include <linux/atmsvc.h>
#include <linux/atmmpc.h>
diff --git a/net/atm/lec.c b/net/atm/lec.c
index ad840b9afba8..c4fc722fef9a 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -7,6 +7,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
/* We are ethernet device */
#include <linux/if_ether.h>
@@ -1321,7 +1322,7 @@ static int lane2_associate_req (struct net_device *dev, u8 *lan_dst,
struct sk_buff *skb;
struct lec_priv *priv = (struct lec_priv*)dev->priv;
- if ( memcmp(lan_dst, dev->dev_addr, ETH_ALEN) != 0 )
+ if (compare_ether_addr(lan_dst, dev->dev_addr))
return (0); /* not our mac address */
kfree(priv->tlvs); /* NULL if there was no previous association */
@@ -1798,7 +1799,7 @@ lec_arp_find(struct lec_priv *priv,
to_return = priv->lec_arp_tables[place];
while(to_return) {
- if (memcmp(mac_addr, to_return->mac_addr, ETH_ALEN) == 0) {
+ if (!compare_ether_addr(mac_addr, to_return->mac_addr)) {
return to_return;
}
to_return = to_return->next;
@@ -1811,8 +1812,7 @@ make_entry(struct lec_priv *priv, unsigned char *mac_addr)
{
struct lec_arp_table *to_return;
- to_return = (struct lec_arp_table *) kmalloc(sizeof(struct lec_arp_table),
- GFP_ATOMIC);
+ to_return = kmalloc(sizeof(struct lec_arp_table), GFP_ATOMIC);
if (!to_return) {
printk("LEC: Arp entry kmalloc failed\n");
return NULL;
@@ -2002,7 +2002,7 @@ lec_arp_resolve(struct lec_priv *priv, unsigned char *mac_to_find,
return priv->mcast_vcc;
break;
case 2: /* LANE2 wants arp for multicast addresses */
- if ( memcmp(mac_to_find, bus_mac, ETH_ALEN) == 0)
+ if (!compare_ether_addr(mac_to_find, bus_mac))
return priv->mcast_vcc;
break;
default:
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 526d9531411f..c304ef1513b9 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -3,6 +3,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/seq_file.h>
/* We are an ethernet device */
@@ -552,7 +553,7 @@ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
goto non_ip; /* Multi-Protocol Over ATM :-) */
while (i < mpc->number_of_mps_macs) {
- if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
+ if (!compare_ether_addr(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN)))
if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
return 0; /* success! */
i++;
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 58f4a2b5aebe..1489067c1e84 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -39,6 +39,7 @@
#include <linux/skbuff.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
+#include <linux/capability.h>
#include <linux/ppp_defs.h>
#include <linux/if_ppp.h>
#include <linux/ppp_channel.h>
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index 2684a92da22b..f2c541774dcd 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -102,7 +102,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
}
-static struct proto_ops pvc_proto_ops = {
+static const struct proto_ops pvc_proto_ops = {
.family = PF_ATMPVC,
.owner = THIS_MODULE,
diff --git a/net/atm/raw.c b/net/atm/raw.c
index 4a0466e91aa6..3e57b17ca523 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/atmdev.h>
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/mm.h>
diff --git a/net/atm/resources.c b/net/atm/resources.c
index c8c459fcb038..224190537c90 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h> /* for barrier */
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <net/sock.h> /* for struct sock */
diff --git a/net/atm/svc.c b/net/atm/svc.c
index d7b266136bf6..3a180cfd7b48 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -613,7 +613,7 @@ static int svc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return error;
}
-static struct proto_ops svc_proto_ops = {
+static const struct proto_ops svc_proto_ops = {
.family = PF_ATMSVC,
.owner = THIS_MODULE,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 1b683f302657..dbf9b47681f7 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -14,6 +14,7 @@
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
*/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -54,7 +55,7 @@
HLIST_HEAD(ax25_list);
DEFINE_SPINLOCK(ax25_list_lock);
-static struct proto_ops ax25_proto_ops;
+static const struct proto_ops ax25_proto_ops;
static void ax25_free_sock(struct sock *sk)
{
@@ -1827,7 +1828,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
default:
- res = dev_ioctl(cmd, argp);
+ res = -ENOIOCTLCMD;
break;
}
release_sock(sk);
@@ -1944,7 +1945,7 @@ static struct net_proto_family ax25_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops ax25_proto_ops = {
+static const struct proto_ops ax25_proto_ops = {
.family = PF_AX25,
.owner = THIS_MODULE,
.release = ax25_release,
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index b1e945bd6ed3..f04f8630fd28 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -11,6 +11,8 @@
* Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
*/
+
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index d53cc8615865..b8b5854bce9a 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -6,6 +6,8 @@
*
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
*/
+
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index ea616e3fc98e..fb031fe9be9e 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -287,10 +287,9 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
timeo = schedule_timeout(timeo);
lock_sock(sk);
- if (sk->sk_err) {
- err = sock_error(sk);
+ err = sock_error(sk);
+ if (err)
break;
- }
}
set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sk_sleep, &wait);
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 682bf20af52d..cbb20c32a6c8 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -75,7 +75,7 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
list_for_each(p, &bnep_session_list) {
s = list_entry(p, struct bnep_session, list);
- if (!memcmp(dst, s->eh.h_source, ETH_ALEN))
+ if (!compare_ether_addr(dst, s->eh.h_source))
return s;
}
return NULL;
@@ -420,10 +420,10 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
iv[il++] = (struct kvec) { &type, 1 };
len++;
- if (!memcmp(eh->h_dest, s->eh.h_source, ETH_ALEN))
+ if (!compare_ether_addr(eh->h_dest, s->eh.h_source))
type |= 0x01;
- if (!memcmp(eh->h_source, s->eh.h_dest, ETH_ALEN))
+ if (!compare_ether_addr(eh->h_source, s->eh.h_dest))
type |= 0x02;
if (type)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 9778c6acd53b..2bfe796cf05d 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -146,7 +147,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return 0;
}
-static struct proto_ops bnep_sock_ops = {
+static const struct proto_ops bnep_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = bnep_sock_release,
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index beb045bf5714..8f8fad23f78a 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -137,7 +138,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
-static struct proto_ops cmtp_sock_ops = {
+static const struct proto_ops cmtp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = cmtp_sock_release,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index a31244e58888..f812ed129e58 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -403,7 +403,7 @@ int hci_get_conn_list(void __user *arg)
size = sizeof(req) + req.conn_num * sizeof(*ci);
- if (!(cl = (void *) kmalloc(size, GFP_KERNEL)))
+ if (!(cl = kmalloc(size, GFP_KERNEL)))
return -ENOMEM;
if (!(hdev = hci_dev_get(req.dev_id))) {
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1d6d0a15c099..bdb6458c6bd5 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -575,7 +576,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char
return 0;
}
-static struct proto_ops hci_sock_ops = {
+static const struct proto_ops hci_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hci_sock_release,
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index bd7568ac87fc..0ed38740388c 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -78,7 +78,7 @@ static struct class_device_attribute *bt_attrs[] = {
};
#ifdef CONFIG_HOTPLUG
-static int bt_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
+static int bt_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
{
struct hci_dev *hdev = class_get_devdata(cdev);
int n, i = 0;
@@ -107,7 +107,7 @@ struct class bt_class = {
.name = "bluetooth",
.release = bt_release,
#ifdef CONFIG_HOTPLUG
- .hotplug = bt_hotplug,
+ .uevent = bt_uevent,
#endif
};
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index f8986f881431..b8f67761b886 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -143,7 +144,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
-static struct proto_ops hidp_sock_ops = {
+static const struct proto_ops hidp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hidp_sock_release,
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index e3bb11ca4235..f6b4a8085357 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -57,7 +58,7 @@
#define VERSION "2.8"
-static struct proto_ops l2cap_sock_ops;
+static const struct proto_ops l2cap_sock_ops;
static struct bt_sock_list l2cap_sk_list = {
.lock = RW_LOCK_UNLOCKED
@@ -767,8 +768,9 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
BT_DBG("sock %p, sk %p", sock, sk);
- if (sk->sk_err)
- return sock_error(sk);
+ err = sock_error(sk);
+ if (err)
+ return err;
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
@@ -2160,7 +2162,7 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL);
-static struct proto_ops l2cap_sock_ops = {
+static const struct proto_ops l2cap_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = l2cap_sock_release,
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 6c34261b232e..757d2dd3b02f 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -58,7 +58,7 @@
#define BT_DBG(D...)
#endif
-static struct proto_ops rfcomm_sock_ops;
+static const struct proto_ops rfcomm_sock_ops;
static struct bt_sock_list rfcomm_sk_list = {
.lock = RW_LOCK_UNLOCKED
@@ -907,7 +907,7 @@ static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf)
static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL);
-static struct proto_ops rfcomm_sock_ops = {
+static const struct proto_ops rfcomm_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = rfcomm_sock_release,
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 158a9c46d863..74368f79ee5d 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -34,6 +34,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
+#include <linux/capability.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
@@ -480,13 +481,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
- register int i;
- for (i = 0; i < skb->len; i++) {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- tty_flip_buffer_push(tty);
-
- tty_insert_flip_char(tty, skb->data[i], 0);
- }
+ tty_buffer_request_room(tty, skb->len);
+ tty_insert_flip_string(tty, skb->data, skb->len);
tty_flip_buffer_push(tty);
} else
tty->ldisc.receive_buf(tty, skb->data, NULL, skb->len);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 9cb00dc6c08c..6b61323ce23c 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -56,7 +56,7 @@
#define VERSION "0.5"
-static struct proto_ops sco_sock_ops;
+static const struct proto_ops sco_sock_ops;
static struct bt_sock_list sco_sk_list = {
.lock = RW_LOCK_UNLOCKED
@@ -637,8 +637,9 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
BT_DBG("sock %p, sk %p", sock, sk);
- if (sk->sk_err)
- return sock_error(sk);
+ err = sock_error(sk);
+ if (err)
+ return err;
if (msg->msg_flags & MSG_OOB)
return -EOPNOTSUPP;
@@ -913,7 +914,7 @@ static ssize_t sco_sysfs_show(struct class *dev, char *buf)
static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL);
-static struct proto_ops sco_sock_ops = {
+static const struct proto_ops sco_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = sco_sock_release,
diff --git a/net/bridge/br.c b/net/bridge/br.c
index f8f184942aaf..188cc1ac49eb 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -67,3 +67,4 @@ EXPORT_SYMBOL(br_should_route_hook);
module_init(br_init)
module_exit(br_deinit)
MODULE_LICENSE("GPL");
+MODULE_VERSION(BR_VERSION);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f564ee99782d..0b33a7b3a00c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -15,7 +15,9 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
-#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+
#include <asm/uaccess.h>
#include "br_private.h"
@@ -82,6 +84,87 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+/* Allow setting mac address of pseudo-bridge to be same as
+ * any of the bound interfaces
+ */
+static int br_set_mac_address(struct net_device *dev, void *p)
+{
+ struct net_bridge *br = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ struct net_bridge_port *port;
+ int err = -EADDRNOTAVAIL;
+
+ spin_lock_bh(&br->lock);
+ list_for_each_entry(port, &br->port_list, list) {
+ if (!compare_ether_addr(port->dev->dev_addr, addr->sa_data)) {
+ br_stp_change_bridge_id(br, addr->sa_data);
+ err = 0;
+ break;
+ }
+ }
+ spin_unlock_bh(&br->lock);
+
+ return err;
+}
+
+static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, "bridge");
+ strcpy(info->version, BR_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, "N/A");
+}
+
+static int br_set_sg(struct net_device *dev, u32 data)
+{
+ struct net_bridge *br = netdev_priv(dev);
+
+ if (data)
+ br->feature_mask |= NETIF_F_SG;
+ else
+ br->feature_mask &= ~NETIF_F_SG;
+
+ br_features_recompute(br);
+ return 0;
+}
+
+static int br_set_tso(struct net_device *dev, u32 data)
+{
+ struct net_bridge *br = netdev_priv(dev);
+
+ if (data)
+ br->feature_mask |= NETIF_F_TSO;
+ else
+ br->feature_mask &= ~NETIF_F_TSO;
+
+ br_features_recompute(br);
+ return 0;
+}
+
+static int br_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct net_bridge *br = netdev_priv(dev);
+
+ if (data)
+ br->feature_mask |= NETIF_F_IP_CSUM;
+ else
+ br->feature_mask &= ~NETIF_F_IP_CSUM;
+
+ br_features_recompute(br);
+ return 0;
+}
+
+static struct ethtool_ops br_ethtool_ops = {
+ .get_drvinfo = br_getinfo,
+ .get_link = ethtool_op_get_link,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = br_set_sg,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = br_set_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = br_set_tso,
+};
+
void br_dev_setup(struct net_device *dev)
{
memset(dev->dev_addr, 0, ETH_ALEN);
@@ -96,8 +179,12 @@ void br_dev_setup(struct net_device *dev)
dev->change_mtu = br_change_mtu;
dev->destructor = free_netdev;
SET_MODULE_OWNER(dev);
+ SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
dev->stop = br_dev_stop;
dev->tx_queue_len = 0;
- dev->set_mac_address = NULL;
+ dev->set_mac_address = br_set_mac_address;
dev->priv_flags = IFF_EBRIDGE;
+
+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
+ | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 975abe254b7a..ba442883e877 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
+#include <linux/if_ether.h>
#include <net/sock.h>
#include "br_private.h"
@@ -32,9 +33,8 @@
* ethtool, use ethtool_ops. Also, since driver might sleep need to
* not be holding any locks.
*/
-static int br_initial_port_cost(struct net_device *dev)
+static int port_cost(struct net_device *dev)
{
-
struct ethtool_cmd ecmd = { ETHTOOL_GSET };
struct ifreq ifr;
mm_segment_t old_fs;
@@ -58,10 +58,6 @@ static int br_initial_port_cost(struct net_device *dev)
return 2;
case SPEED_10:
return 100;
- default:
- pr_info("bridge: can't decode speed from %s: %d\n",
- dev->name, ecmd.speed);
- return 100;
}
}
@@ -75,6 +71,35 @@ static int br_initial_port_cost(struct net_device *dev)
return 100; /* assume old 10Mbps */
}
+
+/*
+ * Check for port carrier transistions.
+ * Called from work queue to allow for calling functions that
+ * might sleep (such as speed check), and to debounce.
+ */
+static void port_carrier_check(void *arg)
+{
+ struct net_bridge_port *p = arg;
+
+ rtnl_lock();
+ if (netif_carrier_ok(p->dev)) {
+ u32 cost = port_cost(p->dev);
+
+ spin_lock_bh(&p->br->lock);
+ if (p->state == BR_STATE_DISABLED) {
+ p->path_cost = cost;
+ br_stp_enable_port(p);
+ }
+ spin_unlock_bh(&p->br->lock);
+ } else {
+ spin_lock_bh(&p->br->lock);
+ if (p->state != BR_STATE_DISABLED)
+ br_stp_disable_port(p);
+ spin_unlock_bh(&p->br->lock);
+ }
+ rtnl_unlock();
+}
+
static void destroy_nbp(struct net_bridge_port *p)
{
struct net_device *dev = p->dev;
@@ -102,6 +127,9 @@ static void del_nbp(struct net_bridge_port *p)
dev->br_port = NULL;
dev_set_promiscuity(dev, -1);
+ cancel_delayed_work(&p->carrier_check);
+ flush_scheduled_work();
+
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
@@ -155,6 +183,7 @@ static struct net_device *new_bridge_dev(const char *name)
br->bridge_id.prio[1] = 0x00;
memset(br->bridge_id.addr, 0, ETH_ALEN);
+ br->feature_mask = dev->features;
br->stp_enabled = 0;
br->designated_root = br->bridge_id;
br->root_path_cost = 0;
@@ -195,10 +224,9 @@ static int find_portno(struct net_bridge *br)
return (index >= BR_MAX_PORTS) ? -EXFULL : index;
}
-/* called with RTNL */
+/* called with RTNL but without bridge lock */
static struct net_bridge_port *new_nbp(struct net_bridge *br,
- struct net_device *dev,
- unsigned long cost)
+ struct net_device *dev)
{
int index;
struct net_bridge_port *p;
@@ -215,12 +243,13 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->br = br;
dev_hold(dev);
p->dev = dev;
- p->path_cost = cost;
+ p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
dev->br_port = p;
p->port_no = index;
br_init_port(p);
p->state = BR_STATE_DISABLED;
+ INIT_WORK(&p->carrier_check, port_carrier_check, p);
kobject_init(&p->kobj);
return p;
@@ -295,7 +324,7 @@ int br_del_bridge(const char *name)
return ret;
}
-/* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */
+/* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */
int br_min_mtu(const struct net_bridge *br)
{
const struct net_bridge_port *p;
@@ -304,7 +333,7 @@ int br_min_mtu(const struct net_bridge *br)
ASSERT_RTNL();
if (list_empty(&br->port_list))
- mtu = 1500;
+ mtu = ETH_DATA_LEN;
else {
list_for_each_entry(p, &br->port_list, list) {
if (!mtu || p->dev->mtu < mtu)
@@ -322,9 +351,8 @@ void br_features_recompute(struct net_bridge *br)
struct net_bridge_port *p;
unsigned long features, checksum;
- features = NETIF_F_SG | NETIF_F_FRAGLIST
- | NETIF_F_HIGHDMA | NETIF_F_TSO;
- checksum = NETIF_F_IP_CSUM; /* least commmon subset */
+ features = br->feature_mask &~ NETIF_F_IP_CSUM;
+ checksum = br->feature_mask & NETIF_F_IP_CSUM;
list_for_each_entry(p, &br->port_list, list) {
if (!(p->dev->features
@@ -351,7 +379,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
if (dev->br_port != NULL)
return -EBUSY;
- if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
+ if (IS_ERR(p = new_nbp(br, dev)))
return PTR_ERR(p);
if ((err = br_fdb_insert(br, p, dev->dev_addr)))
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b88220a64cd8..e3a73cead6b6 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -53,6 +53,11 @@ int br_handle_frame_finish(struct sk_buff *skb)
/* insert into forwarding database after filtering to avoid spoofing */
br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+ if (p->state == BR_STATE_LEARNING) {
+ kfree_skb(skb);
+ goto out;
+ }
+
if (br->dev->flags & IFF_PROMISC) {
struct sk_buff *skb2;
@@ -63,7 +68,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
}
}
- if (dest[0] & 1) {
+ if (is_multicast_ether_addr(dest)) {
br_flood_forward(br, skb, !passedup);
if (!passedup)
br_pass_frame_up(br, skb);
@@ -107,9 +112,6 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
- if (p->state == BR_STATE_LEARNING)
- br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
-
if (p->br->stp_enabled &&
!memcmp(dest, bridge_ula, 5) &&
!(dest[5] & 0xF0)) {
@@ -118,9 +120,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
NULL, br_stp_handle_bpdu);
return 1;
}
+ goto err;
}
- else if (p->state == BR_STATE_FORWARDING) {
+ if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
if (br_should_route_hook) {
if (br_should_route_hook(pskb))
return 0;
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index b8ce14b22181..159fb8409824 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/if_bridge.h>
#include <linux/netdevice.h>
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 23422bd53a5e..7cac3fb9f809 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -26,6 +26,7 @@
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/netfilter_bridge.h>
@@ -33,8 +34,11 @@
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter_arp.h>
#include <linux/in_route.h>
+
#include <net/ip.h>
#include <net/ipv6.h>
+#include <net/route.h>
+
#include <asm/uaccess.h>
#include <asm/checksum.h>
#include "br_private.h"
@@ -390,8 +394,9 @@ inhdr_error:
* target in particular. Save the original destination IP
* address to be able to detect DNAT afterwards. */
static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
- const struct net_device *in, const struct net_device *out,
- int (*okfn)(struct sk_buff *))
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
{
struct iphdr *iph;
__u32 len;
@@ -408,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
goto out;
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+ u8 *vhdr = skb->data;
skb_pull(skb, VLAN_HLEN);
- (skb)->nh.raw += VLAN_HLEN;
+ skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
+ skb->nh.raw += VLAN_HLEN;
}
return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
}
@@ -425,8 +432,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
goto out;
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+ u8 *vhdr = skb->data;
skb_pull(skb, VLAN_HLEN);
- (skb)->nh.raw += VLAN_HLEN;
+ skb_postpull_rcsum(skb, vhdr, VLAN_HLEN);
+ skb->nh.raw += VLAN_HLEN;
}
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 917311c6828b..a43a9c1d50d7 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -52,17 +52,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
br_stp_recalculate_bridge_id(br);
break;
- case NETDEV_CHANGE: /* device is up but carrier changed */
- if (!(br->dev->flags & IFF_UP))
- break;
-
- if (netif_carrier_ok(dev)) {
- if (p->state == BR_STATE_DISABLED)
- br_stp_enable_port(p);
- } else {
- if (p->state != BR_STATE_DISABLED)
- br_stp_disable_port(p);
- }
+ case NETDEV_CHANGE:
+ if (br->dev->flags & IFF_UP)
+ schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
break;
case NETDEV_FEAT_CHANGE:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bdf95a74d8cd..c5bd631ffcd5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -27,6 +27,10 @@
#define BR_PORT_BITS 10
#define BR_MAX_PORTS (1<<BR_PORT_BITS)
+#define BR_PORT_DEBOUNCE (HZ/10)
+
+#define BR_VERSION "2.1"
+
typedef struct bridge_id bridge_id;
typedef struct mac_addr mac_addr;
typedef __u16 port_id;
@@ -78,6 +82,7 @@ struct net_bridge_port
struct timer_list hold_timer;
struct timer_list message_age_timer;
struct kobject kobj;
+ struct work_struct carrier_check;
struct rcu_head rcu;
};
@@ -90,6 +95,7 @@ struct net_bridge
spinlock_t hash_lock;
struct hlist_head hash[BR_HASH_SIZE];
struct list_head age_list;
+ unsigned long feature_mask;
/* STP */
bridge_id designated_root;
@@ -201,6 +207,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
extern void br_stp_enable_port(struct net_bridge_port *p);
extern void br_stp_disable_port(struct net_bridge_port *p);
extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
+extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
extern void br_stp_set_bridge_priority(struct net_bridge *br,
u16 newprio);
extern void br_stp_set_port_priority(struct net_bridge_port *p,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index ac09b6a23523..cc047f7fb6ef 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -120,8 +120,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
}
/* called under bridge lock */
-static void br_stp_change_bridge_id(struct net_bridge *br,
- const unsigned char *addr)
+void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
{
unsigned char oldaddr[6];
struct net_bridge_port *p;
@@ -158,7 +157,7 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
list_for_each_entry(p, &br->port_list, list) {
if (addr == br_mac_zero ||
- compare_ether_addr(p->dev->dev_addr, addr) < 0)
+ memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
addr = p->dev->dev_addr;
}
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 98cf53c81fad..6f577f16c4c0 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -11,6 +11,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index f6a19d53eaeb..0ac0355d16dd 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -11,6 +11,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
@@ -248,7 +249,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
if (err)
goto out2;
- kobject_hotplug(&p->kobj, KOBJ_ADD);
+ kobject_uevent(&p->kobj, KOBJ_ADD);
return 0;
out2:
kobject_del(&p->kobj);
@@ -260,7 +261,7 @@ void br_sysfs_removeif(struct net_bridge_port *p)
{
pr_debug("br_sysfs_removeif\n");
sysfs_remove_link(&p->br->ifobj, p->dev->name);
- kobject_hotplug(&p->kobj, KOBJ_REMOVE);
+ kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
}
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index c70b3be23026..b84fc6075fe1 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -196,9 +196,13 @@ config BRIDGE_EBT_LOG
To compile it as a module, choose M here. If unsure, say N.
config BRIDGE_EBT_ULOG
- tristate "ebt: ulog support"
+ tristate "ebt: ulog support (OBSOLETE)"
depends on BRIDGE_NF_EBTABLES
help
+ This option enables the old bridge-specific "ebt_ulog" implementation
+ which has been obsoleted by the new "nfnetlink_log" code (see
+ CONFIG_NETFILTER_NETLINK_LOG).
+
This option adds the ulog watcher, that you can use in any rule
in any ebtables table. The packet is passed to a userspace
logging daemon using netlink multicast sockets. This differs
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index 7323805b9726..dc5d0b2427cf 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -15,6 +15,7 @@
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_ip.h>
#include <linux/ip.h>
+#include <net/ip.h>
#include <linux/in.h>
#include <linux/module.h>
@@ -51,6 +52,8 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
if (!(info->bitmask & EBT_IP_DPORT) &&
!(info->bitmask & EBT_IP_SPORT))
return EBT_MATCH;
+ if (ntohs(ih->frag_off) & IP_OFFSET)
+ return EBT_NOMATCH;
pptr = skb_header_pointer(skb, ih->ihl*4,
sizeof(_ports), &_ports);
if (pptr == NULL)
@@ -89,7 +92,9 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
if (info->invflags & EBT_IP_PROTO)
return -EINVAL;
if (info->protocol != IPPROTO_TCP &&
- info->protocol != IPPROTO_UDP)
+ info->protocol != IPPROTO_UDP &&
+ info->protocol != IPPROTO_SCTP &&
+ info->protocol != IPPROTO_DCCP)
return -EINVAL;
}
if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 662975be3d1d..0128fbbe2328 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -3,15 +3,19 @@
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
+ * Harald Welte <laforge@netfilter.org>
*
* April, 2002
*
*/
+#include <linux/in.h>
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_log.h>
+#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/ip.h>
+#include <linux/in.h>
#include <linux/if_arp.h>
#include <linux/spinlock.h>
@@ -55,27 +59,30 @@ static void print_MAC(unsigned char *p)
}
#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
-static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
- const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+static void
+ebt_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 *loginfo,
+ const char *prefix)
{
- struct ebt_log_info *info = (struct ebt_log_info *)data;
- char level_string[4] = "< >";
+ unsigned int bitmask;
- level_string[1] = '0' + info->loglevel;
spin_lock_bh(&ebt_log_lock);
- printk(level_string);
- printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "",
- out ? out->name : "");
+ printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
+ prefix, in ? in->name : "", out ? out->name : "");
- printk("MAC source = ");
print_MAC(eth_hdr(skb)->h_source);
printk("MAC dest = ");
print_MAC(eth_hdr(skb)->h_dest);
printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
- if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
+ if (loginfo->type == NF_LOG_TYPE_LOG)
+ bitmask = loginfo->u.log.logflags;
+ else
+ bitmask = NF_LOG_MASK;
+
+ if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
htons(ETH_P_IP)){
struct iphdr _iph, *ih;
@@ -84,12 +91,13 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
printk(" INCOMPLETE IP header");
goto out;
}
- printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
- NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
- printk(" IP tos=0x%02X, IP proto=%d", ih->tos,
- ih->protocol);
+ printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
+ "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
+ NIPQUAD(ih->daddr), ih->tos, ih->protocol);
if (ih->protocol == IPPROTO_TCP ||
- ih->protocol == IPPROTO_UDP) {
+ ih->protocol == IPPROTO_UDP ||
+ ih->protocol == IPPROTO_SCTP ||
+ ih->protocol == IPPROTO_DCCP) {
struct tcpudphdr _ports, *pptr;
pptr = skb_header_pointer(skb, ih->ihl*4,
@@ -104,7 +112,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
goto out;
}
- if ((info->bitmask & EBT_LOG_ARP) &&
+ if ((bitmask & EBT_LOG_ARP) &&
((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
(eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
struct arphdr _arph, *ah;
@@ -144,6 +152,21 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
out:
printk("\n");
spin_unlock_bh(&ebt_log_lock);
+
+}
+
+static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
+ const struct net_device *in, const struct net_device *out,
+ const void *data, unsigned int datalen)
+{
+ struct ebt_log_info *info = (struct ebt_log_info *)data;
+ struct nf_loginfo li;
+
+ li.type = NF_LOG_TYPE_LOG;
+ li.u.log.level = info->loglevel;
+ li.u.log.logflags = info->bitmask;
+
+ nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix);
}
static struct ebt_watcher log =
@@ -154,13 +177,32 @@ static struct ebt_watcher log =
.me = THIS_MODULE,
};
+static struct nf_logger ebt_log_logger = {
+ .name = "ebt_log",
+ .logfn = &ebt_log_packet,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
- return ebt_register_watcher(&log);
+ int ret;
+
+ ret = ebt_register_watcher(&log);
+ if (ret < 0)
+ return ret;
+ if (nf_log_register(PF_BRIDGE, &ebt_log_logger) < 0) {
+ printk(KERN_WARNING "ebt_log: not logging via system console "
+ "since somebody else already registered for PF_INET\n");
+ /* we cannot make module load fail here, since otherwise
+ * ebtables userspace would abort */
+ }
+
+ return 0;
}
static void __exit fini(void)
{
+ nf_log_unregister_logger(&ebt_log_logger);
ebt_unregister_watcher(&log);
}
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index f8a8cdec16ee..0248c67277ee 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -10,6 +10,7 @@
#include <linux/netfilter_bridge/ebtables.h>
#include <linux/netfilter_bridge/ebt_stp.h>
+#include <linux/etherdevice.h>
#include <linux/module.h>
#define BPDU_TYPE_CONFIG 0
@@ -164,8 +165,8 @@ static int ebt_stp_check(const char *tablename, unsigned int hookmask,
if (datalen != len)
return -EINVAL;
/* Make sure the match only receives stp frames */
- if (memcmp(e->destmac, bridge_ula, ETH_ALEN) ||
- memcmp(e->destmsk, msk, ETH_ALEN) || !(e->bitmask & EBT_DESTMAC))
+ if (compare_ether_addr(e->destmac, bridge_ula) ||
+ compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC))
return -EINVAL;
return 0;
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index aae26ae2e61f..ce617b3dbbb8 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -3,6 +3,7 @@
*
* Authors:
* Bart De Schuymer <bdschuym@pandora.be>
+ * Harald Welte <laforge@netfilter.org>
*
* November, 2004
*
@@ -115,14 +116,13 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
return skb;
}
-static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
+static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
- const void *data, unsigned int datalen)
+ const struct ebt_ulog_info *uloginfo, const char *prefix)
{
ebt_ulog_packet_msg_t *pm;
size_t size, copy_len;
struct nlmsghdr *nlh;
- struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
unsigned int group = uloginfo->nlgroup;
ebt_ulog_buff_t *ub = &ulog_buffers[group];
spinlock_t *lock = &ub->lock;
@@ -216,6 +216,39 @@ alloc_failure:
goto unlock;
}
+/* this function is registered with the netfilter core */
+static void ebt_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,
+ const char *prefix)
+{
+ struct ebt_ulog_info loginfo;
+
+ if (!li || li->type != NF_LOG_TYPE_ULOG) {
+ loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
+ loginfo.cprange = 0;
+ loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
+ loginfo.prefix[0] = '\0';
+ } else {
+ loginfo.nlgroup = li->u.ulog.group;
+ loginfo.cprange = li->u.ulog.copy_len;
+ loginfo.qthreshold = li->u.ulog.qthreshold;
+ strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
+ }
+
+ ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
+}
+
+static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
+ const struct net_device *in, const struct net_device *out,
+ const void *data, unsigned int datalen)
+{
+ struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
+
+ ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL);
+}
+
+
static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *data, unsigned int datalen)
{
@@ -240,6 +273,12 @@ static struct ebt_watcher ulog = {
.me = THIS_MODULE,
};
+static struct nf_logger ebt_ulog_logger = {
+ .name = EBT_ULOG_WATCHER,
+ .logfn = &ebt_log_packet,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
int i, ret = 0;
@@ -265,6 +304,13 @@ static int __init init(void)
else if ((ret = ebt_register_watcher(&ulog)))
sock_release(ebtulognl->sk_socket);
+ if (nf_log_register(PF_BRIDGE, &ebt_ulog_logger) < 0) {
+ printk(KERN_WARNING "ebt_ulog: not logging via ulog "
+ "since somebody else already registered for PF_BRIDGE\n");
+ /* we cannot make module load fail here, since otherwise
+ * ebtables userspace would abort */
+ }
+
return ret;
}
@@ -273,6 +319,7 @@ static void __exit fini(void)
ebt_ulog_buff_t *ub;
int i;
+ nf_log_unregister_logger(&ebt_ulog_logger);
ebt_unregister_watcher(&ulog);
for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
ub = &ulog_buffers[i];
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index f8ffbf6e2333..00729b3604f8 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -944,7 +944,7 @@ static int do_replace(void __user *user, unsigned int len)
if (countersize)
memset(newinfo->counters, 0, countersize);
- newinfo->entries = (char *)vmalloc(tmp.entries_size);
+ newinfo->entries = vmalloc(tmp.entries_size);
if (!newinfo->entries) {
ret = -ENOMEM;
goto free_newinfo;
@@ -1146,7 +1146,7 @@ int ebt_register_table(struct ebt_table *table)
if (!newinfo)
return -ENOMEM;
- newinfo->entries = (char *)vmalloc(table->table->entries_size);
+ newinfo->entries = vmalloc(table->table->entries_size);
if (!(newinfo->entries))
goto free_newinfo;
diff --git a/net/core/datagram.c b/net/core/datagram.c
index 1bcfef51ac58..f8d322e1ea92 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -47,6 +47,7 @@
#include <linux/rtnetlink.h>
#include <linux/poll.h>
#include <linux/highmem.h>
+#include <linux/spinlock.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
@@ -200,6 +201,41 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb)
}
/**
+ * skb_kill_datagram - Free a datagram skbuff forcibly
+ * @sk: socket
+ * @skb: datagram skbuff
+ * @flags: MSG_ flags
+ *
+ * This function frees a datagram skbuff that was received by
+ * skb_recv_datagram. The flags argument must match the one
+ * used for skb_recv_datagram.
+ *
+ * If the MSG_PEEK flag is set, and the packet is still on the
+ * receive queue of the socket, it will be taken off the queue
+ * before it is freed.
+ *
+ * This function currently only disables BH when acquiring the
+ * sk_receive_queue lock. Therefore it must not be used in a
+ * context where that lock is acquired in an IRQ context.
+ */
+
+void skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
+{
+ if (flags & MSG_PEEK) {
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ if (skb == skb_peek(&sk->sk_receive_queue)) {
+ __skb_unlink(skb, &sk->sk_receive_queue);
+ atomic_dec(&skb->users);
+ }
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ }
+
+ kfree_skb(skb);
+}
+
+EXPORT_SYMBOL(skb_kill_datagram);
+
+/**
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
* @skb: buffer to copy
* @offset: offset in the buffer to start copying from
diff --git a/net/core/dev.c b/net/core/dev.c
index a5efc9ae010b..fd070a098f20 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -75,6 +75,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/cpu.h>
#include <linux/types.h>
@@ -626,7 +627,7 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas
* Network device names need to be valid file names to
* to allow sysfs to work
*/
-static int dev_valid_name(const char *name)
+int dev_valid_name(const char *name)
{
return !(*name == '\0'
|| !strcmp(name, ".")
@@ -1092,15 +1093,12 @@ int skb_checksum_help(struct sk_buff *skb, int inward)
goto out;
}
- if (offset > (int)skb->len)
- BUG();
+ BUG_ON(offset > (int)skb->len);
csum = skb_checksum(skb, offset, skb->len-offset, 0);
offset = skb->tail - skb->h.raw;
- if (offset <= 0)
- BUG();
- if (skb->csum + 2 > offset)
- BUG();
+ BUG_ON(offset <= 0);
+ BUG_ON(skb->csum + 2 > offset);
*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
skb->ip_summed = CHECKSUM_NONE;
@@ -3270,13 +3268,13 @@ EXPORT_SYMBOL(__dev_get_by_index);
EXPORT_SYMBOL(__dev_get_by_name);
EXPORT_SYMBOL(__dev_remove_pack);
EXPORT_SYMBOL(__skb_linearize);
+EXPORT_SYMBOL(dev_valid_name);
EXPORT_SYMBOL(dev_add_pack);
EXPORT_SYMBOL(dev_alloc_name);
EXPORT_SYMBOL(dev_close);
EXPORT_SYMBOL(dev_get_by_flags);
EXPORT_SYMBOL(dev_get_by_index);
EXPORT_SYMBOL(dev_get_by_name);
-EXPORT_SYMBOL(dev_ioctl);
EXPORT_SYMBOL(dev_open);
EXPORT_SYMBOL(dev_queue_xmit);
EXPORT_SYMBOL(dev_remove_pack);
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index cb530eef0e39..05d60850840e 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -158,7 +158,7 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
int err = 0;
struct dev_mc_list *dmi, *dmi1;
- dmi1 = (struct dev_mc_list *)kmalloc(sizeof(*dmi), GFP_ATOMIC);
+ dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
spin_lock_bh(&dev->xmit_lock);
for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
diff --git a/net/core/dv.c b/net/core/dv.c
index 3f25f4aa4e66..cf581407538c 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -24,6 +24,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <net/dst.h>
@@ -457,7 +458,7 @@ void divert_frame(struct sk_buff *skb)
unsigned char *skb_data_end = skb->data + skb->len;
/* Packet is already aimed at us, return */
- if (!memcmp(eth, skb->dev->dev_addr, ETH_ALEN))
+ if (!compare_ether_addr(eth->h_dest, skb->dev->dev_addr))
return;
/* proto is not IP, do nothing */
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 0350586e9195..e6f76106a99b 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
diff --git a/net/core/filter.c b/net/core/filter.c
index 3a10e0bc90e8..9540946a48f3 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*
* Andi Kleen - Fix a few bad bugs and races.
+ * Kris Katterjohn - Added many additional checks in sk_chk_filter()
*/
#include <linux/module.h>
@@ -73,8 +74,7 @@ static inline void *load_pointer(struct sk_buff *skb, int k,
* filtering, filter is the array of filter instructions, and
* len is the number of filter blocks in the array.
*/
-
-int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
+unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
{
struct sock_filter *fentry; /* We walk down these */
void *ptr;
@@ -174,7 +174,7 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
continue;
case BPF_LD|BPF_W|BPF_ABS:
k = fentry->k;
- load_w:
+load_w:
ptr = load_pointer(skb, k, 4, &tmp);
if (ptr != NULL) {
A = ntohl(*(u32 *)ptr);
@@ -183,7 +183,7 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
break;
case BPF_LD|BPF_H|BPF_ABS:
k = fentry->k;
- load_h:
+load_h:
ptr = load_pointer(skb, k, 2, &tmp);
if (ptr != NULL) {
A = ntohs(*(u16 *)ptr);
@@ -240,9 +240,9 @@ load_b:
A = X;
continue;
case BPF_RET|BPF_K:
- return ((unsigned int)fentry->k);
+ return fentry->k;
case BPF_RET|BPF_A:
- return ((unsigned int)A);
+ return A;
case BPF_ST:
mem[fentry->k] = A;
continue;
@@ -250,7 +250,7 @@ load_b:
mem[fentry->k] = X;
continue;
default:
- /* Invalid instruction counts as RET */
+ WARN_ON(1);
return 0;
}
@@ -283,10 +283,12 @@ load_b:
*
* Check the user's filter code. If we let some ugly
* filter code slip through kaboom! The filter must contain
- * no references or jumps that are out of range, no illegal instructions
- * and no backward jumps. It must end with a RET instruction
+ * no references or jumps that are out of range, no illegal
+ * instructions, and must end with a RET instruction.
*
- * Returns 0 if the rule set is legal or a negative errno code if not.
+ * All jumps are forward as they are not signed.
+ *
+ * Returns 0 if the rule set is legal or -EINVAL if not.
*/
int sk_chk_filter(struct sock_filter *filter, int flen)
{
@@ -298,49 +300,90 @@ int sk_chk_filter(struct sock_filter *filter, int flen)
/* check the filter code now */
for (pc = 0; pc < flen; pc++) {
- /* all jumps are forward as they are not signed */
ftest = &filter[pc];
- if (BPF_CLASS(ftest->code) == BPF_JMP) {
- /* but they mustn't jump off the end */
- if (BPF_OP(ftest->code) == BPF_JA) {
- /*
- * Note, the large ftest->k might cause loops.
- * Compare this with conditional jumps below,
- * where offsets are limited. --ANK (981016)
- */
- if (ftest->k >= (unsigned)(flen-pc-1))
- return -EINVAL;
- } else {
- /* for conditionals both must be safe */
- if (pc + ftest->jt +1 >= flen ||
- pc + ftest->jf +1 >= flen)
- return -EINVAL;
- }
- }
- /* check for division by zero -Kris Katterjohn 2005-10-30 */
- if (ftest->code == (BPF_ALU|BPF_DIV|BPF_K) && ftest->k == 0)
- return -EINVAL;
+ /* Only allow valid instructions */
+ switch (ftest->code) {
+ case BPF_ALU|BPF_ADD|BPF_K:
+ case BPF_ALU|BPF_ADD|BPF_X:
+ case BPF_ALU|BPF_SUB|BPF_K:
+ case BPF_ALU|BPF_SUB|BPF_X:
+ case BPF_ALU|BPF_MUL|BPF_K:
+ case BPF_ALU|BPF_MUL|BPF_X:
+ case BPF_ALU|BPF_DIV|BPF_X:
+ case BPF_ALU|BPF_AND|BPF_K:
+ case BPF_ALU|BPF_AND|BPF_X:
+ case BPF_ALU|BPF_OR|BPF_K:
+ case BPF_ALU|BPF_OR|BPF_X:
+ case BPF_ALU|BPF_LSH|BPF_K:
+ case BPF_ALU|BPF_LSH|BPF_X:
+ case BPF_ALU|BPF_RSH|BPF_K:
+ case BPF_ALU|BPF_RSH|BPF_X:
+ case BPF_ALU|BPF_NEG:
+ case BPF_LD|BPF_W|BPF_ABS:
+ case BPF_LD|BPF_H|BPF_ABS:
+ case BPF_LD|BPF_B|BPF_ABS:
+ case BPF_LD|BPF_W|BPF_LEN:
+ case BPF_LD|BPF_W|BPF_IND:
+ case BPF_LD|BPF_H|BPF_IND:
+ case BPF_LD|BPF_B|BPF_IND:
+ case BPF_LD|BPF_IMM:
+ case BPF_LDX|BPF_W|BPF_LEN:
+ case BPF_LDX|BPF_B|BPF_MSH:
+ case BPF_LDX|BPF_IMM:
+ case BPF_MISC|BPF_TAX:
+ case BPF_MISC|BPF_TXA:
+ case BPF_RET|BPF_K:
+ case BPF_RET|BPF_A:
+ break;
+
+ /* Some instructions need special checks */
- /* check that memory operations use valid addresses. */
- if (ftest->k >= BPF_MEMWORDS) {
- /* but it might not be a memory operation... */
- switch (ftest->code) {
- case BPF_ST:
- case BPF_STX:
- case BPF_LD|BPF_MEM:
- case BPF_LDX|BPF_MEM:
+ case BPF_ALU|BPF_DIV|BPF_K:
+ /* check for division by zero */
+ if (ftest->k == 0)
return -EINVAL;
- }
+ break;
+
+ case BPF_LD|BPF_MEM:
+ case BPF_LDX|BPF_MEM:
+ case BPF_ST:
+ case BPF_STX:
+ /* check for invalid memory addresses */
+ if (ftest->k >= BPF_MEMWORDS)
+ return -EINVAL;
+ break;
+
+ case BPF_JMP|BPF_JA:
+ /*
+ * Note, the large ftest->k might cause loops.
+ * Compare this with conditional jumps below,
+ * where offsets are limited. --ANK (981016)
+ */
+ if (ftest->k >= (unsigned)(flen-pc-1))
+ return -EINVAL;
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ case BPF_JMP|BPF_JGE|BPF_K:
+ case BPF_JMP|BPF_JGE|BPF_X:
+ case BPF_JMP|BPF_JGT|BPF_K:
+ case BPF_JMP|BPF_JGT|BPF_X:
+ case BPF_JMP|BPF_JSET|BPF_K:
+ case BPF_JMP|BPF_JSET|BPF_X:
+ /* for conditionals both must be safe */
+ if (pc + ftest->jt + 1 >= flen ||
+ pc + ftest->jf + 1 >= flen)
+ return -EINVAL;
+ break;
+
+ default:
+ return -EINVAL;
}
}
- /*
- * The program must end with a return. We don't care where they
- * jumped within the script (its always forwards) but in the end
- * they _will_ hit this.
- */
- return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
+ return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL;
}
/**
@@ -360,8 +403,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
int err;
/* Make sure new filter is there and in the right amounts. */
- if (fprog->filter == NULL)
- return -EINVAL;
+ if (fprog->filter == NULL)
+ return -EINVAL;
fp = sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL);
if (!fp)
diff --git a/net/core/flow.c b/net/core/flow.c
index 7e95b39de9fd..c4f25385029f 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -23,6 +23,7 @@
#include <net/flow.h>
#include <asm/atomic.h>
#include <asm/semaphore.h>
+#include <linux/security.h>
struct flow_cache_entry {
struct flow_cache_entry *next;
@@ -30,6 +31,7 @@ struct flow_cache_entry {
u8 dir;
struct flowi key;
u32 genid;
+ u32 sk_sid;
void *object;
atomic_t *object_ref;
};
@@ -162,7 +164,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
return 0;
}
-void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
flow_resolve_t resolver)
{
struct flow_cache_entry *fle, **head;
@@ -186,6 +188,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
for (fle = *head; fle; fle = fle->next) {
if (fle->family == family &&
fle->dir == dir &&
+ fle->sk_sid == sk_sid &&
flow_key_compare(key, &fle->key) == 0) {
if (fle->genid == atomic_read(&flow_cache_genid)) {
void *ret = fle->object;
@@ -210,6 +213,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
*head = fle;
fle->family = family;
fle->dir = dir;
+ fle->sk_sid = sk_sid;
memcpy(&fle->key, key, sizeof(*key));
fle->object = NULL;
flow_count(cpu)++;
@@ -221,7 +225,7 @@ nocache:
void *obj;
atomic_t *obj_ref;
- resolver(key, family, dir, &obj, &obj_ref);
+ resolver(key, sk_sid, family, dir, &obj, &obj_ref);
if (fle) {
fle->genid = atomic_read(&flow_cache_genid);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index e2137f3e489d..e8b2acbc8ea2 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -9,6 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
@@ -16,6 +17,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
+#include <net/iw_handler.h>
#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
#define to_net_dev(class) container_of(class, struct net_device, class_dev)
@@ -84,16 +86,11 @@ static ssize_t netdev_store(struct class_device *dev,
return ret;
}
-/* generate a read-only network device class attribute */
-#define NETDEVICE_ATTR(field, format_string) \
-NETDEVICE_SHOW(field, format_string) \
-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \
-
-NETDEVICE_ATTR(addr_len, fmt_dec);
-NETDEVICE_ATTR(iflink, fmt_dec);
-NETDEVICE_ATTR(ifindex, fmt_dec);
-NETDEVICE_ATTR(features, fmt_long_hex);
-NETDEVICE_ATTR(type, fmt_dec);
+NETDEVICE_SHOW(addr_len, fmt_dec);
+NETDEVICE_SHOW(iflink, fmt_dec);
+NETDEVICE_SHOW(ifindex, fmt_dec);
+NETDEVICE_SHOW(features, fmt_long_hex);
+NETDEVICE_SHOW(type, fmt_dec);
/* use same locking rules as GIFHWADDR ioctl's */
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
@@ -136,10 +133,6 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
return -EINVAL;
}
-static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
-static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
-static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
-
/* read-write attributes */
NETDEVICE_SHOW(mtu, fmt_dec);
@@ -153,8 +146,6 @@ static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
return netdev_store(dev, buf, len, change_mtu);
}
-static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
-
NETDEVICE_SHOW(flags, fmt_hex);
static int change_flags(struct net_device *net, unsigned long new_flags)
@@ -167,8 +158,6 @@ static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len
return netdev_store(dev, buf, len, change_flags);
}
-static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
-
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
@@ -182,9 +171,6 @@ static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, siz
return netdev_store(dev, buf, len, change_tx_queue_len);
}
-static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
- store_tx_queue_len);
-
NETDEVICE_SHOW(weight, fmt_dec);
static int change_weight(struct net_device *net, unsigned long new_weight)
@@ -198,24 +184,21 @@ static ssize_t store_weight(struct class_device *dev, const char *buf, size_t le
return netdev_store(dev, buf, len, change_weight);
}
-static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight,
- store_weight);
-
-
-static struct class_device_attribute *net_class_attributes[] = {
- &class_device_attr_ifindex,
- &class_device_attr_iflink,
- &class_device_attr_addr_len,
- &class_device_attr_tx_queue_len,
- &class_device_attr_features,
- &class_device_attr_mtu,
- &class_device_attr_flags,
- &class_device_attr_weight,
- &class_device_attr_type,
- &class_device_attr_address,
- &class_device_attr_broadcast,
- &class_device_attr_carrier,
- NULL
+static struct class_device_attribute net_class_attributes[] = {
+ __ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
+ __ATTR(iflink, S_IRUGO, show_iflink, NULL),
+ __ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
+ __ATTR(features, S_IRUGO, show_features, NULL),
+ __ATTR(type, S_IRUGO, show_type, NULL),
+ __ATTR(address, S_IRUGO, show_address, NULL),
+ __ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
+ __ATTR(carrier, S_IRUGO, show_carrier, NULL),
+ __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
+ __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
+ __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
+ store_tx_queue_len),
+ __ATTR(weight, S_IRUGO | S_IWUSR, show_weight, store_weight),
+ {}
};
/* Show a given an attribute in the statistics group */
@@ -313,13 +296,19 @@ static ssize_t wireless_show(struct class_device *cd, char *buf,
char *))
{
struct net_device *dev = to_net_dev(cd);
- const struct iw_statistics *iw;
+ const struct iw_statistics *iw = NULL;
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
- if (dev_isalive(dev) && dev->get_wireless_stats
- && (iw = dev->get_wireless_stats(dev)) != NULL)
- ret = (*format)(iw, buf);
+ if (dev_isalive(dev)) {
+ if(dev->wireless_handlers &&
+ dev->wireless_handlers->get_wireless_stats)
+ iw = dev->wireless_handlers->get_wireless_stats(dev);
+ else if (dev->get_wireless_stats)
+ iw = dev->get_wireless_stats(dev);
+ if (iw != NULL)
+ ret = (*format)(iw, buf);
+ }
read_unlock(&dev_base_lock);
return ret;
@@ -369,14 +358,14 @@ static struct attribute_group wireless_group = {
#endif
#ifdef CONFIG_HOTPLUG
-static int netdev_hotplug(struct class_device *cd, char **envp,
- int num_envp, char *buf, int size)
+static int netdev_uevent(struct class_device *cd, char **envp,
+ int num_envp, char *buf, int size)
{
struct net_device *dev = to_net_dev(cd);
int i = 0;
int n;
- /* pass interface in env to hotplug. */
+ /* pass interface to uevent. */
envp[i++] = buf;
n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1;
buf += n;
@@ -407,8 +396,9 @@ static void netdev_release(struct class_device *cd)
static struct class net_class = {
.name = "net",
.release = netdev_release,
+ .class_dev_attrs = net_class_attributes,
#ifdef CONFIG_HOTPLUG
- .hotplug = netdev_hotplug,
+ .uevent = netdev_uevent,
#endif
};
@@ -420,7 +410,8 @@ void netdev_unregister_sysfs(struct net_device * net)
sysfs_remove_group(&class_dev->kobj, &netstat_group);
#ifdef WIRELESS_EXT
- if (net->get_wireless_stats)
+ if (net->get_wireless_stats || (net->wireless_handlers &&
+ net->wireless_handlers->get_wireless_stats))
sysfs_remove_group(&class_dev->kobj, &wireless_group);
#endif
class_device_del(class_dev);
@@ -431,8 +422,6 @@ void netdev_unregister_sysfs(struct net_device * net)
int netdev_register_sysfs(struct net_device *net)
{
struct class_device *class_dev = &(net->class_dev);
- int i;
- struct class_device_attribute *attr;
int ret;
class_dev->class = &net_class;
@@ -442,21 +431,17 @@ int netdev_register_sysfs(struct net_device *net)
if ((ret = class_device_register(class_dev)))
goto out;
- for (i = 0; (attr = net_class_attributes[i]) != NULL; i++) {
- if ((ret = class_device_create_file(class_dev, attr)))
- goto out_unreg;
- }
-
-
if (net->get_stats &&
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
goto out_unreg;
#ifdef WIRELESS_EXT
- if (net->get_wireless_stats &&
- (ret = sysfs_create_group(&class_dev->kobj, &wireless_group)))
- goto out_cleanup;
-
+ if (net->get_wireless_stats || (net->wireless_handlers &&
+ net->wireless_handlers->get_wireless_stats)) {
+ ret = sysfs_create_group(&class_dev->kobj, &wireless_group);
+ if (ret)
+ goto out_cleanup;
+ }
return 0;
out_cleanup:
if (net->get_stats)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 49424a42a2c0..ea51f8d02eb8 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -13,6 +13,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/string.h>
+#include <linux/if_arp.h>
#include <linux/inetdevice.h>
#include <linux/inet.h>
#include <linux/interrupt.h>
@@ -702,7 +703,7 @@ int netpoll_setup(struct netpoll *np)
}
}
- if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr)
+ if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr)
memcpy(np->local_mac, ndev->dev_addr, 6);
if (!np->local_ip) {
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 7fc3e9e28c34..da16f8fd1494 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -116,13 +116,13 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/sched.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/init.h>
@@ -139,6 +139,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/wait.h>
+#include <linux/etherdevice.h>
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
@@ -281,8 +282,8 @@ struct pktgen_dev {
__u32 src_mac_count; /* How many MACs to iterate through */
__u32 dst_mac_count; /* How many MACs to iterate through */
- unsigned char dst_mac[6];
- unsigned char src_mac[6];
+ unsigned char dst_mac[ETH_ALEN];
+ unsigned char src_mac[ETH_ALEN];
__u32 cur_dst_mac_offset;
__u32 cur_src_mac_offset;
@@ -473,7 +474,6 @@ static char version[] __initdata = VERSION;
static int pktgen_remove_device(struct pktgen_thread* t, struct pktgen_dev *i);
static int pktgen_add_device(struct pktgen_thread* t, const char* ifname);
-static struct pktgen_thread* pktgen_find_thread(const char* name);
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread* t, const char* ifname);
static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
static void pktgen_run_all_threads(void);
@@ -487,9 +487,9 @@ static unsigned int fmt_ip6(char *s,const char ip[16]);
/* Module parameters, defaults. */
static int pg_count_d = 1000; /* 1000 pkts by default */
-static int pg_delay_d = 0;
-static int pg_clone_skb_d = 0;
-static int debug = 0;
+static int pg_delay_d;
+static int pg_clone_skb_d;
+static int debug;
static DECLARE_MUTEX(pktgen_sem);
static struct pktgen_thread *pktgen_threads = NULL;
@@ -595,16 +595,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
seq_puts(seq, " src_mac: ");
- if ((pkt_dev->src_mac[0] == 0) &&
- (pkt_dev->src_mac[1] == 0) &&
- (pkt_dev->src_mac[2] == 0) &&
- (pkt_dev->src_mac[3] == 0) &&
- (pkt_dev->src_mac[4] == 0) &&
- (pkt_dev->src_mac[5] == 0))
-
+ if (is_zero_ether_addr(pkt_dev->src_mac))
for (i = 0; i < 6; i++)
seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? " " : ":");
-
else
for (i = 0; i < 6; i++)
seq_printf(seq, "%02X%s", pkt_dev->src_mac[i], i == 5 ? " " : ":");
@@ -1190,9 +1183,9 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
}
if (!strcmp(name, "dst_mac")) {
char *v = valstr;
- unsigned char old_dmac[6];
+ unsigned char old_dmac[ETH_ALEN];
unsigned char *m = pkt_dev->dst_mac;
- memcpy(old_dmac, pkt_dev->dst_mac, 6);
+ memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN);
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
if (len < 0) { return len; }
@@ -1221,8 +1214,8 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer
}
/* Set up Dest MAC */
- if (memcmp(old_dmac, pkt_dev->dst_mac, 6) != 0)
- memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
+ if (compare_ether_addr(old_dmac, pkt_dev->dst_mac))
+ memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
sprintf(pg_result, "OK: dstmac");
return count;
@@ -1561,17 +1554,11 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
/* Default to the interface's mac if not explicitly set. */
- if ((pkt_dev->src_mac[0] == 0) &&
- (pkt_dev->src_mac[1] == 0) &&
- (pkt_dev->src_mac[2] == 0) &&
- (pkt_dev->src_mac[3] == 0) &&
- (pkt_dev->src_mac[4] == 0) &&
- (pkt_dev->src_mac[5] == 0)) {
+ if (is_zero_ether_addr(pkt_dev->src_mac))
+ memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN);
- memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, 6);
- }
/* Set up Dest MAC */
- memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6);
+ memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
/* Set up pkt size */
pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size;
@@ -1873,13 +1860,14 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
*/
mod_cur_headers(pkt_dev);
- skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
+ datalen = (odev->hard_header_len + 16) & ~0xf;
+ skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC);
if (!skb) {
sprintf(pkt_dev->result, "No memory");
return NULL;
}
- skb_reserve(skb, 16);
+ skb_reserve(skb, datalen);
/* Reserve for ethernet and IP header */
eth = (__u8 *) skb_push(skb, 14);
@@ -2883,7 +2871,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char* ifname)
return add_dev_to_thread(t, pkt_dev);
}
-static struct pktgen_thread *pktgen_find_thread(const char* name)
+static struct pktgen_thread * __init pktgen_find_thread(const char* name)
{
struct pktgen_thread *t = NULL;
@@ -2900,7 +2888,7 @@ static struct pktgen_thread *pktgen_find_thread(const char* name)
return t;
}
-static int pktgen_create_thread(const char* name, int cpu)
+static int __init pktgen_create_thread(const char* name, int cpu)
{
struct pktgen_thread *t = NULL;
struct proc_dir_entry *pe;
diff --git a/net/core/scm.c b/net/core/scm.c
index e887d19be506..649d01ef35b6 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/signal.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 83fee37de38e..d0732e9c8560 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -135,17 +135,13 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here)
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
int fclone)
{
+ struct skb_shared_info *shinfo;
struct sk_buff *skb;
u8 *data;
/* Get the HEAD */
- 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);
-
+ skb = kmem_cache_alloc(fclone ? skbuff_fclone_cache : skbuff_head_cache,
+ gfp_mask & ~__GFP_DMA);
if (!skb)
goto out;
@@ -162,6 +158,16 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
skb->data = data;
skb->tail = data;
skb->end = data + size;
+ /* make sure we initialize shinfo sequentially */
+ shinfo = skb_shinfo(skb);
+ atomic_set(&shinfo->dataref, 1);
+ shinfo->nr_frags = 0;
+ shinfo->tso_size = 0;
+ shinfo->tso_segs = 0;
+ shinfo->ufo_size = 0;
+ shinfo->ip6_frag_id = 0;
+ shinfo->frag_list = NULL;
+
if (fclone) {
struct sk_buff *child = skb + 1;
atomic_t *fclone_ref = (atomic_t *) (child + 1);
@@ -171,13 +177,6 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
child->fclone = SKB_FCLONE_UNAVAILABLE;
}
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->tso_size = 0;
- skb_shinfo(skb)->tso_segs = 0;
- skb_shinfo(skb)->frag_list = NULL;
- skb_shinfo(skb)->ufo_size = 0;
- skb_shinfo(skb)->ip6_frag_id = 0;
out:
return skb;
nodata:
@@ -792,8 +791,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
int end = offset + skb_shinfo(skb)->frags[i].size;
if (end > len) {
if (skb_cloned(skb)) {
- if (!realloc)
- BUG();
+ BUG_ON(!realloc);
if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
return -ENOMEM;
}
@@ -895,8 +893,7 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta)
struct sk_buff *insp = NULL;
do {
- if (!list)
- BUG();
+ BUG_ON(!list);
if (list->len <= eat) {
/* Eaten as whole. */
@@ -1200,8 +1197,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset,
start = end;
}
}
- if (len)
- BUG();
+ BUG_ON(len);
return csum;
}
@@ -1283,8 +1279,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
start = end;
}
}
- if (len)
- BUG();
+ BUG_ON(len);
return csum;
}
@@ -1298,8 +1293,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
else
csstart = skb_headlen(skb);
- if (csstart > skb_headlen(skb))
- BUG();
+ BUG_ON(csstart > skb_headlen(skb));
memcpy(to, skb->data, csstart);
diff --git a/net/core/sock.c b/net/core/sock.c
index 13cc3be4f056..6e00811d44bc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -91,6 +91,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -1488,7 +1489,7 @@ int proto_register(struct proto *prot, int alloc_slab)
}
}
- if (prot->twsk_obj_size) {
+ if (prot->twsk_prot != NULL) {
static const char mask[] = "tw_sock_%s";
timewait_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
@@ -1497,11 +1498,12 @@ int proto_register(struct proto *prot, int alloc_slab)
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)
+ prot->twsk_prot->twsk_slab =
+ kmem_cache_create(timewait_sock_slab_name,
+ prot->twsk_prot->twsk_obj_size,
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (prot->twsk_prot->twsk_slab == NULL)
goto out_free_timewait_sock_slab_name;
}
}
@@ -1548,12 +1550,12 @@ void proto_unregister(struct proto *prot)
prot->rsk_prot->slab = NULL;
}
- if (prot->twsk_slab != NULL) {
- const char *name = kmem_cache_name(prot->twsk_slab);
+ if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) {
+ const char *name = kmem_cache_name(prot->twsk_prot->twsk_slab);
- kmem_cache_destroy(prot->twsk_slab);
+ kmem_cache_destroy(prot->twsk_prot->twsk_slab);
kfree(name);
- prot->twsk_slab = NULL;
+ prot->twsk_prot->twsk_slab = NULL;
}
}
diff --git a/net/core/stream.c b/net/core/stream.c
index 15bfd03e8024..35e25259fd95 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -55,8 +55,9 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
int done;
do {
- if (sk->sk_err)
- return sock_error(sk);
+ int err = sock_error(sk);
+ if (err)
+ return err;
if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV))
return -EPIPE;
if (!*timeo_p)
@@ -67,6 +68,7 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
sk->sk_write_pending++;
done = sk_wait_event(sk, timeo_p,
+ !sk->sk_err &&
!((1 << sk->sk_state) &
~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)));
finish_wait(sk->sk_sleep, &wait);
@@ -137,7 +139,9 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p)
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
sk->sk_write_pending++;
- sk_wait_event(sk, &current_timeo, sk_stream_memory_free(sk) &&
+ sk_wait_event(sk, &current_timeo, !sk->sk_err &&
+ !(sk->sk_shutdown & SEND_SHUTDOWN) &&
+ sk_stream_memory_free(sk) &&
vm_wait);
sk->sk_write_pending--;
diff --git a/net/core/utils.c b/net/core/utils.c
index 7b5970fc9e40..ac1d1fcf8673 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -162,7 +162,7 @@ EXPORT_SYMBOL(net_srandom);
* is otherwise not dependent on the TCP/IP stack.
*/
-__u32 in_aton(const char *str)
+__be32 in_aton(const char *str)
{
unsigned long l;
unsigned int val;
@@ -175,7 +175,7 @@ __u32 in_aton(const char *str)
if (*str != '\0')
{
val = 0;
- while (*str != '\0' && *str != '.')
+ while (*str != '\0' && *str != '.' && *str != '\n')
{
val *= 10;
val += *str - '0';
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 271ddb35b0b2..2add7ed609e9 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -78,6 +78,7 @@
#include <linux/seq_file.h>
#include <linux/init.h> /* for __init */
#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <linux/etherdevice.h> /* compare_ether_addr */
#include <linux/wireless.h> /* Pretty obvious */
#include <net/iw_handler.h> /* New driver API */
@@ -1506,7 +1507,7 @@ void wireless_spy_update(struct net_device * dev,
/* Update all records that match */
for(i = 0; i < spydata->spy_number; i++)
- if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
+ if(!compare_ether_addr(address, spydata->spy_address[i])) {
memcpy(&(spydata->spy_stat[i]), wstats,
sizeof(struct iw_quality));
match = i;
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 344a8da153fc..87b27fff6e3b 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -1,3 +1,7 @@
+obj-$(CONFIG_IPV6) += dccp_ipv6.o
+
+dccp_ipv6-y := ipv6.o
+
obj-$(CONFIG_IP_DCCP) += dccp.o
dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c
index c9a62cca22fc..2c77dafbd091 100644
--- a/net/dccp/ackvec.c
+++ b/net/dccp/ackvec.c
@@ -55,8 +55,8 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
from = av->dccpav_buf + av->dccpav_buf_head;
/* Check if buf_head wraps */
- if (av->dccpav_buf_head + len > av->dccpav_vec_len) {
- const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head);
+ if ((int)av->dccpav_buf_head + len > av->dccpav_vec_len) {
+ const u32 tailsize = av->dccpav_vec_len - av->dccpav_buf_head;
memcpy(to, from, tailsize);
to += tailsize;
@@ -93,8 +93,14 @@ int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb)
struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len,
const gfp_t priority)
{
- struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority);
+ struct dccp_ackvec *av;
+ BUG_ON(len == 0);
+
+ if (len > DCCP_MAX_ACKVEC_LEN)
+ return NULL;
+
+ av = kmalloc(sizeof(*av) + len, priority);
if (av != NULL) {
av->dccpav_buf_len = len;
av->dccpav_buf_head =
@@ -117,13 +123,13 @@ void dccp_ackvec_free(struct dccp_ackvec *av)
}
static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av,
- const unsigned int index)
+ const u8 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK;
}
static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
- const unsigned int index)
+ const u8 index)
{
return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK;
}
@@ -135,10 +141,10 @@ static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av,
*/
static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av,
const unsigned int packets,
- const unsigned char state)
+ const unsigned char state)
{
unsigned int gap;
- signed long new_head;
+ long new_head;
if (av->dccpav_vec_len + packets > av->dccpav_buf_len)
return -ENOBUFS;
@@ -223,7 +229,7 @@ int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk,
* could reduce the complexity of this scan.)
*/
u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno);
- unsigned int index = av->dccpav_buf_head;
+ u8 index = av->dccpav_buf_head;
while (1) {
const u8 len = dccp_ackvec_len(av, index);
@@ -291,7 +297,7 @@ void dccp_ackvec_print(const struct dccp_ackvec *av)
}
#endif
-static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av)
+static void dccp_ackvec_throw_away_ack_record(struct dccp_ackvec *av)
{
/*
* As we're keeping track of the ack vector size (dccpav_vec_len) and
@@ -301,9 +307,10 @@ static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av)
* draft-ietf-dccp-spec-11.txt Appendix A. -acme
*/
#if 0
- av->dccpav_buf_tail = av->dccpav_ack_ptr + 1;
- if (av->dccpav_buf_tail >= av->dccpav_vec_len)
- av->dccpav_buf_tail -= av->dccpav_vec_len;
+ u32 new_buf_tail = av->dccpav_ack_ptr + 1;
+ if (new_buf_tail >= av->dccpav_vec_len)
+ new_buf_tail -= av->dccpav_vec_len;
+ av->dccpav_buf_tail = new_buf_tail;
#endif
av->dccpav_vec_len -= av->dccpav_sent_len;
}
@@ -326,7 +333,7 @@ void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk,
debug_prefix, 1,
(unsigned long long)av->dccpav_ack_seqno,
(unsigned long long)av->dccpav_ack_ackno);
- dccp_ackvec_trow_away_ack_record(av);
+ dccp_ackvec_throw_away_ack_record(av);
av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1;
}
}
@@ -389,7 +396,7 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av,
av->dccpav_ack_seqno,
(unsigned long long)
av->dccpav_ack_ackno);
- dccp_ackvec_trow_away_ack_record(av);
+ dccp_ackvec_throw_away_ack_record(av);
}
/*
* If dccpav_ack_seqno was not received, no problem
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h
index d0fd6c60c574..f7dfb5f67b87 100644
--- a/net/dccp/ackvec.h
+++ b/net/dccp/ackvec.h
@@ -54,16 +54,16 @@
* @dccpav_buf - circular buffer of acknowledgeable packets
*/
struct dccp_ackvec {
- unsigned int dccpav_buf_head;
- unsigned int dccpav_buf_tail;
u64 dccpav_buf_ackno;
u64 dccpav_ack_seqno;
u64 dccpav_ack_ackno;
- unsigned int dccpav_ack_ptr;
- unsigned int dccpav_sent_len;
- unsigned int dccpav_vec_len;
- unsigned int dccpav_buf_len;
struct timeval dccpav_time;
+ u8 dccpav_buf_head;
+ u8 dccpav_buf_tail;
+ u8 dccpav_ack_ptr;
+ u8 dccpav_sent_len;
+ u8 dccpav_vec_len;
+ u8 dccpav_buf_len;
u8 dccpav_buf_nonce;
u8 dccpav_ack_nonce;
u8 dccpav_buf[0];
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index c37eeeaf5c6e..de681c6ad081 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -21,6 +21,8 @@
#define CCID_MAX 255
+struct tcp_info;
+
struct ccid {
unsigned char ccid_id;
const char *ccid_name;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index f97b85d55ad8..93f26dd6e6cb 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -59,7 +59,7 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
-extern struct proto dccp_v4_prot;
+extern struct proto dccp_prot;
/* is seq1 < seq2 ? */
static inline int before48(const u64 seq1, const u64 seq2)
@@ -228,6 +228,9 @@ extern int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
extern int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct dccp_hdr *dh, const unsigned len);
+extern int dccp_v4_init_sock(struct sock *sk);
+extern int dccp_v4_destroy_sock(struct sock *sk);
+
extern void dccp_close(struct sock *sk, long timeout);
extern struct sk_buff *dccp_make_response(struct sock *sk,
struct dst_entry *dst,
@@ -238,6 +241,7 @@ extern struct sk_buff *dccp_make_reset(struct sock *sk,
extern int dccp_connect(struct sock *sk);
extern int dccp_disconnect(struct sock *sk, int flags);
+extern void dccp_unhash(struct sock *sk);
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,
@@ -249,6 +253,13 @@ 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 inet_dccp_listen(struct socket *sock, int backlog);
+extern unsigned int dccp_poll(struct file *file, struct socket *sock,
+ poll_table *wait);
+extern void dccp_v4_send_check(struct sock *sk, int len,
+ struct sk_buff *skb);
+extern int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len);
extern int dccp_v4_checksum(const struct sk_buff *skb,
const u32 saddr, const u32 daddr);
@@ -256,6 +267,17 @@ extern int dccp_v4_checksum(const struct sk_buff *skb,
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);
+extern int dccp_invalid_packet(struct sk_buff *skb);
+
+static inline int dccp_bad_service_code(const struct sock *sk,
+ const __u32 service)
+{
+ const struct dccp_sock *dp = dccp_sk(sk);
+
+ if (dp->dccps_service == service)
+ return 0;
+ return !dccp_list_has_service(dp->dccps_service_list, service);
+}
struct dccp_skb_cb {
__u8 dccpd_type:4;
diff --git a/net/dccp/diag.c b/net/dccp/diag.c
index f675d8e642d3..3f78c00e3822 100644
--- a/net/dccp/diag.c
+++ b/net/dccp/diag.c
@@ -28,7 +28,7 @@ static void dccp_get_info(struct sock *sk, struct tcp_info *info)
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;
+ info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
if (dp->dccps_options.dccpo_send_ack_vector)
info->tcpi_options |= TCPI_OPT_SACK;
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 3454d5941900..b6cba72b44e8 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -151,29 +151,12 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
return 0;
}
-int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
- const struct dccp_hdr *dh, const unsigned len)
+static inline 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);
-
- if (dp->dccps_options.dccpo_send_ack_vector &&
- dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
- DCCP_SKB_CB(skb)->dccpd_seq,
- DCCP_ACKVEC_STATE_RECEIVED))
- goto discard;
-
- 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:
@@ -250,6 +233,37 @@ discard:
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);
+
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKVEC_STATE_RECEIVED))
+ goto discard;
+
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
+
+ return __dccp_rcv_established(sk, skb, dh, len);
+discard:
+ __kfree_skb(skb);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rcv_established);
+
static int dccp_rcv_request_sent_state_process(struct sock *sk,
struct sk_buff *skb,
const struct dccp_hdr *dh,
@@ -286,6 +300,12 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
goto out_invalid_packet;
}
+ if (dp->dccps_options.dccpo_send_ack_vector &&
+ dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
+ DCCP_SKB_CB(skb)->dccpd_seq,
+ DCCP_ACKVEC_STATE_RECEIVED))
+ goto out_invalid_packet; /* FIXME: change error code */
+
dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;
dccp_update_gsr(sk, dp->dccps_isr);
/*
@@ -309,7 +329,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
goto out_invalid_packet;
}
- dccp_sync_mss(sk, dp->dccps_pmtu_cookie);
+ dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);
/*
* Step 10: Process REQUEST state (second part)
@@ -329,7 +349,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk,
dccp_set_state(sk, DCCP_PARTOPEN);
/* Make sure socket is routed, for correct metrics. */
- inet_sk_rebuild_header(sk);
+ icsk->icsk_af_ops->rebuild_header(sk);
if (!sock_flag(sk, SOCK_DEAD)) {
sk->sk_state_change(sk);
@@ -398,9 +418,9 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
if (dh->dccph_type == DCCP_PKT_DATAACK ||
dh->dccph_type == DCCP_PKT_DATA) {
- dccp_rcv_established(sk, skb, dh, len);
+ __dccp_rcv_established(sk, skb, dh, len);
queued = 1; /* packet was queued
- (by dccp_rcv_established) */
+ (by __dccp_rcv_established) */
}
break;
}
@@ -444,7 +464,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
*/
if (sk->sk_state == DCCP_LISTEN) {
if (dh->dccph_type == DCCP_PKT_REQUEST) {
- if (dccp_v4_conn_request(sk, skb) < 0)
+ if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
+ skb) < 0)
return 1;
/* FIXME: do congestion control initialization */
@@ -471,14 +492,14 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if (dcb->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);
-
if (dp->dccps_options.dccpo_send_ack_vector &&
dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,
DCCP_SKB_CB(skb)->dccpd_seq,
DCCP_ACKVEC_STATE_RECEIVED))
goto discard;
+
+ ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);
+ ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);
}
/*
@@ -566,3 +587,5 @@ discard:
}
return 0;
}
+
+EXPORT_SYMBOL_GPL(dccp_rcv_state_process);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 656e13e38cfb..00f983226672 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -19,7 +19,9 @@
#include <net/icmp.h>
#include <net/inet_hashtables.h>
+#include <net/inet_sock.h>
#include <net/sock.h>
+#include <net/timewait_sock.h>
#include <net/tcp_states.h>
#include <net/xfrm.h>
@@ -37,7 +39,8 @@ 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);
+ return inet_csk_get_port(&dccp_hashinfo, sk, snum,
+ inet_csk_bind_conflict);
}
static void dccp_v4_hash(struct sock *sk)
@@ -45,171 +48,14 @@ static void dccp_v4_hash(struct sock *sk)
inet_hash(&dccp_hashinfo, sk);
}
-static void dccp_v4_unhash(struct sock *sk)
+void dccp_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);
- unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
- struct inet_ehash_bucket *head = inet_ehash_bucket(&dccp_hashinfo, hash);
- const struct sock *sk2;
- const struct hlist_node *node;
- struct inet_timewait_sock *tw;
-
- prefetch(head->chain.first);
- 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, hash, acookie, saddr, daddr, ports, dif))
- goto not_unique;
- }
- tw = NULL;
-
- /* And established part... */
- sk_for_each(sk2, node, &head->chain) {
- if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
- goto not_unique;
- }
+EXPORT_SYMBOL_GPL(dccp_unhash);
- /* 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_hash = 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 low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int remaining = (high - low) + 1;
- int rover = net_random() % (high - low) + low;
- struct hlist_node *node;
- struct inet_timewait_sock *tw = NULL;
-
- local_bh_disable();
- do {
- 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);
- if (++rover > high)
- rover = low;
- } while (--remaining > 0);
-
- local_bh_enable();
-
- return -EADDRNOTAVAIL;
-
-ok:
- /* All locks still held and bhs disabled */
- 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)
+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);
@@ -259,9 +105,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
inet->dport = usin->sin_port;
inet->daddr = daddr;
- dp->dccps_ext_header_len = 0;
+ inet_csk(sk)->icsk_ext_hdr_len = 0;
if (inet->opt != NULL)
- dp->dccps_ext_header_len = inet->opt->optlen;
+ inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
/*
* Socket identity is still unknown (sport may be zero).
* However we set state to DCCP_REQUESTING and not releasing socket
@@ -269,7 +115,7 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
* complete initialization after this.
*/
dccp_set_state(sk, DCCP_REQUESTING);
- err = dccp_v4_hash_connect(sk);
+ err = inet_hash_connect(&dccp_death_row, sk);
if (err != 0)
goto failure;
@@ -287,16 +133,6 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr,
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);
@@ -316,6 +152,8 @@ failure:
goto out;
}
+EXPORT_SYMBOL_GPL(dccp_v4_connect);
+
/*
* This routine does path mtu discovery as defined in RFC1191.
*/
@@ -354,7 +192,7 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
mtu = dst_mtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
- dp->dccps_pmtu_cookie > mtu) {
+ inet_csk(sk)->icsk_pmtu_cookie > mtu) {
dccp_sync_mss(sk, mtu);
/*
@@ -606,6 +444,17 @@ out:
sock_put(sk);
}
+/* This routine computes an IPv4 DCCP checksum. */
+void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ struct dccp_hdr *dh = dccp_hdr(skb);
+
+ dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr, inet->daddr);
+}
+
+EXPORT_SYMBOL_GPL(dccp_v4_send_check);
+
int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code)
{
struct sk_buff *skb;
@@ -641,16 +490,6 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk,
dccp_hdr(skb)->dccph_sport);
}
-static inline int dccp_bad_service_code(const struct sock *sk,
- const __u32 service)
-{
- const struct dccp_sock *dp = dccp_sk(sk);
-
- if (dp->dccps_service == service)
- return 0;
- return !dccp_list_has_service(dp->dccps_service_list, service);
-}
-
int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
struct inet_request_sock *ireq;
@@ -662,7 +501,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
__u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
- struct dst_entry *dst = NULL;
/* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */
if (((struct rtable *)skb->dst)->rt_flags &
@@ -703,7 +541,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *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;
@@ -721,23 +558,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
dreq->dreq_iss = dccp_v4_init_sequence(sk, skb);
dreq->dreq_service = service;
- if (dccp_v4_send_response(sk, req, dst))
+ if (dccp_v4_send_response(sk, req, NULL))
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);
+ reqsk_free(req);
drop:
DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
dcb->dccpd_reset_code = reset_code;
return -1;
}
+EXPORT_SYMBOL_GPL(dccp_v4_conn_request);
+
/*
* The three way handshake has completed - we got a valid ACK or DATAACK -
* now create the new socket.
@@ -792,6 +628,8 @@ exit:
return NULL;
}
+EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock);
+
static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
{
const struct dccp_hdr *dh = dccp_hdr(skb);
@@ -1011,7 +849,9 @@ discard:
return 0;
}
-static inline int dccp_invalid_packet(struct sk_buff *skb)
+EXPORT_SYMBOL_GPL(dccp_v4_do_rcv);
+
+int dccp_invalid_packet(struct sk_buff *skb)
{
const struct dccp_hdr *dh;
@@ -1065,29 +905,30 @@ static inline int dccp_invalid_packet(struct sk_buff *skb)
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;
}
+EXPORT_SYMBOL_GPL(dccp_invalid_packet);
+
/* 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;
+ /* 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 "%s: incorrect header checksum\n",
+ __FUNCTION__);
+ goto discard_it;
+ }
+
dh = dccp_hdr(skb);
DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
@@ -1143,28 +984,11 @@ int dccp_v4_rcv(struct sk_buff *skb)
goto do_time_wait;
}
- if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) {
- dccp_pr_debug("xfrm4_policy_check failed\n");
+ if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
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);
+ nf_reset(skb);
- sock_put(sk);
- return rc;
+ return sk_receive_skb(sk, skb);
no_dccp_socket:
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
@@ -1194,9 +1018,23 @@ do_time_wait:
goto no_dccp_socket;
}
-static int dccp_v4_init_sock(struct sock *sk)
+struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
+ .queue_xmit = ip_queue_xmit,
+ .send_check = dccp_v4_send_check,
+ .rebuild_header = inet_sk_rebuild_header,
+ .conn_request = dccp_v4_conn_request,
+ .syn_recv_sock = dccp_v4_request_recv_sock,
+ .net_header_len = sizeof(struct iphdr),
+ .setsockopt = ip_setsockopt,
+ .getsockopt = ip_getsockopt,
+ .addr2sockaddr = inet_csk_addr2sockaddr,
+ .sockaddr_len = sizeof(struct sockaddr_in),
+};
+
+int dccp_v4_init_sock(struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
static int dccp_ctl_socket_init = 1;
dccp_options_init(&dp->dccps_options);
@@ -1236,9 +1074,11 @@ static int dccp_v4_init_sock(struct sock *sk)
dccp_ctl_socket_init = 0;
dccp_init_xmit_timers(sk);
- inet_csk(sk)->icsk_rto = DCCP_TIMEOUT_INIT;
+ icsk->icsk_rto = DCCP_TIMEOUT_INIT;
sk->sk_state = DCCP_CLOSED;
sk->sk_write_space = dccp_write_space;
+ icsk->icsk_af_ops = &dccp_ipv4_af_ops;
+ icsk->icsk_sync_mss = dccp_sync_mss;
dp->dccps_mss_cache = 536;
dp->dccps_role = DCCP_ROLE_UNDEFINED;
dp->dccps_service = DCCP_SERVICE_INVALID_VALUE;
@@ -1246,7 +1086,9 @@ static int dccp_v4_init_sock(struct sock *sk)
return 0;
}
-static int dccp_v4_destroy_sock(struct sock *sk)
+EXPORT_SYMBOL_GPL(dccp_v4_init_sock);
+
+int dccp_v4_destroy_sock(struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
@@ -1279,6 +1121,8 @@ static int dccp_v4_destroy_sock(struct sock *sk)
return 0;
}
+EXPORT_SYMBOL_GPL(dccp_v4_destroy_sock);
+
static void dccp_v4_reqsk_destructor(struct request_sock *req)
{
kfree(inet_rsk(req)->opt);
@@ -1293,7 +1137,11 @@ static struct request_sock_ops dccp_request_sock_ops = {
.send_reset = dccp_v4_ctl_send_reset,
};
-struct proto dccp_v4_prot = {
+static struct timewait_sock_ops dccp_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct inet_timewait_sock),
+};
+
+struct proto dccp_prot = {
.name = "DCCP",
.owner = THIS_MODULE,
.close = dccp_close,
@@ -1307,7 +1155,7 @@ struct proto dccp_v4_prot = {
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v4_do_rcv,
.hash = dccp_v4_hash,
- .unhash = dccp_v4_unhash,
+ .unhash = dccp_unhash,
.accept = inet_csk_accept,
.get_port = dccp_v4_get_port,
.shutdown = dccp_shutdown,
@@ -1316,5 +1164,7 @@ struct proto dccp_v4_prot = {
.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),
+ .twsk_prot = &dccp_timewait_sock_ops,
};
+
+EXPORT_SYMBOL_GPL(dccp_prot);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
new file mode 100644
index 000000000000..df074259f9c3
--- /dev/null
+++ b/net/dccp/ipv6.c
@@ -0,0 +1,1262 @@
+/*
+ * DCCP over IPv6
+ * Linux INET6 implementation
+ *
+ * Based on net/dccp6/ipv6.c
+ *
+ * Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/xfrm.h>
+
+#include <net/addrconf.h>
+#include <net/inet_common.h>
+#include <net/inet_hashtables.h>
+#include <net/inet_sock.h>
+#include <net/inet6_connection_sock.h>
+#include <net/inet6_hashtables.h>
+#include <net/ip6_route.h>
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/transp_v6.h>
+#include <net/ip6_checksum.h>
+#include <net/xfrm.h>
+
+#include "dccp.h"
+#include "ipv6.h"
+
+static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
+static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
+ struct request_sock *req);
+static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);
+
+static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
+
+static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
+static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
+
+static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
+{
+ return inet_csk_get_port(&dccp_hashinfo, sk, snum,
+ inet6_csk_bind_conflict);
+}
+
+static void dccp_v6_hash(struct sock *sk)
+{
+ if (sk->sk_state != DCCP_CLOSED) {
+ if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
+ dccp_prot.hash(sk);
+ return;
+ }
+ local_bh_disable();
+ __inet6_hash(&dccp_hashinfo, sk);
+ local_bh_enable();
+ }
+}
+
+static inline u16 dccp_v6_check(struct dccp_hdr *dh, int len,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ unsigned long base)
+{
+ return csum_ipv6_magic(saddr, daddr, len, IPPROTO_DCCP, base);
+}
+
+static __u32 dccp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+
+ if (skb->protocol == htons(ETH_P_IPV6))
+ return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
+ skb->nh.ipv6h->saddr.s6_addr32,
+ dh->dccph_dport,
+ dh->dccph_sport);
+ else
+ return secure_dccp_sequence_number(skb->nh.iph->daddr,
+ skb->nh.iph->saddr,
+ dh->dccph_dport,
+ dh->dccph_sport);
+}
+
+static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
+ int addr_len)
+{
+ struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct dccp_sock *dp = dccp_sk(sk);
+ struct in6_addr *saddr = NULL, *final_p = NULL, final;
+ struct flowi fl;
+ struct dst_entry *dst;
+ int addr_type;
+ int err;
+
+ dp->dccps_role = DCCP_ROLE_CLIENT;
+
+ if (addr_len < SIN6_LEN_RFC2133)
+ return -EINVAL;
+
+ if (usin->sin6_family != AF_INET6)
+ return -EAFNOSUPPORT;
+
+ memset(&fl, 0, sizeof(fl));
+
+ if (np->sndflow) {
+ fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
+ IP6_ECN_flow_init(fl.fl6_flowlabel);
+ if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
+ struct ip6_flowlabel *flowlabel;
+ flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+ if (flowlabel == NULL)
+ return -EINVAL;
+ ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
+ fl6_sock_release(flowlabel);
+ }
+ }
+
+ /*
+ * connect() to INADDR_ANY means loopback (BSD'ism).
+ */
+
+ if (ipv6_addr_any(&usin->sin6_addr))
+ usin->sin6_addr.s6_addr[15] = 0x1;
+
+ addr_type = ipv6_addr_type(&usin->sin6_addr);
+
+ if(addr_type & IPV6_ADDR_MULTICAST)
+ return -ENETUNREACH;
+
+ if (addr_type & IPV6_ADDR_LINKLOCAL) {
+ if (addr_len >= sizeof(struct sockaddr_in6) &&
+ usin->sin6_scope_id) {
+ /* If interface is set while binding, indices
+ * must coincide.
+ */
+ if (sk->sk_bound_dev_if &&
+ sk->sk_bound_dev_if != usin->sin6_scope_id)
+ return -EINVAL;
+
+ sk->sk_bound_dev_if = usin->sin6_scope_id;
+ }
+
+ /* Connect to link-local address requires an interface */
+ if (!sk->sk_bound_dev_if)
+ return -EINVAL;
+ }
+
+ ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
+ np->flow_label = fl.fl6_flowlabel;
+
+ /*
+ * DCCP over IPv4
+ */
+
+ if (addr_type == IPV6_ADDR_MAPPED) {
+ u32 exthdrlen = icsk->icsk_ext_hdr_len;
+ struct sockaddr_in sin;
+
+ SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
+
+ if (__ipv6_only_sock(sk))
+ return -ENETUNREACH;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = usin->sin6_port;
+ sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
+
+ icsk->icsk_af_ops = &dccp_ipv6_mapped;
+ sk->sk_backlog_rcv = dccp_v4_do_rcv;
+
+ err = dccp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
+
+ if (err) {
+ icsk->icsk_ext_hdr_len = exthdrlen;
+ icsk->icsk_af_ops = &dccp_ipv6_af_ops;
+ sk->sk_backlog_rcv = dccp_v6_do_rcv;
+ goto failure;
+ } else {
+ ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
+ inet->saddr);
+ ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
+ inet->rcv_saddr);
+ }
+
+ return err;
+ }
+
+ if (!ipv6_addr_any(&np->rcv_saddr))
+ saddr = &np->rcv_saddr;
+
+ fl.proto = IPPROTO_DCCP;
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+ ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_dport = usin->sin6_port;
+ fl.fl_ip_sport = inet->sport;
+
+ if (np->opt && np->opt->srcrt) {
+ struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+
+ err = ip6_dst_lookup(sk, &dst, &fl);
+ if (err)
+ goto failure;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ goto failure;
+
+ if (saddr == NULL) {
+ saddr = &fl.fl6_src;
+ ipv6_addr_copy(&np->rcv_saddr, saddr);
+ }
+
+ /* set the source address */
+ ipv6_addr_copy(&np->saddr, saddr);
+ inet->rcv_saddr = LOOPBACK4_IPV6;
+
+ ip6_dst_store(sk, dst, NULL);
+
+ icsk->icsk_ext_hdr_len = 0;
+ if (np->opt)
+ icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
+ np->opt->opt_nflen);
+
+ inet->dport = usin->sin6_port;
+
+ dccp_set_state(sk, DCCP_REQUESTING);
+ err = inet6_hash_connect(&dccp_death_row, sk);
+ if (err)
+ goto late_failure;
+ /* FIXME */
+#if 0
+ dp->dccps_gar = secure_dccp_v6_sequence_number(np->saddr.s6_addr32,
+ np->daddr.s6_addr32,
+ inet->sport,
+ inet->dport);
+#endif
+ err = dccp_connect(sk);
+ if (err)
+ goto late_failure;
+
+ return 0;
+
+late_failure:
+ dccp_set_state(sk, DCCP_CLOSED);
+ __sk_dst_reset(sk);
+failure:
+ inet->dport = 0;
+ sk->sk_route_caps = 0;
+ return err;
+}
+
+static void dccp_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;
+ const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset);
+ struct ipv6_pinfo *np;
+ struct sock *sk;
+ int err;
+ __u64 seq;
+
+ sk = inet6_lookup(&dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
+ &hdr->saddr, dh->dccph_sport, skb->dev->ifindex);
+
+ if (sk == NULL) {
+ ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
+ return;
+ }
+
+ if (sk->sk_state == DCCP_TIME_WAIT) {
+ inet_twsk_put((struct inet_timewait_sock *)sk);
+ return;
+ }
+
+ bh_lock_sock(sk);
+ if (sock_owned_by_user(sk))
+ NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
+
+ if (sk->sk_state == DCCP_CLOSED)
+ goto out;
+
+ np = inet6_sk(sk);
+
+ if (type == ICMPV6_PKT_TOOBIG) {
+ struct dst_entry *dst = NULL;
+
+ if (sock_owned_by_user(sk))
+ goto out;
+ if ((1 << sk->sk_state) & (DCCPF_LISTEN | DCCPF_CLOSED))
+ goto out;
+
+ /* icmp should have updated the destination cache entry */
+ dst = __sk_dst_check(sk, np->dst_cookie);
+
+ if (dst == NULL) {
+ struct inet_sock *inet = inet_sk(sk);
+ struct flowi fl;
+
+ /* BUGGG_FUTURE: Again, it is not clear how
+ to handle rthdr case. Ignore this complexity
+ for now.
+ */
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = IPPROTO_DCCP;
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+ ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_dport = inet->dport;
+ fl.fl_ip_sport = inet->sport;
+
+ if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
+ sk->sk_err_soft = -err;
+ goto out;
+ }
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_err_soft = -err;
+ goto out;
+ }
+
+ } else
+ dst_hold(dst);
+
+ if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
+ dccp_sync_mss(sk, dst_mtu(dst));
+ } /* else let the usual retransmit timer handle it */
+ dst_release(dst);
+ goto out;
+ }
+
+ icmpv6_err_convert(type, code, &err);
+
+ seq = DCCP_SKB_CB(skb)->dccpd_seq;
+ /* Might be for an request_sock */
+ switch (sk->sk_state) {
+ struct request_sock *req, **prev;
+ case DCCP_LISTEN:
+ if (sock_owned_by_user(sk))
+ goto out;
+
+ req = inet6_csk_search_req(sk, &prev, dh->dccph_dport,
+ &hdr->daddr, &hdr->saddr,
+ inet6_iif(skb));
+ if (!req)
+ goto out;
+
+ /* ICMPs are not backlogged, hence we cannot get
+ * an established socket here.
+ */
+ BUG_TRAP(req->sk == NULL);
+
+ if (seq != dccp_rsk(req)->dreq_iss) {
+ NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
+ goto out;
+ }
+
+ inet_csk_reqsk_queue_drop(sk, req, prev);
+ goto out;
+
+ case DCCP_REQUESTING:
+ case DCCP_RESPOND: /* Cannot happen.
+ It can, it SYNs are crossed. --ANK */
+ if (!sock_owned_by_user(sk)) {
+ DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ sk->sk_err = err;
+ /*
+ * Wake people up to see the error
+ * (see connect in sock.c)
+ */
+ sk->sk_error_report(sk);
+
+ dccp_done(sk);
+ } else
+ sk->sk_err_soft = err;
+ goto out;
+ }
+
+ if (!sock_owned_by_user(sk) && np->recverr) {
+ sk->sk_err = err;
+ sk->sk_error_report(sk);
+ } else
+ sk->sk_err_soft = err;
+
+out:
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+
+static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
+ struct dst_entry *dst)
+{
+ struct inet6_request_sock *ireq6 = inet6_rsk(req);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct sk_buff *skb;
+ struct ipv6_txoptions *opt = NULL;
+ struct in6_addr *final_p = NULL, final;
+ struct flowi fl;
+ int err = -1;
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = IPPROTO_DCCP;
+ ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
+ ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
+ fl.fl6_flowlabel = 0;
+ fl.oif = ireq6->iif;
+ fl.fl_ip_dport = inet_rsk(req)->rmt_port;
+ fl.fl_ip_sport = inet_sk(sk)->sport;
+
+ if (dst == NULL) {
+ opt = np->opt;
+ if (opt == NULL &&
+ np->rxopt.bits.osrcrt == 2 &&
+ ireq6->pktopts) {
+ struct sk_buff *pktopts = ireq6->pktopts;
+ struct inet6_skb_parm *rxopt = IP6CB(pktopts);
+ if (rxopt->srcrt)
+ opt = ipv6_invert_rthdr(sk,
+ (struct ipv6_rt_hdr *)(pktopts->nh.raw +
+ rxopt->srcrt));
+ }
+
+ if (opt && opt->srcrt) {
+ struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+
+ err = ip6_dst_lookup(sk, &dst, &fl);
+ if (err)
+ goto done;
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ goto done;
+ }
+
+ skb = dccp_make_response(sk, dst, req);
+ if (skb != NULL) {
+ struct dccp_hdr *dh = dccp_hdr(skb);
+ dh->dccph_checksum = dccp_v6_check(dh, skb->len,
+ &ireq6->loc_addr,
+ &ireq6->rmt_addr,
+ csum_partial((char *)dh,
+ skb->len,
+ skb->csum));
+ ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
+ err = ip6_xmit(sk, skb, &fl, opt, 0);
+ if (err == NET_XMIT_CN)
+ err = 0;
+ }
+
+done:
+ if (opt && opt != np->opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+ return err;
+}
+
+static void dccp_v6_reqsk_destructor(struct request_sock *req)
+{
+ if (inet6_rsk(req)->pktopts != NULL)
+ kfree_skb(inet6_rsk(req)->pktopts);
+}
+
+static struct request_sock_ops dccp6_request_sock_ops = {
+ .family = AF_INET6,
+ .obj_size = sizeof(struct dccp6_request_sock),
+ .rtx_syn_ack = dccp_v6_send_response,
+ .send_ack = dccp_v6_reqsk_send_ack,
+ .destructor = dccp_v6_reqsk_destructor,
+ .send_reset = dccp_v6_ctl_send_reset,
+};
+
+static struct timewait_sock_ops dccp6_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct dccp6_timewait_sock),
+};
+
+static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct dccp_hdr *dh = dccp_hdr(skb);
+
+ dh->dccph_checksum = csum_ipv6_magic(&np->saddr, &np->daddr,
+ len, IPPROTO_DCCP,
+ csum_partial((char *)dh,
+ dh->dccph_doff << 2,
+ skb->csum));
+}
+
+static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
+{
+ 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 flowi fl;
+ u64 seqno;
+
+ if (rxdh->dccph_type == DCCP_PKT_RESET)
+ return;
+
+ if (!ipv6_unicast_destination(rxskb))
+ return;
+
+ /*
+ * We need to grab some memory, and put together an RST,
+ * and then put it into the queue to be sent.
+ */
+
+ skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) +
+ dccp_hdr_reset_len, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+
+ skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) +
+ dccp_hdr_reset_len);
+
+ skb->h.raw = skb_push(skb, dccp_hdr_reset_len);
+ dh = dccp_hdr(skb);
+ memset(dh, 0, dccp_hdr_reset_len);
+
+ /* Swap the send and the receive. */
+ 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);
+
+ memset(&fl, 0, sizeof(fl));
+ ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
+ ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
+ dh->dccph_checksum = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
+ sizeof(*dh), IPPROTO_DCCP,
+ skb->csum);
+ fl.proto = IPPROTO_DCCP;
+ fl.oif = inet6_iif(rxskb);
+ fl.fl_ip_dport = dh->dccph_dport;
+ fl.fl_ip_sport = dh->dccph_sport;
+
+ /* sk = NULL, but it is safe for now. RST socket required. */
+ if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
+ if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
+ ip6_xmit(NULL, skb, &fl, NULL, 0);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+ return;
+ }
+ }
+
+ kfree_skb(skb);
+}
+
+static void dccp_v6_ctl_send_ack(struct sk_buff *rxskb)
+{
+ struct flowi fl;
+ 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;
+
+ skb = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) +
+ dccp_hdr_ack_len, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+
+ skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr) +
+ dccp_hdr_ack_len);
+
+ 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);
+
+ memset(&fl, 0, sizeof(fl));
+ ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
+ ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);
+
+ /* FIXME: calculate checksum, IPv4 also should... */
+
+ fl.proto = IPPROTO_DCCP;
+ fl.oif = inet6_iif(rxskb);
+ fl.fl_ip_dport = dh->dccph_dport;
+ fl.fl_ip_sport = dh->dccph_sport;
+
+ if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
+ if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
+ ip6_xmit(NULL, skb, &fl, NULL, 0);
+ DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+ return;
+ }
+ }
+
+ kfree_skb(skb);
+}
+
+static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
+ struct request_sock *req)
+{
+ dccp_v6_ctl_send_ack(skb);
+}
+
+static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+{
+ const struct dccp_hdr *dh = dccp_hdr(skb);
+ const struct ipv6hdr *iph = skb->nh.ipv6h;
+ struct sock *nsk;
+ struct request_sock **prev;
+ /* Find possible connection requests. */
+ struct request_sock *req = inet6_csk_search_req(sk, &prev,
+ dh->dccph_sport,
+ &iph->saddr,
+ &iph->daddr,
+ inet6_iif(skb));
+ if (req != NULL)
+ return dccp_check_req(sk, skb, req, prev);
+
+ nsk = __inet6_lookup_established(&dccp_hashinfo,
+ &iph->saddr, dh->dccph_sport,
+ &iph->daddr, ntohs(dh->dccph_dport),
+ inet6_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;
+}
+
+static int dccp_v6_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;
+ struct inet6_request_sock *ireq6;
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ const __u32 service = dccp_hdr_request(skb)->dccph_req_service;
+ struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
+ __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ return dccp_v4_conn_request(sk, skb);
+
+ if (!ipv6_unicast_destination(skb))
+ goto drop;
+
+ if (dccp_bad_service_code(sk, service)) {
+ reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
+ goto drop;
+ }
+ /*
+ * There are no SYN attacks on IPv6, yet...
+ */
+ if (inet_csk_reqsk_queue_is_full(sk))
+ goto drop;
+
+ if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
+ goto drop;
+
+ req = inet6_reqsk_alloc(sk->sk_prot->rsk_prot);
+ if (req == NULL)
+ goto drop;
+
+ /* FIXME: process options */
+
+ dccp_openreq_init(req, &dp, skb);
+
+ ireq6 = inet6_rsk(req);
+ ireq = inet_rsk(req);
+ ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
+ ipv6_addr_copy(&ireq6->loc_addr, &skb->nh.ipv6h->daddr);
+ req->rcv_wnd = 100; /* Fake, option parsing will get the
+ right value */
+ ireq6->pktopts = NULL;
+
+ if (ipv6_opt_accepted(sk, skb) ||
+ np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
+ np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
+ atomic_inc(&skb->users);
+ ireq6->pktopts = skb;
+ }
+ ireq6->iif = sk->sk_bound_dev_if;
+
+ /* So that link locals have meaning */
+ if (!sk->sk_bound_dev_if &&
+ ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+ ireq6->iif = inet6_iif(skb);
+
+ /*
+ * 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 = dcb->dccpd_seq;
+ dreq->dreq_iss = dccp_v6_init_sequence(sk, skb);
+ dreq->dreq_service = service;
+
+ if (dccp_v6_send_response(sk, req, NULL))
+ goto drop_and_free;
+
+ inet6_csk_reqsk_queue_hash_add(sk, req, DCCP_TIMEOUT_INIT);
+ return 0;
+
+drop_and_free:
+ reqsk_free(req);
+drop:
+ DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
+ dcb->dccpd_reset_code = reset_code;
+ return -1;
+}
+
+static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
+ struct sk_buff *skb,
+ struct request_sock *req,
+ struct dst_entry *dst)
+{
+ struct inet6_request_sock *ireq6 = inet6_rsk(req);
+ struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
+ struct inet_sock *newinet;
+ struct dccp_sock *newdp;
+ struct dccp6_sock *newdp6;
+ struct sock *newsk;
+ struct ipv6_txoptions *opt;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ /*
+ * v6 mapped
+ */
+
+ newsk = dccp_v4_request_recv_sock(sk, skb, req, dst);
+ if (newsk == NULL)
+ return NULL;
+
+ newdp6 = (struct dccp6_sock *)newsk;
+ newdp = dccp_sk(newsk);
+ newinet = inet_sk(newsk);
+ newinet->pinet6 = &newdp6->inet6;
+ newnp = inet6_sk(newsk);
+
+ memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+
+ ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),
+ newinet->daddr);
+
+ ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),
+ newinet->saddr);
+
+ ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
+
+ inet_csk(newsk)->icsk_af_ops = &dccp_ipv6_mapped;
+ newsk->sk_backlog_rcv = dccp_v4_do_rcv;
+ newnp->pktoptions = NULL;
+ newnp->opt = NULL;
+ newnp->mcast_oif = inet6_iif(skb);
+ newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
+
+ /*
+ * No need to charge this sock to the relevant IPv6 refcnt debug socks count
+ * here, dccp_create_openreq_child now does this for us, see the comment in
+ * that function for the gory details. -acme
+ */
+
+ /* It is tricky place. Until this moment IPv4 tcp
+ worked with IPv6 icsk.icsk_af_ops.
+ Sync it now.
+ */
+ dccp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
+
+ return newsk;
+ }
+
+ opt = np->opt;
+
+ if (sk_acceptq_is_full(sk))
+ goto out_overflow;
+
+ if (np->rxopt.bits.osrcrt == 2 &&
+ opt == NULL && ireq6->pktopts) {
+ struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
+ if (rxopt->srcrt)
+ opt = ipv6_invert_rthdr(sk,
+ (struct ipv6_rt_hdr *)(ireq6->pktopts->nh.raw +
+ rxopt->srcrt));
+ }
+
+ if (dst == NULL) {
+ struct in6_addr *final_p = NULL, final;
+ struct flowi fl;
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = IPPROTO_DCCP;
+ ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
+ if (opt && opt->srcrt) {
+ struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+ ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_dport = inet_rsk(req)->rmt_port;
+ fl.fl_ip_sport = inet_sk(sk)->sport;
+
+ if (ip6_dst_lookup(sk, &dst, &fl))
+ goto out;
+
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ goto out;
+ }
+
+ newsk = dccp_create_openreq_child(sk, req, skb);
+ if (newsk == NULL)
+ goto out;
+
+ /*
+ * No need to charge this sock to the relevant IPv6 refcnt debug socks
+ * count here, dccp_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 &
+ ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
+
+ newdp6 = (struct dccp6_sock *)newsk;
+ newinet = inet_sk(newsk);
+ newinet->pinet6 = &newdp6->inet6;
+ newdp = dccp_sk(newsk);
+ newnp = inet6_sk(newsk);
+
+ memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+
+ ipv6_addr_copy(&newnp->daddr, &ireq6->rmt_addr);
+ ipv6_addr_copy(&newnp->saddr, &ireq6->loc_addr);
+ ipv6_addr_copy(&newnp->rcv_saddr, &ireq6->loc_addr);
+ newsk->sk_bound_dev_if = ireq6->iif;
+
+ /* Now IPv6 options...
+
+ First: no IPv4 options.
+ */
+ newinet->opt = NULL;
+
+ /* Clone RX bits */
+ newnp->rxopt.all = np->rxopt.all;
+
+ /* Clone pktoptions received with SYN */
+ newnp->pktoptions = NULL;
+ if (ireq6->pktopts != NULL) {
+ newnp->pktoptions = skb_clone(ireq6->pktopts, GFP_ATOMIC);
+ kfree_skb(ireq6->pktopts);
+ ireq6->pktopts = NULL;
+ if (newnp->pktoptions)
+ skb_set_owner_r(newnp->pktoptions, newsk);
+ }
+ newnp->opt = NULL;
+ newnp->mcast_oif = inet6_iif(skb);
+ newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
+
+ /* Clone native IPv6 options from listening socket (if any)
+
+ Yes, keeping reference count would be much more clever,
+ but we make one more one thing there: reattach optmem
+ to newsk.
+ */
+ if (opt) {
+ newnp->opt = ipv6_dup_options(newsk, opt);
+ if (opt != np->opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+ }
+
+ inet_csk(newsk)->icsk_ext_hdr_len = 0;
+ if (newnp->opt)
+ inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
+ newnp->opt->opt_flen);
+
+ dccp_sync_mss(newsk, dst_mtu(dst));
+
+ newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
+
+ __inet6_hash(&dccp_hashinfo, newsk);
+ inet_inherit_port(&dccp_hashinfo, sk, newsk);
+
+ return newsk;
+
+out_overflow:
+ NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
+out:
+ NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
+ if (opt && opt != np->opt)
+ sock_kfree_s(sk, opt, opt->tot_len);
+ dst_release(dst);
+ return NULL;
+}
+
+/* The socket must have it's spinlock held when we get
+ * here.
+ *
+ * We have a potential double-lock case here, so even when
+ * doing backlog processing we use the BH locking scheme.
+ * This is because we cannot sleep with the original spinlock
+ * held.
+ */
+static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct sk_buff *opt_skb = NULL;
+
+ /* Imagine: socket is IPv6. IPv4 packet arrives,
+ goes to IPv4 receive handler and backlogged.
+ From backlog it always goes here. Kerboom...
+ Fortunately, dccp_rcv_established and rcv_established
+ handle them correctly, but it is not case with
+ dccp_v6_hnd_req and dccp_v6_ctl_send_reset(). --ANK
+ */
+
+ if (skb->protocol == htons(ETH_P_IP))
+ return dccp_v4_do_rcv(sk, skb);
+
+ if (sk_filter(sk, skb, 0))
+ goto discard;
+
+ /*
+ * socket locking is here for SMP purposes as backlog rcv
+ * is currently called with bh processing disabled.
+ */
+
+ /* Do Stevens' IPV6_PKTOPTIONS.
+
+ Yes, guys, it is the only place in our code, where we
+ may make it not affecting IPv4.
+ The rest of code is protocol independent,
+ and I do not like idea to uglify IPv4.
+
+ Actually, all the idea behind IPV6_PKTOPTIONS
+ looks not very well thought. For now we latch
+ options, received in the last packet, enqueued
+ by tcp. Feel free to propose better solution.
+ --ANK (980728)
+ */
+ if (np->rxopt.all)
+ opt_skb = skb_clone(skb, GFP_ATOMIC);
+
+ if (sk->sk_state == DCCP_OPEN) { /* Fast path */
+ if (dccp_rcv_established(sk, skb, dccp_hdr(skb), skb->len))
+ goto reset;
+ return 0;
+ }
+
+ if (sk->sk_state == DCCP_LISTEN) {
+ struct sock *nsk = dccp_v6_hnd_req(sk, skb);
+ if (!nsk)
+ goto discard;
+
+ /*
+ * Queue it on the new socket if the new socket is active,
+ * otherwise we just shortcircuit this and continue with
+ * the new socket..
+ */
+ if(nsk != sk) {
+ if (dccp_child_process(sk, nsk, skb))
+ goto reset;
+ if (opt_skb)
+ __kfree_skb(opt_skb);
+ return 0;
+ }
+ }
+
+ if (dccp_rcv_state_process(sk, skb, dccp_hdr(skb), skb->len))
+ goto reset;
+ return 0;
+
+reset:
+ dccp_v6_ctl_send_reset(skb);
+discard:
+ if (opt_skb)
+ __kfree_skb(opt_skb);
+ kfree_skb(skb);
+ return 0;
+}
+
+static int dccp_v6_rcv(struct sk_buff **pskb)
+{
+ const struct dccp_hdr *dh;
+ struct sk_buff *skb = *pskb;
+ struct sock *sk;
+
+ /* Step 1: Check header basics: */
+
+ if (dccp_invalid_packet(skb))
+ goto discard_it;
+
+ dh = dccp_hdr(skb);
+
+ DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb);
+ DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type;
+
+ if (dccp_packet_without_ack(skb))
+ DCCP_SKB_CB(skb)->dccpd_ack_seq = DCCP_PKT_WITHOUT_ACK_SEQ;
+ else
+ DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
+
+ /* Step 2:
+ * Look up flow ID in table and get corresponding socket */
+ sk = __inet6_lookup(&dccp_hashinfo, &skb->nh.ipv6h->saddr,
+ dh->dccph_sport,
+ &skb->nh.ipv6h->daddr, ntohs(dh->dccph_dport),
+ inet6_iif(skb));
+ /*
+ * Step 2:
+ * If no socket ...
+ * Generate Reset(No Connection) unless P.type == Reset
+ * Drop packet and return
+ */
+ if (sk == NULL)
+ 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)
+ goto do_time_wait;
+
+ if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
+ goto discard_and_relse;
+
+ return sk_receive_skb(sk, skb) ? -1 : 0;
+
+no_dccp_socket:
+ if (!xfrm6_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_v6_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 struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
+ .queue_xmit = inet6_csk_xmit,
+ .send_check = dccp_v6_send_check,
+ .rebuild_header = inet6_sk_rebuild_header,
+ .conn_request = dccp_v6_conn_request,
+ .syn_recv_sock = dccp_v6_request_recv_sock,
+ .net_header_len = sizeof(struct ipv6hdr),
+ .setsockopt = ipv6_setsockopt,
+ .getsockopt = ipv6_getsockopt,
+ .addr2sockaddr = inet6_csk_addr2sockaddr,
+ .sockaddr_len = sizeof(struct sockaddr_in6)
+};
+
+/*
+ * DCCP over IPv4 via INET6 API
+ */
+static struct inet_connection_sock_af_ops dccp_ipv6_mapped = {
+ .queue_xmit = ip_queue_xmit,
+ .send_check = dccp_v4_send_check,
+ .rebuild_header = inet_sk_rebuild_header,
+ .conn_request = dccp_v6_conn_request,
+ .syn_recv_sock = dccp_v6_request_recv_sock,
+ .net_header_len = sizeof(struct iphdr),
+ .setsockopt = ipv6_setsockopt,
+ .getsockopt = ipv6_getsockopt,
+ .addr2sockaddr = inet6_csk_addr2sockaddr,
+ .sockaddr_len = sizeof(struct sockaddr_in6)
+};
+
+/* NOTE: A lot of things set to zero explicitly by call to
+ * sk_alloc() so need not be done here.
+ */
+static int dccp_v6_init_sock(struct sock *sk)
+{
+ int err = dccp_v4_init_sock(sk);
+
+ if (err == 0)
+ inet_csk(sk)->icsk_af_ops = &dccp_ipv6_af_ops;
+
+ return err;
+}
+
+static int dccp_v6_destroy_sock(struct sock *sk)
+{
+ dccp_v4_destroy_sock(sk);
+ return inet6_destroy_sock(sk);
+}
+
+static struct proto dccp_v6_prot = {
+ .name = "DCCPv6",
+ .owner = THIS_MODULE,
+ .close = dccp_close,
+ .connect = dccp_v6_connect,
+ .disconnect = dccp_disconnect,
+ .ioctl = dccp_ioctl,
+ .init = dccp_v6_init_sock,
+ .setsockopt = dccp_setsockopt,
+ .getsockopt = dccp_getsockopt,
+ .sendmsg = dccp_sendmsg,
+ .recvmsg = dccp_recvmsg,
+ .backlog_rcv = dccp_v6_do_rcv,
+ .hash = dccp_v6_hash,
+ .unhash = dccp_unhash,
+ .accept = inet_csk_accept,
+ .get_port = dccp_v6_get_port,
+ .shutdown = dccp_shutdown,
+ .destroy = dccp_v6_destroy_sock,
+ .orphan_count = &dccp_orphan_count,
+ .max_header = MAX_DCCP_HEADER,
+ .obj_size = sizeof(struct dccp6_sock),
+ .rsk_prot = &dccp6_request_sock_ops,
+ .twsk_prot = &dccp6_timewait_sock_ops,
+};
+
+static struct inet6_protocol dccp_v6_protocol = {
+ .handler = dccp_v6_rcv,
+ .err_handler = dccp_v6_err,
+ .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
+};
+
+static struct proto_ops inet6_dccp_ops = {
+ .family = PF_INET6,
+ .owner = THIS_MODULE,
+ .release = inet6_release,
+ .bind = inet6_bind,
+ .connect = inet_stream_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = inet_accept,
+ .getname = inet6_getname,
+ .poll = dccp_poll,
+ .ioctl = inet6_ioctl,
+ .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,
+};
+
+static struct inet_protosw dccp_v6_protosw = {
+ .type = SOCK_DCCP,
+ .protocol = IPPROTO_DCCP,
+ .prot = &dccp_v6_prot,
+ .ops = &inet6_dccp_ops,
+ .capability = -1,
+ .flags = INET_PROTOSW_ICSK,
+};
+
+static int __init dccp_v6_init(void)
+{
+ int err = proto_register(&dccp_v6_prot, 1);
+
+ if (err != 0)
+ goto out;
+
+ err = inet6_add_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ if (err != 0)
+ goto out_unregister_proto;
+
+ inet6_register_protosw(&dccp_v6_protosw);
+out:
+ return err;
+out_unregister_proto:
+ proto_unregister(&dccp_v6_prot);
+ goto out;
+}
+
+static void __exit dccp_v6_exit(void)
+{
+ inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
+ inet6_unregister_protosw(&dccp_v6_protosw);
+ proto_unregister(&dccp_v6_prot);
+}
+
+module_init(dccp_v6_init);
+module_exit(dccp_v6_exit);
+
+/*
+ * __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_INET6-proto-0-type-SOCK_DCCP
+ */
+MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-33-type-6");
+MODULE_ALIAS("net-pf-" __stringify(PF_INET6) "-proto-0-type-6");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
+MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");
diff --git a/net/dccp/ipv6.h b/net/dccp/ipv6.h
new file mode 100644
index 000000000000..e4d4e9309270
--- /dev/null
+++ b/net/dccp/ipv6.h
@@ -0,0 +1,37 @@
+#ifndef _DCCP_IPV6_H
+#define _DCCP_IPV6_H
+/*
+ * net/dccp/ipv6.h
+ *
+ * An implementation of the DCCP protocol
+ * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.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/config.h>
+#include <linux/dccp.h>
+#include <linux/ipv6.h>
+
+struct dccp6_sock {
+ struct dccp_sock dccp;
+ /*
+ * ipv6_pinfo has to be the last member of dccp6_sock,
+ * see inet6_sk_generic.
+ */
+ struct ipv6_pinfo inet6;
+};
+
+struct dccp6_request_sock {
+ struct dccp_request_sock dccp;
+ struct inet6_request_sock inet6;
+};
+
+struct dccp6_timewait_sock {
+ struct inet_timewait_sock inet;
+ struct inet6_timewait_sock tw6;
+};
+
+#endif /* _DCCP_IPV6_H */
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index 1393461898bb..29261fc198e7 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -40,6 +40,8 @@ struct inet_timewait_death_row dccp_death_row = {
(unsigned long)&dccp_death_row),
};
+EXPORT_SYMBOL_GPL(dccp_death_row);
+
void dccp_time_wait(struct sock *sk, int state, int timeo)
{
struct inet_timewait_sock *tw = NULL;
@@ -50,7 +52,18 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
if (tw != NULL) {
const struct inet_connection_sock *icsk = inet_csk(sk);
const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
-
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ if (tw->tw_family == PF_INET6) {
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ struct inet6_timewait_sock *tw6;
+
+ tw->tw_ipv6_offset = inet6_tw_offset(sk->sk_prot);
+ tw6 = inet6_twsk((struct sock *)tw);
+ ipv6_addr_copy(&tw6->tw_v6_daddr, &np->daddr);
+ ipv6_addr_copy(&tw6->tw_v6_rcv_saddr, &np->rcv_saddr);
+ tw->tw_ipv6only = np->ipv6only;
+ }
+#endif
/* Linkage updates. */
__inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
@@ -170,6 +183,8 @@ out_free:
return newsk;
}
+EXPORT_SYMBOL_GPL(dccp_create_openreq_child);
+
/*
* Process an incoming packet for RESPOND sockets represented
* as an request_sock.
@@ -214,7 +229,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
goto drop;
}
- child = dccp_v4_request_recv_sock(sk, skb, req, NULL);
+ child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);
if (child == NULL)
goto listen_overflow;
@@ -236,6 +251,8 @@ drop:
goto out;
}
+EXPORT_SYMBOL_GPL(dccp_check_req);
+
/*
* Queue segment on the new socket if the new socket is active,
* otherwise we just shortcircuit this and continue with
@@ -266,3 +283,5 @@ int dccp_child_process(struct sock *parent, struct sock *child,
sock_put(child);
return ret;
}
+
+EXPORT_SYMBOL_GPL(dccp_child_process);
diff --git a/net/dccp/output.c b/net/dccp/output.c
index 74ff87025878..efd7ffb903a1 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/skbuff.h>
+#include <net/inet_sock.h>
#include <net/sock.h>
#include "ackvec.h"
@@ -43,6 +44,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
{
if (likely(skb != NULL)) {
const struct inet_sock *inet = inet_sk(sk);
+ const struct inet_connection_sock *icsk = inet_csk(sk);
struct dccp_sock *dp = dccp_sk(sk);
struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);
struct dccp_hdr *dh;
@@ -108,8 +110,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
break;
}
- dh->dccph_checksum = dccp_v4_checksum(skb, inet->saddr,
- inet->daddr);
+ icsk->icsk_af_ops->send_check(sk, skb->len, skb);
if (set_ack)
dccp_event_ack_sent(sk);
@@ -117,7 +118,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
- err = ip_queue_xmit(skb, 0);
+ err = icsk->icsk_af_ops->queue_xmit(skb, 0);
if (err <= 0)
return err;
@@ -134,20 +135,13 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
{
+ struct inet_connection_sock *icsk = inet_csk(sk);
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);
+ int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
+ sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext));
/* Now subtract optional transport overhead */
- mss_now -= dp->dccps_ext_header_len;
+ mss_now -= icsk->icsk_ext_hdr_len;
/*
* FIXME: this should come from the CCID infrastructure, where, say,
@@ -160,12 +154,14 @@ unsigned int dccp_sync_mss(struct sock *sk, u32 pmtu)
mss_now -= ((5 + 6 + 10 + 6 + 6 + 6 + 3) / 4) * 4;
/* And store cached results */
- dp->dccps_pmtu_cookie = pmtu;
+ icsk->icsk_pmtu_cookie = pmtu;
dp->dccps_mss_cache = mss_now;
return mss_now;
}
+EXPORT_SYMBOL_GPL(dccp_sync_mss);
+
void dccp_write_space(struct sock *sk)
{
read_lock(&sk->sk_callback_lock);
@@ -266,7 +262,7 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo)
int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
{
- if (inet_sk_rebuild_header(sk) != 0)
+ if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
return -EHOSTUNREACH; /* Routing failure or similar. */
return dccp_transmit_skb(sk, (skb_cloned(skb) ?
@@ -321,6 +317,8 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
return skb;
}
+EXPORT_SYMBOL_GPL(dccp_make_response);
+
struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
const enum dccp_reset_codes code)
@@ -377,6 +375,7 @@ struct sk_buff *dccp_make_reset(struct sock *sk, struct dst_entry *dst,
*/
static inline void dccp_connect_init(struct sock *sk)
{
+ struct dccp_sock *dp = dccp_sk(sk);
struct dst_entry *dst = __sk_dst_get(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
@@ -385,10 +384,16 @@ static inline void dccp_connect_init(struct sock *sk)
dccp_sync_mss(sk, dst_mtu(dst));
- /*
- * FIXME: set dp->{dccps_swh,dccps_swl}, with
- * something like dccp_inc_seq
- */
+ 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));
icsk->icsk_retransmits = 0;
}
@@ -420,6 +425,8 @@ int dccp_connect(struct sock *sk)
return 0;
}
+EXPORT_SYMBOL_GPL(dccp_connect);
+
void dccp_send_ack(struct sock *sk)
{
/* If we have been reset, we may not send again. */
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 8a6b2a9e4581..65b11ea90d85 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -24,7 +24,7 @@
#include <net/checksum.h>
#include <net/inet_common.h>
-#include <net/ip.h>
+#include <net/inet_sock.h>
#include <net/protocol.h>
#include <net/sock.h>
#include <net/xfrm.h>
@@ -34,15 +34,18 @@
#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;
+EXPORT_SYMBOL_GPL(dccp_statistics);
+
atomic_t dccp_orphan_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL_GPL(dccp_orphan_count);
+
static struct net_protocol dccp_protocol = {
.handler = dccp_v4_rcv,
.err_handler = dccp_v4_err,
@@ -149,6 +152,8 @@ int dccp_disconnect(struct sock *sk, int flags)
return err;
}
+EXPORT_SYMBOL_GPL(dccp_disconnect);
+
/*
* Wait for a DCCP event.
*
@@ -156,8 +161,8 @@ int dccp_disconnect(struct sock *sk, int flags)
* 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 dccp_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
{
unsigned int mask;
struct sock *sk = sock->sk;
@@ -205,12 +210,16 @@ static unsigned int dccp_poll(struct file *file, struct socket *sock,
return mask;
}
+EXPORT_SYMBOL_GPL(dccp_poll);
+
int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
dccp_pr_debug("entry\n");
return -ENOIOCTLCMD;
}
+EXPORT_SYMBOL_GPL(dccp_ioctl);
+
static int dccp_setsockopt_service(struct sock *sk, const u32 service,
char __user *optval, int optlen)
{
@@ -254,7 +263,9 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
int val;
if (level != SOL_DCCP)
- return ip_setsockopt(sk, level, optname, optval, optlen);
+ return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
+ optname, optval,
+ optlen);
if (optlen < sizeof(int))
return -EINVAL;
@@ -282,6 +293,8 @@ int dccp_setsockopt(struct sock *sk, int level, int optname,
return err;
}
+EXPORT_SYMBOL_GPL(dccp_setsockopt);
+
static int dccp_getsockopt_service(struct sock *sk, int len,
u32 __user *optval,
int __user *optlen)
@@ -320,8 +333,9 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
int val, len;
if (level != SOL_DCCP)
- return ip_getsockopt(sk, level, optname, optval, optlen);
-
+ return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level,
+ optname, optval,
+ optlen);
if (get_user(len, optlen))
return -EFAULT;
@@ -354,6 +368,8 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
return 0;
}
+EXPORT_SYMBOL_GPL(dccp_getsockopt);
+
int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len)
{
@@ -410,6 +426,8 @@ out_discard:
goto out_release;
}
+EXPORT_SYMBOL_GPL(dccp_sendmsg);
+
int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len, int nonblock, int flags, int *addr_len)
{
@@ -507,7 +525,9 @@ out:
return len;
}
-static int inet_dccp_listen(struct socket *sock, int backlog)
+EXPORT_SYMBOL_GPL(dccp_recvmsg);
+
+int inet_dccp_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
@@ -543,6 +563,8 @@ out:
return err;
}
+EXPORT_SYMBOL_GPL(inet_dccp_listen);
+
static const unsigned char dccp_new_state[] = {
/* current state: new state: action: */
[0] = DCCP_CLOSED,
@@ -648,12 +670,16 @@ adjudge_to_death:
sock_put(sk);
}
+EXPORT_SYMBOL_GPL(dccp_close);
+
void dccp_shutdown(struct sock *sk, int how)
{
dccp_pr_debug("entry\n");
}
-static struct proto_ops inet_dccp_ops = {
+EXPORT_SYMBOL_GPL(dccp_shutdown);
+
+static const struct proto_ops inet_dccp_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
@@ -681,11 +707,11 @@ 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,
+ .prot = &dccp_prot,
.ops = &inet_dccp_ops,
.capability = -1,
.no_check = 0,
- .flags = 0,
+ .flags = INET_PROTOSW_ICSK,
};
/*
@@ -760,13 +786,15 @@ MODULE_PARM_DESC(thash_entries, "Number of ehash buckets");
int dccp_debug;
module_param(dccp_debug, int, 0444);
MODULE_PARM_DESC(dccp_debug, "Enable debug messages");
+
+EXPORT_SYMBOL_GPL(dccp_debug);
#endif
static int __init dccp_init(void)
{
unsigned long goal;
int ehash_order, bhash_order, i;
- int rc = proto_register(&dccp_v4_prot, 1);
+ int rc = proto_register(&dccp_prot, 1);
if (rc)
goto out;
@@ -869,7 +897,7 @@ 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);
+ proto_unregister(&dccp_prot);
goto out;
}
@@ -892,7 +920,7 @@ static void __exit dccp_fini(void)
get_order(dccp_hashinfo.ehash_size *
sizeof(struct inet_ehash_bucket)));
kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
- proto_unregister(&dccp_v4_prot);
+ proto_unregister(&dccp_prot);
}
module_init(dccp_init);
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index d402e9020c68..ce4aaf94860d 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -122,6 +122,7 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <net/flow.h>
#include <asm/system.h>
#include <asm/ioctls.h>
+#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
@@ -149,7 +150,7 @@ static void dn_keepalive(struct sock *sk);
#define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1)
-static struct proto_ops dn_proto_ops;
+static const struct proto_ops dn_proto_ops;
static DEFINE_RWLOCK(dn_hash_lock);
static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
static struct hlist_head dn_wild_sk;
@@ -1252,7 +1253,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
default:
- err = dev_ioctl(cmd, (void __user *)arg);
+ err = -ENOIOCTLCMD;
break;
}
@@ -2342,7 +2343,7 @@ static struct net_proto_family dn_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops dn_proto_ops = {
+static const struct proto_ops dn_proto_ops = {
.family = AF_DECnet,
.owner = THIS_MODULE,
.release = dn_release,
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 5610bb16dbf9..efbead83ba7f 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -25,6 +25,7 @@
*/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 8d0cc3cf3e49..33ab256cfd4a 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -408,11 +408,14 @@ int dn_neigh_router_hello(struct sk_buff *skb)
}
}
- if (!dn_db->router) {
- dn_db->router = neigh_clone(neigh);
- } else {
- if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority)
- neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
+ /* Only use routers in our area */
+ if ((dn_ntohs(src)>>10) == dn_ntohs((decnet_address)>>10)) {
+ if (!dn_db->router) {
+ dn_db->router = neigh_clone(neigh);
+ } else {
+ if (msg->priority > ((struct dn_neigh *)dn_db->router)->priority)
+ neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
+ }
}
write_unlock(&neigh->lock);
neigh_release(neigh);
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 369f25b60f3f..44bda85e678f 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -793,7 +793,6 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
got_it:
if (sk != NULL) {
struct dn_scp *scp = DN_SK(sk);
- int ret;
/* Reset backoff */
scp->nsp_rxtshift = 0;
@@ -807,21 +806,7 @@ got_it:
goto free_out;
}
- bh_lock_sock(sk);
- ret = NET_RX_SUCCESS;
- if (decnet_debug_level & 8)
- printk(KERN_DEBUG "NSP: 0x%02x 0x%02x 0x%04x 0x%04x %d\n",
- (int)cb->rt_flags, (int)cb->nsp_flags,
- (int)cb->src_port, (int)cb->dst_port,
- !!sock_owned_by_user(sk));
- if (!sock_owned_by_user(sk))
- ret = dn_nsp_backlog_rcv(sk, skb);
- else
- sk_add_backlog(sk, skb);
- bh_unlock_sock(sk);
- sock_put(sk);
-
- return ret;
+ return sk_receive_skb(sk, skb);
}
return dn_nsp_no_socket(skb, reason);
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 1ab94c6e22ed..16a5a31e2126 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -26,8 +26,6 @@
#include <net/dn.h>
#include <net/dn_route.h>
-#include <linux/netfilter_decnet.h>
-
static struct sock *dnrmg = NULL;
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 34fdac51df96..c792994d7952 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -31,6 +31,7 @@
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <linux/skbuff.h>
+#include <linux/udp.h>
#include <net/sock.h>
#include <net/inet_common.h>
#include <linux/stat.h>
@@ -45,7 +46,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-static struct proto_ops econet_ops;
+static const struct proto_ops econet_ops;
static struct hlist_head econet_sklist;
static DEFINE_RWLOCK(econet_lock);
@@ -56,7 +57,7 @@ static struct net_device *net2dev_map[256];
#define EC_PORT_IP 0xd2
#ifdef CONFIG_ECONET_AUNUDP
-static spinlock_t aun_queue_lock;
+static DEFINE_SPINLOCK(aun_queue_lock);
static struct socket *udpsock;
#define AUN_PORT 0x8000
@@ -686,7 +687,7 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
break;
default:
- return dev_ioctl(cmd, argp);
+ return -ENOIOCTLCMD;
}
/*NOTREACHED*/
return 0;
@@ -698,7 +699,7 @@ static struct net_proto_family econet_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
.family = PF_ECONET,
.owner = THIS_MODULE,
.release = econet_release,
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index e24577367274..9890fd97e538 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -53,6 +53,7 @@
#include <linux/errno.h>
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/if_ether.h>
#include <net/dst.h>
#include <net/arp.h>
#include <net/sock.h>
@@ -162,7 +163,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
skb_pull(skb,ETH_HLEN);
eth = eth_hdr(skb);
- if (*eth->h_dest&1) {
+ if (is_multicast_ether_addr(eth->h_dest)) {
if (!compare_ether_addr(eth->h_dest, dev->broadcast))
skb->pkt_type = PACKET_BROADCAST;
else
@@ -251,7 +252,7 @@ static int eth_mac_addr(struct net_device *dev, void *p)
static int eth_change_mtu(struct net_device *dev, int new_mtu)
{
- if ((new_mtu < 68) || (new_mtu > 1500))
+ if (new_mtu < 68 || new_mtu > ETH_DATA_LEN)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
@@ -272,7 +273,7 @@ void ether_setup(struct net_device *dev)
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
- dev->mtu = 1500; /* eth_mtu */
+ dev->mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 1000; /* Ethernet wants good queues */
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 073aebdf0f67..f8dca31be5dd 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -75,22 +75,14 @@ static void prism2_wep_deinit(void *priv)
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)
+/* Add WEP IV/key info to a frame that has at least 4 bytes of headroom */
+static int prism2_wep_build_iv(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)
+ u32 klen, len;
+ u8 *pos;
+
+ if (skb_headroom(skb) < 4 || skb->len < hdr_len)
return -1;
len = skb->len - hdr_len;
@@ -112,15 +104,47 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
/* 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->iv >> 16) & 0xff;
+ *pos++ = (wep->iv >> 8) & 0xff;
+ *pos++ = wep->iv & 0xff;
*pos++ = wep->key_idx << 6;
+ return 0;
+}
+
+/* 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 *pos, *icv;
+ struct scatterlist sg;
+ u8 key[WEP_KEY_LEN + 3];
+
+ /* other checks are in prism2_wep_build_iv */
+ if (skb_tailroom(skb) < 4)
+ return -1;
+
+ /* add the IV to the frame */
+ if (prism2_wep_build_iv(skb, hdr_len, priv))
+ return -1;
+
+ /* Copy the IV into the first 3 bytes of the key */
+ memcpy(key, skb->data + hdr_len, 3);
+
/* Copy rest of the WEP key (the secret part) */
memcpy(key + 3, wep->key, wep->key_len);
+
+ len = skb->len - hdr_len - 4;
+ pos = skb->data + hdr_len + 4;
+ klen = 3 + wep->key_len;
- /* Append little-endian CRC32 and encrypt it to produce ICV */
+ /* Append little-endian CRC32 over only the data and encrypt it to produce ICV */
crc = ~crc32_le(~0, pos, len);
icv = skb_put(skb, 4);
icv[0] = crc;
@@ -231,6 +255,7 @@ static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
.name = "WEP",
.init = prism2_wep_init,
.deinit = prism2_wep_deinit,
+ .build_iv = prism2_wep_build_iv,
.encrypt_mpdu = prism2_wep_encrypt,
.decrypt_mpdu = prism2_wep_decrypt,
.encrypt_msdu = NULL,
diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c
index 321287bc887f..90d18b72da3d 100644
--- a/net/ieee80211/ieee80211_module.c
+++ b/net/ieee80211/ieee80211_module.c
@@ -62,7 +62,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
-static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
+static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
{
if (ieee->networks)
return 0;
@@ -90,7 +90,7 @@ static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
ieee->networks = NULL;
}
-static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
+static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
{
int i;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 03efaacbdb73..7a121802faa9 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -35,7 +35,7 @@
#include <net/ieee80211.h>
-static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
+static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats)
{
@@ -76,8 +76,8 @@ static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
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)
+ !compare_ether_addr(entry->src_addr, src) &&
+ !compare_ether_addr(entry->dst_addr, dst))
return entry;
}
@@ -165,7 +165,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
* Responsible for handling management control frames
*
* Called by ieee80211_rx */
-static inline int
+static int
ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats, u16 type,
u16 stype)
@@ -243,12 +243,12 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
/* 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) {
+ !compare_ether_addr(hdr->addr1, dev->dev_addr) &&
+ !compare_ether_addr(hdr->addr3, dev->dev_addr)) {
/* 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) {
+ !compare_ether_addr(hdr->addr1, dev->dev_addr)) {
/* FromDS frame with own addr as DA */
} else
return 0;
@@ -266,7 +266,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
}
/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
+static int
ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
struct ieee80211_crypt_data *crypt)
{
@@ -297,7 +297,7 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
}
/* Called only as a tasklet (software IRQ), by ieee80211_rx */
-static inline int
+static int
ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
struct sk_buff *skb, int keyidx,
struct ieee80211_crypt_data *crypt)
@@ -410,9 +410,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
return 1;
}
- if ((is_multicast_ether_addr(hdr->addr1) ||
- is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt :
- ieee->host_decrypt) {
+ if (is_multicast_ether_addr(hdr->addr1)
+ ? ieee->host_mc_decrypt : ieee->host_decrypt) {
int idx = 0;
if (skb->len >= hdrlen + 3)
idx = skb->data[hdrlen + 3] >> 6;
@@ -506,7 +505,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
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) {
+ && !compare_ether_addr(hdr->addr2, ieee->assoc_ap_addr)) {
/* Frame from BSSID of the AP for which we are a client */
skb->dev = dev = ieee->stadev;
stats = hostap_get_stats(dev);
@@ -1157,7 +1156,7 @@ static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct iee
/***************************************************/
-static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
+static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
*beacon,
struct ieee80211_network *network,
struct ieee80211_rx_stats *stats)
@@ -1232,11 +1231,11 @@ static inline int is_same_network(struct ieee80211_network *src,
* as one network */
return ((src->ssid_len == dst->ssid_len) &&
(src->channel == dst->channel) &&
- !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
+ !compare_ether_addr(src->bssid, dst->bssid) &&
!memcmp(src->ssid, dst->ssid, src->ssid_len));
}
-static inline void update_network(struct ieee80211_network *dst,
+static void update_network(struct ieee80211_network *dst,
struct ieee80211_network *src)
{
int qos_active;
@@ -1295,7 +1294,7 @@ static inline int is_beacon(int fc)
return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
}
-static inline void ieee80211_process_probe_response(struct ieee80211_device
+static void ieee80211_process_probe_response(struct ieee80211_device
*ieee, struct
ieee80211_probe_response
*beacon, struct ieee80211_rx_stats
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 445f206e65e0..8fdd943ebe8e 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -127,7 +127,7 @@ payload of each frame is reduced to 492 bytes.
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_copy_snap(u8 * data, u16 h_proto)
+static int ieee80211_copy_snap(u8 * data, u16 h_proto)
{
struct ieee80211_snap_hdr *snap;
u8 *oui;
@@ -150,7 +150,7 @@ static inline int ieee80211_copy_snap(u8 * data, u16 h_proto)
return SNAP_SIZE + sizeof(u16);
}
-static inline int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
+static 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];
@@ -288,7 +288,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
/* Determine total amount of storage required for TXB packets */
bytes = skb->len + SNAP_SIZE + sizeof(u16);
- if (host_encrypt)
+ if (host_encrypt || host_build_iv)
fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
IEEE80211_FCTL_PROTECTED;
else
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 181755f2aa8b..23e1630f50b7 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -42,7 +42,7 @@ static const char *ieee80211_modes[] = {
};
#define MAX_CUSTOM_LEN 64
-static inline char *ipw2100_translate_scan(struct ieee80211_device *ieee,
+static char *ipw2100_translate_scan(struct ieee80211_device *ieee,
char *start, char *stop,
struct ieee80211_network *network)
{
@@ -284,7 +284,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
};
int i, key, key_provided, len;
struct ieee80211_crypt_data **crypt;
- int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
+ int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
IEEE80211_DEBUG_WX("SET_ENCODE\n");
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e55136ae09f4..011cca7ae02b 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -456,6 +456,14 @@ config TCP_CONG_BIC
increase provides TCP friendliness.
See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/
+config TCP_CONG_CUBIC
+ tristate "CUBIC TCP"
+ default m
+ ---help---
+ This is version 2.0 of BIC-TCP which uses a cubic growth function
+ among other techniques.
+ See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
+
config TCP_CONG_WESTWOOD
tristate "TCP Westwood+"
default m
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index f0435d00db6b..35e5f5999092 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -9,7 +9,7 @@ obj-y := route.o inetpeer.o protocol.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 netfilter.o
+ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
@@ -28,12 +28,13 @@ obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
-obj-$(CONFIG_NETFILTER) += netfilter/
+obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
obj-$(CONFIG_IP_VS) += ipvs/
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_CUBIC) += tcp_cubic.o
obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d368cf249000..97c276f95b35 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -79,6 +79,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -93,6 +94,7 @@
#include <linux/smp_lock.h>
#include <linux/inet.h>
#include <linux/igmp.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <net/ip.h>
#include <net/protocol.h>
@@ -302,6 +304,7 @@ lookup_protocol:
sk->sk_reuse = 1;
inet = inet_sk(sk);
+ inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
@@ -775,16 +778,16 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
err = devinet_ioctl(cmd, (void __user *)arg);
break;
default:
- if (!sk->sk_prot->ioctl ||
- (err = sk->sk_prot->ioctl(sk, cmd, arg)) ==
- -ENOIOCTLCMD)
- err = dev_ioctl(cmd, (void __user *)arg);
+ if (sk->sk_prot->ioctl)
+ err = sk->sk_prot->ioctl(sk, cmd, arg);
+ else
+ err = -ENOIOCTLCMD;
break;
}
return err;
}
-struct proto_ops inet_stream_ops = {
+const struct proto_ops inet_stream_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
@@ -805,7 +808,7 @@ struct proto_ops inet_stream_ops = {
.sendpage = tcp_sendpage
};
-struct proto_ops inet_dgram_ops = {
+const struct proto_ops inet_dgram_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
@@ -830,7 +833,7 @@ struct proto_ops inet_dgram_ops = {
* For SOCK_RAW sockets; should be the same as inet_dgram_ops but without
* udp_poll
*/
-static struct proto_ops inet_sockraw_ops = {
+static const struct proto_ops inet_sockraw_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
@@ -869,7 +872,8 @@ static struct inet_protosw inetsw_array[] =
.ops = &inet_stream_ops,
.capability = -1,
.no_check = 0,
- .flags = INET_PROTOSW_PERMANENT,
+ .flags = INET_PROTOSW_PERMANENT |
+ INET_PROTOSW_ICSK,
},
{
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 035ad2c9e1ba..aed537fa2c88 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -6,6 +6,7 @@
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
#include <net/icmp.h>
+#include <net/protocol.h>
#include <asm/scatterlist.h>
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index b425748f02d7..accdefedfed7 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -79,6 +79,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/socket.h>
#include <linux/sockios.h>
@@ -86,6 +87,7 @@
#include <linux/in.h>
#include <linux/mm.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/fddidevice.h>
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 04a6fe3e95a2..95b9d81ac488 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -32,6 +32,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -58,6 +59,7 @@
#endif
#include <linux/kmod.h>
+#include <net/arp.h>
#include <net/ip.h>
#include <net/route.h>
#include <net/ip_fib.h>
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 1b18ce66e7b7..73bfcae8af9c 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -9,6 +9,7 @@
#include <linux/pfkeyv2.h>
#include <linux/random.h>
#include <net/icmp.h>
+#include <net/protocol.h>
#include <net/udp.h>
/* decapsulation data for use when post-processing */
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 19b1b984d687..4e3d3811dea2 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -20,6 +20,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/bitops.h>
+#include <linux/capability.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -30,6 +31,7 @@
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
@@ -287,13 +289,13 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
{
int i;
- for (i=1; i<=RTA_MAX; i++) {
- struct rtattr *attr = rta[i-1];
+ for (i=1; i<=RTA_MAX; i++, rta++) {
+ struct rtattr *attr = *rta;
if (attr) {
if (RTA_PAYLOAD(attr) < 4)
return -EINVAL;
if (i != RTA_MULTIPATH && i != RTA_METRICS)
- rta[i-1] = (struct rtattr*)RTA_DATA(attr);
+ *rta = (struct rtattr*)RTA_DATA(attr);
}
}
return 0;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 7ea0209cb169..e2890ec8159e 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -29,6 +29,7 @@
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0b298bbc1518..0dd4d06e456d 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -33,6 +33,7 @@
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 6d2a6ac070e3..ef4724de7350 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -29,6 +29,7 @@
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
@@ -36,6 +37,7 @@
#include <linux/netlink.h>
#include <linux/init.h>
+#include <net/arp.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 705e3ce86df9..e320b32373e5 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -41,6 +41,13 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * Substantial contributions to this work comes from:
+ *
+ * David S. Miller, <davem@davemloft.net>
+ * Stephen Hemminger <shemminger@osdl.org>
+ * Paul E. McKenney <paulmck@us.ibm.com>
+ * Patrick McHardy <kaber@trash.net>
*/
#define VERSION "0.404"
@@ -59,6 +66,7 @@
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 92e23b2ad4d2..105039eb7629 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -73,6 +73,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/string.h>
#include <linux/netfilter_ipv4.h>
@@ -898,8 +899,7 @@ static void icmp_address_reply(struct sk_buff *skb)
u32 _mask, *mp;
mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
- if (mp == NULL)
- BUG();
+ BUG_ON(mp == NULL);
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
if (*mp == ifa->ifa_mask &&
inet_ifa_match(rt->rt_src, ifa))
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 4a195c724f01..d8ce7133cd8f 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -91,6 +91,8 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/times.h>
+
+#include <net/arp.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
@@ -231,7 +233,18 @@ static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type,
case IGMPV3_MODE_IS_EXCLUDE:
if (gdeleted || sdeleted)
return 0;
- return !(pmc->gsquery && !psf->sf_gsresp);
+ if (!(pmc->gsquery && !psf->sf_gsresp)) {
+ if (pmc->sfmode == MCAST_INCLUDE)
+ return 1;
+ /* don't include if this source is excluded
+ * in all filters
+ */
+ if (psf->sf_count[MCAST_INCLUDE])
+ return type == IGMPV3_MODE_IS_INCLUDE;
+ return pmc->sfcount[MCAST_EXCLUDE] ==
+ psf->sf_count[MCAST_EXCLUDE];
+ }
+ return 0;
case IGMPV3_CHANGE_TO_INCLUDE:
if (gdeleted || sdeleted)
return 0;
@@ -383,7 +396,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
struct igmpv3_report *pih;
struct igmpv3_grec *pgr = NULL;
struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list;
- int scount, first, isquery, truncate;
+ int scount, stotal, first, isquery, truncate;
if (pmc->multiaddr == IGMP_ALL_HOSTS)
return skb;
@@ -393,25 +406,13 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
truncate = type == IGMPV3_MODE_IS_EXCLUDE ||
type == IGMPV3_CHANGE_TO_EXCLUDE;
+ stotal = scount = 0;
+
psf_list = sdeleted ? &pmc->tomb : &pmc->sources;
- if (!*psf_list) {
- if (type == IGMPV3_ALLOW_NEW_SOURCES ||
- type == IGMPV3_BLOCK_OLD_SOURCES)
- return skb;
- if (pmc->crcount || isquery) {
- /* make sure we have room for group header and at
- * least one source.
- */
- if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)+
- sizeof(__u32)) {
- igmpv3_sendpack(skb);
- skb = NULL; /* add_grhead will get a new one */
- }
- skb = add_grhead(skb, pmc, type, &pgr);
- }
- return skb;
- }
+ if (!*psf_list)
+ goto empty_source;
+
pih = skb ? (struct igmpv3_report *)skb->h.igmph : NULL;
/* EX and TO_EX get a fresh packet, if needed */
@@ -424,7 +425,6 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
}
}
first = 1;
- scount = 0;
psf_prev = NULL;
for (psf=*psf_list; psf; psf=psf_next) {
u32 *psrc;
@@ -458,7 +458,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
}
psrc = (u32 *)skb_put(skb, sizeof(u32));
*psrc = psf->sf_inaddr;
- scount++;
+ scount++; stotal++;
if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) {
psf->sf_crcount--;
@@ -473,6 +473,21 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
}
psf_prev = psf;
}
+
+empty_source:
+ if (!stotal) {
+ if (type == IGMPV3_ALLOW_NEW_SOURCES ||
+ type == IGMPV3_BLOCK_OLD_SOURCES)
+ return skb;
+ if (pmc->crcount || isquery) {
+ /* make sure we have room for group header */
+ if (skb && AVAILABLE(skb)<sizeof(struct igmpv3_grec)) {
+ igmpv3_sendpack(skb);
+ skb = NULL; /* add_grhead will get a new one */
+ }
+ skb = add_grhead(skb, pmc, type, &pgr);
+ }
+ }
if (pgr)
pgr->grec_nsrcs = htons(scount);
@@ -555,11 +570,11 @@ static void igmpv3_send_cr(struct in_device *in_dev)
skb = add_grec(skb, pmc, dtype, 1, 1);
}
if (pmc->crcount) {
- pmc->crcount--;
if (pmc->sfmode == MCAST_EXCLUDE) {
type = IGMPV3_CHANGE_TO_INCLUDE;
skb = add_grec(skb, pmc, type, 1, 0);
}
+ pmc->crcount--;
if (pmc->crcount == 0) {
igmpv3_clear_zeros(&pmc->tomb);
igmpv3_clear_zeros(&pmc->sources);
@@ -592,12 +607,12 @@ static void igmpv3_send_cr(struct in_device *in_dev)
/* filter mode changes */
if (pmc->crcount) {
- pmc->crcount--;
if (pmc->sfmode == MCAST_EXCLUDE)
type = IGMPV3_CHANGE_TO_EXCLUDE;
else
type = IGMPV3_CHANGE_TO_INCLUDE;
skb = add_grec(skb, pmc, type, 0, 0);
+ pmc->crcount--;
}
spin_unlock_bh(&pmc->lock);
}
@@ -733,7 +748,8 @@ static void igmp_timer_expire(unsigned long data)
ip_ma_put(im);
}
-static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+/* mark EXCLUDE-mode sources */
+static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
{
struct ip_sf_list *psf;
int i, scount;
@@ -742,6 +758,37 @@ static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
for (psf=pmc->sources; psf; psf=psf->sf_next) {
if (scount == nsrcs)
break;
+ for (i=0; i<nsrcs; i++) {
+ /* skip inactive filters */
+ if (pmc->sfcount[MCAST_INCLUDE] ||
+ pmc->sfcount[MCAST_EXCLUDE] !=
+ psf->sf_count[MCAST_EXCLUDE])
+ continue;
+ if (srcs[i] == psf->sf_inaddr) {
+ scount++;
+ break;
+ }
+ }
+ }
+ pmc->gsquery = 0;
+ if (scount == nsrcs) /* all sources excluded */
+ return 0;
+ return 1;
+}
+
+static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+{
+ struct ip_sf_list *psf;
+ int i, scount;
+
+ if (pmc->sfmode == MCAST_EXCLUDE)
+ return igmp_xmarksources(pmc, nsrcs, srcs);
+
+ /* mark INCLUDE-mode sources */
+ scount = 0;
+ for (psf=pmc->sources; psf; psf=psf->sf_next) {
+ if (scount == nsrcs)
+ break;
for (i=0; i<nsrcs; i++)
if (srcs[i] == psf->sf_inaddr) {
psf->sf_gsresp = 1;
@@ -749,6 +796,12 @@ static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
break;
}
}
+ if (!scount) {
+ pmc->gsquery = 0;
+ return 0;
+ }
+ pmc->gsquery = 1;
+ return 1;
}
static void igmp_heard_report(struct in_device *in_dev, u32 group)
@@ -843,6 +896,8 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
*/
read_lock(&in_dev->mc_list_lock);
for (im=in_dev->mc_list; im!=NULL; im=im->next) {
+ int changed;
+
if (group && group != im->multiaddr)
continue;
if (im->multiaddr == IGMP_ALL_HOSTS)
@@ -852,10 +907,11 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
im->gsquery = im->gsquery && mark;
else
im->gsquery = mark;
- if (im->gsquery)
- igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
+ changed = !im->gsquery ||
+ igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
spin_unlock_bh(&im->lock);
- igmp_mod_timer(im, max_delay);
+ if (changed)
+ igmp_mod_timer(im, max_delay);
}
read_unlock(&in_dev->mc_list_lock);
}
@@ -973,7 +1029,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
* for deleted items allows change reports to use common code with
* non-deleted or query-response MCA's.
*/
- pmc = (struct ip_mc_list *)kmalloc(sizeof(*pmc), GFP_KERNEL);
+ pmc = kmalloc(sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return;
memset(pmc, 0, sizeof(*pmc));
@@ -1153,7 +1209,7 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
}
}
- im = (struct ip_mc_list *)kmalloc(sizeof(*im), GFP_KERNEL);
+ im = kmalloc(sizeof(*im), GFP_KERNEL);
if (!im)
goto out;
@@ -1474,7 +1530,7 @@ static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
psf_prev = psf;
}
if (!psf) {
- psf = (struct ip_sf_list *)kmalloc(sizeof(*psf), GFP_ATOMIC);
+ psf = kmalloc(sizeof(*psf), GFP_ATOMIC);
if (!psf)
return -ENOBUFS;
memset(psf, 0, sizeof(*psf));
@@ -1508,7 +1564,7 @@ static void sf_markstate(struct ip_mc_list *pmc)
static int sf_setstate(struct ip_mc_list *pmc)
{
- struct ip_sf_list *psf;
+ struct ip_sf_list *psf, *dpsf;
int mca_xcount = pmc->sfcount[MCAST_EXCLUDE];
int qrv = pmc->interface->mr_qrv;
int new_in, rv;
@@ -1520,8 +1576,46 @@ static int sf_setstate(struct ip_mc_list *pmc)
!psf->sf_count[MCAST_INCLUDE];
} else
new_in = psf->sf_count[MCAST_INCLUDE] != 0;
- if (new_in != psf->sf_oldin) {
- psf->sf_crcount = qrv;
+ if (new_in) {
+ if (!psf->sf_oldin) {
+ struct ip_sf_list *prev = 0;
+
+ for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next) {
+ if (dpsf->sf_inaddr == psf->sf_inaddr)
+ break;
+ prev = dpsf;
+ }
+ if (dpsf) {
+ if (prev)
+ prev->sf_next = dpsf->sf_next;
+ else
+ pmc->tomb = dpsf->sf_next;
+ kfree(dpsf);
+ }
+ psf->sf_crcount = qrv;
+ rv++;
+ }
+ } else if (psf->sf_oldin) {
+
+ psf->sf_crcount = 0;
+ /*
+ * add or update "delete" records if an active filter
+ * is now inactive
+ */
+ for (dpsf=pmc->tomb; dpsf; dpsf=dpsf->sf_next)
+ if (dpsf->sf_inaddr == psf->sf_inaddr)
+ break;
+ if (!dpsf) {
+ dpsf = (struct ip_sf_list *)
+ kmalloc(sizeof(*dpsf), GFP_ATOMIC);
+ if (!dpsf)
+ continue;
+ *dpsf = *psf;
+ /* pmc->lock held by callers */
+ dpsf->sf_next = pmc->tomb;
+ pmc->tomb = dpsf;
+ }
+ dpsf->sf_crcount = qrv;
rv++;
}
}
@@ -1657,7 +1751,7 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
err = -ENOBUFS;
if (count >= sysctl_igmp_max_memberships)
goto done;
- iml = (struct ip_mc_socklist *)sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL);
+ iml = sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL);
if (iml == NULL)
goto done;
@@ -1821,8 +1915,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
if (psl)
count += psl->sl_max;
- newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk,
- IP_SFLSIZE(count), GFP_KERNEL);
+ newpsl = sock_kmalloc(sk, IP_SFLSIZE(count), GFP_KERNEL);
if (!newpsl) {
err = -ENOBUFS;
goto done;
@@ -1905,8 +1998,8 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
goto done;
}
if (msf->imsf_numsrc) {
- newpsl = (struct ip_sf_socklist *)sock_kmalloc(sk,
- IP_SFLSIZE(msf->imsf_numsrc), GFP_KERNEL);
+ newpsl = sock_kmalloc(sk, IP_SFLSIZE(msf->imsf_numsrc),
+ GFP_KERNEL);
if (!newpsl) {
err = -ENOBUFS;
goto done;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 3fe021f1a566..ae20281d8deb 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -37,7 +37,8 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg);
*/
int sysctl_local_port_range[2] = { 1024, 4999 };
-static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucket *tb)
+int inet_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb)
{
const u32 sk_rcv_saddr = inet_rcv_saddr(sk);
struct sock *sk2;
@@ -62,11 +63,15 @@ static inline int inet_csk_bind_conflict(struct sock *sk, struct inet_bind_bucke
return node != NULL;
}
+EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
+
/* 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 sock *sk, unsigned short snum,
+ int (*bind_conflict)(const struct sock *sk,
+ const struct inet_bind_bucket *tb))
{
struct inet_bind_hashbucket *head;
struct hlist_node *node;
@@ -125,7 +130,7 @@ tb_found:
goto success;
} else {
ret = 1;
- if (inet_csk_bind_conflict(sk, tb))
+ if (bind_conflict(sk, tb))
goto fail_unlock;
}
}
@@ -380,7 +385,7 @@ struct request_sock *inet_csk_search_req(const struct sock *sk,
EXPORT_SYMBOL_GPL(inet_csk_search_req);
void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
- const unsigned timeout)
+ unsigned long timeout)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
@@ -631,3 +636,15 @@ void inet_csk_listen_stop(struct sock *sk)
}
EXPORT_SYMBOL_GPL(inet_csk_listen_stop);
+
+void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)uaddr;
+ const struct inet_sock *inet = inet_sk(sk);
+
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet->daddr;
+ sin->sin_port = inet->dport;
+}
+
+EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 39061ed53cfd..457db99c76df 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -50,9 +50,10 @@ 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)
+static int inet_csk_diag_fill(struct sock *sk,
+ struct sk_buff *skb,
+ 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);
@@ -70,20 +71,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
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);
- }
+ BUG_ON(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) {
+ const 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;
@@ -93,37 +96,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk,
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;
@@ -185,7 +157,75 @@ nlmsg_failure:
return -1;
}
-static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh)
+static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
+ struct sk_buff *skb, int ext, u32 pid,
+ u32 seq, u16 nlmsg_flags,
+ const struct nlmsghdr *unlh)
+{
+ long tmo;
+ struct inet_diag_msg *r;
+ const unsigned char *previous_tail = skb->tail;
+ struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq,
+ unlh->nlmsg_type, sizeof(*r));
+
+ r = NLMSG_DATA(nlh);
+ BUG_ON(tw->tw_state != TCP_TIME_WAIT);
+
+ nlh->nlmsg_flags = nlmsg_flags;
+
+ tmo = tw->tw_ttd - jiffies;
+ if (tmo < 0)
+ tmo = 0;
+
+ r->idiag_family = tw->tw_family;
+ r->idiag_state = tw->tw_state;
+ r->idiag_timer = 0;
+ r->idiag_retrans = 0;
+ r->id.idiag_if = tw->tw_bound_dev_if;
+ r->id.idiag_cookie[0] = (u32)(unsigned long)tw;
+ r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1);
+ 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 (tw->tw_family == AF_INET6) {
+ const struct inet6_timewait_sock *tw6 =
+ inet6_twsk((struct sock *)tw);
+
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
+ &tw6->tw_v6_rcv_saddr);
+ ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
+ &tw6->tw_v6_daddr);
+ }
+#endif
+ nlh->nlmsg_len = skb->tail - previous_tail;
+ return skb->len;
+nlmsg_failure:
+ skb_trim(skb, previous_tail - skb->data);
+ return -1;
+}
+
+static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
+ int ext, u32 pid, u32 seq, u16 nlmsg_flags,
+ const struct nlmsghdr *unlh)
+{
+ if (sk->sk_state == TCP_TIME_WAIT)
+ return inet_twsk_diag_fill((struct inet_timewait_sock *)sk,
+ skb, ext, pid, seq, nlmsg_flags,
+ unlh);
+ return inet_csk_diag_fill(sk, skb, ext, pid, seq, nlmsg_flags, unlh);
+}
+
+static int inet_diag_get_exact(struct sk_buff *in_skb,
+ const struct nlmsghdr *nlh)
{
int err;
struct sock *sk;
@@ -235,7 +275,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nl
if (!rep)
goto out;
- if (inet_diag_fill(rep, sk, req->idiag_ext,
+ if (sk_diag_fill(sk, rep, req->idiag_ext,
NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, 0, nlh) <= 0)
BUG();
@@ -283,7 +323,7 @@ static int bitstring_match(const u32 *a1, const u32 *a2, int bits)
static int inet_diag_bc_run(const void *bc, int len,
- const struct inet_diag_entry *entry)
+ const struct inet_diag_entry *entry)
{
while (len > 0) {
int yes = 1;
@@ -322,7 +362,7 @@ static int inet_diag_bc_run(const void *bc, int len,
yes = 0;
break;
}
-
+
if (cond->prefix_len == 0)
break;
@@ -331,7 +371,8 @@ static int inet_diag_bc_run(const void *bc, int len,
else
addr = entry->daddr;
- if (bitstring_match(addr, cond->addr, cond->prefix_len))
+ if (bitstring_match(addr, cond->addr,
+ cond->prefix_len))
break;
if (entry->family == AF_INET6 &&
cond->family == AF_INET) {
@@ -346,7 +387,7 @@ static int inet_diag_bc_run(const void *bc, int len,
}
}
- if (yes) {
+ if (yes) {
len -= op->yes;
bc += op->yes;
} else {
@@ -407,14 +448,15 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
default:
return -EINVAL;
}
- bc += op->yes;
+ 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)
+static int inet_csk_diag_dump(struct sock *sk,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
{
struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
@@ -444,14 +486,50 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk,
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);
+ return inet_csk_diag_fill(sk, skb, r->idiag_ext,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+}
+
+static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
+ struct sk_buff *skb,
+ 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);
+
+ entry.family = tw->tw_family;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+ if (tw->tw_family == AF_INET6) {
+ struct inet6_timewait_sock *tw6 =
+ inet6_twsk((struct sock *)tw);
+ entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32;
+ entry.daddr = tw6->tw_v6_daddr.s6_addr32;
+ } else
+#endif
+ {
+ entry.saddr = &tw->tw_rcv_saddr;
+ entry.daddr = &tw->tw_daddr;
+ }
+ entry.sport = tw->tw_num;
+ entry.dport = ntohs(tw->tw_dport);
+ entry.userlocks = 0;
+
+ if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry))
+ return 0;
+ }
+
+ return inet_twsk_diag_fill(tw, skb, 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)
+ 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);
@@ -489,9 +567,9 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
#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);
+ &inet6_rsk(req)->loc_addr);
ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
- &tcp6_rsk(req)->rmt_addr);
+ &inet6_rsk(req)->rmt_addr);
}
#endif
nlh->nlmsg_len = skb->tail - b;
@@ -504,7 +582,7 @@ nlmsg_failure:
}
static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
- struct netlink_callback *cb)
+ struct netlink_callback *cb)
{
struct inet_diag_entry entry;
struct inet_diag_req *r = NLMSG_DATA(cb->nlh);
@@ -553,13 +631,13 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
entry.saddr =
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
(entry.family == AF_INET6) ?
- tcp6_rsk(req)->loc_addr.s6_addr32 :
+ inet6_rsk(req)->loc_addr.s6_addr32 :
#endif
&ireq->loc_addr;
- entry.daddr =
+ entry.daddr =
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
(entry.family == AF_INET6) ?
- tcp6_rsk(req)->rmt_addr.s6_addr32 :
+ inet6_rsk(req)->rmt_addr.s6_addr32 :
#endif
&ireq->rmt_addr;
entry.dport = ntohs(ireq->rmt_port);
@@ -599,7 +677,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
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];
@@ -630,7 +708,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
cb->args[3] > 0)
goto syn_recv;
- if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ if (inet_csk_diag_dump(sk, skb, cb) < 0) {
inet_listen_unlock(hashinfo);
goto done;
}
@@ -672,7 +750,6 @@ skip_listen_ht:
s_num = 0;
read_lock_bh(&head->lock);
-
num = 0;
sk_for_each(sk, node, &head->chain) {
struct inet_sock *inet = inet_sk(sk);
@@ -684,9 +761,10 @@ skip_listen_ht:
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)
+ if (r->id.idiag_dport != inet->dport &&
+ r->id.idiag_dport)
goto next_normal;
- if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ if (inet_csk_diag_dump(sk, skb, cb) < 0) {
read_unlock_bh(&head->lock);
goto done;
}
@@ -695,19 +773,20 @@ next_normal:
}
if (r->idiag_states & TCPF_TIME_WAIT) {
- sk_for_each(sk, node,
+ struct inet_timewait_sock *tw;
+
+ inet_twsk_for_each(tw, 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 &&
+ if (r->id.idiag_sport != tw->tw_sport &&
r->id.idiag_sport)
goto next_dying;
- if (r->id.idiag_dport != inet->dport &&
+ if (r->id.idiag_dport != tw->tw_dport &&
r->id.idiag_dport)
goto next_dying;
- if (inet_diag_dump_sock(skb, sk, cb) < 0) {
+ if (inet_twsk_diag_dump(tw, skb, cb) < 0) {
read_unlock_bh(&head->lock);
goto done;
}
@@ -724,8 +803,7 @@ done:
return skb->len;
}
-static __inline__ int
-inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+static inline int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
return 0;
@@ -755,9 +833,8 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
return netlink_dump_start(idiagnl, skb, nlh,
inet_diag_dump, NULL);
- } else {
+ } else
return inet_diag_get_exact(skb, nlh);
- }
err_inval:
return -EINVAL;
@@ -766,15 +843,15 @@ err_inval:
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)
+ int err;
+ struct nlmsghdr *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)
+ if (err || nlh->nlmsg_flags & NLM_F_ACK)
netlink_ack(skb, nlh, err);
}
}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index e8d29fe736d2..33228115cda4 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -15,12 +15,14 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/random.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <net/inet_connection_sock.h>
#include <net/inet_hashtables.h>
+#include <net/ip.h>
/*
* Allocate and initialize a new local port bind bucket.
@@ -163,3 +165,179 @@ struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 dad
}
EXPORT_SYMBOL_GPL(__inet_lookup_listener);
+
+/* called with local bh disabled */
+static int __inet_check_established(struct inet_timewait_death_row *death_row,
+ struct sock *sk, __u16 lport,
+ struct inet_timewait_sock **twp)
+{
+ struct inet_hashinfo *hinfo = death_row->hashinfo;
+ struct inet_sock *inet = inet_sk(sk);
+ u32 daddr = inet->rcv_saddr;
+ u32 saddr = inet->daddr;
+ int dif = sk->sk_bound_dev_if;
+ INET_ADDR_COOKIE(acookie, saddr, daddr)
+ const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
+ unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+ struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
+ struct sock *sk2;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
+
+ prefetch(head->chain.first);
+ write_lock(&head->lock);
+
+ /* Check TIME-WAIT sockets first. */
+ sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+ tw = inet_twsk(sk2);
+
+ if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
+ if (twsk_unique(sk, sk2, twp))
+ goto unique;
+ else
+ goto not_unique;
+ }
+ }
+ tw = NULL;
+
+ /* And established part... */
+ sk_for_each(sk2, node, &head->chain) {
+ if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
+ goto not_unique;
+ }
+
+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_hash = 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) {
+ *twp = tw;
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+ } else if (tw) {
+ /* Silly. Should hash-dance instead... */
+ inet_twsk_deschedule(tw, death_row);
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+
+ inet_twsk_put(tw);
+ }
+
+ return 0;
+
+not_unique:
+ write_unlock(&head->lock);
+ return -EADDRNOTAVAIL;
+}
+
+static inline u32 inet_sk_port_offset(const struct sock *sk)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ return secure_ipv4_port_ephemeral(inet->rcv_saddr, inet->daddr,
+ inet->dport);
+}
+
+/*
+ * Bind a port for a connect operation and hash it.
+ */
+int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk)
+{
+ struct inet_hashinfo *hinfo = death_row->hashinfo;
+ const unsigned short snum = inet_sk(sk)->num;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
+ int ret;
+
+ if (!snum) {
+ int low = sysctl_local_port_range[0];
+ int high = sysctl_local_port_range[1];
+ int range = high - low;
+ int i;
+ int port;
+ static u32 hint;
+ u32 offset = hint + inet_sk_port_offset(sk);
+ struct hlist_node *node;
+ struct inet_timewait_sock *tw = NULL;
+
+ local_bh_disable();
+ for (i = 1; i <= range; i++) {
+ port = low + (i + offset) % range;
+ head = &hinfo->bhash[inet_bhashfn(port, hinfo->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 == port) {
+ BUG_TRAP(!hlist_empty(&tb->owners));
+ if (tb->fastreuse >= 0)
+ goto next_port;
+ if (!__inet_check_established(death_row,
+ sk, port,
+ &tw))
+ goto ok;
+ goto next_port;
+ }
+ }
+
+ tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, head, port);
+ if (!tb) {
+ spin_unlock(&head->lock);
+ break;
+ }
+ tb->fastreuse = -1;
+ goto ok;
+
+ next_port:
+ spin_unlock(&head->lock);
+ }
+ local_bh_enable();
+
+ return -EADDRNOTAVAIL;
+
+ok:
+ hint += i;
+
+ /* Head lock still held and bh's disabled */
+ inet_bind_hash(sk, tb, port);
+ if (sk_unhashed(sk)) {
+ inet_sk(sk)->sport = htons(port);
+ __inet_hash(hinfo, sk, 0);
+ }
+ spin_unlock(&head->lock);
+
+ if (tw) {
+ inet_twsk_deschedule(tw, death_row);;
+ inet_twsk_put(tw);
+ }
+
+ ret = 0;
+ goto out;
+ }
+
+ head = &hinfo->bhash[inet_bhashfn(snum, hinfo->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) {
+ __inet_hash(hinfo, sk, 0);
+ spin_unlock_bh(&head->lock);
+ return 0;
+ } else {
+ spin_unlock(&head->lock);
+ /* No definite answer... Walk to established hash table */
+ ret = __inet_check_established(death_row, sk, snum, NULL);
+out:
+ local_bh_enable();
+ return ret;
+ }
+}
+
+EXPORT_SYMBOL_GPL(inet_hash_connect);
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index a010e9a68811..417f126c749e 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -90,8 +90,9 @@ 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);
+ struct inet_timewait_sock *tw =
+ kmem_cache_alloc(sk->sk_prot_creator->twsk_prot->twsk_slab,
+ SLAB_ATOMIC);
if (tw != NULL) {
const struct inet_sock *inet = inet_sk(sk);
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 2fc3fd38924f..2160874ce7aa 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -304,8 +304,7 @@ static void unlink_from_pool(struct inet_peer *p)
/* look for a node to insert instead of p */
struct inet_peer *t;
t = lookup_rightempty(p);
- if (*stackptr[-1] != t)
- BUG();
+ BUG_ON(*stackptr[-1] != t);
**--stackptr = t->avl_left;
/* t is removed, t->v4daddr > x->v4daddr for any
* x in p->avl_left subtree.
@@ -314,8 +313,7 @@ static void unlink_from_pool(struct inet_peer *p)
t->avl_left = p->avl_left;
t->avl_right = p->avl_right;
t->avl_height = p->avl_height;
- if (delp[1] != &p->avl_left)
- BUG();
+ BUG_ON(delp[1] != &p->avl_left);
delp[1] = &t->avl_left; /* was &p->avl_left */
}
peer_avl_rebalance(stack, stackptr);
@@ -401,6 +399,7 @@ struct inet_peer *inet_getpeer(__u32 daddr, int create)
return NULL;
n->v4daddr = daddr;
atomic_set(&n->refcnt, 1);
+ atomic_set(&n->rid, 0);
n->ip_id_count = secure_ip_id(daddr);
n->tcp_ts_stamp = 0;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 8ce0ce2ee48e..2a8adda15e11 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -22,6 +22,7 @@
* Patrick McHardy : LRU queue of frag heads for evictor.
*/
+#include <linux/compiler.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -38,6 +39,7 @@
#include <net/ip.h>
#include <net/icmp.h>
#include <net/checksum.h>
+#include <net/inetpeer.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/inet.h>
@@ -56,6 +58,8 @@
int sysctl_ipfrag_high_thresh = 256*1024;
int sysctl_ipfrag_low_thresh = 192*1024;
+int sysctl_ipfrag_max_dist = 64;
+
/* Important NOTE! Fragment queue must be destroyed before MSL expires.
* RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL.
*/
@@ -89,8 +93,10 @@ struct ipq {
spinlock_t lock;
atomic_t refcnt;
struct timer_list timer; /* when will this queue expire? */
- int iif;
struct timeval stamp;
+ int iif;
+ unsigned int rid;
+ struct inet_peer *peer;
};
/* Hash table. */
@@ -195,6 +201,9 @@ static void ip_frag_destroy(struct ipq *qp, int *work)
BUG_TRAP(qp->last_in&COMPLETE);
BUG_TRAP(del_timer(&qp->timer) == 0);
+ if (qp->peer)
+ inet_putpeer(qp->peer);
+
/* Release all fragment data. */
fp = qp->fragments;
while (fp) {
@@ -353,6 +362,7 @@ static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
qp->meat = 0;
qp->fragments = NULL;
qp->iif = 0;
+ qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
/* Initialize a timer for this entry. */
init_timer(&qp->timer);
@@ -373,7 +383,7 @@ out_nomem:
*/
static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
{
- __u16 id = iph->id;
+ __be16 id = iph->id;
__u32 saddr = iph->saddr;
__u32 daddr = iph->daddr;
__u8 protocol = iph->protocol;
@@ -398,6 +408,56 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
return ip_frag_create(hash, iph, user);
}
+/* Is the fragment too far ahead to be part of ipq? */
+static inline int ip_frag_too_far(struct ipq *qp)
+{
+ struct inet_peer *peer = qp->peer;
+ unsigned int max = sysctl_ipfrag_max_dist;
+ unsigned int start, end;
+
+ int rc;
+
+ if (!peer || !max)
+ return 0;
+
+ start = qp->rid;
+ end = atomic_inc_return(&peer->rid);
+ qp->rid = end;
+
+ rc = qp->fragments && (end - start) > max;
+
+ if (rc) {
+ IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
+ }
+
+ return rc;
+}
+
+static int ip_frag_reinit(struct ipq *qp)
+{
+ struct sk_buff *fp;
+
+ if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time)) {
+ atomic_inc(&qp->refcnt);
+ return -ETIMEDOUT;
+ }
+
+ fp = qp->fragments;
+ do {
+ struct sk_buff *xp = fp->next;
+ frag_kfree_skb(fp, NULL);
+ fp = xp;
+ } while (fp);
+
+ qp->last_in = 0;
+ qp->len = 0;
+ qp->meat = 0;
+ qp->fragments = NULL;
+ qp->iif = 0;
+
+ return 0;
+}
+
/* Add new segment to existing queue. */
static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
{
@@ -408,6 +468,12 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (qp->last_in & COMPLETE)
goto err;
+ if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
+ unlikely(ip_frag_too_far(qp)) && unlikely(ip_frag_reinit(qp))) {
+ ipq_kill(qp);
+ goto err;
+ }
+
offset = ntohs(skb->nh.iph->frag_off);
flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 46f9d9cf7a5f..abe23923e4e7 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -10,6 +10,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -28,6 +29,7 @@
#include <linux/inetdevice.h>
#include <linux/igmp.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/if_ether.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -187,7 +189,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
}
if (ipgre_fb_tunnel_dev->flags&IFF_UP)
- return ipgre_fb_tunnel_dev->priv;
+ return netdev_priv(ipgre_fb_tunnel_dev);
return NULL;
}
@@ -277,7 +279,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
return NULL;
dev->init = ipgre_tunnel_init;
- nt = dev->priv;
+ nt = netdev_priv(dev);
nt->parms = *parms;
if (register_netdevice(dev) < 0) {
@@ -285,9 +287,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int
goto failed;
}
- nt = dev->priv;
- nt->parms = *parms;
-
dev_hold(dev);
ipgre_tunnel_link(nt);
return nt;
@@ -298,7 +297,7 @@ failed:
static void ipgre_tunnel_uninit(struct net_device *dev)
{
- ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ ipgre_tunnel_unlink(netdev_priv(dev));
dev_put(dev);
}
@@ -517,7 +516,7 @@ out:
skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
rel_info = htonl(rel_info);
} else if (type == ICMP_TIME_EXCEEDED) {
- struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv;
+ struct ip_tunnel *t = netdev_priv(skb2->dev);
if (t->parms.iph.ttl) {
rel_type = ICMP_DEST_UNREACH;
rel_code = ICMP_HOST_UNREACH;
@@ -668,7 +667,7 @@ drop_nolock:
static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct net_device_stats *stats = &tunnel->stat;
struct iphdr *old_iph = skb->nh.iph;
struct iphdr *tiph;
@@ -831,6 +830,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
skb->nh.raw = skb_push(skb, gre_hlen);
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED);
dst_release(skb->dst);
skb->dst = &rt->u.dst;
@@ -913,7 +913,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t = ipgre_tunnel_locate(&p, 0);
}
if (t == NULL)
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
memcpy(&p, &t->parms, sizeof(p));
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
err = -EFAULT;
@@ -953,7 +953,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
} else {
unsigned nflags=0;
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
if (MULTICAST(p.iph.daddr))
nflags = IFF_BROADCAST;
@@ -1002,7 +1002,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
if ((t = ipgre_tunnel_locate(&p, 0)) == NULL)
goto done;
err = -EPERM;
- if (t == ipgre_fb_tunnel_dev->priv)
+ if (t == netdev_priv(ipgre_fb_tunnel_dev))
goto done;
dev = t->dev;
}
@@ -1019,12 +1019,12 @@ done:
static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev)
{
- return &(((struct ip_tunnel*)dev->priv)->stat);
+ return &(((struct ip_tunnel*)netdev_priv(dev))->stat);
}
static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
- struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen)
return -EINVAL;
dev->mtu = new_mtu;
@@ -1064,7 +1064,7 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
void *daddr, void *saddr, unsigned len)
{
- struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *t = netdev_priv(dev);
struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
u16 *p = (u16*)(iph+1);
@@ -1091,7 +1091,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh
static int ipgre_open(struct net_device *dev)
{
- struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *t = netdev_priv(dev);
if (MULTICAST(t->parms.iph.daddr)) {
struct flowi fl = { .oif = t->parms.link,
@@ -1115,7 +1115,7 @@ static int ipgre_open(struct net_device *dev)
static int ipgre_close(struct net_device *dev)
{
- struct ip_tunnel *t = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *t = netdev_priv(dev);
if (MULTICAST(t->parms.iph.daddr) && t->mlink) {
struct in_device *in_dev = inetdev_by_index(t->mlink);
if (in_dev) {
@@ -1140,7 +1140,7 @@ static void ipgre_tunnel_setup(struct net_device *dev)
dev->type = ARPHRD_IPGRE;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr) + 4;
- dev->mtu = 1500 - sizeof(struct iphdr) - 4;
+ dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 4;
dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4;
@@ -1152,10 +1152,10 @@ static int ipgre_tunnel_init(struct net_device *dev)
struct ip_tunnel *tunnel;
struct iphdr *iph;
int hlen = LL_MAX_HEADER;
- int mtu = 1500;
+ int mtu = ETH_DATA_LEN;
int addend = sizeof(struct iphdr) + 4;
- tunnel = (struct ip_tunnel*)dev->priv;
+ tunnel = netdev_priv(dev);
iph = &tunnel->parms.iph;
tunnel->dev = dev;
@@ -1219,7 +1219,7 @@ static int ipgre_tunnel_init(struct net_device *dev)
static int __init ipgre_fb_tunnel_init(struct net_device *dev)
{
- struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct iphdr *iph = &tunnel->parms.iph;
tunnel->dev = dev;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 473d0f2b2e0d..18d7fad474d7 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -128,6 +128,7 @@
#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -184,7 +185,6 @@ int ip_call_ra_chain(struct sk_buff *skb)
raw_rcv(last, skb2);
}
last = sk;
- nf_reset(skb);
}
}
@@ -203,10 +203,6 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
__skb_pull(skb, ihl);
- /* Free reference early: we don't need it any more, and it may
- hold ip_conntrack module loaded indefinitely. */
- nf_reset(skb);
-
/* Point into the IP datagram, just past the header. */
skb->h.raw = skb->data;
@@ -231,10 +227,12 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
int ret;
- if (!ipprot->no_policy &&
- !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
- kfree_skb(skb);
- goto out;
+ if (!ipprot->no_policy) {
+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ kfree_skb(skb);
+ goto out;
+ }
+ nf_reset(skb);
}
ret = ipprot->handler(skb);
if (ret < 0) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index dbe12da8d8b3..9bebad07bf2e 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <asm/uaccess.h>
@@ -22,6 +23,7 @@
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
+#include <net/route.h>
/*
* Write options to IP header, record destination address to
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index eba64e2bd397..3324fbfe528a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -69,6 +69,7 @@
#include <net/ip.h>
#include <net/protocol.h>
#include <net/route.h>
+#include <net/xfrm.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/arp.h>
@@ -85,6 +86,8 @@
int sysctl_ip_default_ttl = IPDEFTTL;
+static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
+
/* Generate a checksum for an outgoing IP datagram. */
__inline__ void ip_send_check(struct iphdr *iph)
{
@@ -202,13 +205,16 @@ static inline int ip_finish_output2(struct sk_buff *skb)
static inline int ip_finish_output(struct sk_buff *skb)
{
- struct net_device *dev = skb->dst->dev;
-
- skb->dev = dev;
- skb->protocol = htons(ETH_P_IP);
-
- return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
- ip_finish_output2);
+#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
+ /* Policy lookup after SNAT yielded a new policy */
+ if (skb->dst->xfrm != NULL)
+ return xfrm4_output_finish(skb);
+#endif
+ if (skb->len > dst_mtu(skb->dst) &&
+ !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+ return ip_fragment(skb, ip_finish_output2);
+ else
+ return ip_finish_output2(skb);
}
int ip_mc_output(struct sk_buff *skb)
@@ -265,21 +271,21 @@ int ip_mc_output(struct sk_buff *skb)
newskb->dev, ip_dev_loopback_xmit);
}
- if (skb->len > dst_mtu(&rt->u.dst))
- return ip_fragment(skb, ip_finish_output);
- else
- return ip_finish_output(skb);
+ return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
+ ip_finish_output);
}
int ip_output(struct sk_buff *skb)
{
+ struct net_device *dev = skb->dst->dev;
+
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_mtu(skb->dst) &&
- !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
- return ip_fragment(skb, ip_finish_output);
- else
- return ip_finish_output(skb);
+ skb->dev = dev;
+ skb->protocol = htons(ETH_P_IP);
+
+ return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
+ ip_finish_output);
}
int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
@@ -411,7 +417,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
* single device frame, and queue such a frame for sending.
*/
-int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
int raw = 0;
@@ -420,7 +426,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
struct sk_buff *skb2;
unsigned int mtu, hlen, left, len, ll_rs;
int offset;
- int not_last_frag;
+ __be16 not_last_frag;
struct rtable *rt = (struct rtable*)skb->dst;
int err = 0;
@@ -445,6 +451,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
hlen = iph->ihl * 4;
mtu = dst_mtu(&rt->u.dst) - hlen; /* Size of data space */
+ IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE;
/* When frag_list is given, use it. First, check its validity:
* some transformers could create wrong frag_list or break existing
@@ -1181,7 +1188,7 @@ int ip_push_pending_frames(struct sock *sk)
struct ip_options *opt = NULL;
struct rtable *rt = inet->cork.rt;
struct iphdr *iph;
- int df = 0;
+ __be16 df = 0;
__u8 ttl;
int err = 0;
@@ -1392,7 +1399,6 @@ void __init ip_init(void)
#endif
}
-EXPORT_SYMBOL(ip_fragment);
EXPORT_SYMBOL(ip_generic_getfrag);
EXPORT_SYMBOL(ip_queue_xmit);
EXPORT_SYMBOL(ip_send_check);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 4f2d87257309..2bf8d782f678 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -25,12 +25,12 @@
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/icmp.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <net/sock.h>
#include <net/ip.h>
#include <net/icmp.h>
-#include <net/tcp.h>
-#include <linux/tcp.h>
+#include <net/tcp_states.h>
#include <linux/udp.h>
#include <linux/igmp.h>
#include <linux/netfilter.h>
@@ -427,8 +427,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
err = ip_options_get_from_user(&opt, optval, optlen);
if (err)
break;
- if (sk->sk_type == SOCK_STREAM) {
- struct tcp_sock *tp = tcp_sk(sk);
+ if (inet->is_icsk) {
+ struct inet_connection_sock *icsk = inet_csk(sk);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (sk->sk_family == PF_INET ||
(!((1 << sk->sk_state) &
@@ -436,10 +436,10 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
inet->daddr != LOOPBACK4_IPV6)) {
#endif
if (inet->opt)
- tp->ext_header_len -= inet->opt->optlen;
+ icsk->icsk_ext_hdr_len -= inet->opt->optlen;
if (opt)
- tp->ext_header_len += opt->optlen;
- tcp_sync_mss(sk, tp->pmtu_cookie);
+ icsk->icsk_ext_hdr_len += opt->optlen;
+ icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
}
#endif
@@ -621,7 +621,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
err = -ENOBUFS;
break;
}
- msf = (struct ip_msfilter *)kmalloc(optlen, GFP_KERNEL);
+ msf = kmalloc(optlen, GFP_KERNEL);
if (msf == 0) {
err = -ENOBUFS;
break;
@@ -778,7 +778,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
err = -ENOBUFS;
break;
}
- gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
+ gsf = kmalloc(optlen,GFP_KERNEL);
if (gsf == 0) {
err = -ENOBUFS;
break;
@@ -798,7 +798,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
goto mc_msf_out;
}
msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);
- msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);
+ msf = kmalloc(msize,GFP_KERNEL);
if (msf == 0) {
err = -ENOBUFS;
goto mc_msf_out;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index fc718df17b40..d64e2ec8da7b 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -28,6 +28,7 @@
#include <net/xfrm.h>
#include <net/icmp.h>
#include <net/ipcomp.h>
+#include <net/protocol.h>
struct ipcomp_tfms {
struct list_head list;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index e8674baaa8d9..bb3613ec448c 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -42,6 +42,7 @@
#include <linux/in.h>
#include <linux/if.h>
#include <linux/inet.h>
+#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
@@ -58,6 +59,7 @@
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
+#include <net/route.h>
#include <asm/uaccess.h>
#include <net/checksum.h>
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index c05c1df0bb04..e5cbe72c6b80 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -93,6 +93,7 @@
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -108,6 +109,7 @@
#include <linux/mroute.h>
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/if_ether.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -243,7 +245,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
if (dev == NULL)
return NULL;
- nt = dev->priv;
+ nt = netdev_priv(dev);
SET_MODULE_OWNER(dev);
dev->init = ipip_tunnel_init;
nt->parms = *parms;
@@ -268,7 +270,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
tunnels_wc[0] = NULL;
write_unlock_bh(&ipip_lock);
} else
- ipip_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ ipip_tunnel_unlink(netdev_priv(dev));
dev_put(dev);
}
@@ -442,7 +444,7 @@ out:
skb2->dst->ops->update_pmtu(skb2->dst, rel_info);
rel_info = htonl(rel_info);
} else if (type == ICMP_TIME_EXCEEDED) {
- struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv;
+ struct ip_tunnel *t = netdev_priv(skb2->dev);
if (t->parms.iph.ttl) {
rel_type = ICMP_DEST_UNREACH;
rel_code = ICMP_HOST_UNREACH;
@@ -513,7 +515,7 @@ out:
static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct net_device_stats *stats = &tunnel->stat;
struct iphdr *tiph = &tunnel->parms.iph;
u8 tos = tunnel->parms.iph.tos;
@@ -620,6 +622,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE|IPSKB_XFRM_TRANSFORMED);
dst_release(skb->dst);
skb->dst = &rt->u.dst;
@@ -672,7 +675,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t = ipip_tunnel_locate(&p, 0);
}
if (t == NULL)
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
memcpy(&p, &t->parms, sizeof(p));
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
err = -EFAULT;
@@ -709,7 +712,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
err = -EINVAL;
break;
}
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
ipip_tunnel_unlink(t);
t->parms.iph.saddr = p.iph.saddr;
t->parms.iph.daddr = p.iph.daddr;
@@ -763,7 +766,7 @@ done:
static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev)
{
- return &(((struct ip_tunnel*)dev->priv)->stat);
+ return &(((struct ip_tunnel*)netdev_priv(dev))->stat);
}
static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
@@ -786,7 +789,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
dev->type = ARPHRD_TUNNEL;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
- dev->mtu = 1500 - sizeof(struct iphdr);
+ dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr);
dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4;
@@ -798,7 +801,7 @@ static int ipip_tunnel_init(struct net_device *dev)
struct ip_tunnel *tunnel;
struct iphdr *iph;
- tunnel = (struct ip_tunnel*)dev->priv;
+ tunnel = netdev_priv(dev);
iph = &tunnel->parms.iph;
tunnel->dev = dev;
@@ -836,7 +839,7 @@ static int ipip_tunnel_init(struct net_device *dev)
static int __init ipip_fb_tunnel_init(struct net_device *dev)
{
- struct ip_tunnel *tunnel = dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct iphdr *iph = &tunnel->parms.iph;
tunnel->dev = dev;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 302b7eb507c9..5c94c222e3f3 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -33,6 +33,7 @@
#include <asm/uaccess.h>
#include <linux/types.h>
#include <linux/sched.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/mm.h>
@@ -49,9 +50,11 @@
#include <linux/seq_file.h>
#include <linux/mroute.h>
#include <linux/init.h>
+#include <linux/if_ether.h>
#include <net/ip.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
+#include <net/route.h>
#include <net/sock.h>
#include <net/icmp.h>
#include <net/udp.h>
@@ -176,8 +179,8 @@ static int reg_vif_num = -1;
static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
{
read_lock(&mrt_lock);
- ((struct net_device_stats*)dev->priv)->tx_bytes += skb->len;
- ((struct net_device_stats*)dev->priv)->tx_packets++;
+ ((struct net_device_stats*)netdev_priv(dev))->tx_bytes += skb->len;
+ ((struct net_device_stats*)netdev_priv(dev))->tx_packets++;
ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT);
read_unlock(&mrt_lock);
kfree_skb(skb);
@@ -186,13 +189,13 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *reg_vif_get_stats(struct net_device *dev)
{
- return (struct net_device_stats*)dev->priv;
+ return (struct net_device_stats*)netdev_priv(dev);
}
static void reg_vif_setup(struct net_device *dev)
{
dev->type = ARPHRD_PIMREG;
- dev->mtu = 1500 - sizeof(struct iphdr) - 8;
+ dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr) - 8;
dev->flags = IFF_NOARP;
dev->hard_start_xmit = reg_vif_xmit;
dev->get_stats = reg_vif_get_stats;
@@ -1147,8 +1150,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
if (vif->flags & VIFF_REGISTER) {
vif->pkt_out++;
vif->bytes_out+=skb->len;
- ((struct net_device_stats*)vif->dev->priv)->tx_bytes += skb->len;
- ((struct net_device_stats*)vif->dev->priv)->tx_packets++;
+ ((struct net_device_stats*)netdev_priv(vif->dev))->tx_bytes += skb->len;
+ ((struct net_device_stats*)netdev_priv(vif->dev))->tx_packets++;
ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT);
kfree_skb(skb);
return;
@@ -1208,8 +1211,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
if (vif->flags & VIFF_TUNNEL) {
ip_encap(skb, vif->local, vif->remote);
/* FIXME: extra output firewall step used to be here. --RR */
- ((struct ip_tunnel *)vif->dev->priv)->stat.tx_packets++;
- ((struct ip_tunnel *)vif->dev->priv)->stat.tx_bytes+=skb->len;
+ ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_packets++;
+ ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_bytes+=skb->len;
}
IPCB(skb)->flags |= IPSKB_FORWARDED;
@@ -1465,8 +1468,8 @@ int pim_rcv_v1(struct sk_buff * skb)
skb->pkt_type = PACKET_HOST;
dst_release(skb->dst);
skb->dst = NULL;
- ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
- ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
+ ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len;
+ ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++;
nf_reset(skb);
netif_rx(skb);
dev_put(reg_dev);
@@ -1520,8 +1523,8 @@ static int pim_rcv(struct sk_buff * skb)
skb->ip_summed = 0;
skb->pkt_type = PACKET_HOST;
dst_release(skb->dst);
- ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
- ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
+ ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len;
+ ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++;
skb->dst = NULL;
nf_reset(skb);
netif_rx(skb);
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index d7eb680101c2..9b176a942ac5 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -224,34 +224,6 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
}
-#if 0000
-/*
- * Get reference to app by name (called from user context)
- */
-struct ip_vs_app *ip_vs_app_get_by_name(char *appname)
-{
- struct ip_vs_app *app, *a = NULL;
-
- down(&__ip_vs_app_mutex);
-
- list_for_each_entry(ent, &ip_vs_app_list, a_list) {
- if (strcmp(app->name, appname))
- continue;
-
- /* softirq may call ip_vs_app_get too, so the caller
- must disable softirq on the current CPU */
- if (ip_vs_app_get(app))
- a = app;
- break;
- }
-
- up(&__ip_vs_app_mutex);
-
- return a;
-}
-#endif
-
-
/*
* Bind ip_vs_conn to its ip_vs_app (called by cp constructor)
*/
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 2a3a8c59c655..87b83813cf2c 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -24,7 +24,11 @@
*
*/
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/net.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/proc_fs.h> /* for proc_net_* */
#include <linux/seq_file.h>
@@ -219,7 +223,7 @@ struct ip_vs_conn *ip_vs_conn_in_get
if (!cp && atomic_read(&ip_vs_conn_no_cport_cnt))
cp = __ip_vs_conn_in_get(protocol, s_addr, 0, d_addr, d_port);
- IP_VS_DBG(7, "lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
+ IP_VS_DBG(9, "lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
@@ -254,7 +258,7 @@ struct ip_vs_conn *ip_vs_ct_in_get
out:
ct_read_unlock(hash);
- IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
+ IP_VS_DBG(9, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
@@ -295,7 +299,7 @@ struct ip_vs_conn *ip_vs_conn_out_get
ct_read_unlock(hash);
- IP_VS_DBG(7, "lookup/out %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
+ IP_VS_DBG(9, "lookup/out %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n",
ip_vs_proto_name(protocol),
NIPQUAD(s_addr), ntohs(s_port),
NIPQUAD(d_addr), ntohs(d_port),
@@ -391,8 +395,9 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
cp->flags |= atomic_read(&dest->conn_flags);
cp->dest = dest;
- IP_VS_DBG(9, "Bind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
- "d:%u.%u.%u.%u:%d fwd:%c s:%u flg:%X cnt:%d destcnt:%d\n",
+ IP_VS_DBG(7, "Bind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
+ "d:%u.%u.%u.%u:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
+ "dest->refcnt:%d\n",
ip_vs_proto_name(cp->protocol),
NIPQUAD(cp->caddr), ntohs(cp->cport),
NIPQUAD(cp->vaddr), ntohs(cp->vport),
@@ -430,8 +435,9 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
if (!dest)
return;
- IP_VS_DBG(9, "Unbind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
- "d:%u.%u.%u.%u:%d fwd:%c s:%u flg:%X cnt:%d destcnt:%d\n",
+ IP_VS_DBG(7, "Unbind-dest %s c:%u.%u.%u.%u:%d v:%u.%u.%u.%u:%d "
+ "d:%u.%u.%u.%u:%d fwd:%c s:%u conn->flags:%X conn->refcnt:%d "
+ "dest->refcnt:%d\n",
ip_vs_proto_name(cp->protocol),
NIPQUAD(cp->caddr), ntohs(cp->cport),
NIPQUAD(cp->vaddr), ntohs(cp->vport),
@@ -571,7 +577,7 @@ static void ip_vs_conn_expire(unsigned long data)
ip_vs_conn_hash(cp);
expire_later:
- IP_VS_DBG(7, "delayed: refcnt-1=%d conn.n_control=%d\n",
+ IP_VS_DBG(7, "delayed: conn->refcnt-1=%d conn->n_control=%d\n",
atomic_read(&cp->refcnt)-1,
atomic_read(&cp->n_control));
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 1a0843cd58a9..3f47ad8e1cad 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -426,7 +426,7 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
return NULL;
IP_VS_DBG(6, "Schedule fwd:%c c:%u.%u.%u.%u:%u v:%u.%u.%u.%u:%u "
- "d:%u.%u.%u.%u:%u flg:%X cnt:%d\n",
+ "d:%u.%u.%u.%u:%u conn->flags:%X conn->refcnt:%d\n",
ip_vs_fwd_tag(cp),
NIPQUAD(cp->caddr), ntohs(cp->cport),
NIPQUAD(cp->vaddr), ntohs(cp->vport),
@@ -532,11 +532,8 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum,
{
if (!((*pskb)->ipvs_property))
return NF_ACCEPT;
-
/* The packet was sent from IPVS, exit this chain */
- (*okfn)(*pskb);
-
- return NF_STOLEN;
+ return NF_STOP;
}
u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 9bdcf31b760e..7f0288b25fa1 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
+#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
@@ -35,6 +36,7 @@
#include <linux/netfilter_ipv4.h>
#include <net/ip.h>
+#include <net/route.h>
#include <net/sock.h>
#include <asm/uaccess.h>
@@ -447,7 +449,7 @@ ip_vs_service_get(__u32 fwmark, __u16 protocol, __u32 vaddr, __u16 vport)
out:
read_unlock(&__ip_vs_svc_lock);
- IP_VS_DBG(6, "lookup service: fwm %u %s %u.%u.%u.%u:%u %s\n",
+ IP_VS_DBG(9, "lookup service: fwm %u %s %u.%u.%u.%u:%u %s\n",
fwmark, ip_vs_proto_name(protocol),
NIPQUAD(vaddr), ntohs(vport),
svc?"hit":"not hit");
@@ -597,7 +599,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, __u32 daddr, __u16 dport)
*/
list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) {
IP_VS_DBG(3, "Destination %u/%u.%u.%u.%u:%u still in trash, "
- "refcnt=%d\n",
+ "dest->refcnt=%d\n",
dest->vfwmark,
NIPQUAD(dest->addr), ntohs(dest->port),
atomic_read(&dest->refcnt));
@@ -804,7 +806,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
dest = ip_vs_trash_get_dest(svc, daddr, dport);
if (dest != NULL) {
IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, "
- "refcnt=%d, service %u/%u.%u.%u.%u:%u\n",
+ "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n",
NIPQUAD(daddr), ntohs(dport),
atomic_read(&dest->refcnt),
dest->vfwmark,
@@ -949,7 +951,8 @@ static void __ip_vs_del_dest(struct ip_vs_dest *dest)
atomic_dec(&dest->svc->refcnt);
kfree(dest);
} else {
- IP_VS_DBG(3, "Moving dest %u.%u.%u.%u:%u into trash, refcnt=%d\n",
+ IP_VS_DBG(3, "Moving dest %u.%u.%u.%u:%u into trash, "
+ "dest->refcnt=%d\n",
NIPQUAD(dest->addr), ntohs(dest->port),
atomic_read(&dest->refcnt));
list_add(&dest->n_list, &ip_vs_dest_trash);
diff --git a/net/ipv4/ipvs/ip_vs_dh.c b/net/ipv4/ipvs/ip_vs_dh.c
index f3bc320dce93..9fee19c4c617 100644
--- a/net/ipv4/ipvs/ip_vs_dh.c
+++ b/net/ipv4/ipvs/ip_vs_dh.c
@@ -37,8 +37,10 @@
*
*/
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/skbuff.h>
#include <net/ip_vs.h>
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c
index 67b3e2fc1fa1..c453e1e57f4b 100644
--- a/net/ipv4/ipvs/ip_vs_est.c
+++ b/net/ipv4/ipvs/ip_vs_est.c
@@ -13,8 +13,12 @@
* Changes:
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/interrupt.h>
#include <net/ip_vs.h>
diff --git a/net/ipv4/ipvs/ip_vs_lblc.c b/net/ipv4/ipvs/ip_vs_lblc.c
index 561cda326fa8..6e5cb92a5c83 100644
--- a/net/ipv4/ipvs/ip_vs_lblc.c
+++ b/net/ipv4/ipvs/ip_vs_lblc.c
@@ -41,8 +41,10 @@
* me to write this module.
*/
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/skbuff.h>
/* for sysctl */
#include <linux/fs.h>
@@ -228,33 +230,6 @@ ip_vs_lblc_hash(struct ip_vs_lblc_table *tbl, struct ip_vs_lblc_entry *en)
}
-#if 0000
-/*
- * Unhash ip_vs_lblc_entry from ip_vs_lblc_table.
- * returns bool success.
- */
-static int ip_vs_lblc_unhash(struct ip_vs_lblc_table *tbl,
- struct ip_vs_lblc_entry *en)
-{
- if (list_empty(&en->list)) {
- IP_VS_ERR("ip_vs_lblc_unhash(): request for not hashed entry, "
- "called from %p\n", __builtin_return_address(0));
- return 0;
- }
-
- /*
- * Remove it from the table
- */
- write_lock(&tbl->lock);
- list_del(&en->list);
- INIT_LIST_HEAD(&en->list);
- write_unlock(&tbl->lock);
-
- return 1;
-}
-#endif
-
-
/*
* Get ip_vs_lblc_entry associated with supplied parameters.
*/
diff --git a/net/ipv4/ipvs/ip_vs_lblcr.c b/net/ipv4/ipvs/ip_vs_lblcr.c
index ce456dbf09a5..32ba37ba72d8 100644
--- a/net/ipv4/ipvs/ip_vs_lblcr.c
+++ b/net/ipv4/ipvs/ip_vs_lblcr.c
@@ -39,8 +39,10 @@
*
*/
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/skbuff.h>
/* for sysctl */
#include <linux/fs.h>
@@ -414,33 +416,6 @@ ip_vs_lblcr_hash(struct ip_vs_lblcr_table *tbl, struct ip_vs_lblcr_entry *en)
}
-#if 0000
-/*
- * Unhash ip_vs_lblcr_entry from ip_vs_lblcr_table.
- * returns bool success.
- */
-static int ip_vs_lblcr_unhash(struct ip_vs_lblcr_table *tbl,
- struct ip_vs_lblcr_entry *en)
-{
- if (list_empty(&en->list)) {
- IP_VS_ERR("ip_vs_lblcr_unhash(): request for not hashed entry, "
- "called from %p\n", __builtin_return_address(0));
- return 0;
- }
-
- /*
- * Remove it from the table
- */
- write_lock(&tbl->lock);
- list_del(&en->list);
- INIT_LIST_HEAD(&en->list);
- write_unlock(&tbl->lock);
-
- return 1;
-}
-#endif
-
-
/*
* Get ip_vs_lblcr_entry associated with supplied parameters.
*/
diff --git a/net/ipv4/ipvs/ip_vs_proto_ah.c b/net/ipv4/ipvs/ip_vs_proto_ah.c
index 453e94a0bbd7..8b0505b09317 100644
--- a/net/ipv4/ipvs/ip_vs_proto_ah.c
+++ b/net/ipv4/ipvs/ip_vs_proto_ah.c
@@ -12,6 +12,8 @@
*
*/
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
diff --git a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c
index 478e5c7c7e8e..c36ccf057a19 100644
--- a/net/ipv4/ipvs/ip_vs_proto_esp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_esp.c
@@ -12,6 +12,8 @@
*
*/
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 0e878fd6215c..bc28b1160a3a 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -275,28 +275,6 @@ static int tcp_timeouts[IP_VS_TCP_S_LAST+1] = {
[IP_VS_TCP_S_LAST] = 2*HZ,
};
-
-#if 0
-
-/* FIXME: This is going to die */
-
-static int tcp_timeouts_dos[IP_VS_TCP_S_LAST+1] = {
- [IP_VS_TCP_S_NONE] = 2*HZ,
- [IP_VS_TCP_S_ESTABLISHED] = 8*60*HZ,
- [IP_VS_TCP_S_SYN_SENT] = 60*HZ,
- [IP_VS_TCP_S_SYN_RECV] = 10*HZ,
- [IP_VS_TCP_S_FIN_WAIT] = 60*HZ,
- [IP_VS_TCP_S_TIME_WAIT] = 60*HZ,
- [IP_VS_TCP_S_CLOSE] = 10*HZ,
- [IP_VS_TCP_S_CLOSE_WAIT] = 60*HZ,
- [IP_VS_TCP_S_LAST_ACK] = 30*HZ,
- [IP_VS_TCP_S_LISTEN] = 2*60*HZ,
- [IP_VS_TCP_S_SYNACK] = 100*HZ,
- [IP_VS_TCP_S_LAST] = 2*HZ,
-};
-
-#endif
-
static char * tcp_state_name_table[IP_VS_TCP_S_LAST+1] = {
[IP_VS_TCP_S_NONE] = "NONE",
[IP_VS_TCP_S_ESTABLISHED] = "ESTABLISHED",
@@ -448,7 +426,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
struct ip_vs_dest *dest = cp->dest;
IP_VS_DBG(8, "%s %s [%c%c%c%c] %u.%u.%u.%u:%d->"
- "%u.%u.%u.%u:%d state: %s->%s cnt:%d\n",
+ "%u.%u.%u.%u:%d state: %s->%s conn->refcnt:%d\n",
pp->name,
(state_off==TCP_DIR_OUTPUT)?"output ":"input ",
th->syn? 'S' : '.',
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 8ae5f2e0aefa..89d9175d8f28 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -15,8 +15,11 @@
*
*/
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/kernel.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/udp.h>
#include <net/ip_vs.h>
diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
index 0f7c56a225bd..8bc42b76223d 100644
--- a/net/ipv4/ipvs/ip_vs_sched.c
+++ b/net/ipv4/ipvs/ip_vs_sched.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <asm/string.h>
#include <linux/kmod.h>
diff --git a/net/ipv4/ipvs/ip_vs_sh.c b/net/ipv4/ipvs/ip_vs_sh.c
index 6f7c50e44a39..7775e6cc68be 100644
--- a/net/ipv4/ipvs/ip_vs_sh.c
+++ b/net/ipv4/ipvs/ip_vs_sh.c
@@ -34,8 +34,10 @@
*
*/
+#include <linux/ip.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/skbuff.h>
#include <net/ip_vs.h>
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 2e5ced3d8062..1bca714bda3d 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -21,12 +21,14 @@
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/inetdevice.h>
#include <linux/net.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/igmp.h> /* for ip_mc_join_group */
+#include <linux/udp.h>
#include <net/ip.h>
#include <net/sock.h>
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 3b87482049cf..52c12e9edbbc 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -322,7 +322,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct net_device *tdev; /* Device to other host */
struct iphdr *old_iph = skb->nh.iph;
u8 tos = old_iph->tos;
- u16 df = old_iph->frag_off;
+ __be16 df = old_iph->frag_off;
struct iphdr *iph; /* Our new IP header */
int max_headroom; /* The extra header space needed */
int mtu;
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index ae0779d82c5d..52a3d7c57907 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -1,17 +1,11 @@
/* 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>
+#include <net/route.h>
+#include <net/xfrm.h>
+#include <net/ip.h>
/* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
int ip_route_me_harder(struct sk_buff **pskb)
@@ -33,7 +27,6 @@ int ip_route_me_harder(struct sk_buff **pskb)
#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;
@@ -60,6 +53,13 @@ int ip_route_me_harder(struct sk_buff **pskb)
if ((*pskb)->dst->error)
return -1;
+#ifdef CONFIG_XFRM
+ if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+ xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
+ if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
+ return -1;
+#endif
+
/* Change in oif may mean change in hh_len. */
hh_len = (*pskb)->dst->dev->hard_header_len;
if (skb_headroom(*pskb) < hh_len) {
@@ -78,6 +78,9 @@ int ip_route_me_harder(struct sk_buff **pskb)
}
EXPORT_SYMBOL(ip_route_me_harder);
+void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
+EXPORT_SYMBOL(ip_nat_decode_session);
+
/*
* Extra routing may needed on local out, as the QUEUE target never
* returns control to the table.
@@ -135,5 +138,3 @@ static void fini(void)
module_init(init);
module_exit(fini);
-
-#endif /* CONFIG_NETFILTER */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 88a60650e6b8..db783036e4d8 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -182,6 +182,7 @@ config IP_NF_QUEUE
config IP_NF_IPTABLES
tristate "IP tables support (required for filtering/masq/NAT)"
+ depends on NETFILTER_XTABLES
help
iptables is a general, extensible packet identification framework.
The packet filtering and full NAT (masquerading, port forwarding,
@@ -191,16 +192,6 @@ config IP_NF_IPTABLES
To compile it as a module, choose M here. If unsure, say N.
# The matches.
-config IP_NF_MATCH_LIMIT
- tristate "limit match support"
- depends on IP_NF_IPTABLES
- help
- limit matching allows you to control the rate at which a rule can be
- matched: mainly useful in combination with the LOG target ("LOG
- target support", below) and to avoid some Denial of Service attacks.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_IPRANGE
tristate "IP range match support"
depends on IP_NF_IPTABLES
@@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_MAC
- tristate "MAC address match support"
- depends on IP_NF_IPTABLES
- help
- MAC matching allows you to match packets based on the source
- Ethernet address of the packet.
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP_NF_MATCH_PKTTYPE
- tristate "Packet type match support"
- depends on IP_NF_IPTABLES
- help
- Packet type matching allows you to match a packet by
- its "class", eg. BROADCAST, MULTICAST, ...
-
- Typical usage:
- iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP_NF_MATCH_MARK
- tristate "netfilter MARK match support"
- depends on IP_NF_IPTABLES
- help
- Netfilter mark matching allows you to match packets based on the
- `nfmark' value in the packet. This can be set by the MARK target
- (see below).
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_MULTIPORT
tristate "Multiple port match support"
depends on IP_NF_IPTABLES
@@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_LENGTH
- tristate "LENGTH match support"
- depends on IP_NF_IPTABLES
- help
- This option allows you to match the length of a packet against a
- specific value or range of values.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_TTL
tristate "TTL match support"
depends on IP_NF_IPTABLES
@@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_TCPMSS
- tristate "tcpmss match support"
- depends on IP_NF_IPTABLES
- help
- This option adds a `tcpmss' match, which allows you to examine the
- MSS value of TCP SYN packets, which control the maximum packet size
- for that connection.
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP_NF_MATCH_HELPER
- tristate "Helper match support"
- depends on IP_NF_IPTABLES
- depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
- help
- Helper matching allows you to match packets in dynamic connections
- tracked by a conntrack-helper, ie. ip_conntrack_ftp
-
- To compile it as a module, choose M here. If unsure, say Y.
-
-config IP_NF_MATCH_STATE
- tristate "Connection state match support"
- depends on IP_NF_IPTABLES
- depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
- help
- Connection state matching allows you to match packets based on their
- relationship to a tracked connection (ie. previous packets). This
- is a powerful tool for packet classification.
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP_NF_MATCH_CONNTRACK
- tristate "Connection tracking match support"
- depends on IP_NF_IPTABLES
- depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
- help
- This is a general conntrack match module, a superset of the state match.
-
- It allows matching on additional conntrack information, which is
- useful in complex configurations, such as NAT gateways with multiple
- internet links or tunnels.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_OWNER
tristate "Owner match support"
depends on IP_NF_IPTABLES
@@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_MATCH_PHYSDEV
- tristate "Physdev match support"
- depends on IP_NF_IPTABLES && BRIDGE_NETFILTER
- help
- Physdev packet matching matches against the physical bridge ports
- the IP packet arrived on or will leave by.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP_NF_MATCH_ADDRTYPE
tristate 'address type match support'
depends on IP_NF_IPTABLES
@@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE
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_REALM
- tristate 'realm match support'
- depends on IP_NF_IPTABLES
- select NET_CLS_ROUTE
- help
- This option adds a `realm' match, which allows you to use the realm
- key from the routing subsystem inside iptables.
-
- This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
- in tc world.
-
- 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_SCTP
- tristate 'SCTP protocol match support'
- depends on IP_NF_IPTABLES
- help
- With this option enabled, you will be able to use the iptables
- `sctp' match in order to match on SCTP source/destination ports
- and SCTP chunk types.
-
- 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
- help
- This option adds a `comment' dummy-match, which allows you to put
- comments in your iptables ruleset.
-
- 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_CONNMARK
- tristate 'Connection mark match support'
- depends on IP_NF_IPTABLES
- depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
- help
- This option adds a `connmark' match, which allows you to match the
- connection mark value previously set for the session by `CONNMARK'.
-
- If you want to compile it as a module, say M here and read
- <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_IPTABLES
- depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4)
- 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
@@ -474,18 +303,15 @@ 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.
+config IP_NF_MATCH_POLICY
+ tristate "IPsec policy match support"
+ depends on IP_NF_IPTABLES && XFRM
+ help
+ Policy matching allows you to match packets based on the
+ IPsec policy that was used during decapsulation/will
+ be used during encapsulation.
- To compile it as a module, choose M here. If unsure, say N.
+ To compile it as a module, choose M here. If unsure, say N.
# `filter', generic and specific targets
config IP_NF_FILTER
@@ -562,17 +388,6 @@ config IP_NF_TARGET_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_TARGET_NFQUEUE
- tristate "NFQUEUE Target Support"
- depends on IP_NF_IPTABLES
- help
- This Target replaced the old obsolete QUEUE target.
-
- As opposed to QUEUE, it supports 65535 different queues,
- not just one.
-
- To compile it as a module, choose M here. If unsure, say N.
-
# NAT + specific targets
config IP_NF_NAT
tristate "Full NAT"
@@ -725,31 +540,6 @@ config IP_NF_TARGET_DSCP
To compile it as a module, choose M here. If unsure, say N.
-config IP_NF_TARGET_MARK
- tristate "MARK target support"
- depends on IP_NF_MANGLE
- help
- This option adds a `MARK' target, which allows you to create rules
- in the `mangle' table which alter the netfilter mark (nfmark) field
- associated with the packet prior to routing. This can change
- the routing method (see `Use netfilter MARK value as routing
- key') and can also be used by other subsystems to change their
- behavior.
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP_NF_TARGET_CLASSIFY
- tristate "CLASSIFY target support"
- depends on IP_NF_MANGLE
- help
- This option adds a `CLASSIFY' target, which enables the user to set
- the priority of a packet. Some qdiscs can use this value for
- classification, among these are:
-
- atm, cbq, dsmark, pfifo_fast, htb, prio
-
- 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
@@ -764,19 +554,6 @@ config IP_NF_TARGET_TTL
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_MANGLE
- depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
- help
- This option adds a `CONNMARK' target, which allows one to manipulate
- the connection mark value. Similar to the MARK target, but
- affects the connection mark value rather than the packet mark value.
-
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. The module will be called
- ipt_CONNMARK.o. If unsure, say `N'.
-
config IP_NF_TARGET_CLUSTERIP
tristate "CLUSTERIP target support (EXPERIMENTAL)"
depends on IP_NF_MANGLE && EXPERIMENTAL
@@ -800,23 +577,10 @@ config IP_NF_RAW
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_TARGET_NOTRACK
- tristate 'NOTRACK target support'
- depends on IP_NF_RAW
- depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
- help
- The NOTRACK target allows a select rule to specify
- which packets *not* to enter the conntrack/NAT
- subsystem with all the consequences (no ICMP error tracking,
- no protocol helpers for the selected packets).
-
- If you want to compile it as a module, say M here and read
- <file:Documentation/modules.txt>. If unsure, say `N'.
-
-
# ARP tables
config IP_NF_ARPTABLES
tristate "ARP tables support"
+ depends on NETFILTER_XTABLES
help
arptables is a general, extensible packet identification framework.
The ARP packet filtering and mangling (manipulation)subsystems
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index d0a447e520a2..e5c5b3202f02 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -46,15 +46,8 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches
-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
-obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -62,39 +55,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
-obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
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
+obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
-obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
-obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
-obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
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
-obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o
# generic ARP tables
obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 3c2e9639bba6..afe3d8f8177d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
+#include <linux/capability.h>
#include <linux/if_arp.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
@@ -23,6 +24,7 @@
#include <asm/uaccess.h>
#include <asm/semaphore.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_arp/arp_tables.h>
MODULE_LICENSE("GPL");
@@ -54,33 +56,9 @@ do { \
#else
#define ARP_NF_ASSERT(x)
#endif
-#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
-static DECLARE_MUTEX(arpt_mutex);
-
-#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
-#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
#include <linux/netfilter_ipv4/listhelp.h>
-struct arpt_table_info {
- unsigned int size;
- unsigned int number;
- unsigned int initial_entries;
- unsigned int hook_entry[NF_ARP_NUMHOOKS];
- unsigned int underflow[NF_ARP_NUMHOOKS];
- char entries[0] __attribute__((aligned(SMP_CACHE_BYTES)));
-};
-
-static LIST_HEAD(arpt_target);
-static LIST_HEAD(arpt_tables);
-#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
-
-#ifdef CONFIG_SMP
-#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
-#else
-#define TABLE_OFFSET(t,p) 0
-#endif
-
static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
char *hdr_addr, int len)
{
@@ -227,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp)
}
static unsigned int arpt_error(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
@@ -258,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
struct arpt_entry *e, *back;
const char *indev, *outdev;
void *table_base;
+ struct xt_table_info *private = table->private;
/* ARP header, plus 2 device addresses, plus 2 IP addresses. */
if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
@@ -269,11 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
outdev = out ? out->name : nulldevname;
read_lock_bh(&table->lock);
- table_base = (void *)table->private->entries
- + TABLE_OFFSET(table->private,
- smp_processor_id());
- e = get_entry(table_base, table->private->hook_entry[hook]);
- back = get_entry(table_base, table->private->underflow[hook]);
+ table_base = (void *)private->entries[smp_processor_id()];
+ e = get_entry(table_base, private->hook_entry[hook]);
+ back = get_entry(table_base, private->underflow[hook]);
arp = (*pskb)->nh.arph;
do {
@@ -321,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
* abs. verdicts
*/
verdict = t->u.kernel.target->target(pskb,
- hook,
in, out,
+ hook,
t->data,
userdata);
@@ -347,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
return verdict;
}
-/*
- * These are weird, but module loading must not be done with mutex
- * held (since they will register), and we have to have a single
- * function to use try_then_request_module().
- */
-
-/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
-static inline struct arpt_table *find_table_lock(const char *name)
-{
- struct arpt_table *t;
-
- if (down_interruptible(&arpt_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &arpt_tables, list)
- if (strcmp(t->name, name) == 0 && try_module_get(t->me))
- return t;
- up(&arpt_mutex);
- return NULL;
-}
-
-
-/* Find target, grabs ref. Returns ERR_PTR() on error. */
-static inline struct arpt_target *find_target(const char *name, u8 revision)
-{
- struct arpt_target *t;
- int err = 0;
-
- if (down_interruptible(&arpt_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &arpt_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision == revision) {
- if (try_module_get(t->me)) {
- up(&arpt_mutex);
- return t;
- }
- } else
- err = -EPROTOTYPE; /* Found something. */
- }
- }
- up(&arpt_mutex);
- return ERR_PTR(err);
-}
-
-struct arpt_target *arpt_find_target(const char *name, u8 revision)
-{
- struct arpt_target *target;
-
- target = try_then_request_module(find_target(name, revision),
- "arpt_%s", name);
- if (IS_ERR(target) || !target)
- return NULL;
- return target;
-}
-
-static int target_revfn(const char *name, u8 revision, int *bestp)
-{
- struct arpt_target *t;
- int have_rev = 0;
-
- list_for_each_entry(t, &arpt_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision > *bestp)
- *bestp = t->revision;
- if (t->revision == revision)
- have_rev =1;
- }
- }
- return have_rev;
-}
-
-/* Returns true or false (if no such extension at all) */
-static inline int find_revision(const char *name, u8 revision,
- int (*revfn)(const char *, u8, int *),
- int *err)
-{
- int have_rev, best = -1;
-
- if (down_interruptible(&arpt_mutex) != 0) {
- *err = -EINTR;
- return 1;
- }
- have_rev = revfn(name, revision, &best);
- up(&arpt_mutex);
-
- /* Nothing at all? Return 0 to try loading module. */
- if (best == -1) {
- *err = -ENOENT;
- return 0;
- }
-
- *err = best;
- if (!have_rev)
- *err = -EPROTONOSUPPORT;
- return 1;
-}
-
-
/* All zeroes == unconditional rule. */
static inline int unconditional(const struct arpt_arp *arp)
{
@@ -462,7 +339,8 @@ static inline int unconditional(const struct arpt_arp *arp)
/* Figures out from what hook each rule can be called: returns 0 if
* there are loops. Puts hook bitmask in comefrom.
*/
-static int mark_source_chains(struct arpt_table_info *newinfo, unsigned int valid_hooks)
+static int mark_source_chains(struct xt_table_info *newinfo,
+ unsigned int valid_hooks, void *entry0)
{
unsigned int hook;
@@ -472,7 +350,7 @@ static int mark_source_chains(struct arpt_table_info *newinfo, unsigned int vali
for (hook = 0; hook < NF_ARP_NUMHOOKS; hook++) {
unsigned int pos = newinfo->hook_entry[hook];
struct arpt_entry *e
- = (struct arpt_entry *)(newinfo->entries + pos);
+ = (struct arpt_entry *)(entry0 + pos);
if (!(valid_hooks & (1 << hook)))
continue;
@@ -514,13 +392,13 @@ static int mark_source_chains(struct arpt_table_info *newinfo, unsigned int vali
goto next;
e = (struct arpt_entry *)
- (newinfo->entries + pos);
+ (entry0 + pos);
} while (oldpos == pos + e->next_offset);
/* Move along one */
size = e->next_offset;
e = (struct arpt_entry *)
- (newinfo->entries + pos + size);
+ (entry0 + pos + size);
e->counters.pcnt = pos;
pos += size;
} else {
@@ -537,7 +415,7 @@ static int mark_source_chains(struct arpt_table_info *newinfo, unsigned int vali
newpos = pos + e->next_offset;
}
e = (struct arpt_entry *)
- (newinfo->entries + newpos);
+ (entry0 + newpos);
e->counters.pcnt = pos;
pos = newpos;
}
@@ -592,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
}
t = arpt_get_target(e);
- target = try_then_request_module(find_target(t->u.user.name,
- t->u.user.revision),
+ target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
+ t->u.user.revision),
"arpt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -627,7 +505,7 @@ out:
}
static inline int check_entry_size_and_hooks(struct arpt_entry *e,
- struct arpt_table_info *newinfo,
+ struct xt_table_info *newinfo,
unsigned char *base,
unsigned char *limit,
const unsigned int *hook_entries,
@@ -661,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
< 0 (not ARPT_RETURN). --RR */
/* Clear counters and comefrom */
- e->counters = ((struct arpt_counters) { 0, 0 });
+ e->counters = ((struct xt_counters) { 0, 0 });
e->comefrom = 0;
(*i)++;
@@ -688,7 +566,8 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)
*/
static int translate_table(const char *name,
unsigned int valid_hooks,
- struct arpt_table_info *newinfo,
+ struct xt_table_info *newinfo,
+ void *entry0,
unsigned int size,
unsigned int number,
const unsigned int *hook_entries,
@@ -710,11 +589,11 @@ static int translate_table(const char *name,
i = 0;
/* Walk through entries, checking offsets. */
- ret = ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry_size_and_hooks,
newinfo,
- newinfo->entries,
- newinfo->entries + size,
+ entry0,
+ entry0 + size,
hook_entries, underflows, &i);
duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
if (ret != 0)
@@ -743,79 +622,78 @@ static int translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks)) {
+ if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
duprintf("Looping hook\n");
return -ELOOP;
}
/* Finally, each sanity check must pass */
i = 0;
- ret = ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
if (ret != 0) {
- ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ARPT_ENTRY_ITERATE(entry0, newinfo->size,
cleanup_entry, &i);
return ret;
}
/* And one copy for every other CPU */
for_each_cpu(i) {
- if (i == 0)
- continue;
- memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
- newinfo->entries,
- SMP_ALIGN(newinfo->size));
+ if (newinfo->entries[i] && newinfo->entries[i] != entry0)
+ memcpy(newinfo->entries[i], entry0, newinfo->size);
}
return ret;
}
-static struct arpt_table_info *replace_table(struct arpt_table *table,
- unsigned int num_counters,
- struct arpt_table_info *newinfo,
- int *error)
+/* Gets counters. */
+static inline int add_entry_to_counter(const struct arpt_entry *e,
+ struct xt_counters total[],
+ unsigned int *i)
{
- struct arpt_table_info *oldinfo;
-
- /* Do the substitution. */
- write_lock_bh(&table->lock);
- /* Check inside lock: is the old number correct? */
- if (num_counters != table->private->number) {
- duprintf("num_counters != table->private->number (%u/%u)\n",
- num_counters, table->private->number);
- write_unlock_bh(&table->lock);
- *error = -EAGAIN;
- return NULL;
- }
- oldinfo = table->private;
- table->private = newinfo;
- newinfo->initial_entries = oldinfo->initial_entries;
- write_unlock_bh(&table->lock);
+ ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
- return oldinfo;
+ (*i)++;
+ return 0;
}
-/* Gets counters. */
-static inline int add_entry_to_counter(const struct arpt_entry *e,
- struct arpt_counters total[],
+static inline int set_entry_to_counter(const struct arpt_entry *e,
+ struct xt_counters total[],
unsigned int *i)
{
- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
+ SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
(*i)++;
return 0;
}
-static void get_counters(const struct arpt_table_info *t,
- struct arpt_counters counters[])
+static void get_counters(const struct xt_table_info *t,
+ struct xt_counters counters[])
{
unsigned int cpu;
unsigned int i;
+ unsigned int curcpu;
+
+ /* Instead of clearing (by a previous call to memset())
+ * the counters and using adds, we set the counters
+ * with data used by 'current' CPU
+ * We dont care about preemption here.
+ */
+ curcpu = raw_smp_processor_id();
+
+ i = 0;
+ ARPT_ENTRY_ITERATE(t->entries[curcpu],
+ t->size,
+ set_entry_to_counter,
+ counters,
+ &i);
for_each_cpu(cpu) {
+ if (cpu == curcpu)
+ continue;
i = 0;
- ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
+ ARPT_ENTRY_ITERATE(t->entries[cpu],
t->size,
add_entry_to_counter,
counters,
@@ -829,27 +707,29 @@ static int copy_entries_to_user(unsigned int total_size,
{
unsigned int off, num, countersize;
struct arpt_entry *e;
- struct arpt_counters *counters;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
int ret = 0;
+ void *loc_cpu_entry;
/* We need atomic snapshot of counters: rest doesn't change
* (other than comefrom, which userspace doesn't care
* about).
*/
- countersize = sizeof(struct arpt_counters) * table->private->number;
- counters = vmalloc(countersize);
+ countersize = sizeof(struct xt_counters) * private->number;
+ counters = vmalloc_node(countersize, numa_node_id());
if (counters == NULL)
return -ENOMEM;
/* First, sum counters... */
- memset(counters, 0, countersize);
write_lock_bh(&table->lock);
- get_counters(table->private, counters);
+ get_counters(private, counters);
write_unlock_bh(&table->lock);
- /* ... then copy entire thing from CPU 0... */
- if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ /* ... then copy entire thing ... */
+ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
ret = -EFAULT;
goto free_counters;
}
@@ -859,7 +739,7 @@ static int copy_entries_to_user(unsigned int total_size,
for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
struct arpt_entry_target *t;
- e = (struct arpt_entry *)(table->private->entries + off);
+ e = (struct arpt_entry *)(loc_cpu_entry + off);
if (copy_to_user(userptr + off
+ offsetof(struct arpt_entry, counters),
&counters[num],
@@ -890,21 +770,21 @@ static int get_entries(const struct arpt_get_entries *entries,
int ret;
struct arpt_table *t;
- t = find_table_lock(entries->name);
+ t = xt_find_table_lock(NF_ARP, entries->name);
if (t || !IS_ERR(t)) {
+ struct xt_table_info *private = t->private;
duprintf("t->private->number = %u\n",
- t->private->number);
- if (entries->size == t->private->size)
- ret = copy_entries_to_user(t->private->size,
+ private->number);
+ if (entries->size == private->size)
+ ret = copy_entries_to_user(private->size,
t, uptr->entrytable);
else {
duprintf("get_entries: I've got %u not %u!\n",
- t->private->size,
- entries->size);
+ private->size, entries->size);
ret = -EINVAL;
}
module_put(t->me);
- up(&arpt_mutex);
+ xt_table_unlock(t);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -916,8 +796,9 @@ static int do_replace(void __user *user, unsigned int len)
int ret;
struct arpt_replace tmp;
struct arpt_table *t;
- struct arpt_table_info *newinfo, *oldinfo;
- struct arpt_counters *counters;
+ struct xt_table_info *newinfo, *oldinfo;
+ struct xt_counters *counters;
+ void *loc_cpu_entry, *loc_cpu_old_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
@@ -926,38 +807,33 @@ static int do_replace(void __user *user, unsigned int len)
if (len != sizeof(tmp) + tmp.size)
return -ENOPROTOOPT;
- /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
- if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
- return -ENOMEM;
-
- newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(tmp.size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
- if (copy_from_user(newinfo->entries, user + sizeof(tmp),
+ /* choose the copy that is on our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
tmp.size) != 0) {
ret = -EFAULT;
goto free_newinfo;
}
- counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters));
+ counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
if (!counters) {
ret = -ENOMEM;
goto free_newinfo;
}
- memset(counters, 0, tmp.num_counters * sizeof(struct arpt_counters));
ret = translate_table(tmp.name, tmp.valid_hooks,
- newinfo, tmp.size, tmp.num_entries,
+ newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
tmp.hook_entry, tmp.underflow);
if (ret != 0)
goto free_newinfo_counters;
duprintf("arp_tables: Translated table\n");
- t = try_then_request_module(find_table_lock(tmp.name),
+ t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name),
"arptable_%s", tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -972,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len)
goto put_module;
}
- oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+ oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
if (!oldinfo)
goto put_module;
@@ -989,24 +865,26 @@ static int do_replace(void __user *user, unsigned int len)
/* Get the old counters. */
get_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
- ARPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
- vfree(oldinfo);
+ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+ ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
+
+ xt_free_table_info(oldinfo);
if (copy_to_user(tmp.counters, counters,
- sizeof(struct arpt_counters) * tmp.num_counters) != 0)
+ sizeof(struct xt_counters) * tmp.num_counters) != 0)
ret = -EFAULT;
vfree(counters);
- up(&arpt_mutex);
+ xt_table_unlock(t);
return ret;
put_module:
module_put(t->me);
- up(&arpt_mutex);
+ xt_table_unlock(t);
free_newinfo_counters_untrans:
- ARPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry, NULL);
+ ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);
free_newinfo_counters:
vfree(counters);
free_newinfo:
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
@@ -1014,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len)
* and everything is OK.
*/
static inline int add_counter_to_entry(struct arpt_entry *e,
- const struct arpt_counters addme[],
+ const struct xt_counters addme[],
unsigned int *i)
{
@@ -1027,14 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e,
static int do_add_counters(void __user *user, unsigned int len)
{
unsigned int i;
- struct arpt_counters_info tmp, *paddc;
+ struct xt_counters_info tmp, *paddc;
struct arpt_table *t;
+ struct xt_table_info *private;
int ret = 0;
+ void *loc_cpu_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
- if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters))
+ if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
return -EINVAL;
paddc = vmalloc(len);
@@ -1046,27 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len)
goto free;
}
- t = find_table_lock(tmp.name);
+ t = xt_find_table_lock(NF_ARP, tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
}
write_lock_bh(&t->lock);
- if (t->private->number != paddc->num_counters) {
+ private = t->private;
+ if (private->number != paddc->num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
i = 0;
- ARPT_ENTRY_ITERATE(t->private->entries,
- t->private->size,
+ /* Choose the copy that is on our node */
+ loc_cpu_entry = private->entries[smp_processor_id()];
+ ARPT_ENTRY_ITERATE(loc_cpu_entry,
+ private->size,
add_counter_to_entry,
paddc->counters,
&i);
unlock_up_free:
write_unlock_bh(&t->lock);
- up(&arpt_mutex);
+ xt_table_unlock(t);
module_put(t->me);
free:
vfree(paddc);
@@ -1123,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
}
name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
- t = try_then_request_module(find_table_lock(name),
+ t = try_then_request_module(xt_find_table_lock(NF_ARP, name),
"arptable_%s", name);
if (t && !IS_ERR(t)) {
struct arpt_getinfo info;
+ struct xt_table_info *private = t->private;
info.valid_hooks = t->valid_hooks;
- memcpy(info.hook_entry, t->private->hook_entry,
+ memcpy(info.hook_entry, private->hook_entry,
sizeof(info.hook_entry));
- memcpy(info.underflow, t->private->underflow,
+ memcpy(info.underflow, private->underflow,
sizeof(info.underflow));
- info.num_entries = t->private->number;
- info.size = t->private->size;
+ info.num_entries = private->number;
+ info.size = private->size;
strcpy(info.name, name);
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
else
ret = 0;
- up(&arpt_mutex);
+ xt_table_unlock(t);
module_put(t->me);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1166,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
}
case ARPT_SO_GET_REVISION_TARGET: {
- struct arpt_get_revision rev;
+ struct xt_get_revision rev;
if (*len != sizeof(rev)) {
ret = -EINVAL;
@@ -1177,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
break;
}
- try_then_request_module(find_revision(rev.name, rev.revision,
- target_revfn, &ret),
+ try_then_request_module(xt_find_revision(NF_ARP, rev.name,
+ rev.revision, 1, &ret),
"arpt_%s", rev.name);
break;
}
@@ -1191,101 +1075,57 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
return ret;
}
-/* Registration hooks for targets. */
-int arpt_register_target(struct arpt_target *target)
-{
- int ret;
-
- ret = down_interruptible(&arpt_mutex);
- if (ret != 0)
- return ret;
-
- list_add(&target->list, &arpt_target);
- up(&arpt_mutex);
-
- return ret;
-}
-
-void arpt_unregister_target(struct arpt_target *target)
-{
- down(&arpt_mutex);
- LIST_DELETE(&arpt_target, target);
- up(&arpt_mutex);
-}
-
int arpt_register_table(struct arpt_table *table,
const struct arpt_replace *repl)
{
int ret;
- struct arpt_table_info *newinfo;
- static struct arpt_table_info bootstrap
+ struct xt_table_info *newinfo;
+ static struct xt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
+ void *loc_cpu_entry;
- newinfo = vmalloc(sizeof(struct arpt_table_info)
- + SMP_ALIGN(repl->size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(repl->size);
if (!newinfo) {
ret = -ENOMEM;
return ret;
}
- memcpy(newinfo->entries, repl->entries, repl->size);
+
+ /* choose the copy on our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ memcpy(loc_cpu_entry, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, repl->size,
+ newinfo, loc_cpu_entry, repl->size,
repl->num_entries,
repl->hook_entry,
repl->underflow);
+
duprintf("arpt_register_table: translate table gives %d\n", ret);
if (ret != 0) {
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
- ret = down_interruptible(&arpt_mutex);
- if (ret != 0) {
- vfree(newinfo);
+ if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+ xt_free_table_info(newinfo);
return ret;
}
- /* Don't autoload: we'd eat our tail... */
- if (list_named_find(&arpt_tables, table->name)) {
- ret = -EEXIST;
- goto free_unlock;
- }
-
- /* Simplifies replace_table code. */
- table->private = &bootstrap;
- if (!replace_table(table, 0, newinfo, &ret))
- goto free_unlock;
-
- duprintf("table->private->number = %u\n",
- table->private->number);
-
- /* save number of initial entries */
- table->private->initial_entries = table->private->number;
-
- rwlock_init(&table->lock);
- list_prepend(&arpt_tables, table);
-
- unlock:
- up(&arpt_mutex);
- return ret;
-
- free_unlock:
- vfree(newinfo);
- goto unlock;
+ return 0;
}
void arpt_unregister_table(struct arpt_table *table)
{
- down(&arpt_mutex);
- LIST_DELETE(&arpt_tables, table);
- up(&arpt_mutex);
+ struct xt_table_info *private;
+ void *loc_cpu_entry;
+
+ private = xt_unregister_table(table);
/* Decrease module usage counts and free resources */
- ARPT_ENTRY_ITERATE(table->private->entries, table->private->size,
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size,
cleanup_entry, NULL);
- vfree(table->private);
+ xt_free_table_info(private);
}
/* The built-in targets: standard (NULL) and error. */
@@ -1308,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = {
.get = do_arpt_get_ctl,
};
-#ifdef CONFIG_PROC_FS
-static inline int print_name(const struct arpt_table *t,
- off_t start_offset, char *buffer, int length,
- off_t *pos, unsigned int *count)
-{
- if ((*count)++ >= start_offset) {
- unsigned int namelen;
-
- namelen = sprintf(buffer + *pos, "%s\n", t->name);
- if (*pos + namelen > length) {
- /* Stop iterating */
- return 1;
- }
- *pos += namelen;
- }
- return 0;
-}
-
-static int arpt_get_tables(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&arpt_mutex) != 0)
- return 0;
-
- LIST_FIND(&arpt_tables, print_name, struct arpt_table *,
- offset, buffer, length, &pos, &count);
-
- up(&arpt_mutex);
-
- /* `start' hack - see fs/proc/generic.c line ~105 */
- *start=(char *)((unsigned long)count-offset);
- return pos;
-}
-#endif /*CONFIG_PROC_FS*/
-
static int __init init(void)
{
int ret;
+ xt_proto_init(NF_ARP);
+
/* Noone else will be downing sem now, so we won't sleep */
- down(&arpt_mutex);
- list_append(&arpt_target, &arpt_standard_target);
- list_append(&arpt_target, &arpt_error_target);
- up(&arpt_mutex);
+ xt_register_target(NF_ARP, &arpt_standard_target);
+ xt_register_target(NF_ARP, &arpt_error_target);
/* Register setsockopt */
ret = nf_register_sockopt(&arpt_sockopts);
@@ -1362,19 +1165,6 @@ static int __init init(void)
return ret;
}
-#ifdef CONFIG_PROC_FS
- {
- struct proc_dir_entry *proc;
-
- proc = proc_net_create("arp_tables_names", 0, arpt_get_tables);
- if (!proc) {
- nf_unregister_sockopt(&arpt_sockopts);
- return -ENOMEM;
- }
- proc->owner = THIS_MODULE;
- }
-#endif
-
printk("arp_tables: (C) 2002 David S. Miller\n");
return 0;
}
@@ -1382,16 +1172,12 @@ static int __init init(void)
static void __exit fini(void)
{
nf_unregister_sockopt(&arpt_sockopts);
-#ifdef CONFIG_PROC_FS
- proc_net_remove("arp_tables_names");
-#endif
+ xt_proto_fini(NF_ARP);
}
EXPORT_SYMBOL(arpt_register_table);
EXPORT_SYMBOL(arpt_unregister_table);
EXPORT_SYMBOL(arpt_do_table);
-EXPORT_SYMBOL(arpt_register_target);
-EXPORT_SYMBOL(arpt_unregister_target);
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 3e592ec86482..c97650a16a5b 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
MODULE_DESCRIPTION("arptables arp payload mangle target");
static unsigned int
-target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in,
- const struct net_device *out, const void *targinfo, void *userinfo)
+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 arpt_mangle *mangle = targinfo;
struct arphdr *arp;
@@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in,
}
static int
-checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo,
+checkentry(const char *tablename, const void *e, void *targinfo,
unsigned int targinfosize, unsigned int hook_mask)
{
const struct arpt_mangle *mangle = targinfo;
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 0d759f5a4ef0..f6ab45f48681 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -145,6 +145,7 @@ static struct arpt_table packet_filter = {
.lock = RW_LOCK_UNLOCKED,
.private = NULL,
.me = THIS_MODULE,
+ .af = NF_ARP,
};
/* The work comes in here from netfilter.c */
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index e52847fa10f5..84e4f79b7ffa 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -18,11 +18,13 @@
*
*/
+#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/moduleparam.h>
+#include <linux/udp.h>
#include <net/checksum.h>
#include <net/udp.h>
@@ -34,7 +36,7 @@ static unsigned int master_timeout = 300;
MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
MODULE_DESCRIPTION("Amanda connection tracking module");
MODULE_LICENSE("GPL");
-module_param(master_timeout, int, 0600);
+module_param(master_timeout, uint, 0600);
MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
static const char *conns[] = { "DATA ", "MESG ", "INDEX " };
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 68b173bcda60..e627e5856172 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -34,7 +34,7 @@ static int ports_c;
module_param_array(ports, ushort, &ports_c, 0400);
static int loose;
-module_param(loose, int, 0600);
+module_param(loose, bool, 0600);
unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index 4108a5e12b3c..d716bba798f2 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -762,7 +762,7 @@ static struct ip_conntrack_helper pptp = {
.help = conntrack_pptp_help
};
-extern void __exit ip_ct_proto_gre_fini(void);
+extern void ip_ct_proto_gre_fini(void);
extern int __init ip_ct_proto_gre_init(void);
/* ip_conntrack_pptp initialization */
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index d7c40421d0d1..c51a2cf71b4b 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -36,7 +36,7 @@
#define MAX_PORTS 8
static unsigned short ports[MAX_PORTS];
static int ports_c;
-static int max_dcc_channels = 8;
+static unsigned int max_dcc_channels = 8;
static unsigned int dcc_timeout = 300;
/* This is slow, but it's simple. --RR */
static char *irc_buffer;
@@ -54,9 +54,9 @@ MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
MODULE_LICENSE("GPL");
module_param_array(ports, ushort, &ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of IRC servers");
-module_param(max_dcc_channels, int, 0400);
+module_param(max_dcc_channels, uint, 0400);
MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
-module_param(dcc_timeout, int, 0400);
+module_param(dcc_timeout, uint, 0400);
MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
static const char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
@@ -254,10 +254,6 @@ static int __init init(void)
printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n");
return -EBUSY;
}
- if (dcc_timeout < 0) {
- printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
- return -EBUSY;
- }
irc_buffer = kmalloc(65536, GFP_KERNEL);
if (!irc_buffer)
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 186646eb249f..4e68e16a2612 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
MODULE_LICENSE("GPL");
static unsigned int timeout = 3;
-module_param(timeout, int, 0600);
+module_param(timeout, uint, 0400);
MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
static int help(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 91fe8f2e38ff..c9ebbe0d2d9c 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -79,6 +79,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
const struct ip_conntrack_tuple *tuple)
{
struct nfattr *nest_parms;
+ int ret;
nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
@@ -86,10 +87,10 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
NFA_NEST_END(skb, nest_parms);
nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
- ctnetlink_dump_tuples_proto(skb, tuple);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple);
NFA_NEST_END(skb, nest_parms);
- return 0;
+ return ret;
nfattr_failure:
return -1;
@@ -160,7 +161,7 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
return 0;
nest_helper = NFA_NEST(skb, CTA_HELP);
- NFA_PUT(skb, CTA_HELP_NAME, CTA_HELP_MAXNAMESIZE, &ct->helper->name);
+ NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name);
if (ct->helper->to_nfattr)
ct->helper->to_nfattr(skb, ct);
@@ -229,7 +230,7 @@ nfattr_failure:
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));
+ u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
return 0;
@@ -311,29 +312,22 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
if (events & IPCT_DESTROY) {
type = IPCTNL_MSG_CT_DELETE;
group = NFNLGRP_CONNTRACK_DESTROY;
- goto alloc_skb;
- }
- if (events & (IPCT_NEW | IPCT_RELATED)) {
+ } else 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 |
+ } else if (events & (IPCT_STATUS |
IPCT_PROTOINFO |
IPCT_HELPER |
IPCT_HELPINFO |
IPCT_NATINFO)) {
type = IPCTNL_MSG_CT_NEW;
group = NFNLGRP_CONNTRACK_UPDATE;
- goto alloc_skb;
- }
+ } else
+ return NOTIFY_DONE;
- return NOTIFY_DONE;
-
-alloc_skb:
/* FIXME: Check if there are any listeners before, don't hurt performance */
skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
@@ -1037,6 +1031,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
return err;
}
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ if (cda[CTA_MARK-1])
+ ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+#endif
+
ct->helper = ip_conntrack_helper_find_get(rtuple);
add_timer(&ct->timeout);
@@ -1045,11 +1044,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
if (ct->helper)
ip_conntrack_helper_put(ct->helper);
-#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
- if (cda[CTA_MARK-1])
- ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
-#endif
-
DEBUGP("conntrack with id %u inserted\n", ct->id);
return 0;
@@ -1209,7 +1203,6 @@ static int ctnetlink_expect_event(struct notifier_block *this,
unsigned int type;
unsigned char *b;
int flags = 0;
- u16 proto;
if (events & IPEXP_NEW) {
type = IPCTNL_MSG_EXP_NEW;
@@ -1236,7 +1229,6 @@ static int ctnetlink_expect_event(struct notifier_block *this,
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;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
index 88c3712bd251..f891308b5e4c 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
@@ -12,7 +12,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-unsigned long ip_ct_generic_timeout = 600*HZ;
+unsigned int ip_ct_generic_timeout = 600*HZ;
static int generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 744abb9d377a..56794797d55b 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -31,6 +31,8 @@
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
static DEFINE_RWLOCK(ip_ct_gre_lock);
#define ASSERT_READ_LOCK(x)
@@ -308,7 +310,10 @@ int __init ip_ct_proto_gre_init(void)
return ip_conntrack_protocol_register(&gre);
}
-void __exit ip_ct_proto_gre_fini(void)
+/* This cannot be __exit, as it is invoked from ip_conntrack_helper_pptp.c's
+ * init() code on errors.
+ */
+void ip_ct_proto_gre_fini(void)
{
struct list_head *pos, *n;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 5f9925db608e..3021af0910f1 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -16,13 +16,12 @@
#include <linux/skbuff.h>
#include <net/ip.h>
#include <net/checksum.h>
-#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-unsigned long ip_ct_icmp_timeout = 30*HZ;
+unsigned int ip_ct_icmp_timeout = 30*HZ;
#if 0
#define DEBUGP printk
@@ -47,20 +46,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
return 1;
}
+/* Add 1; spaces filled with 0. */
+static const u_int8_t invmap[] = {
+ [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
+ [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
+ [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
+ [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
+ [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
+ [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
+ [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
+ [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+};
+
static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple,
const struct ip_conntrack_tuple *orig)
{
- /* Add 1; spaces filled with 0. */
- static const u_int8_t invmap[]
- = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
- [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
- [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
- [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
- [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
- [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
- [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
- [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
-
if (orig->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[orig->dst.u.icmp.type])
return 0;
@@ -110,17 +110,17 @@ static int icmp_packet(struct ip_conntrack *ct,
return NF_ACCEPT;
}
-static const 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 const 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. */
@@ -279,10 +279,6 @@ static int icmp_tuple_to_nfattr(struct sk_buff *skb,
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:
@@ -295,7 +291,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
if (!tb[CTA_PROTO_ICMP_TYPE-1]
|| !tb[CTA_PROTO_ICMP_CODE-1]
|| !tb[CTA_PROTO_ICMP_ID-1])
- return -1;
+ return -EINVAL;
tuple->dst.u.icmp.type =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
@@ -304,6 +300,10 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
tuple->src.u.icmp.id =
*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+ if (tuple->dst.u.icmp.type >= sizeof(invmap)
+ || !invmap[tuple->dst.u.icmp.type])
+ return -EINVAL;
+
return 0;
}
#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 977fb59d4563..be602e8aeab0 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/timer.h>
+#include <linux/interrupt.h>
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/in.h>
@@ -57,15 +58,15 @@ static const char *sctp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-static unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
-static unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
-static unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
-static unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
-static unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
-static unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
-static unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
+static unsigned int ip_ct_sctp_timeout_closed = 10 SECS;
+static unsigned int ip_ct_sctp_timeout_cookie_wait = 3 SECS;
+static unsigned int ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
+static unsigned int ip_ct_sctp_timeout_established = 5 DAYS;
+static unsigned int ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
+static unsigned int ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
+static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
-static const unsigned long * sctp_timeouts[]
+static const unsigned int * sctp_timeouts[]
= { NULL, /* SCTP_CONNTRACK_NONE */
&ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
&ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e7fa29e576dc..e0dc37063545 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -32,7 +32,6 @@
#include <net/tcp.h>
-#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -85,21 +84,21 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-unsigned long ip_ct_tcp_timeout_syn_sent = 2 MINS;
-unsigned long ip_ct_tcp_timeout_syn_recv = 60 SECS;
-unsigned long ip_ct_tcp_timeout_established = 5 DAYS;
-unsigned long ip_ct_tcp_timeout_fin_wait = 2 MINS;
-unsigned long ip_ct_tcp_timeout_close_wait = 60 SECS;
-unsigned long ip_ct_tcp_timeout_last_ack = 30 SECS;
-unsigned long ip_ct_tcp_timeout_time_wait = 2 MINS;
-unsigned long ip_ct_tcp_timeout_close = 10 SECS;
+unsigned int ip_ct_tcp_timeout_syn_sent = 2 MINS;
+unsigned int ip_ct_tcp_timeout_syn_recv = 60 SECS;
+unsigned int ip_ct_tcp_timeout_established = 5 DAYS;
+unsigned int ip_ct_tcp_timeout_fin_wait = 2 MINS;
+unsigned int ip_ct_tcp_timeout_close_wait = 60 SECS;
+unsigned int ip_ct_tcp_timeout_last_ack = 30 SECS;
+unsigned int ip_ct_tcp_timeout_time_wait = 2 MINS;
+unsigned int ip_ct_tcp_timeout_close = 10 SECS;
/* RFC1122 says the R2 limit should be at least 100 seconds.
Linux uses 15 packets as limit, which corresponds
to ~13-30min depending on RTO. */
-unsigned long ip_ct_tcp_timeout_max_retrans = 5 MINS;
+unsigned int ip_ct_tcp_timeout_max_retrans = 5 MINS;
-static const unsigned long * tcp_timeouts[]
+static const unsigned int * tcp_timeouts[]
= { NULL, /* TCP_CONNTRACK_NONE */
&ip_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
&ip_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
@@ -995,7 +994,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
|| (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
&& conntrack->proto.tcp.last_index == TCP_ACK_SET))
&& ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
- /* RST sent to invalid SYN or ACK we had let trough
+ /* RST sent to invalid SYN or ACK we had let through
* at a) and c) above:
*
* a) SYN was in window then
@@ -1006,7 +1005,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
* segments we ignored. */
goto in_window;
}
- /* Just fall trough */
+ /* Just fall through */
default:
/* Keep compilers happy. */
break;
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index f2dcac7c7660..55b7d3210adf 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -11,15 +11,15 @@
#include <linux/timer.h>
#include <linux/netfilter.h>
#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/seq_file.h>
#include <net/checksum.h>
-#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-unsigned long ip_ct_udp_timeout = 30*HZ;
-unsigned long ip_ct_udp_timeout_stream = 180*HZ;
+unsigned int ip_ct_udp_timeout = 30*HZ;
+unsigned int ip_ct_udp_timeout_stream = 180*HZ;
static int udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index dd476b191f4b..833fcb4be5e7 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -27,6 +27,7 @@
#endif
#include <net/checksum.h>
#include <net/ip.h>
+#include <net/route.h>
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
@@ -450,30 +451,6 @@ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
return NF_ACCEPT;
}
-static unsigned int ip_refrag(unsigned int hooknum,
- struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct rtable *rt = (struct rtable *)(*pskb)->dst;
-
- /* We've seen it coming out the other side: confirm */
- if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
- return NF_DROP;
-
- /* Local packets are never produced too large for their
- interface. We degfragment them at LOCAL_OUT, however,
- so we have to refragment them here. */
- if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
- !skb_shinfo(*pskb)->tso_size) {
- /* No hook can be after us, so this should be OK. */
- ip_fragment(*pskb, okfn);
- return NF_STOLEN;
- }
- return NF_ACCEPT;
-}
-
static unsigned int ip_conntrack_local(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -543,7 +520,7 @@ static struct nf_hook_ops ip_conntrack_helper_in_ops = {
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops = {
- .hook = ip_refrag,
+ .hook = ip_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
@@ -567,28 +544,28 @@ extern int ip_conntrack_max;
extern unsigned int ip_conntrack_htable_size;
/* From ip_conntrack_proto_tcp.c */
-extern unsigned long ip_ct_tcp_timeout_syn_sent;
-extern unsigned long ip_ct_tcp_timeout_syn_recv;
-extern unsigned long ip_ct_tcp_timeout_established;
-extern unsigned long ip_ct_tcp_timeout_fin_wait;
-extern unsigned long ip_ct_tcp_timeout_close_wait;
-extern unsigned long ip_ct_tcp_timeout_last_ack;
-extern unsigned long ip_ct_tcp_timeout_time_wait;
-extern unsigned long ip_ct_tcp_timeout_close;
-extern unsigned long ip_ct_tcp_timeout_max_retrans;
+extern unsigned int ip_ct_tcp_timeout_syn_sent;
+extern unsigned int ip_ct_tcp_timeout_syn_recv;
+extern unsigned int ip_ct_tcp_timeout_established;
+extern unsigned int ip_ct_tcp_timeout_fin_wait;
+extern unsigned int ip_ct_tcp_timeout_close_wait;
+extern unsigned int ip_ct_tcp_timeout_last_ack;
+extern unsigned int ip_ct_tcp_timeout_time_wait;
+extern unsigned int ip_ct_tcp_timeout_close;
+extern unsigned int ip_ct_tcp_timeout_max_retrans;
extern int ip_ct_tcp_loose;
extern int ip_ct_tcp_be_liberal;
extern int ip_ct_tcp_max_retrans;
/* From ip_conntrack_proto_udp.c */
-extern unsigned long ip_ct_udp_timeout;
-extern unsigned long ip_ct_udp_timeout_stream;
+extern unsigned int ip_ct_udp_timeout;
+extern unsigned int ip_ct_udp_timeout_stream;
/* From ip_conntrack_proto_icmp.c */
-extern unsigned long ip_ct_icmp_timeout;
+extern unsigned int ip_ct_icmp_timeout;
/* From ip_conntrack_proto_icmp.c */
-extern unsigned long ip_ct_generic_timeout;
+extern unsigned int ip_ct_generic_timeout;
/* Log invalid packets of a given protocol */
static int log_invalid_proto_min = 0;
@@ -967,7 +944,7 @@ module_exit(fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
-void need_ip_conntrack(void)
+void need_conntrack(void)
{
}
@@ -985,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple);
EXPORT_SYMBOL(invert_tuplepr);
EXPORT_SYMBOL(ip_conntrack_alter_reply);
EXPORT_SYMBOL(ip_conntrack_destroyed);
-EXPORT_SYMBOL(need_ip_conntrack);
+EXPORT_SYMBOL(need_conntrack);
EXPORT_SYMBOL(ip_conntrack_helper_register);
EXPORT_SYMBOL(ip_conntrack_helper_unregister);
EXPORT_SYMBOL(ip_ct_iterate_cleanup);
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index d83757a70d9f..b8daab3c64af 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -171,7 +171,7 @@ static int __init init(void)
/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
static int warn_set(const char *val, struct kernel_param *kp)
{
- printk(KERN_INFO __stringify(KBUILD_MODNAME)
+ printk(KERN_INFO KBUILD_MODNAME
": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index e546203f5662..ac004895781a 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -148,14 +148,14 @@ pptp_outbound_pkt(struct sk_buff **pskb,
{
struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
-
- u_int16_t msg, *cid = NULL, new_callid;
+ u_int16_t msg, new_callid;
+ unsigned int cid_off;
new_callid = htons(ct_pptp_info->pns_call_id);
switch (msg = ntohs(ctlh->messageType)) {
case PPTP_OUT_CALL_REQUEST:
- cid = &pptpReq->ocreq.callID;
+ cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
/* FIXME: ideally we would want to reserve a call ID
* here. current netfilter NAT core is not able to do
* this :( For now we use TCP source port. This breaks
@@ -172,10 +172,10 @@ pptp_outbound_pkt(struct sk_buff **pskb,
ct_pptp_info->pns_call_id = ntohs(new_callid);
break;
case PPTP_IN_CALL_REPLY:
- cid = &pptpReq->icreq.callID;
+ cid_off = offsetof(union pptp_ctrl_union, icreq.callID);
break;
case PPTP_CALL_CLEAR_REQUEST:
- cid = &pptpReq->clrreq.callID;
+ cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
break;
default:
DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
@@ -197,18 +197,15 @@ pptp_outbound_pkt(struct sk_buff **pskb,
/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
* down to here */
-
- IP_NF_ASSERT(cid);
-
DEBUGP("altering call id from 0x%04x to 0x%04x\n",
- ntohs(*cid), ntohs(new_callid));
+ ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid));
/* mangle packet */
if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
- (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
- sizeof(new_callid),
- (char *)&new_callid,
- sizeof(new_callid)) == 0)
+ cid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_callid), (char *)&new_callid,
+ sizeof(new_callid)) == 0)
return NF_DROP;
return NF_ACCEPT;
@@ -299,31 +296,30 @@ pptp_inbound_pkt(struct sk_buff **pskb,
union pptp_ctrl_union *pptpReq)
{
struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
- u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
-
- int ret = NF_ACCEPT, rv;
+ u_int16_t msg, new_cid = 0, new_pcid;
+ unsigned int pcid_off, cid_off = 0;
new_pcid = htons(nat_pptp_info->pns_call_id);
switch (msg = ntohs(ctlh->messageType)) {
case PPTP_OUT_CALL_REPLY:
- pcid = &pptpReq->ocack.peersCallID;
- cid = &pptpReq->ocack.callID;
+ pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
+ cid_off = offsetof(union pptp_ctrl_union, ocack.callID);
break;
case PPTP_IN_CALL_CONNECT:
- pcid = &pptpReq->iccon.peersCallID;
+ pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
break;
case PPTP_IN_CALL_REQUEST:
/* only need to nat in case PAC is behind NAT box */
- break;
+ return NF_ACCEPT;
case PPTP_WAN_ERROR_NOTIFY:
- pcid = &pptpReq->wanerr.peersCallID;
+ pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
break;
case PPTP_CALL_DISCONNECT_NOTIFY:
- pcid = &pptpReq->disc.callID;
+ pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
break;
case PPTP_SET_LINK_INFO:
- pcid = &pptpReq->setlink.peersCallID;
+ pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
break;
default:
@@ -345,35 +341,26 @@ pptp_inbound_pkt(struct sk_buff **pskb,
* WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
/* mangle packet */
- IP_NF_ASSERT(pcid);
DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
- ntohs(*pcid), ntohs(new_pcid));
-
- rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
- (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
- sizeof(new_pcid), (char *)&new_pcid,
- sizeof(new_pcid));
- if (rv != NF_ACCEPT)
- return rv;
+ ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid));
+
+ if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ pcid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_pcid), (char *)&new_pcid,
+ sizeof(new_pcid)) == 0)
+ return NF_DROP;
if (new_cid) {
- IP_NF_ASSERT(cid);
DEBUGP("altering call id from 0x%04x to 0x%04x\n",
- ntohs(*cid), ntohs(new_cid));
- rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
- (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
- sizeof(new_cid),
- (char *)&new_cid,
- sizeof(new_cid));
- if (rv != NF_ACCEPT)
- return rv;
+ ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid));
+ if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
+ cid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_cid), (char *)&new_cid,
+ sizeof(new_cid)) == 0)
+ return NF_DROP;
}
-
- /* check for earlier return value of 'switch' above */
- if (ret != NF_ACCEPT)
- return ret;
-
- /* great, at least we don't need to resize packets */
return NF_ACCEPT;
}
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index de31942babe3..461c833eaca1 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -113,7 +113,7 @@ static int __init init(void)
/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
static int warn_set(const char *val, struct kernel_param *kp)
{
- printk(KERN_INFO __stringify(KBUILD_MODNAME)
+ printk(KERN_INFO KBUILD_MODNAME
": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
return 0;
}
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
index f7cad7cf1aec..6c4899d8046a 100644
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -151,42 +151,6 @@ gre_manip_pkt(struct sk_buff **pskb,
return 1;
}
-/* print out a nat tuple */
-static unsigned int
-gre_print(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask)
-{
- unsigned int len = 0;
-
- if (mask->src.u.gre.key)
- len += sprintf(buffer + len, "srckey=0x%x ",
- ntohl(match->src.u.gre.key));
-
- if (mask->dst.u.gre.key)
- len += sprintf(buffer + len, "dstkey=0x%x ",
- ntohl(match->src.u.gre.key));
-
- return len;
-}
-
-/* print a range of keys */
-static unsigned int
-gre_print_range(char *buffer, const struct ip_nat_range *range)
-{
- if (range->min.gre.key != 0
- || range->max.gre.key != 0xFFFF) {
- if (range->min.gre.key == range->max.gre.key)
- return sprintf(buffer, "key 0x%x ",
- ntohl(range->min.gre.key));
- else
- return sprintf(buffer, "keys 0x%u-0x%u ",
- ntohl(range->min.gre.key),
- ntohl(range->max.gre.key));
- } else
- return 0;
-}
-
/* nat helper struct */
static struct ip_nat_protocol gre = {
.name = "GRE",
@@ -194,8 +158,6 @@ static struct ip_nat_protocol gre = {
.manip_pkt = gre_manip_pkt,
.in_range = gre_in_range,
.unique_tuple = gre_unique_tuple,
- .print = gre_print,
- .print_range = gre_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,
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index 938719043999..31a3f4ccb99c 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -74,38 +74,6 @@ icmp_manip_pkt(struct sk_buff **pskb,
return 1;
}
-static unsigned int
-icmp_print(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask)
-{
- unsigned int len = 0;
-
- if (mask->src.u.icmp.id)
- len += sprintf(buffer + len, "id=%u ",
- ntohs(match->src.u.icmp.id));
-
- if (mask->dst.u.icmp.type)
- len += sprintf(buffer + len, "type=%u ",
- ntohs(match->dst.u.icmp.type));
-
- if (mask->dst.u.icmp.code)
- len += sprintf(buffer + len, "code=%u ",
- ntohs(match->dst.u.icmp.code));
-
- return len;
-}
-
-static unsigned int
-icmp_print_range(char *buffer, const struct ip_nat_range *range)
-{
- if (range->min.icmp.id != 0 || range->max.icmp.id != 0xFFFF)
- return sprintf(buffer, "id %u-%u ",
- ntohs(range->min.icmp.id),
- ntohs(range->max.icmp.id));
- else return 0;
-}
-
struct ip_nat_protocol ip_nat_protocol_icmp = {
.name = "ICMP",
.protonum = IPPROTO_ICMP,
@@ -113,8 +81,6 @@ struct ip_nat_protocol ip_nat_protocol_icmp = {
.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,
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index 1d381bf68574..a3d14079eba6 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -136,40 +136,6 @@ tcp_manip_pkt(struct sk_buff **pskb,
return 1;
}
-static unsigned int
-tcp_print(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask)
-{
- unsigned int len = 0;
-
- if (mask->src.u.tcp.port)
- len += sprintf(buffer + len, "srcpt=%u ",
- ntohs(match->src.u.tcp.port));
-
-
- if (mask->dst.u.tcp.port)
- len += sprintf(buffer + len, "dstpt=%u ",
- ntohs(match->dst.u.tcp.port));
-
- return len;
-}
-
-static unsigned int
-tcp_print_range(char *buffer, const struct ip_nat_range *range)
-{
- if (range->min.tcp.port != 0 || range->max.tcp.port != 0xFFFF) {
- if (range->min.tcp.port == range->max.tcp.port)
- return sprintf(buffer, "port %u ",
- ntohs(range->min.tcp.port));
- else
- return sprintf(buffer, "ports %u-%u ",
- ntohs(range->min.tcp.port),
- ntohs(range->max.tcp.port));
- }
- else return 0;
-}
-
struct ip_nat_protocol ip_nat_protocol_tcp = {
.name = "TCP",
.protonum = IPPROTO_TCP,
@@ -177,8 +143,6 @@ struct ip_nat_protocol ip_nat_protocol_tcp = {
.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,
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index c4906e1aa24a..ec6053fdc867 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -122,40 +122,6 @@ udp_manip_pkt(struct sk_buff **pskb,
return 1;
}
-static unsigned int
-udp_print(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask)
-{
- unsigned int len = 0;
-
- if (mask->src.u.udp.port)
- len += sprintf(buffer + len, "srcpt=%u ",
- ntohs(match->src.u.udp.port));
-
-
- if (mask->dst.u.udp.port)
- len += sprintf(buffer + len, "dstpt=%u ",
- ntohs(match->dst.u.udp.port));
-
- return len;
-}
-
-static unsigned int
-udp_print_range(char *buffer, const struct ip_nat_range *range)
-{
- if (range->min.udp.port != 0 || range->max.udp.port != 0xFFFF) {
- if (range->min.udp.port == range->max.udp.port)
- return sprintf(buffer, "port %u ",
- ntohs(range->min.udp.port));
- else
- return sprintf(buffer, "ports %u-%u ",
- ntohs(range->min.udp.port),
- ntohs(range->max.udp.port));
- }
- else return 0;
-}
-
struct ip_nat_protocol ip_nat_protocol_udp = {
.name = "UDP",
.protonum = IPPROTO_UDP,
@@ -163,8 +129,6 @@ struct ip_nat_protocol ip_nat_protocol_udp = {
.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,
diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
index f0099a646a0b..3bf049517246 100644
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c
@@ -46,26 +46,10 @@ unknown_manip_pkt(struct sk_buff **pskb,
return 1;
}
-static unsigned int
-unknown_print(char *buffer,
- const struct ip_conntrack_tuple *match,
- const struct ip_conntrack_tuple *mask)
-{
- return 0;
-}
-
-static unsigned int
-unknown_print_range(char *buffer, const struct ip_nat_range *range)
-{
- return 0;
-}
-
struct ip_nat_protocol ip_nat_unknown_protocol = {
.name = "unknown",
/* .me isn't set: getting a ref to this cannot fail. */
.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 cb66b8bddeb3..1de86282d232 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -95,6 +95,7 @@ static struct ipt_table nat_table = {
.valid_hooks = NAT_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
+ .af = AF_INET,
};
/* Source NAT */
@@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
}
static int ipt_snat_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
@@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename,
}
static int ipt_dnat_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 8acb7ed40b47..4f95d477805c 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -44,6 +44,7 @@
*
*/
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -53,6 +54,7 @@
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h>
#include <linux/ip.h>
+#include <linux/udp.h>
#include <net/checksum.h>
#include <net/udp.h>
#include <asm/uaccess.h>
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 30cd4e18c129..ad438fb185b8 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -55,6 +55,44 @@
: ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
: "*ERROR*")))
+#ifdef CONFIG_XFRM
+static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
+{
+ struct ip_conntrack *ct;
+ struct ip_conntrack_tuple *t;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ unsigned long statusbit;
+
+ ct = ip_conntrack_get(skb, &ctinfo);
+ if (ct == NULL)
+ return;
+ dir = CTINFO2DIR(ctinfo);
+ t = &ct->tuplehash[dir].tuple;
+
+ if (dir == IP_CT_DIR_ORIGINAL)
+ statusbit = IPS_DST_NAT;
+ else
+ statusbit = IPS_SRC_NAT;
+
+ if (ct->status & statusbit) {
+ fl->fl4_dst = t->dst.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+ t->dst.protonum == IPPROTO_UDP)
+ fl->fl_ip_dport = t->dst.u.tcp.port;
+ }
+
+ statusbit ^= IPS_NAT_MASK;
+
+ if (ct->status & statusbit) {
+ fl->fl4_src = t->src.ip;
+ if (t->dst.protonum == IPPROTO_TCP ||
+ t->dst.protonum == IPPROTO_UDP)
+ fl->fl_ip_sport = t->src.u.tcp.port;
+ }
+}
+#endif
+
static unsigned int
ip_nat_fn(unsigned int hooknum,
struct sk_buff **pskb,
@@ -162,18 +200,20 @@ ip_nat_in(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- u_int32_t saddr, daddr;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
unsigned int ret;
- saddr = (*pskb)->nh.iph->saddr;
- daddr = (*pskb)->nh.iph->daddr;
-
ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN
- && ((*pskb)->nh.iph->saddr != saddr
- || (*pskb)->nh.iph->daddr != daddr)) {
- dst_release((*pskb)->dst);
- (*pskb)->dst = NULL;
+ && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (ct->tuplehash[dir].tuple.src.ip !=
+ ct->tuplehash[!dir].tuple.dst.ip) {
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = NULL;
+ }
}
return ret;
}
@@ -185,29 +225,30 @@ ip_nat_out(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+ unsigned int ret;
+
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
return NF_ACCEPT;
- /* We can hit fragment here; forwarded packets get
- defragmented by connection tracking coming in, then
- fragmented (grr) by the forward code.
-
- In future: If we have nfct != NULL, AND we have NAT
- initialized, AND there is no helper, then we can do full
- NAPT on the head, and IP-address-only NAT on the rest.
-
- I'm starting to have nightmares about fragments. */
-
- if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
-
- if (!*pskb)
- return NF_STOLEN;
+ ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
+ if (ret != NF_DROP && ret != NF_STOLEN
+ && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (ct->tuplehash[dir].tuple.src.ip !=
+ ct->tuplehash[!dir].tuple.dst.ip
+#ifdef CONFIG_XFRM
+ || ct->tuplehash[dir].tuple.src.u.all !=
+ ct->tuplehash[!dir].tuple.dst.u.all
+#endif
+ )
+ return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
}
-
- return ip_nat_fn(hooknum, pskb, in, out, okfn);
+ return ret;
}
static unsigned int
@@ -217,7 +258,8 @@ ip_nat_local_fn(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- u_int32_t saddr, daddr;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
unsigned int ret;
/* root is playing with raw sockets. */
@@ -225,14 +267,20 @@ ip_nat_local_fn(unsigned int hooknum,
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
return NF_ACCEPT;
- saddr = (*pskb)->nh.iph->saddr;
- daddr = (*pskb)->nh.iph->daddr;
-
ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
if (ret != NF_DROP && ret != NF_STOLEN
- && ((*pskb)->nh.iph->saddr != saddr
- || (*pskb)->nh.iph->daddr != daddr))
- return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+ && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) {
+ enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+
+ if (ct->tuplehash[dir].tuple.dst.ip !=
+ ct->tuplehash[!dir].tuple.src.ip
+#ifdef CONFIG_XFRM
+ || ct->tuplehash[dir].tuple.dst.u.all !=
+ ct->tuplehash[dir].tuple.src.u.all
+#endif
+ )
+ return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+ }
return ret;
}
@@ -316,14 +364,18 @@ static int init_or_cleanup(int init)
{
int ret = 0;
- need_ip_conntrack();
+ need_conntrack();
if (!init) goto cleanup;
+#ifdef CONFIG_XFRM
+ BUG_ON(ip_nat_decode_session != NULL);
+ ip_nat_decode_session = nat_decode_session;
+#endif
ret = ip_nat_rule_init();
if (ret < 0) {
printk("ip_nat_init: can't setup rules.\n");
- goto cleanup_nothing;
+ goto cleanup_decode_session;
}
ret = nf_register_hook(&ip_nat_in_ops);
if (ret < 0) {
@@ -371,7 +423,11 @@ static int init_or_cleanup(int init)
nf_unregister_hook(&ip_nat_in_ops);
cleanup_rule_init:
ip_nat_rule_cleanup();
- cleanup_nothing:
+ cleanup_decode_session:
+#ifdef CONFIG_XFRM
+ ip_nat_decode_session = NULL;
+ synchronize_net();
+#endif
return ret;
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 45886c8475e8..2371b2062c2d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2,7 +2,7 @@
* Packet matching code.
*
* Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
- * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * Copyright (C) 2000-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
@@ -11,16 +11,17 @@
* 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
* - increase module usage count as soon as we have rules inside
* a table
+ * 08 Oct 2005 Harald Welte <lafore@netfilter.org>
+ * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables"
*/
#include <linux/config.h>
#include <linux/cache.h>
+#include <linux/capability.h>
#include <linux/skbuff.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
#include <linux/module.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/ip.h>
#include <asm/uaccess.h>
@@ -29,6 +30,7 @@
#include <linux/err.h>
#include <linux/cpumask.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
MODULE_LICENSE("GPL");
@@ -61,14 +63,6 @@ do { \
#else
#define IP_NF_ASSERT(x)
#endif
-#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
-
-static DECLARE_MUTEX(ipt_mutex);
-
-/* Must have mutex */
-#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
-#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
-#include <linux/netfilter_ipv4/listhelp.h>
#if 0
/* All the better to debug you with... */
@@ -83,48 +77,8 @@ static DECLARE_MUTEX(ipt_mutex);
context stops packets coming through and allows user context to read
the counters or update the rules.
- To be cache friendly on SMP, we arrange them like so:
- [ n-entries ]
- ... cache-align padding ...
- [ n-entries ]
-
Hence the start of any table is given by get_table() below. */
-/* The table itself */
-struct ipt_table_info
-{
- /* Size per table */
- unsigned int size;
- /* Number of entries: FIXME. --RR */
- unsigned int number;
- /* Initial number of entries. Needed for module usage count */
- unsigned int initial_entries;
-
- /* Entry points and underflows */
- unsigned int hook_entry[NF_IP_NUMHOOKS];
- unsigned int underflow[NF_IP_NUMHOOKS];
-
- /* ipt_entry tables: one per CPU */
- char entries[0] ____cacheline_aligned;
-};
-
-static LIST_HEAD(ipt_target);
-static LIST_HEAD(ipt_match);
-static LIST_HEAD(ipt_tables);
-#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
-
-#ifdef CONFIG_SMP
-#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
-#else
-#define TABLE_OFFSET(t,p) 0
-#endif
-
-#if 0
-#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
-#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
-#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
-#endif
-
/* Returns whether matches rule or not. */
static inline int
ip_packet_match(const struct iphdr *ip,
@@ -243,7 +197,8 @@ int do_match(struct ipt_entry_match *m,
int *hotdrop)
{
/* Stop iteration if it doesn't match */
- if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop))
+ if (!m->u.kernel.match->match(skb, in, out, m->data, offset,
+ skb->nh.iph->ihl*4, hotdrop))
return 1;
else
return 0;
@@ -274,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb,
const char *indev, *outdev;
void *table_base;
struct ipt_entry *e, *back;
+ struct xt_table_info *private = table->private;
/* Initialization */
ip = (*pskb)->nh.iph;
@@ -290,25 +246,11 @@ ipt_do_table(struct sk_buff **pskb,
read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
- table_base = (void *)table->private->entries
- + TABLE_OFFSET(table->private, smp_processor_id());
- e = get_entry(table_base, table->private->hook_entry[hook]);
-
-#ifdef CONFIG_NETFILTER_DEBUG
- /* Check noone else using our table */
- if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac
- && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) {
- printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
- smp_processor_id(),
- table->name,
- &((struct ipt_entry *)table_base)->comefrom,
- ((struct ipt_entry *)table_base)->comefrom);
- }
- ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
-#endif
+ table_base = (void *)private->entries[smp_processor_id()];
+ e = get_entry(table_base, private->hook_entry[hook]);
/* For return from builtin chain */
- back = get_entry(table_base, table->private->underflow[hook]);
+ back = get_entry(table_base, private->underflow[hook]);
do {
IP_NF_ASSERT(e);
@@ -394,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb,
}
} while (!hotdrop);
-#ifdef CONFIG_NETFILTER_DEBUG
- ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
-#endif
read_unlock_bh(&table->lock);
#ifdef DEBUG_ALLOW_ALL
@@ -408,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb,
#endif
}
-/*
- * These are weird, but module loading must not be done with mutex
- * held (since they will register), and we have to have a single
- * function to use try_then_request_module().
- */
-
-/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
-static inline struct ipt_table *find_table_lock(const char *name)
-{
- struct ipt_table *t;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &ipt_tables, list)
- if (strcmp(t->name, name) == 0 && try_module_get(t->me))
- return t;
- up(&ipt_mutex);
- return NULL;
-}
-
-/* Find match, grabs ref. Returns ERR_PTR() on error. */
-static inline struct ipt_match *find_match(const char *name, u8 revision)
-{
- struct ipt_match *m;
- int err = 0;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(m, &ipt_match, list) {
- if (strcmp(m->name, name) == 0) {
- if (m->revision == revision) {
- if (try_module_get(m->me)) {
- up(&ipt_mutex);
- return m;
- }
- } else
- err = -EPROTOTYPE; /* Found something. */
- }
- }
- up(&ipt_mutex);
- return ERR_PTR(err);
-}
-
-/* Find target, grabs ref. Returns ERR_PTR() on error. */
-static inline struct ipt_target *find_target(const char *name, u8 revision)
-{
- struct ipt_target *t;
- int err = 0;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &ipt_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision == revision) {
- if (try_module_get(t->me)) {
- up(&ipt_mutex);
- return t;
- }
- } else
- err = -EPROTOTYPE; /* Found something. */
- }
- }
- up(&ipt_mutex);
- return ERR_PTR(err);
-}
-
-struct ipt_target *ipt_find_target(const char *name, u8 revision)
-{
- struct ipt_target *target;
-
- target = try_then_request_module(find_target(name, revision),
- "ipt_%s", name);
- if (IS_ERR(target) || !target)
- return NULL;
- return target;
-}
-
-static int match_revfn(const char *name, u8 revision, int *bestp)
-{
- struct ipt_match *m;
- int have_rev = 0;
-
- list_for_each_entry(m, &ipt_match, list) {
- if (strcmp(m->name, name) == 0) {
- if (m->revision > *bestp)
- *bestp = m->revision;
- if (m->revision == revision)
- have_rev = 1;
- }
- }
- return have_rev;
-}
-
-static int target_revfn(const char *name, u8 revision, int *bestp)
-{
- struct ipt_target *t;
- int have_rev = 0;
-
- list_for_each_entry(t, &ipt_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision > *bestp)
- *bestp = t->revision;
- if (t->revision == revision)
- have_rev = 1;
- }
- }
- return have_rev;
-}
-
-/* Returns true or false (if no such extension at all) */
-static inline int find_revision(const char *name, u8 revision,
- int (*revfn)(const char *, u8, int *),
- int *err)
-{
- int have_rev, best = -1;
-
- if (down_interruptible(&ipt_mutex) != 0) {
- *err = -EINTR;
- return 1;
- }
- have_rev = revfn(name, revision, &best);
- up(&ipt_mutex);
-
- /* Nothing at all? Return 0 to try loading module. */
- if (best == -1) {
- *err = -ENOENT;
- return 0;
- }
-
- *err = best;
- if (!have_rev)
- *err = -EPROTONOSUPPORT;
- return 1;
-}
-
-
/* All zeroes == unconditional rule. */
static inline int
unconditional(const struct ipt_ip *ip)
@@ -563,7 +363,8 @@ unconditional(const struct ipt_ip *ip)
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
-mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
+mark_source_chains(struct xt_table_info *newinfo,
+ unsigned int valid_hooks, void *entry0)
{
unsigned int hook;
@@ -572,7 +373,7 @@ mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
unsigned int pos = newinfo->hook_entry[hook];
struct ipt_entry *e
- = (struct ipt_entry *)(newinfo->entries + pos);
+ = (struct ipt_entry *)(entry0 + pos);
if (!(valid_hooks & (1 << hook)))
continue;
@@ -622,13 +423,13 @@ mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
goto next;
e = (struct ipt_entry *)
- (newinfo->entries + pos);
+ (entry0 + pos);
} while (oldpos == pos + e->next_offset);
/* Move along one */
size = e->next_offset;
e = (struct ipt_entry *)
- (newinfo->entries + pos + size);
+ (entry0 + pos + size);
e->counters.pcnt = pos;
pos += size;
} else {
@@ -645,7 +446,7 @@ mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
newpos = pos + e->next_offset;
}
e = (struct ipt_entry *)
- (newinfo->entries + newpos);
+ (entry0 + newpos);
e->counters.pcnt = pos;
pos = newpos;
}
@@ -708,7 +509,7 @@ check_match(struct ipt_entry_match *m,
{
struct ipt_match *match;
- match = try_then_request_module(find_match(m->u.user.name,
+ match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
m->u.user.revision),
"ipt_%s", m->u.user.name);
if (IS_ERR(match) || !match) {
@@ -753,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
goto cleanup_matches;
t = ipt_get_target(e);
- target = try_then_request_module(find_target(t->u.user.name,
+ target = try_then_request_module(xt_find_target(AF_INET,
+ t->u.user.name,
t->u.user.revision),
"ipt_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
@@ -790,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
static inline int
check_entry_size_and_hooks(struct ipt_entry *e,
- struct ipt_table_info *newinfo,
+ struct xt_table_info *newinfo,
unsigned char *base,
unsigned char *limit,
const unsigned int *hook_entries,
@@ -824,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
< 0 (not IPT_RETURN). --RR */
/* Clear counters and comefrom */
- e->counters = ((struct ipt_counters) { 0, 0 });
+ e->counters = ((struct xt_counters) { 0, 0 });
e->comefrom = 0;
(*i)++;
@@ -854,7 +656,8 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
static int
translate_table(const char *name,
unsigned int valid_hooks,
- struct ipt_table_info *newinfo,
+ struct xt_table_info *newinfo,
+ void *entry0,
unsigned int size,
unsigned int number,
const unsigned int *hook_entries,
@@ -875,11 +678,11 @@ translate_table(const char *name,
duprintf("translate_table: size %u\n", newinfo->size);
i = 0;
/* Walk through entries, checking offsets. */
- ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry_size_and_hooks,
newinfo,
- newinfo->entries,
- newinfo->entries + size,
+ entry0,
+ entry0 + size,
hook_entries, underflows, &i);
if (ret != 0)
return ret;
@@ -907,95 +710,79 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks))
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
return -ELOOP;
/* Finally, each sanity check must pass */
i = 0;
- ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
if (ret != 0) {
- IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ IPT_ENTRY_ITERATE(entry0, newinfo->size,
cleanup_entry, &i);
return ret;
}
/* And one copy for every other CPU */
for_each_cpu(i) {
- if (i == 0)
- continue;
- memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
- newinfo->entries,
- SMP_ALIGN(newinfo->size));
+ if (newinfo->entries[i] && newinfo->entries[i] != entry0)
+ memcpy(newinfo->entries[i], entry0, newinfo->size);
}
return ret;
}
-static struct ipt_table_info *
-replace_table(struct ipt_table *table,
- unsigned int num_counters,
- struct ipt_table_info *newinfo,
- int *error)
+/* Gets counters. */
+static inline int
+add_entry_to_counter(const struct ipt_entry *e,
+ struct xt_counters total[],
+ unsigned int *i)
{
- struct ipt_table_info *oldinfo;
-
-#ifdef CONFIG_NETFILTER_DEBUG
- {
- struct ipt_entry *table_base;
- unsigned int i;
-
- for_each_cpu(i) {
- table_base =
- (void *)newinfo->entries
- + TABLE_OFFSET(newinfo, i);
-
- table_base->comefrom = 0xdead57ac;
- }
- }
-#endif
-
- /* Do the substitution. */
- write_lock_bh(&table->lock);
- /* Check inside lock: is the old number correct? */
- if (num_counters != table->private->number) {
- duprintf("num_counters != table->private->number (%u/%u)\n",
- num_counters, table->private->number);
- write_unlock_bh(&table->lock);
- *error = -EAGAIN;
- return NULL;
- }
- oldinfo = table->private;
- table->private = newinfo;
- newinfo->initial_entries = oldinfo->initial_entries;
- write_unlock_bh(&table->lock);
+ ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
- return oldinfo;
+ (*i)++;
+ return 0;
}
-/* Gets counters. */
static inline int
-add_entry_to_counter(const struct ipt_entry *e,
+set_entry_to_counter(const struct ipt_entry *e,
struct ipt_counters total[],
unsigned int *i)
{
- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
+ SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
(*i)++;
return 0;
}
static void
-get_counters(const struct ipt_table_info *t,
- struct ipt_counters counters[])
+get_counters(const struct xt_table_info *t,
+ struct xt_counters counters[])
{
unsigned int cpu;
unsigned int i;
+ unsigned int curcpu;
+
+ /* Instead of clearing (by a previous call to memset())
+ * the counters and using adds, we set the counters
+ * with data used by 'current' CPU
+ * We dont care about preemption here.
+ */
+ curcpu = raw_smp_processor_id();
+
+ i = 0;
+ IPT_ENTRY_ITERATE(t->entries[curcpu],
+ t->size,
+ set_entry_to_counter,
+ counters,
+ &i);
for_each_cpu(cpu) {
+ if (cpu == curcpu)
+ continue;
i = 0;
- IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
+ IPT_ENTRY_ITERATE(t->entries[cpu],
t->size,
add_entry_to_counter,
counters,
@@ -1010,26 +797,32 @@ copy_entries_to_user(unsigned int total_size,
{
unsigned int off, num, countersize;
struct ipt_entry *e;
- struct ipt_counters *counters;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
int ret = 0;
+ void *loc_cpu_entry;
/* We need atomic snapshot of counters: rest doesn't change
(other than comefrom, which userspace doesn't care
about). */
- countersize = sizeof(struct ipt_counters) * table->private->number;
- counters = vmalloc(countersize);
+ countersize = sizeof(struct xt_counters) * private->number;
+ counters = vmalloc_node(countersize, numa_node_id());
if (counters == NULL)
return -ENOMEM;
/* First, sum counters... */
- memset(counters, 0, countersize);
write_lock_bh(&table->lock);
- get_counters(table->private, counters);
+ get_counters(private, counters);
write_unlock_bh(&table->lock);
- /* ... then copy entire thing from CPU 0... */
- if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
+ /* choose the copy that is on our node/cpu, ...
+ * This choice is lazy (because current thread is
+ * allowed to migrate to another cpu)
+ */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ /* ... then copy entire thing ... */
+ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
ret = -EFAULT;
goto free_counters;
}
@@ -1041,7 +834,7 @@ copy_entries_to_user(unsigned int total_size,
struct ipt_entry_match *m;
struct ipt_entry_target *t;
- e = (struct ipt_entry *)(table->private->entries + off);
+ e = (struct ipt_entry *)(loc_cpu_entry + off);
if (copy_to_user(userptr + off
+ offsetof(struct ipt_entry, counters),
&counters[num],
@@ -1089,21 +882,22 @@ get_entries(const struct ipt_get_entries *entries,
int ret;
struct ipt_table *t;
- t = find_table_lock(entries->name);
+ t = xt_find_table_lock(AF_INET, entries->name);
if (t && !IS_ERR(t)) {
+ struct xt_table_info *private = t->private;
duprintf("t->private->number = %u\n",
- t->private->number);
- if (entries->size == t->private->size)
- ret = copy_entries_to_user(t->private->size,
+ private->number);
+ if (entries->size == private->size)
+ ret = copy_entries_to_user(private->size,
t, uptr->entrytable);
else {
duprintf("get_entries: I've got %u not %u!\n",
- t->private->size,
+ private->size,
entries->size);
ret = -EINVAL;
}
module_put(t->me);
- up(&ipt_mutex);
+ xt_table_unlock(t);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1116,8 +910,9 @@ do_replace(void __user *user, unsigned int len)
int ret;
struct ipt_replace tmp;
struct ipt_table *t;
- struct ipt_table_info *newinfo, *oldinfo;
- struct ipt_counters *counters;
+ struct xt_table_info *newinfo, *oldinfo;
+ struct xt_counters *counters;
+ void *loc_cpu_entry, *loc_cpu_old_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
@@ -1126,38 +921,33 @@ do_replace(void __user *user, unsigned int len)
if (len != sizeof(tmp) + tmp.size)
return -ENOPROTOOPT;
- /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
- if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
- return -ENOMEM;
-
- newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(tmp.size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
- if (copy_from_user(newinfo->entries, user + sizeof(tmp),
+ /* choose the copy that is our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
tmp.size) != 0) {
ret = -EFAULT;
goto free_newinfo;
}
- counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters));
+ counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
if (!counters) {
ret = -ENOMEM;
goto free_newinfo;
}
- memset(counters, 0, tmp.num_counters * sizeof(struct ipt_counters));
ret = translate_table(tmp.name, tmp.valid_hooks,
- newinfo, tmp.size, tmp.num_entries,
+ newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
tmp.hook_entry, tmp.underflow);
if (ret != 0)
goto free_newinfo_counters;
duprintf("ip_tables: Translated table\n");
- t = try_then_request_module(find_table_lock(tmp.name),
+ t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name),
"iptable_%s", tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1172,7 +962,7 @@ do_replace(void __user *user, unsigned int len)
goto put_module;
}
- oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+ oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
if (!oldinfo)
goto put_module;
@@ -1189,24 +979,25 @@ do_replace(void __user *user, unsigned int len)
/* Get the old counters. */
get_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
- IPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
- vfree(oldinfo);
+ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+ IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
+ xt_free_table_info(oldinfo);
if (copy_to_user(tmp.counters, counters,
- sizeof(struct ipt_counters) * tmp.num_counters) != 0)
+ sizeof(struct xt_counters) * tmp.num_counters) != 0)
ret = -EFAULT;
vfree(counters);
- up(&ipt_mutex);
+ xt_table_unlock(t);
return ret;
put_module:
module_put(t->me);
- up(&ipt_mutex);
+ xt_table_unlock(t);
free_newinfo_counters_untrans:
- IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
+ IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
free_newinfo_counters:
vfree(counters);
free_newinfo:
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
@@ -1214,7 +1005,7 @@ do_replace(void __user *user, unsigned int len)
* and everything is OK. */
static inline int
add_counter_to_entry(struct ipt_entry *e,
- const struct ipt_counters addme[],
+ const struct xt_counters addme[],
unsigned int *i)
{
#if 0
@@ -1236,17 +1027,19 @@ static int
do_add_counters(void __user *user, unsigned int len)
{
unsigned int i;
- struct ipt_counters_info tmp, *paddc;
+ struct xt_counters_info tmp, *paddc;
struct ipt_table *t;
+ struct xt_table_info *private;
int ret = 0;
+ void *loc_cpu_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
- if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters))
+ if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
return -EINVAL;
- paddc = vmalloc(len);
+ paddc = vmalloc_node(len, numa_node_id());
if (!paddc)
return -ENOMEM;
@@ -1255,27 +1048,30 @@ do_add_counters(void __user *user, unsigned int len)
goto free;
}
- t = find_table_lock(tmp.name);
+ t = xt_find_table_lock(AF_INET, tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
}
write_lock_bh(&t->lock);
- if (t->private->number != paddc->num_counters) {
+ private = t->private;
+ if (private->number != paddc->num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
i = 0;
- IPT_ENTRY_ITERATE(t->private->entries,
- t->private->size,
+ /* Choose the copy that is on our node */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ IPT_ENTRY_ITERATE(loc_cpu_entry,
+ private->size,
add_counter_to_entry,
paddc->counters,
&i);
unlock_up_free:
write_unlock_bh(&t->lock);
- up(&ipt_mutex);
+ xt_table_unlock(t);
module_put(t->me);
free:
vfree(paddc);
@@ -1334,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
}
name[IPT_TABLE_MAXNAMELEN-1] = '\0';
- t = try_then_request_module(find_table_lock(name),
+ t = try_then_request_module(xt_find_table_lock(AF_INET, name),
"iptable_%s", name);
if (t && !IS_ERR(t)) {
struct ipt_getinfo info;
+ struct xt_table_info *private = t->private;
info.valid_hooks = t->valid_hooks;
- memcpy(info.hook_entry, t->private->hook_entry,
+ memcpy(info.hook_entry, private->hook_entry,
sizeof(info.hook_entry));
- memcpy(info.underflow, t->private->underflow,
+ memcpy(info.underflow, private->underflow,
sizeof(info.underflow));
- info.num_entries = t->private->number;
- info.size = t->private->size;
+ info.num_entries = private->number;
+ info.size = private->size;
memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
else
ret = 0;
- up(&ipt_mutex);
+ xt_table_unlock(t);
module_put(t->me);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1379,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
case IPT_SO_GET_REVISION_MATCH:
case IPT_SO_GET_REVISION_TARGET: {
struct ipt_get_revision rev;
- int (*revfn)(const char *, u8, int *);
+ int target;
if (*len != sizeof(rev)) {
ret = -EINVAL;
@@ -1391,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
}
if (cmd == IPT_SO_GET_REVISION_TARGET)
- revfn = target_revfn;
+ target = 1;
else
- revfn = match_revfn;
+ target = 0;
- try_then_request_module(find_revision(rev.name, rev.revision,
- revfn, &ret),
+ try_then_request_module(xt_find_revision(AF_INET, rev.name,
+ rev.revision,
+ target, &ret),
"ipt_%s", rev.name);
break;
}
@@ -1409,309 +1207,53 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-/* Registration hooks for targets. */
-int
-ipt_register_target(struct ipt_target *target)
+int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
{
int ret;
-
- ret = down_interruptible(&ipt_mutex);
- if (ret != 0)
- return ret;
- list_add(&target->list, &ipt_target);
- up(&ipt_mutex);
- return ret;
-}
-
-void
-ipt_unregister_target(struct ipt_target *target)
-{
- down(&ipt_mutex);
- LIST_DELETE(&ipt_target, target);
- up(&ipt_mutex);
-}
-
-int
-ipt_register_match(struct ipt_match *match)
-{
- int ret;
-
- ret = down_interruptible(&ipt_mutex);
- if (ret != 0)
- return ret;
-
- list_add(&match->list, &ipt_match);
- up(&ipt_mutex);
-
- return ret;
-}
-
-void
-ipt_unregister_match(struct ipt_match *match)
-{
- down(&ipt_mutex);
- LIST_DELETE(&ipt_match, match);
- up(&ipt_mutex);
-}
-
-int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl)
-{
- int ret;
- struct ipt_table_info *newinfo;
- static struct ipt_table_info bootstrap
+ struct xt_table_info *newinfo;
+ static struct xt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
+ void *loc_cpu_entry;
- newinfo = vmalloc(sizeof(struct ipt_table_info)
- + SMP_ALIGN(repl->size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(repl->size);
if (!newinfo)
return -ENOMEM;
- memcpy(newinfo->entries, repl->entries, repl->size);
+ /* choose the copy on our node/cpu
+ * but dont care of preemption
+ */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ memcpy(loc_cpu_entry, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, repl->size,
+ newinfo, loc_cpu_entry, repl->size,
repl->num_entries,
repl->hook_entry,
repl->underflow);
if (ret != 0) {
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
- ret = down_interruptible(&ipt_mutex);
- if (ret != 0) {
- vfree(newinfo);
+ if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+ xt_free_table_info(newinfo);
return ret;
}
- /* Don't autoload: we'd eat our tail... */
- if (list_named_find(&ipt_tables, table->name)) {
- ret = -EEXIST;
- goto free_unlock;
- }
-
- /* Simplifies replace_table code. */
- table->private = &bootstrap;
- if (!replace_table(table, 0, newinfo, &ret))
- goto free_unlock;
-
- duprintf("table->private->number = %u\n",
- table->private->number);
-
- /* save number of initial entries */
- table->private->initial_entries = table->private->number;
-
- rwlock_init(&table->lock);
- list_prepend(&ipt_tables, table);
-
- unlock:
- up(&ipt_mutex);
- return ret;
-
- free_unlock:
- vfree(newinfo);
- goto unlock;
+ return 0;
}
void ipt_unregister_table(struct ipt_table *table)
{
- down(&ipt_mutex);
- LIST_DELETE(&ipt_tables, table);
- up(&ipt_mutex);
+ struct xt_table_info *private;
+ void *loc_cpu_entry;
- /* Decrease module usage counts and free resources */
- IPT_ENTRY_ITERATE(table->private->entries, table->private->size,
- cleanup_entry, NULL);
- vfree(table->private);
-}
-
-/* Returns 1 if the port is matched by the range, 0 otherwise */
-static inline int
-port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
-{
- int ret;
-
- ret = (port >= min && port <= max) ^ invert;
- return ret;
-}
-
-static int
-tcp_find_option(u_int8_t option,
- const struct sk_buff *skb,
- unsigned int optlen,
- int invert,
- int *hotdrop)
-{
- /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
- unsigned int i;
-
- duprintf("tcp_match: finding option\n");
-
- if (!optlen)
- return invert;
-
- /* If we don't have the whole header, drop packet. */
- op = skb_header_pointer(skb,
- skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
- optlen, _opt);
- if (op == NULL) {
- *hotdrop = 1;
- return 0;
- }
-
- for (i = 0; i < optlen; ) {
- if (op[i] == option) return !invert;
- if (op[i] < 2) i++;
- else i += op[i+1]?:1;
- }
-
- return invert;
-}
-
-static int
-tcp_match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- int *hotdrop)
-{
- struct tcphdr _tcph, *th;
- const struct ipt_tcp *tcpinfo = matchinfo;
-
- if (offset) {
- /* To quote Alan:
-
- Don't allow a fragment of TCP 8 bytes in. Nobody normal
- causes this. Its a cracker trying to break in by doing a
- flag overwrite to pass the direction checks.
- */
- if (offset == 1) {
- duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = 1;
- }
- /* Must not be a fragment. */
- return 0;
- }
-
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
-
- th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
- sizeof(_tcph), &_tcph);
- if (th == NULL) {
- /* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
- ntohs(th->source),
- !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
- return 0;
- if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
- ntohs(th->dest),
- !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
- return 0;
- if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
- == tcpinfo->flg_cmp,
- IPT_TCP_INV_FLAGS))
- return 0;
- if (tcpinfo->option) {
- if (th->doff * 4 < sizeof(_tcph)) {
- *hotdrop = 1;
- return 0;
- }
- if (!tcp_find_option(tcpinfo->option, skb,
- th->doff*4 - sizeof(_tcph),
- tcpinfo->invflags & IPT_TCP_INV_OPTION,
- hotdrop))
- return 0;
- }
- return 1;
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-tcp_checkentry(const char *tablename,
- const struct ipt_ip *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- const struct ipt_tcp *tcpinfo = matchinfo;
-
- /* Must specify proto == TCP, and no unknown invflags */
- return ip->proto == IPPROTO_TCP
- && !(ip->invflags & IPT_INV_PROTO)
- && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp))
- && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK);
-}
-
-static int
-udp_match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- int *hotdrop)
-{
- struct udphdr _udph, *uh;
- const struct ipt_udp *udpinfo = matchinfo;
-
- /* Must not be a fragment. */
- if (offset)
- return 0;
-
- uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
- sizeof(_udph), &_udph);
- if (uh == NULL) {
- /* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- duprintf("Dropping evil UDP tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
+ private = xt_unregister_table(table);
- return port_match(udpinfo->spts[0], udpinfo->spts[1],
- ntohs(uh->source),
- !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
- && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
- ntohs(uh->dest),
- !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-udp_checkentry(const char *tablename,
- const struct ipt_ip *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
-{
- const struct ipt_udp *udpinfo = matchinfo;
-
- /* Must specify proto == UDP, and no unknown invflags */
- if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) {
- duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
- IPPROTO_UDP);
- return 0;
- }
- if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) {
- duprintf("ipt_udp: matchsize %u != %u\n",
- matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp)));
- return 0;
- }
- if (udpinfo->invflags & ~IPT_UDP_INV_MASK) {
- duprintf("ipt_udp: unknown flags %X\n",
- udpinfo->invflags);
- return 0;
- }
-
- return 1;
+ /* Decrease module usage counts and free resources */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
+ xt_free_table_info(private);
}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1730,6 +1272,7 @@ icmp_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
struct icmphdr _icmph, *ic;
@@ -1739,8 +1282,7 @@ icmp_match(const struct sk_buff *skb,
if (offset)
return 0;
- ic = skb_header_pointer(skb, skb->nh.iph->ihl*4,
- sizeof(_icmph), &_icmph);
+ ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
if (ic == NULL) {
/* We've been asked to examine this packet, and we
* can't. Hence, no choice but to drop.
@@ -1760,11 +1302,12 @@ icmp_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
icmp_checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *info,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ipt_ip *ip = info;
const struct ipt_icmp *icmpinfo = matchinfo;
/* Must specify proto == ICMP, and no unknown invflags */
@@ -1794,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = {
.get = do_ipt_get_ctl,
};
-static struct ipt_match tcp_matchstruct = {
- .name = "tcp",
- .match = &tcp_match,
- .checkentry = &tcp_checkentry,
-};
-
-static struct ipt_match udp_matchstruct = {
- .name = "udp",
- .match = &udp_match,
- .checkentry = &udp_checkentry,
-};
-
static struct ipt_match icmp_matchstruct = {
.name = "icmp",
.match = &icmp_match,
.checkentry = &icmp_checkentry,
};
-#ifdef CONFIG_PROC_FS
-static inline int print_name(const char *i,
- off_t start_offset, char *buffer, int length,
- off_t *pos, unsigned int *count)
-{
- if ((*count)++ >= start_offset) {
- unsigned int namelen;
-
- namelen = sprintf(buffer + *pos, "%s\n",
- i + sizeof(struct list_head));
- if (*pos + namelen > length) {
- /* Stop iterating */
- return 1;
- }
- *pos += namelen;
- }
- return 0;
-}
-
-static inline int print_target(const struct ipt_target *t,
- off_t start_offset, char *buffer, int length,
- off_t *pos, unsigned int *count)
-{
- if (t == &ipt_standard_target || t == &ipt_error_target)
- return 0;
- return print_name((char *)t, start_offset, buffer, length, pos, count);
-}
-
-static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return 0;
-
- LIST_FIND(&ipt_tables, print_name, void *,
- offset, buffer, length, &pos, &count);
-
- up(&ipt_mutex);
-
- /* `start' hack - see fs/proc/generic.c line ~105 */
- *start=(char *)((unsigned long)count-offset);
- return pos;
-}
-
-static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return 0;
-
- LIST_FIND(&ipt_target, print_target, struct ipt_target *,
- offset, buffer, length, &pos, &count);
-
- up(&ipt_mutex);
-
- *start = (char *)((unsigned long)count - offset);
- return pos;
-}
-
-static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ipt_mutex) != 0)
- return 0;
-
- LIST_FIND(&ipt_match, print_name, void *,
- offset, buffer, length, &pos, &count);
-
- up(&ipt_mutex);
-
- *start = (char *)((unsigned long)count - offset);
- return pos;
-}
-
-static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
-{ { "ip_tables_names", ipt_get_tables },
- { "ip_tables_targets", ipt_get_targets },
- { "ip_tables_matches", ipt_get_matches },
- { NULL, NULL} };
-#endif /*CONFIG_PROC_FS*/
-
static int __init init(void)
{
int ret;
+ xt_proto_init(AF_INET);
+
/* Noone else will be downing sem now, so we won't sleep */
- down(&ipt_mutex);
- list_append(&ipt_target, &ipt_standard_target);
- list_append(&ipt_target, &ipt_error_target);
- list_append(&ipt_match, &tcp_matchstruct);
- list_append(&ipt_match, &udp_matchstruct);
- list_append(&ipt_match, &icmp_matchstruct);
- up(&ipt_mutex);
+ xt_register_target(AF_INET, &ipt_standard_target);
+ xt_register_target(AF_INET, &ipt_error_target);
+ xt_register_match(AF_INET, &icmp_matchstruct);
/* Register setsockopt */
ret = nf_register_sockopt(&ipt_sockopts);
@@ -1919,49 +1361,23 @@ static int __init init(void)
return ret;
}
-#ifdef CONFIG_PROC_FS
- {
- struct proc_dir_entry *proc;
- int i;
-
- for (i = 0; ipt_proc_entry[i].name; i++) {
- proc = proc_net_create(ipt_proc_entry[i].name, 0,
- ipt_proc_entry[i].get_info);
- if (!proc) {
- while (--i >= 0)
- proc_net_remove(ipt_proc_entry[i].name);
- nf_unregister_sockopt(&ipt_sockopts);
- return -ENOMEM;
- }
- proc->owner = THIS_MODULE;
- }
- }
-#endif
-
- printk("ip_tables: (C) 2000-2002 Netfilter core team\n");
+ printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
return 0;
}
static void __exit fini(void)
{
nf_unregister_sockopt(&ipt_sockopts);
-#ifdef CONFIG_PROC_FS
- {
- int i;
- for (i = 0; ipt_proc_entry[i].name; i++)
- proc_net_remove(ipt_proc_entry[i].name);
- }
-#endif
+
+ xt_unregister_match(AF_INET, &icmp_matchstruct);
+ xt_unregister_target(AF_INET, &ipt_error_target);
+ xt_unregister_target(AF_INET, &ipt_standard_target);
+
+ xt_proto_fini(AF_INET);
}
EXPORT_SYMBOL(ipt_register_table);
EXPORT_SYMBOL(ipt_unregister_table);
-EXPORT_SYMBOL(ipt_register_match);
-EXPORT_SYMBOL(ipt_unregister_match);
EXPORT_SYMBOL(ipt_do_table);
-EXPORT_SYMBOL(ipt_register_target);
-EXPORT_SYMBOL(ipt_unregister_target);
-EXPORT_SYMBOL(ipt_find_target);
-
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 45c52d8f4d99..d9bc971f03af 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -379,12 +379,13 @@ target(struct sk_buff **pskb,
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
struct ipt_clusterip_tgt_info *cipinfo = targinfo;
+ const struct ipt_entry *e = e_void;
struct clusterip_config *config;
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c
index 6e319570a28c..898cdf79ce18 100644
--- a/net/ipv4/netfilter/ipt_DSCP.c
+++ b/net/ipv4/netfilter/ipt_DSCP.c
@@ -57,7 +57,7 @@ target(struct sk_buff **pskb,
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index a1319693f648..706445426a6d 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -113,12 +113,13 @@ target(struct sk_buff **pskb,
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo;
+ const struct ipt_entry *e = e_void;
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) {
printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n",
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 30be0f1dae37..6606ddb66a29 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb,
}
static int ipt_log_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 275a174c6fe6..12c56d3343ca 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -11,6 +11,7 @@
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/inetdevice.h>
#include <linux/ip.h>
#include <linux/timer.h>
#include <linux/module.h>
@@ -18,6 +19,7 @@
#include <net/protocol.h>
#include <net/ip.h>
#include <net/checksum.h>
+#include <net/route.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_tables.h>
@@ -38,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock);
/* FIXME: Multiple targets. --RR */
static int
masquerade_check(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index e6e7b6095363..b074467fe67b 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
static int
check(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c
deleted file mode 100644
index 3cedc9be8807..000000000000
--- a/net/ipv4/netfilter/ipt_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 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_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 5245bfd33d52..140be51f2f01 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module");
/* FIXME: Take multiple ranges --RR */
static int
redirect_check(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index f057025a719e..3eb47aae78c5 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -203,7 +203,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
sizeof(struct tcphdr), 0));
/* Adjust IP TTL, DF */
- nskb->nh.iph->ttl = MAXTTL;
+ nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
/* Set DF, id = 0 */
nskb->nh.iph->frag_off = htons(IP_DF);
nskb->nh.iph->id = 0;
@@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb,
}
static int check(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const struct ipt_reject_info *rejinfo = targinfo;
+ const struct ipt_entry *e = e_void;
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 7a0536d864ac..a22de59bba0e 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
static int
same_check(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 8db70d6908c3..c122841e182c 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m)
/* Must specify -p tcp --syn/--tcp-flags SYN */
static int
ipt_tcpmss_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
+ const struct ipt_entry *e = e_void;
if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) {
DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n",
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index deadb36d4428..3a44a56db239 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -52,7 +52,7 @@ target(struct sk_buff **pskb,
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e_void,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index b9ae6a9382f3..b769eb231970 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
}
static int ipt_ttl_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 2883ccd8a91d..641dbc477650 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -77,15 +77,15 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
static unsigned int nlbufsiz = 4096;
-module_param(nlbufsiz, uint, 0600); /* FIXME: Check size < 128k --RR */
+module_param(nlbufsiz, uint, 0400);
MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
static unsigned int flushtimeout = 10;
-module_param(flushtimeout, int, 0600);
+module_param(flushtimeout, uint, 0600);
MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
-static unsigned int nflog = 1;
-module_param(nflog, int, 0400);
+static int nflog = 1;
+module_param(nflog, bool, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
/* global data structures */
@@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf,
}
static int ipt_ulog_checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hookmask)
@@ -376,7 +376,7 @@ static int __init init(void)
DEBUGP("ipt_ULOG: init module\n");
- if (nlbufsiz >= 128*1024) {
+ if (nlbufsiz > 128*1024) {
printk("Netlink buffer has to be <= 128kB\n");
return -EINVAL;
}
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index e19c2a52d00c..d6b83a976518 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask)
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)
+ int offset, unsigned int protoff, int *hotdrop)
{
const struct ipt_addrtype_info *info = matchinfo;
const struct iphdr *iph = skb->nh.iph;
@@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
return ret;
}
-static int checkentry(const char *tablename, const struct ipt_ip *ip,
+static int checkentry(const char *tablename, const void *ip,
void *matchinfo, unsigned int matchsize,
unsigned int hook_mask)
{
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index a0fea847cb72..144adfec13cc 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -41,6 +41,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
struct ip_auth_hdr _ahdr, *ah;
@@ -50,7 +51,7 @@ match(const struct sk_buff *skb,
if (offset)
return 0;
- ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+ ah = skb_header_pointer(skb, protoff,
sizeof(_ahdr), &_ahdr);
if (ah == NULL) {
/* We've been asked to examine this packet, and we
@@ -69,12 +70,13 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip_void,
void *matchinfo,
unsigned int matchinfosize,
unsigned int hook_mask)
{
const struct ipt_ah *ahinfo = matchinfo;
+ const struct ipt_ip *ip = ip_void;
/* Must specify proto == AH, and no unknown invflags */
if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c
index 5df52a64a5d4..92063b4f8602 100644
--- a/net/ipv4/netfilter/ipt_dscp.c
+++ b/net/ipv4/netfilter/ipt_dscp.c
@@ -21,7 +21,7 @@ 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)
+ int offset, unsigned int protoff, int *hotdrop)
{
const struct ipt_dscp_info *info = matchinfo;
const struct iphdr *iph = skb->nh.iph;
@@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert;
}
-static int checkentry(const char *tablename, const struct ipt_ip *ip,
+static int checkentry(const char *tablename, const void *ip,
void *matchinfo, unsigned int matchsize,
unsigned int hook_mask)
{
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index b6f7181e89cc..e68b0c7981f0 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb,
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)
+ int offset, unsigned int protoff, int *hotdrop)
{
const struct ipt_ecn_info *info = matchinfo;
@@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
return 1;
}
-static int checkentry(const char *tablename, const struct ipt_ip *ip,
+static int checkentry(const char *tablename, const void *ip_void,
void *matchinfo, unsigned int matchsize,
unsigned int hook_mask)
{
const struct ipt_ecn_info *info = matchinfo;
+ const struct ipt_ip *ip = ip_void;
if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info)))
return 0;
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index e1d0dd31e117..9de191a8162d 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -42,6 +42,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
struct ip_esp_hdr _esp, *eh;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
if (offset)
return 0;
- eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+ eh = skb_header_pointer(skb, protoff,
sizeof(_esp), &_esp);
if (eh == NULL) {
/* We've been asked to examine this packet, and we
@@ -70,12 +71,13 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip_void,
void *matchinfo,
unsigned int matchinfosize,
unsigned int hook_mask)
{
const struct ipt_esp *espinfo = matchinfo;
+ const struct ipt_ip *ip = ip_void;
/* Must specify proto == ESP, and no unknown invflags */
if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) {
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 2dd1cccbdab9..4fe48c1bd5f3 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
struct ipt_hashlimit_info *r =
@@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb,
static int
hashlimit_checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index b835b7b2e560..13fb16fb7892 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
- int offset, int *hotdrop)
+ int offset, unsigned int protoff, int *hotdrop)
{
const struct ipt_iprange_info *info = matchinfo;
const struct iphdr *iph = skb->nh.iph;
@@ -63,7 +63,7 @@ match(const struct sk_buff *skb,
}
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c
deleted file mode 100644
index 4eabcfbda9d1..000000000000
--- a/net/ipv4/netfilter/ipt_length.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Kernel module to match packet length. */
-/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
- *
- * 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_ipv4/ipt_length.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
-MODULE_DESCRIPTION("IP tables packet length matching 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)
-{
- const struct ipt_length_info *info = matchinfo;
- u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
-
- return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
-}
-
-static int
-checkentry(const char *tablename,
- const struct ipt_ip *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info)))
- return 0;
-
- return 1;
-}
-
-static struct ipt_match length_match = {
- .name = "length",
- .match = &match,
- .checkentry = &checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ipt_register_match(&length_match);
-}
-
-static void __exit fini(void)
-{
- ipt_unregister_match(&length_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 99e8188162e2..2d52326553f1 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -97,6 +97,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
u16 _ports[2], *pptr;
@@ -105,7 +106,7 @@ match(const struct sk_buff *skb,
if (offset)
return 0;
- pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+ pptr = skb_header_pointer(skb, protoff,
sizeof(_ports), _ports);
if (pptr == NULL) {
/* We've been asked to examine this packet, and we
@@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
u16 _ports[2], *pptr;
@@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb,
if (offset)
return 0;
- pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+ pptr = skb_header_pointer(skb, protoff,
sizeof(_ports), _ports);
if (pptr == NULL) {
/* We've been asked to examine this packet, and we
@@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
@@ -164,7 +166,7 @@ checkentry(const char *tablename,
static int
checkentry_v1(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 0cee2862ed85..4843d0c9734f 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -27,6 +27,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
const struct ipt_owner_info *info = matchinfo;
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c
deleted file mode 100644
index 1a53924041fc..000000000000
--- a/net/ipv4/netfilter/ipt_physdev.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Kernel module to match the bridge port in and
- * out device for IP packets coming into contact with a bridge. */
-
-/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
- *
- * 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_ipv4/ipt_physdev.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_bridge.h>
-#define MATCH 1
-#define NOMATCH 0
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
-MODULE_DESCRIPTION("iptables bridge physical device match module");
-
-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)
-{
- int i;
- static const char nulldevname[IFNAMSIZ];
- const struct ipt_physdev_info *info = matchinfo;
- unsigned int ret;
- const char *indev, *outdev;
- struct nf_bridge_info *nf_bridge;
-
- /* Not a bridged IP packet or no info available yet:
- * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
- * the destination device will be a bridge. */
- if (!(nf_bridge = skb->nf_bridge)) {
- /* Return MATCH if the invert flags of the used options are on */
- if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
- !(info->invert & IPT_PHYSDEV_OP_BRIDGED))
- return NOMATCH;
- if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) &&
- !(info->invert & IPT_PHYSDEV_OP_ISIN))
- return NOMATCH;
- if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) &&
- !(info->invert & IPT_PHYSDEV_OP_ISOUT))
- return NOMATCH;
- if ((info->bitmask & IPT_PHYSDEV_OP_IN) &&
- !(info->invert & IPT_PHYSDEV_OP_IN))
- return NOMATCH;
- if ((info->bitmask & IPT_PHYSDEV_OP_OUT) &&
- !(info->invert & IPT_PHYSDEV_OP_OUT))
- return NOMATCH;
- return MATCH;
- }
-
- /* This only makes sense in the FORWARD and POSTROUTING chains */
- if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
- (!!(nf_bridge->mask & BRNF_BRIDGED) ^
- !(info->invert & IPT_PHYSDEV_OP_BRIDGED)))
- return NOMATCH;
-
- if ((info->bitmask & IPT_PHYSDEV_OP_ISIN &&
- (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) ||
- (info->bitmask & IPT_PHYSDEV_OP_ISOUT &&
- (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT))))
- return NOMATCH;
-
- if (!(info->bitmask & IPT_PHYSDEV_OP_IN))
- goto match_outdev;
- indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
- for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
- ret |= (((const unsigned int *)indev)[i]
- ^ ((const unsigned int *)info->physindev)[i])
- & ((const unsigned int *)info->in_mask)[i];
- }
-
- if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN))
- return NOMATCH;
-
-match_outdev:
- if (!(info->bitmask & IPT_PHYSDEV_OP_OUT))
- return MATCH;
- outdev = nf_bridge->physoutdev ?
- nf_bridge->physoutdev->name : nulldevname;
- for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
- ret |= (((const unsigned int *)outdev)[i]
- ^ ((const unsigned int *)info->physoutdev)[i])
- & ((const unsigned int *)info->out_mask)[i];
- }
-
- return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT);
-}
-
-static int
-checkentry(const char *tablename,
- const struct ipt_ip *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- const struct ipt_physdev_info *info = matchinfo;
-
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info)))
- return 0;
- if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) ||
- info->bitmask & ~IPT_PHYSDEV_OP_MASK)
- return 0;
- return 1;
-}
-
-static struct ipt_match physdev_match = {
- .name = "physdev",
- .match = &match,
- .checkentry = &checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ipt_register_match(&physdev_match);
-}
-
-static void __exit fini(void)
-{
- ipt_unregister_match(&physdev_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_policy.c b/net/ipv4/netfilter/ipt_policy.c
new file mode 100644
index 000000000000..18ca8258a1c5
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_policy.c
@@ -0,0 +1,173 @@
+/* IP tables module for matching IPsec policy
+ *
+ * Copyright (c) 2004,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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <net/xfrm.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_policy.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("IPtables IPsec policy matching module");
+MODULE_LICENSE("GPL");
+
+
+static inline int
+match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
+{
+#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
+
+ return MATCH(saddr, x->props.saddr.a4 & e->smask) &&
+ MATCH(daddr, x->id.daddr.a4 & e->dmask) &&
+ MATCH(proto, x->id.proto) &&
+ MATCH(mode, x->props.mode) &&
+ MATCH(spi, x->id.spi) &&
+ MATCH(reqid, x->props.reqid);
+}
+
+static int
+match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
+{
+ const struct ipt_policy_elem *e;
+ struct sec_path *sp = skb->sp;
+ int strict = info->flags & IPT_POLICY_MATCH_STRICT;
+ int i, pos;
+
+ if (sp == NULL)
+ return -1;
+ if (strict && info->len != sp->len)
+ return 0;
+
+ for (i = sp->len - 1; i >= 0; i--) {
+ pos = strict ? i - sp->len + 1 : 0;
+ if (pos >= info->len)
+ return 0;
+ e = &info->pol[pos];
+
+ if (match_xfrm_state(sp->x[i].xvec, e)) {
+ if (!strict)
+ return 1;
+ } else if (strict)
+ return 0;
+ }
+
+ return strict ? 1 : 0;
+}
+
+static int
+match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
+{
+ const struct ipt_policy_elem *e;
+ struct dst_entry *dst = skb->dst;
+ int strict = info->flags & IPT_POLICY_MATCH_STRICT;
+ int i, pos;
+
+ if (dst->xfrm == NULL)
+ return -1;
+
+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
+ pos = strict ? i : 0;
+ if (pos >= info->len)
+ return 0;
+ e = &info->pol[pos];
+
+ if (match_xfrm_state(dst->xfrm, e)) {
+ if (!strict)
+ return 1;
+ } else if (strict)
+ return 0;
+ }
+
+ return strict ? 1 : 0;
+}
+
+static int match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ const struct ipt_policy_info *info = matchinfo;
+ int ret;
+
+ if (info->flags & IPT_POLICY_MATCH_IN)
+ ret = match_policy_in(skb, info);
+ else
+ ret = match_policy_out(skb, info);
+
+ if (ret < 0)
+ ret = info->flags & IPT_POLICY_MATCH_NONE ? 1 : 0;
+ else if (info->flags & IPT_POLICY_MATCH_NONE)
+ ret = 0;
+
+ return ret;
+}
+
+static int checkentry(const char *tablename, const void *ip_void,
+ void *matchinfo, unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_policy_info *info = matchinfo;
+
+ if (matchsize != IPT_ALIGN(sizeof(*info))) {
+ printk(KERN_ERR "ipt_policy: matchsize %u != %zu\n",
+ matchsize, IPT_ALIGN(sizeof(*info)));
+ return 0;
+ }
+ if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))) {
+ printk(KERN_ERR "ipt_policy: neither incoming nor "
+ "outgoing policy selected\n");
+ return 0;
+ }
+ if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
+ && info->flags & IPT_POLICY_MATCH_OUT) {
+ printk(KERN_ERR "ipt_policy: output policy not valid in "
+ "PRE_ROUTING and INPUT\n");
+ return 0;
+ }
+ if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
+ && info->flags & IPT_POLICY_MATCH_IN) {
+ printk(KERN_ERR "ipt_policy: input policy not valid in "
+ "POST_ROUTING and OUTPUT\n");
+ return 0;
+ }
+ if (info->len > IPT_POLICY_MAX_ELEM) {
+ printk(KERN_ERR "ipt_policy: too many policy elements\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ipt_match policy_match = {
+ .name = "policy",
+ .match = match,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&policy_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&policy_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 261cbb4d4c49..44611d6d14f5 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -24,10 +24,10 @@
#define HASH_LOG 9
/* Defaults, these can be overridden on the module command-line. */
-static int ip_list_tot = 100;
-static int ip_pkt_list_tot = 20;
-static int ip_list_hash_size = 0;
-static int ip_list_perms = 0644;
+static unsigned int ip_list_tot = 100;
+static unsigned int ip_pkt_list_tot = 20;
+static unsigned int ip_list_hash_size = 0;
+static unsigned int ip_list_perms = 0644;
#ifdef DEBUG
static int debug = 1;
#endif
@@ -38,13 +38,13 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. htt
MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
MODULE_LICENSE("GPL");
-module_param(ip_list_tot, int, 0400);
-module_param(ip_pkt_list_tot, int, 0400);
-module_param(ip_list_hash_size, int, 0400);
-module_param(ip_list_perms, int, 0400);
+module_param(ip_list_tot, uint, 0400);
+module_param(ip_pkt_list_tot, uint, 0400);
+module_param(ip_list_hash_size, uint, 0400);
+module_param(ip_list_perms, uint, 0400);
#ifdef DEBUG
-module_param(debug, int, 0600);
-MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
+module_param(debug, bool, 0600);
+MODULE_PARM_DESC(debug,"enable debugging output");
#endif
MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
@@ -104,6 +104,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop);
/* Function to hash a given address into the hash table of table_size size */
@@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
skb->nh.iph->daddr = 0;
/* Clear ttl since we have no way of knowing it */
skb->nh.iph->ttl = 0;
- match(skb,NULL,NULL,info,0,NULL);
+ match(skb,NULL,NULL,info,0,0,NULL);
kfree(skb->nh.iph);
out_free_skb:
@@ -357,6 +358,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
int pkt_count, hits_found, ans;
@@ -654,7 +656,7 @@ match(const struct sk_buff *skb,
*/
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 086a1bb61e3e..9ab765e126f2 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -23,6 +23,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
const struct ipt_tos_info *info = matchinfo;
@@ -32,7 +33,7 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index 219aa9de88cc..82da53f430ab 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -21,7 +21,7 @@ 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)
+ int offset, unsigned int protoff, int *hotdrop)
{
const struct ipt_ttl_info *info = matchinfo;
@@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
return 0;
}
-static int checkentry(const char *tablename, const struct ipt_ip *ip,
+static int checkentry(const char *tablename, const void *ip,
void *matchinfo, unsigned int matchsize,
unsigned int hook_mask)
{
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 260a4f0a2a90..212a3079085b 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -78,7 +78,8 @@ static struct ipt_table packet_filter = {
.name = "filter",
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
- .me = THIS_MODULE
+ .me = THIS_MODULE,
+ .af = AF_INET,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 160eb11b6e2f..3212a5cc4b6b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = {
.valid_hooks = MANGLE_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
+ .af = AF_INET,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 47449ba83eb9..fdb9e9c81e81 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -83,7 +83,8 @@ static struct ipt_table packet_raw = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
- .me = THIS_MODULE
+ .me = THIS_MODULE,
+ .af = AF_INET,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 8202c1c0afad..167619f638c6 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -22,6 +22,7 @@
#include <linux/skbuff.h>
#include <linux/icmp.h>
#include <linux/sysctl.h>
+#include <net/route.h>
#include <net/ip.h>
#include <linux/netfilter_ipv4.h>
@@ -180,30 +181,6 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
return NF_ACCEPT;
}
-static unsigned int ipv4_refrag(unsigned int hooknum,
- struct sk_buff **pskb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct rtable *rt = (struct rtable *)(*pskb)->dst;
-
- /* We've seen it coming out the other side: confirm */
- if (ipv4_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
- return NF_DROP;
-
- /* Local packets are never produced too large for their
- interface. We degfragment them at LOCAL_OUT, however,
- so we have to refragment them here. */
- if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
- !skb_shinfo(*pskb)->tso_size) {
- /* No hook can be after us, so this should be OK. */
- ip_fragment(*pskb, okfn);
- return NF_STOLEN;
- }
- return NF_ACCEPT;
-}
-
static unsigned int ipv4_conntrack_in(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -283,7 +260,7 @@ static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
/* Refragmenter; last chance. */
static struct nf_hook_ops ipv4_conntrack_out_ops = {
- .hook = ipv4_refrag,
+ .hook = ipv4_confirm,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
@@ -300,7 +277,7 @@ static struct nf_hook_ops ipv4_conntrack_local_in_ops = {
#ifdef CONFIG_SYSCTL
/* From nf_conntrack_proto_icmp.c */
-extern unsigned long nf_ct_icmp_timeout;
+extern unsigned int nf_ct_icmp_timeout;
static struct ctl_table_header *nf_ct_ipv4_sysctl_header;
static ctl_table nf_ct_sysctl_table[] = {
@@ -392,6 +369,48 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
return -ENOENT;
}
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static int ipv4_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t),
+ &tuple->src.u3.ip);
+ NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
+ &tuple->dst.u3.ip);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static const size_t 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 int ipv4_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t)
+{
+ if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
+ return -EINVAL;
+
+ if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
+ return -EINVAL;
+
+ t->src.u3.ip =
+ *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+ t->dst.u3.ip =
+ *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+
+ return 0;
+}
+#endif
+
static struct nf_sockopt_ops so_getorigdst = {
.pf = PF_INET,
.get_optmin = SO_ORIGINAL_DST,
@@ -408,6 +427,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
.print_conntrack = ipv4_print_conntrack,
.prepare = ipv4_prepare,
.get_features = ipv4_get_features,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = ipv4_tuple_to_nfattr,
+ .nfattr_to_tuple = ipv4_nfattr_to_tuple,
+#endif
.me = THIS_MODULE,
};
@@ -551,7 +575,7 @@ MODULE_LICENSE("GPL");
static int __init init(void)
{
- need_nf_conntrack();
+ need_conntrack();
return init_or_cleanup(1);
}
@@ -563,9 +587,4 @@ static void __exit fini(void)
module_init(init);
module_exit(fini);
-void need_ip_conntrack(void)
-{
-}
-
-EXPORT_SYMBOL(need_ip_conntrack);
EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 7ddb5c08f7b8..52dc175be39a 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
return 1;
}
+/* Add 1; spaces filled with 0. */
+static const u_int8_t invmap[] = {
+ [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
+ [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
+ [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
+ [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
+ [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
+ [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
+ [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
+ [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+};
+
static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
- /* Add 1; spaces filled with 0. */
- static u_int8_t invmap[]
- = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
- [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
- [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
- [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
- [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
- [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
- [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
- [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
-
if (orig->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[orig->dst.u.icmp.type])
return 0;
@@ -120,11 +121,12 @@ static int icmp_packet(struct nf_conn *ct,
static int icmp_new(struct nf_conn *conntrack,
const struct sk_buff *skb, unsigned int dataoff)
{
- static u_int8_t valid_new[]
- = { [ICMP_ECHO] = 1,
- [ICMP_TIMESTAMP] = 1,
- [ICMP_INFO_REQUEST] = 1,
- [ICMP_ADDRESS] = 1 };
+ static const 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]) {
@@ -168,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
return -NF_ACCEPT;
}
- innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol);
+ innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -281,6 +283,60 @@ checksum_skipped:
return icmp_error_message(skb, ctinfo, hooknum);
}
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static int icmp_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_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);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static const size_t cta_min_proto[CTA_PROTO_MAX] = {
+ [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 int icmp_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *tuple)
+{
+ if (!tb[CTA_PROTO_ICMP_TYPE-1]
+ || !tb[CTA_PROTO_ICMP_CODE-1]
+ || !tb[CTA_PROTO_ICMP_ID-1])
+ return -EINVAL;
+
+ if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+ return -EINVAL;
+
+ 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_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+
+ if (tuple->dst.u.icmp.type >= sizeof(invmap)
+ || !invmap[tuple->dst.u.icmp.type])
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
{
.list = { NULL, NULL },
@@ -295,7 +351,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
.new = icmp_new,
.error = icmp_error,
.destroy = NULL,
- .me = NULL
+ .me = NULL,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = icmp_tuple_to_nfattr,
+ .nfattr_to_tuple = icmp_nfattr_to_tuple,
+#endif
};
EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 0d7dc668db46..39d49dc333a7 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -38,6 +38,7 @@
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/udp.h>
+#include <linux/inetdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 4b0d7e4d6269..f29a12da5109 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -40,12 +40,12 @@
*/
#include <linux/config.h>
+#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/byteorder.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
-#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/errno.h>
@@ -255,6 +255,7 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
return NET_RX_DROP;
}
+ nf_reset(skb);
skb_push(skb, skb->data - skb->nh.raw);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f701a136a6ae..d82c242ea704 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -240,9 +240,9 @@ static unsigned rt_hash_mask;
static int rt_hash_log;
static unsigned int rt_hash_rnd;
-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 DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
+#define RT_CACHE_STAT_INC(field) \
+ (per_cpu(rt_cache_stat, raw_smp_processor_id()).field++)
static int rt_intern_hash(unsigned hash, struct rtable *rth,
struct rtable **res);
@@ -401,7 +401,7 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos)
if (!cpu_possible(cpu))
continue;
*pos = cpu+1;
- return per_cpu_ptr(rt_cache_stat, cpu);
+ return &per_cpu(rt_cache_stat, cpu);
}
return NULL;
}
@@ -414,7 +414,7 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
if (!cpu_possible(cpu))
continue;
*pos = cpu+1;
- return per_cpu_ptr(rt_cache_stat, cpu);
+ return &per_cpu(rt_cache_stat, cpu);
}
return NULL;
@@ -3160,10 +3160,6 @@ int __init ip_rt_init(void)
ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
ip_rt_max_size = (rt_hash_mask + 1) * 16;
- rt_cache_stat = alloc_percpu(struct rt_cache_stat);
- if (!rt_cache_stat)
- return -ENOMEM;
-
devinet_init();
ip_fib_init();
@@ -3191,7 +3187,6 @@ int __init ip_rt_init(void)
if (!proc_net_fops_create("rt_cache", S_IRUGO, &rt_cache_seq_fops) ||
!(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO,
proc_net_stat))) {
- free_percpu(rt_cache_stat);
return -ENOMEM;
}
rtstat_pde->proc_fops = &rt_cpu_seq_fops;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index a34e60ea48a1..e20be3331f67 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -173,10 +173,10 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
{
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct sock *child;
- child = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
+ child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst);
if (child)
inet_csk_reqsk_queue_add(sk, req, child);
else
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 01444a02b48b..16984d4a8a06 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -12,6 +12,7 @@
#include <linux/sysctl.h>
#include <linux/config.h>
#include <linux/igmp.h>
+#include <linux/inetdevice.h>
#include <net/snmp.h>
#include <net/icmp.h>
#include <net/ip.h>
@@ -22,6 +23,7 @@
extern int sysctl_ip_nonlocal_bind;
#ifdef CONFIG_SYSCTL
+static int zero;
static int tcp_retr1_max = 255;
static int ip_local_port_range_min[] = { 1, 1 };
static int ip_local_port_range_max[] = { 65535, 65535 };
@@ -614,6 +616,15 @@ ctl_table ipv4_table[] = {
.strategy = &sysctl_jiffies
},
{
+ .ctl_name = NET_IPV4_IPFRAG_MAX_DIST,
+ .procname = "ipfrag_max_dist",
+ .data = &sysctl_ipfrag_max_dist,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .extra1 = &zero
+ },
+ {
.ctl_name = NET_TCP_NO_METRICS_SAVE,
.procname = "tcp_no_metrics_save",
.data = &sysctl_tcp_nometrics_save,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ef98b14ac56d..00aa80e93243 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1696,8 +1696,8 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
int err = 0;
if (level != SOL_TCP)
- return tp->af_specific->setsockopt(sk, level, optname,
- optval, optlen);
+ return icsk->icsk_af_ops->setsockopt(sk, level, optname,
+ optval, optlen);
/* This is a string value all the others are int's */
if (optname == TCP_CONGESTION) {
@@ -1914,7 +1914,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
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;
+ info->tcpi_pmtu = icsk->icsk_pmtu_cookie;
info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
@@ -1939,8 +1939,8 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
int val, len;
if (level != SOL_TCP)
- return tp->af_specific->getsockopt(sk, level, optname,
- optval, optlen);
+ return icsk->icsk_af_ops->getsockopt(sk, level, optname,
+ optval, optlen);
if (get_user(len, optlen))
return -EFAULT;
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 1d0cd86621b1..035f2092d73a 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -30,8 +30,6 @@ static int fast_convergence = 1;
static int max_increment = 16;
static int low_window = 14;
static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
-static int low_utilization_threshold = 153;
-static int low_utilization_period = 2;
static int initial_ssthresh = 100;
static int smooth_part = 20;
@@ -43,10 +41,6 @@ module_param(low_window, int, 0644);
MODULE_PARM_DESC(low_window, "lower bound on congestion window (for TCP friendliness)");
module_param(beta, int, 0644);
MODULE_PARM_DESC(beta, "beta for multiplicative increase");
-module_param(low_utilization_threshold, int, 0644);
-MODULE_PARM_DESC(low_utilization_threshold, "percent (scaled by 1024) for low utilization mode");
-module_param(low_utilization_period, int, 0644);
-MODULE_PARM_DESC(low_utilization_period, "if average delay exceeds then goto to low utilization mode (seconds)");
module_param(initial_ssthresh, int, 0644);
MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
module_param(smooth_part, int, 0644);
@@ -60,11 +54,6 @@ struct bictcp {
u32 loss_cwnd; /* congestion window at last loss */
u32 last_cwnd; /* the last snd_cwnd */
u32 last_time; /* time when updated last_cwnd */
- u32 delay_min; /* min delay */
- u32 delay_max; /* max delay */
- u32 last_delay;
- u8 low_utilization;/* 0: high; 1: low */
- u32 low_utilization_start; /* starting time of low utilization detection*/
u32 epoch_start; /* beginning of an epoch */
#define ACK_RATIO_SHIFT 4
u32 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */
@@ -77,11 +66,6 @@ static inline void bictcp_reset(struct bictcp *ca)
ca->loss_cwnd = 0;
ca->last_cwnd = 0;
ca->last_time = 0;
- ca->delay_min = 0;
- ca->delay_max = 0;
- ca->last_delay = 0;
- ca->low_utilization = 0;
- ca->low_utilization_start = 0;
ca->epoch_start = 0;
ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
}
@@ -143,8 +127,7 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
}
/* if in slow start or link utilization is very low */
- if ( ca->loss_cwnd == 0 ||
- (cwnd > ca->loss_cwnd && ca->low_utilization)) {
+ if (ca->loss_cwnd == 0) {
if (ca->cnt > 20) /* increase cwnd 5% per RTT */
ca->cnt = 20;
}
@@ -154,69 +137,12 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
ca->cnt = 1;
}
-
-/* Detect low utilization in congestion avoidance */
-static inline void bictcp_low_utilization(struct sock *sk, int flag)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- struct bictcp *ca = inet_csk_ca(sk);
- u32 dist, delay;
-
- /* No time stamp */
- if (!(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) ||
- /* Discard delay samples right after fast recovery */
- tcp_time_stamp < ca->epoch_start + HZ ||
- /* this delay samples may not be accurate */
- flag == 0) {
- ca->last_delay = 0;
- goto notlow;
- }
-
- delay = ca->last_delay<<3; /* use the same scale as tp->srtt*/
- ca->last_delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
- if (delay == 0) /* no previous delay sample */
- goto notlow;
-
- /* first time call or link delay decreases */
- if (ca->delay_min == 0 || ca->delay_min > delay) {
- ca->delay_min = ca->delay_max = delay;
- goto notlow;
- }
-
- if (ca->delay_max < delay)
- ca->delay_max = delay;
-
- /* utilization is low, if avg delay < dist*threshold
- for checking_period time */
- dist = ca->delay_max - ca->delay_min;
- if (dist <= ca->delay_min>>6 ||
- tp->srtt - ca->delay_min >= (dist*low_utilization_threshold)>>10)
- goto notlow;
-
- if (ca->low_utilization_start == 0) {
- ca->low_utilization = 0;
- ca->low_utilization_start = tcp_time_stamp;
- } else if ((s32)(tcp_time_stamp - ca->low_utilization_start)
- > low_utilization_period*HZ) {
- ca->low_utilization = 1;
- }
-
- return;
-
- notlow:
- ca->low_utilization = 0;
- ca->low_utilization_start = 0;
-
-}
-
static void bictcp_cong_avoid(struct sock *sk, u32 ack,
u32 seq_rtt, u32 in_flight, int data_acked)
{
struct tcp_sock *tp = tcp_sk(sk);
struct bictcp *ca = inet_csk_ca(sk);
- bictcp_low_utilization(sk, data_acked);
-
if (!tcp_is_cwnd_limited(sk, in_flight))
return;
@@ -249,11 +175,6 @@ static u32 bictcp_recalc_ssthresh(struct sock *sk)
ca->epoch_start = 0; /* end of epoch */
- /* in case of wrong delay_max*/
- if (ca->delay_min > 0 && ca->delay_max > ca->delay_min)
- ca->delay_max = ca->delay_min
- + ((ca->delay_max - ca->delay_min)* 90) / 100;
-
/* Wmax and fast convergence */
if (tp->snd_cwnd < ca->last_max_cwnd && fast_convergence)
ca->last_max_cwnd = (tp->snd_cwnd * (BICTCP_BETA_SCALE + beta))
@@ -289,14 +210,14 @@ static void bictcp_state(struct sock *sk, u8 new_state)
bictcp_reset(inet_csk_ca(sk));
}
-/* Track delayed acknowledgement ratio using sliding window
+/* Track delayed acknowledgment ratio using sliding window
* ratio = (15*ratio + sample) / 16
*/
static void bictcp_acked(struct sock *sk, u32 cnt)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
- if (cnt > 0 && icsk->icsk_ca_state == TCP_CA_Open) {
+ 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;
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index c7cc62c8dc12..e688c687d62d 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -174,6 +174,34 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
return err;
}
+
+/*
+ * Linear increase during slow start
+ */
+void tcp_slow_start(struct tcp_sock *tp)
+{
+ if (sysctl_tcp_abc) {
+ /* RFC3465: Slow Start
+ * TCP sender SHOULD increase cwnd by the number of
+ * previously unacknowledged bytes ACKed by each incoming
+ * acknowledgment, provided the increase is not more than L
+ */
+ if (tp->bytes_acked < tp->mss_cache)
+ return;
+
+ /* We MAY increase by 2 if discovered delayed ack */
+ if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ }
+ }
+ tp->bytes_acked = 0;
+
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+}
+EXPORT_SYMBOL_GPL(tcp_slow_start);
+
/*
* TCP Reno congestion control
* This is special case used for fallback as well.
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
new file mode 100644
index 000000000000..31a4986dfbf7
--- /dev/null
+++ b/net/ipv4/tcp_cubic.c
@@ -0,0 +1,411 @@
+/*
+ * TCP CUBIC: Binary Increase Congestion control for TCP v2.0
+ *
+ * This is from the implementation of CUBIC TCP in
+ * Injong Rhee, Lisong Xu.
+ * "CUBIC: A New TCP-Friendly High-Speed TCP Variant
+ * in PFLDnet 2005
+ * Available from:
+ * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/cubic-paper.pdf
+ *
+ * Unless CUBIC is enabled and congestion window is large
+ * this behaves the same as the original Reno.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+#include <asm/div64.h>
+
+#define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation
+ * max_cwnd = snd_cwnd * beta
+ */
+#define BICTCP_B 4 /*
+ * In binary search,
+ * go to point (max+min)/N
+ */
+#define BICTCP_HZ 10 /* BIC HZ 2^10 = 1024 */
+
+static int fast_convergence = 1;
+static int max_increment = 16;
+static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
+static int initial_ssthresh = 100;
+static int bic_scale = 41;
+static int tcp_friendliness = 1;
+
+static u32 cube_rtt_scale;
+static u32 beta_scale;
+static u64 cube_factor;
+
+/* Note parameters that are used for precomputing scale factors are read-only */
+module_param(fast_convergence, int, 0644);
+MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+module_param(max_increment, int, 0644);
+MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+module_param(beta, int, 0444);
+MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+module_param(initial_ssthresh, int, 0644);
+MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+module_param(bic_scale, int, 0444);
+MODULE_PARM_DESC(bic_scale, "scale (scaled by 1024) value for bic function (bic_scale/1024)");
+module_param(tcp_friendliness, int, 0644);
+MODULE_PARM_DESC(tcp_friendliness, "turn on/off tcp friendliness");
+
+#include <asm/div64.h>
+
+/* BIC TCP Parameters */
+struct bictcp {
+ u32 cnt; /* increase cwnd by 1 after ACKs */
+ u32 last_max_cwnd; /* last maximum snd_cwnd */
+ u32 loss_cwnd; /* congestion window at last loss */
+ u32 last_cwnd; /* the last snd_cwnd */
+ u32 last_time; /* time when updated last_cwnd */
+ u32 bic_origin_point;/* origin point of bic function */
+ u32 bic_K; /* time to origin point from the beginning of the current epoch */
+ u32 delay_min; /* min delay */
+ u32 epoch_start; /* beginning of an epoch */
+ u32 ack_cnt; /* number of acks */
+ u32 tcp_cwnd; /* estimated tcp cwnd */
+#define ACK_RATIO_SHIFT 4
+ u32 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */
+};
+
+static inline void bictcp_reset(struct bictcp *ca)
+{
+ ca->cnt = 0;
+ ca->last_max_cwnd = 0;
+ ca->loss_cwnd = 0;
+ ca->last_cwnd = 0;
+ ca->last_time = 0;
+ ca->bic_origin_point = 0;
+ ca->bic_K = 0;
+ ca->delay_min = 0;
+ ca->epoch_start = 0;
+ ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
+ ca->ack_cnt = 0;
+ ca->tcp_cwnd = 0;
+}
+
+static void bictcp_init(struct sock *sk)
+{
+ bictcp_reset(inet_csk_ca(sk));
+ if (initial_ssthresh)
+ tcp_sk(sk)->snd_ssthresh = initial_ssthresh;
+}
+
+/* 64bit divisor, dividend and result. dynamic precision */
+static inline 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;
+ }
+
+ /* avoid 64 bit division if possible */
+ if (dividend >> 32)
+ do_div(dividend, d);
+ else
+ dividend = (uint32_t) dividend / d;
+
+ return dividend;
+}
+
+/*
+ * calculate the cubic root of x using Newton-Raphson
+ */
+static u32 cubic_root(u64 a)
+{
+ u32 x, x1;
+
+ /* Initial estimate is based on:
+ * cbrt(x) = exp(log(x) / 3)
+ */
+ x = 1u << (fls64(a)/3);
+
+ /*
+ * Iteration based on:
+ * 2
+ * x = ( 2 * x + a / x ) / 3
+ * k+1 k k
+ */
+ do {
+ x1 = x;
+ x = (2 * x + (uint32_t) div64_64(a, x*x)) / 3;
+ } while (abs(x1 - x) > 1);
+
+ return x;
+}
+
+/*
+ * Compute congestion window to use.
+ */
+static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+{
+ u64 offs;
+ u32 delta, t, bic_target, min_cnt, max_cnt;
+
+ ca->ack_cnt++; /* count the number of ACKs */
+
+ if (ca->last_cwnd == cwnd &&
+ (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32)
+ return;
+
+ ca->last_cwnd = cwnd;
+ ca->last_time = tcp_time_stamp;
+
+ if (ca->epoch_start == 0) {
+ ca->epoch_start = tcp_time_stamp; /* record the beginning of an epoch */
+ ca->ack_cnt = 1; /* start counting */
+ ca->tcp_cwnd = cwnd; /* syn with cubic */
+
+ if (ca->last_max_cwnd <= cwnd) {
+ ca->bic_K = 0;
+ ca->bic_origin_point = cwnd;
+ } else {
+ /* Compute new K based on
+ * (wmax-cwnd) * (srtt>>3 / HZ) / c * 2^(3*bictcp_HZ)
+ */
+ ca->bic_K = cubic_root(cube_factor
+ * (ca->last_max_cwnd - cwnd));
+ ca->bic_origin_point = ca->last_max_cwnd;
+ }
+ }
+
+ /* cubic function - calc*/
+ /* calculate c * time^3 / rtt,
+ * while considering overflow in calculation of time^3
+ * (so time^3 is done by using 64 bit)
+ * and without the support of division of 64bit numbers
+ * (so all divisions are done by using 32 bit)
+ * also NOTE the unit of those veriables
+ * time = (t - K) / 2^bictcp_HZ
+ * c = bic_scale >> 10
+ * rtt = (srtt >> 3) / HZ
+ * !!! The following code does not have overflow problems,
+ * if the cwnd < 1 million packets !!!
+ */
+
+ /* change the unit from HZ to bictcp_HZ */
+ t = ((tcp_time_stamp + ca->delay_min - ca->epoch_start)
+ << BICTCP_HZ) / HZ;
+
+ if (t < ca->bic_K) /* t - K */
+ offs = ca->bic_K - t;
+ else
+ offs = t - ca->bic_K;
+
+ /* c/rtt * (t-K)^3 */
+ delta = (cube_rtt_scale * offs * offs * offs) >> (10+3*BICTCP_HZ);
+ if (t < ca->bic_K) /* below origin*/
+ bic_target = ca->bic_origin_point - delta;
+ else /* above origin*/
+ bic_target = ca->bic_origin_point + delta;
+
+ /* cubic function - calc bictcp_cnt*/
+ if (bic_target > cwnd) {
+ ca->cnt = cwnd / (bic_target - cwnd);
+ } else {
+ ca->cnt = 100 * cwnd; /* very small increment*/
+ }
+
+ if (ca->delay_min > 0) {
+ /* max increment = Smax * rtt / 0.1 */
+ min_cnt = (cwnd * HZ * 8)/(10 * max_increment * ca->delay_min);
+ if (ca->cnt < min_cnt)
+ ca->cnt = min_cnt;
+ }
+
+ /* slow start and low utilization */
+ if (ca->loss_cwnd == 0) /* could be aggressive in slow start */
+ ca->cnt = 50;
+
+ /* TCP Friendly */
+ if (tcp_friendliness) {
+ u32 scale = beta_scale;
+ delta = (cwnd * scale) >> 3;
+ while (ca->ack_cnt > delta) { /* update tcp cwnd */
+ ca->ack_cnt -= delta;
+ ca->tcp_cwnd++;
+ }
+
+ if (ca->tcp_cwnd > cwnd){ /* if bic is slower than tcp */
+ delta = ca->tcp_cwnd - cwnd;
+ max_cnt = cwnd / delta;
+ if (ca->cnt > max_cnt)
+ ca->cnt = max_cnt;
+ }
+ }
+
+ ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack;
+ if (ca->cnt == 0) /* cannot be zero */
+ ca->cnt = 1;
+}
+
+
+/* Keep track of minimum rtt */
+static inline void measure_delay(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+ u32 delay;
+
+ /* No time stamp */
+ if (!(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) ||
+ /* Discard delay samples right after fast recovery */
+ (s32)(tcp_time_stamp - ca->epoch_start) < HZ)
+ return;
+
+ delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+ if (delay == 0)
+ delay = 1;
+
+ /* first time call or link delay decreases */
+ if (ca->delay_min == 0 || ca->delay_min > delay)
+ ca->delay_min = delay;
+}
+
+static void bictcp_cong_avoid(struct sock *sk, u32 ack,
+ u32 seq_rtt, u32 in_flight, int data_acked)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ if (data_acked)
+ measure_delay(sk);
+
+ if (!tcp_is_cwnd_limited(sk, in_flight))
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh)
+ tcp_slow_start(tp);
+ else {
+ bictcp_update(ca, tp->snd_cwnd);
+
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+ */
+ if (tp->snd_cwnd_cnt >= ca->cnt) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+
+}
+
+static u32 bictcp_recalc_ssthresh(struct sock *sk)
+{
+ const struct tcp_sock *tp = tcp_sk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ ca->epoch_start = 0; /* end of epoch */
+
+ /* Wmax and fast convergence */
+ if (tp->snd_cwnd < ca->last_max_cwnd && fast_convergence)
+ ca->last_max_cwnd = (tp->snd_cwnd * (BICTCP_BETA_SCALE + beta))
+ / (2 * BICTCP_BETA_SCALE);
+ else
+ ca->last_max_cwnd = tp->snd_cwnd;
+
+ ca->loss_cwnd = tp->snd_cwnd;
+
+ return max((tp->snd_cwnd * beta) / BICTCP_BETA_SCALE, 2U);
+}
+
+static u32 bictcp_undo_cwnd(struct sock *sk)
+{
+ struct bictcp *ca = inet_csk_ca(sk);
+
+ return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
+}
+
+static u32 bictcp_min_cwnd(struct sock *sk)
+{
+ return tcp_sk(sk)->snd_ssthresh;
+}
+
+static void bictcp_state(struct sock *sk, u8 new_state)
+{
+ if (new_state == TCP_CA_Loss)
+ bictcp_reset(inet_csk_ca(sk));
+}
+
+/* Track delayed acknowledgment ratio using sliding window
+ * ratio = (15*ratio + sample) / 16
+ */
+static void bictcp_acked(struct sock *sk, u32 cnt)
+{
+ 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;
+ }
+}
+
+
+static struct tcp_congestion_ops cubictcp = {
+ .init = bictcp_init,
+ .ssthresh = bictcp_recalc_ssthresh,
+ .cong_avoid = bictcp_cong_avoid,
+ .set_state = bictcp_state,
+ .undo_cwnd = bictcp_undo_cwnd,
+ .min_cwnd = bictcp_min_cwnd,
+ .pkts_acked = bictcp_acked,
+ .owner = THIS_MODULE,
+ .name = "cubic",
+};
+
+static int __init cubictcp_register(void)
+{
+ BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE);
+
+ /* Precompute a bunch of the scaling factors that are used per-packet
+ * based on SRTT of 100ms
+ */
+
+ beta_scale = 8*(BICTCP_BETA_SCALE+beta)/ 3 / (BICTCP_BETA_SCALE - beta);
+
+ cube_rtt_scale = (bic_scale << 3) / 10; /* 1024*c/rtt */
+
+ /* calculate the "K" for (wmax-cwnd) = c/rtt * K^3
+ * so K = cubic_root( (wmax-cwnd)*rtt/c )
+ * the unit of K is bictcp_HZ=2^10, not HZ
+ *
+ * c = bic_scale >> 10
+ * rtt = 100ms
+ *
+ * the following code has been designed and tested for
+ * cwnd < 1 million packets
+ * RTT < 100 seconds
+ * HZ < 1,000,00 (corresponding to 10 nano-second)
+ */
+
+ /* 1/c * 2^2*bictcp_HZ * srtt */
+ cube_factor = 1ull << (10+3*BICTCP_HZ); /* 2^40 */
+
+ /* divide by bic_scale and by constant Srtt (100ms) */
+ do_div(cube_factor, bic_scale * 10);
+
+ return tcp_register_congestion_control(&cubictcp);
+}
+
+static void __exit cubictcp_unregister(void)
+{
+ tcp_unregister_congestion_control(&cubictcp);
+}
+
+module_init(cubictcp_register);
+module_exit(cubictcp_unregister);
+
+MODULE_AUTHOR("Sangtae Ha, Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CUBIC TCP");
+MODULE_VERSION("2.0");
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bf2e23086bce..a97ed5416c28 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -115,8 +115,8 @@ int sysctl_tcp_abc = 1;
/* Adapt the MSS value used to make delayed ack decision to the
* real world.
*/
-static inline void tcp_measure_rcv_mss(struct sock *sk,
- const struct sk_buff *skb)
+static void tcp_measure_rcv_mss(struct sock *sk,
+ const struct sk_buff *skb)
{
struct inet_connection_sock *icsk = inet_csk(sk);
const unsigned int lss = icsk->icsk_ack.last_seg_size;
@@ -246,8 +246,8 @@ static int __tcp_grow_window(const struct sock *sk, struct tcp_sock *tp,
return 0;
}
-static inline void tcp_grow_window(struct sock *sk, struct tcp_sock *tp,
- struct sk_buff *skb)
+static void tcp_grow_window(struct sock *sk, struct tcp_sock *tp,
+ struct sk_buff *skb)
{
/* Check #1 */
if (tp->rcv_ssthresh < tp->window_clamp &&
@@ -341,6 +341,26 @@ static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
tp->rcv_ssthresh = min(tp->window_clamp, 2U*tp->advmss);
}
+
+/* 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.
+ * It's better to underestimate the RCV_MSS rather than overestimate.
+ * Overestimations make us ACKing less frequently than needed.
+ * Underestimations are more easy to detect and fix by tcp_measure_rcv_mss().
+ */
+void tcp_initialize_rcv_mss(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ unsigned int hint = min_t(unsigned int, tp->advmss, tp->mss_cache);
+
+ hint = min(hint, tp->rcv_wnd/2);
+ hint = min(hint, TCP_MIN_RCVMSS);
+ hint = max(hint, TCP_MIN_MSS);
+
+ inet_csk(sk)->icsk_ack.rcv_mss = hint;
+}
+
/* Receiver "autotuning" code.
*
* The algorithm for RTT estimation w/o timestamps is based on
@@ -735,6 +755,27 @@ __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst)
return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
}
+/* Set slow start threshold and cwnd not falling to slow start */
+void tcp_enter_cwr(struct sock *sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ tp->prior_ssthresh = 0;
+ tp->bytes_acked = 0;
+ if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) {
+ tp->undo_marker = 0;
+ tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk);
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ tcp_packets_in_flight(tp) + 1U);
+ tp->snd_cwnd_cnt = 0;
+ tp->high_seq = tp->snd_nxt;
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ TCP_ECN_queue_cwr(tp);
+
+ tcp_set_ca_state(sk, TCP_CA_CWR);
+ }
+}
+
/* Initialize metrics on socket. */
static void tcp_init_metrics(struct sock *sk)
@@ -2070,8 +2111,8 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
tcp_ack_no_tstamp(sk, seq_rtt, flag);
}
-static inline void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
- u32 in_flight, int good)
+static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
+ u32 in_flight, int good)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
icsk->icsk_ca_ops->cong_avoid(sk, ack, rtt, in_flight, good);
@@ -2082,7 +2123,7 @@ static inline void tcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
* RFC2988 recommends to restart timer to now+rto.
*/
-static inline void tcp_ack_packets_out(struct sock *sk, struct tcp_sock *tp)
+static void tcp_ack_packets_out(struct sock *sk, struct tcp_sock *tp)
{
if (!tp->packets_out) {
inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);
@@ -2147,7 +2188,7 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
return acked;
}
-static inline u32 tcp_usrtt(const struct sk_buff *skb)
+static u32 tcp_usrtt(const struct sk_buff *skb)
{
struct timeval tv, now;
@@ -2342,7 +2383,7 @@ static int tcp_ack_update_window(struct sock *sk, struct tcp_sock *tp,
if (nwin > tp->max_window) {
tp->max_window = nwin;
- tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_sync_mss(sk, inet_csk(sk)->icsk_pmtu_cookie);
}
}
}
@@ -2583,8 +2624,8 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
/* Fast parse options. This hopes to only see timestamps.
* If it is wrong it falls back on tcp_parse_options().
*/
-static inline int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
- struct tcp_sock *tp)
+static int tcp_fast_parse_options(struct sk_buff *skb, struct tcphdr *th,
+ struct tcp_sock *tp)
{
if (th->doff == sizeof(struct tcphdr)>>2) {
tp->rx_opt.saw_tstamp = 0;
@@ -2804,8 +2845,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
}
}
-static __inline__ int
-tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, u32 end_seq)
+static inline int tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, u32 end_seq)
{
if (!after(seq, sp->end_seq) && !after(sp->start_seq, end_seq)) {
if (before(seq, sp->start_seq))
@@ -2817,7 +2857,7 @@ tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, u32 end_seq)
return 0;
}
-static inline void tcp_dsack_set(struct tcp_sock *tp, u32 seq, u32 end_seq)
+static void tcp_dsack_set(struct tcp_sock *tp, u32 seq, u32 end_seq)
{
if (tp->rx_opt.sack_ok && sysctl_tcp_dsack) {
if (before(seq, tp->rcv_nxt))
@@ -2832,7 +2872,7 @@ static inline void tcp_dsack_set(struct tcp_sock *tp, u32 seq, u32 end_seq)
}
}
-static inline void tcp_dsack_extend(struct tcp_sock *tp, u32 seq, u32 end_seq)
+static void tcp_dsack_extend(struct tcp_sock *tp, u32 seq, u32 end_seq)
{
if (!tp->rx_opt.dsack)
tcp_dsack_set(tp, seq, end_seq);
@@ -2890,7 +2930,7 @@ static void tcp_sack_maybe_coalesce(struct tcp_sock *tp)
}
}
-static __inline__ void tcp_sack_swap(struct tcp_sack_block *sack1, struct tcp_sack_block *sack2)
+static inline void tcp_sack_swap(struct tcp_sack_block *sack1, struct tcp_sack_block *sack2)
{
__u32 tmp;
@@ -3307,7 +3347,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list,
int offset = start - TCP_SKB_CB(skb)->seq;
int size = TCP_SKB_CB(skb)->end_seq - start;
- if (offset < 0) BUG();
+ BUG_ON(offset < 0);
if (size > 0) {
size = min(copy, size);
if (skb_copy_bits(skb, offset, skb_put(nskb, size), size))
@@ -3455,7 +3495,7 @@ void tcp_cwnd_application_limited(struct sock *sk)
tp->snd_cwnd_stamp = tcp_time_stamp;
}
-static inline int tcp_should_expand_sndbuf(struct sock *sk, struct tcp_sock *tp)
+static int tcp_should_expand_sndbuf(struct sock *sk, struct tcp_sock *tp)
{
/* If the user specified a specific send buffer setting, do
* not modify it.
@@ -3502,7 +3542,7 @@ static void tcp_new_space(struct sock *sk)
sk->sk_write_space(sk);
}
-static inline void tcp_check_space(struct sock *sk)
+static void tcp_check_space(struct sock *sk)
{
if (sock_flag(sk, SOCK_QUEUE_SHRUNK)) {
sock_reset_flag(sk, SOCK_QUEUE_SHRUNK);
@@ -3512,7 +3552,7 @@ static inline void tcp_check_space(struct sock *sk)
}
}
-static __inline__ void tcp_data_snd_check(struct sock *sk, struct tcp_sock *tp)
+static inline void tcp_data_snd_check(struct sock *sk, struct tcp_sock *tp)
{
tcp_push_pending_frames(sk, tp);
tcp_check_space(sk);
@@ -3544,7 +3584,7 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible)
}
}
-static __inline__ void tcp_ack_snd_check(struct sock *sk)
+static inline void tcp_ack_snd_check(struct sock *sk)
{
if (!inet_csk_ack_scheduled(sk)) {
/* We sent a data segment already. */
@@ -3692,8 +3732,7 @@ static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
return result;
}
-static __inline__ int
-tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
+static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
{
return skb->ip_summed != CHECKSUM_UNNECESSARY &&
__tcp_checksum_complete_user(sk, skb);
@@ -3967,12 +4006,12 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
{
struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
int saved_clamp = tp->rx_opt.mss_clamp;
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
@@ -4061,7 +4100,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
if (tp->rx_opt.sack_ok && sysctl_tcp_fack)
tp->rx_opt.sack_ok |= 2;
- tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
tcp_initialize_rcv_mss(sk);
/* Remember, tcp_poll() does not lock socket!
@@ -4072,7 +4111,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_set_state(sk, TCP_ESTABLISHED);
/* Make sure socket is routed, for correct metrics. */
- tp->af_specific->rebuild_header(sk);
+ icsk->icsk_af_ops->rebuild_header(sk);
tcp_init_metrics(sk);
@@ -4098,8 +4137,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
sk_wake_async(sk, 0, POLL_OUT);
}
- icsk = inet_csk(sk);
-
if (sk->sk_write_pending ||
icsk->icsk_accept_queue.rskq_defer_accept ||
icsk->icsk_ack.pingpong) {
@@ -4173,7 +4210,7 @@ discard:
if (tp->ecn_flags&TCP_ECN_OK)
sock_set_flag(sk, SOCK_NO_LARGESEND);
- tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
tcp_initialize_rcv_mss(sk);
@@ -4220,6 +4257,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
{
struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
int queued = 0;
tp->rx_opt.saw_tstamp = 0;
@@ -4236,7 +4274,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
goto discard;
if(th->syn) {
- if(tp->af_specific->conn_request(sk, skb) < 0)
+ if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
return 1;
/* Now we have several options: In theory there is
@@ -4349,7 +4387,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
/* Make sure socket is routed, for
* correct metrics.
*/
- tp->af_specific->rebuild_header(sk);
+ icsk->icsk_af_ops->rebuild_header(sk);
tcp_init_metrics(sk);
@@ -4475,3 +4513,4 @@ EXPORT_SYMBOL(sysctl_tcp_abc);
EXPORT_SYMBOL(tcp_parse_options);
EXPORT_SYMBOL(tcp_rcv_established);
EXPORT_SYMBOL(tcp_rcv_state_process);
+EXPORT_SYMBOL(tcp_initialize_rcv_mss);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4d5021e1929b..6ea353907af5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -69,6 +69,7 @@
#include <net/transp_v6.h>
#include <net/ipv6.h>
#include <net/inet_common.h>
+#include <net/timewait_sock.h>
#include <net/xfrm.h>
#include <linux/inet.h>
@@ -86,8 +87,7 @@ int sysctl_tcp_low_latency;
/* Socket used for sending RSTs */
static struct socket *tcp_socket;
-void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
- struct sk_buff *skb);
+void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
.lhash_lock = RW_LOCK_UNLOCKED,
@@ -97,7 +97,8 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
{
- return inet_csk_get_port(&tcp_hashinfo, sk, snum);
+ return inet_csk_get_port(&tcp_hashinfo, sk, snum,
+ inet_csk_bind_conflict);
}
static void tcp_v4_hash(struct sock *sk)
@@ -118,202 +119,38 @@ static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb)
skb->h.th->source);
}
-/* called with local bh disabled */
-static int __tcp_v4_check_established(struct sock *sk, __u16 lport,
- struct inet_timewait_sock **twp)
+int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
{
- struct inet_sock *inet = inet_sk(sk);
- u32 daddr = inet->rcv_saddr;
- u32 saddr = inet->daddr;
- int dif = sk->sk_bound_dev_if;
- INET_ADDR_COOKIE(acookie, saddr, daddr)
- const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
- unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
- struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
- struct sock *sk2;
- const struct hlist_node *node;
- struct inet_timewait_sock *tw;
-
- prefetch(head->chain.first);
- write_lock(&head->lock);
-
- /* Check TIME-WAIT sockets first. */
- sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
- tw = inet_twsk(sk2);
-
- if (INET_TW_MATCH(sk2, hash, 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
- of data integrity. Even without PAWS it
- is safe provided sequence spaces do not
- overlap i.e. at data rates <= 80Mbit/sec.
-
- Actually, the idea is close to VJ's one,
- only timestamp cache is held not per host,
- but per port pair and TW bucket is used
- as state holder.
+ const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
+ struct tcp_sock *tp = tcp_sk(sk);
- If TW bucket has been already destroyed we
- fall back to VJ's scheme and use initial
- timestamp retrieved from peer table.
- */
- if (tcptw->tw_ts_recent_stamp &&
- (!twp || (sysctl_tcp_tw_reuse &&
- xtime.tv_sec -
- 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 = tcptw->tw_ts_recent;
- tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
- sock_hold(sk2);
- goto unique;
- } else
- goto not_unique;
- }
- }
- tw = NULL;
+ /* With PAWS, it is safe from the viewpoint
+ of data integrity. Even without PAWS it is safe provided sequence
+ spaces do not overlap i.e. at data rates <= 80Mbit/sec.
- /* And established part... */
- sk_for_each(sk2, node, &head->chain) {
- if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
- goto not_unique;
- }
+ Actually, the idea is close to VJ's one, only timestamp cache is
+ held not per host, but per port pair and TW bucket is used as state
+ holder.
-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_hash = 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) {
- *twp = tw;
- NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
- } else if (tw) {
- /* Silly. Should hash-dance instead... */
- inet_twsk_deschedule(tw, &tcp_death_row);
- NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
-
- inet_twsk_put(tw);
+ If TW bucket has been already destroyed we fall back to VJ's scheme
+ and use initial timestamp retrieved from peer table.
+ */
+ if (tcptw->tw_ts_recent_stamp &&
+ (twp == NULL || (sysctl_tcp_tw_reuse &&
+ xtime.tv_sec - 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 = tcptw->tw_ts_recent;
+ tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
+ sock_hold(sktw);
+ return 1;
}
return 0;
-
-not_unique:
- write_unlock(&head->lock);
- return -EADDRNOTAVAIL;
}
-static inline u32 connect_port_offset(const struct sock *sk)
-{
- const struct inet_sock *inet = inet_sk(sk);
-
- return secure_tcp_port_ephemeral(inet->rcv_saddr, inet->daddr,
- inet->dport);
-}
-
-/*
- * Bind a port for a connect operation and hash it.
- */
-static inline int tcp_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) {
- int low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int range = high - low;
- int i;
- int port;
- static u32 hint;
- u32 offset = hint + connect_port_offset(sk);
- struct hlist_node *node;
- struct inet_timewait_sock *tw = NULL;
-
- local_bh_disable();
- for (i = 1; i <= range; i++) {
- port = low + (i + offset) % range;
- 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.
- */
- inet_bind_bucket_for_each(tb, node, &head->chain) {
- if (tb->port == port) {
- BUG_TRAP(!hlist_empty(&tb->owners));
- if (tb->fastreuse >= 0)
- goto next_port;
- if (!__tcp_v4_check_established(sk,
- port,
- &tw))
- goto ok;
- goto next_port;
- }
- }
-
- tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
- if (!tb) {
- spin_unlock(&head->lock);
- break;
- }
- tb->fastreuse = -1;
- goto ok;
-
- next_port:
- spin_unlock(&head->lock);
- }
- local_bh_enable();
-
- return -EADDRNOTAVAIL;
-
-ok:
- hint += i;
-
- /* Head lock still held and bh's disabled */
- inet_bind_hash(sk, tb, port);
- if (sk_unhashed(sk)) {
- inet_sk(sk)->sport = htons(port);
- __inet_hash(&tcp_hashinfo, sk, 0);
- }
- spin_unlock(&head->lock);
-
- if (tw) {
- inet_twsk_deschedule(tw, &tcp_death_row);;
- inet_twsk_put(tw);
- }
-
- ret = 0;
- goto out;
- }
-
- 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) {
- __inet_hash(&tcp_hashinfo, sk, 0);
- spin_unlock_bh(&head->lock);
- return 0;
- } else {
- spin_unlock(&head->lock);
- /* No definite answer... Walk to established hash table */
- ret = __tcp_v4_check_established(sk, snum, NULL);
-out:
- local_bh_enable();
- return ret;
- }
-}
+EXPORT_SYMBOL_GPL(tcp_twsk_unique);
/* This will initiate an outgoing connection. */
int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
@@ -383,9 +220,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
inet->dport = usin->sin_port;
inet->daddr = daddr;
- tp->ext_header_len = 0;
+ inet_csk(sk)->icsk_ext_hdr_len = 0;
if (inet->opt)
- tp->ext_header_len = inet->opt->optlen;
+ inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
tp->rx_opt.mss_clamp = 536;
@@ -395,7 +232,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
* complete initialization after this.
*/
tcp_set_state(sk, TCP_SYN_SENT);
- err = tcp_v4_hash_connect(sk);
+ err = inet_hash_connect(&tcp_death_row, sk);
if (err)
goto failure;
@@ -433,12 +270,10 @@ failure:
/*
* This routine does path mtu discovery as defined in RFC1191.
*/
-static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
- u32 mtu)
+static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu)
{
struct dst_entry *dst;
struct inet_sock *inet = inet_sk(sk);
- struct tcp_sock *tp = tcp_sk(sk);
/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
* send out by Linux are always <576bytes so they should go through
@@ -467,7 +302,7 @@ static inline void do_pmtu_discovery(struct sock *sk, struct iphdr *iph,
mtu = dst_mtu(dst);
if (inet->pmtudisc != IP_PMTUDISC_DONT &&
- tp->pmtu_cookie > mtu) {
+ inet_csk(sk)->icsk_pmtu_cookie > mtu) {
tcp_sync_mss(sk, mtu);
/* Resend the TCP packet because it's
@@ -644,10 +479,10 @@ out:
}
/* This routine computes an IPv4 TCP checksum. */
-void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
- struct sk_buff *skb)
+void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
{
struct inet_sock *inet = inet_sk(sk);
+ struct tcphdr *th = skb->h.th;
if (skb->ip_summed == CHECKSUM_HW) {
th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0);
@@ -826,7 +661,8 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
kfree(inet_rsk(req)->opt);
}
-static inline void syn_flood_warning(struct sk_buff *skb)
+#ifdef CONFIG_SYN_COOKIES
+static void syn_flood_warning(struct sk_buff *skb)
{
static unsigned long warntime;
@@ -837,12 +673,13 @@ static inline void syn_flood_warning(struct sk_buff *skb)
ntohs(skb->h.th->dest));
}
}
+#endif
/*
* Save and compile IPv4 options into the request_sock if needed.
*/
-static inline struct ip_options *tcp_v4_save_options(struct sock *sk,
- struct sk_buff *skb)
+static struct ip_options *tcp_v4_save_options(struct sock *sk,
+ struct sk_buff *skb)
{
struct ip_options *opt = &(IPCB(skb)->opt);
struct ip_options *dopt = NULL;
@@ -869,6 +706,11 @@ struct request_sock_ops tcp_request_sock_ops = {
.send_reset = tcp_v4_send_reset,
};
+static struct timewait_sock_ops tcp_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct tcp_timewait_sock),
+ .twsk_unique = tcp_twsk_unique,
+};
+
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
struct inet_request_sock *ireq;
@@ -1053,9 +895,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
ireq->opt = NULL;
newinet->mc_index = inet_iif(skb);
newinet->mc_ttl = skb->nh.iph->ttl;
- newtp->ext_header_len = 0;
+ inet_csk(newsk)->icsk_ext_hdr_len = 0;
if (newinet->opt)
- newtp->ext_header_len = newinet->opt->optlen;
+ inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
newinet->id = newtp->write_seq ^ jiffies;
tcp_sync_mss(newsk, dst_mtu(dst));
@@ -1238,6 +1080,7 @@ process:
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
goto discard_and_relse;
+ nf_reset(skb);
if (sk_filter(sk, skb, 0))
goto discard_and_relse;
@@ -1314,16 +1157,6 @@ do_time_wait:
goto discard_it;
}
-static void v4_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
-{
- struct sockaddr_in *sin = (struct sockaddr_in *) uaddr;
- struct inet_sock *inet = inet_sk(sk);
-
- sin->sin_family = AF_INET;
- sin->sin_addr.s_addr = inet->daddr;
- sin->sin_port = inet->dport;
-}
-
/* VJ's idea. Save last timestamp seen from this destination
* and hold it at least for normal timewait interval to use for duplicate
* segment detection in subsequent connections, before they enter synchronized
@@ -1382,7 +1215,7 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
return 0;
}
-struct tcp_func ipv4_specific = {
+struct inet_connection_sock_af_ops ipv4_specific = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
.rebuild_header = inet_sk_rebuild_header,
@@ -1392,7 +1225,7 @@ struct tcp_func ipv4_specific = {
.net_header_len = sizeof(struct iphdr),
.setsockopt = ip_setsockopt,
.getsockopt = ip_getsockopt,
- .addr2sockaddr = v4_addr2sockaddr,
+ .addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
};
@@ -1433,7 +1266,8 @@ static int tcp_v4_init_sock(struct sock *sk)
sk->sk_write_space = sk_stream_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
- tp->af_specific = &ipv4_specific;
+ icsk->icsk_af_ops = &ipv4_specific;
+ icsk->icsk_sync_mss = tcp_sync_mss;
sk->sk_sndbuf = sysctl_tcp_wmem[1];
sk->sk_rcvbuf = sysctl_tcp_rmem[1];
@@ -1989,7 +1823,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),
+ .twsk_prot = &tcp_timewait_sock_ops,
.rsk_prot = &tcp_request_sock_ops,
};
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 1b66a2ac4321..2b9b7f6c7f7c 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -274,18 +274,18 @@ kill:
void tcp_time_wait(struct sock *sk, int state, int timeo)
{
struct inet_timewait_sock *tw = NULL;
+ const struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_sock *tp = tcp_sk(sk);
int recycle_ok = 0;
if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
- recycle_ok = tp->af_specific->remember_stamp(sk);
+ recycle_ok = icsk->icsk_af_ops->remember_stamp(sk);
if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
tw = inet_twsk_alloc(sk, state);
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;
@@ -298,10 +298,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
#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);
+ struct inet6_timewait_sock *tw6;
- ipv6_addr_copy(&tcp6tw->tw_v6_daddr, &np->daddr);
- ipv6_addr_copy(&tcp6tw->tw_v6_rcv_saddr, &np->rcv_saddr);
+ tw->tw_ipv6_offset = inet6_tw_offset(sk->sk_prot);
+ tw6 = inet6_twsk((struct sock *)tw);
+ ipv6_addr_copy(&tw6->tw_v6_daddr, &np->daddr);
+ ipv6_addr_copy(&tw6->tw_v6_rcv_saddr, &np->rcv_saddr);
tw->tw_ipv6only = np->ipv6only;
}
#endif
@@ -456,7 +458,6 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
struct request_sock **prev)
{
struct tcphdr *th = skb->h.th;
- struct tcp_sock *tp = tcp_sk(sk);
u32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
int paws_reject = 0;
struct tcp_options_received tmp_opt;
@@ -613,7 +614,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
* ESTABLISHED STATE. If it will be dropped after
* socket is created, wait for troubles.
*/
- child = tp->af_specific->syn_recv_sock(sk, skb, req, NULL);
+ child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb,
+ req, NULL);
if (child == NULL)
goto listen_overflow;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b7325e0b406a..a7623ead39a8 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -51,8 +51,8 @@ int sysctl_tcp_retrans_collapse = 1;
*/
int sysctl_tcp_tso_win_divisor = 3;
-static inline void update_send_head(struct sock *sk, struct tcp_sock *tp,
- struct sk_buff *skb)
+static void update_send_head(struct sock *sk, struct tcp_sock *tp,
+ struct sk_buff *skb)
{
sk->sk_send_head = skb->next;
if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
@@ -124,8 +124,8 @@ static void tcp_cwnd_restart(struct sock *sk, struct dst_entry *dst)
tp->snd_cwnd_used = 0;
}
-static inline void tcp_event_data_sent(struct tcp_sock *tp,
- struct sk_buff *skb, struct sock *sk)
+static void tcp_event_data_sent(struct tcp_sock *tp,
+ struct sk_buff *skb, struct sock *sk)
{
struct inet_connection_sock *icsk = inet_csk(sk);
const u32 now = tcp_time_stamp;
@@ -142,7 +142,7 @@ static inline void tcp_event_data_sent(struct tcp_sock *tp,
icsk->icsk_ack.pingpong = 1;
}
-static __inline__ void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
+static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
{
tcp_dec_quickack_mode(sk, pkts);
inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
@@ -212,7 +212,7 @@ void tcp_select_initial_window(int __space, __u32 mss,
* value can be stuffed directly into th->window for an outgoing
* frame.
*/
-static __inline__ u16 tcp_select_window(struct sock *sk)
+static u16 tcp_select_window(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
u32 cur_win = tcp_receive_window(tp);
@@ -250,6 +250,75 @@ static __inline__ u16 tcp_select_window(struct sock *sk)
return new_win;
}
+static void tcp_build_and_update_options(__u32 *ptr, struct tcp_sock *tp,
+ __u32 tstamp)
+{
+ if (tp->rx_opt.tstamp_ok) {
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) |
+ TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp);
+ *ptr++ = htonl(tp->rx_opt.ts_recent);
+ }
+ if (tp->rx_opt.eff_sacks) {
+ struct tcp_sack_block *sp = tp->rx_opt.dsack ? tp->duplicate_sack : tp->selective_acks;
+ int this_sack;
+
+ *ptr++ = htonl((TCPOPT_NOP << 24) |
+ (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK << 8) |
+ (TCPOLEN_SACK_BASE + (tp->rx_opt.eff_sacks *
+ TCPOLEN_SACK_PERBLOCK)));
+ for(this_sack = 0; this_sack < tp->rx_opt.eff_sacks; this_sack++) {
+ *ptr++ = htonl(sp[this_sack].start_seq);
+ *ptr++ = htonl(sp[this_sack].end_seq);
+ }
+ if (tp->rx_opt.dsack) {
+ tp->rx_opt.dsack = 0;
+ tp->rx_opt.eff_sacks--;
+ }
+ }
+}
+
+/* Construct a tcp options header for a SYN or SYN_ACK packet.
+ * If this is every changed make sure to change the definition of
+ * MAX_SYN_SIZE to match the new maximum number of options that you
+ * can generate.
+ */
+static void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
+ int offer_wscale, int wscale, __u32 tstamp,
+ __u32 ts_recent)
+{
+ /* We always get an MSS option.
+ * The option bytes which will be seen in normal data
+ * packets should timestamps be used, must be in the MSS
+ * advertised. But we subtract them from tp->mss_cache so
+ * that calculations in tcp_sendmsg are simpler etc.
+ * So account for this fact here if necessary. If we
+ * don't do this correctly, as a receiver we won't
+ * recognize data packets as being full sized when we
+ * should, and thus we won't abide by the delayed ACK
+ * rules correctly.
+ * SACKs don't matter, we never delay an ACK when we
+ * have any of those going out.
+ */
+ *ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
+ if (ts) {
+ if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ else
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+ *ptr++ = htonl(tstamp); /* TSVAL */
+ *ptr++ = htonl(ts_recent); /* TSECR */
+ } else if(sack)
+ *ptr++ = __constant_htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
+ (TCPOPT_SACK_PERM << 8) | TCPOLEN_SACK_PERM);
+ if (offer_wscale)
+ *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
+}
/* This routine actually transmits TCP packets queued in by
* tcp_do_sendmsg(). This is used by both the initial
@@ -371,7 +440,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
TCP_ECN_send(sk, tp, skb, tcp_header_size);
}
- tp->af_specific->send_check(sk, th, skb->len, skb);
+ icsk->icsk_af_ops->send_check(sk, skb->len, skb);
if (likely(tcb->flags & TCPCB_FLAG_ACK))
tcp_event_ack_sent(sk, tcp_skb_pcount(skb));
@@ -381,7 +450,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
TCP_INC_STATS(TCP_MIB_OUTSEGS);
- err = tp->af_specific->queue_xmit(skb, 0);
+ err = icsk->icsk_af_ops->queue_xmit(skb, 0);
if (unlikely(err <= 0))
return err;
@@ -621,7 +690,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
It is minimum of user_mss and mss received with SYN.
It also does not include TCP options.
- tp->pmtu_cookie is last pmtu, seen by this function.
+ inet_csk(sk)->icsk_pmtu_cookie is last pmtu, seen by this function.
tp->mss_cache is current effective sending mss, including
all tcp options except for SACKs. It is evaluated,
@@ -631,26 +700,26 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
NOTE1. rfc1122 clearly states that advertised MSS
DOES NOT include either tcp or ip options.
- NOTE2. tp->pmtu_cookie and tp->mss_cache are READ ONLY outside
- this function. --ANK (980731)
+ NOTE2. inet_csk(sk)->icsk_pmtu_cookie and tp->mss_cache
+ are READ ONLY outside this function. --ANK (980731)
*/
unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
{
struct tcp_sock *tp = tcp_sk(sk);
- int mss_now;
-
+ struct inet_connection_sock *icsk = inet_csk(sk);
/* Calculate base mss without TCP options:
It is MMS_S - sizeof(tcphdr) of rfc1122
*/
- mss_now = pmtu - tp->af_specific->net_header_len - sizeof(struct tcphdr);
+ int mss_now = (pmtu - icsk->icsk_af_ops->net_header_len -
+ sizeof(struct tcphdr));
/* Clamp it (mss_clamp does not include tcp options) */
if (mss_now > tp->rx_opt.mss_clamp)
mss_now = tp->rx_opt.mss_clamp;
/* Now subtract optional transport overhead */
- mss_now -= tp->ext_header_len;
+ mss_now -= icsk->icsk_ext_hdr_len;
/* Then reserve room for full set of TCP options and 8 bytes of data */
if (mss_now < 48)
@@ -664,7 +733,7 @@ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
mss_now = max((tp->max_window>>1), 68U - tp->tcp_header_len);
/* And store cached results */
- tp->pmtu_cookie = pmtu;
+ icsk->icsk_pmtu_cookie = pmtu;
tp->mss_cache = mss_now;
return mss_now;
@@ -694,7 +763,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
if (dst) {
u32 mtu = dst_mtu(dst);
- if (mtu != tp->pmtu_cookie)
+ if (mtu != inet_csk(sk)->icsk_pmtu_cookie)
mss_now = tcp_sync_mss(sk, mtu);
}
@@ -705,9 +774,10 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
xmit_size_goal = mss_now;
if (doing_tso) {
- xmit_size_goal = 65535 -
- tp->af_specific->net_header_len -
- tp->ext_header_len - tp->tcp_header_len;
+ xmit_size_goal = (65535 -
+ inet_csk(sk)->icsk_af_ops->net_header_len -
+ inet_csk(sk)->icsk_ext_hdr_len -
+ tp->tcp_header_len);
if (tp->max_window &&
(xmit_size_goal > (tp->max_window >> 1)))
@@ -723,7 +793,7 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
/* Congestion window validation. (RFC2861) */
-static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp)
+static void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp)
{
__u32 packets_out = tp->packets_out;
@@ -772,7 +842,7 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk
/* This must be invoked the first time we consider transmitting
* SKB onto the wire.
*/
-static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now)
+static int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now)
{
int tso_segs = tcp_skb_pcount(skb);
@@ -1422,7 +1492,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
(sysctl_tcp_retrans_collapse != 0))
tcp_retrans_try_collapse(sk, skb, cur_mss);
- if(tp->af_specific->rebuild_header(sk))
+ if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk))
return -EHOSTUNREACH; /* Routing failure or similar. */
/* Some Solaris stacks overoptimize and ignore the FIN on a
@@ -1793,7 +1863,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
/*
* Do all connect socket setups that can be done AF independent.
*/
-static inline void tcp_connect_init(struct sock *sk)
+static void tcp_connect_init(struct sock *sk)
{
struct dst_entry *dst = __sk_dst_get(sk);
struct tcp_sock *tp = tcp_sk(sk);
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 13e7e6e8df16..3b7403495052 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -330,6 +330,10 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack,
vegas->cntRTT = 0;
vegas->minRTT = 0x7fffffff;
}
+ /* Use normal slow start */
+ else if (tp->snd_cwnd <= tp->snd_ssthresh)
+ tcp_slow_start(tp);
+
}
/* Extract info for Tcp socket info provided via netlink. */
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 2422a5f7195d..00840474a449 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -86,6 +86,7 @@
#include <linux/module.h>
#include <linux/socket.h>
#include <linux/sockios.h>
+#include <linux/igmp.h>
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/timer.h>
@@ -846,20 +847,7 @@ out:
csum_copy_err:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
- /* Clear queue. */
- if (flags&MSG_PEEK) {
- int clear = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- if (skb == skb_peek(&sk->sk_receive_queue)) {
- __skb_unlink(skb, &sk->sk_receive_queue);
- clear = 1;
- }
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- if (clear)
- kfree_skb(skb);
- }
-
- skb_free_datagram(sk, skb);
+ skb_kill_datagram(sk, skb, flags);
if (noblock)
return -EAGAIN;
@@ -1001,6 +989,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
kfree_skb(skb);
return -1;
}
+ nf_reset(skb);
if (up->encap_type) {
/*
@@ -1094,7 +1083,7 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
* Otherwise, csum completion requires chacksumming packet body,
* including udp header and folding it to skb->csum.
*/
-static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
+static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
unsigned short ulen, u32 saddr, u32 daddr)
{
if (uh->check == 0) {
@@ -1108,7 +1097,6 @@ static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
/* Probably, we should checksum udp header (it should be in cache
* in any case) and data in tiny packets (< rx copybreak).
*/
- return 0;
}
/*
@@ -1141,8 +1129,7 @@ int udp_rcv(struct sk_buff *skb)
if (pskb_trim_rcsum(skb, ulen))
goto short_packet;
- if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
- goto csum_error;
+ udp_checksum_init(skb, uh, ulen, saddr, daddr);
if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
@@ -1163,6 +1150,7 @@ int udp_rcv(struct sk_buff *skb)
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
goto drop;
+ nf_reset(skb);
/* No socket. Drop packet silently, if checksum is wrong */
if (udp_checksum_complete(skb))
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 2d3849c38a0f..850d919591d1 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -11,6 +11,8 @@
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>
@@ -45,6 +47,23 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
return xfrm_parse_spi(skb, nexthdr, spi, seq);
}
+#ifdef CONFIG_NETFILTER
+static inline int xfrm4_rcv_encap_finish(struct sk_buff *skb)
+{
+ struct iphdr *iph = skb->nh.iph;
+
+ if (skb->dst == NULL) {
+ if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
+ skb->dev))
+ goto drop;
+ }
+ return dst_input(skb);
+drop:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+#endif
+
int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{
int err;
@@ -137,6 +156,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
skb->sp->len += xfrm_nr;
+ nf_reset(skb);
+
if (decaps) {
if (!(skb->dev->flags&IFF_LOOPBACK)) {
dst_release(skb->dst);
@@ -145,7 +166,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
netif_rx(skb);
return 0;
} else {
+#ifdef CONFIG_NETFILTER
+ __skb_push(skb, skb->data - skb->nh.raw);
+ skb->nh.iph->tot_len = htons(skb->len);
+ ip_send_check(skb->nh.iph);
+
+ NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
+ xfrm4_rcv_encap_finish);
+ return 0;
+#else
return -skb->nh.iph->protocol;
+#endif
}
drop_unlock:
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 66620a95942a..d4df0ddd424b 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -8,8 +8,10 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/compiler.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
+#include <linux/netfilter_ipv4.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
#include <net/xfrm.h>
@@ -95,7 +97,7 @@ out:
return ret;
}
-int xfrm4_output(struct sk_buff *skb)
+static int xfrm4_output_one(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
@@ -113,27 +115,33 @@ int xfrm4_output(struct sk_buff *skb)
goto error_nolock;
}
- spin_lock_bh(&x->lock);
- err = xfrm_state_check(x, skb);
- if (err)
- goto error;
+ do {
+ spin_lock_bh(&x->lock);
+ err = xfrm_state_check(x, skb);
+ if (err)
+ goto error;
- xfrm4_encap(skb);
+ xfrm4_encap(skb);
- err = x->type->output(x, skb);
- if (err)
- goto error;
+ err = x->type->output(x, skb);
+ if (err)
+ goto error;
- x->curlft.bytes += skb->len;
- x->curlft.packets++;
+ x->curlft.bytes += skb->len;
+ x->curlft.packets++;
- spin_unlock_bh(&x->lock);
+ spin_unlock_bh(&x->lock);
- if (!(skb->dst = dst_pop(dst))) {
- err = -EHOSTUNREACH;
- goto error_nolock;
- }
- err = NET_XMIT_BYPASS;
+ if (!(skb->dst = dst_pop(dst))) {
+ err = -EHOSTUNREACH;
+ goto error_nolock;
+ }
+ dst = skb->dst;
+ x = dst->xfrm;
+ } while (x && !x->props.mode);
+
+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
+ err = 0;
out_exit:
return err;
@@ -143,3 +151,33 @@ error_nolock:
kfree_skb(skb);
goto out_exit;
}
+
+int xfrm4_output_finish(struct sk_buff *skb)
+{
+ int err;
+
+ while (likely((err = xfrm4_output_one(skb)) == 0)) {
+ nf_reset(skb);
+
+ err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
+ skb->dst->dev, dst_output);
+ if (unlikely(err != 1))
+ break;
+
+ if (!skb->dst->xfrm)
+ return dst_output(skb);
+
+ err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
+ skb->dst->dev, xfrm4_output_finish);
+ if (unlikely(err != 1))
+ break;
+ }
+
+ return err;
+}
+
+int xfrm4_output(struct sk_buff *skb)
+{
+ return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
+ xfrm4_output_finish);
+}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index d23e07fc81fa..dbabf81a9b7b 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
x->props.saddr = tmpl->saddr;
if (x->props.saddr.a4 == 0)
x->props.saddr.a4 = saddr->a4;
+ if (tmpl->mode && x->props.saddr.a4 == 0) {
+ struct rtable *rt;
+ struct flowi fl_tunnel = {
+ .nl_u = {
+ .ip4_u = {
+ .daddr = x->id.daddr.a4,
+ }
+ }
+ };
+ if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
+ &fl_tunnel, AF_INET)) {
+ x->props.saddr.a4 = rt->rt_src;
+ dst_release(&rt->u.dst);
+ }
+ }
x->props.mode = tmpl->mode;
x->props.reqid = tmpl->reqid;
x->props.family = AF_INET;
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 6460eec834b7..41877abd22e6 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -8,10 +8,11 @@ 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 netfilter.o
+ ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o
ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
xfrm6_output.o
+ipv6-$(CONFIG_NETFILTER) += netfilter.o
ipv6-objs += $(ipv6-y)
obj-$(CONFIG_INET6_AH) += ah6.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a60585fd85ad..d328d5986143 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -58,6 +58,7 @@
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/string.h>
@@ -1195,7 +1196,7 @@ struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *
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);
+ const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2);
u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr;
u32 sk2_rcv_saddr = inet_rcv_saddr(sk2);
int sk_ipv6only = ipv6_only_sock(sk);
@@ -1228,7 +1229,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
/* Gets referenced address, destroys ifaddr */
-void addrconf_dad_stop(struct inet6_ifaddr *ifp)
+static void addrconf_dad_stop(struct inet6_ifaddr *ifp)
{
if (ifp->flags&IFA_F_PERMANENT) {
spin_lock_bh(&ifp->lock);
@@ -2643,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v)
{
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
seq_printf(seq,
- "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n",
+ NIP6_SEQFMT " %02x %02x %02x %02x %8s\n",
NIP6(ifp->addr),
ifp->idev->dev->ifindex,
ifp->prefix_len,
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index d9546380fa04..064ffab82a9f 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -167,6 +168,7 @@ lookup_protocol:
sk->sk_reuse = 1;
inet = inet_sk(sk);
+ inet->is_icsk = INET_PROTOSW_ICSK & answer_flags;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
@@ -389,6 +391,8 @@ int inet6_destroy_sock(struct sock *sk)
return 0;
}
+EXPORT_SYMBOL_GPL(inet6_destroy_sock);
+
/*
* This does both peername and sockname.
*/
@@ -431,7 +435,6 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- int err = -EINVAL;
switch(cmd)
{
@@ -450,16 +453,15 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFDSTADDR:
return addrconf_set_dstaddr((void __user *) arg);
default:
- if (!sk->sk_prot->ioctl ||
- (err = sk->sk_prot->ioctl(sk, cmd, arg)) == -ENOIOCTLCMD)
- return(dev_ioctl(cmd,(void __user *) arg));
- return err;
+ if (!sk->sk_prot->ioctl)
+ return -ENOIOCTLCMD;
+ return sk->sk_prot->ioctl(sk, cmd, arg);
}
/*NOTREACHED*/
return(0);
}
-struct proto_ops inet6_stream_ops = {
+const struct proto_ops inet6_stream_ops = {
.family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release,
@@ -480,7 +482,7 @@ struct proto_ops inet6_stream_ops = {
.sendpage = tcp_sendpage
};
-struct proto_ops inet6_dgram_ops = {
+const struct proto_ops inet6_dgram_ops = {
.family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release,
@@ -508,7 +510,7 @@ static struct net_proto_family inet6_family_ops = {
};
/* Same as inet6_dgram_ops, sans udp_poll. */
-static struct proto_ops inet6_sockraw_ops = {
+static const struct proto_ops inet6_sockraw_ops = {
.family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release,
@@ -609,17 +611,90 @@ inet6_unregister_protosw(struct inet_protosw *p)
}
}
+int inet6_sk_rebuild_header(struct sock *sk)
+{
+ int err;
+ struct dst_entry *dst;
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ dst = __sk_dst_check(sk, np->dst_cookie);
+
+ if (dst == NULL) {
+ struct inet_sock *inet = inet_sk(sk);
+ struct in6_addr *final_p = NULL, final;
+ struct flowi fl;
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = sk->sk_protocol;
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+ ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ fl.fl6_flowlabel = np->flow_label;
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_dport = inet->dport;
+ fl.fl_ip_sport = inet->sport;
+
+ if (np->opt && np->opt->srcrt) {
+ struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+
+ err = ip6_dst_lookup(sk, &dst, &fl);
+ if (err) {
+ sk->sk_route_caps = 0;
+ return err;
+ }
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_err_soft = -err;
+ return err;
+ }
+
+ ip6_dst_store(sk, dst, NULL);
+ sk->sk_route_caps = dst->dev->features &
+ ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(inet6_sk_rebuild_header);
+
+int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct inet6_skb_parm *opt = IP6CB(skb);
+
+ if (np->rxopt.all) {
+ 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;
+}
+
+EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
+
int
snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign)
{
if (ptr == NULL)
return -EINVAL;
- ptr[0] = __alloc_percpu(mibsize, mibalign);
+ ptr[0] = __alloc_percpu(mibsize);
if (!ptr[0])
goto err0;
- ptr[1] = __alloc_percpu(mibsize, mibalign);
+ ptr[1] = __alloc_percpu(mibsize);
if (!ptr[1])
goto err1;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index f3629730eb15..c7932cb420a5 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -33,6 +33,7 @@
#include <linux/string.h>
#include <net/icmp.h>
#include <net/ipv6.h>
+#include <net/protocol.h>
#include <net/xfrm.h>
#include <asm/scatterlist.h>
@@ -331,8 +332,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (!x)
return;
- NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/"
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n",
ntohl(ah->spi), NIP6(iph->daddr));
xfrm_state_put(x);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 6b7294047238..840a33d33296 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
@@ -531,9 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v)
struct ac6_iter_state *state = ac6_seq_private(seq);
seq_printf(seq,
- "%-4d %-15s "
- "%04x%04x%04x%04x%04x%04x%04x%04x "
- "%5d\n",
+ "%-4d %-15s " NIP6_SEQFMT " %5d\n",
state->dev->ifindex, state->dev->name,
NIP6(im->aca_addr),
im->aca_users);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index c4a3a993acb7..99a6eb23378b 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kernel.h>
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 8bfbe9970793..7b5b94f13902 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -36,6 +36,7 @@
#include <linux/random.h>
#include <net/icmp.h>
#include <net/ipv6.h>
+#include <net/protocol.h>
#include <linux/icmpv6.h>
static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
@@ -265,8 +266,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
if (!x)
return;
- printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/"
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n",
ntohl(esph->spi), NIP6(iph->daddr));
xfrm_state_put(x);
}
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index be6faf311387..2a1e7e45b890 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -152,7 +152,7 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
{-1, NULL}
};
-static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_destopt_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
@@ -169,7 +169,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
skb->h.raw += ((skb->h.raw[1]+1)<<3);
- *nhoffp = opt->dst1;
+ opt->nhoff = opt->dst1;
return 1;
}
@@ -192,7 +192,7 @@ void __init ipv6_destopt_init(void)
NONE header. No data in packet.
********************************/
-static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_nodata_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void)
Routing header.
********************************/
-static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_rthdr_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
@@ -249,7 +249,7 @@ looped_back:
skb->h.raw += (hdr->hdrlen + 1) << 3;
opt->dst0 = opt->dst1;
opt->dst1 = 0;
- *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
+ opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
return 1;
}
@@ -413,6 +413,8 @@ ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
return opt;
}
+EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
+
/**********************************
Hop-by-hop options.
**********************************/
@@ -485,9 +487,14 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
{
- IP6CB(skb)->hop = sizeof(struct ipv6hdr);
- if (ip6_parse_tlv(tlvprochopopt_lst, skb))
+ struct inet6_skb_parm *opt = IP6CB(skb);
+
+ opt->hop = sizeof(struct ipv6hdr);
+ if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
+ skb->h.raw += (skb->h.raw[1]+1)<<3;
+ opt->nhoff = sizeof(struct ipv6hdr);
return sizeof(struct ipv6hdr);
+ }
return -1;
}
@@ -579,6 +586,8 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
return opt2;
}
+EXPORT_SYMBOL_GPL(ipv6_dup_options);
+
static int ipv6_renew_option(void *ohdr,
struct ipv6_opt_hdr __user *newopt, int newoptlen,
int inherit,
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 6ec6a2b549bb..fcf883183cef 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -79,7 +79,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly;
static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
#define icmpv6_socket __get_cpu_var(__icmpv6_socket)
-static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
+static int icmpv6_rcv(struct sk_buff **pskb);
static struct inet6_protocol icmpv6_protocol = {
.handler = icmpv6_rcv,
@@ -581,7 +581,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
* Handle icmp messages
*/
-static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int icmpv6_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev;
@@ -607,7 +607,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len,
IPPROTO_ICMPV6, 0);
if (__skb_checksum_complete(skb)) {
- LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n",
+ LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n",
NIP6(*saddr), NIP6(*daddr));
goto discard_it;
}
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
new file mode 100644
index 000000000000..f8f3a37a1494
--- /dev/null
+++ b/net/ipv6/inet6_connection_sock.c
@@ -0,0 +1,200 @@
+/*
+ * 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 INET6 connection oriented protocols.
+ *
+ * Authors: See the TCPv6 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/in6.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+
+#include <net/addrconf.h>
+#include <net/inet_connection_sock.h>
+#include <net/inet_ecn.h>
+#include <net/inet_hashtables.h>
+#include <net/ip6_route.h>
+#include <net/sock.h>
+#include <net/inet6_connection_sock.h>
+
+int inet6_csk_bind_conflict(const struct sock *sk,
+ const struct inet_bind_bucket *tb)
+{
+ 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) {
+ if (sk != sk2 &&
+ (!sk->sk_bound_dev_if ||
+ !sk2->sk_bound_dev_if ||
+ sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
+ (!sk->sk_reuse || !sk2->sk_reuse ||
+ sk2->sk_state == TCP_LISTEN) &&
+ ipv6_rcv_saddr_equal(sk, sk2))
+ break;
+ }
+
+ return node != NULL;
+}
+
+EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict);
+
+/*
+ * request_sock (formerly open request) hash tables.
+ */
+static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport,
+ const u32 rnd, const u16 synq_hsize)
+{
+ u32 a = raddr->s6_addr32[0];
+ u32 b = raddr->s6_addr32[1];
+ u32 c = raddr->s6_addr32[2];
+
+ a += JHASH_GOLDEN_RATIO;
+ b += JHASH_GOLDEN_RATIO;
+ c += rnd;
+ __jhash_mix(a, b, c);
+
+ a += raddr->s6_addr32[3];
+ b += (u32)rport;
+ __jhash_mix(a, b, c);
+
+ return c & (synq_hsize - 1);
+}
+
+struct request_sock *inet6_csk_search_req(const struct sock *sk,
+ struct request_sock ***prevp,
+ const __u16 rport,
+ const struct in6_addr *raddr,
+ const struct in6_addr *laddr,
+ const int iif)
+{
+ 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[inet6_synq_hash(raddr, rport,
+ lopt->hash_rnd,
+ lopt->nr_table_entries)];
+ (req = *prev) != NULL;
+ prev = &req->dl_next) {
+ const struct inet6_request_sock *treq = inet6_rsk(req);
+
+ if (inet_rsk(req)->rmt_port == rport &&
+ req->rsk_ops->family == AF_INET6 &&
+ ipv6_addr_equal(&treq->rmt_addr, raddr) &&
+ ipv6_addr_equal(&treq->loc_addr, laddr) &&
+ (!treq->iif || treq->iif == iif)) {
+ BUG_TRAP(req->sk == NULL);
+ *prevp = prev;
+ return req;
+ }
+ }
+
+ return NULL;
+}
+
+EXPORT_SYMBOL_GPL(inet6_csk_search_req);
+
+void inet6_csk_reqsk_queue_hash_add(struct sock *sk,
+ struct request_sock *req,
+ const unsigned long timeout)
+{
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
+ const u32 h = inet6_synq_hash(&inet6_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);
+}
+
+EXPORT_SYMBOL_GPL(inet6_csk_reqsk_queue_hash_add);
+
+void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr;
+
+ sin6->sin6_family = AF_INET6;
+ ipv6_addr_copy(&sin6->sin6_addr, &np->daddr);
+ sin6->sin6_port = inet_sk(sk)->dport;
+ /* We do not store received flowlabel for TCP */
+ sin6->sin6_flowinfo = 0;
+ sin6->sin6_scope_id = 0;
+ if (sk->sk_bound_dev_if &&
+ ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
+ sin6->sin6_scope_id = sk->sk_bound_dev_if;
+}
+
+EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr);
+
+int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
+{
+ struct sock *sk = skb->sk;
+ struct inet_sock *inet = inet_sk(sk);
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct flowi fl;
+ struct dst_entry *dst;
+ struct in6_addr *final_p = NULL, final;
+
+ memset(&fl, 0, sizeof(fl));
+ fl.proto = sk->sk_protocol;
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+ ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+ fl.fl6_flowlabel = np->flow_label;
+ IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
+ fl.oif = sk->sk_bound_dev_if;
+ fl.fl_ip_sport = inet->sport;
+ fl.fl_ip_dport = inet->dport;
+
+ if (np->opt && np->opt->srcrt) {
+ struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
+ ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
+ }
+
+ dst = __sk_dst_check(sk, np->dst_cookie);
+
+ if (dst == NULL) {
+ int err = ip6_dst_lookup(sk, &dst, &fl);
+
+ if (err) {
+ sk->sk_err_soft = -err;
+ return err;
+ }
+
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+ if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+ sk->sk_route_caps = 0;
+ return err;
+ }
+
+ ip6_dst_store(sk, dst, NULL);
+ sk->sk_route_caps = dst->dev->features &
+ ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
+ }
+
+ skb->dst = dst_clone(dst);
+
+ /* Restore final destination back after routing done */
+ ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+
+ return ip6_xmit(sk, skb, &fl, np->opt, 0);
+}
+
+EXPORT_SYMBOL_GPL(inet6_csk_xmit);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 01d5f46d4e40..4154f3a8b6cf 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -5,7 +5,8 @@
*
* Generic INET6 transport hashtables
*
- * Authors: Lotsa people, from code originally in tcp
+ * Authors: Lotsa people, from code originally in tcp, generalised here
+ * by 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
@@ -14,12 +15,13 @@
*/
#include <linux/config.h>
-
#include <linux/module.h>
+#include <linux/random.h>
#include <net/inet_connection_sock.h>
#include <net/inet_hashtables.h>
#include <net/inet6_hashtables.h>
+#include <net/ip.h>
struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo,
const struct in6_addr *daddr,
@@ -79,3 +81,180 @@ struct sock *inet6_lookup(struct inet_hashinfo *hashinfo,
}
EXPORT_SYMBOL_GPL(inet6_lookup);
+
+static int __inet6_check_established(struct inet_timewait_death_row *death_row,
+ struct sock *sk, const __u16 lport,
+ struct inet_timewait_sock **twp)
+{
+ struct inet_hashinfo *hinfo = death_row->hashinfo;
+ const struct inet_sock *inet = inet_sk(sk);
+ 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 unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
+ inet->dport);
+ struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
+ struct sock *sk2;
+ const struct hlist_node *node;
+ struct inet_timewait_sock *tw;
+
+ prefetch(head->chain.first);
+ write_lock(&head->lock);
+
+ /* Check TIME-WAIT sockets first. */
+ sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+ const struct inet6_timewait_sock *tw6 = inet6_twsk(sk2);
+
+ tw = inet_twsk(sk2);
+
+ if(*((__u32 *)&(tw->tw_dport)) == ports &&
+ sk2->sk_family == PF_INET6 &&
+ ipv6_addr_equal(&tw6->tw_v6_daddr, saddr) &&
+ ipv6_addr_equal(&tw6->tw_v6_rcv_saddr, daddr) &&
+ sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
+ if (twsk_unique(sk, sk2, twp))
+ goto unique;
+ else
+ goto not_unique;
+ }
+ }
+ tw = NULL;
+
+ /* And established part... */
+ sk_for_each(sk2, node, &head->chain) {
+ if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif))
+ goto not_unique;
+ }
+
+unique:
+ BUG_TRAP(sk_unhashed(sk));
+ __sk_add_node(sk, &head->chain);
+ sk->sk_hash = hash;
+ 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, death_row);
+ NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+
+ inet_twsk_put(tw);
+ }
+ return 0;
+
+not_unique:
+ write_unlock(&head->lock);
+ return -EADDRNOTAVAIL;
+}
+
+static inline u32 inet6_sk_port_offset(const struct sock *sk)
+{
+ const struct inet_sock *inet = inet_sk(sk);
+ const struct ipv6_pinfo *np = inet6_sk(sk);
+ return secure_ipv6_port_ephemeral(np->rcv_saddr.s6_addr32,
+ np->daddr.s6_addr32,
+ inet->dport);
+}
+
+int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+ struct sock *sk)
+{
+ struct inet_hashinfo *hinfo = death_row->hashinfo;
+ const unsigned short snum = inet_sk(sk)->num;
+ struct inet_bind_hashbucket *head;
+ struct inet_bind_bucket *tb;
+ int ret;
+
+ if (snum == 0) {
+ const int low = sysctl_local_port_range[0];
+ const int high = sysctl_local_port_range[1];
+ const int range = high - low;
+ int i, port;
+ static u32 hint;
+ const u32 offset = hint + inet6_sk_port_offset(sk);
+ struct hlist_node *node;
+ struct inet_timewait_sock *tw = NULL;
+
+ local_bh_disable();
+ for (i = 1; i <= range; i++) {
+ port = low + (i + offset) % range;
+ head = &hinfo->bhash[inet_bhashfn(port, hinfo->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 == port) {
+ BUG_TRAP(!hlist_empty(&tb->owners));
+ if (tb->fastreuse >= 0)
+ goto next_port;
+ if (!__inet6_check_established(death_row,
+ sk, port,
+ &tw))
+ goto ok;
+ goto next_port;
+ }
+ }
+
+ tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
+ head, port);
+ if (!tb) {
+ spin_unlock(&head->lock);
+ break;
+ }
+ tb->fastreuse = -1;
+ goto ok;
+
+ next_port:
+ spin_unlock(&head->lock);
+ }
+ local_bh_enable();
+
+ return -EADDRNOTAVAIL;
+
+ok:
+ hint += i;
+
+ /* Head lock still held and bh's disabled */
+ inet_bind_hash(sk, tb, port);
+ if (sk_unhashed(sk)) {
+ inet_sk(sk)->sport = htons(port);
+ __inet6_hash(hinfo, sk);
+ }
+ spin_unlock(&head->lock);
+
+ if (tw) {
+ inet_twsk_deschedule(tw, death_row);
+ inet_twsk_put(tw);
+ }
+
+ ret = 0;
+ goto out;
+ }
+
+ head = &hinfo->bhash[inet_bhashfn(snum, hinfo->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) {
+ __inet6_hash(hinfo, sk);
+ spin_unlock_bh(&head->lock);
+ return 0;
+ } else {
+ spin_unlock(&head->lock);
+ /* No definite answer... Walk to established hash table */
+ ret = __inet6_check_established(death_row, sk, snum, NULL);
+out:
+ local_bh_enable();
+ return ret;
+ }
+}
+
+EXPORT_SYMBOL_GPL(inet6_hash_connect);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1cf02765fb5c..69cbe8a66d02 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -9,6 +9,7 @@
* Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -200,6 +201,8 @@ struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label)
return NULL;
}
+EXPORT_SYMBOL_GPL(fl6_sock_lookup);
+
void fl6_free_socklist(struct sock *sk)
{
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -626,9 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
{
while(fl) {
seq_printf(seq,
- "%05X %-1d %-6d %-6d %-6ld %-8ld "
- "%02x%02x%02x%02x%02x%02x%02x%02x "
- "%-4d\n",
+ "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
(unsigned)ntohl(fl->label),
fl->share,
(unsigned)fl->owner,
@@ -644,8 +645,8 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
static int ip6fl_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
- seq_puts(seq, "Label S Owner Users Linger Expires "
- "Dst Opt\n");
+ seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
+ "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
else
ip6fl_fl_seq_show(seq, v);
return 0;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index a6026d2787d2..29f73592e68e 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -48,7 +48,7 @@
-static inline int ip6_rcv_finish( struct sk_buff *skb)
+inline int ip6_rcv_finish( struct sk_buff *skb)
{
if (skb->dst == NULL)
ip6_route_input(skb);
@@ -97,6 +97,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
if (hdr->version != 6)
goto err;
+ skb->h.raw = (u8 *)(hdr + 1);
+ IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
+
pkt_len = ntohs(hdr->payload_len);
/* pkt_len may be zero if Jumbo payload option is present */
@@ -111,8 +114,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
}
if (hdr->nexthdr == NEXTHDR_HOP) {
- skb->h.raw = (u8*)(hdr+1);
- if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) {
+ if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
return 0;
}
@@ -143,26 +145,15 @@ static inline int ip6_input_finish(struct sk_buff *skb)
int nexthdr;
u8 hash;
- skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
-
/*
* Parse extension headers
*/
- nexthdr = skb->nh.ipv6h->nexthdr;
- nhoff = offsetof(struct ipv6hdr, nexthdr);
-
- /* Skip hop-by-hop options, they are already parsed. */
- if (nexthdr == NEXTHDR_HOP) {
- nhoff = sizeof(struct ipv6hdr);
- nexthdr = skb->h.raw[0];
- skb->h.raw += (skb->h.raw[1]+1)<<3;
- }
-
rcu_read_lock();
resubmit:
if (!pskb_pull(skb, skb->h.raw - skb->data))
goto discard;
+ nhoff = IP6CB(skb)->nhoff;
nexthdr = skb->nh.raw[nhoff];
raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
@@ -194,7 +185,7 @@ resubmit:
!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
goto discard;
- ret = ipprot->handler(&skb, &nhoff);
+ ret = ipprot->handler(&skb);
if (ret > 0)
goto resubmit;
else if (ret == 0)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 8523c76ebf76..efa3e72cfcfa 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -226,6 +226,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, first_hop);
+ skb->priority = sk->sk_priority;
+
mtu = dst_mtu(dst);
if ((skb->len <= mtu) || ipfragok) {
IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
@@ -775,6 +777,8 @@ out_err_release:
return err;
}
+EXPORT_SYMBOL_GPL(ip6_dst_lookup);
+
static inline int ip6_ufo_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
@@ -1180,6 +1184,8 @@ int ip6_push_pending_frames(struct sock *sk)
ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
ipv6_addr_copy(&hdr->daddr, final_dst);
+ skb->priority = sk->sk_priority;
+
skb->dst = dst_clone(&rt->u.dst);
IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e315d0f80af1..92ead3cf956b 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -21,6 +21,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/sockios.h>
@@ -243,7 +244,7 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt)
if (dev == NULL)
return -ENOMEM;
- t = dev->priv;
+ t = netdev_priv(dev);
dev->init = ip6ip6_tnl_dev_init;
t->parms = *p;
@@ -308,7 +309,7 @@ ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create)
static void
ip6ip6_tnl_dev_uninit(struct net_device *dev)
{
- struct ip6_tnl *t = dev->priv;
+ struct ip6_tnl *t = netdev_priv(dev);
if (dev == ip6ip6_fb_tnl_dev) {
write_lock_bh(&ip6ip6_lock);
@@ -510,7 +511,7 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
**/
static int
-ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+ip6ip6_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct ipv6hdr *ipv6h;
@@ -623,7 +624,7 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr)
static int
ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
+ struct ip6_tnl *t = netdev_priv(dev);
struct net_device_stats *stats = &t->stat;
struct ipv6hdr *ipv6h = skb->nh.ipv6h;
struct ipv6_txoptions *opt = NULL;
@@ -933,11 +934,11 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
}
if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV)
- t = (struct ip6_tnl *) dev->priv;
+ t = netdev_priv(dev);
else if (err)
break;
} else
- t = (struct ip6_tnl *) dev->priv;
+ t = netdev_priv(dev);
memcpy(&p, &t->parms, sizeof (p));
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) {
@@ -955,7 +956,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
break;
}
if (!create && dev != ip6ip6_fb_tnl_dev) {
- t = (struct ip6_tnl *) dev->priv;
+ t = netdev_priv(dev);
}
if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) {
break;
@@ -991,12 +992,12 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
err = ip6ip6_tnl_locate(&p, &t, 0);
if (err)
break;
- if (t == ip6ip6_fb_tnl_dev->priv) {
+ if (t == netdev_priv(ip6ip6_fb_tnl_dev)) {
err = -EPERM;
break;
}
} else {
- t = (struct ip6_tnl *) dev->priv;
+ t = netdev_priv(dev);
}
err = unregister_netdevice(t->dev);
break;
@@ -1016,7 +1017,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static struct net_device_stats *
ip6ip6_tnl_get_stats(struct net_device *dev)
{
- return &(((struct ip6_tnl *) dev->priv)->stat);
+ return &(((struct ip6_tnl *)netdev_priv(dev))->stat);
}
/**
@@ -1073,7 +1074,7 @@ static void ip6ip6_tnl_dev_setup(struct net_device *dev)
static inline void
ip6ip6_tnl_dev_init_gen(struct net_device *dev)
{
- struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
+ struct ip6_tnl *t = netdev_priv(dev);
t->fl.proto = IPPROTO_IPV6;
t->dev = dev;
strcpy(t->parms.name, dev->name);
@@ -1087,7 +1088,7 @@ ip6ip6_tnl_dev_init_gen(struct net_device *dev)
static int
ip6ip6_tnl_dev_init(struct net_device *dev)
{
- struct ip6_tnl *t = (struct ip6_tnl *) dev->priv;
+ struct ip6_tnl *t = netdev_priv(dev);
ip6ip6_tnl_dev_init_gen(dev);
ip6ip6_tnl_link_config(t);
return 0;
@@ -1103,7 +1104,7 @@ ip6ip6_tnl_dev_init(struct net_device *dev)
static int
ip6ip6_fb_tnl_dev_init(struct net_device *dev)
{
- struct ip6_tnl *t = dev->priv;
+ struct ip6_tnl *t = netdev_priv(dev);
ip6ip6_tnl_dev_init_gen(dev);
dev_hold(dev);
tnls_wc[0] = t;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 55917fb17094..d511a884dad0 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -47,6 +47,7 @@
#include <linux/rtnetlink.h>
#include <net/icmp.h>
#include <net/ipv6.h>
+#include <net/protocol.h>
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
@@ -211,8 +212,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (!x)
return;
- printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/"
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n",
spi, NIP6(iph->daddr));
xfrm_state_put(x);
}
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 3620718defe6..f7142ba519ab 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -26,6 +26,7 @@
*/
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
@@ -163,17 +164,17 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
sk_refcnt_debug_dec(sk);
if (sk->sk_protocol == IPPROTO_TCP) {
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
local_bh_disable();
sock_prot_dec_use(sk->sk_prot);
sock_prot_inc_use(&tcp_prot);
local_bh_enable();
sk->sk_prot = &tcp_prot;
- tp->af_specific = &ipv4_specific;
+ icsk->icsk_af_ops = &ipv4_specific;
sk->sk_socket->ops = &inet_stream_ops;
sk->sk_family = PF_INET;
- tcp_sync_mss(sk, tp->pmtu_cookie);
+ tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
} else {
local_bh_disable();
sock_prot_dec_use(sk->sk_prot);
@@ -317,14 +318,15 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
}
retv = 0;
- if (sk->sk_type == SOCK_STREAM) {
+ if (inet_sk(sk)->is_icsk) {
if (opt) {
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(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);
+ icsk->icsk_ext_hdr_len =
+ opt->opt_flen + opt->opt_nflen;
+ icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
}
}
opt = xchg(&np->opt, opt);
@@ -380,14 +382,15 @@ sticky_done:
goto done;
update:
retv = 0;
- if (sk->sk_type == SOCK_STREAM) {
+ if (inet_sk(sk)->is_icsk) {
if (opt) {
- struct tcp_sock *tp = tcp_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(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);
+ icsk->icsk_ext_hdr_len =
+ opt->opt_flen + opt->opt_nflen;
+ icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie);
}
}
opt = xchg(&np->opt, opt);
@@ -547,7 +550,7 @@ done:
retv = -ENOBUFS;
break;
}
- gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
+ gsf = kmalloc(optlen,GFP_KERNEL);
if (gsf == 0) {
retv = -ENOBUFS;
break;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index f829a4ad3ccc..6c05c7978bef 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -224,7 +224,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
mc_lst->ifindex = dev->ifindex;
mc_lst->sfmode = MCAST_EXCLUDE;
- mc_lst->sflock = RW_LOCK_UNLOCKED;
+ rwlock_init(&mc_lst->sflock);
mc_lst->sflist = NULL;
/*
@@ -449,8 +449,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
if (psl)
count += psl->sl_max;
- newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
- IP6_SFLSIZE(count), GFP_ATOMIC);
+ newpsl = sock_kmalloc(sk, IP6_SFLSIZE(count), GFP_ATOMIC);
if (!newpsl) {
err = -ENOBUFS;
goto done;
@@ -535,8 +534,8 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
goto done;
}
if (gsf->gf_numsrc) {
- newpsl = (struct ip6_sf_socklist *)sock_kmalloc(sk,
- IP6_SFLSIZE(gsf->gf_numsrc), GFP_ATOMIC);
+ newpsl = sock_kmalloc(sk, IP6_SFLSIZE(gsf->gf_numsrc),
+ GFP_ATOMIC);
if (!newpsl) {
err = -ENOBUFS;
goto done;
@@ -768,7 +767,7 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
* for deleted items allows change reports to use common code with
* non-deleted or query-response MCA's.
*/
- pmc = (struct ifmcaddr6 *)kmalloc(sizeof(*pmc), GFP_ATOMIC);
+ pmc = kmalloc(sizeof(*pmc), GFP_ATOMIC);
if (!pmc)
return;
memset(pmc, 0, sizeof(*pmc));
@@ -1937,7 +1936,7 @@ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
psf_prev = psf;
}
if (!psf) {
- psf = (struct ip6_sf_list *)kmalloc(sizeof(*psf), GFP_ATOMIC);
+ psf = kmalloc(sizeof(*psf), GFP_ATOMIC);
if (!psf)
return -ENOBUFS;
memset(psf, 0, sizeof(*psf));
@@ -2374,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq);
seq_printf(seq,
- "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n",
+ "%-4d %-15s " NIP6_SEQFMT " %5d %08X %ld\n",
state->dev->ifindex, state->dev->name,
NIP6(im->mca_addr),
im->mca_users, im->mca_flags,
@@ -2548,10 +2547,7 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
"Source Address", "INC", "EXC");
} else {
seq_printf(seq,
- "%3d %6.6s "
- "%04x%04x%04x%04x%04x%04x%04x%04x "
- "%04x%04x%04x%04x%04x%04x%04x%04x "
- "%6lu %6lu\n",
+ "%3d %6.6s " NIP6_SEQFMT " " NIP6_SEQFMT " %6lu %6lu\n",
state->dev->ifindex, state->dev->name,
NIP6(state->im->mca_addr),
NIP6(psf->sf_addr),
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 305d9ee6d7db..cb8856b1d951 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -692,7 +692,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
if (!(neigh->nud_state & NUD_VALID)) {
ND_PRINTK1(KERN_DEBUG
"%s(): trying to ucast probe in NUD_INVALID: "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ NIP6_FMT "\n",
__FUNCTION__,
NIP6(*target));
}
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index f8626ebf90fd..d750cfc019dc 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -1,15 +1,12 @@
-#include <linux/config.h>
-#include <linux/init.h>
-
-#ifdef CONFIG_NETFILTER
-
#include <linux/kernel.h>
+#include <linux/init.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>
+#include <net/xfrm.h>
int ip6_route_me_harder(struct sk_buff *skb)
{
@@ -21,11 +18,17 @@ int ip6_route_me_harder(struct sk_buff *skb)
{ .ip6_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr, } },
- .proto = iph->nexthdr,
};
dst = ip6_route_output(skb->sk, &fl);
+#ifdef CONFIG_XFRM
+ if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+ xfrm_decode_session(skb, &fl, AF_INET6) == 0)
+ if (xfrm_lookup(&skb->dst, &fl, skb->sk, 0))
+ return -1;
+#endif
+
if (dst->error) {
IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
@@ -87,18 +90,10 @@ int __init ipv6_netfilter_init(void)
return nf_register_queue_rerouter(PF_INET6, &ip6_reroute);
}
+/* This can be called from inet6_init() on errors, so it cannot
+ * be marked __exit. -DaveM
+ */
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 04912f9b35c3..2d6f8ecbc27b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE
config IP6_NF_IPTABLES
tristate "IP6 tables support (required for filtering/masq/NAT)"
+ depends on NETFILTER_XTABLES
help
ip6tables is a general, extensible packet identification framework.
Currently only the packet filtering and packet mangling subsystem
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES
To compile it as a module, choose M here. If unsure, say N.
# The simple matches.
-config IP6_NF_MATCH_LIMIT
- tristate "limit match support"
- depends on IP6_NF_IPTABLES
- help
- limit matching allows you to control the rate at which a rule can be
- matched: mainly useful in combination with the LOG target ("LOG
- target support", below) and to avoid some Denial of Service attacks.
-
- To compile it as a module, choose M here. If unsure, say N.
-
-config IP6_NF_MATCH_MAC
- tristate "MAC address match support"
- depends on IP6_NF_IPTABLES
- help
- mac matching allows you to match packets based on the source
- Ethernet address of the packet.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MATCH_RT
tristate "Routing header match support"
depends on IP6_NF_IPTABLES
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_MARK
- tristate "netfilter MARK match support"
- depends on IP6_NF_IPTABLES
- help
- Netfilter mark matching allows you to match packets based on the
- `nfmark' value in the packet. This can be set by the MARK target
- (see below).
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MATCH_IPV6HEADER
tristate "IPv6 Extension Headers Match"
depends on IP6_NF_IPTABLES
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_LENGTH
- tristate "Packet Length match support"
- depends on IP6_NF_IPTABLES
- help
- This option allows you to match the length of a packet against a
- specific value or range of values.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MATCH_EUI64
tristate "EUI64 address check"
depends on IP6_NF_IPTABLES
@@ -170,12 +133,13 @@ config IP6_NF_MATCH_EUI64
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_MATCH_PHYSDEV
- tristate "Physdev match support"
- depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
+config IP6_NF_MATCH_POLICY
+ tristate "IPsec policy match support"
+ depends on IP6_NF_IPTABLES && XFRM
help
- Physdev packet matching matches against the physical bridge ports
- the IP packet arrived on or will leave by.
+ Policy matching allows you to match packets based on the
+ IPsec policy that was used during decapsulation/will
+ be used during encapsulation.
To compile it as a module, choose M here. If unsure, say N.
@@ -209,17 +173,6 @@ config IP6_NF_TARGET_REJECT
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_TARGET_NFQUEUE
- tristate "NFQUEUE Target Support"
- depends on IP6_NF_IPTABLES
- help
- This Target replaced the old obsolete QUEUE target.
-
- As opposed to QUEUE, it supports 65535 different queues,
- not just one.
-
- To compile it as a module, choose M here. If unsure, say N.
-
config IP6_NF_MANGLE
tristate "Packet mangling"
depends on IP6_NF_IPTABLES
@@ -230,19 +183,6 @@ config IP6_NF_MANGLE
To compile it as a module, choose M here. If unsure, say N.
-config IP6_NF_TARGET_MARK
- tristate "MARK target support"
- depends on IP6_NF_MANGLE
- help
- This option adds a `MARK' target, which allows you to create rules
- in the `mangle' table which alter the netfilter mark (nfmark) field
- associated with the packet packet prior to routing. This can change
- the routing method (see `Use netfilter MARK value as routing
- key') and can also be used by other subsystems to change their
- behavior.
-
- 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
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 9ab5b2ca1f59..db6073c94163 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -4,24 +4,18 @@
# Link order matters here.
obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
-obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
-obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
-obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
-obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
+obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
-obj-$(CONFIG_IP6_NF_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_TARGET_NFQUEUE) += ip6t_NFQUEUE.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
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 95d469271c4d..847068fd3367 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -13,15 +13,19 @@
* a table
* 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu>
* - new extension header parser code
+ * 15 Oct 2005 Harald Welte <laforge@netfilter.org>
+ * - Unification of {ip,ip6}_tables into x_tables
+ * - Removed tcp and udp code, since it's not ipv6 specific
*/
+
+#include <linux/capability.h>
#include <linux/config.h>
+#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
#include <linux/module.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
#include <linux/icmpv6.h>
#include <net/ipv6.h>
#include <asm/uaccess.h>
@@ -30,6 +34,7 @@
#include <linux/cpumask.h>
#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -64,13 +69,8 @@ do { \
#else
#define IP_NF_ASSERT(x)
#endif
-#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
-static DECLARE_MUTEX(ip6t_mutex);
-/* Must have mutex */
-#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
-#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
#include <linux/netfilter_ipv4/listhelp.h>
#if 0
@@ -86,55 +86,22 @@ static DECLARE_MUTEX(ip6t_mutex);
context stops packets coming through and allows user context to read
the counters or update the rules.
- To be cache friendly on SMP, we arrange them like so:
- [ n-entries ]
- ... cache-align padding ...
- [ n-entries ]
-
Hence the start of any table is given by get_table() below. */
-/* The table itself */
-struct ip6t_table_info
-{
- /* Size per table */
- unsigned int size;
- /* Number of entries: FIXME. --RR */
- unsigned int number;
- /* Initial number of entries. Needed for module usage count */
- unsigned int initial_entries;
-
- /* Entry points and underflows */
- unsigned int hook_entry[NF_IP6_NUMHOOKS];
- unsigned int underflow[NF_IP6_NUMHOOKS];
-
- /* ip6t_entry tables: one per CPU */
- char entries[0] ____cacheline_aligned;
-};
-
-static LIST_HEAD(ip6t_target);
-static LIST_HEAD(ip6t_match);
-static LIST_HEAD(ip6t_tables);
-#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
-
-#ifdef CONFIG_SMP
-#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
-#else
-#define TABLE_OFFSET(t,p) 0
-#endif
-
#if 0
#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
#endif
-static int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,
- struct in6_addr addr2)
+int
+ip6_masked_addrcmp(const struct in6_addr *addr1, const struct in6_addr *mask,
+ const struct in6_addr *addr2)
{
int i;
for( i = 0; i < 16; i++){
- if((addr1.s6_addr[i] & mask.s6_addr[i]) !=
- (addr2.s6_addr[i] & mask.s6_addr[i]))
+ if((addr1->s6_addr[i] & mask->s6_addr[i]) !=
+ (addr2->s6_addr[i] & mask->s6_addr[i]))
return 1;
}
return 0;
@@ -168,10 +135,10 @@ ip6_packet_match(const struct sk_buff *skb,
#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
- if (FWINV(ip6_masked_addrcmp(ipv6->saddr,ip6info->smsk,ip6info->src),
- IP6T_INV_SRCIP)
- || FWINV(ip6_masked_addrcmp(ipv6->daddr,ip6info->dmsk,ip6info->dst),
- IP6T_INV_DSTIP)) {
+ if (FWINV(ip6_masked_addrcmp(&ipv6->saddr, &ip6info->smsk,
+ &ip6info->src), IP6T_INV_SRCIP)
+ || FWINV(ip6_masked_addrcmp(&ipv6->daddr, &ip6info->dmsk,
+ &ip6info->dst), IP6T_INV_DSTIP)) {
dprintf("Source or dest mismatch.\n");
/*
dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
@@ -214,69 +181,21 @@ ip6_packet_match(const struct sk_buff *skb,
/* look for the desired protocol header */
if((ip6info->flags & IP6T_F_PROTO)) {
- u_int8_t currenthdr = ipv6->nexthdr;
- struct ipv6_opt_hdr _hdr, *hp;
- u_int16_t ptr; /* Header offset in skb */
- u_int16_t hdrlen; /* Header */
- u_int16_t _fragoff = 0, *fp = NULL;
-
- ptr = IPV6_HDR_LEN;
-
- while (ip6t_ext_hdr(currenthdr)) {
- /* Is there enough space for the next ext header? */
- if (skb->len - ptr < IPV6_OPTHDR_LEN)
- return 0;
-
- /* NONE or ESP: there isn't protocol part */
- /* If we want to count these packets in '-p all',
- * we will change the return 0 to 1*/
- if ((currenthdr == IPPROTO_NONE) ||
- (currenthdr == IPPROTO_ESP))
- break;
-
- hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
- BUG_ON(hp == NULL);
-
- /* Size calculation */
- if (currenthdr == IPPROTO_FRAGMENT) {
- fp = skb_header_pointer(skb,
- ptr+offsetof(struct frag_hdr,
- frag_off),
- sizeof(_fragoff),
- &_fragoff);
- if (fp == NULL)
- return 0;
-
- _fragoff = ntohs(*fp) & ~0x7;
- hdrlen = 8;
- } else if (currenthdr == IPPROTO_AH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
-
- currenthdr = hp->nexthdr;
- ptr += hdrlen;
- /* ptr is too large */
- if ( ptr > skb->len )
- return 0;
- if (_fragoff) {
- if (ip6t_ext_hdr(currenthdr))
- return 0;
- break;
- }
- }
+ int protohdr;
+ unsigned short _frag_off;
- *protoff = ptr;
- *fragoff = _fragoff;
+ protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
+ if (protohdr < 0)
+ return 0;
- /* currenthdr contains the protocol header */
+ *fragoff = _frag_off;
dprintf("Packet protocol %hi ?= %s%hi.\n",
- currenthdr,
+ protohdr,
ip6info->invflags & IP6T_INV_PROTO ? "!":"",
ip6info->proto);
- if (ip6info->proto == currenthdr) {
+ if (ip6info->proto == protohdr) {
if(ip6info->invflags & IP6T_INV_PROTO) {
return 0;
}
@@ -351,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb,
unsigned int hook,
const struct net_device *in,
const struct net_device *out,
- struct ip6t_table *table,
+ struct xt_table *table,
void *userdata)
{
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
@@ -363,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb,
const char *indev, *outdev;
void *table_base;
struct ip6t_entry *e, *back;
+ struct xt_table_info *private;
/* Initialization */
indev = in ? in->name : nulldevname;
@@ -375,10 +295,10 @@ ip6t_do_table(struct sk_buff **pskb,
* match it. */
read_lock_bh(&table->lock);
+ private = table->private;
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
- table_base = (void *)table->private->entries
- + TABLE_OFFSET(table->private, smp_processor_id());
- e = get_entry(table_base, table->private->hook_entry[hook]);
+ table_base = (void *)private->entries[smp_processor_id()];
+ e = get_entry(table_base, private->hook_entry[hook]);
#ifdef CONFIG_NETFILTER_DEBUG
/* Check noone else using our table */
@@ -394,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb,
#endif
/* For return from builtin chain */
- back = get_entry(table_base, table->private->underflow[hook]);
+ back = get_entry(table_base, private->underflow[hook]);
do {
IP_NF_ASSERT(e);
@@ -494,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb,
#endif
}
-/*
- * These are weird, but module loading must not be done with mutex
- * held (since they will register), and we have to have a single
- * function to use try_then_request_module().
- */
-
-/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
-static inline struct ip6t_table *find_table_lock(const char *name)
-{
- struct ip6t_table *t;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &ip6t_tables, list)
- if (strcmp(t->name, name) == 0 && try_module_get(t->me))
- return t;
- up(&ip6t_mutex);
- return NULL;
-}
-
-/* Find match, grabs ref. Returns ERR_PTR() on error. */
-static inline struct ip6t_match *find_match(const char *name, u8 revision)
-{
- struct ip6t_match *m;
- int err = 0;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(m, &ip6t_match, list) {
- if (strcmp(m->name, name) == 0) {
- if (m->revision == revision) {
- if (try_module_get(m->me)) {
- up(&ip6t_mutex);
- return m;
- }
- } else
- err = -EPROTOTYPE; /* Found something. */
- }
- }
- up(&ip6t_mutex);
- return ERR_PTR(err);
-}
-
-/* Find target, grabs ref. Returns ERR_PTR() on error. */
-static inline struct ip6t_target *find_target(const char *name, u8 revision)
-{
- struct ip6t_target *t;
- int err = 0;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return ERR_PTR(-EINTR);
-
- list_for_each_entry(t, &ip6t_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision == revision) {
- if (try_module_get(t->me)) {
- up(&ip6t_mutex);
- return t;
- }
- } else
- err = -EPROTOTYPE; /* Found something. */
- }
- }
- up(&ip6t_mutex);
- return ERR_PTR(err);
-}
-
-struct ip6t_target *ip6t_find_target(const char *name, u8 revision)
-{
- struct ip6t_target *target;
-
- target = try_then_request_module(find_target(name, revision),
- "ip6t_%s", name);
- if (IS_ERR(target) || !target)
- return NULL;
- return target;
-}
-
-static int match_revfn(const char *name, u8 revision, int *bestp)
-{
- struct ip6t_match *m;
- int have_rev = 0;
-
- list_for_each_entry(m, &ip6t_match, list) {
- if (strcmp(m->name, name) == 0) {
- if (m->revision > *bestp)
- *bestp = m->revision;
- if (m->revision == revision)
- have_rev = 1;
- }
- }
- return have_rev;
-}
-
-static int target_revfn(const char *name, u8 revision, int *bestp)
-{
- struct ip6t_target *t;
- int have_rev = 0;
-
- list_for_each_entry(t, &ip6t_target, list) {
- if (strcmp(t->name, name) == 0) {
- if (t->revision > *bestp)
- *bestp = t->revision;
- if (t->revision == revision)
- have_rev = 1;
- }
- }
- return have_rev;
-}
-
-/* Returns true or fals (if no such extension at all) */
-static inline int find_revision(const char *name, u8 revision,
- int (*revfn)(const char *, u8, int *),
- int *err)
-{
- int have_rev, best = -1;
-
- if (down_interruptible(&ip6t_mutex) != 0) {
- *err = -EINTR;
- return 1;
- }
- have_rev = revfn(name, revision, &best);
- up(&ip6t_mutex);
-
- /* Nothing at all? Return 0 to try loading module. */
- if (best == -1) {
- *err = -ENOENT;
- return 0;
- }
-
- *err = best;
- if (!have_rev)
- *err = -EPROTONOSUPPORT;
- return 1;
-}
-
-
/* All zeroes == unconditional rule. */
static inline int
unconditional(const struct ip6t_ip6 *ipv6)
@@ -649,7 +430,8 @@ unconditional(const struct ip6t_ip6 *ipv6)
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
-mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
+mark_source_chains(struct xt_table_info *newinfo,
+ unsigned int valid_hooks, void *entry0)
{
unsigned int hook;
@@ -658,7 +440,7 @@ mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) {
unsigned int pos = newinfo->hook_entry[hook];
struct ip6t_entry *e
- = (struct ip6t_entry *)(newinfo->entries + pos);
+ = (struct ip6t_entry *)(entry0 + pos);
if (!(valid_hooks & (1 << hook)))
continue;
@@ -708,13 +490,13 @@ mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
goto next;
e = (struct ip6t_entry *)
- (newinfo->entries + pos);
+ (entry0 + pos);
} while (oldpos == pos + e->next_offset);
/* Move along one */
size = e->next_offset;
e = (struct ip6t_entry *)
- (newinfo->entries + pos + size);
+ (entry0 + pos + size);
e->counters.pcnt = pos;
pos += size;
} else {
@@ -731,7 +513,7 @@ mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
newpos = pos + e->next_offset;
}
e = (struct ip6t_entry *)
- (newinfo->entries + newpos);
+ (entry0 + newpos);
e->counters.pcnt = pos;
pos = newpos;
}
@@ -794,11 +576,11 @@ check_match(struct ip6t_entry_match *m,
{
struct ip6t_match *match;
- match = try_then_request_module(find_match(m->u.user.name,
- m->u.user.revision),
+ match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name,
+ m->u.user.revision),
"ip6t_%s", m->u.user.name);
if (IS_ERR(match) || !match) {
- duprintf("check_match: `%s' not found\n", m->u.user.name);
+ duprintf("check_match: `%s' not found\n", m->u.user.name);
return match ? PTR_ERR(match) : -ENOENT;
}
m->u.kernel.match = match;
@@ -839,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
goto cleanup_matches;
t = ip6t_get_target(e);
- target = try_then_request_module(find_target(t->u.user.name,
- t->u.user.revision),
+ target = try_then_request_module(xt_find_target(AF_INET6,
+ t->u.user.name,
+ t->u.user.revision),
"ip6t_%s", t->u.user.name);
if (IS_ERR(target) || !target) {
duprintf("check_entry: `%s' not found\n", t->u.user.name);
@@ -876,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
static inline int
check_entry_size_and_hooks(struct ip6t_entry *e,
- struct ip6t_table_info *newinfo,
+ struct xt_table_info *newinfo,
unsigned char *base,
unsigned char *limit,
const unsigned int *hook_entries,
@@ -910,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
< 0 (not IP6T_RETURN). --RR */
/* Clear counters and comefrom */
- e->counters = ((struct ip6t_counters) { 0, 0 });
+ e->counters = ((struct xt_counters) { 0, 0 });
e->comefrom = 0;
(*i)++;
@@ -940,7 +723,8 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
static int
translate_table(const char *name,
unsigned int valid_hooks,
- struct ip6t_table_info *newinfo,
+ struct xt_table_info *newinfo,
+ void *entry0,
unsigned int size,
unsigned int number,
const unsigned int *hook_entries,
@@ -961,11 +745,11 @@ translate_table(const char *name,
duprintf("translate_table: size %u\n", newinfo->size);
i = 0;
/* Walk through entries, checking offsets. */
- ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
check_entry_size_and_hooks,
newinfo,
- newinfo->entries,
- newinfo->entries + size,
+ entry0,
+ entry0 + size,
hook_entries, underflows, &i);
if (ret != 0)
return ret;
@@ -993,95 +777,79 @@ translate_table(const char *name,
}
}
- if (!mark_source_chains(newinfo, valid_hooks))
+ if (!mark_source_chains(newinfo, valid_hooks, entry0))
return -ELOOP;
/* Finally, each sanity check must pass */
i = 0;
- ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
check_entry, name, size, &i);
if (ret != 0) {
- IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+ IP6T_ENTRY_ITERATE(entry0, newinfo->size,
cleanup_entry, &i);
return ret;
}
/* And one copy for every other CPU */
for_each_cpu(i) {
- if (i == 0)
- continue;
- memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
- newinfo->entries,
- SMP_ALIGN(newinfo->size));
+ if (newinfo->entries[i] && newinfo->entries[i] != entry0)
+ memcpy(newinfo->entries[i], entry0, newinfo->size);
}
return ret;
}
-static struct ip6t_table_info *
-replace_table(struct ip6t_table *table,
- unsigned int num_counters,
- struct ip6t_table_info *newinfo,
- int *error)
+/* Gets counters. */
+static inline int
+add_entry_to_counter(const struct ip6t_entry *e,
+ struct xt_counters total[],
+ unsigned int *i)
{
- struct ip6t_table_info *oldinfo;
-
-#ifdef CONFIG_NETFILTER_DEBUG
- {
- struct ip6t_entry *table_base;
- unsigned int i;
-
- for_each_cpu(i) {
- table_base =
- (void *)newinfo->entries
- + TABLE_OFFSET(newinfo, i);
-
- table_base->comefrom = 0xdead57ac;
- }
- }
-#endif
-
- /* Do the substitution. */
- write_lock_bh(&table->lock);
- /* Check inside lock: is the old number correct? */
- if (num_counters != table->private->number) {
- duprintf("num_counters != table->private->number (%u/%u)\n",
- num_counters, table->private->number);
- write_unlock_bh(&table->lock);
- *error = -EAGAIN;
- return NULL;
- }
- oldinfo = table->private;
- table->private = newinfo;
- newinfo->initial_entries = oldinfo->initial_entries;
- write_unlock_bh(&table->lock);
+ ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
- return oldinfo;
+ (*i)++;
+ return 0;
}
-/* Gets counters. */
static inline int
-add_entry_to_counter(const struct ip6t_entry *e,
+set_entry_to_counter(const struct ip6t_entry *e,
struct ip6t_counters total[],
unsigned int *i)
{
- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
+ SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
(*i)++;
return 0;
}
static void
-get_counters(const struct ip6t_table_info *t,
- struct ip6t_counters counters[])
+get_counters(const struct xt_table_info *t,
+ struct xt_counters counters[])
{
unsigned int cpu;
unsigned int i;
+ unsigned int curcpu;
+
+ /* Instead of clearing (by a previous call to memset())
+ * the counters and using adds, we set the counters
+ * with data used by 'current' CPU
+ * We dont care about preemption here.
+ */
+ curcpu = raw_smp_processor_id();
+
+ i = 0;
+ IP6T_ENTRY_ITERATE(t->entries[curcpu],
+ t->size,
+ set_entry_to_counter,
+ counters,
+ &i);
for_each_cpu(cpu) {
+ if (cpu == curcpu)
+ continue;
i = 0;
- IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
+ IP6T_ENTRY_ITERATE(t->entries[cpu],
t->size,
add_entry_to_counter,
counters,
@@ -1091,31 +859,33 @@ get_counters(const struct ip6t_table_info *t,
static int
copy_entries_to_user(unsigned int total_size,
- struct ip6t_table *table,
+ struct xt_table *table,
void __user *userptr)
{
unsigned int off, num, countersize;
struct ip6t_entry *e;
- struct ip6t_counters *counters;
+ struct xt_counters *counters;
+ struct xt_table_info *private = table->private;
int ret = 0;
+ void *loc_cpu_entry;
/* We need atomic snapshot of counters: rest doesn't change
(other than comefrom, which userspace doesn't care
about). */
- countersize = sizeof(struct ip6t_counters) * table->private->number;
+ countersize = sizeof(struct xt_counters) * private->number;
counters = vmalloc(countersize);
if (counters == NULL)
return -ENOMEM;
/* First, sum counters... */
- memset(counters, 0, countersize);
write_lock_bh(&table->lock);
- get_counters(table->private, counters);
+ get_counters(private, counters);
write_unlock_bh(&table->lock);
- /* ... then copy entire thing from CPU 0... */
- if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
+ /* choose the copy that is on ourc node/cpu */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) {
ret = -EFAULT;
goto free_counters;
}
@@ -1127,7 +897,7 @@ copy_entries_to_user(unsigned int total_size,
struct ip6t_entry_match *m;
struct ip6t_entry_target *t;
- e = (struct ip6t_entry *)(table->private->entries + off);
+ e = (struct ip6t_entry *)(loc_cpu_entry + off);
if (copy_to_user(userptr + off
+ offsetof(struct ip6t_entry, counters),
&counters[num],
@@ -1173,23 +943,22 @@ get_entries(const struct ip6t_get_entries *entries,
struct ip6t_get_entries __user *uptr)
{
int ret;
- struct ip6t_table *t;
+ struct xt_table *t;
- t = find_table_lock(entries->name);
+ t = xt_find_table_lock(AF_INET6, entries->name);
if (t && !IS_ERR(t)) {
- duprintf("t->private->number = %u\n",
- t->private->number);
- if (entries->size == t->private->size)
- ret = copy_entries_to_user(t->private->size,
+ struct xt_table_info *private = t->private;
+ duprintf("t->private->number = %u\n", private->number);
+ if (entries->size == private->size)
+ ret = copy_entries_to_user(private->size,
t, uptr->entrytable);
else {
duprintf("get_entries: I've got %u not %u!\n",
- t->private->size,
- entries->size);
+ private->size, entries->size);
ret = -EINVAL;
}
module_put(t->me);
- up(&ip6t_mutex);
+ xt_table_unlock(t);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1201,45 +970,41 @@ do_replace(void __user *user, unsigned int len)
{
int ret;
struct ip6t_replace tmp;
- struct ip6t_table *t;
- struct ip6t_table_info *newinfo, *oldinfo;
- struct ip6t_counters *counters;
+ struct xt_table *t;
+ struct xt_table_info *newinfo, *oldinfo;
+ struct xt_counters *counters;
+ void *loc_cpu_entry, *loc_cpu_old_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
- /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
- if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
- return -ENOMEM;
-
- newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(tmp.size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(tmp.size);
if (!newinfo)
return -ENOMEM;
- if (copy_from_user(newinfo->entries, user + sizeof(tmp),
+ /* choose the copy that is on our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ if (copy_from_user(loc_cpu_entry, user + sizeof(tmp),
tmp.size) != 0) {
ret = -EFAULT;
goto free_newinfo;
}
- counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters));
+ counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters));
if (!counters) {
ret = -ENOMEM;
goto free_newinfo;
}
- memset(counters, 0, tmp.num_counters * sizeof(struct ip6t_counters));
ret = translate_table(tmp.name, tmp.valid_hooks,
- newinfo, tmp.size, tmp.num_entries,
+ newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
tmp.hook_entry, tmp.underflow);
if (ret != 0)
goto free_newinfo_counters;
duprintf("ip_tables: Translated table\n");
- t = try_then_request_module(find_table_lock(tmp.name),
+ t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name),
"ip6table_%s", tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1254,7 +1019,7 @@ do_replace(void __user *user, unsigned int len)
goto put_module;
}
- oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+ oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret);
if (!oldinfo)
goto put_module;
@@ -1271,24 +1036,25 @@ do_replace(void __user *user, unsigned int len)
/* Get the old counters. */
get_counters(oldinfo, counters);
/* Decrease module usage counts and free resource */
- IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
- vfree(oldinfo);
+ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
+ IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL);
+ xt_free_table_info(oldinfo);
if (copy_to_user(tmp.counters, counters,
- sizeof(struct ip6t_counters) * tmp.num_counters) != 0)
+ sizeof(struct xt_counters) * tmp.num_counters) != 0)
ret = -EFAULT;
vfree(counters);
- up(&ip6t_mutex);
+ xt_table_unlock(t);
return ret;
put_module:
module_put(t->me);
- up(&ip6t_mutex);
+ xt_table_unlock(t);
free_newinfo_counters_untrans:
- IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
+ IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL);
free_newinfo_counters:
vfree(counters);
free_newinfo:
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
@@ -1296,7 +1062,7 @@ do_replace(void __user *user, unsigned int len)
* and everything is OK. */
static inline int
add_counter_to_entry(struct ip6t_entry *e,
- const struct ip6t_counters addme[],
+ const struct xt_counters addme[],
unsigned int *i)
{
#if 0
@@ -1318,14 +1084,16 @@ static int
do_add_counters(void __user *user, unsigned int len)
{
unsigned int i;
- struct ip6t_counters_info tmp, *paddc;
- struct ip6t_table *t;
+ struct xt_counters_info tmp, *paddc;
+ struct xt_table_info *private;
+ struct xt_table *t;
int ret = 0;
+ void *loc_cpu_entry;
if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
return -EFAULT;
- if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters))
+ if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters))
return -EINVAL;
paddc = vmalloc(len);
@@ -1337,27 +1105,30 @@ do_add_counters(void __user *user, unsigned int len)
goto free;
}
- t = find_table_lock(tmp.name);
+ t = xt_find_table_lock(AF_INET6, tmp.name);
if (!t || IS_ERR(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
}
write_lock_bh(&t->lock);
- if (t->private->number != paddc->num_counters) {
+ private = t->private;
+ if (private->number != paddc->num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
i = 0;
- IP6T_ENTRY_ITERATE(t->private->entries,
- t->private->size,
+ /* Choose the copy that is on our node */
+ loc_cpu_entry = private->entries[smp_processor_id()];
+ IP6T_ENTRY_ITERATE(loc_cpu_entry,
+ private->size,
add_counter_to_entry,
paddc->counters,
&i);
unlock_up_free:
write_unlock_bh(&t->lock);
- up(&ip6t_mutex);
+ xt_table_unlock(t);
module_put(t->me);
free:
vfree(paddc);
@@ -1401,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
switch (cmd) {
case IP6T_SO_GET_INFO: {
char name[IP6T_TABLE_MAXNAMELEN];
- struct ip6t_table *t;
+ struct xt_table *t;
if (*len != sizeof(struct ip6t_getinfo)) {
duprintf("length %u != %u\n", *len,
@@ -1416,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
}
name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
- t = try_then_request_module(find_table_lock(name),
+ t = try_then_request_module(xt_find_table_lock(AF_INET6, name),
"ip6table_%s", name);
if (t && !IS_ERR(t)) {
struct ip6t_getinfo info;
+ struct xt_table_info *private = t->private;
info.valid_hooks = t->valid_hooks;
- memcpy(info.hook_entry, t->private->hook_entry,
+ memcpy(info.hook_entry, private->hook_entry,
sizeof(info.hook_entry));
- memcpy(info.underflow, t->private->underflow,
+ memcpy(info.underflow, private->underflow,
sizeof(info.underflow));
- info.num_entries = t->private->number;
- info.size = t->private->size;
+ info.num_entries = private->number;
+ info.size = private->size;
memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
else
ret = 0;
- up(&ip6t_mutex);
+ xt_table_unlock(t);
module_put(t->me);
} else
ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1461,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
case IP6T_SO_GET_REVISION_MATCH:
case IP6T_SO_GET_REVISION_TARGET: {
struct ip6t_get_revision rev;
- int (*revfn)(const char *, u8, int *);
+ int target;
if (*len != sizeof(rev)) {
ret = -EINVAL;
@@ -1473,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
}
if (cmd == IP6T_SO_GET_REVISION_TARGET)
- revfn = target_revfn;
+ target = 1;
else
- revfn = match_revfn;
+ target = 0;
- try_then_request_module(find_revision(rev.name, rev.revision,
- revfn, &ret),
+ try_then_request_module(xt_find_revision(AF_INET6, rev.name,
+ rev.revision,
+ target, &ret),
"ip6t_%s", rev.name);
break;
}
@@ -1491,308 +1264,52 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-/* Registration hooks for targets. */
-int
-ip6t_register_target(struct ip6t_target *target)
-{
- int ret;
-
- ret = down_interruptible(&ip6t_mutex);
- if (ret != 0)
- return ret;
- list_add(&target->list, &ip6t_target);
- up(&ip6t_mutex);
- return ret;
-}
-
-void
-ip6t_unregister_target(struct ip6t_target *target)
-{
- down(&ip6t_mutex);
- LIST_DELETE(&ip6t_target, target);
- up(&ip6t_mutex);
-}
-
-int
-ip6t_register_match(struct ip6t_match *match)
-{
- int ret;
-
- ret = down_interruptible(&ip6t_mutex);
- if (ret != 0)
- return ret;
-
- list_add(&match->list, &ip6t_match);
- up(&ip6t_mutex);
-
- return ret;
-}
-
-void
-ip6t_unregister_match(struct ip6t_match *match)
-{
- down(&ip6t_mutex);
- LIST_DELETE(&ip6t_match, match);
- up(&ip6t_mutex);
-}
-
-int ip6t_register_table(struct ip6t_table *table,
+int ip6t_register_table(struct xt_table *table,
const struct ip6t_replace *repl)
{
int ret;
- struct ip6t_table_info *newinfo;
- static struct ip6t_table_info bootstrap
+ struct xt_table_info *newinfo;
+ static struct xt_table_info bootstrap
= { 0, 0, 0, { 0 }, { 0 }, { } };
+ void *loc_cpu_entry;
- newinfo = vmalloc(sizeof(struct ip6t_table_info)
- + SMP_ALIGN(repl->size) *
- (highest_possible_processor_id()+1));
+ newinfo = xt_alloc_table_info(repl->size);
if (!newinfo)
return -ENOMEM;
- memcpy(newinfo->entries, repl->entries, repl->size);
+ /* choose the copy on our node/cpu */
+ loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
+ memcpy(loc_cpu_entry, repl->entries, repl->size);
ret = translate_table(table->name, table->valid_hooks,
- newinfo, repl->size,
+ newinfo, loc_cpu_entry, repl->size,
repl->num_entries,
repl->hook_entry,
repl->underflow);
if (ret != 0) {
- vfree(newinfo);
+ xt_free_table_info(newinfo);
return ret;
}
- ret = down_interruptible(&ip6t_mutex);
- if (ret != 0) {
- vfree(newinfo);
+ if (xt_register_table(table, &bootstrap, newinfo) != 0) {
+ xt_free_table_info(newinfo);
return ret;
}
- /* Don't autoload: we'd eat our tail... */
- if (list_named_find(&ip6t_tables, table->name)) {
- ret = -EEXIST;
- goto free_unlock;
- }
-
- /* Simplifies replace_table code. */
- table->private = &bootstrap;
- if (!replace_table(table, 0, newinfo, &ret))
- goto free_unlock;
-
- duprintf("table->private->number = %u\n",
- table->private->number);
-
- /* save number of initial entries */
- table->private->initial_entries = table->private->number;
-
- rwlock_init(&table->lock);
- list_prepend(&ip6t_tables, table);
-
- unlock:
- up(&ip6t_mutex);
- return ret;
-
- free_unlock:
- vfree(newinfo);
- goto unlock;
-}
-
-void ip6t_unregister_table(struct ip6t_table *table)
-{
- down(&ip6t_mutex);
- LIST_DELETE(&ip6t_tables, table);
- up(&ip6t_mutex);
-
- /* Decrease module usage counts and free resources */
- IP6T_ENTRY_ITERATE(table->private->entries, table->private->size,
- cleanup_entry, NULL);
- vfree(table->private);
-}
-
-/* Returns 1 if the port is matched by the range, 0 otherwise */
-static inline int
-port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
-{
- int ret;
-
- ret = (port >= min && port <= max) ^ invert;
- return ret;
-}
-
-static int
-tcp_find_option(u_int8_t option,
- const struct sk_buff *skb,
- unsigned int tcpoff,
- unsigned int optlen,
- int invert,
- int *hotdrop)
-{
- /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
- unsigned int i;
-
- duprintf("tcp_match: finding option\n");
- if (!optlen)
- return invert;
- /* If we don't have the whole header, drop packet. */
- op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
- _opt);
- if (op == NULL) {
- *hotdrop = 1;
- return 0;
- }
-
- for (i = 0; i < optlen; ) {
- if (op[i] == option) return !invert;
- if (op[i] < 2) i++;
- else i += op[i+1]?:1;
- }
-
- return invert;
-}
-
-static int
-tcp_match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- struct tcphdr _tcph, *th;
- const struct ip6t_tcp *tcpinfo = matchinfo;
-
- if (offset) {
- /* To quote Alan:
-
- Don't allow a fragment of TCP 8 bytes in. Nobody normal
- causes this. Its a cracker trying to break in by doing a
- flag overwrite to pass the direction checks.
- */
- if (offset == 1) {
- duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = 1;
- }
- /* Must not be a fragment. */
- return 0;
- }
-
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
-
- th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
- if (th == NULL) {
- /* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
- ntohs(th->source),
- !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
- return 0;
- if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
- ntohs(th->dest),
- !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
- return 0;
- if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
- == tcpinfo->flg_cmp,
- IP6T_TCP_INV_FLAGS))
- return 0;
- if (tcpinfo->option) {
- if (th->doff * 4 < sizeof(_tcph)) {
- *hotdrop = 1;
- return 0;
- }
- if (!tcp_find_option(tcpinfo->option, skb, protoff,
- th->doff*4 - sizeof(*th),
- tcpinfo->invflags & IP6T_TCP_INV_OPTION,
- hotdrop))
- return 0;
- }
- return 1;
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-tcp_checkentry(const char *tablename,
- const struct ip6t_ip6 *ipv6,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- const struct ip6t_tcp *tcpinfo = matchinfo;
-
- /* Must specify proto == TCP, and no unknown invflags */
- return ipv6->proto == IPPROTO_TCP
- && !(ipv6->invflags & IP6T_INV_PROTO)
- && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
- && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
+ return 0;
}
-static int
-udp_match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+void ip6t_unregister_table(struct xt_table *table)
{
- struct udphdr _udph, *uh;
- const struct ip6t_udp *udpinfo = matchinfo;
+ struct xt_table_info *private;
+ void *loc_cpu_entry;
- /* Must not be a fragment. */
- if (offset)
- return 0;
-
- uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
- if (uh == NULL) {
- /* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- duprintf("Dropping evil UDP tinygram.\n");
- *hotdrop = 1;
- return 0;
- }
-
- return port_match(udpinfo->spts[0], udpinfo->spts[1],
- ntohs(uh->source),
- !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
- && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
- ntohs(uh->dest),
- !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
-}
-
-/* Called when user tries to insert an entry of this type. */
-static int
-udp_checkentry(const char *tablename,
- const struct ip6t_ip6 *ipv6,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
-{
- const struct ip6t_udp *udpinfo = matchinfo;
+ private = xt_unregister_table(table);
- /* Must specify proto == UDP, and no unknown invflags */
- if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
- duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
- IPPROTO_UDP);
- return 0;
- }
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
- duprintf("ip6t_udp: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
- return 0;
- }
- if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
- duprintf("ip6t_udp: unknown flags %X\n",
- udpinfo->invflags);
- return 0;
- }
-
- return 1;
+ /* Decrease module usage counts and free resources */
+ loc_cpu_entry = private->entries[raw_smp_processor_id()];
+ IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
+ xt_free_table_info(private);
}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
@@ -1840,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
icmp6_checkentry(const char *tablename,
- const struct ip6t_ip6 *ipv6,
+ const void *entry,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ip6t_ip6 *ipv6 = entry;
const struct ip6t_icmp *icmpinfo = matchinfo;
/* Must specify proto == ICMP, and no unknown invflags */
@@ -1874,187 +1392,78 @@ static struct nf_sockopt_ops ip6t_sockopts = {
.get = do_ip6t_get_ctl,
};
-static struct ip6t_match tcp_matchstruct = {
- .name = "tcp",
- .match = &tcp_match,
- .checkentry = &tcp_checkentry,
-};
-
-static struct ip6t_match udp_matchstruct = {
- .name = "udp",
- .match = &udp_match,
- .checkentry = &udp_checkentry,
-};
-
static struct ip6t_match icmp6_matchstruct = {
.name = "icmp6",
.match = &icmp6_match,
.checkentry = &icmp6_checkentry,
};
-#ifdef CONFIG_PROC_FS
-static inline int print_name(const char *i,
- off_t start_offset, char *buffer, int length,
- off_t *pos, unsigned int *count)
-{
- if ((*count)++ >= start_offset) {
- unsigned int namelen;
-
- namelen = sprintf(buffer + *pos, "%s\n",
- i + sizeof(struct list_head));
- if (*pos + namelen > length) {
- /* Stop iterating */
- return 1;
- }
- *pos += namelen;
- }
- return 0;
-}
-
-static inline int print_target(const struct ip6t_target *t,
- off_t start_offset, char *buffer, int length,
- off_t *pos, unsigned int *count)
-{
- if (t == &ip6t_standard_target || t == &ip6t_error_target)
- return 0;
- return print_name((char *)t, start_offset, buffer, length, pos, count);
-}
-
-static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return 0;
-
- LIST_FIND(&ip6t_tables, print_name, char *,
- offset, buffer, length, &pos, &count);
-
- up(&ip6t_mutex);
-
- /* `start' hack - see fs/proc/generic.c line ~105 */
- *start=(char *)((unsigned long)count-offset);
- return pos;
-}
-
-static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return 0;
-
- LIST_FIND(&ip6t_target, print_target, struct ip6t_target *,
- offset, buffer, length, &pos, &count);
-
- up(&ip6t_mutex);
-
- *start = (char *)((unsigned long)count - offset);
- return pos;
-}
-
-static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
-{
- off_t pos = 0;
- unsigned int count = 0;
-
- if (down_interruptible(&ip6t_mutex) != 0)
- return 0;
-
- LIST_FIND(&ip6t_match, print_name, char *,
- offset, buffer, length, &pos, &count);
-
- up(&ip6t_mutex);
-
- *start = (char *)((unsigned long)count - offset);
- return pos;
-}
-
-static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
-{ { "ip6_tables_names", ip6t_get_tables },
- { "ip6_tables_targets", ip6t_get_targets },
- { "ip6_tables_matches", ip6t_get_matches },
- { NULL, NULL} };
-#endif /*CONFIG_PROC_FS*/
-
static int __init init(void)
{
int ret;
+ xt_proto_init(AF_INET6);
+
/* Noone else will be downing sem now, so we won't sleep */
- down(&ip6t_mutex);
- list_append(&ip6t_target, &ip6t_standard_target);
- list_append(&ip6t_target, &ip6t_error_target);
- list_append(&ip6t_match, &tcp_matchstruct);
- list_append(&ip6t_match, &udp_matchstruct);
- list_append(&ip6t_match, &icmp6_matchstruct);
- up(&ip6t_mutex);
+ xt_register_target(AF_INET6, &ip6t_standard_target);
+ xt_register_target(AF_INET6, &ip6t_error_target);
+ xt_register_match(AF_INET6, &icmp6_matchstruct);
/* Register setsockopt */
ret = nf_register_sockopt(&ip6t_sockopts);
if (ret < 0) {
duprintf("Unable to register sockopts.\n");
+ xt_proto_fini(AF_INET6);
return ret;
}
-#ifdef CONFIG_PROC_FS
- {
- struct proc_dir_entry *proc;
- int i;
-
- for (i = 0; ip6t_proc_entry[i].name; i++) {
- proc = proc_net_create(ip6t_proc_entry[i].name, 0,
- ip6t_proc_entry[i].get_info);
- if (!proc) {
- while (--i >= 0)
- proc_net_remove(ip6t_proc_entry[i].name);
- nf_unregister_sockopt(&ip6t_sockopts);
- return -ENOMEM;
- }
- proc->owner = THIS_MODULE;
- }
- }
-#endif
-
- printk("ip6_tables: (C) 2000-2002 Netfilter core team\n");
+ printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
return 0;
}
static void __exit fini(void)
{
nf_unregister_sockopt(&ip6t_sockopts);
-#ifdef CONFIG_PROC_FS
- {
- int i;
- for (i = 0; ip6t_proc_entry[i].name; i++)
- proc_net_remove(ip6t_proc_entry[i].name);
- }
-#endif
+ xt_unregister_match(AF_INET6, &icmp6_matchstruct);
+ xt_unregister_target(AF_INET6, &ip6t_error_target);
+ xt_unregister_target(AF_INET6, &ip6t_standard_target);
+ xt_proto_fini(AF_INET6);
}
/*
- * find specified header up to transport protocol header.
- * If found target header, the offset to the header is set to *offset
- * and return 0. otherwise, return -1.
+ * find the offset to specified header or the protocol number of last header
+ * if target < 0. "last header" is transport protocol header, ESP, or
+ * "No next header".
+ *
+ * If target header is found, its offset is set in *offset and return protocol
+ * number. Otherwise, return -1.
+ *
+ * Note that non-1st fragment is special case that "the protocol number
+ * of last header" is "next header" field in Fragment header. In this case,
+ * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
+ * isn't NULL.
*
- * Notes: - non-1st Fragment Header isn't skipped.
- * - ESP header isn't skipped.
- * - The target header may be trancated.
*/
-int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff)
{
unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
u8 nexthdr = skb->nh.ipv6h->nexthdr;
unsigned int len = skb->len - start;
+ if (fragoff)
+ *fragoff = 0;
+
while (nexthdr != target) {
struct ipv6_opt_hdr _hdr, *hp;
unsigned int hdrlen;
- if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE)
+ if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
+ if (target < 0)
+ break;
return -1;
+ }
+
hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
if (hp == NULL)
return -1;
@@ -2068,8 +1477,17 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
if (fp == NULL)
return -1;
- if (ntohs(*fp) & ~0x7)
+ _frag_off = ntohs(*fp) & ~0x7;
+ if (_frag_off) {
+ if (target < 0 &&
+ ((!ipv6_ext_hdr(hp->nexthdr)) ||
+ nexthdr == NEXTHDR_NONE)) {
+ if (fragoff)
+ *fragoff = _frag_off;
+ return hp->nexthdr;
+ }
return -1;
+ }
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
hdrlen = (hp->hdrlen + 2) << 2;
@@ -2082,18 +1500,15 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
}
*offset = start;
- return 0;
+ return nexthdr;
}
EXPORT_SYMBOL(ip6t_register_table);
EXPORT_SYMBOL(ip6t_unregister_table);
EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ip6t_register_match);
-EXPORT_SYMBOL(ip6t_unregister_match);
-EXPORT_SYMBOL(ip6t_register_target);
-EXPORT_SYMBOL(ip6t_unregister_target);
EXPORT_SYMBOL(ip6t_ext_hdr);
EXPORT_SYMBOL(ipv6_find_hdr);
+EXPORT_SYMBOL(ip6_masked_addrcmp);
module_init(init);
module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 8f5549b72720..306200c35057 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
}
static int ip6t_hl_checkentry(const char *tablename,
- const struct ip6t_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 0cd1d1bd9033..77c725832dec 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
+#include <linux/if_arp.h>
#include <linux/ip.h>
#include <linux/spinlock.h>
#include <linux/icmpv6.h>
@@ -62,9 +63,8 @@ static void dump_packet(const struct nf_loginfo *info,
return;
}
- /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
- printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr));
- printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr));
+ /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
+ printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr));
/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
@@ -443,7 +443,7 @@ ip6t_log_target(struct sk_buff **pskb,
static int ip6t_log_checkentry(const char *tablename,
- const struct ip6t_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
deleted file mode 100644
index eab8fb864ee0..000000000000
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* This is a module which is used for setting the NFMARK field of an skb. */
-
-/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
- *
- * 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_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_MARK.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-
-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 ip6t_mark_target_info *markinfo = targinfo;
-
- if((*pskb)->nfmark != markinfo->mark)
- (*pskb)->nfmark = markinfo->mark;
-
- return IP6T_CONTINUE;
-}
-
-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 ip6t_mark_target_info))) {
- printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
- targinfosize,
- IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)));
- return 0;
- }
-
- if (strcmp(tablename, "mangle") != 0) {
- printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
- return 0;
- }
-
- return 1;
-}
-
-static struct ip6t_target ip6t_mark_reg = {
- .name = "MARK",
- .target = target,
- .checkentry = checkentry,
- .me = THIS_MODULE
-};
-
-static int __init init(void)
-{
- printk(KERN_DEBUG "registering ipv6 mark target\n");
- if (ip6t_register_target(&ip6t_mark_reg))
- return -EINVAL;
-
- return 0;
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_target(&ip6t_mark_reg);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c
deleted file mode 100644
index c6e3730e7409..000000000000
--- a/net/ipv6/netfilter/ip6t_NFQUEUE.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* 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
index b03e87adca93..c745717b4ce2 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb,
}
static int check(const char *tablename,
- const struct ip6t_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
const struct ip6t_reject_info *rejinfo = targinfo;
+ const struct ip6t_entry *e = entry;
if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index dde37793d20b..219a30365dff 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <net/checksum.h>
@@ -53,7 +54,7 @@ match(const struct sk_buff *skb,
unsigned int ptr;
unsigned int hdrlen = 0;
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0)
return 0;
ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
@@ -97,7 +98,7 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
+ const void *entry,
void *matchinfo,
unsigned int matchinfosize,
unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index c450a635e54b..b4c153a53500 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -36,19 +36,19 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
#endif
/*
- * (Type & 0xC0) >> 6
- * 0 -> ignorable
- * 1 -> must drop the packet
- * 2 -> send ICMP PARM PROB regardless and drop packet
- * 3 -> Send ICMP if not a multicast address and drop packet
+ * (Type & 0xC0) >> 6
+ * 0 -> ignorable
+ * 1 -> must drop the packet
+ * 2 -> send ICMP PARM PROB regardless and drop packet
+ * 3 -> Send ICMP if not a multicast address and drop packet
* (Type & 0x20) >> 5
- * 0 -> invariant
- * 1 -> can change the routing
+ * 0 -> invariant
+ * 1 -> can change the routing
* (Type & 0x1F) Type
- * 0 -> Pad1 (only 1 byte!)
- * 1 -> PadN LENGTH info (total length = length + 2)
- * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
- * 5 -> RTALERT 2 x x
+ * 0 -> Pad1 (only 1 byte!)
+ * 1 -> PadN LENGTH info (total length = length + 2)
+ * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
+ * 5 -> RTALERT 2 x x
*/
static int
@@ -60,59 +60,58 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ipv6_opt_hdr _optsh, *oh;
- const struct ip6t_opts *optinfo = matchinfo;
- unsigned int temp;
- unsigned int ptr;
- unsigned int hdrlen = 0;
- unsigned int ret = 0;
- u8 _opttype, *tp = NULL;
- u8 _optlen, *lp = NULL;
- unsigned int optlen;
-
+ struct ipv6_opt_hdr _optsh, *oh;
+ const struct ip6t_opts *optinfo = matchinfo;
+ unsigned int temp;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+ unsigned int ret = 0;
+ u8 _opttype, *tp = NULL;
+ u8 _optlen, *lp = NULL;
+ unsigned int optlen;
+
#if HOPBYHOP
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
#else
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
#endif
return 0;
- oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
- if (oh == NULL){
- *hotdrop = 1;
- return 0;
- }
-
- hdrlen = ipv6_optlen(oh);
- if (skb->len - ptr < hdrlen){
- /* Packet smaller than it's length field */
- return 0;
- }
-
- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
-
- DEBUGP("len %02X %04X %02X ",
- optinfo->hdrlen, hdrlen,
- (!(optinfo->flags & IP6T_OPTS_LEN) ||
- ((optinfo->hdrlen == hdrlen) ^
- !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
-
- ret = (oh != NULL)
- &&
- (!(optinfo->flags & IP6T_OPTS_LEN) ||
- ((optinfo->hdrlen == hdrlen) ^
- !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
-
- ptr += 2;
- hdrlen -= 2;
- if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
- return ret;
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ if (oh == NULL) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ hdrlen = ipv6_optlen(oh);
+ if (skb->len - ptr < hdrlen) {
+ /* Packet smaller than it's length field */
+ return 0;
+ }
+
+ DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
+
+ DEBUGP("len %02X %04X %02X ",
+ optinfo->hdrlen, hdrlen,
+ (!(optinfo->flags & IP6T_OPTS_LEN) ||
+ ((optinfo->hdrlen == hdrlen) ^
+ !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
+
+ ret = (oh != NULL) &&
+ (!(optinfo->flags & IP6T_OPTS_LEN) ||
+ ((optinfo->hdrlen == hdrlen) ^
+ !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
+
+ ptr += 2;
+ hdrlen -= 2;
+ if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
+ return ret;
} else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
DEBUGP("Not strict - not implemented");
} else {
DEBUGP("Strict ");
- DEBUGP("#%d ",optinfo->optsnr);
- for(temp=0; temp<optinfo->optsnr; temp++){
+ DEBUGP("#%d ", optinfo->optsnr);
+ for (temp = 0; temp < optinfo->optsnr; temp++) {
/* type field exists ? */
if (hdrlen < 1)
break;
@@ -122,10 +121,10 @@ match(const struct sk_buff *skb,
break;
/* Type check */
- if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
+ if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
DEBUGP("Tbad %02X %02X\n",
*tp,
- (optinfo->opts[temp] & 0xFF00)>>8);
+ (optinfo->opts[temp] & 0xFF00) >> 8);
return 0;
} else {
DEBUGP("Tok ");
@@ -169,7 +168,8 @@ match(const struct sk_buff *skb,
}
if (temp == optinfo->optsnr)
return ret;
- else return 0;
+ else
+ return 0;
}
return 0;
@@ -178,25 +178,24 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
+ const void *info,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
{
- const struct ip6t_opts *optsinfo = matchinfo;
-
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
- DEBUGP("ip6t_opts: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
- return 0;
- }
- if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
- DEBUGP("ip6t_opts: unknown flags %X\n",
- optsinfo->invflags);
- return 0;
- }
-
- return 1;
+ const struct ip6t_opts *optsinfo = matchinfo;
+
+ if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
+ DEBUGP("ip6t_opts: matchsize %u != %u\n",
+ matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
+ return 0;
+ }
+ if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
+ DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
+ return 0;
+ }
+
+ return 1;
}
static struct ip6t_match opts_match = {
@@ -212,12 +211,12 @@ static struct ip6t_match opts_match = {
static int __init init(void)
{
- return ip6t_register_match(&opts_match);
+ return ip6t_register_match(&opts_match);
}
static void __exit cleanup(void)
{
- ip6t_unregister_match(&opts_match);
+ ip6t_unregister_match(&opts_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index 24bc0cde43a1..724285df8711 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/types.h>
#include <net/checksum.h>
@@ -55,7 +56,7 @@ match(const struct sk_buff *skb,
/* Make sure this isn't an evil packet */
/*DEBUGP("ipv6_esp entered \n");*/
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP, NULL) < 0)
return 0;
eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
@@ -75,7 +76,7 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchinfosize,
unsigned int hook_mask)
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 616c2cbcd54d..27396ac0b9ed 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -27,45 +27,45 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
+ unsigned char eui64[8];
+ int i = 0;
- unsigned char eui64[8];
- int i=0;
-
- if ( !(skb->mac.raw >= skb->head
- && (skb->mac.raw + ETH_HLEN) <= skb->data)
- && offset != 0) {
- *hotdrop = 1;
- return 0;
- }
-
- memset(eui64, 0, sizeof(eui64));
-
- if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
- if (skb->nh.ipv6h->version == 0x6) {
- memcpy(eui64, eth_hdr(skb)->h_source, 3);
- memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
- eui64[3]=0xff;
- eui64[4]=0xfe;
- eui64[0] |= 0x02;
-
- i=0;
- while ((skb->nh.ipv6h->saddr.s6_addr[8+i] ==
- eui64[i]) && (i<8)) i++;
-
- if ( i == 8 )
- return 1;
- }
- }
-
- return 0;
+ if (!(skb->mac.raw >= skb->head &&
+ (skb->mac.raw + ETH_HLEN) <= skb->data) &&
+ offset != 0) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ memset(eui64, 0, sizeof(eui64));
+
+ if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
+ if (skb->nh.ipv6h->version == 0x6) {
+ memcpy(eui64, eth_hdr(skb)->h_source, 3);
+ memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
+ eui64[3] = 0xff;
+ eui64[4] = 0xfe;
+ eui64[0] |= 0x02;
+
+ i = 0;
+ while ((skb->nh.ipv6h->saddr.s6_addr[8+i] == eui64[i])
+ && (i < 8))
+ i++;
+
+ if (i == 8)
+ return 1;
+ }
+ }
+
+ return 0;
}
static int
ip6t_eui64_checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
+ const void *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
{
if (hook_mask
& ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 085d5f8eea29..4c14125a0e26 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -31,12 +31,12 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
static inline int
id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
{
- int r=0;
- DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,id,max);
- r=(id >= min && id <= max) ^ invert;
- DEBUGP(" result %s\n",r? "PASS" : "FAILED");
- return r;
+ int r = 0;
+ DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+ min, id, max);
+ r = (id >= min && id <= max) ^ invert;
+ DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+ return r;
}
static int
@@ -48,92 +48,91 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct frag_hdr _frag, *fh;
- const struct ip6t_frag *fraginfo = matchinfo;
- unsigned int ptr;
+ struct frag_hdr _frag, *fh;
+ const struct ip6t_frag *fraginfo = matchinfo;
+ unsigned int ptr;
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0)
return 0;
fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
- if (fh == NULL){
+ if (fh == NULL) {
*hotdrop = 1;
return 0;
}
- DEBUGP("INFO %04X ", fh->frag_off);
- DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
- DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
- DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
- DEBUGP("ID %u %08X\n", ntohl(fh->identification),
- ntohl(fh->identification));
-
- DEBUGP("IPv6 FRAG id %02X ",
- (id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(fh->identification),
- !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
- DEBUGP("res %02X %02X%04X %02X ",
- (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
- ntohs(fh->frag_off) & 0x6,
- !((fraginfo->flags & IP6T_FRAG_RES)
- && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
- DEBUGP("first %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_FST),
- ntohs(fh->frag_off) & ~0x7,
- !((fraginfo->flags & IP6T_FRAG_FST)
- && (ntohs(fh->frag_off) & ~0x7)));
- DEBUGP("mf %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_MF),
- ntohs(fh->frag_off) & IP6_MF,
- !((fraginfo->flags & IP6T_FRAG_MF)
- && !((ntohs(fh->frag_off) & IP6_MF))));
- DEBUGP("last %02X %02X %02X\n",
- (fraginfo->flags & IP6T_FRAG_NMF),
- ntohs(fh->frag_off) & IP6_MF,
- !((fraginfo->flags & IP6T_FRAG_NMF)
- && (ntohs(fh->frag_off) & IP6_MF)));
-
- return (fh != NULL)
- &&
- (id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(fh->identification),
- !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
- &&
- !((fraginfo->flags & IP6T_FRAG_RES)
- && (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
- &&
- !((fraginfo->flags & IP6T_FRAG_FST)
- && (ntohs(fh->frag_off) & ~0x7))
- &&
- !((fraginfo->flags & IP6T_FRAG_MF)
- && !(ntohs(fh->frag_off) & IP6_MF))
- &&
- !((fraginfo->flags & IP6T_FRAG_NMF)
- && (ntohs(fh->frag_off) & IP6_MF));
+ DEBUGP("INFO %04X ", fh->frag_off);
+ DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+ DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+ DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
+ DEBUGP("ID %u %08X\n", ntohl(fh->identification),
+ ntohl(fh->identification));
+
+ DEBUGP("IPv6 FRAG id %02X ",
+ (id_match(fraginfo->ids[0], fraginfo->ids[1],
+ ntohl(fh->identification),
+ !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
+ DEBUGP("res %02X %02X%04X %02X ",
+ (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
+ ntohs(fh->frag_off) & 0x6,
+ !((fraginfo->flags & IP6T_FRAG_RES)
+ && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
+ DEBUGP("first %02X %02X %02X ",
+ (fraginfo->flags & IP6T_FRAG_FST),
+ ntohs(fh->frag_off) & ~0x7,
+ !((fraginfo->flags & IP6T_FRAG_FST)
+ && (ntohs(fh->frag_off) & ~0x7)));
+ DEBUGP("mf %02X %02X %02X ",
+ (fraginfo->flags & IP6T_FRAG_MF),
+ ntohs(fh->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_MF)
+ && !((ntohs(fh->frag_off) & IP6_MF))));
+ DEBUGP("last %02X %02X %02X\n",
+ (fraginfo->flags & IP6T_FRAG_NMF),
+ ntohs(fh->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_NMF)
+ && (ntohs(fh->frag_off) & IP6_MF)));
+
+ return (fh != NULL)
+ &&
+ (id_match(fraginfo->ids[0], fraginfo->ids[1],
+ ntohl(fh->identification),
+ !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
+ &&
+ !((fraginfo->flags & IP6T_FRAG_RES)
+ && (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
+ &&
+ !((fraginfo->flags & IP6T_FRAG_FST)
+ && (ntohs(fh->frag_off) & ~0x7))
+ &&
+ !((fraginfo->flags & IP6T_FRAG_MF)
+ && !(ntohs(fh->frag_off) & IP6_MF))
+ &&
+ !((fraginfo->flags & IP6T_FRAG_NMF)
+ && (ntohs(fh->frag_off) & IP6_MF));
}
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
+ const void *ip,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
{
- const struct ip6t_frag *fraginfo = matchinfo;
-
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) {
- DEBUGP("ip6t_frag: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag)));
- return 0;
- }
- if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
- DEBUGP("ip6t_frag: unknown flags %X\n",
- fraginfo->invflags);
- return 0;
- }
-
- return 1;
+ const struct ip6t_frag *fraginfo = matchinfo;
+
+ if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) {
+ DEBUGP("ip6t_frag: matchsize %u != %u\n",
+ matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag)));
+ return 0;
+ }
+ if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
+ DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
+ return 0;
+ }
+
+ return 1;
}
static struct ip6t_match frag_match = {
@@ -145,12 +144,12 @@ static struct ip6t_match frag_match = {
static int __init init(void)
{
- return ip6t_register_match(&frag_match);
+ return ip6t_register_match(&frag_match);
}
static void __exit cleanup(void)
{
- ip6t_unregister_match(&frag_match);
+ ip6t_unregister_match(&frag_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 1d09485111d0..37a8474a7e0c 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -36,19 +36,19 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
#endif
/*
- * (Type & 0xC0) >> 6
- * 0 -> ignorable
- * 1 -> must drop the packet
- * 2 -> send ICMP PARM PROB regardless and drop packet
- * 3 -> Send ICMP if not a multicast address and drop packet
+ * (Type & 0xC0) >> 6
+ * 0 -> ignorable
+ * 1 -> must drop the packet
+ * 2 -> send ICMP PARM PROB regardless and drop packet
+ * 3 -> Send ICMP if not a multicast address and drop packet
* (Type & 0x20) >> 5
- * 0 -> invariant
- * 1 -> can change the routing
+ * 0 -> invariant
+ * 1 -> can change the routing
* (Type & 0x1F) Type
- * 0 -> Pad1 (only 1 byte!)
- * 1 -> PadN LENGTH info (total length = length + 2)
- * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
- * 5 -> RTALERT 2 x x
+ * 0 -> Pad1 (only 1 byte!)
+ * 1 -> PadN LENGTH info (total length = length + 2)
+ * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
+ * 5 -> RTALERT 2 x x
*/
static int
@@ -60,59 +60,58 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ipv6_opt_hdr _optsh, *oh;
- const struct ip6t_opts *optinfo = matchinfo;
- unsigned int temp;
- unsigned int ptr;
- unsigned int hdrlen = 0;
- unsigned int ret = 0;
- u8 _opttype, *tp = NULL;
- u8 _optlen, *lp = NULL;
- unsigned int optlen;
-
+ struct ipv6_opt_hdr _optsh, *oh;
+ const struct ip6t_opts *optinfo = matchinfo;
+ unsigned int temp;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+ unsigned int ret = 0;
+ u8 _opttype, *tp = NULL;
+ u8 _optlen, *lp = NULL;
+ unsigned int optlen;
+
#if HOPBYHOP
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0)
#else
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0)
#endif
return 0;
- oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
- if (oh == NULL){
- *hotdrop = 1;
- return 0;
- }
-
- hdrlen = ipv6_optlen(oh);
- if (skb->len - ptr < hdrlen){
- /* Packet smaller than it's length field */
- return 0;
- }
-
- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
-
- DEBUGP("len %02X %04X %02X ",
- optinfo->hdrlen, hdrlen,
- (!(optinfo->flags & IP6T_OPTS_LEN) ||
- ((optinfo->hdrlen == hdrlen) ^
- !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
-
- ret = (oh != NULL)
- &&
- (!(optinfo->flags & IP6T_OPTS_LEN) ||
- ((optinfo->hdrlen == hdrlen) ^
- !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
-
- ptr += 2;
- hdrlen -= 2;
- if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
- return ret;
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ if (oh == NULL) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ hdrlen = ipv6_optlen(oh);
+ if (skb->len - ptr < hdrlen) {
+ /* Packet smaller than it's length field */
+ return 0;
+ }
+
+ DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
+
+ DEBUGP("len %02X %04X %02X ",
+ optinfo->hdrlen, hdrlen,
+ (!(optinfo->flags & IP6T_OPTS_LEN) ||
+ ((optinfo->hdrlen == hdrlen) ^
+ !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
+
+ ret = (oh != NULL) &&
+ (!(optinfo->flags & IP6T_OPTS_LEN) ||
+ ((optinfo->hdrlen == hdrlen) ^
+ !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
+
+ ptr += 2;
+ hdrlen -= 2;
+ if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
+ return ret;
} else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
DEBUGP("Not strict - not implemented");
} else {
DEBUGP("Strict ");
- DEBUGP("#%d ",optinfo->optsnr);
- for(temp=0; temp<optinfo->optsnr; temp++){
+ DEBUGP("#%d ", optinfo->optsnr);
+ for (temp = 0; temp < optinfo->optsnr; temp++) {
/* type field exists ? */
if (hdrlen < 1)
break;
@@ -122,10 +121,10 @@ match(const struct sk_buff *skb,
break;
/* Type check */
- if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
+ if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
DEBUGP("Tbad %02X %02X\n",
*tp,
- (optinfo->opts[temp] & 0xFF00)>>8);
+ (optinfo->opts[temp] & 0xFF00) >> 8);
return 0;
} else {
DEBUGP("Tok ");
@@ -169,7 +168,8 @@ match(const struct sk_buff *skb,
}
if (temp == optinfo->optsnr)
return ret;
- else return 0;
+ else
+ return 0;
}
return 0;
@@ -178,25 +178,24 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
+ const void *entry,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
{
- const struct ip6t_opts *optsinfo = matchinfo;
-
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
- DEBUGP("ip6t_opts: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
- return 0;
- }
- if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
- DEBUGP("ip6t_opts: unknown flags %X\n",
- optsinfo->invflags);
- return 0;
- }
-
- return 1;
+ const struct ip6t_opts *optsinfo = matchinfo;
+
+ if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
+ DEBUGP("ip6t_opts: matchsize %u != %u\n",
+ matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
+ return 0;
+ }
+ if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
+ DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
+ return 0;
+ }
+
+ return 1;
}
static struct ip6t_match opts_match = {
@@ -212,12 +211,12 @@ static struct ip6t_match opts_match = {
static int __init init(void)
{
- return ip6t_register_match(&opts_match);
+ return ip6t_register_match(&opts_match);
}
static void __exit cleanup(void)
{
- ip6t_unregister_match(&opts_match);
+ ip6t_unregister_match(&opts_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index 0beaff5471dd..c5d9079f2d9d 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in,
return 0;
}
-static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
+static int checkentry(const char *tablename, const void *entry,
void *matchinfo, unsigned int matchsize,
unsigned int hook_mask)
{
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index 32e67f05845b..83ad6b272f7e 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -50,20 +50,20 @@ ipv6header_match(const struct sk_buff *skb,
len = skb->len - ptr;
temp = 0;
- while (ip6t_ext_hdr(nexthdr)) {
+ while (ip6t_ext_hdr(nexthdr)) {
struct ipv6_opt_hdr _hdr, *hp;
- int hdrlen;
+ int hdrlen;
/* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
+ if (len < (int)sizeof(struct ipv6_opt_hdr))
+ return 0;
/* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
+ if (nexthdr == NEXTHDR_NONE) {
temp |= MASK_NONE;
break;
}
/* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
+ if (nexthdr == NEXTHDR_ESP) {
temp |= MASK_ESP;
break;
}
@@ -72,43 +72,43 @@ ipv6header_match(const struct sk_buff *skb,
BUG_ON(hp == NULL);
/* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hp->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hp);
+ if (nexthdr == NEXTHDR_FRAGMENT) {
+ hdrlen = 8;
+ } else if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = (hp->hdrlen + 2) << 2;
+ else
+ hdrlen = ipv6_optlen(hp);
/* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- temp |= MASK_HOPOPTS;
- break;
- case NEXTHDR_ROUTING:
- temp |= MASK_ROUTING;
- break;
- case NEXTHDR_FRAGMENT:
- temp |= MASK_FRAGMENT;
- break;
- case NEXTHDR_AUTH:
- temp |= MASK_AH;
- break;
- case NEXTHDR_DEST:
- temp |= MASK_DSTOPTS;
- break;
- default:
- return 0;
- break;
+ switch (nexthdr) {
+ case NEXTHDR_HOP:
+ temp |= MASK_HOPOPTS;
+ break;
+ case NEXTHDR_ROUTING:
+ temp |= MASK_ROUTING;
+ break;
+ case NEXTHDR_FRAGMENT:
+ temp |= MASK_FRAGMENT;
+ break;
+ case NEXTHDR_AUTH:
+ temp |= MASK_AH;
+ break;
+ case NEXTHDR_DEST:
+ temp |= MASK_DSTOPTS;
+ break;
+ default:
+ return 0;
+ break;
}
- nexthdr = hp->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ ptr += hdrlen;
if (ptr > skb->len)
break;
- }
+ }
- if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) )
+ if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP))
temp |= MASK_PROTO;
if (info->modeflag)
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb,
static int
ipv6header_checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
@@ -137,8 +137,8 @@ ipv6header_checkentry(const char *tablename,
return 0;
/* invflags is 0 or 0xff in hard mode */
- if ((!info->modeflag) && info->invflags != 0x00
- && info->invflags != 0xFF)
+ if ((!info->modeflag) && info->invflags != 0x00 &&
+ info->invflags != 0xFF)
return 0;
return 1;
@@ -152,7 +152,7 @@ static struct ip6t_match ip6t_ipv6header_match = {
.me = THIS_MODULE,
};
-static int __init ipv6header_init(void)
+static int __init ipv6header_init(void)
{
return ip6t_register_match(&ip6t_ipv6header_match);
}
@@ -164,4 +164,3 @@ static void __exit ipv6header_exit(void)
module_init(ipv6header_init);
module_exit(ipv6header_exit);
-
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
deleted file mode 100644
index e0537d3811d5..000000000000
--- a/net/ipv6/netfilter/ip6t_length.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Length Match - IPv6 Port */
-
-/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
- *
- * 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_ipv6/ip6t_length.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
-MODULE_DESCRIPTION("IPv6 packet length match");
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- const struct ip6t_length_info *info = matchinfo;
- u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
-
- return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
-}
-
-static int
-checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info)))
- return 0;
-
- return 1;
-}
-
-static struct ip6t_match length_match = {
- .name = "length",
- .match = &match,
- .checkentry = &checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ip6t_register_match(&length_match);
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_match(&length_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
deleted file mode 100644
index fb782f610be2..000000000000
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Kernel module to control the rate
- *
- * 2 September 1999: Changed from the target RATE to the match
- * `limit', removed logging. Did I mention that
- * Alexey is a fucking genius?
- * Rusty Russell (rusty@rustcorp.com.au). */
-
-/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
- *
- * 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 <linux/interrupt.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_limit.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
-MODULE_DESCRIPTION("rate limiting within ip6tables");
-
-/* The algorithm used is the Simple Token Bucket Filter (TBF)
- * see net/sched/sch_tbf.c in the linux source tree
- */
-
-static DEFINE_SPINLOCK(limit_lock);
-
-/* Rusty: This is my (non-mathematically-inclined) understanding of
- this algorithm. The `average rate' in jiffies becomes your initial
- amount of credit `credit' and the most credit you can ever have
- `credit_cap'. The `peak rate' becomes the cost of passing the
- test, `cost'.
-
- `prev' tracks the last packet hit: you gain one credit per jiffy.
- If you get credit balance more than this, the extra credit is
- discarded. Every time the match passes, you lose `cost' credits;
- if you don't have that many, the test fails.
-
- See Alexey's formal explanation in net/sched/sch_tbf.c.
-
- To avoid underflow, we multiply by 128 (ie. you get 128 credits per
- jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds
- at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes
- per second at 100HZ. */
-
-#define CREDITS_PER_JIFFY 128
-
-static int
-ip6t_limit_match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
- unsigned long now = jiffies;
-
- spin_lock_bh(&limit_lock);
- r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
- if (r->credit > r->credit_cap)
- r->credit = r->credit_cap;
-
- if (r->credit >= r->cost) {
- /* We're not limited. */
- r->credit -= r->cost;
- spin_unlock_bh(&limit_lock);
- return 1;
- }
-
- spin_unlock_bh(&limit_lock);
- return 0;
-}
-
-/* Precision saver. */
-static u_int32_t
-user2credits(u_int32_t user)
-{
- /* If multiplying would overflow... */
- if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
- /* Divide first. */
- return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
-
- return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE;
-}
-
-static int
-ip6t_limit_checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- struct ip6t_rateinfo *r = matchinfo;
-
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo)))
- return 0;
-
- /* Check for overflow. */
- if (r->burst == 0
- || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
- printk("Call rusty: overflow in ip6t_limit: %u/%u\n",
- r->avg, r->burst);
- return 0;
- }
-
- /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies *
- 128. */
- r->prev = jiffies;
- r->credit = user2credits(r->avg * r->burst); /* Credits full. */
- r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
- r->cost = user2credits(r->avg);
-
- /* For SMP, we only want to use one set of counters. */
- r->master = r;
-
- return 1;
-}
-
-static struct ip6t_match ip6t_limit_reg = {
- .name = "limit",
- .match = ip6t_limit_match,
- .checkentry = ip6t_limit_checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- if (ip6t_register_match(&ip6t_limit_reg))
- return -EINVAL;
- return 0;
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_match(&ip6t_limit_reg);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
deleted file mode 100644
index 526d43e37234..000000000000
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Kernel module to match MAC address parameters. */
-
-/* (C) 1999-2001 Paul `Rusty' Russell
- * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/if_ether.h>
-
-#include <linux/netfilter_ipv6/ip6t_mac.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MAC address matching module for IPv6");
-MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>");
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- const struct ip6t_mac_info *info = matchinfo;
-
- /* Is mac pointer valid? */
- return (skb->mac.raw >= skb->head
- && (skb->mac.raw + ETH_HLEN) <= skb->data
- /* If so, compare... */
- && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
- == 0) ^ info->invert));
-}
-
-static int
-ip6t_mac_checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- if (hook_mask
- & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN)
- | (1 << NF_IP6_FORWARD))) {
- printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or"
- " FORWARD\n");
- return 0;
- }
-
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info)))
- return 0;
-
- return 1;
-}
-
-static struct ip6t_match mac_match = {
- .name = "mac",
- .match = &match,
- .checkentry = &ip6t_mac_checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ip6t_register_match(&mac_match);
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_match(&mac_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
deleted file mode 100644
index affc3de364fc..000000000000
--- a/net/ipv6/netfilter/ip6t_mark.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Kernel module to match NFMARK values. */
-
-/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
- *
- * 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_ipv6/ip6t_mark.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
-MODULE_DESCRIPTION("ip6tables mark match");
-
-static int
-match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
-{
- const struct ip6t_mark_info *info = matchinfo;
-
- return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
-}
-
-static int
-checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
-{
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info)))
- return 0;
-
- return 1;
-}
-
-static struct ip6t_match mark_match = {
- .name = "mark",
- .match = &match,
- .checkentry = &checkentry,
- .me = THIS_MODULE,
-};
-
-static int __init init(void)
-{
- return ip6t_register_match(&mark_match);
-}
-
-static void __exit fini(void)
-{
- ip6t_unregister_match(&mark_match);
-}
-
-module_init(init);
-module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 6e3246153fa3..49f7829dfbc2 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
+ const void *info,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ip6t_ip6 *ip = info;
const struct ip6t_multiport *multiinfo = matchinfo;
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 4de4cdad4b7d..8c8a4c7ec934 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -36,14 +36,14 @@ match(const struct sk_buff *skb,
if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
return 0;
- if(info->match & IP6T_OWNER_UID) {
- if((skb->sk->sk_socket->file->f_uid != info->uid) ^
+ if (info->match & IP6T_OWNER_UID) {
+ if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
!!(info->invert & IP6T_OWNER_UID))
return 0;
}
- if(info->match & IP6T_OWNER_GID) {
- if((skb->sk->sk_socket->file->f_gid != info->gid) ^
+ if (info->match & IP6T_OWNER_GID) {
+ if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
!!(info->invert & IP6T_OWNER_GID))
return 0;
}
@@ -53,23 +53,23 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchsize,
- unsigned int hook_mask)
+ const void *ip,
+ void *matchinfo,
+ 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");
- return 0;
- }
+ 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");
+ return 0;
+ }
if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
return 0;
- if (info->match & (IP6T_OWNER_PID|IP6T_OWNER_SID)) {
+ if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
printk("ipt_owner: pid and sid matching "
"not supported anymore\n");
return 0;
diff --git a/net/ipv6/netfilter/ip6t_policy.c b/net/ipv6/netfilter/ip6t_policy.c
new file mode 100644
index 000000000000..afe1cc4c18a5
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_policy.c
@@ -0,0 +1,175 @@
+/* IP tables module for matching IPsec policy
+ *
+ * Copyright (c) 2004,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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <net/xfrm.h>
+
+#include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv6/ip6t_policy.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("IPtables IPsec policy matching module");
+MODULE_LICENSE("GPL");
+
+
+static inline int
+match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
+{
+#define MATCH_ADDR(x,y,z) (!e->match.x || \
+ ((ip6_masked_addrcmp((z), &e->x, &e->y)) == 0) ^ e->invert.x)
+#define MATCH(x,y) (!e->match.x || ((e->x == (y)) ^ e->invert.x))
+
+ return MATCH_ADDR(saddr, smask, (struct in6_addr *)&x->props.saddr.a6) &&
+ MATCH_ADDR(daddr, dmask, (struct in6_addr *)&x->id.daddr.a6) &&
+ MATCH(proto, x->id.proto) &&
+ MATCH(mode, x->props.mode) &&
+ MATCH(spi, x->id.spi) &&
+ MATCH(reqid, x->props.reqid);
+}
+
+static int
+match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
+{
+ const struct ip6t_policy_elem *e;
+ struct sec_path *sp = skb->sp;
+ int strict = info->flags & IP6T_POLICY_MATCH_STRICT;
+ int i, pos;
+
+ if (sp == NULL)
+ return -1;
+ if (strict && info->len != sp->len)
+ return 0;
+
+ for (i = sp->len - 1; i >= 0; i--) {
+ pos = strict ? i - sp->len + 1 : 0;
+ if (pos >= info->len)
+ return 0;
+ e = &info->pol[pos];
+
+ if (match_xfrm_state(sp->x[i].xvec, e)) {
+ if (!strict)
+ return 1;
+ } else if (strict)
+ return 0;
+ }
+
+ return strict ? 1 : 0;
+}
+
+static int
+match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
+{
+ const struct ip6t_policy_elem *e;
+ struct dst_entry *dst = skb->dst;
+ int strict = info->flags & IP6T_POLICY_MATCH_STRICT;
+ int i, pos;
+
+ if (dst->xfrm == NULL)
+ return -1;
+
+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
+ pos = strict ? i : 0;
+ if (pos >= info->len)
+ return 0;
+ e = &info->pol[pos];
+
+ if (match_xfrm_state(dst->xfrm, e)) {
+ if (!strict)
+ return 1;
+ } else if (strict)
+ return 0;
+ }
+
+ return strict ? 1 : 0;
+}
+
+static int match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ const struct ip6t_policy_info *info = matchinfo;
+ int ret;
+
+ if (info->flags & IP6T_POLICY_MATCH_IN)
+ ret = match_policy_in(skb, info);
+ else
+ ret = match_policy_out(skb, info);
+
+ if (ret < 0)
+ ret = info->flags & IP6T_POLICY_MATCH_NONE ? 1 : 0;
+ else if (info->flags & IP6T_POLICY_MATCH_NONE)
+ ret = 0;
+
+ return ret;
+}
+
+static int checkentry(const char *tablename, const void *ip_void,
+ void *matchinfo, unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ip6t_policy_info *info = matchinfo;
+
+ if (matchsize != IP6T_ALIGN(sizeof(*info))) {
+ printk(KERN_ERR "ip6t_policy: matchsize %u != %zu\n",
+ matchsize, IP6T_ALIGN(sizeof(*info)));
+ return 0;
+ }
+ if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))) {
+ printk(KERN_ERR "ip6t_policy: neither incoming nor "
+ "outgoing policy selected\n");
+ return 0;
+ }
+ if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
+ && info->flags & IP6T_POLICY_MATCH_OUT) {
+ printk(KERN_ERR "ip6t_policy: output policy not valid in "
+ "PRE_ROUTING and INPUT\n");
+ return 0;
+ }
+ if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
+ && info->flags & IP6T_POLICY_MATCH_IN) {
+ printk(KERN_ERR "ip6t_policy: input policy not valid in "
+ "POST_ROUTING and OUTPUT\n");
+ return 0;
+ }
+ if (info->len > IP6T_POLICY_MAX_ELEM) {
+ printk(KERN_ERR "ip6t_policy: too many policy elements\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct ip6t_match policy_match = {
+ .name = "policy",
+ .match = match,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ip6t_register_match(&policy_match);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_match(&policy_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index beb2fd5cebbb..8f82476dc89e 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -33,12 +33,12 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
static inline int
segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
{
- int r=0;
- DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,id,max);
- r=(id >= min && id <= max) ^ invert;
- DEBUGP(" result %s\n",r? "PASS" : "FAILED");
- return r;
+ int r = 0;
+ DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
+ invert ? '!' : ' ', min, id, max);
+ r = (id >= min && id <= max) ^ invert;
+ DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+ return r;
}
static int
@@ -50,87 +50,93 @@ match(const struct sk_buff *skb,
unsigned int protoff,
int *hotdrop)
{
- struct ipv6_rt_hdr _route, *rh;
- const struct ip6t_rt *rtinfo = matchinfo;
- unsigned int temp;
- unsigned int ptr;
- unsigned int hdrlen = 0;
- unsigned int ret = 0;
- struct in6_addr *ap, _addr;
-
- if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0)
+ struct ipv6_rt_hdr _route, *rh;
+ const struct ip6t_rt *rtinfo = matchinfo;
+ unsigned int temp;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+ unsigned int ret = 0;
+ struct in6_addr *ap, _addr;
+
+ if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0)
return 0;
- rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
- if (rh == NULL){
- *hotdrop = 1;
- return 0;
- }
-
- hdrlen = ipv6_optlen(rh);
- if (skb->len - ptr < hdrlen){
- /* Pcket smaller than its length field */
- return 0;
- }
-
- DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
- DEBUGP("TYPE %04X ", rh->type);
- DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
-
- DEBUGP("IPv6 RT segsleft %02X ",
- (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
- rh->segments_left,
- !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
- DEBUGP("type %02X %02X %02X ",
- rtinfo->rt_type, rh->type,
- (!(rtinfo->flags & IP6T_RT_TYP) ||
- ((rtinfo->rt_type == rh->type) ^
- !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
- DEBUGP("len %02X %04X %02X ",
- rtinfo->hdrlen, hdrlen,
- (!(rtinfo->flags & IP6T_RT_LEN) ||
- ((rtinfo->hdrlen == hdrlen) ^
- !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
- DEBUGP("res %02X %02X %02X ",
- (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->reserved,
- !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->reserved)));
-
- ret = (rh != NULL)
- &&
- (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
- rh->segments_left,
- !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
- &&
- (!(rtinfo->flags & IP6T_RT_LEN) ||
- ((rtinfo->hdrlen == hdrlen) ^
- !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
- &&
- (!(rtinfo->flags & IP6T_RT_TYP) ||
- ((rtinfo->rt_type == rh->type) ^
- !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
+ rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+ if (rh == NULL) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ hdrlen = ipv6_optlen(rh);
+ if (skb->len - ptr < hdrlen) {
+ /* Pcket smaller than its length field */
+ return 0;
+ }
+
+ DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+ DEBUGP("TYPE %04X ", rh->type);
+ DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
+
+ DEBUGP("IPv6 RT segsleft %02X ",
+ (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
+ rh->segments_left,
+ !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
+ DEBUGP("type %02X %02X %02X ",
+ rtinfo->rt_type, rh->type,
+ (!(rtinfo->flags & IP6T_RT_TYP) ||
+ ((rtinfo->rt_type == rh->type) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
+ DEBUGP("len %02X %04X %02X ",
+ rtinfo->hdrlen, hdrlen,
+ (!(rtinfo->flags & IP6T_RT_LEN) ||
+ ((rtinfo->hdrlen == hdrlen) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
+ DEBUGP("res %02X %02X %02X ",
+ (rtinfo->flags & IP6T_RT_RES),
+ ((struct rt0_hdr *)rh)->reserved,
+ !((rtinfo->flags & IP6T_RT_RES) &&
+ (((struct rt0_hdr *)rh)->reserved)));
+
+ ret = (rh != NULL)
+ &&
+ (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
+ rh->segments_left,
+ !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
+ &&
+ (!(rtinfo->flags & IP6T_RT_LEN) ||
+ ((rtinfo->hdrlen == hdrlen) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
+ &&
+ (!(rtinfo->flags & IP6T_RT_TYP) ||
+ ((rtinfo->rt_type == rh->type) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
if (ret && (rtinfo->flags & IP6T_RT_RES)) {
u_int32_t *rp, _reserved;
rp = skb_header_pointer(skb,
- ptr + offsetof(struct rt0_hdr, reserved),
- sizeof(_reserved), &_reserved);
+ ptr + offsetof(struct rt0_hdr,
+ reserved),
+ sizeof(_reserved),
+ &_reserved);
ret = (*rp == 0);
}
- DEBUGP("#%d ",rtinfo->addrnr);
- if ( !(rtinfo->flags & IP6T_RT_FST) ){
- return ret;
+ DEBUGP("#%d ", rtinfo->addrnr);
+ if (!(rtinfo->flags & IP6T_RT_FST)) {
+ return ret;
} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
DEBUGP("Not strict ");
- if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){
+ if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
DEBUGP("There isn't enough space\n");
return 0;
} else {
unsigned int i = 0;
- DEBUGP("#%d ",rtinfo->addrnr);
- for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
+ DEBUGP("#%d ", rtinfo->addrnr);
+ for (temp = 0;
+ temp < (unsigned int)((hdrlen - 8) / 16);
+ temp++) {
ap = skb_header_pointer(skb,
ptr
+ sizeof(struct rt0_hdr)
@@ -141,24 +147,26 @@ match(const struct sk_buff *skb,
BUG_ON(ap == NULL);
if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) {
- DEBUGP("i=%d temp=%d;\n",i,temp);
+ DEBUGP("i=%d temp=%d;\n", i, temp);
i++;
}
- if (i==rtinfo->addrnr) break;
+ if (i == rtinfo->addrnr)
+ break;
}
DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
if (i == rtinfo->addrnr)
return ret;
- else return 0;
+ else
+ return 0;
}
} else {
DEBUGP("Strict ");
- if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){
+ if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
DEBUGP("There isn't enough space\n");
return 0;
} else {
- DEBUGP("#%d ",rtinfo->addrnr);
- for(temp=0; temp<rtinfo->addrnr; temp++){
+ DEBUGP("#%d ", rtinfo->addrnr);
+ for (temp = 0; temp < rtinfo->addrnr; temp++) {
ap = skb_header_pointer(skb,
ptr
+ sizeof(struct rt0_hdr)
@@ -171,9 +179,11 @@ match(const struct sk_buff *skb,
break;
}
DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
- if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
+ if ((temp == rtinfo->addrnr) &&
+ (temp == (unsigned int)((hdrlen - 8) / 16)))
return ret;
- else return 0;
+ else
+ return 0;
}
}
@@ -183,32 +193,31 @@ match(const struct sk_buff *skb,
/* Called when user tries to insert an entry of this type. */
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
- void *matchinfo,
- unsigned int matchinfosize,
- unsigned int hook_mask)
+ const void *entry,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
{
- const struct ip6t_rt *rtinfo = matchinfo;
-
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) {
- DEBUGP("ip6t_rt: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt)));
- return 0;
- }
- if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
- DEBUGP("ip6t_rt: unknown flags %X\n",
- rtinfo->invflags);
- return 0;
- }
- if ( (rtinfo->flags & (IP6T_RT_RES|IP6T_RT_FST_MASK)) &&
- (!(rtinfo->flags & IP6T_RT_TYP) ||
- (rtinfo->rt_type != 0) ||
- (rtinfo->invflags & IP6T_RT_INV_TYP)) ) {
- DEBUGP("`--rt-type 0' required before `--rt-0-*'");
- return 0;
- }
-
- return 1;
+ const struct ip6t_rt *rtinfo = matchinfo;
+
+ if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) {
+ DEBUGP("ip6t_rt: matchsize %u != %u\n",
+ matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt)));
+ return 0;
+ }
+ if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
+ DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
+ return 0;
+ }
+ if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) &&
+ (!(rtinfo->flags & IP6T_RT_TYP) ||
+ (rtinfo->rt_type != 0) ||
+ (rtinfo->invflags & IP6T_RT_INV_TYP))) {
+ DEBUGP("`--rt-type 0' required before `--rt-0-*'");
+ return 0;
+ }
+
+ return 1;
}
static struct ip6t_match rt_match = {
@@ -220,12 +229,12 @@ static struct ip6t_match rt_match = {
static int __init init(void)
{
- return ip6t_register_match(&rt_match);
+ return ip6t_register_match(&rt_match);
}
static void __exit cleanup(void)
{
- ip6t_unregister_match(&rt_match);
+ ip6t_unregister_match(&rt_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 4c0028671c20..ce4a968e1f70 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = {
.valid_hooks = FILTER_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
+ .af = AF_INET6,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 85c1e6eada19..30a4627e000d 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = {
.valid_hooks = MANGLE_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
.me = THIS_MODULE,
+ .af = AF_INET6,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index c2982efd14af..db28ba3855e2 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -106,11 +106,12 @@ static struct
}
};
-static struct ip6t_table packet_raw = {
+static struct xt_table packet_raw = {
.name = "raw",
.valid_hooks = RAW_VALID_HOOKS,
.lock = RW_LOCK_UNLOCKED,
- .me = THIS_MODULE
+ .me = THIS_MODULE,
+ .af = AF_INET6,
};
/* The work comes in here from netfilter.c. */
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 753a3ae8502b..ac702a29dd16 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple,
static int ipv6_print_tuple(struct seq_file *s,
const struct nf_conntrack_tuple *tuple)
{
- return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ",
+ return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ",
NIP6(*((struct in6_addr *)tuple->src.u3.ip6)),
NIP6(*((struct in6_addr *)tuple->dst.u3.ip6)));
}
@@ -335,10 +335,10 @@ static struct nf_hook_ops ipv6_conntrack_local_in_ops = {
#ifdef CONFIG_SYSCTL
/* From nf_conntrack_proto_icmpv6.c */
-extern unsigned long nf_ct_icmpv6_timeout;
+extern unsigned int nf_ct_icmpv6_timeout;
/* From nf_conntrack_frag6.c */
-extern unsigned long nf_ct_frag6_timeout;
+extern unsigned int nf_ct_frag6_timeout;
extern unsigned int nf_ct_frag6_low_thresh;
extern unsigned int nf_ct_frag6_high_thresh;
@@ -401,6 +401,48 @@ static ctl_table nf_ct_net_table[] = {
};
#endif
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static int ipv6_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ NFA_PUT(skb, CTA_IP_V6_SRC, sizeof(u_int32_t) * 4,
+ &tuple->src.u3.ip6);
+ NFA_PUT(skb, CTA_IP_V6_DST, sizeof(u_int32_t) * 4,
+ &tuple->dst.u3.ip6);
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static const size_t cta_min_ip[CTA_IP_MAX] = {
+ [CTA_IP_V6_SRC-1] = sizeof(u_int32_t)*4,
+ [CTA_IP_V6_DST-1] = sizeof(u_int32_t)*4,
+};
+
+static int ipv6_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t)
+{
+ if (!tb[CTA_IP_V6_SRC-1] || !tb[CTA_IP_V6_DST-1])
+ return -EINVAL;
+
+ if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
+ return -EINVAL;
+
+ memcpy(&t->src.u3.ip6, NFA_DATA(tb[CTA_IP_V6_SRC-1]),
+ sizeof(u_int32_t) * 4);
+ memcpy(&t->dst.u3.ip6, NFA_DATA(tb[CTA_IP_V6_DST-1]),
+ sizeof(u_int32_t) * 4);
+
+ return 0;
+}
+#endif
+
struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
.l3proto = PF_INET6,
.name = "ipv6",
@@ -409,6 +451,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
.print_tuple = ipv6_print_tuple,
.print_conntrack = ipv6_print_conntrack,
.prepare = ipv6_prepare,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = ipv6_tuple_to_nfattr,
+ .nfattr_to_tuple = ipv6_nfattr_to_tuple,
+#endif
.get_features = ipv6_get_features,
.me = THIS_MODULE,
};
@@ -537,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
static int __init init(void)
{
- need_nf_conntrack();
+ need_conntrack();
return init_or_cleanup(1);
}
@@ -548,9 +595,3 @@ static void __exit fini(void)
module_init(init);
module_exit(fini);
-
-void need_ip6_conntrack(void)
-{
-}
-
-EXPORT_SYMBOL(need_ip6_conntrack);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index a7e03cfacd06..09945c333055 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -57,17 +57,17 @@ static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
return 1;
}
+/* Add 1; spaces filled with 0. */
+static u_int8_t invmap[] = {
+ [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
+ [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
+ [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
+ [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1
+};
+
static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
- /* Add 1; spaces filled with 0. */
- static u_int8_t invmap[] = {
- [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
- [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
- [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
- [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1
- };
-
int type = orig->dst.u.icmp.type - 128;
if (type < 0 || type >= sizeof(invmap) || !invmap[type])
return 0;
@@ -185,7 +185,7 @@ icmpv6_error_message(struct sk_buff *skb,
return -NF_ACCEPT;
}
- inproto = nf_ct_find_proto(PF_INET6, inprotonum);
+ inproto = __nf_ct_proto_find(PF_INET6, inprotonum);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
@@ -255,6 +255,60 @@ skipped:
return icmpv6_error_message(skb, dataoff, ctinfo, hooknum);
}
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+static int icmpv6_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *t)
+{
+ NFA_PUT(skb, CTA_PROTO_ICMPV6_ID, sizeof(u_int16_t),
+ &t->src.u.icmp.id);
+ NFA_PUT(skb, CTA_PROTO_ICMPV6_TYPE, sizeof(u_int8_t),
+ &t->dst.u.icmp.type);
+ NFA_PUT(skb, CTA_PROTO_ICMPV6_CODE, sizeof(u_int8_t),
+ &t->dst.u.icmp.code);
+
+ return 0;
+
+nfattr_failure:
+ return -1;
+}
+
+static const size_t cta_min_proto[CTA_PROTO_MAX] = {
+ [CTA_PROTO_ICMPV6_TYPE-1] = sizeof(u_int8_t),
+ [CTA_PROTO_ICMPV6_CODE-1] = sizeof(u_int8_t),
+ [CTA_PROTO_ICMPV6_ID-1] = sizeof(u_int16_t)
+};
+
+static int icmpv6_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *tuple)
+{
+ if (!tb[CTA_PROTO_ICMPV6_TYPE-1]
+ || !tb[CTA_PROTO_ICMPV6_CODE-1]
+ || !tb[CTA_PROTO_ICMPV6_ID-1])
+ return -EINVAL;
+
+ if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+ return -EINVAL;
+
+ tuple->dst.u.icmp.type =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_TYPE-1]);
+ tuple->dst.u.icmp.code =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]);
+ tuple->src.u.icmp.id =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]);
+
+ if (tuple->dst.u.icmp.type < 128
+ || tuple->dst.u.icmp.type - 128 >= sizeof(invmap)
+ || !invmap[tuple->dst.u.icmp.type - 128])
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
{
.l3proto = PF_INET6,
@@ -267,6 +321,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
.packet = icmpv6_packet,
.new = icmpv6_new,
.error = icmpv6_error,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = icmpv6_tuple_to_nfattr,
+ .nfattr_to_tuple = icmpv6_nfattr_to_tuple,
+#endif
};
EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index c2c52af9e560..84ef9a13108d 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb
struct nf_ct_frag6_queue
{
- struct nf_ct_frag6_queue *next;
- struct list_head lru_list; /* lru list member */
+ struct hlist_node list;
+ struct list_head lru_list; /* lru list member */
__u32 id; /* fragment id */
struct in6_addr saddr;
@@ -90,24 +90,21 @@ struct nf_ct_frag6_queue
#define FIRST_IN 2
#define LAST_IN 1
__u16 nhoffset;
- struct nf_ct_frag6_queue **pprev;
};
/* Hash table. */
#define FRAG6Q_HASHSZ 64
-static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ];
-static rwlock_t nf_ct_frag6_lock = RW_LOCK_UNLOCKED;
+static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
+static DEFINE_RWLOCK(nf_ct_frag6_lock);
static u32 nf_ct_frag6_hash_rnd;
static LIST_HEAD(nf_ct_frag6_lru_list);
int nf_ct_frag6_nqueues = 0;
static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq)
{
- if (fq->next)
- fq->next->pprev = fq->pprev;
- *fq->pprev = fq->next;
+ hlist_del(&fq->list);
list_del(&fq->lru_list);
nf_ct_frag6_nqueues--;
}
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy)
get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32));
for (i = 0; i < FRAG6Q_HASHSZ; i++) {
struct nf_ct_frag6_queue *q;
+ struct hlist_node *p, *n;
- q = nf_ct_frag6_hash[i];
- while (q) {
- struct nf_ct_frag6_queue *next = q->next;
+ hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) {
unsigned int hval = ip6qhashfn(q->id,
&q->saddr,
&q->daddr);
-
if (hval != i) {
- /* Unlink. */
- if (q->next)
- q->next->pprev = q->pprev;
- *q->pprev = q->next;
-
+ hlist_del(&q->list);
/* Relink to new hash chain. */
- if ((q->next = nf_ct_frag6_hash[hval]) != NULL)
- q->next->pprev = &q->next;
- nf_ct_frag6_hash[hval] = q;
- q->pprev = &nf_ct_frag6_hash[hval];
+ hlist_add_head(&q->list,
+ &nf_ct_frag6_hash[hval]);
}
-
- q = next;
}
}
write_unlock(&nf_ct_frag6_lock);
@@ -314,15 +301,17 @@ out:
/* Creation primitives. */
-
static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
struct nf_ct_frag6_queue *fq_in)
{
struct nf_ct_frag6_queue *fq;
+#ifdef CONFIG_SMP
+ struct hlist_node *n;
+#endif
write_lock(&nf_ct_frag6_lock);
#ifdef CONFIG_SMP
- for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) {
+ hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
if (fq->id == fq_in->id &&
!ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
!ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash,
atomic_inc(&fq->refcnt);
atomic_inc(&fq->refcnt);
- if ((fq->next = nf_ct_frag6_hash[hash]) != NULL)
- fq->next->pprev = &fq->next;
- nf_ct_frag6_hash[hash] = fq;
- fq->pprev = &nf_ct_frag6_hash[hash];
+ hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]);
INIT_LIST_HEAD(&fq->lru_list);
list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list);
nf_ct_frag6_nqueues++;
@@ -371,7 +357,7 @@ nf_ct_frag6_create(unsigned int hash, u32 id, struct in6_addr *src, struct
init_timer(&fq->timer);
fq->timer.function = nf_ct_frag6_expire;
fq->timer.data = (long) fq;
- fq->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&fq->lock);
atomic_set(&fq->refcnt, 1);
return nf_ct_frag6_intern(hash, fq);
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue *
fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
{
struct nf_ct_frag6_queue *fq;
+ struct hlist_node *n;
unsigned int hash = ip6qhashfn(id, src, dst);
read_lock(&nf_ct_frag6_lock);
- for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) {
+ hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) {
if (fq->id == id &&
!ipv6_addr_cmp(src, &fq->saddr) &&
!ipv6_addr_cmp(dst, &fq->daddr)) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a66900cda2af..66f1d12ea578 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -32,6 +32,7 @@
#include <linux/icmpv6.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
+#include <linux/skbuff.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
#include <asm/bug.h>
@@ -433,25 +434,14 @@ out:
return err;
csum_copy_err:
- /* Clear queue. */
- if (flags&MSG_PEEK) {
- int clear = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- if (skb == skb_peek(&sk->sk_receive_queue)) {
- __skb_unlink(skb, &sk->sk_receive_queue);
- clear = 1;
- }
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- if (clear)
- kfree_skb(skb);
- }
+ skb_kill_datagram(sk, skb, flags);
/* Error for blocking case is chosen to masquerade
as some normal condition.
*/
err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
/* FIXME: increment a raw6 drops counter here */
- goto out_free;
+ goto out;
}
static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 5d316cb72ec9..15e1456b3f18 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -581,7 +581,6 @@ err:
* the last and the first frames arrived and all the bits are here.
*/
static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
- unsigned int *nhoffp,
struct net_device *dev)
{
struct sk_buff *fp, *head = fq->fragments;
@@ -654,6 +653,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
head->dev = dev;
skb_set_timestamp(head, &fq->stamp);
head->nh.ipv6h->payload_len = htons(payload_len);
+ IP6CB(head)->nhoff = nhoff;
*skb_in = head;
@@ -663,7 +663,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
fq->fragments = NULL;
- *nhoffp = nhoff;
return 1;
out_oversize:
@@ -678,7 +677,7 @@ out_fail:
return -1;
}
-static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
+static int ipv6_frag_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
struct net_device *dev = skb->dev;
@@ -710,7 +709,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
skb->h.raw += sizeof(struct frag_hdr);
IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
- *nhoffp = (u8*)fhdr - skb->nh.raw;
+ IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw;
return 1;
}
@@ -722,11 +721,11 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
spin_lock(&fq->lock);
- ip6_frag_queue(fq, skb, fhdr, *nhoffp);
+ ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
if (fq->last_in == (FIRST_IN|LAST_IN) &&
fq->meat == fq->len)
- ret = ip6_frag_reasm(fq, skbp, nhoffp, dev);
+ ret = ip6_frag_reasm(fq, skbp, dev);
spin_unlock(&fq->lock);
fq_put(fq, NULL);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 66140f13d119..e0d3ad02ffb5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -24,6 +24,7 @@
* reachable. otherwise, round-robin the list.
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/types.h>
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index c3123c9e1a8e..c2d3e17beae6 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -20,6 +20,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -33,6 +34,7 @@
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/netfilter_ipv4.h>
+#include <linux/if_ether.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -183,7 +185,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
if (dev == NULL)
return NULL;
- nt = dev->priv;
+ nt = netdev_priv(dev);
dev->init = ipip6_tunnel_init;
nt->parms = *parms;
@@ -209,7 +211,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
write_unlock_bh(&ipip6_lock);
dev_put(dev);
} else {
- ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv);
+ ipip6_tunnel_unlink(netdev_priv(dev));
dev_put(dev);
}
}
@@ -345,7 +347,7 @@ out:
rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0);
if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) {
- struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv;
+ struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev);
if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) {
rel_type = ICMPV6_DEST_UNREACH;
rel_code = ICMPV6_ADDR_UNREACH;
@@ -380,6 +382,7 @@ static int ipip6_rcv(struct sk_buff *skb)
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+ IPCB(skb)->flags = 0;
skb->protocol = htons(ETH_P_IPV6);
skb->pkt_type = PACKET_HOST;
tunnel->stat.rx_packets++;
@@ -422,7 +425,7 @@ static inline u32 try_6to4(struct in6_addr *v6dst)
static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct net_device_stats *stats = &tunnel->stat;
struct iphdr *tiph = &tunnel->parms.iph;
struct ipv6hdr *iph6 = skb->nh.ipv6h;
@@ -551,6 +554,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
skb->h.raw = skb->nh.raw;
skb->nh.raw = skb_push(skb, sizeof(struct iphdr));
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags = 0;
dst_release(skb->dst);
skb->dst = &rt->u.dst;
@@ -607,7 +611,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
t = ipip6_tunnel_locate(&p, 0);
}
if (t == NULL)
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
memcpy(&p, &t->parms, sizeof(p));
if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p)))
err = -EFAULT;
@@ -644,7 +648,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
err = -EINVAL;
break;
}
- t = (struct ip_tunnel*)dev->priv;
+ t = netdev_priv(dev);
ipip6_tunnel_unlink(t);
t->parms.iph.saddr = p.iph.saddr;
t->parms.iph.daddr = p.iph.daddr;
@@ -680,7 +684,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
if ((t = ipip6_tunnel_locate(&p, 0)) == NULL)
goto done;
err = -EPERM;
- if (t == ipip6_fb_tunnel_dev->priv)
+ if (t == netdev_priv(ipip6_fb_tunnel_dev))
goto done;
dev = t->dev;
}
@@ -697,7 +701,7 @@ done:
static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev)
{
- return &(((struct ip_tunnel*)dev->priv)->stat);
+ return &(((struct ip_tunnel*)netdev_priv(dev))->stat);
}
static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
@@ -720,7 +724,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
dev->type = ARPHRD_SIT;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
- dev->mtu = 1500 - sizeof(struct iphdr);
+ dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr);
dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4;
@@ -732,7 +736,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
struct ip_tunnel *tunnel;
struct iphdr *iph;
- tunnel = (struct ip_tunnel*)dev->priv;
+ tunnel = netdev_priv(dev);
iph = &tunnel->parms.iph;
tunnel->dev = dev;
@@ -772,7 +776,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
static int __init ipip6_fb_tunnel_init(struct net_device *dev)
{
- struct ip_tunnel *tunnel = dev->priv;
+ struct ip_tunnel *tunnel = netdev_priv(dev);
struct iphdr *iph = &tunnel->parms.iph;
tunnel->dev = dev;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 8827389abaf7..66d04004afda 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -48,6 +48,7 @@
#include <net/tcp.h>
#include <net/ndisc.h>
#include <net/inet6_hashtables.h>
+#include <net/inet6_connection_sock.h>
#include <net/ipv6.h>
#include <net/transp_v6.h>
#include <net/addrconf.h>
@@ -59,232 +60,45 @@
#include <net/addrconf.h>
#include <net/snmp.h>
#include <net/dsfield.h>
+#include <net/timewait_sock.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+/* Socket used for sending RSTs and ACKs */
+static struct socket *tcp6_socket;
+
static void tcp_v6_send_reset(struct sk_buff *skb);
static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
-static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
+static void tcp_v6_send_check(struct sock *sk, int len,
struct sk_buff *skb);
static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
-static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok);
-
-static struct tcp_func ipv6_mapped;
-static struct tcp_func ipv6_specific;
-
-static inline int tcp_v6_bind_conflict(const struct sock *sk,
- const struct inet_bind_bucket *tb)
-{
- 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) {
- if (sk != sk2 &&
- (!sk->sk_bound_dev_if ||
- !sk2->sk_bound_dev_if ||
- sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
- (!sk->sk_reuse || !sk2->sk_reuse ||
- sk2->sk_state == TCP_LISTEN) &&
- ipv6_rcv_saddr_equal(sk, sk2))
- break;
- }
- return node != NULL;
-}
+static struct inet_connection_sock_af_ops ipv6_mapped;
+static struct inet_connection_sock_af_ops ipv6_specific;
-/* Grrr, addr_type already calculated by caller, but I don't want
- * to add some silly "cookie" argument to this method just for that.
- * But it doesn't matter, the recalculation is in the rarest path
- * this function ever takes.
- */
static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
{
- struct inet_bind_hashbucket *head;
- struct inet_bind_bucket *tb;
- struct hlist_node *node;
- int ret;
-
- local_bh_disable();
- if (snum == 0) {
- int low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int remaining = (high - low) + 1;
- int rover = net_random() % (high - low) + low;
-
- do {
- head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_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);
- if (++rover > high)
- rover = low;
- } while (--remaining > 0);
-
- /* 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. */
- snum = rover;
- } else {
- head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_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 (tb && !hlist_empty(&tb->owners)) {
- if (tb->fastreuse > 0 && sk->sk_reuse &&
- sk->sk_state != TCP_LISTEN) {
- goto success;
- } else {
- ret = 1;
- if (tcp_v6_bind_conflict(sk, tb))
- goto fail_unlock;
- }
- }
-tb_not_found:
- ret = 1;
- 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;
- 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;
-}
-
-static __inline__ void __tcp_v6_hash(struct sock *sk)
-{
- struct hlist_head *list;
- rwlock_t *lock;
-
- BUG_TRAP(sk_unhashed(sk));
-
- if (sk->sk_state == TCP_LISTEN) {
- list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)];
- lock = &tcp_hashinfo.lhash_lock;
- inet_listen_wlock(&tcp_hashinfo);
- } else {
- unsigned int hash;
- sk->sk_hash = hash = inet6_sk_ehashfn(sk);
- hash &= (tcp_hashinfo.ehash_size - 1);
- list = &tcp_hashinfo.ehash[hash].chain;
- lock = &tcp_hashinfo.ehash[hash].lock;
- write_lock(lock);
- }
-
- __sk_add_node(sk, list);
- sock_prot_inc_use(sk->sk_prot);
- write_unlock(lock);
+ return inet_csk_get_port(&tcp_hashinfo, sk, snum,
+ inet6_csk_bind_conflict);
}
-
static void tcp_v6_hash(struct sock *sk)
{
if (sk->sk_state != TCP_CLOSE) {
- struct tcp_sock *tp = tcp_sk(sk);
-
- if (tp->af_specific == &ipv6_mapped) {
+ if (inet_csk(sk)->icsk_af_ops == &ipv6_mapped) {
tcp_prot.hash(sk);
return;
}
local_bh_disable();
- __tcp_v6_hash(sk);
+ __inet6_hash(&tcp_hashinfo, sk);
local_bh_enable();
}
}
-/*
- * Open request hash tables.
- */
-
-static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd)
-{
- u32 a, b, c;
-
- a = raddr->s6_addr32[0];
- b = raddr->s6_addr32[1];
- c = raddr->s6_addr32[2];
-
- a += JHASH_GOLDEN_RATIO;
- b += JHASH_GOLDEN_RATIO;
- c += rnd;
- __jhash_mix(a, b, c);
-
- a += raddr->s6_addr32[3];
- b += (u32) rport;
- __jhash_mix(a, b, c);
-
- return c & (TCP_SYNQ_HSIZE - 1);
-}
-
-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)
-{
- 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)];
- (req = *prev) != NULL;
- prev = &req->dl_next) {
- const struct tcp6_request_sock *treq = tcp6_rsk(req);
-
- if (inet_rsk(req)->rmt_port == rport &&
- req->rsk_ops->family == AF_INET6 &&
- ipv6_addr_equal(&treq->rmt_addr, raddr) &&
- ipv6_addr_equal(&treq->loc_addr, laddr) &&
- (!treq->iif || treq->iif == iif)) {
- BUG_TRAP(req->sk == NULL);
- *prevp = prev;
- return req;
- }
- }
-
- return NULL;
-}
-
static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
struct in6_addr *saddr,
struct in6_addr *daddr,
@@ -308,195 +122,12 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
}
}
-static int __tcp_v6_check_established(struct sock *sk, const __u16 lport,
- struct inet_timewait_sock **twp)
-{
- struct inet_sock *inet = inet_sk(sk);
- 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);
- unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport);
- struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
- struct sock *sk2;
- const struct hlist_node *node;
- struct inet_timewait_sock *tw;
-
- prefetch(head->chain.first);
- write_lock(&head->lock);
-
- /* Check TIME-WAIT sockets first. */
- 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(&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 (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 = tcptw->tw_snd_nxt + 65535 + 2;
- if (!tp->write_seq)
- tp->write_seq = 1;
- 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
- goto not_unique;
- }
- }
- tw = NULL;
-
- /* And established part... */
- sk_for_each(sk2, node, &head->chain) {
- if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif))
- goto not_unique;
- }
-
-unique:
- BUG_TRAP(sk_unhashed(sk));
- __sk_add_node(sk, &head->chain);
- sk->sk_hash = hash;
- sock_prot_inc_use(sk->sk_prot);
- write_unlock(&head->lock);
-
- if (twp) {
- *twp = tw;
- NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
- } else if (tw) {
- /* Silly. Should hash-dance instead... */
- inet_twsk_deschedule(tw, &tcp_death_row);
- NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
-
- inet_twsk_put(tw);
- }
- return 0;
-
-not_unique:
- write_unlock(&head->lock);
- return -EADDRNOTAVAIL;
-}
-
-static inline u32 tcpv6_port_offset(const struct sock *sk)
-{
- const struct inet_sock *inet = inet_sk(sk);
- const struct ipv6_pinfo *np = inet6_sk(sk);
-
- return secure_tcpv6_port_ephemeral(np->rcv_saddr.s6_addr32,
- np->daddr.s6_addr32,
- inet->dport);
-}
-
-static int tcp_v6_hash_connect(struct sock *sk)
-{
- unsigned short snum = inet_sk(sk)->num;
- struct inet_bind_hashbucket *head;
- struct inet_bind_bucket *tb;
- int ret;
-
- if (!snum) {
- int low = sysctl_local_port_range[0];
- int high = sysctl_local_port_range[1];
- int range = high - low;
- int i;
- int port;
- static u32 hint;
- u32 offset = hint + tcpv6_port_offset(sk);
- struct hlist_node *node;
- struct inet_timewait_sock *tw = NULL;
-
- local_bh_disable();
- for (i = 1; i <= range; i++) {
- port = low + (i + offset) % range;
- 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.
- */
- inet_bind_bucket_for_each(tb, node, &head->chain) {
- if (tb->port == port) {
- BUG_TRAP(!hlist_empty(&tb->owners));
- if (tb->fastreuse >= 0)
- goto next_port;
- if (!__tcp_v6_check_established(sk,
- port,
- &tw))
- goto ok;
- goto next_port;
- }
- }
-
- tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
- if (!tb) {
- spin_unlock(&head->lock);
- break;
- }
- tb->fastreuse = -1;
- goto ok;
-
- next_port:
- spin_unlock(&head->lock);
- }
- local_bh_enable();
-
- return -EADDRNOTAVAIL;
-
-ok:
- hint += i;
-
- /* Head lock still held and bh's disabled */
- inet_bind_hash(sk, tb, port);
- if (sk_unhashed(sk)) {
- inet_sk(sk)->sport = htons(port);
- __tcp_v6_hash(sk);
- }
- spin_unlock(&head->lock);
-
- if (tw) {
- inet_twsk_deschedule(tw, &tcp_death_row);
- inet_twsk_put(tw);
- }
-
- ret = 0;
- goto out;
- }
-
- 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_v6_hash(sk);
- spin_unlock_bh(&head->lock);
- return 0;
- } else {
- spin_unlock(&head->lock);
- /* No definite answer... Walk to established hash table */
- ret = __tcp_v6_check_established(sk, snum, NULL);
-out:
- local_bh_enable();
- return ret;
- }
-}
-
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
int addr_len)
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
- struct inet_sock *inet = inet_sk(sk);
+ struct inet_sock *inet = inet_sk(sk);
+ struct inet_connection_sock *icsk = inet_csk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct in6_addr *saddr = NULL, *final_p = NULL, final;
@@ -571,7 +202,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
*/
if (addr_type == IPV6_ADDR_MAPPED) {
- u32 exthdrlen = tp->ext_header_len;
+ u32 exthdrlen = icsk->icsk_ext_hdr_len;
struct sockaddr_in sin;
SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
@@ -583,14 +214,14 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
sin.sin_port = usin->sin6_port;
sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
- tp->af_specific = &ipv6_mapped;
+ icsk->icsk_af_ops = &ipv6_mapped;
sk->sk_backlog_rcv = tcp_v4_do_rcv;
err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
if (err) {
- tp->ext_header_len = exthdrlen;
- tp->af_specific = &ipv6_specific;
+ icsk->icsk_ext_hdr_len = exthdrlen;
+ icsk->icsk_af_ops = &ipv6_specific;
sk->sk_backlog_rcv = tcp_v6_do_rcv;
goto failure;
} else {
@@ -643,16 +274,17 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
sk->sk_route_caps = dst->dev->features &
~(NETIF_F_IP_CSUM | NETIF_F_TSO);
- tp->ext_header_len = 0;
+ icsk->icsk_ext_hdr_len = 0;
if (np->opt)
- tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
+ icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
+ np->opt->opt_nflen);
tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
inet->dport = usin->sin6_port;
tcp_set_state(sk, TCP_SYN_SENT);
- err = tcp_v6_hash_connect(sk);
+ err = inet6_hash_connect(&tcp_death_row, sk);
if (err)
goto late_failure;
@@ -758,7 +390,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
} else
dst_hold(dst);
- if (tp->pmtu_cookie > dst_mtu(dst)) {
+ if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
tcp_sync_mss(sk, dst_mtu(dst));
tcp_simple_retransmit(sk);
} /* else let the usual retransmit timer handle it */
@@ -775,8 +407,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(sk, &prev, th->dest, &hdr->daddr,
- &hdr->saddr, inet6_iif(skb));
+ req = inet6_csk_search_req(sk, &prev, th->dest, &hdr->daddr,
+ &hdr->saddr, inet6_iif(skb));
if (!req)
goto out;
@@ -822,7 +454,7 @@ out:
static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
struct dst_entry *dst)
{
- struct tcp6_request_sock *treq = tcp6_rsk(req);
+ struct inet6_request_sock *treq = inet6_rsk(req);
struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff * skb;
struct ipv6_txoptions *opt = NULL;
@@ -888,8 +520,8 @@ done:
static void tcp_v6_reqsk_destructor(struct request_sock *req)
{
- if (tcp6_rsk(req)->pktopts)
- kfree_skb(tcp6_rsk(req)->pktopts);
+ if (inet6_rsk(req)->pktopts)
+ kfree_skb(inet6_rsk(req)->pktopts);
}
static struct request_sock_ops tcp6_request_sock_ops = {
@@ -901,26 +533,15 @@ static struct request_sock_ops tcp6_request_sock_ops = {
.send_reset = tcp_v6_send_reset
};
-static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct inet6_skb_parm *opt = IP6CB(skb);
-
- if (np->rxopt.all) {
- 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;
-}
-
+static struct timewait_sock_ops tcp6_timewait_sock_ops = {
+ .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
+ .twsk_unique = tcp_twsk_unique,
+};
-static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
- struct sk_buff *skb)
+static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
+ struct tcphdr *th = skb->h.th;
if (skb->ip_summed == CHECKSUM_HW) {
th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
@@ -993,7 +614,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(NULL, buff, &fl, NULL, 0);
+ ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
return;
@@ -1057,7 +678,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(NULL, buff, &fl, NULL, 0);
+ ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return;
}
@@ -1091,8 +712,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
struct sock *nsk;
/* Find possible connection requests. */
- req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
- &skb->nh.ipv6h->daddr, inet6_iif(skb));
+ req = inet6_csk_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);
@@ -1116,23 +738,12 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
return sk;
}
-static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
-{
- 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(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT);
- inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT);
-}
-
-
/* FIXME: this is substantially similar to the ipv4 code.
* Can some kind of merge be done? -- erics
*/
static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
{
- struct tcp6_request_sock *treq;
+ struct inet6_request_sock *treq;
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_options_received tmp_opt;
struct tcp_sock *tp = tcp_sk(sk);
@@ -1157,7 +768,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
goto drop;
- req = reqsk_alloc(&tcp6_request_sock_ops);
+ req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
if (req == NULL)
goto drop;
@@ -1170,7 +781,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
tcp_openreq_init(req, &tmp_opt, skb);
- treq = tcp6_rsk(req);
+ treq = inet6_rsk(req);
ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
TCP_ECN_create_request(req, skb->h.th);
@@ -1196,8 +807,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (tcp_v6_send_synack(sk, req, NULL))
goto drop;
- tcp_v6_synq_add(sk, req);
-
+ inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
return 0;
drop:
@@ -1212,7 +822,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
{
- struct tcp6_request_sock *treq = tcp6_rsk(req);
+ struct inet6_request_sock *treq = inet6_rsk(req);
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct tcp6_sock *newtcp6sk;
struct inet_sock *newinet;
@@ -1247,7 +857,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
- newtp->af_specific = &ipv6_mapped;
+ inet_csk(newsk)->icsk_af_ops = &ipv6_mapped;
newsk->sk_backlog_rcv = tcp_v4_do_rcv;
newnp->pktoptions = NULL;
newnp->opt = NULL;
@@ -1261,10 +871,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
*/
/* It is tricky place. Until this moment IPv4 tcp
- worked with IPv6 af_tcp.af_specific.
+ worked with IPv6 icsk.icsk_af_ops.
Sync it now.
*/
- tcp_sync_mss(newsk, newtp->pmtu_cookie);
+ tcp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
return newsk;
}
@@ -1371,10 +981,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
sock_kfree_s(sk, opt, opt->tot_len);
}
- newtp->ext_header_len = 0;
+ inet_csk(newsk)->icsk_ext_hdr_len = 0;
if (newnp->opt)
- newtp->ext_header_len = newnp->opt->opt_nflen +
- newnp->opt->opt_flen;
+ inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
+ newnp->opt->opt_flen);
tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
@@ -1382,7 +992,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);
+ __inet6_hash(&tcp_hashinfo, newsk);
inet_inherit_port(&tcp_hashinfo, sk, newsk);
return newsk;
@@ -1546,7 +1156,7 @@ ipv6_pktoptions:
return 0;
}
-static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int tcp_v6_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct tcphdr *th;
@@ -1679,139 +1289,16 @@ do_time_wait:
goto discard_it;
}
-static int tcp_v6_rebuild_header(struct sock *sk)
-{
- int err;
- struct dst_entry *dst;
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- dst = __sk_dst_check(sk, np->dst_cookie);
-
- if (dst == NULL) {
- struct inet_sock *inet = inet_sk(sk);
- struct in6_addr *final_p = NULL, final;
- struct flowi fl;
-
- memset(&fl, 0, sizeof(fl));
- fl.proto = IPPROTO_TCP;
- ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
- ipv6_addr_copy(&fl.fl6_src, &np->saddr);
- fl.fl6_flowlabel = np->flow_label;
- fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_dport = inet->dport;
- fl.fl_ip_sport = inet->sport;
-
- if (np->opt && np->opt->srcrt) {
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- ipv6_addr_copy(&final, &fl.fl6_dst);
- ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
- final_p = &final;
- }
-
- err = ip6_dst_lookup(sk, &dst, &fl);
- if (err) {
- sk->sk_route_caps = 0;
- return err;
- }
- if (final_p)
- ipv6_addr_copy(&fl.fl6_dst, final_p);
-
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
- sk->sk_err_soft = -err;
- return err;
- }
-
- ip6_dst_store(sk, dst, NULL);
- sk->sk_route_caps = dst->dev->features &
- ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
- }
-
- return 0;
-}
-
-static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
-{
- struct sock *sk = skb->sk;
- struct inet_sock *inet = inet_sk(sk);
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct flowi fl;
- struct dst_entry *dst;
- struct in6_addr *final_p = NULL, final;
-
- memset(&fl, 0, sizeof(fl));
- fl.proto = IPPROTO_TCP;
- ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
- ipv6_addr_copy(&fl.fl6_src, &np->saddr);
- fl.fl6_flowlabel = np->flow_label;
- IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
- fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_sport = inet->sport;
- fl.fl_ip_dport = inet->dport;
-
- if (np->opt && np->opt->srcrt) {
- struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
- ipv6_addr_copy(&final, &fl.fl6_dst);
- ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
- final_p = &final;
- }
-
- dst = __sk_dst_check(sk, np->dst_cookie);
-
- if (dst == NULL) {
- int err = ip6_dst_lookup(sk, &dst, &fl);
-
- if (err) {
- sk->sk_err_soft = -err;
- return err;
- }
-
- if (final_p)
- ipv6_addr_copy(&fl.fl6_dst, final_p);
-
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
- sk->sk_route_caps = 0;
- return err;
- }
-
- ip6_dst_store(sk, dst, NULL);
- sk->sk_route_caps = dst->dev->features &
- ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
- }
-
- skb->dst = dst_clone(dst);
-
- /* Restore final destination back after routing done */
- ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-
- return ip6_xmit(sk, skb, &fl, np->opt, 0);
-}
-
-static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr;
-
- sin6->sin6_family = AF_INET6;
- ipv6_addr_copy(&sin6->sin6_addr, &np->daddr);
- sin6->sin6_port = inet_sk(sk)->dport;
- /* We do not store received flowlabel for TCP */
- sin6->sin6_flowinfo = 0;
- sin6->sin6_scope_id = 0;
- if (sk->sk_bound_dev_if &&
- ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
- sin6->sin6_scope_id = sk->sk_bound_dev_if;
-}
-
static int tcp_v6_remember_stamp(struct sock *sk)
{
/* Alas, not yet... */
return 0;
}
-static struct tcp_func ipv6_specific = {
- .queue_xmit = tcp_v6_xmit,
+static struct inet_connection_sock_af_ops ipv6_specific = {
+ .queue_xmit = inet6_csk_xmit,
.send_check = tcp_v6_send_check,
- .rebuild_header = tcp_v6_rebuild_header,
+ .rebuild_header = inet6_sk_rebuild_header,
.conn_request = tcp_v6_conn_request,
.syn_recv_sock = tcp_v6_syn_recv_sock,
.remember_stamp = tcp_v6_remember_stamp,
@@ -1819,7 +1306,7 @@ static struct tcp_func ipv6_specific = {
.setsockopt = ipv6_setsockopt,
.getsockopt = ipv6_getsockopt,
- .addr2sockaddr = v6_addr2sockaddr,
+ .addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6)
};
@@ -1827,7 +1314,7 @@ static struct tcp_func ipv6_specific = {
* TCP over IPv4 via INET6 API
*/
-static struct tcp_func ipv6_mapped = {
+static struct inet_connection_sock_af_ops ipv6_mapped = {
.queue_xmit = ip_queue_xmit,
.send_check = tcp_v4_send_check,
.rebuild_header = inet_sk_rebuild_header,
@@ -1838,7 +1325,7 @@ static struct tcp_func ipv6_mapped = {
.setsockopt = ipv6_setsockopt,
.getsockopt = ipv6_getsockopt,
- .addr2sockaddr = v6_addr2sockaddr,
+ .addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6)
};
@@ -1877,8 +1364,9 @@ static int tcp_v6_init_sock(struct sock *sk)
sk->sk_state = TCP_CLOSE;
- tp->af_specific = &ipv6_specific;
+ icsk->icsk_af_ops = &ipv6_specific;
icsk->icsk_ca_ops = &tcp_init_congestion_ops;
+ icsk->icsk_sync_mss = tcp_sync_mss;
sk->sk_write_space = sk_stream_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
@@ -1900,14 +1388,13 @@ static int tcp_v6_destroy_sock(struct sock *sk)
static void get_openreq6(struct seq_file *seq,
struct sock *sk, struct request_sock *req, int i, int uid)
{
- struct in6_addr *dest, *src;
int ttd = req->expires - jiffies;
+ struct in6_addr *src = &inet6_rsk(req)->loc_addr;
+ struct in6_addr *dest = &inet6_rsk(req)->rmt_addr;
if (ttd < 0)
ttd = 0;
- src = &tcp6_rsk(req)->loc_addr;
- dest = &tcp6_rsk(req)->rmt_addr;
seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
@@ -1988,14 +1475,14 @@ static void get_timewait6_sock(struct seq_file *seq,
{
struct in6_addr *dest, *src;
__u16 destp, srcp;
- struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
+ struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw);
int ttd = tw->tw_ttd - jiffies;
if (ttd < 0)
ttd = 0;
- dest = &tcp6tw->tw_v6_daddr;
- src = &tcp6tw->tw_v6_rcv_saddr;
+ dest = &tw6->tw_v6_daddr;
+ src = &tw6->tw_v6_rcv_saddr;
destp = ntohs(tw->tw_dport);
srcp = ntohs(tw->tw_sport);
@@ -2093,7 +1580,7 @@ struct proto tcpv6_prot = {
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp6_sock),
- .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
+ .twsk_prot = &tcp6_timewait_sock_ops,
.rsk_prot = &tcp6_request_sock_ops,
};
@@ -2110,13 +1597,27 @@ static struct inet_protosw tcpv6_protosw = {
.ops = &inet6_stream_ops,
.capability = -1,
.no_check = 0,
- .flags = INET_PROTOSW_PERMANENT,
+ .flags = INET_PROTOSW_PERMANENT |
+ INET_PROTOSW_ICSK,
};
void __init tcpv6_init(void)
{
+ int err;
+
/* register inet6 protocol */
if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
inet6_register_protosw(&tcpv6_protosw);
+
+ err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_TCP, &tcp6_socket);
+ if (err < 0)
+ panic("Failed to create the TCPv6 control socket.\n");
+ tcp6_socket->sk->sk_allocation = GFP_ATOMIC;
+
+ /* Unhash it so that IP input processing does not even
+ * see it, we do not wish this socket to see incoming
+ * packets.
+ */
+ tcp6_socket->sk->sk_prot->unhash(tcp6_socket->sk);
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 5cc8731eb55b..c47648892c04 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -36,6 +36,7 @@
#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/init.h>
+#include <linux/skbuff.h>
#include <asm/uaccess.h>
#include <net/sock.h>
@@ -300,20 +301,7 @@ out:
return err;
csum_copy_err:
- /* Clear queue. */
- if (flags&MSG_PEEK) {
- int clear = 0;
- spin_lock_bh(&sk->sk_receive_queue.lock);
- if (skb == skb_peek(&sk->sk_receive_queue)) {
- __skb_unlink(skb, &sk->sk_receive_queue);
- clear = 1;
- }
- spin_unlock_bh(&sk->sk_receive_queue.lock);
- if (clear)
- kfree_skb(skb);
- }
-
- skb_free_datagram(sk, skb);
+ skb_kill_datagram(sk, skb, flags);
if (flags & MSG_DONTWAIT) {
UDP6_INC_STATS_USER(UDP_MIB_INERRORS);
@@ -447,7 +435,7 @@ out:
read_unlock(&udp_hash_lock);
}
-static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int udpv6_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct sock *sk;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 28c29d78338e..1ca2da68ef69 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -11,6 +11,8 @@
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv6.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <net/ip.h>
@@ -26,7 +28,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
IP6_ECN_set_ce(inner_iph);
}
-int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
+int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
{
struct sk_buff *skb = *pskb;
int err;
@@ -38,7 +40,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
int nexthdr;
unsigned int nhoff;
- nhoff = *nhoffp;
+ nhoff = IP6CB(skb)->nhoff;
nexthdr = skb->nh.raw[nhoff];
seq = 0;
@@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
skb->sp->len += xfrm_nr;
skb->ip_summed = CHECKSUM_NONE;
+ nf_reset(skb);
+
if (decaps) {
if (!(skb->dev->flags&IFF_LOOPBACK)) {
dst_release(skb->dst);
@@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
netif_rx(skb);
return -1;
} else {
+#ifdef CONFIG_NETFILTER
+ skb->nh.ipv6h->payload_len = htons(skb->len);
+ __skb_push(skb, skb->data - skb->nh.raw);
+
+ NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
+ ip6_rcv_finish);
+ return -1;
+#else
return 1;
+#endif
}
drop_unlock:
@@ -144,7 +157,7 @@ drop:
EXPORT_SYMBOL(xfrm6_rcv_spi);
-int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+int xfrm6_rcv(struct sk_buff **pskb)
{
- return xfrm6_rcv_spi(pskb, nhoffp, 0);
+ return xfrm6_rcv_spi(pskb, 0);
}
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6b9867717d11..80242172a5df 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -9,9 +9,11 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/compiler.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/icmpv6.h>
+#include <linux/netfilter_ipv6.h>
#include <net/dsfield.h>
#include <net/inet_ecn.h>
#include <net/ipv6.h>
@@ -92,7 +94,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
return ret;
}
-int xfrm6_output(struct sk_buff *skb)
+static int xfrm6_output_one(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
@@ -110,29 +112,35 @@ int xfrm6_output(struct sk_buff *skb)
goto error_nolock;
}
- spin_lock_bh(&x->lock);
- err = xfrm_state_check(x, skb);
- if (err)
- goto error;
+ do {
+ spin_lock_bh(&x->lock);
+ err = xfrm_state_check(x, skb);
+ if (err)
+ goto error;
- xfrm6_encap(skb);
+ xfrm6_encap(skb);
- err = x->type->output(x, skb);
- if (err)
- goto error;
+ err = x->type->output(x, skb);
+ if (err)
+ goto error;
- x->curlft.bytes += skb->len;
- x->curlft.packets++;
+ x->curlft.bytes += skb->len;
+ x->curlft.packets++;
- spin_unlock_bh(&x->lock);
+ spin_unlock_bh(&x->lock);
- skb->nh.raw = skb->data;
-
- if (!(skb->dst = dst_pop(dst))) {
- err = -EHOSTUNREACH;
- goto error_nolock;
- }
- err = NET_XMIT_BYPASS;
+ skb->nh.raw = skb->data;
+
+ if (!(skb->dst = dst_pop(dst))) {
+ err = -EHOSTUNREACH;
+ goto error_nolock;
+ }
+ dst = skb->dst;
+ x = dst->xfrm;
+ } while (x && !x->props.mode);
+
+ IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
+ err = 0;
out_exit:
return err;
@@ -142,3 +150,33 @@ error_nolock:
kfree_skb(skb);
goto out_exit;
}
+
+static int xfrm6_output_finish(struct sk_buff *skb)
+{
+ int err;
+
+ while (likely((err = xfrm6_output_one(skb)) == 0)) {
+ nf_reset(skb);
+
+ err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, &skb, NULL,
+ skb->dst->dev, dst_output);
+ if (unlikely(err != 1))
+ break;
+
+ if (!skb->dst->xfrm)
+ return dst_output(skb);
+
+ err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
+ skb->dst->dev, xfrm6_output_finish);
+ if (unlikely(err != 1))
+ break;
+ }
+
+ return err;
+}
+
+int xfrm6_output(struct sk_buff *skb)
+{
+ return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
+ xfrm6_output_finish);
+}
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index bf0d0abc3871..a5723024d3b3 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -15,6 +15,7 @@
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <net/ipv6.h>
+#include <net/addrconf.h>
static struct xfrm_state_afinfo xfrm6_state_afinfo;
@@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr));
if (ipv6_addr_any((struct in6_addr*)&x->props.saddr))
memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr));
+ if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) {
+ struct rt6_info *rt;
+ struct flowi fl_tunnel = {
+ .nl_u = {
+ .ip6_u = {
+ .daddr = *(struct in6_addr *)daddr,
+ }
+ }
+ };
+ if (!xfrm_dst_lookup((struct xfrm_dst **)&rt,
+ &fl_tunnel, AF_INET6)) {
+ ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr,
+ (struct in6_addr *)&x->props.saddr);
+ dst_release(&rt->u.dst);
+ }
+ }
x->props.mode = tmpl->mode;
x->props.reqid = tmpl->reqid;
x->props.family = AF_INET6;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index fbef7826a74f..8cfc58b96fc2 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -259,8 +259,7 @@ try_next_2:;
spi = 0;
goto out;
alloc_spi:
- X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n",
__FUNCTION__,
NIP6(*(struct in6_addr *)saddr));
x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC);
@@ -323,9 +322,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
list_byaddr)
{
if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) {
- X6TPRINTK3(KERN_DEBUG "%s(): x6spi object "
- "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
- "found at %p\n",
+ X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT
+ " found at %p\n",
__FUNCTION__,
NIP6(*(struct in6_addr *)saddr),
x6spi);
@@ -397,7 +395,7 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
EXPORT_SYMBOL(xfrm6_tunnel_deregister);
-static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
@@ -405,11 +403,11 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
u32 spi;
/* device-like_ip6ip6_handler() */
- if (handler && handler->handler(pskb, nhoffp) == 0)
+ if (handler && handler->handler(pskb) == 0)
return 0;
spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
- return xfrm6_rcv_spi(pskb, nhoffp, spi);
+ return xfrm6_rcv_spi(pskb, spi);
}
static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 34b3bb868409..0fb513a34d11 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -29,6 +29,7 @@
*/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
@@ -75,7 +76,7 @@ static struct datalink_proto *pEII_datalink;
static struct datalink_proto *p8023_datalink;
static struct datalink_proto *pSNAP_datalink;
-static struct proto_ops ipx_dgram_ops;
+static const struct proto_ops ipx_dgram_ops;
LIST_HEAD(ipx_interfaces);
DEFINE_SPINLOCK(ipx_interfaces_lock);
@@ -1884,7 +1885,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -EINVAL;
break;
default:
- rc = dev_ioctl(cmd, argp);
+ rc = -ENOIOCTLCMD;
break;
}
@@ -1901,7 +1902,7 @@ static struct net_proto_family ipx_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
.family = PF_IPX,
.owner = THIS_MODULE,
.release = ipx_release,
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 6f92f9c62990..759445648667 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -43,6 +43,7 @@
********************************************************************/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -62,12 +63,12 @@
static int irda_create(struct socket *sock, int protocol);
-static struct proto_ops irda_stream_ops;
-static struct proto_ops irda_seqpacket_ops;
-static struct proto_ops irda_dgram_ops;
+static const struct proto_ops irda_stream_ops;
+static const struct proto_ops irda_seqpacket_ops;
+static const struct proto_ops irda_dgram_ops;
#ifdef CONFIG_IRDA_ULTRA
-static struct proto_ops irda_ultra_ops;
+static const struct proto_ops irda_ultra_ops;
#define ULTRA_MAX_DATA 382
#endif /* CONFIG_IRDA_ULTRA */
@@ -1438,8 +1439,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
/*
* POSIX 1003.1g mandates this order.
*/
- if (sk->sk_err)
- ret = sock_error(sk);
+ ret = sock_error(sk);
+ if (ret)
+ break;
else if (sk->sk_shutdown & RCV_SHUTDOWN)
;
else if (noblock)
@@ -1821,7 +1823,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return -EINVAL;
default:
IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __FUNCTION__);
- return dev_ioctl(cmd, (void __user *) arg);
+ return -ENOIOCTLCMD;
}
/*NOTREACHED*/
@@ -2463,7 +2465,7 @@ static struct net_proto_family irda_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2484,7 +2486,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.sendpage = sock_no_sendpage,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2505,7 +2507,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.sendpage = sock_no_sendpage,
};
-static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2527,7 +2529,7 @@ static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
};
#ifdef CONFIG_IRDA_ULTRA
-static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 70543d89438b..890bac0d4a56 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -33,6 +33,7 @@
#include <linux/string.h>
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
+#include <linux/capability.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index b8bb78af8b8a..254f90746900 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -364,7 +364,7 @@ static void iriap_disconnect_request(struct iriap_cb *self)
/*
* Function iriap_getvaluebyclass (addr, name, attr)
*
- * Retreive all values from attribute in all objects with given class
+ * Retrieve all values from attribute in all objects with given class
* name
*/
int iriap_getvaluebyclass_request(struct iriap_cb *self,
diff --git a/net/irda/irias_object.c b/net/irda/irias_object.c
index 75f2666e8630..c6d169fbdceb 100644
--- a/net/irda/irias_object.c
+++ b/net/irda/irias_object.c
@@ -82,8 +82,7 @@ struct ias_object *irias_new_object( char *name, int id)
IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
- obj = (struct ias_object *) kmalloc(sizeof(struct ias_object),
- GFP_ATOMIC);
+ obj = kmalloc(sizeof(struct ias_object), GFP_ATOMIC);
if (obj == NULL) {
IRDA_WARNING("%s(), Unable to allocate object!\n",
__FUNCTION__);
@@ -348,8 +347,7 @@ void irias_add_integer_attrib(struct ias_object *obj, char *name, int value,
IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
IRDA_ASSERT(name != NULL, return;);
- attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
- GFP_ATOMIC);
+ attrib = kmalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
@@ -385,8 +383,7 @@ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
IRDA_ASSERT(name != NULL, return;);
IRDA_ASSERT(octets != NULL, return;);
- attrib = (struct ias_attrib *) kmalloc(sizeof(struct ias_attrib),
- GFP_ATOMIC);
+ attrib = kmalloc(sizeof(struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
@@ -420,8 +417,7 @@ void irias_add_string_attrib(struct ias_object *obj, char *name, char *value,
IRDA_ASSERT(name != NULL, return;);
IRDA_ASSERT(value != NULL, return;);
- attrib = (struct ias_attrib *) kmalloc(sizeof( struct ias_attrib),
- GFP_ATOMIC);
+ attrib = kmalloc(sizeof( struct ias_attrib), GFP_ATOMIC);
if (attrib == NULL) {
IRDA_WARNING("%s: Unable to allocate attribute!\n",
__FUNCTION__);
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
index b391cb3893d4..e4fe1e80029c 100644
--- a/net/irda/irnet/irnet.h
+++ b/net/irda/irnet/irnet.h
@@ -248,6 +248,7 @@
#include <linux/netdevice.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/ctype.h> /* isspace() */
#include <asm/uaccess.h>
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 39031684b65c..43f1ce74187d 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -15,6 +15,7 @@
*/
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/socket.h>
@@ -113,7 +114,7 @@ static __inline__ void pfkey_unlock_table(void)
}
-static struct proto_ops pfkey_ops;
+static const struct proto_ops pfkey_ops;
static void pfkey_insert(struct sock *sk)
{
@@ -297,8 +298,7 @@ static int pfkey_error(struct sadb_msg *orig, int err, struct sock *sk)
err = EINTR;
if (err >= 512)
err = EINVAL;
- if (err <= 0 || err >= 256)
- BUG();
+ BUG_ON(err <= 0 || err >= 256);
hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
pfkey_hdr_dup(hdr, orig);
@@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = {
[SADB_X_EXT_NAT_T_SPORT] = (u8) sizeof(struct sadb_x_nat_t_port),
[SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port),
[SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address),
+ [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx),
};
/* Verify sadb_address_{len,prefixlen} against sa_family. */
@@ -383,6 +384,55 @@ static int verify_address_len(void *p)
return 0;
}
+static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx)
+{
+ int len = 0;
+
+ len += sizeof(struct sadb_x_sec_ctx);
+ len += sec_ctx->sadb_x_ctx_len;
+ len += sizeof(uint64_t) - 1;
+ len /= sizeof(uint64_t);
+
+ return len;
+}
+
+static inline int verify_sec_ctx_len(void *p)
+{
+ struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+ int len;
+
+ if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE)
+ return -EINVAL;
+
+ len = pfkey_sec_ctx_len(sec_ctx);
+
+ if (sec_ctx->sadb_x_sec_len != len)
+ return -EINVAL;
+
+ return 0;
+}
+
+static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(struct sadb_x_sec_ctx *sec_ctx)
+{
+ struct xfrm_user_sec_ctx *uctx = NULL;
+ int ctx_size = sec_ctx->sadb_x_ctx_len;
+
+ uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL);
+
+ if (!uctx)
+ return NULL;
+
+ uctx->len = pfkey_sec_ctx_len(sec_ctx);
+ uctx->exttype = sec_ctx->sadb_x_sec_exttype;
+ uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi;
+ uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg;
+ uctx->ctx_len = sec_ctx->sadb_x_ctx_len;
+ memcpy(uctx + 1, sec_ctx + 1,
+ uctx->ctx_len);
+
+ return uctx;
+}
+
static int present_and_same_family(struct sadb_address *src,
struct sadb_address *dst)
{
@@ -438,6 +488,10 @@ static int parse_exthdrs(struct sk_buff *skb, struct sadb_msg *hdr, void **ext_h
if (verify_address_len(p))
return -EINVAL;
}
+ if (ext_type == SADB_X_EXT_SEC_CTX) {
+ if (verify_sec_ctx_len(p))
+ return -EINVAL;
+ }
ext_hdrs[ext_type-1] = p;
}
p += ext_len;
@@ -586,6 +640,9 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
struct sadb_key *key;
struct sadb_x_sa2 *sa2;
struct sockaddr_in *sin;
+ struct sadb_x_sec_ctx *sec_ctx;
+ struct xfrm_sec_ctx *xfrm_ctx;
+ int ctx_size = 0;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 *sin6;
#endif
@@ -609,6 +666,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sizeof(struct sadb_address)*2 +
sockaddr_size*2 +
sizeof(struct sadb_x_sa2);
+
+ if ((xfrm_ctx = x->security)) {
+ ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+ size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
+ }
+
/* identity & sensitivity */
if ((x->props.family == AF_INET &&
@@ -899,6 +962,20 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
n_port->sadb_x_nat_t_port_reserved = 0;
}
+ /* security context */
+ if (xfrm_ctx) {
+ sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+ sizeof(struct sadb_x_sec_ctx) + ctx_size);
+ sec_ctx->sadb_x_sec_len =
+ (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
+ sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+ sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+ sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+ sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+ memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+ xfrm_ctx->ctx_len);
+ }
+
return skb;
}
@@ -909,6 +986,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
struct sadb_lifetime *lifetime;
struct sadb_sa *sa;
struct sadb_key *key;
+ struct sadb_x_sec_ctx *sec_ctx;
uint16_t proto;
int err;
@@ -993,6 +1071,21 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
}
+
+ sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ if (sec_ctx != NULL) {
+ struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+
+ if (!uctx)
+ goto out;
+
+ err = security_xfrm_state_alloc(x, uctx);
+ kfree(uctx);
+
+ if (err)
+ goto out;
+ }
+
key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
if (sa->sadb_sa_auth) {
int keysize = 0;
@@ -1720,6 +1813,18 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
return 0;
}
+static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
+{
+ struct xfrm_sec_ctx *xfrm_ctx = xp->security;
+
+ if (xfrm_ctx) {
+ int len = sizeof(struct sadb_x_sec_ctx);
+ len += xfrm_ctx->ctx_len;
+ return PFKEY_ALIGN8(len);
+ }
+ return 0;
+}
+
static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
{
int sockaddr_size = pfkey_sockaddr_size(xp->family);
@@ -1733,7 +1838,8 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
(sockaddr_size * 2) +
sizeof(struct sadb_x_policy) +
(xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
- (socklen * 2)));
+ (socklen * 2))) +
+ pfkey_xfrm_policy2sec_ctx_size(xp);
}
static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
@@ -1757,6 +1863,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
struct sadb_lifetime *lifetime;
struct sadb_x_policy *pol;
struct sockaddr_in *sin;
+ struct sadb_x_sec_ctx *sec_ctx;
+ struct xfrm_sec_ctx *xfrm_ctx;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 *sin6;
#endif
@@ -1941,6 +2049,21 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
}
}
}
+
+ /* security context */
+ if ((xfrm_ctx = xp->security)) {
+ int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
+
+ sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size);
+ sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
+ sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+ sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+ sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+ sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+ memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+ xfrm_ctx->ctx_len);
+ }
+
hdr->sadb_msg_len = size / sizeof(uint64_t);
hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
}
@@ -1976,12 +2099,13 @@ out:
static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
- int err;
+ int err = 0;
struct sadb_lifetime *lifetime;
struct sadb_address *sa;
struct sadb_x_policy *pol;
struct xfrm_policy *xp;
struct km_event c;
+ struct sadb_x_sec_ctx *sec_ctx;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2028,6 +2152,22 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
if (xp->selector.dport)
xp->selector.dport_mask = ~0;
+ sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ if (sec_ctx != NULL) {
+ struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+
+ if (!uctx) {
+ err = -ENOBUFS;
+ goto out;
+ }
+
+ err = security_xfrm_policy_alloc(xp, uctx);
+ kfree(uctx);
+
+ if (err)
+ goto out;
+ }
+
xp->lft.soft_byte_limit = XFRM_INF;
xp->lft.hard_byte_limit = XFRM_INF;
xp->lft.soft_packet_limit = XFRM_INF;
@@ -2051,10 +2191,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
hdr->sadb_msg_type != SADB_X_SPDUPDATE);
- if (err) {
- kfree(xp);
- return err;
- }
+
+ if (err)
+ goto out;
if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
c.event = XFRM_MSG_UPDPOLICY;
@@ -2069,6 +2208,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return 0;
out:
+ security_xfrm_policy_free(xp);
kfree(xp);
return err;
}
@@ -2078,9 +2218,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
int err;
struct sadb_address *sa;
struct sadb_x_policy *pol;
- struct xfrm_policy *xp;
+ struct xfrm_policy *xp, tmp;
struct xfrm_selector sel;
struct km_event c;
+ struct sadb_x_sec_ctx *sec_ctx;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2109,7 +2250,24 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
if (sel.dport)
sel.dport_mask = ~0;
- xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
+ sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+ memset(&tmp, 0, sizeof(struct xfrm_policy));
+
+ if (sec_ctx != NULL) {
+ struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+
+ if (!uctx)
+ return -ENOMEM;
+
+ err = security_xfrm_policy_alloc(&tmp, uctx);
+ kfree(uctx);
+
+ if (err)
+ return err;
+ }
+
+ xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1);
+ security_xfrm_policy_free(&tmp);
if (xp == NULL)
return -ENOENT;
@@ -2660,6 +2818,7 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
{
struct xfrm_policy *xp;
struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+ struct sadb_x_sec_ctx *sec_ctx;
switch (family) {
case AF_INET:
@@ -2709,10 +2868,32 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt,
(*dir = parse_ipsecrequests(xp, pol)) < 0)
goto out;
+ /* security context too */
+ if (len >= (pol->sadb_x_policy_len*8 +
+ sizeof(struct sadb_x_sec_ctx))) {
+ char *p = (char *)pol;
+ struct xfrm_user_sec_ctx *uctx;
+
+ p += pol->sadb_x_policy_len*8;
+ sec_ctx = (struct sadb_x_sec_ctx *)p;
+ if (len < pol->sadb_x_policy_len*8 +
+ sec_ctx->sadb_x_sec_len)
+ goto out;
+ if ((*dir = verify_sec_ctx_len(p)))
+ goto out;
+ uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
+ *dir = security_xfrm_policy_alloc(xp, uctx);
+ kfree(uctx);
+
+ if (*dir)
+ goto out;
+ }
+
*dir = pol->sadb_x_policy_dir-1;
return xp;
out:
+ security_xfrm_policy_free(xp);
kfree(xp);
return NULL;
}
@@ -2946,7 +3127,7 @@ out:
return err;
}
-static struct proto_ops pfkey_ops = {
+static const struct proto_ops pfkey_ops = {
.family = PF_KEY,
.owner = THIS_MODULE,
/* Operations that make no sense on pfkey sockets. */
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index c3f0b0783453..8171c53bc0ed 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -36,7 +36,7 @@
static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
static u16 llc_ui_sap_link_no_max[256];
static struct sockaddr_llc llc_ui_addrnull;
-static struct proto_ops llc_ui_ops;
+static const struct proto_ops llc_ui_ops;
static int llc_ui_wait_for_conn(struct sock *sk, long timeout);
static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
@@ -566,10 +566,9 @@ static int llc_wait_data(struct sock *sk, long timeo)
/*
* POSIX 1003.1g mandates this order.
*/
- if (sk->sk_err) {
- rc = sock_error(sk);
+ rc = sock_error(sk);
+ if (rc)
break;
- }
rc = 0;
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;
@@ -960,7 +959,7 @@ out:
static int llc_ui_ioctl(struct socket *sock, unsigned int cmd,
unsigned long arg)
{
- return dev_ioctl(cmd, (void __user *)arg);
+ return -ENOIOCTLCMD;
}
/**
@@ -1099,7 +1098,7 @@ static struct net_proto_family llc_ui_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops llc_ui_ops = {
+static const struct proto_ops llc_ui_ops = {
.family = PF_LLC,
.owner = THIS_MODULE,
.release = llc_ui_release,
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 794c41d19b28..99c0a0fa4a97 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -95,4 +95,269 @@ config NF_CONNTRACK_FTP
To compile it as a module, choose M here. If unsure, say N.
+config NF_CT_NETLINK
+ tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
+ depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
+ depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+ help
+ This option enables support for a netlink-based userspace interface
+
endmenu
+
+config NETFILTER_XTABLES
+ tristate "Netfilter Xtables support (required for ip_tables)"
+ help
+ This is required if you intend to use any of ip_tables,
+ ip6_tables or arp_tables.
+
+# alphabetically ordered list of targets
+
+config NETFILTER_XT_TARGET_CLASSIFY
+ tristate '"CLASSIFY" target support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `CLASSIFY' target, which enables the user to set
+ the priority of a packet. Some qdiscs can use this value for
+ classification, among these are:
+
+ atm, cbq, dsmark, pfifo_fast, htb, prio
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_TARGET_CONNMARK
+ tristate '"CONNMARK" target support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_MANGLE || IP6_NF_MANGLE
+ depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
+ help
+ This option adds a `CONNMARK' target, which allows one to manipulate
+ the connection mark value. Similar to the MARK target, but
+ affects the connection mark value rather than the packet mark value.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ipt_CONNMARK.o. If unsure, say `N'.
+
+config NETFILTER_XT_TARGET_MARK
+ tristate '"MARK" target support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `MARK' target, which allows you to create rules
+ in the `mangle' table which alter the netfilter mark (nfmark) field
+ associated with the packet prior to routing. This can change
+ the routing method (see `Use netfilter MARK value as routing
+ key') and can also be used by other subsystems to change their
+ behavior.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_TARGET_NFQUEUE
+ tristate '"NFQUEUE" target Support'
+ depends on NETFILTER_XTABLES
+ help
+ This Target replaced the old obsolete QUEUE target.
+
+ As opposed to QUEUE, it supports 65535 different queues,
+ not just one.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_TARGET_NOTRACK
+ tristate '"NOTRACK" target support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_RAW || IP6_NF_RAW
+ depends on IP_NF_CONNTRACK || NF_CONNTRACK
+ help
+ The NOTRACK target allows a select rule to specify
+ which packets *not* to enter the conntrack/NAT
+ subsystem with all the consequences (no ICMP error tracking,
+ no protocol helpers for the selected packets).
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+config NETFILTER_XT_MATCH_COMMENT
+ tristate '"comment" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `comment' dummy-match, which allows you to put
+ comments in your iptables ruleset.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+config NETFILTER_XT_MATCH_CONNBYTES
+ tristate '"connbytes" per-connection counter match support'
+ depends on NETFILTER_XTABLES
+ depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT
+ 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 NETFILTER_XT_MATCH_CONNMARK
+ tristate '"connmark" connection mark match support'
+ depends on NETFILTER_XTABLES
+ depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK
+ help
+ This option adds a `connmark' match, which allows you to match the
+ connection mark value previously set for the session by `CONNMARK'.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. The module will be called
+ ipt_connmark.o. If unsure, say `N'.
+
+config NETFILTER_XT_MATCH_CONNTRACK
+ tristate '"conntrack" connection tracking match support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_CONNTRACK || NF_CONNTRACK
+ help
+ This is a general conntrack match module, a superset of the state match.
+
+ It allows matching on additional conntrack information, which is
+ useful in complex configurations, such as NAT gateways with multiple
+ internet links or tunnels.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_DCCP
+ tristate '"DCCP" protocol match support'
+ depends on NETFILTER_XTABLES
+ 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 NETFILTER_XT_MATCH_HELPER
+ tristate '"helper" match support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_CONNTRACK || NF_CONNTRACK
+ help
+ Helper matching allows you to match packets in dynamic connections
+ tracked by a conntrack-helper, ie. ip_conntrack_ftp
+
+ To compile it as a module, choose M here. If unsure, say Y.
+
+config NETFILTER_XT_MATCH_LENGTH
+ tristate '"length" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option allows you to match the length of a packet against a
+ specific value or range of values.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_LIMIT
+ tristate '"limit" match support'
+ depends on NETFILTER_XTABLES
+ help
+ limit matching allows you to control the rate at which a rule can be
+ matched: mainly useful in combination with the LOG target ("LOG
+ target support", below) and to avoid some Denial of Service attacks.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_MAC
+ tristate '"mac" address match support'
+ depends on NETFILTER_XTABLES
+ help
+ MAC matching allows you to match packets based on the source
+ Ethernet address of the packet.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_MARK
+ tristate '"mark" match support'
+ depends on NETFILTER_XTABLES
+ help
+ Netfilter mark matching allows you to match packets based on the
+ `nfmark' value in the packet. This can be set by the MARK target
+ (see below).
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_PHYSDEV
+ tristate '"physdev" match support'
+ depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
+ help
+ Physdev packet matching matches against the physical bridge ports
+ the IP packet arrived on or will leave by.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_PKTTYPE
+ tristate '"pkttype" packet type match support'
+ depends on NETFILTER_XTABLES
+ help
+ Packet type matching allows you to match a packet by
+ its "class", eg. BROADCAST, MULTICAST, ...
+
+ Typical usage:
+ iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_REALM
+ tristate '"realm" match support'
+ depends on NETFILTER_XTABLES
+ select NET_CLS_ROUTE
+ help
+ This option adds a `realm' match, which allows you to use the realm
+ key from the routing subsystem inside iptables.
+
+ This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
+ in tc world.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+config NETFILTER_XT_MATCH_SCTP
+ tristate '"sctp" protocol match support'
+ depends on NETFILTER_XTABLES
+ help
+ With this option enabled, you will be able to use the
+ `sctp' match in order to match on SCTP source/destination ports
+ and SCTP chunk types.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
+config NETFILTER_XT_MATCH_STATE
+ tristate '"state" match support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_CONNTRACK || NF_CONNTRACK
+ help
+ Connection state matching allows you to match packets based on their
+ relationship to a tracked connection (ie. previous packets). This
+ is a powerful tool for packet classification.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
+config NETFILTER_XT_MATCH_STRING
+ tristate '"string" match support'
+ depends on NETFILTER_XTABLES
+ 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.
+
+config NETFILTER_XT_MATCH_TCPMSS
+ tristate '"tcpmss" match support'
+ depends on NETFILTER_XTABLES
+ help
+ This option adds a `tcpmss' match, which allows you to examine the
+ MSS value of TCP SYN packets, which control the maximum packet size
+ for that connection.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 55f019ad2c08..746172ebc91b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,4 +1,5 @@
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
+nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -6,10 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
-nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
-
+# connection tracking
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
-obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
# SCTP protocol connection tracking
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+
+# netlink interface for nf_conntrack
+obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
+
+# connection tracking helpers
+obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
+
+# generic X tables
+obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
+
+# targets
+obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+
+# matches
+obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index a7c7b490cf22..62bb509f05d4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -82,6 +82,8 @@ unsigned int nf_ct_log_invalid;
static LIST_HEAD(unconfirmed);
static int nf_conntrack_vmalloc;
+static unsigned int nf_conntrack_next_id = 1;
+static unsigned int nf_conntrack_expect_next_id = 1;
#ifdef CONFIG_NF_CONNTRACK_EVENTS
struct notifier_block *nf_conntrack_chain;
struct notifier_block *nf_conntrack_expect_chain;
@@ -184,7 +186,7 @@ DECLARE_MUTEX(nf_ct_cache_mutex);
extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
struct nf_conntrack_protocol *
-nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol)
+__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol)
{
if (unlikely(nf_ct_protos[l3proto] == NULL))
return &nf_conntrack_generic_protocol;
@@ -192,6 +194,50 @@ nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol)
return nf_ct_protos[l3proto][protocol];
}
+/* this is guaranteed to always return a valid protocol helper, since
+ * it falls back to generic_protocol */
+struct nf_conntrack_protocol *
+nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol)
+{
+ struct nf_conntrack_protocol *p;
+
+ preempt_disable();
+ p = __nf_ct_proto_find(l3proto, protocol);
+ if (p) {
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_protocol;
+ }
+ preempt_enable();
+
+ return p;
+}
+
+void nf_ct_proto_put(struct nf_conntrack_protocol *p)
+{
+ module_put(p->me);
+}
+
+struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto)
+{
+ struct nf_conntrack_l3proto *p;
+
+ preempt_disable();
+ p = __nf_ct_l3proto_find(l3proto);
+ if (p) {
+ if (!try_module_get(p->me))
+ p = &nf_conntrack_generic_l3proto;
+ }
+ preempt_enable();
+
+ return p;
+}
+
+void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
+{
+ module_put(p->me);
+}
+
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
@@ -384,7 +430,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
}
/* nf_conntrack_expect helper functions */
-static void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
+void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
ASSERT_WRITE_LOCK(&nf_conntrack_lock);
NF_CT_ASSERT(!timer_pending(&exp->timeout));
@@ -404,6 +450,33 @@ static void expectation_timed_out(unsigned long ul_expect)
nf_conntrack_expect_put(exp);
}
+struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_expect *i;
+
+ list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ if (nf_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 nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_expect *i;
+
+ read_lock_bh(&nf_conntrack_lock);
+ i = __nf_conntrack_expect_find(tuple);
+ read_unlock_bh(&nf_conntrack_lock);
+
+ return i;
+}
+
/* If an expectation for this connection is found, it gets delete from
* global list then returned. */
static struct nf_conntrack_expect *
@@ -432,7 +505,7 @@ find_expectation(const struct nf_conntrack_tuple *tuple)
}
/* delete all expectations for this conntrack */
-static void remove_expectations(struct nf_conn *ct)
+void nf_ct_remove_expectations(struct nf_conn *ct)
{
struct nf_conntrack_expect *i, *tmp;
@@ -462,7 +535,7 @@ clean_from_lists(struct nf_conn *ct)
LIST_DELETE(&nf_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
/* Destroy all pending expectations */
- remove_expectations(ct);
+ nf_ct_remove_expectations(ct);
}
static void
@@ -482,12 +555,11 @@ destroy_conntrack(struct nf_conntrack *nfct)
/* To make sure we don't get any weird locking issues here:
* destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */
- l3proto = nf_ct_find_l3proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
+ l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
if (l3proto && l3proto->destroy)
l3proto->destroy(ct);
- proto = nf_ct_find_proto(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
- ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
+ proto = __nf_ct_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
if (proto && proto->destroy)
proto->destroy(ct);
@@ -499,7 +571,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);
+ nf_ct_remove_expectations(ct);
/* We overload first tuple to link into unconfirmed list. */
if (!nf_ct_is_confirmed(ct)) {
@@ -540,7 +612,7 @@ conntrack_tuple_cmp(const struct nf_conntrack_tuple_hash *i,
&& nf_ct_tuple_equal(tuple, &i->tuple);
}
-static struct nf_conntrack_tuple_hash *
+struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack)
{
@@ -575,6 +647,29 @@ nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
return h;
}
+static void __nf_conntrack_hash_insert(struct nf_conn *ct,
+ unsigned int hash,
+ unsigned int repl_hash)
+{
+ ct->id = ++nf_conntrack_next_id;
+ list_prepend(&nf_conntrack_hash[hash],
+ &ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ list_prepend(&nf_conntrack_hash[repl_hash],
+ &ct->tuplehash[IP_CT_DIR_REPLY].list);
+}
+
+void nf_conntrack_hash_insert(struct nf_conn *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(&nf_conntrack_lock);
+ __nf_conntrack_hash_insert(ct, hash, repl_hash);
+ write_unlock_bh(&nf_conntrack_lock);
+}
+
/* Confirm a connection given skb; places it in hash table */
int
__nf_conntrack_confirm(struct sk_buff **pskb)
@@ -621,10 +716,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
/* Remove from unconfirmed list */
list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
- list_prepend(&nf_conntrack_hash[hash],
- &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
- list_prepend(&nf_conntrack_hash[repl_hash],
- &ct->tuplehash[IP_CT_DIR_REPLY]);
+ __nf_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. */
@@ -708,13 +800,41 @@ static inline int helper_cmp(const struct nf_conntrack_helper *i,
}
static struct nf_conntrack_helper *
-nf_ct_find_helper(const struct nf_conntrack_tuple *tuple)
+__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
{
return LIST_FIND(&helpers, helper_cmp,
struct nf_conntrack_helper *,
tuple);
}
+struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_helper *helper;
+
+ /* need nf_conntrack_lock to assure that helper exists until
+ * try_module_get() is called */
+ read_lock_bh(&nf_conntrack_lock);
+
+ helper = __nf_ct_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(&nf_conntrack_lock);
+
+ return helper;
+}
+
+void nf_ct_helper_put(struct nf_conntrack_helper *helper)
+{
+ module_put(helper->me);
+}
+
static struct nf_conn *
__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl,
@@ -744,7 +864,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
/* find features needed by this conntrack. */
features = l3proto->get_features(orig);
read_lock_bh(&nf_conntrack_lock);
- if (nf_ct_find_helper(repl) != NULL)
+ if (__nf_ct_helper_find(repl) != NULL)
features |= NF_CT_F_HELP;
read_unlock_bh(&nf_conntrack_lock);
@@ -794,7 +914,7 @@ struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
{
struct nf_conntrack_l3proto *l3proto;
- l3proto = nf_ct_find_l3proto(orig->src.l3num);
+ l3proto = __nf_ct_l3proto_find(orig->src.l3num);
return __nf_conntrack_alloc(orig, repl, l3proto);
}
@@ -853,7 +973,7 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
} else {
- conntrack->helper = nf_ct_find_helper(&repl_tuple);
+ conntrack->helper = __nf_ct_helper_find(&repl_tuple);
NF_CT_STAT_INC(new);
}
@@ -947,13 +1067,13 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
return NF_ACCEPT;
}
- l3proto = nf_ct_find_l3proto((u_int16_t)pf);
+ l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
DEBUGP("not prepared to track yet or error occured\n");
return -ret;
}
- proto = nf_ct_find_proto((u_int16_t)pf, protonum);
+ proto = __nf_ct_proto_find((u_int16_t)pf, protonum);
/* It may be an special packet, error, unclean...
* inverse of the return code tells to the netfilter
@@ -1002,9 +1122,9 @@ int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig)
{
return nf_ct_invert_tuple(inverse, orig,
- nf_ct_find_l3proto(orig->src.l3num),
- nf_ct_find_proto(orig->src.l3num,
- orig->dst.protonum));
+ __nf_ct_l3proto_find(orig->src.l3num),
+ __nf_ct_proto_find(orig->src.l3num,
+ orig->dst.protonum));
}
/* Would two expected things clash? */
@@ -1096,6 +1216,7 @@ static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
add_timer(&exp->timeout);
+ exp->id = ++nf_conntrack_expect_next_id;
atomic_inc(&exp->use);
NF_CT_STAT_INC(expect_create);
}
@@ -1129,6 +1250,7 @@ static inline int refresh_timer(struct nf_conntrack_expect *i)
int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
{
struct nf_conntrack_expect *i;
+ struct nf_conn *master = expect->master;
int ret;
DEBUGP("nf_conntrack_expect_related %p\n", related_to);
@@ -1149,9 +1271,9 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
}
}
/* Will be over limit? */
- if (expect->master->helper->max_expected &&
- expect->master->expecting >= expect->master->helper->max_expected)
- evict_oldest_expect(expect->master);
+ if (master->helper->max_expected &&
+ master->expecting >= master->helper->max_expected)
+ evict_oldest_expect(master);
nf_conntrack_expect_insert(expect);
nf_conntrack_expect_event(IPEXP_NEW, expect);
@@ -1175,7 +1297,7 @@ void nf_conntrack_alter_reply(struct nf_conn *conntrack,
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
if (!conntrack->master && conntrack->expecting == 0)
- conntrack->helper = nf_ct_find_helper(newreply);
+ conntrack->helper = __nf_ct_helper_find(newreply);
write_unlock_bh(&nf_conntrack_lock);
}
@@ -1200,6 +1322,19 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
return 0;
}
+struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name)
+{
+ struct nf_conntrack_helper *h;
+
+ list_for_each_entry(h, &helpers, list) {
+ if (!strcmp(h->name, name))
+ return h;
+ }
+
+ return NULL;
+}
+
static inline int unhelp(struct nf_conntrack_tuple_hash *i,
const struct nf_conntrack_helper *me)
{
@@ -1283,6 +1418,51 @@ void __nf_ct_refresh_acct(struct nf_conn *ct,
nf_conntrack_event_cache(event, skb);
}
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+/* 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 nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+ const struct nf_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;
+}
+
+static const size_t cta_min_proto[CTA_PROTO_MAX] = {
+ [CTA_PROTO_SRC_PORT-1] = sizeof(u_int16_t),
+ [CTA_PROTO_DST_PORT-1] = sizeof(u_int16_t)
+};
+
+int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+ struct nf_conntrack_tuple *t)
+{
+ if (!tb[CTA_PROTO_SRC_PORT-1] || !tb[CTA_PROTO_DST_PORT-1])
+ return -EINVAL;
+
+ if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+ 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
+
/* Used by ipt_REJECT and ip6t_REJECT. */
void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
{
@@ -1365,6 +1545,11 @@ static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
get_order(sizeof(struct list_head) * size));
}
+void nf_conntrack_flush()
+{
+ nf_ct_iterate_cleanup(kill_all, NULL);
+}
+
/* Mishearing the voices in his head, our hero wonders how he's
supposed to kill the mall. */
void nf_conntrack_cleanup(void)
@@ -1378,7 +1563,7 @@ void nf_conntrack_cleanup(void)
nf_ct_event_cache_flush();
i_see_dead_people:
- nf_ct_iterate_cleanup(kill_all, NULL);
+ nf_conntrack_flush();
if (atomic_read(&nf_conntrack_count) != 0) {
schedule();
goto i_see_dead_people;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 65080e269f27..ab0c920f0d30 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -44,7 +44,7 @@ static unsigned int ports_c;
module_param_array(ports, ushort, &ports_c, 0400);
static int loose;
-module_param(loose, int, 0600);
+module_param(loose, bool, 0600);
unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
@@ -545,11 +545,11 @@ static int help(struct sk_buff **pskb,
different IP address. Simply don't record it for
NAT. */
if (cmd.l3num == PF_INET) {
- DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n",
+ DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
NIPQUAD(cmd.u3.ip),
NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
} else {
- DEBUGP("conntrack_ftp: NOT RECORDING: %x:%x:%x:%x:%x:%x:%x:%x != %x:%x:%x:%x:%x:%x:%x:%x\n",
+ DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n",
NIP6(*((struct in6_addr *)cmd.u3.ip6)),
NIP6(*((struct in6_addr *)ct->tuplehash[dir]
.tuple.src.u3.ip6)));
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
new file mode 100644
index 000000000000..73ab16bc7d40
--- /dev/null
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -0,0 +1,1653 @@
+/* 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.
+ *
+ * Derived from ip_conntrack_netlink.c: Port by Pablo Neira Ayuso (05/11/14)
+ */
+
+#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/netfilter.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_l3proto.h>
+#include <net/netfilter/nf_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.92";
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+
+static inline int
+ctnetlink_dump_tuples_proto(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_protocol *proto;
+ int ret = 0;
+
+ NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
+
+ /* If no protocol helper is found, this function will return the
+ * generic protocol helper, so proto won't *ever* be NULL */
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+ if (likely(proto->tuple_to_nfattr))
+ ret = proto->tuple_to_nfattr(skb, tuple);
+
+ nf_ct_proto_put(proto);
+
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+ const struct nf_conntrack_tuple *tuple)
+{
+ struct nfattr *nest_parms;
+ struct nf_conntrack_l3proto *l3proto;
+ int ret = 0;
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+ if (likely(l3proto->tuple_to_nfattr))
+ ret = l3proto->tuple_to_nfattr(skb, tuple);
+ NFA_NEST_END(skb, nest_parms);
+
+ nf_ct_l3proto_put(l3proto);
+
+ if (unlikely(ret < 0))
+ return ret;
+
+ nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
+ ret = ctnetlink_dump_tuples_proto(skb, tuple);
+ NFA_NEST_END(skb, nest_parms);
+
+ return ret;
+
+nfattr_failure:
+ return -1;
+}
+
+static inline int
+ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *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 nf_conn *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 nf_conn *ct)
+{
+ struct nf_conntrack_protocol *proto = nf_ct_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num, ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+ struct nfattr *nest_proto;
+ int ret;
+
+ if (!proto->to_nfattr) {
+ nf_ct_proto_put(proto);
+ return 0;
+ }
+
+ nest_proto = NFA_NEST(skb, CTA_PROTOINFO);
+
+ ret = proto->to_nfattr(skb, nest_proto, ct);
+
+ nf_ct_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 nf_conn *ct)
+{
+ struct nfattr *nest_helper;
+
+ if (!ct->helper)
+ return 0;
+
+ nest_helper = NFA_NEST(skb, CTA_HELP);
+ NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), 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_NF_CT_ACCT
+static inline int
+ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *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_int32_t tmp;
+
+ tmp = htonl(ct->counters[dir].packets);
+ NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp);
+
+ tmp = htonl(ct->counters[dir].bytes);
+ NFA_PUT(skb, CTA_COUNTERS32_BYTES, sizeof(u_int32_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_NF_CONNTRACK_MARK
+static inline int
+ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *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 nf_conn *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 nf_conn *ct)
+{
+ u_int32_t 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 nf_conn *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 =
+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 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_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 nf_conn *ct = (struct nf_conn *)ptr;
+ struct sk_buff *skb;
+ unsigned int type;
+ unsigned char *b;
+ unsigned int flags = 0, group;
+
+ /* ignore our fake conntrack entry */
+ if (ct == &nf_conntrack_untracked)
+ return NOTIFY_DONE;
+
+ if (events & IPCT_DESTROY) {
+ type = IPCTNL_MSG_CT_DELETE;
+ group = NFNLGRP_CONNTRACK_DESTROY;
+ } else 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;
+ } else if (events & (IPCT_STATUS |
+ IPCT_PROTOINFO |
+ IPCT_HELPER |
+ IPCT_HELPINFO |
+ IPCT_NATINFO)) {
+ type = IPCTNL_MSG_CT_NEW;
+ group = NFNLGRP_CONNTRACK_UPDATE;
+ } else
+ return NOTIFY_DONE;
+
+ /* 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 = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ 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_NF_CONNTRACK_EVENTS */
+
+static int ctnetlink_done(struct netlink_callback *cb)
+{
+ DEBUGP("entered %s\n", __FUNCTION__);
+ return 0;
+}
+
+#define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
+
+static int
+ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct nf_conn *ct = NULL;
+ struct nf_conntrack_tuple_hash *h;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[1];
+ struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+ u_int8_t l3proto = nfmsg->nfgen_family;
+
+ DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__,
+ cb->args[0], *id);
+
+ read_lock_bh(&nf_conntrack_lock);
+ for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) {
+ list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
+ h = (struct nf_conntrack_tuple_hash *) i;
+ if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+ continue;
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ /* Dump entries of a given L3 protocol number.
+ * If it is not specified, ie. l3proto == 0,
+ * then dump everything. */
+ if (l3proto && L3PROTO(ct) != l3proto)
+ continue;
+ 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(&nf_conntrack_lock);
+
+ DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
+
+ return skb->len;
+}
+
+#ifdef CONFIG_NF_CT_ACCT
+static int
+ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct nf_conn *ct = NULL;
+ struct nf_conntrack_tuple_hash *h;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[1];
+ struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+ u_int8_t l3proto = nfmsg->nfgen_family;
+
+ DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__,
+ cb->args[0], *id);
+
+ write_lock_bh(&nf_conntrack_lock);
+ for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) {
+ list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
+ h = (struct nf_conntrack_tuple_hash *) i;
+ if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+ continue;
+ ct = nf_ct_tuplehash_to_ctrack(h);
+ if (l3proto && L3PROTO(ct) != l3proto)
+ continue;
+ 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(&nf_conntrack_lock);
+
+ DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
+
+ return skb->len;
+}
+#endif
+
+static inline int
+ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple)
+{
+ struct nfattr *tb[CTA_IP_MAX];
+ struct nf_conntrack_l3proto *l3proto;
+ int ret = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ nfattr_parse_nested(tb, CTA_IP_MAX, attr);
+
+ l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+
+ if (likely(l3proto->nfattr_to_tuple))
+ ret = l3proto->nfattr_to_tuple(tb, tuple);
+
+ nf_ct_l3proto_put(l3proto);
+
+ DEBUGP("leaving\n");
+
+ return ret;
+}
+
+static const size_t cta_min_proto[CTA_PROTO_MAX] = {
+ [CTA_PROTO_NUM-1] = sizeof(u_int8_t),
+};
+
+static inline int
+ctnetlink_parse_tuple_proto(struct nfattr *attr,
+ struct nf_conntrack_tuple *tuple)
+{
+ struct nfattr *tb[CTA_PROTO_MAX];
+ struct nf_conntrack_protocol *proto;
+ int ret = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ nfattr_parse_nested(tb, CTA_PROTO_MAX, attr);
+
+ 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_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+
+ proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+
+ if (likely(proto->nfattr_to_tuple))
+ ret = proto->nfattr_to_tuple(tb, tuple);
+
+ nf_ct_proto_put(proto);
+
+ return ret;
+}
+
+static inline int
+ctnetlink_parse_tuple(struct nfattr *cda[], struct nf_conntrack_tuple *tuple,
+ enum ctattr_tuple type, u_int8_t l3num)
+{
+ struct nfattr *tb[CTA_TUPLE_MAX];
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ memset(tuple, 0, sizeof(*tuple));
+
+ nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]);
+
+ if (!tb[CTA_TUPLE_IP-1])
+ return -EINVAL;
+
+ tuple->src.l3num = l3num;
+
+ 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;
+
+ NF_CT_DUMP_TUPLE(tuple);
+
+ DEBUGP("leaving\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+static const size_t 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 nf_conn *ct,
+ struct ip_nat_range *range)
+{
+ struct nfattr *tb[CTA_PROTONAT_MAX];
+ struct ip_nat_protocol *npt;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr);
+
+ if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat))
+ return -EINVAL;
+
+ npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum);
+
+ 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;
+}
+
+static const size_t cta_min_nat[CTA_NAT_MAX] = {
+ [CTA_NAT_MINIP-1] = sizeof(u_int32_t),
+ [CTA_NAT_MAXIP-1] = sizeof(u_int32_t),
+};
+
+static inline int
+ctnetlink_parse_nat(struct nfattr *cda[],
+ const struct nf_conn *ct, struct ip_nat_range *range)
+{
+ struct nfattr *tb[CTA_NAT_MAX];
+ int err;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ memset(range, 0, sizeof(*range));
+
+ nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+
+ if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
+ return -EINVAL;
+
+ 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;
+}
+#endif
+
+static inline int
+ctnetlink_parse_help(struct nfattr *attr, char **helper_name)
+{
+ struct nfattr *tb[CTA_HELP_MAX];
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ nfattr_parse_nested(tb, CTA_HELP_MAX, attr);
+
+ if (!tb[CTA_HELP_NAME-1])
+ return -EINVAL;
+
+ *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]);
+
+ return 0;
+}
+
+static const size_t cta_min[CTA_MAX] = {
+ [CTA_STATUS-1] = sizeof(u_int32_t),
+ [CTA_TIMEOUT-1] = sizeof(u_int32_t),
+ [CTA_MARK-1] = sizeof(u_int32_t),
+ [CTA_USE-1] = sizeof(u_int32_t),
+ [CTA_ID-1] = sizeof(u_int32_t)
+};
+
+static int
+ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_tuple tuple;
+ struct nf_conn *ct;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_bad_size(cda, CTA_MAX, cta_min))
+ return -EINVAL;
+
+ if (cda[CTA_TUPLE_ORIG-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
+ else {
+ /* Flush the whole table */
+ nf_conntrack_flush();
+ return 0;
+ }
+
+ if (err < 0)
+ return err;
+
+ h = nf_conntrack_find_get(&tuple, NULL);
+ if (!h) {
+ DEBUGP("tuple not found in conntrack hash\n");
+ return -ENOENT;
+ }
+
+ ct = nf_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) {
+ nf_ct_put(ct);
+ return -ENOENT;
+ }
+ }
+ if (del_timer(&ct->timeout))
+ ct->timeout.function((unsigned long)ct);
+
+ nf_ct_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 nf_conntrack_tuple_hash *h;
+ struct nf_conntrack_tuple tuple;
+ struct nf_conn *ct;
+ struct sk_buff *skb2 = NULL;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ u32 rlen;
+
+ if (NFNL_MSG_TYPE(nlh->nlmsg_type) ==
+ IPCTNL_MSG_CT_GET_CTRZERO) {
+#ifdef CONFIG_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 (nfattr_bad_size(cda, CTA_MAX, cta_min))
+ return -EINVAL;
+
+ if (cda[CTA_TUPLE_ORIG-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
+ else
+ return -EINVAL;
+
+ if (err < 0)
+ return err;
+
+ h = nf_conntrack_find_get(&tuple, NULL);
+ if (!h) {
+ DEBUGP("tuple not found in conntrack hash");
+ return -ENOENT;
+ }
+ DEBUGP("tuple found\n");
+ ct = nf_ct_tuplehash_to_ctrack(h);
+
+ err = -ENOMEM;
+ skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!skb2) {
+ nf_ct_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);
+ nf_ct_put(ct);
+ if (err <= 0)
+ goto free;
+
+ err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+ if (err < 0)
+ goto out;
+
+ DEBUGP("leaving\n");
+ return 0;
+
+free:
+ kfree_skb(skb2);
+out:
+ return err;
+}
+
+static inline int
+ctnetlink_change_status(struct nf_conn *ct, struct nfattr *cda[])
+{
+ unsigned long d;
+ unsigned status = ntohl(*(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, HOOK2MANIP(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 nf_conn *ct, struct nfattr *cda[])
+{
+ struct nf_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 = __nf_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 ... */
+ nf_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 nf_conn *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 inline int
+ctnetlink_change_protoinfo(struct nf_conn *ct, struct nfattr *cda[])
+{
+ struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1];
+ struct nf_conntrack_protocol *proto;
+ u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
+ u_int16_t l3num = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
+ int err = 0;
+
+ nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
+
+ proto = nf_ct_proto_find_get(l3num, npt);
+
+ if (proto->from_nfattr)
+ err = proto->from_nfattr(tb, ct);
+ nf_ct_proto_put(proto);
+
+ return err;
+}
+
+static int
+ctnetlink_change_conntrack(struct nf_conn *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;
+ }
+
+ if (cda[CTA_PROTOINFO-1]) {
+ err = ctnetlink_change_protoinfo(ct, cda);
+ if (err < 0)
+ return err;
+ }
+
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ if (cda[CTA_MARK-1])
+ ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+#endif
+
+ DEBUGP("all done\n");
+ return 0;
+}
+
+static int
+ctnetlink_create_conntrack(struct nfattr *cda[],
+ struct nf_conntrack_tuple *otuple,
+ struct nf_conntrack_tuple *rtuple)
+{
+ struct nf_conn *ct;
+ int err = -EINVAL;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ ct = nf_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;
+
+ if (cda[CTA_PROTOINFO-1]) {
+ err = ctnetlink_change_protoinfo(ct, cda);
+ if (err < 0)
+ return err;
+ }
+
+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
+ if (cda[CTA_MARK-1])
+ ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+#endif
+
+ ct->helper = nf_ct_helper_find_get(rtuple);
+
+ add_timer(&ct->timeout);
+ nf_conntrack_hash_insert(ct);
+
+ if (ct->helper)
+ nf_ct_helper_put(ct->helper);
+
+ DEBUGP("conntrack with id %u inserted\n", ct->id);
+ return 0;
+
+err:
+ nf_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 nf_conntrack_tuple otuple, rtuple;
+ struct nf_conntrack_tuple_hash *h = NULL;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_bad_size(cda, CTA_MAX, cta_min))
+ return -EINVAL;
+
+ if (cda[CTA_TUPLE_ORIG-1]) {
+ err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
+ if (err < 0)
+ return err;
+ }
+
+ if (cda[CTA_TUPLE_REPLY-1]) {
+ err = ctnetlink_parse_tuple(cda, &rtuple, CTA_TUPLE_REPLY, u3);
+ if (err < 0)
+ return err;
+ }
+
+ write_lock_bh(&nf_conntrack_lock);
+ if (cda[CTA_TUPLE_ORIG-1])
+ h = __nf_conntrack_find(&otuple, NULL);
+ else if (cda[CTA_TUPLE_REPLY-1])
+ h = __nf_conntrack_find(&rtuple, NULL);
+
+ if (h == NULL) {
+ write_unlock_bh(&nf_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(nf_ct_tuplehash_to_ctrack(h), cda);
+
+out_unlock:
+ write_unlock_bh(&nf_conntrack_lock);
+ return err;
+}
+
+/***********************************************************************
+ * EXPECT
+ ***********************************************************************/
+
+static inline int
+ctnetlink_exp_dump_tuple(struct sk_buff *skb,
+ const struct nf_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 nf_conntrack_expect *exp)
+{
+ struct nf_conn *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 nf_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 = exp->tuple.src.l3num;
+ 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_NF_CONNTRACK_EVENTS
+static int ctnetlink_expect_event(struct notifier_block *this,
+ unsigned long events, void *ptr)
+{
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ struct nf_conntrack_expect *exp = (struct nf_conntrack_expect *)ptr;
+ struct sk_buff *skb;
+ unsigned int type;
+ unsigned char *b;
+ int flags = 0;
+
+ 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 = exp->tuple.src.l3num;
+ 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;
+ 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 nf_conntrack_expect *exp = NULL;
+ struct list_head *i;
+ u_int32_t *id = (u_int32_t *) &cb->args[0];
+ struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+ u_int8_t l3proto = nfmsg->nfgen_family;
+
+ DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
+
+ read_lock_bh(&nf_conntrack_lock);
+ list_for_each_prev(i, &nf_conntrack_expect_list) {
+ exp = (struct nf_conntrack_expect *) i;
+ if (l3proto && exp->tuple.src.l3num != l3proto)
+ continue;
+ 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(&nf_conntrack_lock);
+
+ DEBUGP("leaving, last id=%llu\n", *id);
+
+ return skb->len;
+}
+
+static const size_t cta_min_exp[CTA_EXPECT_MAX] = {
+ [CTA_EXPECT_TIMEOUT-1] = sizeof(u_int32_t),
+ [CTA_EXPECT_ID-1] = sizeof(u_int32_t)
+};
+
+static int
+ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_expect *exp;
+ struct sk_buff *skb2;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
+ return -EINVAL;
+
+ if (nlh->nlmsg_flags & NLM_F_DUMP) {
+ u32 rlen;
+
+ 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, u3);
+ else
+ return -EINVAL;
+
+ if (err < 0)
+ return err;
+
+ exp = nf_conntrack_expect_find(&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)) {
+ nf_conntrack_expect_put(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 free;
+
+ nf_conntrack_expect_put(exp);
+
+ return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+
+free:
+ kfree_skb(skb2);
+out:
+ nf_conntrack_expect_put(exp);
+ return err;
+}
+
+static int
+ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
+ struct nlmsghdr *nlh, struct nfattr *cda[], int *errp)
+{
+ struct nf_conntrack_expect *exp, *tmp;
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_helper *h;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err;
+
+ if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
+ return -EINVAL;
+
+ if (cda[CTA_EXPECT_TUPLE-1]) {
+ /* delete a single expect by tuple */
+ err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
+ if (err < 0)
+ return err;
+
+ /* bump usage count to 2 */
+ exp = nf_conntrack_expect_find(&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)) {
+ nf_conntrack_expect_put(exp);
+ return -ENOENT;
+ }
+ }
+
+ /* after list removal, usage count == 1 */
+ nf_conntrack_unexpect_related(exp);
+ /* have to put what we 'get' above.
+ * after this line usage count == 0 */
+ nf_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(&nf_conntrack_lock);
+ h = __nf_conntrack_helper_find_byname(name);
+ if (!h) {
+ write_unlock_bh(&nf_conntrack_lock);
+ return -EINVAL;
+ }
+ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
+ list) {
+ if (exp->master->helper == h
+ && del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_conntrack_expect_put(exp);
+ }
+ }
+ write_unlock_bh(&nf_conntrack_lock);
+ } else {
+ /* This basically means we have to flush everything*/
+ write_lock_bh(&nf_conntrack_lock);
+ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
+ list) {
+ if (del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_conntrack_expect_put(exp);
+ }
+ }
+ write_unlock_bh(&nf_conntrack_lock);
+ }
+
+ return 0;
+}
+static int
+ctnetlink_change_expect(struct nf_conntrack_expect *x, struct nfattr *cda[])
+{
+ return -EOPNOTSUPP;
+}
+
+static int
+ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
+{
+ struct nf_conntrack_tuple tuple, mask, master_tuple;
+ struct nf_conntrack_tuple_hash *h = NULL;
+ struct nf_conntrack_expect *exp;
+ struct nf_conn *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, u3);
+ if (err < 0)
+ return err;
+ err = ctnetlink_parse_tuple(cda, &mask, CTA_EXPECT_MASK, u3);
+ if (err < 0)
+ return err;
+ err = ctnetlink_parse_tuple(cda, &master_tuple, CTA_EXPECT_MASTER, u3);
+ if (err < 0)
+ return err;
+
+ /* Look for master conntrack of this expectation */
+ h = nf_conntrack_find_get(&master_tuple, NULL);
+ if (!h)
+ return -ENOENT;
+ ct = nf_ct_tuplehash_to_ctrack(h);
+
+ if (!ct->helper) {
+ /* such conntrack hasn't got any helper, abort */
+ err = -EINVAL;
+ goto out;
+ }
+
+ exp = nf_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 nf_conntrack_tuple));
+ memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
+
+ err = nf_conntrack_expect_related(exp);
+ nf_conntrack_expect_put(exp);
+
+out:
+ nf_ct_put(nf_ct_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 nf_conntrack_tuple tuple;
+ struct nf_conntrack_expect *exp;
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ u_int8_t u3 = nfmsg->nfgen_family;
+ int err = 0;
+
+ DEBUGP("entered %s\n", __FUNCTION__);
+
+ if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
+ return -EINVAL;
+
+ 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, u3);
+ if (err < 0)
+ return err;
+
+ write_lock_bh(&nf_conntrack_lock);
+ exp = __nf_conntrack_expect_find(&tuple);
+
+ if (!exp) {
+ write_unlock_bh(&nf_conntrack_lock);
+ err = -ENOENT;
+ if (nlh->nlmsg_flags & NLM_F_CREATE)
+ err = ctnetlink_create_expect(cda, u3);
+ return err;
+ }
+
+ err = -EEXIST;
+ if (!(nlh->nlmsg_flags & NLM_F_EXCL))
+ err = ctnetlink_change_expect(exp, cda);
+ write_unlock_bh(&nf_conntrack_lock);
+
+ DEBUGP("leaving\n");
+
+ return err;
+}
+
+#ifdef CONFIG_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, },
+ [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack,
+ .attr_count = CTA_MAX, },
+ [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack,
+ .attr_count = CTA_MAX, },
+ [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
+ .attr_count = CTA_MAX, },
+};
+
+static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
+ [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect,
+ .attr_count = CTA_EXPECT_MAX, },
+ [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect,
+ .attr_count = CTA_EXPECT_MAX, },
+ [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
+ .attr_count = CTA_EXPECT_MAX, },
+};
+
+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,
+};
+
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
+
+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_NF_CONNTRACK_EVENTS
+ ret = nf_conntrack_register_notifier(&ctnl_notifier);
+ if (ret < 0) {
+ printk("ctnetlink_init: cannot register notifier.\n");
+ goto err_unreg_exp_subsys;
+ }
+
+ ret = nf_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_NF_CONNTRACK_EVENTS
+err_unreg_notifier:
+ nf_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_NF_CONNTRACK_EVENTS
+ nf_conntrack_unregister_notifier(&ctnl_notifier_exp);
+ nf_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/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 36425f6c833f..46bc27e2756d 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -17,7 +17,7 @@
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_protocol.h>
-unsigned long nf_ct_generic_timeout = 600*HZ;
+unsigned int nf_ct_generic_timeout = 600*HZ;
static int generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 3a600f77b4e0..cf798e61e379 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -62,15 +62,15 @@ static const char *sctp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-static unsigned long nf_ct_sctp_timeout_closed = 10 SECS;
-static unsigned long nf_ct_sctp_timeout_cookie_wait = 3 SECS;
-static unsigned long nf_ct_sctp_timeout_cookie_echoed = 3 SECS;
-static unsigned long nf_ct_sctp_timeout_established = 5 DAYS;
-static unsigned long nf_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
-static unsigned long nf_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
-static unsigned long nf_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
-
-static unsigned long * sctp_timeouts[]
+static unsigned int nf_ct_sctp_timeout_closed = 10 SECS;
+static unsigned int nf_ct_sctp_timeout_cookie_wait = 3 SECS;
+static unsigned int nf_ct_sctp_timeout_cookie_echoed = 3 SECS;
+static unsigned int nf_ct_sctp_timeout_established = 5 DAYS;
+static unsigned int nf_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
+static unsigned int nf_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
+static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
+
+static unsigned int * sctp_timeouts[]
= { NULL, /* SCTP_CONNTRACK_NONE */
&nf_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
&nf_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 6035633d8225..df99138c3b3b 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -93,21 +93,21 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS
#define DAYS * 24 HOURS
-unsigned long nf_ct_tcp_timeout_syn_sent = 2 MINS;
-unsigned long nf_ct_tcp_timeout_syn_recv = 60 SECS;
-unsigned long nf_ct_tcp_timeout_established = 5 DAYS;
-unsigned long nf_ct_tcp_timeout_fin_wait = 2 MINS;
-unsigned long nf_ct_tcp_timeout_close_wait = 60 SECS;
-unsigned long nf_ct_tcp_timeout_last_ack = 30 SECS;
-unsigned long nf_ct_tcp_timeout_time_wait = 2 MINS;
-unsigned long nf_ct_tcp_timeout_close = 10 SECS;
+unsigned int nf_ct_tcp_timeout_syn_sent = 2 MINS;
+unsigned int nf_ct_tcp_timeout_syn_recv = 60 SECS;
+unsigned int nf_ct_tcp_timeout_established = 5 DAYS;
+unsigned int nf_ct_tcp_timeout_fin_wait = 2 MINS;
+unsigned int nf_ct_tcp_timeout_close_wait = 60 SECS;
+unsigned int nf_ct_tcp_timeout_last_ack = 30 SECS;
+unsigned int nf_ct_tcp_timeout_time_wait = 2 MINS;
+unsigned int nf_ct_tcp_timeout_close = 10 SECS;
/* RFC1122 says the R2 limit should be at least 100 seconds.
Linux uses 15 packets as limit, which corresponds
to ~13-30min depending on RTO. */
-unsigned long nf_ct_tcp_timeout_max_retrans = 5 MINS;
+unsigned int nf_ct_tcp_timeout_max_retrans = 5 MINS;
-static unsigned long * tcp_timeouts[]
+static unsigned int * tcp_timeouts[]
= { NULL, /* TCP_CONNTRACK_NONE */
&nf_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
&nf_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
@@ -988,7 +988,7 @@ static int tcp_packet(struct nf_conn *conntrack,
|| (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
&& conntrack->proto.tcp.last_index == TCP_ACK_SET))
&& ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
- /* RST sent to invalid SYN or ACK we had let trough
+ /* RST sent to invalid SYN or ACK we had let through
* at a) and c) above:
*
* a) SYN was in window then
@@ -999,7 +999,7 @@ static int tcp_packet(struct nf_conn *conntrack,
* segments we ignored. */
goto in_window;
}
- /* Just fall trough */
+ /* Just fall through */
default:
/* Keep compilers happy. */
break;
@@ -1147,6 +1147,63 @@ static int tcp_new(struct nf_conn *conntrack,
receiver->td_scale);
return 1;
}
+
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
+ const struct nf_conn *ct)
+{
+ struct nfattr *nest_parms;
+
+ read_lock_bh(&tcp_lock);
+ nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
+ NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
+ &ct->proto.tcp.state);
+ read_unlock_bh(&tcp_lock);
+
+ NFA_NEST_END(skb, nest_parms);
+
+ return 0;
+
+nfattr_failure:
+ read_unlock_bh(&tcp_lock);
+ return -1;
+}
+
+static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
+ [CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
+};
+
+static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
+{
+ struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1];
+ struct nfattr *tb[CTA_PROTOINFO_TCP_MAX];
+
+ /* updates could not contain anything about the private
+ * protocol info, in that case skip the parsing */
+ if (!attr)
+ return 0;
+
+ nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr);
+
+ if (nfattr_bad_size(tb, CTA_PROTOINFO_TCP_MAX, cta_min_tcp))
+ return -EINVAL;
+
+ if (!tb[CTA_PROTOINFO_TCP_STATE-1])
+ return -EINVAL;
+
+ write_lock_bh(&tcp_lock);
+ ct->proto.tcp.state =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
+ write_unlock_bh(&tcp_lock);
+
+ return 0;
+}
+#endif
struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
{
@@ -1160,6 +1217,13 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp4 =
.packet = tcp_packet,
.new = tcp_new,
.error = tcp_error4,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .to_nfattr = tcp_to_nfattr,
+ .from_nfattr = nfattr_to_tcp,
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
};
struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
@@ -1174,6 +1238,13 @@ struct nf_conntrack_protocol nf_conntrack_protocol_tcp6 =
.packet = tcp_packet,
.new = tcp_new,
.error = tcp_error6,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .to_nfattr = tcp_to_nfattr,
+ .from_nfattr = nfattr_to_tcp,
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
};
EXPORT_SYMBOL(nf_conntrack_protocol_tcp4);
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 3cae7ce420dd..4264dd079a16 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -27,8 +27,8 @@
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_protocol.h>
-unsigned long nf_ct_udp_timeout = 30*HZ;
-unsigned long nf_ct_udp_timeout_stream = 180*HZ;
+unsigned int nf_ct_udp_timeout = 30*HZ;
+unsigned int nf_ct_udp_timeout_stream = 180*HZ;
static int udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
@@ -196,6 +196,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp4 =
.packet = udp_packet,
.new = udp_new,
.error = udp_error4,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
};
struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
@@ -210,6 +215,11 @@ struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
.packet = udp_packet,
.new = udp_new,
.error = udp_error6,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
};
EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 5af381f9fe3d..617599aeeead 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -161,14 +161,14 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (NF_CT_DIRECTION(hash))
return 0;
- l3proto = nf_ct_find_l3proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.src.l3num);
+ l3proto = __nf_ct_l3proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.src.l3num);
NF_CT_ASSERT(l3proto);
- proto = nf_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.src.l3num,
- conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
- .tuple.dst.protonum);
+ proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.src.l3num,
+ conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+ .tuple.dst.protonum);
NF_CT_ASSERT(proto);
if (seq_printf(s, "%-8s %u %-8s %u %ld ",
@@ -307,9 +307,9 @@ static int exp_seq_show(struct seq_file *s, void *v)
expect->tuple.src.l3num,
expect->tuple.dst.protonum);
print_tuple(s, &expect->tuple,
- nf_ct_find_l3proto(expect->tuple.src.l3num),
- nf_ct_find_proto(expect->tuple.src.l3num,
- expect->tuple.dst.protonum));
+ __nf_ct_l3proto_find(expect->tuple.src.l3num),
+ __nf_ct_proto_find(expect->tuple.src.l3num,
+ expect->tuple.dst.protonum));
return seq_putc(s, '\n');
}
@@ -431,25 +431,25 @@ extern int nf_conntrack_max;
extern unsigned int nf_conntrack_htable_size;
/* From nf_conntrack_proto_tcp.c */
-extern unsigned long nf_ct_tcp_timeout_syn_sent;
-extern unsigned long nf_ct_tcp_timeout_syn_recv;
-extern unsigned long nf_ct_tcp_timeout_established;
-extern unsigned long nf_ct_tcp_timeout_fin_wait;
-extern unsigned long nf_ct_tcp_timeout_close_wait;
-extern unsigned long nf_ct_tcp_timeout_last_ack;
-extern unsigned long nf_ct_tcp_timeout_time_wait;
-extern unsigned long nf_ct_tcp_timeout_close;
-extern unsigned long nf_ct_tcp_timeout_max_retrans;
+extern unsigned int nf_ct_tcp_timeout_syn_sent;
+extern unsigned int nf_ct_tcp_timeout_syn_recv;
+extern unsigned int nf_ct_tcp_timeout_established;
+extern unsigned int nf_ct_tcp_timeout_fin_wait;
+extern unsigned int nf_ct_tcp_timeout_close_wait;
+extern unsigned int nf_ct_tcp_timeout_last_ack;
+extern unsigned int nf_ct_tcp_timeout_time_wait;
+extern unsigned int nf_ct_tcp_timeout_close;
+extern unsigned int nf_ct_tcp_timeout_max_retrans;
extern int nf_ct_tcp_loose;
extern int nf_ct_tcp_be_liberal;
extern int nf_ct_tcp_max_retrans;
/* From nf_conntrack_proto_udp.c */
-extern unsigned long nf_ct_udp_timeout;
-extern unsigned long nf_ct_udp_timeout_stream;
+extern unsigned int nf_ct_udp_timeout;
+extern unsigned int nf_ct_udp_timeout_stream;
/* From nf_conntrack_proto_generic.c */
-extern unsigned long nf_ct_generic_timeout;
+extern unsigned int nf_ct_generic_timeout;
/* Log invalid packets of a given protocol */
static int log_invalid_proto_min = 0;
@@ -821,7 +821,7 @@ module_exit(fini);
/* Some modules need us, but don't depend directly on any symbol.
They should call this. */
-void need_nf_conntrack(void)
+void need_conntrack(void)
{
}
@@ -841,13 +841,17 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
EXPORT_SYMBOL(nf_ct_invert_tuplepr);
EXPORT_SYMBOL(nf_conntrack_alter_reply);
EXPORT_SYMBOL(nf_conntrack_destroyed);
-EXPORT_SYMBOL(need_nf_conntrack);
+EXPORT_SYMBOL(need_conntrack);
EXPORT_SYMBOL(nf_conntrack_helper_register);
EXPORT_SYMBOL(nf_conntrack_helper_unregister);
EXPORT_SYMBOL(nf_ct_iterate_cleanup);
EXPORT_SYMBOL(__nf_ct_refresh_acct);
EXPORT_SYMBOL(nf_ct_protos);
-EXPORT_SYMBOL(nf_ct_find_proto);
+EXPORT_SYMBOL(__nf_ct_proto_find);
+EXPORT_SYMBOL(nf_ct_proto_find_get);
+EXPORT_SYMBOL(nf_ct_proto_put);
+EXPORT_SYMBOL(nf_ct_l3proto_find_get);
+EXPORT_SYMBOL(nf_ct_l3proto_put);
EXPORT_SYMBOL(nf_ct_l3protos);
EXPORT_SYMBOL(nf_conntrack_expect_alloc);
EXPORT_SYMBOL(nf_conntrack_expect_put);
@@ -867,3 +871,21 @@ EXPORT_SYMBOL(nf_ct_get_tuple);
EXPORT_SYMBOL(nf_ct_invert_tuple);
EXPORT_SYMBOL(nf_conntrack_in);
EXPORT_SYMBOL(__nf_conntrack_attach);
+EXPORT_SYMBOL(nf_conntrack_alloc);
+EXPORT_SYMBOL(nf_conntrack_free);
+EXPORT_SYMBOL(nf_conntrack_flush);
+EXPORT_SYMBOL(nf_ct_remove_expectations);
+EXPORT_SYMBOL(nf_ct_helper_find_get);
+EXPORT_SYMBOL(nf_ct_helper_put);
+EXPORT_SYMBOL(__nf_conntrack_helper_find_byname);
+EXPORT_SYMBOL(__nf_conntrack_find);
+EXPORT_SYMBOL(nf_ct_unlink_expect);
+EXPORT_SYMBOL(nf_conntrack_hash_insert);
+EXPORT_SYMBOL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_list);
+#if defined(CONFIG_NF_CT_NETLINK) || \
+ defined(CONFIG_NF_CT_NETLINK_MODULE)
+EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr);
+EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple);
+#endif
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 95fdf04f1d88..f6063e8f0050 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -212,7 +212,7 @@ int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags)
}
/* Process one complete nfnetlink message. */
-static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
+static int nfnetlink_rcv_msg(struct sk_buff *skb,
struct nlmsghdr *nlh, int *errp)
{
struct nfnl_callback *nc;
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index cba63729313d..e10512e229b6 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -151,7 +151,7 @@ instance_create(u_int16_t group_num, int pid)
goto out_unlock;
INIT_HLIST_NODE(&inst->hlist);
- inst->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&inst->lock);
/* needs to be two, since we _put() after creation */
atomic_set(&inst->use, 2);
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index f28460b61e47..18ed9c5d209c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -148,7 +148,7 @@ instance_create(u_int16_t queue_num, int pid)
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;
+ spin_lock_init(&inst->lock);
INIT_LIST_HEAD(&inst->queue_list);
if (!try_module_get(THIS_MODULE))
@@ -345,6 +345,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct nfqnl_msg_packet_hdr pmsg;
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
+ struct nf_info *entinf = entry->info;
+ struct sk_buff *entskb = entry->skb;
+ struct net_device *indev;
+ struct net_device *outdev;
unsigned int tmp_uint;
QDEBUG("entered\n");
@@ -361,6 +365,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
+ NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_hw))
+ NLMSG_SPACE(sizeof(struct nfqnl_msg_packet_timestamp));
+ outdev = entinf->outdev;
+
spin_lock_bh(&queue->lock);
switch (queue->copy_mode) {
@@ -370,15 +376,15 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
break;
case NFQNL_COPY_PACKET:
- if (entry->skb->ip_summed == CHECKSUM_HW &&
- (*errp = skb_checksum_help(entry->skb,
- entry->info->outdev == NULL))) {
+ if (entskb->ip_summed == CHECKSUM_HW &&
+ (*errp = skb_checksum_help(entskb,
+ 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;
+ || queue->copy_range > entskb->len)
+ data_len = entskb->len;
else
data_len = queue->copy_range;
@@ -402,29 +408,30 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
sizeof(struct nfgenmsg));
nfmsg = NLMSG_DATA(nlh);
- nfmsg->nfgen_family = entry->info->pf;
+ nfmsg->nfgen_family = entinf->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;
+ pmsg.hw_protocol = htons(entskb->protocol);
+ pmsg.hook = entinf->hook;
NFA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
- if (entry->info->indev) {
- tmp_uint = htonl(entry->info->indev->ifindex);
+ indev = entinf->indev;
+ if (indev) {
+ tmp_uint = htonl(indev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint), &tmp_uint);
#else
- if (entry->info->pf == PF_BRIDGE) {
+ if (entinf->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);
+ tmp_uint = htonl(indev->br_port->br->dev->ifindex);
NFA_PUT(skb, NFQA_IFINDEX_INDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
@@ -432,9 +439,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
* 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);
+ if (entskb->nf_bridge
+ && entskb->nf_bridge->physindev) {
+ tmp_uint = htonl(entskb->nf_bridge->physindev->ifindex);
NFA_PUT(skb, NFQA_IFINDEX_PHYSINDEV,
sizeof(tmp_uint), &tmp_uint);
}
@@ -442,19 +449,19 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
#endif
}
- if (entry->info->outdev) {
- tmp_uint = htonl(entry->info->outdev->ifindex);
+ if (outdev) {
+ tmp_uint = htonl(outdev->ifindex);
#ifndef CONFIG_BRIDGE_NETFILTER
NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint), &tmp_uint);
#else
- if (entry->info->pf == PF_BRIDGE) {
+ if (entinf->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);
+ tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
NFA_PUT(skb, NFQA_IFINDEX_OUTDEV, sizeof(tmp_uint),
&tmp_uint);
} else {
@@ -462,9 +469,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
* 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);
+ if (entskb->nf_bridge
+ && entskb->nf_bridge->physoutdev) {
+ tmp_uint = htonl(entskb->nf_bridge->physoutdev->ifindex);
NFA_PUT(skb, NFQA_IFINDEX_PHYSOUTDEV,
sizeof(tmp_uint), &tmp_uint);
}
@@ -472,27 +479,27 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
#endif
}
- if (entry->skb->nfmark) {
- tmp_uint = htonl(entry->skb->nfmark);
+ if (entskb->nfmark) {
+ tmp_uint = htonl(entskb->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) {
+ if (indev && entskb->dev
+ && entskb->dev->hard_header_parse) {
struct nfqnl_msg_packet_hw phw;
phw.hw_addrlen =
- entry->skb->dev->hard_header_parse(entry->skb,
+ entskb->dev->hard_header_parse(entskb,
phw.hw_addr);
phw.hw_addrlen = htons(phw.hw_addrlen);
NFA_PUT(skb, NFQA_HWADDR, sizeof(phw), &phw);
}
- if (entry->skb->tstamp.off_sec) {
+ if (entskb->tstamp.off_sec) {
struct nfqnl_msg_packet_timestamp ts;
- ts.sec = cpu_to_be64(entry->skb->tstamp.off_sec);
- ts.usec = cpu_to_be64(entry->skb->tstamp.off_usec);
+ ts.sec = cpu_to_be64(entskb->tstamp.off_sec);
+ ts.usec = cpu_to_be64(entskb->tstamp.off_usec);
NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
}
@@ -510,7 +517,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
nfa->nfa_type = NFQA_PAYLOAD;
nfa->nfa_len = size;
- if (skb_copy_bits(entry->skb, 0, NFA_DATA(nfa), data_len))
+ if (skb_copy_bits(entskb, 0, NFA_DATA(nfa), data_len))
BUG();
}
@@ -667,12 +674,14 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
static int
dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex)
{
- if (entry->info->indev)
- if (entry->info->indev->ifindex == ifindex)
+ struct nf_info *entinf = entry->info;
+
+ if (entinf->indev)
+ if (entinf->indev->ifindex == ifindex)
return 1;
- if (entry->info->outdev)
- if (entry->info->outdev->ifindex == ifindex)
+ if (entinf->outdev)
+ if (entinf->outdev->ifindex == ifindex)
return 1;
return 0;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
new file mode 100644
index 000000000000..d7817afc6b96
--- /dev/null
+++ b/net/netfilter/x_tables.c
@@ -0,0 +1,624 @@
+/*
+ * x_tables core - Backend for {ip,ip6,arp}_tables
+ *
+ * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
+ *
+ * Based on existing ip_tables code which is
+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+ * Copyright (C) 2000-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/config.h>
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <linux/net.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter_arp.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
+
+#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
+
+struct xt_af {
+ struct semaphore mutex;
+ struct list_head match;
+ struct list_head target;
+ struct list_head tables;
+};
+
+static struct xt_af *xt;
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+enum {
+ TABLE,
+ TARGET,
+ MATCH,
+};
+
+/* Registration hooks for targets. */
+int
+xt_register_target(int af, struct xt_target *target)
+{
+ int ret;
+
+ ret = down_interruptible(&xt[af].mutex);
+ if (ret != 0)
+ return ret;
+ list_add(&target->list, &xt[af].target);
+ up(&xt[af].mutex);
+ return ret;
+}
+EXPORT_SYMBOL(xt_register_target);
+
+void
+xt_unregister_target(int af, struct xt_target *target)
+{
+ down(&xt[af].mutex);
+ LIST_DELETE(&xt[af].target, target);
+ up(&xt[af].mutex);
+}
+EXPORT_SYMBOL(xt_unregister_target);
+
+int
+xt_register_match(int af, struct xt_match *match)
+{
+ int ret;
+
+ ret = down_interruptible(&xt[af].mutex);
+ if (ret != 0)
+ return ret;
+
+ list_add(&match->list, &xt[af].match);
+ up(&xt[af].mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(xt_register_match);
+
+void
+xt_unregister_match(int af, struct xt_match *match)
+{
+ down(&xt[af].mutex);
+ LIST_DELETE(&xt[af].match, match);
+ up(&xt[af].mutex);
+}
+EXPORT_SYMBOL(xt_unregister_match);
+
+
+/*
+ * These are weird, but module loading must not be done with mutex
+ * held (since they will register), and we have to have a single
+ * function to use try_then_request_module().
+ */
+
+/* Find match, grabs ref. Returns ERR_PTR() on error. */
+struct xt_match *xt_find_match(int af, const char *name, u8 revision)
+{
+ struct xt_match *m;
+ int err = 0;
+
+ if (down_interruptible(&xt[af].mutex) != 0)
+ return ERR_PTR(-EINTR);
+
+ list_for_each_entry(m, &xt[af].match, list) {
+ if (strcmp(m->name, name) == 0) {
+ if (m->revision == revision) {
+ if (try_module_get(m->me)) {
+ up(&xt[af].mutex);
+ return m;
+ }
+ } else
+ err = -EPROTOTYPE; /* Found something. */
+ }
+ }
+ up(&xt[af].mutex);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(xt_find_match);
+
+/* Find target, grabs ref. Returns ERR_PTR() on error. */
+struct xt_target *xt_find_target(int af, const char *name, u8 revision)
+{
+ struct xt_target *t;
+ int err = 0;
+
+ if (down_interruptible(&xt[af].mutex) != 0)
+ return ERR_PTR(-EINTR);
+
+ list_for_each_entry(t, &xt[af].target, list) {
+ if (strcmp(t->name, name) == 0) {
+ if (t->revision == revision) {
+ if (try_module_get(t->me)) {
+ up(&xt[af].mutex);
+ return t;
+ }
+ } else
+ err = -EPROTOTYPE; /* Found something. */
+ }
+ }
+ up(&xt[af].mutex);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(xt_find_target);
+
+static const char *xt_prefix[NPROTO] = {
+ [AF_INET] = "ipt_%s",
+ [AF_INET6] = "ip6t_%s",
+ [NF_ARP] = "arpt_%s",
+};
+
+struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
+{
+ struct xt_target *target;
+
+ target = try_then_request_module(xt_find_target(af, name, revision),
+ xt_prefix[af], name);
+ if (IS_ERR(target) || !target)
+ return NULL;
+ return target;
+}
+EXPORT_SYMBOL_GPL(xt_request_find_target);
+
+static int match_revfn(int af, const char *name, u8 revision, int *bestp)
+{
+ struct xt_match *m;
+ int have_rev = 0;
+
+ list_for_each_entry(m, &xt[af].match, list) {
+ if (strcmp(m->name, name) == 0) {
+ if (m->revision > *bestp)
+ *bestp = m->revision;
+ if (m->revision == revision)
+ have_rev = 1;
+ }
+ }
+ return have_rev;
+}
+
+static int target_revfn(int af, const char *name, u8 revision, int *bestp)
+{
+ struct xt_target *t;
+ int have_rev = 0;
+
+ list_for_each_entry(t, &xt[af].target, list) {
+ if (strcmp(t->name, name) == 0) {
+ if (t->revision > *bestp)
+ *bestp = t->revision;
+ if (t->revision == revision)
+ have_rev = 1;
+ }
+ }
+ return have_rev;
+}
+
+/* Returns true or false (if no such extension at all) */
+int xt_find_revision(int af, const char *name, u8 revision, int target,
+ int *err)
+{
+ int have_rev, best = -1;
+
+ if (down_interruptible(&xt[af].mutex) != 0) {
+ *err = -EINTR;
+ return 1;
+ }
+ if (target == 1)
+ have_rev = target_revfn(af, name, revision, &best);
+ else
+ have_rev = match_revfn(af, name, revision, &best);
+ up(&xt[af].mutex);
+
+ /* Nothing at all? Return 0 to try loading module. */
+ if (best == -1) {
+ *err = -ENOENT;
+ return 0;
+ }
+
+ *err = best;
+ if (!have_rev)
+ *err = -EPROTONOSUPPORT;
+ return 1;
+}
+EXPORT_SYMBOL_GPL(xt_find_revision);
+
+struct xt_table_info *xt_alloc_table_info(unsigned int size)
+{
+ struct xt_table_info *newinfo;
+ int cpu;
+
+ /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
+ if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
+ return NULL;
+
+ newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
+ if (!newinfo)
+ return NULL;
+
+ newinfo->size = size;
+
+ for_each_cpu(cpu) {
+ if (size <= PAGE_SIZE)
+ newinfo->entries[cpu] = kmalloc_node(size,
+ GFP_KERNEL,
+ cpu_to_node(cpu));
+ else
+ newinfo->entries[cpu] = vmalloc_node(size,
+ cpu_to_node(cpu));
+
+ if (newinfo->entries[cpu] == NULL) {
+ xt_free_table_info(newinfo);
+ return NULL;
+ }
+ }
+
+ return newinfo;
+}
+EXPORT_SYMBOL(xt_alloc_table_info);
+
+void xt_free_table_info(struct xt_table_info *info)
+{
+ int cpu;
+
+ for_each_cpu(cpu) {
+ if (info->size <= PAGE_SIZE)
+ kfree(info->entries[cpu]);
+ else
+ vfree(info->entries[cpu]);
+ }
+ kfree(info);
+}
+EXPORT_SYMBOL(xt_free_table_info);
+
+/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
+struct xt_table *xt_find_table_lock(int af, const char *name)
+{
+ struct xt_table *t;
+
+ if (down_interruptible(&xt[af].mutex) != 0)
+ return ERR_PTR(-EINTR);
+
+ list_for_each_entry(t, &xt[af].tables, list)
+ if (strcmp(t->name, name) == 0 && try_module_get(t->me))
+ return t;
+ up(&xt[af].mutex);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(xt_find_table_lock);
+
+void xt_table_unlock(struct xt_table *table)
+{
+ up(&xt[table->af].mutex);
+}
+EXPORT_SYMBOL_GPL(xt_table_unlock);
+
+
+struct xt_table_info *
+xt_replace_table(struct xt_table *table,
+ unsigned int num_counters,
+ struct xt_table_info *newinfo,
+ int *error)
+{
+ struct xt_table_info *oldinfo, *private;
+
+ /* Do the substitution. */
+ write_lock_bh(&table->lock);
+ private = table->private;
+ /* Check inside lock: is the old number correct? */
+ if (num_counters != private->number) {
+ duprintf("num_counters != table->private->number (%u/%u)\n",
+ num_counters, private->number);
+ write_unlock_bh(&table->lock);
+ *error = -EAGAIN;
+ return NULL;
+ }
+ oldinfo = private;
+ table->private = newinfo;
+ newinfo->initial_entries = oldinfo->initial_entries;
+ write_unlock_bh(&table->lock);
+
+ return oldinfo;
+}
+EXPORT_SYMBOL_GPL(xt_replace_table);
+
+int xt_register_table(struct xt_table *table,
+ struct xt_table_info *bootstrap,
+ struct xt_table_info *newinfo)
+{
+ int ret;
+ struct xt_table_info *private;
+
+ ret = down_interruptible(&xt[table->af].mutex);
+ if (ret != 0)
+ return ret;
+
+ /* Don't autoload: we'd eat our tail... */
+ if (list_named_find(&xt[table->af].tables, table->name)) {
+ ret = -EEXIST;
+ goto unlock;
+ }
+
+ /* Simplifies replace_table code. */
+ table->private = bootstrap;
+ if (!xt_replace_table(table, 0, newinfo, &ret))
+ goto unlock;
+
+ private = table->private;
+ duprintf("table->private->number = %u\n", private->number);
+
+ /* save number of initial entries */
+ private->initial_entries = private->number;
+
+ rwlock_init(&table->lock);
+ list_prepend(&xt[table->af].tables, table);
+
+ ret = 0;
+ unlock:
+ up(&xt[table->af].mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xt_register_table);
+
+void *xt_unregister_table(struct xt_table *table)
+{
+ struct xt_table_info *private;
+
+ down(&xt[table->af].mutex);
+ private = table->private;
+ LIST_DELETE(&xt[table->af].tables, table);
+ up(&xt[table->af].mutex);
+
+ return private;
+}
+EXPORT_SYMBOL_GPL(xt_unregister_table);
+
+#ifdef CONFIG_PROC_FS
+static char *xt_proto_prefix[NPROTO] = {
+ [AF_INET] = "ip",
+ [AF_INET6] = "ip6",
+ [NF_ARP] = "arp",
+};
+
+static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
+{
+ struct list_head *head = list->next;
+
+ if (!head || list_empty(list))
+ return NULL;
+
+ while (pos && (head = head->next)) {
+ if (head == list)
+ return NULL;
+ pos--;
+ }
+ return pos ? NULL : head;
+}
+
+static struct list_head *type2list(u_int16_t af, u_int16_t type)
+{
+ struct list_head *list;
+
+ switch (type) {
+ case TARGET:
+ list = &xt[af].target;
+ break;
+ case MATCH:
+ list = &xt[af].match;
+ break;
+ case TABLE:
+ list = &xt[af].tables;
+ break;
+ default:
+ list = NULL;
+ break;
+ }
+
+ return list;
+}
+
+static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
+ u_int16_t af = (unsigned long)pde->data & 0xffff;
+ u_int16_t type = (unsigned long)pde->data >> 16;
+ struct list_head *list;
+
+ if (af >= NPROTO)
+ return NULL;
+
+ list = type2list(af, type);
+ if (!list)
+ return NULL;
+
+ if (down_interruptible(&xt[af].mutex) != 0)
+ return NULL;
+
+ return xt_get_idx(list, seq, *pos);
+}
+
+static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct proc_dir_entry *pde = seq->private;
+ u_int16_t af = (unsigned long)pde->data & 0xffff;
+ u_int16_t type = (unsigned long)pde->data >> 16;
+ struct list_head *list;
+
+ if (af >= NPROTO)
+ return NULL;
+
+ list = type2list(af, type);
+ if (!list)
+ return NULL;
+
+ (*pos)++;
+ return xt_get_idx(list, seq, *pos);
+}
+
+static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
+{
+ struct proc_dir_entry *pde = seq->private;
+ u_int16_t af = (unsigned long)pde->data & 0xffff;
+
+ up(&xt[af].mutex);
+}
+
+static int xt_name_seq_show(struct seq_file *seq, void *v)
+{
+ char *name = (char *)v + sizeof(struct list_head);
+
+ if (strlen(name))
+ return seq_printf(seq, "%s\n", name);
+ else
+ return 0;
+}
+
+static struct seq_operations xt_tgt_seq_ops = {
+ .start = xt_tgt_seq_start,
+ .next = xt_tgt_seq_next,
+ .stop = xt_tgt_seq_stop,
+ .show = xt_name_seq_show,
+};
+
+static int xt_tgt_open(struct inode *inode, struct file *file)
+{
+ int ret;
+
+ ret = seq_open(file, &xt_tgt_seq_ops);
+ if (!ret) {
+ struct seq_file *seq = file->private_data;
+ struct proc_dir_entry *pde = PDE(inode);
+
+ seq->private = pde;
+ }
+
+ return ret;
+}
+
+static struct file_operations xt_file_ops = {
+ .owner = THIS_MODULE,
+ .open = xt_tgt_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+#define FORMAT_TABLES "_tables_names"
+#define FORMAT_MATCHES "_tables_matches"
+#define FORMAT_TARGETS "_tables_targets"
+
+#endif /* CONFIG_PROC_FS */
+
+int xt_proto_init(int af)
+{
+#ifdef CONFIG_PROC_FS
+ char buf[XT_FUNCTION_MAXNAMELEN];
+ struct proc_dir_entry *proc;
+#endif
+
+ if (af >= NPROTO)
+ return -EINVAL;
+
+
+#ifdef CONFIG_PROC_FS
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ if (!proc)
+ goto out;
+ proc->data = (void *) ((unsigned long) af | (TABLE << 16));
+
+
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ if (!proc)
+ goto out_remove_tables;
+ proc->data = (void *) ((unsigned long) af | (MATCH << 16));
+
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+ proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
+ if (!proc)
+ goto out_remove_matches;
+ proc->data = (void *) ((unsigned long) af | (TARGET << 16));
+#endif
+
+ return 0;
+
+#ifdef CONFIG_PROC_FS
+out_remove_matches:
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ proc_net_remove(buf);
+
+out_remove_tables:
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ proc_net_remove(buf);
+out:
+ return -1;
+#endif
+}
+EXPORT_SYMBOL_GPL(xt_proto_init);
+
+void xt_proto_fini(int af)
+{
+#ifdef CONFIG_PROC_FS
+ char buf[XT_FUNCTION_MAXNAMELEN];
+
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_TABLES, sizeof(buf));
+ proc_net_remove(buf);
+
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_TARGETS, sizeof(buf));
+ proc_net_remove(buf);
+
+ strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
+ strlcat(buf, FORMAT_MATCHES, sizeof(buf));
+ proc_net_remove(buf);
+#endif /*CONFIG_PROC_FS*/
+}
+EXPORT_SYMBOL_GPL(xt_proto_fini);
+
+
+static int __init xt_init(void)
+{
+ int i;
+
+ xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
+ if (!xt)
+ return -ENOMEM;
+
+ for (i = 0; i < NPROTO; i++) {
+ init_MUTEX(&xt[i].mutex);
+ INIT_LIST_HEAD(&xt[i].target);
+ INIT_LIST_HEAD(&xt[i].match);
+ INIT_LIST_HEAD(&xt[i].tables);
+ }
+ return 0;
+}
+
+static void __exit xt_fini(void)
+{
+ kfree(xt);
+}
+
+module_init(xt_init);
+module_exit(xt_fini);
+
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index dab78d8bd494..78ee266a12ee 100644
--- a/net/ipv4/netfilter/ipt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -15,12 +15,13 @@
#include <linux/ip.h>
#include <net/checksum.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CLASSIFY.h>
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("iptables qdisc classification target module");
+MODULE_ALIAS("ipt_CLASSIFY");
static unsigned int
target(struct sk_buff **pskb,
@@ -30,25 +31,25 @@ target(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
- const struct ipt_classify_target_info *clinfo = targinfo;
+ const struct xt_classify_target_info *clinfo = targinfo;
- if((*pskb)->priority != clinfo->priority)
+ if ((*pskb)->priority != clinfo->priority)
(*pskb)->priority = clinfo->priority;
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *e,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
- if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
+ if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){
printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
targinfosize,
- IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
+ XT_ALIGN(sizeof(struct xt_classify_target_info)));
return 0;
}
@@ -69,21 +70,39 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_target ipt_classify_reg = {
+static struct xt_target classify_reg = {
+ .name = "CLASSIFY",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_target classify6_reg = {
.name = "CLASSIFY",
.target = target,
.checkentry = checkentry,
.me = THIS_MODULE,
};
+
static int __init init(void)
{
- return ipt_register_target(&ipt_classify_reg);
+ int ret;
+
+ ret = xt_register_target(AF_INET, &classify_reg);
+ if (ret)
+ return ret;
+
+ ret = xt_register_target(AF_INET6, &classify6_reg);
+ if (ret)
+ xt_unregister_target(AF_INET, &classify_reg);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_target(&ipt_classify_reg);
+ xt_unregister_target(AF_INET, &classify_reg);
+ xt_unregister_target(AF_INET6, &classify6_reg);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index 8acac5a40a92..22506e376be5 100644
--- a/net/ipv4/netfilter/ipt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -26,9 +26,10 @@
MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
MODULE_DESCRIPTION("IP tables CONNMARK matching module");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_CONNMARK");
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNMARK.h>
#include <net/netfilter/nf_conntrack_compat.h>
static unsigned int
@@ -39,7 +40,7 @@ target(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
- const struct ipt_connmark_target_info *markinfo = targinfo;
+ const struct xt_connmark_target_info *markinfo = targinfo;
u_int32_t diff;
u_int32_t nfmark;
u_int32_t newmark;
@@ -48,17 +49,17 @@ target(struct sk_buff **pskb,
if (ctmark) {
switch(markinfo->mode) {
- case IPT_CONNMARK_SET:
+ case XT_CONNMARK_SET:
newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
if (newmark != *ctmark)
*ctmark = newmark;
break;
- case IPT_CONNMARK_SAVE:
+ case XT_CONNMARK_SAVE:
newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
if (*ctmark != newmark)
*ctmark = newmark;
break;
- case IPT_CONNMARK_RESTORE:
+ case XT_CONNMARK_RESTORE:
nfmark = (*pskb)->nfmark;
diff = (*ctmark ^ nfmark) & markinfo->mask;
if (diff != 0)
@@ -67,25 +68,25 @@ target(struct sk_buff **pskb,
}
}
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
- struct ipt_connmark_target_info *matchinfo = targinfo;
- if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
+ struct xt_connmark_target_info *matchinfo = targinfo;
+ if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) {
printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
targinfosize,
- IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
+ XT_ALIGN(sizeof(struct xt_connmark_target_info)));
return 0;
}
- if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
+ if (matchinfo->mode == XT_CONNMARK_RESTORE) {
if (strcmp(tablename, "mangle") != 0) {
printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
return 0;
@@ -100,7 +101,13 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_target ipt_connmark_reg = {
+static struct xt_target connmark_reg = {
+ .name = "CONNMARK",
+ .target = &target,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+static struct xt_target connmark6_reg = {
.name = "CONNMARK",
.target = &target,
.checkentry = &checkentry,
@@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = {
static int __init init(void)
{
- need_ip_conntrack();
- return ipt_register_target(&ipt_connmark_reg);
+ int ret;
+
+ need_conntrack();
+
+ ret = xt_register_target(AF_INET, &connmark_reg);
+ if (ret)
+ return ret;
+
+ ret = xt_register_target(AF_INET6, &connmark6_reg);
+ if (ret)
+ xt_unregister_target(AF_INET, &connmark_reg);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_target(&ipt_connmark_reg);
+ xt_unregister_target(AF_INET, &connmark_reg);
+ xt_unregister_target(AF_INET6, &connmark6_reg);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c
index 52b4f2c296bf..0c11ee9550f3 100644
--- a/net/ipv4/netfilter/ipt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -12,12 +12,14 @@
#include <linux/ip.h>
#include <net/checksum.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_MARK.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_MARK.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
-MODULE_DESCRIPTION("iptables MARK modification module");
+MODULE_DESCRIPTION("ip[6]tables MARK modification module");
+MODULE_ALIAS("ipt_MARK");
+MODULE_ALIAS("ip6t_MARK");
static unsigned int
target_v0(struct sk_buff **pskb,
@@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
- const struct ipt_mark_target_info *markinfo = targinfo;
+ const struct xt_mark_target_info *markinfo = targinfo;
if((*pskb)->nfmark != markinfo->mark)
(*pskb)->nfmark = markinfo->mark;
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static unsigned int
@@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
- const struct ipt_mark_target_info_v1 *markinfo = targinfo;
+ const struct xt_mark_target_info_v1 *markinfo = targinfo;
int mark = 0;
switch (markinfo->mode) {
- case IPT_MARK_SET:
+ case XT_MARK_SET:
mark = markinfo->mark;
break;
- case IPT_MARK_AND:
+ case XT_MARK_AND:
mark = (*pskb)->nfmark & markinfo->mark;
break;
- case IPT_MARK_OR:
+ case XT_MARK_OR:
mark = (*pskb)->nfmark | markinfo->mark;
break;
}
@@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb,
if((*pskb)->nfmark != mark)
(*pskb)->nfmark = mark;
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static int
checkentry_v0(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
- struct ipt_mark_target_info *markinfo = targinfo;
+ struct xt_mark_target_info *markinfo = targinfo;
- if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
+ if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) {
printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
targinfosize,
- IPT_ALIGN(sizeof(struct ipt_mark_target_info)));
+ XT_ALIGN(sizeof(struct xt_mark_target_info)));
return 0;
}
@@ -98,17 +100,17 @@ checkentry_v0(const char *tablename,
static int
checkentry_v1(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
{
- struct ipt_mark_target_info_v1 *markinfo = targinfo;
+ struct xt_mark_target_info_v1 *markinfo = targinfo;
- if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){
+ if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){
printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
targinfosize,
- IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)));
+ XT_ALIGN(sizeof(struct xt_mark_target_info_v1)));
return 0;
}
@@ -117,9 +119,9 @@ checkentry_v1(const char *tablename,
return 0;
}
- if (markinfo->mode != IPT_MARK_SET
- && markinfo->mode != IPT_MARK_AND
- && markinfo->mode != IPT_MARK_OR) {
+ if (markinfo->mode != XT_MARK_SET
+ && markinfo->mode != XT_MARK_AND
+ && markinfo->mode != XT_MARK_OR) {
printk(KERN_WARNING "MARK: unknown mode %u\n",
markinfo->mode);
return 0;
@@ -133,7 +135,7 @@ checkentry_v1(const char *tablename,
return 1;
}
-static struct ipt_target ipt_mark_reg_v0 = {
+static struct xt_target ipt_mark_reg_v0 = {
.name = "MARK",
.target = target_v0,
.checkentry = checkentry_v0,
@@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = {
.revision = 0,
};
-static struct ipt_target ipt_mark_reg_v1 = {
+static struct xt_target ipt_mark_reg_v1 = {
.name = "MARK",
.target = target_v1,
.checkentry = checkentry_v1,
@@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = {
.revision = 1,
};
+static struct xt_target ip6t_mark_reg_v0 = {
+ .name = "MARK",
+ .target = target_v0,
+ .checkentry = checkentry_v0,
+ .me = THIS_MODULE,
+ .revision = 0,
+};
+
static int __init init(void)
{
int err;
- err = ipt_register_target(&ipt_mark_reg_v0);
- if (!err) {
- err = ipt_register_target(&ipt_mark_reg_v1);
- if (err)
- ipt_unregister_target(&ipt_mark_reg_v0);
+ err = xt_register_target(AF_INET, &ipt_mark_reg_v0);
+ if (err)
+ return err;
+
+ err = xt_register_target(AF_INET, &ipt_mark_reg_v1);
+ if (err)
+ xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
+
+ err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0);
+ if (err) {
+ xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
+ xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
}
+
return err;
}
static void __exit fini(void)
{
- ipt_unregister_target(&ipt_mark_reg_v0);
- ipt_unregister_target(&ipt_mark_reg_v1);
+ xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
+ xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
+ xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0);
}
module_init(init);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
new file mode 100644
index 000000000000..8b76b6f8d1e4
--- /dev/null
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -0,0 +1,107 @@
+/* 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_arp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_NFQUEUE.h>
+
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_NFQUEUE");
+MODULE_ALIAS("ip6t_NFQUEUE");
+MODULE_ALIAS("arpt_NFQUEUE");
+
+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 xt_NFQ_info *tinfo = targinfo;
+
+ return NF_QUEUE_NR(tinfo->queuenum);
+}
+
+static int
+checkentry(const char *tablename,
+ const void *entry,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) {
+ printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
+ targinfosize,
+ XT_ALIGN(sizeof(struct xt_NFQ_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct xt_target ipt_NFQ_reg = {
+ .name = "NFQUEUE",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static struct xt_target ip6t_NFQ_reg = {
+ .name = "NFQUEUE",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static struct xt_target arpt_NFQ_reg = {
+ .name = "NFQUEUE",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ int ret;
+ ret = xt_register_target(AF_INET, &ipt_NFQ_reg);
+ if (ret)
+ return ret;
+ ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg);
+ if (ret)
+ goto out_ip;
+ ret = xt_register_target(NF_ARP, &arpt_NFQ_reg);
+ if (ret)
+ goto out_ip6;
+
+ return ret;
+out_ip6:
+ xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
+out_ip:
+ xt_unregister_target(AF_INET, &ipt_NFQ_reg);
+
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_target(NF_ARP, &arpt_NFQ_reg);
+ xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
+ xt_unregister_target(AF_INET, &ipt_NFQ_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index e3c69d072c6e..24d477afa939 100644
--- a/net/ipv4/netfilter/ipt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -4,9 +4,12 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
#include <net/netfilter/nf_conntrack_compat.h>
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_NOTRACK");
+
static unsigned int
target(struct sk_buff **pskb,
const struct net_device *in,
@@ -17,7 +20,7 @@ target(struct sk_buff **pskb,
{
/* Previously seen (loopback)? Ignore. */
if ((*pskb)->nfct != NULL)
- return IPT_CONTINUE;
+ return XT_CONTINUE;
/* Attach fake conntrack entry.
If there is a real ct entry correspondig to this packet,
@@ -27,12 +30,12 @@ target(struct sk_buff **pskb,
(*pskb)->nfctinfo = IP_CT_NEW;
nf_conntrack_get((*pskb)->nfct);
- return IPT_CONTINUE;
+ return XT_CONTINUE;
}
static int
checkentry(const char *tablename,
- const struct ipt_entry *e,
+ const void *entry,
void *targinfo,
unsigned int targinfosize,
unsigned int hook_mask)
@@ -51,26 +54,39 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_target ipt_notrack_reg = {
+static struct xt_target notrack_reg = {
.name = "NOTRACK",
.target = target,
.checkentry = checkentry,
- .me = THIS_MODULE
+ .me = THIS_MODULE,
+};
+static struct xt_target notrack6_reg = {
+ .name = "NOTRACK",
+ .target = target,
+ .checkentry = checkentry,
+ .me = THIS_MODULE,
};
static int __init init(void)
{
- if (ipt_register_target(&ipt_notrack_reg))
- return -EINVAL;
+ int ret;
+
+ ret = xt_register_target(AF_INET, &notrack_reg);
+ if (ret)
+ return ret;
- return 0;
+ ret = xt_register_target(AF_INET6, &notrack6_reg);
+ if (ret)
+ xt_unregister_target(AF_INET, &notrack_reg);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_target(&ipt_notrack_reg);
+ xt_unregister_target(AF_INET6, &notrack6_reg);
+ xt_unregister_target(AF_INET, &notrack_reg);
}
module_init(init);
module_exit(fini);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c
index 6b76a1ea5245..4ba6fd65c6e9 100644
--- a/net/ipv4/netfilter/ipt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -6,12 +6,14 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_comment.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_comment.h>
MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
MODULE_DESCRIPTION("iptables comment match module");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_comment");
+MODULE_ALIAS("ip6t_comment");
static int
match(const struct sk_buff *skb,
@@ -19,6 +21,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protooff,
int *hotdrop)
{
/* We always match */
@@ -27,18 +30,25 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
/* Check the size */
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info)))
return 0;
return 1;
}
-static struct ipt_match comment_match = {
+static struct xt_match comment_match = {
+ .name = "comment",
+ .match = match,
+ .checkentry = checkentry,
+ .me = THIS_MODULE
+};
+
+static struct xt_match comment6_match = {
.name = "comment",
.match = match,
.checkentry = checkentry,
@@ -47,12 +57,23 @@ static struct ipt_match comment_match = {
static int __init init(void)
{
- return ipt_register_match(&comment_match);
+ int ret;
+
+ ret = xt_register_match(AF_INET, &comment_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &comment6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &comment_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&comment_match);
+ xt_unregister_match(AF_INET, &comment_match);
+ xt_unregister_match(AF_INET6, &comment6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c
index d68a048b7176..150d2a4b0f71 100644
--- a/net/ipv4/netfilter/ipt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -6,13 +6,15 @@
* - add functionality to match number of packets
* - add functionality to match average packet size
* - add support to match directions seperately
+ * 2005-10-16 Harald Welte <laforge@netfilter.org>
+ * - Port to x_tables
*
*/
#include <linux/module.h>
#include <linux/skbuff.h>
#include <net/netfilter/nf_conntrack_compat.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_connbytes.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_connbytes.h>
#include <asm/div64.h>
#include <asm/bitops.h>
@@ -20,6 +22,7 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
+MODULE_ALIAS("ipt_connbytes");
/* 64bit divisor, dividend and result. dynamic precision */
static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
@@ -43,9 +46,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_connbytes_info *sinfo = matchinfo;
+ const struct xt_connbytes_info *sinfo = matchinfo;
u_int64_t what = 0; /* initialize to make gcc happy */
const struct ip_conntrack_counter *counters;
@@ -53,45 +57,45 @@ match(const struct sk_buff *skb,
return 0; /* no match */
switch (sinfo->what) {
- case IPT_CONNBYTES_PKTS:
+ case XT_CONNBYTES_PKTS:
switch (sinfo->direction) {
- case IPT_CONNBYTES_DIR_ORIGINAL:
+ case XT_CONNBYTES_DIR_ORIGINAL:
what = counters[IP_CT_DIR_ORIGINAL].packets;
break;
- case IPT_CONNBYTES_DIR_REPLY:
+ case XT_CONNBYTES_DIR_REPLY:
what = counters[IP_CT_DIR_REPLY].packets;
break;
- case IPT_CONNBYTES_DIR_BOTH:
+ case XT_CONNBYTES_DIR_BOTH:
what = counters[IP_CT_DIR_ORIGINAL].packets;
what += counters[IP_CT_DIR_REPLY].packets;
break;
}
break;
- case IPT_CONNBYTES_BYTES:
+ case XT_CONNBYTES_BYTES:
switch (sinfo->direction) {
- case IPT_CONNBYTES_DIR_ORIGINAL:
+ case XT_CONNBYTES_DIR_ORIGINAL:
what = counters[IP_CT_DIR_ORIGINAL].bytes;
break;
- case IPT_CONNBYTES_DIR_REPLY:
+ case XT_CONNBYTES_DIR_REPLY:
what = counters[IP_CT_DIR_REPLY].bytes;
break;
- case IPT_CONNBYTES_DIR_BOTH:
+ case XT_CONNBYTES_DIR_BOTH:
what = counters[IP_CT_DIR_ORIGINAL].bytes;
what += counters[IP_CT_DIR_REPLY].bytes;
break;
}
break;
- case IPT_CONNBYTES_AVGPKT:
+ case XT_CONNBYTES_AVGPKT:
switch (sinfo->direction) {
- case IPT_CONNBYTES_DIR_ORIGINAL:
+ case XT_CONNBYTES_DIR_ORIGINAL:
what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
counters[IP_CT_DIR_ORIGINAL].packets);
break;
- case IPT_CONNBYTES_DIR_REPLY:
+ case XT_CONNBYTES_DIR_REPLY:
what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
counters[IP_CT_DIR_REPLY].packets);
break;
- case IPT_CONNBYTES_DIR_BOTH:
+ case XT_CONNBYTES_DIR_BOTH:
{
u_int64_t bytes;
u_int64_t pkts;
@@ -117,30 +121,36 @@ match(const struct sk_buff *skb,
}
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- const struct ipt_connbytes_info *sinfo = matchinfo;
+ const struct xt_connbytes_info *sinfo = matchinfo;
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info)))
return 0;
- if (sinfo->what != IPT_CONNBYTES_PKTS &&
- sinfo->what != IPT_CONNBYTES_BYTES &&
- sinfo->what != IPT_CONNBYTES_AVGPKT)
+ if (sinfo->what != XT_CONNBYTES_PKTS &&
+ sinfo->what != XT_CONNBYTES_BYTES &&
+ sinfo->what != XT_CONNBYTES_AVGPKT)
return 0;
- if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL &&
- sinfo->direction != IPT_CONNBYTES_DIR_REPLY &&
- sinfo->direction != IPT_CONNBYTES_DIR_BOTH)
+ if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
+ sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
+ sinfo->direction != XT_CONNBYTES_DIR_BOTH)
return 0;
return 1;
}
-static struct ipt_match state_match = {
+static struct xt_match connbytes_match = {
+ .name = "connbytes",
+ .match = &match,
+ .checkentry = &check,
+ .me = THIS_MODULE
+};
+static struct xt_match connbytes6_match = {
.name = "connbytes",
.match = &match,
.checkentry = &check,
@@ -149,12 +159,21 @@ static struct ipt_match state_match = {
static int __init init(void)
{
- return ipt_register_match(&state_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &connbytes_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &connbytes6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &connbytes_match);
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&state_match);
+ xt_unregister_match(AF_INET, &connbytes_match);
+ xt_unregister_match(AF_INET6, &connbytes6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c
index 5306ef293b92..d06e925032da 100644
--- a/net/ipv4/netfilter/ipt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -25,9 +25,10 @@
MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
MODULE_DESCRIPTION("IP tables connmark match module");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_connmark");
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_connmark.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_connmark.h>
#include <net/netfilter/nf_conntrack_compat.h>
static int
@@ -36,9 +37,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_connmark_info *info = matchinfo;
+ const struct xt_connmark_info *info = matchinfo;
u_int32_t ctinfo;
const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
if (!ctmark)
@@ -49,14 +51,14 @@ match(const struct sk_buff *skb,
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
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)))
+ struct xt_connmark_info *cm =
+ (struct xt_connmark_info *)matchinfo;
+ if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info)))
return 0;
if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
@@ -67,21 +69,40 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_match connmark_match = {
+static struct xt_match connmark_match = {
+ .name = "connmark",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+static struct xt_match connmark6_match = {
.name = "connmark",
.match = &match,
.checkentry = &checkentry,
.me = THIS_MODULE
};
+
static int __init init(void)
{
- return ipt_register_match(&connmark_match);
+ int ret;
+
+ need_conntrack();
+
+ ret = xt_register_match(AF_INET, &connmark_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &connmark6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &connmark_match);
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&connmark_match);
+ xt_unregister_match(AF_INET6, &connmark6_match);
+ xt_unregister_match(AF_INET, &connmark_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c
index c8d18705469b..ffdebc95eb95 100644
--- a/net/ipv4/netfilter/ipt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -18,12 +18,13 @@
#include <net/netfilter/nf_conntrack.h>
#endif
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_conntrack.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_conntrack.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables connection tracking match module");
+MODULE_ALIAS("ipt_conntrack");
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
@@ -33,9 +34,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_conntrack_info *sinfo = matchinfo;
+ const struct xt_conntrack_info *sinfo = matchinfo;
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
@@ -45,58 +47,58 @@ match(const struct sk_buff *skb,
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
if (ct == &ip_conntrack_untracked)
- statebit = IPT_CONNTRACK_STATE_UNTRACKED;
+ statebit = XT_CONNTRACK_STATE_UNTRACKED;
else if (ct)
- statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
+ statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
else
- statebit = IPT_CONNTRACK_STATE_INVALID;
+ statebit = XT_CONNTRACK_STATE_INVALID;
- if(sinfo->flags & IPT_CONNTRACK_STATE) {
+ if(sinfo->flags & XT_CONNTRACK_STATE) {
if (ct) {
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
- statebit |= IPT_CONNTRACK_STATE_SNAT;
+ statebit |= XT_CONNTRACK_STATE_SNAT;
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
- statebit |= IPT_CONNTRACK_STATE_DNAT;
+ statebit |= XT_CONNTRACK_STATE_DNAT;
}
- if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE))
+ if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_PROTO) {
- if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO))
+ if(sinfo->flags & XT_CONNTRACK_PROTO) {
+ if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC))
+ if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST))
+ if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC))
+ if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST))
+ if(sinfo->flags & XT_CONNTRACK_REPLDST) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_STATUS) {
- if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
+ if(sinfo->flags & XT_CONNTRACK_STATUS) {
+ if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
+ if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
unsigned long expires;
if(!ct)
@@ -104,7 +106,7 @@ match(const struct sk_buff *skb,
expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
- if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
+ if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
return 0;
}
@@ -118,9 +120,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_conntrack_info *sinfo = matchinfo;
+ const struct xt_conntrack_info *sinfo = matchinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
@@ -130,58 +133,58 @@ match(const struct sk_buff *skb,
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
if (ct == &nf_conntrack_untracked)
- statebit = IPT_CONNTRACK_STATE_UNTRACKED;
+ statebit = XT_CONNTRACK_STATE_UNTRACKED;
else if (ct)
- statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
+ statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
else
- statebit = IPT_CONNTRACK_STATE_INVALID;
+ statebit = XT_CONNTRACK_STATE_INVALID;
- if(sinfo->flags & IPT_CONNTRACK_STATE) {
+ if(sinfo->flags & XT_CONNTRACK_STATE) {
if (ct) {
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
- statebit |= IPT_CONNTRACK_STATE_SNAT;
+ statebit |= XT_CONNTRACK_STATE_SNAT;
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
- statebit |= IPT_CONNTRACK_STATE_DNAT;
+ statebit |= XT_CONNTRACK_STATE_DNAT;
}
- if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE))
+ if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_PROTO) {
- if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO))
+ if(sinfo->flags & XT_CONNTRACK_PROTO) {
+ if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC))
+ if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST))
+ if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC))
+ if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
- if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST))
+ if(sinfo->flags & XT_CONNTRACK_REPLDST) {
+ if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_STATUS) {
- if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
+ if(sinfo->flags & XT_CONNTRACK_STATUS) {
+ if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
return 0;
}
- if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
+ if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
unsigned long expires;
if(!ct)
@@ -189,7 +192,7 @@ match(const struct sk_buff *skb,
expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
- if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
+ if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
return 0;
}
@@ -199,18 +202,18 @@ match(const struct sk_buff *skb,
#endif /* CONFIG_NF_IP_CONNTRACK */
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info)))
return 0;
return 1;
}
-static struct ipt_match conntrack_match = {
+static struct xt_match conntrack_match = {
.name = "conntrack",
.match = &match,
.checkentry = &check,
@@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = {
static int __init init(void)
{
- need_ip_conntrack();
- return ipt_register_match(&conntrack_match);
+ int ret;
+ need_conntrack();
+ ret = xt_register_match(AF_INET, &conntrack_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&conntrack_match);
+ xt_unregister_match(AF_INET, &conntrack_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c
index ad3278bba6c1..779f42fc9524 100644
--- a/net/ipv4/netfilter/ipt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -14,8 +14,16 @@
#include <net/ip.h>
#include <linux/dccp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_dccp.h>
+
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_dccp.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
+MODULE_DESCRIPTION("Match for DCCP protocol packets");
+MODULE_ALIAS("ipt_dccp");
#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|| (!!((invflag) & (option)) ^ (cond)))
@@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock);
static inline int
dccp_find_option(u_int8_t option,
const struct sk_buff *skb,
+ unsigned int protoff,
const struct dccp_hdr *dh,
int *hotdrop)
{
@@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option,
return 0;
spin_lock_bh(&dccp_buflock);
- op = skb_header_pointer(skb,
- skb->nh.iph->ihl*4 + optoff,
- optlen, dccp_optbuf);
+ op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
if (op == NULL) {
/* If we don't have the whole header, drop packet. */
spin_unlock_bh(&dccp_buflock);
@@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask)
}
static inline int
-match_option(u_int8_t option, const struct sk_buff *skb,
+match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
const struct dccp_hdr *dh, int *hotdrop)
{
- return dccp_find_option(option, skb, dh, hotdrop);
+ return dccp_find_option(option, skb, protoff, dh, hotdrop);
}
static int
@@ -90,16 +97,17 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_dccp_info *info =
- (const struct ipt_dccp_info *)matchinfo;
+ const struct xt_dccp_info *info =
+ (const struct xt_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);
+ dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
if (dh == NULL) {
*hotdrop = 1;
return 0;
@@ -107,42 +115,73 @@ match(const struct sk_buff *skb,
return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
&& (ntohs(dh->dccph_sport) <= info->spts[1])),
- IPT_DCCP_SRC_PORTS, info->flags, info->invflags)
+ XT_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)
+ XT_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);
+ XT_DCCP_TYPE, info->flags, info->invflags)
+ && DCCHECK(match_option(info->option, skb, protoff, dh,
+ hotdrop),
+ XT_DCCP_OPTION, info->flags, info->invflags);
}
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- const struct ipt_dccp_info *info;
+ const struct ipt_ip *ip = inf;
+ const struct xt_dccp_info *info;
- info = (const struct ipt_dccp_info *)matchinfo;
+ info = (const struct xt_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)
+ && !(ip->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
+ && !(info->flags & ~XT_DCCP_VALID_FLAGS)
+ && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
&& !(info->invflags & ~info->flags);
}
-static struct ipt_match dccp_match =
+static int
+checkentry6(const char *tablename,
+ const void *inf,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = inf;
+ const struct xt_dccp_info *info;
+
+ info = (const struct xt_dccp_info *)matchinfo;
+
+ return ip->proto == IPPROTO_DCCP
+ && !(ip->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
+ && !(info->flags & ~XT_DCCP_VALID_FLAGS)
+ && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
+ && !(info->invflags & ~info->flags);
+}
+
+
+static struct xt_match dccp_match =
{
.name = "dccp",
.match = &match,
.checkentry = &checkentry,
.me = THIS_MODULE,
};
+static struct xt_match dccp6_match =
+{
+ .name = "dccp",
+ .match = &match,
+ .checkentry = &checkentry6,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
@@ -154,23 +193,29 @@ static int __init init(void)
dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
if (!dccp_optbuf)
return -ENOMEM;
- ret = ipt_register_match(&dccp_match);
+ ret = xt_register_match(AF_INET, &dccp_match);
if (ret)
- kfree(dccp_optbuf);
+ goto out_kfree;
+ ret = xt_register_match(AF_INET6, &dccp6_match);
+ if (ret)
+ goto out_unreg;
+
+ return ret;
+
+out_unreg:
+ xt_unregister_match(AF_INET, &dccp_match);
+out_kfree:
+ kfree(dccp_optbuf);
return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&dccp_match);
+ xt_unregister_match(AF_INET6, &dccp6_match);
+ xt_unregister_match(AF_INET, &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_helper.c b/net/netfilter/xt_helper.c
index bf14e1c7798a..38b6715e1db4 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -22,12 +22,14 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h>
#endif
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_helper.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_helper.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
MODULE_DESCRIPTION("iptables helper match module");
+MODULE_ALIAS("ipt_helper");
+MODULE_ALIAS("ip6t_helper");
#if 0
#define DEBUGP printk
@@ -42,27 +44,28 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_helper_info *info = matchinfo;
+ const struct xt_helper_info *info = matchinfo;
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
int ret = info->invert;
ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
if (!ct) {
- DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
+ DEBUGP("xt_helper: Eek! invalid conntrack?\n");
return ret;
}
if (!ct->master) {
- DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
+ DEBUGP("xt_helper: conntrack %p has no master\n", ct);
return ret;
}
read_lock_bh(&ip_conntrack_lock);
if (!ct->master->helper) {
- DEBUGP("ipt_helper: master ct %p has no helper\n",
+ DEBUGP("xt_helper: master ct %p has no helper\n",
exp->expectant);
goto out_unlock;
}
@@ -88,27 +91,28 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_helper_info *info = matchinfo;
+ const struct xt_helper_info *info = matchinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
int ret = info->invert;
ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
if (!ct) {
- DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
+ DEBUGP("xt_helper: Eek! invalid conntrack?\n");
return ret;
}
if (!ct->master) {
- DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
+ DEBUGP("xt_helper: conntrack %p has no master\n", ct);
return ret;
}
read_lock_bh(&nf_conntrack_lock);
if (!ct->master->helper) {
- DEBUGP("ipt_helper: master ct %p has no helper\n",
+ DEBUGP("xt_helper: master ct %p has no helper\n",
exp->expectant);
goto out_unlock;
}
@@ -128,23 +132,29 @@ out_unlock:
#endif
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- struct ipt_helper_info *info = matchinfo;
+ struct xt_helper_info *info = matchinfo;
info->name[29] = '\0';
/* verify size */
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info)))
return 0;
return 1;
}
-static struct ipt_match helper_match = {
+static struct xt_match helper_match = {
+ .name = "helper",
+ .match = &match,
+ .checkentry = &check,
+ .me = THIS_MODULE,
+};
+static struct xt_match helper6_match = {
.name = "helper",
.match = &match,
.checkentry = &check,
@@ -153,13 +163,24 @@ static struct ipt_match helper_match = {
static int __init init(void)
{
- need_ip_conntrack();
- return ipt_register_match(&helper_match);
+ int ret;
+ need_conntrack();
+
+ ret = xt_register_match(AF_INET, &helper_match);
+ if (ret < 0)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &helper6_match);
+ if (ret < 0)
+ xt_unregister_match(AF_INET, &helper_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&helper_match);
+ xt_unregister_match(AF_INET, &helper_match);
+ xt_unregister_match(AF_INET6, &helper6_match);
}
module_init(init);
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
new file mode 100644
index 000000000000..39c8faea63de
--- /dev/null
+++ b/net/netfilter/xt_length.c
@@ -0,0 +1,99 @@
+/* Kernel module to match packet length. */
+/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
+ *
+ * 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/ipv6.h>
+#include <net/ip.h>
+
+#include <linux/netfilter/xt_length.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+MODULE_DESCRIPTION("IP tables packet length matching module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_length");
+MODULE_ALIAS("ip6t_length");
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ const struct xt_length_info *info = matchinfo;
+ u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
+
+ return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
+}
+
+static int
+match6(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ const struct xt_length_info *info = matchinfo;
+ u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
+
+ return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
+}
+
+static int
+checkentry(const char *tablename,
+ const void *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ if (matchsize != XT_ALIGN(sizeof(struct xt_length_info)))
+ return 0;
+
+ return 1;
+}
+
+static struct xt_match length_match = {
+ .name = "length",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_match length6_match = {
+ .name = "length",
+ .match = &match6,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ int ret;
+ ret = xt_register_match(AF_INET, &length_match);
+ if (ret)
+ return ret;
+ ret = xt_register_match(AF_INET6, &length6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &length_match);
+
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_match(AF_INET, &length_match);
+ xt_unregister_match(AF_INET6, &length6_match);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c
index 0c24dcc703a5..15e40506bc3a 100644
--- a/net/ipv4/netfilter/ipt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -18,12 +18,14 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_limit.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_limit.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
MODULE_DESCRIPTION("iptables rate limit match");
+MODULE_ALIAS("ipt_limit");
+MODULE_ALIAS("ip6t_limit");
/* The algorithm used is the Simple Token Bucket Filter (TBF)
* see net/sched/sch_tbf.c in the linux source tree
@@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master;
+ struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
unsigned long now = jiffies;
spin_lock_bh(&limit_lock);
@@ -96,32 +99,32 @@ user2credits(u_int32_t user)
/* If multiplying would overflow... */
if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
/* Divide first. */
- return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
+ return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
- return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE;
+ return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
}
static int
ipt_limit_checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- struct ipt_rateinfo *r = matchinfo;
+ struct xt_rateinfo *r = matchinfo;
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo)))
return 0;
/* Check for overflow. */
if (r->burst == 0
|| user2credits(r->avg * r->burst) < user2credits(r->avg)) {
- printk("Overflow in ipt_limit, try lower: %u/%u\n",
+ printk("Overflow in xt_limit, try lower: %u/%u\n",
r->avg, r->burst);
return 0;
}
- /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies *
+ /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
128. */
r->prev = jiffies;
r->credit = user2credits(r->avg * r->burst); /* Credits full. */
@@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename,
return 1;
}
-static struct ipt_match ipt_limit_reg = {
+static struct xt_match ipt_limit_reg = {
+ .name = "limit",
+ .match = ipt_limit_match,
+ .checkentry = ipt_limit_checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_match limit6_reg = {
.name = "limit",
.match = ipt_limit_match,
.checkentry = ipt_limit_checkentry,
@@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = {
static int __init init(void)
{
- if (ipt_register_match(&ipt_limit_reg))
- return -EINVAL;
- return 0;
+ int ret;
+
+ ret = xt_register_match(AF_INET, &ipt_limit_reg);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &limit6_reg);
+ if (ret)
+ xt_unregister_match(AF_INET, &ipt_limit_reg);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&ipt_limit_reg);
+ xt_unregister_match(AF_INET, &ipt_limit_reg);
+ xt_unregister_match(AF_INET6, &limit6_reg);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c
index 11a459e33f25..0461dcb5fc7a 100644
--- a/net/ipv4/netfilter/ipt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -11,13 +11,17 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
-#include <linux/netfilter_ipv4/ipt_mac.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/xt_mac.h>
+#include <linux/netfilter/x_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables mac matching module");
+MODULE_ALIAS("ipt_mac");
+MODULE_ALIAS("ip6t_mac");
static int
match(const struct sk_buff *skb,
@@ -25,21 +29,22 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_mac_info *info = matchinfo;
+ const struct xt_mac_info *info = matchinfo;
/* Is mac pointer valid? */
return (skb->mac.raw >= skb->head
&& (skb->mac.raw + ETH_HLEN) <= skb->data
/* If so, compare... */
- && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
- == 0) ^ info->invert));
+ && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
+ ^ info->invert));
}
static int
ipt_mac_checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
@@ -48,17 +53,23 @@ ipt_mac_checkentry(const char *tablename,
if (hook_mask
& ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
| (1 << NF_IP_FORWARD))) {
- printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
+ printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
return 0;
}
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info)))
return 0;
return 1;
}
-static struct ipt_match mac_match = {
+static struct xt_match mac_match = {
+ .name = "mac",
+ .match = &match,
+ .checkentry = &ipt_mac_checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_match mac6_match = {
.name = "mac",
.match = &match,
.checkentry = &ipt_mac_checkentry,
@@ -67,12 +78,22 @@ static struct ipt_match mac_match = {
static int __init init(void)
{
- return ipt_register_match(&mac_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &mac_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &mac6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &mac_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&mac_match);
+ xt_unregister_match(AF_INET, &mac_match);
+ xt_unregister_match(AF_INET6, &mac6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c
index 00bef6cdd3f8..2a0ac62b72c8 100644
--- a/net/ipv4/netfilter/ipt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -10,12 +10,14 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/netfilter_ipv4/ipt_mark.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/xt_mark.h>
+#include <linux/netfilter/x_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables mark matching module");
+MODULE_ALIAS("ipt_mark");
+MODULE_ALIAS("ip6t_mark");
static int
match(const struct sk_buff *skb,
@@ -23,23 +25,24 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_mark_info *info = matchinfo;
+ const struct xt_mark_info *info = matchinfo;
return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
}
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *entry,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo;
+ struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info)))
return 0;
if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
@@ -50,7 +53,14 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_match mark_match = {
+static struct xt_match mark_match = {
+ .name = "mark",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match mark6_match = {
.name = "mark",
.match = &match,
.checkentry = &checkentry,
@@ -59,12 +69,22 @@ static struct ipt_match mark_match = {
static int __init init(void)
{
- return ipt_register_match(&mark_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &mark_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &mark6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &mark_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&mark_match);
+ xt_unregister_match(AF_INET, &mark_match);
+ xt_unregister_match(AF_INET6, &mark6_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c
index 71515c86ece1..19bb57c14dfe 100644
--- a/net/ipv6/netfilter/ip6t_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -10,8 +10,8 @@
#include <linux/module.h>
#include <linux/skbuff.h>
-#include <linux/netfilter_ipv6/ip6t_physdev.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_physdev.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge.h>
#define MATCH 1
#define NOMATCH 0
@@ -19,6 +19,8 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
MODULE_DESCRIPTION("iptables bridge physical device match module");
+MODULE_ALIAS("ipt_physdev");
+MODULE_ALIAS("ip6t_physdev");
static int
match(const struct sk_buff *skb,
@@ -31,7 +33,7 @@ match(const struct sk_buff *skb,
{
int i;
static const char nulldevname[IFNAMSIZ];
- const struct ip6t_physdev_info *info = matchinfo;
+ const struct xt_physdev_info *info = matchinfo;
unsigned int ret;
const char *indev, *outdev;
struct nf_bridge_info *nf_bridge;
@@ -41,37 +43,37 @@ match(const struct sk_buff *skb,
* the destination device will be a bridge. */
if (!(nf_bridge = skb->nf_bridge)) {
/* Return MATCH if the invert flags of the used options are on */
- if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
- !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))
+ if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
+ !(info->invert & XT_PHYSDEV_OP_BRIDGED))
return NOMATCH;
- if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) &&
- !(info->invert & IP6T_PHYSDEV_OP_ISIN))
+ if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
+ !(info->invert & XT_PHYSDEV_OP_ISIN))
return NOMATCH;
- if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) &&
- !(info->invert & IP6T_PHYSDEV_OP_ISOUT))
+ if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
+ !(info->invert & XT_PHYSDEV_OP_ISOUT))
return NOMATCH;
- if ((info->bitmask & IP6T_PHYSDEV_OP_IN) &&
- !(info->invert & IP6T_PHYSDEV_OP_IN))
+ if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
+ !(info->invert & XT_PHYSDEV_OP_IN))
return NOMATCH;
- if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) &&
- !(info->invert & IP6T_PHYSDEV_OP_OUT))
+ if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
+ !(info->invert & XT_PHYSDEV_OP_OUT))
return NOMATCH;
return MATCH;
}
/* This only makes sense in the FORWARD and POSTROUTING chains */
- if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+ if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
(!!(nf_bridge->mask & BRNF_BRIDGED) ^
- !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)))
+ !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
return NOMATCH;
- if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN &&
- (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) ||
- (info->bitmask & IP6T_PHYSDEV_OP_ISOUT &&
- (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT))))
+ if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
+ (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
+ (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
+ (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
return NOMATCH;
- if (!(info->bitmask & IP6T_PHYSDEV_OP_IN))
+ if (!(info->bitmask & XT_PHYSDEV_OP_IN))
goto match_outdev;
indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
@@ -80,11 +82,11 @@ match(const struct sk_buff *skb,
& ((const unsigned int *)info->in_mask)[i];
}
- if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN))
+ if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
return NOMATCH;
match_outdev:
- if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT))
+ if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
return MATCH;
outdev = nf_bridge->physoutdev ?
nf_bridge->physoutdev->name : nulldevname;
@@ -94,27 +96,34 @@ match_outdev:
& ((const unsigned int *)info->out_mask)[i];
}
- return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT);
+ return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
}
static int
checkentry(const char *tablename,
- const struct ip6t_ip6 *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- const struct ip6t_physdev_info *info = matchinfo;
+ const struct xt_physdev_info *info = matchinfo;
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info)))
return 0;
- if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) ||
- info->bitmask & ~IP6T_PHYSDEV_OP_MASK)
+ if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
+ info->bitmask & ~XT_PHYSDEV_OP_MASK)
return 0;
return 1;
}
-static struct ip6t_match physdev_match = {
+static struct xt_match physdev_match = {
+ .name = "physdev",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match physdev6_match = {
.name = "physdev",
.match = &match,
.checkentry = &checkentry,
@@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = {
static int __init init(void)
{
- return ip6t_register_match(&physdev_match);
+ int ret;
+
+ ret = xt_register_match(AF_INET, &physdev_match);
+ if (ret < 0)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &physdev6_match);
+ if (ret < 0)
+ xt_unregister_match(AF_INET, &physdev_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ip6t_unregister_match(&physdev_match);
+ xt_unregister_match(AF_INET, &physdev_match);
+ xt_unregister_match(AF_INET6, &physdev6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c
index 8ddb1dc5e5ae..ab1b2630f97d 100644
--- a/net/ipv4/netfilter/ipt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -10,60 +10,72 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
-#include <linux/netfilter_ipv4/ipt_pkttype.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/xt_pkttype.h>
+#include <linux/netfilter/x_tables.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
+MODULE_ALIAS("ipt_pkttype");
+MODULE_ALIAS("ip6t_pkttype");
static int match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_pkttype_info *info = matchinfo;
+ const struct xt_pkttype_info *info = matchinfo;
- return (skb->pkt_type == info->pkttype) ^ info->invert;
+ return (skb->pkt_type == info->pkttype) ^ info->invert;
}
static int checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
-/*
- if (hook_mask
- & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
- | (1 << NF_IP_FORWARD))) {
- printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
- return 0;
- }
-*/
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info)))
return 0;
return 1;
}
-static struct ipt_match pkttype_match = {
+static struct xt_match pkttype_match = {
.name = "pkttype",
.match = &match,
.checkentry = &checkentry,
.me = THIS_MODULE,
};
+static struct xt_match pkttype6_match = {
+ .name = "pkttype",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
static int __init init(void)
{
- return ipt_register_match(&pkttype_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &pkttype_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &pkttype6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &pkttype_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&pkttype_match);
+ xt_unregister_match(AF_INET, &pkttype_match);
+ xt_unregister_match(AF_INET6, &pkttype6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c
index 54a6897ebaa6..2b7e1781d34d 100644
--- a/net/ipv4/netfilter/ipt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -14,12 +14,14 @@
#include <linux/netdevice.h>
#include <net/route.h>
-#include <linux/netfilter_ipv4/ipt_realm.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/xt_realm.h>
+#include <linux/netfilter/x_tables.h>
MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("iptables realm match");
+MODULE_DESCRIPTION("X_tables realm match");
+MODULE_ALIAS("ipt_realm");
static int
match(const struct sk_buff *skb,
@@ -27,16 +29,17 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_realm_info *info = matchinfo;
+ const struct xt_realm_info *info = matchinfo;
struct dst_entry *dst = skb->dst;
return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
}
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
@@ -44,18 +47,18 @@ static int check(const char *tablename,
if (hook_mask
& ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
(1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
- printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
+ printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
"LOCAL_IN or FORWARD.\n");
return 0;
}
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) {
- printk("ipt_realm: invalid matchsize.\n");
+ if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) {
+ printk("xt_realm: invalid matchsize.\n");
return 0;
}
return 1;
}
-static struct ipt_match realm_match = {
+static struct xt_match realm_match = {
.name = "realm",
.match = match,
.checkentry = check,
@@ -64,12 +67,12 @@ static struct ipt_match realm_match = {
static int __init init(void)
{
- return ipt_register_match(&realm_match);
+ return xt_register_match(AF_INET, &realm_match);
}
static void __exit fini(void)
{
- ipt_unregister_match(&realm_match);
+ xt_unregister_match(AF_INET, &realm_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c
index fe2b327bcaa4..10fbfc5ba758 100644
--- a/net/ipv4/netfilter/ipt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -1,10 +1,18 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <net/ip.h>
+#include <net/ipv6.h>
#include <linux/sctp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_sctp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_sctp.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kiran Kumar Immidi");
+MODULE_DESCRIPTION("Match for SCTP protocol packets");
+MODULE_ALIAS("ipt_sctp");
#ifdef DEBUG_SCTP
#define duprintf(format, args...) printk(format , ## args)
@@ -16,7 +24,7 @@
|| (!!((invflag) & (option)) ^ (cond)))
static int
-match_flags(const struct ipt_sctp_flag_info *flag_info,
+match_flags(const struct xt_sctp_flag_info *flag_info,
const int flag_count,
u_int8_t chunktype,
u_int8_t chunkflags)
@@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info,
return 1;
}
-static int
+static inline int
match_packet(const struct sk_buff *skb,
+ unsigned int offset,
const u_int32_t *chunkmap,
int chunk_match_type,
- const struct ipt_sctp_flag_info *flag_info,
+ const struct xt_sctp_flag_info *flag_info,
const int flag_count,
int *hotdrop)
{
- int offset;
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
sctp_chunkhdr_t _sch, *sch;
@@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb,
SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
}
- offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
do {
sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
if (sch == NULL) {
@@ -118,19 +125,20 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_sctp_info *info;
+ const struct xt_sctp_info *info;
sctp_sctphdr_t _sh, *sh;
- info = (const struct ipt_sctp_info *)matchinfo;
+ info = (const struct xt_sctp_info *)matchinfo;
if (offset) {
duprintf("Dropping non-first fragment.. FIXME\n");
return 0;
}
- sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh);
+ sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
if (sh == NULL) {
duprintf("Dropping evil TCP offset=0 tinygram.\n");
*hotdrop = 1;
@@ -140,64 +148,103 @@ match(const struct sk_buff *skb,
return SCCHECK(((ntohs(sh->source) >= info->spts[0])
&& (ntohs(sh->source) <= info->spts[1])),
- IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
+ XT_SCTP_SRC_PORTS, info->flags, info->invflags)
&& SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
&& (ntohs(sh->dest) <= info->dpts[1])),
- IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
- && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
+ XT_SCTP_DEST_PORTS, info->flags, info->invflags)
+ && SCCHECK(match_packet(skb, protoff,
+ info->chunkmap, info->chunk_match_type,
info->flag_info, info->flag_count,
hotdrop),
- IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
+ XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
}
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *inf,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct xt_sctp_info *info;
+ const struct ipt_ip *ip = inf;
+
+ info = (const struct xt_sctp_info *)matchinfo;
+
+ return ip->proto == IPPROTO_SCTP
+ && !(ip->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
+ && !(info->flags & ~XT_SCTP_VALID_FLAGS)
+ && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
+ && !(info->invflags & ~info->flags)
+ && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
+ (info->chunk_match_type &
+ (SCTP_CHUNK_MATCH_ALL
+ | SCTP_CHUNK_MATCH_ANY
+ | SCTP_CHUNK_MATCH_ONLY)));
+}
+
+static int
+checkentry6(const char *tablename,
+ const void *inf,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- const struct ipt_sctp_info *info;
+ const struct xt_sctp_info *info;
+ const struct ip6t_ip6 *ip = inf;
- info = (const struct ipt_sctp_info *)matchinfo;
+ info = (const struct xt_sctp_info *)matchinfo;
return ip->proto == IPPROTO_SCTP
- && !(ip->invflags & IPT_INV_PROTO)
- && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
- && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
- && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
+ && !(ip->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
+ && !(info->flags & ~XT_SCTP_VALID_FLAGS)
+ && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
&& !(info->invflags & ~info->flags)
- && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
+ && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
(info->chunk_match_type &
(SCTP_CHUNK_MATCH_ALL
| SCTP_CHUNK_MATCH_ANY
| SCTP_CHUNK_MATCH_ONLY)));
}
-static struct ipt_match sctp_match =
+
+static struct xt_match sctp_match =
{
- .list = { NULL, NULL},
.name = "sctp",
.match = &match,
.checkentry = &checkentry,
- .destroy = NULL,
+ .me = THIS_MODULE
+};
+static struct xt_match sctp6_match =
+{
+ .name = "sctp",
+ .match = &match,
+ .checkentry = &checkentry6,
.me = THIS_MODULE
};
+
static int __init init(void)
{
- return ipt_register_match(&sctp_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &sctp_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &sctp6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &sctp_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&sctp_match);
+ xt_unregister_match(AF_INET6, &sctp6_match);
+ xt_unregister_match(AF_INET, &sctp_match);
}
module_init(init);
module_exit(fini);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kiran Kumar Immidi");
-MODULE_DESCRIPTION("Match for SCTP protocol packets");
-
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c
index 4d7f16b70cec..39ce808d40ef 100644
--- a/net/ipv4/netfilter/ipt_state.c
+++ b/net/netfilter/xt_state.c
@@ -1,7 +1,7 @@
/* Kernel module to match connection tracking information. */
/* (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
@@ -11,12 +11,14 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <net/netfilter/nf_conntrack_compat.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_state.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_state.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
-MODULE_DESCRIPTION("iptables connection tracking state match module");
+MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
+MODULE_ALIAS("ipt_state");
+MODULE_ALIAS("ip6t_state");
static int
match(const struct sk_buff *skb,
@@ -24,35 +26,43 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_state_info *sinfo = matchinfo;
+ const struct xt_state_info *sinfo = matchinfo;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
if (nf_ct_is_untracked(skb))
- statebit = IPT_STATE_UNTRACKED;
+ statebit = XT_STATE_UNTRACKED;
else if (!nf_ct_get_ctinfo(skb, &ctinfo))
- statebit = IPT_STATE_INVALID;
+ statebit = XT_STATE_INVALID;
else
- statebit = IPT_STATE_BIT(ctinfo);
+ statebit = XT_STATE_BIT(ctinfo);
return (sinfo->statemask & statebit);
}
static int check(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_state_info)))
return 0;
return 1;
}
-static struct ipt_match state_match = {
+static struct xt_match state_match = {
+ .name = "state",
+ .match = &match,
+ .checkentry = &check,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match state6_match = {
.name = "state",
.match = &match,
.checkentry = &check,
@@ -61,13 +71,25 @@ static struct ipt_match state_match = {
static int __init init(void)
{
- need_ip_conntrack();
- return ipt_register_match(&state_match);
+ int ret;
+
+ need_conntrack();
+
+ ret = xt_register_match(AF_INET, &state_match);
+ if (ret < 0)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &state6_match);
+ if (ret < 0)
+ xt_unregister_match(AF_INET,&state_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&state_match);
+ xt_unregister_match(AF_INET, &state_match);
+ xt_unregister_match(AF_INET6, &state6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c
index b5def204d798..7c7d5c8807d6 100644
--- a/net/ipv4/netfilter/ipt_string.c
+++ b/net/netfilter/xt_string.c
@@ -11,23 +11,26 @@
#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/netfilter/x_tables.h>
+#include <linux/netfilter/xt_string.h>
#include <linux/textsearch.h>
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
MODULE_DESCRIPTION("IP tables string match module");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_string");
+MODULE_ALIAS("ip6t_string");
static int match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
struct ts_state state;
- struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo;
+ struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
memset(&state, 0, sizeof(struct ts_state));
@@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb,
!= UINT_MAX) && !conf->invert;
}
-#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m)
+#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
static int checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- struct ipt_string_info *conf = matchinfo;
+ struct xt_string_info *conf = matchinfo;
struct ts_config *ts_conf;
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
+ if (matchsize != XT_ALIGN(sizeof(struct xt_string_info)))
return 0;
/* Damn, can't handle this case properly with iptables... */
@@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize)
textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
}
-static struct ipt_match string_match = {
+static struct xt_match string_match = {
+ .name = "string",
+ .match = match,
+ .checkentry = checkentry,
+ .destroy = destroy,
+ .me = THIS_MODULE
+};
+static struct xt_match string6_match = {
.name = "string",
.match = match,
.checkentry = checkentry,
@@ -79,12 +89,22 @@ static struct ipt_match string_match = {
static int __init init(void)
{
- return ipt_register_match(&string_match);
+ int ret;
+
+ ret = xt_register_match(AF_INET, &string_match);
+ if (ret)
+ return ret;
+ ret = xt_register_match(AF_INET6, &string6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &string_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&string_match);
+ xt_unregister_match(AF_INET, &string_match);
+ xt_unregister_match(AF_INET6, &string6_match);
}
module_init(init);
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 4dc9b16ab4a3..acf7f533e9f1 100644
--- a/net/ipv4/netfilter/ipt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -1,6 +1,7 @@
/* Kernel module to match TCP MSS values. */
/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
+ * Portions (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
@@ -11,19 +12,24 @@
#include <linux/skbuff.h>
#include <net/tcp.h>
-#include <linux/netfilter_ipv4/ipt_tcpmss.h>
+#include <linux/netfilter/xt_tcpmss.h>
+#include <linux/netfilter/x_tables.h>
+
#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
#define TH_SYN 0x02
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables TCP MSS match module");
+MODULE_ALIAS("ipt_tcpmss");
/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
static inline int
mssoption_match(u_int16_t min, u_int16_t max,
const struct sk_buff *skb,
+ unsigned int protoff,
int invert,
int *hotdrop)
{
@@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
unsigned int i, optlen;
/* If we don't have the whole header, drop packet. */
- th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
- sizeof(_tcph), &_tcph);
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL)
goto dropit;
@@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max,
goto out;
/* Truncated options. */
- op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th),
- optlen, _opt);
+ op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt);
if (op == NULL)
goto dropit;
@@ -79,22 +83,24 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
+ unsigned int protoff,
int *hotdrop)
{
- const struct ipt_tcpmss_match_info *info = matchinfo;
+ const struct xt_tcpmss_match_info *info = matchinfo;
- return mssoption_match(info->mss_min, info->mss_max, skb,
+ return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
info->invert, hotdrop);
}
static int
checkentry(const char *tablename,
- const struct ipt_ip *ip,
+ const void *ipinfo,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
- if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info)))
+ const struct ipt_ip *ip = ipinfo;
+ if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
return 0;
/* Must specify -p tcp */
@@ -106,21 +112,60 @@ checkentry(const char *tablename,
return 1;
}
-static struct ipt_match tcpmss_match = {
+static int
+checkentry6(const char *tablename,
+ const void *ipinfo,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ip = ipinfo;
+
+ if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
+ return 0;
+
+ /* Must specify -p tcp */
+ if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) {
+ printk("tcpmss: Only works on TCP packets\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct xt_match tcpmss_match = {
.name = "tcpmss",
.match = &match,
.checkentry = &checkentry,
.me = THIS_MODULE,
};
+static struct xt_match tcpmss6_match = {
+ .name = "tcpmss",
+ .match = &match,
+ .checkentry = &checkentry6,
+ .me = THIS_MODULE,
+};
+
+
static int __init init(void)
{
- return ipt_register_match(&tcpmss_match);
+ int ret;
+ ret = xt_register_match(AF_INET, &tcpmss_match);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &tcpmss6_match);
+ if (ret)
+ xt_unregister_match(AF_INET, &tcpmss_match);
+
+ return ret;
}
static void __exit fini(void)
{
- ipt_unregister_match(&tcpmss_match);
+ xt_unregister_match(AF_INET6, &tcpmss6_match);
+ xt_unregister_match(AF_INET, &tcpmss_match);
}
module_init(init);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
new file mode 100644
index 000000000000..669c8113cc60
--- /dev/null
+++ b/net/netfilter/xt_tcpudp.c
@@ -0,0 +1,334 @@
+#include <linux/types.h>
+#include <linux/module.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_tcpudp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xt_tcp");
+MODULE_ALIAS("xt_udp");
+MODULE_ALIAS("ipt_udp");
+MODULE_ALIAS("ipt_tcp");
+MODULE_ALIAS("ip6t_udp");
+MODULE_ALIAS("ip6t_tcp");
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+
+/* Returns 1 if the port is matched by the range, 0 otherwise */
+static inline int
+port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
+{
+ int ret;
+
+ ret = (port >= min && port <= max) ^ invert;
+ return ret;
+}
+
+static int
+tcp_find_option(u_int8_t option,
+ const struct sk_buff *skb,
+ unsigned int protoff,
+ unsigned int optlen,
+ int invert,
+ int *hotdrop)
+{
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+ u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+ unsigned int i;
+
+ duprintf("tcp_match: finding option\n");
+
+ if (!optlen)
+ return invert;
+
+ /* If we don't have the whole header, drop packet. */
+ op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
+ optlen, _opt);
+ if (op == NULL) {
+ *hotdrop = 1;
+ return 0;
+ }
+
+ for (i = 0; i < optlen; ) {
+ if (op[i] == option) return !invert;
+ if (op[i] < 2) i++;
+ else i += op[i+1]?:1;
+ }
+
+ return invert;
+}
+
+static int
+tcp_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ struct tcphdr _tcph, *th;
+ const struct xt_tcp *tcpinfo = matchinfo;
+
+ if (offset) {
+ /* To quote Alan:
+
+ Don't allow a fragment of TCP 8 bytes in. Nobody normal
+ causes this. Its a cracker trying to break in by doing a
+ flag overwrite to pass the direction checks.
+ */
+ if (offset == 1) {
+ duprintf("Dropping evil TCP offset=1 frag.\n");
+ *hotdrop = 1;
+ }
+ /* Must not be a fragment. */
+ return 0;
+ }
+
+#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+ if (th == NULL) {
+ /* We've been asked to examine this packet, and we
+ can't. Hence, no choice but to drop. */
+ duprintf("Dropping evil TCP offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
+ ntohs(th->source),
+ !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
+ return 0;
+ if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
+ ntohs(th->dest),
+ !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
+ return 0;
+ if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
+ == tcpinfo->flg_cmp,
+ XT_TCP_INV_FLAGS))
+ return 0;
+ if (tcpinfo->option) {
+ if (th->doff * 4 < sizeof(_tcph)) {
+ *hotdrop = 1;
+ return 0;
+ }
+ if (!tcp_find_option(tcpinfo->option, skb, protoff,
+ th->doff*4 - sizeof(_tcph),
+ tcpinfo->invflags & XT_TCP_INV_OPTION,
+ hotdrop))
+ return 0;
+ }
+ return 1;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+tcp_checkentry(const char *tablename,
+ const void *info,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_tcp *tcpinfo = matchinfo;
+
+ /* Must specify proto == TCP, and no unknown invflags */
+ return ip->proto == IPPROTO_TCP
+ && !(ip->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
+ && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+tcp6_checkentry(const char *tablename,
+ const void *entry,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ipv6 = entry;
+ const struct xt_tcp *tcpinfo = matchinfo;
+
+ /* Must specify proto == TCP, and no unknown invflags */
+ return ipv6->proto == IPPROTO_TCP
+ && !(ipv6->invflags & XT_INV_PROTO)
+ && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
+ && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
+}
+
+
+static int
+udp_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ int *hotdrop)
+{
+ struct udphdr _udph, *uh;
+ const struct xt_udp *udpinfo = matchinfo;
+
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+ if (uh == NULL) {
+ /* We've been asked to examine this packet, and we
+ can't. Hence, no choice but to drop. */
+ duprintf("Dropping evil UDP tinygram.\n");
+ *hotdrop = 1;
+ return 0;
+ }
+
+ return port_match(udpinfo->spts[0], udpinfo->spts[1],
+ ntohs(uh->source),
+ !!(udpinfo->invflags & XT_UDP_INV_SRCPT))
+ && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
+ ntohs(uh->dest),
+ !!(udpinfo->invflags & XT_UDP_INV_DSTPT));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+udp_checkentry(const char *tablename,
+ const void *info,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
+{
+ const struct ipt_ip *ip = info;
+ const struct xt_udp *udpinfo = matchinfo;
+
+ /* Must specify proto == UDP, and no unknown invflags */
+ if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) {
+ duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
+ IPPROTO_UDP);
+ return 0;
+ }
+ if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
+ duprintf("ipt_udp: matchsize %u != %u\n",
+ matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
+ return 0;
+ }
+ if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
+ duprintf("ipt_udp: unknown flags %X\n",
+ udpinfo->invflags);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+udp6_checkentry(const char *tablename,
+ const void *entry,
+ void *matchinfo,
+ unsigned int matchinfosize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_ip6 *ipv6 = entry;
+ const struct xt_udp *udpinfo = matchinfo;
+
+ /* Must specify proto == UDP, and no unknown invflags */
+ if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) {
+ duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
+ IPPROTO_UDP);
+ return 0;
+ }
+ if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
+ duprintf("ip6t_udp: matchsize %u != %u\n",
+ matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
+ return 0;
+ }
+ if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
+ duprintf("ip6t_udp: unknown flags %X\n",
+ udpinfo->invflags);
+ return 0;
+ }
+
+ return 1;
+}
+
+static struct xt_match tcp_matchstruct = {
+ .name = "tcp",
+ .match = &tcp_match,
+ .checkentry = &tcp_checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_match tcp6_matchstruct = {
+ .name = "tcp",
+ .match = &tcp_match,
+ .checkentry = &tcp6_checkentry,
+ .me = THIS_MODULE,
+};
+
+static struct xt_match udp_matchstruct = {
+ .name = "udp",
+ .match = &udp_match,
+ .checkentry = &udp_checkentry,
+ .me = THIS_MODULE,
+};
+static struct xt_match udp6_matchstruct = {
+ .name = "udp",
+ .match = &udp_match,
+ .checkentry = &udp6_checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ int ret;
+ ret = xt_register_match(AF_INET, &tcp_matchstruct);
+ if (ret)
+ return ret;
+
+ ret = xt_register_match(AF_INET6, &tcp6_matchstruct);
+ if (ret)
+ goto out_unreg_tcp;
+
+ ret = xt_register_match(AF_INET, &udp_matchstruct);
+ if (ret)
+ goto out_unreg_tcp6;
+
+ ret = xt_register_match(AF_INET6, &udp6_matchstruct);
+ if (ret)
+ goto out_unreg_udp;
+
+ return ret;
+
+out_unreg_udp:
+ xt_unregister_match(AF_INET, &tcp_matchstruct);
+out_unreg_tcp6:
+ xt_unregister_match(AF_INET6, &tcp6_matchstruct);
+out_unreg_tcp:
+ xt_unregister_match(AF_INET, &tcp_matchstruct);
+ return ret;
+}
+
+static void __exit fini(void)
+{
+ xt_unregister_match(AF_INET6, &udp6_matchstruct);
+ xt_unregister_match(AF_INET, &udp_matchstruct);
+ xt_unregister_match(AF_INET6, &tcp6_matchstruct);
+ xt_unregister_match(AF_INET, &tcp_matchstruct);
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 96020d7087e8..2101b45d2ec6 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -24,6 +24,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/signal.h>
@@ -293,7 +294,7 @@ static inline int nl_pid_hash_dilute(struct nl_pid_hash *hash, int len)
return 0;
}
-static struct proto_ops netlink_ops;
+static const struct proto_ops netlink_ops;
static int netlink_insert(struct sock *sk, u32 pid)
{
@@ -402,7 +403,7 @@ static int netlink_create(struct socket *sock, int protocol)
groups = nl_table[protocol].groups;
netlink_unlock_table();
- if ((err = __netlink_create(sock, protocol) < 0))
+ if ((err = __netlink_create(sock, protocol)) < 0)
goto out_module;
nlk = nlk_sk(sock->sk);
@@ -1422,7 +1423,7 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *,
while (skb->len >= nlmsg_total_size(0)) {
nlh = (struct nlmsghdr *) skb->data;
- if (skb->len < nlh->nlmsg_len)
+ if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len)
return 0;
total_len = min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len);
@@ -1656,7 +1657,7 @@ int netlink_unregister_notifier(struct notifier_block *nb)
return notifier_chain_unregister(&netlink_chain, nb);
}
-static struct proto_ops netlink_ops = {
+static const struct proto_ops netlink_ops = {
.family = PF_NETLINK,
.owner = THIS_MODULE,
.release = netlink_release,
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 287cfcc56951..4ae1538c54a9 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -222,11 +222,6 @@ int genl_register_family(struct genl_family *family)
goto errout_locked;
}
- if (!try_module_get(family->owner)) {
- err = -EBUSY;
- goto errout_locked;
- }
-
if (family->id == GENL_ID_GENERATE) {
u16 newid = genl_generate_id();
@@ -283,7 +278,6 @@ int genl_unregister_family(struct genl_family *family)
INIT_LIST_HEAD(&family->ops_list);
genl_unlock();
- module_put(family->owner);
kfree(family->attrbuf);
genl_ctrl_event(CTRL_CMD_DELFAMILY, family);
return 0;
@@ -441,7 +435,7 @@ errout:
}
static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
- int seq, int cmd)
+ int seq, u8 cmd)
{
struct sk_buff *skb;
int err;
@@ -535,7 +529,6 @@ static struct genl_family genl_ctrl = {
.name = "nlctrl",
.version = 0x1,
.maxattr = CTRL_ATTR_MAX,
- .owner = THIS_MODULE,
};
static int __init genl_init(void)
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index e5d82d711cae..d44981f5a619 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -11,6 +11,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -63,7 +64,7 @@ static unsigned short circuit = 0x101;
static HLIST_HEAD(nr_list);
static DEFINE_SPINLOCK(nr_list_lock);
-static struct proto_ops nr_proto_ops;
+static const struct proto_ops nr_proto_ops;
/*
* Socket removal during an interrupt is now safe.
@@ -1166,10 +1167,11 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int ret;
- lock_sock(sk);
switch (cmd) {
case TIOCOUTQ: {
long amount;
+
+ lock_sock(sk);
amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
if (amount < 0)
amount = 0;
@@ -1180,6 +1182,8 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case TIOCINQ: {
struct sk_buff *skb;
long amount = 0L;
+
+ lock_sock(sk);
/* 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;
@@ -1188,6 +1192,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
case SIOCGSTAMP:
+ lock_sock(sk);
ret = sock_get_timestamp(sk, argp);
release_sock(sk);
return ret;
@@ -1202,21 +1207,17 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK:
case SIOCGIFMETRIC:
case SIOCSIFMETRIC:
- release_sock(sk);
return -EINVAL;
case SIOCADDRT:
case SIOCDELRT:
case SIOCNRDECOBS:
- release_sock(sk);
if (!capable(CAP_NET_ADMIN)) return -EPERM;
return nr_rt_ioctl(cmd, argp);
default:
- release_sock(sk);
- return dev_ioctl(cmd, argp);
+ return -ENOIOCTLCMD;
}
- release_sock(sk);
return 0;
}
@@ -1337,7 +1338,7 @@ static struct net_proto_family nr_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops nr_proto_ops = {
+static const struct proto_ops nr_proto_ops = {
.family = PF_NETROM,
.owner = THIS_MODULE,
.release = nr_release,
diff --git a/net/nonet.c b/net/nonet.c
index e5241dceaa57..1230f0ae832e 100644
--- a/net/nonet.c
+++ b/net/nonet.c
@@ -14,11 +14,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
-void __init sock_init(void)
-{
- printk(KERN_INFO "Linux NoNET1.0 for Linux 2.6\n");
-}
-
static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
{
return -ENXIO;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 3e2462760413..ee93abc71cb8 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -53,6 +53,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/socket.h>
#include <linux/in.h>
@@ -251,10 +252,10 @@ static void packet_sock_destruct(struct sock *sk)
}
-static struct proto_ops packet_ops;
+static const struct proto_ops packet_ops;
#ifdef CONFIG_SOCK_PACKET
-static struct proto_ops packet_ops_spkt;
+static const struct proto_ops packet_ops_spkt;
static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
@@ -1237,7 +1238,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)
goto done;
err = -ENOBUFS;
- i = (struct packet_mclist *)kmalloc(sizeof(*i), GFP_KERNEL);
+ i = kmalloc(sizeof(*i), GFP_KERNEL);
if (i == NULL)
goto done;
@@ -1521,7 +1522,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
#endif
default:
- return dev_ioctl(cmd, (void __user *)arg);
+ return -ENOIOCTLCMD;
}
return 0;
}
@@ -1784,7 +1785,7 @@ out:
#ifdef CONFIG_SOCK_PACKET
-static struct proto_ops packet_ops_spkt = {
+static const struct proto_ops packet_ops_spkt = {
.family = PF_PACKET,
.owner = THIS_MODULE,
.release = packet_release,
@@ -1806,7 +1807,7 @@ static struct proto_ops packet_ops_spkt = {
};
#endif
-static struct proto_ops packet_ops = {
+static const struct proto_ops packet_ops = {
.family = PF_PACKET,
.owner = THIS_MODULE,
.release = packet_release,
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 829fdbc4400b..ea65396d1619 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -9,7 +9,9 @@
* Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)
* Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
*/
+
#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -1320,7 +1322,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return 0;
default:
- return dev_ioctl(cmd, argp);
+ return -ENOIOCTLCMD;
}
return 0;
diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c
index 2ba14a75dbbe..0e0a4553499f 100644
--- a/net/rxrpc/connection.c
+++ b/net/rxrpc/connection.c
@@ -220,6 +220,7 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
{
struct rxrpc_connection *conn, *candidate = NULL;
struct list_head *_p;
+ struct sk_buff *pkt = msg->pkt;
int ret, fresh = 0;
__be32 x_epoch, x_connid;
__be16 x_port, x_servid;
@@ -229,10 +230,10 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
_enter("%p{{%hu}},%u,%hu",
peer,
peer->trans->port,
- ntohs(msg->pkt->h.uh->source),
+ ntohs(pkt->h.uh->source),
ntohs(msg->hdr.serviceId));
- x_port = msg->pkt->h.uh->source;
+ x_port = pkt->h.uh->source;
x_epoch = msg->hdr.epoch;
x_clflag = msg->hdr.flags & RXRPC_CLIENT_INITIATED;
x_connid = htonl(ntohl(msg->hdr.cid) & RXRPC_CIDMASK);
@@ -267,7 +268,7 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
/* fill in the specifics */
candidate->addr.sin_family = AF_INET;
candidate->addr.sin_port = x_port;
- candidate->addr.sin_addr.s_addr = msg->pkt->nh.iph->saddr;
+ candidate->addr.sin_addr.s_addr = pkt->nh.iph->saddr;
candidate->in_epoch = x_epoch;
candidate->out_epoch = x_epoch;
candidate->in_clientflag = RXRPC_CLIENT_INITIATED;
@@ -675,6 +676,7 @@ int rxrpc_conn_receive_call_packet(struct rxrpc_connection *conn,
struct rxrpc_message *msg)
{
struct rxrpc_message *pmsg;
+ struct dst_entry *dst;
struct list_head *_p;
unsigned cix, seq;
int ret = 0;
@@ -710,10 +712,10 @@ int rxrpc_conn_receive_call_packet(struct rxrpc_connection *conn,
call->pkt_rcv_count++;
- if (msg->pkt->dst && msg->pkt->dst->dev)
+ dst = msg->pkt->dst;
+ if (dst && dst->dev)
conn->peer->if_mtu =
- msg->pkt->dst->dev->mtu -
- msg->pkt->dst->dev->hard_header_len;
+ dst->dev->mtu - dst->dev->hard_header_len;
/* queue on the call in seq order */
rxrpc_get_message(msg);
diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
index 3ac81cdd1211..3e7466900bd4 100644
--- a/net/rxrpc/krxtimod.c
+++ b/net/rxrpc/krxtimod.c
@@ -81,7 +81,7 @@ static int krxtimod(void *arg)
for (;;) {
unsigned long jif;
- signed long timeout;
+ long timeout;
/* deal with the server being asked to die */
if (krxtimod_die) {
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 3b5ecd8e2401..29975d99d864 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -361,7 +361,7 @@ static void rxrpc_proc_peers_stop(struct seq_file *p, void *v)
static int rxrpc_proc_peers_show(struct seq_file *m, void *v)
{
struct rxrpc_peer *peer = list_entry(v, struct rxrpc_peer, proc_link);
- signed long timeout;
+ long timeout;
/* display header on line 1 */
if (v == SEQ_START_TOKEN) {
@@ -373,8 +373,8 @@ static int rxrpc_proc_peers_show(struct seq_file *m, void *v)
/* display one peer per line on subsequent lines */
timeout = 0;
if (!list_empty(&peer->timeout.link))
- timeout = (signed long) peer->timeout.timo_jif -
- (signed long) jiffies;
+ timeout = (long) peer->timeout.timo_jif -
+ (long) jiffies;
seq_printf(m, "%5hu %08x %5d %5d %8ld %5Zu %7lu\n",
peer->trans->port,
@@ -468,7 +468,7 @@ static void rxrpc_proc_conns_stop(struct seq_file *p, void *v)
static int rxrpc_proc_conns_show(struct seq_file *m, void *v)
{
struct rxrpc_connection *conn;
- signed long timeout;
+ long timeout;
conn = list_entry(v, struct rxrpc_connection, proc_link);
@@ -484,8 +484,8 @@ static int rxrpc_proc_conns_show(struct seq_file *m, void *v)
/* display one conn per line on subsequent lines */
timeout = 0;
if (!list_empty(&conn->timeout.link))
- timeout = (signed long) conn->timeout.timo_jif -
- (signed long) jiffies;
+ timeout = (long) conn->timeout.timo_jif -
+ (long) jiffies;
seq_printf(m,
"%5hu %08x %5hu %04hx %08x %-3.3s %08x %08x %5Zu %8ld\n",
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 55cd5327fbd7..778b1e5a4b50 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -44,7 +44,7 @@ if NET_SCHED
choice
prompt "Packet scheduler clock source"
- default NET_SCH_CLK_JIFFIES
+ default NET_SCH_CLK_GETTIMEOFDAY
---help---
Packet schedulers need a monotonic clock that increments at a static
rate. The kernel provides several suitable interfaces, each with
@@ -411,7 +411,7 @@ config NET_EMATCH_META
tristate "Metadata"
depends on NET_EMATCH
---help---
- Say Y here if you want to be ablt to classify packets based on
+ Say Y here if you want to be able to classify packets based on
metadata such as load average, netfilter attributes, socket
attributes and routing decisions.
diff --git a/net/sched/Makefile b/net/sched/Makefile
index e48d0d456b3e..0f06aec66094 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -7,13 +7,13 @@ obj-y := sch_generic.o
obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o
obj-$(CONFIG_NET_CLS) += cls_api.o
obj-$(CONFIG_NET_CLS_ACT) += act_api.o
-obj-$(CONFIG_NET_ACT_POLICE) += police.o
-obj-$(CONFIG_NET_CLS_POLICE) += police.o
-obj-$(CONFIG_NET_ACT_GACT) += gact.o
-obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o
-obj-$(CONFIG_NET_ACT_IPT) += ipt.o
-obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o
-obj-$(CONFIG_NET_ACT_SIMP) += simple.o
+obj-$(CONFIG_NET_ACT_POLICE) += act_police.o
+obj-$(CONFIG_NET_CLS_POLICE) += act_police.o
+obj-$(CONFIG_NET_ACT_GACT) += act_gact.o
+obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o
+obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o
+obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o
+obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 2ce1cb2aa2ed..792ce59940ec 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, res);
+ 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);
@@ -290,7 +290,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est,
if (a_o == NULL) {
#ifdef CONFIG_KMOD
rtnl_unlock();
- request_module(act_name);
+ request_module("act_%s", act_name);
rtnl_lock();
a_o = tc_lookup_action_n(act_name);
diff --git a/net/sched/gact.c b/net/sched/act_gact.c
index d1c6d542912a..a1e68f78dcc2 100644
--- a/net/sched/gact.c
+++ b/net/sched/act_gact.c
@@ -135,10 +135,9 @@ tcf_gact_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_gact(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
+tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_gact *p = PRIV(a, gact);
- struct sk_buff *skb = *pskb;
int action = TC_ACT_SHOT;
spin_lock(&p->lock);
diff --git a/net/sched/ipt.c b/net/sched/act_ipt.c
index f50136eed211..39a22a3ffe78 100644
--- a/net/sched/ipt.c
+++ b/net/sched/act_ipt.c
@@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook)
struct ipt_target *target;
int ret = 0;
- target = ipt_find_target(t->u.user.name, t->u.user.revision);
+ target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
if (!target)
return -ENOENT;
@@ -201,11 +201,10 @@ tcf_ipt_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
+tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
{
int ret = 0, result = 0;
struct tcf_ipt *p = PRIV(a, ipt);
- struct sk_buff *skb = *pskb;
if (skb_cloned(skb)) {
if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
@@ -222,6 +221,9 @@ tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
worry later - danger - this API seems to have changed
from earlier kernels */
+ /* iptables targets take a double skb pointer in case the skb
+ * needs to be replaced. We don't own the skb, so this must not
+ * happen. The pskb_expand_head above should make sure of this */
ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL,
p->hook, p->t->data, NULL);
switch (ret) {
diff --git a/net/sched/mirred.c b/net/sched/act_mirred.c
index 20d06916dc0b..4fcccbd50885 100644
--- a/net/sched/mirred.c
+++ b/net/sched/act_mirred.c
@@ -158,12 +158,11 @@ tcf_mirred_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_mirred(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
+tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_mirred *p = PRIV(a, mirred);
struct net_device *dev;
struct sk_buff *skb2 = NULL;
- struct sk_buff *skb = *pskb;
u32 at = G_TC_AT(skb->tc_verd);
spin_lock(&p->lock);
diff --git a/net/sched/pedit.c b/net/sched/act_pedit.c
index 767d24f4610e..1742a68e0122 100644
--- a/net/sched/pedit.c
+++ b/net/sched/act_pedit.c
@@ -130,10 +130,9 @@ tcf_pedit_cleanup(struct tc_action *a, int bind)
}
static int
-tcf_pedit(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res)
+tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
{
struct tcf_pedit *p = PRIV(a, pedit);
- struct sk_buff *skb = *pskb;
int i, munged = 0;
u8 *pptr;
@@ -246,10 +245,12 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref)
t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
t.expires = jiffies_to_clock_t(p->tm.expires);
RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t);
+ kfree(opt);
return skb->len;
rtattr_failure:
skb_trim(skb, b - skb->data);
+ kfree(opt);
return -1;
}
diff --git a/net/sched/police.c b/net/sched/act_police.c
index eb39fb2f39b6..fa877f8f652c 100644
--- a/net/sched/police.c
+++ b/net/sched/act_police.c
@@ -284,11 +284,10 @@ 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 *skb, struct tc_action *a,
struct tcf_result *res)
{
psched_time_t now;
- struct sk_buff *skb = *pskb;
struct tcf_police *p = PRIV(a);
long toks;
long ptoks = 0;
@@ -408,7 +407,7 @@ police_cleanup_module(void)
module_init(police_init_module);
module_exit(police_cleanup_module);
-#endif
+#else /* CONFIG_NET_CLS_ACT */
struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
{
@@ -545,6 +544,7 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *p)
spin_unlock(&p->lock);
return p->action;
}
+EXPORT_SYMBOL(tcf_police);
int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p)
{
@@ -601,13 +601,4 @@ errout:
return -1;
}
-
-EXPORT_SYMBOL(tcf_police);
-EXPORT_SYMBOL(tcf_police_destroy);
-EXPORT_SYMBOL(tcf_police_dump);
-EXPORT_SYMBOL(tcf_police_dump_stats);
-EXPORT_SYMBOL(tcf_police_hash);
-EXPORT_SYMBOL(tcf_police_ht);
-EXPORT_SYMBOL(tcf_police_locate);
-EXPORT_SYMBOL(tcf_police_lookup);
-EXPORT_SYMBOL(tcf_police_new_index);
+#endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/simple.c b/net/sched/act_simple.c
index 8a6ae4f491e8..e5f2e1f431e2 100644
--- a/net/sched/simple.c
+++ b/net/sched/act_simple.c
@@ -44,9 +44,8 @@ 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, struct tcf_result *res)
+static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
{
- struct sk_buff *skb = *pskb;
struct tcf_defact *p = PRIV(a, defact);
spin_lock(&p->lock);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 64b047c65568..5cb956b721e8 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -92,7 +92,6 @@
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <net/pkt_cls.h>
-#include <config/net/ematch/stack.h>
static LIST_HEAD(ematch_ops);
static DEFINE_RWLOCK(ematch_mod_lock);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 09453f997d8c..6cd81708bf71 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -257,7 +257,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
(cl = cbq_class_lookup(q, prio)) != NULL)
return cl;
- *qerr = NET_XMIT_DROP;
+ *qerr = NET_XMIT_BYPASS;
for (;;) {
int result = 0;
defmap = head->defaults;
@@ -413,7 +413,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
q->rx_class = cl;
#endif
if (cl == NULL) {
- if (ret == NET_XMIT_DROP)
+ if (ret == NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb(skb);
return ret;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index c26764bc4103..91132f6871d7 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -208,7 +208,7 @@ struct hfsc_sched
do { \
struct timeval tv; \
do_gettimeofday(&tv); \
- (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \
+ (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \
} while (0)
#endif
@@ -502,8 +502,8 @@ d2dx(u32 d)
u64 dx;
dx = ((u64)d * PSCHED_JIFFIE2US(HZ));
- dx += 1000000 - 1;
- do_div(dx, 1000000);
+ dx += USEC_PER_SEC - 1;
+ do_div(dx, USEC_PER_SEC);
return dx;
}
@@ -523,7 +523,7 @@ dx2d(u64 dx)
{
u64 d;
- d = dx * 1000000;
+ d = dx * USEC_PER_SEC;
do_div(d, PSCHED_JIFFIE2US(HZ));
return (u32)d;
}
@@ -1227,7 +1227,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
if (cl->level == 0)
return cl;
- *qerr = NET_XMIT_DROP;
+ *qerr = NET_XMIT_BYPASS;
tcf = q->root.filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
@@ -1643,7 +1643,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
cl = hfsc_classify(skb, sch, &err);
if (cl == NULL) {
- if (err == NET_XMIT_DROP)
+ if (err == NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb(skb);
return err;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 558cc087e602..3ec95df4a85e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -321,7 +321,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, in
if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0)
return cl;
- *qerr = NET_XMIT_DROP;
+ *qerr = NET_XMIT_BYPASS;
tcf = q->filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
@@ -724,7 +724,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
}
#ifdef CONFIG_NET_CLS_ACT
} else if (!cl) {
- if (ret == NET_XMIT_DROP)
+ if (ret == NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb (skb);
return ret;
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 82fb07aa06a5..ba5283204837 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -25,7 +25,7 @@
#include <net/pkt_sched.h>
-#define VERSION "1.1"
+#define VERSION "1.2"
/* Network Emulation Queuing algorithm.
====================================
@@ -65,11 +65,12 @@ struct netem_sched_data {
u32 jitter;
u32 duplicate;
u32 reorder;
+ u32 corrupt;
struct crndstate {
unsigned long last;
unsigned long rho;
- } delay_cor, loss_cor, dup_cor, reorder_cor;
+ } delay_cor, loss_cor, dup_cor, reorder_cor, corrupt_cor;
struct disttable {
u32 size;
@@ -183,6 +184,23 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
q->duplicate = dupsave;
}
+ /*
+ * Randomized packet corruption.
+ * Make copy if needed since we are modifying
+ * If packet is going to be hardware checksummed, then
+ * do it now in software before we mangle it.
+ */
+ if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
+ if (!(skb = skb_unshare(skb, GFP_ATOMIC))
+ || (skb->ip_summed == CHECKSUM_HW
+ && skb_checksum_help(skb, 0))) {
+ sch->qstats.drops++;
+ return NET_XMIT_DROP;
+ }
+
+ skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
+ }
+
if (q->gap == 0 /* not doing reordering */
|| q->counter < q->gap /* inside last reordering gap */
|| q->reorder < get_crandom(&q->reorder_cor)) {
@@ -382,6 +400,20 @@ static int get_reorder(struct Qdisc *sch, const struct rtattr *attr)
return 0;
}
+static int get_corrupt(struct Qdisc *sch, const struct rtattr *attr)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+ const struct tc_netem_corrupt *r = RTA_DATA(attr);
+
+ if (RTA_PAYLOAD(attr) != sizeof(*r))
+ return -EINVAL;
+
+ q->corrupt = r->probability;
+ init_crandom(&q->corrupt_cor, r->correlation);
+ return 0;
+}
+
+/* Parse netlink message to set options */
static int netem_change(struct Qdisc *sch, struct rtattr *opt)
{
struct netem_sched_data *q = qdisc_priv(sch);
@@ -432,13 +464,19 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
if (ret)
return ret;
}
+
if (tb[TCA_NETEM_REORDER-1]) {
ret = get_reorder(sch, tb[TCA_NETEM_REORDER-1]);
if (ret)
return ret;
}
- }
+ if (tb[TCA_NETEM_CORRUPT-1]) {
+ ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT-1]);
+ if (ret)
+ return ret;
+ }
+ }
return 0;
}
@@ -564,6 +602,7 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
struct tc_netem_qopt qopt;
struct tc_netem_corr cor;
struct tc_netem_reorder reorder;
+ struct tc_netem_corrupt corrupt;
qopt.latency = q->latency;
qopt.jitter = q->jitter;
@@ -582,6 +621,10 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
reorder.correlation = q->reorder_cor.rho;
RTA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder);
+ corrupt.probability = q->corrupt;
+ corrupt.correlation = q->corrupt_cor.rho;
+ RTA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
+
rta->rta_len = skb->tail - b;
return skb->len;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 3ac0f495bad0..1641db33a994 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -54,7 +54,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
u32 band = skb->priority;
struct tcf_result res;
- *qerr = NET_XMIT_DROP;
+ *qerr = NET_XMIT_BYPASS;
if (TC_H_MAJ(skb->priority) != sch->handle) {
#ifdef CONFIG_NET_CLS_ACT
switch (tc_classify(skb, q->filter_list, &res)) {
@@ -91,7 +91,8 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
qdisc = prio_classify(skb, sch, &ret);
#ifdef CONFIG_NET_CLS_ACT
if (qdisc == NULL) {
- if (ret == NET_XMIT_DROP)
+
+ if (ret == NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb(skb);
return ret;
@@ -118,7 +119,7 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
qdisc = prio_classify(skb, sch, &ret);
#ifdef CONFIG_NET_CLS_ACT
if (qdisc == NULL) {
- if (ret == NET_XMIT_DROP)
+ if (ret == NET_XMIT_BYPASS)
sch->qstats.drops++;
kfree_skb(skb);
return ret;
@@ -227,14 +228,13 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
}
sch_tree_unlock(sch);
- for (i=0; i<=TC_PRIO_MAX; i++) {
- int band = q->prio2band[i];
- if (q->queues[band] == &noop_qdisc) {
+ for (i=0; i<q->bands; i++) {
+ if (q->queues[i] == &noop_qdisc) {
struct Qdisc *child;
child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
if (child) {
sch_tree_lock(sch);
- child = xchg(&q->queues[band], child);
+ child = xchg(&q->queues[i], child);
if (child != &noop_qdisc)
qdisc_destroy(child);
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 8734bb7280e3..86d8da0cbd02 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -144,6 +144,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
(iph->protocol == IPPROTO_TCP ||
iph->protocol == IPPROTO_UDP ||
+ iph->protocol == IPPROTO_SCTP ||
+ iph->protocol == IPPROTO_DCCP ||
iph->protocol == IPPROTO_ESP))
h2 ^= *(((u32*)iph) + iph->ihl);
break;
@@ -155,6 +157,8 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
h2 = iph->saddr.s6_addr32[3]^iph->nexthdr;
if (iph->nexthdr == IPPROTO_TCP ||
iph->nexthdr == IPPROTO_UDP ||
+ iph->nexthdr == IPPROTO_SCTP ||
+ iph->nexthdr == IPPROTO_DCCP ||
iph->nexthdr == IPPROTO_ESP)
h2 ^= *(u32*)&iph[1];
break;
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 6cf0342706b5..79b8ef34c6e4 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -22,6 +22,7 @@
#include <linux/in.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
+#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -273,7 +274,7 @@ teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *de
static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct teql_master *master = (void*)dev->priv;
+ struct teql_master *master = netdev_priv(dev);
struct Qdisc *start, *q;
int busy;
int nores;
@@ -349,7 +350,7 @@ drop:
static int teql_master_open(struct net_device *dev)
{
struct Qdisc * q;
- struct teql_master *m = (void*)dev->priv;
+ struct teql_master *m = netdev_priv(dev);
int mtu = 0xFFFE;
unsigned flags = IFF_NOARP|IFF_MULTICAST;
@@ -396,13 +397,13 @@ static int teql_master_close(struct net_device *dev)
static struct net_device_stats *teql_master_stats(struct net_device *dev)
{
- struct teql_master *m = (void*)dev->priv;
+ struct teql_master *m = netdev_priv(dev);
return &m->stats;
}
static int teql_master_mtu(struct net_device *dev, int new_mtu)
{
- struct teql_master *m = (void*)dev->priv;
+ struct teql_master *m = netdev_priv(dev);
struct Qdisc *q;
if (new_mtu < 68)
@@ -422,7 +423,7 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu)
static __init void teql_master_setup(struct net_device *dev)
{
- struct teql_master *master = dev->priv;
+ struct teql_master *master = netdev_priv(dev);
struct Qdisc_ops *ops = &master->qops;
master->dev = dev;
@@ -475,7 +476,7 @@ static int __init teql_init(void)
break;
}
- master = dev->priv;
+ master = netdev_priv(dev);
strlcpy(master->qops.id, dev->name, IFNAMSIZ);
err = register_qdisc(&master->qops);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index dec68a604773..9d05e13e92f6 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -110,7 +110,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->cookie_life.tv_sec = sp->assocparams.sasoc_cookie_life / 1000;
asoc->cookie_life.tv_usec = (sp->assocparams.sasoc_cookie_life % 1000)
* 1000;
- asoc->pmtu = 0;
asoc->frag_point = 0;
/* Set the association max_retrans and RTO values from the
@@ -123,6 +122,25 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->overall_error_count = 0;
+ /* Initialize the association's heartbeat interval based on the
+ * sock configured value.
+ */
+ asoc->hbinterval = msecs_to_jiffies(sp->hbinterval);
+
+ /* Initialize path max retrans value. */
+ asoc->pathmaxrxt = sp->pathmaxrxt;
+
+ /* Initialize default path MTU. */
+ asoc->pathmtu = sp->pathmtu;
+
+ /* Set association default SACK delay */
+ asoc->sackdelay = msecs_to_jiffies(sp->sackdelay);
+
+ /* Set the association default flags controlling
+ * Heartbeat, SACK delay, and Path MTU Discovery.
+ */
+ asoc->param_flags = sp->param_flags;
+
/* Initialize the maximum mumber of new data packets that can be sent
* in a burst.
*/
@@ -144,8 +162,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
= 5 * asoc->rto_max;
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
- asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
- SCTP_DEFAULT_TIMEOUT_SACK;
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
@@ -540,23 +557,46 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
sctp_transport_set_owner(peer, asoc);
+ /* Initialize the peer's heartbeat interval based on the
+ * association configured value.
+ */
+ peer->hbinterval = asoc->hbinterval;
+
+ /* Set the path max_retrans. */
+ peer->pathmaxrxt = asoc->pathmaxrxt;
+
+ /* Initialize the peer's SACK delay timeout based on the
+ * association configured value.
+ */
+ peer->sackdelay = asoc->sackdelay;
+
+ /* Enable/disable heartbeat, SACK delay, and path MTU discovery
+ * based on association setting.
+ */
+ peer->param_flags = asoc->param_flags;
+
/* Initialize the pmtu of the transport. */
- sctp_transport_pmtu(peer);
+ if (peer->param_flags & SPP_PMTUD_ENABLE)
+ sctp_transport_pmtu(peer);
+ else if (asoc->pathmtu)
+ peer->pathmtu = asoc->pathmtu;
+ else
+ peer->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
/* If this is the first transport addr on this association,
* initialize the association PMTU to the peer's PMTU.
* If not and the current association PMTU is higher than the new
* peer's PMTU, reset the association PMTU to the new peer's PMTU.
*/
- if (asoc->pmtu)
- asoc->pmtu = min_t(int, peer->pmtu, asoc->pmtu);
+ if (asoc->pathmtu)
+ asoc->pathmtu = min_t(int, peer->pathmtu, asoc->pathmtu);
else
- asoc->pmtu = peer->pmtu;
+ asoc->pathmtu = peer->pathmtu;
SCTP_DEBUG_PRINTK("sctp_assoc_add_peer:association %p PMTU set to "
- "%d\n", asoc, asoc->pmtu);
+ "%d\n", asoc, asoc->pathmtu);
- asoc->frag_point = sctp_frag_point(sp, asoc->pmtu);
+ asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
/* The asoc->peer.port might not be meaningful yet, but
* initialize the packet structure anyway.
@@ -574,7 +614,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
* (for example, implementations MAY use the size of the
* receiver advertised window).
*/
- peer->cwnd = min(4*asoc->pmtu, max_t(__u32, 2*asoc->pmtu, 4380));
+ peer->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
/* At this point, we may not have the receiver's advertised window,
* so initialize ssthresh to the default value and it will be set
@@ -585,17 +625,6 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
peer->partial_bytes_acked = 0;
peer->flight_size = 0;
- /* By default, enable heartbeat for peer address. */
- peer->hb_allowed = 1;
-
- /* Initialize the peer's heartbeat interval based on the
- * sock configured value.
- */
- peer->hb_interval = msecs_to_jiffies(sp->paddrparam.spp_hbinterval);
-
- /* Set the path max_retrans. */
- peer->max_retrans = sp->paddrparam.spp_pathmaxrxt;
-
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
@@ -1155,18 +1184,18 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
/* Get the lowest pmtu of all the transports. */
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);
- if (!pmtu || (t->pmtu < pmtu))
- pmtu = t->pmtu;
+ if (!pmtu || (t->pathmtu < pmtu))
+ pmtu = t->pathmtu;
}
if (pmtu) {
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
- asoc->pmtu = pmtu;
+ asoc->pathmtu = pmtu;
asoc->frag_point = sctp_frag_point(sp, pmtu);
}
SCTP_DEBUG_PRINTK("%s: asoc:%p, pmtu:%d, frag_point:%d\n",
- __FUNCTION__, asoc, asoc->pmtu, asoc->frag_point);
+ __FUNCTION__, asoc, asoc->pathmtu, asoc->frag_point);
}
/* Should we send a SACK to update our peer? */
@@ -1179,7 +1208,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
case SCTP_STATE_SHUTDOWN_SENT:
if ((asoc->rwnd > asoc->a_rwnd) &&
((asoc->rwnd - asoc->a_rwnd) >=
- min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu)))
+ min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pathmtu)))
return 1;
break;
default:
diff --git a/net/sctp/input.c b/net/sctp/input.c
index b24ff2c1aef5..4aa6fc60357c 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -225,6 +225,7 @@ int sctp_rcv(struct sk_buff *skb)
if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
goto discard_release;
+ nf_reset(skb);
ret = sk_filter(sk, skb, 1);
if (ret)
@@ -305,18 +306,36 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
struct sctp_transport *t, __u32 pmtu)
{
- if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
- printk(KERN_WARNING "%s: Reported pmtu %d too low, "
- "using default minimum of %d\n", __FUNCTION__, pmtu,
- SCTP_DEFAULT_MINSEGMENT);
- pmtu = SCTP_DEFAULT_MINSEGMENT;
- }
+ if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu))
+ return;
- if (!sock_owned_by_user(sk) && t && (t->pmtu != pmtu)) {
- t->pmtu = pmtu;
+ if (t->param_flags & SPP_PMTUD_ENABLE) {
+ if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
+ printk(KERN_WARNING "%s: Reported pmtu %d too low, "
+ "using default minimum of %d\n",
+ __FUNCTION__, pmtu,
+ SCTP_DEFAULT_MINSEGMENT);
+ /* Use default minimum segment size and disable
+ * pmtu discovery on this transport.
+ */
+ t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
+ t->param_flags = (t->param_flags & ~SPP_HB) |
+ SPP_PMTUD_DISABLE;
+ } else {
+ t->pathmtu = pmtu;
+ }
+
+ /* Update association pmtu. */
sctp_assoc_sync_pmtu(asoc);
- sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
}
+
+ /* Retransmit with the new pmtu setting.
+ * Normally, if PMTU discovery is disabled, an ICMP Fragmentation
+ * Needed will never be sent, but if a message was sent before
+ * PMTU discovery was disabled that was larger than the PMTU, it
+ * would not be fragmented, so it must be re-transmitted fragmented.
+ */
+ sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
}
/*
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index fa3be2b8fb5f..2e266129a764 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -180,8 +180,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport,
}
SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
- "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
- "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ "src:" NIP6_FMT " dst:" NIP6_FMT "\n",
__FUNCTION__, skb, skb->len,
NIP6(fl.fl6_src), NIP6(fl.fl6_dst));
@@ -206,13 +205,13 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
fl.oif = daddr->v6.sin6_scope_id;
- SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
+ SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
__FUNCTION__, NIP6(fl.fl6_dst));
if (saddr) {
ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
SCTP_DEBUG_PRINTK(
- "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ",
+ "SRC=" NIP6_FMT " - ",
NIP6(fl.fl6_src));
}
@@ -221,8 +220,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
struct rt6_info *rt;
rt = (struct rt6_info *)dst;
SCTP_DEBUG_PRINTK(
- "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
- "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n",
NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr));
} else {
SCTP_DEBUG_PRINTK("NO ROUTE\n");
@@ -271,13 +269,12 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
__u8 bmatchlen;
SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p "
- "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
+ "daddr:" NIP6_FMT " ",
__FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr));
if (!asoc) {
ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr);
- SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n",
NIP6(saddr->v6.sin6_addr));
return;
}
@@ -305,13 +302,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc,
if (baddr) {
memcpy(saddr, baddr, sizeof(union sctp_addr));
- SCTP_DEBUG_PRINTK("saddr: "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n",
NIP6(saddr->v6.sin6_addr));
} else {
printk(KERN_ERR "%s: asoc:%p Could not find a valid source "
- "address for the "
- "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ "address for the dest:" NIP6_FMT "\n",
__FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr));
}
@@ -675,8 +670,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb)
/* Dump the v6 addr to the seq file. */
static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
{
- seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ",
- NIP6(addr->v6.sin6_addr));
+ seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr));
}
/* Initialize a PF_INET6 socket msg_name. */
@@ -866,7 +860,7 @@ static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
return 2;
}
-static struct proto_ops inet6_seqpacket_ops = {
+static const struct proto_ops inet6_seqpacket_ops = {
.family = PF_INET6,
.owner = THIS_MODULE,
.release = inet6_release,
@@ -905,7 +899,7 @@ static struct inet_protosw sctpv6_stream_protosw = {
.flags = SCTP_PROTOSW_FLAG,
};
-static int sctp6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+static int sctp6_rcv(struct sk_buff **pskb)
{
return sctp_rcv(*pskb) ? -1 : 0;
}
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 931371633464..a40991ef72c9 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -234,8 +234,8 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet,
goto finish;
pmtu = ((packet->transport->asoc) ?
- (packet->transport->asoc->pmtu) :
- (packet->transport->pmtu));
+ (packet->transport->asoc->pathmtu) :
+ (packet->transport->pathmtu));
too_big = (psize + chunk_len > pmtu);
@@ -482,7 +482,9 @@ int sctp_packet_transmit(struct sctp_packet *packet)
if (!dst || (dst->obsolete > 1)) {
dst_release(dst);
sctp_transport_route(tp, NULL, sctp_sk(sk));
- sctp_assoc_sync_pmtu(asoc);
+ if (asoc->param_flags & SPP_PMTUD_ENABLE) {
+ sctp_assoc_sync_pmtu(asoc);
+ }
}
nskb->dst = dst_clone(tp->dst);
@@ -492,7 +494,10 @@ int sctp_packet_transmit(struct sctp_packet *packet)
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
nskb->len);
- (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
+ if (tp->param_flags & SPP_PMTUD_ENABLE)
+ (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok);
+ else
+ (*tp->af_specific->sctp_xmit)(nskb, tp, 1);
out:
packet->size = packet->overhead;
@@ -577,7 +582,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
* if ((flightsize + Max.Burst * MTU) < cwnd)
* cwnd = flightsize + Max.Burst * MTU
*/
- max_burst_bytes = asoc->max_burst * asoc->pmtu;
+ max_burst_bytes = asoc->max_burst * asoc->pathmtu;
if ((transport->flight_size + max_burst_bytes) < transport->cwnd) {
transport->cwnd = transport->flight_size + max_burst_bytes;
SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: "
@@ -622,7 +627,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet,
* data will fit or delay in hopes of bundling a full
* sized packet.
*/
- if (len < asoc->pmtu - packet->overhead) {
+ if (len < asoc->pathmtu - packet->overhead) {
retval = SCTP_XMIT_NAGLE_DELAY;
goto finish;
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index f775d78aa59d..de693b43c8ea 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -54,6 +54,7 @@
#include <net/protocol.h>
#include <net/ip.h>
#include <net/ipv6.h>
+#include <net/route.h>
#include <net/sctp/sctp.h>
#include <net/addrconf.h>
#include <net/inet_common.h>
@@ -829,7 +830,7 @@ static struct notifier_block sctp_inetaddr_notifier = {
};
/* Socket operations. */
-static struct proto_ops inet_seqpacket_ops = {
+static const struct proto_ops inet_seqpacket_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, /* Needs to be wrapped... */
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index f9573eba5c7a..556c495c6922 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1287,7 +1287,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
- (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize;
- retval = (sctp_cookie_param_t *)kmalloc(*cookie_len, GFP_ATOMIC);
+ retval = kmalloc(*cookie_len, GFP_ATOMIC);
if (!retval) {
*cookie_len = 0;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 823947170a33..b8b38aba92b3 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -157,9 +157,12 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
{
__u32 ctsn, max_tsn_seen;
struct sctp_chunk *sack;
+ struct sctp_transport *trans = asoc->peer.last_data_from;
int error = 0;
- if (force)
+ if (force ||
+ (!trans && (asoc->param_flags & SPP_SACKDELAY_DISABLE)) ||
+ (trans && (trans->param_flags & SPP_SACKDELAY_DISABLE)))
asoc->peer.sack_needed = 1;
ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
@@ -189,7 +192,22 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
if (!asoc->peer.sack_needed) {
/* We will need a SACK for the next packet. */
asoc->peer.sack_needed = 1;
- goto out;
+
+ /* Set the SACK delay timeout based on the
+ * SACK delay for the last transport
+ * data was received from, or the default
+ * for the association.
+ */
+ if (trans)
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
+ trans->sackdelay;
+ else
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
+ asoc->sackdelay;
+
+ /* Restart the SACK timer. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
} else {
if (asoc->a_rwnd > asoc->rwnd)
asoc->a_rwnd = asoc->rwnd;
@@ -205,7 +223,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
}
-out:
+
return error;
nomem:
error = -ENOMEM;
@@ -415,7 +433,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
asoc->overall_error_count++;
if (transport->state != SCTP_INACTIVE &&
- (transport->error_count++ >= transport->max_retrans)) {
+ (transport->error_count++ >= transport->pathmaxrxt)) {
SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
" transport IP: port:%d failed.\n",
asoc,
@@ -1232,8 +1250,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
case SCTP_CMD_TIMER_START:
timer = &asoc->timers[cmd->obj.to];
timeout = asoc->timeouts[cmd->obj.to];
- if (!timeout)
- BUG();
+ BUG_ON(!timeout);
timer->expires = jiffies + timeout;
sctp_association_hold(asoc);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 475bfb4972d9..477d7f80dba6 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -900,7 +900,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
* HEARTBEAT is sent (see Section 8.3).
*/
- if (transport->hb_allowed) {
+ if (transport->param_flags & SPP_HB_ENABLE) {
if (SCTP_DISPOSITION_NOMEM ==
sctp_sf_heartbeat(ep, asoc, type, arg,
commands))
@@ -1036,14 +1036,14 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
if (from_addr.sa.sa_family == AF_INET6) {
printk(KERN_WARNING
"%s association %p could not find address "
- "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ NIP6_FMT "\n",
__FUNCTION__,
asoc,
NIP6(from_addr.v6.sin6_addr));
} else {
printk(KERN_WARNING
"%s association %p could not find address "
- "%u.%u.%u.%u\n",
+ NIPQUAD_FMT "\n",
__FUNCTION__,
asoc,
NIPQUAD(from_addr.v4.sin_addr.s_addr));
@@ -1051,7 +1051,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
return SCTP_DISPOSITION_DISCARD;
}
- max_interval = link->hb_interval + link->rto;
+ max_interval = link->hbinterval + link->rto;
/* Check if the timestamp looks valid. */
if (time_after(hbinfo->sent_at, jiffies) ||
@@ -2691,14 +2691,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
* document allow. However, an SCTP transmitter MUST NOT be
* more aggressive than the following algorithms allow.
*/
- if (chunk->end_of_packet) {
+ if (chunk->end_of_packet)
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
- /* Start the SACK timer. */
- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
- SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
- }
-
return SCTP_DISPOSITION_CONSUME;
discard_force:
@@ -2721,13 +2716,9 @@ discard_force:
return SCTP_DISPOSITION_DISCARD;
discard_noforce:
- if (chunk->end_of_packet) {
+ if (chunk->end_of_packet)
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
- /* Start the SACK timer. */
- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
- SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
- }
return SCTP_DISPOSITION_DISCARD;
consume:
return SCTP_DISPOSITION_CONSUME;
@@ -3442,9 +3433,6 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
* send another.
*/
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
- /* Start the SACK timer. */
- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
- SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
return SCTP_DISPOSITION_CONSUME;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9df888e932c5..c98ee375ba5e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -63,6 +63,7 @@
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/ip.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
@@ -860,7 +861,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
return -EFAULT;
/* Alloc space for the address array in kernel memory. */
- kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+ kaddrs = kmalloc(addrs_size, GFP_KERNEL);
if (unlikely(!kaddrs))
return -ENOMEM;
@@ -1150,7 +1151,7 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
return -EFAULT;
/* Alloc space for the address array in kernel memory. */
- kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+ kaddrs = kmalloc(addrs_size, GFP_KERNEL);
if (unlikely(!kaddrs))
return -ENOMEM;
@@ -1941,107 +1942,379 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
* address's parameters:
*
* struct sctp_paddrparams {
- * sctp_assoc_t spp_assoc_id;
- * struct sockaddr_storage spp_address;
- * uint32_t spp_hbinterval;
- * uint16_t spp_pathmaxrxt;
- * };
- *
- * spp_assoc_id - (UDP style socket) This is filled in the application,
- * and identifies the association for this query.
+ * sctp_assoc_t spp_assoc_id;
+ * struct sockaddr_storage spp_address;
+ * uint32_t spp_hbinterval;
+ * uint16_t spp_pathmaxrxt;
+ * uint32_t spp_pathmtu;
+ * uint32_t spp_sackdelay;
+ * uint32_t spp_flags;
+ * };
+ *
+ * spp_assoc_id - (one-to-many style socket) This is filled in the
+ * application, and identifies the association for
+ * this query.
* spp_address - This specifies which address is of interest.
* spp_hbinterval - This contains the value of the heartbeat interval,
- * in milliseconds. A value of 0, when modifying the
- * parameter, specifies that the heartbeat on this
- * address should be disabled. A value of UINT32_MAX
- * (4294967295), when modifying the parameter,
- * specifies that a heartbeat should be sent
- * immediately to the peer address, and the current
- * interval should remain unchanged.
+ * in milliseconds. If a value of zero
+ * is present in this field then no changes are to
+ * be made to this parameter.
* spp_pathmaxrxt - This contains the maximum number of
* retransmissions before this address shall be
- * considered unreachable.
+ * considered unreachable. If a value of zero
+ * is present in this field then no changes are to
+ * be made to this parameter.
+ * spp_pathmtu - When Path MTU discovery is disabled the value
+ * specified here will be the "fixed" path mtu.
+ * Note that if the spp_address field is empty
+ * then all associations on this address will
+ * have this fixed path mtu set upon them.
+ *
+ * spp_sackdelay - When delayed sack is enabled, this value specifies
+ * the number of milliseconds that sacks will be delayed
+ * for. This value will apply to all addresses of an
+ * association if the spp_address field is empty. Note
+ * also, that if delayed sack is enabled and this
+ * value is set to 0, no change is made to the last
+ * recorded delayed sack timer value.
+ *
+ * spp_flags - These flags are used to control various features
+ * on an association. The flag field may contain
+ * zero or more of the following options.
+ *
+ * SPP_HB_ENABLE - Enable heartbeats on the
+ * specified address. Note that if the address
+ * field is empty all addresses for the association
+ * have heartbeats enabled upon them.
+ *
+ * SPP_HB_DISABLE - Disable heartbeats on the
+ * speicifed address. Note that if the address
+ * field is empty all addresses for the association
+ * will have their heartbeats disabled. Note also
+ * that SPP_HB_ENABLE and SPP_HB_DISABLE are
+ * mutually exclusive, only one of these two should
+ * be specified. Enabling both fields will have
+ * undetermined results.
+ *
+ * SPP_HB_DEMAND - Request a user initiated heartbeat
+ * to be made immediately.
+ *
+ * SPP_PMTUD_ENABLE - This field will enable PMTU
+ * discovery upon the specified address. Note that
+ * if the address feild is empty then all addresses
+ * on the association are effected.
+ *
+ * SPP_PMTUD_DISABLE - This field will disable PMTU
+ * discovery upon the specified address. Note that
+ * if the address feild is empty then all addresses
+ * on the association are effected. Not also that
+ * SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually
+ * exclusive. Enabling both will have undetermined
+ * results.
+ *
+ * SPP_SACKDELAY_ENABLE - Setting this flag turns
+ * on delayed sack. The time specified in spp_sackdelay
+ * is used to specify the sack delay for this address. Note
+ * that if spp_address is empty then all addresses will
+ * enable delayed sack and take on the sack delay
+ * value specified in spp_sackdelay.
+ * SPP_SACKDELAY_DISABLE - Setting this flag turns
+ * off delayed sack. If the spp_address field is blank then
+ * delayed sack is disabled for the entire association. Note
+ * also that this field is mutually exclusive to
+ * SPP_SACKDELAY_ENABLE, setting both will have undefined
+ * results.
*/
+int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
+ struct sctp_transport *trans,
+ struct sctp_association *asoc,
+ struct sctp_sock *sp,
+ int hb_change,
+ int pmtud_change,
+ int sackdelay_change)
+{
+ int error;
+
+ if (params->spp_flags & SPP_HB_DEMAND && trans) {
+ error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
+ if (error)
+ return error;
+ }
+
+ if (params->spp_hbinterval) {
+ if (trans) {
+ trans->hbinterval = msecs_to_jiffies(params->spp_hbinterval);
+ } else if (asoc) {
+ asoc->hbinterval = msecs_to_jiffies(params->spp_hbinterval);
+ } else {
+ sp->hbinterval = params->spp_hbinterval;
+ }
+ }
+
+ if (hb_change) {
+ if (trans) {
+ trans->param_flags =
+ (trans->param_flags & ~SPP_HB) | hb_change;
+ } else if (asoc) {
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_HB) | hb_change;
+ } else {
+ sp->param_flags =
+ (sp->param_flags & ~SPP_HB) | hb_change;
+ }
+ }
+
+ if (params->spp_pathmtu) {
+ if (trans) {
+ trans->pathmtu = params->spp_pathmtu;
+ sctp_assoc_sync_pmtu(asoc);
+ } else if (asoc) {
+ asoc->pathmtu = params->spp_pathmtu;
+ sctp_frag_point(sp, params->spp_pathmtu);
+ } else {
+ sp->pathmtu = params->spp_pathmtu;
+ }
+ }
+
+ if (pmtud_change) {
+ if (trans) {
+ int update = (trans->param_flags & SPP_PMTUD_DISABLE) &&
+ (params->spp_flags & SPP_PMTUD_ENABLE);
+ trans->param_flags =
+ (trans->param_flags & ~SPP_PMTUD) | pmtud_change;
+ if (update) {
+ sctp_transport_pmtu(trans);
+ sctp_assoc_sync_pmtu(asoc);
+ }
+ } else if (asoc) {
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_PMTUD) | pmtud_change;
+ } else {
+ sp->param_flags =
+ (sp->param_flags & ~SPP_PMTUD) | pmtud_change;
+ }
+ }
+
+ if (params->spp_sackdelay) {
+ if (trans) {
+ trans->sackdelay =
+ msecs_to_jiffies(params->spp_sackdelay);
+ } else if (asoc) {
+ asoc->sackdelay =
+ msecs_to_jiffies(params->spp_sackdelay);
+ } else {
+ sp->sackdelay = params->spp_sackdelay;
+ }
+ }
+
+ if (sackdelay_change) {
+ if (trans) {
+ trans->param_flags =
+ (trans->param_flags & ~SPP_SACKDELAY) |
+ sackdelay_change;
+ } else if (asoc) {
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_SACKDELAY) |
+ sackdelay_change;
+ } else {
+ sp->param_flags =
+ (sp->param_flags & ~SPP_SACKDELAY) |
+ sackdelay_change;
+ }
+ }
+
+ if (params->spp_pathmaxrxt) {
+ if (trans) {
+ trans->pathmaxrxt = params->spp_pathmaxrxt;
+ } else if (asoc) {
+ asoc->pathmaxrxt = params->spp_pathmaxrxt;
+ } else {
+ sp->pathmaxrxt = params->spp_pathmaxrxt;
+ }
+ }
+
+ return 0;
+}
+
static int sctp_setsockopt_peer_addr_params(struct sock *sk,
char __user *optval, int optlen)
{
- struct sctp_paddrparams params;
- struct sctp_transport *trans;
+ struct sctp_paddrparams params;
+ struct sctp_transport *trans = NULL;
+ struct sctp_association *asoc = NULL;
+ struct sctp_sock *sp = sctp_sk(sk);
int error;
+ int hb_change, pmtud_change, sackdelay_change;
if (optlen != sizeof(struct sctp_paddrparams))
- return -EINVAL;
+ return - EINVAL;
+
if (copy_from_user(&params, optval, optlen))
return -EFAULT;
- /*
- * API 7. Socket Options (setting the default value for the endpoint)
- * All options that support specific settings on an association by
- * filling in either an association id variable or a sockaddr_storage
- * SHOULD also support setting of the same value for the entire endpoint
- * (i.e. future associations). To accomplish this the following logic is
- * used when setting one of these options:
-
- * c) If neither the sockaddr_storage or association identification is
- * set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and
- * the association identification is 0, the settings are a default
- * and to be applied to the endpoint (all future associations).
- */
+ /* Validate flags and value parameters. */
+ hb_change = params.spp_flags & SPP_HB;
+ pmtud_change = params.spp_flags & SPP_PMTUD;
+ sackdelay_change = params.spp_flags & SPP_SACKDELAY;
+
+ if (hb_change == SPP_HB ||
+ pmtud_change == SPP_PMTUD ||
+ sackdelay_change == SPP_SACKDELAY ||
+ params.spp_sackdelay > 500 ||
+ (params.spp_pathmtu
+ && params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT))
+ return -EINVAL;
- /* update default value for endpoint (all future associations) */
- if (!params.spp_assoc_id &&
- sctp_is_any(( union sctp_addr *)&params.spp_address)) {
- /* Manual heartbeat on an endpoint is invalid. */
- if (0xffffffff == params.spp_hbinterval)
+ /* If an address other than INADDR_ANY is specified, and
+ * no transport is found, then the request is invalid.
+ */
+ if (!sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+ trans = sctp_addr_id2transport(sk, &params.spp_address,
+ params.spp_assoc_id);
+ if (!trans)
return -EINVAL;
- else if (params.spp_hbinterval)
- sctp_sk(sk)->paddrparam.spp_hbinterval =
- params.spp_hbinterval;
- if (params.spp_pathmaxrxt)
- sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
- params.spp_pathmaxrxt;
- return 0;
}
- trans = sctp_addr_id2transport(sk, &params.spp_address,
- params.spp_assoc_id);
- if (!trans)
+ /* Get association, if assoc_id != 0 and the socket is a one
+ * to many style socket, and an association was not found, then
+ * the id was invalid.
+ */
+ asoc = sctp_id2assoc(sk, params.spp_assoc_id);
+ if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP))
return -EINVAL;
- /* Applications can enable or disable heartbeats for any peer address
- * of an association, modify an address's heartbeat interval, force a
- * heartbeat to be sent immediately, and adjust the address's maximum
- * number of retransmissions sent before an address is considered
- * unreachable.
- *
- * The value of the heartbeat interval, in milliseconds. A value of
- * UINT32_MAX (4294967295), when modifying the parameter, specifies
- * that a heartbeat should be sent immediately to the peer address,
- * and the current interval should remain unchanged.
+ /* Heartbeat demand can only be sent on a transport or
+ * association, but not a socket.
*/
- if (0xffffffff == params.spp_hbinterval) {
- error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
- if (error)
- return error;
- } else {
- /* The value of the heartbeat interval, in milliseconds. A value of 0,
- * when modifying the parameter, specifies that the heartbeat on this
- * address should be disabled.
+ if (params.spp_flags & SPP_HB_DEMAND && !trans && !asoc)
+ return -EINVAL;
+
+ /* Process parameters. */
+ error = sctp_apply_peer_addr_params(&params, trans, asoc, sp,
+ hb_change, pmtud_change,
+ sackdelay_change);
+
+ if (error)
+ return error;
+
+ /* If changes are for association, also apply parameters to each
+ * transport.
*/
- if (params.spp_hbinterval) {
- trans->hb_allowed = 1;
- trans->hb_interval =
- msecs_to_jiffies(params.spp_hbinterval);
- } else
- trans->hb_allowed = 0;
+ if (!trans && asoc) {
+ struct list_head *pos;
+
+ list_for_each(pos, &asoc->peer.transport_addr_list) {
+ trans = list_entry(pos, struct sctp_transport,
+ transports);
+ sctp_apply_peer_addr_params(&params, trans, asoc, sp,
+ hb_change, pmtud_change,
+ sackdelay_change);
+ }
}
- /* spp_pathmaxrxt contains the maximum number of retransmissions
- * before this address shall be considered unreachable.
- */
- if (params.spp_pathmaxrxt)
- trans->max_retrans = params.spp_pathmaxrxt;
+ return 0;
+}
+
+/* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
+ *
+ * This options will get or set the delayed ack timer. The time is set
+ * in milliseconds. If the assoc_id is 0, then this sets or gets the
+ * endpoints default delayed ack timer value. If the assoc_id field is
+ * non-zero, then the set or get effects the specified association.
+ *
+ * struct sctp_assoc_value {
+ * sctp_assoc_t assoc_id;
+ * uint32_t assoc_value;
+ * };
+ *
+ * assoc_id - This parameter, indicates which association the
+ * user is preforming an action upon. Note that if
+ * this field's value is zero then the endpoints
+ * default value is changed (effecting future
+ * associations only).
+ *
+ * assoc_value - This parameter contains the number of milliseconds
+ * that the user is requesting the delayed ACK timer
+ * be set to. Note that this value is defined in
+ * the standard to be between 200 and 500 milliseconds.
+ *
+ * Note: a value of zero will leave the value alone,
+ * but disable SACK delay. A non-zero value will also
+ * enable SACK delay.
+ */
+static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
+ char __user *optval, int optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_transport *trans = NULL;
+ struct sctp_association *asoc = NULL;
+ struct sctp_sock *sp = sctp_sk(sk);
+
+ if (optlen != sizeof(struct sctp_assoc_value))
+ return - EINVAL;
+
+ if (copy_from_user(&params, optval, optlen))
+ return -EFAULT;
+
+ /* Validate value parameter. */
+ if (params.assoc_value > 500)
+ return -EINVAL;
+
+ /* Get association, if assoc_id != 0 and the socket is a one
+ * to many style socket, and an association was not found, then
+ * the id was invalid.
+ */
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id && sctp_style(sk, UDP))
+ return -EINVAL;
+
+ if (params.assoc_value) {
+ if (asoc) {
+ asoc->sackdelay =
+ msecs_to_jiffies(params.assoc_value);
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
+ } else {
+ sp->sackdelay = params.assoc_value;
+ sp->param_flags =
+ (sp->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
+ }
+ } else {
+ if (asoc) {
+ asoc->param_flags =
+ (asoc->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_DISABLE;
+ } else {
+ sp->param_flags =
+ (sp->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_DISABLE;
+ }
+ }
+
+ /* If change is for association, also apply to each transport. */
+ if (asoc) {
+ struct list_head *pos;
+
+ list_for_each(pos, &asoc->peer.transport_addr_list) {
+ trans = list_entry(pos, struct sctp_transport,
+ transports);
+ if (params.assoc_value) {
+ trans->sackdelay =
+ msecs_to_jiffies(params.assoc_value);
+ trans->param_flags =
+ (trans->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_ENABLE;
+ } else {
+ trans->param_flags =
+ (trans->param_flags & ~SPP_SACKDELAY) |
+ SPP_SACKDELAY_DISABLE;
+ }
+ }
+ }
+
return 0;
}
@@ -2334,7 +2607,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
/* Update the frag_point of the existing associations. */
list_for_each(pos, &(sp->ep->asocs)) {
asoc = list_entry(pos, struct sctp_association, asocs);
- asoc->frag_point = sctp_frag_point(sp, asoc->pmtu);
+ asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
}
return 0;
@@ -2491,6 +2764,10 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
break;
+ case SCTP_DELAYED_ACK_TIME:
+ retval = sctp_setsockopt_delayed_ack_time(sk, optval, optlen);
+ break;
+
case SCTP_INITMSG:
retval = sctp_setsockopt_initmsg(sk, optval, optlen);
break;
@@ -2715,8 +2992,13 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* Default Peer Address Parameters. These defaults can
* be modified via SCTP_PEER_ADDR_PARAMS
*/
- sp->paddrparam.spp_hbinterval = jiffies_to_msecs(sctp_hb_interval);
- sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
+ sp->hbinterval = jiffies_to_msecs(sctp_hb_interval);
+ sp->pathmaxrxt = sctp_max_retrans_path;
+ sp->pathmtu = 0; // allow default discovery
+ sp->sackdelay = sctp_sack_timeout;
+ sp->param_flags = SPP_HB_ENABLE |
+ SPP_PMTUD_ENABLE |
+ SPP_SACKDELAY_ENABLE;
/* If enabled no SCTP message fragmentation will be performed.
* Configure through SCTP_DISABLE_FRAGMENTS socket option.
@@ -2865,7 +3147,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
status.sstat_primary.spinfo_cwnd = transport->cwnd;
status.sstat_primary.spinfo_srtt = transport->srtt;
status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
- status.sstat_primary.spinfo_mtu = transport->pmtu;
+ status.sstat_primary.spinfo_mtu = transport->pathmtu;
if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
status.sstat_primary.spinfo_state = SCTP_ACTIVE;
@@ -2924,7 +3206,7 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
pinfo.spinfo_cwnd = transport->cwnd;
pinfo.spinfo_srtt = transport->srtt;
pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
- pinfo.spinfo_mtu = transport->pmtu;
+ pinfo.spinfo_mtu = transport->pathmtu;
if (pinfo.spinfo_state == SCTP_UNKNOWN)
pinfo.spinfo_state = SCTP_ACTIVE;
@@ -3086,69 +3368,227 @@ out:
* address's parameters:
*
* struct sctp_paddrparams {
- * sctp_assoc_t spp_assoc_id;
- * struct sockaddr_storage spp_address;
- * uint32_t spp_hbinterval;
- * uint16_t spp_pathmaxrxt;
- * };
- *
- * spp_assoc_id - (UDP style socket) This is filled in the application,
- * and identifies the association for this query.
+ * sctp_assoc_t spp_assoc_id;
+ * struct sockaddr_storage spp_address;
+ * uint32_t spp_hbinterval;
+ * uint16_t spp_pathmaxrxt;
+ * uint32_t spp_pathmtu;
+ * uint32_t spp_sackdelay;
+ * uint32_t spp_flags;
+ * };
+ *
+ * spp_assoc_id - (one-to-many style socket) This is filled in the
+ * application, and identifies the association for
+ * this query.
* spp_address - This specifies which address is of interest.
* spp_hbinterval - This contains the value of the heartbeat interval,
- * in milliseconds. A value of 0, when modifying the
- * parameter, specifies that the heartbeat on this
- * address should be disabled. A value of UINT32_MAX
- * (4294967295), when modifying the parameter,
- * specifies that a heartbeat should be sent
- * immediately to the peer address, and the current
- * interval should remain unchanged.
+ * in milliseconds. If a value of zero
+ * is present in this field then no changes are to
+ * be made to this parameter.
* spp_pathmaxrxt - This contains the maximum number of
* retransmissions before this address shall be
- * considered unreachable.
+ * considered unreachable. If a value of zero
+ * is present in this field then no changes are to
+ * be made to this parameter.
+ * spp_pathmtu - When Path MTU discovery is disabled the value
+ * specified here will be the "fixed" path mtu.
+ * Note that if the spp_address field is empty
+ * then all associations on this address will
+ * have this fixed path mtu set upon them.
+ *
+ * spp_sackdelay - When delayed sack is enabled, this value specifies
+ * the number of milliseconds that sacks will be delayed
+ * for. This value will apply to all addresses of an
+ * association if the spp_address field is empty. Note
+ * also, that if delayed sack is enabled and this
+ * value is set to 0, no change is made to the last
+ * recorded delayed sack timer value.
+ *
+ * spp_flags - These flags are used to control various features
+ * on an association. The flag field may contain
+ * zero or more of the following options.
+ *
+ * SPP_HB_ENABLE - Enable heartbeats on the
+ * specified address. Note that if the address
+ * field is empty all addresses for the association
+ * have heartbeats enabled upon them.
+ *
+ * SPP_HB_DISABLE - Disable heartbeats on the
+ * speicifed address. Note that if the address
+ * field is empty all addresses for the association
+ * will have their heartbeats disabled. Note also
+ * that SPP_HB_ENABLE and SPP_HB_DISABLE are
+ * mutually exclusive, only one of these two should
+ * be specified. Enabling both fields will have
+ * undetermined results.
+ *
+ * SPP_HB_DEMAND - Request a user initiated heartbeat
+ * to be made immediately.
+ *
+ * SPP_PMTUD_ENABLE - This field will enable PMTU
+ * discovery upon the specified address. Note that
+ * if the address feild is empty then all addresses
+ * on the association are effected.
+ *
+ * SPP_PMTUD_DISABLE - This field will disable PMTU
+ * discovery upon the specified address. Note that
+ * if the address feild is empty then all addresses
+ * on the association are effected. Not also that
+ * SPP_PMTUD_ENABLE and SPP_PMTUD_DISABLE are mutually
+ * exclusive. Enabling both will have undetermined
+ * results.
+ *
+ * SPP_SACKDELAY_ENABLE - Setting this flag turns
+ * on delayed sack. The time specified in spp_sackdelay
+ * is used to specify the sack delay for this address. Note
+ * that if spp_address is empty then all addresses will
+ * enable delayed sack and take on the sack delay
+ * value specified in spp_sackdelay.
+ * SPP_SACKDELAY_DISABLE - Setting this flag turns
+ * off delayed sack. If the spp_address field is blank then
+ * delayed sack is disabled for the entire association. Note
+ * also that this field is mutually exclusive to
+ * SPP_SACKDELAY_ENABLE, setting both will have undefined
+ * results.
*/
static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
- char __user *optval, int __user *optlen)
+ char __user *optval, int __user *optlen)
{
- struct sctp_paddrparams params;
- struct sctp_transport *trans;
+ struct sctp_paddrparams params;
+ struct sctp_transport *trans = NULL;
+ struct sctp_association *asoc = NULL;
+ struct sctp_sock *sp = sctp_sk(sk);
if (len != sizeof(struct sctp_paddrparams))
return -EINVAL;
+
if (copy_from_user(&params, optval, len))
return -EFAULT;
- /* If no association id is specified retrieve the default value
- * for the endpoint that will be used for all future associations
+ /* If an address other than INADDR_ANY is specified, and
+ * no transport is found, then the request is invalid.
*/
- if (!params.spp_assoc_id &&
- sctp_is_any(( union sctp_addr *)&params.spp_address)) {
- params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval;
- params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt;
-
- goto done;
+ if (!sctp_is_any(( union sctp_addr *)&params.spp_address)) {
+ trans = sctp_addr_id2transport(sk, &params.spp_address,
+ params.spp_assoc_id);
+ if (!trans) {
+ SCTP_DEBUG_PRINTK("Failed no transport\n");
+ return -EINVAL;
+ }
}
- trans = sctp_addr_id2transport(sk, &params.spp_address,
- params.spp_assoc_id);
- if (!trans)
+ /* Get association, if assoc_id != 0 and the socket is a one
+ * to many style socket, and an association was not found, then
+ * the id was invalid.
+ */
+ asoc = sctp_id2assoc(sk, params.spp_assoc_id);
+ if (!asoc && params.spp_assoc_id && sctp_style(sk, UDP)) {
+ SCTP_DEBUG_PRINTK("Failed no association\n");
return -EINVAL;
+ }
- /* The value of the heartbeat interval, in milliseconds. A value of 0,
- * when modifying the parameter, specifies that the heartbeat on this
- * address should be disabled.
- */
- if (!trans->hb_allowed)
- params.spp_hbinterval = 0;
- else
- params.spp_hbinterval = jiffies_to_msecs(trans->hb_interval);
+ if (trans) {
+ /* Fetch transport values. */
+ params.spp_hbinterval = jiffies_to_msecs(trans->hbinterval);
+ params.spp_pathmtu = trans->pathmtu;
+ params.spp_pathmaxrxt = trans->pathmaxrxt;
+ params.spp_sackdelay = jiffies_to_msecs(trans->sackdelay);
+
+ /*draft-11 doesn't say what to return in spp_flags*/
+ params.spp_flags = trans->param_flags;
+ } else if (asoc) {
+ /* Fetch association values. */
+ params.spp_hbinterval = jiffies_to_msecs(asoc->hbinterval);
+ params.spp_pathmtu = asoc->pathmtu;
+ params.spp_pathmaxrxt = asoc->pathmaxrxt;
+ params.spp_sackdelay = jiffies_to_msecs(asoc->sackdelay);
+
+ /*draft-11 doesn't say what to return in spp_flags*/
+ params.spp_flags = asoc->param_flags;
+ } else {
+ /* Fetch socket values. */
+ params.spp_hbinterval = sp->hbinterval;
+ params.spp_pathmtu = sp->pathmtu;
+ params.spp_sackdelay = sp->sackdelay;
+ params.spp_pathmaxrxt = sp->pathmaxrxt;
+
+ /*draft-11 doesn't say what to return in spp_flags*/
+ params.spp_flags = sp->param_flags;
+ }
- /* spp_pathmaxrxt contains the maximum number of retransmissions
- * before this address shall be considered unreachable.
- */
- params.spp_pathmaxrxt = trans->max_retrans;
+ if (copy_to_user(optval, &params, len))
+ return -EFAULT;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+
+ return 0;
+}
+
+/* 7.1.24. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
+ *
+ * This options will get or set the delayed ack timer. The time is set
+ * in milliseconds. If the assoc_id is 0, then this sets or gets the
+ * endpoints default delayed ack timer value. If the assoc_id field is
+ * non-zero, then the set or get effects the specified association.
+ *
+ * struct sctp_assoc_value {
+ * sctp_assoc_t assoc_id;
+ * uint32_t assoc_value;
+ * };
+ *
+ * assoc_id - This parameter, indicates which association the
+ * user is preforming an action upon. Note that if
+ * this field's value is zero then the endpoints
+ * default value is changed (effecting future
+ * associations only).
+ *
+ * assoc_value - This parameter contains the number of milliseconds
+ * that the user is requesting the delayed ACK timer
+ * be set to. Note that this value is defined in
+ * the standard to be between 200 and 500 milliseconds.
+ *
+ * Note: a value of zero will leave the value alone,
+ * but disable SACK delay. A non-zero value will also
+ * enable SACK delay.
+ */
+static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
+ char __user *optval,
+ int __user *optlen)
+{
+ struct sctp_assoc_value params;
+ struct sctp_association *asoc = NULL;
+ struct sctp_sock *sp = sctp_sk(sk);
+
+ if (len != sizeof(struct sctp_assoc_value))
+ return - EINVAL;
+
+ if (copy_from_user(&params, optval, len))
+ return -EFAULT;
+
+ /* Get association, if assoc_id != 0 and the socket is a one
+ * to many style socket, and an association was not found, then
+ * the id was invalid.
+ */
+ asoc = sctp_id2assoc(sk, params.assoc_id);
+ if (!asoc && params.assoc_id && sctp_style(sk, UDP))
+ return -EINVAL;
+
+ if (asoc) {
+ /* Fetch association values. */
+ if (asoc->param_flags & SPP_SACKDELAY_ENABLE)
+ params.assoc_value = jiffies_to_msecs(
+ asoc->sackdelay);
+ else
+ params.assoc_value = 0;
+ } else {
+ /* Fetch socket values. */
+ if (sp->param_flags & SPP_SACKDELAY_ENABLE)
+ params.assoc_value = sp->sackdelay;
+ else
+ params.assoc_value = 0;
+ }
-done:
if (copy_to_user(optval, &params, len))
return -EFAULT;
@@ -4015,6 +4455,10 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
optlen);
break;
+ case SCTP_DELAYED_ACK_TIME:
+ retval = sctp_getsockopt_delayed_ack_time(sk, len, optval,
+ optlen);
+ break;
case SCTP_INITMSG:
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
break;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 268ddaf2dc0f..68d73e2dd155 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -86,10 +86,13 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->init_sent_count = 0;
peer->state = SCTP_ACTIVE;
- peer->hb_allowed = 0;
+ peer->param_flags = SPP_HB_DISABLE |
+ SPP_PMTUD_ENABLE |
+ SPP_SACKDELAY_ENABLE;
+ peer->hbinterval = 0;
/* Initialize the default path max_retrans. */
- peer->max_retrans = sctp_max_retrans_path;
+ peer->pathmaxrxt = sctp_max_retrans_path;
peer->error_count = 0;
INIT_LIST_HEAD(&peer->transmitted);
@@ -229,10 +232,10 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL);
if (dst) {
- transport->pmtu = dst_mtu(dst);
+ transport->pathmtu = dst_mtu(dst);
dst_release(dst);
} else
- transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
+ transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
/* Caches the dst entry and source address for a transport's destination
@@ -254,8 +257,11 @@ void sctp_transport_route(struct sctp_transport *transport,
af->get_saddr(asoc, dst, daddr, &transport->saddr);
transport->dst = dst;
+ if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) {
+ return;
+ }
if (dst) {
- transport->pmtu = dst_mtu(dst);
+ transport->pathmtu = dst_mtu(dst);
/* Initialize sk->sk_rcv_saddr, if the transport is the
* association's active path for getsockname().
@@ -264,7 +270,7 @@ void sctp_transport_route(struct sctp_transport *transport,
opt->pf->af->to_sk_saddr(&transport->saddr,
asoc->base.sk);
} else
- transport->pmtu = SCTP_DEFAULT_MAXSEGMENT;
+ transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
/* Hold a reference to a transport. */
@@ -369,7 +375,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *transport,
ssthresh = transport->ssthresh;
pba = transport->partial_bytes_acked;
- pmtu = transport->asoc->pmtu;
+ pmtu = transport->asoc->pathmtu;
if (cwnd <= ssthresh) {
/* RFC 2960 7.2.1, sctpimpguide-05 2.14.2 When cwnd is less
@@ -441,8 +447,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
* partial_bytes_acked = 0
*/
transport->ssthresh = max(transport->cwnd/2,
- 4*transport->asoc->pmtu);
- transport->cwnd = transport->asoc->pmtu;
+ 4*transport->asoc->pathmtu);
+ transport->cwnd = transport->asoc->pathmtu;
break;
case SCTP_LOWER_CWND_FAST_RTX:
@@ -459,7 +465,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
* partial_bytes_acked = 0
*/
transport->ssthresh = max(transport->cwnd/2,
- 4*transport->asoc->pmtu);
+ 4*transport->asoc->pathmtu);
transport->cwnd = transport->ssthresh;
break;
@@ -479,7 +485,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
if ((jiffies - transport->last_time_ecne_reduced) >
transport->rtt) {
transport->ssthresh = max(transport->cwnd/2,
- 4*transport->asoc->pmtu);
+ 4*transport->asoc->pathmtu);
transport->cwnd = transport->ssthresh;
transport->last_time_ecne_reduced = jiffies;
}
@@ -496,7 +502,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
*/
if ((jiffies - transport->last_time_used) > transport->rto)
transport->cwnd = max(transport->cwnd/2,
- 4*transport->asoc->pmtu);
+ 4*transport->asoc->pathmtu);
break;
};
@@ -511,7 +517,7 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
unsigned long sctp_transport_timeout(struct sctp_transport *t)
{
unsigned long timeout;
- timeout = t->hb_interval + t->rto + sctp_jitter(t->rto);
+ timeout = t->hbinterval + t->rto + sctp_jitter(t->rto);
timeout += jiffies;
return timeout;
}
diff --git a/net/socket.c b/net/socket.c
index 3145103cdf54..b38a263853c3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -640,154 +640,150 @@ static void sock_aio_dtor(struct kiocb *iocb)
kfree(iocb->private);
}
-/*
- * Read data from a socket. ubuf is a user mode pointer. We make sure the user
- * area ubuf...ubuf+size-1 is writable before asking the protocol.
- */
-
-static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
- size_t size, loff_t pos)
+static ssize_t sock_sendpage(struct file *file, struct page *page,
+ int offset, size_t size, loff_t *ppos, int more)
{
- struct sock_iocb *x, siocb;
struct socket *sock;
int flags;
- if (pos != 0)
- return -ESPIPE;
- if (size==0) /* Match SYS5 behaviour */
- return 0;
+ sock = file->private_data;
- if (is_sync_kiocb(iocb))
- x = &siocb;
- else {
- x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL);
- if (!x)
- return -ENOMEM;
+ flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
+ if (more)
+ flags |= MSG_MORE;
+
+ return sock->ops->sendpage(sock, page, offset, size, flags);
+}
+
+static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
+ char __user *ubuf, size_t size, struct sock_iocb *siocb)
+{
+ if (!is_sync_kiocb(iocb)) {
+ siocb = kmalloc(sizeof(*siocb), GFP_KERNEL);
+ if (!siocb)
+ return NULL;
iocb->ki_dtor = sock_aio_dtor;
}
- iocb->private = x;
- x->kiocb = iocb;
- sock = iocb->ki_filp->private_data;
- x->async_msg.msg_name = NULL;
- x->async_msg.msg_namelen = 0;
- x->async_msg.msg_iov = &x->async_iov;
- x->async_msg.msg_iovlen = 1;
- x->async_msg.msg_control = NULL;
- x->async_msg.msg_controllen = 0;
- x->async_iov.iov_base = ubuf;
- x->async_iov.iov_len = size;
- flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
+ siocb->kiocb = iocb;
+ siocb->async_iov.iov_base = ubuf;
+ siocb->async_iov.iov_len = size;
- return __sock_recvmsg(iocb, sock, &x->async_msg, size, flags);
+ iocb->private = siocb;
+ return siocb;
}
+static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
+ struct file *file, struct iovec *iov, unsigned long nr_segs)
+{
+ struct socket *sock = file->private_data;
+ size_t size = 0;
+ int i;
-/*
- * Write data to a socket. We verify that the user area ubuf..ubuf+size-1
- * is readable by the user process.
- */
+ for (i = 0 ; i < nr_segs ; i++)
+ size += iov[i].iov_len;
-static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
- size_t size, loff_t pos)
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ msg->msg_control = NULL;
+ msg->msg_controllen = 0;
+ msg->msg_iov = (struct iovec *) iov;
+ msg->msg_iovlen = nr_segs;
+ msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+
+ return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
+}
+
+static ssize_t sock_readv(struct file *file, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
{
- struct sock_iocb *x, siocb;
- struct socket *sock;
-
+ struct kiocb iocb;
+ struct sock_iocb siocb;
+ struct msghdr msg;
+ int ret;
+
+ init_sync_kiocb(&iocb, NULL);
+ iocb.private = &siocb;
+
+ ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ if (-EIOCBQUEUED == ret)
+ ret = wait_on_sync_kiocb(&iocb);
+ return ret;
+}
+
+static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf,
+ size_t count, loff_t pos)
+{
+ struct sock_iocb siocb, *x;
+
if (pos != 0)
return -ESPIPE;
- if(size==0) /* Match SYS5 behaviour */
+ if (count == 0) /* Match SYS5 behaviour */
return 0;
- if (is_sync_kiocb(iocb))
- x = &siocb;
- else {
- x = kmalloc(sizeof(struct sock_iocb), GFP_KERNEL);
- if (!x)
- return -ENOMEM;
- iocb->ki_dtor = sock_aio_dtor;
- }
- iocb->private = x;
- x->kiocb = iocb;
- sock = iocb->ki_filp->private_data;
-
- x->async_msg.msg_name = NULL;
- x->async_msg.msg_namelen = 0;
- x->async_msg.msg_iov = &x->async_iov;
- x->async_msg.msg_iovlen = 1;
- x->async_msg.msg_control = NULL;
- x->async_msg.msg_controllen = 0;
- x->async_msg.msg_flags = !(iocb->ki_filp->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
- if (sock->type == SOCK_SEQPACKET)
- x->async_msg.msg_flags |= MSG_EOR;
- x->async_iov.iov_base = (void __user *)ubuf;
- x->async_iov.iov_len = size;
-
- return __sock_sendmsg(iocb, sock, &x->async_msg, size);
+ x = alloc_sock_iocb(iocb, ubuf, count, &siocb);
+ if (!x)
+ return -ENOMEM;
+ return do_sock_read(&x->async_msg, iocb, iocb->ki_filp,
+ &x->async_iov, 1);
}
-static ssize_t sock_sendpage(struct file *file, struct page *page,
- int offset, size_t size, loff_t *ppos, int more)
+static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
+ struct file *file, struct iovec *iov, unsigned long nr_segs)
{
- struct socket *sock;
- int flags;
+ struct socket *sock = file->private_data;
+ size_t size = 0;
+ int i;
- sock = file->private_data;
+ for (i = 0 ; i < nr_segs ; i++)
+ size += iov[i].iov_len;
- flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
- if (more)
- flags |= MSG_MORE;
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ msg->msg_control = NULL;
+ msg->msg_controllen = 0;
+ msg->msg_iov = (struct iovec *) iov;
+ msg->msg_iovlen = nr_segs;
+ msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+ if (sock->type == SOCK_SEQPACKET)
+ msg->msg_flags |= MSG_EOR;
- return sock->ops->sendpage(sock, page, offset, size, flags);
+ return __sock_sendmsg(iocb, sock, msg, size);
}
-static int sock_readv_writev(int type,
- struct file * file, const struct iovec * iov,
- long count, size_t size)
+static ssize_t sock_writev(struct file *file, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos)
{
struct msghdr msg;
- struct socket *sock;
+ struct kiocb iocb;
+ struct sock_iocb siocb;
+ int ret;
- sock = file->private_data;
+ init_sync_kiocb(&iocb, NULL);
+ iocb.private = &siocb;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
- msg.msg_controllen = 0;
- msg.msg_iov = (struct iovec *) iov;
- msg.msg_iovlen = count;
- msg.msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+ ret = do_sock_write(&msg, &iocb, file, (struct iovec *)iov, nr_segs);
+ if (-EIOCBQUEUED == ret)
+ ret = wait_on_sync_kiocb(&iocb);
+ return ret;
+}
- /* read() does a VERIFY_WRITE */
- if (type == VERIFY_WRITE)
- return sock_recvmsg(sock, &msg, size, msg.msg_flags);
+static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf,
+ size_t count, loff_t pos)
+{
+ struct sock_iocb siocb, *x;
- if (sock->type == SOCK_SEQPACKET)
- msg.msg_flags |= MSG_EOR;
+ if (pos != 0)
+ return -ESPIPE;
+ if (count == 0) /* Match SYS5 behaviour */
+ return 0;
- return sock_sendmsg(sock, &msg, size);
-}
+ x = alloc_sock_iocb(iocb, (void __user *)ubuf, count, &siocb);
+ if (!x)
+ return -ENOMEM;
-static ssize_t sock_readv(struct file *file, const struct iovec *vector,
- unsigned long count, loff_t *ppos)
-{
- size_t tot_len = 0;
- int i;
- for (i = 0 ; i < count ; i++)
- tot_len += vector[i].iov_len;
- return sock_readv_writev(VERIFY_WRITE,
- file, vector, count, tot_len);
-}
-
-static ssize_t sock_writev(struct file *file, const struct iovec *vector,
- unsigned long count, loff_t *ppos)
-{
- size_t tot_len = 0;
- int i;
- for (i = 0 ; i < count ; i++)
- tot_len += vector[i].iov_len;
- return sock_readv_writev(VERIFY_READ,
- file, vector, count, tot_len);
+ return do_sock_write(&x->async_msg, iocb, iocb->ki_filp,
+ &x->async_iov, 1);
}
@@ -904,6 +900,13 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
default:
err = sock->ops->ioctl(sock, cmd, arg);
+
+ /*
+ * If this ioctl is unknown try to hand it down
+ * to the NIC driver.
+ */
+ if (err == -ENOIOCTLCMD)
+ err = dev_ioctl(cmd, argp);
break;
}
return err;
@@ -990,7 +993,7 @@ static int sock_fasync(int fd, struct file *filp, int on)
if (on)
{
- fna=(struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
+ fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
if(fna==NULL)
return -ENOMEM;
}
@@ -2036,7 +2039,7 @@ int sock_unregister(int family)
return 0;
}
-void __init sock_init(void)
+static int __init sock_init(void)
{
/*
* Initialize sock SLAB cache.
@@ -2044,12 +2047,10 @@ void __init sock_init(void)
sk_init();
-#ifdef SLAB_SKB
/*
* Initialize skbuff SLAB cache
*/
skb_init();
-#endif
/*
* Initialize the protocols module.
@@ -2058,15 +2059,19 @@ void __init sock_init(void)
init_inodecache();
register_filesystem(&sock_fs_type);
sock_mnt = kern_mount(&sock_fs_type);
- /* The real protocol initialization is performed when
- * do_initcalls is run.
+
+ /* The real protocol initialization is performed in later initcalls.
*/
#ifdef CONFIG_NETFILTER
netfilter_init();
#endif
+
+ return 0;
}
+core_initcall(sock_init); /* early initcall */
+
#ifdef CONFIG_PROC_FS
void socket_seq_show(struct seq_file *seq)
{
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 8c7756036e95..9ac1b8c26c01 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -94,7 +94,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
struct rpc_cred_cache *new;
int i;
- new = (struct rpc_cred_cache *)kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
if (!new)
return -ENOMEM;
for (i = 0; i < RPC_CREDCACHE_NR; i++)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 5f1f806a0b11..129e2bd36aff 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -97,13 +97,17 @@ get_key(const void *p, const void *end, struct crypto_tfm **res)
alg_mode = CRYPTO_TFM_MODE_CBC;
break;
default:
- dprintk("RPC: get_key: unsupported algorithm %d\n", alg);
+ printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
goto out_err_free_key;
}
- if (!(*res = crypto_alloc_tfm(alg_name, alg_mode)))
+ if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) {
+ printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name);
goto out_err_free_key;
- if (crypto_cipher_setkey(*res, key.data, key.len))
+ }
+ if (crypto_cipher_setkey(*res, key.data, key.len)) {
+ printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name);
goto out_err_free_tfm;
+ }
kfree(key.data);
return p;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 39b3edc14694..58400807d4df 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -111,14 +111,18 @@ get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg)
setkey = 0;
break;
default:
- dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
+ dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg);
goto out_err_free_key;
}
- if (!(*res = crypto_alloc_tfm(alg_name, alg_mode)))
+ if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) {
+ printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name);
goto out_err_free_key;
+ }
if (setkey) {
- if (crypto_cipher_setkey(*res, key.data, key.len))
+ if (crypto_cipher_setkey(*res, key.data, key.len)) {
+ printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name);
goto out_err_free_tfm;
+ }
}
if(key.len > 0)
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
index d1e12b25d6e2..86fbf7c3e39c 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_seal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_seal.c
@@ -59,7 +59,7 @@ spkm3_make_token(struct spkm3_ctx *ctx,
char tokhdrbuf[25];
struct xdr_netobj md5cksum = {.len = 0, .data = NULL};
struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf};
- int tmsglen, tokenlen = 0;
+ int tokenlen = 0;
unsigned char *ptr;
s32 now;
int ctxelen = 0, ctxzbit = 0;
@@ -92,24 +92,23 @@ spkm3_make_token(struct spkm3_ctx *ctx,
}
if (toktype == SPKM_MIC_TOK) {
- tmsglen = 0;
/* Calculate checksum over the mic-header */
asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
ctxelen, ctxzbit);
if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len,
- text, &md5cksum))
+ text, 0, &md5cksum))
goto out_err;
asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
- tokenlen = 10 + ctxelen + 1 + 2 + md5elen + 1;
+ tokenlen = 10 + ctxelen + 1 + md5elen + 1;
/* Create token header using generic routines */
- token->len = g_token_size(&ctx->mech_used, tokenlen + tmsglen);
+ token->len = g_token_size(&ctx->mech_used, tokenlen);
ptr = token->data;
- g_make_token_header(&ctx->mech_used, tokenlen + tmsglen, &ptr);
+ g_make_token_header(&ctx->mech_used, tokenlen, &ptr);
spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
} else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
index 1f824578d773..af0d7ce74686 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_token.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_token.c
@@ -182,6 +182,7 @@ spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ct
* *tokp points to the beginning of the SPKM_MIC token described
* in rfc 2025, section 3.2.1:
*
+ * toklen is the inner token length
*/
void
spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
@@ -189,7 +190,7 @@ spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hd
unsigned char *ict = *tokp;
*(u8 *)ict++ = 0xa4;
- *(u8 *)ict++ = toklen - 2;
+ *(u8 *)ict++ = toklen;
memcpy(ict, mic_hdr->data, mic_hdr->len);
ict += mic_hdr->len;
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
index 241d5b30dfcb..96851b0ba1ba 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_unseal.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
@@ -95,7 +95,7 @@ spkm3_read_token(struct spkm3_ctx *ctx,
ret = GSS_S_DEFECTIVE_TOKEN;
code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2,
mic_hdrlen + 2,
- message_buffer, &md5cksum);
+ message_buffer, 0, &md5cksum);
if (code)
goto out;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index e4ada15ed856..23632d84d8d7 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -420,7 +420,8 @@ static int rsc_parse(struct cache_detail *cd,
gss_mech_put(gm);
goto out;
}
- if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
+ status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
+ if (status) {
gss_mech_put(gm);
goto out;
}
@@ -586,6 +587,20 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
}
static int
+gss_write_null_verf(struct svc_rqst *rqstp)
+{
+ u32 *p;
+
+ svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
+ p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
+ /* don't really need to check if head->iov_len > PAGE_SIZE ... */
+ *p++ = 0;
+ if (!xdr_ressize_check(rqstp, p))
+ return -1;
+ return 0;
+}
+
+static int
gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
{
u32 xdr_seq;
@@ -741,6 +756,21 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
return SVC_OK;
}
+static inline int
+gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
+{
+ struct rsc *rsci;
+
+ if (rsip->major_status != GSS_S_COMPLETE)
+ return gss_write_null_verf(rqstp);
+ rsci = gss_svc_searchbyctx(&rsip->out_handle);
+ if (rsci == NULL) {
+ rsip->major_status = GSS_S_NO_CONTEXT;
+ return gss_write_null_verf(rqstp);
+ }
+ return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+}
+
/*
* Accept an rpcsec packet.
* If context establishment, punt to user space
@@ -876,11 +906,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
case -ENOENT:
goto drop;
case 0:
- rsci = gss_svc_searchbyctx(&rsip->out_handle);
- if (!rsci) {
- goto drop;
- }
- if (gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN))
+ if (gss_write_init_verf(rqstp, rsip))
goto drop;
if (resv->iov_len + 4 > PAGE_SIZE)
goto drop;
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 890fb5ea0dcb..1b3ed4fd1987 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -70,7 +70,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
acred->uid, acred->gid);
- if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL)))
+ if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
return ERR_PTR(-ENOMEM);
atomic_set(&cred->uc_count, 1);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index f509e9992767..dcaa0c4453ff 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -575,12 +575,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
if (rp->q.list.next == &cd->queue) {
spin_unlock(&queue_lock);
up(&queue_io_sem);
- if (rp->offset)
- BUG();
+ BUG_ON(rp->offset);
return 0;
}
rq = container_of(rp->q.list.next, struct cache_request, q.list);
- if (rq->q.reader) BUG();
+ BUG_ON(rq->q.reader);
if (rp->offset == 0)
rq->readers++;
spin_unlock(&queue_lock);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 61c3abeaccae..d2f0550c4ba0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -118,7 +118,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
goto out_err;
err = -ENOMEM;
- clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
+ clnt = kmalloc(sizeof(*clnt), GFP_KERNEL);
if (!clnt)
goto out_err;
memset(clnt, 0, sizeof(*clnt));
@@ -225,7 +225,7 @@ rpc_clone_client(struct rpc_clnt *clnt)
{
struct rpc_clnt *new;
- new = (struct rpc_clnt *)kmalloc(sizeof(*new), GFP_KERNEL);
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
if (!new)
goto out_no_clnt;
memcpy(new, clnt, sizeof(*new));
@@ -268,7 +268,8 @@ rpc_shutdown_client(struct rpc_clnt *clnt)
clnt->cl_oneshot = 0;
clnt->cl_dead = 0;
rpc_killall_tasks(clnt);
- sleep_on_timeout(&destroy_wait, 1*HZ);
+ wait_event_timeout(destroy_wait,
+ !atomic_read(&clnt->cl_users), 1*HZ);
}
if (atomic_read(&clnt->cl_users) < 0) {
@@ -374,19 +375,23 @@ out:
* Default callback for async RPC calls
*/
static void
-rpc_default_callback(struct rpc_task *task)
+rpc_default_callback(struct rpc_task *task, void *data)
{
}
+static const struct rpc_call_ops rpc_default_ops = {
+ .rpc_call_done = rpc_default_callback,
+};
+
/*
* Export the signal mask handling for synchronous code that
* sleeps on RPC calls
*/
-#define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL))
+#define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM))
static void rpc_save_sigmask(sigset_t *oldset, int intr)
{
- unsigned long sigallow = 0;
+ unsigned long sigallow = sigmask(SIGKILL);
sigset_t sigmask;
/* Block all signals except those listed in sigallow */
@@ -432,7 +437,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
BUG_ON(flags & RPC_TASK_ASYNC);
status = -ENOMEM;
- task = rpc_new_task(clnt, NULL, flags);
+ task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
if (task == NULL)
goto out;
@@ -442,14 +447,15 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
rpc_call_setup(task, msg, 0);
/* Set up the call info struct and execute the task */
- if (task->tk_status == 0) {
+ status = task->tk_status;
+ if (status == 0) {
+ atomic_inc(&task->tk_count);
status = rpc_execute(task);
- } else {
- status = task->tk_status;
- rpc_release_task(task);
+ if (status == 0)
+ status = task->tk_status;
}
-
rpc_restore_sigmask(&oldset);
+ rpc_release_task(task);
out:
return status;
}
@@ -459,7 +465,7 @@ out:
*/
int
rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
- rpc_action callback, void *data)
+ const struct rpc_call_ops *tk_ops, void *data)
{
struct rpc_task *task;
sigset_t oldset;
@@ -472,12 +478,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
flags |= RPC_TASK_ASYNC;
/* Create/initialize a new RPC task */
- if (!callback)
- callback = rpc_default_callback;
status = -ENOMEM;
- if (!(task = rpc_new_task(clnt, callback, flags)))
+ if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
goto out;
- task->tk_calldata = data;
/* Mask signals on GSS_AUTH upcalls */
rpc_task_sigmask(task, &oldset);
@@ -511,7 +514,7 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
if (task->tk_status == 0)
task->tk_action = call_start;
else
- task->tk_action = NULL;
+ task->tk_action = rpc_exit_task;
}
void
@@ -536,6 +539,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt)
}
EXPORT_SYMBOL(rpc_max_payload);
+/**
+ * rpc_force_rebind - force transport to check that remote port is unchanged
+ * @clnt: client to rebind
+ *
+ */
+void rpc_force_rebind(struct rpc_clnt *clnt)
+{
+ if (clnt->cl_autobind)
+ clnt->cl_port = 0;
+}
+EXPORT_SYMBOL(rpc_force_rebind);
+
/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
@@ -642,24 +657,26 @@ call_reserveresult(struct rpc_task *task)
/*
* 2. Allocate the buffer. For details, see sched.c:rpc_malloc.
- * (Note: buffer memory is freed in rpc_task_release).
+ * (Note: buffer memory is freed in xprt_release).
*/
static void
call_allocate(struct rpc_task *task)
{
+ struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = task->tk_xprt;
unsigned int bufsiz;
dprintk("RPC: %4d call_allocate (status %d)\n",
task->tk_pid, task->tk_status);
task->tk_action = call_bind;
- if (task->tk_buffer)
+ if (req->rq_buffer)
return;
/* FIXME: compute buffer requirements more exactly using
* auth->au_wslack */
bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE;
- if (rpc_malloc(task, bufsiz << 1) != NULL)
+ if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL)
return;
printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task);
@@ -702,14 +719,14 @@ call_encode(struct rpc_task *task)
task->tk_pid, task->tk_status);
/* Default buffer setup */
- bufsiz = task->tk_bufsize >> 1;
- sndbuf->head[0].iov_base = (void *)task->tk_buffer;
+ bufsiz = req->rq_bufsize >> 1;
+ sndbuf->head[0].iov_base = (void *)req->rq_buffer;
sndbuf->head[0].iov_len = bufsiz;
sndbuf->tail[0].iov_len = 0;
sndbuf->page_len = 0;
sndbuf->len = 0;
sndbuf->buflen = bufsiz;
- rcvbuf->head[0].iov_base = (void *)((char *)task->tk_buffer + bufsiz);
+ rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz);
rcvbuf->head[0].iov_len = bufsiz;
rcvbuf->tail[0].iov_len = 0;
rcvbuf->page_len = 0;
@@ -849,8 +866,7 @@ call_connect_status(struct rpc_task *task)
}
/* Something failed: remote service port may have changed */
- if (clnt->cl_autobind)
- clnt->cl_port = 0;
+ rpc_force_rebind(clnt);
switch (status) {
case -ENOTCONN:
@@ -892,7 +908,7 @@ call_transmit(struct rpc_task *task)
if (task->tk_status < 0)
return;
if (!task->tk_msg.rpc_proc->p_decode) {
- task->tk_action = NULL;
+ task->tk_action = rpc_exit_task;
rpc_wake_up_task(task);
}
return;
@@ -931,8 +947,7 @@ call_status(struct rpc_task *task)
break;
case -ECONNREFUSED:
case -ENOTCONN:
- if (clnt->cl_autobind)
- clnt->cl_port = 0;
+ rpc_force_rebind(clnt);
task->tk_action = call_bind;
break;
case -EAGAIN:
@@ -943,8 +958,7 @@ call_status(struct rpc_task *task)
rpc_exit(task, status);
break;
default:
- if (clnt->cl_chatty)
- printk("%s: RPC call returned error %d\n",
+ printk("%s: RPC call returned error %d\n",
clnt->cl_protname, -status);
rpc_exit(task, status);
break;
@@ -979,20 +993,18 @@ call_timeout(struct rpc_task *task)
dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid);
if (RPC_IS_SOFT(task)) {
- if (clnt->cl_chatty)
- printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
+ printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
clnt->cl_protname, clnt->cl_server);
rpc_exit(task, -EIO);
return;
}
- if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) {
+ if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) {
task->tk_flags |= RPC_CALL_MAJORSEEN;
printk(KERN_NOTICE "%s: server %s not responding, still trying\n",
clnt->cl_protname, clnt->cl_server);
}
- if (clnt->cl_autobind)
- clnt->cl_port = 0;
+ rpc_force_rebind(clnt);
retry:
clnt->cl_stats->rpcretrans++;
@@ -1014,7 +1026,7 @@ call_decode(struct rpc_task *task)
dprintk("RPC: %4d call_decode (status %d)\n",
task->tk_pid, task->tk_status);
- if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) {
+ if (task->tk_flags & RPC_CALL_MAJORSEEN) {
printk(KERN_NOTICE "%s: server %s OK\n",
clnt->cl_protname, clnt->cl_server);
task->tk_flags &= ~RPC_CALL_MAJORSEEN;
@@ -1039,13 +1051,14 @@ call_decode(struct rpc_task *task)
sizeof(req->rq_rcv_buf)) != 0);
/* Verify the RPC header */
- if (!(p = call_verify(task))) {
- if (task->tk_action == NULL)
- return;
- goto out_retry;
+ p = call_verify(task);
+ if (IS_ERR(p)) {
+ if (p == ERR_PTR(-EAGAIN))
+ goto out_retry;
+ return;
}
- task->tk_action = NULL;
+ task->tk_action = rpc_exit_task;
if (decode)
task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
@@ -1138,7 +1151,7 @@ call_verify(struct rpc_task *task)
if ((n = ntohl(*p++)) != RPC_REPLY) {
printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
- goto out_retry;
+ goto out_garbage;
}
if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
if (--len < 0)
@@ -1168,7 +1181,7 @@ call_verify(struct rpc_task *task)
task->tk_pid);
rpcauth_invalcred(task);
task->tk_action = call_refresh;
- return NULL;
+ goto out_retry;
case RPC_AUTH_BADCRED:
case RPC_AUTH_BADVERF:
/* possibly garbled cred/verf? */
@@ -1178,7 +1191,7 @@ call_verify(struct rpc_task *task)
dprintk("RPC: %4d call_verify: retry garbled creds\n",
task->tk_pid);
task->tk_action = call_bind;
- return NULL;
+ goto out_retry;
case RPC_AUTH_TOOWEAK:
printk(KERN_NOTICE "call_verify: server requires stronger "
"authentication.\n");
@@ -1193,7 +1206,7 @@ call_verify(struct rpc_task *task)
}
if (!(p = rpcauth_checkverf(task, p))) {
printk(KERN_WARNING "call_verify: auth check failed\n");
- goto out_retry; /* bad verifier, retry */
+ goto out_garbage; /* bad verifier, retry */
}
len = p - (u32 *)iov->iov_base - 1;
if (len < 0)
@@ -1230,23 +1243,24 @@ call_verify(struct rpc_task *task)
/* Also retry */
}
-out_retry:
+out_garbage:
task->tk_client->cl_stats->rpcgarbage++;
if (task->tk_garb_retry) {
task->tk_garb_retry--;
dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
task->tk_action = call_bind;
- return NULL;
+out_retry:
+ return ERR_PTR(-EAGAIN);
}
printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
out_eio:
error = -EIO;
out_err:
rpc_exit(task, error);
- return NULL;
+ return ERR_PTR(error);
out_overflow:
printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
- goto out_retry;
+ goto out_garbage;
}
static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index a398575f94b8..8139ce68e915 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -90,8 +90,7 @@ bailout:
map->pm_binding = 0;
rpc_wake_up(&map->pm_bindwait);
spin_unlock(&pmap_lock);
- task->tk_status = -EIO;
- task->tk_action = NULL;
+ rpc_exit(task, -EIO);
}
#ifdef CONFIG_ROOT_NFS
@@ -132,21 +131,22 @@ static void
pmap_getport_done(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
+ struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_portmap *map = clnt->cl_pmap;
dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n",
task->tk_pid, task->tk_status, clnt->cl_port);
+
+ xprt->ops->set_port(xprt, 0);
if (task->tk_status < 0) {
/* Make the calling task exit with an error */
- task->tk_action = NULL;
+ task->tk_action = rpc_exit_task;
} else if (clnt->cl_port == 0) {
/* Program not registered */
- task->tk_status = -EACCES;
- task->tk_action = NULL;
+ rpc_exit(task, -EACCES);
} else {
- /* byte-swap port number first */
+ xprt->ops->set_port(xprt, clnt->cl_port);
clnt->cl_port = htons(clnt->cl_port);
- clnt->cl_xprt->addr.sin_port = clnt->cl_port;
}
spin_lock(&pmap_lock);
map->pm_binding = 0;
@@ -207,7 +207,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileg
xprt = xprt_create_proto(proto, srvaddr, NULL);
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
- xprt->addr.sin_port = htons(RPC_PMAP_PORT);
+ xprt->ops->set_port(xprt, RPC_PMAP_PORT);
if (!privileged)
xprt->resvport = 0;
@@ -217,7 +217,6 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileg
RPC_AUTH_UNIX);
if (!IS_ERR(clnt)) {
clnt->cl_softrtry = 1;
- clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
}
return clnt;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 16a2458f38f7..9764c80ab0b2 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -69,10 +69,13 @@ rpc_timeout_upcall_queue(void *data)
struct rpc_inode *rpci = (struct rpc_inode *)data;
struct inode *inode = &rpci->vfs_inode;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
+ if (rpci->ops == NULL)
+ goto out;
if (rpci->nreaders == 0 && !list_empty(&rpci->pipe))
__rpc_purge_upcall(inode, -ETIMEDOUT);
- up(&inode->i_sem);
+out:
+ mutex_unlock(&inode->i_mutex);
}
int
@@ -81,7 +84,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
struct rpc_inode *rpci = RPC_I(inode);
int res = -EPIPE;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops == NULL)
goto out;
if (rpci->nreaders) {
@@ -97,7 +100,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg)
res = 0;
}
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
wake_up(&rpci->waitq);
return res;
}
@@ -113,9 +116,7 @@ rpc_close_pipes(struct inode *inode)
{
struct rpc_inode *rpci = RPC_I(inode);
- cancel_delayed_work(&rpci->queue_timeout);
- flush_scheduled_work();
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops != NULL) {
rpci->nreaders = 0;
__rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE);
@@ -126,7 +127,9 @@ rpc_close_pipes(struct inode *inode)
rpci->ops = NULL;
}
rpc_inode_setowner(inode, NULL);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
+ cancel_delayed_work(&rpci->queue_timeout);
+ flush_scheduled_work();
}
static struct inode *
@@ -151,7 +154,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp)
struct rpc_inode *rpci = RPC_I(inode);
int res = -ENXIO;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops != NULL) {
if (filp->f_mode & FMODE_READ)
rpci->nreaders ++;
@@ -159,17 +162,17 @@ rpc_pipe_open(struct inode *inode, struct file *filp)
rpci->nwriters ++;
res = 0;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
static int
rpc_pipe_release(struct inode *inode, struct file *filp)
{
- struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode);
+ struct rpc_inode *rpci = RPC_I(inode);
struct rpc_pipe_msg *msg;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops == NULL)
goto out;
msg = (struct rpc_pipe_msg *)filp->private_data;
@@ -187,7 +190,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp)
if (rpci->ops->release_pipe)
rpci->ops->release_pipe(inode);
out:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return 0;
}
@@ -199,7 +202,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
struct rpc_pipe_msg *msg;
int res = 0;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
if (rpci->ops == NULL) {
res = -EPIPE;
goto out_unlock;
@@ -226,7 +229,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset)
rpci->ops->destroy_msg(msg);
}
out_unlock:
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
@@ -237,11 +240,11 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of
struct rpc_inode *rpci = RPC_I(inode);
int res;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
res = -EPIPE;
if (rpci->ops != NULL)
res = rpci->ops->downcall(filp, buf, len);
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
return res;
}
@@ -319,7 +322,7 @@ rpc_info_open(struct inode *inode, struct file *file)
if (!ret) {
struct seq_file *m = file->private_data;
- down(&inode->i_sem);
+ mutex_lock(&inode->i_mutex);
clnt = RPC_I(inode)->private;
if (clnt) {
atomic_inc(&clnt->cl_users);
@@ -328,7 +331,7 @@ rpc_info_open(struct inode *inode, struct file *file)
single_release(inode, file);
ret = -EINVAL;
}
- up(&inode->i_sem);
+ mutex_unlock(&inode->i_mutex);
}
return ret;
}
@@ -488,11 +491,11 @@ rpc_depopulate(struct dentry *parent)
struct dentry *dentry, *dvec[10];
int n = 0;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
repeat:
spin_lock(&dcache_lock);
list_for_each_safe(pos, next, &parent->d_subdirs) {
- dentry = list_entry(pos, struct dentry, d_child);
+ dentry = list_entry(pos, struct dentry, d_u.d_child);
spin_lock(&dentry->d_lock);
if (!d_unhashed(dentry)) {
dget_locked(dentry);
@@ -516,7 +519,7 @@ repeat:
} while (n);
goto repeat;
}
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
}
static int
@@ -529,7 +532,7 @@ rpc_populate(struct dentry *parent,
struct dentry *dentry;
int mode, i;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
for (i = start; i < eof; i++) {
dentry = d_alloc_name(parent, files[i].name);
if (!dentry)
@@ -549,10 +552,10 @@ rpc_populate(struct dentry *parent,
dir->i_nlink++;
d_add(dentry, inode);
}
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
return 0;
out_bad:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
__FILE__, __FUNCTION__, parent->d_name.name);
return -ENOMEM;
@@ -606,7 +609,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd)
if ((error = rpc_lookup_parent(path, nd)) != 0)
return ERR_PTR(error);
dir = nd->dentry->d_inode;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
dentry = lookup_hash(nd);
if (IS_ERR(dentry))
goto out_err;
@@ -617,7 +620,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd)
}
return dentry;
out_err:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(nd);
return dentry;
}
@@ -643,7 +646,7 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
if (error)
goto err_depopulate;
out:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
return dentry;
err_depopulate:
@@ -668,7 +671,7 @@ rpc_rmdir(char *path)
if ((error = rpc_lookup_parent(path, &nd)) != 0)
return error;
dir = nd.dentry->d_inode;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
dentry = lookup_hash(&nd);
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
@@ -678,7 +681,7 @@ rpc_rmdir(char *path)
error = __rpc_rmdir(dir, dentry);
dput(dentry);
out_release:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
return error;
}
@@ -707,7 +710,7 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
rpci->ops = ops;
inode_dir_notify(dir, DN_CREATE);
out:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
return dentry;
err_dput:
@@ -729,7 +732,7 @@ rpc_unlink(char *path)
if ((error = rpc_lookup_parent(path, &nd)) != 0)
return error;
dir = nd.dentry->d_inode;
- down(&dir->i_sem);
+ mutex_lock(&dir->i_mutex);
dentry = lookup_hash(&nd);
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
@@ -743,7 +746,7 @@ rpc_unlink(char *path)
dput(dentry);
inode_dir_notify(dir, DN_DELETE);
out_release:
- up(&dir->i_sem);
+ mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd);
return error;
}
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 54e60a657500..7415406aa1ae 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -41,8 +41,6 @@ static mempool_t *rpc_buffer_mempool __read_mostly;
static void __rpc_default_timer(struct rpc_task *task);
static void rpciod_killall(void);
-static void rpc_free(struct rpc_task *task);
-
static void rpc_async_schedule(void *);
/*
@@ -264,6 +262,35 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname)
}
EXPORT_SYMBOL(rpc_init_wait_queue);
+static int rpc_wait_bit_interruptible(void *word)
+{
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ schedule();
+ return 0;
+}
+
+/*
+ * Mark an RPC call as having completed by clearing the 'active' bit
+ */
+static inline void rpc_mark_complete_task(struct rpc_task *task)
+{
+ rpc_clear_active(task);
+ wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE);
+}
+
+/*
+ * Allow callers to wait for completion of an RPC call
+ */
+int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *))
+{
+ if (action == NULL)
+ action = rpc_wait_bit_interruptible;
+ return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE,
+ action, TASK_INTERRUPTIBLE);
+}
+EXPORT_SYMBOL(__rpc_wait_for_completion_task);
+
/*
* Make an RPC task runnable.
*
@@ -299,10 +326,7 @@ static void rpc_make_runnable(struct rpc_task *task)
static inline void
rpc_schedule_run(struct rpc_task *task)
{
- /* Don't run a child twice! */
- if (RPC_IS_ACTIVATED(task))
- return;
- task->tk_active = 1;
+ rpc_set_active(task);
rpc_make_runnable(task);
}
@@ -324,8 +348,7 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task,
}
/* Mark the task as being activated if so needed */
- if (!RPC_IS_ACTIVATED(task))
- task->tk_active = 1;
+ rpc_set_active(task);
__rpc_add_wait_queue(q, task);
@@ -555,36 +578,29 @@ __rpc_atrun(struct rpc_task *task)
}
/*
- * Helper that calls task->tk_exit if it exists and then returns
- * true if we should exit __rpc_execute.
+ * Helper to call task->tk_ops->rpc_call_prepare
*/
-static inline int __rpc_do_exit(struct rpc_task *task)
+static void rpc_prepare_task(struct rpc_task *task)
{
- if (task->tk_exit != NULL) {
- lock_kernel();
- task->tk_exit(task);
- unlock_kernel();
- /* If tk_action is non-null, we should restart the call */
- if (task->tk_action != NULL) {
- if (!RPC_ASSASSINATED(task)) {
- /* Release RPC slot and buffer memory */
- xprt_release(task);
- rpc_free(task);
- return 0;
- }
- printk(KERN_ERR "RPC: dead task tried to walk away.\n");
- }
- }
- return 1;
+ task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
}
-static int rpc_wait_bit_interruptible(void *word)
+/*
+ * Helper that calls task->tk_ops->rpc_call_done if it exists
+ */
+void rpc_exit_task(struct rpc_task *task)
{
- if (signal_pending(current))
- return -ERESTARTSYS;
- schedule();
- return 0;
+ task->tk_action = NULL;
+ if (task->tk_ops->rpc_call_done != NULL) {
+ task->tk_ops->rpc_call_done(task, task->tk_calldata);
+ if (task->tk_action != NULL) {
+ WARN_ON(RPC_ASSASSINATED(task));
+ /* Always release the RPC slot and buffer memory */
+ xprt_release(task);
+ }
+ }
}
+EXPORT_SYMBOL(rpc_exit_task);
/*
* This is the RPC `scheduler' (or rather, the finite state machine).
@@ -631,12 +647,11 @@ static int __rpc_execute(struct rpc_task *task)
* by someone else.
*/
if (!RPC_IS_QUEUED(task)) {
- if (task->tk_action != NULL) {
- lock_kernel();
- task->tk_action(task);
- unlock_kernel();
- } else if (__rpc_do_exit(task))
+ if (task->tk_action == NULL)
break;
+ lock_kernel();
+ task->tk_action(task);
+ unlock_kernel();
}
/*
@@ -676,9 +691,9 @@ static int __rpc_execute(struct rpc_task *task)
dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
}
- dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status);
- status = task->tk_status;
-
+ dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status);
+ /* Wake up anyone who is waiting for task completion */
+ rpc_mark_complete_task(task);
/* Release all resources associated with the task */
rpc_release_task(task);
return status;
@@ -696,9 +711,7 @@ static int __rpc_execute(struct rpc_task *task)
int
rpc_execute(struct rpc_task *task)
{
- BUG_ON(task->tk_active);
-
- task->tk_active = 1;
+ rpc_set_active(task);
rpc_set_running(task);
return __rpc_execute(task);
}
@@ -708,17 +721,19 @@ static void rpc_async_schedule(void *arg)
__rpc_execute((struct rpc_task *)arg);
}
-/*
- * Allocate memory for RPC purposes.
+/**
+ * rpc_malloc - allocate an RPC buffer
+ * @task: RPC task that will use this buffer
+ * @size: requested byte size
*
* We try to ensure that some NFS reads and writes can always proceed
* by using a mempool when allocating 'small' buffers.
* In order to avoid memory starvation triggering more writebacks of
* NFS requests, we use GFP_NOFS rather than GFP_KERNEL.
*/
-void *
-rpc_malloc(struct rpc_task *task, size_t size)
+void * rpc_malloc(struct rpc_task *task, size_t size)
{
+ struct rpc_rqst *req = task->tk_rqstp;
gfp_t gfp;
if (task->tk_flags & RPC_TASK_SWAPPER)
@@ -727,42 +742,52 @@ rpc_malloc(struct rpc_task *task, size_t size)
gfp = GFP_NOFS;
if (size > RPC_BUFFER_MAXSIZE) {
- task->tk_buffer = kmalloc(size, gfp);
- if (task->tk_buffer)
- task->tk_bufsize = size;
+ req->rq_buffer = kmalloc(size, gfp);
+ if (req->rq_buffer)
+ req->rq_bufsize = size;
} else {
- task->tk_buffer = mempool_alloc(rpc_buffer_mempool, gfp);
- if (task->tk_buffer)
- task->tk_bufsize = RPC_BUFFER_MAXSIZE;
+ req->rq_buffer = mempool_alloc(rpc_buffer_mempool, gfp);
+ if (req->rq_buffer)
+ req->rq_bufsize = RPC_BUFFER_MAXSIZE;
}
- return task->tk_buffer;
+ return req->rq_buffer;
}
-static void
-rpc_free(struct rpc_task *task)
+/**
+ * rpc_free - free buffer allocated via rpc_malloc
+ * @task: RPC task with a buffer to be freed
+ *
+ */
+void rpc_free(struct rpc_task *task)
{
- if (task->tk_buffer) {
- if (task->tk_bufsize == RPC_BUFFER_MAXSIZE)
- mempool_free(task->tk_buffer, rpc_buffer_mempool);
+ struct rpc_rqst *req = task->tk_rqstp;
+
+ if (req->rq_buffer) {
+ if (req->rq_bufsize == RPC_BUFFER_MAXSIZE)
+ mempool_free(req->rq_buffer, rpc_buffer_mempool);
else
- kfree(task->tk_buffer);
- task->tk_buffer = NULL;
- task->tk_bufsize = 0;
+ kfree(req->rq_buffer);
+ req->rq_buffer = NULL;
+ req->rq_bufsize = 0;
}
}
/*
* Creation and deletion of RPC task structures
*/
-void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action callback, int flags)
+void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
{
memset(task, 0, sizeof(*task));
init_timer(&task->tk_timer);
task->tk_timer.data = (unsigned long) task;
task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer;
+ atomic_set(&task->tk_count, 1);
task->tk_client = clnt;
task->tk_flags = flags;
- task->tk_exit = callback;
+ task->tk_ops = tk_ops;
+ if (tk_ops->rpc_call_prepare != NULL)
+ task->tk_action = rpc_prepare_task;
+ task->tk_calldata = calldata;
/* Initialize retry counters */
task->tk_garb_retry = 2;
@@ -791,6 +816,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
list_add_tail(&task->tk_task, &all_tasks);
spin_unlock(&rpc_sched_lock);
+ BUG_ON(task->tk_ops == NULL);
+
dprintk("RPC: %4d new task procpid %d\n", task->tk_pid,
current->pid);
}
@@ -801,8 +828,7 @@ rpc_alloc_task(void)
return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS);
}
-static void
-rpc_default_free_task(struct rpc_task *task)
+static void rpc_free_task(struct rpc_task *task)
{
dprintk("RPC: %4d freeing task\n", task->tk_pid);
mempool_free(task, rpc_task_mempool);
@@ -813,8 +839,7 @@ rpc_default_free_task(struct rpc_task *task)
* clean up after an allocation failure, as the client may
* have specified "oneshot".
*/
-struct rpc_task *
-rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags)
+struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
{
struct rpc_task *task;
@@ -822,10 +847,7 @@ rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags)
if (!task)
goto cleanup;
- rpc_init_task(task, clnt, callback, flags);
-
- /* Replace tk_release */
- task->tk_release = rpc_default_free_task;
+ rpc_init_task(task, clnt, flags, tk_ops, calldata);
dprintk("RPC: %4d allocated task\n", task->tk_pid);
task->tk_flags |= RPC_TASK_DYNAMIC;
@@ -845,11 +867,15 @@ cleanup:
void rpc_release_task(struct rpc_task *task)
{
- dprintk("RPC: %4d release task\n", task->tk_pid);
+ const struct rpc_call_ops *tk_ops = task->tk_ops;
+ void *calldata = task->tk_calldata;
#ifdef RPC_DEBUG
BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID);
#endif
+ if (!atomic_dec_and_test(&task->tk_count))
+ return;
+ dprintk("RPC: %4d release task\n", task->tk_pid);
/* Remove from global task list */
spin_lock(&rpc_sched_lock);
@@ -857,7 +883,6 @@ void rpc_release_task(struct rpc_task *task)
spin_unlock(&rpc_sched_lock);
BUG_ON (RPC_IS_QUEUED(task));
- task->tk_active = 0;
/* Synchronously delete any running timer */
rpc_delete_timer(task);
@@ -867,7 +892,6 @@ void rpc_release_task(struct rpc_task *task)
xprt_release(task);
if (task->tk_msg.rpc_cred)
rpcauth_unbindcred(task);
- rpc_free(task);
if (task->tk_client) {
rpc_release_client(task->tk_client);
task->tk_client = NULL;
@@ -876,11 +900,34 @@ void rpc_release_task(struct rpc_task *task)
#ifdef RPC_DEBUG
task->tk_magic = 0;
#endif
- if (task->tk_release)
- task->tk_release(task);
+ if (task->tk_flags & RPC_TASK_DYNAMIC)
+ rpc_free_task(task);
+ if (tk_ops->rpc_release)
+ tk_ops->rpc_release(calldata);
}
/**
+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+ * @clnt - pointer to RPC client
+ * @flags - RPC flags
+ * @ops - RPC call ops
+ * @data - user call data
+ */
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+ const struct rpc_call_ops *ops,
+ void *data)
+{
+ struct rpc_task *task;
+ task = rpc_new_task(clnt, flags, ops, data);
+ if (task == NULL)
+ return ERR_PTR(-ENOMEM);
+ atomic_inc(&task->tk_count);
+ rpc_execute(task);
+ return task;
+}
+EXPORT_SYMBOL(rpc_run_task);
+
+/**
* rpc_find_parent - find the parent of a child task.
* @child: child task
*
@@ -890,12 +937,11 @@ void rpc_release_task(struct rpc_task *task)
*
* Caller must hold childq.lock
*/
-static inline struct rpc_task *rpc_find_parent(struct rpc_task *child)
+static inline struct rpc_task *rpc_find_parent(struct rpc_task *child, struct rpc_task *parent)
{
- struct rpc_task *task, *parent;
+ struct rpc_task *task;
struct list_head *le;
- parent = (struct rpc_task *) child->tk_calldata;
task_for_each(task, le, &childq.tasks[0])
if (task == parent)
return parent;
@@ -903,18 +949,22 @@ static inline struct rpc_task *rpc_find_parent(struct rpc_task *child)
return NULL;
}
-static void rpc_child_exit(struct rpc_task *child)
+static void rpc_child_exit(struct rpc_task *child, void *calldata)
{
struct rpc_task *parent;
spin_lock_bh(&childq.lock);
- if ((parent = rpc_find_parent(child)) != NULL) {
+ if ((parent = rpc_find_parent(child, calldata)) != NULL) {
parent->tk_status = child->tk_status;
__rpc_wake_up_task(parent);
}
spin_unlock_bh(&childq.lock);
}
+static const struct rpc_call_ops rpc_child_ops = {
+ .rpc_call_done = rpc_child_exit,
+};
+
/*
* Note: rpc_new_task releases the client after a failure.
*/
@@ -923,11 +973,9 @@ rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent)
{
struct rpc_task *task;
- task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD);
+ task = rpc_new_task(clnt, RPC_TASK_ASYNC | RPC_TASK_CHILD, &rpc_child_ops, parent);
if (!task)
goto fail;
- task->tk_exit = rpc_child_exit;
- task->tk_calldata = parent;
return task;
fail:
@@ -1063,7 +1111,7 @@ void rpc_show_tasks(void)
return;
}
printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
- "-rpcwait -action- --exit--\n");
+ "-rpcwait -action- ---ops--\n");
alltask_for_each(t, le, &all_tasks) {
const char *rpc_waitq = "none";
@@ -1078,7 +1126,7 @@ void rpc_show_tasks(void)
(t->tk_client ? t->tk_client->cl_prog : 0),
t->tk_rqstp, t->tk_timeout,
rpc_waitq,
- t->tk_action, t->tk_exit);
+ t->tk_action, t->tk_ops);
}
spin_unlock(&rpc_sched_lock);
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index a03d4b600c92..9f7373203592 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -30,8 +30,6 @@ EXPORT_SYMBOL(rpc_init_task);
EXPORT_SYMBOL(rpc_sleep_on);
EXPORT_SYMBOL(rpc_wake_up_next);
EXPORT_SYMBOL(rpc_wake_up_task);
-EXPORT_SYMBOL(rpc_new_child);
-EXPORT_SYMBOL(rpc_run_child);
EXPORT_SYMBOL(rpciod_down);
EXPORT_SYMBOL(rpciod_up);
EXPORT_SYMBOL(rpc_new_task);
@@ -45,7 +43,6 @@ EXPORT_SYMBOL(rpc_clone_client);
EXPORT_SYMBOL(rpc_bind_new_program);
EXPORT_SYMBOL(rpc_destroy_client);
EXPORT_SYMBOL(rpc_shutdown_client);
-EXPORT_SYMBOL(rpc_release_client);
EXPORT_SYMBOL(rpc_killall_tasks);
EXPORT_SYMBOL(rpc_call_sync);
EXPORT_SYMBOL(rpc_call_async);
@@ -120,7 +117,6 @@ EXPORT_SYMBOL(unix_domain_find);
/* Generic XDR */
EXPORT_SYMBOL(xdr_encode_string);
-EXPORT_SYMBOL(xdr_decode_string);
EXPORT_SYMBOL(xdr_decode_string_inplace);
EXPORT_SYMBOL(xdr_decode_netobj);
EXPORT_SYMBOL(xdr_encode_netobj);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e4296c8b861e..b08419e1fc68 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -32,7 +32,7 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
int vers;
unsigned int xdrsize;
- if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL)))
+ if (!(serv = kmalloc(sizeof(*serv), GFP_KERNEL)))
return NULL;
memset(serv, 0, sizeof(*serv));
serv->sv_name = prog->pg_name;
@@ -122,8 +122,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size)
rqstp->rq_argused = 0;
rqstp->rq_resused = 0;
arghi = 0;
- if (pages > RPCSVC_MAXPAGES)
- BUG();
+ BUG_ON(pages > RPCSVC_MAXPAGES);
while (pages) {
struct page *p = alloc_page(GFP_KERNEL);
if (!p)
@@ -167,8 +166,8 @@ svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
memset(rqstp, 0, sizeof(*rqstp));
init_waitqueue_head(&rqstp->rq_wait);
- if (!(rqstp->rq_argp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
- || !(rqstp->rq_resp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
+ if (!(rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
+ || !(rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL))
|| !svc_init_buffer(rqstp, serv->sv_bufsz))
goto out_thread;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index cac2e774dd81..3e6c694bbad1 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -101,10 +101,22 @@ static void ip_map_put(struct cache_head *item, struct cache_detail *cd)
}
}
+#if IP_HASHBITS == 8
+/* hash_long on a 64 bit machine is currently REALLY BAD for
+ * IP addresses in reverse-endian (i.e. on a little-endian machine).
+ * So use a trivial but reliable hash instead
+ */
+static inline int hash_ip(unsigned long ip)
+{
+ int hash = ip ^ (ip>>16);
+ return (hash ^ (hash>>8)) & 0xff;
+}
+#endif
+
static inline int ip_map_hash(struct ip_map *item)
{
return hash_str(item->m_class, IP_HASHBITS) ^
- hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
+ hash_ip((unsigned long)item->m_addr.s_addr);
}
static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
{
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index c6a51911e71e..50580620e897 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -758,7 +758,7 @@ svc_tcp_accept(struct svc_sock *svsk)
struct svc_serv *serv = svsk->sk_server;
struct socket *sock = svsk->sk_sock;
struct socket *newsock;
- struct proto_ops *ops;
+ const struct proto_ops *ops;
struct svc_sock *newsvsk;
int err, slen;
@@ -1026,7 +1026,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
} else {
printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
svsk->sk_server->sv_name, -len);
- svc_sock_received(svsk);
+ goto err_delete;
}
return len;
@@ -1527,6 +1527,7 @@ svc_defer(struct cache_req *req)
dr->handle.owner = rqstp->rq_server;
dr->prot = rqstp->rq_prot;
dr->addr = rqstp->rq_addr;
+ dr->daddr = rqstp->rq_daddr;
dr->argslen = rqstp->rq_arg.len >> 2;
memcpy(dr->args, rqstp->rq_arg.head[0].iov_base-skip, dr->argslen<<2);
}
@@ -1552,6 +1553,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp)
rqstp->rq_arg.len = dr->argslen<<2;
rqstp->rq_prot = dr->prot;
rqstp->rq_addr = dr->addr;
+ rqstp->rq_daddr = dr->daddr;
return dr->argslen<<2;
}
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index aaf08cdd19f0..ca4bfa57e116 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -93,27 +93,6 @@ xdr_encode_string(u32 *p, const char *string)
}
u32 *
-xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen)
-{
- unsigned int len;
- char *string;
-
- if ((len = ntohl(*p++)) > maxlen)
- return NULL;
- if (lenp)
- *lenp = len;
- if ((len % 4) != 0) {
- string = (char *) p;
- } else {
- string = (char *) (p - 1);
- memmove(string, p, len);
- }
- string[len] = '\0';
- *sp = string;
- return p + XDR_QUADLEN(len);
-}
-
-u32 *
xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen)
{
unsigned int len;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 6dda3860351f..8ff2c8acb223 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -119,6 +119,17 @@ out_sleep:
return 0;
}
+static void xprt_clear_locked(struct rpc_xprt *xprt)
+{
+ xprt->snd_task = NULL;
+ if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) {
+ smp_mb__before_clear_bit();
+ clear_bit(XPRT_LOCKED, &xprt->state);
+ smp_mb__after_clear_bit();
+ } else
+ schedule_work(&xprt->task_cleanup);
+}
+
/*
* xprt_reserve_xprt_cong - serialize write access to transports
* @task: task that is requesting access to the transport
@@ -145,9 +156,7 @@ int xprt_reserve_xprt_cong(struct rpc_task *task)
}
return 1;
}
- smp_mb__before_clear_bit();
- clear_bit(XPRT_LOCKED, &xprt->state);
- smp_mb__after_clear_bit();
+ xprt_clear_locked(xprt);
out_sleep:
dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt);
task->tk_timeout = 0;
@@ -193,9 +202,7 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt)
return;
out_unlock:
- smp_mb__before_clear_bit();
- clear_bit(XPRT_LOCKED, &xprt->state);
- smp_mb__after_clear_bit();
+ xprt_clear_locked(xprt);
}
static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
@@ -222,9 +229,7 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt)
return;
}
out_unlock:
- smp_mb__before_clear_bit();
- clear_bit(XPRT_LOCKED, &xprt->state);
- smp_mb__after_clear_bit();
+ xprt_clear_locked(xprt);
}
/**
@@ -237,10 +242,7 @@ out_unlock:
void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
{
if (xprt->snd_task == task) {
- xprt->snd_task = NULL;
- smp_mb__before_clear_bit();
- clear_bit(XPRT_LOCKED, &xprt->state);
- smp_mb__after_clear_bit();
+ xprt_clear_locked(xprt);
__xprt_lock_write_next(xprt);
}
}
@@ -256,10 +258,7 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task)
{
if (xprt->snd_task == task) {
- xprt->snd_task = NULL;
- smp_mb__before_clear_bit();
- clear_bit(XPRT_LOCKED, &xprt->state);
- smp_mb__after_clear_bit();
+ xprt_clear_locked(xprt);
__xprt_lock_write_next_cong(xprt);
}
}
@@ -535,10 +534,6 @@ void xprt_connect(struct rpc_task *task)
dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid,
xprt, (xprt_connected(xprt) ? "is" : "is not"));
- if (xprt->shutdown) {
- task->tk_status = -EIO;
- return;
- }
if (!xprt->addr.sin_port) {
task->tk_status = -EIO;
return;
@@ -687,9 +682,6 @@ int xprt_prepare_transmit(struct rpc_task *task)
dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid);
- if (xprt->shutdown)
- return -EIO;
-
spin_lock_bh(&xprt->transport_lock);
if (req->rq_received && !req->rq_bytes_sent) {
err = req->rq_received;
@@ -814,11 +806,9 @@ void xprt_reserve(struct rpc_task *task)
struct rpc_xprt *xprt = task->tk_xprt;
task->tk_status = -EIO;
- if (!xprt->shutdown) {
- spin_lock(&xprt->reserve_lock);
- do_xprt_reserve(task);
- spin_unlock(&xprt->reserve_lock);
- }
+ spin_lock(&xprt->reserve_lock);
+ do_xprt_reserve(task);
+ spin_unlock(&xprt->reserve_lock);
}
static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
@@ -838,6 +828,8 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
req->rq_timeout = xprt->timeout.to_initval;
req->rq_task = task;
req->rq_xprt = xprt;
+ req->rq_buffer = NULL;
+ req->rq_bufsize = 0;
req->rq_xid = xprt_alloc_xid(xprt);
req->rq_release_snd_buf = NULL;
dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
@@ -863,10 +855,11 @@ void xprt_release(struct rpc_task *task)
if (!list_empty(&req->rq_list))
list_del(&req->rq_list);
xprt->last_used = jiffies;
- if (list_empty(&xprt->recv) && !xprt->shutdown)
+ if (list_empty(&xprt->recv))
mod_timer(&xprt->timer,
xprt->last_used + xprt->idle_timeout);
spin_unlock_bh(&xprt->transport_lock);
+ xprt->ops->buf_free(task);
task->tk_rqstp = NULL;
if (req->rq_release_snd_buf)
req->rq_release_snd_buf(req);
@@ -974,16 +967,6 @@ struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rp
return xprt;
}
-static void xprt_shutdown(struct rpc_xprt *xprt)
-{
- xprt->shutdown = 1;
- rpc_wake_up(&xprt->sending);
- rpc_wake_up(&xprt->resend);
- xprt_wake_pending_tasks(xprt, -EIO);
- rpc_wake_up(&xprt->backlog);
- del_timer_sync(&xprt->timer);
-}
-
/**
* xprt_destroy - destroy an RPC transport, killing off all requests.
* @xprt: transport to destroy
@@ -992,7 +975,8 @@ static void xprt_shutdown(struct rpc_xprt *xprt)
int xprt_destroy(struct rpc_xprt *xprt)
{
dprintk("RPC: destroying transport %p\n", xprt);
- xprt_shutdown(xprt);
+ xprt->shutdown = 1;
+ del_timer_sync(&xprt->timer);
xprt->ops->destroy(xprt);
kfree(xprt);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 77e8800d4127..c458f8d1d6d1 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -28,6 +28,7 @@
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/sched.h>
#include <linux/file.h>
#include <net/sock.h>
@@ -424,7 +425,7 @@ static void xs_close(struct rpc_xprt *xprt)
struct sock *sk = xprt->inet;
if (!sk)
- return;
+ goto clear_close_wait;
dprintk("RPC: xs_close xprt %p\n", xprt);
@@ -441,6 +442,10 @@ static void xs_close(struct rpc_xprt *xprt)
sk->sk_no_check = 0;
sock_release(sock);
+clear_close_wait:
+ smp_mb__before_clear_bit();
+ clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ smp_mb__after_clear_bit();
}
/**
@@ -800,9 +805,13 @@ static void xs_tcp_state_change(struct sock *sk)
case TCP_SYN_SENT:
case TCP_SYN_RECV:
break;
+ case TCP_CLOSE_WAIT:
+ /* Try to schedule an autoclose RPC calls */
+ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ schedule_work(&xprt->task_cleanup);
default:
xprt_disconnect(xprt);
- break;
}
out:
read_unlock(&sk->sk_callback_lock);
@@ -920,6 +929,18 @@ static void xs_udp_timer(struct rpc_task *task)
xprt_adjust_cwnd(task, -ETIMEDOUT);
}
+/**
+ * xs_set_port - reset the port number in the remote endpoint address
+ * @xprt: generic transport
+ * @port: new port number
+ *
+ */
+static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
+{
+ dprintk("RPC: setting port for xprt %p to %u\n", xprt, port);
+ xprt->addr.sin_port = htons(port);
+}
+
static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
{
struct sockaddr_in myaddr = {
@@ -1160,7 +1181,10 @@ static struct rpc_xprt_ops xs_udp_ops = {
.set_buffer_size = xs_udp_set_buffer_size,
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong,
+ .set_port = xs_set_port,
.connect = xs_connect,
+ .buf_alloc = rpc_malloc,
+ .buf_free = rpc_free,
.send_request = xs_udp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_rtt,
.timer = xs_udp_timer,
@@ -1172,7 +1196,10 @@ static struct rpc_xprt_ops xs_udp_ops = {
static struct rpc_xprt_ops xs_tcp_ops = {
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xprt_release_xprt,
+ .set_port = xs_set_port,
.connect = xs_connect,
+ .buf_alloc = rpc_malloc,
+ .buf_free = rpc_free,
.send_request = xs_tcp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_def,
.close = xs_close,
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
new file mode 100644
index 000000000000..3891cc00087d
--- /dev/null
+++ b/net/tipc/Kconfig
@@ -0,0 +1,117 @@
+#
+# TIPC configuration
+#
+
+menu "TIPC Configuration (EXPERIMENTAL)"
+ depends on INET && EXPERIMENTAL
+
+config TIPC
+ tristate "The TIPC Protocol (EXPERIMENTAL)"
+ ---help---
+ The Transparent Inter Process Communication (TIPC) protocol is
+ specially designed for intra cluster communication. This protocol
+ originates from Ericsson where it has been used in carrier grade
+ cluster applications for many years.
+
+ For more information about TIPC, see http://tipc.sourceforge.net.
+
+ This protocol support is also available as a module ( = code which
+ can be inserted in and removed from the running kernel whenever you
+ want). The module will be called tipc. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ If in doubt, say N.
+
+config TIPC_ADVANCED
+ bool "TIPC: Advanced configuration"
+ depends on TIPC
+ default n
+ help
+ Saying Y here will open some advanced configuration
+ for TIPC. Most users do not need to bother, so if
+ unsure, just say N.
+
+config TIPC_ZONES
+ int "Maximum number of zones in network"
+ depends on TIPC && TIPC_ADVANCED
+ default "3"
+ help
+ Max number of zones inside TIPC network. Max supported value
+ is 255 zones, minimum is 1
+
+ Default is 3 zones in a network; setting this to higher
+ allows more zones but might use more memory.
+
+config TIPC_CLUSTERS
+ int "Maximum number of clusters in a zone"
+ depends on TIPC && TIPC_ADVANCED
+ default "1"
+ help
+ ***Only 1 (one cluster in a zone) is supported by current code.
+ Any value set here will be overridden.***
+
+ (Max number of clusters inside TIPC zone. Max supported
+ value is 4095 clusters, minimum is 1.
+
+ Default is 1; setting this to smaller value might save
+ some memory, setting it to higher
+ allows more clusters and might consume more memory.)
+
+config TIPC_NODES
+ int "Maximum number of nodes in cluster"
+ depends on TIPC && TIPC_ADVANCED
+ default "255"
+ help
+ Maximum number of nodes inside a TIPC cluster. Maximum
+ supported value is 2047 nodes, minimum is 8.
+
+ Setting this to a smaller value saves some memory,
+ setting it to higher allows more nodes.
+
+config TIPC_SLAVE_NODES
+ int "Maximum number of slave nodes in cluster"
+ depends on TIPC && TIPC_ADVANCED
+ default "0"
+ help
+ ***This capability is not supported by current code.***
+
+ Maximum number of slave nodes inside a TIPC cluster. Maximum
+ supported value is 2047 nodes, minimum is 0.
+
+ Setting this to a smaller value saves some memory,
+ setting it to higher allows more nodes.
+
+config TIPC_PORTS
+ int "Maximum number of ports in a node"
+ depends on TIPC && TIPC_ADVANCED
+ default "8191"
+ help
+ Maximum number of ports within a node. Maximum
+ supported value is 64535 nodes, minimum is 127.
+
+ Setting this to a smaller value saves some memory,
+ setting it to higher allows more ports.
+
+config TIPC_LOG
+ int "Size of log buffer"
+ depends on TIPC && TIPC_ADVANCED
+ default 0
+ help
+ Size (in bytes) of TIPC's internal log buffer, which records the
+ occurrence of significant events. Maximum supported value
+ is 32768 bytes, minimum is 0.
+
+ There is no need to enable the log buffer unless the node will be
+ managed remotely via TIPC.
+
+config TIPC_DEBUG
+ bool "Enable debugging support"
+ depends on TIPC
+ default n
+ help
+ This will enable debugging of TIPC.
+
+ Only say Y here if you are having trouble with TIPC. It will
+ enable the display of detailed information about what is going on.
+
+endmenu
diff --git a/net/tipc/Makefile b/net/tipc/Makefile
new file mode 100644
index 000000000000..dceb7027946c
--- /dev/null
+++ b/net/tipc/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux TIPC layer
+#
+
+obj-$(CONFIG_TIPC) := tipc.o
+
+tipc-y += addr.o bcast.o bearer.o config.o cluster.o \
+ core.o handler.o link.o discover.o msg.o \
+ name_distr.o subscr.o name_table.o net.o \
+ netlink.o node.o node_subscr.o port.o ref.o \
+ socket.o user_reg.o zone.o dbg.o eth_media.o
+
+# End of file
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
new file mode 100644
index 000000000000..0be25e175b93
--- /dev/null
+++ b/net/tipc/addr.c
@@ -0,0 +1,94 @@
+/*
+ * net/tipc/addr.c: TIPC address utility routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "addr.h"
+#include "zone.h"
+#include "cluster.h"
+#include "net.h"
+
+u32 tipc_get_addr(void)
+{
+ return tipc_own_addr;
+}
+
+/**
+ * tipc_addr_domain_valid - validates a network domain address
+ *
+ * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
+ * where Z, C, and N are non-zero and do not exceed the configured limits.
+ *
+ * Returns 1 if domain address is valid, otherwise 0
+ */
+
+int tipc_addr_domain_valid(u32 addr)
+{
+ u32 n = tipc_node(addr);
+ u32 c = tipc_cluster(addr);
+ u32 z = tipc_zone(addr);
+ u32 max_nodes = tipc_max_nodes;
+
+ if (is_slave(addr))
+ max_nodes = LOWEST_SLAVE + tipc_max_slaves;
+ if (n > max_nodes)
+ return 0;
+ if (c > tipc_max_clusters)
+ return 0;
+ if (z > tipc_max_zones)
+ return 0;
+
+ if (n && (!z || !c))
+ return 0;
+ if (c && !z)
+ return 0;
+ return 1;
+}
+
+/**
+ * tipc_addr_node_valid - validates a proposed network address for this node
+ *
+ * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed
+ * the configured limits.
+ *
+ * Returns 1 if address can be used, otherwise 0
+ */
+
+int tipc_addr_node_valid(u32 addr)
+{
+ return (tipc_addr_domain_valid(addr) && tipc_node(addr));
+}
+
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
new file mode 100644
index 000000000000..bcfebb3cbbf3
--- /dev/null
+++ b/net/tipc/addr.h
@@ -0,0 +1,128 @@
+/*
+ * net/tipc/addr.h: Include file for TIPC address utility routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_ADDR_H
+#define _TIPC_ADDR_H
+
+static inline u32 own_node(void)
+{
+ return tipc_node(tipc_own_addr);
+}
+
+static inline u32 own_cluster(void)
+{
+ return tipc_cluster(tipc_own_addr);
+}
+
+static inline u32 own_zone(void)
+{
+ return tipc_zone(tipc_own_addr);
+}
+
+static inline int in_own_cluster(u32 addr)
+{
+ return !((addr ^ tipc_own_addr) >> 12);
+}
+
+static inline int in_own_zone(u32 addr)
+{
+ return !((addr ^ tipc_own_addr) >> 24);
+}
+
+static inline int is_slave(u32 addr)
+{
+ return addr & 0x800;
+}
+
+static inline int may_route(u32 addr)
+{
+ return(addr ^ tipc_own_addr) >> 11;
+}
+
+static inline int in_scope(u32 domain, u32 addr)
+{
+ if (!domain || (domain == addr))
+ return 1;
+ if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */
+ return 1;
+ if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */
+ return 1;
+ return 0;
+}
+
+/**
+ * addr_scope - convert message lookup domain to equivalent 2-bit scope value
+ */
+
+static inline int addr_scope(u32 domain)
+{
+ if (likely(!domain))
+ return TIPC_ZONE_SCOPE;
+ if (tipc_node(domain))
+ return TIPC_NODE_SCOPE;
+ if (tipc_cluster(domain))
+ return TIPC_CLUSTER_SCOPE;
+ return TIPC_ZONE_SCOPE;
+}
+
+/**
+ * addr_domain - convert 2-bit scope value to equivalent message lookup domain
+ *
+ * Needed when address of a named message must be looked up a second time
+ * after a network hop.
+ */
+
+static inline int addr_domain(int sc)
+{
+ if (likely(sc == TIPC_NODE_SCOPE))
+ return tipc_own_addr;
+ if (sc == TIPC_CLUSTER_SCOPE)
+ return tipc_addr(tipc_zone(tipc_own_addr),
+ tipc_cluster(tipc_own_addr), 0);
+ return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);
+}
+
+static inline char *addr_string_fill(char *string, u32 addr)
+{
+ snprintf(string, 16, "<%u.%u.%u>",
+ tipc_zone(addr), tipc_cluster(addr), tipc_node(addr));
+ return string;
+}
+
+int tipc_addr_domain_valid(u32);
+int tipc_addr_node_valid(u32 addr);
+
+#endif
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
new file mode 100644
index 000000000000..a7b04f397c12
--- /dev/null
+++ b/net/tipc/bcast.c
@@ -0,0 +1,806 @@
+/*
+ * net/tipc/bcast.c: TIPC broadcast code
+ *
+ * Copyright (c) 2004-2006, Ericsson AB
+ * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "msg.h"
+#include "dbg.h"
+#include "link.h"
+#include "net.h"
+#include "node.h"
+#include "port.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "name_distr.h"
+#include "bearer.h"
+#include "name_table.h"
+#include "bcast.h"
+
+
+#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
+
+#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
+
+#define BCLINK_LOG_BUF_SIZE 0
+
+/**
+ * struct bcbearer_pair - a pair of bearers used by broadcast link
+ * @primary: pointer to primary bearer
+ * @secondary: pointer to secondary bearer
+ *
+ * Bearers must have same priority and same set of reachable destinations
+ * to be paired.
+ */
+
+struct bcbearer_pair {
+ struct bearer *primary;
+ struct bearer *secondary;
+};
+
+/**
+ * struct bcbearer - bearer used by broadcast link
+ * @bearer: (non-standard) broadcast bearer structure
+ * @media: (non-standard) broadcast media structure
+ * @bpairs: array of bearer pairs
+ * @bpairs_temp: array of bearer pairs used during creation of "bpairs"
+ */
+
+struct bcbearer {
+ struct bearer bearer;
+ struct media media;
+ struct bcbearer_pair bpairs[MAX_BEARERS];
+ struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
+};
+
+/**
+ * struct bclink - link used for broadcast messages
+ * @link: (non-standard) broadcast link structure
+ * @node: (non-standard) node structure representing b'cast link's peer node
+ *
+ * Handles sequence numbering, fragmentation, bundling, etc.
+ */
+
+struct bclink {
+ struct link link;
+ struct node node;
+};
+
+
+static struct bcbearer *bcbearer = NULL;
+static struct bclink *bclink = NULL;
+static struct link *bcl = NULL;
+static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
+
+char tipc_bclink_name[] = "multicast-link";
+
+
+static inline u32 buf_seqno(struct sk_buff *buf)
+{
+ return msg_seqno(buf_msg(buf));
+}
+
+static inline u32 bcbuf_acks(struct sk_buff *buf)
+{
+ return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
+}
+
+static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks)
+{
+ TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks;
+}
+
+static inline void bcbuf_decr_acks(struct sk_buff *buf)
+{
+ bcbuf_set_acks(buf, bcbuf_acks(buf) - 1);
+}
+
+
+/**
+ * bclink_set_gap - set gap according to contents of current deferred pkt queue
+ *
+ * Called with 'node' locked, bc_lock unlocked
+ */
+
+static inline void bclink_set_gap(struct node *n_ptr)
+{
+ struct sk_buff *buf = n_ptr->bclink.deferred_head;
+
+ n_ptr->bclink.gap_after = n_ptr->bclink.gap_to =
+ mod(n_ptr->bclink.last_in);
+ if (unlikely(buf != NULL))
+ n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1);
+}
+
+/**
+ * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment
+ *
+ * This mechanism endeavours to prevent all nodes in network from trying
+ * to ACK or NACK at the same time.
+ *
+ * Note: TIPC uses a different trigger to distribute ACKs than it does to
+ * distribute NACKs, but tries to use the same spacing (divide by 16).
+ */
+
+static inline int bclink_ack_allowed(u32 n)
+{
+ return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag);
+}
+
+
+/**
+ * bclink_retransmit_pkt - retransmit broadcast packets
+ * @after: sequence number of last packet to *not* retransmit
+ * @to: sequence number of last packet to retransmit
+ *
+ * Called with 'node' locked, bc_lock unlocked
+ */
+
+static void bclink_retransmit_pkt(u32 after, u32 to)
+{
+ struct sk_buff *buf;
+
+ spin_lock_bh(&bc_lock);
+ buf = bcl->first_out;
+ while (buf && less_eq(buf_seqno(buf), after)) {
+ buf = buf->next;
+ }
+ if (buf != NULL)
+ tipc_link_retransmit(bcl, buf, mod(to - after));
+ spin_unlock_bh(&bc_lock);
+}
+
+/**
+ * tipc_bclink_acknowledge - handle acknowledgement of broadcast packets
+ * @n_ptr: node that sent acknowledgement info
+ * @acked: broadcast sequence # that has been acknowledged
+ *
+ * Node is locked, bc_lock unlocked.
+ */
+
+void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked)
+{
+ struct sk_buff *crs;
+ struct sk_buff *next;
+ unsigned int released = 0;
+
+ if (less_eq(acked, n_ptr->bclink.acked))
+ return;
+
+ spin_lock_bh(&bc_lock);
+
+ /* Skip over packets that node has previously acknowledged */
+
+ crs = bcl->first_out;
+ while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) {
+ crs = crs->next;
+ }
+
+ /* Update packets that node is now acknowledging */
+
+ while (crs && less_eq(buf_seqno(crs), acked)) {
+ next = crs->next;
+ bcbuf_decr_acks(crs);
+ if (bcbuf_acks(crs) == 0) {
+ bcl->first_out = next;
+ bcl->out_queue_size--;
+ buf_discard(crs);
+ released = 1;
+ }
+ crs = next;
+ }
+ n_ptr->bclink.acked = acked;
+
+ /* Try resolving broadcast link congestion, if necessary */
+
+ if (unlikely(bcl->next_out))
+ tipc_link_push_queue(bcl);
+ if (unlikely(released && !list_empty(&bcl->waiting_ports)))
+ tipc_link_wakeup_ports(bcl, 0);
+ spin_unlock_bh(&bc_lock);
+}
+
+/**
+ * bclink_send_ack - unicast an ACK msg
+ *
+ * tipc_net_lock and node lock set
+ */
+
+static void bclink_send_ack(struct node *n_ptr)
+{
+ struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1];
+
+ if (l_ptr != NULL)
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+}
+
+/**
+ * bclink_send_nack- broadcast a NACK msg
+ *
+ * tipc_net_lock and node lock set
+ */
+
+static void bclink_send_nack(struct node *n_ptr)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+
+ if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to))
+ return;
+
+ buf = buf_acquire(INT_H_SIZE);
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
+ TIPC_OK, INT_H_SIZE, n_ptr->addr);
+ msg_set_mc_netid(msg, tipc_net_id);
+ msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in));
+ msg_set_bcgap_after(msg, n_ptr->bclink.gap_after);
+ msg_set_bcgap_to(msg, n_ptr->bclink.gap_to);
+ msg_set_bcast_tag(msg, tipc_own_tag);
+
+ if (tipc_bearer_send(&bcbearer->bearer, buf, 0)) {
+ bcl->stats.sent_nacks++;
+ buf_discard(buf);
+ } else {
+ tipc_bearer_schedule(bcl->b_ptr, bcl);
+ bcl->proto_msg_queue = buf;
+ bcl->stats.bearer_congs++;
+ }
+
+ /*
+ * Ensure we doesn't send another NACK msg to the node
+ * until 16 more deferred messages arrive from it
+ * (i.e. helps prevent all nodes from NACK'ing at same time)
+ */
+
+ n_ptr->bclink.nack_sync = tipc_own_tag;
+ }
+}
+
+/**
+ * tipc_bclink_check_gap - send a NACK if a sequence gap exists
+ *
+ * tipc_net_lock and node lock set
+ */
+
+void tipc_bclink_check_gap(struct node *n_ptr, u32 last_sent)
+{
+ if (!n_ptr->bclink.supported ||
+ less_eq(last_sent, mod(n_ptr->bclink.last_in)))
+ return;
+
+ bclink_set_gap(n_ptr);
+ if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to)
+ n_ptr->bclink.gap_to = last_sent;
+ bclink_send_nack(n_ptr);
+}
+
+/**
+ * tipc_bclink_peek_nack - process a NACK msg meant for another node
+ *
+ * Only tipc_net_lock set.
+ */
+
+void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to)
+{
+ struct node *n_ptr = tipc_node_find(dest);
+ u32 my_after, my_to;
+
+ if (unlikely(!n_ptr || !tipc_node_is_up(n_ptr)))
+ return;
+ tipc_node_lock(n_ptr);
+ /*
+ * Modify gap to suppress unnecessary NACKs from this node
+ */
+ my_after = n_ptr->bclink.gap_after;
+ my_to = n_ptr->bclink.gap_to;
+
+ if (less_eq(gap_after, my_after)) {
+ if (less(my_after, gap_to) && less(gap_to, my_to))
+ n_ptr->bclink.gap_after = gap_to;
+ else if (less_eq(my_to, gap_to))
+ n_ptr->bclink.gap_to = n_ptr->bclink.gap_after;
+ } else if (less_eq(gap_after, my_to)) {
+ if (less_eq(my_to, gap_to))
+ n_ptr->bclink.gap_to = gap_after;
+ } else {
+ /*
+ * Expand gap if missing bufs not in deferred queue:
+ */
+ struct sk_buff *buf = n_ptr->bclink.deferred_head;
+ u32 prev = n_ptr->bclink.gap_to;
+
+ for (; buf; buf = buf->next) {
+ u32 seqno = buf_seqno(buf);
+
+ if (mod(seqno - prev) != 1)
+ buf = NULL;
+ if (seqno == gap_after)
+ break;
+ prev = seqno;
+ }
+ if (buf == NULL)
+ n_ptr->bclink.gap_to = gap_after;
+ }
+ /*
+ * Some nodes may send a complementary NACK now:
+ */
+ if (bclink_ack_allowed(sender_tag + 1)) {
+ if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) {
+ bclink_send_nack(n_ptr);
+ bclink_set_gap(n_ptr);
+ }
+ }
+ tipc_node_unlock(n_ptr);
+}
+
+/**
+ * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster
+ */
+
+int tipc_bclink_send_msg(struct sk_buff *buf)
+{
+ int res;
+
+ spin_lock_bh(&bc_lock);
+
+ res = tipc_link_send_buf(bcl, buf);
+ if (unlikely(res == -ELINKCONG))
+ buf_discard(buf);
+ else
+ bcl->stats.sent_info++;
+
+ if (bcl->out_queue_size > bcl->stats.max_queue_sz)
+ bcl->stats.max_queue_sz = bcl->out_queue_size;
+ bcl->stats.queue_sz_counts++;
+ bcl->stats.accu_queue_sz += bcl->out_queue_size;
+
+ spin_unlock_bh(&bc_lock);
+ return res;
+}
+
+/**
+ * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards
+ *
+ * tipc_net_lock is read_locked, no other locks set
+ */
+
+void tipc_bclink_recv_pkt(struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ struct node* node = tipc_node_find(msg_prevnode(msg));
+ u32 next_in;
+ u32 seqno;
+ struct sk_buff *deferred;
+
+ msg_dbg(msg, "<BC<<<");
+
+ if (unlikely(!node || !tipc_node_is_up(node) || !node->bclink.supported ||
+ (msg_mc_netid(msg) != tipc_net_id))) {
+ buf_discard(buf);
+ return;
+ }
+
+ if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) {
+ msg_dbg(msg, "<BCNACK<<<");
+ if (msg_destnode(msg) == tipc_own_addr) {
+ tipc_node_lock(node);
+ tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
+ tipc_node_unlock(node);
+ bcl->stats.recv_nacks++;
+ bclink_retransmit_pkt(msg_bcgap_after(msg),
+ msg_bcgap_to(msg));
+ } else {
+ tipc_bclink_peek_nack(msg_destnode(msg),
+ msg_bcast_tag(msg),
+ msg_bcgap_after(msg),
+ msg_bcgap_to(msg));
+ }
+ buf_discard(buf);
+ return;
+ }
+
+ tipc_node_lock(node);
+receive:
+ deferred = node->bclink.deferred_head;
+ next_in = mod(node->bclink.last_in + 1);
+ seqno = msg_seqno(msg);
+
+ if (likely(seqno == next_in)) {
+ bcl->stats.recv_info++;
+ node->bclink.last_in++;
+ bclink_set_gap(node);
+ if (unlikely(bclink_ack_allowed(seqno))) {
+ bclink_send_ack(node);
+ bcl->stats.sent_acks++;
+ }
+ if (likely(msg_isdata(msg))) {
+ tipc_node_unlock(node);
+ tipc_port_recv_mcast(buf, NULL);
+ } else if (msg_user(msg) == MSG_BUNDLER) {
+ bcl->stats.recv_bundles++;
+ bcl->stats.recv_bundled += msg_msgcnt(msg);
+ tipc_node_unlock(node);
+ tipc_link_recv_bundle(buf);
+ } else if (msg_user(msg) == MSG_FRAGMENTER) {
+ bcl->stats.recv_fragments++;
+ if (tipc_link_recv_fragment(&node->bclink.defragm,
+ &buf, &msg))
+ bcl->stats.recv_fragmented++;
+ tipc_node_unlock(node);
+ tipc_net_route_msg(buf);
+ } else {
+ tipc_node_unlock(node);
+ tipc_net_route_msg(buf);
+ }
+ if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) {
+ tipc_node_lock(node);
+ buf = deferred;
+ msg = buf_msg(buf);
+ node->bclink.deferred_head = deferred->next;
+ goto receive;
+ }
+ return;
+ } else if (less(next_in, seqno)) {
+ u32 gap_after = node->bclink.gap_after;
+ u32 gap_to = node->bclink.gap_to;
+
+ if (tipc_link_defer_pkt(&node->bclink.deferred_head,
+ &node->bclink.deferred_tail,
+ buf)) {
+ node->bclink.nack_sync++;
+ bcl->stats.deferred_recv++;
+ if (seqno == mod(gap_after + 1))
+ node->bclink.gap_after = seqno;
+ else if (less(gap_after, seqno) && less(seqno, gap_to))
+ node->bclink.gap_to = seqno;
+ }
+ if (bclink_ack_allowed(node->bclink.nack_sync)) {
+ if (gap_to != gap_after)
+ bclink_send_nack(node);
+ bclink_set_gap(node);
+ }
+ } else {
+ bcl->stats.duplicates++;
+ buf_discard(buf);
+ }
+ tipc_node_unlock(node);
+}
+
+u32 tipc_bclink_get_last_sent(void)
+{
+ u32 last_sent = mod(bcl->next_out_no - 1);
+
+ if (bcl->next_out)
+ last_sent = mod(buf_seqno(bcl->next_out) - 1);
+ return last_sent;
+}
+
+u32 tipc_bclink_acks_missing(struct node *n_ptr)
+{
+ return (n_ptr->bclink.supported &&
+ (tipc_bclink_get_last_sent() != n_ptr->bclink.acked));
+}
+
+
+/**
+ * tipc_bcbearer_send - send a packet through the broadcast pseudo-bearer
+ *
+ * Send through as many bearers as necessary to reach all nodes
+ * that support TIPC multicasting.
+ *
+ * Returns 0 if packet sent successfully, non-zero if not
+ */
+
+int tipc_bcbearer_send(struct sk_buff *buf,
+ struct tipc_bearer *unused1,
+ struct tipc_media_addr *unused2)
+{
+ static int send_count = 0;
+
+ struct node_map remains;
+ struct node_map remains_new;
+ int bp_index;
+ int swap_time;
+
+ /* Prepare buffer for broadcasting (if first time trying to send it) */
+
+ if (likely(!msg_non_seq(buf_msg(buf)))) {
+ struct tipc_msg *msg;
+
+ assert(tipc_cltr_bcast_nodes.count != 0);
+ bcbuf_set_acks(buf, tipc_cltr_bcast_nodes.count);
+ msg = buf_msg(buf);
+ msg_set_non_seq(msg);
+ msg_set_mc_netid(msg, tipc_net_id);
+ }
+
+ /* Determine if bearer pairs should be swapped following this attempt */
+
+ if ((swap_time = (++send_count >= 10)))
+ send_count = 0;
+
+ /* Send buffer over bearers until all targets reached */
+
+ remains = tipc_cltr_bcast_nodes;
+
+ for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
+ struct bearer *p = bcbearer->bpairs[bp_index].primary;
+ struct bearer *s = bcbearer->bpairs[bp_index].secondary;
+
+ if (!p)
+ break; /* no more bearers to try */
+
+ tipc_nmap_diff(&remains, &p->nodes, &remains_new);
+ if (remains_new.count == remains.count)
+ continue; /* bearer pair doesn't add anything */
+
+ if (!p->publ.blocked &&
+ !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) {
+ if (swap_time && s && !s->publ.blocked)
+ goto swap;
+ else
+ goto update;
+ }
+
+ if (!s || s->publ.blocked ||
+ s->media->send_msg(buf, &s->publ, &s->media->bcast_addr))
+ continue; /* unable to send using bearer pair */
+swap:
+ bcbearer->bpairs[bp_index].primary = s;
+ bcbearer->bpairs[bp_index].secondary = p;
+update:
+ if (remains_new.count == 0)
+ return TIPC_OK;
+
+ remains = remains_new;
+ }
+
+ /* Unable to reach all targets */
+
+ bcbearer->bearer.publ.blocked = 1;
+ bcl->stats.bearer_congs++;
+ return ~TIPC_OK;
+}
+
+/**
+ * tipc_bcbearer_sort - create sets of bearer pairs used by broadcast bearer
+ */
+
+void tipc_bcbearer_sort(void)
+{
+ struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp;
+ struct bcbearer_pair *bp_curr;
+ int b_index;
+ int pri;
+
+ spin_lock_bh(&bc_lock);
+
+ /* Group bearers by priority (can assume max of two per priority) */
+
+ memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
+
+ for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
+ struct bearer *b = &tipc_bearers[b_index];
+
+ if (!b->active || !b->nodes.count)
+ continue;
+
+ if (!bp_temp[b->priority].primary)
+ bp_temp[b->priority].primary = b;
+ else
+ bp_temp[b->priority].secondary = b;
+ }
+
+ /* Create array of bearer pairs for broadcasting */
+
+ bp_curr = bcbearer->bpairs;
+ memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs));
+
+ for (pri = TIPC_MAX_LINK_PRI; pri >= 0; pri--) {
+
+ if (!bp_temp[pri].primary)
+ continue;
+
+ bp_curr->primary = bp_temp[pri].primary;
+
+ if (bp_temp[pri].secondary) {
+ if (tipc_nmap_equal(&bp_temp[pri].primary->nodes,
+ &bp_temp[pri].secondary->nodes)) {
+ bp_curr->secondary = bp_temp[pri].secondary;
+ } else {
+ bp_curr++;
+ bp_curr->primary = bp_temp[pri].secondary;
+ }
+ }
+
+ bp_curr++;
+ }
+
+ spin_unlock_bh(&bc_lock);
+}
+
+/**
+ * tipc_bcbearer_push - resolve bearer congestion
+ *
+ * Forces bclink to push out any unsent packets, until all packets are gone
+ * or congestion reoccurs.
+ * No locks set when function called
+ */
+
+void tipc_bcbearer_push(void)
+{
+ struct bearer *b_ptr;
+
+ spin_lock_bh(&bc_lock);
+ b_ptr = &bcbearer->bearer;
+ if (b_ptr->publ.blocked) {
+ b_ptr->publ.blocked = 0;
+ tipc_bearer_lock_push(b_ptr);
+ }
+ spin_unlock_bh(&bc_lock);
+}
+
+
+int tipc_bclink_stats(char *buf, const u32 buf_size)
+{
+ struct print_buf pb;
+
+ if (!bcl)
+ return 0;
+
+ tipc_printbuf_init(&pb, buf, buf_size);
+
+ spin_lock_bh(&bc_lock);
+
+ tipc_printf(&pb, "Link <%s>\n"
+ " Window:%u packets\n",
+ bcl->name, bcl->queue_limit[0]);
+ tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
+ bcl->stats.recv_info,
+ bcl->stats.recv_fragments,
+ bcl->stats.recv_fragmented,
+ bcl->stats.recv_bundles,
+ bcl->stats.recv_bundled);
+ tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
+ bcl->stats.sent_info,
+ bcl->stats.sent_fragments,
+ bcl->stats.sent_fragmented,
+ bcl->stats.sent_bundles,
+ bcl->stats.sent_bundled);
+ tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n",
+ bcl->stats.recv_nacks,
+ bcl->stats.deferred_recv,
+ bcl->stats.duplicates);
+ tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n",
+ bcl->stats.sent_nacks,
+ bcl->stats.sent_acks,
+ bcl->stats.retransmitted);
+ tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
+ bcl->stats.bearer_congs,
+ bcl->stats.link_congs,
+ bcl->stats.max_queue_sz,
+ bcl->stats.queue_sz_counts
+ ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts)
+ : 0);
+
+ spin_unlock_bh(&bc_lock);
+ return tipc_printbuf_validate(&pb);
+}
+
+int tipc_bclink_reset_stats(void)
+{
+ if (!bcl)
+ return -ENOPROTOOPT;
+
+ spin_lock_bh(&bc_lock);
+ memset(&bcl->stats, 0, sizeof(bcl->stats));
+ spin_unlock_bh(&bc_lock);
+ return TIPC_OK;
+}
+
+int tipc_bclink_set_queue_limits(u32 limit)
+{
+ if (!bcl)
+ return -ENOPROTOOPT;
+ if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
+ return -EINVAL;
+
+ spin_lock_bh(&bc_lock);
+ tipc_link_set_queue_limits(bcl, limit);
+ spin_unlock_bh(&bc_lock);
+ return TIPC_OK;
+}
+
+int tipc_bclink_init(void)
+{
+ bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC);
+ bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
+ if (!bcbearer || !bclink) {
+ nomem:
+ warn("Memory squeeze; Failed to create multicast link\n");
+ kfree(bcbearer);
+ bcbearer = NULL;
+ kfree(bclink);
+ bclink = NULL;
+ return -ENOMEM;
+ }
+
+ memset(bcbearer, 0, sizeof(struct bcbearer));
+ INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
+ bcbearer->bearer.media = &bcbearer->media;
+ bcbearer->media.send_msg = tipc_bcbearer_send;
+ sprintf(bcbearer->media.name, "tipc-multicast");
+
+ bcl = &bclink->link;
+ memset(bclink, 0, sizeof(struct bclink));
+ INIT_LIST_HEAD(&bcl->waiting_ports);
+ bcl->next_out_no = 1;
+ bclink->node.lock = SPIN_LOCK_UNLOCKED;
+ bcl->owner = &bclink->node;
+ bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
+ tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
+ bcl->b_ptr = &bcbearer->bearer;
+ bcl->state = WORKING_WORKING;
+ sprintf(bcl->name, tipc_bclink_name);
+
+ if (BCLINK_LOG_BUF_SIZE) {
+ char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC);
+
+ if (!pb)
+ goto nomem;
+ tipc_printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE);
+ }
+
+ return TIPC_OK;
+}
+
+void tipc_bclink_stop(void)
+{
+ spin_lock_bh(&bc_lock);
+ if (bcbearer) {
+ tipc_link_stop(bcl);
+ if (BCLINK_LOG_BUF_SIZE)
+ kfree(bcl->print_buf.buf);
+ bcl = NULL;
+ kfree(bclink);
+ bclink = NULL;
+ kfree(bcbearer);
+ bcbearer = NULL;
+ }
+ spin_unlock_bh(&bc_lock);
+}
+
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
new file mode 100644
index 000000000000..0e3be2ab3307
--- /dev/null
+++ b/net/tipc/bcast.h
@@ -0,0 +1,223 @@
+/*
+ * net/tipc/bcast.h: Include file for TIPC broadcast code
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_BCAST_H
+#define _TIPC_BCAST_H
+
+#define MAX_NODES 4096
+#define WSIZE 32
+
+/**
+ * struct node_map - set of node identifiers
+ * @count: # of nodes in set
+ * @map: bitmap of node identifiers that are in the set
+ */
+
+struct node_map {
+ u32 count;
+ u32 map[MAX_NODES / WSIZE];
+};
+
+
+#define PLSIZE 32
+
+/**
+ * struct port_list - set of node local destination ports
+ * @count: # of ports in set (only valid for first entry in list)
+ * @next: pointer to next entry in list
+ * @ports: array of port references
+ */
+
+struct port_list {
+ int count;
+ struct port_list *next;
+ u32 ports[PLSIZE];
+};
+
+
+struct node;
+
+extern char tipc_bclink_name[];
+
+
+/**
+ * nmap_get - determine if node exists in a node map
+ */
+
+static inline int tipc_nmap_get(struct node_map *nm_ptr, u32 node)
+{
+ int n = tipc_node(node);
+ int w = n / WSIZE;
+ int b = n % WSIZE;
+
+ return nm_ptr->map[w] & (1 << b);
+}
+
+/**
+ * nmap_add - add a node to a node map
+ */
+
+static inline void tipc_nmap_add(struct node_map *nm_ptr, u32 node)
+{
+ int n = tipc_node(node);
+ int w = n / WSIZE;
+ u32 mask = (1 << (n % WSIZE));
+
+ if ((nm_ptr->map[w] & mask) == 0) {
+ nm_ptr->count++;
+ nm_ptr->map[w] |= mask;
+ }
+}
+
+/**
+ * nmap_remove - remove a node from a node map
+ */
+
+static inline void tipc_nmap_remove(struct node_map *nm_ptr, u32 node)
+{
+ int n = tipc_node(node);
+ int w = n / WSIZE;
+ u32 mask = (1 << (n % WSIZE));
+
+ if ((nm_ptr->map[w] & mask) != 0) {
+ nm_ptr->map[w] &= ~mask;
+ nm_ptr->count--;
+ }
+}
+
+/**
+ * nmap_equal - test for equality of node maps
+ */
+
+static inline int tipc_nmap_equal(struct node_map *nm_a, struct node_map *nm_b)
+{
+ return !memcmp(nm_a, nm_b, sizeof(*nm_a));
+}
+
+/**
+ * nmap_diff - find differences between node maps
+ * @nm_a: input node map A
+ * @nm_b: input node map B
+ * @nm_diff: output node map A-B (i.e. nodes of A that are not in B)
+ */
+
+static inline void tipc_nmap_diff(struct node_map *nm_a, struct node_map *nm_b,
+ struct node_map *nm_diff)
+{
+ int stop = sizeof(nm_a->map) / sizeof(u32);
+ int w;
+ int b;
+ u32 map;
+
+ memset(nm_diff, 0, sizeof(*nm_diff));
+ for (w = 0; w < stop; w++) {
+ map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]);
+ nm_diff->map[w] = map;
+ if (map != 0) {
+ for (b = 0 ; b < WSIZE; b++) {
+ if (map & (1 << b))
+ nm_diff->count++;
+ }
+ }
+ }
+}
+
+/**
+ * port_list_add - add a port to a port list, ensuring no duplicates
+ */
+
+static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port)
+{
+ struct port_list *item = pl_ptr;
+ int i;
+ int item_sz = PLSIZE;
+ int cnt = pl_ptr->count;
+
+ for (; ; cnt -= item_sz, item = item->next) {
+ if (cnt < PLSIZE)
+ item_sz = cnt;
+ for (i = 0; i < item_sz; i++)
+ if (item->ports[i] == port)
+ return;
+ if (i < PLSIZE) {
+ item->ports[i] = port;
+ pl_ptr->count++;
+ return;
+ }
+ if (!item->next) {
+ item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
+ if (!item->next) {
+ warn("Memory squeeze: multicast destination port list is incomplete\n");
+ return;
+ }
+ item->next->next = NULL;
+ }
+ }
+}
+
+/**
+ * port_list_free - free dynamically created entries in port_list chain
+ *
+ * Note: First item is on stack, so it doesn't need to be released
+ */
+
+static inline void tipc_port_list_free(struct port_list *pl_ptr)
+{
+ struct port_list *item;
+ struct port_list *next;
+
+ for (item = pl_ptr->next; item; item = next) {
+ next = item->next;
+ kfree(item);
+ }
+}
+
+
+int tipc_bclink_init(void);
+void tipc_bclink_stop(void);
+void tipc_bclink_acknowledge(struct node *n_ptr, u32 acked);
+int tipc_bclink_send_msg(struct sk_buff *buf);
+void tipc_bclink_recv_pkt(struct sk_buff *buf);
+u32 tipc_bclink_get_last_sent(void);
+u32 tipc_bclink_acks_missing(struct node *n_ptr);
+void tipc_bclink_check_gap(struct node *n_ptr, u32 seqno);
+int tipc_bclink_stats(char *stats_buf, const u32 buf_size);
+int tipc_bclink_reset_stats(void);
+int tipc_bclink_set_queue_limits(u32 limit);
+void tipc_bcbearer_sort(void);
+void tipc_bcbearer_push(void);
+
+#endif
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
new file mode 100644
index 000000000000..64dcb0f3a8b2
--- /dev/null
+++ b/net/tipc/bearer.c
@@ -0,0 +1,699 @@
+/*
+ * net/tipc/bearer.c: TIPC bearer code
+ *
+ * Copyright (c) 1996-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include "dbg.h"
+#include "bearer.h"
+#include "link.h"
+#include "port.h"
+#include "discover.h"
+#include "bcast.h"
+
+#define MAX_ADDR_STR 32
+
+static struct media *media_list = 0;
+static u32 media_count = 0;
+
+struct bearer *tipc_bearers = 0;
+
+/**
+ * media_name_valid - validate media name
+ *
+ * Returns 1 if media name is valid, otherwise 0.
+ */
+
+static int media_name_valid(const char *name)
+{
+ u32 len;
+
+ len = strlen(name);
+ if ((len + 1) > TIPC_MAX_MEDIA_NAME)
+ return 0;
+ return (strspn(name, tipc_alphabet) == len);
+}
+
+/**
+ * media_find - locates specified media object by name
+ */
+
+static struct media *media_find(const char *name)
+{
+ struct media *m_ptr;
+ u32 i;
+
+ for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
+ if (!strcmp(m_ptr->name, name))
+ return m_ptr;
+ }
+ return 0;
+}
+
+/**
+ * tipc_register_media - register a media type
+ *
+ * Bearers for this media type must be activated separately at a later stage.
+ */
+
+int tipc_register_media(u32 media_type,
+ char *name,
+ int (*enable)(struct tipc_bearer *),
+ void (*disable)(struct tipc_bearer *),
+ int (*send_msg)(struct sk_buff *,
+ struct tipc_bearer *,
+ struct tipc_media_addr *),
+ char *(*addr2str)(struct tipc_media_addr *a,
+ char *str_buf, int str_size),
+ struct tipc_media_addr *bcast_addr,
+ const u32 bearer_priority,
+ const u32 link_tolerance, /* [ms] */
+ const u32 send_window_limit)
+{
+ struct media *m_ptr;
+ u32 media_id;
+ u32 i;
+ int res = -EINVAL;
+
+ write_lock_bh(&tipc_net_lock);
+ if (!media_list)
+ goto exit;
+
+ if (!media_name_valid(name)) {
+ warn("Media registration error: illegal name <%s>\n", name);
+ goto exit;
+ }
+ if (!bcast_addr) {
+ warn("Media registration error: no broadcast address supplied\n");
+ goto exit;
+ }
+ if ((bearer_priority < TIPC_MIN_LINK_PRI) &&
+ (bearer_priority > TIPC_MAX_LINK_PRI)) {
+ warn("Media registration error: priority %u\n", bearer_priority);
+ goto exit;
+ }
+ if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
+ (link_tolerance > TIPC_MAX_LINK_TOL)) {
+ warn("Media registration error: tolerance %u\n", link_tolerance);
+ goto exit;
+ }
+
+ media_id = media_count++;
+ if (media_id >= MAX_MEDIA) {
+ warn("Attempt to register more than %u media\n", MAX_MEDIA);
+ media_count--;
+ goto exit;
+ }
+ for (i = 0; i < media_id; i++) {
+ if (media_list[i].type_id == media_type) {
+ warn("Attempt to register second media with type %u\n",
+ media_type);
+ media_count--;
+ goto exit;
+ }
+ if (!strcmp(name, media_list[i].name)) {
+ warn("Attempt to re-register media name <%s>\n", name);
+ media_count--;
+ goto exit;
+ }
+ }
+
+ m_ptr = &media_list[media_id];
+ m_ptr->type_id = media_type;
+ m_ptr->send_msg = send_msg;
+ m_ptr->enable_bearer = enable;
+ m_ptr->disable_bearer = disable;
+ m_ptr->addr2str = addr2str;
+ memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
+ m_ptr->bcast = 1;
+ strcpy(m_ptr->name, name);
+ m_ptr->priority = bearer_priority;
+ m_ptr->tolerance = link_tolerance;
+ m_ptr->window = send_window_limit;
+ dbg("Media <%s> registered\n", name);
+ res = 0;
+exit:
+ write_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+/**
+ * tipc_media_addr_printf - record media address in print buffer
+ */
+
+void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
+{
+ struct media *m_ptr;
+ u32 media_type;
+ u32 i;
+
+ media_type = ntohl(a->type);
+ for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
+ if (m_ptr->type_id == media_type)
+ break;
+ }
+
+ if ((i < media_count) && (m_ptr->addr2str != NULL)) {
+ char addr_str[MAX_ADDR_STR];
+
+ tipc_printf(pb, "%s(%s) ", m_ptr->name,
+ m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
+ } else {
+ unchar *addr = (unchar *)&a->dev_addr;
+
+ tipc_printf(pb, "UNKNOWN(%u):", media_type);
+ for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
+ tipc_printf(pb, "%02x ", addr[i]);
+ }
+ }
+}
+
+/**
+ * tipc_media_get_names - record names of registered media in buffer
+ */
+
+struct sk_buff *tipc_media_get_names(void)
+{
+ struct sk_buff *buf;
+ struct media *m_ptr;
+ int i;
+
+ buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
+ if (!buf)
+ return NULL;
+
+ read_lock_bh(&tipc_net_lock);
+ for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
+ tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
+ strlen(m_ptr->name) + 1);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ return buf;
+}
+
+/**
+ * bearer_name_validate - validate & (optionally) deconstruct bearer name
+ * @name - ptr to bearer name string
+ * @name_parts - ptr to area for bearer name components (or NULL if not needed)
+ *
+ * Returns 1 if bearer name is valid, otherwise 0.
+ */
+
+static int bearer_name_validate(const char *name,
+ struct bearer_name *name_parts)
+{
+ char name_copy[TIPC_MAX_BEARER_NAME];
+ char *media_name;
+ char *if_name;
+ u32 media_len;
+ u32 if_len;
+
+ /* copy bearer name & ensure length is OK */
+
+ name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
+ /* need above in case non-Posix strncpy() doesn't pad with nulls */
+ strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
+ if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
+ return 0;
+
+ /* ensure all component parts of bearer name are present */
+
+ media_name = name_copy;
+ if ((if_name = strchr(media_name, ':')) == NULL)
+ return 0;
+ *(if_name++) = 0;
+ media_len = if_name - media_name;
+ if_len = strlen(if_name) + 1;
+
+ /* validate component parts of bearer name */
+
+ if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
+ (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
+ (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
+ (strspn(if_name, tipc_alphabet) != (if_len - 1)))
+ return 0;
+
+ /* return bearer name components, if necessary */
+
+ if (name_parts) {
+ strcpy(name_parts->media_name, media_name);
+ strcpy(name_parts->if_name, if_name);
+ }
+ return 1;
+}
+
+/**
+ * bearer_find - locates bearer object with matching bearer name
+ */
+
+static struct bearer *bearer_find(const char *name)
+{
+ struct bearer *b_ptr;
+ u32 i;
+
+ for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
+ if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
+ return b_ptr;
+ }
+ return 0;
+}
+
+/**
+ * tipc_bearer_find_interface - locates bearer object with matching interface name
+ */
+
+struct bearer *tipc_bearer_find_interface(const char *if_name)
+{
+ struct bearer *b_ptr;
+ char *b_if_name;
+ u32 i;
+
+ for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
+ if (!b_ptr->active)
+ continue;
+ b_if_name = strchr(b_ptr->publ.name, ':') + 1;
+ if (!strcmp(b_if_name, if_name))
+ return b_ptr;
+ }
+ return 0;
+}
+
+/**
+ * tipc_bearer_get_names - record names of bearers in buffer
+ */
+
+struct sk_buff *tipc_bearer_get_names(void)
+{
+ struct sk_buff *buf;
+ struct media *m_ptr;
+ struct bearer *b_ptr;
+ int i, j;
+
+ buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
+ if (!buf)
+ return NULL;
+
+ read_lock_bh(&tipc_net_lock);
+ for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
+ for (j = 0; j < MAX_BEARERS; j++) {
+ b_ptr = &tipc_bearers[j];
+ if (b_ptr->active && (b_ptr->media == m_ptr)) {
+ tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
+ b_ptr->publ.name,
+ strlen(b_ptr->publ.name) + 1);
+ }
+ }
+ }
+ read_unlock_bh(&tipc_net_lock);
+ return buf;
+}
+
+void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest)
+{
+ tipc_nmap_add(&b_ptr->nodes, dest);
+ tipc_disc_update_link_req(b_ptr->link_req);
+ tipc_bcbearer_sort();
+}
+
+void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest)
+{
+ tipc_nmap_remove(&b_ptr->nodes, dest);
+ tipc_disc_update_link_req(b_ptr->link_req);
+ tipc_bcbearer_sort();
+}
+
+/*
+ * bearer_push(): Resolve bearer congestion. Force the waiting
+ * links to push out their unsent packets, one packet per link
+ * per iteration, until all packets are gone or congestion reoccurs.
+ * 'tipc_net_lock' is read_locked when this function is called
+ * bearer.lock must be taken before calling
+ * Returns binary true(1) ore false(0)
+ */
+static int bearer_push(struct bearer *b_ptr)
+{
+ u32 res = TIPC_OK;
+ struct link *ln, *tln;
+
+ if (b_ptr->publ.blocked)
+ return 0;
+
+ while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
+ list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
+ res = tipc_link_push_packet(ln);
+ if (res == PUSH_FAILED)
+ break;
+ if (res == PUSH_FINISHED)
+ list_move_tail(&ln->link_list, &b_ptr->links);
+ }
+ }
+ return list_empty(&b_ptr->cong_links);
+}
+
+void tipc_bearer_lock_push(struct bearer *b_ptr)
+{
+ int res;
+
+ spin_lock_bh(&b_ptr->publ.lock);
+ res = bearer_push(b_ptr);
+ spin_unlock_bh(&b_ptr->publ.lock);
+ if (res)
+ tipc_bcbearer_push();
+}
+
+
+/*
+ * Interrupt enabling new requests after bearer congestion or blocking:
+ * See bearer_send().
+ */
+void tipc_continue(struct tipc_bearer *tb_ptr)
+{
+ struct bearer *b_ptr = (struct bearer *)tb_ptr;
+
+ spin_lock_bh(&b_ptr->publ.lock);
+ b_ptr->continue_count++;
+ if (!list_empty(&b_ptr->cong_links))
+ tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
+ b_ptr->publ.blocked = 0;
+ spin_unlock_bh(&b_ptr->publ.lock);
+}
+
+/*
+ * Schedule link for sending of messages after the bearer
+ * has been deblocked by 'continue()'. This method is called
+ * when somebody tries to send a message via this link while
+ * the bearer is congested. 'tipc_net_lock' is in read_lock here
+ * bearer.lock is busy
+ */
+
+static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
+{
+ list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
+}
+
+/*
+ * Schedule link for sending of messages after the bearer
+ * has been deblocked by 'continue()'. This method is called
+ * when somebody tries to send a message via this link while
+ * the bearer is congested. 'tipc_net_lock' is in read_lock here,
+ * bearer.lock is free
+ */
+
+void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
+{
+ spin_lock_bh(&b_ptr->publ.lock);
+ tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
+ spin_unlock_bh(&b_ptr->publ.lock);
+}
+
+
+/*
+ * tipc_bearer_resolve_congestion(): Check if there is bearer congestion,
+ * and if there is, try to resolve it before returning.
+ * 'tipc_net_lock' is read_locked when this function is called
+ */
+int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
+{
+ int res = 1;
+
+ if (list_empty(&b_ptr->cong_links))
+ return 1;
+ spin_lock_bh(&b_ptr->publ.lock);
+ if (!bearer_push(b_ptr)) {
+ tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
+ res = 0;
+ }
+ spin_unlock_bh(&b_ptr->publ.lock);
+ return res;
+}
+
+
+/**
+ * tipc_enable_bearer - enable bearer with the given name
+ */
+
+int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
+{
+ struct bearer *b_ptr;
+ struct media *m_ptr;
+ struct bearer_name b_name;
+ char addr_string[16];
+ u32 bearer_id;
+ u32 with_this_prio;
+ u32 i;
+ int res = -EINVAL;
+
+ if (tipc_mode != TIPC_NET_MODE)
+ return -ENOPROTOOPT;
+
+ if (!bearer_name_validate(name, &b_name) ||
+ !tipc_addr_domain_valid(bcast_scope) ||
+ !in_scope(bcast_scope, tipc_own_addr))
+ return -EINVAL;
+
+ if ((priority < TIPC_MIN_LINK_PRI ||
+ priority > TIPC_MAX_LINK_PRI) &&
+ (priority != TIPC_MEDIA_LINK_PRI))
+ return -EINVAL;
+
+ write_lock_bh(&tipc_net_lock);
+ if (!tipc_bearers)
+ goto failed;
+
+ m_ptr = media_find(b_name.media_name);
+ if (!m_ptr) {
+ warn("No media <%s>\n", b_name.media_name);
+ goto failed;
+ }
+
+ if (priority == TIPC_MEDIA_LINK_PRI)
+ priority = m_ptr->priority;
+
+restart:
+ bearer_id = MAX_BEARERS;
+ with_this_prio = 1;
+ for (i = MAX_BEARERS; i-- != 0; ) {
+ if (!tipc_bearers[i].active) {
+ bearer_id = i;
+ continue;
+ }
+ if (!strcmp(name, tipc_bearers[i].publ.name)) {
+ warn("Bearer <%s> already enabled\n", name);
+ goto failed;
+ }
+ if ((tipc_bearers[i].priority == priority) &&
+ (++with_this_prio > 2)) {
+ if (priority-- == 0) {
+ warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
+ name, priority + 1, priority);
+ goto failed;
+ }
+ warn("Third bearer <%s> with priority %u, lowering to %u\n",
+ name, priority + 1, priority);
+ goto restart;
+ }
+ }
+ if (bearer_id >= MAX_BEARERS) {
+ warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
+ goto failed;
+ }
+
+ b_ptr = &tipc_bearers[bearer_id];
+ memset(b_ptr, 0, sizeof(struct bearer));
+
+ strcpy(b_ptr->publ.name, name);
+ res = m_ptr->enable_bearer(&b_ptr->publ);
+ if (res) {
+ warn("Failed to enable bearer <%s>\n", name);
+ goto failed;
+ }
+
+ b_ptr->identity = bearer_id;
+ b_ptr->media = m_ptr;
+ b_ptr->net_plane = bearer_id + 'A';
+ b_ptr->active = 1;
+ b_ptr->detect_scope = bcast_scope;
+ b_ptr->priority = priority;
+ INIT_LIST_HEAD(&b_ptr->cong_links);
+ INIT_LIST_HEAD(&b_ptr->links);
+ if (m_ptr->bcast) {
+ b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
+ bcast_scope, 2);
+ }
+ b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
+ write_unlock_bh(&tipc_net_lock);
+ info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
+ name, addr_string_fill(addr_string, bcast_scope), priority);
+ return 0;
+failed:
+ write_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+/**
+ * tipc_block_bearer(): Block the bearer with the given name,
+ * and reset all its links
+ */
+
+int tipc_block_bearer(const char *name)
+{
+ struct bearer *b_ptr = 0;
+ struct link *l_ptr;
+ struct link *temp_l_ptr;
+
+ if (tipc_mode != TIPC_NET_MODE)
+ return -ENOPROTOOPT;
+
+ read_lock_bh(&tipc_net_lock);
+ b_ptr = bearer_find(name);
+ if (!b_ptr) {
+ warn("Attempt to block unknown bearer <%s>\n", name);
+ read_unlock_bh(&tipc_net_lock);
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&b_ptr->publ.lock);
+ b_ptr->publ.blocked = 1;
+ list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
+ struct node *n_ptr = l_ptr->owner;
+
+ spin_lock_bh(&n_ptr->lock);
+ tipc_link_reset(l_ptr);
+ spin_unlock_bh(&n_ptr->lock);
+ }
+ spin_unlock_bh(&b_ptr->publ.lock);
+ read_unlock_bh(&tipc_net_lock);
+ info("Blocked bearer <%s>\n", name);
+ return TIPC_OK;
+}
+
+/**
+ * bearer_disable -
+ *
+ * Note: This routine assumes caller holds tipc_net_lock.
+ */
+
+static int bearer_disable(const char *name)
+{
+ struct bearer *b_ptr;
+ struct link *l_ptr;
+ struct link *temp_l_ptr;
+
+ if (tipc_mode != TIPC_NET_MODE)
+ return -ENOPROTOOPT;
+
+ b_ptr = bearer_find(name);
+ if (!b_ptr) {
+ warn("Attempt to disable unknown bearer <%s>\n", name);
+ return -EINVAL;
+ }
+
+ tipc_disc_stop_link_req(b_ptr->link_req);
+ spin_lock_bh(&b_ptr->publ.lock);
+ b_ptr->link_req = NULL;
+ b_ptr->publ.blocked = 1;
+ if (b_ptr->media->disable_bearer) {
+ spin_unlock_bh(&b_ptr->publ.lock);
+ write_unlock_bh(&tipc_net_lock);
+ b_ptr->media->disable_bearer(&b_ptr->publ);
+ write_lock_bh(&tipc_net_lock);
+ spin_lock_bh(&b_ptr->publ.lock);
+ }
+ list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
+ tipc_link_delete(l_ptr);
+ }
+ spin_unlock_bh(&b_ptr->publ.lock);
+ info("Disabled bearer <%s>\n", name);
+ memset(b_ptr, 0, sizeof(struct bearer));
+ return TIPC_OK;
+}
+
+int tipc_disable_bearer(const char *name)
+{
+ int res;
+
+ write_lock_bh(&tipc_net_lock);
+ res = bearer_disable(name);
+ write_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+
+
+int tipc_bearer_init(void)
+{
+ int res;
+
+ write_lock_bh(&tipc_net_lock);
+ tipc_bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
+ media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
+ if (tipc_bearers && media_list) {
+ memset(tipc_bearers, 0, MAX_BEARERS * sizeof(struct bearer));
+ memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
+ res = TIPC_OK;
+ } else {
+ kfree(tipc_bearers);
+ kfree(media_list);
+ tipc_bearers = 0;
+ media_list = 0;
+ res = -ENOMEM;
+ }
+ write_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+void tipc_bearer_stop(void)
+{
+ u32 i;
+
+ if (!tipc_bearers)
+ return;
+
+ for (i = 0; i < MAX_BEARERS; i++) {
+ if (tipc_bearers[i].active)
+ tipc_bearers[i].publ.blocked = 1;
+ }
+ for (i = 0; i < MAX_BEARERS; i++) {
+ if (tipc_bearers[i].active)
+ bearer_disable(tipc_bearers[i].publ.name);
+ }
+ kfree(tipc_bearers);
+ kfree(media_list);
+ tipc_bearers = 0;
+ media_list = 0;
+ media_count = 0;
+}
+
+
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
new file mode 100644
index 000000000000..c4e7c1c3655b
--- /dev/null
+++ b/net/tipc/bearer.h
@@ -0,0 +1,170 @@
+/*
+ * net/tipc/bearer.h: Include file for TIPC bearer code
+ *
+ * Copyright (c) 1996-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_BEARER_H
+#define _TIPC_BEARER_H
+
+#include "core.h"
+#include "bcast.h"
+
+#define MAX_BEARERS 8
+#define MAX_MEDIA 4
+
+
+/**
+ * struct media - TIPC media information available to internal users
+ * @send_msg: routine which handles buffer transmission
+ * @enable_bearer: routine which enables a bearer
+ * @disable_bearer: routine which disables a bearer
+ * @addr2str: routine which converts bearer's address to string form
+ * @bcast_addr: media address used in broadcasting
+ * @bcast: non-zero if media supports broadcasting [currently mandatory]
+ * @priority: default link (and bearer) priority
+ * @tolerance: default time (in ms) before declaring link failure
+ * @window: default window (in packets) before declaring link congestion
+ * @type_id: TIPC media identifier [defined in tipc_bearer.h]
+ * @name: media name
+ */
+
+struct media {
+ int (*send_msg)(struct sk_buff *buf,
+ struct tipc_bearer *b_ptr,
+ struct tipc_media_addr *dest);
+ int (*enable_bearer)(struct tipc_bearer *b_ptr);
+ void (*disable_bearer)(struct tipc_bearer *b_ptr);
+ char *(*addr2str)(struct tipc_media_addr *a,
+ char *str_buf, int str_size);
+ struct tipc_media_addr bcast_addr;
+ int bcast;
+ u32 priority;
+ u32 tolerance;
+ u32 window;
+ u32 type_id;
+ char name[TIPC_MAX_MEDIA_NAME];
+};
+
+/**
+ * struct bearer - TIPC bearer information available to internal users
+ * @publ: bearer information available to privileged users
+ * @media: ptr to media structure associated with bearer
+ * @priority: default link priority for bearer
+ * @detect_scope: network address mask used during automatic link creation
+ * @identity: array index of this bearer within TIPC bearer array
+ * @link_req: ptr to (optional) structure making periodic link setup requests
+ * @links: list of non-congested links associated with bearer
+ * @cong_links: list of congested links associated with bearer
+ * @continue_count: # of times bearer has resumed after congestion or blocking
+ * @active: non-zero if bearer structure is represents a bearer
+ * @net_plane: network plane ('A' through 'H') currently associated with bearer
+ * @nodes: indicates which nodes in cluster can be reached through bearer
+ */
+
+struct bearer {
+ struct tipc_bearer publ;
+ struct media *media;
+ u32 priority;
+ u32 detect_scope;
+ u32 identity;
+ struct link_req *link_req;
+ struct list_head links;
+ struct list_head cong_links;
+ u32 continue_count;
+ int active;
+ char net_plane;
+ struct node_map nodes;
+};
+
+struct bearer_name {
+ char media_name[TIPC_MAX_MEDIA_NAME];
+ char if_name[TIPC_MAX_IF_NAME];
+};
+
+struct link;
+
+extern struct bearer *tipc_bearers;
+
+void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
+struct sk_buff *tipc_media_get_names(void);
+
+struct sk_buff *tipc_bearer_get_names(void);
+void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest);
+void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest);
+void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
+struct bearer *tipc_bearer_find_interface(const char *if_name);
+int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
+int tipc_bearer_init(void);
+void tipc_bearer_stop(void);
+void tipc_bearer_lock_push(struct bearer *b_ptr);
+
+
+/**
+ * tipc_bearer_send- sends buffer to destination over bearer
+ *
+ * Returns true (1) if successful, or false (0) if unable to send
+ *
+ * IMPORTANT:
+ * The media send routine must not alter the buffer being passed in
+ * as it may be needed for later retransmission!
+ *
+ * If the media send routine returns a non-zero value (indicating that
+ * it was unable to send the buffer), it must:
+ * 1) mark the bearer as blocked,
+ * 2) call tipc_continue() once the bearer is able to send again.
+ * Media types that are unable to meet these two critera must ensure their
+ * send routine always returns success -- even if the buffer was not sent --
+ * and let TIPC's link code deal with the undelivered message.
+ */
+
+static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
+ struct tipc_media_addr *dest)
+{
+ return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);
+}
+
+/**
+ * tipc_bearer_congested - determines if bearer is currently congested
+ */
+
+static inline int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
+{
+ if (unlikely(b_ptr->publ.blocked))
+ return 1;
+ if (likely(list_empty(&b_ptr->cong_links)))
+ return 0;
+ return !tipc_bearer_resolve_congestion(b_ptr, l_ptr);
+}
+
+#endif
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
new file mode 100644
index 000000000000..ab974ca19371
--- /dev/null
+++ b/net/tipc/cluster.c
@@ -0,0 +1,576 @@
+/*
+ * net/tipc/cluster.c: TIPC cluster management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "cluster.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "link.h"
+#include "node.h"
+#include "net.h"
+#include "msg.h"
+#include "bearer.h"
+
+void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
+ u32 lower, u32 upper);
+struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest);
+
+struct node **tipc_local_nodes = 0;
+struct node_map tipc_cltr_bcast_nodes = {0,{0,}};
+u32 tipc_highest_allowed_slave = 0;
+
+struct cluster *tipc_cltr_create(u32 addr)
+{
+ struct _zone *z_ptr;
+ struct cluster *c_ptr;
+ int max_nodes;
+ int alloc;
+
+ c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
+ if (c_ptr == NULL)
+ return 0;
+ memset(c_ptr, 0, sizeof(*c_ptr));
+
+ c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
+ if (in_own_cluster(addr))
+ max_nodes = LOWEST_SLAVE + tipc_max_slaves;
+ else
+ max_nodes = tipc_max_nodes + 1;
+ alloc = sizeof(void *) * (max_nodes + 1);
+ c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
+ if (c_ptr->nodes == NULL) {
+ kfree(c_ptr);
+ return 0;
+ }
+ memset(c_ptr->nodes, 0, alloc);
+ if (in_own_cluster(addr))
+ tipc_local_nodes = c_ptr->nodes;
+ c_ptr->highest_slave = LOWEST_SLAVE - 1;
+ c_ptr->highest_node = 0;
+
+ z_ptr = tipc_zone_find(tipc_zone(addr));
+ if (z_ptr == NULL) {
+ z_ptr = tipc_zone_create(addr);
+ }
+ if (z_ptr != NULL) {
+ tipc_zone_attach_cluster(z_ptr, c_ptr);
+ c_ptr->owner = z_ptr;
+ }
+ else {
+ kfree(c_ptr);
+ c_ptr = 0;
+ }
+
+ return c_ptr;
+}
+
+void tipc_cltr_delete(struct cluster *c_ptr)
+{
+ u32 n_num;
+
+ if (!c_ptr)
+ return;
+ for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) {
+ tipc_node_delete(c_ptr->nodes[n_num]);
+ }
+ for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) {
+ tipc_node_delete(c_ptr->nodes[n_num]);
+ }
+ kfree(c_ptr->nodes);
+ kfree(c_ptr);
+}
+
+u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr)
+{
+ struct node *n_ptr;
+ u32 n_num = tipc_node(addr) + 1;
+
+ if (!c_ptr)
+ return addr;
+ for (; n_num <= c_ptr->highest_node; n_num++) {
+ n_ptr = c_ptr->nodes[n_num];
+ if (n_ptr && tipc_node_has_active_links(n_ptr))
+ return n_ptr->addr;
+ }
+ for (n_num = 1; n_num < tipc_node(addr); n_num++) {
+ n_ptr = c_ptr->nodes[n_num];
+ if (n_ptr && tipc_node_has_active_links(n_ptr))
+ return n_ptr->addr;
+ }
+ return 0;
+}
+
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr)
+{
+ u32 n_num = tipc_node(n_ptr->addr);
+ u32 max_n_num = tipc_max_nodes;
+
+ if (in_own_cluster(n_ptr->addr))
+ max_n_num = tipc_highest_allowed_slave;
+ assert(n_num > 0);
+ assert(n_num <= max_n_num);
+ assert(c_ptr->nodes[n_num] == 0);
+ c_ptr->nodes[n_num] = n_ptr;
+ if (n_num > c_ptr->highest_node)
+ c_ptr->highest_node = n_num;
+}
+
+/**
+ * tipc_cltr_select_router - select router to a cluster
+ *
+ * Uses deterministic and fair algorithm.
+ */
+
+u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref)
+{
+ u32 n_num;
+ u32 ulim = c_ptr->highest_node;
+ u32 mask;
+ u32 tstart;
+
+ assert(!in_own_cluster(c_ptr->addr));
+ if (!ulim)
+ return 0;
+
+ /* Start entry must be random */
+ mask = tipc_max_nodes;
+ while (mask > ulim)
+ mask >>= 1;
+ tstart = ref & mask;
+ n_num = tstart;
+
+ /* Lookup upwards with wrap-around */
+ do {
+ if (tipc_node_is_up(c_ptr->nodes[n_num]))
+ break;
+ } while (++n_num <= ulim);
+ if (n_num > ulim) {
+ n_num = 1;
+ do {
+ if (tipc_node_is_up(c_ptr->nodes[n_num]))
+ break;
+ } while (++n_num < tstart);
+ if (n_num == tstart)
+ return 0;
+ }
+ assert(n_num <= ulim);
+ return tipc_node_select_router(c_ptr->nodes[n_num], ref);
+}
+
+/**
+ * tipc_cltr_select_node - select destination node within a remote cluster
+ *
+ * Uses deterministic and fair algorithm.
+ */
+
+struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector)
+{
+ u32 n_num;
+ u32 mask = tipc_max_nodes;
+ u32 start_entry;
+
+ assert(!in_own_cluster(c_ptr->addr));
+ if (!c_ptr->highest_node)
+ return 0;
+
+ /* Start entry must be random */
+ while (mask > c_ptr->highest_node) {
+ mask >>= 1;
+ }
+ start_entry = (selector & mask) ? selector & mask : 1u;
+ assert(start_entry <= c_ptr->highest_node);
+
+ /* Lookup upwards with wrap-around */
+ for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) {
+ if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
+ return c_ptr->nodes[n_num];
+ }
+ for (n_num = 1; n_num < start_entry; n_num++) {
+ if (tipc_node_has_active_links(c_ptr->nodes[n_num]))
+ return c_ptr->nodes[n_num];
+ }
+ return 0;
+}
+
+/*
+ * Routing table management: See description in node.c
+ */
+
+struct sk_buff *tipc_cltr_prepare_routing_msg(u32 data_size, u32 dest)
+{
+ u32 size = INT_H_SIZE + data_size;
+ struct sk_buff *buf = buf_acquire(size);
+ struct tipc_msg *msg;
+
+ if (buf) {
+ msg = buf_msg(buf);
+ memset((char *)msg, 0, size);
+ msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest);
+ }
+ return buf;
+}
+
+void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest,
+ u32 lower, u32 upper)
+{
+ struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
+ struct tipc_msg *msg;
+
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_set_remote_node(msg, dest);
+ msg_set_type(msg, ROUTE_ADDITION);
+ tipc_cltr_multicast(c_ptr, buf, lower, upper);
+ } else {
+ warn("Memory squeeze: broadcast of new route failed\n");
+ }
+}
+
+void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest,
+ u32 lower, u32 upper)
+{
+ struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr);
+ struct tipc_msg *msg;
+
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_set_remote_node(msg, dest);
+ msg_set_type(msg, ROUTE_REMOVAL);
+ tipc_cltr_multicast(c_ptr, buf, lower, upper);
+ } else {
+ warn("Memory squeeze: broadcast of lost route failed\n");
+ }
+}
+
+void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ u32 highest = c_ptr->highest_slave;
+ u32 n_num;
+ int send = 0;
+
+ assert(!is_slave(dest));
+ assert(in_own_cluster(dest));
+ assert(in_own_cluster(c_ptr->addr));
+ if (highest <= LOWEST_SLAVE)
+ return;
+ buf = tipc_cltr_prepare_routing_msg(highest - LOWEST_SLAVE + 1,
+ c_ptr->addr);
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_set_remote_node(msg, c_ptr->addr);
+ msg_set_type(msg, SLAVE_ROUTING_TABLE);
+ for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) {
+ if (c_ptr->nodes[n_num] &&
+ tipc_node_has_active_links(c_ptr->nodes[n_num])) {
+ send = 1;
+ msg_set_dataoctet(msg, n_num);
+ }
+ }
+ if (send)
+ tipc_link_send(buf, dest, dest);
+ else
+ buf_discard(buf);
+ } else {
+ warn("Memory squeeze: broadcast of lost route failed\n");
+ }
+}
+
+void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ u32 highest = c_ptr->highest_node;
+ u32 n_num;
+ int send = 0;
+
+ if (in_own_cluster(c_ptr->addr))
+ return;
+ assert(!is_slave(dest));
+ assert(in_own_cluster(dest));
+ highest = c_ptr->highest_node;
+ buf = tipc_cltr_prepare_routing_msg(highest + 1, c_ptr->addr);
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_set_remote_node(msg, c_ptr->addr);
+ msg_set_type(msg, EXT_ROUTING_TABLE);
+ for (n_num = 1; n_num <= highest; n_num++) {
+ if (c_ptr->nodes[n_num] &&
+ tipc_node_has_active_links(c_ptr->nodes[n_num])) {
+ send = 1;
+ msg_set_dataoctet(msg, n_num);
+ }
+ }
+ if (send)
+ tipc_link_send(buf, dest, dest);
+ else
+ buf_discard(buf);
+ } else {
+ warn("Memory squeeze: broadcast of external route failed\n");
+ }
+}
+
+void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ u32 highest = c_ptr->highest_node;
+ u32 n_num;
+ int send = 0;
+
+ assert(is_slave(dest));
+ assert(in_own_cluster(c_ptr->addr));
+ buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr);
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_set_remote_node(msg, c_ptr->addr);
+ msg_set_type(msg, LOCAL_ROUTING_TABLE);
+ for (n_num = 1; n_num <= highest; n_num++) {
+ if (c_ptr->nodes[n_num] &&
+ tipc_node_has_active_links(c_ptr->nodes[n_num])) {
+ send = 1;
+ msg_set_dataoctet(msg, n_num);
+ }
+ }
+ if (send)
+ tipc_link_send(buf, dest, dest);
+ else
+ buf_discard(buf);
+ } else {
+ warn("Memory squeeze: broadcast of local route failed\n");
+ }
+}
+
+void tipc_cltr_recv_routing_table(struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ struct cluster *c_ptr;
+ struct node *n_ptr;
+ unchar *node_table;
+ u32 table_size;
+ u32 router;
+ u32 rem_node = msg_remote_node(msg);
+ u32 z_num;
+ u32 c_num;
+ u32 n_num;
+
+ c_ptr = tipc_cltr_find(rem_node);
+ if (!c_ptr) {
+ c_ptr = tipc_cltr_create(rem_node);
+ if (!c_ptr) {
+ buf_discard(buf);
+ return;
+ }
+ }
+
+ node_table = buf->data + msg_hdr_sz(msg);
+ table_size = msg_size(msg) - msg_hdr_sz(msg);
+ router = msg_prevnode(msg);
+ z_num = tipc_zone(rem_node);
+ c_num = tipc_cluster(rem_node);
+
+ switch (msg_type(msg)) {
+ case LOCAL_ROUTING_TABLE:
+ assert(is_slave(tipc_own_addr));
+ case EXT_ROUTING_TABLE:
+ for (n_num = 1; n_num < table_size; n_num++) {
+ if (node_table[n_num]) {
+ u32 addr = tipc_addr(z_num, c_num, n_num);
+ n_ptr = c_ptr->nodes[n_num];
+ if (!n_ptr) {
+ n_ptr = tipc_node_create(addr);
+ }
+ if (n_ptr)
+ tipc_node_add_router(n_ptr, router);
+ }
+ }
+ break;
+ case SLAVE_ROUTING_TABLE:
+ assert(!is_slave(tipc_own_addr));
+ assert(in_own_cluster(c_ptr->addr));
+ for (n_num = 1; n_num < table_size; n_num++) {
+ if (node_table[n_num]) {
+ u32 slave_num = n_num + LOWEST_SLAVE;
+ u32 addr = tipc_addr(z_num, c_num, slave_num);
+ n_ptr = c_ptr->nodes[slave_num];
+ if (!n_ptr) {
+ n_ptr = tipc_node_create(addr);
+ }
+ if (n_ptr)
+ tipc_node_add_router(n_ptr, router);
+ }
+ }
+ break;
+ case ROUTE_ADDITION:
+ if (!is_slave(tipc_own_addr)) {
+ assert(!in_own_cluster(c_ptr->addr)
+ || is_slave(rem_node));
+ } else {
+ assert(in_own_cluster(c_ptr->addr)
+ && !is_slave(rem_node));
+ }
+ n_ptr = c_ptr->nodes[tipc_node(rem_node)];
+ if (!n_ptr)
+ n_ptr = tipc_node_create(rem_node);
+ if (n_ptr)
+ tipc_node_add_router(n_ptr, router);
+ break;
+ case ROUTE_REMOVAL:
+ if (!is_slave(tipc_own_addr)) {
+ assert(!in_own_cluster(c_ptr->addr)
+ || is_slave(rem_node));
+ } else {
+ assert(in_own_cluster(c_ptr->addr)
+ && !is_slave(rem_node));
+ }
+ n_ptr = c_ptr->nodes[tipc_node(rem_node)];
+ if (n_ptr)
+ tipc_node_remove_router(n_ptr, router);
+ break;
+ default:
+ assert(!"Illegal routing manager message received\n");
+ }
+ buf_discard(buf);
+}
+
+void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router)
+{
+ u32 start_entry;
+ u32 tstop;
+ u32 n_num;
+
+ if (is_slave(router))
+ return; /* Slave nodes can not be routers */
+
+ if (in_own_cluster(c_ptr->addr)) {
+ start_entry = LOWEST_SLAVE;
+ tstop = c_ptr->highest_slave;
+ } else {
+ start_entry = 1;
+ tstop = c_ptr->highest_node;
+ }
+
+ for (n_num = start_entry; n_num <= tstop; n_num++) {
+ if (c_ptr->nodes[n_num]) {
+ tipc_node_remove_router(c_ptr->nodes[n_num], router);
+ }
+ }
+}
+
+/**
+ * tipc_cltr_multicast - multicast message to local nodes
+ */
+
+void tipc_cltr_multicast(struct cluster *c_ptr, struct sk_buff *buf,
+ u32 lower, u32 upper)
+{
+ struct sk_buff *buf_copy;
+ struct node *n_ptr;
+ u32 n_num;
+ u32 tstop;
+
+ assert(lower <= upper);
+ assert(((lower >= 1) && (lower <= tipc_max_nodes)) ||
+ ((lower >= LOWEST_SLAVE) && (lower <= tipc_highest_allowed_slave)));
+ assert(((upper >= 1) && (upper <= tipc_max_nodes)) ||
+ ((upper >= LOWEST_SLAVE) && (upper <= tipc_highest_allowed_slave)));
+ assert(in_own_cluster(c_ptr->addr));
+
+ tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node;
+ if (tstop > upper)
+ tstop = upper;
+ for (n_num = lower; n_num <= tstop; n_num++) {
+ n_ptr = c_ptr->nodes[n_num];
+ if (n_ptr && tipc_node_has_active_links(n_ptr)) {
+ buf_copy = skb_copy(buf, GFP_ATOMIC);
+ if (buf_copy == NULL)
+ break;
+ msg_set_destnode(buf_msg(buf_copy), n_ptr->addr);
+ tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr);
+ }
+ }
+ buf_discard(buf);
+}
+
+/**
+ * tipc_cltr_broadcast - broadcast message to all nodes within cluster
+ */
+
+void tipc_cltr_broadcast(struct sk_buff *buf)
+{
+ struct sk_buff *buf_copy;
+ struct cluster *c_ptr;
+ struct node *n_ptr;
+ u32 n_num;
+ u32 tstart;
+ u32 tstop;
+ u32 node_type;
+
+ if (tipc_mode == TIPC_NET_MODE) {
+ c_ptr = tipc_cltr_find(tipc_own_addr);
+ assert(in_own_cluster(c_ptr->addr)); /* For now */
+
+ /* Send to standard nodes, then repeat loop sending to slaves */
+ tstart = 1;
+ tstop = c_ptr->highest_node;
+ for (node_type = 1; node_type <= 2; node_type++) {
+ for (n_num = tstart; n_num <= tstop; n_num++) {
+ n_ptr = c_ptr->nodes[n_num];
+ if (n_ptr && tipc_node_has_active_links(n_ptr)) {
+ buf_copy = skb_copy(buf, GFP_ATOMIC);
+ if (buf_copy == NULL)
+ goto exit;
+ msg_set_destnode(buf_msg(buf_copy),
+ n_ptr->addr);
+ tipc_link_send(buf_copy, n_ptr->addr,
+ n_ptr->addr);
+ }
+ }
+ tstart = LOWEST_SLAVE;
+ tstop = c_ptr->highest_slave;
+ }
+ }
+exit:
+ buf_discard(buf);
+}
+
+int tipc_cltr_init(void)
+{
+ tipc_highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves;
+ return tipc_cltr_create(tipc_own_addr) ? TIPC_OK : -ENOMEM;
+}
+
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h
new file mode 100644
index 000000000000..9963642e1058
--- /dev/null
+++ b/net/tipc/cluster.h
@@ -0,0 +1,92 @@
+/*
+ * net/tipc/cluster.h: Include file for TIPC cluster management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_CLUSTER_H
+#define _TIPC_CLUSTER_H
+
+#include "addr.h"
+#include "zone.h"
+
+#define LOWEST_SLAVE 2048u
+
+/**
+ * struct cluster - TIPC cluster structure
+ * @addr: network address of cluster
+ * @owner: pointer to zone that cluster belongs to
+ * @nodes: array of pointers to all nodes within cluster
+ * @highest_node: id of highest numbered node within cluster
+ * @highest_slave: (used for secondary node support)
+ */
+
+struct cluster {
+ u32 addr;
+ struct _zone *owner;
+ struct node **nodes;
+ u32 highest_node;
+ u32 highest_slave;
+};
+
+
+extern struct node **tipc_local_nodes;
+extern u32 tipc_highest_allowed_slave;
+extern struct node_map tipc_cltr_bcast_nodes;
+
+void tipc_cltr_remove_as_router(struct cluster *c_ptr, u32 router);
+void tipc_cltr_send_ext_routes(struct cluster *c_ptr, u32 dest);
+struct node *tipc_cltr_select_node(struct cluster *c_ptr, u32 selector);
+u32 tipc_cltr_select_router(struct cluster *c_ptr, u32 ref);
+void tipc_cltr_recv_routing_table(struct sk_buff *buf);
+struct cluster *tipc_cltr_create(u32 addr);
+void tipc_cltr_delete(struct cluster *c_ptr);
+void tipc_cltr_attach_node(struct cluster *c_ptr, struct node *n_ptr);
+void tipc_cltr_send_slave_routes(struct cluster *c_ptr, u32 dest);
+void tipc_cltr_broadcast(struct sk_buff *buf);
+int tipc_cltr_init(void);
+u32 tipc_cltr_next_node(struct cluster *c_ptr, u32 addr);
+void tipc_cltr_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
+void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest);
+void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
+
+static inline struct cluster *tipc_cltr_find(u32 addr)
+{
+ struct _zone *z_ptr = tipc_zone_find(addr);
+
+ if (z_ptr)
+ return z_ptr->clusters[1];
+ return 0;
+}
+
+#endif
diff --git a/net/tipc/config.c b/net/tipc/config.c
new file mode 100644
index 000000000000..3c8e6740e5ae
--- /dev/null
+++ b/net/tipc/config.c
@@ -0,0 +1,718 @@
+/*
+ * net/tipc/config.c: TIPC configuration management code
+ *
+ * Copyright (c) 2002-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "bearer.h"
+#include "port.h"
+#include "link.h"
+#include "zone.h"
+#include "addr.h"
+#include "name_table.h"
+#include "node.h"
+#include "config.h"
+#include "discover.h"
+
+struct subscr_data {
+ char usr_handle[8];
+ u32 domain;
+ u32 port_ref;
+ struct list_head subd_list;
+};
+
+struct manager {
+ u32 user_ref;
+ u32 port_ref;
+ u32 subscr_ref;
+ u32 link_subscriptions;
+ struct list_head link_subscribers;
+};
+
+static struct manager mng = { 0};
+
+static spinlock_t config_lock = SPIN_LOCK_UNLOCKED;
+
+static const void *req_tlv_area; /* request message TLV area */
+static int req_tlv_space; /* request message TLV area size */
+static int rep_headroom; /* reply message headroom to use */
+
+
+void tipc_cfg_link_event(u32 addr, char *name, int up)
+{
+ /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
+}
+
+
+struct sk_buff *tipc_cfg_reply_alloc(int payload_size)
+{
+ struct sk_buff *buf;
+
+ buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC);
+ if (buf)
+ skb_reserve(buf, rep_headroom);
+ return buf;
+}
+
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
+ void *tlv_data, int tlv_data_size)
+{
+ struct tlv_desc *tlv = (struct tlv_desc *)buf->tail;
+ int new_tlv_space = TLV_SPACE(tlv_data_size);
+
+ if (skb_tailroom(buf) < new_tlv_space) {
+ dbg("tipc_cfg_append_tlv unable to append TLV\n");
+ return 0;
+ }
+ skb_put(buf, new_tlv_space);
+ tlv->tlv_type = htons(tlv_type);
+ tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size));
+ if (tlv_data_size && tlv_data)
+ memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size);
+ return 1;
+}
+
+struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value)
+{
+ struct sk_buff *buf;
+ u32 value_net;
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(value)));
+ if (buf) {
+ value_net = htonl(value);
+ tipc_cfg_append_tlv(buf, tlv_type, &value_net,
+ sizeof(value_net));
+ }
+ return buf;
+}
+
+struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string)
+{
+ struct sk_buff *buf;
+ int string_len = strlen(string) + 1;
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(string_len));
+ if (buf)
+ tipc_cfg_append_tlv(buf, tlv_type, string, string_len);
+ return buf;
+}
+
+
+
+
+#if 0
+
+/* Now obsolete code for handling commands not yet implemented the new way */
+
+int tipc_cfg_cmd(const struct tipc_cmd_msg * msg,
+ char *data,
+ u32 sz,
+ u32 *ret_size,
+ struct tipc_portid *orig)
+{
+ int rv = -EINVAL;
+ u32 cmd = msg->cmd;
+
+ *ret_size = 0;
+ switch (cmd) {
+ case TIPC_REMOVE_LINK:
+ case TIPC_CMD_BLOCK_LINK:
+ case TIPC_CMD_UNBLOCK_LINK:
+ if (!cfg_check_connection(orig))
+ rv = link_control(msg->argv.link_name, msg->cmd, 0);
+ break;
+ case TIPC_ESTABLISH:
+ {
+ int connected;
+
+ tipc_isconnected(mng.conn_port_ref, &connected);
+ if (connected || !orig) {
+ rv = TIPC_FAILURE;
+ break;
+ }
+ rv = tipc_connect2port(mng.conn_port_ref, orig);
+ if (rv == TIPC_OK)
+ orig = 0;
+ break;
+ }
+ case TIPC_GET_PEER_ADDRESS:
+ *ret_size = link_peer_addr(msg->argv.link_name, data, sz);
+ break;
+ case TIPC_GET_ROUTES:
+ rv = TIPC_OK;
+ break;
+ default: {}
+ }
+ if (*ret_size)
+ rv = TIPC_OK;
+ return rv;
+}
+
+static void cfg_cmd_event(struct tipc_cmd_msg *msg,
+ char *data,
+ u32 sz,
+ struct tipc_portid const *orig)
+{
+ int rv = -EINVAL;
+ struct tipc_cmd_result_msg rmsg;
+ struct iovec msg_sect[2];
+ int *arg;
+
+ msg->cmd = ntohl(msg->cmd);
+
+ cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect,
+ data, 0);
+ if (ntohl(msg->magic) != TIPC_MAGIC)
+ goto exit;
+
+ switch (msg->cmd) {
+ case TIPC_CREATE_LINK:
+ if (!cfg_check_connection(orig))
+ rv = disc_create_link(&msg->argv.create_link);
+ break;
+ case TIPC_LINK_SUBSCRIBE:
+ {
+ struct subscr_data *sub;
+
+ if (mng.link_subscriptions > 64)
+ break;
+ sub = (struct subscr_data *)kmalloc(sizeof(*sub),
+ GFP_ATOMIC);
+ if (sub == NULL) {
+ warn("Memory squeeze; dropped remote link subscription\n");
+ break;
+ }
+ INIT_LIST_HEAD(&sub->subd_list);
+ tipc_createport(mng.user_ref,
+ (void *)sub,
+ TIPC_HIGH_IMPORTANCE,
+ 0,
+ 0,
+ (tipc_conn_shutdown_event)cfg_linksubscr_cancel,
+ 0,
+ 0,
+ (tipc_conn_msg_event)cfg_linksubscr_cancel,
+ 0,
+ &sub->port_ref);
+ if (!sub->port_ref) {
+ kfree(sub);
+ break;
+ }
+ memcpy(sub->usr_handle,msg->usr_handle,
+ sizeof(sub->usr_handle));
+ sub->domain = msg->argv.domain;
+ list_add_tail(&sub->subd_list, &mng.link_subscribers);
+ tipc_connect2port(sub->port_ref, orig);
+ rmsg.retval = TIPC_OK;
+ tipc_send(sub->port_ref, 2u, msg_sect);
+ mng.link_subscriptions++;
+ return;
+ }
+ default:
+ rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig);
+ }
+ exit:
+ rmsg.result_len = htonl(msg_sect[1].iov_len);
+ rmsg.retval = htonl(rv);
+ tipc_cfg_respond(msg_sect, 2u, orig);
+}
+#endif
+
+static struct sk_buff *cfg_enable_bearer(void)
+{
+ struct tipc_bearer_config *args;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
+ if (tipc_enable_bearer(args->name,
+ ntohl(args->detect_scope),
+ ntohl(args->priority)))
+ return tipc_cfg_reply_error_string("unable to enable bearer");
+
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_disable_bearer(void)
+{
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area)))
+ return tipc_cfg_reply_error_string("unable to disable bearer");
+
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_own_addr(void)
+{
+ u32 addr;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ addr = *(u32 *)TLV_DATA(req_tlv_area);
+ addr = ntohl(addr);
+ if (addr == tipc_own_addr)
+ return tipc_cfg_reply_none();
+ if (!tipc_addr_node_valid(addr))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (node address)");
+ if (tipc_own_addr)
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (cannot change node address once assigned)");
+
+ spin_unlock_bh(&config_lock);
+ tipc_core_stop_net();
+ tipc_own_addr = addr;
+ tipc_core_start_net();
+ spin_lock_bh(&config_lock);
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_remote_mng(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ tipc_remote_management = (value != 0);
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_max_publications(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 1, 65535))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (max publications must be 1-65535)");
+ tipc_max_publications = value;
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_max_subscriptions(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 1, 65535))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (max subscriptions must be 1-65535");
+ tipc_max_subscriptions = value;
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_max_ports(void)
+{
+ int orig_mode;
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 127, 65535))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (max ports must be 127-65535)");
+
+ if (value == tipc_max_ports)
+ return tipc_cfg_reply_none();
+
+ if (atomic_read(&tipc_user_count) > 2)
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (cannot change max ports while TIPC users exist)");
+
+ spin_unlock_bh(&config_lock);
+ orig_mode = tipc_get_mode();
+ if (orig_mode == TIPC_NET_MODE)
+ tipc_core_stop_net();
+ tipc_core_stop();
+ tipc_max_ports = value;
+ tipc_core_start();
+ if (orig_mode == TIPC_NET_MODE)
+ tipc_core_start_net();
+ spin_lock_bh(&config_lock);
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *set_net_max(int value, int *parameter)
+{
+ int orig_mode;
+
+ if (value != *parameter) {
+ orig_mode = tipc_get_mode();
+ if (orig_mode == TIPC_NET_MODE)
+ tipc_core_stop_net();
+ *parameter = value;
+ if (orig_mode == TIPC_NET_MODE)
+ tipc_core_start_net();
+ }
+
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_max_zones(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 1, 255))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (max zones must be 1-255)");
+ return set_net_max(value, &tipc_max_zones);
+}
+
+static struct sk_buff *cfg_set_max_clusters(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != 1)
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (max clusters fixed at 1)");
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_max_nodes(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 8, 2047))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (max nodes must be 8-2047)");
+ return set_net_max(value, &tipc_max_nodes);
+}
+
+static struct sk_buff *cfg_set_max_slaves(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != 0)
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (max secondary nodes fixed at 0)");
+ return tipc_cfg_reply_none();
+}
+
+static struct sk_buff *cfg_set_netid(void)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 1, 9999))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (network id must be 1-9999)");
+
+ if (tipc_own_addr)
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (cannot change network id once part of network)");
+
+ return set_net_max(value, &tipc_net_id);
+}
+
+struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
+ int request_space, int reply_headroom)
+{
+ struct sk_buff *rep_tlv_buf;
+
+ spin_lock_bh(&config_lock);
+
+ /* Save request and reply details in a well-known location */
+
+ req_tlv_area = request_area;
+ req_tlv_space = request_space;
+ rep_headroom = reply_headroom;
+
+ /* Check command authorization */
+
+ if (likely(orig_node == tipc_own_addr)) {
+ /* command is permitted */
+ } else if (cmd >= 0x8000) {
+ rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (cannot be done remotely)");
+ goto exit;
+ } else if (!tipc_remote_management) {
+ rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE);
+ goto exit;
+ }
+ else if (cmd >= 0x4000) {
+ u32 domain = 0;
+
+ if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) ||
+ (domain != orig_node)) {
+ rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR);
+ goto exit;
+ }
+ }
+
+ /* Call appropriate processing routine */
+
+ switch (cmd) {
+ case TIPC_CMD_NOOP:
+ rep_tlv_buf = tipc_cfg_reply_none();
+ break;
+ case TIPC_CMD_GET_NODES:
+ rep_tlv_buf = tipc_node_get_nodes(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_GET_LINKS:
+ rep_tlv_buf = tipc_node_get_links(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_SHOW_LINK_STATS:
+ rep_tlv_buf = tipc_link_cmd_show_stats(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_RESET_LINK_STATS:
+ rep_tlv_buf = tipc_link_cmd_reset_stats(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_SHOW_NAME_TABLE:
+ rep_tlv_buf = tipc_nametbl_get(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_GET_BEARER_NAMES:
+ rep_tlv_buf = tipc_bearer_get_names();
+ break;
+ case TIPC_CMD_GET_MEDIA_NAMES:
+ rep_tlv_buf = tipc_media_get_names();
+ break;
+ case TIPC_CMD_SHOW_PORTS:
+ rep_tlv_buf = tipc_port_get_ports();
+ break;
+#if 0
+ case TIPC_CMD_SHOW_PORT_STATS:
+ rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_RESET_PORT_STATS:
+ rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED);
+ break;
+#endif
+ case TIPC_CMD_SET_LOG_SIZE:
+ rep_tlv_buf = tipc_log_resize(req_tlv_area, req_tlv_space);
+ break;
+ case TIPC_CMD_DUMP_LOG:
+ rep_tlv_buf = tipc_log_dump();
+ break;
+ case TIPC_CMD_SET_LINK_TOL:
+ case TIPC_CMD_SET_LINK_PRI:
+ case TIPC_CMD_SET_LINK_WINDOW:
+ rep_tlv_buf = tipc_link_cmd_config(req_tlv_area, req_tlv_space, cmd);
+ break;
+ case TIPC_CMD_ENABLE_BEARER:
+ rep_tlv_buf = cfg_enable_bearer();
+ break;
+ case TIPC_CMD_DISABLE_BEARER:
+ rep_tlv_buf = cfg_disable_bearer();
+ break;
+ case TIPC_CMD_SET_NODE_ADDR:
+ rep_tlv_buf = cfg_set_own_addr();
+ break;
+ case TIPC_CMD_SET_REMOTE_MNG:
+ rep_tlv_buf = cfg_set_remote_mng();
+ break;
+ case TIPC_CMD_SET_MAX_PORTS:
+ rep_tlv_buf = cfg_set_max_ports();
+ break;
+ case TIPC_CMD_SET_MAX_PUBL:
+ rep_tlv_buf = cfg_set_max_publications();
+ break;
+ case TIPC_CMD_SET_MAX_SUBSCR:
+ rep_tlv_buf = cfg_set_max_subscriptions();
+ break;
+ case TIPC_CMD_SET_MAX_ZONES:
+ rep_tlv_buf = cfg_set_max_zones();
+ break;
+ case TIPC_CMD_SET_MAX_CLUSTERS:
+ rep_tlv_buf = cfg_set_max_clusters();
+ break;
+ case TIPC_CMD_SET_MAX_NODES:
+ rep_tlv_buf = cfg_set_max_nodes();
+ break;
+ case TIPC_CMD_SET_MAX_SLAVES:
+ rep_tlv_buf = cfg_set_max_slaves();
+ break;
+ case TIPC_CMD_SET_NETID:
+ rep_tlv_buf = cfg_set_netid();
+ break;
+ case TIPC_CMD_GET_REMOTE_MNG:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management);
+ break;
+ case TIPC_CMD_GET_MAX_PORTS:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports);
+ break;
+ case TIPC_CMD_GET_MAX_PUBL:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications);
+ break;
+ case TIPC_CMD_GET_MAX_SUBSCR:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);
+ break;
+ case TIPC_CMD_GET_MAX_ZONES:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_zones);
+ break;
+ case TIPC_CMD_GET_MAX_CLUSTERS:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_clusters);
+ break;
+ case TIPC_CMD_GET_MAX_NODES:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes);
+ break;
+ case TIPC_CMD_GET_MAX_SLAVES:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_slaves);
+ break;
+ case TIPC_CMD_GET_NETID:
+ rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
+ break;
+ default:
+ rep_tlv_buf = NULL;
+ break;
+ }
+
+ /* Return reply buffer */
+exit:
+ spin_unlock_bh(&config_lock);
+ return rep_tlv_buf;
+}
+
+static void cfg_named_msg_event(void *userdata,
+ u32 port_ref,
+ struct sk_buff **buf,
+ const unchar *msg,
+ u32 size,
+ u32 importance,
+ struct tipc_portid const *orig,
+ struct tipc_name_seq const *dest)
+{
+ struct tipc_cfg_msg_hdr *req_hdr;
+ struct tipc_cfg_msg_hdr *rep_hdr;
+ struct sk_buff *rep_buf;
+
+ /* Validate configuration message header (ignore invalid message) */
+
+ req_hdr = (struct tipc_cfg_msg_hdr *)msg;
+ if ((size < sizeof(*req_hdr)) ||
+ (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
+ (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
+ warn("discarded invalid configuration message\n");
+ return;
+ }
+
+ /* Generate reply for request (if can't, return request) */
+
+ rep_buf = tipc_cfg_do_cmd(orig->node,
+ ntohs(req_hdr->tcm_type),
+ msg + sizeof(*req_hdr),
+ size - sizeof(*req_hdr),
+ BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr));
+ if (rep_buf) {
+ skb_push(rep_buf, sizeof(*rep_hdr));
+ rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data;
+ memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
+ rep_hdr->tcm_len = htonl(rep_buf->len);
+ rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
+ } else {
+ rep_buf = *buf;
+ *buf = NULL;
+ }
+
+ /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */
+ tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len);
+}
+
+int tipc_cfg_init(void)
+{
+ struct tipc_name_seq seq;
+ int res;
+
+ memset(&mng, 0, sizeof(mng));
+ INIT_LIST_HEAD(&mng.link_subscribers);
+
+ res = tipc_attach(&mng.user_ref, 0, 0);
+ if (res)
+ goto failed;
+
+ res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE,
+ NULL, NULL, NULL,
+ NULL, cfg_named_msg_event, NULL,
+ NULL, &mng.port_ref);
+ if (res)
+ goto failed;
+
+ seq.type = TIPC_CFG_SRV;
+ seq.lower = seq.upper = tipc_own_addr;
+ res = tipc_nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq);
+ if (res)
+ goto failed;
+
+ return 0;
+
+failed:
+ err("Unable to create configuration service\n");
+ tipc_detach(mng.user_ref);
+ mng.user_ref = 0;
+ return res;
+}
+
+void tipc_cfg_stop(void)
+{
+ if (mng.user_ref) {
+ tipc_detach(mng.user_ref);
+ mng.user_ref = 0;
+ }
+}
diff --git a/net/tipc/config.h b/net/tipc/config.h
new file mode 100644
index 000000000000..7a728f954d84
--- /dev/null
+++ b/net/tipc/config.h
@@ -0,0 +1,79 @@
+/*
+ * net/tipc/config.h: Include file for TIPC configuration service code
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_CONFIG_H
+#define _TIPC_CONFIG_H
+
+/* ---------------------------------------------------------------------- */
+
+#include "core.h"
+#include "link.h"
+
+struct sk_buff *tipc_cfg_reply_alloc(int payload_size);
+int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type,
+ void *tlv_data, int tlv_data_size);
+struct sk_buff *tipc_cfg_reply_unsigned_type(u16 tlv_type, u32 value);
+struct sk_buff *tipc_cfg_reply_string_type(u16 tlv_type, char *string);
+
+static inline struct sk_buff *tipc_cfg_reply_none(void)
+{
+ return tipc_cfg_reply_alloc(0);
+}
+
+static inline struct sk_buff *tipc_cfg_reply_unsigned(u32 value)
+{
+ return tipc_cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
+}
+
+static inline struct sk_buff *tipc_cfg_reply_error_string(char *string)
+{
+ return tipc_cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
+}
+
+static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string)
+{
+ return tipc_cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
+}
+
+struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd,
+ const void *req_tlv_area, int req_tlv_space,
+ int headroom);
+
+void tipc_cfg_link_event(u32 addr, char *name, int up);
+int tipc_cfg_init(void);
+void tipc_cfg_stop(void);
+
+#endif
diff --git a/net/tipc/core.c b/net/tipc/core.c
new file mode 100644
index 000000000000..3d0a8ee4e1d3
--- /dev/null
+++ b/net/tipc/core.c
@@ -0,0 +1,284 @@
+/*
+ * net/tipc/core.c: TIPC module code
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+
+#include "core.h"
+#include "dbg.h"
+#include "ref.h"
+#include "net.h"
+#include "user_reg.h"
+#include "name_table.h"
+#include "subscr.h"
+#include "config.h"
+
+int tipc_eth_media_start(void);
+void tipc_eth_media_stop(void);
+int tipc_handler_start(void);
+void tipc_handler_stop(void);
+int tipc_socket_init(void);
+void tipc_socket_stop(void);
+int tipc_netlink_start(void);
+void tipc_netlink_stop(void);
+
+#define MOD_NAME "tipc_start: "
+
+#ifndef CONFIG_TIPC_ZONES
+#define CONFIG_TIPC_ZONES 3
+#endif
+
+#ifndef CONFIG_TIPC_CLUSTERS
+#define CONFIG_TIPC_CLUSTERS 1
+#endif
+
+#ifndef CONFIG_TIPC_NODES
+#define CONFIG_TIPC_NODES 255
+#endif
+
+#ifndef CONFIG_TIPC_SLAVE_NODES
+#define CONFIG_TIPC_SLAVE_NODES 0
+#endif
+
+#ifndef CONFIG_TIPC_PORTS
+#define CONFIG_TIPC_PORTS 8191
+#endif
+
+#ifndef CONFIG_TIPC_LOG
+#define CONFIG_TIPC_LOG 0
+#endif
+
+/* global variables used by multiple sub-systems within TIPC */
+
+int tipc_mode = TIPC_NOT_RUNNING;
+int tipc_random;
+atomic_t tipc_user_count = ATOMIC_INIT(0);
+
+const char tipc_alphabet[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+/* configurable TIPC parameters */
+
+u32 tipc_own_addr;
+int tipc_max_zones;
+int tipc_max_clusters;
+int tipc_max_nodes;
+int tipc_max_slaves;
+int tipc_max_ports;
+int tipc_max_subscriptions;
+int tipc_max_publications;
+int tipc_net_id;
+int tipc_remote_management;
+
+
+int tipc_get_mode(void)
+{
+ return tipc_mode;
+}
+
+/**
+ * tipc_core_stop_net - shut down TIPC networking sub-systems
+ */
+
+void tipc_core_stop_net(void)
+{
+ tipc_eth_media_stop();
+ tipc_net_stop();
+}
+
+/**
+ * start_net - start TIPC networking sub-systems
+ */
+
+int tipc_core_start_net(void)
+{
+ int res;
+
+ if ((res = tipc_net_start()) ||
+ (res = tipc_eth_media_start())) {
+ tipc_core_stop_net();
+ }
+ return res;
+}
+
+/**
+ * tipc_core_stop - switch TIPC from SINGLE NODE to NOT RUNNING mode
+ */
+
+void tipc_core_stop(void)
+{
+ if (tipc_mode != TIPC_NODE_MODE)
+ return;
+
+ tipc_mode = TIPC_NOT_RUNNING;
+
+ tipc_netlink_stop();
+ tipc_handler_stop();
+ tipc_cfg_stop();
+ tipc_subscr_stop();
+ tipc_reg_stop();
+ tipc_nametbl_stop();
+ tipc_ref_table_stop();
+ tipc_socket_stop();
+}
+
+/**
+ * tipc_core_start - switch TIPC from NOT RUNNING to SINGLE NODE mode
+ */
+
+int tipc_core_start(void)
+{
+ int res;
+
+ if (tipc_mode != TIPC_NOT_RUNNING)
+ return -ENOPROTOOPT;
+
+ get_random_bytes(&tipc_random, sizeof(tipc_random));
+ tipc_mode = TIPC_NODE_MODE;
+
+ if ((res = tipc_handler_start()) ||
+ (res = tipc_ref_table_init(tipc_max_ports + tipc_max_subscriptions,
+ tipc_random)) ||
+ (res = tipc_reg_start()) ||
+ (res = tipc_nametbl_init()) ||
+ (res = tipc_k_signal((Handler)tipc_subscr_start, 0)) ||
+ (res = tipc_k_signal((Handler)tipc_cfg_init, 0)) ||
+ (res = tipc_netlink_start()) ||
+ (res = tipc_socket_init())) {
+ tipc_core_stop();
+ }
+ return res;
+}
+
+
+static int __init tipc_init(void)
+{
+ int res;
+
+ tipc_log_reinit(CONFIG_TIPC_LOG);
+ info("Activated (compiled " __DATE__ " " __TIME__ ")\n");
+
+ tipc_own_addr = 0;
+ tipc_remote_management = 1;
+ tipc_max_publications = 10000;
+ tipc_max_subscriptions = 2000;
+ tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536);
+ tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511);
+ tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1);
+ tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047);
+ tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
+ tipc_net_id = 4711;
+
+ if ((res = tipc_core_start()))
+ err("Unable to start in single node mode\n");
+ else
+ info("Started in single node mode\n");
+ return res;
+}
+
+static void __exit tipc_exit(void)
+{
+ tipc_core_stop_net();
+ tipc_core_stop();
+ info("Deactivated\n");
+ tipc_log_stop();
+}
+
+module_init(tipc_init);
+module_exit(tipc_exit);
+
+MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* Native TIPC API for kernel-space applications (see tipc.h) */
+
+EXPORT_SYMBOL(tipc_attach);
+EXPORT_SYMBOL(tipc_detach);
+EXPORT_SYMBOL(tipc_get_addr);
+EXPORT_SYMBOL(tipc_get_mode);
+EXPORT_SYMBOL(tipc_createport);
+EXPORT_SYMBOL(tipc_deleteport);
+EXPORT_SYMBOL(tipc_ownidentity);
+EXPORT_SYMBOL(tipc_portimportance);
+EXPORT_SYMBOL(tipc_set_portimportance);
+EXPORT_SYMBOL(tipc_portunreliable);
+EXPORT_SYMBOL(tipc_set_portunreliable);
+EXPORT_SYMBOL(tipc_portunreturnable);
+EXPORT_SYMBOL(tipc_set_portunreturnable);
+EXPORT_SYMBOL(tipc_publish);
+EXPORT_SYMBOL(tipc_withdraw);
+EXPORT_SYMBOL(tipc_connect2port);
+EXPORT_SYMBOL(tipc_disconnect);
+EXPORT_SYMBOL(tipc_shutdown);
+EXPORT_SYMBOL(tipc_isconnected);
+EXPORT_SYMBOL(tipc_peer);
+EXPORT_SYMBOL(tipc_ref_valid);
+EXPORT_SYMBOL(tipc_send);
+EXPORT_SYMBOL(tipc_send_buf);
+EXPORT_SYMBOL(tipc_send2name);
+EXPORT_SYMBOL(tipc_forward2name);
+EXPORT_SYMBOL(tipc_send_buf2name);
+EXPORT_SYMBOL(tipc_forward_buf2name);
+EXPORT_SYMBOL(tipc_send2port);
+EXPORT_SYMBOL(tipc_forward2port);
+EXPORT_SYMBOL(tipc_send_buf2port);
+EXPORT_SYMBOL(tipc_forward_buf2port);
+EXPORT_SYMBOL(tipc_multicast);
+/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */
+EXPORT_SYMBOL(tipc_ispublished);
+EXPORT_SYMBOL(tipc_available_nodes);
+
+/* TIPC API for external bearers (see tipc_bearer.h) */
+
+EXPORT_SYMBOL(tipc_block_bearer);
+EXPORT_SYMBOL(tipc_continue);
+EXPORT_SYMBOL(tipc_disable_bearer);
+EXPORT_SYMBOL(tipc_enable_bearer);
+EXPORT_SYMBOL(tipc_recv_msg);
+EXPORT_SYMBOL(tipc_register_media);
+
+/* TIPC API for external APIs (see tipc_port.h) */
+
+EXPORT_SYMBOL(tipc_createport_raw);
+EXPORT_SYMBOL(tipc_set_msg_option);
+EXPORT_SYMBOL(tipc_reject_msg);
+EXPORT_SYMBOL(tipc_send_buf_fast);
+EXPORT_SYMBOL(tipc_acknowledge);
+EXPORT_SYMBOL(tipc_get_port);
+EXPORT_SYMBOL(tipc_get_handle);
+
diff --git a/net/tipc/core.h b/net/tipc/core.h
new file mode 100644
index 000000000000..1f2e8b27a13f
--- /dev/null
+++ b/net/tipc/core.h
@@ -0,0 +1,321 @@
+/*
+ * net/tipc/core.h: Include file for TIPC global declarations
+ *
+ * Copyright (c) 2005-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_CORE_H
+#define _TIPC_CORE_H
+
+#include <linux/tipc.h>
+#include <linux/tipc_config.h>
+#include <net/tipc/tipc_msg.h>
+#include <net/tipc/tipc_port.h>
+#include <net/tipc/tipc_bearer.h>
+#include <net/tipc/tipc.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+#include <linux/interrupt.h>
+#include <asm/atomic.h>
+#include <asm/hardirq.h>
+#include <linux/netdevice.h>
+#include <linux/in.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+
+/*
+ * TIPC debugging code
+ */
+
+#define assert(i) BUG_ON(!(i))
+
+struct tipc_msg;
+extern struct print_buf *TIPC_CONS, *TIPC_LOG;
+extern struct print_buf *TIPC_TEE(struct print_buf *, struct print_buf *);
+void tipc_msg_print(struct print_buf*,struct tipc_msg *,const char*);
+void tipc_printf(struct print_buf *, const char *fmt, ...);
+void tipc_dump(struct print_buf*,const char *fmt, ...);
+
+#ifdef CONFIG_TIPC_DEBUG
+
+/*
+ * TIPC debug support included:
+ * - system messages are printed to TIPC_OUTPUT print buffer
+ * - debug messages are printed to DBG_OUTPUT print buffer
+ */
+
+#define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg)
+#define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg)
+#define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg)
+
+#define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0)
+#define msg_dbg(msg, txt) do {if (DBG_OUTPUT) tipc_msg_print(DBG_OUTPUT, msg, txt);} while(0)
+#define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0)
+
+
+/*
+ * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer,
+ * while DBG_OUTPUT is the null print buffer. These defaults can be changed
+ * here, or on a per .c file basis, by redefining these symbols. The following
+ * print buffer options are available:
+ *
+ * NULL : Output to null print buffer (i.e. print nowhere)
+ * TIPC_CONS : Output to system console
+ * TIPC_LOG : Output to TIPC log buffer
+ * &buf : Output to user-defined buffer (struct print_buf *)
+ * TIPC_TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TIPC_TEE(TIPC_CONS,TIPC_LOG) )
+ */
+
+#ifndef TIPC_OUTPUT
+#define TIPC_OUTPUT TIPC_TEE(TIPC_CONS,TIPC_LOG)
+#endif
+
+#ifndef DBG_OUTPUT
+#define DBG_OUTPUT NULL
+#endif
+
+#else
+
+#ifndef DBG_OUTPUT
+#define DBG_OUTPUT NULL
+#endif
+
+/*
+ * TIPC debug support not included:
+ * - system messages are printed to system console
+ * - debug messages are not printed
+ */
+
+#define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg)
+#define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg)
+#define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg)
+
+#define dbg(fmt, arg...) do {} while (0)
+#define msg_dbg(msg,txt) do {} while (0)
+#define dump(fmt,arg...) do {} while (0)
+
+#endif
+
+
+/*
+ * TIPC-specific error codes
+ */
+
+#define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */
+
+/*
+ * Global configuration variables
+ */
+
+extern u32 tipc_own_addr;
+extern int tipc_max_zones;
+extern int tipc_max_clusters;
+extern int tipc_max_nodes;
+extern int tipc_max_slaves;
+extern int tipc_max_ports;
+extern int tipc_max_subscriptions;
+extern int tipc_max_publications;
+extern int tipc_net_id;
+extern int tipc_remote_management;
+
+/*
+ * Other global variables
+ */
+
+extern int tipc_mode;
+extern int tipc_random;
+extern const char tipc_alphabet[];
+extern atomic_t tipc_user_count;
+
+
+/*
+ * Routines available to privileged subsystems
+ */
+
+extern int tipc_core_start(void);
+extern void tipc_core_stop(void);
+extern int tipc_core_start_net(void);
+extern void tipc_core_stop_net(void);
+
+static inline int delimit(int val, int min, int max)
+{
+ if (val > max)
+ return max;
+ if (val < min)
+ return min;
+ return val;
+}
+
+
+/*
+ * TIPC timer and signal code
+ */
+
+typedef void (*Handler) (unsigned long);
+
+u32 tipc_k_signal(Handler routine, unsigned long argument);
+
+/**
+ * k_init_timer - initialize a timer
+ * @timer: pointer to timer structure
+ * @routine: pointer to routine to invoke when timer expires
+ * @argument: value to pass to routine when timer expires
+ *
+ * Timer must be initialized before use (and terminated when no longer needed).
+ */
+
+static inline void k_init_timer(struct timer_list *timer, Handler routine,
+ unsigned long argument)
+{
+ dbg("initializing timer %p\n", timer);
+ init_timer(timer);
+ timer->function = routine;
+ timer->data = argument;
+}
+
+/**
+ * k_start_timer - start a timer
+ * @timer: pointer to timer structure
+ * @msec: time to delay (in ms)
+ *
+ * Schedules a previously initialized timer for later execution.
+ * If timer is already running, the new timeout overrides the previous request.
+ *
+ * To ensure the timer doesn't expire before the specified delay elapses,
+ * the amount of delay is rounded up when converting to the jiffies
+ * then an additional jiffy is added to account for the fact that
+ * the starting time may be in the middle of the current jiffy.
+ */
+
+static inline void k_start_timer(struct timer_list *timer, unsigned long msec)
+{
+ dbg("starting timer %p for %u\n", timer, msec);
+ mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1);
+}
+
+/**
+ * k_cancel_timer - cancel a timer
+ * @timer: pointer to timer structure
+ *
+ * Cancels a previously initialized timer.
+ * Can be called safely even if the timer is already inactive.
+ *
+ * WARNING: Must not be called when holding locks required by the timer's
+ * timeout routine, otherwise deadlock can occur on SMP systems!
+ */
+
+static inline void k_cancel_timer(struct timer_list *timer)
+{
+ dbg("cancelling timer %p\n", timer);
+ del_timer_sync(timer);
+}
+
+/**
+ * k_term_timer - terminate a timer
+ * @timer: pointer to timer structure
+ *
+ * Prevents further use of a previously initialized timer.
+ *
+ * WARNING: Caller must ensure timer isn't currently running.
+ *
+ * (Do not "enhance" this routine to automatically cancel an active timer,
+ * otherwise deadlock can arise when a timeout routine calls k_term_timer.)
+ */
+
+static inline void k_term_timer(struct timer_list *timer)
+{
+ dbg("terminating timer %p\n", timer);
+}
+
+
+/*
+ * TIPC message buffer code
+ *
+ * TIPC message buffer headroom leaves room for 14 byte Ethernet header,
+ * while ensuring TIPC header is word aligned for quicker access
+ */
+
+#define BUF_HEADROOM 16u
+
+struct tipc_skb_cb {
+ void *handle;
+};
+
+#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
+
+
+static inline struct tipc_msg *buf_msg(struct sk_buff *skb)
+{
+ return (struct tipc_msg *)skb->data;
+}
+
+/**
+ * buf_acquire - creates a TIPC message buffer
+ * @size: message size (including TIPC header)
+ *
+ * Returns a new buffer. Space is reserved for a data link header.
+ */
+
+static inline struct sk_buff *buf_acquire(u32 size)
+{
+ struct sk_buff *skb;
+ unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
+
+ skb = alloc_skb(buf_size, GFP_ATOMIC);
+ if (skb) {
+ skb_reserve(skb, BUF_HEADROOM);
+ skb_put(skb, size);
+ skb->next = NULL;
+ }
+ return skb;
+}
+
+/**
+ * buf_discard - frees a TIPC message buffer
+ * @skb: message buffer
+ *
+ * Frees a new buffer. If passed NULL, just returns.
+ */
+
+static inline void buf_discard(struct sk_buff *skb)
+{
+ if (likely(skb != NULL))
+ kfree_skb(skb);
+}
+
+#endif
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
new file mode 100644
index 000000000000..4f4beefa7830
--- /dev/null
+++ b/net/tipc/dbg.c
@@ -0,0 +1,395 @@
+/*
+ * net/tipc/dbg.c: TIPC print buffer routines for debuggign
+ *
+ * Copyright (c) 1996-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include "dbg.h"
+
+#define MAX_STRING 512
+
+static char print_string[MAX_STRING];
+static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
+
+static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
+struct print_buf *TIPC_CONS = &cons_buf;
+
+static struct print_buf log_buf = { NULL, 0, NULL, NULL };
+struct print_buf *TIPC_LOG = &log_buf;
+
+
+#define FORMAT(PTR,LEN,FMT) \
+{\
+ va_list args;\
+ va_start(args, FMT);\
+ LEN = vsprintf(PTR, FMT, args);\
+ va_end(args);\
+ *(PTR + LEN) = '\0';\
+}
+
+/*
+ * Locking policy when using print buffers.
+ *
+ * 1) Routines of the form printbuf_XXX() rely on the caller to prevent
+ * simultaneous use of the print buffer(s) being manipulated.
+ * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of
+ * 'print_string' and to protect its print buffer(s).
+ * 3) TIPC_TEE() uses 'print_lock' to protect its print buffer(s).
+ * 4) Routines of the form log_XXX() uses 'print_lock' to protect TIPC_LOG.
+ */
+
+/**
+ * tipc_printbuf_init - initialize print buffer to empty
+ */
+
+void tipc_printbuf_init(struct print_buf *pb, char *raw, u32 sz)
+{
+ if (!pb || !raw || (sz < (MAX_STRING + 1)))
+ return;
+
+ pb->crs = pb->buf = raw;
+ pb->size = sz;
+ pb->next = 0;
+ pb->buf[0] = 0;
+ pb->buf[sz-1] = ~0;
+}
+
+/**
+ * tipc_printbuf_reset - reinitialize print buffer to empty state
+ */
+
+void tipc_printbuf_reset(struct print_buf *pb)
+{
+ if (pb && pb->buf)
+ tipc_printbuf_init(pb, pb->buf, pb->size);
+}
+
+/**
+ * tipc_printbuf_empty - test if print buffer is in empty state
+ */
+
+int tipc_printbuf_empty(struct print_buf *pb)
+{
+ return (!pb || !pb->buf || (pb->crs == pb->buf));
+}
+
+/**
+ * tipc_printbuf_validate - check for print buffer overflow
+ *
+ * Verifies that a print buffer has captured all data written to it.
+ * If data has been lost, linearize buffer and prepend an error message
+ *
+ * Returns length of print buffer data string (including trailing NULL)
+ */
+
+int tipc_printbuf_validate(struct print_buf *pb)
+{
+ char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n";
+ char *cp_buf;
+ struct print_buf cb;
+
+ if (!pb || !pb->buf)
+ return 0;
+
+ if (pb->buf[pb->size - 1] == '\0') {
+ cp_buf = kmalloc(pb->size, GFP_ATOMIC);
+ if (cp_buf != NULL){
+ tipc_printbuf_init(&cb, cp_buf, pb->size);
+ tipc_printbuf_move(&cb, pb);
+ tipc_printbuf_move(pb, &cb);
+ kfree(cp_buf);
+ memcpy(pb->buf, err, strlen(err));
+ } else {
+ tipc_printbuf_reset(pb);
+ tipc_printf(pb, err);
+ }
+ }
+ return (pb->crs - pb->buf + 1);
+}
+
+/**
+ * tipc_printbuf_move - move print buffer contents to another print buffer
+ *
+ * Current contents of destination print buffer (if any) are discarded.
+ * Source print buffer becomes empty if a successful move occurs.
+ */
+
+void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from)
+{
+ int len;
+
+ /* Handle the cases where contents can't be moved */
+
+ if (!pb_to || !pb_to->buf)
+ return;
+
+ if (!pb_from || !pb_from->buf) {
+ tipc_printbuf_reset(pb_to);
+ return;
+ }
+
+ if (pb_to->size < pb_from->size) {
+ tipc_printbuf_reset(pb_to);
+ tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***");
+ return;
+ }
+
+ /* Copy data from char after cursor to end (if used) */
+ len = pb_from->buf + pb_from->size - pb_from->crs - 2;
+ if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) {
+ strcpy(pb_to->buf, pb_from->crs + 1);
+ pb_to->crs = pb_to->buf + len;
+ } else
+ pb_to->crs = pb_to->buf;
+
+ /* Copy data from start to cursor (always) */
+ len = pb_from->crs - pb_from->buf;
+ strcpy(pb_to->crs, pb_from->buf);
+ pb_to->crs += len;
+
+ tipc_printbuf_reset(pb_from);
+}
+
+/**
+ * tipc_printf - append formatted output to print buffer chain
+ */
+
+void tipc_printf(struct print_buf *pb, const char *fmt, ...)
+{
+ int chars_to_add;
+ int chars_left;
+ char save_char;
+ struct print_buf *pb_next;
+
+ spin_lock_bh(&print_lock);
+ FORMAT(print_string, chars_to_add, fmt);
+ if (chars_to_add >= MAX_STRING)
+ strcpy(print_string, "*** STRING TOO LONG ***");
+
+ while (pb) {
+ if (pb == TIPC_CONS)
+ printk(print_string);
+ else if (pb->buf) {
+ chars_left = pb->buf + pb->size - pb->crs - 1;
+ if (chars_to_add <= chars_left) {
+ strcpy(pb->crs, print_string);
+ pb->crs += chars_to_add;
+ } else {
+ strcpy(pb->buf, print_string + chars_left);
+ save_char = print_string[chars_left];
+ print_string[chars_left] = 0;
+ strcpy(pb->crs, print_string);
+ print_string[chars_left] = save_char;
+ pb->crs = pb->buf + chars_to_add - chars_left;
+ }
+ }
+ pb_next = pb->next;
+ pb->next = 0;
+ pb = pb_next;
+ }
+ spin_unlock_bh(&print_lock);
+}
+
+/**
+ * TIPC_TEE - perform next output operation on both print buffers
+ */
+
+struct print_buf *TIPC_TEE(struct print_buf *b0, struct print_buf *b1)
+{
+ struct print_buf *pb = b0;
+
+ if (!b0 || (b0 == b1))
+ return b1;
+ if (!b1)
+ return b0;
+
+ spin_lock_bh(&print_lock);
+ while (pb->next) {
+ if ((pb->next == b1) || (pb->next == b0))
+ pb->next = pb->next->next;
+ else
+ pb = pb->next;
+ }
+ pb->next = b1;
+ spin_unlock_bh(&print_lock);
+ return b0;
+}
+
+/**
+ * print_to_console - write string of bytes to console in multiple chunks
+ */
+
+static void print_to_console(char *crs, int len)
+{
+ int rest = len;
+
+ while (rest > 0) {
+ int sz = rest < MAX_STRING ? rest : MAX_STRING;
+ char c = crs[sz];
+
+ crs[sz] = 0;
+ printk((const char *)crs);
+ crs[sz] = c;
+ rest -= sz;
+ crs += sz;
+ }
+}
+
+/**
+ * printbuf_dump - write print buffer contents to console
+ */
+
+static void printbuf_dump(struct print_buf *pb)
+{
+ int len;
+
+ /* Dump print buffer from char after cursor to end (if used) */
+ len = pb->buf + pb->size - pb->crs - 2;
+ if ((pb->buf[pb->size - 1] == 0) && (len > 0))
+ print_to_console(pb->crs + 1, len);
+
+ /* Dump print buffer from start to cursor (always) */
+ len = pb->crs - pb->buf;
+ print_to_console(pb->buf, len);
+}
+
+/**
+ * tipc_dump - dump non-console print buffer(s) to console
+ */
+
+void tipc_dump(struct print_buf *pb, const char *fmt, ...)
+{
+ int len;
+
+ spin_lock_bh(&print_lock);
+ FORMAT(TIPC_CONS->buf, len, fmt);
+ printk(TIPC_CONS->buf);
+
+ for (; pb; pb = pb->next) {
+ if (pb == TIPC_CONS)
+ continue;
+ printk("\n---- Start of dump,%s log ----\n\n",
+ (pb == TIPC_LOG) ? "global" : "local");
+ printbuf_dump(pb);
+ tipc_printbuf_reset(pb);
+ printk("\n-------- End of dump --------\n");
+ }
+ spin_unlock_bh(&print_lock);
+}
+
+/**
+ * tipc_log_stop - free up TIPC log print buffer
+ */
+
+void tipc_log_stop(void)
+{
+ spin_lock_bh(&print_lock);
+ if (TIPC_LOG->buf) {
+ kfree(TIPC_LOG->buf);
+ TIPC_LOG->buf = NULL;
+ }
+ spin_unlock_bh(&print_lock);
+}
+
+/**
+ * tipc_log_reinit - set TIPC log print buffer to specified size
+ */
+
+void tipc_log_reinit(int log_size)
+{
+ tipc_log_stop();
+
+ if (log_size) {
+ if (log_size <= MAX_STRING)
+ log_size = MAX_STRING + 1;
+ spin_lock_bh(&print_lock);
+ tipc_printbuf_init(TIPC_LOG, kmalloc(log_size, GFP_ATOMIC), log_size);
+ spin_unlock_bh(&print_lock);
+ }
+}
+
+/**
+ * tipc_log_resize - reconfigure size of TIPC log buffer
+ */
+
+struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space)
+{
+ u32 value;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ value = *(u32 *)TLV_DATA(req_tlv_area);
+ value = ntohl(value);
+ if (value != delimit(value, 0, 32768))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (log size must be 0-32768)");
+ tipc_log_reinit(value);
+ return tipc_cfg_reply_none();
+}
+
+/**
+ * tipc_log_dump - capture TIPC log buffer contents in configuration message
+ */
+
+struct sk_buff *tipc_log_dump(void)
+{
+ struct sk_buff *reply;
+
+ spin_lock_bh(&print_lock);
+ if (!TIPC_LOG->buf)
+ reply = tipc_cfg_reply_ultra_string("log not activated\n");
+ else if (tipc_printbuf_empty(TIPC_LOG))
+ reply = tipc_cfg_reply_ultra_string("log is empty\n");
+ else {
+ struct tlv_desc *rep_tlv;
+ struct print_buf pb;
+ int str_len;
+
+ str_len = min(TIPC_LOG->size, 32768u);
+ reply = tipc_cfg_reply_alloc(TLV_SPACE(str_len));
+ if (reply) {
+ rep_tlv = (struct tlv_desc *)reply->data;
+ tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), str_len);
+ tipc_printbuf_move(&pb, TIPC_LOG);
+ str_len = strlen(TLV_DATA(rep_tlv)) + 1;
+ skb_put(reply, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+ }
+ }
+ spin_unlock_bh(&print_lock);
+ return reply;
+}
+
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h
new file mode 100644
index 000000000000..227f050d2a52
--- /dev/null
+++ b/net/tipc/dbg.h
@@ -0,0 +1,59 @@
+/*
+ * net/tipc/dbg.h: Include file for TIPC print buffer routines
+ *
+ * Copyright (c) 1997-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_DBG_H
+#define _TIPC_DBG_H
+
+struct print_buf {
+ char *buf;
+ u32 size;
+ char *crs;
+ struct print_buf *next;
+};
+
+void tipc_printbuf_init(struct print_buf *pb, char *buf, u32 sz);
+void tipc_printbuf_reset(struct print_buf *pb);
+int tipc_printbuf_empty(struct print_buf *pb);
+int tipc_printbuf_validate(struct print_buf *pb);
+void tipc_printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
+
+void tipc_log_reinit(int log_size);
+void tipc_log_stop(void);
+
+struct sk_buff *tipc_log_resize(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_log_dump(void);
+
+#endif
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
new file mode 100644
index 000000000000..53ba4630c10d
--- /dev/null
+++ b/net/tipc/discover.c
@@ -0,0 +1,318 @@
+/*
+ * net/tipc/discover.c
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "link.h"
+#include "zone.h"
+#include "discover.h"
+#include "port.h"
+#include "name_table.h"
+
+#define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */
+#define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */
+#define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */
+
+#if 0
+#define GET_NODE_INFO 300
+#define GET_NODE_INFO_RESULT 301
+#define FORWARD_LINK_PROBE 302
+#define LINK_REQUEST_REJECTED 303
+#define LINK_REQUEST_ACCEPTED 304
+#define DROP_LINK_REQUEST 305
+#define CHECK_LINK_COUNT 306
+#endif
+
+/*
+ * TODO: Most of the inter-cluster setup stuff should be
+ * rewritten, and be made conformant with specification.
+ */
+
+
+/**
+ * struct link_req - information about an ongoing link setup request
+ * @bearer: bearer issuing requests
+ * @dest: destination address for request messages
+ * @buf: request message to be (repeatedly) sent
+ * @timer: timer governing period between requests
+ * @timer_intv: current interval between requests (in ms)
+ */
+struct link_req {
+ struct bearer *bearer;
+ struct tipc_media_addr dest;
+ struct sk_buff *buf;
+ struct timer_list timer;
+ unsigned int timer_intv;
+};
+
+
+#if 0
+int disc_create_link(const struct tipc_link_create *argv)
+{
+ /*
+ * Code for inter cluster link setup here
+ */
+ return TIPC_OK;
+}
+#endif
+
+/*
+ * disc_lost_link(): A link has lost contact
+ */
+
+void tipc_disc_link_event(u32 addr, char *name, int up)
+{
+ if (in_own_cluster(addr))
+ return;
+ /*
+ * Code for inter cluster link setup here
+ */
+}
+
+/**
+ * tipc_disc_init_msg - initialize a link setup message
+ * @type: message type (request or response)
+ * @req_links: number of links associated with message
+ * @dest_domain: network domain of node(s) which should respond to message
+ * @b_ptr: ptr to bearer issuing message
+ */
+
+struct sk_buff *tipc_disc_init_msg(u32 type,
+ u32 req_links,
+ u32 dest_domain,
+ struct bearer *b_ptr)
+{
+ struct sk_buff *buf = buf_acquire(DSC_H_SIZE);
+ struct tipc_msg *msg;
+
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE,
+ dest_domain);
+ msg_set_non_seq(msg);
+ msg_set_req_links(msg, req_links);
+ msg_set_dest_domain(msg, dest_domain);
+ msg_set_bc_netid(msg, tipc_net_id);
+ msg_set_media_addr(msg, &b_ptr->publ.addr);
+ }
+ return buf;
+}
+
+/**
+ * tipc_disc_recv_msg - handle incoming link setup message (request or response)
+ * @buf: buffer containing message
+ */
+
+void tipc_disc_recv_msg(struct sk_buff *buf)
+{
+ struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle;
+ struct link *link;
+ struct tipc_media_addr media_addr;
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 dest = msg_dest_domain(msg);
+ u32 orig = msg_prevnode(msg);
+ u32 net_id = msg_bc_netid(msg);
+ u32 type = msg_type(msg);
+
+ msg_get_media_addr(msg,&media_addr);
+ msg_dbg(msg, "RECV:");
+ buf_discard(buf);
+
+ if (net_id != tipc_net_id)
+ return;
+ if (!tipc_addr_domain_valid(dest))
+ return;
+ if (!tipc_addr_node_valid(orig))
+ return;
+ if (orig == tipc_own_addr)
+ return;
+ if (!in_scope(dest, tipc_own_addr))
+ return;
+ if (is_slave(tipc_own_addr) && is_slave(orig))
+ return;
+ if (is_slave(orig) && !in_own_cluster(orig))
+ return;
+ if (in_own_cluster(orig)) {
+ /* Always accept link here */
+ struct sk_buff *rbuf;
+ struct tipc_media_addr *addr;
+ struct node *n_ptr = tipc_node_find(orig);
+ int link_up;
+ dbg(" in own cluster\n");
+ if (n_ptr == NULL) {
+ n_ptr = tipc_node_create(orig);
+ }
+ if (n_ptr == NULL) {
+ warn("Memory squeeze; Failed to create node\n");
+ return;
+ }
+ spin_lock_bh(&n_ptr->lock);
+ link = n_ptr->links[b_ptr->identity];
+ if (!link) {
+ dbg("creating link\n");
+ link = tipc_link_create(b_ptr, orig, &media_addr);
+ if (!link) {
+ spin_unlock_bh(&n_ptr->lock);
+ return;
+ }
+ }
+ addr = &link->media_addr;
+ if (memcmp(addr, &media_addr, sizeof(*addr))) {
+ char addr_string[16];
+
+ warn("New bearer address for %s\n",
+ addr_string_fill(addr_string, orig));
+ memcpy(addr, &media_addr, sizeof(*addr));
+ tipc_link_reset(link);
+ }
+ link_up = tipc_link_is_up(link);
+ spin_unlock_bh(&n_ptr->lock);
+ if ((type == DSC_RESP_MSG) || link_up)
+ return;
+ rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
+ if (rbuf != NULL) {
+ msg_dbg(buf_msg(rbuf),"SEND:");
+ b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr);
+ buf_discard(rbuf);
+ }
+ }
+}
+
+/**
+ * tipc_disc_stop_link_req - stop sending periodic link setup requests
+ * @req: ptr to link request structure
+ */
+
+void tipc_disc_stop_link_req(struct link_req *req)
+{
+ if (!req)
+ return;
+
+ k_cancel_timer(&req->timer);
+ k_term_timer(&req->timer);
+ buf_discard(req->buf);
+ kfree(req);
+}
+
+/**
+ * tipc_disc_update_link_req - update frequency of periodic link setup requests
+ * @req: ptr to link request structure
+ */
+
+void tipc_disc_update_link_req(struct link_req *req)
+{
+ if (!req)
+ return;
+
+ if (req->timer_intv == TIPC_LINK_REQ_SLOW) {
+ if (!req->bearer->nodes.count) {
+ req->timer_intv = TIPC_LINK_REQ_FAST;
+ k_start_timer(&req->timer, req->timer_intv);
+ }
+ } else if (req->timer_intv == TIPC_LINK_REQ_FAST) {
+ if (req->bearer->nodes.count) {
+ req->timer_intv = TIPC_LINK_REQ_SLOW;
+ k_start_timer(&req->timer, req->timer_intv);
+ }
+ } else {
+ /* leave timer "as is" if haven't yet reached a "normal" rate */
+ }
+}
+
+/**
+ * disc_timeout - send a periodic link setup request
+ * @req: ptr to link request structure
+ *
+ * Called whenever a link setup request timer associated with a bearer expires.
+ */
+
+static void disc_timeout(struct link_req *req)
+{
+ spin_lock_bh(&req->bearer->publ.lock);
+
+ req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest);
+
+ if ((req->timer_intv == TIPC_LINK_REQ_SLOW) ||
+ (req->timer_intv == TIPC_LINK_REQ_FAST)) {
+ /* leave timer interval "as is" if already at a "normal" rate */
+ } else {
+ req->timer_intv *= 2;
+ if (req->timer_intv > TIPC_LINK_REQ_SLOW)
+ req->timer_intv = TIPC_LINK_REQ_SLOW;
+ if ((req->timer_intv == TIPC_LINK_REQ_FAST) &&
+ (req->bearer->nodes.count))
+ req->timer_intv = TIPC_LINK_REQ_SLOW;
+ }
+ k_start_timer(&req->timer, req->timer_intv);
+
+ spin_unlock_bh(&req->bearer->publ.lock);
+}
+
+/**
+ * tipc_disc_init_link_req - start sending periodic link setup requests
+ * @b_ptr: ptr to bearer issuing requests
+ * @dest: destination address for request messages
+ * @dest_domain: network domain of node(s) which should respond to message
+ * @req_links: max number of desired links
+ *
+ * Returns pointer to link request structure, or NULL if unable to create.
+ */
+
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
+ const struct tipc_media_addr *dest,
+ u32 dest_domain,
+ u32 req_links)
+{
+ struct link_req *req;
+
+ req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC);
+ if (!req)
+ return NULL;
+
+ req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
+ if (!req->buf) {
+ kfree(req);
+ return NULL;
+ }
+
+ memcpy(&req->dest, dest, sizeof(*dest));
+ req->bearer = b_ptr;
+ req->timer_intv = TIPC_LINK_REQ_INIT;
+ k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
+ k_start_timer(&req->timer, req->timer_intv);
+ return req;
+}
+
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
new file mode 100644
index 000000000000..0454fd1ae7f3
--- /dev/null
+++ b/net/tipc/discover.h
@@ -0,0 +1,58 @@
+/*
+ * net/tipc/discover.h
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_DISCOVER_H
+#define _TIPC_DISCOVER_H
+
+#include "core.h"
+
+struct link_req;
+
+struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
+ const struct tipc_media_addr *dest,
+ u32 dest_domain,
+ u32 req_links);
+void tipc_disc_update_link_req(struct link_req *req);
+void tipc_disc_stop_link_req(struct link_req *req);
+
+void tipc_disc_recv_msg(struct sk_buff *buf);
+
+void tipc_disc_link_event(u32 addr, char *name, int up);
+#if 0
+int disc_create_link(const struct tipc_link_create *argv);
+#endif
+
+#endif
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
new file mode 100644
index 000000000000..1f8d83b9c8b4
--- /dev/null
+++ b/net/tipc/eth_media.c
@@ -0,0 +1,297 @@
+/*
+ * net/tipc/eth_media.c: Ethernet bearer support for TIPC
+ *
+ * Copyright (c) 2001-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <net/tipc/tipc.h>
+#include <net/tipc/tipc_bearer.h>
+#include <net/tipc/tipc_msg.h>
+#include <linux/netdevice.h>
+
+#define MAX_ETH_BEARERS 2
+#define ETH_LINK_PRIORITY TIPC_DEF_LINK_PRI
+#define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL
+#define ETH_LINK_WINDOW TIPC_DEF_LINK_WIN
+
+/**
+ * struct eth_bearer - Ethernet bearer data structure
+ * @bearer: ptr to associated "generic" bearer structure
+ * @dev: ptr to associated Ethernet network device
+ * @tipc_packet_type: used in binding TIPC to Ethernet driver
+ */
+
+struct eth_bearer {
+ struct tipc_bearer *bearer;
+ struct net_device *dev;
+ struct packet_type tipc_packet_type;
+};
+
+static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
+static int eth_started = 0;
+static struct notifier_block notifier;
+
+/**
+ * send_msg - send a TIPC message out over an Ethernet interface
+ */
+
+static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
+ struct tipc_media_addr *dest)
+{
+ struct sk_buff *clone;
+ struct net_device *dev;
+
+ clone = skb_clone(buf, GFP_ATOMIC);
+ if (clone) {
+ clone->nh.raw = clone->data;
+ dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
+ clone->dev = dev;
+ dev->hard_header(clone, dev, ETH_P_TIPC,
+ &dest->dev_addr.eth_addr,
+ dev->dev_addr, clone->len);
+ dev_queue_xmit(clone);
+ }
+ return TIPC_OK;
+}
+
+/**
+ * recv_msg - handle incoming TIPC message from an Ethernet interface
+ *
+ * Routine truncates any Ethernet padding/CRC appended to the message,
+ * and ensures message size matches actual length
+ */
+
+static int recv_msg(struct sk_buff *buf, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+{
+ struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
+ u32 size;
+
+ if (likely(eb_ptr->bearer)) {
+ size = msg_size((struct tipc_msg *)buf->data);
+ skb_trim(buf, size);
+ if (likely(buf->len == size)) {
+ buf->next = NULL;
+ tipc_recv_msg(buf, eb_ptr->bearer);
+ } else {
+ kfree_skb(buf);
+ }
+ } else {
+ kfree_skb(buf);
+ }
+ return TIPC_OK;
+}
+
+/**
+ * enable_bearer - attach TIPC bearer to an Ethernet interface
+ */
+
+static int enable_bearer(struct tipc_bearer *tb_ptr)
+{
+ struct net_device *dev = dev_base;
+ struct eth_bearer *eb_ptr = &eth_bearers[0];
+ struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
+ char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
+
+ /* Find device with specified name */
+
+ while (dev && dev->name &&
+ (memcmp(dev->name, driver_name, strlen(dev->name)))) {
+ dev = dev->next;
+ }
+ if (!dev)
+ return -ENODEV;
+
+ /* Find Ethernet bearer for device (or create one) */
+
+ for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++);
+ if (eb_ptr == stop)
+ return -EDQUOT;
+ if (!eb_ptr->dev) {
+ eb_ptr->dev = dev;
+ eb_ptr->tipc_packet_type.type = __constant_htons(ETH_P_TIPC);
+ eb_ptr->tipc_packet_type.dev = dev;
+ eb_ptr->tipc_packet_type.func = recv_msg;
+ eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
+ INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
+ dev_hold(dev);
+ dev_add_pack(&eb_ptr->tipc_packet_type);
+ }
+
+ /* Associate TIPC bearer with Ethernet bearer */
+
+ eb_ptr->bearer = tb_ptr;
+ tb_ptr->usr_handle = (void *)eb_ptr;
+ tb_ptr->mtu = dev->mtu;
+ tb_ptr->blocked = 0;
+ tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
+ memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN);
+ return 0;
+}
+
+/**
+ * disable_bearer - detach TIPC bearer from an Ethernet interface
+ *
+ * We really should do dev_remove_pack() here, but this function can not be
+ * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
+ * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit.
+ */
+
+static void disable_bearer(struct tipc_bearer *tb_ptr)
+{
+ ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0;
+}
+
+/**
+ * recv_notification - handle device updates from OS
+ *
+ * Change the state of the Ethernet bearer (if any) associated with the
+ * specified device.
+ */
+
+static int recv_notification(struct notifier_block *nb, unsigned long evt,
+ void *dv)
+{
+ struct net_device *dev = (struct net_device *)dv;
+ struct eth_bearer *eb_ptr = &eth_bearers[0];
+ struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
+
+ while ((eb_ptr->dev != dev)) {
+ if (++eb_ptr == stop)
+ return NOTIFY_DONE; /* couldn't find device */
+ }
+ if (!eb_ptr->bearer)
+ return NOTIFY_DONE; /* bearer had been disabled */
+
+ eb_ptr->bearer->mtu = dev->mtu;
+
+ switch (evt) {
+ case NETDEV_CHANGE:
+ if (netif_carrier_ok(dev))
+ tipc_continue(eb_ptr->bearer);
+ else
+ tipc_block_bearer(eb_ptr->bearer->name);
+ break;
+ case NETDEV_UP:
+ tipc_continue(eb_ptr->bearer);
+ break;
+ case NETDEV_DOWN:
+ tipc_block_bearer(eb_ptr->bearer->name);
+ break;
+ case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGEADDR:
+ tipc_block_bearer(eb_ptr->bearer->name);
+ tipc_continue(eb_ptr->bearer);
+ break;
+ case NETDEV_UNREGISTER:
+ case NETDEV_CHANGENAME:
+ tipc_disable_bearer(eb_ptr->bearer->name);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+/**
+ * eth_addr2str - convert Ethernet address to string
+ */
+
+static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
+{
+ unchar *addr = (unchar *)&a->dev_addr;
+
+ if (str_size < 18)
+ *str_buf = '\0';
+ else
+ sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+ return str_buf;
+}
+
+/**
+ * tipc_eth_media_start - activate Ethernet bearer support
+ *
+ * Register Ethernet media type with TIPC bearer code. Also register
+ * with OS for notifications about device state changes.
+ */
+
+int tipc_eth_media_start(void)
+{
+ struct tipc_media_addr bcast_addr;
+ int res;
+
+ if (eth_started)
+ return -EINVAL;
+
+ memset(&bcast_addr, 0xff, sizeof(bcast_addr));
+ memset(eth_bearers, 0, sizeof(eth_bearers));
+
+ res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
+ enable_bearer, disable_bearer, send_msg,
+ eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
+ ETH_LINK_TOLERANCE, ETH_LINK_WINDOW);
+ if (res)
+ return res;
+
+ notifier.notifier_call = &recv_notification;
+ notifier.priority = 0;
+ res = register_netdevice_notifier(&notifier);
+ if (!res)
+ eth_started = 1;
+ return res;
+}
+
+/**
+ * tipc_eth_media_stop - deactivate Ethernet bearer support
+ */
+
+void tipc_eth_media_stop(void)
+{
+ int i;
+
+ if (!eth_started)
+ return;
+
+ unregister_netdevice_notifier(&notifier);
+ for (i = 0; i < MAX_ETH_BEARERS ; i++) {
+ if (eth_bearers[i].bearer) {
+ eth_bearers[i].bearer->blocked = 1;
+ eth_bearers[i].bearer = 0;
+ }
+ if (eth_bearers[i].dev) {
+ dev_remove_pack(&eth_bearers[i].tipc_packet_type);
+ dev_put(eth_bearers[i].dev);
+ }
+ }
+ memset(&eth_bearers, 0, sizeof(eth_bearers));
+ eth_started = 0;
+}
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
new file mode 100644
index 000000000000..966f70a1b608
--- /dev/null
+++ b/net/tipc/handler.c
@@ -0,0 +1,132 @@
+/*
+ * net/tipc/handler.c: TIPC signal handling
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+
+struct queue_item {
+ struct list_head next_signal;
+ void (*handler) (unsigned long);
+ unsigned long data;
+};
+
+static kmem_cache_t *tipc_queue_item_cache;
+static struct list_head signal_queue_head;
+static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED;
+static int handler_enabled = 0;
+
+static void process_signal_queue(unsigned long dummy);
+
+static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0);
+
+
+unsigned int tipc_k_signal(Handler routine, unsigned long argument)
+{
+ struct queue_item *item;
+
+ if (!handler_enabled) {
+ err("Signal request ignored by handler\n");
+ return -ENOPROTOOPT;
+ }
+
+ spin_lock_bh(&qitem_lock);
+ item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
+ if (!item) {
+ err("Signal queue out of memory\n");
+ spin_unlock_bh(&qitem_lock);
+ return -ENOMEM;
+ }
+ item->handler = routine;
+ item->data = argument;
+ list_add_tail(&item->next_signal, &signal_queue_head);
+ spin_unlock_bh(&qitem_lock);
+ tasklet_schedule(&tipc_tasklet);
+ return 0;
+}
+
+static void process_signal_queue(unsigned long dummy)
+{
+ struct queue_item *__volatile__ item;
+ struct list_head *l, *n;
+
+ spin_lock_bh(&qitem_lock);
+ list_for_each_safe(l, n, &signal_queue_head) {
+ item = list_entry(l, struct queue_item, next_signal);
+ list_del(&item->next_signal);
+ spin_unlock_bh(&qitem_lock);
+ item->handler(item->data);
+ spin_lock_bh(&qitem_lock);
+ kmem_cache_free(tipc_queue_item_cache, item);
+ }
+ spin_unlock_bh(&qitem_lock);
+}
+
+int tipc_handler_start(void)
+{
+ tipc_queue_item_cache =
+ kmem_cache_create("tipc_queue_items", sizeof(struct queue_item),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (!tipc_queue_item_cache)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&signal_queue_head);
+ tasklet_enable(&tipc_tasklet);
+ handler_enabled = 1;
+ return 0;
+}
+
+void tipc_handler_stop(void)
+{
+ struct list_head *l, *n;
+ struct queue_item *item;
+
+ if (!handler_enabled)
+ return;
+
+ handler_enabled = 0;
+ tasklet_disable(&tipc_tasklet);
+ tasklet_kill(&tipc_tasklet);
+
+ spin_lock_bh(&qitem_lock);
+ list_for_each_safe(l, n, &signal_queue_head) {
+ item = list_entry(l, struct queue_item, next_signal);
+ list_del(&item->next_signal);
+ kmem_cache_free(tipc_queue_item_cache, item);
+ }
+ spin_unlock_bh(&qitem_lock);
+
+ kmem_cache_destroy(tipc_queue_item_cache);
+}
+
diff --git a/net/tipc/link.c b/net/tipc/link.c
new file mode 100644
index 000000000000..511872afa459
--- /dev/null
+++ b/net/tipc/link.c
@@ -0,0 +1,3166 @@
+/*
+ * net/tipc/link.c: TIPC link code
+ *
+ * Copyright (c) 1996-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "link.h"
+#include "net.h"
+#include "node.h"
+#include "port.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "name_distr.h"
+#include "bearer.h"
+#include "name_table.h"
+#include "discover.h"
+#include "config.h"
+#include "bcast.h"
+
+
+/*
+ * Limit for deferred reception queue:
+ */
+
+#define DEF_QUEUE_LIMIT 256u
+
+/*
+ * Link state events:
+ */
+
+#define STARTING_EVT 856384768 /* link processing trigger */
+#define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */
+#define TIMEOUT_EVT 560817u /* link timer expired */
+
+/*
+ * The following two 'message types' is really just implementation
+ * data conveniently stored in the message header.
+ * They must not be considered part of the protocol
+ */
+#define OPEN_MSG 0
+#define CLOSED_MSG 1
+
+/*
+ * State value stored in 'exp_msg_count'
+ */
+
+#define START_CHANGEOVER 100000u
+
+/**
+ * struct link_name - deconstructed link name
+ * @addr_local: network address of node at this end
+ * @if_local: name of interface at this end
+ * @addr_peer: network address of node at far end
+ * @if_peer: name of interface at far end
+ */
+
+struct link_name {
+ u32 addr_local;
+ char if_local[TIPC_MAX_IF_NAME];
+ u32 addr_peer;
+ char if_peer[TIPC_MAX_IF_NAME];
+};
+
+#if 0
+
+/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
+
+/**
+ * struct link_event - link up/down event notification
+ */
+
+struct link_event {
+ u32 addr;
+ int up;
+ void (*fcn)(u32, char *, int);
+ char name[TIPC_MAX_LINK_NAME];
+};
+
+#endif
+
+static void link_handle_out_of_seq_msg(struct link *l_ptr,
+ struct sk_buff *buf);
+static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf);
+static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf);
+static void link_set_supervision_props(struct link *l_ptr, u32 tolerance);
+static int link_send_sections_long(struct port *sender,
+ struct iovec const *msg_sect,
+ u32 num_sect, u32 destnode);
+static void link_check_defragm_bufs(struct link *l_ptr);
+static void link_state_event(struct link *l_ptr, u32 event);
+static void link_reset_statistics(struct link *l_ptr);
+static void link_print(struct link *l_ptr, struct print_buf *buf,
+ const char *str);
+
+/*
+ * Debugging code used by link routines only
+ *
+ * When debugging link problems on a system that has multiple links,
+ * the standard TIPC debugging routines may not be useful since they
+ * allow the output from multiple links to be intermixed. For this reason
+ * routines of the form "dbg_link_XXX()" have been created that will capture
+ * debug info into a link's personal print buffer, which can then be dumped
+ * into the TIPC system log (LOG) upon request.
+ *
+ * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size
+ * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0,
+ * the dbg_link_XXX() routines simply send their output to the standard
+ * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful
+ * when there is only a single link in the system being debugged.
+ *
+ * Notes:
+ * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes)
+ * - "l_ptr" must be valid when using dbg_link_XXX() macros
+ */
+
+#define LINK_LOG_BUF_SIZE 0
+
+#define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0)
+#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0)
+#define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0)
+#define dbg_link_dump() do { \
+ if (LINK_LOG_BUF_SIZE) { \
+ tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \
+ tipc_printbuf_move(LOG, &l_ptr->print_buf); \
+ } \
+} while (0)
+
+static inline void dbg_print_link(struct link *l_ptr, const char *str)
+{
+ if (DBG_OUTPUT)
+ link_print(l_ptr, DBG_OUTPUT, str);
+}
+
+static inline void dbg_print_buf_chain(struct sk_buff *root_buf)
+{
+ if (DBG_OUTPUT) {
+ struct sk_buff *buf = root_buf;
+
+ while (buf) {
+ msg_dbg(buf_msg(buf), "In chain: ");
+ buf = buf->next;
+ }
+ }
+}
+
+/*
+ * Simple inlined link routines
+ */
+
+static inline unsigned int align(unsigned int i)
+{
+ return (i + 3) & ~3u;
+}
+
+static inline int link_working_working(struct link *l_ptr)
+{
+ return (l_ptr->state == WORKING_WORKING);
+}
+
+static inline int link_working_unknown(struct link *l_ptr)
+{
+ return (l_ptr->state == WORKING_UNKNOWN);
+}
+
+static inline int link_reset_unknown(struct link *l_ptr)
+{
+ return (l_ptr->state == RESET_UNKNOWN);
+}
+
+static inline int link_reset_reset(struct link *l_ptr)
+{
+ return (l_ptr->state == RESET_RESET);
+}
+
+static inline int link_blocked(struct link *l_ptr)
+{
+ return (l_ptr->exp_msg_count || l_ptr->blocked);
+}
+
+static inline int link_congested(struct link *l_ptr)
+{
+ return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
+}
+
+static inline u32 link_max_pkt(struct link *l_ptr)
+{
+ return l_ptr->max_pkt;
+}
+
+static inline void link_init_max_pkt(struct link *l_ptr)
+{
+ u32 max_pkt;
+
+ max_pkt = (l_ptr->b_ptr->publ.mtu & ~3);
+ if (max_pkt > MAX_MSG_SIZE)
+ max_pkt = MAX_MSG_SIZE;
+
+ l_ptr->max_pkt_target = max_pkt;
+ if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT)
+ l_ptr->max_pkt = l_ptr->max_pkt_target;
+ else
+ l_ptr->max_pkt = MAX_PKT_DEFAULT;
+
+ l_ptr->max_pkt_probes = 0;
+}
+
+static inline u32 link_next_sent(struct link *l_ptr)
+{
+ if (l_ptr->next_out)
+ return msg_seqno(buf_msg(l_ptr->next_out));
+ return mod(l_ptr->next_out_no);
+}
+
+static inline u32 link_last_sent(struct link *l_ptr)
+{
+ return mod(link_next_sent(l_ptr) - 1);
+}
+
+/*
+ * Simple non-inlined link routines (i.e. referenced outside this file)
+ */
+
+int tipc_link_is_up(struct link *l_ptr)
+{
+ if (!l_ptr)
+ return 0;
+ return (link_working_working(l_ptr) || link_working_unknown(l_ptr));
+}
+
+int tipc_link_is_active(struct link *l_ptr)
+{
+ return ((l_ptr->owner->active_links[0] == l_ptr) ||
+ (l_ptr->owner->active_links[1] == l_ptr));
+}
+
+/**
+ * link_name_validate - validate & (optionally) deconstruct link name
+ * @name - ptr to link name string
+ * @name_parts - ptr to area for link name components (or NULL if not needed)
+ *
+ * Returns 1 if link name is valid, otherwise 0.
+ */
+
+static int link_name_validate(const char *name, struct link_name *name_parts)
+{
+ char name_copy[TIPC_MAX_LINK_NAME];
+ char *addr_local;
+ char *if_local;
+ char *addr_peer;
+ char *if_peer;
+ char dummy;
+ u32 z_local, c_local, n_local;
+ u32 z_peer, c_peer, n_peer;
+ u32 if_local_len;
+ u32 if_peer_len;
+
+ /* copy link name & ensure length is OK */
+
+ name_copy[TIPC_MAX_LINK_NAME - 1] = 0;
+ /* need above in case non-Posix strncpy() doesn't pad with nulls */
+ strncpy(name_copy, name, TIPC_MAX_LINK_NAME);
+ if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0)
+ return 0;
+
+ /* ensure all component parts of link name are present */
+
+ addr_local = name_copy;
+ if ((if_local = strchr(addr_local, ':')) == NULL)
+ return 0;
+ *(if_local++) = 0;
+ if ((addr_peer = strchr(if_local, '-')) == NULL)
+ return 0;
+ *(addr_peer++) = 0;
+ if_local_len = addr_peer - if_local;
+ if ((if_peer = strchr(addr_peer, ':')) == NULL)
+ return 0;
+ *(if_peer++) = 0;
+ if_peer_len = strlen(if_peer) + 1;
+
+ /* validate component parts of link name */
+
+ if ((sscanf(addr_local, "%u.%u.%u%c",
+ &z_local, &c_local, &n_local, &dummy) != 3) ||
+ (sscanf(addr_peer, "%u.%u.%u%c",
+ &z_peer, &c_peer, &n_peer, &dummy) != 3) ||
+ (z_local > 255) || (c_local > 4095) || (n_local > 4095) ||
+ (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) ||
+ (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) ||
+ (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) ||
+ (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) ||
+ (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1)))
+ return 0;
+
+ /* return link name components, if necessary */
+
+ if (name_parts) {
+ name_parts->addr_local = tipc_addr(z_local, c_local, n_local);
+ strcpy(name_parts->if_local, if_local);
+ name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer);
+ strcpy(name_parts->if_peer, if_peer);
+ }
+ return 1;
+}
+
+/**
+ * link_timeout - handle expiration of link timer
+ * @l_ptr: pointer to link
+ *
+ * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict
+ * with tipc_link_delete(). (There is no risk that the node will be deleted by
+ * another thread because tipc_link_delete() always cancels the link timer before
+ * tipc_node_delete() is called.)
+ */
+
+static void link_timeout(struct link *l_ptr)
+{
+ tipc_node_lock(l_ptr->owner);
+
+ /* update counters used in statistical profiling of send traffic */
+
+ l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size;
+ l_ptr->stats.queue_sz_counts++;
+
+ if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz)
+ l_ptr->stats.max_queue_sz = l_ptr->out_queue_size;
+
+ if (l_ptr->first_out) {
+ struct tipc_msg *msg = buf_msg(l_ptr->first_out);
+ u32 length = msg_size(msg);
+
+ if ((msg_user(msg) == MSG_FRAGMENTER)
+ && (msg_type(msg) == FIRST_FRAGMENT)) {
+ length = msg_size(msg_get_wrapped(msg));
+ }
+ if (length) {
+ l_ptr->stats.msg_lengths_total += length;
+ l_ptr->stats.msg_length_counts++;
+ if (length <= 64)
+ l_ptr->stats.msg_length_profile[0]++;
+ else if (length <= 256)
+ l_ptr->stats.msg_length_profile[1]++;
+ else if (length <= 1024)
+ l_ptr->stats.msg_length_profile[2]++;
+ else if (length <= 4096)
+ l_ptr->stats.msg_length_profile[3]++;
+ else if (length <= 16384)
+ l_ptr->stats.msg_length_profile[4]++;
+ else if (length <= 32768)
+ l_ptr->stats.msg_length_profile[5]++;
+ else
+ l_ptr->stats.msg_length_profile[6]++;
+ }
+ }
+
+ /* do all other link processing performed on a periodic basis */
+
+ link_check_defragm_bufs(l_ptr);
+
+ link_state_event(l_ptr, TIMEOUT_EVT);
+
+ if (l_ptr->next_out)
+ tipc_link_push_queue(l_ptr);
+
+ tipc_node_unlock(l_ptr->owner);
+}
+
+static inline void link_set_timer(struct link *l_ptr, u32 time)
+{
+ k_start_timer(&l_ptr->timer, time);
+}
+
+/**
+ * tipc_link_create - create a new link
+ * @b_ptr: pointer to associated bearer
+ * @peer: network address of node at other end of link
+ * @media_addr: media address to use when sending messages over link
+ *
+ * Returns pointer to link.
+ */
+
+struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+ const struct tipc_media_addr *media_addr)
+{
+ struct link *l_ptr;
+ struct tipc_msg *msg;
+ char *if_name;
+
+ l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC);
+ if (!l_ptr) {
+ warn("Memory squeeze; Failed to create link\n");
+ return NULL;
+ }
+ memset(l_ptr, 0, sizeof(*l_ptr));
+
+ l_ptr->addr = peer;
+ if_name = strchr(b_ptr->publ.name, ':') + 1;
+ sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:",
+ tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
+ tipc_node(tipc_own_addr),
+ if_name,
+ tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
+ /* note: peer i/f is appended to link name by reset/activate */
+ memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
+ k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
+ list_add_tail(&l_ptr->link_list, &b_ptr->links);
+ l_ptr->checkpoint = 1;
+ l_ptr->b_ptr = b_ptr;
+ link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
+ l_ptr->state = RESET_UNKNOWN;
+
+ l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
+ msg = l_ptr->pmsg;
+ msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+ msg_set_size(msg, sizeof(l_ptr->proto_msg));
+ msg_set_session(msg, tipc_random);
+ msg_set_bearer_id(msg, b_ptr->identity);
+ strcpy((char *)msg_data(msg), if_name);
+
+ l_ptr->priority = b_ptr->priority;
+ tipc_link_set_queue_limits(l_ptr, b_ptr->media->window);
+
+ link_init_max_pkt(l_ptr);
+
+ l_ptr->next_out_no = 1;
+ INIT_LIST_HEAD(&l_ptr->waiting_ports);
+
+ link_reset_statistics(l_ptr);
+
+ l_ptr->owner = tipc_node_attach_link(l_ptr);
+ if (!l_ptr->owner) {
+ kfree(l_ptr);
+ return NULL;
+ }
+
+ if (LINK_LOG_BUF_SIZE) {
+ char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC);
+
+ if (!pb) {
+ kfree(l_ptr);
+ warn("Memory squeeze; Failed to create link\n");
+ return NULL;
+ }
+ tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE);
+ }
+
+ tipc_k_signal((Handler)tipc_link_start, (unsigned long)l_ptr);
+
+ dbg("tipc_link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n",
+ l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit);
+
+ return l_ptr;
+}
+
+/**
+ * tipc_link_delete - delete a link
+ * @l_ptr: pointer to link
+ *
+ * Note: 'tipc_net_lock' is write_locked, bearer is locked.
+ * This routine must not grab the node lock until after link timer cancellation
+ * to avoid a potential deadlock situation.
+ */
+
+void tipc_link_delete(struct link *l_ptr)
+{
+ if (!l_ptr) {
+ err("Attempt to delete non-existent link\n");
+ return;
+ }
+
+ dbg("tipc_link_delete()\n");
+
+ k_cancel_timer(&l_ptr->timer);
+
+ tipc_node_lock(l_ptr->owner);
+ tipc_link_reset(l_ptr);
+ tipc_node_detach_link(l_ptr->owner, l_ptr);
+ tipc_link_stop(l_ptr);
+ list_del_init(&l_ptr->link_list);
+ if (LINK_LOG_BUF_SIZE)
+ kfree(l_ptr->print_buf.buf);
+ tipc_node_unlock(l_ptr->owner);
+ k_term_timer(&l_ptr->timer);
+ kfree(l_ptr);
+}
+
+void tipc_link_start(struct link *l_ptr)
+{
+ dbg("tipc_link_start %x\n", l_ptr);
+ link_state_event(l_ptr, STARTING_EVT);
+}
+
+/**
+ * link_schedule_port - schedule port for deferred sending
+ * @l_ptr: pointer to link
+ * @origport: reference to sending port
+ * @sz: amount of data to be sent
+ *
+ * Schedules port for renewed sending of messages after link congestion
+ * has abated.
+ */
+
+static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)
+{
+ struct port *p_ptr;
+
+ spin_lock_bh(&tipc_port_list_lock);
+ p_ptr = tipc_port_lock(origport);
+ if (p_ptr) {
+ if (!p_ptr->wakeup)
+ goto exit;
+ if (!list_empty(&p_ptr->wait_list))
+ goto exit;
+ p_ptr->congested_link = l_ptr;
+ p_ptr->publ.congested = 1;
+ p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr));
+ list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
+ l_ptr->stats.link_congs++;
+exit:
+ tipc_port_unlock(p_ptr);
+ }
+ spin_unlock_bh(&tipc_port_list_lock);
+ return -ELINKCONG;
+}
+
+void tipc_link_wakeup_ports(struct link *l_ptr, int all)
+{
+ struct port *p_ptr;
+ struct port *temp_p_ptr;
+ int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;
+
+ if (all)
+ win = 100000;
+ if (win <= 0)
+ return;
+ if (!spin_trylock_bh(&tipc_port_list_lock))
+ return;
+ if (link_congested(l_ptr))
+ goto exit;
+ list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports,
+ wait_list) {
+ if (win <= 0)
+ break;
+ list_del_init(&p_ptr->wait_list);
+ p_ptr->congested_link = 0;
+ assert(p_ptr->wakeup);
+ spin_lock_bh(p_ptr->publ.lock);
+ p_ptr->publ.congested = 0;
+ p_ptr->wakeup(&p_ptr->publ);
+ win -= p_ptr->waiting_pkts;
+ spin_unlock_bh(p_ptr->publ.lock);
+ }
+
+exit:
+ spin_unlock_bh(&tipc_port_list_lock);
+}
+
+/**
+ * link_release_outqueue - purge link's outbound message queue
+ * @l_ptr: pointer to link
+ */
+
+static void link_release_outqueue(struct link *l_ptr)
+{
+ struct sk_buff *buf = l_ptr->first_out;
+ struct sk_buff *next;
+
+ while (buf) {
+ next = buf->next;
+ buf_discard(buf);
+ buf = next;
+ }
+ l_ptr->first_out = NULL;
+ l_ptr->out_queue_size = 0;
+}
+
+/**
+ * tipc_link_reset_fragments - purge link's inbound message fragments queue
+ * @l_ptr: pointer to link
+ */
+
+void tipc_link_reset_fragments(struct link *l_ptr)
+{
+ struct sk_buff *buf = l_ptr->defragm_buf;
+ struct sk_buff *next;
+
+ while (buf) {
+ next = buf->next;
+ buf_discard(buf);
+ buf = next;
+ }
+ l_ptr->defragm_buf = NULL;
+}
+
+/**
+ * tipc_link_stop - purge all inbound and outbound messages associated with link
+ * @l_ptr: pointer to link
+ */
+
+void tipc_link_stop(struct link *l_ptr)
+{
+ struct sk_buff *buf;
+ struct sk_buff *next;
+
+ buf = l_ptr->oldest_deferred_in;
+ while (buf) {
+ next = buf->next;
+ buf_discard(buf);
+ buf = next;
+ }
+
+ buf = l_ptr->first_out;
+ while (buf) {
+ next = buf->next;
+ buf_discard(buf);
+ buf = next;
+ }
+
+ tipc_link_reset_fragments(l_ptr);
+
+ buf_discard(l_ptr->proto_msg_queue);
+ l_ptr->proto_msg_queue = NULL;
+}
+
+#if 0
+
+/* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */
+
+static void link_recv_event(struct link_event *ev)
+{
+ ev->fcn(ev->addr, ev->name, ev->up);
+ kfree(ev);
+}
+
+static void link_send_event(void (*fcn)(u32 a, char *n, int up),
+ struct link *l_ptr, int up)
+{
+ struct link_event *ev;
+
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev) {
+ warn("Link event allocation failure\n");
+ return;
+ }
+ ev->addr = l_ptr->addr;
+ ev->up = up;
+ ev->fcn = fcn;
+ memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME);
+ tipc_k_signal((Handler)link_recv_event, (unsigned long)ev);
+}
+
+#else
+
+#define link_send_event(fcn, l_ptr, up) do { } while (0)
+
+#endif
+
+void tipc_link_reset(struct link *l_ptr)
+{
+ struct sk_buff *buf;
+ u32 prev_state = l_ptr->state;
+ u32 checkpoint = l_ptr->next_in_no;
+
+ msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
+
+ /* Link is down, accept any session: */
+ l_ptr->peer_session = 0;
+
+ /* Prepare for max packet size negotiation */
+ link_init_max_pkt(l_ptr);
+
+ l_ptr->state = RESET_UNKNOWN;
+ dbg_link_state("Resetting Link\n");
+
+ if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET))
+ return;
+
+ tipc_node_link_down(l_ptr->owner, l_ptr);
+ tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
+#if 0
+ tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
+ dbg_link_dump();
+#endif
+ if (tipc_node_has_active_links(l_ptr->owner) &&
+ l_ptr->owner->permit_changeover) {
+ l_ptr->reset_checkpoint = checkpoint;
+ l_ptr->exp_msg_count = START_CHANGEOVER;
+ }
+
+ /* Clean up all queues: */
+
+ link_release_outqueue(l_ptr);
+ buf_discard(l_ptr->proto_msg_queue);
+ l_ptr->proto_msg_queue = NULL;
+ buf = l_ptr->oldest_deferred_in;
+ while (buf) {
+ struct sk_buff *next = buf->next;
+ buf_discard(buf);
+ buf = next;
+ }
+ if (!list_empty(&l_ptr->waiting_ports))
+ tipc_link_wakeup_ports(l_ptr, 1);
+
+ l_ptr->retransm_queue_head = 0;
+ l_ptr->retransm_queue_size = 0;
+ l_ptr->last_out = NULL;
+ l_ptr->first_out = NULL;
+ l_ptr->next_out = NULL;
+ l_ptr->unacked_window = 0;
+ l_ptr->checkpoint = 1;
+ l_ptr->next_out_no = 1;
+ l_ptr->deferred_inqueue_sz = 0;
+ l_ptr->oldest_deferred_in = NULL;
+ l_ptr->newest_deferred_in = NULL;
+ l_ptr->fsm_msg_cnt = 0;
+ l_ptr->stale_count = 0;
+ link_reset_statistics(l_ptr);
+
+ link_send_event(tipc_cfg_link_event, l_ptr, 0);
+ if (!in_own_cluster(l_ptr->addr))
+ link_send_event(tipc_disc_link_event, l_ptr, 0);
+}
+
+
+static void link_activate(struct link *l_ptr)
+{
+ l_ptr->next_in_no = 1;
+ tipc_node_link_up(l_ptr->owner, l_ptr);
+ tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
+ link_send_event(tipc_cfg_link_event, l_ptr, 1);
+ if (!in_own_cluster(l_ptr->addr))
+ link_send_event(tipc_disc_link_event, l_ptr, 1);
+}
+
+/**
+ * link_state_event - link finite state machine
+ * @l_ptr: pointer to link
+ * @event: state machine event to process
+ */
+
+static void link_state_event(struct link *l_ptr, unsigned event)
+{
+ struct link *other;
+ u32 cont_intv = l_ptr->continuity_interval;
+
+ if (!l_ptr->started && (event != STARTING_EVT))
+ return; /* Not yet. */
+
+ if (link_blocked(l_ptr)) {
+ if (event == TIMEOUT_EVT) {
+ link_set_timer(l_ptr, cont_intv);
+ }
+ return; /* Changeover going on */
+ }
+ dbg_link("STATE_EV: <%s> ", l_ptr->name);
+
+ switch (l_ptr->state) {
+ case WORKING_WORKING:
+ dbg_link("WW/");
+ switch (event) {
+ case TRAFFIC_MSG_EVT:
+ dbg_link("TRF-");
+ /* fall through */
+ case ACTIVATE_MSG:
+ dbg_link("ACT\n");
+ break;
+ case TIMEOUT_EVT:
+ dbg_link("TIM ");
+ if (l_ptr->next_in_no != l_ptr->checkpoint) {
+ l_ptr->checkpoint = l_ptr->next_in_no;
+ if (tipc_bclink_acks_missing(l_ptr->owner)) {
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) {
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ }
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ }
+ dbg_link(" -> WU\n");
+ l_ptr->state = WORKING_UNKNOWN;
+ l_ptr->fsm_msg_cnt = 0;
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv / 4);
+ break;
+ case RESET_MSG:
+ dbg_link("RES -> RR\n");
+ tipc_link_reset(l_ptr);
+ l_ptr->state = RESET_RESET;
+ l_ptr->fsm_msg_cnt = 0;
+ tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ default:
+ err("Unknown link event %u in WW state\n", event);
+ }
+ break;
+ case WORKING_UNKNOWN:
+ dbg_link("WU/");
+ switch (event) {
+ case TRAFFIC_MSG_EVT:
+ dbg_link("TRF-");
+ case ACTIVATE_MSG:
+ dbg_link("ACT -> WW\n");
+ l_ptr->state = WORKING_WORKING;
+ l_ptr->fsm_msg_cnt = 0;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ case RESET_MSG:
+ dbg_link("RES -> RR\n");
+ tipc_link_reset(l_ptr);
+ l_ptr->state = RESET_RESET;
+ l_ptr->fsm_msg_cnt = 0;
+ tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ case TIMEOUT_EVT:
+ dbg_link("TIM ");
+ if (l_ptr->next_in_no != l_ptr->checkpoint) {
+ dbg_link("-> WW \n");
+ l_ptr->state = WORKING_WORKING;
+ l_ptr->fsm_msg_cnt = 0;
+ l_ptr->checkpoint = l_ptr->next_in_no;
+ if (tipc_bclink_acks_missing(l_ptr->owner)) {
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ }
+ link_set_timer(l_ptr, cont_intv);
+ } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) {
+ dbg_link("Probing %u/%u,timer = %u ms)\n",
+ l_ptr->fsm_msg_cnt, l_ptr->abort_limit,
+ cont_intv / 4);
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv / 4);
+ } else { /* Link has failed */
+ dbg_link("-> RU (%u probes unanswered)\n",
+ l_ptr->fsm_msg_cnt);
+ tipc_link_reset(l_ptr);
+ l_ptr->state = RESET_UNKNOWN;
+ l_ptr->fsm_msg_cnt = 0;
+ tipc_link_send_proto_msg(l_ptr, RESET_MSG,
+ 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ }
+ break;
+ default:
+ err("Unknown link event %u in WU state\n", event);
+ }
+ break;
+ case RESET_UNKNOWN:
+ dbg_link("RU/");
+ switch (event) {
+ case TRAFFIC_MSG_EVT:
+ dbg_link("TRF-\n");
+ break;
+ case ACTIVATE_MSG:
+ other = l_ptr->owner->active_links[0];
+ if (other && link_working_unknown(other)) {
+ dbg_link("ACT\n");
+ break;
+ }
+ dbg_link("ACT -> WW\n");
+ l_ptr->state = WORKING_WORKING;
+ l_ptr->fsm_msg_cnt = 0;
+ link_activate(l_ptr);
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ case RESET_MSG:
+ dbg_link("RES \n");
+ dbg_link(" -> RR\n");
+ l_ptr->state = RESET_RESET;
+ l_ptr->fsm_msg_cnt = 0;
+ tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ case STARTING_EVT:
+ dbg_link("START-");
+ l_ptr->started = 1;
+ /* fall through */
+ case TIMEOUT_EVT:
+ dbg_link("TIM \n");
+ tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ default:
+ err("Unknown link event %u in RU state\n", event);
+ }
+ break;
+ case RESET_RESET:
+ dbg_link("RR/ ");
+ switch (event) {
+ case TRAFFIC_MSG_EVT:
+ dbg_link("TRF-");
+ /* fall through */
+ case ACTIVATE_MSG:
+ other = l_ptr->owner->active_links[0];
+ if (other && link_working_unknown(other)) {
+ dbg_link("ACT\n");
+ break;
+ }
+ dbg_link("ACT -> WW\n");
+ l_ptr->state = WORKING_WORKING;
+ l_ptr->fsm_msg_cnt = 0;
+ link_activate(l_ptr);
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ break;
+ case RESET_MSG:
+ dbg_link("RES\n");
+ break;
+ case TIMEOUT_EVT:
+ dbg_link("TIM\n");
+ tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0);
+ l_ptr->fsm_msg_cnt++;
+ link_set_timer(l_ptr, cont_intv);
+ dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt);
+ break;
+ default:
+ err("Unknown link event %u in RR state\n", event);
+ }
+ break;
+ default:
+ err("Unknown link state %u/%u\n", l_ptr->state, event);
+ }
+}
+
+/*
+ * link_bundle_buf(): Append contents of a buffer to
+ * the tail of an existing one.
+ */
+
+static int link_bundle_buf(struct link *l_ptr,
+ struct sk_buff *bundler,
+ struct sk_buff *buf)
+{
+ struct tipc_msg *bundler_msg = buf_msg(bundler);
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 size = msg_size(msg);
+ u32 to_pos = align(msg_size(bundler_msg));
+ u32 rest = link_max_pkt(l_ptr) - to_pos;
+
+ if (msg_user(bundler_msg) != MSG_BUNDLER)
+ return 0;
+ if (msg_type(bundler_msg) != OPEN_MSG)
+ return 0;
+ if (rest < align(size))
+ return 0;
+
+ skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size);
+ memcpy(bundler->data + to_pos, buf->data, size);
+ msg_set_size(bundler_msg, to_pos + size);
+ msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1);
+ dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n",
+ msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg));
+ msg_dbg(msg, "PACKD:");
+ buf_discard(buf);
+ l_ptr->stats.sent_bundled++;
+ return 1;
+}
+
+static inline void link_add_to_outqueue(struct link *l_ptr,
+ struct sk_buff *buf,
+ struct tipc_msg *msg)
+{
+ u32 ack = mod(l_ptr->next_in_no - 1);
+ u32 seqno = mod(l_ptr->next_out_no++);
+
+ msg_set_word(msg, 2, ((ack << 16) | seqno));
+ msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
+ buf->next = NULL;
+ if (l_ptr->first_out) {
+ l_ptr->last_out->next = buf;
+ l_ptr->last_out = buf;
+ } else
+ l_ptr->first_out = l_ptr->last_out = buf;
+ l_ptr->out_queue_size++;
+}
+
+/*
+ * tipc_link_send_buf() is the 'full path' for messages, called from
+ * inside TIPC when the 'fast path' in tipc_send_buf
+ * has failed, and from link_send()
+ */
+
+int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 size = msg_size(msg);
+ u32 dsz = msg_data_sz(msg);
+ u32 queue_size = l_ptr->out_queue_size;
+ u32 imp = msg_tot_importance(msg);
+ u32 queue_limit = l_ptr->queue_limit[imp];
+ u32 max_packet = link_max_pkt(l_ptr);
+
+ msg_set_prevnode(msg, tipc_own_addr); /* If routed message */
+
+ /* Match msg importance against queue limits: */
+
+ if (unlikely(queue_size >= queue_limit)) {
+ if (imp <= TIPC_CRITICAL_IMPORTANCE) {
+ return link_schedule_port(l_ptr, msg_origport(msg),
+ size);
+ }
+ msg_dbg(msg, "TIPC: Congestion, throwing away\n");
+ buf_discard(buf);
+ if (imp > CONN_MANAGER) {
+ warn("Resetting <%s>, send queue full", l_ptr->name);
+ tipc_link_reset(l_ptr);
+ }
+ return dsz;
+ }
+
+ /* Fragmentation needed ? */
+
+ if (size > max_packet)
+ return tipc_link_send_long_buf(l_ptr, buf);
+
+ /* Packet can be queued or sent: */
+
+ if (queue_size > l_ptr->stats.max_queue_sz)
+ l_ptr->stats.max_queue_sz = queue_size;
+
+ if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) &&
+ !link_congested(l_ptr))) {
+ link_add_to_outqueue(l_ptr, buf, msg);
+
+ if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
+ l_ptr->unacked_window = 0;
+ } else {
+ tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+ l_ptr->stats.bearer_congs++;
+ l_ptr->next_out = buf;
+ }
+ return dsz;
+ }
+ /* Congestion: can message be bundled ?: */
+
+ if ((msg_user(msg) != CHANGEOVER_PROTOCOL) &&
+ (msg_user(msg) != MSG_FRAGMENTER)) {
+
+ /* Try adding message to an existing bundle */
+
+ if (l_ptr->next_out &&
+ link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
+ tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+ return dsz;
+ }
+
+ /* Try creating a new bundle */
+
+ if (size <= max_packet * 2 / 3) {
+ struct sk_buff *bundler = buf_acquire(max_packet);
+ struct tipc_msg bundler_hdr;
+
+ if (bundler) {
+ msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
+ TIPC_OK, INT_H_SIZE, l_ptr->addr);
+ memcpy(bundler->data, (unchar *)&bundler_hdr,
+ INT_H_SIZE);
+ skb_trim(bundler, INT_H_SIZE);
+ link_bundle_buf(l_ptr, bundler, buf);
+ buf = bundler;
+ msg = buf_msg(buf);
+ l_ptr->stats.sent_bundles++;
+ }
+ }
+ }
+ if (!l_ptr->next_out)
+ l_ptr->next_out = buf;
+ link_add_to_outqueue(l_ptr, buf, msg);
+ tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+ return dsz;
+}
+
+/*
+ * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has
+ * not been selected yet, and the the owner node is not locked
+ * Called by TIPC internal users, e.g. the name distributor
+ */
+
+int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
+{
+ struct link *l_ptr;
+ struct node *n_ptr;
+ int res = -ELINKCONG;
+
+ read_lock_bh(&tipc_net_lock);
+ n_ptr = tipc_node_select(dest, selector);
+ if (n_ptr) {
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->active_links[selector & 1];
+ dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest);
+ if (l_ptr) {
+ res = tipc_link_send_buf(l_ptr, buf);
+ }
+ tipc_node_unlock(n_ptr);
+ } else {
+ dbg("Attempt to send msg to unknown node:\n");
+ msg_dbg(buf_msg(buf),">>>");
+ buf_discard(buf);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+/*
+ * link_send_buf_fast: Entry for data messages where the
+ * destination link is known and the header is complete,
+ * inclusive total message length. Very time critical.
+ * Link is locked. Returns user data length.
+ */
+
+static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
+ u32 *used_max_pkt)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ int res = msg_data_sz(msg);
+
+ if (likely(!link_congested(l_ptr))) {
+ if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) {
+ if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {
+ link_add_to_outqueue(l_ptr, buf, msg);
+ if (likely(tipc_bearer_send(l_ptr->b_ptr, buf,
+ &l_ptr->media_addr))) {
+ l_ptr->unacked_window = 0;
+ msg_dbg(msg,"SENT_FAST:");
+ return res;
+ }
+ dbg("failed sent fast...\n");
+ tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+ l_ptr->stats.bearer_congs++;
+ l_ptr->next_out = buf;
+ return res;
+ }
+ }
+ else
+ *used_max_pkt = link_max_pkt(l_ptr);
+ }
+ return tipc_link_send_buf(l_ptr, buf); /* All other cases */
+}
+
+/*
+ * tipc_send_buf_fast: Entry for data messages where the
+ * destination node is known and the header is complete,
+ * inclusive total message length.
+ * Returns user data length.
+ */
+int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
+{
+ struct link *l_ptr;
+ struct node *n_ptr;
+ int res;
+ u32 selector = msg_origport(buf_msg(buf)) & 1;
+ u32 dummy;
+
+ if (destnode == tipc_own_addr)
+ return tipc_port_recv_msg(buf);
+
+ read_lock_bh(&tipc_net_lock);
+ n_ptr = tipc_node_select(destnode, selector);
+ if (likely(n_ptr)) {
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->active_links[selector];
+ dbg("send_fast: buf %x selected %x, destnode = %x\n",
+ buf, l_ptr, destnode);
+ if (likely(l_ptr)) {
+ res = link_send_buf_fast(l_ptr, buf, &dummy);
+ tipc_node_unlock(n_ptr);
+ read_unlock_bh(&tipc_net_lock);
+ return res;
+ }
+ tipc_node_unlock(n_ptr);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ res = msg_data_sz(buf_msg(buf));
+ tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
+ return res;
+}
+
+
+/*
+ * tipc_link_send_sections_fast: Entry for messages where the
+ * destination processor is known and the header is complete,
+ * except for total message length.
+ * Returns user data length or errno.
+ */
+int tipc_link_send_sections_fast(struct port *sender,
+ struct iovec const *msg_sect,
+ const u32 num_sect,
+ u32 destaddr)
+{
+ struct tipc_msg *hdr = &sender->publ.phdr;
+ struct link *l_ptr;
+ struct sk_buff *buf;
+ struct node *node;
+ int res;
+ u32 selector = msg_origport(hdr) & 1;
+
+ assert(destaddr != tipc_own_addr);
+
+again:
+ /*
+ * Try building message using port's max_pkt hint.
+ * (Must not hold any locks while building message.)
+ */
+
+ res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
+ !sender->user_port, &buf);
+
+ read_lock_bh(&tipc_net_lock);
+ node = tipc_node_select(destaddr, selector);
+ if (likely(node)) {
+ tipc_node_lock(node);
+ l_ptr = node->active_links[selector];
+ if (likely(l_ptr)) {
+ if (likely(buf)) {
+ res = link_send_buf_fast(l_ptr, buf,
+ &sender->max_pkt);
+ if (unlikely(res < 0))
+ buf_discard(buf);
+exit:
+ tipc_node_unlock(node);
+ read_unlock_bh(&tipc_net_lock);
+ return res;
+ }
+
+ /* Exit if build request was invalid */
+
+ if (unlikely(res < 0))
+ goto exit;
+
+ /* Exit if link (or bearer) is congested */
+
+ if (link_congested(l_ptr) ||
+ !list_empty(&l_ptr->b_ptr->cong_links)) {
+ res = link_schedule_port(l_ptr,
+ sender->publ.ref, res);
+ goto exit;
+ }
+
+ /*
+ * Message size exceeds max_pkt hint; update hint,
+ * then re-try fast path or fragment the message
+ */
+
+ sender->max_pkt = link_max_pkt(l_ptr);
+ tipc_node_unlock(node);
+ read_unlock_bh(&tipc_net_lock);
+
+
+ if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
+ goto again;
+
+ return link_send_sections_long(sender, msg_sect,
+ num_sect, destaddr);
+ }
+ tipc_node_unlock(node);
+ }
+ read_unlock_bh(&tipc_net_lock);
+
+ /* Couldn't find a link to the destination node */
+
+ if (buf)
+ return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
+ if (res >= 0)
+ return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
+ TIPC_ERR_NO_NODE);
+ return res;
+}
+
+/*
+ * link_send_sections_long(): Entry for long messages where the
+ * destination node is known and the header is complete,
+ * inclusive total message length.
+ * Link and bearer congestion status have been checked to be ok,
+ * and are ignored if they change.
+ *
+ * Note that fragments do not use the full link MTU so that they won't have
+ * to undergo refragmentation if link changeover causes them to be sent
+ * over another link with an additional tunnel header added as prefix.
+ * (Refragmentation will still occur if the other link has a smaller MTU.)
+ *
+ * Returns user data length or errno.
+ */
+static int link_send_sections_long(struct port *sender,
+ struct iovec const *msg_sect,
+ u32 num_sect,
+ u32 destaddr)
+{
+ struct link *l_ptr;
+ struct node *node;
+ struct tipc_msg *hdr = &sender->publ.phdr;
+ u32 dsz = msg_data_sz(hdr);
+ u32 max_pkt,fragm_sz,rest;
+ struct tipc_msg fragm_hdr;
+ struct sk_buff *buf,*buf_chain,*prev;
+ u32 fragm_crs,fragm_rest,hsz,sect_rest;
+ const unchar *sect_crs;
+ int curr_sect;
+ u32 fragm_no;
+
+again:
+ fragm_no = 1;
+ max_pkt = sender->max_pkt - INT_H_SIZE;
+ /* leave room for tunnel header in case of link changeover */
+ fragm_sz = max_pkt - INT_H_SIZE;
+ /* leave room for fragmentation header in each fragment */
+ rest = dsz;
+ fragm_crs = 0;
+ fragm_rest = 0;
+ sect_rest = 0;
+ sect_crs = 0;
+ curr_sect = -1;
+
+ /* Prepare reusable fragment header: */
+
+ msg_dbg(hdr, ">FRAGMENTING>");
+ msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
+ TIPC_OK, INT_H_SIZE, msg_destnode(hdr));
+ msg_set_link_selector(&fragm_hdr, sender->publ.ref);
+ msg_set_size(&fragm_hdr, max_pkt);
+ msg_set_fragm_no(&fragm_hdr, 1);
+
+ /* Prepare header of first fragment: */
+
+ buf_chain = buf = buf_acquire(max_pkt);
+ if (!buf)
+ return -ENOMEM;
+ buf->next = NULL;
+ memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE);
+ hsz = msg_hdr_sz(hdr);
+ memcpy(buf->data + INT_H_SIZE, (unchar *)hdr, hsz);
+ msg_dbg(buf_msg(buf), ">BUILD>");
+
+ /* Chop up message: */
+
+ fragm_crs = INT_H_SIZE + hsz;
+ fragm_rest = fragm_sz - hsz;
+
+ do { /* For all sections */
+ u32 sz;
+
+ if (!sect_rest) {
+ sect_rest = msg_sect[++curr_sect].iov_len;
+ sect_crs = (const unchar *)msg_sect[curr_sect].iov_base;
+ }
+
+ if (sect_rest < fragm_rest)
+ sz = sect_rest;
+ else
+ sz = fragm_rest;
+
+ if (likely(!sender->user_port)) {
+ if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) {
+error:
+ for (; buf_chain; buf_chain = buf) {
+ buf = buf_chain->next;
+ buf_discard(buf_chain);
+ }
+ return -EFAULT;
+ }
+ } else
+ memcpy(buf->data + fragm_crs, sect_crs, sz);
+
+ sect_crs += sz;
+ sect_rest -= sz;
+ fragm_crs += sz;
+ fragm_rest -= sz;
+ rest -= sz;
+
+ if (!fragm_rest && rest) {
+
+ /* Initiate new fragment: */
+ if (rest <= fragm_sz) {
+ fragm_sz = rest;
+ msg_set_type(&fragm_hdr,LAST_FRAGMENT);
+ } else {
+ msg_set_type(&fragm_hdr, FRAGMENT);
+ }
+ msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
+ msg_set_fragm_no(&fragm_hdr, ++fragm_no);
+ prev = buf;
+ buf = buf_acquire(fragm_sz + INT_H_SIZE);
+ if (!buf)
+ goto error;
+
+ buf->next = NULL;
+ prev->next = buf;
+ memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE);
+ fragm_crs = INT_H_SIZE;
+ fragm_rest = fragm_sz;
+ msg_dbg(buf_msg(buf)," >BUILD>");
+ }
+ }
+ while (rest > 0);
+
+ /*
+ * Now we have a buffer chain. Select a link and check
+ * that packet size is still OK
+ */
+ node = tipc_node_select(destaddr, sender->publ.ref & 1);
+ if (likely(node)) {
+ tipc_node_lock(node);
+ l_ptr = node->active_links[sender->publ.ref & 1];
+ if (!l_ptr) {
+ tipc_node_unlock(node);
+ goto reject;
+ }
+ if (link_max_pkt(l_ptr) < max_pkt) {
+ sender->max_pkt = link_max_pkt(l_ptr);
+ tipc_node_unlock(node);
+ for (; buf_chain; buf_chain = buf) {
+ buf = buf_chain->next;
+ buf_discard(buf_chain);
+ }
+ goto again;
+ }
+ } else {
+reject:
+ for (; buf_chain; buf_chain = buf) {
+ buf = buf_chain->next;
+ buf_discard(buf_chain);
+ }
+ return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
+ TIPC_ERR_NO_NODE);
+ }
+
+ /* Append whole chain to send queue: */
+
+ buf = buf_chain;
+ l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1);
+ if (!l_ptr->next_out)
+ l_ptr->next_out = buf_chain;
+ l_ptr->stats.sent_fragmented++;
+ while (buf) {
+ struct sk_buff *next = buf->next;
+ struct tipc_msg *msg = buf_msg(buf);
+
+ l_ptr->stats.sent_fragments++;
+ msg_set_long_msgno(msg, l_ptr->long_msg_seq_no);
+ link_add_to_outqueue(l_ptr, buf, msg);
+ msg_dbg(msg, ">ADD>");
+ buf = next;
+ }
+
+ /* Send it, if possible: */
+
+ tipc_link_push_queue(l_ptr);
+ tipc_node_unlock(node);
+ return dsz;
+}
+
+/*
+ * tipc_link_push_packet: Push one unsent packet to the media
+ */
+u32 tipc_link_push_packet(struct link *l_ptr)
+{
+ struct sk_buff *buf = l_ptr->first_out;
+ u32 r_q_size = l_ptr->retransm_queue_size;
+ u32 r_q_head = l_ptr->retransm_queue_head;
+
+ /* Step to position where retransmission failed, if any, */
+ /* consider that buffers may have been released in meantime */
+
+ if (r_q_size && buf) {
+ u32 last = lesser(mod(r_q_head + r_q_size),
+ link_last_sent(l_ptr));
+ u32 first = msg_seqno(buf_msg(buf));
+
+ while (buf && less(first, r_q_head)) {
+ first = mod(first + 1);
+ buf = buf->next;
+ }
+ l_ptr->retransm_queue_head = r_q_head = first;
+ l_ptr->retransm_queue_size = r_q_size = mod(last - first);
+ }
+
+ /* Continue retransmission now, if there is anything: */
+
+ if (r_q_size && buf && !skb_cloned(buf)) {
+ msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
+ msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
+ if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+ msg_dbg(buf_msg(buf), ">DEF-RETR>");
+ l_ptr->retransm_queue_head = mod(++r_q_head);
+ l_ptr->retransm_queue_size = --r_q_size;
+ l_ptr->stats.retransmitted++;
+ return TIPC_OK;
+ } else {
+ l_ptr->stats.bearer_congs++;
+ msg_dbg(buf_msg(buf), "|>DEF-RETR>");
+ return PUSH_FAILED;
+ }
+ }
+
+ /* Send deferred protocol message, if any: */
+
+ buf = l_ptr->proto_msg_queue;
+ if (buf) {
+ msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
+ msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in);
+ if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+ msg_dbg(buf_msg(buf), ">DEF-PROT>");
+ l_ptr->unacked_window = 0;
+ buf_discard(buf);
+ l_ptr->proto_msg_queue = 0;
+ return TIPC_OK;
+ } else {
+ msg_dbg(buf_msg(buf), "|>DEF-PROT>");
+ l_ptr->stats.bearer_congs++;
+ return PUSH_FAILED;
+ }
+ }
+
+ /* Send one deferred data message, if send window not full: */
+
+ buf = l_ptr->next_out;
+ if (buf) {
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 next = msg_seqno(msg);
+ u32 first = msg_seqno(buf_msg(l_ptr->first_out));
+
+ if (mod(next - first) < l_ptr->queue_limit[0]) {
+ msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
+ msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
+ if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+ if (msg_user(msg) == MSG_BUNDLER)
+ msg_set_type(msg, CLOSED_MSG);
+ msg_dbg(msg, ">PUSH-DATA>");
+ l_ptr->next_out = buf->next;
+ return TIPC_OK;
+ } else {
+ msg_dbg(msg, "|PUSH-DATA|");
+ l_ptr->stats.bearer_congs++;
+ return PUSH_FAILED;
+ }
+ }
+ }
+ return PUSH_FINISHED;
+}
+
+/*
+ * push_queue(): push out the unsent messages of a link where
+ * congestion has abated. Node is locked
+ */
+void tipc_link_push_queue(struct link *l_ptr)
+{
+ u32 res;
+
+ if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr))
+ return;
+
+ do {
+ res = tipc_link_push_packet(l_ptr);
+ }
+ while (res == TIPC_OK);
+ if (res == PUSH_FAILED)
+ tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+}
+
+void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
+ u32 retransmits)
+{
+ struct tipc_msg *msg;
+
+ dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
+
+ if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) {
+ msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>");
+ dbg_print_link(l_ptr, " ");
+ l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
+ l_ptr->retransm_queue_size = retransmits;
+ return;
+ }
+ while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
+ msg = buf_msg(buf);
+ msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
+ msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
+ if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+ /* Catch if retransmissions fail repeatedly: */
+ if (l_ptr->last_retransmitted == msg_seqno(msg)) {
+ if (++l_ptr->stale_count > 100) {
+ tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>");
+ info("...Retransmitted %u times\n",
+ l_ptr->stale_count);
+ link_print(l_ptr, TIPC_CONS, "Resetting Link\n");;
+ tipc_link_reset(l_ptr);
+ break;
+ }
+ } else {
+ l_ptr->stale_count = 0;
+ }
+ l_ptr->last_retransmitted = msg_seqno(msg);
+
+ msg_dbg(buf_msg(buf), ">RETR>");
+ buf = buf->next;
+ retransmits--;
+ l_ptr->stats.retransmitted++;
+ } else {
+ tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+ l_ptr->stats.bearer_congs++;
+ l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
+ l_ptr->retransm_queue_size = retransmits;
+ return;
+ }
+ }
+ l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
+}
+
+/*
+ * link_recv_non_seq: Receive packets which are outside
+ * the link sequence flow
+ */
+
+static void link_recv_non_seq(struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+
+ if (msg_user(msg) == LINK_CONFIG)
+ tipc_disc_recv_msg(buf);
+ else
+ tipc_bclink_recv_pkt(buf);
+}
+
+/**
+ * link_insert_deferred_queue - insert deferred messages back into receive chain
+ */
+
+static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
+ struct sk_buff *buf)
+{
+ u32 seq_no;
+
+ if (l_ptr->oldest_deferred_in == NULL)
+ return buf;
+
+ seq_no = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
+ if (seq_no == mod(l_ptr->next_in_no)) {
+ l_ptr->newest_deferred_in->next = buf;
+ buf = l_ptr->oldest_deferred_in;
+ l_ptr->oldest_deferred_in = NULL;
+ l_ptr->deferred_inqueue_sz = 0;
+ }
+ return buf;
+}
+
+void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+{
+ read_lock_bh(&tipc_net_lock);
+ while (head) {
+ struct bearer *b_ptr;
+ struct node *n_ptr;
+ struct link *l_ptr;
+ struct sk_buff *crs;
+ struct sk_buff *buf = head;
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 seq_no = msg_seqno(msg);
+ u32 ackd = msg_ack(msg);
+ u32 released = 0;
+ int type;
+
+ b_ptr = (struct bearer *)tb_ptr;
+ TIPC_SKB_CB(buf)->handle = b_ptr;
+
+ head = head->next;
+ if (unlikely(msg_version(msg) != TIPC_VERSION))
+ goto cont;
+#if 0
+ if (msg_user(msg) != LINK_PROTOCOL)
+#endif
+ msg_dbg(msg,"<REC<");
+
+ if (unlikely(msg_non_seq(msg))) {
+ link_recv_non_seq(buf);
+ continue;
+ }
+ n_ptr = tipc_node_find(msg_prevnode(msg));
+ if (unlikely(!n_ptr))
+ goto cont;
+
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->links[b_ptr->identity];
+ if (unlikely(!l_ptr)) {
+ tipc_node_unlock(n_ptr);
+ goto cont;
+ }
+ /*
+ * Release acked messages
+ */
+ if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
+ if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
+ tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
+ }
+
+ crs = l_ptr->first_out;
+ while ((crs != l_ptr->next_out) &&
+ less_eq(msg_seqno(buf_msg(crs)), ackd)) {
+ struct sk_buff *next = crs->next;
+
+ buf_discard(crs);
+ crs = next;
+ released++;
+ }
+ if (released) {
+ l_ptr->first_out = crs;
+ l_ptr->out_queue_size -= released;
+ }
+ if (unlikely(l_ptr->next_out))
+ tipc_link_push_queue(l_ptr);
+ if (unlikely(!list_empty(&l_ptr->waiting_ports)))
+ tipc_link_wakeup_ports(l_ptr, 0);
+ if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) {
+ l_ptr->stats.sent_acks++;
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+ }
+
+protocol_check:
+ if (likely(link_working_working(l_ptr))) {
+ if (likely(seq_no == mod(l_ptr->next_in_no))) {
+ l_ptr->next_in_no++;
+ if (unlikely(l_ptr->oldest_deferred_in))
+ head = link_insert_deferred_queue(l_ptr,
+ head);
+ if (likely(msg_is_dest(msg, tipc_own_addr))) {
+deliver:
+ if (likely(msg_isdata(msg))) {
+ tipc_node_unlock(n_ptr);
+ tipc_port_recv_msg(buf);
+ continue;
+ }
+ switch (msg_user(msg)) {
+ case MSG_BUNDLER:
+ l_ptr->stats.recv_bundles++;
+ l_ptr->stats.recv_bundled +=
+ msg_msgcnt(msg);
+ tipc_node_unlock(n_ptr);
+ tipc_link_recv_bundle(buf);
+ continue;
+ case ROUTE_DISTRIBUTOR:
+ tipc_node_unlock(n_ptr);
+ tipc_cltr_recv_routing_table(buf);
+ continue;
+ case NAME_DISTRIBUTOR:
+ tipc_node_unlock(n_ptr);
+ tipc_named_recv(buf);
+ continue;
+ case CONN_MANAGER:
+ tipc_node_unlock(n_ptr);
+ tipc_port_recv_proto_msg(buf);
+ continue;
+ case MSG_FRAGMENTER:
+ l_ptr->stats.recv_fragments++;
+ if (tipc_link_recv_fragment(&l_ptr->defragm_buf,
+ &buf, &msg)) {
+ l_ptr->stats.recv_fragmented++;
+ goto deliver;
+ }
+ break;
+ case CHANGEOVER_PROTOCOL:
+ type = msg_type(msg);
+ if (link_recv_changeover_msg(&l_ptr, &buf)) {
+ msg = buf_msg(buf);
+ seq_no = msg_seqno(msg);
+ TIPC_SKB_CB(buf)->handle
+ = b_ptr;
+ if (type == ORIGINAL_MSG)
+ goto deliver;
+ goto protocol_check;
+ }
+ break;
+ }
+ }
+ tipc_node_unlock(n_ptr);
+ tipc_net_route_msg(buf);
+ continue;
+ }
+ link_handle_out_of_seq_msg(l_ptr, buf);
+ head = link_insert_deferred_queue(l_ptr, head);
+ tipc_node_unlock(n_ptr);
+ continue;
+ }
+
+ if (msg_user(msg) == LINK_PROTOCOL) {
+ link_recv_proto_msg(l_ptr, buf);
+ head = link_insert_deferred_queue(l_ptr, head);
+ tipc_node_unlock(n_ptr);
+ continue;
+ }
+ msg_dbg(msg,"NSEQ<REC<");
+ link_state_event(l_ptr, TRAFFIC_MSG_EVT);
+
+ if (link_working_working(l_ptr)) {
+ /* Re-insert in front of queue */
+ msg_dbg(msg,"RECV-REINS:");
+ buf->next = head;
+ head = buf;
+ tipc_node_unlock(n_ptr);
+ continue;
+ }
+ tipc_node_unlock(n_ptr);
+cont:
+ buf_discard(buf);
+ }
+ read_unlock_bh(&tipc_net_lock);
+}
+
+/*
+ * link_defer_buf(): Sort a received out-of-sequence packet
+ * into the deferred reception queue.
+ * Returns the increase of the queue length,i.e. 0 or 1
+ */
+
+u32 tipc_link_defer_pkt(struct sk_buff **head,
+ struct sk_buff **tail,
+ struct sk_buff *buf)
+{
+ struct sk_buff *prev = 0;
+ struct sk_buff *crs = *head;
+ u32 seq_no = msg_seqno(buf_msg(buf));
+
+ buf->next = NULL;
+
+ /* Empty queue ? */
+ if (*head == NULL) {
+ *head = *tail = buf;
+ return 1;
+ }
+
+ /* Last ? */
+ if (less(msg_seqno(buf_msg(*tail)), seq_no)) {
+ (*tail)->next = buf;
+ *tail = buf;
+ return 1;
+ }
+
+ /* Scan through queue and sort it in */
+ do {
+ struct tipc_msg *msg = buf_msg(crs);
+
+ if (less(seq_no, msg_seqno(msg))) {
+ buf->next = crs;
+ if (prev)
+ prev->next = buf;
+ else
+ *head = buf;
+ return 1;
+ }
+ if (seq_no == msg_seqno(msg)) {
+ break;
+ }
+ prev = crs;
+ crs = crs->next;
+ }
+ while (crs);
+
+ /* Message is a duplicate of an existing message */
+
+ buf_discard(buf);
+ return 0;
+}
+
+/**
+ * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet
+ */
+
+static void link_handle_out_of_seq_msg(struct link *l_ptr,
+ struct sk_buff *buf)
+{
+ u32 seq_no = msg_seqno(buf_msg(buf));
+
+ if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) {
+ link_recv_proto_msg(l_ptr, buf);
+ return;
+ }
+
+ dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n",
+ seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no);
+
+ /* Record OOS packet arrival (force mismatch on next timeout) */
+
+ l_ptr->checkpoint--;
+
+ /*
+ * Discard packet if a duplicate; otherwise add it to deferred queue
+ * and notify peer of gap as per protocol specification
+ */
+
+ if (less(seq_no, mod(l_ptr->next_in_no))) {
+ l_ptr->stats.duplicates++;
+ buf_discard(buf);
+ return;
+ }
+
+ if (tipc_link_defer_pkt(&l_ptr->oldest_deferred_in,
+ &l_ptr->newest_deferred_in, buf)) {
+ l_ptr->deferred_inqueue_sz++;
+ l_ptr->stats.deferred_recv++;
+ if ((l_ptr->deferred_inqueue_sz % 16) == 1)
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
+ } else
+ l_ptr->stats.duplicates++;
+}
+
+/*
+ * Send protocol message to the other endpoint.
+ */
+void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
+ u32 gap, u32 tolerance, u32 priority, u32 ack_mtu)
+{
+ struct sk_buff *buf = 0;
+ struct tipc_msg *msg = l_ptr->pmsg;
+ u32 msg_size = sizeof(l_ptr->proto_msg);
+
+ if (link_blocked(l_ptr))
+ return;
+ msg_set_type(msg, msg_typ);
+ msg_set_net_plane(msg, l_ptr->b_ptr->net_plane);
+ msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in));
+ msg_set_last_bcast(msg, tipc_bclink_get_last_sent());
+
+ if (msg_typ == STATE_MSG) {
+ u32 next_sent = mod(l_ptr->next_out_no);
+
+ if (!tipc_link_is_up(l_ptr))
+ return;
+ if (l_ptr->next_out)
+ next_sent = msg_seqno(buf_msg(l_ptr->next_out));
+ msg_set_next_sent(msg, next_sent);
+ if (l_ptr->oldest_deferred_in) {
+ u32 rec = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
+ gap = mod(rec - mod(l_ptr->next_in_no));
+ }
+ msg_set_seq_gap(msg, gap);
+ if (gap)
+ l_ptr->stats.sent_nacks++;
+ msg_set_link_tolerance(msg, tolerance);
+ msg_set_linkprio(msg, priority);
+ msg_set_max_pkt(msg, ack_mtu);
+ msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
+ msg_set_probe(msg, probe_msg != 0);
+ if (probe_msg) {
+ u32 mtu = l_ptr->max_pkt;
+
+ if ((mtu < l_ptr->max_pkt_target) &&
+ link_working_working(l_ptr) &&
+ l_ptr->fsm_msg_cnt) {
+ msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
+ if (l_ptr->max_pkt_probes == 10) {
+ l_ptr->max_pkt_target = (msg_size - 4);
+ l_ptr->max_pkt_probes = 0;
+ msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3;
+ }
+ l_ptr->max_pkt_probes++;
+ }
+
+ l_ptr->stats.sent_probes++;
+ }
+ l_ptr->stats.sent_states++;
+ } else { /* RESET_MSG or ACTIVATE_MSG */
+ msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1));
+ msg_set_seq_gap(msg, 0);
+ msg_set_next_sent(msg, 1);
+ msg_set_link_tolerance(msg, l_ptr->tolerance);
+ msg_set_linkprio(msg, l_ptr->priority);
+ msg_set_max_pkt(msg, l_ptr->max_pkt_target);
+ }
+
+ if (tipc_node_has_redundant_links(l_ptr->owner)) {
+ msg_set_redundant_link(msg);
+ } else {
+ msg_clear_redundant_link(msg);
+ }
+ msg_set_linkprio(msg, l_ptr->priority);
+
+ /* Ensure sequence number will not fit : */
+
+ msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2)));
+
+ /* Congestion? */
+
+ if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
+ if (!l_ptr->proto_msg_queue) {
+ l_ptr->proto_msg_queue =
+ buf_acquire(sizeof(l_ptr->proto_msg));
+ }
+ buf = l_ptr->proto_msg_queue;
+ if (!buf)
+ return;
+ memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
+ return;
+ }
+ msg_set_timestamp(msg, jiffies_to_msecs(jiffies));
+
+ /* Message can be sent */
+
+ msg_dbg(msg, ">>");
+
+ buf = buf_acquire(msg_size);
+ if (!buf)
+ return;
+
+ memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg));
+ msg_set_size(buf_msg(buf), msg_size);
+
+ if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
+ l_ptr->unacked_window = 0;
+ buf_discard(buf);
+ return;
+ }
+
+ /* New congestion */
+ tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+ l_ptr->proto_msg_queue = buf;
+ l_ptr->stats.bearer_congs++;
+}
+
+/*
+ * Receive protocol message :
+ * Note that network plane id propagates through the network, and may
+ * change at any time. The node with lowest address rules
+ */
+
+static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
+{
+ u32 rec_gap = 0;
+ u32 max_pkt_info;
+ u32 max_pkt_ack;
+ u32 msg_tol;
+ struct tipc_msg *msg = buf_msg(buf);
+
+ dbg("AT(%u):", jiffies_to_msecs(jiffies));
+ msg_dbg(msg, "<<");
+ if (link_blocked(l_ptr))
+ goto exit;
+
+ /* record unnumbered packet arrival (force mismatch on next timeout) */
+
+ l_ptr->checkpoint--;
+
+ if (l_ptr->b_ptr->net_plane != msg_net_plane(msg))
+ if (tipc_own_addr > msg_prevnode(msg))
+ l_ptr->b_ptr->net_plane = msg_net_plane(msg);
+
+ l_ptr->owner->permit_changeover = msg_redundant_link(msg);
+
+ switch (msg_type(msg)) {
+
+ case RESET_MSG:
+ if (!link_working_unknown(l_ptr) && l_ptr->peer_session) {
+ if (msg_session(msg) == l_ptr->peer_session) {
+ dbg("Duplicate RESET: %u<->%u\n",
+ msg_session(msg), l_ptr->peer_session);
+ break; /* duplicate: ignore */
+ }
+ }
+ /* fall thru' */
+ case ACTIVATE_MSG:
+ /* Update link settings according other endpoint's values */
+
+ strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg));
+
+ if ((msg_tol = msg_link_tolerance(msg)) &&
+ (msg_tol > l_ptr->tolerance))
+ link_set_supervision_props(l_ptr, msg_tol);
+
+ if (msg_linkprio(msg) > l_ptr->priority)
+ l_ptr->priority = msg_linkprio(msg);
+
+ max_pkt_info = msg_max_pkt(msg);
+ if (max_pkt_info) {
+ if (max_pkt_info < l_ptr->max_pkt_target)
+ l_ptr->max_pkt_target = max_pkt_info;
+ if (l_ptr->max_pkt > l_ptr->max_pkt_target)
+ l_ptr->max_pkt = l_ptr->max_pkt_target;
+ } else {
+ l_ptr->max_pkt = l_ptr->max_pkt_target;
+ }
+ l_ptr->owner->bclink.supported = (max_pkt_info != 0);
+
+ link_state_event(l_ptr, msg_type(msg));
+
+ l_ptr->peer_session = msg_session(msg);
+ l_ptr->peer_bearer_id = msg_bearer_id(msg);
+
+ /* Synchronize broadcast sequence numbers */
+ if (!tipc_node_has_redundant_links(l_ptr->owner)) {
+ l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));
+ }
+ break;
+ case STATE_MSG:
+
+ if ((msg_tol = msg_link_tolerance(msg)))
+ link_set_supervision_props(l_ptr, msg_tol);
+
+ if (msg_linkprio(msg) &&
+ (msg_linkprio(msg) != l_ptr->priority)) {
+ warn("Changing prio <%s>: %u->%u\n",
+ l_ptr->name, l_ptr->priority, msg_linkprio(msg));
+ l_ptr->priority = msg_linkprio(msg);
+ tipc_link_reset(l_ptr); /* Enforce change to take effect */
+ break;
+ }
+ link_state_event(l_ptr, TRAFFIC_MSG_EVT);
+ l_ptr->stats.recv_states++;
+ if (link_reset_unknown(l_ptr))
+ break;
+
+ if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) {
+ rec_gap = mod(msg_next_sent(msg) -
+ mod(l_ptr->next_in_no));
+ }
+
+ max_pkt_ack = msg_max_pkt(msg);
+ if (max_pkt_ack > l_ptr->max_pkt) {
+ dbg("Link <%s> updated MTU %u -> %u\n",
+ l_ptr->name, l_ptr->max_pkt, max_pkt_ack);
+ l_ptr->max_pkt = max_pkt_ack;
+ l_ptr->max_pkt_probes = 0;
+ }
+
+ max_pkt_ack = 0;
+ if (msg_probe(msg)) {
+ l_ptr->stats.recv_probes++;
+ if (msg_size(msg) > sizeof(l_ptr->proto_msg)) {
+ max_pkt_ack = msg_size(msg);
+ }
+ }
+
+ /* Protocol message before retransmits, reduce loss risk */
+
+ tipc_bclink_check_gap(l_ptr->owner, msg_last_bcast(msg));
+
+ if (rec_gap || (msg_probe(msg))) {
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 0, rec_gap, 0, 0, max_pkt_ack);
+ }
+ if (msg_seq_gap(msg)) {
+ msg_dbg(msg, "With Gap:");
+ l_ptr->stats.recv_nacks++;
+ tipc_link_retransmit(l_ptr, l_ptr->first_out,
+ msg_seq_gap(msg));
+ }
+ break;
+ default:
+ msg_dbg(buf_msg(buf), "<DISCARDING UNKNOWN<");
+ }
+exit:
+ buf_discard(buf);
+}
+
+
+/*
+ * tipc_link_tunnel(): Send one message via a link belonging to
+ * another bearer. Owner node is locked.
+ */
+void tipc_link_tunnel(struct link *l_ptr,
+ struct tipc_msg *tunnel_hdr,
+ struct tipc_msg *msg,
+ u32 selector)
+{
+ struct link *tunnel;
+ struct sk_buff *buf;
+ u32 length = msg_size(msg);
+
+ tunnel = l_ptr->owner->active_links[selector & 1];
+ if (!tipc_link_is_up(tunnel))
+ return;
+ msg_set_size(tunnel_hdr, length + INT_H_SIZE);
+ buf = buf_acquire(length + INT_H_SIZE);
+ if (!buf)
+ return;
+ memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE);
+ memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length);
+ dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane);
+ msg_dbg(buf_msg(buf), ">SEND>");
+ assert(tunnel);
+ tipc_link_send_buf(tunnel, buf);
+}
+
+
+
+/*
+ * changeover(): Send whole message queue via the remaining link
+ * Owner node is locked.
+ */
+
+void tipc_link_changeover(struct link *l_ptr)
+{
+ u32 msgcount = l_ptr->out_queue_size;
+ struct sk_buff *crs = l_ptr->first_out;
+ struct link *tunnel = l_ptr->owner->active_links[0];
+ int split_bundles = tipc_node_has_redundant_links(l_ptr->owner);
+ struct tipc_msg tunnel_hdr;
+
+ if (!tunnel)
+ return;
+
+ if (!l_ptr->owner->permit_changeover)
+ return;
+
+ msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
+ ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+ msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
+ msg_set_msgcnt(&tunnel_hdr, msgcount);
+ if (!l_ptr->first_out) {
+ struct sk_buff *buf;
+
+ assert(!msgcount);
+ buf = buf_acquire(INT_H_SIZE);
+ if (buf) {
+ memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
+ msg_set_size(&tunnel_hdr, INT_H_SIZE);
+ dbg("%c->%c:", l_ptr->b_ptr->net_plane,
+ tunnel->b_ptr->net_plane);
+ msg_dbg(&tunnel_hdr, "EMPTY>SEND>");
+ tipc_link_send_buf(tunnel, buf);
+ } else {
+ warn("Memory squeeze; link changeover failed\n");
+ }
+ return;
+ }
+ while (crs) {
+ struct tipc_msg *msg = buf_msg(crs);
+
+ if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) {
+ u32 msgcount = msg_msgcnt(msg);
+ struct tipc_msg *m = msg_get_wrapped(msg);
+ unchar* pos = (unchar*)m;
+
+ while (msgcount--) {
+ msg_set_seqno(m,msg_seqno(msg));
+ tipc_link_tunnel(l_ptr, &tunnel_hdr, m,
+ msg_link_selector(m));
+ pos += align(msg_size(m));
+ m = (struct tipc_msg *)pos;
+ }
+ } else {
+ tipc_link_tunnel(l_ptr, &tunnel_hdr, msg,
+ msg_link_selector(msg));
+ }
+ crs = crs->next;
+ }
+}
+
+void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel)
+{
+ struct sk_buff *iter;
+ struct tipc_msg tunnel_hdr;
+
+ msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
+ DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+ msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size);
+ msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
+ iter = l_ptr->first_out;
+ while (iter) {
+ struct sk_buff *outbuf;
+ struct tipc_msg *msg = buf_msg(iter);
+ u32 length = msg_size(msg);
+
+ if (msg_user(msg) == MSG_BUNDLER)
+ msg_set_type(msg, CLOSED_MSG);
+ msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */
+ msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
+ msg_set_size(&tunnel_hdr, length + INT_H_SIZE);
+ outbuf = buf_acquire(length + INT_H_SIZE);
+ if (outbuf == NULL) {
+ warn("Memory squeeze; buffer duplication failed\n");
+ return;
+ }
+ memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
+ memcpy(outbuf->data + INT_H_SIZE, iter->data, length);
+ dbg("%c->%c:", l_ptr->b_ptr->net_plane,
+ tunnel->b_ptr->net_plane);
+ msg_dbg(buf_msg(outbuf), ">SEND>");
+ tipc_link_send_buf(tunnel, outbuf);
+ if (!tipc_link_is_up(l_ptr))
+ return;
+ iter = iter->next;
+ }
+}
+
+
+
+/**
+ * buf_extract - extracts embedded TIPC message from another message
+ * @skb: encapsulating message buffer
+ * @from_pos: offset to extract from
+ *
+ * Returns a new message buffer containing an embedded message. The
+ * encapsulating message itself is left unchanged.
+ */
+
+static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
+{
+ struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos);
+ u32 size = msg_size(msg);
+ struct sk_buff *eb;
+
+ eb = buf_acquire(size);
+ if (eb)
+ memcpy(eb->data, (unchar *)msg, size);
+ return eb;
+}
+
+/*
+ * link_recv_changeover_msg(): Receive tunneled packet sent
+ * via other link. Node is locked. Return extracted buffer.
+ */
+
+static int link_recv_changeover_msg(struct link **l_ptr,
+ struct sk_buff **buf)
+{
+ struct sk_buff *tunnel_buf = *buf;
+ struct link *dest_link;
+ struct tipc_msg *msg;
+ struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf);
+ u32 msg_typ = msg_type(tunnel_msg);
+ u32 msg_count = msg_msgcnt(tunnel_msg);
+
+ dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)];
+ assert(dest_link != *l_ptr);
+ if (!dest_link) {
+ msg_dbg(tunnel_msg, "NOLINK/<REC<");
+ goto exit;
+ }
+ dbg("%c<-%c:", dest_link->b_ptr->net_plane,
+ (*l_ptr)->b_ptr->net_plane);
+ *l_ptr = dest_link;
+ msg = msg_get_wrapped(tunnel_msg);
+
+ if (msg_typ == DUPLICATE_MSG) {
+ if (less(msg_seqno(msg), mod(dest_link->next_in_no))) {
+ msg_dbg(tunnel_msg, "DROP/<REC<");
+ goto exit;
+ }
+ *buf = buf_extract(tunnel_buf,INT_H_SIZE);
+ if (*buf == NULL) {
+ warn("Memory squeeze; failed to extract msg\n");
+ goto exit;
+ }
+ msg_dbg(tunnel_msg, "TNL<REC<");
+ buf_discard(tunnel_buf);
+ return 1;
+ }
+
+ /* First original message ?: */
+
+ if (tipc_link_is_up(dest_link)) {
+ msg_dbg(tunnel_msg, "UP/FIRST/<REC<");
+ tipc_link_reset(dest_link);
+ dest_link->exp_msg_count = msg_count;
+ if (!msg_count)
+ goto exit;
+ } else if (dest_link->exp_msg_count == START_CHANGEOVER) {
+ msg_dbg(tunnel_msg, "BLK/FIRST/<REC<");
+ dest_link->exp_msg_count = msg_count;
+ if (!msg_count)
+ goto exit;
+ }
+
+ /* Receive original message */
+
+ if (dest_link->exp_msg_count == 0) {
+ msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<");
+ dbg_print_link(dest_link, "LINK:");
+ goto exit;
+ }
+ dest_link->exp_msg_count--;
+ if (less(msg_seqno(msg), dest_link->reset_checkpoint)) {
+ msg_dbg(tunnel_msg, "DROP/DUPL/<REC<");
+ goto exit;
+ } else {
+ *buf = buf_extract(tunnel_buf, INT_H_SIZE);
+ if (*buf != NULL) {
+ msg_dbg(tunnel_msg, "TNL<REC<");
+ buf_discard(tunnel_buf);
+ return 1;
+ } else {
+ warn("Memory squeeze; dropped incoming msg\n");
+ }
+ }
+exit:
+ *buf = 0;
+ buf_discard(tunnel_buf);
+ return 0;
+}
+
+/*
+ * Bundler functionality:
+ */
+void tipc_link_recv_bundle(struct sk_buff *buf)
+{
+ u32 msgcount = msg_msgcnt(buf_msg(buf));
+ u32 pos = INT_H_SIZE;
+ struct sk_buff *obuf;
+
+ msg_dbg(buf_msg(buf), "<BNDL<: ");
+ while (msgcount--) {
+ obuf = buf_extract(buf, pos);
+ if (obuf == NULL) {
+ char addr_string[16];
+
+ warn("Buffer allocation failure;\n");
+ warn(" incoming message(s) from %s lost\n",
+ addr_string_fill(addr_string,
+ msg_orignode(buf_msg(buf))));
+ return;
+ };
+ pos += align(msg_size(buf_msg(obuf)));
+ msg_dbg(buf_msg(obuf), " /");
+ tipc_net_route_msg(obuf);
+ }
+ buf_discard(buf);
+}
+
+/*
+ * Fragmentation/defragmentation:
+ */
+
+
+/*
+ * tipc_link_send_long_buf: Entry for buffers needing fragmentation.
+ * The buffer is complete, inclusive total message length.
+ * Returns user data length.
+ */
+int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
+{
+ struct tipc_msg *inmsg = buf_msg(buf);
+ struct tipc_msg fragm_hdr;
+ u32 insize = msg_size(inmsg);
+ u32 dsz = msg_data_sz(inmsg);
+ unchar *crs = buf->data;
+ u32 rest = insize;
+ u32 pack_sz = link_max_pkt(l_ptr);
+ u32 fragm_sz = pack_sz - INT_H_SIZE;
+ u32 fragm_no = 1;
+ u32 destaddr = msg_destnode(inmsg);
+
+ if (msg_short(inmsg))
+ destaddr = l_ptr->addr;
+
+ if (msg_routed(inmsg))
+ msg_set_prevnode(inmsg, tipc_own_addr);
+
+ /* Prepare reusable fragment header: */
+
+ msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
+ TIPC_OK, INT_H_SIZE, destaddr);
+ msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg));
+ msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++));
+ msg_set_fragm_no(&fragm_hdr, fragm_no);
+ l_ptr->stats.sent_fragmented++;
+
+ /* Chop up message: */
+
+ while (rest > 0) {
+ struct sk_buff *fragm;
+
+ if (rest <= fragm_sz) {
+ fragm_sz = rest;
+ msg_set_type(&fragm_hdr, LAST_FRAGMENT);
+ }
+ fragm = buf_acquire(fragm_sz + INT_H_SIZE);
+ if (fragm == NULL) {
+ warn("Memory squeeze; failed to fragment msg\n");
+ dsz = -ENOMEM;
+ goto exit;
+ }
+ msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
+ memcpy(fragm->data, (unchar *)&fragm_hdr, INT_H_SIZE);
+ memcpy(fragm->data + INT_H_SIZE, crs, fragm_sz);
+
+ /* Send queued messages first, if any: */
+
+ l_ptr->stats.sent_fragments++;
+ tipc_link_send_buf(l_ptr, fragm);
+ if (!tipc_link_is_up(l_ptr))
+ return dsz;
+ msg_set_fragm_no(&fragm_hdr, ++fragm_no);
+ rest -= fragm_sz;
+ crs += fragm_sz;
+ msg_set_type(&fragm_hdr, FRAGMENT);
+ }
+exit:
+ buf_discard(buf);
+ return dsz;
+}
+
+/*
+ * A pending message being re-assembled must store certain values
+ * to handle subsequent fragments correctly. The following functions
+ * help storing these values in unused, available fields in the
+ * pending message. This makes dynamic memory allocation unecessary.
+ */
+
+static inline u32 get_long_msg_seqno(struct sk_buff *buf)
+{
+ return msg_seqno(buf_msg(buf));
+}
+
+static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
+{
+ msg_set_seqno(buf_msg(buf), seqno);
+}
+
+static inline u32 get_fragm_size(struct sk_buff *buf)
+{
+ return msg_ack(buf_msg(buf));
+}
+
+static inline void set_fragm_size(struct sk_buff *buf, u32 sz)
+{
+ msg_set_ack(buf_msg(buf), sz);
+}
+
+static inline u32 get_expected_frags(struct sk_buff *buf)
+{
+ return msg_bcast_ack(buf_msg(buf));
+}
+
+static inline void set_expected_frags(struct sk_buff *buf, u32 exp)
+{
+ msg_set_bcast_ack(buf_msg(buf), exp);
+}
+
+static inline u32 get_timer_cnt(struct sk_buff *buf)
+{
+ return msg_reroute_cnt(buf_msg(buf));
+}
+
+static inline void incr_timer_cnt(struct sk_buff *buf)
+{
+ msg_incr_reroute_cnt(buf_msg(buf));
+}
+
+/*
+ * tipc_link_recv_fragment(): Called with node lock on. Returns
+ * the reassembled buffer if message is complete.
+ */
+int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
+ struct tipc_msg **m)
+{
+ struct sk_buff *prev = 0;
+ struct sk_buff *fbuf = *fb;
+ struct tipc_msg *fragm = buf_msg(fbuf);
+ struct sk_buff *pbuf = *pending;
+ u32 long_msg_seq_no = msg_long_msgno(fragm);
+
+ *fb = 0;
+ msg_dbg(fragm,"FRG<REC<");
+
+ /* Is there an incomplete message waiting for this fragment? */
+
+ while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no)
+ || (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) {
+ prev = pbuf;
+ pbuf = pbuf->next;
+ }
+
+ if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) {
+ struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm);
+ u32 msg_sz = msg_size(imsg);
+ u32 fragm_sz = msg_data_sz(fragm);
+ u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz);
+ u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE;
+ if (msg_type(imsg) == TIPC_MCAST_MSG)
+ max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
+ if (msg_size(imsg) > max) {
+ msg_dbg(fragm,"<REC<Oversized: ");
+ buf_discard(fbuf);
+ return 0;
+ }
+ pbuf = buf_acquire(msg_size(imsg));
+ if (pbuf != NULL) {
+ pbuf->next = *pending;
+ *pending = pbuf;
+ memcpy(pbuf->data, (unchar *)imsg, msg_data_sz(fragm));
+
+ /* Prepare buffer for subsequent fragments. */
+
+ set_long_msg_seqno(pbuf, long_msg_seq_no);
+ set_fragm_size(pbuf,fragm_sz);
+ set_expected_frags(pbuf,exp_fragm_cnt - 1);
+ } else {
+ warn("Memory squeeze; got no defragmenting buffer\n");
+ }
+ buf_discard(fbuf);
+ return 0;
+ } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) {
+ u32 dsz = msg_data_sz(fragm);
+ u32 fsz = get_fragm_size(pbuf);
+ u32 crs = ((msg_fragm_no(fragm) - 1) * fsz);
+ u32 exp_frags = get_expected_frags(pbuf) - 1;
+ memcpy(pbuf->data + crs, msg_data(fragm), dsz);
+ buf_discard(fbuf);
+
+ /* Is message complete? */
+
+ if (exp_frags == 0) {
+ if (prev)
+ prev->next = pbuf->next;
+ else
+ *pending = pbuf->next;
+ msg_reset_reroute_cnt(buf_msg(pbuf));
+ *fb = pbuf;
+ *m = buf_msg(pbuf);
+ return 1;
+ }
+ set_expected_frags(pbuf,exp_frags);
+ return 0;
+ }
+ dbg(" Discarding orphan fragment %x\n",fbuf);
+ msg_dbg(fragm,"ORPHAN:");
+ dbg("Pending long buffers:\n");
+ dbg_print_buf_chain(*pending);
+ buf_discard(fbuf);
+ return 0;
+}
+
+/**
+ * link_check_defragm_bufs - flush stale incoming message fragments
+ * @l_ptr: pointer to link
+ */
+
+static void link_check_defragm_bufs(struct link *l_ptr)
+{
+ struct sk_buff *prev = 0;
+ struct sk_buff *next = 0;
+ struct sk_buff *buf = l_ptr->defragm_buf;
+
+ if (!buf)
+ return;
+ if (!link_working_working(l_ptr))
+ return;
+ while (buf) {
+ u32 cnt = get_timer_cnt(buf);
+
+ next = buf->next;
+ if (cnt < 4) {
+ incr_timer_cnt(buf);
+ prev = buf;
+ } else {
+ dbg(" Discarding incomplete long buffer\n");
+ msg_dbg(buf_msg(buf), "LONG:");
+ dbg_print_link(l_ptr, "curr:");
+ dbg("Pending long buffers:\n");
+ dbg_print_buf_chain(l_ptr->defragm_buf);
+ if (prev)
+ prev->next = buf->next;
+ else
+ l_ptr->defragm_buf = buf->next;
+ buf_discard(buf);
+ }
+ buf = next;
+ }
+}
+
+
+
+static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
+{
+ l_ptr->tolerance = tolerance;
+ l_ptr->continuity_interval =
+ ((tolerance / 4) > 500) ? 500 : tolerance / 4;
+ l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4);
+}
+
+
+void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
+{
+ /* Data messages from this node, inclusive FIRST_FRAGM */
+ l_ptr->queue_limit[DATA_LOW] = window;
+ l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4;
+ l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5;
+ l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6;
+ /* Transiting data messages,inclusive FIRST_FRAGM */
+ l_ptr->queue_limit[DATA_LOW + 4] = 300;
+ l_ptr->queue_limit[DATA_MEDIUM + 4] = 600;
+ l_ptr->queue_limit[DATA_HIGH + 4] = 900;
+ l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200;
+ l_ptr->queue_limit[CONN_MANAGER] = 1200;
+ l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200;
+ l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500;
+ l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000;
+ /* FRAGMENT and LAST_FRAGMENT packets */
+ l_ptr->queue_limit[MSG_FRAGMENTER] = 4000;
+}
+
+/**
+ * link_find_link - locate link by name
+ * @name - ptr to link name string
+ * @node - ptr to area to be filled with ptr to associated node
+ *
+ * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted;
+ * this also prevents link deletion.
+ *
+ * Returns pointer to link (or 0 if invalid link name).
+ */
+
+static struct link *link_find_link(const char *name, struct node **node)
+{
+ struct link_name link_name_parts;
+ struct bearer *b_ptr;
+ struct link *l_ptr;
+
+ if (!link_name_validate(name, &link_name_parts))
+ return 0;
+
+ b_ptr = tipc_bearer_find_interface(link_name_parts.if_local);
+ if (!b_ptr)
+ return 0;
+
+ *node = tipc_node_find(link_name_parts.addr_peer);
+ if (!*node)
+ return 0;
+
+ l_ptr = (*node)->links[b_ptr->identity];
+ if (!l_ptr || strcmp(l_ptr->name, name))
+ return 0;
+
+ return l_ptr;
+}
+
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space,
+ u16 cmd)
+{
+ struct tipc_link_config *args;
+ u32 new_value;
+ struct link *l_ptr;
+ struct node *node;
+ int res;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ args = (struct tipc_link_config *)TLV_DATA(req_tlv_area);
+ new_value = ntohl(args->value);
+
+ if (!strcmp(args->name, tipc_bclink_name)) {
+ if ((cmd == TIPC_CMD_SET_LINK_WINDOW) &&
+ (tipc_bclink_set_queue_limits(new_value) == 0))
+ return tipc_cfg_reply_none();
+ return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+ " (cannot change setting on broadcast link)");
+ }
+
+ read_lock_bh(&tipc_net_lock);
+ l_ptr = link_find_link(args->name, &node);
+ if (!l_ptr) {
+ read_unlock_bh(&tipc_net_lock);
+ return tipc_cfg_reply_error_string("link not found");
+ }
+
+ tipc_node_lock(node);
+ res = -EINVAL;
+ switch (cmd) {
+ case TIPC_CMD_SET_LINK_TOL:
+ if ((new_value >= TIPC_MIN_LINK_TOL) &&
+ (new_value <= TIPC_MAX_LINK_TOL)) {
+ link_set_supervision_props(l_ptr, new_value);
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 0, 0, new_value, 0, 0);
+ res = TIPC_OK;
+ }
+ break;
+ case TIPC_CMD_SET_LINK_PRI:
+ if ((new_value >= TIPC_MIN_LINK_PRI) &&
+ (new_value <= TIPC_MAX_LINK_PRI)) {
+ l_ptr->priority = new_value;
+ tipc_link_send_proto_msg(l_ptr, STATE_MSG,
+ 0, 0, 0, new_value, 0);
+ res = TIPC_OK;
+ }
+ break;
+ case TIPC_CMD_SET_LINK_WINDOW:
+ if ((new_value >= TIPC_MIN_LINK_WIN) &&
+ (new_value <= TIPC_MAX_LINK_WIN)) {
+ tipc_link_set_queue_limits(l_ptr, new_value);
+ res = TIPC_OK;
+ }
+ break;
+ }
+ tipc_node_unlock(node);
+
+ read_unlock_bh(&tipc_net_lock);
+ if (res)
+ return tipc_cfg_reply_error_string("cannot change link setting");
+
+ return tipc_cfg_reply_none();
+}
+
+/**
+ * link_reset_statistics - reset link statistics
+ * @l_ptr: pointer to link
+ */
+
+static void link_reset_statistics(struct link *l_ptr)
+{
+ memset(&l_ptr->stats, 0, sizeof(l_ptr->stats));
+ l_ptr->stats.sent_info = l_ptr->next_out_no;
+ l_ptr->stats.recv_info = l_ptr->next_in_no;
+}
+
+struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space)
+{
+ char *link_name;
+ struct link *l_ptr;
+ struct node *node;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ link_name = (char *)TLV_DATA(req_tlv_area);
+ if (!strcmp(link_name, tipc_bclink_name)) {
+ if (tipc_bclink_reset_stats())
+ return tipc_cfg_reply_error_string("link not found");
+ return tipc_cfg_reply_none();
+ }
+
+ read_lock_bh(&tipc_net_lock);
+ l_ptr = link_find_link(link_name, &node);
+ if (!l_ptr) {
+ read_unlock_bh(&tipc_net_lock);
+ return tipc_cfg_reply_error_string("link not found");
+ }
+
+ tipc_node_lock(node);
+ link_reset_statistics(l_ptr);
+ tipc_node_unlock(node);
+ read_unlock_bh(&tipc_net_lock);
+ return tipc_cfg_reply_none();
+}
+
+/**
+ * percent - convert count to a percentage of total (rounding up or down)
+ */
+
+static u32 percent(u32 count, u32 total)
+{
+ return (count * 100 + (total / 2)) / total;
+}
+
+/**
+ * tipc_link_stats - print link statistics
+ * @name: link name
+ * @buf: print buffer area
+ * @buf_size: size of print buffer area
+ *
+ * Returns length of print buffer data string (or 0 if error)
+ */
+
+static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
+{
+ struct print_buf pb;
+ struct link *l_ptr;
+ struct node *node;
+ char *status;
+ u32 profile_total = 0;
+
+ if (!strcmp(name, tipc_bclink_name))
+ return tipc_bclink_stats(buf, buf_size);
+
+ tipc_printbuf_init(&pb, buf, buf_size);
+
+ read_lock_bh(&tipc_net_lock);
+ l_ptr = link_find_link(name, &node);
+ if (!l_ptr) {
+ read_unlock_bh(&tipc_net_lock);
+ return 0;
+ }
+ tipc_node_lock(node);
+
+ if (tipc_link_is_active(l_ptr))
+ status = "ACTIVE";
+ else if (tipc_link_is_up(l_ptr))
+ status = "STANDBY";
+ else
+ status = "DEFUNCT";
+ tipc_printf(&pb, "Link <%s>\n"
+ " %s MTU:%u Priority:%u Tolerance:%u ms"
+ " Window:%u packets\n",
+ l_ptr->name, status, link_max_pkt(l_ptr),
+ l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]);
+ tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n",
+ l_ptr->next_in_no - l_ptr->stats.recv_info,
+ l_ptr->stats.recv_fragments,
+ l_ptr->stats.recv_fragmented,
+ l_ptr->stats.recv_bundles,
+ l_ptr->stats.recv_bundled);
+ tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n",
+ l_ptr->next_out_no - l_ptr->stats.sent_info,
+ l_ptr->stats.sent_fragments,
+ l_ptr->stats.sent_fragmented,
+ l_ptr->stats.sent_bundles,
+ l_ptr->stats.sent_bundled);
+ profile_total = l_ptr->stats.msg_length_counts;
+ if (!profile_total)
+ profile_total = 1;
+ tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n"
+ " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% "
+ "-16354:%u%% -32768:%u%% -66000:%u%%\n",
+ l_ptr->stats.msg_length_counts,
+ l_ptr->stats.msg_lengths_total / profile_total,
+ percent(l_ptr->stats.msg_length_profile[0], profile_total),
+ percent(l_ptr->stats.msg_length_profile[1], profile_total),
+ percent(l_ptr->stats.msg_length_profile[2], profile_total),
+ percent(l_ptr->stats.msg_length_profile[3], profile_total),
+ percent(l_ptr->stats.msg_length_profile[4], profile_total),
+ percent(l_ptr->stats.msg_length_profile[5], profile_total),
+ percent(l_ptr->stats.msg_length_profile[6], profile_total));
+ tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n",
+ l_ptr->stats.recv_states,
+ l_ptr->stats.recv_probes,
+ l_ptr->stats.recv_nacks,
+ l_ptr->stats.deferred_recv,
+ l_ptr->stats.duplicates);
+ tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n",
+ l_ptr->stats.sent_states,
+ l_ptr->stats.sent_probes,
+ l_ptr->stats.sent_nacks,
+ l_ptr->stats.sent_acks,
+ l_ptr->stats.retransmitted);
+ tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n",
+ l_ptr->stats.bearer_congs,
+ l_ptr->stats.link_congs,
+ l_ptr->stats.max_queue_sz,
+ l_ptr->stats.queue_sz_counts
+ ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts)
+ : 0);
+
+ tipc_node_unlock(node);
+ read_unlock_bh(&tipc_net_lock);
+ return tipc_printbuf_validate(&pb);
+}
+
+#define MAX_LINK_STATS_INFO 2000
+
+struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space)
+{
+ struct sk_buff *buf;
+ struct tlv_desc *rep_tlv;
+ int str_len;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO));
+ if (!buf)
+ return NULL;
+
+ rep_tlv = (struct tlv_desc *)buf->data;
+
+ str_len = tipc_link_stats((char *)TLV_DATA(req_tlv_area),
+ (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO);
+ if (!str_len) {
+ buf_discard(buf);
+ return tipc_cfg_reply_error_string("link not found");
+ }
+
+ skb_put(buf, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+
+ return buf;
+}
+
+#if 0
+int link_control(const char *name, u32 op, u32 val)
+{
+ int res = -EINVAL;
+ struct link *l_ptr;
+ u32 bearer_id;
+ struct node * node;
+ u32 a;
+
+ a = link_name2addr(name, &bearer_id);
+ read_lock_bh(&tipc_net_lock);
+ node = tipc_node_find(a);
+ if (node) {
+ tipc_node_lock(node);
+ l_ptr = node->links[bearer_id];
+ if (l_ptr) {
+ if (op == TIPC_REMOVE_LINK) {
+ struct bearer *b_ptr = l_ptr->b_ptr;
+ spin_lock_bh(&b_ptr->publ.lock);
+ tipc_link_delete(l_ptr);
+ spin_unlock_bh(&b_ptr->publ.lock);
+ }
+ if (op == TIPC_CMD_BLOCK_LINK) {
+ tipc_link_reset(l_ptr);
+ l_ptr->blocked = 1;
+ }
+ if (op == TIPC_CMD_UNBLOCK_LINK) {
+ l_ptr->blocked = 0;
+ }
+ res = TIPC_OK;
+ }
+ tipc_node_unlock(node);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ return res;
+}
+#endif
+
+/**
+ * tipc_link_get_max_pkt - get maximum packet size to use when sending to destination
+ * @dest: network address of destination node
+ * @selector: used to select from set of active links
+ *
+ * If no active link can be found, uses default maximum packet size.
+ */
+
+u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
+{
+ struct node *n_ptr;
+ struct link *l_ptr;
+ u32 res = MAX_PKT_DEFAULT;
+
+ if (dest == tipc_own_addr)
+ return MAX_MSG_SIZE;
+
+ read_lock_bh(&tipc_net_lock);
+ n_ptr = tipc_node_select(dest, selector);
+ if (n_ptr) {
+ tipc_node_lock(n_ptr);
+ l_ptr = n_ptr->active_links[selector & 1];
+ if (l_ptr)
+ res = link_max_pkt(l_ptr);
+ tipc_node_unlock(n_ptr);
+ }
+ read_unlock_bh(&tipc_net_lock);
+ return res;
+}
+
+#if 0
+static void link_dump_rec_queue(struct link *l_ptr)
+{
+ struct sk_buff *crs;
+
+ if (!l_ptr->oldest_deferred_in) {
+ info("Reception queue empty\n");
+ return;
+ }
+ info("Contents of Reception queue:\n");
+ crs = l_ptr->oldest_deferred_in;
+ while (crs) {
+ if (crs->data == (void *)0x0000a3a3) {
+ info("buffer %x invalid\n", crs);
+ return;
+ }
+ msg_dbg(buf_msg(crs), "In rec queue: \n");
+ crs = crs->next;
+ }
+}
+#endif
+
+static void link_dump_send_queue(struct link *l_ptr)
+{
+ if (l_ptr->next_out) {
+ info("\nContents of unsent queue:\n");
+ dbg_print_buf_chain(l_ptr->next_out);
+ }
+ info("\nContents of send queue:\n");
+ if (l_ptr->first_out) {
+ dbg_print_buf_chain(l_ptr->first_out);
+ }
+ info("Empty send queue\n");
+}
+
+static void link_print(struct link *l_ptr, struct print_buf *buf,
+ const char *str)
+{
+ tipc_printf(buf, str);
+ if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr))
+ return;
+ tipc_printf(buf, "Link %x<%s>:",
+ l_ptr->addr, l_ptr->b_ptr->publ.name);
+ tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no));
+ tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no));
+ tipc_printf(buf, "SQUE");
+ if (l_ptr->first_out) {
+ tipc_printf(buf, "[%u..", msg_seqno(buf_msg(l_ptr->first_out)));
+ if (l_ptr->next_out)
+ tipc_printf(buf, "%u..",
+ msg_seqno(buf_msg(l_ptr->next_out)));
+ tipc_printf(buf, "%u]",
+ msg_seqno(buf_msg
+ (l_ptr->last_out)), l_ptr->out_queue_size);
+ if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) -
+ msg_seqno(buf_msg(l_ptr->first_out)))
+ != (l_ptr->out_queue_size - 1))
+ || (l_ptr->last_out->next != 0)) {
+ tipc_printf(buf, "\nSend queue inconsistency\n");
+ tipc_printf(buf, "first_out= %x ", l_ptr->first_out);
+ tipc_printf(buf, "next_out= %x ", l_ptr->next_out);
+ tipc_printf(buf, "last_out= %x ", l_ptr->last_out);
+ link_dump_send_queue(l_ptr);
+ }
+ } else
+ tipc_printf(buf, "[]");
+ tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size);
+ if (l_ptr->oldest_deferred_in) {
+ u32 o = msg_seqno(buf_msg(l_ptr->oldest_deferred_in));
+ u32 n = msg_seqno(buf_msg(l_ptr->newest_deferred_in));
+ tipc_printf(buf, ":RQUE[%u..%u]", o, n);
+ if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) {
+ tipc_printf(buf, ":RQSIZ(%u)",
+ l_ptr->deferred_inqueue_sz);
+ }
+ }
+ if (link_working_unknown(l_ptr))
+ tipc_printf(buf, ":WU");
+ if (link_reset_reset(l_ptr))
+ tipc_printf(buf, ":RR");
+ if (link_reset_unknown(l_ptr))
+ tipc_printf(buf, ":RU");
+ if (link_working_working(l_ptr))
+ tipc_printf(buf, ":WW");
+ tipc_printf(buf, "\n");
+}
+
diff --git a/net/tipc/link.h b/net/tipc/link.h
new file mode 100644
index 000000000000..2d3c157f707d
--- /dev/null
+++ b/net/tipc/link.h
@@ -0,0 +1,295 @@
+/*
+ * net/tipc/link.h: Include file for TIPC link code
+ *
+ * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_LINK_H
+#define _TIPC_LINK_H
+
+#include "dbg.h"
+#include "msg.h"
+#include "bearer.h"
+#include "node.h"
+
+#define PUSH_FAILED 1
+#define PUSH_FINISHED 2
+
+/*
+ * Link states
+ */
+
+#define WORKING_WORKING 560810u
+#define WORKING_UNKNOWN 560811u
+#define RESET_UNKNOWN 560812u
+#define RESET_RESET 560813u
+
+/*
+ * Starting value for maximum packet size negotiation on unicast links
+ * (unless bearer MTU is less)
+ */
+
+#define MAX_PKT_DEFAULT 1500
+
+/**
+ * struct link - TIPC link data structure
+ * @addr: network address of link's peer node
+ * @name: link name character string
+ * @media_addr: media address to use when sending messages over link
+ * @timer: link timer
+ * @owner: pointer to peer node
+ * @link_list: adjacent links in bearer's list of links
+ * @started: indicates if link has been started
+ * @checkpoint: reference point for triggering link continuity checking
+ * @peer_session: link session # being used by peer end of link
+ * @peer_bearer_id: bearer id used by link's peer endpoint
+ * @b_ptr: pointer to bearer used by link
+ * @tolerance: minimum link continuity loss needed to reset link [in ms]
+ * @continuity_interval: link continuity testing interval [in ms]
+ * @abort_limit: # of unacknowledged continuity probes needed to reset link
+ * @state: current state of link FSM
+ * @blocked: indicates if link has been administratively blocked
+ * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state
+ * @proto_msg: template for control messages generated by link
+ * @pmsg: convenience pointer to "proto_msg" field
+ * @priority: current link priority
+ * @queue_limit: outbound message queue congestion thresholds (indexed by user)
+ * @exp_msg_count: # of tunnelled messages expected during link changeover
+ * @reset_checkpoint: seq # of last acknowledged message at time of link reset
+ * @max_pkt: current maximum packet size for this link
+ * @max_pkt_target: desired maximum packet size for this link
+ * @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target)
+ * @out_queue_size: # of messages in outbound message queue
+ * @first_out: ptr to first outbound message in queue
+ * @last_out: ptr to last outbound message in queue
+ * @next_out_no: next sequence number to use for outbound messages
+ * @last_retransmitted: sequence number of most recently retransmitted message
+ * @stale_count: # of identical retransmit requests made by peer
+ * @next_in_no: next sequence number to expect for inbound messages
+ * @deferred_inqueue_sz: # of messages in inbound message queue
+ * @oldest_deferred_in: ptr to first inbound message in queue
+ * @newest_deferred_in: ptr to last inbound message in queue
+ * @unacked_window: # of inbound messages rx'd without ack'ing back to peer
+ * @proto_msg_queue: ptr to (single) outbound control message
+ * @retransm_queue_size: number of messages to retransmit
+ * @retransm_queue_head: sequence number of first message to retransmit
+ * @next_out: ptr to first unsent outbound message in queue
+ * @waiting_ports: linked list of ports waiting for link congestion to abate
+ * @long_msg_seq_no: next identifier to use for outbound fragmented messages
+ * @defragm_buf: list of partially reassembled inbound message fragments
+ * @stats: collects statistics regarding link activity
+ * @print_buf: print buffer used to log link activity
+ */
+
+struct link {
+ u32 addr;
+ char name[TIPC_MAX_LINK_NAME];
+ struct tipc_media_addr media_addr;
+ struct timer_list timer;
+ struct node *owner;
+ struct list_head link_list;
+
+ /* Management and link supervision data */
+ int started;
+ u32 checkpoint;
+ u32 peer_session;
+ u32 peer_bearer_id;
+ struct bearer *b_ptr;
+ u32 tolerance;
+ u32 continuity_interval;
+ u32 abort_limit;
+ int state;
+ int blocked;
+ u32 fsm_msg_cnt;
+ struct {
+ unchar hdr[INT_H_SIZE];
+ unchar body[TIPC_MAX_IF_NAME];
+ } proto_msg;
+ struct tipc_msg *pmsg;
+ u32 priority;
+ u32 queue_limit[15]; /* queue_limit[0]==window limit */
+
+ /* Changeover */
+ u32 exp_msg_count;
+ u32 reset_checkpoint;
+
+ /* Max packet negotiation */
+ u32 max_pkt;
+ u32 max_pkt_target;
+ u32 max_pkt_probes;
+
+ /* Sending */
+ u32 out_queue_size;
+ struct sk_buff *first_out;
+ struct sk_buff *last_out;
+ u32 next_out_no;
+ u32 last_retransmitted;
+ u32 stale_count;
+
+ /* Reception */
+ u32 next_in_no;
+ u32 deferred_inqueue_sz;
+ struct sk_buff *oldest_deferred_in;
+ struct sk_buff *newest_deferred_in;
+ u32 unacked_window;
+
+ /* Congestion handling */
+ struct sk_buff *proto_msg_queue;
+ u32 retransm_queue_size;
+ u32 retransm_queue_head;
+ struct sk_buff *next_out;
+ struct list_head waiting_ports;
+
+ /* Fragmentation/defragmentation */
+ u32 long_msg_seq_no;
+ struct sk_buff *defragm_buf;
+
+ /* Statistics */
+ struct {
+ u32 sent_info; /* used in counting # sent packets */
+ u32 recv_info; /* used in counting # recv'd packets */
+ u32 sent_states;
+ u32 recv_states;
+ u32 sent_probes;
+ u32 recv_probes;
+ u32 sent_nacks;
+ u32 recv_nacks;
+ u32 sent_acks;
+ u32 sent_bundled;
+ u32 sent_bundles;
+ u32 recv_bundled;
+ u32 recv_bundles;
+ u32 retransmitted;
+ u32 sent_fragmented;
+ u32 sent_fragments;
+ u32 recv_fragmented;
+ u32 recv_fragments;
+ u32 link_congs; /* # port sends blocked by congestion */
+ u32 bearer_congs;
+ u32 deferred_recv;
+ u32 duplicates;
+
+ /* for statistical profiling of send queue size */
+
+ u32 max_queue_sz;
+ u32 accu_queue_sz;
+ u32 queue_sz_counts;
+
+ /* for statistical profiling of message lengths */
+
+ u32 msg_length_counts;
+ u32 msg_lengths_total;
+ u32 msg_length_profile[7];
+#if 0
+ u32 sent_tunneled;
+ u32 recv_tunneled;
+#endif
+ } stats;
+
+ struct print_buf print_buf;
+};
+
+struct port;
+
+struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+ const struct tipc_media_addr *media_addr);
+void tipc_link_delete(struct link *l_ptr);
+void tipc_link_changeover(struct link *l_ptr);
+void tipc_link_send_duplicate(struct link *l_ptr, struct link *dest);
+void tipc_link_reset_fragments(struct link *l_ptr);
+int tipc_link_is_up(struct link *l_ptr);
+int tipc_link_is_active(struct link *l_ptr);
+void tipc_link_start(struct link *l_ptr);
+u32 tipc_link_push_packet(struct link *l_ptr);
+void tipc_link_stop(struct link *l_ptr);
+struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
+struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
+void tipc_link_reset(struct link *l_ptr);
+int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
+int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf);
+u32 tipc_link_get_max_pkt(u32 dest,u32 selector);
+int tipc_link_send_sections_fast(struct port* sender,
+ struct iovec const *msg_sect,
+ const u32 num_sect,
+ u32 destnode);
+int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
+void tipc_link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
+ struct tipc_msg *msg, u32 selector);
+void tipc_link_recv_bundle(struct sk_buff *buf);
+int tipc_link_recv_fragment(struct sk_buff **pending,
+ struct sk_buff **fb,
+ struct tipc_msg **msg);
+void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap,
+ u32 tolerance, u32 priority, u32 acked_mtu);
+void tipc_link_push_queue(struct link *l_ptr);
+u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
+ struct sk_buff *buf);
+void tipc_link_wakeup_ports(struct link *l_ptr, int all);
+void tipc_link_set_queue_limits(struct link *l_ptr, u32 window);
+void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits);
+
+/*
+ * Link sequence number manipulation routines (uses modulo 2**16 arithmetic)
+ */
+
+static inline u32 mod(u32 x)
+{
+ return x & 0xffffu;
+}
+
+static inline int between(u32 lower, u32 upper, u32 n)
+{
+ if ((lower < n) && (n < upper))
+ return 1;
+ if ((upper < lower) && ((n > lower) || (n < upper)))
+ return 1;
+ return 0;
+}
+
+static inline int less_eq(u32 left, u32 right)
+{
+ return (mod(right - left) < 32768u);
+}
+
+static inline int less(u32 left, u32 right)
+{
+ return (less_eq(left, right) && (mod(right) != mod(left)));
+}
+
+static inline u32 lesser(u32 left, u32 right)
+{
+ return less_eq(left, right) ? left : right;
+}
+
+#endif
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
new file mode 100644
index 000000000000..3bd345a344e5
--- /dev/null
+++ b/net/tipc/msg.c
@@ -0,0 +1,323 @@
+/*
+ * net/tipc/msg.c: TIPC message header routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "addr.h"
+#include "dbg.h"
+#include "msg.h"
+#include "bearer.h"
+
+
+void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
+{
+ u32 usr = msg_user(msg);
+ tipc_printf(buf, str);
+
+ switch (usr) {
+ case MSG_BUNDLER:
+ tipc_printf(buf, "BNDL::");
+ tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
+ break;
+ case BCAST_PROTOCOL:
+ tipc_printf(buf, "BCASTP::");
+ break;
+ case MSG_FRAGMENTER:
+ tipc_printf(buf, "FRAGM::");
+ switch (msg_type(msg)) {
+ case FIRST_FRAGMENT:
+ tipc_printf(buf, "FIRST:");
+ break;
+ case FRAGMENT:
+ tipc_printf(buf, "BODY:");
+ break;
+ case LAST_FRAGMENT:
+ tipc_printf(buf, "LAST:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
+
+ }
+ tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
+ msg_fragm_no(msg));
+ break;
+ case DATA_LOW:
+ case DATA_MEDIUM:
+ case DATA_HIGH:
+ case DATA_CRITICAL:
+ tipc_printf(buf, "DAT%u:", msg_user(msg));
+ if (msg_short(msg)) {
+ tipc_printf(buf, "CON:");
+ break;
+ }
+ switch (msg_type(msg)) {
+ case TIPC_CONN_MSG:
+ tipc_printf(buf, "CON:");
+ break;
+ case TIPC_MCAST_MSG:
+ tipc_printf(buf, "MCST:");
+ break;
+ case TIPC_NAMED_MSG:
+ tipc_printf(buf, "NAM:");
+ break;
+ case TIPC_DIRECT_MSG:
+ tipc_printf(buf, "DIR:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg));
+ }
+ if (msg_routed(msg) && !msg_non_seq(msg))
+ tipc_printf(buf, "ROUT:");
+ if (msg_reroute_cnt(msg))
+ tipc_printf(buf, "REROUTED(%u):",
+ msg_reroute_cnt(msg));
+ break;
+ case NAME_DISTRIBUTOR:
+ tipc_printf(buf, "NMD::");
+ switch (msg_type(msg)) {
+ case PUBLICATION:
+ tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */
+ break;
+ case WITHDRAWAL:
+ tipc_printf(buf, "WDRW:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
+ }
+ if (msg_routed(msg))
+ tipc_printf(buf, "ROUT:");
+ if (msg_reroute_cnt(msg))
+ tipc_printf(buf, "REROUTED(%u):",
+ msg_reroute_cnt(msg));
+ break;
+ case CONN_MANAGER:
+ tipc_printf(buf, "CONN_MNG:");
+ switch (msg_type(msg)) {
+ case CONN_PROBE:
+ tipc_printf(buf, "PROBE:");
+ break;
+ case CONN_PROBE_REPLY:
+ tipc_printf(buf, "PROBE_REPLY:");
+ break;
+ case CONN_ACK:
+ tipc_printf(buf, "CONN_ACK:");
+ tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg));
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
+ }
+ if (msg_routed(msg))
+ tipc_printf(buf, "ROUT:");
+ if (msg_reroute_cnt(msg))
+ tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg));
+ break;
+ case LINK_PROTOCOL:
+ tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg));
+ switch (msg_type(msg)) {
+ case STATE_MSG:
+ tipc_printf(buf, "STATE:");
+ tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :"");
+ tipc_printf(buf, "NXS(%u):",msg_next_sent(msg));
+ tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg));
+ tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg));
+ break;
+ case RESET_MSG:
+ tipc_printf(buf, "RESET:");
+ if (msg_size(msg) != msg_hdr_sz(msg))
+ tipc_printf(buf, "BEAR:%s:",msg_data(msg));
+ break;
+ case ACTIVATE_MSG:
+ tipc_printf(buf, "ACTIVATE:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
+ }
+ tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg));
+ tipc_printf(buf, "SESS(%u):",msg_session(msg));
+ break;
+ case CHANGEOVER_PROTOCOL:
+ tipc_printf(buf, "TUNL:");
+ switch (msg_type(msg)) {
+ case DUPLICATE_MSG:
+ tipc_printf(buf, "DUPL:");
+ break;
+ case ORIGINAL_MSG:
+ tipc_printf(buf, "ORIG:");
+ tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg));
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
+ }
+ break;
+ case ROUTE_DISTRIBUTOR:
+ tipc_printf(buf, "ROUTING_MNG:");
+ switch (msg_type(msg)) {
+ case EXT_ROUTING_TABLE:
+ tipc_printf(buf, "EXT_TBL:");
+ tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
+ break;
+ case LOCAL_ROUTING_TABLE:
+ tipc_printf(buf, "LOCAL_TBL:");
+ tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
+ break;
+ case SLAVE_ROUTING_TABLE:
+ tipc_printf(buf, "DP_TBL:");
+ tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
+ break;
+ case ROUTE_ADDITION:
+ tipc_printf(buf, "ADD:");
+ tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
+ break;
+ case ROUTE_REMOVAL:
+ tipc_printf(buf, "REMOVE:");
+ tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
+ }
+ break;
+ case LINK_CONFIG:
+ tipc_printf(buf, "CFG:");
+ switch (msg_type(msg)) {
+ case DSC_REQ_MSG:
+ tipc_printf(buf, "DSC_REQ:");
+ break;
+ case DSC_RESP_MSG:
+ tipc_printf(buf, "DSC_RESP:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg));
+ break;
+ }
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN USER:");
+ }
+
+ switch (usr) {
+ case CONN_MANAGER:
+ case NAME_DISTRIBUTOR:
+ case DATA_LOW:
+ case DATA_MEDIUM:
+ case DATA_HIGH:
+ case DATA_CRITICAL:
+ if (msg_short(msg))
+ break; /* No error */
+ switch (msg_errcode(msg)) {
+ case TIPC_OK:
+ break;
+ case TIPC_ERR_NO_NAME:
+ tipc_printf(buf, "NO_NAME:");
+ break;
+ case TIPC_ERR_NO_PORT:
+ tipc_printf(buf, "NO_PORT:");
+ break;
+ case TIPC_ERR_NO_NODE:
+ tipc_printf(buf, "NO_PROC:");
+ break;
+ case TIPC_ERR_OVERLOAD:
+ tipc_printf(buf, "OVERLOAD:");
+ break;
+ case TIPC_CONN_SHUTDOWN:
+ tipc_printf(buf, "SHUTDOWN:");
+ break;
+ default:
+ tipc_printf(buf, "UNKNOWN ERROR(%x):",
+ msg_errcode(msg));
+ }
+ default:{}
+ }
+
+ tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg));
+ tipc_printf(buf, "SZ(%u):", msg_size(msg));
+ tipc_printf(buf, "SQNO(%u):", msg_seqno(msg));
+
+ if (msg_non_seq(msg))
+ tipc_printf(buf, "NOSEQ:");
+ else {
+ tipc_printf(buf, "ACK(%u):", msg_ack(msg));
+ }
+ tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg));
+ tipc_printf(buf, "PRND(%x)", msg_prevnode(msg));
+
+ if (msg_isdata(msg)) {
+ if (msg_named(msg)) {
+ tipc_printf(buf, "NTYP(%u):", msg_nametype(msg));
+ tipc_printf(buf, "NINST(%u)", msg_nameinst(msg));
+ }
+ }
+
+ if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) &&
+ (usr != MSG_BUNDLER)) {
+ if (!msg_short(msg)) {
+ tipc_printf(buf, ":ORIG(%x:%u):",
+ msg_orignode(msg), msg_origport(msg));
+ tipc_printf(buf, ":DEST(%x:%u):",
+ msg_destnode(msg), msg_destport(msg));
+ } else {
+ tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
+ tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
+ }
+ if (msg_routed(msg) && !msg_non_seq(msg))
+ tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
+ }
+ if (msg_user(msg) == NAME_DISTRIBUTOR) {
+ tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
+ tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
+ if (msg_routed(msg)) {
+ tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
+ }
+ }
+
+ if (msg_user(msg) == LINK_CONFIG) {
+ u32* raw = (u32*)msg;
+ struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5];
+ tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
+ tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
+ tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
+ tipc_media_addr_printf(buf, orig);
+ }
+ if (msg_user(msg) == BCAST_PROTOCOL) {
+ tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
+ tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg));
+ }
+ tipc_printf(buf, "\n");
+ if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
+ tipc_msg_print(buf,msg_get_wrapped(msg)," /");
+ }
+ if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
+ tipc_msg_print(buf,msg_get_wrapped(msg)," /");
+ }
+}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
new file mode 100644
index 000000000000..6699aaf7bd4c
--- /dev/null
+++ b/net/tipc/msg.h
@@ -0,0 +1,818 @@
+/*
+ * net/tipc/msg.h: Include file for TIPC message header routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_MSG_H
+#define _TIPC_MSG_H
+
+#include "core.h"
+
+#define TIPC_VERSION 2
+#define DATA_LOW TIPC_LOW_IMPORTANCE
+#define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE
+#define DATA_HIGH TIPC_HIGH_IMPORTANCE
+#define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE
+#define SHORT_H_SIZE 24 /* Connected,in cluster */
+#define DIR_MSG_H_SIZE 32 /* Directly addressed messages */
+#define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/
+#define LONG_H_SIZE 40 /* Named Messages */
+#define MCAST_H_SIZE 44 /* Multicast messages */
+#define MAX_H_SIZE 60 /* Inclusive full options */
+#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
+#define LINK_CONFIG 13
+
+
+/*
+ TIPC user data message header format, version 2
+
+ - Fundamental definitions available to privileged TIPC users
+ are located in tipc_msg.h.
+ - Remaining definitions available to TIPC internal users appear below.
+*/
+
+
+static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val)
+{
+ m->hdr[w] = htonl(val);
+}
+
+static inline void msg_set_bits(struct tipc_msg *m, u32 w,
+ u32 pos, u32 mask, u32 val)
+{
+ u32 word = msg_word(m,w) & ~(mask << pos);
+ msg_set_word(m, w, (word |= (val << pos)));
+}
+
+/*
+ * Word 0
+ */
+
+static inline u32 msg_version(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 29, 7);
+}
+
+static inline void msg_set_version(struct tipc_msg *m)
+{
+ msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
+}
+
+static inline u32 msg_user(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 25, 0xf);
+}
+
+static inline u32 msg_isdata(struct tipc_msg *m)
+{
+ return (msg_user(m) <= DATA_CRITICAL);
+}
+
+static inline void msg_set_user(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 0, 25, 0xf, n);
+}
+
+static inline void msg_set_importance(struct tipc_msg *m, u32 i)
+{
+ msg_set_user(m, i);
+}
+
+static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n)
+{
+ msg_set_bits(m, 0, 21, 0xf, n>>2);
+}
+
+static inline int msg_non_seq(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 20, 1);
+}
+
+static inline void msg_set_non_seq(struct tipc_msg *m)
+{
+ msg_set_bits(m, 0, 20, 1, 1);
+}
+
+static inline int msg_dest_droppable(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 19, 1);
+}
+
+static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d)
+{
+ msg_set_bits(m, 0, 19, 1, d);
+}
+
+static inline int msg_src_droppable(struct tipc_msg *m)
+{
+ return msg_bits(m, 0, 18, 1);
+}
+
+static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d)
+{
+ msg_set_bits(m, 0, 18, 1, d);
+}
+
+static inline void msg_set_size(struct tipc_msg *m, u32 sz)
+{
+ m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz);
+}
+
+
+/*
+ * Word 1
+ */
+
+static inline void msg_set_type(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 1, 29, 0x7, n);
+}
+
+static inline void msg_set_errcode(struct tipc_msg *m, u32 err)
+{
+ msg_set_bits(m, 1, 25, 0xf, err);
+}
+
+static inline u32 msg_reroute_cnt(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 21, 0xf);
+}
+
+static inline void msg_incr_reroute_cnt(struct tipc_msg *m)
+{
+ msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1);
+}
+
+static inline void msg_reset_reroute_cnt(struct tipc_msg *m)
+{
+ msg_set_bits(m, 1, 21, 0xf, 0);
+}
+
+static inline u32 msg_lookup_scope(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 19, 0x3);
+}
+
+static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 1, 19, 0x3, n);
+}
+
+static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz)
+{
+ u32 hsz = msg_hdr_sz(m);
+ char *to = (char *)&m->hdr[hsz/4];
+
+ if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
+ return;
+ msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
+ msg_set_hdr_sz(m, hsz + sz);
+ memcpy(to, opt, sz);
+}
+
+static inline u32 msg_bcast_ack(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 0, 0xffff);
+}
+
+static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 1, 0, 0xffff, n);
+}
+
+
+/*
+ * Word 2
+ */
+
+static inline u32 msg_ack(struct tipc_msg *m)
+{
+ return msg_bits(m, 2, 16, 0xffff);
+}
+
+static inline void msg_set_ack(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 2, 16, 0xffff, n);
+}
+
+static inline u32 msg_seqno(struct tipc_msg *m)
+{
+ return msg_bits(m, 2, 0, 0xffff);
+}
+
+static inline void msg_set_seqno(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 2, 0, 0xffff, n);
+}
+
+
+/*
+ * Words 3-10
+ */
+
+
+static inline void msg_set_prevnode(struct tipc_msg *m, u32 a)
+{
+ msg_set_word(m, 3, a);
+}
+
+static inline void msg_set_origport(struct tipc_msg *m, u32 p)
+{
+ msg_set_word(m, 4, p);
+}
+
+static inline void msg_set_destport(struct tipc_msg *m, u32 p)
+{
+ msg_set_word(m, 5, p);
+}
+
+static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
+{
+ msg_set_word(m, 5, p);
+}
+
+static inline void msg_set_orignode(struct tipc_msg *m, u32 a)
+{
+ msg_set_word(m, 6, a);
+}
+
+static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
+{
+ msg_set_word(m, 7, a);
+}
+
+static inline int msg_is_dest(struct tipc_msg *m, u32 d)
+{
+ return(msg_short(m) || (msg_destnode(m) == d));
+}
+
+static inline u32 msg_routed(struct tipc_msg *m)
+{
+ if (likely(msg_short(m)))
+ return 0;
+ return(msg_destnode(m) ^ msg_orignode(m)) >> 11;
+}
+
+static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 8, n);
+}
+
+static inline u32 msg_transp_seqno(struct tipc_msg *m)
+{
+ return msg_word(m, 8);
+}
+
+static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 8, n);
+}
+
+static inline u32 msg_timestamp(struct tipc_msg *m)
+{
+ return msg_word(m, 8);
+}
+
+static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 8, n);
+}
+
+static inline void msg_set_namelower(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 9, n);
+}
+
+static inline void msg_set_nameinst(struct tipc_msg *m, u32 n)
+{
+ msg_set_namelower(m, n);
+}
+
+static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 10, n);
+}
+
+static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
+{
+ return (struct tipc_msg *)msg_data(m);
+}
+
+static inline void msg_expand(struct tipc_msg *m, u32 destnode)
+{
+ if (!msg_short(m))
+ return;
+ msg_set_hdr_sz(m, LONG_H_SIZE);
+ msg_set_orignode(m, msg_prevnode(m));
+ msg_set_destnode(m, destnode);
+ memset(&m->hdr[8], 0, 12);
+}
+
+
+
+/*
+ TIPC internal message header format, version 2
+
+ 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w0:|vers |msg usr|hdr sz |n|resrv| packet size |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w1:|m typ|rsv=0| sequence gap | broadcast ack no |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w3:| previous node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w5:| session no |rsv=0|r|berid|link prio|netpl|p|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w6:| originating node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w7:| destination node |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w8:| transport sequence number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ w9:| msg count / bcast tag | link tolerance |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ \ \
+ / User Specific Data /
+ \ \
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ NB: CONN_MANAGER use data message format. LINK_CONFIG has own format.
+*/
+
+/*
+ * Internal users
+ */
+
+#define BCAST_PROTOCOL 5
+#define MSG_BUNDLER 6
+#define LINK_PROTOCOL 7
+#define CONN_MANAGER 8
+#define ROUTE_DISTRIBUTOR 9
+#define CHANGEOVER_PROTOCOL 10
+#define NAME_DISTRIBUTOR 11
+#define MSG_FRAGMENTER 12
+#define LINK_CONFIG 13
+#define INT_H_SIZE 40
+#define DSC_H_SIZE 40
+
+/*
+ * Connection management protocol messages
+ */
+
+#define CONN_PROBE 0
+#define CONN_PROBE_REPLY 1
+#define CONN_ACK 2
+
+/*
+ * Name distributor messages
+ */
+
+#define PUBLICATION 0
+#define WITHDRAWAL 1
+
+
+/*
+ * Word 1
+ */
+
+static inline u32 msg_seq_gap(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 16, 0xff);
+}
+
+static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 1, 16, 0xff, n);
+}
+
+static inline u32 msg_req_links(struct tipc_msg *m)
+{
+ return msg_bits(m, 1, 16, 0xfff);
+}
+
+static inline void msg_set_req_links(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 1, 16, 0xfff, n);
+}
+
+
+/*
+ * Word 2
+ */
+
+static inline u32 msg_dest_domain(struct tipc_msg *m)
+{
+ return msg_word(m, 2);
+}
+
+static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n)
+{
+ msg_set_word(m, 2, n);
+}
+
+static inline u32 msg_bcgap_after(struct tipc_msg *m)
+{
+ return msg_bits(m, 2, 16, 0xffff);
+}
+
+static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 2, 16, 0xffff, n);
+}
+
+static inline u32 msg_bcgap_to(struct tipc_msg *m)
+{
+ return msg_bits(m, 2, 0, 0xffff);
+}
+
+static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 2, 0, 0xffff, n);
+}
+
+
+/*
+ * Word 4
+ */
+
+static inline u32 msg_last_bcast(struct tipc_msg *m)
+{
+ return msg_bits(m, 4, 16, 0xffff);
+}
+
+static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 4, 16, 0xffff, n);
+}
+
+
+static inline u32 msg_fragm_no(struct tipc_msg *m)
+{
+ return msg_bits(m, 4, 16, 0xffff);
+}
+
+static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 4, 16, 0xffff, n);
+}
+
+
+static inline u32 msg_next_sent(struct tipc_msg *m)
+{
+ return msg_bits(m, 4, 0, 0xffff);
+}
+
+static inline void msg_set_next_sent(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 4, 0, 0xffff, n);
+}
+
+
+static inline u32 msg_long_msgno(struct tipc_msg *m)
+{
+ return msg_bits(m, 4, 0, 0xffff);
+}
+
+static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 4, 0, 0xffff, n);
+}
+
+static inline u32 msg_bc_netid(struct tipc_msg *m)
+{
+ return msg_word(m, 4);
+}
+
+static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id)
+{
+ msg_set_word(m, 4, id);
+}
+
+static inline u32 msg_link_selector(struct tipc_msg *m)
+{
+ return msg_bits(m, 4, 0, 1);
+}
+
+static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 4, 0, 1, (n & 1));
+}
+
+/*
+ * Word 5
+ */
+
+static inline u32 msg_session(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 16, 0xffff);
+}
+
+static inline void msg_set_session(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 5, 16, 0xffff, n);
+}
+
+static inline u32 msg_probe(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 0, 1);
+}
+
+static inline void msg_set_probe(struct tipc_msg *m, u32 val)
+{
+ msg_set_bits(m, 5, 0, 1, (val & 1));
+}
+
+static inline char msg_net_plane(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 1, 7) + 'A';
+}
+
+static inline void msg_set_net_plane(struct tipc_msg *m, char n)
+{
+ msg_set_bits(m, 5, 1, 7, (n - 'A'));
+}
+
+static inline u32 msg_linkprio(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 4, 0x1f);
+}
+
+static inline void msg_set_linkprio(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 5, 4, 0x1f, n);
+}
+
+static inline u32 msg_bearer_id(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 9, 0x7);
+}
+
+static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 5, 9, 0x7, n);
+}
+
+static inline u32 msg_redundant_link(struct tipc_msg *m)
+{
+ return msg_bits(m, 5, 12, 0x1);
+}
+
+static inline void msg_set_redundant_link(struct tipc_msg *m)
+{
+ msg_set_bits(m, 5, 12, 0x1, 1);
+}
+
+static inline void msg_clear_redundant_link(struct tipc_msg *m)
+{
+ msg_set_bits(m, 5, 12, 0x1, 0);
+}
+
+
+/*
+ * Word 9
+ */
+
+static inline u32 msg_msgcnt(struct tipc_msg *m)
+{
+ return msg_bits(m, 9, 16, 0xffff);
+}
+
+static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 9, 16, 0xffff, n);
+}
+
+static inline u32 msg_bcast_tag(struct tipc_msg *m)
+{
+ return msg_bits(m, 9, 16, 0xffff);
+}
+
+static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 9, 16, 0xffff, n);
+}
+
+static inline u32 msg_max_pkt(struct tipc_msg *m)
+{
+ return (msg_bits(m, 9, 16, 0xffff) * 4);
+}
+
+static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 9, 16, 0xffff, (n / 4));
+}
+
+static inline u32 msg_link_tolerance(struct tipc_msg *m)
+{
+ return msg_bits(m, 9, 0, 0xffff);
+}
+
+static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
+{
+ msg_set_bits(m, 9, 0, 0xffff, n);
+}
+
+/*
+ * Routing table message data
+ */
+
+
+static inline u32 msg_remote_node(struct tipc_msg *m)
+{
+ return msg_word(m, msg_hdr_sz(m)/4);
+}
+
+static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
+{
+ msg_set_word(m, msg_hdr_sz(m)/4, a);
+}
+
+static inline int msg_dataoctet(struct tipc_msg *m, u32 pos)
+{
+ return(msg_data(m)[pos + 4] != 0);
+}
+
+static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)
+{
+ msg_data(m)[pos + 4] = 1;
+}
+
+/*
+ * Segmentation message types
+ */
+
+#define FIRST_FRAGMENT 0
+#define FRAGMENT 1
+#define LAST_FRAGMENT 2
+
+/*
+ * Link management protocol message types
+ */
+
+#define STATE_MSG 0
+#define RESET_MSG 1
+#define ACTIVATE_MSG 2
+
+/*
+ * Changeover tunnel message types
+ */
+#define DUPLICATE_MSG 0
+#define ORIGINAL_MSG 1
+
+/*
+ * Routing table message types
+ */
+#define EXT_ROUTING_TABLE 0
+#define LOCAL_ROUTING_TABLE 1
+#define SLAVE_ROUTING_TABLE 2
+#define ROUTE_ADDITION 3
+#define ROUTE_REMOVAL 4
+
+/*
+ * Config protocol message types
+ */
+
+#define DSC_REQ_MSG 0
+#define DSC_RESP_MSG 1
+
+static inline u32 msg_tot_importance(struct tipc_msg *m)
+{
+ if (likely(msg_isdata(m))) {
+ if (likely(msg_orignode(m) == tipc_own_addr))
+ return msg_importance(m);
+ return msg_importance(m) + 4;
+ }
+ if ((msg_user(m) == MSG_FRAGMENTER) &&
+ (msg_type(m) == FIRST_FRAGMENT))
+ return msg_importance(msg_get_wrapped(m));
+ return msg_importance(m);
+}
+
+
+static inline void msg_init(struct tipc_msg *m, u32 user, u32 type,
+ u32 err, u32 hsize, u32 destnode)
+{
+ memset(m, 0, hsize);
+ msg_set_version(m);
+ msg_set_user(m, user);
+ msg_set_hdr_sz(m, hsize);
+ msg_set_size(m, hsize);
+ msg_set_prevnode(m, tipc_own_addr);
+ msg_set_type(m, type);
+ msg_set_errcode(m, err);
+ if (!msg_short(m)) {
+ msg_set_orignode(m, tipc_own_addr);
+ msg_set_destnode(m, destnode);
+ }
+}
+
+/**
+ * msg_calc_data_size - determine total data size for message
+ */
+
+static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
+{
+ int dsz = 0;
+ int i;
+
+ for (i = 0; i < num_sect; i++)
+ dsz += msg_sect[i].iov_len;
+ return dsz;
+}
+
+/**
+ * msg_build - create message using specified header and data
+ *
+ * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
+ *
+ * Returns message data size or errno
+ */
+
+static inline int msg_build(struct tipc_msg *hdr,
+ struct iovec const *msg_sect, u32 num_sect,
+ int max_size, int usrmem, struct sk_buff** buf)
+{
+ int dsz, sz, hsz, pos, res, cnt;
+
+ dsz = msg_calc_data_size(msg_sect, num_sect);
+ if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
+ *buf = NULL;
+ return -EINVAL;
+ }
+
+ pos = hsz = msg_hdr_sz(hdr);
+ sz = hsz + dsz;
+ msg_set_size(hdr, sz);
+ if (unlikely(sz > max_size)) {
+ *buf = NULL;
+ return dsz;
+ }
+
+ *buf = buf_acquire(sz);
+ if (!(*buf))
+ return -ENOMEM;
+ memcpy((*buf)->data, (unchar *)hdr, hsz);
+ for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
+ if (likely(usrmem))
+ res = !copy_from_user((*buf)->data + pos,
+ msg_sect[cnt].iov_base,
+ msg_sect[cnt].iov_len);
+ else
+ memcpy((*buf)->data + pos, msg_sect[cnt].iov_base,
+ msg_sect[cnt].iov_len);
+ pos += msg_sect[cnt].iov_len;
+ }
+ if (likely(res))
+ return dsz;
+
+ buf_discard(*buf);
+ *buf = NULL;
+ return -EFAULT;
+}
+
+static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
+{
+ memcpy(&((int *)m)[5], a, sizeof(*a));
+}
+
+static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
+{
+ memcpy(a, &((int*)m)[5], sizeof(*a));
+}
+
+#endif
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
new file mode 100644
index 000000000000..830f90999041
--- /dev/null
+++ b/net/tipc/name_distr.c
@@ -0,0 +1,309 @@
+/*
+ * net/tipc/name_distr.c: TIPC name distribution code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "cluster.h"
+#include "dbg.h"
+#include "link.h"
+#include "msg.h"
+#include "name_distr.h"
+
+#undef DBG_OUTPUT
+#define DBG_OUTPUT NULL
+
+#define ITEM_SIZE sizeof(struct distr_item)
+
+/**
+ * struct distr_item - publication info distributed to other nodes
+ * @type: name sequence type
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @ref: publishing port reference
+ * @key: publication key
+ *
+ * ===> All fields are stored in network byte order. <===
+ *
+ * First 3 fields identify (name or) name sequence being published.
+ * Reference field uniquely identifies port that published name sequence.
+ * Key field uniquely identifies publication, in the event a port has
+ * multiple publications of the same name sequence.
+ *
+ * Note: There is no field that identifies the publishing node because it is
+ * the same for all items contained within a publication message.
+ */
+
+struct distr_item {
+ u32 type;
+ u32 lower;
+ u32 upper;
+ u32 ref;
+ u32 key;
+};
+
+/**
+ * List of externally visible publications by this node --
+ * that is, all publications having scope > TIPC_NODE_SCOPE.
+ */
+
+static LIST_HEAD(publ_root);
+static u32 publ_cnt = 0;
+
+/**
+ * publ_to_item - add publication info to a publication message
+ */
+
+static void publ_to_item(struct distr_item *i, struct publication *p)
+{
+ i->type = htonl(p->type);
+ i->lower = htonl(p->lower);
+ i->upper = htonl(p->upper);
+ i->ref = htonl(p->ref);
+ i->key = htonl(p->key);
+ dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper);
+}
+
+/**
+ * named_prepare_buf - allocate & initialize a publication message
+ */
+
+static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
+{
+ struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
+ struct tipc_msg *msg;
+
+ if (buf != NULL) {
+ msg = buf_msg(buf);
+ msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK,
+ LONG_H_SIZE, dest);
+ msg_set_size(msg, LONG_H_SIZE + size);
+ }
+ return buf;
+}
+
+/**
+ * tipc_named_publish - tell other nodes about a new publication by this node
+ */
+
+void tipc_named_publish(struct publication *publ)
+{
+ struct sk_buff *buf;
+ struct distr_item *item;
+
+ list_add(&publ->local_list, &publ_root);
+ publ_cnt++;
+
+ buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
+ if (!buf) {
+ warn("Memory squeeze; failed to distribute publication\n");
+ return;
+ }
+
+ item = (struct distr_item *)msg_data(buf_msg(buf));
+ publ_to_item(item, publ);
+ dbg("tipc_named_withdraw: broadcasting publish msg\n");
+ tipc_cltr_broadcast(buf);
+}
+
+/**
+ * tipc_named_withdraw - tell other nodes about a withdrawn publication by this node
+ */
+
+void tipc_named_withdraw(struct publication *publ)
+{
+ struct sk_buff *buf;
+ struct distr_item *item;
+
+ list_del(&publ->local_list);
+ publ_cnt--;
+
+ buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
+ if (!buf) {
+ warn("Memory squeeze; failed to distribute withdrawal\n");
+ return;
+ }
+
+ item = (struct distr_item *)msg_data(buf_msg(buf));
+ publ_to_item(item, publ);
+ dbg("tipc_named_withdraw: broadcasting withdraw msg\n");
+ tipc_cltr_broadcast(buf);
+}
+
+/**
+ * tipc_named_node_up - tell specified node about all publications by this node
+ */
+
+void tipc_named_node_up(unsigned long node)
+{
+ struct publication *publ;
+ struct distr_item *item = 0;
+ struct sk_buff *buf = 0;
+ u32 left = 0;
+ u32 rest;
+ u32 max_item_buf;
+
+ assert(in_own_cluster(node));
+ read_lock_bh(&tipc_nametbl_lock);
+ max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
+ max_item_buf *= ITEM_SIZE;
+ rest = publ_cnt * ITEM_SIZE;
+
+ list_for_each_entry(publ, &publ_root, local_list) {
+ if (!buf) {
+ left = (rest <= max_item_buf) ? rest : max_item_buf;
+ rest -= left;
+ buf = named_prepare_buf(PUBLICATION, left, node);
+ if (buf == NULL) {
+ warn("Memory Squeeze; could not send publication\n");
+ goto exit;
+ }
+ item = (struct distr_item *)msg_data(buf_msg(buf));
+ }
+ publ_to_item(item, publ);
+ item++;
+ left -= ITEM_SIZE;
+ if (!left) {
+ msg_set_link_selector(buf_msg(buf), node);
+ dbg("tipc_named_node_up: sending publish msg to "
+ "<%u.%u.%u>\n", tipc_zone(node),
+ tipc_cluster(node), tipc_node(node));
+ tipc_link_send(buf, node, node);
+ buf = 0;
+ }
+ }
+exit:
+ read_unlock_bh(&tipc_nametbl_lock);
+}
+
+/**
+ * node_is_down - remove publication associated with a failed node
+ *
+ * Invoked for each publication issued by a newly failed node.
+ * Removes publication structure from name table & deletes it.
+ * In rare cases the link may have come back up again when this
+ * function is called, and we have two items representing the same
+ * publication. Nudge this item's key to distinguish it from the other.
+ * (Note: Publication's node subscription is already unsubscribed.)
+ */
+
+static void node_is_down(struct publication *publ)
+{
+ struct publication *p;
+ write_lock_bh(&tipc_nametbl_lock);
+ dbg("node_is_down: withdrawing %u, %u, %u\n",
+ publ->type, publ->lower, publ->upper);
+ publ->key += 1222345;
+ p = tipc_nametbl_remove_publ(publ->type, publ->lower,
+ publ->node, publ->ref, publ->key);
+ assert(p == publ);
+ write_unlock_bh(&tipc_nametbl_lock);
+ if (publ)
+ kfree(publ);
+}
+
+/**
+ * tipc_named_recv - process name table update message sent by another node
+ */
+
+void tipc_named_recv(struct sk_buff *buf)
+{
+ struct publication *publ;
+ struct tipc_msg *msg = buf_msg(buf);
+ struct distr_item *item = (struct distr_item *)msg_data(msg);
+ u32 count = msg_data_sz(msg) / ITEM_SIZE;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ while (count--) {
+ if (msg_type(msg) == PUBLICATION) {
+ dbg("tipc_named_recv: got publication for %u, %u, %u\n",
+ ntohl(item->type), ntohl(item->lower),
+ ntohl(item->upper));
+ publ = tipc_nametbl_insert_publ(ntohl(item->type),
+ ntohl(item->lower),
+ ntohl(item->upper),
+ TIPC_CLUSTER_SCOPE,
+ msg_orignode(msg),
+ ntohl(item->ref),
+ ntohl(item->key));
+ if (publ) {
+ tipc_nodesub_subscribe(&publ->subscr,
+ msg_orignode(msg),
+ publ,
+ (net_ev_handler)node_is_down);
+ }
+ } else if (msg_type(msg) == WITHDRAWAL) {
+ dbg("tipc_named_recv: got withdrawl for %u, %u, %u\n",
+ ntohl(item->type), ntohl(item->lower),
+ ntohl(item->upper));
+ publ = tipc_nametbl_remove_publ(ntohl(item->type),
+ ntohl(item->lower),
+ msg_orignode(msg),
+ ntohl(item->ref),
+ ntohl(item->key));
+
+ if (publ) {
+ tipc_nodesub_unsubscribe(&publ->subscr);
+ kfree(publ);
+ }
+ } else {
+ warn("tipc_named_recv: unknown msg\n");
+ }
+ item++;
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+ buf_discard(buf);
+}
+
+/**
+ * tipc_named_reinit - re-initialize local publication list
+ *
+ * This routine is called whenever TIPC networking is (re)enabled.
+ * All existing publications by this node that have "cluster" or "zone" scope
+ * are updated to reflect the node's current network address.
+ * (If the node's address is unchanged, the update loop terminates immediately.)
+ */
+
+void tipc_named_reinit(void)
+{
+ struct publication *publ;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ list_for_each_entry(publ, &publ_root, local_list) {
+ if (publ->node == tipc_own_addr)
+ break;
+ publ->node = tipc_own_addr;
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+}
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h
new file mode 100644
index 000000000000..843da0172f4e
--- /dev/null
+++ b/net/tipc/name_distr.h
@@ -0,0 +1,48 @@
+/*
+ * net/tipc/name_distr.h: Include file for TIPC name distribution code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NAME_DISTR_H
+#define _TIPC_NAME_DISTR_H
+
+#include "name_table.h"
+
+void tipc_named_publish(struct publication *publ);
+void tipc_named_withdraw(struct publication *publ);
+void tipc_named_node_up(unsigned long node);
+void tipc_named_recv(struct sk_buff *buf);
+void tipc_named_reinit(void);
+
+#endif
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
new file mode 100644
index 000000000000..3f4b23bd08f7
--- /dev/null
+++ b/net/tipc/name_table.c
@@ -0,0 +1,1079 @@
+/*
+ * net/tipc/name_table.c: TIPC name table code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include "dbg.h"
+#include "name_table.h"
+#include "name_distr.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "subscr.h"
+#include "port.h"
+#include "cluster.h"
+#include "bcast.h"
+
+int tipc_nametbl_size = 1024; /* must be a power of 2 */
+
+/**
+ * struct sub_seq - container for all published instances of a name sequence
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @node_list: circular list of matching publications with >= node scope
+ * @cluster_list: circular list of matching publications with >= cluster scope
+ * @zone_list: circular list of matching publications with >= zone scope
+ */
+
+struct sub_seq {
+ u32 lower;
+ u32 upper;
+ struct publication *node_list;
+ struct publication *cluster_list;
+ struct publication *zone_list;
+};
+
+/**
+ * struct name_seq - container for all published instances of a name type
+ * @type: 32 bit 'type' value for name sequence
+ * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
+ * sub-sequences are sorted in ascending order
+ * @alloc: number of sub-sequences currently in array
+ * @first_free: upper bound of highest sub-sequence + 1
+ * @ns_list: links to adjacent name sequences in hash chain
+ * @subscriptions: list of subscriptions for this 'type'
+ * @lock: spinlock controlling access to name sequence structure
+ */
+
+struct name_seq {
+ u32 type;
+ struct sub_seq *sseqs;
+ u32 alloc;
+ u32 first_free;
+ struct hlist_node ns_list;
+ struct list_head subscriptions;
+ spinlock_t lock;
+};
+
+/**
+ * struct name_table - table containing all existing port name publications
+ * @types: pointer to fixed-sized array of name sequence lists,
+ * accessed via hashing on 'type'; name sequence lists are *not* sorted
+ * @local_publ_count: number of publications issued by this node
+ */
+
+struct name_table {
+ struct hlist_head *types;
+ u32 local_publ_count;
+};
+
+static struct name_table table = { NULL } ;
+static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
+rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED;
+
+
+static inline int hash(int x)
+{
+ return(x & (tipc_nametbl_size - 1));
+}
+
+/**
+ * publ_create - create a publication structure
+ */
+
+static struct publication *publ_create(u32 type, u32 lower, u32 upper,
+ u32 scope, u32 node, u32 port_ref,
+ u32 key)
+{
+ struct publication *publ =
+ (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
+ if (publ == NULL) {
+ warn("Memory squeeze; failed to create publication\n");
+ return 0;
+ }
+
+ memset(publ, 0, sizeof(*publ));
+ publ->type = type;
+ publ->lower = lower;
+ publ->upper = upper;
+ publ->scope = scope;
+ publ->node = node;
+ publ->ref = port_ref;
+ publ->key = key;
+ INIT_LIST_HEAD(&publ->local_list);
+ INIT_LIST_HEAD(&publ->pport_list);
+ INIT_LIST_HEAD(&publ->subscr.nodesub_list);
+ return publ;
+}
+
+/**
+ * tipc_subseq_alloc - allocate a specified number of sub-sequence structures
+ */
+
+struct sub_seq *tipc_subseq_alloc(u32 cnt)
+{
+ u32 sz = cnt * sizeof(struct sub_seq);
+ struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC);
+
+ if (sseq)
+ memset(sseq, 0, sz);
+ return sseq;
+}
+
+/**
+ * tipc_nameseq_create - create a name sequence structure for the specified 'type'
+ *
+ * Allocates a single sub-sequence structure and sets it to all 0's.
+ */
+
+struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
+{
+ struct name_seq *nseq =
+ (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC);
+ struct sub_seq *sseq = tipc_subseq_alloc(1);
+
+ if (!nseq || !sseq) {
+ warn("Memory squeeze; failed to create name sequence\n");
+ kfree(nseq);
+ kfree(sseq);
+ return 0;
+ }
+
+ memset(nseq, 0, sizeof(*nseq));
+ nseq->lock = SPIN_LOCK_UNLOCKED;
+ nseq->type = type;
+ nseq->sseqs = sseq;
+ dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n",
+ nseq, type, nseq->sseqs, nseq->first_free);
+ nseq->alloc = 1;
+ INIT_HLIST_NODE(&nseq->ns_list);
+ INIT_LIST_HEAD(&nseq->subscriptions);
+ hlist_add_head(&nseq->ns_list, seq_head);
+ return nseq;
+}
+
+/**
+ * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
+ *
+ * Very time-critical, so binary searches through sub-sequence array.
+ */
+
+static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
+ u32 instance)
+{
+ struct sub_seq *sseqs = nseq->sseqs;
+ int low = 0;
+ int high = nseq->first_free - 1;
+ int mid;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if (instance < sseqs[mid].lower)
+ high = mid - 1;
+ else if (instance > sseqs[mid].upper)
+ low = mid + 1;
+ else
+ return &sseqs[mid];
+ }
+ return 0;
+}
+
+/**
+ * nameseq_locate_subseq - determine position of name instance in sub-sequence
+ *
+ * Returns index in sub-sequence array of the entry that contains the specified
+ * instance value; if no entry contains that value, returns the position
+ * where a new entry for it would be inserted in the array.
+ *
+ * Note: Similar to binary search code for locating a sub-sequence.
+ */
+
+static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
+{
+ struct sub_seq *sseqs = nseq->sseqs;
+ int low = 0;
+ int high = nseq->first_free - 1;
+ int mid;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if (instance < sseqs[mid].lower)
+ high = mid - 1;
+ else if (instance > sseqs[mid].upper)
+ low = mid + 1;
+ else
+ return mid;
+ }
+ return low;
+}
+
+/**
+ * tipc_nameseq_insert_publ -
+ */
+
+struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
+ u32 type, u32 lower, u32 upper,
+ u32 scope, u32 node, u32 port, u32 key)
+{
+ struct subscription *s;
+ struct subscription *st;
+ struct publication *publ;
+ struct sub_seq *sseq;
+ int created_subseq = 0;
+
+ assert(nseq->first_free <= nseq->alloc);
+ sseq = nameseq_find_subseq(nseq, lower);
+ dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n",
+ nseq, type, lower, sseq);
+ if (sseq) {
+
+ /* Lower end overlaps existing entry => need an exact match */
+
+ if ((sseq->lower != lower) || (sseq->upper != upper)) {
+ warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
+ return 0;
+ }
+ } else {
+ u32 inspos;
+ struct sub_seq *freesseq;
+
+ /* Find where lower end should be inserted */
+
+ inspos = nameseq_locate_subseq(nseq, lower);
+
+ /* Fail if upper end overlaps into an existing entry */
+
+ if ((inspos < nseq->first_free) &&
+ (upper >= nseq->sseqs[inspos].lower)) {
+ warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
+ return 0;
+ }
+
+ /* Ensure there is space for new sub-sequence */
+
+ if (nseq->first_free == nseq->alloc) {
+ struct sub_seq *sseqs = nseq->sseqs;
+ nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2);
+ if (nseq->sseqs != NULL) {
+ memcpy(nseq->sseqs, sseqs,
+ nseq->alloc * sizeof (struct sub_seq));
+ kfree(sseqs);
+ dbg("Allocated %u sseqs\n", nseq->alloc);
+ nseq->alloc *= 2;
+ } else {
+ warn("Memory squeeze; failed to create sub-sequence\n");
+ return 0;
+ }
+ }
+ dbg("Have %u sseqs for type %u\n", nseq->alloc, type);
+
+ /* Insert new sub-sequence */
+
+ dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free);
+ sseq = &nseq->sseqs[inspos];
+ freesseq = &nseq->sseqs[nseq->first_free];
+ memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq));
+ memset(sseq, 0, sizeof (*sseq));
+ nseq->first_free++;
+ sseq->lower = lower;
+ sseq->upper = upper;
+ created_subseq = 1;
+ }
+ dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n",
+ type, lower, upper, node, port, sseq,
+ sseq->lower, sseq->upper, nseq);
+
+ /* Insert a publication: */
+
+ publ = publ_create(type, lower, upper, scope, node, port, key);
+ if (!publ)
+ return 0;
+ dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n",
+ publ, node, publ->node, publ->subscr.node);
+
+ if (!sseq->zone_list)
+ sseq->zone_list = publ->zone_list_next = publ;
+ else {
+ publ->zone_list_next = sseq->zone_list->zone_list_next;
+ sseq->zone_list->zone_list_next = publ;
+ }
+
+ if (in_own_cluster(node)) {
+ if (!sseq->cluster_list)
+ sseq->cluster_list = publ->cluster_list_next = publ;
+ else {
+ publ->cluster_list_next =
+ sseq->cluster_list->cluster_list_next;
+ sseq->cluster_list->cluster_list_next = publ;
+ }
+ }
+
+ if (node == tipc_own_addr) {
+ if (!sseq->node_list)
+ sseq->node_list = publ->node_list_next = publ;
+ else {
+ publ->node_list_next = sseq->node_list->node_list_next;
+ sseq->node_list->node_list_next = publ;
+ }
+ }
+
+ /*
+ * Any subscriptions waiting for notification?
+ */
+ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
+ dbg("calling report_overlap()\n");
+ tipc_subscr_report_overlap(s,
+ publ->lower,
+ publ->upper,
+ TIPC_PUBLISHED,
+ publ->ref,
+ publ->node,
+ created_subseq);
+ }
+ return publ;
+}
+
+/**
+ * tipc_nameseq_remove_publ -
+ */
+
+struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
+ u32 node, u32 ref, u32 key)
+{
+ struct publication *publ;
+ struct publication *prev;
+ struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
+ struct sub_seq *free;
+ struct subscription *s, *st;
+ int removed_subseq = 0;
+
+ assert(nseq);
+
+ if (!sseq) {
+ int i;
+
+ warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst);
+ assert(nseq->sseqs);
+ dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n",
+ nseq->sseqs, nseq, nseq->alloc,
+ nseq->first_free);
+ for (i = 0; i < nseq->first_free; i++) {
+ dbg("Subseq %u(%x): lower = %u,upper = %u\n",
+ i, &nseq->sseqs[i], nseq->sseqs[i].lower,
+ nseq->sseqs[i].upper);
+ }
+ return 0;
+ }
+ dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n",
+ nseq, sseq, nseq->type, inst, key);
+
+ prev = sseq->zone_list;
+ publ = sseq->zone_list->zone_list_next;
+ while ((publ->key != key) || (publ->ref != ref) ||
+ (publ->node && (publ->node != node))) {
+ prev = publ;
+ publ = publ->zone_list_next;
+ assert(prev != sseq->zone_list);
+ }
+ if (publ != sseq->zone_list)
+ prev->zone_list_next = publ->zone_list_next;
+ else if (publ->zone_list_next != publ) {
+ prev->zone_list_next = publ->zone_list_next;
+ sseq->zone_list = publ->zone_list_next;
+ } else {
+ sseq->zone_list = 0;
+ }
+
+ if (in_own_cluster(node)) {
+ prev = sseq->cluster_list;
+ publ = sseq->cluster_list->cluster_list_next;
+ while ((publ->key != key) || (publ->ref != ref) ||
+ (publ->node && (publ->node != node))) {
+ prev = publ;
+ publ = publ->cluster_list_next;
+ assert(prev != sseq->cluster_list);
+ }
+ if (publ != sseq->cluster_list)
+ prev->cluster_list_next = publ->cluster_list_next;
+ else if (publ->cluster_list_next != publ) {
+ prev->cluster_list_next = publ->cluster_list_next;
+ sseq->cluster_list = publ->cluster_list_next;
+ } else {
+ sseq->cluster_list = 0;
+ }
+ }
+
+ if (node == tipc_own_addr) {
+ prev = sseq->node_list;
+ publ = sseq->node_list->node_list_next;
+ while ((publ->key != key) || (publ->ref != ref) ||
+ (publ->node && (publ->node != node))) {
+ prev = publ;
+ publ = publ->node_list_next;
+ assert(prev != sseq->node_list);
+ }
+ if (publ != sseq->node_list)
+ prev->node_list_next = publ->node_list_next;
+ else if (publ->node_list_next != publ) {
+ prev->node_list_next = publ->node_list_next;
+ sseq->node_list = publ->node_list_next;
+ } else {
+ sseq->node_list = 0;
+ }
+ }
+ assert(!publ->node || (publ->node == node));
+ assert(publ->ref == ref);
+ assert(publ->key == key);
+
+ /*
+ * Contract subseq list if no more publications:
+ */
+ if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) {
+ free = &nseq->sseqs[nseq->first_free--];
+ memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq));
+ removed_subseq = 1;
+ }
+
+ /*
+ * Any subscriptions waiting ?
+ */
+ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
+ tipc_subscr_report_overlap(s,
+ publ->lower,
+ publ->upper,
+ TIPC_WITHDRAWN,
+ publ->ref,
+ publ->node,
+ removed_subseq);
+ }
+ return publ;
+}
+
+/**
+ * tipc_nameseq_subscribe: attach a subscription, and issue
+ * the prescribed number of events if there is any sub-
+ * sequence overlapping with the requested sequence
+ */
+
+void tipc_nameseq_subscribe(struct name_seq *nseq, struct subscription *s)
+{
+ struct sub_seq *sseq = nseq->sseqs;
+
+ list_add(&s->nameseq_list, &nseq->subscriptions);
+
+ if (!sseq)
+ return;
+
+ while (sseq != &nseq->sseqs[nseq->first_free]) {
+ struct publication *zl = sseq->zone_list;
+ if (zl && tipc_subscr_overlap(s,sseq->lower,sseq->upper)) {
+ struct publication *crs = zl;
+ int must_report = 1;
+
+ do {
+ tipc_subscr_report_overlap(s,
+ sseq->lower,
+ sseq->upper,
+ TIPC_PUBLISHED,
+ crs->ref,
+ crs->node,
+ must_report);
+ must_report = 0;
+ crs = crs->zone_list_next;
+ } while (crs != zl);
+ }
+ sseq++;
+ }
+}
+
+static struct name_seq *nametbl_find_seq(u32 type)
+{
+ struct hlist_head *seq_head;
+ struct hlist_node *seq_node;
+ struct name_seq *ns;
+
+ dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n",
+ type, ntohl(type), type, table.types, hash(type));
+
+ seq_head = &table.types[hash(type)];
+ hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
+ if (ns->type == type) {
+ dbg("found %x\n", ns);
+ return ns;
+ }
+ }
+
+ return 0;
+};
+
+struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
+ u32 scope, u32 node, u32 port, u32 key)
+{
+ struct name_seq *seq = nametbl_find_seq(type);
+
+ dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq);
+ if (lower > upper) {
+ warn("Failed to publish illegal <%u,%u,%u>\n",
+ type, lower, upper);
+ return 0;
+ }
+
+ dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
+ if (!seq) {
+ seq = tipc_nameseq_create(type, &table.types[hash(type)]);
+ dbg("tipc_nametbl_insert_publ: created %x\n", seq);
+ }
+ if (!seq)
+ return 0;
+
+ assert(seq->type == type);
+ return tipc_nameseq_insert_publ(seq, type, lower, upper,
+ scope, node, port, key);
+}
+
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
+ u32 node, u32 ref, u32 key)
+{
+ struct publication *publ;
+ struct name_seq *seq = nametbl_find_seq(type);
+
+ if (!seq)
+ return 0;
+
+ dbg("Withdrawing <%u,%u> from %x\n", type, lower, node);
+ publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
+
+ if (!seq->first_free && list_empty(&seq->subscriptions)) {
+ hlist_del_init(&seq->ns_list);
+ kfree(seq->sseqs);
+ kfree(seq);
+ }
+ return publ;
+}
+
+/*
+ * tipc_nametbl_translate(): Translate tipc_name -> tipc_portid.
+ * Very time-critical.
+ *
+ * Note: on entry 'destnode' is the search domain used during translation;
+ * on exit it passes back the node address of the matching port (if any)
+ */
+
+u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
+{
+ struct sub_seq *sseq;
+ struct publication *publ = 0;
+ struct name_seq *seq;
+ u32 ref;
+
+ if (!in_scope(*destnode, tipc_own_addr))
+ return 0;
+
+ read_lock_bh(&tipc_nametbl_lock);
+ seq = nametbl_find_seq(type);
+ if (unlikely(!seq))
+ goto not_found;
+ sseq = nameseq_find_subseq(seq, instance);
+ if (unlikely(!sseq))
+ goto not_found;
+ spin_lock_bh(&seq->lock);
+
+ /* Closest-First Algorithm: */
+ if (likely(!*destnode)) {
+ publ = sseq->node_list;
+ if (publ) {
+ sseq->node_list = publ->node_list_next;
+found:
+ ref = publ->ref;
+ *destnode = publ->node;
+ spin_unlock_bh(&seq->lock);
+ read_unlock_bh(&tipc_nametbl_lock);
+ return ref;
+ }
+ publ = sseq->cluster_list;
+ if (publ) {
+ sseq->cluster_list = publ->cluster_list_next;
+ goto found;
+ }
+ publ = sseq->zone_list;
+ if (publ) {
+ sseq->zone_list = publ->zone_list_next;
+ goto found;
+ }
+ }
+
+ /* Round-Robin Algorithm: */
+ else if (*destnode == tipc_own_addr) {
+ publ = sseq->node_list;
+ if (publ) {
+ sseq->node_list = publ->node_list_next;
+ goto found;
+ }
+ } else if (in_own_cluster(*destnode)) {
+ publ = sseq->cluster_list;
+ if (publ) {
+ sseq->cluster_list = publ->cluster_list_next;
+ goto found;
+ }
+ } else {
+ publ = sseq->zone_list;
+ if (publ) {
+ sseq->zone_list = publ->zone_list_next;
+ goto found;
+ }
+ }
+ spin_unlock_bh(&seq->lock);
+not_found:
+ *destnode = 0;
+ read_unlock_bh(&tipc_nametbl_lock);
+ return 0;
+}
+
+/**
+ * tipc_nametbl_mc_translate - find multicast destinations
+ *
+ * Creates list of all local ports that overlap the given multicast address;
+ * also determines if any off-node ports overlap.
+ *
+ * Note: Publications with a scope narrower than 'limit' are ignored.
+ * (i.e. local node-scope publications mustn't receive messages arriving
+ * from another node, even if the multcast link brought it here)
+ *
+ * Returns non-zero if any off-node ports overlap
+ */
+
+int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
+ struct port_list *dports)
+{
+ struct name_seq *seq;
+ struct sub_seq *sseq;
+ struct sub_seq *sseq_stop;
+ int res = 0;
+
+ read_lock_bh(&tipc_nametbl_lock);
+ seq = nametbl_find_seq(type);
+ if (!seq)
+ goto exit;
+
+ spin_lock_bh(&seq->lock);
+
+ sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
+ sseq_stop = seq->sseqs + seq->first_free;
+ for (; sseq != sseq_stop; sseq++) {
+ struct publication *publ;
+
+ if (sseq->lower > upper)
+ break;
+ publ = sseq->cluster_list;
+ if (publ && (publ->scope <= limit))
+ do {
+ if (publ->node == tipc_own_addr)
+ tipc_port_list_add(dports, publ->ref);
+ else
+ res = 1;
+ publ = publ->cluster_list_next;
+ } while (publ != sseq->cluster_list);
+ }
+
+ spin_unlock_bh(&seq->lock);
+exit:
+ read_unlock_bh(&tipc_nametbl_lock);
+ return res;
+}
+
+/**
+ * tipc_nametbl_publish_rsv - publish port name using a reserved name type
+ */
+
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
+ struct tipc_name_seq const *seq)
+{
+ int res;
+
+ atomic_inc(&rsv_publ_ok);
+ res = tipc_publish(ref, scope, seq);
+ atomic_dec(&rsv_publ_ok);
+ return res;
+}
+
+/**
+ * tipc_nametbl_publish - add name publication to network name tables
+ */
+
+struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
+ u32 scope, u32 port_ref, u32 key)
+{
+ struct publication *publ;
+
+ if (table.local_publ_count >= tipc_max_publications) {
+ warn("Failed publish: max %u local publication\n",
+ tipc_max_publications);
+ return 0;
+ }
+ if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
+ warn("Failed to publish reserved name <%u,%u,%u>\n",
+ type, lower, upper);
+ return 0;
+ }
+
+ write_lock_bh(&tipc_nametbl_lock);
+ table.local_publ_count++;
+ publ = tipc_nametbl_insert_publ(type, lower, upper, scope,
+ tipc_own_addr, port_ref, key);
+ if (publ && (scope != TIPC_NODE_SCOPE)) {
+ tipc_named_publish(publ);
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+ return publ;
+}
+
+/**
+ * tipc_nametbl_withdraw - withdraw name publication from network name tables
+ */
+
+int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
+{
+ struct publication *publ;
+
+ dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
+ write_lock_bh(&tipc_nametbl_lock);
+ publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
+ if (publ) {
+ table.local_publ_count--;
+ if (publ->scope != TIPC_NODE_SCOPE)
+ tipc_named_withdraw(publ);
+ write_unlock_bh(&tipc_nametbl_lock);
+ list_del_init(&publ->pport_list);
+ kfree(publ);
+ return 1;
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+ return 0;
+}
+
+/**
+ * tipc_nametbl_subscribe - add a subscription object to the name table
+ */
+
+void
+tipc_nametbl_subscribe(struct subscription *s)
+{
+ u32 type = s->seq.type;
+ struct name_seq *seq;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ seq = nametbl_find_seq(type);
+ if (!seq) {
+ seq = tipc_nameseq_create(type, &table.types[hash(type)]);
+ }
+ if (seq){
+ spin_lock_bh(&seq->lock);
+ dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n",
+ seq, type, s->seq.lower, s->seq.upper);
+ assert(seq->type == type);
+ tipc_nameseq_subscribe(seq, s);
+ spin_unlock_bh(&seq->lock);
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+}
+
+/**
+ * tipc_nametbl_unsubscribe - remove a subscription object from name table
+ */
+
+void
+tipc_nametbl_unsubscribe(struct subscription *s)
+{
+ struct name_seq *seq;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ seq = nametbl_find_seq(s->seq.type);
+ if (seq != NULL){
+ spin_lock_bh(&seq->lock);
+ list_del_init(&s->nameseq_list);
+ spin_unlock_bh(&seq->lock);
+ if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
+ hlist_del_init(&seq->ns_list);
+ kfree(seq->sseqs);
+ kfree(seq);
+ }
+ }
+ write_unlock_bh(&tipc_nametbl_lock);
+}
+
+
+/**
+ * subseq_list: print specified sub-sequence contents into the given buffer
+ */
+
+static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
+ u32 index)
+{
+ char portIdStr[27];
+ char *scopeStr;
+ struct publication *publ = sseq->zone_list;
+
+ tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
+
+ if (depth == 2 || !publ) {
+ tipc_printf(buf, "\n");
+ return;
+ }
+
+ do {
+ sprintf (portIdStr, "<%u.%u.%u:%u>",
+ tipc_zone(publ->node), tipc_cluster(publ->node),
+ tipc_node(publ->node), publ->ref);
+ tipc_printf(buf, "%-26s ", portIdStr);
+ if (depth > 3) {
+ if (publ->node != tipc_own_addr)
+ scopeStr = "";
+ else if (publ->scope == TIPC_NODE_SCOPE)
+ scopeStr = "node";
+ else if (publ->scope == TIPC_CLUSTER_SCOPE)
+ scopeStr = "cluster";
+ else
+ scopeStr = "zone";
+ tipc_printf(buf, "%-10u %s", publ->key, scopeStr);
+ }
+
+ publ = publ->zone_list_next;
+ if (publ == sseq->zone_list)
+ break;
+
+ tipc_printf(buf, "\n%33s", " ");
+ } while (1);
+
+ tipc_printf(buf, "\n");
+}
+
+/**
+ * nameseq_list: print specified name sequence contents into the given buffer
+ */
+
+static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth,
+ u32 type, u32 lowbound, u32 upbound, u32 index)
+{
+ struct sub_seq *sseq;
+ char typearea[11];
+
+ sprintf(typearea, "%-10u", seq->type);
+
+ if (depth == 1) {
+ tipc_printf(buf, "%s\n", typearea);
+ return;
+ }
+
+ for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
+ if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
+ tipc_printf(buf, "%s ", typearea);
+ subseq_list(sseq, buf, depth, index);
+ sprintf(typearea, "%10s", " ");
+ }
+ }
+}
+
+/**
+ * nametbl_header - print name table header into the given buffer
+ */
+
+static void nametbl_header(struct print_buf *buf, u32 depth)
+{
+ tipc_printf(buf, "Type ");
+
+ if (depth > 1)
+ tipc_printf(buf, "Lower Upper ");
+ if (depth > 2)
+ tipc_printf(buf, "Port Identity ");
+ if (depth > 3)
+ tipc_printf(buf, "Publication");
+
+ tipc_printf(buf, "\n-----------");
+
+ if (depth > 1)
+ tipc_printf(buf, "--------------------- ");
+ if (depth > 2)
+ tipc_printf(buf, "-------------------------- ");
+ if (depth > 3)
+ tipc_printf(buf, "------------------");
+
+ tipc_printf(buf, "\n");
+}
+
+/**
+ * nametbl_list - print specified name table contents into the given buffer
+ */
+
+static void nametbl_list(struct print_buf *buf, u32 depth_info,
+ u32 type, u32 lowbound, u32 upbound)
+{
+ struct hlist_head *seq_head;
+ struct hlist_node *seq_node;
+ struct name_seq *seq;
+ int all_types;
+ u32 depth;
+ u32 i;
+
+ all_types = (depth_info & TIPC_NTQ_ALLTYPES);
+ depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
+
+ if (depth == 0)
+ return;
+
+ if (all_types) {
+ /* display all entries in name table to specified depth */
+ nametbl_header(buf, depth);
+ lowbound = 0;
+ upbound = ~0;
+ for (i = 0; i < tipc_nametbl_size; i++) {
+ seq_head = &table.types[i];
+ hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
+ nameseq_list(seq, buf, depth, seq->type,
+ lowbound, upbound, i);
+ }
+ }
+ } else {
+ /* display only the sequence that matches the specified type */
+ if (upbound < lowbound) {
+ tipc_printf(buf, "invalid name sequence specified\n");
+ return;
+ }
+ nametbl_header(buf, depth);
+ i = hash(type);
+ seq_head = &table.types[i];
+ hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
+ if (seq->type == type) {
+ nameseq_list(seq, buf, depth, type,
+ lowbound, upbound, i);
+ break;
+ }
+ }
+ }
+}
+
+void tipc_nametbl_print(struct print_buf *buf, const char *str)
+{
+ tipc_printf(buf, str);
+ read_lock_bh(&tipc_nametbl_lock);
+ nametbl_list(buf, 0, 0, 0, 0);
+ read_unlock_bh(&tipc_nametbl_lock);
+}
+
+#define MAX_NAME_TBL_QUERY 32768
+
+struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
+{
+ struct sk_buff *buf;
+ struct tipc_name_table_query *argv;
+ struct tlv_desc *rep_tlv;
+ struct print_buf b;
+ int str_len;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
+ if (!buf)
+ return NULL;
+
+ rep_tlv = (struct tlv_desc *)buf->data;
+ tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
+ argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
+ read_lock_bh(&tipc_nametbl_lock);
+ nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type),
+ ntohl(argv->lowbound), ntohl(argv->upbound));
+ read_unlock_bh(&tipc_nametbl_lock);
+ str_len = tipc_printbuf_validate(&b);
+
+ skb_put(buf, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+
+ return buf;
+}
+
+void tipc_nametbl_dump(void)
+{
+ nametbl_list(TIPC_CONS, 0, 0, 0, 0);
+}
+
+int tipc_nametbl_init(void)
+{
+ int array_size = sizeof(struct hlist_head) * tipc_nametbl_size;
+
+ table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC);
+ if (!table.types)
+ return -ENOMEM;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ memset(table.types, 0, array_size);
+ table.local_publ_count = 0;
+ write_unlock_bh(&tipc_nametbl_lock);
+ return 0;
+}
+
+void tipc_nametbl_stop(void)
+{
+ struct hlist_head *seq_head;
+ struct hlist_node *seq_node;
+ struct hlist_node *tmp;
+ struct name_seq *seq;
+ u32 i;
+
+ if (!table.types)
+ return;
+
+ write_lock_bh(&tipc_nametbl_lock);
+ for (i = 0; i < tipc_nametbl_size; i++) {
+ seq_head = &table.types[i];
+ hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) {
+ struct sub_seq *sseq = seq->sseqs;
+
+ for (; sseq != &seq->sseqs[seq->first_free]; sseq++) {
+ struct publication *publ = sseq->zone_list;
+ assert(publ);
+ do {
+ struct publication *next =
+ publ->zone_list_next;
+ kfree(publ);
+ publ = next;
+ }
+ while (publ != sseq->zone_list);
+ }
+ }
+ }
+ kfree(table.types);
+ table.types = NULL;
+ write_unlock_bh(&tipc_nametbl_lock);
+}
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
new file mode 100644
index 000000000000..e8a3d71763ce
--- /dev/null
+++ b/net/tipc/name_table.h
@@ -0,0 +1,108 @@
+/*
+ * net/tipc/name_table.h: Include file for TIPC name table code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NAME_TABLE_H
+#define _TIPC_NAME_TABLE_H
+
+#include "node_subscr.h"
+
+struct subscription;
+struct port_list;
+
+/*
+ * TIPC name types reserved for internal TIPC use (both current and planned)
+ */
+
+#define TIPC_ZM_SRV 3 /* zone master service name type */
+
+
+/**
+ * struct publication - info about a published (name or) name sequence
+ * @type: name sequence type
+ * @lower: name sequence lower bound
+ * @upper: name sequence upper bound
+ * @scope: scope of publication
+ * @node: network address of publishing port's node
+ * @ref: publishing port
+ * @key: publication key
+ * @subscr: subscription to "node down" event (for off-node publications only)
+ * @local_list: adjacent entries in list of publications made by this node
+ * @pport_list: adjacent entries in list of publications made by this port
+ * @node_list: next matching name seq publication with >= node scope
+ * @cluster_list: next matching name seq publication with >= cluster scope
+ * @zone_list: next matching name seq publication with >= zone scope
+ *
+ * Note that the node list, cluster list, and zone list are circular lists.
+ */
+
+struct publication {
+ u32 type;
+ u32 lower;
+ u32 upper;
+ u32 scope;
+ u32 node;
+ u32 ref;
+ u32 key;
+ struct node_subscr subscr;
+ struct list_head local_list;
+ struct list_head pport_list;
+ struct publication *node_list_next;
+ struct publication *cluster_list_next;
+ struct publication *zone_list_next;
+};
+
+
+extern rwlock_t tipc_nametbl_lock;
+
+struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space);
+u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *node);
+int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
+ struct port_list *dports);
+int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
+ struct tipc_name_seq const *seq);
+struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
+ u32 scope, u32 port_ref, u32 key);
+int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
+struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
+ u32 scope, u32 node, u32 ref, u32 key);
+struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
+ u32 node, u32 ref, u32 key);
+void tipc_nametbl_subscribe(struct subscription *s);
+void tipc_nametbl_unsubscribe(struct subscription *s);
+int tipc_nametbl_init(void);
+void tipc_nametbl_stop(void);
+
+#endif
diff --git a/net/tipc/net.c b/net/tipc/net.c
new file mode 100644
index 000000000000..074891ad4f09
--- /dev/null
+++ b/net/tipc/net.c
@@ -0,0 +1,311 @@
+/*
+ * net/tipc/net.c: TIPC network routing code
+ *
+ * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "bearer.h"
+#include "net.h"
+#include "zone.h"
+#include "addr.h"
+#include "name_table.h"
+#include "name_distr.h"
+#include "subscr.h"
+#include "link.h"
+#include "msg.h"
+#include "port.h"
+#include "bcast.h"
+#include "discover.h"
+#include "config.h"
+
+/*
+ * The TIPC locking policy is designed to ensure a very fine locking
+ * granularity, permitting complete parallel access to individual
+ * port and node/link instances. The code consists of three major
+ * locking domains, each protected with their own disjunct set of locks.
+ *
+ * 1: The routing hierarchy.
+ * Comprises the structures 'zone', 'cluster', 'node', 'link'
+ * and 'bearer'. The whole hierarchy is protected by a big
+ * read/write lock, tipc_net_lock, to enssure that nothing is added
+ * or removed while code is accessing any of these structures.
+ * This layer must not be called from the two others while they
+ * hold any of their own locks.
+ * Neither must it itself do any upcalls to the other two before
+ * it has released tipc_net_lock and other protective locks.
+ *
+ * Within the tipc_net_lock domain there are two sub-domains;'node' and
+ * 'bearer', where local write operations are permitted,
+ * provided that those are protected by individual spin_locks
+ * per instance. Code holding tipc_net_lock(read) and a node spin_lock
+ * is permitted to poke around in both the node itself and its
+ * subordinate links. I.e, it can update link counters and queues,
+ * change link state, send protocol messages, and alter the
+ * "active_links" array in the node; but it can _not_ remove a link
+ * or a node from the overall structure.
+ * Correspondingly, individual bearers may change status within a
+ * tipc_net_lock(read), protected by an individual spin_lock ber bearer
+ * instance, but it needs tipc_net_lock(write) to remove/add any bearers.
+ *
+ *
+ * 2: The transport level of the protocol.
+ * This consists of the structures port, (and its user level
+ * representations, such as user_port and tipc_sock), reference and
+ * tipc_user (port.c, reg.c, socket.c).
+ *
+ * This layer has four different locks:
+ * - The tipc_port spin_lock. This is protecting each port instance
+ * from parallel data access and removal. Since we can not place
+ * this lock in the port itself, it has been placed in the
+ * corresponding reference table entry, which has the same life
+ * cycle as the module. This entry is difficult to access from
+ * outside the TIPC core, however, so a pointer to the lock has
+ * been added in the port instance, -to be used for unlocking
+ * only.
+ * - A read/write lock to protect the reference table itself (teg.c).
+ * (Nobody is using read-only access to this, so it can just as
+ * well be changed to a spin_lock)
+ * - A spin lock to protect the registry of kernel/driver users (reg.c)
+ * - A global spin_lock (tipc_port_lock), which only task is to ensure
+ * consistency where more than one port is involved in an operation,
+ * i.e., whe a port is part of a linked list of ports.
+ * There are two such lists; 'port_list', which is used for management,
+ * and 'wait_list', which is used to queue ports during congestion.
+ *
+ * 3: The name table (name_table.c, name_distr.c, subscription.c)
+ * - There is one big read/write-lock (tipc_nametbl_lock) protecting the
+ * overall name table structure. Nothing must be added/removed to
+ * this structure without holding write access to it.
+ * - There is one local spin_lock per sub_sequence, which can be seen
+ * as a sub-domain to the tipc_nametbl_lock domain. It is used only
+ * for translation operations, and is needed because a translation
+ * steps the root of the 'publication' linked list between each lookup.
+ * This is always used within the scope of a tipc_nametbl_lock(read).
+ * - A local spin_lock protecting the queue of subscriber events.
+*/
+
+rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED;
+struct network tipc_net = { 0 };
+
+struct node *tipc_net_select_remote_node(u32 addr, u32 ref)
+{
+ return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref);
+}
+
+u32 tipc_net_select_router(u32 addr, u32 ref)
+{
+ return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref);
+}
+
+
+u32 tipc_net_next_node(u32 a)
+{
+ if (tipc_net.zones[tipc_zone(a)])
+ return tipc_zone_next_node(a);
+ return 0;
+}
+
+void tipc_net_remove_as_router(u32 router)
+{
+ u32 z_num;
+
+ for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
+ if (!tipc_net.zones[z_num])
+ continue;
+ tipc_zone_remove_as_router(tipc_net.zones[z_num], router);
+ }
+}
+
+void tipc_net_send_external_routes(u32 dest)
+{
+ u32 z_num;
+
+ for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
+ if (tipc_net.zones[z_num])
+ tipc_zone_send_external_routes(tipc_net.zones[z_num], dest);
+ }
+}
+
+static int net_init(void)
+{
+ u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1);
+
+ memset(&tipc_net, 0, sizeof(tipc_net));
+ tipc_net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC);
+ if (!tipc_net.zones) {
+ return -ENOMEM;
+ }
+ memset(tipc_net.zones, 0, sz);
+ return TIPC_OK;
+}
+
+static void net_stop(void)
+{
+ u32 z_num;
+
+ if (!tipc_net.zones)
+ return;
+
+ for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
+ tipc_zone_delete(tipc_net.zones[z_num]);
+ }
+ kfree(tipc_net.zones);
+ tipc_net.zones = 0;
+}
+
+static void net_route_named_msg(struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 dnode;
+ u32 dport;
+
+ if (!msg_named(msg)) {
+ msg_dbg(msg, "tipc_net->drop_nam:");
+ buf_discard(buf);
+ return;
+ }
+
+ dnode = addr_domain(msg_lookup_scope(msg));
+ dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
+ dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n",
+ msg_nametype(msg), msg_nameinst(msg), dport, dnode);
+ if (dport) {
+ msg_set_destnode(msg, dnode);
+ msg_set_destport(msg, dport);
+ tipc_net_route_msg(buf);
+ return;
+ }
+ msg_dbg(msg, "tipc_net->rej:NO NAME: ");
+ tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
+}
+
+void tipc_net_route_msg(struct sk_buff *buf)
+{
+ struct tipc_msg *msg;
+ u32 dnode;
+
+ if (!buf)
+ return;
+ msg = buf_msg(buf);
+
+ msg_incr_reroute_cnt(msg);
+ if (msg_reroute_cnt(msg) > 6) {
+ if (msg_errcode(msg)) {
+ msg_dbg(msg, "NET>DISC>:");
+ buf_discard(buf);
+ } else {
+ msg_dbg(msg, "NET>REJ>:");
+ tipc_reject_msg(buf, msg_destport(msg) ?
+ TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
+ }
+ return;
+ }
+
+ msg_dbg(msg, "tipc_net->rout: ");
+
+ /* Handle message for this node */
+ dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
+ if (in_scope(dnode, tipc_own_addr)) {
+ if (msg_isdata(msg)) {
+ if (msg_mcast(msg))
+ tipc_port_recv_mcast(buf, NULL);
+ else if (msg_destport(msg))
+ tipc_port_recv_msg(buf);
+ else
+ net_route_named_msg(buf);
+ return;
+ }
+ switch (msg_user(msg)) {
+ case ROUTE_DISTRIBUTOR:
+ tipc_cltr_recv_routing_table(buf);
+ break;
+ case NAME_DISTRIBUTOR:
+ tipc_named_recv(buf);
+ break;
+ case CONN_MANAGER:
+ tipc_port_recv_proto_msg(buf);
+ break;
+ default:
+ msg_dbg(msg,"DROP/NET/<REC<");
+ buf_discard(buf);
+ }
+ return;
+ }
+
+ /* Handle message for another node */
+ msg_dbg(msg, "NET>SEND>: ");
+ tipc_link_send(buf, dnode, msg_link_selector(msg));
+}
+
+int tipc_net_start(void)
+{
+ char addr_string[16];
+ int res;
+
+ if (tipc_mode != TIPC_NODE_MODE)
+ return -ENOPROTOOPT;
+
+ tipc_mode = TIPC_NET_MODE;
+ tipc_named_reinit();
+ tipc_port_reinit();
+
+ if ((res = tipc_bearer_init()) ||
+ (res = net_init()) ||
+ (res = tipc_cltr_init()) ||
+ (res = tipc_bclink_init())) {
+ return res;
+ }
+ tipc_subscr_stop();
+ tipc_cfg_stop();
+ tipc_k_signal((Handler)tipc_subscr_start, 0);
+ tipc_k_signal((Handler)tipc_cfg_init, 0);
+ info("Started in network mode\n");
+ info("Own node address %s, network identity %u\n",
+ addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
+ return TIPC_OK;
+}
+
+void tipc_net_stop(void)
+{
+ if (tipc_mode != TIPC_NET_MODE)
+ return;
+ write_lock_bh(&tipc_net_lock);
+ tipc_bearer_stop();
+ tipc_mode = TIPC_NODE_MODE;
+ tipc_bclink_stop();
+ net_stop();
+ write_unlock_bh(&tipc_net_lock);
+ info("Left network mode \n");
+}
+
diff --git a/net/tipc/net.h b/net/tipc/net.h
new file mode 100644
index 000000000000..f3e0b85e6475
--- /dev/null
+++ b/net/tipc/net.h
@@ -0,0 +1,64 @@
+/*
+ * net/tipc/net.h: Include file for TIPC network routing code
+ *
+ * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NET_H
+#define _TIPC_NET_H
+
+struct _zone;
+
+/**
+ * struct network - TIPC network structure
+ * @zones: array of pointers to all zones within network
+ */
+
+struct network {
+ struct _zone **zones;
+};
+
+
+extern struct network tipc_net;
+extern rwlock_t tipc_net_lock;
+
+void tipc_net_remove_as_router(u32 router);
+void tipc_net_send_external_routes(u32 dest);
+void tipc_net_route_msg(struct sk_buff *buf);
+struct node *tipc_net_select_remote_node(u32 addr, u32 ref);
+u32 tipc_net_select_router(u32 addr, u32 ref);
+
+int tipc_net_start(void);
+void tipc_net_stop(void);
+
+#endif
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
new file mode 100644
index 000000000000..eb1bb4dce7af
--- /dev/null
+++ b/net/tipc/netlink.c
@@ -0,0 +1,112 @@
+/*
+ * net/tipc/netlink.c: TIPC configuration handling
+ *
+ * Copyright (c) 2005-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include <net/genetlink.h>
+
+static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sk_buff *rep_buf;
+ struct nlmsghdr *rep_nlh;
+ struct nlmsghdr *req_nlh = info->nlhdr;
+ struct tipc_genlmsghdr *req_userhdr = info->userhdr;
+ int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN);
+
+ if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN)))
+ rep_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN);
+ else
+ rep_buf = tipc_cfg_do_cmd(req_userhdr->dest,
+ req_userhdr->cmd,
+ NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN,
+ NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN),
+ hdr_space);
+
+ if (rep_buf) {
+ skb_push(rep_buf, hdr_space);
+ rep_nlh = (struct nlmsghdr *)rep_buf->data;
+ memcpy(rep_nlh, req_nlh, hdr_space);
+ rep_nlh->nlmsg_len = rep_buf->len;
+ genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
+ }
+
+ return 0;
+}
+
+static struct genl_family family = {
+ .id = GENL_ID_GENERATE,
+ .name = TIPC_GENL_NAME,
+ .version = TIPC_GENL_VERSION,
+ .hdrsize = TIPC_GENL_HDRLEN,
+ .maxattr = 0,
+};
+
+static struct genl_ops ops = {
+ .cmd = TIPC_GENL_CMD,
+ .doit = handle_cmd,
+};
+
+static int family_registered = 0;
+
+int tipc_netlink_start(void)
+{
+
+
+ if (genl_register_family(&family))
+ goto err;
+
+ family_registered = 1;
+
+ if (genl_register_ops(&family, &ops))
+ goto err_unregister;
+
+ return 0;
+
+ err_unregister:
+ genl_unregister_family(&family);
+ family_registered = 0;
+ err:
+ err("Failed to register netlink interface\n");
+ return -EFAULT;
+}
+
+void tipc_netlink_stop(void)
+{
+ if (family_registered) {
+ genl_unregister_family(&family);
+ family_registered = 0;
+ }
+}
diff --git a/net/tipc/node.c b/net/tipc/node.c
new file mode 100644
index 000000000000..6d65010e5fa1
--- /dev/null
+++ b/net/tipc/node.c
@@ -0,0 +1,678 @@
+/*
+ * net/tipc/node.c: TIPC node management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include "node.h"
+#include "cluster.h"
+#include "net.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "link.h"
+#include "port.h"
+#include "bearer.h"
+#include "name_distr.h"
+
+void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
+static void node_lost_contact(struct node *n_ptr);
+static void node_established_contact(struct node *n_ptr);
+
+struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */
+
+u32 tipc_own_tag = 0;
+
+struct node *tipc_node_create(u32 addr)
+{
+ struct cluster *c_ptr;
+ struct node *n_ptr;
+ struct node **curr_node;
+
+ n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
+ if (n_ptr != NULL) {
+ memset(n_ptr, 0, sizeof(*n_ptr));
+ n_ptr->addr = addr;
+ n_ptr->lock = SPIN_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&n_ptr->nsub);
+
+ c_ptr = tipc_cltr_find(addr);
+ if (c_ptr == NULL)
+ c_ptr = tipc_cltr_create(addr);
+ if (c_ptr != NULL) {
+ n_ptr->owner = c_ptr;
+ tipc_cltr_attach_node(c_ptr, n_ptr);
+ n_ptr->last_router = -1;
+
+ /* Insert node into ordered list */
+ for (curr_node = &tipc_nodes; *curr_node;
+ curr_node = &(*curr_node)->next) {
+ if (addr < (*curr_node)->addr) {
+ n_ptr->next = *curr_node;
+ break;
+ }
+ }
+ (*curr_node) = n_ptr;
+ } else {
+ kfree(n_ptr);
+ n_ptr = NULL;
+ }
+ }
+ return n_ptr;
+}
+
+void tipc_node_delete(struct node *n_ptr)
+{
+ if (!n_ptr)
+ return;
+
+#if 0
+ /* Not needed because links are already deleted via tipc_bearer_stop() */
+
+ u32 l_num;
+
+ for (l_num = 0; l_num < MAX_BEARERS; l_num++) {
+ link_delete(n_ptr->links[l_num]);
+ }
+#endif
+
+ dbg("node %x deleted\n", n_ptr->addr);
+ kfree(n_ptr);
+}
+
+
+/**
+ * tipc_node_link_up - handle addition of link
+ *
+ * Link becomes active (alone or shared) or standby, depending on its priority.
+ */
+
+void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr)
+{
+ struct link **active = &n_ptr->active_links[0];
+
+ info("Established link <%s> on network plane %c\n",
+ l_ptr->name, l_ptr->b_ptr->net_plane);
+
+ if (!active[0]) {
+ dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]);
+ active[0] = active[1] = l_ptr;
+ node_established_contact(n_ptr);
+ return;
+ }
+ if (l_ptr->priority < active[0]->priority) {
+ info("Link is standby\n");
+ return;
+ }
+ tipc_link_send_duplicate(active[0], l_ptr);
+ if (l_ptr->priority == active[0]->priority) {
+ active[0] = l_ptr;
+ return;
+ }
+ info("Link <%s> on network plane %c becomes standby\n",
+ active[0]->name, active[0]->b_ptr->net_plane);
+ active[0] = active[1] = l_ptr;
+}
+
+/**
+ * node_select_active_links - select active link
+ */
+
+static void node_select_active_links(struct node *n_ptr)
+{
+ struct link **active = &n_ptr->active_links[0];
+ u32 i;
+ u32 highest_prio = 0;
+
+ active[0] = active[1] = 0;
+
+ for (i = 0; i < MAX_BEARERS; i++) {
+ struct link *l_ptr = n_ptr->links[i];
+
+ if (!l_ptr || !tipc_link_is_up(l_ptr) ||
+ (l_ptr->priority < highest_prio))
+ continue;
+
+ if (l_ptr->priority > highest_prio) {
+ highest_prio = l_ptr->priority;
+ active[0] = active[1] = l_ptr;
+ } else {
+ active[1] = l_ptr;
+ }
+ }
+}
+
+/**
+ * tipc_node_link_down - handle loss of link
+ */
+
+void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr)
+{
+ struct link **active;
+
+ if (!tipc_link_is_active(l_ptr)) {
+ info("Lost standby link <%s> on network plane %c\n",
+ l_ptr->name, l_ptr->b_ptr->net_plane);
+ return;
+ }
+ info("Lost link <%s> on network plane %c\n",
+ l_ptr->name, l_ptr->b_ptr->net_plane);
+
+ active = &n_ptr->active_links[0];
+ if (active[0] == l_ptr)
+ active[0] = active[1];
+ if (active[1] == l_ptr)
+ active[1] = active[0];
+ if (active[0] == l_ptr)
+ node_select_active_links(n_ptr);
+ if (tipc_node_is_up(n_ptr))
+ tipc_link_changeover(l_ptr);
+ else
+ node_lost_contact(n_ptr);
+}
+
+int tipc_node_has_active_links(struct node *n_ptr)
+{
+ return (n_ptr &&
+ ((n_ptr->active_links[0]) || (n_ptr->active_links[1])));
+}
+
+int tipc_node_has_redundant_links(struct node *n_ptr)
+{
+ return (tipc_node_has_active_links(n_ptr) &&
+ (n_ptr->active_links[0] != n_ptr->active_links[1]));
+}
+
+int tipc_node_has_active_routes(struct node *n_ptr)
+{
+ return (n_ptr && (n_ptr->last_router >= 0));
+}
+
+int tipc_node_is_up(struct node *n_ptr)
+{
+ return (tipc_node_has_active_links(n_ptr) || tipc_node_has_active_routes(n_ptr));
+}
+
+struct node *tipc_node_attach_link(struct link *l_ptr)
+{
+ struct node *n_ptr = tipc_node_find(l_ptr->addr);
+
+ if (!n_ptr)
+ n_ptr = tipc_node_create(l_ptr->addr);
+ if (n_ptr) {
+ u32 bearer_id = l_ptr->b_ptr->identity;
+ char addr_string[16];
+
+ assert(bearer_id < MAX_BEARERS);
+ if (n_ptr->link_cnt >= 2) {
+ char addr_string[16];
+
+ err("Attempt to create third link to %s\n",
+ addr_string_fill(addr_string, n_ptr->addr));
+ return 0;
+ }
+
+ if (!n_ptr->links[bearer_id]) {
+ n_ptr->links[bearer_id] = l_ptr;
+ tipc_net.zones[tipc_zone(l_ptr->addr)]->links++;
+ n_ptr->link_cnt++;
+ return n_ptr;
+ }
+ err("Attempt to establish second link on <%s> to <%s> \n",
+ l_ptr->b_ptr->publ.name,
+ addr_string_fill(addr_string, l_ptr->addr));
+ }
+ return 0;
+}
+
+void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr)
+{
+ n_ptr->links[l_ptr->b_ptr->identity] = 0;
+ tipc_net.zones[tipc_zone(l_ptr->addr)]->links--;
+ n_ptr->link_cnt--;
+}
+
+/*
+ * Routing table management - five cases to handle:
+ *
+ * 1: A link towards a zone/cluster external node comes up.
+ * => Send a multicast message updating routing tables of all
+ * system nodes within own cluster that the new destination
+ * can be reached via this node.
+ * (node.establishedContact()=>cluster.multicastNewRoute())
+ *
+ * 2: A link towards a slave node comes up.
+ * => Send a multicast message updating routing tables of all
+ * system nodes within own cluster that the new destination
+ * can be reached via this node.
+ * (node.establishedContact()=>cluster.multicastNewRoute())
+ * => Send a message to the slave node about existence
+ * of all system nodes within cluster:
+ * (node.establishedContact()=>cluster.sendLocalRoutes())
+ *
+ * 3: A new cluster local system node becomes available.
+ * => Send message(s) to this particular node containing
+ * information about all cluster external and slave
+ * nodes which can be reached via this node.
+ * (node.establishedContact()==>network.sendExternalRoutes())
+ * (node.establishedContact()==>network.sendSlaveRoutes())
+ * => Send messages to all directly connected slave nodes
+ * containing information about the existence of the new node
+ * (node.establishedContact()=>cluster.multicastNewRoute())
+ *
+ * 4: The link towards a zone/cluster external node or slave
+ * node goes down.
+ * => Send a multcast message updating routing tables of all
+ * nodes within cluster that the new destination can not any
+ * longer be reached via this node.
+ * (node.lostAllLinks()=>cluster.bcastLostRoute())
+ *
+ * 5: A cluster local system node becomes unavailable.
+ * => Remove all references to this node from the local
+ * routing tables. Note: This is a completely node
+ * local operation.
+ * (node.lostAllLinks()=>network.removeAsRouter())
+ * => Send messages to all directly connected slave nodes
+ * containing information about loss of the node
+ * (node.establishedContact()=>cluster.multicastLostRoute())
+ *
+ */
+
+static void node_established_contact(struct node *n_ptr)
+{
+ struct cluster *c_ptr;
+
+ dbg("node_established_contact:-> %x\n", n_ptr->addr);
+ if (!tipc_node_has_active_routes(n_ptr)) {
+ tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
+ }
+
+ /* Syncronize broadcast acks */
+ n_ptr->bclink.acked = tipc_bclink_get_last_sent();
+
+ if (is_slave(tipc_own_addr))
+ return;
+ if (!in_own_cluster(n_ptr->addr)) {
+ /* Usage case 1 (see above) */
+ c_ptr = tipc_cltr_find(tipc_own_addr);
+ if (!c_ptr)
+ c_ptr = tipc_cltr_create(tipc_own_addr);
+ if (c_ptr)
+ tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1,
+ tipc_max_nodes);
+ return;
+ }
+
+ c_ptr = n_ptr->owner;
+ if (is_slave(n_ptr->addr)) {
+ /* Usage case 2 (see above) */
+ tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes);
+ tipc_cltr_send_local_routes(c_ptr, n_ptr->addr);
+ return;
+ }
+
+ if (n_ptr->bclink.supported) {
+ tipc_nmap_add(&tipc_cltr_bcast_nodes, n_ptr->addr);
+ if (n_ptr->addr < tipc_own_addr)
+ tipc_own_tag++;
+ }
+
+ /* Case 3 (see above) */
+ tipc_net_send_external_routes(n_ptr->addr);
+ tipc_cltr_send_slave_routes(c_ptr, n_ptr->addr);
+ tipc_cltr_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE,
+ tipc_highest_allowed_slave);
+}
+
+static void node_lost_contact(struct node *n_ptr)
+{
+ struct cluster *c_ptr;
+ struct node_subscr *ns, *tns;
+ char addr_string[16];
+ u32 i;
+
+ /* Clean up broadcast reception remains */
+ n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0;
+ while (n_ptr->bclink.deferred_head) {
+ struct sk_buff* buf = n_ptr->bclink.deferred_head;
+ n_ptr->bclink.deferred_head = buf->next;
+ buf_discard(buf);
+ }
+ if (n_ptr->bclink.defragm) {
+ buf_discard(n_ptr->bclink.defragm);
+ n_ptr->bclink.defragm = NULL;
+ }
+ if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) {
+ tipc_bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000));
+ }
+
+ /* Update routing tables */
+ if (is_slave(tipc_own_addr)) {
+ tipc_net_remove_as_router(n_ptr->addr);
+ } else {
+ if (!in_own_cluster(n_ptr->addr)) {
+ /* Case 4 (see above) */
+ c_ptr = tipc_cltr_find(tipc_own_addr);
+ tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
+ tipc_max_nodes);
+ } else {
+ /* Case 5 (see above) */
+ c_ptr = tipc_cltr_find(n_ptr->addr);
+ if (is_slave(n_ptr->addr)) {
+ tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr, 1,
+ tipc_max_nodes);
+ } else {
+ if (n_ptr->bclink.supported) {
+ tipc_nmap_remove(&tipc_cltr_bcast_nodes,
+ n_ptr->addr);
+ if (n_ptr->addr < tipc_own_addr)
+ tipc_own_tag--;
+ }
+ tipc_net_remove_as_router(n_ptr->addr);
+ tipc_cltr_bcast_lost_route(c_ptr, n_ptr->addr,
+ LOWEST_SLAVE,
+ tipc_highest_allowed_slave);
+ }
+ }
+ }
+ if (tipc_node_has_active_routes(n_ptr))
+ return;
+
+ info("Lost contact with %s\n",
+ addr_string_fill(addr_string, n_ptr->addr));
+
+ /* Abort link changeover */
+ for (i = 0; i < MAX_BEARERS; i++) {
+ struct link *l_ptr = n_ptr->links[i];
+ if (!l_ptr)
+ continue;
+ l_ptr->reset_checkpoint = l_ptr->next_in_no;
+ l_ptr->exp_msg_count = 0;
+ tipc_link_reset_fragments(l_ptr);
+ }
+
+ /* Notify subscribers */
+ list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
+ ns->node = 0;
+ list_del_init(&ns->nodesub_list);
+ tipc_k_signal((Handler)ns->handle_node_down,
+ (unsigned long)ns->usr_handle);
+ }
+}
+
+/**
+ * tipc_node_select_next_hop - find the next-hop node for a message
+ *
+ * Called by when cluster local lookup has failed.
+ */
+
+struct node *tipc_node_select_next_hop(u32 addr, u32 selector)
+{
+ struct node *n_ptr;
+ u32 router_addr;
+
+ if (!tipc_addr_domain_valid(addr))
+ return 0;
+
+ /* Look for direct link to destination processsor */
+ n_ptr = tipc_node_find(addr);
+ if (n_ptr && tipc_node_has_active_links(n_ptr))
+ return n_ptr;
+
+ /* Cluster local system nodes *must* have direct links */
+ if (!is_slave(addr) && in_own_cluster(addr))
+ return 0;
+
+ /* Look for cluster local router with direct link to node */
+ router_addr = tipc_node_select_router(n_ptr, selector);
+ if (router_addr)
+ return tipc_node_select(router_addr, selector);
+
+ /* Slave nodes can only be accessed within own cluster via a
+ known router with direct link -- if no router was found,give up */
+ if (is_slave(addr))
+ return 0;
+
+ /* Inter zone/cluster -- find any direct link to remote cluster */
+ addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
+ n_ptr = tipc_net_select_remote_node(addr, selector);
+ if (n_ptr && tipc_node_has_active_links(n_ptr))
+ return n_ptr;
+
+ /* Last resort -- look for any router to anywhere in remote zone */
+ router_addr = tipc_net_select_router(addr, selector);
+ if (router_addr)
+ return tipc_node_select(router_addr, selector);
+
+ return 0;
+}
+
+/**
+ * tipc_node_select_router - select router to reach specified node
+ *
+ * Uses a deterministic and fair algorithm for selecting router node.
+ */
+
+u32 tipc_node_select_router(struct node *n_ptr, u32 ref)
+{
+ u32 ulim;
+ u32 mask;
+ u32 start;
+ u32 r;
+
+ if (!n_ptr)
+ return 0;
+
+ if (n_ptr->last_router < 0)
+ return 0;
+ ulim = ((n_ptr->last_router + 1) * 32) - 1;
+
+ /* Start entry must be random */
+ mask = tipc_max_nodes;
+ while (mask > ulim)
+ mask >>= 1;
+ start = ref & mask;
+ r = start;
+
+ /* Lookup upwards with wrap-around */
+ do {
+ if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
+ break;
+ } while (++r <= ulim);
+ if (r > ulim) {
+ r = 1;
+ do {
+ if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1)
+ break;
+ } while (++r < start);
+ assert(r != start);
+ }
+ assert(r && (r <= ulim));
+ return tipc_addr(own_zone(), own_cluster(), r);
+}
+
+void tipc_node_add_router(struct node *n_ptr, u32 router)
+{
+ u32 r_num = tipc_node(router);
+
+ n_ptr->routers[r_num / 32] =
+ ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]);
+ n_ptr->last_router = tipc_max_nodes / 32;
+ while ((--n_ptr->last_router >= 0) &&
+ !n_ptr->routers[n_ptr->last_router]);
+}
+
+void tipc_node_remove_router(struct node *n_ptr, u32 router)
+{
+ u32 r_num = tipc_node(router);
+
+ if (n_ptr->last_router < 0)
+ return; /* No routes */
+
+ n_ptr->routers[r_num / 32] =
+ ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32]));
+ n_ptr->last_router = tipc_max_nodes / 32;
+ while ((--n_ptr->last_router >= 0) &&
+ !n_ptr->routers[n_ptr->last_router]);
+
+ if (!tipc_node_is_up(n_ptr))
+ node_lost_contact(n_ptr);
+}
+
+#if 0
+void node_print(struct print_buf *buf, struct node *n_ptr, char *str)
+{
+ u32 i;
+
+ tipc_printf(buf, "\n\n%s", str);
+ for (i = 0; i < MAX_BEARERS; i++) {
+ if (!n_ptr->links[i])
+ continue;
+ tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]);
+ }
+ tipc_printf(buf, "Active links: [%x,%x]\n",
+ n_ptr->active_links[0], n_ptr->active_links[1]);
+}
+#endif
+
+u32 tipc_available_nodes(const u32 domain)
+{
+ struct node *n_ptr;
+ u32 cnt = 0;
+
+ for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
+ if (!in_scope(domain, n_ptr->addr))
+ continue;
+ if (tipc_node_is_up(n_ptr))
+ cnt++;
+ }
+ return cnt;
+}
+
+struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
+{
+ u32 domain;
+ struct sk_buff *buf;
+ struct node *n_ptr;
+ struct tipc_node_info node_info;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ domain = *(u32 *)TLV_DATA(req_tlv_area);
+ domain = ntohl(domain);
+ if (!tipc_addr_domain_valid(domain))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (network address)");
+
+ if (!tipc_nodes)
+ return tipc_cfg_reply_none();
+
+ /* For now, get space for all other nodes
+ (will need to modify this when slave nodes are supported */
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) *
+ (tipc_max_nodes - 1));
+ if (!buf)
+ return NULL;
+
+ /* Add TLVs for all nodes in scope */
+
+ for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
+ if (!in_scope(domain, n_ptr->addr))
+ continue;
+ node_info.addr = htonl(n_ptr->addr);
+ node_info.up = htonl(tipc_node_is_up(n_ptr));
+ tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO,
+ &node_info, sizeof(node_info));
+ }
+
+ return buf;
+}
+
+struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
+{
+ u32 domain;
+ struct sk_buff *buf;
+ struct node *n_ptr;
+ struct tipc_link_info link_info;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
+ return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ domain = *(u32 *)TLV_DATA(req_tlv_area);
+ domain = ntohl(domain);
+ if (!tipc_addr_domain_valid(domain))
+ return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
+ " (network address)");
+
+ if (!tipc_nodes)
+ return tipc_cfg_reply_none();
+
+ /* For now, get space for 2 links to all other nodes + bcast link
+ (will need to modify this when slave nodes are supported */
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) *
+ (2 * (tipc_max_nodes - 1) + 1));
+ if (!buf)
+ return NULL;
+
+ /* Add TLV for broadcast link */
+
+ link_info.dest = tipc_own_addr & 0xfffff00;
+ link_info.dest = htonl(link_info.dest);
+ link_info.up = htonl(1);
+ sprintf(link_info.str, tipc_bclink_name);
+ tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
+
+ /* Add TLVs for any other links in scope */
+
+ for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
+ u32 i;
+
+ if (!in_scope(domain, n_ptr->addr))
+ continue;
+ for (i = 0; i < MAX_BEARERS; i++) {
+ if (!n_ptr->links[i])
+ continue;
+ link_info.dest = htonl(n_ptr->addr);
+ link_info.up = htonl(tipc_link_is_up(n_ptr->links[i]));
+ strcpy(link_info.str, n_ptr->links[i]->name);
+ tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO,
+ &link_info, sizeof(link_info));
+ }
+ }
+
+ return buf;
+}
diff --git a/net/tipc/node.h b/net/tipc/node.h
new file mode 100644
index 000000000000..29f7ae6992d4
--- /dev/null
+++ b/net/tipc/node.h
@@ -0,0 +1,144 @@
+/*
+ * net/tipc/node.h: Include file for TIPC node management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NODE_H
+#define _TIPC_NODE_H
+
+#include "node_subscr.h"
+#include "addr.h"
+#include "cluster.h"
+#include "bearer.h"
+
+/**
+ * struct node - TIPC node structure
+ * @addr: network address of node
+ * @lock: spinlock governing access to structure
+ * @owner: pointer to cluster that node belongs to
+ * @next: pointer to next node in sorted list of cluster's nodes
+ * @nsub: list of "node down" subscriptions monitoring node
+ * @active_links: pointers to active links to node
+ * @links: pointers to all links to node
+ * @link_cnt: number of links to node
+ * @permit_changeover: non-zero if node has redundant links to this system
+ * @routers: bitmap (used for multicluster communication)
+ * @last_router: (used for multicluster communication)
+ * @bclink: broadcast-related info
+ * @supported: non-zero if node supports TIPC b'cast capability
+ * @acked: sequence # of last outbound b'cast message acknowledged by node
+ * @last_in: sequence # of last in-sequence b'cast message received from node
+ * @gap_after: sequence # of last message not requiring a NAK request
+ * @gap_to: sequence # of last message requiring a NAK request
+ * @nack_sync: counter that determines when NAK requests should be sent
+ * @deferred_head: oldest OOS b'cast message received from node
+ * @deferred_tail: newest OOS b'cast message received from node
+ * @defragm: list of partially reassembled b'cast message fragments from node
+ */
+
+struct node {
+ u32 addr;
+ spinlock_t lock;
+ struct cluster *owner;
+ struct node *next;
+ struct list_head nsub;
+ struct link *active_links[2];
+ struct link *links[MAX_BEARERS];
+ int link_cnt;
+ int permit_changeover;
+ u32 routers[512/32];
+ int last_router;
+ struct {
+ int supported;
+ u32 acked;
+ u32 last_in;
+ u32 gap_after;
+ u32 gap_to;
+ u32 nack_sync;
+ struct sk_buff *deferred_head;
+ struct sk_buff *deferred_tail;
+ struct sk_buff *defragm;
+ } bclink;
+};
+
+extern struct node *tipc_nodes;
+extern u32 tipc_own_tag;
+
+struct node *tipc_node_create(u32 addr);
+void tipc_node_delete(struct node *n_ptr);
+struct node *tipc_node_attach_link(struct link *l_ptr);
+void tipc_node_detach_link(struct node *n_ptr, struct link *l_ptr);
+void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr);
+void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr);
+int tipc_node_has_active_links(struct node *n_ptr);
+int tipc_node_has_redundant_links(struct node *n_ptr);
+u32 tipc_node_select_router(struct node *n_ptr, u32 ref);
+struct node *tipc_node_select_next_hop(u32 addr, u32 selector);
+int tipc_node_is_up(struct node *n_ptr);
+void tipc_node_add_router(struct node *n_ptr, u32 router);
+void tipc_node_remove_router(struct node *n_ptr, u32 router);
+struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
+struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
+
+static inline struct node *tipc_node_find(u32 addr)
+{
+ if (likely(in_own_cluster(addr)))
+ return tipc_local_nodes[tipc_node(addr)];
+ else if (tipc_addr_domain_valid(addr)) {
+ struct cluster *c_ptr = tipc_cltr_find(addr);
+
+ if (c_ptr)
+ return c_ptr->nodes[tipc_node(addr)];
+ }
+ return 0;
+}
+
+static inline struct node *tipc_node_select(u32 addr, u32 selector)
+{
+ if (likely(in_own_cluster(addr)))
+ return tipc_local_nodes[tipc_node(addr)];
+ return tipc_node_select_next_hop(addr, selector);
+}
+
+static inline void tipc_node_lock(struct node *n_ptr)
+{
+ spin_lock_bh(&n_ptr->lock);
+}
+
+static inline void tipc_node_unlock(struct node *n_ptr)
+{
+ spin_unlock_bh(&n_ptr->lock);
+}
+
+#endif
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
new file mode 100644
index 000000000000..afeea121d8be
--- /dev/null
+++ b/net/tipc/node_subscr.c
@@ -0,0 +1,79 @@
+/*
+ * net/tipc/node_subscr.c: TIPC "node down" subscription handling
+ *
+ * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "node_subscr.h"
+#include "node.h"
+#include "addr.h"
+
+/**
+ * tipc_nodesub_subscribe - create "node down" subscription for specified node
+ */
+
+void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
+ void *usr_handle, net_ev_handler handle_down)
+{
+ node_sub->node = 0;
+ if (addr == tipc_own_addr)
+ return;
+ if (!tipc_addr_node_valid(addr)) {
+ warn("node_subscr with illegal %x\n", addr);
+ return;
+ }
+
+ node_sub->handle_node_down = handle_down;
+ node_sub->usr_handle = usr_handle;
+ node_sub->node = tipc_node_find(addr);
+ assert(node_sub->node);
+ tipc_node_lock(node_sub->node);
+ list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
+ tipc_node_unlock(node_sub->node);
+}
+
+/**
+ * tipc_nodesub_unsubscribe - cancel "node down" subscription (if any)
+ */
+
+void tipc_nodesub_unsubscribe(struct node_subscr *node_sub)
+{
+ if (!node_sub->node)
+ return;
+
+ tipc_node_lock(node_sub->node);
+ list_del_init(&node_sub->nodesub_list);
+ tipc_node_unlock(node_sub->node);
+}
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
new file mode 100644
index 000000000000..01751c4fbb43
--- /dev/null
+++ b/net/tipc/node_subscr.h
@@ -0,0 +1,63 @@
+/*
+ * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
+ *
+ * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_NODE_SUBSCR_H
+#define _TIPC_NODE_SUBSCR_H
+
+#include "addr.h"
+
+typedef void (*net_ev_handler) (void *usr_handle);
+
+/**
+ * struct node_subscr - "node down" subscription entry
+ * @node: ptr to node structure of interest (or NULL, if none)
+ * @handle_node_down: routine to invoke when node fails
+ * @usr_handle: argument to pass to routine when node fails
+ * @nodesub_list: adjacent entries in list of subscriptions for the node
+ */
+
+struct node_subscr {
+ struct node *node;
+ net_ev_handler handle_node_down;
+ void *usr_handle;
+ struct list_head nodesub_list;
+};
+
+void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
+ void *usr_handle, net_ev_handler handle_down);
+void tipc_nodesub_unsubscribe(struct node_subscr *node_sub);
+
+#endif
diff --git a/net/tipc/port.c b/net/tipc/port.c
new file mode 100644
index 000000000000..72aae52bfec1
--- /dev/null
+++ b/net/tipc/port.c
@@ -0,0 +1,1708 @@
+/*
+ * net/tipc/port.c: TIPC port code
+ *
+ * Copyright (c) 1992-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "config.h"
+#include "dbg.h"
+#include "port.h"
+#include "addr.h"
+#include "link.h"
+#include "node.h"
+#include "port.h"
+#include "name_table.h"
+#include "user_reg.h"
+#include "msg.h"
+#include "bcast.h"
+
+/* Connection management: */
+#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */
+#define CONFIRMED 0
+#define PROBING 1
+
+#define MAX_REJECT_SIZE 1024
+
+static struct sk_buff *msg_queue_head = 0;
+static struct sk_buff *msg_queue_tail = 0;
+
+spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
+
+static LIST_HEAD(ports);
+static void port_handle_node_down(unsigned long ref);
+static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err);
+static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err);
+static void port_timeout(unsigned long ref);
+
+
+static inline u32 port_peernode(struct port *p_ptr)
+{
+ return msg_destnode(&p_ptr->publ.phdr);
+}
+
+static inline u32 port_peerport(struct port *p_ptr)
+{
+ return msg_destport(&p_ptr->publ.phdr);
+}
+
+static inline u32 port_out_seqno(struct port *p_ptr)
+{
+ return msg_transp_seqno(&p_ptr->publ.phdr);
+}
+
+static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno)
+{
+ msg_set_transp_seqno(&p_ptr->publ.phdr,seqno);
+}
+
+static inline void port_incr_out_seqno(struct port *p_ptr)
+{
+ struct tipc_msg *m = &p_ptr->publ.phdr;
+
+ if (likely(!msg_routed(m)))
+ return;
+ msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1));
+}
+
+/**
+ * tipc_multicast - send a multicast message to local and remote destinations
+ */
+
+int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain,
+ u32 num_sect, struct iovec const *msg_sect)
+{
+ struct tipc_msg *hdr;
+ struct sk_buff *buf;
+ struct sk_buff *ibuf = NULL;
+ struct port_list dports = {0, NULL, };
+ struct port *oport = tipc_port_deref(ref);
+ int ext_targets;
+ int res;
+
+ if (unlikely(!oport))
+ return -EINVAL;
+
+ /* Create multicast message */
+
+ hdr = &oport->publ.phdr;
+ msg_set_type(hdr, TIPC_MCAST_MSG);
+ msg_set_nametype(hdr, seq->type);
+ msg_set_namelower(hdr, seq->lower);
+ msg_set_nameupper(hdr, seq->upper);
+ msg_set_hdr_sz(hdr, MCAST_H_SIZE);
+ res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
+ !oport->user_port, &buf);
+ if (unlikely(!buf))
+ return res;
+
+ /* Figure out where to send multicast message */
+
+ ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper,
+ TIPC_NODE_SCOPE, &dports);
+
+ /* Send message to destinations (duplicate it only if necessary) */
+
+ if (ext_targets) {
+ if (dports.count != 0) {
+ ibuf = skb_copy(buf, GFP_ATOMIC);
+ if (ibuf == NULL) {
+ tipc_port_list_free(&dports);
+ buf_discard(buf);
+ return -ENOMEM;
+ }
+ }
+ res = tipc_bclink_send_msg(buf);
+ if ((res < 0) && (dports.count != 0)) {
+ buf_discard(ibuf);
+ }
+ } else {
+ ibuf = buf;
+ }
+
+ if (res >= 0) {
+ if (ibuf)
+ tipc_port_recv_mcast(ibuf, &dports);
+ } else {
+ tipc_port_list_free(&dports);
+ }
+ return res;
+}
+
+/**
+ * tipc_port_recv_mcast - deliver multicast message to all destination ports
+ *
+ * If there is no port list, perform a lookup to create one
+ */
+
+void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
+{
+ struct tipc_msg* msg;
+ struct port_list dports = {0, NULL, };
+ struct port_list *item = dp;
+ int cnt = 0;
+
+ assert(buf);
+ msg = buf_msg(buf);
+
+ /* Create destination port list, if one wasn't supplied */
+
+ if (dp == NULL) {
+ tipc_nametbl_mc_translate(msg_nametype(msg),
+ msg_namelower(msg),
+ msg_nameupper(msg),
+ TIPC_CLUSTER_SCOPE,
+ &dports);
+ item = dp = &dports;
+ }
+
+ /* Deliver a copy of message to each destination port */
+
+ if (dp->count != 0) {
+ if (dp->count == 1) {
+ msg_set_destport(msg, dp->ports[0]);
+ tipc_port_recv_msg(buf);
+ tipc_port_list_free(dp);
+ return;
+ }
+ for (; cnt < dp->count; cnt++) {
+ int index = cnt % PLSIZE;
+ struct sk_buff *b = skb_clone(buf, GFP_ATOMIC);
+
+ if (b == NULL) {
+ warn("Buffer allocation failure\n");
+ msg_dbg(msg, "LOST:");
+ goto exit;
+ }
+ if ((index == 0) && (cnt != 0)) {
+ item = item->next;
+ }
+ msg_set_destport(buf_msg(b),item->ports[index]);
+ tipc_port_recv_msg(b);
+ }
+ }
+exit:
+ buf_discard(buf);
+ tipc_port_list_free(dp);
+}
+
+/**
+ * tipc_createport_raw - create a native TIPC port
+ *
+ * Returns local port reference
+ */
+
+u32 tipc_createport_raw(void *usr_handle,
+ u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
+ void (*wakeup)(struct tipc_port *),
+ const u32 importance)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ u32 ref;
+
+ p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC);
+ if (p_ptr == NULL) {
+ warn("Memory squeeze; failed to create port\n");
+ return 0;
+ }
+ memset(p_ptr, 0, sizeof(*p_ptr));
+ ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
+ if (!ref) {
+ warn("Reference Table Exhausted\n");
+ kfree(p_ptr);
+ return 0;
+ }
+
+ tipc_port_lock(ref);
+ p_ptr->publ.ref = ref;
+ msg = &p_ptr->publ.phdr;
+ msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
+ msg_set_orignode(msg, tipc_own_addr);
+ msg_set_prevnode(msg, tipc_own_addr);
+ msg_set_origport(msg, ref);
+ msg_set_importance(msg,importance);
+ p_ptr->last_in_seqno = 41;
+ p_ptr->sent = 1;
+ p_ptr->publ.usr_handle = usr_handle;
+ INIT_LIST_HEAD(&p_ptr->wait_list);
+ INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
+ p_ptr->congested_link = 0;
+ p_ptr->max_pkt = MAX_PKT_DEFAULT;
+ p_ptr->dispatcher = dispatcher;
+ p_ptr->wakeup = wakeup;
+ p_ptr->user_port = 0;
+ k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
+ spin_lock_bh(&tipc_port_list_lock);
+ INIT_LIST_HEAD(&p_ptr->publications);
+ INIT_LIST_HEAD(&p_ptr->port_list);
+ list_add_tail(&p_ptr->port_list, &ports);
+ spin_unlock_bh(&tipc_port_list_lock);
+ tipc_port_unlock(p_ptr);
+ return ref;
+}
+
+int tipc_deleteport(u32 ref)
+{
+ struct port *p_ptr;
+ struct sk_buff *buf = 0;
+
+ tipc_withdraw(ref, 0, 0);
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+
+ tipc_ref_discard(ref);
+ tipc_port_unlock(p_ptr);
+
+ k_cancel_timer(&p_ptr->timer);
+ if (p_ptr->publ.connected) {
+ buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
+ tipc_nodesub_unsubscribe(&p_ptr->subscription);
+ }
+ if (p_ptr->user_port) {
+ tipc_reg_remove_port(p_ptr->user_port);
+ kfree(p_ptr->user_port);
+ }
+
+ spin_lock_bh(&tipc_port_list_lock);
+ list_del(&p_ptr->port_list);
+ list_del(&p_ptr->wait_list);
+ spin_unlock_bh(&tipc_port_list_lock);
+ k_term_timer(&p_ptr->timer);
+ kfree(p_ptr);
+ dbg("Deleted port %u\n", ref);
+ tipc_net_route_msg(buf);
+ return TIPC_OK;
+}
+
+/**
+ * tipc_get_port() - return port associated with 'ref'
+ *
+ * Note: Port is not locked.
+ */
+
+struct tipc_port *tipc_get_port(const u32 ref)
+{
+ return (struct tipc_port *)tipc_ref_deref(ref);
+}
+
+/**
+ * tipc_get_handle - return user handle associated to port 'ref'
+ */
+
+void *tipc_get_handle(const u32 ref)
+{
+ struct port *p_ptr;
+ void * handle;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return 0;
+ handle = p_ptr->publ.usr_handle;
+ tipc_port_unlock(p_ptr);
+ return handle;
+}
+
+static inline int port_unreliable(struct port *p_ptr)
+{
+ return msg_src_droppable(&p_ptr->publ.phdr);
+}
+
+int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ *isunreliable = port_unreliable(p_ptr);
+ spin_unlock_bh(p_ptr->publ.lock);
+ return TIPC_OK;
+}
+
+int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0));
+ tipc_port_unlock(p_ptr);
+ return TIPC_OK;
+}
+
+static inline int port_unreturnable(struct port *p_ptr)
+{
+ return msg_dest_droppable(&p_ptr->publ.phdr);
+}
+
+int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ *isunrejectable = port_unreturnable(p_ptr);
+ spin_unlock_bh(p_ptr->publ.lock);
+ return TIPC_OK;
+}
+
+int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0));
+ tipc_port_unlock(p_ptr);
+ return TIPC_OK;
+}
+
+/*
+ * port_build_proto_msg(): build a port level protocol
+ * or a connection abortion message. Called with
+ * tipc_port lock on.
+ */
+static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
+ u32 origport, u32 orignode,
+ u32 usr, u32 type, u32 err,
+ u32 seqno, u32 ack)
+{
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+
+ buf = buf_acquire(LONG_H_SIZE);
+ if (buf) {
+ msg = buf_msg(buf);
+ msg_init(msg, usr, type, err, LONG_H_SIZE, destnode);
+ msg_set_destport(msg, destport);
+ msg_set_origport(msg, origport);
+ msg_set_destnode(msg, destnode);
+ msg_set_orignode(msg, orignode);
+ msg_set_transp_seqno(msg, seqno);
+ msg_set_msgcnt(msg, ack);
+ msg_dbg(msg, "PORT>SEND>:");
+ }
+ return buf;
+}
+
+int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz)
+{
+ msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr));
+ msg_set_options(&tp_ptr->phdr, opt, sz);
+ return TIPC_OK;
+}
+
+int tipc_reject_msg(struct sk_buff *buf, u32 err)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ struct sk_buff *rbuf;
+ struct tipc_msg *rmsg;
+ int hdr_sz;
+ u32 imp = msg_importance(msg);
+ u32 data_sz = msg_data_sz(msg);
+
+ if (data_sz > MAX_REJECT_SIZE)
+ data_sz = MAX_REJECT_SIZE;
+ if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
+ imp++;
+ msg_dbg(msg, "port->rej: ");
+
+ /* discard rejected message if it shouldn't be returned to sender */
+ if (msg_errcode(msg) || msg_dest_droppable(msg)) {
+ buf_discard(buf);
+ return data_sz;
+ }
+
+ /* construct rejected message */
+ if (msg_mcast(msg))
+ hdr_sz = MCAST_H_SIZE;
+ else
+ hdr_sz = LONG_H_SIZE;
+ rbuf = buf_acquire(data_sz + hdr_sz);
+ if (rbuf == NULL) {
+ buf_discard(buf);
+ return data_sz;
+ }
+ rmsg = buf_msg(rbuf);
+ msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg));
+ msg_set_destport(rmsg, msg_origport(msg));
+ msg_set_prevnode(rmsg, tipc_own_addr);
+ msg_set_origport(rmsg, msg_destport(msg));
+ if (msg_short(msg))
+ msg_set_orignode(rmsg, tipc_own_addr);
+ else
+ msg_set_orignode(rmsg, msg_destnode(msg));
+ msg_set_size(rmsg, data_sz + hdr_sz);
+ msg_set_nametype(rmsg, msg_nametype(msg));
+ msg_set_nameinst(rmsg, msg_nameinst(msg));
+ memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz);
+
+ /* send self-abort message when rejecting on a connected port */
+ if (msg_connected(msg)) {
+ struct sk_buff *abuf = 0;
+ struct port *p_ptr = tipc_port_lock(msg_destport(msg));
+
+ if (p_ptr) {
+ if (p_ptr->publ.connected)
+ abuf = port_build_self_abort_msg(p_ptr, err);
+ tipc_port_unlock(p_ptr);
+ }
+ tipc_net_route_msg(abuf);
+ }
+
+ /* send rejected message */
+ buf_discard(buf);
+ tipc_net_route_msg(rbuf);
+ return data_sz;
+}
+
+int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+ struct iovec const *msg_sect, u32 num_sect,
+ int err)
+{
+ struct sk_buff *buf;
+ int res;
+
+ res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
+ !p_ptr->user_port, &buf);
+ if (!buf)
+ return res;
+
+ return tipc_reject_msg(buf, err);
+}
+
+static void port_timeout(unsigned long ref)
+{
+ struct port *p_ptr = tipc_port_lock(ref);
+ struct sk_buff *buf = 0;
+
+ if (!p_ptr || !p_ptr->publ.connected)
+ return;
+
+ /* Last probe answered ? */
+ if (p_ptr->probing_state == PROBING) {
+ buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
+ } else {
+ buf = port_build_proto_msg(port_peerport(p_ptr),
+ port_peernode(p_ptr),
+ p_ptr->publ.ref,
+ tipc_own_addr,
+ CONN_MANAGER,
+ CONN_PROBE,
+ TIPC_OK,
+ port_out_seqno(p_ptr),
+ 0);
+ port_incr_out_seqno(p_ptr);
+ p_ptr->probing_state = PROBING;
+ k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
+ }
+ tipc_port_unlock(p_ptr);
+ tipc_net_route_msg(buf);
+}
+
+
+static void port_handle_node_down(unsigned long ref)
+{
+ struct port *p_ptr = tipc_port_lock(ref);
+ struct sk_buff* buf = 0;
+
+ if (!p_ptr)
+ return;
+ buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE);
+ tipc_port_unlock(p_ptr);
+ tipc_net_route_msg(buf);
+}
+
+
+static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err)
+{
+ u32 imp = msg_importance(&p_ptr->publ.phdr);
+
+ if (!p_ptr->publ.connected)
+ return 0;
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ imp++;
+ return port_build_proto_msg(p_ptr->publ.ref,
+ tipc_own_addr,
+ port_peerport(p_ptr),
+ port_peernode(p_ptr),
+ imp,
+ TIPC_CONN_MSG,
+ err,
+ p_ptr->last_in_seqno + 1,
+ 0);
+}
+
+
+static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err)
+{
+ u32 imp = msg_importance(&p_ptr->publ.phdr);
+
+ if (!p_ptr->publ.connected)
+ return 0;
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ imp++;
+ return port_build_proto_msg(port_peerport(p_ptr),
+ port_peernode(p_ptr),
+ p_ptr->publ.ref,
+ tipc_own_addr,
+ imp,
+ TIPC_CONN_MSG,
+ err,
+ port_out_seqno(p_ptr),
+ 0);
+}
+
+void tipc_port_recv_proto_msg(struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ struct port *p_ptr = tipc_port_lock(msg_destport(msg));
+ u32 err = TIPC_OK;
+ struct sk_buff *r_buf = 0;
+ struct sk_buff *abort_buf = 0;
+
+ msg_dbg(msg, "PORT<RECV<:");
+
+ if (!p_ptr) {
+ err = TIPC_ERR_NO_PORT;
+ } else if (p_ptr->publ.connected) {
+ if (port_peernode(p_ptr) != msg_orignode(msg))
+ err = TIPC_ERR_NO_PORT;
+ if (port_peerport(p_ptr) != msg_origport(msg))
+ err = TIPC_ERR_NO_PORT;
+ if (!err && msg_routed(msg)) {
+ u32 seqno = msg_transp_seqno(msg);
+ u32 myno = ++p_ptr->last_in_seqno;
+ if (seqno != myno) {
+ err = TIPC_ERR_NO_PORT;
+ abort_buf = port_build_self_abort_msg(p_ptr, err);
+ }
+ }
+ if (msg_type(msg) == CONN_ACK) {
+ int wakeup = tipc_port_congested(p_ptr) &&
+ p_ptr->publ.congested &&
+ p_ptr->wakeup;
+ p_ptr->acked += msg_msgcnt(msg);
+ if (tipc_port_congested(p_ptr))
+ goto exit;
+ p_ptr->publ.congested = 0;
+ if (!wakeup)
+ goto exit;
+ p_ptr->wakeup(&p_ptr->publ);
+ goto exit;
+ }
+ } else if (p_ptr->publ.published) {
+ err = TIPC_ERR_NO_PORT;
+ }
+ if (err) {
+ r_buf = port_build_proto_msg(msg_origport(msg),
+ msg_orignode(msg),
+ msg_destport(msg),
+ tipc_own_addr,
+ DATA_HIGH,
+ TIPC_CONN_MSG,
+ err,
+ 0,
+ 0);
+ goto exit;
+ }
+
+ /* All is fine */
+ if (msg_type(msg) == CONN_PROBE) {
+ r_buf = port_build_proto_msg(msg_origport(msg),
+ msg_orignode(msg),
+ msg_destport(msg),
+ tipc_own_addr,
+ CONN_MANAGER,
+ CONN_PROBE_REPLY,
+ TIPC_OK,
+ port_out_seqno(p_ptr),
+ 0);
+ }
+ p_ptr->probing_state = CONFIRMED;
+ port_incr_out_seqno(p_ptr);
+exit:
+ if (p_ptr)
+ tipc_port_unlock(p_ptr);
+ tipc_net_route_msg(r_buf);
+ tipc_net_route_msg(abort_buf);
+ buf_discard(buf);
+}
+
+static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id)
+{
+ struct publication *publ;
+
+ if (full_id)
+ tipc_printf(buf, "<%u.%u.%u:%u>:",
+ tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
+ tipc_node(tipc_own_addr), p_ptr->publ.ref);
+ else
+ tipc_printf(buf, "%-10u:", p_ptr->publ.ref);
+
+ if (p_ptr->publ.connected) {
+ u32 dport = port_peerport(p_ptr);
+ u32 destnode = port_peernode(p_ptr);
+
+ tipc_printf(buf, " connected to <%u.%u.%u:%u>",
+ tipc_zone(destnode), tipc_cluster(destnode),
+ tipc_node(destnode), dport);
+ if (p_ptr->publ.conn_type != 0)
+ tipc_printf(buf, " via {%u,%u}",
+ p_ptr->publ.conn_type,
+ p_ptr->publ.conn_instance);
+ }
+ else if (p_ptr->publ.published) {
+ tipc_printf(buf, " bound to");
+ list_for_each_entry(publ, &p_ptr->publications, pport_list) {
+ if (publ->lower == publ->upper)
+ tipc_printf(buf, " {%u,%u}", publ->type,
+ publ->lower);
+ else
+ tipc_printf(buf, " {%u,%u,%u}", publ->type,
+ publ->lower, publ->upper);
+ }
+ }
+ tipc_printf(buf, "\n");
+}
+
+#define MAX_PORT_QUERY 32768
+
+struct sk_buff *tipc_port_get_ports(void)
+{
+ struct sk_buff *buf;
+ struct tlv_desc *rep_tlv;
+ struct print_buf pb;
+ struct port *p_ptr;
+ int str_len;
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
+ if (!buf)
+ return NULL;
+ rep_tlv = (struct tlv_desc *)buf->data;
+
+ tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
+ spin_lock_bh(&tipc_port_list_lock);
+ list_for_each_entry(p_ptr, &ports, port_list) {
+ spin_lock_bh(p_ptr->publ.lock);
+ port_print(p_ptr, &pb, 0);
+ spin_unlock_bh(p_ptr->publ.lock);
+ }
+ spin_unlock_bh(&tipc_port_list_lock);
+ str_len = tipc_printbuf_validate(&pb);
+
+ skb_put(buf, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+
+ return buf;
+}
+
+#if 0
+
+#define MAX_PORT_STATS 2000
+
+struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space)
+{
+ u32 ref;
+ struct port *p_ptr;
+ struct sk_buff *buf;
+ struct tlv_desc *rep_tlv;
+ struct print_buf pb;
+ int str_len;
+
+ if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF))
+ return cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
+
+ ref = *(u32 *)TLV_DATA(req_tlv_area);
+ ref = ntohl(ref);
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return cfg_reply_error_string("port not found");
+
+ buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS));
+ if (!buf) {
+ tipc_port_unlock(p_ptr);
+ return NULL;
+ }
+ rep_tlv = (struct tlv_desc *)buf->data;
+
+ tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS);
+ port_print(p_ptr, &pb, 1);
+ /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */
+ tipc_port_unlock(p_ptr);
+ str_len = tipc_printbuf_validate(&pb);
+
+ skb_put(buf, TLV_SPACE(str_len));
+ TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
+
+ return buf;
+}
+
+#endif
+
+void tipc_port_reinit(void)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+
+ spin_lock_bh(&tipc_port_list_lock);
+ list_for_each_entry(p_ptr, &ports, port_list) {
+ msg = &p_ptr->publ.phdr;
+ if (msg_orignode(msg) == tipc_own_addr)
+ break;
+ msg_set_orignode(msg, tipc_own_addr);
+ }
+ spin_unlock_bh(&tipc_port_list_lock);
+}
+
+
+/*
+ * port_dispatcher_sigh(): Signal handler for messages destinated
+ * to the tipc_port interface.
+ */
+
+static void port_dispatcher_sigh(void *dummy)
+{
+ struct sk_buff *buf;
+
+ spin_lock_bh(&queue_lock);
+ buf = msg_queue_head;
+ msg_queue_head = 0;
+ spin_unlock_bh(&queue_lock);
+
+ while (buf) {
+ struct port *p_ptr;
+ struct user_port *up_ptr;
+ struct tipc_portid orig;
+ struct tipc_name_seq dseq;
+ void *usr_handle;
+ int connected;
+ int published;
+
+ struct sk_buff *next = buf->next;
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 dref = msg_destport(msg);
+
+ p_ptr = tipc_port_lock(dref);
+ if (!p_ptr) {
+ /* Port deleted while msg in queue */
+ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+ buf = next;
+ continue;
+ }
+ orig.ref = msg_origport(msg);
+ orig.node = msg_orignode(msg);
+ up_ptr = p_ptr->user_port;
+ usr_handle = up_ptr->usr_handle;
+ connected = p_ptr->publ.connected;
+ published = p_ptr->publ.published;
+
+ if (unlikely(msg_errcode(msg)))
+ goto err;
+
+ switch (msg_type(msg)) {
+
+ case TIPC_CONN_MSG:{
+ tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
+ u32 peer_port = port_peerport(p_ptr);
+ u32 peer_node = port_peernode(p_ptr);
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (unlikely(!connected)) {
+ if (unlikely(published))
+ goto reject;
+ tipc_connect2port(dref,&orig);
+ }
+ if (unlikely(msg_origport(msg) != peer_port))
+ goto reject;
+ if (unlikely(msg_orignode(msg) != peer_node))
+ goto reject;
+ if (unlikely(!cb))
+ goto reject;
+ if (unlikely(++p_ptr->publ.conn_unacked >=
+ TIPC_FLOW_CONTROL_WIN))
+ tipc_acknowledge(dref,
+ p_ptr->publ.conn_unacked);
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg));
+ break;
+ }
+ case TIPC_DIRECT_MSG:{
+ tipc_msg_event cb = up_ptr->msg_cb;
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (unlikely(connected))
+ goto reject;
+ if (unlikely(!cb))
+ goto reject;
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg), msg_importance(msg),
+ &orig);
+ break;
+ }
+ case TIPC_NAMED_MSG:{
+ tipc_named_msg_event cb = up_ptr->named_msg_cb;
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (unlikely(connected))
+ goto reject;
+ if (unlikely(!cb))
+ goto reject;
+ if (unlikely(!published))
+ goto reject;
+ dseq.type = msg_nametype(msg);
+ dseq.lower = msg_nameinst(msg);
+ dseq.upper = dseq.lower;
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg), msg_importance(msg),
+ &orig, &dseq);
+ break;
+ }
+ }
+ if (buf)
+ buf_discard(buf);
+ buf = next;
+ continue;
+err:
+ switch (msg_type(msg)) {
+
+ case TIPC_CONN_MSG:{
+ tipc_conn_shutdown_event cb =
+ up_ptr->conn_err_cb;
+ u32 peer_port = port_peerport(p_ptr);
+ u32 peer_node = port_peernode(p_ptr);
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (!connected || !cb)
+ break;
+ if (msg_origport(msg) != peer_port)
+ break;
+ if (msg_orignode(msg) != peer_node)
+ break;
+ tipc_disconnect(dref);
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg), msg_errcode(msg));
+ break;
+ }
+ case TIPC_DIRECT_MSG:{
+ tipc_msg_err_event cb = up_ptr->err_cb;
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (connected || !cb)
+ break;
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg), msg_errcode(msg), &orig);
+ break;
+ }
+ case TIPC_NAMED_MSG:{
+ tipc_named_msg_err_event cb =
+ up_ptr->named_err_cb;
+
+ spin_unlock_bh(p_ptr->publ.lock);
+ if (connected || !cb)
+ break;
+ dseq.type = msg_nametype(msg);
+ dseq.lower = msg_nameinst(msg);
+ dseq.upper = dseq.lower;
+ skb_pull(buf, msg_hdr_sz(msg));
+ cb(usr_handle, dref, &buf, msg_data(msg),
+ msg_data_sz(msg), msg_errcode(msg), &dseq);
+ break;
+ }
+ }
+ if (buf)
+ buf_discard(buf);
+ buf = next;
+ continue;
+reject:
+ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+ buf = next;
+ }
+}
+
+/*
+ * port_dispatcher(): Dispatcher for messages destinated
+ * to the tipc_port interface. Called with port locked.
+ */
+
+static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf)
+{
+ buf->next = NULL;
+ spin_lock_bh(&queue_lock);
+ if (msg_queue_head) {
+ msg_queue_tail->next = buf;
+ msg_queue_tail = buf;
+ } else {
+ msg_queue_tail = msg_queue_head = buf;
+ tipc_k_signal((Handler)port_dispatcher_sigh, 0);
+ }
+ spin_unlock_bh(&queue_lock);
+ return TIPC_OK;
+}
+
+/*
+ * Wake up port after congestion: Called with port locked,
+ *
+ */
+
+static void port_wakeup_sh(unsigned long ref)
+{
+ struct port *p_ptr;
+ struct user_port *up_ptr;
+ tipc_continue_event cb = 0;
+ void *uh = 0;
+
+ p_ptr = tipc_port_lock(ref);
+ if (p_ptr) {
+ up_ptr = p_ptr->user_port;
+ if (up_ptr) {
+ cb = up_ptr->continue_event_cb;
+ uh = up_ptr->usr_handle;
+ }
+ tipc_port_unlock(p_ptr);
+ }
+ if (cb)
+ cb(uh, ref);
+}
+
+
+static void port_wakeup(struct tipc_port *p_ptr)
+{
+ tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref);
+}
+
+void tipc_acknowledge(u32 ref, u32 ack)
+{
+ struct port *p_ptr;
+ struct sk_buff *buf = 0;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return;
+ if (p_ptr->publ.connected) {
+ p_ptr->publ.conn_unacked -= ack;
+ buf = port_build_proto_msg(port_peerport(p_ptr),
+ port_peernode(p_ptr),
+ ref,
+ tipc_own_addr,
+ CONN_MANAGER,
+ CONN_ACK,
+ TIPC_OK,
+ port_out_seqno(p_ptr),
+ ack);
+ }
+ tipc_port_unlock(p_ptr);
+ tipc_net_route_msg(buf);
+}
+
+/*
+ * tipc_createport(): user level call. Will add port to
+ * registry if non-zero user_ref.
+ */
+
+int tipc_createport(u32 user_ref,
+ void *usr_handle,
+ unsigned int importance,
+ tipc_msg_err_event error_cb,
+ tipc_named_msg_err_event named_error_cb,
+ tipc_conn_shutdown_event conn_error_cb,
+ tipc_msg_event msg_cb,
+ tipc_named_msg_event named_msg_cb,
+ tipc_conn_msg_event conn_msg_cb,
+ tipc_continue_event continue_event_cb,/* May be zero */
+ u32 *portref)
+{
+ struct user_port *up_ptr;
+ struct port *p_ptr;
+ u32 ref;
+
+ up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
+ if (up_ptr == NULL) {
+ return -ENOMEM;
+ }
+ ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance);
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr) {
+ kfree(up_ptr);
+ return -ENOMEM;
+ }
+
+ p_ptr->user_port = up_ptr;
+ up_ptr->user_ref = user_ref;
+ up_ptr->usr_handle = usr_handle;
+ up_ptr->ref = p_ptr->publ.ref;
+ up_ptr->err_cb = error_cb;
+ up_ptr->named_err_cb = named_error_cb;
+ up_ptr->conn_err_cb = conn_error_cb;
+ up_ptr->msg_cb = msg_cb;
+ up_ptr->named_msg_cb = named_msg_cb;
+ up_ptr->conn_msg_cb = conn_msg_cb;
+ up_ptr->continue_event_cb = continue_event_cb;
+ INIT_LIST_HEAD(&up_ptr->uport_list);
+ tipc_reg_add_port(up_ptr);
+ *portref = p_ptr->publ.ref;
+ dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref);
+ tipc_port_unlock(p_ptr);
+ return TIPC_OK;
+}
+
+int tipc_ownidentity(u32 ref, struct tipc_portid *id)
+{
+ id->ref = ref;
+ id->node = tipc_own_addr;
+ return TIPC_OK;
+}
+
+int tipc_portimportance(u32 ref, unsigned int *importance)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr);
+ spin_unlock_bh(p_ptr->publ.lock);
+ return TIPC_OK;
+}
+
+int tipc_set_portimportance(u32 ref, unsigned int imp)
+{
+ struct port *p_ptr;
+
+ if (imp > TIPC_CRITICAL_IMPORTANCE)
+ return -EINVAL;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ msg_set_importance(&p_ptr->publ.phdr, (u32)imp);
+ spin_unlock_bh(p_ptr->publ.lock);
+ return TIPC_OK;
+}
+
+
+int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+{
+ struct port *p_ptr;
+ struct publication *publ;
+ u32 key;
+ int res = -EINVAL;
+
+ p_ptr = tipc_port_lock(ref);
+ dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, "
+ "lower = %u, upper = %u\n",
+ ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper);
+ if (!p_ptr)
+ return -EINVAL;
+ if (p_ptr->publ.connected)
+ goto exit;
+ if (seq->lower > seq->upper)
+ goto exit;
+ if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE))
+ goto exit;
+ key = ref + p_ptr->pub_count + 1;
+ if (key == ref) {
+ res = -EADDRINUSE;
+ goto exit;
+ }
+ publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
+ scope, p_ptr->publ.ref, key);
+ if (publ) {
+ list_add(&publ->pport_list, &p_ptr->publications);
+ p_ptr->pub_count++;
+ p_ptr->publ.published = 1;
+ res = TIPC_OK;
+ }
+exit:
+ tipc_port_unlock(p_ptr);
+ return res;
+}
+
+int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
+{
+ struct port *p_ptr;
+ struct publication *publ;
+ struct publication *tpubl;
+ int res = -EINVAL;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ if (!p_ptr->publ.published)
+ goto exit;
+ if (!seq) {
+ list_for_each_entry_safe(publ, tpubl,
+ &p_ptr->publications, pport_list) {
+ tipc_nametbl_withdraw(publ->type, publ->lower,
+ publ->ref, publ->key);
+ }
+ res = TIPC_OK;
+ } else {
+ list_for_each_entry_safe(publ, tpubl,
+ &p_ptr->publications, pport_list) {
+ if (publ->scope != scope)
+ continue;
+ if (publ->type != seq->type)
+ continue;
+ if (publ->lower != seq->lower)
+ continue;
+ if (publ->upper != seq->upper)
+ break;
+ tipc_nametbl_withdraw(publ->type, publ->lower,
+ publ->ref, publ->key);
+ res = TIPC_OK;
+ break;
+ }
+ }
+ if (list_empty(&p_ptr->publications))
+ p_ptr->publ.published = 0;
+exit:
+ tipc_port_unlock(p_ptr);
+ return res;
+}
+
+int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ int res = -EINVAL;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ if (p_ptr->publ.published || p_ptr->publ.connected)
+ goto exit;
+ if (!peer->ref)
+ goto exit;
+
+ msg = &p_ptr->publ.phdr;
+ msg_set_destnode(msg, peer->node);
+ msg_set_destport(msg, peer->ref);
+ msg_set_orignode(msg, tipc_own_addr);
+ msg_set_origport(msg, p_ptr->publ.ref);
+ msg_set_transp_seqno(msg, 42);
+ msg_set_type(msg, TIPC_CONN_MSG);
+ if (!may_route(peer->node))
+ msg_set_hdr_sz(msg, SHORT_H_SIZE);
+ else
+ msg_set_hdr_sz(msg, LONG_H_SIZE);
+
+ p_ptr->probing_interval = PROBING_INTERVAL;
+ p_ptr->probing_state = CONFIRMED;
+ p_ptr->publ.connected = 1;
+ k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
+
+ tipc_nodesub_subscribe(&p_ptr->subscription,peer->node,
+ (void *)(unsigned long)ref,
+ (net_ev_handler)port_handle_node_down);
+ res = TIPC_OK;
+exit:
+ tipc_port_unlock(p_ptr);
+ p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+ return res;
+}
+
+/*
+ * tipc_disconnect(): Disconnect port form peer.
+ * This is a node local operation.
+ */
+
+int tipc_disconnect(u32 ref)
+{
+ struct port *p_ptr;
+ int res = -ENOTCONN;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ if (p_ptr->publ.connected) {
+ p_ptr->publ.connected = 0;
+ /* let timer expire on it's own to avoid deadlock! */
+ tipc_nodesub_unsubscribe(&p_ptr->subscription);
+ res = TIPC_OK;
+ }
+ tipc_port_unlock(p_ptr);
+ return res;
+}
+
+/*
+ * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect
+ */
+int tipc_shutdown(u32 ref)
+{
+ struct port *p_ptr;
+ struct sk_buff *buf = 0;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+
+ if (p_ptr->publ.connected) {
+ u32 imp = msg_importance(&p_ptr->publ.phdr);
+ if (imp < TIPC_CRITICAL_IMPORTANCE)
+ imp++;
+ buf = port_build_proto_msg(port_peerport(p_ptr),
+ port_peernode(p_ptr),
+ ref,
+ tipc_own_addr,
+ imp,
+ TIPC_CONN_MSG,
+ TIPC_CONN_SHUTDOWN,
+ port_out_seqno(p_ptr),
+ 0);
+ }
+ tipc_port_unlock(p_ptr);
+ tipc_net_route_msg(buf);
+ return tipc_disconnect(ref);
+}
+
+int tipc_isconnected(u32 ref, int *isconnected)
+{
+ struct port *p_ptr;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ *isconnected = p_ptr->publ.connected;
+ tipc_port_unlock(p_ptr);
+ return TIPC_OK;
+}
+
+int tipc_peer(u32 ref, struct tipc_portid *peer)
+{
+ struct port *p_ptr;
+ int res;
+
+ p_ptr = tipc_port_lock(ref);
+ if (!p_ptr)
+ return -EINVAL;
+ if (p_ptr->publ.connected) {
+ peer->ref = port_peerport(p_ptr);
+ peer->node = port_peernode(p_ptr);
+ res = TIPC_OK;
+ } else
+ res = -ENOTCONN;
+ tipc_port_unlock(p_ptr);
+ return res;
+}
+
+int tipc_ref_valid(u32 ref)
+{
+ /* Works irrespective of type */
+ return !!tipc_ref_deref(ref);
+}
+
+
+/*
+ * tipc_port_recv_sections(): Concatenate and deliver sectioned
+ * message for this node.
+ */
+
+int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
+ struct iovec const *msg_sect)
+{
+ struct sk_buff *buf;
+ int res;
+
+ res = msg_build(&sender->publ.phdr, msg_sect, num_sect,
+ MAX_MSG_SIZE, !sender->user_port, &buf);
+ if (likely(buf))
+ tipc_port_recv_msg(buf);
+ return res;
+}
+
+/**
+ * tipc_send - send message sections on connection
+ */
+
+int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
+{
+ struct port *p_ptr;
+ u32 destnode;
+ int res;
+
+ p_ptr = tipc_port_deref(ref);
+ if (!p_ptr || !p_ptr->publ.connected)
+ return -EINVAL;
+
+ p_ptr->publ.congested = 1;
+ if (!tipc_port_congested(p_ptr)) {
+ destnode = port_peernode(p_ptr);
+ if (likely(destnode != tipc_own_addr))
+ res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
+ destnode);
+ else
+ res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+
+ if (likely(res != -ELINKCONG)) {
+ port_incr_out_seqno(p_ptr);
+ p_ptr->publ.congested = 0;
+ p_ptr->sent++;
+ return res;
+ }
+ }
+ if (port_unreliable(p_ptr)) {
+ p_ptr->publ.congested = 0;
+ /* Just calculate msg length and return */
+ return msg_calc_data_size(msg_sect, num_sect);
+ }
+ return -ELINKCONG;
+}
+
+/**
+ * tipc_send_buf - send message buffer on connection
+ */
+
+int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ u32 destnode;
+ u32 hsz;
+ u32 sz;
+ u32 res;
+
+ p_ptr = tipc_port_deref(ref);
+ if (!p_ptr || !p_ptr->publ.connected)
+ return -EINVAL;
+
+ msg = &p_ptr->publ.phdr;
+ hsz = msg_hdr_sz(msg);
+ sz = hsz + dsz;
+ msg_set_size(msg, sz);
+ if (skb_cow(buf, hsz))
+ return -ENOMEM;
+
+ skb_push(buf, hsz);
+ memcpy(buf->data, (unchar *)msg, hsz);
+ destnode = msg_destnode(msg);
+ p_ptr->publ.congested = 1;
+ if (!tipc_port_congested(p_ptr)) {
+ if (likely(destnode != tipc_own_addr))
+ res = tipc_send_buf_fast(buf, destnode);
+ else {
+ tipc_port_recv_msg(buf);
+ res = sz;
+ }
+ if (likely(res != -ELINKCONG)) {
+ port_incr_out_seqno(p_ptr);
+ p_ptr->sent++;
+ p_ptr->publ.congested = 0;
+ return res;
+ }
+ }
+ if (port_unreliable(p_ptr)) {
+ p_ptr->publ.congested = 0;
+ return dsz;
+ }
+ return -ELINKCONG;
+}
+
+/**
+ * tipc_forward2name - forward message sections to port name
+ */
+
+int tipc_forward2name(u32 ref,
+ struct tipc_name const *name,
+ u32 domain,
+ u32 num_sect,
+ struct iovec const *msg_sect,
+ struct tipc_portid const *orig,
+ unsigned int importance)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ u32 destnode = domain;
+ u32 destport = 0;
+ int res;
+
+ p_ptr = tipc_port_deref(ref);
+ if (!p_ptr || p_ptr->publ.connected)
+ return -EINVAL;
+
+ msg = &p_ptr->publ.phdr;
+ msg_set_type(msg, TIPC_NAMED_MSG);
+ msg_set_orignode(msg, orig->node);
+ msg_set_origport(msg, orig->ref);
+ msg_set_hdr_sz(msg, LONG_H_SIZE);
+ msg_set_nametype(msg, name->type);
+ msg_set_nameinst(msg, name->instance);
+ msg_set_lookup_scope(msg, addr_scope(domain));
+ if (importance <= TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg,importance);
+ destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
+ msg_set_destnode(msg, destnode);
+ msg_set_destport(msg, destport);
+
+ if (likely(destport || destnode)) {
+ p_ptr->sent++;
+ if (likely(destnode == tipc_own_addr))
+ return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+ res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
+ destnode);
+ if (likely(res != -ELINKCONG))
+ return res;
+ if (port_unreliable(p_ptr)) {
+ /* Just calculate msg length and return */
+ return msg_calc_data_size(msg_sect, num_sect);
+ }
+ return -ELINKCONG;
+ }
+ return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect,
+ TIPC_ERR_NO_NAME);
+}
+
+/**
+ * tipc_send2name - send message sections to port name
+ */
+
+int tipc_send2name(u32 ref,
+ struct tipc_name const *name,
+ unsigned int domain,
+ unsigned int num_sect,
+ struct iovec const *msg_sect)
+{
+ struct tipc_portid orig;
+
+ orig.ref = ref;
+ orig.node = tipc_own_addr;
+ return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig,
+ TIPC_PORT_IMPORTANCE);
+}
+
+/**
+ * tipc_forward_buf2name - forward message buffer to port name
+ */
+
+int tipc_forward_buf2name(u32 ref,
+ struct tipc_name const *name,
+ u32 domain,
+ struct sk_buff *buf,
+ unsigned int dsz,
+ struct tipc_portid const *orig,
+ unsigned int importance)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ u32 destnode = domain;
+ u32 destport = 0;
+ int res;
+
+ p_ptr = (struct port *)tipc_ref_deref(ref);
+ if (!p_ptr || p_ptr->publ.connected)
+ return -EINVAL;
+
+ msg = &p_ptr->publ.phdr;
+ if (importance <= TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg, importance);
+ msg_set_type(msg, TIPC_NAMED_MSG);
+ msg_set_orignode(msg, orig->node);
+ msg_set_origport(msg, orig->ref);
+ msg_set_nametype(msg, name->type);
+ msg_set_nameinst(msg, name->instance);
+ msg_set_lookup_scope(msg, addr_scope(domain));
+ msg_set_hdr_sz(msg, LONG_H_SIZE);
+ msg_set_size(msg, LONG_H_SIZE + dsz);
+ destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
+ msg_set_destnode(msg, destnode);
+ msg_set_destport(msg, destport);
+ msg_dbg(msg, "forw2name ==> ");
+ if (skb_cow(buf, LONG_H_SIZE))
+ return -ENOMEM;
+ skb_push(buf, LONG_H_SIZE);
+ memcpy(buf->data, (unchar *)msg, LONG_H_SIZE);
+ msg_dbg(buf_msg(buf),"PREP:");
+ if (likely(destport || destnode)) {
+ p_ptr->sent++;
+ if (destnode == tipc_own_addr)
+ return tipc_port_recv_msg(buf);
+ res = tipc_send_buf_fast(buf, destnode);
+ if (likely(res != -ELINKCONG))
+ return res;
+ if (port_unreliable(p_ptr))
+ return dsz;
+ return -ELINKCONG;
+ }
+ return tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
+}
+
+/**
+ * tipc_send_buf2name - send message buffer to port name
+ */
+
+int tipc_send_buf2name(u32 ref,
+ struct tipc_name const *dest,
+ u32 domain,
+ struct sk_buff *buf,
+ unsigned int dsz)
+{
+ struct tipc_portid orig;
+
+ orig.ref = ref;
+ orig.node = tipc_own_addr;
+ return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig,
+ TIPC_PORT_IMPORTANCE);
+}
+
+/**
+ * tipc_forward2port - forward message sections to port identity
+ */
+
+int tipc_forward2port(u32 ref,
+ struct tipc_portid const *dest,
+ unsigned int num_sect,
+ struct iovec const *msg_sect,
+ struct tipc_portid const *orig,
+ unsigned int importance)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ int res;
+
+ p_ptr = tipc_port_deref(ref);
+ if (!p_ptr || p_ptr->publ.connected)
+ return -EINVAL;
+
+ msg = &p_ptr->publ.phdr;
+ msg_set_type(msg, TIPC_DIRECT_MSG);
+ msg_set_orignode(msg, orig->node);
+ msg_set_origport(msg, orig->ref);
+ msg_set_destnode(msg, dest->node);
+ msg_set_destport(msg, dest->ref);
+ msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
+ if (importance <= TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg, importance);
+ p_ptr->sent++;
+ if (dest->node == tipc_own_addr)
+ return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+ res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node);
+ if (likely(res != -ELINKCONG))
+ return res;
+ if (port_unreliable(p_ptr)) {
+ /* Just calculate msg length and return */
+ return msg_calc_data_size(msg_sect, num_sect);
+ }
+ return -ELINKCONG;
+}
+
+/**
+ * tipc_send2port - send message sections to port identity
+ */
+
+int tipc_send2port(u32 ref,
+ struct tipc_portid const *dest,
+ unsigned int num_sect,
+ struct iovec const *msg_sect)
+{
+ struct tipc_portid orig;
+
+ orig.ref = ref;
+ orig.node = tipc_own_addr;
+ return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig,
+ TIPC_PORT_IMPORTANCE);
+}
+
+/**
+ * tipc_forward_buf2port - forward message buffer to port identity
+ */
+int tipc_forward_buf2port(u32 ref,
+ struct tipc_portid const *dest,
+ struct sk_buff *buf,
+ unsigned int dsz,
+ struct tipc_portid const *orig,
+ unsigned int importance)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg;
+ int res;
+
+ p_ptr = (struct port *)tipc_ref_deref(ref);
+ if (!p_ptr || p_ptr->publ.connected)
+ return -EINVAL;
+
+ msg = &p_ptr->publ.phdr;
+ msg_set_type(msg, TIPC_DIRECT_MSG);
+ msg_set_orignode(msg, orig->node);
+ msg_set_origport(msg, orig->ref);
+ msg_set_destnode(msg, dest->node);
+ msg_set_destport(msg, dest->ref);
+ msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
+ if (importance <= TIPC_CRITICAL_IMPORTANCE)
+ msg_set_importance(msg, importance);
+ msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
+ if (skb_cow(buf, DIR_MSG_H_SIZE))
+ return -ENOMEM;
+
+ skb_push(buf, DIR_MSG_H_SIZE);
+ memcpy(buf->data, (unchar *)msg, DIR_MSG_H_SIZE);
+ msg_dbg(msg, "buf2port: ");
+ p_ptr->sent++;
+ if (dest->node == tipc_own_addr)
+ return tipc_port_recv_msg(buf);
+ res = tipc_send_buf_fast(buf, dest->node);
+ if (likely(res != -ELINKCONG))
+ return res;
+ if (port_unreliable(p_ptr))
+ return dsz;
+ return -ELINKCONG;
+}
+
+/**
+ * tipc_send_buf2port - send message buffer to port identity
+ */
+
+int tipc_send_buf2port(u32 ref,
+ struct tipc_portid const *dest,
+ struct sk_buff *buf,
+ unsigned int dsz)
+{
+ struct tipc_portid orig;
+
+ orig.ref = ref;
+ orig.node = tipc_own_addr;
+ return tipc_forward_buf2port(ref, dest, buf, dsz, &orig,
+ TIPC_PORT_IMPORTANCE);
+}
+
diff --git a/net/tipc/port.h b/net/tipc/port.h
new file mode 100644
index 000000000000..839f100da646
--- /dev/null
+++ b/net/tipc/port.h
@@ -0,0 +1,209 @@
+/*
+ * net/tipc/port.h: Include file for TIPC port code
+ *
+ * Copyright (c) 1994-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_PORT_H
+#define _TIPC_PORT_H
+
+#include "core.h"
+#include "ref.h"
+#include "net.h"
+#include "msg.h"
+#include "dbg.h"
+#include "node_subscr.h"
+
+/**
+ * struct user_port - TIPC user port (used with native API)
+ * @user_ref: id of user who created user port
+ * @usr_handle: user-specified field
+ * @ref: object reference to associated TIPC port
+ * <various callback routines>
+ * @uport_list: adjacent user ports in list of ports held by user
+ */
+
+struct user_port {
+ u32 user_ref;
+ void *usr_handle;
+ u32 ref;
+ tipc_msg_err_event err_cb;
+ tipc_named_msg_err_event named_err_cb;
+ tipc_conn_shutdown_event conn_err_cb;
+ tipc_msg_event msg_cb;
+ tipc_named_msg_event named_msg_cb;
+ tipc_conn_msg_event conn_msg_cb;
+ tipc_continue_event continue_event_cb;
+ struct list_head uport_list;
+};
+
+/**
+ * struct port - TIPC port structure
+ * @publ: TIPC port info available to privileged users
+ * @port_list: adjacent ports in TIPC's global list of ports
+ * @dispatcher: ptr to routine which handles received messages
+ * @wakeup: ptr to routine to call when port is no longer congested
+ * @user_port: ptr to user port associated with port (if any)
+ * @wait_list: adjacent ports in list of ports waiting on link congestion
+ * @congested_link: ptr to congested link port is waiting on
+ * @waiting_pkts:
+ * @sent:
+ * @acked:
+ * @publications: list of publications for port
+ * @pub_count: total # of publications port has made during its lifetime
+ * @max_pkt: maximum packet size "hint" used when building messages sent by port
+ * @probing_state:
+ * @probing_interval:
+ * @last_in_seqno:
+ * @timer_ref:
+ * @subscription: "node down" subscription used to terminate failed connections
+ */
+
+struct port {
+ struct tipc_port publ;
+ struct list_head port_list;
+ u32 (*dispatcher)(struct tipc_port *, struct sk_buff *);
+ void (*wakeup)(struct tipc_port *);
+ struct user_port *user_port;
+ struct list_head wait_list;
+ struct link *congested_link;
+ u32 waiting_pkts;
+ u32 sent;
+ u32 acked;
+ struct list_head publications;
+ u32 pub_count;
+ u32 max_pkt;
+ u32 probing_state;
+ u32 probing_interval;
+ u32 last_in_seqno;
+ struct timer_list timer;
+ struct node_subscr subscription;
+};
+
+extern spinlock_t tipc_port_list_lock;
+struct port_list;
+
+int tipc_port_recv_sections(struct port *p_ptr, u32 num_sect,
+ struct iovec const *msg_sect);
+int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+ struct iovec const *msg_sect, u32 num_sect,
+ int err);
+struct sk_buff *tipc_port_get_ports(void);
+struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space);
+void tipc_port_recv_proto_msg(struct sk_buff *buf);
+void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
+void tipc_port_reinit(void);
+
+/**
+ * tipc_port_lock - lock port instance referred to and return its pointer
+ */
+
+static inline struct port *tipc_port_lock(u32 ref)
+{
+ return (struct port *)tipc_ref_lock(ref);
+}
+
+/**
+ * tipc_port_unlock - unlock a port instance
+ *
+ * Can use pointer instead of tipc_ref_unlock() since port is already locked.
+ */
+
+static inline void tipc_port_unlock(struct port *p_ptr)
+{
+ spin_unlock_bh(p_ptr->publ.lock);
+}
+
+static inline struct port* tipc_port_deref(u32 ref)
+{
+ return (struct port *)tipc_ref_deref(ref);
+}
+
+static inline u32 tipc_peer_port(struct port *p_ptr)
+{
+ return msg_destport(&p_ptr->publ.phdr);
+}
+
+static inline u32 tipc_peer_node(struct port *p_ptr)
+{
+ return msg_destnode(&p_ptr->publ.phdr);
+}
+
+static inline int tipc_port_congested(struct port *p_ptr)
+{
+ return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2));
+}
+
+/**
+ * tipc_port_recv_msg - receive message from lower layer and deliver to port user
+ */
+
+static inline int tipc_port_recv_msg(struct sk_buff *buf)
+{
+ struct port *p_ptr;
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 destport = msg_destport(msg);
+ u32 dsz = msg_data_sz(msg);
+ u32 err;
+
+ /* forward unresolved named message */
+ if (unlikely(!destport)) {
+ tipc_net_route_msg(buf);
+ return dsz;
+ }
+
+ /* validate destination & pass to port, otherwise reject message */
+ p_ptr = tipc_port_lock(destport);
+ if (likely(p_ptr)) {
+ if (likely(p_ptr->publ.connected)) {
+ if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) ||
+ (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) ||
+ (unlikely(!msg_connected(msg)))) {
+ err = TIPC_ERR_NO_PORT;
+ tipc_port_unlock(p_ptr);
+ goto reject;
+ }
+ }
+ err = p_ptr->dispatcher(&p_ptr->publ, buf);
+ tipc_port_unlock(p_ptr);
+ if (likely(!err))
+ return dsz;
+ } else {
+ err = TIPC_ERR_NO_PORT;
+ }
+reject:
+ dbg("port->rejecting, err = %x..\n",err);
+ return tipc_reject_msg(buf, err);
+}
+
+#endif
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
new file mode 100644
index 000000000000..5a13c2defe4a
--- /dev/null
+++ b/net/tipc/ref.c
@@ -0,0 +1,189 @@
+/*
+ * net/tipc/ref.c: TIPC object registry code
+ *
+ * Copyright (c) 1991-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "ref.h"
+#include "port.h"
+#include "subscr.h"
+#include "name_distr.h"
+#include "name_table.h"
+#include "config.h"
+#include "discover.h"
+#include "bearer.h"
+#include "node.h"
+#include "bcast.h"
+
+/*
+ * Object reference table consists of 2**N entries.
+ *
+ * A used entry has object ptr != 0, reference == XXXX|own index
+ * (XXXX changes each time entry is acquired)
+ * A free entry has object ptr == 0, reference == YYYY|next free index
+ * (YYYY is one more than last used XXXX)
+ *
+ * Free list is initially chained from entry (2**N)-1 to entry 1.
+ * Entry 0 is not used to allow index 0 to indicate the end of the free list.
+ *
+ * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0
+ * because entry 0's reference field has the form XXXX|1--1.
+ */
+
+struct ref_table tipc_ref_table = { 0 };
+
+static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED;
+
+/**
+ * tipc_ref_table_init - create reference table for objects
+ */
+
+int tipc_ref_table_init(u32 requested_size, u32 start)
+{
+ struct reference *table;
+ u32 sz = 1 << 4;
+ u32 index_mask;
+ int i;
+
+ while (sz < requested_size) {
+ sz <<= 1;
+ }
+ table = (struct reference *)vmalloc(sz * sizeof(struct reference));
+ if (table == NULL)
+ return -ENOMEM;
+
+ write_lock_bh(&ref_table_lock);
+ index_mask = sz - 1;
+ for (i = sz - 1; i >= 0; i--) {
+ table[i].object = 0;
+ table[i].lock = SPIN_LOCK_UNLOCKED;
+ table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
+ }
+ tipc_ref_table.entries = table;
+ tipc_ref_table.index_mask = index_mask;
+ tipc_ref_table.first_free = sz - 1;
+ tipc_ref_table.last_free = 1;
+ write_unlock_bh(&ref_table_lock);
+ return TIPC_OK;
+}
+
+/**
+ * tipc_ref_table_stop - destroy reference table for objects
+ */
+
+void tipc_ref_table_stop(void)
+{
+ if (!tipc_ref_table.entries)
+ return;
+
+ vfree(tipc_ref_table.entries);
+ tipc_ref_table.entries = 0;
+}
+
+/**
+ * tipc_ref_acquire - create reference to an object
+ *
+ * Return a unique reference value which can be translated back to the pointer
+ * 'object' at a later time. Also, pass back a pointer to the lock protecting
+ * the object, but without locking it.
+ */
+
+u32 tipc_ref_acquire(void *object, spinlock_t **lock)
+{
+ struct reference *entry;
+ u32 index;
+ u32 index_mask;
+ u32 next_plus_upper;
+ u32 reference = 0;
+
+ assert(tipc_ref_table.entries && object);
+
+ write_lock_bh(&ref_table_lock);
+ if (tipc_ref_table.first_free) {
+ index = tipc_ref_table.first_free;
+ entry = &(tipc_ref_table.entries[index]);
+ index_mask = tipc_ref_table.index_mask;
+ /* take lock in case a previous user of entry still holds it */
+ spin_lock_bh(&entry->lock);
+ next_plus_upper = entry->data.next_plus_upper;
+ tipc_ref_table.first_free = next_plus_upper & index_mask;
+ reference = (next_plus_upper & ~index_mask) + index;
+ entry->data.reference = reference;
+ entry->object = object;
+ if (lock != 0)
+ *lock = &entry->lock;
+ spin_unlock_bh(&entry->lock);
+ }
+ write_unlock_bh(&ref_table_lock);
+ return reference;
+}
+
+/**
+ * tipc_ref_discard - invalidate references to an object
+ *
+ * Disallow future references to an object and free up the entry for re-use.
+ * Note: The entry's spin_lock may still be busy after discard
+ */
+
+void tipc_ref_discard(u32 ref)
+{
+ struct reference *entry;
+ u32 index;
+ u32 index_mask;
+
+ assert(tipc_ref_table.entries);
+ assert(ref != 0);
+
+ write_lock_bh(&ref_table_lock);
+ index_mask = tipc_ref_table.index_mask;
+ index = ref & index_mask;
+ entry = &(tipc_ref_table.entries[index]);
+ assert(entry->object != 0);
+ assert(entry->data.reference == ref);
+
+ /* mark entry as unused */
+ entry->object = 0;
+ if (tipc_ref_table.first_free == 0)
+ tipc_ref_table.first_free = index;
+ else
+ /* next_plus_upper is always XXXX|0--0 for last free entry */
+ tipc_ref_table.entries[tipc_ref_table.last_free].data.next_plus_upper
+ |= index;
+ tipc_ref_table.last_free = index;
+
+ /* increment upper bits of entry to invalidate subsequent references */
+ entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
+ write_unlock_bh(&ref_table_lock);
+}
+
diff --git a/net/tipc/ref.h b/net/tipc/ref.h
new file mode 100644
index 000000000000..4f8f9f40dcac
--- /dev/null
+++ b/net/tipc/ref.h
@@ -0,0 +1,131 @@
+/*
+ * net/tipc/ref.h: Include file for TIPC object registry code
+ *
+ * Copyright (c) 1991-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_REF_H
+#define _TIPC_REF_H
+
+/**
+ * struct reference - TIPC object reference entry
+ * @object: pointer to object associated with reference entry
+ * @lock: spinlock controlling access to object
+ * @data: reference value associated with object (or link to next unused entry)
+ */
+
+struct reference {
+ void *object;
+ spinlock_t lock;
+ union {
+ u32 next_plus_upper;
+ u32 reference;
+ } data;
+};
+
+/**
+ * struct tipc_ref_table - table of TIPC object reference entries
+ * @entries: pointer to array of reference entries
+ * @index_mask: bitmask for array index portion of reference values
+ * @first_free: array index of first unused object reference entry
+ * @last_free: array index of last unused object reference entry
+ */
+
+struct ref_table {
+ struct reference *entries;
+ u32 index_mask;
+ u32 first_free;
+ u32 last_free;
+};
+
+extern struct ref_table tipc_ref_table;
+
+int tipc_ref_table_init(u32 requested_size, u32 start);
+void tipc_ref_table_stop(void);
+
+u32 tipc_ref_acquire(void *object, spinlock_t **lock);
+void tipc_ref_discard(u32 ref);
+
+
+/**
+ * tipc_ref_lock - lock referenced object and return pointer to it
+ */
+
+static inline void *tipc_ref_lock(u32 ref)
+{
+ if (likely(tipc_ref_table.entries)) {
+ struct reference *r =
+ &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+
+ spin_lock_bh(&r->lock);
+ if (likely(r->data.reference == ref))
+ return r->object;
+ spin_unlock_bh(&r->lock);
+ }
+ return 0;
+}
+
+/**
+ * tipc_ref_unlock - unlock referenced object
+ */
+
+static inline void tipc_ref_unlock(u32 ref)
+{
+ if (likely(tipc_ref_table.entries)) {
+ struct reference *r =
+ &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+
+ if (likely(r->data.reference == ref))
+ spin_unlock_bh(&r->lock);
+ else
+ err("tipc_ref_unlock() invoked using obsolete reference\n");
+ }
+}
+
+/**
+ * tipc_ref_deref - return pointer referenced object (without locking it)
+ */
+
+static inline void *tipc_ref_deref(u32 ref)
+{
+ if (likely(tipc_ref_table.entries)) {
+ struct reference *r =
+ &tipc_ref_table.entries[ref & tipc_ref_table.index_mask];
+
+ if (likely(r->data.reference == ref))
+ return r->object;
+ }
+ return 0;
+}
+
+#endif
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
new file mode 100644
index 000000000000..67253bfcd702
--- /dev/null
+++ b/net/tipc/socket.c
@@ -0,0 +1,1724 @@
+/*
+ * net/tipc/socket.c: TIPC socket API
+ *
+ * Copyright (c) 2001-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/fcntl.h>
+#include <asm/semaphore.h>
+#include <asm/string.h>
+#include <asm/atomic.h>
+#include <net/sock.h>
+
+#include <linux/tipc.h>
+#include <linux/tipc_config.h>
+#include <net/tipc/tipc_msg.h>
+#include <net/tipc/tipc_port.h>
+
+#include "core.h"
+
+#define SS_LISTENING -1 /* socket is listening */
+#define SS_READY -2 /* socket is connectionless */
+
+#define OVERLOAD_LIMIT_BASE 5000
+
+struct tipc_sock {
+ struct sock sk;
+ struct tipc_port *p;
+ struct semaphore sem;
+};
+
+#define tipc_sk(sk) ((struct tipc_sock*)sk)
+
+static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
+static void wakeupdispatch(struct tipc_port *tport);
+
+static struct proto_ops packet_ops;
+static struct proto_ops stream_ops;
+static struct proto_ops msg_ops;
+
+static struct proto tipc_proto;
+
+static int sockets_enabled = 0;
+
+static atomic_t tipc_queue_size = ATOMIC_INIT(0);
+
+
+/*
+ * sock_lock(): Lock a port/socket pair. lock_sock() can
+ * not be used here, since the same lock must protect ports
+ * with non-socket interfaces.
+ * See net.c for description of locking policy.
+ */
+static inline void sock_lock(struct tipc_sock* tsock)
+{
+ spin_lock_bh(tsock->p->lock);
+}
+
+/*
+ * sock_unlock(): Unlock a port/socket pair
+ */
+static inline void sock_unlock(struct tipc_sock* tsock)
+{
+ spin_unlock_bh(tsock->p->lock);
+}
+
+/**
+ * pollmask - determine the current set of poll() events for a socket
+ * @sock: socket structure
+ *
+ * TIPC sets the returned events as follows:
+ * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
+ * or if a connection-oriented socket is does not have an active connection
+ * (i.e. a read operation will not block).
+ * b) POLLOUT is set except when a socket's connection has been terminated
+ * (i.e. a write operation will not block).
+ * c) POLLHUP is set when a socket's connection has been terminated.
+ *
+ * IMPORTANT: The fact that a read or write operation will not block does NOT
+ * imply that the operation will succeed!
+ *
+ * Returns pollmask value
+ */
+
+static inline u32 pollmask(struct socket *sock)
+{
+ u32 mask;
+
+ if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) ||
+ (sock->state == SS_UNCONNECTED) ||
+ (sock->state == SS_DISCONNECTING))
+ mask = (POLLRDNORM | POLLIN);
+ else
+ mask = 0;
+
+ if (sock->state == SS_DISCONNECTING)
+ mask |= POLLHUP;
+ else
+ mask |= POLLOUT;
+
+ return mask;
+}
+
+
+/**
+ * advance_queue - discard first buffer in queue
+ * @tsock: TIPC socket
+ */
+
+static inline void advance_queue(struct tipc_sock *tsock)
+{
+ sock_lock(tsock);
+ buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue));
+ sock_unlock(tsock);
+ atomic_dec(&tipc_queue_size);
+}
+
+/**
+ * tipc_create - create a TIPC socket
+ * @sock: pre-allocated socket structure
+ * @protocol: protocol indicator (must be 0)
+ *
+ * This routine creates and attaches a 'struct sock' to the 'struct socket',
+ * then create and attaches a TIPC port to the 'struct sock' part.
+ *
+ * Returns 0 on success, errno otherwise
+ */
+static int tipc_create(struct socket *sock, int protocol)
+{
+ struct tipc_sock *tsock;
+ struct tipc_port *port;
+ struct sock *sk;
+ u32 ref;
+
+ if ((sock->type != SOCK_STREAM) &&
+ (sock->type != SOCK_SEQPACKET) &&
+ (sock->type != SOCK_DGRAM) &&
+ (sock->type != SOCK_RDM))
+ return -EPROTOTYPE;
+
+ if (unlikely(protocol != 0))
+ return -EPROTONOSUPPORT;
+
+ ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE);
+ if (unlikely(!ref))
+ return -ENOMEM;
+
+ sock->state = SS_UNCONNECTED;
+
+ switch (sock->type) {
+ case SOCK_STREAM:
+ sock->ops = &stream_ops;
+ break;
+ case SOCK_SEQPACKET:
+ sock->ops = &packet_ops;
+ break;
+ case SOCK_DGRAM:
+ tipc_set_portunreliable(ref, 1);
+ /* fall through */
+ case SOCK_RDM:
+ tipc_set_portunreturnable(ref, 1);
+ sock->ops = &msg_ops;
+ sock->state = SS_READY;
+ break;
+ }
+
+ sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
+ if (!sk) {
+ tipc_deleteport(ref);
+ return -ENOMEM;
+ }
+
+ sock_init_data(sock, sk);
+ init_waitqueue_head(sk->sk_sleep);
+ sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */
+
+ tsock = tipc_sk(sk);
+ port = tipc_get_port(ref);
+
+ tsock->p = port;
+ port->usr_handle = tsock;
+
+ init_MUTEX(&tsock->sem);
+
+ dbg("sock_create: %x\n",tsock);
+
+ atomic_inc(&tipc_user_count);
+
+ return 0;
+}
+
+/**
+ * release - destroy a TIPC socket
+ * @sock: socket to destroy
+ *
+ * This routine cleans up any messages that are still queued on the socket.
+ * For DGRAM and RDM socket types, all queued messages are rejected.
+ * For SEQPACKET and STREAM socket types, the first message is rejected
+ * and any others are discarded. (If the first message on a STREAM socket
+ * is partially-read, it is discarded and the next one is rejected instead.)
+ *
+ * NOTE: Rejected messages are not necessarily returned to the sender! They
+ * are returned or discarded according to the "destination droppable" setting
+ * specified for the message by the sender.
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int release(struct socket *sock)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sock *sk = sock->sk;
+ int res = TIPC_OK;
+ struct sk_buff *buf;
+
+ dbg("sock_delete: %x\n",tsock);
+ if (!tsock)
+ return 0;
+ down_interruptible(&tsock->sem);
+ if (!sock->sk) {
+ up(&tsock->sem);
+ return 0;
+ }
+
+ /* Reject unreceived messages, unless no longer connected */
+
+ while (sock->state != SS_DISCONNECTING) {
+ sock_lock(tsock);
+ buf = skb_dequeue(&sk->sk_receive_queue);
+ if (!buf)
+ tsock->p->usr_handle = 0;
+ sock_unlock(tsock);
+ if (!buf)
+ break;
+ if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
+ buf_discard(buf);
+ else
+ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+ atomic_dec(&tipc_queue_size);
+ }
+
+ /* Delete TIPC port */
+
+ res = tipc_deleteport(tsock->p->ref);
+ sock->sk = NULL;
+
+ /* Discard any remaining messages */
+
+ while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
+ buf_discard(buf);
+ atomic_dec(&tipc_queue_size);
+ }
+
+ up(&tsock->sem);
+
+ sock_put(sk);
+
+ atomic_dec(&tipc_user_count);
+ return res;
+}
+
+/**
+ * bind - associate or disassocate TIPC name(s) with a socket
+ * @sock: socket structure
+ * @uaddr: socket address describing name(s) and desired operation
+ * @uaddr_len: size of socket address data structure
+ *
+ * Name and name sequence binding is indicated using a positive scope value;
+ * a negative scope value unbinds the specified name. Specifying no name
+ * (i.e. a socket address length of 0) unbinds all names from the socket.
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
+ int res;
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ if (unlikely(!uaddr_len)) {
+ res = tipc_withdraw(tsock->p->ref, 0, 0);
+ goto exit;
+ }
+
+ if (uaddr_len < sizeof(struct sockaddr_tipc)) {
+ res = -EINVAL;
+ goto exit;
+ }
+
+ if (addr->family != AF_TIPC) {
+ res = -EAFNOSUPPORT;
+ goto exit;
+ }
+ if (addr->addrtype == TIPC_ADDR_NAME)
+ addr->addr.nameseq.upper = addr->addr.nameseq.lower;
+ else if (addr->addrtype != TIPC_ADDR_NAMESEQ) {
+ res = -EAFNOSUPPORT;
+ goto exit;
+ }
+
+ if (addr->scope > 0)
+ res = tipc_publish(tsock->p->ref, addr->scope,
+ &addr->addr.nameseq);
+ else
+ res = tipc_withdraw(tsock->p->ref, -addr->scope,
+ &addr->addr.nameseq);
+exit:
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * get_name - get port ID of socket or peer socket
+ * @sock: socket structure
+ * @uaddr: area for returned socket address
+ * @uaddr_len: area for returned length of socket address
+ * @peer: 0 to obtain socket name, 1 to obtain peer socket name
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int get_name(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddr_len, int peer)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr;
+ u32 res;
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ *uaddr_len = sizeof(*addr);
+ addr->addrtype = TIPC_ADDR_ID;
+ addr->family = AF_TIPC;
+ addr->scope = 0;
+ if (peer)
+ res = tipc_peer(tsock->p->ref, &addr->addr.id);
+ else
+ res = tipc_ownidentity(tsock->p->ref, &addr->addr.id);
+ addr->addr.name.domain = 0;
+
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * poll - read and possibly block on pollmask
+ * @file: file structure associated with the socket
+ * @sock: socket for which to calculate the poll bits
+ * @wait: ???
+ *
+ * Returns the pollmask
+ */
+
+static unsigned int poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ poll_wait(file, sock->sk->sk_sleep, wait);
+ /* NEED LOCK HERE? */
+ return pollmask(sock);
+}
+
+/**
+ * dest_name_check - verify user is permitted to send to specified port name
+ * @dest: destination address
+ * @m: descriptor for message to be sent
+ *
+ * Prevents restricted configuration commands from being issued by
+ * unauthorized users.
+ *
+ * Returns 0 if permission is granted, otherwise errno
+ */
+
+static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
+{
+ struct tipc_cfg_msg_hdr hdr;
+
+ if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES))
+ return 0;
+ if (likely(dest->addr.name.name.type == TIPC_TOP_SRV))
+ return 0;
+
+ if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
+ return -EACCES;
+
+ if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
+ return -EFAULT;
+ if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN)))
+ return -EACCES;
+
+ return 0;
+}
+
+/**
+ * send_msg - send message in connectionless manner
+ * @iocb: (unused)
+ * @sock: socket structure
+ * @m: message to send
+ * @total_len: (unused)
+ *
+ * Message must have an destination specified explicitly.
+ * Used for SOCK_RDM and SOCK_DGRAM messages,
+ * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections.
+ * (Note: 'SYN+' is prohibited on SOCK_STREAM.)
+ *
+ * Returns the number of bytes sent on success, or errno otherwise
+ */
+
+static int send_msg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+ struct sk_buff *buf;
+ int needs_conn;
+ int res = -EINVAL;
+
+ if (unlikely(!dest))
+ return -EDESTADDRREQ;
+ if (unlikely(dest->family != AF_TIPC))
+ return -EINVAL;
+
+ needs_conn = (sock->state != SS_READY);
+ if (unlikely(needs_conn)) {
+ if (sock->state == SS_LISTENING)
+ return -EPIPE;
+ if (sock->state != SS_UNCONNECTED)
+ return -EISCONN;
+ if ((tsock->p->published) ||
+ ((sock->type == SOCK_STREAM) && (total_len != 0)))
+ return -EOPNOTSUPP;
+ }
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ if (needs_conn) {
+
+ /* Abort any pending connection attempts (very unlikely) */
+
+ while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+ tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
+ atomic_dec(&tipc_queue_size);
+ }
+
+ sock->state = SS_CONNECTING;
+ }
+
+ do {
+ if (dest->addrtype == TIPC_ADDR_NAME) {
+ if ((res = dest_name_check(dest, m)))
+ goto exit;
+ res = tipc_send2name(tsock->p->ref,
+ &dest->addr.name.name,
+ dest->addr.name.domain,
+ m->msg_iovlen,
+ m->msg_iov);
+ }
+ else if (dest->addrtype == TIPC_ADDR_ID) {
+ res = tipc_send2port(tsock->p->ref,
+ &dest->addr.id,
+ m->msg_iovlen,
+ m->msg_iov);
+ }
+ else if (dest->addrtype == TIPC_ADDR_MCAST) {
+ if (needs_conn) {
+ res = -EOPNOTSUPP;
+ goto exit;
+ }
+ if ((res = dest_name_check(dest, m)))
+ goto exit;
+ res = tipc_multicast(tsock->p->ref,
+ &dest->addr.nameseq,
+ 0,
+ m->msg_iovlen,
+ m->msg_iov);
+ }
+ if (likely(res != -ELINKCONG)) {
+exit:
+ up(&tsock->sem);
+ return res;
+ }
+ if (m->msg_flags & MSG_DONTWAIT) {
+ res = -EWOULDBLOCK;
+ goto exit;
+ }
+ if (wait_event_interruptible(*sock->sk->sk_sleep,
+ !tsock->p->congested)) {
+ res = -ERESTARTSYS;
+ goto exit;
+ }
+ } while (1);
+}
+
+/**
+ * send_packet - send a connection-oriented message
+ * @iocb: (unused)
+ * @sock: socket structure
+ * @m: message to send
+ * @total_len: (unused)
+ *
+ * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
+ *
+ * Returns the number of bytes sent on success, or errno otherwise
+ */
+
+static int send_packet(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
+ int res;
+
+ /* Handle implied connection establishment */
+
+ if (unlikely(dest))
+ return send_msg(iocb, sock, m, total_len);
+
+ if (down_interruptible(&tsock->sem)) {
+ return -ERESTARTSYS;
+ }
+
+ if (unlikely(sock->state != SS_CONNECTED)) {
+ if (sock->state == SS_DISCONNECTING)
+ res = -EPIPE;
+ else
+ res = -ENOTCONN;
+ goto exit;
+ }
+
+ do {
+ res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
+ if (likely(res != -ELINKCONG)) {
+exit:
+ up(&tsock->sem);
+ return res;
+ }
+ if (m->msg_flags & MSG_DONTWAIT) {
+ res = -EWOULDBLOCK;
+ goto exit;
+ }
+ if (wait_event_interruptible(*sock->sk->sk_sleep,
+ !tsock->p->congested)) {
+ res = -ERESTARTSYS;
+ goto exit;
+ }
+ } while (1);
+}
+
+/**
+ * send_stream - send stream-oriented data
+ * @iocb: (unused)
+ * @sock: socket structure
+ * @m: data to send
+ * @total_len: total length of data to be sent
+ *
+ * Used for SOCK_STREAM data.
+ *
+ * Returns the number of bytes sent on success, or errno otherwise
+ */
+
+
+static int send_stream(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t total_len)
+{
+ struct msghdr my_msg;
+ struct iovec my_iov;
+ struct iovec *curr_iov;
+ int curr_iovlen;
+ char __user *curr_start;
+ int curr_left;
+ int bytes_to_send;
+ int res;
+
+ if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
+ return send_packet(iocb, sock, m, total_len);
+
+ /* Can only send large data streams if already connected */
+
+ if (unlikely(sock->state != SS_CONNECTED)) {
+ if (sock->state == SS_DISCONNECTING)
+ return -EPIPE;
+ else
+ return -ENOTCONN;
+ }
+
+ /*
+ * Send each iovec entry using one or more messages
+ *
+ * Note: This algorithm is good for the most likely case
+ * (i.e. one large iovec entry), but could be improved to pass sets
+ * of small iovec entries into send_packet().
+ */
+
+ my_msg = *m;
+ curr_iov = my_msg.msg_iov;
+ curr_iovlen = my_msg.msg_iovlen;
+ my_msg.msg_iov = &my_iov;
+ my_msg.msg_iovlen = 1;
+
+ while (curr_iovlen--) {
+ curr_start = curr_iov->iov_base;
+ curr_left = curr_iov->iov_len;
+
+ while (curr_left) {
+ bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
+ ? curr_left : TIPC_MAX_USER_MSG_SIZE;
+ my_iov.iov_base = curr_start;
+ my_iov.iov_len = bytes_to_send;
+ if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0)
+ return res;
+ curr_left -= bytes_to_send;
+ curr_start += bytes_to_send;
+ }
+
+ curr_iov++;
+ }
+
+ return total_len;
+}
+
+/**
+ * auto_connect - complete connection setup to a remote port
+ * @sock: socket structure
+ * @tsock: TIPC-specific socket structure
+ * @msg: peer's response message
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int auto_connect(struct socket *sock, struct tipc_sock *tsock,
+ struct tipc_msg *msg)
+{
+ struct tipc_portid peer;
+
+ if (msg_errcode(msg)) {
+ sock->state = SS_DISCONNECTING;
+ return -ECONNREFUSED;
+ }
+
+ peer.ref = msg_origport(msg);
+ peer.node = msg_orignode(msg);
+ tipc_connect2port(tsock->p->ref, &peer);
+ tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
+ sock->state = SS_CONNECTED;
+ return 0;
+}
+
+/**
+ * set_orig_addr - capture sender's address for received message
+ * @m: descriptor for message info
+ * @msg: received message header
+ *
+ * Note: Address is not captured if not requested by receiver.
+ */
+
+static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg)
+{
+ struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name;
+
+ if (addr) {
+ addr->family = AF_TIPC;
+ addr->addrtype = TIPC_ADDR_ID;
+ addr->addr.id.ref = msg_origport(msg);
+ addr->addr.id.node = msg_orignode(msg);
+ addr->addr.name.domain = 0; /* could leave uninitialized */
+ addr->scope = 0; /* could leave uninitialized */
+ m->msg_namelen = sizeof(struct sockaddr_tipc);
+ }
+}
+
+/**
+ * anc_data_recv - optionally capture ancillary data for received message
+ * @m: descriptor for message info
+ * @msg: received message header
+ * @tport: TIPC port associated with message
+ *
+ * Note: Ancillary data is not captured if not requested by receiver.
+ *
+ * Returns 0 if successful, otherwise errno
+ */
+
+static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
+ struct tipc_port *tport)
+{
+ u32 anc_data[3];
+ u32 err;
+ u32 dest_type;
+ int res;
+
+ if (likely(m->msg_controllen == 0))
+ return 0;
+
+ /* Optionally capture errored message object(s) */
+
+ err = msg ? msg_errcode(msg) : 0;
+ if (unlikely(err)) {
+ anc_data[0] = err;
+ anc_data[1] = msg_data_sz(msg);
+ if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data)))
+ return res;
+ if (anc_data[1] &&
+ (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1],
+ msg_data(msg))))
+ return res;
+ }
+
+ /* Optionally capture message destination object */
+
+ dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
+ switch (dest_type) {
+ case TIPC_NAMED_MSG:
+ anc_data[0] = msg_nametype(msg);
+ anc_data[1] = msg_namelower(msg);
+ anc_data[2] = msg_namelower(msg);
+ break;
+ case TIPC_MCAST_MSG:
+ anc_data[0] = msg_nametype(msg);
+ anc_data[1] = msg_namelower(msg);
+ anc_data[2] = msg_nameupper(msg);
+ break;
+ case TIPC_CONN_MSG:
+ anc_data[0] = tport->conn_type;
+ anc_data[1] = tport->conn_instance;
+ anc_data[2] = tport->conn_instance;
+ break;
+ default:
+ anc_data[0] = 0;
+ }
+ if (anc_data[0] &&
+ (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data)))
+ return res;
+
+ return 0;
+}
+
+/**
+ * recv_msg - receive packet-oriented message
+ * @iocb: (unused)
+ * @m: descriptor for message info
+ * @buf_len: total size of user buffer area
+ * @flags: receive flags
+ *
+ * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages.
+ * If the complete message doesn't fit in user area, truncate it.
+ *
+ * Returns size of returned message data, errno otherwise
+ */
+
+static int recv_msg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t buf_len, int flags)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ unsigned int q_len;
+ unsigned int sz;
+ u32 err;
+ int res;
+
+ /* Currently doesn't support receiving into multiple iovec entries */
+
+ if (m->msg_iovlen != 1)
+ return -EOPNOTSUPP;
+
+ /* Catch invalid receive attempts */
+
+ if (unlikely(!buf_len))
+ return -EINVAL;
+
+ if (sock->type == SOCK_SEQPACKET) {
+ if (unlikely(sock->state == SS_UNCONNECTED))
+ return -ENOTCONN;
+ if (unlikely((sock->state == SS_DISCONNECTING) &&
+ (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
+ return -ENOTCONN;
+ }
+
+ /* Look for a message in receive queue; wait if necessary */
+
+ if (unlikely(down_interruptible(&tsock->sem)))
+ return -ERESTARTSYS;
+
+restart:
+ if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+ (flags & MSG_DONTWAIT))) {
+ res = -EWOULDBLOCK;
+ goto exit;
+ }
+
+ if ((res = wait_event_interruptible(
+ *sock->sk->sk_sleep,
+ ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+ (sock->state == SS_DISCONNECTING))) )) {
+ goto exit;
+ }
+
+ /* Catch attempt to receive on an already terminated connection */
+ /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
+
+ if (!q_len) {
+ res = -ENOTCONN;
+ goto exit;
+ }
+
+ /* Get access to first message in receive queue */
+
+ buf = skb_peek(&sock->sk->sk_receive_queue);
+ msg = buf_msg(buf);
+ sz = msg_data_sz(msg);
+ err = msg_errcode(msg);
+
+ /* Complete connection setup for an implied connect */
+
+ if (unlikely(sock->state == SS_CONNECTING)) {
+ if ((res = auto_connect(sock, tsock, msg)))
+ goto exit;
+ }
+
+ /* Discard an empty non-errored message & try again */
+
+ if ((!sz) && (!err)) {
+ advance_queue(tsock);
+ goto restart;
+ }
+
+ /* Capture sender's address (optional) */
+
+ set_orig_addr(m, msg);
+
+ /* Capture ancillary data (optional) */
+
+ if ((res = anc_data_recv(m, msg, tsock->p)))
+ goto exit;
+
+ /* Capture message data (if valid) & compute return value (always) */
+
+ if (!err) {
+ if (unlikely(buf_len < sz)) {
+ sz = buf_len;
+ m->msg_flags |= MSG_TRUNC;
+ }
+ if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
+ sz))) {
+ res = -EFAULT;
+ goto exit;
+ }
+ res = sz;
+ } else {
+ if ((sock->state == SS_READY) ||
+ ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
+ res = 0;
+ else
+ res = -ECONNRESET;
+ }
+
+ /* Consume received message (optional) */
+
+ if (likely(!(flags & MSG_PEEK))) {
+ if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+ tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+ advance_queue(tsock);
+ }
+exit:
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * recv_stream - receive stream-oriented data
+ * @iocb: (unused)
+ * @m: descriptor for message info
+ * @buf_len: total size of user buffer area
+ * @flags: receive flags
+ *
+ * Used for SOCK_STREAM messages only. If not enough data is available
+ * will optionally wait for more; never truncates data.
+ *
+ * Returns size of returned message data, errno otherwise
+ */
+
+static int recv_stream(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *m, size_t buf_len, int flags)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ unsigned int q_len;
+ unsigned int sz;
+ int sz_to_copy;
+ int sz_copied = 0;
+ int needed;
+ char *crs = m->msg_iov->iov_base;
+ unsigned char *buf_crs;
+ u32 err;
+ int res;
+
+ /* Currently doesn't support receiving into multiple iovec entries */
+
+ if (m->msg_iovlen != 1)
+ return -EOPNOTSUPP;
+
+ /* Catch invalid receive attempts */
+
+ if (unlikely(!buf_len))
+ return -EINVAL;
+
+ if (unlikely(sock->state == SS_DISCONNECTING)) {
+ if (skb_queue_len(&sock->sk->sk_receive_queue) == 0)
+ return -ENOTCONN;
+ } else if (unlikely(sock->state != SS_CONNECTED))
+ return -ENOTCONN;
+
+ /* Look for a message in receive queue; wait if necessary */
+
+ if (unlikely(down_interruptible(&tsock->sem)))
+ return -ERESTARTSYS;
+
+restart:
+ if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+ (flags & MSG_DONTWAIT))) {
+ res = (sz_copied == 0) ? -EWOULDBLOCK : 0;
+ goto exit;
+ }
+
+ if ((res = wait_event_interruptible(
+ *sock->sk->sk_sleep,
+ ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
+ (sock->state == SS_DISCONNECTING))) )) {
+ goto exit;
+ }
+
+ /* Catch attempt to receive on an already terminated connection */
+ /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */
+
+ if (!q_len) {
+ res = -ENOTCONN;
+ goto exit;
+ }
+
+ /* Get access to first message in receive queue */
+
+ buf = skb_peek(&sock->sk->sk_receive_queue);
+ msg = buf_msg(buf);
+ sz = msg_data_sz(msg);
+ err = msg_errcode(msg);
+
+ /* Discard an empty non-errored message & try again */
+
+ if ((!sz) && (!err)) {
+ advance_queue(tsock);
+ goto restart;
+ }
+
+ /* Optionally capture sender's address & ancillary data of first msg */
+
+ if (sz_copied == 0) {
+ set_orig_addr(m, msg);
+ if ((res = anc_data_recv(m, msg, tsock->p)))
+ goto exit;
+ }
+
+ /* Capture message data (if valid) & compute return value (always) */
+
+ if (!err) {
+ buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
+ sz = buf->tail - buf_crs;
+
+ needed = (buf_len - sz_copied);
+ sz_to_copy = (sz <= needed) ? sz : needed;
+ if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
+ res = -EFAULT;
+ goto exit;
+ }
+ sz_copied += sz_to_copy;
+
+ if (sz_to_copy < sz) {
+ if (!(flags & MSG_PEEK))
+ TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
+ goto exit;
+ }
+
+ crs += sz_to_copy;
+ } else {
+ if (sz_copied != 0)
+ goto exit; /* can't add error msg to valid data */
+
+ if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)
+ res = 0;
+ else
+ res = -ECONNRESET;
+ }
+
+ /* Consume received message (optional) */
+
+ if (likely(!(flags & MSG_PEEK))) {
+ if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
+ tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
+ advance_queue(tsock);
+ }
+
+ /* Loop around if more data is required */
+
+ if ((sz_copied < buf_len) /* didn't get all requested data */
+ && (flags & MSG_WAITALL) /* ... and need to wait for more */
+ && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */
+ && (!err) /* ... and haven't reached a FIN */
+ )
+ goto restart;
+
+exit:
+ up(&tsock->sem);
+ return res ? res : sz_copied;
+}
+
+/**
+ * queue_overloaded - test if queue overload condition exists
+ * @queue_size: current size of queue
+ * @base: nominal maximum size of queue
+ * @msg: message to be added to queue
+ *
+ * Returns 1 if queue is currently overloaded, 0 otherwise
+ */
+
+static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg)
+{
+ u32 threshold;
+ u32 imp = msg_importance(msg);
+
+ if (imp == TIPC_LOW_IMPORTANCE)
+ threshold = base;
+ else if (imp == TIPC_MEDIUM_IMPORTANCE)
+ threshold = base * 2;
+ else if (imp == TIPC_HIGH_IMPORTANCE)
+ threshold = base * 100;
+ else
+ return 0;
+
+ if (msg_connected(msg))
+ threshold *= 4;
+
+ return (queue_size > threshold);
+}
+
+/**
+ * async_disconnect - wrapper function used to disconnect port
+ * @portref: TIPC port reference (passed as pointer-sized value)
+ */
+
+static void async_disconnect(unsigned long portref)
+{
+ tipc_disconnect((u32)portref);
+}
+
+/**
+ * dispatch - handle arriving message
+ * @tport: TIPC port that received message
+ * @buf: message
+ *
+ * Called with port locked. Must not take socket lock to avoid deadlock risk.
+ *
+ * Returns TIPC error status code (TIPC_OK if message is not to be rejected)
+ */
+
+static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
+ struct socket *sock;
+ u32 recv_q_len;
+
+ /* Reject message if socket is closing */
+
+ if (!tsock)
+ return TIPC_ERR_NO_PORT;
+
+ /* Reject message if it is wrong sort of message for socket */
+
+ /*
+ * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
+ * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
+ * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
+ */
+ sock = tsock->sk.sk_socket;
+ if (sock->state == SS_READY) {
+ if (msg_connected(msg)) {
+ msg_dbg(msg, "dispatch filter 1\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ } else {
+ if (msg_mcast(msg)) {
+ msg_dbg(msg, "dispatch filter 2\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ if (sock->state == SS_CONNECTED) {
+ if (!msg_connected(msg)) {
+ msg_dbg(msg, "dispatch filter 3\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ }
+ else if (sock->state == SS_CONNECTING) {
+ if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
+ msg_dbg(msg, "dispatch filter 4\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ }
+ else if (sock->state == SS_LISTENING) {
+ if (msg_connected(msg) || msg_errcode(msg)) {
+ msg_dbg(msg, "dispatch filter 5\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ }
+ else if (sock->state == SS_DISCONNECTING) {
+ msg_dbg(msg, "dispatch filter 6\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ else /* (sock->state == SS_UNCONNECTED) */ {
+ if (msg_connected(msg) || msg_errcode(msg)) {
+ msg_dbg(msg, "dispatch filter 7\n");
+ return TIPC_ERR_NO_PORT;
+ }
+ }
+ }
+
+ /* Reject message if there isn't room to queue it */
+
+ if (unlikely((u32)atomic_read(&tipc_queue_size) >
+ OVERLOAD_LIMIT_BASE)) {
+ if (queue_overloaded(atomic_read(&tipc_queue_size),
+ OVERLOAD_LIMIT_BASE, msg))
+ return TIPC_ERR_OVERLOAD;
+ }
+ recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
+ if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
+ if (queue_overloaded(recv_q_len,
+ OVERLOAD_LIMIT_BASE / 2, msg))
+ return TIPC_ERR_OVERLOAD;
+ }
+
+ /* Initiate connection termination for an incoming 'FIN' */
+
+ if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
+ sock->state = SS_DISCONNECTING;
+ /* Note: Use signal since port lock is already taken! */
+ tipc_k_signal((Handler)async_disconnect, tport->ref);
+ }
+
+ /* Enqueue message (finally!) */
+
+ msg_dbg(msg,"<DISP<: ");
+ TIPC_SKB_CB(buf)->handle = msg_data(msg);
+ atomic_inc(&tipc_queue_size);
+ skb_queue_tail(&sock->sk->sk_receive_queue, buf);
+
+ wake_up_interruptible(sock->sk->sk_sleep);
+ return TIPC_OK;
+}
+
+/**
+ * wakeupdispatch - wake up port after congestion
+ * @tport: port to wakeup
+ *
+ * Called with port lock on.
+ */
+
+static void wakeupdispatch(struct tipc_port *tport)
+{
+ struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
+
+ wake_up_interruptible(tsock->sk.sk_sleep);
+}
+
+/**
+ * connect - establish a connection to another TIPC port
+ * @sock: socket structure
+ * @dest: socket address for destination port
+ * @destlen: size of socket address data structure
+ * @flags: (unused)
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
+ int flags)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
+ struct msghdr m = {0,};
+ struct sk_buff *buf;
+ struct tipc_msg *msg;
+ int res;
+
+ /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */
+
+ if (sock->state == SS_READY)
+ return -EOPNOTSUPP;
+
+ /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */
+ if (sock->state == SS_LISTENING)
+ return -EOPNOTSUPP;
+ if (sock->state == SS_CONNECTING)
+ return -EALREADY;
+ if (sock->state != SS_UNCONNECTED)
+ return -EISCONN;
+
+ if ((dst->family != AF_TIPC) ||
+ ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID)))
+ return -EINVAL;
+
+ /* Send a 'SYN-' to destination */
+
+ m.msg_name = dest;
+ if ((res = send_msg(0, sock, &m, 0)) < 0) {
+ sock->state = SS_DISCONNECTING;
+ return res;
+ }
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ /* Wait for destination's 'ACK' response */
+
+ res = wait_event_interruptible_timeout(*sock->sk->sk_sleep,
+ skb_queue_len(&sock->sk->sk_receive_queue),
+ sock->sk->sk_rcvtimeo);
+ buf = skb_peek(&sock->sk->sk_receive_queue);
+ if (res > 0) {
+ msg = buf_msg(buf);
+ res = auto_connect(sock, tsock, msg);
+ if (!res) {
+ if (dst->addrtype == TIPC_ADDR_NAME) {
+ tsock->p->conn_type = dst->addr.name.name.type;
+ tsock->p->conn_instance = dst->addr.name.name.instance;
+ }
+ if (!msg_data_sz(msg))
+ advance_queue(tsock);
+ }
+ } else {
+ if (res == 0) {
+ res = -ETIMEDOUT;
+ } else
+ { /* leave "res" unchanged */ }
+ sock->state = SS_DISCONNECTING;
+ }
+
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * listen - allow socket to listen for incoming connections
+ * @sock: socket structure
+ * @len: (unused)
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int listen(struct socket *sock, int len)
+{
+ /* REQUIRES SOCKET LOCKING OF SOME SORT? */
+
+ if (sock->state == SS_READY)
+ return -EOPNOTSUPP;
+ if (sock->state != SS_UNCONNECTED)
+ return -EINVAL;
+ sock->state = SS_LISTENING;
+ return 0;
+}
+
+/**
+ * accept - wait for connection request
+ * @sock: listening socket
+ * @newsock: new socket that is to be connected
+ * @flags: file-related flags associated with socket
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int accept(struct socket *sock, struct socket *newsock, int flags)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ struct sk_buff *buf;
+ int res = -EFAULT;
+
+ if (sock->state == SS_READY)
+ return -EOPNOTSUPP;
+ if (sock->state != SS_LISTENING)
+ return -EINVAL;
+
+ if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
+ (flags & O_NONBLOCK)))
+ return -EWOULDBLOCK;
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ if (wait_event_interruptible(*sock->sk->sk_sleep,
+ skb_queue_len(&sock->sk->sk_receive_queue))) {
+ res = -ERESTARTSYS;
+ goto exit;
+ }
+ buf = skb_peek(&sock->sk->sk_receive_queue);
+
+ res = tipc_create(newsock, 0);
+ if (!res) {
+ struct tipc_sock *new_tsock = tipc_sk(newsock->sk);
+ struct tipc_portid id;
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 new_ref = new_tsock->p->ref;
+
+ id.ref = msg_origport(msg);
+ id.node = msg_orignode(msg);
+ tipc_connect2port(new_ref, &id);
+ newsock->state = SS_CONNECTED;
+
+ tipc_set_portimportance(new_ref, msg_importance(msg));
+ if (msg_named(msg)) {
+ new_tsock->p->conn_type = msg_nametype(msg);
+ new_tsock->p->conn_instance = msg_nameinst(msg);
+ }
+
+ /*
+ * Respond to 'SYN-' by discarding it & returning 'ACK'-.
+ * Respond to 'SYN+' by queuing it on new socket.
+ */
+
+ msg_dbg(msg,"<ACC<: ");
+ if (!msg_data_sz(msg)) {
+ struct msghdr m = {0,};
+
+ send_packet(0, newsock, &m, 0);
+ advance_queue(tsock);
+ } else {
+ sock_lock(tsock);
+ skb_dequeue(&sock->sk->sk_receive_queue);
+ sock_unlock(tsock);
+ skb_queue_head(&newsock->sk->sk_receive_queue, buf);
+ }
+ }
+exit:
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * shutdown - shutdown socket connection
+ * @sock: socket structure
+ * @how: direction to close (always treated as read + write)
+ *
+ * Terminates connection (if necessary), then purges socket's receive queue.
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int shutdown(struct socket *sock, int how)
+{
+ struct tipc_sock* tsock = tipc_sk(sock->sk);
+ struct sk_buff *buf;
+ int res;
+
+ /* Could return -EINVAL for an invalid "how", but why bother? */
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ sock_lock(tsock);
+
+ switch (sock->state) {
+ case SS_CONNECTED:
+
+ /* Send 'FIN+' or 'FIN-' message to peer */
+
+ sock_unlock(tsock);
+restart:
+ if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+ atomic_dec(&tipc_queue_size);
+ if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
+ buf_discard(buf);
+ goto restart;
+ }
+ tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
+ }
+ else {
+ tipc_shutdown(tsock->p->ref);
+ }
+ sock_lock(tsock);
+
+ /* fall through */
+
+ case SS_DISCONNECTING:
+
+ /* Discard any unreceived messages */
+
+ while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
+ atomic_dec(&tipc_queue_size);
+ buf_discard(buf);
+ }
+ tsock->p->conn_unacked = 0;
+
+ /* fall through */
+
+ case SS_CONNECTING:
+ sock->state = SS_DISCONNECTING;
+ res = 0;
+ break;
+
+ default:
+ res = -ENOTCONN;
+ }
+
+ sock_unlock(tsock);
+
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * setsockopt - set socket option
+ * @sock: socket structure
+ * @lvl: option level
+ * @opt: option identifier
+ * @ov: pointer to new option value
+ * @ol: length of option value
+ *
+ * For stream sockets only, accepts and ignores all IPPROTO_TCP options
+ * (to ease compatibility).
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ u32 value;
+ int res;
+
+ if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
+ return 0;
+ if (lvl != SOL_TIPC)
+ return -ENOPROTOOPT;
+ if (ol < sizeof(value))
+ return -EINVAL;
+ if ((res = get_user(value, (u32 *)ov)))
+ return res;
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ switch (opt) {
+ case TIPC_IMPORTANCE:
+ res = tipc_set_portimportance(tsock->p->ref, value);
+ break;
+ case TIPC_SRC_DROPPABLE:
+ if (sock->type != SOCK_STREAM)
+ res = tipc_set_portunreliable(tsock->p->ref, value);
+ else
+ res = -ENOPROTOOPT;
+ break;
+ case TIPC_DEST_DROPPABLE:
+ res = tipc_set_portunreturnable(tsock->p->ref, value);
+ break;
+ case TIPC_CONN_TIMEOUT:
+ sock->sk->sk_rcvtimeo = (value * HZ / 1000);
+ break;
+ default:
+ res = -EINVAL;
+ }
+
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * getsockopt - get socket option
+ * @sock: socket structure
+ * @lvl: option level
+ * @opt: option identifier
+ * @ov: receptacle for option value
+ * @ol: receptacle for length of option value
+ *
+ * For stream sockets only, returns 0 length result for all IPPROTO_TCP options
+ * (to ease compatibility).
+ *
+ * Returns 0 on success, errno otherwise
+ */
+
+static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol)
+{
+ struct tipc_sock *tsock = tipc_sk(sock->sk);
+ int len;
+ u32 value;
+ int res;
+
+ if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM))
+ return put_user(0, ol);
+ if (lvl != SOL_TIPC)
+ return -ENOPROTOOPT;
+ if ((res = get_user(len, ol)))
+ return res;
+
+ if (down_interruptible(&tsock->sem))
+ return -ERESTARTSYS;
+
+ switch (opt) {
+ case TIPC_IMPORTANCE:
+ res = tipc_portimportance(tsock->p->ref, &value);
+ break;
+ case TIPC_SRC_DROPPABLE:
+ res = tipc_portunreliable(tsock->p->ref, &value);
+ break;
+ case TIPC_DEST_DROPPABLE:
+ res = tipc_portunreturnable(tsock->p->ref, &value);
+ break;
+ case TIPC_CONN_TIMEOUT:
+ value = (sock->sk->sk_rcvtimeo * 1000) / HZ;
+ break;
+ default:
+ res = -EINVAL;
+ }
+
+ if (res) {
+ /* "get" failed */
+ }
+ else if (len < sizeof(value)) {
+ res = -EINVAL;
+ }
+ else if ((res = copy_to_user(ov, &value, sizeof(value)))) {
+ /* couldn't return value */
+ }
+ else {
+ res = put_user(sizeof(value), ol);
+ }
+
+ up(&tsock->sem);
+ return res;
+}
+
+/**
+ * Placeholders for non-implemented functionality
+ *
+ * Returns error code (POSIX-compliant where defined)
+ */
+
+static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
+{
+ return -EINVAL;
+}
+
+static int no_mmap(struct file *file, struct socket *sock,
+ struct vm_area_struct *vma)
+{
+ return -EINVAL;
+}
+static ssize_t no_sendpage(struct socket *sock, struct page *page,
+ int offset, size_t size, int flags)
+{
+ return -EINVAL;
+}
+
+static int no_skpair(struct socket *s1, struct socket *s2)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * Protocol switches for the various types of TIPC sockets
+ */
+
+static struct proto_ops msg_ops = {
+ .owner = THIS_MODULE,
+ .family = AF_TIPC,
+ .release = release,
+ .bind = bind,
+ .connect = connect,
+ .socketpair = no_skpair,
+ .accept = accept,
+ .getname = get_name,
+ .poll = poll,
+ .ioctl = ioctl,
+ .listen = listen,
+ .shutdown = shutdown,
+ .setsockopt = setsockopt,
+ .getsockopt = getsockopt,
+ .sendmsg = send_msg,
+ .recvmsg = recv_msg,
+ .mmap = no_mmap,
+ .sendpage = no_sendpage
+};
+
+static struct proto_ops packet_ops = {
+ .owner = THIS_MODULE,
+ .family = AF_TIPC,
+ .release = release,
+ .bind = bind,
+ .connect = connect,
+ .socketpair = no_skpair,
+ .accept = accept,
+ .getname = get_name,
+ .poll = poll,
+ .ioctl = ioctl,
+ .listen = listen,
+ .shutdown = shutdown,
+ .setsockopt = setsockopt,
+ .getsockopt = getsockopt,
+ .sendmsg = send_packet,
+ .recvmsg = recv_msg,
+ .mmap = no_mmap,
+ .sendpage = no_sendpage
+};
+
+static struct proto_ops stream_ops = {
+ .owner = THIS_MODULE,
+ .family = AF_TIPC,
+ .release = release,
+ .bind = bind,
+ .connect = connect,
+ .socketpair = no_skpair,
+ .accept = accept,
+ .getname = get_name,
+ .poll = poll,
+ .ioctl = ioctl,
+ .listen = listen,
+ .shutdown = shutdown,
+ .setsockopt = setsockopt,
+ .getsockopt = getsockopt,
+ .sendmsg = send_stream,
+ .recvmsg = recv_stream,
+ .mmap = no_mmap,
+ .sendpage = no_sendpage
+};
+
+static struct net_proto_family tipc_family_ops = {
+ .owner = THIS_MODULE,
+ .family = AF_TIPC,
+ .create = tipc_create
+};
+
+static struct proto tipc_proto = {
+ .name = "TIPC",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct tipc_sock)
+};
+
+/**
+ * tipc_socket_init - initialize TIPC socket interface
+ *
+ * Returns 0 on success, errno otherwise
+ */
+int tipc_socket_init(void)
+{
+ int res;
+
+ res = proto_register(&tipc_proto, 1);
+ if (res) {
+ err("Failed to register TIPC protocol type\n");
+ goto out;
+ }
+
+ res = sock_register(&tipc_family_ops);
+ if (res) {
+ err("Failed to register TIPC socket type\n");
+ proto_unregister(&tipc_proto);
+ goto out;
+ }
+
+ sockets_enabled = 1;
+ out:
+ return res;
+}
+
+/**
+ * tipc_socket_stop - stop TIPC socket interface
+ */
+void tipc_socket_stop(void)
+{
+ if (!sockets_enabled)
+ return;
+
+ sockets_enabled = 0;
+ sock_unregister(tipc_family_ops.family);
+ proto_unregister(&tipc_proto);
+}
+
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
new file mode 100644
index 000000000000..5ff38b9f3194
--- /dev/null
+++ b/net/tipc/subscr.c
@@ -0,0 +1,527 @@
+/*
+ * net/tipc/subscr.c: TIPC subscription service
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "dbg.h"
+#include "subscr.h"
+#include "name_table.h"
+#include "ref.h"
+
+/**
+ * struct subscriber - TIPC network topology subscriber
+ * @ref: object reference to subscriber object itself
+ * @lock: pointer to spinlock controlling access to subscriber object
+ * @subscriber_list: adjacent subscribers in top. server's list of subscribers
+ * @subscription_list: list of subscription objects for this subscriber
+ * @port_ref: object reference to port used to communicate with subscriber
+ * @swap: indicates if subscriber uses opposite endianness in its messages
+ */
+
+struct subscriber {
+ u32 ref;
+ spinlock_t *lock;
+ struct list_head subscriber_list;
+ struct list_head subscription_list;
+ u32 port_ref;
+ int swap;
+};
+
+/**
+ * struct top_srv - TIPC network topology subscription service
+ * @user_ref: TIPC userid of subscription service
+ * @setup_port: reference to TIPC port that handles subscription requests
+ * @subscription_count: number of active subscriptions (not subscribers!)
+ * @subscriber_list: list of ports subscribing to service
+ * @lock: spinlock govering access to subscriber list
+ */
+
+struct top_srv {
+ u32 user_ref;
+ u32 setup_port;
+ atomic_t subscription_count;
+ struct list_head subscriber_list;
+ spinlock_t lock;
+};
+
+static struct top_srv topsrv = { 0 };
+
+/**
+ * htohl - convert value to endianness used by destination
+ * @in: value to convert
+ * @swap: non-zero if endianness must be reversed
+ *
+ * Returns converted value
+ */
+
+static inline u32 htohl(u32 in, int swap)
+{
+ char *c = (char *)&in;
+
+ return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in;
+}
+
+/**
+ * subscr_send_event - send a message containing a tipc_event to the subscriber
+ */
+
+static void subscr_send_event(struct subscription *sub,
+ u32 found_lower,
+ u32 found_upper,
+ u32 event,
+ u32 port_ref,
+ u32 node)
+{
+ struct iovec msg_sect;
+
+ msg_sect.iov_base = (void *)&sub->evt;
+ msg_sect.iov_len = sizeof(struct tipc_event);
+
+ sub->evt.event = htohl(event, sub->owner->swap);
+ sub->evt.found_lower = htohl(found_lower, sub->owner->swap);
+ sub->evt.found_upper = htohl(found_upper, sub->owner->swap);
+ sub->evt.port.ref = htohl(port_ref, sub->owner->swap);
+ sub->evt.port.node = htohl(node, sub->owner->swap);
+ tipc_send(sub->owner->port_ref, 1, &msg_sect);
+}
+
+/**
+ * tipc_subscr_overlap - test for subscription overlap with the given values
+ *
+ * Returns 1 if there is overlap, otherwise 0.
+ */
+
+int tipc_subscr_overlap(struct subscription *sub,
+ u32 found_lower,
+ u32 found_upper)
+
+{
+ if (found_lower < sub->seq.lower)
+ found_lower = sub->seq.lower;
+ if (found_upper > sub->seq.upper)
+ found_upper = sub->seq.upper;
+ if (found_lower > found_upper)
+ return 0;
+ return 1;
+}
+
+/**
+ * tipc_subscr_report_overlap - issue event if there is subscription overlap
+ *
+ * Protected by nameseq.lock in name_table.c
+ */
+
+void tipc_subscr_report_overlap(struct subscription *sub,
+ u32 found_lower,
+ u32 found_upper,
+ u32 event,
+ u32 port_ref,
+ u32 node,
+ int must)
+{
+ dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower,
+ sub->seq.upper, found_lower, found_upper);
+ if (!tipc_subscr_overlap(sub, found_lower, found_upper))
+ return;
+ if (!must && (sub->filter != TIPC_SUB_PORTS))
+ return;
+ subscr_send_event(sub, found_lower, found_upper, event, port_ref, node);
+}
+
+/**
+ * subscr_timeout - subscription timeout has occurred
+ */
+
+static void subscr_timeout(struct subscription *sub)
+{
+ struct subscriber *subscriber;
+ u32 subscriber_ref;
+
+ /* Validate subscriber reference (in case subscriber is terminating) */
+
+ subscriber_ref = sub->owner->ref;
+ subscriber = (struct subscriber *)tipc_ref_lock(subscriber_ref);
+ if (subscriber == NULL)
+ return;
+
+ /* Unlink subscription from name table */
+
+ tipc_nametbl_unsubscribe(sub);
+
+ /* Notify subscriber of timeout, then unlink subscription */
+
+ subscr_send_event(sub,
+ sub->evt.s.seq.lower,
+ sub->evt.s.seq.upper,
+ TIPC_SUBSCR_TIMEOUT,
+ 0,
+ 0);
+ list_del(&sub->subscription_list);
+
+ /* Now destroy subscription */
+
+ tipc_ref_unlock(subscriber_ref);
+ k_term_timer(&sub->timer);
+ kfree(sub);
+ atomic_dec(&topsrv.subscription_count);
+}
+
+/**
+ * subscr_terminate - terminate communication with a subscriber
+ *
+ * Called with subscriber locked. Routine must temporarily release this lock
+ * to enable subscription timeout routine(s) to finish without deadlocking;
+ * the lock is then reclaimed to allow caller to release it upon return.
+ * (This should work even in the unlikely event some other thread creates
+ * a new object reference in the interim that uses this lock; this routine will
+ * simply wait for it to be released, then claim it.)
+ */
+
+static void subscr_terminate(struct subscriber *subscriber)
+{
+ struct subscription *sub;
+ struct subscription *sub_temp;
+
+ /* Invalidate subscriber reference */
+
+ tipc_ref_discard(subscriber->ref);
+ spin_unlock_bh(subscriber->lock);
+
+ /* Destroy any existing subscriptions for subscriber */
+
+ list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
+ subscription_list) {
+ if (sub->timeout != TIPC_WAIT_FOREVER) {
+ k_cancel_timer(&sub->timer);
+ k_term_timer(&sub->timer);
+ }
+ tipc_nametbl_unsubscribe(sub);
+ list_del(&sub->subscription_list);
+ dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n",
+ sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber);
+ kfree(sub);
+ atomic_dec(&topsrv.subscription_count);
+ }
+
+ /* Sever connection to subscriber */
+
+ tipc_shutdown(subscriber->port_ref);
+ tipc_deleteport(subscriber->port_ref);
+
+ /* Remove subscriber from topology server's subscriber list */
+
+ spin_lock_bh(&topsrv.lock);
+ list_del(&subscriber->subscriber_list);
+ spin_unlock_bh(&topsrv.lock);
+
+ /* Now destroy subscriber */
+
+ spin_lock_bh(subscriber->lock);
+ kfree(subscriber);
+}
+
+/**
+ * subscr_subscribe - create subscription for subscriber
+ *
+ * Called with subscriber locked
+ */
+
+static void subscr_subscribe(struct tipc_subscr *s,
+ struct subscriber *subscriber)
+{
+ struct subscription *sub;
+
+ /* Refuse subscription if global limit exceeded */
+
+ if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
+ warn("Failed: max %u subscriptions\n", tipc_max_subscriptions);
+ subscr_terminate(subscriber);
+ return;
+ }
+
+ /* Allocate subscription object */
+
+ sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
+ if (sub == NULL) {
+ warn("Memory squeeze; ignoring subscription\n");
+ subscr_terminate(subscriber);
+ return;
+ }
+
+ /* Determine/update subscriber's endianness */
+
+ if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE))
+ subscriber->swap = 0;
+ else
+ subscriber->swap = 1;
+
+ /* Initialize subscription object */
+
+ memset(sub, 0, sizeof(*sub));
+ sub->seq.type = htohl(s->seq.type, subscriber->swap);
+ sub->seq.lower = htohl(s->seq.lower, subscriber->swap);
+ sub->seq.upper = htohl(s->seq.upper, subscriber->swap);
+ sub->timeout = htohl(s->timeout, subscriber->swap);
+ sub->filter = htohl(s->filter, subscriber->swap);
+ if ((((sub->filter != TIPC_SUB_PORTS)
+ && (sub->filter != TIPC_SUB_SERVICE)))
+ || (sub->seq.lower > sub->seq.upper)) {
+ warn("Rejecting illegal subscription %u,%u,%u\n",
+ sub->seq.type, sub->seq.lower, sub->seq.upper);
+ kfree(sub);
+ subscr_terminate(subscriber);
+ return;
+ }
+ memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr));
+ INIT_LIST_HEAD(&sub->subscription_list);
+ INIT_LIST_HEAD(&sub->nameseq_list);
+ list_add(&sub->subscription_list, &subscriber->subscription_list);
+ atomic_inc(&topsrv.subscription_count);
+ if (sub->timeout != TIPC_WAIT_FOREVER) {
+ k_init_timer(&sub->timer,
+ (Handler)subscr_timeout, (unsigned long)sub);
+ k_start_timer(&sub->timer, sub->timeout);
+ }
+ sub->owner = subscriber;
+ tipc_nametbl_subscribe(sub);
+}
+
+/**
+ * subscr_conn_shutdown_event - handle termination request from subscriber
+ */
+
+static void subscr_conn_shutdown_event(void *usr_handle,
+ u32 portref,
+ struct sk_buff **buf,
+ unsigned char const *data,
+ unsigned int size,
+ int reason)
+{
+ struct subscriber *subscriber;
+ spinlock_t *subscriber_lock;
+
+ subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle);
+ if (subscriber == NULL)
+ return;
+
+ subscriber_lock = subscriber->lock;
+ subscr_terminate(subscriber);
+ spin_unlock_bh(subscriber_lock);
+}
+
+/**
+ * subscr_conn_msg_event - handle new subscription request from subscriber
+ */
+
+static void subscr_conn_msg_event(void *usr_handle,
+ u32 port_ref,
+ struct sk_buff **buf,
+ const unchar *data,
+ u32 size)
+{
+ struct subscriber *subscriber;
+ spinlock_t *subscriber_lock;
+
+ subscriber = tipc_ref_lock((u32)(unsigned long)usr_handle);
+ if (subscriber == NULL)
+ return;
+
+ subscriber_lock = subscriber->lock;
+ if (size != sizeof(struct tipc_subscr))
+ subscr_terminate(subscriber);
+ else
+ subscr_subscribe((struct tipc_subscr *)data, subscriber);
+
+ spin_unlock_bh(subscriber_lock);
+}
+
+/**
+ * subscr_named_msg_event - handle request to establish a new subscriber
+ */
+
+static void subscr_named_msg_event(void *usr_handle,
+ u32 port_ref,
+ struct sk_buff **buf,
+ const unchar *data,
+ u32 size,
+ u32 importance,
+ struct tipc_portid const *orig,
+ struct tipc_name_seq const *dest)
+{
+ struct subscriber *subscriber;
+ struct iovec msg_sect = {0, 0};
+ spinlock_t *subscriber_lock;
+
+ dbg("subscr_named_msg_event: orig = %x own = %x,\n",
+ orig->node, tipc_own_addr);
+ if (size && (size != sizeof(struct tipc_subscr))) {
+ warn("Received tipc_subscr of invalid size\n");
+ return;
+ }
+
+ /* Create subscriber object */
+
+ subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
+ if (subscriber == NULL) {
+ warn("Memory squeeze; ignoring subscriber setup\n");
+ return;
+ }
+ memset(subscriber, 0, sizeof(struct subscriber));
+ INIT_LIST_HEAD(&subscriber->subscription_list);
+ INIT_LIST_HEAD(&subscriber->subscriber_list);
+ subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock);
+ if (subscriber->ref == 0) {
+ warn("Failed to acquire subscriber reference\n");
+ kfree(subscriber);
+ return;
+ }
+
+ /* Establish a connection to subscriber */
+
+ tipc_createport(topsrv.user_ref,
+ (void *)(unsigned long)subscriber->ref,
+ importance,
+ 0,
+ 0,
+ subscr_conn_shutdown_event,
+ 0,
+ 0,
+ subscr_conn_msg_event,
+ 0,
+ &subscriber->port_ref);
+ if (subscriber->port_ref == 0) {
+ warn("Memory squeeze; failed to create subscription port\n");
+ tipc_ref_discard(subscriber->ref);
+ kfree(subscriber);
+ return;
+ }
+ tipc_connect2port(subscriber->port_ref, orig);
+
+
+ /* Add subscriber to topology server's subscriber list */
+
+ tipc_ref_lock(subscriber->ref);
+ spin_lock_bh(&topsrv.lock);
+ list_add(&subscriber->subscriber_list, &topsrv.subscriber_list);
+ spin_unlock_bh(&topsrv.lock);
+
+ /*
+ * Subscribe now if message contains a subscription,
+ * otherwise send an empty response to complete connection handshaking
+ */
+
+ subscriber_lock = subscriber->lock;
+ if (size)
+ subscr_subscribe((struct tipc_subscr *)data, subscriber);
+ else
+ tipc_send(subscriber->port_ref, 1, &msg_sect);
+
+ spin_unlock_bh(subscriber_lock);
+}
+
+int tipc_subscr_start(void)
+{
+ struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV};
+ int res = -1;
+
+ memset(&topsrv, 0, sizeof (topsrv));
+ topsrv.lock = SPIN_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&topsrv.subscriber_list);
+
+ spin_lock_bh(&topsrv.lock);
+ res = tipc_attach(&topsrv.user_ref, 0, 0);
+ if (res) {
+ spin_unlock_bh(&topsrv.lock);
+ return res;
+ }
+
+ res = tipc_createport(topsrv.user_ref,
+ 0,
+ TIPC_CRITICAL_IMPORTANCE,
+ 0,
+ 0,
+ 0,
+ 0,
+ subscr_named_msg_event,
+ 0,
+ 0,
+ &topsrv.setup_port);
+ if (res)
+ goto failed;
+
+ res = tipc_nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq);
+ if (res)
+ goto failed;
+
+ spin_unlock_bh(&topsrv.lock);
+ return 0;
+
+failed:
+ err("Failed to create subscription service\n");
+ tipc_detach(topsrv.user_ref);
+ topsrv.user_ref = 0;
+ spin_unlock_bh(&topsrv.lock);
+ return res;
+}
+
+void tipc_subscr_stop(void)
+{
+ struct subscriber *subscriber;
+ struct subscriber *subscriber_temp;
+ spinlock_t *subscriber_lock;
+
+ if (topsrv.user_ref) {
+ tipc_deleteport(topsrv.setup_port);
+ list_for_each_entry_safe(subscriber, subscriber_temp,
+ &topsrv.subscriber_list,
+ subscriber_list) {
+ tipc_ref_lock(subscriber->ref);
+ subscriber_lock = subscriber->lock;
+ subscr_terminate(subscriber);
+ spin_unlock_bh(subscriber_lock);
+ }
+ tipc_detach(topsrv.user_ref);
+ topsrv.user_ref = 0;
+ }
+}
+
+
+int tipc_ispublished(struct tipc_name const *name)
+{
+ u32 domain = 0;
+
+ return(tipc_nametbl_translate(name->type, name->instance,&domain) != 0);
+}
+
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
new file mode 100644
index 000000000000..1e5090465d2e
--- /dev/null
+++ b/net/tipc/subscr.h
@@ -0,0 +1,80 @@
+/*
+ * net/tipc/subscr.h: Include file for TIPC subscription service
+ *
+ * Copyright (c) 2003-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_SUBSCR_H
+#define _TIPC_SUBSCR_H
+
+/**
+ * struct subscription - TIPC network topology subscription object
+ * @seq: name sequence associated with subscription
+ * @timeout: duration of subscription (in ms)
+ * @filter: event filtering to be done for subscription
+ * @evt: template for events generated by subscription
+ * @subscription_list: adjacent subscriptions in subscriber's subscription list
+ * @nameseq_list: adjacent subscriptions in name sequence's subscription list
+ * @timer_ref: reference to timer governing subscription duration (may be NULL)
+ * @owner: pointer to subscriber object associated with this subscription
+ */
+
+struct subscription {
+ struct tipc_name_seq seq;
+ u32 timeout;
+ u32 filter;
+ struct tipc_event evt;
+ struct list_head subscription_list;
+ struct list_head nameseq_list;
+ struct timer_list timer;
+ struct subscriber *owner;
+};
+
+int tipc_subscr_overlap(struct subscription * sub,
+ u32 found_lower,
+ u32 found_upper);
+
+void tipc_subscr_report_overlap(struct subscription * sub,
+ u32 found_lower,
+ u32 found_upper,
+ u32 event,
+ u32 port_ref,
+ u32 node,
+ int must_report);
+
+int tipc_subscr_start(void);
+
+void tipc_subscr_stop(void);
+
+
+#endif
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
new file mode 100644
index 000000000000..106200d76587
--- /dev/null
+++ b/net/tipc/user_reg.c
@@ -0,0 +1,265 @@
+/*
+ * net/tipc/user_reg.c: TIPC user registry code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2004-2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "user_reg.h"
+
+/*
+ * TIPC user registry keeps track of users of the tipc_port interface.
+ *
+ * The registry utilizes an array of "TIPC user" entries;
+ * a user's ID is the index of their associated array entry.
+ * Array entry 0 is not used, so userid 0 is not valid;
+ * TIPC sometimes uses this value to denote an anonymous user.
+ * The list of free entries is initially chained from last entry to entry 1.
+ */
+
+/**
+ * struct tipc_user - registered TIPC user info
+ * @next: index of next free registry entry (or -1 for an allocated entry)
+ * @callback: ptr to routine to call when TIPC mode changes (NULL if none)
+ * @usr_handle: user-defined value passed to callback routine
+ * @ports: list of user ports owned by the user
+ */
+
+struct tipc_user {
+ int next;
+ tipc_mode_event callback;
+ void *usr_handle;
+ struct list_head ports;
+};
+
+#define MAX_USERID 64
+#define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user))
+
+static struct tipc_user *users = 0;
+static u32 next_free_user = MAX_USERID + 1;
+static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
+
+/**
+ * reg_init - create TIPC user registry (but don't activate it)
+ *
+ * If registry has been pre-initialized it is left "as is".
+ * NOTE: This routine may be called when TIPC is inactive.
+ */
+
+static int reg_init(void)
+{
+ u32 i;
+
+ spin_lock_bh(&reg_lock);
+ if (!users) {
+ users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC);
+ if (users) {
+ memset(users, 0, USER_LIST_SIZE);
+ for (i = 1; i <= MAX_USERID; i++) {
+ users[i].next = i - 1;
+ }
+ next_free_user = MAX_USERID;
+ }
+ }
+ spin_unlock_bh(&reg_lock);
+ return users ? TIPC_OK : -ENOMEM;
+}
+
+/**
+ * reg_callback - inform TIPC user about current operating mode
+ */
+
+static void reg_callback(struct tipc_user *user_ptr)
+{
+ tipc_mode_event cb;
+ void *arg;
+
+ spin_lock_bh(&reg_lock);
+ cb = user_ptr->callback;
+ arg = user_ptr->usr_handle;
+ spin_unlock_bh(&reg_lock);
+
+ if (cb)
+ cb(arg, tipc_mode, tipc_own_addr);
+}
+
+/**
+ * tipc_reg_start - activate TIPC user registry
+ */
+
+int tipc_reg_start(void)
+{
+ u32 u;
+ int res;
+
+ if ((res = reg_init()))
+ return res;
+
+ for (u = 1; u <= MAX_USERID; u++) {
+ if (users[u].callback)
+ tipc_k_signal((Handler)reg_callback,
+ (unsigned long)&users[u]);
+ }
+ return TIPC_OK;
+}
+
+/**
+ * tipc_reg_stop - shut down & delete TIPC user registry
+ */
+
+void tipc_reg_stop(void)
+{
+ int id;
+
+ if (!users)
+ return;
+
+ for (id = 1; id <= MAX_USERID; id++) {
+ if (users[id].callback)
+ reg_callback(&users[id]);
+ }
+ kfree(users);
+ users = 0;
+}
+
+/**
+ * tipc_attach - register a TIPC user
+ *
+ * NOTE: This routine may be called when TIPC is inactive.
+ */
+
+int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle)
+{
+ struct tipc_user *user_ptr;
+
+ if ((tipc_mode == TIPC_NOT_RUNNING) && !cb)
+ return -ENOPROTOOPT;
+ if (!users)
+ reg_init();
+
+ spin_lock_bh(&reg_lock);
+ if (!next_free_user) {
+ spin_unlock_bh(&reg_lock);
+ return -EBUSY;
+ }
+ user_ptr = &users[next_free_user];
+ *userid = next_free_user;
+ next_free_user = user_ptr->next;
+ user_ptr->next = -1;
+ spin_unlock_bh(&reg_lock);
+
+ user_ptr->callback = cb;
+ user_ptr->usr_handle = usr_handle;
+ INIT_LIST_HEAD(&user_ptr->ports);
+ atomic_inc(&tipc_user_count);
+
+ if (cb && (tipc_mode != TIPC_NOT_RUNNING))
+ tipc_k_signal((Handler)reg_callback, (unsigned long)user_ptr);
+ return TIPC_OK;
+}
+
+/**
+ * tipc_detach - deregister a TIPC user
+ */
+
+void tipc_detach(u32 userid)
+{
+ struct tipc_user *user_ptr;
+ struct list_head ports_temp;
+ struct user_port *up_ptr, *temp_up_ptr;
+
+ if ((userid == 0) || (userid > MAX_USERID))
+ return;
+
+ spin_lock_bh(&reg_lock);
+ if ((!users) || (users[userid].next >= 0)) {
+ spin_unlock_bh(&reg_lock);
+ return;
+ }
+
+ user_ptr = &users[userid];
+ user_ptr->callback = NULL;
+ INIT_LIST_HEAD(&ports_temp);
+ list_splice(&user_ptr->ports, &ports_temp);
+ user_ptr->next = next_free_user;
+ next_free_user = userid;
+ spin_unlock_bh(&reg_lock);
+
+ atomic_dec(&tipc_user_count);
+
+ list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) {
+ tipc_deleteport(up_ptr->ref);
+ }
+}
+
+/**
+ * tipc_reg_add_port - register a user's driver port
+ */
+
+int tipc_reg_add_port(struct user_port *up_ptr)
+{
+ struct tipc_user *user_ptr;
+
+ if (up_ptr->user_ref == 0)
+ return TIPC_OK;
+ if (up_ptr->user_ref > MAX_USERID)
+ return -EINVAL;
+ if ((tipc_mode == TIPC_NOT_RUNNING) || !users )
+ return -ENOPROTOOPT;
+
+ spin_lock_bh(&reg_lock);
+ user_ptr = &users[up_ptr->user_ref];
+ list_add(&up_ptr->uport_list, &user_ptr->ports);
+ spin_unlock_bh(&reg_lock);
+ return TIPC_OK;
+}
+
+/**
+ * tipc_reg_remove_port - deregister a user's driver port
+ */
+
+int tipc_reg_remove_port(struct user_port *up_ptr)
+{
+ if (up_ptr->user_ref == 0)
+ return TIPC_OK;
+ if (up_ptr->user_ref > MAX_USERID)
+ return -EINVAL;
+ if (!users )
+ return -ENOPROTOOPT;
+
+ spin_lock_bh(&reg_lock);
+ list_del_init(&up_ptr->uport_list);
+ spin_unlock_bh(&reg_lock);
+ return TIPC_OK;
+}
+
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h
new file mode 100644
index 000000000000..d0e88794ed1b
--- /dev/null
+++ b/net/tipc/user_reg.h
@@ -0,0 +1,48 @@
+/*
+ * net/tipc/user_reg.h: Include file for TIPC user registry code
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_USER_REG_H
+#define _TIPC_USER_REG_H
+
+#include "port.h"
+
+int tipc_reg_start(void);
+void tipc_reg_stop(void);
+
+int tipc_reg_add_port(struct user_port *up_ptr);
+int tipc_reg_remove_port(struct user_port *up_ptr);
+
+#endif
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
new file mode 100644
index 000000000000..7c11f7f83a21
--- /dev/null
+++ b/net/tipc/zone.c
@@ -0,0 +1,169 @@
+/*
+ * net/tipc/zone.c: TIPC zone management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "core.h"
+#include "zone.h"
+#include "net.h"
+#include "addr.h"
+#include "node_subscr.h"
+#include "cluster.h"
+#include "node.h"
+
+struct _zone *tipc_zone_create(u32 addr)
+{
+ struct _zone *z_ptr = 0;
+ u32 z_num;
+
+ if (!tipc_addr_domain_valid(addr))
+ return 0;
+
+ z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
+ if (z_ptr != NULL) {
+ memset(z_ptr, 0, sizeof(*z_ptr));
+ z_num = tipc_zone(addr);
+ z_ptr->addr = tipc_addr(z_num, 0, 0);
+ tipc_net.zones[z_num] = z_ptr;
+ }
+ return z_ptr;
+}
+
+void tipc_zone_delete(struct _zone *z_ptr)
+{
+ u32 c_num;
+
+ if (!z_ptr)
+ return;
+ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
+ tipc_cltr_delete(z_ptr->clusters[c_num]);
+ }
+ kfree(z_ptr);
+}
+
+void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr)
+{
+ u32 c_num = tipc_cluster(c_ptr->addr);
+
+ assert(c_ptr->addr);
+ assert(c_num <= tipc_max_clusters);
+ assert(z_ptr->clusters[c_num] == 0);
+ z_ptr->clusters[c_num] = c_ptr;
+}
+
+void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router)
+{
+ u32 c_num;
+
+ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
+ if (z_ptr->clusters[c_num]) {
+ tipc_cltr_remove_as_router(z_ptr->clusters[c_num],
+ router);
+ }
+ }
+}
+
+void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest)
+{
+ u32 c_num;
+
+ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
+ if (z_ptr->clusters[c_num]) {
+ if (in_own_cluster(z_ptr->addr))
+ continue;
+ tipc_cltr_send_ext_routes(z_ptr->clusters[c_num], dest);
+ }
+ }
+}
+
+struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref)
+{
+ struct cluster *c_ptr;
+ struct node *n_ptr;
+ u32 c_num;
+
+ if (!z_ptr)
+ return 0;
+ c_ptr = z_ptr->clusters[tipc_cluster(addr)];
+ if (!c_ptr)
+ return 0;
+ n_ptr = tipc_cltr_select_node(c_ptr, ref);
+ if (n_ptr)
+ return n_ptr;
+
+ /* Links to any other clusters within this zone ? */
+ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
+ c_ptr = z_ptr->clusters[c_num];
+ if (!c_ptr)
+ return 0;
+ n_ptr = tipc_cltr_select_node(c_ptr, ref);
+ if (n_ptr)
+ return n_ptr;
+ }
+ return 0;
+}
+
+u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref)
+{
+ struct cluster *c_ptr;
+ u32 c_num;
+ u32 router;
+
+ if (!z_ptr)
+ return 0;
+ c_ptr = z_ptr->clusters[tipc_cluster(addr)];
+ router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0;
+ if (router)
+ return router;
+
+ /* Links to any other clusters within the zone? */
+ for (c_num = 1; c_num <= tipc_max_clusters; c_num++) {
+ c_ptr = z_ptr->clusters[c_num];
+ router = c_ptr ? tipc_cltr_select_router(c_ptr, ref) : 0;
+ if (router)
+ return router;
+ }
+ return 0;
+}
+
+
+u32 tipc_zone_next_node(u32 addr)
+{
+ struct cluster *c_ptr = tipc_cltr_find(addr);
+
+ if (c_ptr)
+ return tipc_cltr_next_node(c_ptr, addr);
+ return 0;
+}
+
diff --git a/net/tipc/zone.h b/net/tipc/zone.h
new file mode 100644
index 000000000000..267999c5a240
--- /dev/null
+++ b/net/tipc/zone.h
@@ -0,0 +1,71 @@
+/*
+ * net/tipc/zone.h: Include file for TIPC zone management routines
+ *
+ * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2005, Wind River Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders nor the names of its
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _TIPC_ZONE_H
+#define _TIPC_ZONE_H
+
+#include "node_subscr.h"
+#include "net.h"
+
+
+/**
+ * struct _zone - TIPC zone structure
+ * @addr: network address of zone
+ * @clusters: array of pointers to all clusters within zone
+ * @links: (used for inter-zone communication)
+ */
+
+struct _zone {
+ u32 addr;
+ struct cluster *clusters[2]; /* currently limited to just 1 cluster */
+ u32 links;
+};
+
+struct node *tipc_zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
+u32 tipc_zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
+void tipc_zone_remove_as_router(struct _zone *z_ptr, u32 router);
+void tipc_zone_send_external_routes(struct _zone *z_ptr, u32 dest);
+struct _zone *tipc_zone_create(u32 addr);
+void tipc_zone_delete(struct _zone *z_ptr);
+void tipc_zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
+u32 tipc_zone_next_node(u32 addr);
+
+static inline struct _zone *tipc_zone_find(u32 addr)
+{
+ return tipc_net.zones[tipc_zone(addr)];
+}
+
+#endif
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index acc73ba8bade..1b5989b1b670 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -121,7 +121,7 @@
int sysctl_unix_max_dgram_qlen = 10;
struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
-DEFINE_RWLOCK(unix_table_lock);
+DEFINE_SPINLOCK(unix_table_lock);
static atomic_t unix_nr_socks = ATOMIC_INIT(0);
#define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE])
@@ -130,7 +130,7 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
/*
* SMP locking strategy:
- * hash table is protected with rwlock unix_table_lock
+ * hash table is protected with spinlock unix_table_lock
* each socket state is protected by separate rwlock.
*/
@@ -214,16 +214,16 @@ static void __unix_insert_socket(struct hlist_head *list, struct sock *sk)
static inline void unix_remove_socket(struct sock *sk)
{
- write_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
__unix_remove_socket(sk);
- write_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
}
static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)
{
- write_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
__unix_insert_socket(list, sk);
- write_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
}
static struct sock *__unix_find_socket_byname(struct sockaddr_un *sunname,
@@ -250,11 +250,11 @@ static inline struct sock *unix_find_socket_byname(struct sockaddr_un *sunname,
{
struct sock *s;
- read_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
s = __unix_find_socket_byname(sunname, len, type, hash);
if (s)
sock_hold(s);
- read_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
return s;
}
@@ -263,7 +263,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
struct sock *s;
struct hlist_node *node;
- read_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
sk_for_each(s, node,
&unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
struct dentry *dentry = unix_sk(s)->dentry;
@@ -276,7 +276,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
}
s = NULL;
found:
- read_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
return s;
}
@@ -473,7 +473,7 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *,
static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
struct msghdr *, size_t);
-static struct proto_ops unix_stream_ops = {
+static const struct proto_ops unix_stream_ops = {
.family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release,
@@ -494,7 +494,7 @@ static struct proto_ops unix_stream_ops = {
.sendpage = sock_no_sendpage,
};
-static struct proto_ops unix_dgram_ops = {
+static const struct proto_ops unix_dgram_ops = {
.family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release,
@@ -515,7 +515,7 @@ static struct proto_ops unix_dgram_ops = {
.sendpage = sock_no_sendpage,
};
-static struct proto_ops unix_seqpacket_ops = {
+static const struct proto_ops unix_seqpacket_ops = {
.family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release,
@@ -564,7 +564,7 @@ static struct sock * unix_create1(struct socket *sock)
u = unix_sk(sk);
u->dentry = NULL;
u->mnt = NULL;
- rwlock_init(&u->lock);
+ spin_lock_init(&u->lock);
atomic_set(&u->inflight, sock ? 0 : -1);
init_MUTEX(&u->readsem); /* single task reading lock */
init_waitqueue_head(&u->peer_wait);
@@ -642,12 +642,12 @@ retry:
addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
addr->hash = unix_hash_fold(csum_partial((void*)addr->name, addr->len, 0));
- write_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
ordernum = (ordernum+1)&0xFFFFF;
if (__unix_find_socket_byname(addr->name, addr->len, sock->type,
addr->hash)) {
- write_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
/* Sanity yield. It is unusual case, but yet... */
if (!(ordernum&0xFF))
yield();
@@ -658,7 +658,7 @@ retry:
__unix_remove_socket(sk);
u->addr = addr;
__unix_insert_socket(&unix_socket_table[addr->hash], sk);
- write_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
err = 0;
out: up(&u->readsem);
@@ -784,14 +784,14 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
if (err)
goto out_mknod_dput;
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
dput(nd.dentry);
nd.dentry = dentry;
addr->hash = UNIX_HASH_SIZE;
}
- write_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
if (!sunaddr->sun_path[0]) {
err = -EADDRINUSE;
@@ -814,7 +814,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
__unix_insert_socket(list, sk);
out_unlock:
- write_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
out_up:
up(&u->readsem);
out:
@@ -823,7 +823,7 @@ out:
out_mknod_dput:
dput(dentry);
out_mknod_unlock:
- up(&nd.dentry->d_inode->i_sem);
+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
path_release(&nd);
out_mknod_parent:
if (err==-EEXIST)
@@ -1063,10 +1063,12 @@ restart:
/* Set credentials */
sk->sk_peercred = other->sk_peercred;
- sock_hold(newsk);
- unix_peer(sk) = newsk;
sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
+ sock_hold(newsk);
+
+ smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
+ unix_peer(sk) = newsk;
unix_state_wunlock(sk);
@@ -1414,7 +1416,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
} else {
sunaddr = NULL;
err = -ENOTCONN;
- other = unix_peer_get(sk);
+ other = unix_peer(sk);
if (!other)
goto out_err;
}
@@ -1476,7 +1478,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
other->sk_data_ready(other, size);
sent+=size;
}
- sock_put(other);
scm_destroy(siocb->scm);
siocb->scm = NULL;
@@ -1491,8 +1492,6 @@ pipe_err:
send_sig(SIGPIPE,current,0);
err = -EPIPE;
out_err:
- if (other)
- sock_put(other);
scm_destroy(siocb->scm);
siocb->scm = NULL;
return sent ? : err;
@@ -1860,7 +1859,7 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
default:
- err = dev_ioctl(cmd, (void __user *)arg);
+ err = -ENOIOCTLCMD;
break;
}
return err;
@@ -1917,7 +1916,7 @@ static struct sock *unix_seq_idx(int *iter, loff_t pos)
static void *unix_seq_start(struct seq_file *seq, loff_t *pos)
{
- read_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1);
}
@@ -1932,7 +1931,7 @@ static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
static void unix_seq_stop(struct seq_file *seq, void *v)
{
- read_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
}
static int unix_seq_show(struct seq_file *seq, void *v)
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 6ffc64e1712d..411802bd4d37 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -182,7 +182,7 @@ void unix_gc(void)
if (down_trylock(&unix_gc_sem))
return;
- read_lock(&unix_table_lock);
+ spin_lock(&unix_table_lock);
forall_unix_sockets(i, s)
{
@@ -301,7 +301,7 @@ void unix_gc(void)
}
u->gc_tree = GC_ORPHAN;
}
- read_unlock(&unix_table_lock);
+ spin_unlock(&unix_table_lock);
/*
* Here we are. Hitlist is filled. Die.
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 59fec59b2132..8b9bf4a763b5 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -36,6 +36,7 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/capability.h>
#include <linux/fcntl.h>
#include <linux/socket.h>
#include <linux/in.h>
@@ -181,7 +182,7 @@ struct wanpipe_opt
#endif
static int sk_count;
-extern struct proto_ops wanpipe_ops;
+extern const struct proto_ops wanpipe_ops;
static unsigned long find_free_critical;
static void wanpipe_unlink_driver(struct sock *sk);
@@ -1839,7 +1840,7 @@ static int wanpipe_ioctl(struct socket *sock, unsigned int cmd, unsigned long ar
#endif
default:
- return dev_ioctl(cmd,(void __user *) arg);
+ return -ENOIOCTLCMD;
}
/*NOTREACHED*/
}
@@ -2546,7 +2547,7 @@ static int wanpipe_connect(struct socket *sock, struct sockaddr *uaddr, int addr
return 0;
}
-struct proto_ops wanpipe_ops = {
+const struct proto_ops wanpipe_ops = {
.family = PF_WANPIPE,
.owner = THIS_MODULE,
.release = wanpipe_release,
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index bcf7b3faa76a..c34833dc7cc1 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -44,6 +44,7 @@
#include <linux/config.h>
#include <linux/stddef.h> /* offsetof(), etc. */
+#include <linux/capability.h>
#include <linux/errno.h> /* return codes */
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 020d73cc8414..72b6ff3299ba 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -37,6 +37,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -64,7 +65,7 @@ int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2;
HLIST_HEAD(x25_list);
DEFINE_RWLOCK(x25_list_lock);
-static struct proto_ops x25_proto_ops;
+static const struct proto_ops x25_proto_ops;
static struct x25_address null_x25_address = {" "};
@@ -540,12 +541,7 @@ static struct sock *x25_make_new(struct sock *osk)
sk->sk_state = TCP_ESTABLISHED;
sk->sk_sleep = osk->sk_sleep;
sk->sk_backlog_rcv = osk->sk_backlog_rcv;
-
- if (sock_flag(osk, SOCK_ZAPPED))
- sock_set_flag(sk, SOCK_ZAPPED);
-
- if (sock_flag(osk, SOCK_DBG))
- sock_set_flag(sk, SOCK_DBG);
+ sock_copy_flags(sk, osk);
ox25 = x25_sk(osk);
x25->t21 = ox25->t21;
@@ -1378,7 +1374,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
default:
- rc = dev_ioctl(cmd, argp);
+ rc = -ENOIOCTLCMD;
break;
}
@@ -1391,7 +1387,7 @@ static struct net_proto_family x25_family_ops = {
.owner = THIS_MODULE,
};
-static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release,
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 2f4531fcaca2..6ed3302312fb 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -540,8 +540,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
start = end;
}
}
- if (len)
- BUG();
+ BUG_ON(len);
}
EXPORT_SYMBOL_GPL(skb_icv_walk);
@@ -610,8 +609,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
start = end;
}
}
- if (len)
- BUG();
+ BUG_ON(len);
return elt;
}
EXPORT_SYMBOL_GPL(skb_to_sgvec);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d19e274b9c4a..077bbf9fb9b7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -10,7 +10,7 @@
* YOSHIFUJI Hideaki
* Split up af-specific portion
* Derek Atkins <derek@ihtfp.com> Add the post_input processor
- *
+ *
*/
#include <asm/bug.h>
@@ -22,6 +22,7 @@
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
+#include <linux/netfilter.h>
#include <linux/module.h>
#include <net/xfrm.h>
#include <net/ip.h>
@@ -247,15 +248,14 @@ EXPORT_SYMBOL(xfrm_policy_alloc);
void __xfrm_policy_destroy(struct xfrm_policy *policy)
{
- if (!policy->dead)
- BUG();
+ BUG_ON(!policy->dead);
- if (policy->bundles)
- BUG();
+ BUG_ON(policy->bundles);
if (del_timer(&policy->timer))
BUG();
+ security_xfrm_policy_free(policy);
kfree(policy);
}
EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -350,7 +350,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
write_lock_bh(&xfrm_policy_lock);
for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) {
- if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0) {
+ if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 &&
+ xfrm_sec_ctx_match(pol->security, policy->security)) {
if (excl) {
write_unlock_bh(&xfrm_policy_lock);
return -EEXIST;
@@ -416,14 +417,15 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
}
EXPORT_SYMBOL(xfrm_policy_insert);
-struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
- int delete)
+struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel,
+ struct xfrm_sec_ctx *ctx, int delete)
{
struct xfrm_policy *pol, **p;
write_lock_bh(&xfrm_policy_lock);
for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
- if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+ if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) &&
+ (xfrm_sec_ctx_match(ctx, pol->security))) {
xfrm_pol_hold(pol);
if (delete)
*p = pol->next;
@@ -438,7 +440,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
}
return pol;
}
-EXPORT_SYMBOL(xfrm_policy_bysel);
+EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
{
@@ -519,7 +521,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
/* Find policy to apply to this flow. */
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir,
void **objp, atomic_t **obj_refp)
{
struct xfrm_policy *pol;
@@ -533,9 +535,12 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
continue;
match = xfrm_selector_match(sel, fl, family);
+
if (match) {
- xfrm_pol_hold(pol);
- break;
+ if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) {
+ xfrm_pol_hold(pol);
+ break;
+ }
}
}
read_unlock_bh(&xfrm_policy_lock);
@@ -543,15 +548,37 @@ static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
*obj_refp = &pol->refcnt;
}
-static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
+static inline int policy_to_flow_dir(int dir)
+{
+ if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+ XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+ XFRM_POLICY_FWD == FLOW_DIR_FWD)
+ return dir;
+ switch (dir) {
+ default:
+ case XFRM_POLICY_IN:
+ return FLOW_DIR_IN;
+ case XFRM_POLICY_OUT:
+ return FLOW_DIR_OUT;
+ case XFRM_POLICY_FWD:
+ return FLOW_DIR_FWD;
+ };
+}
+
+static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid)
{
struct xfrm_policy *pol;
read_lock_bh(&xfrm_policy_lock);
if ((pol = sk->sk_policy[dir]) != NULL) {
- int match = xfrm_selector_match(&pol->selector, fl,
+ int match = xfrm_selector_match(&pol->selector, fl,
sk->sk_family);
+ int err = 0;
+
if (match)
+ err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir));
+
+ if (match && !err)
xfrm_pol_hold(pol);
else
pol = NULL;
@@ -624,6 +651,10 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
if (newp) {
newp->selector = old->selector;
+ if (security_xfrm_policy_clone(old, newp)) {
+ kfree(newp);
+ return NULL; /* ENOMEM */
+ }
newp->lft = old->lft;
newp->curlft = old->curlft;
newp->action = old->action;
@@ -735,22 +766,6 @@ xfrm_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx,
return err;
}
-static inline int policy_to_flow_dir(int dir)
-{
- if (XFRM_POLICY_IN == FLOW_DIR_IN &&
- XFRM_POLICY_OUT == FLOW_DIR_OUT &&
- XFRM_POLICY_FWD == FLOW_DIR_FWD)
- return dir;
- switch (dir) {
- default:
- case XFRM_POLICY_IN:
- return FLOW_DIR_IN;
- case XFRM_POLICY_OUT:
- return FLOW_DIR_OUT;
- case XFRM_POLICY_FWD:
- return FLOW_DIR_FWD;
- };
-}
static int stale_bundle(struct dst_entry *dst);
@@ -769,19 +784,20 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
int err;
u32 genid;
u16 family = dst_orig->ops->family;
+ u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
+ u32 sk_sid = security_sk_sid(sk, fl, dir);
restart:
genid = atomic_read(&flow_cache_genid);
policy = NULL;
if (sk && sk->sk_policy[1])
- policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+ policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid);
if (!policy) {
/* To accelerate a bit... */
if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
return 0;
- policy = flow_cache_lookup(fl, family,
- policy_to_flow_dir(XFRM_POLICY_OUT),
+ policy = flow_cache_lookup(fl, sk_sid, family, dir,
xfrm_policy_lookup);
}
@@ -934,8 +950,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
return start;
}
-static int
-_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
+int
+xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
{
struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
@@ -946,6 +962,7 @@ _decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
xfrm_policy_put_afinfo(afinfo);
return 0;
}
+EXPORT_SYMBOL(xfrm_decode_session);
static inline int secpath_has_tunnel(struct sec_path *sp, int k)
{
@@ -962,16 +979,21 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
{
struct xfrm_policy *pol;
struct flowi fl;
+ u8 fl_dir = policy_to_flow_dir(dir);
+ u32 sk_sid;
- if (_decode_session(skb, &fl, family) < 0)
+ if (xfrm_decode_session(skb, &fl, family) < 0)
return 0;
+ nf_nat_decode_session(skb, &fl, family);
+
+ sk_sid = security_sk_sid(sk, &fl, fl_dir);
/* First, check used SA against their selectors. */
if (skb->sp) {
int i;
for (i=skb->sp->len-1; i>=0; i--) {
- struct sec_decap_state *xvec = &(skb->sp->x[i]);
+ struct sec_decap_state *xvec = &(skb->sp->x[i]);
if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
return 0;
@@ -986,11 +1008,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
pol = NULL;
if (sk && sk->sk_policy[dir])
- pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+ pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid);
if (!pol)
- pol = flow_cache_lookup(&fl, family,
- policy_to_flow_dir(dir),
+ pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir,
xfrm_policy_lookup);
if (!pol)
@@ -1035,7 +1056,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
struct flowi fl;
- if (_decode_session(skb, &fl, family) < 0)
+ if (xfrm_decode_session(skb, &fl, family) < 0)
return 0;
return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 479effc97666..e12d0be5f976 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -10,7 +10,7 @@
* Split up af-specific functions
* Derek Atkins <derek@ihtfp.com>
* Add UDP Encapsulation
- *
+ *
*/
#include <linux/workqueue.h>
@@ -70,6 +70,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
x->type->destructor(x);
xfrm_put_type(x->type);
}
+ security_xfrm_state_free(x);
kfree(x);
}
@@ -343,7 +344,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
selector.
*/
if (x->km.state == XFRM_STATE_VALID) {
- if (!xfrm_selector_match(&x->sel, fl, family))
+ if (!xfrm_selector_match(&x->sel, fl, family) ||
+ !xfrm_sec_ctx_match(pol->security, x->security))
continue;
if (!best ||
best->km.dying > x->km.dying ||
@@ -354,7 +356,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
acquire_in_progress = 1;
} else if (x->km.state == XFRM_STATE_ERROR ||
x->km.state == XFRM_STATE_EXPIRED) {
- if (xfrm_selector_match(&x->sel, fl, family))
+ if (xfrm_selector_match(&x->sel, fl, family) &&
+ xfrm_sec_ctx_match(pol->security, x->security))
error = -ESRCH;
}
}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 0cdd9a07e043..ac87a09ba83e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -7,7 +7,7 @@
* Kazunori MIYAZAWA @USAGI
* Kunihiro Ishiguro <kunihiro@ipinfusion.com>
* IPv6 support
- *
+ *
*/
#include <linux/module.h>
@@ -88,6 +88,34 @@ static int verify_encap_tmpl(struct rtattr **xfrma)
return 0;
}
+
+static inline int verify_sec_ctx_len(struct rtattr **xfrma)
+{
+ struct rtattr *rt = xfrma[XFRMA_SEC_CTX - 1];
+ struct xfrm_user_sec_ctx *uctx;
+ int len = 0;
+
+ if (!rt)
+ return 0;
+
+ if (rt->rta_len < sizeof(*uctx))
+ return -EINVAL;
+
+ uctx = RTA_DATA(rt);
+
+ if (uctx->ctx_len > PAGE_SIZE)
+ return -EINVAL;
+
+ len += sizeof(struct xfrm_user_sec_ctx);
+ len += uctx->ctx_len;
+
+ if (uctx->len != len)
+ return -EINVAL;
+
+ return 0;
+}
+
+
static int verify_newsa_info(struct xfrm_usersa_info *p,
struct rtattr **xfrma)
{
@@ -145,6 +173,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
goto out;
if ((err = verify_encap_tmpl(xfrma)))
goto out;
+ if ((err = verify_sec_ctx_len(xfrma)))
+ goto out;
err = -EINVAL;
switch (p->mode) {
@@ -209,6 +239,30 @@ static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_a
return 0;
}
+
+static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
+{
+ struct xfrm_sec_ctx *xfrm_ctx = xp->security;
+ int len = 0;
+
+ if (xfrm_ctx) {
+ len += sizeof(struct xfrm_user_sec_ctx);
+ len += xfrm_ctx->ctx_len;
+ }
+ return len;
+}
+
+static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
+{
+ struct xfrm_user_sec_ctx *uctx;
+
+ if (!u_arg)
+ return 0;
+
+ uctx = RTA_DATA(u_arg);
+ return security_xfrm_state_alloc(x, uctx);
+}
+
static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
memcpy(&x->id, &p->id, sizeof(x->id));
@@ -253,6 +307,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
if (err)
goto error;
+ if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
+ goto error;
+
x->km.seq = p->seq;
return x;
@@ -272,11 +329,11 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
int err;
struct km_event c;
- err = verify_newsa_info(p, (struct rtattr **) xfrma);
+ err = verify_newsa_info(p, (struct rtattr **)xfrma);
if (err)
return err;
- x = xfrm_state_construct(p, (struct rtattr **) xfrma, &err);
+ x = xfrm_state_construct(p, (struct rtattr **)xfrma, &err);
if (!x)
return err;
@@ -390,6 +447,19 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
if (x->encap)
RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+ if (x->security) {
+ int ctx_size = sizeof(struct xfrm_sec_ctx) +
+ x->security->ctx_len;
+ struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
+ struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+ uctx->exttype = XFRMA_SEC_CTX;
+ uctx->len = ctx_size;
+ uctx->ctx_doi = x->security->ctx_doi;
+ uctx->ctx_alg = x->security->ctx_alg;
+ uctx->ctx_len = x->security->ctx_len;
+ memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len);
+ }
nlh->nlmsg_len = skb->tail - b;
out:
sp->this_idx++;
@@ -603,6 +673,18 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
return verify_policy_dir(p->dir);
}
+static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr **xfrma)
+{
+ struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
+ struct xfrm_user_sec_ctx *uctx;
+
+ if (!rt)
+ return 0;
+
+ uctx = RTA_DATA(rt);
+ return security_xfrm_policy_alloc(pol, uctx);
+}
+
static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
int nr)
{
@@ -681,7 +763,10 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p,
}
copy_from_user_policy(xp, p);
- err = copy_from_user_tmpl(xp, xfrma);
+
+ if (!(err = copy_from_user_tmpl(xp, xfrma)))
+ err = copy_from_user_sec_ctx(xp, xfrma);
+
if (err) {
*errp = err;
kfree(xp);
@@ -702,8 +787,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
err = verify_newpolicy_info(p);
if (err)
return err;
+ err = verify_sec_ctx_len((struct rtattr **)xfrma);
+ if (err)
+ return err;
- xp = xfrm_policy_construct(p, (struct rtattr **) xfrma, &err);
+ xp = xfrm_policy_construct(p, (struct rtattr **)xfrma, &err);
if (!xp)
return err;
@@ -714,6 +802,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
err = xfrm_policy_insert(p->dir, xp, excl);
if (err) {
+ security_xfrm_policy_free(xp);
kfree(xp);
return err;
}
@@ -761,6 +850,27 @@ rtattr_failure:
return -1;
}
+static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
+{
+ if (xp->security) {
+ int ctx_size = sizeof(struct xfrm_sec_ctx) +
+ xp->security->ctx_len;
+ struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
+ struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+ uctx->exttype = XFRMA_SEC_CTX;
+ uctx->len = ctx_size;
+ uctx->ctx_doi = xp->security->ctx_doi;
+ uctx->ctx_alg = xp->security->ctx_alg;
+ uctx->ctx_len = xp->security->ctx_len;
+ memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len);
+ }
+ return 0;
+
+ rtattr_failure:
+ return -1;
+}
+
static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
{
struct xfrm_dump_info *sp = ptr;
@@ -782,6 +892,8 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
copy_to_user_policy(xp, p, dir);
if (copy_to_user_tmpl(xp, skb) < 0)
goto nlmsg_failure;
+ if (copy_to_user_sec_ctx(xp, skb))
+ goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
out:
@@ -852,8 +964,25 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
if (p->index)
xp = xfrm_policy_byid(p->dir, p->index, delete);
- else
- xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
+ else {
+ struct rtattr **rtattrs = (struct rtattr **)xfrma;
+ struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+ struct xfrm_policy tmp;
+
+ err = verify_sec_ctx_len(rtattrs);
+ if (err)
+ return err;
+
+ memset(&tmp, 0, sizeof(struct xfrm_policy));
+ if (rt) {
+ struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+ if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
+ return err;
+ }
+ xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete);
+ security_xfrm_policy_free(&tmp);
+ }
if (xp == NULL)
return -ENOENT;
@@ -1224,6 +1353,8 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
if (copy_to_user_tmpl(xp, skb) < 0)
goto nlmsg_failure;
+ if (copy_to_user_sec_ctx(xp, skb))
+ goto nlmsg_failure;
nlh->nlmsg_len = skb->tail - b;
return skb->len;
@@ -1241,6 +1372,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt,
len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
+ len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
@@ -1324,6 +1456,8 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
copy_to_user_policy(xp, &upe->pol, dir);
if (copy_to_user_tmpl(xp, skb) < 0)
goto nlmsg_failure;
+ if (copy_to_user_sec_ctx(xp, skb))
+ goto nlmsg_failure;
upe->hard = !!hard;
nlh->nlmsg_len = skb->tail - b;
@@ -1341,6 +1475,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
+ len += RTA_SPACE(xfrm_user_sec_ctx_size(xp));
skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
diff --git a/scripts/.gitignore b/scripts/.gitignore
index b46d68bb9e17..a234e524a490 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -1,4 +1,7 @@
+#
+# Generated files
+#
conmakehash
kallsyms
pnmtologo
-
+bin2c
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index db3c708e546b..0168d6c37075 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -3,6 +3,7 @@
# Convinient variables
comma := ,
+squote := '
empty :=
space := $(empty) $(empty)
@@ -12,6 +13,10 @@ space := $(empty) $(empty)
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
###
+# Escape single quote for use in echo statements
+escsq = $(subst $(squote),'\$(squote)',$1)
+
+###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
@@ -47,7 +52,7 @@ 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))
+ echo ' $(call escsq,$($(quiet)cmd_$(1)))' &&) $(cmd_$(1))
# Add $(obj)/ for paths that is not absolute
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
@@ -68,7 +73,7 @@ endif
# echo command. Short version is $(quiet) equals quiet, otherwise full command
echo-cmd = $(if $($(quiet)cmd_$(1)), \
- echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';)
+ echo ' $(call escsq,$($(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
@@ -78,7 +83,7 @@ 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)
+ echo 'cmd_$@ := $(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
# execute the command and also postprocess generated .d dependencies
# file
@@ -87,7 +92,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
@set -e; \
$(echo-cmd) \
$(cmd_$(1)); \
- scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
+ scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
diff --git a/scripts/Makefile b/scripts/Makefile
index 67763eeb8a3e..6f6b48f39f0a 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -19,4 +19,4 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-$(CONFIG_MODULES) += mod
# Let clean descend into subdirs
-subdir- += basic lxdialog kconfig package
+subdir- += basic kconfig package
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 506e3f3befe3..c33e62bde6b0 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -179,10 +179,10 @@ endif
define rule_cc_o_c
$(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \
$(cmd_checksrc) \
- $(if $($(quiet)cmd_cc_o_c),echo ' $(subst ','\'',$($(quiet)cmd_cc_o_c))';) \
+ $(if $($(quiet)cmd_cc_o_c),echo ' $(call escsq,$($(quiet)cmd_cc_o_c))';) \
$(cmd_cc_o_c); \
$(cmd_modversions) \
- scripts/basic/fixdep $(depfile) $@ '$(subst ','\'',$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \
+ scripts/basic/fixdep $(depfile) $@ '$(call escsq,$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0f81dcfd6909..550798f57da5 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -81,8 +81,10 @@ obj-dirs := $(addprefix $(obj)/,$(obj-dirs))
# Note: It's possible that one object gets potentially linked into more
# than one module. In that case KBUILD_MODNAME will be set to foo_bar,
# where foo and bar are the name of the modules.
-basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
-modname_flags = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname))))
+name-fix = $(subst $(comma),_,$(subst -,_,$1))
+basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(*F)))"
+modname_flags = $(if $(filter 1,$(words $(modname))),\
+ -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
@@ -113,7 +115,7 @@ endif
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
$(__c_flags) $(modkern_cflags) \
- $(basename_flags) $(modname_flags)
+ -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
$(__a_flags) $(modkern_aflags)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 0c4f3a9f2ea9..bf96a61d4b86 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -30,7 +30,7 @@
# - See include/linux/module.h for more details
# Step 4 is solely used to allow module versioning in external modules,
-# where the CRC of each module is retreived from the Module.symers file.
+# where the CRC of each module is retrieved from the Module.symers file.
.PHONY: _modpost
_modpost: __modpost
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 0b61bea869f7..679124b11e12 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -130,9 +130,22 @@ void usage(void)
exit(1);
}
+/*
+ * Print out the commandline prefixed with cmd_<target filename> :=
+ * If commandline contains '#' escape with '\' so make to not see
+ * the '#' as a start-of-comment symbol
+ **/
void print_cmdline(void)
{
- printf("cmd_%s := %s\n\n", target, cmdline);
+ char *p = cmdline;
+
+ printf("cmd_%s := ", target);
+ for (; *p; p++) {
+ if (*p == '#')
+ printf("\\");
+ printf("%c", *p);
+ }
+ printf("\n\n");
}
char * str_config = NULL;
diff --git a/scripts/binoffset.c b/scripts/binoffset.c
index 591309d85518..1a2e39b8e3e5 100644
--- a/scripts/binoffset.c
+++ b/scripts/binoffset.c
@@ -1,6 +1,6 @@
/***************************************************************************
* binoffset.c
- * (C) 2002 Randy Dunlap <rddunlap@osdl.org>
+ * (C) 2002 Randy Dunlap <rdunlap@xenotime.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
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
new file mode 100644
index 000000000000..75f21d843c1d
--- /dev/null
+++ b/scripts/bloat-o-meter
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+#
+# Copyright 2004 Matt Mackall <mpm@selenic.com>
+#
+# inspired by perl Bloat-O-Meter (c) 1997 by Andi Kleen
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+
+import sys, os, re
+
+if len(sys.argv) != 3:
+ sys.stderr.write("usage: %s file1 file2\n" % sys.argv[0])
+ sys.exit(-1)
+
+def getsizes(file):
+ sym = {}
+ for l in os.popen("nm --size-sort " + file).readlines():
+ size, type, name = l[:-1].split()
+ if type in "tTdDbB":
+ sym[name] = int(size, 16)
+ return sym
+
+old = getsizes(sys.argv[1])
+new = getsizes(sys.argv[2])
+grow, shrink, add, remove, up, down = 0, 0, 0, 0, 0, 0
+delta, common = [], {}
+
+for a in old:
+ if a in new:
+ common[a] = 1
+
+for name in old:
+ if name not in common:
+ remove += 1
+ down += old[name]
+ delta.append((-old[name], name))
+
+for name in new:
+ if name not in common:
+ add += 1
+ up += new[name]
+ delta.append((new[name], name))
+
+for name in common:
+ d = new.get(name, 0) - old.get(name, 0)
+ if d>0: grow, up = grow+1, up+d
+ if d<0: shrink, down = shrink+1, down-d
+ delta.append((d, name))
+
+delta.sort()
+delta.reverse()
+
+print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
+ (add, remove, grow, shrink, up, -down, up-down)
+print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")
+for d, n in delta:
+ if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
diff --git a/scripts/checkversion.pl b/scripts/checkversion.pl
index df10db662eb1..9f84e562318d 100755
--- a/scripts/checkversion.pl
+++ b/scripts/checkversion.pl
@@ -3,7 +3,7 @@
# checkversion find uses of LINUX_VERSION_CODE, KERNEL_VERSION, or
# UTS_RELEASE without including <linux/version.h>, or cases of
# including <linux/version.h> that don't need it.
-# Copyright (C) 2003, Randy Dunlap <rddunlap@osdl.org>
+# Copyright (C) 2003, Randy Dunlap <rdunlap@xenotime.net>
$| = 1;
diff --git a/scripts/genksyms/.gitignore b/scripts/genksyms/.gitignore
new file mode 100644
index 000000000000..be5cadb1b907
--- /dev/null
+++ b/scripts/genksyms/.gitignore
@@ -0,0 +1,4 @@
+keywords.c
+lex.c
+parse.[ch]
+genksyms
diff --git a/scripts/genksyms/keywords.c_shipped b/scripts/genksyms/keywords.c_shipped
index eabaf7401cd6..ee4647805c58 100644
--- a/scripts/genksyms/keywords.c_shipped
+++ b/scripts/genksyms/keywords.c_shipped
@@ -1,7 +1,38 @@
-/* ANSI-C code produced by gperf version 2.7.2 */
+/* ANSI-C code produced by gperf version 3.0.1 */
/* Command-line: gperf -L ANSI-C -a -C -E -g -H is_reserved_hash -k '1,3,$' -N is_reserved_word -p -t scripts/genksyms/keywords.gperf */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
+#endif
+
+#line 1 "scripts/genksyms/keywords.gperf"
+
+#line 3 "scripts/genksyms/keywords.gperf"
struct resword { const char *name; int token; };
-/* maximum key range = 109, duplicates = 0 */
+/* maximum key range = 68, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -15,32 +46,32 @@ is_reserved_hash (register const char *str, register unsigned int len)
{
static const unsigned char asso_values[] =
{
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 5,
- 113, 113, 113, 113, 113, 113, 0, 113, 113, 113,
- 0, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 0, 113, 0, 113, 20,
- 25, 0, 35, 30, 113, 20, 113, 113, 40, 30,
- 30, 0, 0, 113, 0, 51, 0, 15, 5, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113, 113, 113, 113, 113,
- 113, 113, 113, 113, 113, 113
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 15,
+ 71, 71, 71, 71, 71, 71, 15, 71, 71, 71,
+ 10, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 0, 71, 0, 71, 5,
+ 5, 0, 10, 20, 71, 25, 71, 71, 20, 0,
+ 20, 30, 25, 71, 10, 5, 0, 20, 15, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 71
};
return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
}
@@ -56,77 +87,112 @@ is_reserved_word (register const char *str, register unsigned int len)
TOTAL_KEYWORDS = 41,
MIN_WORD_LENGTH = 3,
MAX_WORD_LENGTH = 17,
- MIN_HASH_VALUE = 4,
- MAX_HASH_VALUE = 112
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 70
};
static const struct resword wordlist[] =
{
- {""}, {""}, {""}, {""},
- {"auto", AUTO_KEYW},
- {""}, {""},
+ {""}, {""}, {""},
+#line 24 "scripts/genksyms/keywords.gperf"
+ {"asm", ASM_KEYW},
+ {""},
+#line 7 "scripts/genksyms/keywords.gperf"
+ {"__asm", ASM_KEYW},
+ {""},
+#line 8 "scripts/genksyms/keywords.gperf"
{"__asm__", ASM_KEYW},
{""},
+#line 21 "scripts/genksyms/keywords.gperf"
{"_restrict", RESTRICT_KEYW},
+#line 50 "scripts/genksyms/keywords.gperf"
{"__typeof__", TYPEOF_KEYW},
+#line 9 "scripts/genksyms/keywords.gperf"
{"__attribute", ATTRIBUTE_KEYW},
- {"__restrict__", RESTRICT_KEYW},
+#line 11 "scripts/genksyms/keywords.gperf"
+ {"__const", CONST_KEYW},
+#line 10 "scripts/genksyms/keywords.gperf"
{"__attribute__", ATTRIBUTE_KEYW},
+#line 12 "scripts/genksyms/keywords.gperf"
+ {"__const__", CONST_KEYW},
+#line 16 "scripts/genksyms/keywords.gperf"
+ {"__signed__", SIGNED_KEYW},
+#line 42 "scripts/genksyms/keywords.gperf"
+ {"static", STATIC_KEYW},
{""},
- {"__volatile", VOLATILE_KEYW},
+#line 15 "scripts/genksyms/keywords.gperf"
+ {"__signed", SIGNED_KEYW},
+#line 30 "scripts/genksyms/keywords.gperf"
+ {"char", CHAR_KEYW},
{""},
+#line 43 "scripts/genksyms/keywords.gperf"
+ {"struct", STRUCT_KEYW},
+#line 22 "scripts/genksyms/keywords.gperf"
+ {"__restrict__", RESTRICT_KEYW},
+#line 23 "scripts/genksyms/keywords.gperf"
+ {"restrict", RESTRICT_KEYW},
+#line 33 "scripts/genksyms/keywords.gperf"
+ {"enum", ENUM_KEYW},
+#line 17 "scripts/genksyms/keywords.gperf"
+ {"__volatile", VOLATILE_KEYW},
+#line 34 "scripts/genksyms/keywords.gperf"
+ {"extern", EXTERN_KEYW},
+#line 18 "scripts/genksyms/keywords.gperf"
{"__volatile__", VOLATILE_KEYW},
- {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
- {""}, {""}, {""},
- {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
+#line 37 "scripts/genksyms/keywords.gperf"
{"int", INT_KEYW},
- {"char", CHAR_KEYW},
- {""}, {""},
- {"__const", CONST_KEYW},
+ {""},
+#line 31 "scripts/genksyms/keywords.gperf"
+ {"const", CONST_KEYW},
+#line 32 "scripts/genksyms/keywords.gperf"
+ {"double", DOUBLE_KEYW},
+ {""},
+#line 13 "scripts/genksyms/keywords.gperf"
{"__inline", INLINE_KEYW},
- {"__const__", CONST_KEYW},
+#line 29 "scripts/genksyms/keywords.gperf"
+ {"auto", AUTO_KEYW},
+#line 14 "scripts/genksyms/keywords.gperf"
{"__inline__", INLINE_KEYW},
- {""}, {""}, {""}, {""},
- {"__asm", ASM_KEYW},
- {"extern", EXTERN_KEYW},
+#line 41 "scripts/genksyms/keywords.gperf"
+ {"signed", SIGNED_KEYW},
{""},
- {"register", REGISTER_KEYW},
+#line 46 "scripts/genksyms/keywords.gperf"
+ {"unsigned", UNSIGNED_KEYW},
{""},
- {"float", FLOAT_KEYW},
+#line 40 "scripts/genksyms/keywords.gperf"
+ {"short", SHORT_KEYW},
+#line 49 "scripts/genksyms/keywords.gperf"
{"typeof", TYPEOF_KEYW},
+#line 44 "scripts/genksyms/keywords.gperf"
{"typedef", TYPEDEF_KEYW},
- {""}, {""},
- {"_Bool", BOOL_KEYW},
- {"double", DOUBLE_KEYW},
- {""}, {""},
- {"enum", ENUM_KEYW},
- {""}, {""}, {""},
+#line 48 "scripts/genksyms/keywords.gperf"
{"volatile", VOLATILE_KEYW},
+ {""},
+#line 35 "scripts/genksyms/keywords.gperf"
+ {"float", FLOAT_KEYW},
+ {""}, {""},
+#line 39 "scripts/genksyms/keywords.gperf"
+ {"register", REGISTER_KEYW},
+#line 47 "scripts/genksyms/keywords.gperf"
{"void", VOID_KEYW},
- {"const", CONST_KEYW},
- {"short", SHORT_KEYW},
- {"struct", STRUCT_KEYW},
{""},
- {"restrict", RESTRICT_KEYW},
+#line 36 "scripts/genksyms/keywords.gperf"
+ {"inline", INLINE_KEYW},
{""},
- {"__signed__", SIGNED_KEYW},
+#line 5 "scripts/genksyms/keywords.gperf"
+ {"EXPORT_SYMBOL", EXPORT_SYMBOL_KEYW},
{""},
- {"asm", ASM_KEYW},
- {""}, {""},
- {"inline", INLINE_KEYW},
- {""}, {""}, {""},
- {"union", UNION_KEYW},
- {""}, {""}, {""}, {""}, {""}, {""},
- {"static", STATIC_KEYW},
+#line 20 "scripts/genksyms/keywords.gperf"
+ {"_Bool", BOOL_KEYW},
+ {""},
+#line 6 "scripts/genksyms/keywords.gperf"
+ {"EXPORT_SYMBOL_GPL", EXPORT_SYMBOL_KEYW},
{""}, {""}, {""}, {""}, {""}, {""},
- {"__signed", SIGNED_KEYW},
- {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
- {""}, {""}, {""}, {""}, {""},
- {"unsigned", UNSIGNED_KEYW},
- {""}, {""}, {""}, {""},
+#line 38 "scripts/genksyms/keywords.gperf"
{"long", LONG_KEYW},
- {""}, {""}, {""}, {""}, {""}, {""}, {""},
- {"signed", SIGNED_KEYW}
+ {""}, {""}, {""}, {""}, {""},
+#line 45 "scripts/genksyms/keywords.gperf"
+ {"union", UNION_KEYW}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped
index d9bfbb5948f2..1218053ee960 100644
--- a/scripts/genksyms/lex.c_shipped
+++ b/scripts/genksyms/lex.c_shipped
@@ -2036,49 +2036,131 @@ fini:
return token;
}
-#ifndef YYSTYPE
-#define YYSTYPE int
-#endif
-#define ASM_KEYW 257
-#define ATTRIBUTE_KEYW 258
-#define AUTO_KEYW 259
-#define BOOL_KEYW 260
-#define CHAR_KEYW 261
-#define CONST_KEYW 262
-#define DOUBLE_KEYW 263
-#define ENUM_KEYW 264
-#define EXTERN_KEYW 265
-#define FLOAT_KEYW 266
-#define INLINE_KEYW 267
-#define INT_KEYW 268
-#define LONG_KEYW 269
-#define REGISTER_KEYW 270
-#define RESTRICT_KEYW 271
-#define SHORT_KEYW 272
-#define SIGNED_KEYW 273
-#define STATIC_KEYW 274
-#define STRUCT_KEYW 275
-#define TYPEDEF_KEYW 276
-#define UNION_KEYW 277
-#define UNSIGNED_KEYW 278
-#define VOID_KEYW 279
-#define VOLATILE_KEYW 280
-#define TYPEOF_KEYW 281
-#define EXPORT_SYMBOL_KEYW 282
-#define ASM_PHRASE 283
-#define ATTRIBUTE_PHRASE 284
-#define BRACE_PHRASE 285
-#define BRACKET_PHRASE 286
-#define EXPRESSION_PHRASE 287
-#define CHAR 288
-#define DOTS 289
-#define IDENT 290
-#define INT 291
-#define REAL 292
-#define STRING 293
-#define TYPE 294
-#define OTHER 295
-#define FILENAME 296
+/* A Bison parser, made by GNU Bison 2.0. */
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, 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, 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ASM_KEYW = 258,
+ ATTRIBUTE_KEYW = 259,
+ AUTO_KEYW = 260,
+ BOOL_KEYW = 261,
+ CHAR_KEYW = 262,
+ CONST_KEYW = 263,
+ DOUBLE_KEYW = 264,
+ ENUM_KEYW = 265,
+ EXTERN_KEYW = 266,
+ FLOAT_KEYW = 267,
+ INLINE_KEYW = 268,
+ INT_KEYW = 269,
+ LONG_KEYW = 270,
+ REGISTER_KEYW = 271,
+ RESTRICT_KEYW = 272,
+ SHORT_KEYW = 273,
+ SIGNED_KEYW = 274,
+ STATIC_KEYW = 275,
+ STRUCT_KEYW = 276,
+ TYPEDEF_KEYW = 277,
+ UNION_KEYW = 278,
+ UNSIGNED_KEYW = 279,
+ VOID_KEYW = 280,
+ VOLATILE_KEYW = 281,
+ TYPEOF_KEYW = 282,
+ EXPORT_SYMBOL_KEYW = 283,
+ ASM_PHRASE = 284,
+ ATTRIBUTE_PHRASE = 285,
+ BRACE_PHRASE = 286,
+ BRACKET_PHRASE = 287,
+ EXPRESSION_PHRASE = 288,
+ CHAR = 289,
+ DOTS = 290,
+ IDENT = 291,
+ INT = 292,
+ REAL = 293,
+ STRING = 294,
+ TYPE = 295,
+ OTHER = 296,
+ FILENAME = 297
+ };
+#endif
+#define ASM_KEYW 258
+#define ATTRIBUTE_KEYW 259
+#define AUTO_KEYW 260
+#define BOOL_KEYW 261
+#define CHAR_KEYW 262
+#define CONST_KEYW 263
+#define DOUBLE_KEYW 264
+#define ENUM_KEYW 265
+#define EXTERN_KEYW 266
+#define FLOAT_KEYW 267
+#define INLINE_KEYW 268
+#define INT_KEYW 269
+#define LONG_KEYW 270
+#define REGISTER_KEYW 271
+#define RESTRICT_KEYW 272
+#define SHORT_KEYW 273
+#define SIGNED_KEYW 274
+#define STATIC_KEYW 275
+#define STRUCT_KEYW 276
+#define TYPEDEF_KEYW 277
+#define UNION_KEYW 278
+#define UNSIGNED_KEYW 279
+#define VOID_KEYW 280
+#define VOLATILE_KEYW 281
+#define TYPEOF_KEYW 282
+#define EXPORT_SYMBOL_KEYW 283
+#define ASM_PHRASE 284
+#define ATTRIBUTE_PHRASE 285
+#define BRACE_PHRASE 286
+#define BRACKET_PHRASE 287
+#define EXPRESSION_PHRASE 288
+#define CHAR 289
+#define DOTS 290
+#define IDENT 291
+#define INT 292
+#define REAL 293
+#define STRING 294
+#define TYPE 295
+#define OTHER 296
+#define FILENAME 297
+
+
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
extern YYSTYPE yylval;
+
+
+
diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped
index 2c6b1286b638..99d7c258696d 100644
--- a/scripts/genksyms/parse.c_shipped
+++ b/scripts/genksyms/parse.c_shipped
@@ -1,50 +1,145 @@
+/* A Bison parser, made by GNU Bison 2.0. */
-/* A Bison parser, made from scripts/genksyms/parse.y
- by GNU Bison version 1.28 */
-
-#define YYBISON 1 /* Identify Bison output. */
-
-#define ASM_KEYW 257
-#define ATTRIBUTE_KEYW 258
-#define AUTO_KEYW 259
-#define BOOL_KEYW 260
-#define CHAR_KEYW 261
-#define CONST_KEYW 262
-#define DOUBLE_KEYW 263
-#define ENUM_KEYW 264
-#define EXTERN_KEYW 265
-#define FLOAT_KEYW 266
-#define INLINE_KEYW 267
-#define INT_KEYW 268
-#define LONG_KEYW 269
-#define REGISTER_KEYW 270
-#define RESTRICT_KEYW 271
-#define SHORT_KEYW 272
-#define SIGNED_KEYW 273
-#define STATIC_KEYW 274
-#define STRUCT_KEYW 275
-#define TYPEDEF_KEYW 276
-#define UNION_KEYW 277
-#define UNSIGNED_KEYW 278
-#define VOID_KEYW 279
-#define VOLATILE_KEYW 280
-#define TYPEOF_KEYW 281
-#define EXPORT_SYMBOL_KEYW 282
-#define ASM_PHRASE 283
-#define ATTRIBUTE_PHRASE 284
-#define BRACE_PHRASE 285
-#define BRACKET_PHRASE 286
-#define EXPRESSION_PHRASE 287
-#define CHAR 288
-#define DOTS 289
-#define IDENT 290
-#define INT 291
-#define REAL 292
-#define STRING 293
-#define TYPE 294
-#define OTHER 295
-#define FILENAME 296
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, 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, 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Written by Richard Stallman by simplifying the original so called
+ ``semantic'' parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ASM_KEYW = 258,
+ ATTRIBUTE_KEYW = 259,
+ AUTO_KEYW = 260,
+ BOOL_KEYW = 261,
+ CHAR_KEYW = 262,
+ CONST_KEYW = 263,
+ DOUBLE_KEYW = 264,
+ ENUM_KEYW = 265,
+ EXTERN_KEYW = 266,
+ FLOAT_KEYW = 267,
+ INLINE_KEYW = 268,
+ INT_KEYW = 269,
+ LONG_KEYW = 270,
+ REGISTER_KEYW = 271,
+ RESTRICT_KEYW = 272,
+ SHORT_KEYW = 273,
+ SIGNED_KEYW = 274,
+ STATIC_KEYW = 275,
+ STRUCT_KEYW = 276,
+ TYPEDEF_KEYW = 277,
+ UNION_KEYW = 278,
+ UNSIGNED_KEYW = 279,
+ VOID_KEYW = 280,
+ VOLATILE_KEYW = 281,
+ TYPEOF_KEYW = 282,
+ EXPORT_SYMBOL_KEYW = 283,
+ ASM_PHRASE = 284,
+ ATTRIBUTE_PHRASE = 285,
+ BRACE_PHRASE = 286,
+ BRACKET_PHRASE = 287,
+ EXPRESSION_PHRASE = 288,
+ CHAR = 289,
+ DOTS = 290,
+ IDENT = 291,
+ INT = 292,
+ REAL = 293,
+ STRING = 294,
+ TYPE = 295,
+ OTHER = 296,
+ FILENAME = 297
+ };
+#endif
+#define ASM_KEYW 258
+#define ATTRIBUTE_KEYW 259
+#define AUTO_KEYW 260
+#define BOOL_KEYW 261
+#define CHAR_KEYW 262
+#define CONST_KEYW 263
+#define DOUBLE_KEYW 264
+#define ENUM_KEYW 265
+#define EXTERN_KEYW 266
+#define FLOAT_KEYW 267
+#define INLINE_KEYW 268
+#define INT_KEYW 269
+#define LONG_KEYW 270
+#define REGISTER_KEYW 271
+#define RESTRICT_KEYW 272
+#define SHORT_KEYW 273
+#define SIGNED_KEYW 274
+#define STATIC_KEYW 275
+#define STRUCT_KEYW 276
+#define TYPEDEF_KEYW 277
+#define UNION_KEYW 278
+#define UNSIGNED_KEYW 279
+#define VOID_KEYW 280
+#define VOLATILE_KEYW 281
+#define TYPEOF_KEYW 282
+#define EXPORT_SYMBOL_KEYW 283
+#define ASM_PHRASE 284
+#define ATTRIBUTE_PHRASE 285
+#define BRACE_PHRASE 286
+#define BRACKET_PHRASE 287
+#define EXPRESSION_PHRASE 288
+#define CHAR 289
+#define DOTS 290
+#define IDENT 291
+#define INT 292
+#define REAL 293
+#define STRING 294
+#define TYPE 295
+#define OTHER 296
+#define FILENAME 297
+
+
+
+
+/* Copy the first part of user declarations. */
#line 24 "scripts/genksyms/parse.y"
@@ -75,661 +170,1000 @@ remove_list(struct string_list **pb, struct string_list **pe)
free_list(b, e);
}
-#ifndef YYSTYPE
-#define YYSTYPE int
-#endif
+
+
+/* Enabling traces. */
#ifndef YYDEBUG
-#define YYDEBUG 1
+# define YYDEBUG 1
#endif
-#include <stdio.h>
-
-#ifndef __cplusplus
-#ifndef __STDC__
-#define const
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
#endif
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
#endif
-#define YYFINAL 172
-#define YYFLAG -32768
-#define YYNTBASE 52
-
-#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 96)
-
-static const char yytranslate[] = { 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 46,
- 47, 48, 2, 45, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 51, 43, 2,
- 49, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 50, 2, 44, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 38, 39, 40, 41, 42
-};
+/* Copy the second part of user declarations. */
-#if YYDEBUG != 0
-static const short yyprhs[] = { 0,
- 0, 2, 5, 6, 9, 10, 14, 16, 18, 20,
- 22, 25, 28, 32, 33, 35, 37, 41, 46, 47,
- 49, 51, 54, 56, 58, 60, 62, 64, 66, 68,
- 70, 72, 77, 80, 83, 86, 90, 94, 98, 101,
- 104, 107, 109, 111, 113, 115, 117, 119, 121, 123,
- 125, 127, 129, 132, 133, 135, 137, 140, 142, 144,
- 146, 148, 151, 153, 155, 160, 165, 168, 172, 176,
- 179, 181, 183, 185, 190, 195, 198, 202, 206, 209,
- 211, 215, 216, 218, 220, 224, 227, 230, 232, 233,
- 235, 237, 242, 247, 250, 254, 258, 262, 263, 265,
- 268, 272, 276, 277, 279, 281, 284, 288, 291, 292,
- 294, 296, 300, 303, 306, 308, 311, 312, 314, 317,
- 318, 320
-};
-static const short yyrhs[] = { 53,
- 0, 52, 53, 0, 0, 54, 55, 0, 0, 22,
- 56, 57, 0, 57, 0, 81, 0, 93, 0, 95,
- 0, 1, 43, 0, 1, 44, 0, 61, 58, 43,
- 0, 0, 59, 0, 60, 0, 59, 45, 60, 0,
- 71, 94, 92, 82, 0, 0, 62, 0, 63, 0,
- 62, 63, 0, 64, 0, 65, 0, 5, 0, 16,
- 0, 20, 0, 11, 0, 13, 0, 66, 0, 70,
- 0, 27, 46, 62, 47, 0, 21, 36, 0, 23,
- 36, 0, 10, 36, 0, 21, 36, 84, 0, 23,
- 36, 84, 0, 10, 36, 31, 0, 10, 31, 0,
- 21, 84, 0, 23, 84, 0, 7, 0, 18, 0,
- 14, 0, 15, 0, 19, 0, 24, 0, 12, 0,
- 9, 0, 25, 0, 6, 0, 40, 0, 48, 68,
- 0, 0, 69, 0, 70, 0, 69, 70, 0, 8,
- 0, 26, 0, 30, 0, 17, 0, 67, 71, 0,
- 72, 0, 36, 0, 72, 46, 75, 47, 0, 72,
- 46, 1, 47, 0, 72, 32, 0, 46, 71, 47,
- 0, 46, 1, 47, 0, 67, 73, 0, 74, 0,
- 36, 0, 40, 0, 74, 46, 75, 47, 0, 74,
- 46, 1, 47, 0, 74, 32, 0, 46, 73, 47,
- 0, 46, 1, 47, 0, 76, 35, 0, 76, 0,
- 77, 45, 35, 0, 0, 77, 0, 78, 0, 77,
- 45, 78, 0, 62, 79, 0, 67, 79, 0, 80,
- 0, 0, 36, 0, 40, 0, 80, 46, 75, 47,
- 0, 80, 46, 1, 47, 0, 80, 32, 0, 46,
- 79, 47, 0, 46, 1, 47, 0, 61, 71, 31,
- 0, 0, 83, 0, 49, 33, 0, 50, 85, 44,
- 0, 50, 1, 44, 0, 0, 86, 0, 87, 0,
- 86, 87, 0, 61, 88, 43, 0, 1, 43, 0,
- 0, 89, 0, 90, 0, 89, 45, 90, 0, 73,
- 92, 0, 36, 91, 0, 91, 0, 51, 33, 0,
- 0, 30, 0, 29, 43, 0, 0, 29, 0, 28,
- 46, 36, 47, 43, 0
-};
+/* Line 213 of yacc.c. */
+#line 202 "scripts/genksyms/parse.c"
-#endif
+#if ! defined (yyoverflow) || YYERROR_VERBOSE
-#if YYDEBUG != 0
-static const short yyrline[] = { 0,
- 101, 103, 106, 109, 112, 114, 115, 116, 117, 118,
- 119, 120, 123, 137, 139, 142, 151, 163, 169, 171,
- 174, 176, 179, 186, 189, 191, 192, 193, 194, 197,
- 199, 200, 204, 206, 208, 212, 219, 226, 235, 236,
- 237, 240, 242, 243, 244, 245, 246, 247, 248, 249,
- 250, 251, 254, 259, 261, 264, 266, 269, 270, 270,
- 271, 278, 280, 283, 293, 295, 297, 299, 301, 307,
- 309, 312, 314, 315, 317, 319, 321, 323, 327, 329,
- 330, 333, 335, 338, 340, 344, 349, 352, 355, 357,
- 365, 369, 371, 373, 375, 377, 381, 390, 392, 396,
- 401, 403, 406, 408, 411, 413, 416, 419, 423, 425,
- 428, 430, 433, 435, 436, 439, 443, 445, 448, 452,
- 454, 457
-};
-#endif
+# ifndef YYFREE
+# define YYFREE free
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# endif
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# else
+# define YYSTACK_ALLOC alloca
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# endif
+#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
+
+
+#if (! defined (yyoverflow) \
+ && (! defined (__cplusplus) \
+ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ short int yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined (__GNUC__) && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ register YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
-
-static const char * const yytname[] = { "$","error","$undefined.","ASM_KEYW",
-"ATTRIBUTE_KEYW","AUTO_KEYW","BOOL_KEYW","CHAR_KEYW","CONST_KEYW","DOUBLE_KEYW",
-"ENUM_KEYW","EXTERN_KEYW","FLOAT_KEYW","INLINE_KEYW","INT_KEYW","LONG_KEYW",
-"REGISTER_KEYW","RESTRICT_KEYW","SHORT_KEYW","SIGNED_KEYW","STATIC_KEYW","STRUCT_KEYW",
-"TYPEDEF_KEYW","UNION_KEYW","UNSIGNED_KEYW","VOID_KEYW","VOLATILE_KEYW","TYPEOF_KEYW",
-"EXPORT_SYMBOL_KEYW","ASM_PHRASE","ATTRIBUTE_PHRASE","BRACE_PHRASE","BRACKET_PHRASE",
-"EXPRESSION_PHRASE","CHAR","DOTS","IDENT","INT","REAL","STRING","TYPE","OTHER",
-"FILENAME","';'","'}'","','","'('","')'","'*'","'='","'{'","':'","declaration_seq",
-"declaration","@1","declaration1","@2","simple_declaration","init_declarator_list_opt",
-"init_declarator_list","init_declarator","decl_specifier_seq_opt","decl_specifier_seq",
-"decl_specifier","storage_class_specifier","type_specifier","simple_type_specifier",
-"ptr_operator","cvar_qualifier_seq_opt","cvar_qualifier_seq","cvar_qualifier",
-"declarator","direct_declarator","nested_declarator","direct_nested_declarator",
-"parameter_declaration_clause","parameter_declaration_list_opt","parameter_declaration_list",
-"parameter_declaration","m_abstract_declarator","direct_m_abstract_declarator",
-"function_definition","initializer_opt","initializer","class_body","member_specification_opt",
-"member_specification","member_declaration","member_declarator_list_opt","member_declarator_list",
-"member_declarator","member_bitfield_declarator","attribute_opt","asm_definition",
-"asm_phrase_opt","export_definition", NULL
-};
#endif
-static const short yyr1[] = { 0,
- 52, 52, 54, 53, 56, 55, 55, 55, 55, 55,
- 55, 55, 57, 58, 58, 59, 59, 60, 61, 61,
- 62, 62, 63, 63, 64, 64, 64, 64, 64, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 67, 68, 68, 69, 69, 70, 70, 70,
- 70, 71, 71, 72, 72, 72, 72, 72, 72, 73,
- 73, 74, 74, 74, 74, 74, 74, 74, 75, 75,
- 75, 76, 76, 77, 77, 78, 79, 79, 80, 80,
- 80, 80, 80, 80, 80, 80, 81, 82, 82, 83,
- 84, 84, 85, 85, 86, 86, 87, 87, 88, 88,
- 89, 89, 90, 90, 90, 91, 92, 92, 93, 94,
- 94, 95
+#if defined (__STDC__) || defined (__cplusplus)
+ typedef signed char yysigned_char;
+#else
+ typedef short int yysigned_char;
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 4
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 535
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 52
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 45
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 124
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 174
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 297
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const unsigned char yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 46, 48, 47, 2, 45, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 51, 43,
+ 2, 49, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 50, 2, 44, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42
};
-static const short yyr2[] = { 0,
- 1, 2, 0, 2, 0, 3, 1, 1, 1, 1,
- 2, 2, 3, 0, 1, 1, 3, 4, 0, 1,
- 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 4, 2, 2, 2, 3, 3, 3, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 2, 0, 1, 1, 2, 1, 1, 1,
- 1, 2, 1, 1, 4, 4, 2, 3, 3, 2,
- 1, 1, 1, 4, 4, 2, 3, 3, 2, 1,
- 3, 0, 1, 1, 3, 2, 2, 1, 0, 1,
- 1, 4, 4, 2, 3, 3, 3, 0, 1, 2,
- 3, 3, 0, 1, 1, 2, 3, 2, 0, 1,
- 1, 3, 2, 2, 1, 2, 0, 1, 2, 0,
- 1, 5
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const unsigned short int yyprhs[] =
+{
+ 0, 0, 3, 5, 8, 9, 12, 13, 17, 19,
+ 21, 23, 25, 28, 31, 35, 36, 38, 40, 44,
+ 49, 50, 52, 54, 57, 59, 61, 63, 65, 67,
+ 69, 71, 73, 75, 81, 86, 89, 92, 95, 99,
+ 103, 107, 110, 113, 116, 118, 120, 122, 124, 126,
+ 128, 130, 132, 134, 136, 138, 141, 142, 144, 146,
+ 149, 151, 153, 155, 157, 160, 162, 164, 169, 174,
+ 177, 181, 185, 188, 190, 192, 194, 199, 204, 207,
+ 211, 215, 218, 220, 224, 225, 227, 229, 233, 236,
+ 239, 241, 242, 244, 246, 251, 256, 259, 263, 267,
+ 271, 272, 274, 277, 281, 285, 286, 288, 290, 293,
+ 297, 300, 301, 303, 305, 309, 312, 315, 317, 320,
+ 321, 323, 326, 327, 329
};
-static const short yydefact[] = { 3,
- 3, 1, 0, 2, 0, 25, 51, 42, 58, 49,
- 0, 28, 48, 29, 44, 45, 26, 61, 43, 46,
- 27, 0, 5, 0, 47, 50, 59, 0, 0, 0,
- 60, 52, 4, 7, 14, 20, 21, 23, 24, 30,
- 31, 8, 9, 10, 11, 12, 39, 35, 33, 0,
- 40, 19, 34, 41, 0, 0, 119, 64, 0, 54,
- 0, 15, 16, 0, 120, 63, 22, 38, 36, 0,
- 109, 0, 0, 105, 6, 14, 37, 0, 0, 0,
- 0, 53, 55, 56, 13, 0, 62, 121, 97, 117,
- 67, 0, 108, 102, 72, 73, 0, 0, 0, 117,
- 71, 0, 110, 111, 115, 101, 0, 106, 120, 32,
- 0, 69, 68, 57, 17, 118, 98, 0, 89, 0,
- 80, 83, 84, 114, 0, 72, 0, 116, 70, 113,
- 76, 0, 107, 0, 122, 0, 18, 99, 66, 90,
- 52, 0, 89, 86, 88, 65, 79, 0, 78, 77,
- 0, 0, 112, 100, 0, 91, 0, 87, 94, 0,
- 81, 85, 75, 74, 96, 95, 0, 0, 93, 92,
- 0, 0
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yysigned_char yyrhs[] =
+{
+ 53, 0, -1, 54, -1, 53, 54, -1, -1, 55,
+ 56, -1, -1, 22, 57, 58, -1, 58, -1, 82,
+ -1, 94, -1, 96, -1, 1, 43, -1, 1, 44,
+ -1, 62, 59, 43, -1, -1, 60, -1, 61, -1,
+ 60, 45, 61, -1, 72, 95, 93, 83, -1, -1,
+ 63, -1, 64, -1, 63, 64, -1, 65, -1, 66,
+ -1, 5, -1, 16, -1, 20, -1, 11, -1, 13,
+ -1, 67, -1, 71, -1, 27, 46, 63, 47, 48,
+ -1, 27, 46, 63, 48, -1, 21, 36, -1, 23,
+ 36, -1, 10, 36, -1, 21, 36, 85, -1, 23,
+ 36, 85, -1, 10, 36, 31, -1, 10, 31, -1,
+ 21, 85, -1, 23, 85, -1, 7, -1, 18, -1,
+ 14, -1, 15, -1, 19, -1, 24, -1, 12, -1,
+ 9, -1, 25, -1, 6, -1, 40, -1, 47, 69,
+ -1, -1, 70, -1, 71, -1, 70, 71, -1, 8,
+ -1, 26, -1, 30, -1, 17, -1, 68, 72, -1,
+ 73, -1, 36, -1, 73, 46, 76, 48, -1, 73,
+ 46, 1, 48, -1, 73, 32, -1, 46, 72, 48,
+ -1, 46, 1, 48, -1, 68, 74, -1, 75, -1,
+ 36, -1, 40, -1, 75, 46, 76, 48, -1, 75,
+ 46, 1, 48, -1, 75, 32, -1, 46, 74, 48,
+ -1, 46, 1, 48, -1, 77, 35, -1, 77, -1,
+ 78, 45, 35, -1, -1, 78, -1, 79, -1, 78,
+ 45, 79, -1, 63, 80, -1, 68, 80, -1, 81,
+ -1, -1, 36, -1, 40, -1, 81, 46, 76, 48,
+ -1, 81, 46, 1, 48, -1, 81, 32, -1, 46,
+ 80, 48, -1, 46, 1, 48, -1, 62, 72, 31,
+ -1, -1, 84, -1, 49, 33, -1, 50, 86, 44,
+ -1, 50, 1, 44, -1, -1, 87, -1, 88, -1,
+ 87, 88, -1, 62, 89, 43, -1, 1, 43, -1,
+ -1, 90, -1, 91, -1, 90, 45, 91, -1, 74,
+ 93, -1, 36, 92, -1, 92, -1, 51, 33, -1,
+ -1, 30, -1, 29, 43, -1, -1, 29, -1, 28,
+ 46, 36, 48, 43, -1
};
-static const short yydefgoto[] = { 1,
- 2, 3, 33, 52, 34, 61, 62, 63, 71, 36,
- 37, 38, 39, 40, 64, 82, 83, 41, 109, 66,
- 100, 101, 120, 121, 122, 123, 144, 145, 42, 137,
- 138, 51, 72, 73, 74, 102, 103, 104, 105, 117,
- 43, 90, 44
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const unsigned short int yyrline[] =
+{
+ 0, 102, 102, 103, 107, 107, 113, 113, 115, 116,
+ 117, 118, 119, 120, 124, 138, 139, 143, 151, 164,
+ 170, 171, 175, 176, 180, 186, 190, 191, 192, 193,
+ 194, 198, 199, 200, 201, 205, 207, 209, 213, 220,
+ 227, 236, 237, 238, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 256, 261, 262, 266, 267,
+ 271, 271, 271, 272, 280, 281, 285, 294, 296, 298,
+ 300, 302, 309, 310, 314, 315, 316, 318, 320, 322,
+ 324, 329, 330, 331, 335, 336, 340, 341, 346, 351,
+ 353, 357, 358, 366, 370, 372, 374, 376, 378, 383,
+ 392, 393, 398, 403, 404, 408, 409, 413, 414, 418,
+ 420, 425, 426, 430, 431, 435, 436, 437, 441, 445,
+ 446, 450, 454, 455, 459
};
+#endif
-static const short yypact[] = {-32768,
- 15,-32768, 197,-32768, 23,-32768,-32768,-32768,-32768,-32768,
- -18,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768, -28,-32768, -25,-32768,-32768,-32768, -26, -22, -12,
--32768,-32768,-32768,-32768, 49, 493,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768, 27, -8, 101,
--32768, 493, -8,-32768, 493, 10,-32768,-32768, 11, 9,
- 18, 26,-32768, 49, -15, -13,-32768,-32768,-32768, 25,
- 24, 48, 149,-32768,-32768, 49,-32768, 414, 39, 40,
- 47,-32768, 9,-32768,-32768, 49,-32768,-32768,-32768, 66,
--32768, 241,-32768,-32768, 50,-32768, 5, 65, 42, 66,
- 17, 56, 55,-32768,-32768,-32768, 60,-32768, 75,-32768,
- 80,-32768,-32768,-32768,-32768,-32768, 81, 82, 370, 85,
- 98, 89,-32768,-32768, 88,-32768, 91,-32768,-32768,-32768,
--32768, 284,-32768, 24,-32768, 103,-32768,-32768,-32768,-32768,
--32768, 8, 43,-32768, 30,-32768,-32768, 457,-32768,-32768,
- 92, 93,-32768,-32768, 95,-32768, 96,-32768,-32768, 327,
--32768,-32768,-32768,-32768,-32768,-32768, 99, 104,-32768,-32768,
- 148,-32768
+#if YYDEBUG || YYERROR_VERBOSE
+/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ASM_KEYW", "ATTRIBUTE_KEYW",
+ "AUTO_KEYW", "BOOL_KEYW", "CHAR_KEYW", "CONST_KEYW", "DOUBLE_KEYW",
+ "ENUM_KEYW", "EXTERN_KEYW", "FLOAT_KEYW", "INLINE_KEYW", "INT_KEYW",
+ "LONG_KEYW", "REGISTER_KEYW", "RESTRICT_KEYW", "SHORT_KEYW",
+ "SIGNED_KEYW", "STATIC_KEYW", "STRUCT_KEYW", "TYPEDEF_KEYW",
+ "UNION_KEYW", "UNSIGNED_KEYW", "VOID_KEYW", "VOLATILE_KEYW",
+ "TYPEOF_KEYW", "EXPORT_SYMBOL_KEYW", "ASM_PHRASE", "ATTRIBUTE_PHRASE",
+ "BRACE_PHRASE", "BRACKET_PHRASE", "EXPRESSION_PHRASE", "CHAR", "DOTS",
+ "IDENT", "INT", "REAL", "STRING", "TYPE", "OTHER", "FILENAME", "';'",
+ "'}'", "','", "'('", "'*'", "')'", "'='", "'{'", "':'", "$accept",
+ "declaration_seq", "declaration", "@1", "declaration1", "@2",
+ "simple_declaration", "init_declarator_list_opt", "init_declarator_list",
+ "init_declarator", "decl_specifier_seq_opt", "decl_specifier_seq",
+ "decl_specifier", "storage_class_specifier", "type_specifier",
+ "simple_type_specifier", "ptr_operator", "cvar_qualifier_seq_opt",
+ "cvar_qualifier_seq", "cvar_qualifier", "declarator",
+ "direct_declarator", "nested_declarator", "direct_nested_declarator",
+ "parameter_declaration_clause", "parameter_declaration_list_opt",
+ "parameter_declaration_list", "parameter_declaration",
+ "m_abstract_declarator", "direct_m_abstract_declarator",
+ "function_definition", "initializer_opt", "initializer", "class_body",
+ "member_specification_opt", "member_specification", "member_declaration",
+ "member_declarator_list_opt", "member_declarator_list",
+ "member_declarator", "member_bitfield_declarator", "attribute_opt",
+ "asm_definition", "asm_phrase_opt", "export_definition", 0
};
+#endif
-static const short yypgoto[] = {-32768,
- 152,-32768,-32768,-32768, 119,-32768,-32768, 94, 0, -55,
- -35,-32768,-32768,-32768, -69,-32768,-32768, -56, -30,-32768,
- -76,-32768, -122,-32768,-32768, 29, -62,-32768,-32768,-32768,
--32768, -17,-32768,-32768, 105,-32768,-32768, 52, 86, 83,
--32768,-32768,-32768
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const unsigned short int yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 59, 125, 44, 40, 42, 41, 61,
+ 123, 58
};
+# endif
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const unsigned char yyr1[] =
+{
+ 0, 52, 53, 53, 55, 54, 57, 56, 56, 56,
+ 56, 56, 56, 56, 58, 59, 59, 60, 60, 61,
+ 62, 62, 63, 63, 64, 64, 65, 65, 65, 65,
+ 65, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 68, 69, 69, 70, 70,
+ 71, 71, 71, 71, 72, 72, 73, 73, 73, 73,
+ 73, 73, 74, 74, 75, 75, 75, 75, 75, 75,
+ 75, 76, 76, 76, 77, 77, 78, 78, 79, 80,
+ 80, 81, 81, 81, 81, 81, 81, 81, 81, 82,
+ 83, 83, 84, 85, 85, 86, 86, 87, 87, 88,
+ 88, 89, 89, 90, 90, 91, 91, 91, 92, 93,
+ 93, 94, 95, 95, 96
+};
-#define YYLAST 533
-
-
-static const short yytable[] = { 78,
- 67, 99, 35, 84, 65, 125, 54, 49, 155, 152,
- 53, 80, 47, 88, 171, 89, 9, 48, 91, 55,
- 127, 50, 129, 56, 50, 18, 114, 99, 81, 99,
- 57, 69, 92, 87, 27, 77, 119, 168, 31, -89,
- 126, 50, 67, 140, 96, 79, 58, 156, 131, 143,
- 97, 76, 60, 142, -89, 60, 59, 68, 60, 95,
- 85, 159, 132, 96, 99, 45, 46, 93, 94, 97,
- 86, 60, 143, 143, 98, 160, 119, 126, 140, 157,
- 158, 96, 156, 67, 58, 111, 112, 97, 142, 60,
- 60, 106, 119, 113, 59, 116, 60, 128, 133, 134,
- 98, 70, 93, 88, 119, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 135, 24, 25, 26, 27, 28, 139, 136,
- 31, 146, 147, 148, 149, 154, -19, 150, 163, 164,
- 32, 165, 166, -19, -103, 169, -19, 172, -19, 107,
- 170, -19, 4, 6, 7, 8, 9, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 75, 24, 25, 26, 27, 28, 162, 108, 31, 115,
- 124, 0, 130, 0, -19, 153, 0, 0, 32, 0,
- 0, -19, -104, 0, -19, 0, -19, 5, 0, -19,
- 0, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 0, 0, 0,
- 0, 0, -19, 0, 0, 0, 32, 0, 0, -19,
- 0, 118, -19, 0, -19, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 0, 24, 25, 26, 27, 28, 0, 0,
- 31, 0, 0, 0, 0, -82, 0, 0, 0, 0,
- 32, 0, 0, 0, 151, 0, 0, -82, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 0, 24, 25, 26, 27,
- 28, 0, 0, 31, 0, 0, 0, 0, -82, 0,
- 0, 0, 0, 32, 0, 0, 0, 167, 0, 0,
- -82, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 0, 24,
- 25, 26, 27, 28, 0, 0, 31, 0, 0, 0,
- 0, -82, 0, 0, 0, 0, 32, 0, 0, 0,
- 0, 0, 0, -82, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 0, 24, 25, 26, 27, 28, 0, 0, 31,
- 0, 0, 0, 0, 0, 140, 0, 0, 0, 141,
- 0, 0, 0, 0, 0, 142, 0, 60, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 0, 24, 25, 26, 27,
- 28, 0, 0, 31, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
- 110, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 0, 24,
- 25, 26, 27, 28, 0, 0, 31, 0, 0, 0,
- 0, 161, 0, 0, 0, 0, 32, 6, 7, 8,
- 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 0, 24, 25, 26, 27, 28,
- 0, 0, 31, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 32
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const unsigned char yyr2[] =
+{
+ 0, 2, 1, 2, 0, 2, 0, 3, 1, 1,
+ 1, 1, 2, 2, 3, 0, 1, 1, 3, 4,
+ 0, 1, 1, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 5, 4, 2, 2, 2, 3, 3,
+ 3, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 0, 1, 1, 2,
+ 1, 1, 1, 1, 2, 1, 1, 4, 4, 2,
+ 3, 3, 2, 1, 1, 1, 4, 4, 2, 3,
+ 3, 2, 1, 3, 0, 1, 1, 3, 2, 2,
+ 1, 0, 1, 1, 4, 4, 2, 3, 3, 3,
+ 0, 1, 2, 3, 3, 0, 1, 1, 2, 3,
+ 2, 0, 1, 1, 3, 2, 2, 1, 2, 0,
+ 1, 2, 0, 1, 5
};
-static const short yycheck[] = { 55,
- 36, 71, 3, 60, 35, 1, 24, 36, 1, 132,
- 36, 1, 31, 29, 0, 31, 8, 36, 32, 46,
- 97, 50, 99, 46, 50, 17, 83, 97, 59, 99,
- 43, 49, 46, 64, 26, 53, 92, 160, 30, 32,
- 36, 50, 78, 36, 40, 36, 36, 40, 32, 119,
- 46, 52, 48, 46, 47, 48, 46, 31, 48, 36,
- 43, 32, 46, 40, 134, 43, 44, 43, 44, 46,
- 45, 48, 142, 143, 51, 46, 132, 36, 36, 142,
- 143, 40, 40, 119, 36, 47, 47, 46, 46, 48,
- 48, 44, 148, 47, 46, 30, 48, 33, 43, 45,
- 51, 1, 43, 29, 160, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 43, 23, 24, 25, 26, 27, 47, 49,
- 30, 47, 35, 45, 47, 33, 36, 47, 47, 47,
- 40, 47, 47, 43, 44, 47, 46, 0, 48, 1,
- 47, 51, 1, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 52, 23, 24, 25, 26, 27, 148, 73, 30, 86,
- 95, -1, 100, -1, 36, 134, -1, -1, 40, -1,
- -1, 43, 44, -1, 46, -1, 48, 1, -1, 51,
- -1, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, -1, -1, -1,
- -1, -1, 36, -1, -1, -1, 40, -1, -1, 43,
- -1, 1, 46, -1, 48, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, -1, 23, 24, 25, 26, 27, -1, -1,
- 30, -1, -1, -1, -1, 35, -1, -1, -1, -1,
- 40, -1, -1, -1, 1, -1, -1, 47, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, -1, 23, 24, 25, 26,
- 27, -1, -1, 30, -1, -1, -1, -1, 35, -1,
- -1, -1, -1, 40, -1, -1, -1, 1, -1, -1,
- 47, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, -1, 23,
- 24, 25, 26, 27, -1, -1, 30, -1, -1, -1,
- -1, 35, -1, -1, -1, -1, 40, -1, -1, -1,
- -1, -1, -1, 47, 5, 6, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, -1, 23, 24, 25, 26, 27, -1, -1, 30,
- -1, -1, -1, -1, -1, 36, -1, -1, -1, 40,
- -1, -1, -1, -1, -1, 46, -1, 48, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, -1, 23, 24, 25, 26,
- 27, -1, -1, 30, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 40, -1, -1, -1, -1, -1, -1,
- 47, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, -1, 23,
- 24, 25, 26, 27, -1, -1, 30, -1, -1, -1,
- -1, 35, -1, -1, -1, -1, 40, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, -1, 23, 24, 25, 26, 27,
- -1, -1, 30, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 40
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const unsigned char yydefact[] =
+{
+ 4, 4, 2, 0, 1, 3, 0, 26, 53, 44,
+ 60, 51, 0, 29, 50, 30, 46, 47, 27, 63,
+ 45, 48, 28, 0, 6, 0, 49, 52, 61, 0,
+ 0, 0, 62, 54, 5, 8, 15, 21, 22, 24,
+ 25, 31, 32, 9, 10, 11, 12, 13, 41, 37,
+ 35, 0, 42, 20, 36, 43, 0, 0, 121, 66,
+ 0, 56, 0, 16, 17, 0, 122, 65, 23, 40,
+ 38, 0, 111, 0, 0, 107, 7, 15, 39, 0,
+ 0, 0, 0, 55, 57, 58, 14, 0, 64, 123,
+ 99, 119, 69, 0, 110, 104, 74, 75, 0, 0,
+ 0, 119, 73, 0, 112, 113, 117, 103, 0, 108,
+ 122, 0, 34, 0, 71, 70, 59, 18, 120, 100,
+ 0, 91, 0, 82, 85, 86, 116, 0, 74, 0,
+ 118, 72, 115, 78, 0, 109, 0, 33, 124, 0,
+ 19, 101, 68, 92, 54, 0, 91, 88, 90, 67,
+ 81, 0, 80, 79, 0, 0, 114, 102, 0, 93,
+ 0, 89, 96, 0, 83, 87, 77, 76, 98, 97,
+ 0, 0, 95, 94
};
-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/usr/lib/bison.simple"
-/* This file comes from bison-1.28. */
-/* Skeleton output parser for bison,
- Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
+/* YYDEFGOTO[NTERM-NUM]. */
+static const short int yydefgoto[] =
+{
+ -1, 1, 2, 3, 34, 53, 35, 62, 63, 64,
+ 72, 37, 38, 39, 40, 41, 65, 83, 84, 42,
+ 110, 67, 101, 102, 122, 123, 124, 125, 147, 148,
+ 43, 140, 141, 52, 73, 74, 75, 103, 104, 105,
+ 106, 119, 44, 91, 45
+};
- This program is free software; you can redistribute 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.
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -128
+static const short int yypact[] =
+{
+ -128, 13, -128, 329, -128, -128, 36, -128, -128, -128,
+ -128, -128, -16, -128, -128, -128, -128, -128, -128, -128,
+ -128, -128, -128, -25, -128, -24, -128, -128, -128, -29,
+ -4, -22, -128, -128, -128, -128, -28, 495, -128, -128,
+ -128, -128, -128, -128, -128, -128, -128, -128, -128, 16,
+ -23, 103, -128, 495, -23, -128, 495, 35, -128, -128,
+ 3, 15, 9, 17, -128, -28, -15, -8, -128, -128,
+ -128, 47, 23, 44, 150, -128, -128, -28, -128, 372,
+ 33, 48, 49, -128, 15, -128, -128, -28, -128, -128,
+ -128, 64, -128, 197, -128, -128, 50, -128, 21, 65,
+ 37, 64, 14, 56, 55, -128, -128, -128, 59, -128,
+ 74, 57, -128, 63, -128, -128, -128, -128, -128, 76,
+ 83, 416, 84, 99, 90, -128, -128, 88, -128, 89,
+ -128, -128, -128, -128, 241, -128, 23, -128, -128, 105,
+ -128, -128, -128, -128, -128, 8, 46, -128, 26, -128,
+ -128, 459, -128, -128, 92, 93, -128, -128, 94, -128,
+ 96, -128, -128, 285, -128, -128, -128, -128, -128, -128,
+ 97, 100, -128, -128
+};
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+/* YYPGOTO[NTERM-NUM]. */
+static const short int yypgoto[] =
+{
+ -128, -128, 151, -128, -128, -128, 119, -128, -128, 66,
+ 0, -56, -36, -128, -128, -128, -70, -128, -128, -51,
+ -31, -128, -11, -128, -127, -128, -128, 27, -81, -128,
+ -128, -128, -128, -19, -128, -128, 107, -128, -128, 43,
+ 86, 82, -128, -128, -128
+};
- You 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. */
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -107
+static const short int yytable[] =
+{
+ 79, 68, 100, 36, 81, 66, 55, 155, 59, 158,
+ 85, 50, 54, 4, 89, 48, 90, 56, 60, 61,
+ 49, 58, 127, 10, 92, 51, 51, 51, 100, 82,
+ 100, 70, 19, 116, 88, 78, 171, 121, 93, 59,
+ -91, 28, 57, 68, 143, 32, 133, 69, 159, 60,
+ 61, 146, 86, 77, 145, 61, -91, 128, 162, 96,
+ 134, 97, 87, 97, 160, 161, 100, 98, 61, 98,
+ 61, 80, 163, 128, 99, 146, 146, 97, 121, 46,
+ 47, 113, 143, 98, 61, 68, 159, 129, 107, 131,
+ 94, 95, 145, 61, 118, 121, 114, 115, 130, 135,
+ 136, 99, 94, 89, 71, 137, 138, 121, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 139, 25, 26, 27, 28,
+ 29, 142, 149, 32, 150, 151, 152, 153, 157, -20,
+ 166, 167, 168, 33, 169, 172, -20, -105, 173, -20,
+ -20, 108, 5, 117, -20, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 76, 25, 26, 27, 28, 29, 165, 156,
+ 32, 109, 126, 132, 0, 0, -20, 0, 0, 0,
+ 33, 0, 0, -20, -106, 0, -20, -20, 120, 0,
+ 0, -20, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 0,
+ 25, 26, 27, 28, 29, 0, 0, 32, 0, 0,
+ 0, 0, -84, 0, 0, 0, 0, 33, 0, 0,
+ 0, 0, 154, 0, 0, -84, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 0, 25, 26, 27, 28, 29, 0,
+ 0, 32, 0, 0, 0, 0, -84, 0, 0, 0,
+ 0, 33, 0, 0, 0, 0, 170, 0, 0, -84,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
+ 27, 28, 29, 0, 0, 32, 0, 0, 0, 0,
+ -84, 0, 0, 0, 0, 33, 0, 0, 0, 0,
+ 6, 0, 0, -84, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 0, 0, 0, 0, 0, -20, 0, 0, 0, 33,
+ 0, 0, -20, 0, 0, -20, -20, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 0, 25, 26, 27, 28, 29,
+ 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 33, 0, 0, 0, 0, 0, 0, 111,
+ 112, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 0, 25,
+ 26, 27, 28, 29, 0, 0, 32, 0, 0, 0,
+ 0, 0, 143, 0, 0, 0, 144, 0, 0, 0,
+ 0, 0, 145, 61, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 0, 25, 26, 27, 28, 29, 0, 0, 32,
+ 0, 0, 0, 0, 164, 0, 0, 0, 0, 33,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 0, 25, 26,
+ 27, 28, 29, 0, 0, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33
+};
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
+static const short int yycheck[] =
+{
+ 56, 37, 72, 3, 1, 36, 25, 134, 36, 1,
+ 61, 36, 36, 0, 29, 31, 31, 46, 46, 47,
+ 36, 43, 1, 8, 32, 50, 50, 50, 98, 60,
+ 100, 50, 17, 84, 65, 54, 163, 93, 46, 36,
+ 32, 26, 46, 79, 36, 30, 32, 31, 40, 46,
+ 47, 121, 43, 53, 46, 47, 48, 36, 32, 36,
+ 46, 40, 45, 40, 145, 146, 136, 46, 47, 46,
+ 47, 36, 46, 36, 51, 145, 146, 40, 134, 43,
+ 44, 48, 36, 46, 47, 121, 40, 98, 44, 100,
+ 43, 44, 46, 47, 30, 151, 48, 48, 33, 43,
+ 45, 51, 43, 29, 1, 48, 43, 163, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 49, 23, 24, 25, 26,
+ 27, 48, 48, 30, 35, 45, 48, 48, 33, 36,
+ 48, 48, 48, 40, 48, 48, 43, 44, 48, 46,
+ 47, 1, 1, 87, 51, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 53, 23, 24, 25, 26, 27, 151, 136,
+ 30, 74, 96, 101, -1, -1, 36, -1, -1, -1,
+ 40, -1, -1, 43, 44, -1, 46, 47, 1, -1,
+ -1, 51, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, -1,
+ 23, 24, 25, 26, 27, -1, -1, 30, -1, -1,
+ -1, -1, 35, -1, -1, -1, -1, 40, -1, -1,
+ -1, -1, 1, -1, -1, 48, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, -1, 23, 24, 25, 26, 27, -1,
+ -1, 30, -1, -1, -1, -1, 35, -1, -1, -1,
+ -1, 40, -1, -1, -1, -1, 1, -1, -1, 48,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, -1, 23, 24,
+ 25, 26, 27, -1, -1, 30, -1, -1, -1, -1,
+ 35, -1, -1, -1, -1, 40, -1, -1, -1, -1,
+ 1, -1, -1, 48, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ -1, -1, -1, -1, -1, 36, -1, -1, -1, 40,
+ -1, -1, 43, -1, -1, 46, 47, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, -1, 23, 24, 25, 26, 27,
+ -1, -1, 30, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 40, -1, -1, -1, -1, -1, -1, 47,
+ 48, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, -1, 23,
+ 24, 25, 26, 27, -1, -1, 30, -1, -1, -1,
+ -1, -1, 36, -1, -1, -1, 40, -1, -1, -1,
+ -1, -1, 46, 47, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, -1, 23, 24, 25, 26, 27, -1, -1, 30,
+ -1, -1, -1, -1, 35, -1, -1, -1, -1, 40,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, -1, 23, 24,
+ 25, 26, 27, -1, -1, 30, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 40
+};
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const unsigned char yystos[] =
+{
+ 0, 53, 54, 55, 0, 54, 1, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 40, 56, 58, 62, 63, 64, 65,
+ 66, 67, 71, 82, 94, 96, 43, 44, 31, 36,
+ 36, 50, 85, 57, 36, 85, 46, 46, 43, 36,
+ 46, 47, 59, 60, 61, 68, 72, 73, 64, 31,
+ 85, 1, 62, 86, 87, 88, 58, 62, 85, 63,
+ 36, 1, 72, 69, 70, 71, 43, 45, 72, 29,
+ 31, 95, 32, 46, 43, 44, 36, 40, 46, 51,
+ 68, 74, 75, 89, 90, 91, 92, 44, 1, 88,
+ 72, 47, 48, 48, 48, 48, 71, 61, 30, 93,
+ 1, 63, 76, 77, 78, 79, 92, 1, 36, 74,
+ 33, 74, 93, 32, 46, 43, 45, 48, 43, 49,
+ 83, 84, 48, 36, 40, 46, 68, 80, 81, 48,
+ 35, 45, 48, 48, 1, 76, 91, 33, 1, 40,
+ 80, 80, 32, 46, 35, 79, 48, 48, 48, 48,
+ 1, 76, 48, 48
+};
-#ifndef YYSTACK_USE_ALLOCA
-#ifdef alloca
-#define YYSTACK_USE_ALLOCA
-#else /* alloca not defined */
-#ifdef __GNUC__
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
-#define YYSTACK_USE_ALLOCA
-#include <alloca.h>
-#else /* not sparc */
-/* We think this test detects Watcom and Microsoft C. */
-/* This used to test MSDOS, but that is a bad idea
- since that symbol is in the user namespace. */
-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
-#if 0 /* No need for malloc.h, which pollutes the namespace;
- instead, just don't use alloca. */
-#include <malloc.h>
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
#endif
-#else /* not MSDOS, or __TURBOC__ */
-#if defined(_AIX)
-/* I don't know what this was needed for, but it pollutes the namespace.
- So I turned it off. rms, 2 May 1997. */
-/* #include <malloc.h> */
- #pragma alloca
-#define YYSTACK_USE_ALLOCA
-#else /* not MSDOS, or __TURBOC__, or _AIX */
-#if 0
-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
- and on HPUX 10. Eventually we can turn this on. */
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#endif /* __hpux */
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
#endif
-#endif /* not _AIX */
-#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc */
-#endif /* not GNU C */
-#endif /* alloca not defined */
-#endif /* YYSTACK_USE_ALLOCA not defined */
-
-#ifdef YYSTACK_USE_ALLOCA
-#define YYSTACK_ALLOC alloca
-#else
-#define YYSTACK_ALLOC malloc
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
#endif
-
-/* Note: there must be only one dollar sign in this file.
- It is replaced by the list of actions, each action
- as one case of the switch. */
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY -2
+#define YYEMPTY (-2)
#define YYEOF 0
+
#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrlab1
-/* Like YYERROR except do call yyerror.
- This remains here temporarily to ease the
- transition to the new meaning of YYERROR, for GCC.
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
+
#define YYFAIL goto yyerrlab
+
#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(token, value) \
+
+#define YYBACKUP(Token, Value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
- { yychar = (token), yylval = (value); \
- yychar1 = YYTRANSLATE (yychar); \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK; \
goto yybackup; \
} \
else \
- { yyerror ("syntax error: cannot back up"); YYERROR; } \
+ { \
+ yyerror ("syntax error: cannot back up");\
+ YYERROR; \
+ } \
while (0)
+
#define YYTERROR 1
#define YYERRCODE 256
-#ifndef YYPURE
-#define YYLEX yylex()
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (0)
#endif
-#ifdef YYPURE
-#ifdef YYLSP_NEEDED
-#ifdef YYLEX_PARAM
-#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
-#else
-#define YYLEX yylex(&yylval, &yylloc)
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
#endif
-#else /* not YYLSP_NEEDED */
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
#ifdef YYLEX_PARAM
-#define YYLEX yylex(&yylval, YYLEX_PARAM)
+# define YYLEX yylex (YYLEX_PARAM)
#else
-#define YYLEX yylex(&yylval)
+# define YYLEX yylex ()
#endif
-#endif /* not YYLSP_NEEDED */
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yysymprint (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_stack_print (short int *bottom, short int *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ short int *bottom;
+ short int *top;
#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (/* Nothing. */; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
-/* If nonreentrant, generate the variables here */
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
-#ifndef YYPURE
-int yychar; /* the lookahead symbol */
-YYSTYPE yylval; /* the semantic value of the */
- /* lookahead symbol */
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
-#ifdef YYLSP_NEEDED
-YYLTYPE yylloc; /* location data for the lookahead */
- /* symbol */
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yy_reduce_print (int yyrule)
+#else
+static void
+yy_reduce_print (yyrule)
+ int yyrule;
#endif
+{
+ int yyi;
+ unsigned int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+ yyrule - 1, yylno);
+ /* Print the symbols being reduced, and their result. */
+ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
+ YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
+ YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+}
-int yynerrs; /* number of parse errors so far */
-#endif /* not YYPURE */
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (Rule); \
+} while (0)
-#if YYDEBUG != 0
-int yydebug; /* nonzero means print parse trace */
-/* Since this is uninitialized, it does not stop multiple parsers
- from coexisting. */
-#endif
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
-/* YYINITDEPTH indicates the initial size of the parser's stacks */
+/* YYINITDEPTH -- initial size of the parser's stacks. */
#ifndef YYINITDEPTH
-#define YYINITDEPTH 200
+# define YYINITDEPTH 200
#endif
-/* YYMAXDEPTH is the maximum size the stacks can grow to
- (effective only if the built-in stack extension method is used). */
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
-#if YYMAXDEPTH == 0
-#undef YYMAXDEPTH
-#endif
+ Do not make this value too large; the results are undefined if
+ SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
+# define YYMAXDEPTH 10000
#endif
+
-/* Define __yy_memcpy. Note that the size argument
- should be passed with type unsigned int, because that is what the non-GCC
- definitions require. With GCC, __builtin_memcpy takes an arg
- of type size_t, but it can handle unsigned int. */
-
-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
-#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
-#else /* not GNU C or C++ */
-#ifndef __cplusplus
-
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
-static void
-__yy_memcpy (to, from, count)
- char *to;
- char *from;
- unsigned int count;
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined (__GLIBC__) && defined (_STRING_H)
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+# if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+# else
+yystrlen (yystr)
+ const char *yystr;
+# endif
+{
+ register const char *yys = yystr;
+
+ while (*yys++ != '\0')
+ continue;
+
+ return yys - yystr - 1;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+# if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+# else
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+# endif
{
- register char *f = from;
- register char *t = to;
- register int i = count;
+ register char *yyd = yydest;
+ register const char *yys = yysrc;
- while (i-- > 0)
- *t++ = *f++;
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
}
+# endif
+# endif
+
+#endif /* !YYERROR_VERBOSE */
-#else /* __cplusplus */
+
+
+#if YYDEBUG
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
+#if defined (__STDC__) || defined (__cplusplus)
static void
-__yy_memcpy (char *to, char *from, unsigned int count)
+yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yysymprint (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
{
- register char *t = to;
- register char *f = from;
- register int i = count;
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
- while (i-- > 0)
- *t++ = *f++;
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+ YYFPRINTF (yyoutput, ")");
}
+#endif /* ! YYDEBUG */
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+#if defined (__STDC__) || defined (__cplusplus)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
#endif
-#endif
+{
+ /* Pacify ``unused variable'' warnings. */
+ (void) yyvaluep;
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
-#line 217 "/usr/lib/bison.simple"
-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
- into yyparse. The argument should have type void *.
- It should actually point to an object.
- Grammar actions can access the variable by casting it
- to the proper pointer type. */
+/* Prevent warnings from -Wmissing-prototypes. */
#ifdef YYPARSE_PARAM
-#ifdef __cplusplus
-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL
-#else /* not __cplusplus */
-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
-#endif /* not __cplusplus */
-#else /* not YYPARSE_PARAM */
-#define YYPARSE_PARAM_ARG
-#define YYPARSE_PARAM_DECL
-#endif /* not YYPARSE_PARAM */
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-#ifdef YYPARSE_PARAM
-int yyparse (void *);
-#else
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM);
+# else
+int yyparse ();
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
int yyparse (void);
+#else
+int yyparse ();
#endif
-#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+int yychar;
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+int yyparse (void *YYPARSE_PARAM)
+# else
+int yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+# endif
+#else /* ! YYPARSE_PARAM */
+#if defined (__STDC__) || defined (__cplusplus)
+int
+yyparse (void)
+#else
int
-yyparse(YYPARSE_PARAM_ARG)
- YYPARSE_PARAM_DECL
+yyparse ()
+
+#endif
+#endif
{
+
register int yystate;
register int yyn;
- register short *yyssp;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ short int yyssa[YYINITDEPTH];
+ short int *yyss = yyssa;
+ register short int *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
register YYSTYPE *yyvsp;
- int yyerrstatus; /* number of tokens to shift before error messages enabled */
- int yychar1 = 0; /* lookahead token as an internal (translated) token number */
-
- short yyssa[YYINITDEPTH]; /* the state stack */
- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
-#ifdef YYLSP_NEEDED
- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
-#else
#define YYPOPSTACK (yyvsp--, yyssp--)
-#endif
- int yystacksize = YYINITDEPTH;
- int yyfree_stacks = 0;
+ YYSIZE_T yystacksize = YYINITDEPTH;
-#ifdef YYPURE
- int yychar;
- YYSTYPE yylval;
- int yynerrs;
-#ifdef YYLSP_NEEDED
- YYLTYPE yylloc;
-#endif
-#endif
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
- YYSTYPE yyval; /* the variable used to return */
- /* semantic values from the action */
- /* routines */
+ /* When reducing, the number of symbols on the RHS of the reduced
+ rule. */
int yylen;
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Starting parse\n");
-#endif
+ YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
@@ -741,833 +1175,872 @@ yyparse(YYPARSE_PARAM_ARG)
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
- yyssp = yyss - 1;
+ yyssp = yyss;
yyvsp = yyvs;
-#ifdef YYLSP_NEEDED
- yylsp = yyls;
-#endif
-/* Push a new state, which is found in yystate . */
-/* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks. */
-yynewstate:
- *++yyssp = yystate;
+ yyvsp[0] = yylval;
- if (yyssp >= yyss + yystacksize - 1)
- {
- /* Give user a chance to reallocate the stack */
- /* Use copies of these so that the &'s don't force the real ones into memory. */
- YYSTYPE *yyvs1 = yyvs;
- short *yyss1 = yyss;
-#ifdef YYLSP_NEEDED
- YYLTYPE *yyls1 = yyls;
-#endif
+ goto yysetstate;
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks.
+ */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
/* Get the current used size of the three stacks, in elements. */
- int size = yyssp - yyss + 1;
+ YYSIZE_T yysize = yyssp - yyss + 1;
#ifdef yyoverflow
- /* Each stack pointer address is followed by the size of
- the data in use in that stack, in bytes. */
-#ifdef YYLSP_NEEDED
- /* This used to be a conditional around just the two extra args,
- but that might be undefined if yyoverflow is a macro. */
- yyoverflow("parser stack overflow",
- &yyss1, size * sizeof (*yyssp),
- &yyvs1, size * sizeof (*yyvsp),
- &yyls1, size * sizeof (*yylsp),
- &yystacksize);
-#else
- yyoverflow("parser stack overflow",
- &yyss1, size * sizeof (*yyssp),
- &yyvs1, size * sizeof (*yyvsp),
- &yystacksize);
-#endif
-
- yyss = yyss1; yyvs = yyvs1;
-#ifdef YYLSP_NEEDED
- yyls = yyls1;
-#endif
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short int *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow ("parser stack overflow",
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyoverflowlab;
+# else
/* Extend the stack our own way. */
- if (yystacksize >= YYMAXDEPTH)
- {
- yyerror("parser stack overflow");
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
-#endif
- }
- return 2;
- }
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyoverflowlab;
yystacksize *= 2;
- if (yystacksize > YYMAXDEPTH)
+ if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
-#ifndef YYSTACK_USE_ALLOCA
- yyfree_stacks = 1;
-#endif
- yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
- __yy_memcpy ((char *)yyss, (char *)yyss1,
- size * (unsigned int) sizeof (*yyssp));
- yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
- __yy_memcpy ((char *)yyvs, (char *)yyvs1,
- size * (unsigned int) sizeof (*yyvsp));
-#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
- __yy_memcpy ((char *)yyls, (char *)yyls1,
- size * (unsigned int) sizeof (*yylsp));
-#endif
+
+ {
+ short int *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyoverflowlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
#endif /* no yyoverflow */
- yyssp = yyss + size - 1;
- yyvsp = yyvs + size - 1;
-#ifdef YYLSP_NEEDED
- yylsp = yyls + size - 1;
-#endif
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
-#endif
- if (yyssp >= yyss + yystacksize - 1)
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Entering state %d\n", yystate);
-#endif
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
goto yybackup;
- yybackup:
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
+/* Read a look-ahead token if we need one and don't already have one. */
/* yyresume: */
- /* First try to decide what to do without reference to lookahead token. */
+ /* First try to decide what to do without reference to look-ahead token. */
yyn = yypact[yystate];
- if (yyn == YYFLAG)
+ if (yyn == YYPACT_NINF)
goto yydefault;
- /* Not known => get a lookahead token if don't already have one. */
-
- /* yychar is either YYEMPTY or YYEOF
- or a valid token in external form. */
+ /* Not known => get a look-ahead token if don't already have one. */
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
if (yychar == YYEMPTY)
{
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Reading a token: ");
-#endif
+ YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX;
}
- /* Convert token to internal form (in yychar1) for indexing tables with */
-
- if (yychar <= 0) /* This means end of input. */
+ if (yychar <= YYEOF)
{
- yychar1 = 0;
- yychar = YYEOF; /* Don't call YYLEX any more */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Now at end of input.\n");
-#endif
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
}
else
{
- yychar1 = YYTRANSLATE(yychar);
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
- /* Give the individual parser a way to print the precise meaning
- of a token, for further debugging info. */
-#ifdef YYPRINT
- YYPRINT (stderr, yychar, yylval);
-#endif
- fprintf (stderr, ")\n");
- }
-#endif
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
}
- yyn += yychar1;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
goto yydefault;
-
yyn = yytable[yyn];
-
- /* yyn is what to do for this token type in this state.
- Negative => reduce, -yyn is rule number.
- Positive => shift, yyn is new state.
- New state is final state => don't bother to shift,
- just return success.
- 0, or most negative number => error. */
-
- if (yyn < 0)
+ if (yyn <= 0)
{
- if (yyn == YYFLAG)
+ if (yyn == 0 || yyn == YYTABLE_NINF)
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
- else if (yyn == 0)
- goto yyerrlab;
if (yyn == YYFINAL)
YYACCEPT;
- /* Shift the lookahead token. */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
-#endif
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
/* Discard the token being shifted unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
*++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
- /* count tokens shifted since error; after three, turn off error status. */
- if (yyerrstatus) yyerrstatus--;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
yystate = yyn;
goto yynewstate;
-/* Do the default action for the current state. */
-yydefault:
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
+ goto yyreduce;
-/* Do a reduction. yyn is the number of a rule to reduce with. */
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
yyreduce:
+ /* yyn is the number of a rule to reduce with. */
yylen = yyr2[yyn];
- if (yylen > 0)
- yyval = yyvsp[1-yylen]; /* implement default value of the action */
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- int i;
- fprintf (stderr, "Reducing via rule %d (line %d), ",
- yyn, yyrline[yyn]);
-
- /* Print the symbols being reduced, and their result. */
- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
- }
-#endif
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
- switch (yyn) {
-case 3:
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
#line 107 "scripts/genksyms/parse.y"
-{ is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;
- break;}
-case 4:
+ { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
+ break;
+
+ case 5:
#line 109 "scripts/genksyms/parse.y"
-{ free_list(*yyvsp[0], NULL); *yyvsp[0] = NULL; ;
- break;}
-case 5:
+ { free_list(*(yyvsp[0]), NULL); *(yyvsp[0]) = NULL; ;}
+ break;
+
+ case 6:
#line 113 "scripts/genksyms/parse.y"
-{ is_typedef = 1; ;
- break;}
-case 6:
+ { is_typedef = 1; ;}
+ break;
+
+ case 7:
#line 114 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 11:
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 12:
#line 119 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 12:
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 13:
#line 120 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 13:
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 14:
#line 125 "scripts/genksyms/parse.y"
-{ if (current_name) {
- struct string_list *decl = (*yyvsp[0])->next;
- (*yyvsp[0])->next = NULL;
+ { if (current_name) {
+ struct string_list *decl = (*(yyvsp[0]))->next;
+ (*(yyvsp[0]))->next = NULL;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL,
decl, is_extern);
current_name = NULL;
}
- yyval = yyvsp[0];
- ;
- break;}
-case 14:
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 15:
#line 138 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 16:
+ { (yyval) = NULL; ;}
+ break;
+
+ case 17:
#line 144 "scripts/genksyms/parse.y"
-{ struct string_list *decl = *yyvsp[0];
- *yyvsp[0] = NULL;
+ { struct string_list *decl = *(yyvsp[0]);
+ *(yyvsp[0]) = NULL;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
current_name = NULL;
- yyval = yyvsp[0];
- ;
- break;}
-case 17:
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 18:
#line 152 "scripts/genksyms/parse.y"
-{ struct string_list *decl = *yyvsp[0];
- *yyvsp[0] = NULL;
- free_list(*yyvsp[-1], NULL);
- *yyvsp[-1] = decl_spec;
+ { struct string_list *decl = *(yyvsp[0]);
+ *(yyvsp[0]) = NULL;
+ free_list(*(yyvsp[-1]), NULL);
+ *(yyvsp[-1]) = decl_spec;
add_symbol(current_name,
is_typedef ? SYM_TYPEDEF : SYM_NORMAL, decl, is_extern);
current_name = NULL;
- yyval = yyvsp[0];
- ;
- break;}
-case 18:
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 19:
#line 165 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1] ? yyvsp[-1] : yyvsp[-2] ? yyvsp[-2] : yyvsp[-3]; ;
- break;}
-case 19:
+ { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]) ? (yyvsp[-1]) : (yyvsp[-2]) ? (yyvsp[-2]) : (yyvsp[-3]); ;}
+ break;
+
+ case 20:
#line 170 "scripts/genksyms/parse.y"
-{ decl_spec = NULL; ;
- break;}
-case 21:
+ { decl_spec = NULL; ;}
+ break;
+
+ case 22:
#line 175 "scripts/genksyms/parse.y"
-{ decl_spec = *yyvsp[0]; ;
- break;}
-case 22:
+ { decl_spec = *(yyvsp[0]); ;}
+ break;
+
+ case 23:
#line 176 "scripts/genksyms/parse.y"
-{ decl_spec = *yyvsp[0]; ;
- break;}
-case 23:
+ { decl_spec = *(yyvsp[0]); ;}
+ break;
+
+ case 24:
#line 181 "scripts/genksyms/parse.y"
-{ /* Version 2 checksumming ignores storage class, as that
+ { /* Version 2 checksumming ignores storage class, as that
is really irrelevant to the linkage. */
- remove_node(yyvsp[0]);
- yyval = yyvsp[0];
- ;
- break;}
-case 28:
+ remove_node((yyvsp[0]));
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 29:
#line 193 "scripts/genksyms/parse.y"
-{ is_extern = 1; yyval = yyvsp[0]; ;
- break;}
-case 29:
+ { is_extern = 1; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 30:
#line 194 "scripts/genksyms/parse.y"
-{ is_extern = 0; yyval = yyvsp[0]; ;
- break;}
-case 33:
-#line 205 "scripts/genksyms/parse.y"
-{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_STRUCT; yyval = yyvsp[0]; ;
- break;}
-case 34:
-#line 207 "scripts/genksyms/parse.y"
-{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_UNION; yyval = yyvsp[0]; ;
- break;}
-case 35:
-#line 209 "scripts/genksyms/parse.y"
-{ remove_node(yyvsp[-1]); (*yyvsp[0])->tag = SYM_ENUM; yyval = yyvsp[0]; ;
- break;}
-case 36:
-#line 213 "scripts/genksyms/parse.y"
-{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r;
+ { is_extern = 0; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 35:
+#line 206 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_STRUCT; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 36:
+#line 208 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_UNION; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 37:
+#line 210 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[-1])); (*(yyvsp[0]))->tag = SYM_ENUM; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 38:
+#line 214 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
r = copy_node(i); r->tag = SYM_STRUCT;
- r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL;
+ r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
add_symbol(i->string, SYM_STRUCT, s, is_extern);
- yyval = yyvsp[0];
- ;
- break;}
-case 37:
-#line 220 "scripts/genksyms/parse.y"
-{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r;
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 39:
+#line 221 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
r = copy_node(i); r->tag = SYM_UNION;
- r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL;
+ r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
add_symbol(i->string, SYM_UNION, s, is_extern);
- yyval = yyvsp[0];
- ;
- break;}
-case 38:
-#line 227 "scripts/genksyms/parse.y"
-{ struct string_list *s = *yyvsp[0], *i = *yyvsp[-1], *r;
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 40:
+#line 228 "scripts/genksyms/parse.y"
+ { struct string_list *s = *(yyvsp[0]), *i = *(yyvsp[-1]), *r;
r = copy_node(i); r->tag = SYM_ENUM;
- r->next = (*yyvsp[-2])->next; *yyvsp[0] = r; (*yyvsp[-2])->next = NULL;
+ r->next = (*(yyvsp[-2]))->next; *(yyvsp[0]) = r; (*(yyvsp[-2]))->next = NULL;
add_symbol(i->string, SYM_ENUM, s, is_extern);
- yyval = yyvsp[0];
- ;
- break;}
-case 39:
-#line 235 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 40:
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 41:
#line 236 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 41:
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 42:
#line 237 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 52:
-#line 251 "scripts/genksyms/parse.y"
-{ (*yyvsp[0])->tag = SYM_TYPEDEF; yyval = yyvsp[0]; ;
- break;}
-case 53:
-#line 256 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ;
- break;}
-case 54:
-#line 260 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 57:
-#line 266 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 61:
-#line 272 "scripts/genksyms/parse.y"
-{ /* restrict has no effect in prototypes so ignore it */
- remove_node(yyvsp[0]);
- yyval = yyvsp[0];
- ;
- break;}
-case 62:
-#line 279 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 64:
-#line 285 "scripts/genksyms/parse.y"
-{ if (current_name != NULL) {
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 43:
+#line 238 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 54:
+#line 252 "scripts/genksyms/parse.y"
+ { (*(yyvsp[0]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 55:
+#line 257 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ break;
+
+ case 56:
+#line 261 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 59:
+#line 267 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 63:
+#line 273 "scripts/genksyms/parse.y"
+ { /* restrict has no effect in prototypes so ignore it */
+ remove_node((yyvsp[0]));
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 64:
+#line 280 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 66:
+#line 286 "scripts/genksyms/parse.y"
+ { if (current_name != NULL) {
error_with_pos("unexpected second declaration name");
YYERROR;
} else {
- current_name = (*yyvsp[0])->string;
- yyval = yyvsp[0];
+ current_name = (*(yyvsp[0]))->string;
+ (yyval) = (yyvsp[0]);
}
- ;
- break;}
-case 65:
-#line 294 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 66:
-#line 296 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 67:
-#line 298 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 68:
-#line 300 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 69:
-#line 302 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 70:
-#line 308 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 74:
-#line 316 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 75:
-#line 318 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 76:
-#line 320 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 77:
-#line 322 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 78:
-#line 324 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 79:
-#line 328 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 81:
-#line 330 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 82:
-#line 334 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 85:
-#line 341 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 86:
-#line 346 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ;
- break;}
-case 87:
-#line 351 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ;
- break;}
-case 89:
-#line 356 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 90:
-#line 358 "scripts/genksyms/parse.y"
-{ /* For version 2 checksums, we don't want to remember
+ ;}
+ break;
+
+ case 67:
+#line 295 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 68:
+#line 297 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 69:
+#line 299 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 70:
+#line 301 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 71:
+#line 303 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 72:
+#line 309 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 76:
+#line 317 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 77:
+#line 319 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 78:
+#line 321 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 79:
+#line 323 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 80:
+#line 325 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 81:
+#line 329 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 83:
+#line 331 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 84:
+#line 335 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 87:
+#line 342 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 88:
+#line 347 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ break;
+
+ case 89:
+#line 352 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ break;
+
+ case 91:
+#line 357 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 92:
+#line 359 "scripts/genksyms/parse.y"
+ { /* For version 2 checksums, we don't want to remember
private parameter names. */
- remove_node(yyvsp[0]);
- yyval = yyvsp[0];
- ;
- break;}
-case 91:
-#line 366 "scripts/genksyms/parse.y"
-{ remove_node(yyvsp[0]);
- yyval = yyvsp[0];
- ;
- break;}
-case 92:
-#line 370 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 93:
-#line 372 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 94:
-#line 374 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 95:
-#line 376 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 96:
-#line 378 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 97:
-#line 383 "scripts/genksyms/parse.y"
-{ struct string_list *decl = *yyvsp[-1];
- *yyvsp[-1] = NULL;
+ remove_node((yyvsp[0]));
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 93:
+#line 367 "scripts/genksyms/parse.y"
+ { remove_node((yyvsp[0]));
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 94:
+#line 371 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 95:
+#line 373 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 96:
+#line 375 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 97:
+#line 377 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 98:
+#line 379 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 99:
+#line 384 "scripts/genksyms/parse.y"
+ { struct string_list *decl = *(yyvsp[-1]);
+ *(yyvsp[-1]) = NULL;
add_symbol(current_name, SYM_NORMAL, decl, is_extern);
- yyval = yyvsp[0];
- ;
- break;}
-case 98:
-#line 391 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 100:
-#line 398 "scripts/genksyms/parse.y"
-{ remove_list(yyvsp[0], &(*yyvsp[-1])->next); yyval = yyvsp[0]; ;
- break;}
-case 101:
-#line 402 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 102:
+ (yyval) = (yyvsp[0]);
+ ;}
+ break;
+
+ case 100:
+#line 392 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 102:
+#line 399 "scripts/genksyms/parse.y"
+ { remove_list((yyvsp[0]), &(*(yyvsp[-1]))->next); (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 103:
#line 403 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 103:
-#line 407 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 106:
-#line 413 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 107:
-#line 418 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 108:
-#line 420 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 109:
-#line 424 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 112:
-#line 430 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 113:
-#line 434 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0] ? yyvsp[0] : yyvsp[-1]; ;
- break;}
-case 114:
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 104:
+#line 404 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 105:
+#line 408 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 108:
+#line 414 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 109:
+#line 419 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 110:
+#line 421 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 111:
+#line 425 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 114:
+#line 431 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 115:
#line 435 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 116:
-#line 440 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 117:
-#line 444 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 119:
-#line 449 "scripts/genksyms/parse.y"
-{ yyval = yyvsp[0]; ;
- break;}
-case 120:
-#line 453 "scripts/genksyms/parse.y"
-{ yyval = NULL; ;
- break;}
-case 122:
-#line 459 "scripts/genksyms/parse.y"
-{ export_symbol((*yyvsp[-2])->string); yyval = yyvsp[0]; ;
- break;}
-}
- /* the action file gets copied in in place of this dollarsign */
-#line 543 "/usr/lib/bison.simple"
+ { (yyval) = (yyvsp[0]) ? (yyvsp[0]) : (yyvsp[-1]); ;}
+ break;
+
+ case 116:
+#line 436 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 118:
+#line 441 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 119:
+#line 445 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 121:
+#line 450 "scripts/genksyms/parse.y"
+ { (yyval) = (yyvsp[0]); ;}
+ break;
+
+ case 122:
+#line 454 "scripts/genksyms/parse.y"
+ { (yyval) = NULL; ;}
+ break;
+
+ case 124:
+#line 460 "scripts/genksyms/parse.y"
+ { export_symbol((*(yyvsp[-2]))->string); (yyval) = (yyvsp[0]); ;}
+ break;
+
+
+ }
+
+/* Line 1037 of yacc.c. */
+#line 1816 "scripts/genksyms/parse.c"
yyvsp -= yylen;
yyssp -= yylen;
-#ifdef YYLSP_NEEDED
- yylsp -= yylen;
-#endif
-#if YYDEBUG != 0
- if (yydebug)
- {
- short *ssp1 = yyss - 1;
- fprintf (stderr, "state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
+
+ YY_STACK_PRINT (yyss, yyssp);
*++yyvsp = yyval;
-#ifdef YYLSP_NEEDED
- yylsp++;
- if (yylen == 0)
- {
- yylsp->first_line = yylloc.first_line;
- yylsp->first_column = yylloc.first_column;
- yylsp->last_line = (yylsp-1)->last_line;
- yylsp->last_column = (yylsp-1)->last_column;
- yylsp->text = 0;
- }
- else
- {
- yylsp->last_line = (yylsp+yylen-1)->last_line;
- yylsp->last_column = (yylsp+yylen-1)->last_column;
- }
-#endif
- /* Now "shift" the result of the reduction.
- Determine what state that goes to,
- based on the state we popped back to
- and the rule number reduced by. */
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
yyn = yyr1[yyn];
- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
- yystate = yydefgoto[yyn - YYNTBASE];
+ yystate = yydefgoto[yyn - YYNTOKENS];
goto yynewstate;
-yyerrlab: /* here on detecting error */
- if (! yyerrstatus)
- /* If not already recovering from an error, report this error. */
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
{
++yynerrs;
-
-#ifdef YYERROR_VERBOSE
+#if YYERROR_VERBOSE
yyn = yypact[yystate];
- if (yyn > YYFLAG && yyn < YYLAST)
+ if (YYPACT_NINF < yyn && yyn < YYLAST)
{
- int size = 0;
- char *msg;
- int x, count;
-
- count = 0;
- /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
- for (x = (yyn < 0 ? -yyn : 0);
- x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
- size += strlen(yytname[x]) + 15, count++;
- msg = (char *) malloc(size + 15);
- if (msg != 0)
+ YYSIZE_T yysize = 0;
+ int yytype = YYTRANSLATE (yychar);
+ const char* yyprefix;
+ char *yymsg;
+ int yyx;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 0;
+
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
+ yycount += 1;
+ if (yycount == 5)
+ {
+ yysize = 0;
+ break;
+ }
+ }
+ yysize += (sizeof ("syntax error, unexpected ")
+ + yystrlen (yytname[yytype]));
+ yymsg = (char *) YYSTACK_ALLOC (yysize);
+ if (yymsg != 0)
{
- strcpy(msg, "parse error");
+ char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
+ yyp = yystpcpy (yyp, yytname[yytype]);
- if (count < 5)
+ if (yycount < 5)
{
- count = 0;
- for (x = (yyn < 0 ? -yyn : 0);
- x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
+ yyprefix = ", expecting ";
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
{
- strcat(msg, count == 0 ? ", expecting `" : " or `");
- strcat(msg, yytname[x]);
- strcat(msg, "'");
- count++;
+ yyp = yystpcpy (yyp, yyprefix);
+ yyp = yystpcpy (yyp, yytname[yyx]);
+ yyprefix = " or ";
}
}
- yyerror(msg);
- free(msg);
+ yyerror (yymsg);
+ YYSTACK_FREE (yymsg);
}
else
- yyerror ("parse error; also virtual memory exceeded");
+ yyerror ("syntax error; also virtual memory exhausted");
}
else
#endif /* YYERROR_VERBOSE */
- yyerror("parse error");
+ yyerror ("syntax error");
}
- goto yyerrlab1;
-yyerrlab1: /* here on error raised explicitly by an action */
+
if (yyerrstatus == 3)
{
- /* if just tried and failed to reuse lookahead token after an error, discard it. */
-
- /* return failure if at end of input */
- if (yychar == YYEOF)
- YYABORT;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
-#endif
-
- yychar = YYEMPTY;
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* If at end of input, pop the error token,
+ then the rest of the stack, then return failure. */
+ if (yychar == YYEOF)
+ for (;;)
+ {
+
+ YYPOPSTACK;
+ if (yyssp == yyss)
+ YYABORT;
+ yydestruct ("Error: popping",
+ yystos[*yyssp], yyvsp);
+ }
+ }
+ else
+ {
+ yydestruct ("Error: discarding", yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
}
- /* Else will try to reuse lookahead token
- after shifting the error token. */
-
- yyerrstatus = 3; /* Each real token shifted decrements this */
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
- goto yyerrhandle;
-yyerrdefault: /* current state does not do anything special for the error token. */
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
-#if 0
- /* This is wrong; only states that explicitly want error tokens
- should shift them. */
- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
- if (yyn) goto yydefault;
+#ifdef __GNUC__
+ /* Pacify GCC when the user code never invokes YYERROR and the label
+ yyerrorlab therefore never appears in user code. */
+ if (0)
+ goto yyerrorlab;
#endif
-yyerrpop: /* pop the current state because it cannot handle the error token */
+yyvsp -= yylen;
+ yyssp -= yylen;
+ yystate = *yyssp;
+ goto yyerrlab1;
+
- if (yyssp == yyss) YYABORT;
- yyvsp--;
- yystate = *--yyssp;
-#ifdef YYLSP_NEEDED
- yylsp--;
-#endif
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
-#if YYDEBUG != 0
- if (yydebug)
+ for (;;)
{
- short *ssp1 = yyss - 1;
- fprintf (stderr, "Error: state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
-
-yyerrhandle:
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
- yyn = yypact[yystate];
- if (yyn == YYFLAG)
- goto yyerrdefault;
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
- yyn += YYTERROR;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
- goto yyerrdefault;
- yyn = yytable[yyn];
- if (yyn < 0)
- {
- if (yyn == YYFLAG)
- goto yyerrpop;
- yyn = -yyn;
- goto yyreduce;
+ yydestruct ("Error: popping", yystos[yystate], yyvsp);
+ YYPOPSTACK;
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
}
- else if (yyn == 0)
- goto yyerrpop;
if (yyn == YYFINAL)
YYACCEPT;
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting error token, ");
-#endif
-
*++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
yystate = yyn;
goto yynewstate;
- yyacceptlab:
- /* YYACCEPT comes here. */
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yydestruct ("Error: discarding lookahead",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*----------------------------------------------.
+| yyoverflowlab -- parser overflow comes here. |
+`----------------------------------------------*/
+yyoverflowlab:
+ yyerror ("parser stack overflow");
+ yyresult = 2;
+ /* Fall through. */
#endif
- }
- return 0;
- yyabortlab:
- /* YYABORT comes here. */
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
+yyreturn:
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
#endif
- }
- return 1;
+ return yyresult;
}
-#line 463 "scripts/genksyms/parse.y"
+
+
+#line 464 "scripts/genksyms/parse.y"
static void
@@ -1575,3 +2048,4 @@ yyerror(const char *e)
{
error_with_pos("%s", e);
}
+
diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped
index d5b27e3b20c4..f3fb2bb058e1 100644
--- a/scripts/genksyms/parse.h_shipped
+++ b/scripts/genksyms/parse.h_shipped
@@ -1,46 +1,128 @@
-#ifndef YYSTYPE
-#define YYSTYPE int
+/* A Bison parser, made by GNU Bison 2.0. */
+
+/* Skeleton parser for Yacc-like parsing with Bison,
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, 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, 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ASM_KEYW = 258,
+ ATTRIBUTE_KEYW = 259,
+ AUTO_KEYW = 260,
+ BOOL_KEYW = 261,
+ CHAR_KEYW = 262,
+ CONST_KEYW = 263,
+ DOUBLE_KEYW = 264,
+ ENUM_KEYW = 265,
+ EXTERN_KEYW = 266,
+ FLOAT_KEYW = 267,
+ INLINE_KEYW = 268,
+ INT_KEYW = 269,
+ LONG_KEYW = 270,
+ REGISTER_KEYW = 271,
+ RESTRICT_KEYW = 272,
+ SHORT_KEYW = 273,
+ SIGNED_KEYW = 274,
+ STATIC_KEYW = 275,
+ STRUCT_KEYW = 276,
+ TYPEDEF_KEYW = 277,
+ UNION_KEYW = 278,
+ UNSIGNED_KEYW = 279,
+ VOID_KEYW = 280,
+ VOLATILE_KEYW = 281,
+ TYPEOF_KEYW = 282,
+ EXPORT_SYMBOL_KEYW = 283,
+ ASM_PHRASE = 284,
+ ATTRIBUTE_PHRASE = 285,
+ BRACE_PHRASE = 286,
+ BRACKET_PHRASE = 287,
+ EXPRESSION_PHRASE = 288,
+ CHAR = 289,
+ DOTS = 290,
+ IDENT = 291,
+ INT = 292,
+ REAL = 293,
+ STRING = 294,
+ TYPE = 295,
+ OTHER = 296,
+ FILENAME = 297
+ };
#endif
-#define ASM_KEYW 257
-#define ATTRIBUTE_KEYW 258
-#define AUTO_KEYW 259
-#define BOOL_KEYW 260
-#define CHAR_KEYW 261
-#define CONST_KEYW 262
-#define DOUBLE_KEYW 263
-#define ENUM_KEYW 264
-#define EXTERN_KEYW 265
-#define FLOAT_KEYW 266
-#define INLINE_KEYW 267
-#define INT_KEYW 268
-#define LONG_KEYW 269
-#define REGISTER_KEYW 270
-#define RESTRICT_KEYW 271
-#define SHORT_KEYW 272
-#define SIGNED_KEYW 273
-#define STATIC_KEYW 274
-#define STRUCT_KEYW 275
-#define TYPEDEF_KEYW 276
-#define UNION_KEYW 277
-#define UNSIGNED_KEYW 278
-#define VOID_KEYW 279
-#define VOLATILE_KEYW 280
-#define TYPEOF_KEYW 281
-#define EXPORT_SYMBOL_KEYW 282
-#define ASM_PHRASE 283
-#define ATTRIBUTE_PHRASE 284
-#define BRACE_PHRASE 285
-#define BRACKET_PHRASE 286
-#define EXPRESSION_PHRASE 287
-#define CHAR 288
-#define DOTS 289
-#define IDENT 290
-#define INT 291
-#define REAL 292
-#define STRING 293
-#define TYPE 294
-#define OTHER 295
-#define FILENAME 296
+#define ASM_KEYW 258
+#define ATTRIBUTE_KEYW 259
+#define AUTO_KEYW 260
+#define BOOL_KEYW 261
+#define CHAR_KEYW 262
+#define CONST_KEYW 263
+#define DOUBLE_KEYW 264
+#define ENUM_KEYW 265
+#define EXTERN_KEYW 266
+#define FLOAT_KEYW 267
+#define INLINE_KEYW 268
+#define INT_KEYW 269
+#define LONG_KEYW 270
+#define REGISTER_KEYW 271
+#define RESTRICT_KEYW 272
+#define SHORT_KEYW 273
+#define SIGNED_KEYW 274
+#define STATIC_KEYW 275
+#define STRUCT_KEYW 276
+#define TYPEDEF_KEYW 277
+#define UNION_KEYW 278
+#define UNSIGNED_KEYW 279
+#define VOID_KEYW 280
+#define VOLATILE_KEYW 281
+#define TYPEOF_KEYW 282
+#define EXPORT_SYMBOL_KEYW 283
+#define ASM_PHRASE 284
+#define ATTRIBUTE_PHRASE 285
+#define BRACE_PHRASE 286
+#define BRACKET_PHRASE 287
+#define EXPRESSION_PHRASE 288
+#define CHAR 289
+#define DOTS 290
+#define IDENT 291
+#define INT 292
+#define REAL 293
+#define STRING 294
+#define TYPE 295
+#define OTHER 296
+#define FILENAME 297
+
+
+#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
extern YYSTYPE yylval;
+
+
+
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 099043713db4..ca04c944b7c3 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -197,6 +197,7 @@ storage_class_specifier:
type_specifier:
simple_type_specifier
| cvar_qualifier
+ | TYPEOF_KEYW '(' decl_specifier_seq '*' ')'
| TYPEOF_KEYW '(' decl_specifier_seq ')'
/* References to s/u/e's defined elsewhere. Rearrange things
diff --git a/scripts/kconfig/.gitignore b/scripts/kconfig/.gitignore
index 2dac3442e0ac..e8ad1f6b3da4 100644
--- a/scripts/kconfig/.gitignore
+++ b/scripts/kconfig/.gitignore
@@ -5,6 +5,7 @@ config*
lex.*.c
*.tab.c
*.tab.h
+zconf.hash.c
#
# configuration programs
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index a96153fc793f..5760e057ecba 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -11,7 +11,7 @@ gconfig: $(obj)/gconf
$< arch/$(ARCH)/Kconfig
menuconfig: $(obj)/mconf
- $(Q)$(MAKE) $(build)=scripts/lxdialog
+ $(Q)$(MAKE) $(build)=scripts/kconfig/lxdialog
$< arch/$(ARCH)/Kconfig
config: $(obj)/conf
@@ -115,6 +115,7 @@ endif
clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
.tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c
+subdir- += lxdialog
# Needed for systems without gettext
KBUILD_HAVE_NLS := $(shell \
@@ -132,8 +133,8 @@ HOSTCFLAGS_zconf.tab.o := -I$(src)
HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl
HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK
-HOSTLOADLIBES_gconf = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --libs`
-HOSTCFLAGS_gconf.o = `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --cflags` \
+HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0`
+HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
-D LKC_DIRECT_LINK
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
@@ -192,8 +193,8 @@ ifeq ($(gconf-target),1)
# GTK needs some extra effort, too...
$(obj)/.tmp_gtkcheck:
- @if `pkg-config gtk+-2.0 gmodule-2.0 libglade-2.0 --exists`; then \
- if `pkg-config gtk+-2.0 --atleast-version=2.0.0`; then \
+ @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \
+ if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \
touch $@; \
else \
echo "*"; \
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 8ba5d29d3d42..10eeae53d827 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -63,6 +63,20 @@ static void check_stdin(void)
}
}
+static char *fgets_check_stream(char *s, int size, FILE *stream)
+{
+ char *ret = fgets(s, size, stream);
+
+ if (ret == NULL && feof(stream)) {
+ printf(_("aborted!\n\n"));
+ printf(_("Console input is closed. "));
+ printf(_("Run 'make oldconfig' to update configuration.\n\n"));
+ exit(1);
+ }
+
+ return ret;
+}
+
static void conf_askvalue(struct symbol *sym, const char *def)
{
enum symbol_type type = sym_get_type(sym);
@@ -100,7 +114,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
check_stdin();
case ask_all:
fflush(stdout);
- fgets(line, 128, stdin);
+ fgets_check_stream(line, 128, stdin);
return;
case set_default:
printf("%s\n", def);
@@ -356,7 +370,7 @@ static int conf_choice(struct menu *menu)
check_stdin();
case ask_all:
fflush(stdout);
- fgets(line, 128, stdin);
+ fgets_check_stream(line, 128, stdin);
strip(line);
if (line[0] == '?') {
printf("\n%s\n", menu->sym->help ?
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index ccd45130c482..b0cbbe2e41bb 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -375,7 +375,7 @@ int conf_write(const char *name)
if (!out_h)
return 1;
}
- sym = sym_lookup("KERNELRELEASE", 0);
+ sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
time(&now);
env = getenv("KCONFIG_NOTIMESTAMP");
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 9f5aabd58fa9..665bd5300a19 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -276,7 +276,7 @@ void init_main_window(const gchar * glade_file)
NULL);
sprintf(title, _("Linux Kernel v%s Configuration"),
- getenv("KERNELRELEASE"));
+ getenv("KERNELVERSION"));
gtk_window_set_title(GTK_WINDOW(main_wnd), title);
gtk_widget_show(main_wnd);
diff --git a/scripts/kconfig/lxdialog/.gitignore b/scripts/kconfig/lxdialog/.gitignore
new file mode 100644
index 000000000000..90b08ff025a6
--- /dev/null
+++ b/scripts/kconfig/lxdialog/.gitignore
@@ -0,0 +1,4 @@
+#
+# Generated files
+#
+lxdialog
diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
index a8999d82bdb3..a8999d82bdb3 100644
--- a/scripts/lxdialog/BIG.FAT.WARNING
+++ b/scripts/kconfig/lxdialog/BIG.FAT.WARNING
diff --git a/scripts/kconfig/lxdialog/Makefile b/scripts/kconfig/lxdialog/Makefile
new file mode 100644
index 000000000000..fae3e29fc924
--- /dev/null
+++ b/scripts/kconfig/lxdialog/Makefile
@@ -0,0 +1,18 @@
+# Makefile to build lxdialog package
+#
+
+check-lxdialog := $(srctree)/$(src)/check-lxdialog.sh
+HOST_EXTRACFLAGS:= $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
+HOST_LOADLIBES := $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
+
+HOST_EXTRACFLAGS += -DLOCALE
+
+.PHONY: dochecklxdialog
+$(obj)/dochecklxdialog:
+ $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES)
+
+hostprogs-y := lxdialog
+always := $(hostprogs-y) dochecklxdialog
+
+lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
+ util.o lxdialog.o msgbox.o
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
new file mode 100644
index 000000000000..448e353923f3
--- /dev/null
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+# Check ncurses compatibility
+
+# What library to link
+ldflags()
+{
+ echo "main() {}" | $cc -lncursesw -xc - -o /dev/null 2> /dev/null
+ if [ $? -eq 0 ]; then
+ echo '-lncursesw'
+ exit
+ fi
+ echo "main() {}" | $cc -lncurses -xc - -o /dev/null 2> /dev/null
+ if [ $? -eq 0 ]; then
+ echo '-lncurses'
+ exit
+ fi
+ echo "main() {}" | $cc -lcurses -xc - -o /dev/null 2> /dev/null
+ if [ $? -eq 0 ]; then
+ echo '-lcurses'
+ exit
+ fi
+ exit 1
+}
+
+# Where is ncurses.h?
+ccflags()
+{
+ if [ -f /usr/include/ncurses/ncurses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
+ elif [ -f /usr/include/ncurses/curses.h ]; then
+ echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
+ elif [ -f /usr/include/ncurses.h ]; then
+ echo '-DCURSES_LOC="<ncurses.h>"'
+ else
+ echo '-DCURSES_LOC="<curses.h>"'
+ fi
+}
+
+compiler=""
+# Check if we can link to ncurses
+check() {
+ echo "main() {}" | $cc -xc - -o /dev/null 2> /dev/null
+ if [ $? != 0 ]; then
+ echo " *** Unable to find the ncurses libraries." 1>&2
+ echo " *** make menuconfig require the ncurses libraries" 1>&2
+ echo " *** " 1>&2
+ echo " *** Install ncurses (ncurses-devel) and try again" 1>&2
+ echo " *** " 1>&2
+ exit 1
+ fi
+}
+
+usage() {
+ printf "Usage: $0 [-check compiler options|-header|-library]\n"
+}
+
+if [ $# == 0 ]; then
+ usage
+ exit 1
+fi
+
+case "$1" in
+ "-check")
+ shift
+ cc="$@"
+ check
+ ;;
+ "-ccflags")
+ ccflags
+ ;;
+ "-ldflags")
+ shift
+ cc="$@"
+ ldflags
+ ;;
+ "*")
+ usage
+ exit 1
+ ;;
+esac
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
new file mode 100644
index 000000000000..db07ae73e051
--- /dev/null
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -0,0 +1,334 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
+ * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+static int list_width, check_x, item_x;
+
+/*
+ * Print list item
+ */
+static void print_item(WINDOW * win, const char *item, int status, int choice,
+ int selected)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch(win, ' ');
+
+ wmove(win, choice, check_x);
+ wattrset(win, selected ? check_selected_attr : check_attr);
+ wprintw(win, "(%c)", status ? 'X' : ' ');
+
+ wattrset(win, selected ? tag_selected_attr : tag_attr);
+ mvwaddch(win, choice, item_x, item[0]);
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ waddstr(win, (char *)item + 1);
+ if (selected) {
+ wmove(win, choice, check_x + 1);
+ wrefresh(win);
+ }
+}
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int choice, int item_no, int scroll,
+ int y, int x, int height)
+{
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, uarrow_attr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, menubox_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+
+ if ((height < item_no) && (scroll + choice < item_no - 1)) {
+ wattrset(win, darrow_attr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, menubox_border_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+}
+
+/*
+ * Display the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, "Select", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ * in the style of radiolist (only one option turned on at a time).
+ */
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char *const *items)
+{
+ int i, x, y, box_x, box_y;
+ int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
+ WINDOW *dialog, *list;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = malloc(sizeof(int) * item_no)) == NULL) {
+ endwin();
+ fprintf(stderr,
+ "\nCan't allocate memory in dialog_checklist().\n");
+ exit(-1);
+ }
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = !strcasecmp(items[i * 3 + 2], "on");
+ if ((!choice && status[i])
+ || !strcasecmp(items[i * 3 + 2], "selected"))
+ choice = i + 1;
+ }
+ if (choice)
+ choice--;
+
+ max_choice = MIN(list_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ list_width = width - 6;
+ box_y = height - list_height - 5;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin(dialog, list_height, list_width, y + box_y + 1,
+ x + box_x + 1);
+
+ keypad(list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Find length of longest item in order to center checklist */
+ check_x = 0;
+ for (i = 0; i < item_no; i++)
+ check_x = MAX(check_x, +strlen(items[i * 3 + 1]) + 4);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + 4;
+
+ if (choice >= list_height) {
+ scroll = choice - list_height + 1;
+ choice -= scroll;
+ }
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++) {
+ print_item(list, items[(scroll + i) * 3 + 1],
+ status[i + scroll], i, i == choice);
+ }
+
+ print_arrows(dialog, choice, item_no, scroll,
+ box_y, box_x + check_x + 5, list_height);
+
+ print_buttons(dialog, height, width, 0);
+
+ wnoutrefresh(list);
+ wnoutrefresh(dialog);
+ doupdate();
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ for (i = 0; i < max_choice; i++)
+ if (toupper(key) ==
+ toupper(items[(scroll + i) * 3 + 1][0]))
+ break;
+
+ if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
+ key == '+' || key == '-') {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (!scroll)
+ continue;
+ /* Scroll list down */
+ if (list_height > 1) {
+ /* De-highlight current first item */
+ print_item(list, items[scroll * 3 + 1],
+ status[scroll], 0, FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, -1);
+ scrollok(list, FALSE);
+ }
+ scroll--;
+ print_item(list, items[scroll * 3 + 1], status[scroll], 0, TRUE);
+ wnoutrefresh(list);
+
+ print_arrows(dialog, choice, item_no,
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wrefresh(dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice - 1;
+ } else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll + choice >= item_no - 1)
+ continue;
+ /* Scroll list up */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1],
+ max_choice - 1, FALSE);
+ scrollok(list, TRUE);
+ wscrl(list, 1);
+ scrollok(list, FALSE);
+ }
+ scroll++;
+ print_item(list, items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1, TRUE);
+ wnoutrefresh(list);
+
+ print_arrows(dialog, choice, item_no,
+ scroll, box_y, box_x + check_x + 5, list_height);
+
+ wrefresh(dialog);
+
+ continue; /* wait for another key press */
+ } else
+ i = choice + 1;
+ }
+ if (i != choice) {
+ /* De-highlight current item */
+ print_item(list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, FALSE);
+ /* Highlight new item */
+ choice = i;
+ print_item(list, items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, TRUE);
+ wnoutrefresh(list);
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ switch (key) {
+ case 'H':
+ case 'h':
+ case '?':
+ fprintf(stderr, "%s", items[(scroll + choice) * 3]);
+ delwin(dialog);
+ free(status);
+ return 1;
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case 'S':
+ case 's':
+ case ' ':
+ case '\n':
+ if (!button) {
+ if (!status[scroll + choice]) {
+ for (i = 0; i < item_no; i++)
+ status[i] = 0;
+ status[scroll + choice] = 1;
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice);
+ }
+ wnoutrefresh(list);
+ wrefresh(dialog);
+
+ for (i = 0; i < item_no; i++)
+ if (status[i])
+ fprintf(stderr, "%s", items[i * 3]);
+ } else
+ fprintf(stderr, "%s", items[(scroll + choice) * 3]);
+ delwin(dialog);
+ free(status);
+ return button;
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+
+ /* Now, update everything... */
+ doupdate();
+ }
+
+ delwin(dialog);
+ free(status);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/lxdialog/colors.h b/scripts/kconfig/lxdialog/colors.h
index 25c59528a251..db071df12bbb 100644
--- a/scripts/lxdialog/colors.h
+++ b/scripts/kconfig/lxdialog/colors.h
@@ -18,7 +18,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
/*
* Default color definitions
*
diff --git a/scripts/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index eb63e1bb63a3..af3cf716e215 100644
--- a/scripts/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -1,4 +1,3 @@
-
/*
* dialog.h -- common declarations for all dialog modules
*
@@ -42,7 +41,7 @@
#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE)
#define OLD_NCURSES 1
#undef wbkgdset
-#define wbkgdset(w,p) /*nothing*/
+#define wbkgdset(w,p) /*nothing */
#else
#define OLD_NCURSES 0
#endif
@@ -56,7 +55,6 @@
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
-
#ifndef ACS_ULCORNER
#define ACS_ULCORNER '+'
#endif
@@ -88,7 +86,7 @@
#define ACS_DARROW 'v'
#endif
-/*
+/*
* Attribute names
*/
#define screen_attr attributes[0]
@@ -137,35 +135,35 @@ extern const char *backtitle;
/*
* Function prototypes
*/
-extern void create_rc (const char *filename);
-extern int parse_rc (void);
-
-
-void init_dialog (void);
-void end_dialog (void);
-void attr_clear (WINDOW * win, int height, int width, chtype attr);
-void dialog_clear (void);
-void color_setup (void);
-void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x);
-void print_button (WINDOW * win, const char *label, int y, int x, int selected);
-void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box,
- chtype border);
-void draw_shadow (WINDOW * win, int y, int x, int height, int width);
-
-int first_alpha (const char *string, const char *exempt);
-int dialog_yesno (const char *title, const char *prompt, int height, int width);
-int dialog_msgbox (const char *title, const char *prompt, int height,
- int width, int pause);
-int dialog_textbox (const char *title, const char *file, int height, int width);
-int dialog_menu (const char *title, const char *prompt, int height, int width,
- int menu_height, const char *choice, int item_no,
- const char * const * items);
-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 void create_rc(const char *filename);
+extern int parse_rc(void);
+
+void init_dialog(void);
+void end_dialog(void);
+void attr_clear(WINDOW * win, int height, int width, chtype attr);
+void dialog_clear(void);
+void color_setup(void);
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x);
+void print_button(WINDOW * win, const char *label, int y, int x, int selected);
+void print_title(WINDOW *dialog, const char *title, int width);
+void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
+ chtype border);
+void draw_shadow(WINDOW * win, int y, int x, int height, int width);
+
+int first_alpha(const char *string, const char *exempt);
+int dialog_yesno(const char *title, const char *prompt, int height, int width);
+int dialog_msgbox(const char *title, const char *prompt, int height,
+ int width, int pause);
+int dialog_textbox(const char *title, const char *file, int height, int width);
+int dialog_menu(const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *choice, int item_no,
+ const char *const *items);
+int dialog_checklist(const char *title, const char *prompt, int height,
+ int width, int list_height, int item_no,
+ const char *const *items);
extern char dialog_input_result[];
-int dialog_inputbox (const char *title, const char *prompt, int height,
- int width, const char *init);
+int dialog_inputbox(const char *title, const char *prompt, int height,
+ int width, const char *init);
/*
* This is the base for fictitious keys, which activate
@@ -177,11 +175,3 @@ int dialog_inputbox (const char *title, const char *prompt, int height,
* -- uppercase chars are used to invoke the button (M_EVENT + 'O')
*/
#define M_EVENT (KEY_MAX+1)
-
-
-/*
- * The `flag' parameter in checklist is used to select between
- * radiolist and checklist
- */
-#define FLAG_CHECK 1
-#define FLAG_RADIO 0
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c
new file mode 100644
index 000000000000..779503726b0a
--- /dev/null
+++ b/scripts/kconfig/lxdialog/inputbox.c
@@ -0,0 +1,224 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+char dialog_input_result[MAX_LEN + 1];
+
+/*
+ * Print the termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 11;
+ int y = height - 2;
+
+ print_button(dialog, " Ok ", y, x, selected == 0);
+ print_button(dialog, " Help ", y, x + 14, selected == 1);
+
+ wmove(dialog, y, x + 1 + 14 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int dialog_inputbox(const char *title, const char *prompt, int height, int width,
+ const char *init)
+{
+ int i, x, y, box_y, box_x, box_width;
+ int input_x = 0, scroll = 0, key = 0, button = -1;
+ char *instr = dialog_input_result;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ /* Draw the input field box */
+ box_width = width - 6;
+ getyx(dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width) / 2;
+ draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, border_attr, dialog_attr);
+
+ print_buttons(dialog, height, width, 0);
+
+ /* Set up the initial value */
+ wmove(dialog, box_y, box_x);
+ wattrset(dialog, inputbox_attr);
+
+ if (!init)
+ instr[0] = '\0';
+ else
+ strcpy(instr, init);
+
+ input_x = strlen(instr);
+
+ if (input_x >= box_width) {
+ scroll = input_x - box_width + 1;
+ input_x = box_width - 1;
+ for (i = 0; i < box_width - 1; i++)
+ waddch(dialog, instr[scroll + i]);
+ } else {
+ waddstr(dialog, instr);
+ }
+
+ wmove(dialog, box_y, box_x + input_x);
+
+ wrefresh(dialog);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ if (button == -1) { /* Input box selected */
+ switch (key) {
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ break;
+ case KEY_LEFT:
+ continue;
+ case KEY_RIGHT:
+ continue;
+ case KEY_BACKSPACE:
+ case 127:
+ if (input_x || scroll) {
+ wattrset(dialog, inputbox_attr);
+ if (!input_x) {
+ scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1);
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width; i++)
+ waddch(dialog,
+ instr[scroll + input_x + i] ?
+ instr[scroll + input_x + i] : ' ');
+ input_x = strlen(instr) - scroll;
+ } else
+ input_x--;
+ instr[scroll + input_x] = '\0';
+ mvwaddch(dialog, box_y, input_x + box_x, ' ');
+ wmove(dialog, box_y, input_x + box_x);
+ wrefresh(dialog);
+ }
+ continue;
+ default:
+ if (key < 0x100 && isprint(key)) {
+ if (scroll + input_x < MAX_LEN) {
+ wattrset(dialog, inputbox_attr);
+ instr[scroll + input_x] = key;
+ instr[scroll + input_x + 1] = '\0';
+ if (input_x == box_width - 1) {
+ scroll++;
+ wmove(dialog, box_y, box_x);
+ for (i = 0; i < box_width - 1; i++)
+ waddch(dialog, instr [scroll + i]);
+ } else {
+ wmove(dialog, box_y, input_x++ + box_x);
+ waddch(dialog, key);
+ }
+ wrefresh(dialog);
+ } else
+ flash(); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin(dialog);
+ return 0;
+ case 'H':
+ case 'h':
+ delwin(dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_buttons(dialog, height, width, 0);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_buttons(dialog, height, width, 1);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_buttons(dialog, height, width, 0);
+ wmove(dialog, box_y, box_x + input_x);
+ wrefresh(dialog);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return (button == -1 ? 0 : button);
+ case 'X':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/kconfig/lxdialog/lxdialog.c b/scripts/kconfig/lxdialog/lxdialog.c
new file mode 100644
index 000000000000..79f6c5fb5cef
--- /dev/null
+++ b/scripts/kconfig/lxdialog/lxdialog.c
@@ -0,0 +1,204 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+static void Usage(const char *name);
+
+typedef int (jumperFn) (const char *title, int argc, const char *const *argv);
+
+struct Mode {
+ char *name;
+ int argmin, argmax, argmod;
+ jumperFn *jumper;
+};
+
+jumperFn j_menu, j_radiolist, j_yesno, j_textbox, j_inputbox;
+jumperFn j_msgbox, j_infobox;
+
+static struct Mode modes[] = {
+ {"--menu", 9, 0, 3, j_menu},
+ {"--radiolist", 9, 0, 3, j_radiolist},
+ {"--yesno", 5, 5, 1, j_yesno},
+ {"--textbox", 5, 5, 1, j_textbox},
+ {"--inputbox", 5, 6, 1, j_inputbox},
+ {"--msgbox", 5, 5, 1, j_msgbox},
+ {"--infobox", 5, 5, 1, j_infobox},
+ {NULL, 0, 0, 0, NULL}
+};
+
+static struct Mode *modePtr;
+
+#ifdef LOCALE
+#include <locale.h>
+#endif
+
+int main(int argc, const char *const *argv)
+{
+ int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
+ const char *title = NULL;
+
+#ifdef LOCALE
+ (void)setlocale(LC_ALL, "");
+#endif
+
+#ifdef TRACE
+ trace(TRACE_CALLS | TRACE_UPDATE);
+#endif
+ if (argc < 2) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+
+ while (offset < argc - 1 && !end_common_opts) { /* Common options */
+ if (!strcmp(argv[offset + 1], "--title")) {
+ if (argc - offset < 3 || title != NULL) {
+ Usage(argv[0]);
+ exit(-1);
+ } else {
+ title = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp(argv[offset + 1], "--backtitle")) {
+ if (backtitle != NULL) {
+ Usage(argv[0]);
+ exit(-1);
+ } else {
+ backtitle = argv[offset + 2];
+ offset += 2;
+ }
+ } else if (!strcmp(argv[offset + 1], "--clear")) {
+ if (opt_clear) { /* Hey, "--clear" can't appear twice! */
+ Usage(argv[0]);
+ exit(-1);
+ } else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog();
+ refresh(); /* init_dialog() will clear the screen for us */
+ end_dialog();
+ return 0;
+ } else {
+ opt_clear = 1;
+ offset++;
+ }
+ } else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc - 1 == offset) { /* no more options */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ /* use a table to look for the requested mode, to avoid code duplication */
+
+ for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
+ if (!strcmp(argv[offset + 1], modePtr->name))
+ break;
+
+ if (!modePtr->name)
+ Usage(argv[0]);
+ if (argc - offset < modePtr->argmin)
+ Usage(argv[0]);
+ if (modePtr->argmax && argc - offset > modePtr->argmax)
+ Usage(argv[0]);
+
+ init_dialog();
+ retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
+
+ if (opt_clear) { /* clear screen before exit */
+ attr_clear(stdscr, LINES, COLS, screen_attr);
+ refresh();
+ }
+ end_dialog();
+
+ exit(retval);
+}
+
+/*
+ * Print program usage
+ */
+static void Usage(const char *name)
+{
+ fprintf(stderr, "\
+\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n modified/gutted for use as a Linux kernel config tool by \
+\n William Roadcap (roadcapw@cfw.com)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --textbox <file> <height> <width>\
+\n --inputbox <text> <height> <width> [<init>]\
+\n --yesno <text> <height> <width>\
+\n", name, name);
+ exit(-1);
+}
+
+/*
+ * These are the program jumpers
+ */
+
+int j_menu(const char *t, int ac, const char *const *av)
+{
+ return dialog_menu(t, av[2], atoi(av[3]), atoi(av[4]),
+ atoi(av[5]), av[6], (ac - 6) / 2, av + 7);
+}
+
+int j_radiolist(const char *t, int ac, const char *const *av)
+{
+ return dialog_checklist(t, av[2], atoi(av[3]), atoi(av[4]),
+ atoi(av[5]), (ac - 6) / 3, av + 6);
+}
+
+int j_textbox(const char *t, int ac, const char *const *av)
+{
+ return dialog_textbox(t, av[2], atoi(av[3]), atoi(av[4]));
+}
+
+int j_yesno(const char *t, int ac, const char *const *av)
+{
+ return dialog_yesno(t, av[2], atoi(av[3]), atoi(av[4]));
+}
+
+int j_inputbox(const char *t, int ac, const char *const *av)
+{
+ int ret = dialog_inputbox(t, av[2], atoi(av[3]), atoi(av[4]),
+ ac == 6 ? av[5] : (char *)NULL);
+ if (ret == 0)
+ fprintf(stderr, dialog_input_result);
+ return ret;
+}
+
+int j_msgbox(const char *t, int ac, const char *const *av)
+{
+ return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 1);
+}
+
+int j_infobox(const char *t, int ac, const char *const *av)
+{
+ return dialog_msgbox(t, av[2], atoi(av[3]), atoi(av[4]), 0);
+}
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c
new file mode 100644
index 000000000000..09512b544375
--- /dev/null
+++ b/scripts/kconfig/lxdialog/menubox.c
@@ -0,0 +1,425 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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.
+ */
+
+/*
+ * Changes by Clifford Wolf (god@clifford.at)
+ *
+ * [ 1998-06-13 ]
+ *
+ * *) A bugfix for the Page-Down problem
+ *
+ * *) Formerly when I used Page Down and Page Up, the cursor would be set
+ * to the first position in the menu box. Now lxdialog is a bit
+ * smarter and works more like other menu systems (just have a look at
+ * it).
+ *
+ * *) Formerly if I selected something my scrolling would be broken because
+ * lxdialog is re-invoked by the Menuconfig shell script, can't
+ * remember the last scrolling position, and just sets it so that the
+ * cursor is at the bottom of the box. Now it writes the temporary file
+ * lxdialog.scrltmp which contains this information. The file is
+ * deleted by lxdialog if the user leaves a submenu or enters a new
+ * one, but it would be nice if Menuconfig could make another "rm -f"
+ * just to be sure. Just try it out - you will recognise a difference!
+ *
+ * [ 1998-06-14 ]
+ *
+ * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
+ * and menus change their size on the fly.
+ *
+ * *) If for some reason the last scrolling position is not saved by
+ * lxdialog, it sets the scrolling so that the selected item is in the
+ * middle of the menu box, not at the bottom.
+ *
+ * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
+ * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
+ * This fixes a bug in Menuconfig where using ' ' to descend into menus
+ * would leave mis-synchronized lxdialog.scrltmp files lying around,
+ * fscanf would read in 'scroll', and eventually that value would get used.
+ */
+
+#include "dialog.h"
+
+#define ITEM_IDENT 1 /* Indent of menu entries. Fixed for all menus */
+static int menu_width;
+
+/*
+ * Print menu item
+ */
+static void do_print_item(WINDOW * win, const char *item, int choice,
+ int selected, int hotkey)
+{
+ int j;
+ char *menu_item = malloc(menu_width + 1);
+
+ strncpy(menu_item, item, menu_width - ITEM_IDENT);
+ menu_item[menu_width] = 0;
+ j = first_alpha(menu_item, "YyNnMmHh");
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < menu_width; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ mvwaddstr(win, choice, ITEM_IDENT, menu_item);
+ if (hotkey) {
+ wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
+ mvwaddch(win, choice, ITEM_IDENT + j, menu_item[j]);
+ }
+ if (selected) {
+ wmove(win, choice, ITEM_IDENT + 1);
+ }
+ free(menu_item);
+ wrefresh(win);
+}
+
+#define print_item(index, choice, selected) \
+do {\
+ int hotkey = (items[(index) * 2][0] != ':'); \
+ do_print_item(menu, items[(index) * 2 + 1], choice, selected, hotkey); \
+} while (0)
+
+/*
+ * Print the scroll indicators.
+ */
+static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
+ int height)
+{
+ int cur_y, cur_x;
+
+ getyx(win, cur_y, cur_x);
+
+ wmove(win, y, x);
+
+ if (scroll > 0) {
+ wattrset(win, uarrow_attr);
+ waddch(win, ACS_UARROW);
+ waddstr(win, "(-)");
+ } else {
+ wattrset(win, menubox_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ y = y + height + 1;
+ wmove(win, y, x);
+ wrefresh(win);
+
+ if ((height < item_no) && (scroll + height < item_no)) {
+ wattrset(win, darrow_attr);
+ waddch(win, ACS_DARROW);
+ waddstr(win, "(+)");
+ } else {
+ wattrset(win, menubox_border_attr);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ waddch(win, ACS_HLINE);
+ }
+
+ wmove(win, cur_y, cur_x);
+ wrefresh(win);
+}
+
+/*
+ * Display the termination buttons.
+ */
+static void print_buttons(WINDOW * win, int height, int width, int selected)
+{
+ int x = width / 2 - 16;
+ int y = height - 2;
+
+ print_button(win, "Select", y, x, selected == 0);
+ print_button(win, " Exit ", y, x + 12, selected == 1);
+ print_button(win, " Help ", y, x + 24, selected == 2);
+
+ wmove(win, y, x + 1 + 12 * selected);
+ wrefresh(win);
+}
+
+/* scroll up n lines (n may be negative) */
+static void do_scroll(WINDOW *win, int *scroll, int n)
+{
+ /* Scroll menu up */
+ scrollok(win, TRUE);
+ wscrl(win, n);
+ scrollok(win, FALSE);
+ *scroll = *scroll + n;
+ wrefresh(win);
+}
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int dialog_menu(const char *title, const char *prompt, int height, int width,
+ int menu_height, const char *current, int item_no,
+ const char *const *items)
+{
+ int i, j, x, y, box_x, box_y;
+ int key = 0, button = 0, scroll = 0, choice = 0;
+ int first_item = 0, max_choice;
+ WINDOW *dialog, *menu;
+ FILE *f;
+
+ max_choice = MIN(menu_height, item_no);
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ wbkgdset(dialog, dialog_attr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ menu_width = width - 6;
+ box_y = height - menu_height - 5;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin(dialog, menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ keypad(menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
+ menubox_border_attr, menubox_attr);
+
+ /* Set choice to default item */
+ for (i = 0; i < item_no; i++)
+ if (strcmp(current, items[i * 2]) == 0)
+ choice = i;
+
+ /* get the scroll info from the temp file */
+ if ((f = fopen("lxdialog.scrltmp", "r")) != NULL) {
+ if ((fscanf(f, "%d\n", &scroll) == 1) && (scroll <= choice) &&
+ (scroll + max_choice > choice) && (scroll >= 0) &&
+ (scroll + max_choice <= item_no)) {
+ first_item = scroll;
+ choice = choice - scroll;
+ fclose(f);
+ } else {
+ scroll = 0;
+ remove("lxdialog.scrltmp");
+ fclose(f);
+ f = NULL;
+ }
+ }
+ if ((choice >= max_choice) || (f == NULL && choice >= max_choice / 2)) {
+ if (choice >= item_no - max_choice / 2)
+ scroll = first_item = item_no - max_choice;
+ else
+ scroll = first_item = choice - max_choice / 2;
+ choice = choice - scroll;
+ }
+
+ /* Print the menu */
+ for (i = 0; i < max_choice; i++) {
+ print_item(first_item + i, i, i == choice);
+ }
+
+ wnoutrefresh(menu);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x + ITEM_IDENT + 1, menu_height);
+
+ print_buttons(dialog, height, width, 0);
+ wmove(menu, choice, ITEM_IDENT + 1);
+ wrefresh(menu);
+
+ while (key != ESC) {
+ key = wgetch(menu);
+
+ if (key < 256 && isalpha(key))
+ key = tolower(key);
+
+ if (strchr("ynmh", key))
+ i = max_choice;
+ else {
+ for (i = choice + 1; i < max_choice; i++) {
+ j = first_alpha(items[(scroll + i) * 2 + 1], "YyNnMmHh");
+ if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ break;
+ }
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++) {
+ j = first_alpha(items [(scroll + i) * 2 + 1], "YyNnMmHh");
+ if (key == tolower(items[(scroll + i) * 2 + 1][j]))
+ break;
+ }
+ }
+
+ if (i < max_choice ||
+ key == KEY_UP || key == KEY_DOWN ||
+ key == '-' || key == '+' ||
+ key == KEY_PPAGE || key == KEY_NPAGE) {
+ /* Remove highligt of current item */
+ print_item(scroll + choice, choice, FALSE);
+
+ if (key == KEY_UP || key == '-') {
+ if (choice < 2 && scroll) {
+ /* Scroll menu down */
+ do_scroll(menu, &scroll, -1);
+
+ print_item(scroll, 0, FALSE);
+ } else
+ choice = MAX(choice - 1, 0);
+
+ } else if (key == KEY_DOWN || key == '+') {
+ print_item(scroll+choice, choice, FALSE);
+
+ if ((choice > max_choice - 3) &&
+ (scroll + max_choice < item_no)) {
+ /* Scroll menu up */
+ do_scroll(menu, &scroll, 1);
+
+ print_item(scroll+max_choice - 1,
+ max_choice - 1, FALSE);
+ } else
+ choice = MIN(choice + 1, max_choice - 1);
+
+ } else if (key == KEY_PPAGE) {
+ scrollok(menu, TRUE);
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll > 0) {
+ do_scroll(menu, &scroll, -1);
+ print_item(scroll, 0, FALSE);
+ } else {
+ if (choice > 0)
+ choice--;
+ }
+ }
+
+ } else if (key == KEY_NPAGE) {
+ for (i = 0; (i < max_choice); i++) {
+ if (scroll + max_choice < item_no) {
+ do_scroll(menu, &scroll, 1);
+ print_item(scroll+max_choice-1,
+ max_choice - 1, FALSE);
+ } else {
+ if (choice + 1 < max_choice)
+ choice++;
+ }
+ }
+ } else
+ choice = i;
+
+ print_item(scroll + choice, choice, TRUE);
+
+ print_arrows(dialog, item_no, scroll,
+ box_y, box_x + ITEM_IDENT + 1, menu_height);
+
+ wnoutrefresh(dialog);
+ wrefresh(menu);
+
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_LEFT:
+ case TAB:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0)
+ ? 2 : (button > 2 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(menu);
+ break;
+ case ' ':
+ case 's':
+ case 'y':
+ case 'n':
+ case 'm':
+ case '/':
+ /* save scroll info */
+ if ((f = fopen("lxdialog.scrltmp", "w")) != NULL) {
+ fprintf(f, "%d\n", scroll);
+ fclose(f);
+ }
+ delwin(dialog);
+ fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
+ switch (key) {
+ case 's':
+ return 3;
+ case 'y':
+ return 3;
+ case 'n':
+ return 4;
+ case 'm':
+ return 5;
+ case ' ':
+ return 6;
+ case '/':
+ return 7;
+ }
+ return 0;
+ case 'h':
+ case '?':
+ button = 2;
+ case '\n':
+ delwin(dialog);
+ if (button == 2)
+ fprintf(stderr, "%s \"%s\"\n",
+ items[(scroll + choice) * 2],
+ items[(scroll + choice) * 2 + 1] +
+ first_alpha(items [(scroll + choice) * 2 + 1], ""));
+ else
+ fprintf(stderr, "%s\n",
+ items[(scroll + choice) * 2]);
+
+ remove("lxdialog.scrltmp");
+ return button;
+ case 'e':
+ case 'x':
+ key = ESC;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ remove("lxdialog.scrltmp");
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/kconfig/lxdialog/msgbox.c b/scripts/kconfig/lxdialog/msgbox.c
new file mode 100644
index 000000000000..7323f5471f69
--- /dev/null
+++ b/scripts/kconfig/lxdialog/msgbox.c
@@ -0,0 +1,71 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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 "dialog.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int dialog_msgbox(const char *title, const char *prompt, int height, int width,
+ int pause)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 2);
+
+ if (pause) {
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_button(dialog, " Ok ", height - 2, width / 2 - 4, TRUE);
+
+ wrefresh(dialog);
+ while (key != ESC && key != '\n' && key != ' ' &&
+ key != 'O' && key != 'o' && key != 'X' && key != 'x')
+ key = wgetch(dialog);
+ } else {
+ key = '\n';
+ wrefresh(dialog);
+ }
+
+ delwin(dialog);
+ return key == ESC ? -1 : 0;
+}
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
new file mode 100644
index 000000000000..77848bb8e07f
--- /dev/null
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -0,0 +1,533 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+static void back_lines(int n);
+static void print_page(WINDOW * win, int height, int width);
+static void print_line(WINDOW * win, int row, int width);
+static char *get_line(void);
+static void print_position(WINDOW * win, int height, int width);
+
+static int hscroll, fd, file_size, bytes_read;
+static int begin_reached = 1, end_reached, page_length;
+static char *buf, *page;
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int dialog_textbox(const char *title, const char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0;
+ int passed_end;
+ char search_term[MAX_LEN + 1];
+ WINDOW *dialog, *text;
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open(file, O_RDONLY)) == -1) {
+ endwin();
+ fprintf(stderr, "\nCan't open input file in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc(BUF_SIZE + 1)) == NULL) {
+ endwin();
+ fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+ text = subwin(dialog, height - 4, width - 2, y + 1, x + 1);
+ wattrset(text, dialog_attr);
+ wbkgdset(text, dialog_attr & A_COLOR);
+
+ keypad(text, TRUE);
+
+ /* register the new window, along with its borders */
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ wbkgdset(dialog, dialog_attr & A_COLOR);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
+ wnoutrefresh(dialog);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear(text, height - 4, width - 2, dialog_attr);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+
+ while ((key != ESC) && (key != '\n')) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ case 'X':
+ case 'x':
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'G': /* Last page */
+ case KEY_END:
+
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines(height - 4);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case KEY_UP:
+ if (!begin_reached) {
+ back_lines(page_length + 1);
+
+ /* We don't call print_page() here but use scrolling to ensure
+ faster screen update. However, 'end_reached' and
+ 'page_length' should still be updated, and 'page' should
+ point to start of next page. This is done by calling
+ get_line() in the following 'for' loop. */
+ scrollok(text, TRUE);
+ wscrl(text, -1); /* Scroll text region down one line */
+ scrollok(text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height - 4; i++) {
+ if (!i) {
+ /* print first line of page */
+ print_line(text, 0, width - 2);
+ wnoutrefresh(text);
+ } else
+ /* Called to update 'end_reached' and 'page' */
+ get_line();
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (begin_reached)
+ break;
+ back_lines(page_length + height - 4);
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok(text, TRUE);
+ scroll(text); /* Scroll text region up one line */
+ scrollok(text, FALSE);
+ print_line(text, height - 5, width - 2);
+ wnoutrefresh(text);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case KEY_NPAGE: /* Next page */
+ case ' ':
+ if (end_reached)
+ break;
+
+ begin_reached = 0;
+ print_page(text, height - 4, width - 2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll <= 0)
+ break;
+
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height - 4, width - 2);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll >= MAX_LEN)
+ break;
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height - 4, width - 2);
+ wmove(dialog, cur_y, cur_x);
+ wrefresh(dialog);
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return -1; /* ESC pressed */
+}
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void back_lines(int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached
+ since at end of file, the line is not ended by a '\n'.
+ The code inside 'if' basically does a '--page' to move one
+ character backward so as to skip '\n' of the previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of
+ file yet, so read previous part of file into buffer.
+ Note that we only move backward for BUF_SIZE/2 bytes,
+ but not BUF_SIZE bytes to avoid re-reading again in
+ print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin();
+ fprintf(stderr, "\nInternal error in back_lines().\n");
+ exit(-1);
+ }
+ }
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE / 2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer "
+ "in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ } else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer"
+ " in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE / 2;
+ }
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in "
+ "back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ } else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void print_page(WINDOW * win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line(win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh(win);
+}
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void print_line(WINDOW * win, int row, int width)
+{
+ int y, x;
+ char *line;
+
+ line = get_line();
+ line += MIN(strlen(line), hscroll); /* Scroll horizontally */
+ wmove(win, row, 0); /* move cursor to correct line */
+ waddch(win, ' ');
+ waddnstr(win, line, MIN(strlen(line), width - 2));
+
+ getyx(win, y, x);
+ /* Clear 'residue' of previous line */
+#if OLD_NCURSES
+ {
+ int i;
+ for (i = 0; i < width - x; i++)
+ waddch(win, ' ');
+ }
+#else
+ wclrtoeol(win);
+#endif
+}
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static char *get_line(void)
+{
+ int i = 0, fpos;
+ static char line[MAX_LEN + 1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') {
+ /* Either end of file or end of buffer reached */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in "
+ "get_line().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet,
+ so read next part of file into buffer */
+ if ((bytes_read =
+ read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in get_line().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ } else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ } else if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ /* Truncate lines longer than MAX_LEN characters */
+ if (i == MAX_LEN)
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW * win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in print_position().\n");
+ exit(-1);
+ }
+ wattrset(win, position_indicator_attr);
+ wbkgdset(win, position_indicator_attr & A_COLOR);
+ percent = !file_size ?
+ 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
+ wmove(win, height - 3, width - 9);
+ wprintw(win, "(%3d%%)", percent);
+}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
new file mode 100644
index 000000000000..f82cebb9ff06
--- /dev/null
+++ b/scripts/kconfig/lxdialog/util.c
@@ -0,0 +1,362 @@
+/*
+ * util.c
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+/* use colors by default? */
+bool use_colors = 1;
+
+const char *backtitle = NULL;
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] = {
+ A_NORMAL, /* screen_attr */
+ A_NORMAL, /* shadow_attr */
+ A_NORMAL, /* dialog_attr */
+ A_BOLD, /* title_attr */
+ A_NORMAL, /* border_attr */
+ A_REVERSE, /* button_active_attr */
+ A_DIM, /* button_inactive_attr */
+ A_REVERSE, /* button_key_active_attr */
+ A_BOLD, /* button_key_inactive_attr */
+ A_REVERSE, /* button_label_active_attr */
+ A_NORMAL, /* button_label_inactive_attr */
+ A_NORMAL, /* inputbox_attr */
+ A_NORMAL, /* inputbox_border_attr */
+ A_NORMAL, /* searchbox_attr */
+ A_BOLD, /* searchbox_title_attr */
+ A_NORMAL, /* searchbox_border_attr */
+ A_BOLD, /* position_indicator_attr */
+ A_NORMAL, /* menubox_attr */
+ A_NORMAL, /* menubox_border_attr */
+ A_NORMAL, /* item_attr */
+ A_REVERSE, /* item_selected_attr */
+ A_BOLD, /* tag_attr */
+ A_REVERSE, /* tag_selected_attr */
+ A_BOLD, /* tag_key_attr */
+ A_REVERSE, /* tag_key_selected_attr */
+ A_BOLD, /* check_attr */
+ A_REVERSE, /* check_selected_attr */
+ A_BOLD, /* uarrow_attr */
+ A_BOLD /* darrow_attr */
+};
+
+#include "colors.h"
+
+/*
+ * Table of color values
+ */
+int color_table[][3] = {
+ {SCREEN_FG, SCREEN_BG, SCREEN_HL},
+ {SHADOW_FG, SHADOW_BG, SHADOW_HL},
+ {DIALOG_FG, DIALOG_BG, DIALOG_HL},
+ {TITLE_FG, TITLE_BG, TITLE_HL},
+ {BORDER_FG, BORDER_BG, BORDER_HL},
+ {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
+ {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
+ {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
+ {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG,
+ BUTTON_KEY_INACTIVE_HL},
+ {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG,
+ BUTTON_LABEL_ACTIVE_HL},
+ {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
+ BUTTON_LABEL_INACTIVE_HL},
+ {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
+ {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
+ {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
+ {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
+ {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
+ {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
+ {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
+ {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
+ {ITEM_FG, ITEM_BG, ITEM_HL},
+ {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
+ {TAG_FG, TAG_BG, TAG_HL},
+ {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
+ {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
+ {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
+ {CHECK_FG, CHECK_BG, CHECK_HL},
+ {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
+ {UARROW_FG, UARROW_BG, UARROW_HL},
+ {DARROW_FG, DARROW_BG, DARROW_HL},
+}; /* color_table */
+
+/*
+ * Set window to attribute 'attr'
+ */
+void attr_clear(WINDOW * win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset(win, attr);
+ for (i = 0; i < height; i++) {
+ wmove(win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch(win, ' ');
+ }
+ touchwin(win);
+}
+
+void dialog_clear(void)
+{
+ attr_clear(stdscr, LINES, COLS, screen_attr);
+ /* Display background title if it exists ... - SLH */
+ if (backtitle != NULL) {
+ int i;
+
+ wattrset(stdscr, screen_attr);
+ mvwaddstr(stdscr, 0, 1, (char *)backtitle);
+ wmove(stdscr, 1, 1);
+ for (i = 1; i < COLS - 1; i++)
+ waddch(stdscr, ACS_HLINE);
+ }
+ wnoutrefresh(stdscr);
+}
+
+/*
+ * Do some initialization for dialog
+ */
+void init_dialog(void)
+{
+ initscr(); /* Init curses */
+ keypad(stdscr, TRUE);
+ cbreak();
+ noecho();
+
+ if (use_colors) /* Set up colors */
+ color_setup();
+
+ dialog_clear();
+}
+
+/*
+ * Setup for color display
+ */
+void color_setup(void)
+{
+ int i;
+
+ if (has_colors()) { /* Terminal supports color? */
+ start_color();
+
+ /* Initialize color pairs */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ init_pair(i + 1, color_table[i][0], color_table[i][1]);
+
+ /* Setup color attributes */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ attributes[i] = C_ATTR(color_table[i][2], i + 1);
+ }
+}
+
+/*
+ * End using dialog functions.
+ */
+void end_dialog(void)
+{
+ endwin();
+}
+
+/* Print the title of the dialog. Center the title and truncate
+ * tile if wider than dialog (- 2 chars).
+ **/
+void print_title(WINDOW *dialog, const char *title, int width)
+{
+ if (title) {
+ int tlen = MIN(width - 2, strlen(title));
+ wattrset(dialog, title_attr);
+ mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
+ mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
+ waddch(dialog, ' ');
+ }
+}
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces. We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
+ */
+void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
+{
+ int newl, cur_x, cur_y;
+ int i, prompt_len, room, wlen;
+ char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
+
+ strcpy(tempstr, prompt);
+
+ prompt_len = strlen(tempstr);
+
+ /*
+ * Remove newlines
+ */
+ for (i = 0; i < prompt_len; i++) {
+ if (tempstr[i] == '\n')
+ tempstr[i] = ' ';
+ }
+
+ if (prompt_len <= width - x * 2) { /* If prompt is short */
+ wmove(win, y, (width - prompt_len) / 2);
+ waddstr(win, tempstr);
+ } else {
+ cur_x = x;
+ cur_y = y;
+ newl = 1;
+ word = tempstr;
+ while (word && *word) {
+ sp = index(word, ' ');
+ if (sp)
+ *sp++ = 0;
+
+ /* Wrap to next line if either the word does not fit,
+ or it is the first word of a new sentence, and it is
+ short, and the next word does not fit. */
+ room = width - cur_x;
+ wlen = strlen(word);
+ if (wlen > room ||
+ (newl && wlen < 4 && sp
+ && wlen + 1 + strlen(sp) > room
+ && (!(sp2 = index(sp, ' '))
+ || wlen + 1 + (sp2 - sp) > room))) {
+ cur_y++;
+ cur_x = x;
+ }
+ wmove(win, cur_y, cur_x);
+ waddstr(win, word);
+ getyx(win, cur_y, cur_x);
+ cur_x++;
+ if (sp && *sp == ' ') {
+ cur_x++; /* double space */
+ while (*++sp == ' ') ;
+ newl = 1;
+ } else
+ newl = 0;
+ word = sp;
+ }
+ }
+}
+
+/*
+ * Print a button
+ */
+void print_button(WINDOW * win, const char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove(win, y, x);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, "<");
+ temp = strspn(label, " ");
+ label += temp;
+ wattrset(win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ for (i = 0; i < temp; i++)
+ waddch(win, ' ');
+ wattrset(win, selected ? button_key_active_attr
+ : button_key_inactive_attr);
+ waddch(win, label[0]);
+ wattrset(win, selected ? button_label_active_attr
+ : button_label_inactive_attr);
+ waddstr(win, (char *)label + 1);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, ">");
+ wmove(win, y, x + temp + 1);
+}
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void
+draw_box(WINDOW * win, int y, int x, int height, int width,
+ chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset(win, 0);
+ for (i = 0; i < height; i++) {
+ wmove(win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch(win, border | ACS_ULCORNER);
+ else if (i == height - 1 && !j)
+ waddch(win, border | ACS_LLCORNER);
+ else if (!i && j == width - 1)
+ waddch(win, box | ACS_URCORNER);
+ else if (i == height - 1 && j == width - 1)
+ waddch(win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch(win, border | ACS_HLINE);
+ else if (i == height - 1)
+ waddch(win, box | ACS_HLINE);
+ else if (!j)
+ waddch(win, border | ACS_VLINE);
+ else if (j == width - 1)
+ waddch(win, box | ACS_VLINE);
+ else
+ waddch(win, box | ' ');
+ }
+}
+
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void draw_shadow(WINDOW * win, int y, int x, int height, int width)
+{
+ int i;
+
+ if (has_colors()) { /* Whether terminal supports color? */
+ wattrset(win, shadow_attr);
+ wmove(win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ waddch(win, winch(win) & A_CHARTEXT);
+ for (i = y + 1; i < y + height + 1; i++) {
+ wmove(win, i, x + width);
+ waddch(win, winch(win) & A_CHARTEXT);
+ waddch(win, winch(win) & A_CHARTEXT);
+ }
+ wnoutrefresh(win);
+ }
+}
+
+/*
+ * Return the position of the first alphabetic character in a string.
+ */
+int first_alpha(const char *string, const char *exempt)
+{
+ int i, in_paren = 0, c;
+
+ for (i = 0; i < strlen(string); i++) {
+ c = tolower(string[i]);
+
+ if (strchr("<[(", c))
+ ++in_paren;
+ if (strchr(">])", c) && in_paren > 0)
+ --in_paren;
+
+ if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
+ return i;
+ }
+
+ return 0;
+}
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c
new file mode 100644
index 000000000000..cb2568aae3ed
--- /dev/null
+++ b/scripts/kconfig/lxdialog/yesno.c
@@ -0,0 +1,102 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
+
+/*
+ * Display termination buttons
+ */
+static void print_buttons(WINDOW * dialog, int height, int width, int selected)
+{
+ int x = width / 2 - 10;
+ int y = height - 2;
+
+ print_button(dialog, " Yes ", y, x, selected == 0);
+ print_button(dialog, " No ", y, x + 13, selected == 1);
+
+ wmove(dialog, y, x + 1 + 13 * selected);
+ wrefresh(dialog);
+}
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int dialog_yesno(const char *title, const char *prompt, int height, int width)
+{
+ int i, x, y, key = 0, button = 0;
+ WINDOW *dialog;
+
+ /* center dialog box on screen */
+ x = (COLS - width) / 2;
+ y = (LINES - height) / 2;
+
+ draw_shadow(stdscr, y, x, height, width);
+
+ dialog = newwin(height, width, y, x);
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ mvwaddch(dialog, height - 3, 0, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+
+ print_title(dialog, title, width);
+
+ wattrset(dialog, dialog_attr);
+ print_autowrap(dialog, prompt, width - 2, 1, 3);
+
+ print_buttons(dialog, height, width, 0);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin(dialog);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin(dialog);
+ return 1;
+
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button);
+
+ print_buttons(dialog, height, width, button);
+ wrefresh(dialog);
+ break;
+ case ' ':
+ case '\n':
+ delwin(dialog);
+ return button;
+ case ESC:
+ break;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index d1ad40531ee5..7f973195e79a 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -325,7 +325,7 @@ static void cprint_init(void)
memset(args, 0, sizeof(args));
indent = 0;
child_count = 0;
- cprint("./scripts/lxdialog/lxdialog");
+ cprint("./scripts/kconfig/lxdialog/lxdialog");
cprint("--backtitle");
cprint(menu_backtitle);
}
@@ -1051,7 +1051,7 @@ int main(int ac, char **av)
conf_parse(av[1]);
conf_read(NULL);
- sym = sym_lookup("KERNELRELEASE", 0);
+ sym = sym_lookup("KERNELVERSION", 0);
sym_calc_value(sym);
sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
sym_get_string_value(sym));
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 7c03927d4c7c..e52f3e90bf0c 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -22,8 +22,8 @@ public:
#if QT_VERSION >= 300
void readListSettings();
- QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok);
- bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value);
+ QValueList<int> readSizes(const QString& key, bool *ok);
+ bool writeSizes(const QString& key, const QValueList<int>& value);
#endif
bool showAll;
@@ -124,7 +124,7 @@ public:
void setParentMenu(void);
template <class P>
- void ConfigList::updateMenuList(P*, struct menu*);
+ void updateMenuList(P*, struct menu*);
bool updateAll;
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 69c2549c0baa..3d7877afccd5 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -61,10 +61,10 @@ void sym_init(void)
if (p)
sym_add_default(sym, p);
- sym = sym_lookup("KERNELRELEASE", 0);
+ sym = sym_lookup("KERNELVERSION", 0);
sym->type = S_STRING;
sym->flags |= SYMBOL_AUTO;
- p = getenv("KERNELRELEASE");
+ p = getenv("KERNELVERSION");
if (p)
sym_add_default(sym, p);
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 1fa4c0b801b3..656d2c87d661 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -33,7 +33,7 @@ int file_write_dep(const char *name)
FILE *out;
if (!name)
- name = ".config.cmd";
+ name = ".kconfig.d";
out = fopen("..config.tmp", "w");
if (!out)
return 1;
@@ -101,7 +101,7 @@ void str_printf(struct gstr *gs, const char *fmt, ...)
va_end(ap);
}
-/* Retreive value of growable string */
+/* Retrieve value of growable string */
const char *str_get(struct gstr *gs)
{
return gs->s;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 2f45fd2969d0..9fd5f5b87d1e 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1405,6 +1405,7 @@ sub create_parameterlist($$$) {
my $type;
my $param;
+ # temporarily replace commas inside function pointer definition
while ($args =~ /(\([^\),]+),/) {
$args =~ s/(\([^\),]+),/$1#/g;
}
@@ -1465,11 +1466,10 @@ sub push_parameter($$$) {
my $param_name = $param;
$param_name =~ s/\[.*//;
- if ($type eq "" && $param eq "...")
+ if ($type eq "" && $param =~ /\.\.\.$/)
{
$type="";
- $param="...";
- $parameterdescs{"..."} = "variable arguments";
+ $parameterdescs{$param} = "variable arguments";
}
elsif ($type eq "" && ($param eq "" or $param eq "void"))
{
@@ -1477,7 +1477,11 @@ sub push_parameter($$$) {
$param="void";
$parameterdescs{void} = "no arguments";
}
- if (defined $type && $type && !defined $parameterdescs{$param_name}) {
+ # warn if parameter has no description
+ # (but ignore ones starting with # as these are no parameters
+ # but inline preprocessor statements
+ if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
+
$parameterdescs{$param_name} = $undescribed;
if (($type eq 'function') || ($type eq 'enum')) {
diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
deleted file mode 100644
index a45a13fb26ed..000000000000
--- a/scripts/lxdialog/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-HOST_EXTRACFLAGS := -DLOCALE
-ifeq ($(shell uname),SunOS)
-HOST_LOADLIBES := -lcurses
-else
-HOST_LOADLIBES := -lncurses
-endif
-
-ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h))
- HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"
-else
-ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h))
- HOST_EXTRACFLAGS += -I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"
-else
-ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h))
- HOST_EXTRACFLAGS += -DCURSES_LOC="<ncurses.h>"
-else
- HOST_EXTRACFLAGS += -DCURSES_LOC="<curses.h>"
-endif
-endif
-endif
-
-hostprogs-y := lxdialog
-always := ncurses $(hostprogs-y)
-
-lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
- util.o lxdialog.o msgbox.o
-
-.PHONY: $(obj)/ncurses
-$(obj)/ncurses:
- @echo "main() {}" > lxtemp.c
- @if $(HOSTCC) lxtemp.c $(HOST_LOADLIBES); then \
- rm -f lxtemp.c a.out; \
- else \
- rm -f lxtemp.c; \
- echo -e "\007" ;\
- echo ">> Unable to find the Ncurses libraries." ;\
- echo ">>" ;\
- echo ">> You must install ncurses-devel in order" ;\
- echo ">> to use 'make menuconfig'" ;\
- echo ;\
- exit 1 ;\
- fi
diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c
deleted file mode 100644
index 7aba17c72e64..000000000000
--- a/scripts/lxdialog/checklist.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * checklist.c -- implements the checklist box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension
- * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-static int list_width, check_x, item_x, checkflag;
-
-/*
- * Print list item
- */
-static void
-print_item (WINDOW * win, const char *item, int status,
- int choice, int selected)
-{
- int i;
-
- /* Clear 'residue' of last item */
- wattrset (win, menubox_attr);
- wmove (win, choice, 0);
- for (i = 0; i < list_width; i++)
- waddch (win, ' ');
-
- wmove (win, choice, check_x);
- wattrset (win, selected ? check_selected_attr : check_attr);
- if (checkflag == FLAG_CHECK)
- wprintw (win, "[%c]", status ? 'X' : ' ');
- else
- wprintw (win, "(%c)", status ? 'X' : ' ');
-
- wattrset (win, selected ? tag_selected_attr : tag_attr);
- mvwaddch(win, choice, item_x, item[0]);
- wattrset (win, selected ? item_selected_attr : item_attr);
- waddstr (win, (char *)item+1);
- if (selected) {
- wmove (win, choice, check_x+1);
- wrefresh (win);
- }
-}
-
-/*
- * Print the scroll indicators.
- */
-static void
-print_arrows (WINDOW * win, int choice, int item_no, int scroll,
- int y, int x, int height)
-{
- wmove(win, y, x);
-
- if (scroll > 0) {
- wattrset (win, uarrow_attr);
- waddch (win, ACS_UARROW);
- waddstr (win, "(-)");
- }
- else {
- wattrset (win, menubox_attr);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- }
-
- y = y + height + 1;
- wmove(win, y, x);
-
- if ((height < item_no) && (scroll + choice < item_no - 1)) {
- wattrset (win, darrow_attr);
- waddch (win, ACS_DARROW);
- waddstr (win, "(+)");
- }
- else {
- wattrset (win, menubox_border_attr);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- }
-}
-
-/*
- * Display the termination buttons
- */
-static void
-print_buttons( WINDOW *dialog, int height, int width, int selected)
-{
- int x = width / 2 - 11;
- int y = height - 2;
-
- print_button (dialog, "Select", y, x, selected == 0);
- print_button (dialog, " Help ", y, x + 14, selected == 1);
-
- wmove(dialog, y, x+1 + 14*selected);
- wrefresh (dialog);
-}
-
-/*
- * Display a dialog box with a list of options that can be turned on or off
- * The `flag' parameter is used to select between radiolist and checklist.
- */
-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)
-
-{
- int i, x, y, box_x, box_y;
- int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status;
- WINDOW *dialog, *list;
-
- checkflag = flag;
-
- /* Allocate space for storing item on/off status */
- if ((status = malloc (sizeof (int) * item_no)) == NULL) {
- endwin ();
- fprintf (stderr,
- "\nCan't allocate memory in dialog_checklist().\n");
- exit (-1);
- }
-
- /* Initializes status */
- for (i = 0; i < item_no; i++) {
- status[i] = !strcasecmp (items[i * 3 + 2], "on");
- if ((!choice && status[i]) || !strcasecmp (items[i * 3 + 2], "selected"))
- choice = i + 1;
- }
- if (choice)
- choice--;
-
- max_choice = MIN (list_height, item_no);
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height-3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- waddch (dialog, ACS_RTEE);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
-
- wattrset (dialog, dialog_attr);
- print_autowrap (dialog, prompt, width - 2, 1, 3);
-
- list_width = width - 6;
- box_y = height - list_height - 5;
- box_x = (width - list_width) / 2 - 1;
-
- /* create new window for the list */
- list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1);
-
- keypad (list, TRUE);
-
- /* draw a box around the list items */
- draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2,
- menubox_border_attr, menubox_attr);
-
- /* Find length of longest item in order to center checklist */
- check_x = 0;
- for (i = 0; i < item_no; i++)
- check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4);
-
- check_x = (list_width - check_x) / 2;
- item_x = check_x + 4;
-
- if (choice >= list_height) {
- scroll = choice - list_height + 1;
- choice -= scroll;
- }
-
- /* Print the list */
- for (i = 0; i < max_choice; i++) {
- print_item (list, items[(scroll+i) * 3 + 1],
- status[i+scroll], i, i == choice);
- }
-
- print_arrows(dialog, choice, item_no, scroll,
- box_y, box_x + check_x + 5, list_height);
-
- print_buttons(dialog, height, width, 0);
-
- wnoutrefresh (list);
- wnoutrefresh (dialog);
- doupdate ();
-
- while (key != ESC) {
- key = wgetch (dialog);
-
- for (i = 0; i < max_choice; i++)
- if (toupper(key) == toupper(items[(scroll+i)*3+1][0]))
- break;
-
-
- if ( i < max_choice || key == KEY_UP || key == KEY_DOWN ||
- key == '+' || key == '-' ) {
- if (key == KEY_UP || key == '-') {
- if (!choice) {
- if (!scroll)
- continue;
- /* Scroll list down */
- if (list_height > 1) {
- /* De-highlight current first item */
- print_item (list, items[scroll * 3 + 1],
- status[scroll], 0, FALSE);
- scrollok (list, TRUE);
- wscrl (list, -1);
- scrollok (list, FALSE);
- }
- scroll--;
- print_item (list, items[scroll * 3 + 1],
- status[scroll], 0, TRUE);
- wnoutrefresh (list);
-
- print_arrows(dialog, choice, item_no, scroll,
- box_y, box_x + check_x + 5, list_height);
-
- wrefresh (dialog);
-
- continue; /* wait for another key press */
- } else
- i = choice - 1;
- } else if (key == KEY_DOWN || key == '+') {
- if (choice == max_choice - 1) {
- if (scroll + choice >= item_no - 1)
- continue;
- /* Scroll list up */
- if (list_height > 1) {
- /* De-highlight current last item before scrolling up */
- print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
- status[scroll + max_choice - 1],
- max_choice - 1, FALSE);
- scrollok (list, TRUE);
- wscrl (list, 1);
- scrollok (list, FALSE);
- }
- scroll++;
- print_item (list, items[(scroll + max_choice - 1) * 3 + 1],
- status[scroll + max_choice - 1],
- max_choice - 1, TRUE);
- wnoutrefresh (list);
-
- print_arrows(dialog, choice, item_no, scroll,
- box_y, box_x + check_x + 5, list_height);
-
- wrefresh (dialog);
-
- continue; /* wait for another key press */
- } else
- i = choice + 1;
- }
- if (i != choice) {
- /* De-highlight current item */
- print_item (list, items[(scroll + choice) * 3 + 1],
- status[scroll + choice], choice, FALSE);
- /* Highlight new item */
- choice = i;
- print_item (list, items[(scroll + choice) * 3 + 1],
- status[scroll + choice], choice, TRUE);
- wnoutrefresh (list);
- wrefresh (dialog);
- }
- continue; /* wait for another key press */
- }
- switch (key) {
- case 'H':
- case 'h':
- case '?':
- fprintf (stderr, "%s", items[(scroll + choice) * 3]);
- delwin (dialog);
- free (status);
- return 1;
- case TAB:
- case KEY_LEFT:
- case KEY_RIGHT:
- button = ((key == KEY_LEFT ? --button : ++button) < 0)
- ? 1 : (button > 1 ? 0 : button);
-
- print_buttons(dialog, height, width, button);
- wrefresh (dialog);
- break;
- case 'S':
- case 's':
- case ' ':
- case '\n':
- if (!button) {
- if (flag == FLAG_CHECK) {
- status[scroll + choice] = !status[scroll + choice];
- wmove (list, choice, check_x);
- wattrset (list, check_selected_attr);
- wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' ');
- } else {
- if (!status[scroll + choice]) {
- for (i = 0; i < item_no; i++)
- status[i] = 0;
- status[scroll + choice] = 1;
- for (i = 0; i < max_choice; i++)
- print_item (list, items[(scroll + i) * 3 + 1],
- status[scroll + i], i, i == choice);
- }
- }
- wnoutrefresh (list);
- wrefresh (dialog);
-
- for (i = 0; i < item_no; i++) {
- if (status[i]) {
- if (flag == FLAG_CHECK) {
- fprintf (stderr, "\"%s\" ", items[i * 3]);
- } else {
- fprintf (stderr, "%s", items[i * 3]);
- }
-
- }
- }
- } else
- fprintf (stderr, "%s", items[(scroll + choice) * 3]);
- delwin (dialog);
- free (status);
- return button;
- case 'X':
- case 'x':
- key = ESC;
- case ESC:
- break;
- }
-
- /* Now, update everything... */
- doupdate ();
- }
-
-
- delwin (dialog);
- free (status);
- return -1; /* ESC pressed */
-}
diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c
deleted file mode 100644
index 074d2d68bd31..000000000000
--- a/scripts/lxdialog/inputbox.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * inputbox.c -- implements the input box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-char dialog_input_result[MAX_LEN + 1];
-
-/*
- * Print the termination buttons
- */
-static void
-print_buttons(WINDOW *dialog, int height, int width, int selected)
-{
- int x = width / 2 - 11;
- int y = height - 2;
-
- print_button (dialog, " Ok ", y, x, selected==0);
- print_button (dialog, " Help ", y, x + 14, selected==1);
-
- wmove(dialog, y, x+1+14*selected);
- wrefresh(dialog);
-}
-
-/*
- * Display a dialog box for inputing a string
- */
-int
-dialog_inputbox (const char *title, const char *prompt, int height, int width,
- const char *init)
-{
- int i, x, y, box_y, box_x, box_width;
- int input_x = 0, scroll = 0, key = 0, button = -1;
- char *instr = dialog_input_result;
- WINDOW *dialog;
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height-3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- waddch (dialog, ACS_RTEE);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
-
- wattrset (dialog, dialog_attr);
- print_autowrap (dialog, prompt, width - 2, 1, 3);
-
- /* Draw the input field box */
- box_width = width - 6;
- getyx (dialog, y, x);
- box_y = y + 2;
- box_x = (width - box_width) / 2;
- draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2,
- border_attr, dialog_attr);
-
- print_buttons(dialog, height, width, 0);
-
- /* Set up the initial value */
- wmove (dialog, box_y, box_x);
- wattrset (dialog, inputbox_attr);
-
- if (!init)
- instr[0] = '\0';
- else
- strcpy (instr, init);
-
- input_x = strlen (instr);
-
- if (input_x >= box_width) {
- scroll = input_x - box_width + 1;
- input_x = box_width - 1;
- for (i = 0; i < box_width - 1; i++)
- waddch (dialog, instr[scroll + i]);
- } else
- waddstr (dialog, instr);
-
- wmove (dialog, box_y, box_x + input_x);
-
- wrefresh (dialog);
-
- while (key != ESC) {
- key = wgetch (dialog);
-
- if (button == -1) { /* Input box selected */
- switch (key) {
- case TAB:
- case KEY_UP:
- case KEY_DOWN:
- break;
- case KEY_LEFT:
- continue;
- case KEY_RIGHT:
- continue;
- case KEY_BACKSPACE:
- case 127:
- if (input_x || scroll) {
- wattrset (dialog, inputbox_attr);
- if (!input_x) {
- scroll = scroll < box_width - 1 ?
- 0 : scroll - (box_width - 1);
- wmove (dialog, box_y, box_x);
- for (i = 0; i < box_width; i++)
- waddch (dialog, instr[scroll + input_x + i] ?
- instr[scroll + input_x + i] : ' ');
- input_x = strlen (instr) - scroll;
- } else
- input_x--;
- instr[scroll + input_x] = '\0';
- mvwaddch (dialog, box_y, input_x + box_x, ' ');
- wmove (dialog, box_y, input_x + box_x);
- wrefresh (dialog);
- }
- continue;
- default:
- if (key < 0x100 && isprint (key)) {
- if (scroll + input_x < MAX_LEN) {
- wattrset (dialog, inputbox_attr);
- instr[scroll + input_x] = key;
- instr[scroll + input_x + 1] = '\0';
- if (input_x == box_width - 1) {
- scroll++;
- wmove (dialog, box_y, box_x);
- for (i = 0; i < box_width - 1; i++)
- waddch (dialog, instr[scroll + i]);
- } else {
- wmove (dialog, box_y, input_x++ + box_x);
- waddch (dialog, key);
- }
- wrefresh (dialog);
- } else
- flash (); /* Alarm user about overflow */
- continue;
- }
- }
- }
- switch (key) {
- case 'O':
- case 'o':
- delwin (dialog);
- return 0;
- case 'H':
- case 'h':
- delwin (dialog);
- return 1;
- case KEY_UP:
- case KEY_LEFT:
- switch (button) {
- case -1:
- button = 1; /* Indicates "Cancel" button is selected */
- print_buttons(dialog, height, width, 1);
- break;
- case 0:
- button = -1; /* Indicates input box is selected */
- print_buttons(dialog, height, width, 0);
- wmove (dialog, box_y, box_x + input_x);
- wrefresh (dialog);
- break;
- case 1:
- button = 0; /* Indicates "OK" button is selected */
- print_buttons(dialog, height, width, 0);
- break;
- }
- break;
- case TAB:
- case KEY_DOWN:
- case KEY_RIGHT:
- switch (button) {
- case -1:
- button = 0; /* Indicates "OK" button is selected */
- print_buttons(dialog, height, width, 0);
- break;
- case 0:
- button = 1; /* Indicates "Cancel" button is selected */
- print_buttons(dialog, height, width, 1);
- break;
- case 1:
- button = -1; /* Indicates input box is selected */
- print_buttons(dialog, height, width, 0);
- wmove (dialog, box_y, box_x + input_x);
- wrefresh (dialog);
- break;
- }
- break;
- case ' ':
- case '\n':
- delwin (dialog);
- return (button == -1 ? 0 : button);
- case 'X':
- case 'x':
- key = ESC;
- case ESC:
- break;
- }
- }
-
- delwin (dialog);
- return -1; /* ESC pressed */
-}
diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
deleted file mode 100644
index f283a8545426..000000000000
--- a/scripts/lxdialog/lxdialog.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * dialog - Display simple dialog boxes from shell scripts
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-static void Usage (const char *name);
-
-typedef int (jumperFn) (const char *title, int argc, const char * const * argv);
-
-struct Mode {
- char *name;
- int argmin, argmax, argmod;
- jumperFn *jumper;
-};
-
-jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox;
-jumperFn j_msgbox, j_infobox;
-
-static struct Mode modes[] =
-{
- {"--menu", 9, 0, 3, j_menu},
- {"--checklist", 9, 0, 3, j_checklist},
- {"--radiolist", 9, 0, 3, j_radiolist},
- {"--yesno", 5,5,1, j_yesno},
- {"--textbox", 5,5,1, j_textbox},
- {"--inputbox", 5, 6, 1, j_inputbox},
- {"--msgbox", 5, 5, 1, j_msgbox},
- {"--infobox", 5, 5, 1, j_infobox},
- {NULL, 0, 0, 0, NULL}
-};
-
-static struct Mode *modePtr;
-
-#ifdef LOCALE
-#include <locale.h>
-#endif
-
-int
-main (int argc, const char * const * argv)
-{
- int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
- const char *title = NULL;
-
-#ifdef LOCALE
- (void) setlocale (LC_ALL, "");
-#endif
-
-#ifdef TRACE
- trace(TRACE_CALLS|TRACE_UPDATE);
-#endif
- if (argc < 2) {
- Usage (argv[0]);
- exit (-1);
- }
-
- while (offset < argc - 1 && !end_common_opts) { /* Common options */
- if (!strcmp (argv[offset + 1], "--title")) {
- if (argc - offset < 3 || title != NULL) {
- Usage (argv[0]);
- exit (-1);
- } else {
- title = argv[offset + 2];
- offset += 2;
- }
- } else if (!strcmp (argv[offset + 1], "--backtitle")) {
- if (backtitle != NULL) {
- Usage (argv[0]);
- exit (-1);
- } else {
- backtitle = argv[offset + 2];
- offset += 2;
- }
- } else if (!strcmp (argv[offset + 1], "--clear")) {
- if (opt_clear) { /* Hey, "--clear" can't appear twice! */
- Usage (argv[0]);
- exit (-1);
- } else if (argc == 2) { /* we only want to clear the screen */
- init_dialog ();
- refresh (); /* init_dialog() will clear the screen for us */
- end_dialog ();
- return 0;
- } else {
- opt_clear = 1;
- offset++;
- }
- } else /* no more common options */
- end_common_opts = 1;
- }
-
- if (argc - 1 == offset) { /* no more options */
- Usage (argv[0]);
- exit (-1);
- }
- /* use a table to look for the requested mode, to avoid code duplication */
-
- for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */
- if (!strcmp (argv[offset + 1], modePtr->name))
- break;
-
- if (!modePtr->name)
- Usage (argv[0]);
- if (argc - offset < modePtr->argmin)
- Usage (argv[0]);
- if (modePtr->argmax && argc - offset > modePtr->argmax)
- Usage (argv[0]);
-
-
-
- init_dialog ();
- retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
-
- if (opt_clear) { /* clear screen before exit */
- attr_clear (stdscr, LINES, COLS, screen_attr);
- refresh ();
- }
- end_dialog();
-
- exit (retval);
-}
-
-/*
- * Print program usage
- */
-static void
-Usage (const char *name)
-{
- fprintf (stderr, "\
-\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\
-\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\
-\n modified/gutted for use as a Linux kernel config tool by \
-\n William Roadcap (roadcapw@cfw.com)\
-\n\
-\n* Display dialog boxes from shell scripts *\
-\n\
-\nUsage: %s --clear\
-\n %s [--title <title>] [--backtitle <backtitle>] --clear <Box options>\
-\n\
-\nBox options:\
-\n\
-\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
-\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
-\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
-\n --textbox <file> <height> <width>\
-\n --inputbox <text> <height> <width> [<init>]\
-\n --yesno <text> <height> <width>\
-\n", name, name);
- exit (-1);
-}
-
-/*
- * These are the program jumpers
- */
-
-int
-j_menu (const char *t, int ac, const char * const * av)
-{
- return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]),
- atoi (av[5]), av[6], (ac - 6) / 2, av + 7);
-}
-
-int
-j_checklist (const char *t, int ac, const char * const * av)
-{
- return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
- atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK);
-}
-
-int
-j_radiolist (const char *t, int ac, const char * const * av)
-{
- return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]),
- atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO);
-}
-
-int
-j_textbox (const char *t, int ac, const char * const * av)
-{
- return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4]));
-}
-
-int
-j_yesno (const char *t, int ac, const char * const * av)
-{
- return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4]));
-}
-
-int
-j_inputbox (const char *t, int ac, const char * const * av)
-{
- int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]),
- ac == 6 ? av[5] : (char *) NULL);
- if (ret == 0)
- fprintf(stderr, dialog_input_result);
- return ret;
-}
-
-int
-j_msgbox (const char *t, int ac, const char * const * av)
-{
- return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1);
-}
-
-int
-j_infobox (const char *t, int ac, const char * const * av)
-{
- return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0);
-}
-
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
deleted file mode 100644
index 91d82ba17f8d..000000000000
--- a/scripts/lxdialog/menubox.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * menubox.c -- implements the menu box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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.
- */
-
-/*
- * Changes by Clifford Wolf (god@clifford.at)
- *
- * [ 1998-06-13 ]
- *
- * *) A bugfix for the Page-Down problem
- *
- * *) Formerly when I used Page Down and Page Up, the cursor would be set
- * to the first position in the menu box. Now lxdialog is a bit
- * smarter and works more like other menu systems (just have a look at
- * it).
- *
- * *) Formerly if I selected something my scrolling would be broken because
- * lxdialog is re-invoked by the Menuconfig shell script, can't
- * remember the last scrolling position, and just sets it so that the
- * cursor is at the bottom of the box. Now it writes the temporary file
- * lxdialog.scrltmp which contains this information. The file is
- * deleted by lxdialog if the user leaves a submenu or enters a new
- * one, but it would be nice if Menuconfig could make another "rm -f"
- * just to be sure. Just try it out - you will recognise a difference!
- *
- * [ 1998-06-14 ]
- *
- * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
- * and menus change their size on the fly.
- *
- * *) If for some reason the last scrolling position is not saved by
- * lxdialog, it sets the scrolling so that the selected item is in the
- * middle of the menu box, not at the bottom.
- *
- * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net)
- * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
- * This fixes a bug in Menuconfig where using ' ' to descend into menus
- * would leave mis-synchronized lxdialog.scrltmp files lying around,
- * fscanf would read in 'scroll', and eventually that value would get used.
- */
-
-#include "dialog.h"
-
-static int menu_width, item_x;
-
-/*
- * Print menu item
- */
-static void
-print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey)
-{
- int j;
- char menu_item[menu_width+1];
-
- strncpy(menu_item, item, menu_width);
- menu_item[menu_width] = 0;
- j = first_alpha(menu_item, "YyNnMmHh");
-
- /* Clear 'residue' of last item */
- wattrset (win, menubox_attr);
- wmove (win, choice, 0);
-#if OLD_NCURSES
- {
- int i;
- for (i = 0; i < menu_width; i++)
- waddch (win, ' ');
- }
-#else
- wclrtoeol(win);
-#endif
- wattrset (win, selected ? item_selected_attr : item_attr);
- mvwaddstr (win, choice, item_x, menu_item);
- if (hotkey) {
- wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
- mvwaddch(win, choice, item_x+j, menu_item[j]);
- }
- if (selected) {
- wmove (win, choice, item_x+1);
- wrefresh (win);
- }
-}
-
-/*
- * Print the scroll indicators.
- */
-static void
-print_arrows (WINDOW * win, int item_no, int scroll,
- int y, int x, int height)
-{
- int cur_y, cur_x;
-
- getyx(win, cur_y, cur_x);
-
- wmove(win, y, x);
-
- if (scroll > 0) {
- wattrset (win, uarrow_attr);
- waddch (win, ACS_UARROW);
- waddstr (win, "(-)");
- }
- else {
- wattrset (win, menubox_attr);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- }
-
- y = y + height + 1;
- wmove(win, y, x);
-
- if ((height < item_no) && (scroll + height < item_no)) {
- wattrset (win, darrow_attr);
- waddch (win, ACS_DARROW);
- waddstr (win, "(+)");
- }
- else {
- wattrset (win, menubox_border_attr);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- waddch (win, ACS_HLINE);
- }
-
- wmove(win, cur_y, cur_x);
-}
-
-/*
- * Display the termination buttons.
- */
-static void
-print_buttons (WINDOW *win, int height, int width, int selected)
-{
- int x = width / 2 - 16;
- int y = height - 2;
-
- print_button (win, "Select", y, x, selected == 0);
- print_button (win, " Exit ", y, x + 12, selected == 1);
- print_button (win, " Help ", y, x + 24, selected == 2);
-
- wmove(win, y, x+1+12*selected);
- wrefresh (win);
-}
-
-/*
- * Display a menu for choosing among a number of options
- */
-int
-dialog_menu (const char *title, const char *prompt, int height, int width,
- int menu_height, const char *current, int item_no,
- const char * const * items)
-
-{
- int i, j, x, y, box_x, box_y;
- int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice;
- WINDOW *dialog, *menu;
- FILE *f;
-
- max_choice = MIN (menu_height, item_no);
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- wbkgdset (dialog, dialog_attr & A_COLOR);
- waddch (dialog, ACS_RTEE);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
-
- wattrset (dialog, dialog_attr);
- print_autowrap (dialog, prompt, width - 2, 1, 3);
-
- menu_width = width - 6;
- box_y = height - menu_height - 5;
- box_x = (width - menu_width) / 2 - 1;
-
- /* create new window for the menu */
- menu = subwin (dialog, menu_height, menu_width,
- y + box_y + 1, x + box_x + 1);
- keypad (menu, TRUE);
-
- /* draw a box around the menu items */
- draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2,
- menubox_border_attr, menubox_attr);
-
- /*
- * Find length of longest item in order to center menu.
- * Set 'choice' to default item.
- */
- item_x = 0;
- for (i = 0; i < item_no; i++) {
- item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2));
- if (strcmp(current, items[i*2]) == 0) choice = i;
- }
-
- item_x = (menu_width - item_x) / 2;
-
- /* get the scroll info from the temp file */
- if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) {
- if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) &&
- (scroll+max_choice > choice) && (scroll >= 0) &&
- (scroll+max_choice <= item_no) ) {
- first_item = scroll;
- choice = choice - scroll;
- fclose(f);
- } else {
- scroll=0;
- remove("lxdialog.scrltmp");
- fclose(f);
- f=NULL;
- }
- }
- if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) {
- if (choice >= item_no-max_choice/2)
- scroll = first_item = item_no-max_choice;
- else
- scroll = first_item = choice - max_choice/2;
- choice = choice - scroll;
- }
-
- /* Print the menu */
- for (i=0; i < max_choice; i++) {
- print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice,
- (items[(first_item + i)*2][0] != ':'));
- }
-
- wnoutrefresh (menu);
-
- print_arrows(dialog, item_no, scroll,
- box_y, box_x+item_x+1, menu_height);
-
- print_buttons (dialog, height, width, 0);
- wmove (menu, choice, item_x+1);
- wrefresh (menu);
-
- while (key != ESC) {
- key = wgetch(menu);
-
- if (key < 256 && isalpha(key)) key = tolower(key);
-
- if (strchr("ynmh", key))
- i = max_choice;
- else {
- for (i = choice+1; i < max_choice; i++) {
- j = first_alpha(items[(scroll+i)*2+1], "YyNnMmHh");
- if (key == tolower(items[(scroll+i)*2+1][j]))
- break;
- }
- if (i == max_choice)
- for (i = 0; i < max_choice; i++) {
- j = first_alpha(items[(scroll+i)*2+1], "YyNnMmHh");
- if (key == tolower(items[(scroll+i)*2+1][j]))
- break;
- }
- }
-
- if (i < max_choice ||
- key == KEY_UP || key == KEY_DOWN ||
- key == '-' || key == '+' ||
- key == KEY_PPAGE || key == KEY_NPAGE) {
-
- print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
- (items[(scroll+choice)*2][0] != ':'));
-
- if (key == KEY_UP || key == '-') {
- if (choice < 2 && scroll) {
- /* Scroll menu down */
- scrollok (menu, TRUE);
- wscrl (menu, -1);
- scrollok (menu, FALSE);
-
- scroll--;
-
- print_item (menu, items[scroll * 2 + 1], 0, FALSE,
- (items[scroll*2][0] != ':'));
- } else
- choice = MAX(choice - 1, 0);
-
- } else if (key == KEY_DOWN || key == '+') {
-
- print_item (menu, items[(scroll+choice)*2+1], choice, FALSE,
- (items[(scroll+choice)*2][0] != ':'));
-
- if ((choice > max_choice-3) &&
- (scroll + max_choice < item_no)
- ) {
- /* Scroll menu up */
- scrollok (menu, TRUE);
- wscrl (menu, 1);
- scrollok (menu, FALSE);
-
- scroll++;
-
- print_item (menu, items[(scroll+max_choice-1)*2+1],
- max_choice-1, FALSE,
- (items[(scroll+max_choice-1)*2][0] != ':'));
- } else
- choice = MIN(choice+1, max_choice-1);
-
- } else if (key == KEY_PPAGE) {
- scrollok (menu, TRUE);
- for (i=0; (i < max_choice); i++) {
- if (scroll > 0) {
- wscrl (menu, -1);
- scroll--;
- print_item (menu, items[scroll * 2 + 1], 0, FALSE,
- (items[scroll*2][0] != ':'));
- } else {
- if (choice > 0)
- choice--;
- }
- }
- scrollok (menu, FALSE);
-
- } else if (key == KEY_NPAGE) {
- for (i=0; (i < max_choice); i++) {
- if (scroll+max_choice < item_no) {
- scrollok (menu, TRUE);
- wscrl (menu, 1);
- scrollok (menu, FALSE);
- scroll++;
- print_item (menu, items[(scroll+max_choice-1)*2+1],
- max_choice-1, FALSE,
- (items[(scroll+max_choice-1)*2][0] != ':'));
- } else {
- if (choice+1 < max_choice)
- choice++;
- }
- }
-
- } else
- choice = i;
-
- print_item (menu, items[(scroll+choice)*2+1], choice, TRUE,
- (items[(scroll+choice)*2][0] != ':'));
-
- print_arrows(dialog, item_no, scroll,
- box_y, box_x+item_x+1, menu_height);
-
- wnoutrefresh (dialog);
- wrefresh (menu);
-
- continue; /* wait for another key press */
- }
-
- switch (key) {
- case KEY_LEFT:
- case TAB:
- case KEY_RIGHT:
- button = ((key == KEY_LEFT ? --button : ++button) < 0)
- ? 2 : (button > 2 ? 0 : button);
-
- print_buttons(dialog, height, width, button);
- wrefresh (menu);
- break;
- case ' ':
- case 's':
- case 'y':
- case 'n':
- case 'm':
- case '/':
- /* save scroll info */
- if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) {
- fprintf(f,"%d\n",scroll);
- fclose(f);
- }
- delwin (dialog);
- fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
- switch (key) {
- case 's': return 3;
- case 'y': return 3;
- case 'n': return 4;
- case 'm': return 5;
- case ' ': return 6;
- case '/': return 7;
- }
- return 0;
- case 'h':
- case '?':
- button = 2;
- case '\n':
- delwin (dialog);
- if (button == 2)
- fprintf(stderr, "%s \"%s\"\n",
- items[(scroll + choice) * 2],
- items[(scroll + choice) * 2 + 1] +
- first_alpha(items[(scroll + choice) * 2 + 1],""));
- else
- fprintf(stderr, "%s\n", items[(scroll + choice) * 2]);
-
- remove("lxdialog.scrltmp");
- return button;
- case 'e':
- case 'x':
- key = ESC;
- case ESC:
- break;
- }
- }
-
- delwin (dialog);
- remove("lxdialog.scrltmp");
- return -1; /* ESC pressed */
-}
diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c
deleted file mode 100644
index 93692e1fbcc2..000000000000
--- a/scripts/lxdialog/msgbox.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * msgbox.c -- implements the message box and info box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.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 "dialog.h"
-
-/*
- * Display a message box. Program will pause and display an "OK" button
- * if the parameter 'pause' is non-zero.
- */
-int
-dialog_msgbox (const char *title, const char *prompt, int height, int width,
- int pause)
-{
- int i, x, y, key = 0;
- WINDOW *dialog;
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
- wattrset (dialog, dialog_attr);
- print_autowrap (dialog, prompt, width - 2, 1, 2);
-
- if (pause) {
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- waddch (dialog, ACS_RTEE);
-
- print_button (dialog, " Ok ",
- height - 2, width / 2 - 4, TRUE);
-
- wrefresh (dialog);
- while (key != ESC && key != '\n' && key != ' ' &&
- key != 'O' && key != 'o' && key != 'X' && key != 'x')
- key = wgetch (dialog);
- } else {
- key = '\n';
- wrefresh (dialog);
- }
-
- delwin (dialog);
- return key == ESC ? -1 : 0;
-}
diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c
deleted file mode 100644
index ed23df2d096a..000000000000
--- a/scripts/lxdialog/textbox.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * textbox.c -- implements the text box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-static void back_lines (int n);
-static void print_page (WINDOW * win, int height, int width);
-static void print_line (WINDOW * win, int row, int width);
-static char *get_line (void);
-static void print_position (WINDOW * win, int height, int width);
-
-static int hscroll, fd, file_size, bytes_read;
-static int begin_reached = 1, end_reached, page_length;
-static char *buf, *page;
-
-/*
- * Display text from a file in a dialog box.
- */
-int
-dialog_textbox (const char *title, const char *file, int height, int width)
-{
- int i, x, y, cur_x, cur_y, fpos, key = 0;
- int passed_end;
- char search_term[MAX_LEN + 1];
- WINDOW *dialog, *text;
-
- search_term[0] = '\0'; /* no search term entered yet */
-
- /* Open input file for reading */
- if ((fd = open (file, O_RDONLY)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nCan't open input file in dialog_textbox().\n");
- exit (-1);
- }
- /* Get file size. Actually, 'file_size' is the real file size - 1,
- since it's only the last byte offset from the beginning */
- if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
- endwin ();
- fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
- exit (-1);
- }
- /* Restore file pointer to beginning of file after getting file size */
- if (lseek (fd, 0, SEEK_SET) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
- exit (-1);
- }
- /* Allocate space for read buffer */
- if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
- endwin ();
- fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
- exit (-1);
- }
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr, "\nError reading file in dialog_textbox().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0'; /* mark end of valid data */
- page = buf; /* page is pointer to start of page to be displayed */
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- /* Create window for text region, used for scrolling text */
- text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
- wattrset (text, dialog_attr);
- wbkgdset (text, dialog_attr & A_COLOR);
-
- keypad (text, TRUE);
-
- /* register the new window, along with its borders */
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
-
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height-3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- wbkgdset (dialog, dialog_attr & A_COLOR);
- waddch (dialog, ACS_RTEE);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
- print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
- wnoutrefresh (dialog);
- getyx (dialog, cur_y, cur_x); /* Save cursor position */
-
- /* Print first page of text */
- attr_clear (text, height - 4, width - 2, dialog_attr);
- print_page (text, height - 4, width - 2);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh (dialog);
-
- while ((key != ESC) && (key != '\n')) {
- key = wgetch (dialog);
- switch (key) {
- case 'E': /* Exit */
- case 'e':
- case 'X':
- case 'x':
- delwin (dialog);
- free (buf);
- close (fd);
- return 0;
- case 'g': /* First page */
- case KEY_HOME:
- if (!begin_reached) {
- begin_reached = 1;
- /* First page not in buffer? */
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError moving file pointer in dialog_textbox().\n");
- exit (-1);
- }
- if (fpos > bytes_read) { /* Yes, we have to read it in */
- if (lseek (fd, 0, SEEK_SET) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in "
- "dialog_textbox().\n");
- exit (-1);
- }
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError reading file in dialog_textbox().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0';
- }
- page = buf;
- print_page (text, height - 4, width - 2);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh (dialog);
- }
- break;
- case 'G': /* Last page */
- case KEY_END:
-
- end_reached = 1;
- /* Last page not in buffer? */
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError moving file pointer in dialog_textbox().\n");
- exit (-1);
- }
- if (fpos < file_size) { /* Yes, we have to read it in */
- if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError moving file pointer in dialog_textbox().\n");
- exit (-1);
- }
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError reading file in dialog_textbox().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0';
- }
- page = buf + bytes_read;
- back_lines (height - 4);
- print_page (text, height - 4, width - 2);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh (dialog);
- break;
- case 'K': /* Previous line */
- case 'k':
- case KEY_UP:
- if (!begin_reached) {
- back_lines (page_length + 1);
-
- /* We don't call print_page() here but use scrolling to ensure
- faster screen update. However, 'end_reached' and
- 'page_length' should still be updated, and 'page' should
- point to start of next page. This is done by calling
- get_line() in the following 'for' loop. */
- scrollok (text, TRUE);
- wscrl (text, -1); /* Scroll text region down one line */
- scrollok (text, FALSE);
- page_length = 0;
- passed_end = 0;
- for (i = 0; i < height - 4; i++) {
- if (!i) {
- /* print first line of page */
- print_line (text, 0, width - 2);
- wnoutrefresh (text);
- } else
- /* Called to update 'end_reached' and 'page' */
- get_line ();
- if (!passed_end)
- page_length++;
- if (end_reached && !passed_end)
- passed_end = 1;
- }
-
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh (dialog);
- }
- break;
- case 'B': /* Previous page */
- case 'b':
- case KEY_PPAGE:
- if (begin_reached)
- break;
- back_lines (page_length + height - 4);
- print_page (text, height - 4, width - 2);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x);
- wrefresh (dialog);
- break;
- case 'J': /* Next line */
- case 'j':
- case KEY_DOWN:
- if (!end_reached) {
- begin_reached = 0;
- scrollok (text, TRUE);
- scroll (text); /* Scroll text region up one line */
- scrollok (text, FALSE);
- print_line (text, height - 5, width - 2);
- wnoutrefresh (text);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh (dialog);
- }
- break;
- case KEY_NPAGE: /* Next page */
- case ' ':
- if (end_reached)
- break;
-
- begin_reached = 0;
- print_page (text, height - 4, width - 2);
- print_position (dialog, height, width);
- wmove (dialog, cur_y, cur_x);
- wrefresh (dialog);
- break;
- case '0': /* Beginning of line */
- case 'H': /* Scroll left */
- case 'h':
- case KEY_LEFT:
- if (hscroll <= 0)
- break;
-
- if (key == '0')
- hscroll = 0;
- else
- hscroll--;
- /* Reprint current page to scroll horizontally */
- back_lines (page_length);
- print_page (text, height - 4, width - 2);
- wmove (dialog, cur_y, cur_x);
- wrefresh (dialog);
- break;
- case 'L': /* Scroll right */
- case 'l':
- case KEY_RIGHT:
- if (hscroll >= MAX_LEN)
- break;
- hscroll++;
- /* Reprint current page to scroll horizontally */
- back_lines (page_length);
- print_page (text, height - 4, width - 2);
- wmove (dialog, cur_y, cur_x);
- wrefresh (dialog);
- break;
- case ESC:
- break;
- }
- }
-
- delwin (dialog);
- free (buf);
- close (fd);
- return -1; /* ESC pressed */
-}
-
-/*
- * Go back 'n' lines in text file. Called by dialog_textbox().
- * 'page' will be updated to point to the desired line in 'buf'.
- */
-static void
-back_lines (int n)
-{
- int i, fpos;
-
- begin_reached = 0;
- /* We have to distinguish between end_reached and !end_reached
- since at end of file, the line is not ended by a '\n'.
- The code inside 'if' basically does a '--page' to move one
- character backward so as to skip '\n' of the previous line */
- if (!end_reached) {
- /* Either beginning of buffer or beginning of file reached? */
- if (page == buf) {
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in "
- "back_lines().\n");
- exit (-1);
- }
- if (fpos > bytes_read) { /* Not beginning of file yet */
- /* We've reached beginning of buffer, but not beginning of
- file yet, so read previous part of file into buffer.
- Note that we only move backward for BUF_SIZE/2 bytes,
- but not BUF_SIZE bytes to avoid re-reading again in
- print_page() later */
- /* Really possible to move backward BUF_SIZE/2 bytes? */
- if (fpos < BUF_SIZE / 2 + bytes_read) {
- /* No, move less then */
- if (lseek (fd, 0, SEEK_SET) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in "
- "back_lines().\n");
- exit (-1);
- }
- page = buf + fpos - bytes_read;
- } else { /* Move backward BUF_SIZE/2 bytes */
- if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
- == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer "
- "in back_lines().\n");
- exit (-1);
- }
- page = buf + BUF_SIZE / 2;
- }
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr, "\nError reading file in back_lines().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0';
- } else { /* Beginning of file reached */
- begin_reached = 1;
- return;
- }
- }
- if (*(--page) != '\n') { /* '--page' here */
- /* Something's wrong... */
- endwin ();
- fprintf (stderr, "\nInternal error in back_lines().\n");
- exit (-1);
- }
- }
- /* Go back 'n' lines */
- for (i = 0; i < n; i++)
- do {
- if (page == buf) {
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr,
- "\nError moving file pointer in back_lines().\n");
- exit (-1);
- }
- if (fpos > bytes_read) {
- /* Really possible to move backward BUF_SIZE/2 bytes? */
- if (fpos < BUF_SIZE / 2 + bytes_read) {
- /* No, move less then */
- if (lseek (fd, 0, SEEK_SET) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer "
- "in back_lines().\n");
- exit (-1);
- }
- page = buf + fpos - bytes_read;
- } else { /* Move backward BUF_SIZE/2 bytes */
- if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
- SEEK_CUR) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer"
- " in back_lines().\n");
- exit (-1);
- }
- page = buf + BUF_SIZE / 2;
- }
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr, "\nError reading file in "
- "back_lines().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0';
- } else { /* Beginning of file reached */
- begin_reached = 1;
- return;
- }
- }
- } while (*(--page) != '\n');
- page++;
-}
-
-/*
- * Print a new page of text. Called by dialog_textbox().
- */
-static void
-print_page (WINDOW * win, int height, int width)
-{
- int i, passed_end = 0;
-
- page_length = 0;
- for (i = 0; i < height; i++) {
- print_line (win, i, width);
- if (!passed_end)
- page_length++;
- if (end_reached && !passed_end)
- passed_end = 1;
- }
- wnoutrefresh (win);
-}
-
-/*
- * Print a new line of text. Called by dialog_textbox() and print_page().
- */
-static void
-print_line (WINDOW * win, int row, int width)
-{
- int y, x;
- char *line;
-
- line = get_line ();
- line += MIN (strlen (line), hscroll); /* Scroll horizontally */
- wmove (win, row, 0); /* move cursor to correct line */
- waddch (win, ' ');
- waddnstr (win, line, MIN (strlen (line), width - 2));
-
- getyx (win, y, x);
- /* Clear 'residue' of previous line */
-#if OLD_NCURSES
- {
- int i;
- for (i = 0; i < width - x; i++)
- waddch (win, ' ');
- }
-#else
- wclrtoeol(win);
-#endif
-}
-
-/*
- * Return current line of text. Called by dialog_textbox() and print_line().
- * 'page' should point to start of current line before calling, and will be
- * updated to point to start of next line.
- */
-static char *
-get_line (void)
-{
- int i = 0, fpos;
- static char line[MAX_LEN + 1];
-
- end_reached = 0;
- while (*page != '\n') {
- if (*page == '\0') {
- /* Either end of file or end of buffer reached */
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in "
- "get_line().\n");
- exit (-1);
- }
- if (fpos < file_size) { /* Not end of file yet */
- /* We've reached end of buffer, but not end of file yet,
- so read next part of file into buffer */
- if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
- endwin ();
- fprintf (stderr, "\nError reading file in get_line().\n");
- exit (-1);
- }
- buf[bytes_read] = '\0';
- page = buf;
- } else {
- if (!end_reached)
- end_reached = 1;
- break;
- }
- } else if (i < MAX_LEN)
- line[i++] = *(page++);
- else {
- /* Truncate lines longer than MAX_LEN characters */
- if (i == MAX_LEN)
- line[i++] = '\0';
- page++;
- }
- }
- if (i <= MAX_LEN)
- line[i] = '\0';
- if (!end_reached)
- page++; /* move pass '\n' */
-
- return line;
-}
-
-/*
- * Print current position
- */
-static void
-print_position (WINDOW * win, int height, int width)
-{
- int fpos, percent;
-
- if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
- endwin ();
- fprintf (stderr, "\nError moving file pointer in print_position().\n");
- exit (-1);
- }
- wattrset (win, position_indicator_attr);
- wbkgdset (win, position_indicator_attr & A_COLOR);
- percent = !file_size ?
- 100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
- wmove (win, height - 3, width - 9);
- wprintw (win, "(%3d%%)", percent);
-}
diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c
deleted file mode 100644
index e7bce9be69c3..000000000000
--- a/scripts/lxdialog/util.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * util.c
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-
-/* use colors by default? */
-bool use_colors = 1;
-
-const char *backtitle = NULL;
-
-const char *dialog_result;
-
-/*
- * Attribute values, default is for mono display
- */
-chtype attributes[] =
-{
- A_NORMAL, /* screen_attr */
- A_NORMAL, /* shadow_attr */
- A_NORMAL, /* dialog_attr */
- A_BOLD, /* title_attr */
- A_NORMAL, /* border_attr */
- A_REVERSE, /* button_active_attr */
- A_DIM, /* button_inactive_attr */
- A_REVERSE, /* button_key_active_attr */
- A_BOLD, /* button_key_inactive_attr */
- A_REVERSE, /* button_label_active_attr */
- A_NORMAL, /* button_label_inactive_attr */
- A_NORMAL, /* inputbox_attr */
- A_NORMAL, /* inputbox_border_attr */
- A_NORMAL, /* searchbox_attr */
- A_BOLD, /* searchbox_title_attr */
- A_NORMAL, /* searchbox_border_attr */
- A_BOLD, /* position_indicator_attr */
- A_NORMAL, /* menubox_attr */
- A_NORMAL, /* menubox_border_attr */
- A_NORMAL, /* item_attr */
- A_REVERSE, /* item_selected_attr */
- A_BOLD, /* tag_attr */
- A_REVERSE, /* tag_selected_attr */
- A_BOLD, /* tag_key_attr */
- A_REVERSE, /* tag_key_selected_attr */
- A_BOLD, /* check_attr */
- A_REVERSE, /* check_selected_attr */
- A_BOLD, /* uarrow_attr */
- A_BOLD /* darrow_attr */
-};
-
-
-#include "colors.h"
-
-/*
- * Table of color values
- */
-int color_table[][3] =
-{
- {SCREEN_FG, SCREEN_BG, SCREEN_HL},
- {SHADOW_FG, SHADOW_BG, SHADOW_HL},
- {DIALOG_FG, DIALOG_BG, DIALOG_HL},
- {TITLE_FG, TITLE_BG, TITLE_HL},
- {BORDER_FG, BORDER_BG, BORDER_HL},
- {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
- {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
- {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
- {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL},
- {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL},
- {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
- BUTTON_LABEL_INACTIVE_HL},
- {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
- {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
- {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
- {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
- {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
- {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
- {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
- {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
- {ITEM_FG, ITEM_BG, ITEM_HL},
- {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
- {TAG_FG, TAG_BG, TAG_HL},
- {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
- {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
- {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
- {CHECK_FG, CHECK_BG, CHECK_HL},
- {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
- {UARROW_FG, UARROW_BG, UARROW_HL},
- {DARROW_FG, DARROW_BG, DARROW_HL},
-}; /* color_table */
-
-/*
- * Set window to attribute 'attr'
- */
-void
-attr_clear (WINDOW * win, int height, int width, chtype attr)
-{
- int i, j;
-
- wattrset (win, attr);
- for (i = 0; i < height; i++) {
- wmove (win, i, 0);
- for (j = 0; j < width; j++)
- waddch (win, ' ');
- }
- touchwin (win);
-}
-
-void dialog_clear (void)
-{
- attr_clear (stdscr, LINES, COLS, screen_attr);
- /* Display background title if it exists ... - SLH */
- if (backtitle != NULL) {
- int i;
-
- wattrset (stdscr, screen_attr);
- mvwaddstr (stdscr, 0, 1, (char *)backtitle);
- wmove (stdscr, 1, 1);
- for (i = 1; i < COLS - 1; i++)
- waddch (stdscr, ACS_HLINE);
- }
- wnoutrefresh (stdscr);
-}
-
-/*
- * Do some initialization for dialog
- */
-void
-init_dialog (void)
-{
- initscr (); /* Init curses */
- keypad (stdscr, TRUE);
- cbreak ();
- noecho ();
-
-
- if (use_colors) /* Set up colors */
- color_setup ();
-
-
- dialog_clear ();
-}
-
-/*
- * Setup for color display
- */
-void
-color_setup (void)
-{
- int i;
-
- if (has_colors ()) { /* Terminal supports color? */
- start_color ();
-
- /* Initialize color pairs */
- for (i = 0; i < ATTRIBUTE_COUNT; i++)
- init_pair (i + 1, color_table[i][0], color_table[i][1]);
-
- /* Setup color attributes */
- for (i = 0; i < ATTRIBUTE_COUNT; i++)
- attributes[i] = C_ATTR (color_table[i][2], i + 1);
- }
-}
-
-/*
- * End using dialog functions.
- */
-void
-end_dialog (void)
-{
- endwin ();
-}
-
-
-/*
- * Print a string of text in a window, automatically wrap around to the
- * next line if the string is too long to fit on one line. Newline
- * characters '\n' are replaced by spaces. We start on a new line
- * if there is no room for at least 4 nonblanks following a double-space.
- */
-void
-print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
-{
- int newl, cur_x, cur_y;
- int i, prompt_len, room, wlen;
- char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
-
- strcpy (tempstr, prompt);
-
- prompt_len = strlen(tempstr);
-
- /*
- * Remove newlines
- */
- for(i=0; i<prompt_len; i++) {
- if(tempstr[i] == '\n') tempstr[i] = ' ';
- }
-
- if (prompt_len <= width - x * 2) { /* If prompt is short */
- wmove (win, y, (width - prompt_len) / 2);
- waddstr (win, tempstr);
- } else {
- cur_x = x;
- cur_y = y;
- newl = 1;
- word = tempstr;
- while (word && *word) {
- sp = index(word, ' ');
- if (sp)
- *sp++ = 0;
-
- /* Wrap to next line if either the word does not fit,
- or it is the first word of a new sentence, and it is
- short, and the next word does not fit. */
- room = width - cur_x;
- wlen = strlen(word);
- if (wlen > room ||
- (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
- && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
- cur_y++;
- cur_x = x;
- }
- wmove (win, cur_y, cur_x);
- waddstr (win, word);
- getyx (win, cur_y, cur_x);
- cur_x++;
- if (sp && *sp == ' ') {
- cur_x++; /* double space */
- while (*++sp == ' ');
- newl = 1;
- } else
- newl = 0;
- word = sp;
- }
- }
-}
-
-/*
- * Print a button
- */
-void
-print_button (WINDOW * win, const char *label, int y, int x, int selected)
-{
- int i, temp;
-
- wmove (win, y, x);
- wattrset (win, selected ? button_active_attr : button_inactive_attr);
- waddstr (win, "<");
- temp = strspn (label, " ");
- label += temp;
- wattrset (win, selected ? button_label_active_attr
- : button_label_inactive_attr);
- for (i = 0; i < temp; i++)
- waddch (win, ' ');
- wattrset (win, selected ? button_key_active_attr
- : button_key_inactive_attr);
- waddch (win, label[0]);
- wattrset (win, selected ? button_label_active_attr
- : button_label_inactive_attr);
- waddstr (win, (char *)label + 1);
- wattrset (win, selected ? button_active_attr : button_inactive_attr);
- waddstr (win, ">");
- wmove (win, y, x + temp + 1);
-}
-
-/*
- * Draw a rectangular box with line drawing characters
- */
-void
-draw_box (WINDOW * win, int y, int x, int height, int width,
- chtype box, chtype border)
-{
- int i, j;
-
- wattrset (win, 0);
- for (i = 0; i < height; i++) {
- wmove (win, y + i, x);
- for (j = 0; j < width; j++)
- if (!i && !j)
- waddch (win, border | ACS_ULCORNER);
- else if (i == height - 1 && !j)
- waddch (win, border | ACS_LLCORNER);
- else if (!i && j == width - 1)
- waddch (win, box | ACS_URCORNER);
- else if (i == height - 1 && j == width - 1)
- waddch (win, box | ACS_LRCORNER);
- else if (!i)
- waddch (win, border | ACS_HLINE);
- else if (i == height - 1)
- waddch (win, box | ACS_HLINE);
- else if (!j)
- waddch (win, border | ACS_VLINE);
- else if (j == width - 1)
- waddch (win, box | ACS_VLINE);
- else
- waddch (win, box | ' ');
- }
-}
-
-/*
- * Draw shadows along the right and bottom edge to give a more 3D look
- * to the boxes
- */
-void
-draw_shadow (WINDOW * win, int y, int x, int height, int width)
-{
- int i;
-
- if (has_colors ()) { /* Whether terminal supports color? */
- wattrset (win, shadow_attr);
- wmove (win, y + height, x + 2);
- for (i = 0; i < width; i++)
- waddch (win, winch (win) & A_CHARTEXT);
- for (i = y + 1; i < y + height + 1; i++) {
- wmove (win, i, x + width);
- waddch (win, winch (win) & A_CHARTEXT);
- waddch (win, winch (win) & A_CHARTEXT);
- }
- wnoutrefresh (win);
- }
-}
-
-/*
- * Return the position of the first alphabetic character in a string.
- */
-int
-first_alpha(const char *string, const char *exempt)
-{
- int i, in_paren=0, c;
-
- for (i = 0; i < strlen(string); i++) {
- c = tolower(string[i]);
-
- if (strchr("<[(", c)) ++in_paren;
- if (strchr(">])", c) && in_paren > 0) --in_paren;
-
- if ((! in_paren) && isalpha(c) &&
- strchr(exempt, c) == 0)
- return i;
- }
-
- return 0;
-}
diff --git a/scripts/lxdialog/yesno.c b/scripts/lxdialog/yesno.c
deleted file mode 100644
index 11fcc25f5159..000000000000
--- a/scripts/lxdialog/yesno.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * yesno.c -- implements the yes/no box
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.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 "dialog.h"
-
-/*
- * Display termination buttons
- */
-static void
-print_buttons(WINDOW *dialog, int height, int width, int selected)
-{
- int x = width / 2 - 10;
- int y = height - 2;
-
- print_button (dialog, " Yes ", y, x, selected == 0);
- print_button (dialog, " No ", y, x + 13, selected == 1);
-
- wmove(dialog, y, x+1 + 13*selected );
- wrefresh (dialog);
-}
-
-/*
- * Display a dialog box with two buttons - Yes and No
- */
-int
-dialog_yesno (const char *title, const char *prompt, int height, int width)
-{
- int i, x, y, key = 0, button = 0;
- WINDOW *dialog;
-
- /* center dialog box on screen */
- x = (COLS - width) / 2;
- y = (LINES - height) / 2;
-
- draw_shadow (stdscr, y, x, height, width);
-
- dialog = newwin (height, width, y, x);
- keypad (dialog, TRUE);
-
- draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
- wattrset (dialog, border_attr);
- mvwaddch (dialog, height-3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch (dialog, ACS_HLINE);
- wattrset (dialog, dialog_attr);
- waddch (dialog, ACS_RTEE);
-
- if (title != NULL && strlen(title) >= width-2 ) {
- /* truncate long title -- mec */
- char * title2 = malloc(width-2+1);
- memcpy( title2, title, width-2 );
- title2[width-2] = '\0';
- title = title2;
- }
-
- if (title != NULL) {
- wattrset (dialog, title_attr);
- mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' ');
- waddstr (dialog, (char *)title);
- waddch (dialog, ' ');
- }
-
- wattrset (dialog, dialog_attr);
- print_autowrap (dialog, prompt, width - 2, 1, 3);
-
- print_buttons(dialog, height, width, 0);
-
- while (key != ESC) {
- key = wgetch (dialog);
- switch (key) {
- case 'Y':
- case 'y':
- delwin (dialog);
- return 0;
- case 'N':
- case 'n':
- delwin (dialog);
- return 1;
-
- case TAB:
- case KEY_LEFT:
- case KEY_RIGHT:
- button = ((key == KEY_LEFT ? --button : ++button) < 0)
- ? 1 : (button > 1 ? 0 : button);
-
- print_buttons(dialog, height, width, button);
- wrefresh (dialog);
- break;
- case ' ':
- case '\n':
- delwin (dialog);
- return button;
- case ESC:
- break;
- }
- }
-
- delwin (dialog);
- return -1; /* ESC pressed */
-}
diff --git a/scripts/mksysmap b/scripts/mksysmap
index a6430e05972d..4390fab9f5bd 100644
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
@@ -1,7 +1,7 @@
#!/bin/sh -x
# Based on the vmlinux file create the System.map file
# System.map is used by module-init tools and some debugging
-# tools to retreive the actual addresses of symbols in the kernel.
+# tools to retrieve the actual addresses of symbols in the kernel.
#
# Usage
# mksysmap vmlinux System.map
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e3d144a3f10b..be97caf664bb 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -16,8 +16,10 @@
* use either stdint.h or inttypes.h for the rest. */
#if KERNEL_ELFCLASS == ELFCLASS32
typedef Elf32_Addr kernel_ulong_t;
+#define BITS_PER_LONG 32
#else
typedef Elf64_Addr kernel_ulong_t;
+#define BITS_PER_LONG 64
#endif
#ifdef __sun__
#include <inttypes.h>
@@ -35,6 +37,7 @@ typedef unsigned char __u8;
* even potentially has different endianness and word sizes, since
* we handle those differences explicitly below */
#include "../../include/linux/mod_devicetable.h"
+#include "../../include/linux/input.h"
#define ADD(str, sep, cond, field) \
do { \
@@ -366,6 +369,61 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *a
return 1;
}
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void do_input(char *alias,
+ kernel_ulong_t *arr, unsigned int min, unsigned int max)
+{
+ unsigned int i;
+ for (i = min; i < max; i++) {
+ if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+ sprintf(alias+strlen(alias), "%X,*", i);
+ }
+}
+
+/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
+static int do_input_entry(const char *filename, struct input_device_id *id,
+ char *alias)
+{
+ sprintf(alias, "input:");
+
+ ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
+ ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
+ ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
+ id->id.product);
+ ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
+ id->id.version);
+
+ sprintf(alias + strlen(alias), "-e*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
+ do_input(alias, id->evbit, 0, EV_MAX);
+ sprintf(alias + strlen(alias), "k*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
+ do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+ sprintf(alias + strlen(alias), "r*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
+ do_input(alias, id->relbit, 0, REL_MAX);
+ sprintf(alias + strlen(alias), "a*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
+ do_input(alias, id->absbit, 0, ABS_MAX);
+ sprintf(alias + strlen(alias), "m*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
+ do_input(alias, id->mscbit, 0, MSC_MAX);
+ sprintf(alias + strlen(alias), "l*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
+ do_input(alias, id->ledbit, 0, LED_MAX);
+ sprintf(alias + strlen(alias), "s*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
+ do_input(alias, id->sndbit, 0, SND_MAX);
+ sprintf(alias + strlen(alias), "f*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
+ do_input(alias, id->ffbit, 0, FF_MAX);
+ sprintf(alias + strlen(alias), "w*");
+ if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
+ do_input(alias, id->swbit, 0, SW_MAX);
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -453,7 +511,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
else if (sym_is(symname, "__mod_i2c_device_table"))
do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
do_i2c_entry, mod);
-
+ else if (sym_is(symname, "__mod_input_device_table"))
+ do_table(symval, sym->st_size, sizeof(struct input_device_id),
+ do_input_entry, mod);
}
/* Now add out buffered information to the generated C source */
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3bed09e625c0..f70ff13d4818 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -326,8 +326,8 @@ parse_elf_finish(struct elf_info *info)
release_file(info->hdr, info->size);
}
-#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
-#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
+#define CRC_PFX "__crc_"
+#define KSYMTAB_PFX "__ksymtab_"
void
handle_modversions(struct module *mod, struct elf_info *info,
@@ -539,10 +539,9 @@ add_header(struct buffer *b, struct module *mod)
buf_printf(b, "\n");
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n");
buf_printf(b, "\n");
- buf_printf(b, "#undef unix\n"); /* We have a module called "unix" */
buf_printf(b, "struct module __this_module\n");
buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
- buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n");
+ buf_printf(b, " .name = KBUILD_MODNAME,\n");
if (mod->has_init)
buf_printf(b, " .init = init_module,\n");
if (mod->has_cleanup)
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index f3e7e8e4a500..c201ef001f09 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -84,7 +84,7 @@ clean-dirs += $(objtree)/debian/
# ---------------------------------------------------------------------------
.PHONY: tar%pkg
tar%pkg:
- $(MAKE)
+ $(MAKE) KBUILD_SRC=
$(CONFIG_SHELL) $(srctree)/scripts/package/buildtar $@
clean-dirs += $(objtree)/tar-install/
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index d8fffe6f8906..88b5281ac41e 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -1,9 +1,9 @@
#!/bin/sh
#
-# buildtar 0.0.3
+# buildtar 0.0.4
#
-# (C) 2004-2005 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
+# (C) 2004-2006 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
@@ -15,9 +15,8 @@ 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"
+tarball="${objtree}/linux-${KERNELRELEASE}.tar"
#
@@ -53,21 +52,17 @@ 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
+if grep -q '^CONFIG_MODULES=y' "${objtree}/.config"; then
+ make ARCH="${ARCH}" O="${objtree}" KBUILD_SRC= INSTALL_MOD_PATH="${tmpdir}" modules_install
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}"
+cp -v -- "${objtree}/System.map" "${tmpdir}/boot/System.map-${KERNELRELEASE}"
+cp -v -- "${objtree}/.config" "${tmpdir}/boot/config-${KERNELRELEASE}"
+cp -v -- "${objtree}/vmlinux" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}"
#
@@ -75,17 +70,17 @@ cp -v -- vmlinux "${tmpdir}/boot/vmlinux-${version}"
#
case "${ARCH}" in
i386)
- [ -f arch/i386/boot/bzImage ] && cp -v -- arch/i386/boot/bzImage "${tmpdir}/boot/vmlinuz-${version}"
+ [ -f "${objtree}/arch/i386/boot/bzImage" ] && cp -v -- "${objtree}/arch/i386/boot/bzImage" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
;;
alpha)
- [ -f arch/alpha/boot/vmlinux.gz ] && cp -v -- arch/alpha/boot/vmlinux.gz "${tmpdir}/boot/vmlinuz-${version}"
+ [ -f "${objtree}/arch/alpha/boot/vmlinux.gz" ] && cp -v -- "${objtree}/arch/alpha/boot/vmlinux.gz" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}"
;;
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 "${objtree}/vmlinux.SYS" ] && cp -v -- "${objtree}/vmlinux.SYS" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.SYS"
+ [ -f "${objtree}/vmlinux.dsk" ] && cp -v -- "${objtree}/vmlinux.dsk" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}.dsk"
;;
*)
- [ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${version}"
+ [ -f "${KBUILD_IMAGE}" ] && cp -v -- "${KBUILD_IMAGE}" "${tmpdir}/boot/vmlinux-kbuild-${KERNELRELEASE}"
echo "" >&2
echo '** ** ** WARNING ** ** **' >&2
echo "" >&2
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
index f2d47ca9c8fa..67e4b1868e50 100755
--- a/scripts/patch-kernel
+++ b/scripts/patch-kernel
@@ -45,7 +45,7 @@
# update usage message;
# fix some whitespace damage;
# be smarter about stopping when current version is larger than requested;
-# Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18.
+# Randy Dunlap <rdunlap@xenotime.net>, 2004-AUG-18.
#
# Add better support for (non-incremental) 2.6.x.y patches;
# If an ending version number if not specified, the script automatically
@@ -56,7 +56,7 @@
# patch-kernel does not normally support reverse patching, but does so when
# applying EXTRAVERSION (x.y) patches, so that moving from 2.6.11.y to 2.6.11.z
# is easy and handled by the script (reverse 2.6.11.y and apply 2.6.11.z).
-# Randy Dunlap <rddunlap@osdl.org>, 2005-APR-08.
+# Randy Dunlap <rdunlap@xenotime.net>, 2005-APR-08.
PNAME=patch-kernel
diff --git a/scripts/reference_discarded.pl b/scripts/reference_discarded.pl
index c2d54148a91f..4ee6ab2135b3 100644
--- a/scripts/reference_discarded.pl
+++ b/scripts/reference_discarded.pl
@@ -71,6 +71,11 @@ foreach $object (keys(%object)) {
# printf("ignoring %d conglomerate(s)\n", $ignore);
# printf("Scanning objects\n");
+
+# Keith Ownes <kaos@sgi.com> commented:
+# For our future {in}sanity, add a comment that this is the ppc .opd
+# section, not the ia64 .opd section.
+# ia64 .opd should not point to discarded sections.
$errorcount = 0;
foreach $object (keys(%object)) {
my $from;
@@ -88,6 +93,7 @@ foreach $object (keys(%object)) {
($from !~ /\.text\.exit$/ &&
$from !~ /\.exit\.text$/ &&
$from !~ /\.data\.exit$/ &&
+ $from !~ /\.opd$/ &&
$from !~ /\.exit\.data$/ &&
$from !~ /\.altinstructions$/ &&
$from !~ /\.pdr$/ &&
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 7c805c8fccd2..9a23825218f2 100644
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -1,56 +1,22 @@
-#!/usr/bin/perl
-# Copyright 2004 - Ryan Anderson <ryan@michonline.com> GPL v2
+#!/bin/sh
+# Print additional version information for non-release trees.
-use strict;
-use warnings;
-use Digest::MD5;
-require 5.006;
-
-if (@ARGV != 1) {
- print <<EOT;
-Usage: setlocalversion <srctree>
-EOT
- exit(1);
+usage() {
+ echo "Usage: $0 [srctree]" >&2
+ 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);
+cd "${1:-.}" || usage
- 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();
-}
+# Check for git and a git repo.
+if head=`git rev-parse --verify HEAD 2>/dev/null`; then
+ # Do we have an untagged version?
+ if [ "`git name-rev --tags HEAD`" = "HEAD undefined" ]; then
+ printf '%s%s' -g `echo "$head" | cut -c1-8`
+ fi
-printf "-%s\n", join("-",@LOCALVERSIONS) if (scalar @LOCALVERSIONS > 0);
+ # Are there uncommitted changes?
+ if git diff-files | read dummy; then
+ printf '%s' -dirty
+ fi
+fi
diff --git a/security/Kconfig b/security/Kconfig
index 64d3f1e9ca85..34f593410d57 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -54,6 +54,19 @@ config SECURITY_NETWORK
implement socket and networking access controls.
If you are unsure how to answer this question, answer N.
+config SECURITY_NETWORK_XFRM
+ bool "XFRM (IPSec) Networking Security Hooks"
+ depends on XFRM && SECURITY_NETWORK
+ help
+ This enables the XFRM (IPSec) networking security hooks.
+ If enabled, a security module can use these hooks to
+ implement per-packet access controls based on labels
+ derived from IPSec policy. Non-IPSec communications are
+ designated as unlabelled, and only sockets authorized
+ to communicate unlabelled data can send without using
+ IPSec.
+ If you are unsure how to answer this question, answer N.
+
config SECURITY_CAPABILITIES
tristate "Default Linux Capabilities"
depends on SECURITY
diff --git a/security/capability.c b/security/capability.c
index ec18d6075625..f9b35cc0b248 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -49,8 +49,6 @@ static struct security_operations capability_ops = {
.vm_enough_memory = cap_vm_enough_memory,
};
-#define MY_NAME __stringify(KBUILD_MODNAME)
-
/* flag to keep track of how we were registered */
static int secondary;
@@ -67,7 +65,7 @@ static int __init capability_init (void)
/* register ourselves with the security framework */
if (register_security (&capability_ops)) {
/* try registering with primary module */
- if (mod_reg_security (MY_NAME, &capability_ops)) {
+ if (mod_reg_security (KBUILD_MODNAME, &capability_ops)) {
printk (KERN_INFO "Failure registering capabilities "
"with primary security module.\n");
return -EINVAL;
@@ -85,7 +83,7 @@ static void __exit capability_exit (void)
return;
/* remove ourselves from the security framework */
if (secondary) {
- if (mod_unreg_security (MY_NAME, &capability_ops))
+ if (mod_unreg_security (KBUILD_MODNAME, &capability_ops))
printk (KERN_INFO "Failure unregistering capabilities "
"with primary module.\n");
return;
diff --git a/security/commoncap.c b/security/commoncap.c
index 04c12f58d656..8a6e097f99ea 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -7,6 +7,7 @@
*
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/security/dummy.c b/security/dummy.c
index 3ca5f2b828a0..f1a5bd98bf10 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -14,6 +14,7 @@
#undef DEBUG
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -776,8 +777,42 @@ static inline int dummy_sk_alloc_security (struct sock *sk, int family, gfp_t pr
static inline void dummy_sk_free_security (struct sock *sk)
{
}
+
+static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir)
+{
+ return 0;
+}
#endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return 0;
+}
+
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+ return 0;
+}
+
+static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+{
+}
+
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+{
+ return 0;
+}
+
+static void dummy_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
static int dummy_register_security (const char *name, struct security_operations *ops)
{
return -EINVAL;
@@ -970,7 +1005,16 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, socket_getpeersec);
set_to_dummy_if_null(ops, sk_alloc_security);
set_to_dummy_if_null(ops, sk_free_security);
-#endif /* CONFIG_SECURITY_NETWORK */
+ set_to_dummy_if_null(ops, sk_getsid);
+ #endif /* CONFIG_SECURITY_NETWORK */
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
+ set_to_dummy_if_null(ops, xfrm_policy_clone_security);
+ set_to_dummy_if_null(ops, xfrm_policy_free_security);
+ set_to_dummy_if_null(ops, xfrm_state_alloc_security);
+ set_to_dummy_if_null(ops, xfrm_state_free_security);
+ set_to_dummy_if_null(ops, xfrm_policy_lookup);
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
set_to_dummy_if_null(ops, key_alloc);
set_to_dummy_if_null(ops, key_free);
diff --git a/security/inode.c b/security/inode.c
index a5964502ae30..0f77b0223662 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -172,7 +172,7 @@ static int create_by_name(const char *name, mode_t mode,
return -EFAULT;
}
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
@@ -181,7 +181,7 @@ static int create_by_name(const char *name, mode_t mode,
error = create(parent->d_inode, *dentry, mode);
} else
error = PTR_ERR(dentry);
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
@@ -302,7 +302,7 @@ void securityfs_remove(struct dentry *dentry)
if (!parent || !parent->d_inode)
return;
- down(&parent->d_inode->i_sem);
+ mutex_lock(&parent->d_inode->i_mutex);
if (positive(dentry)) {
if (dentry->d_inode) {
if (S_ISDIR(dentry->d_inode->i_mode))
@@ -312,7 +312,7 @@ void securityfs_remove(struct dentry *dentry)
dput(dentry);
}
}
- up(&parent->d_inode->i_sem);
+ mutex_unlock(&parent->d_inode->i_mutex);
simple_release_fs(&mount, &mount_count);
}
EXPORT_SYMBOL_GPL(securityfs_remove);
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 3303673c636e..bcdb28533733 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -74,6 +74,12 @@ asmlinkage long compat_sys_keyctl(u32 option,
case KEYCTL_SET_REQKEY_KEYRING:
return keyctl_set_reqkey_keyring(arg2);
+ case KEYCTL_SET_TIMEOUT:
+ return keyctl_set_timeout(arg2, arg3);
+
+ case KEYCTL_ASSUME_AUTHORITY:
+ return keyctl_assume_authority(arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index db99ed434f3a..e066e6057955 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -25,7 +25,6 @@
#define kdebug(FMT, a...) do {} while(0)
#endif
-extern struct key_type key_type_dead;
extern struct key_type key_type_user;
/*****************************************************************************/
@@ -108,12 +107,13 @@ extern struct key *request_key_and_link(struct key_type *type,
struct request_key_auth {
struct key *target_key;
struct task_struct *context;
+ const char *callout_info;
pid_t pid;
};
extern struct key_type key_type_request_key_auth;
extern struct key *request_key_auth_new(struct key *target,
- struct key **_rkakey);
+ const char *callout_info);
extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
@@ -137,6 +137,8 @@ extern long keyctl_instantiate_key(key_serial_t, const void __user *,
size_t, key_serial_t);
extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
extern long keyctl_set_reqkey_keyring(int);
+extern long keyctl_set_timeout(key_serial_t, unsigned);
+extern long keyctl_assume_authority(key_serial_t);
/*
diff --git a/security/keys/key.c b/security/keys/key.c
index 01bcfecb7eae..99781b798312 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -36,7 +36,7 @@ static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL);
DECLARE_RWSEM(key_construction_sem);
/* any key who's type gets unegistered will be re-typed to this */
-struct key_type key_type_dead = {
+static struct key_type key_type_dead = {
.name = "dead",
};
@@ -240,9 +240,9 @@ static inline void key_alloc_serial(struct key *key)
/*
* allocate a key of the specified type
* - update the user's quota to reflect the existence of the key
- * - called from a key-type operation with key_types_sem read-locked by either
- * key_create_or_update() or by key_duplicate(); this prevents unregistration
- * of the key type
+ * - called from a key-type operation with key_types_sem read-locked by
+ * key_create_or_update()
+ * - this prevents unregistration of the key type
* - upon return the key is as yet uninstantiated; the caller needs to either
* instantiate the key or discard it before returning
*/
@@ -889,56 +889,6 @@ EXPORT_SYMBOL(key_update);
/*****************************************************************************/
/*
- * duplicate a key, potentially with a revised description
- * - must be supported by the keytype (keyrings for instance can be duplicated)
- */
-struct key *key_duplicate(struct key *source, const char *desc)
-{
- struct key *key;
- int ret;
-
- key_check(source);
-
- if (!desc)
- desc = source->description;
-
- down_read(&key_types_sem);
-
- ret = -EINVAL;
- if (!source->type->duplicate)
- goto error;
-
- /* allocate and instantiate a key */
- key = key_alloc(source->type, desc, current->fsuid, current->fsgid,
- source->perm, 0);
- if (IS_ERR(key))
- goto error_k;
-
- down_read(&source->sem);
- ret = key->type->duplicate(key, source);
- up_read(&source->sem);
- if (ret < 0)
- goto error2;
-
- atomic_inc(&key->user->nikeys);
- set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
-
- error_k:
- up_read(&key_types_sem);
- out:
- return key;
-
- error2:
- key_put(key);
- error:
- up_read(&key_types_sem);
- key = ERR_PTR(ret);
- goto out;
-
-} /* end key_duplicate() */
-
-/*****************************************************************************/
-/*
* revoke a key
*/
void key_revoke(struct key *key)
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index b7a468fabdf9..90db5c76cf6e 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -16,6 +16,7 @@
#include <linux/syscalls.h>
#include <linux/keyctl.h>
#include <linux/fs.h>
+#include <linux/capability.h>
#include <linux/err.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -834,6 +835,17 @@ long keyctl_instantiate_key(key_serial_t id,
if (plen > 32767)
goto error;
+ /* the appropriate instantiation authorisation key must have been
+ * assumed before calling this */
+ ret = -EPERM;
+ instkey = current->request_key_auth;
+ if (!instkey)
+ goto error;
+
+ rka = instkey->payload.data;
+ if (rka->target_key->serial != id)
+ goto error;
+
/* pull the payload in if one was supplied */
payload = NULL;
@@ -848,15 +860,6 @@ long keyctl_instantiate_key(key_serial_t id,
goto error2;
}
- /* find the instantiation authorisation key */
- instkey = key_get_instantiation_authkey(id);
- if (IS_ERR(instkey)) {
- ret = PTR_ERR(instkey);
- goto error2;
- }
-
- rka = instkey->payload.data;
-
/* find the destination keyring amongst those belonging to the
* requesting task */
keyring_ref = NULL;
@@ -865,7 +868,7 @@ long keyctl_instantiate_key(key_serial_t id,
KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
- goto error3;
+ goto error2;
}
}
@@ -874,11 +877,17 @@ long keyctl_instantiate_key(key_serial_t id,
key_ref_to_ptr(keyring_ref), instkey);
key_ref_put(keyring_ref);
- error3:
- key_put(instkey);
- error2:
+
+ /* discard the assumed authority if it's just been disabled by
+ * instantiation of the key */
+ if (ret == 0) {
+ key_put(current->request_key_auth);
+ current->request_key_auth = NULL;
+ }
+
+error2:
kfree(payload);
- error:
+error:
return ret;
} /* end keyctl_instantiate_key() */
@@ -895,14 +904,16 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
key_ref_t keyring_ref;
long ret;
- /* find the instantiation authorisation key */
- instkey = key_get_instantiation_authkey(id);
- if (IS_ERR(instkey)) {
- ret = PTR_ERR(instkey);
+ /* the appropriate instantiation authorisation key must have been
+ * assumed before calling this */
+ ret = -EPERM;
+ instkey = current->request_key_auth;
+ if (!instkey)
goto error;
- }
rka = instkey->payload.data;
+ if (rka->target_key->serial != id)
+ goto error;
/* find the destination keyring if present (which must also be
* writable) */
@@ -911,7 +922,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
if (IS_ERR(keyring_ref)) {
ret = PTR_ERR(keyring_ref);
- goto error2;
+ goto error;
}
}
@@ -920,9 +931,15 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
key_ref_to_ptr(keyring_ref), instkey);
key_ref_put(keyring_ref);
- error2:
- key_put(instkey);
- error:
+
+ /* discard the assumed authority if it's just been disabled by
+ * instantiation of the key */
+ if (ret == 0) {
+ key_put(current->request_key_auth);
+ current->request_key_auth = NULL;
+ }
+
+error:
return ret;
} /* end keyctl_negate_key() */
@@ -967,6 +984,88 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
/*****************************************************************************/
/*
+ * set or clear the timeout for a key
+ */
+long keyctl_set_timeout(key_serial_t id, unsigned timeout)
+{
+ struct timespec now;
+ struct key *key;
+ key_ref_t key_ref;
+ time_t expiry;
+ long ret;
+
+ key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
+ if (IS_ERR(key_ref)) {
+ ret = PTR_ERR(key_ref);
+ goto error;
+ }
+
+ key = key_ref_to_ptr(key_ref);
+
+ /* make the changes with the locks held to prevent races */
+ down_write(&key->sem);
+
+ expiry = 0;
+ if (timeout > 0) {
+ now = current_kernel_time();
+ expiry = now.tv_sec + timeout;
+ }
+
+ key->expiry = expiry;
+
+ up_write(&key->sem);
+ key_put(key);
+
+ ret = 0;
+error:
+ return ret;
+
+} /* end keyctl_set_timeout() */
+
+/*****************************************************************************/
+/*
+ * assume the authority to instantiate the specified key
+ */
+long keyctl_assume_authority(key_serial_t id)
+{
+ struct key *authkey;
+ long ret;
+
+ /* special key IDs aren't permitted */
+ ret = -EINVAL;
+ if (id < 0)
+ goto error;
+
+ /* we divest ourselves of authority if given an ID of 0 */
+ if (id == 0) {
+ key_put(current->request_key_auth);
+ current->request_key_auth = NULL;
+ ret = 0;
+ goto error;
+ }
+
+ /* attempt to assume the authority temporarily granted to us whilst we
+ * instantiate the specified key
+ * - the authorisation key must be in the current task's keyrings
+ * somewhere
+ */
+ authkey = key_get_instantiation_authkey(id);
+ if (IS_ERR(authkey)) {
+ ret = PTR_ERR(authkey);
+ goto error;
+ }
+
+ key_put(current->request_key_auth);
+ current->request_key_auth = authkey;
+ ret = authkey->serial;
+
+error:
+ return ret;
+
+} /* end keyctl_assume_authority() */
+
+/*****************************************************************************/
+/*
* the key control system call
*/
asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
@@ -1038,6 +1137,13 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
case KEYCTL_SET_REQKEY_KEYRING:
return keyctl_set_reqkey_keyring(arg2);
+ case KEYCTL_SET_TIMEOUT:
+ return keyctl_set_timeout((key_serial_t) arg2,
+ (unsigned) arg3);
+
+ case KEYCTL_ASSUME_AUTHORITY:
+ return keyctl_assume_authority((key_serial_t) arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 4e9fa8be44b8..d65a180f888d 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -48,7 +48,6 @@ static inline unsigned keyring_hash(const char *desc)
*/
static int keyring_instantiate(struct key *keyring,
const void *data, size_t datalen);
-static int keyring_duplicate(struct key *keyring, const struct key *source);
static int keyring_match(const struct key *keyring, const void *criterion);
static void keyring_destroy(struct key *keyring);
static void keyring_describe(const struct key *keyring, struct seq_file *m);
@@ -59,7 +58,6 @@ struct key_type key_type_keyring = {
.name = "keyring",
.def_datalen = sizeof(struct keyring_list),
.instantiate = keyring_instantiate,
- .duplicate = keyring_duplicate,
.match = keyring_match,
.destroy = keyring_destroy,
.describe = keyring_describe,
@@ -70,7 +68,7 @@ struct key_type key_type_keyring = {
* semaphore to serialise link/link calls to prevent two link calls in parallel
* introducing a cycle
*/
-DECLARE_RWSEM(keyring_serialise_link_sem);
+static DECLARE_RWSEM(keyring_serialise_link_sem);
/*****************************************************************************/
/*
@@ -120,68 +118,6 @@ static int keyring_instantiate(struct key *keyring,
/*****************************************************************************/
/*
- * duplicate the list of subscribed keys from a source keyring into this one
- */
-static int keyring_duplicate(struct key *keyring, const struct key *source)
-{
- struct keyring_list *sklist, *klist;
- unsigned max;
- size_t size;
- int loop, ret;
-
- const unsigned limit =
- (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *);
-
- ret = 0;
-
- /* find out how many keys are currently linked */
- rcu_read_lock();
- sklist = rcu_dereference(source->payload.subscriptions);
- max = 0;
- if (sklist)
- max = sklist->nkeys;
- rcu_read_unlock();
-
- /* allocate a new payload and stuff load with key links */
- if (max > 0) {
- BUG_ON(max > limit);
-
- max = (max + 3) & ~3;
- if (max > limit)
- max = limit;
-
- ret = -ENOMEM;
- size = sizeof(*klist) + sizeof(struct key *) * max;
- klist = kmalloc(size, GFP_KERNEL);
- if (!klist)
- goto error;
-
- /* set links */
- rcu_read_lock();
- sklist = rcu_dereference(source->payload.subscriptions);
-
- klist->maxkeys = max;
- klist->nkeys = sklist->nkeys;
- memcpy(klist->keys,
- sklist->keys,
- sklist->nkeys * sizeof(struct key *));
-
- for (loop = klist->nkeys - 1; loop >= 0; loop--)
- atomic_inc(&klist->keys[loop]->usage);
-
- rcu_read_unlock();
-
- rcu_assign_pointer(keyring->payload.subscriptions, klist);
- ret = 0;
- }
-
- error:
- return ret;
-
-} /* end keyring_duplicate() */
-
-/*****************************************************************************/
-/*
* match keyrings on their name
*/
static int keyring_match(const struct key *keyring, const void *description)
@@ -545,51 +481,6 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
/*****************************************************************************/
/*
- * search for an instantiation authorisation key matching a target key
- * - the RCU read lock must be held by the caller
- * - a target_id of zero specifies any valid token
- */
-struct key *keyring_search_instkey(struct key *keyring,
- key_serial_t target_id)
-{
- struct request_key_auth *rka;
- struct keyring_list *klist;
- struct key *instkey;
- int loop;
-
- klist = rcu_dereference(keyring->payload.subscriptions);
- if (klist) {
- for (loop = 0; loop < klist->nkeys; loop++) {
- instkey = klist->keys[loop];
-
- if (instkey->type != &key_type_request_key_auth)
- continue;
-
- rka = instkey->payload.data;
- if (target_id && rka->target_key->serial != target_id)
- continue;
-
- /* the auth key is revoked during instantiation */
- if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
- goto found;
-
- instkey = ERR_PTR(-EKEYREVOKED);
- goto error;
- }
- }
-
- instkey = ERR_PTR(-EACCES);
- goto error;
-
-found:
- atomic_inc(&instkey->usage);
-error:
- return instkey;
-
-} /* end keyring_search_instkey() */
-
-/*****************************************************************************/
-/*
* find a keyring with the specified name
* - all named keyrings are searched
* - only find keyrings with search permission for the process
@@ -748,15 +639,31 @@ static void keyring_link_rcu_disposal(struct rcu_head *rcu)
/*****************************************************************************/
/*
+ * dispose of a keyring list after the RCU grace period, freeing the unlinked
+ * key
+ */
+static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
+{
+ struct keyring_list *klist =
+ container_of(rcu, struct keyring_list, rcu);
+
+ key_put(klist->keys[klist->delkey]);
+ kfree(klist);
+
+} /* end keyring_unlink_rcu_disposal() */
+
+/*****************************************************************************/
+/*
* link a key into to a keyring
* - must be called with the keyring's semaphore write-locked
+ * - discard already extant link to matching key if there is one
*/
int __key_link(struct key *keyring, struct key *key)
{
struct keyring_list *klist, *nklist;
unsigned max;
size_t size;
- int ret;
+ int loop, ret;
ret = -EKEYREVOKED;
if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -778,6 +685,48 @@ int __key_link(struct key *keyring, struct key *key)
goto error2;
}
+ /* see if there's a matching key we can displace */
+ klist = keyring->payload.subscriptions;
+
+ if (klist && klist->nkeys > 0) {
+ struct key_type *type = key->type;
+
+ for (loop = klist->nkeys - 1; loop >= 0; loop--) {
+ if (klist->keys[loop]->type == type &&
+ strcmp(klist->keys[loop]->description,
+ key->description) == 0
+ ) {
+ /* found a match - replace with new key */
+ size = sizeof(struct key *) * klist->maxkeys;
+ size += sizeof(*klist);
+ BUG_ON(size > PAGE_SIZE);
+
+ ret = -ENOMEM;
+ nklist = kmalloc(size, GFP_KERNEL);
+ if (!nklist)
+ goto error2;
+
+ memcpy(nklist, klist, size);
+
+ /* replace matched key */
+ atomic_inc(&key->usage);
+ nklist->keys[loop] = key;
+
+ rcu_assign_pointer(
+ keyring->payload.subscriptions,
+ nklist);
+
+ /* dispose of the old keyring list and the
+ * displaced key */
+ klist->delkey = loop;
+ call_rcu(&klist->rcu,
+ keyring_unlink_rcu_disposal);
+
+ goto done;
+ }
+ }
+ }
+
/* check that we aren't going to overrun the user's quota */
ret = key_payload_reserve(keyring,
keyring->datalen + KEYQUOTA_LINK_BYTES);
@@ -794,8 +743,6 @@ int __key_link(struct key *keyring, struct key *key)
smp_wmb();
klist->nkeys++;
smp_wmb();
-
- ret = 0;
}
else {
/* grow the key list */
@@ -833,16 +780,16 @@ int __key_link(struct key *keyring, struct key *key)
/* dispose of the old keyring list */
if (klist)
call_rcu(&klist->rcu, keyring_link_rcu_disposal);
-
- ret = 0;
}
- error2:
+done:
+ ret = 0;
+error2:
up_write(&keyring_serialise_link_sem);
- error:
+error:
return ret;
- error3:
+error3:
/* undo the quota changes */
key_payload_reserve(keyring,
keyring->datalen - KEYQUOTA_LINK_BYTES);
@@ -873,21 +820,6 @@ EXPORT_SYMBOL(key_link);
/*****************************************************************************/
/*
- * dispose of a keyring list after the RCU grace period, freeing the unlinked
- * key
- */
-static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
-{
- struct keyring_list *klist =
- container_of(rcu, struct keyring_list, rcu);
-
- key_put(klist->keys[klist->delkey]);
- kfree(klist);
-
-} /* end keyring_unlink_rcu_disposal() */
-
-/*****************************************************************************/
-/*
* unlink the first link to a key from a keyring
*/
int key_unlink(struct key *keyring, struct key *key)
diff --git a/security/keys/permission.c b/security/keys/permission.c
index e7f579c0eaf5..3b41f9b52537 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -73,3 +73,35 @@ use_these_perms:
} /* end key_task_permission() */
EXPORT_SYMBOL(key_task_permission);
+
+/*****************************************************************************/
+/*
+ * validate a key
+ */
+int key_validate(struct key *key)
+{
+ struct timespec now;
+ int ret = 0;
+
+ if (key) {
+ /* check it's still accessible */
+ ret = -EKEYREVOKED;
+ if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
+ test_bit(KEY_FLAG_DEAD, &key->flags))
+ goto error;
+
+ /* check it hasn't expired */
+ ret = 0;
+ if (key->expiry) {
+ now = current_kernel_time();
+ if (now.tv_sec >= key->expiry)
+ ret = -EKEYEXPIRED;
+ }
+ }
+
+ error:
+ return ret;
+
+} /* end key_validate() */
+
+EXPORT_SYMBOL(key_validate);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 566b1cc0118a..74cb79eb917e 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -270,9 +270,14 @@ int copy_thread_group_keys(struct task_struct *tsk)
int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
{
key_check(tsk->thread_keyring);
+ key_check(tsk->request_key_auth);
/* no thread keyring yet */
tsk->thread_keyring = NULL;
+
+ /* copy the request_key() authorisation for this thread */
+ key_get(tsk->request_key_auth);
+
return 0;
} /* end copy_keys() */
@@ -290,11 +295,12 @@ void exit_thread_group_keys(struct signal_struct *tg)
/*****************************************************************************/
/*
- * dispose of keys upon thread exit
+ * dispose of per-thread keys upon thread exit
*/
void exit_keys(struct task_struct *tsk)
{
key_put(tsk->thread_keyring);
+ key_put(tsk->request_key_auth);
} /* end exit_keys() */
@@ -382,7 +388,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
struct task_struct *context)
{
struct request_key_auth *rka;
- key_ref_t key_ref, ret, err, instkey_ref;
+ key_ref_t key_ref, ret, err;
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key;
@@ -461,30 +467,12 @@ key_ref_t search_process_keyrings(struct key_type *type,
err = key_ref;
break;
}
-
- /* if this process has a session keyring and that has an
- * instantiation authorisation key in the bottom level, then we
- * also search the keyrings of the process mentioned there */
- if (context != current)
- goto no_key;
-
- rcu_read_lock();
- instkey_ref = __keyring_search_one(
- make_key_ref(rcu_dereference(
- context->signal->session_keyring),
- 1),
- &key_type_request_key_auth, NULL, 0);
- rcu_read_unlock();
-
- if (IS_ERR(instkey_ref))
- goto no_key;
-
- rka = key_ref_to_ptr(instkey_ref)->payload.data;
-
- key_ref = search_process_keyrings(type, description, match,
- rka->context);
- key_ref_put(instkey_ref);
-
+ }
+ /* or search the user-session keyring */
+ else {
+ key_ref = keyring_search_aux(
+ make_key_ref(context->user->session_keyring, 1),
+ context, type, description, match);
if (!IS_ERR(key_ref))
goto found;
@@ -500,11 +488,21 @@ key_ref_t search_process_keyrings(struct key_type *type,
break;
}
}
- /* or search the user-session keyring */
- else {
- key_ref = keyring_search_aux(
- make_key_ref(context->user->session_keyring, 1),
- context, type, description, match);
+
+ /* if this process has an instantiation authorisation key, then we also
+ * search the keyrings of the process mentioned there
+ * - we don't permit access to request_key auth keys via this method
+ */
+ if (context->request_key_auth &&
+ context == current &&
+ type != &key_type_request_key_auth &&
+ key_validate(context->request_key_auth) == 0
+ ) {
+ rka = context->request_key_auth->payload.data;
+
+ key_ref = search_process_keyrings(type, description, match,
+ rka->context);
+
if (!IS_ERR(key_ref))
goto found;
@@ -521,8 +519,6 @@ key_ref_t search_process_keyrings(struct key_type *type,
}
}
-
-no_key:
/* no key - decide on the error we're going to go for */
key_ref = ret ? ret : err;
@@ -628,6 +624,15 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
key = ERR_PTR(-EINVAL);
goto error;
+ case KEY_SPEC_REQKEY_AUTH_KEY:
+ key = context->request_key_auth;
+ if (!key)
+ goto error;
+
+ atomic_inc(&key->usage);
+ key_ref = make_key_ref(key, 1);
+ break;
+
default:
key_ref = ERR_PTR(-EINVAL);
if (id < 1)
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 5cc4bba70db6..f030a0ccbb93 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -29,28 +29,36 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
/*****************************************************************************/
/*
* request userspace finish the construction of a key
- * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
+ * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"
*/
-static int call_request_key(struct key *key,
- const char *op,
- const char *callout_info)
+static int call_sbin_request_key(struct key *key,
+ struct key *authkey,
+ const char *op)
{
struct task_struct *tsk = current;
key_serial_t prkey, sskey;
- struct key *session_keyring, *rkakey;
- char *argv[10], *envp[3], uid_str[12], gid_str[12];
+ struct key *keyring;
+ char *argv[9], *envp[3], uid_str[12], gid_str[12];
char key_str[12], keyring_str[3][12];
+ char desc[20];
int ret, i;
- kenter("{%d},%s,%s", key->serial, op, callout_info);
+ kenter("{%d},{%d},%s", key->serial, authkey->serial, op);
- /* generate a new session keyring with an auth key in it */
- session_keyring = request_key_auth_new(key, &rkakey);
- if (IS_ERR(session_keyring)) {
- ret = PTR_ERR(session_keyring);
- goto error;
+ /* allocate a new session keyring */
+ sprintf(desc, "_req.%u", key->serial);
+
+ keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
+ if (IS_ERR(keyring)) {
+ ret = PTR_ERR(keyring);
+ goto error_alloc;
}
+ /* attach the auth key to the session keyring */
+ ret = __key_link(keyring, authkey);
+ if (ret < 0)
+ goto error_link;
+
/* record the UID and GID */
sprintf(uid_str, "%d", current->fsuid);
sprintf(gid_str, "%d", current->fsgid);
@@ -95,22 +103,19 @@ static int call_request_key(struct key *key,
argv[i++] = keyring_str[0];
argv[i++] = keyring_str[1];
argv[i++] = keyring_str[2];
- argv[i++] = (char *) callout_info;
argv[i] = NULL;
/* do it */
- ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1);
+ ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, 1);
- /* dispose of the special keys */
- key_revoke(rkakey);
- key_put(rkakey);
- key_put(session_keyring);
+error_link:
+ key_put(keyring);
- error:
+error_alloc:
kleave(" = %d", ret);
return ret;
-} /* end call_request_key() */
+} /* end call_sbin_request_key() */
/*****************************************************************************/
/*
@@ -122,9 +127,10 @@ static struct key *__request_key_construction(struct key_type *type,
const char *description,
const char *callout_info)
{
+ request_key_actor_t actor;
struct key_construction cons;
struct timespec now;
- struct key *key;
+ struct key *key, *authkey;
int ret, negated;
kenter("%s,%s,%s", type->name, description, callout_info);
@@ -143,8 +149,19 @@ static struct key *__request_key_construction(struct key_type *type,
/* we drop the construction sem here on behalf of the caller */
up_write(&key_construction_sem);
+ /* allocate an authorisation key */
+ authkey = request_key_auth_new(key, callout_info);
+ if (IS_ERR(authkey)) {
+ ret = PTR_ERR(authkey);
+ authkey = NULL;
+ goto alloc_authkey_failed;
+ }
+
/* make the call */
- ret = call_request_key(key, "create", callout_info);
+ actor = call_sbin_request_key;
+ if (type->request_key)
+ actor = type->request_key;
+ ret = actor(key, authkey, "create");
if (ret < 0)
goto request_failed;
@@ -153,22 +170,29 @@ static struct key *__request_key_construction(struct key_type *type,
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
goto request_failed;
+ key_revoke(authkey);
+ key_put(authkey);
+
down_write(&key_construction_sem);
list_del(&cons.link);
up_write(&key_construction_sem);
/* also give an error if the key was negatively instantiated */
- check_not_negative:
+check_not_negative:
if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
key_put(key);
key = ERR_PTR(-ENOKEY);
}
- out:
+out:
kleave(" = %p", key);
return key;
- request_failed:
+request_failed:
+ key_revoke(authkey);
+ key_put(authkey);
+
+alloc_authkey_failed:
/* it wasn't instantiated
* - remove from construction queue
* - mark the key as dead
@@ -217,7 +241,7 @@ static struct key *__request_key_construction(struct key_type *type,
key = ERR_PTR(ret);
goto out;
- alloc_failed:
+alloc_failed:
up_write(&key_construction_sem);
goto out;
@@ -464,35 +488,3 @@ struct key *request_key(struct key_type *type,
} /* end request_key() */
EXPORT_SYMBOL(request_key);
-
-/*****************************************************************************/
-/*
- * validate a key
- */
-int key_validate(struct key *key)
-{
- struct timespec now;
- int ret = 0;
-
- if (key) {
- /* check it's still accessible */
- ret = -EKEYREVOKED;
- if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
- test_bit(KEY_FLAG_DEAD, &key->flags))
- goto error;
-
- /* check it hasn't expired */
- ret = 0;
- if (key->expiry) {
- now = current_kernel_time();
- if (now.tv_sec >= key->expiry)
- ret = -EKEYEXPIRED;
- }
- }
-
- error:
- return ret;
-
-} /* end key_validate() */
-
-EXPORT_SYMBOL(key_validate);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index a8e4069d48cb..cce6ba6b0323 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -15,11 +15,13 @@
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/seq_file.h>
+#include <asm/uaccess.h>
#include "internal.h"
static int request_key_auth_instantiate(struct key *, const void *, size_t);
static void request_key_auth_describe(const struct key *, struct seq_file *);
static void request_key_auth_destroy(struct key *);
+static long request_key_auth_read(const struct key *, char __user *, size_t);
/*
* the request-key authorisation key type definition
@@ -30,51 +32,25 @@ struct key_type key_type_request_key_auth = {
.instantiate = request_key_auth_instantiate,
.describe = request_key_auth_describe,
.destroy = request_key_auth_destroy,
+ .read = request_key_auth_read,
};
/*****************************************************************************/
/*
- * instantiate a request-key authorisation record
+ * instantiate a request-key authorisation key
*/
static int request_key_auth_instantiate(struct key *key,
const void *data,
size_t datalen)
{
- struct request_key_auth *rka, *irka;
- struct key *instkey;
- int ret;
-
- ret = -ENOMEM;
- rka = kmalloc(sizeof(*rka), GFP_KERNEL);
- if (rka) {
- /* see if the calling process is already servicing the key
- * request of another process */
- instkey = key_get_instantiation_authkey(0);
- if (!IS_ERR(instkey)) {
- /* it is - use that instantiation context here too */
- irka = instkey->payload.data;
- rka->context = irka->context;
- rka->pid = irka->pid;
- key_put(instkey);
- }
- else {
- /* it isn't - use this process as the context */
- rka->context = current;
- rka->pid = current->pid;
- }
-
- rka->target_key = key_get((struct key *) data);
- key->payload.data = rka;
- ret = 0;
- }
-
- return ret;
+ key->payload.data = (struct request_key_auth *) data;
+ return 0;
} /* end request_key_auth_instantiate() */
/*****************************************************************************/
/*
- *
+ * reading a request-key authorisation key retrieves the callout information
*/
static void request_key_auth_describe(const struct key *key,
struct seq_file *m)
@@ -83,12 +59,40 @@ static void request_key_auth_describe(const struct key *key,
seq_puts(m, "key:");
seq_puts(m, key->description);
- seq_printf(m, " pid:%d", rka->pid);
+ seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
} /* end request_key_auth_describe() */
/*****************************************************************************/
/*
+ * read the callout_info data
+ * - the key's semaphore is read-locked
+ */
+static long request_key_auth_read(const struct key *key,
+ char __user *buffer, size_t buflen)
+{
+ struct request_key_auth *rka = key->payload.data;
+ size_t datalen;
+ long ret;
+
+ datalen = strlen(rka->callout_info);
+ ret = datalen;
+
+ /* we can return the data as is */
+ if (buffer && buflen > 0) {
+ if (buflen > datalen)
+ buflen = datalen;
+
+ if (copy_to_user(buffer, rka->callout_info, buflen) != 0)
+ ret = -EFAULT;
+ }
+
+ return ret;
+
+} /* end request_key_auth_read() */
+
+/*****************************************************************************/
+/*
* destroy an instantiation authorisation token key
*/
static void request_key_auth_destroy(struct key *key)
@@ -104,56 +108,89 @@ static void request_key_auth_destroy(struct key *key)
/*****************************************************************************/
/*
- * create a session keyring to be for the invokation of /sbin/request-key and
- * stick an authorisation token in it
+ * create an authorisation token for /sbin/request-key or whoever to gain
+ * access to the caller's security data
*/
-struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
+struct key *request_key_auth_new(struct key *target, const char *callout_info)
{
- struct key *keyring, *rkakey = NULL;
+ struct request_key_auth *rka, *irka;
+ struct key *authkey = NULL;
char desc[20];
int ret;
kenter("%d,", target->serial);
- /* allocate a new session keyring */
- sprintf(desc, "_req.%u", target->serial);
+ /* allocate a auth record */
+ rka = kmalloc(sizeof(*rka), GFP_KERNEL);
+ if (!rka) {
+ kleave(" = -ENOMEM");
+ return ERR_PTR(-ENOMEM);
+ }
- keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
- if (IS_ERR(keyring)) {
- kleave("= %ld", PTR_ERR(keyring));
- return keyring;
+ /* see if the calling process is already servicing the key request of
+ * another process */
+ if (current->request_key_auth) {
+ /* it is - use that instantiation context here too */
+ irka = current->request_key_auth->payload.data;
+ rka->context = irka->context;
+ rka->pid = irka->pid;
}
+ else {
+ /* it isn't - use this process as the context */
+ rka->context = current;
+ rka->pid = current->pid;
+ }
+
+ rka->target_key = key_get(target);
+ rka->callout_info = callout_info;
/* allocate the auth key */
sprintf(desc, "%x", target->serial);
- rkakey = key_alloc(&key_type_request_key_auth, desc,
- current->fsuid, current->fsgid,
- KEY_POS_VIEW | KEY_USR_VIEW, 1);
- if (IS_ERR(rkakey)) {
- key_put(keyring);
- kleave("= %ld", PTR_ERR(rkakey));
- return rkakey;
+ authkey = key_alloc(&key_type_request_key_auth, desc,
+ current->fsuid, current->fsgid,
+ KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
+ KEY_USR_VIEW, 1);
+ if (IS_ERR(authkey)) {
+ ret = PTR_ERR(authkey);
+ goto error_alloc;
}
/* construct and attach to the keyring */
- ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
- if (ret < 0) {
- key_revoke(rkakey);
- key_put(rkakey);
- key_put(keyring);
- kleave("= %d", ret);
- return ERR_PTR(ret);
- }
+ ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
+ if (ret < 0)
+ goto error_inst;
- *_rkakey = rkakey;
- kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
- return keyring;
+ kleave(" = {%d})", authkey->serial);
+ return authkey;
+
+error_inst:
+ key_revoke(authkey);
+ key_put(authkey);
+error_alloc:
+ key_put(rka->target_key);
+ kfree(rka);
+ kleave("= %d", ret);
+ return ERR_PTR(ret);
} /* end request_key_auth_new() */
/*****************************************************************************/
/*
+ * see if an authorisation key is associated with a particular key
+ */
+static int key_get_instantiation_authkey_match(const struct key *key,
+ const void *_id)
+{
+ struct request_key_auth *rka = key->payload.data;
+ key_serial_t id = (key_serial_t)(unsigned long) _id;
+
+ return rka->target_key->serial == id;
+
+} /* end key_get_instantiation_authkey_match() */
+
+/*****************************************************************************/
+/*
* get the authorisation key for instantiation of a specific key if attached to
* the current process's keyrings
* - this key is inserted into a keyring and that is set as /sbin/request-key's
@@ -162,22 +199,27 @@ struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
*/
struct key *key_get_instantiation_authkey(key_serial_t target_id)
{
- struct task_struct *tsk = current;
- struct key *instkey;
-
- /* we must have our own personal session keyring */
- if (!tsk->signal->session_keyring)
- return ERR_PTR(-EACCES);
-
- /* and it must contain a suitable request authorisation key
- * - lock RCU against session keyring changing
- */
- rcu_read_lock();
+ struct key *authkey;
+ key_ref_t authkey_ref;
+
+ authkey_ref = search_process_keyrings(
+ &key_type_request_key_auth,
+ (void *) (unsigned long) target_id,
+ key_get_instantiation_authkey_match,
+ current);
+
+ if (IS_ERR(authkey_ref)) {
+ authkey = ERR_PTR(PTR_ERR(authkey_ref));
+ goto error;
+ }
- instkey = keyring_search_instkey(
- rcu_dereference(tsk->signal->session_keyring), target_id);
+ authkey = key_ref_to_ptr(authkey_ref);
+ if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {
+ key_put(authkey);
+ authkey = ERR_PTR(-EKEYREVOKED);
+ }
- rcu_read_unlock();
- return instkey;
+error:
+ return authkey;
} /* end key_get_instantiation_authkey() */
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index cbda3b2780a1..8e71895b97a7 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -26,7 +26,6 @@
struct key_type key_type_user = {
.name = "user",
.instantiate = user_instantiate,
- .duplicate = user_duplicate,
.update = user_update,
.match = user_match,
.destroy = user_destroy,
@@ -68,42 +67,10 @@ error:
return ret;
} /* end user_instantiate() */
-
EXPORT_SYMBOL_GPL(user_instantiate);
/*****************************************************************************/
/*
- * duplicate a user defined key
- * - both keys' semaphores are locked against further modification
- * - the new key cannot yet be accessed
- */
-int user_duplicate(struct key *key, const struct key *source)
-{
- struct user_key_payload *upayload, *spayload;
- int ret;
-
- /* just copy the payload */
- ret = -ENOMEM;
- upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
- if (upayload) {
- spayload = rcu_dereference(source->payload.data);
- BUG_ON(source->datalen != spayload->datalen);
-
- upayload->datalen = key->datalen = spayload->datalen;
- memcpy(upayload->data, spayload->data, key->datalen);
-
- key->payload.data = upayload;
- ret = 0;
- }
-
- return ret;
-
-} /* end user_duplicate() */
-
-EXPORT_SYMBOL_GPL(user_duplicate);
-
-/*****************************************************************************/
-/*
* dispose of the old data from an updated user defined key
*/
static void user_update_rcu_disposal(struct rcu_head *rcu)
diff --git a/security/security.c b/security/security.c
index ed5fb80769c3..f693e1f66b98 100644
--- a/security/security.c
+++ b/security/security.c
@@ -11,6 +11,7 @@
* (at your option) any later version.
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index b038cd0fae2e..06d54d9d20a5 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -8,5 +8,7 @@ selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
+selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
+
EXTRA_CFLAGS += -Isecurity/selinux/include
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 12e4fb72bf0f..53d6c7bbf564 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -494,8 +494,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab,
char *name1, char *name2)
{
if (!ipv6_addr_any(addr))
- audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:"
- "%04x:%04x:%04x", name1, NIP6(*addr));
+ audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr));
if (port)
audit_log_format(ab, " %s=%d", name2, ntohs(port));
}
@@ -504,7 +503,7 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr,
__be16 port, char *name1, char *name2)
{
if (addr)
- audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr));
+ audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr));
if (port)
audit_log_format(ab, " %s=%d", name2, ntohs(port));
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index fc774436a264..b9f8d9731c3d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -73,6 +73,7 @@
#include "avc.h"
#include "objsec.h"
#include "netif.h"
+#include "xfrm.h"
#define XATTR_SELINUX_SUFFIX "selinux"
#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -1018,7 +1019,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
has the same SID as the process. If av is zero, then
access to the file is not checked, e.g. for cases
where only the descriptor is affected like seek. */
-static inline int file_has_perm(struct task_struct *tsk,
+static int file_has_perm(struct task_struct *tsk,
struct file *file,
u32 av)
{
@@ -1662,7 +1663,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
continue;
}
if (devnull) {
- rcuref_inc(&devnull->f_count);
+ get_file(devnull);
} else {
devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
if (!devnull) {
@@ -3349,6 +3350,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
err = avc_has_perm(sock_sid, port_sid,
sock_class, recv_perm, &ad);
}
+
+ if (!err)
+ err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+
out:
return err;
}
@@ -3401,6 +3406,24 @@ static void selinux_sk_free_security(struct sock *sk)
sk_free_security(sk);
}
+static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir)
+{
+ struct inode_security_struct *isec;
+ u32 sock_sid = SECINITSID_ANY_SOCKET;
+
+ if (!sk)
+ return selinux_no_sk_sid(fl);
+
+ read_lock_bh(&sk->sk_callback_lock);
+ isec = get_sock_isec(sk);
+
+ if (isec)
+ sock_sid = isec->sid;
+
+ read_unlock_bh(&sk->sk_callback_lock);
+ return sock_sid;
+}
+
static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
{
int err = 0;
@@ -3536,6 +3559,11 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
send_perm, &ad) ? NF_DROP : NF_ACCEPT;
}
+ if (err != NF_ACCEPT)
+ goto out;
+
+ err = selinux_xfrm_postroute_last(isec->sid, skb);
+
out:
return err;
}
@@ -4380,6 +4408,16 @@ static struct security_operations selinux_ops = {
.socket_getpeersec = selinux_socket_getpeersec,
.sk_alloc_security = selinux_sk_alloc_security,
.sk_free_security = selinux_sk_free_security,
+ .sk_getsid = selinux_sk_getsid_security,
+#endif
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+ .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
+ .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
+ .xfrm_policy_free_security = selinux_xfrm_policy_free,
+ .xfrm_state_alloc_security = selinux_xfrm_state_alloc,
+ .xfrm_state_free_security = selinux_xfrm_state_free,
+ .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
#endif
};
@@ -4491,6 +4529,7 @@ static int __init selinux_nf_ip_init(void)
panic("SELinux: nf_register_hook for IPv6: error %d\n", err);
#endif /* IPV6 */
+
out:
return err;
}
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 1deb59e1b762..591e98d9315a 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -238,3 +238,4 @@
S_(SECCLASS_NSCD, NSCD__SHMEMHOST, "shmemhost")
S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
+ S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index a78b5d59c9fc..d7f02edf3930 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -908,6 +908,7 @@
#define ASSOCIATION__SENDTO 0x00000001UL
#define ASSOCIATION__RECVFROM 0x00000002UL
+#define ASSOCIATION__SETCONTEXT 0x00000004UL
#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL
#define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
new file mode 100644
index 000000000000..8e87996c6dd5
--- /dev/null
+++ b/security/selinux/include/xfrm.h
@@ -0,0 +1,54 @@
+/*
+ * SELinux support for the XFRM LSM hooks
+ *
+ * Author : Trent Jaeger, <jaegert@us.ibm.com>
+ */
+#ifndef _SELINUX_XFRM_H_
+#define _SELINUX_XFRM_H_
+
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
+void selinux_xfrm_state_free(struct xfrm_state *x);
+int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
+
+/*
+ * Extract the security blob from the sock (it's actually on the socket)
+ */
+static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
+{
+ if (!sk->sk_socket)
+ return NULL;
+
+ return SOCK_INODE(sk->sk_socket)->i_security;
+}
+
+
+static inline u32 selinux_no_sk_sid(struct flowi *fl)
+{
+ /* NOTE: no sock occurs on ICMP reply, forwards, ... */
+ /* icmp_reply: authorize as kernel packet */
+ if (fl && fl->proto == IPPROTO_ICMP) {
+ return SECINITSID_KERNEL;
+ }
+
+ return SECINITSID_ANY_SOCKET;
+}
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
+#else
+static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+ return NF_ACCEPT;
+}
+#endif
+
+#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 0e1352a555c8..b5fa02d17b1e 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -376,7 +376,7 @@ static ssize_t selinux_transaction_write(struct file *file, const char __user *b
char *data;
ssize_t rv;
- if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
+ if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
return -EINVAL;
data = simple_transaction_get(file, buf, size);
@@ -889,7 +889,7 @@ static void sel_remove_bools(struct dentry *de)
spin_lock(&dcache_lock);
node = de->d_subdirs.next;
while (node != &de->d_subdirs) {
- struct dentry *d = list_entry(node, struct dentry, d_child);
+ struct dentry *d = list_entry(node, struct dentry, d_u.d_child);
list_del_init(node);
if (d->d_inode) {
@@ -1161,7 +1161,7 @@ static int sel_make_avc_files(struct dentry *dir)
#endif
};
- for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE(files); i++) {
struct inode *inode;
struct dentry *dentry;
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index dde094feb20d..d049c7acbc8b 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -359,7 +359,7 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
return -1;
}
- for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) {
+ for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
if (val & spec_order[i]) {
key.specified = spec_order[i] | enabled;
datum.data = le32_to_cpu(buf32[items++]);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac311dc8371..0111990ba837 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -103,7 +103,7 @@ static struct policydb_compat_info *policydb_lookup_compat(int version)
int i;
struct policydb_compat_info *info = NULL;
- for (i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++) {
+ for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) {
if (policydb_compat[i].version == version) {
info = &policydb_compat[i];
break;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 44eb4d74908d..8a764928ff4b 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1712,11 +1712,11 @@ int security_get_bools(int *len, char ***names, int **values)
goto out;
}
- *names = (char**)kcalloc(*len, sizeof(char*), GFP_ATOMIC);
+ *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC);
if (!*names)
goto err;
- *values = (int*)kcalloc(*len, sizeof(int), GFP_ATOMIC);
+ *values = kcalloc(*len, sizeof(int), GFP_ATOMIC);
if (!*values)
goto err;
@@ -1724,7 +1724,7 @@ int security_get_bools(int *len, char ***names, int **values)
size_t name_len;
(*values)[i] = policydb.bool_val_to_struct[i]->state;
name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
- (*names)[i] = (char*)kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
+ (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
if (!(*names)[i])
goto err;
strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
new file mode 100644
index 000000000000..b2af7ca496c1
--- /dev/null
+++ b/security/selinux/xfrm.c
@@ -0,0 +1,305 @@
+/*
+ * NSA Security-Enhanced Linux (SELinux) security module
+ *
+ * This file contains the SELinux XFRM hook function implementations.
+ *
+ * Authors: Serge Hallyn <sergeh@us.ibm.com>
+ * Trent Jaeger <jaegert@us.ibm.com>
+ *
+ * Copyright (C) 2005 International Business Machines 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.
+ */
+
+/*
+ * USAGE:
+ * NOTES:
+ * 1. Make sure to enable the following options in your kernel config:
+ * CONFIG_SECURITY=y
+ * CONFIG_SECURITY_NETWORK=y
+ * CONFIG_SECURITY_NETWORK_XFRM=y
+ * CONFIG_SECURITY_SELINUX=m/y
+ * ISSUES:
+ * 1. Caching packets, so they are not dropped during negotiation
+ * 2. Emulating a reasonable SO_PEERSEC across machines
+ * 3. Testing addition of sk_policy's with security context via setsockopt
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/xfrm.h>
+#include <net/xfrm.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <asm/semaphore.h>
+
+#include "avc.h"
+#include "objsec.h"
+#include "xfrm.h"
+
+
+/*
+ * Returns true if an LSM/SELinux context
+ */
+static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
+{
+ return (ctx &&
+ (ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
+ (ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
+}
+
+/*
+ * Returns true if the xfrm contains a security blob for SELinux
+ */
+static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
+{
+ return selinux_authorizable_ctx(x->security);
+}
+
+/*
+ * LSM hook implementation that authorizes that a socket can be used
+ * with the corresponding xfrm_sec_ctx and direction.
+ */
+int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+{
+ int rc = 0;
+ u32 sel_sid = SECINITSID_UNLABELED;
+ struct xfrm_sec_ctx *ctx;
+
+ /* Context sid is either set to label or ANY_ASSOC */
+ if ((ctx = xp->security)) {
+ if (!selinux_authorizable_ctx(ctx))
+ return -EINVAL;
+
+ sel_sid = ctx->ctx_sid;
+ }
+
+ rc = avc_has_perm(sk_sid, sel_sid, SECCLASS_ASSOCIATION,
+ ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM :
+ ((dir == FLOW_DIR_OUT) ? ASSOCIATION__SENDTO :
+ (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))),
+ NULL);
+
+ return rc;
+}
+
+/*
+ * Security blob allocation for xfrm_policy and xfrm_state
+ * CTX does not have a meaningful value on input
+ */
+static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *uctx)
+{
+ int rc = 0;
+ struct task_security_struct *tsec = current->security;
+ struct xfrm_sec_ctx *ctx;
+
+ BUG_ON(!uctx);
+ BUG_ON(uctx->ctx_doi != XFRM_SC_ALG_SELINUX);
+
+ if (uctx->ctx_len >= PAGE_SIZE)
+ return -ENOMEM;
+
+ *ctxp = ctx = kmalloc(sizeof(*ctx) +
+ uctx->ctx_len,
+ GFP_KERNEL);
+
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->ctx_doi = uctx->ctx_doi;
+ ctx->ctx_len = uctx->ctx_len;
+ ctx->ctx_alg = uctx->ctx_alg;
+
+ memcpy(ctx->ctx_str,
+ uctx+1,
+ ctx->ctx_len);
+ rc = security_context_to_sid(ctx->ctx_str,
+ ctx->ctx_len,
+ &ctx->ctx_sid);
+
+ if (rc)
+ goto out;
+
+ /*
+ * Does the subject have permission to set security or permission to
+ * do the relabel?
+ * Must be permitted to relabel from default socket type (process type)
+ * to specified context
+ */
+ rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+ SECCLASS_ASSOCIATION,
+ ASSOCIATION__SETCONTEXT, NULL);
+ if (rc)
+ goto out;
+
+ return rc;
+
+out:
+ *ctxp = NULL;
+ kfree(ctx);
+ return rc;
+}
+
+/*
+ * LSM hook implementation that allocs and transfers uctx spec to
+ * xfrm_policy.
+ */
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *uctx)
+{
+ int err;
+
+ BUG_ON(!xp);
+
+ err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx);
+ return err;
+}
+
+
+/*
+ * LSM hook implementation that copies security data structure from old to
+ * new for policy cloning.
+ */
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+ struct xfrm_sec_ctx *old_ctx, *new_ctx;
+
+ old_ctx = old->security;
+
+ if (old_ctx) {
+ new_ctx = new->security = kmalloc(sizeof(*new_ctx) +
+ old_ctx->ctx_len,
+ GFP_KERNEL);
+
+ if (!new_ctx)
+ return -ENOMEM;
+
+ memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
+ memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
+ }
+ return 0;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_policy security information.
+ */
+void selinux_xfrm_policy_free(struct xfrm_policy *xp)
+{
+ struct xfrm_sec_ctx *ctx = xp->security;
+ if (ctx)
+ kfree(ctx);
+}
+
+/*
+ * LSM hook implementation that allocs and transfers sec_ctx spec to
+ * xfrm_state.
+ */
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx)
+{
+ int err;
+
+ BUG_ON(!x);
+
+ err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx);
+ return err;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_state security information.
+ */
+void selinux_xfrm_state_free(struct xfrm_state *x)
+{
+ struct xfrm_sec_ctx *ctx = x->security;
+ if (ctx)
+ kfree(ctx);
+}
+
+/*
+ * LSM hook that controls access to unlabelled packets. If
+ * a xfrm_state is authorizable (defined by macro) then it was
+ * already authorized by the IPSec process. If not, then
+ * we need to check for unlabelled access since this may not have
+ * gone thru the IPSec process.
+ */
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+ int i, rc = 0;
+ struct sec_path *sp;
+
+ sp = skb->sp;
+
+ if (sp) {
+ /*
+ * __xfrm_policy_check does not approve unless xfrm_policy_ok
+ * says that spi's match for policy and the socket.
+ *
+ * Only need to verify the existence of an authorizable sp.
+ */
+ for (i = 0; i < sp->len; i++) {
+ struct xfrm_state *x = sp->x[i].xvec;
+
+ if (x && selinux_authorizable_xfrm(x))
+ goto accept;
+ }
+ }
+
+ /* check SELinux sock for unlabelled access */
+ rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+ ASSOCIATION__RECVFROM, NULL);
+ if (rc)
+ goto drop;
+
+accept:
+ return 0;
+
+drop:
+ return rc;
+}
+
+/*
+ * POSTROUTE_LAST hook's XFRM processing:
+ * If we have no security association, then we need to determine
+ * whether the socket is allowed to send to an unlabelled destination.
+ * If we do have a authorizable security association, then it has already been
+ * checked in xfrm_policy_lookup hook.
+ */
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+ struct dst_entry *dst;
+ int rc = 0;
+
+ dst = skb->dst;
+
+ if (dst) {
+ struct dst_entry *dst_test;
+
+ for (dst_test = dst; dst_test != 0;
+ dst_test = dst_test->child) {
+ struct xfrm_state *x = dst_test->xfrm;
+
+ if (x && selinux_authorizable_xfrm(x))
+ goto accept;
+ }
+ }
+
+ rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+ ASSOCIATION__SENDTO, NULL);
+ if (rc)
+ goto drop;
+
+accept:
+ return NF_ACCEPT;
+
+drop:
+ return NF_DROP;
+}
diff --git a/sound/Kconfig b/sound/Kconfig
index d8f11408ce27..b65ee4701f98 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -48,14 +48,6 @@ config SND
For more information, see <http://www.alsa-project.org/>
-config SND_AC97_CODEC
- tristate
- select SND_PCM
- select SND_AC97_BUS
-
-config SND_AC97_BUS
- tristate
-
source "sound/core/Kconfig"
source "sound/drivers/Kconfig"
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index 0864a7ce414d..2e4a5e0d16db 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -7,7 +7,6 @@ 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/aaci.c b/sound/arm/aaci.c
index 559ead6367da..54147c1f6361 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -17,11 +17,11 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/amba/bus.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/sizes.h>
-#include <asm/hardware/amba.h>
#include <sound/driver.h>
#include <sound/core.h>
@@ -40,7 +40,7 @@
*/
#undef CONFIG_PM
-static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
+static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)
{
u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
@@ -65,7 +65,7 @@ static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
* SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
* register.
*/
-static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
struct aaci *aaci = ac97->private_data;
u32 v;
@@ -97,7 +97,7 @@ static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val
/*
* Read an AC'97 register.
*/
-static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
+static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
struct aaci *aaci = ac97->private_data;
u32 v;
@@ -284,11 +284,11 @@ static unsigned int rate_list[] = {
* (unimplemented)
*/
static int
-aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+aaci_rule_rate_by_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
{
struct aaci *aaci = rule->private;
unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
- snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
switch (c->max) {
case 6:
@@ -304,7 +304,7 @@ aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
rate_mask);
}
-static snd_pcm_hardware_t aaci_hw_info = {
+static struct snd_pcm_hardware aaci_hw_info = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -330,10 +330,10 @@ static snd_pcm_hardware_t aaci_hw_info = {
.periods_max = PAGE_SIZE / 16,
};
-static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
+static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream,
struct aaci_runtime *aacirun)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
aacirun->substream = substream;
@@ -375,7 +375,7 @@ static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
/*
* Common ALSA stuff
*/
-static int aaci_pcm_close(snd_pcm_substream_t *substream)
+static int aaci_pcm_close(struct snd_pcm_substream *substream)
{
struct aaci *aaci = substream->private_data;
struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -388,7 +388,7 @@ static int aaci_pcm_close(snd_pcm_substream_t *substream)
return 0;
}
-static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
+static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -409,9 +409,9 @@ static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
return 0;
}
-static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
+static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
struct aaci_runtime *aacirun,
- snd_pcm_hw_params_t *params)
+ struct snd_pcm_hw_params *params)
{
int err;
@@ -434,9 +434,9 @@ static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
return err;
}
-static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
+static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct aaci_runtime *aacirun = runtime->private_data;
aacirun->start = (void *)runtime->dma_area;
@@ -448,16 +448,16 @@ static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct aaci_runtime *aacirun = runtime->private_data;
ssize_t bytes = aacirun->ptr - aacirun->start;
return bytes_to_frames(runtime, bytes);
}
-static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+static int aaci_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
{
return devdma_mmap(NULL, substream, vma);
}
@@ -484,7 +484,7 @@ static const u32 channels_to_txmask[] = {
static unsigned int channel_list[] = { 2, 4, 6 };
static int
-aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
{
struct aaci *aaci = rule->private;
unsigned int chan_mask = 1 << 0, slots;
@@ -504,7 +504,7 @@ aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
chan_mask);
}
-static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
+static int aaci_pcm_playback_open(struct snd_pcm_substream *substream)
{
struct aaci *aaci = substream->private_data;
int ret;
@@ -522,8 +522,8 @@ static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
return aaci_pcm_open(aaci, substream, &aaci->playback);
}
-static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
struct aaci *aaci = substream->private_data;
struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -575,7 +575,7 @@ static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
writel(aacirun->cr, aacirun->base + AACI_TXCR);
}
-static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct aaci *aaci = substream->private_data;
struct aaci_runtime *aacirun = substream->runtime->private_data;
@@ -614,7 +614,7 @@ static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
return ret;
}
-static snd_pcm_ops_t aaci_playback_ops = {
+static struct snd_pcm_ops aaci_playback_ops = {
.open = aaci_pcm_playback_open,
.close = aaci_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -632,34 +632,29 @@ static snd_pcm_ops_t aaci_playback_ops = {
* Power Management.
*/
#ifdef CONFIG_PM
-static int aaci_do_suspend(snd_card_t *card, unsigned int state)
+static int aaci_do_suspend(struct snd_card *card, unsigned int state)
{
struct aaci *aaci = card->private_data;
- if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
- snd_pcm_suspend_all(aaci->pcm);
- snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
- }
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
+ snd_pcm_suspend_all(aaci->pcm);
return 0;
}
-static int aaci_do_resume(snd_card_t *card, unsigned int state)
+static int aaci_do_resume(struct snd_card *card, unsigned int state)
{
- struct aaci *aaci = card->private_data;
- if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
- snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
- }
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
static int aaci_suspend(struct amba_device *dev, pm_message_t state)
{
- snd_card_t *card = amba_get_drvdata(dev);
+ struct snd_card *card = amba_get_drvdata(dev);
return card ? aaci_do_suspend(card) : 0;
}
static int aaci_resume(struct amba_device *dev)
{
- snd_card_t *card = amba_get_drvdata(dev);
+ struct snd_card *card = amba_get_drvdata(dev);
return card ? aaci_do_resume(card) : 0;
}
#else
@@ -705,16 +700,16 @@ static struct ac97_pcm ac97_defs[] __devinitdata = {
}
};
-static ac97_bus_ops_t aaci_bus_ops = {
+static struct snd_ac97_bus_ops aaci_bus_ops = {
.write = aaci_ac97_write,
.read = aaci_ac97_read,
};
static int __devinit aaci_probe_ac97(struct aaci *aaci)
{
- ac97_template_t ac97_template;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
+ struct snd_ac97_template ac97_template;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
int ret;
/*
@@ -737,7 +732,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
ac97_bus->clock = 48000;
aaci->ac97_bus = ac97_bus;
- memset(&ac97_template, 0, sizeof(ac97_template_t));
+ memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
ac97_template.private_data = aaci;
ac97_template.num = 0;
ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
@@ -762,7 +757,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
return ret;
}
-static void aaci_free_card(snd_card_t *card)
+static void aaci_free_card(struct snd_card *card)
{
struct aaci *aaci = card->private_data;
if (aaci->base)
@@ -772,7 +767,7 @@ static void aaci_free_card(snd_card_t *card)
static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
{
struct aaci *aaci;
- snd_card_t *card;
+ struct snd_card *card;
card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
THIS_MODULE, sizeof(struct aaci));
@@ -780,7 +775,6 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
return ERR_PTR(-ENOMEM);
card->private_free = aaci_free_card;
- snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
@@ -803,7 +797,7 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
static int __devinit aaci_init_pcm(struct aaci *aaci)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int ret;
ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
@@ -920,7 +914,7 @@ static int __devinit aaci_probe(struct amba_device *dev, void *id)
static int __devexit aaci_remove(struct amba_device *dev)
{
- snd_card_t *card = amba_get_drvdata(dev);
+ struct snd_card *card = amba_get_drvdata(dev);
amba_set_drvdata(dev, NULL);
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index b2f969bc7845..83f73c2505c6 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -207,7 +207,7 @@ struct aaci_runtime {
int pcm_open;
u32 cr;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
/*
* PIO support
@@ -222,7 +222,7 @@ struct aaci_runtime {
struct aaci {
struct amba_device *dev;
- snd_card_t *card;
+ struct snd_card *card;
void __iomem *base;
unsigned int fifosize;
@@ -236,7 +236,7 @@ struct aaci {
struct aaci_runtime playback;
struct aaci_runtime capture;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
};
#define ACSTREAM_FRONT 0
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c
index 60826a5324b4..ca3bf4ee05a3 100644
--- a/sound/arm/devdma.c
+++ b/sound/arm/devdma.c
@@ -18,9 +18,9 @@
#include "devdma.h"
-void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
+void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_dma_buffer *buf = runtime->dma_buffer_p;
if (runtime->dma_area == NULL)
@@ -34,9 +34,9 @@ void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
snd_pcm_set_runtime_buffer(substream, NULL);
}
-int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size)
+int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_dma_buffer *buf = runtime->dma_buffer_p;
int ret = 0;
@@ -74,8 +74,8 @@ int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t s
return -ENOMEM;
}
-int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
}
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h
index 5a33b6bacc34..d025329c8a0f 100644
--- a/sound/arm/devdma.h
+++ b/sound/arm/devdma.h
@@ -1,3 +1,3 @@
-void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream);
-int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size);
-int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma);
+void devdma_hw_free(struct device *dev, struct snd_pcm_substream *substream);
+int devdma_hw_alloc(struct device *dev, struct snd_pcm_substream *substream, size_t size);
+int devdma_mmap(struct device *dev, struct snd_pcm_substream *substream, struct vm_area_struct *vma);
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index c96c8a2aa1c2..3acbc6023d19 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -37,69 +37,74 @@ static DECLARE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
-static unsigned short pxa2xx_ac97_read(ac97_t *ac97, unsigned short reg)
+/*
+ * Beware PXA27x bugs:
+ *
+ * o Slot 12 read from modem space will hang controller.
+ * o CDONE, SDONE interrupt fails after any slot 12 IO.
+ *
+ * We therefore have an hybrid approach for waiting on SDONE (interrupt or
+ * 1 jiffy timeout if interrupt never comes).
+ */
+
+static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
unsigned short val = -1;
volatile u32 *reg_addr;
down(&car_mutex);
- if (CAR & CAR_CAIP) {
- printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__);
- goto out;
- }
/* set up primary or secondary codec space */
reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
reg_addr += (reg >> 1);
/* start read access across the ac97 link */
+ GSR = GSR_CDONE | GSR_SDONE;
gsr_bits = 0;
val = *reg_addr;
if (reg == AC97_GPIO_STATUS)
goto out;
- wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1);
- if (!gsr_bits & GSR_SDONE) {
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_SDONE)) {
printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
- __FUNCTION__, reg, gsr_bits);
+ __FUNCTION__, reg, GSR | gsr_bits);
val = -1;
goto out;
}
/* valid data now */
+ GSR = GSR_CDONE | GSR_SDONE;
gsr_bits = 0;
val = *reg_addr;
/* but we've just started another cycle... */
- wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1);
+ wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
out: up(&car_mutex);
return val;
}
-static void pxa2xx_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
volatile u32 *reg_addr;
down(&car_mutex);
- if (CAR & CAR_CAIP) {
- printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__);
- goto out;
- }
-
/* set up primary or secondary codec space */
reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE;
reg_addr += (reg >> 1);
+
+ GSR = GSR_CDONE | GSR_SDONE;
gsr_bits = 0;
*reg_addr = val;
- wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1);
- if (!gsr_bits & GSR_SDONE)
+ if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
+ !((GSR | gsr_bits) & GSR_CDONE))
printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
- __FUNCTION__, reg, gsr_bits);
+ __FUNCTION__, reg, GSR | gsr_bits);
-out: up(&car_mutex);
+ up(&car_mutex);
}
-static void pxa2xx_ac97_reset(ac97_t *ac97)
+static void pxa2xx_ac97_reset(struct snd_ac97 *ac97)
{
/* First, try cold reset */
GCR &= GCR_COLD_RST; /* clear everything but nCRST */
@@ -172,13 +177,13 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
-static ac97_bus_ops_t pxa2xx_ac97_ops = {
+static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
.read = pxa2xx_ac97_read,
.write = pxa2xx_ac97_write,
.reset = pxa2xx_ac97_reset,
};
-static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = {
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = {
.name = "AC97 PCM out",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRTXPCDR,
@@ -186,7 +191,7 @@ static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_out = {
DCMD_BURST32 | DCMD_WIDTH4,
};
-static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = {
+static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = {
.name = "AC97 PCM in",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRRXPCDR,
@@ -194,12 +199,12 @@ static pxa2xx_pcm_dma_params_t pxa2xx_ac97_pcm_in = {
DCMD_BURST32 | DCMD_WIDTH4,
};
-static snd_pcm_t *pxa2xx_ac97_pcm;
-static ac97_t *pxa2xx_ac97_ac97;
+static struct snd_pcm *pxa2xx_ac97_pcm;
+static struct snd_ac97 *pxa2xx_ac97_ac97;
-static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream)
+static int pxa2xx_ac97_pcm_startup(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
pxa2xx_audio_ops_t *platform_ops;
int r;
@@ -218,7 +223,7 @@ static int pxa2xx_ac97_pcm_startup(snd_pcm_substream_t *substream)
return 0;
}
-static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream)
+static void pxa2xx_ac97_pcm_shutdown(struct snd_pcm_substream *substream)
{
pxa2xx_audio_ops_t *platform_ops;
@@ -227,15 +232,15 @@ static void pxa2xx_ac97_pcm_shutdown(snd_pcm_substream_t *substream)
platform_ops->shutdown(substream, platform_ops->priv);
}
-static int pxa2xx_ac97_pcm_prepare(snd_pcm_substream_t *substream)
+static int pxa2xx_ac97_pcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
return snd_ac97_set_rate(pxa2xx_ac97_ac97, reg, runtime->rate);
}
-static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = {
+static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = {
.playback_params = &pxa2xx_ac97_pcm_out,
.capture_params = &pxa2xx_ac97_pcm_in,
.startup = pxa2xx_ac97_pcm_startup,
@@ -245,39 +250,37 @@ static pxa2xx_pcm_client_t pxa2xx_ac97_pcm_client = {
#ifdef CONFIG_PM
-static int pxa2xx_ac97_do_suspend(snd_card_t *card, pm_message_t state)
+static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state)
{
- if (card->power_state != SNDRV_CTL_POWER_D3cold) {
- pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
- snd_pcm_suspend_all(pxa2xx_ac97_pcm);
- snd_ac97_suspend(pxa2xx_ac97_ac97);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
- if (platform_ops && platform_ops->suspend)
- platform_ops->suspend(platform_ops->priv);
- GCR |= GCR_ACLINK_OFF;
- pxa_set_cken(CKEN2_AC97, 0);
- }
+ pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
+ snd_pcm_suspend_all(pxa2xx_ac97_pcm);
+ snd_ac97_suspend(pxa2xx_ac97_ac97);
+ if (platform_ops && platform_ops->suspend)
+ platform_ops->suspend(platform_ops->priv);
+ GCR |= GCR_ACLINK_OFF;
+ pxa_set_cken(CKEN2_AC97, 0);
return 0;
}
-static int pxa2xx_ac97_do_resume(snd_card_t *card)
+static int pxa2xx_ac97_do_resume(struct snd_card *card)
{
- if (card->power_state != SNDRV_CTL_POWER_D0) {
- pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
- pxa_set_cken(CKEN2_AC97, 1);
- if (platform_ops && platform_ops->resume)
- platform_ops->resume(platform_ops->priv);
- snd_ac97_resume(pxa2xx_ac97_ac97);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- }
+ pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data;
+
+ pxa_set_cken(CKEN2_AC97, 1);
+ if (platform_ops && platform_ops->resume)
+ platform_ops->resume(platform_ops->priv);
+ snd_ac97_resume(pxa2xx_ac97_ac97);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state)
{
- snd_card_t *card = platform_get_drvdata(dev);
+ struct snd_card *card = platform_get_drvdata(dev);
int ret = 0;
if (card)
@@ -288,7 +291,7 @@ static int pxa2xx_ac97_suspend(struct platform_device *dev, pm_message_t state)
static int pxa2xx_ac97_resume(struct platform_device *dev)
{
- snd_card_t *card = platform_get_drvdata(dev);
+ struct snd_card *card = platform_get_drvdata(dev);
int ret = 0;
if (card)
@@ -304,9 +307,9 @@ static int pxa2xx_ac97_resume(struct platform_device *dev)
static int pxa2xx_ac97_probe(struct platform_device *dev)
{
- snd_card_t *card;
- ac97_bus_t *ac97_bus;
- ac97_template_t ac97_template;
+ struct snd_card *card;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97_template ac97_template;
int ret;
ret = -ENOMEM;
@@ -349,8 +352,6 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
snprintf(card->longname, sizeof(card->longname),
"%s (%s)", dev->dev.driver->name, card->mixername);
- snd_card_set_pm_callback(card, pxa2xx_ac97_do_suspend,
- pxa2xx_ac97_do_resume, NULL);
ret = snd_card_register(card);
if (ret == 0) {
platform_set_drvdata(dev, card);
@@ -370,7 +371,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
static int pxa2xx_ac97_remove(struct platform_device *dev)
{
- snd_card_t *card = platform_get_drvdata(dev);
+ struct snd_card *card = platform_get_drvdata(dev);
if (card) {
snd_card_free(card);
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index b1eb53b02eae..4938ef10b813 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -28,7 +28,7 @@
#include "pxa2xx-pcm.h"
-static const snd_pcm_hardware_t pxa2xx_pcm_hardware = {
+static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -44,15 +44,15 @@ static const snd_pcm_hardware_t pxa2xx_pcm_hardware = {
struct pxa2xx_runtime_data {
int dma_ch;
- pxa2xx_pcm_dma_params_t *params;
+ struct pxa2xx_pcm_dma_params *params;
pxa_dma_desc *dma_desc_array;
dma_addr_t dma_desc_array_phys;
};
-static int pxa2xx_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
size_t totsize = params_buffer_bytes(params);
size_t period = params_period_bytes(params);
@@ -86,7 +86,7 @@ static int pxa2xx_pcm_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int pxa2xx_pcm_hw_free(snd_pcm_substream_t *substream)
+static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
@@ -95,10 +95,10 @@ static int pxa2xx_pcm_hw_free(snd_pcm_substream_t *substream)
return 0;
}
-static int pxa2xx_pcm_prepare(snd_pcm_substream_t *substream)
+static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
- pxa2xx_pcm_client_t *client = substream->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct pxa2xx_pcm_client *client = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
DCSR(rtd->dma_ch) &= ~DCSR_RUN;
@@ -109,7 +109,7 @@ static int pxa2xx_pcm_prepare(snd_pcm_substream_t *substream)
return client->prepare(substream);
}
-static int pxa2xx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
int ret = 0;
@@ -139,7 +139,7 @@ static int pxa2xx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs)
{
- snd_pcm_substream_t *substream = dev_id;
+ struct snd_pcm_substream *substream = dev_id;
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
int dcsr;
@@ -155,9 +155,9 @@ static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id, struct pt_regs *regs)
}
}
-static snd_pcm_uframes_t pxa2xx_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd = runtime->private_data;
dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch);
@@ -168,9 +168,9 @@ static snd_pcm_uframes_t pxa2xx_pcm_pointer(snd_pcm_substream_t *substream)
}
static int
-pxa2xx_pcm_hw_rule_mult32(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule)
+pxa2xx_pcm_hw_rule_mult32(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *i = hw_param_interval(params, rule->var);
+ struct snd_interval *i = hw_param_interval(params, rule->var);
int changed = 0;
if (i->min & 31) {
@@ -188,10 +188,10 @@ pxa2xx_pcm_hw_rule_mult32(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule)
return changed;
}
-static int pxa2xx_pcm_open(snd_pcm_substream_t *substream)
+static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
- pxa2xx_pcm_client_t *client = substream->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct pxa2xx_pcm_client *client = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct pxa2xx_runtime_data *rtd;
int ret;
@@ -246,9 +246,9 @@ static int pxa2xx_pcm_open(snd_pcm_substream_t *substream)
return ret;
}
-static int pxa2xx_pcm_close(snd_pcm_substream_t *substream)
+static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
{
- pxa2xx_pcm_client_t *client = substream->private_data;
+ struct pxa2xx_pcm_client *client = substream->private_data;
struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
pxa_free_dma(rtd->dma_ch);
@@ -260,16 +260,16 @@ static int pxa2xx_pcm_close(snd_pcm_substream_t *substream)
}
static int
-pxa2xx_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
return dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area,
runtime->dma_addr,
runtime->dma_bytes);
}
-static snd_pcm_ops_t pxa2xx_pcm_ops = {
+static struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -281,9 +281,9 @@ static snd_pcm_ops_t pxa2xx_pcm_ops = {
.mmap = pxa2xx_pcm_mmap,
};
-static int pxa2xx_pcm_preallocate_dma_buffer(snd_pcm_t *pcm, int stream)
+static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
- snd_pcm_substream_t *substream = pcm->streams[stream].substream;
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
@@ -297,9 +297,9 @@ static int pxa2xx_pcm_preallocate_dma_buffer(snd_pcm_t *pcm, int stream)
return 0;
}
-static void pxa2xx_pcm_free_dma_buffers(snd_pcm_t *pcm)
+static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
@@ -318,9 +318,10 @@ static void pxa2xx_pcm_free_dma_buffers(snd_pcm_t *pcm)
static u64 pxa2xx_pcm_dmamask = 0xffffffff;
-int pxa2xx_pcm_new(snd_card_t *card, pxa2xx_pcm_client_t *client, snd_pcm_t **rpcm)
+int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
+ struct snd_pcm **rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int play = client->playback_params ? 1 : 0;
int capt = client->capture_params ? 1 : 0;
int ret;
diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h
index 43517597cab9..b79f1e803780 100644
--- a/sound/arm/pxa2xx-pcm.h
+++ b/sound/arm/pxa2xx-pcm.h
@@ -10,20 +10,20 @@
* published by the Free Software Foundation.
*/
-typedef struct {
+struct pxa2xx_pcm_dma_params {
char *name; /* stream identifier */
u32 dcmd; /* DMA descriptor dcmd field */
volatile u32 *drcmr; /* the DMA request channel to use */
u32 dev_addr; /* device physical address for DMA */
-} pxa2xx_pcm_dma_params_t;
+};
-typedef struct {
- pxa2xx_pcm_dma_params_t *playback_params;
- pxa2xx_pcm_dma_params_t *capture_params;
- int (*startup)(snd_pcm_substream_t *);
- void (*shutdown)(snd_pcm_substream_t *);
- int (*prepare)(snd_pcm_substream_t *);
-} pxa2xx_pcm_client_t;
+struct pxa2xx_pcm_client {
+ struct pxa2xx_pcm_dma_params *playback_params;
+ struct pxa2xx_pcm_dma_params *capture_params;
+ int (*startup)(struct snd_pcm_substream *);
+ void (*shutdown)(struct snd_pcm_substream *);
+ int (*prepare)(struct snd_pcm_substream *);
+};
-extern int pxa2xx_pcm_new(snd_card_t *, pxa2xx_pcm_client_t *, snd_pcm_t **);
+extern int pxa2xx_pcm_new(struct snd_card *, struct pxa2xx_pcm_client *, struct snd_pcm **);
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 6ee912259cc5..13057d92f08a 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.23 2005/09/09 13:22:34 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.27 2005/12/07 09:13:42 cladisch Exp $ */
/***************************************************************************************************
*
@@ -64,6 +64,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/delay.h>
@@ -115,7 +117,7 @@ static char *id = NULL; /* ID for this card */
module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
-typedef struct audio_stream {
+struct audio_stream {
char *id; /* identification string */
int stream_id; /* numeric identification */
dma_device_t dma_dev; /* device identifier for DMA */
@@ -130,18 +132,16 @@ typedef struct audio_stream {
int tx_spin; /* are we recoding - flag used to do DMA trans. for sync */
unsigned int old_offset;
spinlock_t dma_lock; /* for locking in DMA operations (see dma-sa1100.c in the kernel) */
- snd_pcm_substream_t *stream;
-}audio_stream_t;
+ struct snd_pcm_substream *stream;
+};
-typedef struct snd_card_sa11xx_uda1341 {
- snd_card_t *card;
+struct sa11xx_uda1341 {
+ struct snd_card *card;
struct l3_client *uda1341;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
long samplerate;
- audio_stream_t s[2]; /* playback & capture */
-} sa11xx_uda1341_t;
-
-static struct snd_card_sa11xx_uda1341 *sa11xx_uda1341 = NULL;
+ struct audio_stream s[2]; /* playback & capture */
+};
static unsigned int rates[] = {
8000, 10666, 10985, 14647,
@@ -149,12 +149,14 @@ static unsigned int rates[] = {
29400, 32000, 44100, 48000,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
+static struct platform_device *device;
+
/* }}} */
/* {{{ Clock and sample rate stuff */
@@ -195,7 +197,7 @@ static void sa11xx_uda1341_set_audio_clock(long val)
}
}
-static void sa11xx_uda1341_set_samplerate(sa11xx_uda1341_t *sa11xx_uda1341, long rate)
+static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate)
{
int clk_div = 0;
int clk=0;
@@ -280,7 +282,7 @@ static void sa11xx_uda1341_set_samplerate(sa11xx_uda1341_t *sa11xx_uda1341, long
/* {{{ HW init and shutdown */
-static void sa11xx_uda1341_audio_init(sa11xx_uda1341_t *sa11xx_uda1341)
+static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341)
{
unsigned long flags;
@@ -337,7 +339,7 @@ static void sa11xx_uda1341_audio_init(sa11xx_uda1341_t *sa11xx_uda1341)
#endif
}
-static void sa11xx_uda1341_audio_shutdown(sa11xx_uda1341_t *sa11xx_uda1341)
+static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341)
{
/* mute on */
#ifdef CONFIG_H3600_HAL
@@ -378,7 +380,7 @@ static void sa11xx_uda1341_audio_shutdown(sa11xx_uda1341_t *sa11xx_uda1341)
#ifdef HH_VERSION
-static int audio_dma_request(audio_stream_t *s, void (*callback)(void *, int))
+static int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int))
{
int ret;
@@ -391,7 +393,7 @@ static int audio_dma_request(audio_stream_t *s, void (*callback)(void *, int))
return 0;
}
-static inline void audio_dma_free(audio_stream_t *s)
+static inline void audio_dma_free(struct audio_stream *s)
{
sa1100_free_dma(s->dmach);
s->dmach = -1;
@@ -399,7 +401,7 @@ static inline void audio_dma_free(audio_stream_t *s)
#else
-static int audio_dma_request(audio_stream_t *s, void (*callback)(void *))
+static int audio_dma_request(struct audio_stream *s, void (*callback)(void *))
{
int ret;
@@ -409,18 +411,18 @@ static int audio_dma_request(audio_stream_t *s, void (*callback)(void *))
return ret;
}
-static void audio_dma_free(audio_stream_t *s)
+static void audio_dma_free(struct audio_stream *s)
{
- sa1100_free_dma((s)->dma_regs);
- (s)->dma_regs = 0;
+ sa1100_free_dma(s->dma_regs);
+ s->dma_regs = 0;
}
#endif
-static u_int audio_get_dma_pos(audio_stream_t *s)
+static u_int audio_get_dma_pos(struct audio_stream *s)
{
- snd_pcm_substream_t * substream = s->stream;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_substream *substream = s->stream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int offset;
unsigned long flags;
dma_addr_t addr;
@@ -445,7 +447,7 @@ static u_int audio_get_dma_pos(audio_stream_t *s)
/*
* this stops the dma and clears the dma ptrs
*/
-static void audio_stop_dma(audio_stream_t *s)
+static void audio_stop_dma(struct audio_stream *s)
{
unsigned long flags;
@@ -461,10 +463,10 @@ static void audio_stop_dma(audio_stream_t *s)
spin_unlock_irqrestore(&s->dma_lock, flags);
}
-static void audio_process_dma(audio_stream_t *s)
+static void audio_process_dma(struct audio_stream *s)
{
- snd_pcm_substream_t *substream = s->stream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = s->stream;
+ struct snd_pcm_runtime *runtime;
unsigned int dma_size;
unsigned int offset;
int ret;
@@ -527,7 +529,7 @@ static void audio_dma_callback(void *data, int size)
static void audio_dma_callback(void *data)
#endif
{
- audio_stream_t *s = data;
+ struct audio_stream *s = data;
/*
* If we are getting a callback for an active stream then we inform
@@ -549,12 +551,12 @@ static void audio_dma_callback(void *data)
/* {{{ trigger & timer */
-static int snd_sa11xx_uda1341_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_sa11xx_uda1341_trigger(struct snd_pcm_substream *substream, int cmd)
{
- sa11xx_uda1341_t *chip = snd_pcm_substream_chip(substream);
+ struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
int stream_id = substream->pstr->stream;
- audio_stream_t *s = &chip->s[stream_id];
- audio_stream_t *s1 = &chip->s[stream_id ^ 1];
+ struct audio_stream *s = &chip->s[stream_id];
+ struct audio_stream *s1 = &chip->s[stream_id ^ 1];
int err = 0;
/* note local interrupts are already disabled in the midlevel code */
@@ -683,11 +685,11 @@ static int snd_sa11xx_uda1341_trigger(snd_pcm_substream_t * substream, int cmd)
return err;
}
-static int snd_sa11xx_uda1341_prepare(snd_pcm_substream_t * substream)
+static int snd_sa11xx_uda1341_prepare(struct snd_pcm_substream *substream)
{
- sa11xx_uda1341_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- audio_stream_t *s = &chip->s[substream->pstr->stream];
+ struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct audio_stream *s = &chip->s[substream->pstr->stream];
/* set requested samplerate */
sa11xx_uda1341_set_samplerate(chip, runtime->rate);
@@ -701,15 +703,15 @@ static int snd_sa11xx_uda1341_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(struct snd_pcm_substream *substream)
{
- sa11xx_uda1341_t *chip = snd_pcm_substream_chip(substream);
+ struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
}
/* }}} */
-static snd_pcm_hardware_t snd_sa11xx_uda1341_capture =
+static struct snd_pcm_hardware snd_sa11xx_uda1341_capture =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -732,7 +734,7 @@ static snd_pcm_hardware_t snd_sa11xx_uda1341_capture =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_sa11xx_uda1341_playback =
+static struct snd_pcm_hardware snd_sa11xx_uda1341_playback =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -755,10 +757,10 @@ static snd_pcm_hardware_t snd_sa11xx_uda1341_playback =
.fifo_size = 0,
};
-static int snd_card_sa11xx_uda1341_open(snd_pcm_substream_t * substream)
+static int snd_card_sa11xx_uda1341_open(struct snd_pcm_substream *substream)
{
- sa11xx_uda1341_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int stream_id = substream->pstr->stream;
int err;
@@ -776,9 +778,9 @@ static int snd_card_sa11xx_uda1341_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_card_sa11xx_uda1341_close(snd_pcm_substream_t * substream)
+static int snd_card_sa11xx_uda1341_close(struct snd_pcm_substream *substream)
{
- sa11xx_uda1341_t *chip = snd_pcm_substream_chip(substream);
+ struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
chip->s[substream->pstr->stream].stream = NULL;
return 0;
@@ -786,21 +788,21 @@ static int snd_card_sa11xx_uda1341_close(snd_pcm_substream_t * substream)
/* {{{ HW params & free */
-static int snd_sa11xx_uda1341_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_sa11xx_uda1341_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_sa11xx_uda1341_hw_free(snd_pcm_substream_t * substream)
+static int snd_sa11xx_uda1341_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
/* }}} */
-static snd_pcm_ops_t snd_card_sa11xx_uda1341_playback_ops = {
+static struct snd_pcm_ops snd_card_sa11xx_uda1341_playback_ops = {
.open = snd_card_sa11xx_uda1341_open,
.close = snd_card_sa11xx_uda1341_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -811,7 +813,7 @@ static snd_pcm_ops_t snd_card_sa11xx_uda1341_playback_ops = {
.pointer = snd_sa11xx_uda1341_pointer,
};
-static snd_pcm_ops_t snd_card_sa11xx_uda1341_capture_ops = {
+static struct snd_pcm_ops snd_card_sa11xx_uda1341_capture_ops = {
.open = snd_card_sa11xx_uda1341_open,
.close = snd_card_sa11xx_uda1341_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -822,9 +824,9 @@ static snd_pcm_ops_t snd_card_sa11xx_uda1341_capture_ops = {
.pointer = snd_sa11xx_uda1341_pointer,
};
-static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341, int device)
+static int __init snd_card_sa11xx_uda1341_pcm(struct sa11xx_uda1341 *sa11xx_uda1341, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(sa11xx_uda1341->card, "UDA1341 PCM", device, 1, 1, &pcm)) < 0)
@@ -835,8 +837,8 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
* isa works but I'm not sure why (or if) it's the right choice
* this may be too large, trying it for now
*/
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_ISA,
- snd_pcm_dma_flags(0),
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_isa_data(),
64*1024, 64*1024);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_sa11xx_uda1341_playback_ops);
@@ -862,12 +864,15 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
#ifdef CONFIG_PM
-static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
+static int snd_sa11xx_uda1341_suspend(struct platform_device *devptr,
+ pm_message_t state)
{
- sa11xx_uda1341_t *chip = card->pm_private_data;
+ struct snd_card *card = platform_get_drvdata(devptr);
+ struct sa11xx_uda1341 *chip = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
-#ifdef HH_VERSION
+#ifdef HH_VERSION
sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach);
sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach);
#else
@@ -875,12 +880,14 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
#endif
l3_command(chip->uda1341, CMD_SUSPEND, NULL);
sa11xx_uda1341_audio_shutdown(chip);
+
return 0;
}
-static int snd_sa11xx_uda1341_resume(snd_card_t *card)
+static int snd_sa11xx_uda1341_resume(struct platform_device *devptr)
{
- sa11xx_uda1341_t *chip = card->pm_private_data;
+ struct snd_card *card = platform_get_drvdata(devptr);
+ struct sa11xx_uda1341 *chip = card->private_data;
sa11xx_uda1341_audio_init(chip);
l3_command(chip->uda1341, CMD_RESUME, NULL);
@@ -890,67 +897,55 @@ static int snd_sa11xx_uda1341_resume(snd_card_t *card)
#else
//FIXME
#endif
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* COMFIG_PM */
-void snd_sa11xx_uda1341_free(snd_card_t *card)
+void snd_sa11xx_uda1341_free(struct snd_card *card)
{
- sa11xx_uda1341_t *chip = card->private_data;
+ struct sa11xx_uda1341 *chip = card->private_data;
audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
- sa11xx_uda1341 = NULL;
- card->private_data = NULL;
- kfree(chip);
}
-static int __init sa11xx_uda1341_init(void)
+static int __init sa11xx_uda1341_probe(struct platform_device *devptr)
{
int err;
- snd_card_t *card;
-
- if (!machine_is_h3xxx())
- return -ENODEV;
+ struct snd_card *card;
+ struct sa11xx_uda1341 *chip;
/* register the soundcard */
- card = snd_card_new(-1, id, THIS_MODULE, sizeof(sa11xx_uda1341_t));
+ card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341));
if (card == NULL)
return -ENOMEM;
- sa11xx_uda1341 = kzalloc(sizeof(*sa11xx_uda1341), GFP_KERNEL);
- if (sa11xx_uda1341 == NULL)
- return -ENOMEM;
+ chip = card->private_data;
spin_lock_init(&chip->s[0].dma_lock);
spin_lock_init(&chip->s[1].dma_lock);
-
- card->private_data = (void *)sa11xx_uda1341;
- card->private_free = snd_sa11xx_uda1341_free;
- sa11xx_uda1341->card = card;
- sa11xx_uda1341->samplerate = AUDIO_RATE_DEFAULT;
+ card->private_free = snd_sa11xx_uda1341_free;
+ chip->card = card;
+ chip->samplerate = AUDIO_RATE_DEFAULT;
// mixer
- if ((err = snd_chip_uda1341_mixer_new(sa11xx_uda1341->card, &sa11xx_uda1341->uda1341)))
+ if ((err = snd_chip_uda1341_mixer_new(card, &chip->uda1341)))
goto nodev;
// PCM
- if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
+ if ((err = snd_card_sa11xx_uda1341_pcm(chip, 0)) < 0)
goto nodev;
- snd_card_set_generic_pm_callback(card,
- snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume,
- sa11xx_uda1341);
-
strcpy(card->driver, "UDA1341");
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;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) == 0) {
printk( KERN_INFO "iPAQ audio support initialized\n" );
+ platform_set_drvdata(devptr, card);
return 0;
}
@@ -959,9 +954,47 @@ static int __init sa11xx_uda1341_init(void)
return err;
}
+static int __devexit sa11xx_uda1341_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define SA11XX_UDA1341_DRIVER "sa11xx_uda1341"
+
+static struct platform_driver sa11xx_uda1341_driver = {
+ .probe = sa11xx_uda1341_probe,
+ .remove = __devexit_p(sa11xx_uda1341_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_sa11xx_uda1341_suspend,
+ .resume = snd_sa11xx_uda1341_resume,
+#endif
+ .driver = {
+ .name = SA11XX_UDA1341_DRIVER,
+ },
+};
+
+static int __init sa11xx_uda1341_init(void)
+{
+ int err;
+
+ if (!machine_is_h3xxx())
+ return -ENODEV;
+ if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0)
+ return err;
+ device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0);
+ if (IS_ERR(device)) {
+ platform_driver_unregister(&sa11xx_uda1341_driver);
+ return PTR_ERR(device);
+ }
+ return 0;
+}
+
static void __exit sa11xx_uda1341_exit(void)
{
- snd_card_free(sa11xx_uda1341->card);
+ platform_device_unregister(device);
+ platform_driver_unregister(&sa11xx_uda1341_driver);
}
module_init(sa11xx_uda1341_init);
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 82718836f937..f79755f77a81 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -111,6 +111,25 @@ config SND_SEQ_RTCTIMER_DEFAULT
If in doubt, say Y.
+config SND_DYNAMIC_MINORS
+ bool "Dynamic device file minor numbers (EXPERIMENTAL)"
+ depends on SND && EXPERIMENTAL
+ help
+ If you say Y here, the minor numbers of ALSA device files in
+ /dev/snd/ are allocated dynamically. This allows you to have
+ more than 8 sound cards, but requires a dynamic device file
+ system like udev.
+
+ If you are unsure about this, say N here.
+
+config SND_SUPPORT_OLD_API
+ bool "Support old ALSA API"
+ depends on SND
+ default y
+ help
+ Say Y here to support the obsolete ALSA PCM API (ver.0.9.0 rc3
+ or older).
+
config SND_VERBOSE_PRINTK
bool "Verbose printk"
depends on SND
@@ -133,7 +152,3 @@ config SND_DEBUG_DETECT
help
Say Y here to enable extra-verbose log messages printed when
detecting devices.
-
-config SND_GENERIC_DRIVER
- bool
- depends on SND
diff --git a/sound/core/control.c b/sound/core/control.c
index 212c46a94376..abd62f943726 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -34,12 +34,10 @@
/* max number of user-defined controls */
#define MAX_USER_CONTROLS 32
-typedef struct _snd_kctl_ioctl {
+struct snd_kctl_ioctl {
struct list_head list; /* list of all ioctls */
snd_kctl_ioctl_func_t fioctl;
-} snd_kctl_ioctl_t;
-
-#define snd_kctl_ioctl(n) list_entry(n, snd_kctl_ioctl_t, list)
+};
static DECLARE_RWSEM(snd_ioctl_rwsem);
static LIST_HEAD(snd_control_ioctls);
@@ -49,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls);
static int snd_ctl_open(struct inode *inode, struct file *file)
{
- int cardnum = SNDRV_MINOR_CARD(iminor(inode));
unsigned long flags;
- snd_card_t *card;
- snd_ctl_file_t *ctl;
+ struct snd_card *card;
+ struct snd_ctl_file *ctl;
int err;
- card = snd_cards[cardnum];
+ card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
if (!card) {
err = -ENODEV;
goto __error1;
@@ -93,9 +90,9 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
return err;
}
-static void snd_ctl_empty_read_queue(snd_ctl_file_t * ctl)
+static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
{
- snd_kctl_event_t *cread;
+ struct snd_kctl_event *cread;
spin_lock(&ctl->read_lock);
while (!list_empty(&ctl->events)) {
@@ -110,9 +107,9 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
{
unsigned long flags;
struct list_head *list;
- snd_card_t *card;
- snd_ctl_file_t *ctl;
- snd_kcontrol_t *control;
+ struct snd_card *card;
+ struct snd_ctl_file *ctl;
+ struct snd_kcontrol *control;
unsigned int idx;
ctl = file->private_data;
@@ -137,12 +134,13 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
return 0;
}
-void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
+void snd_ctl_notify(struct snd_card *card, unsigned int mask,
+ struct snd_ctl_elem_id *id)
{
unsigned long flags;
struct list_head *flist;
- snd_ctl_file_t *ctl;
- snd_kctl_event_t *ev;
+ struct snd_ctl_file *ctl;
+ struct snd_kctl_event *ev;
snd_assert(card != NULL && id != NULL, return);
read_lock(&card->ctl_files_rwlock);
@@ -183,21 +181,23 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
* @control: the control template
* @access: the default control access
*
- * Allocates a new snd_kcontrol_t instance and copies the given template
+ * Allocates a new struct snd_kcontrol instance and copies the given template
* to the new instance. It does not copy volatile data (access).
*
* Returns the pointer of the new instance, or NULL on failure.
*/
-snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
+struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int access)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
unsigned int idx;
snd_assert(control != NULL, return NULL);
snd_assert(control->count > 0, return NULL);
- kctl = kzalloc(sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
- if (kctl == NULL)
+ kctl = kzalloc(sizeof(*kctl) + sizeof(struct snd_kcontrol_volatile) * control->count, GFP_KERNEL);
+ if (kctl == NULL) {
+ snd_printk(KERN_ERR "Cannot allocate control instance\n");
return NULL;
+ }
*kctl = *control;
for (idx = 0; idx < kctl->count; idx++)
kctl->vd[idx].access = access;
@@ -209,15 +209,16 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
* @ncontrol: the initialization record
* @private_data: the private data to set
*
- * Allocates a new snd_kcontrol_t instance and initialize from the given
+ * Allocates a new struct snd_kcontrol instance and initialize from the given
* template. When the access field of ncontrol is 0, it's assumed as
* READWRITE access. When the count field is 0, it's assumes as one.
*
* Returns the pointer of the newly generated instance, or NULL on failure.
*/
-snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data)
+struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
+ void *private_data)
{
- snd_kcontrol_t kctl;
+ struct snd_kcontrol kctl;
unsigned int access;
snd_assert(ncontrol != NULL, return NULL);
@@ -249,7 +250,7 @@ snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_
* or snd_ctl_new1().
* Don't call this after the control was added to the card.
*/
-void snd_ctl_free_one(snd_kcontrol_t * kcontrol)
+void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
{
if (kcontrol) {
if (kcontrol->private_free)
@@ -258,11 +259,11 @@ void snd_ctl_free_one(snd_kcontrol_t * kcontrol)
}
}
-static unsigned int snd_ctl_hole_check(snd_card_t * card,
+static unsigned int snd_ctl_hole_check(struct snd_card *card,
unsigned int count)
{
struct list_head *list;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
list_for_each(list, &card->controls) {
kctl = snd_kcontrol(list);
@@ -275,7 +276,7 @@ static unsigned int snd_ctl_hole_check(snd_card_t * card,
return card->last_numid;
}
-static int snd_ctl_find_hole(snd_card_t * card, unsigned int count)
+static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
{
unsigned int last_numid, iter = 100000;
@@ -304,12 +305,14 @@ static int snd_ctl_find_hole(snd_card_t * card, unsigned int count)
*
* It frees automatically the control which cannot be added.
*/
-int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol)
+int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
unsigned int idx;
- snd_assert(card != NULL && kcontrol != NULL, return -EINVAL);
+ snd_assert(card != NULL, return -EINVAL);
+ if (! kcontrol)
+ return -EINVAL;
snd_assert(kcontrol->info != NULL, return -EINVAL);
id = kcontrol->id;
down_write(&card->controls_rwsem);
@@ -350,9 +353,9 @@ int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol)
*
* Returns 0 if successful, or a negative error code on failure.
*/
-int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol)
+int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
unsigned int idx;
snd_assert(card != NULL && kcontrol != NULL, return -EINVAL);
@@ -375,9 +378,9 @@ int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol)
*
* Returns 0 if successful, or a negative error code on failure.
*/
-int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id)
+int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
int ret;
down_write(&card->controls_rwsem);
@@ -401,10 +404,11 @@ int snd_ctl_remove_id(snd_card_t * card, snd_ctl_elem_id_t *id)
*
* Returns 0 if successful, or a negative error code on failure.
*/
-static int snd_ctl_remove_unlocked_id(snd_ctl_file_t * file, snd_ctl_elem_id_t *id)
+static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
+ struct snd_ctl_elem_id *id)
{
- snd_card_t *card = file->card;
- snd_kcontrol_t *kctl;
+ struct snd_card *card = file->card;
+ struct snd_kcontrol *kctl;
int idx, ret;
down_write(&card->controls_rwsem);
@@ -434,9 +438,10 @@ static int snd_ctl_remove_unlocked_id(snd_ctl_file_t * file, snd_ctl_elem_id_t *
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem_id_t *dst_id)
+int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id,
+ struct snd_ctl_elem_id *dst_id)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
down_write(&card->controls_rwsem);
kctl = snd_ctl_find_id(card, src_id);
@@ -463,10 +468,10 @@ int snd_ctl_rename_id(snd_card_t * card, snd_ctl_elem_id_t *src_id, snd_ctl_elem
* The caller must down card->controls_rwsem before calling this function
* (if the race condition can happen).
*/
-snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
+struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
{
struct list_head *list;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
snd_assert(card != NULL && numid != 0, return NULL);
list_for_each(list, &card->controls) {
@@ -489,10 +494,11 @@ snd_kcontrol_t *snd_ctl_find_numid(snd_card_t * card, unsigned int numid)
* The caller must down card->controls_rwsem before calling this function
* (if the race condition can happen).
*/
-snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
+struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
+ struct snd_ctl_elem_id *id)
{
struct list_head *list;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
snd_assert(card != NULL && id != NULL, return NULL);
if (id->numid != 0)
@@ -516,10 +522,10 @@ snd_kcontrol_t *snd_ctl_find_id(snd_card_t * card, snd_ctl_elem_id_t *id)
return NULL;
}
-static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
+static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
unsigned int cmd, void __user *arg)
{
- snd_ctl_card_info_t *info;
+ struct snd_ctl_card_info *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (! info)
@@ -533,7 +539,7 @@ static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
strlcpy(info->components, card->components, sizeof(info->components));
up_read(&snd_ioctl_rwsem);
- if (copy_to_user(arg, info, sizeof(snd_ctl_card_info_t))) {
+ if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
kfree(info);
return -EFAULT;
}
@@ -541,12 +547,13 @@ static int snd_ctl_card_info(snd_card_t * card, snd_ctl_file_t * ctl,
return 0;
}
-static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list)
+static int snd_ctl_elem_list(struct snd_card *card,
+ struct snd_ctl_elem_list __user *_list)
{
struct list_head *plist;
- snd_ctl_elem_list_t list;
- snd_kcontrol_t *kctl;
- snd_ctl_elem_id_t *dst, *id;
+ struct snd_ctl_elem_list list;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_id *dst, *id;
unsigned int offset, space, first, jidx;
if (copy_from_user(&list, _list, sizeof(list)))
@@ -559,7 +566,7 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list
return -ENOMEM;
if (space > 0) {
/* allocate temporary buffer for atomic operation */
- dst = vmalloc(space * sizeof(snd_ctl_elem_id_t));
+ dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
if (dst == NULL)
return -ENOMEM;
down_read(&card->controls_rwsem);
@@ -588,7 +595,9 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list
offset = 0;
}
up_read(&card->controls_rwsem);
- if (list.used > 0 && copy_to_user(list.pids, dst, list.used * sizeof(snd_ctl_elem_id_t))) {
+ if (list.used > 0 &&
+ copy_to_user(list.pids, dst,
+ list.used * sizeof(struct snd_ctl_elem_id))) {
vfree(dst);
return -EFAULT;
}
@@ -603,11 +612,12 @@ static int snd_ctl_elem_list(snd_card_t *card, snd_ctl_elem_list_t __user *_list
return 0;
}
-static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info)
+static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
+ struct snd_ctl_elem_info *info)
{
- snd_card_t *card = ctl->card;
- snd_kcontrol_t *kctl;
- snd_kcontrol_volatile_t *vd;
+ struct snd_card *card = ctl->card;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
int result;
@@ -640,9 +650,10 @@ static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info)
return result;
}
-static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info)
+static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
+ struct snd_ctl_elem_info __user *_info)
{
- snd_ctl_elem_info_t info;
+ struct snd_ctl_elem_info info;
int result;
if (copy_from_user(&info, _info, sizeof(info)))
@@ -654,10 +665,10 @@ static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __use
return result;
}
-int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control)
+int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control)
{
- snd_kcontrol_t *kctl;
- snd_kcontrol_volatile_t *vd;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
int result, indirect;
@@ -684,9 +695,10 @@ int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control)
return result;
}
-static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user *_control)
+static int snd_ctl_elem_read_user(struct snd_card *card,
+ struct snd_ctl_elem_value __user *_control)
{
- snd_ctl_elem_value_t *control;
+ struct snd_ctl_elem_value *control;
int result;
control = kmalloc(sizeof(*control), GFP_KERNEL);
@@ -704,10 +716,11 @@ static int snd_ctl_elem_read_user(snd_card_t *card, snd_ctl_elem_value_t __user
return result;
}
-int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control)
+int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
+ struct snd_ctl_elem_value *control)
{
- snd_kcontrol_t *kctl;
- snd_kcontrol_volatile_t *vd;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
unsigned int index_offset;
int result, indirect;
@@ -741,9 +754,10 @@ int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_valu
return result;
}
-static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __user *_control)
+static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
+ struct snd_ctl_elem_value __user *_control)
{
- snd_ctl_elem_value_t *control;
+ struct snd_ctl_elem_value *control;
int result;
control = kmalloc(sizeof(*control), GFP_KERNEL);
@@ -761,12 +775,13 @@ static int snd_ctl_elem_write_user(snd_ctl_file_t *file, snd_ctl_elem_value_t __
return result;
}
-static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
+static int snd_ctl_elem_lock(struct snd_ctl_file *file,
+ struct snd_ctl_elem_id __user *_id)
{
- snd_card_t *card = file->card;
- snd_ctl_elem_id_t id;
- snd_kcontrol_t *kctl;
- snd_kcontrol_volatile_t *vd;
+ struct snd_card *card = file->card;
+ struct snd_ctl_elem_id id;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
int result;
if (copy_from_user(&id, _id, sizeof(id)))
@@ -789,12 +804,13 @@ static int snd_ctl_elem_lock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id
return result;
}
-static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
+static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
+ struct snd_ctl_elem_id __user *_id)
{
- snd_card_t *card = file->card;
- snd_ctl_elem_id_t id;
- snd_kcontrol_t *kctl;
- snd_kcontrol_volatile_t *vd;
+ struct snd_card *card = file->card;
+ struct snd_ctl_elem_id id;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_volatile *vd;
int result;
if (copy_from_user(&id, _id, sizeof(id)))
@@ -820,14 +836,15 @@ static int snd_ctl_elem_unlock(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_
}
struct user_element {
- snd_ctl_elem_info_t info;
+ struct snd_ctl_elem_info info;
void *elem_data; /* element data */
unsigned long elem_data_size; /* size of element data in bytes */
void *priv_data; /* private data (like strings for enumerated type) */
unsigned long priv_data_size; /* size of private data in bytes */
};
-static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
struct user_element *ue = kcontrol->private_data;
@@ -835,7 +852,8 @@ static int snd_ctl_elem_user_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ctl_elem_user_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct user_element *ue = kcontrol->private_data;
@@ -843,7 +861,8 @@ static int snd_ctl_elem_user_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ctl_elem_user_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int change;
struct user_element *ue = kcontrol->private_data;
@@ -854,15 +873,16 @@ static int snd_ctl_elem_user_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static void snd_ctl_elem_user_free(snd_kcontrol_t * kcontrol)
+static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
{
kfree(kcontrol->private_data);
}
-static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace)
+static int snd_ctl_elem_add(struct snd_ctl_file *file,
+ struct snd_ctl_elem_info *info, int replace)
{
- snd_card_t *card = file->card;
- snd_kcontrol_t kctl, *_kctl;
+ struct snd_card *card = file->card;
+ struct snd_kcontrol kctl, *_kctl;
unsigned int access;
long private_size;
struct user_element *ue;
@@ -873,7 +893,8 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int
if (info->count > 1024)
return -EINVAL;
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
- (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE));
+ (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE));
info->id.numid = 0;
memset(&kctl, 0, sizeof(kctl));
down_write(&card->controls_rwsem);
@@ -921,7 +942,7 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int
return -EINVAL;
break;
case SNDRV_CTL_ELEM_TYPE_IEC958:
- private_size = sizeof(struct sndrv_aes_iec958);
+ private_size = sizeof(struct snd_aes_iec958);
if (info->count != 1)
return -EINVAL;
break;
@@ -957,24 +978,26 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int
return 0;
}
-static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
+static int snd_ctl_elem_add_user(struct snd_ctl_file *file,
+ struct snd_ctl_elem_info __user *_info, int replace)
{
- snd_ctl_elem_info_t info;
+ struct snd_ctl_elem_info info;
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
return snd_ctl_elem_add(file, &info, replace);
}
-static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
+static int snd_ctl_elem_remove(struct snd_ctl_file *file,
+ struct snd_ctl_elem_id __user *_id)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
int err;
if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
err = snd_ctl_remove_unlocked_id(file, &id);
if (! err) {
- snd_card_t *card = file->card;
+ struct snd_card *card = file->card;
down_write(&card->controls_rwsem);
card->user_ctl_count--;
up_write(&card->controls_rwsem);
@@ -982,7 +1005,7 @@ static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_
return err;
}
-static int snd_ctl_subscribe_events(snd_ctl_file_t *file, int __user *ptr)
+static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
{
int subscribe;
if (get_user(subscribe, ptr))
@@ -1003,42 +1026,12 @@ static int snd_ctl_subscribe_events(snd_ctl_file_t *file, int __user *ptr)
return 0;
}
-#ifdef CONFIG_PM
-/*
- * change the power state
- */
-static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state)
-{
- switch (power_state) {
- case SNDRV_CTL_POWER_D0:
- if (card->power_state != power_state) {
- card->pm_resume(card);
- snd_power_change_state(card, power_state);
- }
- break;
- case SNDRV_CTL_POWER_D3hot:
- if (card->power_state != power_state) {
- card->pm_suspend(card, PMSG_SUSPEND);
- snd_power_change_state(card, power_state);
- }
- break;
- case SNDRV_CTL_POWER_D1:
- case SNDRV_CTL_POWER_D2:
- case SNDRV_CTL_POWER_D3cold:
- /* not supported yet */
- default:
- return -EINVAL;
- }
- return 0;
-}
-#endif
-
static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_ctl_file_t *ctl;
- snd_card_t *card;
+ struct snd_ctl_file *ctl;
+ struct snd_card *card;
struct list_head *list;
- snd_kctl_ioctl_t *p;
+ struct snd_kctl_ioctl *p;
void __user *argp = (void __user *)arg;
int __user *ip = argp;
int err;
@@ -1072,19 +1065,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
return snd_ctl_subscribe_events(ctl, ip);
case SNDRV_CTL_IOCTL_POWER:
- if (get_user(err, ip))
- return -EFAULT;
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-#ifdef CONFIG_PM
- if (card->pm_suspend && card->pm_resume) {
- snd_power_lock(card);
- err = snd_ctl_set_power_state(card, err);
- snd_power_unlock(card);
- } else
-#endif
- err = -ENOPROTOOPT;
- return err;
+ return -ENOPROTOOPT;
case SNDRV_CTL_IOCTL_POWER_STATE:
#ifdef CONFIG_PM
return put_user(card->power_state, ip) ? -EFAULT : 0;
@@ -1094,7 +1075,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
}
down_read(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_ioctls) {
- p = list_entry(list, snd_kctl_ioctl_t, list);
+ p = list_entry(list, struct snd_kctl_ioctl, list);
err = p->fioctl(card, ctl, cmd, arg);
if (err != -ENOIOCTLCMD) {
up_read(&snd_ioctl_rwsem);
@@ -1106,9 +1087,10 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
return -ENOTTY;
}
-static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
+static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
+ size_t count, loff_t * offset)
{
- snd_ctl_file_t *ctl;
+ struct snd_ctl_file *ctl;
int err = 0;
ssize_t result = 0;
@@ -1116,12 +1098,12 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count
snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO);
if (!ctl->subscribed)
return -EBADFD;
- if (count < sizeof(snd_ctl_event_t))
+ if (count < sizeof(struct snd_ctl_event))
return -EINVAL;
spin_lock_irq(&ctl->read_lock);
- while (count >= sizeof(snd_ctl_event_t)) {
- snd_ctl_event_t ev;
- snd_kctl_event_t *kev;
+ while (count >= sizeof(struct snd_ctl_event)) {
+ struct snd_ctl_event ev;
+ struct snd_kctl_event *kev;
while (list_empty(&ctl->events)) {
wait_queue_t wait;
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
@@ -1145,14 +1127,14 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count
list_del(&kev->list);
spin_unlock_irq(&ctl->read_lock);
kfree(kev);
- if (copy_to_user(buffer, &ev, sizeof(snd_ctl_event_t))) {
+ if (copy_to_user(buffer, &ev, sizeof(struct snd_ctl_event))) {
err = -EFAULT;
goto __end;
}
spin_lock_irq(&ctl->read_lock);
- buffer += sizeof(snd_ctl_event_t);
- count -= sizeof(snd_ctl_event_t);
- result += sizeof(snd_ctl_event_t);
+ buffer += sizeof(struct snd_ctl_event);
+ count -= sizeof(struct snd_ctl_event);
+ result += sizeof(struct snd_ctl_event);
}
__end_lock:
spin_unlock_irq(&ctl->read_lock);
@@ -1163,7 +1145,7 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count
static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
{
unsigned int mask;
- snd_ctl_file_t *ctl;
+ struct snd_ctl_file *ctl;
ctl = file->private_data;
if (!ctl->subscribed)
@@ -1183,9 +1165,9 @@ static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
*/
static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
{
- snd_kctl_ioctl_t *pn;
+ struct snd_kctl_ioctl *pn;
- pn = kzalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+ pn = kzalloc(sizeof(struct snd_kctl_ioctl), GFP_KERNEL);
if (pn == NULL)
return -ENOMEM;
pn->fioctl = fcn;
@@ -1210,15 +1192,16 @@ int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
/*
* de-register the device-specific control-ioctls.
*/
-static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
+static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
+ struct list_head *lists)
{
struct list_head *list;
- snd_kctl_ioctl_t *p;
+ struct snd_kctl_ioctl *p;
snd_assert(fcn != NULL, return -EINVAL);
down_write(&snd_ioctl_rwsem);
list_for_each(list, lists) {
- p = list_entry(list, snd_kctl_ioctl_t, list);
+ p = list_entry(list, struct snd_kctl_ioctl, list);
if (p->fioctl == fcn) {
list_del(&p->list);
up_write(&snd_ioctl_rwsem);
@@ -1246,7 +1229,7 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
static int snd_ctl_fasync(int fd, struct file * file, int on)
{
- snd_ctl_file_t *ctl;
+ struct snd_ctl_file *ctl;
int err;
ctl = file->private_data;
err = fasync_helper(fd, file, on, &ctl->fasync);
@@ -1280,18 +1263,12 @@ static struct file_operations snd_ctl_f_ops =
.fasync = snd_ctl_fasync,
};
-static snd_minor_t snd_ctl_reg =
-{
- .comment = "ctl",
- .f_ops = &snd_ctl_f_ops,
-};
-
/*
* registration of the control device
*/
-static int snd_ctl_dev_register(snd_device_t *device)
+static int snd_ctl_dev_register(struct snd_device *device)
{
- snd_card_t *card = device->device_data;
+ struct snd_card *card = device->device_data;
int err, cardnum;
char name[16];
@@ -1299,8 +1276,8 @@ static int snd_ctl_dev_register(snd_device_t *device)
cardnum = card->number;
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
sprintf(name, "controlC%i", cardnum);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL,
- card, 0, &snd_ctl_reg, name)) < 0)
+ if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
+ &snd_ctl_f_ops, card, name)) < 0)
return err;
return 0;
}
@@ -1308,11 +1285,11 @@ static int snd_ctl_dev_register(snd_device_t *device)
/*
* disconnection of the control device
*/
-static int snd_ctl_dev_disconnect(snd_device_t *device)
+static int snd_ctl_dev_disconnect(struct snd_device *device)
{
- snd_card_t *card = device->device_data;
+ struct snd_card *card = device->device_data;
struct list_head *flist;
- snd_ctl_file_t *ctl;
+ struct snd_ctl_file *ctl;
down_read(&card->controls_rwsem);
list_for_each(flist, &card->ctl_files) {
@@ -1327,10 +1304,10 @@ static int snd_ctl_dev_disconnect(snd_device_t *device)
/*
* free all controls
*/
-static int snd_ctl_dev_free(snd_device_t *device)
+static int snd_ctl_dev_free(struct snd_device *device)
{
- snd_card_t *card = device->device_data;
- snd_kcontrol_t *control;
+ struct snd_card *card = device->device_data;
+ struct snd_kcontrol *control;
down_write(&card->controls_rwsem);
while (!list_empty(&card->controls)) {
@@ -1344,15 +1321,16 @@ static int snd_ctl_dev_free(snd_device_t *device)
/*
* de-registration of the control device
*/
-static int snd_ctl_dev_unregister(snd_device_t *device)
+static int snd_ctl_dev_unregister(struct snd_device *device)
{
- snd_card_t *card = device->device_data;
+ struct snd_card *card = device->device_data;
int err, cardnum;
snd_assert(card != NULL, return -ENXIO);
cardnum = card->number;
snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
- if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, card, 0)) < 0)
+ if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
+ card, -1)) < 0)
return err;
return snd_ctl_dev_free(device);
}
@@ -1361,9 +1339,9 @@ static int snd_ctl_dev_unregister(snd_device_t *device)
* create control core:
* called from init.c
*/
-int snd_ctl_create(snd_card_t *card)
+int snd_ctl_create(struct snd_card *card)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ctl_dev_free,
.dev_register = snd_ctl_dev_register,
.dev_disconnect = snd_ctl_dev_disconnect,
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 207c7de5129c..418c6d4e5daf 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -22,7 +22,7 @@
#include <linux/compat.h>
-struct sndrv_ctl_elem_list32 {
+struct snd_ctl_elem_list32 {
u32 offset;
u32 space;
u32 used;
@@ -31,9 +31,10 @@ struct sndrv_ctl_elem_list32 {
unsigned char reserved[50];
} /* don't set packed attribute here */;
-static int snd_ctl_elem_list_compat(snd_card_t *card, struct sndrv_ctl_elem_list32 __user *data32)
+static int snd_ctl_elem_list_compat(struct snd_card *card,
+ struct snd_ctl_elem_list32 __user *data32)
{
- struct sndrv_ctl_elem_list __user *data;
+ struct snd_ctl_elem_list __user *data;
compat_caddr_t ptr;
int err;
@@ -60,8 +61,8 @@ static int snd_ctl_elem_list_compat(snd_card_t *card, struct sndrv_ctl_elem_list
* it uses union, so the things are not easy..
*/
-struct sndrv_ctl_elem_info32 {
- struct sndrv_ctl_elem_id id; // the size of struct is same
+struct snd_ctl_elem_info32 {
+ struct snd_ctl_elem_id id; // the size of struct is same
s32 type;
u32 access;
u32 count;
@@ -87,9 +88,10 @@ struct sndrv_ctl_elem_info32 {
unsigned char reserved[64];
} __attribute__((packed));
-static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_info32 __user *data32)
+static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl,
+ struct snd_ctl_elem_info32 __user *data32)
{
- struct sndrv_ctl_elem_info *data;
+ struct snd_ctl_elem_info *data;
int err;
data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -146,8 +148,8 @@ static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_i
}
/* read / write */
-struct sndrv_ctl_elem_value32 {
- struct sndrv_ctl_elem_id id;
+struct snd_ctl_elem_value32 {
+ struct snd_ctl_elem_id id;
unsigned int indirect; /* bit-field causes misalignment */
union {
s32 integer[128];
@@ -161,10 +163,11 @@ struct sndrv_ctl_elem_value32 {
/* get the value type and count of the control */
-static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id, int *countp)
+static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
+ int *countp)
{
- snd_kcontrol_t *kctl;
- snd_ctl_elem_info_t info;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_info info;
int err;
down_read(&card->controls_rwsem);
@@ -193,15 +196,15 @@ static int get_elem_size(int type, int count)
case SNDRV_CTL_ELEM_TYPE_BYTES:
return 512;
case SNDRV_CTL_ELEM_TYPE_IEC958:
- return sizeof(struct sndrv_aes_iec958);
+ return sizeof(struct snd_aes_iec958);
default:
return -1;
}
}
-static int copy_ctl_value_from_user(snd_card_t *card,
- struct sndrv_ctl_elem_value *data,
- struct sndrv_ctl_elem_value32 __user *data32,
+static int copy_ctl_value_from_user(struct snd_card *card,
+ struct snd_ctl_elem_value *data,
+ struct snd_ctl_elem_value32 __user *data32,
int *typep, int *countp)
{
int i, type, count, size;
@@ -242,8 +245,8 @@ static int copy_ctl_value_from_user(snd_card_t *card,
}
/* restore the value to 32bit */
-static int copy_ctl_value_to_user(struct sndrv_ctl_elem_value32 __user *data32,
- struct sndrv_ctl_elem_value *data,
+static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
+ struct snd_ctl_elem_value *data,
int type, int count)
{
int i, size;
@@ -265,10 +268,10 @@ static int copy_ctl_value_to_user(struct sndrv_ctl_elem_value32 __user *data32,
return 0;
}
-static int snd_ctl_elem_read_user_compat(snd_card_t *card,
- struct sndrv_ctl_elem_value32 __user *data32)
+static int snd_ctl_elem_read_user_compat(struct snd_card *card,
+ struct snd_ctl_elem_value32 __user *data32)
{
- struct sndrv_ctl_elem_value *data;
+ struct snd_ctl_elem_value *data;
int err, type, count;
data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -285,10 +288,10 @@ static int snd_ctl_elem_read_user_compat(snd_card_t *card,
return err;
}
-static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
- struct sndrv_ctl_elem_value32 __user *data32)
+static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+ struct snd_ctl_elem_value32 __user *data32)
{
- struct sndrv_ctl_elem_value *data;
+ struct snd_ctl_elem_value *data;
int err, type, count;
data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -306,11 +309,11 @@ static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
}
/* add or replace a user control */
-static int snd_ctl_elem_add_compat(snd_ctl_file_t *file,
- struct sndrv_ctl_elem_info32 __user *data32,
+static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
+ struct snd_ctl_elem_info32 __user *data32,
int replace)
{
- struct sndrv_ctl_elem_info *data;
+ struct snd_ctl_elem_info *data;
int err;
data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -355,17 +358,17 @@ static int snd_ctl_elem_add_compat(snd_ctl_file_t *file,
}
enum {
- SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32),
- SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32),
- SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32),
- SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32),
- SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct sndrv_ctl_elem_info32),
- SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct sndrv_ctl_elem_info32),
+ SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct snd_ctl_elem_list32),
+ SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct snd_ctl_elem_info32),
+ SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct snd_ctl_elem_value32),
+ SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
+ SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
+ SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
};
static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_ctl_file_t *ctl;
+ struct snd_ctl_file *ctl;
struct list_head *list;
void __user *argp = compat_ptr(arg);
int err;
@@ -398,7 +401,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
down_read(&snd_ioctl_rwsem);
list_for_each(list, &snd_control_compat_ioctls) {
- snd_kctl_ioctl_t *p = list_entry(list, snd_kctl_ioctl_t, list);
+ struct snd_kctl_ioctl *p = list_entry(list, struct snd_kctl_ioctl, list);
if (p->fioctl) {
err = p->fioctl(ctl->card, ctl, cmd, arg);
if (err != -ENOIOCTLCMD) {
diff --git a/sound/core/device.c b/sound/core/device.c
index 1f509f56e60c..b1cf6ec56784 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -41,17 +41,19 @@
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_device_new(snd_card_t *card, snd_device_type_t type,
- void *device_data, snd_device_ops_t *ops)
+int snd_device_new(struct snd_card *card, snd_device_type_t type,
+ void *device_data, struct snd_device_ops *ops)
{
- snd_device_t *dev;
+ struct snd_device *dev;
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
snd_assert(ops != NULL, return -ENXIO);
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL)
+ if (dev == NULL) {
+ snd_printk(KERN_ERR "Cannot allocate device\n");
return -ENOMEM;
+ }
dev->card = card;
dev->type = type;
dev->state = SNDRV_DEV_BUILD;
@@ -73,10 +75,10 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
* Returns zero if successful, or a negative error code on failure or if the
* device not found.
*/
-int snd_device_free(snd_card_t *card, void *device_data)
+int snd_device_free(struct snd_card *card, void *device_data)
{
struct list_head *list;
- snd_device_t *dev;
+ struct snd_device *dev;
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
@@ -86,7 +88,8 @@ int snd_device_free(snd_card_t *card, void *device_data)
continue;
/* unlink */
list_del(&dev->list);
- if ((dev->state == SNDRV_DEV_REGISTERED || dev->state == SNDRV_DEV_DISCONNECTED) &&
+ if ((dev->state == SNDRV_DEV_REGISTERED ||
+ dev->state == SNDRV_DEV_DISCONNECTED) &&
dev->ops->dev_unregister) {
if (dev->ops->dev_unregister(dev))
snd_printk(KERN_ERR "device unregister failure\n");
@@ -99,7 +102,8 @@ int snd_device_free(snd_card_t *card, void *device_data)
kfree(dev);
return 0;
}
- snd_printd("device free %p (from %p), not found\n", device_data, __builtin_return_address(0));
+ snd_printd("device free %p (from %p), not found\n", device_data,
+ __builtin_return_address(0));
return -ENXIO;
}
@@ -116,10 +120,10 @@ int snd_device_free(snd_card_t *card, void *device_data)
* Returns zero if successful, or a negative error code on failure or if the
* device not found.
*/
-int snd_device_disconnect(snd_card_t *card, void *device_data)
+int snd_device_disconnect(struct snd_card *card, void *device_data)
{
struct list_head *list;
- snd_device_t *dev;
+ struct snd_device *dev;
snd_assert(card != NULL, return -ENXIO);
snd_assert(device_data != NULL, return -ENXIO);
@@ -127,14 +131,16 @@ int snd_device_disconnect(snd_card_t *card, void *device_data)
dev = snd_device(list);
if (dev->device_data != device_data)
continue;
- if (dev->state == SNDRV_DEV_REGISTERED && dev->ops->dev_disconnect) {
+ if (dev->state == SNDRV_DEV_REGISTERED &&
+ dev->ops->dev_disconnect) {
if (dev->ops->dev_disconnect(dev))
snd_printk(KERN_ERR "device disconnect failure\n");
dev->state = SNDRV_DEV_DISCONNECTED;
}
return 0;
}
- snd_printd("device disconnect %p (from %p), not found\n", device_data, __builtin_return_address(0));
+ snd_printd("device disconnect %p (from %p), not found\n", device_data,
+ __builtin_return_address(0));
return -ENXIO;
}
@@ -151,10 +157,10 @@ int snd_device_disconnect(snd_card_t *card, void *device_data)
* Returns zero if successful, or a negative error code on failure or if the
* device not found.
*/
-int snd_device_register(snd_card_t *card, void *device_data)
+int snd_device_register(struct snd_card *card, void *device_data)
{
struct list_head *list;
- snd_device_t *dev;
+ struct snd_device *dev;
int err;
snd_assert(card != NULL, return -ENXIO);
@@ -169,6 +175,7 @@ int snd_device_register(snd_card_t *card, void *device_data)
dev->state = SNDRV_DEV_REGISTERED;
return 0;
}
+ snd_printd("snd_device_register busy\n");
return -EBUSY;
}
snd_BUG();
@@ -179,10 +186,10 @@ int snd_device_register(snd_card_t *card, void *device_data)
* register all the devices on the card.
* called from init.c
*/
-int snd_device_register_all(snd_card_t *card)
+int snd_device_register_all(struct snd_card *card)
{
struct list_head *list;
- snd_device_t *dev;
+ struct snd_device *dev;
int err;
snd_assert(card != NULL, return -ENXIO);
@@ -201,9 +208,9 @@ int snd_device_register_all(snd_card_t *card)
* disconnect all the devices on the card.
* called from init.c
*/
-int snd_device_disconnect_all(snd_card_t *card)
+int snd_device_disconnect_all(struct snd_card *card)
{
- snd_device_t *dev;
+ struct snd_device *dev;
struct list_head *list;
int err = 0;
@@ -220,9 +227,9 @@ int snd_device_disconnect_all(snd_card_t *card)
* release all the devices on the card.
* called from init.c
*/
-int snd_device_free_all(snd_card_t *card, snd_device_cmd_t cmd)
+int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
{
- snd_device_t *dev;
+ struct snd_device *dev;
struct list_head *list;
int err;
unsigned int range_low, range_high;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index e91cee35a4b9..618c43be0bc3 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -35,38 +35,49 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Hardware dependent layer");
MODULE_LICENSE("GPL");
-static snd_hwdep_t *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS];
-
+static LIST_HEAD(snd_hwdep_devices);
static DECLARE_MUTEX(register_mutex);
-static int snd_hwdep_free(snd_hwdep_t *hwdep);
-static int snd_hwdep_dev_free(snd_device_t *device);
-static int snd_hwdep_dev_register(snd_device_t *device);
-static int snd_hwdep_dev_unregister(snd_device_t *device);
+static int snd_hwdep_free(struct snd_hwdep *hwdep);
+static int snd_hwdep_dev_free(struct snd_device *device);
+static int snd_hwdep_dev_register(struct snd_device *device);
+static int snd_hwdep_dev_unregister(struct snd_device *device);
-/*
- */
+static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
+{
+ struct list_head *p;
+ struct snd_hwdep *hwdep;
+
+ list_for_each(p, &snd_hwdep_devices) {
+ hwdep = list_entry(p, struct snd_hwdep, list);
+ if (hwdep->card == card && hwdep->device == device)
+ return hwdep;
+ }
+ return NULL;
+}
static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
if (hw->ops.llseek)
return hw->ops.llseek(hw, file, offset, orig);
return -ENXIO;
}
-static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_hwdep_read(struct file * file, char __user *buf,
+ size_t count, loff_t *offset)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
if (hw->ops.read)
return hw->ops.read(hw, buf, count, offset);
return -ENXIO;
}
-static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
+ size_t count, loff_t *offset)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
if (hw->ops.write)
return hw->ops.write(hw, buf, count, offset);
return -ENXIO;
@@ -75,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, size_
static int snd_hwdep_open(struct inode *inode, struct file * file)
{
int major = imajor(inode);
- int cardnum;
- int device;
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
int err;
wait_queue_t wait;
if (major == snd_major) {
- cardnum = SNDRV_MINOR_CARD(iminor(inode));
- device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP;
+ hw = snd_lookup_minor_data(iminor(inode),
+ SNDRV_DEVICE_TYPE_HWDEP);
#ifdef CONFIG_SND_OSSEMUL
} else if (major == SOUND_MAJOR) {
- cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
- device = 0;
+ hw = snd_lookup_oss_minor_data(iminor(inode),
+ SNDRV_OSS_DEVICE_TYPE_DMFM);
#endif
} else
return -ENXIO;
- cardnum %= SNDRV_CARDS;
- device %= SNDRV_MINOR_HWDEPS;
- hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
if (hw == NULL)
return -ENODEV;
if (!hw->ops.open)
return -ENXIO;
-#ifdef CONFIG_SND_OSSEMUL
- if (major == SOUND_MAJOR && hw->oss_type < 0)
- return -ENXIO;
-#endif
if (!try_module_get(hw->card->module))
return -EFAULT;
@@ -154,7 +156,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
static int snd_hwdep_release(struct inode *inode, struct file * file)
{
int err = -ENXIO;
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
down(&hw->open_mutex);
if (hw->ops.release) {
err = hw->ops.release(hw, file);
@@ -170,15 +172,16 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
if (hw->ops.poll)
return hw->ops.poll(hw, file, wait);
return 0;
}
-static int snd_hwdep_info(snd_hwdep_t *hw, snd_hwdep_info_t __user *_info)
+static int snd_hwdep_info(struct snd_hwdep *hw,
+ struct snd_hwdep_info __user *_info)
{
- snd_hwdep_info_t info;
+ struct snd_hwdep_info info;
memset(&info, 0, sizeof(info));
info.card = hw->card->number;
@@ -190,9 +193,10 @@ static int snd_hwdep_info(snd_hwdep_t *hw, snd_hwdep_info_t __user *_info)
return 0;
}
-static int snd_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t __user *_info)
+static int snd_hwdep_dsp_status(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_status __user *_info)
{
- snd_hwdep_dsp_status_t info;
+ struct snd_hwdep_dsp_status info;
int err;
if (! hw->ops.dsp_status)
@@ -206,9 +210,10 @@ static int snd_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t __user *
return 0;
}
-static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_info)
+static int snd_hwdep_dsp_load(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image __user *_info)
{
- snd_hwdep_dsp_image_t info;
+ struct snd_hwdep_dsp_image info;
int err;
if (! hw->ops.dsp_load)
@@ -228,9 +233,10 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
return 0;
}
-static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
+static long snd_hwdep_ioctl(struct file * file, unsigned int cmd,
+ unsigned long arg)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
void __user *argp = (void __user *)arg;
switch (cmd) {
case SNDRV_HWDEP_IOCTL_PVERSION:
@@ -249,18 +255,16 @@ static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long
static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
if (hw->ops.mmap)
return hw->ops.mmap(hw, file, vma);
return -ENXIO;
}
-static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
+static int snd_hwdep_control_ioctl(struct snd_card *card,
+ struct snd_ctl_file * control,
unsigned int cmd, unsigned long arg)
{
- unsigned int tmp;
-
- tmp = card->number * SNDRV_MINOR_HWDEPS;
switch (cmd) {
case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
{
@@ -268,32 +272,36 @@ static int snd_hwdep_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
if (get_user(device, (int __user *)arg))
return -EFAULT;
+ down(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_MINOR_HWDEPS) {
- if (snd_hwdep_devices[tmp + device])
+ if (snd_hwdep_search(card, device))
break;
device++;
}
if (device >= SNDRV_MINOR_HWDEPS)
device = -1;
+ up(&register_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
}
case SNDRV_CTL_IOCTL_HWDEP_INFO:
{
- snd_hwdep_info_t __user *info = (snd_hwdep_info_t __user *)arg;
- int device;
- snd_hwdep_t *hwdep;
+ struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
+ int device, err;
+ struct snd_hwdep *hwdep;
if (get_user(device, &info->device))
return -EFAULT;
- if (device < 0 || device >= SNDRV_MINOR_HWDEPS)
- return -ENXIO;
- hwdep = snd_hwdep_devices[tmp + device];
- if (hwdep == NULL)
- return -ENXIO;
- return snd_hwdep_info(hwdep, info);
+ down(&register_mutex);
+ hwdep = snd_hwdep_search(card, device);
+ if (hwdep)
+ err = snd_hwdep_info(hwdep, info);
+ else
+ err = -ENXIO;
+ up(&register_mutex);
+ return err;
}
}
return -ENOIOCTLCMD;
@@ -323,12 +331,6 @@ static struct file_operations snd_hwdep_f_ops =
.mmap = snd_hwdep_mmap,
};
-static snd_minor_t snd_hwdep_reg =
-{
- .comment = "hardware dependent",
- .f_ops = &snd_hwdep_f_ops,
-};
-
/**
* snd_hwdep_new - create a new hwdep instance
* @card: the card instance
@@ -342,11 +344,12 @@ static snd_minor_t snd_hwdep_reg =
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep)
+int snd_hwdep_new(struct snd_card *card, char *id, int device,
+ struct snd_hwdep **rhwdep)
{
- snd_hwdep_t *hwdep;
+ struct snd_hwdep *hwdep;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_hwdep_dev_free,
.dev_register = snd_hwdep_dev_register,
.dev_unregister = snd_hwdep_dev_unregister
@@ -356,13 +359,14 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
*rhwdep = NULL;
snd_assert(card != NULL, return -ENXIO);
hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL);
- if (hwdep == NULL)
+ if (hwdep == NULL) {
+ snd_printk(KERN_ERR "hwdep: cannot allocate\n");
return -ENOMEM;
+ }
hwdep->card = card;
hwdep->device = device;
- if (id) {
+ if (id)
strlcpy(hwdep->id, id, sizeof(hwdep->id));
- }
#ifdef CONFIG_SND_OSSEMUL
hwdep->oss_type = -1;
#endif
@@ -376,7 +380,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
return 0;
}
-static int snd_hwdep_free(snd_hwdep_t *hwdep)
+static int snd_hwdep_free(struct snd_hwdep *hwdep)
{
snd_assert(hwdep != NULL, return -ENXIO);
if (hwdep->private_free)
@@ -385,32 +389,31 @@ static int snd_hwdep_free(snd_hwdep_t *hwdep)
return 0;
}
-static int snd_hwdep_dev_free(snd_device_t *device)
+static int snd_hwdep_dev_free(struct snd_device *device)
{
- snd_hwdep_t *hwdep = device->device_data;
+ struct snd_hwdep *hwdep = device->device_data;
return snd_hwdep_free(hwdep);
}
-static int snd_hwdep_dev_register(snd_device_t *device)
+static int snd_hwdep_dev_register(struct snd_device *device)
{
- snd_hwdep_t *hwdep = device->device_data;
- int idx, err;
+ struct snd_hwdep *hwdep = device->device_data;
+ int err;
char name[32];
down(&register_mutex);
- idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
- if (snd_hwdep_devices[idx]) {
+ if (snd_hwdep_search(hwdep->card, hwdep->device)) {
up(&register_mutex);
return -EBUSY;
}
- snd_hwdep_devices[idx] = hwdep;
+ list_add_tail(&hwdep->list, &snd_hwdep_devices);
sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
hwdep->card, hwdep->device,
- &snd_hwdep_reg, name)) < 0) {
+ &snd_hwdep_f_ops, hwdep, name)) < 0) {
snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
hwdep->card->number, hwdep->device);
- snd_hwdep_devices[idx] = NULL;
+ list_del(&hwdep->list);
up(&register_mutex);
return err;
}
@@ -422,7 +425,8 @@ static int snd_hwdep_dev_register(snd_device_t *device)
} else {
if (snd_register_oss_device(hwdep->oss_type,
hwdep->card, hwdep->device,
- &snd_hwdep_reg, hwdep->oss_dev) < 0) {
+ &snd_hwdep_f_ops, hwdep,
+ hwdep->oss_dev) < 0) {
snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
hwdep->card->number, hwdep->device);
} else
@@ -434,15 +438,13 @@ static int snd_hwdep_dev_register(snd_device_t *device)
return 0;
}
-static int snd_hwdep_dev_unregister(snd_device_t *device)
+static int snd_hwdep_dev_unregister(struct snd_device *device)
{
- snd_hwdep_t *hwdep = device->device_data;
- int idx;
+ struct snd_hwdep *hwdep = device->device_data;
snd_assert(hwdep != NULL, return -ENXIO);
down(&register_mutex);
- idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device;
- if (snd_hwdep_devices[idx] != hwdep) {
+ if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
up(&register_mutex);
return -EINVAL;
}
@@ -451,47 +453,39 @@ static int snd_hwdep_dev_unregister(snd_device_t *device)
snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
#endif
snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
- snd_hwdep_devices[idx] = NULL;
+ list_del(&hwdep->list);
up(&register_mutex);
return snd_hwdep_free(hwdep);
}
+#ifdef CONFIG_PROC_FS
/*
* Info interface
*/
-static void snd_hwdep_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_hwdep_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- int idx;
- snd_hwdep_t *hwdep;
+ struct list_head *p;
+ struct snd_hwdep *hwdep;
down(&register_mutex);
- for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) {
- hwdep = snd_hwdep_devices[idx];
- if (hwdep == NULL)
- continue;
+ list_for_each(p, &snd_hwdep_devices) {
+ hwdep = list_entry(p, struct snd_hwdep, list);
snd_iprintf(buffer, "%02i-%02i: %s\n",
- idx / SNDRV_MINOR_HWDEPS,
- idx % SNDRV_MINOR_HWDEPS,
- hwdep->name);
+ hwdep->card->number, hwdep->device, hwdep->name);
}
up(&register_mutex);
}
-/*
- * ENTRY functions
- */
+static struct snd_info_entry *snd_hwdep_proc_entry;
-static snd_info_entry_t *snd_hwdep_proc_entry = NULL;
-
-static int __init alsa_hwdep_init(void)
+static void __init snd_hwdep_proc_init(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
- memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices));
if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
- entry->c.text.read_size = 512;
+ entry->c.text.read_size = PAGE_SIZE;
entry->c.text.read = snd_hwdep_proc_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@@ -499,6 +493,25 @@ static int __init alsa_hwdep_init(void)
}
}
snd_hwdep_proc_entry = entry;
+}
+
+static void __exit snd_hwdep_proc_done(void)
+{
+ snd_info_unregister(snd_hwdep_proc_entry);
+}
+#else /* !CONFIG_PROC_FS */
+#define snd_hwdep_proc_init()
+#define snd_hwdep_proc_done()
+#endif /* CONFIG_PROC_FS */
+
+
+/*
+ * ENTRY functions
+ */
+
+static int __init alsa_hwdep_init(void)
+{
+ snd_hwdep_proc_init();
snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
return 0;
@@ -508,10 +521,7 @@ static void __exit alsa_hwdep_exit(void)
{
snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
- if (snd_hwdep_proc_entry) {
- snd_info_unregister(snd_hwdep_proc_entry);
- snd_hwdep_proc_entry = NULL;
- }
+ snd_hwdep_proc_done();
}
module_init(alsa_hwdep_init)
diff --git a/sound/core/hwdep_compat.c b/sound/core/hwdep_compat.c
index 6866f423d4b9..938f77580966 100644
--- a/sound/core/hwdep_compat.c
+++ b/sound/core/hwdep_compat.c
@@ -22,7 +22,7 @@
#include <linux/compat.h>
-struct sndrv_hwdep_dsp_image32 {
+struct snd_hwdep_dsp_image32 {
u32 index;
unsigned char name[64];
u32 image; /* pointer */
@@ -30,10 +30,10 @@ struct sndrv_hwdep_dsp_image32 {
u32 driver_data;
} /* don't set packed attribute here */;
-static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
- struct sndrv_hwdep_dsp_image32 __user *src)
+static int snd_hwdep_dsp_load_compat(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image32 __user *src)
{
- struct sndrv_hwdep_dsp_image *dst;
+ struct snd_hwdep_dsp_image *dst;
compat_caddr_t ptr;
u32 val;
@@ -56,12 +56,13 @@ static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
}
enum {
- SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
+ SNDRV_HWDEP_IOCTL_DSP_LOAD32 = _IOW('H', 0x03, struct snd_hwdep_dsp_image32)
};
-static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
+static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd,
+ unsigned long arg)
{
- snd_hwdep_t *hw = file->private_data;
+ struct snd_hwdep *hw = file->private_data;
void __user *argp = compat_ptr(arg);
switch (cmd) {
case SNDRV_HWDEP_IOCTL_PVERSION:
diff --git a/sound/core/info.c b/sound/core/info.c
index 39f9b97d9219..ae8853921464 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -37,6 +37,8 @@
*
*/
+#ifdef CONFIG_PROC_FS
+
int snd_info_check_reserved_words(const char *str)
{
static char *reserved[] =
@@ -66,16 +68,14 @@ int snd_info_check_reserved_words(const char *str)
return 1;
}
-#ifdef CONFIG_PROC_FS
-
static DECLARE_MUTEX(info_mutex);
-typedef struct _snd_info_private_data {
- snd_info_buffer_t *rbuffer;
- snd_info_buffer_t *wbuffer;
- snd_info_entry_t *entry;
+struct snd_info_private_data {
+ struct snd_info_buffer *rbuffer;
+ struct snd_info_buffer *wbuffer;
+ struct snd_info_entry *entry;
void *file_private_data;
-} snd_info_private_data_t;
+};
static int snd_info_version_init(void);
static int snd_info_version_done(void);
@@ -90,7 +90,7 @@ static int snd_info_version_done(void);
*
* Returns the size of output string.
*/
-int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...)
+int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...)
{
va_list args;
int len, res;
@@ -115,9 +115,9 @@ int snd_iprintf(snd_info_buffer_t * buffer, char *fmt,...)
*/
static struct proc_dir_entry *snd_proc_root = NULL;
-snd_info_entry_t *snd_seq_root = NULL;
+struct snd_info_entry *snd_seq_root = NULL;
#ifdef CONFIG_SND_OSSEMUL
-snd_info_entry_t *snd_oss_root = NULL;
+struct snd_info_entry *snd_oss_root = NULL;
#endif
static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
@@ -134,7 +134,7 @@ static void snd_remove_proc_entry(struct proc_dir_entry *parent,
static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
{
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
loff_t ret;
@@ -176,9 +176,9 @@ out:
static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
size_t count, loff_t * offset)
{
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
- snd_info_buffer_t *buf;
+ struct snd_info_buffer *buf;
size_t size = 0;
loff_t pos;
@@ -217,9 +217,9 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer,
size_t count, loff_t * offset)
{
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
- snd_info_buffer_t *buf;
+ struct snd_info_buffer *buf;
size_t size = 0;
loff_t pos;
@@ -259,15 +259,15 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
static int snd_info_entry_open(struct inode *inode, struct file *file)
{
- snd_info_entry_t *entry;
- snd_info_private_data_t *data;
- snd_info_buffer_t *buffer;
+ struct snd_info_entry *entry;
+ struct snd_info_private_data *data;
+ struct snd_info_buffer *buffer;
struct proc_dir_entry *p;
int mode, err;
down(&info_mutex);
p = PDE(inode);
- entry = p == NULL ? NULL : (snd_info_entry_t *)p->data;
+ entry = p == NULL ? NULL : (struct snd_info_entry *)p->data;
if (entry == NULL || entry->disconnected) {
up(&info_mutex);
return -ENODEV;
@@ -381,8 +381,8 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
static int snd_info_entry_release(struct inode *inode, struct file *file)
{
- snd_info_entry_t *entry;
- snd_info_private_data_t *data;
+ struct snd_info_entry *entry;
+ struct snd_info_private_data *data;
int mode;
mode = file->f_flags & O_ACCMODE;
@@ -420,7 +420,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
{
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
unsigned int mask;
@@ -447,7 +447,7 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
data = file->private_data;
@@ -479,7 +479,7 @@ static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file->f_dentry->d_inode;
- snd_info_private_data_t *data;
+ struct snd_info_private_data *data;
struct snd_info_entry *entry;
data = file->private_data;
@@ -541,7 +541,7 @@ int __init snd_info_init(void)
snd_proc_root = p;
#ifdef CONFIG_SND_OSSEMUL
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
@@ -554,7 +554,7 @@ int __init snd_info_init(void)
#endif
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
@@ -580,12 +580,10 @@ int __exit snd_info_done(void)
snd_info_version_done();
if (snd_proc_root) {
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
- if (snd_seq_root)
- snd_info_unregister(snd_seq_root);
+ snd_info_unregister(snd_seq_root);
#endif
#ifdef CONFIG_SND_OSSEMUL
- if (snd_oss_root)
- snd_info_unregister(snd_oss_root);
+ snd_info_unregister(snd_oss_root);
#endif
snd_remove_proc_entry(&proc_root, snd_proc_root);
}
@@ -601,10 +599,10 @@ int __exit snd_info_done(void)
* create a card proc file
* called from init.c
*/
-int snd_info_card_create(snd_card_t * card)
+int snd_info_card_create(struct snd_card *card)
{
char str[8];
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
snd_assert(card != NULL, return -ENXIO);
@@ -624,7 +622,7 @@ int snd_info_card_create(snd_card_t * card)
* register the card proc file
* called from init.c
*/
-int snd_info_card_register(snd_card_t * card)
+int snd_info_card_register(struct snd_card *card)
{
struct proc_dir_entry *p;
@@ -644,7 +642,7 @@ int snd_info_card_register(snd_card_t * card)
* de-register the card proc file
* called from init.c
*/
-int snd_info_card_free(snd_card_t * card)
+int snd_info_card_free(struct snd_card *card)
{
snd_assert(card != NULL, return -ENXIO);
if (card->proc_root_link) {
@@ -669,7 +667,7 @@ int snd_info_card_free(snd_card_t * card)
*
* Returns zero if successful, or 1 if error or EOF.
*/
-int snd_info_get_line(snd_info_buffer_t * buffer, char *line, int len)
+int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
{
int c = -1;
@@ -747,9 +745,9 @@ char *snd_info_get_str(char *dest, char *src, int len)
*
* Returns the pointer of the new instance, or NULL on failure.
*/
-static snd_info_entry_t *snd_info_create_entry(const char *name)
+static struct snd_info_entry *snd_info_create_entry(const char *name)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
return NULL;
@@ -774,11 +772,11 @@ static snd_info_entry_t *snd_info_create_entry(const char *name)
*
* Returns the pointer of the new instance, or NULL on failure.
*/
-snd_info_entry_t *snd_info_create_module_entry(struct module * module,
+struct snd_info_entry *snd_info_create_module_entry(struct module * module,
const char *name,
- snd_info_entry_t *parent)
+ struct snd_info_entry *parent)
{
- snd_info_entry_t *entry = snd_info_create_entry(name);
+ struct snd_info_entry *entry = snd_info_create_entry(name);
if (entry) {
entry->module = module;
entry->parent = parent;
@@ -796,11 +794,11 @@ snd_info_entry_t *snd_info_create_module_entry(struct module * module,
*
* Returns the pointer of the new instance, or NULL on failure.
*/
-snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card,
+struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
const char *name,
- snd_info_entry_t * parent)
+ struct snd_info_entry * parent)
{
- snd_info_entry_t *entry = snd_info_create_entry(name);
+ struct snd_info_entry *entry = snd_info_create_entry(name);
if (entry) {
entry->module = card->module;
entry->card = card;
@@ -809,29 +807,29 @@ snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card,
return entry;
}
-static int snd_info_dev_free_entry(snd_device_t *device)
+static int snd_info_dev_free_entry(struct snd_device *device)
{
- snd_info_entry_t *entry = device->device_data;
+ struct snd_info_entry *entry = device->device_data;
snd_info_free_entry(entry);
return 0;
}
-static int snd_info_dev_register_entry(snd_device_t *device)
+static int snd_info_dev_register_entry(struct snd_device *device)
{
- snd_info_entry_t *entry = device->device_data;
+ struct snd_info_entry *entry = device->device_data;
return snd_info_register(entry);
}
-static int snd_info_dev_disconnect_entry(snd_device_t *device)
+static int snd_info_dev_disconnect_entry(struct snd_device *device)
{
- snd_info_entry_t *entry = device->device_data;
+ struct snd_info_entry *entry = device->device_data;
entry->disconnected = 1;
return 0;
}
-static int snd_info_dev_unregister_entry(snd_device_t *device)
+static int snd_info_dev_unregister_entry(struct snd_device *device)
{
- snd_info_entry_t *entry = device->device_data;
+ struct snd_info_entry *entry = device->device_data;
return snd_info_unregister(entry);
}
@@ -855,16 +853,16 @@ static int snd_info_dev_unregister_entry(snd_device_t *device)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_card_proc_new(snd_card_t *card, const char *name,
- snd_info_entry_t **entryp)
+int snd_card_proc_new(struct snd_card *card, const char *name,
+ struct snd_info_entry **entryp)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_info_dev_free_entry,
.dev_register = snd_info_dev_register_entry,
.dev_disconnect = snd_info_dev_disconnect_entry,
.dev_unregister = snd_info_dev_unregister_entry
};
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
int err;
entry = snd_info_create_card_entry(card, name, card->proc_root);
@@ -885,7 +883,7 @@ int snd_card_proc_new(snd_card_t *card, const char *name,
*
* Releases the info entry. Don't call this after registered.
*/
-void snd_info_free_entry(snd_info_entry_t * entry)
+void snd_info_free_entry(struct snd_info_entry * entry)
{
if (entry == NULL)
return;
@@ -903,7 +901,7 @@ void snd_info_free_entry(snd_info_entry_t * entry)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_info_register(snd_info_entry_t * entry)
+int snd_info_register(struct snd_info_entry * entry)
{
struct proc_dir_entry *root, *p = NULL;
@@ -933,11 +931,12 @@ int snd_info_register(snd_info_entry_t * entry)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_info_unregister(snd_info_entry_t * entry)
+int snd_info_unregister(struct snd_info_entry * entry)
{
struct proc_dir_entry *root;
- snd_assert(entry != NULL, return -ENXIO);
+ if (! entry)
+ return 0;
snd_assert(entry->p != NULL, return -ENXIO);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_assert(root, return -ENXIO);
@@ -952,9 +951,9 @@ int snd_info_unregister(snd_info_entry_t * entry)
*/
-static snd_info_entry_t *snd_info_version_entry = NULL;
+static struct snd_info_entry *snd_info_version_entry = NULL;
-static void snd_info_version_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
snd_iprintf(buffer,
"Advanced Linux Sound Architecture Driver Version "
@@ -964,7 +963,7 @@ static void snd_info_version_read(snd_info_entry_t *entry, snd_info_buffer_t * b
static int __init snd_info_version_init(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);
if (entry == NULL)
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index 12107968d402..820f4772e44a 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -37,7 +37,7 @@
static DECLARE_MUTEX(strings);
static char *snd_sndstat_strings[SNDRV_CARDS][SNDRV_OSS_INFO_DEV_COUNT];
-static snd_info_entry_t *snd_sndstat_proc_entry;
+static struct snd_info_entry *snd_sndstat_proc_entry;
int snd_oss_info_register(int dev, int num, char *string)
{
@@ -63,9 +63,9 @@ int snd_oss_info_register(int dev, int num, char *string)
return 0;
}
-extern void snd_card_info_read_oss(snd_info_buffer_t * buffer);
+extern void snd_card_info_read_oss(struct snd_info_buffer *buffer);
-static int snd_sndstat_show_strings(snd_info_buffer_t * buf, char *id, int dev)
+static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
{
int idx, ok = -1;
char *str;
@@ -88,7 +88,8 @@ static int snd_sndstat_show_strings(snd_info_buffer_t * buf, char *id, int dev)
return ok;
}
-static void snd_sndstat_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_sndstat_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA v" CONFIG_SND_VERSION " emulation code)\n");
snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n",
@@ -111,7 +112,7 @@ static void snd_sndstat_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * b
int snd_info_minor_register(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings));
if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) {
diff --git a/sound/core/init.c b/sound/core/init.c
index 33813f92ab52..75816688607c 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -28,7 +28,6 @@
#include <linux/ctype.h>
#include <linux/pci.h>
#include <linux/pm.h>
-#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -40,18 +39,46 @@ struct snd_shutdown_f_ops {
};
unsigned int snd_cards_lock = 0; /* locked for registering/using */
-snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
+struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
DEFINE_RWLOCK(snd_card_rwlock);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag);
+int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
#endif
-static void snd_card_id_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+#ifdef CONFIG_PROC_FS
+static void snd_card_id_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_iprintf(buffer, "%s\n", entry->card->id);
}
+static inline int init_info_for_card(struct snd_card *card)
+{
+ int err;
+ struct snd_info_entry *entry;
+
+ if ((err = snd_info_card_register(card)) < 0) {
+ snd_printd("unable to create card info\n");
+ return err;
+ }
+ if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
+ snd_printd("unable to create card entry\n");
+ return err;
+ }
+ entry->c.text.read_size = PAGE_SIZE;
+ entry->c.text.read = snd_card_id_read;
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ entry = NULL;
+ }
+ card->proc_id = entry;
+ return 0;
+}
+#else /* !CONFIG_PROC_FS */
+#define init_info_for_card(card)
+#endif
+
static void snd_card_free_thread(void * __card);
/**
@@ -63,13 +90,13 @@ static void snd_card_free_thread(void * __card);
*
* Creates and initializes a soundcard structure.
*
- * Returns kmallocated snd_card_t structure. Creates the ALSA control interface
+ * Returns kmallocated snd_card structure. Creates the ALSA control interface
* (which is blocked until snd_card_register function is called).
*/
-snd_card_t *snd_card_new(int idx, const char *xid,
+struct snd_card *snd_card_new(int idx, const char *xid,
struct module *module, int extra_size)
{
- snd_card_t *card;
+ struct snd_card *card;
int err;
if (extra_size < 0)
@@ -132,7 +159,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
goto __error_ctl;
}
if (extra_size > 0)
- card->private_data = (char *)card + sizeof(snd_card_t);
+ card->private_data = (char *)card + sizeof(struct snd_card);
return card;
__error_ctl:
@@ -158,7 +185,7 @@ static unsigned int snd_disconnect_poll(struct file * file, poll_table * wait)
* Note: The current implementation replaces all active file->f_op with special
* dummy file operations (they do nothing except release).
*/
-int snd_card_disconnect(snd_card_t * card)
+int snd_card_disconnect(struct snd_card *card)
{
struct snd_monitor_file *mfile;
struct file *file;
@@ -228,12 +255,6 @@ int snd_card_disconnect(snd_card_t * card)
return 0;
}
-#ifdef CONFIG_SND_GENERIC_DRIVER
-static void snd_generic_device_unregister(snd_card_t *card);
-#else
-#define snd_generic_device_unregister(x) /*NOP*/
-#endif
-
/**
* snd_card_free - frees given soundcard structure
* @card: soundcard structure
@@ -245,7 +266,7 @@ static void snd_generic_device_unregister(snd_card_t *card);
* Returns zero. Frees all associated devices and frees the control
* interface associated to given soundcard.
*/
-int snd_card_free(snd_card_t * card)
+int snd_card_free(struct snd_card *card)
{
struct snd_shutdown_f_ops *s_f_ops;
@@ -279,13 +300,11 @@ int snd_card_free(snd_card_t * card)
}
if (card->private_free)
card->private_free(card);
- if (card->proc_id)
- snd_info_unregister(card->proc_id);
+ snd_info_unregister(card->proc_id);
if (snd_info_card_free(card) < 0) {
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;
@@ -300,7 +319,7 @@ int snd_card_free(snd_card_t * card)
static void snd_card_free_thread(void * __card)
{
- snd_card_t *card = __card;
+ struct snd_card *card = __card;
struct module * module = card->module;
if (!try_module_get(module)) {
@@ -327,7 +346,7 @@ static void snd_card_free_thread(void * __card)
*
* Returns - zero otherwise a negative error code if the start of thread failed.
*/
-int snd_card_free_in_thread(snd_card_t * card)
+int snd_card_free_in_thread(struct snd_card *card)
{
if (card->files == NULL) {
snd_card_free(card);
@@ -343,9 +362,9 @@ int snd_card_free_in_thread(snd_card_t * card)
return -EFAULT;
}
-static void choose_default_id(snd_card_t * card)
+static void choose_default_id(struct snd_card *card)
{
- int i, len, idx_flag = 0, loops = 8;
+ int i, len, idx_flag = 0, loops = SNDRV_CARDS;
char *id, *spos;
id = spos = card->shortname;
@@ -387,9 +406,12 @@ static void choose_default_id(snd_card_t * card)
__change:
len = strlen(id);
- if (idx_flag)
- id[len-1]++;
- else if ((size_t)len <= sizeof(card->id) - 3) {
+ if (idx_flag) {
+ if (id[len-1] != '9')
+ id[len-1]++;
+ else
+ id[len-1] = 'A';
+ } else if ((size_t)len <= sizeof(card->id) - 3) {
strcat(id, "_1");
idx_flag++;
} else {
@@ -415,10 +437,9 @@ static void choose_default_id(snd_card_t * card)
*
* Returns zero otherwise a negative error code if the registrain failed.
*/
-int snd_card_register(snd_card_t * card)
+int snd_card_register(struct snd_card *card)
{
int err;
- snd_info_entry_t *entry;
snd_assert(card != NULL, return -EINVAL);
if ((err = snd_device_register_all(card)) < 0)
@@ -433,22 +454,7 @@ int snd_card_register(snd_card_t * card)
choose_default_id(card);
snd_cards[card->number] = card;
write_unlock(&snd_card_rwlock);
- if ((err = snd_info_card_register(card)) < 0) {
- snd_printd("unable to create card info\n");
- goto __skip_info;
- }
- if ((entry = snd_info_create_card_entry(card, "id", card->proc_root)) == NULL) {
- snd_printd("unable to create card entry\n");
- goto __skip_info;
- }
- entry->c.text.read_size = PAGE_SIZE;
- entry->c.text.read = snd_card_id_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- card->proc_id = entry;
- __skip_info:
+ init_info_for_card(card);
#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
@@ -456,23 +462,25 @@ int snd_card_register(snd_card_t * card)
return 0;
}
-static snd_info_entry_t *snd_card_info_entry = NULL;
+#ifdef CONFIG_PROC_FS
+static struct snd_info_entry *snd_card_info_entry = NULL;
-static void snd_card_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_card_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
int idx, count;
- snd_card_t *card;
+ struct snd_card *card;
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
read_lock(&snd_card_rwlock);
if ((card = snd_cards[idx]) != NULL) {
count++;
- snd_iprintf(buffer, "%i [%-15s]: %s - %s\n",
+ snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
idx,
card->id,
card->driver,
card->shortname);
- snd_iprintf(buffer, " %s\n",
+ snd_iprintf(buffer, " %s\n",
card->longname);
}
read_unlock(&snd_card_rwlock);
@@ -481,12 +489,12 @@ static void snd_card_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
snd_iprintf(buffer, "--- no soundcards ---\n");
}
-#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
+#ifdef CONFIG_SND_OSSEMUL
-void snd_card_info_read_oss(snd_info_buffer_t * buffer)
+void snd_card_info_read_oss(struct snd_info_buffer *buffer)
{
int idx, count;
- snd_card_t *card;
+ struct snd_card *card;
for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
read_lock(&snd_card_rwlock);
@@ -504,16 +512,18 @@ void snd_card_info_read_oss(snd_info_buffer_t * buffer)
#endif
#ifdef MODULE
-static snd_info_entry_t *snd_card_module_info_entry;
-static void snd_card_module_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static struct snd_info_entry *snd_card_module_info_entry;
+static void snd_card_module_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
int idx;
- snd_card_t *card;
+ struct snd_card *card;
for (idx = 0; idx < SNDRV_CARDS; idx++) {
read_lock(&snd_card_rwlock);
if ((card = snd_cards[idx]) != NULL)
- snd_iprintf(buffer, "%i %s\n", idx, card->module->name);
+ snd_iprintf(buffer, "%2i %s\n",
+ idx, card->module->name);
read_unlock(&snd_card_rwlock);
}
}
@@ -521,7 +531,7 @@ static void snd_card_module_info_read(snd_info_entry_t *entry, snd_info_buffer_t
int __init snd_card_info_init(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
if (! entry)
@@ -551,15 +561,15 @@ int __init snd_card_info_init(void)
int __exit snd_card_info_done(void)
{
- if (snd_card_info_entry)
- snd_info_unregister(snd_card_info_entry);
+ snd_info_unregister(snd_card_info_entry);
#ifdef MODULE
- if (snd_card_module_info_entry)
- snd_info_unregister(snd_card_module_info_entry);
+ snd_info_unregister(snd_card_module_info_entry);
#endif
return 0;
}
+#endif /* CONFIG_PROC_FS */
+
/**
* snd_component_add - add a component string
* @card: soundcard structure
@@ -571,7 +581,7 @@ int __exit snd_card_info_done(void)
* Returns zero otherwise a negative error code.
*/
-int snd_component_add(snd_card_t *card, const char *component)
+int snd_component_add(struct snd_card *card, const char *component)
{
char *ptr;
int len = strlen(component);
@@ -602,7 +612,7 @@ int snd_component_add(snd_card_t *card, const char *component)
*
* Returns zero or a negative error code.
*/
-int snd_card_file_add(snd_card_t *card, struct file *file)
+int snd_card_file_add(struct snd_card *card, struct file *file)
{
struct snd_monitor_file *mfile;
@@ -636,7 +646,7 @@ int snd_card_file_add(snd_card_t *card, struct file *file)
*
* Returns zero or a negative error code.
*/
-int snd_card_file_remove(snd_card_t *card, struct file *file)
+int snd_card_file_remove(struct snd_card *card, struct file *file)
{
struct snd_monitor_file *mfile, *pfile = NULL;
@@ -664,97 +674,6 @@ 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(dev, struct snd_generic_device, pdev)->card
-
-#define SND_GENERIC_NAME "snd_generic"
-
-#ifdef CONFIG_PM
-static int snd_generic_suspend(struct platform_device *dev, pm_message_t state);
-static int snd_generic_resume(struct platform_device *dev);
-#endif
-
-/* initialized in sound.c */
-struct platform_driver snd_generic_driver = {
-#ifdef CONFIG_PM
- .suspend = snd_generic_suspend,
- .resume = snd_generic_resume,
-#endif
- .driver = {
- .name = SND_GENERIC_NAME,
- },
-};
-
-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.
@@ -766,7 +685,7 @@ int snd_card_set_generic_dev(snd_card_t *card)
*
* Note: the power lock must be active before call.
*/
-int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file)
+int snd_power_wait(struct snd_card *card, unsigned int power_state, struct file *file)
{
wait_queue_t wait;
int result = 0;
@@ -798,107 +717,4 @@ int snd_power_wait(snd_card_t *card, unsigned int power_state, struct file *file
return result;
}
-/**
- * snd_card_set_pm_callback - set the PCI power-management callbacks
- * @card: soundcard structure
- * @suspend: suspend callback function
- * @resume: resume callback function
- * @private_data: private data to pass to the callback functions
- *
- * Sets the power-management callback functions of the card.
- * These callbacks are called from ALSA's common PCI suspend/resume
- * handler and from the control API.
- */
-int snd_card_set_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, pm_message_t),
- int (*resume)(snd_card_t *),
- void *private_data)
-{
- card->pm_suspend = suspend;
- card->pm_resume = resume;
- card->pm_private_data = private_data;
- return 0;
-}
-
-#ifdef CONFIG_SND_GENERIC_DRIVER
-/* suspend/resume callbacks for snd_generic platform device */
-static int snd_generic_suspend(struct platform_device *dev, pm_message_t state)
-{
- snd_card_t *card;
-
- card = get_snd_generic_card(dev);
- if (card->power_state == SNDRV_CTL_POWER_D3hot)
- return 0;
- if (card->pm_suspend)
- card->pm_suspend(card, PMSG_SUSPEND);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- return 0;
-}
-
-static int snd_generic_resume(struct platform_device *dev)
-{
- snd_card_t *card;
-
- card = get_snd_generic_card(dev);
- if (card->power_state == SNDRV_CTL_POWER_D0)
- return 0;
- if (card->pm_resume)
- card->pm_resume(card);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- return 0;
-}
-
-/**
- * snd_card_set_generic_pm_callback - set the generic power-management callbacks
- * @card: soundcard structure
- * @suspend: suspend callback function
- * @resume: resume callback function
- * @private_data: private data to pass to the callback functions
- *
- * Registers the power-management and sets the lowlevel callbacks for
- * the given card. These callbacks are called from the ALSA's common
- * PM handler and from the control API.
- */
-int snd_card_set_generic_pm_callback(snd_card_t *card,
- int (*suspend)(snd_card_t *, pm_message_t),
- int (*resume)(snd_card_t *),
- void *private_data)
-{
- 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_DRIVER */
-
-#ifdef CONFIG_PCI
-int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
-{
- snd_card_t *card = pci_get_drvdata(dev);
- int err;
- if (! card || ! card->pm_suspend)
- return 0;
- if (card->power_state == SNDRV_CTL_POWER_D3hot)
- return 0;
- err = card->pm_suspend(card, PMSG_SUSPEND);
- pci_save_state(dev);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- return err;
-}
-
-int snd_card_pci_resume(struct pci_dev *dev)
-{
- snd_card_t *card = pci_get_drvdata(dev);
- if (! card || ! card->pm_resume)
- return 0;
- if (card->power_state == SNDRV_CTL_POWER_D0)
- return 0;
- /* restore the PCI config space */
- pci_restore_state(dev);
- card->pm_resume(card);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- return 0;
-}
-#endif
-
#endif /* CONFIG_PM */
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index e4b8959dd4bb..19b3dcbb09c2 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -43,10 +43,6 @@ MODULE_DESCRIPTION("Memory allocator for ALSA system.");
MODULE_LICENSE("GPL");
-#ifndef SNDRV_CARDS
-#define SNDRV_CARDS 8
-#endif
-
/*
*/
diff --git a/sound/core/oss/copy.c b/sound/core/oss/copy.c
index edecbe7417bd..d6a04c2d5a75 100644
--- a/sound/core/oss/copy.c
+++ b/sound/core/oss/copy.c
@@ -25,9 +25,9 @@
#include <sound/pcm.h>
#include "pcm_plugin.h"
-static snd_pcm_sframes_t copy_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t copy_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
unsigned int channel;
@@ -58,13 +58,13 @@ static snd_pcm_sframes_t copy_transfer(snd_pcm_plugin_t *plugin,
return frames;
}
-int snd_pcm_plugin_build_copy(snd_pcm_plug_t *plug,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_copy(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin)
{
int err;
- snd_pcm_plugin_t *plugin;
+ struct snd_pcm_plugin *plugin;
int width;
snd_assert(r_plugin != NULL, return -ENXIO);
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index bb1c99a5b734..322702e05f3e 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -35,9 +35,9 @@
* Basic io plugin
*/
-static snd_pcm_sframes_t io_playback_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels ATTRIBUTE_UNUSED,
+static snd_pcm_sframes_t io_playback_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
snd_assert(plugin != NULL, return -ENXIO);
@@ -58,9 +58,9 @@ static snd_pcm_sframes_t io_playback_transfer(snd_pcm_plugin_t *plugin,
}
}
-static snd_pcm_sframes_t io_capture_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels ATTRIBUTE_UNUSED,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t io_capture_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
snd_assert(plugin != NULL, return -ENXIO);
@@ -82,13 +82,13 @@ static snd_pcm_sframes_t io_capture_transfer(snd_pcm_plugin_t *plugin,
return 0;
}
-static snd_pcm_sframes_t io_src_channels(snd_pcm_plugin_t *plugin,
+static snd_pcm_sframes_t io_src_channels(struct snd_pcm_plugin *plugin,
snd_pcm_uframes_t frames,
- snd_pcm_plugin_channel_t **channels)
+ struct snd_pcm_plugin_channel **channels)
{
int err;
unsigned int channel;
- snd_pcm_plugin_channel_t *v;
+ struct snd_pcm_plugin_channel *v;
err = snd_pcm_plugin_client_channels(plugin, frames, &v);
if (err < 0)
return err;
@@ -100,13 +100,13 @@ static snd_pcm_sframes_t io_src_channels(snd_pcm_plugin_t *plugin,
return frames;
}
-int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug,
- snd_pcm_hw_params_t *params,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_io(struct snd_pcm_substream *plug,
+ struct snd_pcm_hw_params *params,
+ struct snd_pcm_plugin **r_plugin)
{
int err;
- snd_pcm_plugin_format_t format;
- snd_pcm_plugin_t *plugin;
+ struct snd_pcm_plugin_format format;
+ struct snd_pcm_plugin *plugin;
snd_assert(r_plugin != NULL, return -ENXIO);
*r_plugin = NULL;
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 12ed27a57b27..8cbfa415ce40 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -30,19 +30,19 @@
* Basic linear conversion plugin
*/
-typedef struct linear_private_data {
+struct linear_priv {
int conv;
-} linear_t;
+};
-static void convert(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static void convert(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
#define CONV_LABELS
#include "plugin_ops.h"
#undef CONV_LABELS
- linear_t *data = (linear_t *)plugin->extra_data;
+ struct linear_priv *data = (struct linear_priv *)plugin->extra_data;
void *conv = conv_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
@@ -75,15 +75,15 @@ static void convert(snd_pcm_plugin_t *plugin,
}
}
-static snd_pcm_sframes_t linear_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- linear_t *data;
+ struct linear_priv *data;
snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
- data = (linear_t *)plugin->extra_data;
+ data = (struct linear_priv *)plugin->extra_data;
if (frames == 0)
return 0;
#ifdef CONFIG_SND_DEBUG
@@ -128,14 +128,14 @@ int conv_index(int src_format, int dst_format)
return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian;
}
-int snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_linear(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin)
{
int err;
- struct linear_private_data *data;
- snd_pcm_plugin_t *plugin;
+ struct linear_priv *data;
+ struct snd_pcm_plugin *plugin;
snd_assert(r_plugin != NULL, return -ENXIO);
*r_plugin = NULL;
@@ -147,10 +147,10 @@ int snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug,
err = snd_pcm_plugin_build(plug, "linear format conversion",
src_format, dst_format,
- sizeof(linear_t), &plugin);
+ sizeof(struct linear_priv), &plugin);
if (err < 0)
return err;
- data = (linear_t *)plugin->extra_data;
+ data = (struct linear_priv *)plugin->extra_data;
data->conv = conv_index(src_format->format, dst_format->format);
plugin->transfer = linear_transfer;
*r_plugin = plugin;
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 214933cf5d49..f08e65a2bffe 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
static int snd_mixer_oss_open(struct inode *inode, struct file *file)
{
- int cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
- snd_card_t *card;
- snd_mixer_oss_file_t *fmixer;
+ struct snd_card *card;
+ struct snd_mixer_oss_file *fmixer;
int err;
- if ((card = snd_cards[cardnum]) == NULL)
+ card = snd_lookup_oss_minor_data(iminor(inode),
+ SNDRV_OSS_DEVICE_TYPE_MIXER);
+ if (card == NULL)
return -ENODEV;
if (card->mixer_oss == NULL)
return -ENODEV;
@@ -71,10 +72,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
static int snd_mixer_oss_release(struct inode *inode, struct file *file)
{
- snd_mixer_oss_file_t *fmixer;
+ struct snd_mixer_oss_file *fmixer;
if (file->private_data) {
- fmixer = (snd_mixer_oss_file_t *) file->private_data;
+ fmixer = (struct snd_mixer_oss_file *) file->private_data;
module_put(fmixer->card->module);
snd_card_file_remove(fmixer->card, file);
kfree(fmixer);
@@ -82,11 +83,11 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
return 0;
}
-static int snd_mixer_oss_info(snd_mixer_oss_file_t *fmixer,
+static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer,
mixer_info __user *_info)
{
- snd_card_t *card = fmixer->card;
- snd_mixer_oss_t *mixer = fmixer->mixer;
+ struct snd_card *card = fmixer->card;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
struct mixer_info info;
memset(&info, 0, sizeof(info));
@@ -98,11 +99,11 @@ static int snd_mixer_oss_info(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_info_obsolete(snd_mixer_oss_file_t *fmixer,
+static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer,
_old_mixer_info __user *_info)
{
- snd_card_t *card = fmixer->card;
- snd_mixer_oss_t *mixer = fmixer->mixer;
+ struct snd_card *card = fmixer->card;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
_old_mixer_info info;
memset(&info, 0, sizeof(info));
@@ -113,9 +114,9 @@ static int snd_mixer_oss_info_obsolete(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_caps(snd_mixer_oss_file_t *fmixer)
+static int snd_mixer_oss_caps(struct snd_mixer_oss_file *fmixer)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
int result = 0;
if (mixer == NULL)
@@ -125,10 +126,10 @@ static int snd_mixer_oss_caps(snd_mixer_oss_file_t *fmixer)
return result;
}
-static int snd_mixer_oss_devmask(snd_mixer_oss_file_t *fmixer)
+static int snd_mixer_oss_devmask(struct snd_mixer_oss_file *fmixer)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_mixer_oss_slot *pslot;
int result = 0, chn;
if (mixer == NULL)
@@ -141,10 +142,10 @@ static int snd_mixer_oss_devmask(snd_mixer_oss_file_t *fmixer)
return result;
}
-static int snd_mixer_oss_stereodevs(snd_mixer_oss_file_t *fmixer)
+static int snd_mixer_oss_stereodevs(struct snd_mixer_oss_file *fmixer)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_mixer_oss_slot *pslot;
int result = 0, chn;
if (mixer == NULL)
@@ -157,9 +158,9 @@ static int snd_mixer_oss_stereodevs(snd_mixer_oss_file_t *fmixer)
return result;
}
-static int snd_mixer_oss_recmask(snd_mixer_oss_file_t *fmixer)
+static int snd_mixer_oss_recmask(struct snd_mixer_oss_file *fmixer)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
int result = 0;
if (mixer == NULL)
@@ -167,7 +168,7 @@ static int snd_mixer_oss_recmask(snd_mixer_oss_file_t *fmixer)
if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */
result = mixer->mask_recsrc;
} else {
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss_slot *pslot;
int chn;
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
@@ -178,9 +179,9 @@ static int snd_mixer_oss_recmask(snd_mixer_oss_file_t *fmixer)
return result;
}
-static int snd_mixer_oss_get_recsrc(snd_mixer_oss_file_t *fmixer)
+static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
int result = 0;
if (mixer == NULL)
@@ -191,7 +192,7 @@ static int snd_mixer_oss_get_recsrc(snd_mixer_oss_file_t *fmixer)
return err;
result = 1 << result;
} else {
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss_slot *pslot;
int chn;
for (chn = 0; chn < 31; chn++) {
pslot = &mixer->slots[chn];
@@ -206,10 +207,10 @@ static int snd_mixer_oss_get_recsrc(snd_mixer_oss_file_t *fmixer)
return mixer->oss_recsrc = result;
}
-static int snd_mixer_oss_set_recsrc(snd_mixer_oss_file_t *fmixer, int recsrc)
+static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsrc)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_mixer_oss_slot *pslot;
int chn, active;
int result = 0;
@@ -243,10 +244,10 @@ static int snd_mixer_oss_set_recsrc(snd_mixer_oss_file_t *fmixer, int recsrc)
return result;
}
-static int snd_mixer_oss_get_volume(snd_mixer_oss_file_t *fmixer, int slot)
+static int snd_mixer_oss_get_volume(struct snd_mixer_oss_file *fmixer, int slot)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_mixer_oss_slot *pslot;
int result = 0, left, right;
if (mixer == NULL || slot > 30)
@@ -268,11 +269,11 @@ static int snd_mixer_oss_get_volume(snd_mixer_oss_file_t *fmixer, int slot)
return result;
}
-static int snd_mixer_oss_set_volume(snd_mixer_oss_file_t *fmixer,
+static int snd_mixer_oss_set_volume(struct snd_mixer_oss_file *fmixer,
int slot, int volume)
{
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_mixer_oss_slot *pslot;
int result = 0, left = volume & 0xff, right = (volume >> 8) & 0xff;
if (mixer == NULL || slot > 30)
@@ -293,7 +294,7 @@ static int snd_mixer_oss_set_volume(snd_mixer_oss_file_t *fmixer,
return (left & 0xff) | ((right & 0xff) << 8);
}
-static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd, unsigned long arg)
+static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
@@ -362,12 +363,12 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+ return snd_mixer_oss_ioctl1((struct snd_mixer_oss_file *) file->private_data, cmd, arg);
}
-int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
+int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg)
{
- snd_mixer_oss_file_t fmixer;
+ struct snd_mixer_oss_file fmixer;
snd_assert(card != NULL, return -ENXIO);
if (card->mixer_oss == NULL)
@@ -398,12 +399,6 @@ static struct file_operations snd_mixer_oss_f_ops =
.compat_ioctl = snd_mixer_oss_ioctl_compat,
};
-static snd_minor_t snd_mixer_oss_reg =
-{
- .comment = "mixer",
- .f_ops = &snd_mixer_oss_f_ops,
-};
-
/*
* utilities
*/
@@ -432,16 +427,16 @@ static long snd_mixer_oss_conv2(long val, long min, long max)
}
#if 0
-static void snd_mixer_oss_recsrce_set(snd_card_t *card, int slot)
+static void snd_mixer_oss_recsrce_set(struct snd_card *card, int slot)
{
- snd_mixer_oss_t *mixer = card->mixer_oss;
+ struct snd_mixer_oss *mixer = card->mixer_oss;
if (mixer)
mixer->mask_recsrc |= 1 << slot;
}
-static int snd_mixer_oss_recsrce_get(snd_card_t *card, int slot)
+static int snd_mixer_oss_recsrce_get(struct snd_card *card, int slot)
{
- snd_mixer_oss_t *mixer = card->mixer_oss;
+ struct snd_mixer_oss *mixer = card->mixer_oss;
if (mixer && (mixer->mask_recsrc & (1 << slot)))
return 1;
return 0;
@@ -488,10 +483,10 @@ struct slot {
#define ID_UNKNOWN ((unsigned int)-1)
-static snd_kcontrol_t *snd_mixer_oss_test_id(snd_mixer_oss_t *mixer, const char *name, int index)
+static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, const char *name, int index)
{
- snd_card_t * card = mixer->card;
- snd_ctl_elem_id_t id;
+ struct snd_card *card = mixer->card;
+ struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -500,15 +495,15 @@ static snd_kcontrol_t *snd_mixer_oss_test_id(snd_mixer_oss_t *mixer, const char
return snd_ctl_find_id(card, &id);
}
-static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
unsigned int numid,
int *left, int *right)
{
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
- snd_kcontrol_t *kctl;
- snd_card_t *card = fmixer->card;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
@@ -537,16 +532,16 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
kfree(uinfo);
}
-static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
unsigned int numid,
int *left, int *right,
int route)
{
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
- snd_kcontrol_t *kctl;
- snd_card_t *card = fmixer->card;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = fmixer->card;
if (numid == ID_UNKNOWN)
return;
@@ -576,8 +571,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
kfree(uinfo);
}
-static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int *left, int *right)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -602,15 +597,15 @@ static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
unsigned int numid,
int left, int right)
{
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
- snd_kcontrol_t *kctl;
- snd_card_t *card = fmixer->card;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = fmixer->card;
int res;
if (numid == ID_UNKNOWN)
@@ -640,16 +635,16 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
kfree(uinfo);
}
-static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
unsigned int numid,
int left, int right,
int route)
{
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
- snd_kcontrol_t *kctl;
- snd_card_t *card = fmixer->card;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = fmixer->card;
int res;
if (numid == ID_UNKNOWN)
@@ -685,8 +680,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
kfree(uinfo);
}
-static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int left, int right)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -723,8 +718,8 @@ static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_get_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int *active)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -736,8 +731,8 @@ static int snd_mixer_oss_get_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_get_recsrc1_route(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int *active)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -749,8 +744,8 @@ static int snd_mixer_oss_get_recsrc1_route(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_put_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int active)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -759,8 +754,8 @@ static int snd_mixer_oss_put_recsrc1_sw(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_put_recsrc1_route(snd_mixer_oss_file_t *fmixer,
- snd_mixer_oss_slot_t *pslot,
+static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer,
+ struct snd_mixer_oss_slot *pslot,
int active)
{
struct slot *slot = (struct slot *)pslot->private_data;
@@ -769,15 +764,15 @@ static int snd_mixer_oss_put_recsrc1_route(snd_mixer_oss_file_t *fmixer,
return 0;
}
-static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int *active_index)
+static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int *active_index)
{
- snd_card_t *card = fmixer->card;
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_kcontrol_t *kctl;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_card *card = fmixer->card;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_kcontrol *kctl;
+ struct snd_mixer_oss_slot *pslot;
struct slot *slot;
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
int err, idx;
uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
@@ -818,15 +813,15 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
return err;
}
-static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int active_index)
+static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned int active_index)
{
- snd_card_t *card = fmixer->card;
- snd_mixer_oss_t *mixer = fmixer->mixer;
- snd_kcontrol_t *kctl;
- snd_mixer_oss_slot_t *pslot;
+ struct snd_card *card = fmixer->card;
+ struct snd_mixer_oss *mixer = fmixer->mixer;
+ struct snd_kcontrol *kctl;
+ struct snd_mixer_oss_slot *pslot;
struct slot *slot = NULL;
- snd_ctl_elem_info_t *uinfo;
- snd_ctl_elem_value_t *uctl;
+ struct snd_ctl_elem_info *uinfo;
+ struct snd_ctl_elem_value *uctl;
int err;
unsigned int idx;
@@ -878,11 +873,11 @@ struct snd_mixer_oss_assign_table {
int index;
};
-static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, const char *name, int index, int item)
+static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *slot, const char *name, int index, int item)
{
- snd_ctl_elem_info_t *info;
- snd_kcontrol_t *kcontrol;
- snd_card_t *card = mixer->card;
+ struct snd_ctl_elem_info *info;
+ struct snd_kcontrol *kcontrol;
+ struct snd_card *card = mixer->card;
int err;
down_read(&card->controls_rwsem);
@@ -910,7 +905,7 @@ static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, c
return 0;
}
-static void snd_mixer_oss_slot_free(snd_mixer_oss_slot_t *chn)
+static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
{
struct slot *p = (struct slot *)chn->private_data;
if (p) {
@@ -922,7 +917,7 @@ static void snd_mixer_oss_slot_free(snd_mixer_oss_slot_t *chn)
}
}
-static void mixer_slot_clear(snd_mixer_oss_slot_t *rslot)
+static void mixer_slot_clear(struct snd_mixer_oss_slot *rslot)
{
int idx = rslot->number; /* remember this */
if (rslot->private_free)
@@ -936,12 +931,12 @@ static void mixer_slot_clear(snd_mixer_oss_slot_t *rslot)
* ptr_allocated means the entry is dynamically allocated (change via proc file).
* when replace_old = 1, the old entry is replaced with the new one.
*/
-static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old)
+static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old)
{
struct slot slot;
struct slot *pslot;
- snd_kcontrol_t *kctl;
- snd_mixer_oss_slot_t *rslot;
+ struct snd_kcontrol *kctl;
+ struct snd_mixer_oss_slot *rslot;
char str[64];
/* check if already assigned */
@@ -991,7 +986,7 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
return 0;
down_read(&mixer->card->controls_rwsem);
if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
- snd_ctl_elem_info_t *uinfo;
+ struct snd_ctl_elem_info *uinfo;
uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
if (! uinfo) {
@@ -1058,6 +1053,7 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
*/
#define MIXER_VOL(name) [SOUND_MIXER_##name] = #name
@@ -1093,10 +1089,10 @@ static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
* /proc interface
*/
-static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_mixer_oss_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_mixer_oss_t *mixer = entry->private_data;
+ struct snd_mixer_oss *mixer = entry->private_data;
int i;
down(&mixer->reg_mutex);
@@ -1117,10 +1113,10 @@ static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
up(&mixer->reg_mutex);
}
-static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_mixer_oss_t *mixer = entry->private_data;
+ struct snd_mixer_oss *mixer = entry->private_data;
char line[128], str[32], idxstr[16], *cptr;
int ch, idx;
struct snd_mixer_oss_assign_table *tbl;
@@ -1176,9 +1172,9 @@ static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
}
}
-static void snd_mixer_oss_proc_init(snd_mixer_oss_t *mixer)
+static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_card_entry(mixer->card, "oss_mixer",
mixer->card->proc_root);
@@ -1198,15 +1194,19 @@ static void snd_mixer_oss_proc_init(snd_mixer_oss_t *mixer)
mixer->proc_entry = entry;
}
-static void snd_mixer_oss_proc_done(snd_mixer_oss_t *mixer)
+static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer)
{
if (mixer->proc_entry) {
snd_info_unregister(mixer->proc_entry);
mixer->proc_entry = NULL;
}
}
+#else /* !CONFIG_PROC_FS */
+#define snd_mixer_oss_proc_init(mix)
+#define snd_mixer_oss_proc_done(mix)
+#endif /* CONFIG_PROC_FS */
-static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
+static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
{
static struct snd_mixer_oss_assign_table table[] = {
{ SOUND_MIXER_VOLUME, "Master", 0 },
@@ -1260,8 +1260,8 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
static int snd_mixer_oss_free1(void *private)
{
- snd_mixer_oss_t *mixer = private;
- snd_card_t * card;
+ struct snd_mixer_oss *mixer = private;
+ struct snd_card *card;
int idx;
snd_assert(mixer != NULL, return -ENXIO);
@@ -1269,7 +1269,7 @@ static int snd_mixer_oss_free1(void *private)
snd_assert(mixer == card->mixer_oss, return -ENXIO);
card->mixer_oss = NULL;
for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) {
- snd_mixer_oss_slot_t *chn = &mixer->slots[idx];
+ struct snd_mixer_oss_slot *chn = &mixer->slots[idx];
if (chn->private_free)
chn->private_free(chn);
}
@@ -1277,9 +1277,9 @@ static int snd_mixer_oss_free1(void *private)
return 0;
}
-static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
+static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
{
- snd_mixer_oss_t *mixer;
+ struct snd_mixer_oss *mixer;
if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) {
char name[128];
@@ -1292,7 +1292,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
sprintf(name, "mixer%i%i", card->number, 0);
if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
card, 0,
- &snd_mixer_oss_reg,
+ &snd_mixer_oss_f_ops, card,
name)) < 0) {
snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
card->number, 0);
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index 44ec4c66eb19..14f5578ec7a7 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -139,25 +139,25 @@ static int ulaw2linear(unsigned char u_val)
* Basic Mu-Law plugin
*/
-typedef void (*mulaw_f)(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+typedef void (*mulaw_f)(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames);
-typedef struct mulaw_private_data {
+struct mulaw_priv {
mulaw_f func;
int conv;
-} mulaw_t;
+};
-static void mulaw_decode(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static void mulaw_decode(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
#define PUT_S16_LABELS
#include "plugin_ops.h"
#undef PUT_S16_LABELS
- mulaw_t *data = (mulaw_t *)plugin->extra_data;
+ struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
void *put = put_s16_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
@@ -191,15 +191,15 @@ static void mulaw_decode(snd_pcm_plugin_t *plugin,
}
}
-static void mulaw_encode(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static void mulaw_encode(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
#define GET_S16_LABELS
#include "plugin_ops.h"
#undef GET_S16_LABELS
- mulaw_t *data = (mulaw_t *)plugin->extra_data;
+ struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
void *get = get_s16_labels[data->conv];
int channel;
int nchannels = plugin->src_format.channels;
@@ -234,12 +234,12 @@ static void mulaw_encode(snd_pcm_plugin_t *plugin,
}
}
-static snd_pcm_sframes_t mulaw_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- mulaw_t *data;
+ struct mulaw_priv *data;
snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
if (frames == 0)
@@ -257,20 +257,20 @@ static snd_pcm_sframes_t mulaw_transfer(snd_pcm_plugin_t *plugin,
}
}
#endif
- data = (mulaw_t *)plugin->extra_data;
+ data = (struct mulaw_priv *)plugin->extra_data;
data->func(plugin, src_channels, dst_channels, frames);
return frames;
}
-int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin)
{
int err;
- mulaw_t *data;
- snd_pcm_plugin_t *plugin;
- snd_pcm_plugin_format_t *format;
+ struct mulaw_priv *data;
+ struct snd_pcm_plugin *plugin;
+ struct snd_pcm_plugin_format *format;
mulaw_f func;
snd_assert(r_plugin != NULL, return -ENXIO);
@@ -295,10 +295,10 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug,
err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
src_format, dst_format,
- sizeof(mulaw_t), &plugin);
+ sizeof(struct mulaw_priv), &plugin);
if (err < 0)
return err;
- data = (mulaw_t*)plugin->extra_data;
+ data = (struct mulaw_priv *)plugin->extra_data;
data->func = func;
data->conv = getput_index(format->format);
snd_assert(data->conv >= 0 && data->conv < 4*2*2, return -EINVAL);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index bcc970759134..7fd072392c7e 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -61,10 +61,10 @@ MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
-extern int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg);
-static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file);
-static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file);
-static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file);
+extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg);
+static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
+static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
+static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
static inline mm_segment_t snd_enter_user(void)
{
@@ -78,10 +78,10 @@ static inline void snd_leave_user(mm_segment_t fs)
set_fs(fs);
}
-static int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_plugin_t *plugin, *next;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_plugin *plugin, *next;
plugin = runtime->oss.plugin_first;
while (plugin) {
@@ -93,9 +93,9 @@ static int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin)
+static int snd_pcm_plugin_insert(struct snd_pcm_plugin *plugin)
{
- snd_pcm_runtime_t *runtime = plugin->plug->runtime;
+ struct snd_pcm_runtime *runtime = plugin->plug->runtime;
plugin->next = runtime->oss.plugin_first;
plugin->prev = NULL;
if (runtime->oss.plugin_first) {
@@ -108,9 +108,9 @@ static int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin)
return 0;
}
-int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
+int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin)
{
- snd_pcm_runtime_t *runtime = plugin->plug->runtime;
+ struct snd_pcm_runtime *runtime = plugin->plug->runtime;
plugin->next = NULL;
plugin->prev = runtime->oss.plugin_last;
if (runtime->oss.plugin_last) {
@@ -123,9 +123,9 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
return 0;
}
-static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
+static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
long buffer_size = snd_pcm_lib_buffer_bytes(substream);
long bytes = frames_to_bytes(runtime, frames);
if (buffer_size == runtime->oss.buffer_bytes)
@@ -142,9 +142,9 @@ static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
#endif
}
-static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
+static long snd_pcm_alsa_frames(struct snd_pcm_substream *substream, long bytes)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
long buffer_size = snd_pcm_lib_buffer_bytes(substream);
if (buffer_size == runtime->oss.buffer_bytes)
return bytes_to_frames(runtime, bytes);
@@ -185,14 +185,14 @@ static int snd_pcm_oss_format_to(int format)
}
}
-static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *oss_params,
- snd_pcm_hw_params_t *slave_params)
+static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *oss_params,
+ struct snd_pcm_hw_params *slave_params)
{
size_t s;
size_t oss_buffer_size, oss_period_size, oss_periods;
size_t min_period_size, max_period_size;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
size_t oss_frame_size;
oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) *
@@ -277,11 +277,11 @@ static int snd_pcm_oss_period_size(snd_pcm_substream_t *substream,
return 0;
}
-static int choose_rate(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params, unsigned int best_rate)
+static int choose_rate(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, unsigned int best_rate)
{
- snd_interval_t *it;
- snd_pcm_hw_params_t *save;
+ struct snd_interval *it;
+ struct snd_pcm_hw_params *save;
unsigned int rate, prev;
save = kmalloc(sizeof(*save), GFP_KERNEL);
@@ -317,18 +317,18 @@ static int choose_rate(snd_pcm_substream_t *substream,
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
}
-static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_hw_params_t *params, *sparams;
- snd_pcm_sw_params_t *sw_params;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hw_params *params, *sparams;
+ struct snd_pcm_sw_params *sw_params;
ssize_t oss_buffer_size, oss_period_size;
size_t oss_frame_size;
int err;
int direct;
int format, sformat, n;
- snd_mask_t sformat_mask;
- snd_mask_t mask;
+ struct snd_mask sformat_mask;
+ struct snd_mask mask;
sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -342,7 +342,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
if (atomic_read(&runtime->mmap_count)) {
direct = 1;
} else {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
direct = (setup != NULL && setup->direct);
}
@@ -424,7 +424,7 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
goto failure;
}
if (runtime->oss.plugin_first) {
- snd_pcm_plugin_t *plugin;
+ struct snd_pcm_plugin *plugin;
if ((err = snd_pcm_plugin_build_io(substream, sparams, &plugin)) < 0) {
snd_printd("snd_pcm_plugin_build_io failed: %i\n", err);
snd_pcm_oss_plugin_clear(substream);
@@ -540,10 +540,10 @@ failure:
return err;
}
-static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, snd_pcm_substream_t **r_substream)
+static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_file, struct snd_pcm_substream **r_substream)
{
int idx, err;
- snd_pcm_substream_t *asubstream = NULL, *substream;
+ struct snd_pcm_substream *asubstream = NULL, *substream;
for (idx = 0; idx < 2; idx++) {
substream = pcm_oss_file->streams[idx];
@@ -563,10 +563,10 @@ static int snd_pcm_oss_get_active_substream(snd_pcm_oss_file_t *pcm_oss_file, sn
return 0;
}
-static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream)
{
int err;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
if (err < 0) {
@@ -581,9 +581,9 @@ static int snd_pcm_oss_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int err;
if (substream == NULL)
@@ -602,9 +602,9 @@ static int snd_pcm_oss_make_ready(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, snd_pcm_sframes_t *delay)
+static int snd_pcm_oss_capture_position_fixup(struct snd_pcm_substream *substream, snd_pcm_sframes_t *delay)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
snd_pcm_uframes_t frames;
int err = 0;
@@ -627,9 +627,9 @@ static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, sn
return err;
}
-snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
@@ -662,9 +662,9 @@ snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t delay;
int ret;
while (1) {
@@ -709,9 +709,9 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, s
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
@@ -745,9 +745,9 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **buf
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
@@ -780,12 +780,12 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs
return ret;
}
-static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *buf, size_t bytes, int in_kernel)
+static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
if (runtime->oss.plugin_first) {
- snd_pcm_plugin_channel_t *channels;
+ struct snd_pcm_plugin_channel *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
if (!in_kernel) {
if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
@@ -810,11 +810,11 @@ static ssize_t snd_pcm_oss_write2(snd_pcm_substream_t *substream, const char *bu
return bytes;
}
-static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __user *buf, size_t bytes)
+static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const char __user *buf, size_t bytes)
{
size_t xfer = 0;
ssize_t tmp;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&runtime->mmap_count))
return -ENXIO;
@@ -867,13 +867,13 @@ static ssize_t snd_pcm_oss_write1(snd_pcm_substream_t *substream, const char __u
return xfer;
}
-static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size_t bytes, int in_kernel)
+static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, size_t bytes, int in_kernel)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t frames, frames1;
char __user *final_dst = (char __user *)buf;
if (runtime->oss.plugin_first) {
- snd_pcm_plugin_channel_t *channels;
+ struct snd_pcm_plugin_channel *channels;
size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
if (!in_kernel)
buf = runtime->oss.buffer;
@@ -897,11 +897,11 @@ static ssize_t snd_pcm_oss_read2(snd_pcm_substream_t *substream, char *buf, size
return bytes;
}
-static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *buf, size_t bytes)
+static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __user *buf, size_t bytes)
{
size_t xfer = 0;
ssize_t tmp;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&runtime->mmap_count))
return -ENXIO;
@@ -941,9 +941,9 @@ static ssize_t snd_pcm_oss_read1(snd_pcm_substream_t *substream, char __user *bu
return xfer;
}
-static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_reset(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream != NULL) {
@@ -958,9 +958,9 @@ static int snd_pcm_oss_reset(snd_pcm_oss_file_t *pcm_oss_file)
return 0;
}
-static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_post(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -974,9 +974,9 @@ static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file)
return 0;
}
-static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size)
+static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
ssize_t result = 0;
long res;
wait_queue_t wait;
@@ -1020,12 +1020,12 @@ static int snd_pcm_oss_sync1(snd_pcm_substream_t *substream, size_t size)
return result;
}
-static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
{
int err = 0;
unsigned int saved_f_flags;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_format_t format;
unsigned long width;
size_t size;
@@ -1117,13 +1117,13 @@ static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file)
return 0;
}
-static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate)
+static int snd_pcm_oss_set_rate(struct snd_pcm_oss_file *pcm_oss_file, int rate)
{
int idx;
for (idx = 1; idx >= 0; --idx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -1139,9 +1139,9 @@ static int snd_pcm_oss_set_rate(snd_pcm_oss_file_t *pcm_oss_file, int rate)
return snd_pcm_oss_get_rate(pcm_oss_file);
}
-static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1149,7 +1149,7 @@ static int snd_pcm_oss_get_rate(snd_pcm_oss_file_t *pcm_oss_file)
return substream->runtime->oss.rate;
}
-static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned int channels)
+static int snd_pcm_oss_set_channels(struct snd_pcm_oss_file *pcm_oss_file, unsigned int channels)
{
int idx;
if (channels < 1)
@@ -1157,8 +1157,8 @@ static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned i
if (channels > 128)
return -EINVAL;
for (idx = 1; idx >= 0; --idx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -1170,9 +1170,9 @@ static int snd_pcm_oss_set_channels(snd_pcm_oss_file_t *pcm_oss_file, unsigned i
return snd_pcm_oss_get_channels(pcm_oss_file);
}
-static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1180,9 +1180,9 @@ static int snd_pcm_oss_get_channels(snd_pcm_oss_file_t *pcm_oss_file)
return substream->runtime->oss.channels;
}
-static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_block_size(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1190,14 +1190,14 @@ static int snd_pcm_oss_get_block_size(snd_pcm_oss_file_t *pcm_oss_file)
return substream->runtime->oss.period_bytes;
}
-static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
int direct;
- snd_pcm_hw_params_t *params;
+ struct snd_pcm_hw_params *params;
unsigned int formats = 0;
- snd_mask_t format_mask;
+ struct snd_mask format_mask;
int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1205,7 +1205,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
if (atomic_read(&substream->runtime->mmap_count)) {
direct = 1;
} else {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
direct = (setup != NULL && setup->direct);
}
if (!direct)
@@ -1231,7 +1231,7 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
return formats;
}
-static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format)
+static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format)
{
int formats, idx;
@@ -1240,8 +1240,8 @@ static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format)
if (!(formats & format))
format = AFMT_U8;
for (idx = 1; idx >= 0; --idx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -1254,9 +1254,9 @@ static int snd_pcm_oss_set_format(snd_pcm_oss_file_t *pcm_oss_file, int format)
return snd_pcm_oss_get_format(pcm_oss_file);
}
-static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int err;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1264,9 +1264,9 @@ static int snd_pcm_oss_get_format(snd_pcm_oss_file_t *pcm_oss_file)
return substream->runtime->oss.format;
}
-static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdivide)
+static int snd_pcm_oss_set_subdivide1(struct snd_pcm_substream *substream, int subdivide)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
return 0;
@@ -1287,12 +1287,12 @@ static int snd_pcm_oss_set_subdivide1(snd_pcm_substream_t *substream, int subdiv
return subdivide;
}
-static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdivide)
+static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int subdivide)
{
int err = -EINVAL, idx;
for (idx = 1; idx >= 0; --idx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
if (substream == NULL)
continue;
if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0)
@@ -1301,9 +1301,9 @@ static int snd_pcm_oss_set_subdivide(snd_pcm_oss_file_t *pcm_oss_file, int subdi
return err;
}
-static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned int val)
+static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
return 0;
@@ -1320,12 +1320,12 @@ static int snd_pcm_oss_set_fragment1(snd_pcm_substream_t *substream, unsigned in
return 0;
}
-static int snd_pcm_oss_set_fragment(snd_pcm_oss_file_t *pcm_oss_file, unsigned int val)
+static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsigned int val)
{
int err = -EINVAL, idx;
for (idx = 1; idx >= 0; --idx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
if (substream == NULL)
continue;
if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0)
@@ -1340,7 +1340,7 @@ static int snd_pcm_oss_nonblock(struct file * file)
return 0;
}
-static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res)
+static int snd_pcm_oss_get_caps1(struct snd_pcm_substream *substream, int res)
{
if (substream == NULL) {
@@ -1356,7 +1356,7 @@ static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res)
/* all ALSA drivers can return actual pointer in ring buffer */
#if defined(DSP_CAP_REALTIME) && 0
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->info & (SNDRV_PCM_INFO_BLOCK_TRANSFER|SNDRV_PCM_INFO_BATCH))
res &= ~DSP_CAP_REALTIME;
}
@@ -1364,32 +1364,32 @@ static int snd_pcm_oss_get_caps1(snd_pcm_substream_t *substream, int res)
return res;
}
-static int snd_pcm_oss_get_caps(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_caps(struct snd_pcm_oss_file *pcm_oss_file)
{
int result, idx;
result = DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_DUPLEX | DSP_CAP_REALTIME;
for (idx = 0; idx < 2; idx++) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[idx];
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[idx];
result = snd_pcm_oss_get_caps1(substream, result);
}
result |= 0x0001; /* revision - same as SB AWE 64 */
return result;
}
-static void snd_pcm_oss_simulate_fill(snd_pcm_substream_t *substream, snd_pcm_uframes_t hw_ptr)
+static void snd_pcm_oss_simulate_fill(struct snd_pcm_substream *substream, snd_pcm_uframes_t hw_ptr)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t appl_ptr;
appl_ptr = hw_ptr + runtime->buffer_size;
appl_ptr %= runtime->boundary;
runtime->control->appl_ptr = appl_ptr;
}
-static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger)
+static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int trigger)
{
- snd_pcm_runtime_t *runtime;
- snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_runtime *runtime;
+ struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
int err, cmd;
#ifdef OSS_DEBUG
@@ -1454,9 +1454,9 @@ static int snd_pcm_oss_set_trigger(snd_pcm_oss_file_t *pcm_oss_file, int trigger
return 0;
}
-static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
int result = 0;
psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -1468,10 +1468,10 @@ static int snd_pcm_oss_get_trigger(snd_pcm_oss_file_t *pcm_oss_file)
return result;
}
-static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_get_odelay(struct snd_pcm_oss_file *pcm_oss_file)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t delay;
int err;
@@ -1491,10 +1491,10 @@ static int snd_pcm_oss_get_odelay(snd_pcm_oss_file_t *pcm_oss_file)
return snd_pcm_oss_bytes(substream, delay);
}
-static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct count_info __user * _info)
+static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct count_info __user * _info)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t delay;
int fixup;
struct count_info info;
@@ -1543,7 +1543,7 @@ 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) {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
if (setup && setup->buggyptr)
info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
else
@@ -1560,10 +1560,10 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
return 0;
}
-static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
+static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct audio_buf_info __user *_info)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t avail;
int fixup;
struct audio_buf_info info;
@@ -1619,17 +1619,17 @@ static int snd_pcm_oss_get_space(snd_pcm_oss_file_t *pcm_oss_file, int stream, s
return 0;
}
-static int snd_pcm_oss_get_mapbuf(snd_pcm_oss_file_t *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
+static int snd_pcm_oss_get_mapbuf(struct snd_pcm_oss_file *pcm_oss_file, int stream, struct buffmem_desc __user * _info)
{
// it won't be probably implemented
// snd_printd("TODO: snd_pcm_oss_get_mapbuf\n");
return -EINVAL;
}
-static snd_pcm_oss_setup_t *snd_pcm_oss_look_for_setup(snd_pcm_t *pcm, int stream, const char *task_name)
+static struct snd_pcm_oss_setup *snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream, const char *task_name)
{
const char *ptr, *ptrl;
- snd_pcm_oss_setup_t *setup;
+ struct snd_pcm_oss_setup *setup;
down(&pcm->streams[stream].oss.setup_mutex);
for (setup = pcm->streams[stream].oss.setup_list; setup; setup = setup->next) {
@@ -1659,11 +1659,11 @@ static snd_pcm_oss_setup_t *snd_pcm_oss_look_for_setup(snd_pcm_t *pcm, int strea
return NULL;
}
-static void snd_pcm_oss_init_substream(snd_pcm_substream_t *substream,
- snd_pcm_oss_setup_t *setup,
+static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream,
+ struct snd_pcm_oss_setup *setup,
int minor)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
substream->oss.oss = 1;
substream->oss.setup = setup;
@@ -1687,9 +1687,9 @@ static void snd_pcm_oss_init_substream(snd_pcm_substream_t *substream,
runtime->oss.subdivision = 0;
}
-static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream)
+static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
runtime = substream->runtime;
vfree(runtime->oss.buffer);
snd_pcm_oss_plugin_clear(substream);
@@ -1697,13 +1697,13 @@ static void snd_pcm_oss_release_substream(snd_pcm_substream_t *substream)
substream->oss.oss = 0;
}
-static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
+static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file)
{
int cidx;
snd_assert(pcm_oss_file != NULL, return -ENXIO);
for (cidx = 0; cidx < 2; ++cidx) {
- snd_pcm_substream_t *substream = pcm_oss_file->streams[cidx];
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = pcm_oss_file->streams[cidx];
+ struct snd_pcm_runtime *runtime;
if (substream == NULL)
continue;
runtime = substream->runtime;
@@ -1726,15 +1726,15 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
}
static int snd_pcm_oss_open_file(struct file *file,
- snd_pcm_t *pcm,
- snd_pcm_oss_file_t **rpcm_oss_file,
+ struct snd_pcm *pcm,
+ struct snd_pcm_oss_file **rpcm_oss_file,
int minor,
- snd_pcm_oss_setup_t *psetup,
- snd_pcm_oss_setup_t *csetup)
+ struct snd_pcm_oss_setup *psetup,
+ struct snd_pcm_oss_setup *csetup)
{
int err = 0;
- snd_pcm_oss_file_t *pcm_oss_file;
- snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_oss_file *pcm_oss_file;
+ struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
unsigned int f_mode = file->f_mode;
snd_assert(rpcm_oss_file != NULL, return -EINVAL);
@@ -1834,22 +1834,16 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size)
static int snd_pcm_oss_open(struct inode *inode, struct file *file)
{
- int minor = iminor(inode);
- int cardnum = SNDRV_MINOR_OSS_CARD(minor);
- int device;
int err;
char task_name[32];
- snd_pcm_t *pcm;
- snd_pcm_oss_file_t *pcm_oss_file;
- snd_pcm_oss_setup_t *psetup = NULL, *csetup = NULL;
+ struct snd_pcm *pcm;
+ struct snd_pcm_oss_file *pcm_oss_file;
+ struct snd_pcm_oss_setup *psetup = NULL, *csetup = NULL;
int nonblock;
wait_queue_t wait;
- snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
- device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ?
- adsp_map[cardnum] : dsp_map[cardnum];
-
- pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
+ pcm = snd_lookup_oss_minor_data(iminor(inode),
+ SNDRV_OSS_DEVICE_TYPE_PCM);
if (pcm == NULL) {
err = -ENODEV;
goto __error1;
@@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
down(&pcm->open_mutex);
while (1) {
err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
- minor, psetup, csetup);
+ iminor(inode), psetup, csetup);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -1925,9 +1919,9 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
static int snd_pcm_oss_release(struct inode *inode, struct file *file)
{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
- snd_pcm_oss_file_t *pcm_oss_file;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_oss_file *pcm_oss_file;
pcm_oss_file = file->private_data;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -1947,7 +1941,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_pcm_oss_file_t *pcm_oss_file;
+ struct snd_pcm_oss_file *pcm_oss_file;
int __user *p = (int __user *)arg;
int res;
@@ -1958,7 +1952,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
return put_user(1, p);
#if defined(CONFIG_SND_MIXER_OSS) || (defined(MODULE) && defined(CONFIG_SND_MIXER_OSS_MODULE))
if (((cmd >> 8) & 0xff) == 'M') { /* mixer ioctl - for OSS compatibility */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int idx;
for (idx = 0; idx < 2; ++idx) {
substream = pcm_oss_file->streams[idx];
@@ -2113,8 +2107,8 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- snd_pcm_oss_file_t *pcm_oss_file;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_oss_file *pcm_oss_file;
+ struct snd_pcm_substream *substream;
pcm_oss_file = file->private_data;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -2133,35 +2127,33 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
- snd_pcm_oss_file_t *pcm_oss_file;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_oss_file *pcm_oss_file;
+ struct snd_pcm_substream *substream;
long result;
pcm_oss_file = file->private_data;
substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (substream == NULL)
return -ENXIO;
- up(&file->f_dentry->d_inode->i_sem);
result = snd_pcm_oss_write1(substream, buf, count);
- down(&file->f_dentry->d_inode->i_sem);
#ifdef OSS_DEBUG
printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
#endif
return result;
}
-static int snd_pcm_oss_playback_ready(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&runtime->mmap_count))
return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
else
return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
}
-static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream)
+static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (atomic_read(&runtime->mmap_count))
return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
else
@@ -2170,9 +2162,9 @@ static int snd_pcm_oss_capture_ready(snd_pcm_substream_t *substream)
static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
{
- snd_pcm_oss_file_t *pcm_oss_file;
+ struct snd_pcm_oss_file *pcm_oss_file;
unsigned int mask;
- snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
+ struct snd_pcm_substream *psubstream = NULL, *csubstream = NULL;
pcm_oss_file = file->private_data;
@@ -2181,7 +2173,7 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
mask = 0;
if (psubstream != NULL) {
- snd_pcm_runtime_t *runtime = psubstream->runtime;
+ struct snd_pcm_runtime *runtime = psubstream->runtime;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(psubstream);
if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
@@ -2191,8 +2183,8 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
snd_pcm_stream_unlock_irq(psubstream);
}
if (csubstream != NULL) {
- snd_pcm_runtime_t *runtime = csubstream->runtime;
- enum sndrv_pcm_state ostate;
+ struct snd_pcm_runtime *runtime = csubstream->runtime;
+ snd_pcm_state_t ostate;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(csubstream);
if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING ||
@@ -2200,7 +2192,7 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
mask |= POLLIN | POLLRDNORM;
snd_pcm_stream_unlock_irq(csubstream);
if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
- snd_pcm_oss_file_t ofile;
+ struct snd_pcm_oss_file ofile;
memset(&ofile, 0, sizeof(ofile));
ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
runtime->oss.trigger = 0;
@@ -2213,9 +2205,9 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
{
- snd_pcm_oss_file_t *pcm_oss_file;
- snd_pcm_substream_t *substream = NULL;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_oss_file *pcm_oss_file;
+ struct snd_pcm_substream *substream = NULL;
+ struct snd_pcm_runtime *runtime;
int err;
#ifdef OSS_DEBUG
@@ -2275,15 +2267,16 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* /proc interface
*/
-static void snd_pcm_oss_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
- snd_pcm_oss_setup_t *setup = pstr->oss.setup_list;
+ struct snd_pcm_str *pstr = entry->private_data;
+ struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
down(&pstr->oss.setup_mutex);
while (setup) {
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
@@ -2301,11 +2294,11 @@ static void snd_pcm_oss_proc_read(snd_info_entry_t *entry,
up(&pstr->oss.setup_mutex);
}
-static void snd_pcm_oss_proc_free_setup_list(snd_pcm_str_t * pstr)
+static void snd_pcm_oss_proc_free_setup_list(struct snd_pcm_str * pstr)
{
unsigned int idx;
- snd_pcm_substream_t *substream;
- snd_pcm_oss_setup_t *setup, *setupn;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_oss_setup *setup, *setupn;
for (idx = 0, substream = pstr->substream;
idx < pstr->substream_count; idx++, substream = substream->next)
@@ -2319,13 +2312,13 @@ static void snd_pcm_oss_proc_free_setup_list(snd_pcm_str_t * pstr)
pstr->oss.setup_list = NULL;
}
-static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
+ struct snd_pcm_str *pstr = entry->private_data;
char line[128], str[32], task_name[32], *ptr;
int idx1;
- snd_pcm_oss_setup_t *setup, *setup1, template;
+ struct snd_pcm_oss_setup *setup, *setup1, template;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
down(&pstr->oss.setup_mutex);
@@ -2370,7 +2363,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
}
} while (*str);
if (setup == NULL) {
- setup = (snd_pcm_oss_setup_t *) kmalloc(sizeof(snd_pcm_oss_setup_t), GFP_KERNEL);
+ setup = kmalloc(sizeof(struct snd_pcm_oss_setup), GFP_KERNEL);
if (setup) {
if (pstr->oss.setup_list == NULL) {
pstr->oss.setup_list = setup;
@@ -2389,12 +2382,12 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
}
}
-static void snd_pcm_oss_proc_init(snd_pcm_t *pcm)
+static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
{
int stream;
for (stream = 0; stream < 2; ++stream) {
- snd_info_entry_t *entry;
- snd_pcm_str_t *pstr = &pcm->streams[stream];
+ struct snd_info_entry *entry;
+ struct snd_pcm_str *pstr = &pcm->streams[stream];
if (pstr->substream_count == 0)
continue;
if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
@@ -2414,11 +2407,11 @@ static void snd_pcm_oss_proc_init(snd_pcm_t *pcm)
}
}
-static void snd_pcm_oss_proc_done(snd_pcm_t *pcm)
+static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
{
int stream;
for (stream = 0; stream < 2; ++stream) {
- snd_pcm_str_t *pstr = &pcm->streams[stream];
+ struct snd_pcm_str *pstr = &pcm->streams[stream];
if (pstr->oss.proc_entry) {
snd_info_unregister(pstr->oss.proc_entry);
pstr->oss.proc_entry = NULL;
@@ -2426,6 +2419,10 @@ static void snd_pcm_oss_proc_done(snd_pcm_t *pcm)
}
}
}
+#else /* !CONFIG_PROC_FS */
+#define snd_pcm_oss_proc_init(pcm)
+#define snd_pcm_oss_proc_done(pcm)
+#endif /* CONFIG_PROC_FS */
/*
* ENTRY functions
@@ -2444,25 +2441,19 @@ static struct file_operations snd_pcm_oss_f_reg =
.mmap = snd_pcm_oss_mmap,
};
-static snd_minor_t snd_pcm_oss_reg =
-{
- .comment = "digital audio",
- .f_ops = &snd_pcm_oss_f_reg,
-};
-
-static void register_oss_dsp(snd_pcm_t *pcm, int index)
+static void register_oss_dsp(struct snd_pcm *pcm, int index)
{
char name[128];
sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
- pcm->card, index, &snd_pcm_oss_reg,
- name) < 0) {
+ pcm->card, index, &snd_pcm_oss_f_reg,
+ pcm, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
pcm->card->number, pcm->device);
}
}
-static int snd_pcm_oss_register_minor(snd_pcm_t * pcm)
+static int snd_pcm_oss_register_minor(struct snd_pcm *pcm)
{
pcm->oss.reg = 0;
if (dsp_map[pcm->card->number] == (int)pcm->device) {
@@ -2493,7 +2484,7 @@ static int snd_pcm_oss_register_minor(snd_pcm_t * pcm)
return 0;
}
-static int snd_pcm_oss_disconnect_minor(snd_pcm_t * pcm)
+static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm)
{
if (pcm->oss.reg) {
if (pcm->oss.reg_mask & 1) {
@@ -2510,7 +2501,7 @@ static int snd_pcm_oss_disconnect_minor(snd_pcm_t * pcm)
return 0;
}
-static int snd_pcm_oss_unregister_minor(snd_pcm_t * pcm)
+static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm)
{
snd_pcm_oss_disconnect_minor(pcm);
if (pcm->oss.reg) {
@@ -2525,7 +2516,7 @@ static int snd_pcm_oss_unregister_minor(snd_pcm_t * pcm)
return 0;
}
-static snd_pcm_notify_t snd_pcm_oss_notify =
+static struct snd_pcm_notify snd_pcm_oss_notify =
{
.n_register = snd_pcm_oss_register_minor,
.n_disconnect = snd_pcm_oss_disconnect_minor,
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index fc23373c000d..7e8676880dde 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -36,22 +36,22 @@
#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
-static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin,
- bitset_t *dst_vmask,
- bitset_t **src_vmask)
+static int snd_pcm_plugin_src_channels_mask(struct snd_pcm_plugin *plugin,
+ unsigned long *dst_vmask,
+ unsigned long **src_vmask)
{
- bitset_t *vmask = plugin->src_vmask;
- bitset_copy(vmask, dst_vmask, plugin->src_format.channels);
+ unsigned long *vmask = plugin->src_vmask;
+ bitmap_copy(vmask, dst_vmask, plugin->src_format.channels);
*src_vmask = vmask;
return 0;
}
-static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
- bitset_t *src_vmask,
- bitset_t **dst_vmask)
+static int snd_pcm_plugin_dst_channels_mask(struct snd_pcm_plugin *plugin,
+ unsigned long *src_vmask,
+ unsigned long **dst_vmask)
{
- bitset_t *vmask = plugin->dst_vmask;
- bitset_copy(vmask, src_vmask, plugin->dst_format.channels);
+ unsigned long *vmask = plugin->dst_vmask;
+ bitmap_copy(vmask, src_vmask, plugin->dst_format.channels);
*dst_vmask = vmask;
return 0;
}
@@ -67,13 +67,13 @@ static int rate_match(unsigned int src_rate, unsigned int dst_rate)
return dst_rate >= low && dst_rate <= high;
}
-static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
+static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
{
- snd_pcm_plugin_format_t *format;
+ struct snd_pcm_plugin_format *format;
ssize_t width;
size_t size;
unsigned int channel;
- snd_pcm_plugin_channel_t *c;
+ struct snd_pcm_plugin_channel *c;
if (plugin->stream == SNDRV_PCM_STREAM_PLAYBACK) {
format = &plugin->src_format;
@@ -120,12 +120,12 @@ static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t fram
return 0;
}
-int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t frames)
+int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames)
{
int err;
snd_assert(snd_pcm_plug_first(plug) != NULL, return -ENXIO);
if (snd_pcm_plug_stream(plug) == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
+ struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
while (plugin->next) {
if (plugin->dst_frames)
frames = plugin->dst_frames(plugin, frames);
@@ -136,7 +136,7 @@ int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t frames)
return err;
}
} else {
- snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
+ struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
while (plugin->prev) {
if (plugin->src_frames)
frames = plugin->src_frames(plugin, frames);
@@ -151,22 +151,22 @@ int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t frames)
}
-snd_pcm_sframes_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin,
+snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
snd_pcm_uframes_t frames,
- snd_pcm_plugin_channel_t **channels)
+ struct snd_pcm_plugin_channel **channels)
{
*channels = plugin->buf_channels;
return frames;
}
-int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
+int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
const char *name,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
size_t extra,
- snd_pcm_plugin_t **ret)
+ struct snd_pcm_plugin **ret)
{
- snd_pcm_plugin_t *plugin;
+ struct snd_pcm_plugin *plugin;
unsigned int channels;
snd_assert(plug != NULL, return -ENXIO);
@@ -193,12 +193,12 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin);
return -ENOMEM;
}
- plugin->src_vmask = bitset_alloc(src_format->channels);
+ plugin->src_vmask = bitmap_alloc(src_format->channels);
if (plugin->src_vmask == NULL) {
snd_pcm_plugin_free(plugin);
return -ENOMEM;
}
- plugin->dst_vmask = bitset_alloc(dst_format->channels);
+ plugin->dst_vmask = bitmap_alloc(dst_format->channels);
if (plugin->dst_vmask == NULL) {
snd_pcm_plugin_free(plugin);
return -ENOMEM;
@@ -210,7 +210,7 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
return 0;
}
-int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin)
+int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
{
if (! plugin)
return 0;
@@ -224,9 +224,9 @@ int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin)
return 0;
}
-snd_pcm_sframes_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, snd_pcm_uframes_t drv_frames)
+snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t drv_frames)
{
- snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
+ struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
int stream = snd_pcm_plug_stream(plug);
snd_assert(plug != NULL, return -ENXIO);
@@ -253,9 +253,9 @@ snd_pcm_sframes_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, snd_pcm_uframes
return drv_frames;
}
-snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, snd_pcm_uframes_t clt_frames)
+snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pcm_uframes_t clt_frames)
{
- snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
+ struct snd_pcm_plugin *plugin, *plugin_prev, *plugin_next;
snd_pcm_sframes_t frames;
int stream = snd_pcm_plug_stream(plug);
@@ -290,9 +290,9 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, snd_pcm_uframes_
return frames;
}
-static int snd_pcm_plug_formats(snd_mask_t *mask, int format)
+static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
{
- snd_mask_t formats = *mask;
+ struct snd_mask formats = *mask;
u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_BE | SNDRV_PCM_FMTBIT_S16_BE |
@@ -326,7 +326,7 @@ static int preferred_formats[] = {
SNDRV_PCM_FORMAT_U8
};
-int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask)
+int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
{
if (snd_mask_test(format_mask, format))
return format;
@@ -376,15 +376,15 @@ int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask)
}
}
-int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *slave_params)
+int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
+ struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_params *slave_params)
{
- snd_pcm_plugin_format_t tmpformat;
- snd_pcm_plugin_format_t dstformat;
- snd_pcm_plugin_format_t srcformat;
+ struct snd_pcm_plugin_format tmpformat;
+ struct snd_pcm_plugin_format dstformat;
+ struct snd_pcm_plugin_format srcformat;
int src_access, dst_access;
- snd_pcm_plugin_t *plugin = NULL;
+ struct snd_pcm_plugin *plugin = NULL;
int err;
int stream = snd_pcm_plug_stream(plug);
int slave_interleaved = (params_channels(slave_params) == 1 ||
@@ -462,7 +462,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
if (srcformat.channels > dstformat.channels) {
int sv = srcformat.channels;
int dv = dstformat.channels;
- route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
+ int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
if (ttable == NULL)
return -ENOMEM;
#if 1
@@ -525,7 +525,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
if (srcformat.channels < dstformat.channels) {
int sv = srcformat.channels;
int dv = dstformat.channels;
- route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
+ int *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
if (ttable == NULL)
return -ENOMEM;
#if 0
@@ -614,14 +614,14 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
return 0;
}
-snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
+snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *plug,
char *buf,
snd_pcm_uframes_t count,
- snd_pcm_plugin_channel_t **channels)
+ struct snd_pcm_plugin_channel **channels)
{
- snd_pcm_plugin_t *plugin;
- snd_pcm_plugin_channel_t *v;
- snd_pcm_plugin_format_t *format;
+ struct snd_pcm_plugin *plugin;
+ struct snd_pcm_plugin_channel *v;
+ struct snd_pcm_plugin_format *format;
int width, nchannels, channel;
int stream = snd_pcm_plug_stream(plug);
@@ -650,19 +650,19 @@ snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
return count;
}
-static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
- bitset_t *client_vmask)
+static int snd_pcm_plug_playback_channels_mask(struct snd_pcm_substream *plug,
+ unsigned long *client_vmask)
{
- snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
+ struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
if (plugin == NULL) {
return 0;
} else {
int schannels = plugin->dst_format.channels;
- bitset_t bs[bitset_size(schannels)];
- bitset_t *srcmask;
- bitset_t *dstmask = bs;
+ DECLARE_BITMAP(bs, schannels);
+ unsigned long *srcmask;
+ unsigned long *dstmask = bs;
int err;
- bitset_one(dstmask, schannels);
+ bitmap_fill(dstmask, schannels);
while (1) {
err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
@@ -673,52 +673,52 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
break;
plugin = plugin->prev;
}
- bitset_and(client_vmask, dstmask, plugin->src_format.channels);
+ bitmap_and(client_vmask, client_vmask, dstmask, plugin->src_format.channels);
return 0;
}
}
-static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug,
- snd_pcm_plugin_channel_t *src_channels)
+static int snd_pcm_plug_playback_disable_useless_channels(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_channel *src_channels)
{
- snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
+ struct snd_pcm_plugin *plugin = snd_pcm_plug_first(plug);
unsigned int nchannels = plugin->src_format.channels;
- bitset_t bs[bitset_size(nchannels)];
- bitset_t *srcmask = bs;
+ DECLARE_BITMAP(bs, nchannels);
+ unsigned long *srcmask = bs;
int err;
unsigned int channel;
for (channel = 0; channel < nchannels; channel++) {
if (src_channels[channel].enabled)
- bitset_set(srcmask, channel);
+ set_bit(channel, srcmask);
else
- bitset_reset(srcmask, channel);
+ clear_bit(channel, srcmask);
}
err = snd_pcm_plug_playback_channels_mask(plug, srcmask);
if (err < 0)
return err;
for (channel = 0; channel < nchannels; channel++) {
- if (!bitset_get(srcmask, channel))
+ if (!test_bit(channel, srcmask))
src_channels[channel].enabled = 0;
}
return 0;
}
-static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug,
- snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *client_channels)
+static int snd_pcm_plug_capture_disable_useless_channels(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *client_channels)
{
- snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
+ struct snd_pcm_plugin *plugin = snd_pcm_plug_last(plug);
unsigned int nchannels = plugin->dst_format.channels;
- bitset_t bs[bitset_size(nchannels)];
- bitset_t *dstmask = bs;
- bitset_t *srcmask;
+ DECLARE_BITMAP(bs, nchannels);
+ unsigned long *dstmask = bs;
+ unsigned long *srcmask;
int err;
unsigned int channel;
for (channel = 0; channel < nchannels; channel++) {
if (client_channels[channel].enabled)
- bitset_set(dstmask, channel);
+ set_bit(channel, dstmask);
else
- bitset_reset(dstmask, channel);
+ clear_bit(channel, dstmask);
}
while (plugin) {
err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
@@ -730,16 +730,16 @@ static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug,
plugin = snd_pcm_plug_first(plug);
nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; channel++) {
- if (!bitset_get(dstmask, channel))
+ if (!test_bit(channel, dstmask))
src_channels[channel].enabled = 0;
}
return 0;
}
-snd_pcm_sframes_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size)
{
- snd_pcm_plugin_t *plugin, *next;
- snd_pcm_plugin_channel_t *dst_channels;
+ struct snd_pcm_plugin *plugin, *next;
+ struct snd_pcm_plugin_channel *dst_channels;
int err;
snd_pcm_sframes_t frames = size;
@@ -771,10 +771,10 @@ snd_pcm_sframes_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plug
return snd_pcm_plug_client_size(plug, frames);
}
-snd_pcm_sframes_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size)
{
- snd_pcm_plugin_t *plugin, *next;
- snd_pcm_plugin_channel_t *src_channels, *dst_channels;
+ struct snd_pcm_plugin *plugin, *next;
+ struct snd_pcm_plugin_channel *src_channels, *dst_channels;
snd_pcm_sframes_t frames = size;
int err;
@@ -806,7 +806,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugi
return frames;
}
-int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offset,
+int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
size_t samples, int format)
{
/* FIXME: sub byte resolution and odd dst_offset */
@@ -852,8 +852,8 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offs
return 0;
}
-int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,
- const snd_pcm_channel_area_t *dst_area, size_t dst_offset,
+int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
+ const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
size_t samples, int format)
{
/* FIXME: sub byte resolution and odd dst_offset */
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 0f86ce477490..29198da615cd 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -22,214 +22,164 @@
*
*/
-#ifndef ATTRIBUTE_UNUSED
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-#endif
-
-typedef unsigned int bitset_t;
-
-static inline size_t bitset_size(int nbits)
-{
- return (nbits + sizeof(bitset_t) * 8 - 1) / (sizeof(bitset_t) * 8);
-}
-
-static inline bitset_t *bitset_alloc(int nbits)
-{
- return kcalloc(bitset_size(nbits), sizeof(bitset_t), GFP_KERNEL);
-}
-
-static inline void bitset_set(bitset_t *bitmap, unsigned int pos)
-{
- size_t bits = sizeof(*bitmap) * 8;
- bitmap[pos / bits] |= 1 << (pos % bits);
-}
+#include <linux/bitmap.h>
-static inline void bitset_reset(bitset_t *bitmap, unsigned int pos)
+static inline unsigned long *bitmap_alloc(unsigned int nbits)
{
- size_t bits = sizeof(*bitmap) * 8;
- bitmap[pos / bits] &= ~(1 << (pos % bits));
+ return kmalloc(BITS_TO_LONGS(nbits), GFP_KERNEL);
}
-static inline int bitset_get(bitset_t *bitmap, unsigned int pos)
-{
- size_t bits = sizeof(*bitmap) * 8;
- return !!(bitmap[pos / bits] & (1 << (pos % bits)));
-}
-
-static inline void bitset_copy(bitset_t *dst, bitset_t *src, unsigned int nbits)
-{
- memcpy(dst, src, bitset_size(nbits) * sizeof(bitset_t));
-}
-
-static inline void bitset_and(bitset_t *dst, bitset_t *bs, unsigned int nbits)
-{
- bitset_t *end = dst + bitset_size(nbits);
- while (dst < end)
- *dst++ &= *bs++;
-}
-
-static inline void bitset_or(bitset_t *dst, bitset_t *bs, unsigned int nbits)
-{
- bitset_t *end = dst + bitset_size(nbits);
- while (dst < end)
- *dst++ |= *bs++;
-}
-
-static inline void bitset_zero(bitset_t *dst, unsigned int nbits)
-{
- bitset_t *end = dst + bitset_size(nbits);
- while (dst < end)
- *dst++ = 0;
-}
-
-static inline void bitset_one(bitset_t *dst, unsigned int nbits)
-{
- bitset_t *end = dst + bitset_size(nbits);
- while (dst < end)
- *dst++ = ~(bitset_t)0;
-}
-
-#define snd_pcm_plug_t snd_pcm_substream_t
#define snd_pcm_plug_stream(plug) ((plug)->stream)
-typedef enum {
+enum snd_pcm_plugin_action {
INIT = 0,
PREPARE = 1,
-} snd_pcm_plugin_action_t;
+};
-typedef struct _snd_pcm_channel_area {
+struct snd_pcm_channel_area {
void *addr; /* base address of channel samples */
unsigned int first; /* offset to first sample in bits */
unsigned int step; /* samples distance in bits */
-} snd_pcm_channel_area_t;
+};
-typedef struct _snd_pcm_plugin_channel {
+struct snd_pcm_plugin_channel {
void *aptr; /* pointer to the allocated area */
- snd_pcm_channel_area_t area;
+ struct snd_pcm_channel_area area;
snd_pcm_uframes_t frames; /* allocated frames */
unsigned int enabled:1; /* channel need to be processed */
unsigned int wanted:1; /* channel is wanted */
-} snd_pcm_plugin_channel_t;
+};
-typedef struct _snd_pcm_plugin_format {
+struct snd_pcm_plugin_format {
int format;
unsigned int rate;
unsigned int channels;
-} snd_pcm_plugin_format_t;
+};
-struct _snd_pcm_plugin {
+struct snd_pcm_plugin {
const char *name; /* plug-in name */
int stream;
- snd_pcm_plugin_format_t src_format; /* source format */
- snd_pcm_plugin_format_t dst_format; /* destination format */
+ struct snd_pcm_plugin_format src_format; /* source format */
+ struct snd_pcm_plugin_format dst_format; /* destination format */
int src_width; /* sample width in bits */
int dst_width; /* sample width in bits */
int access;
- snd_pcm_sframes_t (*src_frames)(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t dst_frames);
- snd_pcm_sframes_t (*dst_frames)(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t src_frames);
- snd_pcm_sframes_t (*client_channels)(snd_pcm_plugin_t *plugin,
- snd_pcm_uframes_t frames,
- snd_pcm_plugin_channel_t **channels);
- int (*src_channels_mask)(snd_pcm_plugin_t *plugin,
- bitset_t *dst_vmask,
- bitset_t **src_vmask);
- int (*dst_channels_mask)(snd_pcm_plugin_t *plugin,
- bitset_t *src_vmask,
- bitset_t **dst_vmask);
- snd_pcm_sframes_t (*transfer)(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
- snd_pcm_uframes_t frames);
- int (*action)(snd_pcm_plugin_t *plugin,
- snd_pcm_plugin_action_t action,
+ snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames);
+ snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames);
+ snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
+ snd_pcm_uframes_t frames,
+ struct snd_pcm_plugin_channel **channels);
+ int (*src_channels_mask)(struct snd_pcm_plugin *plugin,
+ unsigned long *dst_vmask,
+ unsigned long **src_vmask);
+ int (*dst_channels_mask)(struct snd_pcm_plugin *plugin,
+ unsigned long *src_vmask,
+ unsigned long **dst_vmask);
+ snd_pcm_sframes_t (*transfer)(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
+ snd_pcm_uframes_t frames);
+ int (*action)(struct snd_pcm_plugin *plugin,
+ enum snd_pcm_plugin_action action,
unsigned long data);
- snd_pcm_plugin_t *prev;
- snd_pcm_plugin_t *next;
- snd_pcm_plug_t *plug;
+ struct snd_pcm_plugin *prev;
+ struct snd_pcm_plugin *next;
+ struct snd_pcm_substream *plug;
void *private_data;
- void (*private_free)(snd_pcm_plugin_t *plugin);
+ void (*private_free)(struct snd_pcm_plugin *plugin);
char *buf;
snd_pcm_uframes_t buf_frames;
- snd_pcm_plugin_channel_t *buf_channels;
- bitset_t *src_vmask;
- bitset_t *dst_vmask;
+ struct snd_pcm_plugin_channel *buf_channels;
+ unsigned long *src_vmask;
+ unsigned long *dst_vmask;
char extra_data[0];
};
-int snd_pcm_plugin_build(snd_pcm_plug_t *handle,
+int snd_pcm_plugin_build(struct snd_pcm_substream *handle,
const char *name,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
size_t extra,
- snd_pcm_plugin_t **ret);
-int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin);
-int snd_pcm_plugin_clear(snd_pcm_plugin_t **first);
-int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_plug_client_size(snd_pcm_plug_t *handle, snd_pcm_uframes_t drv_size);
-snd_pcm_sframes_t snd_pcm_plug_slave_size(snd_pcm_plug_t *handle, snd_pcm_uframes_t clt_size);
+ struct snd_pcm_plugin **ret);
+int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin);
+int snd_pcm_plugin_clear(struct snd_pcm_plugin **first);
+int snd_pcm_plug_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t frames);
+snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size);
+snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size);
#define FULL ROUTE_PLUGIN_RESOLUTION
#define HALF ROUTE_PLUGIN_RESOLUTION / 2
-typedef int route_ttable_entry_t;
-
-int snd_pcm_plugin_build_io(snd_pcm_plug_t *handle,
- snd_pcm_hw_params_t *params,
- snd_pcm_plugin_t **r_plugin);
-int snd_pcm_plugin_build_linear(snd_pcm_plug_t *handle,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin);
-int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *handle,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin);
-int snd_pcm_plugin_build_rate(snd_pcm_plug_t *handle,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin);
-int snd_pcm_plugin_build_route(snd_pcm_plug_t *handle,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- route_ttable_entry_t *ttable,
- snd_pcm_plugin_t **r_plugin);
-int snd_pcm_plugin_build_copy(snd_pcm_plug_t *handle,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin);
-
-int snd_pcm_plug_format_plugins(snd_pcm_plug_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *slave_params);
-
-int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask);
-
-int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin);
-
-snd_pcm_sframes_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *handle, snd_pcm_plugin_channel_t *src_channels, snd_pcm_uframes_t size);
-snd_pcm_sframes_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *handle, snd_pcm_plugin_channel_t *dst_channels_final, snd_pcm_uframes_t size);
-
-snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *handle,
- char *buf, snd_pcm_uframes_t count,
- snd_pcm_plugin_channel_t **channels);
-
-snd_pcm_sframes_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin,
- snd_pcm_uframes_t frames,
- snd_pcm_plugin_channel_t **channels);
-
-int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset,
+
+int snd_pcm_plugin_build_io(struct snd_pcm_substream *handle,
+ struct snd_pcm_hw_params *params,
+ struct snd_pcm_plugin **r_plugin);
+int snd_pcm_plugin_build_linear(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin);
+int snd_pcm_plugin_build_mulaw(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin);
+int snd_pcm_plugin_build_rate(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin);
+int snd_pcm_plugin_build_route(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ int *ttable,
+ struct snd_pcm_plugin **r_plugin);
+int snd_pcm_plugin_build_copy(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin);
+
+int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_params *slave_params);
+
+int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask);
+
+int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
+
+snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_channel *src_channels,
+ snd_pcm_uframes_t size);
+snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *handle,
+ struct snd_pcm_plugin_channel *dst_channels_final,
+ snd_pcm_uframes_t size);
+
+snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(struct snd_pcm_substream *handle,
+ char *buf, snd_pcm_uframes_t count,
+ struct snd_pcm_plugin_channel **channels);
+
+snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
+ snd_pcm_uframes_t frames,
+ struct snd_pcm_plugin_channel **channels);
+
+int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel,
+ size_t dst_offset,
size_t samples, int format);
-int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_channel, size_t src_offset,
- const snd_pcm_channel_area_t *dst_channel, size_t dst_offset,
+int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
+ size_t src_offset,
+ const struct snd_pcm_channel_area *dst_channel,
+ size_t dst_offset,
size_t samples, int format);
-void *snd_pcm_plug_buf_alloc(snd_pcm_plug_t *plug, snd_pcm_uframes_t size);
-void snd_pcm_plug_buf_unlock(snd_pcm_plug_t *plug, void *ptr);
-snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t size, int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t size, int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_writev3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel);
-snd_pcm_sframes_t snd_pcm_oss_readv3(snd_pcm_substream_t *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel);
-
-
+void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
+void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
+snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
+ const char *ptr, snd_pcm_uframes_t size,
+ int in_kernel);
+snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
+ char *ptr, snd_pcm_uframes_t size, int in_kernel);
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
+ void **bufs, snd_pcm_uframes_t frames,
+ int in_kernel);
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
+ void **bufs, snd_pcm_uframes_t frames,
+ int in_kernel);
#define ROUTE_PLUGIN_RESOLUTION 16
@@ -237,8 +187,8 @@ int getput_index(int format);
int copy_index(int format);
int conv_index(int src_format, int dst_format);
-void zero_channel(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *dst_channel,
+void zero_channel(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *dst_channel,
size_t samples);
#ifdef PLUGIN_DEBUG
diff --git a/sound/core/oss/rate.c b/sound/core/oss/rate.c
index 1096ec186714..4854cef6fb4f 100644
--- a/sound/core/oss/rate.c
+++ b/sound/core/oss/rate.c
@@ -33,29 +33,29 @@
* Basic rate conversion plugin
*/
-typedef struct {
+struct rate_channel {
signed short last_S1;
signed short last_S2;
-} rate_channel_t;
+};
-typedef void (*rate_f)(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+typedef void (*rate_f)(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
int src_frames, int dst_frames);
-typedef struct rate_private_data {
+struct rate_priv {
unsigned int pitch;
unsigned int pos;
rate_f func;
int get, put;
snd_pcm_sframes_t old_src_frames, old_dst_frames;
- rate_channel_t channels[0];
-} rate_t;
+ struct rate_channel channels[0];
+};
-static void rate_init(snd_pcm_plugin_t *plugin)
+static void rate_init(struct snd_pcm_plugin *plugin)
{
unsigned int channel;
- rate_t *data = (rate_t *)plugin->extra_data;
+ struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
data->pos = 0;
for (channel = 0; channel < plugin->src_format.channels; channel++) {
data->channels[channel].last_S1 = 0;
@@ -63,9 +63,9 @@ static void rate_init(snd_pcm_plugin_t *plugin)
}
}
-static void resample_expand(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static void resample_expand(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
int src_frames, int dst_frames)
{
unsigned int pos = 0;
@@ -75,8 +75,8 @@ static void resample_expand(snd_pcm_plugin_t *plugin,
unsigned int channel;
int src_step, dst_step;
int src_frames1, dst_frames1;
- rate_t *data = (rate_t *)plugin->extra_data;
- rate_channel_t *rchannels = data->channels;
+ struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
+ struct rate_channel *rchannels = data->channels;
#define GET_S16_LABELS
#define PUT_S16_LABELS
@@ -139,9 +139,9 @@ static void resample_expand(snd_pcm_plugin_t *plugin,
data->pos = pos;
}
-static void resample_shrink(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static void resample_shrink(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
int src_frames, int dst_frames)
{
unsigned int pos = 0;
@@ -151,8 +151,8 @@ static void resample_shrink(snd_pcm_plugin_t *plugin,
unsigned int channel;
int src_step, dst_step;
int src_frames1, dst_frames1;
- rate_t *data = (rate_t *)plugin->extra_data;
- rate_channel_t *rchannels = data->channels;
+ struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
+ struct rate_channel *rchannels = data->channels;
#define GET_S16_LABELS
#define PUT_S16_LABELS
@@ -216,15 +216,15 @@ static void resample_shrink(snd_pcm_plugin_t *plugin,
data->pos = pos;
}
-static snd_pcm_sframes_t rate_src_frames(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
{
- rate_t *data;
+ struct rate_priv *data;
snd_pcm_sframes_t res;
snd_assert(plugin != NULL, return -ENXIO);
if (frames == 0)
return 0;
- data = (rate_t *)plugin->extra_data;
+ data = (struct rate_priv *)plugin->extra_data;
if (plugin->src_format.rate < plugin->dst_format.rate) {
res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
} else {
@@ -248,15 +248,15 @@ static snd_pcm_sframes_t rate_src_frames(snd_pcm_plugin_t *plugin, snd_pcm_ufram
return res;
}
-static snd_pcm_sframes_t rate_dst_frames(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t frames)
{
- rate_t *data;
+ struct rate_priv *data;
snd_pcm_sframes_t res;
snd_assert(plugin != NULL, return -ENXIO);
if (frames == 0)
return 0;
- data = (rate_t *)plugin->extra_data;
+ data = (struct rate_priv *)plugin->extra_data;
if (plugin->src_format.rate < plugin->dst_format.rate) {
res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
} else {
@@ -280,13 +280,13 @@ static snd_pcm_sframes_t rate_dst_frames(snd_pcm_plugin_t *plugin, snd_pcm_ufram
return res;
}
-static snd_pcm_sframes_t rate_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t rate_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
snd_pcm_uframes_t dst_frames;
- rate_t *data;
+ struct rate_priv *data;
snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
if (frames == 0)
@@ -308,14 +308,14 @@ static snd_pcm_sframes_t rate_transfer(snd_pcm_plugin_t *plugin,
dst_frames = rate_dst_frames(plugin, frames);
if (dst_frames > dst_channels[0].frames)
dst_frames = dst_channels[0].frames;
- data = (rate_t *)plugin->extra_data;
+ data = (struct rate_priv *)plugin->extra_data;
data->func(plugin, src_channels, dst_channels, frames, dst_frames);
return dst_frames;
}
-static int rate_action(snd_pcm_plugin_t *plugin,
- snd_pcm_plugin_action_t action,
- unsigned long udata ATTRIBUTE_UNUSED)
+static int rate_action(struct snd_pcm_plugin *plugin,
+ enum snd_pcm_plugin_action action,
+ unsigned long udata)
{
snd_assert(plugin != NULL, return -ENXIO);
switch (action) {
@@ -329,14 +329,14 @@ static int rate_action(snd_pcm_plugin_t *plugin,
return 0; /* silenty ignore other actions */
}
-int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_rate(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ struct snd_pcm_plugin **r_plugin)
{
int err;
- rate_t *data;
- snd_pcm_plugin_t *plugin;
+ struct rate_priv *data;
+ struct snd_pcm_plugin *plugin;
snd_assert(r_plugin != NULL, return -ENXIO);
*r_plugin = NULL;
@@ -349,11 +349,12 @@ int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug,
err = snd_pcm_plugin_build(plug, "rate conversion",
src_format, dst_format,
- sizeof(rate_t) + src_format->channels * sizeof(rate_channel_t),
+ sizeof(struct rate_priv) +
+ src_format->channels * sizeof(struct rate_channel),
&plugin);
if (err < 0)
return err;
- data = (rate_t *)plugin->extra_data;
+ data = (struct rate_priv *)plugin->extra_data;
data->get = getput_index(src_format->format);
snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
data->put = getput_index(dst_format->format);
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index c955b7dfdb30..726c5caa3fdb 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -35,61 +35,62 @@
#error "Add some code here"
#endif
-typedef struct ttable_dst ttable_dst_t;
-typedef struct route_private_data route_t;
+struct ttable_dst;
-typedef void (*route_channel_f)(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channel,
- ttable_dst_t* ttable, snd_pcm_uframes_t frames);
+typedef void (*route_channel_f)(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channel,
+ struct ttable_dst *ttable, snd_pcm_uframes_t frames);
-typedef struct {
+struct ttable_src {
int channel;
int as_int;
-} ttable_src_t;
+};
struct ttable_dst {
int att; /* Attenuated */
unsigned int nsrcs;
- ttable_src_t* srcs;
+ struct ttable_src *srcs;
route_channel_f func;
};
-struct route_private_data {
+struct route_priv {
enum {R_UINT32=0, R_UINT64=1} sum_type;
int get, put;
int conv;
int src_sample_size;
- ttable_dst_t ttable[0];
+ struct ttable_dst ttable[0];
};
-typedef union {
+union sum {
u_int32_t as_uint32;
u_int64_t as_uint64;
-} sum_t;
+};
-static void route_to_channel_from_zero(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels ATTRIBUTE_UNUSED,
- snd_pcm_plugin_channel_t *dst_channel,
- ttable_dst_t* ttable ATTRIBUTE_UNUSED, snd_pcm_uframes_t frames)
+static void route_to_channel_from_zero(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channel,
+ struct ttable_dst *ttable,
+ snd_pcm_uframes_t frames)
{
if (dst_channel->wanted)
snd_pcm_area_silence(&dst_channel->area, 0, frames, plugin->dst_format.format);
dst_channel->enabled = 0;
}
-static void route_to_channel_from_one(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channel,
- ttable_dst_t* ttable, snd_pcm_uframes_t frames)
+static void route_to_channel_from_one(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channel,
+ struct ttable_dst *ttable,
+ snd_pcm_uframes_t frames)
{
#define CONV_LABELS
#include "plugin_ops.h"
#undef CONV_LABELS
- route_t *data = (route_t *)plugin->extra_data;
+ struct route_priv *data = (struct route_priv *)plugin->extra_data;
void *conv;
- const snd_pcm_plugin_channel_t *src_channel = NULL;
+ const struct snd_pcm_plugin_channel *src_channel = NULL;
unsigned int srcidx;
char *src, *dst;
int src_step, dst_step;
@@ -120,10 +121,10 @@ static void route_to_channel_from_one(snd_pcm_plugin_t *plugin,
}
}
-static void route_to_channel(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channel,
- ttable_dst_t* ttable, snd_pcm_uframes_t frames)
+static void route_to_channel(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channel,
+ struct ttable_dst *ttable, snd_pcm_uframes_t frames)
{
#define GET_U_LABELS
#define PUT_U32_LABELS
@@ -153,18 +154,18 @@ static void route_to_channel(snd_pcm_plugin_t *plugin,
&&norm_int64_16_att,
&&norm_int64_24_att,
};
- route_t *data = (route_t *)plugin->extra_data;
+ struct route_priv *data = (struct route_priv *)plugin->extra_data;
void *zero, *get, *add, *norm, *put_u32;
int nsrcs = ttable->nsrcs;
char *dst;
int dst_step;
char *srcs[nsrcs];
int src_steps[nsrcs];
- ttable_src_t src_tt[nsrcs];
+ struct ttable_src src_tt[nsrcs];
u_int32_t sample = 0;
int srcidx, srcidx1 = 0;
for (srcidx = 0; srcidx < nsrcs; ++srcidx) {
- const snd_pcm_plugin_channel_t *src_channel = &src_channels[ttable->srcs[srcidx].channel];
+ const struct snd_pcm_plugin_channel *src_channel = &src_channels[ttable->srcs[srcidx].channel];
if (!src_channel->enabled)
continue;
srcs[srcidx1] = src_channel->area.addr + src_channel->area.first / 8;
@@ -191,8 +192,8 @@ static void route_to_channel(snd_pcm_plugin_t *plugin,
dst_step = dst_channel->area.step / 8;
while (frames-- > 0) {
- ttable_src_t *ttp = src_tt;
- sum_t sum;
+ struct ttable_src *ttp = src_tt;
+ union sum sum;
/* Zero sum */
goto *zero;
@@ -297,47 +298,47 @@ static void route_to_channel(snd_pcm_plugin_t *plugin,
}
}
-static int route_src_channels_mask(snd_pcm_plugin_t *plugin,
- bitset_t *dst_vmask,
- bitset_t **src_vmask)
+static int route_src_channels_mask(struct snd_pcm_plugin *plugin,
+ unsigned long *dst_vmask,
+ unsigned long **src_vmask)
{
- route_t *data = (route_t *)plugin->extra_data;
+ struct route_priv *data = (struct route_priv *)plugin->extra_data;
int schannels = plugin->src_format.channels;
int dchannels = plugin->dst_format.channels;
- bitset_t *vmask = plugin->src_vmask;
+ unsigned long *vmask = plugin->src_vmask;
int channel;
- ttable_dst_t *dp = data->ttable;
- bitset_zero(vmask, schannels);
+ struct ttable_dst *dp = data->ttable;
+ bitmap_zero(vmask, schannels);
for (channel = 0; channel < dchannels; channel++, dp++) {
unsigned int src;
- ttable_src_t *sp;
- if (!bitset_get(dst_vmask, channel))
+ struct ttable_src *sp;
+ if (!test_bit(channel, dst_vmask))
continue;
sp = dp->srcs;
for (src = 0; src < dp->nsrcs; src++, sp++)
- bitset_set(vmask, sp->channel);
+ set_bit(sp->channel, vmask);
}
*src_vmask = vmask;
return 0;
}
-static int route_dst_channels_mask(snd_pcm_plugin_t *plugin,
- bitset_t *src_vmask,
- bitset_t **dst_vmask)
+static int route_dst_channels_mask(struct snd_pcm_plugin *plugin,
+ unsigned long *src_vmask,
+ unsigned long **dst_vmask)
{
- route_t *data = (route_t *)plugin->extra_data;
+ struct route_priv *data = (struct route_priv *)plugin->extra_data;
int dchannels = plugin->dst_format.channels;
- bitset_t *vmask = plugin->dst_vmask;
+ unsigned long *vmask = plugin->dst_vmask;
int channel;
- ttable_dst_t *dp = data->ttable;
- bitset_zero(vmask, dchannels);
+ struct ttable_dst *dp = data->ttable;
+ bitmap_zero(vmask, dchannels);
for (channel = 0; channel < dchannels; channel++, dp++) {
unsigned int src;
- ttable_src_t *sp;
+ struct ttable_src *sp;
sp = dp->srcs;
for (src = 0; src < dp->nsrcs; src++, sp++) {
- if (bitset_get(src_vmask, sp->channel)) {
- bitset_set(vmask, channel);
+ if (test_bit(sp->channel, src_vmask)) {
+ set_bit(channel, vmask);
break;
}
}
@@ -346,33 +347,33 @@ static int route_dst_channels_mask(snd_pcm_plugin_t *plugin,
return 0;
}
-static void route_free(snd_pcm_plugin_t *plugin)
+static void route_free(struct snd_pcm_plugin *plugin)
{
- route_t *data = (route_t *)plugin->extra_data;
+ struct route_priv *data = (struct route_priv *)plugin->extra_data;
unsigned int dst_channel;
for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
kfree(data->ttable[dst_channel].srcs);
}
}
-static int route_load_ttable(snd_pcm_plugin_t *plugin,
- const route_ttable_entry_t* src_ttable)
+static int route_load_ttable(struct snd_pcm_plugin *plugin,
+ const int *src_ttable)
{
- route_t *data;
+ struct route_priv *data;
unsigned int src_channel, dst_channel;
- const route_ttable_entry_t *sptr;
- ttable_dst_t *dptr;
+ const int *sptr;
+ struct ttable_dst *dptr;
if (src_ttable == NULL)
return 0;
- data = (route_t *)plugin->extra_data;
+ data = (struct route_priv *)plugin->extra_data;
dptr = data->ttable;
sptr = src_ttable;
plugin->private_free = route_free;
for (dst_channel = 0; dst_channel < plugin->dst_format.channels; ++dst_channel) {
- route_ttable_entry_t t = 0;
+ int t = 0;
int att = 0;
int nsrcs = 0;
- ttable_src_t srcs[plugin->src_format.channels];
+ struct ttable_src srcs[plugin->src_format.channels];
for (src_channel = 0; src_channel < plugin->src_format.channels; ++src_channel) {
snd_assert(*sptr >= 0 || *sptr <= FULL, return -ENXIO);
if (*sptr != 0) {
@@ -405,21 +406,21 @@ static int route_load_ttable(snd_pcm_plugin_t *plugin,
return 0;
}
-static snd_pcm_sframes_t route_transfer(snd_pcm_plugin_t *plugin,
- const snd_pcm_plugin_channel_t *src_channels,
- snd_pcm_plugin_channel_t *dst_channels,
+static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
+ const struct snd_pcm_plugin_channel *src_channels,
+ struct snd_pcm_plugin_channel *dst_channels,
snd_pcm_uframes_t frames)
{
- route_t *data;
+ struct route_priv *data;
int src_nchannels, dst_nchannels;
int dst_channel;
- ttable_dst_t *ttp;
- snd_pcm_plugin_channel_t *dvp;
+ struct ttable_dst *ttp;
+ struct snd_pcm_plugin_channel *dvp;
snd_assert(plugin != NULL && src_channels != NULL && dst_channels != NULL, return -ENXIO);
if (frames == 0)
return 0;
- data = (route_t *)plugin->extra_data;
+ data = (struct route_priv *)plugin->extra_data;
src_nchannels = plugin->src_format.channels;
dst_nchannels = plugin->dst_format.channels;
@@ -469,14 +470,14 @@ int getput_index(int format)
return width * 4 + endian * 2 + sign;
}
-int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug,
- snd_pcm_plugin_format_t *src_format,
- snd_pcm_plugin_format_t *dst_format,
- route_ttable_entry_t *ttable,
- snd_pcm_plugin_t **r_plugin)
+int snd_pcm_plugin_build_route(struct snd_pcm_substream *plug,
+ struct snd_pcm_plugin_format *src_format,
+ struct snd_pcm_plugin_format *dst_format,
+ int *ttable,
+ struct snd_pcm_plugin **r_plugin)
{
- route_t *data;
- snd_pcm_plugin_t *plugin;
+ struct route_priv *data;
+ struct snd_pcm_plugin *plugin;
int err;
snd_assert(r_plugin != NULL, return -ENXIO);
@@ -488,12 +489,13 @@ int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug,
err = snd_pcm_plugin_build(plug, "attenuated route conversion",
src_format, dst_format,
- sizeof(route_t) + sizeof(data->ttable[0]) * dst_format->channels,
+ sizeof(struct route_priv) +
+ sizeof(data->ttable[0]) * dst_format->channels,
&plugin);
if (err < 0)
return err;
- data = (route_t *) plugin->extra_data;
+ data = (struct route_priv *)plugin->extra_data;
data->get = getput_index(src_format->format);
snd_assert(data->get >= 0 && data->get < 4*2*2, return -EINVAL);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 184e74b75ba9..28ca61eb0b0d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -33,23 +33,33 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL");
-snd_pcm_t *snd_pcm_devices[SNDRV_CARDS * SNDRV_PCM_DEVICES];
+static LIST_HEAD(snd_pcm_devices);
static LIST_HEAD(snd_pcm_notify_list);
static DECLARE_MUTEX(register_mutex);
-static int snd_pcm_free(snd_pcm_t *pcm);
-static int snd_pcm_dev_free(snd_device_t *device);
-static int snd_pcm_dev_register(snd_device_t *device);
-static int snd_pcm_dev_disconnect(snd_device_t *device);
-static int snd_pcm_dev_unregister(snd_device_t *device);
+static int snd_pcm_free(struct snd_pcm *pcm);
+static int snd_pcm_dev_free(struct snd_device *device);
+static int snd_pcm_dev_register(struct snd_device *device);
+static int snd_pcm_dev_disconnect(struct snd_device *device);
+static int snd_pcm_dev_unregister(struct snd_device *device);
-static int snd_pcm_control_ioctl(snd_card_t * card,
- snd_ctl_file_t * control,
- unsigned int cmd, unsigned long arg)
+static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
{
- unsigned int tmp;
+ struct list_head *p;
+ struct snd_pcm *pcm;
+
+ list_for_each(p, &snd_pcm_devices) {
+ pcm = list_entry(p, struct snd_pcm, list);
+ if (pcm->card == card && pcm->device == device)
+ return pcm;
+ }
+ return NULL;
+}
- tmp = card->number * SNDRV_PCM_DEVICES;
+static int snd_pcm_control_ioctl(struct snd_card *card,
+ struct snd_ctl_file *control,
+ unsigned int cmd, unsigned long arg)
+{
switch (cmd) {
case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
{
@@ -57,51 +67,66 @@ static int snd_pcm_control_ioctl(snd_card_t * card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
+ down(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_PCM_DEVICES) {
- if (snd_pcm_devices[tmp + device])
+ if (snd_pcm_search(card, device))
break;
device++;
}
if (device == SNDRV_PCM_DEVICES)
device = -1;
+ up(&register_mutex);
if (put_user(device, (int __user *)arg))
return -EFAULT;
return 0;
}
case SNDRV_CTL_IOCTL_PCM_INFO:
{
- snd_pcm_info_t __user *info;
+ struct snd_pcm_info __user *info;
unsigned int device, subdevice;
- snd_pcm_stream_t stream;
- snd_pcm_t *pcm;
- snd_pcm_str_t *pstr;
- snd_pcm_substream_t *substream;
- info = (snd_pcm_info_t __user *)arg;
+ int stream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_str *pstr;
+ struct snd_pcm_substream *substream;
+ int err;
+
+ info = (struct snd_pcm_info __user *)arg;
if (get_user(device, &info->device))
return -EFAULT;
- if (device >= SNDRV_PCM_DEVICES)
- return -ENXIO;
- pcm = snd_pcm_devices[tmp + device];
- if (pcm == NULL)
- return -ENXIO;
if (get_user(stream, &info->stream))
return -EFAULT;
if (stream < 0 || stream > 1)
return -EINVAL;
- pstr = &pcm->streams[stream];
- if (pstr->substream_count == 0)
- return -ENOENT;
if (get_user(subdevice, &info->subdevice))
return -EFAULT;
- if (subdevice >= pstr->substream_count)
- return -ENXIO;
- for (substream = pstr->substream; substream; substream = substream->next)
+ down(&register_mutex);
+ pcm = snd_pcm_search(card, device);
+ if (pcm == NULL) {
+ err = -ENXIO;
+ goto _error;
+ }
+ pstr = &pcm->streams[stream];
+ if (pstr->substream_count == 0) {
+ err = -ENOENT;
+ goto _error;
+ }
+ if (subdevice >= pstr->substream_count) {
+ err = -ENXIO;
+ goto _error;
+ }
+ for (substream = pstr->substream; substream;
+ substream = substream->next)
if (substream->number == (int)subdevice)
break;
- if (substream == NULL)
- return -ENXIO;
- return snd_pcm_info_user(substream, info);
+ if (substream == NULL) {
+ err = -ENXIO;
+ goto _error;
+ }
+ err = snd_pcm_info_user(substream, info);
+ _error:
+ up(&register_mutex);
+ return err;
}
case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
{
@@ -126,30 +151,6 @@ static int snd_pcm_control_ioctl(snd_card_t * card,
#define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v
-static char *snd_pcm_stream_names[] = {
- STREAM(PLAYBACK),
- STREAM(CAPTURE),
-};
-
-static char *snd_pcm_state_names[] = {
- STATE(OPEN),
- STATE(SETUP),
- STATE(PREPARED),
- STATE(RUNNING),
- STATE(XRUN),
- STATE(DRAINING),
- STATE(PAUSED),
- STATE(SUSPENDED),
-};
-
-static char *snd_pcm_access_names[] = {
- ACCESS(MMAP_INTERLEAVED),
- ACCESS(MMAP_NONINTERLEAVED),
- ACCESS(MMAP_COMPLEX),
- ACCESS(RW_INTERLEAVED),
- ACCESS(RW_NONINTERLEAVED),
-};
-
static char *snd_pcm_format_names[] = {
FORMAT(S8),
FORMAT(U8),
@@ -191,6 +192,36 @@ static char *snd_pcm_format_names[] = {
FORMAT(U18_3BE),
};
+const char *snd_pcm_format_name(snd_pcm_format_t format)
+{
+ return snd_pcm_format_names[format];
+}
+
+#ifdef CONFIG_PROC_FS
+static char *snd_pcm_stream_names[] = {
+ STREAM(PLAYBACK),
+ STREAM(CAPTURE),
+};
+
+static char *snd_pcm_state_names[] = {
+ STATE(OPEN),
+ STATE(SETUP),
+ STATE(PREPARED),
+ STATE(RUNNING),
+ STATE(XRUN),
+ STATE(DRAINING),
+ STATE(PAUSED),
+ STATE(SUSPENDED),
+};
+
+static char *snd_pcm_access_names[] = {
+ ACCESS(MMAP_INTERLEAVED),
+ ACCESS(MMAP_NONINTERLEAVED),
+ ACCESS(MMAP_COMPLEX),
+ ACCESS(RW_INTERLEAVED),
+ ACCESS(RW_NONINTERLEAVED),
+};
+
static char *snd_pcm_subformat_names[] = {
SUBFORMAT(STD),
};
@@ -200,7 +231,7 @@ static char *snd_pcm_tstamp_mode_names[] = {
TSTAMP(MMAP),
};
-static const char *snd_pcm_stream_name(snd_pcm_stream_t stream)
+static const char *snd_pcm_stream_name(int stream)
{
snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL);
return snd_pcm_stream_names[stream];
@@ -208,23 +239,15 @@ static const char *snd_pcm_stream_name(snd_pcm_stream_t stream)
static const char *snd_pcm_access_name(snd_pcm_access_t access)
{
- snd_assert(access <= SNDRV_PCM_ACCESS_LAST, return NULL);
return snd_pcm_access_names[access];
}
-const char *snd_pcm_format_name(snd_pcm_format_t format)
-{
- snd_assert(format <= SNDRV_PCM_FORMAT_LAST, return NULL);
- return snd_pcm_format_names[format];
-}
-
static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
{
- snd_assert(subformat <= SNDRV_PCM_SUBFORMAT_LAST, return NULL);
return snd_pcm_subformat_names[subformat];
}
-static const char *snd_pcm_tstamp_mode_name(snd_pcm_tstamp_t mode)
+static const char *snd_pcm_tstamp_mode_name(int mode)
{
snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL);
return snd_pcm_tstamp_mode_names[mode];
@@ -232,7 +255,6 @@ static const char *snd_pcm_tstamp_mode_name(snd_pcm_tstamp_t mode)
static const char *snd_pcm_state_name(snd_pcm_state_t state)
{
- snd_assert(state <= SNDRV_PCM_STATE_LAST, return NULL);
return snd_pcm_state_names[state];
}
@@ -267,10 +289,10 @@ static const char *snd_pcm_oss_format_name(int format)
}
#endif
-#ifdef CONFIG_PROC_FS
-static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buffer_t *buffer)
+static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_info_t *info;
+ struct snd_pcm_info *info;
int err;
if (! substream)
@@ -302,20 +324,25 @@ static void snd_pcm_proc_info_read(snd_pcm_substream_t *substream, snd_info_buff
kfree(info);
}
-static void snd_pcm_stream_proc_info_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_proc_info_read(((snd_pcm_str_t *)entry->private_data)->substream, buffer);
+ snd_pcm_proc_info_read(((struct snd_pcm_str *)entry->private_data)->substream,
+ buffer);
}
-static void snd_pcm_substream_proc_info_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_proc_info_read((snd_pcm_substream_t *)entry->private_data, buffer);
+ snd_pcm_proc_info_read((struct snd_pcm_substream *)entry->private_data,
+ buffer);
}
-static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_substream *substream = entry->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
return;
@@ -347,10 +374,11 @@ static void snd_pcm_substream_proc_hw_params_read(snd_info_entry_t *entry, snd_i
snd_pcm_stream_unlock_irq(substream);
}
-static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_substream *substream = entry->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
return;
@@ -374,11 +402,12 @@ static void snd_pcm_substream_proc_sw_params_read(snd_info_entry_t *entry, snd_i
snd_pcm_stream_unlock_irq(substream);
}
-static void snd_pcm_substream_proc_status_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_status_t status;
+ struct snd_pcm_substream *substream = entry->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_status status;
int err;
if (!runtime) {
snd_iprintf(buffer, "closed\n");
@@ -402,28 +431,29 @@ static void snd_pcm_substream_proc_status_read(snd_info_entry_t *entry, snd_info
snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
}
-#endif
#ifdef CONFIG_SND_DEBUG
-static void snd_pcm_xrun_debug_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
+ struct snd_pcm_str *pstr = entry->private_data;
snd_iprintf(buffer, "%d\n", pstr->xrun_debug);
}
-static void snd_pcm_xrun_debug_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_pcm_xrun_debug_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
+ struct snd_pcm_str *pstr = entry->private_data;
char line[64];
if (!snd_info_get_line(buffer, line, sizeof(line)))
pstr->xrun_debug = simple_strtoul(line, NULL, 10);
}
#endif
-static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
+static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
{
- snd_pcm_t *pcm = pstr->pcm;
- snd_info_entry_t *entry;
+ struct snd_pcm *pcm = pstr->pcm;
+ struct snd_info_entry *entry;
char name[16];
sprintf(name, "pcm%i%c", pcm->device,
@@ -447,7 +477,8 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
pstr->proc_info_entry = entry;
#ifdef CONFIG_SND_DEBUG
- if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", pstr->proc_root)) != NULL) {
+ if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
+ pstr->proc_root)) != NULL) {
entry->c.text.read_size = 64;
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write_size = 64;
@@ -464,7 +495,7 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
return 0;
}
-static int snd_pcm_stream_proc_done(snd_pcm_str_t *pstr)
+static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
#ifdef CONFIG_SND_DEBUG
if (pstr->proc_xrun_debug_entry) {
@@ -483,10 +514,10 @@ static int snd_pcm_stream_proc_done(snd_pcm_str_t *pstr)
return 0;
}
-static int snd_pcm_substream_proc_init(snd_pcm_substream_t *substream)
+static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
{
- snd_info_entry_t *entry;
- snd_card_t *card;
+ struct snd_info_entry *entry;
+ struct snd_card *card;
char name[16];
card = substream->pcm->card;
@@ -540,7 +571,7 @@ static int snd_pcm_substream_proc_init(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_pcm_substream_proc_done(snd_pcm_substream_t *substream)
+static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
{
if (substream->proc_info_entry) {
snd_info_unregister(substream->proc_info_entry);
@@ -564,6 +595,12 @@ static int snd_pcm_substream_proc_done(snd_pcm_substream_t *substream)
}
return 0;
}
+#else /* !CONFIG_PROC_FS */
+static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
+static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
+static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
+static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
+#endif /* CONFIG_PROC_FS */
/**
* snd_pcm_new_stream - create a new PCM stream
@@ -578,11 +615,11 @@ static int snd_pcm_substream_proc_done(snd_pcm_substream_t *substream)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
+int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
{
int idx, err;
- snd_pcm_str_t *pstr = &pcm->streams[stream];
- snd_pcm_substream_t *substream, *prev;
+ struct snd_pcm_str *pstr = &pcm->streams[stream];
+ struct snd_pcm_substream *substream, *prev;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
init_MUTEX(&pstr->oss.setup_mutex);
@@ -590,17 +627,20 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
pstr->stream = stream;
pstr->pcm = pcm;
pstr->substream_count = substream_count;
- pstr->reg = &snd_pcm_reg[stream];
if (substream_count > 0) {
err = snd_pcm_stream_proc_init(pstr);
- if (err < 0)
+ if (err < 0) {
+ snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
return err;
+ }
}
prev = NULL;
for (idx = 0, prev = NULL; idx < substream_count; idx++) {
substream = kzalloc(sizeof(*substream), GFP_KERNEL);
- if (substream == NULL)
+ if (substream == NULL) {
+ snd_printk(KERN_ERR "Cannot allocate PCM substream\n");
return -ENOMEM;
+ }
substream->pcm = pcm;
substream->pstr = pstr;
substream->number = idx;
@@ -613,6 +653,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
prev->next = substream;
err = snd_pcm_substream_proc_init(substream);
if (err < 0) {
+ snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
kfree(substream);
return err;
}
@@ -642,13 +683,13 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_new(snd_card_t * card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, char *id, int device,
int playback_count, int capture_count,
- snd_pcm_t ** rpcm)
+ struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_pcm_dev_free,
.dev_register = snd_pcm_dev_register,
.dev_disconnect = snd_pcm_dev_disconnect,
@@ -659,13 +700,14 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
*rpcm = NULL;
snd_assert(card != NULL, return -ENXIO);
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
- if (pcm == NULL)
+ if (pcm == NULL) {
+ snd_printk(KERN_ERR "Cannot allocate PCM\n");
return -ENOMEM;
+ }
pcm->card = card;
pcm->device = device;
- if (id) {
+ if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
- }
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
snd_pcm_free(pcm);
return err;
@@ -684,11 +726,11 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
return 0;
}
-static void snd_pcm_free_stream(snd_pcm_str_t * pstr)
+static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
- snd_pcm_substream_t *substream, *substream_next;
+ struct snd_pcm_substream *substream, *substream_next;
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
- snd_pcm_oss_setup_t *setup, *setupn;
+ struct snd_pcm_oss_setup *setup, *setupn;
#endif
substream = pstr->substream;
while (substream) {
@@ -707,7 +749,7 @@ static void snd_pcm_free_stream(snd_pcm_str_t * pstr)
#endif
}
-static int snd_pcm_free(snd_pcm_t *pcm)
+static int snd_pcm_free(struct snd_pcm *pcm)
{
snd_assert(pcm != NULL, return -ENXIO);
if (pcm->private_free)
@@ -719,26 +761,26 @@ static int snd_pcm_free(snd_pcm_t *pcm)
return 0;
}
-static int snd_pcm_dev_free(snd_device_t *device)
+static int snd_pcm_dev_free(struct snd_device *device)
{
- snd_pcm_t *pcm = device->device_data;
+ struct snd_pcm *pcm = device->device_data;
return snd_pcm_free(pcm);
}
static void snd_pcm_tick_timer_func(unsigned long data)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t*) data;
+ struct snd_pcm_substream *substream = (struct snd_pcm_substream *) data;
snd_pcm_tick_elapsed(substream);
}
-int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
- snd_pcm_substream_t **rsubstream)
+int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
+ struct snd_pcm_substream **rsubstream)
{
- snd_pcm_str_t * pstr;
- snd_pcm_substream_t * substream;
- snd_pcm_runtime_t * runtime;
- snd_ctl_file_t *kctl;
- snd_card_t *card;
+ struct snd_pcm_str * pstr;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ struct snd_ctl_file *kctl;
+ struct snd_card *card;
struct list_head *list;
int prefer_subdevice = -1;
size_t size;
@@ -800,7 +842,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
if (runtime == NULL)
return -ENOMEM;
- size = PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t));
+ size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status));
runtime->status = snd_malloc_pages(size, GFP_KERNEL);
if (runtime->status == NULL) {
kfree(runtime);
@@ -808,10 +850,11 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
}
memset((void*)runtime->status, 0, size);
- size = PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t));
+ size = PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control));
runtime->control = snd_malloc_pages(size, GFP_KERNEL);
if (runtime->control == NULL) {
- snd_free_pages((void*)runtime->status, PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)));
+ snd_free_pages((void*)runtime->status,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
kfree(runtime);
return -ENOMEM;
}
@@ -832,39 +875,39 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
return 0;
}
-void snd_pcm_release_substream(snd_pcm_substream_t *substream)
+void snd_pcm_release_substream(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t * runtime;
+ struct snd_pcm_runtime *runtime;
substream->file = NULL;
runtime = substream->runtime;
snd_assert(runtime != NULL, return);
if (runtime->private_free != NULL)
runtime->private_free(runtime);
- snd_free_pages((void*)runtime->status, PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)));
- snd_free_pages((void*)runtime->control, PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t)));
+ snd_free_pages((void*)runtime->status,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)));
+ snd_free_pages((void*)runtime->control,
+ PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)));
kfree(runtime->hw_constraints.rules);
kfree(runtime);
substream->runtime = NULL;
substream->pstr->substream_opened--;
}
-static int snd_pcm_dev_register(snd_device_t *device)
+static int snd_pcm_dev_register(struct snd_device *device)
{
- int idx, cidx, err;
- unsigned short minor;
- snd_pcm_substream_t *substream;
+ int cidx, err;
+ struct snd_pcm_substream *substream;
struct list_head *list;
char str[16];
- snd_pcm_t *pcm = device->device_data;
+ struct snd_pcm *pcm = device->device_data;
snd_assert(pcm != NULL && device != NULL, return -ENXIO);
down(&register_mutex);
- idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
- if (snd_pcm_devices[idx]) {
+ if (snd_pcm_search(pcm->card, pcm->device)) {
up(&register_mutex);
return -EBUSY;
}
- snd_pcm_devices[idx] = pcm;
+ list_add_tail(&pcm->list, &snd_pcm_devices);
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
if (pcm->streams[cidx].substream == NULL)
@@ -872,17 +915,19 @@ static int snd_pcm_dev_register(snd_device_t *device)
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
- minor = SNDRV_MINOR_PCM_PLAYBACK + idx;
devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
break;
case SNDRV_PCM_STREAM_CAPTURE:
sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
- minor = SNDRV_MINOR_PCM_CAPTURE + idx;
devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
break;
}
- if ((err = snd_register_device(devtype, pcm->card, pcm->device, pcm->streams[cidx].reg, str)) < 0) {
- snd_pcm_devices[idx] = NULL;
+ if ((err = snd_register_device(devtype, pcm->card,
+ pcm->device,
+ &snd_pcm_f_ops[cidx],
+ pcm, str)) < 0)
+ {
+ list_del(&pcm->list);
up(&register_mutex);
return err;
}
@@ -890,48 +935,46 @@ static int snd_pcm_dev_register(snd_device_t *device)
snd_pcm_timer_init(substream);
}
list_for_each(list, &snd_pcm_notify_list) {
- snd_pcm_notify_t *notify;
- notify = list_entry(list, snd_pcm_notify_t, list);
+ struct snd_pcm_notify *notify;
+ notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_register(pcm);
}
up(&register_mutex);
return 0;
}
-static int snd_pcm_dev_disconnect(snd_device_t *device)
+static int snd_pcm_dev_disconnect(struct snd_device *device)
{
- snd_pcm_t *pcm = device->device_data;
+ struct snd_pcm *pcm = device->device_data;
struct list_head *list;
- snd_pcm_substream_t *substream;
- int idx, cidx;
+ struct snd_pcm_substream *substream;
+ int cidx;
down(&register_mutex);
- idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
- snd_pcm_devices[idx] = NULL;
+ list_del_init(&pcm->list);
for (cidx = 0; cidx < 2; cidx++)
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
if (substream->runtime)
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
list_for_each(list, &snd_pcm_notify_list) {
- snd_pcm_notify_t *notify;
- notify = list_entry(list, snd_pcm_notify_t, list);
+ struct snd_pcm_notify *notify;
+ notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_disconnect(pcm);
}
up(&register_mutex);
return 0;
}
-static int snd_pcm_dev_unregister(snd_device_t *device)
+static int snd_pcm_dev_unregister(struct snd_device *device)
{
- int idx, cidx, devtype;
- snd_pcm_substream_t *substream;
+ int cidx, devtype;
+ struct snd_pcm_substream *substream;
struct list_head *list;
- snd_pcm_t *pcm = device->device_data;
+ struct snd_pcm *pcm = device->device_data;
snd_assert(pcm != NULL, return -ENXIO);
down(&register_mutex);
- idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device;
- snd_pcm_devices[idx] = NULL;
+ list_del(&pcm->list);
for (cidx = 0; cidx < 2; cidx++) {
devtype = -1;
switch (cidx) {
@@ -947,84 +990,99 @@ static int snd_pcm_dev_unregister(snd_device_t *device)
snd_pcm_timer_done(substream);
}
list_for_each(list, &snd_pcm_notify_list) {
- snd_pcm_notify_t *notify;
- notify = list_entry(list, snd_pcm_notify_t, list);
+ struct snd_pcm_notify *notify;
+ notify = list_entry(list, struct snd_pcm_notify, list);
notify->n_unregister(pcm);
}
up(&register_mutex);
return snd_pcm_free(pcm);
}
-int snd_pcm_notify(snd_pcm_notify_t *notify, int nfree)
+int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
{
- int idx;
+ struct list_head *p;
snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
down(&register_mutex);
if (nfree) {
list_del(&notify->list);
- for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
- if (snd_pcm_devices[idx] == NULL)
- continue;
- notify->n_unregister(snd_pcm_devices[idx]);
- }
+ list_for_each(p, &snd_pcm_devices)
+ notify->n_unregister(list_entry(p,
+ struct snd_pcm, list));
} else {
list_add_tail(&notify->list, &snd_pcm_notify_list);
- for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
- if (snd_pcm_devices[idx] == NULL)
- continue;
- notify->n_register(snd_pcm_devices[idx]);
- }
+ list_for_each(p, &snd_pcm_devices)
+ notify->n_register(list_entry(p, struct snd_pcm, list));
}
up(&register_mutex);
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* Info interface
*/
-static void snd_pcm_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_pcm_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- int idx;
- snd_pcm_t *pcm;
+ struct list_head *p;
+ struct snd_pcm *pcm;
down(&register_mutex);
- for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) {
- pcm = snd_pcm_devices[idx];
- if (pcm == NULL)
- continue;
- snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,
- idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);
+ list_for_each(p, &snd_pcm_devices) {
+ pcm = list_entry(p, struct snd_pcm, list);
+ snd_iprintf(buffer, "%02i-%02i: %s : %s",
+ pcm->card->number, pcm->device, pcm->id, pcm->name);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
- snd_iprintf(buffer, " : playback %i", pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
+ snd_iprintf(buffer, " : playback %i",
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
- snd_iprintf(buffer, " : capture %i", pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
+ snd_iprintf(buffer, " : capture %i",
+ pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count);
snd_iprintf(buffer, "\n");
}
up(&register_mutex);
}
-/*
- * ENTRY functions
- */
-
-static snd_info_entry_t *snd_pcm_proc_entry = NULL;
+static struct snd_info_entry *snd_pcm_proc_entry = NULL;
-static int __init alsa_pcm_init(void)
+static void snd_pcm_proc_init(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
- snd_ctl_register_ioctl(snd_pcm_control_ioctl);
- snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
- snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);
+ snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128,
+ snd_pcm_proc_read);
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
}
}
snd_pcm_proc_entry = entry;
+}
+
+static void snd_pcm_proc_done(void)
+{
+ if (snd_pcm_proc_entry)
+ snd_info_unregister(snd_pcm_proc_entry);
+}
+
+#else /* !CONFIG_PROC_FS */
+#define snd_pcm_proc_init()
+#define snd_pcm_proc_done()
+#endif /* CONFIG_PROC_FS */
+
+
+/*
+ * ENTRY functions
+ */
+
+static int __init alsa_pcm_init(void)
+{
+ snd_ctl_register_ioctl(snd_pcm_control_ioctl);
+ snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
+ snd_pcm_proc_init();
return 0;
}
@@ -1032,16 +1090,12 @@ static void __exit alsa_pcm_exit(void)
{
snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
- if (snd_pcm_proc_entry) {
- snd_info_unregister(snd_pcm_proc_entry);
- snd_pcm_proc_entry = NULL;
- }
+ snd_pcm_proc_done();
}
module_init(alsa_pcm_init)
module_exit(alsa_pcm_exit)
-EXPORT_SYMBOL(snd_pcm_devices);
EXPORT_SYMBOL(snd_pcm_new);
EXPORT_SYMBOL(snd_pcm_new_stream);
EXPORT_SYMBOL(snd_pcm_notify);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 4b6307df846d..e5133033de5e 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -22,7 +22,7 @@
#include <linux/compat.h>
-static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream,
+static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
s32 __user *src)
{
snd_pcm_sframes_t delay;
@@ -39,7 +39,7 @@ static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream,
return err;
}
-static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream,
+static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
u32 __user *src)
{
snd_pcm_uframes_t frames;
@@ -56,7 +56,7 @@ static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream,
return err < 0 ? err : 0;
}
-static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream,
+static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
u32 __user *src)
{
snd_pcm_uframes_t frames;
@@ -73,12 +73,12 @@ static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream,
return err < 0 ? err : 0;
}
-struct sndrv_pcm_hw_params32 {
+struct snd_pcm_hw_params32 {
u32 flags;
- struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
- struct sndrv_mask mres[5]; /* reserved masks */
- struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
- struct sndrv_interval ires[9]; /* reserved intervals */
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
+ struct snd_mask mres[5]; /* reserved masks */
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9]; /* reserved intervals */
u32 rmask;
u32 cmask;
u32 info;
@@ -89,7 +89,7 @@ struct sndrv_pcm_hw_params32 {
unsigned char reserved[64];
};
-struct sndrv_pcm_sw_params32 {
+struct snd_pcm_sw_params32 {
s32 tstamp_mode;
u32 period_step;
u32 sleep_min;
@@ -104,7 +104,7 @@ struct sndrv_pcm_sw_params32 {
};
/* recalcuate the boundary within 32bit */
-static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
+static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t boundary;
@@ -116,10 +116,10 @@ static snd_pcm_uframes_t recalculate_boundary(snd_pcm_runtime_t *runtime)
return boundary;
}
-static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
- struct sndrv_pcm_sw_params32 __user *src)
+static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
+ struct snd_pcm_sw_params32 __user *src)
{
- snd_pcm_sw_params_t params;
+ struct snd_pcm_sw_params params;
snd_pcm_uframes_t boundary;
int err;
@@ -149,17 +149,17 @@ static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
return err;
}
-struct sndrv_pcm_channel_info32 {
+struct snd_pcm_channel_info32 {
u32 channel;
u32 offset;
u32 first;
u32 step;
};
-static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream,
- struct sndrv_pcm_channel_info32 __user *src)
+static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info32 __user *src)
{
- snd_pcm_channel_info_t info;
+ struct snd_pcm_channel_info info;
int err;
if (get_user(info.channel, &src->channel) ||
@@ -178,7 +178,7 @@ static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream,
return err;
}
-struct sndrv_pcm_status32 {
+struct snd_pcm_status32 {
s32 state;
struct compat_timespec trigger_tstamp;
struct compat_timespec tstamp;
@@ -193,10 +193,10 @@ struct sndrv_pcm_status32 {
} __attribute__((packed));
-static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
- struct sndrv_pcm_status32 __user *src)
+static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
+ struct snd_pcm_status32 __user *src)
{
- snd_pcm_status_t status;
+ struct snd_pcm_status status;
int err;
err = snd_pcm_status(substream, &status);
@@ -221,12 +221,12 @@ static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
}
/* both for HW_PARAMS and HW_REFINE */
-static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
+static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
int refine,
- struct sndrv_pcm_hw_params32 __user *data32)
+ struct snd_pcm_hw_params32 __user *data32)
{
- struct sndrv_pcm_hw_params *data;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_hw_params *data;
+ struct snd_pcm_runtime *runtime;
int err;
if (! (runtime = substream->runtime))
@@ -265,14 +265,14 @@ static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
/*
*/
-struct sndrv_xferi32 {
+struct snd_xferi32 {
s32 result;
u32 buf;
u32 frames;
};
-static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream,
- int dir, struct sndrv_xferi32 __user *data32)
+static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream,
+ int dir, struct snd_xferi32 __user *data32)
{
compat_caddr_t buf;
u32 frames;
@@ -303,7 +303,7 @@ static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream,
/* snd_xfern needs remapping of bufs */
-struct sndrv_xfern32 {
+struct snd_xfern32 {
s32 result;
u32 bufs; /* this is void **; */
u32 frames;
@@ -315,8 +315,8 @@ struct sndrv_xfern32 {
* handler there expands again the same 128 pointers on stack, so it is better
* to handle the function (calling pcm_readv/writev) directly in this handler.
*/
-static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream,
- int dir, struct sndrv_xfern32 __user *data32)
+static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
+ int dir, struct snd_xfern32 __user *data32)
{
compat_caddr_t buf;
compat_caddr_t __user *bufptr;
@@ -360,7 +360,7 @@ static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream,
}
-struct sndrv_pcm_mmap_status32 {
+struct snd_pcm_mmap_status32 {
s32 state;
s32 pad1;
u32 hw_ptr;
@@ -368,32 +368,32 @@ struct sndrv_pcm_mmap_status32 {
s32 suspended_state;
} __attribute__((packed));
-struct sndrv_pcm_mmap_control32 {
+struct snd_pcm_mmap_control32 {
u32 appl_ptr;
u32 avail_min;
};
-struct sndrv_pcm_sync_ptr32 {
+struct snd_pcm_sync_ptr32 {
u32 flags;
union {
- struct sndrv_pcm_mmap_status32 status;
+ struct snd_pcm_mmap_status32 status;
unsigned char reserved[64];
} s;
union {
- struct sndrv_pcm_mmap_control32 control;
+ struct snd_pcm_mmap_control32 control;
unsigned char reserved[64];
} c;
} __attribute__((packed));
-static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
- struct sndrv_pcm_sync_ptr32 __user *src)
+static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
+ struct snd_pcm_sync_ptr32 __user *src)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- volatile struct sndrv_pcm_mmap_status *status;
- volatile struct sndrv_pcm_mmap_control *control;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
u32 sflags;
- struct sndrv_pcm_mmap_control scontrol;
- struct sndrv_pcm_mmap_status sstatus;
+ struct snd_pcm_mmap_control scontrol;
+ struct snd_pcm_mmap_status sstatus;
snd_pcm_uframes_t boundary;
int err;
@@ -444,26 +444,26 @@ static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
/*
*/
enum {
- SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32),
- SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32),
- SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32),
- SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32),
+ SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
+ SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
+ SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
+ SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
- SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32),
+ SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
- SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32),
- SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
- SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
- SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
- SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
+ SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct snd_xferi32),
+ SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
+ SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
+ SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
+ SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
};
static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
void __user *argp = compat_ptr(arg);
pcm_file = file->private_data;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 3dbf9bf2ac16..eeba2f060955 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -39,9 +39,9 @@
*
* when runtime->silence_size >= runtime->boundary - fill processed area with silence immediately
*/
-void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t new_hw_ptr)
+void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
if (runtime->silence_size < runtime->boundary) {
@@ -56,9 +56,8 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
runtime->silence_filled = 0;
runtime->silence_start = runtime->control->appl_ptr;
}
- if (runtime->silence_filled == runtime->buffer_size)
+ if (runtime->silence_filled >= runtime->buffer_size)
return;
- snd_assert(runtime->silence_filled <= runtime->buffer_size, return);
noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold)
return;
@@ -128,7 +127,7 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
}
}
-static void xrun(snd_pcm_substream_t *substream)
+static void xrun(struct snd_pcm_substream *substream)
{
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
#ifdef CONFIG_SND_DEBUG
@@ -143,8 +142,8 @@ static void xrun(snd_pcm_substream_t *substream)
#endif
}
-static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *substream,
- snd_pcm_runtime_t *runtime)
+static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t pos;
@@ -162,8 +161,8 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *s
return pos;
}
-static inline int snd_pcm_update_hw_ptr_post(snd_pcm_substream_t *substream,
- snd_pcm_runtime_t *runtime)
+static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime)
{
snd_pcm_uframes_t avail;
@@ -185,9 +184,9 @@ static inline int snd_pcm_update_hw_ptr_post(snd_pcm_substream_t *substream,
return 0;
}
-static inline int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream)
+static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt;
snd_pcm_sframes_t delta;
@@ -232,9 +231,9 @@ static inline int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream
}
/* CAUTION: call it with irq disabled */
-int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream)
+int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t pos;
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
snd_pcm_sframes_t delta;
@@ -281,10 +280,10 @@ int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream)
*
* Sets the given PCM operators to the pcm instance.
*/
-void snd_pcm_set_ops(snd_pcm_t *pcm, int direction, snd_pcm_ops_t *ops)
+void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops)
{
- snd_pcm_str_t *stream = &pcm->streams[direction];
- snd_pcm_substream_t *substream;
+ struct snd_pcm_str *stream = &pcm->streams[direction];
+ struct snd_pcm_substream *substream;
for (substream = stream->substream; substream != NULL; substream = substream->next)
substream->ops = ops;
@@ -297,9 +296,9 @@ void snd_pcm_set_ops(snd_pcm_t *pcm, int direction, snd_pcm_ops_t *ops)
*
* Sets the PCM sync identifier for the card.
*/
-void snd_pcm_set_sync(snd_pcm_substream_t * substream)
+void snd_pcm_set_sync(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->sync.id32[0] = substream->pcm->card->number;
runtime->sync.id32[1] = -1;
@@ -370,7 +369,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
return n;
}
-static int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int openmin)
+static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
{
int changed = 0;
assert(!snd_interval_empty(i));
@@ -395,7 +394,7 @@ static int snd_interval_refine_min(snd_interval_t *i, unsigned int min, int open
return changed;
}
-static int snd_interval_refine_max(snd_interval_t *i, unsigned int max, int openmax)
+static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
{
int changed = 0;
assert(!snd_interval_empty(i));
@@ -431,7 +430,7 @@ static int snd_interval_refine_max(snd_interval_t *i, unsigned int max, int open
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-int snd_interval_refine(snd_interval_t *i, const snd_interval_t *v)
+int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
{
int changed = 0;
assert(!snd_interval_empty(i));
@@ -473,7 +472,7 @@ int snd_interval_refine(snd_interval_t *i, const snd_interval_t *v)
return changed;
}
-static int snd_interval_refine_first(snd_interval_t *i)
+static int snd_interval_refine_first(struct snd_interval *i)
{
assert(!snd_interval_empty(i));
if (snd_interval_single(i))
@@ -485,7 +484,7 @@ static int snd_interval_refine_first(snd_interval_t *i)
return 1;
}
-static int snd_interval_refine_last(snd_interval_t *i)
+static int snd_interval_refine_last(struct snd_interval *i)
{
assert(!snd_interval_empty(i));
if (snd_interval_single(i))
@@ -497,9 +496,9 @@ static int snd_interval_refine_last(snd_interval_t *i)
return 1;
}
-static int snd_interval_refine_set(snd_interval_t *i, unsigned int val)
+static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
{
- snd_interval_t t;
+ struct snd_interval t;
t.empty = 0;
t.min = t.max = val;
t.openmin = t.openmax = 0;
@@ -507,7 +506,7 @@ static int snd_interval_refine_set(snd_interval_t *i, unsigned int val)
return snd_interval_refine(i, &t);
}
-void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
+void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
{
if (a->empty || b->empty) {
snd_interval_none(c);
@@ -531,7 +530,7 @@ void snd_interval_mul(const snd_interval_t *a, const snd_interval_t *b, snd_inte
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_interval_t *c)
+void snd_interval_div(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
{
unsigned int r;
if (a->empty || b->empty) {
@@ -566,8 +565,8 @@ void snd_interval_div(const snd_interval_t *a, const snd_interval_t *b, snd_inte
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
- unsigned int k, snd_interval_t *c)
+void snd_interval_muldivk(const struct snd_interval *a, const struct snd_interval *b,
+ unsigned int k, struct snd_interval *c)
{
unsigned int r;
if (a->empty || b->empty) {
@@ -597,8 +596,8 @@ void snd_interval_muldivk(const snd_interval_t *a, const snd_interval_t *b,
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
- const snd_interval_t *b, snd_interval_t *c)
+void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+ const struct snd_interval *b, struct snd_interval *c)
{
unsigned int r;
if (a->empty || b->empty) {
@@ -636,13 +635,13 @@ void snd_interval_mulkdiv(const snd_interval_t *a, unsigned int k,
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-int snd_interval_ratnum(snd_interval_t *i,
- unsigned int rats_count, ratnum_t *rats,
- unsigned int *nump, unsigned int *denp)
+int snd_interval_ratnum(struct snd_interval *i,
+ unsigned int rats_count, struct snd_ratnum *rats,
+ unsigned int *nump, unsigned int *denp)
{
unsigned int best_num, best_diff, best_den;
unsigned int k;
- snd_interval_t t;
+ struct snd_interval t;
int err;
best_num = best_den = best_diff = 0;
@@ -731,20 +730,20 @@ 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
+ * @rats_count: number of struct ratden
+ * @rats: struct ratden 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.
*/
-static int snd_interval_ratden(snd_interval_t *i,
- unsigned int rats_count, ratden_t *rats,
+static int snd_interval_ratden(struct snd_interval *i,
+ unsigned int rats_count, struct snd_ratden *rats,
unsigned int *nump, unsigned int *denp)
{
unsigned int best_num, best_diff, best_den;
unsigned int k;
- snd_interval_t t;
+ struct snd_interval t;
int err;
best_num = best_den = best_diff = 0;
@@ -837,7 +836,7 @@ static int snd_interval_ratden(snd_interval_t *i,
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-int snd_interval_list(snd_interval_t *i, unsigned int count, unsigned int *list, unsigned int mask)
+int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
{
unsigned int k;
int changed = 0;
@@ -878,7 +877,7 @@ int snd_interval_list(snd_interval_t *i, unsigned int count, unsigned int *list,
return changed;
}
-static int snd_interval_step(snd_interval_t *i, unsigned int min, unsigned int step)
+static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
{
unsigned int n;
int changed = 0;
@@ -912,18 +911,18 @@ static int snd_interval_step(snd_interval_t *i, unsigned int min, unsigned int s
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
+int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
int var,
snd_pcm_hw_rule_func_t func, void *private,
int dep, ...)
{
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
- snd_pcm_hw_rule_t *c;
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
+ struct snd_pcm_hw_rule *c;
unsigned int k;
va_list args;
va_start(args, dep);
if (constrs->rules_num >= constrs->rules_all) {
- snd_pcm_hw_rule_t *new;
+ struct snd_pcm_hw_rule *new;
unsigned int new_rules = constrs->rules_all + 16;
new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
if (!new)
@@ -962,11 +961,11 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
*
* 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,
+int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int32_t mask)
{
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
- snd_mask_t *maskp = constrs_mask(constrs, var);
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
+ struct snd_mask *maskp = constrs_mask(constrs, var);
*maskp->bits &= mask;
memset(maskp->bits + 1, 0, (SNDRV_MASK_MAX-32) / 8); /* clear rest */
if (*maskp->bits == 0)
@@ -982,11 +981,11 @@ int snd_pcm_hw_constraint_mask(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t va
*
* 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,
+int snd_pcm_hw_constraint_mask64(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
u_int64_t mask)
{
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
- snd_mask_t *maskp = constrs_mask(constrs, var);
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
+ struct snd_mask *maskp = constrs_mask(constrs, var);
maskp->bits[0] &= (u_int32_t)mask;
maskp->bits[1] &= (u_int32_t)(mask >> 32);
memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
@@ -1002,9 +1001,9 @@ int snd_pcm_hw_constraint_mask64(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
*
* 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)
+int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var)
{
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
return snd_interval_setinteger(constrs_interval(constrs, var));
}
@@ -1017,11 +1016,11 @@ int snd_pcm_hw_constraint_integer(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
*
* 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,
+int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_param_t var,
unsigned int min, unsigned int max)
{
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
- snd_interval_t t;
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
+ struct snd_interval t;
t.min = min;
t.max = max;
t.openmin = t.openmax = 0;
@@ -1029,10 +1028,10 @@ int snd_pcm_hw_constraint_minmax(snd_pcm_runtime_t *runtime, snd_pcm_hw_param_t
return snd_interval_refine(constrs_interval(constrs, var), &t);
}
-static int snd_pcm_hw_rule_list(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_pcm_hw_constraint_list_t *list = rule->private;
+ struct snd_pcm_hw_constraint_list *list = rule->private;
return snd_interval_list(hw_param_interval(params, rule->var), list->count, list->list, list->mask);
}
@@ -1046,20 +1045,20 @@ static int snd_pcm_hw_rule_list(snd_pcm_hw_params_t *params,
*
* Apply the list of constraints to an interval parameter.
*/
-int snd_pcm_hw_constraint_list(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_list_t *l)
+ struct snd_pcm_hw_constraint_list *l)
{
return snd_pcm_hw_rule_add(runtime, cond, var,
snd_pcm_hw_rule_list, l,
var, -1);
}
-static int snd_pcm_hw_rule_ratnums(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_pcm_hw_constraint_ratnums_t *r = rule->private;
+ struct snd_pcm_hw_constraint_ratnums *r = rule->private;
unsigned int num = 0, den = 0;
int err;
err = snd_interval_ratnum(hw_param_interval(params, rule->var),
@@ -1076,22 +1075,22 @@ static int snd_pcm_hw_rule_ratnums(snd_pcm_hw_params_t *params,
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the ratnums constraint
- * @r: ratnums_t constriants
+ * @r: struct snd_ratnums constriants
*/
-int snd_pcm_hw_constraint_ratnums(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_ratnums_t *r)
+ struct snd_pcm_hw_constraint_ratnums *r)
{
return snd_pcm_hw_rule_add(runtime, cond, var,
snd_pcm_hw_rule_ratnums, r,
var, -1);
}
-static int snd_pcm_hw_rule_ratdens(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_pcm_hw_constraint_ratdens_t *r = rule->private;
+ struct snd_pcm_hw_constraint_ratdens *r = rule->private;
unsigned int num = 0, den = 0;
int err = snd_interval_ratden(hw_param_interval(params, rule->var),
r->nrats, r->rats, &num, &den);
@@ -1107,25 +1106,25 @@ static int snd_pcm_hw_rule_ratdens(snd_pcm_hw_params_t *params,
* @runtime: PCM runtime instance
* @cond: condition bits
* @var: hw_params variable to apply the ratdens constraint
- * @r: ratdens_t constriants
+ * @r: struct snd_ratdens constriants
*/
-int snd_pcm_hw_constraint_ratdens(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
- snd_pcm_hw_constraint_ratdens_t *r)
+ struct snd_pcm_hw_constraint_ratdens *r)
{
return snd_pcm_hw_rule_add(runtime, cond, var,
snd_pcm_hw_rule_ratdens, r,
var, -1);
}
-static int snd_pcm_hw_rule_msbits(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned int l = (unsigned long) rule->private;
int width = l & 0xffff;
unsigned int msbits = l >> 16;
- snd_interval_t *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+ struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
if (snd_interval_single(i) && snd_interval_value(i) == width)
params->msbits = msbits;
return 0;
@@ -1138,7 +1137,7 @@ static int snd_pcm_hw_rule_msbits(snd_pcm_hw_params_t *params,
* @width: sample bits width
* @msbits: msbits width
*/
-int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime,
unsigned int cond,
unsigned int width,
unsigned int msbits)
@@ -1150,8 +1149,8 @@ int snd_pcm_hw_constraint_msbits(snd_pcm_runtime_t *runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
}
-static int snd_pcm_hw_rule_step(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned long step = (unsigned long) rule->private;
return snd_interval_step(hw_param_interval(params, rule->var), 0, step);
@@ -1164,7 +1163,7 @@ static int snd_pcm_hw_rule_step(snd_pcm_hw_params_t *params,
* @var: hw_params variable to apply the step constraint
* @step: step size
*/
-int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
+int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var,
unsigned long step)
@@ -1174,7 +1173,7 @@ int snd_pcm_hw_constraint_step(snd_pcm_runtime_t *runtime,
var, -1);
}
-static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
{
static int pow2_sizes[] = {
1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
@@ -1192,7 +1191,7 @@ static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *
* @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,
+int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
unsigned int cond,
snd_pcm_hw_param_t var)
{
@@ -1202,13 +1201,12 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
}
/* To use the same code we have in alsa-lib */
-#define snd_pcm_t snd_pcm_substream_t
#define assert(i) snd_assert((i), return -EINVAL)
#ifndef INT_MIN
#define INT_MIN ((int)((unsigned int)INT_MAX+1))
#endif
-static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
+static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
if (hw_is_mask(var)) {
@@ -1230,7 +1228,7 @@ static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
/*
* snd_pcm_hw_param_any
*/
-int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+int snd_pcm_hw_param_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
_snd_pcm_hw_param_any(params, var);
@@ -1238,7 +1236,7 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
}
#endif /* 0 */
-void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
+void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
{
unsigned int k;
memset(params, 0, sizeof(*params));
@@ -1255,7 +1253,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
*
* Fill PARAMS with full configuration space boundaries
*/
-int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params)
{
_snd_pcm_hw_params_any(params);
return snd_pcm_hw_refine(pcm, params);
@@ -1271,11 +1269,11 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
* Return the value for field PAR if it's fixed in configuration space
* defined by PARAMS. Return -EINVAL otherwise
*/
-static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
+static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
- const snd_mask_t *mask = hw_param_mask_c(params, var);
+ const struct snd_mask *mask = hw_param_mask_c(params, var);
if (!snd_mask_single(mask))
return -EINVAL;
if (dir)
@@ -1283,7 +1281,7 @@ static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
return snd_mask_value(mask);
}
if (hw_is_interval(var)) {
- const snd_interval_t *i = hw_param_interval_c(params, var);
+ const struct snd_interval *i = hw_param_interval_c(params, var);
if (!snd_interval_single(i))
return -EINVAL;
if (dir)
@@ -1302,7 +1300,7 @@ static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
*
* Return the minimum value for field PAR.
*/
-unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
+unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
@@ -1311,7 +1309,7 @@ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
return snd_mask_min(hw_param_mask_c(params, var));
}
if (hw_is_interval(var)) {
- const snd_interval_t *i = hw_param_interval_c(params, var);
+ const struct snd_interval *i = hw_param_interval_c(params, var);
if (dir)
*dir = i->openmin;
return snd_interval_min(i);
@@ -1328,7 +1326,7 @@ unsigned int snd_pcm_hw_param_value_min(const snd_pcm_hw_params_t *params,
*
* Return the maximum value for field PAR.
*/
-unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
+unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
@@ -1337,7 +1335,7 @@ unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
return snd_mask_max(hw_param_mask_c(params, var));
}
if (hw_is_interval(var)) {
- const snd_interval_t *i = hw_param_interval_c(params, var);
+ const struct snd_interval *i = hw_param_interval_c(params, var);
if (dir)
*dir = - (int) i->openmax;
return snd_interval_max(i);
@@ -1346,7 +1344,7 @@ unsigned int snd_pcm_hw_param_value_max(const snd_pcm_hw_params_t *params,
return -EINVAL;
}
-void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params,
+void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
if (hw_is_mask(var)) {
@@ -1362,7 +1360,7 @@ void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params,
}
}
-int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
+int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
int changed;
@@ -1383,8 +1381,8 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
* non integer values. Reduce configuration space accordingly.
* Return -EINVAL if the configuration space is empty
*/
-int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
+int snd_pcm_hw_param_setinteger(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
int changed = _snd_pcm_hw_param_setinteger(params, var);
@@ -1399,7 +1397,7 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
}
#endif /* 0 */
-static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
+static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
int changed;
@@ -1430,8 +1428,8 @@ static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
* values > minimum. Reduce configuration space accordingly.
* Return the minimum.
*/
-static int snd_pcm_hw_param_first(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
+static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_first(params, var);
@@ -1444,7 +1442,7 @@ static int snd_pcm_hw_param_first(snd_pcm_t *pcm,
return snd_pcm_hw_param_value(params, var, dir);
}
-static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
+static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
int changed;
@@ -1475,8 +1473,8 @@ static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
* values < maximum. Reduce configuration space accordingly.
* Return the maximum.
*/
-static int snd_pcm_hw_param_last(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
+static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm,
+ struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_last(params, var);
@@ -1489,7 +1487,7 @@ static int snd_pcm_hw_param_last(snd_pcm_t *pcm,
return snd_pcm_hw_param_value(params, var, dir);
}
-int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
+int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir)
{
int changed;
@@ -1531,7 +1529,7 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
* values < VAL. Reduce configuration space accordingly.
* Return new minimum or -EINVAL if the configuration space is empty
*/
-static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int *dir)
{
@@ -1546,7 +1544,7 @@ static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
return snd_pcm_hw_param_value_min(params, var, dir);
}
-static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
+static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int dir)
{
@@ -1591,7 +1589,7 @@ static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
* values >= VAL + 1. Reduce configuration space accordingly.
* Return new maximum or -EINVAL if the configuration space is empty
*/
-static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val,
int *dir)
{
@@ -1606,12 +1604,12 @@ static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
return snd_pcm_hw_param_value_max(params, var, dir);
}
-int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
+int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir)
{
int changed;
if (hw_is_mask(var)) {
- snd_mask_t *m = hw_param_mask(params, var);
+ struct snd_mask *m = hw_param_mask(params, var);
if (val == 0 && dir < 0) {
changed = -EINVAL;
snd_mask_none(m);
@@ -1623,14 +1621,14 @@ int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
changed = snd_mask_refine_set(hw_param_mask(params, var), val);
}
} else if (hw_is_interval(var)) {
- snd_interval_t *i = hw_param_interval(params, var);
+ struct snd_interval *i = hw_param_interval(params, var);
if (val == 0 && dir < 0) {
changed = -EINVAL;
snd_interval_none(i);
} else if (dir == 0)
changed = snd_interval_refine_set(i, val);
else {
- snd_interval_t t;
+ struct snd_interval t;
t.openmin = 1;
t.openmax = 1;
t.empty = 0;
@@ -1667,7 +1665,7 @@ int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
* values != VAL. Reduce configuration space accordingly.
* Return VAL or -EINVAL if the configuration space is empty
*/
-int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int val, int dir)
{
int changed = _snd_pcm_hw_param_set(params, var, val, dir);
@@ -1681,8 +1679,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);
}
-static 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(struct snd_pcm_hw_params *params,
+ snd_pcm_hw_param_t var, const struct snd_mask *val)
{
int changed;
assert(hw_is_mask(var));
@@ -1708,8 +1706,8 @@ static int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
* Return 0 on success or -EINVAL
* if the configuration space is empty
*/
-int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, const snd_mask_t *val)
+int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
+ snd_pcm_hw_param_t var, const struct snd_mask *val)
{
int changed = _snd_pcm_hw_param_mask(params, var, val);
if (changed < 0)
@@ -1784,10 +1782,10 @@ static int boundary_nearer(int min, int mindir,
* SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
* Return the value found.
*/
-int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var, unsigned int best, int *dir)
{
- snd_pcm_hw_params_t *save = NULL;
+ struct snd_pcm_hw_params *save = NULL;
int v;
unsigned int saved_min;
int last = 0;
@@ -1814,7 +1812,7 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
saved_min = min;
min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
if (min >= 0) {
- snd_pcm_hw_params_t *params1;
+ struct snd_pcm_hw_params *params1;
if (max < 0)
goto _end;
if ((unsigned int)min == saved_min && mindir == valdir)
@@ -1861,7 +1859,7 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
* first access, first format, first subformat, min channels,
* min rate, min period time, max buffer size, min tick time
*/
-int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params)
{
int err;
@@ -1892,13 +1890,12 @@ int snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
return 0;
}
-#undef snd_pcm_t
#undef assert
-static int snd_pcm_lib_ioctl_reset(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
void *arg)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
snd_pcm_stream_lock_irqsave(substream, flags);
if (snd_pcm_running(substream) &&
@@ -1910,11 +1907,11 @@ static int snd_pcm_lib_ioctl_reset(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_pcm_lib_ioctl_channel_info(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_ioctl_channel_info(struct snd_pcm_substream *substream,
void *arg)
{
- snd_pcm_channel_info_t *info = arg;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_channel_info *info = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int width;
if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) {
info->offset = -1;
@@ -1956,7 +1953,7 @@ static int snd_pcm_lib_ioctl_channel_info(snd_pcm_substream_t *substream,
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_ioctl(snd_pcm_substream_t *substream,
+int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -1974,10 +1971,10 @@ int snd_pcm_lib_ioctl(snd_pcm_substream_t *substream,
* Conditions
*/
-static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream,
+static void snd_pcm_system_tick_set(struct snd_pcm_substream *substream,
unsigned long ticks)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (ticks == 0)
del_timer(&runtime->tick_timer);
else {
@@ -1988,14 +1985,14 @@ static void snd_pcm_system_tick_set(snd_pcm_substream_t *substream,
}
/* Temporary alias */
-void snd_pcm_tick_set(snd_pcm_substream_t *substream, unsigned long ticks)
+void snd_pcm_tick_set(struct snd_pcm_substream *substream, unsigned long ticks)
{
snd_pcm_system_tick_set(substream, ticks);
}
-void snd_pcm_tick_prepare(snd_pcm_substream_t *substream)
+void snd_pcm_tick_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames = ULONG_MAX;
snd_pcm_uframes_t avail, dist;
unsigned int ticks;
@@ -2008,8 +2005,8 @@ void snd_pcm_tick_prepare(snd_pcm_substream_t *substream)
runtime->silence_filled < runtime->buffer_size) {
snd_pcm_sframes_t noise_dist;
noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled;
- snd_assert(noise_dist <= (snd_pcm_sframes_t)runtime->silence_threshold, );
- frames = noise_dist - runtime->silence_threshold;
+ if (noise_dist > (snd_pcm_sframes_t)runtime->silence_threshold)
+ frames = noise_dist - runtime->silence_threshold;
}
avail = snd_pcm_playback_avail(runtime);
} else {
@@ -2046,9 +2043,9 @@ void snd_pcm_tick_prepare(snd_pcm_substream_t *substream)
snd_pcm_tick_set(substream, (unsigned long) ticks);
}
-void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream)
+void snd_pcm_tick_elapsed(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
unsigned long flags;
snd_assert(substream != NULL, return);
@@ -2076,9 +2073,9 @@ void snd_pcm_tick_elapsed(snd_pcm_substream_t *substream)
* Even if more than one periods have elapsed since the last call, you
* have to call this only once.
*/
-void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
+void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
unsigned long flags;
snd_assert(substream != NULL, return);
@@ -2104,12 +2101,12 @@ void snd_pcm_period_elapsed(snd_pcm_substream_t *substream)
kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
}
-static int snd_pcm_lib_write_transfer(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
unsigned int hwoff,
unsigned long data, unsigned int off,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
if (substream->ops->copy) {
@@ -2124,17 +2121,17 @@ static int snd_pcm_lib_write_transfer(snd_pcm_substream_t *substream,
return 0;
}
-typedef int (*transfer_f)(snd_pcm_substream_t *substream, unsigned int hwoff,
+typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
unsigned long data, unsigned int off,
snd_pcm_uframes_t size);
-static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
+static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
unsigned long data,
snd_pcm_uframes_t size,
int nonblock,
transfer_f transfer)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
int err = 0;
@@ -2290,9 +2287,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
-snd_pcm_sframes_t snd_pcm_lib_write(snd_pcm_substream_t *substream, const void __user *buf, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int nonblock;
snd_assert(substream != NULL, return -ENXIO);
@@ -2306,7 +2303,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(snd_pcm_substream_t *substream, const void _
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
if (substream->oss.oss) {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
if (setup != NULL) {
if (setup->nonblock)
nonblock = 1;
@@ -2323,12 +2320,12 @@ snd_pcm_sframes_t snd_pcm_lib_write(snd_pcm_substream_t *substream, const void _
snd_pcm_lib_write_transfer);
}
-static int snd_pcm_lib_writev_transfer(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
unsigned int hwoff,
unsigned long data, unsigned int off,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
void __user **bufs = (void __user **)data;
int channels = runtime->channels;
@@ -2363,11 +2360,11 @@ static int snd_pcm_lib_writev_transfer(snd_pcm_substream_t *substream,
return 0;
}
-snd_pcm_sframes_t snd_pcm_lib_writev(snd_pcm_substream_t *substream,
+snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
void __user **bufs,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int nonblock;
snd_assert(substream != NULL, return -ENXIO);
@@ -2381,7 +2378,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(snd_pcm_substream_t *substream,
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
if (substream->oss.oss) {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
if (setup != NULL) {
if (setup->nonblock)
nonblock = 1;
@@ -2397,12 +2394,12 @@ snd_pcm_sframes_t snd_pcm_lib_writev(snd_pcm_substream_t *substream,
nonblock, snd_pcm_lib_writev_transfer);
}
-static int snd_pcm_lib_read_transfer(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
unsigned int hwoff,
unsigned long data, unsigned int off,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
if (substream->ops->copy) {
@@ -2417,13 +2414,13 @@ static int snd_pcm_lib_read_transfer(snd_pcm_substream_t *substream,
return 0;
}
-static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
+static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
unsigned long data,
snd_pcm_uframes_t size,
int nonblock,
transfer_f transfer)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
int err = 0;
@@ -2587,9 +2584,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
-snd_pcm_sframes_t snd_pcm_lib_read(snd_pcm_substream_t *substream, void __user *buf, snd_pcm_uframes_t size)
+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int nonblock;
snd_assert(substream != NULL, return -ENXIO);
@@ -2603,7 +2600,7 @@ snd_pcm_sframes_t snd_pcm_lib_read(snd_pcm_substream_t *substream, void __user *
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
if (substream->oss.oss) {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
if (setup != NULL) {
if (setup->nonblock)
nonblock = 1;
@@ -2617,12 +2614,12 @@ snd_pcm_sframes_t snd_pcm_lib_read(snd_pcm_substream_t *substream, void __user *
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
}
-static int snd_pcm_lib_readv_transfer(snd_pcm_substream_t *substream,
+static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
unsigned int hwoff,
unsigned long data, unsigned int off,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
void __user **bufs = (void __user **)data;
int channels = runtime->channels;
@@ -2654,11 +2651,11 @@ static int snd_pcm_lib_readv_transfer(snd_pcm_substream_t *substream,
return 0;
}
-snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
+snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
void __user **bufs,
snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int nonblock;
snd_assert(substream != NULL, return -ENXIO);
@@ -2672,7 +2669,7 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
if (substream->oss.oss) {
- snd_pcm_oss_setup_t *setup = substream->oss.setup;
+ struct snd_pcm_oss_setup *setup = substream->oss.setup;
if (setup != NULL) {
if (setup->nonblock)
nonblock = 1;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index b3f5344f60be..a0119ae67dcd 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -46,7 +46,7 @@ static const size_t snd_minimum_buffer = 16384;
*
* the minimum size is snd_minimum_buffer. it should be power of 2.
*/
-static int preallocate_pcm_pages(snd_pcm_substream_t *substream, size_t size)
+static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
{
struct snd_dma_buffer *dmab = &substream->dma_buffer;
int err;
@@ -78,7 +78,7 @@ static int preallocate_pcm_pages(snd_pcm_substream_t *substream, size_t size)
/*
* release the preallocated buffer if not yet done.
*/
-static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
+static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
{
if (substream->dma_buffer.area == NULL)
return;
@@ -97,13 +97,11 @@ static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_free(snd_pcm_substream_t *substream)
+int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_preallocate_dma_free(substream);
- if (substream->proc_prealloc_entry) {
- snd_info_unregister(substream->proc_prealloc_entry);
- substream->proc_prealloc_entry = NULL;
- }
+ snd_info_unregister(substream->proc_prealloc_entry);
+ substream->proc_prealloc_entry = NULL;
return 0;
}
@@ -115,9 +113,9 @@ int snd_pcm_lib_preallocate_free(snd_pcm_substream_t *substream)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_free_for_all(snd_pcm_t *pcm)
+int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int stream;
for (stream = 0; stream < 2; stream++)
@@ -126,15 +124,16 @@ int snd_pcm_lib_preallocate_free_for_all(snd_pcm_t *pcm)
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* read callback for prealloc proc file
*
* prints the current allocated size in kB.
*/
-static void snd_pcm_lib_preallocate_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
+ struct snd_pcm_substream *substream = entry->private_data;
snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_buffer.bytes / 1024);
}
@@ -143,10 +142,10 @@ static void snd_pcm_lib_preallocate_proc_read(snd_info_entry_t *entry,
*
* accepts the preallocation size in kB.
*/
-static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)entry->private_data;
+ struct snd_pcm_substream *substream = entry->private_data;
char line[64], str[64];
size_t size;
struct snd_dma_buffer new_dmab;
@@ -185,20 +184,10 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
}
}
-/*
- * pre-allocate the buffer and create a proc file for the substream
- */
-static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
- size_t size, size_t max)
+static inline void preallocate_info_init(struct snd_pcm_substream *substream)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
- if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
- preallocate_pcm_pages(substream, size);
-
- if (substream->dma_buffer.bytes > 0)
- substream->buffer_bytes_max = substream->dma_buffer.bytes;
- substream->dma_max = max;
if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
entry->c.text.read_size = 64;
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
@@ -212,6 +201,26 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
}
}
substream->proc_prealloc_entry = entry;
+}
+
+#else /* !CONFIG_PROC_FS */
+#define preallocate_info_init(s)
+#endif
+
+/*
+ * pre-allocate the buffer and create a proc file for the substream
+ */
+static int snd_pcm_lib_preallocate_pages1(struct snd_pcm_substream *substream,
+ size_t size, size_t max)
+{
+
+ if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
+ preallocate_pcm_pages(substream, size);
+
+ if (substream->dma_buffer.bytes > 0)
+ substream->buffer_bytes_max = substream->dma_buffer.bytes;
+ substream->dma_max = max;
+ preallocate_info_init(substream);
return 0;
}
@@ -233,7 +242,7 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
+int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream,
int type, struct device *data,
size_t size, size_t max)
{
@@ -255,11 +264,11 @@ int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t *pcm,
+int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
int type, void *data,
size_t size, size_t max)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int stream, err;
for (stream = 0; stream < 2; stream++)
@@ -277,7 +286,7 @@ int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t *pcm,
* Returns the page struct at the given buffer offset.
* Used as the page callback of PCM ops.
*/
-struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset)
+struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset)
{
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
@@ -298,9 +307,9 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
* Returns 1 if the buffer is changed, 0 if not changed, or a negative
* code on failure.
*/
-int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
+int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
struct snd_dma_buffer *dmab = NULL;
snd_assert(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
@@ -318,7 +327,8 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
}
snd_pcm_lib_free_pages(substream);
}
- if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+ if (substream->dma_buffer.area != NULL &&
+ substream->dma_buffer.bytes >= size) {
dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
} else {
dmab = kzalloc(sizeof(*dmab), GFP_KERNEL);
@@ -345,9 +355,9 @@ int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream)
+int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
snd_assert(substream != NULL, return -EINVAL);
runtime = substream->runtime;
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 1453743e4da0..593c77f4d181 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -441,7 +441,7 @@ snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_end
*
* Returns zero if successful.
*/
-int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime)
+int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
{
static unsigned rates[] = {
/* ATTENTION: these values depend on the definition in pcm.h! */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 16e252f54954..f3d5de7b55ac 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -39,11 +39,11 @@
* Compatibility
*/
-struct sndrv_pcm_hw_params_old {
+struct snd_pcm_hw_params_old {
unsigned int flags;
unsigned int masks[SNDRV_PCM_HW_PARAM_SUBFORMAT -
SNDRV_PCM_HW_PARAM_ACCESS + 1];
- struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_TICK_TIME -
SNDRV_PCM_HW_PARAM_SAMPLE_BITS + 1];
unsigned int rmask;
unsigned int cmask;
@@ -51,15 +51,20 @@ struct sndrv_pcm_hw_params_old {
unsigned int msbits;
unsigned int rate_num;
unsigned int rate_den;
- sndrv_pcm_uframes_t fifo_size;
+ snd_pcm_uframes_t fifo_size;
unsigned char reserved[64];
};
-#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old)
-#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old)
+#ifdef CONFIG_SND_SUPPORT_OLD_API
+#define SNDRV_PCM_IOCTL_HW_REFINE_OLD _IOWR('A', 0x10, struct snd_pcm_hw_params_old)
+#define SNDRV_PCM_IOCTL_HW_PARAMS_OLD _IOWR('A', 0x11, struct snd_pcm_hw_params_old)
-static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams);
-static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams);
+static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params_old __user * _oparams);
+static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params_old __user * _oparams);
+#endif
+static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
/*
*
@@ -83,11 +88,11 @@ static inline void snd_leave_user(mm_segment_t fs)
-int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
+int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
{
- snd_pcm_runtime_t * runtime;
- snd_pcm_t *pcm = substream->pcm;
- snd_pcm_str_t *pstr = substream->pstr;
+ struct snd_pcm_runtime *runtime;
+ struct snd_pcm *pcm = substream->pcm;
+ struct snd_pcm_str *pstr = substream->pstr;
snd_assert(substream != NULL, return -ENXIO);
memset(info, 0, sizeof(*info));
@@ -111,9 +116,10 @@ int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
return 0;
}
-int snd_pcm_info_user(snd_pcm_substream_t * substream, snd_pcm_info_t __user * _info)
+int snd_pcm_info_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_info __user * _info)
{
- snd_pcm_info_t *info;
+ struct snd_pcm_info *info;
int err;
info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -151,14 +157,14 @@ char *snd_pcm_hw_param_names[] = {
};
#endif
-int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
unsigned int k;
- snd_pcm_hardware_t *hw;
- snd_interval_t *i = NULL;
- snd_mask_t *m = NULL;
- snd_pcm_hw_constraints_t *constrs = &substream->runtime->hw_constraints;
+ struct snd_pcm_hardware *hw;
+ struct snd_interval *i = NULL;
+ struct snd_mask *m = NULL;
+ struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints;
unsigned int rstamps[constrs->rules_num];
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp = 2;
@@ -231,7 +237,7 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
do {
again = 0;
for (k = 0; k < constrs->rules_num; k++) {
- snd_pcm_hw_rule_t *r = &constrs->rules[k];
+ struct snd_pcm_hw_rule *r = &constrs->rules[k];
unsigned int d;
int doit = 0;
if (r->cond && !(r->cond & params->flags))
@@ -313,9 +319,10 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
+static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params __user * _params)
{
- snd_pcm_hw_params_t *params;
+ struct snd_pcm_hw_params *params;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -337,10 +344,10 @@ out:
return err;
}
-static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int err;
unsigned int bits;
snd_pcm_uframes_t frames;
@@ -432,9 +439,10 @@ static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
return err;
}
-static int snd_pcm_hw_params_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
+static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params __user * _params)
{
- snd_pcm_hw_params_t *params;
+ struct snd_pcm_hw_params *params;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -456,9 +464,9 @@ out:
return err;
}
-static int snd_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
int result = 0;
snd_assert(substream != NULL, return -ENXIO);
@@ -482,9 +490,10 @@ static int snd_pcm_hw_free(snd_pcm_substream_t * substream)
return result;
}
-static int snd_pcm_sw_params(snd_pcm_substream_t * substream, snd_pcm_sw_params_t *params)
+static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_sw_params *params)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
snd_assert(substream != NULL, return -ENXIO);
runtime = substream->runtime;
@@ -537,9 +546,10 @@ static int snd_pcm_sw_params(snd_pcm_substream_t * substream, snd_pcm_sw_params_
return 0;
}
-static int snd_pcm_sw_params_user(snd_pcm_substream_t * substream, snd_pcm_sw_params_t __user * _params)
+static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_sw_params __user * _params)
{
- snd_pcm_sw_params_t params;
+ struct snd_pcm_sw_params params;
int err;
if (copy_from_user(&params, _params, sizeof(params)))
return -EFAULT;
@@ -549,10 +559,10 @@ static int snd_pcm_sw_params_user(snd_pcm_substream_t * substream, snd_pcm_sw_pa
return err;
}
-int snd_pcm_status(snd_pcm_substream_t *substream,
- snd_pcm_status_t *status)
+int snd_pcm_status(struct snd_pcm_substream *substream,
+ struct snd_pcm_status *status)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
status->state = runtime->status->state;
@@ -593,10 +603,11 @@ int snd_pcm_status(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t __user * _status)
+static int snd_pcm_status_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_status __user * _status)
{
- snd_pcm_status_t status;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_status status;
+ struct snd_pcm_runtime *runtime;
int res;
snd_assert(substream != NULL, return -ENXIO);
@@ -610,9 +621,10 @@ static int snd_pcm_status_user(snd_pcm_substream_t * substream, snd_pcm_status_t
return 0;
}
-static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info)
+static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info * info)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
unsigned int channel;
snd_assert(substream != NULL, return -ENXIO);
@@ -631,9 +643,10 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel
return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
}
-static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
+static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info __user * _info)
{
- snd_pcm_channel_info_t info;
+ struct snd_pcm_channel_info info;
int res;
if (copy_from_user(&info, _info, sizeof(info)))
@@ -646,9 +659,9 @@ static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_ch
return 0;
}
-static void snd_pcm_trigger_tstamp(snd_pcm_substream_t *substream)
+static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->trigger_master == NULL)
return;
if (runtime->trigger_master == substream) {
@@ -661,10 +674,10 @@ static void snd_pcm_trigger_tstamp(snd_pcm_substream_t *substream)
}
struct action_ops {
- int (*pre_action)(snd_pcm_substream_t *substream, int state);
- int (*do_action)(snd_pcm_substream_t *substream, int state);
- void (*undo_action)(snd_pcm_substream_t *substream, int state);
- void (*post_action)(snd_pcm_substream_t *substream, int state);
+ int (*pre_action)(struct snd_pcm_substream *substream, int state);
+ int (*do_action)(struct snd_pcm_substream *substream, int state);
+ void (*undo_action)(struct snd_pcm_substream *substream, int state);
+ void (*post_action)(struct snd_pcm_substream *substream, int state);
};
/*
@@ -673,12 +686,12 @@ struct action_ops {
* Note2: call with calling stream lock + link lock
*/
static int snd_pcm_action_group(struct action_ops *ops,
- snd_pcm_substream_t *substream,
+ struct snd_pcm_substream *substream,
int state, int do_lock)
{
struct list_head *pos;
- snd_pcm_substream_t *s = NULL;
- snd_pcm_substream_t *s1;
+ struct snd_pcm_substream *s = NULL;
+ struct snd_pcm_substream *s1;
int res = 0;
snd_pcm_group_for_each(pos, substream) {
@@ -727,7 +740,7 @@ static int snd_pcm_action_group(struct action_ops *ops,
* Note: call with stream lock
*/
static int snd_pcm_action_single(struct action_ops *ops,
- snd_pcm_substream_t *substream,
+ struct snd_pcm_substream *substream,
int state)
{
int res;
@@ -747,7 +760,7 @@ static int snd_pcm_action_single(struct action_ops *ops,
* Note: call with stream lock
*/
static int snd_pcm_action(struct action_ops *ops,
- snd_pcm_substream_t *substream,
+ struct snd_pcm_substream *substream,
int state)
{
int res;
@@ -770,7 +783,7 @@ static int snd_pcm_action(struct action_ops *ops,
* Note: don't use any locks before
*/
static int snd_pcm_action_lock_irq(struct action_ops *ops,
- snd_pcm_substream_t *substream,
+ struct snd_pcm_substream *substream,
int state)
{
int res;
@@ -794,7 +807,7 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops,
/*
*/
static int snd_pcm_action_nonatomic(struct action_ops *ops,
- snd_pcm_substream_t *substream,
+ struct snd_pcm_substream *substream,
int state)
{
int res;
@@ -811,9 +824,9 @@ static int snd_pcm_action_nonatomic(struct action_ops *ops,
/*
* start callbacks
*/
-static int snd_pcm_pre_start(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
return -EBADFD;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
@@ -823,22 +836,22 @@ static int snd_pcm_pre_start(snd_pcm_substream_t *substream, int state)
return 0;
}
-static int snd_pcm_do_start(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
{
if (substream->runtime->trigger_master != substream)
return 0;
return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
}
-static void snd_pcm_undo_start(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
{
if (substream->runtime->trigger_master == substream)
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
}
-static void snd_pcm_post_start(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
runtime->status->state = state;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
@@ -847,7 +860,8 @@ static void snd_pcm_post_start(snd_pcm_substream_t *substream, int state)
if (runtime->sleep_min)
snd_pcm_tick_prepare(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
+ &runtime->trigger_tstamp);
}
static struct action_ops snd_pcm_action_start = {
@@ -863,24 +877,25 @@ static struct action_ops snd_pcm_action_start = {
*
* Start all linked streams.
*/
-int snd_pcm_start(snd_pcm_substream_t *substream)
+int snd_pcm_start(struct snd_pcm_substream *substream)
{
- return snd_pcm_action(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
+ return snd_pcm_action(&snd_pcm_action_start, substream,
+ SNDRV_PCM_STATE_RUNNING);
}
/*
* stop callbacks
*/
-static int snd_pcm_pre_stop(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
runtime->trigger_master = substream;
return 0;
}
-static int snd_pcm_do_stop(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
{
if (substream->runtime->trigger_master == substream &&
snd_pcm_running(substream))
@@ -888,13 +903,14 @@ static int snd_pcm_do_stop(snd_pcm_substream_t *substream, int state)
return 0; /* unconditonally stop all substreams */
}
-static void snd_pcm_post_stop(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state != state) {
snd_pcm_trigger_tstamp(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
+ &runtime->trigger_tstamp);
runtime->status->state = state;
snd_pcm_tick_set(substream, 0);
}
@@ -915,7 +931,7 @@ static struct action_ops snd_pcm_action_stop = {
* Try to stop all running streams in the substream group.
* The state of each stream is changed to the given value after that unconditionally.
*/
-int snd_pcm_stop(snd_pcm_substream_t *substream, int state)
+int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
{
return snd_pcm_action(&snd_pcm_action_stop, substream, state);
}
@@ -928,17 +944,18 @@ int snd_pcm_stop(snd_pcm_substream_t *substream, int state)
* The state is changed to SETUP.
* Unlike snd_pcm_stop(), this affects only the given stream.
*/
-int snd_pcm_drain_done(snd_pcm_substream_t *substream)
+int snd_pcm_drain_done(struct snd_pcm_substream *substream)
{
- return snd_pcm_action_single(&snd_pcm_action_stop, substream, SNDRV_PCM_STATE_SETUP);
+ return snd_pcm_action_single(&snd_pcm_action_stop, substream,
+ SNDRV_PCM_STATE_SETUP);
}
/*
* pause callbacks
*/
-static int snd_pcm_pre_pause(snd_pcm_substream_t *substream, int push)
+static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
return -ENOSYS;
if (push) {
@@ -950,7 +967,7 @@ static int snd_pcm_pre_pause(snd_pcm_substream_t *substream, int push)
return 0;
}
-static int snd_pcm_do_pause(snd_pcm_substream_t *substream, int push)
+static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
{
if (substream->runtime->trigger_master != substream)
return 0;
@@ -959,7 +976,7 @@ static int snd_pcm_do_pause(snd_pcm_substream_t *substream, int push)
SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
}
-static void snd_pcm_undo_pause(snd_pcm_substream_t *substream, int push)
+static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
{
if (substream->runtime->trigger_master == substream)
substream->ops->trigger(substream,
@@ -967,14 +984,16 @@ static void snd_pcm_undo_pause(snd_pcm_substream_t *substream, int push)
SNDRV_PCM_TRIGGER_PAUSE_PUSH);
}
-static void snd_pcm_post_pause(snd_pcm_substream_t *substream, int push)
+static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (push) {
runtime->status->state = SNDRV_PCM_STATE_PAUSED;
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MPAUSE, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer,
+ SNDRV_TIMER_EVENT_MPAUSE,
+ &runtime->trigger_tstamp);
snd_pcm_tick_set(substream, 0);
wake_up(&runtime->sleep);
} else {
@@ -982,7 +1001,9 @@ static void snd_pcm_post_pause(snd_pcm_substream_t *substream, int push)
if (runtime->sleep_min)
snd_pcm_tick_prepare(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MCONTINUE, &runtime->trigger_tstamp);
+ snd_timer_notify(substream->timer,
+ SNDRV_TIMER_EVENT_MCONTINUE,
+ &runtime->trigger_tstamp);
}
}
@@ -996,7 +1017,7 @@ static struct action_ops snd_pcm_action_pause = {
/*
* Push/release the pause for all linked streams.
*/
-static int snd_pcm_pause(snd_pcm_substream_t *substream, int push)
+static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
{
return snd_pcm_action(&snd_pcm_action_pause, substream, push);
}
@@ -1004,18 +1025,18 @@ static int snd_pcm_pause(snd_pcm_substream_t *substream, int push)
#ifdef CONFIG_PM
/* suspend */
-static int snd_pcm_pre_suspend(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
return -EBUSY;
runtime->trigger_master = substream;
return 0;
}
-static int snd_pcm_do_suspend(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->trigger_master != substream)
return 0;
if (! snd_pcm_running(substream))
@@ -1024,12 +1045,13 @@ static int snd_pcm_do_suspend(snd_pcm_substream_t *substream, int state)
return 0; /* suspend unconditionally */
}
-static void snd_pcm_post_suspend(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSUSPEND, &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);
@@ -1049,11 +1071,14 @@ static struct action_ops snd_pcm_action_suspend = {
* Trigger SUSPEND to all linked streams.
* After this call, all streams are changed to SUSPENDED state.
*/
-int snd_pcm_suspend(snd_pcm_substream_t *substream)
+int snd_pcm_suspend(struct snd_pcm_substream *substream)
{
int err;
unsigned long flags;
+ if (! substream)
+ return 0;
+
snd_pcm_stream_lock_irqsave(substream, flags);
err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
snd_pcm_stream_unlock_irqrestore(substream, flags);
@@ -1067,13 +1092,17 @@ int snd_pcm_suspend(snd_pcm_substream_t *substream)
* Trigger SUSPEND to all substreams in the given pcm.
* After this call, all streams are changed to SUSPENDED state.
*/
-int snd_pcm_suspend_all(snd_pcm_t *pcm)
+int snd_pcm_suspend_all(struct snd_pcm *pcm)
{
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int stream, err = 0;
+ if (! pcm)
+ return 0;
+
for (stream = 0; stream < 2; stream++) {
- for (substream = pcm->streams[stream].substream; substream; substream = substream->next) {
+ for (substream = pcm->streams[stream].substream;
+ substream; substream = substream->next) {
/* FIXME: the open/close code should lock this as well */
if (substream->runtime == NULL)
continue;
@@ -1087,18 +1116,18 @@ int snd_pcm_suspend_all(snd_pcm_t *pcm)
/* resume */
-static int snd_pcm_pre_resume(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
return -ENOSYS;
runtime->trigger_master = substream;
return 0;
}
-static int snd_pcm_do_resume(snd_pcm_substream_t *substream, int state)
+static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->trigger_master != substream)
return 0;
/* DMA not running previously? */
@@ -1109,19 +1138,20 @@ static int snd_pcm_do_resume(snd_pcm_substream_t *substream, int state)
return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
}
-static void snd_pcm_undo_resume(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
{
if (substream->runtime->trigger_master == substream &&
snd_pcm_running(substream))
substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
}
-static void snd_pcm_post_resume(snd_pcm_substream_t *substream, int state)
+static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (substream->timer)
- snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME, &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);
@@ -1134,9 +1164,9 @@ static struct action_ops snd_pcm_action_resume = {
.post_action = snd_pcm_post_resume
};
-static int snd_pcm_resume(snd_pcm_substream_t *substream)
+static int snd_pcm_resume(struct snd_pcm_substream *substream)
{
- snd_card_t *card = substream->pcm->card;
+ struct snd_card *card = substream->pcm->card;
int res;
snd_power_lock(card);
@@ -1148,7 +1178,7 @@ static int snd_pcm_resume(snd_pcm_substream_t *substream)
#else
-static int snd_pcm_resume(snd_pcm_substream_t *substream)
+static int snd_pcm_resume(struct snd_pcm_substream *substream)
{
return -ENOSYS;
}
@@ -1160,10 +1190,10 @@ static int snd_pcm_resume(snd_pcm_substream_t *substream)
*
* Change the RUNNING stream(s) to XRUN state.
*/
-static int snd_pcm_xrun(snd_pcm_substream_t *substream)
+static int snd_pcm_xrun(struct snd_pcm_substream *substream)
{
- snd_card_t *card = substream->pcm->card;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_card *card = substream->pcm->card;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int result;
snd_power_lock(card);
@@ -1193,9 +1223,9 @@ static int snd_pcm_xrun(snd_pcm_substream_t *substream)
/*
* reset ioctl
*/
-static int snd_pcm_pre_reset(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
@@ -1207,23 +1237,24 @@ static int snd_pcm_pre_reset(snd_pcm_substream_t * substream, int state)
}
}
-static int snd_pcm_do_reset(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
if (err < 0)
return err;
// snd_assert(runtime->status->hw_ptr < runtime->buffer_size, );
runtime->hw_ptr_base = 0;
- runtime->hw_ptr_interrupt = runtime->status->hw_ptr - runtime->status->hw_ptr % runtime->period_size;
+ runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
+ runtime->status->hw_ptr % runtime->period_size;
runtime->silence_start = runtime->status->hw_ptr;
runtime->silence_filled = 0;
return 0;
}
-static void snd_pcm_post_reset(snd_pcm_substream_t * substream, int state)
+static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->control->appl_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
@@ -1236,7 +1267,7 @@ static struct action_ops snd_pcm_action_reset = {
.post_action = snd_pcm_post_reset
};
-static int snd_pcm_reset(snd_pcm_substream_t *substream)
+static int snd_pcm_reset(struct snd_pcm_substream *substream)
{
return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
}
@@ -1244,9 +1275,9 @@ static int snd_pcm_reset(snd_pcm_substream_t *substream)
/*
* prepare ioctl
*/
-static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (snd_pcm_running(substream))
@@ -1254,7 +1285,7 @@ static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
return 0;
}
-static int snd_pcm_do_prepare(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
{
int err;
err = substream->ops->prepare(substream);
@@ -1263,9 +1294,9 @@ static int snd_pcm_do_prepare(snd_pcm_substream_t * substream, int state)
return snd_pcm_do_reset(substream, 0);
}
-static void snd_pcm_post_prepare(snd_pcm_substream_t * substream, int state)
+static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->control->appl_ptr = runtime->status->hw_ptr;
runtime->status->state = SNDRV_PCM_STATE_PREPARED;
}
@@ -1282,10 +1313,10 @@ static struct action_ops snd_pcm_action_prepare = {
*
* Prepare the PCM substream to be triggerable.
*/
-int snd_pcm_prepare(snd_pcm_substream_t *substream)
+int snd_pcm_prepare(struct snd_pcm_substream *substream)
{
int res;
- snd_card_t *card = substream->pcm->card;
+ struct snd_card *card = substream->pcm->card;
snd_power_lock(card);
if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
@@ -1298,7 +1329,7 @@ int snd_pcm_prepare(snd_pcm_substream_t *substream)
* drain ioctl
*/
-static int snd_pcm_pre_drain_init(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
if (substream->ffile->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -1306,9 +1337,9 @@ static int snd_pcm_pre_drain_init(snd_pcm_substream_t * substream, int state)
return 0;
}
-static int snd_pcm_do_drain_init(snd_pcm_substream_t * substream, int state)
+static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
switch (runtime->status->state) {
case SNDRV_PCM_STATE_PREPARED:
@@ -1336,7 +1367,7 @@ static int snd_pcm_do_drain_init(snd_pcm_substream_t * substream, int state)
return 0;
}
-static void snd_pcm_post_drain_init(snd_pcm_substream_t * substream, int state)
+static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
{
}
@@ -1347,12 +1378,12 @@ static struct action_ops snd_pcm_action_drain_init = {
};
struct drain_rec {
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
wait_queue_t wait;
snd_pcm_uframes_t stop_threshold;
};
-static int snd_pcm_drop(snd_pcm_substream_t *substream);
+static int snd_pcm_drop(struct snd_pcm_substream *substream);
/*
* Drain the stream(s).
@@ -1361,10 +1392,10 @@ static int snd_pcm_drop(snd_pcm_substream_t *substream);
* After this call, all streams are supposed to be either SETUP or DRAINING
* (capture only) state.
*/
-static int snd_pcm_drain(snd_pcm_substream_t *substream)
+static int snd_pcm_drain(struct snd_pcm_substream *substream)
{
- snd_card_t *card;
- snd_pcm_runtime_t *runtime;
+ struct snd_card *card;
+ struct snd_pcm_runtime *runtime;
struct list_head *pos;
int result = 0;
int i, num_drecs;
@@ -1401,7 +1432,7 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
/* count only playback streams */
num_drecs = 0;
snd_pcm_group_for_each(pos, substream) {
- snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
+ struct snd_pcm_substream *s = snd_pcm_group_substream_entry(pos);
runtime = s->runtime;
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
d = &drec[num_drecs++];
@@ -1487,10 +1518,10 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
*
* Immediately put all linked substreams into SETUP state.
*/
-static int snd_pcm_drop(snd_pcm_substream_t *substream)
+static int snd_pcm_drop(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime;
- snd_card_t *card;
+ struct snd_pcm_runtime *runtime;
+ struct snd_card *card;
int result = 0;
snd_assert(substream != NULL, return -ENXIO);
@@ -1526,7 +1557,8 @@ static struct file *snd_pcm_file_fd(int fd)
{
struct file *file;
struct inode *inode;
- unsigned short minor;
+ unsigned int minor;
+
file = fget(fd);
if (!file)
return NULL;
@@ -1537,8 +1569,8 @@ static struct file *snd_pcm_file_fd(int fd)
return NULL;
}
minor = iminor(inode);
- if (minor >= 256 ||
- minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) {
+ if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
+ !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
fput(file);
return NULL;
}
@@ -1548,12 +1580,12 @@ static struct file *snd_pcm_file_fd(int fd)
/*
* PCM link handling
*/
-static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
+static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
{
int res = 0;
struct file *file;
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream1;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream1;
file = snd_pcm_file_fd(fd);
if (!file)
@@ -1572,7 +1604,7 @@ static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
goto _end;
}
if (!snd_pcm_stream_linked(substream)) {
- substream->group = kmalloc(sizeof(snd_pcm_group_t), GFP_ATOMIC);
+ substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC);
if (substream->group == NULL) {
res = -ENOMEM;
goto _end;
@@ -1592,14 +1624,14 @@ static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
return res;
}
-static void relink_to_local(snd_pcm_substream_t *substream)
+static void relink_to_local(struct snd_pcm_substream *substream)
{
substream->group = &substream->self_group;
INIT_LIST_HEAD(&substream->self_group.substreams);
list_add_tail(&substream->link_list, &substream->self_group.substreams);
}
-static int snd_pcm_unlink(snd_pcm_substream_t *substream)
+static int snd_pcm_unlink(struct snd_pcm_substream *substream)
{
struct list_head *pos;
int res = 0;
@@ -1629,51 +1661,51 @@ static int snd_pcm_unlink(snd_pcm_substream_t *substream)
/*
* hw configurator
*/
-static int snd_pcm_hw_rule_mul(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_mul(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
+ struct snd_interval t;
snd_interval_mul(hw_param_interval_c(params, rule->deps[0]),
hw_param_interval_c(params, rule->deps[1]), &t);
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
-static int snd_pcm_hw_rule_div(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_div(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
+ struct snd_interval t;
snd_interval_div(hw_param_interval_c(params, rule->deps[0]),
hw_param_interval_c(params, rule->deps[1]), &t);
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
-static int snd_pcm_hw_rule_muldivk(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_muldivk(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
+ struct snd_interval t;
snd_interval_muldivk(hw_param_interval_c(params, rule->deps[0]),
hw_param_interval_c(params, rule->deps[1]),
(unsigned long) rule->private, &t);
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
-static int snd_pcm_hw_rule_mulkdiv(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_mulkdiv(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
+ struct snd_interval t;
snd_interval_mulkdiv(hw_param_interval_c(params, rule->deps[0]),
(unsigned long) rule->private,
hw_param_interval_c(params, rule->deps[1]), &t);
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
-static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned int k;
- snd_interval_t *i = hw_param_interval(params, rule->deps[0]);
- snd_mask_t m;
- snd_mask_t *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_interval *i = hw_param_interval(params, rule->deps[0]);
+ struct snd_mask m;
+ struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_any(&m);
for (k = 0; k <= SNDRV_PCM_FORMAT_LAST; ++k) {
int bits;
@@ -1688,10 +1720,10 @@ static int snd_pcm_hw_rule_format(snd_pcm_hw_params_t *params,
return snd_mask_refine(mask, &m);
}
-static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
+ struct snd_interval t;
unsigned int k;
t.min = UINT_MAX;
t.max = 0;
@@ -1720,19 +1752,19 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
48000, 64000, 88200, 96000, 176400, 192000 };
-static int snd_pcm_hw_rule_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_pcm_hardware_t *hw = rule->private;
+ struct snd_pcm_hardware *hw = rule->private;
return snd_interval_list(hw_param_interval(params, rule->var),
ARRAY_SIZE(rates), rates, hw->rates);
}
-static int snd_pcm_hw_rule_buffer_bytes_max(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t t;
- snd_pcm_substream_t *substream = rule->private;
+ struct snd_interval t;
+ struct snd_pcm_substream *substream = rule->private;
t.min = 0;
t.max = substream->buffer_bytes_max;
t.openmin = 0;
@@ -1741,10 +1773,10 @@ static int snd_pcm_hw_rule_buffer_bytes_max(snd_pcm_hw_params_t *params,
return snd_interval_refine(hw_param_interval(params, rule->var), &t);
}
-int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream)
+int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_hw_constraints_t *constrs = &runtime->hw_constraints;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
int k, err;
for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) {
@@ -1865,10 +1897,10 @@ int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream)
return 0;
}
-int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream)
+int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_hardware_t *hw = &runtime->hw;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hardware *hw = &runtime->hw;
int err;
unsigned int mask = 0;
@@ -1941,17 +1973,17 @@ int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream)
return 0;
}
-static void snd_pcm_add_file(snd_pcm_str_t *str,
- snd_pcm_file_t *pcm_file)
+static void snd_pcm_add_file(struct snd_pcm_str *str,
+ struct snd_pcm_file *pcm_file)
{
pcm_file->next = str->files;
str->files = pcm_file;
}
-static void snd_pcm_remove_file(snd_pcm_str_t *str,
- snd_pcm_file_t *pcm_file)
+static void snd_pcm_remove_file(struct snd_pcm_str *str,
+ struct snd_pcm_file *pcm_file)
{
- snd_pcm_file_t * pcm_file1;
+ struct snd_pcm_file * pcm_file1;
if (str->files == pcm_file) {
str->files = pcm_file->next;
} else {
@@ -1963,11 +1995,11 @@ static void snd_pcm_remove_file(snd_pcm_str_t *str,
}
}
-static int snd_pcm_release_file(snd_pcm_file_t * pcm_file)
+static int snd_pcm_release_file(struct snd_pcm_file * pcm_file)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
- snd_pcm_str_t * str;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ struct snd_pcm_str * str;
snd_assert(pcm_file != NULL, return -ENXIO);
substream = pcm_file->substream;
@@ -1988,14 +2020,14 @@ static int snd_pcm_release_file(snd_pcm_file_t * pcm_file)
}
static int snd_pcm_open_file(struct file *file,
- snd_pcm_t *pcm,
+ struct snd_pcm *pcm,
int stream,
- snd_pcm_file_t **rpcm_file)
+ struct snd_pcm_file **rpcm_file)
{
int err = 0;
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_str_t *str;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_str *str;
snd_assert(rpcm_file != NULL, return -EINVAL);
*rpcm_file = NULL;
@@ -2043,18 +2075,30 @@ static int snd_pcm_open_file(struct file *file,
return 0;
}
-static int snd_pcm_open(struct inode *inode, struct file *file)
+static int snd_pcm_playback_open(struct inode *inode, struct file *file)
+{
+ struct snd_pcm *pcm;
+
+ pcm = snd_lookup_minor_data(iminor(inode),
+ SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
+ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+static int snd_pcm_capture_open(struct inode *inode, struct file *file)
+{
+ struct snd_pcm *pcm;
+
+ pcm = snd_lookup_minor_data(iminor(inode),
+ SNDRV_DEVICE_TYPE_PCM_CAPTURE);
+ return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+}
+
+static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
{
- int cardnum = SNDRV_MINOR_CARD(iminor(inode));
- int device = SNDRV_MINOR_DEVICE(iminor(inode));
int err;
- snd_pcm_t *pcm;
- snd_pcm_file_t *pcm_file;
+ struct snd_pcm_file *pcm_file;
wait_queue_t wait;
- if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES)
- return -ENXIO;
- pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)];
if (pcm == NULL) {
err = -ENODEV;
goto __error1;
@@ -2070,7 +2114,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
add_wait_queue(&pcm->open_wait, &wait);
down(&pcm->open_mutex);
while (1) {
- err = snd_pcm_open_file(file, pcm, device >= SNDRV_MINOR_PCM_CAPTURE ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, &pcm_file);
+ err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -2105,9 +2149,9 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
static int snd_pcm_release(struct inode *inode, struct file *file)
{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
- snd_pcm_file_t *pcm_file;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_file *pcm_file;
pcm_file = file->private_data;
substream = pcm_file->substream;
@@ -2125,9 +2169,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
return 0;
}
-static snd_pcm_sframes_t snd_pcm_playback_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t hw_avail;
@@ -2174,9 +2219,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(snd_pcm_substream_t *substream,
return ret;
}
-static snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t hw_avail;
@@ -2223,9 +2269,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream,
return ret;
}
-static snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t avail;
@@ -2273,9 +2320,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(snd_pcm_substream_t *substream
return ret;
}
-static snd_pcm_sframes_t snd_pcm_capture_forward(snd_pcm_substream_t *substream, snd_pcm_uframes_t frames)
+static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
snd_pcm_sframes_t avail;
@@ -2323,9 +2371,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(snd_pcm_substream_t *substream,
return ret;
}
-static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
+static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_stream_lock_irq(substream);
@@ -2353,9 +2401,10 @@ static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
return err;
}
-static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t __user *res)
+static int snd_pcm_delay(struct snd_pcm_substream *substream,
+ snd_pcm_sframes_t __user *res)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
@@ -2391,18 +2440,19 @@ static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t __use
return err;
}
-static int snd_pcm_sync_ptr(snd_pcm_substream_t *substream, struct sndrv_pcm_sync_ptr __user *_sync_ptr)
+static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
+ struct snd_pcm_sync_ptr __user *_sync_ptr)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- struct sndrv_pcm_sync_ptr sync_ptr;
- volatile struct sndrv_pcm_mmap_status *status;
- volatile struct sndrv_pcm_mmap_control *control;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_sync_ptr sync_ptr;
+ volatile struct snd_pcm_mmap_status *status;
+ volatile struct snd_pcm_mmap_control *control;
int err;
memset(&sync_ptr, 0, sizeof(sync_ptr));
if (get_user(sync_ptr.flags, (unsigned __user *)&(_sync_ptr->flags)))
return -EFAULT;
- if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct sndrv_pcm_mmap_control)))
+ if (copy_from_user(&sync_ptr.c.control, &(_sync_ptr->c.control), sizeof(struct snd_pcm_mmap_control)))
return -EFAULT;
status = runtime->status;
control = runtime->control;
@@ -2430,12 +2480,12 @@ static int snd_pcm_sync_ptr(snd_pcm_substream_t *substream, struct sndrv_pcm_syn
return 0;
}
-static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
+static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg);
-static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
+static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg);
-static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
+static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_assert(substream != NULL, return -ENXIO);
@@ -2479,10 +2529,12 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_delay(substream, arg);
case SNDRV_PCM_IOCTL_SYNC_PTR:
return snd_pcm_sync_ptr(substream, arg);
+#ifdef CONFIG_SND_SUPPORT_OLD_API
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
return snd_pcm_hw_refine_old_user(substream, arg);
case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
return snd_pcm_hw_params_old_user(substream, arg);
+#endif
case SNDRV_PCM_IOCTL_DRAIN:
return snd_pcm_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
@@ -2492,7 +2544,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return -ENOTTY;
}
-static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
+static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_assert(substream != NULL, return -ENXIO);
@@ -2500,9 +2552,9 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
{
- snd_xferi_t xferi;
- snd_xferi_t __user *_xferi = arg;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_xferi xferi;
+ struct snd_xferi __user *_xferi = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2516,9 +2568,9 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
}
case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
{
- snd_xfern_t xfern;
- snd_xfern_t __user *_xfern = arg;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_xfern xfern;
+ struct snd_xfern __user *_xfern = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
void __user **bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
@@ -2579,7 +2631,7 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
-static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
+static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_assert(substream != NULL, return -ENXIO);
@@ -2587,9 +2639,9 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
switch (cmd) {
case SNDRV_PCM_IOCTL_READI_FRAMES:
{
- snd_xferi_t xferi;
- snd_xferi_t __user *_xferi = arg;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_xferi xferi;
+ struct snd_xferi __user *_xferi = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2603,9 +2655,9 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
}
case SNDRV_PCM_IOCTL_READN_FRAMES:
{
- snd_xfern_t xfern;
- snd_xfern_t __user *_xfern = arg;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_xfern xfern;
+ struct snd_xfern __user *_xfern = arg;
+ struct snd_pcm_runtime *runtime = substream->runtime;
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
@@ -2658,9 +2710,10 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
-static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
- snd_pcm_file_t *pcm_file;
+ struct snd_pcm_file *pcm_file;
pcm_file = file->private_data;
@@ -2670,9 +2723,10 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned
return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
-static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
- snd_pcm_file_t *pcm_file;
+ struct snd_pcm_file *pcm_file;
pcm_file = file->private_data;
@@ -2682,7 +2736,7 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned
return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
}
-int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
+int snd_pcm_kernel_playback_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
mm_segment_t fs;
@@ -2694,7 +2748,7 @@ int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
return result;
}
-int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
+int snd_pcm_kernel_capture_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
mm_segment_t fs;
@@ -2706,7 +2760,7 @@ int snd_pcm_kernel_capture_ioctl(snd_pcm_substream_t *substream,
return result;
}
-int snd_pcm_kernel_ioctl(snd_pcm_substream_t *substream,
+int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (substream->stream) {
@@ -2719,11 +2773,12 @@ int snd_pcm_kernel_ioctl(snd_pcm_substream_t *substream,
}
}
-static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, loff_t * offset)
+static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
+ loff_t * offset)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
pcm_file = file->private_data;
@@ -2741,11 +2796,12 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, l
return result;
}
-static ssize_t snd_pcm_write(struct file *file, const char __user *buf, size_t count, loff_t * offset)
+static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
+ size_t count, loff_t * offset)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
pcm_file = file->private_data;
@@ -2772,9 +2828,9 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
unsigned long count, loff_t * offset)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs;
@@ -2806,9 +2862,9 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
unsigned long count, loff_t * offset)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs;
@@ -2843,9 +2899,9 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
unsigned int mask;
snd_pcm_uframes_t avail;
@@ -2881,9 +2937,9 @@ static unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
{
- snd_pcm_file_t *pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file *pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
unsigned int mask;
snd_pcm_uframes_t avail;
@@ -2933,10 +2989,11 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
/*
* mmap status record
*/
-static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = area->vm_private_data;
+ struct snd_pcm_runtime *runtime;
struct page * page;
if (substream == NULL)
@@ -2954,17 +3011,17 @@ static struct vm_operations_struct snd_pcm_vm_ops_status =
.nopage = snd_pcm_mmap_status_nopage,
};
-static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
long size;
if (!(area->vm_flags & VM_READ))
return -EINVAL;
runtime = substream->runtime;
snd_assert(runtime != NULL, return -EAGAIN);
size = area->vm_end - area->vm_start;
- if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_status_t)))
+ if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_status)))
return -EINVAL;
area->vm_ops = &snd_pcm_vm_ops_status;
area->vm_private_data = substream;
@@ -2975,10 +3032,11 @@ static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file
/*
* mmap control record
*/
-static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = area->vm_private_data;
+ struct snd_pcm_runtime *runtime;
struct page * page;
if (substream == NULL)
@@ -2996,17 +3054,17 @@ static struct vm_operations_struct snd_pcm_vm_ops_control =
.nopage = snd_pcm_mmap_control_nopage,
};
-static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file,
+static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
long size;
if (!(area->vm_flags & VM_READ))
return -EINVAL;
runtime = substream->runtime;
snd_assert(runtime != NULL, return -EAGAIN);
size = area->vm_end - area->vm_start;
- if (size != PAGE_ALIGN(sizeof(snd_pcm_mmap_control_t)))
+ if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
return -EINVAL;
area->vm_ops = &snd_pcm_vm_ops_control;
area->vm_private_data = substream;
@@ -3017,12 +3075,12 @@ static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *fil
/*
* don't support mmap for status and control records.
*/
-static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
return -ENXIO;
}
-static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file,
+static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
return -ENXIO;
@@ -3032,10 +3090,11 @@ static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *fil
/*
* nopage callback for mmapping a RAM page
*/
-static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
+ unsigned long address, int *type)
{
- snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream = area->vm_private_data;
+ struct snd_pcm_runtime *runtime;
unsigned long offset;
struct page * page;
void *vaddr;
@@ -3074,7 +3133,8 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
/*
* mmap the DMA buffer on RAM
*/
-static int snd_pcm_default_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *area)
{
area->vm_ops = &snd_pcm_vm_ops_data;
area->vm_private_data = substream;
@@ -3093,7 +3153,8 @@ static struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
.close = snd_pcm_mmap_data_close,
};
-int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
+ struct vm_area_struct *area)
{
long size;
unsigned long offset;
@@ -3118,10 +3179,10 @@ int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct
/*
* mmap DMA buffer
*/
-int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
+int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
struct vm_area_struct *area)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
long size;
unsigned long offset;
size_t dma_bytes;
@@ -3158,8 +3219,8 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
{
- snd_pcm_file_t * pcm_file;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_file * pcm_file;
+ struct snd_pcm_substream *substream;
unsigned long offset;
pcm_file = file->private_data;
@@ -3184,9 +3245,9 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
static int snd_pcm_fasync(int fd, struct file * file, int on)
{
- snd_pcm_file_t * pcm_file;
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_file * pcm_file;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
int err;
pcm_file = file->private_data;
@@ -3213,10 +3274,12 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
* To be removed helpers to keep binary compatibility
*/
+#ifdef CONFIG_SND_SUPPORT_OLD_API
#define __OLD_TO_NEW_MASK(x) ((x&7)|((x&0x07fffff8)<<5))
#define __NEW_TO_OLD_MASK(x) ((x&7)|((x&0xffffff00)>>5))
-static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, struct sndrv_pcm_hw_params_old *oparams)
+static void snd_pcm_hw_convert_from_old_params(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_params_old *oparams)
{
unsigned int i;
@@ -3234,7 +3297,8 @@ static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, stru
params->fifo_size = oparams->fifo_size;
}
-static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *oparams, snd_pcm_hw_params_t *params)
+static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *oparams,
+ struct snd_pcm_hw_params *params)
{
unsigned int i;
@@ -3252,10 +3316,11 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *opa
oparams->fifo_size = params->fifo_size;
}
-static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
+static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params_old __user * _oparams)
{
- snd_pcm_hw_params_t *params;
- struct sndrv_pcm_hw_params_old *oparams = NULL;
+ struct snd_pcm_hw_params *params;
+ struct snd_pcm_hw_params_old *oparams = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -3286,10 +3351,11 @@ out:
return err;
}
-static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
+static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params_old __user * _oparams)
{
- snd_pcm_hw_params_t *params;
- struct sndrv_pcm_hw_params_old *oparams = NULL;
+ struct snd_pcm_hw_params *params;
+ struct snd_pcm_hw_params_old *oparams = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -3318,45 +3384,35 @@ out:
kfree(oparams);
return err;
}
+#endif /* CONFIG_SND_SUPPORT_OLD_API */
/*
* Register section
*/
-static struct file_operations snd_pcm_f_ops_playback = {
- .owner = THIS_MODULE,
- .write = snd_pcm_write,
- .writev = snd_pcm_writev,
- .open = snd_pcm_open,
- .release = snd_pcm_release,
- .poll = snd_pcm_playback_poll,
- .unlocked_ioctl = snd_pcm_playback_ioctl,
- .compat_ioctl = snd_pcm_ioctl_compat,
- .mmap = snd_pcm_mmap,
- .fasync = snd_pcm_fasync,
-};
-
-static struct file_operations snd_pcm_f_ops_capture = {
- .owner = THIS_MODULE,
- .read = snd_pcm_read,
- .readv = snd_pcm_readv,
- .open = snd_pcm_open,
- .release = snd_pcm_release,
- .poll = snd_pcm_capture_poll,
- .unlocked_ioctl = snd_pcm_capture_ioctl,
- .compat_ioctl = snd_pcm_ioctl_compat,
- .mmap = snd_pcm_mmap,
- .fasync = snd_pcm_fasync,
-};
-
-snd_minor_t snd_pcm_reg[2] =
-{
+struct file_operations snd_pcm_f_ops[2] = {
{
- .comment = "digital audio playback",
- .f_ops = &snd_pcm_f_ops_playback,
+ .owner = THIS_MODULE,
+ .write = snd_pcm_write,
+ .writev = snd_pcm_writev,
+ .open = snd_pcm_playback_open,
+ .release = snd_pcm_release,
+ .poll = snd_pcm_playback_poll,
+ .unlocked_ioctl = snd_pcm_playback_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
+ .fasync = snd_pcm_fasync,
},
{
- .comment = "digital audio capture",
- .f_ops = &snd_pcm_f_ops_capture,
+ .owner = THIS_MODULE,
+ .read = snd_pcm_read,
+ .readv = snd_pcm_readv,
+ .open = snd_pcm_capture_open,
+ .release = snd_pcm_release,
+ .poll = snd_pcm_capture_poll,
+ .unlocked_ioctl = snd_pcm_capture_ioctl,
+ .compat_ioctl = snd_pcm_ioctl_compat,
+ .mmap = snd_pcm_mmap,
+ .fasync = snd_pcm_fasync,
}
};
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 884eaea31fec..d94ed16d21ea 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -45,10 +45,10 @@ static unsigned long gcd(unsigned long a, unsigned long b)
return b;
}
-void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
+void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
{
unsigned long rate, mult, fsize, l, post;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
mult = 1000000000;
rate = runtime->rate;
@@ -74,18 +74,18 @@ void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
runtime->timer_resolution = (mult * fsize / rate) * post;
}
-static unsigned long snd_pcm_timer_resolution(snd_timer_t * timer)
+static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
{
- snd_pcm_substream_t * substream;
+ struct snd_pcm_substream *substream;
substream = timer->private_data;
return substream->runtime ? substream->runtime->timer_resolution : 0;
}
-static int snd_pcm_timer_start(snd_timer_t * timer)
+static int snd_pcm_timer_start(struct snd_timer * timer)
{
unsigned long flags;
- snd_pcm_substream_t * substream;
+ struct snd_pcm_substream *substream;
substream = snd_timer_chip(timer);
spin_lock_irqsave(&substream->timer_lock, flags);
@@ -94,10 +94,10 @@ static int snd_pcm_timer_start(snd_timer_t * timer)
return 0;
}
-static int snd_pcm_timer_stop(snd_timer_t * timer)
+static int snd_pcm_timer_stop(struct snd_timer * timer)
{
unsigned long flags;
- snd_pcm_substream_t * substream;
+ struct snd_pcm_substream *substream;
substream = snd_timer_chip(timer);
spin_lock_irqsave(&substream->timer_lock, flags);
@@ -106,7 +106,7 @@ static int snd_pcm_timer_stop(snd_timer_t * timer)
return 0;
}
-static struct _snd_timer_hardware snd_pcm_timer =
+static struct snd_timer_hardware snd_pcm_timer =
{
.flags = SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_SLAVE,
.resolution = 0,
@@ -120,16 +120,16 @@ static struct _snd_timer_hardware snd_pcm_timer =
* Init functions
*/
-static void snd_pcm_timer_free(snd_timer_t *timer)
+static void snd_pcm_timer_free(struct snd_timer *timer)
{
- snd_pcm_substream_t *substream = timer->private_data;
+ struct snd_pcm_substream *substream = timer->private_data;
substream->timer = NULL;
}
-void snd_pcm_timer_init(snd_pcm_substream_t *substream)
+void snd_pcm_timer_init(struct snd_pcm_substream *substream)
{
- snd_timer_id_t tid;
- snd_timer_t *timer;
+ struct snd_timer_id tid;
+ struct snd_timer *timer;
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
tid.dev_class = SNDRV_TIMER_CLASS_PCM;
@@ -152,7 +152,7 @@ void snd_pcm_timer_init(snd_pcm_substream_t *substream)
substream->timer = timer;
}
-void snd_pcm_timer_done(snd_pcm_substream_t *substream)
+void snd_pcm_timer_done(struct snd_pcm_substream *substream)
{
if (substream->timer) {
snd_device_free(substream->pcm->card, substream->timer);
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index d033e61c05c7..d4d124e21924 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -50,16 +50,28 @@ module_param_array(amidi_map, int, NULL, 0444);
MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
#endif /* CONFIG_SND_OSSEMUL */
-static int snd_rawmidi_free(snd_rawmidi_t *rawmidi);
-static int snd_rawmidi_dev_free(snd_device_t *device);
-static int snd_rawmidi_dev_register(snd_device_t *device);
-static int snd_rawmidi_dev_disconnect(snd_device_t *device);
-static int snd_rawmidi_dev_unregister(snd_device_t *device);
-
-static snd_rawmidi_t *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES];
+static int snd_rawmidi_free(struct snd_rawmidi *rawmidi);
+static int snd_rawmidi_dev_free(struct snd_device *device);
+static int snd_rawmidi_dev_register(struct snd_device *device);
+static int snd_rawmidi_dev_disconnect(struct snd_device *device);
+static int snd_rawmidi_dev_unregister(struct snd_device *device);
+static LIST_HEAD(snd_rawmidi_devices);
static DECLARE_MUTEX(register_mutex);
+static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
+{
+ struct list_head *p;
+ struct snd_rawmidi *rawmidi;
+
+ list_for_each(p, &snd_rawmidi_devices) {
+ rawmidi = list_entry(p, struct snd_rawmidi, list);
+ if (rawmidi->card == card && rawmidi->device == device)
+ return rawmidi;
+ }
+ return NULL;
+}
+
static inline unsigned short snd_rawmidi_file_flags(struct file *file)
{
switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
@@ -72,34 +84,35 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file)
}
}
-static inline int snd_rawmidi_ready(snd_rawmidi_substream_t * substream)
+static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
return runtime->avail >= runtime->avail_min;
}
-static inline int snd_rawmidi_ready_append(snd_rawmidi_substream_t * substream, size_t count)
+static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream,
+ size_t count)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
return runtime->avail >= runtime->avail_min &&
(!substream->append || runtime->avail >= count);
}
static void snd_rawmidi_input_event_tasklet(unsigned long data)
{
- snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data;
+ struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
substream->runtime->event(substream);
}
static void snd_rawmidi_output_trigger_tasklet(unsigned long data)
{
- snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data;
+ struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *)data;
substream->ops->trigger(substream, 1);
}
-static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
+static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)
{
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi_runtime *runtime;
if ((runtime = kzalloc(sizeof(*runtime), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -129,9 +142,9 @@ static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream)
+static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
kfree(runtime->buffer);
kfree(runtime);
@@ -139,7 +152,7 @@ static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream)
return 0;
}
-static inline void snd_rawmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up)
{
if (up) {
tasklet_hi_schedule(&substream->runtime->tasklet);
@@ -149,17 +162,17 @@ static inline void snd_rawmidi_output_trigger(snd_rawmidi_substream_t * substrea
}
}
-static void snd_rawmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
substream->ops->trigger(substream, up);
if (!up && substream->runtime->event)
tasklet_kill(&substream->runtime->tasklet);
}
-int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream)
+int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
snd_rawmidi_output_trigger(substream, 0);
runtime->drain = 0;
@@ -170,11 +183,11 @@ int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream)
return 0;
}
-int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
+int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)
{
int err;
long timeout;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
err = 0;
runtime->drain = 1;
@@ -199,10 +212,10 @@ int snd_rawmidi_drain_output(snd_rawmidi_substream_t * substream)
return err;
}
-int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream)
+int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
snd_rawmidi_input_trigger(substream, 0);
runtime->drain = 0;
@@ -213,18 +226,20 @@ int snd_rawmidi_drain_input(snd_rawmidi_substream_t * substream)
return 0;
}
-int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
- int mode, snd_rawmidi_file_t * rfile)
+int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
+ int mode, struct snd_rawmidi_file * rfile)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
struct list_head *list1, *list2;
- snd_rawmidi_substream_t *sinput = NULL, *soutput = NULL;
- snd_rawmidi_runtime_t *input = NULL, *output = NULL;
+ struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
+ struct snd_rawmidi_runtime *input = NULL, *output = NULL;
int err;
if (rfile)
rfile->input = rfile->output = NULL;
- rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
+ down(&register_mutex);
+ rmidi = snd_rawmidi_search(card, device);
+ up(&register_mutex);
if (rmidi == NULL) {
err = -ENODEV;
goto __error1;
@@ -275,7 +290,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
}
break;
}
- sinput = list_entry(list1, snd_rawmidi_substream_t, list);
+ sinput = list_entry(list1, struct snd_rawmidi_substream, list);
if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened)
goto __nexti;
if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number))
@@ -293,7 +308,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
}
break;
}
- soutput = list_entry(list2, snd_rawmidi_substream_t, list);
+ soutput = list_entry(list2, struct snd_rawmidi_substream, list);
if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
if (mode & SNDRV_RAWMIDI_LFLG_APPEND) {
if (soutput->opened && !soutput->append)
@@ -367,39 +382,29 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
static int snd_rawmidi_open(struct inode *inode, struct file *file)
{
int maj = imajor(inode);
- int cardnum;
- snd_card_t *card;
- int device, subdevice;
+ struct snd_card *card;
+ int subdevice;
unsigned short fflags;
int err;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_file_t *rawmidi_file;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_file *rawmidi_file;
wait_queue_t wait;
struct list_head *list;
- snd_ctl_file_t *kctl;
+ struct snd_ctl_file *kctl;
if (maj == snd_major) {
- cardnum = SNDRV_MINOR_CARD(iminor(inode));
- cardnum %= SNDRV_CARDS;
- device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI;
- device %= SNDRV_MINOR_RAWMIDIS;
+ rmidi = snd_lookup_minor_data(iminor(inode),
+ SNDRV_DEVICE_TYPE_RAWMIDI);
#ifdef CONFIG_SND_OSSEMUL
} else if (maj == SOUND_MAJOR) {
- cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
- cardnum %= SNDRV_CARDS;
- device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ?
- midi_map[cardnum] : amidi_map[cardnum];
+ rmidi = snd_lookup_oss_minor_data(iminor(inode),
+ SNDRV_OSS_DEVICE_TYPE_MIDI);
#endif
} else
return -ENXIO;
- rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
if (rmidi == NULL)
return -ENODEV;
-#ifdef CONFIG_SND_OSSEMUL
- if (maj == SOUND_MAJOR && !rmidi->ossreg)
- return -ENXIO;
-#endif
if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
return -EINVAL; /* invalid combination */
card = rmidi->card;
@@ -429,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
}
}
up_read(&card->controls_rwsem);
- err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file);
+ err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
+ subdevice, fflags, rawmidi_file);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -465,11 +471,11 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
return err;
}
-int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
+int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
{
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *substream;
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *substream;
+ struct snd_rawmidi_runtime *runtime;
snd_assert(rfile != NULL, return -ENXIO);
snd_assert(rfile->input != NULL || rfile->output != NULL, return -ENXIO);
@@ -515,8 +521,8 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
static int snd_rawmidi_release(struct inode *inode, struct file *file)
{
- snd_rawmidi_file_t *rfile;
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi_file *rfile;
+ struct snd_rawmidi *rmidi;
int err;
rfile = file->private_data;
@@ -528,9 +534,10 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
return err;
}
-int snd_rawmidi_info(snd_rawmidi_substream_t *substream, snd_rawmidi_info_t *info)
+static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_info *info)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
if (substream == NULL)
return -ENODEV;
@@ -550,26 +557,30 @@ int snd_rawmidi_info(snd_rawmidi_substream_t *substream, snd_rawmidi_info_t *inf
return 0;
}
-static int snd_rawmidi_info_user(snd_rawmidi_substream_t *substream, snd_rawmidi_info_t __user * _info)
+static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_info __user * _info)
{
- snd_rawmidi_info_t info;
+ struct snd_rawmidi_info info;
int err;
if ((err = snd_rawmidi_info(substream, &info)) < 0)
return err;
- if (copy_to_user(_info, &info, sizeof(snd_rawmidi_info_t)))
+ if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
return -EFAULT;
return 0;
}
-int snd_rawmidi_info_select(snd_card_t *card, snd_rawmidi_info_t *info)
+int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info)
{
- snd_rawmidi_t *rmidi;
- snd_rawmidi_str_t *pstr;
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_str *pstr;
+ struct snd_rawmidi_substream *substream;
struct list_head *list;
- if (info->device >= SNDRV_RAWMIDI_DEVICES)
+
+ down(&register_mutex);
+ rmidi = snd_rawmidi_search(card, info->device);
+ up(&register_mutex);
+ if (!rmidi)
return -ENXIO;
- rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device];
if (info->stream < 0 || info->stream > 1)
return -EINVAL;
pstr = &rmidi->streams[info->stream];
@@ -578,18 +589,18 @@ int snd_rawmidi_info_select(snd_card_t *card, snd_rawmidi_info_t *info)
if (info->subdevice >= pstr->substream_count)
return -ENXIO;
list_for_each(list, &pstr->substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
if ((unsigned int)substream->number == info->subdevice)
return snd_rawmidi_info(substream, info);
}
return -ENXIO;
}
-static int snd_rawmidi_info_select_user(snd_card_t *card,
- snd_rawmidi_info_t __user *_info)
+static int snd_rawmidi_info_select_user(struct snd_card *card,
+ struct snd_rawmidi_info __user *_info)
{
int err;
- snd_rawmidi_info_t info;
+ struct snd_rawmidi_info info;
if (get_user(info.device, &_info->device))
return -EFAULT;
if (get_user(info.stream, &_info->stream))
@@ -598,16 +609,16 @@ static int snd_rawmidi_info_select_user(snd_card_t *card,
return -EFAULT;
if ((err = snd_rawmidi_info_select(card, &info)) < 0)
return err;
- if (copy_to_user(_info, &info, sizeof(snd_rawmidi_info_t)))
+ if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))
return -EFAULT;
return 0;
}
-int snd_rawmidi_output_params(snd_rawmidi_substream_t * substream,
- snd_rawmidi_params_t * params)
+int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_params * params)
{
char *newbuf;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
if (substream->append && substream->use_count > 1)
return -EBUSY;
@@ -624,17 +635,18 @@ int snd_rawmidi_output_params(snd_rawmidi_substream_t * substream,
kfree(runtime->buffer);
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
+ runtime->avail = runtime->buffer_size;
}
runtime->avail_min = params->avail_min;
substream->active_sensing = !params->no_active_sensing;
return 0;
}
-int snd_rawmidi_input_params(snd_rawmidi_substream_t * substream,
- snd_rawmidi_params_t * params)
+int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_params * params)
{
char *newbuf;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
snd_rawmidi_drain_input(substream);
if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
@@ -654,10 +666,10 @@ int snd_rawmidi_input_params(snd_rawmidi_substream_t * substream,
return 0;
}
-static int snd_rawmidi_output_status(snd_rawmidi_substream_t * substream,
- snd_rawmidi_status_t * status)
+static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_status * status)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
memset(status, 0, sizeof(*status));
status->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
@@ -667,10 +679,10 @@ static int snd_rawmidi_output_status(snd_rawmidi_substream_t * substream,
return 0;
}
-static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream,
- snd_rawmidi_status_t * status)
+static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
+ struct snd_rawmidi_status * status)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
memset(status, 0, sizeof(*status));
status->stream = SNDRV_RAWMIDI_STREAM_INPUT;
@@ -684,7 +696,7 @@ static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream,
static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_rawmidi_file_t *rfile;
+ struct snd_rawmidi_file *rfile;
void __user *argp = (void __user *)arg;
rfile = file->private_data;
@@ -695,8 +707,8 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
return put_user(SNDRV_RAWMIDI_VERSION, (int __user *)argp) ? -EFAULT : 0;
case SNDRV_RAWMIDI_IOCTL_INFO:
{
- snd_rawmidi_stream_t stream;
- snd_rawmidi_info_t __user *info = argp;
+ int stream;
+ struct snd_rawmidi_info __user *info = argp;
if (get_user(stream, &info->stream))
return -EFAULT;
switch (stream) {
@@ -710,8 +722,8 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
}
case SNDRV_RAWMIDI_IOCTL_PARAMS:
{
- snd_rawmidi_params_t params;
- if (copy_from_user(&params, argp, sizeof(snd_rawmidi_params_t)))
+ struct snd_rawmidi_params params;
+ if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))
return -EFAULT;
switch (params.stream) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
@@ -729,8 +741,8 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
case SNDRV_RAWMIDI_IOCTL_STATUS:
{
int err = 0;
- snd_rawmidi_status_t status;
- if (copy_from_user(&status, argp, sizeof(snd_rawmidi_status_t)))
+ struct snd_rawmidi_status status;
+ if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
return -EFAULT;
switch (status.stream) {
case SNDRV_RAWMIDI_STREAM_OUTPUT:
@@ -748,7 +760,7 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
}
if (err < 0)
return err;
- if (copy_to_user(argp, &status, sizeof(snd_rawmidi_status_t)))
+ if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status)))
return -EFAULT;
return 0;
}
@@ -792,15 +804,13 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
return -ENOTTY;
}
-static int snd_rawmidi_control_ioctl(snd_card_t * card,
- snd_ctl_file_t * control,
+static int snd_rawmidi_control_ioctl(struct snd_card *card,
+ struct snd_ctl_file *control,
unsigned int cmd,
unsigned long arg)
{
void __user *argp = (void __user *)arg;
- unsigned int tmp;
- tmp = card->number * SNDRV_RAWMIDI_DEVICES;
switch (cmd) {
case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
{
@@ -808,14 +818,16 @@ static int snd_rawmidi_control_ioctl(snd_card_t * card,
if (get_user(device, (int __user *)argp))
return -EFAULT;
+ down(&register_mutex);
device = device < 0 ? 0 : device + 1;
while (device < SNDRV_RAWMIDI_DEVICES) {
- if (snd_rawmidi_devices[tmp + device])
+ if (snd_rawmidi_search(card, device))
break;
device++;
}
if (device == SNDRV_RAWMIDI_DEVICES)
device = -1;
+ up(&register_mutex);
if (put_user(device, (int __user *)argp))
return -EFAULT;
return 0;
@@ -845,11 +857,12 @@ static int snd_rawmidi_control_ioctl(snd_card_t * card,
*
* Returns the size of read data, or a negative error code on failure.
*/
-int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char *buffer, int count)
+int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
+ const unsigned char *buffer, int count)
{
unsigned long flags;
int result = 0, count1;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
if (runtime->buffer == NULL) {
snd_printd("snd_rawmidi_receive: input is not active!!!\n");
@@ -904,12 +917,12 @@ int snd_rawmidi_receive(snd_rawmidi_substream_t * substream, const unsigned char
return result;
}
-static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
+static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
unsigned char *buf, long count, int kernel)
{
unsigned long flags;
long result = 0, count1;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
@@ -938,19 +951,21 @@ static long snd_rawmidi_kernel_read1(snd_rawmidi_substream_t *substream,
return result;
}
-long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count)
+long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,
+ unsigned char *buf, long count)
{
snd_rawmidi_input_trigger(substream, 1);
return snd_rawmidi_kernel_read1(substream, buf, count, 1);
}
-static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,
+ loff_t *offset)
{
long result;
int count1;
- snd_rawmidi_file_t *rfile;
- snd_rawmidi_substream_t *substream;
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi_file *rfile;
+ struct snd_rawmidi_substream *substream;
+ struct snd_rawmidi_runtime *runtime;
rfile = file->private_data;
substream = rfile->input;
@@ -998,9 +1013,9 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
*
* Returns 1 if the internal output buffer is empty, 0 if not.
*/
-int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream)
+int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
{
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
int result;
unsigned long flags;
@@ -1028,11 +1043,12 @@ int snd_rawmidi_transmit_empty(snd_rawmidi_substream_t * substream)
*
* Returns the size of copied data, or a negative error code on failure.
*/
-int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char *buffer, int count)
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
{
unsigned long flags;
int result, count1;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
if (runtime->buffer == NULL) {
snd_printd("snd_rawmidi_transmit_peek: output is not active!!!\n");
@@ -1079,10 +1095,10 @@ int snd_rawmidi_transmit_peek(snd_rawmidi_substream_t * substream, unsigned char
*
* Returns the advanced size if successful, or a negative error code on failure.
*/
-int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
{
unsigned long flags;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
if (runtime->buffer == NULL) {
snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");
@@ -1112,7 +1128,8 @@ int snd_rawmidi_transmit_ack(snd_rawmidi_substream_t * substream, int count)
*
* Returns the copied size if successful, or a negative error code on failure.
*/
-int snd_rawmidi_transmit(snd_rawmidi_substream_t * substream, unsigned char *buffer, int count)
+int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
{
count = snd_rawmidi_transmit_peek(substream, buffer, count);
if (count < 0)
@@ -1120,11 +1137,12 @@ int snd_rawmidi_transmit(snd_rawmidi_substream_t * substream, unsigned char *buf
return snd_rawmidi_transmit_ack(substream, count);
}
-static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const unsigned char *buf, long count, int kernel)
+static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
+ const unsigned char *buf, long count, int kernel)
{
unsigned long flags;
long count1, result;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
snd_assert(buf != NULL, return -EINVAL);
snd_assert(runtime->buffer != NULL, return -EINVAL);
@@ -1170,18 +1188,20 @@ static long snd_rawmidi_kernel_write1(snd_rawmidi_substream_t * substream, const
return result;
}
-long snd_rawmidi_kernel_write(snd_rawmidi_substream_t * substream, const unsigned char *buf, long count)
+long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,
+ const unsigned char *buf, long count)
{
return snd_rawmidi_kernel_write1(substream, buf, count, 1);
}
-static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
{
long result, timeout;
int count1;
- snd_rawmidi_file_t *rfile;
- snd_rawmidi_runtime_t *runtime;
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_file *rfile;
+ struct snd_rawmidi_runtime *runtime;
+ struct snd_rawmidi_substream *substream;
rfile = file->private_data;
substream = rfile->output;
@@ -1246,8 +1266,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
{
- snd_rawmidi_file_t *rfile;
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi_file *rfile;
+ struct snd_rawmidi_runtime *runtime;
unsigned int mask;
rfile = file->private_data;
@@ -1284,12 +1304,12 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
*/
-static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *substream;
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *substream;
+ struct snd_rawmidi_runtime *runtime;
struct list_head *list;
rmidi = entry->private_data;
@@ -1297,7 +1317,7 @@ static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry,
down(&rmidi->open_mutex);
if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
snd_iprintf(buffer,
"Output %d\n"
" Tx bytes : %lu\n",
@@ -1317,7 +1337,7 @@ static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry,
}
if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {
list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
snd_iprintf(buffer,
"Input %d\n"
" Rx bytes : %lu\n",
@@ -1354,25 +1374,21 @@ static struct file_operations snd_rawmidi_f_ops =
.compat_ioctl = snd_rawmidi_ioctl_compat,
};
-static snd_minor_t snd_rawmidi_reg =
-{
- .comment = "raw midi",
- .f_ops = &snd_rawmidi_f_ops,
-};
-
-static int snd_rawmidi_alloc_substreams(snd_rawmidi_t *rmidi,
- snd_rawmidi_str_t *stream,
+static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,
+ struct snd_rawmidi_str *stream,
int direction,
int count)
{
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
int idx;
INIT_LIST_HEAD(&stream->substreams);
for (idx = 0; idx < count; idx++) {
substream = kzalloc(sizeof(*substream), GFP_KERNEL);
- if (substream == NULL)
+ if (substream == NULL) {
+ snd_printk(KERN_ERR "rawmidi: cannot allocate substream\n");
return -ENOMEM;
+ }
substream->stream = direction;
substream->number = idx;
substream->rmidi = rmidi;
@@ -1397,13 +1413,13 @@ static int snd_rawmidi_alloc_substreams(snd_rawmidi_t *rmidi,
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_rawmidi_new(snd_card_t * card, char *id, int device,
+int snd_rawmidi_new(struct snd_card *card, char *id, int device,
int output_count, int input_count,
- snd_rawmidi_t ** rrawmidi)
+ struct snd_rawmidi ** rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_rawmidi_dev_free,
.dev_register = snd_rawmidi_dev_register,
.dev_disconnect = snd_rawmidi_dev_disconnect,
@@ -1414,19 +1430,27 @@ int snd_rawmidi_new(snd_card_t * card, char *id, int device,
*rrawmidi = NULL;
snd_assert(card != NULL, return -ENXIO);
rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);
- if (rmidi == NULL)
+ if (rmidi == NULL) {
+ snd_printk(KERN_ERR "rawmidi: cannot allocate\n");
return -ENOMEM;
+ }
rmidi->card = card;
rmidi->device = device;
init_MUTEX(&rmidi->open_mutex);
init_waitqueue_head(&rmidi->open_wait);
if (id != NULL)
strlcpy(rmidi->id, id, sizeof(rmidi->id));
- if ((err = snd_rawmidi_alloc_substreams(rmidi, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT], SNDRV_RAWMIDI_STREAM_INPUT, input_count)) < 0) {
+ if ((err = snd_rawmidi_alloc_substreams(rmidi,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ input_count)) < 0) {
snd_rawmidi_free(rmidi);
return err;
}
- if ((err = snd_rawmidi_alloc_substreams(rmidi, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT], SNDRV_RAWMIDI_STREAM_OUTPUT, output_count)) < 0) {
+ if ((err = snd_rawmidi_alloc_substreams(rmidi,
+ &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],
+ SNDRV_RAWMIDI_STREAM_OUTPUT,
+ output_count)) < 0) {
snd_rawmidi_free(rmidi);
return err;
}
@@ -1438,18 +1462,18 @@ int snd_rawmidi_new(snd_card_t * card, char *id, int device,
return 0;
}
-static void snd_rawmidi_free_substreams(snd_rawmidi_str_t *stream)
+static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream)
{
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
while (!list_empty(&stream->substreams)) {
- substream = list_entry(stream->substreams.next, snd_rawmidi_substream_t, list);
+ substream = list_entry(stream->substreams.next, struct snd_rawmidi_substream, list);
list_del(&substream->list);
kfree(substream);
}
}
-static int snd_rawmidi_free(snd_rawmidi_t *rmidi)
+static int snd_rawmidi_free(struct snd_rawmidi *rmidi)
{
snd_assert(rmidi != NULL, return -ENXIO);
snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
@@ -1460,49 +1484,48 @@ static int snd_rawmidi_free(snd_rawmidi_t *rmidi)
return 0;
}
-static int snd_rawmidi_dev_free(snd_device_t *device)
+static int snd_rawmidi_dev_free(struct snd_device *device)
{
- snd_rawmidi_t *rmidi = device->device_data;
+ struct snd_rawmidi *rmidi = device->device_data;
return snd_rawmidi_free(rmidi);
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-static void snd_rawmidi_dev_seq_free(snd_seq_device_t *device)
+static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
{
- snd_rawmidi_t *rmidi = device->private_data;
+ struct snd_rawmidi *rmidi = device->private_data;
rmidi->seq_dev = NULL;
}
#endif
-static int snd_rawmidi_dev_register(snd_device_t *device)
+static int snd_rawmidi_dev_register(struct snd_device *device)
{
- int idx, err;
- snd_info_entry_t *entry;
+ int err;
+ struct snd_info_entry *entry;
char name[16];
- snd_rawmidi_t *rmidi = device->device_data;
+ struct snd_rawmidi *rmidi = device->device_data;
if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
return -ENOMEM;
down(&register_mutex);
- idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
- if (snd_rawmidi_devices[idx] != NULL) {
+ if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
up(&register_mutex);
return -EBUSY;
}
- snd_rawmidi_devices[idx] = rmidi;
+ list_add_tail(&rmidi->list, &snd_rawmidi_devices);
sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);
if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
rmidi->card, rmidi->device,
- &snd_rawmidi_reg, name)) < 0) {
+ &snd_rawmidi_f_ops, rmidi, name)) < 0) {
snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
- snd_rawmidi_devices[idx] = NULL;
+ list_del(&rmidi->list);
up(&register_mutex);
return err;
}
if (rmidi->ops && rmidi->ops->dev_register &&
(err = rmidi->ops->dev_register(rmidi)) < 0) {
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
- snd_rawmidi_devices[idx] = NULL;
+ list_del(&rmidi->list);
up(&register_mutex);
return err;
}
@@ -1510,7 +1533,8 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
rmidi->ossreg = 0;
if ((int)rmidi->device == midi_map[rmidi->card->number]) {
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
- rmidi->card, 0, &snd_rawmidi_reg, name) < 0) {
+ rmidi->card, 0, &snd_rawmidi_f_ops,
+ rmidi, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
} else {
rmidi->ossreg++;
@@ -1521,7 +1545,8 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
}
if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
- rmidi->card, 1, &snd_rawmidi_reg, name) < 0) {
+ rmidi->card, 1, &snd_rawmidi_f_ops,
+ rmidi, name) < 0) {
snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
} else {
rmidi->ossreg++;
@@ -1554,27 +1579,23 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
return 0;
}
-static int snd_rawmidi_dev_disconnect(snd_device_t *device)
+static int snd_rawmidi_dev_disconnect(struct snd_device *device)
{
- snd_rawmidi_t *rmidi = device->device_data;
- int idx;
+ struct snd_rawmidi *rmidi = device->device_data;
down(&register_mutex);
- idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
- snd_rawmidi_devices[idx] = NULL;
+ list_del_init(&rmidi->list);
up(&register_mutex);
return 0;
}
-static int snd_rawmidi_dev_unregister(snd_device_t *device)
+static int snd_rawmidi_dev_unregister(struct snd_device *device)
{
- int idx;
- snd_rawmidi_t *rmidi = device->device_data;
+ struct snd_rawmidi *rmidi = device->device_data;
snd_assert(rmidi != NULL, return -ENXIO);
down(&register_mutex);
- idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device;
- snd_rawmidi_devices[idx] = NULL;
+ list_del(&rmidi->list);
if (rmidi->proc_entry) {
snd_info_unregister(rmidi->proc_entry);
rmidi->proc_entry = NULL;
@@ -1613,13 +1634,14 @@ static int snd_rawmidi_dev_unregister(snd_device_t *device)
*
* Sets the rawmidi operators for the given stream direction.
*/
-void snd_rawmidi_set_ops(snd_rawmidi_t *rmidi, int stream, snd_rawmidi_ops_t *ops)
+void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
+ struct snd_rawmidi_ops *ops)
{
struct list_head *list;
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
list_for_each(list, &rmidi->streams[stream].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
substream->ops = ops;
}
}
@@ -1672,7 +1694,6 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
EXPORT_SYMBOL(snd_rawmidi_transmit);
EXPORT_SYMBOL(snd_rawmidi_new);
EXPORT_SYMBOL(snd_rawmidi_set_ops);
-EXPORT_SYMBOL(snd_rawmidi_info);
EXPORT_SYMBOL(snd_rawmidi_info_select);
EXPORT_SYMBOL(snd_rawmidi_kernel_open);
EXPORT_SYMBOL(snd_rawmidi_kernel_release);
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c
index d97631c3f3ad..5268c1f58c25 100644
--- a/sound/core/rawmidi_compat.c
+++ b/sound/core/rawmidi_compat.c
@@ -22,7 +22,7 @@
#include <linux/compat.h>
-struct sndrv_rawmidi_params32 {
+struct snd_rawmidi_params32 {
s32 stream;
u32 buffer_size;
u32 avail_min;
@@ -30,10 +30,10 @@ struct sndrv_rawmidi_params32 {
unsigned char reserved[16];
} __attribute__((packed));
-static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
- struct sndrv_rawmidi_params32 __user *src)
+static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
+ struct snd_rawmidi_params32 __user *src)
{
- snd_rawmidi_params_t params;
+ struct snd_rawmidi_params params;
unsigned int val;
if (rfile->output == NULL)
@@ -53,7 +53,7 @@ static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
return -EINVAL;
}
-struct sndrv_rawmidi_status32 {
+struct snd_rawmidi_status32 {
s32 stream;
struct compat_timespec tstamp;
u32 avail;
@@ -61,11 +61,11 @@ struct sndrv_rawmidi_status32 {
unsigned char reserved[16];
} __attribute__((packed));
-static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
- struct sndrv_rawmidi_status32 __user *src)
+static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
+ struct snd_rawmidi_status32 __user *src)
{
int err;
- snd_rawmidi_status_t status;
+ struct snd_rawmidi_status status;
if (rfile->output == NULL)
return -EINVAL;
@@ -95,13 +95,13 @@ static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
}
enum {
- SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
- SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
+ SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
+ SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
};
static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_rawmidi_file_t *rfile;
+ struct snd_rawmidi_file *rfile;
void __user *argp = compat_ptr(arg);
rfile = file->private_data;
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index c3c18568207e..84704ccb1829 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -40,16 +40,16 @@
/*
* prototypes
*/
-static int rtctimer_open(snd_timer_t *t);
-static int rtctimer_close(snd_timer_t *t);
-static int rtctimer_start(snd_timer_t *t);
-static int rtctimer_stop(snd_timer_t *t);
+static int rtctimer_open(struct snd_timer *t);
+static int rtctimer_close(struct snd_timer *t);
+static int rtctimer_start(struct snd_timer *t);
+static int rtctimer_stop(struct snd_timer *t);
/*
* The hardware dependent description for this timer.
*/
-static struct _snd_timer_hardware rtc_hw = {
+static struct snd_timer_hardware rtc_hw = {
.flags = SNDRV_TIMER_HW_FIRST|SNDRV_TIMER_HW_AUTO,
.ticks = 100000000L, /* FIXME: XXX */
.open = rtctimer_open,
@@ -59,12 +59,12 @@ static struct _snd_timer_hardware rtc_hw = {
};
static int rtctimer_freq = RTC_FREQ; /* frequency */
-static snd_timer_t *rtctimer;
+static struct snd_timer *rtctimer;
static rtc_task_t rtc_task;
static int
-rtctimer_open(snd_timer_t *t)
+rtctimer_open(struct snd_timer *t)
{
int err;
@@ -76,7 +76,7 @@ rtctimer_open(snd_timer_t *t)
}
static int
-rtctimer_close(snd_timer_t *t)
+rtctimer_close(struct snd_timer *t)
{
rtc_task_t *rtc = t->private_data;
if (rtc) {
@@ -87,7 +87,7 @@ rtctimer_close(snd_timer_t *t)
}
static int
-rtctimer_start(snd_timer_t *timer)
+rtctimer_start(struct snd_timer *timer)
{
rtc_task_t *rtc = timer->private_data;
snd_assert(rtc != NULL, return -EINVAL);
@@ -97,7 +97,7 @@ rtctimer_start(snd_timer_t *timer)
}
static int
-rtctimer_stop(snd_timer_t *timer)
+rtctimer_stop(struct snd_timer *timer)
{
rtc_task_t *rtc = timer->private_data;
snd_assert(rtc != NULL, return -EINVAL);
@@ -120,7 +120,7 @@ static void rtctimer_interrupt(void *private_data)
static int __init rtctimer_init(void)
{
int err;
- snd_timer_t *timer;
+ struct snd_timer *timer;
if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
(rtctimer_freq & (rtctimer_freq - 1)) != 0) {
diff --git a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c
index 5c671e69884f..b09babf272cd 100644
--- a/sound/core/seq/instr/ainstr_fm.c
+++ b/sound/core/seq/instr/ainstr_fm.c
@@ -30,11 +30,11 @@ MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
MODULE_LICENSE("GPL");
-static int snd_seq_fm_put(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_fm_put(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic, int cmd)
{
- fm_instrument_t *ip;
- fm_xinstrument_t ix;
+ struct fm_instrument *ip;
+ struct fm_xinstrument ix;
int idx;
if (cmd != SNDRV_SEQ_INSTR_PUT_CMD_CREATE)
@@ -46,7 +46,7 @@ static int snd_seq_fm_put(void *private_data, snd_seq_kinstr_t *instr,
return -EFAULT;
if (ix.stype != FM_STRU_INSTR)
return -EINVAL;
- ip = (fm_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct fm_instrument *)KINSTR_DATA(instr);
ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
@@ -72,12 +72,12 @@ static int snd_seq_fm_put(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static int snd_seq_fm_get(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_fm_get(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic,
int cmd)
{
- fm_instrument_t *ip;
- fm_xinstrument_t ix;
+ struct fm_instrument *ip;
+ struct fm_xinstrument ix;
int idx;
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
@@ -85,7 +85,7 @@ static int snd_seq_fm_get(void *private_data, snd_seq_kinstr_t *instr,
if (len < (long)sizeof(ix))
return -ENOMEM;
memset(&ix, 0, sizeof(ix));
- ip = (fm_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct fm_instrument *)KINSTR_DATA(instr);
ix.stype = FM_STRU_INSTR;
ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
@@ -114,19 +114,19 @@ static int snd_seq_fm_get(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static int snd_seq_fm_get_size(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_fm_get_size(void *private_data, struct snd_seq_kinstr *instr,
long *size)
{
- *size = sizeof(fm_xinstrument_t);
+ *size = sizeof(struct fm_xinstrument);
return 0;
}
-int snd_seq_fm_init(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_ops_t *next)
+int snd_seq_fm_init(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_ops *next)
{
memset(ops, 0, sizeof(*ops));
// ops->private_data = private_data;
- ops->add_len = sizeof(fm_instrument_t);
+ ops->add_len = sizeof(struct fm_instrument);
ops->instr_type = SNDRV_SEQ_INSTR_ID_OPL2_3;
ops->put = snd_seq_fm_put;
ops->get = snd_seq_fm_get;
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 0e4df8826eed..3c31038a74ba 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -42,14 +42,14 @@ static unsigned int snd_seq_gf1_size(unsigned int size, unsigned int format)
return format;
}
-static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
- gf1_instrument_t *ip,
+static int snd_seq_gf1_copy_wave_from_stream(struct snd_gf1_ops *ops,
+ struct gf1_instrument *ip,
char __user **data,
long *len,
int atomic)
{
- gf1_wave_t *wp, *prev;
- gf1_xwave_t xp;
+ struct gf1_wave *wp, *prev;
+ struct gf1_xwave xp;
int err;
gfp_t gfp_mask;
unsigned int real_size;
@@ -116,8 +116,8 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
return 0;
}
-static void snd_seq_gf1_wave_free(snd_gf1_ops_t *ops,
- gf1_wave_t *wave,
+static void snd_seq_gf1_wave_free(struct snd_gf1_ops *ops,
+ struct gf1_wave *wave,
int atomic)
{
if (ops->remove_sample)
@@ -125,11 +125,11 @@ static void snd_seq_gf1_wave_free(snd_gf1_ops_t *ops,
kfree(wave);
}
-static void snd_seq_gf1_instr_free(snd_gf1_ops_t *ops,
- gf1_instrument_t *ip,
+static void snd_seq_gf1_instr_free(struct snd_gf1_ops *ops,
+ struct gf1_instrument *ip,
int atomic)
{
- gf1_wave_t *wave;
+ struct gf1_wave *wave;
while ((wave = ip->wave) != NULL) {
ip->wave = wave->next;
@@ -137,13 +137,13 @@ static void snd_seq_gf1_instr_free(snd_gf1_ops_t *ops,
}
}
-static int snd_seq_gf1_put(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_gf1_put(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic,
int cmd)
{
- snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
- gf1_instrument_t *ip;
- gf1_xinstrument_t ix;
+ struct snd_gf1_ops *ops = private_data;
+ struct gf1_instrument *ip;
+ struct gf1_xinstrument ix;
int err;
gfp_t gfp_mask;
@@ -159,7 +159,7 @@ static int snd_seq_gf1_put(void *private_data, snd_seq_kinstr_t *instr,
return -EINVAL;
instr_data += sizeof(ix);
len -= sizeof(ix);
- ip = (gf1_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct gf1_instrument *)KINSTR_DATA(instr);
ip->exclusion = le16_to_cpu(ix.exclusion);
ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
ip->effect1 = ix.effect1;
@@ -189,14 +189,14 @@ static int snd_seq_gf1_put(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static int snd_seq_gf1_copy_wave_to_stream(snd_gf1_ops_t *ops,
- gf1_instrument_t *ip,
+static int snd_seq_gf1_copy_wave_to_stream(struct snd_gf1_ops *ops,
+ struct gf1_instrument *ip,
char __user **data,
long *len,
int atomic)
{
- gf1_wave_t *wp;
- gf1_xwave_t xp;
+ struct gf1_wave *wp;
+ struct gf1_xwave xp;
int err;
unsigned int real_size;
@@ -251,20 +251,20 @@ static int snd_seq_gf1_copy_wave_to_stream(snd_gf1_ops_t *ops,
return 0;
}
-static int snd_seq_gf1_get(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_gf1_get(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic,
int cmd)
{
- snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
- gf1_instrument_t *ip;
- gf1_xinstrument_t ix;
+ struct snd_gf1_ops *ops = private_data;
+ struct gf1_instrument *ip;
+ struct gf1_xinstrument ix;
if (cmd != SNDRV_SEQ_INSTR_GET_CMD_FULL)
return -EINVAL;
if (len < (long)sizeof(ix))
return -ENOMEM;
memset(&ix, 0, sizeof(ix));
- ip = (gf1_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct gf1_instrument *)KINSTR_DATA(instr);
ix.stype = GF1_STRU_INSTR;
ix.exclusion = cpu_to_le16(ip->exclusion);
ix.exclusion_group = cpu_to_le16(ip->exclusion_group);
@@ -283,18 +283,18 @@ static int snd_seq_gf1_get(void *private_data, snd_seq_kinstr_t *instr,
atomic);
}
-static int snd_seq_gf1_get_size(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_gf1_get_size(void *private_data, struct snd_seq_kinstr *instr,
long *size)
{
long result;
- gf1_instrument_t *ip;
- gf1_wave_t *wp;
+ struct gf1_instrument *ip;
+ struct gf1_wave *wp;
*size = 0;
- ip = (gf1_instrument_t *)KINSTR_DATA(instr);
- result = sizeof(gf1_xinstrument_t);
+ ip = (struct gf1_instrument *)KINSTR_DATA(instr);
+ result = sizeof(struct gf1_xinstrument);
for (wp = ip->wave; wp; wp = wp->next) {
- result += sizeof(gf1_xwave_t);
+ result += sizeof(struct gf1_xwave);
result += wp->size;
}
*size = result;
@@ -302,35 +302,35 @@ static int snd_seq_gf1_get_size(void *private_data, snd_seq_kinstr_t *instr,
}
static int snd_seq_gf1_remove(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int atomic)
{
- snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
- gf1_instrument_t *ip;
+ struct snd_gf1_ops *ops = private_data;
+ struct gf1_instrument *ip;
- ip = (gf1_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct gf1_instrument *)KINSTR_DATA(instr);
snd_seq_gf1_instr_free(ops, ip, atomic);
return 0;
}
static void snd_seq_gf1_notify(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int what)
{
- snd_gf1_ops_t *ops = (snd_gf1_ops_t *)private_data;
+ struct snd_gf1_ops *ops = private_data;
if (ops->notify)
ops->notify(ops->private_data, instr, what);
}
-int snd_seq_gf1_init(snd_gf1_ops_t *ops,
+int snd_seq_gf1_init(struct snd_gf1_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next)
+ struct snd_seq_kinstr_ops *next)
{
memset(ops, 0, sizeof(*ops));
ops->private_data = private_data;
ops->kops.private_data = ops;
- ops->kops.add_len = sizeof(gf1_instrument_t);
+ ops->kops.add_len = sizeof(struct gf1_instrument);
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
ops->kops.put = snd_seq_gf1_put;
ops->kops.get = snd_seq_gf1_get;
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index 7c19fbbc5d0f..7f8df19ba563 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -42,8 +42,8 @@ static unsigned int snd_seq_iwffff_size(unsigned int size, unsigned int format)
return result;
}
-static void snd_seq_iwffff_copy_lfo_from_stream(iwffff_lfo_t *fp,
- iwffff_xlfo_t *fx)
+static void snd_seq_iwffff_copy_lfo_from_stream(struct iwffff_lfo *fp,
+ struct iwffff_xlfo *fx)
{
fp->freq = le16_to_cpu(fx->freq);
fp->depth = le16_to_cpu(fx->depth);
@@ -53,18 +53,18 @@ static void snd_seq_iwffff_copy_lfo_from_stream(iwffff_lfo_t *fp,
}
static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
- iwffff_layer_t *lp,
- iwffff_env_t *ep,
- iwffff_xenv_t *ex,
+ struct iwffff_layer *lp,
+ struct iwffff_env *ep,
+ struct iwffff_xenv *ex,
char __user **data,
long *len,
gfp_t gfp_mask)
{
__u32 stype;
- iwffff_env_record_t *rp, *rp_last;
- iwffff_xenv_record_t rx;
- iwffff_env_point_t *pp;
- iwffff_xenv_point_t px;
+ struct iwffff_env_record *rp, *rp_last;
+ struct iwffff_xenv_record rx;
+ struct iwffff_env_point *pp;
+ struct iwffff_xenv_point px;
int points_size, idx;
ep->flags = ex->flags;
@@ -101,7 +101,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
rp->sustain_rate = le16_to_cpu(rx.sustain_rate);
rp->release_rate = le16_to_cpu(rx.release_rate);
rp->hirange = rx.hirange;
- pp = (iwffff_env_point_t *)(rp + 1);
+ pp = (struct iwffff_env_point *)(rp + 1);
for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
if (copy_from_user(&px, *data, sizeof(px)))
return -EFAULT;
@@ -120,14 +120,14 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
return 0;
}
-static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
- iwffff_layer_t *lp,
+static int snd_seq_iwffff_copy_wave_from_stream(struct snd_iwffff_ops *ops,
+ struct iwffff_layer *lp,
char __user **data,
long *len,
int atomic)
{
- iwffff_wave_t *wp, *prev;
- iwffff_xwave_t xp;
+ struct iwffff_wave *wp, *prev;
+ struct iwffff_xwave xp;
int err;
gfp_t gfp_mask;
unsigned int real_size;
@@ -186,11 +186,11 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
return 0;
}
-static void snd_seq_iwffff_env_free(snd_iwffff_ops_t *ops,
- iwffff_env_t *env,
+static void snd_seq_iwffff_env_free(struct snd_iwffff_ops *ops,
+ struct iwffff_env *env,
int atomic)
{
- iwffff_env_record_t *rec;
+ struct iwffff_env_record *rec;
while ((rec = env->record) != NULL) {
env->record = rec->next;
@@ -198,8 +198,8 @@ static void snd_seq_iwffff_env_free(snd_iwffff_ops_t *ops,
}
}
-static void snd_seq_iwffff_wave_free(snd_iwffff_ops_t *ops,
- iwffff_wave_t *wave,
+static void snd_seq_iwffff_wave_free(struct snd_iwffff_ops *ops,
+ struct iwffff_wave *wave,
int atomic)
{
if (ops->remove_sample)
@@ -207,12 +207,12 @@ static void snd_seq_iwffff_wave_free(snd_iwffff_ops_t *ops,
kfree(wave);
}
-static void snd_seq_iwffff_instr_free(snd_iwffff_ops_t *ops,
- iwffff_instrument_t *ip,
+static void snd_seq_iwffff_instr_free(struct snd_iwffff_ops *ops,
+ struct iwffff_instrument *ip,
int atomic)
{
- iwffff_layer_t *layer;
- iwffff_wave_t *wave;
+ struct iwffff_layer *layer;
+ struct iwffff_wave *wave;
while ((layer = ip->layer) != NULL) {
ip->layer = layer->next;
@@ -226,15 +226,15 @@ static void snd_seq_iwffff_instr_free(snd_iwffff_ops_t *ops,
}
}
-static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_iwffff_put(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic,
int cmd)
{
- snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
- iwffff_instrument_t *ip;
- iwffff_xinstrument_t ix;
- iwffff_layer_t *lp, *prev_lp;
- iwffff_xlayer_t lx;
+ struct snd_iwffff_ops *ops = private_data;
+ struct iwffff_instrument *ip;
+ struct iwffff_xinstrument ix;
+ struct iwffff_layer *lp, *prev_lp;
+ struct iwffff_xlayer lx;
int err;
gfp_t gfp_mask;
@@ -250,7 +250,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
return -EINVAL;
instr_data += sizeof(ix);
len -= sizeof(ix);
- ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
ip->exclusion = le16_to_cpu(ix.exclusion);
ip->layer_type = le16_to_cpu(ix.layer_type);
ip->exclusion_group = le16_to_cpu(ix.exclusion_group);
@@ -261,7 +261,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
/* copy layers */
prev_lp = NULL;
while (len > 0) {
- if (len < (long)sizeof(iwffff_xlayer_t)) {
+ if (len < (long)sizeof(struct iwffff_xlayer)) {
snd_seq_iwffff_instr_free(ops, ip, atomic);
return -EINVAL;
}
@@ -335,8 +335,8 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static void snd_seq_iwffff_copy_lfo_to_stream(iwffff_xlfo_t *fx,
- iwffff_lfo_t *fp)
+static void snd_seq_iwffff_copy_lfo_to_stream(struct iwffff_xlfo *fx,
+ struct iwffff_lfo *fp)
{
fx->freq = cpu_to_le16(fp->freq);
fx->depth = cpu_to_le16(fp->depth);
@@ -346,16 +346,16 @@ static void snd_seq_iwffff_copy_lfo_to_stream(iwffff_xlfo_t *fx,
}
static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
- iwffff_layer_t *lp,
- iwffff_xenv_t *ex,
- iwffff_env_t *ep,
+ struct iwffff_layer *lp,
+ struct iwffff_xenv *ex,
+ struct iwffff_env *ep,
char __user **data,
long *len)
{
- iwffff_env_record_t *rp;
- iwffff_xenv_record_t rx;
- iwffff_env_point_t *pp;
- iwffff_xenv_point_t px;
+ struct iwffff_env_record *rp;
+ struct iwffff_xenv_record rx;
+ struct iwffff_env_point *pp;
+ struct iwffff_xenv_point px;
int points_size, idx;
ex->flags = ep->flags;
@@ -379,7 +379,7 @@ static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
points_size = (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
if (*len < points_size)
return -ENOMEM;
- pp = (iwffff_env_point_t *)(rp + 1);
+ pp = (struct iwffff_env_point *)(rp + 1);
for (idx = 0; idx < rp->nattack + rp->nrelease; idx++) {
px.offset = cpu_to_le16(pp->offset);
px.rate = cpu_to_le16(pp->rate);
@@ -392,14 +392,14 @@ static int snd_seq_iwffff_copy_env_to_stream(__u32 req_stype,
return 0;
}
-static int snd_seq_iwffff_copy_wave_to_stream(snd_iwffff_ops_t *ops,
- iwffff_layer_t *lp,
+static int snd_seq_iwffff_copy_wave_to_stream(struct snd_iwffff_ops *ops,
+ struct iwffff_layer *lp,
char __user **data,
long *len,
int atomic)
{
- iwffff_wave_t *wp;
- iwffff_xwave_t xp;
+ struct iwffff_wave *wp;
+ struct iwffff_xwave xp;
int err;
unsigned int real_size;
@@ -447,14 +447,14 @@ static int snd_seq_iwffff_copy_wave_to_stream(snd_iwffff_ops_t *ops,
return 0;
}
-static int snd_seq_iwffff_get(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_iwffff_get(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len, int atomic, int cmd)
{
- snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
- iwffff_instrument_t *ip;
- iwffff_xinstrument_t ix;
- iwffff_layer_t *lp;
- iwffff_xlayer_t lx;
+ struct snd_iwffff_ops *ops = private_data;
+ struct iwffff_instrument *ip;
+ struct iwffff_xinstrument ix;
+ struct iwffff_layer *lp;
+ struct iwffff_xlayer lx;
char __user *layer_instr_data;
int err;
@@ -463,7 +463,7 @@ static int snd_seq_iwffff_get(void *private_data, snd_seq_kinstr_t *instr,
if (len < (long)sizeof(ix))
return -ENOMEM;
memset(&ix, 0, sizeof(ix));
- ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
ix.stype = IWFFFF_STRU_INSTR;
ix.exclusion = cpu_to_le16(ip->exclusion);
ix.layer_type = cpu_to_le16(ip->layer_type);
@@ -520,43 +520,43 @@ static int snd_seq_iwffff_get(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static long snd_seq_iwffff_env_size_in_stream(iwffff_env_t *ep)
+static long snd_seq_iwffff_env_size_in_stream(struct iwffff_env *ep)
{
long result = 0;
- iwffff_env_record_t *rp;
+ struct iwffff_env_record *rp;
for (rp = ep->record; rp; rp = rp->next) {
- result += sizeof(iwffff_xenv_record_t);
+ result += sizeof(struct iwffff_xenv_record);
result += (rp->nattack + rp->nrelease) * 2 * sizeof(__u16);
}
return 0;
}
-static long snd_seq_iwffff_wave_size_in_stream(iwffff_layer_t *lp)
+static long snd_seq_iwffff_wave_size_in_stream(struct iwffff_layer *lp)
{
long result = 0;
- iwffff_wave_t *wp;
+ struct iwffff_wave *wp;
for (wp = lp->wave; wp; wp = wp->next) {
- result += sizeof(iwffff_xwave_t);
+ result += sizeof(struct iwffff_xwave);
if (!(wp->format & IWFFFF_WAVE_ROM))
result += wp->size;
}
return result;
}
-static int snd_seq_iwffff_get_size(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_iwffff_get_size(void *private_data, struct snd_seq_kinstr *instr,
long *size)
{
long result;
- iwffff_instrument_t *ip;
- iwffff_layer_t *lp;
+ struct iwffff_instrument *ip;
+ struct iwffff_layer *lp;
*size = 0;
- ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
- result = sizeof(iwffff_xinstrument_t);
+ ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
+ result = sizeof(struct iwffff_xinstrument);
for (lp = ip->layer; lp; lp = lp->next) {
- result += sizeof(iwffff_xlayer_t);
+ result += sizeof(struct iwffff_xlayer);
result += snd_seq_iwffff_env_size_in_stream(&lp->penv);
result += snd_seq_iwffff_env_size_in_stream(&lp->venv);
result += snd_seq_iwffff_wave_size_in_stream(lp);
@@ -566,35 +566,35 @@ static int snd_seq_iwffff_get_size(void *private_data, snd_seq_kinstr_t *instr,
}
static int snd_seq_iwffff_remove(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int atomic)
{
- snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
- iwffff_instrument_t *ip;
+ struct snd_iwffff_ops *ops = private_data;
+ struct iwffff_instrument *ip;
- ip = (iwffff_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct iwffff_instrument *)KINSTR_DATA(instr);
snd_seq_iwffff_instr_free(ops, ip, atomic);
return 0;
}
static void snd_seq_iwffff_notify(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int what)
{
- snd_iwffff_ops_t *ops = (snd_iwffff_ops_t *)private_data;
+ struct snd_iwffff_ops *ops = private_data;
if (ops->notify)
ops->notify(ops->private_data, instr, what);
}
-int snd_seq_iwffff_init(snd_iwffff_ops_t *ops,
+int snd_seq_iwffff_init(struct snd_iwffff_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next)
+ struct snd_seq_kinstr_ops *next)
{
memset(ops, 0, sizeof(*ops));
ops->private_data = private_data;
ops->kops.private_data = ops;
- ops->kops.add_len = sizeof(iwffff_instrument_t);
+ ops->kops.add_len = sizeof(struct iwffff_instrument);
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_INTERWAVE;
ops->kops.put = snd_seq_iwffff_put;
ops->kops.get = snd_seq_iwffff_get;
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
index 17ab94e76073..6d6ffece7cbe 100644
--- a/sound/core/seq/instr/ainstr_simple.c
+++ b/sound/core/seq/instr/ainstr_simple.c
@@ -42,21 +42,21 @@ static unsigned int snd_seq_simple_size(unsigned int size, unsigned int format)
return result;
}
-static void snd_seq_simple_instr_free(snd_simple_ops_t *ops,
- simple_instrument_t *ip,
+static void snd_seq_simple_instr_free(struct snd_simple_ops *ops,
+ struct simple_instrument *ip,
int atomic)
{
if (ops->remove_sample)
ops->remove_sample(ops->private_data, ip, atomic);
}
-static int snd_seq_simple_put(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_simple_put(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len,
int atomic, int cmd)
{
- snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
- simple_instrument_t *ip;
- simple_xinstrument_t ix;
+ struct snd_simple_ops *ops = private_data;
+ struct simple_instrument *ip;
+ struct simple_xinstrument ix;
int err;
gfp_t gfp_mask;
unsigned int real_size;
@@ -73,7 +73,7 @@ static int snd_seq_simple_put(void *private_data, snd_seq_kinstr_t *instr,
return -EINVAL;
instr_data += sizeof(ix);
len -= sizeof(ix);
- ip = (simple_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct simple_instrument *)KINSTR_DATA(instr);
ip->share_id[0] = le32_to_cpu(ix.share_id[0]);
ip->share_id[1] = le32_to_cpu(ix.share_id[1]);
ip->share_id[2] = le32_to_cpu(ix.share_id[2]);
@@ -100,13 +100,13 @@ static int snd_seq_simple_put(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static int snd_seq_simple_get(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_simple_get(void *private_data, struct snd_seq_kinstr *instr,
char __user *instr_data, long len,
int atomic, int cmd)
{
- snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
- simple_instrument_t *ip;
- simple_xinstrument_t ix;
+ struct snd_simple_ops *ops = private_data;
+ struct simple_instrument *ip;
+ struct simple_xinstrument ix;
int err;
unsigned int real_size;
@@ -115,7 +115,7 @@ static int snd_seq_simple_get(void *private_data, snd_seq_kinstr_t *instr,
if (len < (long)sizeof(ix))
return -ENOMEM;
memset(&ix, 0, sizeof(ix));
- ip = (simple_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct simple_instrument *)KINSTR_DATA(instr);
ix.stype = SIMPLE_STRU_INSTR;
ix.share_id[0] = cpu_to_le32(ip->share_id[0]);
ix.share_id[1] = cpu_to_le32(ip->share_id[1]);
@@ -147,46 +147,46 @@ static int snd_seq_simple_get(void *private_data, snd_seq_kinstr_t *instr,
return 0;
}
-static int snd_seq_simple_get_size(void *private_data, snd_seq_kinstr_t *instr,
+static int snd_seq_simple_get_size(void *private_data, struct snd_seq_kinstr *instr,
long *size)
{
- simple_instrument_t *ip;
+ struct simple_instrument *ip;
- ip = (simple_instrument_t *)KINSTR_DATA(instr);
- *size = sizeof(simple_xinstrument_t) + snd_seq_simple_size(ip->size, ip->format);
+ ip = (struct simple_instrument *)KINSTR_DATA(instr);
+ *size = sizeof(struct simple_xinstrument) + snd_seq_simple_size(ip->size, ip->format);
return 0;
}
static int snd_seq_simple_remove(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int atomic)
{
- snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
- simple_instrument_t *ip;
+ struct snd_simple_ops *ops = private_data;
+ struct simple_instrument *ip;
- ip = (simple_instrument_t *)KINSTR_DATA(instr);
+ ip = (struct simple_instrument *)KINSTR_DATA(instr);
snd_seq_simple_instr_free(ops, ip, atomic);
return 0;
}
static void snd_seq_simple_notify(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int what)
{
- snd_simple_ops_t *ops = (snd_simple_ops_t *)private_data;
+ struct snd_simple_ops *ops = private_data;
if (ops->notify)
ops->notify(ops->private_data, instr, what);
}
-int snd_seq_simple_init(snd_simple_ops_t *ops,
+int snd_seq_simple_init(struct snd_simple_ops *ops,
void *private_data,
- snd_seq_kinstr_ops_t *next)
+ struct snd_seq_kinstr_ops *next)
{
memset(ops, 0, sizeof(*ops));
ops->private_data = private_data;
ops->kops.private_data = ops;
- ops->kops.add_len = sizeof(simple_instrument_t);
+ ops->kops.add_len = sizeof(struct simple_instrument);
ops->kops.instr_type = SNDRV_SEQ_INSTR_ID_SIMPLE;
ops->kops.put = snd_seq_simple_put;
ops->kops.get = snd_seq_simple_get;
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 4c0558c0a8b4..c98f0ba13810 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -52,8 +52,13 @@ int seq_oss_debug = 0;
*/
static int register_device(void);
static void unregister_device(void);
+#ifdef CONFIG_PROC_FS
static int register_proc(void);
static void unregister_proc(void);
+#else
+static inline int register_proc(void) { return 0; }
+static inline void unregister_proc(void) {}
+#endif
static int odev_open(struct inode *inode, struct file *file);
static int odev_release(struct inode *inode, struct file *file);
@@ -61,9 +66,6 @@ static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff
static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static unsigned int odev_poll(struct file *file, poll_table * wait);
-#ifdef CONFIG_PROC_FS
-static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf);
-#endif
/*
@@ -73,7 +75,7 @@ static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf);
static int __init alsa_seq_oss_init(void)
{
int rc;
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_seq_oss_synth_register,
snd_seq_oss_synth_unregister,
};
@@ -92,7 +94,7 @@ static int __init alsa_seq_oss_init(void)
}
if ((rc = snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OSS, &ops,
- sizeof(snd_seq_oss_reg_t))) < 0) {
+ sizeof(struct snd_seq_oss_reg))) < 0) {
snd_seq_oss_delete_client();
unregister_proc();
unregister_device();
@@ -144,7 +146,7 @@ odev_open(struct inode *inode, struct file *file)
static int
odev_release(struct inode *inode, struct file *file)
{
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
if ((dp = file->private_data) == NULL)
return 0;
@@ -161,7 +163,7 @@ odev_release(struct inode *inode, struct file *file)
static ssize_t
odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
dp = file->private_data;
snd_assert(dp != NULL, return -EIO);
return snd_seq_oss_read(dp, buf, count);
@@ -171,7 +173,7 @@ odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
static ssize_t
odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
dp = file->private_data;
snd_assert(dp != NULL, return -EIO);
return snd_seq_oss_write(dp, buf, count, file);
@@ -180,7 +182,7 @@ odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offs
static long
odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
dp = file->private_data;
snd_assert(dp != NULL, return -EIO);
return snd_seq_oss_ioctl(dp, cmd, arg);
@@ -195,7 +197,7 @@ odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static unsigned int
odev_poll(struct file *file, poll_table * wait)
{
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
dp = file->private_data;
snd_assert(dp != NULL, return 0);
return snd_seq_oss_poll(dp, file, wait);
@@ -217,11 +219,6 @@ static struct file_operations seq_oss_f_ops =
.compat_ioctl = odev_ioctl_compat,
};
-static snd_minor_t seq_oss_reg = {
- .comment = "sequencer",
- .f_ops = &seq_oss_f_ops,
-};
-
static int __init
register_device(void)
{
@@ -230,7 +227,7 @@ register_device(void)
down(&register_mutex);
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
NULL, 0,
- &seq_oss_reg,
+ &seq_oss_f_ops, NULL,
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device seq\n");
up(&register_mutex);
@@ -238,7 +235,7 @@ register_device(void)
}
if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
NULL, 0,
- &seq_oss_reg,
+ &seq_oss_f_ops, NULL,
SNDRV_SEQ_OSS_DEVNAME)) < 0) {
snd_printk(KERN_ERR "can't register device music\n");
snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
@@ -268,10 +265,10 @@ unregister_device(void)
#ifdef CONFIG_PROC_FS
-static snd_info_entry_t *info_entry;
+static struct snd_info_entry *info_entry;
static void
-info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
+info_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
{
down(&register_mutex);
snd_iprintf(buf, "OSS sequencer emulation version %s\n", SNDRV_SEQ_OSS_VERSION_STR);
@@ -281,13 +278,11 @@ info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
up(&register_mutex);
}
-#endif /* CONFIG_PROC_FS */
static int __init
register_proc(void)
{
-#ifdef CONFIG_PROC_FS
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, SNDRV_SEQ_OSS_PROCNAME, snd_seq_root);
if (entry == NULL)
@@ -302,16 +297,14 @@ register_proc(void)
return -ENOMEM;
}
info_entry = entry;
-#endif
return 0;
}
static void
unregister_proc(void)
{
-#ifdef CONFIG_PROC_FS
if (info_entry)
snd_info_unregister(info_entry);
info_entry = NULL;
-#endif
}
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_device.h b/sound/core/seq/oss/seq_oss_device.h
index 973786758c55..9a8567c928ec 100644
--- a/sound/core/seq/oss/seq_oss_device.h
+++ b/sound/core/seq/oss/seq_oss_device.h
@@ -55,32 +55,24 @@
* type definitions
*/
-typedef struct seq_oss_devinfo_t seq_oss_devinfo_t;
-typedef struct seq_oss_writeq_t seq_oss_writeq_t;
-typedef struct seq_oss_readq_t seq_oss_readq_t;
-typedef struct seq_oss_timer_t seq_oss_timer_t;
-typedef struct seq_oss_synthinfo_t seq_oss_synthinfo_t;
-typedef struct seq_oss_synth_sysex_t seq_oss_synth_sysex_t;
-typedef struct seq_oss_chinfo_t seq_oss_chinfo_t;
typedef unsigned int reltime_t;
typedef unsigned int abstime_t;
-typedef union evrec_t evrec_t;
/*
* synthesizer channel information
*/
-struct seq_oss_chinfo_t {
+struct seq_oss_chinfo {
int note, vel;
};
/*
* synthesizer information
*/
-struct seq_oss_synthinfo_t {
- snd_seq_oss_arg_t arg;
- seq_oss_chinfo_t *ch;
- seq_oss_synth_sysex_t *sysex;
+struct seq_oss_synthinfo {
+ struct snd_seq_oss_arg arg;
+ struct seq_oss_chinfo *ch;
+ struct seq_oss_synth_sysex *sysex;
int nr_voices;
int opened;
int is_midi;
@@ -92,14 +84,14 @@ struct seq_oss_synthinfo_t {
* sequencer client information
*/
-struct seq_oss_devinfo_t {
+struct seq_oss_devinfo {
int index; /* application index */
int cseq; /* sequencer client number */
int port; /* sequencer port number */
int queue; /* sequencer queue number */
- snd_seq_addr_t addr; /* address of this device */
+ struct snd_seq_addr addr; /* address of this device */
int seq_mode; /* sequencer mode */
int file_mode; /* file access */
@@ -109,17 +101,17 @@ struct seq_oss_devinfo_t {
/* synth device table */
int max_synthdev;
- seq_oss_synthinfo_t synths[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
+ struct seq_oss_synthinfo synths[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
int synth_opened;
/* output queue */
- seq_oss_writeq_t *writeq;
+ struct seq_oss_writeq *writeq;
/* midi input queue */
- seq_oss_readq_t *readq;
+ struct seq_oss_readq *readq;
/* timer */
- seq_oss_timer_t *timer;
+ struct seq_oss_timer *timer;
};
@@ -133,24 +125,24 @@ int snd_seq_oss_delete_client(void);
/* device file interface */
int snd_seq_oss_open(struct file *file, int level);
-void snd_seq_oss_release(seq_oss_devinfo_t *dp);
-int snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long arg);
-int snd_seq_oss_read(seq_oss_devinfo_t *dev, char __user *buf, int count);
-int snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt);
-unsigned int snd_seq_oss_poll(seq_oss_devinfo_t *dp, struct file *file, poll_table * wait);
+void snd_seq_oss_release(struct seq_oss_devinfo *dp);
+int snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long arg);
+int snd_seq_oss_read(struct seq_oss_devinfo *dev, char __user *buf, int count);
+int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt);
+unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
-void snd_seq_oss_reset(seq_oss_devinfo_t *dp);
-void snd_seq_oss_drain_write(seq_oss_devinfo_t *dp);
+void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
+void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
/* */
-void snd_seq_oss_process_queue(seq_oss_devinfo_t *dp, abstime_t time);
+void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
/* proc interface */
-void snd_seq_oss_system_info_read(snd_info_buffer_t *buf);
-void snd_seq_oss_midi_info_read(snd_info_buffer_t *buf);
-void snd_seq_oss_synth_info_read(snd_info_buffer_t *buf);
-void snd_seq_oss_readq_info_read(seq_oss_readq_t *q, snd_info_buffer_t *buf);
+void snd_seq_oss_system_info_read(struct snd_info_buffer *buf);
+void snd_seq_oss_midi_info_read(struct snd_info_buffer *buf);
+void snd_seq_oss_synth_info_read(struct snd_info_buffer *buf);
+void snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf);
/* file mode macros */
#define is_read_mode(mode) ((mode) & SNDRV_SEQ_OSS_FILE_READ)
@@ -159,21 +151,21 @@ void snd_seq_oss_readq_info_read(seq_oss_readq_t *q, snd_info_buffer_t *buf);
/* dispatch event */
static inline int
-snd_seq_oss_dispatch(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int atomic, int hop)
+snd_seq_oss_dispatch(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int atomic, int hop)
{
return snd_seq_kernel_client_dispatch(dp->cseq, ev, atomic, hop);
}
/* ioctl */
static inline int
-snd_seq_oss_control(seq_oss_devinfo_t *dp, unsigned int type, void *arg)
+snd_seq_oss_control(struct seq_oss_devinfo *dp, unsigned int type, void *arg)
{
return snd_seq_kernel_client_ctl(dp->cseq, type, arg);
}
/* fill the addresses in header */
static inline void
-snd_seq_oss_fill_addr(seq_oss_devinfo_t *dp, snd_seq_event_t *ev,
+snd_seq_oss_fill_addr(struct seq_oss_devinfo *dp, struct snd_seq_event *ev,
int dest_client, int dest_port)
{
ev->queue = dp->queue;
diff --git a/sound/core/seq/oss/seq_oss_event.c b/sound/core/seq/oss/seq_oss_event.c
index 58e52ddd2927..066f5f3e3f4c 100644
--- a/sound/core/seq/oss/seq_oss_event.c
+++ b/sound/core/seq/oss/seq_oss_event.c
@@ -31,17 +31,17 @@
/*
* prototypes
*/
-static int extended_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev);
-static int chn_voice_event(seq_oss_devinfo_t *dp, evrec_t *event_rec, snd_seq_event_t *ev);
-static int chn_common_event(seq_oss_devinfo_t *dp, evrec_t *event_rec, snd_seq_event_t *ev);
-static int timing_event(seq_oss_devinfo_t *dp, evrec_t *event_rec, snd_seq_event_t *ev);
-static int local_event(seq_oss_devinfo_t *dp, evrec_t *event_rec, snd_seq_event_t *ev);
-static int old_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev);
-static int note_on_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_seq_event_t *ev);
-static int note_off_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_seq_event_t *ev);
-static int set_note_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int note, int vel, snd_seq_event_t *ev);
-static int set_control_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int param, int val, snd_seq_event_t *ev);
-static int set_echo_event(seq_oss_devinfo_t *dp, evrec_t *rec, snd_seq_event_t *ev);
+static int extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
+static int chn_voice_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
+static int chn_common_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
+static int timing_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
+static int local_event(struct seq_oss_devinfo *dp, union evrec *event_rec, struct snd_seq_event *ev);
+static int old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
+static int note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
+static int note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev);
+static int set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev);
+static int set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev);
+static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev);
/*
@@ -51,7 +51,7 @@ static int set_echo_event(seq_oss_devinfo_t *dp, evrec_t *rec, snd_seq_event_t *
*/
int
-snd_seq_oss_process_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
switch (q->s.code) {
case SEQ_EXTENDED:
@@ -104,7 +104,7 @@ snd_seq_oss_process_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev
/* old type events: mode1 only */
static int
-old_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+old_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
switch (q->s.code) {
case SEQ_NOTEOFF:
@@ -130,7 +130,7 @@ old_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
/* 8bytes extended event: mode1 only */
static int
-extended_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+extended_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
int val;
@@ -184,7 +184,7 @@ extended_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
/* channel voice events: mode1 and 2 */
static int
-chn_voice_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+chn_voice_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
if (q->v.chn >= 32)
return -EINVAL;
@@ -205,7 +205,7 @@ chn_voice_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
/* channel common events: mode1 and 2 */
static int
-chn_common_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+chn_common_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
if (q->l.chn >= 32)
return -EINVAL;
@@ -232,14 +232,14 @@ chn_common_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
/* timer events: mode1 and mode2 */
static int
-timing_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+timing_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
switch (q->t.cmd) {
case TMR_ECHO:
if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
return set_echo_event(dp, q, ev);
else {
- evrec_t tmp;
+ union evrec tmp;
memset(&tmp, 0, sizeof(tmp));
/* XXX: only for little-endian! */
tmp.echo = (q->t.time << 8) | SEQ_ECHO;
@@ -267,7 +267,7 @@ timing_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
/* local events: mode1 and 2 */
static int
-local_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
+local_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
{
return -EINVAL;
}
@@ -283,9 +283,9 @@ local_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev)
* Use key-pressure if note >= 128
*/
static int
-note_on_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_seq_event_t *ev)
+note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
{
- seq_oss_synthinfo_t *info = &dp->synths[dev];
+ struct seq_oss_synthinfo *info = &dp->synths[dev];
switch (info->arg.event_passing) {
case SNDRV_SEQ_OSS_PROCESS_EVENTS:
if (! info->ch || ch < 0 || ch >= info->nr_voices) {
@@ -338,9 +338,9 @@ note_on_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_seq
* process note-off event for OSS synth
*/
static int
-note_off_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_seq_event_t *ev)
+note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, struct snd_seq_event *ev)
{
- seq_oss_synthinfo_t *info = &dp->synths[dev];
+ struct seq_oss_synthinfo *info = &dp->synths[dev];
switch (info->arg.event_passing) {
case SNDRV_SEQ_OSS_PROCESS_EVENTS:
if (! info->ch || ch < 0 || ch >= info->nr_voices) {
@@ -369,7 +369,7 @@ note_off_event(seq_oss_devinfo_t *dp, int dev, int ch, int note, int vel, snd_se
* create a note event
*/
static int
-set_note_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int note, int vel, snd_seq_event_t *ev)
+set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev)
{
if (! snd_seq_oss_synth_is_valid(dp, dev))
return -ENXIO;
@@ -387,7 +387,7 @@ set_note_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int note, int v
* create a control event
*/
static int
-set_control_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int param, int val, snd_seq_event_t *ev)
+set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev)
{
if (! snd_seq_oss_synth_is_valid(dp, dev))
return -ENXIO;
@@ -405,7 +405,7 @@ set_control_event(seq_oss_devinfo_t *dp, int dev, int type, int ch, int param, i
* create an echo event
*/
static int
-set_echo_event(seq_oss_devinfo_t *dp, evrec_t *rec, snd_seq_event_t *ev)
+set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct snd_seq_event *ev)
{
ev->type = SNDRV_SEQ_EVENT_ECHO;
/* echo back to itself */
@@ -419,11 +419,11 @@ set_echo_event(seq_oss_devinfo_t *dp, evrec_t *rec, snd_seq_event_t *ev)
* the echo event is processed here.
*/
int
-snd_seq_oss_event_input(snd_seq_event_t *ev, int direct, void *private_data,
+snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data,
int atomic, int hop)
{
- seq_oss_devinfo_t *dp = (seq_oss_devinfo_t *)private_data;
- evrec_t *rec;
+ struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
+ union evrec *rec;
if (ev->type != SNDRV_SEQ_EVENT_ECHO)
return snd_seq_oss_midi_input(ev, direct, private_data);
@@ -431,7 +431,7 @@ snd_seq_oss_event_input(snd_seq_event_t *ev, int direct, void *private_data,
if (ev->source.client != dp->cseq)
return 0; /* ignored */
- rec = (evrec_t*)&ev->data;
+ rec = (union evrec*)&ev->data;
if (rec->s.code == SEQ_SYNCTIMER) {
/* sync echo back */
snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time);
diff --git a/sound/core/seq/oss/seq_oss_event.h b/sound/core/seq/oss/seq_oss_event.h
index bf1d4d3f53c9..9a4d9adb7b8c 100644
--- a/sound/core/seq/oss/seq_oss_event.h
+++ b/sound/core/seq/oss/seq_oss_event.h
@@ -29,74 +29,74 @@
#define LONG_EVENT_SIZE 8
/* short event (4bytes) */
-typedef struct evrec_short_t {
+struct evrec_short {
unsigned char code;
unsigned char parm1;
unsigned char dev;
unsigned char parm2;
-} evrec_short_t;
+};
/* short note events (4bytes) */
-typedef struct evrec_note_t {
+struct evrec_note {
unsigned char code;
unsigned char chn;
unsigned char note;
unsigned char vel;
-} evrec_note_t;
+};
/* long timer events (8bytes) */
-typedef struct evrec_timer_t {
+struct evrec_timer {
unsigned char code;
unsigned char cmd;
unsigned char dummy1, dummy2;
unsigned int time;
-} evrec_timer_t;
+};
/* long extended events (8bytes) */
-typedef struct evrec_extended_t {
+struct evrec_extended {
unsigned char code;
unsigned char cmd;
unsigned char dev;
unsigned char chn;
unsigned char p1, p2, p3, p4;
-} evrec_extended_t;
+};
/* long channel events (8bytes) */
-typedef struct evrec_long_t {
+struct evrec_long {
unsigned char code;
unsigned char dev;
unsigned char cmd;
unsigned char chn;
unsigned char p1, p2;
unsigned short val;
-} evrec_long_t;
+};
/* channel voice events (8bytes) */
-typedef struct evrec_voice_t {
+struct evrec_voice {
unsigned char code;
unsigned char dev;
unsigned char cmd;
unsigned char chn;
unsigned char note, parm;
unsigned short dummy;
-} evrec_voice_t;
+};
/* sysex events (8bytes) */
-typedef struct evrec_sysex_t {
+struct evrec_sysex {
unsigned char code;
unsigned char dev;
unsigned char buf[6];
-} evrec_sysex_t;
+};
/* event record */
-union evrec_t {
- evrec_short_t s;
- evrec_note_t n;
- evrec_long_t l;
- evrec_voice_t v;
- evrec_timer_t t;
- evrec_extended_t e;
- evrec_sysex_t x;
+union evrec {
+ struct evrec_short s;
+ struct evrec_note n;
+ struct evrec_long l;
+ struct evrec_voice v;
+ struct evrec_timer t;
+ struct evrec_extended e;
+ struct evrec_sysex x;
unsigned int echo;
unsigned char c[LONG_EVENT_SIZE];
};
@@ -104,9 +104,9 @@ union evrec_t {
#define ev_is_long(ev) ((ev)->s.code >= 128)
#define ev_length(ev) ((ev)->s.code >= 128 ? LONG_EVENT_SIZE : SHORT_EVENT_SIZE)
-int snd_seq_oss_process_event(seq_oss_devinfo_t *dp, evrec_t *q, snd_seq_event_t *ev);
-int snd_seq_oss_process_timer_event(seq_oss_timer_t *rec, evrec_t *q);
-int snd_seq_oss_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop);
+int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
+int snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *q);
+int snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop);
#endif /* __SEQ_OSS_EVENT_H */
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index 1ab1cf8158c8..ca5a2ed4d7c3 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -41,17 +41,17 @@ static int system_client = -1; /* ALSA sequencer client number */
static int system_port = -1;
static int num_clients;
-static seq_oss_devinfo_t *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
+static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
/*
* prototypes
*/
-static int receive_announce(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop);
+static int receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop);
static int translate_mode(struct file *file);
-static int create_port(seq_oss_devinfo_t *dp);
-static int delete_port(seq_oss_devinfo_t *dp);
-static int alloc_seq_queue(seq_oss_devinfo_t *dp);
+static int create_port(struct seq_oss_devinfo *dp);
+static int delete_port(struct seq_oss_devinfo *dp);
+static int alloc_seq_queue(struct seq_oss_devinfo *dp);
static int delete_seq_queue(int queue);
static void free_devinfo(void *private);
@@ -65,40 +65,24 @@ int __init
snd_seq_oss_create_client(void)
{
int rc;
- snd_seq_client_callback_t callback;
- snd_seq_client_info_t *info;
- snd_seq_port_info_t *port;
- snd_seq_port_callback_t port_callback;
+ struct snd_seq_port_info *port;
+ struct snd_seq_port_callback port_callback;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
port = kmalloc(sizeof(*port), GFP_KERNEL);
- if (!info || !port) {
+ if (!port) {
rc = -ENOMEM;
goto __error;
}
/* create ALSA client */
- memset(&callback, 0, sizeof(callback));
-
- callback.private_data = NULL;
- callback.allow_input = 1;
- callback.allow_output = 1;
-
- rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback);
+ rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS,
+ "OSS sequencer");
if (rc < 0)
goto __error;
system_client = rc;
debug_printk(("new client = %d\n", rc));
- /* set client information */
- memset(info, 0, sizeof(*info));
- info->client = system_client;
- info->type = KERNEL_CLIENT;
- strcpy(info->name, "OSS sequencer");
-
- rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
-
/* look up midi devices */
snd_seq_oss_midi_lookup_ports(system_client);
@@ -118,7 +102,7 @@ snd_seq_oss_create_client(void)
call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
if ((system_port = port->addr.port) >= 0) {
- snd_seq_port_subscribe_t subs;
+ struct snd_seq_port_subscribe subs;
memset(&subs, 0, sizeof(subs));
subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
@@ -131,7 +115,6 @@ snd_seq_oss_create_client(void)
__error:
kfree(port);
- kfree(info);
return rc;
}
@@ -140,9 +123,9 @@ snd_seq_oss_create_client(void)
* receive annoucement from system port, and check the midi device
*/
static int
-receive_announce(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop)
+receive_announce(struct snd_seq_event *ev, int direct, void *private, int atomic, int hop)
{
- snd_seq_port_info_t pinfo;
+ struct snd_seq_port_info pinfo;
if (atomic)
return 0; /* it must not happen */
@@ -191,7 +174,7 @@ int
snd_seq_oss_open(struct file *file, int level)
{
int i, rc;
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
if ((dp = kzalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc device info\n");
@@ -323,11 +306,11 @@ translate_mode(struct file *file)
* create sequencer port
*/
static int
-create_port(seq_oss_devinfo_t *dp)
+create_port(struct seq_oss_devinfo *dp)
{
int rc;
- snd_seq_port_info_t port;
- snd_seq_port_callback_t callback;
+ struct snd_seq_port_info port;
+ struct snd_seq_port_callback callback;
memset(&port, 0, sizeof(port));
port.addr.client = dp->cseq;
@@ -358,7 +341,7 @@ create_port(seq_oss_devinfo_t *dp)
* delete ALSA port
*/
static int
-delete_port(seq_oss_devinfo_t *dp)
+delete_port(struct seq_oss_devinfo *dp)
{
if (dp->port < 0)
return 0;
@@ -371,9 +354,9 @@ delete_port(seq_oss_devinfo_t *dp)
* allocate a queue
*/
static int
-alloc_seq_queue(seq_oss_devinfo_t *dp)
+alloc_seq_queue(struct seq_oss_devinfo *dp)
{
- snd_seq_queue_info_t qinfo;
+ struct snd_seq_queue_info qinfo;
int rc;
memset(&qinfo, 0, sizeof(qinfo));
@@ -392,7 +375,7 @@ alloc_seq_queue(seq_oss_devinfo_t *dp)
static int
delete_seq_queue(int queue)
{
- snd_seq_queue_info_t qinfo;
+ struct snd_seq_queue_info qinfo;
int rc;
if (queue < 0)
@@ -412,7 +395,7 @@ delete_seq_queue(int queue)
static void
free_devinfo(void *private)
{
- seq_oss_devinfo_t *dp = (seq_oss_devinfo_t *)private;
+ struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private;
if (dp->timer)
snd_seq_oss_timer_delete(dp->timer);
@@ -431,7 +414,7 @@ free_devinfo(void *private)
* close sequencer device
*/
void
-snd_seq_oss_release(seq_oss_devinfo_t *dp)
+snd_seq_oss_release(struct seq_oss_devinfo *dp)
{
int queue;
@@ -460,7 +443,7 @@ snd_seq_oss_release(seq_oss_devinfo_t *dp)
* Wait until the queue is empty (if we don't have nonblock)
*/
void
-snd_seq_oss_drain_write(seq_oss_devinfo_t *dp)
+snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
{
if (! dp->timer->running)
return;
@@ -477,7 +460,7 @@ snd_seq_oss_drain_write(seq_oss_devinfo_t *dp)
* reset sequencer devices
*/
void
-snd_seq_oss_reset(seq_oss_devinfo_t *dp)
+snd_seq_oss_reset(struct seq_oss_devinfo *dp)
{
int i;
@@ -502,6 +485,7 @@ snd_seq_oss_reset(seq_oss_devinfo_t *dp)
}
+#ifdef CONFIG_PROC_FS
/*
* misc. functions for proc interface
*/
@@ -525,10 +509,10 @@ filemode_str(int val)
* proc interface
*/
void
-snd_seq_oss_system_info_read(snd_info_buffer_t *buf)
+snd_seq_oss_system_info_read(struct snd_info_buffer *buf)
{
int i;
- seq_oss_devinfo_t *dp;
+ struct seq_oss_devinfo *dp;
snd_iprintf(buf, "ALSA client number %d\n", system_client);
snd_iprintf(buf, "ALSA receiver port %d\n", system_port);
@@ -552,4 +536,4 @@ snd_seq_oss_system_info_read(snd_info_buffer_t *buf)
snd_seq_oss_readq_info_read(dp->readq, buf);
}
}
-
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c
index e86f18d00f39..5ac701c903c1 100644
--- a/sound/core/seq/oss/seq_oss_ioctl.c
+++ b/sound/core/seq/oss/seq_oss_ioctl.c
@@ -28,7 +28,7 @@
#include "seq_oss_midi.h"
#include "seq_oss_event.h"
-static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
{
struct synth_info info;
@@ -41,7 +41,7 @@ static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
return 0;
}
-static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
{
struct midi_info info;
@@ -54,24 +54,24 @@ static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
return 0;
}
-static int snd_seq_oss_oob_user(seq_oss_devinfo_t *dp, void __user *arg)
+static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
{
unsigned char ev[8];
- snd_seq_event_t tmpev;
+ struct snd_seq_event tmpev;
if (copy_from_user(ev, arg, 8))
return -EFAULT;
memset(&tmpev, 0, sizeof(tmpev));
snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
tmpev.time.tick = 0;
- if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
+ if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
}
return 0;
}
int
-snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
+snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
{
int dev, val;
void __user *arg = (void __user *)carg;
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index f0e95c8f2eef..0a711d2d04f0 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -37,15 +37,15 @@
/*
* definition of midi device record
*/
-struct seq_oss_midi_t {
+struct seq_oss_midi {
int seq_device; /* device number */
int client; /* sequencer client number */
int port; /* sequencer port number */
unsigned int flags; /* port capability */
int opened; /* flag for opening */
unsigned char name[SNDRV_SEQ_OSS_MAX_MIDI_NAME];
- snd_midi_event_t *coder; /* MIDI event coder */
- seq_oss_devinfo_t *devinfo; /* assigned OSSseq device */
+ struct snd_midi_event *coder; /* MIDI event coder */
+ struct seq_oss_devinfo *devinfo; /* assigned OSSseq device */
snd_use_lock_t use_lock;
};
@@ -54,17 +54,17 @@ struct seq_oss_midi_t {
* midi device table
*/
static int max_midi_devs;
-static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
+static struct seq_oss_midi *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
*/
-static seq_oss_midi_t *get_mdev(int dev);
-static seq_oss_midi_t *get_mididev(seq_oss_devinfo_t *dp, int dev);
-static int send_synth_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int dev);
-static int send_midi_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, seq_oss_midi_t *mdev);
+static struct seq_oss_midi *get_mdev(int dev);
+static struct seq_oss_midi *get_mididev(struct seq_oss_devinfo *dp, int dev);
+static int send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev);
+static int send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev);
/*
* look up the existing ports
@@ -73,8 +73,8 @@ static int send_midi_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, seq_oss_m
int __init
snd_seq_oss_midi_lookup_ports(int client)
{
- snd_seq_client_info_t *clinfo;
- snd_seq_port_info_t *pinfo;
+ struct snd_seq_client_info *clinfo;
+ struct snd_seq_port_info *pinfo;
clinfo = kzalloc(sizeof(*clinfo), GFP_KERNEL);
pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
@@ -100,10 +100,10 @@ snd_seq_oss_midi_lookup_ports(int client)
/*
*/
-static seq_oss_midi_t *
+static struct seq_oss_midi *
get_mdev(int dev)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
@@ -117,11 +117,11 @@ get_mdev(int dev)
/*
* look for the identical slot
*/
-static seq_oss_midi_t *
+static struct seq_oss_midi *
find_slot(int client, int port)
{
int i;
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
@@ -145,10 +145,10 @@ find_slot(int client, int port)
* register a new port if it doesn't exist yet
*/
int
-snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
+snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{
int i;
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
unsigned long flags;
debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port));
@@ -226,7 +226,7 @@ snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
int
snd_seq_oss_midi_check_exit_port(int client, int port)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
unsigned long flags;
int index;
@@ -258,7 +258,7 @@ void
snd_seq_oss_midi_clear_all(void)
{
int i;
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
@@ -279,7 +279,7 @@ snd_seq_oss_midi_clear_all(void)
* set up midi tables
*/
void
-snd_seq_oss_midi_setup(seq_oss_devinfo_t *dp)
+snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
{
dp->max_mididev = max_midi_devs;
}
@@ -288,7 +288,7 @@ snd_seq_oss_midi_setup(seq_oss_devinfo_t *dp)
* clean up midi tables
*/
void
-snd_seq_oss_midi_cleanup(seq_oss_devinfo_t *dp)
+snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp)
{
int i;
for (i = 0; i < dp->max_mididev; i++)
@@ -301,7 +301,7 @@ snd_seq_oss_midi_cleanup(seq_oss_devinfo_t *dp)
* open all midi devices. ignore errors.
*/
void
-snd_seq_oss_midi_open_all(seq_oss_devinfo_t *dp, int file_mode)
+snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode)
{
int i;
for (i = 0; i < dp->max_mididev; i++)
@@ -312,8 +312,8 @@ snd_seq_oss_midi_open_all(seq_oss_devinfo_t *dp, int file_mode)
/*
* get the midi device information
*/
-static seq_oss_midi_t *
-get_mididev(seq_oss_devinfo_t *dp, int dev)
+static struct seq_oss_midi *
+get_mididev(struct seq_oss_devinfo *dp, int dev)
{
if (dev < 0 || dev >= dp->max_mididev)
return NULL;
@@ -325,11 +325,11 @@ get_mididev(seq_oss_devinfo_t *dp, int dev)
* open the midi device if not opened yet
*/
int
-snd_seq_oss_midi_open(seq_oss_devinfo_t *dp, int dev, int fmode)
+snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int fmode)
{
int perm;
- seq_oss_midi_t *mdev;
- snd_seq_port_subscribe_t subs;
+ struct seq_oss_midi *mdev;
+ struct snd_seq_port_subscribe subs;
if ((mdev = get_mididev(dp, dev)) == NULL)
return -ENODEV;
@@ -392,10 +392,10 @@ snd_seq_oss_midi_open(seq_oss_devinfo_t *dp, int dev, int fmode)
* close the midi device if already opened
*/
int
-snd_seq_oss_midi_close(seq_oss_devinfo_t *dp, int dev)
+snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_midi_t *mdev;
- snd_seq_port_subscribe_t subs;
+ struct seq_oss_midi *mdev;
+ struct snd_seq_port_subscribe subs;
if ((mdev = get_mididev(dp, dev)) == NULL)
return -ENODEV;
@@ -430,9 +430,9 @@ snd_seq_oss_midi_close(seq_oss_devinfo_t *dp, int dev)
* change seq capability flags to file mode flags
*/
int
-snd_seq_oss_midi_filemode(seq_oss_devinfo_t *dp, int dev)
+snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
int mode;
if ((mdev = get_mididev(dp, dev)) == NULL)
@@ -453,9 +453,9 @@ snd_seq_oss_midi_filemode(seq_oss_devinfo_t *dp, int dev)
* so far, only close the device.
*/
void
-snd_seq_oss_midi_reset(seq_oss_devinfo_t *dp, int dev)
+snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL)
return;
@@ -465,7 +465,7 @@ snd_seq_oss_midi_reset(seq_oss_devinfo_t *dp, int dev)
}
if (mdev->opened & PERM_WRITE) {
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
int c;
debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port));
@@ -501,9 +501,9 @@ snd_seq_oss_midi_reset(seq_oss_devinfo_t *dp, int dev)
* get client/port of the specified MIDI device
*/
void
-snd_seq_oss_midi_get_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_addr_t *addr)
+snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL)
return;
@@ -517,10 +517,10 @@ snd_seq_oss_midi_get_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_addr_t *addr)
* input callback - this can be atomic
*/
int
-snd_seq_oss_midi_input(snd_seq_event_t *ev, int direct, void *private_data)
+snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private_data)
{
- seq_oss_devinfo_t *dp = (seq_oss_devinfo_t *)private_data;
- seq_oss_midi_t *mdev;
+ struct seq_oss_devinfo *dp = (struct seq_oss_devinfo *)private_data;
+ struct seq_oss_midi *mdev;
int rc;
if (dp->readq == NULL)
@@ -545,9 +545,9 @@ snd_seq_oss_midi_input(snd_seq_event_t *ev, int direct, void *private_data)
* convert ALSA sequencer event to OSS synth event
*/
static int
-send_synth_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int dev)
+send_synth_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, int dev)
{
- evrec_t ossev;
+ union evrec ossev;
memset(&ossev, 0, sizeof(ossev));
@@ -606,7 +606,7 @@ send_synth_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, int dev)
* decode event and send MIDI bytes to read queue
*/
static int
-send_midi_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, seq_oss_midi_t *mdev)
+send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq_oss_midi *mdev)
{
char msg[32];
int len;
@@ -634,9 +634,9 @@ send_midi_event(seq_oss_devinfo_t *dp, snd_seq_event_t *ev, seq_oss_midi_t *mdev
* non-zero : invalid - ignored
*/
int
-snd_seq_oss_midi_putc(seq_oss_devinfo_t *dp, int dev, unsigned char c, snd_seq_event_t *ev)
+snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL)
return -ENODEV;
@@ -653,9 +653,9 @@ snd_seq_oss_midi_putc(seq_oss_devinfo_t *dp, int dev, unsigned char c, snd_seq_e
* create OSS compatible midi_info record
*/
int
-snd_seq_oss_midi_make_info(seq_oss_devinfo_t *dp, int dev, struct midi_info *inf)
+snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf)
{
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
if ((mdev = get_mididev(dp, dev)) == NULL)
return -ENXIO;
@@ -668,6 +668,7 @@ snd_seq_oss_midi_make_info(seq_oss_devinfo_t *dp, int dev, struct midi_info *inf
}
+#ifdef CONFIG_PROC_FS
/*
* proc interface
*/
@@ -686,10 +687,10 @@ capmode_str(int val)
}
void
-snd_seq_oss_midi_info_read(snd_info_buffer_t *buf)
+snd_seq_oss_midi_info_read(struct snd_info_buffer *buf)
{
int i;
- seq_oss_midi_t *mdev;
+ struct seq_oss_midi *mdev;
snd_iprintf(buf, "\nNumber of MIDI devices: %d\n", max_midi_devs);
for (i = 0; i < max_midi_devs; i++) {
@@ -707,4 +708,4 @@ snd_seq_oss_midi_info_read(snd_info_buffer_t *buf)
snd_use_lock_free(&mdev->use_lock);
}
}
-
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_midi.h b/sound/core/seq/oss/seq_oss_midi.h
index 462484b2b6fe..84eb866ba58e 100644
--- a/sound/core/seq/oss/seq_oss_midi.h
+++ b/sound/core/seq/oss/seq_oss_midi.h
@@ -26,24 +26,23 @@
#include "seq_oss_device.h"
#include <sound/seq_oss_legacy.h>
-typedef struct seq_oss_midi_t seq_oss_midi_t;
-
int snd_seq_oss_midi_lookup_ports(int client);
-int snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo);
+int snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo);
int snd_seq_oss_midi_check_exit_port(int client, int port);
void snd_seq_oss_midi_clear_all(void);
-void snd_seq_oss_midi_setup(seq_oss_devinfo_t *dp);
-void snd_seq_oss_midi_cleanup(seq_oss_devinfo_t *dp);
+void snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp);
+void snd_seq_oss_midi_cleanup(struct seq_oss_devinfo *dp);
-int snd_seq_oss_midi_open(seq_oss_devinfo_t *dp, int dev, int file_mode);
-void snd_seq_oss_midi_open_all(seq_oss_devinfo_t *dp, int file_mode);
-int snd_seq_oss_midi_close(seq_oss_devinfo_t *dp, int dev);
-void snd_seq_oss_midi_reset(seq_oss_devinfo_t *dp, int dev);
-int snd_seq_oss_midi_putc(seq_oss_devinfo_t *dp, int dev, unsigned char c, snd_seq_event_t *ev);
-int snd_seq_oss_midi_input(snd_seq_event_t *ev, int direct, void *private);
-int snd_seq_oss_midi_filemode(seq_oss_devinfo_t *dp, int dev);
-int snd_seq_oss_midi_make_info(seq_oss_devinfo_t *dp, int dev, struct midi_info *inf);
-void snd_seq_oss_midi_get_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_addr_t *addr);
+int snd_seq_oss_midi_open(struct seq_oss_devinfo *dp, int dev, int file_mode);
+void snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode);
+int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev);
+void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev);
+int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c,
+ struct snd_seq_event *ev);
+int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private);
+int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev);
+int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf);
+void snd_seq_oss_midi_get_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_addr *addr);
#endif
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 55571e15cd38..f5de79f29f1e 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -41,17 +41,17 @@
/*
* create a read queue
*/
-seq_oss_readq_t *
-snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
+struct seq_oss_readq *
+snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
{
- seq_oss_readq_t *q;
+ struct seq_oss_readq *q;
if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc read queue\n");
return NULL;
}
- if ((q->q = kcalloc(maxlen, sizeof(evrec_t), GFP_KERNEL)) == NULL) {
+ if ((q->q = kcalloc(maxlen, sizeof(union evrec), GFP_KERNEL)) == NULL) {
snd_printk(KERN_ERR "can't malloc read queue buffer\n");
kfree(q);
return NULL;
@@ -72,7 +72,7 @@ snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
* delete the read queue
*/
void
-snd_seq_oss_readq_delete(seq_oss_readq_t *q)
+snd_seq_oss_readq_delete(struct seq_oss_readq *q)
{
if (q) {
kfree(q->q);
@@ -84,7 +84,7 @@ snd_seq_oss_readq_delete(seq_oss_readq_t *q)
* reset the read queue
*/
void
-snd_seq_oss_readq_clear(seq_oss_readq_t *q)
+snd_seq_oss_readq_clear(struct seq_oss_readq *q)
{
if (q->qlen) {
q->qlen = 0;
@@ -100,9 +100,9 @@ snd_seq_oss_readq_clear(seq_oss_readq_t *q)
* put a midi byte
*/
int
-snd_seq_oss_readq_puts(seq_oss_readq_t *q, int dev, unsigned char *data, int len)
+snd_seq_oss_readq_puts(struct seq_oss_readq *q, int dev, unsigned char *data, int len)
{
- evrec_t rec;
+ union evrec rec;
int result;
memset(&rec, 0, sizeof(rec));
@@ -123,7 +123,7 @@ snd_seq_oss_readq_puts(seq_oss_readq_t *q, int dev, unsigned char *data, int len
* return zero if enqueued
*/
int
-snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
+snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
{
unsigned long flags;
@@ -152,7 +152,7 @@ snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
* caller must hold lock
*/
int
-snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
+snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec)
{
if (q->qlen == 0)
return -EAGAIN;
@@ -164,7 +164,7 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
* sleep until ready
*/
void
-snd_seq_oss_readq_wait(seq_oss_readq_t *q)
+snd_seq_oss_readq_wait(struct seq_oss_readq *q)
{
wait_event_interruptible_timeout(q->midi_sleep,
(q->qlen > 0 || q->head == q->tail),
@@ -176,7 +176,7 @@ snd_seq_oss_readq_wait(seq_oss_readq_t *q)
* caller must hold lock
*/
void
-snd_seq_oss_readq_free(seq_oss_readq_t *q)
+snd_seq_oss_readq_free(struct seq_oss_readq *q)
{
if (q->qlen > 0) {
q->head = (q->head + 1) % q->maxlen;
@@ -189,7 +189,7 @@ snd_seq_oss_readq_free(seq_oss_readq_t *q)
* return non-zero if readq is not empty.
*/
unsigned int
-snd_seq_oss_readq_poll(seq_oss_readq_t *q, struct file *file, poll_table *wait)
+snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *wait)
{
poll_wait(file, &q->midi_sleep, wait);
return q->qlen;
@@ -199,10 +199,10 @@ snd_seq_oss_readq_poll(seq_oss_readq_t *q, struct file *file, poll_table *wait)
* put a timestamp
*/
int
-snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *q, unsigned long curt, int seq_mode)
+snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
{
if (curt != q->input_time) {
- evrec_t rec;
+ union evrec rec;
memset(&rec, 0, sizeof(rec));
switch (seq_mode) {
case SNDRV_SEQ_OSS_MODE_SYNTH:
@@ -222,13 +222,15 @@ snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *q, unsigned long curt, int seq_
}
+#ifdef CONFIG_PROC_FS
/*
* proc interface
*/
void
-snd_seq_oss_readq_info_read(seq_oss_readq_t *q, snd_info_buffer_t *buf)
+snd_seq_oss_readq_info_read(struct seq_oss_readq *q, struct snd_info_buffer *buf)
{
snd_iprintf(buf, " read queue [%s] length = %d : tick = %ld\n",
(waitqueue_active(&q->midi_sleep) ? "sleeping":"running"),
q->qlen, q->input_time);
}
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h
index 303b9298f206..f1463f1f449e 100644
--- a/sound/core/seq/oss/seq_oss_readq.h
+++ b/sound/core/seq/oss/seq_oss_readq.h
@@ -28,8 +28,8 @@
/*
* definition of read queue
*/
-struct seq_oss_readq_t {
- evrec_t *q;
+struct seq_oss_readq {
+ union evrec *q;
int qlen;
int maxlen;
int head, tail;
@@ -39,16 +39,16 @@ struct seq_oss_readq_t {
spinlock_t lock;
};
-seq_oss_readq_t *snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen);
-void snd_seq_oss_readq_delete(seq_oss_readq_t *q);
-void snd_seq_oss_readq_clear(seq_oss_readq_t *readq);
-unsigned int snd_seq_oss_readq_poll(seq_oss_readq_t *readq, struct file *file, poll_table *wait);
-int snd_seq_oss_readq_puts(seq_oss_readq_t *readq, int dev, unsigned char *data, int len);
-int snd_seq_oss_readq_put_event(seq_oss_readq_t *readq, evrec_t *ev);
-int snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *readq, unsigned long curt, int seq_mode);
-int snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec);
-void snd_seq_oss_readq_wait(seq_oss_readq_t *q);
-void snd_seq_oss_readq_free(seq_oss_readq_t *q);
+struct seq_oss_readq *snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen);
+void snd_seq_oss_readq_delete(struct seq_oss_readq *q);
+void snd_seq_oss_readq_clear(struct seq_oss_readq *readq);
+unsigned int snd_seq_oss_readq_poll(struct seq_oss_readq *readq, struct file *file, poll_table *wait);
+int snd_seq_oss_readq_puts(struct seq_oss_readq *readq, int dev, unsigned char *data, int len);
+int snd_seq_oss_readq_put_event(struct seq_oss_readq *readq, union evrec *ev);
+int snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *readq, unsigned long curt, int seq_mode);
+int snd_seq_oss_readq_pick(struct seq_oss_readq *q, union evrec *rec);
+void snd_seq_oss_readq_wait(struct seq_oss_readq *q);
+void snd_seq_oss_readq_free(struct seq_oss_readq *q);
#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags)
#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags)
diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c
index 1d8fbd22e3e3..6a7b6aceeca9 100644
--- a/sound/core/seq/oss/seq_oss_rw.c
+++ b/sound/core/seq/oss/seq_oss_rw.c
@@ -33,7 +33,7 @@
/*
* protoypes
*/
-static int insert_queue(seq_oss_devinfo_t *dp, evrec_t *rec, struct file *opt);
+static int insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt);
/*
@@ -41,12 +41,12 @@ static int insert_queue(seq_oss_devinfo_t *dp, evrec_t *rec, struct file *opt);
*/
int
-snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
+snd_seq_oss_read(struct seq_oss_devinfo *dp, char __user *buf, int count)
{
- seq_oss_readq_t *readq = dp->readq;
+ struct seq_oss_readq *readq = dp->readq;
int result = 0, err = 0;
int ev_len;
- evrec_t rec;
+ union evrec rec;
unsigned long flags;
if (readq == NULL || ! is_read_mode(dp->file_mode))
@@ -93,11 +93,11 @@ snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
*/
int
-snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt)
+snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt)
{
int result = 0, err = 0;
int ev_size, fmt;
- evrec_t rec;
+ union evrec rec;
if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
return -ENXIO;
@@ -161,10 +161,10 @@ snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, stru
* return: 0 = OK, non-zero = NG
*/
static int
-insert_queue(seq_oss_devinfo_t *dp, evrec_t *rec, struct file *opt)
+insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt)
{
int rc = 0;
- snd_seq_event_t event;
+ struct snd_seq_event event;
/* if this is a timing event, process the current time */
if (snd_seq_oss_process_timer_event(dp->timer, rec))
@@ -197,7 +197,7 @@ insert_queue(seq_oss_devinfo_t *dp, evrec_t *rec, struct file *opt)
*/
unsigned int
-snd_seq_oss_poll(seq_oss_devinfo_t *dp, struct file *file, poll_table * wait)
+snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait)
{
unsigned int mask = 0;
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 8257fce2ca1b..ab570a0a6183 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -37,14 +37,14 @@
*/
/* sysex buffer */
-struct seq_oss_synth_sysex_t {
+struct seq_oss_synth_sysex {
int len;
int skip;
unsigned char buf[MAX_SYSEX_BUFLEN];
};
/* synth info */
-struct seq_oss_synth_t {
+struct seq_oss_synth {
int seq_device;
/* for synth_info */
@@ -53,7 +53,7 @@ struct seq_oss_synth_t {
int nr_voices;
char name[SNDRV_SEQ_OSS_MAX_SYNTH_NAME];
- snd_seq_oss_callback_t oper;
+ struct snd_seq_oss_callback oper;
int opened;
@@ -66,8 +66,8 @@ struct seq_oss_synth_t {
* device table
*/
static int max_synth_devs;
-static seq_oss_synth_t *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
-static seq_oss_synth_t midi_synth_dev = {
+static struct seq_oss_synth *synth_devs[SNDRV_SEQ_OSS_MAX_SYNTH_DEVS];
+static struct seq_oss_synth midi_synth_dev = {
-1, /* seq_device */
SYNTH_TYPE_MIDI, /* synth_type */
0, /* synth_subtype */
@@ -80,8 +80,8 @@ static DEFINE_SPINLOCK(register_lock);
/*
* prototypes
*/
-static seq_oss_synth_t *get_synthdev(seq_oss_devinfo_t *dp, int dev);
-static void reset_channels(seq_oss_synthinfo_t *info);
+static struct seq_oss_synth *get_synthdev(struct seq_oss_devinfo *dp, int dev);
+static void reset_channels(struct seq_oss_synthinfo *info);
/*
* global initialization
@@ -96,11 +96,11 @@ snd_seq_oss_synth_init(void)
* registration of the synth device
*/
int
-snd_seq_oss_synth_register(snd_seq_device_t *dev)
+snd_seq_oss_synth_register(struct snd_seq_device *dev)
{
int i;
- seq_oss_synth_t *rec;
- snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ struct seq_oss_synth *rec;
+ struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
unsigned long flags;
if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
@@ -148,10 +148,10 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
int
-snd_seq_oss_synth_unregister(snd_seq_device_t *dev)
+snd_seq_oss_synth_unregister(struct snd_seq_device *dev)
{
int index;
- seq_oss_synth_t *rec = dev->driver_data;
+ struct seq_oss_synth *rec = dev->driver_data;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
@@ -187,10 +187,10 @@ snd_seq_oss_synth_unregister(snd_seq_device_t *dev)
/*
*/
-static seq_oss_synth_t *
+static struct seq_oss_synth *
get_sdev(int dev)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
unsigned long flags;
spin_lock_irqsave(&register_lock, flags);
@@ -207,11 +207,11 @@ get_sdev(int dev)
*/
void
-snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
+snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
{
int i;
- seq_oss_synth_t *rec;
- seq_oss_synthinfo_t *info;
+ struct seq_oss_synth *rec;
+ struct seq_oss_synthinfo *info;
dp->max_synthdev = max_synth_devs;
dp->synth_opened = 0;
@@ -244,7 +244,7 @@ snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
}
info->nr_voices = rec->nr_voices;
if (info->nr_voices > 0) {
- info->ch = kcalloc(info->nr_voices, sizeof(seq_oss_chinfo_t), GFP_KERNEL);
+ info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
if (!info->ch)
BUG();
reset_channels(info);
@@ -263,7 +263,7 @@ snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
*/
void
-snd_seq_oss_synth_setup_midi(seq_oss_devinfo_t *dp)
+snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp)
{
int i;
@@ -271,7 +271,7 @@ snd_seq_oss_synth_setup_midi(seq_oss_devinfo_t *dp)
return;
for (i = 0; i < dp->max_mididev; i++) {
- seq_oss_synthinfo_t *info;
+ struct seq_oss_synthinfo *info;
info = &dp->synths[dp->max_synthdev];
if (snd_seq_oss_midi_open(dp, i, dp->file_mode) < 0)
continue;
@@ -297,11 +297,11 @@ snd_seq_oss_synth_setup_midi(seq_oss_devinfo_t *dp)
*/
void
-snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
+snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
{
int i;
- seq_oss_synth_t *rec;
- seq_oss_synthinfo_t *info;
+ struct seq_oss_synth *rec;
+ struct seq_oss_synthinfo *info;
snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return);
for (i = 0; i < dp->max_synthdev; i++) {
@@ -338,7 +338,7 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
* check if the specified device is MIDI mapped device
*/
static int
-is_midi_dev(seq_oss_devinfo_t *dp, int dev)
+is_midi_dev(struct seq_oss_devinfo *dp, int dev)
{
if (dev < 0 || dev >= dp->max_synthdev)
return 0;
@@ -350,10 +350,10 @@ is_midi_dev(seq_oss_devinfo_t *dp, int dev)
/*
* return synth device information pointer
*/
-static seq_oss_synth_t *
-get_synthdev(seq_oss_devinfo_t *dp, int dev)
+static struct seq_oss_synth *
+get_synthdev(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
if (dev < 0 || dev >= dp->max_synthdev)
return NULL;
if (! dp->synths[dev].opened)
@@ -374,7 +374,7 @@ get_synthdev(seq_oss_devinfo_t *dp, int dev)
* reset note and velocity on each channel.
*/
static void
-reset_channels(seq_oss_synthinfo_t *info)
+reset_channels(struct seq_oss_synthinfo *info)
{
int i;
if (info->ch == NULL || ! info->nr_voices)
@@ -392,10 +392,10 @@ reset_channels(seq_oss_synthinfo_t *info)
* event to the corresponding port.
*/
void
-snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
+snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_synth_t *rec;
- seq_oss_synthinfo_t *info;
+ struct seq_oss_synth *rec;
+ struct seq_oss_synthinfo *info;
snd_assert(dev >= 0 && dev < dp->max_synthdev, return);
info = &dp->synths[dev];
@@ -428,7 +428,7 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
if (rec->oper.reset) {
rec->oper.reset(&info->arg);
} else {
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
memset(&ev, 0, sizeof(ev));
snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
info->arg.addr.port);
@@ -444,10 +444,10 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
* call load_patch callback function
*/
int
-snd_seq_oss_synth_load_patch(seq_oss_devinfo_t *dp, int dev, int fmt,
+snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
int rc;
if (dev < 0 || dev >= dp->max_synthdev)
@@ -470,9 +470,9 @@ snd_seq_oss_synth_load_patch(seq_oss_devinfo_t *dp, int dev, int fmt,
* check if the device is valid synth device
*/
int
-snd_seq_oss_synth_is_valid(seq_oss_devinfo_t *dp, int dev)
+snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
rec = get_synthdev(dp, dev);
if (rec) {
snd_use_lock_free(&rec->use_lock);
@@ -488,11 +488,11 @@ snd_seq_oss_synth_is_valid(seq_oss_devinfo_t *dp, int dev)
* (0xff).
*/
int
-snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_seq_event_t *ev)
+snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, struct snd_seq_event *ev)
{
int i, send;
unsigned char *dest;
- seq_oss_synth_sysex_t *sysex;
+ struct seq_oss_synth_sysex *sysex;
if (! snd_seq_oss_synth_is_valid(dp, dev))
return -ENXIO;
@@ -545,7 +545,7 @@ snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_
* fill the event source/destination addresses
*/
int
-snd_seq_oss_synth_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_event_t *ev)
+snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
{
if (! snd_seq_oss_synth_is_valid(dp, dev))
return -EINVAL;
@@ -559,9 +559,9 @@ snd_seq_oss_synth_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_event_t *ev)
* OSS compatible ioctl
*/
int
-snd_seq_oss_synth_ioctl(seq_oss_devinfo_t *dp, int dev, unsigned int cmd, unsigned long addr)
+snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
int rc;
if (is_midi_dev(dp, dev))
@@ -581,7 +581,7 @@ snd_seq_oss_synth_ioctl(seq_oss_devinfo_t *dp, int dev, unsigned int cmd, unsign
* send OSS raw events - SEQ_PRIVATE and SEQ_VOLUME
*/
int
-snd_seq_oss_synth_raw_event(seq_oss_devinfo_t *dp, int dev, unsigned char *data, snd_seq_event_t *ev)
+snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
{
if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev))
return -ENXIO;
@@ -595,9 +595,9 @@ snd_seq_oss_synth_raw_event(seq_oss_devinfo_t *dp, int dev, unsigned char *data,
* create OSS compatible synth_info record
*/
int
-snd_seq_oss_synth_make_info(seq_oss_devinfo_t *dp, int dev, struct synth_info *inf)
+snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf)
{
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
if (dp->synths[dev].is_midi) {
struct midi_info minf;
@@ -621,14 +621,15 @@ snd_seq_oss_synth_make_info(seq_oss_devinfo_t *dp, int dev, struct synth_info *i
}
+#ifdef CONFIG_PROC_FS
/*
* proc interface
*/
void
-snd_seq_oss_synth_info_read(snd_info_buffer_t *buf)
+snd_seq_oss_synth_info_read(struct snd_info_buffer *buf)
{
int i;
- seq_oss_synth_t *rec;
+ struct seq_oss_synth *rec;
snd_iprintf(buf, "\nNumber of synth devices: %d\n", max_synth_devs);
for (i = 0; i < max_synth_devs; i++) {
@@ -648,4 +649,4 @@ snd_seq_oss_synth_info_read(snd_info_buffer_t *buf)
snd_use_lock_free(&rec->use_lock);
}
}
-
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/core/seq/oss/seq_oss_synth.h b/sound/core/seq/oss/seq_oss_synth.h
index 07bc0e2cfb82..dbdfcbb80eaa 100644
--- a/sound/core/seq/oss/seq_oss_synth.h
+++ b/sound/core/seq/oss/seq_oss_synth.h
@@ -27,23 +27,25 @@
#include <sound/seq_oss_legacy.h>
#include <sound/seq_device.h>
-typedef struct seq_oss_synth_t seq_oss_synth_t;
-
void snd_seq_oss_synth_init(void);
-int snd_seq_oss_synth_register(snd_seq_device_t *dev);
-int snd_seq_oss_synth_unregister(snd_seq_device_t *dev);
-void snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp);
-void snd_seq_oss_synth_setup_midi(seq_oss_devinfo_t *dp);
-void snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp);
+int snd_seq_oss_synth_register(struct snd_seq_device *dev);
+int snd_seq_oss_synth_unregister(struct snd_seq_device *dev);
+void snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp);
+void snd_seq_oss_synth_setup_midi(struct seq_oss_devinfo *dp);
+void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
-void snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev);
-int snd_seq_oss_synth_load_patch(seq_oss_devinfo_t *dp, int dev, int fmt, const char __user *buf, int p, int c);
-int snd_seq_oss_synth_is_valid(seq_oss_devinfo_t *dp, int dev);
-int snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_seq_event_t *ev);
-int snd_seq_oss_synth_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_event_t *ev);
-int snd_seq_oss_synth_ioctl(seq_oss_devinfo_t *dp, int dev, unsigned int cmd, unsigned long addr);
-int snd_seq_oss_synth_raw_event(seq_oss_devinfo_t *dp, int dev, unsigned char *data, snd_seq_event_t *ev);
+void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev);
+int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
+ const char __user *buf, int p, int c);
+int snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev);
+int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
+ struct snd_seq_event *ev);
+int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev);
+int snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd,
+ unsigned long addr);
+int snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev,
+ unsigned char *data, struct snd_seq_event *ev);
-int snd_seq_oss_synth_make_info(seq_oss_devinfo_t *dp, int dev, struct synth_info *inf);
+int snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_info *inf);
#endif
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index 64d594b3170f..c440fdacec93 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -33,18 +33,18 @@
/*
*/
-static void calc_alsa_tempo(seq_oss_timer_t *timer);
-static int send_timer_event(seq_oss_devinfo_t *dp, int type, int value);
+static void calc_alsa_tempo(struct seq_oss_timer *timer);
+static int send_timer_event(struct seq_oss_devinfo *dp, int type, int value);
/*
* create and register a new timer.
* if queue is not started yet, start it.
*/
-seq_oss_timer_t *
-snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
+struct seq_oss_timer *
+snd_seq_oss_timer_new(struct seq_oss_devinfo *dp)
{
- seq_oss_timer_t *rec;
+ struct seq_oss_timer *rec;
rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (rec == NULL)
@@ -67,7 +67,7 @@ snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
* if no more timer exists, stop the queue.
*/
void
-snd_seq_oss_timer_delete(seq_oss_timer_t *rec)
+snd_seq_oss_timer_delete(struct seq_oss_timer *rec)
{
if (rec) {
snd_seq_oss_timer_stop(rec);
@@ -82,7 +82,7 @@ snd_seq_oss_timer_delete(seq_oss_timer_t *rec)
* 0 : not a timer event -- enqueue this event
*/
int
-snd_seq_oss_process_timer_event(seq_oss_timer_t *rec, evrec_t *ev)
+snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *ev)
{
abstime_t parm = ev->t.time;
@@ -125,7 +125,7 @@ snd_seq_oss_process_timer_event(seq_oss_timer_t *rec, evrec_t *ev)
* convert tempo units
*/
static void
-calc_alsa_tempo(seq_oss_timer_t *timer)
+calc_alsa_tempo(struct seq_oss_timer *timer)
{
timer->tempo = (60 * 1000000) / timer->oss_tempo;
timer->ppq = timer->oss_timebase;
@@ -136,9 +136,9 @@ calc_alsa_tempo(seq_oss_timer_t *timer)
* dispatch a timer event
*/
static int
-send_timer_event(seq_oss_devinfo_t *dp, int type, int value)
+send_timer_event(struct seq_oss_devinfo *dp, int type, int value)
{
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = type;
@@ -156,10 +156,10 @@ send_timer_event(seq_oss_devinfo_t *dp, int type, int value)
* set queue tempo and start queue
*/
int
-snd_seq_oss_timer_start(seq_oss_timer_t *timer)
+snd_seq_oss_timer_start(struct seq_oss_timer *timer)
{
- seq_oss_devinfo_t *dp = timer->dp;
- snd_seq_queue_tempo_t tmprec;
+ struct seq_oss_devinfo *dp = timer->dp;
+ struct snd_seq_queue_tempo tmprec;
if (timer->running)
snd_seq_oss_timer_stop(timer);
@@ -181,7 +181,7 @@ snd_seq_oss_timer_start(seq_oss_timer_t *timer)
* stop queue
*/
int
-snd_seq_oss_timer_stop(seq_oss_timer_t *timer)
+snd_seq_oss_timer_stop(struct seq_oss_timer *timer)
{
if (! timer->running)
return 0;
@@ -195,7 +195,7 @@ snd_seq_oss_timer_stop(seq_oss_timer_t *timer)
* continue queue
*/
int
-snd_seq_oss_timer_continue(seq_oss_timer_t *timer)
+snd_seq_oss_timer_continue(struct seq_oss_timer *timer)
{
if (timer->running)
return 0;
@@ -209,7 +209,7 @@ snd_seq_oss_timer_continue(seq_oss_timer_t *timer)
* change queue tempo
*/
int
-snd_seq_oss_timer_tempo(seq_oss_timer_t *timer, int value)
+snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value)
{
if (value < MIN_OSS_TEMPO)
value = MIN_OSS_TEMPO;
@@ -227,7 +227,7 @@ snd_seq_oss_timer_tempo(seq_oss_timer_t *timer, int value)
* ioctls
*/
int
-snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, int __user *arg)
+snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg)
{
int value;
diff --git a/sound/core/seq/oss/seq_oss_timer.h b/sound/core/seq/oss/seq_oss_timer.h
index 6e4dbd8504c1..b995bd68ad1f 100644
--- a/sound/core/seq/oss/seq_oss_timer.h
+++ b/sound/core/seq/oss/seq_oss_timer.h
@@ -27,8 +27,8 @@
/*
* timer information definition
*/
-struct seq_oss_timer_t {
- seq_oss_devinfo_t *dp;
+struct seq_oss_timer {
+ struct seq_oss_devinfo *dp;
reltime_t cur_tick;
int realtime;
int running;
@@ -37,22 +37,22 @@ struct seq_oss_timer_t {
};
-seq_oss_timer_t *snd_seq_oss_timer_new(seq_oss_devinfo_t *dp);
-void snd_seq_oss_timer_delete(seq_oss_timer_t *dp);
+struct seq_oss_timer *snd_seq_oss_timer_new(struct seq_oss_devinfo *dp);
+void snd_seq_oss_timer_delete(struct seq_oss_timer *dp);
-int snd_seq_oss_timer_start(seq_oss_timer_t *timer);
-int snd_seq_oss_timer_stop(seq_oss_timer_t *timer);
-int snd_seq_oss_timer_continue(seq_oss_timer_t *timer);
-int snd_seq_oss_timer_tempo(seq_oss_timer_t *timer, int value);
+int snd_seq_oss_timer_start(struct seq_oss_timer *timer);
+int snd_seq_oss_timer_stop(struct seq_oss_timer *timer);
+int snd_seq_oss_timer_continue(struct seq_oss_timer *timer);
+int snd_seq_oss_timer_tempo(struct seq_oss_timer *timer, int value);
#define snd_seq_oss_timer_reset snd_seq_oss_timer_start
-int snd_seq_oss_timer_ioctl(seq_oss_timer_t *timer, unsigned int cmd, int __user *arg);
+int snd_seq_oss_timer_ioctl(struct seq_oss_timer *timer, unsigned int cmd, int __user *arg);
/*
* get current processed time
*/
static inline abstime_t
-snd_seq_oss_timer_cur_tick(seq_oss_timer_t *timer)
+snd_seq_oss_timer_cur_tick(struct seq_oss_timer *timer)
{
return timer->cur_tick;
}
@@ -62,7 +62,7 @@ snd_seq_oss_timer_cur_tick(seq_oss_timer_t *timer)
* is realtime event?
*/
static inline int
-snd_seq_oss_timer_is_realtime(seq_oss_timer_t *timer)
+snd_seq_oss_timer_is_realtime(struct seq_oss_timer *timer)
{
return timer->realtime;
}
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index b20378024547..5c8495601a38 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -32,11 +32,11 @@
/*
* create a write queue record
*/
-seq_oss_writeq_t *
-snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
+struct seq_oss_writeq *
+snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen)
{
- seq_oss_writeq_t *q;
- snd_seq_client_pool_t pool;
+ struct seq_oss_writeq *q;
+ struct snd_seq_client_pool pool;
if ((q = kzalloc(sizeof(*q), GFP_KERNEL)) == NULL)
return NULL;
@@ -61,7 +61,7 @@ snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
* delete the write queue
*/
void
-snd_seq_oss_writeq_delete(seq_oss_writeq_t *q)
+snd_seq_oss_writeq_delete(struct seq_oss_writeq *q)
{
snd_seq_oss_writeq_clear(q); /* to be sure */
kfree(q);
@@ -72,9 +72,9 @@ snd_seq_oss_writeq_delete(seq_oss_writeq_t *q)
* reset the write queue
*/
void
-snd_seq_oss_writeq_clear(seq_oss_writeq_t *q)
+snd_seq_oss_writeq_clear(struct seq_oss_writeq *q)
{
- snd_seq_remove_events_t reset;
+ struct snd_seq_remove_events reset;
memset(&reset, 0, sizeof(reset));
reset.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT; /* remove all */
@@ -88,9 +88,9 @@ snd_seq_oss_writeq_clear(seq_oss_writeq_t *q)
* wait until the write buffer has enough room
*/
int
-snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
+snd_seq_oss_writeq_sync(struct seq_oss_writeq *q)
{
- seq_oss_devinfo_t *dp = q->dp;
+ struct seq_oss_devinfo *dp = q->dp;
abstime_t time;
time = snd_seq_oss_timer_cur_tick(dp->timer);
@@ -98,8 +98,8 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
return 0; /* already finished */
if (! q->sync_event_put) {
- snd_seq_event_t ev;
- evrec_t *rec;
+ struct snd_seq_event ev;
+ union evrec *rec;
/* put echoback event */
memset(&ev, 0, sizeof(ev));
@@ -108,7 +108,7 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
ev.time.tick = time;
/* echo back to itself */
snd_seq_oss_fill_addr(dp, &ev, dp->addr.client, dp->addr.port);
- rec = (evrec_t*)&ev.data;
+ rec = (union evrec *)&ev.data;
rec->t.code = SEQ_SYNCTIMER;
rec->t.time = time;
q->sync_event_put = 1;
@@ -128,7 +128,7 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
* wake up sync - echo event was catched
*/
void
-snd_seq_oss_writeq_wakeup(seq_oss_writeq_t *q, abstime_t time)
+snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time)
{
unsigned long flags;
@@ -146,9 +146,9 @@ snd_seq_oss_writeq_wakeup(seq_oss_writeq_t *q, abstime_t time)
* return the unused pool size
*/
int
-snd_seq_oss_writeq_get_free_size(seq_oss_writeq_t *q)
+snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q)
{
- snd_seq_client_pool_t pool;
+ struct snd_seq_client_pool pool;
pool.client = q->dp->cseq;
snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool);
return pool.output_free;
@@ -159,9 +159,9 @@ snd_seq_oss_writeq_get_free_size(seq_oss_writeq_t *q)
* set output threshold size from ioctl
*/
void
-snd_seq_oss_writeq_set_output(seq_oss_writeq_t *q, int val)
+snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int val)
{
- snd_seq_client_pool_t pool;
+ struct snd_seq_client_pool pool;
pool.client = q->dp->cseq;
snd_seq_oss_control(q->dp, SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, &pool);
pool.output_room = val;
diff --git a/sound/core/seq/oss/seq_oss_writeq.h b/sound/core/seq/oss/seq_oss_writeq.h
index 6a13c85e2399..c469d2967566 100644
--- a/sound/core/seq/oss/seq_oss_writeq.h
+++ b/sound/core/seq/oss/seq_oss_writeq.h
@@ -25,8 +25,8 @@
#include "seq_oss_device.h"
-struct seq_oss_writeq_t {
- seq_oss_devinfo_t *dp;
+struct seq_oss_writeq {
+ struct seq_oss_devinfo *dp;
int maxlen;
abstime_t sync_time;
int sync_event_put;
@@ -38,13 +38,13 @@ struct seq_oss_writeq_t {
/*
* seq_oss_writeq.c
*/
-seq_oss_writeq_t *snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen);
-void snd_seq_oss_writeq_delete(seq_oss_writeq_t *q);
-void snd_seq_oss_writeq_clear(seq_oss_writeq_t *q);
-int snd_seq_oss_writeq_sync(seq_oss_writeq_t *q);
-void snd_seq_oss_writeq_wakeup(seq_oss_writeq_t *q, abstime_t time);
-int snd_seq_oss_writeq_get_free_size(seq_oss_writeq_t *q);
-void snd_seq_oss_writeq_set_output(seq_oss_writeq_t *q, int size);
+struct seq_oss_writeq *snd_seq_oss_writeq_new(struct seq_oss_devinfo *dp, int maxlen);
+void snd_seq_oss_writeq_delete(struct seq_oss_writeq *q);
+void snd_seq_oss_writeq_clear(struct seq_oss_writeq *q);
+int snd_seq_oss_writeq_sync(struct seq_oss_writeq *q);
+void snd_seq_oss_writeq_wakeup(struct seq_oss_writeq *q, abstime_t time);
+int snd_seq_oss_writeq_get_free_size(struct seq_oss_writeq *q);
+void snd_seq_oss_writeq_set_output(struct seq_oss_writeq *q, int size);
#endif
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 24644150f24b..20f954bc7aa0 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -36,9 +36,9 @@
#include <sound/seq_device.h>
#if defined(CONFIG_SND_SEQ_DUMMY_MODULE)
-int seq_client_load[64] = {[0] = SNDRV_SEQ_CLIENT_DUMMY, [1 ... 63] = -1};
+int seq_client_load[15] = {[0] = SNDRV_SEQ_CLIENT_DUMMY, [1 ... 14] = -1};
#else
-int seq_client_load[64] = {[0 ... 63] = -1};
+int seq_client_load[15] = {[0 ... 14] = -1};
#endif
int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index a886db94b1fa..fd2032eae214 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -47,6 +47,21 @@
*
*/
+/*
+ * There are four ranges of client numbers (last two shared):
+ * 0..15: global clients
+ * 16..127: statically allocated client numbers for cards 0..27
+ * 128..191: dynamically allocated client numbers for cards 28..31
+ * 128..191: dynamically allocated client numbers for applications
+ */
+
+/* number of kernel non-card clients */
+#define SNDRV_SEQ_GLOBAL_CLIENTS 16
+/* clients per cards, for static clients */
+#define SNDRV_SEQ_CLIENTS_PER_CARD 4
+/* dynamically allocated client numbers (both kernel drivers and user space) */
+#define SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN 128
+
#define SNDRV_SEQ_LFLG_INPUT 0x0001
#define SNDRV_SEQ_LFLG_OUTPUT 0x0002
#define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
@@ -58,14 +73,18 @@ static DECLARE_MUTEX(register_mutex);
* client table
*/
static char clienttablock[SNDRV_SEQ_MAX_CLIENTS];
-static client_t *clienttab[SNDRV_SEQ_MAX_CLIENTS];
-static usage_t client_usage;
+static struct snd_seq_client *clienttab[SNDRV_SEQ_MAX_CLIENTS];
+static struct snd_seq_usage client_usage;
/*
* prototypes
*/
-static int bounce_error_event(client_t *client, snd_seq_event_t *event, int err, int atomic, int hop);
-static int snd_seq_deliver_single_event(client_t *client, snd_seq_event_t *event, int filter, int atomic, int hop);
+static int bounce_error_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int err, int atomic, int hop);
+static int snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
+ int filter, int atomic, int hop);
/*
*/
@@ -96,16 +115,17 @@ static inline unsigned short snd_seq_file_flags(struct file *file)
}
}
-static inline int snd_seq_write_pool_allocated(client_t *client)
+static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client)
{
return snd_seq_total_cells(client->pool) > 0;
}
/* return pointer to client structure for specified id */
-static client_t *clientptr(int clientid)
+static struct snd_seq_client *clientptr(int clientid)
{
if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
- snd_printd("Seq: oops. Trying to get pointer to client %d\n", clientid);
+ snd_printd("Seq: oops. Trying to get pointer to client %d\n",
+ clientid);
return NULL;
}
return clienttab[clientid];
@@ -113,13 +133,14 @@ static client_t *clientptr(int clientid)
extern int seq_client_load[];
-client_t *snd_seq_client_use_ptr(int clientid)
+struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
{
unsigned long flags;
- client_t *client;
+ struct snd_seq_client *client;
if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {
- snd_printd("Seq: oops. Trying to get pointer to client %d\n", clientid);
+ snd_printd("Seq: oops. Trying to get pointer to client %d\n",
+ clientid);
return NULL;
}
spin_lock_irqsave(&clients_lock, flags);
@@ -133,24 +154,26 @@ client_t *snd_seq_client_use_ptr(int clientid)
spin_unlock_irqrestore(&clients_lock, flags);
#ifdef CONFIG_KMOD
if (!in_interrupt() && current->fs->root) {
- static char client_requested[64];
+ static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
static char card_requested[SNDRV_CARDS];
- if (clientid < 64) {
+ if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
int idx;
if (! client_requested[clientid] && current->fs->root) {
client_requested[clientid] = 1;
- for (idx = 0; idx < 64; idx++) {
+ for (idx = 0; idx < 15; idx++) {
if (seq_client_load[idx] < 0)
break;
if (seq_client_load[idx] == clientid) {
- request_module("snd-seq-client-%i", clientid);
+ request_module("snd-seq-client-%i",
+ clientid);
break;
}
}
}
- } else if (clientid >= 64 && clientid < 128) {
- int card = (clientid - 64) / 8;
+ } else if (clientid < SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) {
+ int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
+ SNDRV_SEQ_CLIENTS_PER_CARD;
if (card < snd_ecards_limit) {
if (! card_requested[card]) {
card_requested[card] = 1;
@@ -174,14 +197,14 @@ client_t *snd_seq_client_use_ptr(int clientid)
return client;
}
-static void usage_alloc(usage_t * res, int num)
+static void usage_alloc(struct snd_seq_usage *res, int num)
{
res->cur += num;
if (res->cur > res->peak)
res->peak = res->cur;
}
-static void usage_free(usage_t * res, int num)
+static void usage_free(struct snd_seq_usage *res, int num)
{
res->cur -= num;
}
@@ -196,11 +219,11 @@ int __init client_init_data(void)
}
-static client_t *seq_create_client1(int client_index, int poolsize)
+static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)
{
unsigned long flags;
int c;
- client_t *client;
+ struct snd_seq_client *client;
/* init client data */
client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -220,7 +243,9 @@ static client_t *seq_create_client1(int client_index, int poolsize)
/* find free slot in the client table */
spin_lock_irqsave(&clients_lock, flags);
if (client_index < 0) {
- for (c = 128; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
+ for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;
+ c < SNDRV_SEQ_MAX_CLIENTS;
+ c++) {
if (clienttab[c] || clienttablock[c])
continue;
clienttab[client->number = c] = client;
@@ -241,7 +266,7 @@ static client_t *seq_create_client1(int client_index, int poolsize)
}
-static int seq_free_client1(client_t *client)
+static int seq_free_client1(struct snd_seq_client *client)
{
unsigned long flags;
@@ -263,12 +288,13 @@ static int seq_free_client1(client_t *client)
}
-static void seq_free_client(client_t * client)
+static void seq_free_client(struct snd_seq_client * client)
{
down(&register_mutex);
switch (client->type) {
case NO_CLIENT:
- snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", client->number);
+ snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n",
+ client->number);
break;
case USER_CLIENT:
case KERNEL_CLIENT:
@@ -277,7 +303,8 @@ static void seq_free_client(client_t * client)
break;
default:
- snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", client->number, client->type);
+ snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n",
+ client->number, client->type);
}
up(&register_mutex);
@@ -292,8 +319,8 @@ static void seq_free_client(client_t * client)
static int snd_seq_open(struct inode *inode, struct file *file)
{
int c, mode; /* client id */
- client_t *client;
- user_client_t *user;
+ struct snd_seq_client *client;
+ struct snd_seq_user_client *user;
if (down_interruptible(&register_mutex))
return -ERESTARTSYS;
@@ -344,7 +371,7 @@ static int snd_seq_open(struct inode *inode, struct file *file)
/* delete a user client */
static int snd_seq_release(struct inode *inode, struct file *file)
{
- client_t *client = (client_t *) file->private_data;
+ struct snd_seq_client *client = file->private_data;
if (client) {
seq_free_client(client);
@@ -364,13 +391,14 @@ static int snd_seq_release(struct inode *inode, struct file *file)
* -EINVAL no enough user-space buffer to write the whole event
* -EFAULT seg. fault during copy to user space
*/
-static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
+ loff_t *offset)
{
- client_t *client = (client_t *) file->private_data;
- fifo_t *fifo;
+ struct snd_seq_client *client = file->private_data;
+ struct snd_seq_fifo *fifo;
int err;
long result = 0;
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT))
return -ENXIO;
@@ -396,7 +424,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
snd_seq_fifo_lock(fifo);
/* while data available in queue */
- while (count >= sizeof(snd_seq_event_t)) {
+ while (count >= sizeof(struct snd_seq_event)) {
int nonblock;
nonblock = (file->f_flags & O_NONBLOCK) || result > 0;
@@ -404,34 +432,34 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
break;
}
if (snd_seq_ev_is_variable(&cell->event)) {
- snd_seq_event_t tmpev;
+ struct snd_seq_event tmpev;
tmpev = cell->event;
tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK;
- if (copy_to_user(buf, &tmpev, sizeof(snd_seq_event_t))) {
+ if (copy_to_user(buf, &tmpev, sizeof(struct snd_seq_event))) {
err = -EFAULT;
break;
}
- count -= sizeof(snd_seq_event_t);
- buf += sizeof(snd_seq_event_t);
+ count -= sizeof(struct snd_seq_event);
+ buf += sizeof(struct snd_seq_event);
err = snd_seq_expand_var_event(&cell->event, count,
(char __force *)buf, 0,
- sizeof(snd_seq_event_t));
+ sizeof(struct snd_seq_event));
if (err < 0)
break;
result += err;
count -= err;
buf += err;
} else {
- if (copy_to_user(buf, &cell->event, sizeof(snd_seq_event_t))) {
+ if (copy_to_user(buf, &cell->event, sizeof(struct snd_seq_event))) {
err = -EFAULT;
break;
}
- count -= sizeof(snd_seq_event_t);
- buf += sizeof(snd_seq_event_t);
+ count -= sizeof(struct snd_seq_event);
+ buf += sizeof(struct snd_seq_event);
}
snd_seq_cell_free(cell);
cell = NULL; /* to be sure */
- result += sizeof(snd_seq_event_t);
+ result += sizeof(struct snd_seq_event);
}
if (err < 0) {
@@ -449,7 +477,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count, l
/*
* check access permission to the port
*/
-static int check_port_perm(client_port_t *port, unsigned int flags)
+static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)
{
if ((port->capability & flags) != flags)
return 0;
@@ -460,9 +488,10 @@ static int check_port_perm(client_port_t *port, unsigned int flags)
* check if the destination client is available, and return the pointer
* if filter is non-zero, client filter bitmap is tested.
*/
-static client_t *get_event_dest_client(snd_seq_event_t *event, int filter)
+static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event,
+ int filter)
{
- client_t *dest;
+ struct snd_seq_client *dest;
dest = snd_seq_client_use_ptr(event->dest.client);
if (dest == NULL)
@@ -493,10 +522,11 @@ __not_avail:
* quoted in SNDRV_SEQ_EVENT_KERNEL_ERROR, since this requires no extra
* kmalloc.
*/
-static int bounce_error_event(client_t *client, snd_seq_event_t *event,
+static int bounce_error_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
int err, int atomic, int hop)
{
- snd_seq_event_t bounce_ev;
+ struct snd_seq_event bounce_ev;
int result;
if (client == NULL ||
@@ -531,9 +561,10 @@ static int bounce_error_event(client_t *client, snd_seq_event_t *event,
* of the given queue.
* return non-zero if updated.
*/
-static int update_timestamp_of_queue(snd_seq_event_t *event, int queue, int real_time)
+static int update_timestamp_of_queue(struct snd_seq_event *event,
+ int queue, int real_time)
{
- queue_t *q;
+ struct snd_seq_queue *q;
q = queueptr(queue);
if (! q)
@@ -559,12 +590,12 @@ static int update_timestamp_of_queue(snd_seq_event_t *event, int queue, int real
* RETURN VALUE: 0 : if succeeded
* <0 : error
*/
-static int snd_seq_deliver_single_event(client_t *client,
- snd_seq_event_t *event,
+static int snd_seq_deliver_single_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
int filter, int atomic, int hop)
{
- client_t *dest = NULL;
- client_port_t *dest_port = NULL;
+ struct snd_seq_client *dest = NULL;
+ struct snd_seq_client_port *dest_port = NULL;
int result = -ENOENT;
int direct;
@@ -596,7 +627,9 @@ static int snd_seq_deliver_single_event(client_t *client,
case KERNEL_CLIENT:
if (dest_port->event_input == NULL)
break;
- result = dest_port->event_input(event, direct, dest_port->private_data, atomic, hop);
+ result = dest_port->event_input(event, direct,
+ dest_port->private_data,
+ atomic, hop);
break;
default:
break;
@@ -618,16 +651,16 @@ static int snd_seq_deliver_single_event(client_t *client,
/*
* send the event to all subscribers:
*/
-static int deliver_to_subscribers(client_t *client,
- snd_seq_event_t *event,
+static int deliver_to_subscribers(struct snd_seq_client *client,
+ struct snd_seq_event *event,
int atomic, int hop)
{
- subscribers_t *subs;
+ struct snd_seq_subscribers *subs;
int err = 0, num_ev = 0;
- snd_seq_event_t event_saved;
- client_port_t *src_port;
+ struct snd_seq_event event_saved;
+ struct snd_seq_client_port *src_port;
struct list_head *p;
- port_subs_info_t *grp;
+ struct snd_seq_port_subs_info *grp;
src_port = snd_seq_port_use_ptr(client, event->source.port);
if (src_port == NULL)
@@ -642,7 +675,7 @@ static int deliver_to_subscribers(client_t *client,
else
down_read(&grp->list_mutex);
list_for_each(p, &grp->list_head) {
- subs = list_entry(p, subscribers_t, src_list);
+ subs = list_entry(p, struct snd_seq_subscribers, src_list);
event->dest = subs->info.dest;
if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
/* convert time according to flag with subscription */
@@ -670,12 +703,12 @@ static int deliver_to_subscribers(client_t *client,
/*
* broadcast to all ports:
*/
-static int port_broadcast_event(client_t *client,
- snd_seq_event_t *event,
+static int port_broadcast_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
int atomic, int hop)
{
int num_ev = 0, err = 0;
- client_t *dest_client;
+ struct snd_seq_client *dest_client;
struct list_head *p;
dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST);
@@ -684,7 +717,7 @@ static int port_broadcast_event(client_t *client,
read_lock(&dest_client->ports_lock);
list_for_each(p, &dest_client->ports_list_head) {
- client_port_t *port = list_entry(p, client_port_t, list);
+ struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list);
event->dest.port = port->addr.port;
/* pass NULL as source client to avoid error bounce */
err = snd_seq_deliver_single_event(NULL, event,
@@ -704,12 +737,12 @@ static int port_broadcast_event(client_t *client,
* send the event to all clients:
* if destination port is also ADDRESS_BROADCAST, deliver to all ports.
*/
-static int broadcast_event(client_t *client,
- snd_seq_event_t *event, int atomic, int hop)
+static int broadcast_event(struct snd_seq_client *client,
+ struct snd_seq_event *event, int atomic, int hop)
{
int err = 0, num_ev = 0;
int dest;
- snd_seq_addr_t addr;
+ struct snd_seq_addr addr;
addr = event->dest; /* save */
@@ -736,7 +769,7 @@ static int broadcast_event(client_t *client,
/* multicast - not supported yet */
-static int multicast_event(client_t *client, snd_seq_event_t *event,
+static int multicast_event(struct snd_seq_client *client, struct snd_seq_event *event,
int atomic, int hop)
{
snd_printd("seq: multicast not supported yet.\n");
@@ -753,7 +786,7 @@ static int multicast_event(client_t *client, snd_seq_event_t *event,
* n == 0 : the event was not passed to any client.
* n < 0 : error - event was not processed.
*/
-static int snd_seq_deliver_event(client_t *client, snd_seq_event_t *event,
+static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_event *event,
int atomic, int hop)
{
int result;
@@ -794,9 +827,9 @@ static int snd_seq_deliver_event(client_t *client, snd_seq_event_t *event,
* n == 0 : the event was not passed to any client.
* n < 0 : error - event was not processed.
*/
-int snd_seq_dispatch_event(snd_seq_event_cell_t *cell, int atomic, int hop)
+int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
- client_t *client;
+ struct snd_seq_client *client;
int result;
snd_assert(cell != NULL, return -EINVAL);
@@ -812,7 +845,7 @@ int snd_seq_dispatch_event(snd_seq_event_cell_t *cell, int atomic, int hop)
* the event cell is re-used as a NOTE-OFF event and
* enqueued again.
*/
- snd_seq_event_t tmpev, *ev;
+ struct snd_seq_event tmpev, *ev;
/* reserve this event to enqueue note-off later */
tmpev = cell->event;
@@ -865,12 +898,12 @@ int snd_seq_dispatch_event(snd_seq_event_cell_t *cell, int atomic, int hop)
* if pool is empty and blocking is TRUE, sleep until a new cell is
* available.
*/
-static int snd_seq_client_enqueue_event(client_t *client,
- snd_seq_event_t *event,
+static int snd_seq_client_enqueue_event(struct snd_seq_client *client,
+ struct snd_seq_event *event,
struct file *file, int blocking,
int atomic, int hop)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
int err;
/* special queue values - force direct passing */
@@ -886,7 +919,7 @@ static int snd_seq_client_enqueue_event(client_t *client,
#endif
if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {
/* check presence of source port */
- client_port_t *src_port = snd_seq_port_use_ptr(client, event->source.port);
+ struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port);
if (src_port == NULL)
return -EINVAL;
snd_seq_port_unlock(src_port);
@@ -924,7 +957,7 @@ static int snd_seq_client_enqueue_event(client_t *client,
* check validity of event type and data length.
* return non-zero if invalid.
*/
-static int check_event_type_and_length(snd_seq_event_t *ev)
+static int check_event_type_and_length(struct snd_seq_event *ev)
{
switch (snd_seq_ev_length_type(ev)) {
case SNDRV_SEQ_EVENT_LENGTH_FIXED:
@@ -957,12 +990,13 @@ static int check_event_type_and_length(snd_seq_event_t *ev)
* -EMLINK too many hops
* others depends on return value from driver callback
*/
-static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
+static ssize_t snd_seq_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
{
- client_t *client = (client_t *) file->private_data;
+ struct snd_seq_client *client = file->private_data;
int written = 0, len;
int err = -EINVAL;
- snd_seq_event_t event;
+ struct snd_seq_event event;
if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT))
return -ENXIO;
@@ -980,7 +1014,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c
}
/* only process whole events */
- while (count >= sizeof(snd_seq_event_t)) {
+ while (count >= sizeof(struct snd_seq_event)) {
/* Read in the event header from the user */
len = sizeof(event);
if (copy_from_user(&event, buf, len)) {
@@ -1012,7 +1046,7 @@ 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 __force *)buf
- + sizeof(snd_seq_event_t);
+ + sizeof(struct snd_seq_event);
len += extlen; /* increment data length */
} else {
#ifdef CONFIG_COMPAT
@@ -1046,7 +1080,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, size_t c
*/
static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
{
- client_t *client = (client_t *) file->private_data;
+ struct snd_seq_client *client = file->private_data;
unsigned int mask = 0;
/* check client structures are in place */
@@ -1076,9 +1110,9 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
/* SYSTEM_INFO ioctl() */
-static int snd_seq_ioctl_system_info(client_t *client, void __user *arg)
+static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg)
{
- snd_seq_system_info_t info;
+ struct snd_seq_system_info info;
memset(&info, 0, sizeof(info));
/* fill the info fields */
@@ -1096,10 +1130,10 @@ static int snd_seq_ioctl_system_info(client_t *client, void __user *arg)
/* RUNNING_MODE ioctl() */
-static int snd_seq_ioctl_running_mode(client_t *client, void __user *arg)
+static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg)
{
- struct sndrv_seq_running_info info;
- client_t *cptr;
+ struct snd_seq_running_info info;
+ struct snd_seq_client *cptr;
int err = 0;
if (copy_from_user(&info, arg, sizeof(info)))
@@ -1133,7 +1167,8 @@ static int snd_seq_ioctl_running_mode(client_t *client, void __user *arg)
}
/* CLIENT_INFO ioctl() */
-static void get_client_info(client_t *cptr, snd_seq_client_info_t *info)
+static void get_client_info(struct snd_seq_client *cptr,
+ struct snd_seq_client_info *info)
{
info->client = cptr->number;
@@ -1147,10 +1182,11 @@ static void get_client_info(client_t *cptr, snd_seq_client_info_t *info)
memset(info->reserved, 0, sizeof(info->reserved));
}
-static int snd_seq_ioctl_get_client_info(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
+ void __user *arg)
{
- client_t *cptr;
- snd_seq_client_info_t client_info;
+ struct snd_seq_client *cptr;
+ struct snd_seq_client_info client_info;
if (copy_from_user(&client_info, arg, sizeof(client_info)))
return -EFAULT;
@@ -1170,9 +1206,10 @@ static int snd_seq_ioctl_get_client_info(client_t * client, void __user *arg)
/* CLIENT_INFO ioctl() */
-static int snd_seq_ioctl_set_client_info(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_client_info_t client_info;
+ struct snd_seq_client_info client_info;
if (copy_from_user(&client_info, arg, sizeof(client_info)))
return -EFAULT;
@@ -1199,11 +1236,12 @@ static int snd_seq_ioctl_set_client_info(client_t * client, void __user *arg)
/*
* CREATE PORT ioctl()
*/
-static int snd_seq_ioctl_create_port(client_t * client, void __user *arg)
+static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
+ void __user *arg)
{
- client_port_t *port;
- snd_seq_port_info_t info;
- snd_seq_port_callback_t *callback;
+ struct snd_seq_client_port *port;
+ struct snd_seq_port_info info;
+ struct snd_seq_port_callback *callback;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1249,9 +1287,10 @@ static int snd_seq_ioctl_create_port(client_t * client, void __user *arg)
/*
* DELETE PORT ioctl()
*/
-static int snd_seq_ioctl_delete_port(client_t * client, void __user *arg)
+static int snd_seq_ioctl_delete_port(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_port_info_t info;
+ struct snd_seq_port_info info;
int err;
/* set passed parameters */
@@ -1272,11 +1311,12 @@ static int snd_seq_ioctl_delete_port(client_t * client, void __user *arg)
/*
* GET_PORT_INFO ioctl() (on any client)
*/
-static int snd_seq_ioctl_get_port_info(client_t *client, void __user *arg)
+static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client,
+ void __user *arg)
{
- client_t *cptr;
- client_port_t *port;
- snd_seq_port_info_t info;
+ struct snd_seq_client *cptr;
+ struct snd_seq_client_port *port;
+ struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1304,10 +1344,11 @@ static int snd_seq_ioctl_get_port_info(client_t *client, void __user *arg)
/*
* SET_PORT_INFO ioctl() (only ports on this/own client)
*/
-static int snd_seq_ioctl_set_port_info(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client,
+ void __user *arg)
{
- client_port_t *port;
- snd_seq_port_info_t info;
+ struct snd_seq_client_port *port;
+ struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1329,9 +1370,10 @@ static int snd_seq_ioctl_set_port_info(client_t * client, void __user *arg)
#define PERM_RD (SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)
#define PERM_WR (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)
-static int check_subscription_permission(client_t *client, client_port_t *sport,
- client_port_t *dport,
- snd_seq_port_subscribe_t *subs)
+static int check_subscription_permission(struct snd_seq_client *client,
+ struct snd_seq_client_port *sport,
+ struct snd_seq_client_port *dport,
+ struct snd_seq_port_subscribe *subs)
{
if (client->number != subs->sender.client &&
client->number != subs->dest.client) {
@@ -1363,9 +1405,10 @@ static int check_subscription_permission(client_t *client, client_port_t *sport,
* client must be user client.
*/
int snd_seq_client_notify_subscription(int client, int port,
- snd_seq_port_subscribe_t *info, int evtype)
+ struct snd_seq_port_subscribe *info,
+ int evtype)
{
- snd_seq_event_t event;
+ struct snd_seq_event event;
memset(&event, 0, sizeof(event));
event.type = evtype;
@@ -1379,12 +1422,13 @@ int snd_seq_client_notify_subscription(int client, int port,
/*
* add to port's subscription list IOCTL interface
*/
-static int snd_seq_ioctl_subscribe_port(client_t * client, void __user *arg)
+static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
+ void __user *arg)
{
int result = -EINVAL;
- client_t *receiver = NULL, *sender = NULL;
- client_port_t *sport = NULL, *dport = NULL;
- snd_seq_port_subscribe_t subs;
+ struct snd_seq_client *receiver = NULL, *sender = NULL;
+ struct snd_seq_client_port *sport = NULL, *dport = NULL;
+ struct snd_seq_port_subscribe subs;
if (copy_from_user(&subs, arg, sizeof(subs)))
return -EFAULT;
@@ -1423,12 +1467,13 @@ static int snd_seq_ioctl_subscribe_port(client_t * client, void __user *arg)
/*
* remove from port's subscription list
*/
-static int snd_seq_ioctl_unsubscribe_port(client_t * client, void __user *arg)
+static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
+ void __user *arg)
{
int result = -ENXIO;
- client_t *receiver = NULL, *sender = NULL;
- client_port_t *sport = NULL, *dport = NULL;
- snd_seq_port_subscribe_t subs;
+ struct snd_seq_client *receiver = NULL, *sender = NULL;
+ struct snd_seq_client_port *sport = NULL, *dport = NULL;
+ struct snd_seq_port_subscribe subs;
if (copy_from_user(&subs, arg, sizeof(subs)))
return -EFAULT;
@@ -1464,11 +1509,12 @@ static int snd_seq_ioctl_unsubscribe_port(client_t * client, void __user *arg)
/* CREATE_QUEUE ioctl() */
-static int snd_seq_ioctl_create_queue(client_t *client, void __user *arg)
+static int snd_seq_ioctl_create_queue(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_info_t info;
+ struct snd_seq_queue_info info;
int result;
- queue_t *q;
+ struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1498,9 +1544,10 @@ static int snd_seq_ioctl_create_queue(client_t *client, void __user *arg)
}
/* DELETE_QUEUE ioctl() */
-static int snd_seq_ioctl_delete_queue(client_t *client, void __user *arg)
+static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_info_t info;
+ struct snd_seq_queue_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1509,10 +1556,11 @@ static int snd_seq_ioctl_delete_queue(client_t *client, void __user *arg)
}
/* GET_QUEUE_INFO ioctl() */
-static int snd_seq_ioctl_get_queue_info(client_t *client, void __user *arg)
+static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_info_t info;
- queue_t *q;
+ struct snd_seq_queue_info info;
+ struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1535,10 +1583,11 @@ static int snd_seq_ioctl_get_queue_info(client_t *client, void __user *arg)
}
/* SET_QUEUE_INFO ioctl() */
-static int snd_seq_ioctl_set_queue_info(client_t *client, void __user *arg)
+static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_info_t info;
- queue_t *q;
+ struct snd_seq_queue_info info;
+ struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1570,10 +1619,10 @@ static int snd_seq_ioctl_set_queue_info(client_t *client, void __user *arg)
}
/* GET_NAMED_QUEUE ioctl() */
-static int snd_seq_ioctl_get_named_queue(client_t *client, void __user *arg)
+static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg)
{
- snd_seq_queue_info_t info;
- queue_t *q;
+ struct snd_seq_queue_info info;
+ struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1593,11 +1642,12 @@ static int snd_seq_ioctl_get_named_queue(client_t *client, void __user *arg)
}
/* GET_QUEUE_STATUS ioctl() */
-static int snd_seq_ioctl_get_queue_status(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_status_t status;
- queue_t *queue;
- seq_timer_t *tmr;
+ struct snd_seq_queue_status status;
+ struct snd_seq_queue *queue;
+ struct snd_seq_timer *tmr;
if (copy_from_user(&status, arg, sizeof(status)))
return -EFAULT;
@@ -1626,11 +1676,12 @@ static int snd_seq_ioctl_get_queue_status(client_t * client, void __user *arg)
/* GET_QUEUE_TEMPO ioctl() */
-static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_tempo_t tempo;
- queue_t *queue;
- seq_timer_t *tmr;
+ struct snd_seq_queue_tempo tempo;
+ struct snd_seq_queue *queue;
+ struct snd_seq_timer *tmr;
if (copy_from_user(&tempo, arg, sizeof(tempo)))
return -EFAULT;
@@ -1656,17 +1707,18 @@ static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg)
/* SET_QUEUE_TEMPO ioctl() */
-int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo)
+int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
{
if (!snd_seq_queue_check_access(tempo->queue, client))
return -EPERM;
return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
}
-static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
+ void __user *arg)
{
int result;
- snd_seq_queue_tempo_t tempo;
+ struct snd_seq_queue_tempo tempo;
if (copy_from_user(&tempo, arg, sizeof(tempo)))
return -EFAULT;
@@ -1677,11 +1729,12 @@ static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
/* GET_QUEUE_TIMER ioctl() */
-static int snd_seq_ioctl_get_queue_timer(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_timer_t timer;
- queue_t *queue;
- seq_timer_t *tmr;
+ struct snd_seq_queue_timer timer;
+ struct snd_seq_queue *queue;
+ struct snd_seq_timer *tmr;
if (copy_from_user(&timer, arg, sizeof(timer)))
return -EFAULT;
@@ -1713,10 +1766,11 @@ static int snd_seq_ioctl_get_queue_timer(client_t * client, void __user *arg)
/* SET_QUEUE_TIMER ioctl() */
-static int snd_seq_ioctl_set_queue_timer(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
+ void __user *arg)
{
int result = 0;
- snd_seq_queue_timer_t timer;
+ struct snd_seq_queue_timer timer;
if (copy_from_user(&timer, arg, sizeof(timer)))
return -EFAULT;
@@ -1725,8 +1779,8 @@ static int snd_seq_ioctl_set_queue_timer(client_t * client, void __user *arg)
return -EINVAL;
if (snd_seq_queue_check_access(timer.queue, client->number)) {
- queue_t *q;
- seq_timer_t *tmr;
+ struct snd_seq_queue *q;
+ struct snd_seq_timer *tmr;
q = queueptr(timer.queue);
if (q == NULL)
@@ -1754,9 +1808,10 @@ static int snd_seq_ioctl_set_queue_timer(client_t * client, void __user *arg)
/* GET_QUEUE_CLIENT ioctl() */
-static int snd_seq_ioctl_get_queue_client(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_queue_client_t info;
+ struct snd_seq_queue_client info;
int used;
if (copy_from_user(&info, arg, sizeof(info)))
@@ -1775,10 +1830,11 @@ static int snd_seq_ioctl_get_queue_client(client_t * client, void __user *arg)
/* SET_QUEUE_CLIENT ioctl() */
-static int snd_seq_ioctl_set_queue_client(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
+ void __user *arg)
{
int err;
- snd_seq_queue_client_t info;
+ struct snd_seq_queue_client info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1794,10 +1850,11 @@ static int snd_seq_ioctl_set_queue_client(client_t * client, void __user *arg)
/* GET_CLIENT_POOL ioctl() */
-static int snd_seq_ioctl_get_client_pool(client_t * client, void __user *arg)
+static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_client_pool_t info;
- client_t *cptr;
+ struct snd_seq_client_pool info;
+ struct snd_seq_client *cptr;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1828,9 +1885,10 @@ static int snd_seq_ioctl_get_client_pool(client_t * client, void __user *arg)
}
/* SET_CLIENT_POOL ioctl() */
-static int snd_seq_ioctl_set_client_pool(client_t * client, void __user *arg)
+static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_client_pool_t info;
+ struct snd_seq_client_pool info;
int rc;
if (copy_from_user(&info, arg, sizeof(info)))
@@ -1872,9 +1930,10 @@ static int snd_seq_ioctl_set_client_pool(client_t * client, void __user *arg)
/* REMOVE_EVENTS ioctl() */
-static int snd_seq_ioctl_remove_events(client_t * client, void __user *arg)
+static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
+ void __user *arg)
{
- snd_seq_remove_events_t info;
+ struct snd_seq_remove_events info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1901,13 +1960,14 @@ static int snd_seq_ioctl_remove_events(client_t * client, void __user *arg)
/*
* get subscription info
*/
-static int snd_seq_ioctl_get_subscription(client_t *client, void __user *arg)
+static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
+ void __user *arg)
{
int result;
- client_t *sender = NULL;
- client_port_t *sport = NULL;
- snd_seq_port_subscribe_t subs;
- subscribers_t *p;
+ struct snd_seq_client *sender = NULL;
+ struct snd_seq_client_port *sport = NULL;
+ struct snd_seq_port_subscribe subs;
+ struct snd_seq_subscribers *p;
if (copy_from_user(&subs, arg, sizeof(subs)))
return -EFAULT;
@@ -1940,13 +2000,14 @@ static int snd_seq_ioctl_get_subscription(client_t *client, void __user *arg)
/*
* get subscription info - check only its presence
*/
-static int snd_seq_ioctl_query_subs(client_t *client, void __user *arg)
+static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
+ void __user *arg)
{
int result = -ENXIO;
- client_t *cptr = NULL;
- client_port_t *port = NULL;
- snd_seq_query_subs_t subs;
- port_subs_info_t *group;
+ struct snd_seq_client *cptr = NULL;
+ struct snd_seq_client_port *port = NULL;
+ struct snd_seq_query_subs subs;
+ struct snd_seq_port_subs_info *group;
struct list_head *p;
int i;
@@ -1977,12 +2038,12 @@ static int snd_seq_ioctl_query_subs(client_t *client, void __user *arg)
list_for_each(p, &group->list_head) {
if (i++ == subs.index) {
/* found! */
- subscribers_t *s;
+ struct snd_seq_subscribers *s;
if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) {
- s = list_entry(p, subscribers_t, src_list);
+ s = list_entry(p, struct snd_seq_subscribers, src_list);
subs.addr = s->info.dest;
} else {
- s = list_entry(p, subscribers_t, dest_list);
+ s = list_entry(p, struct snd_seq_subscribers, dest_list);
subs.addr = s->info.sender;
}
subs.flags = s->info.flags;
@@ -2009,10 +2070,11 @@ static int snd_seq_ioctl_query_subs(client_t *client, void __user *arg)
/*
* query next client
*/
-static int snd_seq_ioctl_query_next_client(client_t *client, void __user *arg)
+static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
+ void __user *arg)
{
- client_t *cptr = NULL;
- snd_seq_client_info_t info;
+ struct snd_seq_client *cptr = NULL;
+ struct snd_seq_client_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -2040,11 +2102,12 @@ static int snd_seq_ioctl_query_next_client(client_t *client, void __user *arg)
/*
* query next port
*/
-static int snd_seq_ioctl_query_next_port(client_t *client, void __user *arg)
+static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
+ void __user *arg)
{
- client_t *cptr;
- client_port_t *port = NULL;
- snd_seq_port_info_t info;
+ struct snd_seq_client *cptr;
+ struct snd_seq_client_port *port = NULL;
+ struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -2075,7 +2138,7 @@ static int snd_seq_ioctl_query_next_port(client_t *client, void __user *arg)
static struct seq_ioctl_table {
unsigned int cmd;
- int (*func)(client_t *client, void __user * arg);
+ int (*func)(struct snd_seq_client *client, void __user * arg);
} ioctl_tables[] = {
{ SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info },
{ SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },
@@ -2109,7 +2172,8 @@ static struct seq_ioctl_table {
{ 0, NULL },
};
-static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, void __user *arg)
+static int snd_seq_do_ioctl(struct snd_seq_client *client, unsigned int cmd,
+ void __user *arg)
{
struct seq_ioctl_table *p;
@@ -2136,7 +2200,7 @@ static int snd_seq_do_ioctl(client_t *client, unsigned int cmd, void __user *arg
static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- client_t *client = (client_t *) file->private_data;
+ struct snd_seq_client *client = file->private_data;
snd_assert(client != NULL, return -ENXIO);
@@ -2153,23 +2217,29 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg
/* exported to kernel modules */
-int snd_seq_create_kernel_client(snd_card_t *card, int client_index, snd_seq_client_callback_t * callback)
+int snd_seq_create_kernel_client(struct snd_card *card, int client_index,
+ const char *name_fmt, ...)
{
- client_t *client;
+ struct snd_seq_client *client;
+ va_list args;
snd_assert(! in_interrupt(), return -EBUSY);
- if (callback == NULL)
+ if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD)
return -EINVAL;
- if (card && client_index > 7)
+ if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)
return -EINVAL;
- if (card == NULL && client_index > 63)
- return -EINVAL;
- if (card)
- client_index += 64 + (card->number << 3);
if (down_interruptible(&register_mutex))
return -ERESTARTSYS;
+
+ if (card) {
+ client_index += SNDRV_SEQ_GLOBAL_CLIENTS
+ + card->number * SNDRV_SEQ_CLIENTS_PER_CARD;
+ if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN)
+ client_index = -1;
+ }
+
/* empty write queue as default */
client = seq_create_client1(client_index, 0);
if (client == NULL) {
@@ -2178,13 +2248,12 @@ int snd_seq_create_kernel_client(snd_card_t *card, int client_index, snd_seq_cli
}
usage_alloc(&client_usage, 1);
- client->accept_input = callback->allow_output;
- client->accept_output = callback->allow_input;
+ client->accept_input = 1;
+ client->accept_output = 1;
- /* fill client data */
- client->data.kernel.card = card;
- client->data.kernel.private_data = callback->private_data;
- sprintf(client->name, "Client-%d", client->number);
+ va_start(args, name_fmt);
+ vsnprintf(client->name, sizeof(client->name), name_fmt, args);
+ va_end(args);
client->type = KERNEL_CLIENT;
up(&register_mutex);
@@ -2199,7 +2268,7 @@ int snd_seq_create_kernel_client(snd_card_t *card, int client_index, snd_seq_cli
/* exported to kernel modules */
int snd_seq_delete_kernel_client(int client)
{
- client_t *ptr;
+ struct snd_seq_client *ptr;
snd_assert(! in_interrupt(), return -EBUSY);
@@ -2216,11 +2285,11 @@ int snd_seq_delete_kernel_client(int client)
/* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
* and snd_seq_kernel_client_enqueue_blocking
*/
-static int kernel_client_enqueue(int client, snd_seq_event_t *ev,
+static int kernel_client_enqueue(int client, struct snd_seq_event *ev,
struct file *file, int blocking,
int atomic, int hop)
{
- client_t *cptr;
+ struct snd_seq_client *cptr;
int result;
snd_assert(ev != NULL, return -EINVAL);
@@ -2254,7 +2323,7 @@ static int kernel_client_enqueue(int client, snd_seq_event_t *ev,
*
* RETURN VALUE: zero if succeed, negative if error
*/
-int snd_seq_kernel_client_enqueue(int client, snd_seq_event_t * ev,
+int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev,
int atomic, int hop)
{
return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
@@ -2265,7 +2334,7 @@ int snd_seq_kernel_client_enqueue(int client, snd_seq_event_t * ev,
*
* RETURN VALUE: zero if succeed, negative if error
*/
-int snd_seq_kernel_client_enqueue_blocking(int client, snd_seq_event_t * ev,
+int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
struct file *file,
int atomic, int hop)
{
@@ -2280,10 +2349,10 @@ int snd_seq_kernel_client_enqueue_blocking(int client, snd_seq_event_t * ev,
* RETURN VALUE: negative = delivery failed,
* zero, or positive: the number of delivered events
*/
-int snd_seq_kernel_client_dispatch(int client, snd_seq_event_t * ev,
+int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,
int atomic, int hop)
{
- client_t *cptr;
+ struct snd_seq_client *cptr;
int result;
snd_assert(ev != NULL, return -EINVAL);
@@ -2315,7 +2384,7 @@ int snd_seq_kernel_client_dispatch(int client, snd_seq_event_t * ev,
*/
int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
{
- client_t *client;
+ struct snd_seq_client *client;
mm_segment_t fs;
int result;
@@ -2332,7 +2401,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
/* exported (for OSS emulator) */
int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)
{
- client_t *client;
+ struct snd_seq_client *client;
client = clientptr(clientid);
if (client == NULL)
@@ -2347,13 +2416,16 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table
/*---------------------------------------------------------------------------*/
+#ifdef CONFIG_PROC_FS
/*
* /proc interface
*/
-static void snd_seq_info_dump_subscribers(snd_info_buffer_t *buffer, port_subs_info_t *group, int is_src, char *msg)
+static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
+ struct snd_seq_port_subs_info *group,
+ int is_src, char *msg)
{
struct list_head *p;
- subscribers_t *s;
+ struct snd_seq_subscribers *s;
int count = 0;
down_read(&group->list_mutex);
@@ -2364,9 +2436,9 @@ static void snd_seq_info_dump_subscribers(snd_info_buffer_t *buffer, port_subs_i
snd_iprintf(buffer, msg);
list_for_each(p, &group->list_head) {
if (is_src)
- s = list_entry(p, subscribers_t, src_list);
+ s = list_entry(p, struct snd_seq_subscribers, src_list);
else
- s = list_entry(p, subscribers_t, dest_list);
+ s = list_entry(p, struct snd_seq_subscribers, dest_list);
if (count++)
snd_iprintf(buffer, ", ");
snd_iprintf(buffer, "%d:%d",
@@ -2387,13 +2459,14 @@ static void snd_seq_info_dump_subscribers(snd_info_buffer_t *buffer, port_subs_i
#define FLAG_PERM_DUPLEX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_DUPLEX ? 'X' : '-')
-static void snd_seq_info_dump_ports(snd_info_buffer_t *buffer, client_t *client)
+static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
+ struct snd_seq_client *client)
{
struct list_head *l;
down(&client->ports_mutex);
list_for_each(l, &client->ports_list_head) {
- client_port_t *p = list_entry(l, client_port_t, list);
+ struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n",
p->addr.port, p->name,
FLAG_PERM_RD(p->capability),
@@ -2407,13 +2480,15 @@ static void snd_seq_info_dump_ports(snd_info_buffer_t *buffer, client_t *client)
}
+void snd_seq_info_pool(struct snd_info_buffer *buffer,
+ struct snd_seq_pool *pool, char *space);
+
/* exported to seq_info.c */
-void snd_seq_info_clients_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+void snd_seq_info_clients_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- extern void snd_seq_info_pool(snd_info_buffer_t * buffer, pool_t * pool, char *space);
int c;
- client_t *client;
+ struct snd_seq_client *client;
snd_iprintf(buffer, "Client info\n");
snd_iprintf(buffer, " cur clients : %d\n", client_usage.cur);
@@ -2447,7 +2522,7 @@ void snd_seq_info_clients_read(snd_info_entry_t *entry,
snd_seq_client_unlock(client);
}
}
-
+#endif /* CONFIG_PROC_FS */
/*---------------------------------------------------------------------------*/
@@ -2468,13 +2543,6 @@ static struct file_operations snd_seq_f_ops =
.compat_ioctl = snd_seq_ioctl_compat,
};
-static snd_minor_t snd_seq_reg =
-{
- .comment = "sequencer",
- .f_ops = &snd_seq_f_ops,
-};
-
-
/*
* register sequencer device
*/
@@ -2485,7 +2553,8 @@ int __init snd_sequencer_device_init(void)
if (down_interruptible(&register_mutex))
return -ERESTARTSYS;
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, &snd_seq_reg, "seq")) < 0) {
+ if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
+ &snd_seq_f_ops, NULL, "seq")) < 0) {
up(&register_mutex);
return err;
}
diff --git a/sound/core/seq/seq_clientmgr.h b/sound/core/seq/seq_clientmgr.h
index 3715c36183d3..450091ca153d 100644
--- a/sound/core/seq/seq_clientmgr.h
+++ b/sound/core/seq/seq_clientmgr.h
@@ -30,24 +30,21 @@
/* client manager */
-struct _snd_seq_user_client {
+struct snd_seq_user_client {
struct file *file; /* file struct of client */
/* ... */
/* fifo */
- fifo_t *fifo; /* queue for incoming events */
+ struct snd_seq_fifo *fifo; /* queue for incoming events */
int fifo_pool_size;
};
-struct _snd_seq_kernel_client {
- snd_card_t *card;
- /* pointer to client functions */
- void *private_data; /* private data for client */
+struct snd_seq_kernel_client {
/* ... */
};
-struct _snd_seq_client {
+struct snd_seq_client {
snd_seq_client_type_t type;
unsigned int accept_input: 1,
accept_output: 1;
@@ -65,40 +62,40 @@ struct _snd_seq_client {
int convert32; /* convert 32->64bit */
/* output pool */
- pool_t *pool; /* memory pool for this client */
+ struct snd_seq_pool *pool; /* memory pool for this client */
union {
- user_client_t user;
- kernel_client_t kernel;
+ struct snd_seq_user_client user;
+ struct snd_seq_kernel_client kernel;
} data;
};
/* usage statistics */
-typedef struct {
+struct snd_seq_usage {
int cur;
int peak;
-} usage_t;
+};
-extern int client_init_data(void);
-extern int snd_sequencer_device_init(void);
-extern void snd_sequencer_device_done(void);
+int client_init_data(void);
+int snd_sequencer_device_init(void);
+void snd_sequencer_device_done(void);
/* get locked pointer to client */
-extern client_t *snd_seq_client_use_ptr(int clientid);
+struct snd_seq_client *snd_seq_client_use_ptr(int clientid);
/* unlock pointer to client */
#define snd_seq_client_unlock(client) snd_use_lock_free(&(client)->use_lock)
/* dispatch event to client(s) */
-extern int snd_seq_dispatch_event(snd_seq_event_cell_t *cell, int atomic, int hop);
+int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop);
/* exported to other modules */
-extern int snd_seq_register_kernel_client(snd_seq_client_callback_t *callback, void *private_data);
-extern int snd_seq_unregister_kernel_client(int client);
-extern int snd_seq_kernel_client_enqueue(int client, snd_seq_event_t *ev, int atomic, int hop);
-int snd_seq_kernel_client_enqueue_blocking(int client, snd_seq_event_t * ev, struct file *file, int atomic, int hop);
+int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev, int atomic, int hop);
+int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev,
+ struct file *file, int atomic, int hop);
int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait);
-int snd_seq_client_notify_subscription(int client, int port, snd_seq_port_subscribe_t *info, int evtype);
+int snd_seq_client_notify_subscription(int client, int port,
+ struct snd_seq_port_subscribe *info, int evtype);
#endif
diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index 902ad8b0c355..9628c06e4eab 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -22,8 +22,8 @@
#include <linux/compat.h>
-struct sndrv_seq_port_info32 {
- struct sndrv_seq_addr addr; /* client/port numbers */
+struct snd_seq_port_info32 {
+ struct snd_seq_addr addr; /* client/port numbers */
char name[64]; /* port name */
u32 capability; /* port capability bits */
@@ -41,11 +41,11 @@ struct sndrv_seq_port_info32 {
char reserved[59]; /* for future use */
};
-static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd,
- struct sndrv_seq_port_info32 __user *data32)
+static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
+ struct snd_seq_port_info32 __user *data32)
{
int err = -EFAULT;
- snd_seq_port_info_t *data;
+ struct snd_seq_port_info *data;
mm_segment_t fs;
data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -80,16 +80,16 @@ static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd,
*/
enum {
- SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32),
- SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32),
- SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32),
- SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32),
- SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32),
+ SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32),
+ SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32),
+ SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32),
+ SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32),
+ SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32),
};
static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
{
- client_t *client = (client_t *) file->private_data;
+ struct snd_seq_client *client = file->private_data;
void __user *argp = compat_ptr(arg);
snd_assert(client != NULL, return -ENXIO);
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 252b52731003..9ece443fba55 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -50,11 +50,6 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("ALSA sequencer device management");
MODULE_LICENSE("GPL");
-/*
- * driver list
- */
-typedef struct ops_list ops_list_t;
-
/* driver state */
#define DRIVER_EMPTY 0
#define DRIVER_LOADED (1<<0)
@@ -68,7 +63,7 @@ struct ops_list {
int argsize; /* argument size */
/* operators */
- snd_seq_dev_ops_t ops;
+ struct snd_seq_dev_ops ops;
/* registred devices */
struct list_head dev_list; /* list of devices */
@@ -83,35 +78,39 @@ struct ops_list {
static LIST_HEAD(opslist);
static int num_ops;
static DECLARE_MUTEX(ops_mutex);
-static snd_info_entry_t *info_entry = NULL;
+#ifdef CONFIG_PROC_FS
+static struct snd_info_entry *info_entry = NULL;
+#endif
/*
* prototypes
*/
-static int snd_seq_device_free(snd_seq_device_t *dev);
-static int snd_seq_device_dev_free(snd_device_t *device);
-static int snd_seq_device_dev_register(snd_device_t *device);
-static int snd_seq_device_dev_disconnect(snd_device_t *device);
-static int snd_seq_device_dev_unregister(snd_device_t *device);
-
-static int init_device(snd_seq_device_t *dev, ops_list_t *ops);
-static int free_device(snd_seq_device_t *dev, ops_list_t *ops);
-static ops_list_t *find_driver(char *id, int create_if_empty);
-static ops_list_t *create_driver(char *id);
-static void unlock_driver(ops_list_t *ops);
+static int snd_seq_device_free(struct snd_seq_device *dev);
+static int snd_seq_device_dev_free(struct snd_device *device);
+static int snd_seq_device_dev_register(struct snd_device *device);
+static int snd_seq_device_dev_disconnect(struct snd_device *device);
+static int snd_seq_device_dev_unregister(struct snd_device *device);
+
+static int init_device(struct snd_seq_device *dev, struct ops_list *ops);
+static int free_device(struct snd_seq_device *dev, struct ops_list *ops);
+static struct ops_list *find_driver(char *id, int create_if_empty);
+static struct ops_list *create_driver(char *id);
+static void unlock_driver(struct ops_list *ops);
static void remove_drivers(void);
/*
* show all drivers and their status
*/
-static void snd_seq_device_info(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+#ifdef CONFIG_PROC_FS
+static void snd_seq_device_info(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct list_head *head;
down(&ops_mutex);
list_for_each(head, &opslist) {
- ops_list_t *ops = list_entry(head, ops_list_t, list);
+ struct ops_list *ops = list_entry(head, struct ops_list, list);
snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
ops->id,
ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
@@ -121,6 +120,7 @@ static void snd_seq_device_info(snd_info_entry_t *entry, snd_info_buffer_t * buf
}
up(&ops_mutex);
}
+#endif
/*
* load all registered drivers (called from seq_clientmgr.c)
@@ -156,7 +156,7 @@ void snd_seq_device_load_drivers(void)
down(&ops_mutex);
list_for_each(head, &opslist) {
- ops_list_t *ops = list_entry(head, ops_list_t, list);
+ struct ops_list *ops = list_entry(head, struct ops_list, list);
if (! (ops->driver & DRIVER_LOADED) &&
! (ops->driver & DRIVER_REQUESTED)) {
ops->used++;
@@ -178,13 +178,13 @@ void snd_seq_device_load_drivers(void)
* id = id of driver
* result = return pointer (NULL allowed if unnecessary)
*/
-int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
- snd_seq_device_t **result)
+int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize,
+ struct snd_seq_device **result)
{
- snd_seq_device_t *dev;
- ops_list_t *ops;
+ struct snd_seq_device *dev;
+ struct ops_list *ops;
int err;
- static snd_device_ops_t dops = {
+ static struct snd_device_ops dops = {
.dev_free = snd_seq_device_dev_free,
.dev_register = snd_seq_device_dev_register,
.dev_disconnect = snd_seq_device_dev_disconnect,
@@ -235,9 +235,9 @@ int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
/*
* free the existing device
*/
-static int snd_seq_device_free(snd_seq_device_t *dev)
+static int snd_seq_device_free(struct snd_seq_device *dev)
{
- ops_list_t *ops;
+ struct ops_list *ops;
snd_assert(dev != NULL, return -EINVAL);
@@ -261,19 +261,19 @@ static int snd_seq_device_free(snd_seq_device_t *dev)
return 0;
}
-static int snd_seq_device_dev_free(snd_device_t *device)
+static int snd_seq_device_dev_free(struct snd_device *device)
{
- snd_seq_device_t *dev = device->device_data;
+ struct snd_seq_device *dev = device->device_data;
return snd_seq_device_free(dev);
}
/*
* register the device
*/
-static int snd_seq_device_dev_register(snd_device_t *device)
+static int snd_seq_device_dev_register(struct snd_device *device)
{
- snd_seq_device_t *dev = device->device_data;
- ops_list_t *ops;
+ struct snd_seq_device *dev = device->device_data;
+ struct ops_list *ops;
ops = find_driver(dev->id, 0);
if (ops == NULL)
@@ -292,10 +292,10 @@ static int snd_seq_device_dev_register(snd_device_t *device)
/*
* disconnect the device
*/
-static int snd_seq_device_dev_disconnect(snd_device_t *device)
+static int snd_seq_device_dev_disconnect(struct snd_device *device)
{
- snd_seq_device_t *dev = device->device_data;
- ops_list_t *ops;
+ struct snd_seq_device *dev = device->device_data;
+ struct ops_list *ops;
ops = find_driver(dev->id, 0);
if (ops == NULL)
@@ -310,9 +310,9 @@ static int snd_seq_device_dev_disconnect(snd_device_t *device)
/*
* unregister the existing device
*/
-static int snd_seq_device_dev_unregister(snd_device_t *device)
+static int snd_seq_device_dev_unregister(struct snd_device *device)
{
- snd_seq_device_t *dev = device->device_data;
+ struct snd_seq_device *dev = device->device_data;
return snd_seq_device_free(dev);
}
@@ -321,10 +321,11 @@ static int snd_seq_device_dev_unregister(snd_device_t *device)
* id = driver id
* entry = driver operators - duplicated to each instance
*/
-int snd_seq_device_register_driver(char *id, snd_seq_dev_ops_t *entry, int argsize)
+int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
+ int argsize)
{
struct list_head *head;
- ops_list_t *ops;
+ struct ops_list *ops;
if (id == NULL || entry == NULL ||
entry->init_device == NULL || entry->free_device == NULL)
@@ -351,7 +352,7 @@ int snd_seq_device_register_driver(char *id, snd_seq_dev_ops_t *entry, int argsi
/* initialize existing devices if necessary */
list_for_each(head, &ops->dev_list) {
- snd_seq_device_t *dev = list_entry(head, snd_seq_device_t, list);
+ struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
init_device(dev, ops);
}
up(&ops->reg_mutex);
@@ -366,9 +367,9 @@ int snd_seq_device_register_driver(char *id, snd_seq_dev_ops_t *entry, int argsi
/*
* create driver record
*/
-static ops_list_t * create_driver(char *id)
+static struct ops_list * create_driver(char *id)
{
- ops_list_t *ops;
+ struct ops_list *ops;
ops = kmalloc(sizeof(*ops), GFP_KERNEL);
if (ops == NULL)
@@ -399,14 +400,15 @@ static ops_list_t * create_driver(char *id)
int snd_seq_device_unregister_driver(char *id)
{
struct list_head *head;
- ops_list_t *ops;
+ struct ops_list *ops;
ops = find_driver(id, 0);
if (ops == NULL)
return -ENXIO;
if (! (ops->driver & DRIVER_LOADED) ||
(ops->driver & DRIVER_LOCKED)) {
- snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n", id, ops->driver);
+ snd_printk(KERN_ERR "driver_unregister: cannot unload driver '%s': status=%x\n",
+ id, ops->driver);
unlock_driver(ops);
return -EBUSY;
}
@@ -415,13 +417,14 @@ int snd_seq_device_unregister_driver(char *id)
down(&ops->reg_mutex);
ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
list_for_each(head, &ops->dev_list) {
- snd_seq_device_t *dev = list_entry(head, snd_seq_device_t, list);
+ struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
free_device(dev, ops);
}
ops->driver = 0;
if (ops->num_init_devices > 0)
- snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n", ops->num_init_devices);
+ snd_printk(KERN_ERR "free_driver: init_devices > 0!! (%d)\n",
+ ops->num_init_devices);
up(&ops->reg_mutex);
unlock_driver(ops);
@@ -443,7 +446,7 @@ static void remove_drivers(void)
down(&ops_mutex);
head = opslist.next;
while (head != &opslist) {
- ops_list_t *ops = list_entry(head, ops_list_t, list);
+ struct ops_list *ops = list_entry(head, struct ops_list, list);
if (! (ops->driver & DRIVER_LOADED) &&
ops->used == 0 && ops->num_devices == 0) {
head = head->next;
@@ -459,21 +462,23 @@ static void remove_drivers(void)
/*
* initialize the device - call init_device operator
*/
-static int init_device(snd_seq_device_t *dev, ops_list_t *ops)
+static int init_device(struct snd_seq_device *dev, struct ops_list *ops)
{
if (! (ops->driver & DRIVER_LOADED))
return 0; /* driver is not loaded yet */
if (dev->status != SNDRV_SEQ_DEVICE_FREE)
return 0; /* already initialized */
if (ops->argsize != dev->argsize) {
- snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize);
+ snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
+ dev->name, ops->id, ops->argsize, dev->argsize);
return -EINVAL;
}
if (ops->ops.init_device(dev) >= 0) {
dev->status = SNDRV_SEQ_DEVICE_REGISTERED;
ops->num_init_devices++;
} else {
- snd_printk(KERN_ERR "init_device failed: %s: %s\n", dev->name, dev->id);
+ snd_printk(KERN_ERR "init_device failed: %s: %s\n",
+ dev->name, dev->id);
}
return 0;
@@ -482,7 +487,7 @@ static int init_device(snd_seq_device_t *dev, ops_list_t *ops)
/*
* release the device - call free_device operator
*/
-static int free_device(snd_seq_device_t *dev, ops_list_t *ops)
+static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
{
int result;
@@ -491,7 +496,8 @@ static int free_device(snd_seq_device_t *dev, ops_list_t *ops)
if (dev->status != SNDRV_SEQ_DEVICE_REGISTERED)
return 0; /* not registered */
if (ops->argsize != dev->argsize) {
- snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n", dev->name, ops->id, ops->argsize, dev->argsize);
+ snd_printk(KERN_ERR "incompatible device '%s' for plug-in '%s' (%d %d)\n",
+ dev->name, ops->id, ops->argsize, dev->argsize);
return -EINVAL;
}
if ((result = ops->ops.free_device(dev)) >= 0 || result == -ENXIO) {
@@ -499,7 +505,8 @@ static int free_device(snd_seq_device_t *dev, ops_list_t *ops)
dev->driver_data = NULL;
ops->num_init_devices--;
} else {
- snd_printk(KERN_ERR "free_device failed: %s: %s\n", dev->name, dev->id);
+ snd_printk(KERN_ERR "free_device failed: %s: %s\n",
+ dev->name, dev->id);
}
return 0;
@@ -508,13 +515,13 @@ static int free_device(snd_seq_device_t *dev, ops_list_t *ops)
/*
* find the matching driver with given id
*/
-static ops_list_t * find_driver(char *id, int create_if_empty)
+static struct ops_list * find_driver(char *id, int create_if_empty)
{
struct list_head *head;
down(&ops_mutex);
list_for_each(head, &opslist) {
- ops_list_t *ops = list_entry(head, ops_list_t, list);
+ struct ops_list *ops = list_entry(head, struct ops_list, list);
if (strcmp(ops->id, id) == 0) {
ops->used++;
up(&ops_mutex);
@@ -527,7 +534,7 @@ static ops_list_t * find_driver(char *id, int create_if_empty)
return NULL;
}
-static void unlock_driver(ops_list_t *ops)
+static void unlock_driver(struct ops_list *ops)
{
down(&ops_mutex);
ops->used--;
@@ -541,7 +548,9 @@ static void unlock_driver(ops_list_t *ops)
static int __init alsa_seq_device_init(void)
{
- info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers", snd_seq_root);
+#ifdef CONFIG_PROC_FS
+ info_entry = snd_info_create_module_entry(THIS_MODULE, "drivers",
+ snd_seq_root);
if (info_entry == NULL)
return -ENOMEM;
info_entry->content = SNDRV_INFO_CONTENT_TEXT;
@@ -551,13 +560,16 @@ static int __init alsa_seq_device_init(void)
snd_info_free_entry(info_entry);
return -ENOMEM;
}
+#endif
return 0;
}
static void __exit alsa_seq_device_exit(void)
{
remove_drivers();
+#ifdef CONFIG_PROC_FS
snd_info_unregister(info_entry);
+#endif
if (num_ops)
snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops);
}
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 5dd0e6a19e50..2a283a59ea4d 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -73,12 +73,12 @@ MODULE_PARM_DESC(ports, "number of ports to be created");
module_param(duplex, bool, 0444);
MODULE_PARM_DESC(duplex, "create DUPLEX ports");
-typedef struct snd_seq_dummy_port {
+struct snd_seq_dummy_port {
int client;
int port;
int duplex;
int connect;
-} snd_seq_dummy_port_t;
+};
static int my_client = -1;
@@ -88,11 +88,11 @@ static int my_client = -1;
* Note: this callback is called only after all subscribers are removed.
*/
static int
-dummy_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
- snd_seq_dummy_port_t *p;
+ struct snd_seq_dummy_port *p;
int i;
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
p = private_data;
memset(&ev, 0, sizeof(ev));
@@ -116,10 +116,11 @@ dummy_unuse(void *private_data, snd_seq_port_subscribe_t *info)
* event input callback - just redirect events to subscribers
*/
static int
-dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
+dummy_input(struct snd_seq_event *ev, int direct, void *private_data,
+ int atomic, int hop)
{
- snd_seq_dummy_port_t *p;
- snd_seq_event_t tmpev;
+ struct snd_seq_dummy_port *p;
+ struct snd_seq_event tmpev;
p = private_data;
if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
@@ -146,12 +147,12 @@ dummy_free(void *private_data)
/*
* create a port
*/
-static snd_seq_dummy_port_t __init *
+static struct snd_seq_dummy_port __init *
create_port(int idx, int type)
{
- snd_seq_port_info_t pinfo;
- snd_seq_port_callback_t pcb;
- snd_seq_dummy_port_t *rec;
+ struct snd_seq_port_info pinfo;
+ struct snd_seq_port_callback pcb;
+ struct snd_seq_dummy_port *rec;
if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL)
return NULL;
@@ -192,9 +193,7 @@ create_port(int idx, int type)
static int __init
register_client(void)
{
- snd_seq_client_callback_t cb;
- snd_seq_client_info_t cinfo;
- snd_seq_dummy_port_t *rec1, *rec2;
+ struct snd_seq_dummy_port *rec1, *rec2;
int i;
if (ports < 1) {
@@ -203,20 +202,11 @@ register_client(void)
}
/* create client */
- memset(&cb, 0, sizeof(cb));
- cb.allow_input = 1;
- cb.allow_output = 1;
- my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY, &cb);
+ my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY,
+ "Midi Through");
if (my_client < 0)
return my_client;
- /* set client name */
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = my_client;
- cinfo.type = KERNEL_CLIENT;
- strcpy(cinfo.name, "Midi Through");
- snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
-
/* create ports */
for (i = 0; i < ports; i++) {
rec1 = create_port(i, 0);
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 4767cfdc361f..6b055aed7a4b 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -29,9 +29,9 @@
/* FIFO */
/* create new fifo */
-fifo_t *snd_seq_fifo_new(int poolsize)
+struct snd_seq_fifo *snd_seq_fifo_new(int poolsize)
{
- fifo_t *f;
+ struct snd_seq_fifo *f;
f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
@@ -62,9 +62,9 @@ fifo_t *snd_seq_fifo_new(int poolsize)
return f;
}
-void snd_seq_fifo_delete(fifo_t **fifo)
+void snd_seq_fifo_delete(struct snd_seq_fifo **fifo)
{
- fifo_t *f;
+ struct snd_seq_fifo *f;
snd_assert(fifo != NULL, return);
f = *fifo;
@@ -88,12 +88,12 @@ void snd_seq_fifo_delete(fifo_t **fifo)
kfree(f);
}
-static snd_seq_event_cell_t *fifo_cell_out(fifo_t *f);
+static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f);
/* clear queue */
-void snd_seq_fifo_clear(fifo_t *f)
+void snd_seq_fifo_clear(struct snd_seq_fifo *f)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
unsigned long flags;
/* clear overflow flag */
@@ -110,9 +110,10 @@ void snd_seq_fifo_clear(fifo_t *f)
/* enqueue event to fifo */
-int snd_seq_fifo_event_in(fifo_t *f, snd_seq_event_t *event)
+int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
+ struct snd_seq_event *event)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
unsigned long flags;
int err;
@@ -148,9 +149,9 @@ int snd_seq_fifo_event_in(fifo_t *f, snd_seq_event_t *event)
}
/* dequeue cell from fifo */
-static snd_seq_event_cell_t *fifo_cell_out(fifo_t *f)
+static struct snd_seq_event_cell *fifo_cell_out(struct snd_seq_fifo *f)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
if ((cell = f->head) != NULL) {
f->head = cell->next;
@@ -167,9 +168,10 @@ static snd_seq_event_cell_t *fifo_cell_out(fifo_t *f)
}
/* dequeue cell from fifo and copy on user space */
-int snd_seq_fifo_cell_out(fifo_t *f, snd_seq_event_cell_t **cellp, int nonblock)
+int snd_seq_fifo_cell_out(struct snd_seq_fifo *f,
+ struct snd_seq_event_cell **cellp, int nonblock)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
unsigned long flags;
wait_queue_t wait;
@@ -202,7 +204,8 @@ int snd_seq_fifo_cell_out(fifo_t *f, snd_seq_event_cell_t **cellp, int nonblock)
}
-void snd_seq_fifo_cell_putback(fifo_t *f, snd_seq_event_cell_t *cell)
+void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f,
+ struct snd_seq_event_cell *cell)
{
unsigned long flags;
@@ -217,18 +220,19 @@ void snd_seq_fifo_cell_putback(fifo_t *f, snd_seq_event_cell_t *cell)
/* polling; return non-zero if queue is available */
-int snd_seq_fifo_poll_wait(fifo_t *f, struct file *file, poll_table *wait)
+int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file,
+ poll_table *wait)
{
poll_wait(file, &f->input_sleep, wait);
return (f->cells > 0);
}
/* change the size of pool; all old events are removed */
-int snd_seq_fifo_resize(fifo_t *f, int poolsize)
+int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
{
unsigned long flags;
- pool_t *newpool, *oldpool;
- snd_seq_event_cell_t *cell, *next, *oldhead;
+ struct snd_seq_pool *newpool, *oldpool;
+ struct snd_seq_event_cell *cell, *next, *oldhead;
snd_assert(f != NULL && f->pool != NULL, return -EINVAL);
diff --git a/sound/core/seq/seq_fifo.h b/sound/core/seq/seq_fifo.h
index d677c261b0a4..062c446e7867 100644
--- a/sound/core/seq/seq_fifo.h
+++ b/sound/core/seq/seq_fifo.h
@@ -27,46 +27,46 @@
/* === FIFO === */
-typedef struct {
- pool_t *pool; /* FIFO pool */
- snd_seq_event_cell_t* head; /* pointer to head of fifo */
- snd_seq_event_cell_t* tail; /* pointer to tail of fifo */
+struct snd_seq_fifo {
+ struct snd_seq_pool *pool; /* FIFO pool */
+ struct snd_seq_event_cell *head; /* pointer to head of fifo */
+ struct snd_seq_event_cell *tail; /* pointer to tail of fifo */
int cells;
spinlock_t lock;
snd_use_lock_t use_lock;
wait_queue_head_t input_sleep;
atomic_t overflow;
-} fifo_t;
+};
/* create new fifo (constructor) */
-extern fifo_t *snd_seq_fifo_new(int poolsize);
+struct snd_seq_fifo *snd_seq_fifo_new(int poolsize);
/* delete fifo (destructor) */
-extern void snd_seq_fifo_delete(fifo_t **f);
+void snd_seq_fifo_delete(struct snd_seq_fifo **f);
/* enqueue event to fifo */
-extern int snd_seq_fifo_event_in(fifo_t *f, snd_seq_event_t *event);
+int snd_seq_fifo_event_in(struct snd_seq_fifo *f, struct snd_seq_event *event);
/* lock fifo from release */
#define snd_seq_fifo_lock(fifo) snd_use_lock_use(&(fifo)->use_lock)
#define snd_seq_fifo_unlock(fifo) snd_use_lock_free(&(fifo)->use_lock)
/* get a cell from fifo - fifo should be locked */
-int snd_seq_fifo_cell_out(fifo_t *f, snd_seq_event_cell_t **cellp, int nonblock);
+int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, struct snd_seq_event_cell **cellp, int nonblock);
/* free dequeued cell - fifo should be locked */
-extern void snd_seq_fifo_cell_putback(fifo_t *f, snd_seq_event_cell_t *cell);
+void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f, struct snd_seq_event_cell *cell);
/* clean up queue */
-extern void snd_seq_fifo_clear(fifo_t *f);
+void snd_seq_fifo_clear(struct snd_seq_fifo *f);
/* polling */
-extern int snd_seq_fifo_poll_wait(fifo_t *f, struct file *file, poll_table *wait);
+int snd_seq_fifo_poll_wait(struct snd_seq_fifo *f, struct file *file, poll_table *wait);
/* resize pool in fifo */
-int snd_seq_fifo_resize(fifo_t *f, int poolsize);
+int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize);
#endif
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c
index b50b695c41c4..acce21afdaa4 100644
--- a/sound/core/seq/seq_info.c
+++ b/sound/core/seq/seq_info.c
@@ -27,16 +27,17 @@
#include "seq_clientmgr.h"
#include "seq_timer.h"
+#ifdef CONFIG_PROC_FS
+static struct snd_info_entry *queues_entry;
+static struct snd_info_entry *clients_entry;
+static struct snd_info_entry *timer_entry;
-static snd_info_entry_t *queues_entry;
-static snd_info_entry_t *clients_entry;
-static snd_info_entry_t *timer_entry;
-
-static snd_info_entry_t * __init
-create_info_entry(char *name, int size, void (*read)(snd_info_entry_t *, snd_info_buffer_t *))
+static struct snd_info_entry * __init
+create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *,
+ struct snd_info_buffer *))
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, name, snd_seq_root);
if (entry == NULL)
@@ -51,7 +52,6 @@ create_info_entry(char *name, int size, void (*read)(snd_info_entry_t *, snd_inf
return entry;
}
-
/* create all our /proc entries */
int __init snd_seq_info_init(void)
{
@@ -65,11 +65,9 @@ int __init snd_seq_info_init(void)
int __exit snd_seq_info_done(void)
{
- if (queues_entry)
- snd_info_unregister(queues_entry);
- if (clients_entry)
- snd_info_unregister(clients_entry);
- if (timer_entry)
- snd_info_unregister(timer_entry);
+ snd_info_unregister(queues_entry);
+ snd_info_unregister(clients_entry);
+ snd_info_unregister(timer_entry);
return 0;
}
+#endif
diff --git a/sound/core/seq/seq_info.h b/sound/core/seq/seq_info.h
index efd099a858e4..4892a7f35c08 100644
--- a/sound/core/seq/seq_info.h
+++ b/sound/core/seq/seq_info.h
@@ -24,13 +24,17 @@
#include <sound/info.h>
#include <sound/seq_kernel.h>
-void snd_seq_info_clients_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer);
-void snd_seq_info_timer_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer);
-void snd_seq_info_queues_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer);
+void snd_seq_info_clients_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
+void snd_seq_info_timer_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
+void snd_seq_info_queues_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
+#ifdef CONFIG_PROC_FS
int snd_seq_info_init( void );
int snd_seq_info_done( void );
-
+#else
+static inline int snd_seq_info_init(void) { return 0; }
+static inline int snd_seq_info_done(void) { return 0; }
+#endif
#endif
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index 1d525b13ebb6..487452063965 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument libra
MODULE_LICENSE("GPL");
-static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list)
+static void snd_instr_lock_ops(struct snd_seq_kinstr_list *list)
{
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
spin_lock_irqsave(&list->ops_lock, list->ops_flags);
@@ -40,7 +40,7 @@ static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list)
}
}
-static void snd_instr_unlock_ops(snd_seq_kinstr_list_t *list)
+static void snd_instr_unlock_ops(struct snd_seq_kinstr_list *list)
{
if (!(list->flags & SNDRV_SEQ_INSTR_FLG_DIRECT)) {
spin_unlock_irqrestore(&list->ops_lock, list->ops_flags);
@@ -49,18 +49,18 @@ static void snd_instr_unlock_ops(snd_seq_kinstr_list_t *list)
}
}
-static snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic)
+static struct snd_seq_kinstr *snd_seq_instr_new(int add_len, int atomic)
{
- snd_seq_kinstr_t *instr;
+ struct snd_seq_kinstr *instr;
- instr = kzalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+ instr = kzalloc(sizeof(struct snd_seq_kinstr) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
if (instr == NULL)
return NULL;
instr->add_len = add_len;
return instr;
}
-static int snd_seq_instr_free(snd_seq_kinstr_t *instr, int atomic)
+static int snd_seq_instr_free(struct snd_seq_kinstr *instr, int atomic)
{
int result = 0;
@@ -73,11 +73,11 @@ static int snd_seq_instr_free(snd_seq_kinstr_t *instr, int atomic)
return result;
}
-snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
+struct snd_seq_kinstr_list *snd_seq_instr_list_new(void)
{
- snd_seq_kinstr_list_t *list;
+ struct snd_seq_kinstr_list *list;
- list = kzalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+ list = kzalloc(sizeof(struct snd_seq_kinstr_list), GFP_KERNEL);
if (list == NULL)
return NULL;
spin_lock_init(&list->lock);
@@ -87,11 +87,11 @@ snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
return list;
}
-void snd_seq_instr_list_free(snd_seq_kinstr_list_t **list_ptr)
+void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr)
{
- snd_seq_kinstr_list_t *list;
- snd_seq_kinstr_t *instr;
- snd_seq_kcluster_t *cluster;
+ struct snd_seq_kinstr_list *list;
+ struct snd_seq_kinstr *instr;
+ struct snd_seq_kcluster *cluster;
int idx;
unsigned long flags;
@@ -125,8 +125,8 @@ void snd_seq_instr_list_free(snd_seq_kinstr_list_t **list_ptr)
kfree(list);
}
-static int instr_free_compare(snd_seq_kinstr_t *instr,
- snd_seq_instr_header_t *ifree,
+static int instr_free_compare(struct snd_seq_kinstr *instr,
+ struct snd_seq_instr_header *ifree,
unsigned int client)
{
switch (ifree->cmd) {
@@ -160,12 +160,12 @@ static int instr_free_compare(snd_seq_kinstr_t *instr,
return 1;
}
-int snd_seq_instr_list_free_cond(snd_seq_kinstr_list_t *list,
- snd_seq_instr_header_t *ifree,
+int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list,
+ struct snd_seq_instr_header *ifree,
int client,
int atomic)
{
- snd_seq_kinstr_t *instr, *prev, *next, *flist;
+ struct snd_seq_kinstr *instr, *prev, *next, *flist;
int idx;
unsigned long flags;
@@ -209,7 +209,7 @@ int snd_seq_instr_list_free_cond(snd_seq_kinstr_list_t *list,
return 0;
}
-static int compute_hash_instr_key(snd_seq_instr_t *instr)
+static int compute_hash_instr_key(struct snd_seq_instr *instr)
{
int result;
@@ -233,7 +233,7 @@ static int compute_hash_cluster_key(snd_seq_instr_cluster_t cluster)
}
#endif
-static int compare_instr(snd_seq_instr_t *i1, snd_seq_instr_t *i2, int exact)
+static int compare_instr(struct snd_seq_instr *i1, struct snd_seq_instr *i2, int exact)
{
if (exact) {
if (i1->cluster != i2->cluster ||
@@ -262,14 +262,14 @@ static int compare_instr(snd_seq_instr_t *i1, snd_seq_instr_t *i2, int exact)
}
}
-snd_seq_kinstr_t *snd_seq_instr_find(snd_seq_kinstr_list_t *list,
- snd_seq_instr_t *instr,
- int exact,
- int follow_alias)
+struct snd_seq_kinstr *snd_seq_instr_find(struct snd_seq_kinstr_list *list,
+ struct snd_seq_instr *instr,
+ int exact,
+ int follow_alias)
{
unsigned long flags;
int depth = 0;
- snd_seq_kinstr_t *result;
+ struct snd_seq_kinstr *result;
if (list == NULL || instr == NULL)
return NULL;
@@ -279,7 +279,7 @@ snd_seq_kinstr_t *snd_seq_instr_find(snd_seq_kinstr_list_t *list,
while (result) {
if (!compare_instr(&result->instr, instr, exact)) {
if (follow_alias && (result->type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)) {
- instr = (snd_seq_instr_t *)KINSTR_DATA(result);
+ instr = (struct snd_seq_instr *)KINSTR_DATA(result);
if (++depth > 10)
goto __not_found;
goto __again;
@@ -295,8 +295,8 @@ snd_seq_kinstr_t *snd_seq_instr_find(snd_seq_kinstr_list_t *list,
return NULL;
}
-void snd_seq_instr_free_use(snd_seq_kinstr_list_t *list,
- snd_seq_kinstr_t *instr)
+void snd_seq_instr_free_use(struct snd_seq_kinstr_list *list,
+ struct snd_seq_kinstr *instr)
{
unsigned long flags;
@@ -311,7 +311,8 @@ void snd_seq_instr_free_use(snd_seq_kinstr_list_t *list,
spin_unlock_irqrestore(&list->lock, flags);
}
-static snd_seq_kinstr_ops_t *instr_ops(snd_seq_kinstr_ops_t *ops, char *instr_type)
+static struct snd_seq_kinstr_ops *instr_ops(struct snd_seq_kinstr_ops *ops,
+ char *instr_type)
{
while (ops) {
if (!strcmp(ops->instr_type, instr_type))
@@ -321,11 +322,11 @@ static snd_seq_kinstr_ops_t *instr_ops(snd_seq_kinstr_ops_t *ops, char *instr_ty
return NULL;
}
-static int instr_result(snd_seq_event_t *ev,
+static int instr_result(struct snd_seq_event *ev,
int type, int result,
int atomic)
{
- snd_seq_event_t sev;
+ struct snd_seq_event sev;
memset(&sev, 0, sizeof(sev));
sev.type = SNDRV_SEQ_EVENT_RESULT;
@@ -345,9 +346,9 @@ static int instr_result(snd_seq_event_t *ev,
return snd_seq_kernel_client_dispatch(sev.source.client, &sev, atomic, 0);
}
-static int instr_begin(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_begin(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
unsigned long flags;
@@ -362,9 +363,9 @@ static int instr_begin(snd_seq_kinstr_ops_t *ops,
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_BEGIN, 0, atomic);
}
-static int instr_end(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_end(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
unsigned long flags;
@@ -380,54 +381,55 @@ static int instr_end(snd_seq_kinstr_ops_t *ops,
return instr_result(ev, SNDRV_SEQ_EVENT_INSTR_END, -EINVAL, atomic);
}
-static int instr_info(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_info(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_format_info(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_format_info(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_reset(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_reset(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_status(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_status(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_put(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_put(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
unsigned long flags;
- snd_seq_instr_header_t put;
- snd_seq_kinstr_t *instr;
+ struct snd_seq_instr_header put;
+ struct snd_seq_kinstr *instr;
int result = -EINVAL, len, key;
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
goto __return;
- if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
+ if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
goto __return;
- if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+ if (copy_from_user(&put, (void __user *)ev->data.ext.ptr,
+ sizeof(struct snd_seq_instr_header))) {
result = -EFAULT;
goto __return;
}
@@ -449,7 +451,7 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
}
len = ops->add_len;
if (put.data.type == SNDRV_SEQ_INSTR_ATYPE_ALIAS)
- len = sizeof(snd_seq_instr_t);
+ len = sizeof(struct snd_seq_instr);
instr = snd_seq_instr_new(len, atomic);
if (instr == NULL) {
snd_instr_unlock_ops(list);
@@ -463,8 +465,8 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
result = ops->put(ops->private_data,
instr,
- (void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
- ev->data.ext.len - sizeof(snd_seq_instr_header_t),
+ (void __user *)ev->data.ext.ptr + sizeof(struct snd_seq_instr_header),
+ ev->data.ext.len - sizeof(struct snd_seq_instr_header),
atomic,
put.cmd);
if (result < 0) {
@@ -486,21 +488,21 @@ static int instr_put(snd_seq_kinstr_ops_t *ops,
return result;
}
-static int instr_get(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_get(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_free(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_free(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
- snd_seq_instr_header_t ifree;
- snd_seq_kinstr_t *instr, *prev;
+ struct snd_seq_instr_header ifree;
+ struct snd_seq_kinstr *instr, *prev;
int result = -EINVAL;
unsigned long flags;
unsigned int hash;
@@ -508,9 +510,10 @@ static int instr_free(snd_seq_kinstr_ops_t *ops,
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARUSR)
goto __return;
- if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
+ if (ev->data.ext.len < sizeof(struct snd_seq_instr_header))
goto __return;
- if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+ if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr,
+ sizeof(struct snd_seq_instr_header))) {
result = -EFAULT;
goto __return;
}
@@ -548,7 +551,8 @@ static int instr_free(snd_seq_kinstr_ops_t *ops,
list->hash[hash] = instr->next;
}
if (instr->ops && instr->ops->notify)
- instr->ops->notify(instr->ops->private_data, instr, SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
+ instr->ops->notify(instr->ops->private_data, instr,
+ SNDRV_SEQ_INSTR_NOTIFY_REMOVE);
while (instr->use) {
spin_unlock_irqrestore(&list->lock, flags);
schedule_timeout_interruptible(1);
@@ -565,25 +569,25 @@ static int instr_free(snd_seq_kinstr_ops_t *ops,
return result;
}
-static int instr_list(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_list(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-static int instr_cluster(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+static int instr_cluster(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
return -ENXIO;
}
-int snd_seq_instr_event(snd_seq_kinstr_ops_t *ops,
- snd_seq_kinstr_list_t *list,
- snd_seq_event_t *ev,
+int snd_seq_instr_event(struct snd_seq_kinstr_ops *ops,
+ struct snd_seq_kinstr_list *list,
+ struct snd_seq_event *ev,
int client,
int atomic,
int hop)
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 8416bcffa091..40b4f679c80e 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -32,16 +32,12 @@
#include "seq_info.h"
#include "seq_lock.h"
-/* semaphore in struct file record */
-#define semaphore_of(fp) ((fp)->f_dentry->d_inode->i_sem)
-
-
-static inline int snd_seq_pool_available(pool_t *pool)
+static inline int snd_seq_pool_available(struct snd_seq_pool *pool)
{
return pool->total_elements - atomic_read(&pool->counter);
}
-static inline int snd_seq_output_ok(pool_t *pool)
+static inline int snd_seq_output_ok(struct snd_seq_pool *pool)
{
return snd_seq_pool_available(pool) >= pool->room;
}
@@ -72,7 +68,7 @@ static inline int snd_seq_output_ok(pool_t *pool)
* call dump function to expand external data.
*/
-static int get_var_len(const snd_seq_event_t *event)
+static int get_var_len(const struct snd_seq_event *event)
{
if ((event->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
return -EINVAL;
@@ -80,10 +76,11 @@ static int get_var_len(const snd_seq_event_t *event)
return event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
}
-int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data)
+int snd_seq_dump_var_event(const struct snd_seq_event *event,
+ snd_seq_dump_func_t func, void *private_data)
{
int len, err;
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
if ((len = get_var_len(event)) <= 0)
return len;
@@ -108,9 +105,9 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
return func(private_data, event->data.ext.ptr, len);
}
- cell = (snd_seq_event_cell_t*)event->data.ext.ptr;
+ cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
for (; len > 0 && cell; cell = cell->next) {
- int size = sizeof(snd_seq_event_t);
+ int size = sizeof(struct snd_seq_event);
if (len < size)
size = len;
err = func(private_data, &cell->event, size);
@@ -142,7 +139,8 @@ static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
return 0;
}
-int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned)
+int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
+ int in_kernel, int size_aligned)
{
int len, newlen;
int err;
@@ -174,17 +172,18 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
* release this cell, free extended data if available
*/
-static inline void free_cell(pool_t *pool, snd_seq_event_cell_t *cell)
+static inline void free_cell(struct snd_seq_pool *pool,
+ struct snd_seq_event_cell *cell)
{
cell->next = pool->free;
pool->free = cell;
atomic_dec(&pool->counter);
}
-void snd_seq_cell_free(snd_seq_event_cell_t * cell)
+void snd_seq_cell_free(struct snd_seq_event_cell * cell)
{
unsigned long flags;
- pool_t *pool;
+ struct snd_seq_pool *pool;
snd_assert(cell != NULL, return);
pool = cell->pool;
@@ -194,7 +193,7 @@ void snd_seq_cell_free(snd_seq_event_cell_t * cell)
free_cell(pool, cell);
if (snd_seq_ev_is_variable(&cell->event)) {
if (cell->event.data.ext.len & SNDRV_SEQ_EXT_CHAINED) {
- snd_seq_event_cell_t *curp, *nextptr;
+ struct snd_seq_event_cell *curp, *nextptr;
curp = cell->event.data.ext.ptr;
for (; curp; curp = nextptr) {
nextptr = curp->next;
@@ -215,9 +214,11 @@ void snd_seq_cell_free(snd_seq_event_cell_t * cell)
/*
* allocate an event cell.
*/
-static int snd_seq_cell_alloc(pool_t *pool, snd_seq_event_cell_t **cellp, int nonblock, struct file *file)
+static int snd_seq_cell_alloc(struct snd_seq_pool *pool,
+ struct snd_seq_event_cell **cellp,
+ int nonblock, struct file *file)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
unsigned long flags;
int err = -EAGAIN;
wait_queue_t wait;
@@ -280,11 +281,13 @@ __error:
* if the event has external data, the data is decomposed to additional
* cells.
*/
-int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t **cellp, int nonblock, struct file *file)
+int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
+ struct snd_seq_event_cell **cellp, int nonblock,
+ struct file *file)
{
int ncells, err;
unsigned int extlen;
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
*cellp = NULL;
@@ -292,7 +295,7 @@ int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t
extlen = 0;
if (snd_seq_ev_is_variable(event)) {
extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
- ncells = (extlen + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
+ ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event);
}
if (ncells >= pool->total_elements)
return -ENOMEM;
@@ -309,18 +312,18 @@ int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t
int len = extlen;
int is_chained = event->data.ext.len & SNDRV_SEQ_EXT_CHAINED;
int is_usrptr = event->data.ext.len & SNDRV_SEQ_EXT_USRPTR;
- snd_seq_event_cell_t *src, *tmp, *tail;
+ struct snd_seq_event_cell *src, *tmp, *tail;
char *buf;
cell->event.data.ext.len = extlen | SNDRV_SEQ_EXT_CHAINED;
cell->event.data.ext.ptr = NULL;
- src = (snd_seq_event_cell_t*)event->data.ext.ptr;
+ src = (struct snd_seq_event_cell *)event->data.ext.ptr;
buf = (char *)event->data.ext.ptr;
tail = NULL;
while (ncells-- > 0) {
- int size = sizeof(snd_seq_event_t);
+ int size = sizeof(struct snd_seq_event);
if (len < size)
size = len;
err = snd_seq_cell_alloc(pool, &tmp, nonblock, file);
@@ -358,7 +361,8 @@ __error:
/* poll wait */
-int snd_seq_pool_poll_wait(pool_t *pool, struct file *file, poll_table *wait)
+int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file,
+ poll_table *wait)
{
poll_wait(file, &pool->output_sleep, wait);
return snd_seq_output_ok(pool);
@@ -366,17 +370,17 @@ int snd_seq_pool_poll_wait(pool_t *pool, struct file *file, poll_table *wait)
/* allocate room specified number of events */
-int snd_seq_pool_init(pool_t *pool)
+int snd_seq_pool_init(struct snd_seq_pool *pool)
{
int cell;
- snd_seq_event_cell_t *cellptr;
+ struct snd_seq_event_cell *cellptr;
unsigned long flags;
snd_assert(pool != NULL, return -EINVAL);
if (pool->ptr) /* should be atomic? */
return 0;
- pool->ptr = vmalloc(sizeof(snd_seq_event_cell_t) * pool->size);
+ pool->ptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
if (pool->ptr == NULL) {
snd_printd("seq: malloc for sequencer events failed\n");
return -ENOMEM;
@@ -402,10 +406,10 @@ int snd_seq_pool_init(pool_t *pool)
}
/* remove events */
-int snd_seq_pool_done(pool_t *pool)
+int snd_seq_pool_done(struct snd_seq_pool *pool)
{
unsigned long flags;
- snd_seq_event_cell_t *ptr;
+ struct snd_seq_event_cell *ptr;
int max_count = 5 * HZ;
snd_assert(pool != NULL, return -EINVAL);
@@ -446,9 +450,9 @@ int snd_seq_pool_done(pool_t *pool)
/* init new memory pool */
-pool_t *snd_seq_pool_new(int poolsize)
+struct snd_seq_pool *snd_seq_pool_new(int poolsize)
{
- pool_t *pool;
+ struct snd_seq_pool *pool;
/* create pool block */
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
@@ -472,9 +476,9 @@ pool_t *snd_seq_pool_new(int poolsize)
}
/* remove memory pool */
-int snd_seq_pool_delete(pool_t **ppool)
+int snd_seq_pool_delete(struct snd_seq_pool **ppool)
{
- pool_t *pool = *ppool;
+ struct snd_seq_pool *pool = *ppool;
*ppool = NULL;
if (pool == NULL)
@@ -497,7 +501,8 @@ void __exit snd_sequencer_memory_done(void)
/* exported to seq_clientmgr.c */
-void snd_seq_info_pool(snd_info_buffer_t * buffer, pool_t *pool, char *space)
+void snd_seq_info_pool(struct snd_info_buffer *buffer,
+ struct snd_seq_pool *pool, char *space)
{
if (pool == NULL)
return;
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h
index 6c4dde5d3d6f..39c60d9e1efc 100644
--- a/sound/core/seq/seq_memory.h
+++ b/sound/core/seq/seq_memory.h
@@ -24,23 +24,21 @@
#include <sound/seq_kernel.h>
#include <linux/poll.h>
-typedef struct pool pool_t;
-
/* container for sequencer event (internal use) */
-typedef struct snd_seq_event_cell_t {
- snd_seq_event_t event;
- pool_t *pool; /* used pool */
- struct snd_seq_event_cell_t *next; /* next cell */
-} snd_seq_event_cell_t;
+struct snd_seq_event_cell {
+ struct snd_seq_event event;
+ struct snd_seq_pool *pool; /* used pool */
+ struct snd_seq_event_cell *next; /* next cell */
+};
/* design note: the pool is a contigious block of memory, if we dynamicly
want to add additional cells to the pool be better store this in another
pool as we need to know the base address of the pool when releasing
memory. */
-struct pool {
- snd_seq_event_cell_t *ptr; /* pointer to first event chunk */
- snd_seq_event_cell_t *free; /* pointer to the head of the free list */
+struct snd_seq_pool {
+ struct snd_seq_event_cell *ptr; /* pointer to first event chunk */
+ struct snd_seq_event_cell *free; /* pointer to the head of the free list */
int total_elements; /* pool size actually allocated */
atomic_t counter; /* cells free */
@@ -63,33 +61,34 @@ struct pool {
spinlock_t lock;
};
-extern void snd_seq_cell_free(snd_seq_event_cell_t* cell);
+void snd_seq_cell_free(struct snd_seq_event_cell *cell);
-int snd_seq_event_dup(pool_t *pool, snd_seq_event_t *event, snd_seq_event_cell_t **cellp, int nonblock, struct file *file);
+int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
+ struct snd_seq_event_cell **cellp, int nonblock, struct file *file);
/* return number of unused (free) cells */
-static inline int snd_seq_unused_cells(pool_t *pool)
+static inline int snd_seq_unused_cells(struct snd_seq_pool *pool)
{
return pool ? pool->total_elements - atomic_read(&pool->counter) : 0;
}
/* return total number of allocated cells */
-static inline int snd_seq_total_cells(pool_t *pool)
+static inline int snd_seq_total_cells(struct snd_seq_pool *pool)
{
return pool ? pool->total_elements : 0;
}
/* init pool - allocate events */
-int snd_seq_pool_init(pool_t *pool);
+int snd_seq_pool_init(struct snd_seq_pool *pool);
/* done pool - free events */
-int snd_seq_pool_done(pool_t *pool);
+int snd_seq_pool_done(struct snd_seq_pool *pool);
/* create pool */
-pool_t *snd_seq_pool_new(int poolsize);
+struct snd_seq_pool *snd_seq_pool_new(int poolsize);
/* remove pool */
-int snd_seq_pool_delete(pool_t **pool);
+int snd_seq_pool_delete(struct snd_seq_pool **pool);
/* init memory */
int snd_sequencer_memory_init(void);
@@ -98,7 +97,7 @@ int snd_sequencer_memory_init(void);
void snd_sequencer_memory_done(void);
/* polling */
-int snd_seq_pool_poll_wait(pool_t *pool, struct file *file, poll_table *wait);
+int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
#endif
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index f89f40f44876..ce0df86157de 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -51,40 +51,40 @@ module_param(input_buffer_size, int, 0644);
MODULE_PARM_DESC(input_buffer_size, "Input buffer size in bytes.");
/* data for this midi synth driver */
-typedef struct {
- snd_card_t *card;
+struct seq_midisynth {
+ struct snd_card *card;
int device;
int subdevice;
- snd_rawmidi_file_t input_rfile;
- snd_rawmidi_file_t output_rfile;
+ struct snd_rawmidi_file input_rfile;
+ struct snd_rawmidi_file output_rfile;
int seq_client;
int seq_port;
- snd_midi_event_t *parser;
-} seq_midisynth_t;
+ struct snd_midi_event *parser;
+};
-typedef struct {
+struct seq_midisynth_client {
int seq_client;
int num_ports;
int ports_per_device[SNDRV_RAWMIDI_DEVICES];
- seq_midisynth_t *ports[SNDRV_RAWMIDI_DEVICES];
-} seq_midisynth_client_t;
+ struct seq_midisynth *ports[SNDRV_RAWMIDI_DEVICES];
+};
-static seq_midisynth_client_t *synths[SNDRV_CARDS];
+static struct seq_midisynth_client *synths[SNDRV_CARDS];
static DECLARE_MUTEX(register_mutex);
/* handle rawmidi input event (MIDI v1.0 stream) */
-static void snd_midi_input_event(snd_rawmidi_substream_t * substream)
+static void snd_midi_input_event(struct snd_rawmidi_substream *substream)
{
- snd_rawmidi_runtime_t *runtime;
- seq_midisynth_t *msynth;
- snd_seq_event_t ev;
+ struct snd_rawmidi_runtime *runtime;
+ struct seq_midisynth *msynth;
+ struct snd_seq_event ev;
char buf[16], *pbuf;
long res, count;
if (substream == NULL)
return;
runtime = substream->runtime;
- msynth = (seq_midisynth_t *) runtime->private_data;
+ msynth = runtime->private_data;
if (msynth == NULL)
return;
memset(&ev, 0, sizeof(ev));
@@ -112,9 +112,9 @@ static void snd_midi_input_event(snd_rawmidi_substream_t * substream)
}
}
-static int dump_midi(snd_rawmidi_substream_t *substream, const char *buf, int count)
+static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, int count)
{
- snd_rawmidi_runtime_t *runtime;
+ struct snd_rawmidi_runtime *runtime;
int tmp;
snd_assert(substream != NULL || buf != NULL, return -EINVAL);
@@ -128,12 +128,12 @@ static int dump_midi(snd_rawmidi_substream_t *substream, const char *buf, int co
return 0;
}
-static int event_process_midi(snd_seq_event_t * ev, int direct,
+static int event_process_midi(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
- seq_midisynth_t *msynth = (seq_midisynth_t *) private_data;
+ struct seq_midisynth *msynth = private_data;
unsigned char msg[10]; /* buffer for constructing midi messages */
- snd_rawmidi_substream_t *substream;
+ struct snd_rawmidi_substream *substream;
int len;
snd_assert(msynth != NULL, return -EINVAL);
@@ -161,8 +161,8 @@ static int event_process_midi(snd_seq_event_t * ev, int direct,
}
-static int snd_seq_midisynth_new(seq_midisynth_t *msynth,
- snd_card_t *card,
+static int snd_seq_midisynth_new(struct seq_midisynth *msynth,
+ struct snd_card *card,
int device,
int subdevice)
{
@@ -175,15 +175,18 @@ static int snd_seq_midisynth_new(seq_midisynth_t *msynth,
}
/* open associated midi device for input */
-static int midisynth_subscribe(void *private_data, snd_seq_port_subscribe_t *info)
+static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe *info)
{
int err;
- seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
- snd_rawmidi_runtime_t *runtime;
- snd_rawmidi_params_t params;
+ struct seq_midisynth *msynth = private_data;
+ struct snd_rawmidi_runtime *runtime;
+ struct snd_rawmidi_params params;
/* open midi port */
- if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) {
+ if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
+ msynth->subdevice,
+ SNDRV_RAWMIDI_LFLG_INPUT,
+ &msynth->input_rfile)) < 0) {
snd_printd("midi input open failed!!!\n");
return err;
}
@@ -203,10 +206,10 @@ static int midisynth_subscribe(void *private_data, snd_seq_port_subscribe_t *inf
}
/* close associated midi device for input */
-static int midisynth_unsubscribe(void *private_data, snd_seq_port_subscribe_t *info)
+static int midisynth_unsubscribe(void *private_data, struct snd_seq_port_subscribe *info)
{
int err;
- seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
+ struct seq_midisynth *msynth = private_data;
snd_assert(msynth->input_rfile.input != NULL, return -EINVAL);
err = snd_rawmidi_kernel_release(&msynth->input_rfile);
@@ -214,14 +217,17 @@ static int midisynth_unsubscribe(void *private_data, snd_seq_port_subscribe_t *i
}
/* open associated midi device for output */
-static int midisynth_use(void *private_data, snd_seq_port_subscribe_t *info)
+static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info)
{
int err;
- seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
- snd_rawmidi_params_t params;
+ struct seq_midisynth *msynth = private_data;
+ struct snd_rawmidi_params params;
/* open midi port */
- if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) {
+ if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
+ msynth->subdevice,
+ SNDRV_RAWMIDI_LFLG_OUTPUT,
+ &msynth->output_rfile)) < 0) {
snd_printd("midi output open failed!!!\n");
return err;
}
@@ -237,9 +243,9 @@ static int midisynth_use(void *private_data, snd_seq_port_subscribe_t *info)
}
/* close associated midi device for output */
-static int midisynth_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
- seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
+ struct seq_midisynth *msynth = private_data;
unsigned char buf = 0xff; /* MIDI reset */
snd_assert(msynth->output_rfile.output != NULL, return -EINVAL);
@@ -250,7 +256,7 @@ static int midisynth_unuse(void *private_data, snd_seq_port_subscribe_t *info)
}
/* delete given midi synth port */
-static void snd_seq_midisynth_delete(seq_midisynth_t *msynth)
+static void snd_seq_midisynth_delete(struct seq_midisynth *msynth)
{
if (msynth == NULL)
return;
@@ -264,34 +270,18 @@ static void snd_seq_midisynth_delete(seq_midisynth_t *msynth)
snd_midi_event_free(msynth->parser);
}
-/* set our client name */
-static int set_client_name(seq_midisynth_client_t *client, snd_card_t *card,
- snd_rawmidi_info_t *rmidi)
-{
- snd_seq_client_info_t cinfo;
- const char *name;
-
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client->seq_client;
- cinfo.type = KERNEL_CLIENT;
- name = rmidi->name[0] ? (const char *)rmidi->name : "External MIDI";
- strlcpy(cinfo.name, name, sizeof(cinfo.name));
- return snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
-}
-
/* register new midi synth port */
static int
-snd_seq_midisynth_register_port(snd_seq_device_t *dev)
+snd_seq_midisynth_register_port(struct snd_seq_device *dev)
{
- seq_midisynth_client_t *client;
- seq_midisynth_t *msynth, *ms;
- snd_seq_port_info_t *port;
- snd_rawmidi_info_t *info;
+ struct seq_midisynth_client *client;
+ struct seq_midisynth *msynth, *ms;
+ struct snd_seq_port_info *port;
+ struct snd_rawmidi_info *info;
int newclient = 0;
unsigned int p, ports;
- snd_seq_client_callback_t callbacks;
- snd_seq_port_callback_t pcallbacks;
- snd_card_t *card = dev->card;
+ struct snd_seq_port_callback pcallbacks;
+ struct snd_card *card = dev->card;
int device = dev->device;
unsigned int input_count = 0, output_count = 0;
@@ -328,21 +318,19 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
kfree(info);
return -ENOMEM;
}
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = client;
- callbacks.allow_input = callbacks.allow_output = 1;
- client->seq_client = snd_seq_create_kernel_client(card, 0, &callbacks);
+ client->seq_client =
+ snd_seq_create_kernel_client(
+ card, 0, "%s", info->name[0] ?
+ (const char *)info->name : "External MIDI");
if (client->seq_client < 0) {
kfree(client);
up(&register_mutex);
kfree(info);
return -ENOMEM;
}
- set_client_name(client, card, info);
- } else if (device == 0)
- set_client_name(client, card, info); /* use the first device's name */
+ }
- msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
+ msynth = kcalloc(ports, sizeof(struct seq_midisynth), GFP_KERNEL);
port = kmalloc(sizeof(*port), GFP_KERNEL);
if (msynth == NULL || port == NULL)
goto __nomem;
@@ -432,11 +420,11 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
/* release midi synth port */
static int
-snd_seq_midisynth_unregister_port(snd_seq_device_t *dev)
+snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
{
- seq_midisynth_client_t *client;
- seq_midisynth_t *msynth;
- snd_card_t *card = dev->card;
+ struct seq_midisynth_client *client;
+ struct seq_midisynth *msynth;
+ struct snd_card *card = dev->card;
int device = dev->device, p, ports;
down(&register_mutex);
@@ -465,7 +453,7 @@ snd_seq_midisynth_unregister_port(snd_seq_device_t *dev)
static int __init alsa_seq_midi_init(void)
{
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_seq_midisynth_register_port,
snd_seq_midisynth_unregister_port,
};
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 35fe8a7e34bf..d7c4fb86b9eb 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -44,17 +44,25 @@ MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation."
MODULE_LICENSE("GPL");
/* Prototypes for static functions */
-static void note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int vel);
-static void do_control(snd_midi_op_t *ops, void *private,
- snd_midi_channel_set_t *chset, snd_midi_channel_t *chan,
+static void note_off(struct snd_midi_op *ops, void *drv,
+ struct snd_midi_channel *chan,
+ int note, int vel);
+static void do_control(struct snd_midi_op *ops, void *private,
+ struct snd_midi_channel_set *chset,
+ struct snd_midi_channel *chan,
int control, int value);
-static void rpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
-static void nrpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
-static void sysex(snd_midi_op_t *ops, void *private, unsigned char *sysex, int len, snd_midi_channel_set_t *chset);
-static void all_sounds_off(snd_midi_op_t *ops, void *private, snd_midi_channel_t *chan);
-static void all_notes_off(snd_midi_op_t *ops, void *private, snd_midi_channel_t *chan);
-static void snd_midi_reset_controllers(snd_midi_channel_t *chan);
-static void reset_all_channels(snd_midi_channel_set_t *chset);
+static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset);
+static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset);
+static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex,
+ int len, struct snd_midi_channel_set *chset);
+static void all_sounds_off(struct snd_midi_op *ops, void *private,
+ struct snd_midi_channel *chan);
+static void all_notes_off(struct snd_midi_op *ops, void *private,
+ struct snd_midi_channel *chan);
+static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
+static void reset_all_channels(struct snd_midi_channel_set *chset);
/*
@@ -72,10 +80,11 @@ static void reset_all_channels(snd_midi_channel_set_t *chset);
* be interpreted.
*/
void
-snd_midi_process_event(snd_midi_op_t *ops,
- snd_seq_event_t *ev, snd_midi_channel_set_t *chanset)
+snd_midi_process_event(struct snd_midi_op *ops,
+ struct snd_seq_event *ev,
+ struct snd_midi_channel_set *chanset)
{
- snd_midi_channel_t *chan;
+ struct snd_midi_channel *chan;
void *drv;
int dest_channel = 0;
@@ -89,7 +98,8 @@ snd_midi_process_event(snd_midi_op_t *ops,
if (snd_seq_ev_is_channel_type(ev)) {
dest_channel = ev->data.note.channel;
if (dest_channel >= chanset->max_channels) {
- snd_printd("dest channel is %d, max is %d\n", dest_channel, chanset->max_channels);
+ snd_printd("dest channel is %d, max is %d\n",
+ dest_channel, chanset->max_channels);
return;
}
}
@@ -239,7 +249,8 @@ snd_midi_process_event(snd_midi_op_t *ops,
* release note
*/
static void
-note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int vel)
+note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+ int note, int vel)
{
if (chan->gm_hold) {
/* Hold this note until pedal is turned off */
@@ -260,8 +271,8 @@ note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int
* events that need to take place immediately to the driver.
*/
static void
-do_control(snd_midi_op_t *ops, void *drv, snd_midi_channel_set_t *chset,
- snd_midi_channel_t *chan, int control, int value)
+do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset,
+ struct snd_midi_channel *chan, int control, int value)
{
int i;
@@ -376,7 +387,7 @@ do_control(snd_midi_op_t *ops, void *drv, snd_midi_channel_set_t *chset,
* initialize the MIDI status
*/
void
-snd_midi_channel_set_clear(snd_midi_channel_set_t *chset)
+snd_midi_channel_set_clear(struct snd_midi_channel_set *chset)
{
int i;
@@ -384,7 +395,7 @@ snd_midi_channel_set_clear(snd_midi_channel_set_t *chset)
chset->gs_master_volume = 127;
for (i = 0; i < chset->max_channels; i++) {
- snd_midi_channel_t *chan = chset->channels + i;
+ struct snd_midi_channel *chan = chset->channels + i;
memset(chan->note, 0, sizeof(chan->note));
chan->midi_aftertouch = 0;
@@ -407,8 +418,8 @@ snd_midi_channel_set_clear(snd_midi_channel_set_t *chset)
* Process a rpn message.
*/
static void
-rpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan,
- snd_midi_channel_set_t *chset)
+rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset)
{
int type;
int val;
@@ -447,8 +458,8 @@ rpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan,
* Process an nrpn message.
*/
static void
-nrpn(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan,
- snd_midi_channel_set_t *chset)
+nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset)
{
/* parse XG NRPNs here if possible */
if (ops->nrpn)
@@ -475,7 +486,8 @@ get_channel(unsigned char cmd)
* Process a sysex message.
*/
static void
-sysex(snd_midi_op_t *ops, void *private, unsigned char *buf, int len, snd_midi_channel_set_t *chset)
+sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
+ struct snd_midi_channel_set *chset)
{
/* GM on */
static unsigned char gm_on_macro[] = {
@@ -588,7 +600,7 @@ sysex(snd_midi_op_t *ops, void *private, unsigned char *buf, int len, snd_midi_c
* all sound off
*/
static void
-all_sounds_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan)
+all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
{
int n;
@@ -606,7 +618,7 @@ all_sounds_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan)
* all notes off
*/
static void
-all_notes_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan)
+all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
{
int n;
@@ -621,12 +633,12 @@ all_notes_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan)
/*
* Initialise a single midi channel control block.
*/
-static void snd_midi_channel_init(snd_midi_channel_t *p, int n)
+static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
{
if (p == NULL)
return;
- memset(p, 0, sizeof(snd_midi_channel_t));
+ memset(p, 0, sizeof(struct snd_midi_channel));
p->private = NULL;
p->number = n;
@@ -642,12 +654,12 @@ static void snd_midi_channel_init(snd_midi_channel_t *p, int n)
/*
* Allocate and initialise a set of midi channel control blocks.
*/
-static snd_midi_channel_t *snd_midi_channel_init_set(int n)
+static struct snd_midi_channel *snd_midi_channel_init_set(int n)
{
- snd_midi_channel_t *chan;
+ struct snd_midi_channel *chan;
int i;
- chan = kmalloc(n * sizeof(snd_midi_channel_t), GFP_KERNEL);
+ chan = kmalloc(n * sizeof(struct snd_midi_channel), GFP_KERNEL);
if (chan) {
for (i = 0; i < n; i++)
snd_midi_channel_init(chan+i, i);
@@ -660,11 +672,11 @@ static snd_midi_channel_t *snd_midi_channel_init_set(int n)
* reset all midi channels
*/
static void
-reset_all_channels(snd_midi_channel_set_t *chset)
+reset_all_channels(struct snd_midi_channel_set *chset)
{
int ch;
for (ch = 0; ch < chset->max_channels; ch++) {
- snd_midi_channel_t *chan = chset->channels + ch;
+ struct snd_midi_channel *chan = chset->channels + ch;
snd_midi_reset_controllers(chan);
chan->gm_rpn_pitch_bend_range = 256; /* 2 semitones */
chan->gm_rpn_fine_tuning = 0;
@@ -681,9 +693,9 @@ reset_all_channels(snd_midi_channel_set_t *chset)
/*
* Allocate and initialise a midi channel set.
*/
-snd_midi_channel_set_t *snd_midi_channel_alloc_set(int n)
+struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
{
- snd_midi_channel_set_t *chset;
+ struct snd_midi_channel_set *chset;
chset = kmalloc(sizeof(*chset), GFP_KERNEL);
if (chset) {
@@ -697,7 +709,7 @@ snd_midi_channel_set_t *snd_midi_channel_alloc_set(int n)
/*
* Reset the midi controllers on a particular channel to default values.
*/
-static void snd_midi_reset_controllers(snd_midi_channel_t *chan)
+static void snd_midi_reset_controllers(struct snd_midi_channel *chan)
{
memset(chan->control, 0, sizeof(chan->control));
chan->gm_volume = 127;
@@ -709,7 +721,7 @@ static void snd_midi_reset_controllers(snd_midi_channel_t *chan)
/*
* Free a midi channel set.
*/
-void snd_midi_channel_free_set(snd_midi_channel_set_t *chset)
+void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
{
if (chset == NULL)
return;
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 2dc1aecfb426..5ff80b776906 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -41,33 +41,29 @@ MODULE_LICENSE("GPL");
/* from 8 to 15 are events for 0xf0-0xf7 */
-/* status event types */
-typedef void (*event_encode_t)(snd_midi_event_t *dev, snd_seq_event_t *ev);
-typedef void (*event_decode_t)(snd_seq_event_t *ev, unsigned char *buf);
-
/*
* prototypes
*/
-static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev);
-static void note_decode(snd_seq_event_t *ev, unsigned char *buf);
-static void one_param_decode(snd_seq_event_t *ev, unsigned char *buf);
-static void pitchbend_decode(snd_seq_event_t *ev, unsigned char *buf);
-static void two_param_decode(snd_seq_event_t *ev, unsigned char *buf);
-static void songpos_decode(snd_seq_event_t *ev, unsigned char *buf);
+static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev);
+static void note_decode(struct snd_seq_event *ev, unsigned char *buf);
+static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf);
+static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf);
+static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf);
+static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf);
/*
* event list
*/
-static struct status_event_list_t {
+static struct status_event_list {
int event;
int qlen;
- event_encode_t encode;
- event_decode_t decode;
+ void (*encode)(struct snd_midi_event *dev, struct snd_seq_event *ev);
+ void (*decode)(struct snd_seq_event *ev, unsigned char *buf);
} status_event[] = {
/* 0x80 - 0xf0 */
{SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode},
@@ -97,12 +93,15 @@ static struct status_event_list_t {
{SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */
};
-static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev);
-static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, snd_seq_event_t *ev);
+static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf, int len,
+ struct snd_seq_event *ev);
+static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, int count,
+ struct snd_seq_event *ev);
-static struct extra_event_list_t {
+static struct extra_event_list {
int event;
- int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev);
+ int (*decode)(struct snd_midi_event *dev, unsigned char *buf, int len,
+ struct snd_seq_event *ev);
} extra_event[] = {
{SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14},
{SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_xrpn},
@@ -113,9 +112,9 @@ static struct extra_event_list_t {
* new/delete record
*/
-int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
+int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev)
{
- snd_midi_event_t *dev;
+ struct snd_midi_event *dev;
*rdev = NULL;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -135,7 +134,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
return 0;
}
-void snd_midi_event_free(snd_midi_event_t *dev)
+void snd_midi_event_free(struct snd_midi_event *dev)
{
if (dev != NULL) {
kfree(dev->buf);
@@ -146,14 +145,14 @@ void snd_midi_event_free(snd_midi_event_t *dev)
/*
* initialize record
*/
-static inline void reset_encode(snd_midi_event_t *dev)
+static inline void reset_encode(struct snd_midi_event *dev)
{
dev->read = 0;
dev->qlen = 0;
dev->type = 0;
}
-void snd_midi_event_reset_encode(snd_midi_event_t *dev)
+void snd_midi_event_reset_encode(struct snd_midi_event *dev)
{
unsigned long flags;
@@ -162,7 +161,7 @@ void snd_midi_event_reset_encode(snd_midi_event_t *dev)
spin_unlock_irqrestore(&dev->lock, flags);
}
-void snd_midi_event_reset_decode(snd_midi_event_t *dev)
+void snd_midi_event_reset_decode(struct snd_midi_event *dev)
{
unsigned long flags;
@@ -172,14 +171,14 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev)
}
#if 0
-void snd_midi_event_init(snd_midi_event_t *dev)
+void snd_midi_event_init(struct snd_midi_event *dev)
{
snd_midi_event_reset_encode(dev);
snd_midi_event_reset_decode(dev);
}
#endif /* 0 */
-void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
+void snd_midi_event_no_status(struct snd_midi_event *dev, int on)
{
dev->nostat = on ? 1 : 0;
}
@@ -188,7 +187,7 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
* resize buffer
*/
#if 0
-int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
+int snd_midi_event_resize_buffer(struct snd_midi_event *dev, int bufsize)
{
unsigned char *new_buf, *old_buf;
unsigned long flags;
@@ -213,7 +212,8 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
* read bytes and encode to sequencer event if finished
* return the size of encoded bytes
*/
-long snd_midi_event_encode(snd_midi_event_t *dev, unsigned char *buf, long count, snd_seq_event_t *ev)
+long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev)
{
long result = 0;
int rc;
@@ -238,7 +238,8 @@ long snd_midi_event_encode(snd_midi_event_t *dev, unsigned char *buf, long count
* 0 data is not finished
* negative for error
*/
-int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev)
+int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c,
+ struct snd_seq_event *ev)
{
int rc = 0;
unsigned long flags;
@@ -303,7 +304,7 @@ int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev
}
/* encode note event */
-static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.note.channel = dev->buf[0] & 0x0f;
ev->data.note.note = dev->buf[1];
@@ -311,21 +312,21 @@ static void note_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
}
/* encode one parameter controls */
-static void one_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void one_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.control.channel = dev->buf[0] & 0x0f;
ev->data.control.value = dev->buf[1];
}
/* encode pitch wheel change */
-static void pitchbend_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void pitchbend_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.control.channel = dev->buf[0] & 0x0f;
ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1] - 8192;
}
/* encode midi control change */
-static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void two_param_ctrl_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.control.channel = dev->buf[0] & 0x0f;
ev->data.control.param = dev->buf[1];
@@ -333,13 +334,13 @@ static void two_param_ctrl_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
}
/* encode one parameter value*/
-static void one_param_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void one_param_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.control.value = dev->buf[1];
}
/* encode song position */
-static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
+static void songpos_event(struct snd_midi_event *dev, struct snd_seq_event *ev)
{
ev->data.control.value = (int)dev->buf[2] * 128 + (int)dev->buf[1];
}
@@ -348,7 +349,8 @@ static void songpos_event(snd_midi_event_t *dev, snd_seq_event_t *ev)
* decode from a sequencer event to midi bytes
* return the size of decoded midi events
*/
-long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count, snd_seq_event_t *ev)
+long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long count,
+ struct snd_seq_event *ev)
{
unsigned int cmd, type;
@@ -404,20 +406,20 @@ long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count
/* decode note event */
-static void note_decode(snd_seq_event_t *ev, unsigned char *buf)
+static void note_decode(struct snd_seq_event *ev, unsigned char *buf)
{
buf[0] = ev->data.note.note & 0x7f;
buf[1] = ev->data.note.velocity & 0x7f;
}
/* decode one parameter controls */
-static void one_param_decode(snd_seq_event_t *ev, unsigned char *buf)
+static void one_param_decode(struct snd_seq_event *ev, unsigned char *buf)
{
buf[0] = ev->data.control.value & 0x7f;
}
/* decode pitch wheel change */
-static void pitchbend_decode(snd_seq_event_t *ev, unsigned char *buf)
+static void pitchbend_decode(struct snd_seq_event *ev, unsigned char *buf)
{
int value = ev->data.control.value + 8192;
buf[0] = value & 0x7f;
@@ -425,21 +427,22 @@ static void pitchbend_decode(snd_seq_event_t *ev, unsigned char *buf)
}
/* decode midi control change */
-static void two_param_decode(snd_seq_event_t *ev, unsigned char *buf)
+static void two_param_decode(struct snd_seq_event *ev, unsigned char *buf)
{
buf[0] = ev->data.control.param & 0x7f;
buf[1] = ev->data.control.value & 0x7f;
}
/* decode song position */
-static void songpos_decode(snd_seq_event_t *ev, unsigned char *buf)
+static void songpos_decode(struct snd_seq_event *ev, unsigned char *buf)
{
buf[0] = ev->data.control.value & 0x7f;
buf[1] = (ev->data.control.value >> 7) & 0x7f;
}
/* decode 14bit control */
-static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int count, snd_seq_event_t *ev)
+static int extra_decode_ctrl14(struct snd_midi_event *dev, unsigned char *buf,
+ int count, struct snd_seq_event *ev)
{
unsigned char cmd;
int idx = 0;
@@ -476,7 +479,8 @@ static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int co
}
/* decode reg/nonreg param */
-static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int count, snd_seq_event_t *ev)
+static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
+ int count, struct snd_seq_event *ev)
{
unsigned char cmd;
char *cbytes;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 57ec31df0d15..2b384fd7967f 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -56,16 +56,17 @@ much elements are in array.
*/
/* return pointer to port structure - port is locked if found */
-client_port_t *snd_seq_port_use_ptr(client_t *client, int num)
+struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
+ int num)
{
struct list_head *p;
- client_port_t *port;
+ struct snd_seq_client_port *port;
if (client == NULL)
return NULL;
read_lock(&client->ports_lock);
list_for_each(p, &client->ports_list_head) {
- port = list_entry(p, client_port_t, list);
+ port = list_entry(p, struct snd_seq_client_port, list);
if (port->addr.port == num) {
if (port->closing)
break; /* deleting now */
@@ -80,17 +81,18 @@ client_port_t *snd_seq_port_use_ptr(client_t *client, int num)
/* search for the next port - port is locked if found */
-client_port_t *snd_seq_port_query_nearest(client_t *client, snd_seq_port_info_t *pinfo)
+struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
+ struct snd_seq_port_info *pinfo)
{
int num;
struct list_head *p;
- client_port_t *port, *found;
+ struct snd_seq_client_port *port, *found;
num = pinfo->addr.port;
found = NULL;
read_lock(&client->ports_lock);
list_for_each(p, &client->ports_list_head) {
- port = list_entry(p, client_port_t, list);
+ port = list_entry(p, struct snd_seq_client_port, list);
if (port->addr.port < num)
continue;
if (port->addr.port == num) {
@@ -111,8 +113,8 @@ client_port_t *snd_seq_port_query_nearest(client_t *client, snd_seq_port_info_t
}
-/* initialize port_subs_info_t */
-static void port_subs_info_init(port_subs_info_t *grp)
+/* initialize snd_seq_port_subs_info */
+static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
{
INIT_LIST_HEAD(&grp->list_head);
grp->count = 0;
@@ -125,10 +127,11 @@ static void port_subs_info_init(port_subs_info_t *grp)
/* create a port, port number is returned (-1 on failure) */
-client_port_t *snd_seq_create_port(client_t *client, int port)
+struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
+ int port)
{
unsigned long flags;
- client_port_t *new_port;
+ struct snd_seq_client_port *new_port;
struct list_head *l;
int num = -1;
@@ -159,7 +162,7 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
down(&client->ports_mutex);
write_lock_irqsave(&client->ports_lock, flags);
list_for_each(l, &client->ports_list_head) {
- client_port_t *p = list_entry(l, client_port_t, list);
+ struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
if (p->addr.port > num)
break;
if (port < 0) /* auto-probe mode */
@@ -177,17 +180,24 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
}
/* */
-enum group_type_t {
+enum group_type {
SRC_LIST, DEST_LIST
};
-static int subscribe_port(client_t *client, client_port_t *port, port_subs_info_t *grp, snd_seq_port_subscribe_t *info, int send_ack);
-static int unsubscribe_port(client_t *client, client_port_t *port, port_subs_info_t *grp, snd_seq_port_subscribe_t *info, int send_ack);
+static int subscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+ struct snd_seq_port_subscribe *info, int send_ack);
+static int unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+ struct snd_seq_port_subscribe *info, int send_ack);
-static client_port_t *get_client_port(snd_seq_addr_t *addr, client_t **cp)
+static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
+ struct snd_seq_client **cp)
{
- client_port_t *p;
+ struct snd_seq_client_port *p;
*cp = snd_seq_client_use_ptr(addr->client);
if (*cp) {
p = snd_seq_port_use_ptr(*cp, addr->port);
@@ -204,22 +214,24 @@ static client_port_t *get_client_port(snd_seq_addr_t *addr, client_t **cp)
* remove all subscribers on the list
* this is called from port_delete, for each src and dest list.
*/
-static void clear_subscriber_list(client_t *client, client_port_t *port,
- port_subs_info_t *grp, int grptype)
+static void clear_subscriber_list(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+ int grptype)
{
struct list_head *p, *n;
down_write(&grp->list_mutex);
list_for_each_safe(p, n, &grp->list_head) {
- subscribers_t *subs;
- client_t *c;
- client_port_t *aport;
+ struct snd_seq_subscribers *subs;
+ struct snd_seq_client *c;
+ struct snd_seq_client_port *aport;
if (grptype == SRC_LIST) {
- subs = list_entry(p, subscribers_t, src_list);
+ subs = list_entry(p, struct snd_seq_subscribers, src_list);
aport = get_client_port(&subs->info.dest, &c);
} else {
- subs = list_entry(p, subscribers_t, dest_list);
+ subs = list_entry(p, struct snd_seq_subscribers, dest_list);
aport = get_client_port(&subs->info.sender, &c);
}
list_del(p);
@@ -233,7 +245,7 @@ static void clear_subscriber_list(client_t *client, client_port_t *port,
kfree(subs);
} else {
/* ok we got the connected port */
- port_subs_info_t *agrp;
+ struct snd_seq_port_subs_info *agrp;
agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
down_write(&agrp->list_mutex);
if (grptype == SRC_LIST)
@@ -251,7 +263,8 @@ static void clear_subscriber_list(client_t *client, client_port_t *port,
}
/* delete port data */
-static int port_delete(client_t *client, client_port_t *port)
+static int port_delete(struct snd_seq_client *client,
+ struct snd_seq_client_port *port)
{
/* set closing flag and wait for all port access are gone */
port->closing = 1;
@@ -273,16 +286,16 @@ static int port_delete(client_t *client, client_port_t *port)
/* delete a port with the given port id */
-int snd_seq_delete_port(client_t *client, int port)
+int snd_seq_delete_port(struct snd_seq_client *client, int port)
{
unsigned long flags;
struct list_head *l;
- client_port_t *found = NULL;
+ struct snd_seq_client_port *found = NULL;
down(&client->ports_mutex);
write_lock_irqsave(&client->ports_lock, flags);
list_for_each(l, &client->ports_list_head) {
- client_port_t *p = list_entry(l, client_port_t, list);
+ struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
if (p->addr.port == port) {
/* ok found. delete from the list at first */
list_del(l);
@@ -300,7 +313,7 @@ int snd_seq_delete_port(client_t *client, int port)
}
/* delete the all ports belonging to the given client */
-int snd_seq_delete_all_ports(client_t *client)
+int snd_seq_delete_all_ports(struct snd_seq_client *client)
{
unsigned long flags;
struct list_head deleted_list, *p, *n;
@@ -323,7 +336,7 @@ int snd_seq_delete_all_ports(client_t *client)
/* remove each port in deleted_list */
list_for_each_safe(p, n, &deleted_list) {
- client_port_t *port = list_entry(p, client_port_t, list);
+ struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list);
list_del(p);
snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
port_delete(client, port);
@@ -333,7 +346,8 @@ int snd_seq_delete_all_ports(client_t *client)
}
/* set port info fields */
-int snd_seq_set_port_info(client_port_t * port, snd_seq_port_info_t * info)
+int snd_seq_set_port_info(struct snd_seq_client_port * port,
+ struct snd_seq_port_info * info)
{
snd_assert(port && info, return -EINVAL);
@@ -361,7 +375,8 @@ int snd_seq_set_port_info(client_port_t * port, snd_seq_port_info_t * info)
}
/* get port info fields */
-int snd_seq_get_port_info(client_port_t * port, snd_seq_port_info_t * info)
+int snd_seq_get_port_info(struct snd_seq_client_port * port,
+ struct snd_seq_port_info * info)
{
snd_assert(port && info, return -EINVAL);
@@ -410,8 +425,11 @@ int snd_seq_get_port_info(client_port_t * port, snd_seq_port_info_t * info)
* at each connnection/disconnection.
*/
-static int subscribe_port(client_t *client, client_port_t *port, port_subs_info_t *grp,
- snd_seq_port_subscribe_t *info, int send_ack)
+static int subscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+ struct snd_seq_port_subscribe *info,
+ int send_ack)
{
int err = 0;
@@ -432,9 +450,11 @@ static int subscribe_port(client_t *client, client_port_t *port, port_subs_info_
return err;
}
-static int unsubscribe_port(client_t *client, client_port_t *port,
- port_subs_info_t *grp,
- snd_seq_port_subscribe_t *info, int send_ack)
+static int unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+ struct snd_seq_port_subscribe *info,
+ int send_ack)
{
int err = 0;
@@ -453,15 +473,15 @@ static int unsubscribe_port(client_t *client, client_port_t *port,
/* check if both addresses are identical */
-static inline int addr_match(snd_seq_addr_t *r, snd_seq_addr_t *s)
+static inline int addr_match(struct snd_seq_addr *r, struct snd_seq_addr *s)
{
return (r->client == s->client) && (r->port == s->port);
}
/* check the two subscribe info match */
/* if flags is zero, checks only sender and destination addresses */
-static int match_subs_info(snd_seq_port_subscribe_t *r,
- snd_seq_port_subscribe_t *s)
+static int match_subs_info(struct snd_seq_port_subscribe *r,
+ struct snd_seq_port_subscribe *s)
{
if (addr_match(&r->sender, &s->sender) &&
addr_match(&r->dest, &s->dest)) {
@@ -475,14 +495,16 @@ static int match_subs_info(snd_seq_port_subscribe_t *r,
/* connect two ports */
-int snd_seq_port_connect(client_t *connector,
- client_t *src_client, client_port_t *src_port,
- client_t *dest_client, client_port_t *dest_port,
- snd_seq_port_subscribe_t *info)
+int snd_seq_port_connect(struct snd_seq_client *connector,
+ struct snd_seq_client *src_client,
+ struct snd_seq_client_port *src_port,
+ struct snd_seq_client *dest_client,
+ struct snd_seq_client_port *dest_port,
+ struct snd_seq_port_subscribe *info)
{
- port_subs_info_t *src = &src_port->c_src;
- port_subs_info_t *dest = &dest_port->c_dest;
- subscribers_t *subs;
+ struct snd_seq_port_subs_info *src = &src_port->c_src;
+ struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+ struct snd_seq_subscribers *subs;
struct list_head *p;
int err, src_called = 0;
unsigned long flags;
@@ -508,12 +530,12 @@ int snd_seq_port_connect(client_t *connector,
goto __error;
/* check whether already exists */
list_for_each(p, &src->list_head) {
- subscribers_t *s = list_entry(p, subscribers_t, src_list);
+ struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, src_list);
if (match_subs_info(info, &s->info))
goto __error;
}
list_for_each(p, &dest->list_head) {
- subscribers_t *s = list_entry(p, subscribers_t, dest_list);
+ struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, dest_list);
if (match_subs_info(info, &s->info))
goto __error;
}
@@ -554,14 +576,16 @@ int snd_seq_port_connect(client_t *connector,
/* remove the connection */
-int snd_seq_port_disconnect(client_t *connector,
- client_t *src_client, client_port_t *src_port,
- client_t *dest_client, client_port_t *dest_port,
- snd_seq_port_subscribe_t *info)
+int snd_seq_port_disconnect(struct snd_seq_client *connector,
+ struct snd_seq_client *src_client,
+ struct snd_seq_client_port *src_port,
+ struct snd_seq_client *dest_client,
+ struct snd_seq_client_port *dest_port,
+ struct snd_seq_port_subscribe *info)
{
- port_subs_info_t *src = &src_port->c_src;
- port_subs_info_t *dest = &dest_port->c_dest;
- subscribers_t *subs;
+ struct snd_seq_port_subs_info *src = &src_port->c_src;
+ struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+ struct snd_seq_subscribers *subs;
struct list_head *p;
int err = -ENOENT;
unsigned long flags;
@@ -571,7 +595,7 @@ int snd_seq_port_disconnect(client_t *connector,
/* look for the connection */
list_for_each(p, &src->list_head) {
- subs = list_entry(p, subscribers_t, src_list);
+ subs = list_entry(p, struct snd_seq_subscribers, src_list);
if (match_subs_info(info, &subs->info)) {
write_lock_irqsave(&src->list_lock, flags);
// write_lock(&dest->list_lock); // no lock yet
@@ -597,15 +621,15 @@ int snd_seq_port_disconnect(client_t *connector,
/* get matched subscriber */
-subscribers_t *snd_seq_port_get_subscription(port_subs_info_t *src_grp,
- snd_seq_addr_t *dest_addr)
+struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
+ struct snd_seq_addr *dest_addr)
{
struct list_head *p;
- subscribers_t *s, *found = NULL;
+ struct snd_seq_subscribers *s, *found = NULL;
down_read(&src_grp->list_mutex);
list_for_each(p, &src_grp->list_head) {
- s = list_entry(p, subscribers_t, src_list);
+ s = list_entry(p, struct snd_seq_subscribers, src_list);
if (addr_match(dest_addr, &s->info.dest)) {
found = s;
break;
@@ -623,11 +647,11 @@ subscribers_t *snd_seq_port_get_subscription(port_subs_info_t *src_grp,
*/
/* exported */
int snd_seq_event_port_attach(int client,
- snd_seq_port_callback_t *pcbp,
+ struct snd_seq_port_callback *pcbp,
int cap, int type, int midi_channels,
int midi_voices, char *portname)
{
- snd_seq_port_info_t portinfo;
+ struct snd_seq_port_info portinfo;
int ret;
/* Set up the port */
@@ -660,7 +684,7 @@ int snd_seq_event_port_attach(int client,
/* exported */
int snd_seq_event_port_detach(int client, int port)
{
- snd_seq_port_info_t portinfo;
+ struct snd_seq_port_info portinfo;
int err;
memset(&portinfo, 0, sizeof(portinfo));
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index 89fd4416f6fa..9d7117118ba4 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -40,37 +40,38 @@
*/
-typedef struct subscribers_t {
- snd_seq_port_subscribe_t info; /* additional info */
+struct snd_seq_subscribers {
+ struct snd_seq_port_subscribe info; /* additional info */
struct list_head src_list; /* link of sources */
struct list_head dest_list; /* link of destinations */
atomic_t ref_count;
-} subscribers_t;
+};
-typedef struct port_subs_info_t {
+struct snd_seq_port_subs_info {
struct list_head list_head; /* list of subscribed ports */
unsigned int count; /* count of subscribers */
unsigned int exclusive: 1; /* exclusive mode */
struct rw_semaphore list_mutex;
rwlock_t list_lock;
- snd_seq_kernel_port_open_t *open;
- snd_seq_kernel_port_close_t *close;
-} port_subs_info_t;
+ int (*open)(void *private_data, struct snd_seq_port_subscribe *info);
+ int (*close)(void *private_data, struct snd_seq_port_subscribe *info);
+};
-typedef struct client_port_t {
+struct snd_seq_client_port {
- snd_seq_addr_t addr; /* client/port number */
+ struct snd_seq_addr addr; /* client/port number */
struct module *owner; /* owner of this port */
char name[64]; /* port name */
struct list_head list; /* port list */
snd_use_lock_t use_lock;
/* subscribers */
- port_subs_info_t c_src; /* read (sender) list */
- port_subs_info_t c_dest; /* write (dest) list */
+ struct snd_seq_port_subs_info c_src; /* read (sender) list */
+ struct snd_seq_port_subs_info c_dest; /* write (dest) list */
- snd_seq_kernel_port_input_t *event_input;
- snd_seq_kernel_port_private_free_t *private_free;
+ int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data,
+ int atomic, int hop);
+ void (*private_free)(void *private_data);
void *private_data;
unsigned int callback_all : 1;
unsigned int closing : 1;
@@ -87,42 +88,55 @@ typedef struct client_port_t {
int midi_voices;
int synth_voices;
-} client_port_t;
+};
+
+struct snd_seq_client;
/* return pointer to port structure and lock port */
-client_port_t *snd_seq_port_use_ptr(client_t *client, int num);
+struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, int num);
/* search for next port - port is locked if found */
-client_port_t *snd_seq_port_query_nearest(client_t *client, snd_seq_port_info_t *pinfo);
+struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
+ struct snd_seq_port_info *pinfo);
/* unlock the port */
#define snd_seq_port_unlock(port) snd_use_lock_free(&(port)->use_lock)
/* create a port, port number is returned (-1 on failure) */
-client_port_t *snd_seq_create_port(client_t *client, int port_index);
+struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, int port_index);
/* delete a port */
-int snd_seq_delete_port(client_t *client, int port);
+int snd_seq_delete_port(struct snd_seq_client *client, int port);
/* delete all ports */
-int snd_seq_delete_all_ports(client_t *client);
+int snd_seq_delete_all_ports(struct snd_seq_client *client);
/* set port info fields */
-int snd_seq_set_port_info(client_port_t *port, snd_seq_port_info_t *info);
+int snd_seq_set_port_info(struct snd_seq_client_port *port,
+ struct snd_seq_port_info *info);
/* get port info fields */
-int snd_seq_get_port_info(client_port_t *port, snd_seq_port_info_t *info);
+int snd_seq_get_port_info(struct snd_seq_client_port *port,
+ struct snd_seq_port_info *info);
/* add subscriber to subscription list */
-int snd_seq_port_connect(client_t *caller, client_t *s, client_port_t *sp, client_t *d, client_port_t *dp, snd_seq_port_subscribe_t *info);
+int snd_seq_port_connect(struct snd_seq_client *caller,
+ struct snd_seq_client *s, struct snd_seq_client_port *sp,
+ struct snd_seq_client *d, struct snd_seq_client_port *dp,
+ struct snd_seq_port_subscribe *info);
/* remove subscriber from subscription list */
-int snd_seq_port_disconnect(client_t *caller, client_t *s, client_port_t *sp, client_t *d, client_port_t *dp, snd_seq_port_subscribe_t *info);
+int snd_seq_port_disconnect(struct snd_seq_client *caller,
+ struct snd_seq_client *s, struct snd_seq_client_port *sp,
+ struct snd_seq_client *d, struct snd_seq_client_port *dp,
+ struct snd_seq_port_subscribe *info);
/* subscribe port */
-int snd_seq_port_subscribe(client_port_t *port, snd_seq_port_subscribe_t *info);
+int snd_seq_port_subscribe(struct snd_seq_client_port *port,
+ struct snd_seq_port_subscribe *info);
/* get matched subscriber */
-subscribers_t *snd_seq_port_get_subscription(port_subs_info_t *src_grp, snd_seq_addr_t *dest_addr);
+struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
+ struct snd_seq_addr *dest_addr);
#endif
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index cd641bca9945..074418617ee9 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -55,9 +55,9 @@
/* create new prioq (constructor) */
-prioq_t *snd_seq_prioq_new(void)
+struct snd_seq_prioq *snd_seq_prioq_new(void)
{
- prioq_t *f;
+ struct snd_seq_prioq *f;
f = kzalloc(sizeof(*f), GFP_KERNEL);
if (f == NULL) {
@@ -74,9 +74,9 @@ prioq_t *snd_seq_prioq_new(void)
}
/* delete prioq (destructor) */
-void snd_seq_prioq_delete(prioq_t **fifo)
+void snd_seq_prioq_delete(struct snd_seq_prioq **fifo)
{
- prioq_t *f = *fifo;
+ struct snd_seq_prioq *f = *fifo;
*fifo = NULL;
if (f == NULL) {
@@ -101,7 +101,8 @@ void snd_seq_prioq_delete(prioq_t **fifo)
/* compare timestamp between events */
/* return 1 if a >= b; 0 */
-static inline int compare_timestamp(snd_seq_event_t * a, snd_seq_event_t * b)
+static inline int compare_timestamp(struct snd_seq_event *a,
+ struct snd_seq_event *b)
{
if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
/* compare ticks */
@@ -117,7 +118,8 @@ static inline int compare_timestamp(snd_seq_event_t * a, snd_seq_event_t * b)
* zero if a = b;
* positive if a > b;
*/
-static inline int compare_timestamp_rel(snd_seq_event_t *a, snd_seq_event_t *b)
+static inline int compare_timestamp_rel(struct snd_seq_event *a,
+ struct snd_seq_event *b)
{
if ((a->flags & SNDRV_SEQ_TIME_STAMP_MASK) == SNDRV_SEQ_TIME_STAMP_TICK) {
/* compare ticks */
@@ -144,9 +146,10 @@ static inline int compare_timestamp_rel(snd_seq_event_t *a, snd_seq_event_t *b)
}
/* enqueue cell to prioq */
-int snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
+int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
+ struct snd_seq_event_cell * cell)
{
- snd_seq_event_cell_t *cur, *prev;
+ struct snd_seq_event_cell *cur, *prev;
unsigned long flags;
int count;
int prior;
@@ -215,9 +218,9 @@ int snd_seq_prioq_cell_in(prioq_t * f, snd_seq_event_cell_t * cell)
}
/* dequeue cell from prioq */
-snd_seq_event_cell_t *snd_seq_prioq_cell_out(prioq_t * f)
+struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f)
{
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
unsigned long flags;
if (f == NULL) {
@@ -243,7 +246,7 @@ snd_seq_event_cell_t *snd_seq_prioq_cell_out(prioq_t * f)
}
/* return number of events available in prioq */
-int snd_seq_prioq_avail(prioq_t * f)
+int snd_seq_prioq_avail(struct snd_seq_prioq * f)
{
if (f == NULL) {
snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
@@ -254,7 +257,7 @@ int snd_seq_prioq_avail(prioq_t * f)
/* peek at cell at the head of the prioq */
-snd_seq_event_cell_t *snd_seq_prioq_cell_peek(prioq_t * f)
+struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq * f)
{
if (f == NULL) {
snd_printd("oops: snd_seq_prioq_cell_in() called with NULL prioq\n");
@@ -264,7 +267,8 @@ snd_seq_event_cell_t *snd_seq_prioq_cell_peek(prioq_t * f)
}
-static inline int prioq_match(snd_seq_event_cell_t *cell, int client, int timestamp)
+static inline int prioq_match(struct snd_seq_event_cell *cell,
+ int client, int timestamp)
{
if (cell->event.source.client == client ||
cell->event.dest.client == client)
@@ -286,12 +290,12 @@ static inline int prioq_match(snd_seq_event_cell_t *cell, int client, int timest
}
/* remove cells for left client */
-void snd_seq_prioq_leave(prioq_t * f, int client, int timestamp)
+void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
{
- register snd_seq_event_cell_t *cell, *next;
+ register struct snd_seq_event_cell *cell, *next;
unsigned long flags;
- snd_seq_event_cell_t *prev = NULL;
- snd_seq_event_cell_t *freefirst = NULL, *freeprev = NULL, *freenext;
+ struct snd_seq_event_cell *prev = NULL;
+ struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
/* collect all removed cells */
spin_lock_irqsave(&f->lock, flags);
@@ -338,8 +342,8 @@ void snd_seq_prioq_leave(prioq_t * f, int client, int timestamp)
}
}
-static int prioq_remove_match(snd_seq_remove_events_t *info,
- snd_seq_event_t *ev)
+static int prioq_remove_match(struct snd_seq_remove_events *info,
+ struct snd_seq_event *ev)
{
int res;
@@ -394,13 +398,13 @@ static int prioq_remove_match(snd_seq_remove_events_t *info,
}
/* remove cells matching remove criteria */
-void snd_seq_prioq_remove_events(prioq_t * f, int client,
- snd_seq_remove_events_t *info)
+void snd_seq_prioq_remove_events(struct snd_seq_prioq * f, int client,
+ struct snd_seq_remove_events *info)
{
- register snd_seq_event_cell_t *cell, *next;
+ struct snd_seq_event_cell *cell, *next;
unsigned long flags;
- snd_seq_event_cell_t *prev = NULL;
- snd_seq_event_cell_t *freefirst = NULL, *freeprev = NULL, *freenext;
+ struct snd_seq_event_cell *prev = NULL;
+ struct snd_seq_event_cell *freefirst = NULL, *freeprev = NULL, *freenext;
/* collect all removed cells */
spin_lock_irqsave(&f->lock, flags);
diff --git a/sound/core/seq/seq_prioq.h b/sound/core/seq/seq_prioq.h
index f12af79308b8..d38bb78d9345 100644
--- a/sound/core/seq/seq_prioq.h
+++ b/sound/core/seq/seq_prioq.h
@@ -26,37 +26,37 @@
/* === PRIOQ === */
-typedef struct {
- snd_seq_event_cell_t* head; /* pointer to head of prioq */
- snd_seq_event_cell_t* tail; /* pointer to tail of prioq */
+struct snd_seq_prioq {
+ struct snd_seq_event_cell *head; /* pointer to head of prioq */
+ struct snd_seq_event_cell *tail; /* pointer to tail of prioq */
int cells;
spinlock_t lock;
-} prioq_t;
+};
/* create new prioq (constructor) */
-extern prioq_t *snd_seq_prioq_new(void);
+struct snd_seq_prioq *snd_seq_prioq_new(void);
/* delete prioq (destructor) */
-extern void snd_seq_prioq_delete(prioq_t **fifo);
+void snd_seq_prioq_delete(struct snd_seq_prioq **fifo);
/* enqueue cell to prioq */
-extern int snd_seq_prioq_cell_in(prioq_t *f, snd_seq_event_cell_t *cell);
+int snd_seq_prioq_cell_in(struct snd_seq_prioq *f, struct snd_seq_event_cell *cell);
/* dequeue cell from prioq */
-extern snd_seq_event_cell_t *snd_seq_prioq_cell_out(prioq_t *f);
+struct snd_seq_event_cell *snd_seq_prioq_cell_out(struct snd_seq_prioq *f);
/* return number of events available in prioq */
-extern int snd_seq_prioq_avail(prioq_t *f);
+int snd_seq_prioq_avail(struct snd_seq_prioq *f);
/* peek at cell at the head of the prioq */
-extern snd_seq_event_cell_t *snd_seq_prioq_cell_peek(prioq_t *f);
+struct snd_seq_event_cell *snd_seq_prioq_cell_peek(struct snd_seq_prioq *f);
/* client left queue */
-extern void snd_seq_prioq_leave(prioq_t *f, int client, int timestamp);
+void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp);
/* Remove events */
-void snd_seq_prioq_remove_events(prioq_t * f, int client,
- snd_seq_remove_events_t *info);
+void snd_seq_prioq_remove_events(struct snd_seq_prioq *f, int client,
+ struct snd_seq_remove_events *info);
#endif
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 5f5c3cb37cbf..9cf20f045542 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -29,7 +29,7 @@
* Aug. 30, 2000 Takashi Iwai
* - Queues are managed in static array again, but with better way.
* The API itself is identical.
- * - The queue is locked when queue_t pinter is returned via
+ * - The queue is locked when struct snd_seq_queue pointer is returned via
* queueptr(). This pointer *MUST* be released afterward by
* queuefree(ptr).
* - Addition of experimental sync support.
@@ -48,7 +48,7 @@
#include "seq_info.h"
/* list of allocated queues */
-static queue_t *queue_list[SNDRV_SEQ_MAX_QUEUES];
+static struct snd_seq_queue *queue_list[SNDRV_SEQ_MAX_QUEUES];
static DEFINE_SPINLOCK(queue_list_lock);
/* number of queues allocated */
static int num_queues;
@@ -61,7 +61,7 @@ int snd_seq_queue_get_cur_queues(void)
/*----------------------------------------------------------------*/
/* assign queue id and insert to list */
-static int queue_list_add(queue_t *q)
+static int queue_list_add(struct snd_seq_queue *q)
{
int i;
unsigned long flags;
@@ -80,9 +80,9 @@ static int queue_list_add(queue_t *q)
return -1;
}
-static queue_t *queue_list_remove(int id, int client)
+static struct snd_seq_queue *queue_list_remove(int id, int client)
{
- queue_t *q;
+ struct snd_seq_queue *q;
unsigned long flags;
spin_lock_irqsave(&queue_list_lock, flags);
@@ -107,9 +107,9 @@ static queue_t *queue_list_remove(int id, int client)
/*----------------------------------------------------------------*/
/* create new queue (constructor) */
-static queue_t *queue_new(int owner, int locked)
+static struct snd_seq_queue *queue_new(int owner, int locked)
{
- queue_t *q;
+ struct snd_seq_queue *q;
q = kzalloc(sizeof(*q), GFP_KERNEL);
if (q == NULL) {
@@ -142,7 +142,7 @@ static queue_t *queue_new(int owner, int locked)
}
/* delete queue (destructor) */
-static void queue_delete(queue_t *q)
+static void queue_delete(struct snd_seq_queue *q)
{
/* stop and release the timer */
snd_seq_timer_stop(q->timer);
@@ -187,7 +187,7 @@ void __exit snd_seq_queues_delete(void)
*/
int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
{
- queue_t *q;
+ struct snd_seq_queue *q;
q = queue_new(client, locked);
if (q == NULL)
@@ -204,7 +204,7 @@ int snd_seq_queue_alloc(int client, int locked, unsigned int info_flags)
/* delete a queue - queue must be owned by the client */
int snd_seq_queue_delete(int client, int queueid)
{
- queue_t *q;
+ struct snd_seq_queue *q;
if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES)
return -EINVAL;
@@ -218,9 +218,9 @@ int snd_seq_queue_delete(int client, int queueid)
/* return pointer to queue structure for specified id */
-queue_t *queueptr(int queueid)
+struct snd_seq_queue *queueptr(int queueid)
{
- queue_t *q;
+ struct snd_seq_queue *q;
unsigned long flags;
if (queueid < 0 || queueid >= SNDRV_SEQ_MAX_QUEUES)
@@ -234,10 +234,10 @@ queue_t *queueptr(int queueid)
}
/* return the (first) queue matching with the specified name */
-queue_t *snd_seq_queue_find_name(char *name)
+struct snd_seq_queue *snd_seq_queue_find_name(char *name)
{
int i;
- queue_t *q;
+ struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) != NULL) {
@@ -252,10 +252,10 @@ queue_t *snd_seq_queue_find_name(char *name)
/* -------------------------------------------------------- */
-void snd_seq_check_queue(queue_t *q, int atomic, int hop)
+void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
{
unsigned long flags;
- snd_seq_event_cell_t *cell;
+ struct snd_seq_event_cell *cell;
if (q == NULL)
return;
@@ -273,7 +273,8 @@ void snd_seq_check_queue(queue_t *q, int atomic, int hop)
__again:
/* Process tick queue... */
while ((cell = snd_seq_prioq_cell_peek(q->tickq)) != NULL) {
- if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick, &cell->event.time.tick)) {
+ if (snd_seq_compare_tick_time(&q->timer->tick.cur_tick,
+ &cell->event.time.tick)) {
cell = snd_seq_prioq_cell_out(q->tickq);
if (cell)
snd_seq_dispatch_event(cell, atomic, hop);
@@ -286,7 +287,8 @@ void snd_seq_check_queue(queue_t *q, int atomic, int hop)
/* Process time queue... */
while ((cell = snd_seq_prioq_cell_peek(q->timeq)) != NULL) {
- if (snd_seq_compare_real_time(&q->timer->cur_time, &cell->event.time.time)) {
+ if (snd_seq_compare_real_time(&q->timer->cur_time,
+ &cell->event.time.time)) {
cell = snd_seq_prioq_cell_out(q->timeq);
if (cell)
snd_seq_dispatch_event(cell, atomic, hop);
@@ -309,10 +311,10 @@ void snd_seq_check_queue(queue_t *q, int atomic, int hop)
/* enqueue a event to singe queue */
-int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop)
+int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop)
{
int dest, err;
- queue_t *q;
+ struct snd_seq_queue *q;
snd_assert(cell != NULL, return -EINVAL);
dest = cell->event.queue; /* destination queue */
@@ -327,7 +329,8 @@ int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop)
break;
case SNDRV_SEQ_TIME_STAMP_REAL:
- snd_seq_inc_real_time(&cell->event.time.time, &q->timer->cur_time);
+ snd_seq_inc_real_time(&cell->event.time.time,
+ &q->timer->cur_time);
break;
}
cell->event.flags &= ~SNDRV_SEQ_TIME_MODE_MASK;
@@ -361,7 +364,7 @@ int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop)
/*----------------------------------------------------------------*/
-static inline int check_access(queue_t *q, int client)
+static inline int check_access(struct snd_seq_queue *q, int client)
{
return (q->owner == client) || (!q->locked && !q->klocked);
}
@@ -369,7 +372,7 @@ static inline int check_access(queue_t *q, int client)
/* check if the client has permission to modify queue parameters.
* if it does, lock the queue
*/
-static int queue_access_lock(queue_t *q, int client)
+static int queue_access_lock(struct snd_seq_queue *q, int client)
{
unsigned long flags;
int access_ok;
@@ -383,7 +386,7 @@ static int queue_access_lock(queue_t *q, int client)
}
/* unlock the queue */
-static inline void queue_access_unlock(queue_t *q)
+static inline void queue_access_unlock(struct snd_seq_queue *q)
{
unsigned long flags;
@@ -395,7 +398,7 @@ static inline void queue_access_unlock(queue_t *q)
/* exported - only checking permission */
int snd_seq_queue_check_access(int queueid, int client)
{
- queue_t *q = queueptr(queueid);
+ struct snd_seq_queue *q = queueptr(queueid);
int access_ok;
unsigned long flags;
@@ -415,7 +418,7 @@ int snd_seq_queue_check_access(int queueid, int client)
*/
int snd_seq_queue_set_owner(int queueid, int client, int locked)
{
- queue_t *q = queueptr(queueid);
+ struct snd_seq_queue *q = queueptr(queueid);
if (q == NULL)
return -EINVAL;
@@ -443,8 +446,8 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
int snd_seq_queue_timer_open(int queueid)
{
int result = 0;
- queue_t *queue;
- seq_timer_t *tmr;
+ struct snd_seq_queue *queue;
+ struct snd_seq_timer *tmr;
queue = queueptr(queueid);
if (queue == NULL)
@@ -463,8 +466,8 @@ int snd_seq_queue_timer_open(int queueid)
*/
int snd_seq_queue_timer_close(int queueid)
{
- queue_t *queue;
- seq_timer_t *tmr;
+ struct snd_seq_queue *queue;
+ struct snd_seq_timer *tmr;
int result = 0;
queue = queueptr(queueid);
@@ -477,9 +480,10 @@ int snd_seq_queue_timer_close(int queueid)
}
/* change queue tempo and ppq */
-int snd_seq_queue_timer_set_tempo(int queueid, int client, snd_seq_queue_tempo_t *info)
+int snd_seq_queue_timer_set_tempo(int queueid, int client,
+ struct snd_seq_queue_tempo *info)
{
- queue_t *q = queueptr(queueid);
+ struct snd_seq_queue *q = queueptr(queueid);
int result;
if (q == NULL)
@@ -493,7 +497,8 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client, snd_seq_queue_tempo_t
if (result >= 0)
result = snd_seq_timer_set_ppq(q->timer, info->ppq);
if (result >= 0 && info->skew_base > 0)
- result = snd_seq_timer_set_skew(q->timer, info->skew_value, info->skew_base);
+ result = snd_seq_timer_set_skew(q->timer, info->skew_value,
+ info->skew_base);
queue_access_unlock(q);
queuefree(q);
return result;
@@ -506,7 +511,7 @@ int snd_seq_queue_timer_set_tempo(int queueid, int client, snd_seq_queue_tempo_t
*/
int snd_seq_queue_use(int queueid, int client, int use)
{
- queue_t *queue;
+ struct snd_seq_queue *queue;
queue = queueptr(queueid);
if (queue == NULL)
@@ -538,7 +543,7 @@ int snd_seq_queue_use(int queueid, int client, int use)
*/
int snd_seq_queue_is_used(int queueid, int client)
{
- queue_t *q;
+ struct snd_seq_queue *q;
int result;
q = queueptr(queueid);
@@ -559,7 +564,7 @@ void snd_seq_queue_client_termination(int client)
{
unsigned long flags;
int i;
- queue_t *q;
+ struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL)
@@ -584,7 +589,7 @@ void snd_seq_queue_client_termination(int client)
void snd_seq_queue_client_leave(int client)
{
int i;
- queue_t *q;
+ struct snd_seq_queue *q;
/* delete own queues from queue list */
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
@@ -615,7 +620,7 @@ void snd_seq_queue_client_leave(int client)
void snd_seq_queue_client_leave_cells(int client)
{
int i;
- queue_t *q;
+ struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL)
@@ -627,10 +632,10 @@ void snd_seq_queue_client_leave_cells(int client)
}
/* remove cells based on flush criteria */
-void snd_seq_queue_remove_cells(int client, snd_seq_remove_events_t *info)
+void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
{
int i;
- queue_t *q;
+ struct snd_seq_queue *q;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL)
@@ -650,9 +655,10 @@ void snd_seq_queue_remove_cells(int client, snd_seq_remove_events_t *info)
/*
* send events to all subscribed ports
*/
-static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
+static void queue_broadcast_event(struct snd_seq_queue *q, struct snd_seq_event *ev,
+ int atomic, int hop)
{
- snd_seq_event_t sev;
+ struct snd_seq_event sev;
sev = *ev;
@@ -672,7 +678,8 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i
* process a received queue-control event.
* this function is exported for seq_sync.c.
*/
-static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
+static void snd_seq_queue_process_event(struct snd_seq_queue *q,
+ struct snd_seq_event *ev,
int atomic, int hop)
{
switch (ev->type) {
@@ -724,9 +731,9 @@ static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
* Queue control via timer control port:
* this function is exported as a callback of timer port.
*/
-int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop)
+int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop)
{
- queue_t *q;
+ struct snd_seq_queue *q;
snd_assert(ev != NULL, return -EINVAL);
q = queueptr(ev->data.queue.queue);
@@ -749,13 +756,14 @@ int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop)
/*----------------------------------------------------------------*/
+#ifdef CONFIG_PROC_FS
/* exported to seq_info.c */
-void snd_seq_info_queues_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+void snd_seq_info_queues_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
int i, bpm;
- queue_t *q;
- seq_timer_t *tmr;
+ struct snd_seq_queue *q;
+ struct snd_seq_timer *tmr;
for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
if ((q = queueptr(i)) == NULL)
@@ -782,3 +790,5 @@ void snd_seq_info_queues_read(snd_info_entry_t *entry,
queuefree(q);
}
}
+#endif /* CONFIG_PROC_FS */
+
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index ea3c54216ea8..888438599387 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -30,15 +30,15 @@
#define SEQ_QUEUE_NO_OWNER (-1)
-struct _snd_seq_queue {
+struct snd_seq_queue {
int queue; /* queue number */
char name[64]; /* name of this queue */
- prioq_t *tickq; /* midi tick event queue */
- prioq_t *timeq; /* real-time event queue */
+ struct snd_seq_prioq *tickq; /* midi tick event queue */
+ struct snd_seq_prioq *timeq; /* real-time event queue */
- seq_timer_t *timer; /* time keeper for this queue */
+ struct snd_seq_timer *timer; /* time keeper for this queue */
int owner; /* client that 'owns' the timer */
unsigned int locked:1, /* timer is only accesibble by owner if set */
klocked:1, /* kernel lock (after START) */
@@ -83,26 +83,26 @@ void snd_seq_queue_client_termination(int client);
void snd_seq_queue_client_leave(int client);
/* enqueue a event received from one the clients */
-int snd_seq_enqueue_event(snd_seq_event_cell_t *cell, int atomic, int hop);
+int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop);
/* Remove events */
void snd_seq_queue_client_leave_cells(int client);
-void snd_seq_queue_remove_cells(int client, snd_seq_remove_events_t *info);
+void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info);
/* return pointer to queue structure for specified id */
-queue_t *queueptr(int queueid);
+struct snd_seq_queue *queueptr(int queueid);
/* unlock */
#define queuefree(q) snd_use_lock_free(&(q)->use_lock)
/* return the (first) queue matching with the specified name */
-queue_t *snd_seq_queue_find_name(char *name);
+struct snd_seq_queue *snd_seq_queue_find_name(char *name);
/* check single queue and dispatch events */
-void snd_seq_check_queue(queue_t *q, int atomic, int hop);
+void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop);
/* access to queue's parameters */
int snd_seq_queue_check_access(int queueid, int client);
-int snd_seq_queue_timer_set_tempo(int queueid, int client, snd_seq_queue_tempo_t *info);
+int snd_seq_queue_timer_set_tempo(int queueid, int client, struct snd_seq_queue_tempo *info);
int snd_seq_queue_set_owner(int queueid, int client, int locked);
int snd_seq_queue_set_locked(int queueid, int client, int locked);
int snd_seq_queue_timer_open(int queueid);
@@ -110,7 +110,7 @@ int snd_seq_queue_timer_close(int queueid);
int snd_seq_queue_use(int queueid, int client, int use);
int snd_seq_queue_is_used(int queueid, int client);
-int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
+int snd_seq_control_queue(struct snd_seq_event *ev, int atomic, int hop);
/*
* 64bit division - for sync stuff..
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index 0d9eff85ab88..b201b76e9412 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -66,12 +66,12 @@ static int announce_port = -1;
/* fill standard header data, source port & channel are filled in */
-static int setheader(snd_seq_event_t * ev, int client, int port)
+static int setheader(struct snd_seq_event * ev, int client, int port)
{
if (announce_port < 0)
return -ENODEV;
- memset(ev, 0, sizeof(snd_seq_event_t));
+ memset(ev, 0, sizeof(struct snd_seq_event));
ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
@@ -92,7 +92,7 @@ static int setheader(snd_seq_event_t * ev, int client, int port)
/* entry points for broadcasting system events */
void snd_seq_system_broadcast(int client, int port, int type)
{
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
if (setheader(&ev, client, port) < 0)
return;
@@ -101,7 +101,7 @@ void snd_seq_system_broadcast(int client, int port, int type)
}
/* entry points for broadcasting system events */
-int snd_seq_system_notify(int client, int port, snd_seq_event_t *ev)
+int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev)
{
ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
ev->source.client = sysclient;
@@ -112,7 +112,7 @@ int snd_seq_system_notify(int client, int port, snd_seq_event_t *ev)
}
/* call-back handler for timer events */
-static int event_input_timer(snd_seq_event_t * ev, int direct, void *private_data, int atomic, int hop)
+static int event_input_timer(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
{
return snd_seq_control_queue(ev, atomic, hop);
}
@@ -120,34 +120,19 @@ static int event_input_timer(snd_seq_event_t * ev, int direct, void *private_dat
/* register our internal client */
int __init snd_seq_system_client_init(void)
{
+ struct snd_seq_port_callback pcallbacks;
+ struct snd_seq_port_info *port;
- snd_seq_client_callback_t callbacks;
- snd_seq_port_callback_t pcallbacks;
- snd_seq_client_info_t *inf;
- snd_seq_port_info_t *port;
-
- inf = kzalloc(sizeof(*inf), GFP_KERNEL);
port = kzalloc(sizeof(*port), GFP_KERNEL);
- if (! inf || ! port) {
- kfree(inf);
- kfree(port);
+ if (!port)
return -ENOMEM;
- }
- memset(&callbacks, 0, sizeof(callbacks));
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
pcallbacks.event_input = event_input_timer;
/* register client */
- callbacks.allow_input = callbacks.allow_output = 1;
- sysclient = snd_seq_create_kernel_client(NULL, 0, &callbacks);
-
- /* set our name */
- inf->client = 0;
- inf->type = KERNEL_CLIENT;
- strcpy(inf->name, "System");
- snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, inf);
+ sysclient = snd_seq_create_kernel_client(NULL, 0, "System");
/* register timer */
strcpy(port->name, "Timer");
@@ -171,7 +156,6 @@ int __init snd_seq_system_client_init(void)
snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
announce_port = port->addr.port;
- kfree(inf);
kfree(port);
return 0;
}
diff --git a/sound/core/seq/seq_system.h b/sound/core/seq/seq_system.h
index 900007255bb4..cf2cfa23430e 100644
--- a/sound/core/seq/seq_system.h
+++ b/sound/core/seq/seq_system.h
@@ -34,7 +34,7 @@ void snd_seq_system_broadcast(int client, int port, int type);
#define snd_seq_system_client_ev_port_exit(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_EXIT)
#define snd_seq_system_client_ev_port_change(client, port) snd_seq_system_broadcast(client, port, SNDRV_SEQ_EVENT_PORT_CHANGE)
-int snd_seq_system_notify(int client, int port, snd_seq_event_t *ev);
+int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev);
/* register our internal client */
int snd_seq_system_client_init(void);
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 65b64a7c456d..b4b9a132cb16 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -41,7 +41,7 @@ extern int seq_default_timer_resolution;
#define SKEW_BASE 0x10000 /* 16bit shift */
-static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
+static void snd_seq_timer_set_tick_resolution(struct snd_seq_timer_tick *tick,
int tempo, int ppq)
{
if (tempo < 1000000)
@@ -60,9 +60,9 @@ static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
}
/* create new timer (constructor) */
-seq_timer_t *snd_seq_timer_new(void)
+struct snd_seq_timer *snd_seq_timer_new(void)
{
- seq_timer_t *tmr;
+ struct snd_seq_timer *tmr;
tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
if (tmr == NULL) {
@@ -81,9 +81,9 @@ seq_timer_t *snd_seq_timer_new(void)
}
/* delete timer (destructor) */
-void snd_seq_timer_delete(seq_timer_t **tmr)
+void snd_seq_timer_delete(struct snd_seq_timer **tmr)
{
- seq_timer_t *t = *tmr;
+ struct snd_seq_timer *t = *tmr;
*tmr = NULL;
if (t == NULL) {
@@ -99,7 +99,7 @@ void snd_seq_timer_delete(seq_timer_t **tmr)
kfree(t);
}
-void snd_seq_timer_defaults(seq_timer_t * tmr)
+void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
{
/* setup defaults */
tmr->ppq = 96; /* 96 PPQ */
@@ -118,7 +118,7 @@ void snd_seq_timer_defaults(seq_timer_t * tmr)
tmr->skew = tmr->skew_base = SKEW_BASE;
}
-void snd_seq_timer_reset(seq_timer_t * tmr)
+void snd_seq_timer_reset(struct snd_seq_timer * tmr)
{
unsigned long flags;
@@ -136,13 +136,13 @@ void snd_seq_timer_reset(seq_timer_t * tmr)
/* called by timer interrupt routine. the period time since previous invocation is passed */
-static void snd_seq_timer_interrupt(snd_timer_instance_t *timeri,
+static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
unsigned long resolution,
unsigned long ticks)
{
unsigned long flags;
- queue_t *q = (queue_t *)timeri->callback_data;
- seq_timer_t *tmr;
+ struct snd_seq_queue *q = timeri->callback_data;
+ struct snd_seq_timer *tmr;
if (q == NULL)
return;
@@ -177,7 +177,7 @@ static void snd_seq_timer_interrupt(snd_timer_instance_t *timeri,
}
/* set current tempo */
-int snd_seq_timer_set_tempo(seq_timer_t * tmr, int tempo)
+int snd_seq_timer_set_tempo(struct snd_seq_timer * tmr, int tempo)
{
unsigned long flags;
@@ -194,7 +194,7 @@ int snd_seq_timer_set_tempo(seq_timer_t * tmr, int tempo)
}
/* set current ppq */
-int snd_seq_timer_set_ppq(seq_timer_t * tmr, int ppq)
+int snd_seq_timer_set_ppq(struct snd_seq_timer * tmr, int ppq)
{
unsigned long flags;
@@ -217,7 +217,8 @@ int snd_seq_timer_set_ppq(seq_timer_t * tmr, int ppq)
}
/* set current tick position */
-int snd_seq_timer_set_position_tick(seq_timer_t *tmr, snd_seq_tick_time_t position)
+int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr,
+ snd_seq_tick_time_t position)
{
unsigned long flags;
@@ -231,7 +232,8 @@ int snd_seq_timer_set_position_tick(seq_timer_t *tmr, snd_seq_tick_time_t positi
}
/* set current real-time position */
-int snd_seq_timer_set_position_time(seq_timer_t *tmr, snd_seq_real_time_t position)
+int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr,
+ snd_seq_real_time_t position)
{
unsigned long flags;
@@ -245,7 +247,8 @@ int snd_seq_timer_set_position_time(seq_timer_t *tmr, snd_seq_real_time_t positi
}
/* set timer skew */
-int snd_seq_timer_set_skew(seq_timer_t *tmr, unsigned int skew, unsigned int base)
+int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew,
+ unsigned int base)
{
unsigned long flags;
@@ -262,10 +265,10 @@ int snd_seq_timer_set_skew(seq_timer_t *tmr, unsigned int skew, unsigned int bas
return 0;
}
-int snd_seq_timer_open(queue_t *q)
+int snd_seq_timer_open(struct snd_seq_queue *q)
{
- snd_timer_instance_t *t;
- seq_timer_t *tmr;
+ struct snd_timer_instance *t;
+ struct snd_seq_timer *tmr;
char str[32];
int err;
@@ -282,7 +285,7 @@ int snd_seq_timer_open(queue_t *q)
if (err < 0 && tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_SLAVE) {
if (tmr->alsa_id.dev_class != SNDRV_TIMER_CLASS_GLOBAL ||
tmr->alsa_id.device != SNDRV_TIMER_GLOBAL_SYSTEM) {
- snd_timer_id_t tid;
+ struct snd_timer_id tid;
memset(&tid, 0, sizeof(tid));
tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
tid.dev_sclass = SNDRV_TIMER_SCLASS_SEQUENCER;
@@ -302,9 +305,9 @@ int snd_seq_timer_open(queue_t *q)
return 0;
}
-int snd_seq_timer_close(queue_t *q)
+int snd_seq_timer_close(struct snd_seq_queue *q)
{
- seq_timer_t *tmr;
+ struct snd_seq_timer *tmr;
tmr = q->timer;
snd_assert(tmr != NULL, return -EINVAL);
@@ -316,7 +319,7 @@ int snd_seq_timer_close(queue_t *q)
return 0;
}
-int snd_seq_timer_stop(seq_timer_t * tmr)
+int snd_seq_timer_stop(struct snd_seq_timer * tmr)
{
if (! tmr->timeri)
return -EINVAL;
@@ -327,9 +330,9 @@ int snd_seq_timer_stop(seq_timer_t * tmr)
return 0;
}
-static int initialize_timer(seq_timer_t *tmr)
+static int initialize_timer(struct snd_seq_timer *tmr)
{
- snd_timer_t *t;
+ struct snd_timer *t;
unsigned long freq;
t = tmr->timeri->timer;
@@ -358,7 +361,7 @@ static int initialize_timer(seq_timer_t *tmr)
return 0;
}
-int snd_seq_timer_start(seq_timer_t * tmr)
+int snd_seq_timer_start(struct snd_seq_timer * tmr)
{
if (! tmr->timeri)
return -EINVAL;
@@ -373,7 +376,7 @@ int snd_seq_timer_start(seq_timer_t * tmr)
return 0;
}
-int snd_seq_timer_continue(seq_timer_t * tmr)
+int snd_seq_timer_continue(struct snd_seq_timer * tmr)
{
if (! tmr->timeri)
return -EINVAL;
@@ -391,7 +394,7 @@ int snd_seq_timer_continue(seq_timer_t * tmr)
}
/* return current 'real' time. use timeofday() to get better granularity. */
-snd_seq_real_time_t snd_seq_timer_get_cur_time(seq_timer_t *tmr)
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
{
snd_seq_real_time_t cur_time;
@@ -416,19 +419,21 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(seq_timer_t *tmr)
/* TODO: use interpolation on tick queue (will only be useful for very
high PPQ values) */
-snd_seq_tick_time_t snd_seq_timer_get_cur_tick(seq_timer_t *tmr)
+snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
{
return tmr->tick.cur_tick;
}
+#ifdef CONFIG_PROC_FS
/* exported to seq_info.c */
-void snd_seq_info_timer_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+void snd_seq_info_timer_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
int idx;
- queue_t *q;
- seq_timer_t *tmr;
- snd_timer_instance_t *ti;
+ struct snd_seq_queue *q;
+ struct snd_seq_timer *tmr;
+ struct snd_timer_instance *ti;
unsigned long resolution;
for (idx = 0; idx < SNDRV_SEQ_MAX_QUEUES; idx++) {
@@ -447,3 +452,5 @@ void snd_seq_info_timer_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer
queuefree(q);
}
}
+#endif /* CONFIG_PROC_FS */
+
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h
index 287ed68591de..e9ee1543c924 100644
--- a/sound/core/seq/seq_timer.h
+++ b/sound/core/seq/seq_timer.h
@@ -24,13 +24,13 @@
#include <sound/timer.h>
#include <sound/seq_kernel.h>
-typedef struct {
+struct snd_seq_timer_tick {
snd_seq_tick_time_t cur_tick; /* current tick */
unsigned long resolution; /* time per tick in nsec */
unsigned long fraction; /* current time per tick in nsec */
-} seq_timer_tick_t;
+};
-typedef struct {
+struct snd_seq_timer {
/* ... tempo / offset / running state */
unsigned int running:1, /* running state of queue */
@@ -40,12 +40,12 @@ typedef struct {
int ppq; /* time resolution, ticks/quarter */
snd_seq_real_time_t cur_time; /* current time */
- seq_timer_tick_t tick; /* current tick */
+ struct snd_seq_timer_tick tick; /* current tick */
int tick_updated;
int type; /* timer type */
- snd_timer_id_t alsa_id; /* ALSA's timer ID */
- snd_timer_instance_t *timeri; /* timer instance */
+ struct snd_timer_id alsa_id; /* ALSA's timer ID */
+ struct snd_timer_instance *timeri; /* timer instance */
unsigned int ticks;
unsigned long preferred_resolution; /* timer resolution, ticks/sec */
@@ -55,17 +55,18 @@ typedef struct {
struct timeval last_update; /* time of last clock update, used for interpolation */
spinlock_t lock;
-} seq_timer_t;
+};
/* create new timer (constructor) */
-extern seq_timer_t *snd_seq_timer_new(void);
+struct snd_seq_timer *snd_seq_timer_new(void);
/* delete timer (destructor) */
-extern void snd_seq_timer_delete(seq_timer_t **tmr);
+void snd_seq_timer_delete(struct snd_seq_timer **tmr);
/* */
-static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution)
+static inline void snd_seq_timer_update_tick(struct snd_seq_timer_tick *tick,
+ unsigned long resolution)
{
if (tick->resolution > 0) {
tick->fraction += resolution;
@@ -119,21 +120,22 @@ static inline void snd_seq_inc_time_nsec(snd_seq_real_time_t *tm, unsigned long
}
/* called by timer isr */
-int snd_seq_timer_open(queue_t *q);
-int snd_seq_timer_close(queue_t *q);
-int snd_seq_timer_midi_open(queue_t *q);
-int snd_seq_timer_midi_close(queue_t *q);
-void snd_seq_timer_defaults(seq_timer_t *tmr);
-void snd_seq_timer_reset(seq_timer_t *tmr);
-int snd_seq_timer_stop(seq_timer_t *tmr);
-int snd_seq_timer_start(seq_timer_t *tmr);
-int snd_seq_timer_continue(seq_timer_t *tmr);
-int snd_seq_timer_set_tempo(seq_timer_t *tmr, int tempo);
-int snd_seq_timer_set_ppq(seq_timer_t *tmr, int ppq);
-int snd_seq_timer_set_position_tick(seq_timer_t *tmr, snd_seq_tick_time_t position);
-int snd_seq_timer_set_position_time(seq_timer_t *tmr, snd_seq_real_time_t position);
-int snd_seq_timer_set_skew(seq_timer_t *tmr, unsigned int skew, unsigned int base);
-snd_seq_real_time_t snd_seq_timer_get_cur_time(seq_timer_t *tmr);
-snd_seq_tick_time_t snd_seq_timer_get_cur_tick(seq_timer_t *tmr);
+struct snd_seq_queue;
+int snd_seq_timer_open(struct snd_seq_queue *q);
+int snd_seq_timer_close(struct snd_seq_queue *q);
+int snd_seq_timer_midi_open(struct snd_seq_queue *q);
+int snd_seq_timer_midi_close(struct snd_seq_queue *q);
+void snd_seq_timer_defaults(struct snd_seq_timer *tmr);
+void snd_seq_timer_reset(struct snd_seq_timer *tmr);
+int snd_seq_timer_stop(struct snd_seq_timer *tmr);
+int snd_seq_timer_start(struct snd_seq_timer *tmr);
+int snd_seq_timer_continue(struct snd_seq_timer *tmr);
+int snd_seq_timer_set_tempo(struct snd_seq_timer *tmr, int tempo);
+int snd_seq_timer_set_ppq(struct snd_seq_timer *tmr, int ppq);
+int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
+int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
+int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr);
+snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
#endif
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index e4f512aa7426..14fd1a608e14 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -56,7 +56,8 @@ MODULE_LICENSE("GPL");
/*
* initialize an event record
*/
-static void snd_virmidi_init_event(snd_virmidi_t *vmidi, snd_seq_event_t *ev)
+static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
+ struct snd_seq_event *ev)
{
memset(ev, 0, sizeof(*ev));
ev->source.port = vmidi->port;
@@ -76,16 +77,17 @@ static void snd_virmidi_init_event(snd_virmidi_t *vmidi, snd_seq_event_t *ev)
/*
* decode input event and put to read buffer of each opened file
*/
-static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_t *ev)
+static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
+ struct snd_seq_event *ev)
{
- snd_virmidi_t *vmidi;
+ struct snd_virmidi *vmidi;
struct list_head *list;
unsigned char msg[4];
int len;
read_lock(&rdev->filelist_lock);
list_for_each(list, &rdev->filelist) {
- vmidi = list_entry(list, snd_virmidi_t, list);
+ vmidi = list_entry(list, struct snd_virmidi, list);
if (!vmidi->trigger)
continue;
if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
@@ -111,9 +113,9 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
* SNDRV_VIRMIDI_SEQ_ATTACH.
*/
#if 0
-int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
+int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = rmidi->private_data;
return snd_virmidi_dev_receive_event(rdev, ev);
@@ -123,10 +125,10 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
/*
* event handler of virmidi port
*/
-static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
+static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = private_data;
if (!(rdev->flags & SNDRV_VIRMIDI_USE))
@@ -137,9 +139,9 @@ static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
/*
* trigger rawmidi stream for input
*/
-static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_virmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- snd_virmidi_t *vmidi = substream->runtime->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
if (up) {
vmidi->trigger = 1;
@@ -151,9 +153,9 @@ static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int u
/*
* trigger rawmidi stream for output
*/
-static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- snd_virmidi_t *vmidi = substream->runtime->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
int count, res;
unsigned char buf[32], *pbuf;
@@ -198,11 +200,11 @@ static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int
/*
* open rawmidi handle for input
*/
-static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream)
{
- snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
- snd_virmidi_t *vmidi;
+ struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ struct snd_virmidi *vmidi;
unsigned long flags;
vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
@@ -227,11 +229,11 @@ static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
/*
* open rawmidi handle for output
*/
-static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
{
- snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
- snd_rawmidi_runtime_t *runtime = substream->runtime;
- snd_virmidi_t *vmidi;
+ struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ struct snd_virmidi *vmidi;
vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL);
if (vmidi == NULL)
@@ -253,9 +255,9 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
/*
* close rawmidi handle for input
*/
-static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
{
- snd_virmidi_t *vmidi = substream->runtime->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
snd_midi_event_free(vmidi->parser);
list_del(&vmidi->list);
substream->runtime->private_data = NULL;
@@ -266,9 +268,9 @@ static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
/*
* close rawmidi handle for output
*/
-static int snd_virmidi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_virmidi_output_close(struct snd_rawmidi_substream *substream)
{
- snd_virmidi_t *vmidi = substream->runtime->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
snd_midi_event_free(vmidi->parser);
substream->runtime->private_data = NULL;
kfree(vmidi);
@@ -278,9 +280,10 @@ static int snd_virmidi_output_close(snd_rawmidi_substream_t * substream)
/*
* subscribe callback - allow output to rawmidi device
*/
-static int snd_virmidi_subscribe(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_virmidi_subscribe(void *private_data,
+ struct snd_seq_port_subscribe *info)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = private_data;
if (!try_module_get(rdev->card->module))
@@ -292,9 +295,10 @@ static int snd_virmidi_subscribe(void *private_data, snd_seq_port_subscribe_t *i
/*
* unsubscribe callback - disallow output to rawmidi device
*/
-static int snd_virmidi_unsubscribe(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_virmidi_unsubscribe(void *private_data,
+ struct snd_seq_port_subscribe *info)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = private_data;
rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
@@ -306,9 +310,10 @@ static int snd_virmidi_unsubscribe(void *private_data, snd_seq_port_subscribe_t
/*
* use callback - allow input to rawmidi device
*/
-static int snd_virmidi_use(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_virmidi_use(void *private_data,
+ struct snd_seq_port_subscribe *info)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = private_data;
if (!try_module_get(rdev->card->module))
@@ -320,9 +325,10 @@ static int snd_virmidi_use(void *private_data, snd_seq_port_subscribe_t *info)
/*
* unuse callback - disallow input to rawmidi device
*/
-static int snd_virmidi_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_virmidi_unuse(void *private_data,
+ struct snd_seq_port_subscribe *info)
{
- snd_virmidi_dev_t *rdev;
+ struct snd_virmidi_dev *rdev;
rdev = private_data;
rdev->flags &= ~SNDRV_VIRMIDI_USE;
@@ -335,13 +341,13 @@ static int snd_virmidi_unuse(void *private_data, snd_seq_port_subscribe_t *info)
* Register functions
*/
-static snd_rawmidi_ops_t snd_virmidi_input_ops = {
+static struct snd_rawmidi_ops snd_virmidi_input_ops = {
.open = snd_virmidi_input_open,
.close = snd_virmidi_input_close,
.trigger = snd_virmidi_input_trigger,
};
-static snd_rawmidi_ops_t snd_virmidi_output_ops = {
+static struct snd_rawmidi_ops snd_virmidi_output_ops = {
.open = snd_virmidi_output_open,
.close = snd_virmidi_output_close,
.trigger = snd_virmidi_output_trigger,
@@ -350,43 +356,32 @@ static snd_rawmidi_ops_t snd_virmidi_output_ops = {
/*
* create a sequencer client and a port
*/
-static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
+static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev)
{
int client;
- snd_seq_client_callback_t callbacks;
- snd_seq_port_callback_t pcallbacks;
- snd_seq_client_info_t *info;
- snd_seq_port_info_t *pinfo;
+ struct snd_seq_port_callback pcallbacks;
+ struct snd_seq_port_info *pinfo;
int err;
if (rdev->client >= 0)
return 0;
- info = kmalloc(sizeof(*info), GFP_KERNEL);
pinfo = kmalloc(sizeof(*pinfo), GFP_KERNEL);
- if (! info || ! pinfo) {
+ if (!pinfo) {
err = -ENOMEM;
goto __error;
}
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = rdev;
- callbacks.allow_input = 1;
- callbacks.allow_output = 1;
- client = snd_seq_create_kernel_client(rdev->card, rdev->device, &callbacks);
+ client = snd_seq_create_kernel_client(rdev->card, rdev->device,
+ "%s %d-%d", rdev->rmidi->name,
+ rdev->card->number,
+ rdev->device);
if (client < 0) {
err = client;
goto __error;
}
rdev->client = client;
- /* set client name */
- memset(info, 0, sizeof(*info));
- info->client = client;
- info->type = KERNEL_CLIENT;
- sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
-
/* create a port */
memset(pinfo, 0, sizeof(*pinfo));
pinfo->addr.client = client;
@@ -417,7 +412,6 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
err = 0; /* success */
__error:
- kfree(info);
kfree(pinfo);
return err;
}
@@ -426,7 +420,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
/*
* release the sequencer client
*/
-static void snd_virmidi_dev_detach_seq(snd_virmidi_dev_t *rdev)
+static void snd_virmidi_dev_detach_seq(struct snd_virmidi_dev *rdev)
{
if (rdev->client >= 0) {
snd_seq_delete_kernel_client(rdev->client);
@@ -437,9 +431,9 @@ static void snd_virmidi_dev_detach_seq(snd_virmidi_dev_t *rdev)
/*
* register the device
*/
-static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
+static int snd_virmidi_dev_register(struct snd_rawmidi *rmidi)
{
- snd_virmidi_dev_t *rdev = rmidi->private_data;
+ struct snd_virmidi_dev *rdev = rmidi->private_data;
int err;
switch (rdev->seq_mode) {
@@ -464,9 +458,9 @@ static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
/*
* unregister the device
*/
-static int snd_virmidi_dev_unregister(snd_rawmidi_t *rmidi)
+static int snd_virmidi_dev_unregister(struct snd_rawmidi *rmidi)
{
- snd_virmidi_dev_t *rdev = rmidi->private_data;
+ struct snd_virmidi_dev *rdev = rmidi->private_data;
if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
snd_virmidi_dev_detach_seq(rdev);
@@ -476,7 +470,7 @@ static int snd_virmidi_dev_unregister(snd_rawmidi_t *rmidi)
/*
*
*/
-static snd_rawmidi_global_ops_t snd_virmidi_global_ops = {
+static struct snd_rawmidi_global_ops snd_virmidi_global_ops = {
.dev_register = snd_virmidi_dev_register,
.dev_unregister = snd_virmidi_dev_unregister,
};
@@ -484,9 +478,9 @@ static snd_rawmidi_global_ops_t snd_virmidi_global_ops = {
/*
* free device
*/
-static void snd_virmidi_free(snd_rawmidi_t *rmidi)
+static void snd_virmidi_free(struct snd_rawmidi *rmidi)
{
- snd_virmidi_dev_t *rdev = rmidi->private_data;
+ struct snd_virmidi_dev *rdev = rmidi->private_data;
kfree(rdev);
}
@@ -495,10 +489,10 @@ static void snd_virmidi_free(snd_rawmidi_t *rmidi)
*
*/
/* exported */
-int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
+int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmidi)
{
- snd_rawmidi_t *rmidi;
- snd_virmidi_dev_t *rdev;
+ struct snd_rawmidi *rmidi;
+ struct snd_virmidi_dev *rdev;
int err;
*rrmidi = NULL;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 6e7cad1e947e..a8eda02bcf1c 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/device.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/minors.h>
@@ -32,7 +33,6 @@
#include <sound/initval.h>
#include <linux/kmod.h>
#include <linux/devfs_fs_kernel.h>
-#include <linux/platform_device.h>
#define SNDRV_OS_MINORS 256
@@ -60,8 +60,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
*/
int snd_ecards_limit;
-static struct list_head snd_minors_hash[SNDRV_CARDS];
-
+static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DECLARE_MUTEX(sound_mutex);
extern struct class *sound_class;
@@ -108,44 +107,61 @@ static void snd_request_other(int minor)
#endif /* request_module support */
-static snd_minor_t *snd_minor_search(int minor)
+/**
+ * snd_lookup_minor_data - get user data of a registered device
+ * @minor: the minor number
+ * @type: device type (SNDRV_DEVICE_TYPE_XXX)
+ *
+ * Checks that a minor device with the specified type is registered, and returns
+ * its user data pointer.
+ */
+void *snd_lookup_minor_data(unsigned int minor, int type)
{
- struct list_head *list;
- snd_minor_t *mptr;
+ struct snd_minor *mreg;
+ void *private_data;
- list_for_each(list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]) {
- mptr = list_entry(list, snd_minor_t, list);
- if (mptr->number == minor)
- return mptr;
- }
- return NULL;
+ if (minor > ARRAY_SIZE(snd_minors))
+ return NULL;
+ down(&sound_mutex);
+ mreg = snd_minors[minor];
+ if (mreg && mreg->type == type)
+ private_data = mreg->private_data;
+ else
+ private_data = NULL;
+ up(&sound_mutex);
+ return private_data;
}
static int snd_open(struct inode *inode, struct file *file)
{
- int minor = iminor(inode);
- int card = SNDRV_MINOR_CARD(minor);
- int dev = SNDRV_MINOR_DEVICE(minor);
- snd_minor_t *mptr = NULL;
+ unsigned int minor = iminor(inode);
+ struct snd_minor *mptr = NULL;
struct file_operations *old_fops;
int err = 0;
- if (dev != SNDRV_MINOR_GLOBAL) {
- if (snd_cards[card] == NULL) {
+ if (minor > ARRAY_SIZE(snd_minors))
+ return -ENODEV;
+ mptr = snd_minors[minor];
+ if (mptr == NULL) {
#ifdef CONFIG_KMOD
- snd_request_card(card);
+ int dev = SNDRV_MINOR_DEVICE(minor);
+ if (dev == SNDRV_MINOR_CONTROL) {
+ /* /dev/aloadC? */
+ int card = SNDRV_MINOR_CARD(minor);
if (snd_cards[card] == NULL)
-#endif
- return -ENODEV;
- }
- } else {
-#ifdef CONFIG_KMOD
- if ((mptr = snd_minor_search(minor)) == NULL)
+ snd_request_card(card);
+ } else if (dev == SNDRV_MINOR_GLOBAL) {
+ /* /dev/aloadSEQ */
snd_request_other(minor);
+ }
+#ifndef CONFIG_SND_DYNAMIC_MINORS
+ /* /dev/snd/{controlC?,seq} */
+ mptr = snd_minors[minor];
+ if (mptr == NULL)
#endif
+#endif
+ return -ENODEV;
}
- if (mptr == NULL && (mptr = snd_minor_search(minor)) == NULL)
- return -ENODEV;
old_fops = file->f_op;
file->f_op = fops_get(mptr->f_ops);
if (file->f_op->open)
@@ -164,7 +180,23 @@ static struct file_operations snd_fops =
.open = snd_open
};
-static int snd_kernel_minor(int type, snd_card_t * card, int dev)
+#ifdef CONFIG_SND_DYNAMIC_MINORS
+static int snd_find_free_minor(void)
+{
+ int minor;
+
+ for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {
+ /* skip minors still used statically for autoloading devices */
+ if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL ||
+ minor == SNDRV_MINOR_SEQUENCER)
+ continue;
+ if (!snd_minors[minor])
+ return minor;
+ }
+ return -EBUSY;
+}
+#else
+static int snd_kernel_minor(int type, struct snd_card *card, int dev)
{
int minor;
@@ -190,13 +222,15 @@ static int snd_kernel_minor(int type, snd_card_t * card, int dev)
snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
return minor;
}
+#endif
/**
* snd_register_device - Register the ALSA device file for the card
* @type: the device type, SNDRV_DEVICE_TYPE_XXX
* @card: the card instance
* @dev: the device index
- * @reg: the snd_minor_t record
+ * @f_ops: the file operations
+ * @private_data: user pointer for f_ops->open()
* @name: the device file name
*
* Registers an ALSA device file for the given card.
@@ -204,30 +238,39 @@ static int snd_kernel_minor(int type, snd_card_t * card, int dev)
*
* Retrurns zero if successful, or a negative error code on failure.
*/
-int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, const char *name)
+int snd_register_device(int type, struct snd_card *card, int dev,
+ struct file_operations *f_ops, void *private_data,
+ const char *name)
{
- int minor = snd_kernel_minor(type, card, dev);
- snd_minor_t *preg;
+ int minor;
+ struct snd_minor *preg;
struct device *device = NULL;
- if (minor < 0)
- return minor;
snd_assert(name, return -EINVAL);
- preg = (snd_minor_t *)kmalloc(sizeof(snd_minor_t) + strlen(name) + 1, GFP_KERNEL);
+ preg = kmalloc(sizeof(struct snd_minor) + strlen(name) + 1, GFP_KERNEL);
if (preg == NULL)
return -ENOMEM;
- *preg = *reg;
- preg->number = minor;
+ preg->type = type;
+ preg->card = card ? card->number : -1;
preg->device = dev;
+ preg->f_ops = f_ops;
+ preg->private_data = private_data;
strcpy(preg->name, name);
down(&sound_mutex);
- if (snd_minor_search(minor)) {
+#ifdef CONFIG_SND_DYNAMIC_MINORS
+ minor = snd_find_free_minor();
+#else
+ minor = snd_kernel_minor(type, card, dev);
+ if (minor >= 0 && snd_minors[minor])
+ minor = -EBUSY;
+#endif
+ if (minor < 0) {
up(&sound_mutex);
kfree(preg);
- return -EBUSY;
+ return minor;
}
- list_add_tail(&preg->list, &snd_minors_hash[SNDRV_MINOR_CARD(minor)]);
- if (strncmp(name, "controlC", 8) || card->number >= cards_limit)
+ snd_minors[minor] = preg;
+ if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit)
devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
if (card)
device = card->dev;
@@ -248,61 +291,92 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg,
*
* Returns zero if sucecessful, or a negative error code on failure
*/
-int snd_unregister_device(int type, snd_card_t * card, int dev)
+int snd_unregister_device(int type, struct snd_card *card, int dev)
{
- int minor = snd_kernel_minor(type, card, dev);
- snd_minor_t *mptr;
+ int cardnum, minor;
+ struct snd_minor *mptr;
- if (minor < 0)
- return minor;
+ cardnum = card ? card->number : -1;
down(&sound_mutex);
- if ((mptr = snd_minor_search(minor)) == NULL) {
+ for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
+ if ((mptr = snd_minors[minor]) != NULL &&
+ mptr->type == type &&
+ mptr->card == cardnum &&
+ mptr->device == dev)
+ break;
+ if (minor == ARRAY_SIZE(snd_minors)) {
up(&sound_mutex);
return -EINVAL;
}
- if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */
+ if (mptr->type != SNDRV_DEVICE_TYPE_CONTROL ||
+ mptr->card >= cards_limit) /* created in sound.c */
devfs_remove("snd/%s", mptr->name);
class_device_destroy(sound_class, MKDEV(major, minor));
- list_del(&mptr->list);
+ snd_minors[minor] = NULL;
up(&sound_mutex);
kfree(mptr);
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* INFO PART
*/
-static snd_info_entry_t *snd_minor_info_entry = NULL;
+static struct snd_info_entry *snd_minor_info_entry = NULL;
+
+static const char *snd_device_type_name(int type)
+{
+ switch (type) {
+ case SNDRV_DEVICE_TYPE_CONTROL:
+ return "control";
+ case SNDRV_DEVICE_TYPE_HWDEP:
+ return "hardware dependent";
+ case SNDRV_DEVICE_TYPE_RAWMIDI:
+ return "raw midi";
+ case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
+ return "digital audio playback";
+ case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
+ return "digital audio capture";
+ case SNDRV_DEVICE_TYPE_SEQUENCER:
+ return "sequencer";
+ case SNDRV_DEVICE_TYPE_TIMER:
+ return "timer";
+ default:
+ return "?";
+ }
+}
-static void snd_minor_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_minor_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- int card, device;
- struct list_head *list;
- snd_minor_t *mptr;
+ int minor;
+ struct snd_minor *mptr;
down(&sound_mutex);
- for (card = 0; card < SNDRV_CARDS; card++) {
- list_for_each(list, &snd_minors_hash[card]) {
- mptr = list_entry(list, snd_minor_t, list);
- if (SNDRV_MINOR_DEVICE(mptr->number) != SNDRV_MINOR_GLOBAL) {
- if ((device = mptr->device) >= 0)
- snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, device, mptr->comment);
- else
- snd_iprintf(buffer, "%3i: [%i] : %s\n", mptr->number, card, mptr->comment);
- } else {
- snd_iprintf(buffer, "%3i: : %s\n", mptr->number, mptr->comment);
- }
- }
+ for (minor = 0; minor < SNDRV_OS_MINORS; ++minor) {
+ if (!(mptr = snd_minors[minor]))
+ continue;
+ if (mptr->card >= 0) {
+ if (mptr->device >= 0)
+ snd_iprintf(buffer, "%3i: [%2i-%2i]: %s\n",
+ minor, mptr->card, mptr->device,
+ snd_device_type_name(mptr->type));
+ else
+ snd_iprintf(buffer, "%3i: [%2i] : %s\n",
+ minor, mptr->card,
+ snd_device_type_name(mptr->type));
+ } else
+ snd_iprintf(buffer, "%3i: : %s\n", minor,
+ snd_device_type_name(mptr->type));
}
up(&sound_mutex);
}
int __init snd_minor_info_init(void)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
if (entry) {
@@ -323,27 +397,18 @@ int __exit snd_minor_info_done(void)
snd_info_unregister(snd_minor_info_entry);
return 0;
}
+#endif /* CONFIG_PROC_FS */
/*
* INIT PART
*/
-#ifdef CONFIG_SND_GENERIC_DRIVER
-extern struct platform_driver snd_generic_driver;
-#endif
-
static int __init alsa_sound_init(void)
{
short controlnum;
- int err;
- int card;
snd_major = major;
snd_ecards_limit = cards_limit;
- for (card = 0; card < SNDRV_CARDS; card++)
- INIT_LIST_HEAD(&snd_minors_hash[card]);
- if ((err = snd_oss_init_module()) < 0)
- return err;
devfs_mk_dir("snd");
if (register_chrdev(major, "alsa", &snd_fops)) {
snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
@@ -356,9 +421,6 @@ static int __init alsa_sound_init(void)
return -ENOMEM;
}
snd_info_minor_register();
-#ifdef CONFIG_SND_GENERIC_DRIVER
- platform_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
@@ -374,9 +436,6 @@ 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
- platform_driver_unregister(&snd_generic_driver);
-#endif
snd_info_minor_unregister();
snd_info_done();
if (unregister_chrdev(major, "alsa") != 0)
@@ -395,9 +454,11 @@ EXPORT_SYMBOL(snd_request_card);
#endif
EXPORT_SYMBOL(snd_register_device);
EXPORT_SYMBOL(snd_unregister_device);
+EXPORT_SYMBOL(snd_lookup_minor_data);
#if defined(CONFIG_SND_OSSEMUL)
EXPORT_SYMBOL(snd_register_oss_device);
EXPORT_SYMBOL(snd_unregister_oss_device);
+EXPORT_SYMBOL(snd_lookup_oss_minor_data);
#endif
/* memory.c */
EXPORT_SYMBOL(copy_to_user_fromio);
@@ -415,19 +476,8 @@ 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);
-#ifdef CONFIG_SND_GENERIC_DRIVER
-EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
-#endif
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(snd_card_pci_suspend);
-EXPORT_SYMBOL(snd_card_pci_resume);
-#endif
#endif
/* device.c */
EXPORT_SYMBOL(snd_device_new);
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index e401c6703297..d0be32b517c1 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -35,26 +35,29 @@
#include <sound/info.h>
#include <linux/sound.h>
-#define SNDRV_OS_MINORS 256
-
-static struct list_head snd_oss_minors_hash[SNDRV_CARDS];
+#define SNDRV_OSS_MINORS 128
+static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
static DECLARE_MUTEX(sound_oss_mutex);
-static snd_minor_t *snd_oss_minor_search(int minor)
+void *snd_lookup_oss_minor_data(unsigned int minor, int type)
{
- struct list_head *list;
- snd_minor_t *mptr;
+ struct snd_minor *mreg;
+ void *private_data;
- list_for_each(list, &snd_oss_minors_hash[SNDRV_MINOR_OSS_CARD(minor)]) {
- mptr = list_entry(list, snd_minor_t, list);
- if (mptr->number == minor)
- return mptr;
- }
- return NULL;
+ if (minor > ARRAY_SIZE(snd_oss_minors))
+ return NULL;
+ down(&sound_oss_mutex);
+ mreg = snd_oss_minors[minor];
+ if (mreg && mreg->type == type)
+ private_data = mreg->private_data;
+ else
+ private_data = NULL;
+ up(&sound_oss_mutex);
+ return private_data;
}
-static int snd_oss_kernel_minor(int type, snd_card_t * card, int dev)
+static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
{
int minor;
@@ -86,30 +89,36 @@ static int snd_oss_kernel_minor(int type, snd_card_t * card, int dev)
default:
return -EINVAL;
}
- snd_assert(minor >= 0 && minor < SNDRV_OS_MINORS, return -EINVAL);
+ snd_assert(minor >= 0 && minor < SNDRV_OSS_MINORS, return -EINVAL);
return minor;
}
-int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t * reg, const char *name)
+int snd_register_oss_device(int type, struct snd_card *card, int dev,
+ struct file_operations *f_ops, void *private_data,
+ const char *name)
{
int minor = snd_oss_kernel_minor(type, card, dev);
int minor_unit;
- snd_minor_t *preg;
+ struct snd_minor *preg;
int cidx = SNDRV_MINOR_OSS_CARD(minor);
int track2 = -1;
int register1 = -1, register2 = -1;
struct device *carddev = NULL;
+ if (card && card->number >= 8)
+ return 0; /* ignore silently */
if (minor < 0)
return minor;
- preg = (snd_minor_t *)kmalloc(sizeof(snd_minor_t), GFP_KERNEL);
+ preg = kmalloc(sizeof(struct snd_minor), GFP_KERNEL);
if (preg == NULL)
return -ENOMEM;
- *preg = *reg;
- preg->number = minor;
+ preg->type = type;
+ preg->card = card ? card->number : -1;
preg->device = dev;
+ preg->f_ops = f_ops;
+ preg->private_data = private_data;
down(&sound_oss_mutex);
- list_add_tail(&preg->list, &snd_oss_minors_hash[cidx]);
+ snd_oss_minors[minor] = preg;
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
switch (minor_unit) {
case SNDRV_MINOR_OSS_PCM:
@@ -124,13 +133,15 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
}
if (card)
carddev = card->dev;
- register1 = register_sound_special_device(reg->f_ops, minor, carddev);
+ register1 = register_sound_special_device(f_ops, minor, carddev);
if (register1 != minor)
goto __end;
if (track2 >= 0) {
- register2 = register_sound_special_device(reg->f_ops, track2, carddev);
+ register2 = register_sound_special_device(f_ops, track2,
+ carddev);
if (register2 != track2)
goto __end;
+ snd_oss_minors[track2] = preg;
}
up(&sound_oss_mutex);
return 0;
@@ -140,23 +151,25 @@ int snd_register_oss_device(int type, snd_card_t * card, int dev, snd_minor_t *
unregister_sound_special(register2);
if (register1 >= 0)
unregister_sound_special(register1);
- list_del(&preg->list);
+ snd_oss_minors[minor] = NULL;
up(&sound_oss_mutex);
kfree(preg);
return -EBUSY;
}
-int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
+int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
{
int minor = snd_oss_kernel_minor(type, card, dev);
int cidx = SNDRV_MINOR_OSS_CARD(minor);
int track2 = -1;
- snd_minor_t *mptr;
+ struct snd_minor *mptr;
+ if (card && card->number >= 8)
+ return 0;
if (minor < 0)
return minor;
down(&sound_oss_mutex);
- mptr = snd_oss_minor_search(minor);
+ mptr = snd_oss_minors[minor];
if (mptr == NULL) {
up(&sound_oss_mutex);
return -ENOENT;
@@ -173,9 +186,11 @@ int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break;
}
- if (track2 >= 0)
+ if (track2 >= 0) {
unregister_sound_special(track2);
- list_del(&mptr->list);
+ snd_oss_minors[track2] = NULL;
+ }
+ snd_oss_minors[minor] = NULL;
up(&sound_oss_mutex);
kfree(mptr);
return 0;
@@ -187,36 +202,52 @@ int snd_unregister_oss_device(int type, snd_card_t * card, int dev)
#ifdef CONFIG_PROC_FS
-static snd_info_entry_t *snd_minor_info_oss_entry = NULL;
+static struct snd_info_entry *snd_minor_info_oss_entry = NULL;
+
+static const char *snd_oss_device_type_name(int type)
+{
+ switch (type) {
+ case SNDRV_OSS_DEVICE_TYPE_MIXER:
+ return "mixer";
+ case SNDRV_OSS_DEVICE_TYPE_SEQUENCER:
+ case SNDRV_OSS_DEVICE_TYPE_MUSIC:
+ return "sequencer";
+ case SNDRV_OSS_DEVICE_TYPE_PCM:
+ return "digital audio";
+ case SNDRV_OSS_DEVICE_TYPE_MIDI:
+ return "raw midi";
+ case SNDRV_OSS_DEVICE_TYPE_DMFM:
+ return "hardware dependent";
+ default:
+ return "?";
+ }
+}
-static void snd_minor_info_oss_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_minor_info_oss_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- int card, dev;
- struct list_head *list;
- snd_minor_t *mptr;
+ int minor;
+ struct snd_minor *mptr;
down(&sound_oss_mutex);
- for (card = 0; card < SNDRV_CARDS; card++) {
- list_for_each(list, &snd_oss_minors_hash[card]) {
- mptr = list_entry(list, snd_minor_t, list);
- dev = SNDRV_MINOR_OSS_DEVICE(mptr->number);
- if (dev != SNDRV_MINOR_OSS_SNDSTAT &&
- dev != SNDRV_MINOR_OSS_SEQUENCER &&
- dev != SNDRV_MINOR_OSS_MUSIC)
- snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", mptr->number, card, dev, mptr->comment);
- else
- snd_iprintf(buffer, "%3i: : %s\n", mptr->number, mptr->comment);
- }
+ for (minor = 0; minor < SNDRV_OSS_MINORS; ++minor) {
+ if (!(mptr = snd_oss_minors[minor]))
+ continue;
+ if (mptr->card >= 0)
+ snd_iprintf(buffer, "%3i: [%i-%2i]: %s\n", minor,
+ mptr->card, mptr->device,
+ snd_oss_device_type_name(mptr->type));
+ else
+ snd_iprintf(buffer, "%3i: : %s\n", minor,
+ snd_oss_device_type_name(mptr->type));
}
up(&sound_oss_mutex);
}
-#endif /* CONFIG_PROC_FS */
int __init snd_minor_info_oss_init(void)
{
-#ifdef CONFIG_PROC_FS
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
if (entry) {
@@ -228,26 +259,15 @@ int __init snd_minor_info_oss_init(void)
}
}
snd_minor_info_oss_entry = entry;
-#endif
return 0;
}
int __exit snd_minor_info_oss_done(void)
{
-#ifdef CONFIG_PROC_FS
if (snd_minor_info_oss_entry)
snd_info_unregister(snd_minor_info_oss_entry);
-#endif
- return 0;
-}
-
-int __init snd_oss_init_module(void)
-{
- int card;
-
- for (card = 0; card < SNDRV_CARDS; card++)
- INIT_LIST_HEAD(&snd_oss_minors_hash[card]);
return 0;
}
+#endif /* CONFIG_PROC_FS */
#endif /* CONFIG_SND_OSSEMUL */
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 1b90a38d10ff..2425b971b240 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -53,8 +53,8 @@ MODULE_LICENSE("GPL");
module_param(timer_limit, int, 0444);
MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
-typedef struct {
- snd_timer_instance_t *timeri;
+struct snd_timer_user {
+ struct snd_timer_instance *timeri;
int tread; /* enhanced read with timestamps and events */
unsigned long ticks;
unsigned long overrun;
@@ -62,8 +62,8 @@ typedef struct {
int qtail;
int qused;
int queue_size;
- snd_timer_read_t *queue;
- snd_timer_tread_t *tqueue;
+ struct snd_timer_read *queue;
+ struct snd_timer_tread *tqueue;
spinlock_t qlock;
unsigned long last_resolution;
unsigned int filter;
@@ -71,7 +71,7 @@ typedef struct {
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
struct semaphore tread_sem;
-} snd_timer_user_t;
+};
/* list of timers */
static LIST_HEAD(snd_timer_list);
@@ -84,21 +84,21 @@ static DEFINE_SPINLOCK(slave_active_lock);
static DECLARE_MUTEX(register_mutex);
-static int snd_timer_free(snd_timer_t *timer);
-static int snd_timer_dev_free(snd_device_t *device);
-static int snd_timer_dev_register(snd_device_t *device);
-static int snd_timer_dev_unregister(snd_device_t *device);
+static int snd_timer_free(struct snd_timer *timer);
+static int snd_timer_dev_free(struct snd_device *device);
+static int snd_timer_dev_register(struct snd_device *device);
+static int snd_timer_dev_unregister(struct snd_device *device);
-static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left);
+static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left);
/*
* create a timer instance with the given owner string.
* when timer is not NULL, increments the module counter
*/
-static snd_timer_instance_t *snd_timer_instance_new(char *owner,
- snd_timer_t *timer)
+static struct snd_timer_instance *snd_timer_instance_new(char *owner,
+ struct snd_timer *timer)
{
- snd_timer_instance_t *timeri;
+ struct snd_timer_instance *timeri;
timeri = kzalloc(sizeof(*timeri), GFP_KERNEL);
if (timeri == NULL)
return NULL;
@@ -126,13 +126,13 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner,
/*
* find a timer instance from the given timer id
*/
-static snd_timer_t *snd_timer_find(snd_timer_id_t *tid)
+static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
{
- snd_timer_t *timer = NULL;
+ struct snd_timer *timer = NULL;
struct list_head *p;
list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, snd_timer_t, device_list);
+ timer = list_entry(p, struct snd_timer, device_list);
if (timer->tmr_class != tid->dev_class)
continue;
@@ -152,7 +152,7 @@ static snd_timer_t *snd_timer_find(snd_timer_id_t *tid)
#ifdef CONFIG_KMOD
-static void snd_timer_request(snd_timer_id_t *tid)
+static void snd_timer_request(struct snd_timer_id *tid)
{
if (! current->fs->root)
return;
@@ -179,17 +179,17 @@ static void snd_timer_request(snd_timer_id_t *tid)
*
* call this with register_mutex down.
*/
-static void snd_timer_check_slave(snd_timer_instance_t *slave)
+static void snd_timer_check_slave(struct snd_timer_instance *slave)
{
- snd_timer_t *timer;
- snd_timer_instance_t *master;
+ struct snd_timer *timer;
+ struct snd_timer_instance *master;
struct list_head *p, *q;
/* FIXME: it's really dumb to look up all entries.. */
list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, snd_timer_t, device_list);
+ timer = list_entry(p, struct snd_timer, device_list);
list_for_each(q, &timer->open_list_head) {
- master = list_entry(q, snd_timer_instance_t, open_list);
+ master = list_entry(q, struct snd_timer_instance, open_list);
if (slave->slave_class == master->slave_class &&
slave->slave_id == master->slave_id) {
list_del(&slave->open_list);
@@ -211,14 +211,14 @@ static void snd_timer_check_slave(snd_timer_instance_t *slave)
*
* call this with register_mutex down.
*/
-static void snd_timer_check_master(snd_timer_instance_t *master)
+static void snd_timer_check_master(struct snd_timer_instance *master)
{
- snd_timer_instance_t *slave;
+ struct snd_timer_instance *slave;
struct list_head *p, *n;
/* check all pending slaves */
list_for_each_safe(p, n, &snd_timer_slave_list) {
- slave = list_entry(p, snd_timer_instance_t, open_list);
+ slave = list_entry(p, struct snd_timer_instance, open_list);
if (slave->slave_class == master->slave_class &&
slave->slave_id == master->slave_id) {
list_del(p);
@@ -238,12 +238,12 @@ static void snd_timer_check_master(snd_timer_instance_t *master)
* open a timer instance
* when opening a master, the slave id must be here given.
*/
-int snd_timer_open(snd_timer_instance_t **ti,
- char *owner, snd_timer_id_t *tid,
+int snd_timer_open(struct snd_timer_instance **ti,
+ char *owner, struct snd_timer_id *tid,
unsigned int slave_id)
{
- snd_timer_t *timer;
- snd_timer_instance_t *timeri = NULL;
+ struct snd_timer *timer;
+ struct snd_timer_instance *timeri = NULL;
if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) {
/* open a slave instance */
@@ -285,7 +285,7 @@ int snd_timer_open(snd_timer_instance_t **ti,
}
if (!list_empty(&timer->open_list_head)) {
timeri = list_entry(timer->open_list_head.next,
- snd_timer_instance_t, open_list);
+ struct snd_timer_instance, open_list);
if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) {
up(&register_mutex);
return -EBUSY;
@@ -307,17 +307,17 @@ int snd_timer_open(snd_timer_instance_t **ti,
return 0;
}
-static int _snd_timer_stop(snd_timer_instance_t * timeri,
- int keep_flag, enum sndrv_timer_event event);
+static int _snd_timer_stop(struct snd_timer_instance *timeri,
+ int keep_flag, int event);
/*
* close a timer instance
*/
-int snd_timer_close(snd_timer_instance_t * timeri)
+int snd_timer_close(struct snd_timer_instance *timeri)
{
- snd_timer_t *timer = NULL;
+ struct snd_timer *timer = NULL;
struct list_head *p, *n;
- snd_timer_instance_t *slave;
+ struct snd_timer_instance *slave;
snd_assert(timeri != NULL, return -ENXIO);
@@ -353,7 +353,7 @@ int snd_timer_close(snd_timer_instance_t * timeri)
timer->hw.close(timer);
/* remove slave links */
list_for_each_safe(p, n, &timeri->slave_list_head) {
- slave = list_entry(p, snd_timer_instance_t, open_list);
+ slave = list_entry(p, struct snd_timer_instance, open_list);
spin_lock_irq(&slave_active_lock);
_snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
list_del(p);
@@ -373,9 +373,9 @@ int snd_timer_close(snd_timer_instance_t * timeri)
return 0;
}
-unsigned long snd_timer_resolution(snd_timer_instance_t * timeri)
+unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
- snd_timer_t * timer;
+ struct snd_timer * timer;
if (timeri == NULL)
return 0;
@@ -387,13 +387,12 @@ unsigned long snd_timer_resolution(snd_timer_instance_t * timeri)
return 0;
}
-static void snd_timer_notify1(snd_timer_instance_t *ti,
- enum sndrv_timer_event event)
+static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
unsigned long flags;
unsigned long resolution = 0;
- snd_timer_instance_t *ts;
+ struct snd_timer_instance *ts;
struct list_head *n;
struct timespec tstamp;
@@ -414,14 +413,14 @@ static void snd_timer_notify1(snd_timer_instance_t *ti,
return;
spin_lock_irqsave(&timer->lock, flags);
list_for_each(n, &ti->slave_active_head) {
- ts = list_entry(n, snd_timer_instance_t, active_list);
+ ts = list_entry(n, struct snd_timer_instance, active_list);
if (ts->ccallback)
ts->ccallback(ti, event + 100, &tstamp, resolution);
}
spin_unlock_irqrestore(&timer->lock, flags);
}
-static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri,
+static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
unsigned long sticks)
{
list_del(&timeri->active_list);
@@ -442,7 +441,7 @@ static int snd_timer_start1(snd_timer_t *timer, snd_timer_instance_t *timeri,
}
}
-static int snd_timer_start_slave(snd_timer_instance_t *timeri)
+static int snd_timer_start_slave(struct snd_timer_instance *timeri)
{
unsigned long flags;
@@ -458,9 +457,9 @@ static int snd_timer_start_slave(snd_timer_instance_t *timeri)
/*
* start the timer instance
*/
-int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks)
+int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
int result = -EINVAL;
unsigned long flags;
@@ -483,10 +482,10 @@ int snd_timer_start(snd_timer_instance_t * timeri, unsigned int ticks)
return result;
}
-static int _snd_timer_stop(snd_timer_instance_t * timeri,
- int keep_flag, enum sndrv_timer_event event)
+static int _snd_timer_stop(struct snd_timer_instance * timeri,
+ int keep_flag, int event)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
unsigned long flags;
snd_assert(timeri != NULL, return -ENXIO);
@@ -532,9 +531,9 @@ static int _snd_timer_stop(snd_timer_instance_t * timeri,
*
* do not call this from the timer callback!
*/
-int snd_timer_stop(snd_timer_instance_t * timeri)
+int snd_timer_stop(struct snd_timer_instance *timeri)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
unsigned long flags;
int err;
@@ -552,9 +551,9 @@ int snd_timer_stop(snd_timer_instance_t * timeri)
/*
* start again.. the tick is kept.
*/
-int snd_timer_continue(snd_timer_instance_t * timeri)
+int snd_timer_continue(struct snd_timer_instance *timeri)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
int result = -EINVAL;
unsigned long flags;
@@ -578,7 +577,7 @@ int snd_timer_continue(snd_timer_instance_t * timeri)
/*
* pause.. remember the ticks left
*/
-int snd_timer_pause(snd_timer_instance_t * timeri)
+int snd_timer_pause(struct snd_timer_instance * timeri)
{
return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
}
@@ -589,14 +588,14 @@ int snd_timer_pause(snd_timer_instance_t * timeri)
* start pending instances and check the scheduling ticks.
* when the scheduling ticks is changed set CHANGE flag to reprogram the timer.
*/
-static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left)
+static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left)
{
- snd_timer_instance_t *ti;
+ struct snd_timer_instance *ti;
unsigned long ticks = ~0UL;
struct list_head *p;
list_for_each(p, &timer->active_list_head) {
- ti = list_entry(p, snd_timer_instance_t, active_list);
+ ti = list_entry(p, struct snd_timer_instance, active_list);
if (ti->flags & SNDRV_TIMER_IFLG_START) {
ti->flags &= ~SNDRV_TIMER_IFLG_START;
ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
@@ -624,8 +623,8 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left)
*/
static void snd_timer_tasklet(unsigned long arg)
{
- snd_timer_t *timer = (snd_timer_t *) arg;
- snd_timer_instance_t *ti;
+ struct snd_timer *timer = (struct snd_timer *) arg;
+ struct snd_timer_instance *ti;
struct list_head *p;
unsigned long resolution, ticks;
@@ -633,7 +632,7 @@ static void snd_timer_tasklet(unsigned long arg)
/* now process all callbacks */
while (!list_empty(&timer->sack_list_head)) {
p = timer->sack_list_head.next; /* get first item */
- ti = list_entry(p, snd_timer_instance_t, ack_list);
+ ti = list_entry(p, struct snd_timer_instance, ack_list);
/* remove from ack_list and make empty */
list_del_init(p);
@@ -658,17 +657,18 @@ static void snd_timer_tasklet(unsigned long arg)
* ticks_left is usually equal to timer->sticks.
*
*/
-void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
+void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
{
- snd_timer_instance_t *ti, *ts;
+ struct snd_timer_instance *ti, *ts;
unsigned long resolution, ticks;
struct list_head *p, *q, *n, *ack_list_head;
+ unsigned long flags;
int use_tasklet = 0;
if (timer == NULL)
return;
- spin_lock(&timer->lock);
+ spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
if (timer->hw.c_resolution)
@@ -682,7 +682,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
* is called.
*/
list_for_each_safe(p, n, &timer->active_list_head) {
- ti = list_entry(p, snd_timer_instance_t, active_list);
+ ti = list_entry(p, struct snd_timer_instance, active_list);
if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
continue;
ti->pticks += ticks_left;
@@ -708,7 +708,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
if (list_empty(&ti->ack_list))
list_add_tail(&ti->ack_list, ack_list_head);
list_for_each(q, &ti->slave_active_head) {
- ts = list_entry(q, snd_timer_instance_t, active_list);
+ ts = list_entry(q, struct snd_timer_instance, active_list);
ts->pticks = ti->pticks;
ts->resolution = resolution;
if (list_empty(&ts->ack_list))
@@ -735,7 +735,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
/* now process all fast callbacks */
while (!list_empty(&timer->ack_list_head)) {
p = timer->ack_list_head.next; /* get first item */
- ti = list_entry(p, snd_timer_instance_t, ack_list);
+ ti = list_entry(p, struct snd_timer_instance, ack_list);
/* remove from ack_list and make empty */
list_del_init(p);
@@ -753,7 +753,7 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
/* do we have any slow callbacks? */
use_tasklet = !list_empty(&timer->sack_list_head);
- spin_unlock(&timer->lock);
+ spin_unlock_irqrestore(&timer->lock, flags);
if (use_tasklet)
tasklet_hi_schedule(&timer->task_queue);
@@ -763,12 +763,12 @@ void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left)
*/
-int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid,
- snd_timer_t **rtimer)
+int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
+ struct snd_timer **rtimer)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_timer_dev_free,
.dev_register = snd_timer_dev_register,
.dev_unregister = snd_timer_dev_unregister
@@ -778,8 +778,10 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid,
snd_assert(rtimer != NULL, return -EINVAL);
*rtimer = NULL;
timer = kzalloc(sizeof(*timer), GFP_KERNEL);
- if (timer == NULL)
+ if (timer == NULL) {
+ snd_printk(KERN_ERR "timer: cannot allocate\n");
return -ENOMEM;
+ }
timer->tmr_class = tid->dev_class;
timer->card = card;
timer->tmr_device = tid->device;
@@ -806,7 +808,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid,
return 0;
}
-static int snd_timer_free(snd_timer_t *timer)
+static int snd_timer_free(struct snd_timer *timer)
{
snd_assert(timer != NULL, return -ENXIO);
if (timer->private_free)
@@ -815,16 +817,16 @@ static int snd_timer_free(snd_timer_t *timer)
return 0;
}
-static int snd_timer_dev_free(snd_device_t *device)
+static int snd_timer_dev_free(struct snd_device *device)
{
- snd_timer_t *timer = device->device_data;
+ struct snd_timer *timer = device->device_data;
return snd_timer_free(timer);
}
-static int snd_timer_dev_register(snd_device_t *dev)
+static int snd_timer_dev_register(struct snd_device *dev)
{
- snd_timer_t *timer = dev->device_data;
- snd_timer_t *timer1;
+ struct snd_timer *timer = dev->device_data;
+ struct snd_timer *timer1;
struct list_head *p;
snd_assert(timer != NULL && timer->hw.start != NULL &&
@@ -835,7 +837,7 @@ static int snd_timer_dev_register(snd_device_t *dev)
down(&register_mutex);
list_for_each(p, &snd_timer_list) {
- timer1 = list_entry(p, snd_timer_t, device_list);
+ timer1 = list_entry(p, struct snd_timer, device_list);
if (timer1->tmr_class > timer->tmr_class)
break;
if (timer1->tmr_class < timer->tmr_class)
@@ -863,10 +865,10 @@ static int snd_timer_dev_register(snd_device_t *dev)
return 0;
}
-static int snd_timer_unregister(snd_timer_t *timer)
+static int snd_timer_unregister(struct snd_timer *timer)
{
struct list_head *p, *n;
- snd_timer_instance_t *ti;
+ struct snd_timer_instance *ti;
snd_assert(timer != NULL, return -ENXIO);
down(&register_mutex);
@@ -874,7 +876,7 @@ static int snd_timer_unregister(snd_timer_t *timer)
snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer);
list_for_each_safe(p, n, &timer->open_list_head) {
list_del_init(p);
- ti = list_entry(p, snd_timer_instance_t, open_list);
+ ti = list_entry(p, struct snd_timer_instance, open_list);
ti->timer = NULL;
}
}
@@ -883,18 +885,17 @@ static int snd_timer_unregister(snd_timer_t *timer)
return snd_timer_free(timer);
}
-static int snd_timer_dev_unregister(snd_device_t *device)
+static int snd_timer_dev_unregister(struct snd_device *device)
{
- snd_timer_t *timer = device->device_data;
+ struct snd_timer *timer = device->device_data;
return snd_timer_unregister(timer);
}
-void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event,
- struct timespec *tstamp)
+void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
{
unsigned long flags;
unsigned long resolution = 0;
- snd_timer_instance_t *ti, *ts;
+ struct snd_timer_instance *ti, *ts;
struct list_head *p, *n;
if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
@@ -911,11 +912,11 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event,
resolution = timer->hw.resolution;
}
list_for_each(p, &timer->active_list_head) {
- ti = list_entry(p, snd_timer_instance_t, active_list);
+ ti = list_entry(p, struct snd_timer_instance, active_list);
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
list_for_each(n, &ti->slave_active_head) {
- ts = list_entry(n, snd_timer_instance_t, active_list);
+ ts = list_entry(n, struct snd_timer_instance, active_list);
if (ts->ccallback)
ts->ccallback(ts, event, tstamp, resolution);
}
@@ -926,9 +927,9 @@ void snd_timer_notify(snd_timer_t *timer, enum sndrv_timer_event event,
/*
* exported functions for global timers
*/
-int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer)
+int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
{
- snd_timer_id_t tid;
+ struct snd_timer_id tid;
tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL;
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
@@ -938,21 +939,21 @@ int snd_timer_global_new(char *id, int device, snd_timer_t **rtimer)
return snd_timer_new(NULL, id, &tid, rtimer);
}
-int snd_timer_global_free(snd_timer_t *timer)
+int snd_timer_global_free(struct snd_timer *timer)
{
return snd_timer_free(timer);
}
-int snd_timer_global_register(snd_timer_t *timer)
+int snd_timer_global_register(struct snd_timer *timer)
{
- snd_device_t dev;
+ struct snd_device dev;
memset(&dev, 0, sizeof(dev));
dev.device_data = timer;
return snd_timer_dev_register(&dev);
}
-int snd_timer_global_unregister(snd_timer_t *timer)
+int snd_timer_global_unregister(struct snd_timer *timer)
{
return snd_timer_unregister(timer);
}
@@ -971,7 +972,7 @@ struct snd_timer_system_private {
static void snd_timer_s_function(unsigned long data)
{
- snd_timer_t *timer = (snd_timer_t *)data;
+ struct snd_timer *timer = (struct snd_timer *)data;
struct snd_timer_system_private *priv = timer->private_data;
unsigned long jiff = jiffies;
if (time_after(jiff, priv->last_expires))
@@ -979,7 +980,7 @@ static void snd_timer_s_function(unsigned long data)
snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies);
}
-static int snd_timer_s_start(snd_timer_t * timer)
+static int snd_timer_s_start(struct snd_timer * timer)
{
struct snd_timer_system_private *priv;
unsigned long njiff;
@@ -998,7 +999,7 @@ static int snd_timer_s_start(snd_timer_t * timer)
return 0;
}
-static int snd_timer_s_stop(snd_timer_t * timer)
+static int snd_timer_s_stop(struct snd_timer * timer)
{
struct snd_timer_system_private *priv;
unsigned long jiff;
@@ -1013,7 +1014,7 @@ static int snd_timer_s_stop(snd_timer_t * timer)
return 0;
}
-static struct _snd_timer_hardware snd_timer_system =
+static struct snd_timer_hardware snd_timer_system =
{
.flags = SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
.resolution = 1000000000L / HZ,
@@ -1022,14 +1023,14 @@ static struct _snd_timer_hardware snd_timer_system =
.stop = snd_timer_s_stop
};
-static void snd_timer_free_system(snd_timer_t *timer)
+static void snd_timer_free_system(struct snd_timer *timer)
{
kfree(timer->private_data);
}
static int snd_timer_register_system(void)
{
- snd_timer_t *timer;
+ struct snd_timer *timer;
struct snd_timer_system_private *priv;
int err;
@@ -1051,21 +1052,22 @@ static int snd_timer_register_system(void)
return snd_timer_global_register(timer);
}
+#ifdef CONFIG_PROC_FS
/*
* Info interface
*/
-static void snd_timer_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_timer_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
unsigned long flags;
- snd_timer_t *timer;
- snd_timer_instance_t *ti;
+ struct snd_timer *timer;
+ struct snd_timer_instance *ti;
struct list_head *p, *q;
down(&register_mutex);
list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, snd_timer_t, device_list);
+ timer = list_entry(p, struct snd_timer, device_list);
switch (timer->tmr_class) {
case SNDRV_TIMER_CLASS_GLOBAL:
snd_iprintf(buffer, "G%i: ", timer->tmr_device);
@@ -1094,7 +1096,7 @@ static void snd_timer_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "\n");
spin_lock_irqsave(&timer->lock, flags);
list_for_each(q, &timer->open_list_head) {
- ti = list_entry(q, snd_timer_instance_t, open_list);
+ ti = list_entry(q, struct snd_timer_instance, open_list);
snd_iprintf(buffer, " Client %s : %s\n",
ti->owner ? ti->owner : "unknown",
ti->flags & (SNDRV_TIMER_IFLG_START |
@@ -1106,16 +1108,43 @@ static void snd_timer_proc_read(snd_info_entry_t *entry,
up(&register_mutex);
}
+static struct snd_info_entry *snd_timer_proc_entry = NULL;
+
+static void __init snd_timer_proc_init(void)
+{
+ struct snd_info_entry *entry;
+
+ entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
+ if (entry != NULL) {
+ entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128;
+ entry->c.text.read = snd_timer_proc_read;
+ if (snd_info_register(entry) < 0) {
+ snd_info_free_entry(entry);
+ entry = NULL;
+ }
+ }
+ snd_timer_proc_entry = entry;
+}
+
+static void __exit snd_timer_proc_done(void)
+{
+ snd_info_unregister(snd_timer_proc_entry);
+}
+#else /* !CONFIG_PROC_FS */
+#define snd_timer_proc_init()
+#define snd_timer_proc_done()
+#endif
+
/*
* USER SPACE interface
*/
-static void snd_timer_user_interrupt(snd_timer_instance_t *timeri,
+static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
unsigned long resolution,
unsigned long ticks)
{
- snd_timer_user_t *tu = timeri->callback_data;
- snd_timer_read_t *r;
+ struct snd_timer_user *tu = timeri->callback_data;
+ struct snd_timer_read *r;
int prev;
spin_lock(&tu->qlock);
@@ -1142,8 +1171,8 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri,
wake_up(&tu->qchange_sleep);
}
-static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu,
- snd_timer_tread_t *tread)
+static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
+ struct snd_timer_tread *tread)
{
if (tu->qused >= tu->queue_size) {
tu->overrun++;
@@ -1154,13 +1183,13 @@ static void snd_timer_user_append_to_tqueue(snd_timer_user_t *tu,
}
}
-static void snd_timer_user_ccallback(snd_timer_instance_t *timeri,
- enum sndrv_timer_event event,
+static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
+ int event,
struct timespec *tstamp,
unsigned long resolution)
{
- snd_timer_user_t *tu = timeri->callback_data;
- snd_timer_tread_t r1;
+ struct snd_timer_user *tu = timeri->callback_data;
+ struct snd_timer_tread r1;
if (event >= SNDRV_TIMER_EVENT_START &&
event <= SNDRV_TIMER_EVENT_PAUSE)
@@ -1177,12 +1206,12 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri,
wake_up(&tu->qchange_sleep);
}
-static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri,
+static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
unsigned long resolution,
unsigned long ticks)
{
- snd_timer_user_t *tu = timeri->callback_data;
- snd_timer_tread_t *r, r1;
+ struct snd_timer_user *tu = timeri->callback_data;
+ struct snd_timer_tread *r, r1;
struct timespec tstamp;
int prev, append = 0;
@@ -1233,7 +1262,7 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri,
static int snd_timer_user_open(struct inode *inode, struct file *file)
{
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = kzalloc(sizeof(*tu), GFP_KERNEL);
if (tu == NULL)
@@ -1243,7 +1272,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
init_MUTEX(&tu->tread_sem);
tu->ticks = 1;
tu->queue_size = 128;
- tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t),
+ tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
GFP_KERNEL);
if (tu->queue == NULL) {
kfree(tu);
@@ -1255,7 +1284,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
static int snd_timer_user_release(struct inode *inode, struct file *file)
{
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
if (file->private_data) {
tu = file->private_data;
@@ -1270,7 +1299,7 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
return 0;
}
-static void snd_timer_user_zero_id(snd_timer_id_t *id)
+static void snd_timer_user_zero_id(struct snd_timer_id *id)
{
id->dev_class = SNDRV_TIMER_CLASS_NONE;
id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
@@ -1279,7 +1308,7 @@ static void snd_timer_user_zero_id(snd_timer_id_t *id)
id->subdevice = -1;
}
-static void snd_timer_user_copy_id(snd_timer_id_t *id, snd_timer_t *timer)
+static void snd_timer_user_copy_id(struct snd_timer_id *id, struct snd_timer *timer)
{
id->dev_class = timer->tmr_class;
id->dev_sclass = SNDRV_TIMER_SCLASS_NONE;
@@ -1288,10 +1317,10 @@ static void snd_timer_user_copy_id(snd_timer_id_t *id, snd_timer_t *timer)
id->subdevice = timer->tmr_subdevice;
}
-static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
+static int snd_timer_user_next_device(struct snd_timer_id __user *_tid)
{
- snd_timer_id_t id;
- snd_timer_t *timer;
+ struct snd_timer_id id;
+ struct snd_timer *timer;
struct list_head *p;
if (copy_from_user(&id, _tid, sizeof(id)))
@@ -1302,7 +1331,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
snd_timer_user_zero_id(&id);
else {
timer = list_entry(snd_timer_list.next,
- snd_timer_t, device_list);
+ struct snd_timer, device_list);
snd_timer_user_copy_id(&id, timer);
}
} else {
@@ -1310,7 +1339,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
case SNDRV_TIMER_CLASS_GLOBAL:
id.device = id.device < 0 ? 0 : id.device + 1;
list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, snd_timer_t, device_list);
+ timer = list_entry(p, struct snd_timer, device_list);
if (timer->tmr_class > SNDRV_TIMER_CLASS_GLOBAL) {
snd_timer_user_copy_id(&id, timer);
break;
@@ -1343,7 +1372,7 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
}
}
list_for_each(p, &snd_timer_list) {
- timer = list_entry(p, snd_timer_t, device_list);
+ timer = list_entry(p, struct snd_timer, device_list);
if (timer->tmr_class > id.dev_class) {
snd_timer_user_copy_id(&id, timer);
break;
@@ -1385,11 +1414,11 @@ static int snd_timer_user_next_device(snd_timer_id_t __user *_tid)
}
static int snd_timer_user_ginfo(struct file *file,
- snd_timer_ginfo_t __user *_ginfo)
+ struct snd_timer_ginfo __user *_ginfo)
{
- snd_timer_ginfo_t *ginfo;
- snd_timer_id_t tid;
- snd_timer_t *t;
+ struct snd_timer_ginfo *ginfo;
+ struct snd_timer_id tid;
+ struct snd_timer *t;
struct list_head *p;
int err = 0;
@@ -1430,10 +1459,10 @@ static int snd_timer_user_ginfo(struct file *file,
}
static int snd_timer_user_gparams(struct file *file,
- snd_timer_gparams_t __user *_gparams)
+ struct snd_timer_gparams __user *_gparams)
{
- snd_timer_gparams_t gparams;
- snd_timer_t *t;
+ struct snd_timer_gparams gparams;
+ struct snd_timer *t;
int err;
if (copy_from_user(&gparams, _gparams, sizeof(gparams)))
@@ -1459,11 +1488,11 @@ _error:
}
static int snd_timer_user_gstatus(struct file *file,
- snd_timer_gstatus_t __user *_gstatus)
+ struct snd_timer_gstatus __user *_gstatus)
{
- snd_timer_gstatus_t gstatus;
- snd_timer_id_t tid;
- snd_timer_t *t;
+ struct snd_timer_gstatus gstatus;
+ struct snd_timer_id tid;
+ struct snd_timer *t;
int err = 0;
if (copy_from_user(&gstatus, _gstatus, sizeof(gstatus)))
@@ -1495,10 +1524,10 @@ static int snd_timer_user_gstatus(struct file *file,
}
static int snd_timer_user_tselect(struct file *file,
- snd_timer_select_t __user *_tselect)
+ struct snd_timer_select __user *_tselect)
{
- snd_timer_user_t *tu;
- snd_timer_select_t tselect;
+ struct snd_timer_user *tu;
+ struct snd_timer_select tselect;
char str[32];
int err = 0;
@@ -1524,12 +1553,12 @@ static int snd_timer_user_tselect(struct file *file,
kfree(tu->tqueue);
tu->tqueue = NULL;
if (tu->tread) {
- tu->tqueue = kmalloc(tu->queue_size * sizeof(snd_timer_tread_t),
+ tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
GFP_KERNEL);
if (tu->tqueue == NULL)
err = -ENOMEM;
} else {
- tu->queue = kmalloc(tu->queue_size * sizeof(snd_timer_read_t),
+ tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
GFP_KERNEL);
if (tu->queue == NULL)
err = -ENOMEM;
@@ -1552,11 +1581,11 @@ static int snd_timer_user_tselect(struct file *file,
}
static int snd_timer_user_info(struct file *file,
- snd_timer_info_t __user *_info)
+ struct snd_timer_info __user *_info)
{
- snd_timer_user_t *tu;
- snd_timer_info_t *info;
- snd_timer_t *t;
+ struct snd_timer_user *tu;
+ struct snd_timer_info *info;
+ struct snd_timer *t;
int err = 0;
tu = file->private_data;
@@ -1580,13 +1609,13 @@ static int snd_timer_user_info(struct file *file,
}
static int snd_timer_user_params(struct file *file,
- snd_timer_params_t __user *_params)
+ struct snd_timer_params __user *_params)
{
- snd_timer_user_t *tu;
- snd_timer_params_t params;
- snd_timer_t *t;
- snd_timer_read_t *tr;
- snd_timer_tread_t *ttr;
+ struct snd_timer_user *tu;
+ struct snd_timer_params params;
+ struct snd_timer *t;
+ struct snd_timer_read *tr;
+ struct snd_timer_tread *ttr;
int err;
tu = file->private_data;
@@ -1656,14 +1685,14 @@ static int snd_timer_user_params(struct file *file,
tu->qhead = tu->qtail = tu->qused = 0;
if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
if (tu->tread) {
- snd_timer_tread_t tread;
+ struct snd_timer_tread tread;
tread.event = SNDRV_TIMER_EVENT_EARLY;
tread.tstamp.tv_sec = 0;
tread.tstamp.tv_nsec = 0;
tread.val = 0;
snd_timer_user_append_to_tqueue(tu, &tread);
} else {
- snd_timer_read_t *r = &tu->queue[0];
+ struct snd_timer_read *r = &tu->queue[0];
r->resolution = 0;
r->ticks = 0;
tu->qused++;
@@ -1680,10 +1709,10 @@ static int snd_timer_user_params(struct file *file,
}
static int snd_timer_user_status(struct file *file,
- snd_timer_status_t __user *_status)
+ struct snd_timer_status __user *_status)
{
- snd_timer_user_t *tu;
- snd_timer_status_t status;
+ struct snd_timer_user *tu;
+ struct snd_timer_status status;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -1703,7 +1732,7 @@ static int snd_timer_user_status(struct file *file,
static int snd_timer_user_start(struct file *file)
{
int err;
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -1716,7 +1745,7 @@ static int snd_timer_user_start(struct file *file)
static int snd_timer_user_stop(struct file *file)
{
int err;
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -1726,7 +1755,7 @@ static int snd_timer_user_stop(struct file *file)
static int snd_timer_user_continue(struct file *file)
{
int err;
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -1737,7 +1766,7 @@ static int snd_timer_user_continue(struct file *file)
static int snd_timer_user_pause(struct file *file)
{
int err;
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -1754,7 +1783,7 @@ enum {
static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
void __user *argp = (void __user *)arg;
int __user *p = argp;
@@ -1813,7 +1842,7 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
static int snd_timer_user_fasync(int fd, struct file * file, int on)
{
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
int err;
tu = file->private_data;
@@ -1826,12 +1855,12 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on)
static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
size_t count, loff_t *offset)
{
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
long result = 0, unit;
int err = 0;
tu = file->private_data;
- unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t);
+ unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
spin_lock_irq(&tu->qlock);
while ((long)count - result >= unit) {
while (!tu->qused) {
@@ -1864,13 +1893,13 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
if (tu->tread) {
if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
- sizeof(snd_timer_tread_t))) {
+ sizeof(struct snd_timer_tread))) {
err = -EFAULT;
goto _error;
}
} else {
if (copy_to_user(buffer, &tu->queue[tu->qhead++],
- sizeof(snd_timer_read_t))) {
+ sizeof(struct snd_timer_read))) {
err = -EFAULT;
goto _error;
}
@@ -1892,7 +1921,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
{
unsigned int mask;
- snd_timer_user_t *tu;
+ struct snd_timer_user *tu;
tu = file->private_data;
@@ -1923,44 +1952,27 @@ static struct file_operations snd_timer_f_ops =
.fasync = snd_timer_user_fasync,
};
-static snd_minor_t snd_timer_reg =
-{
- .comment = "timer",
- .f_ops = &snd_timer_f_ops,
-};
-
/*
* ENTRY functions
*/
-static snd_info_entry_t *snd_timer_proc_entry = NULL;
-
static int __init alsa_timer_init(void)
{
int err;
- snd_info_entry_t *entry;
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_register(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1,
"system timer");
#endif
- entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
- if (entry != NULL) {
- entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128;
- entry->c.text.read = snd_timer_proc_read;
- if (snd_info_register(entry) < 0) {
- snd_info_free_entry(entry);
- entry = NULL;
- }
- }
- snd_timer_proc_entry = entry;
+
if ((err = snd_timer_register_system()) < 0)
snd_printk(KERN_ERR "unable to register system timer (%i)\n",
err);
- if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER,
- NULL, 0, &snd_timer_reg, "timer"))<0)
+ if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
+ &snd_timer_f_ops, NULL, "timer")) < 0)
snd_printk(KERN_ERR "unable to register timer device (%i)\n",
err);
+ snd_timer_proc_init();
return 0;
}
@@ -1971,13 +1983,10 @@ static void __exit alsa_timer_exit(void)
snd_unregister_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0);
/* unregister the system timer */
list_for_each_safe(p, n, &snd_timer_list) {
- snd_timer_t *timer = list_entry(p, snd_timer_t, device_list);
+ struct snd_timer *timer = list_entry(p, struct snd_timer, device_list);
snd_timer_unregister(timer);
}
- if (snd_timer_proc_entry) {
- snd_info_unregister(snd_timer_proc_entry);
- snd_timer_proc_entry = NULL;
- }
+ snd_timer_proc_done();
#ifdef SNDRV_OSS_INFO_DEV_TIMERS
snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_TIMERS, SNDRV_CARDS - 1);
#endif
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 3de552dfe80f..5512f5373c52 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -22,7 +22,7 @@
#include <linux/compat.h>
-struct sndrv_timer_info32 {
+struct snd_timer_info32 {
u32 flags;
s32 card;
unsigned char id[64];
@@ -33,11 +33,11 @@ struct sndrv_timer_info32 {
};
static int snd_timer_user_info_compat(struct file *file,
- struct sndrv_timer_info32 __user *_info)
+ struct snd_timer_info32 __user *_info)
{
- snd_timer_user_t *tu;
- struct sndrv_timer_info32 info;
- snd_timer_t *t;
+ struct snd_timer_user *tu;
+ struct snd_timer_info32 info;
+ struct snd_timer *t;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -55,7 +55,7 @@ static int snd_timer_user_info_compat(struct file *file,
return 0;
}
-struct sndrv_timer_status32 {
+struct snd_timer_status32 {
struct compat_timespec tstamp;
u32 resolution;
u32 lost;
@@ -65,10 +65,10 @@ struct sndrv_timer_status32 {
};
static int snd_timer_user_status_compat(struct file *file,
- struct sndrv_timer_status32 __user *_status)
+ struct snd_timer_status32 __user *_status)
{
- snd_timer_user_t *tu;
- snd_timer_status_t status;
+ struct snd_timer_user *tu;
+ struct snd_timer_status status;
tu = file->private_data;
snd_assert(tu->timeri != NULL, return -ENXIO);
@@ -89,8 +89,8 @@ static int snd_timer_user_status_compat(struct file *file,
*/
enum {
- SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
- SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
+ SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
+ SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
};
static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index efcb4eb2d1a0..395c4ef52ac9 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -6,7 +6,6 @@ menu "Generic devices"
config SND_MPU401_UART
tristate
- select SND_TIMER
select SND_RAWMIDI
config SND_OPL3_LIB
@@ -24,12 +23,19 @@ config SND_VX_LIB
select SND_HWDEP
select SND_PCM
+config SND_AC97_CODEC
+ tristate
+ select SND_PCM
+ select SND_AC97_BUS
+
+config SND_AC97_BUS
+ tristate
+
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.
@@ -45,7 +51,6 @@ 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,9 +64,7 @@ config SND_VIRMIDI
config SND_MTPAV
tristate "MOTU MidiTimePiece AV multiport MIDI"
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
@@ -73,9 +76,7 @@ config SND_MTPAV
config SND_SERIAL_U16550
tristate "UART16550 serial MIDI driver"
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>.
@@ -92,7 +93,6 @@ 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 64ef7f62851d..14e1a671b5cf 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -20,6 +20,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/time.h>
@@ -42,7 +44,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
#if 0 /* emu10k1 emulation */
#define MAX_BUFFER_SIZE (128 * 1024)
-static int emu10k1_playback_constraints(snd_pcm_runtime_t *runtime)
+static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
{
int err;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
@@ -90,11 +92,27 @@ static int emu10k1_playback_constraints(snd_pcm_runtime_t *runtime)
#define USE_RATE_MAX 48000
#endif
+#if 0 /* CA0106 */
+#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
+#define USE_CHANNELS_MIN 2
+#define USE_CHANNELS_MAX 2
+#define USE_RATE (SNDRV_PCM_RATE_48000|SNDRV_PCM_RATE_96000|SNDRV_PCM_RATE_192000)
+#define USE_RATE_MIN 48000
+#define USE_RATE_MAX 192000
+#define MAX_BUFFER_SIZE ((65536-64)*8)
+#define MAX_PERIOD_SIZE (65536-64)
+#define USE_PERIODS_MIN 2
+#define USE_PERIODS_MAX 8
+#endif
+
/* defaults */
#ifndef MAX_BUFFER_SIZE
#define MAX_BUFFER_SIZE (64*1024)
#endif
+#ifndef MAX_PERIOD_SIZE
+#define MAX_PERIOD_SIZE MAX_BUFFER_SIZE
+#endif
#ifndef USE_FORMATS
#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
#endif
@@ -142,6 +160,8 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
//module_param_array(midi_devs, int, NULL, 0444);
//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
+static struct platform_device *devices[SNDRV_CARDS];
+
#define MIXER_ADDR_MASTER 0
#define MIXER_ADDR_LINE 1
#define MIXER_ADDR_MIC 2
@@ -149,15 +169,16 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
#define MIXER_ADDR_CD 4
#define MIXER_ADDR_LAST 4
-typedef struct snd_card_dummy {
- snd_card_t *card;
+struct snd_dummy {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
spinlock_t mixer_lock;
int mixer_volume[MIXER_ADDR_LAST+1][2];
int capture_source[MIXER_ADDR_LAST+1][2];
-} snd_card_dummy_t;
+};
-typedef struct snd_card_dummy_pcm {
- snd_card_dummy_t *dummy;
+struct snd_dummy_pcm {
+ struct snd_dummy *dummy;
spinlock_t lock;
struct timer_list timer;
unsigned int pcm_size;
@@ -166,59 +187,49 @@ typedef struct snd_card_dummy_pcm {
unsigned int pcm_jiffie; /* bytes per one jiffie */
unsigned int pcm_irq_pos; /* IRQ position */
unsigned int pcm_buf_pos; /* position in buffer */
- snd_pcm_substream_t *substream;
-} snd_card_dummy_pcm_t;
-
-static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+ struct snd_pcm_substream *substream;
+};
-static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
+static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
-
dpcm->timer.expires = 1 + jiffies;
add_timer(&dpcm->timer);
}
-static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream)
+static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
-
del_timer(&dpcm->timer);
}
-static int snd_card_dummy_playback_trigger(snd_pcm_substream_t * substream,
- int cmd)
-{
- if (cmd == SNDRV_PCM_TRIGGER_START) {
- snd_card_dummy_pcm_timer_start(substream);
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
- snd_card_dummy_pcm_timer_stop(substream);
- } else {
- return -EINVAL;
- }
- return 0;
-}
-
-static int snd_card_dummy_capture_trigger(snd_pcm_substream_t * substream,
- int cmd)
+static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- if (cmd == SNDRV_PCM_TRIGGER_START) {
- snd_card_dummy_pcm_timer_start(substream);
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
- snd_card_dummy_pcm_timer_stop(substream);
- } else {
- return -EINVAL;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm = runtime->private_data;
+ int err = 0;
+
+ spin_lock(&dpcm->lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ snd_card_dummy_pcm_timer_start(dpcm);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ snd_card_dummy_pcm_timer_stop(dpcm);
+ break;
+ default:
+ err = -EINVAL;
+ break;
}
+ spin_unlock(&dpcm->lock);
return 0;
}
-static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
+static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm = runtime->private_data;
unsigned int bps;
bps = runtime->rate * runtime->channels;
@@ -235,53 +246,37 @@ static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_card_dummy_playback_prepare(snd_pcm_substream_t * substream)
-{
- return snd_card_dummy_pcm_prepare(substream);
-}
-
-static int snd_card_dummy_capture_prepare(snd_pcm_substream_t * substream)
-{
- return snd_card_dummy_pcm_prepare(substream);
-}
-
static void snd_card_dummy_pcm_timer_function(unsigned long data)
{
- snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data;
+ struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data;
+ unsigned long flags;
+ spin_lock_irqsave(&dpcm->lock, flags);
dpcm->timer.expires = 1 + jiffies;
add_timer(&dpcm->timer);
- spin_lock_irq(&dpcm->lock);
dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
dpcm->pcm_buf_pos %= dpcm->pcm_size;
if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
dpcm->pcm_irq_pos %= dpcm->pcm_count;
+ spin_unlock_irqrestore(&dpcm->lock, flags);
snd_pcm_period_elapsed(dpcm->substream);
- }
- spin_unlock_irq(&dpcm->lock);
+ } else
+ spin_unlock_irqrestore(&dpcm->lock, flags);
}
-static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm = runtime->private_data;
return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
}
-static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream)
-{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
-
- return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
-}
-
-static snd_pcm_hardware_t snd_card_dummy_playback =
+static struct snd_pcm_hardware snd_card_dummy_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = USE_FORMATS,
.rates = USE_RATE,
.rate_min = USE_RATE_MIN,
@@ -296,10 +291,10 @@ static snd_pcm_hardware_t snd_card_dummy_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_card_dummy_capture =
+static struct snd_pcm_hardware snd_card_dummy_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = USE_FORMATS,
.rates = USE_RATE,
.rate_min = USE_RATE_MIN,
@@ -308,43 +303,51 @@ static snd_pcm_hardware_t snd_card_dummy_capture =
.channels_max = USE_CHANNELS_MAX,
.buffer_bytes_max = MAX_BUFFER_SIZE,
.period_bytes_min = 64,
- .period_bytes_max = MAX_BUFFER_SIZE,
+ .period_bytes_max = MAX_PERIOD_SIZE,
.periods_min = USE_PERIODS_MIN,
.periods_max = USE_PERIODS_MAX,
.fifo_size = 0,
};
-static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime)
+static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime)
{
- snd_card_dummy_pcm_t *dpcm = runtime->private_data;
- kfree(dpcm);
+ kfree(runtime->private_data);
}
-static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream)
+static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
+static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm;
- int err;
+ struct snd_dummy_pcm *dpcm;
dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
- if (dpcm == NULL)
- return -ENOMEM;
+ if (! dpcm)
+ return dpcm;
init_timer(&dpcm->timer);
dpcm->timer.data = (unsigned long) dpcm;
dpcm->timer.function = snd_card_dummy_pcm_timer_function;
spin_lock_init(&dpcm->lock);
dpcm->substream = substream;
+ return dpcm;
+}
+
+static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm;
+ int err;
+
+ if ((dpcm = new_pcm_stream(substream)) == NULL)
+ return -ENOMEM;
runtime->private_data = dpcm;
runtime->private_free = snd_card_dummy_runtime_free;
runtime->hw = snd_card_dummy_playback;
@@ -362,20 +365,14 @@ static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
+static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_dummy_pcm_t *dpcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dummy_pcm *dpcm;
int err;
- dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
- if (dpcm == NULL)
+ if ((dpcm = new_pcm_stream(substream)) == NULL)
return -ENOMEM;
- init_timer(&dpcm->timer);
- dpcm->timer.data = (unsigned long) dpcm;
- dpcm->timer.function = snd_card_dummy_pcm_timer_function;
- spin_lock_init(&dpcm->lock);
- dpcm->substream = substream;
runtime->private_data = dpcm;
runtime->private_free = snd_card_dummy_runtime_free;
runtime->hw = snd_card_dummy_capture;
@@ -393,45 +390,47 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
+static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream)
{
return 0;
}
-static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
+static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream)
{
return 0;
}
-static snd_pcm_ops_t snd_card_dummy_playback_ops = {
+static struct snd_pcm_ops snd_card_dummy_playback_ops = {
.open = snd_card_dummy_playback_open,
.close = snd_card_dummy_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_card_dummy_hw_params,
.hw_free = snd_card_dummy_hw_free,
- .prepare = snd_card_dummy_playback_prepare,
- .trigger = snd_card_dummy_playback_trigger,
- .pointer = snd_card_dummy_playback_pointer,
+ .prepare = snd_card_dummy_pcm_prepare,
+ .trigger = snd_card_dummy_pcm_trigger,
+ .pointer = snd_card_dummy_pcm_pointer,
};
-static snd_pcm_ops_t snd_card_dummy_capture_ops = {
+static struct snd_pcm_ops snd_card_dummy_capture_ops = {
.open = snd_card_dummy_capture_open,
.close = snd_card_dummy_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_card_dummy_hw_params,
.hw_free = snd_card_dummy_hw_free,
- .prepare = snd_card_dummy_capture_prepare,
- .trigger = snd_card_dummy_capture_trigger,
- .pointer = snd_card_dummy_capture_pointer,
+ .prepare = snd_card_dummy_pcm_prepare,
+ .trigger = snd_card_dummy_pcm_trigger,
+ .pointer = snd_card_dummy_pcm_pointer,
};
-static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int substreams)
+static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int substreams)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
- if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm)) < 0)
+ if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device,
+ substreams, substreams, &pcm)) < 0)
return err;
+ dummy->pcm = pcm;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
pcm->private_data = dummy;
@@ -449,7 +448,8 @@ static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int su
.get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \
.private_value = addr }
-static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -458,23 +458,23 @@ static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
int addr = kcontrol->private_value;
- spin_lock_irqsave(&dummy->mixer_lock, flags);
+ spin_lock_irq(&dummy->mixer_lock);
ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0];
ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
- spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+ spin_unlock_irq(&dummy->mixer_lock);
return 0;
}
-static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
int change, addr = kcontrol->private_value;
int left, right;
@@ -488,12 +488,12 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
right = -50;
if (right > 100)
right = 100;
- spin_lock_irqsave(&dummy->mixer_lock, flags);
+ spin_lock_irq(&dummy->mixer_lock);
change = dummy->mixer_volume[addr][0] != left ||
dummy->mixer_volume[addr][1] != right;
dummy->mixer_volume[addr][0] = left;
dummy->mixer_volume[addr][1] = right;
- spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+ spin_unlock_irq(&dummy->mixer_lock);
return change;
}
@@ -503,7 +503,8 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \
.private_value = addr }
-static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_dummy_capsrc_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -512,38 +513,37 @@ static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
int addr = kcontrol->private_value;
- spin_lock_irqsave(&dummy->mixer_lock, flags);
+ spin_lock_irq(&dummy->mixer_lock);
ucontrol->value.integer.value[0] = dummy->capture_source[addr][0];
ucontrol->value.integer.value[1] = dummy->capture_source[addr][1];
- spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+ spin_unlock_irq(&dummy->mixer_lock);
return 0;
}
-static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dummy_capsrc_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
+ struct snd_dummy *dummy = snd_kcontrol_chip(kcontrol);
int change, addr = kcontrol->private_value;
int left, right;
left = ucontrol->value.integer.value[0] & 1;
right = ucontrol->value.integer.value[1] & 1;
- spin_lock_irqsave(&dummy->mixer_lock, flags);
+ spin_lock_irq(&dummy->mixer_lock);
change = dummy->capture_source[addr][0] != left &&
dummy->capture_source[addr][1] != right;
dummy->capture_source[addr][0] = left;
dummy->capture_source[addr][1] = right;
- spin_unlock_irqrestore(&dummy->mixer_lock, flags);
+ spin_unlock_irq(&dummy->mixer_lock);
return change;
}
-static snd_kcontrol_new_t snd_dummy_controls[] = {
+static struct snd_kcontrol_new snd_dummy_controls[] = {
DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
@@ -556,9 +556,9 @@ DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_MASTER)
};
-static int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
+static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy)
{
- snd_card_t *card = dummy->card;
+ struct snd_card *card = dummy->card;
unsigned int idx;
int err;
@@ -573,19 +573,18 @@ static int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
return 0;
}
-static int __init snd_card_dummy_probe(int dev)
+static int __init snd_dummy_probe(struct platform_device *devptr)
{
- snd_card_t *card;
- struct snd_card_dummy *dummy;
+ struct snd_card *card;
+ struct snd_dummy *dummy;
int idx, err;
+ int dev = devptr->id;
- if (!enable[dev])
- return -ENODEV;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_dummy));
+ sizeof(struct snd_dummy));
if (card == NULL)
return -ENOMEM;
- dummy = (struct snd_card_dummy *)card->private_data;
+ dummy = card->private_data;
dummy->card = card;
for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
if (pcm_substreams[dev] < 1)
@@ -601,11 +600,10 @@ static int __init snd_card_dummy_probe(int dev)
strcpy(card->shortname, "Dummy");
sprintf(card->longname, "Dummy %i", dev + 1);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto __nodev;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) == 0) {
- snd_dummy_cards[dev] = card;
+ platform_set_drvdata(devptr, card);
return 0;
}
__nodev:
@@ -613,34 +611,92 @@ static int __init snd_card_dummy_probe(int dev)
return err;
}
-static int __init alsa_card_dummy_init(void)
+static int snd_dummy_remove(struct platform_device *devptr)
{
- int dev, cards;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (snd_card_dummy_probe(dev) < 0) {
-#ifdef MODULE
- printk(KERN_ERR "Dummy soundcard #%i not found or device busy\n", dev + 1);
+#ifdef CONFIG_PM
+static int snd_dummy_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_dummy *dummy = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(dummy->pcm);
+ return 0;
+}
+
+static int snd_dummy_resume(struct platform_device *pdev)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+#define SND_DUMMY_DRIVER "snd_dummy"
+
+static struct platform_driver snd_dummy_driver = {
+ .probe = snd_dummy_probe,
+ .remove = snd_dummy_remove,
+#ifdef CONFIG_PM
+ .suspend = snd_dummy_suspend,
+ .resume = snd_dummy_resume,
#endif
- break;
+ .driver = {
+ .name = SND_DUMMY_DRIVER
+ },
+};
+
+static void __init_or_module snd_dummy_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_dummy_driver);
+}
+
+static int __init alsa_card_dummy_init(void)
+{
+ int i, cards, err;
+
+ if ((err = platform_driver_register(&snd_dummy_driver)) < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_DUMMY_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
}
+ devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "Dummy soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_dummy_unregister_all();
+ return err;
}
static void __exit alsa_card_dummy_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_dummy_cards[idx]);
+ snd_dummy_unregister_all();
}
module_init(alsa_card_dummy_init)
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 54e2ff9b5ca1..915589a402ab 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -23,6 +23,8 @@
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/pnp.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/mpu401.h>
@@ -56,12 +58,12 @@ MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
module_param_array(irq, int, NULL, 0444);
MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
-static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *platform_devices[SNDRV_CARDS];
static int pnp_registered = 0;
-static int snd_mpu401_create(int dev, snd_card_t **rcard)
+static int snd_mpu401_create(int dev, struct snd_card **rcard)
{
- snd_card_t *card;
+ struct snd_card *card;
int err;
*rcard = NULL;
@@ -85,12 +87,6 @@ static int snd_mpu401_create(int dev, snd_card_t **rcard)
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;
@@ -99,8 +95,12 @@ static int snd_mpu401_create(int dev, snd_card_t **rcard)
return err;
}
-static int __devinit snd_mpu401_probe(int dev)
+static int __devinit snd_mpu401_probe(struct platform_device *devptr)
{
+ int dev = devptr->id;
+ int err;
+ struct snd_card *card;
+
if (port[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR "specify port\n");
return -EINVAL;
@@ -109,9 +109,36 @@ static int __devinit snd_mpu401_probe(int dev)
snd_printk(KERN_ERR "specify or disable IRQ\n");
return -EINVAL;
}
- return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]);
+ err = snd_mpu401_create(dev, &card);
+ if (err < 0)
+ return err;
+ snd_card_set_dev(card, &devptr->dev);
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ platform_set_drvdata(devptr, card);
+ return 0;
}
+static int __devexit snd_mpu401_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define SND_MPU401_DRIVER "snd_mpu401"
+
+static struct platform_driver snd_mpu401_driver = {
+ .probe = snd_mpu401_probe,
+ .remove = __devexit_p(snd_mpu401_remove),
+ .driver = {
+ .name = SND_MPU401_DRIVER
+ },
+};
+
+
#ifdef CONFIG_PNP
#define IO_EXTENT 2
@@ -152,7 +179,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
const struct pnp_device_id *id)
{
static int dev;
- snd_card_t *card;
+ struct snd_card *card;
int err;
for ( ; dev < SNDRV_CARDS; ++dev) {
@@ -164,6 +191,10 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
err = snd_mpu401_create(dev, &card);
if (err < 0)
return err;
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
snd_card_set_dev(card, &pnp_dev->dev);
pnp_set_drvdata(pnp_dev, card);
++dev;
@@ -174,7 +205,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
{
- snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev);
+ struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev);
snd_card_disconnect(card);
snd_card_free_in_thread(card);
@@ -190,20 +221,39 @@ static struct pnp_driver snd_mpu401_pnp_driver = {
static struct pnp_driver snd_mpu401_pnp_driver;
#endif
+static void __init_or_module snd_mpu401_unregister_all(void)
+{
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_driver(&snd_mpu401_pnp_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_mpu401_driver);
+}
+
static int __init alsa_card_mpu401_init(void)
{
- int dev, devices = 0;
- int err;
+ int i, err, devices;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev])
- continue;
+ if ((err = platform_driver_register(&snd_mpu401_driver)) < 0)
+ return err;
+
+ devices = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
#ifdef CONFIG_PNP
- if (pnp[dev])
+ if (pnp[i])
continue;
#endif
- if (snd_mpu401_probe(dev) >= 0)
- devices++;
+ device = platform_device_register_simple(SND_MPU401_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ devices++;
}
if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
pnp_registered = 1;
@@ -214,21 +264,19 @@ static int __init alsa_card_mpu401_init(void)
#ifdef MODULE
printk(KERN_ERR "MPU-401 device not found or device busy\n");
#endif
- if (pnp_registered)
- pnp_unregister_driver(&snd_mpu401_pnp_driver);
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_mpu401_unregister_all();
+ return err;
}
static void __exit alsa_card_mpu401_exit(void)
{
- int idx;
-
- if (pnp_registered)
- pnp_unregister_driver(&snd_mpu401_pnp_driver);
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_mpu401_legacy_cards[idx]);
+ snd_mpu401_unregister_all();
}
module_init(alsa_card_mpu401_init)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index bdeb2c00dac5..8687ae3c66b8 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -43,8 +43,8 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode");
MODULE_LICENSE("GPL");
-static void snd_mpu401_uart_input_read(mpu401_t * mpu);
-static void snd_mpu401_uart_output_write(mpu401_t * mpu);
+static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu);
+static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
/*
@@ -58,28 +58,28 @@ static void snd_mpu401_uart_output_write(mpu401_t * mpu);
#define MPU401_ACK 0xfe
/* Build in lowlevel io */
-static void mpu401_write_port(mpu401_t *mpu, unsigned char data, unsigned long addr)
+static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
{
outb(data, addr);
}
-static unsigned char mpu401_read_port(mpu401_t *mpu, unsigned long addr)
+static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr)
{
return inb(addr);
}
-static void mpu401_write_mmio(mpu401_t *mpu, unsigned char data, unsigned long addr)
+static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
{
writeb(data, (void __iomem *)addr);
}
-static unsigned char mpu401_read_mmio(mpu401_t *mpu, unsigned long addr)
+static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr)
{
return readb((void __iomem *)addr);
}
/* */
-static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
+static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
{
int timeout = 100000;
for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
@@ -90,7 +90,7 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
#endif
}
-static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
+static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
{
spin_lock(&mpu->input_lock);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
@@ -118,7 +118,7 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
*/
irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- mpu401_t *mpu = dev_id;
+ struct snd_mpu401 *mpu = dev_id;
if (mpu == NULL)
return IRQ_NONE;
@@ -132,13 +132,14 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
*/
static void snd_mpu401_uart_timer(unsigned long data)
{
- mpu401_t *mpu = (mpu401_t *)data;
+ struct snd_mpu401 *mpu = (struct snd_mpu401 *)data;
+ unsigned long flags;
- spin_lock(&mpu->timer_lock);
+ spin_lock_irqsave(&mpu->timer_lock, flags);
/*mpu->mode |= MPU401_MODE_TIMER;*/
mpu->timer.expires = 1 + jiffies;
add_timer(&mpu->timer);
- spin_unlock(&mpu->timer_lock);
+ spin_unlock_irqrestore(&mpu->timer_lock, flags);
if (mpu->rmidi)
_snd_mpu401_uart_interrupt(mpu);
}
@@ -146,7 +147,7 @@ static void snd_mpu401_uart_timer(unsigned long data)
/*
* initialize the timer callback if not programmed yet
*/
-static void snd_mpu401_uart_add_timer (mpu401_t *mpu, int input)
+static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
{
unsigned long flags;
@@ -165,7 +166,7 @@ static void snd_mpu401_uart_add_timer (mpu401_t *mpu, int input)
/*
* remove the timer callback if still active
*/
-static void snd_mpu401_uart_remove_timer (mpu401_t *mpu, int input)
+static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
{
unsigned long flags;
@@ -182,7 +183,7 @@ static void snd_mpu401_uart_remove_timer (mpu401_t *mpu, int input)
*/
-static void snd_mpu401_uart_cmd(mpu401_t * mpu, unsigned char cmd, int ack)
+static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
{
unsigned long flags;
int timeout, ok;
@@ -225,9 +226,9 @@ static void snd_mpu401_uart_cmd(mpu401_t * mpu, unsigned char cmd, int ack)
/*
* input/output open/close - protected by open_mutex in rawmidi.c
*/
-static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
+static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
{
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
int err;
mpu = substream->rmidi->private_data;
@@ -242,9 +243,9 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
+static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
{
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
int err;
mpu = substream->rmidi->private_data;
@@ -259,9 +260,9 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
+static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
{
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
@@ -273,9 +274,9 @@ static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
+static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
{
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
mpu = substream->rmidi->private_data;
clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
@@ -290,10 +291,10 @@ static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
/*
* trigger input callback
*/
-static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
int max = 64;
mpu = substream->rmidi->private_data;
@@ -321,7 +322,7 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
* transfer input pending data
* call with input_lock spinlock held
*/
-static void snd_mpu401_uart_input_read(mpu401_t * mpu)
+static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
{
int max = 128;
unsigned char byte;
@@ -349,7 +350,7 @@ static void snd_mpu401_uart_input_read(mpu401_t * mpu)
* write output pending bytes
* call with output_lock spinlock held
*/
-static void snd_mpu401_uart_output_write(mpu401_t * mpu)
+static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
{
unsigned char byte;
int max = 256, timeout;
@@ -375,10 +376,10 @@ static void snd_mpu401_uart_output_write(mpu401_t * mpu)
/*
* output trigger callback
*/
-static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
mpu = substream->rmidi->private_data;
if (up) {
@@ -404,23 +405,23 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
*/
-static snd_rawmidi_ops_t snd_mpu401_uart_output =
+static struct snd_rawmidi_ops snd_mpu401_uart_output =
{
.open = snd_mpu401_uart_output_open,
.close = snd_mpu401_uart_output_close,
.trigger = snd_mpu401_uart_output_trigger,
};
-static snd_rawmidi_ops_t snd_mpu401_uart_input =
+static struct snd_rawmidi_ops snd_mpu401_uart_input =
{
.open = snd_mpu401_uart_input_open,
.close = snd_mpu401_uart_input_close,
.trigger = snd_mpu401_uart_input_trigger,
};
-static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
+static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
{
- mpu401_t *mpu = rmidi->private_data;
+ struct snd_mpu401 *mpu = rmidi->private_data;
if (mpu->irq_flags && mpu->irq >= 0)
free_irq(mpu->irq, (void *) mpu);
release_and_free_resource(mpu->res);
@@ -442,18 +443,18 @@ static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
*
* Note that the rawmidi instance is returned on the rrawmidi argument,
* not the mpu401 instance itself. To access to the mpu401 instance,
- * cast from rawmidi->private_data (with mpu401_t magic-cast).
+ * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
*
* Returns zero if successful, or a negative error code.
*/
-int snd_mpu401_uart_new(snd_card_t * card, int device,
+int snd_mpu401_uart_new(struct snd_card *card, int device,
unsigned short hardware,
unsigned long port, int integrated,
int irq, int irq_flags,
- snd_rawmidi_t ** rrawmidi)
+ struct snd_rawmidi ** rrawmidi)
{
- mpu401_t *mpu;
- snd_rawmidi_t *rmidi;
+ struct snd_mpu401 *mpu;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
@@ -462,6 +463,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
return err;
mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
if (mpu == NULL) {
+ snd_printk(KERN_ERR "mpu401_uart: cannot allocate\n");
snd_device_free(card, rmidi);
return -ENOMEM;
}
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index e9d52c668edc..b7a0b42813e1 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -53,6 +53,8 @@
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/moduleparam.h>
@@ -93,6 +95,8 @@ MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
module_param(hwports, int, 0444);
MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
+static struct platform_device *device;
+
/*
* defines
*/
@@ -125,17 +129,17 @@ MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
/*
*/
-typedef struct mtpav_port {
+struct mtpav_port {
u8 number;
u8 hwport;
u8 mode;
u8 running_status;
- snd_rawmidi_substream_t *input;
- snd_rawmidi_substream_t *output;
-} mtpav_port_t;
+ struct snd_rawmidi_substream *input;
+ struct snd_rawmidi_substream *output;
+};
-typedef struct mtpav {
- snd_card_t *card;
+struct mtpav {
+ struct snd_card *card;
unsigned long port;
struct resource *res_port;
int irq; /* interrupt (for inputs) */
@@ -143,24 +147,18 @@ typedef struct mtpav {
int share_irq; /* number of accesses to input interrupts */
int istimer; /* number of accesses to timer interrupts */
struct timer_list timer; /* timer interrupts for outputs */
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int num_ports; /* number of hw ports (1-8) */
- mtpav_port_t ports[NUMPORTS]; /* all ports including computer, adat and bc */
+ struct mtpav_port ports[NUMPORTS]; /* all ports including computer, adat and bc */
u32 inmidiport; /* selected input midi port */
u32 inmidistate; /* during midi command 0xf5 */
u32 outmidihwport; /* selected output midi hw port */
-} mtpav_t;
+};
/*
- * global instance
- * hey, we handle at most only one card..
- */
-static mtpav_t *mtp_card;
-
-/*
* possible hardware ports (selected by 0xf5 port message)
* 0x00 all ports
* 0x01 .. 0x08 this MTP's ports 1..8
@@ -183,7 +181,7 @@ static mtpav_t *mtp_card;
#define MTPAV_PIDX_BROADCAST 2
-static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev)
+static int translate_subdevice_to_hwport(struct mtpav *chip, int subdev)
{
if (subdev < 0)
return 0x01; /* invalid - use port 0 as default */
@@ -198,7 +196,7 @@ static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev)
return 0; /* all ports */
}
-static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport)
+static int translate_hwport_to_subdevice(struct mtpav *chip, int hwport)
{
int p;
if (hwport <= 0x00) /* all ports */
@@ -223,7 +221,7 @@ static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport)
/*
*/
-static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg)
+static u8 snd_mtpav_getreg(struct mtpav *chip, u16 reg)
{
u8 rval = 0;
@@ -241,19 +239,16 @@ static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg)
/*
*/
-static void snd_mtpav_mputreg(mtpav_t *chip, u16 reg, u8 val)
+static inline void snd_mtpav_mputreg(struct mtpav *chip, u16 reg, u8 val)
{
- if (reg == DREG) {
- outb(val, chip->port + DREG);
- } else if (reg == CREG) {
- outb(val, chip->port + CREG);
- }
+ if (reg == DREG || reg == CREG)
+ outb(val, chip->port + reg);
}
/*
*/
-static void snd_mtpav_wait_rfdhi(mtpav_t *chip)
+static void snd_mtpav_wait_rfdhi(struct mtpav *chip)
{
int counts = 10000;
u8 sbyte;
@@ -265,7 +260,7 @@ static void snd_mtpav_wait_rfdhi(mtpav_t *chip)
}
}
-static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte)
+static void snd_mtpav_send_byte(struct mtpav *chip, u8 byte)
{
u8 tcbyt;
u8 clrwrite;
@@ -291,8 +286,9 @@ static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte)
*/
/* call this with spin lock held */
-static void snd_mtpav_output_port_write(mtpav_port_t *port,
- snd_rawmidi_substream_t *substream)
+static void snd_mtpav_output_port_write(struct mtpav *mtp_card,
+ struct mtpav_port *portp,
+ struct snd_rawmidi_substream *substream)
{
u8 outbyte;
@@ -303,34 +299,35 @@ static void snd_mtpav_output_port_write(mtpav_port_t *port,
// send port change command if necessary
- if (port->hwport != mtp_card->outmidihwport) {
- mtp_card->outmidihwport = port->hwport;
+ if (portp->hwport != mtp_card->outmidihwport) {
+ mtp_card->outmidihwport = portp->hwport;
snd_mtpav_send_byte(mtp_card, 0xf5);
- snd_mtpav_send_byte(mtp_card, port->hwport);
- //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport);
+ snd_mtpav_send_byte(mtp_card, portp->hwport);
+ //snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport);
- if (!(outbyte & 0x80) && port->running_status)
- snd_mtpav_send_byte(mtp_card, port->running_status);
+ if (!(outbyte & 0x80) && portp->running_status)
+ snd_mtpav_send_byte(mtp_card, portp->running_status);
}
// send data
do {
if (outbyte & 0x80)
- port->running_status = outbyte;
+ portp->running_status = outbyte;
snd_mtpav_send_byte(mtp_card, outbyte);
} while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
}
-static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream)
+static void snd_mtpav_output_write(struct snd_rawmidi_substream *substream)
{
- mtpav_port_t *port = &mtp_card->ports[substream->number];
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
spin_lock_irqsave(&mtp_card->spinlock, flags);
- snd_mtpav_output_port_write(port, substream);
+ snd_mtpav_output_port_write(mtp_card, portp, substream);
spin_unlock_irqrestore(&mtp_card->spinlock, flags);
}
@@ -339,7 +336,7 @@ static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream)
* mtpav control
*/
-static void snd_mtpav_portscan(mtpav_t *chip) // put mtp into smart routing mode
+static void snd_mtpav_portscan(struct mtpav *chip) // put mtp into smart routing mode
{
u8 p;
@@ -353,12 +350,12 @@ static void snd_mtpav_portscan(mtpav_t *chip) // put mtp into smart routing mode
/*
*/
-static int snd_mtpav_input_open(snd_rawmidi_substream_t * substream)
+static int snd_mtpav_input_open(struct snd_rawmidi_substream *substream)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
- //printk("mtpav port: %d opened\n", (int) substream->number);
spin_lock_irqsave(&mtp_card->spinlock, flags);
portp->mode |= MTPAV_MODE_INPUT_OPENED;
portp->input = substream;
@@ -371,20 +368,17 @@ static int snd_mtpav_input_open(snd_rawmidi_substream_t * substream)
/*
*/
-static int snd_mtpav_input_close(snd_rawmidi_substream_t *substream)
+static int snd_mtpav_input_close(struct snd_rawmidi_substream *substream)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
-
- //printk("mtpav port: %d closed\n", (int) portp);
spin_lock_irqsave(&mtp_card->spinlock, flags);
-
- portp->mode &= (~MTPAV_MODE_INPUT_OPENED);
+ portp->mode &= ~MTPAV_MODE_INPUT_OPENED;
portp->input = NULL;
if (--mtp_card->share_irq == 0)
snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts
-
spin_unlock_irqrestore(&mtp_card->spinlock, flags);
return 0;
}
@@ -392,10 +386,11 @@ static int snd_mtpav_input_close(snd_rawmidi_substream_t *substream)
/*
*/
-static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_mtpav_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
spin_lock_irqsave(&mtp_card->spinlock, flags);
if (up)
@@ -414,7 +409,7 @@ static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
static void snd_mtpav_output_timer(unsigned long data)
{
unsigned long flags;
- mtpav_t *chip = (mtpav_t *)data;
+ struct mtpav *chip = (struct mtpav *)data;
int p;
spin_lock_irqsave(&chip->spinlock, flags);
@@ -423,25 +418,22 @@ static void snd_mtpav_output_timer(unsigned long data)
add_timer(&chip->timer);
/* process each port */
for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
- mtpav_port_t *portp = &mtp_card->ports[p];
+ struct mtpav_port *portp = &chip->ports[p];
if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
- snd_mtpav_output_port_write(portp, portp->output);
+ snd_mtpav_output_port_write(chip, portp, portp->output);
}
spin_unlock_irqrestore(&chip->spinlock, flags);
}
/* spinlock held! */
-static void snd_mtpav_add_output_timer(mtpav_t *chip)
+static void snd_mtpav_add_output_timer(struct mtpav *chip)
{
- init_timer(&chip->timer);
- chip->timer.function = snd_mtpav_output_timer;
- chip->timer.data = (unsigned long) mtp_card;
chip->timer.expires = 1 + jiffies;
add_timer(&chip->timer);
}
/* spinlock held! */
-static void snd_mtpav_remove_output_timer(mtpav_t *chip)
+static void snd_mtpav_remove_output_timer(struct mtpav *chip)
{
del_timer(&chip->timer);
}
@@ -449,10 +441,11 @@ static void snd_mtpav_remove_output_timer(mtpav_t *chip)
/*
*/
-static int snd_mtpav_output_open(snd_rawmidi_substream_t * substream)
+static int snd_mtpav_output_open(struct snd_rawmidi_substream *substream)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
spin_lock_irqsave(&mtp_card->spinlock, flags);
portp->mode |= MTPAV_MODE_OUTPUT_OPENED;
@@ -464,13 +457,14 @@ static int snd_mtpav_output_open(snd_rawmidi_substream_t * substream)
/*
*/
-static int snd_mtpav_output_close(snd_rawmidi_substream_t * substream)
+static int snd_mtpav_output_close(struct snd_rawmidi_substream *substream)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
spin_lock_irqsave(&mtp_card->spinlock, flags);
- portp->mode &= (~MTPAV_MODE_OUTPUT_OPENED);
+ portp->mode &= ~MTPAV_MODE_OUTPUT_OPENED;
portp->output = NULL;
spin_unlock_irqrestore(&mtp_card->spinlock, flags);
return 0;
@@ -479,14 +473,15 @@ static int snd_mtpav_output_close(snd_rawmidi_substream_t * substream)
/*
*/
-static void snd_mtpav_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_mtpav_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
+ struct mtpav *mtp_card = substream->rmidi->private_data;
+ struct mtpav_port *portp = &mtp_card->ports[substream->number];
unsigned long flags;
- mtpav_port_t *portp = &mtp_card->ports[substream->number];
spin_lock_irqsave(&mtp_card->spinlock, flags);
if (up) {
- if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {
+ if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {
if (mtp_card->istimer++ == 0)
snd_mtpav_add_output_timer(mtp_card);
portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;
@@ -506,23 +501,20 @@ static void snd_mtpav_output_trigger(snd_rawmidi_substream_t * substream, int up
* midi interrupt for inputs
*/
-static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
+static void snd_mtpav_inmidi_process(struct mtpav *mcrd, u8 inbyte)
{
- mtpav_port_t *portp;
+ struct mtpav_port *portp;
if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)
return;
portp = &mcrd->ports[mcrd->inmidiport];
- if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
+ if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED)
snd_rawmidi_receive(portp->input, &inbyte, 1);
- }
}
-static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte)
+static void snd_mtpav_inmidi_h(struct mtpav *mcrd, u8 inbyte)
{
- snd_assert(mcrd, return);
-
if (inbyte >= 0xf8) {
/* real-time midi code */
snd_mtpav_inmidi_process(mcrd, inbyte);
@@ -540,7 +532,7 @@ static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte)
}
}
-static void snd_mtpav_read_bytes(mtpav_t * mcrd)
+static void snd_mtpav_read_bytes(struct mtpav *mcrd)
{
u8 clrread, setread;
u8 mtp_read_byte;
@@ -580,9 +572,8 @@ static void snd_mtpav_read_bytes(mtpav_t * mcrd)
static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
{
- mtpav_t *mcard = dev_id;
+ struct mtpav *mcard = dev_id;
- //printk("irqh()\n");
spin_lock(&mcard->spinlock);
snd_mtpav_read_bytes(mcard);
spin_unlock(&mcard->spinlock);
@@ -592,14 +583,14 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
/*
* get ISA resources
*/
-static int snd_mtpav_get_ISA(mtpav_t * mcard)
+static int __init snd_mtpav_get_ISA(struct mtpav * mcard)
{
if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
snd_printk("MTVAP port 0x%lx is busy\n", port);
return -EBUSY;
}
mcard->port = port;
- if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", (void *)mcard)) {
+ if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", mcard)) {
snd_printk("MTVAP IRQ %d busy\n", irq);
return -EBUSY;
}
@@ -611,13 +602,13 @@ static int snd_mtpav_get_ISA(mtpav_t * mcard)
/*
*/
-static snd_rawmidi_ops_t snd_mtpav_output = {
+static struct snd_rawmidi_ops snd_mtpav_output = {
.open = snd_mtpav_output_open,
.close = snd_mtpav_output_close,
.trigger = snd_mtpav_output_trigger,
};
-static snd_rawmidi_ops_t snd_mtpav_input = {
+static struct snd_rawmidi_ops snd_mtpav_input = {
.open = snd_mtpav_input_open,
.close = snd_mtpav_input_close,
.trigger = snd_mtpav_input_trigger,
@@ -628,7 +619,8 @@ static snd_rawmidi_ops_t snd_mtpav_input = {
* get RAWMIDI resources
*/
-static void snd_mtpav_set_name(mtpav_t *chip, snd_rawmidi_substream_t *substream)
+static void __init snd_mtpav_set_name(struct mtpav *chip,
+ struct snd_rawmidi_substream *substream)
{
if (substream->number >= 0 && substream->number < chip->num_ports)
sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
@@ -642,21 +634,18 @@ static void snd_mtpav_set_name(mtpav_t *chip, snd_rawmidi_substream_t *substream
strcpy(substream->name, "MTP broadcast");
}
-static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
+static int __init snd_mtpav_get_RAWMIDI(struct mtpav *mcard)
{
- int rval = 0;
- snd_rawmidi_t *rawmidi;
- snd_rawmidi_substream_t *substream;
+ int rval;
+ struct snd_rawmidi *rawmidi;
+ struct snd_rawmidi_substream *substream;
struct list_head *list;
- //printk("entering snd_mtpav_get_RAWMIDI\n");
-
if (hwports < 1)
- mcard->num_ports = 1;
+ hwports = 1;
else if (hwports > 8)
- mcard->num_ports = 8;
- else
- mcard->num_ports = hwports;
+ hwports = 8;
+ mcard->num_ports = hwports;
if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
@@ -664,14 +653,15 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
&mcard->rmidi)) < 0)
return rval;
rawmidi = mcard->rmidi;
+ rawmidi->private_data = mcard;
list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
snd_mtpav_set_name(mcard, substream);
substream->ops = &snd_mtpav_input;
}
list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
- substream = list_entry(list, snd_rawmidi_substream_t, list);
+ substream = list_entry(list, struct snd_rawmidi_substream, list);
snd_mtpav_set_name(mcard, substream);
substream->ops = &snd_mtpav_output;
mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);
@@ -679,36 +669,15 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
sprintf(rawmidi->name, "MTP AV MIDI");
- //printk("exiting snd_mtpav_get_RAWMIDI() \n");
return 0;
}
/*
*/
-static mtpav_t *new_mtpav(void)
-{
- mtpav_t *ncrd = kzalloc(sizeof(*ncrd), GFP_KERNEL);
- if (ncrd != NULL) {
- spin_lock_init(&ncrd->spinlock);
-
- init_timer(&ncrd->timer);
- ncrd->card = NULL;
- ncrd->irq = -1;
- ncrd->share_irq = 0;
-
- ncrd->inmidiport = 0xffffffff;
- ncrd->inmidistate = 0;
- ncrd->outmidihwport = 0xffffffff;
- }
- return ncrd;
-}
-
-/*
- */
-
-static void free_mtpav(mtpav_t * crd)
+static void snd_mtpav_free(struct snd_card *card)
{
+ struct mtpav *crd = card->private_data;
unsigned long flags;
spin_lock_irqsave(&crd->spinlock, flags);
@@ -718,78 +687,101 @@ static void free_mtpav(mtpav_t * crd)
if (crd->irq >= 0)
free_irq(crd->irq, (void *)crd);
release_and_free_resource(crd->res_port);
- kfree(crd);
}
/*
*/
-
-static int __init alsa_card_mtpav_init(void)
+static int __init snd_mtpav_probe(struct platform_device *dev)
{
- int err = 0;
- char longname_buffer[80];
+ struct snd_card *card;
+ int err;
+ struct mtpav *mtp_card;
- mtp_card = new_mtpav();
- if (mtp_card == NULL)
+ card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card));
+ if (! card)
return -ENOMEM;
- mtp_card->card = snd_card_new(index, id, THIS_MODULE, 0);
- if (mtp_card->card == NULL) {
- free_mtpav(mtp_card);
- return -ENOMEM;
- }
+ mtp_card = card->private_data;
+ spin_lock_init(&mtp_card->spinlock);
+ init_timer(&mtp_card->timer);
+ mtp_card->card = card;
+ mtp_card->irq = -1;
+ mtp_card->share_irq = 0;
+ mtp_card->inmidiport = 0xffffffff;
+ mtp_card->inmidistate = 0;
+ mtp_card->outmidihwport = 0xffffffff;
+ init_timer(&mtp_card->timer);
+ mtp_card->timer.function = snd_mtpav_output_timer;
+ mtp_card->timer.data = (unsigned long) mtp_card;
+
+ card->private_free = snd_mtpav_free;
err = snd_mtpav_get_ISA(mtp_card);
- //printk("snd_mtpav_get_ISA returned: %d\n", err);
if (err < 0)
goto __error;
- strcpy(mtp_card->card->driver, "MTPAV");
- strcpy(mtp_card->card->shortname, "MTPAV on parallel port");
- memset(longname_buffer, 0, sizeof(longname_buffer));
- sprintf(longname_buffer, "MTPAV on parallel port at");
+ strcpy(card->driver, "MTPAV");
+ strcpy(card->shortname, "MTPAV on parallel port");
+ snprintf(card->longname, sizeof(card->longname),
+ "MTPAV on parallel port at 0x%lx", port);
err = snd_mtpav_get_RAWMIDI(mtp_card);
- //snd_printk("snd_mtapv_get_RAWMIDI returned: %d\n", err);
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!
+ snd_mtpav_portscan(mtp_card);
- //printk("snd_card_register returned %d\n", err);
+ snd_card_set_dev(card, &dev->dev);
+ err = snd_card_register(mtp_card->card);
if (err < 0)
goto __error;
-
- snd_mtpav_portscan(mtp_card);
-
+ platform_set_drvdata(dev, card);
printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
-
return 0;
- __error:
- snd_card_free(mtp_card->card);
- free_mtpav(mtp_card);
+ __error:
+ snd_card_free(card);
return err;
}
-/*
- */
+static int snd_mtpav_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
-static void __exit alsa_card_mtpav_exit(void)
+#define SND_MTPAV_DRIVER "snd_mtpav"
+
+static struct platform_driver snd_mtpav_driver = {
+ .probe = snd_mtpav_probe,
+ .remove = snd_mtpav_remove,
+ .driver = {
+ .name = SND_MTPAV_DRIVER
+ },
+};
+
+static int __init alsa_card_mtpav_init(void)
{
- if (mtp_card == NULL)
- return;
- if (mtp_card->card)
- snd_card_free(mtp_card->card);
- free_mtpav(mtp_card);
+ int err;
+
+ if ((err = platform_driver_register(&snd_mtpav_driver)) < 0)
+ return err;
+
+ device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
+ if (IS_ERR(device)) {
+ platform_driver_unregister(&snd_mtpav_driver);
+ return PTR_ERR(device);
+ }
+ return 0;
}
-/*
- */
+static void __exit alsa_card_mtpav_exit(void)
+{
+ platform_device_unregister(device);
+ platform_driver_unregister(&snd_mtpav_driver);
+}
module_init(alsa_card_mtpav_init)
module_exit(alsa_card_mtpav_exit)
diff --git a/sound/drivers/opl3/opl3_drums.c b/sound/drivers/opl3/opl3_drums.c
index f26332680c19..73694380734a 100644
--- a/sound/drivers/opl3/opl3_drums.c
+++ b/sound/drivers/opl3/opl3_drums.c
@@ -45,7 +45,7 @@ static char snd_opl3_drum_table[47] =
OPL3_CYMBAL_ON, OPL3_CYMBAL_ON /* 80 - 81 */
};
-typedef struct snd_opl3_drum_voice {
+struct snd_opl3_drum_voice {
int voice;
int op;
unsigned char am_vib;
@@ -54,33 +54,34 @@ typedef struct snd_opl3_drum_voice {
unsigned char sustain_release;
unsigned char feedback_connection;
unsigned char wave_select;
-} snd_opl3_drum_voice_t;
+};
-typedef struct snd_opl3_drum_note {
+struct snd_opl3_drum_note {
int voice;
unsigned char fnum;
unsigned char octave_f;
unsigned char feedback_connection;
-} snd_opl3_drum_note_t;
+};
-static snd_opl3_drum_voice_t bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
-static snd_opl3_drum_voice_t bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
-static snd_opl3_drum_note_t bass_note = {6, 0x90, 0x09};
+static struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
+static struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
+static struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09};
-static snd_opl3_drum_voice_t hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
+static struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
-static snd_opl3_drum_voice_t snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
-static snd_opl3_drum_note_t snare_note = {7, 0xf4, 0x0d};
+static struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
+static struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d};
-static snd_opl3_drum_voice_t tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
-static snd_opl3_drum_note_t tomtom_note = {8, 0xf4, 0x09};
+static struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
+static struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09};
-static snd_opl3_drum_voice_t cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
+static struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
/*
* set drum voice characteristics
*/
-static void snd_opl3_drum_voice_set(opl3_t *opl3, snd_opl3_drum_voice_t *data)
+static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3,
+ struct snd_opl3_drum_voice *data)
{
unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
unsigned char voice_offset = data->voice;
@@ -114,7 +115,8 @@ static void snd_opl3_drum_voice_set(opl3_t *opl3, snd_opl3_drum_voice_t *data)
/*
* Set drum voice pitch
*/
-static void snd_opl3_drum_note_set(opl3_t *opl3, snd_opl3_drum_note_t *data)
+static void snd_opl3_drum_note_set(struct snd_opl3 *opl3,
+ struct snd_opl3_drum_note *data)
{
unsigned char voice_offset = data->voice;
unsigned short opl3_reg;
@@ -131,8 +133,9 @@ static void snd_opl3_drum_note_set(opl3_t *opl3, snd_opl3_drum_note_t *data)
/*
* Set drum voice volume and position
*/
-static void snd_opl3_drum_vol_set(opl3_t *opl3, snd_opl3_drum_voice_t *data,
- int vel, snd_midi_channel_t *chan)
+static void snd_opl3_drum_vol_set(struct snd_opl3 *opl3,
+ struct snd_opl3_drum_voice *data,
+ int vel, struct snd_midi_channel *chan)
{
unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
unsigned char voice_offset = data->voice;
@@ -159,7 +162,7 @@ static void snd_opl3_drum_vol_set(opl3_t *opl3, snd_opl3_drum_voice_t *data,
/*
* Loads drum voices at init time
*/
-void snd_opl3_load_drums(opl3_t *opl3)
+void snd_opl3_load_drums(struct snd_opl3 *opl3)
{
snd_opl3_drum_voice_set(opl3, &bass_op0);
snd_opl3_drum_voice_set(opl3, &bass_op1);
@@ -179,11 +182,11 @@ void snd_opl3_load_drums(opl3_t *opl3)
/*
* Switch drum voice on or off
*/
-void snd_opl3_drum_switch(opl3_t *opl3, int note, int vel, int on_off,
- snd_midi_channel_t *chan)
+void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int vel, int on_off,
+ struct snd_midi_channel *chan)
{
unsigned char drum_mask;
- snd_opl3_drum_voice_t *drum_voice;
+ struct snd_opl3_drum_voice *drum_voice;
if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE))
return;
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 06246503083c..1e0c76b9acfc 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
-static void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
+static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
{
unsigned long flags;
unsigned long port;
@@ -60,7 +60,7 @@ static void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char va
spin_unlock_irqrestore(&opl3->reg_lock, flags);
}
-static void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
+static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)
{
unsigned long flags;
unsigned long port;
@@ -85,7 +85,7 @@ static void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char va
spin_unlock_irqrestore(&opl3->reg_lock, flags);
}
-static int snd_opl3_detect(opl3_t * opl3)
+static int snd_opl3_detect(struct snd_opl3 * opl3)
{
/*
* This function returns 1 if the FM chip is present at the given I/O port
@@ -153,12 +153,12 @@ static int snd_opl3_detect(opl3_t * opl3)
* Timer 1 - 80us
*/
-static int snd_opl3_timer1_start(snd_timer_t * timer)
+static int snd_opl3_timer1_start(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
unsigned int ticks;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = snd_timer_chip(timer);
spin_lock_irqsave(&opl3->timer_lock, flags);
@@ -171,11 +171,11 @@ static int snd_opl3_timer1_start(snd_timer_t * timer)
return 0;
}
-static int snd_opl3_timer1_stop(snd_timer_t * timer)
+static int snd_opl3_timer1_stop(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = snd_timer_chip(timer);
spin_lock_irqsave(&opl3->timer_lock, flags);
@@ -190,12 +190,12 @@ static int snd_opl3_timer1_stop(snd_timer_t * timer)
* Timer 2 - 320us
*/
-static int snd_opl3_timer2_start(snd_timer_t * timer)
+static int snd_opl3_timer2_start(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
unsigned int ticks;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = snd_timer_chip(timer);
spin_lock_irqsave(&opl3->timer_lock, flags);
@@ -208,11 +208,11 @@ static int snd_opl3_timer2_start(snd_timer_t * timer)
return 0;
}
-static int snd_opl3_timer2_stop(snd_timer_t * timer)
+static int snd_opl3_timer2_stop(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = snd_timer_chip(timer);
spin_lock_irqsave(&opl3->timer_lock, flags);
@@ -227,7 +227,7 @@ static int snd_opl3_timer2_stop(snd_timer_t * timer)
*/
-static struct _snd_timer_hardware snd_opl3_timer1 =
+static struct snd_timer_hardware snd_opl3_timer1 =
{
.flags = SNDRV_TIMER_HW_STOP,
.resolution = 80000,
@@ -236,7 +236,7 @@ static struct _snd_timer_hardware snd_opl3_timer1 =
.stop = snd_opl3_timer1_stop,
};
-static struct _snd_timer_hardware snd_opl3_timer2 =
+static struct snd_timer_hardware snd_opl3_timer2 =
{
.flags = SNDRV_TIMER_HW_STOP,
.resolution = 320000,
@@ -245,10 +245,10 @@ static struct _snd_timer_hardware snd_opl3_timer2 =
.stop = snd_opl3_timer2_stop,
};
-static int snd_opl3_timer1_init(opl3_t * opl3, int timer_no)
+static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no)
{
- snd_timer_t *timer = NULL;
- snd_timer_id_t tid;
+ struct snd_timer *timer = NULL;
+ struct snd_timer_id tid;
int err;
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
@@ -265,10 +265,10 @@ static int snd_opl3_timer1_init(opl3_t * opl3, int timer_no)
return err;
}
-static int snd_opl3_timer2_init(opl3_t * opl3, int timer_no)
+static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
{
- snd_timer_t *timer = NULL;
- snd_timer_id_t tid;
+ struct snd_timer *timer = NULL;
+ struct snd_timer_id tid;
int err;
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
@@ -289,11 +289,11 @@ static int snd_opl3_timer2_init(opl3_t * opl3, int timer_no)
*/
-void snd_opl3_interrupt(snd_hwdep_t * hw)
+void snd_opl3_interrupt(struct snd_hwdep * hw)
{
unsigned char status;
- opl3_t *opl3;
- snd_timer_t *timer;
+ struct snd_opl3 *opl3;
+ struct snd_timer *timer;
if (hw == NULL)
return;
@@ -320,7 +320,7 @@ void snd_opl3_interrupt(snd_hwdep_t * hw)
*/
-static int snd_opl3_free(opl3_t *opl3)
+static int snd_opl3_free(struct snd_opl3 *opl3)
{
snd_assert(opl3 != NULL, return -ENXIO);
if (opl3->private_free)
@@ -331,26 +331,28 @@ static int snd_opl3_free(opl3_t *opl3)
return 0;
}
-static int snd_opl3_dev_free(snd_device_t *device)
+static int snd_opl3_dev_free(struct snd_device *device)
{
- opl3_t *opl3 = device->device_data;
+ struct snd_opl3 *opl3 = device->device_data;
return snd_opl3_free(opl3);
}
-int snd_opl3_new(snd_card_t *card,
+int snd_opl3_new(struct snd_card *card,
unsigned short hardware,
- opl3_t **ropl3)
+ struct snd_opl3 **ropl3)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_opl3_dev_free,
};
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int err;
*ropl3 = NULL;
opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
- if (opl3 == NULL)
+ if (opl3 == NULL) {
+ snd_printk(KERN_ERR "opl3: cannot allocate\n");
return -ENOMEM;
+ }
opl3->card = card;
opl3->hardware = hardware;
@@ -367,7 +369,7 @@ int snd_opl3_new(snd_card_t *card,
return 0;
}
-int snd_opl3_init(opl3_t *opl3)
+int snd_opl3_init(struct snd_opl3 *opl3)
{
if (! opl3->command) {
printk(KERN_ERR "snd_opl3_init: command not defined!\n");
@@ -391,14 +393,14 @@ int snd_opl3_init(opl3_t *opl3)
return 0;
}
-int snd_opl3_create(snd_card_t * card,
+int snd_opl3_create(struct snd_card *card,
unsigned long l_port,
unsigned long r_port,
unsigned short hardware,
int integrated,
- opl3_t ** ropl3)
+ struct snd_opl3 ** ropl3)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int err;
*ropl3 = NULL;
@@ -407,13 +409,13 @@ int snd_opl3_create(snd_card_t * card,
if (! integrated) {
if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) {
snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
- snd_opl3_free(opl3);
+ snd_device_free(card, opl3);
return -EBUSY;
}
if (r_port != 0 &&
(opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
- snd_opl3_free(opl3);
+ snd_device_free(card, opl3);
return -EBUSY;
}
}
@@ -432,7 +434,7 @@ int snd_opl3_create(snd_card_t * card,
if ((err = snd_opl3_detect(opl3)) < 0) {
snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
opl3->l_port, opl3->r_port);
- snd_opl3_free(opl3);
+ snd_device_free(card, opl3);
return err;
}
/* detect routine returns correct hardware type */
@@ -449,7 +451,7 @@ int snd_opl3_create(snd_card_t * card,
return 0;
}
-int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev)
+int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
{
int err;
@@ -466,12 +468,12 @@ int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev)
return 0;
}
-int snd_opl3_hwdep_new(opl3_t * opl3,
+int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
int device, int seq_device,
- snd_hwdep_t ** rhwdep)
+ struct snd_hwdep ** rhwdep)
{
- snd_hwdep_t *hw;
- snd_card_t *card = opl3->card;
+ struct snd_hwdep *hw;
+ struct snd_card *card = opl3->card;
int err;
if (rhwdep)
@@ -514,9 +516,9 @@ int snd_opl3_hwdep_new(opl3_t * opl3,
opl3->seq_dev_num = seq_device;
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
- sizeof(opl3_t*), &opl3->seq_dev) >= 0) {
+ sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
strcpy(opl3->seq_dev->name, hw->name);
- *(opl3_t**)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
+ *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
}
#endif
if (rhwdep)
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 93d674070b71..1b6f227af370 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -60,7 +60,7 @@ static char opl3_volume_table[128] =
};
void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
- snd_midi_channel_t *chan)
+ struct snd_midi_channel *chan)
{
int oldvol, newvol, n;
int volume;
@@ -93,7 +93,7 @@ static short opl3_note_table[16] =
};
static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum,
- int note, snd_midi_channel_t *chan)
+ int note, struct snd_midi_channel *chan)
{
int block = ((note / 12) & 0x07) - 1;
int idx = (note % 12) + 2;
@@ -121,7 +121,7 @@ static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum,
#ifdef DEBUG_ALLOC
-static void debug_alloc(opl3_t *opl3, char *s, int voice) {
+static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) {
int i;
char *str = "x.24";
@@ -135,12 +135,12 @@ static void debug_alloc(opl3_t *opl3, char *s, int voice) {
/*
* Get a FM voice (channel) to play a note on.
*/
-static int opl3_get_voice(opl3_t *opl3, int instr_4op,
- snd_midi_channel_t *chan) {
+static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
+ struct snd_midi_channel *chan) {
int chan_4op_1; /* first voice for 4op instrument */
int chan_4op_2; /* second voice for 4op instrument */
- snd_opl3_voice_t *vp, *vp2;
+ struct snd_opl3_voice *vp, *vp2;
unsigned int voice_time;
int i;
@@ -237,13 +237,14 @@ static int opl3_get_voice(opl3_t *opl3, int instr_4op,
void snd_opl3_timer_func(unsigned long data)
{
- opl3_t *opl3 = (opl3_t *)data;
+ struct snd_opl3 *opl3 = (struct snd_opl3 *)data;
+ unsigned long flags;
int again = 0;
int i;
- spin_lock(&opl3->sys_timer_lock);
+ spin_lock_irqsave(&opl3->sys_timer_lock, flags);
for (i = 0; i < opl3->max_voices; i++) {
- snd_opl3_voice_t *vp = &opl3->voices[i];
+ struct snd_opl3_voice *vp = &opl3->voices[i];
if (vp->state > 0 && vp->note_off_check) {
if (vp->note_off == jiffies)
snd_opl3_note_off(opl3, vp->note, 0, vp->chan);
@@ -257,13 +258,13 @@ void snd_opl3_timer_func(unsigned long data)
} else {
opl3->sys_timer_status = 0;
}
- spin_unlock(&opl3->sys_timer_lock);
+ spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
}
/*
* Start system timer
*/
-static void snd_opl3_start_timer(opl3_t *opl3)
+static void snd_opl3_start_timer(struct snd_opl3 *opl3)
{
unsigned long flags;
spin_lock_irqsave(&opl3->sys_timer_lock, flags);
@@ -285,15 +286,15 @@ static int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
/*
* Start a note.
*/
-void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
+void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
{
- opl3_t *opl3;
- snd_seq_instr_t wanted;
- snd_seq_kinstr_t *kinstr;
+ struct snd_opl3 *opl3;
+ struct snd_seq_instr wanted;
+ struct snd_seq_kinstr *kinstr;
int instr_4op;
int voice;
- snd_opl3_voice_t *vp, *vp2;
+ struct snd_opl3_voice *vp, *vp2;
unsigned short connect_mask;
unsigned char connection;
unsigned char vol_op[4];
@@ -310,7 +311,7 @@ void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
unsigned char fnum, blocknum;
int i;
- fm_instrument_t *fm;
+ struct fm_instrument *fm;
unsigned long flags;
opl3 = p;
@@ -615,13 +616,13 @@ void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
spin_unlock_irqrestore(&opl3->voice_lock, flags);
}
-static void snd_opl3_kill_voice(opl3_t *opl3, int voice)
+static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
{
unsigned short reg_side;
unsigned char voice_offset;
unsigned short opl3_reg;
- snd_opl3_voice_t *vp, *vp2;
+ struct snd_opl3_voice *vp, *vp2;
snd_assert(voice < MAX_OPL3_VOICES, return);
@@ -663,12 +664,12 @@ static void snd_opl3_kill_voice(opl3_t *opl3, int voice)
/*
* Release a note in response to a midi note off.
*/
-void snd_opl3_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
+void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int voice;
- snd_opl3_voice_t *vp;
+ struct snd_opl3_voice *vp;
unsigned long flags;
@@ -708,9 +709,9 @@ void snd_opl3_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
/*
* key pressure change
*/
-void snd_opl3_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
+void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = p;
#ifdef DEBUG_MIDI
@@ -722,9 +723,9 @@ void snd_opl3_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
/*
* terminate note
*/
-void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan)
+void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = p;
#ifdef DEBUG_MIDI
@@ -733,7 +734,7 @@ void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan)
#endif
}
-static void snd_opl3_update_pitch(opl3_t *opl3, int voice)
+static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice)
{
unsigned short reg_side;
unsigned char voice_offset;
@@ -741,7 +742,7 @@ static void snd_opl3_update_pitch(opl3_t *opl3, int voice)
unsigned char fnum, blocknum;
- snd_opl3_voice_t *vp;
+ struct snd_opl3_voice *vp;
snd_assert(voice < MAX_OPL3_VOICES, return);
@@ -780,10 +781,10 @@ static void snd_opl3_update_pitch(opl3_t *opl3, int voice)
/*
* Update voice pitch controller
*/
-static void snd_opl3_pitch_ctrl(opl3_t *opl3, snd_midi_channel_t *chan)
+static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel *chan)
{
int voice;
- snd_opl3_voice_t *vp;
+ struct snd_opl3_voice *vp;
unsigned long flags;
@@ -810,9 +811,9 @@ static void snd_opl3_pitch_ctrl(opl3_t *opl3, snd_midi_channel_t *chan)
* Deal with a controler type event. This includes all types of
* control events, not just the midi controllers
*/
-void snd_opl3_control(void *p, int type, snd_midi_channel_t *chan)
+void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = p;
#ifdef DEBUG_MIDI
@@ -846,10 +847,10 @@ void snd_opl3_control(void *p, int type, snd_midi_channel_t *chan)
/*
* NRPN events
*/
-void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan,
- snd_midi_channel_set_t *chset)
+void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = p;
#ifdef DEBUG_MIDI
@@ -862,9 +863,9 @@ void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan,
* receive sysex
*/
void snd_opl3_sysex(void *p, unsigned char *buf, int len,
- int parsed, snd_midi_channel_set_t *chset)
+ int parsed, struct snd_midi_channel_set *chset)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
opl3 = p;
#ifdef DEBUG_MIDI
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index 21a2b409d6d3..31f1f2e25aa0 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -21,11 +21,11 @@
#include "opl3_voice.h"
#include <linux/slab.h>
-static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure);
-static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg);
-static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg);
-static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format, const char __user *buf, int offs, int count);
-static int snd_opl3_reset_seq_oss(snd_seq_oss_arg_t *arg);
+static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure);
+static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg);
+static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg);
+static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count);
+static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg);
/* */
@@ -43,9 +43,9 @@ static inline void snd_leave_user(mm_segment_t fs)
/* operators */
-extern snd_midi_op_t opl3_ops;
+extern struct snd_midi_op opl3_ops;
-static snd_seq_oss_callback_t oss_callback = {
+static struct snd_seq_oss_callback oss_callback = {
.owner = THIS_MODULE,
.open = snd_opl3_open_seq_oss,
.close = snd_opl3_close_seq_oss,
@@ -54,10 +54,10 @@ static snd_seq_oss_callback_t oss_callback = {
.reset = snd_opl3_reset_seq_oss,
};
-static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
+static int snd_opl3_oss_event_input(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
if (ev->type != SNDRV_SEQ_EVENT_OSS)
snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset);
@@ -68,14 +68,14 @@ static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
static void snd_opl3_oss_free_port(void *private_data)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
snd_midi_channel_free_set(opl3->oss_chset);
}
-static int snd_opl3_oss_create_port(opl3_t * opl3)
+static int snd_opl3_oss_create_port(struct snd_opl3 * opl3)
{
- snd_seq_port_callback_t callbacks;
+ struct snd_seq_port_callback callbacks;
char name[32];
int voices, opl_ver;
@@ -113,13 +113,13 @@ static int snd_opl3_oss_create_port(opl3_t * opl3)
/* ------------------------------ */
/* register OSS synth */
-void snd_opl3_init_seq_oss(opl3_t *opl3, char *name)
+void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name)
{
- snd_seq_oss_reg_t *arg;
- snd_seq_device_t *dev;
+ struct snd_seq_oss_reg *arg;
+ struct snd_seq_device *dev;
if (snd_seq_device_new(opl3->card, 0, SNDRV_SEQ_DEV_ID_OSS,
- sizeof(snd_seq_oss_reg_t), &dev) < 0)
+ sizeof(struct snd_seq_oss_reg), &dev) < 0)
return;
opl3->oss_seq_dev = dev;
@@ -143,7 +143,7 @@ void snd_opl3_init_seq_oss(opl3_t *opl3, char *name)
}
/* unregister */
-void snd_opl3_free_seq_oss(opl3_t *opl3)
+void snd_opl3_free_seq_oss(struct snd_opl3 *opl3)
{
if (opl3->oss_seq_dev) {
snd_device_free(opl3->card, opl3->oss_seq_dev);
@@ -154,9 +154,9 @@ void snd_opl3_free_seq_oss(opl3_t *opl3)
/* ------------------------------ */
/* open OSS sequencer */
-static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
+static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
{
- opl3_t *opl3 = closure;
+ struct snd_opl3 *opl3 = closure;
int err;
snd_assert(arg != NULL, return -ENXIO);
@@ -177,9 +177,9 @@ static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
}
/* close OSS sequencer */
-static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg)
+static int snd_opl3_close_seq_oss(struct snd_seq_oss_arg *arg)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
snd_assert(arg != NULL, return -ENXIO);
opl3 = arg->private_data;
@@ -206,10 +206,10 @@ static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg)
/* from sound_config.h */
#define SBFM_MAXINSTR 256
-static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
+static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
const char __user *buf, int offs, int count)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int err = -EINVAL;
snd_assert(arg != NULL, return -ENXIO);
@@ -219,11 +219,11 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
struct sbi_instrument sbi;
size_t size;
- snd_seq_instr_header_t *put;
- snd_seq_instr_data_t *data;
- fm_xinstrument_t *xinstr;
+ struct snd_seq_instr_header *put;
+ struct snd_seq_instr_data *data;
+ struct fm_xinstrument *xinstr;
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
int i;
mm_segment_t fs;
@@ -240,7 +240,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
return -EINVAL;
}
- size = sizeof(*put) + sizeof(fm_xinstrument_t);
+ size = sizeof(*put) + sizeof(struct fm_xinstrument);
put = kzalloc(size, GFP_KERNEL);
if (put == NULL)
return -ENOMEM;
@@ -249,7 +249,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
data->type = SNDRV_SEQ_INSTR_ATYPE_DATA;
strcpy(data->data.format, SNDRV_SEQ_INSTR_ID_OPL2_3);
/* build data section */
- xinstr = (fm_xinstrument_t *)(data + 1);
+ xinstr = (struct fm_xinstrument *)(data + 1);
xinstr->stype = FM_STRU_INSTR;
for (i = 0; i < 2; i++) {
@@ -296,7 +296,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
err = snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev,
opl3->seq_client, 0, 0);
if (err == -EBUSY) {
- snd_seq_instr_header_t remove;
+ struct snd_seq_instr_header remove;
memset (&remove, 0, sizeof(remove));
remove.cmd = SNDRV_SEQ_INSTR_FREE_CMD_SINGLE;
@@ -319,10 +319,10 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
}
/* ioctl */
-static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd,
+static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
unsigned long ioarg)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
snd_assert(arg != NULL, return -ENXIO);
opl3 = arg->private_data;
@@ -345,9 +345,9 @@ static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd,
}
/* reset device */
-static int snd_opl3_reset_seq_oss(snd_seq_oss_arg_t *arg)
+static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
snd_assert(arg != NULL, return -ENXIO);
opl3 = arg->private_data;
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 136964b844de..c4ead790008a 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -35,7 +35,7 @@ int use_internal_drums = 0;
module_param(use_internal_drums, bool, 0444);
MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums.");
-int snd_opl3_synth_use_inc(opl3_t * opl3)
+int snd_opl3_synth_use_inc(struct snd_opl3 * opl3)
{
if (!try_module_get(opl3->card->module))
return -EFAULT;
@@ -43,12 +43,12 @@ int snd_opl3_synth_use_inc(opl3_t * opl3)
}
-void snd_opl3_synth_use_dec(opl3_t * opl3)
+void snd_opl3_synth_use_dec(struct snd_opl3 * opl3)
{
module_put(opl3->card->module);
}
-int snd_opl3_synth_setup(opl3_t * opl3)
+int snd_opl3_synth_setup(struct snd_opl3 * opl3)
{
int idx;
@@ -78,7 +78,7 @@ int snd_opl3_synth_setup(opl3_t * opl3)
return 0;
}
-void snd_opl3_synth_cleanup(opl3_t * opl3)
+void snd_opl3_synth_cleanup(struct snd_opl3 * opl3)
{
unsigned long flags;
@@ -96,9 +96,9 @@ void snd_opl3_synth_cleanup(opl3_t * opl3)
up(&opl3->access_mutex);
}
-static int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
+static int snd_opl3_synth_use(void *private_data, struct snd_seq_port_subscribe * info)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
int err;
if ((err = snd_opl3_synth_setup(opl3)) < 0)
@@ -123,9 +123,9 @@ static int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * inf
return 0;
}
-static int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
+static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
snd_opl3_synth_cleanup(opl3);
@@ -137,7 +137,7 @@ static int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * i
/*
* MIDI emulation operators
*/
-snd_midi_op_t opl3_ops = {
+struct snd_midi_op opl3_ops = {
.note_on = snd_opl3_note_on,
.note_off = snd_opl3_note_off,
.key_press = snd_opl3_key_press,
@@ -147,10 +147,10 @@ snd_midi_op_t opl3_ops = {
.sysex = snd_opl3_sysex,
};
-static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
+static int snd_opl3_synth_event_input(struct snd_seq_event * ev, int direct,
void *private_data, int atomic, int hop)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN &&
ev->type <= SNDRV_SEQ_EVENT_INSTR_CHANGE) {
@@ -168,14 +168,14 @@ static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
static void snd_opl3_synth_free_port(void *private_data)
{
- opl3_t *opl3 = private_data;
+ struct snd_opl3 *opl3 = private_data;
snd_midi_channel_free_set(opl3->chset);
}
-static int snd_opl3_synth_create_port(opl3_t * opl3)
+static int snd_opl3_synth_create_port(struct snd_opl3 * opl3)
{
- snd_seq_port_callback_t callbacks;
+ struct snd_seq_port_callback callbacks;
char name[32];
int voices, opl_ver;
@@ -215,15 +215,14 @@ static int snd_opl3_synth_create_port(opl3_t * opl3)
/* ------------------------------ */
-static int snd_opl3_seq_new_device(snd_seq_device_t *dev)
+static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int client;
- snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
+ char name[32];
int opl_ver;
- opl3 = *(opl3_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (opl3 == NULL)
return -EINVAL;
@@ -232,22 +231,14 @@ static int snd_opl3_seq_new_device(snd_seq_device_t *dev)
opl3->seq_client = -1;
/* allocate new client */
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = opl3;
- callbacks.allow_output = callbacks.allow_input = 1;
+ opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
+ sprintf(name, "OPL%i FM synth", opl_ver);
client = opl3->seq_client =
- snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, &callbacks);
+ snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num,
+ name);
if (client < 0)
return client;
- /* change name of client */
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client;
- cinfo.type = KERNEL_CLIENT;
- opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
- sprintf(cinfo.name, "OPL%i FM synth", opl_ver);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
-
snd_opl3_synth_create_port(opl3);
/* initialize instrument list */
@@ -268,16 +259,16 @@ static int snd_opl3_seq_new_device(snd_seq_device_t *dev)
opl3->sys_timer_status = 0;
#ifdef CONFIG_SND_SEQUENCER_OSS
- snd_opl3_init_seq_oss(opl3, cinfo.name);
+ snd_opl3_init_seq_oss(opl3, name);
#endif
return 0;
}
-static int snd_opl3_seq_delete_device(snd_seq_device_t *dev)
+static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
{
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
- opl3 = *(opl3_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (opl3 == NULL)
return -EINVAL;
@@ -295,14 +286,14 @@ static int snd_opl3_seq_delete_device(snd_seq_device_t *dev)
static int __init alsa_opl3_seq_init(void)
{
- static snd_seq_dev_ops_t ops =
+ static struct snd_seq_dev_ops ops =
{
snd_opl3_seq_new_device,
snd_opl3_seq_delete_device
};
return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops,
- sizeof(opl3_t*));
+ sizeof(struct snd_opl3 *));
}
static void __exit alsa_opl3_seq_exit(void)
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 04f9f955e5b7..3534a0e3342a 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -61,20 +61,20 @@ char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
/*
* prototypes
*/
-static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note);
-static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice);
-static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params);
-static int snd_opl3_set_mode(opl3_t * opl3, int mode);
-static int snd_opl3_set_connection(opl3_t * opl3, int connection);
+static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note);
+static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice);
+static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params);
+static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode);
+static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection);
/* ------------------------------ */
/*
* open the device exclusively
*/
-int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
+int snd_opl3_open(struct snd_hwdep * hw, struct file *file)
{
- opl3_t *opl3 = hw->private_data;
+ struct snd_opl3 *opl3 = hw->private_data;
down(&opl3->access_mutex);
if (opl3->used) {
@@ -90,10 +90,10 @@ int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
/*
* ioctl for hwdep device:
*/
-int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
+int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
- opl3_t *opl3 = hw->private_data;
+ struct snd_opl3 *opl3 = hw->private_data;
void __user *argp = (void __user *)arg;
snd_assert(opl3 != NULL, return -EINVAL);
@@ -102,11 +102,11 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
/* get information */
case SNDRV_DM_FM_IOCTL_INFO:
{
- snd_dm_fm_info_t info;
+ struct snd_dm_fm_info info;
info.fm_mode = opl3->fm_mode;
info.rhythm = opl3->rhythm;
- if (copy_to_user(argp, &info, sizeof(snd_dm_fm_info_t)))
+ if (copy_to_user(argp, &info, sizeof(struct snd_dm_fm_info)))
return -EFAULT;
return 0;
}
@@ -123,8 +123,8 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE:
#endif
{
- snd_dm_fm_note_t note;
- if (copy_from_user(&note, argp, sizeof(snd_dm_fm_note_t)))
+ struct snd_dm_fm_note note;
+ if (copy_from_user(&note, argp, sizeof(struct snd_dm_fm_note)))
return -EFAULT;
return snd_opl3_play_note(opl3, &note);
}
@@ -134,8 +134,8 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE:
#endif
{
- snd_dm_fm_voice_t voice;
- if (copy_from_user(&voice, argp, sizeof(snd_dm_fm_voice_t)))
+ struct snd_dm_fm_voice voice;
+ if (copy_from_user(&voice, argp, sizeof(struct snd_dm_fm_voice)))
return -EFAULT;
return snd_opl3_set_voice(opl3, &voice);
}
@@ -145,8 +145,8 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS:
#endif
{
- snd_dm_fm_params_t params;
- if (copy_from_user(&params, argp, sizeof(snd_dm_fm_params_t)))
+ struct snd_dm_fm_params params;
+ if (copy_from_user(&params, argp, sizeof(struct snd_dm_fm_params)))
return -EFAULT;
return snd_opl3_set_params(opl3, &params);
}
@@ -174,9 +174,9 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
/*
* close the device
*/
-int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
+int snd_opl3_release(struct snd_hwdep * hw, struct file *file)
{
- opl3_t *opl3 = hw->private_data;
+ struct snd_opl3 *opl3 = hw->private_data;
snd_opl3_reset(opl3);
down(&opl3->access_mutex);
@@ -188,7 +188,7 @@ int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
/* ------------------------------ */
-void snd_opl3_reset(opl3_t * opl3)
+void snd_opl3_reset(struct snd_opl3 * opl3)
{
unsigned short opl3_reg;
@@ -229,7 +229,7 @@ void snd_opl3_reset(opl3_t * opl3)
}
-static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note)
+static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note)
{
unsigned short reg_side;
unsigned char voice_offset;
@@ -276,7 +276,7 @@ static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note)
}
-static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice)
+static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * voice)
{
unsigned short reg_side;
unsigned char op_offset;
@@ -378,7 +378,7 @@ static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice)
return 0;
}
-static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params)
+static int snd_opl3_set_params(struct snd_opl3 * opl3, struct snd_dm_fm_params * params)
{
unsigned char reg_val;
@@ -418,7 +418,7 @@ static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params)
return 0;
}
-static int snd_opl3_set_mode(opl3_t * opl3, int mode)
+static int snd_opl3_set_mode(struct snd_opl3 * opl3, int mode)
{
if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3))
return -EINVAL;
@@ -430,7 +430,7 @@ static int snd_opl3_set_mode(opl3_t * opl3, int mode)
return 0;
}
-static int snd_opl3_set_connection(opl3_t * opl3, int connection)
+static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection)
{
unsigned char reg_val;
diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h
index 63346a5c3498..a371c075ac87 100644
--- a/sound/drivers/opl3/opl3_voice.h
+++ b/sound/drivers/opl3/opl3_voice.h
@@ -22,31 +22,31 @@
#include <sound/opl3.h>
/* Prototypes for opl3_seq.c */
-int snd_opl3_synth_use_inc(opl3_t * opl3);
-void snd_opl3_synth_use_dec(opl3_t * opl3);
-int snd_opl3_synth_setup(opl3_t * opl3);
-void snd_opl3_synth_cleanup(opl3_t * opl3);
+int snd_opl3_synth_use_inc(struct snd_opl3 * opl3);
+void snd_opl3_synth_use_dec(struct snd_opl3 * opl3);
+int snd_opl3_synth_setup(struct snd_opl3 * opl3);
+void snd_opl3_synth_cleanup(struct snd_opl3 * opl3);
/* Prototypes for opl3_midi.c */
void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan);
void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan);
void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan);
-void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan);
+void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan);
void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan);
-void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
-void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
+void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, struct snd_midi_channel_set *chset);
+void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset);
-void snd_opl3_calc_volume(unsigned char *reg, int vel, snd_midi_channel_t *chan);
+void snd_opl3_calc_volume(unsigned char *reg, int vel, struct snd_midi_channel *chan);
void snd_opl3_timer_func(unsigned long data);
/* Prototypes for opl3_drums.c */
-void snd_opl3_load_drums(opl3_t *opl3);
-void snd_opl3_drum_switch(opl3_t *opl3, int note, int on_off, int vel, snd_midi_channel_t *chan);
+void snd_opl3_load_drums(struct snd_opl3 *opl3);
+void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan);
/* Prototypes for opl3_oss.c */
#ifdef CONFIG_SND_SEQUENCER_OSS
-void snd_opl3_init_seq_oss(opl3_t *opl3, char *name);
-void snd_opl3_free_seq_oss(opl3_t *opl3);
+void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name);
+void snd_opl3_free_seq_oss(struct snd_opl3 *opl3);
#endif
#endif
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 4ae5dd8f011e..ddfc10d04be2 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -27,14 +27,14 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_DESCRIPTION("OPL4 driver");
MODULE_LICENSE("GPL");
-static void inline snd_opl4_wait(opl4_t *opl4)
+static void inline snd_opl4_wait(struct snd_opl4 *opl4)
{
int timeout = 10;
while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
;
}
-void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
+void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value)
{
snd_opl4_wait(opl4);
outb(reg, opl4->pcm_port);
@@ -43,7 +43,7 @@ void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
outb(value, opl4->pcm_port + 1);
}
-u8 snd_opl4_read(opl4_t *opl4, u8 reg)
+u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
{
snd_opl4_wait(opl4);
outb(reg, opl4->pcm_port);
@@ -52,7 +52,7 @@ u8 snd_opl4_read(opl4_t *opl4, u8 reg)
return inb(opl4->pcm_port + 1);
}
-void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
+void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size)
{
unsigned long flags;
u8 memcfg;
@@ -76,7 +76,7 @@ void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
spin_unlock_irqrestore(&opl4->reg_lock, flags);
}
-void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
+void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size)
{
unsigned long flags;
u8 memcfg;
@@ -100,7 +100,7 @@ void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
spin_unlock_irqrestore(&opl4->reg_lock, flags);
}
-static void snd_opl4_enable_opl4(opl4_t *opl4)
+static void snd_opl4_enable_opl4(struct snd_opl4 *opl4)
{
outb(OPL3_REG_MODE, opl4->fm_port + 2);
inb(opl4->fm_port);
@@ -110,7 +110,7 @@ static void snd_opl4_enable_opl4(opl4_t *opl4)
inb(opl4->fm_port);
}
-static int snd_opl4_detect(opl4_t *opl4)
+static int snd_opl4_detect(struct snd_opl4 *opl4)
{
u8 id1, id2;
@@ -144,19 +144,19 @@ static int snd_opl4_detect(opl4_t *opl4)
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
+static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
{
- opl4_t *opl4 = seq_dev->private_data;
+ struct snd_opl4 *opl4 = seq_dev->private_data;
opl4->seq_dev = NULL;
}
-static int snd_opl4_create_seq_dev(opl4_t *opl4, int seq_device)
+static int snd_opl4_create_seq_dev(struct snd_opl4 *opl4, int seq_device)
{
opl4->seq_dev_num = seq_device;
if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4,
- sizeof(opl4_t *), &opl4->seq_dev) >= 0) {
+ sizeof(struct snd_opl4 *), &opl4->seq_dev) >= 0) {
strcpy(opl4->seq_dev->name, "OPL4 Wavetable");
- *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
+ *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
opl4->seq_dev->private_data = opl4;
opl4->seq_dev->private_free = snd_opl4_seq_dev_free;
}
@@ -164,7 +164,7 @@ static int snd_opl4_create_seq_dev(opl4_t *opl4, int seq_device)
}
#endif
-static void snd_opl4_free(opl4_t *opl4)
+static void snd_opl4_free(struct snd_opl4 *opl4)
{
#ifdef CONFIG_PROC_FS
snd_opl4_free_proc(opl4);
@@ -174,22 +174,22 @@ static void snd_opl4_free(opl4_t *opl4)
kfree(opl4);
}
-static int snd_opl4_dev_free(snd_device_t *device)
+static int snd_opl4_dev_free(struct snd_device *device)
{
- opl4_t *opl4 = device->device_data;
+ struct snd_opl4 *opl4 = device->device_data;
snd_opl4_free(opl4);
return 0;
}
-int snd_opl4_create(snd_card_t *card,
+int snd_opl4_create(struct snd_card *card,
unsigned long fm_port, unsigned long pcm_port,
int seq_device,
- opl3_t **ropl3, opl4_t **ropl4)
+ struct snd_opl3 **ropl3, struct snd_opl4 **ropl4)
{
- opl4_t *opl4;
- opl3_t *opl3;
+ struct snd_opl4 *opl4;
+ struct snd_opl3 *opl3;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_opl4_dev_free
};
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
index c455680843f6..7e088a4a2f4c 100644
--- a/sound/drivers/opl4/opl4_local.h
+++ b/sound/drivers/opl4/opl4_local.h
@@ -131,7 +131,7 @@
#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth"
-typedef struct opl4_sound {
+struct opl4_sound {
u16 tone;
s16 pitch_offset;
u8 key_scaling;
@@ -144,42 +144,42 @@ typedef struct opl4_sound {
u8 reg_level_decay2;
u8 reg_release_correction;
u8 reg_tremolo;
-} opl4_sound_t;
+};
-typedef struct opl4_region {
+struct opl4_region {
u8 key_min, key_max;
- opl4_sound_t sound;
-} opl4_region_t;
+ struct opl4_sound sound;
+};
-typedef struct opl4_region_ptr {
+struct opl4_region_ptr {
int count;
- const opl4_region_t *regions;
-} opl4_region_ptr_t;
+ const struct opl4_region *regions;
+};
-typedef struct opl4_voice {
+struct opl4_voice {
struct list_head list;
int number;
- snd_midi_channel_t *chan;
+ struct snd_midi_channel *chan;
int note;
int velocity;
- const opl4_sound_t *sound;
+ const struct opl4_sound *sound;
u8 level_direct;
u8 reg_f_number;
u8 reg_misc;
u8 reg_lfo_vibrato;
-} opl4_voice_t;
+};
-struct opl4 {
+struct snd_opl4 {
unsigned long fm_port;
unsigned long pcm_port;
struct resource *res_fm_port;
struct resource *res_pcm_port;
unsigned short hardware;
spinlock_t reg_lock;
- snd_card_t *card;
+ struct snd_card *card;
#ifdef CONFIG_PROC_FS
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
int memory_access;
#endif
struct semaphore access_mutex;
@@ -189,44 +189,44 @@ struct opl4 {
int seq_dev_num;
int seq_client;
- snd_seq_device_t *seq_dev;
+ struct snd_seq_device *seq_dev;
- snd_midi_channel_set_t *chset;
- opl4_voice_t voices[OPL4_MAX_VOICES];
+ struct snd_midi_channel_set *chset;
+ struct opl4_voice voices[OPL4_MAX_VOICES];
struct list_head off_voices;
struct list_head on_voices;
#endif
};
/* opl4_lib.c */
-void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value);
-u8 snd_opl4_read(opl4_t *opl4, u8 reg);
-void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size);
-void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size);
+void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value);
+u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg);
+void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size);
+void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size);
/* opl4_mixer.c */
-int snd_opl4_create_mixer(opl4_t *opl4);
+int snd_opl4_create_mixer(struct snd_opl4 *opl4);
#ifdef CONFIG_PROC_FS
/* opl4_proc.c */
-int snd_opl4_create_proc(opl4_t *opl4);
-void snd_opl4_free_proc(opl4_t *opl4);
+int snd_opl4_create_proc(struct snd_opl4 *opl4);
+void snd_opl4_free_proc(struct snd_opl4 *opl4);
#endif
/* opl4_seq.c */
extern int volume_boost;
/* opl4_synth.c */
-void snd_opl4_synth_reset(opl4_t *opl4);
-void snd_opl4_synth_shutdown(opl4_t *opl4);
-void snd_opl4_note_on(void *p, int note, int vel, snd_midi_channel_t *chan);
-void snd_opl4_note_off(void *p, int note, int vel, snd_midi_channel_t *chan);
-void snd_opl4_terminate_note(void *p, int note, snd_midi_channel_t *chan);
-void snd_opl4_control(void *p, int type, snd_midi_channel_t *chan);
-void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
+void snd_opl4_synth_reset(struct snd_opl4 *opl4);
+void snd_opl4_synth_shutdown(struct snd_opl4 *opl4);
+void snd_opl4_note_on(void *p, int note, int vel, struct snd_midi_channel *chan);
+void snd_opl4_note_off(void *p, int note, int vel, struct snd_midi_channel *chan);
+void snd_opl4_terminate_note(void *p, int note, struct snd_midi_channel *chan);
+void snd_opl4_control(void *p, int type, struct snd_midi_channel *chan);
+void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, struct snd_midi_channel_set *chset);
/* yrw801.c */
-int snd_yrw801_detect(opl4_t *opl4);
-extern const opl4_region_ptr_t snd_yrw801_regions[];
+int snd_yrw801_detect(struct snd_opl4 *opl4);
+extern const struct opl4_region_ptr snd_yrw801_regions[];
#endif /* __OPL4_LOCAL_H */
diff --git a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c
index ec7a228fbe7e..04079de4c35f 100644
--- a/sound/drivers/opl4/opl4_mixer.c
+++ b/sound/drivers/opl4/opl4_mixer.c
@@ -20,7 +20,7 @@
#include "opl4_local.h"
#include <sound/control.h>
-static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_opl4_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -29,9 +29,9 @@ static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_opl4_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+ struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
u8 reg = kcontrol->private_value;
u8 value;
@@ -44,9 +44,9 @@ static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+ struct snd_opl4 *opl4 = snd_kcontrol_chip(kcontrol);
unsigned long flags;
u8 reg = kcontrol->private_value;
u8 value, old_value;
@@ -60,7 +60,7 @@ static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return value != old_value;
}
-static snd_kcontrol_new_t snd_opl4_controls[] = {
+static struct snd_kcontrol_new snd_opl4_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "FM Playback Volume",
@@ -79,9 +79,9 @@ static snd_kcontrol_new_t snd_opl4_controls[] = {
}
};
-int snd_opl4_create_mixer(opl4_t *opl4)
+int snd_opl4_create_mixer(struct snd_opl4 *opl4)
{
- snd_card_t *card = opl4->card;
+ struct snd_card *card = opl4->card;
int i, err;
strcat(card->mixername, ",OPL4");
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
index 6a1486258acf..f4b4e74fcc18 100644
--- a/sound/drivers/opl4/opl4_proc.c
+++ b/sound/drivers/opl4/opl4_proc.c
@@ -23,10 +23,10 @@
#ifdef CONFIG_PROC_FS
-static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
+static int snd_opl4_mem_proc_open(struct snd_info_entry *entry,
unsigned short mode, void **file_private_data)
{
- opl4_t *opl4 = entry->private_data;
+ struct snd_opl4 *opl4 = entry->private_data;
down(&opl4->access_mutex);
if (opl4->memory_access) {
@@ -38,10 +38,10 @@ static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
return 0;
}
-static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
+static int snd_opl4_mem_proc_release(struct snd_info_entry *entry,
unsigned short mode, void *file_private_data)
{
- opl4_t *opl4 = entry->private_data;
+ struct snd_opl4 *opl4 = entry->private_data;
down(&opl4->access_mutex);
opl4->memory_access--;
@@ -49,11 +49,11 @@ static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
return 0;
}
-static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_opl4_mem_proc_read(struct snd_info_entry *entry, void *file_private_data,
struct file *file, char __user *_buf,
unsigned long count, unsigned long pos)
{
- opl4_t *opl4 = entry->private_data;
+ struct snd_opl4 *opl4 = entry->private_data;
long size;
char* buf;
@@ -75,11 +75,11 @@ static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_d
return 0;
}
-static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_data,
+static long snd_opl4_mem_proc_write(struct snd_info_entry *entry, void *file_private_data,
struct file *file, const char __user *_buf,
unsigned long count, unsigned long pos)
{
- opl4_t *opl4 = entry->private_data;
+ struct snd_opl4 *opl4 = entry->private_data;
long size;
char *buf;
@@ -101,7 +101,7 @@ static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_
return 0;
}
-static long long snd_opl4_mem_proc_llseek(snd_info_entry_t *entry, void *file_private_data,
+static long long snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, void *file_private_data,
struct file *file, long long offset, int orig)
{
switch (orig) {
@@ -130,9 +130,9 @@ static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
.llseek = snd_opl4_mem_proc_llseek,
};
-int snd_opl4_create_proc(opl4_t *opl4)
+int snd_opl4_create_proc(struct snd_opl4 *opl4)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root);
if (entry) {
@@ -157,7 +157,7 @@ int snd_opl4_create_proc(opl4_t *opl4)
return 0;
}
-void snd_opl4_free_proc(opl4_t *opl4)
+void snd_opl4_free_proc(struct snd_opl4 *opl4)
{
if (opl4->proc_entry)
snd_info_unregister(opl4->proc_entry);
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index 958dfe88479a..e3480326e735 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -45,21 +45,21 @@ int volume_boost = 8;
module_param(volume_boost, int, 0644);
MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
-static int snd_opl4_seq_use_inc(opl4_t *opl4)
+static int snd_opl4_seq_use_inc(struct snd_opl4 *opl4)
{
if (!try_module_get(opl4->card->module))
return -EFAULT;
return 0;
}
-static void snd_opl4_seq_use_dec(opl4_t *opl4)
+static void snd_opl4_seq_use_dec(struct snd_opl4 *opl4)
{
module_put(opl4->card->module);
}
-static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_opl4_seq_use(void *private_data, struct snd_seq_port_subscribe *info)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
int err;
down(&opl4->access_mutex);
@@ -84,9 +84,9 @@ static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
return 0;
}
-static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
snd_opl4_synth_shutdown(opl4);
@@ -99,7 +99,7 @@ static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info
return 0;
}
-static snd_midi_op_t opl4_ops = {
+static struct snd_midi_op opl4_ops = {
.note_on = snd_opl4_note_on,
.note_off = snd_opl4_note_off,
.note_terminate = snd_opl4_terminate_note,
@@ -107,10 +107,10 @@ static snd_midi_op_t opl4_ops = {
.sysex = snd_opl4_sysex,
};
-static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
+static int snd_opl4_seq_event_input(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
snd_midi_process_event(&opl4_ops, ev, opl4->chset);
return 0;
@@ -118,20 +118,18 @@ static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
static void snd_opl4_seq_free_port(void *private_data)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
snd_midi_channel_free_set(opl4->chset);
}
-static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
+static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
{
- opl4_t *opl4;
+ struct snd_opl4 *opl4;
int client;
- snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
- snd_seq_port_callback_t pcallbacks;
+ struct snd_seq_port_callback pcallbacks;
- opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (!opl4)
return -EINVAL;
@@ -144,10 +142,8 @@ static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
opl4->chset->private_data = opl4;
/* allocate new client */
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = opl4;
- callbacks.allow_output = callbacks.allow_input = 1;
- client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, &callbacks);
+ client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num,
+ "OPL4 Wavetable");
if (client < 0) {
snd_midi_channel_free_set(opl4->chset);
return client;
@@ -155,13 +151,6 @@ static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
opl4->seq_client = client;
opl4->chset->client = client;
- /* change name of client */
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client;
- cinfo.type = KERNEL_CLIENT;
- strcpy(cinfo.name, "OPL4 Wavetable");
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
-
/* create new port */
memset(&pcallbacks, 0, sizeof(pcallbacks));
pcallbacks.owner = THIS_MODULE;
@@ -188,11 +177,11 @@ static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
return 0;
}
-static int snd_opl4_seq_delete_device(snd_seq_device_t *dev)
+static int snd_opl4_seq_delete_device(struct snd_seq_device *dev)
{
- opl4_t *opl4;
+ struct snd_opl4 *opl4;
- opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (!opl4)
return -EINVAL;
@@ -205,13 +194,13 @@ static int snd_opl4_seq_delete_device(snd_seq_device_t *dev)
static int __init alsa_opl4_synth_init(void)
{
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_opl4_seq_new_device,
snd_opl4_seq_delete_device
};
return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops,
- sizeof(opl4_t*));
+ sizeof(struct snd_opl4 *));
}
static void __exit alsa_opl4_synth_exit(void)
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
index b146a1c995d9..74f6e53eae0d 100644
--- a/sound/drivers/opl4/opl4_synth.c
+++ b/sound/drivers/opl4/opl4_synth.c
@@ -270,7 +270,7 @@ static unsigned char snd_opl4_volume_table[128] = {
/*
* Initializes all voices.
*/
-void snd_opl4_synth_reset(opl4_t *opl4)
+void snd_opl4_synth_reset(struct snd_opl4 *opl4)
{
unsigned long flags;
int i;
@@ -294,7 +294,7 @@ void snd_opl4_synth_reset(opl4_t *opl4)
/*
* Shuts down all voices.
*/
-void snd_opl4_synth_shutdown(opl4_t *opl4)
+void snd_opl4_synth_shutdown(struct snd_opl4 *opl4)
{
unsigned long flags;
int i;
@@ -309,12 +309,12 @@ void snd_opl4_synth_shutdown(opl4_t *opl4)
/*
* Executes the callback for all voices playing the specified note.
*/
-static void snd_opl4_do_for_note(opl4_t *opl4, int note, snd_midi_channel_t *chan,
- void (*func)(opl4_t *opl4, opl4_voice_t *voice))
+static void snd_opl4_do_for_note(struct snd_opl4 *opl4, int note, struct snd_midi_channel *chan,
+ void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice))
{
int i;
unsigned long flags;
- opl4_voice_t *voice;
+ struct opl4_voice *voice;
spin_lock_irqsave(&opl4->reg_lock, flags);
for (i = 0; i < OPL4_MAX_VOICES; i++) {
@@ -329,12 +329,13 @@ static void snd_opl4_do_for_note(opl4_t *opl4, int note, snd_midi_channel_t *cha
/*
* Executes the callback for all voices of to the specified channel.
*/
-static void snd_opl4_do_for_channel(opl4_t *opl4, snd_midi_channel_t *chan,
- void (*func)(opl4_t *opl4, opl4_voice_t *voice))
+static void snd_opl4_do_for_channel(struct snd_opl4 *opl4,
+ struct snd_midi_channel *chan,
+ void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice))
{
int i;
unsigned long flags;
- opl4_voice_t *voice;
+ struct opl4_voice *voice;
spin_lock_irqsave(&opl4->reg_lock, flags);
for (i = 0; i < OPL4_MAX_VOICES; i++) {
@@ -349,12 +350,12 @@ static void snd_opl4_do_for_channel(opl4_t *opl4, snd_midi_channel_t *chan,
/*
* Executes the callback for all active voices.
*/
-static void snd_opl4_do_for_all(opl4_t *opl4,
- void (*func)(opl4_t *opl4, opl4_voice_t *voice))
+static void snd_opl4_do_for_all(struct snd_opl4 *opl4,
+ void (*func)(struct snd_opl4 *opl4, struct opl4_voice *voice))
{
int i;
unsigned long flags;
- opl4_voice_t *voice;
+ struct opl4_voice *voice;
spin_lock_irqsave(&opl4->reg_lock, flags);
for (i = 0; i < OPL4_MAX_VOICES; i++) {
@@ -365,7 +366,7 @@ static void snd_opl4_do_for_all(opl4_t *opl4,
spin_unlock_irqrestore(&opl4->reg_lock, flags);
}
-static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_update_volume(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
int att;
@@ -384,7 +385,7 @@ static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
voice->level_direct = 0;
}
-static void snd_opl4_update_pan(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_update_pan(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
int pan = voice->sound->panpot;
@@ -399,7 +400,8 @@ static void snd_opl4_update_pan(opl4_t *opl4, opl4_voice_t *voice)
snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
}
-static void snd_opl4_update_vibrato_depth(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_update_vibrato_depth(struct snd_opl4 *opl4,
+ struct opl4_voice *voice)
{
int depth;
@@ -414,9 +416,10 @@ static void snd_opl4_update_vibrato_depth(opl4_t *opl4, opl4_voice_t *voice)
voice->reg_lfo_vibrato);
}
-static void snd_opl4_update_pitch(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_update_pitch(struct snd_opl4 *opl4,
+ struct opl4_voice *voice)
{
- snd_midi_channel_t *chan = voice->chan;
+ struct snd_midi_channel *chan = voice->chan;
int note, pitch, octave;
note = chan->drum_channel ? 60 : voice->note;
@@ -444,7 +447,8 @@ static void snd_opl4_update_pitch(opl4_t *opl4, opl4_voice_t *voice)
snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number);
}
-static void snd_opl4_update_tone_parameters(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_update_tone_parameters(struct snd_opl4 *opl4,
+ struct opl4_voice *voice)
{
snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number,
voice->sound->reg_attack_decay1);
@@ -457,17 +461,17 @@ static void snd_opl4_update_tone_parameters(opl4_t *opl4, opl4_voice_t *voice)
}
/* allocate one voice */
-static opl4_voice_t *snd_opl4_get_voice(opl4_t *opl4)
+static struct opl4_voice *snd_opl4_get_voice(struct snd_opl4 *opl4)
{
/* first, try to get the oldest key-off voice */
if (!list_empty(&opl4->off_voices))
- return list_entry(opl4->off_voices.next, opl4_voice_t, list);
+ return list_entry(opl4->off_voices.next, struct opl4_voice, list);
/* then get the oldest key-on voice */
snd_assert(!list_empty(&opl4->on_voices), );
- return list_entry(opl4->on_voices.next, opl4_voice_t, list);
+ return list_entry(opl4->on_voices.next, struct opl4_voice, list);
}
-static void snd_opl4_wait_for_wave_headers(opl4_t *opl4)
+static void snd_opl4_wait_for_wave_headers(struct snd_opl4 *opl4)
{
int timeout = 200;
@@ -475,12 +479,12 @@ static void snd_opl4_wait_for_wave_headers(opl4_t *opl4)
udelay(10);
}
-void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t *chan)
+void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_channel *chan)
{
- opl4_t *opl4 = private_data;
- const opl4_region_ptr_t *regions;
- opl4_voice_t *voice[2];
- const opl4_sound_t *sound[2];
+ struct snd_opl4 *opl4 = private_data;
+ const struct opl4_region_ptr *regions;
+ struct opl4_voice *voice[2];
+ const struct opl4_sound *sound[2];
int voices = 0, i;
unsigned long flags;
@@ -549,7 +553,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
spin_unlock_irqrestore(&opl4->reg_lock, flags);
}
-static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
list_del(&voice->list);
list_add_tail(&voice->list, &opl4->off_voices);
@@ -558,14 +562,14 @@ static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
}
-void snd_opl4_note_off(void *private_data, int note, int vel, snd_midi_channel_t *chan)
+void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_channel *chan)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
}
-static void snd_opl4_terminate_voice(opl4_t *opl4, opl4_voice_t *voice)
+static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
list_del(&voice->list);
list_add_tail(&voice->list, &opl4->off_voices);
@@ -574,16 +578,16 @@ static void snd_opl4_terminate_voice(opl4_t *opl4, opl4_voice_t *voice)
snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
}
-void snd_opl4_terminate_note(void *private_data, int note, snd_midi_channel_t *chan)
+void snd_opl4_terminate_note(void *private_data, int note, struct snd_midi_channel *chan)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
}
-void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
+void snd_opl4_control(void *private_data, int type, struct snd_midi_channel *chan)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
switch (type) {
case MIDI_CTL_MSB_MODWHEEL:
@@ -621,9 +625,9 @@ void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
}
void snd_opl4_sysex(void *private_data, unsigned char *buf, int len,
- int parsed, snd_midi_channel_set_t *chset)
+ int parsed, struct snd_midi_channel_set *chset)
{
- opl4_t *opl4 = private_data;
+ struct snd_opl4 *opl4 = private_data;
if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME)
snd_opl4_do_for_all(opl4, snd_opl4_update_volume);
diff --git a/sound/drivers/opl4/yrw801.c b/sound/drivers/opl4/yrw801.c
index a51174dd3e56..6c335492d082 100644
--- a/sound/drivers/opl4/yrw801.c
+++ b/sound/drivers/opl4/yrw801.c
@@ -33,7 +33,7 @@
#include "opl4_local.h"
-int snd_yrw801_detect(opl4_t *opl4)
+int snd_yrw801_detect(struct snd_opl4 *opl4)
{
char buf[15];
@@ -54,7 +54,7 @@ int snd_yrw801_detect(opl4_t *opl4)
* by this driver.
*/
-static const opl4_region_t regions_00[] = { /* Acoustic Grand Piano */
+static const struct opl4_region regions_00[] = { /* Acoustic Grand Piano */
{0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}},
{0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
{0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
@@ -66,7 +66,7 @@ static const opl4_region_t regions_00[] = { /* Acoustic Grand Piano */
{0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xc8,0x20,0xf3,0x14,0x18,0x0}},
{0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}}
};
-static const opl4_region_t regions_01[] = { /* Bright Acoustic Piano */
+static const struct opl4_region regions_01[] = { /* Bright Acoustic Piano */
{0x14, 0x2d, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}},
{0x2e, 0x33, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
{0x34, 0x39, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
@@ -78,7 +78,7 @@ static const opl4_region_t regions_01[] = { /* Bright Acoustic Piano */
{0x59, 0x5e, {0x134,1444,100, 0,0,0x0a,0xc8,0x20,0xf3,0x14,0x18,0x0}},
{0x5f, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}}
};
-static const opl4_region_t regions_02[] = { /* Electric Grand Piano */
+static const struct opl4_region regions_02[] = { /* Electric Grand Piano */
{0x14, 0x2d, {0x12c,7476,100, 1,0,0x00,0xae,0x20,0xf2,0x13,0x07,0x0}},
{0x2e, 0x33, {0x12d,6818,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
{0x34, 0x39, {0x12e,5901,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
@@ -91,7 +91,7 @@ static const opl4_region_t regions_02[] = { /* Electric Grand Piano */
{0x5f, 0x6d, {0x135,1917,100, 1,0,0x00,0xae,0x20,0xf4,0x15,0x07,0x0}},
{0x00, 0x7f, {0x06c,6375,100,-1,0,0x00,0xc2,0x28,0xf4,0x23,0x18,0x0}}
};
-static const opl4_region_t regions_03[] = { /* Honky-Tonk Piano */
+static const struct opl4_region regions_03[] = { /* Honky-Tonk Piano */
{0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}},
{0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
{0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
@@ -113,11 +113,11 @@ static const opl4_region_t regions_03[] = { /* Honky-Tonk Piano */
{0x53, 0x58, {0x134,1457,100, 0,0,0x01,0xb4,0x20,0xf3,0x14,0x18,0x0}},
{0x59, 0x6d, {0x135,1903,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}}
};
-static const opl4_region_t regions_04[] = { /* Electric Piano 1 */
+static const struct opl4_region regions_04[] = { /* Electric Piano 1 */
{0x15, 0x6c, {0x00b,6570,100, 0,0,0x00,0x28,0x38,0xf0,0x00,0x0c,0x0}},
{0x00, 0x7f, {0x06c,6375,100, 0,2,0x00,0xb0,0x22,0xf4,0x23,0x19,0x0}}
};
-static const opl4_region_t regions_05[] = { /* Electric Piano 2 */
+static const struct opl4_region regions_05[] = { /* Electric Piano 2 */
{0x14, 0x27, {0x12c,7476,100, 0,3,0x00,0xa2,0x1b,0xf2,0x13,0x08,0x0}},
{0x28, 0x2d, {0x12d,6818,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
{0x2e, 0x33, {0x12e,5901,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
@@ -139,103 +139,103 @@ static const opl4_region_t regions_05[] = { /* Electric Piano 2 */
{0x59, 0x5e, {0x134,1442,100, 0,0,0x0a,0xa2,0x18,0xf3,0x14,0x18,0x0}},
{0x5f, 0x6d, {0x135,1913,100, 0,0,0x00,0xa2,0x18,0xf4,0x15,0x08,0x0}}
};
-static const opl4_region_t regions_06[] = { /* Harpsichord */
+static const struct opl4_region regions_06[] = { /* Harpsichord */
{0x15, 0x39, {0x080,5158,100, 0,0,0x00,0xb2,0x20,0xf5,0x24,0x19,0x0}},
{0x3a, 0x3f, {0x081,4408,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}},
{0x40, 0x45, {0x082,3622,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}},
{0x46, 0x4d, {0x083,2843,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x19,0x0}},
{0x4e, 0x6c, {0x084,1307,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x29,0x0}}
};
-static const opl4_region_t regions_07[] = { /* Clavinet */
+static const struct opl4_region regions_07[] = { /* Clavinet */
{0x15, 0x51, {0x027,5009,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x2b,0x0}},
{0x52, 0x6c, {0x028,3495,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x3b,0x0}}
};
-static const opl4_region_t regions_08[] = { /* Celesta */
+static const struct opl4_region regions_08[] = { /* Celesta */
{0x15, 0x6c, {0x02b,3267,100, 0,0,0x00,0xdc,0x20,0xf4,0x15,0x07,0x3}}
};
-static const opl4_region_t regions_09[] = { /* Glockenspiel */
+static const struct opl4_region regions_09[] = { /* Glockenspiel */
{0x15, 0x78, {0x0f3, 285,100, 0,0,0x00,0xc2,0x28,0xf6,0x25,0x25,0x0}}
};
-static const opl4_region_t regions_0a[] = { /* Music Box */
+static const struct opl4_region regions_0a[] = { /* Music Box */
{0x15, 0x6c, {0x0f3,3362,100, 0,0,0x00,0xb6,0x20,0xa6,0x25,0x25,0x0}},
{0x15, 0x6c, {0x101,4773,100, 0,0,0x00,0xaa,0x20,0xd4,0x14,0x16,0x0}}
};
-static const opl4_region_t regions_0b[] = { /* Vibraphone */
+static const struct opl4_region regions_0b[] = { /* Vibraphone */
{0x15, 0x6c, {0x101,4778,100, 0,0,0x00,0xc0,0x28,0xf4,0x14,0x16,0x4}}
};
-static const opl4_region_t regions_0c[] = { /* Marimba */
+static const struct opl4_region regions_0c[] = { /* Marimba */
{0x15, 0x3f, {0x0f4,4778,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}},
{0x40, 0x4c, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}},
{0x4d, 0x5a, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x08,0x0}},
{0x5b, 0x7f, {0x0f5,3218,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x18,0x0}}
};
-static const opl4_region_t regions_0d[] = { /* Xylophone */
+static const struct opl4_region regions_0d[] = { /* Xylophone */
{0x00, 0x7f, {0x136,1729,100, 0,0,0x00,0xd2,0x38,0xf0,0x06,0x36,0x0}}
};
-static const opl4_region_t regions_0e[] = { /* Tubular Bell */
+static const struct opl4_region regions_0e[] = { /* Tubular Bell */
{0x01, 0x7f, {0x0ff,3999,100, 0,1,0x00,0x90,0x21,0xf4,0xa3,0x25,0x1}}
};
-static const opl4_region_t regions_0f[] = { /* Dulcimer */
+static const struct opl4_region regions_0f[] = { /* Dulcimer */
{0x00, 0x7f, {0x03f,4236,100, 0,1,0x00,0xbc,0x29,0xf5,0x16,0x07,0x0}},
{0x00, 0x7f, {0x040,4236,100, 0,2,0x0e,0x94,0x2a,0xf5,0x16,0x07,0x0}}
};
-static const opl4_region_t regions_10[] = { /* Drawbar Organ */
+static const struct opl4_region regions_10[] = { /* Drawbar Organ */
{0x01, 0x7f, {0x08e,4394,100, 0,2,0x14,0xc2,0x3a,0xf0,0x00,0x0a,0x0}}
};
-static const opl4_region_t regions_11[] = { /* Percussive Organ */
+static const struct opl4_region regions_11[] = { /* Percussive Organ */
{0x15, 0x3b, {0x08c,6062,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}},
{0x3c, 0x6c, {0x08d,2984,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_12[] = { /* Rock Organ */
+static const struct opl4_region regions_12[] = { /* Rock Organ */
{0x15, 0x30, {0x128,6574,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
{0x31, 0x3c, {0x129,5040,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
{0x3d, 0x48, {0x12a,3498,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
{0x49, 0x54, {0x12b,1957,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
{0x55, 0x6c, {0x127, 423,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}
};
-static const opl4_region_t regions_13[] = { /* Church Organ */
+static const struct opl4_region regions_13[] = { /* Church Organ */
{0x15, 0x29, {0x087,7466,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
{0x2a, 0x30, {0x088,6456,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
{0x31, 0x38, {0x089,5428,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
{0x39, 0x41, {0x08a,4408,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
{0x42, 0x6c, {0x08b,3406,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_14[] = { /* Reed Organ */
+static const struct opl4_region regions_14[] = { /* Reed Organ */
{0x00, 0x53, {0x0ac,5570,100, 0,0,0x06,0xc0,0x38,0xf0,0x00,0x09,0x1}},
{0x54, 0x7f, {0x0ad,2497,100, 0,0,0x00,0xc0,0x38,0xf0,0x00,0x09,0x1}}
};
-static const opl4_region_t regions_15[] = { /* Accordion */
+static const struct opl4_region regions_15[] = { /* Accordion */
{0x15, 0x4c, {0x006,4261,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}},
{0x4d, 0x6c, {0x007,1530,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}},
{0x15, 0x6c, {0x070,4391,100, 0,3,0x00,0x8a,0x23,0xa0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_16[] = { /* Harmonica */
+static const struct opl4_region regions_16[] = { /* Harmonica */
{0x15, 0x6c, {0x070,4408,100, 0,0,0x00,0xae,0x30,0xa0,0x00,0x09,0x2}}
};
-static const opl4_region_t regions_17[] = { /* Tango Accordion */
+static const struct opl4_region regions_17[] = { /* Tango Accordion */
{0x00, 0x53, {0x0ac,5573,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}},
{0x54, 0x7f, {0x0ad,2500,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}},
{0x15, 0x6c, {0x041,8479,100, 0,2,0x00,0x6a,0x3a,0x75,0x20,0x0a,0x0}}
};
-static const opl4_region_t regions_18[] = { /* Nylon Guitar */
+static const struct opl4_region regions_18[] = { /* Nylon Guitar */
{0x15, 0x2f, {0x0b3,6964,100, 0,0,0x05,0xca,0x28,0xf5,0x34,0x09,0x0}},
{0x30, 0x36, {0x0b7,5567,100, 0,0,0x0c,0xca,0x28,0xf5,0x34,0x09,0x0}},
{0x37, 0x3c, {0x0b5,4653,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
{0x3d, 0x43, {0x0b4,3892,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x09,0x0}},
{0x44, 0x60, {0x0b6,2723,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x19,0x0}}
};
-static const opl4_region_t regions_19[] = { /* Steel Guitar */
+static const struct opl4_region regions_19[] = { /* Steel Guitar */
{0x15, 0x31, {0x00c,6937,100, 0,0,0x00,0xbc,0x28,0xf0,0x04,0x19,0x0}},
{0x32, 0x38, {0x00d,5410,100, 0,0,0x00,0xbc,0x28,0xf0,0x05,0x09,0x0}},
{0x39, 0x47, {0x00e,4379,100, 0,0,0x00,0xbc,0x28,0xf5,0x94,0x09,0x0}},
{0x48, 0x6c, {0x00f,2843,100, 0,0,0x00,0xbc,0x28,0xf6,0x95,0x09,0x0}}
};
-static const opl4_region_t regions_1a[] = { /* Jazz Guitar */
+static const struct opl4_region regions_1a[] = { /* Jazz Guitar */
{0x15, 0x31, {0x05a,6832,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
{0x32, 0x3f, {0x05b,4897,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
{0x40, 0x6c, {0x05c,3218,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}
};
-static const opl4_region_t regions_1b[] = { /* Clean Guitar */
+static const struct opl4_region regions_1b[] = { /* Clean Guitar */
{0x15, 0x2c, {0x061,7053,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}},
{0x2d, 0x31, {0x060,6434,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}},
{0x32, 0x38, {0x063,5764,100, 0,1,0x00,0xbe,0x29,0xf5,0x55,0x0a,0x0}},
@@ -245,14 +245,14 @@ static const opl4_region_t regions_1b[] = { /* Clean Guitar */
{0x4c, 0x54, {0x066,2462,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x2a,0x0}},
{0x55, 0x6c, {0x067,1307,100, 0,1,0x00,0xb4,0x29,0xf6,0x56,0x0a,0x0}}
};
-static const opl4_region_t regions_1c[] = { /* Muted Guitar */
+static const struct opl4_region regions_1c[] = { /* Muted Guitar */
{0x01, 0x7f, {0x068,4408,100, 0,0,0x00,0xcc,0x28,0xf6,0x15,0x09,0x0}}
};
-static const opl4_region_t regions_1d[] = { /* Overdriven Guitar */
+static const struct opl4_region regions_1d[] = { /* Overdriven Guitar */
{0x00, 0x40, {0x0a5,6589,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}},
{0x41, 0x7f, {0x0a6,5428,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}}
};
-static const opl4_region_t regions_1e[] = { /* Distortion Guitar */
+static const struct opl4_region regions_1e[] = { /* Distortion Guitar */
{0x15, 0x2a, {0x051,6928,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
{0x2b, 0x2e, {0x052,6433,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
{0x2f, 0x32, {0x053,5944,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
@@ -263,44 +263,44 @@ static const opl4_region_t regions_1e[] = { /* Distortion Guitar */
{0x43, 0x46, {0x058,3361,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
{0x47, 0x6c, {0x059,2784,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}
};
-static const opl4_region_t regions_1f[] = { /* Guitar Harmonics */
+static const struct opl4_region regions_1f[] = { /* Guitar Harmonics */
{0x15, 0x44, {0x05e,5499,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}},
{0x45, 0x49, {0x05d,4850,100, 0,0,0x00,0xe2,0x28,0xf4,0x24,0x09,0x0}},
{0x4a, 0x6c, {0x05f,4259,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}}
};
-static const opl4_region_t regions_20[] = { /* Acoustic Bass */
+static const struct opl4_region regions_20[] = { /* Acoustic Bass */
{0x15, 0x30, {0x004,8053,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}},
{0x31, 0x6c, {0x005,4754,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}}
};
-static const opl4_region_t regions_21[] = { /* Fingered Bass */
+static const struct opl4_region regions_21[] = { /* Fingered Bass */
{0x01, 0x20, {0x04a,8762,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
{0x21, 0x25, {0x04b,8114,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
{0x26, 0x2a, {0x04c,7475,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
{0x2b, 0x7f, {0x04d,6841,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}
};
-static const opl4_region_t regions_22[] = { /* Picked Bass */
+static const struct opl4_region regions_22[] = { /* Picked Bass */
{0x15, 0x23, {0x04f,7954,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x0a,0x0}},
{0x24, 0x2a, {0x050,7318,100, 0,0,0x05,0xcc,0x18,0xf3,0x90,0x1a,0x0}},
{0x2b, 0x2f, {0x06b,6654,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x2a,0x0}},
{0x30, 0x47, {0x069,6031,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}},
{0x48, 0x6c, {0x06a,5393,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}}
};
-static const opl4_region_t regions_23[] = { /* Fretless Bass */
+static const struct opl4_region regions_23[] = { /* Fretless Bass */
{0x01, 0x7f, {0x04e,5297,100, 0,0,0x00,0xd2,0x10,0xf3,0x63,0x19,0x0}}
};
-static const opl4_region_t regions_24[] = { /* Slap Bass 1 */
+static const struct opl4_region regions_24[] = { /* Slap Bass 1 */
{0x15, 0x6c, {0x0a3,7606,100, 0,1,0x00,0xde,0x19,0xf5,0x32,0x1a,0x0}}
};
-static const opl4_region_t regions_25[] = { /* Slap Bass 2 */
+static const struct opl4_region regions_25[] = { /* Slap Bass 2 */
{0x01, 0x7f, {0x0a2,6694,100, 0,0,0x00,0xda,0x20,0xb0,0x02,0x09,0x0}}
};
-static const opl4_region_t regions_26[] = { /* Synth Bass 1 */
+static const struct opl4_region regions_26[] = { /* Synth Bass 1 */
{0x15, 0x6c, {0x0be,7466,100, 0,1,0x00,0xb8,0x39,0xf4,0x14,0x09,0x0}}
};
-static const opl4_region_t regions_27[] = { /* Synth Bass 2 */
+static const struct opl4_region regions_27[] = { /* Synth Bass 2 */
{0x00, 0x7f, {0x117,8103,100, 0,1,0x00,0xca,0x39,0xf3,0x50,0x08,0x0}}
};
-static const opl4_region_t regions_28[] = { /* Violin */
+static const struct opl4_region regions_28[] = { /* Violin */
{0x15, 0x3a, {0x105,5158,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
{0x3b, 0x3f, {0x102,4754,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
{0x40, 0x41, {0x106,4132,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
@@ -312,7 +312,7 @@ static const opl4_region_t regions_28[] = { /* Violin */
{0x4f, 0x51, {0x10d,2166,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
{0x52, 0x6c, {0x109,1825,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}
};
-static const opl4_region_t regions_29[] = { /* Viola */
+static const struct opl4_region regions_29[] = { /* Viola */
{0x15, 0x32, {0x103,5780,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
{0x33, 0x35, {0x104,5534,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
{0x36, 0x38, {0x105,5158,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
@@ -326,76 +326,76 @@ static const opl4_region_t regions_29[] = { /* Viola */
{0x4d, 0x4f, {0x10d,2166,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}},
{0x50, 0x6c, {0x109,1825,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}
};
-static const opl4_region_t regions_2a[] = { /* Cello */
+static const struct opl4_region regions_2a[] = { /* Cello */
{0x15, 0x2d, {0x112,6545,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}},
{0x2e, 0x37, {0x113,5764,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}},
{0x38, 0x3e, {0x115,4378,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}},
{0x3f, 0x44, {0x116,3998,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}},
{0x45, 0x6c, {0x114,3218,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}
};
-static const opl4_region_t regions_2b[] = { /* Contrabass */
+static const struct opl4_region regions_2b[] = { /* Contrabass */
{0x15, 0x29, {0x110,7713,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}},
{0x2a, 0x6c, {0x111,6162,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_2c[] = { /* Tremolo Strings */
+static const struct opl4_region regions_2c[] = { /* Tremolo Strings */
{0x15, 0x3b, {0x0b0,4810,100, 0,0,0x0a,0xde,0x38,0xf0,0x00,0x07,0x6}},
{0x3c, 0x41, {0x035,4035,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
{0x42, 0x47, {0x033,3129,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
{0x48, 0x52, {0x034,2625,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
{0x53, 0x6c, {0x0af, 936,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x07,0x6}}
};
-static const opl4_region_t regions_2d[] = { /* Pizzicato Strings */
+static const struct opl4_region regions_2d[] = { /* Pizzicato Strings */
{0x15, 0x32, {0x0b8,6186,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
{0x33, 0x3b, {0x0b9,5031,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
{0x3c, 0x42, {0x0bb,4146,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
{0x43, 0x48, {0x0ba,3245,100, 0,0,0x00,0xc2,0x28,0xf0,0x00,0x05,0x0}},
{0x49, 0x6c, {0x0bc,2352,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}
};
-static const opl4_region_t regions_2e[] = { /* Harp */
+static const struct opl4_region regions_2e[] = { /* Harp */
{0x15, 0x46, {0x07e,3740,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}},
{0x47, 0x6c, {0x07f,2319,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}}
};
-static const opl4_region_t regions_2f[] = { /* Timpani */
+static const struct opl4_region regions_2f[] = { /* Timpani */
{0x15, 0x6c, {0x100,6570,100, 0,0,0x00,0xf8,0x28,0xf0,0x05,0x16,0x0}}
};
-static const opl4_region_t regions_30[] = { /* Strings */
+static const struct opl4_region regions_30[] = { /* Strings */
{0x15, 0x3b, {0x13c,4806,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
{0x3c, 0x41, {0x13e,4035,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
{0x42, 0x47, {0x13d,3122,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
{0x48, 0x52, {0x13f,2629,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}},
{0x53, 0x6c, {0x140, 950,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}}
};
-static const opl4_region_t regions_31[] = { /* Slow Strings */
+static const struct opl4_region regions_31[] = { /* Slow Strings */
{0x15, 0x3b, {0x0b0,4810,100, 0,1,0x0a,0xbe,0x19,0xf0,0x00,0x07,0x0}},
{0x3c, 0x41, {0x035,4035,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
{0x42, 0x47, {0x033,3129,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
{0x48, 0x52, {0x034,2625,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
{0x53, 0x6c, {0x0af, 936,100, 0,1,0x00,0xbe,0x19,0xf0,0x00,0x07,0x0}}
};
-static const opl4_region_t regions_32[] = { /* Synth Strings 1 */
+static const struct opl4_region regions_32[] = { /* Synth Strings 1 */
{0x05, 0x71, {0x002,6045,100,-2,0,0x00,0xa6,0x20,0x93,0x22,0x06,0x0}},
{0x15, 0x6c, {0x0ae,3261,100, 2,0,0x00,0xc6,0x20,0x70,0x01,0x06,0x0}}
};
-static const opl4_region_t regions_33[] = { /* Synth Strings 2 */
+static const struct opl4_region regions_33[] = { /* Synth Strings 2 */
{0x15, 0x6c, {0x002,4513,100, 5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}},
{0x15, 0x6c, {0x002,4501,100,-5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}}
};
-static const opl4_region_t regions_34[] = { /* Choir Aahs */
+static const struct opl4_region regions_34[] = { /* Choir Aahs */
{0x15, 0x3a, {0x018,5010,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
{0x3b, 0x40, {0x019,4370,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
{0x41, 0x47, {0x01a,3478,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
{0x48, 0x6c, {0x01b,2197,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}
};
-static const opl4_region_t regions_35[] = { /* Voice Oohs */
+static const struct opl4_region regions_35[] = { /* Voice Oohs */
{0x15, 0x6c, {0x029,3596,100, 0,0,0x00,0xe6,0x20,0xf7,0x20,0x08,0x0}}
};
-static const opl4_region_t regions_36[] = { /* Synth Voice */
+static const struct opl4_region regions_36[] = { /* Synth Voice */
{0x15, 0x6c, {0x02a,3482,100, 0,1,0x00,0xc2,0x19,0x85,0x21,0x07,0x0}}
};
-static const opl4_region_t regions_37[] = { /* Orchestra Hit */
+static const struct opl4_region regions_37[] = { /* Orchestra Hit */
{0x15, 0x6c, {0x049,4394,100, 0,0,0x00,0xfe,0x30,0x80,0x05,0x05,0x0}}
};
-static const opl4_region_t regions_38[] = { /* Trumpet */
+static const struct opl4_region regions_38[] = { /* Trumpet */
{0x15, 0x3c, {0x0f6,4706,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
{0x3d, 0x43, {0x0f8,3894,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
{0x44, 0x48, {0x0f7,3118,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
@@ -403,28 +403,28 @@ static const opl4_region_t regions_38[] = { /* Trumpet */
{0x4f, 0x55, {0x0f9,1634,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
{0x56, 0x6c, {0x0fb, 786,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}
};
-static const opl4_region_t regions_39[] = { /* Trombone */
+static const struct opl4_region regions_39[] = { /* Trombone */
{0x15, 0x3a, {0x0f0,5053,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}},
{0x3b, 0x3f, {0x0f1,4290,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}},
{0x40, 0x6c, {0x0f2,3580,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_3a[] = { /* Tuba */
+static const struct opl4_region regions_3a[] = { /* Tuba */
{0x15, 0x2d, {0x085,7096,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}},
{0x2e, 0x6c, {0x086,6014,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}}
};
-static const opl4_region_t regions_3b[] = { /* Muted Trumpet */
+static const struct opl4_region regions_3b[] = { /* Muted Trumpet */
{0x15, 0x45, {0x0b1,4135,100, 0,0,0x00,0xcc,0x28,0xf3,0x10,0x0a,0x1}},
{0x46, 0x6c, {0x0b2,2599,100, 0,0,0x00,0xcc,0x28,0x83,0x10,0x0a,0x1}}
};
-static const opl4_region_t regions_3c[] = { /* French Horns */
+static const struct opl4_region regions_3c[] = { /* French Horns */
{0x15, 0x49, {0x07c,3624,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}},
{0x4a, 0x6c, {0x07d,2664,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_3d[] = { /* Brass Section */
+static const struct opl4_region regions_3d[] = { /* Brass Section */
{0x15, 0x42, {0x0fc,4375,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}},
{0x43, 0x6c, {0x0fd,2854,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}}
};
-static const opl4_region_t regions_3e[] = { /* Synth Brass 1 */
+static const struct opl4_region regions_3e[] = { /* Synth Brass 1 */
{0x01, 0x27, {0x0d3,9094,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
{0x28, 0x2d, {0x0da,8335,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
{0x2e, 0x33, {0x0d4,7558,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
@@ -450,7 +450,7 @@ static const opl4_region_t regions_3e[] = { /* Synth Brass 1 */
{0x5e, 0x64, {0x122,1421,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
{0x65, 0x7f, {0x123,-115,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}
};
-static const opl4_region_t regions_3f[] = { /* Synth Brass 2 */
+static const struct opl4_region regions_3f[] = { /* Synth Brass 2 */
{0x01, 0x27, {0x118,9113,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
{0x28, 0x2d, {0x119,8350,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
{0x2e, 0x33, {0x11a,7575,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
@@ -465,7 +465,7 @@ static const opl4_region_t regions_3f[] = { /* Synth Brass 2 */
{0x65, 0x7f, {0x123,-105,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
{0x00, 0x7f, {0x124,4034,100,-3,2,0x00,0xea,0x22,0x85,0x23,0x08,0x0}}
};
-static const opl4_region_t regions_40[] = { /* Soprano Sax */
+static const struct opl4_region regions_40[] = { /* Soprano Sax */
{0x15, 0x3f, {0x0e3,4228,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}},
{0x40, 0x45, {0x0e4,3495,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}},
{0x46, 0x4b, {0x0e5,2660,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}},
@@ -473,7 +473,7 @@ static const opl4_region_t regions_40[] = { /* Soprano Sax */
{0x52, 0x59, {0x0e7,1186,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}},
{0x59, 0x6c, {0x0e8,1730,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}
};
-static const opl4_region_t regions_41[] = { /* Alto Sax */
+static const struct opl4_region regions_41[] = { /* Alto Sax */
{0x15, 0x32, {0x092,6204,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
{0x33, 0x35, {0x096,5812,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
{0x36, 0x3a, {0x099,5318,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
@@ -488,7 +488,7 @@ static const opl4_region_t regions_41[] = { /* Alto Sax */
{0x51, 0x53, {0x091,2088,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
{0x54, 0x6c, {0x095,1732,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}
};
-static const opl4_region_t regions_42[] = { /* Tenor Sax */
+static const struct opl4_region regions_42[] = { /* Tenor Sax */
{0x24, 0x30, {0x0e9,6301,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
{0x31, 0x34, {0x0ea,5781,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
{0x35, 0x3a, {0x0eb,5053,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
@@ -497,13 +497,13 @@ static const opl4_region_t regions_42[] = { /* Tenor Sax */
{0x48, 0x51, {0x0ee,2462,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
{0x52, 0x6c, {0x0ef,1421,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}
};
-static const opl4_region_t regions_43[] = { /* Baritone Sax */
+static const struct opl4_region regions_43[] = { /* Baritone Sax */
{0x15, 0x2d, {0x0df,6714,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
{0x2e, 0x34, {0x0e1,5552,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
{0x35, 0x39, {0x0e2,5178,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
{0x3a, 0x6c, {0x0e0,4437,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}
};
-static const opl4_region_t regions_44[] = { /* Oboe */
+static const struct opl4_region regions_44[] = { /* Oboe */
{0x15, 0x3c, {0x042,4493,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}},
{0x3d, 0x43, {0x044,3702,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
{0x44, 0x49, {0x043,2956,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
@@ -511,55 +511,55 @@ static const opl4_region_t regions_44[] = { /* Oboe */
{0x50, 0x55, {0x045,1420,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
{0x56, 0x6c, {0x047, 630,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}}
};
-static const opl4_region_t regions_45[] = { /* English Horn */
+static const struct opl4_region regions_45[] = { /* English Horn */
{0x15, 0x38, {0x03c,5098,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}},
{0x39, 0x3e, {0x03b,4291,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}},
{0x3f, 0x6c, {0x03d,3540,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_46[] = { /* Bassoon */
+static const struct opl4_region regions_46[] = { /* Bassoon */
{0x15, 0x22, {0x038,7833,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}},
{0x23, 0x2e, {0x03a,7070,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}},
{0x2f, 0x6c, {0x039,6302,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}
};
-static const opl4_region_t regions_47[] = { /* Clarinet */
+static const struct opl4_region regions_47[] = { /* Clarinet */
{0x15, 0x3b, {0x09e,5900,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
{0x3c, 0x41, {0x0a0,5158,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
{0x42, 0x4a, {0x09f,4260,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
{0x4b, 0x6c, {0x0a1,2957,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}
};
-static const opl4_region_t regions_48[] = { /* Piccolo */
+static const struct opl4_region regions_48[] = { /* Piccolo */
{0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
{0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
{0x4e, 0x53, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
{0x54, 0x5f, {0x074,2085,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
{0x60, 0x6c, {0x075,1421,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}
};
-static const opl4_region_t regions_49[] = { /* Flute */
+static const struct opl4_region regions_49[] = { /* Flute */
{0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}},
{0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}},
{0x4e, 0x6c, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}
};
-static const opl4_region_t regions_4a[] = { /* Recorder */
+static const struct opl4_region regions_4a[] = { /* Recorder */
{0x15, 0x6f, {0x0bd,4897,100, 0,0,0x00,0xec,0x30,0x70,0x00,0x09,0x1}}
};
-static const opl4_region_t regions_4b[] = { /* Pan Flute */
+static const struct opl4_region regions_4b[] = { /* Pan Flute */
{0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x09,0x3}}
};
-static const opl4_region_t regions_4c[] = { /* Bottle Blow */
+static const struct opl4_region regions_4c[] = { /* Bottle Blow */
{0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xc8,0x38,0xf0,0x00,0x09,0x1}},
{0x01, 0x7f, {0x125,7372,100, 0,0,0x1e,0x80,0x00,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_4d[] = { /* Shakuhachi */
+static const struct opl4_region regions_4d[] = { /* Shakuhachi */
{0x00, 0x7f, {0x0ab,4548,100, 0,0,0x00,0xd6,0x30,0xf0,0x00,0x0a,0x3}},
{0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xa2,0x28,0x70,0x00,0x09,0x2}}
};
-static const opl4_region_t regions_4e[] = { /* Whistle */
+static const struct opl4_region regions_4e[] = { /* Whistle */
{0x00, 0x7f, {0x0aa,1731,100, 0,4,0x00,0xd2,0x2c,0x70,0x00,0x0a,0x0}}
};
-static const opl4_region_t regions_4f[] = { /* Ocarina */
+static const struct opl4_region regions_4f[] = { /* Ocarina */
{0x00, 0x7f, {0x0aa,1731,100, 0,1,0x00,0xce,0x29,0x90,0x00,0x0a,0x1}}
};
-static const opl4_region_t regions_50[] = { /* Square Lead */
+static const struct opl4_region regions_50[] = { /* Square Lead */
{0x01, 0x2a, {0x0cc,9853,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
{0x2b, 0x36, {0x0cd,6785,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
{0x37, 0x42, {0x0ca,5248,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
@@ -573,7 +573,7 @@ static const opl4_region_t regions_50[] = { /* Square Lead */
{0x4f, 0x5a, {0x0ce,2167,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
{0x5b, 0x7f, {0x0cb, 631,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}
};
-static const opl4_region_t regions_51[] = { /* Sawtooth Lead */
+static const struct opl4_region regions_51[] = { /* Sawtooth Lead */
{0x01, 0x27, {0x118,9108,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
{0x28, 0x2d, {0x119,8345,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
{0x2e, 0x33, {0x11a,7570,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
@@ -599,15 +599,15 @@ static const opl4_region_t regions_51[] = { /* Sawtooth Lead */
{0x5e, 0x66, {0x122,1416,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
{0x67, 0x7f, {0x123,-120,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}
};
-static const opl4_region_t regions_52[] = { /* Calliope Lead */
+static const struct opl4_region regions_52[] = { /* Calliope Lead */
{0x00, 0x7f, {0x0aa,1731,100, 0,0,0x00,0xc2,0x28,0x90,0x00,0x0a,0x2}},
{0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xb6,0x28,0xb0,0x00,0x09,0x2}}
};
-static const opl4_region_t regions_53[] = { /* Chiffer Lead */
+static const struct opl4_region regions_53[] = { /* Chiffer Lead */
{0x00, 0x7f, {0x13a,3665,100, 0,2,0x00,0xcc,0x2a,0xf0,0x10,0x09,0x1}},
{0x01, 0x7f, {0x0fe,3660,100, 0,0,0x00,0xbe,0x28,0xf3,0x10,0x17,0x0}}
};
-static const opl4_region_t regions_54[] = { /* Charang Lead */
+static const struct opl4_region regions_54[] = { /* Charang Lead */
{0x00, 0x40, {0x0a5,6594,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}},
{0x41, 0x7f, {0x0a6,5433,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}},
{0x01, 0x27, {0x118,9098,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
@@ -623,11 +623,11 @@ static const opl4_region_t regions_54[] = { /* Charang Lead */
{0x5e, 0x66, {0x122,1416,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
{0x67, 0x7f, {0x123,-120,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}
};
-static const opl4_region_t regions_55[] = { /* Voice Lead */
+static const struct opl4_region regions_55[] = { /* Voice Lead */
{0x00, 0x7f, {0x0aa,1739,100, 0,6,0x00,0x8c,0x2e,0x90,0x00,0x0a,0x0}},
{0x15, 0x6c, {0x02a,3474,100, 0,1,0x00,0xd8,0x29,0xf0,0x05,0x0a,0x0}}
};
-static const opl4_region_t regions_56[] = { /* 5ths Lead */
+static const struct opl4_region regions_56[] = { /* 5ths Lead */
{0x01, 0x27, {0x118,8468,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
{0x28, 0x2d, {0x119,7705,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
{0x2e, 0x33, {0x11a,6930,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
@@ -642,7 +642,7 @@ static const opl4_region_t regions_56[] = { /* 5ths Lead */
{0x65, 0x7f, {0x123,-750,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
{0x05, 0x71, {0x002,4503,100, 0,1,0x00,0xb8,0x31,0xb3,0x20,0x0b,0x0}}
};
-static const opl4_region_t regions_57[] = { /* Bass & Lead */
+static const struct opl4_region regions_57[] = { /* Bass & Lead */
{0x00, 0x7f, {0x117,8109,100, 0,1,0x00,0xbc,0x29,0xf3,0x50,0x08,0x0}},
{0x01, 0x27, {0x118,9097,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
{0x28, 0x2d, {0x119,8334,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
@@ -657,15 +657,15 @@ static const opl4_region_t regions_57[] = { /* Bass & Lead */
{0x5e, 0x66, {0x122,1415,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
{0x67, 0x7f, {0x123,-121,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}
};
-static const opl4_region_t regions_58[] = { /* New Age Pad */
+static const struct opl4_region regions_58[] = { /* New Age Pad */
{0x15, 0x6c, {0x002,4501,100, 0,4,0x00,0xa4,0x24,0x80,0x01,0x05,0x0}},
{0x15, 0x6c, {0x0f3,4253,100, 0,3,0x00,0x8c,0x23,0xa2,0x14,0x06,0x1}}
};
-static const opl4_region_t regions_59[] = { /* Warm Pad */
+static const struct opl4_region regions_59[] = { /* Warm Pad */
{0x15, 0x6c, {0x04e,5306,100, 2,2,0x00,0x92,0x2a,0x34,0x23,0x05,0x2}},
{0x15, 0x6c, {0x029,3575,100,-2,2,0x00,0xbe,0x22,0x31,0x23,0x06,0x0}}
};
-static const opl4_region_t regions_5a[] = { /* Polysynth Pad */
+static const struct opl4_region regions_5a[] = { /* Polysynth Pad */
{0x01, 0x27, {0x118,9111,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
{0x28, 0x2d, {0x119,8348,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
{0x2e, 0x33, {0x11a,7573,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
@@ -680,29 +680,29 @@ static const opl4_region_t regions_5a[] = { /* Polysynth Pad */
{0x67, 0x7f, {0x123,-107,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
{0x00, 0x7f, {0x124,4024,100, 0,2,0x00,0xae,0x22,0xe5,0x20,0x08,0x0}}
};
-static const opl4_region_t regions_5b[] = { /* Choir Pad */
+static const struct opl4_region regions_5b[] = { /* Choir Pad */
{0x15, 0x3a, {0x018,5010,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
{0x3b, 0x40, {0x019,4370,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
{0x41, 0x47, {0x01a,3478,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
{0x48, 0x6c, {0x01b,2197,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
{0x15, 0x6c, {0x02a,3482,100, 0,4,0x00,0x98,0x24,0x65,0x21,0x06,0x0}}
};
-static const opl4_region_t regions_5c[] = { /* Bowed Pad */
+static const struct opl4_region regions_5c[] = { /* Bowed Pad */
{0x15, 0x6c, {0x101,4790,100,-1,1,0x00,0xbe,0x19,0x44,0x14,0x16,0x0}},
{0x00, 0x7f, {0x0aa,1720,100, 1,1,0x00,0x94,0x19,0x40,0x00,0x06,0x0}}
};
-static const opl4_region_t regions_5d[] = { /* Metallic Pad */
+static const struct opl4_region regions_5d[] = { /* Metallic Pad */
{0x15, 0x31, {0x00c,6943,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
{0x32, 0x38, {0x00d,5416,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
{0x39, 0x47, {0x00e,4385,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
{0x48, 0x6c, {0x00f,2849,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
{0x00, 0x7f, {0x03f,4224,100, 0,1,0x00,0x9c,0x31,0x65,0x16,0x07,0x0}}
};
-static const opl4_region_t regions_5e[] = { /* Halo Pad */
+static const struct opl4_region regions_5e[] = { /* Halo Pad */
{0x00, 0x7f, {0x124,4038,100, 0,2,0x00,0xa6,0x1a,0x85,0x23,0x08,0x0}},
{0x15, 0x6c, {0x02a,3471,100, 0,3,0x00,0xc0,0x1b,0xc0,0x05,0x06,0x0}}
};
-static const opl4_region_t regions_5f[] = { /* Sweep Pad */
+static const struct opl4_region regions_5f[] = { /* Sweep Pad */
{0x01, 0x27, {0x0d3,9100,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
{0x28, 0x2d, {0x0da,8341,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
{0x2e, 0x33, {0x0d4,7564,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
@@ -728,21 +728,21 @@ static const opl4_region_t regions_5f[] = { /* Sweep Pad */
{0x5e, 0x63, {0x0d8,1415,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
{0x64, 0x7f, {0x0d9,-121,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}
};
-static const opl4_region_t regions_60[] = { /* Ice Rain */
+static const struct opl4_region regions_60[] = { /* Ice Rain */
{0x01, 0x7f, {0x04e,9345,100, 0,2,0x00,0xcc,0x22,0xa3,0x63,0x17,0x0}},
{0x00, 0x7f, {0x143,5586, 20, 0,2,0x00,0x6e,0x2a,0xf0,0x05,0x05,0x0}}
};
-static const opl4_region_t regions_61[] = { /* Soundtrack */
+static const struct opl4_region regions_61[] = { /* Soundtrack */
{0x15, 0x6c, {0x002,4501,100, 0,2,0x00,0xb6,0x2a,0x60,0x01,0x05,0x0}},
{0x15, 0x6c, {0x0f3,1160,100, 0,5,0x00,0xa8,0x2d,0x52,0x14,0x06,0x2}}
};
-static const opl4_region_t regions_62[] = { /* Crystal */
+static const struct opl4_region regions_62[] = { /* Crystal */
{0x15, 0x6c, {0x0f3,1826,100, 0,3,0x00,0xb8,0x33,0xf6,0x25,0x25,0x0}},
{0x15, 0x2c, {0x06d,7454,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}},
{0x2d, 0x36, {0x06e,5925,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}},
{0x37, 0x6c, {0x06f,4403,100, 0,3,0x09,0xac,0x3b,0x85,0x24,0x06,0x0}}
};
-static const opl4_region_t regions_63[] = { /* Atmosphere */
+static const struct opl4_region regions_63[] = { /* Atmosphere */
{0x05, 0x71, {0x002,4509,100, 0,2,0x00,0xc8,0x32,0x73,0x22,0x06,0x1}},
{0x15, 0x2f, {0x0b3,6964,100, 0,2,0x05,0xc2,0x32,0xf5,0x34,0x07,0x2}},
{0x30, 0x36, {0x0b7,5567,100, 0,2,0x0c,0xc2,0x32,0xf5,0x34,0x07,0x2}},
@@ -750,29 +750,29 @@ static const opl4_region_t regions_63[] = { /* Atmosphere */
{0x3d, 0x43, {0x0b4,3892,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x07,0x2}},
{0x44, 0x60, {0x0b6,2723,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x17,0x2}}
};
-static const opl4_region_t regions_64[] = { /* Brightness */
+static const struct opl4_region regions_64[] = { /* Brightness */
{0x00, 0x7f, {0x137,5285,100, 0,2,0x00,0xbe,0x2a,0xa5,0x18,0x08,0x0}},
{0x15, 0x6c, {0x02a,3481,100, 0,1,0x00,0xc8,0x29,0x80,0x05,0x05,0x0}}
};
-static const opl4_region_t regions_65[] = { /* Goblins */
+static const struct opl4_region regions_65[] = { /* Goblins */
{0x15, 0x6c, {0x002,4501,100,-1,2,0x00,0xca,0x2a,0x40,0x01,0x05,0x0}},
{0x15, 0x6c, {0x009,9679, 20, 1,4,0x00,0x3c,0x0c,0x22,0x11,0x06,0x0}}
};
-static const opl4_region_t regions_66[] = { /* Echoes */
+static const struct opl4_region regions_66[] = { /* Echoes */
{0x15, 0x6c, {0x02a,3487,100, 0,3,0x00,0xae,0x2b,0xf5,0x21,0x06,0x0}},
{0x00, 0x7f, {0x124,4027,100, 0,3,0x00,0xae,0x2b,0x85,0x23,0x07,0x0}}
};
-static const opl4_region_t regions_67[] = { /* Sci-Fi */
+static const struct opl4_region regions_67[] = { /* Sci-Fi */
{0x15, 0x31, {0x00c,6940,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
{0x32, 0x38, {0x00d,5413,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
{0x39, 0x47, {0x00e,4382,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
{0x48, 0x6c, {0x00f,2846,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
{0x15, 0x6c, {0x002,4498,100, 0,2,0x00,0xd4,0x22,0x80,0x01,0x05,0x0}}
};
-static const opl4_region_t regions_68[] = { /* Sitar */
+static const struct opl4_region regions_68[] = { /* Sitar */
{0x00, 0x7f, {0x10f,4408,100, 0,2,0x00,0xc4,0x32,0xf4,0x15,0x16,0x1}}
};
-static const opl4_region_t regions_69[] = { /* Banjo */
+static const struct opl4_region regions_69[] = { /* Banjo */
{0x15, 0x34, {0x013,5685,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
{0x35, 0x38, {0x014,5009,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
{0x39, 0x3c, {0x012,4520,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
@@ -780,21 +780,21 @@ static const opl4_region_t regions_69[] = { /* Banjo */
{0x45, 0x4c, {0x017,2661,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
{0x4d, 0x6d, {0x016,1632,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}
};
-static const opl4_region_t regions_6a[] = { /* Shamisen */
+static const struct opl4_region regions_6a[] = { /* Shamisen */
{0x15, 0x6c, {0x10e,3273,100, 0,0,0x00,0xc0,0x28,0xf7,0x76,0x08,0x0}}
};
-static const opl4_region_t regions_6b[] = { /* Koto */
+static const struct opl4_region regions_6b[] = { /* Koto */
{0x00, 0x7f, {0x0a9,4033,100, 0,0,0x00,0xc6,0x20,0xf0,0x06,0x07,0x0}}
};
-static const opl4_region_t regions_6c[] = { /* Kalimba */
+static const struct opl4_region regions_6c[] = { /* Kalimba */
{0x00, 0x7f, {0x137,3749,100, 0,0,0x00,0xce,0x38,0xf5,0x18,0x08,0x0}}
};
-static const opl4_region_t regions_6d[] = { /* Bagpipe */
+static const struct opl4_region regions_6d[] = { /* Bagpipe */
{0x15, 0x39, {0x0a4,7683,100, 0,4,0x00,0xc0,0x1c,0xf0,0x00,0x09,0x0}},
{0x15, 0x39, {0x0a7,7680,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}},
{0x3a, 0x6c, {0x0a8,3697,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_6e[] = { /* Fiddle */
+static const struct opl4_region regions_6e[] = { /* Fiddle */
{0x15, 0x3a, {0x105,5158,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
{0x3b, 0x3f, {0x102,4754,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
{0x40, 0x41, {0x106,4132,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
@@ -806,64 +806,64 @@ static const opl4_region_t regions_6e[] = { /* Fiddle */
{0x4f, 0x51, {0x10d,2166,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
{0x52, 0x6c, {0x109,1825,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}
};
-static const opl4_region_t regions_6f[] = { /* Shanai */
+static const struct opl4_region regions_6f[] = { /* Shanai */
{0x15, 0x6c, {0x041,6946,100, 0,1,0x00,0xc4,0x31,0x95,0x20,0x09,0x0}}
};
-static const opl4_region_t regions_70[] = { /* Tinkle Bell */
+static const struct opl4_region regions_70[] = { /* Tinkle Bell */
{0x15, 0x73, {0x0f3,1821,100, 0,3,0x00,0xc8,0x3b,0xd6,0x25,0x25,0x0}},
{0x00, 0x7f, {0x137,5669,100, 0,3,0x00,0x66,0x3b,0xf5,0x18,0x08,0x0}}
};
-static const opl4_region_t regions_71[] = { /* Agogo */
+static const struct opl4_region regions_71[] = { /* Agogo */
{0x15, 0x74, {0x00b,2474,100, 0,0,0x00,0xd2,0x38,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_72[] = { /* Steel Drums */
+static const struct opl4_region regions_72[] = { /* Steel Drums */
{0x01, 0x7f, {0x0fe,3670,100, 0,0,0x00,0xca,0x38,0xf3,0x06,0x17,0x1}},
{0x15, 0x6c, {0x100,9602,100, 0,0,0x00,0x54,0x38,0xb0,0x05,0x16,0x1}}
};
-static const opl4_region_t regions_73[] = { /* Woodblock */
+static const struct opl4_region regions_73[] = { /* Woodblock */
{0x15, 0x6c, {0x02c,2963, 50, 0,0,0x07,0xd4,0x00,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_74[] = { /* Taiko Drum */
+static const struct opl4_region regions_74[] = { /* Taiko Drum */
{0x13, 0x6c, {0x03e,1194, 50, 0,0,0x00,0xaa,0x38,0xf0,0x04,0x04,0x0}}
};
-static const opl4_region_t regions_75[] = { /* Melodic Tom */
+static const struct opl4_region regions_75[] = { /* Melodic Tom */
{0x15, 0x6c, {0x0c7,6418, 50, 0,0,0x00,0xe4,0x38,0xf0,0x05,0x01,0x0}}
};
-static const opl4_region_t regions_76[] = { /* Synth Drum */
+static const struct opl4_region regions_76[] = { /* Synth Drum */
{0x15, 0x6c, {0x026,3898, 50, 0,0,0x00,0xd0,0x38,0xf0,0x04,0x04,0x0}}
};
-static const opl4_region_t regions_77[] = { /* Reverse Cymbal */
+static const struct opl4_region regions_77[] = { /* Reverse Cymbal */
{0x15, 0x6c, {0x031,4138, 50, 0,0,0x00,0xfe,0x38,0x3a,0xf0,0x09,0x0}}
};
-static const opl4_region_t regions_78[] = { /* Guitar Fret Noise */
+static const struct opl4_region regions_78[] = { /* Guitar Fret Noise */
{0x15, 0x6c, {0x138,5266,100, 0,0,0x00,0xa0,0x38,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_79[] = { /* Breath Noise */
+static const struct opl4_region regions_79[] = { /* Breath Noise */
{0x01, 0x7f, {0x125,4269,100, 0,0,0x1e,0xd0,0x38,0xf0,0x00,0x09,0x0}}
};
-static const opl4_region_t regions_7a[] = { /* Seashore */
+static const struct opl4_region regions_7a[] = { /* Seashore */
{0x15, 0x6c, {0x008,2965, 20,-2,0,0x00,0xfe,0x00,0x20,0x03,0x04,0x0}},
{0x01, 0x7f, {0x037,4394, 20, 2,0,0x14,0xfe,0x00,0x20,0x04,0x05,0x0}}
};
-static const opl4_region_t regions_7b[] = { /* Bird Tweet */
+static const struct opl4_region regions_7b[] = { /* Bird Tweet */
{0x15, 0x6c, {0x009,8078, 5,-4,7,0x00,0xc2,0x0f,0x22,0x12,0x07,0x0}},
{0x15, 0x6c, {0x009,3583, 5, 4,5,0x00,0xae,0x15,0x72,0x12,0x07,0x0}}
};
-static const opl4_region_t regions_7c[] = { /* Telephone Ring */
+static const struct opl4_region regions_7c[] = { /* Telephone Ring */
{0x15, 0x6c, {0x003,3602, 10, 0,0,0x00,0xce,0x00,0xf0,0x00,0x0f,0x0}}
};
-static const opl4_region_t regions_7d[] = { /* Helicopter */
+static const struct opl4_region regions_7d[] = { /* Helicopter */
{0x0c, 0x7f, {0x001,2965, 10,-2,0,0x00,0xe0,0x08,0x30,0x01,0x07,0x0}},
{0x01, 0x7f, {0x037,4394, 10, 2,0,0x44,0x76,0x00,0x30,0x01,0x07,0x0}}
};
-static const opl4_region_t regions_7e[] = { /* Applause */
+static const struct opl4_region regions_7e[] = { /* Applause */
{0x15, 0x6c, {0x036,8273, 20,-6,7,0x00,0xc4,0x0f,0x70,0x01,0x05,0x0}},
{0x15, 0x6c, {0x036,8115, 5, 6,7,0x00,0xc6,0x07,0x70,0x01,0x05,0x0}}
};
-static const opl4_region_t regions_7f[] = { /* Gun Shot */
+static const struct opl4_region regions_7f[] = { /* Gun Shot */
{0x15, 0x6c, {0x139,2858, 20, 0,0,0x00,0xbe,0x38,0xf0,0x03,0x00,0x0}}
};
-static const opl4_region_t regions_drums[] = {
+static const struct opl4_region regions_drums[] = {
{0x18, 0x18, {0x0cb,6397,100, 3,0,0x00,0xf4,0x38,0xc9,0x1c,0x0c,0x0}},
{0x19, 0x19, {0x0c4,3714,100, 0,0,0x00,0xe0,0x00,0x97,0x19,0x09,0x0}},
{0x1a, 0x1a, {0x0c4,3519,100, 0,0,0x00,0xea,0x00,0x61,0x01,0x07,0x0}},
@@ -924,7 +924,7 @@ static const opl4_region_t regions_drums[] = {
};
#define REGION(num) { ARRAY_SIZE(regions ## num), regions ## num }
-const opl4_region_ptr_t snd_yrw801_regions[0x81] = {
+const struct opl4_region_ptr snd_yrw801_regions[0x81] = {
REGION(_00), REGION(_01), REGION(_02), REGION(_03),
REGION(_04), REGION(_05), REGION(_06), REGION(_07),
REGION(_08), REGION(_09), REGION(_0a), REGION(_0b),
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 1ed58df42671..29676d800cae 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -33,6 +33,8 @@
#include <sound/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/moduleparam.h>
@@ -116,10 +118,10 @@ MODULE_PARM_DESC(adaptor, "Type of adaptor.");
#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3)
typedef struct _snd_uart16550 {
- snd_card_t *card;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *midi_output[SNDRV_SERIAL_MAX_OUTS];
- snd_rawmidi_substream_t *midi_input[SNDRV_SERIAL_MAX_INS];
+ struct snd_card *card;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS];
+ struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS];
int filemode; //open status of file
@@ -166,7 +168,7 @@ typedef struct _snd_uart16550 {
} snd_uart16550_t;
-static snd_card_t *snd_serial_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
static inline void snd_uart16550_add_timer(snd_uart16550_t *uart)
{
@@ -509,7 +511,7 @@ static void snd_uart16550_do_close(snd_uart16550_t * uart)
}
}
-static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
+static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -523,7 +525,7 @@ static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
+static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -537,7 +539,7 @@ static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -551,7 +553,7 @@ static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int
spin_unlock_irqrestore(&uart->open_lock, flags);
}
-static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
+static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -565,7 +567,7 @@ static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
return 0;
};
-static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream)
+static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -603,7 +605,7 @@ static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned cha
return 0;
}
-static int snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte)
+static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_substream *substream, unsigned char midi_byte)
{
if (uart->buff_in_count == 0 /* Buffer empty? */
&& ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
@@ -636,7 +638,7 @@ static int snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substrea
return 1;
}
-static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
+static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
unsigned char midi_byte, addr_byte;
@@ -715,7 +717,7 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
spin_unlock_irqrestore(&uart->open_lock, flags);
}
-static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
snd_uart16550_t *uart = substream->rmidi->private_data;
@@ -731,14 +733,14 @@ static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, in
snd_uart16550_output_write(substream);
}
-static snd_rawmidi_ops_t snd_uart16550_output =
+static struct snd_rawmidi_ops snd_uart16550_output =
{
.open = snd_uart16550_output_open,
.close = snd_uart16550_output_close,
.trigger = snd_uart16550_output_trigger,
};
-static snd_rawmidi_ops_t snd_uart16550_input =
+static struct snd_rawmidi_ops snd_uart16550_input =
{
.open = snd_uart16550_input_open,
.close = snd_uart16550_input_close,
@@ -754,13 +756,13 @@ static int snd_uart16550_free(snd_uart16550_t *uart)
return 0;
};
-static int snd_uart16550_dev_free(snd_device_t *device)
+static int snd_uart16550_dev_free(struct snd_device *device)
{
snd_uart16550_t *uart = device->device_data;
return snd_uart16550_free(uart);
}
-static int __init snd_uart16550_create(snd_card_t * card,
+static int __init snd_uart16550_create(struct snd_card *card,
unsigned long iobase,
int irq,
unsigned int speed,
@@ -769,7 +771,7 @@ static int __init snd_uart16550_create(snd_card_t * card,
int droponfull,
snd_uart16550_t **ruart)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_uart16550_dev_free,
};
snd_uart16550_t *uart;
@@ -838,19 +840,19 @@ static int __init snd_uart16550_create(snd_card_t * card,
return 0;
}
-static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream)
+static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream)
{
struct list_head *list;
list_for_each(list, &stream->substreams) {
- snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, list);
+ struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
}
}
-static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi)
+static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, struct snd_rawmidi **rmidi)
{
- snd_rawmidi_t *rrawmidi;
+ struct snd_rawmidi *rrawmidi;
int err;
if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0)
@@ -869,14 +871,12 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out
return 0;
}
-static int __init snd_serial_probe(int dev)
+static int __init snd_serial_probe(struct platform_device *devptr)
{
- snd_card_t *card;
+ struct snd_card *card;
snd_uart16550_t *uart;
int err;
-
- if (!enable[dev])
- return -ENOENT;
+ int dev = devptr->id;
switch (adaptor[dev]) {
case SNDRV_SERIAL_SOUNDCANVAS:
@@ -942,13 +942,12 @@ static int __init snd_serial_probe(int dev)
adaptor_names[uart->adaptor],
uart->drop_on_full);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_serial_cards[dev] = card;
+ platform_set_drvdata(devptr, card);
return 0;
_err:
@@ -956,33 +955,68 @@ static int __init snd_serial_probe(int dev)
return err;
}
+static int snd_serial_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define SND_SERIAL_DRIVER "snd_serial_u16550"
+
+static struct platform_driver snd_serial_driver = {
+ .probe = snd_serial_probe,
+ .remove = snd_serial_remove,
+ .driver = {
+ .name = SND_SERIAL_DRIVER
+ },
+};
+
+static void __init_or_module snd_serial_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_serial_driver);
+}
+
static int __init alsa_card_serial_init(void)
{
- int dev = 0;
- int cards = 0;
+ int i, cards, err;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (snd_serial_probe(dev) == 0)
- cards++;
- }
+ if ((err = platform_driver_register(&snd_serial_driver)) < 0)
+ return err;
- if (cards == 0) {
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_SERIAL_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
+ if (! cards) {
#ifdef MODULE
printk(KERN_ERR "serial midi soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_serial_unregister_all();
+ return err;
}
static void __exit alsa_card_serial_exit(void)
{
- int dev;
-
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (snd_serial_cards[dev] != NULL)
- snd_card_free(snd_serial_cards[dev]);
- }
+ snd_serial_unregister_all();
}
module_init(alsa_card_serial_init)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index af12185ab8a2..4258723de2ab 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -45,6 +45,8 @@
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/seq_kernel.h>
@@ -59,7 +61,7 @@ MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}");
-#define MAX_MIDI_DEVICES 8
+#define MAX_MIDI_DEVICES 4
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
@@ -73,24 +75,23 @@ MODULE_PARM_DESC(id, "ID string for virmidi soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable this soundcard.");
module_param_array(midi_devs, int, NULL, 0444);
-MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-8)");
+MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-4)");
-typedef struct snd_card_virmidi {
- snd_card_t *card;
- snd_rawmidi_t *midi[MAX_MIDI_DEVICES];
-} snd_card_virmidi_t;
+struct snd_card_virmidi {
+ struct snd_card *card;
+ struct snd_rawmidi *midi[MAX_MIDI_DEVICES];
+};
-static snd_card_t *snd_virmidi_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
-static int __init snd_card_virmidi_probe(int dev)
+static int __init snd_virmidi_probe(struct platform_device *devptr)
{
- snd_card_t *card;
+ struct snd_card *card;
struct snd_card_virmidi *vmidi;
int idx, err;
+ int dev = devptr->id;
- if (!enable[dev])
- return -ENODEV;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_virmidi));
if (card == NULL)
@@ -103,8 +104,8 @@ static int __init snd_card_virmidi_probe(int dev)
midi_devs[dev] = MAX_MIDI_DEVICES;
}
for (idx = 0; idx < midi_devs[dev]; idx++) {
- snd_rawmidi_t *rmidi;
- snd_virmidi_dev_t *rdev;
+ struct snd_rawmidi *rmidi;
+ struct snd_virmidi_dev *rdev;
if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0)
goto __nodev;
rdev = rmidi->private_data;
@@ -117,11 +118,10 @@ static int __init snd_card_virmidi_probe(int dev)
strcpy(card->shortname, "VirMIDI");
sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto __nodev;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) == 0) {
- snd_virmidi_cards[dev] = card;
+ platform_set_drvdata(devptr, card);
return 0;
}
__nodev:
@@ -129,34 +129,68 @@ static int __init snd_card_virmidi_probe(int dev)
return err;
}
-static int __init alsa_card_virmidi_init(void)
+static int snd_virmidi_remove(struct platform_device *devptr)
{
- int dev, cards;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (snd_card_virmidi_probe(dev) < 0) {
-#ifdef MODULE
- printk(KERN_ERR "Card-VirMIDI #%i not found or device busy\n", dev + 1);
-#endif
- break;
+#define SND_VIRMIDI_DRIVER "snd_virmidi"
+
+static struct platform_driver snd_virmidi_driver = {
+ .probe = snd_virmidi_probe,
+ .remove = snd_virmidi_remove,
+ .driver = {
+ .name = SND_VIRMIDI_DRIVER
+ },
+};
+
+static void __init_or_module snd_virmidi_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_virmidi_driver);
+}
+
+static int __init alsa_card_virmidi_init(void)
+{
+ int i, cards, err;
+
+ if ((err = platform_driver_register(&snd_virmidi_driver)) < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_VIRMIDI_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
}
+ devices[i] = device;
cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_virmidi_unregister_all();
+ return err;
}
static void __exit alsa_card_virmidi_exit(void)
{
- int dev;
-
- for (dev = 0; dev < SNDRV_CARDS; dev++)
- snd_card_free(snd_virmidi_cards[dev]);
+ snd_virmidi_unregister_all();
}
module_init(alsa_card_virmidi_init)
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 4697b1d75cbb..43f615d7a545 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -41,18 +41,6 @@ MODULE_LICENSE("GPL");
/*
- * snd_vx_delay - delay for the specified time
- * @xmsec: the time to delay in msec
- */
-void snd_vx_delay(vx_core_t *chip, int xmsec)
-{
- if (! in_interrupt() && xmsec >= 1000 / HZ)
- msleep(xmsec);
- else
- mdelay(xmsec);
-}
-
-/*
* vx_check_reg_bit - wait for the specified bit is set/reset on a register
* @reg: register to check
* @mask: bit mask
@@ -61,7 +49,7 @@ void snd_vx_delay(vx_core_t *chip, int xmsec)
*
* returns zero if a bit matches, or a negative error code.
*/
-int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time)
+int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time)
{
unsigned long end_time = jiffies + (time * HZ + 999) / 1000;
#ifdef CONFIG_SND_DEBUG
@@ -76,7 +64,7 @@ int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time)
do {
if ((snd_vx_inb(chip, reg) & mask) == bit)
return 0;
- //snd_vx_delay(chip, 10);
+ //msleep(10);
} while (time_after_eq(end_time, jiffies));
snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg));
return -EIO;
@@ -90,7 +78,7 @@ int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time)
* returns 0 if successful, or a negative error code.
*
*/
-static int vx_send_irq_dsp(vx_core_t *chip, int num)
+static int vx_send_irq_dsp(struct vx_core *chip, int num)
{
int nirq;
@@ -111,7 +99,7 @@ static int vx_send_irq_dsp(vx_core_t *chip, int num)
*
* returns 0 if successful, or a negative error code.
*/
-static int vx_reset_chk(vx_core_t *chip)
+static int vx_reset_chk(struct vx_core *chip)
{
/* Reset irq CHK */
if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0)
@@ -130,7 +118,7 @@ static int vx_reset_chk(vx_core_t *chip)
* the error code can be VX-specific, retrieved via vx_get_error().
* NB: call with spinlock held!
*/
-static int vx_transfer_end(vx_core_t *chip, int cmd)
+static int vx_transfer_end(struct vx_core *chip, int cmd)
{
int err;
@@ -168,7 +156,7 @@ static int vx_transfer_end(vx_core_t *chip, int cmd)
* the error code can be VX-specific, retrieved via vx_get_error().
* NB: call with spinlock held!
*/
-static int vx_read_status(vx_core_t *chip, struct vx_rmh *rmh)
+static int vx_read_status(struct vx_core *chip, struct vx_rmh *rmh)
{
int i, err, val, size;
@@ -248,7 +236,7 @@ static int vx_read_status(vx_core_t *chip, struct vx_rmh *rmh)
*
* this function doesn't call spinlock at all.
*/
-int vx_send_msg_nolock(vx_core_t *chip, struct vx_rmh *rmh)
+int vx_send_msg_nolock(struct vx_core *chip, struct vx_rmh *rmh)
{
int i, err;
@@ -353,7 +341,7 @@ int vx_send_msg_nolock(vx_core_t *chip, struct vx_rmh *rmh)
* returns 0 if successful, or a negative error code.
* see vx_send_msg_nolock().
*/
-int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh)
+int vx_send_msg(struct vx_core *chip, struct vx_rmh *rmh)
{
unsigned long flags;
int err;
@@ -376,7 +364,7 @@ int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh)
*
* unlike RMH, no command is sent to DSP.
*/
-int vx_send_rih_nolock(vx_core_t *chip, int cmd)
+int vx_send_rih_nolock(struct vx_core *chip, int cmd)
{
int err;
@@ -413,7 +401,7 @@ int vx_send_rih_nolock(vx_core_t *chip, int cmd)
*
* see vx_send_rih_nolock().
*/
-int vx_send_rih(vx_core_t *chip, int cmd)
+int vx_send_rih(struct vx_core *chip, int cmd)
{
unsigned long flags;
int err;
@@ -430,7 +418,7 @@ int vx_send_rih(vx_core_t *chip, int cmd)
* snd_vx_boot_xilinx - boot up the xilinx interface
* @boot: the boot record to load
*/
-int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *boot)
+int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot)
{
unsigned int i;
int no_fillup = vx_has_new_dsp(chip);
@@ -482,7 +470,7 @@ int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *boot)
*
* called from irq handler only
*/
-static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
+static int vx_test_irq_src(struct vx_core *chip, unsigned int *ret)
{
int err;
@@ -503,7 +491,7 @@ static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
*/
static void vx_interrupt(unsigned long private_data)
{
- vx_core_t *chip = (vx_core_t *) private_data;
+ struct vx_core *chip = (struct vx_core *) private_data;
unsigned int events;
if (chip->chip_status & VX_STAT_IS_STALE)
@@ -547,7 +535,7 @@ static void vx_interrupt(unsigned long private_data)
*/
irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
{
- vx_core_t *chip = dev;
+ struct vx_core *chip = dev;
if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
(chip->chip_status & VX_STAT_IS_STALE))
@@ -560,7 +548,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
/*
*/
-static void vx_reset_board(vx_core_t *chip, int cold_reset)
+static void vx_reset_board(struct vx_core *chip, int cold_reset)
{
snd_assert(chip->ops->reset_board, return);
@@ -599,9 +587,9 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset)
* proc interface
*/
-static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- vx_core_t *chip = entry->private_data;
+ struct vx_core *chip = entry->private_data;
static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
static char *clock_mode[] = { "Auto", "Internal", "External" };
@@ -642,9 +630,9 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
chip->ibl.granularity);
}
-static void vx_proc_init(vx_core_t *chip)
+static void vx_proc_init(struct vx_core *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "vx-status", &entry))
snd_info_set_text_ops(entry, chip, 1024, vx_proc_read);
@@ -654,7 +642,7 @@ static void vx_proc_init(vx_core_t *chip)
/**
* snd_vx_dsp_boot - load the DSP boot
*/
-int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot)
+int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot)
{
int err;
int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT);
@@ -664,7 +652,7 @@ int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot)
if ((err = snd_vx_load_boot_image(chip, boot)) < 0)
return err;
- snd_vx_delay(chip, 10);
+ msleep(10);
return 0;
}
@@ -672,7 +660,7 @@ int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot)
/**
* snd_vx_dsp_load - load the DSP image
*/
-int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
+int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
{
unsigned int i;
int err;
@@ -704,7 +692,7 @@ int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
}
snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum);
- snd_vx_delay(chip, 200);
+ msleep(200);
if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
return err;
@@ -721,13 +709,11 @@ int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
/*
* suspend
*/
-static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
+int snd_vx_suspend(struct vx_core *chip, pm_message_t state)
{
- vx_core_t *chip = card->pm_private_data;
unsigned int i;
- snd_assert(chip, return -EINVAL);
-
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
chip->chip_status |= VX_STAT_IN_SUSPEND;
for (i = 0; i < chip->hw->num_codecs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
@@ -738,13 +724,10 @@ static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
/*
* resume
*/
-static int snd_vx_resume(snd_card_t *card)
+int snd_vx_resume(struct vx_core *chip)
{
- vx_core_t *chip = card->pm_private_data;
int i, err;
- snd_assert(chip, return -EINVAL);
-
chip->chip_status &= ~VX_STAT_CHIP_INIT;
for (i = 0; i < 4; i++) {
@@ -760,13 +743,14 @@ static int snd_vx_resume(snd_card_t *card)
chip->chip_status |= VX_STAT_CHIP_INIT;
chip->chip_status &= ~VX_STAT_IN_SUSPEND;
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif
/**
- * snd_vx_create - constructor for vx_core_t
+ * snd_vx_create - constructor for struct vx_core
* @hw: hardware specific record
*
* this function allocates the instance and prepare for the hardware
@@ -774,11 +758,11 @@ static int snd_vx_resume(snd_card_t *card)
*
* return the instance pointer if successful, NULL in error.
*/
-vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
- struct snd_vx_ops *ops,
- int extra_size)
+struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
+ struct snd_vx_ops *ops,
+ int extra_size)
{
- vx_core_t *chip;
+ struct vx_core *chip;
snd_assert(card && hw && ops, return NULL);
@@ -801,8 +785,6 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
strcpy(card->driver, hw->name);
sprintf(card->shortname, "Digigram %s", hw->name);
- snd_card_set_pm_callback(card, snd_vx_suspend, snd_vx_resume, chip);
-
vx_proc_init(chip);
return chip;
@@ -831,7 +813,10 @@ EXPORT_SYMBOL(snd_vx_create);
EXPORT_SYMBOL(snd_vx_setup_firmware);
EXPORT_SYMBOL(snd_vx_free_firmware);
EXPORT_SYMBOL(snd_vx_irq_handler);
-EXPORT_SYMBOL(snd_vx_delay);
EXPORT_SYMBOL(snd_vx_dsp_boot);
EXPORT_SYMBOL(snd_vx_dsp_load);
EXPORT_SYMBOL(snd_vx_load_boot_image);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(snd_vx_suspend);
+EXPORT_SYMBOL(snd_vx_resume);
+#endif
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index c4993b004c42..d837783fb538 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -30,7 +30,7 @@
#ifdef SND_VX_FW_LOADER
-int snd_vx_setup_firmware(vx_core_t *chip)
+int snd_vx_setup_firmware(struct vx_core *chip)
{
static char *fw_files[VX_TYPE_NUMS][4] = {
[VX_TYPE_BOARD] = {
@@ -95,7 +95,7 @@ int snd_vx_setup_firmware(vx_core_t *chip)
}
/* exported */
-void snd_vx_free_firmware(vx_core_t *chip)
+void snd_vx_free_firmware(struct vx_core *chip)
{
#ifdef CONFIG_PM
int i;
@@ -106,17 +106,18 @@ void snd_vx_free_firmware(vx_core_t *chip)
#else /* old style firmware loading */
-static int vx_hwdep_open(snd_hwdep_t *hw, struct file *file)
+static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int vx_hwdep_release(snd_hwdep_t *hw, struct file *file)
+static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_status *info)
{
static char *type_ids[VX_TYPE_NUMS] = {
[VX_TYPE_BOARD] = "vxboard",
@@ -125,7 +126,7 @@ static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
[VX_TYPE_VXPOCKET] = "vxpocket",
[VX_TYPE_VXP440] = "vxp440",
};
- vx_core_t *vx = hw->private_data;
+ struct vx_core *vx = hw->private_data;
snd_assert(type_ids[vx->type], return -EINVAL);
strcpy(info->id, type_ids[vx->type]);
@@ -147,9 +148,10 @@ static void free_fw(const struct firmware *fw)
}
}
-static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+static int vx_hwdep_dsp_load(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image *dsp)
{
- vx_core_t *vx = hw->private_data;
+ struct vx_core *vx = hw->private_data;
int index, err;
struct firmware *fw;
@@ -216,10 +218,10 @@ static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
/* exported */
-int snd_vx_setup_firmware(vx_core_t *chip)
+int snd_vx_setup_firmware(struct vx_core *chip)
{
int err;
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
return err;
@@ -238,7 +240,7 @@ int snd_vx_setup_firmware(vx_core_t *chip)
}
/* exported */
-void snd_vx_free_firmware(vx_core_t *chip)
+void snd_vx_free_firmware(struct vx_core *chip)
{
#ifdef CONFIG_PM
int i;
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 19fc68c23378..8ec2c605d2f0 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -30,7 +30,7 @@
/*
* write a codec data (24bit)
*/
-static void vx_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
+static void vx_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
{
unsigned long flags;
@@ -47,7 +47,7 @@ static void vx_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
/*
* Data type used to access the Codec
*/
-typedef union {
+union vx_codec_data {
u32 l;
#ifdef SNDRV_BIG_ENDIAN
struct w {
@@ -72,7 +72,7 @@ typedef union {
u8 hh;
} b;
#endif
-} vx_codec_data_t;
+};
#define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s))
#define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r))
@@ -85,9 +85,9 @@ typedef union {
* @reg: register index
* @val: data value
*/
-static void vx_set_codec_reg(vx_core_t *chip, int codec, int reg, int val)
+static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val)
{
- vx_codec_data_t data;
+ union vx_codec_data data;
/* DAC control register */
SET_CDC_DATA_INIT(data);
SET_CDC_DATA_REG(data, reg);
@@ -102,7 +102,7 @@ static void vx_set_codec_reg(vx_core_t *chip, int codec, int reg, int val)
* @left: left output level, 0 = mute
* @right: right output level
*/
-static void vx_set_analog_output_level(vx_core_t *chip, int codec, int left, int right)
+static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right)
{
left = chip->hw->output_level_max - left;
right = chip->hw->output_level_max - right;
@@ -126,7 +126,7 @@ static void vx_set_analog_output_level(vx_core_t *chip, int codec, int left, int
#define DAC_ATTEN_MIN 0x08
#define DAC_ATTEN_MAX 0x38
-void vx_toggle_dac_mute(vx_core_t *chip, int mute)
+void vx_toggle_dac_mute(struct vx_core *chip, int mute)
{
unsigned int i;
for (i = 0; i < chip->hw->num_codecs; i++) {
@@ -141,7 +141,7 @@ void vx_toggle_dac_mute(vx_core_t *chip, int mute)
/*
* vx_reset_codec - reset and initialize the codecs
*/
-void vx_reset_codec(vx_core_t *chip, int cold_reset)
+void vx_reset_codec(struct vx_core *chip, int cold_reset)
{
unsigned int i;
int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65;
@@ -175,7 +175,7 @@ void vx_reset_codec(vx_core_t *chip, int cold_reset)
* change the audio input source
* @src: the target source (VX_AUDIO_SRC_XXX)
*/
-static void vx_change_audio_source(vx_core_t *chip, int src)
+static void vx_change_audio_source(struct vx_core *chip, int src)
{
unsigned long flags;
@@ -192,7 +192,7 @@ static void vx_change_audio_source(vx_core_t *chip, int src)
* change the audio source if necessary and possible
* returns 1 if the source is actually changed.
*/
-int vx_sync_audio_source(vx_core_t *chip)
+int vx_sync_audio_source(struct vx_core *chip)
{
if (chip->audio_source_target == chip->audio_source ||
chip->pcm_running)
@@ -217,7 +217,7 @@ struct vx_audio_level {
short monitor_level;
};
-static int vx_adjust_audio_level(vx_core_t *chip, int audio, int capture,
+static int vx_adjust_audio_level(struct vx_core *chip, int audio, int capture,
struct vx_audio_level *info)
{
struct vx_rmh rmh;
@@ -256,7 +256,7 @@ static int vx_adjust_audio_level(vx_core_t *chip, int audio, int capture,
#if 0 // not used
-static int vx_read_audio_level(vx_core_t *chip, int audio, int capture,
+static int vx_read_audio_level(struct vx_core *chip, int audio, int capture,
struct vx_audio_level *info)
{
int err;
@@ -283,7 +283,7 @@ static int vx_read_audio_level(vx_core_t *chip, int audio, int capture,
* set the monitoring level and mute state of the given audio
* no more static, because must be called from vx_pcm to demute monitoring
*/
-int vx_set_monitor_level(vx_core_t *chip, int audio, int level, int active)
+int vx_set_monitor_level(struct vx_core *chip, int audio, int level, int active)
{
struct vx_audio_level info;
@@ -301,7 +301,7 @@ int vx_set_monitor_level(vx_core_t *chip, int audio, int level, int active)
/*
* set the mute status of the given audio
*/
-static int vx_set_audio_switch(vx_core_t *chip, int audio, int active)
+static int vx_set_audio_switch(struct vx_core *chip, int audio, int active)
{
struct vx_audio_level info;
@@ -315,7 +315,7 @@ static int vx_set_audio_switch(vx_core_t *chip, int audio, int active)
/*
* set the mute status of the given audio
*/
-static int vx_set_audio_gain(vx_core_t *chip, int audio, int capture, int level)
+static int vx_set_audio_gain(struct vx_core *chip, int audio, int capture, int level)
{
struct vx_audio_level info;
@@ -329,7 +329,7 @@ static int vx_set_audio_gain(vx_core_t *chip, int audio, int capture, int level)
/*
* reset all audio levels
*/
-static void vx_reset_audio_levels(vx_core_t *chip)
+static void vx_reset_audio_levels(struct vx_core *chip)
{
unsigned int i, c;
struct vx_audio_level info;
@@ -375,7 +375,7 @@ struct vx_vu_meter {
* @capture: 0 = playback, 1 = capture operation
* @info: the array of vx_vu_meter records (size = 2).
*/
-static int vx_get_audio_vu_meter(vx_core_t *chip, int audio, int capture, struct vx_vu_meter *info)
+static int vx_get_audio_vu_meter(struct vx_core *chip, int audio, int capture, struct vx_vu_meter *info)
{
struct vx_rmh rmh;
int i, err;
@@ -413,9 +413,9 @@ static int vx_get_audio_vu_meter(vx_core_t *chip, int audio, int capture, struct
/*
* output level control
*/
-static int vx_output_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_output_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
@@ -423,9 +423,9 @@ static int vx_output_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return 0;
}
-static int vx_output_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_output_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->id.index;
down(&chip->mixer_mutex);
ucontrol->value.integer.value[0] = chip->output_level[codec][0];
@@ -434,9 +434,9 @@ static int vx_output_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static int vx_output_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->id.index;
down(&chip->mixer_mutex);
if (ucontrol->value.integer.value[0] != chip->output_level[codec][0] ||
@@ -453,7 +453,7 @@ static int vx_output_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static snd_kcontrol_new_t vx_control_output_level = {
+static struct snd_kcontrol_new vx_control_output_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.info = vx_output_level_info,
@@ -464,7 +464,7 @@ static snd_kcontrol_new_t vx_control_output_level = {
/*
* audio source select
*/
-static int vx_audio_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_audio_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts_mic[3] = {
"Digital", "Line", "Mic"
@@ -472,7 +472,7 @@ static int vx_audio_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
static char *texts_vx2[2] = {
"Digital", "Analog"
};
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -492,16 +492,16 @@ static int vx_audio_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int vx_audio_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = chip->audio_source_target;
return 0;
}
-static int vx_audio_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mixer_mutex);
if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) {
chip->audio_source_target = ucontrol->value.enumerated.item[0];
@@ -513,7 +513,7 @@ static int vx_audio_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static snd_kcontrol_new_t vx_control_audio_src = {
+static struct snd_kcontrol_new vx_control_audio_src = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = vx_audio_src_info,
@@ -524,7 +524,7 @@ static snd_kcontrol_new_t vx_control_audio_src = {
/*
* clock mode selection
*/
-static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_clock_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {
"Auto", "Internal", "External"
@@ -540,16 +540,16 @@ static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_clock_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = chip->clock_mode;
return 0;
}
-static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mixer_mutex);
if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
chip->clock_mode = ucontrol->value.enumerated.item[0];
@@ -561,7 +561,7 @@ static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static snd_kcontrol_new_t vx_control_clock_mode = {
+static struct snd_kcontrol_new vx_control_clock_mode = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Clock Mode",
.info = vx_clock_mode_info,
@@ -572,7 +572,7 @@ static snd_kcontrol_new_t vx_control_clock_mode = {
/*
* Audio Gain
*/
-static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_audio_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -581,9 +581,9 @@ static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int vx_audio_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
int capture = (kcontrol->private_value >> 8) & 1;
@@ -594,9 +594,9 @@ static int vx_audio_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static int vx_audio_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
int capture = (kcontrol->private_value >> 8) & 1;
@@ -612,9 +612,9 @@ static int vx_audio_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static int vx_audio_monitor_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_monitor_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -624,9 +624,9 @@ static int vx_audio_monitor_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int vx_audio_monitor_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_monitor_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -643,7 +643,7 @@ static int vx_audio_monitor_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int vx_audio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_audio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -652,9 +652,9 @@ static int vx_audio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
return 0;
}
-static int vx_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -664,9 +664,9 @@ static int vx_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int vx_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -681,9 +681,9 @@ static int vx_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int vx_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -693,9 +693,9 @@ static int vx_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static int vx_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
int audio = kcontrol->private_value & 0xff;
down(&chip->mixer_mutex);
@@ -712,28 +712,28 @@ static int vx_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static snd_kcontrol_new_t vx_control_audio_gain = {
+static struct snd_kcontrol_new vx_control_audio_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* name will be filled later */
.info = vx_audio_gain_info,
.get = vx_audio_gain_get,
.put = vx_audio_gain_put
};
-static snd_kcontrol_new_t vx_control_output_switch = {
+static struct snd_kcontrol_new vx_control_output_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.info = vx_audio_sw_info,
.get = vx_audio_sw_get,
.put = vx_audio_sw_put
};
-static snd_kcontrol_new_t vx_control_monitor_gain = {
+static struct snd_kcontrol_new vx_control_monitor_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Volume",
.info = vx_audio_gain_info, /* shared */
.get = vx_audio_monitor_get,
.put = vx_audio_monitor_put
};
-static snd_kcontrol_new_t vx_control_monitor_switch = {
+static struct snd_kcontrol_new vx_control_monitor_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Switch",
.info = vx_audio_sw_info, /* shared */
@@ -745,16 +745,16 @@ static snd_kcontrol_new_t vx_control_monitor_switch = {
/*
* IEC958 status bits
*/
-static int vx_iec958_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int vx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mixer_mutex);
ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff;
@@ -765,7 +765,7 @@ static int vx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro
return 0;
}
-static int vx_iec958_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_iec958_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -774,9 +774,9 @@ static int vx_iec958_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
unsigned int val;
val = (ucontrol->value.iec958.status[0] << 0) |
@@ -794,7 +794,7 @@ static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro
return 0;
}
-static snd_kcontrol_new_t vx_control_iec958_mask = {
+static struct snd_kcontrol_new vx_control_iec958_mask = {
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
@@ -802,7 +802,7 @@ static snd_kcontrol_new_t vx_control_iec958_mask = {
.get = vx_iec958_mask_get,
};
-static snd_kcontrol_new_t vx_control_iec958 = {
+static struct snd_kcontrol_new vx_control_iec958 = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.info = vx_iec958_info,
@@ -818,7 +818,7 @@ static snd_kcontrol_new_t vx_control_iec958 = {
#define METER_MAX 0xff
#define METER_SHIFT 16
-static int vx_vu_meter_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_vu_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -827,9 +827,9 @@ static int vx_vu_meter_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
return 0;
}
-static int vx_vu_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_vu_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
struct vx_vu_meter meter[2];
int audio = kcontrol->private_value & 0xff;
int capture = (kcontrol->private_value >> 8) & 1;
@@ -840,9 +840,9 @@ static int vx_vu_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int vx_peak_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_peak_meter_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
struct vx_vu_meter meter[2];
int audio = kcontrol->private_value & 0xff;
int capture = (kcontrol->private_value >> 8) & 1;
@@ -853,7 +853,7 @@ static int vx_peak_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static int vx_saturation_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_saturation_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -862,9 +862,9 @@ static int vx_saturation_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int vx_saturation_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *chip = snd_kcontrol_chip(kcontrol);
struct vx_vu_meter meter[2];
int audio = kcontrol->private_value & 0xff;
@@ -874,7 +874,7 @@ static int vx_saturation_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static snd_kcontrol_new_t vx_control_vu_meter = {
+static struct snd_kcontrol_new vx_control_vu_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -882,7 +882,7 @@ static snd_kcontrol_new_t vx_control_vu_meter = {
.get = vx_vu_meter_get,
};
-static snd_kcontrol_new_t vx_control_peak_meter = {
+static struct snd_kcontrol_new vx_control_peak_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -890,7 +890,7 @@ static snd_kcontrol_new_t vx_control_peak_meter = {
.get = vx_peak_meter_get,
};
-static snd_kcontrol_new_t vx_control_saturation = {
+static struct snd_kcontrol_new vx_control_saturation = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Saturation",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -904,12 +904,12 @@ static snd_kcontrol_new_t vx_control_saturation = {
*
*/
-int snd_vx_mixer_new(vx_core_t *chip)
+int snd_vx_mixer_new(struct vx_core *chip)
{
unsigned int i, c;
int err;
- snd_kcontrol_new_t temp;
- snd_card_t *card = chip->card;
+ struct snd_kcontrol_new temp;
+ struct snd_card *card = chip->card;
char name[32];
strcpy(card->mixername, card->driver);
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 2b46758fe86f..464109e421d4 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -61,7 +61,8 @@
*/
/* get the physical page pointer on the given offset */
-static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned long offset)
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+ unsigned long offset)
{
void *pageptr = subs->runtime->dma_area + offset;
return vmalloc_to_page(pageptr);
@@ -72,9 +73,9 @@ static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned
* called from hw_params
* NOTE: this may be called not only once per pcm open!
*/
-static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
/* already allocated */
if (runtime->dma_bytes >= size)
@@ -94,9 +95,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
* called from hw_free callback
* NOTE: this may be called not only once per pcm open!
*/
-static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
+static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
vfree(runtime->dma_area);
runtime->dma_area = NULL;
@@ -108,7 +109,8 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
/*
* read three pending pcm bytes via inb()
*/
-static void vx_pcm_read_per_bytes(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
+static void vx_pcm_read_per_bytes(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe)
{
int offset = pipe->hw_ptr;
unsigned char *buf = (unsigned char *)(runtime->dma_area + offset);
@@ -135,7 +137,8 @@ static void vx_pcm_read_per_bytes(vx_core_t *chip, snd_pcm_runtime_t *runtime, v
* @pc_time: the pointer for the PC-time to set
* @dsp_time: the pointer for RMH status time array
*/
-static void vx_set_pcx_time(vx_core_t *chip, pcx_time_t *pc_time, unsigned int *dsp_time)
+static void vx_set_pcx_time(struct vx_core *chip, pcx_time_t *pc_time,
+ unsigned int *dsp_time)
{
dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK;
dsp_time[1] = (unsigned int)(*pc_time) & MASK_DSP_WORD;
@@ -151,7 +154,8 @@ static void vx_set_pcx_time(vx_core_t *chip, pcx_time_t *pc_time, unsigned int *
*
* returns the increase of the command length.
*/
-static int vx_set_differed_time(vx_core_t *chip, struct vx_rmh *rmh, vx_pipe_t *pipe)
+static int vx_set_differed_time(struct vx_core *chip, struct vx_rmh *rmh,
+ struct vx_pipe *pipe)
{
/* Update The length added to the RMH command by the timestamp */
if (! (pipe->differed_type & DC_DIFFERED_DELAY))
@@ -184,7 +188,8 @@ static int vx_set_differed_time(vx_core_t *chip, struct vx_rmh *rmh, vx_pipe_t *
* @pipe: the affected pipe
* @data: format bitmask
*/
-static int vx_set_stream_format(vx_core_t *chip, vx_pipe_t *pipe, unsigned int data)
+static int vx_set_stream_format(struct vx_core *chip, struct vx_pipe *pipe,
+ unsigned int data)
{
struct vx_rmh rmh;
@@ -210,8 +215,8 @@ static int vx_set_stream_format(vx_core_t *chip, vx_pipe_t *pipe, unsigned int d
*
* returns 0 if successful, or a negative error code.
*/
-static int vx_set_format(vx_core_t *chip, vx_pipe_t *pipe,
- snd_pcm_runtime_t *runtime)
+static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe,
+ struct snd_pcm_runtime *runtime)
{
unsigned int header = HEADER_FMT_BASE;
@@ -239,7 +244,7 @@ static int vx_set_format(vx_core_t *chip, vx_pipe_t *pipe,
/*
* set / query the IBL size
*/
-static int vx_set_ibl(vx_core_t *chip, struct vx_ibl_info *info)
+static int vx_set_ibl(struct vx_core *chip, struct vx_ibl_info *info)
{
int err;
struct vx_rmh rmh;
@@ -269,7 +274,7 @@ static int vx_set_ibl(vx_core_t *chip, struct vx_ibl_info *info)
*
* called from trigger callback only
*/
-static int vx_get_pipe_state(vx_core_t *chip, vx_pipe_t *pipe, int *state)
+static int vx_get_pipe_state(struct vx_core *chip, struct vx_pipe *pipe, int *state)
{
int err;
struct vx_rmh rmh;
@@ -294,7 +299,7 @@ static int vx_get_pipe_state(vx_core_t *chip, vx_pipe_t *pipe, int *state)
* you'll need to disconnect the host to get back to the
* normal mode.
*/
-static int vx_query_hbuffer_size(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_query_hbuffer_size(struct vx_core *chip, struct vx_pipe *pipe)
{
int result;
struct vx_rmh rmh;
@@ -318,7 +323,7 @@ static int vx_query_hbuffer_size(vx_core_t *chip, vx_pipe_t *pipe)
*
* called from trigger callback only
*/
-static int vx_pipe_can_start(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_pipe_can_start(struct vx_core *chip, struct vx_pipe *pipe)
{
int err;
struct vx_rmh rmh;
@@ -339,7 +344,7 @@ static int vx_pipe_can_start(vx_core_t *chip, vx_pipe_t *pipe)
* vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
* @pipe: the pipe to be configured
*/
-static int vx_conf_pipe(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_conf_pipe(struct vx_core *chip, struct vx_pipe *pipe)
{
struct vx_rmh rmh;
@@ -353,7 +358,7 @@ static int vx_conf_pipe(vx_core_t *chip, vx_pipe_t *pipe)
/*
* vx_send_irqa - trigger IRQA
*/
-static int vx_send_irqa(vx_core_t *chip)
+static int vx_send_irqa(struct vx_core *chip)
{
struct vx_rmh rmh;
@@ -378,7 +383,7 @@ static int vx_send_irqa(vx_core_t *chip)
* called from trigger callback only
*
*/
-static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
+static int vx_toggle_pipe(struct vx_core *chip, struct vx_pipe *pipe, int state)
{
int err, i, cur_state;
@@ -431,7 +436,7 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
*
* called from trigger callback only
*/
-static int vx_stop_pipe(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_stop_pipe(struct vx_core *chip, struct vx_pipe *pipe)
{
struct vx_rmh rmh;
vx_init_rmh(&rmh, CMD_STOP_PIPE);
@@ -449,12 +454,12 @@ static int vx_stop_pipe(vx_core_t *chip, vx_pipe_t *pipe)
*
* return 0 on success, or a negative error code.
*/
-static int vx_alloc_pipe(vx_core_t *chip, int capture,
+static int vx_alloc_pipe(struct vx_core *chip, int capture,
int audioid, int num_audio,
- vx_pipe_t **pipep)
+ struct vx_pipe **pipep)
{
int err;
- vx_pipe_t *pipe;
+ struct vx_pipe *pipe;
struct vx_rmh rmh;
int data_mode;
@@ -499,7 +504,7 @@ static int vx_alloc_pipe(vx_core_t *chip, int capture,
* vx_free_pipe - release a pipe
* @pipe: pipe to be released
*/
-static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_free_pipe(struct vx_core *chip, struct vx_pipe *pipe)
{
struct vx_rmh rmh;
@@ -517,7 +522,7 @@ static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
*
* called from trigger callback only
*/
-static int vx_start_stream(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_start_stream(struct vx_core *chip, struct vx_pipe *pipe)
{
struct vx_rmh rmh;
@@ -533,7 +538,7 @@ static int vx_start_stream(vx_core_t *chip, vx_pipe_t *pipe)
*
* called from trigger callback only
*/
-static int vx_stop_stream(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_stop_stream(struct vx_core *chip, struct vx_pipe *pipe)
{
struct vx_rmh rmh;
@@ -547,11 +552,12 @@ static int vx_stop_stream(vx_core_t *chip, vx_pipe_t *pipe)
* playback hw information
*/
-static snd_pcm_hardware_t vx_pcm_playback_hw = {
+static struct snd_pcm_hardware 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*/),
- .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
+ .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,
.rate_max = 48000,
@@ -571,11 +577,11 @@ static void vx_pcm_delayed_start(unsigned long arg);
/*
* vx_pcm_playback_open - open callback for playback
*/
-static int vx_pcm_playback_open(snd_pcm_substream_t *subs)
+static int vx_pcm_playback_open(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- vx_pipe_t *pipe = NULL;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct vx_pipe *pipe = NULL;
unsigned int audio;
int err;
@@ -615,10 +621,10 @@ static int vx_pcm_playback_open(snd_pcm_substream_t *subs)
/*
* vx_pcm_playback_close - close callback for playback
*/
-static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
+static int vx_pcm_playback_close(struct snd_pcm_substream *subs)
{
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- vx_pipe_t *pipe;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct vx_pipe *pipe;
if (! subs->runtime->private_data)
return -EINVAL;
@@ -641,7 +647,7 @@ static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
*
* NB: call with a certain lock.
*/
-static int vx_notify_end_of_buffer(vx_core_t *chip, vx_pipe_t *pipe)
+static int vx_notify_end_of_buffer(struct vx_core *chip, struct vx_pipe *pipe)
{
int err;
struct vx_rmh rmh; /* use a temporary rmh here */
@@ -669,7 +675,9 @@ static int vx_notify_end_of_buffer(vx_core_t *chip, vx_pipe_t *pipe)
*
* return 0 if ok.
*/
-static int vx_pcm_playback_transfer_chunk(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe, int size)
+static int vx_pcm_playback_transfer_chunk(struct vx_core *chip,
+ struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int size)
{
int space, err = 0;
@@ -705,7 +713,9 @@ static int vx_pcm_playback_transfer_chunk(vx_core_t *chip, snd_pcm_runtime_t *ru
* so that the caller can check the total transferred size later
* (to call snd_pcm_period_elapsed).
*/
-static int vx_update_pipe_position(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
+static int vx_update_pipe_position(struct vx_core *chip,
+ struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe)
{
struct vx_rmh rmh;
int err, update;
@@ -731,10 +741,12 @@ static int vx_update_pipe_position(vx_core_t *chip, snd_pcm_runtime_t *runtime,
* transfer the pending playback buffer data to DSP
* called from interrupt handler
*/
-static void vx_pcm_playback_transfer(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe, int nchunks)
+static void vx_pcm_playback_transfer(struct vx_core *chip,
+ struct snd_pcm_substream *subs,
+ struct vx_pipe *pipe, int nchunks)
{
int i, err;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
return;
@@ -749,10 +761,12 @@ static void vx_pcm_playback_transfer(vx_core_t *chip, snd_pcm_substream_t *subs,
* update the playback position and call snd_pcm_period_elapsed() if necessary
* called from interrupt handler
*/
-static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
+static void vx_pcm_playback_update(struct vx_core *chip,
+ struct snd_pcm_substream *subs,
+ struct vx_pipe *pipe)
{
int err;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0)
@@ -771,9 +785,9 @@ static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, v
*/
static void vx_pcm_delayed_start(unsigned long arg)
{
- snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
- vx_core_t *chip = subs->pcm->private_data;
- vx_pipe_t *pipe = subs->runtime->private_data;
+ struct snd_pcm_substream *subs = (struct snd_pcm_substream *)arg;
+ struct vx_core *chip = subs->pcm->private_data;
+ struct vx_pipe *pipe = subs->runtime->private_data;
int err;
/* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
@@ -792,10 +806,10 @@ static void vx_pcm_delayed_start(unsigned long arg)
/*
* vx_pcm_playback_trigger - trigger callback for playback
*/
-static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
+static int vx_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
{
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- vx_pipe_t *pipe = subs->runtime->private_data;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct vx_pipe *pipe = subs->runtime->private_data;
int err;
if (chip->chip_status & VX_STAT_IS_STALE)
@@ -839,18 +853,18 @@ static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
/*
* vx_pcm_playback_pointer - pointer callback for playback
*/
-static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- vx_pipe_t *pipe = runtime->private_data;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct vx_pipe *pipe = runtime->private_data;
return pipe->position;
}
/*
* vx_pcm_hw_params - hw_params callback for playback and capture
*/
-static int vx_pcm_hw_params(snd_pcm_substream_t *subs,
- snd_pcm_hw_params_t *hw_params)
+static int vx_pcm_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params));
}
@@ -858,7 +872,7 @@ static int vx_pcm_hw_params(snd_pcm_substream_t *subs,
/*
* vx_pcm_hw_free - hw_free callback for playback and capture
*/
-static int vx_pcm_hw_free(snd_pcm_substream_t *subs)
+static int vx_pcm_hw_free(struct snd_pcm_substream *subs)
{
return snd_pcm_free_vmalloc_buffer(subs);
}
@@ -866,11 +880,11 @@ static int vx_pcm_hw_free(snd_pcm_substream_t *subs)
/*
* vx_pcm_prepare - prepare callback for playback and capture
*/
-static int vx_pcm_prepare(snd_pcm_substream_t *subs)
+static int vx_pcm_prepare(struct snd_pcm_substream *subs)
{
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
- vx_pipe_t *pipe = runtime->private_data;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct vx_pipe *pipe = runtime->private_data;
int err, data_mode;
// int max_size, nchunks;
@@ -897,7 +911,8 @@ static int vx_pcm_prepare(snd_pcm_substream_t *subs)
}
if (chip->pcm_running && chip->freq != runtime->rate) {
- snd_printk(KERN_ERR "vx: cannot set different clock %d from the current %d\n", runtime->rate, chip->freq);
+ snd_printk(KERN_ERR "vx: cannot set different clock %d "
+ "from the current %d\n", runtime->rate, chip->freq);
return -EINVAL;
}
vx_set_clock(chip, runtime->rate);
@@ -930,7 +945,7 @@ static int vx_pcm_prepare(snd_pcm_substream_t *subs)
/*
* operators for PCM playback
*/
-static snd_pcm_ops_t vx_pcm_playback_ops = {
+static struct snd_pcm_ops vx_pcm_playback_ops = {
.open = vx_pcm_playback_open,
.close = vx_pcm_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -947,11 +962,12 @@ static snd_pcm_ops_t vx_pcm_playback_ops = {
* playback hw information
*/
-static snd_pcm_hardware_t vx_pcm_capture_hw = {
+static struct snd_pcm_hardware 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*/),
- .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
+ .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,
.rate_max = 48000,
@@ -969,12 +985,12 @@ static snd_pcm_hardware_t vx_pcm_capture_hw = {
/*
* vx_pcm_capture_open - open callback for capture
*/
-static int vx_pcm_capture_open(snd_pcm_substream_t *subs)
+static int vx_pcm_capture_open(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- vx_pipe_t *pipe;
- vx_pipe_t *pipe_out_monitoring = NULL;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct vx_pipe *pipe;
+ struct vx_pipe *pipe_out_monitoring = NULL;
unsigned int audio;
int err;
@@ -1005,9 +1021,11 @@ static int vx_pcm_capture_open(snd_pcm_substream_t *subs)
if an output pipe is available, it's audios still may need to be
unmuted. hence we'll have to call a mixer entry point.
*/
- vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], chip->audio_monitor_active[audio]);
+ vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
+ chip->audio_monitor_active[audio]);
/* assuming stereo */
- vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], chip->audio_monitor_active[audio+1]);
+ vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
+ chip->audio_monitor_active[audio+1]);
}
pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */
@@ -1026,11 +1044,11 @@ static int vx_pcm_capture_open(snd_pcm_substream_t *subs)
/*
* vx_pcm_capture_close - close callback for capture
*/
-static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
+static int vx_pcm_capture_close(struct snd_pcm_substream *subs)
{
- vx_core_t *chip = snd_pcm_substream_chip(subs);
- vx_pipe_t *pipe;
- vx_pipe_t *pipe_out_monitoring;
+ struct vx_core *chip = snd_pcm_substream_chip(subs);
+ struct vx_pipe *pipe;
+ struct vx_pipe *pipe_out_monitoring;
if (! subs->runtime->private_data)
return -EINVAL;
@@ -1062,10 +1080,11 @@ static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
/*
* vx_pcm_capture_update - update the capture buffer
*/
-static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
+static void vx_pcm_capture_update(struct vx_core *chip, struct snd_pcm_substream *subs,
+ struct vx_pipe *pipe)
{
int size, space, count;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
return;
@@ -1135,17 +1154,17 @@ static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx
/*
* vx_pcm_capture_pointer - pointer callback for capture
*/
-static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- vx_pipe_t *pipe = runtime->private_data;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct vx_pipe *pipe = runtime->private_data;
return bytes_to_frames(runtime, pipe->hw_ptr);
}
/*
* operators for PCM capture
*/
-static snd_pcm_ops_t vx_pcm_capture_ops = {
+static struct snd_pcm_ops vx_pcm_capture_ops = {
.open = vx_pcm_capture_open,
.close = vx_pcm_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1161,10 +1180,10 @@ static snd_pcm_ops_t vx_pcm_capture_ops = {
/*
* interrupt handler for pcm streams
*/
-void vx_pcm_update_intr(vx_core_t *chip, unsigned int events)
+void vx_pcm_update_intr(struct vx_core *chip, unsigned int events)
{
unsigned int i;
- vx_pipe_t *pipe;
+ struct vx_pipe *pipe;
#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)
@@ -1218,7 +1237,7 @@ void vx_pcm_update_intr(vx_core_t *chip, unsigned int events)
/*
* vx_init_audio_io - check the availabe audio i/o and allocate pipe arrays
*/
-static int vx_init_audio_io(vx_core_t *chip)
+static int vx_init_audio_io(struct vx_core *chip)
{
struct vx_rmh rmh;
int preferred;
@@ -1234,19 +1253,20 @@ static int vx_init_audio_io(vx_core_t *chip)
chip->audio_info = rmh.Stat[1];
/* allocate pipes */
- chip->playback_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_outs, GFP_KERNEL);
- chip->capture_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_ins, GFP_KERNEL);
+ chip->playback_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_outs, GFP_KERNEL);
+ chip->capture_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_ins, GFP_KERNEL);
if (! chip->playback_pipes || ! chip->capture_pipes)
return -ENOMEM;
- memset(chip->playback_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_outs);
- memset(chip->capture_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_ins);
+ memset(chip->playback_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_outs);
+ memset(chip->capture_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_ins);
preferred = chip->ibl.size;
chip->ibl.size = 0;
vx_set_ibl(chip, &chip->ibl); /* query the info */
if (preferred > 0) {
- chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / chip->ibl.granularity) * chip->ibl.granularity;
+ chip->ibl.size = ((preferred + chip->ibl.granularity - 1) /
+ chip->ibl.granularity) * chip->ibl.granularity;
if (chip->ibl.size > chip->ibl.max_size)
chip->ibl.size = chip->ibl.max_size;
} else
@@ -1260,9 +1280,9 @@ static int vx_init_audio_io(vx_core_t *chip)
/*
* free callback for pcm
*/
-static void snd_vx_pcm_free(snd_pcm_t *pcm)
+static void snd_vx_pcm_free(struct snd_pcm *pcm)
{
- vx_core_t *chip = pcm->private_data;
+ struct vx_core *chip = pcm->private_data;
chip->pcm[pcm->device] = NULL;
kfree(chip->playback_pipes);
chip->playback_pipes = NULL;
@@ -1273,9 +1293,9 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm)
/*
* snd_vx_pcm_new - create and initialize a pcm
*/
-int snd_vx_pcm_new(vx_core_t *chip)
+int snd_vx_pcm_new(struct vx_core *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
unsigned int i;
int err;
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
index 4fc38bde34f4..7400306b7f28 100644
--- a/sound/drivers/vx/vx_uer.c
+++ b/sound/drivers/vx/vx_uer.c
@@ -31,7 +31,7 @@
* vx_modify_board_clock - tell the board that its clock has been modified
* @sync: DSP needs to resynchronize its FIFO
*/
-static int vx_modify_board_clock(vx_core_t *chip, int sync)
+static int vx_modify_board_clock(struct vx_core *chip, int sync)
{
struct vx_rmh rmh;
@@ -45,7 +45,7 @@ static int vx_modify_board_clock(vx_core_t *chip, int sync)
/*
* vx_modify_board_inputs - resync audio inputs
*/
-static int vx_modify_board_inputs(vx_core_t *chip)
+static int vx_modify_board_inputs(struct vx_core *chip)
{
struct vx_rmh rmh;
@@ -59,7 +59,7 @@ static int vx_modify_board_inputs(vx_core_t *chip)
* @index: the bit index
* returns 0 or 1.
*/
-static int vx_read_one_cbit(vx_core_t *chip, int index)
+static int vx_read_one_cbit(struct vx_core *chip, int index)
{
unsigned long flags;
int val;
@@ -82,7 +82,7 @@ static int vx_read_one_cbit(vx_core_t *chip, int index)
* @index: the bit index
* @val: bit value, 0 or 1
*/
-static void vx_write_one_cbit(vx_core_t *chip, int index, int val)
+static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
{
unsigned long flags;
val = !!val; /* 0 or 1 */
@@ -104,7 +104,7 @@ static void vx_write_one_cbit(vx_core_t *chip, int index, int val)
* returns the frequency of UER, or 0 if not sync,
* or a negative error code.
*/
-static int vx_read_uer_status(vx_core_t *chip, int *mode)
+static int vx_read_uer_status(struct vx_core *chip, int *mode)
{
int val, freq;
@@ -160,7 +160,7 @@ static int vx_read_uer_status(vx_core_t *chip, int *mode)
* default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF
*/
-static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
+static int vx_calc_clock_from_freq(struct vx_core *chip, int freq)
{
int hexfreq;
@@ -187,7 +187,7 @@ static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
* vx_change_clock_source - change the clock source
* @source: the new source
*/
-static void vx_change_clock_source(vx_core_t *chip, int source)
+static void vx_change_clock_source(struct vx_core *chip, int source)
{
unsigned long flags;
@@ -205,7 +205,7 @@ static void vx_change_clock_source(vx_core_t *chip, int source)
/*
* set the internal clock
*/
-void vx_set_internal_clock(vx_core_t *chip, unsigned int freq)
+void vx_set_internal_clock(struct vx_core *chip, unsigned int freq)
{
int clock;
unsigned long flags;
@@ -228,7 +228,7 @@ void vx_set_internal_clock(vx_core_t *chip, unsigned int freq)
* set the iec958 status bits
* @bits: 32-bit status bits
*/
-void vx_set_iec958_status(vx_core_t *chip, unsigned int bits)
+void vx_set_iec958_status(struct vx_core *chip, unsigned int bits)
{
int i;
@@ -243,7 +243,7 @@ void vx_set_iec958_status(vx_core_t *chip, unsigned int bits)
/*
* vx_set_clock - change the clock and audio source if necessary
*/
-int vx_set_clock(vx_core_t *chip, unsigned int freq)
+int vx_set_clock(struct vx_core *chip, unsigned int freq)
{
int src_changed = 0;
@@ -285,7 +285,7 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq)
/*
* vx_change_frequency - called from interrupt handler
*/
-int vx_change_frequency(vx_core_t *chip)
+int vx_change_frequency(struct vx_core *chip)
{
int freq;
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 1a05cfbdc7c6..9deba80a587c 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -30,7 +30,7 @@
#include <sound/cs8427.h>
#include <sound/asoundef.h>
-static void snd_cs8427_reset(snd_i2c_device_t *cs8427);
+static void snd_cs8427_reset(struct snd_i2c_device *cs8427);
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
@@ -38,22 +38,22 @@ MODULE_LICENSE("GPL");
#define CS8427_ADDR (0x20>>1) /* fixed address */
-typedef struct {
- snd_pcm_substream_t *substream;
+struct cs8427_stream {
+ struct snd_pcm_substream *substream;
char hw_status[24]; /* hardware status */
char def_status[24]; /* default status */
char pcm_status[24]; /* PCM private status */
char hw_udata[32];
- snd_kcontrol_t *pcm_ctl;
-} cs8427_stream_t;
+ struct snd_kcontrol *pcm_ctl;
+};
-typedef struct {
+struct cs8427 {
unsigned char regmap[0x14]; /* map of first 1 + 13 registers */
unsigned int rate;
unsigned int reset_timeout;
- cs8427_stream_t playback;
- cs8427_stream_t capture;
-} cs8427_t;
+ struct cs8427_stream playback;
+ struct cs8427_stream capture;
+};
static unsigned char swapbits(unsigned char val)
{
@@ -67,7 +67,8 @@ static unsigned char swapbits(unsigned char val)
return res;
}
-int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned char val)
+int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
+ unsigned char val)
{
int err;
unsigned char buf[2];
@@ -81,7 +82,7 @@ int snd_cs8427_reg_write(snd_i2c_device_t *device, unsigned char reg, unsigned c
return 0;
}
-static int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
+static int snd_cs8427_reg_read(struct snd_i2c_device *device, unsigned char reg)
{
int err;
unsigned char buf;
@@ -97,28 +98,29 @@ static int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
return buf;
}
-static int snd_cs8427_select_corudata(snd_i2c_device_t *device, int udata)
+static int snd_cs8427_select_corudata(struct snd_i2c_device *device, int udata)
{
- cs8427_t *chip = device->private_data;
+ struct cs8427 *chip = device->private_data;
int err;
udata = udata ? CS8427_BSEL : 0;
if (udata != (chip->regmap[CS8427_REG_CSDATABUF] & udata)) {
chip->regmap[CS8427_REG_CSDATABUF] &= ~CS8427_BSEL;
chip->regmap[CS8427_REG_CSDATABUF] |= udata;
- err = snd_cs8427_reg_write(device, CS8427_REG_CSDATABUF, chip->regmap[CS8427_REG_CSDATABUF]);
+ err = snd_cs8427_reg_write(device, CS8427_REG_CSDATABUF,
+ chip->regmap[CS8427_REG_CSDATABUF]);
if (err < 0)
return err;
}
return 0;
}
-static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
+static int snd_cs8427_send_corudata(struct snd_i2c_device *device,
int udata,
unsigned char *ndata,
int count)
{
- cs8427_t *chip = device->private_data;
+ struct cs8427 *chip = device->private_data;
char *hw_data = udata ? chip->playback.hw_udata : chip->playback.hw_status;
char data[32];
int err, idx;
@@ -133,7 +135,8 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
if (memcmp(hw_data, data, count) == 0) {
chip->regmap[CS8427_REG_UDATABUF] &= ~CS8427_UBMMASK;
chip->regmap[CS8427_REG_UDATABUF] |= CS8427_UBMZEROS | CS8427_EFTUI;
- if ((err = snd_cs8427_reg_write(device, CS8427_REG_UDATABUF, chip->regmap[CS8427_REG_UDATABUF])) < 0)
+ if ((err = snd_cs8427_reg_write(device, CS8427_REG_UDATABUF,
+ chip->regmap[CS8427_REG_UDATABUF])) < 0)
return err;
return 0;
}
@@ -146,15 +149,15 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
return 1;
}
-static void snd_cs8427_free(snd_i2c_device_t *device)
+static void snd_cs8427_free(struct snd_i2c_device *device)
{
kfree(device->private_data);
}
-int snd_cs8427_create(snd_i2c_bus_t *bus,
+int snd_cs8427_create(struct snd_i2c_bus *bus,
unsigned char addr,
unsigned int reset_timeout,
- snd_i2c_device_t **r_cs8427)
+ struct snd_i2c_device **r_cs8427)
{
static unsigned char initvals1[] = {
CS8427_REG_CONTROL1 | CS8427_REG_AUTOINC,
@@ -194,11 +197,12 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
CS8427_UD | CS8427_EFTUI | CS8427_DETUI,
};
int err;
- cs8427_t *chip;
- snd_i2c_device_t *device;
+ struct cs8427 *chip;
+ struct snd_i2c_device *device;
unsigned char buf[24];
- if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
+ if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7),
+ &device)) < 0)
return err;
chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
@@ -208,9 +212,13 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
device->private_free = snd_cs8427_free;
snd_i2c_lock(bus);
- if ((err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER)) != CS8427_VER8427A) {
+ if ((err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER)) !=
+ CS8427_VER8427A) {
snd_i2c_unlock(bus);
- snd_printk(KERN_ERR "unable to find CS8427 signature (expected 0x%x, read 0x%x), initialization is not completed\n", CS8427_VER8427A, err);
+ snd_printk(KERN_ERR "unable to find CS8427 signature "
+ "(expected 0x%x, read 0x%x),\n",
+ CS8427_VER8427A, err);
+ snd_printk(KERN_ERR " initialization is not completed\n");
return -EFAULT;
}
/* turn off run bit while making changes to configuration */
@@ -279,9 +287,9 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
* put back AES3INPUT. This workaround is described in latest
* CS8427 datasheet, otherwise TXDSERIAL will not work.
*/
-static void snd_cs8427_reset(snd_i2c_device_t *cs8427)
+static void snd_cs8427_reset(struct snd_i2c_device *cs8427)
{
- cs8427_t *chip;
+ struct cs8427 *chip;
unsigned long end_time;
int data;
@@ -289,10 +297,12 @@ static void snd_cs8427_reset(snd_i2c_device_t *cs8427)
chip = cs8427->private_data;
snd_i2c_lock(cs8427->bus);
chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK);
- snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
+ snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
+ chip->regmap[CS8427_REG_CLOCKSOURCE]);
udelay(200);
chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RUN | CS8427_RXDILRCK;
- snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
+ snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
+ chip->regmap[CS8427_REG_CLOCKSOURCE]);
udelay(200);
snd_i2c_unlock(cs8427->bus);
end_time = jiffies + chip->reset_timeout;
@@ -307,12 +317,13 @@ static void snd_cs8427_reset(snd_i2c_device_t *cs8427)
snd_i2c_lock(cs8427->bus);
chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~CS8427_RXDMASK;
chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RXDAES3INPUT;
- snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
+ snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
+ chip->regmap[CS8427_REG_CLOCKSOURCE]);
snd_i2c_unlock(cs8427->bus);
}
-static int snd_cs8427_in_status_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cs8427_in_status_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -321,10 +332,10 @@ static int snd_cs8427_in_status_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs8427_in_status_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs8427_in_status_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
+ struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
int data;
snd_i2c_lock(device->bus);
@@ -336,18 +347,18 @@ static int snd_cs8427_in_status_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs8427_qsubcode_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cs8427_qsubcode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
uinfo->count = 10;
return 0;
}
-static int snd_cs8427_qsubcode_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs8427_qsubcode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
+ struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
unsigned char reg = CS8427_REG_QSUBCODE;
int err;
@@ -366,18 +377,18 @@ static int snd_cs8427_qsubcode_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs8427_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs8427_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cs8427_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs8427_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
- cs8427_t *chip = device->private_data;
+ struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
+ struct cs8427 *chip = device->private_data;
snd_i2c_lock(device->bus);
memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24);
@@ -385,13 +396,15 @@ static int snd_cs8427_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs8427_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs8427_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
- cs8427_t *chip = device->private_data;
- unsigned char *status = kcontrol->private_value ? chip->playback.pcm_status : chip->playback.def_status;
- snd_pcm_runtime_t *runtime = chip->playback.substream ? chip->playback.substream->runtime : NULL;
+ struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
+ struct cs8427 *chip = device->private_data;
+ unsigned char *status = kcontrol->private_value ?
+ chip->playback.pcm_status : chip->playback.def_status;
+ struct snd_pcm_runtime *runtime = chip->playback.substream ?
+ chip->playback.substream->runtime : NULL;
int err, change;
snd_i2c_lock(device->bus);
@@ -406,21 +419,22 @@ static int snd_cs8427_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static int snd_cs8427_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs8427_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cs8427_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs8427_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
memset(ucontrol->value.iec958.status, 0xff, 24);
return 0;
}
-static snd_kcontrol_new_t snd_cs8427_iec958_controls[] = {
+static struct snd_kcontrol_new snd_cs8427_iec958_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.info = snd_cs8427_in_status_info,
@@ -469,12 +483,12 @@ static snd_kcontrol_new_t snd_cs8427_iec958_controls[] = {
.get = snd_cs8427_qsubcode_get
}};
-int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427,
- snd_pcm_substream_t *play_substream,
- snd_pcm_substream_t *cap_substream)
+int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
+ struct snd_pcm_substream *play_substream,
+ struct snd_pcm_substream *cap_substream)
{
- cs8427_t *chip = cs8427->private_data;
- snd_kcontrol_t *kctl;
+ struct cs8427 *chip = cs8427->private_data;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -498,9 +512,9 @@ int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427,
return 0;
}
-int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active)
+int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active)
{
- cs8427_t *chip;
+ struct cs8427 *chip;
snd_assert(cs8427, return -ENXIO);
chip = cs8427->private_data;
@@ -512,9 +526,9 @@ int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active)
return 0;
}
-int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate)
+int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate)
{
- cs8427_t *chip;
+ struct cs8427 *chip;
char *status;
int err, reset;
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index e4e505b9d88b..c4e1f2c23ced 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -32,20 +32,23 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Generic i2c interface for ALSA");
MODULE_LICENSE("GPL");
-static int snd_i2c_bit_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count);
-static int snd_i2c_bit_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count);
-static int snd_i2c_bit_probeaddr(snd_i2c_bus_t *bus, unsigned short addr);
-
-static snd_i2c_ops_t snd_i2c_bit_ops = {
+static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
+ unsigned char *bytes, int count);
+static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
+ unsigned char *bytes, int count);
+static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus,
+ unsigned short addr);
+
+static struct snd_i2c_ops snd_i2c_bit_ops = {
.sendbytes = snd_i2c_bit_sendbytes,
.readbytes = snd_i2c_bit_readbytes,
.probeaddr = snd_i2c_bit_probeaddr,
};
-static int snd_i2c_bus_free(snd_i2c_bus_t *bus)
+static int snd_i2c_bus_free(struct snd_i2c_bus *bus)
{
- snd_i2c_bus_t *slave;
- snd_i2c_device_t *device;
+ struct snd_i2c_bus *slave;
+ struct snd_i2c_device *device;
snd_assert(bus != NULL, return -EINVAL);
while (!list_empty(&bus->devices)) {
@@ -66,17 +69,18 @@ static int snd_i2c_bus_free(snd_i2c_bus_t *bus)
return 0;
}
-static int snd_i2c_bus_dev_free(snd_device_t *device)
+static int snd_i2c_bus_dev_free(struct snd_device *device)
{
- snd_i2c_bus_t *bus = device->device_data;
+ struct snd_i2c_bus *bus = device->device_data;
return snd_i2c_bus_free(bus);
}
-int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master, snd_i2c_bus_t **ri2c)
+int snd_i2c_bus_create(struct snd_card *card, const char *name,
+ struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c)
{
- snd_i2c_bus_t *bus;
+ struct snd_i2c_bus *bus;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_i2c_bus_dev_free,
};
@@ -102,9 +106,10 @@ int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master
return 0;
}
-int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char addr, snd_i2c_device_t **rdevice)
+int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
+ unsigned char addr, struct snd_i2c_device **rdevice)
{
- snd_i2c_device_t *device;
+ struct snd_i2c_device *device;
*rdevice = NULL;
snd_assert(bus != NULL, return -EINVAL);
@@ -119,7 +124,7 @@ int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char ad
return 0;
}
-int snd_i2c_device_free(snd_i2c_device_t *device)
+int snd_i2c_device_free(struct snd_i2c_device *device)
{
if (device->bus)
list_del(&device->list);
@@ -129,18 +134,18 @@ int snd_i2c_device_free(snd_i2c_device_t *device)
return 0;
}
-int snd_i2c_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
{
return device->bus->ops->sendbytes(device, bytes, count);
}
-int snd_i2c_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
{
return device->bus->ops->readbytes(device, bytes, count);
}
-int snd_i2c_probeaddr(snd_i2c_bus_t *bus, unsigned short addr)
+int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
{
return bus->ops->probeaddr(bus, addr);
}
@@ -149,31 +154,31 @@ int snd_i2c_probeaddr(snd_i2c_bus_t *bus, unsigned short addr)
* bit-operations
*/
-static inline void snd_i2c_bit_hw_start(snd_i2c_bus_t *bus)
+static inline void snd_i2c_bit_hw_start(struct snd_i2c_bus *bus)
{
if (bus->hw_ops.bit->start)
bus->hw_ops.bit->start(bus);
}
-static inline void snd_i2c_bit_hw_stop(snd_i2c_bus_t *bus)
+static inline void snd_i2c_bit_hw_stop(struct snd_i2c_bus *bus)
{
if (bus->hw_ops.bit->stop)
bus->hw_ops.bit->stop(bus);
}
-static void snd_i2c_bit_direction(snd_i2c_bus_t *bus, int clock, int data)
+static void snd_i2c_bit_direction(struct snd_i2c_bus *bus, int clock, int data)
{
if (bus->hw_ops.bit->direction)
bus->hw_ops.bit->direction(bus, clock, data);
}
-static void snd_i2c_bit_set(snd_i2c_bus_t *bus, int clock, int data)
+static void snd_i2c_bit_set(struct snd_i2c_bus *bus, int clock, int data)
{
bus->hw_ops.bit->setlines(bus, clock, data);
}
#if 0
-static int snd_i2c_bit_clock(snd_i2c_bus_t *bus)
+static int snd_i2c_bit_clock(struct snd_i2c_bus *bus)
{
if (bus->hw_ops.bit->getclock)
return bus->hw_ops.bit->getclock(bus);
@@ -181,12 +186,12 @@ static int snd_i2c_bit_clock(snd_i2c_bus_t *bus)
}
#endif
-static int snd_i2c_bit_data(snd_i2c_bus_t *bus, int ack)
+static int snd_i2c_bit_data(struct snd_i2c_bus *bus, int ack)
{
return bus->hw_ops.bit->getdata(bus, ack);
}
-static void snd_i2c_bit_start(snd_i2c_bus_t *bus)
+static void snd_i2c_bit_start(struct snd_i2c_bus *bus)
{
snd_i2c_bit_hw_start(bus);
snd_i2c_bit_direction(bus, 1, 1); /* SCL - wr, SDA - wr */
@@ -195,7 +200,7 @@ static void snd_i2c_bit_start(snd_i2c_bus_t *bus)
snd_i2c_bit_set(bus, 0, 0);
}
-static void snd_i2c_bit_stop(snd_i2c_bus_t *bus)
+static void snd_i2c_bit_stop(struct snd_i2c_bus *bus)
{
snd_i2c_bit_set(bus, 0, 0);
snd_i2c_bit_set(bus, 1, 0);
@@ -203,14 +208,14 @@ static void snd_i2c_bit_stop(snd_i2c_bus_t *bus)
snd_i2c_bit_hw_stop(bus);
}
-static void snd_i2c_bit_send(snd_i2c_bus_t *bus, int data)
+static void snd_i2c_bit_send(struct snd_i2c_bus *bus, int data)
{
snd_i2c_bit_set(bus, 0, data);
snd_i2c_bit_set(bus, 1, data);
snd_i2c_bit_set(bus, 0, data);
}
-static int snd_i2c_bit_ack(snd_i2c_bus_t *bus)
+static int snd_i2c_bit_ack(struct snd_i2c_bus *bus)
{
int ack;
@@ -223,7 +228,7 @@ static int snd_i2c_bit_ack(snd_i2c_bus_t *bus)
return ack ? -EIO : 0;
}
-static int snd_i2c_bit_sendbyte(snd_i2c_bus_t *bus, unsigned char data)
+static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data)
{
int i, err;
@@ -234,7 +239,7 @@ static int snd_i2c_bit_sendbyte(snd_i2c_bus_t *bus, unsigned char data)
return 0;
}
-static int snd_i2c_bit_readbyte(snd_i2c_bus_t *bus, int last)
+static int snd_i2c_bit_readbyte(struct snd_i2c_bus *bus, int last)
{
int i;
unsigned char data = 0;
@@ -252,9 +257,10 @@ static int snd_i2c_bit_readbyte(snd_i2c_bus_t *bus, int last)
return data;
}
-static int snd_i2c_bit_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
+ unsigned char *bytes, int count)
{
- snd_i2c_bus_t *bus = device->bus;
+ struct snd_i2c_bus *bus = device->bus;
int err, res = 0;
if (device->flags & SND_I2C_DEVICE_ADDRTEN)
@@ -275,9 +281,10 @@ static int snd_i2c_bit_sendbytes(snd_i2c_device_t *device, unsigned char *bytes,
return res;
}
-static int snd_i2c_bit_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
+ unsigned char *bytes, int count)
{
- snd_i2c_bus_t *bus = device->bus;
+ struct snd_i2c_bus *bus = device->bus;
int err, res = 0;
if (device->flags & SND_I2C_DEVICE_ADDRTEN)
@@ -299,7 +306,7 @@ static int snd_i2c_bit_readbytes(snd_i2c_device_t *device, unsigned char *bytes,
return res;
}
-static int snd_i2c_bit_probeaddr(snd_i2c_bus_t *bus, unsigned short addr)
+static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
{
int err;
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 103a7dcd0dde..746500e06950 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.16 2005/09/09 13:22:34 tiwai Exp $ */
+/* $Id: uda1341.c,v 1.18 2005/11/17 14:17:21 tiwai Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
@@ -56,6 +56,33 @@
/* }}} */
+
+static const char *peak_names[] = {
+ "before",
+ "after",
+};
+
+static const char *filter_names[] = {
+ "flat",
+ "min",
+ "min",
+ "max",
+};
+
+static const char *mixer_names[] = {
+ "double differential",
+ "input channel 1 (line in)",
+ "input channel 2 (microphone)",
+ "digital mixer",
+};
+
+static const char *deemp_names[] = {
+ "none",
+ "32 kHz",
+ "44.1 kHz",
+ "48 kHz",
+};
+
enum uda1341_regs_names {
stat0,
stat1,
@@ -73,7 +100,7 @@ enum uda1341_regs_names {
uda1341_reg_last,
};
-const char *uda1341_reg_names[] = {
+static const char *uda1341_reg_names[] = {
"stat 0 ",
"stat 1 ",
"data 00",
@@ -89,7 +116,7 @@ const char *uda1341_reg_names[] = {
"ext 6",
};
-const int uda1341_enum_items[] = {
+static const int uda1341_enum_items[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, //peak - before/after
4, //deemp - none/32/44.1/48
@@ -100,7 +127,7 @@ const int uda1341_enum_items[] = {
0, 0, 0, 0, 0,
};
-const char ** uda1341_enum_names[] = {
+static const char ** uda1341_enum_names[] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
peak_names, //peak - before/after
deemp_names, //deemp - none/32/44.1/48
@@ -113,15 +140,13 @@ const char ** uda1341_enum_names[] = {
typedef int uda1341_cfg[CMD_LAST];
-typedef struct uda1341 uda1341_t;
-
struct uda1341 {
int (*write) (struct l3_client *uda1341, unsigned short reg, unsigned short val);
int (*read) (struct l3_client *uda1341, unsigned short reg);
unsigned char regs[uda1341_reg_last];
int active;
spinlock_t reg_lock;
- snd_card_t *card;
+ struct snd_card *card;
uda1341_cfg cfg;
#ifdef CONFIG_PM
unsigned char suspend_regs[uda1341_reg_last];
@@ -129,11 +154,9 @@ struct uda1341 {
#endif
};
-//hack for ALSA magic casting
-typedef struct l3_client l3_client_t;
-
/* transfer 8bit integer into string with binary representation */
-void int2str_bin8(uint8_t val, char *buf){
+static void int2str_bin8(uint8_t val, char *buf)
+{
const int size = sizeof(val) * 8;
int i;
@@ -146,7 +169,7 @@ void int2str_bin8(uint8_t val, char *buf){
/* {{{ HW manipulation routines */
-int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val)
+static int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned short val)
{
struct uda1341 *uda = clnt->driver_data;
unsigned char buf[2] = { 0xc0, 0xe0 }; // for EXT addressing
@@ -171,7 +194,7 @@ int snd_uda1341_codec_write(struct l3_client *clnt, unsigned short reg, unsigned
return err;
}
-int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg)
+static int snd_uda1341_codec_read(struct l3_client *clnt, unsigned short reg)
{
unsigned char val;
int err;
@@ -188,8 +211,9 @@ static inline int snd_uda1341_valid_reg(struct l3_client *clnt, unsigned short r
return reg < uda1341_reg_last;
}
-int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg, unsigned short mask,
- unsigned short shift, unsigned short value, int flush)
+static int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg,
+ unsigned short mask, unsigned short shift,
+ unsigned short value, int flush)
{
int change;
unsigned short old, new;
@@ -214,8 +238,8 @@ int snd_uda1341_update_bits(struct l3_client *clnt, unsigned short reg, unsigned
return change;
}
-int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
- unsigned short value, int flush)
+static int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
+ unsigned short value, int flush)
{
struct uda1341 *uda = clnt->driver_data;
int ret = 0;
@@ -327,9 +351,84 @@ int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
/* }}} */
/* {{{ Proc interface */
+#ifdef CONFIG_PROC_FS
+
+static const char *format_names[] = {
+ "I2S-bus",
+ "LSB 16bits",
+ "LSB 18bits",
+ "LSB 20bits",
+ "MSB",
+ "in LSB 16bits/out MSB",
+ "in LSB 18bits/out MSB",
+ "in LSB 20bits/out MSB",
+};
+
+static const char *fs_names[] = {
+ "512*fs",
+ "384*fs",
+ "256*fs",
+ "Unused - bad value!",
+};
+
+static const char* bass_values[][16] = {
+ {"0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB", "0 dB",
+ "0 dB", "0 dB", "0 dB", "0 dB", "undefined", }, //flat
+ {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
+ "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
+ {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "18 dB",
+ "18 dB", "18 dB", "18 dB", "18 dB", "undefined",}, // min
+ {"0 dB", "2 dB", "4 dB", "6 dB", "8 dB", "10 dB", "12 dB", "14 dB", "16 dB", "18 dB", "20 dB",
+ "22 dB", "24 dB", "24 dB", "24 dB", "undefined",}, // max
+};
+
+static const char *mic_sens_value[] = {
+ "-3 dB", "0 dB", "3 dB", "9 dB", "15 dB", "21 dB", "27 dB", "not used",
+};
+
+static const unsigned short AGC_atime[] = {
+ 11, 16, 11, 16, 21, 11, 16, 21,
+};
+
+static const unsigned short AGC_dtime[] = {
+ 100, 100, 200, 200, 200, 400, 400, 400,
+};
-static void snd_uda1341_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static const char *AGC_level[] = {
+ "-9.0", "-11.5", "-15.0", "-17.5",
+};
+
+static const char *ig_small_value[] = {
+ "-3.0", "-2.5", "-2.0", "-1.5", "-1.0", "-0.5",
+};
+
+/*
+ * this was computed as peak_value[i] = pow((63-i)*1.42,1.013)
+ *
+ * UDA1341 datasheet on page 21: Peak value (dB) = (Peak level - 63.5)*5*log2
+ * There is an table with these values [level]=value: [3]=-90.31, [7]=-84.29
+ * [61]=-2.78, [62] = -1.48, [63] = 0.0
+ * I tried to compute it, but using but even using logarithm with base either 10 or 2
+ * i was'n able to get values in the table from the formula. So I constructed another
+ * formula (see above) to interpolate the values as good as possible. If there is some
+ * mistake, please contact me on tomas.kasparek@seznam.cz. Thanks.
+ * UDA1341TS datasheet is available at:
+ * http://www-us9.semiconductors.com/acrobat/datasheets/UDA1341TS_3.pdf
+ */
+static const char *peak_value[] = {
+ "-INF dB", "N.A.", "N.A", "90.31 dB", "N.A.", "N.A.", "N.A.", "-84.29 dB",
+ "-82.65 dB", "-81.13 dB", "-79.61 dB", "-78.09 dB", "-76.57 dB", "-75.05 dB", "-73.53 dB",
+ "-72.01 dB", "-70.49 dB", "-68.97 dB", "-67.45 dB", "-65.93 dB", "-64.41 dB", "-62.90 dB",
+ "-61.38 dB", "-59.86 dB", "-58.35 dB", "-56.83 dB", "-55.32 dB", "-53.80 dB", "-52.29 dB",
+ "-50.78 dB", "-49.26 dB", "-47.75 dB", "-46.24 dB", "-44.73 dB", "-43.22 dB", "-41.71 dB",
+ "-40.20 dB", "-38.69 dB", "-37.19 dB", "-35.68 dB", "-34.17 dB", "-32.67 dB", "-31.17 dB",
+ "-29.66 dB", "-28.16 dB", "-26.66 dB", "-25.16 dB", "-23.66 dB", "-22.16 dB", "-20.67 dB",
+ "-19.17 dB", "-17.68 dB", "-16.19 dB", "-14.70 dB", "-13.21 dB", "-11.72 dB", "-10.24 dB",
+ "-8.76 dB", "-7.28 dB", "-5.81 dB", "-4.34 dB", "-2.88 dB", "-1.43 dB", "0.00 dB",
+};
+
+static void snd_uda1341_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct l3_client *clnt = entry->private_data;
struct uda1341 *uda = clnt->driver_data;
@@ -393,15 +492,14 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "Input Amp. Gain ch 2: %s dB\n", ig_small_value[uda->cfg[CMD_IG]]);
}
-static void snd_uda1341_proc_regs_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_uda1341_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
struct l3_client *clnt = entry->private_data;
struct uda1341 *uda = clnt->driver_data;
int reg;
char buf[12];
- spin_lock(&uda->reg_lock);
for (reg = 0; reg < uda1341_reg_last; reg ++) {
if (reg == empty)
continue;
@@ -411,13 +509,12 @@ static void snd_uda1341_proc_regs_read(snd_info_entry_t *entry,
int2str_bin8(snd_uda1341_codec_read(clnt, UDA1341_DATA1), buf);
snd_iprintf(buffer, "DATA1 = %s\n", buf);
-
- spin_unlock(&uda->reg_lock);
}
+#endif /* CONFIG_PROC_FS */
-static void __devinit snd_uda1341_proc_init(snd_card_t *card, struct l3_client *clnt)
+static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_client *clnt)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(card, "uda1341", &entry))
snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read);
@@ -437,7 +534,8 @@ static void __devinit snd_uda1341_proc_init(snd_card_t *card, struct l3_client *
.private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
}
-static int snd_uda1341_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_uda1341_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 12) & 63;
@@ -448,10 +546,11 @@ static int snd_uda1341_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_uda1341_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
int mask = (kcontrol->private_value >> 12) & 63;
int invert = (kcontrol->private_value >> 18) & 1;
@@ -463,10 +562,11 @@ static int snd_uda1341_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_uda1341_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
int reg = (kcontrol->private_value >> 5) & 15;
int shift = (kcontrol->private_value >> 9) & 7;
@@ -492,7 +592,8 @@ static int snd_uda1341_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.private_value = where | (reg << 5) | (shift << 9) | (mask << 12) | (invert << 18) \
}
-static int snd_uda1341_info_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_uda1341_info_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int where = kcontrol->private_value & 31;
const char **texts;
@@ -513,20 +614,22 @@ static int snd_uda1341_info_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_uda1341_get_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_get_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
ucontrol->value.enumerated.item[0] = uda->cfg[where];
return 0;
}
-static int snd_uda1341_put_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
int reg = (kcontrol->private_value >> 5) & 15;
int shift = (kcontrol->private_value >> 9) & 7;
@@ -549,7 +652,8 @@ static int snd_uda1341_put_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
-static int snd_uda1341_info_2regs(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_uda1341_info_2regs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask_1 = (kcontrol->private_value >> 19) & 63;
int mask_2 = (kcontrol->private_value >> 25) & 63;
@@ -563,10 +667,11 @@ static int snd_uda1341_info_2regs(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_uda1341_get_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_get_2regs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
int mask_1 = (kcontrol->private_value >> 19) & 63;
int mask_2 = (kcontrol->private_value >> 25) & 63;
@@ -581,10 +686,11 @@ static int snd_uda1341_get_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_uda1341_put_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_uda1341_put_2regs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct l3_client *clnt = snd_kcontrol_chip(kcontrol);
- uda1341_t *uda = clnt->driver_data;
+ struct uda1341 *uda = clnt->driver_data;
int where = kcontrol->private_value & 31;
int reg_1 = (kcontrol->private_value >> 5) & 15;
int reg_2 = (kcontrol->private_value >> 9) & 15;
@@ -617,7 +723,7 @@ static int snd_uda1341_put_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/* }}} */
-static snd_kcontrol_new_t snd_uda1341_controls[] = {
+static struct snd_kcontrol_new snd_uda1341_controls[] = {
UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
@@ -647,54 +753,55 @@ static snd_kcontrol_new_t snd_uda1341_controls[] = {
UDA1341_2REGS("Gain Input Amplifier Gain (channel 2)", CMD_IG, ext4, ext5, 0, 0, 3, 31, 0),
};
-static void uda1341_free(struct l3_client *uda1341)
+static void uda1341_free(struct l3_client *clnt)
{
- l3_detach_client(uda1341); // calls kfree for driver_data (uda1341_t)
- kfree(uda1341);
+ l3_detach_client(clnt); // calls kfree for driver_data (struct uda1341)
+ kfree(clnt);
}
-static int uda1341_dev_free(snd_device_t *device)
+static int uda1341_dev_free(struct snd_device *device)
{
struct l3_client *clnt = device->device_data;
uda1341_free(clnt);
return 0;
}
-int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
+int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clntp)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = uda1341_dev_free,
};
- struct l3_client *uda1341;
+ struct l3_client *clnt;
int idx, err;
snd_assert(card != NULL, return -EINVAL);
- uda1341 = kzalloc(sizeof(*uda1341), GFP_KERNEL);
- if (uda1341 == NULL)
+ clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
+ if (clnt == NULL)
return -ENOMEM;
- if ((err = l3_attach_client(uda1341, "l3-bit-sa1100-gpio", "snd-uda1341"))) {
- kfree(uda1341);
- return err;
- }
-
- if ((err = snd_device_new(card, SNDRV_DEV_CODEC, uda1341, &ops)) < 0) {
- l3_detach_client(uda1341);
- kfree(uda1341);
+ if ((err = l3_attach_client(clnt, "l3-bit-sa1100-gpio", UDA1341_ALSA_NAME))) {
+ kfree(clnt);
return err;
}
for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
- if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], uda1341))) < 0)
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], clnt))) < 0) {
+ uda1341_free(clnt);
return err;
+ }
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_CODEC, clnt, &ops)) < 0) {
+ uda1341_free(clnt);
+ return err;
}
- *clnt = uda1341;
+ *clntp = clnt;
strcpy(card->mixername, "UDA1341TS Mixer");
- ((uda1341_t *)uda1341->driver_data)->card = card;
+ ((struct uda1341 *)clnt->driver_data)->card = card;
- snd_uda1341_proc_init(card, uda1341);
+ snd_uda1341_proc_init(card, clnt);
return 0;
}
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d351b3aa1916..12ffffc9e814 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -37,7 +37,7 @@ MODULE_LICENSE("GPL");
static void ak4114_stats(void *);
-static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val)
+static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val)
{
ak4114->write(ak4114->private_data, reg, val);
if (reg <= AK4114_REG_INT1_MASK)
@@ -46,13 +46,13 @@ static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val)
ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val;
}
-static inline unsigned char reg_read(ak4114_t *ak4114, unsigned char reg)
+static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg)
{
return ak4114->read(ak4114->private_data, reg);
}
#if 0
-static void reg_dump(ak4114_t *ak4114)
+static void reg_dump(struct ak4114 *ak4114)
{
int i;
@@ -62,7 +62,7 @@ static void reg_dump(ak4114_t *ak4114)
}
#endif
-static void snd_ak4114_free(ak4114_t *chip)
+static void snd_ak4114_free(struct ak4114 *chip)
{
chip->init = 1; /* don't schedule new work */
mb();
@@ -73,22 +73,22 @@ static void snd_ak4114_free(ak4114_t *chip)
kfree(chip);
}
-static int snd_ak4114_dev_free(snd_device_t *device)
+static int snd_ak4114_dev_free(struct snd_device *device)
{
- ak4114_t *chip = device->device_data;
+ struct ak4114 *chip = device->device_data;
snd_ak4114_free(chip);
return 0;
}
-int snd_ak4114_create(snd_card_t *card,
+int snd_ak4114_create(struct snd_card *card,
ak4114_read_t *read, ak4114_write_t *write,
unsigned char pgm[7], unsigned char txcsb[5],
- void *private_data, ak4114_t **r_ak4114)
+ void *private_data, struct ak4114 **r_ak4114)
{
- ak4114_t *chip;
+ struct ak4114 *chip;
int err = 0;
unsigned char reg;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ak4114_dev_free,
};
@@ -129,7 +129,7 @@ int snd_ak4114_create(snd_card_t *card,
return err < 0 ? err : -EIO;
}
-void snd_ak4114_reg_write(ak4114_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val)
{
if (reg <= AK4114_REG_INT1_MASK)
reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
@@ -137,7 +137,7 @@ void snd_ak4114_reg_write(ak4114_t *chip, unsigned char reg, unsigned char mask,
reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val);
}
-void snd_ak4114_reinit(ak4114_t *chip)
+void snd_ak4114_reinit(struct ak4114 *chip)
{
unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
@@ -176,8 +176,8 @@ static unsigned int external_rate(unsigned char rcs1)
}
}
-static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_in_error_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -186,10 +186,10 @@ static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
long *ptr;
spin_lock_irq(&chip->lock);
@@ -200,8 +200,8 @@ static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_in_bit_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -210,10 +210,10 @@ static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_in_bit_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned char reg = kcontrol->private_value & 0xff;
unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
unsigned char inv = (kcontrol->private_value >> 31) & 1;
@@ -222,8 +222,8 @@ static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4114_rate_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -232,26 +232,26 @@ static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4114_rate_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4114_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1));
return 0;
}
-static int snd_ak4114_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++)
@@ -259,10 +259,10 @@ static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_playback_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
@@ -270,10 +270,10 @@ static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_playback_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
@@ -281,21 +281,21 @@ static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4114_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ak4114_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE);
return 0;
}
-static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.min = 0;
@@ -304,10 +304,10 @@ static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_pget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned short tmp;
ucontrol->value.integer.value[0] = 0xf8f2;
@@ -319,17 +319,17 @@ static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4114_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4114_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
uinfo->count = AK4114_REG_QSUB_SIZE;
return 0;
}
-static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4114_spdif_qget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4114_REG_QSUB_SIZE; i++)
@@ -338,14 +338,14 @@ static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol,
}
/* Don't forget to change AK4114_CONTROLS define!!! */
-static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
+static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "IEC958 Parity Errors",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(ak4114_t, parity_errors),
+ .private_value = offsetof(struct ak4114, parity_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -353,7 +353,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(ak4114_t, v_bit_errors),
+ .private_value = offsetof(struct ak4114, v_bit_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -361,7 +361,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(ak4114_t, ccrc_errors),
+ .private_value = offsetof(struct ak4114, ccrc_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -369,7 +369,7 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(ak4114_t, qcrc_errors),
+ .private_value = offsetof(struct ak4114, qcrc_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -447,11 +447,11 @@ static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
}
};
-int snd_ak4114_build(ak4114_t *ak4114,
- snd_pcm_substream_t *ply_substream,
- snd_pcm_substream_t *cap_substream)
+int snd_ak4114_build(struct ak4114 *ak4114,
+ struct snd_pcm_substream *ply_substream,
+ struct snd_pcm_substream *cap_substream)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -482,7 +482,7 @@ int snd_ak4114_build(ak4114_t *ak4114,
return 0;
}
-int snd_ak4114_external_rate(ak4114_t *ak4114)
+int snd_ak4114_external_rate(struct ak4114 *ak4114)
{
unsigned char rcs1;
@@ -490,9 +490,9 @@ int snd_ak4114_external_rate(ak4114_t *ak4114)
return external_rate(rcs1);
}
-int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
+int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
{
- snd_pcm_runtime_t *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
+ struct snd_pcm_runtime *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
unsigned long _flags;
int res = 0;
unsigned char rcs0, rcs1;
@@ -563,7 +563,7 @@ int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
static void ak4114_stats(void *data)
{
- ak4114_t *chip = (ak4114_t *)data;
+ struct ak4114 *chip = (struct ak4114 *)data;
if (chip->init)
return;
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 35b4584483a3..4e45952dd95a 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -37,20 +37,20 @@ MODULE_LICENSE("GPL");
static void snd_ak4117_timer(unsigned long data);
-static void reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char val)
+static void reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char val)
{
ak4117->write(ak4117->private_data, reg, val);
if (reg < sizeof(ak4117->regmap))
ak4117->regmap[reg] = val;
}
-static inline unsigned char reg_read(ak4117_t *ak4117, unsigned char reg)
+static inline unsigned char reg_read(struct ak4117 *ak4117, unsigned char reg)
{
return ak4117->read(ak4117->private_data, reg);
}
#if 0
-static void reg_dump(ak4117_t *ak4117)
+static void reg_dump(struct ak4117 *ak4117)
{
int i;
@@ -60,26 +60,26 @@ static void reg_dump(ak4117_t *ak4117)
}
#endif
-static void snd_ak4117_free(ak4117_t *chip)
+static void snd_ak4117_free(struct ak4117 *chip)
{
del_timer(&chip->timer);
kfree(chip);
}
-static int snd_ak4117_dev_free(snd_device_t *device)
+static int snd_ak4117_dev_free(struct snd_device *device)
{
- ak4117_t *chip = device->device_data;
+ struct ak4117 *chip = device->device_data;
snd_ak4117_free(chip);
return 0;
}
-int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write,
- unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117)
+int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
+ unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117)
{
- ak4117_t *chip;
+ struct ak4117 *chip;
int err = 0;
unsigned char reg;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ak4117_dev_free,
};
@@ -115,14 +115,14 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *wri
return err < 0 ? err : -EIO;
}
-void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+void snd_ak4117_reg_write(struct ak4117 *chip, unsigned char reg, unsigned char mask, unsigned char val)
{
if (reg >= 5)
return;
reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
}
-void snd_ak4117_reinit(ak4117_t *chip)
+void snd_ak4117_reinit(struct ak4117 *chip)
{
unsigned char old = chip->regmap[AK4117_REG_PWRDN], reg;
@@ -157,8 +157,8 @@ static unsigned int external_rate(unsigned char rcs1)
}
}
-static int snd_ak4117_in_error_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4117_in_error_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -167,10 +167,10 @@ static int snd_ak4117_in_error_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_in_error_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
long *ptr;
spin_lock_irq(&chip->lock);
@@ -181,8 +181,8 @@ static int snd_ak4117_in_error_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_in_bit_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4117_in_bit_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -191,10 +191,10 @@ static int snd_ak4117_in_bit_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_in_bit_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4117_in_bit_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
unsigned char reg = kcontrol->private_value & 0xff;
unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
unsigned char inv = (kcontrol->private_value >> 31) & 1;
@@ -203,8 +203,8 @@ static int snd_ak4117_in_bit_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_rx_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4117_rx_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -213,19 +213,19 @@ static int snd_ak4117_rx_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_rx_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4117_rx_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (chip->regmap[AK4117_REG_IO] & AK4117_IPS) ? 1 : 0;
return 0;
}
-static int snd_ak4117_rx_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4117_rx_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
int change;
u8 old_val;
@@ -238,8 +238,8 @@ static int snd_ak4117_rx_put(snd_kcontrol_t *kcontrol,
return change;
}
-static int snd_ak4117_rate_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ak4117_rate_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -248,26 +248,26 @@ static int snd_ak4117_rate_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ak4117_rate_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ak4117_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4117_REG_RCS1));
return 0;
}
-static int snd_ak4117_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4117_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ak4117_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4117_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4117_REG_RXCSB_SIZE; i++)
@@ -275,21 +275,21 @@ static int snd_ak4117_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4117_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4117_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ak4117_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4117_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
memset(ucontrol->value.iec958.status, 0xff, AK4117_REG_RXCSB_SIZE);
return 0;
}
-static int snd_ak4117_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4117_spdif_pinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->value.integer.min = 0;
@@ -298,10 +298,10 @@ static int snd_ak4117_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ak4117_spdif_pget(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4117_spdif_pget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
unsigned short tmp;
ucontrol->value.integer.value[0] = 0xf8f2;
@@ -313,17 +313,17 @@ static int snd_ak4117_spdif_pget(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ak4117_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4117_spdif_qinfo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
uinfo->count = AK4117_REG_QSUB_SIZE;
return 0;
}
-static int snd_ak4117_spdif_qget(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4117_spdif_qget(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ak4117_t *chip = snd_kcontrol_chip(kcontrol);
+ struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
unsigned i;
for (i = 0; i < AK4117_REG_QSUB_SIZE; i++)
@@ -332,14 +332,14 @@ static int snd_ak4117_spdif_qget(snd_kcontrol_t * kcontrol,
}
/* Don't forget to change AK4117_CONTROLS define!!! */
-static snd_kcontrol_new_t snd_ak4117_iec958_controls[] = {
+static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "IEC958 Parity Errors",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(ak4117_t, parity_errors),
+ .private_value = offsetof(struct ak4117, parity_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -347,7 +347,7 @@ static snd_kcontrol_new_t snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(ak4117_t, v_bit_errors),
+ .private_value = offsetof(struct ak4117, v_bit_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -355,7 +355,7 @@ static snd_kcontrol_new_t snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(ak4117_t, ccrc_errors),
+ .private_value = offsetof(struct ak4117, ccrc_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -363,7 +363,7 @@ static snd_kcontrol_new_t snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(ak4117_t, qcrc_errors),
+ .private_value = offsetof(struct ak4117, qcrc_errors),
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -434,9 +434,9 @@ static snd_kcontrol_new_t snd_ak4117_iec958_controls[] = {
}
};
-int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *cap_substream)
+int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *cap_substream)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -456,7 +456,7 @@ int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *cap_substream)
return 0;
}
-int snd_ak4117_external_rate(ak4117_t *ak4117)
+int snd_ak4117_external_rate(struct ak4117 *ak4117)
{
unsigned char rcs1;
@@ -464,9 +464,9 @@ int snd_ak4117_external_rate(ak4117_t *ak4117)
return external_rate(rcs1);
}
-int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags)
+int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags)
{
- snd_pcm_runtime_t *runtime = ak4117->substream ? ak4117->substream->runtime : NULL;
+ struct snd_pcm_runtime *runtime = ak4117->substream ? ak4117->substream->runtime : NULL;
unsigned long _flags;
int res = 0;
unsigned char rcs0, rcs1, rcs2;
@@ -542,7 +542,7 @@ int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags)
static void snd_ak4117_timer(unsigned long data)
{
- ak4117_t *chip = (ak4117_t *)data;
+ struct ak4117 *chip = (struct ak4117 *)data;
if (chip->init)
return;
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index db2b7274a9d6..045e32a311e0 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -34,7 +34,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters");
MODULE_LICENSE("GPL");
-void snd_akm4xxx_write(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char val)
+void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val)
{
ak->ops.lock(ak, chip);
ak->ops.write(ak, chip, reg, val);
@@ -58,7 +58,7 @@ void snd_akm4xxx_write(akm4xxx_t *ak, int chip, unsigned char reg, unsigned char
*
* assert the reset operation and restores the register values to the chips.
*/
-void snd_akm4xxx_reset(akm4xxx_t *ak, int state)
+void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state)
{
unsigned int chip;
unsigned char reg;
@@ -109,7 +109,7 @@ void snd_akm4xxx_reset(akm4xxx_t *ak, int state)
/*
* initialize all the ak4xxx chips
*/
-void snd_akm4xxx_init(akm4xxx_t *ak)
+void snd_akm4xxx_init(struct snd_akm4xxx *ak)
{
static unsigned char inits_ak4524[] = {
0x00, 0x07, /* 0: all power up */
@@ -247,7 +247,8 @@ void snd_akm4xxx_init(akm4xxx_t *ak)
#define AK_COMPOSE(chip,addr,shift,mask) (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24))
#define AK_INVERT (1<<23)
-static int snd_akm4xxx_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
unsigned int mask = AK_GET_MASK(kcontrol->private_value);
@@ -258,9 +259,10 @@ static int snd_akm4xxx_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -271,9 +273,10 @@ static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_akm4xxx_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -289,7 +292,8 @@ static int snd_akm4xxx_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return change;
}
-static int snd_akm4xxx_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -298,18 +302,20 @@ static int snd_akm4xxx_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f;
return 0;
}
-static int snd_akm4xxx_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
@@ -319,7 +325,8 @@ static int snd_akm4xxx_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
return change;
}
-static int snd_akm4xxx_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"44.1kHz", "Off", "48kHz", "32kHz",
@@ -333,9 +340,10 @@ static int snd_akm4xxx_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int shift = AK_GET_SHIFT(kcontrol->private_value);
@@ -343,9 +351,10 @@ static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
+ struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
int chip = AK_GET_CHIP(kcontrol->private_value);
int addr = AK_GET_ADDR(kcontrol->private_value);
int shift = AK_GET_SHIFT(kcontrol->private_value);
@@ -363,10 +372,10 @@ static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
* build AK4xxx controls
*/
-int snd_akm4xxx_build_controls(akm4xxx_t *ak)
+int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
{
unsigned int idx, num_emphs;
- snd_kcontrol_t *ctl;
+ struct snd_kcontrol *ctl;
int err;
ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 0f05a2b9a370..4c2fd14c1056 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -58,7 +58,7 @@ MODULE_LICENSE("GPL");
* lowlevel part
*/
-static void snd_tea575x_set_freq(tea575x_t *tea)
+static void snd_tea575x_set_freq(struct snd_tea575x *tea)
{
unsigned long freq;
@@ -89,7 +89,7 @@ static int snd_tea575x_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
struct video_device *dev = video_devdata(file);
- tea575x_t *tea = video_get_drvdata(dev);
+ struct snd_tea575x *tea = video_get_drvdata(dev);
void __user *arg = (void __user *)data;
switch(cmd) {
@@ -175,7 +175,7 @@ static void snd_tea575x_release(struct video_device *vfd)
/*
* initialize all the tea575x chips
*/
-void snd_tea575x_init(tea575x_t *tea)
+void snd_tea575x_init(struct snd_tea575x *tea)
{
unsigned int val;
@@ -209,7 +209,7 @@ void snd_tea575x_init(tea575x_t *tea)
snd_tea575x_set_freq(tea);
}
-void snd_tea575x_exit(tea575x_t *tea)
+void snd_tea575x_exit(struct snd_tea575x *tea)
{
if (tea->vd_registered) {
video_unregister_device(&tea->vd);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 4fdd1fb57dfe..ae5b1e3a68ce 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <sound/core.h>
+#include <sound/control.h>
#include <sound/tea6330t.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -43,7 +44,20 @@ MODULE_LICENSE("GPL");
#define TEA6330T_GMU 0x80 /* mute control, general mute */
#define TEA6330T_EQN 0x40 /* equalizer switchover (0=equalizer-on) */
-int snd_tea6330t_detect(snd_i2c_bus_t *bus, int equalizer)
+
+struct tea6330t {
+ struct snd_i2c_device *device;
+ struct snd_i2c_bus *bus;
+ int equalizer;
+ int fader;
+ unsigned char regs[8];
+ unsigned char mleft, mright;
+ unsigned char bass, treble;
+ unsigned char max_bass, max_treble;
+};
+
+
+int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer)
{
int res;
@@ -54,7 +68,7 @@ int snd_tea6330t_detect(snd_i2c_bus_t *bus, int equalizer)
}
#if 0
-static void snd_tea6330t_set(tea6330t_t *tea,
+static void snd_tea6330t_set(struct tea6330t *tea,
unsigned char addr, unsigned char value)
{
#if 0
@@ -69,7 +83,8 @@ static void snd_tea6330t_set(tea6330t_t *tea,
.info = snd_tea6330t_info_master_volume, \
.get = snd_tea6330t_get_master_volume, .put = snd_tea6330t_put_master_volume }
-static int snd_tea6330t_info_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_tea6330t_info_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -78,9 +93,10 @@ static int snd_tea6330t_info_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_tea6330t_get_master_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_get_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
snd_i2c_lock(tea->bus);
ucontrol->value.integer.value[0] = tea->mleft - 0x14;
@@ -89,9 +105,10 @@ static int snd_tea6330t_get_master_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
return 0;
}
-static int snd_tea6330t_put_master_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
int change, count, err;
unsigned char bytes[3];
unsigned char val1, val2;
@@ -125,7 +142,8 @@ static int snd_tea6330t_put_master_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
.info = snd_tea6330t_info_master_switch, \
.get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch }
-static int snd_tea6330t_info_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_tea6330t_info_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -134,9 +152,10 @@ static int snd_tea6330t_info_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_tea6330t_get_master_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
snd_i2c_lock(tea->bus);
ucontrol->value.integer.value[0] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] == 0 ? 0 : 1;
@@ -145,9 +164,10 @@ static int snd_tea6330t_get_master_switch(snd_kcontrol_t * kcontrol, snd_ctl_ele
return 0;
}
-static int snd_tea6330t_put_master_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_put_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
int change, err;
unsigned char bytes[3];
unsigned char oval1, oval2, val1, val2;
@@ -174,9 +194,10 @@ static int snd_tea6330t_put_master_switch(snd_kcontrol_t * kcontrol, snd_ctl_ele
.info = snd_tea6330t_info_bass, \
.get = snd_tea6330t_get_bass, .put = snd_tea6330t_put_bass }
-static int snd_tea6330t_info_bass(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_tea6330t_info_bass(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -185,17 +206,19 @@ static int snd_tea6330t_info_bass(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_tea6330t_get_bass(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_get_bass(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = tea->bass;
return 0;
}
-static int snd_tea6330t_put_bass(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_put_bass(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
int change, err;
unsigned char bytes[2];
unsigned char val1;
@@ -218,9 +241,10 @@ static int snd_tea6330t_put_bass(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.info = snd_tea6330t_info_treble, \
.get = snd_tea6330t_get_treble, .put = snd_tea6330t_put_treble }
-static int snd_tea6330t_info_treble(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_tea6330t_info_treble(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -229,17 +253,19 @@ static int snd_tea6330t_info_treble(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_tea6330t_get_treble(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_get_treble(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = tea->treble;
return 0;
}
-static int snd_tea6330t_put_treble(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_tea6330t_put_treble(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- tea6330t_t *tea = snd_kcontrol_chip(kcontrol);
+ struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
int change, err;
unsigned char bytes[2];
unsigned char val1;
@@ -257,25 +283,25 @@ static int snd_tea6330t_put_treble(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return change;
}
-static snd_kcontrol_new_t snd_tea6330t_controls[] = {
+static struct snd_kcontrol_new snd_tea6330t_controls[] = {
TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
TEA6330T_BASS("Tone Control - Bass", 0),
TEA6330T_TREBLE("Tone Control - Treble", 0)
};
-static void snd_tea6330_free(snd_i2c_device_t *device)
+static void snd_tea6330_free(struct snd_i2c_device *device)
{
kfree(device->private_data);
}
-int snd_tea6330t_update_mixer(snd_card_t * card,
- snd_i2c_bus_t *bus,
+int snd_tea6330t_update_mixer(struct snd_card *card,
+ struct snd_i2c_bus *bus,
int equalizer, int fader)
{
- snd_i2c_device_t *device;
- tea6330t_t *tea;
- snd_kcontrol_new_t *knew;
+ struct snd_i2c_device *device;
+ struct tea6330t *tea;
+ struct snd_kcontrol_new *knew;
unsigned int idx;
int err = -ENOMEM;
u8 default_treble, default_bass;
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 5d6c300ac0d5..ff8fef932786 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -6,12 +6,10 @@ menu "ISA devices"
config SND_AD1848_LIB
tristate
select SND_PCM
- select SND_GENERIC_DRIVER
config SND_CS4231_LIB
tristate
select SND_PCM
- select SND_GENERIC_DRIVER
config SND_AD1816A
tristate "Analog Devices SoundPort AD1816A"
@@ -41,6 +39,45 @@ config SND_AD1848
To compile this driver as a module, choose M here: the module
will be called snd-ad1848.
+config SND_ALS100
+ tristate "Avance Logic ALS100/ALS120"
+ depends on SND && PNP && ISA
+ select ISAPNP
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ Say Y here to include support for soundcards based on Avance
+ Logic ALS100, ALS110, ALS120 and ALS200 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-als100.
+
+config SND_AZT2320
+ tristate "Aztech Systems AZT2320"
+ depends on SND && PNP && ISA
+ select ISAPNP
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_CS4231_LIB
+ help
+ Say Y here to include support for soundcards based on the
+ Aztech Systems AZT2320 chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-azt2320.
+
+config SND_CMI8330
+ tristate "C-Media CMI8330"
+ depends on SND
+ select SND_AD1848_LIB
+ help
+ Say Y here to include support for soundcards based on the
+ C-Media CMI8330 chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-cmi8330.
+
config SND_CS4231
tristate "Generic Cirrus Logic CS4231 driver"
depends on SND
@@ -79,6 +116,20 @@ config SND_CS4236
To compile this driver as a module, choose M here: the module
will be called snd-cs4236.
+config SND_DT019X
+ tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
+ depends on SND && PNP && ISA
+ select ISAPNP
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ Say Y here to include support for soundcards based on the
+ Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-dt019x.
+
config SND_ES968
tristate "Generic ESS ES968 driver"
depends on SND && PNP && ISA
@@ -97,7 +148,6 @@ 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.
@@ -111,7 +161,6 @@ config SND_ES18XX
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 ES18xx chips.
@@ -127,7 +176,6 @@ 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.
@@ -142,7 +190,6 @@ 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.
@@ -156,7 +203,6 @@ 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.
@@ -170,7 +216,6 @@ config SND_INTERWAVE
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards (Gravis UltraSound Plug & Play, STB SoundRage32,
@@ -185,7 +230,6 @@ config SND_INTERWAVE_STB
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
- select SND_GENERIC_DRIVER
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
@@ -194,6 +238,19 @@ config SND_INTERWAVE_STB
To compile this driver as a module, choose M here: the module
will be called snd-interwave-stb.
+config SND_OPL3SA2
+ tristate "Yamaha OPL3-SA2/SA3"
+ depends on SND
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_CS4231_LIB
+ help
+ Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
+ chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-opl3sa2.
+
config SND_OPTI92X_AD1848
tristate "OPTi 82C92x - AD1848"
depends on SND
@@ -228,7 +285,6 @@ 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.
@@ -242,7 +298,6 @@ 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.
@@ -256,7 +311,6 @@ 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).
@@ -270,7 +324,6 @@ 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).
@@ -286,85 +339,6 @@ config SND_SB16_CSP
coprocessor can do variable tasks like various compression and
decompression algorithms.
-config SND_WAVEFRONT
- tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
- depends on SND
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_CS4231_LIB
- help
- Say Y here to include support for Turtle Beach Maui, Tropez
- and Tropez+ soundcards based on the Wavefront chip.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-wavefront.
-
-config SND_ALS100
- tristate "Avance Logic ALS100/ALS120"
- depends on SND && PNP && ISA
- select ISAPNP
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_PCM
- help
- Say Y here to include support for soundcards based on Avance
- Logic ALS100, ALS110, ALS120 and ALS200 chips.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-als100.
-
-config SND_AZT2320
- tristate "Aztech Systems AZT2320"
- depends on SND && PNP && ISA
- select ISAPNP
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_CS4231_LIB
- help
- Say Y here to include support for soundcards based on the
- Aztech Systems AZT2320 chip.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-azt2320.
-
-config SND_CMI8330
- tristate "C-Media CMI8330"
- depends on SND
- select SND_AD1848_LIB
- help
- Say Y here to include support for soundcards based on the
- C-Media CMI8330 chip.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-cmi8330.
-
-config SND_DT019X
- tristate "Diamond Technologies DT-019X, Avance Logic ALS-007"
- depends on SND && PNP && ISA
- select ISAPNP
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_PCM
- help
- Say Y here to include support for soundcards based on the
- Diamond Technologies DT-019X or Avance Logic ALS-007 chips.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-dt019x.
-
-config SND_OPL3SA2
- tristate "Yamaha OPL3-SA2/SA3"
- depends on SND
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_CS4231_LIB
- help
- Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
- chips.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-opl3sa2.
-
config SND_SGALAXY
tristate "Aztech Sound Galaxy"
depends on SND
@@ -389,4 +363,17 @@ config SND_SSCAPE
To compile this driver as a module, choose M here: the module
will be called snd-sscape.
+config SND_WAVEFRONT
+ tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
+ depends on SND
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_CS4231_LIB
+ help
+ Say Y here to include support for Turtle Beach Maui, Tropez
+ and Tropez+ soundcards based on the Wavefront chip.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-wavefront.
+
endmenu
diff --git a/sound/isa/ad1816a/Makefile b/sound/isa/ad1816a/Makefile
index a42b29cf8549..90e00e842e49 100644
--- a/sound/isa/ad1816a/Makefile
+++ b/sound/isa/ad1816a/Makefile
@@ -3,8 +3,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
#
-snd-ad1816a-lib-objs := ad1816a_lib.o
-snd-ad1816a-objs := ad1816a.o
+snd-ad1816a-objs := ad1816a.o ad1816a_lib.o
# Toplevel Module Dependency
-obj-$(CONFIG_SND_AD1816A) += snd-ad1816a.o snd-ad1816a-lib.o
+obj-$(CONFIG_SND_AD1816A) += snd-ad1816a.o
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 0eb442ca23d6..7051f7798ed7 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -188,10 +188,10 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
const struct pnp_card_device_id *pid)
{
int error;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_card_ad1816a *acard;
- ad1816a_t *chip;
- opl3_t *opl3;
+ struct snd_ad1816a *chip;
+ struct snd_opl3 *opl3;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_ad1816a))) == NULL)
@@ -282,10 +282,8 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card,
static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
static struct pnp_card_driver ad1816a_pnpc_driver = {
@@ -294,20 +292,22 @@ static struct pnp_card_driver ad1816a_pnpc_driver = {
.id_table = snd_ad1816a_pnpids,
.probe = snd_ad1816a_pnp_detect,
.remove = __devexit_p(snd_ad1816a_pnp_remove),
+ /* FIXME: suspend/resume */
};
static int __init alsa_card_ad1816a_init(void)
{
- int cards = 0;
+ int cards;
- cards += pnp_register_card_driver(&ad1816a_pnpc_driver);
-#ifdef MODULE
- if (!cards) {
+ cards = pnp_register_card_driver(&ad1816a_pnpc_driver);
+ if (cards <= 0) {
pnp_unregister_card_driver(&ad1816a_pnpc_driver);
+#ifdef MODULE
printk(KERN_ERR "no AD1816A based soundcards found.\n");
- }
#endif /* MODULE */
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_ad1816a_exit(void)
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 7ae02396cae2..ac0d808fff57 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -30,11 +30,7 @@
#include <asm/io.h>
#include <asm/dma.h>
-MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
-MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
-MODULE_LICENSE("GPL");
-
-static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
+static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip)
{
int timeout;
@@ -46,34 +42,34 @@ static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
return -EBUSY;
}
-static inline unsigned char snd_ad1816a_in(ad1816a_t *chip, unsigned char reg)
+static inline unsigned char snd_ad1816a_in(struct snd_ad1816a *chip, unsigned char reg)
{
snd_ad1816a_busy_wait(chip);
return inb(AD1816A_REG(reg));
}
-static inline void snd_ad1816a_out(ad1816a_t *chip, unsigned char reg,
+static inline void snd_ad1816a_out(struct snd_ad1816a *chip, unsigned char reg,
unsigned char value)
{
snd_ad1816a_busy_wait(chip);
outb(value, AD1816A_REG(reg));
}
-static inline void snd_ad1816a_out_mask(ad1816a_t *chip, unsigned char reg,
+static inline void snd_ad1816a_out_mask(struct snd_ad1816a *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
snd_ad1816a_out(chip, reg,
(value & mask) | (snd_ad1816a_in(chip, reg) & ~mask));
}
-static unsigned short snd_ad1816a_read(ad1816a_t *chip, unsigned char reg)
+static unsigned short snd_ad1816a_read(struct snd_ad1816a *chip, unsigned char reg)
{
snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
return snd_ad1816a_in(chip, AD1816A_INDIR_DATA_LOW) |
(snd_ad1816a_in(chip, AD1816A_INDIR_DATA_HIGH) << 8);
}
-static void snd_ad1816a_write(ad1816a_t *chip, unsigned char reg,
+static void snd_ad1816a_write(struct snd_ad1816a *chip, unsigned char reg,
unsigned short value)
{
snd_ad1816a_out(chip, AD1816A_INDIR_ADDR, reg & 0x3f);
@@ -81,7 +77,7 @@ static void snd_ad1816a_write(ad1816a_t *chip, unsigned char reg,
snd_ad1816a_out(chip, AD1816A_INDIR_DATA_HIGH, (value >> 8) & 0xff);
}
-static void snd_ad1816a_write_mask(ad1816a_t *chip, unsigned char reg,
+static void snd_ad1816a_write_mask(struct snd_ad1816a *chip, unsigned char reg,
unsigned short mask, unsigned short value)
{
snd_ad1816a_write(chip, reg,
@@ -89,7 +85,7 @@ static void snd_ad1816a_write_mask(ad1816a_t *chip, unsigned char reg,
}
-static unsigned char snd_ad1816a_get_format(ad1816a_t *chip,
+static unsigned char snd_ad1816a_get_format(struct snd_ad1816a *chip,
unsigned int format, int channels)
{
unsigned char retval = AD1816A_FMT_LINEAR_8;
@@ -110,7 +106,7 @@ static unsigned char snd_ad1816a_get_format(ad1816a_t *chip,
return (channels > 1) ? (retval | AD1816A_FMT_STEREO) : retval;
}
-static int snd_ad1816a_open(ad1816a_t *chip, unsigned int mode)
+static int snd_ad1816a_open(struct snd_ad1816a *chip, unsigned int mode)
{
unsigned long flags;
@@ -146,7 +142,7 @@ static int snd_ad1816a_open(ad1816a_t *chip, unsigned int mode)
return 0;
}
-static void snd_ad1816a_close(ad1816a_t *chip, unsigned int mode)
+static void snd_ad1816a_close(struct snd_ad1816a *chip, unsigned int mode)
{
unsigned long flags;
@@ -178,7 +174,7 @@ static void snd_ad1816a_close(ad1816a_t *chip, unsigned int mode)
}
-static int snd_ad1816a_trigger(ad1816a_t *chip, unsigned char what,
+static int snd_ad1816a_trigger(struct snd_ad1816a *chip, unsigned char what,
int channel, int cmd)
{
int error = 0;
@@ -204,36 +200,36 @@ static int snd_ad1816a_trigger(ad1816a_t *chip, unsigned char what,
return error;
}
-static int snd_ad1816a_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_ad1816a_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE,
SNDRV_PCM_STREAM_PLAYBACK, cmd);
}
-static int snd_ad1816a_capture_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE,
SNDRV_PCM_STREAM_CAPTURE, cmd);
}
-static int snd_ad1816a_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ad1816a_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ad1816a_hw_free(snd_pcm_substream_t * substream)
+static int snd_ad1816a_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size, rate;
spin_lock_irqsave(&chip->lock, flags);
@@ -261,11 +257,11 @@ static int snd_ad1816a_playback_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size, rate;
spin_lock_irqsave(&chip->lock, flags);
@@ -294,9 +290,9 @@ static int snd_ad1816a_capture_prepare(snd_pcm_substream_t *substream)
}
-static snd_pcm_uframes_t snd_ad1816a_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ad1816a_playback_pointer(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->mode & AD1816A_MODE_PLAYBACK))
return 0;
@@ -304,9 +300,9 @@ static snd_pcm_uframes_t snd_ad1816a_playback_pointer(snd_pcm_substream_t *subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ad1816a_capture_pointer(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->mode & AD1816A_MODE_CAPTURE))
return 0;
@@ -317,7 +313,7 @@ static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substr
static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ad1816a_t *chip = dev_id;
+ struct snd_ad1816a *chip = dev_id;
unsigned char status;
spin_lock(&chip->lock);
@@ -340,7 +336,7 @@ static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *
}
-static snd_pcm_hardware_t snd_ad1816a_playback = {
+static struct snd_pcm_hardware snd_ad1816a_playback = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
@@ -359,7 +355,7 @@ static snd_pcm_hardware_t snd_ad1816a_playback = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ad1816a_capture = {
+static struct snd_pcm_hardware snd_ad1816a_capture = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
@@ -379,32 +375,32 @@ static snd_pcm_hardware_t snd_ad1816a_capture = {
};
#if 0 /* not used now */
-static int snd_ad1816a_timer_close(snd_timer_t *timer)
+static int snd_ad1816a_timer_close(struct snd_timer *timer)
{
- ad1816a_t *chip = snd_timer_chip(timer);
+ struct snd_ad1816a *chip = snd_timer_chip(timer);
snd_ad1816a_close(chip, AD1816A_MODE_TIMER);
return 0;
}
-static int snd_ad1816a_timer_open(snd_timer_t *timer)
+static int snd_ad1816a_timer_open(struct snd_timer *timer)
{
- ad1816a_t *chip = snd_timer_chip(timer);
+ struct snd_ad1816a *chip = snd_timer_chip(timer);
snd_ad1816a_open(chip, AD1816A_MODE_TIMER);
return 0;
}
-static unsigned long snd_ad1816a_timer_resolution(snd_timer_t *timer)
+static unsigned long snd_ad1816a_timer_resolution(struct snd_timer *timer)
{
snd_assert(timer != NULL, return 0);
return 10000;
}
-static int snd_ad1816a_timer_start(snd_timer_t *timer)
+static int snd_ad1816a_timer_start(struct snd_timer *timer)
{
unsigned short bits;
unsigned long flags;
- ad1816a_t *chip = snd_timer_chip(timer);
+ struct snd_ad1816a *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->lock, flags);
bits = snd_ad1816a_read(chip, AD1816A_INTERRUPT_ENABLE);
@@ -419,10 +415,10 @@ static int snd_ad1816a_timer_start(snd_timer_t *timer)
return 0;
}
-static int snd_ad1816a_timer_stop(snd_timer_t *timer)
+static int snd_ad1816a_timer_stop(struct snd_timer *timer)
{
unsigned long flags;
- ad1816a_t *chip = snd_timer_chip(timer);
+ struct snd_ad1816a *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->lock, flags);
snd_ad1816a_write_mask(chip, AD1816A_INTERRUPT_ENABLE,
@@ -432,7 +428,7 @@ static int snd_ad1816a_timer_stop(snd_timer_t *timer)
return 0;
}
-static struct _snd_timer_hardware snd_ad1816a_timer_table = {
+static struct snd_timer_hardware snd_ad1816a_timer_table = {
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 10000,
.ticks = 65535,
@@ -445,10 +441,10 @@ static struct _snd_timer_hardware snd_ad1816a_timer_table = {
#endif /* not used now */
-static int snd_ad1816a_playback_open(snd_pcm_substream_t *substream)
+static int snd_ad1816a_playback_open(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int error;
if ((error = snd_ad1816a_open(chip, AD1816A_MODE_PLAYBACK)) < 0)
@@ -461,10 +457,10 @@ static int snd_ad1816a_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_ad1816a_capture_open(snd_pcm_substream_t *substream)
+static int snd_ad1816a_capture_open(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int error;
if ((error = snd_ad1816a_open(chip, AD1816A_MODE_CAPTURE)) < 0)
@@ -477,18 +473,18 @@ static int snd_ad1816a_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_ad1816a_playback_close(snd_pcm_substream_t *substream)
+static int snd_ad1816a_playback_close(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
snd_ad1816a_close(chip, AD1816A_MODE_PLAYBACK);
return 0;
}
-static int snd_ad1816a_capture_close(snd_pcm_substream_t *substream)
+static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream)
{
- ad1816a_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
snd_ad1816a_close(chip, AD1816A_MODE_CAPTURE);
@@ -496,7 +492,7 @@ static int snd_ad1816a_capture_close(snd_pcm_substream_t *substream)
}
-static void snd_ad1816a_init(ad1816a_t *chip)
+static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip)
{
unsigned long flags;
@@ -516,7 +512,7 @@ static void snd_ad1816a_init(ad1816a_t *chip)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static int snd_ad1816a_probe(ad1816a_t *chip)
+static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip)
{
unsigned long flags;
@@ -540,7 +536,7 @@ static int snd_ad1816a_probe(ad1816a_t *chip)
return 0;
}
-static int snd_ad1816a_free(ad1816a_t *chip)
+static int snd_ad1816a_free(struct snd_ad1816a *chip)
{
release_and_free_resource(chip->res_port);
if (chip->irq >= 0)
@@ -557,13 +553,13 @@ static int snd_ad1816a_free(ad1816a_t *chip)
return 0;
}
-static int snd_ad1816a_dev_free(snd_device_t *device)
+static int snd_ad1816a_dev_free(struct snd_device *device)
{
- ad1816a_t *chip = device->device_data;
+ struct snd_ad1816a *chip = device->device_data;
return snd_ad1816a_free(chip);
}
-static const char *snd_ad1816a_chip_id(ad1816a_t *chip)
+static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip)
{
switch (chip->hardware) {
case AD1816A_HW_AD1816A: return "AD1816A";
@@ -576,15 +572,15 @@ static const char *snd_ad1816a_chip_id(ad1816a_t *chip)
}
}
-int snd_ad1816a_create(snd_card_t *card,
- unsigned long port, int irq, int dma1, int dma2,
- ad1816a_t **rchip)
+int __devinit snd_ad1816a_create(struct snd_card *card,
+ unsigned long port, int irq, int dma1, int dma2,
+ struct snd_ad1816a **rchip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ad1816a_dev_free,
};
int error;
- ad1816a_t *chip;
+ struct snd_ad1816a *chip;
*rchip = NULL;
@@ -640,7 +636,7 @@ int snd_ad1816a_create(snd_card_t *card,
return 0;
}
-static snd_pcm_ops_t snd_ad1816a_playback_ops = {
+static struct snd_pcm_ops snd_ad1816a_playback_ops = {
.open = snd_ad1816a_playback_open,
.close = snd_ad1816a_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -651,7 +647,7 @@ static snd_pcm_ops_t snd_ad1816a_playback_ops = {
.pointer = snd_ad1816a_playback_pointer,
};
-static snd_pcm_ops_t snd_ad1816a_capture_ops = {
+static struct snd_pcm_ops snd_ad1816a_capture_ops = {
.open = snd_ad1816a_capture_open,
.close = snd_ad1816a_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -662,17 +658,10 @@ static snd_pcm_ops_t snd_ad1816a_capture_ops = {
.pointer = snd_ad1816a_capture_pointer,
};
-static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
-{
- ad1816a_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
+int __devinit snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
{
int error;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
if ((error = snd_pcm_new(chip->card, "AD1816A", device, 1, 1, &pcm)))
return error;
@@ -681,7 +670,6 @@ int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1816a_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_ad1816a_pcm_free;
pcm->info_flags = (chip->dma1 == chip->dma2 ) ? SNDRV_PCM_INFO_JOINT_DUPLEX : 0;
strcpy(pcm->name, snd_ad1816a_chip_id(chip));
@@ -698,16 +686,10 @@ int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
}
#if 0 /* not used now */
-static void snd_ad1816a_timer_free(snd_timer_t *timer)
+int __devinit snd_ad1816a_timer(struct snd_ad1816a *chip, int device, struct snd_timer **rtimer)
{
- ad1816a_t *chip = timer->private_data;
- chip->timer = NULL;
-}
-
-int snd_ad1816a_timer(ad1816a_t *chip, int device, snd_timer_t **rtimer)
-{
- snd_timer_t *timer;
- snd_timer_id_t tid;
+ struct snd_timer *timer;
+ struct snd_timer_id tid;
int error;
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
@@ -719,7 +701,6 @@ int snd_ad1816a_timer(ad1816a_t *chip, int device, snd_timer_t **rtimer)
return error;
strcpy(timer->name, snd_ad1816a_chip_id(chip));
timer->private_data = chip;
- timer->private_free = snd_ad1816a_timer_free;
chip->timer = timer;
timer->hw = snd_ad1816a_timer_table;
if (rtimer)
@@ -732,7 +713,7 @@ int snd_ad1816a_timer(ad1816a_t *chip, int device, snd_timer_t **rtimer)
*
*/
-static int snd_ad1816a_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1816a_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[8] = {
"Line", "Mix", "CD", "Synth", "Video",
@@ -748,9 +729,9 @@ static int snd_ad1816a_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_ad1816a_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short val;
@@ -762,9 +743,9 @@ static int snd_ad1816a_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_ad1816a_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short val;
int change;
@@ -786,7 +767,7 @@ static int snd_ad1816a_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
.get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_ad1816a_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1816a_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -797,9 +778,9 @@ static int snd_ad1816a_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ad1816a_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -814,9 +795,9 @@ static int snd_ad1816a_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_ad1816a_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -843,7 +824,7 @@ static int snd_ad1816a_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \
.private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }
-static int snd_ad1816a_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1816a_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -854,9 +835,9 @@ static int snd_ad1816a_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ad1816a_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift_left = (kcontrol->private_value >> 8) & 0x0f;
@@ -877,9 +858,9 @@ static int snd_ad1816a_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1816a_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1816a *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift_left = (kcontrol->private_value >> 8) & 0x0f;
@@ -906,7 +887,7 @@ static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return change;
}
-static snd_kcontrol_new_t snd_ad1816a_controls[] = {
+static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1),
@@ -941,9 +922,9 @@ AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1),
AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0),
};
-int snd_ad1816a_mixer(ad1816a_t *chip)
+int __devinit snd_ad1816a_mixer(struct snd_ad1816a *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx;
int err;
@@ -959,19 +940,3 @@ int snd_ad1816a_mixer(ad1816a_t *chip)
}
return 0;
}
-
-EXPORT_SYMBOL(snd_ad1816a_create);
-EXPORT_SYMBOL(snd_ad1816a_pcm);
-EXPORT_SYMBOL(snd_ad1816a_mixer);
-
-static int __init alsa_ad1816a_init(void)
-{
- return 0;
-}
-
-static void __exit alsa_ad1816a_exit(void)
-{
-}
-
-module_init(alsa_ad1816a_init)
-module_exit(alsa_ad1816a_exit)
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 3ebcc482b07a..e091bbeffd2a 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -23,6 +23,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
@@ -60,14 +62,15 @@ MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
module_param_array(thinkpad, bool, NULL, 0444);
MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
-static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
-static int __init snd_card_ad1848_probe(int dev)
+static int __init snd_ad1848_probe(struct platform_device *pdev)
{
- snd_card_t *card;
- ad1848_t *chip;
- snd_pcm_t *pcm;
+ int dev = pdev->id;
+ struct snd_card *card;
+ struct snd_ad1848 *chip;
+ struct snd_pcm *pcm;
int err;
if (port[dev] == SNDRV_AUTO_PORT) {
@@ -93,6 +96,7 @@ static int __init snd_card_ad1848_probe(int dev)
thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
&chip)) < 0)
goto _err;
+ card->private_data = chip;
if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0)
goto _err;
@@ -109,13 +113,12 @@ static int __init snd_card_ad1848_probe(int dev)
if (thinkpad[dev])
strcat(card->longname, " [Thinkpad]");
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_ad1848_cards[dev] = card;
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -123,29 +126,95 @@ static int __init snd_card_ad1848_probe(int dev)
return err;
}
-static int __init alsa_card_ad1848_init(void)
+static int __devexit snd_ad1848_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip->suspend(chip);
+ return 0;
+}
+
+static int snd_ad1848_resume(struct platform_device *pdev)
{
- int dev, cards;
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++)
- if (snd_card_ad1848_probe(dev) >= 0)
- cards++;
+ chip->resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+#define SND_AD1848_DRIVER "snd_ad1848"
+
+static struct platform_driver snd_ad1848_driver = {
+ .probe = snd_ad1848_probe,
+ .remove = __devexit_p(snd_ad1848_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_ad1848_suspend,
+ .resume = snd_ad1848_resume,
+#endif
+ .driver = {
+ .name = SND_AD1848_DRIVER
+ },
+};
+
+static void __init_or_module snd_ad1848_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_ad1848_driver);
+}
+
+static int __init alsa_card_ad1848_init(void)
+{
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_ad1848_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_AD1848_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_ad1848_unregister_all();
+ return err;
}
static void __exit alsa_card_ad1848_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_ad1848_cards[idx]);
+ snd_ad1848_unregister_all();
}
module_init(alsa_card_ad1848_init)
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 891bacc94f68..b78530d7ea90 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -24,7 +24,6 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <sound/core.h>
@@ -69,7 +68,7 @@ static unsigned int rates[14] = {
27042, 32000, 33075, 37800, 44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = 14,
.list = rates,
.mask = 0,
@@ -99,7 +98,7 @@ static unsigned char snd_ad1848_original_image[16] =
* Basic I/O functions
*/
-void snd_ad1848_out(ad1848_t *chip,
+void snd_ad1848_out(struct snd_ad1848 *chip,
unsigned char reg,
unsigned char value)
{
@@ -119,7 +118,7 @@ void snd_ad1848_out(ad1848_t *chip,
#endif
}
-static void snd_ad1848_dout(ad1848_t *chip,
+static void snd_ad1848_dout(struct snd_ad1848 *chip,
unsigned char reg, unsigned char value)
{
int timeout;
@@ -131,7 +130,7 @@ static void snd_ad1848_dout(ad1848_t *chip,
mb();
}
-static unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg)
+static unsigned char snd_ad1848_in(struct snd_ad1848 *chip, unsigned char reg)
{
int timeout;
@@ -148,7 +147,7 @@ static unsigned char snd_ad1848_in(ad1848_t *chip, unsigned char reg)
#if 0
-static void snd_ad1848_debug(ad1848_t *chip)
+static void snd_ad1848_debug(struct snd_ad1848 *chip)
{
printk("AD1848 REGS: INDEX = 0x%02x ", inb(AD1848P(chip, REGSEL)));
printk(" STATUS = 0x%02x\n", inb(AD1848P(chip, STATUS)));
@@ -176,7 +175,7 @@ static void snd_ad1848_debug(ad1848_t *chip)
* AD1848 detection / MCE routines
*/
-static void snd_ad1848_mce_up(ad1848_t *chip)
+static void snd_ad1848_mce_up(struct snd_ad1848 *chip)
{
unsigned long flags;
int timeout;
@@ -197,7 +196,7 @@ static void snd_ad1848_mce_up(ad1848_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_ad1848_mce_down(ad1848_t *chip)
+static void snd_ad1848_mce_down(struct snd_ad1848 *chip)
{
unsigned long flags;
int timeout;
@@ -279,7 +278,7 @@ static unsigned int snd_ad1848_get_count(unsigned char format,
return size;
}
-static int snd_ad1848_trigger(ad1848_t *chip, unsigned char what,
+static int snd_ad1848_trigger(struct snd_ad1848 *chip, unsigned char what,
int channel, int cmd)
{
int result = 0;
@@ -324,7 +323,7 @@ static unsigned char snd_ad1848_get_rate(unsigned int rate)
return freq_bits[13];
}
-static int snd_ad1848_ioctl(snd_pcm_substream_t * substream,
+static int snd_ad1848_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
return snd_pcm_lib_ioctl(substream, cmd, arg);
@@ -348,7 +347,7 @@ static unsigned char snd_ad1848_get_format(int format, int channels)
return rformat;
}
-static void snd_ad1848_calibrate_mute(ad1848_t *chip, int mute)
+static void snd_ad1848_calibrate_mute(struct snd_ad1848 *chip, int mute)
{
unsigned long flags;
@@ -372,7 +371,7 @@ static void snd_ad1848_calibrate_mute(ad1848_t *chip, int mute)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_ad1848_set_data_format(ad1848_t *chip, snd_pcm_hw_params_t *hw_params)
+static void snd_ad1848_set_data_format(struct snd_ad1848 *chip, struct snd_pcm_hw_params *hw_params)
{
if (hw_params == NULL) {
chip->image[AD1848_DATA_FORMAT] = 0x20;
@@ -384,7 +383,7 @@ static void snd_ad1848_set_data_format(ad1848_t *chip, snd_pcm_hw_params_t *hw_p
// snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]);
}
-static int snd_ad1848_open(ad1848_t *chip, unsigned int mode)
+static int snd_ad1848_open(struct snd_ad1848 *chip, unsigned int mode)
{
unsigned long flags;
@@ -438,7 +437,7 @@ static int snd_ad1848_open(ad1848_t *chip, unsigned int mode)
return 0;
}
-static void snd_ad1848_close(ad1848_t *chip)
+static void snd_ad1848_close(struct snd_ad1848 *chip)
{
unsigned long flags;
@@ -479,24 +478,24 @@ static void snd_ad1848_close(ad1848_t *chip)
* ok.. exported functions..
*/
-static int snd_ad1848_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);
}
-static int snd_ad1848_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);
}
-static int snd_ad1848_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
int err;
@@ -513,15 +512,15 @@ static int snd_ad1848_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_ad1848_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ad1848_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -537,10 +536,10 @@ static int snd_ad1848_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ad1848_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
int err;
@@ -557,15 +556,15 @@ static int snd_ad1848_capture_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_ad1848_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -583,7 +582,7 @@ static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream)
static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ad1848_t *chip = dev_id;
+ struct snd_ad1848 *chip = dev_id;
if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
(chip->mode & AD1848_MODE_RUNNING))
@@ -595,9 +594,9 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_ad1848_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))
@@ -606,9 +605,9 @@ static snd_pcm_uframes_t snd_ad1848_playback_pointer(snd_pcm_substream_t * subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_ad1848_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))
@@ -621,7 +620,7 @@ static snd_pcm_uframes_t snd_ad1848_capture_pointer(snd_pcm_substream_t * substr
*/
-static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
+static void snd_ad1848_thinkpad_twiddle(struct snd_ad1848 *chip, int on) {
int tmp;
@@ -642,33 +641,34 @@ static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
}
#ifdef CONFIG_PM
-static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state)
+static void snd_ad1848_suspend(struct snd_ad1848 *chip)
{
- ad1848_t *chip = card->pm_private_data;
-
snd_pcm_suspend_all(chip->pcm);
- /* FIXME: save registers? */
-
if (chip->thinkpad_flag)
snd_ad1848_thinkpad_twiddle(chip, 0);
-
- return 0;
}
-static int snd_ad1848_resume(snd_card_t *card)
+static void snd_ad1848_resume(struct snd_ad1848 *chip)
{
- ad1848_t *chip = card->pm_private_data;
+ int i;
if (chip->thinkpad_flag)
snd_ad1848_thinkpad_twiddle(chip, 1);
- /* FIXME: restore registers? */
+ /* clear any pendings IRQ */
+ inb(AD1848P(chip, STATUS));
+ outb(0, AD1848P(chip, STATUS));
+ mb();
- return 0;
+ snd_ad1848_mce_down(chip);
+ for (i = 0; i < 16; i++)
+ snd_ad1848_out(chip, i, chip->image[i]);
+ snd_ad1848_mce_up(chip);
+ snd_ad1848_mce_down(chip);
}
#endif /* CONFIG_PM */
-static int snd_ad1848_probe(ad1848_t * chip)
+static int snd_ad1848_probe(struct snd_ad1848 * chip)
{
unsigned long flags;
int i, id, rev, ad1847;
@@ -748,7 +748,7 @@ static int snd_ad1848_probe(ad1848_t * chip)
*/
-static snd_pcm_hardware_t snd_ad1848_playback =
+static struct snd_pcm_hardware snd_ad1848_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -767,7 +767,7 @@ static snd_pcm_hardware_t snd_ad1848_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ad1848_capture =
+static struct snd_pcm_hardware snd_ad1848_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -790,10 +790,10 @@ static snd_pcm_hardware_t snd_ad1848_capture =
*/
-static int snd_ad1848_playback_open(snd_pcm_substream_t * substream)
+static int snd_ad1848_playback_open(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0)
@@ -806,10 +806,10 @@ static int snd_ad1848_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ad1848_capture_open(snd_pcm_substream_t * substream)
+static int snd_ad1848_capture_open(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0)
@@ -822,9 +822,9 @@ static int snd_ad1848_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ad1848_playback_close(snd_pcm_substream_t * substream)
+static int snd_ad1848_playback_close(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
chip->mode &= ~AD1848_MODE_PLAY;
chip->playback_substream = NULL;
@@ -832,9 +832,9 @@ static int snd_ad1848_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ad1848_capture_close(snd_pcm_substream_t * substream)
+static int snd_ad1848_capture_close(struct snd_pcm_substream *substream)
{
- ad1848_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ad1848 *chip = snd_pcm_substream_chip(substream);
chip->mode &= ~AD1848_MODE_CAPTURE;
chip->capture_substream = NULL;
@@ -842,7 +842,7 @@ static int snd_ad1848_capture_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ad1848_free(ad1848_t *chip)
+static int snd_ad1848_free(struct snd_ad1848 *chip)
{
release_and_free_resource(chip->res_port);
if (chip->irq >= 0)
@@ -855,13 +855,13 @@ static int snd_ad1848_free(ad1848_t *chip)
return 0;
}
-static int snd_ad1848_dev_free(snd_device_t *device)
+static int snd_ad1848_dev_free(struct snd_device *device)
{
- ad1848_t *chip = device->device_data;
+ struct snd_ad1848 *chip = device->device_data;
return snd_ad1848_free(chip);
}
-static const char *snd_ad1848_chip_id(ad1848_t *chip)
+static const char *snd_ad1848_chip_id(struct snd_ad1848 *chip)
{
switch (chip->hardware) {
case AD1848_HW_AD1847: return "AD1847";
@@ -872,16 +872,16 @@ static const char *snd_ad1848_chip_id(ad1848_t *chip)
}
}
-int snd_ad1848_create(snd_card_t * card,
+int snd_ad1848_create(struct snd_card *card,
unsigned long port,
int irq, int dma,
unsigned short hardware,
- ad1848_t ** rchip)
+ struct snd_ad1848 ** rchip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ad1848_dev_free,
};
- ad1848_t *chip;
+ struct snd_ad1848 *chip;
int err;
*rchip = NULL;
@@ -919,7 +919,6 @@ int snd_ad1848_create(snd_card_t * card,
chip->thinkpad_flag = 1;
chip->hardware = AD1848_HW_DETECT; /* reset */
snd_ad1848_thinkpad_twiddle(chip, 1);
- snd_card_set_isa_pm_callback(card, snd_ad1848_suspend, snd_ad1848_resume, chip);
}
if (snd_ad1848_probe(chip) < 0) {
@@ -933,11 +932,16 @@ int snd_ad1848_create(snd_card_t * card,
return err;
}
+#ifdef CONFIG_PM
+ chip->suspend = snd_ad1848_suspend;
+ chip->resume = snd_ad1848_resume;
+#endif
+
*rchip = chip;
return 0;
}
-static snd_pcm_ops_t snd_ad1848_playback_ops = {
+static struct snd_pcm_ops snd_ad1848_playback_ops = {
.open = snd_ad1848_playback_open,
.close = snd_ad1848_playback_close,
.ioctl = snd_ad1848_ioctl,
@@ -948,7 +952,7 @@ static snd_pcm_ops_t snd_ad1848_playback_ops = {
.pointer = snd_ad1848_playback_pointer,
};
-static snd_pcm_ops_t snd_ad1848_capture_ops = {
+static struct snd_pcm_ops snd_ad1848_capture_ops = {
.open = snd_ad1848_capture_open,
.close = snd_ad1848_capture_close,
.ioctl = snd_ad1848_ioctl,
@@ -959,16 +963,9 @@ static snd_pcm_ops_t snd_ad1848_capture_ops = {
.pointer = snd_ad1848_capture_pointer,
};
-static void snd_ad1848_pcm_free(snd_pcm_t *pcm)
-{
- ad1848_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_ad1848_pcm(ad1848_t *chip, int device, snd_pcm_t **rpcm)
+int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0)
@@ -977,7 +974,6 @@ int snd_ad1848_pcm(ad1848_t *chip, int device, snd_pcm_t **rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops);
- pcm->private_free = snd_ad1848_pcm_free;
pcm->private_data = chip;
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
strcpy(pcm->name, snd_ad1848_chip_id(chip));
@@ -992,7 +988,7 @@ int snd_ad1848_pcm(ad1848_t *chip, int device, snd_pcm_t **rpcm)
return 0;
}
-const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction)
+const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction)
{
return direction == SNDRV_PCM_STREAM_PLAYBACK ?
&snd_ad1848_playback_ops : &snd_ad1848_capture_ops;
@@ -1002,7 +998,7 @@ const snd_pcm_ops_t *snd_ad1848_get_pcm_ops(int direction)
* MIXER part
*/
-static int snd_ad1848_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Line", "Aux", "Mic", "Mix"
@@ -1017,9 +1013,9 @@ static int snd_ad1848_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_ad1848_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1029,9 +1025,9 @@ static int snd_ad1848_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_ad1848_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short left, right;
int change;
@@ -1052,7 +1048,7 @@ static int snd_ad1848_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return change;
}
-static int snd_ad1848_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1063,9 +1059,9 @@ static int snd_ad1848_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ad1848_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1080,9 +1076,9 @@ static int snd_ad1848_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ad1848_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1103,7 +1099,7 @@ static int snd_ad1848_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static int snd_ad1848_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1114,9 +1110,9 @@ static int snd_ad1848_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ad1848_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1136,9 +1132,9 @@ static int snd_ad1848_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ad1848_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ad1848_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ad1848 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1175,9 +1171,9 @@ static int snd_ad1848_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/*
*/
-int snd_ad1848_add_ctl(ad1848_t *chip, const char *name, int index, int type, unsigned long value)
+int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value)
{
- static snd_kcontrol_new_t newctls[] = {
+ static struct snd_kcontrol_new newctls[] = {
[AD1848_MIX_SINGLE] = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ad1848_info_single,
@@ -1197,7 +1193,7 @@ int snd_ad1848_add_ctl(ad1848_t *chip, const char *name, int index, int type, un
.put = snd_ad1848_put_mux,
},
};
- snd_kcontrol_t *ctl;
+ struct snd_kcontrol *ctl;
int err;
ctl = snd_ctl_new1(&newctls[type], chip);
@@ -1230,10 +1226,10 @@ AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0),
AD1848_SINGLE("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0)
};
-int snd_ad1848_mixer(ad1848_t *chip)
+int snd_ad1848_mixer(struct snd_ad1848 *chip)
{
- snd_card_t *card;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
unsigned int idx;
int err;
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index ac8f13664983..9b77c17b3f66 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -83,6 +83,7 @@ struct snd_card_als100 {
struct pnp_dev *dev;
struct pnp_dev *devmpu;
struct pnp_dev *devopl;
+ struct snd_sb *chip;
};
static struct pnp_card_device_id snd_als100_pnpids[] = {
@@ -203,15 +204,15 @@ static int __init snd_card_als100_probe(int dev,
const struct pnp_card_device_id *pid)
{
int error;
- sb_t *chip;
- snd_card_t *card;
+ struct snd_sb *chip;
+ struct snd_card *card;
struct snd_card_als100 *acard;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_als100))) == NULL)
return -ENOMEM;
- acard = (struct snd_card_als100 *)card->private_data;
+ acard = card->private_data;
if ((error = snd_card_als100_pnp(dev, acard, pcard, pid))) {
snd_card_free(card);
@@ -228,6 +229,7 @@ static int __init snd_card_als100_probe(int dev,
snd_card_free(card);
return error;
}
+ acard->chip = chip;
strcpy(card->driver, "ALS100");
strcpy(card->shortname, "Avance Logic ALS100");
@@ -299,32 +301,61 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_als100 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
}
+static int snd_als100_pnp_resume(struct pnp_card_link *pcard)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_als100 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pnp_card_driver als100_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "als100",
.id_table = snd_als100_pnpids,
.probe = snd_als100_pnp_detect,
.remove = __devexit_p(snd_als100_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_als100_pnp_suspend,
+ .resume = snd_als100_pnp_resume,
+#endif
};
static int __init alsa_card_als100_init(void)
{
- int cards = 0;
+ int cards;
- cards += pnp_register_card_driver(&als100_pnpc_driver);
-#ifdef MODULE
- if (!cards) {
+ cards = pnp_register_card_driver(&als100_pnpc_driver);
+ if (cards <= 0) {
pnp_unregister_card_driver(&als100_pnpc_driver);
+#ifdef MODULE
snd_printk(KERN_ERR "no ALS100 based soundcards found\n");
- }
#endif
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_als100_exit(void)
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index bb41c6ec2f43..a530691bf4f7 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -93,6 +93,7 @@ struct snd_card_azt2320 {
int dev_no;
struct pnp_dev *dev;
struct pnp_dev *devmpu;
+ struct snd_cs4231 *chip;
};
static struct pnp_card_device_id snd_azt2320_pnpids[] = {
@@ -227,10 +228,10 @@ static int __devinit snd_card_azt2320_probe(int dev,
const struct pnp_card_device_id *pid)
{
int error;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_card_azt2320 *acard;
- cs4231_t *chip;
- opl3_t *opl3;
+ struct snd_cs4231 *chip;
+ struct snd_opl3 *opl3;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_azt2320))) == NULL)
@@ -329,32 +330,59 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card,
static void __devexit snd_azt2320_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_azt2320 *acard = card->private_data;
+ struct snd_cs4231 *chip = acard->chip;
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip->suspend(chip);
+ return 0;
}
+static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_azt2320 *acard = card->private_data;
+ struct snd_cs4231 *chip = acard->chip;
+
+ chip->resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pnp_card_driver azt2320_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "azt2320",
.id_table = snd_azt2320_pnpids,
.probe = snd_azt2320_pnp_detect,
.remove = __devexit_p(snd_azt2320_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_azt2320_pnp_suspend,
+ .resume = snd_azt2320_pnp_resume,
+#endif
};
static int __init alsa_card_azt2320_init(void)
{
- int cards = 0;
+ int cards;
- cards += pnp_register_card_driver(&azt2320_pnpc_driver);
-#ifdef MODULE
- if (!cards) {
+ cards = pnp_register_card_driver(&azt2320_pnpc_driver);
+ if (cards <= 0) {
pnp_unregister_card_driver(&azt2320_pnpc_driver);
+#ifdef MODULE
snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
- }
#endif
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_azt2320_exit(void)
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 5252206ea388..bd8e23818460 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -45,6 +45,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
@@ -106,6 +108,9 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
module_param_array(wssdma, int, NULL, 0444);
MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
#define CMI8330_RMUX3D 16
#define CMI8330_MUTEMUX 17
#define CMI8330_OUTPUTVOL 18
@@ -137,27 +142,25 @@ static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
0x0 /* 26 - cd-in rec gain */
};
-typedef int (*snd_pcm_open_callback_t)(snd_pcm_substream_t *);
+typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *);
struct snd_cmi8330 {
#ifdef CONFIG_PNP
struct pnp_dev *cap;
struct pnp_dev *play;
#endif
- snd_card_t *card;
- ad1848_t *wss;
- sb_t *sb;
+ struct snd_card *card;
+ struct snd_ad1848 *wss;
+ struct snd_sb *sb;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
struct snd_cmi8330_stream {
- snd_pcm_ops_t ops;
+ struct snd_pcm_ops ops;
snd_pcm_open_callback_t open;
void *private_data; /* sb or wss */
} streams[2];
};
-static snd_card_t *snd_cmi8330_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
#ifdef CONFIG_PNP
static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
@@ -231,7 +234,7 @@ static unsigned char cmi8330_sb_init_values[][2] __initdata = {
};
-static int __devinit cmi8330_add_sb_mixers(sb_t *chip)
+static int __devinit cmi8330_add_sb_mixers(struct snd_sb *chip)
{
int idx, err;
unsigned long flags;
@@ -256,7 +259,7 @@ static int __devinit cmi8330_add_sb_mixers(sb_t *chip)
}
#endif
-static int __devinit snd_cmi8330_mixer(snd_card_t *card, struct snd_cmi8330 *acard)
+static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 *acard)
{
unsigned int idx;
int err;
@@ -370,7 +373,7 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
#define CMI_AD_STREAM SNDRV_PCM_STREAM_PLAYBACK
#endif
-static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
+static int snd_cmi8330_playback_open(struct snd_pcm_substream *substream)
{
struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
@@ -379,7 +382,7 @@ static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
return chip->streams[SNDRV_PCM_STREAM_PLAYBACK].open(substream);
}
-static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream)
+static int snd_cmi8330_capture_open(struct snd_pcm_substream *substream)
{
struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
@@ -388,15 +391,10 @@ static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream)
return chip->streams[SNDRV_PCM_STREAM_CAPTURE].open(substream);
}
-static void snd_cmi8330_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
-{
- snd_pcm_t *pcm;
- const snd_pcm_ops_t *ops;
+ struct snd_pcm *pcm;
+ const struct snd_pcm_ops *ops;
int err;
static snd_pcm_open_callback_t cmi_open_callbacks[2] = {
snd_cmi8330_playback_open,
@@ -407,7 +405,6 @@ static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
return err;
strcpy(pcm->name, "CMI8330");
pcm->private_data = chip;
- pcm->private_free = snd_cmi8330_pcm_free;
/* SB16 */
ops = snd_sb16dsp_get_pcm_ops(CMI_SB_STREAM);
@@ -435,6 +432,31 @@ static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
}
+#ifdef CONFIG_PM
+static int snd_cmi8330_suspend(struct snd_card *card)
+{
+ struct snd_cmi8330 *acard = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(acard->pcm);
+ acard->wss->suspend(acard->wss);
+ snd_sbmixer_suspend(acard->sb);
+ return 0;
+}
+
+static int snd_cmi8330_resume(struct snd_card *card)
+{
+ struct snd_cmi8330 *acard = card->private_data;
+
+ snd_sbdsp_reset(acard->sb);
+ snd_sbmixer_suspend(acard->sb);
+ acard->wss->resume(acard->wss);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+
/*
*/
@@ -446,44 +468,28 @@ static int __devinit snd_cmi8330_pcm(snd_card_t *card, struct snd_cmi8330 *chip)
#define PFX "cmi8330: "
-static int __devinit snd_cmi8330_probe(int dev,
- struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static struct snd_card *snd_cmi8330_card_new(int dev)
{
- snd_card_t *card;
+ struct snd_card *card;
struct snd_cmi8330 *acard;
- int i, err;
-
- if (! is_isapnp_selected(dev)) {
- if (wssport[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify wssport\n");
- return -EINVAL;
- }
- if (sbport[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify sbport\n");
- return -EINVAL;
- }
- }
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_cmi8330));
if (card == NULL) {
snd_printk(KERN_ERR PFX "could not get a new card\n");
- return -ENOMEM;
+ return NULL;
}
- acard = (struct snd_cmi8330 *)card->private_data;
+ acard = card->private_data;
acard->card = card;
+ return card;
+}
-#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if ((err = snd_cmi8330_pnp(dev, acard, pcard, pid)) < 0) {
- snd_printk(KERN_ERR PFX "PnP detection failed\n");
- goto _err;
- }
- snd_card_set_dev(card, &pcard->card->dev);
- }
-#endif
+static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
+{
+ struct snd_cmi8330 *acard;
+ int i, err;
+ acard = card->private_data;
if ((err = snd_ad1848_create(card,
wssport[dev] + 4,
wssirq[dev],
@@ -491,12 +497,11 @@ static int __devinit snd_cmi8330_probe(int dev,
AD1848_HW_DETECT,
&acard->wss)) < 0) {
snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
- goto _err;
+ return err;
}
if (acard->wss->hardware != AD1848_HW_CMI8330) {
snd_printk(KERN_ERR PFX "(AD1848) not found during probe\n");
- err = -ENODEV;
- goto _err;
+ return -ENODEV;
}
if ((err = snd_sbdsp_create(card, sbport[dev],
@@ -506,11 +511,11 @@ static int __devinit snd_cmi8330_probe(int dev,
sbdma16[dev],
SB_HW_AUTO, &acard->sb)) < 0) {
snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
- goto _err;
+ return err;
}
if (acard->sb->hardware != SB_HW_16) {
snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
- goto _err;
+ return err;
}
snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
@@ -519,12 +524,12 @@ static int __devinit snd_cmi8330_probe(int dev,
if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
snd_printk(KERN_ERR PFX "failed to create mixers\n");
- goto _err;
+ return err;
}
if ((err = snd_cmi8330_pcm(card, acard)) < 0) {
snd_printk(KERN_ERR PFX "failed to create pcms\n");
- goto _err;
+ return err;
}
strcpy(card->driver, "CMI8330/C3D");
@@ -535,49 +540,120 @@ static int __devinit snd_cmi8330_probe(int dev,
wssirq[dev],
wssdma[dev]);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ return snd_card_register(card);
+}
- if ((err = snd_card_register(card)) < 0)
- goto _err;
+static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
+{
+ struct snd_card *card;
+ int err;
+ int dev = pdev->id;
+
+ if (wssport[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify wssport\n");
+ return -EINVAL;
+ }
+ if (sbport[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify sbport\n");
+ return -EINVAL;
+ }
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_cmi8330_legacy[dev] = card;
+ card = snd_cmi8330_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_cmi8330_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ platform_set_drvdata(pdev, card);
return 0;
+}
- _err:
- snd_card_free(card);
- return err;
+static int snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
}
+#ifdef CONFIG_PM
+static int snd_cmi8330_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return snd_cmi8330_suspend(platform_get_drvdata(dev));
+}
+
+static int snd_cmi8330_nonpnp_resume(struct platform_device *dev)
+{
+ return snd_cmi8330_resume(platform_get_drvdata(dev));
+}
+#endif
+
+#define CMI8330_DRIVER "snd_cmi8330"
+
+static struct platform_driver snd_cmi8330_driver = {
+ .probe = snd_cmi8330_nonpnp_probe,
+ .remove = snd_cmi8330_nonpnp_remove,
+#ifdef CONFIG_PM
+ .suspend = snd_cmi8330_nonpnp_suspend,
+ .resume = snd_cmi8330_nonpnp_resume,
+#endif
+ .driver = {
+ .name = CMI8330_DRIVER
+ },
+};
+
+
#ifdef CONFIG_PNP
-static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
+ struct snd_card *card;
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_cmi8330_probe(dev, card, id);
- if (res < 0)
- return res;
- dev++;
- return 0;
+ if (enable[dev] && isapnp[dev])
+ break;
}
- return -ENODEV;
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_cmi8330_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ if ((res = snd_cmi8330_pnp(dev, card->private_data, pcard, pid)) < 0) {
+ snd_printk(KERN_ERR PFX "PnP detection failed\n");
+ snd_card_free(card);
+ return res;
+ }
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((res = snd_cmi8330_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return res;
+ }
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
static void __devexit snd_cmi8330_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_cmi8330_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ return snd_cmi8330_suspend(pnp_get_card_drvdata(pcard));
+}
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+static int snd_cmi8330_pnp_resume(struct pnp_card_link *pcard)
+{
+ return snd_cmi8330_resume(pnp_get_card_drvdata(pcard));
}
+#endif
static struct pnp_card_driver cmi8330_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
@@ -585,47 +661,68 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
.id_table = snd_cmi8330_pnpids,
.probe = snd_cmi8330_pnp_detect,
.remove = __devexit_p(snd_cmi8330_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cmi8330_pnp_suspend,
+ .resume = snd_cmi8330_pnp_resume,
+#endif
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_cmi8330_unregister_all(void)
+{
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_card_driver(&cmi8330_pnpc_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_cmi8330_driver);
+}
+
static int __init alsa_card_cmi8330_init(void)
{
- int dev, cards = 0;
+ int i, err, cards = 0;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev])
- continue;
- if (is_isapnp_selected(dev))
+ if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ if (is_isapnp_selected(i))
continue;
- if (snd_cmi8330_probe(dev, NULL, NULL) >= 0)
- cards++;
+ device = platform_device_register_simple(CMI8330_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ cards++;
+ }
+
+ err = pnp_register_card_driver(&cmi8330_pnpc_driver);
+ if (err >= 0) {
+ pnp_registered = 1;
+ cards += err;
}
-#ifdef CONFIG_PNP
- cards += pnp_register_card_driver(&cmi8330_pnpc_driver);
-#endif
if (!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&cmi8330_pnpc_driver);
-#endif
#ifdef MODULE
snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_cmi8330_unregister_all();
+ return err;
}
static void __exit alsa_card_cmi8330_exit(void)
{
- int i;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&cmi8330_pnpc_driver);
-#endif
- for (i = 0; i < SNDRV_CARDS; i++)
- snd_card_free(snd_cmi8330_legacy[i]);
+ snd_cmi8330_unregister_all();
}
module_init(alsa_card_cmi8330_init)
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 9be5416bcb92..ab67b5c2590d 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -22,6 +22,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
@@ -64,15 +66,15 @@ MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
-static snd_card_t *snd_cs4231_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
-static int __init snd_card_cs4231_probe(int dev)
+static int __init snd_cs4231_probe(struct platform_device *pdev)
{
- snd_card_t *card;
- struct snd_card_cs4231 *acard;
- snd_pcm_t *pcm = NULL;
- cs4231_t *chip;
+ int dev = pdev->id;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_cs4231 *chip;
int err;
if (port[dev] == SNDRV_AUTO_PORT) {
@@ -90,7 +92,6 @@ static int __init snd_card_cs4231_probe(int dev)
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- acard = (struct snd_card_cs4231 *)card->private_data;
if ((err = snd_cs4231_create(card, port[dev], -1,
irq[dev],
dma1[dev],
@@ -98,6 +99,7 @@ static int __init snd_card_cs4231_probe(int dev)
CS4231_HW_DETECT,
0, &chip)) < 0)
goto _err;
+ card->private_data = chip;
if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
goto _err;
@@ -125,12 +127,12 @@ static int __init snd_card_cs4231_probe(int dev)
printk(KERN_WARNING "cs4231: MPU401 not detected\n");
}
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_cs4231_cards[dev] = card;
+
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -138,29 +140,97 @@ static int __init snd_card_cs4231_probe(int dev)
return err;
}
-static int __init alsa_card_cs4231_init(void)
+static int __devexit snd_cs4231_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_cs4231_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct snd_card *card;
+ struct snd_cs4231 *chip;
+ card = platform_get_drvdata(dev);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip = card->private_data;
+ chip->suspend(chip);
+ return 0;
+}
+
+static int snd_cs4231_resume(struct platform_device *dev)
+{
+ struct snd_card *card;
+ struct snd_cs4231 *chip;
+ card = platform_get_drvdata(dev);
+ chip = card->private_data;
+ chip->resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+#define SND_CS4231_DRIVER "snd_cs4231"
+
+static struct platform_driver snd_cs4231_driver = {
+ .probe = snd_cs4231_probe,
+ .remove = __devexit_p(snd_cs4231_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cs4231_suspend,
+ .resume = snd_cs4231_resume,
+#endif
+ .driver = {
+ .name = SND_CS4231_DRIVER
+ },
+};
+
+static void __init_or_module snd_cs4231_unregister_all(void)
{
- int dev, cards;
+ int i;
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (snd_card_cs4231_probe(dev) >= 0)
- cards++;
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_cs4231_driver);
+}
+
+static int __init alsa_card_cs4231_init(void)
+{
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_cs4231_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_CS4231_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
}
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_cs4231_unregister_all();
+ return err;
}
static void __exit alsa_card_cs4231_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_cs4231_cards[idx]);
+ snd_cs4231_unregister_all();
}
module_init(alsa_card_cs4231_init)
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 4af769030beb..eab7eb59b5f7 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -73,13 +73,13 @@ static unsigned int rates[14] = {
27042, 32000, 33075, 37800, 44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = 14,
.list = rates,
.mask = 0,
};
-static int snd_cs4231_xrate(snd_pcm_runtime_t *runtime)
+static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
{
return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
}
@@ -124,49 +124,17 @@ static unsigned char snd_cs4231_original_image[32] =
* Basic I/O functions
*/
-#if !defined(EBUS_SUPPORT) && !defined(SBUS_SUPPORT)
-#define __CS4231_INLINE__ inline
-#else
-#define __CS4231_INLINE__ /* nothing */
-#endif
-
-static __CS4231_INLINE__ void cs4231_outb(cs4231_t *chip, u8 offset, u8 val)
+static inline void cs4231_outb(struct snd_cs4231 *chip, u8 offset, u8 val)
{
-#ifdef EBUS_SUPPORT
- if (chip->ebus->flag) {
- writeb(val, chip->port + (offset << 2));
- } else {
-#endif
-#ifdef SBUS_SUPPORT
- sbus_writeb(val, chip->port + (offset << 2));
-#endif
-#ifdef EBUS_SUPPORT
- }
-#endif
-#ifdef LEGACY_SUPPORT
outb(val, chip->port + offset);
-#endif
}
-static __CS4231_INLINE__ u8 cs4231_inb(cs4231_t *chip, u8 offset)
+static inline u8 cs4231_inb(struct snd_cs4231 *chip, u8 offset)
{
-#ifdef EBUS_SUPPORT
- if (chip->ebus_flag) {
- return readb(chip->port + (offset << 2));
- } else {
-#endif
-#ifdef SBUS_SUPPORT
- return sbus_readb(chip->port + (offset << 2));
-#endif
-#ifdef EBUS_SUPPORT
- }
-#endif
-#ifdef LEGACY_SUPPORT
return inb(chip->port + offset);
-#endif
}
-static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
+static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
int timeout;
@@ -193,7 +161,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
}
}
-static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
{
int timeout;
@@ -206,7 +174,7 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
mb();
}
-void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
+void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
{
int timeout;
@@ -227,7 +195,7 @@ void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
#endif
}
-unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
+unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
{
int timeout;
@@ -244,7 +212,7 @@ unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
return cs4231_inb(chip, CS4231P(REG));
}
-void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
+void snd_cs4236_ext_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val)
{
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
@@ -255,7 +223,7 @@ void snd_cs4236_ext_out(cs4231_t *chip, unsigned char reg, unsigned char val)
#endif
}
-unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
+unsigned char snd_cs4236_ext_in(struct snd_cs4231 *chip, unsigned char reg)
{
cs4231_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
cs4231_outb(chip, CS4231P(REG), reg | (chip->image[CS4236_EXT_REG] & 0x01));
@@ -273,7 +241,7 @@ unsigned char snd_cs4236_ext_in(cs4231_t *chip, unsigned char reg)
#if 0
-static void snd_cs4231_debug(cs4231_t *chip)
+static void snd_cs4231_debug(struct snd_cs4231 *chip)
{
printk("CS4231 REGS: INDEX = 0x%02x ", cs4231_inb(chip, CS4231P(REGSEL)));
printk(" STATUS = 0x%02x\n", cs4231_inb(chip, CS4231P(STATUS)));
@@ -317,7 +285,7 @@ static void snd_cs4231_debug(cs4231_t *chip)
* CS4231 detection / MCE routines
*/
-static void snd_cs4231_busy_wait(cs4231_t *chip)
+static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
{
int timeout;
@@ -331,7 +299,7 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
udelay(10);
}
-void snd_cs4231_mce_up(cs4231_t *chip)
+void snd_cs4231_mce_up(struct snd_cs4231 *chip)
{
unsigned long flags;
int timeout;
@@ -352,7 +320,7 @@ void snd_cs4231_mce_up(cs4231_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-void snd_cs4231_mce_down(cs4231_t *chip)
+void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{
unsigned long flags;
int timeout;
@@ -431,14 +399,14 @@ static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size
return size;
}
-static int snd_cs4231_trigger(snd_pcm_substream_t *substream,
+static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
int result = 0;
unsigned int what;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
int do_start;
#if 0
@@ -500,7 +468,7 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate)
return freq_bits[13];
}
-static unsigned char snd_cs4231_get_format(cs4231_t *chip,
+static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip,
int format,
int channels)
{
@@ -522,7 +490,7 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip,
return rformat;
}
-static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
+static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
{
unsigned long flags;
@@ -556,8 +524,8 @@ static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4231_playback_format(cs4231_t *chip,
- snd_pcm_hw_params_t *params,
+static void snd_cs4231_playback_format(struct snd_cs4231 *chip,
+ struct snd_pcm_hw_params *params,
unsigned char pdfr)
{
unsigned long flags;
@@ -595,8 +563,8 @@ static void snd_cs4231_playback_format(cs4231_t *chip,
up(&chip->mce_mutex);
}
-static void snd_cs4231_capture_format(cs4231_t *chip,
- snd_pcm_hw_params_t *params,
+static void snd_cs4231_capture_format(struct snd_cs4231 *chip,
+ struct snd_pcm_hw_params *params,
unsigned char cdfr)
{
unsigned long flags;
@@ -642,20 +610,20 @@ static void snd_cs4231_capture_format(cs4231_t *chip,
* Timer interface
*/
-static unsigned long snd_cs4231_timer_resolution(snd_timer_t * timer)
+static unsigned long snd_cs4231_timer_resolution(struct snd_timer * timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
if (chip->hardware & CS4231_HW_CS4236B_MASK)
return 14467;
else
return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
}
-static int snd_cs4231_timer_start(snd_timer_t * timer)
+static int snd_cs4231_timer_start(struct snd_timer * timer)
{
unsigned long flags;
unsigned int ticks;
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->reg_lock, flags);
ticks = timer->sticks;
if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
@@ -669,17 +637,17 @@ static int snd_cs4231_timer_start(snd_timer_t * timer)
return 0;
}
-static int snd_cs4231_timer_stop(snd_timer_t * timer)
+static int snd_cs4231_timer_stop(struct snd_timer * timer)
{
unsigned long flags;
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->reg_lock, flags);
snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
-static void snd_cs4231_init(cs4231_t *chip)
+static void snd_cs4231_init(struct snd_cs4231 *chip)
{
unsigned long flags;
@@ -737,7 +705,7 @@ static void snd_cs4231_init(cs4231_t *chip)
#endif
}
-static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
+static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
{
unsigned long flags;
@@ -773,7 +741,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
return 0;
}
-static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
+static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
{
unsigned long flags;
@@ -824,21 +792,21 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
* timer open/close
*/
-static int snd_cs4231_timer_open(snd_timer_t * timer)
+static int snd_cs4231_timer_open(struct snd_timer * timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
snd_cs4231_open(chip, CS4231_MODE_TIMER);
return 0;
}
-static int snd_cs4231_timer_close(snd_timer_t * timer)
+static int snd_cs4231_timer_close(struct snd_timer * timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
snd_cs4231_close(chip, CS4231_MODE_TIMER);
return 0;
}
-static struct _snd_timer_hardware snd_cs4231_timer_table =
+static struct snd_timer_hardware snd_cs4231_timer_table =
{
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 9945,
@@ -854,10 +822,10 @@ static struct _snd_timer_hardware snd_cs4231_timer_table =
* ok.. exported functions..
*/
-static int snd_cs4231_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
unsigned char new_pdfr;
int err;
@@ -869,16 +837,15 @@ static int snd_cs4231_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_cs4231_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-#ifdef LEGACY_SUPPORT
-static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -896,12 +863,11 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t * substream)
#endif
return 0;
}
-#endif /* LEGACY_SUPPORT */
-static int snd_cs4231_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
unsigned char new_cdfr;
int err;
@@ -913,16 +879,15 @@ static int snd_cs4231_capture_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_cs4231_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-#ifdef LEGACY_SUPPORT
-static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -942,9 +907,8 @@ static int snd_cs4231_capture_prepare(snd_pcm_substream_t * substream)
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
-#endif
-static void snd_cs4231_overrange(cs4231_t *chip)
+static void snd_cs4231_overrange(struct snd_cs4231 *chip)
{
unsigned long flags;
unsigned char res;
@@ -958,7 +922,7 @@ static void snd_cs4231_overrange(cs4231_t *chip)
irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- cs4231_t *chip = dev_id;
+ struct snd_cs4231 *chip = dev_id;
unsigned char status;
status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
@@ -998,10 +962,9 @@ irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-#ifdef LEGACY_SUPPORT
-static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
@@ -1010,9 +973,9 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t * subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
@@ -1020,13 +983,12 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
return bytes_to_frames(substream->runtime, ptr);
}
-#endif /* LEGACY_SUPPORT */
/*
*/
-static int snd_cs4231_probe(cs4231_t *chip)
+static int snd_cs4231_probe(struct snd_cs4231 *chip)
{
unsigned long flags;
int i, id, rev;
@@ -1190,7 +1152,7 @@ static int snd_cs4231_probe(cs4231_t *chip)
*/
-static snd_pcm_hardware_t snd_cs4231_playback =
+static struct snd_pcm_hardware snd_cs4231_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1211,7 +1173,7 @@ static snd_pcm_hardware_t snd_cs4231_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_cs4231_capture =
+static struct snd_pcm_hardware snd_cs4231_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1236,10 +1198,10 @@ static snd_pcm_hardware_t snd_cs4231_capture =
*/
-static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
+static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
runtime->hw = snd_cs4231_playback;
@@ -1253,7 +1215,6 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
-#ifdef LEGACY_SUPPORT
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
@@ -1261,29 +1222,23 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t * substream)
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
return err;
}
-#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
-#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma1);
-#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->playback_substream = substream;
-#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
- chip->p_periods_sent = 0;
-#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
}
-static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
+static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
runtime->hw = snd_cs4231_capture;
@@ -1293,7 +1248,6 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
chip->hardware == CS4231_HW_CS4239)
runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
-#ifdef LEGACY_SUPPORT
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
@@ -1301,37 +1255,31 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t * substream)
if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
return err;
}
-#endif
if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
-#ifdef LEGACY_SUPPORT
if (chip->release_dma)
chip->release_dma(chip, chip->dma_private_data, chip->dma2);
-#endif
snd_free_pages(runtime->dma_area, runtime->dma_bytes);
return err;
}
chip->capture_substream = substream;
-#if defined(SBUS_SUPPORT) || defined(EBUS_SUPPORT)
- chip->c_periods_sent = 0;
-#endif
snd_pcm_set_sync(substream);
chip->rate_constraint(runtime);
return 0;
}
-static int snd_cs4231_playback_close(snd_pcm_substream_t * substream)
+static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
snd_cs4231_close(chip, CS4231_MODE_PLAY);
return 0;
}
-static int snd_cs4231_capture_close(snd_pcm_substream_t * substream)
+static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
snd_cs4231_close(chip, CS4231_MODE_RECORD);
@@ -1341,13 +1289,12 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t * substream)
#ifdef CONFIG_PM
/* lowlevel suspend callback for CS4231 */
-static void snd_cs4231_suspend(cs4231_t *chip)
+static void snd_cs4231_suspend(struct snd_cs4231 *chip)
{
int reg;
unsigned long flags;
- if (chip->pcm)
- snd_pcm_suspend_all(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);
@@ -1355,11 +1302,11 @@ static void snd_cs4231_suspend(cs4231_t *chip)
}
/* lowlevel resume callback for CS4231 */
-static void snd_cs4231_resume(cs4231_t *chip)
+static void snd_cs4231_resume(struct snd_cs4231 *chip)
{
int reg;
unsigned long flags;
- int timeout;
+ /* int timeout; */
snd_cs4231_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1373,7 +1320,7 @@ static void snd_cs4231_resume(cs4231_t *chip)
}
}
spin_unlock_irqrestore(&chip->reg_lock, flags);
-#if 0
+#if 1
snd_cs4231_mce_down(chip);
#else
/* The following is a workaround to avoid freeze after resume on TP600E.
@@ -1395,27 +1342,9 @@ static void snd_cs4231_resume(cs4231_t *chip)
snd_cs4231_busy_wait(chip);
#endif
}
-
-static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state)
-{
- cs4231_t *chip = card->pm_private_data;
- if (chip->suspend)
- chip->suspend(chip);
- return 0;
-}
-
-static int snd_cs4231_pm_resume(snd_card_t *card)
-{
- cs4231_t *chip = card->pm_private_data;
- if (chip->resume)
- chip->resume(chip);
- return 0;
-}
#endif /* CONFIG_PM */
-#ifdef LEGACY_SUPPORT
-
-static int snd_cs4231_free(cs4231_t *chip)
+static int snd_cs4231_free(struct snd_cs4231 *chip)
{
release_and_free_resource(chip->res_port);
release_and_free_resource(chip->res_cport);
@@ -1438,15 +1367,13 @@ static int snd_cs4231_free(cs4231_t *chip)
return 0;
}
-static int snd_cs4231_dev_free(snd_device_t *device)
+static int snd_cs4231_dev_free(struct snd_device *device)
{
- cs4231_t *chip = device->device_data;
+ struct snd_cs4231 *chip = device->device_data;
return snd_cs4231_free(chip);
}
-#endif /* LEGACY_SUPPORT */
-
-const char *snd_cs4231_chip_id(cs4231_t *chip)
+const char *snd_cs4231_chip_id(struct snd_cs4231 *chip)
{
switch (chip->hardware) {
case CS4231_HW_CS4231: return "CS4231";
@@ -1466,12 +1393,12 @@ const char *snd_cs4231_chip_id(cs4231_t *chip)
}
}
-static int snd_cs4231_new(snd_card_t * card,
+static int snd_cs4231_new(struct snd_card *card,
unsigned short hardware,
unsigned short hwshare,
- cs4231_t ** rchip)
+ struct snd_cs4231 ** rchip)
{
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
*rchip = NULL;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -1493,20 +1420,18 @@ static int snd_cs4231_new(snd_card_t * card,
return 0;
}
-#ifdef LEGACY_SUPPORT
-
-int snd_cs4231_create(snd_card_t * card,
+int snd_cs4231_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
int irq, int dma1, int dma2,
unsigned short hardware,
unsigned short hwshare,
- cs4231_t ** rchip)
+ struct snd_cs4231 ** rchip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_cs4231_dev_free,
};
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
int err;
err = snd_cs4231_new(card, hardware, hwshare, &chip);
@@ -1559,10 +1484,12 @@ int snd_cs4231_create(snd_card_t * card,
}
snd_cs4231_init(chip);
+#if 0
if (chip->hardware & CS4231_HW_CS4232_MASK) {
if (chip->res_cport == NULL)
snd_printk("CS4232 control port features are not accessible\n");
}
+#endif
/* Register device */
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
@@ -1574,16 +1501,13 @@ int snd_cs4231_create(snd_card_t * card,
/* Power Management */
chip->suspend = snd_cs4231_suspend;
chip->resume = snd_cs4231_resume;
- snd_card_set_isa_pm_callback(card, snd_cs4231_pm_suspend, snd_cs4231_pm_resume, chip);
#endif
*rchip = chip;
return 0;
}
-#endif /* LEGACY_SUPPORT */
-
-static snd_pcm_ops_t snd_cs4231_playback_ops = {
+static struct snd_pcm_ops snd_cs4231_playback_ops = {
.open = snd_cs4231_playback_open,
.close = snd_cs4231_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1594,7 +1518,7 @@ static snd_pcm_ops_t snd_cs4231_playback_ops = {
.pointer = snd_cs4231_playback_pointer,
};
-static snd_pcm_ops_t snd_cs4231_capture_ops = {
+static struct snd_pcm_ops snd_cs4231_capture_ops = {
.open = snd_cs4231_capture_open,
.close = snd_cs4231_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1605,16 +1529,9 @@ static snd_pcm_ops_t snd_cs4231_capture_ops = {
.pointer = snd_cs4231_capture_pointer,
};
-static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
+int snd_cs4231_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm)
{
- cs4231_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)
@@ -1629,7 +1546,6 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
/* global setup */
pcm->private_data = chip;
- pcm->private_free = snd_cs4231_pcm_free;
pcm->info_flags = 0;
if (chip->single_dma)
pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
@@ -1637,27 +1553,9 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, snd_cs4231_chip_id(chip));
-#ifdef LEGACY_SUPPORT
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_isa_data(),
64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
-#else
-# ifdef EBUS_SUPPORT
- if (chip->ebus_flag) {
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- chip->dev_u.pdev,
- 64*1024, 128*1024);
- } else {
-# endif
-# ifdef SBUS_SUPPORT
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
- chip->dev_u.sdev,
- 64*1024, 128*1024);
-# endif
-# ifdef EBUS_SUPPORT
- }
-# endif
-#endif
chip->pcm = pcm;
if (rpcm)
@@ -1665,16 +1563,16 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
return 0;
}
-static void snd_cs4231_timer_free(snd_timer_t *timer)
+static void snd_cs4231_timer_free(struct snd_timer *timer)
{
- cs4231_t *chip = timer->private_data;
+ struct snd_cs4231 *chip = timer->private_data;
chip->timer = NULL;
}
-int snd_cs4231_timer(cs4231_t *chip, int device, snd_timer_t **rtimer)
+int snd_cs4231_timer(struct snd_cs4231 *chip, int device, struct snd_timer **rtimer)
{
- snd_timer_t *timer;
- snd_timer_id_t tid;
+ struct snd_timer *timer;
+ struct snd_timer_id tid;
int err;
/* Timer initialization */
@@ -1699,7 +1597,7 @@ int snd_cs4231_timer(cs4231_t *chip, int device, snd_timer_t **rtimer)
* MIXER part
*/
-static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Line", "Aux", "Mic", "Mix"
@@ -1711,7 +1609,7 @@ static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
"Line", "Synth", "Mic", "Mix"
};
char **ptexts = texts;
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
snd_assert(chip->card != NULL, return -EINVAL);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1729,9 +1627,9 @@ static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_cs4231_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1741,9 +1639,9 @@ static int snd_cs4231_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_cs4231_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short left, right;
int change;
@@ -1764,7 +1662,7 @@ static int snd_cs4231_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return change;
}
-int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_cs4231_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1775,9 +1673,9 @@ int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo
return 0;
}
-int snd_cs4231_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1792,9 +1690,9 @@ int snd_cs4231_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
return 0;
}
-int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1815,7 +1713,7 @@ int snd_cs4231_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
return change;
}
-int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_cs4231_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1826,9 +1724,9 @@ int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo
return 0;
}
-int snd_cs4231_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1848,9 +1746,9 @@ int snd_cs4231_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
return 0;
}
-int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1879,7 +1777,7 @@ int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
return change;
}
-static snd_kcontrol_new_t snd_cs4231_controls[] = {
+static struct snd_kcontrol_new snd_cs4231_controls[] = {
CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
@@ -1905,9 +1803,9 @@ CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1)
};
-int snd_cs4231_mixer(cs4231_t *chip)
+int snd_cs4231_mixer(struct snd_cs4231 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx;
int err;
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index d60a55e6a0b1..e1683337e6cd 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -21,6 +21,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
@@ -122,7 +124,14 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnpc_registered;
+#ifdef CS4232
+static int pnp_registered;
+#endif
+
struct snd_card_cs4236 {
+ struct snd_cs4231 *chip;
struct resource *res_sb_port;
#ifdef CONFIG_PNP
struct pnp_dev *wss;
@@ -131,33 +140,26 @@ struct snd_card_cs4236 {
#endif
};
-static snd_card_t *snd_cs4236_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
#ifdef CONFIG_PNP
-#define ISAPNP_CS4232(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
- { \
- ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
- .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
- ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
- ISAPNP_DEVICE_ID(_va, _vb, _vc, _mpu401) } \
- }
-#define ISAPNP_CS4232_1(_va, _vb, _vc, _device, _wss, _ctrl, _mpu401) \
- { \
- ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
- .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
- ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl), \
- ISAPNP_DEVICE_ID('P', 'N', 'P', _mpu401) } \
- }
-#define ISAPNP_CS4232_WOMPU(_va, _vb, _vc, _device, _wss, _ctrl) \
- { \
- ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
- .devs = { ISAPNP_DEVICE_ID(_va, _vb, _vc, _wss), \
- ISAPNP_DEVICE_ID(_va, _vb, _vc, _ctrl) } \
- }
-
+#ifdef CS4232
+/*
+ * PNP BIOS
+ */
+static const struct pnp_device_id snd_cs4232_pnpbiosids[] = {
+ { .id = "CSC0100" },
+ { .id = "CSC0000" },
+ /* Guillemot Turtlebeach something appears to be cs4232 compatible
+ * (untested) */
+ { .id = "GIM0100" },
+ { .id = "" }
+};
+MODULE_DEVICE_TABLE(pnp, snd_cs4232_pnpbiosids);
+#endif /* CS4232 */
#ifdef CS4232
+#define CS423X_DRIVER "snd_cs4232"
+#define CS423X_ISAPNP_DRIVER "cs4232_isapnp"
static struct pnp_card_device_id snd_cs423x_pnpids[] = {
/* Philips PCA70PS */
{ .id = "CSC0d32", .devs = { { "CSC0000" }, { "CSC0010" }, { "PNPb006" } } },
@@ -177,6 +179,8 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
{ .id = "" } /* end */
};
#else /* CS4236 */
+#define CS423X_DRIVER "snd_cs4236"
+#define CS423X_ISAPNP_DRIVER "cs4236_isapnp"
static struct pnp_card_device_id snd_cs423x_pnpids[] = {
/* Intel Marlin Spike Motherboard - CS4235 */
{ .id = "CSC0225", .devs = { { "CSC0000" }, { "CSC0010" }, { "CSC0003" } } },
@@ -261,37 +265,12 @@ static struct pnp_card_device_id snd_cs423x_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, snd_cs423x_pnpids);
-static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
- struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+/* WSS initialization */
+static int __devinit snd_cs423x_pnp_init_wss(int dev, struct pnp_dev *pdev,
+ struct pnp_resource_table *cfg)
{
- struct pnp_dev *pdev;
- struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
int err;
- if (!cfg)
- return -ENOMEM;
-
- acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
- if (acard->wss == NULL) {
- kfree(cfg);
- return -EBUSY;
- }
- acard->ctrl = pnp_request_card_device(card, id->devs[1].id, NULL);
- if (acard->ctrl == NULL) {
- kfree(cfg);
- return -EBUSY;
- }
- if (id->devs[2].id[0]) {
- acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
- if (acard->mpu == NULL) {
- kfree(cfg);
- return -EBUSY;
- }
- }
-
- /* WSS initialization */
- pdev = acard->wss;
pnp_init_resource_table(cfg);
if (port[dev] != SNDRV_AUTO_PORT)
pnp_resource_change(&cfg->port_resource[0], port[dev], 4);
@@ -310,7 +289,6 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
snd_printk(KERN_ERR IDENT " WSS PnP manual resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
- kfree(cfg);
printk(KERN_ERR IDENT " WSS PnP configure failed for WSS (out of resources?)\n");
return -EBUSY;
}
@@ -325,63 +303,124 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
port[dev], fm_port[dev], sb_port[dev]);
snd_printdd("isapnp WSS: irq=%i, dma1=%i, dma2=%i\n",
irq[dev], dma1[dev], dma2[dev]);
- /* CTRL initialization */
- if (acard->ctrl && cport[dev] > 0) {
- pdev = acard->ctrl;
- pnp_init_resource_table(cfg);
- if (cport[dev] != SNDRV_AUTO_PORT)
- pnp_resource_change(&cfg->port_resource[0], cport[dev], 8);
- err = pnp_manual_config_dev(pdev, cfg, 0);
- if (err < 0)
- snd_printk(KERN_ERR IDENT " CTRL PnP manual resources are invalid, using auto config\n");
- err = pnp_activate_dev(pdev);
- if (err < 0) {
- kfree(cfg);
- printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
- return -EBUSY;
- }
- cport[dev] = pnp_port_start(pdev, 0);
- snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]);
+ return 0;
+}
+
+/* CTRL initialization */
+static int __devinit snd_cs423x_pnp_init_ctrl(int dev, struct pnp_dev *pdev,
+ struct pnp_resource_table *cfg)
+{
+ int err;
+
+ pnp_init_resource_table(cfg);
+ if (cport[dev] != SNDRV_AUTO_PORT)
+ pnp_resource_change(&cfg->port_resource[0], cport[dev], 8);
+ err = pnp_manual_config_dev(pdev, cfg, 0);
+ if (err < 0)
+ snd_printk(KERN_ERR IDENT " CTRL PnP manual resources are invalid, using auto config\n");
+ err = pnp_activate_dev(pdev);
+ if (err < 0) {
+ printk(KERN_ERR IDENT " CTRL PnP configure failed for WSS (out of resources?)\n");
+ return -EBUSY;
}
- /* MPU initialization */
- if (acard->mpu && mpu_port[dev] > 0) {
- pdev = acard->mpu;
- pnp_init_resource_table(cfg);
- if (mpu_port[dev] != SNDRV_AUTO_PORT)
- pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
- if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
- pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
- err = pnp_manual_config_dev(pdev, cfg, 0);
- if (err < 0)
- snd_printk(KERN_ERR IDENT " MPU401 PnP manual resources are invalid, using auto config\n");
- err = pnp_activate_dev(pdev);
- if (err < 0) {
- printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
- mpu_port[dev] = SNDRV_AUTO_PORT;
- mpu_irq[dev] = SNDRV_AUTO_IRQ;
+ cport[dev] = pnp_port_start(pdev, 0);
+ snd_printdd("isapnp CTRL: control port=0x%lx\n", cport[dev]);
+ return 0;
+}
+
+/* MPU initialization */
+static int __devinit snd_cs423x_pnp_init_mpu(int dev, struct pnp_dev *pdev,
+ struct pnp_resource_table *cfg)
+{
+ int err;
+
+ pnp_init_resource_table(cfg);
+ if (mpu_port[dev] != SNDRV_AUTO_PORT)
+ pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
+ if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
+ pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
+ err = pnp_manual_config_dev(pdev, cfg, 0);
+ if (err < 0)
+ snd_printk(KERN_ERR IDENT " MPU401 PnP manual resources are invalid, using auto config\n");
+ err = pnp_activate_dev(pdev);
+ if (err < 0) {
+ printk(KERN_ERR IDENT " MPU401 PnP configure failed for WSS (out of resources?)\n");
+ mpu_port[dev] = SNDRV_AUTO_PORT;
+ mpu_irq[dev] = SNDRV_AUTO_IRQ;
+ } else {
+ mpu_port[dev] = pnp_port_start(pdev, 0);
+ if (mpu_irq[dev] >= 0 &&
+ pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) {
+ mpu_irq[dev] = pnp_irq(pdev, 0);
} else {
- mpu_port[dev] = pnp_port_start(pdev, 0);
- if (mpu_irq[dev] >= 0 &&
- pnp_irq_valid(pdev, 0) && pnp_irq(pdev, 0) >= 0) {
- mpu_irq[dev] = pnp_irq(pdev, 0);
- } else {
- mpu_irq[dev] = -1; /* disable interrupt */
- }
+ mpu_irq[dev] = -1; /* disable interrupt */
}
- snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]);
+ }
+ snd_printdd("isapnp MPU: port=0x%lx, irq=%i\n", mpu_port[dev], mpu_irq[dev]);
+ return 0;
+}
+
+#ifdef CS4232
+static int __devinit snd_card_cs4232_pnp(int dev, struct snd_card_cs4236 *acard,
+ struct pnp_dev *pdev)
+{
+ struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+
+ if (!cfg)
+ return -ENOMEM;
+ if (snd_cs423x_pnp_init_wss(dev, acard->wss, cfg) < 0) {
+ kfree(cfg);
+ return -EBUSY;
}
kfree(cfg);
+ cport[dev] = -1;
return 0;
}
-#endif /* CONFIG_PNP */
+#endif
-static void snd_card_cs4236_free(snd_card_t *card)
+static int __devinit snd_card_cs423x_pnpc(int dev, struct snd_card_cs4236 *acard,
+ struct pnp_card_link *card,
+ const struct pnp_card_device_id *id)
{
- struct snd_card_cs4236 *acard = (struct snd_card_cs4236 *)card->private_data;
+ struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
+
+ if (!cfg)
+ return -ENOMEM;
+
+ acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL);
+ if (acard->wss == NULL)
+ goto error;
+ acard->ctrl = pnp_request_card_device(card, id->devs[1].id, NULL);
+ if (acard->ctrl == NULL)
+ goto error;
+ if (id->devs[2].id[0]) {
+ acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
+ if (acard->mpu == NULL)
+ goto error;
+ }
- if (acard)
- release_and_free_resource(acard->res_sb_port);
+ /* WSS initialization */
+ if (snd_cs423x_pnp_init_wss(dev, acard->wss, cfg) < 0)
+ goto error;
+
+ /* CTRL initialization */
+ if (acard->ctrl && cport[dev] > 0) {
+ if (snd_cs423x_pnp_init_ctrl(dev, acard->ctrl, cfg) < 0)
+ goto error;
+ }
+ /* MPU initialization */
+ if (acard->mpu && mpu_port[dev] > 0) {
+ if (snd_cs423x_pnp_init_mpu(dev, acard->ctrl, cfg) < 0)
+ goto error;
+ }
+ kfree(cfg);
+ return 0;
+
+ error:
+ kfree(cfg);
+ return -EBUSY;
}
+#endif /* CONFIG_PNP */
#ifdef CONFIG_PNP
#define is_isapnp_selected(dev) isapnp[dev]
@@ -389,46 +428,38 @@ static void snd_card_cs4236_free(snd_card_t *card)
#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)
+static void snd_card_cs4236_free(struct snd_card *card)
{
- snd_card_t *card;
- struct snd_card_cs4236 *acard;
- snd_pcm_t *pcm = NULL;
- cs4231_t *chip;
- opl3_t *opl3;
- int err;
+ struct snd_card_cs4236 *acard = card->private_data;
+
+ release_and_free_resource(acard->res_sb_port);
+}
+
+static struct snd_card *snd_cs423x_card_new(int dev)
+{
+ struct snd_card *card;
- if (! is_isapnp_selected(dev)) {
- if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR "specify port\n");
- return -EINVAL;
- }
- if (cport[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR "specify cport\n");
- return -EINVAL;
- }
- }
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_cs4236));
if (card == NULL)
- return -ENOMEM;
- acard = (struct snd_card_cs4236 *)card->private_data;
+ return NULL;
card->private_free = snd_card_cs4236_free;
-#ifdef CONFIG_PNP
- 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");
- goto _err;
- }
- snd_card_set_dev(card, &pcard->card->dev);
- }
-#endif
+ return card;
+}
+
+static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
+{
+ struct snd_card_cs4236 *acard;
+ struct snd_pcm *pcm;
+ struct snd_cs4231 *chip;
+ struct snd_opl3 *opl3;
+ int err;
+
+ acard = card->private_data;
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]);
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
#ifdef CS4232
@@ -441,13 +472,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
CS4231_HW_DETECT,
0,
&chip)) < 0)
- goto _err;
+ return err;
+ acard->chip = chip;
if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
- goto _err;
+ return err;
if ((err = snd_cs4231_mixer(chip)) < 0)
- goto _err;
+ return err;
#else /* CS4236 */
if ((err = snd_cs4236_create(card,
@@ -459,13 +491,14 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
CS4231_HW_DETECT,
0,
&chip)) < 0)
- goto _err;
+ return err;
+ acard->chip = chip;
if ((err = snd_cs4236_pcm(chip, 0, &pcm)) < 0)
- goto _err;
+ return err;
if ((err = snd_cs4236_mixer(chip)) < 0)
- goto _err;
+ return err;
#endif
strcpy(card->driver, pcm->name);
strcpy(card->shortname, pcm->name);
@@ -478,7 +511,7 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
- goto _err;
+ return err;
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
if (snd_opl3_create(card,
@@ -487,7 +520,7 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
printk(KERN_WARNING IDENT ": OPL3 not detected\n");
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
- goto _err;
+ return err;
}
}
@@ -501,95 +534,279 @@ static int __devinit snd_card_cs423x_probe(int dev, struct pnp_card_link *pcard,
printk(KERN_WARNING IDENT ": MPU401 not detected\n");
}
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ return snd_card_register(card);
+}
- if ((err = snd_card_register(card)) < 0)
- goto _err;
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_cs4236_legacy[dev] = card;
+static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev)
+{
+ int dev = pdev->id;
+ struct snd_card *card;
+ int err;
+
+ if (port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR "specify port\n");
+ return -EINVAL;
+ }
+ if (cport[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR "specify cport\n");
+ return -EINVAL;
+ }
+
+ card = snd_cs423x_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_cs423x_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ platform_set_drvdata(pdev, card);
return 0;
+}
- _err:
- snd_card_free(card);
- return err;
+static int __devexit snd_cs423x_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
}
+#ifdef CONFIG_PM
+static int snd_cs423x_suspend(struct snd_card *card)
+{
+ struct snd_card_cs4236 *acard = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ acard->chip->suspend(acard->chip);
+ return 0;
+}
+
+static int snd_cs423x_resume(struct snd_card *card)
+{
+ struct snd_card_cs4236 *acard = card->private_data;
+ acard->chip->resume(acard->chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+
+static int snd_cs423x_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return snd_cs423x_suspend(platform_get_drvdata(dev));
+}
+
+static int snd_cs423x_nonpnp_resume(struct platform_device *dev)
+{
+ return snd_cs423x_resume(platform_get_drvdata(dev));
+}
+#endif
+
+static struct platform_driver cs423x_nonpnp_driver = {
+ .probe = snd_cs423x_nonpnp_probe,
+ .remove = __devexit_p(snd_cs423x_nonpnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cs423x_nonpnp_suspend,
+ .resume = snd_cs423x_nonpnp_resume,
+#endif
+ .driver = {
+ .name = CS423X_DRIVER
+ },
+};
+
+
#ifdef CONFIG_PNP
-static int __devinit snd_cs423x_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+#ifdef CS4232
+static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
+ const struct pnp_device_id *id)
{
static int dev;
+ int err;
+ struct snd_card *card;
+
+ if (pnp_device_is_isapnp(pdev))
+ return -ENOENT; /* we have another procedure - card */
+ for (; dev < SNDRV_CARDS; dev++) {
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_cs423x_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ if ((err = snd_card_cs4232_pnp(dev, card->private_data, pdev)) < 0) {
+ printk(KERN_ERR "PnP BIOS detection failed for " IDENT "\n");
+ snd_card_free(card);
+ return err;
+ }
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_cs423x_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pnp_set_drvdata(pdev, card);
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_cs4232_pnp_remove(struct pnp_dev * pdev)
+{
+ snd_card_free(pnp_get_drvdata(pdev));
+ pnp_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_cs4232_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+ return snd_cs423x_suspend(pnp_get_drvdata(pdev));
+}
+
+static int snd_cs4232_pnp_resume(struct pnp_dev *pdev)
+{
+ return snd_cs423x_resume(pnp_get_drvdata(pdev));
+}
+#endif
+
+static struct pnp_driver cs4232_pnp_driver = {
+ .name = "cs4232-pnpbios",
+ .id_table = snd_cs4232_pnpbiosids,
+ .probe = snd_cs4232_pnpbios_detect,
+ .remove = __devexit_p(snd_cs4232_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cs4232_pnp_suspend,
+ .resume = snd_cs4232_pnp_resume,
+#endif
+};
+#endif /* CS4232 */
+
+static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
+{
+ static int dev;
+ struct snd_card *card;
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_card_cs423x_probe(dev, card, id);
- if (res < 0)
- return res;
- dev++;
- return 0;
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_cs423x_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ if ((res = snd_card_cs423x_pnpc(dev, card->private_data, pcard, pid)) < 0) {
+ printk(KERN_ERR "isapnp detection failed and probing for " IDENT
+ " is not supported\n");
+ snd_card_free(card);
+ return res;
+ }
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((res = snd_cs423x_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return res;
}
- return -ENODEV;
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
-static void __devexit snd_cs423x_pnp_remove(struct pnp_card_link * pcard)
+static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
+#ifdef CONFIG_PM
+static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ return snd_cs423x_suspend(pnp_get_card_drvdata(pcard));
+}
+
+static int snd_cs423x_pnpc_resume(struct pnp_card_link *pcard)
+{
+ return snd_cs423x_resume(pnp_get_card_drvdata(pcard));
+}
+#endif
+
static struct pnp_card_driver cs423x_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
- .name = "cs423x",
+ .name = CS423X_ISAPNP_DRIVER,
.id_table = snd_cs423x_pnpids,
- .probe = snd_cs423x_pnp_detect,
- .remove = __devexit_p(snd_cs423x_pnp_remove),
+ .probe = snd_cs423x_pnpc_detect,
+ .remove = __devexit_p(snd_cs423x_pnpc_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cs423x_pnpc_suspend,
+ .resume = snd_cs423x_pnpc_resume,
+#endif
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_cs423x_unregister_all(void)
+{
+ int i;
+
+ if (pnpc_registered)
+ pnp_unregister_card_driver(&cs423x_pnpc_driver);
+#ifdef CS4232
+ if (pnp_registered)
+ pnp_unregister_driver(&cs4232_pnp_driver);
+#endif
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&cs423x_nonpnp_driver);
+}
+
static int __init alsa_card_cs423x_init(void)
{
- int dev, cards = 0;
+ int i, err, cards = 0;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev])
- continue;
- if (is_isapnp_selected(dev))
+ if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ if (is_isapnp_selected(i))
continue;
- if (snd_card_cs423x_probe(dev, NULL, NULL) >= 0)
- cards++;
+ device = platform_device_register_simple(CS423X_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ cards++;
+ }
+#ifdef CS4232
+ i = pnp_register_driver(&cs4232_pnp_driver);
+ if (i >= 0) {
+ pnp_registered = 1;
+ cards += i;
}
-#ifdef CONFIG_PNP
- cards += pnp_register_card_driver(&cs423x_pnpc_driver);
#endif
+ i = pnp_register_card_driver(&cs423x_pnpc_driver);
+ if (i >= 0) {
+ pnpc_registered = 1;
+ cards += i;
+ }
if (!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&cs423x_pnpc_driver);
-#endif
#ifdef MODULE
printk(KERN_ERR IDENT " soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_cs423x_unregister_all();
+ return err;
}
static void __exit alsa_card_cs423x_exit(void)
{
- int idx;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&cs423x_pnpc_driver);
-#endif
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_cs4236_legacy[idx]);
+ snd_cs423x_unregister_all();
}
module_init(alsa_card_cs423x_init)
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 1adb88d5f8f4..e36981d64ec5 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -122,13 +122,13 @@ static unsigned char snd_cs4236_ext_map[18] = {
*
*/
-static void snd_cs4236_ctrl_out(cs4231_t *chip, unsigned char reg, unsigned char val)
+static void snd_cs4236_ctrl_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char val)
{
outb(reg, chip->cport + 3);
outb(chip->cimage[reg] = val, chip->cport + 4);
}
-static unsigned char snd_cs4236_ctrl_in(cs4231_t *chip, unsigned char reg)
+static unsigned char snd_cs4236_ctrl_in(struct snd_cs4231 *chip, unsigned char reg)
{
outb(reg, chip->cport + 3);
return inb(chip->cport + 4);
@@ -140,7 +140,7 @@ static unsigned char snd_cs4236_ctrl_in(cs4231_t *chip, unsigned char reg)
#define CLOCKS 8
-static ratnum_t clocks[CLOCKS] = {
+static struct snd_ratnum clocks[CLOCKS] = {
{ .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 },
{ .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 },
{ .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 },
@@ -151,12 +151,12 @@ static ratnum_t clocks[CLOCKS] = {
{ .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 }
};
-static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
.nrats = CLOCKS,
.rats = clocks,
};
-static int snd_cs4236_xrate(snd_pcm_runtime_t *runtime)
+static int snd_cs4236_xrate(struct snd_pcm_runtime *runtime)
{
return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hw_constraints_clocks);
@@ -181,7 +181,7 @@ static unsigned char divisor_to_rate_register(unsigned int divisor)
}
}
-static void snd_cs4236_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *params, unsigned char pdfr)
+static void snd_cs4236_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char pdfr)
{
unsigned long flags;
unsigned char rate = divisor_to_rate_register(params->rate_den);
@@ -195,7 +195,7 @@ static void snd_cs4236_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *para
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4236_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *params, unsigned char cdfr)
+static void snd_cs4236_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, unsigned char cdfr)
{
unsigned long flags;
unsigned char rate = divisor_to_rate_register(params->rate_den);
@@ -211,7 +211,7 @@ static void snd_cs4236_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *param
#ifdef CONFIG_PM
-static void snd_cs4236_suspend(cs4231_t *chip)
+static void snd_cs4236_suspend(struct snd_cs4231 *chip)
{
int reg;
unsigned long flags;
@@ -226,7 +226,7 @@ static void snd_cs4236_suspend(cs4231_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4236_resume(cs4231_t *chip)
+static void snd_cs4236_resume(struct snd_cs4231 *chip)
{
int reg;
unsigned long flags;
@@ -261,15 +261,15 @@ static void snd_cs4236_resume(cs4231_t *chip)
#endif /* CONFIG_PM */
-int snd_cs4236_create(snd_card_t * card,
+int snd_cs4236_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
int irq, int dma1, int dma2,
unsigned short hardware,
unsigned short hwshare,
- cs4231_t ** rchip)
+ struct snd_cs4231 ** rchip)
{
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
unsigned char ver1, ver2;
unsigned int reg;
int err;
@@ -352,9 +352,9 @@ int snd_cs4236_create(snd_card_t * card,
return 0;
}
-int snd_cs4236_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
+int snd_cs4236_pcm(struct snd_cs4231 *chip, int device, struct snd_pcm **rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_cs4231_pcm(chip, device, &pcm)) < 0)
@@ -375,7 +375,7 @@ int snd_cs4236_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
.get = snd_cs4236_get_single, .put = snd_cs4236_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_cs4236_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs4236_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -386,9 +386,9 @@ static int snd_cs4236_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_cs4236_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -403,9 +403,9 @@ static int snd_cs4236_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_cs4236_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -432,9 +432,9 @@ static int snd_cs4236_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_cs4236_get_singlec, .put = snd_cs4236_put_singlec, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_cs4236_get_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -449,9 +449,9 @@ static int snd_cs4236_get_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_cs4236_put_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_singlec(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -478,7 +478,7 @@ static int snd_cs4236_put_singlec(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.get = snd_cs4236_get_double, .put = snd_cs4236_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_cs4236_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs4236_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -489,9 +489,9 @@ static int snd_cs4236_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_cs4236_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -511,9 +511,9 @@ static int snd_cs4236_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_cs4236_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -554,9 +554,9 @@ static int snd_cs4236_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_cs4236_get_double1, .put = snd_cs4236_put_double1, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_cs4236_get_double1(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -576,9 +576,9 @@ static int snd_cs4236_get_double1(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_cs4236_put_double1(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_double1(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -618,9 +618,9 @@ static inline int snd_cs4236_mixer_master_digital_invert_volume(int vol)
return (vol < 64) ? 63 - vol : 64 + (71 - vol);
}
-static int snd_cs4236_get_master_digital(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -630,9 +630,9 @@ static int snd_cs4236_get_master_digital(snd_kcontrol_t * kcontrol, snd_ctl_elem
return 0;
}
-static int snd_cs4236_put_master_digital(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_master_digital(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1, val2;
@@ -677,9 +677,9 @@ static inline int snd_cs4235_mixer_output_accu_set_volume(int vol)
return 1 << 5;
}
-static int snd_cs4235_get_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4235_get_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -689,9 +689,9 @@ static int snd_cs4235_get_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4235_put_output_accu(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1, val2;
@@ -708,7 +708,7 @@ static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return change;
}
-static snd_kcontrol_new_t snd_cs4236_controls[] = {
+static struct snd_kcontrol_new snd_cs4236_controls[] = {
CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
CS4236_DOUBLE("Master Digital Capture Switch", 0, CS4236_DAC_MUTE, CS4236_DAC_MUTE, 7, 6, 1, 1),
@@ -759,7 +759,7 @@ CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
};
-static snd_kcontrol_new_t snd_cs4235_controls[] = {
+static struct snd_kcontrol_new snd_cs4235_controls[] = {
CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
CS4231_DOUBLE("Master Volume", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 0, 0, 31, 1),
@@ -812,9 +812,9 @@ CS4231_DOUBLE("Analog Loopback Switch", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT
.get = snd_cs4236_get_iec958_switch, .put = snd_cs4236_put_iec958_switch, \
.private_value = 1 << 16 }
-static int snd_cs4236_get_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_get_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -832,9 +832,9 @@ static int snd_cs4236_get_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short enable, val;
@@ -868,7 +868,7 @@ static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return change;
}
-static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {
+static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
@@ -877,12 +877,12 @@ CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
};
-static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {
+static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
};
-static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {
+static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
@@ -890,19 +890,19 @@ CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
};
-static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {
+static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
};
-int snd_cs4236_mixer(cs4231_t *chip)
+int snd_cs4236_mixer(struct snd_cs4231 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx, count;
int err;
- snd_kcontrol_new_t *kcontrol;
+ struct snd_kcontrol_new *kcontrol;
snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
card = chip->card;
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index db7c3397b323..50e7bc5ef561 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -74,6 +74,7 @@ struct snd_card_dt019x {
struct pnp_dev *dev;
struct pnp_dev *devmpu;
struct pnp_dev *devopl;
+ struct snd_sb *chip;
};
static struct pnp_card_device_id snd_dt019x_pnpids[] = {
@@ -188,15 +189,15 @@ static int __devinit snd_card_dt019x_pnp(int dev, struct snd_card_dt019x *acard,
static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, const struct pnp_card_device_id *pid)
{
int error;
- sb_t *chip;
- snd_card_t *card;
+ struct snd_sb *chip;
+ struct snd_card *card;
struct snd_card_dt019x *acard;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_dt019x))) == NULL)
return -ENOMEM;
- acard = (struct snd_card_dt019x *)card->private_data;
+ acard = card->private_data;
snd_card_set_dev(card, &pcard->card->dev);
if ((error = snd_card_dt019x_pnp(dev, acard, pcard, pid))) {
@@ -214,6 +215,7 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
+ acard->chip = chip;
strcpy(card->driver, "DT-019X");
strcpy(card->shortname, "Diamond Tech. DT-019X");
@@ -290,32 +292,61 @@ static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
static void __devexit snd_dt019x_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
+#ifdef CONFIG_PM
+static int snd_dt019x_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_dt019x *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
+}
+
+static int snd_dt019x_pnp_resume(struct pnp_card_link *pcard)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_dt019x *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pnp_card_driver dt019x_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "dt019x",
.id_table = snd_dt019x_pnpids,
.probe = snd_dt019x_pnp_probe,
.remove = __devexit_p(snd_dt019x_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_dt019x_pnp_suspend,
+ .resume = snd_dt019x_pnp_resume,
+#endif
};
static int __init alsa_card_dt019x_init(void)
{
int cards = 0;
- cards += pnp_register_card_driver(&dt019x_pnpc_driver);
-
-#ifdef MODULE
- if (!cards) {
+ cards = pnp_register_card_driver(&dt019x_pnpc_driver);
+ if (cards <= 0) {
pnp_unregister_card_driver(&dt019x_pnpc_driver);
+#ifdef MODULE
snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
- }
#endif
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_dt019x_exit(void)
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 26a7d335ed8e..50d23cf3d7cc 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -20,16 +20,17 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/es1688.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
@@ -68,19 +69,20 @@ MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver.");
module_param_array(dma8, int, NULL, 0444);
MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
-static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
#define PFX "es1688: "
-static int __init snd_audiodrive_probe(int dev)
+static int __init snd_es1688_probe(struct platform_device *pdev)
{
+ int dev = pdev->id;
static int possible_irqs[] = {5, 9, 10, 7, -1};
static int possible_dmas[] = {1, 3, 0, -1};
int xirq, xdma, xmpu_irq;
- snd_card_t *card;
- es1688_t *chip;
- opl3_t *opl3;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_es1688 *chip;
+ struct snd_opl3 *opl3;
+ struct snd_pcm *pcm;
int err;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
@@ -105,10 +107,30 @@ static int __init snd_audiodrive_probe(int dev)
}
}
- if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
- xirq, xmpu_irq, xdma,
- ES1688_HW_AUTO, &chip)) < 0)
- goto _err;
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
+ xirq, xmpu_irq, xdma,
+ ES1688_HW_AUTO, &chip)) < 0)
+ goto _err;
+ } else {
+ /* auto-probe legacy ports */
+ static unsigned long possible_ports[] = {
+ 0x220, 0x240, 0x260,
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ err = snd_es1688_create(card, possible_ports[i],
+ mpu_port[dev],
+ xirq, xmpu_irq, xdma,
+ ES1688_HW_AUTO, &chip);
+ if (err >= 0) {
+ port[dev] = possible_ports[i];
+ break;
+ }
+ }
+ if (i >= ARRAY_SIZE(possible_ports))
+ goto _err;
+ }
if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0)
goto _err;
@@ -136,13 +158,12 @@ static int __init snd_audiodrive_probe(int dev)
goto _err;
}
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_audiodrive_cards[dev] = card;
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -150,53 +171,70 @@ static int __init snd_audiodrive_probe(int dev)
return err;
}
-static int __init snd_audiodrive_legacy_auto_probe(unsigned long xport)
+static int snd_es1688_remove(struct platform_device *devptr)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- port[dev] = xport;
- res = snd_audiodrive_probe(dev);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
- }
- return -ENODEV;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define ES1688_DRIVER "snd_es1688"
+
+static struct platform_driver snd_es1688_driver = {
+ .probe = snd_es1688_probe,
+ .remove = snd_es1688_remove,
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = ES1688_DRIVER
+ },
+};
+
+static void __init_or_module snd_es1688_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_es1688_driver);
}
static int __init alsa_card_es1688_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
- int dev, cards = 0, i;
-
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (snd_audiodrive_probe(dev) >= 0)
- cards++;
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_es1688_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(ES1688_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
}
- i = snd_legacy_auto_probe(possible_ports, snd_audiodrive_legacy_auto_probe);
- if (i > 0)
- cards += i;
-
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_es1688_unregister_all();
+ return err;
}
static void __exit alsa_card_es1688_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_audiodrive_cards[idx]);
+ snd_es1688_unregister_all();
}
module_init(alsa_card_es1688_init)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 2edc9c9f0445..702ad51ee9d5 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -36,7 +36,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
MODULE_LICENSE("GPL");
-static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
+static int snd_es1688_dsp_command(struct snd_es1688 *chip, unsigned char val)
{
int i;
@@ -51,7 +51,7 @@ static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
return 0;
}
-static int snd_es1688_dsp_get_byte(es1688_t *chip)
+static int snd_es1688_dsp_get_byte(struct snd_es1688 *chip)
{
int i;
@@ -62,7 +62,7 @@ static int snd_es1688_dsp_get_byte(es1688_t *chip)
return -ENODEV;
}
-static int snd_es1688_write(es1688_t *chip,
+static int snd_es1688_write(struct snd_es1688 *chip,
unsigned char reg, unsigned char data)
{
if (!snd_es1688_dsp_command(chip, reg))
@@ -70,7 +70,7 @@ static int snd_es1688_write(es1688_t *chip,
return snd_es1688_dsp_command(chip, data);
}
-static int snd_es1688_read(es1688_t *chip, unsigned char reg)
+static int snd_es1688_read(struct snd_es1688 *chip, unsigned char reg)
{
/* Read a byte from an extended mode register of ES1688 */
if (!snd_es1688_dsp_command(chip, 0xc0))
@@ -80,7 +80,7 @@ static int snd_es1688_read(es1688_t *chip, unsigned char reg)
return snd_es1688_dsp_get_byte(chip);
}
-void snd_es1688_mixer_write(es1688_t *chip,
+void snd_es1688_mixer_write(struct snd_es1688 *chip,
unsigned char reg, unsigned char data)
{
outb(reg, ES1688P(chip, MIXER_ADDR));
@@ -89,7 +89,7 @@ void snd_es1688_mixer_write(es1688_t *chip,
udelay(10);
}
-static unsigned char snd_es1688_mixer_read(es1688_t *chip, unsigned char reg)
+static unsigned char snd_es1688_mixer_read(struct snd_es1688 *chip, unsigned char reg)
{
unsigned char result;
@@ -100,7 +100,7 @@ static unsigned char snd_es1688_mixer_read(es1688_t *chip, unsigned char reg)
return result;
}
-static int snd_es1688_reset(es1688_t *chip)
+static int snd_es1688_reset(struct snd_es1688 *chip)
{
int i;
@@ -117,7 +117,7 @@ static int snd_es1688_reset(es1688_t *chip)
return 0;
}
-static int snd_es1688_probe(es1688_t *chip)
+static int snd_es1688_probe(struct snd_es1688 *chip)
{
unsigned long flags;
unsigned short major, minor, hw;
@@ -191,7 +191,7 @@ static int snd_es1688_probe(es1688_t *chip)
return 0;
}
-static int snd_es1688_init(es1688_t * chip, int enable)
+static int snd_es1688_init(struct snd_es1688 * chip, int enable)
{
static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
unsigned long flags;
@@ -283,7 +283,7 @@ static int snd_es1688_init(es1688_t * chip, int enable)
*/
-static ratnum_t clocks[2] = {
+static struct snd_ratnum clocks[2] = {
{
.num = 795444,
.den_min = 1,
@@ -298,14 +298,14 @@ static ratnum_t clocks[2] = {
}
};
-static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
.nrats = 2,
.rats = clocks,
};
-static void snd_es1688_set_rate(es1688_t *chip, snd_pcm_substream_t *substream)
+static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int bits, divider;
if (runtime->rate_num == clocks[0].num)
@@ -319,13 +319,13 @@ static void snd_es1688_set_rate(es1688_t *chip, snd_pcm_substream_t *substream)
snd_es1688_write(chip, 0xa2, divider);
}
-static int snd_es1688_ioctl(snd_pcm_substream_t * substream,
+static int snd_es1688_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static int snd_es1688_trigger(es1688_t *chip, int cmd, unsigned char value)
+static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value)
{
int val;
@@ -350,22 +350,22 @@ static int snd_es1688_trigger(es1688_t *chip, int cmd, unsigned char value)
return 0;
}
-static int snd_es1688_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_es1688_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_es1688_hw_free(snd_pcm_substream_t * substream)
+static int snd_es1688_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_es1688_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- es1688_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -415,18 +415,18 @@ static int snd_es1688_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1688_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_es1688_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
return snd_es1688_trigger(chip, cmd, 0x05);
}
-static int snd_es1688_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_es1688_capture_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- es1688_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -472,16 +472,16 @@ static int snd_es1688_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1688_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_es1688_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
return snd_es1688_trigger(chip, cmd, 0x0f);
}
static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- es1688_t *chip = dev_id;
+ struct snd_es1688 *chip = dev_id;
if (chip->trigger_value == 0x05) /* ok.. playback is active */
snd_pcm_period_elapsed(chip->playback_substream);
@@ -492,9 +492,9 @@ static irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_es1688_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es1688_playback_pointer(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (chip->trigger_value != 0x05)
@@ -503,9 +503,9 @@ static snd_pcm_uframes_t snd_es1688_playback_pointer(snd_pcm_substream_t * subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_es1688_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es1688_capture_pointer(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (chip->trigger_value != 0x0f)
@@ -518,7 +518,7 @@ static snd_pcm_uframes_t snd_es1688_capture_pointer(snd_pcm_substream_t * substr
*/
-static snd_pcm_hardware_t snd_es1688_playback =
+static struct snd_pcm_hardware snd_es1688_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -536,7 +536,7 @@ static snd_pcm_hardware_t snd_es1688_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_es1688_capture =
+static struct snd_pcm_hardware snd_es1688_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -558,10 +558,10 @@ static snd_pcm_hardware_t snd_es1688_capture =
*/
-static int snd_es1688_playback_open(snd_pcm_substream_t * substream)
+static int snd_es1688_playback_open(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (chip->capture_substream != NULL)
return -EAGAIN;
@@ -572,10 +572,10 @@ static int snd_es1688_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1688_capture_open(snd_pcm_substream_t * substream)
+static int snd_es1688_capture_open(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (chip->playback_substream != NULL)
return -EAGAIN;
@@ -586,23 +586,23 @@ static int snd_es1688_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1688_playback_close(snd_pcm_substream_t * substream)
+static int snd_es1688_playback_close(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
return 0;
}
-static int snd_es1688_capture_close(snd_pcm_substream_t * substream)
+static int snd_es1688_capture_close(struct snd_pcm_substream *substream)
{
- es1688_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es1688 *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
return 0;
}
-static int snd_es1688_free(es1688_t *chip)
+static int snd_es1688_free(struct snd_es1688 *chip)
{
if (chip->res_port) {
snd_es1688_init(chip, 0);
@@ -618,33 +618,33 @@ static int snd_es1688_free(es1688_t *chip)
return 0;
}
-static int snd_es1688_dev_free(snd_device_t *device)
+static int snd_es1688_dev_free(struct snd_device *device)
{
- es1688_t *chip = device->device_data;
+ struct snd_es1688 *chip = device->device_data;
return snd_es1688_free(chip);
}
-static const char *snd_es1688_chip_id(es1688_t *chip)
+static const char *snd_es1688_chip_id(struct snd_es1688 *chip)
{
static char tmp[16];
sprintf(tmp, "ES%s688 rev %i", chip->hardware == ES1688_HW_688 ? "" : "1", chip->version & 0x0f);
return tmp;
}
-int snd_es1688_create(snd_card_t * card,
+int snd_es1688_create(struct snd_card *card,
unsigned long port,
unsigned long mpu_port,
int irq,
int mpu_irq,
int dma8,
unsigned short hardware,
- es1688_t **rchip)
+ struct snd_es1688 **rchip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_es1688_dev_free,
};
- es1688_t *chip;
+ struct snd_es1688 *chip;
int err;
*rchip = NULL;
@@ -702,7 +702,7 @@ int snd_es1688_create(snd_card_t * card,
return 0;
}
-static snd_pcm_ops_t snd_es1688_playback_ops = {
+static struct snd_pcm_ops snd_es1688_playback_ops = {
.open = snd_es1688_playback_open,
.close = snd_es1688_playback_close,
.ioctl = snd_es1688_ioctl,
@@ -713,7 +713,7 @@ static snd_pcm_ops_t snd_es1688_playback_ops = {
.pointer = snd_es1688_playback_pointer,
};
-static snd_pcm_ops_t snd_es1688_capture_ops = {
+static struct snd_pcm_ops snd_es1688_capture_ops = {
.open = snd_es1688_capture_open,
.close = snd_es1688_capture_close,
.ioctl = snd_es1688_ioctl,
@@ -724,16 +724,9 @@ static snd_pcm_ops_t snd_es1688_capture_ops = {
.pointer = snd_es1688_capture_pointer,
};
-static void snd_es1688_pcm_free(snd_pcm_t *pcm)
+int snd_es1688_pcm(struct snd_es1688 * chip, int device, struct snd_pcm ** rpcm)
{
- es1688_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_es1688_pcm(es1688_t * chip, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "ESx688", device, 1, 1, &pcm)) < 0)
@@ -743,7 +736,6 @@ int snd_es1688_pcm(es1688_t * chip, int device, snd_pcm_t ** rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1688_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_es1688_pcm_free;
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
sprintf(pcm->name, snd_es1688_chip_id(chip));
chip->pcm = pcm;
@@ -761,7 +753,7 @@ int snd_es1688_pcm(es1688_t * chip, int device, snd_pcm_t ** rpcm)
* MIXER part
*/
-static int snd_es1688_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1688_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[9] = {
"Mic", "Mic Master", "CD", "AOUT",
@@ -777,16 +769,16 @@ static int snd_es1688_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_es1688_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = snd_es1688_mixer_read(chip, ES1688_REC_DEV) & 7;
return 0;
}
-static int snd_es1688_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned char oval, nval;
int change;
@@ -809,7 +801,7 @@ static int snd_es1688_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
.get = snd_es1688_get_single, .put = snd_es1688_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_es1688_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1688_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -820,9 +812,9 @@ static int snd_es1688_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es1688_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -837,9 +829,9 @@ static int snd_es1688_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es1688_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -868,7 +860,7 @@ static int snd_es1688_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_es1688_get_double, .put = snd_es1688_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_es1688_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1688_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -879,9 +871,9 @@ static int snd_es1688_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es1688_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -913,9 +905,9 @@ static int snd_es1688_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es1688_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es1688_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es1688 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -976,7 +968,7 @@ static int snd_es1688_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t snd_es1688_controls[] = {
+static struct snd_kcontrol_new snd_es1688_controls[] = {
ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
@@ -1011,9 +1003,9 @@ static unsigned char snd_es1688_init_table[][2] = {
{ ES1688_REC_DEV, 0x17 }
};
-int snd_es1688_mixer(es1688_t *chip)
+int snd_es1688_mixer(struct snd_es1688 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx;
int err;
unsigned char reg, val;
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 970e2aaade27..bf5de0782eb0 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -65,28 +65,28 @@
#include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
#include <linux/init.h>
-#include <linux/pm.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/isapnp.h>
#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/mpu401.h>
#include <sound/opl3.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
#define PFX "es18xx: "
-struct _snd_es18xx {
+struct snd_es18xx {
unsigned long port; /* port of ESS chip */
unsigned long mpu_port; /* MPU-401 port of ESS chip */
unsigned long fm_port; /* FM port */
@@ -107,18 +107,18 @@ struct _snd_es18xx {
unsigned int dma1_shift;
unsigned int dma2_shift;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_a_substream;
- snd_pcm_substream_t *capture_a_substream;
- snd_pcm_substream_t *playback_b_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_a_substream;
+ struct snd_pcm_substream *capture_a_substream;
+ struct snd_pcm_substream *playback_b_substream;
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
- snd_kcontrol_t *hw_volume;
- snd_kcontrol_t *hw_switch;
- snd_kcontrol_t *master_volume;
- snd_kcontrol_t *master_switch;
+ struct snd_kcontrol *hw_volume;
+ struct snd_kcontrol *hw_switch;
+ struct snd_kcontrol *master_volume;
+ struct snd_kcontrol *master_switch;
spinlock_t reg_lock;
spinlock_t mixer_lock;
@@ -128,6 +128,14 @@ struct _snd_es18xx {
#endif
};
+struct snd_audiodrive {
+ struct snd_es18xx *chip;
+#ifdef CONFIG_PNP
+ struct pnp_dev *dev;
+ struct pnp_dev *devc;
+#endif
+};
+
#define AUDIO1_IRQ 0x01
#define AUDIO2_IRQ 0x02
#define HWV_IRQ 0x04
@@ -155,8 +163,6 @@ struct _snd_es18xx {
#define ES18XX_PM_FM 0x020
#define ES18XX_PM_SUS 0x080
-typedef struct _snd_es18xx es18xx_t;
-
/* Lowlevel */
#define DAC1 0x01
@@ -164,7 +170,7 @@ typedef struct _snd_es18xx es18xx_t;
#define DAC2 0x04
#define MILLISECOND 10000
-static int snd_es18xx_dsp_command(es18xx_t *chip, unsigned char val)
+static int snd_es18xx_dsp_command(struct snd_es18xx *chip, unsigned char val)
{
int i;
@@ -177,7 +183,7 @@ static int snd_es18xx_dsp_command(es18xx_t *chip, unsigned char val)
return -EINVAL;
}
-static int snd_es18xx_dsp_get_byte(es18xx_t *chip)
+static int snd_es18xx_dsp_get_byte(struct snd_es18xx *chip)
{
int i;
@@ -191,7 +197,7 @@ static int snd_es18xx_dsp_get_byte(es18xx_t *chip)
#undef REG_DEBUG
-static int snd_es18xx_write(es18xx_t *chip,
+static int snd_es18xx_write(struct snd_es18xx *chip,
unsigned char reg, unsigned char data)
{
unsigned long flags;
@@ -210,7 +216,7 @@ static int snd_es18xx_write(es18xx_t *chip,
return ret;
}
-static int snd_es18xx_read(es18xx_t *chip, unsigned char reg)
+static int snd_es18xx_read(struct snd_es18xx *chip, unsigned char reg)
{
unsigned long flags;
int ret, data;
@@ -232,7 +238,7 @@ static int snd_es18xx_read(es18xx_t *chip, unsigned char reg)
}
/* Return old value */
-static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg,
+static int snd_es18xx_bits(struct snd_es18xx *chip, unsigned char reg,
unsigned char mask, unsigned char val)
{
int ret;
@@ -270,7 +276,7 @@ static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg,
return ret;
}
-static inline void snd_es18xx_mixer_write(es18xx_t *chip,
+static inline void snd_es18xx_mixer_write(struct snd_es18xx *chip,
unsigned char reg, unsigned char data)
{
unsigned long flags;
@@ -283,7 +289,7 @@ static inline void snd_es18xx_mixer_write(es18xx_t *chip,
#endif
}
-static inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg)
+static inline int snd_es18xx_mixer_read(struct snd_es18xx *chip, unsigned char reg)
{
unsigned long flags;
int data;
@@ -298,7 +304,7 @@ static inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg)
}
/* Return old value */
-static inline int snd_es18xx_mixer_bits(es18xx_t *chip, unsigned char reg,
+static inline int snd_es18xx_mixer_bits(struct snd_es18xx *chip, unsigned char reg,
unsigned char mask, unsigned char val)
{
unsigned char old, new, oval;
@@ -319,7 +325,7 @@ static inline int snd_es18xx_mixer_bits(es18xx_t *chip, unsigned char reg,
return oval;
}
-static inline int snd_es18xx_mixer_writable(es18xx_t *chip, unsigned char reg,
+static inline int snd_es18xx_mixer_writable(struct snd_es18xx *chip, unsigned char reg,
unsigned char mask)
{
int old, expected, new;
@@ -339,7 +345,7 @@ static inline int snd_es18xx_mixer_writable(es18xx_t *chip, unsigned char reg,
}
-static int snd_es18xx_reset(es18xx_t *chip)
+static int snd_es18xx_reset(struct snd_es18xx *chip)
{
int i;
outb(0x03, chip->port + 0x06);
@@ -351,7 +357,7 @@ static int snd_es18xx_reset(es18xx_t *chip)
return 0;
}
-static int snd_es18xx_reset_fifo(es18xx_t *chip)
+static int snd_es18xx_reset_fifo(struct snd_es18xx *chip)
{
outb(0x02, chip->port + 0x06);
inb(chip->port + 0x06);
@@ -359,7 +365,7 @@ static int snd_es18xx_reset_fifo(es18xx_t *chip)
return 0;
}
-static ratnum_t new_clocks[2] = {
+static struct snd_ratnum new_clocks[2] = {
{
.num = 793800,
.den_min = 1,
@@ -374,12 +380,12 @@ static ratnum_t new_clocks[2] = {
}
};
-static snd_pcm_hw_constraint_ratnums_t new_hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = {
.nrats = 2,
.rats = new_clocks,
};
-static ratnum_t old_clocks[2] = {
+static struct snd_ratnum old_clocks[2] = {
{
.num = 795444,
.den_min = 1,
@@ -394,18 +400,18 @@ static ratnum_t old_clocks[2] = {
}
};
-static snd_pcm_hw_constraint_ratnums_t old_hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = {
.nrats = 2,
.rats = old_clocks,
};
-static void snd_es18xx_rate_set(es18xx_t *chip,
- snd_pcm_substream_t *substream,
+static void snd_es18xx_rate_set(struct snd_es18xx *chip,
+ struct snd_pcm_substream *substream,
int mode)
{
unsigned int bits, div0;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (chip->caps & ES18XX_NEW_RATE) {
if (runtime->rate_num == new_clocks[0].num)
bits = 128 - runtime->rate_den;
@@ -435,10 +441,10 @@ static void snd_es18xx_rate_set(es18xx_t *chip,
}
}
-static int snd_es18xx_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_es18xx_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
int shift, err;
shift = 0;
@@ -463,15 +469,15 @@ static int snd_es18xx_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_es18xx_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_es18xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_es18xx_playback1_prepare(es18xx_t *chip,
- snd_pcm_substream_t *substream)
+static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -496,8 +502,8 @@ static int snd_es18xx_playback1_prepare(es18xx_t *chip,
return 0;
}
-static int snd_es18xx_playback1_trigger(es18xx_t *chip,
- snd_pcm_substream_t * substream,
+static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip,
+ struct snd_pcm_substream *substream,
int cmd)
{
switch (cmd) {
@@ -546,10 +552,10 @@ static int snd_es18xx_playback1_trigger(es18xx_t *chip,
return 0;
}
-static int snd_es18xx_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_es18xx_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
int shift, err;
shift = 0;
@@ -569,10 +575,10 @@ static int snd_es18xx_capture_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_es18xx_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -608,10 +614,10 @@ static int snd_es18xx_capture_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_es18xx_capture_trigger(snd_pcm_substream_t *substream,
+static int snd_es18xx_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -637,10 +643,10 @@ static int snd_es18xx_capture_trigger(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_es18xx_playback2_prepare(es18xx_t *chip,
- snd_pcm_substream_t *substream)
+static int snd_es18xx_playback2_prepare(struct snd_es18xx *chip,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -674,8 +680,8 @@ static int snd_es18xx_playback2_prepare(es18xx_t *chip,
return 0;
}
-static int snd_es18xx_playback2_trigger(es18xx_t *chip,
- snd_pcm_substream_t *substream,
+static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip,
+ struct snd_pcm_substream *substream,
int cmd)
{
switch (cmd) {
@@ -714,19 +720,19 @@ static int snd_es18xx_playback2_trigger(es18xx_t *chip,
return 0;
}
-static int snd_es18xx_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_es18xx_playback_prepare(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
return snd_es18xx_playback1_prepare(chip, substream);
else
return snd_es18xx_playback2_prepare(chip, substream);
}
-static int snd_es18xx_playback_trigger(snd_pcm_substream_t *substream,
+static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
return snd_es18xx_playback1_trigger(chip, substream, cmd);
else
@@ -735,7 +741,7 @@ static int snd_es18xx_playback_trigger(snd_pcm_substream_t *substream,
static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- es18xx_t *chip = dev_id;
+ struct snd_es18xx *chip = dev_id;
unsigned char status;
if (chip->caps & ES18XX_CONTROL) {
@@ -795,9 +801,9 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_es18xx_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es18xx_playback_pointer(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
int pos;
if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
@@ -813,9 +819,9 @@ static snd_pcm_uframes_t snd_es18xx_playback_pointer(snd_pcm_substream_t * subst
}
}
-static snd_pcm_uframes_t snd_es18xx_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es18xx_capture_pointer(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
int pos;
if (!(chip->active & ADC1))
@@ -824,7 +830,7 @@ static snd_pcm_uframes_t snd_es18xx_capture_pointer(snd_pcm_substream_t * substr
return pos >> chip->dma1_shift;
}
-static snd_pcm_hardware_t snd_es18xx_playback =
+static struct snd_pcm_hardware snd_es18xx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_RESUME |
@@ -844,7 +850,7 @@ static snd_pcm_hardware_t snd_es18xx_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_es18xx_capture =
+static struct snd_pcm_hardware snd_es18xx_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_RESUME |
@@ -864,10 +870,10 @@ static snd_pcm_hardware_t snd_es18xx_capture =
.fifo_size = 0,
};
-static int snd_es18xx_playback_open(snd_pcm_substream_t * substream)
+static int snd_es18xx_playback_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
if (substream->number == 0 && (chip->caps & ES18XX_PCM2)) {
if ((chip->caps & ES18XX_DUPLEX_MONO) &&
@@ -889,10 +895,10 @@ static int snd_es18xx_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es18xx_capture_open(snd_pcm_substream_t * substream)
+static int snd_es18xx_capture_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
if (chip->playback_b_substream)
return -EAGAIN;
@@ -907,9 +913,9 @@ static int snd_es18xx_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es18xx_playback_close(snd_pcm_substream_t * substream)
+static int snd_es18xx_playback_close(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
if (substream->number == 0 && (chip->caps & ES18XX_PCM2))
chip->playback_a_substream = NULL;
@@ -920,9 +926,9 @@ static int snd_es18xx_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es18xx_capture_close(snd_pcm_substream_t * substream)
+static int snd_es18xx_capture_close(struct snd_pcm_substream *substream)
{
- es18xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
chip->capture_a_substream = NULL;
snd_pcm_lib_free_pages(substream);
@@ -933,7 +939,7 @@ static int snd_es18xx_capture_close(snd_pcm_substream_t * substream)
* MIXER part
*/
-static int snd_es18xx_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[8] = {
"Mic", "Mic Master", "CD", "AOUT",
@@ -949,16 +955,16 @@ static int snd_es18xx_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_es18xx_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = snd_es18xx_mixer_read(chip, 0x1c) & 0x07;
return 0;
}
-static int snd_es18xx_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
unsigned char val = ucontrol->value.enumerated.item[0];
if (val > 7)
@@ -966,7 +972,7 @@ static int snd_es18xx_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val;
}
-static int snd_es18xx_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -975,17 +981,17 @@ static int snd_es18xx_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_es18xx_get_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
unsigned char val = snd_es18xx_mixer_read(chip, 0x50);
ucontrol->value.integer.value[0] = !!(val & 8);
return 0;
}
-static int snd_es18xx_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_put_spatializer_enable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
unsigned char oval, nval;
int change;
nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04;
@@ -998,7 +1004,7 @@ static int snd_es18xx_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_
return change;
}
-static int snd_es18xx_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1007,15 +1013,15 @@ static int snd_es18xx_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_es18xx_get_hw_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_hw_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = snd_es18xx_mixer_read(chip, 0x61) & 0x3f;
ucontrol->value.integer.value[1] = snd_es18xx_mixer_read(chip, 0x63) & 0x3f;
return 0;
}
-static int snd_es18xx_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -1024,24 +1030,24 @@ static int snd_es18xx_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_es18xx_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_hw_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = !(snd_es18xx_mixer_read(chip, 0x61) & 0x40);
ucontrol->value.integer.value[1] = !(snd_es18xx_mixer_read(chip, 0x63) & 0x40);
return 0;
}
-static void snd_es18xx_hwv_free(snd_kcontrol_t *kcontrol)
+static void snd_es18xx_hwv_free(struct snd_kcontrol *kcontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
chip->master_volume = NULL;
chip->master_switch = NULL;
chip->hw_volume = NULL;
chip->hw_switch = NULL;
}
-static int snd_es18xx_reg_bits(es18xx_t *chip, unsigned char reg,
+static int snd_es18xx_reg_bits(struct snd_es18xx *chip, unsigned char reg,
unsigned char mask, unsigned char val)
{
if (reg < 0xa0)
@@ -1050,7 +1056,7 @@ static int snd_es18xx_reg_bits(es18xx_t *chip, unsigned char reg,
return snd_es18xx_bits(chip, reg, mask, val);
}
-static int snd_es18xx_reg_read(es18xx_t *chip, unsigned char reg)
+static int snd_es18xx_reg_read(struct snd_es18xx *chip, unsigned char reg)
{
if (reg < 0xa0)
return snd_es18xx_mixer_read(chip, reg);
@@ -1064,7 +1070,7 @@ static int snd_es18xx_reg_read(es18xx_t *chip, unsigned char reg)
.get = snd_es18xx_get_single, .put = snd_es18xx_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_es18xx_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1075,9 +1081,9 @@ static int snd_es18xx_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es18xx_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1091,9 +1097,9 @@ static int snd_es18xx_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es18xx_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1114,7 +1120,7 @@ static int snd_es18xx_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_es18xx_get_double, .put = snd_es18xx_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_es18xx_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es18xx_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1125,9 +1131,9 @@ static int snd_es18xx_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es18xx_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1150,9 +1156,9 @@ static int snd_es18xx_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es18xx_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es18xx_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- es18xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1185,7 +1191,7 @@ static int snd_es18xx_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t snd_es18xx_base_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_base_controls[] = {
ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0),
@@ -1207,10 +1213,10 @@ ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
}
};
-static snd_kcontrol_new_t snd_es18xx_mono_in_control =
+static struct snd_kcontrol_new snd_es18xx_mono_in_control =
ES18XX_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0);
-static snd_kcontrol_new_t snd_es18xx_recmix_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_recmix_controls[] = {
ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0),
ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0),
ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0),
@@ -1220,16 +1226,16 @@ ES18XX_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0),
ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
};
-static snd_kcontrol_new_t snd_es18xx_pcm1_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_pcm1_controls[] = {
ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0),
};
-static snd_kcontrol_new_t snd_es18xx_pcm2_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_pcm2_controls[] = {
ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0),
ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0)
};
-static snd_kcontrol_new_t snd_es18xx_spatializer_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_spatializer_controls[] = {
ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1240,13 +1246,13 @@ ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
}
};
-static snd_kcontrol_new_t snd_es18xx_micpre1_control =
+static struct snd_kcontrol_new snd_es18xx_micpre1_control =
ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0);
-static snd_kcontrol_new_t snd_es18xx_micpre2_control =
+static struct snd_kcontrol_new snd_es18xx_micpre2_control =
ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0);
-static snd_kcontrol_new_t snd_es18xx_hw_volume_controls[] = {
+static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Hardware Master Playback Volume",
@@ -1265,7 +1271,7 @@ ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
};
#if 0
-static int __devinit snd_es18xx_config_read(es18xx_t *chip, unsigned char reg)
+static int __devinit snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
{
int data;
unsigned long flags;
@@ -1277,7 +1283,7 @@ static int __devinit snd_es18xx_config_read(es18xx_t *chip, unsigned char reg)
}
#endif
-static void __devinit snd_es18xx_config_write(es18xx_t *chip,
+static void __devinit snd_es18xx_config_write(struct snd_es18xx *chip,
unsigned char reg, unsigned char data)
{
/* No need for spinlocks, this function is used only in
@@ -1289,7 +1295,7 @@ static void __devinit snd_es18xx_config_write(es18xx_t *chip,
#endif
}
-static int __devinit snd_es18xx_initialize(es18xx_t *chip)
+static int __devinit snd_es18xx_initialize(struct snd_es18xx *chip)
{
int mask = 0;
@@ -1438,7 +1444,7 @@ static int __devinit snd_es18xx_initialize(es18xx_t *chip)
return 0;
}
-static int __devinit snd_es18xx_identify(es18xx_t *chip)
+static int __devinit snd_es18xx_identify(struct snd_es18xx *chip)
{
int hi,lo;
@@ -1504,7 +1510,7 @@ static int __devinit snd_es18xx_identify(es18xx_t *chip)
return 0;
}
-static int __devinit snd_es18xx_probe(es18xx_t *chip)
+static int __devinit snd_es18xx_probe(struct snd_es18xx *chip)
{
if (snd_es18xx_identify(chip) < 0) {
snd_printk(KERN_ERR PFX "[0x%lx] ESS chip not found\n", chip->port);
@@ -1544,7 +1550,7 @@ static int __devinit snd_es18xx_probe(es18xx_t *chip)
return snd_es18xx_initialize(chip);
}
-static snd_pcm_ops_t snd_es18xx_playback_ops = {
+static struct snd_pcm_ops snd_es18xx_playback_ops = {
.open = snd_es18xx_playback_open,
.close = snd_es18xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1555,7 +1561,7 @@ static snd_pcm_ops_t snd_es18xx_playback_ops = {
.pointer = snd_es18xx_playback_pointer,
};
-static snd_pcm_ops_t snd_es18xx_capture_ops = {
+static struct snd_pcm_ops snd_es18xx_capture_ops = {
.open = snd_es18xx_capture_open,
.close = snd_es18xx_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1566,27 +1572,19 @@ static snd_pcm_ops_t snd_es18xx_capture_ops = {
.pointer = snd_es18xx_capture_pointer,
};
-static void snd_es18xx_pcm_free(snd_pcm_t *pcm)
-{
- es18xx_t *codec = pcm->private_data;
- codec->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
char str[16];
int err;
if (rpcm)
*rpcm = NULL;
sprintf(str, "ES%x", chip->version);
- if (chip->caps & ES18XX_PCM2) {
+ if (chip->caps & ES18XX_PCM2)
err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
- } else {
+ else
err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
- }
if (err < 0)
return err;
@@ -1595,7 +1593,6 @@ static int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpc
/* global setup */
pcm->private_data = chip;
- pcm->private_free = snd_es18xx_pcm_free;
pcm->info_flags = 0;
if (chip->caps & ES18XX_DUPLEX_SAME)
pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
@@ -1616,9 +1613,12 @@ static int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpc
/* Power Management support functions */
#ifdef CONFIG_PM
-static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state)
+static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
{
- es18xx_t *chip = card->pm_private_data;
+ struct snd_audiodrive *acard = card->private_data;
+ struct snd_es18xx *chip = acard->chip;
+
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
@@ -1631,18 +1631,20 @@ static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state)
return 0;
}
-static int snd_es18xx_resume(snd_card_t *card)
+static int snd_es18xx_resume(struct snd_card *card)
{
- es18xx_t *chip = card->pm_private_data;
+ struct snd_audiodrive *acard = card->private_data;
+ struct snd_es18xx *chip = acard->chip;
/* restore PM register, we won't wake till (not 0x07) i/o activity though */
snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_es18xx_free(es18xx_t *chip)
+static int snd_es18xx_free(struct snd_es18xx *chip)
{
release_and_free_resource(chip->res_port);
release_and_free_resource(chip->res_ctrl_port);
@@ -1661,21 +1663,21 @@ static int snd_es18xx_free(es18xx_t *chip)
return 0;
}
-static int snd_es18xx_dev_free(snd_device_t *device)
+static int snd_es18xx_dev_free(struct snd_device *device)
{
- es18xx_t *chip = device->device_data;
+ struct snd_es18xx *chip = device->device_data;
return snd_es18xx_free(chip);
}
-static int __devinit snd_es18xx_new_device(snd_card_t * card,
+static int __devinit snd_es18xx_new_device(struct snd_card *card,
unsigned long port,
unsigned long mpu_port,
unsigned long fm_port,
int irq, int dma1, int dma2,
- es18xx_t ** rchip)
+ struct snd_es18xx ** rchip)
{
- es18xx_t *chip;
- static snd_device_ops_t ops = {
+ struct snd_es18xx *chip;
+ static struct snd_device_ops ops = {
.dev_free = snd_es18xx_dev_free,
};
int err;
@@ -1736,9 +1738,9 @@ static int __devinit snd_es18xx_new_device(snd_card_t * card,
return 0;
}
-static int __devinit snd_es18xx_mixer(es18xx_t *chip)
+static int __devinit snd_es18xx_mixer(struct snd_es18xx *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
int err;
unsigned int idx;
@@ -1747,7 +1749,7 @@ static int __devinit snd_es18xx_mixer(es18xx_t *chip)
strcpy(card->mixername, chip->pcm->name);
for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip);
if (chip->caps & ES18XX_HWV) {
switch (idx) {
@@ -1805,7 +1807,7 @@ static int __devinit snd_es18xx_mixer(es18xx_t *chip)
}
if (chip->caps & ES18XX_HWV) {
for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip);
if (idx == 0)
chip->hw_volume = kctl;
@@ -1875,14 +1877,8 @@ MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
module_param_array(dma2, int, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
-struct snd_audiodrive {
-#ifdef CONFIG_PNP
- struct pnp_dev *dev;
- struct pnp_dev *devc;
-#endif
-};
-
-static snd_card_t *snd_audiodrive_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
#ifdef CONFIG_PNP
@@ -1989,227 +1985,281 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
#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)
+static struct snd_card *snd_es18xx_card_new(int dev)
{
- static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
- static int possible_dmas[] = {1, 0, 3, 5, -1};
- int xirq, xdma1, xdma2;
- snd_card_t *card;
- struct snd_audiodrive *acard;
- es18xx_t *chip;
- opl3_t *opl3;
- int err;
-
- card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ return snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_audiodrive));
- if (card == NULL)
- return -ENOMEM;
- acard = (struct snd_audiodrive *)card->private_data;
-#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if ((err = snd_audiodrive_pnp(dev, acard, pcard, pid)) < 0) {
- snd_card_free(card);
- return 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_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_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_printk(KERN_ERR PFX "unable to find a free DMA2\n");
- err = -EBUSY;
- goto _err;
- }
- }
+static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
+{
+ struct snd_audiodrive *acard = card->private_data;
+ struct snd_es18xx *chip;
+ struct snd_opl3 *opl3;
+ int err;
if ((err = snd_es18xx_new_device(card,
port[dev],
mpu_port[dev],
fm_port[dev],
- xirq, xdma1, xdma2,
+ irq[dev], dma1[dev], dma2[dev],
&chip)) < 0)
- goto _err;
+ return err;
+ acard->chip = chip;
sprintf(card->driver, "ES%x", chip->version);
+
sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
- if (xdma1 != xdma2)
+ if (dma1[dev] != dma2[dev])
sprintf(card->longname, "%s at 0x%lx, irq %d, dma1 %d, dma2 %d",
card->shortname,
chip->port,
- xirq, xdma1, xdma2);
+ irq[dev], dma1[dev], dma2[dev]);
else
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
card->shortname,
chip->port,
- xirq, xdma1);
+ irq[dev], dma1[dev]);
if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
- goto _err;
+ return err;
if ((err = snd_es18xx_mixer(chip)) < 0)
- goto _err;
+ return 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_WARNING PFX "opl3 not detected at 0x%lx\n", chip->fm_port);
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
- goto _err;
+ return err;
}
}
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
chip->mpu_port, 0,
- xirq, 0,
+ irq[dev], 0,
&chip->rmidi)) < 0)
- goto _err;
+ return 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);
+ return snd_card_register(card);
+}
- if ((err = snd_card_register(card)) < 0)
- goto _err;
+static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
+{
+ struct snd_card *card;
+ int err;
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_audiodrive_legacy[dev] = card;
+ card = snd_es18xx_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &devptr->dev);
+ if ((err = snd_audiodrive_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ platform_set_drvdata(devptr, card);
return 0;
-
- _err:
- snd_card_free(card);
- return err;
}
-static int __devinit snd_audiodrive_probe_legacy_port(unsigned long xport)
+static int __init snd_es18xx_nonpnp_probe(struct platform_device *pdev)
{
- static int dev;
- int res;
+ int dev = pdev->id;
+ int err;
+ static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
+ static int possible_dmas[] = {1, 0, 3, 5, -1};
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- if (is_isapnp_selected(dev))
- continue;
- port[dev] = xport;
- res = snd_audiodrive_probe(dev, NULL, NULL);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
+ if (irq[dev] == SNDRV_AUTO_IRQ) {
+ if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (dma1[dev] == SNDRV_AUTO_DMA) {
+ if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ return -EBUSY;
+ }
+ }
+ if (dma2[dev] == SNDRV_AUTO_DMA) {
+ if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ return -EBUSY;
+ }
+ }
+
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ return snd_es18xx_nonpnp_probe1(dev, pdev);
+ } else {
+ static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280};
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ port[dev] = possible_ports[i];
+ err = snd_es18xx_nonpnp_probe1(dev, pdev);
+ if (! err)
+ return 0;
+ }
+ return err;
}
- return -ENODEV;
}
+static int __devexit snd_es18xx_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_es18xx_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return snd_es18xx_suspend(platform_get_drvdata(dev), state);
+}
+
+static int snd_es18xx_nonpnp_resume(struct platform_device *dev)
+{
+ return snd_es18xx_resume(platform_get_drvdata(dev));
+}
+#endif
+
+#define ES18XX_DRIVER "snd_es18xx"
+
+static struct platform_driver snd_es18xx_nonpnp_driver = {
+ .probe = snd_es18xx_nonpnp_probe,
+ .remove = __devexit_p(snd_es18xx_nonpnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_es18xx_nonpnp_suspend,
+ .resume = snd_es18xx_nonpnp_resume,
+#endif
+ .driver = {
+ .name = ES18XX_DRIVER
+ },
+};
+
#ifdef CONFIG_PNP
-static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
+ struct snd_card *card;
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_audiodrive_probe(dev, card, id);
- if (res < 0)
- return res;
- dev++;
- return 0;
- }
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
- return -ENODEV;
+ card = snd_es18xx_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+
+ if ((res = snd_audiodrive_pnp(dev, card->private_data, pcard, pid)) < 0) {
+ snd_card_free(card);
+ return res;
+ }
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((res = snd_audiodrive_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return res;
+ }
+
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
static void __devexit snd_audiodrive_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_audiodrive_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state);
+}
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+static int snd_audiodrive_pnp_resume(struct pnp_card_link *pcard)
+{
+ return snd_es18xx_resume(pnp_get_card_drvdata(pcard));
}
+#endif
+
static struct pnp_card_driver es18xx_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "es18xx",
.id_table = snd_audiodrive_pnpids,
.probe = snd_audiodrive_pnp_detect,
.remove = __devexit_p(snd_audiodrive_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_audiodrive_pnp_suspend,
+ .resume = snd_audiodrive_pnp_resume,
+#endif
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_es18xx_unregister_all(void)
+{
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_card_driver(&es18xx_pnpc_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_es18xx_nonpnp_driver);
+}
+
static int __init alsa_card_es18xx_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
- int dev, cards = 0, i;
+ int i, err, cards = 0;
- /* legacy non-auto cards at first */
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (is_isapnp_selected(dev))
+ if ((err = platform_driver_register(&snd_es18xx_nonpnp_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ if (is_isapnp_selected(i))
continue;
- if (snd_audiodrive_probe(dev, NULL, NULL) >= 0)
- cards++;
+ device = platform_device_register_simple(ES18XX_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ cards++;
}
- /* legacy auto configured cards */
- i = snd_legacy_auto_probe(possible_ports, snd_audiodrive_probe_legacy_port);
- if (i > 0)
- cards += i;
-#ifdef CONFIG_PNP
- /* ISA PnP cards at last */
i = pnp_register_card_driver(&es18xx_pnpc_driver);
- if (i > 0)
+ if (i >= 0) {
+ pnp_registered = 1;
cards += i;
+ }
-#endif
if(!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&es18xx_pnpc_driver);
-#endif
#ifdef MODULE
snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_es18xx_unregister_all();
+ return err;
}
static void __exit alsa_card_es18xx_exit(void)
{
- int idx;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&es18xx_pnpc_driver);
-#endif
- for(idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_audiodrive_legacy[idx]);
+ snd_es18xx_unregister_all();
}
module_init(alsa_card_es18xx_init)
diff --git a/sound/isa/gus/gus_dma.c b/sound/isa/gus/gus_dma.c
index ef1b2e9832e4..930f4bc56f34 100644
--- a/sound/isa/gus/gus_dma.c
+++ b/sound/isa/gus/gus_dma.c
@@ -25,7 +25,7 @@
#include <sound/core.h>
#include <sound/gus.h>
-static void snd_gf1_dma_ack(snd_gus_card_t * gus)
+static void snd_gf1_dma_ack(struct snd_gus_card * gus)
{
unsigned long flags;
@@ -35,7 +35,7 @@ static void snd_gf1_dma_ack(snd_gus_card_t * gus)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-static void snd_gf1_dma_program(snd_gus_card_t * gus,
+static void snd_gf1_dma_program(struct snd_gus_card * gus,
unsigned int addr,
unsigned long buf_addr,
unsigned int count,
@@ -91,9 +91,9 @@ static void snd_gf1_dma_program(snd_gus_card_t * gus,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-static snd_gf1_dma_block_t *snd_gf1_dma_next_block(snd_gus_card_t * gus)
+static struct snd_gf1_dma_block *snd_gf1_dma_next_block(struct snd_gus_card * gus)
{
- snd_gf1_dma_block_t *block;
+ struct snd_gf1_dma_block *block;
/* PCM block have bigger priority than synthesizer one */
if (gus->gf1.dma_data_pcm) {
@@ -123,9 +123,9 @@ static snd_gf1_dma_block_t *snd_gf1_dma_next_block(snd_gus_card_t * gus)
}
-static void snd_gf1_dma_interrupt(snd_gus_card_t * gus)
+static void snd_gf1_dma_interrupt(struct snd_gus_card * gus)
{
- snd_gf1_dma_block_t *block;
+ struct snd_gf1_dma_block *block;
snd_gf1_dma_ack(gus);
if (gus->gf1.dma_ack)
@@ -147,7 +147,7 @@ static void snd_gf1_dma_interrupt(snd_gus_card_t * gus)
#endif
}
-int snd_gf1_dma_init(snd_gus_card_t * gus)
+int snd_gf1_dma_init(struct snd_gus_card * gus)
{
down(&gus->dma_mutex);
gus->gf1.dma_shared++;
@@ -164,9 +164,9 @@ int snd_gf1_dma_init(snd_gus_card_t * gus)
return 0;
}
-int snd_gf1_dma_done(snd_gus_card_t * gus)
+int snd_gf1_dma_done(struct snd_gus_card * gus)
{
- snd_gf1_dma_block_t *block;
+ struct snd_gf1_dma_block *block;
down(&gus->dma_mutex);
gus->gf1.dma_shared--;
@@ -189,13 +189,13 @@ int snd_gf1_dma_done(snd_gus_card_t * gus)
return 0;
}
-int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
- snd_gf1_dma_block_t * __block,
+int snd_gf1_dma_transfer_block(struct snd_gus_card * gus,
+ struct snd_gf1_dma_block * __block,
int atomic,
int synth)
{
unsigned long flags;
- snd_gf1_dma_block_t *block;
+ struct snd_gf1_dma_block *block;
block = kmalloc(sizeof(*block), atomic ? GFP_ATOMIC : GFP_KERNEL);
if (block == NULL) {
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c
index 22120b868b5c..f22fe7967fcc 100644
--- a/sound/isa/gus/gus_dram.c
+++ b/sound/isa/gus/gus_dram.c
@@ -26,7 +26,7 @@
#include <sound/info.h>
-static int snd_gus_dram_poke(snd_gus_card_t *gus, char __user *_buffer,
+static int snd_gus_dram_poke(struct snd_gus_card *gus, char __user *_buffer,
unsigned int address, unsigned int size)
{
unsigned long flags;
@@ -57,13 +57,13 @@ static int snd_gus_dram_poke(snd_gus_card_t *gus, char __user *_buffer,
}
-int snd_gus_dram_write(snd_gus_card_t *gus, char __user *buffer,
+int snd_gus_dram_write(struct snd_gus_card *gus, char __user *buffer,
unsigned int address, unsigned int size)
{
return snd_gus_dram_poke(gus, buffer, address, size);
}
-static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
+static int snd_gus_dram_peek(struct snd_gus_card *gus, char __user *_buffer,
unsigned int address, unsigned int size,
int rom)
{
@@ -95,7 +95,7 @@ static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
return 0;
}
-int snd_gus_dram_read(snd_gus_card_t *gus, char __user *buffer,
+int snd_gus_dram_read(struct snd_gus_card *gus, char __user *buffer,
unsigned int address, unsigned int size,
int rom)
{
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
index 591a9a17feb5..d0c38e1856ef 100644
--- a/sound/isa/gus/gus_instr.c
+++ b/sound/isa/gus/gus_instr.c
@@ -28,11 +28,11 @@
*
*/
-int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
- snd_gf1_mem_block_t *block;
+ struct snd_gus_card *gus = private_data;
+ struct snd_gf1_mem_block *block;
int err;
if (wave->format & IWFFFF_WAVE_ROM)
@@ -58,19 +58,19 @@ int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
return 0;
}
-int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
}
-int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
+int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave,
int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
if (wave->format & IWFFFF_WAVE_ROM)
return 0; /* it's probably ok - verify the address? */
@@ -81,11 +81,11 @@ int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
*
*/
-int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
- snd_gf1_mem_block_t *block;
+ struct snd_gus_card *gus = private_data;
+ struct snd_gf1_mem_block *block;
int err;
if (wave->format & GF1_WAVE_STEREO)
@@ -109,18 +109,18 @@ int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
return 0;
}
-int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
}
-int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
+int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave,
int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
}
@@ -129,11 +129,11 @@ int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
*
*/
-int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
- snd_gf1_mem_block_t *block;
+ struct snd_gus_card *gus = private_data;
+ struct snd_gf1_mem_block *block;
int err;
if (instr->format & SIMPLE_WAVE_STEREO)
@@ -156,18 +156,18 @@ int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
return 0;
}
-int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr,
char __user *data, long len, int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
}
-int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
+int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr,
int atomic)
{
- snd_gus_card_t *gus = private_data;
+ struct snd_gus_card *gus = private_data;
return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
}
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index 8d5752b23787..9b1fe292de4d 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -25,7 +25,7 @@
#include <sound/core.h>
#include <sound/gus.h>
-void snd_gf1_delay(snd_gus_card_t * gus)
+void snd_gf1_delay(struct snd_gus_card * gus)
{
int i;
@@ -44,7 +44,7 @@ void snd_gf1_delay(snd_gus_card_t * gus)
* big UltraClick (tm) elimination...
*/
-static inline void __snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
+static inline void __snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg)
{
unsigned char value;
@@ -58,7 +58,7 @@ static inline void __snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
mb();
}
-static inline void __snd_gf1_write8(snd_gus_card_t * gus,
+static inline void __snd_gf1_write8(struct snd_gus_card * gus,
unsigned char reg,
unsigned char data)
{
@@ -68,7 +68,7 @@ static inline void __snd_gf1_write8(snd_gus_card_t * gus,
mb();
}
-static inline unsigned char __snd_gf1_look8(snd_gus_card_t * gus,
+static inline unsigned char __snd_gf1_look8(struct snd_gus_card * gus,
unsigned char reg)
{
outb(reg, gus->gf1.reg_regsel);
@@ -76,7 +76,7 @@ static inline unsigned char __snd_gf1_look8(snd_gus_card_t * gus,
return inb(gus->gf1.reg_data8);
}
-static inline void __snd_gf1_write16(snd_gus_card_t * gus,
+static inline void __snd_gf1_write16(struct snd_gus_card * gus,
unsigned char reg, unsigned int data)
{
outb(reg, gus->gf1.reg_regsel);
@@ -85,7 +85,7 @@ static inline void __snd_gf1_write16(snd_gus_card_t * gus,
mb();
}
-static inline unsigned short __snd_gf1_look16(snd_gus_card_t * gus,
+static inline unsigned short __snd_gf1_look16(struct snd_gus_card * gus,
unsigned char reg)
{
outb(reg, gus->gf1.reg_regsel);
@@ -93,7 +93,7 @@ static inline unsigned short __snd_gf1_look16(snd_gus_card_t * gus,
return inw(gus->gf1.reg_data16);
}
-static inline void __snd_gf1_adlib_write(snd_gus_card_t * gus,
+static inline void __snd_gf1_adlib_write(struct snd_gus_card * gus,
unsigned char reg, unsigned char data)
{
outb(reg, gus->gf1.reg_timerctrl);
@@ -104,7 +104,7 @@ static inline void __snd_gf1_adlib_write(snd_gus_card_t * gus,
inb(gus->gf1.reg_timerctrl);
}
-static inline void __snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg,
+static inline void __snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg,
unsigned int addr, int w_16bit)
{
if (gus->gf1.enh_mode) {
@@ -117,7 +117,7 @@ static inline void __snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg,
__snd_gf1_write16(gus, reg + 1, (unsigned short) (addr << 5));
}
-static inline unsigned int __snd_gf1_read_addr(snd_gus_card_t * gus,
+static inline unsigned int __snd_gf1_read_addr(struct snd_gus_card * gus,
unsigned char reg, short w_16bit)
{
unsigned int res;
@@ -138,49 +138,49 @@ static inline unsigned int __snd_gf1_read_addr(snd_gus_card_t * gus,
* =======================================================================
*/
-void snd_gf1_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
+void snd_gf1_ctrl_stop(struct snd_gus_card * gus, unsigned char reg)
{
__snd_gf1_ctrl_stop(gus, reg);
}
-void snd_gf1_write8(snd_gus_card_t * gus,
+void snd_gf1_write8(struct snd_gus_card * gus,
unsigned char reg,
unsigned char data)
{
__snd_gf1_write8(gus, reg, data);
}
-unsigned char snd_gf1_look8(snd_gus_card_t * gus, unsigned char reg)
+unsigned char snd_gf1_look8(struct snd_gus_card * gus, unsigned char reg)
{
return __snd_gf1_look8(gus, reg);
}
-void snd_gf1_write16(snd_gus_card_t * gus,
+void snd_gf1_write16(struct snd_gus_card * gus,
unsigned char reg,
unsigned int data)
{
__snd_gf1_write16(gus, reg, data);
}
-unsigned short snd_gf1_look16(snd_gus_card_t * gus, unsigned char reg)
+unsigned short snd_gf1_look16(struct snd_gus_card * gus, unsigned char reg)
{
return __snd_gf1_look16(gus, reg);
}
-void snd_gf1_adlib_write(snd_gus_card_t * gus,
+void snd_gf1_adlib_write(struct snd_gus_card * gus,
unsigned char reg,
unsigned char data)
{
__snd_gf1_adlib_write(gus, reg, data);
}
-void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg,
+void snd_gf1_write_addr(struct snd_gus_card * gus, unsigned char reg,
unsigned int addr, short w_16bit)
{
__snd_gf1_write_addr(gus, reg, addr, w_16bit);
}
-unsigned int snd_gf1_read_addr(snd_gus_card_t * gus,
+unsigned int snd_gf1_read_addr(struct snd_gus_card * gus,
unsigned char reg,
short w_16bit)
{
@@ -191,7 +191,7 @@ unsigned int snd_gf1_read_addr(snd_gus_card_t * gus,
*/
-void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
+void snd_gf1_i_ctrl_stop(struct snd_gus_card * gus, unsigned char reg)
{
unsigned long flags;
@@ -200,7 +200,7 @@ void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-void snd_gf1_i_write8(snd_gus_card_t * gus,
+void snd_gf1_i_write8(struct snd_gus_card * gus,
unsigned char reg,
unsigned char data)
{
@@ -211,7 +211,7 @@ void snd_gf1_i_write8(snd_gus_card_t * gus,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-unsigned char snd_gf1_i_look8(snd_gus_card_t * gus, unsigned char reg)
+unsigned char snd_gf1_i_look8(struct snd_gus_card * gus, unsigned char reg)
{
unsigned long flags;
unsigned char res;
@@ -222,7 +222,7 @@ unsigned char snd_gf1_i_look8(snd_gus_card_t * gus, unsigned char reg)
return res;
}
-void snd_gf1_i_write16(snd_gus_card_t * gus,
+void snd_gf1_i_write16(struct snd_gus_card * gus,
unsigned char reg,
unsigned int data)
{
@@ -233,7 +233,7 @@ void snd_gf1_i_write16(snd_gus_card_t * gus,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
+unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg)
{
unsigned long flags;
unsigned short res;
@@ -246,7 +246,7 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
#if 0
-void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
+void snd_gf1_i_adlib_write(struct snd_gus_card * gus,
unsigned char reg,
unsigned char data)
{
@@ -257,7 +257,7 @@ void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
+void snd_gf1_i_write_addr(struct snd_gus_card * gus, unsigned char reg,
unsigned int addr, short w_16bit)
{
unsigned long flags;
@@ -270,7 +270,7 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
#endif /* 0 */
#ifdef CONFIG_SND_DEBUG
-static unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
+static unsigned int snd_gf1_i_read_addr(struct snd_gus_card * gus,
unsigned char reg, short w_16bit)
{
unsigned int res;
@@ -287,7 +287,7 @@ static unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
*/
-void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr)
+void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr)
{
outb(0x43, gus->gf1.reg_regsel);
mb();
@@ -299,7 +299,7 @@ void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr)
mb();
}
-void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data)
+void snd_gf1_poke(struct snd_gus_card * gus, unsigned int addr, unsigned char data)
{
unsigned long flags;
@@ -316,7 +316,7 @@ void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
+unsigned char snd_gf1_peek(struct snd_gus_card * gus, unsigned int addr)
{
unsigned long flags;
unsigned char res;
@@ -337,7 +337,7 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
#if 0
-void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
+void snd_gf1_pokew(struct snd_gus_card * gus, unsigned int addr, unsigned short data)
{
unsigned long flags;
@@ -360,7 +360,7 @@ void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr)
+unsigned short snd_gf1_peekw(struct snd_gus_card * gus, unsigned int addr)
{
unsigned long flags;
unsigned short res;
@@ -385,7 +385,7 @@ unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr)
return res;
}
-void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
+void snd_gf1_dram_setmem(struct snd_gus_card * gus, unsigned int addr,
unsigned short value, unsigned int count)
{
unsigned long port;
@@ -415,7 +415,7 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
#endif /* 0 */
-void snd_gf1_select_active_voices(snd_gus_card_t * gus)
+void snd_gf1_select_active_voices(struct snd_gus_card * gus)
{
unsigned short voices;
@@ -443,7 +443,7 @@ void snd_gf1_select_active_voices(snd_gus_card_t * gus)
#ifdef CONFIG_SND_DEBUG
-void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
+void snd_gf1_print_voice_registers(struct snd_gus_card * gus)
{
unsigned char mode;
int voice, ctrl;
@@ -477,7 +477,7 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
#if 0
-void snd_gf1_print_global_registers(snd_gus_card_t * gus)
+void snd_gf1_print_global_registers(struct snd_gus_card * gus)
{
unsigned char global_mode = 0x00;
@@ -504,7 +504,7 @@ void snd_gf1_print_global_registers(snd_gus_card_t * gus)
}
}
-void snd_gf1_print_setup_registers(snd_gus_card_t * gus)
+void snd_gf1_print_setup_registers(struct snd_gus_card * gus)
{
printk(KERN_INFO " -S- mix control = 0x%x\n", inb(GUSP(gus, MIXCNTRLREG)));
printk(KERN_INFO " -S- IRQ status = 0x%x\n", inb(GUSP(gus, IRQSTAT)));
@@ -523,7 +523,7 @@ void snd_gf1_print_setup_registers(snd_gus_card_t * gus)
}
}
-void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit)
+void snd_gf1_peek_print_block(struct snd_gus_card * gus, unsigned int addr, int count, int w_16bit)
{
if (!w_16bit) {
while (count-- > 0)
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 1e2a15eb8106..c19ba2910b72 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -32,7 +32,7 @@
irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- snd_gus_card_t * gus = dev_id;
+ struct snd_gus_card * gus = dev_id;
unsigned char status;
int loop = 100;
int handled = 0;
@@ -54,7 +54,7 @@ __again:
if (status & (0x20 | 0x40)) {
unsigned int already, _current_;
unsigned char voice_status, voice;
- snd_gus_voice_t *pvoice;
+ struct snd_gus_voice *pvoice;
already = 0;
while (((voice_status = snd_gf1_i_read8(gus, SNDRV_GF1_GB_VOICES_IRQ)) & 0xc0) != 0xc0) {
@@ -107,11 +107,11 @@ __again:
}
#ifdef CONFIG_SND_DEBUG
-static void snd_gus_irq_info_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_gus_irq_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_gus_card_t *gus;
- snd_gus_voice_t *pvoice;
+ struct snd_gus_card *gus;
+ struct snd_gus_voice *pvoice;
int idx;
gus = entry->private_data;
@@ -131,9 +131,9 @@ static void snd_gus_irq_info_read(snd_info_entry_t *entry,
}
}
-void snd_gus_irq_profile_init(snd_gus_card_t *gus)
+void snd_gus_irq_profile_init(struct snd_gus_card *gus)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(gus->card, "gusirq", &entry))
snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read);
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 4f57ff4ab351..6d15b3d18a87 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -35,21 +35,21 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
MODULE_LICENSE("GPL");
-static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
+static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches);
-int snd_gus_use_inc(snd_gus_card_t * gus)
+int snd_gus_use_inc(struct snd_gus_card * gus)
{
if (!try_module_get(gus->card->module))
return 0;
return 1;
}
-void snd_gus_use_dec(snd_gus_card_t * gus)
+void snd_gus_use_dec(struct snd_gus_card * gus)
{
module_put(gus->card->module);
}
-static int snd_gus_joystick_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_gus_joystick_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -58,17 +58,17 @@ static int snd_gus_joystick_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_gus_joystick_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gus_joystick_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = gus->joystick_dac & 31;
return 0;
}
-static int snd_gus_joystick_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval;
@@ -82,7 +82,7 @@ static int snd_gus_joystick_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t snd_gus_joystick_control = {
+static struct snd_kcontrol_new snd_gus_joystick_control = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "Joystick Speed",
.info = snd_gus_joystick_info,
@@ -90,7 +90,7 @@ static snd_kcontrol_new_t snd_gus_joystick_control = {
.put = snd_gus_joystick_put
};
-static void snd_gus_init_control(snd_gus_card_t *gus)
+static void snd_gus_init_control(struct snd_gus_card *gus)
{
if (!gus->ace_flag)
snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus));
@@ -100,7 +100,7 @@ static void snd_gus_init_control(snd_gus_card_t *gus)
*
*/
-static int snd_gus_free(snd_gus_card_t *gus)
+static int snd_gus_free(struct snd_gus_card *gus)
{
if (gus->gf1.res_port2 == NULL)
goto __hw_end;
@@ -129,24 +129,24 @@ static int snd_gus_free(snd_gus_card_t *gus)
return 0;
}
-static int snd_gus_dev_free(snd_device_t *device)
+static int snd_gus_dev_free(struct snd_device *device)
{
- snd_gus_card_t *gus = device->device_data;
+ struct snd_gus_card *gus = device->device_data;
return snd_gus_free(gus);
}
-int snd_gus_create(snd_card_t * card,
+int snd_gus_create(struct snd_card *card,
unsigned long port,
int irq, int dma1, int dma2,
int timer_dev,
int voices,
int pcm_channels,
int effect,
- snd_gus_card_t **rgus)
+ struct snd_gus_card **rgus)
{
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_gus_dev_free,
};
@@ -238,7 +238,7 @@ int snd_gus_create(snd_card_t * card,
* Memory detection routine for plain GF1 soundcards
*/
-static int snd_gus_detect_memory(snd_gus_card_t * gus)
+static int snd_gus_detect_memory(struct snd_gus_card * gus)
{
int l, idx, local;
unsigned char d;
@@ -273,9 +273,9 @@ static int snd_gus_detect_memory(snd_gus_card_t * gus)
return 0; /* some memory were detected */
}
-static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches)
+static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned long flags;
int irq, dma1, dma2;
static unsigned char irqs[16] =
@@ -360,11 +360,11 @@ static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches)
return 0;
}
-static int snd_gus_check_version(snd_gus_card_t * gus)
+static int snd_gus_check_version(struct snd_gus_card * gus)
{
unsigned long flags;
unsigned char val, rev;
- snd_card_t *card;
+ struct snd_card *card;
card = gus->card;
spin_lock_irqsave(&gus->reg_lock, flags);
@@ -409,14 +409,14 @@ static int snd_gus_check_version(snd_gus_card_t * gus)
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
+static void snd_gus_seq_dev_free(struct snd_seq_device *seq_dev)
{
- snd_gus_card_t *gus = seq_dev->private_data;
+ struct snd_gus_card *gus = seq_dev->private_data;
gus->seq_dev = NULL;
}
#endif
-int snd_gus_initialize(snd_gus_card_t *gus)
+int snd_gus_initialize(struct snd_gus_card *gus)
{
int err;
@@ -432,9 +432,9 @@ int snd_gus_initialize(snd_gus_card_t *gus)
return err;
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS,
- sizeof(snd_gus_card_t*), &gus->seq_dev) >= 0) {
+ sizeof(struct snd_gus_card *), &gus->seq_dev) >= 0) {
strcpy(gus->seq_dev->name, "GUS");
- *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus;
+ *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus;
gus->seq_dev->private_data = gus;
gus->seq_dev->private_free = snd_gus_seq_dev_free;
}
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index 2e23f2a8c627..e8bdb860a19f 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -27,11 +27,11 @@
#include <sound/info.h>
#ifdef CONFIG_SND_DEBUG
-static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer);
+static void snd_gf1_mem_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer);
#endif
-void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
+void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup)
{
if (!xup) {
down(&alloc->memory_mutex);
@@ -40,12 +40,12 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
}
}
-static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
- snd_gf1_mem_block_t * block)
+static struct snd_gf1_mem_block *snd_gf1_mem_xalloc(struct snd_gf1_mem * alloc,
+ struct snd_gf1_mem_block * block)
{
- snd_gf1_mem_block_t *pblock, *nblock;
+ struct snd_gf1_mem_block *pblock, *nblock;
- nblock = (snd_gf1_mem_block_t *) kmalloc(sizeof(snd_gf1_mem_block_t), GFP_KERNEL);
+ nblock = kmalloc(sizeof(struct snd_gf1_mem_block), GFP_KERNEL);
if (nblock == NULL)
return NULL;
*nblock = *block;
@@ -76,7 +76,7 @@ static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
return nblock;
}
-int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
+int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block)
{
if (block->share) { /* ok.. shared block */
block->share--;
@@ -106,10 +106,10 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
return 0;
}
-static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+static struct snd_gf1_mem_block *snd_gf1_mem_look(struct snd_gf1_mem * alloc,
unsigned int address)
{
- snd_gf1_mem_block_t *block;
+ struct snd_gf1_mem_block *block;
for (block = alloc->first; block; block = block->next) {
if (block->ptr == address) {
@@ -119,10 +119,10 @@ static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
return NULL;
}
-static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+static struct snd_gf1_mem_block *snd_gf1_mem_share(struct snd_gf1_mem * alloc,
unsigned int *share_id)
{
- snd_gf1_mem_block_t *block;
+ struct snd_gf1_mem_block *block;
if (!share_id[0] && !share_id[1] &&
!share_id[2] && !share_id[3])
@@ -133,14 +133,14 @@ static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
return NULL;
}
-static int snd_gf1_mem_find(snd_gf1_mem_t * alloc,
- snd_gf1_mem_block_t * block,
+static int snd_gf1_mem_find(struct snd_gf1_mem * alloc,
+ struct snd_gf1_mem_block * block,
unsigned int size, int w_16, int align)
{
- snd_gf1_bank_info_t *info = w_16 ? alloc->banks_16 : alloc->banks_8;
+ struct snd_gf1_bank_info *info = w_16 ? alloc->banks_16 : alloc->banks_8;
unsigned int idx, boundary;
int size1;
- snd_gf1_mem_block_t *pblock;
+ struct snd_gf1_mem_block *pblock;
unsigned int ptr1, ptr2;
align--;
@@ -186,11 +186,11 @@ static int snd_gf1_mem_find(snd_gf1_mem_t * alloc,
return -ENOMEM;
}
-snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
+struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner,
char *name, int size, int w_16, int align,
unsigned int *share_id)
{
- snd_gf1_mem_block_t block, *nblock;
+ struct snd_gf1_mem_block block, *nblock;
snd_gf1_mem_lock(alloc, 0);
if (share_id != NULL) {
@@ -220,10 +220,10 @@ snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
return nblock;
}
-int snd_gf1_mem_free(snd_gf1_mem_t * alloc, unsigned int address)
+int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address)
{
int result;
- snd_gf1_mem_block_t *block;
+ struct snd_gf1_mem_block *block;
snd_gf1_mem_lock(alloc, 0);
if ((block = snd_gf1_mem_look(alloc, address)) != NULL) {
@@ -235,12 +235,12 @@ int snd_gf1_mem_free(snd_gf1_mem_t * alloc, unsigned int address)
return -EINVAL;
}
-int snd_gf1_mem_init(snd_gus_card_t * gus)
+int snd_gf1_mem_init(struct snd_gus_card * gus)
{
- snd_gf1_mem_t *alloc;
- snd_gf1_mem_block_t block;
+ struct snd_gf1_mem *alloc;
+ struct snd_gf1_mem_block block;
#ifdef CONFIG_SND_DEBUG
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
#endif
alloc = &gus->gf1.mem_alloc;
@@ -272,10 +272,10 @@ int snd_gf1_mem_init(snd_gus_card_t * gus)
return 0;
}
-int snd_gf1_mem_done(snd_gus_card_t * gus)
+int snd_gf1_mem_done(struct snd_gus_card * gus)
{
- snd_gf1_mem_t *alloc;
- snd_gf1_mem_block_t *block, *nblock;
+ struct snd_gf1_mem *alloc;
+ struct snd_gf1_mem_block *block, *nblock;
alloc = &gus->gf1.mem_alloc;
block = alloc->first;
@@ -288,12 +288,12 @@ int snd_gf1_mem_done(snd_gus_card_t * gus)
}
#ifdef CONFIG_SND_DEBUG
-static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_gf1_mem_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- snd_gus_card_t *gus;
- snd_gf1_mem_t *alloc;
- snd_gf1_mem_block_t *block;
+ struct snd_gus_card *gus;
+ struct snd_gf1_mem *alloc;
+ struct snd_gf1_mem_block *block;
unsigned int total, used;
int i;
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 7f96ac237f3c..4080255007d5 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -25,20 +25,20 @@
#include <sound/gus.h>
#include <sound/info.h>
-typedef struct gus_proc_private {
+struct gus_proc_private {
int rom; /* data are in ROM */
unsigned int address;
unsigned int size;
- snd_gus_card_t * gus;
-} gus_proc_private_t;
+ struct snd_gus_card * gus;
+};
-static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_data,
+static long snd_gf1_mem_proc_dump(struct snd_info_entry *entry, void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
long size;
- gus_proc_private_t *priv = entry->private_data;
- snd_gus_card_t *gus = priv->gus;
+ struct gus_proc_private *priv = entry->private_data;
+ struct snd_gus_card *gus = priv->gus;
int err;
size = count;
@@ -52,13 +52,13 @@ static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_da
return 0;
}
-static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
+static long long snd_gf1_mem_proc_llseek(struct snd_info_entry *entry,
void *private_file_data,
struct file *file,
long long offset,
int orig)
{
- gus_proc_private_t *priv = entry->private_data;
+ struct gus_proc_private *priv = entry->private_data;
switch (orig) {
case 0: /* SEEK_SET */
@@ -78,9 +78,9 @@ static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
return file->f_pos;
}
-static void snd_gf1_mem_proc_free(snd_info_entry_t *entry)
+static void snd_gf1_mem_proc_free(struct snd_info_entry *entry)
{
- gus_proc_private_t *priv = entry->private_data;
+ struct gus_proc_private *priv = entry->private_data;
kfree(priv);
}
@@ -89,12 +89,12 @@ static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
.llseek = snd_gf1_mem_proc_llseek,
};
-int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
+int snd_gf1_mem_proc_init(struct snd_gus_card * gus)
{
int idx;
char name[16];
- gus_proc_private_t *priv;
- snd_info_entry_t *entry;
+ struct gus_proc_private *priv;
+ struct snd_info_entry *entry;
for (idx = 0; idx < 4; idx++) {
if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
index a051094d510e..acc25a297200 100644
--- a/sound/isa/gus/gus_mixer.c
+++ b/sound/isa/gus/gus_mixer.c
@@ -36,7 +36,7 @@
.get = snd_gf1_get_single, .put = snd_gf1_put_single, \
.private_value = shift | (invert << 8) }
-static int snd_gf1_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_gf1_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -45,9 +45,9 @@ static int snd_gf1_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_gf1_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
@@ -57,9 +57,9 @@ static int snd_gf1_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_gf1_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
@@ -86,7 +86,7 @@ static int snd_gf1_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
.get = snd_ics_get_double, .put = snd_ics_put_double, \
.private_value = addr }
-static int snd_ics_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ics_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -95,9 +95,9 @@ static int snd_ics_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_ics_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int addr = kcontrol->private_value & 0xff;
unsigned char left, right;
@@ -111,9 +111,9 @@ static int snd_ics_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_ics_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int addr = kcontrol->private_value & 0xff;
int change;
@@ -146,13 +146,13 @@ static int snd_ics_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return change;
}
-static snd_kcontrol_new_t snd_gf1_controls[] = {
+static struct snd_kcontrol_new snd_gf1_controls[] = {
GF1_SINGLE("Master Playback Switch", 0, 1, 1),
GF1_SINGLE("Line Switch", 0, 0, 1),
GF1_SINGLE("Mic Switch", 0, 2, 0)
};
-static snd_kcontrol_new_t snd_ics_controls[] = {
+static struct snd_kcontrol_new snd_ics_controls[] = {
GF1_SINGLE("Master Playback Switch", 0, 1, 1),
ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV),
@@ -163,9 +163,9 @@ ICS_DOUBLE("Mic Playback Volume", 0, SNDRV_ICS_MIC_DEV),
ICS_DOUBLE("CD Playback Volume", 0, SNDRV_ICS_CD_DEV)
};
-int snd_gf1_new_mixer(snd_gus_card_t * gus)
+int snd_gf1_new_mixer(struct snd_gus_card * gus)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx, max;
int err;
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 1cc89fb67bf2..d0829393ec8a 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -42,12 +42,12 @@
#define SNDRV_GF1_PCM_PFLG_ACTIVE (1<<0)
#define SNDRV_GF1_PCM_PFLG_NEUTRAL (2<<0)
-typedef struct {
- snd_gus_card_t * gus;
- snd_pcm_substream_t * substream;
+struct gus_pcm_private {
+ struct snd_gus_card * gus;
+ struct snd_pcm_substream *substream;
spinlock_t lock;
unsigned int voices;
- snd_gus_voice_t *pvoices[2];
+ struct snd_gus_voice *pvoices[2];
unsigned int memory;
unsigned short flags;
unsigned char voice_ctrl, ramp_ctrl;
@@ -58,13 +58,13 @@ typedef struct {
wait_queue_head_t sleep;
atomic_t dma_count;
int final_volume;
-} gus_pcm_private_t;
+};
static int snd_gf1_pcm_use_dma = 1;
-static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_data)
+static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data)
{
- gus_pcm_private_t *pcmp = private_data;
+ struct gus_pcm_private *pcmp = private_data;
if (pcmp) {
atomic_dec(&pcmp->dma_count);
@@ -72,14 +72,14 @@ static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_dat
}
}
-static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
+static int snd_gf1_pcm_block_change(struct snd_pcm_substream *substream,
unsigned int offset,
unsigned int addr,
unsigned int count)
{
- snd_gf1_dma_block_t block;
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_gf1_dma_block block;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
count += offset & 31;
offset &= ~31;
@@ -101,11 +101,11 @@ static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
return 0;
}
-static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
+static void snd_gf1_pcm_trigger_up(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
- snd_gus_card_t * gus = pcmp->gus;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
+ struct snd_gus_card * gus = pcmp->gus;
unsigned long flags;
unsigned char voice_ctrl, ramp_ctrl;
unsigned short rate;
@@ -179,10 +179,11 @@ static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-static void snd_gf1_pcm_interrupt_wave(snd_gus_card_t * gus, snd_gus_voice_t *pvoice)
+static void snd_gf1_pcm_interrupt_wave(struct snd_gus_card * gus,
+ struct snd_gus_voice *pvoice)
{
- gus_pcm_private_t * pcmp;
- snd_pcm_runtime_t * runtime;
+ struct gus_pcm_private * pcmp;
+ struct snd_pcm_runtime *runtime;
unsigned char voice_ctrl, ramp_ctrl;
unsigned int idx;
unsigned int end, step;
@@ -261,11 +262,12 @@ static void snd_gf1_pcm_interrupt_wave(snd_gus_card_t * gus, snd_gus_voice_t *pv
#endif
}
-static void snd_gf1_pcm_interrupt_volume(snd_gus_card_t * gus, snd_gus_voice_t * pvoice)
+static void snd_gf1_pcm_interrupt_volume(struct snd_gus_card * gus,
+ struct snd_gus_voice * pvoice)
{
unsigned short vol;
int cvoice;
- gus_pcm_private_t *pcmp = pvoice->private_data;
+ struct gus_pcm_private *pcmp = pvoice->private_data;
/* stop ramp, but leave rollover bit untouched */
spin_lock(&gus->reg_lock);
@@ -289,11 +291,11 @@ static void snd_gf1_pcm_interrupt_volume(snd_gus_card_t * gus, snd_gus_voice_t *
spin_unlock(&gus->reg_lock);
}
-static void snd_gf1_pcm_volume_change(snd_gus_card_t * gus)
+static void snd_gf1_pcm_volume_change(struct snd_gus_card * gus)
{
}
-static int snd_gf1_pcm_poke_block(snd_gus_card_t *gus, unsigned char *buf,
+static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf,
unsigned int pos, unsigned int count,
int w16, int invert)
{
@@ -341,14 +343,14 @@ static int snd_gf1_pcm_poke_block(snd_gus_card_t *gus, unsigned char *buf,
return 0;
}
-static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
+static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
int voice,
snd_pcm_uframes_t pos,
void __user *src,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
unsigned int bpos, len;
bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -360,7 +362,7 @@ static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
if (snd_gf1_pcm_use_dma && len > 32) {
return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
} else {
- snd_gus_card_t *gus = pcmp->gus;
+ struct snd_gus_card *gus = pcmp->gus;
int err, w16, invert;
w16 = (snd_pcm_format_width(runtime->format) == 16);
@@ -371,13 +373,13 @@ static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
+static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
int voice,
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
unsigned int bpos, len;
bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -388,7 +390,7 @@ static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
if (snd_gf1_pcm_use_dma && len > 32) {
return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
} else {
- snd_gus_card_t *gus = pcmp->gus;
+ struct snd_gus_card *gus = pcmp->gus;
int err, w16, invert;
w16 = (snd_pcm_format_width(runtime->format) == 16);
@@ -399,18 +401,18 @@ static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
int err;
if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
return err;
if (err > 0) { /* change */
- snd_gf1_mem_block_t *block;
+ struct snd_gf1_mem_block *block;
if (pcmp->memory > 0) {
snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory);
pcmp->memory = 0;
@@ -448,10 +450,10 @@ static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_playback_hw_free(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
snd_pcm_lib_free_pages(substream);
if (pcmp->pvoices[0]) {
@@ -469,10 +471,10 @@ static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
pcmp->bpos = 0;
pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -481,12 +483,12 @@ static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_gf1_pcm_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_gf1_pcm_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
int voice;
if (cmd == SNDRV_PCM_TRIGGER_START) {
@@ -507,11 +509,11 @@ static int snd_gf1_pcm_playback_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream *substream)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
unsigned int pos;
unsigned char voice_ctrl;
@@ -529,22 +531,22 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(snd_pcm_substream_t * subs
return pos;
}
-static ratnum_t clock = {
+static struct snd_ratnum clock = {
.num = 9878400/16,
.den_min = 2,
.den_max = 257,
.den_step = 1,
};
-static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
.nrats = 1,
.rats = &clock,
};
-static int snd_gf1_pcm_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_gf1_pcm_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
gus->c_dma_size = params_buffer_bytes(hw_params);
gus->c_period_size = params_period_bytes(hw_params);
@@ -559,15 +561,15 @@ static int snd_gf1_pcm_capture_hw_params(snd_pcm_substream_t * substream,
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_gf1_pcm_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_capture_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_gf1_pcm_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_capture_prepare(struct snd_pcm_substream *substream)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RECORD_RATE, runtime->rate_den - 2);
snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */
@@ -576,10 +578,10 @@ static int snd_gf1_pcm_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_gf1_pcm_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_gf1_pcm_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
int val;
if (cmd == SNDRV_PCM_TRIGGER_START) {
@@ -597,15 +599,15 @@ static int snd_gf1_pcm_capture_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_gf1_pcm_capture_pointer(struct snd_pcm_substream *substream)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
int pos = snd_dma_pointer(gus->gf1.dma2, gus->c_period_size);
pos = bytes_to_frames(substream->runtime, (gus->c_pos + pos) % gus->c_dma_size);
return pos;
}
-static void snd_gf1_pcm_interrupt_dma_read(snd_gus_card_t * gus)
+static void snd_gf1_pcm_interrupt_dma_read(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL, 0); /* disable sampling */
snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL); /* Sampling Control Register */
@@ -617,7 +619,7 @@ static void snd_gf1_pcm_interrupt_dma_read(snd_gus_card_t * gus)
}
}
-static snd_pcm_hardware_t snd_gf1_pcm_playback =
+static struct snd_pcm_hardware snd_gf1_pcm_playback =
{
.info = SNDRV_PCM_INFO_NONINTERLEAVED,
.formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
@@ -635,7 +637,7 @@ static snd_pcm_hardware_t snd_gf1_pcm_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_gf1_pcm_capture =
+static struct snd_pcm_hardware snd_gf1_pcm_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -653,16 +655,16 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
.fifo_size = 0,
};
-static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
+static void snd_gf1_pcm_playback_free(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
-static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
+static int snd_gf1_pcm_playback_open(struct snd_pcm_substream *substream)
{
- gus_pcm_private_t *pcmp;
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
pcmp = kzalloc(sizeof(*pcmp), GFP_KERNEL);
@@ -690,11 +692,11 @@ static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_playback_close(struct snd_pcm_substream *substream)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- gus_pcm_private_t *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ))
snd_printk(KERN_ERR "gf1 pcm - serious DMA problem\n");
@@ -703,10 +705,10 @@ static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_gf1_pcm_capture_open(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_capture_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
gus->gf1.interrupt_handler_dma_read = snd_gf1_pcm_interrupt_dma_read;
gus->pcm_cap_substream = substream;
@@ -718,23 +720,16 @@ static int snd_gf1_pcm_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_gf1_pcm_capture_close(snd_pcm_substream_t * substream)
+static int snd_gf1_pcm_capture_close(struct snd_pcm_substream *substream)
{
- snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
+ struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
gus->pcm_cap_substream = NULL;
snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_DMA_READ);
return 0;
}
-static void snd_gf1_pcm_free(snd_pcm_t *pcm)
-{
- snd_gus_card_t *gus = pcm->private_data;
- gus->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int snd_gf1_pcm_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_gf1_pcm_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -743,9 +738,9 @@ static int snd_gf1_pcm_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_gf1_pcm_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gf1_pcm_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&gus->pcm_volume_level_lock, flags);
@@ -755,15 +750,15 @@ static int snd_gf1_pcm_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_gf1_pcm_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_gus_card_t *gus = snd_kcontrol_chip(kcontrol);
+ struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned int idx;
unsigned short val1, val2, vol;
- gus_pcm_private_t *pcmp;
- snd_gus_voice_t *pvoice;
+ struct gus_pcm_private *pcmp;
+ struct snd_gus_voice *pvoice;
val1 = ucontrol->value.integer.value[0] & 127;
val2 = ucontrol->value.integer.value[1] & 127;
@@ -797,7 +792,7 @@ static int snd_gf1_pcm_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return change;
}
-static snd_kcontrol_new_t snd_gf1_pcm_volume_control =
+static struct snd_kcontrol_new snd_gf1_pcm_volume_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
@@ -806,7 +801,7 @@ static snd_kcontrol_new_t snd_gf1_pcm_volume_control =
.put = snd_gf1_pcm_volume_put
};
-static snd_kcontrol_new_t snd_gf1_pcm_volume_control1 =
+static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "GPCM Playback Volume",
@@ -815,7 +810,7 @@ static snd_kcontrol_new_t snd_gf1_pcm_volume_control1 =
.put = snd_gf1_pcm_volume_put
};
-static snd_pcm_ops_t snd_gf1_pcm_playback_ops = {
+static struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
.open = snd_gf1_pcm_playback_open,
.close = snd_gf1_pcm_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -828,7 +823,7 @@ static snd_pcm_ops_t snd_gf1_pcm_playback_ops = {
.silence = snd_gf1_pcm_playback_silence,
};
-static snd_pcm_ops_t snd_gf1_pcm_capture_ops = {
+static struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
.open = snd_gf1_pcm_capture_open,
.close = snd_gf1_pcm_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -839,12 +834,12 @@ static snd_pcm_ops_t snd_gf1_pcm_capture_ops = {
.pointer = snd_gf1_pcm_capture_pointer,
};
-int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pcm_t ** rpcm)
+int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm)
{
- snd_card_t *card;
- snd_kcontrol_t *kctl;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
+ struct snd_card *card;
+ struct snd_kcontrol *kctl;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
int capture, err;
if (rpcm)
@@ -860,7 +855,6 @@ int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pc
if (err < 0)
return err;
pcm->private_data = gus;
- pcm->private_free = snd_gf1_pcm_free;
/* playback setup */
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops);
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index 90710969ef7f..b263655c4116 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -25,52 +25,52 @@
#include <sound/core.h>
#include <sound/gus.h>
-extern void snd_gf1_timers_init(snd_gus_card_t * gus);
-extern void snd_gf1_timers_done(snd_gus_card_t * gus);
-extern int snd_gf1_synth_init(snd_gus_card_t * gus);
-extern void snd_gf1_synth_done(snd_gus_card_t * gus);
+extern void snd_gf1_timers_init(struct snd_gus_card * gus);
+extern void snd_gf1_timers_done(struct snd_gus_card * gus);
+extern int snd_gf1_synth_init(struct snd_gus_card * gus);
+extern void snd_gf1_synth_done(struct snd_gus_card * gus);
/*
* ok.. default interrupt handlers...
*/
-static void snd_gf1_default_interrupt_handler_midi_out(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_midi_out(struct snd_gus_card * gus)
{
snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x20);
}
-static void snd_gf1_default_interrupt_handler_midi_in(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_midi_in(struct snd_gus_card * gus)
{
snd_gf1_uart_cmd(gus, gus->gf1.uart_cmd &= ~0x80);
}
-static void snd_gf1_default_interrupt_handler_timer1(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_timer1(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~4);
}
-static void snd_gf1_default_interrupt_handler_timer2(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_timer2(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, gus->gf1.timer_enabled &= ~8);
}
-static void snd_gf1_default_interrupt_handler_wave_and_volume(snd_gus_card_t * gus, snd_gus_voice_t * voice)
+static void snd_gf1_default_interrupt_handler_wave_and_volume(struct snd_gus_card * gus, struct snd_gus_voice * voice)
{
snd_gf1_i_ctrl_stop(gus, 0x00);
snd_gf1_i_ctrl_stop(gus, 0x0d);
}
-static void snd_gf1_default_interrupt_handler_dma_write(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_dma_write(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, 0x41, 0x00);
}
-static void snd_gf1_default_interrupt_handler_dma_read(snd_gus_card_t * gus)
+static void snd_gf1_default_interrupt_handler_dma_read(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, 0x49, 0x00);
}
-void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what)
+void snd_gf1_set_default_handlers(struct snd_gus_card * gus, unsigned int what)
{
if (what & SNDRV_GF1_HANDLER_MIDI_OUT)
gus->gf1.interrupt_handler_midi_out = snd_gf1_default_interrupt_handler_midi_out;
@@ -81,7 +81,7 @@ void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what)
if (what & SNDRV_GF1_HANDLER_TIMER2)
gus->gf1.interrupt_handler_timer2 = snd_gf1_default_interrupt_handler_timer2;
if (what & SNDRV_GF1_HANDLER_VOICE) {
- snd_gus_voice_t *voice;
+ struct snd_gus_voice *voice;
voice = &gus->gf1.voices[what & 0xffff];
voice->handler_wave =
@@ -99,7 +99,7 @@ void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what)
*/
-static void snd_gf1_clear_regs(snd_gus_card_t * gus)
+static void snd_gf1_clear_regs(struct snd_gus_card * gus)
{
unsigned long flags;
@@ -111,7 +111,7 @@ static void snd_gf1_clear_regs(snd_gus_card_t * gus)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-static void snd_gf1_look_regs(snd_gus_card_t * gus)
+static void snd_gf1_look_regs(struct snd_gus_card * gus)
{
unsigned long flags;
@@ -127,7 +127,7 @@ static void snd_gf1_look_regs(snd_gus_card_t * gus)
* put selected GF1 voices to initial stage...
*/
-void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice)
+void snd_gf1_smart_stop_voice(struct snd_gus_card * gus, unsigned short voice)
{
unsigned long flags;
@@ -141,7 +141,7 @@ void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice)
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
+void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice)
{
unsigned long flags;
@@ -161,7 +161,7 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
#endif
}
-static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
+static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min,
unsigned short v_max)
{
unsigned long flags;
@@ -203,7 +203,7 @@ static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
}
}
-void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
+void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max)
{
unsigned long flags;
short i, ramp_ok;
@@ -232,8 +232,8 @@ void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned sh
snd_gf1_clear_voices(gus, v_min, v_max);
}
-static void snd_gf1_alloc_voice_use(snd_gus_card_t * gus,
- snd_gus_voice_t * pvoice,
+static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus,
+ struct snd_gus_voice * pvoice,
int type, int client, int port)
{
pvoice->use = 1;
@@ -255,9 +255,9 @@ static void snd_gf1_alloc_voice_use(snd_gus_card_t * gus,
}
}
-snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port)
+struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port)
{
- snd_gus_voice_t *pvoice;
+ struct snd_gus_voice *pvoice;
unsigned long flags;
int idx;
@@ -289,10 +289,10 @@ snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client,
return NULL;
}
-void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice)
+void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice)
{
unsigned long flags;
- void (*private_free)(snd_gus_voice_t *voice);
+ void (*private_free)(struct snd_gus_voice *voice);
void *private_data;
if (voice == NULL || !voice->use)
@@ -317,7 +317,7 @@ void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice)
* call this function only by start of driver
*/
-int snd_gf1_start(snd_gus_card_t * gus)
+int snd_gf1_start(struct snd_gus_card * gus)
{
unsigned long flags;
unsigned int i;
@@ -400,7 +400,7 @@ int snd_gf1_start(snd_gus_card_t * gus)
* call this function only by shutdown of driver
*/
-int snd_gf1_stop(snd_gus_card_t * gus)
+int snd_gf1_stop(struct snd_gus_card * gus)
{
snd_gf1_i_write8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL, 0); /* stop all timers */
snd_gf1_stop_voices(gus, 0, 31); /* stop all voices */
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c
index 4290e03acd51..9e0c55ab25b2 100644
--- a/sound/isa/gus/gus_sample.c
+++ b/sound/isa/gus/gus_sample.c
@@ -28,9 +28,9 @@
*
*/
-static void select_instrument(snd_gus_card_t * gus, snd_gus_voice_t * v)
+static void select_instrument(struct snd_gus_card * gus, struct snd_gus_voice * v)
{
- snd_seq_kinstr_t *instr;
+ struct snd_seq_kinstr *instr;
#if 0
printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n",
@@ -53,7 +53,8 @@ static void select_instrument(snd_gus_card_t * gus, snd_gus_voice_t * v)
*
*/
-static void event_sample(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_sample(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
@@ -67,7 +68,8 @@ static void event_sample(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t
select_instrument(p->gus, v);
}
-static void event_cluster(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_cluster(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY);
@@ -75,50 +77,58 @@ static void event_cluster(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_
select_instrument(p->gus, v);
}
-static void event_start(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_start(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_start)
v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position);
}
-static void event_stop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_stop(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode);
}
-static void event_freq(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_freq(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_freq)
v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency);
}
-static void event_volume(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_volume(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_volume)
v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume);
}
-static void event_loop(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_loop(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_loop)
v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop);
}
-static void event_position(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_position(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_pos)
v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position);
}
-static void event_private1(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v)
+static void event_private1(struct snd_seq_event *ev, struct snd_gus_port *p,
+ struct snd_gus_voice *v)
{
if (v->sample_ops && v->sample_ops->sample_private1)
v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8);
}
-typedef void (gus_sample_event_handler_t)(snd_seq_event_t *ev, snd_gus_port_t *p, snd_gus_voice_t *v);
-
+typedef void (gus_sample_event_handler_t)(struct snd_seq_event *ev,
+ struct snd_gus_port *p,
+ struct snd_gus_voice *v);
static gus_sample_event_handler_t *gus_sample_event_handlers[9] = {
event_sample,
event_cluster,
@@ -131,11 +141,11 @@ static gus_sample_event_handler_t *gus_sample_event_handlers[9] = {
event_private1
};
-void snd_gus_sample_event(snd_seq_event_t *ev, snd_gus_port_t *p)
+void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p)
{
int idx, voice;
- snd_gus_card_t *gus = p->gus;
- snd_gus_voice_t *v;
+ struct snd_gus_card *gus = p->gus;
+ struct snd_gus_voice *v;
unsigned long flags;
idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c
index dfed85b58b3a..dcad6ed0198c 100644
--- a/sound/isa/gus/gus_simple.c
+++ b/sound/isa/gus/gus_simple.c
@@ -29,19 +29,19 @@
*
*/
-static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice);
-static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice);
-static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice);
-
-static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position);
-static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode);
-static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq);
-static void sample_volume(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume);
-static void sample_loop(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop);
-static void sample_pos(snd_gus_card_t *card, snd_gus_voice_t *voice, snd_seq_position_t position);
-static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data);
-
-static snd_gus_sample_ops_t sample_ops = {
+static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice);
+static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice);
+static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice);
+
+static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position);
+static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode);
+static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq);
+static void sample_volume(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume);
+static void sample_loop(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop);
+static void sample_pos(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position);
+static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data);
+
+static struct snd_gus_sample_ops sample_ops = {
sample_start,
sample_stop,
sample_freq,
@@ -53,13 +53,13 @@ static snd_gus_sample_ops_t sample_ops = {
#if 0
-static void note_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, int wait);
-static void note_wait(snd_gus_card_t *gus, snd_gus_voice_t *voice);
-static void note_off(snd_gus_card_t *gus, snd_gus_voice_t *voice);
-static void note_volume(snd_gus_card_t *card, snd_gus_voice_t *voice);
-static void note_pitchbend(snd_gus_card_t *card, snd_gus_voice_t *voice);
-static void note_vibrato(snd_gus_card_t *card, snd_gus_voice_t *voice);
-static void note_tremolo(snd_gus_card_t *card, snd_gus_voice_t *voice);
+static void note_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int wait);
+static void note_wait(struct snd_gus_card *gus, struct snd_gus_voice *voice);
+static void note_off(struct snd_gus_card *gus, struct snd_gus_voice *voice);
+static void note_volume(struct snd_gus_card *card, struct snd_gus_voice *voice);
+static void note_pitchbend(struct snd_gus_card *card, struct snd_gus_voice *voice);
+static void note_vibrato(struct snd_gus_card *card, struct snd_gus_voice *voice);
+static void note_tremolo(struct snd_gus_card *card, struct snd_gus_voice *voice);
static struct snd_gus_note_handlers note_commands = {
note_stop,
@@ -71,7 +71,7 @@ static struct snd_gus_note_handlers note_commands = {
note_tremolo
};
-static void chn_trigger_down(snd_gus_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority );
+static void chn_trigger_down(struct snd_gus_card *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority );
static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note );
static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 );
@@ -83,14 +83,14 @@ static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = {
#endif
-static void do_volume_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);
-static void do_pan_envelope(snd_gus_card_t *card, snd_gus_voice_t *voice);
+static void do_volume_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice);
+static void do_pan_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice);
/*
*
*/
-static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice)
+static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice)
{
spin_lock(&gus->event_lock);
snd_gf1_stop_voice(gus, voice->number);
@@ -102,7 +102,7 @@ static void interrupt_wave(snd_gus_card_t *gus, snd_gus_voice_t *voice)
spin_unlock(&gus->event_lock);
}
-static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice)
+static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice)
{
spin_lock(&gus->event_lock);
if (voice->flags & SNDRV_GF1_VFLG_RUNNING)
@@ -112,7 +112,7 @@ static void interrupt_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice)
spin_unlock(&gus->event_lock);
}
-static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice)
+static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice)
{
spin_lock(&gus->event_lock);
if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) ==
@@ -125,7 +125,7 @@ static void interrupt_effect(snd_gus_card_t *gus, snd_gus_voice_t *voice)
*
*/
-static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
+static void do_volume_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice)
{
unsigned short next, rate, old_volume;
int program_next_ramp;
@@ -229,7 +229,7 @@ static void do_volume_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
}
}
-static void do_pan_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
+static void do_pan_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice)
{
unsigned long flags;
unsigned char old_pan;
@@ -276,7 +276,7 @@ static void do_pan_envelope(snd_gus_card_t *gus, snd_gus_voice_t *voice)
#endif
}
-static void set_enhanced_pan(snd_gus_card_t *gus, snd_gus_voice_t *voice, unsigned short pan)
+static void set_enhanced_pan(struct snd_gus_card *gus, struct snd_gus_voice *voice, unsigned short pan)
{
unsigned long flags;
unsigned short vlo, vro;
@@ -307,13 +307,13 @@ static void set_enhanced_pan(snd_gus_card_t *gus, snd_gus_voice_t *voice, unsign
*
*/
-static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
+static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position)
{
unsigned long flags;
unsigned int begin, addr, addr_end, addr_start;
int w_16;
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1);
if (instr == NULL)
@@ -397,7 +397,7 @@ static void sample_start(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_po
snd_seq_instr_free_use(gus->gf1.ilist, instr);
}
-static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_stop_mode_t mode)
+static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode)
{
unsigned char control;
unsigned long flags;
@@ -433,7 +433,7 @@ static void sample_stop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_sto
}
}
-static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_frequency_t freq)
+static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq)
{
unsigned long flags;
@@ -444,7 +444,7 @@ static void sample_freq(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_fre
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-static void sample_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_volume_t *volume)
+static void sample_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume)
{
if (volume->volume >= 0) {
volume->volume &= 0x3fff;
@@ -471,13 +471,13 @@ static void sample_volume(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_e
}
}
-static void sample_loop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_loop_t *loop)
+static void sample_loop(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop)
{
unsigned long flags;
int w_16 = voice->control & 0x04;
unsigned int begin, addr_start, addr_end;
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
#if 0
printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
@@ -500,13 +500,13 @@ static void sample_loop(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_ev_
snd_seq_instr_free_use(gus->gf1.ilist, instr);
}
-static void sample_pos(snd_gus_card_t *gus, snd_gus_voice_t *voice, snd_seq_position_t position)
+static void sample_pos(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position)
{
unsigned long flags;
int w_16 = voice->control & 0x04;
unsigned int begin, addr;
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
#if 0
printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end);
@@ -537,7 +537,7 @@ static unsigned char get_effects_mask( ultra_card_t *card, int value )
#endif
-static void sample_private1(snd_gus_card_t *card, snd_gus_voice_t *voice, unsigned char *data)
+static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data)
{
#if 0
unsigned long flags;
@@ -624,7 +624,7 @@ static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned
#endif
-void snd_gf1_simple_init(snd_gus_voice_t *voice)
+void snd_gf1_simple_init(struct snd_gus_voice *voice)
{
voice->handler_wave = interrupt_wave;
voice->handler_volume = interrupt_volume;
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index f51c386ee192..85a1b051f09a 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -34,10 +34,10 @@ MODULE_LICENSE("GPL");
*
*/
-static void snd_gus_synth_free_voices(snd_gus_card_t * gus, int client, int port)
+static void snd_gus_synth_free_voices(struct snd_gus_card * gus, int client, int port)
{
int idx;
- snd_gus_voice_t * voice;
+ struct snd_gus_voice * voice;
for (idx = 0; idx < 32; idx++) {
voice = &gus->gf1.voices[idx];
@@ -46,11 +46,11 @@ static void snd_gus_synth_free_voices(snd_gus_card_t * gus, int client, int port
}
}
-static int snd_gus_synth_use(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_gus_synth_use(void *private_data, struct snd_seq_port_subscribe *info)
{
- snd_gus_port_t * port = (snd_gus_port_t *)private_data;
- snd_gus_card_t * gus = port->gus;
- snd_gus_voice_t * voice;
+ struct snd_gus_port * port = private_data;
+ struct snd_gus_card * gus = port->gus;
+ struct snd_gus_voice * voice;
unsigned int idx;
if (info->voices > 32)
@@ -74,10 +74,10 @@ static int snd_gus_synth_use(void *private_data, snd_seq_port_subscribe_t *info)
return 0;
}
-static int snd_gus_synth_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+static int snd_gus_synth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
- snd_gus_port_t * port = (snd_gus_port_t *)private_data;
- snd_gus_card_t * gus = port->gus;
+ struct snd_gus_port * port = private_data;
+ struct snd_gus_card * gus = port->gus;
down(&gus->register_mutex);
snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port);
@@ -90,19 +90,19 @@ static int snd_gus_synth_unuse(void *private_data, snd_seq_port_subscribe_t *inf
*
*/
-static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client)
+static void snd_gus_synth_free_private_instruments(struct snd_gus_port *p, int client)
{
- snd_seq_instr_header_t ifree;
+ struct snd_seq_instr_header ifree;
memset(&ifree, 0, sizeof(ifree));
ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;
snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
}
-static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
+static int snd_gus_synth_event_input(struct snd_seq_event *ev, int direct,
void *private_data, int atomic, int hop)
{
- snd_gus_port_t * p = (snd_gus_port_t *) private_data;
+ struct snd_gus_port * p = private_data;
snd_assert(p != NULL, return -EINVAL);
if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&
@@ -131,12 +131,12 @@ static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
}
static void snd_gus_synth_instr_notify(void *private_data,
- snd_seq_kinstr_t *instr,
+ struct snd_seq_kinstr *instr,
int what)
{
unsigned int idx;
- snd_gus_card_t *gus = private_data;
- snd_gus_voice_t *pvoice;
+ struct snd_gus_card *gus = private_data;
+ struct snd_gus_voice *pvoice;
unsigned long flags;
spin_lock_irqsave(&gus->event_lock, flags);
@@ -160,16 +160,16 @@ static void snd_gus_synth_instr_notify(void *private_data,
static void snd_gus_synth_free_port(void *private_data)
{
- snd_gus_port_t * p = (snd_gus_port_t *)private_data;
+ struct snd_gus_port * p = private_data;
if (p)
snd_midi_channel_free_set(p->chset);
}
-static int snd_gus_synth_create_port(snd_gus_card_t * gus, int idx)
+static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx)
{
- snd_gus_port_t * p;
- snd_seq_port_callback_t callbacks;
+ struct snd_gus_port * p;
+ struct snd_seq_port_callback callbacks;
char name[32];
int result;
@@ -210,46 +210,28 @@ static int snd_gus_synth_create_port(snd_gus_card_t * gus, int idx)
*
*/
-static int snd_gus_synth_new_device(snd_seq_device_t *dev)
+static int snd_gus_synth_new_device(struct snd_seq_device *dev)
{
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
int client, i;
- snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t *cinfo;
- snd_seq_port_subscribe_t sub;
- snd_iwffff_ops_t *iwops;
- snd_gf1_ops_t *gf1ops;
- snd_simple_ops_t *simpleops;
-
- gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ struct snd_seq_port_subscribe sub;
+ struct snd_iwffff_ops *iwops;
+ struct snd_gf1_ops *gf1ops;
+ struct snd_simple_ops *simpleops;
+
+ gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (gus == NULL)
return -EINVAL;
init_MUTEX(&gus->register_mutex);
gus->gf1.seq_client = -1;
- cinfo = kmalloc(sizeof(*cinfo), GFP_KERNEL);
- if (! cinfo)
- return -ENOMEM;
-
/* allocate new client */
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = gus;
- callbacks.allow_output = callbacks.allow_input = 1;
client = gus->gf1.seq_client =
- snd_seq_create_kernel_client(gus->card, 1, &callbacks);
- if (client < 0) {
- kfree(cinfo);
+ snd_seq_create_kernel_client(gus->card, 1, gus->interwave ?
+ "AMD InterWave" : "GF1");
+ if (client < 0)
return client;
- }
-
- /* change name of client */
- memset(cinfo, 0, sizeof(*cinfo));
- cinfo->client = client;
- cinfo->type = KERNEL_CLIENT;
- sprintf(cinfo->name, gus->interwave ? "AMD InterWave" : "GF1");
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, cinfo);
- kfree(cinfo);
for (i = 0; i < 4; i++)
snd_gus_synth_create_port(gus, i);
@@ -293,11 +275,11 @@ static int snd_gus_synth_new_device(snd_seq_device_t *dev)
return 0;
}
-static int snd_gus_synth_delete_device(snd_seq_device_t *dev)
+static int snd_gus_synth_delete_device(struct snd_seq_device *dev)
{
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
- gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (gus == NULL)
return -EINVAL;
@@ -312,13 +294,13 @@ static int snd_gus_synth_delete_device(snd_seq_device_t *dev)
static int __init alsa_gus_synth_init(void)
{
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_gus_synth_new_device,
snd_gus_synth_delete_device
};
return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_GUS, &ops,
- sizeof(snd_gus_card_t*));
+ sizeof(struct snd_gus_card *));
}
static void __exit alsa_gus_synth_exit(void)
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c
index 9876603ff6c1..a43b662f17c7 100644
--- a/sound/isa/gus/gus_timer.c
+++ b/sound/isa/gus/gus_timer.c
@@ -30,12 +30,12 @@
* Timer 1 - 80us
*/
-static int snd_gf1_timer1_start(snd_timer_t * timer)
+static int snd_gf1_timer1_start(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
unsigned int ticks;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = snd_timer_chip(timer);
spin_lock_irqsave(&gus->reg_lock, flags);
@@ -48,11 +48,11 @@ static int snd_gf1_timer1_start(snd_timer_t * timer)
return 0;
}
-static int snd_gf1_timer1_stop(snd_timer_t * timer)
+static int snd_gf1_timer1_stop(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = snd_timer_chip(timer);
spin_lock_irqsave(&gus->reg_lock, flags);
@@ -66,12 +66,12 @@ static int snd_gf1_timer1_stop(snd_timer_t * timer)
* Timer 2 - 320us
*/
-static int snd_gf1_timer2_start(snd_timer_t * timer)
+static int snd_gf1_timer2_start(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
unsigned int ticks;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = snd_timer_chip(timer);
spin_lock_irqsave(&gus->reg_lock, flags);
@@ -84,11 +84,11 @@ static int snd_gf1_timer2_start(snd_timer_t * timer)
return 0;
}
-static int snd_gf1_timer2_stop(snd_timer_t * timer)
+static int snd_gf1_timer2_stop(struct snd_timer * timer)
{
unsigned long flags;
unsigned char tmp;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = snd_timer_chip(timer);
spin_lock_irqsave(&gus->reg_lock, flags);
@@ -102,18 +102,18 @@ static int snd_gf1_timer2_stop(snd_timer_t * timer)
*/
-static void snd_gf1_interrupt_timer1(snd_gus_card_t * gus)
+static void snd_gf1_interrupt_timer1(struct snd_gus_card * gus)
{
- snd_timer_t *timer = gus->gf1.timer1;
+ struct snd_timer *timer = gus->gf1.timer1;
if (timer == NULL)
return;
snd_timer_interrupt(timer, timer->sticks);
}
-static void snd_gf1_interrupt_timer2(snd_gus_card_t * gus)
+static void snd_gf1_interrupt_timer2(struct snd_gus_card * gus)
{
- snd_timer_t *timer = gus->gf1.timer2;
+ struct snd_timer *timer = gus->gf1.timer2;
if (timer == NULL)
return;
@@ -124,7 +124,7 @@ static void snd_gf1_interrupt_timer2(snd_gus_card_t * gus)
*/
-static struct _snd_timer_hardware snd_gf1_timer1 =
+static struct snd_timer_hardware snd_gf1_timer1 =
{
.flags = SNDRV_TIMER_HW_STOP,
.resolution = 80000,
@@ -133,7 +133,7 @@ static struct _snd_timer_hardware snd_gf1_timer1 =
.stop = snd_gf1_timer1_stop,
};
-static struct _snd_timer_hardware snd_gf1_timer2 =
+static struct snd_timer_hardware snd_gf1_timer2 =
{
.flags = SNDRV_TIMER_HW_STOP,
.resolution = 320000,
@@ -142,22 +142,22 @@ static struct _snd_timer_hardware snd_gf1_timer2 =
.stop = snd_gf1_timer2_stop,
};
-static void snd_gf1_timer1_free(snd_timer_t *timer)
+static void snd_gf1_timer1_free(struct snd_timer *timer)
{
- snd_gus_card_t *gus = timer->private_data;
+ struct snd_gus_card *gus = timer->private_data;
gus->gf1.timer1 = NULL;
}
-static void snd_gf1_timer2_free(snd_timer_t *timer)
+static void snd_gf1_timer2_free(struct snd_timer *timer)
{
- snd_gus_card_t *gus = timer->private_data;
+ struct snd_gus_card *gus = timer->private_data;
gus->gf1.timer2 = NULL;
}
-void snd_gf1_timers_init(snd_gus_card_t * gus)
+void snd_gf1_timers_init(struct snd_gus_card * gus)
{
- snd_timer_t *timer;
- snd_timer_id_t tid;
+ struct snd_timer *timer;
+ struct snd_timer_id tid;
if (gus->gf1.timer1 != NULL || gus->gf1.timer2 != NULL)
return;
@@ -190,7 +190,7 @@ void snd_gf1_timers_init(snd_gus_card_t * gus)
gus->gf1.timer2 = timer;
}
-void snd_gf1_timers_done(snd_gus_card_t * gus)
+void snd_gf1_timers_done(struct snd_gus_card * gus)
{
snd_gf1_set_default_handlers(gus, SNDRV_GF1_HANDLER_TIMER1 | SNDRV_GF1_HANDLER_TIMER2);
if (gus->gf1.timer1) {
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index fbc95e99105c..654290a8b21c 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -26,7 +26,7 @@
#include <sound/core.h>
#include <sound/gus.h>
-static void snd_gf1_interrupt_midi_in(snd_gus_card_t * gus)
+static void snd_gf1_interrupt_midi_in(struct snd_gus_card * gus)
{
int count;
unsigned char stat, data, byte;
@@ -61,7 +61,7 @@ static void snd_gf1_interrupt_midi_in(snd_gus_card_t * gus)
}
}
-static void snd_gf1_interrupt_midi_out(snd_gus_card_t * gus)
+static void snd_gf1_interrupt_midi_out(struct snd_gus_card * gus)
{
char byte;
unsigned long flags;
@@ -81,7 +81,7 @@ static void snd_gf1_interrupt_midi_out(snd_gus_card_t * gus)
spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
}
-static void snd_gf1_uart_reset(snd_gus_card_t * gus, int close)
+static void snd_gf1_uart_reset(struct snd_gus_card * gus, int close)
{
snd_gf1_uart_cmd(gus, 0x03); /* reset */
if (!close && gus->uart_enable) {
@@ -90,10 +90,10 @@ static void snd_gf1_uart_reset(snd_gus_card_t * gus, int close)
}
}
-static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream)
+static int snd_gf1_uart_output_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = substream->rmidi->private_data;
spin_lock_irqsave(&gus->uart_cmd_lock, flags);
@@ -109,10 +109,10 @@ static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream)
+static int snd_gf1_uart_input_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
int i;
gus = substream->rmidi->private_data;
@@ -136,10 +136,10 @@ static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_gf1_uart_output_close(snd_rawmidi_substream_t * substream)
+static int snd_gf1_uart_output_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = substream->rmidi->private_data;
spin_lock_irqsave(&gus->uart_cmd_lock, flags);
@@ -151,10 +151,10 @@ static int snd_gf1_uart_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_gf1_uart_input_close(snd_rawmidi_substream_t * substream)
+static int snd_gf1_uart_input_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
gus = substream->rmidi->private_data;
spin_lock_irqsave(&gus->uart_cmd_lock, flags);
@@ -166,9 +166,9 @@ static int snd_gf1_uart_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_gf1_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_gf1_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
unsigned long flags;
gus = substream->rmidi->private_data;
@@ -184,10 +184,10 @@ static void snd_gf1_uart_input_trigger(snd_rawmidi_substream_t * substream, int
spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
}
-static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_gf1_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- snd_gus_card_t *gus;
+ struct snd_gus_card *gus;
char byte;
int timeout;
@@ -222,23 +222,23 @@ static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int
spin_unlock_irqrestore(&gus->uart_cmd_lock, flags);
}
-static snd_rawmidi_ops_t snd_gf1_uart_output =
+static struct snd_rawmidi_ops snd_gf1_uart_output =
{
.open = snd_gf1_uart_output_open,
.close = snd_gf1_uart_output_close,
.trigger = snd_gf1_uart_output_trigger,
};
-static snd_rawmidi_ops_t snd_gf1_uart_input =
+static struct snd_rawmidi_ops snd_gf1_uart_input =
{
.open = snd_gf1_uart_input_open,
.close = snd_gf1_uart_input_close,
.trigger = snd_gf1_uart_input_trigger,
};
-int snd_gf1_rawmidi_new(snd_gus_card_t * gus, int device, snd_rawmidi_t ** rrawmidi)
+int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi ** rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
index b3382fec5298..dbbc0a6d7659 100644
--- a/sound/isa/gus/gus_volume.c
+++ b/sound/isa/gus/gus_volume.c
@@ -72,7 +72,7 @@ unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
return rvol | (m >> (8 - e));
}
-unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
+unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus,
unsigned short start,
unsigned short end,
unsigned int us)
@@ -112,7 +112,7 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
#endif /* 0 */
-unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
+unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int freq16)
{
freq16 >>= 3;
if (freq16 < 50)
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 39cef38835ca..d1165b96fa3f 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -20,14 +20,15 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
@@ -70,11 +71,12 @@ MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver.");
module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
-static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *devices[SNDRV_CARDS];
+
#define PFX "gusclassic: "
-static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
+static int __init snd_gusclassic_detect(struct snd_gus_card * gus)
{
unsigned char d;
@@ -93,7 +95,7 @@ static int __init snd_gusclassic_detect(snd_gus_card_t * gus)
return 0;
}
-static void __init snd_gusclassic_init(int dev, snd_gus_card_t * gus)
+static void __init snd_gusclassic_init(int dev, struct snd_gus_card * gus)
{
gus->equal_irq = 0;
gus->codec_flag = 0;
@@ -101,20 +103,19 @@ static void __init snd_gusclassic_init(int dev, snd_gus_card_t * gus)
gus->joystick_dac = joystick_dac[dev];
}
-static int __init snd_gusclassic_probe(int dev)
+static int __init snd_gusclassic_probe(struct platform_device *pdev)
{
+ int dev = pdev->id;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
int xirq, xdma1, xdma2;
- snd_card_t *card;
- struct snd_gusclassic *guscard;
- snd_gus_card_t *gus = NULL;
+ struct snd_card *card;
+ struct snd_gus_card *gus = NULL;
int err;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- guscard = (struct snd_gusclassic *)card->private_data;
if (pcm_channels[dev] < 2)
pcm_channels[dev] = 2;
@@ -143,12 +144,31 @@ static int __init snd_gusclassic_probe(int dev)
}
}
-
- if ((err = snd_gus_create(card,
- port[dev],
- xirq, xdma1, xdma2,
- 0, channels[dev], pcm_channels[dev],
- 0, &gus)) < 0)
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ err = snd_gus_create(card,
+ port[dev],
+ xirq, xdma1, xdma2,
+ 0, channels[dev], pcm_channels[dev],
+ 0, &gus);
+ } else {
+ /* auto-probe legacy ports */
+ static unsigned long possible_ports[] = {
+ 0x220, 0x230, 0x240, 0x250, 0x260,
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ err = snd_gus_create(card,
+ possible_ports[i],
+ xirq, xdma1, xdma2,
+ 0, channels[dev], pcm_channels[dev],
+ 0, &gus);
+ if (err >= 0) {
+ port[dev] = possible_ports[i];
+ break;
+ }
+ }
+ }
+ if (err < 0)
goto _err;
if ((err = snd_gusclassic_detect(gus)) < 0)
@@ -178,13 +198,12 @@ static int __init snd_gusclassic_probe(int dev)
if (dma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_gusclassic_cards[dev] = card;
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -192,53 +211,70 @@ static int __init snd_gusclassic_probe(int dev)
return err;
}
-static int __init snd_gusclassic_legacy_auto_probe(unsigned long xport)
+static int snd_gusclassic_remove(struct platform_device *devptr)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- port[dev] = xport;
- res = snd_gusclassic_probe(dev);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
- }
- return -ENODEV;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define GUSCLASSIC_DRIVER "snd_gusclassic"
+
+static struct platform_driver snd_gusclassic_driver = {
+ .probe = snd_gusclassic_probe,
+ .remove = snd_gusclassic_remove,
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = GUSCLASSIC_DRIVER
+ },
+};
+
+static void __init_or_module snd_gusclassic_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_gusclassic_driver);
}
static int __init alsa_card_gusclassic_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1};
- int dev, cards, i;
-
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (snd_gusclassic_probe(dev) >= 0)
- cards++;
- }
- i = snd_legacy_auto_probe(possible_ports, snd_gusclassic_legacy_auto_probe);
- if (i > 0)
- cards += i;
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_gusclassic_driver);
+ if (err < 0)
+ return err;
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(GUSCLASSIC_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_gusclassic_unregister_all();
+ return err;
}
static void __exit alsa_card_gusclassic_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_gusclassic_cards[idx]);
+ snd_gusclassic_unregister_all();
}
module_init(alsa_card_gusclassic_init)
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index d2e7cb1df537..239f16e6b9ee 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -20,11 +20,13 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/es1688.h>
@@ -85,14 +87,15 @@ MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver.");
module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
-static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+struct platform_device *devices[SNDRV_CARDS];
+
#define PFX "gusextreme: "
static int __init snd_gusextreme_detect(int dev,
- snd_card_t * card,
- snd_gus_card_t * gus,
- es1688_t *es1688)
+ struct snd_card *card,
+ struct snd_gus_card * gus,
+ struct snd_es1688 *es1688)
{
unsigned long flags;
unsigned char d;
@@ -139,15 +142,15 @@ static int __init snd_gusextreme_detect(int dev,
return 0;
}
-static void __init snd_gusextreme_init(int dev, snd_gus_card_t * gus)
+static void __init snd_gusextreme_init(int dev, struct snd_gus_card * gus)
{
gus->joystick_dac = joystick_dac[dev];
}
-static int __init snd_gusextreme_mixer(es1688_t *chip)
+static int __init snd_gusextreme_mixer(struct snd_es1688 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
int err;
memset(&id1, 0, sizeof(id1));
@@ -166,24 +169,23 @@ static int __init snd_gusextreme_mixer(es1688_t *chip)
return 0;
}
-static int __init snd_gusextreme_probe(int dev)
+static int __init snd_gusextreme_probe(struct platform_device *pdev)
{
+ int dev = pdev->id;
static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
static int possible_ess_dmas[] = {1, 3, 0, -1};
static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1};
int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma;
- snd_card_t *card;
- struct snd_gusextreme *acard;
- snd_gus_card_t *gus;
- es1688_t *es1688;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct snd_gus_card *gus;
+ struct snd_es1688 *es1688;
+ struct snd_opl3 *opl3;
int err;
card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- acard = (struct snd_gusextreme *)card->private_data;
xgf1_irq = gf1_irq[dev];
if (xgf1_irq == SNDRV_AUTO_IRQ) {
@@ -223,10 +225,29 @@ static int __init snd_gusextreme_probe(int dev)
}
}
- if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
- xess_irq, xmpu_irq, xess_dma,
- ES1688_HW_1688, &es1688)) < 0)
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ err = snd_es1688_create(card, port[dev], mpu_port[dev],
+ xess_irq, xmpu_irq, xess_dma,
+ ES1688_HW_1688, &es1688);
+ } else {
+ /* auto-probe legacy ports */
+ static unsigned long possible_ports[] = {0x220, 0x240, 0x260};
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ err = snd_es1688_create(card,
+ possible_ports[i],
+ mpu_port[dev],
+ xess_irq, xmpu_irq, xess_dma,
+ ES1688_HW_1688, &es1688);
+ if (err >= 0) {
+ port[dev] = possible_ports[i];
+ break;
+ }
+ }
+ }
+ if (err < 0)
goto out;
+
if (gf1_port[dev] < 0)
gf1_port[dev] = port[dev] + 0x20;
if ((err = snd_gus_create(card,
@@ -287,13 +308,12 @@ 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;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto out;
- snd_gusextreme_cards[dev] = card;
+ platform_set_drvdata(pdev, card);
return 0;
out:
@@ -301,60 +321,70 @@ static int __init snd_gusextreme_probe(int dev)
return err;
}
-static int __init snd_gusextreme_legacy_auto_probe(unsigned long xport)
+static int snd_gusextreme_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define GUSEXTREME_DRIVER "snd_gusextreme"
+
+static struct platform_driver snd_gusextreme_driver = {
+ .probe = snd_gusextreme_probe,
+ .remove = snd_gusextreme_remove,
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = GUSEXTREME_DRIVER
+ },
+};
+
+static void __init_or_module snd_gusextreme_unregister_all(void)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- port[dev] = xport;
- res = snd_gusextreme_probe(dev);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
- }
- return -ENODEV;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_gusextreme_driver);
}
static int __init alsa_card_gusextreme_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
- int dev, cards, i;
-
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) {
- if (port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (snd_gusextreme_probe(dev) >= 0)
- cards++;
- }
- i = snd_legacy_auto_probe(possible_ports, snd_gusextreme_legacy_auto_probe);
- if (i > 0)
- cards += i;
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_gusextreme_driver);
+ if (err < 0)
+ return err;
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(GUSEXTREME_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_gusextreme_unregister_all();
+ return err;
}
static void __exit alsa_card_gusextreme_exit(void)
{
- int idx;
- snd_card_t *card;
- struct snd_gusextreme *acard;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++) {
- card = snd_gusextreme_cards[idx];
- if (card == NULL)
- continue;
- acard = (struct snd_gusextreme *)card->private_data;
- snd_card_free(snd_gusextreme_cards[idx]);
- }
+ snd_gusextreme_unregister_all();
}
module_init(alsa_card_gusextreme_init)
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 0bb44b519340..d4d2b2a517d5 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -20,15 +20,16 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/cs4231.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
@@ -71,20 +72,20 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
module_param_array(pcm_channels, int, NULL, 0444);
MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
+static struct platform_device *devices[SNDRV_CARDS];
+
struct snd_gusmax {
int irq;
- snd_card_t *card;
- snd_gus_card_t *gus;
- cs4231_t *cs4231;
+ struct snd_card *card;
+ struct snd_gus_card *gus;
+ struct snd_cs4231 *cs4231;
unsigned short gus_status_reg;
unsigned short pcm_status_reg;
};
-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)
+static int __init snd_gusmax_detect(struct snd_gus_card * gus)
{
unsigned char d;
@@ -126,7 +127,7 @@ static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_RETVAL(handled);
}
-static void __init snd_gusmax_init(int dev, snd_card_t * card, snd_gus_card_t * gus)
+static void __init snd_gusmax_init(int dev, struct snd_card *card, struct snd_gus_card * gus)
{
gus->equal_irq = 1;
gus->codec_flag = 1;
@@ -144,10 +145,10 @@ static void __init snd_gusmax_init(int dev, snd_card_t * card, snd_gus_card_t *
#define CS4231_PRIVATE( left, right, shift, mute ) \
((left << 24)|(right << 16)|(shift<<8)|mute)
-static int __init snd_gusmax_mixer(cs4231_t *chip)
+static int __init snd_gusmax_mixer(struct snd_cs4231 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
int err;
memset(&id1, 0, sizeof(id1));
@@ -193,7 +194,7 @@ static int __init snd_gusmax_mixer(cs4231_t *chip)
return 0;
}
-static void snd_gusmax_free(snd_card_t *card)
+static void snd_gusmax_free(struct snd_card *card)
{
struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data;
@@ -203,14 +204,15 @@ static void snd_gusmax_free(snd_card_t *card)
free_irq(maxcard->irq, (void *)maxcard);
}
-static int __init snd_gusmax_probe(int dev)
+static int __init snd_gusmax_probe(struct platform_device *pdev)
{
+ int dev = pdev->id;
static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
int xirq, xdma1, xdma2, err;
- snd_card_t *card;
- snd_gus_card_t *gus = NULL;
- cs4231_t *cs4231;
+ struct snd_card *card;
+ struct snd_gus_card *gus = NULL;
+ struct snd_cs4231 *cs4231;
struct snd_gusmax *maxcard;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
@@ -247,12 +249,32 @@ static int __init snd_gusmax_probe(int dev)
}
}
- if ((err = snd_gus_create(card,
- port[dev],
- -xirq, xdma1, xdma2,
- 0, channels[dev],
- pcm_channels[dev],
- 0, &gus)) < 0)
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ err = snd_gus_create(card,
+ port[dev],
+ -xirq, xdma1, xdma2,
+ 0, channels[dev],
+ pcm_channels[dev],
+ 0, &gus);
+ } else {
+ static unsigned long possible_ports[] = {
+ 0x220, 0x230, 0x240, 0x250, 0x260
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ err = snd_gus_create(card,
+ possible_ports[i],
+ -xirq, xdma1, xdma2,
+ 0, channels[dev],
+ pcm_channels[dev],
+ 0, &gus);
+ if (err >= 0) {
+ port[dev] = possible_ports[i];
+ break;
+ }
+ }
+ }
+ if (err < 0)
goto _err;
if ((err = snd_gusmax_detect(gus)) < 0)
@@ -310,15 +332,15 @@ static int __init snd_gusmax_probe(int dev)
if (xdma2 >= 0)
sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
maxcard->gus = gus;
maxcard->cs4231 = cs4231;
- snd_gusmax_cards[dev] = card;
+
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -326,53 +348,70 @@ static int __init snd_gusmax_probe(int dev)
return err;
}
-static int __init snd_gusmax_legacy_auto_probe(unsigned long xport)
+static int snd_gusmax_remove(struct platform_device *devptr)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- port[dev] = xport;
- res = snd_gusmax_probe(dev);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
- }
- return -ENODEV;
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define GUSMAX_DRIVER "snd_gusmax"
+
+static struct platform_driver snd_gusmax_driver = {
+ .probe = snd_gusmax_probe,
+ .remove = snd_gusmax_remove,
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = GUSMAX_DRIVER
+ },
+};
+
+static void __init_or_module snd_gusmax_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_gusmax_driver);
}
static int __init alsa_card_gusmax_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260, -1};
- int dev, cards, i;
-
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev] > 0; dev++) {
- if (port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (snd_gusmax_probe(dev) >= 0)
- cards++;
- }
- i = snd_legacy_auto_probe(possible_ports, snd_gusmax_legacy_auto_probe);
- if (i > 0)
- cards += i;
+ int i, cards, err;
+ err = platform_driver_register(&snd_gusmax_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(GUSMAX_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
+ }
if (!cards) {
#ifdef MODULE
printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_gusmax_unregister_all();
+ return err;
}
static void __exit alsa_card_gusmax_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_gusmax_cards[idx]);
+ snd_gusmax_unregister_all();
}
module_init(alsa_card_gusmax_init)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index f703a9f4257c..9838d992b101 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -23,19 +23,20 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
-#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/cs4231.h>
#ifdef SNDRV_STB
#include <sound/tea6330t.h>
#endif
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
@@ -75,8 +76,12 @@ static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
#ifdef SNDRV_STB
#define PFX "interwave-stb: "
+#define INTERWAVE_DRIVER "snd_interwave_stb"
+#define INTERWAVE_PNP_DRIVER "interwave-stb"
#else
#define PFX "interwave: "
+#define INTERWAVE_DRIVER "snd_interwave"
+#define INTERWAVE_PNP_DRIVER "interwave"
#endif
module_param_array(index, int, NULL, 0444);
@@ -110,11 +115,14 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
module_param_array(effect, int, NULL, 0444);
MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
struct snd_interwave {
int irq;
- snd_card_t *card;
- snd_gus_card_t *gus;
- cs4231_t *cs4231;
+ struct snd_card *card;
+ struct snd_gus_card *gus;
+ struct snd_cs4231 *cs4231;
#ifdef SNDRV_STB
struct resource *i2c_res;
#endif
@@ -128,7 +136,6 @@ struct snd_interwave {
#endif
};
-static snd_card_t *snd_interwave_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
#ifdef CONFIG_PNP
@@ -160,7 +167,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_interwave_pnpids);
#ifdef SNDRV_STB
-static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data)
+static void snd_interwave_i2c_setlines(struct snd_i2c_bus *bus, int ctrl, int data)
{
unsigned long port = bus->private_value;
@@ -171,7 +178,7 @@ static void snd_interwave_i2c_setlines(snd_i2c_bus_t *bus, int ctrl, int data)
udelay(10);
}
-static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus)
+static int snd_interwave_i2c_getclockline(struct snd_i2c_bus *bus)
{
unsigned long port = bus->private_value;
unsigned char res;
@@ -183,7 +190,7 @@ static int snd_interwave_i2c_getclockline(snd_i2c_bus_t *bus)
return res;
}
-static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack)
+static int snd_interwave_i2c_getdataline(struct snd_i2c_bus *bus, int ack)
{
unsigned long port = bus->private_value;
unsigned char res;
@@ -197,19 +204,19 @@ static int snd_interwave_i2c_getdataline(snd_i2c_bus_t *bus, int ack)
return res;
}
-static snd_i2c_bit_ops_t snd_interwave_i2c_bit_ops = {
+static struct snd_i2c_bit_ops snd_interwave_i2c_bit_ops = {
.setlines = snd_interwave_i2c_setlines,
.getclock = snd_interwave_i2c_getclockline,
.getdata = snd_interwave_i2c_getdataline,
};
static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
- snd_gus_card_t * gus, int dev,
- snd_i2c_bus_t **rbus)
+ struct snd_gus_card * gus, int dev,
+ struct snd_i2c_bus **rbus)
{
unsigned long port;
- snd_i2c_bus_t *bus;
- snd_card_t *card = iwcard->card;
+ struct snd_i2c_bus *bus;
+ struct snd_card *card = iwcard->card;
char name[32];
int err;
@@ -246,10 +253,10 @@ static int __devinit snd_interwave_detect_stb(struct snd_interwave *iwcard,
#endif
static int __devinit snd_interwave_detect(struct snd_interwave *iwcard,
- snd_gus_card_t * gus,
+ struct snd_gus_card * gus,
int dev
#ifdef SNDRV_STB
- , snd_i2c_bus_t **rbus
+ , struct snd_i2c_bus **rbus
#endif
)
{
@@ -314,7 +321,7 @@ static irqreturn_t snd_interwave_interrupt(int irq, void *dev_id, struct pt_regs
return IRQ_RETVAL(handled);
}
-static void __devinit snd_interwave_reset(snd_gus_card_t * gus)
+static void __devinit snd_interwave_reset(struct snd_gus_card * gus)
{
snd_gf1_write8(gus, SNDRV_GF1_GB_RESET, 0x00);
udelay(160);
@@ -322,7 +329,7 @@ static void __devinit snd_interwave_reset(snd_gus_card_t * gus)
udelay(160);
}
-static void __devinit snd_interwave_bank_sizes(snd_gus_card_t * gus, int *sizes)
+static void __devinit snd_interwave_bank_sizes(struct snd_gus_card * gus, int *sizes)
{
unsigned int idx;
unsigned int local;
@@ -371,7 +378,7 @@ struct rom_hdr {
/* 511 */ unsigned char csum;
};
-static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
+static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus)
{
static unsigned int lmc[13] =
{
@@ -470,7 +477,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
snd_interwave_reset(gus);
}
-static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus)
+static void __devinit snd_interwave_init(int dev, struct snd_gus_card * gus)
{
unsigned long flags;
@@ -492,17 +499,17 @@ static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus)
}
-static snd_kcontrol_new_t snd_interwave_controls[] = {
+static struct snd_kcontrol_new snd_interwave_controls[] = {
CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
CS4231_DOUBLE("Mic Playback Switch", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 7, 7, 1, 1),
CS4231_DOUBLE("Mic Playback Volume", 0, CS4231_LEFT_MIC_INPUT, CS4231_RIGHT_MIC_INPUT, 0, 0, 31, 1)
};
-static int __devinit snd_interwave_mixer(cs4231_t *chip)
+static int __devinit snd_interwave_mixer(struct snd_cs4231 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
unsigned int idx;
int err;
@@ -631,9 +638,9 @@ static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard,
}
#endif /* CONFIG_PNP */
-static void snd_interwave_free(snd_card_t *card)
+static void snd_interwave_free(struct snd_card *card)
{
- struct snd_interwave *iwcard = (struct snd_interwave *)card->private_data;
+ struct snd_interwave *iwcard = card->private_data;
if (iwcard == NULL)
return;
@@ -644,76 +651,52 @@ static void snd_interwave_free(snd_card_t *card)
free_irq(iwcard->irq, (void *)iwcard);
}
-static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static struct snd_card *snd_interwave_card_new(int dev)
{
- static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
- static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
- int xirq, xdma1, xdma2;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_interwave *iwcard;
- cs4231_t *cs4231;
- snd_gus_card_t *gus;
-#ifdef SNDRV_STB
- snd_i2c_bus_t *i2c_bus;
-#endif
- snd_pcm_t *pcm;
- char *str;
- int err;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_interwave));
if (card == NULL)
- return -ENOMEM;
- iwcard = (struct snd_interwave *)card->private_data;
+ return NULL;
+ iwcard = card->private_data;
iwcard->card = card;
iwcard->irq = -1;
card->private_free = snd_interwave_free;
-#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if ((err = snd_interwave_pnp(dev, iwcard, pcard, pid)) < 0)
- goto _err;
- snd_card_set_dev(card, &pcard->card->dev);
- }
+ return card;
+}
+
+static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
+{
+ int xirq, xdma1, xdma2;
+ struct snd_interwave *iwcard = card->private_data;
+ struct snd_cs4231 *cs4231;
+ struct snd_gus_card *gus;
+#ifdef SNDRV_STB
+ struct snd_i2c_bus *i2c_bus;
#endif
+ struct snd_pcm *pcm;
+ char *str;
+ int err;
+
xirq = irq[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;
- }
- }
xdma1 = dma1[dev];
- if (xdma1 == SNDRV_AUTO_DMA) {
- if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
- 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_printk(KERN_ERR PFX "unable to find a free DMA2\n");
- err = -EBUSY;
- goto _err;
- }
- }
if ((err = snd_gus_create(card,
port[dev],
-xirq, xdma1, xdma2,
0, 32,
pcm_channels[dev], effect[dev], &gus)) < 0)
- goto _err;
+ return err;
if ((err = snd_interwave_detect(iwcard, gus, dev
#ifdef SNDRV_STB
, &i2c_bus
#endif
)) < 0)
- goto _err;
+ return err;
iwcard->gus_status_reg = gus->gf1.reg_irqstat;
iwcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
@@ -721,12 +704,12 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
snd_interwave_init(dev, gus);
snd_interwave_detect_memory(gus);
if ((err = snd_gus_initialize(gus)) < 0)
- goto _err;
+ return err;
- if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", (void *)iwcard)) {
+ if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT,
+ "InterWave", iwcard)) {
snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
- err = -EBUSY;
- goto _err;
+ return -EBUSY;
}
iwcard->irq = xirq;
@@ -738,30 +721,30 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
CS4231_HWSHARE_DMA1 |
CS4231_HWSHARE_DMA2,
&cs4231)) < 0)
- goto _err;
+ return err;
if ((err = snd_cs4231_pcm(cs4231, 0, &pcm)) < 0)
- goto _err;
+ return 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)
- goto _err;
+ return err;
if ((err = snd_cs4231_mixer(cs4231)) < 0)
- goto _err;
+ return err;
if (pcm_channels[dev] > 0) {
if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
- goto _err;
+ return err;
}
if ((err = snd_interwave_mixer(cs4231)) < 0)
- goto _err;
+ return err;
#ifdef SNDRV_STB
{
- snd_ctl_elem_id_t id1, id2;
+ struct snd_ctl_elem_id id1, id2;
memset(&id1, 0, sizeof(id1));
memset(&id2, 0, sizeof(id2));
id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -769,19 +752,19 @@ static int __devinit snd_interwave_probe(int dev, struct pnp_card_link *pcard,
strcpy(id2.name, id1.name);
id2.index = 1;
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
- goto _err;
+ return err;
strcpy(id1.name, "Master Playback Volume");
strcpy(id2.name, id1.name);
if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
- goto _err;
+ return err;
if ((err = snd_tea6330t_update_mixer(card, i2c_bus, 0, 1)) < 0)
- goto _err;
+ return err;
}
#endif
gus->uart_enable = midi[dev];
if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
- goto _err;
+ return err;
#ifndef SNDRV_STB
str = "AMD InterWave";
@@ -800,139 +783,198 @@ 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_set_generic_dev(card)) < 0)
- goto _err;
-
if ((err = snd_card_register(card)) < 0)
- goto _err;
+ return err;
iwcard->cs4231 = cs4231;
iwcard->gus = gus;
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_interwave_legacy[dev++] = card;
return 0;
+}
- _err:
- snd_card_free(card);
- return err;
+static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
+{
+ struct snd_card *card;
+ int err;
+
+ card = snd_interwave_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+
+ snd_card_set_dev(card, &devptr->dev);
+ if ((err = snd_interwave_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ platform_set_drvdata(devptr, card);
+ return 0;
}
-static int __devinit snd_interwave_probe_legacy_port(unsigned long xport)
+static int __init snd_interwave_nonpnp_probe(struct platform_device *pdev)
{
- static int dev;
- int res;
+ int dev = pdev->id;
+ int err;
+ static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
+ static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
-#ifdef CONFIG_PNP
- if (isapnp[dev])
- continue;
-#endif
- port[dev] = xport;
- res = snd_interwave_probe(dev, NULL, NULL);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
+ if (irq[dev] == SNDRV_AUTO_IRQ) {
+ if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
}
- return -ENODEV;
+ if (dma1[dev] == SNDRV_AUTO_DMA) {
+ if ((dma1[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
+ return -EBUSY;
+ }
+ }
+ if (dma2[dev] == SNDRV_AUTO_DMA) {
+ if ((dma2[dev] = snd_legacy_find_free_dma(possible_dmas)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
+ return -EBUSY;
+ }
+ }
+
+ if (port[dev] != SNDRV_AUTO_PORT)
+ return snd_interwave_nonpnp_probe1(dev, pdev);
+ else {
+ static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ port[dev] = possible_ports[i];
+ err = snd_interwave_nonpnp_probe1(dev, pdev);
+ if (! err)
+ return 0;
+ }
+ return err;
+ }
+}
+
+static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
}
+static struct platform_driver snd_interwave_driver = {
+ .probe = snd_interwave_nonpnp_probe,
+ .remove = __devexit_p(snd_interwave_nonpnp_remove),
+ /* FIXME: suspend,resume */
+ .driver = {
+ .name = INTERWAVE_DRIVER
+ },
+};
+
#ifdef CONFIG_PNP
-static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
+ struct snd_card *card;
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_interwave_probe(dev, card, id);
- if (res < 0)
- return res;
- dev++;
- return 0;
- }
-
- return -ENODEV;
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_interwave_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+
+ if ((res = snd_interwave_pnp(dev, card->private_data, pcard, pid)) < 0) {
+ snd_card_free(card);
+ return res;
+ }
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((res = snd_interwave_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return res;
+ }
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
static void __devexit snd_interwave_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
static struct pnp_card_driver interwave_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
- .name = "interwave",
+ .name = INTERWAVE_PNP_DRIVER,
.id_table = snd_interwave_pnpids,
.probe = snd_interwave_pnp_detect,
.remove = __devexit_p(snd_interwave_pnp_remove),
+ /* FIXME: suspend,resume */
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_interwave_unregister_all(void)
+{
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_card_driver(&interwave_pnpc_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_interwave_driver);
+}
+
static int __init alsa_card_interwave_init(void)
{
- int cards = 0, i;
- static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260, -1};
- int dev;
+ int i, err, cards = 0;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
- continue;
+ if ((err = platform_driver_register(&snd_interwave_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (isapnp[i])
continue;
#endif
- if (!snd_interwave_probe(dev, NULL, NULL)) {
- cards++;
- continue;
+ device = platform_device_register_simple(INTERWAVE_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
}
-#ifdef MODULE
- printk(KERN_ERR "InterWave soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);
-#endif
+ platform_devices[i] = device;
+ cards++;
}
- /* legacy auto configured cards */
- i = snd_legacy_auto_probe(possible_ports, snd_interwave_probe_legacy_port);
- if (i > 0)
- cards += i;
-#ifdef CONFIG_PNP
+
/* ISA PnP cards */
i = pnp_register_card_driver(&interwave_pnpc_driver);
- if (i > 0)
+ if (i >= 0) {
+ pnp_registered = 1;
cards += i;
-#endif
+ }
if (!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&interwave_pnpc_driver);
-#endif
#ifdef MODULE
printk(KERN_ERR "InterWave soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_interwave_unregister_all();
+ return err;
}
static void __exit alsa_card_interwave_exit(void)
{
- int dev;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&interwave_pnpc_driver);
-#endif
- for (dev = 0; dev < SNDRV_CARDS; dev++)
- snd_card_free(snd_interwave_legacy[dev]);
+ snd_interwave_unregister_all();
}
module_init(alsa_card_interwave_init)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 47cabda792b6..ca359e0c674b 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -21,6 +21,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -88,6 +90,10 @@ MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
module_param_array(opl3sa3_ymode, int, NULL, 0444);
MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+static int pnpc_registered;
+
/* control ports */
#define OPL3SA2_PM_CTRL 0x01
#define OPL3SA2_SYS_CTRL 0x02
@@ -115,34 +121,23 @@ MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode:
#define OPL3SA2_PM_D0 0x00
#define OPL3SA2_PM_D3 (OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
-typedef struct snd_opl3sa2 opl3sa2_t;
-
struct snd_opl3sa2 {
- snd_card_t *card;
+ struct snd_card *card;
int version; /* 2 or 3 */
unsigned long port; /* control port */
struct resource *res_port; /* control port resource */
int irq;
int single_dma;
spinlock_t reg_lock;
- snd_hwdep_t *synth;
- snd_rawmidi_t *rmidi;
- cs4231_t *cs4231;
-#ifdef CONFIG_PNP
- struct pnp_dev *dev;
-#endif
+ struct snd_hwdep *synth;
+ struct snd_rawmidi *rmidi;
+ struct snd_cs4231 *cs4231;
unsigned char ctlregs[0x20];
int ymode; /* SL added */
- snd_kcontrol_t *master_switch;
- snd_kcontrol_t *master_volume;
-#ifdef CONFIG_PM
- void (*cs4231_suspend)(cs4231_t *);
- void (*cs4231_resume)(cs4231_t *);
-#endif
+ struct snd_kcontrol *master_switch;
+ struct snd_kcontrol *master_volume;
};
-static snd_card_t *snd_opl3sa2_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
#define PFX "opl3sa2: "
#ifdef CONFIG_PNP
@@ -176,7 +171,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opl3sa2_pnpids);
/* read control port (w/o spinlock) */
-static unsigned char __snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
+static unsigned char __snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg)
{
unsigned char result;
#if 0
@@ -192,7 +187,7 @@ static unsigned char __snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
}
/* read control port (with spinlock) */
-static unsigned char snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
+static unsigned char snd_opl3sa2_read(struct snd_opl3sa2 *chip, unsigned char reg)
{
unsigned long flags;
unsigned char result;
@@ -204,7 +199,7 @@ static unsigned char snd_opl3sa2_read(opl3sa2_t *chip, unsigned char reg)
}
/* write control port (w/o spinlock) */
-static void __snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned char value)
+static void __snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value)
{
#if 0
outb(0x1d, port); /* password */
@@ -215,7 +210,7 @@ static void __snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned cha
}
/* write control port (with spinlock) */
-static void snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned char value)
+static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsigned char value)
{
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -223,9 +218,9 @@ static void snd_opl3sa2_write(opl3sa2_t *chip, unsigned char reg, unsigned char
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
+static int __init snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned long port;
unsigned char tmp, tmp1;
char str[2];
@@ -298,7 +293,7 @@ static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned short status;
- opl3sa2_t *chip = dev_id;
+ struct snd_opl3sa2 *chip = dev_id;
int handled = 0;
if (chip == NULL || chip->card == NULL)
@@ -340,7 +335,7 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *
.get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_opl3sa2_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -351,9 +346,9 @@ static int snd_opl3sa2_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opl3sa2_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -368,9 +363,9 @@ static int snd_opl3sa2_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -398,7 +393,7 @@ static int snd_opl3sa2_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -409,9 +404,9 @@ static int snd_opl3sa2_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opl3sa2_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -431,9 +426,9 @@ static int snd_opl3sa2_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -471,31 +466,31 @@ static int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return change;
}
-static snd_kcontrol_new_t snd_opl3sa2_controls[] = {
+static struct snd_kcontrol_new snd_opl3sa2_controls[] = {
OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1),
OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1),
OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1)
};
-static snd_kcontrol_new_t snd_opl3sa2_tone_controls[] = {
+static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = {
OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0),
OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0),
OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0)
};
-static void snd_opl3sa2_master_free(snd_kcontrol_t *kcontrol)
+static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol)
{
- opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opl3sa2 *chip = snd_kcontrol_chip(kcontrol);
chip->master_switch = NULL;
chip->master_volume = NULL;
}
-static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
+static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
- snd_kcontrol_t *kctl;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -505,21 +500,29 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
/* reassign AUX0 to CD */
strcpy(id1.name, "Aux Playback Switch");
strcpy(id2.name, "CD Playback Switch");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
strcpy(id1.name, "Aux Playback Volume");
strcpy(id2.name, "CD Playback Volume");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
/* reassign AUX1 to FM */
strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
strcpy(id2.name, "FM Playback Switch");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
strcpy(id1.name, "Aux Playback Volume");
strcpy(id2.name, "FM Playback Volume");
- if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
+ if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0) {
+ snd_printk(KERN_ERR "Cannot rename opl3sa2 control\n");
return err;
+ }
/* add OPL3SA2 controls */
for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0)
@@ -539,22 +542,21 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
/* Power Management support functions */
#ifdef CONFIG_PM
-static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state)
+static int snd_opl3sa2_suspend(struct snd_card *card, pm_message_t state)
{
- opl3sa2_t *chip = card->pm_private_data;
-
- snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */
- chip->cs4231_suspend(chip->cs4231);
+ struct snd_opl3sa2 *chip = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip->cs4231->suspend(chip->cs4231);
/* power down */
snd_opl3sa2_write(chip, OPL3SA2_PM_CTRL, OPL3SA2_PM_D3);
return 0;
}
-static int snd_opl3sa2_resume(snd_card_t *card)
+static int snd_opl3sa2_resume(struct snd_card *card)
{
- opl3sa2_t *chip = card->pm_private_data;
+ struct snd_opl3sa2 *chip = card->private_data;
int i;
/* power up */
@@ -570,26 +572,25 @@ static int snd_opl3sa2_resume(snd_card_t *card)
snd_opl3sa2_write(chip, i, chip->ctlregs[i]);
}
/* restore cs4231 */
- chip->cs4231_resume(chip->cs4231);
+ chip->cs4231->resume(chip->cs4231);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
#ifdef CONFIG_PNP
-static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
- struct pnp_dev *pdev,
- int isapnp)
+static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
+ struct pnp_dev *pdev)
{
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)
+ if (!cfg) {
+ snd_printk(KERN_ERR PFX "cannot allocate pnp cfg\n");
return -ENOMEM;
+ }
/* PnP initialization */
pnp_init_resource_table(cfg);
if (sb_port[dev] != SNDRV_AUTO_PORT)
@@ -609,8 +610,8 @@ 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 && isapnp)
- snd_printk(KERN_ERR "PnP manual resources are invalid, using auto config\n");
+ if (err < 0)
+ snd_printk(KERN_WARNING "PnP manual resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
kfree(cfg);
@@ -630,111 +631,47 @@ static int __init snd_opl3sa2_pnp(int dev, opl3sa2_t *chip,
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)
+static void snd_opl3sa2_free(struct snd_card *card)
{
+ struct snd_opl3sa2 *chip = card->private_data;
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
release_and_free_resource(chip->res_port);
- kfree(chip);
- return 0;
}
-static int snd_opl3sa2_dev_free(snd_device_t *device)
-{
- opl3sa2_t *chip = device->device_data;
- 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)
+static struct snd_card *snd_opl3sa2_card_new(int dev)
{
- int xirq, xdma1, xdma2;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_opl3sa2 *chip;
- cs4231_t *cs4231;
- opl3_t *opl3;
- static snd_device_ops_t ops = {
- .dev_free = snd_opl3sa2_dev_free,
- };
- int err;
-
- if (! is_isapnp_selected(dev)) {
- if (port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify port\n");
- return -EINVAL;
- }
- if (wss_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify wss_port\n");
- return -EINVAL;
- }
- if (fm_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify fm_port\n");
- return -EINVAL;
- }
- if (midi_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk(KERN_ERR PFX "specify midi_port\n");
- return -EINVAL;
- }
- }
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_opl3sa2));
if (card == NULL)
- return -ENOMEM;
+ return NULL;
strcpy(card->driver, "OPL3SA2");
strcpy(card->shortname, "Yamaha OPL3-SA2");
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- err = -ENOMEM;
- goto __error;
- }
+ chip = card->private_data;
spin_lock_init(&chip->reg_lock);
chip->irq = -1;
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
- goto __error;
-#ifdef CONFIG_PNP
- 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);
- }
-#endif
- chip->ymode = opl3sa3_ymode[dev] & 0x03 ; /* initialise this card from supplied (or default) parameter*/
chip->card = card;
+ card->private_free = snd_opl3sa2_free;
+ return card;
+}
+
+static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
+{
+ int xirq, xdma1, xdma2;
+ struct snd_opl3sa2 *chip;
+ struct snd_cs4231 *cs4231;
+ struct snd_opl3 *opl3;
+ int err;
+
+ /* initialise this card from supplied (or default) parameter*/
+ chip = card->private_data;
+ chip->ymode = opl3sa3_ymode[dev] & 0x03 ;
chip->port = port[dev];
xirq = irq[dev];
xdma1 = dma1[dev];
@@ -742,11 +679,10 @@ static int __devinit snd_opl3sa2_probe(int dev,
if (xdma2 < 0)
chip->single_dma = 1;
if ((err = snd_opl3sa2_detect(chip)) < 0)
- goto __error;
- if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", (void *)chip)) {
+ return err;
+ if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", chip)) {
snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
- err = -ENODEV;
- goto __error;
+ return -ENODEV;
}
chip->irq = xirq;
if ((err = snd_cs4231_create(card,
@@ -756,179 +692,303 @@ static int __devinit snd_opl3sa2_probe(int dev,
CS4231_HWSHARE_IRQ,
&cs4231)) < 0) {
snd_printd("Oops, WSS not detected at 0x%lx\n", wss_port[dev] + 4);
- goto __error;
+ return err;
}
chip->cs4231 = cs4231;
if ((err = snd_cs4231_pcm(cs4231, 0, NULL)) < 0)
- goto __error;
+ return err;
if ((err = snd_cs4231_mixer(cs4231)) < 0)
- goto __error;
+ return err;
if ((err = snd_opl3sa2_mixer(chip)) < 0)
- goto __error;
+ return err;
if ((err = snd_cs4231_timer(cs4231, 0, NULL)) < 0)
- goto __error;
+ return err;
if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
if ((err = snd_opl3_create(card, fm_port[dev],
fm_port[dev] + 2,
OPL3_HW_OPL3, 0, &opl3)) < 0)
- goto __error;
+ return err;
if ((err = snd_opl3_timer_new(opl3, 1, 2)) < 0)
- goto __error;
+ return err;
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, &chip->synth)) < 0)
- goto __error;
+ return err;
}
if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2,
midi_port[dev], 0,
xirq, 0, &chip->rmidi)) < 0)
- goto __error;
+ return err;
}
-#ifdef CONFIG_PM
- chip->cs4231_suspend = chip->cs4231->suspend;
- chip->cs4231_resume = chip->cs4231->resume;
- /* now clear callbacks for cs4231 */
- chip->cs4231->suspend = NULL;
- chip->cs4231->resume = NULL;
- snd_card_set_isa_pm_callback(card, snd_opl3sa2_suspend, snd_opl3sa2_resume, chip);
-#endif
-
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
card->shortname, chip->port, xirq, xdma1);
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 (pdev)
- pnp_set_drvdata(pdev, card);
- else if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_opl3sa2_legacy[dev] = card;
- return 0;
-
- __error:
- snd_card_free(card);
- return err;
+ return snd_card_register(card);
}
#ifdef CONFIG_PNP
static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
const struct pnp_device_id *id)
{
- static int dev;
- int res;
+ static int dev;
+ int err;
+ struct snd_card *card;
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_opl3sa2_probe(dev, pdev, NULL, NULL);
- if (res < 0)
- return res;
- dev++;
- return 0;
- }
- return -ENODEV;
+ if (pnp_device_is_isapnp(pdev))
+ return -ENOENT; /* we have another procedure - card */
+ for (; dev < SNDRV_CARDS; dev++) {
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_opl3sa2_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pnp_set_drvdata(pdev, card);
+ dev++;
+ return 0;
}
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);
+ snd_card_free(pnp_get_drvdata(pdev));
+ pnp_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_opl3sa2_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+ return snd_opl3sa2_suspend(pnp_get_drvdata(pdev), state);
}
+static int snd_opl3sa2_pnp_resume(struct pnp_dev *pdev)
+{
+ return snd_opl3sa2_resume(pnp_get_drvdata(pdev));
+}
+#endif
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),
+#ifdef CONFIG_PM
+ .suspend = snd_opl3sa2_pnp_suspend,
+ .resume = snd_opl3sa2_pnp_resume,
+#endif
};
-static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *card,
+static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *id)
{
- static int dev;
- int res;
+ static int dev;
+ struct pnp_dev *pdev;
+ int err;
+ struct snd_card *card;
- 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++;
- return 0;
- }
- return -ENODEV;
+ pdev = pnp_request_card_device(pcard, id->devs[0].id, NULL);
+ if (pdev == NULL) {
+ snd_printk(KERN_ERR PFX "can't get pnp device from id '%s'\n",
+ id->devs[0].id);
+ return -EBUSY;
+ }
+ for (; dev < SNDRV_CARDS; dev++) {
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_opl3sa2_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ if ((err = snd_opl3sa2_pnp(dev, card->private_data, pdev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
static void __devexit snd_opl3sa2_pnp_cremove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
+#ifdef CONFIG_PM
+static int snd_opl3sa2_pnp_csuspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ return snd_opl3sa2_suspend(pnp_get_card_drvdata(pcard), state);
+}
+static int snd_opl3sa2_pnp_cresume(struct pnp_card_link *pcard)
+{
+ return snd_opl3sa2_resume(pnp_get_card_drvdata(pcard));
+}
+#endif
+
static struct pnp_card_driver opl3sa2_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "opl3sa2",
.id_table = snd_opl3sa2_pnpids,
.probe = snd_opl3sa2_pnp_cdetect,
.remove = __devexit_p(snd_opl3sa2_pnp_cremove),
+#ifdef CONFIG_PM
+ .suspend = snd_opl3sa2_pnp_csuspend,
+ .resume = snd_opl3sa2_pnp_cresume,
+#endif
};
#endif /* CONFIG_PNP */
+static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
+{
+ struct snd_card *card;
+ int err;
+ int dev = pdev->id;
+
+ if (port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify port\n");
+ return -EINVAL;
+ }
+ if (wss_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify wss_port\n");
+ return -EINVAL;
+ }
+ if (fm_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify fm_port\n");
+ return -EINVAL;
+ }
+ if (midi_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk(KERN_ERR PFX "specify midi_port\n");
+ return -EINVAL;
+ }
+
+ card = snd_opl3sa2_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ platform_set_drvdata(pdev, card);
+ return 0;
+}
+
+static int snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_opl3sa2_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return snd_opl3sa2_suspend(platform_get_drvdata(dev), state);
+}
+
+static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev)
+{
+ return snd_opl3sa2_resume(platform_get_drvdata(dev));
+}
+#endif
+
+#define OPL3SA2_DRIVER "snd_opl3sa2"
+
+static struct platform_driver snd_opl3sa2_nonpnp_driver = {
+ .probe = snd_opl3sa2_nonpnp_probe,
+ .remove = snd_opl3sa2_nonpnp_remove,
+#ifdef CONFIG_PM
+ .suspend = snd_opl3sa2_nonpnp_suspend,
+ .resume = snd_opl3sa2_nonpnp_resume,
+#endif
+ .driver = {
+ .name = OPL3SA2_DRIVER
+ },
+};
+
+static void __init_or_module snd_opl3sa2_unregister_all(void)
+{
+ int i;
+
+ if (pnpc_registered)
+ pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
+ if (pnp_registered)
+ pnp_unregister_driver(&opl3sa2_pnp_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
+}
+
static int __init alsa_card_opl3sa2_init(void)
{
- int dev, cards = 0;
+ int i, err, cards = 0;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev])
- continue;
+ if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (isapnp[i])
continue;
#endif
- if (snd_opl3sa2_probe(dev, NULL, NULL, NULL) >= 0)
- cards++;
+ device = platform_device_register_simple(OPL3SA2_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ cards++;
}
-#ifdef CONFIG_PNP
- cards += pnp_register_driver(&opl3sa2_pnp_driver);
- cards += pnp_register_card_driver(&opl3sa2_pnpc_driver);
-#endif
+
+ err = pnp_register_driver(&opl3sa2_pnp_driver);
+ if (err >= 0) {
+ pnp_registered = 1;
+ cards += err;
+ }
+ err = pnp_register_card_driver(&opl3sa2_pnpc_driver);
+ if (err >= 0) {
+ pnpc_registered = 1;
+ cards += err;
+ }
+
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
#endif
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
- pnp_unregister_driver(&opl3sa2_pnp_driver);
-#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_opl3sa2_unregister_all();
+ return err;
}
static void __exit alsa_card_opl3sa2_exit(void)
{
- int idx;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
- pnp_unregister_driver(&opl3sa2_pnp_driver);
-#endif
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_opl3sa2_legacy[idx]);
+ snd_opl3sa2_unregister_all();
}
module_init(alsa_card_opl3sa2_init)
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index b94339f8306f..1ea3944ef7ab 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -24,13 +24,15 @@
#include <sound/driver.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <asm/dma.h>
#include <sound/core.h>
#ifdef CS4231
#include <sound/cs4231.h>
@@ -120,8 +122,6 @@ MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
#define OPTi9XX_MC_REG(n) n
-typedef struct _snd_opti9xx opti9xx_t;
-
#ifdef OPTi93X
#define OPTi93X_INDEX 0x00
@@ -193,16 +193,14 @@ typedef struct _snd_opti9xx opti9xx_t;
#define OPTi93X_IRQ_CAPTURE 0x08
-typedef struct _snd_opti93x opti93x_t;
-
-struct _snd_opti93x {
+struct snd_opti93x {
unsigned long port;
struct resource *res_port;
int irq;
int dma1;
int dma2;
- opti9xx_t *chip;
+ struct snd_opti9xx *chip;
unsigned short hardware;
unsigned char image[32];
@@ -212,10 +210,10 @@ struct _snd_opti93x {
spinlock_t lock;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int p_dma_size;
unsigned int c_dma_size;
};
@@ -227,7 +225,7 @@ struct _snd_opti93x {
#endif /* OPTi93X */
-struct _snd_opti9xx {
+struct snd_opti9xx {
unsigned short hardware;
unsigned char password;
char name[7];
@@ -260,8 +258,8 @@ struct _snd_opti9xx {
#endif /* CONFIG_PNP */
};
-static int snd_opti9xx_first_hit = 1;
-static snd_card_t *snd_opti9xx_legacy = SNDRV_DEFAULT_PTR1;
+static int snd_opti9xx_pnp_is_probed;
+static struct platform_device *snd_opti9xx_platform_device;
#ifdef CONFIG_PNP
@@ -296,7 +294,7 @@ static char * snd_opti9xx_names[] = {
};
-static long snd_legacy_find_free_ioport(long *port_table, long size)
+static long __init snd_legacy_find_free_ioport(long *port_table, long size)
{
while (*port_table != -1) {
if (request_region(*port_table, size, "ALSA test")) {
@@ -308,7 +306,7 @@ static long snd_legacy_find_free_ioport(long *port_table, long size)
return -1;
}
-static int __devinit snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware)
+static int __init snd_opti9xx_init(struct snd_opti9xx *chip, unsigned short hardware)
{
static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
@@ -363,7 +361,7 @@ static int __devinit snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware)
return 0;
}
-static unsigned char snd_opti9xx_read(opti9xx_t *chip,
+static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
unsigned char reg)
{
unsigned long flags;
@@ -406,7 +404,7 @@ static unsigned char snd_opti9xx_read(opti9xx_t *chip,
return retval;
}
-static void snd_opti9xx_write(opti9xx_t *chip, unsigned char reg,
+static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
unsigned char value)
{
unsigned long flags;
@@ -453,7 +451,7 @@ static void snd_opti9xx_write(opti9xx_t *chip, unsigned char reg,
(snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
-static int __devinit snd_opti9xx_configure(opti9xx_t *chip)
+static int __init snd_opti9xx_configure(struct snd_opti9xx *chip)
{
unsigned char wss_base_bits;
unsigned char irq_bits;
@@ -684,7 +682,7 @@ static unsigned char snd_opti93x_default_image[32] =
};
-static int snd_opti93x_busy_wait(opti93x_t *chip)
+static int snd_opti93x_busy_wait(struct snd_opti93x *chip)
{
int timeout;
@@ -696,14 +694,14 @@ static int snd_opti93x_busy_wait(opti93x_t *chip)
return -EBUSY;
}
-static unsigned char snd_opti93x_in(opti93x_t *chip, unsigned char reg)
+static unsigned char snd_opti93x_in(struct snd_opti93x *chip, unsigned char reg)
{
snd_opti93x_busy_wait(chip);
outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
return inb(OPTi93X_PORT(chip, DATA));
}
-static void snd_opti93x_out(opti93x_t *chip, unsigned char reg,
+static void snd_opti93x_out(struct snd_opti93x *chip, unsigned char reg,
unsigned char value)
{
snd_opti93x_busy_wait(chip);
@@ -711,13 +709,13 @@ static void snd_opti93x_out(opti93x_t *chip, unsigned char reg,
outb(value, OPTi93X_PORT(chip, DATA));
}
-static void snd_opti93x_out_image(opti93x_t *chip, unsigned char reg,
+static void snd_opti93x_out_image(struct snd_opti93x *chip, unsigned char reg,
unsigned char value)
{
snd_opti93x_out(chip, reg, chip->image[reg] = value);
}
-static void snd_opti93x_out_mask(opti93x_t *chip, unsigned char reg,
+static void snd_opti93x_out_mask(struct snd_opti93x *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
snd_opti93x_out_image(chip, reg,
@@ -725,7 +723,7 @@ static void snd_opti93x_out_mask(opti93x_t *chip, unsigned char reg,
}
-static void snd_opti93x_mce_up(opti93x_t *chip)
+static void snd_opti93x_mce_up(struct snd_opti93x *chip)
{
snd_opti93x_busy_wait(chip);
@@ -734,7 +732,7 @@ static void snd_opti93x_mce_up(opti93x_t *chip)
outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
}
-static void snd_opti93x_mce_down(opti93x_t *chip)
+static void snd_opti93x_mce_down(struct snd_opti93x *chip)
{
snd_opti93x_busy_wait(chip);
@@ -746,7 +744,7 @@ static void snd_opti93x_mce_down(opti93x_t *chip)
#define snd_opti93x_mute_reg(chip, reg, mute) \
snd_opti93x_out(chip, reg, mute ? 0x80 : chip->image[reg]);
-static void snd_opti93x_mute(opti93x_t *chip, int mute)
+static void snd_opti93x_mute(struct snd_opti93x *chip, int mute)
{
mute = mute ? 1 : 0;
if (chip->mute == mute)
@@ -798,7 +796,7 @@ static unsigned int rates[] = { 5512, 6615, 8000, 9600, 11025, 16000,
44100, 48000 };
#define RATES ARRAY_SIZE(rates)
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = RATES,
.list = rates,
.mask = 0,
@@ -820,7 +818,7 @@ static unsigned char snd_opti93x_get_freq(unsigned int rate)
return bits[RATES-1];
}
-static unsigned char snd_opti93x_get_format(opti93x_t *chip,
+static unsigned char snd_opti93x_get_format(struct snd_opti93x *chip,
unsigned int format, int channels)
{
unsigned char retval = OPTi93X_LINEAR_8;
@@ -845,7 +843,7 @@ static unsigned char snd_opti93x_get_format(opti93x_t *chip,
}
-static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
+static void snd_opti93x_playback_format(struct snd_opti93x *chip, unsigned char fmt)
{
unsigned char mask;
@@ -859,7 +857,7 @@ static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
snd_opti93x_mute(chip, 0);
}
-static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
+static void snd_opti93x_capture_format(struct snd_opti93x *chip, unsigned char fmt)
{
snd_opti93x_mute(chip, 1);
@@ -875,7 +873,7 @@ static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
}
-static int snd_opti93x_open(opti93x_t *chip, unsigned int mode)
+static int snd_opti93x_open(struct snd_opti93x *chip, unsigned int mode)
{
unsigned long flags;
@@ -899,7 +897,7 @@ static int snd_opti93x_open(opti93x_t *chip, unsigned int mode)
return 0;
}
-static void snd_opti93x_close(opti93x_t *chip, unsigned int mode)
+static void snd_opti93x_close(struct snd_opti93x *chip, unsigned int mode)
{
unsigned long flags;
@@ -926,10 +924,10 @@ static void snd_opti93x_close(opti93x_t *chip, unsigned int mode)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
+static int snd_opti93x_trigger(struct snd_pcm_substream *substream,
unsigned char what, int cmd)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -937,7 +935,7 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
{
unsigned int what = 0;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == chip->playback_substream) {
@@ -964,36 +962,36 @@ static int snd_opti93x_trigger(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_opti93x_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_opti93x_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_opti93x_trigger(substream,
OPTi93X_PLAYBACK_ENABLE, cmd);
}
-static int snd_opti93x_capture_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_opti93x_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_opti93x_trigger(substream,
OPTi93X_CAPTURE_ENABLE, cmd);
}
-static int snd_opti93x_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_opti93x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_opti93x_hw_free(snd_pcm_substream_t * substream)
+static int snd_opti93x_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_opti93x_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_opti93x_playback_prepare(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned char format;
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -1023,10 +1021,10 @@ static int snd_opti93x_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_opti93x_capture_prepare(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
unsigned char format;
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -1055,9 +1053,9 @@ static int snd_opti93x_capture_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static snd_pcm_uframes_t snd_opti93x_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_opti93x_playback_pointer(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_PLAYBACK_ENABLE))
@@ -1067,9 +1065,9 @@ static snd_pcm_uframes_t snd_opti93x_playback_pointer(snd_pcm_substream_t *subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_opti93x_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_opti93x_capture_pointer(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_CAPTURE_ENABLE))
@@ -1080,7 +1078,7 @@ static snd_pcm_uframes_t snd_opti93x_capture_pointer(snd_pcm_substream_t *substr
}
-static void snd_opti93x_overrange(opti93x_t *chip)
+static void snd_opti93x_overrange(struct snd_opti93x *chip)
{
unsigned long flags;
@@ -1094,7 +1092,7 @@ static void snd_opti93x_overrange(opti93x_t *chip)
static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- opti93x_t *codec = dev_id;
+ struct snd_opti93x *codec = dev_id;
unsigned char status;
status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
@@ -1109,7 +1107,7 @@ static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *
}
-static snd_pcm_hardware_t snd_opti93x_playback = {
+static struct snd_pcm_hardware snd_opti93x_playback = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
.formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
@@ -1127,7 +1125,7 @@ static snd_pcm_hardware_t snd_opti93x_playback = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_opti93x_capture = {
+static struct snd_pcm_hardware snd_opti93x_capture = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
.formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
@@ -1145,11 +1143,11 @@ static snd_pcm_hardware_t snd_opti93x_capture = {
.fifo_size = 0,
};
-static int snd_opti93x_playback_open(snd_pcm_substream_t *substream)
+static int snd_opti93x_playback_open(struct snd_pcm_substream *substream)
{
int error;
- opti93x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if ((error = snd_opti93x_open(chip, OPTi93X_MODE_PLAY)) < 0)
return error;
@@ -1161,11 +1159,11 @@ static int snd_opti93x_playback_open(snd_pcm_substream_t *substream)
return error;
}
-static int snd_opti93x_capture_open(snd_pcm_substream_t *substream)
+static int snd_opti93x_capture_open(struct snd_pcm_substream *substream)
{
int error;
- opti93x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if ((error = snd_opti93x_open(chip, OPTi93X_MODE_CAPTURE)) < 0)
return error;
@@ -1177,18 +1175,18 @@ static int snd_opti93x_capture_open(snd_pcm_substream_t *substream)
return error;
}
-static int snd_opti93x_playback_close(snd_pcm_substream_t *substream)
+static int snd_opti93x_playback_close(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
snd_opti93x_close(chip, OPTi93X_MODE_PLAY);
return 0;
}
-static int snd_opti93x_capture_close(snd_pcm_substream_t *substream)
+static int snd_opti93x_capture_close(struct snd_pcm_substream *substream)
{
- opti93x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
snd_opti93x_close(chip, OPTi93X_MODE_CAPTURE);
@@ -1196,7 +1194,7 @@ static int snd_opti93x_capture_close(snd_pcm_substream_t *substream)
}
-static void snd_opti93x_init(opti93x_t *chip)
+static void snd_opti93x_init(struct snd_opti93x *chip)
{
unsigned long flags;
int i;
@@ -1211,7 +1209,7 @@ static void snd_opti93x_init(opti93x_t *chip)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static int snd_opti93x_probe(opti93x_t *chip)
+static int snd_opti93x_probe(struct snd_opti93x *chip)
{
unsigned long flags;
unsigned char val;
@@ -1223,7 +1221,7 @@ static int snd_opti93x_probe(opti93x_t *chip)
return (val == 0x0a) ? 0 : -ENODEV;
}
-static int snd_opti93x_free(opti93x_t *chip)
+static int snd_opti93x_free(struct snd_opti93x *chip)
{
release_and_free_resource(chip->res_port);
if (chip->dma1 >= 0) {
@@ -1241,13 +1239,13 @@ static int snd_opti93x_free(opti93x_t *chip)
return 0;
}
-static int snd_opti93x_dev_free(snd_device_t *device)
+static int snd_opti93x_dev_free(struct snd_device *device)
{
- opti93x_t *chip = device->device_data;
+ struct snd_opti93x *chip = device->device_data;
return snd_opti93x_free(chip);
}
-static const char *snd_opti93x_chip_id(opti93x_t *codec)
+static const char *snd_opti93x_chip_id(struct snd_opti93x *codec)
{
switch (codec->hardware) {
case OPTi9XX_HW_82C930: return "82C930";
@@ -1257,15 +1255,15 @@ static const char *snd_opti93x_chip_id(opti93x_t *codec)
}
}
-static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
+static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip,
int dma1, int dma2,
- opti93x_t **rcodec)
+ struct snd_opti93x **rcodec)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_opti93x_dev_free,
};
int error;
- opti93x_t *codec;
+ struct snd_opti93x *codec;
*rcodec = NULL;
codec = kzalloc(sizeof(*codec), GFP_KERNEL);
@@ -1324,7 +1322,7 @@ static int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
return 0;
}
-static snd_pcm_ops_t snd_opti93x_playback_ops = {
+static struct snd_pcm_ops snd_opti93x_playback_ops = {
.open = snd_opti93x_playback_open,
.close = snd_opti93x_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1335,7 +1333,7 @@ static snd_pcm_ops_t snd_opti93x_playback_ops = {
.pointer = snd_opti93x_playback_pointer,
};
-static snd_pcm_ops_t snd_opti93x_capture_ops = {
+static struct snd_pcm_ops snd_opti93x_capture_ops = {
.open = snd_opti93x_capture_open,
.close = snd_opti93x_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1346,17 +1344,10 @@ static snd_pcm_ops_t snd_opti93x_capture_ops = {
.pointer = snd_opti93x_capture_pointer,
};
-static void snd_opti93x_pcm_free(snd_pcm_t *pcm)
-{
- opti93x_t *codec = pcm->private_data;
- codec->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm)
+static int snd_opti93x_pcm(struct snd_opti93x *codec, int device, struct snd_pcm **rpcm)
{
int error;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)))
return error;
@@ -1365,7 +1356,6 @@ static int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_opti93x_capture_ops);
pcm->private_data = codec;
- pcm->private_free = snd_opti93x_pcm_free;
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, snd_opti93x_chip_id(codec));
@@ -1384,7 +1374,7 @@ static int snd_opti93x_pcm(opti93x_t *codec, int device, snd_pcm_t **rpcm)
* MIXER part
*/
-static int snd_opti93x_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_opti93x_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Line1", "Aux", "Mic", "Mix"
@@ -1399,9 +1389,9 @@ static int snd_opti93x_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_opti93x_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -1411,9 +1401,9 @@ static int snd_opti93x_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_opti93x_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short left, right;
int change;
@@ -1442,7 +1432,7 @@ static int snd_opti93x_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
.get = snd_opti93x_get_single, .put = snd_opti93x_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_opti93x_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_opti93x_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1453,9 +1443,9 @@ static int snd_opti93x_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_opti93x_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1470,9 +1460,9 @@ static int snd_opti93x_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_opti93x_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1507,7 +1497,7 @@ static int snd_opti93x_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
do { xctl.private_value &= ~0x0000ffff; \
xctl.private_value |= left_reg | (right_reg << 8); } while (0)
-static int snd_opti93x_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_opti93x_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1518,9 +1508,9 @@ static int snd_opti93x_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_opti93x_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1540,9 +1530,9 @@ static int snd_opti93x_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- opti93x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1571,7 +1561,7 @@ static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return change;
}
-static snd_kcontrol_new_t snd_opti93x_controls[] = {
+static struct snd_kcontrol_new snd_opti93x_controls[] = {
OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
@@ -1597,10 +1587,10 @@ OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0
}
};
-static int snd_opti93x_mixer(opti93x_t *chip)
+static int snd_opti93x_mixer(struct snd_opti93x *chip)
{
- snd_card_t *card;
- snd_kcontrol_new_t knew;
+ struct snd_card *card;
+ struct snd_kcontrol_new knew;
int err;
unsigned int idx;
@@ -1632,7 +1622,7 @@ static int snd_opti93x_mixer(opti93x_t *chip)
#endif /* OPTi93X */
-static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
+static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti9xx *chip)
{
int i, err;
@@ -1686,8 +1676,8 @@ static int __devinit snd_card_opti9xx_detect(snd_card_t *card, opti9xx_t *chip)
}
#ifdef CONFIG_PNP
-static int __devinit snd_card_opti9xx_pnp(opti9xx_t *chip, struct pnp_card_link *card,
- const struct pnp_card_device_id *pid)
+static int __init snd_card_opti9xx_pnp(struct snd_opti9xx *chip, struct pnp_card_link *card,
+ const struct pnp_card_device_id *pid)
{
struct pnp_dev *pdev;
struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
@@ -1778,195 +1768,35 @@ static int __devinit snd_card_opti9xx_pnp(opti9xx_t *chip, struct pnp_card_link
}
#endif /* CONFIG_PNP */
-#if 0
-static int __devinit snd_card_opti9xx_resources(struct snd_card_opti9xx *chip,
- snd_card_t *card)
-{
- int error, i, pnp = 0;
-
-#ifdef CONFIG_PNP
- pnp = chip->dev != NULL;
-#endif /* CONFIG_PNP */
-
-#ifndef OPTi93X
- if (chip->chip->hardware == OPTi9XX_HW_82C928)
- mpu_port = -1;
-#endif /* OPTi93X */
- error = 0;
- if (!pnp && (mpu_port == SNDRV_DEFAULT_PORT1)) {
- for (i = 0; possible_mpu_ports[i] != -1; i++)
- if (!snd_register_ioport(card, possible_mpu_ports[i], 2,
- DRIVER_NAME" - MPU-401", NULL)) {
- mpu_port = possible_mpu_ports[i];
- break;
- }
- if (mpu_port == SNDRV_DEFAULT_PORT1)
- error = -EBUSY;
- }
- else
- error = (mpu_port == -1) ? -ENODEV :
- snd_register_ioport(card, mpu_port, 2,
- DRIVER_NAME" - MPU-401", NULL);
- if (error)
- chip->chip->mpu_port = -1;
- else if (pnp && (irq == mpu_irq))
- chip->chip->mpu_irq = mpu_irq;
- else if (!snd_register_interrupt(card,
- DRIVER_NAME" - MPU-401",
- mpu_irq, SNDRV_IRQ_TYPE_ISA,
- snd_card_opti9xx_mpu_interrupt, chip,
- pnp ? no_alternatives : possible_mpu_irqs,
- &chip->mpuirqptr)) {
- chip->chip->mpu_port = mpu_port;
- chip->chip->mpu_irq = chip->mpuirqptr->irq;
- }
- else
- chip->chip->mpu_port = -1;
-
- if (!pnp && (port == SNDRV_DEFAULT_PORT1)) {
- for (i = 0; possible_ports[i] != -1; i++)
- if (!snd_register_ioport(card, possible_ports[i], 8,
- DRIVER_NAME" - WSS", NULL)) {
- port = possible_ports[i];
- break;
- }
- if (port == SNDRV_DEFAULT_PORT1)
- return -EBUSY;
- }
- else if ((error = snd_register_ioport(card, port, 8,
- DRIVER_NAME" - WSS", NULL)) < 0)
- return error;
- chip->chip->wss_base = port;
- if ((error = snd_register_interrupt(card, DRIVER_NAME" - WSS",
- irq, SNDRV_IRQ_TYPE_ISA,
- snd_card_opti9xx_interrupt, chip,
- pnp ? no_alternatives : possible_irqs,
- &chip->irqptr)) < 0)
- return error;
- chip->chip->irq = chip->irqptr->irq;
- if ((error = snd_register_dma_channel(card,
-#if defined(CS4231) || defined(OPTi93X)
- DRIVER_NAME" - WSS playback",
-#else
- DRIVER_NAME" - WSS",
-#endif /* CS4231 || OPTi93X */
- dma1, SNDRV_DMA_TYPE_ISA, dma1_size,
- pnp ? no_alternatives : possible_dma1s,
- &chip->dma1ptr)) < 0)
- return error;
- chip->chip->dma1 = chip->dma1ptr->dma;
-#if defined(CS4231) || defined(OPTi93X)
- if ((error = snd_register_dma_channel(card, DRIVER_NAME" - WSS capture",
- dma2, SNDRV_DMA_TYPE_ISA, dma2_size,
- pnp ? no_alternatives :
- possible_dma2s[chip->dma1ptr->dma],
- &chip->dma2ptr)) < 0)
- return error;
- chip->chip->dma2 = chip->dma2ptr->dma;
-#endif /* CS4231 || OPTi93X */
-
- if (snd_register_ioport(card,
- pnp ? fm_port : fm_port = 0x388, 4,
- DRIVER_NAME" - OPL", NULL) < 0)
- fm_port = -1;
- chip->chip->fm_port = fm_port;
-
- return 0;
-}
-#endif
-
-static void snd_card_opti9xx_free(snd_card_t *card)
+static void snd_card_opti9xx_free(struct snd_card *card)
{
- opti9xx_t *chip = (opti9xx_t *)card->private_data;
+ struct snd_opti9xx *chip = card->private_data;
if (chip)
release_and_free_resource(chip->res_mc_base);
}
-static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static int __init snd_opti9xx_probe(struct snd_card *card)
{
static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
- static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
-#ifdef OPTi93X
- static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
-#else
- static int possible_irqs[] = {9, 10, 11, 7, -1};
-#endif /* OPTi93X */
- static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
- static int possible_dma1s[] = {3, 1, 0, -1};
-#if defined(CS4231) || defined(OPTi93X)
- static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
-#endif /* CS4231 || OPTi93X */
int error;
- opti9xx_t *chip;
+ struct snd_opti9xx *chip = card->private_data;
#if defined(OPTi93X)
- opti93x_t *codec;
+ struct snd_opti93x *codec;
#elif defined(CS4231)
- cs4231_t *codec;
- snd_timer_t *timer;
+ struct snd_cs4231 *codec;
+ struct snd_timer *timer;
#else
- ad1848_t *codec;
+ struct snd_ad1848 *codec;
#endif
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_rawmidi_t *rmidi;
- snd_hwdep_t *synth;
-#ifdef CONFIG_PNP
- int hw;
-#endif /* CONFIG_PNP */
-
- if (pcard && !snd_opti9xx_first_hit)
- return -EBUSY;
- if (!(card = snd_card_new(index, id, THIS_MODULE,
- sizeof(opti9xx_t))))
- return -ENOMEM;
- card->private_free = snd_card_opti9xx_free;
- chip = (opti9xx_t *)card->private_data;
-
-#ifdef CONFIG_PNP
- if (isapnp && pcard && (hw = snd_card_opti9xx_pnp(chip, pcard, pid)) > 0) {
- switch (hw) {
- case 0x0924:
- hw = OPTi9XX_HW_82C924;
- break;
- case 0x0925:
- hw = OPTi9XX_HW_82C925;
- break;
- case 0x0931:
- hw = OPTi9XX_HW_82C931;
- break;
- default:
- snd_card_free(card);
- return -ENODEV;
- }
-
- if ((error = snd_opti9xx_init(chip, hw))) {
- snd_card_free(card);
- return error;
- }
- if (hw <= OPTi9XX_HW_82C930)
- chip->mc_base -= 0x80;
- snd_card_set_dev(card, &pcard->card->dev);
- } else {
-#endif /* CONFIG_PNP */
- if ((error = snd_card_opti9xx_detect(card, chip)) < 0) {
- 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 */
+ struct snd_pcm *pcm;
+ struct snd_rawmidi *rmidi;
+ struct snd_hwdep *synth;
if (! chip->res_mc_base &&
- (chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) {
- snd_card_free(card);
+ (chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size,
+ "OPTi9xx MC")) == NULL)
return -ENOMEM;
- }
chip->wss_base = port;
chip->fm_port = fm_port;
@@ -1980,110 +1810,42 @@ static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
if (chip->wss_base == SNDRV_AUTO_PORT) {
if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
- snd_card_free(card);
snd_printk("unable to find a free WSS port\n");
return -EBUSY;
}
}
-#ifdef CONFIG_PNP
- if (!isapnp) {
-#endif
- if (chip->mpu_port == SNDRV_AUTO_PORT) {
- if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free MPU401 port\n");
- return -EBUSY;
- }
- }
- if (chip->irq == SNDRV_AUTO_IRQ) {
- if ((chip->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free IRQ\n");
- return -EBUSY;
- }
- }
- if (chip->mpu_irq == SNDRV_AUTO_IRQ) {
- if ((chip->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free MPU401 IRQ\n");
- return -EBUSY;
- }
- }
- if (chip->dma1 == SNDRV_AUTO_DMA) {
- if ((chip->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA1\n");
- return -EBUSY;
- }
- }
-#if defined(CS4231) || defined(OPTi93X)
- if (chip->dma2 == SNDRV_AUTO_DMA) {
- if ((chip->dma2 = snd_legacy_find_free_dma(possible_dma2s[chip->dma1 % 4])) < 0) {
- snd_card_free(card);
- snd_printk("unable to find a free DMA2\n");
- return -EBUSY;
- }
- }
-#endif
-
-#ifdef CONFIG_PNP
- }
-#endif
-
- if ((error = snd_opti9xx_configure(chip))) {
- snd_card_free(card);
+ if ((error = snd_opti9xx_configure(chip)))
return error;
- }
#if defined(OPTi93X)
- if ((error = snd_opti93x_create(card, chip, chip->dma1, chip->dma2, &codec))) {
- snd_card_free(card);
+ if ((error = snd_opti93x_create(card, chip, chip->dma1, chip->dma2, &codec)))
return error;
- }
- if ((error = snd_opti93x_pcm(codec, 0, &pcm)) < 0) {
- snd_card_free(card);
+ if ((error = snd_opti93x_pcm(codec, 0, &pcm)) < 0)
return error;
- }
- if ((error = snd_opti93x_mixer(codec)) < 0) {
- snd_card_free(card);
+ if ((error = snd_opti93x_mixer(codec)) < 0)
return error;
- }
#elif defined(CS4231)
if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1,
chip->irq, chip->dma1, chip->dma2,
CS4231_HW_DETECT,
0,
- &codec)) < 0) {
- snd_card_free(card);
+ &codec)) < 0)
return error;
- }
- if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
- snd_card_free(card);
+ if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0)
return error;
- }
- if ((error = snd_cs4231_mixer(codec)) < 0) {
- snd_card_free(card);
+ if ((error = snd_cs4231_mixer(codec)) < 0)
return error;
- }
- if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
- snd_card_free(card);
+ if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0)
return error;
- }
#else
if ((error = snd_ad1848_create(card, chip->wss_base + 4,
chip->irq, chip->dma1,
- AD1848_HW_DETECT, &codec)) < 0) {
- snd_card_free(card);
+ AD1848_HW_DETECT, &codec)) < 0)
return error;
- }
- if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0) {
- snd_card_free(card);
+ if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0)
return error;
- }
- if ((error = snd_ad1848_mixer(codec)) < 0) {
- snd_card_free(card);
+ if ((error = snd_ad1848_mixer(codec)) < 0)
return error;
- }
#endif
strcpy(card->driver, chip->name);
sprintf(card->shortname, "OPTi %s", card->driver);
@@ -2103,15 +1865,16 @@ static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
chip->mpu_port, 0, chip->mpu_irq, SA_INTERRUPT,
&rmidi)))
- snd_printk("no MPU-401 device at 0x%lx?\n", chip->mpu_port);
+ snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
+ chip->mpu_port);
if (chip->fm_port > 0 && chip->fm_port != SNDRV_AUTO_PORT) {
- opl3_t *opl3 = NULL;
+ struct snd_opl3 *opl3 = NULL;
#ifndef OPTi93X
if (chip->hardware == OPTi9XX_HW_82C928 ||
chip->hardware == OPTi9XX_HW_82C929 ||
chip->hardware == OPTi9XX_HW_82C924) {
- opl4_t *opl4;
+ struct snd_opl4 *opl4;
/* assume we have an OPL4 */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
0x20, 0x20);
@@ -2129,89 +1892,230 @@ static int snd_card_opti9xx_probe(struct pnp_card_link *pcard,
chip->fm_port,
chip->fm_port + 2,
OPL3_HW_AUTO, 0, &opl3) < 0) {
- snd_printk("no OPL device at 0x%lx-0x%lx\n",
+ snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
chip->fm_port, chip->fm_port + 4 - 1);
}
if (opl3) {
- if ((error = snd_opl3_timer_new(opl3,
#ifdef CS4231
- 1, 2)) < 0) {
+ const int t1dev = 1;
#else
- 0, 1)) < 0) {
-#endif /* CS4231 */
- snd_card_free(card);
+ const int t1dev = 0;
+#endif
+ if ((error = snd_opl3_timer_new(opl3, t1dev, t1dev+1)) < 0)
return error;
- }
- if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0) {
- snd_card_free(card);
+ if ((error = snd_opl3_hwdep_new(opl3, 0, 1, &synth)) < 0)
return error;
- }
}
}
- if ((error = snd_card_register(card))) {
+ return snd_card_register(card);
+}
+
+static struct snd_card *snd_opti9xx_card_new(void)
+{
+ struct snd_card *card;
+
+ card = snd_card_new(index, id, THIS_MODULE, sizeof(struct snd_opti9xx));
+ if (! card)
+ return NULL;
+ card->private_free = snd_card_opti9xx_free;
+ return card;
+}
+
+static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
+{
+ struct snd_card *card;
+ int error;
+ static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
+#ifdef OPTi93X
+ static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
+#else
+ static int possible_irqs[] = {9, 10, 11, 7, -1};
+#endif /* OPTi93X */
+ static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
+ static int possible_dma1s[] = {3, 1, 0, -1};
+#if defined(CS4231) || defined(OPTi93X)
+ static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
+#endif /* CS4231 || OPTi93X */
+
+ if (snd_opti9xx_pnp_is_probed)
+ return -EBUSY;
+
+ if (mpu_port == SNDRV_AUTO_PORT) {
+ if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
+ snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
+ return -EBUSY;
+ }
+ }
+ if (irq == SNDRV_AUTO_IRQ) {
+ if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (mpu_irq == SNDRV_AUTO_IRQ) {
+ if ((mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
+ snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (dma1 == SNDRV_AUTO_DMA) {
+ if ((dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
+ snd_printk(KERN_ERR "unable to find a free DMA1\n");
+ return -EBUSY;
+ }
+ }
+#if defined(CS4231) || defined(OPTi93X)
+ if (dma2 == SNDRV_AUTO_DMA) {
+ if ((dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4])) < 0) {
+ snd_printk("unable to find a free DMA2\n");
+ return -EBUSY;
+ }
+ }
+#endif
+
+ card = snd_opti9xx_card_new();
+ if (! card)
+ return -ENOMEM;
+
+ if ((error = snd_card_opti9xx_detect(card, card->private_data)) < 0) {
snd_card_free(card);
return error;
}
- snd_opti9xx_first_hit = 0;
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_opti9xx_legacy = card;
+ snd_card_set_dev(card, &devptr->dev);
+ if ((error = snd_opti9xx_probe(card)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ platform_set_drvdata(devptr, card);
+ return 0;
+}
+
+static int __devexit snd_opti9xx_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
return 0;
}
+static struct platform_driver snd_opti9xx_driver = {
+ .probe = snd_opti9xx_nonpnp_probe,
+ .remove = __devexit_p(snd_opti9xx_nonpnp_remove),
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = DRIVER_NAME
+ },
+};
+
#ifdef CONFIG_PNP
-static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
+static int __init snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ struct snd_card *card;
+ int error, hw;
+ struct snd_opti9xx *chip;
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
- snd_opti9xx_first_hit = 0;
+ if (snd_opti9xx_pnp_is_probed)
+ return -EBUSY;
+ if (! isapnp)
+ return -ENODEV;
+ card = snd_opti9xx_card_new();
+ if (! card)
+ return -ENOMEM;
+ chip = card->private_data;
+
+ hw = snd_card_opti9xx_pnp(chip, pcard, pid);
+ switch (hw) {
+ case 0x0924:
+ hw = OPTi9XX_HW_82C924;
+ break;
+ case 0x0925:
+ hw = OPTi9XX_HW_82C925;
+ break;
+ case 0x0931:
+ hw = OPTi9XX_HW_82C931;
+ break;
+ default:
+ snd_card_free(card);
+ return -ENODEV;
+ }
+
+ if ((error = snd_opti9xx_init(chip, hw))) {
+ snd_card_free(card);
+ return error;
+ }
+ if (hw <= OPTi9XX_HW_82C930)
+ chip->mc_base -= 0x80;
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((error = snd_opti9xx_probe(card)) < 0) {
+ snd_card_free(card);
+ return error;
+ }
+ pnp_set_card_drvdata(pcard, card);
+ snd_opti9xx_pnp_is_probed = 1;
+ return 0;
+}
+
+static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard)
+{
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+ snd_opti9xx_pnp_is_probed = 0;
}
static struct pnp_card_driver opti9xx_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "opti9xx",
.id_table = snd_opti9xx_pnpids,
- .probe = snd_card_opti9xx_probe,
+ .probe = snd_opti9xx_pnp_probe,
.remove = __devexit_p(snd_opti9xx_pnp_remove),
};
#endif
-static int __init alsa_card_opti9xx_init(void)
-{
- int cards, error;
-
#ifdef CONFIG_PNP
- cards = pnp_register_card_driver(&opti9xx_pnpc_driver);
+#define is_isapnp_selected() isapnp
#else
- cards = 0;
-#endif
- if (cards == 0 && (error = snd_card_opti9xx_probe(NULL, NULL)) < 0) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&opti9xx_pnpc_driver);
+#define is_isapnp_selected() 0
#endif
-#ifdef MODULE
#ifdef OPTi93X
- printk(KERN_ERR "no OPTi 82C93x soundcard found\n");
+#define CHIP_NAME "82C93x"
#else
- printk(KERN_ERR "no OPTi 82C92x soundcard found\n");
-#endif /* OPTi93X */
+#define CHIP_NAME "82C92x"
#endif
- return error;
+
+static int __init alsa_card_opti9xx_init(void)
+{
+ int error;
+ struct platform_device *device;
+
+ pnp_register_card_driver(&opti9xx_pnpc_driver);
+ if (snd_opti9xx_pnp_is_probed)
+ return 0;
+ if (! is_isapnp_selected()) {
+ error = platform_driver_register(&snd_opti9xx_driver);
+ if (error < 0)
+ return error;
+ device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+ if (!IS_ERR(device)) {
+ snd_opti9xx_platform_device = device;
+ return 0;
+ }
+ platform_driver_unregister(&snd_opti9xx_driver);
}
- return 0;
+ pnp_unregister_card_driver(&opti9xx_pnpc_driver);
+#ifdef MODULE
+ printk(KERN_ERR "no OPTi " CHIP_NAME " soundcard found\n");
+#endif
+ return -ENODEV;
}
static void __exit alsa_card_opti9xx_exit(void)
{
-#ifdef CONFIG_PNP
+ if (!snd_opti9xx_pnp_is_probed) {
+ platform_device_unregister(snd_opti9xx_platform_device);
+ platform_driver_unregister(&snd_opti9xx_driver);
+ }
pnp_unregister_card_driver(&opti9xx_pnpc_driver);
-#endif
- if (snd_opti9xx_legacy)
- snd_card_free(snd_opti9xx_legacy);
}
module_init(alsa_card_opti9xx_init)
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index b09c6575e01a..c0b8d61b75e7 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -45,7 +45,7 @@
* directly. The macros handle the port number and command word.
*/
/* Write a word */
-void snd_emu8000_poke(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
+void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
{
unsigned long flags;
spin_lock_irqsave(&emu->reg_lock, flags);
@@ -58,7 +58,7 @@ void snd_emu8000_poke(emu8000_t *emu, unsigned int port, unsigned int reg, unsig
}
/* Read a word */
-unsigned short snd_emu8000_peek(emu8000_t *emu, unsigned int port, unsigned int reg)
+unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
{
unsigned short res;
unsigned long flags;
@@ -73,7 +73,7 @@ unsigned short snd_emu8000_peek(emu8000_t *emu, unsigned int port, unsigned int
}
/* Write a double word */
-void snd_emu8000_poke_dw(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
+void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
{
unsigned long flags;
spin_lock_irqsave(&emu->reg_lock, flags);
@@ -87,7 +87,7 @@ void snd_emu8000_poke_dw(emu8000_t *emu, unsigned int port, unsigned int reg, un
}
/* Read a double word */
-unsigned int snd_emu8000_peek_dw(emu8000_t *emu, unsigned int port, unsigned int reg)
+unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
{
unsigned short low;
unsigned int res;
@@ -107,7 +107,7 @@ unsigned int snd_emu8000_peek_dw(emu8000_t *emu, unsigned int port, unsigned int
* Set up / close a channel to be used for DMA.
*/
/*exported*/ void
-snd_emu8000_dma_chan(emu8000_t *emu, int ch, int mode)
+snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
{
unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
mode &= EMU8000_RAM_MODE_MASK;
@@ -132,7 +132,7 @@ snd_emu8000_dma_chan(emu8000_t *emu, int ch, int mode)
/*
*/
static void __init
-snd_emu8000_read_wait(emu8000_t *emu)
+snd_emu8000_read_wait(struct snd_emu8000 *emu)
{
while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
schedule_timeout_interruptible(1);
@@ -144,7 +144,7 @@ snd_emu8000_read_wait(emu8000_t *emu)
/*
*/
static void __init
-snd_emu8000_write_wait(emu8000_t *emu)
+snd_emu8000_write_wait(struct snd_emu8000 *emu)
{
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
schedule_timeout_interruptible(1);
@@ -157,7 +157,7 @@ snd_emu8000_write_wait(emu8000_t *emu)
* detect a card at the given port
*/
static int __init
-snd_emu8000_detect(emu8000_t *emu)
+snd_emu8000_detect(struct snd_emu8000 *emu)
{
/* Initialise */
EMU8000_HWCF1_WRITE(emu, 0x0059);
@@ -183,7 +183,7 @@ snd_emu8000_detect(emu8000_t *emu)
* intiailize audio channels
*/
static void __init
-init_audio(emu8000_t *emu)
+init_audio(struct snd_emu8000 *emu)
{
int ch;
@@ -224,7 +224,7 @@ init_audio(emu8000_t *emu)
* initialize DMA address
*/
static void __init
-init_dma(emu8000_t *emu)
+init_dma(struct snd_emu8000 *emu)
{
EMU8000_SMALR_WRITE(emu, 0);
EMU8000_SMARR_WRITE(emu, 0);
@@ -328,7 +328,7 @@ static unsigned short init4[128] /*__devinitdata*/ = {
* is meant to work
*/
static void __init
-send_array(emu8000_t *emu, unsigned short *data, int size)
+send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
{
int i;
unsigned short *p;
@@ -350,7 +350,7 @@ send_array(emu8000_t *emu, unsigned short *data, int size)
* initialisation sequence in the adip.
*/
static void __init
-init_arrays(emu8000_t *emu)
+init_arrays(struct snd_emu8000 *emu)
{
send_array(emu, init1, ARRAY_SIZE(init1)/4);
@@ -376,7 +376,7 @@ init_arrays(emu8000_t *emu)
* reallocating between read and write.
*/
static void __init
-size_dram(emu8000_t *emu)
+size_dram(struct snd_emu8000 *emu)
{
int i, size;
@@ -455,7 +455,7 @@ size_dram(emu8000_t *emu)
* and therefore lose 2 voices.
*/
/*exported*/ void
-snd_emu8000_init_fm(emu8000_t *emu)
+snd_emu8000_init_fm(struct snd_emu8000 *emu)
{
unsigned long flags;
@@ -501,7 +501,7 @@ snd_emu8000_init_fm(emu8000_t *emu)
* The main initialization routine.
*/
static void __init
-snd_emu8000_init_hw(emu8000_t *emu)
+snd_emu8000_init_hw(struct snd_emu8000 *emu)
{
int i;
@@ -585,7 +585,7 @@ static unsigned short treble_parm[12][9] = {
* set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
*/
/*exported*/ void
-snd_emu8000_update_equalizer(emu8000_t *emu)
+snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
{
unsigned short w;
int bass = emu->bass_level;
@@ -628,17 +628,17 @@ snd_emu8000_update_equalizer(emu8000_t *emu)
/* user can define chorus modes up to 32 */
#define SNDRV_EMU8000_CHORUS_NUMBERS 32
-typedef struct soundfont_chorus_fx_t {
+struct soundfont_chorus_fx {
unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
-} soundfont_chorus_fx_t;
+};
/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
-static soundfont_chorus_fx_t chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
+static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
{0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
{0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
{0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
@@ -650,9 +650,9 @@ static soundfont_chorus_fx_t chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
};
/*exported*/ int
-snd_emu8000_load_chorus_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
+snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
{
- soundfont_chorus_fx_t rec;
+ struct soundfont_chorus_fx rec;
if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
return -EINVAL;
@@ -665,7 +665,7 @@ snd_emu8000_load_chorus_fx(emu8000_t *emu, int mode, const void __user *buf, lon
}
/*exported*/ void
-snd_emu8000_update_chorus_mode(emu8000_t *emu)
+snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
{
int effect = emu->chorus_mode;
if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
@@ -699,15 +699,15 @@ snd_emu8000_update_chorus_mode(emu8000_t *emu)
/* user can define reverb modes up to 32 */
#define SNDRV_EMU8000_REVERB_NUMBERS 32
-typedef struct soundfont_reverb_fx_t {
+struct soundfont_reverb_fx {
unsigned short parms[28];
-} soundfont_reverb_fx_t;
+};
/* reverb mode settings; write the following 28 data of 16 bit length
* on the corresponding ports in the reverb_cmds array
*/
static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
-static soundfont_reverb_fx_t reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
+static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
{{ /* room 1 */
0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
@@ -777,9 +777,9 @@ static struct reverb_cmd_pair {
};
/*exported*/ int
-snd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
+snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
{
- soundfont_reverb_fx_t rec;
+ struct soundfont_reverb_fx rec;
if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
@@ -793,7 +793,7 @@ snd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, lon
}
/*exported*/ void
-snd_emu8000_update_reverb_mode(emu8000_t *emu)
+snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
{
int effect = emu->reverb_mode;
int i;
@@ -819,7 +819,7 @@ snd_emu8000_update_reverb_mode(emu8000_t *emu)
/*
* bass/treble
*/
-static int mixer_bass_treble_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -828,17 +828,17 @@ static int mixer_bass_treble_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int mixer_bass_treble_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
return 0;
}
-static int mixer_bass_treble_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1;
@@ -857,7 +857,7 @@ static int mixer_bass_treble_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t mixer_bass_control =
+static struct snd_kcontrol_new mixer_bass_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Synth Tone Control - Bass",
@@ -867,7 +867,7 @@ static snd_kcontrol_new_t mixer_bass_control =
.private_value = 0,
};
-static snd_kcontrol_new_t mixer_treble_control =
+static struct snd_kcontrol_new mixer_treble_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Synth Tone Control - Treble",
@@ -880,7 +880,7 @@ static snd_kcontrol_new_t mixer_treble_control =
/*
* chorus/reverb mode
*/
-static int mixer_chorus_reverb_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -889,17 +889,17 @@ static int mixer_chorus_reverb_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int mixer_chorus_reverb_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
return 0;
}
-static int mixer_chorus_reverb_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1;
@@ -924,7 +924,7 @@ static int mixer_chorus_reverb_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return change;
}
-static snd_kcontrol_new_t mixer_chorus_mode_control =
+static struct snd_kcontrol_new mixer_chorus_mode_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Chorus Mode",
@@ -934,7 +934,7 @@ static snd_kcontrol_new_t mixer_chorus_mode_control =
.private_value = 1,
};
-static snd_kcontrol_new_t mixer_reverb_mode_control =
+static struct snd_kcontrol_new mixer_reverb_mode_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Reverb Mode",
@@ -947,7 +947,7 @@ static snd_kcontrol_new_t mixer_reverb_mode_control =
/*
* FM OPL3 chorus/reverb depth
*/
-static int mixer_fm_depth_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -956,17 +956,17 @@ static int mixer_fm_depth_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int mixer_fm_depth_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
return 0;
}
-static int mixer_fm_depth_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu8000_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned short val1;
@@ -986,7 +986,7 @@ static int mixer_fm_depth_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return change;
}
-static snd_kcontrol_new_t mixer_fm_chorus_depth_control =
+static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "FM Chorus Depth",
@@ -996,7 +996,7 @@ static snd_kcontrol_new_t mixer_fm_chorus_depth_control =
.private_value = 1,
};
-static snd_kcontrol_new_t mixer_fm_reverb_depth_control =
+static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "FM Reverb Depth",
@@ -1007,7 +1007,7 @@ static snd_kcontrol_new_t mixer_fm_reverb_depth_control =
};
-static snd_kcontrol_new_t *mixer_defs[EMU8000_NUM_CONTROLS] = {
+static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
&mixer_bass_control,
&mixer_treble_control,
&mixer_chorus_mode_control,
@@ -1020,7 +1020,7 @@ static snd_kcontrol_new_t *mixer_defs[EMU8000_NUM_CONTROLS] = {
* create and attach mixer elements for WaveTable treble/bass controls
*/
static int __init
-snd_emu8000_create_mixer(snd_card_t *card, emu8000_t *emu)
+snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
{
int i, err = 0;
@@ -1049,7 +1049,7 @@ __error:
/*
* free resources
*/
-static int snd_emu8000_free(emu8000_t *hw)
+static int snd_emu8000_free(struct snd_emu8000 *hw)
{
release_and_free_resource(hw->res_port1);
release_and_free_resource(hw->res_port2);
@@ -1060,9 +1060,9 @@ static int snd_emu8000_free(emu8000_t *hw)
/*
*/
-static int snd_emu8000_dev_free(snd_device_t *device)
+static int snd_emu8000_dev_free(struct snd_device *device)
{
- emu8000_t *hw = device->device_data;
+ struct snd_emu8000 *hw = device->device_data;
return snd_emu8000_free(hw);
}
@@ -1070,12 +1070,13 @@ static int snd_emu8000_dev_free(snd_device_t *device)
* initialize and register emu8000 synth device.
*/
int __init
-snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_device_t **awe_ret)
+snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
+ struct snd_seq_device **awe_ret)
{
- snd_seq_device_t *awe;
- emu8000_t *hw;
+ struct snd_seq_device *awe;
+ struct snd_emu8000 *hw;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_emu8000_dev_free,
};
@@ -1127,9 +1128,9 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
}
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
- sizeof(emu8000_t*), &awe) >= 0) {
+ sizeof(struct snd_emu8000*), &awe) >= 0) {
strcpy(awe->name, "EMU-8000");
- *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
+ *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
}
#else
awe = NULL;
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
index 1cc4101a17a4..9a3c71cc2e07 100644
--- a/sound/isa/sb/emu8000_callback.c
+++ b/sound/isa/sb/emu8000_callback.c
@@ -25,27 +25,30 @@
/*
* prototypes
*/
-static snd_emux_voice_t *get_voice(snd_emux_t *emu, snd_emux_port_t *port);
-static int start_voice(snd_emux_voice_t *vp);
-static void trigger_voice(snd_emux_voice_t *vp);
-static void release_voice(snd_emux_voice_t *vp);
-static void update_voice(snd_emux_voice_t *vp, int update);
-static void reset_voice(snd_emux_t *emu, int ch);
-static void terminate_voice(snd_emux_voice_t *vp);
-static void sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
+static struct snd_emux_voice *get_voice(struct snd_emux *emu,
+ struct snd_emux_port *port);
+static int start_voice(struct snd_emux_voice *vp);
+static void trigger_voice(struct snd_emux_voice *vp);
+static void release_voice(struct snd_emux_voice *vp);
+static void update_voice(struct snd_emux_voice *vp, int update);
+static void reset_voice(struct snd_emux *emu, int ch);
+static void terminate_voice(struct snd_emux_voice *vp);
+static void sysex(struct snd_emux *emu, char *buf, int len, int parsed,
+ struct snd_midi_channel_set *chset);
#ifdef CONFIG_SND_SEQUENCER_OSS
-static int oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2);
+static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2);
#endif
-static int load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len);
-
-static void set_pitch(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_volume(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_pan(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_fmmod(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_tremfreq(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_fm2frq2(emu8000_t *hw, snd_emux_voice_t *vp);
-static void set_filterQ(emu8000_t *hw, snd_emux_voice_t *vp);
-static void snd_emu8000_tweak_voice(emu8000_t *emu, int ch);
+static int load_fx(struct snd_emux *emu, int type, int mode,
+ const void __user *buf, long len);
+
+static void set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
+static void snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int ch);
/*
* Ensure a value is between two points
@@ -58,7 +61,7 @@ static void snd_emu8000_tweak_voice(emu8000_t *emu, int ch);
/*
* set up operators
*/
-static snd_emux_operators_t emu8000_ops = {
+static struct snd_emux_operators emu8000_ops = {
.owner = THIS_MODULE,
.get_voice = get_voice,
.prepare = start_voice,
@@ -78,7 +81,7 @@ static snd_emux_operators_t emu8000_ops = {
};
void
-snd_emu8000_ops_setup(emu8000_t *hw)
+snd_emu8000_ops_setup(struct snd_emu8000 *hw)
{
hw->emu->ops = emu8000_ops;
}
@@ -89,10 +92,10 @@ snd_emu8000_ops_setup(emu8000_t *hw)
* Terminate a voice
*/
static void
-release_voice(snd_emux_voice_t *vp)
+release_voice(struct snd_emux_voice *vp)
{
int dcysusv;
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = vp->hw;
dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
@@ -105,9 +108,9 @@ release_voice(snd_emux_voice_t *vp)
/*
*/
static void
-terminate_voice(snd_emux_voice_t *vp)
+terminate_voice(struct snd_emux_voice *vp)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = vp->hw;
EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
@@ -117,9 +120,9 @@ terminate_voice(snd_emux_voice_t *vp)
/*
*/
static void
-update_voice(snd_emux_voice_t *vp, int update)
+update_voice(struct snd_emux_voice *vp, int update)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = vp->hw;
if (update & SNDRV_EMUX_UPDATE_VOLUME)
@@ -149,12 +152,12 @@ update_voice(snd_emux_voice_t *vp, int update)
* The channel index (vp->ch) must be initialized in this routine.
* In Emu8k, it is identical with the array index.
*/
-static snd_emux_voice_t *
-get_voice(snd_emux_t *emu, snd_emux_port_t *port)
+static struct snd_emux_voice *
+get_voice(struct snd_emux *emu, struct snd_emux_port *port)
{
int i;
- snd_emux_voice_t *vp;
- emu8000_t *hw;
+ struct snd_emux_voice *vp;
+ struct snd_emu8000 *hw;
/* what we are looking for, in order of preference */
enum {
@@ -227,13 +230,13 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
/*
*/
static int
-start_voice(snd_emux_voice_t *vp)
+start_voice(struct snd_emux_voice *vp)
{
unsigned int temp;
int ch;
int addr;
- snd_midi_channel_t *chan;
- emu8000_t *hw;
+ struct snd_midi_channel *chan;
+ struct snd_emu8000 *hw;
hw = vp->hw;
ch = vp->ch;
@@ -307,11 +310,11 @@ start_voice(snd_emux_voice_t *vp)
* Start envelope
*/
static void
-trigger_voice(snd_emux_voice_t *vp)
+trigger_voice(struct snd_emux_voice *vp)
{
int ch = vp->ch;
unsigned int temp;
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = vp->hw;
@@ -329,9 +332,9 @@ trigger_voice(snd_emux_voice_t *vp)
* reset voice parameters
*/
static void
-reset_voice(snd_emux_t *emu, int ch)
+reset_voice(struct snd_emux *emu, int ch)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = emu->hw;
EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
@@ -342,7 +345,7 @@ reset_voice(snd_emux_t *emu, int ch)
* Set the pitch of a possibly playing note.
*/
static void
-set_pitch(emu8000_t *hw, snd_emux_voice_t *vp)
+set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
EMU8000_IP_WRITE(hw, vp->ch, vp->apitch);
}
@@ -351,7 +354,7 @@ set_pitch(emu8000_t *hw, snd_emux_voice_t *vp)
* Set the volume of a possibly already playing note
*/
static void
-set_volume(emu8000_t *hw, snd_emux_voice_t *vp)
+set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
int ifatn;
@@ -365,7 +368,7 @@ set_volume(emu8000_t *hw, snd_emux_voice_t *vp)
* Set pan and loop start address.
*/
static void
-set_pan(emu8000_t *hw, snd_emux_voice_t *vp)
+set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned int temp;
@@ -376,7 +379,7 @@ set_pan(emu8000_t *hw, snd_emux_voice_t *vp)
#define MOD_SENSE 18
static void
-set_fmmod(emu8000_t *hw, snd_emux_voice_t *vp)
+set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned short fmmod;
short pitch;
@@ -394,14 +397,14 @@ set_fmmod(emu8000_t *hw, snd_emux_voice_t *vp)
/* set tremolo (lfo1) volume & frequency */
static void
-set_tremfreq(emu8000_t *hw, snd_emux_voice_t *vp)
+set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq);
}
/* set lfo2 pitch & frequency */
static void
-set_fm2frq2(emu8000_t *hw, snd_emux_voice_t *vp)
+set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned short fm2frq2;
short pitch;
@@ -419,7 +422,7 @@ set_fm2frq2(emu8000_t *hw, snd_emux_voice_t *vp)
/* set filterQ */
static void
-set_filterQ(emu8000_t *hw, snd_emux_voice_t *vp)
+set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
{
unsigned int addr;
addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
@@ -431,7 +434,7 @@ set_filterQ(emu8000_t *hw, snd_emux_voice_t *vp)
* set the envelope & LFO parameters to the default values
*/
static void
-snd_emu8000_tweak_voice(emu8000_t *emu, int i)
+snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int i)
{
/* set all mod/vol envelope shape to minimum */
EMU8000_ENVVOL_WRITE(emu, i, 0x8000);
@@ -453,9 +456,9 @@ snd_emu8000_tweak_voice(emu8000_t *emu, int i)
* sysex callback
*/
static void
-sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *chset)
+sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = emu->hw;
@@ -478,9 +481,9 @@ sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *c
* OSS ioctl callback
*/
static int
-oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2)
+oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = emu->hw;
@@ -523,9 +526,9 @@ oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2)
*/
static int
-load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len)
+load_fx(struct snd_emux *emu, int type, int mode, const void __user *buf, long len)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
hw = emu->hw;
/* skip header */
diff --git a/sound/isa/sb/emu8000_local.h b/sound/isa/sb/emu8000_local.h
index ea4996a895fc..2ac77f10bb4e 100644
--- a/sound/isa/sb/emu8000_local.h
+++ b/sound/isa/sb/emu8000_local.h
@@ -30,14 +30,17 @@
#include <sound/emu8000_reg.h>
/* emu8000_patch.c */
-int snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
-int snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
-void snd_emu8000_sample_reset(snd_emux_t *rec);
+int snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *data, long count);
+int snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr);
+void snd_emu8000_sample_reset(struct snd_emux *rec);
/* emu8000_callback.c */
-void snd_emu8000_ops_setup(emu8000_t *emu);
+void snd_emu8000_ops_setup(struct snd_emu8000 *emu);
/* emu8000_pcm.c */
-int snd_emu8000_pcm_new(snd_card_t *card, emu8000_t *emu, int index);
+int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index);
#endif /* __EMU8000_LOCAL_H */
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index 2fea67e71c78..80b1cf84a1ae 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -32,7 +32,7 @@ MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes sl
* Open up channels.
*/
static int
-snd_emu8000_open_dma(emu8000_t *emu, int write)
+snd_emu8000_open_dma(struct snd_emu8000 *emu, int write)
{
int i;
@@ -59,7 +59,7 @@ snd_emu8000_open_dma(emu8000_t *emu, int write)
* Close all dram channels.
*/
static void
-snd_emu8000_close_dma(emu8000_t *emu)
+snd_emu8000_close_dma(struct snd_emu8000 *emu)
{
int i;
@@ -106,7 +106,7 @@ read_word(const void __user *buf, int offset, int mode)
/*
*/
static void
-snd_emu8000_write_wait(emu8000_t *emu)
+snd_emu8000_write_wait(struct snd_emu8000 *emu)
{
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
schedule_timeout_interruptible(1);
@@ -128,7 +128,7 @@ snd_emu8000_write_wait(emu8000_t *emu)
* working.
*/
static inline void
-write_word(emu8000_t *emu, int *offset, unsigned short data)
+write_word(struct snd_emu8000 *emu, int *offset, unsigned short data)
{
if (emu8000_reset_addr) {
if (emu8000_reset_addr > 1)
@@ -144,15 +144,16 @@ write_word(emu8000_t *emu, int *offset, unsigned short data)
* the generic soundfont routines as a callback.
*/
int
-snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
- snd_util_memhdr_t *hdr, const void __user *data, long count)
+snd_emu8000_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *data, long count)
{
int i;
int rc;
int offset;
int truesize;
int dram_offset, dram_start;
- emu8000_t *emu;
+ struct snd_emu8000 *emu;
emu = rec->hw;
snd_assert(sp != NULL, return -EINVAL);
@@ -282,7 +283,8 @@ snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
* free a sample block
*/
int
-snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr)
+snd_emu8000_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr)
{
if (sp->block) {
snd_util_mem_free(hdr, sp->block);
@@ -296,7 +298,7 @@ snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t
* sample_reset callback - terminate voices
*/
void
-snd_emu8000_sample_reset(snd_emux_t *rec)
+snd_emu8000_sample_reset(struct snd_emux *rec)
{
snd_emux_terminate_all(rec);
}
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index b323beeeda15..91dc3d83e2cf 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -46,14 +46,12 @@
*/
-typedef struct snd_emu8k_pcm emu8k_pcm_t;
-
struct snd_emu8k_pcm {
- emu8000_t *emu;
- snd_pcm_substream_t *substream;
+ struct snd_emu8000 *emu;
+ struct snd_pcm_substream *substream;
unsigned int allocated_bytes;
- snd_util_memblk_t *block;
+ struct snd_util_memblk *block;
unsigned int offset;
unsigned int buf_size;
unsigned int period_size;
@@ -77,7 +75,7 @@ struct snd_emu8k_pcm {
* open up channels for the simultaneous data transfer and playback
*/
static int
-emu8k_open_dram_for_pcm(emu8000_t *emu, int channels)
+emu8k_open_dram_for_pcm(struct snd_emu8000 *emu, int channels)
{
int i;
@@ -113,7 +111,7 @@ emu8k_open_dram_for_pcm(emu8000_t *emu, int channels)
/*
*/
static void
-snd_emu8000_write_wait(emu8000_t *emu, int can_schedule)
+snd_emu8000_write_wait(struct snd_emu8000 *emu, int can_schedule)
{
while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
if (can_schedule) {
@@ -128,7 +126,7 @@ snd_emu8000_write_wait(emu8000_t *emu, int can_schedule)
* close all channels
*/
static void
-emu8k_close_dram(emu8000_t *emu)
+emu8k_close_dram(struct snd_emu8000 *emu)
{
int i;
@@ -156,7 +154,7 @@ static int calc_rate_offset(int hz)
/*
*/
-static snd_pcm_hardware_t emu8k_pcm_hw = {
+static struct snd_pcm_hardware emu8k_pcm_hw = {
#ifdef USE_NONINTERLEAVE
.info = SNDRV_PCM_INFO_NONINTERLEAVED,
#else
@@ -180,7 +178,7 @@ static snd_pcm_hardware_t emu8k_pcm_hw = {
/*
* get the current position at the given channel from CCCA register
*/
-static inline int emu8k_get_curpos(emu8k_pcm_t *rec, int ch)
+static inline int emu8k_get_curpos(struct snd_emu8k_pcm *rec, int ch)
{
int val = EMU8000_CCCA_READ(rec->emu, ch) & 0xfffffff;
val -= rec->loop_start[ch] - 1;
@@ -194,7 +192,7 @@ static inline int emu8k_get_curpos(emu8k_pcm_t *rec, int ch)
*/
static void emu8k_pcm_timer_func(unsigned long data)
{
- emu8k_pcm_t *rec = (emu8k_pcm_t *)data;
+ struct snd_emu8k_pcm *rec = (struct snd_emu8k_pcm *)data;
int ptr, delta;
spin_lock(&rec->timer_lock);
@@ -226,11 +224,11 @@ static void emu8k_pcm_timer_func(unsigned long data)
* open pcm
* creating an instance here
*/
-static int emu8k_pcm_open(snd_pcm_substream_t *subs)
+static int emu8k_pcm_open(struct snd_pcm_substream *subs)
{
- emu8000_t *emu = snd_pcm_substream_chip(subs);
- emu8k_pcm_t *rec;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_emu8000 *emu = snd_pcm_substream_chip(subs);
+ struct snd_emu8k_pcm *rec;
+ struct snd_pcm_runtime *runtime = subs->runtime;
rec = kzalloc(sizeof(*rec), GFP_KERNEL);
if (! rec)
@@ -256,9 +254,9 @@ static int emu8k_pcm_open(snd_pcm_substream_t *subs)
return 0;
}
-static int emu8k_pcm_close(snd_pcm_substream_t *subs)
+static int emu8k_pcm_close(struct snd_pcm_substream *subs)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
kfree(rec);
subs->runtime->private_data = NULL;
return 0;
@@ -281,9 +279,9 @@ static int calc_pitch_target(int pitch)
/*
* set up the voice
*/
-static void setup_voice(emu8k_pcm_t *rec, int ch)
+static void setup_voice(struct snd_emu8k_pcm *rec, int ch)
{
- emu8000_t *hw = rec->emu;
+ struct snd_emu8000 *hw = rec->emu;
unsigned int temp;
/* channel to be silent and idle */
@@ -334,10 +332,10 @@ static void setup_voice(emu8k_pcm_t *rec, int ch)
/*
* trigger the voice
*/
-static void start_voice(emu8k_pcm_t *rec, int ch)
+static void start_voice(struct snd_emu8k_pcm *rec, int ch)
{
unsigned long flags;
- emu8000_t *hw = rec->emu;
+ struct snd_emu8000 *hw = rec->emu;
unsigned int temp, aux;
int pt = calc_pitch_target(rec->pitch);
@@ -370,10 +368,10 @@ static void start_voice(emu8k_pcm_t *rec, int ch)
/*
* stop the voice immediately
*/
-static void stop_voice(emu8k_pcm_t *rec, int ch)
+static void stop_voice(struct snd_emu8k_pcm *rec, int ch)
{
unsigned long flags;
- emu8000_t *hw = rec->emu;
+ struct snd_emu8000 *hw = rec->emu;
EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
@@ -386,9 +384,9 @@ static void stop_voice(emu8k_pcm_t *rec, int ch)
spin_unlock_irqrestore(&rec->timer_lock, flags);
}
-static int emu8k_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
+static int emu8k_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
int ch;
switch (cmd) {
@@ -428,7 +426,7 @@ do { \
#ifdef USE_NONINTERLEAVE
/* copy one channel block */
-static int emu8k_transfer_block(emu8000_t *emu, int offset, unsigned short *buf, int count)
+static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count)
{
EMU8000_SMALW_WRITE(emu, offset);
while (count > 0) {
@@ -442,14 +440,14 @@ static int emu8k_transfer_block(emu8000_t *emu, int offset, unsigned short *buf,
return 0;
}
-static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
+static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int voice,
snd_pcm_uframes_t pos,
void *src,
snd_pcm_uframes_t count)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
- emu8000_t *emu = rec->emu;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+ struct snd_emu8000 *emu = rec->emu;
snd_emu8000_write_wait(emu, 1);
if (voice == -1) {
@@ -469,7 +467,7 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
}
/* make a channel block silence */
-static int emu8k_silence_block(emu8000_t *emu, int offset, int count)
+static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
{
EMU8000_SMALW_WRITE(emu, offset);
while (count > 0) {
@@ -480,13 +478,13 @@ static int emu8k_silence_block(emu8000_t *emu, int offset, int count)
return 0;
}
-static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
+static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
int voice,
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
- emu8000_t *emu = rec->emu;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+ struct snd_emu8000 *emu = rec->emu;
snd_emu8000_write_wait(emu, 1);
if (voice == -1 && rec->voices == 1)
@@ -508,14 +506,14 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
* copy the interleaved data can be done easily by using
* DMA "left" and "right" channels on emu8k engine.
*/
-static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
+static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int voice,
snd_pcm_uframes_t pos,
void __user *src,
snd_pcm_uframes_t count)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
- emu8000_t *emu = rec->emu;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+ struct snd_emu8000 *emu = rec->emu;
unsigned short __user *buf = src;
snd_emu8000_write_wait(emu, 1);
@@ -539,13 +537,13 @@ static int emu8k_pcm_copy(snd_pcm_substream_t *subs,
return 0;
}
-static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
+static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
int voice,
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
- emu8000_t *emu = rec->emu;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+ struct snd_emu8000 *emu = rec->emu;
snd_emu8000_write_wait(emu, 1);
EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
@@ -567,10 +565,10 @@ static int emu8k_pcm_silence(snd_pcm_substream_t *subs,
/*
* allocate a memory block
*/
-static int emu8k_pcm_hw_params(snd_pcm_substream_t *subs,
- snd_pcm_hw_params_t *hw_params)
+static int emu8k_pcm_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw_params)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
if (rec->block) {
/* reallocation - release the old block */
@@ -592,9 +590,9 @@ static int emu8k_pcm_hw_params(snd_pcm_substream_t *subs,
/*
* free the memory block
*/
-static int emu8k_pcm_hw_free(snd_pcm_substream_t *subs)
+static int emu8k_pcm_hw_free(struct snd_pcm_substream *subs)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
if (rec->block) {
int ch;
@@ -610,9 +608,9 @@ static int emu8k_pcm_hw_free(snd_pcm_substream_t *subs)
/*
*/
-static int emu8k_pcm_prepare(snd_pcm_substream_t *subs)
+static int emu8k_pcm_prepare(struct snd_pcm_substream *subs)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
rec->pitch = 0xe000 + calc_rate_offset(subs->runtime->rate);
rec->last_ptr = 0;
@@ -656,16 +654,16 @@ static int emu8k_pcm_prepare(snd_pcm_substream_t *subs)
return 0;
}
-static snd_pcm_uframes_t emu8k_pcm_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs)
{
- emu8k_pcm_t *rec = subs->runtime->private_data;
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
if (rec->running)
return emu8k_get_curpos(rec, 0);
return 0;
}
-static snd_pcm_ops_t emu8k_pcm_ops = {
+static struct snd_pcm_ops emu8k_pcm_ops = {
.open = emu8k_pcm_open,
.close = emu8k_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -679,15 +677,15 @@ static snd_pcm_ops_t emu8k_pcm_ops = {
};
-static void snd_emu8000_pcm_free(snd_pcm_t *pcm)
+static void snd_emu8000_pcm_free(struct snd_pcm *pcm)
{
- emu8000_t *emu = pcm->private_data;
+ struct snd_emu8000 *emu = pcm->private_data;
emu->pcm = NULL;
}
-int snd_emu8000_pcm_new(snd_card_t *card, emu8000_t *emu, int index)
+int snd_emu8000_pcm_new(struct snd_card *card, struct snd_emu8000 *emu, int index)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(card, "Emu8000 PCM", index, 1, 0, &pcm)) < 0)
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index f68e217416a6..3d72742b342f 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -33,12 +33,12 @@ MODULE_LICENSE("GPL");
/*
* create a new hardware dependent device for Emu8000
*/
-static int snd_emu8000_new_device(snd_seq_device_t *dev)
+static int snd_emu8000_new_device(struct snd_seq_device *dev)
{
- emu8000_t *hw;
- snd_emux_t *emu;
+ struct snd_emu8000 *hw;
+ struct snd_emux *emu;
- hw = *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ hw = *(struct snd_emu8000**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (hw == NULL)
return -EINVAL;
@@ -92,9 +92,9 @@ static int snd_emu8000_new_device(snd_seq_device_t *dev)
/*
* free all resources
*/
-static int snd_emu8000_delete_device(snd_seq_device_t *dev)
+static int snd_emu8000_delete_device(struct snd_seq_device *dev)
{
- emu8000_t *hw;
+ struct snd_emu8000 *hw;
if (dev->driver_data == NULL)
return 0; /* no synth was allocated actually */
@@ -118,11 +118,12 @@ static int snd_emu8000_delete_device(snd_seq_device_t *dev)
static int __init alsa_emu8000_init(void)
{
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_emu8000_new_device,
snd_emu8000_delete_device,
};
- return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops, sizeof(emu8000_t*));
+ return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU8000, &ops,
+ sizeof(struct snd_emu8000*));
}
static void __exit alsa_emu8000_exit(void)
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index c859917c14db..9da80bfa3027 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -58,6 +58,7 @@ MODULE_PARM_DESC(dma8, "8-bit DMA # for es968 driver.");
struct snd_card_es968 {
struct pnp_dev *dev;
+ struct snd_sb *chip;
};
static struct pnp_card_device_id snd_es968_pnpids[] = {
@@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- sb_t *chip = dev_id;
+ struct snd_sb *chip = dev_id;
if (chip->open & SB_OPEN_PCM) {
return snd_sb8dsp_interrupt(chip);
@@ -128,14 +129,14 @@ static int __init snd_card_es968_probe(int dev,
const struct pnp_card_device_id *pid)
{
int error;
- sb_t *chip;
- snd_card_t *card;
+ struct snd_sb *chip;
+ struct snd_card *card;
struct snd_card_es968 *acard;
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_es968))) == NULL)
return -ENOMEM;
- acard = (struct snd_card_es968 *)card->private_data;
+ acard = card->private_data;
if ((error = snd_card_es968_pnp(dev, acard, pcard, pid))) {
snd_card_free(card);
return error;
@@ -151,6 +152,7 @@ static int __init snd_card_es968_probe(int dev,
snd_card_free(card);
return error;
}
+ acard->chip = chip;
if ((error = snd_sb8dsp_pcm(chip, 0, NULL)) < 0) {
snd_card_free(card);
@@ -200,30 +202,59 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card,
static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_es968_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_es968 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
}
+static int snd_es968_pnp_resume(struct pnp_card_link *pcard)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_es968 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pnp_card_driver es968_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "es968",
.id_table = snd_es968_pnpids,
.probe = snd_es968_pnp_detect,
.remove = __devexit_p(snd_es968_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_es968_pnp_suspend,
+ .resume = snd_es968_pnp_resume,
+#endif
};
static int __init alsa_card_es968_init(void)
{
int cards = pnp_register_card_driver(&es968_pnpc_driver);
-#ifdef MODULE
- if (cards == 0) {
+ if (cards <= 0) {
pnp_unregister_card_driver(&es968_pnpc_driver);
+#ifdef MODULE
snd_printk(KERN_ERR "no ES968 based soundcards found\n");
- }
#endif
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_es968_exit(void)
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index c2fa451bc8f0..c0be7a5a3425 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -24,6 +24,8 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pnp.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/sb.h>
@@ -32,7 +34,6 @@
#include <sound/opl3.h>
#include <sound/emu8000.h>
#include <sound/seq_device.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#define SNDRV_LEGACY_FIND_FREE_IRQ
#define SNDRV_LEGACY_FIND_FREE_DMA
#include <sound/initval.h>
@@ -127,8 +128,14 @@ module_param_array(seq_ports, int, NULL, 0444);
MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
#endif
+static struct platform_device *platform_devices[SNDRV_CARDS];
+#ifdef CONFIG_PNP
+static int pnp_registered;
+#endif
+
struct snd_card_sb16 {
struct resource *fm_res; /* used to block FM i/o region for legacy cards */
+ struct snd_sb *chip;
#ifdef CONFIG_PNP
int dev_no;
struct pnp_dev *dev;
@@ -138,8 +145,6 @@ struct snd_card_sb16 {
#endif
};
-static snd_card_t *snd_sb16_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
#ifdef CONFIG_PNP
static struct pnp_card_device_id snd_sb16_pnpids[] = {
@@ -339,9 +344,9 @@ __wt_error:
#endif /* CONFIG_PNP */
-static void snd_sb16_free(snd_card_t *card)
+static void snd_sb16_free(struct snd_card *card)
{
- struct snd_card_sb16 *acard = (struct snd_card_sb16 *)card->private_data;
+ struct snd_card_sb16 *acard = card->private_data;
if (acard == NULL)
return;
@@ -354,73 +359,32 @@ static void snd_sb16_free(snd_card_t *card)
#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)
+static struct snd_card *snd_sb16_card_new(int dev)
+{
+ struct snd_card *card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct snd_card_sb16));
+ if (card == NULL)
+ return NULL;
+ card->private_free = snd_sb16_free;
+ return card;
+}
+
+static int __init snd_sb16_probe(struct snd_card *card, int dev)
{
- static int possible_irqs[] = {5, 9, 10, 7, -1};
- static int possible_dmas8[] = {1, 3, 0, -1};
- static int possible_dmas16[] = {5, 6, 7, -1};
int xirq, xdma8, xdma16;
- sb_t *chip;
- snd_card_t *card;
- struct snd_card_sb16 *acard;
- opl3_t *opl3;
- snd_hwdep_t *synth = NULL;
+ struct snd_sb *chip;
+ struct snd_card_sb16 *acard = card->private_data;
+ struct snd_opl3 *opl3;
+ struct snd_hwdep *synth = NULL;
#ifdef CONFIG_SND_SB16_CSP
- snd_hwdep_t *xcsp = NULL;
+ struct snd_hwdep *xcsp = NULL;
#endif
unsigned long flags;
int err;
- card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(struct snd_card_sb16));
- if (card == NULL)
- return -ENOMEM;
- acard = (struct snd_card_sb16 *) card->private_data;
- card->private_free = snd_sb16_free;
-#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if ((err = snd_card_sb16_pnp(dev, acard, pcard, pid)))
- goto _err;
- snd_card_set_dev(card, &pcard->card->dev);
- }
-#endif
-
xirq = irq[dev];
xdma8 = dma8[dev];
xdma16 = dma16[dev];
- 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_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_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");
-#ifdef SNDRV_SBAWE_EMU8000
- /* non-PnP AWE port address is hardwired with base port address */
- awe_port[dev] = port[dev] + 0x400;
-#endif
- }
if ((err = snd_sbdsp_create(card,
port[dev],
@@ -430,19 +394,19 @@ static int __init snd_sb16_probe(int dev,
xdma16,
SB_HW_AUTO,
&chip)) < 0)
- goto _err;
+ return err;
+ acard->chip = chip;
if (chip->hardware != SB_HW_16) {
snd_printk(KERN_ERR PFX "SB 16 chip was not detected at 0x%lx\n", port[dev]);
- err = -ENODEV;
- goto _err;
+ return -ENODEV;
}
chip->mpu_port = mpu_port[dev];
if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
- goto _err;
+ return err;
- if ((err = snd_sb16dsp_pcm(chip, 0, NULL)) < 0)
- goto _err;
+ if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0)
+ return err;
strcpy(card->driver,
#ifdef SNDRV_SBAWE_EMU8000
@@ -464,7 +428,7 @@ static int __init snd_sb16_probe(int dev,
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
chip->mpu_port, 0,
xirq, 0, &chip->rmidi)) < 0)
- goto _err;
+ return err;
chip->rmidi_callback = snd_mpu401_uart_interrupt;
}
@@ -487,12 +451,12 @@ static int __init snd_sb16_probe(int dev,
int seqdev = 1;
#endif
if ((err = snd_opl3_hwdep_new(opl3, 0, seqdev, &synth)) < 0)
- goto _err;
+ return err;
}
}
if ((err = snd_sbmixer_new(chip)) < 0)
- goto _err;
+ return err;
#ifdef CONFIG_SND_SB16_CSP
/* CSP chip on SB16ASP/AWE32 */
@@ -512,7 +476,7 @@ static int __init snd_sb16_probe(int 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]);
- goto _err;
+ return err;
}
}
#endif
@@ -524,56 +488,168 @@ static int __init snd_sb16_probe(int dev,
(mic_agc[dev] ? 0x00 : 0x01));
spin_unlock_irqrestore(&chip->mixer_lock, flags);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
-
if ((err = snd_card_register(card)) < 0)
- goto _err;
+ return err;
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_sb16_legacy[dev] = card;
return 0;
+}
- _err:
- snd_card_free(card);
- return err;
+#ifdef CONFIG_PM
+static int snd_sb16_suspend(struct snd_card *card, pm_message_t state)
+{
+ struct snd_card_sb16 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
}
-static int __init snd_sb16_probe_legacy_port(unsigned long xport)
+static int snd_sb16_resume(struct snd_card *card)
{
- static int dev;
- int res;
+ struct snd_card_sb16 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- if (is_isapnp_selected(dev))
- continue;
- port[dev] = xport;
- res = snd_sb16_probe(dev, NULL, NULL);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
+{
+ struct snd_card_sb16 *acard;
+ struct snd_card *card;
+ int err;
+
+ card = snd_sb16_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+
+ acard = card->private_data;
+ /* 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;
+#endif
+
+ snd_card_set_dev(card, &devptr->dev);
+ if ((err = snd_sb16_probe(card, dev)) < 0) {
+ snd_card_free(card);
+ return err;
}
- return -ENODEV;
+ platform_set_drvdata(devptr, card);
+ return 0;
}
+
+static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev)
+{
+ int dev = pdev->id;
+ int err;
+ static int possible_irqs[] = {5, 9, 10, 7, -1};
+ static int possible_dmas8[] = {1, 3, 0, -1};
+ static int possible_dmas16[] = {5, 6, 7, -1};
+
+ if (irq[dev] == SNDRV_AUTO_IRQ) {
+ if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
+ return -EBUSY;
+ }
+ }
+ if (dma8[dev] == SNDRV_AUTO_DMA) {
+ if ((dma8[dev] = snd_legacy_find_free_dma(possible_dmas8)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 8-bit DMA\n");
+ return -EBUSY;
+ }
+ }
+ if (dma16[dev] == SNDRV_AUTO_DMA) {
+ if ((dma16[dev] = snd_legacy_find_free_dma(possible_dmas16)) < 0) {
+ snd_printk(KERN_ERR PFX "unable to find a free 16-bit DMA\n");
+ return -EBUSY;
+ }
+ }
+
+ if (port[dev] != SNDRV_AUTO_PORT)
+ return snd_sb16_nonpnp_probe1(dev, pdev);
+ else {
+ static int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ port[dev] = possible_ports[i];
+ err = snd_sb16_nonpnp_probe1(dev, pdev);
+ if (! err)
+ return 0;
+ }
+ return err;
+ }
+}
+
+static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return snd_sb16_suspend(platform_get_drvdata(dev), state);
+}
+
+static int snd_sb16_nonpnp_resume(struct platform_device *dev)
+{
+ return snd_sb16_resume(platform_get_drvdata(dev));
+}
+#endif
+
+#ifdef SNDRV_SBAWE
+#define SND_SB16_DRIVER "snd_sbawe"
+#else
+#define SND_SB16_DRIVER "snd_sb16"
+#endif
+
+static struct platform_driver snd_sb16_nonpnp_driver = {
+ .probe = snd_sb16_nonpnp_probe,
+ .remove = __devexit_p(snd_sb16_nonpnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_sb16_nonpnp_suspend,
+ .resume = snd_sb16_nonpnp_resume,
+#endif
+ .driver = {
+ .name = SND_SB16_DRIVER
+ },
+};
+
+
#ifdef CONFIG_PNP
-static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
static int dev;
+ struct snd_card *card;
int res;
for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev] || !isapnp[dev])
continue;
- res = snd_sb16_probe(dev, card, id);
- if (res < 0)
+ card = snd_sb16_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &pcard->card->dev);
+ if ((res = snd_card_sb16_pnp(dev, card->private_data, pcard, pid)) < 0 ||
+ (res = snd_sb16_probe(card, dev)) < 0) {
+ snd_card_free(card);
return res;
+ }
+ pnp_set_card_drvdata(pcard, card);
dev++;
return 0;
}
@@ -583,57 +659,82 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *card,
static void __devexit snd_sb16_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+#ifdef CONFIG_PM
+static int snd_sb16_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ return snd_sb16_suspend(pnp_get_card_drvdata(pcard), state);
}
+static int snd_sb16_pnp_resume(struct pnp_card_link *pcard)
+{
+ return snd_sb16_resume(pnp_get_card_drvdata(pcard));
+}
+#endif
static struct pnp_card_driver sb16_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
+#ifdef SNDRV_SBAWE
+ .name = "sbawe",
+#else
.name = "sb16",
+#endif
.id_table = snd_sb16_pnpids,
.probe = snd_sb16_pnp_detect,
.remove = __devexit_p(snd_sb16_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_sb16_pnp_suspend,
+ .resume = snd_sb16_pnp_resume,
+#endif
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_sb16_unregister_all(void)
+{
+ int i;
+
+#ifdef CONFIG_PNP
+ if (pnp_registered)
+ pnp_unregister_card_driver(&sb16_pnpc_driver);
+#endif
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_sb16_nonpnp_driver);
+}
+
static int __init alsa_card_sb16_init(void)
{
- int dev, cards = 0, i;
- static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
+ int i, err, cards = 0;
- /* legacy non-auto cards at first */
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (is_isapnp_selected(dev))
- continue;
- if (!snd_sb16_probe(dev, NULL, NULL)) {
- cards++;
+ if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ if (is_isapnp_selected(i))
continue;
+ device = platform_device_register_simple(SND_SB16_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
}
-#ifdef MODULE
- snd_printk(KERN_ERR "Sound Blaster 16+ soundcard #%i not found at 0x%lx or device busy\n", dev, port[dev]);
-#endif
+ platform_devices[i] = device;
+ cards++;
}
- /* legacy auto configured cards */
- i = snd_legacy_auto_probe(possible_ports, snd_sb16_probe_legacy_port);
- if (i > 0)
- cards += i;
-
#ifdef CONFIG_PNP
/* PnP cards at last */
i = pnp_register_card_driver(&sb16_pnpc_driver);
- if (i >0)
+ if (i >= 0) {
+ pnp_registered = 1;
cards += i;
+ }
#endif
if (!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sb16_pnpc_driver);
-#endif
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
#ifdef SNDRV_SBAWE_EMU8000
@@ -642,21 +743,19 @@ static int __init alsa_card_sb16_init(void)
snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
#endif
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_sb16_unregister_all();
+ return err;
}
static void __exit alsa_card_sb16_exit(void)
{
- int dev;
-
-#ifdef CONFIG_PNP
- /* PnP cards first */
- pnp_unregister_card_driver(&sb16_pnpc_driver);
-#endif
- for (dev = 0; dev < SNDRV_CARDS; dev++)
- snd_card_free(snd_sb16_legacy[dev]);
+ snd_sb16_unregister_all();
}
module_init(alsa_card_sb16_init)
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 7192d4c758e6..9c2b5efbacbf 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -72,46 +72,47 @@ struct desc_header {
/*
* prototypes
*/
-static void snd_sb_csp_free(snd_hwdep_t *hw);
-static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file);
-static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg);
-static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file);
-
-static int csp_detect(sb_t *chip, int *version);
-static int set_codec_parameter(sb_t *chip, unsigned char par, unsigned char val);
-static int set_register(sb_t *chip, unsigned char reg, unsigned char val);
-static int read_register(sb_t *chip, unsigned char reg);
-static int set_mode_register(sb_t *chip, unsigned char mode);
-static int get_version(sb_t *chip);
-
-static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user * code);
-static int snd_sb_csp_unload(snd_sb_csp_t * p);
-static int snd_sb_csp_load_user(snd_sb_csp_t * p, const unsigned char __user *buf, int size, int load_flags);
-static int snd_sb_csp_autoload(snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode);
-static int snd_sb_csp_check_version(snd_sb_csp_t * p);
-
-static int snd_sb_csp_use(snd_sb_csp_t * p);
-static int snd_sb_csp_unuse(snd_sb_csp_t * p);
-static int snd_sb_csp_start(snd_sb_csp_t * p, int sample_width, int channels);
-static int snd_sb_csp_stop(snd_sb_csp_t * p);
-static int snd_sb_csp_pause(snd_sb_csp_t * p);
-static int snd_sb_csp_restart(snd_sb_csp_t * p);
-
-static int snd_sb_qsound_build(snd_sb_csp_t * p);
-static void snd_sb_qsound_destroy(snd_sb_csp_t * p);
-static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p);
-
-static int init_proc_entry(snd_sb_csp_t * p, int device);
-static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer);
+static void snd_sb_csp_free(struct snd_hwdep *hw);
+static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file);
+static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg);
+static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file);
+
+static int csp_detect(struct snd_sb *chip, int *version);
+static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val);
+static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val);
+static int read_register(struct snd_sb *chip, unsigned char reg);
+static int set_mode_register(struct snd_sb *chip, unsigned char mode);
+static int get_version(struct snd_sb *chip);
+
+static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ struct snd_sb_csp_microcode __user * code);
+static int snd_sb_csp_unload(struct snd_sb_csp * p);
+static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags);
+static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode);
+static int snd_sb_csp_check_version(struct snd_sb_csp * p);
+
+static int snd_sb_csp_use(struct snd_sb_csp * p);
+static int snd_sb_csp_unuse(struct snd_sb_csp * p);
+static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels);
+static int snd_sb_csp_stop(struct snd_sb_csp * p);
+static int snd_sb_csp_pause(struct snd_sb_csp * p);
+static int snd_sb_csp_restart(struct snd_sb_csp * p);
+
+static int snd_sb_qsound_build(struct snd_sb_csp * p);
+static void snd_sb_qsound_destroy(struct snd_sb_csp * p);
+static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p);
+
+static int init_proc_entry(struct snd_sb_csp * p, int device);
+static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer);
/*
* Detect CSP chip and create a new instance
*/
-int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
+int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
{
- snd_sb_csp_t *p;
+ struct snd_sb_csp *p;
int version, err;
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
if (rhwdep)
*rhwdep = NULL;
@@ -158,9 +159,9 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
/*
* free_private for hwdep instance
*/
-static void snd_sb_csp_free(snd_hwdep_t *hwdep)
+static void snd_sb_csp_free(struct snd_hwdep *hwdep)
{
- snd_sb_csp_t *p = hwdep->private_data;
+ struct snd_sb_csp *p = hwdep->private_data;
if (p) {
if (p->running & SNDRV_SB_CSP_ST_RUNNING)
snd_sb_csp_stop(p);
@@ -173,20 +174,20 @@ static void snd_sb_csp_free(snd_hwdep_t *hwdep)
/*
* open the device exclusively
*/
-static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
+static int snd_sb_csp_open(struct snd_hwdep * hw, struct file *file)
{
- snd_sb_csp_t *p = hw->private_data;
+ struct snd_sb_csp *p = hw->private_data;
return (snd_sb_csp_use(p));
}
/*
* ioctl for hwdep device:
*/
-static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
+static int snd_sb_csp_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
{
- snd_sb_csp_t *p = hw->private_data;
- snd_sb_csp_info_t info;
- snd_sb_csp_start_t start_info;
+ struct snd_sb_csp *p = hw->private_data;
+ struct snd_sb_csp_info info;
+ struct snd_sb_csp_start start_info;
int err;
snd_assert(p != NULL, return -EINVAL);
@@ -217,7 +218,7 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
/* load CSP microcode */
case SNDRV_SB_CSP_IOCTL_LOAD_CODE:
err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
- -EBUSY : snd_sb_csp_riff_load(p, (snd_sb_csp_microcode_t __user *) arg));
+ -EBUSY : snd_sb_csp_riff_load(p, (struct snd_sb_csp_microcode __user *) arg));
break;
case SNDRV_SB_CSP_IOCTL_UNLOAD_CODE:
err = (p->running & SNDRV_SB_CSP_ST_RUNNING ?
@@ -251,9 +252,9 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
/*
* close the device
*/
-static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
+static int snd_sb_csp_release(struct snd_hwdep * hw, struct file *file)
{
- snd_sb_csp_t *p = hw->private_data;
+ struct snd_sb_csp *p = hw->private_data;
return (snd_sb_csp_unuse(p));
}
@@ -262,7 +263,7 @@ static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
/*
* acquire device
*/
-static int snd_sb_csp_use(snd_sb_csp_t * p)
+static int snd_sb_csp_use(struct snd_sb_csp * p)
{
down(&p->access_mutex);
if (p->used) {
@@ -279,7 +280,7 @@ static int snd_sb_csp_use(snd_sb_csp_t * p)
/*
* release device
*/
-static int snd_sb_csp_unuse(snd_sb_csp_t * p)
+static int snd_sb_csp_unuse(struct snd_sb_csp * p)
{
down(&p->access_mutex);
p->used--;
@@ -292,9 +293,10 @@ static int snd_sb_csp_unuse(snd_sb_csp_t * p)
* load microcode via ioctl:
* code is user-space pointer
*/
-static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user * mcode)
+static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
+ struct snd_sb_csp_microcode __user * mcode)
{
- snd_sb_csp_mc_header_t info;
+ struct snd_sb_csp_mc_header info;
unsigned char __user *data_ptr;
unsigned char __user *data_end;
@@ -449,7 +451,7 @@ static int snd_sb_csp_riff_load(snd_sb_csp_t * p, snd_sb_csp_microcode_t __user
/*
* unload CSP microcode
*/
-static int snd_sb_csp_unload(snd_sb_csp_t * p)
+static int snd_sb_csp_unload(struct snd_sb_csp * p)
{
if (p->running & SNDRV_SB_CSP_ST_RUNNING)
return -EBUSY;
@@ -472,7 +474,7 @@ static int snd_sb_csp_unload(snd_sb_csp_t * p)
/*
* send command sequence to DSP
*/
-static inline int command_seq(sb_t *chip, const unsigned char *seq, int size)
+static inline int command_seq(struct snd_sb *chip, const unsigned char *seq, int size)
{
int i;
for (i = 0; i < size; i++) {
@@ -485,7 +487,7 @@ static inline int command_seq(sb_t *chip, const unsigned char *seq, int size)
/*
* set CSP codec parameter
*/
-static int set_codec_parameter(sb_t *chip, unsigned char par, unsigned char val)
+static int set_codec_parameter(struct snd_sb *chip, unsigned char par, unsigned char val)
{
unsigned char dsp_cmd[3];
@@ -502,7 +504,7 @@ static int set_codec_parameter(sb_t *chip, unsigned char par, unsigned char val)
/*
* set CSP register
*/
-static int set_register(sb_t *chip, unsigned char reg, unsigned char val)
+static int set_register(struct snd_sb *chip, unsigned char reg, unsigned char val)
{
unsigned char dsp_cmd[3];
@@ -516,7 +518,7 @@ static int set_register(sb_t *chip, unsigned char reg, unsigned char val)
* read CSP register
* return < 0 -> error
*/
-static int read_register(sb_t *chip, unsigned char reg)
+static int read_register(struct snd_sb *chip, unsigned char reg)
{
unsigned char dsp_cmd[2];
@@ -529,7 +531,7 @@ static int read_register(sb_t *chip, unsigned char reg)
/*
* set CSP mode register
*/
-static int set_mode_register(sb_t *chip, unsigned char mode)
+static int set_mode_register(struct snd_sb *chip, unsigned char mode)
{
unsigned char dsp_cmd[2];
@@ -542,7 +544,7 @@ static int set_mode_register(sb_t *chip, unsigned char mode)
* Detect CSP
* return 0 if CSP exists.
*/
-static int csp_detect(sb_t *chip, int *version)
+static int csp_detect(struct snd_sb *chip, int *version)
{
unsigned char csp_test1, csp_test2;
unsigned long flags;
@@ -579,7 +581,7 @@ static int csp_detect(sb_t *chip, int *version)
/*
* get CSP version number
*/
-static int get_version(sb_t *chip)
+static int get_version(struct snd_sb *chip)
{
unsigned char dsp_cmd[2];
@@ -593,7 +595,7 @@ static int get_version(sb_t *chip)
/*
* check if the CSP version is valid
*/
-static int snd_sb_csp_check_version(snd_sb_csp_t * p)
+static int snd_sb_csp_check_version(struct snd_sb_csp * p)
{
if (p->version < 0x10 || p->version > 0x1f) {
snd_printd("%s: Invalid CSP version: 0x%x\n", __FUNCTION__, p->version);
@@ -605,7 +607,7 @@ static int snd_sb_csp_check_version(snd_sb_csp_t * p)
/*
* download microcode to CSP (microcode should have one "main" block).
*/
-static int snd_sb_csp_load(snd_sb_csp_t * p, const unsigned char *buf, int size, int load_flags)
+static int snd_sb_csp_load(struct snd_sb_csp * p, const unsigned char *buf, int size, int load_flags)
{
int status, i;
int err;
@@ -671,7 +673,7 @@ static int snd_sb_csp_load(snd_sb_csp_t * p, const unsigned char *buf, int size,
return result;
}
-static int snd_sb_csp_load_user(snd_sb_csp_t * p, const unsigned char __user *buf, int size, int load_flags)
+static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __user *buf, int size, int load_flags)
{
int err = -ENOMEM;
unsigned char *kbuf = kmalloc(size, GFP_KERNEL);
@@ -691,7 +693,7 @@ static int snd_sb_csp_load_user(snd_sb_csp_t * p, const unsigned char __user *bu
* autoload hardware codec if necessary
* return 0 if CSP is loaded and ready to run (p->running != 0)
*/
-static int snd_sb_csp_autoload(snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode)
+static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec_mode)
{
unsigned long flags;
int err = 0;
@@ -763,7 +765,7 @@ static int snd_sb_csp_autoload(snd_sb_csp_t * p, int pcm_sfmt, int play_rec_mode
/*
* start CSP
*/
-static int snd_sb_csp_start(snd_sb_csp_t * p, int sample_width, int channels)
+static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channels)
{
unsigned char s_type; /* sample type */
unsigned char mixL, mixR;
@@ -842,7 +844,7 @@ static int snd_sb_csp_start(snd_sb_csp_t * p, int sample_width, int channels)
/*
* stop CSP
*/
-static int snd_sb_csp_stop(snd_sb_csp_t * p)
+static int snd_sb_csp_stop(struct snd_sb_csp * p)
{
int result;
unsigned char mixL, mixR;
@@ -883,7 +885,7 @@ static int snd_sb_csp_stop(snd_sb_csp_t * p)
/*
* pause CSP codec and hold DMA transfer
*/
-static int snd_sb_csp_pause(snd_sb_csp_t * p)
+static int snd_sb_csp_pause(struct snd_sb_csp * p)
{
int result;
unsigned long flags;
@@ -903,7 +905,7 @@ static int snd_sb_csp_pause(snd_sb_csp_t * p)
/*
* restart CSP codec and resume DMA transfer
*/
-static int snd_sb_csp_restart(snd_sb_csp_t * p)
+static int snd_sb_csp_restart(struct snd_sb_csp * p)
{
int result;
unsigned long flags;
@@ -926,7 +928,7 @@ static int snd_sb_csp_restart(snd_sb_csp_t * p)
* QSound mixer control for PCM
*/
-static int snd_sb_qsound_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sb_qsound_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -935,17 +937,17 @@ static int snd_sb_qsound_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_sb_qsound_switch_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb_qsound_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
+ struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = p->q_enabled ? 1 : 0;
return 0;
}
-static int snd_sb_qsound_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb_qsound_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
+ struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval;
@@ -958,7 +960,7 @@ static int snd_sb_qsound_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return change;
}
-static int snd_sb_qsound_space_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sb_qsound_space_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -967,9 +969,9 @@ static int snd_sb_qsound_space_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_sb_qsound_space_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb_qsound_space_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
+ struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&p->q_lock, flags);
@@ -979,9 +981,9 @@ static int snd_sb_qsound_space_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_sb_qsound_space_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- snd_sb_csp_t *p = snd_kcontrol_chip(kcontrol);
+ struct snd_sb_csp *p = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval1, nval2;
@@ -1001,7 +1003,7 @@ static int snd_sb_qsound_space_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return change;
}
-static snd_kcontrol_new_t snd_sb_qsound_switch = {
+static struct snd_kcontrol_new snd_sb_qsound_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Switch",
.info = snd_sb_qsound_switch_info,
@@ -1009,7 +1011,7 @@ static snd_kcontrol_new_t snd_sb_qsound_switch = {
.put = snd_sb_qsound_switch_put
};
-static snd_kcontrol_new_t snd_sb_qsound_space = {
+static struct snd_kcontrol_new snd_sb_qsound_space = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Space",
.info = snd_sb_qsound_space_info,
@@ -1017,9 +1019,9 @@ static snd_kcontrol_new_t snd_sb_qsound_space = {
.put = snd_sb_qsound_space_put
};
-static int snd_sb_qsound_build(snd_sb_csp_t * p)
+static int snd_sb_qsound_build(struct snd_sb_csp * p)
{
- snd_card_t * card;
+ struct snd_card *card;
int err;
snd_assert(p != NULL, return -EINVAL);
@@ -1042,9 +1044,9 @@ static int snd_sb_qsound_build(snd_sb_csp_t * p)
return err;
}
-static void snd_sb_qsound_destroy(snd_sb_csp_t * p)
+static void snd_sb_qsound_destroy(struct snd_sb_csp * p)
{
- snd_card_t * card;
+ struct snd_card *card;
unsigned long flags;
snd_assert(p != NULL, return);
@@ -1068,7 +1070,7 @@ static void snd_sb_qsound_destroy(snd_sb_csp_t * p)
* Transfer qsound parameters to CSP,
* function should be called from interrupt routine
*/
-static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p)
+static int snd_sb_csp_qsound_transfer(struct snd_sb_csp * p)
{
int err = -ENXIO;
@@ -1093,19 +1095,19 @@ static int snd_sb_csp_qsound_transfer(snd_sb_csp_t * p)
/*
* proc interface
*/
-static int init_proc_entry(snd_sb_csp_t * p, int device)
+static int init_proc_entry(struct snd_sb_csp * p, int device)
{
char name[16];
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
sprintf(name, "cspD%d", device);
if (! snd_card_proc_new(p->chip->card, name, &entry))
snd_info_set_text_ops(entry, p, 1024, info_read);
return 0;
}
-static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- snd_sb_csp_t *p = entry->private_data;
+ struct snd_sb_csp *p = entry->private_data;
snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 556b95e3e22f..f183f1845a36 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -50,10 +50,10 @@ MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones
MODULE_LICENSE("GPL");
#ifdef CONFIG_SND_SB16_CSP
-static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
+static void snd_sb16_csp_playback_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime)
{
if (chip->hardware == SB_HW_16CSP) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
/* manually loaded codec */
@@ -98,10 +98,10 @@ static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime
}
}
-static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
+static void snd_sb16_csp_capture_prepare(struct snd_sb *chip, struct snd_pcm_runtime *runtime)
{
if (chip->hardware == SB_HW_16CSP) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
/* manually loaded codec */
@@ -136,10 +136,10 @@ static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
}
}
-static void snd_sb16_csp_update(sb_t *chip)
+static void snd_sb16_csp_update(struct snd_sb *chip)
{
if (chip->hardware == SB_HW_16CSP) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->qpos_changed) {
spin_lock(&chip->reg_lock);
@@ -149,11 +149,11 @@ static void snd_sb16_csp_update(sb_t *chip)
}
}
-static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
+static void snd_sb16_csp_playback_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime)
{
/* CSP decoders (QSound excluded) support only 16bit transfers */
if (chip->hardware == SB_HW_16CSP) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
/* manually loaded codec */
@@ -168,10 +168,10 @@ static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
}
}
-static void snd_sb16_csp_playback_close(sb_t *chip)
+static void snd_sb16_csp_playback_close(struct snd_sb *chip)
{
if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->ops.csp_stop(csp) == 0) {
csp->ops.csp_unuse(csp);
@@ -180,11 +180,11 @@ static void snd_sb16_csp_playback_close(sb_t *chip)
}
}
-static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
+static void snd_sb16_csp_capture_open(struct snd_sb *chip, struct snd_pcm_runtime *runtime)
{
/* CSP coders support only 16bit transfers */
if (chip->hardware == SB_HW_16CSP) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
/* manually loaded codec */
@@ -199,10 +199,10 @@ static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
}
}
-static void snd_sb16_csp_capture_close(sb_t *chip)
+static void snd_sb16_csp_capture_close(struct snd_sb *chip)
{
if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) {
- snd_sb_csp_t *csp = chip->csp;
+ struct snd_sb_csp *csp = chip->csp;
if (csp->ops.csp_stop(csp) == 0) {
csp->ops.csp_unuse(csp);
@@ -221,7 +221,7 @@ static void snd_sb16_csp_capture_close(sb_t *chip)
#endif
-static void snd_sb16_setup_rate(sb_t *chip,
+static void snd_sb16_setup_rate(struct snd_sb *chip,
unsigned short rate,
int channel)
{
@@ -244,23 +244,23 @@ static void snd_sb16_setup_rate(sb_t *chip,
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static int snd_sb16_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_sb16_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_sb16_hw_free(snd_pcm_substream_t * substream)
+static int snd_sb16_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_sb16_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char format;
unsigned int size, count, dma;
@@ -298,19 +298,21 @@ static int snd_sb16_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb16_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_sb16_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
int result = 0;
spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->mode |= SB_RATE_LOCK_PLAYBACK;
snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
snd_sbdsp_command(chip, chip->mode & SB_MODE_PLAYBACK_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF);
/* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */
if (chip->mode & SB_RATE_LOCK_CAPTURE)
@@ -324,11 +326,11 @@ static int snd_sb16_playback_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_sb16_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_sb16_capture_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char format;
unsigned int size, count, dma;
@@ -365,19 +367,21 @@ static int snd_sb16_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb16_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_sb16_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
int result = 0;
spin_lock(&chip->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->mode |= SB_RATE_LOCK_CAPTURE;
snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_ON : SB_DSP_DMA8_ON);
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
snd_sbdsp_command(chip, chip->mode & SB_MODE_CAPTURE_16 ? SB_DSP_DMA16_OFF : SB_DSP_DMA8_OFF);
/* next two lines are needed for some types of DSP4 (SB AWE 32 - 4.13) */
if (chip->mode & SB_RATE_LOCK_PLAYBACK)
@@ -393,7 +397,7 @@ static int snd_sb16_capture_trigger(snd_pcm_substream_t * substream,
irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- sb_t *chip = dev_id;
+ struct snd_sb *chip = dev_id;
unsigned char status;
int ok;
@@ -443,9 +447,9 @@ irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
-static snd_pcm_uframes_t snd_sb16_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sb16_playback_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned int dma;
size_t ptr;
@@ -454,9 +458,9 @@ static snd_pcm_uframes_t snd_sb16_playback_pointer(snd_pcm_substream_t * substre
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_sb16_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sb16_capture_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned int dma;
size_t ptr;
@@ -469,7 +473,7 @@ static snd_pcm_uframes_t snd_sb16_capture_pointer(snd_pcm_substream_t * substrea
*/
-static snd_pcm_hardware_t snd_sb16_playback =
+static struct snd_pcm_hardware snd_sb16_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -487,7 +491,7 @@ static snd_pcm_hardware_t snd_sb16_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_sb16_capture =
+static struct snd_pcm_hardware snd_sb16_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -509,11 +513,11 @@ static snd_pcm_hardware_t snd_sb16_capture =
* open/close
*/
-static int snd_sb16_playback_open(snd_pcm_substream_t * substream)
+static int snd_sb16_playback_open(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
spin_lock_irqsave(&chip->open_lock, flags);
if (chip->mode & SB_MODE_PLAYBACK) {
@@ -566,10 +570,10 @@ static int snd_sb16_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb16_playback_close(snd_pcm_substream_t * substream)
+static int snd_sb16_playback_close(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
snd_sb16_csp_playback_close(chip);
spin_lock_irqsave(&chip->open_lock, flags);
@@ -579,11 +583,11 @@ static int snd_sb16_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb16_capture_open(snd_pcm_substream_t * substream)
+static int snd_sb16_capture_open(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
spin_lock_irqsave(&chip->open_lock, flags);
if (chip->mode & SB_MODE_CAPTURE) {
@@ -636,10 +640,10 @@ static int snd_sb16_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb16_capture_close(snd_pcm_substream_t * substream)
+static int snd_sb16_capture_close(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
snd_sb16_csp_capture_close(chip);
spin_lock_irqsave(&chip->open_lock, flags);
@@ -653,7 +657,7 @@ static int snd_sb16_capture_close(snd_pcm_substream_t * substream)
* DMA control interface
*/
-static int snd_sb16_set_dma_mode(sb_t *chip, int what)
+static int snd_sb16_set_dma_mode(struct snd_sb *chip, int what)
{
if (chip->dma8 < 0 || chip->dma16 < 0) {
snd_assert(what == 0, return -EINVAL);
@@ -671,7 +675,7 @@ static int snd_sb16_set_dma_mode(sb_t *chip, int what)
return 0;
}
-static int snd_sb16_get_dma_mode(sb_t *chip)
+static int snd_sb16_get_dma_mode(struct snd_sb *chip)
{
if (chip->dma8 < 0 || chip->dma16 < 0)
return 0;
@@ -685,7 +689,7 @@ static int snd_sb16_get_dma_mode(sb_t *chip)
}
}
-static int snd_sb16_dma_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sb16_dma_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {
"Auto", "Playback", "Capture"
@@ -700,9 +704,9 @@ static int snd_sb16_dma_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_sb16_dma_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb16_dma_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -711,9 +715,9 @@ static int snd_sb16_dma_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_sb16_dma_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned char nval, oval;
int change;
@@ -728,7 +732,7 @@ static int snd_sb16_dma_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return change;
}
-static snd_kcontrol_new_t snd_sb16_dma_control = {
+static struct snd_kcontrol_new snd_sb16_dma_control = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "16-bit DMA Allocation",
.info = snd_sb16_dma_control_info,
@@ -740,7 +744,7 @@ static snd_kcontrol_new_t snd_sb16_dma_control = {
* Initialization part
*/
-int snd_sb16dsp_configure(sb_t * chip)
+int snd_sb16dsp_configure(struct snd_sb * chip)
{
unsigned long flags;
unsigned char irqreg = 0, dmareg = 0, mpureg;
@@ -829,7 +833,7 @@ int snd_sb16dsp_configure(sb_t * chip)
return 0;
}
-static snd_pcm_ops_t snd_sb16_playback_ops = {
+static struct snd_pcm_ops snd_sb16_playback_ops = {
.open = snd_sb16_playback_open,
.close = snd_sb16_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -840,7 +844,7 @@ static snd_pcm_ops_t snd_sb16_playback_ops = {
.pointer = snd_sb16_playback_pointer,
};
-static snd_pcm_ops_t snd_sb16_capture_ops = {
+static struct snd_pcm_ops snd_sb16_capture_ops = {
.open = snd_sb16_capture_open,
.close = snd_sb16_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -851,15 +855,10 @@ static snd_pcm_ops_t snd_sb16_capture_ops = {
.pointer = snd_sb16_capture_pointer,
};
-static void snd_sb16dsp_pcm_free(snd_pcm_t *pcm)
+int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_sb16dsp_pcm(sb_t * chip, int device, snd_pcm_t ** rpcm)
-{
- snd_card_t *card = chip->card;
- snd_pcm_t *pcm;
+ struct snd_card *card = chip->card;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -869,7 +868,6 @@ int snd_sb16dsp_pcm(sb_t * chip, int device, snd_pcm_t ** rpcm)
sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
pcm->private_data = chip;
- pcm->private_free = snd_sb16dsp_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
@@ -888,7 +886,7 @@ int snd_sb16dsp_pcm(sb_t * chip, int device, snd_pcm_t ** rpcm)
return 0;
}
-const snd_pcm_ops_t *snd_sb16dsp_get_pcm_ops(int direction)
+const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction)
{
return direction == SNDRV_PCM_STREAM_PLAYBACK ?
&snd_sb16_playback_ops : &snd_sb16_capture_ops;
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 0bc0a3afdabc..60ee79cd14a3 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -21,13 +21,14 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/opl3.h>
-#define SNDRV_LEGACY_AUTO_PROBE
#include <sound/initval.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -55,15 +56,16 @@ MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
module_param_array(dma8, int, NULL, 0444);
MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
+static struct platform_device *devices[SNDRV_CARDS];
+
struct snd_sb8 {
struct resource *fm_res; /* used to block FM i/o region for legacy cards */
+ struct snd_sb *chip;
};
-static snd_card_t *snd_sb8_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- sb_t *chip = dev_id;
+ struct snd_sb *chip = dev_id;
if (chip->open & SB_OPEN_PCM) {
return snd_sb8dsp_interrupt(chip);
@@ -72,7 +74,7 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs
}
}
-static void snd_sb8_free(snd_card_t *card)
+static void snd_sb8_free(struct snd_card *card)
{
struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data;
@@ -81,32 +83,57 @@ static void snd_sb8_free(snd_card_t *card)
release_and_free_resource(acard->fm_res);
}
-static int __init snd_sb8_probe(int dev)
+static int __init snd_sb8_probe(struct platform_device *pdev)
{
- sb_t *chip;
- snd_card_t *card;
+ int dev = pdev->id;
+ struct snd_sb *chip;
+ struct snd_card *card;
struct snd_sb8 *acard;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int err;
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_sb8));
if (card == NULL)
return -ENOMEM;
- acard = (struct snd_sb8 *)card->private_data;
+ acard = card->private_data;
card->private_free = snd_sb8_free;
/* block the 0x388 port to avoid PnP conflicts */
acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
- if ((err = snd_sbdsp_create(card, port[dev], irq[dev],
- snd_sb8_interrupt,
- dma8[dev],
- -1,
- SB_HW_AUTO,
- &chip)) < 0)
- goto _err;
-
+ if (port[dev] != SNDRV_AUTO_PORT) {
+ if ((err = snd_sbdsp_create(card, port[dev], irq[dev],
+ snd_sb8_interrupt,
+ dma8[dev],
+ -1,
+ SB_HW_AUTO,
+ &chip)) < 0)
+ goto _err;
+ } else {
+ /* auto-probe legacy ports */
+ static unsigned long possible_ports[] = {
+ 0x220, 0x240, 0x260,
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
+ err = snd_sbdsp_create(card, possible_ports[i],
+ irq[dev],
+ snd_sb8_interrupt,
+ dma8[dev],
+ -1,
+ SB_HW_AUTO,
+ &chip);
+ if (err >= 0) {
+ port[dev] = possible_ports[i];
+ break;
+ }
+ }
+ if (i >= ARRAY_SIZE(possible_ports))
+ goto _err;
+ }
+ acard->chip = chip;
+
if (chip->hardware >= SB_HW_16) {
if (chip->hardware == SB_HW_ALS100)
snd_printk(KERN_WARNING "ALS100 chip detected at 0x%lx, try snd-als100 module\n",
@@ -153,13 +180,12 @@ static int __init snd_sb8_probe(int dev)
chip->port,
irq[dev], dma8[dev]);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &pdev->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_sb8_cards[dev] = card;
+ platform_set_drvdata(pdev, card);
return 0;
_err:
@@ -167,53 +193,99 @@ static int __init snd_sb8_probe(int dev)
return err;
}
-static int __init snd_card_sb8_legacy_auto_probe(unsigned long xport)
+static int snd_sb8_remove(struct platform_device *pdev)
+{
+ snd_card_free(platform_get_drvdata(pdev));
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(dev);
+ struct snd_sb8 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
+}
+
+static int snd_sb8_resume(struct platform_device *dev)
+{
+ struct snd_card *card = platform_get_drvdata(dev);
+ struct snd_sb8 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+#define SND_SB8_DRIVER "snd_sb8"
+
+static struct platform_driver snd_sb8_driver = {
+ .probe = snd_sb8_probe,
+ .remove = snd_sb8_remove,
+#ifdef CONFIG_PM
+ .suspend = snd_sb8_suspend,
+ .resume = snd_sb8_resume,
+#endif
+ .driver = {
+ .name = SND_SB8_DRIVER
+ },
+};
+
+static void __init_or_module snd_sb8_unregister_all(void)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || port[dev] != SNDRV_AUTO_PORT)
- continue;
- port[dev] = xport;
- res = snd_sb8_probe(dev);
- if (res < 0)
- port[dev] = SNDRV_AUTO_PORT;
- return res;
- }
- return -ENODEV;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_sb8_driver);
}
static int __init alsa_card_sb8_init(void)
{
- static unsigned long possible_ports[] = {0x220, 0x240, 0x260, -1};
- int dev, cards, i;
-
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (port[dev] == SNDRV_AUTO_PORT)
- continue;
- if (snd_sb8_probe(dev) >= 0)
- cards++;
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_sb8_driver);
+ if (err < 0)
+ return err;
+
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_SB8_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
}
- i = snd_legacy_auto_probe(possible_ports, snd_card_sb8_legacy_auto_probe);
- if (i > 0)
- cards += i;
-
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_sb8_unregister_all();
+ return err;
}
static void __exit alsa_card_sb8_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_sb8_cards[idx]);
+ snd_sb8_unregister_all();
}
module_init(alsa_card_sb8_init)
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index 5ddc6e41d909..aea9e5ec7b36 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -46,19 +46,19 @@ MODULE_LICENSE("GPL");
#define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v))
#define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v))
-static ratnum_t clock = {
+static struct snd_ratnum clock = {
.num = SB8_CLOCK,
.den_min = 1,
.den_max = 256,
.den_step = 1,
};
-static snd_pcm_hw_constraint_ratnums_t hw_constraints_clock = {
+static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = {
.nrats = 1,
.rats = &clock,
};
-static ratnum_t stereo_clocks[] = {
+static struct snd_ratnum stereo_clocks[] = {
{
.num = SB8_CLOCK,
.den_min = SB8_DEN(22050),
@@ -73,10 +73,10 @@ static ratnum_t stereo_clocks[] = {
}
};
-static int snd_sb8_hw_constraint_rate_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_sb8_hw_constraint_rate_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
if (c->min > 1) {
unsigned int num = 0, den = 0;
int err = snd_interval_ratnum(hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE),
@@ -90,22 +90,22 @@ static int snd_sb8_hw_constraint_rate_channels(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_sb8_hw_constraint_channels_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_sb8_hw_constraint_channels_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (r->min > SB8_RATE(22050) || r->max <= SB8_RATE(11025)) {
- snd_interval_t t = { .min = 1, .max = 1 };
+ struct snd_interval t = { .min = 1, .max = 1 };
return snd_interval_refine(hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS), &t);
}
return 0;
}
-static int snd_sb8_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_sb8_playback_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int mixreg, rate, size, count;
rate = runtime->rate;
@@ -178,11 +178,11 @@ static int snd_sb8_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb8_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned int count;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -197,7 +197,7 @@ static int snd_sb8_playback_trigger(snd_pcm_substream_t * substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
if (chip->playback_format == SB_DSP_HI_OUTPUT_AUTO) {
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_sbdsp_reset(chip);
if (runtime->channels > 1) {
spin_lock(&chip->mixer_lock);
@@ -215,23 +215,23 @@ static int snd_sb8_playback_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_sb8_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_sb8_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_sb8_hw_free(snd_pcm_substream_t * substream)
+static int snd_sb8_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_sb8_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int mixreg, rate, size, count;
rate = runtime->rate;
@@ -290,11 +290,11 @@ static int snd_sb8_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_sb8_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned int count;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -309,7 +309,7 @@ static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
if (chip->capture_format == SB_DSP_HI_INPUT_AUTO) {
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_sbdsp_reset(chip);
if (runtime->channels > 1) {
/* restore input filter status */
@@ -329,10 +329,10 @@ static int snd_sb8_capture_trigger(snd_pcm_substream_t * substream,
return 0;
}
-irqreturn_t snd_sb8dsp_interrupt(sb_t *chip)
+irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
snd_sb_ack_8bit(chip);
switch (chip->mode) {
@@ -354,9 +354,9 @@ irqreturn_t snd_sb8dsp_interrupt(sb_t *chip)
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_sb8_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sb8_playback_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (chip->mode != SB_MODE_PLAYBACK_8)
@@ -365,9 +365,9 @@ static snd_pcm_uframes_t snd_sb8_playback_pointer(snd_pcm_substream_t * substrea
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_sb8_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sb8_capture_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (chip->mode != SB_MODE_CAPTURE_8)
@@ -380,7 +380,7 @@ static snd_pcm_uframes_t snd_sb8_capture_pointer(snd_pcm_substream_t * substream
*/
-static snd_pcm_hardware_t snd_sb8_playback =
+static struct snd_pcm_hardware snd_sb8_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -399,7 +399,7 @@ static snd_pcm_hardware_t snd_sb8_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_sb8_capture =
+static struct snd_pcm_hardware snd_sb8_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -422,10 +422,10 @@ static snd_pcm_hardware_t snd_sb8_capture =
*
*/
-static int snd_sb8_open(snd_pcm_substream_t *substream)
+static int snd_sb8_open(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -468,10 +468,10 @@ static int snd_sb8_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_sb8_close(snd_pcm_substream_t *substream)
+static int snd_sb8_close(struct snd_pcm_substream *substream)
{
unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
chip->capture_substream = NULL;
@@ -485,7 +485,7 @@ static int snd_sb8_close(snd_pcm_substream_t *substream)
* Initialization part
*/
-static snd_pcm_ops_t snd_sb8_playback_ops = {
+static struct snd_pcm_ops snd_sb8_playback_ops = {
.open = snd_sb8_open,
.close = snd_sb8_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -496,7 +496,7 @@ static snd_pcm_ops_t snd_sb8_playback_ops = {
.pointer = snd_sb8_playback_pointer,
};
-static snd_pcm_ops_t snd_sb8_capture_ops = {
+static struct snd_pcm_ops snd_sb8_capture_ops = {
.open = snd_sb8_open,
.close = snd_sb8_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -507,15 +507,10 @@ static snd_pcm_ops_t snd_sb8_capture_ops = {
.pointer = snd_sb8_capture_pointer,
};
-static void snd_sb8dsp_pcm_free(snd_pcm_t *pcm)
+int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm)
-{
- snd_card_t *card = chip->card;
- snd_pcm_t *pcm;
+ struct snd_card *card = chip->card;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -525,7 +520,6 @@ int snd_sb8dsp_pcm(sb_t *chip, int device, snd_pcm_t ** rpcm)
sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
pcm->private_data = chip;
- pcm->private_free = snd_sb8dsp_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb8_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb8_capture_ops);
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index d2c633a40e74..c549aceea294 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -36,9 +36,9 @@
*/
-irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
+irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int max = 64;
char byte;
@@ -63,10 +63,10 @@ irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
*/
-static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
unsigned int valid_open_flags;
chip = substream->rmidi->private_data;
@@ -90,10 +90,10 @@ static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_sb8dsp_midi_output_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
unsigned int valid_open_flags;
chip = substream->rmidi->private_data;
@@ -117,10 +117,10 @@ static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_sb8dsp_midi_input_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -135,10 +135,10 @@ static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_sb8dsp_midi_output_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -153,10 +153,10 @@ static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_sb8dsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -176,10 +176,10 @@ static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, i
spin_unlock_irqrestore(&chip->open_lock, flags);
}
-static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
+static void snd_sb8dsp_midi_output_write(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
char byte;
int max = 32;
@@ -214,8 +214,8 @@ static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
static void snd_sb8dsp_midi_output_timer(unsigned long data)
{
- snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
- sb_t * chip = substream->rmidi->private_data;
+ struct snd_rawmidi_substream *substream = (struct snd_rawmidi_substream *) data;
+ struct snd_sb * chip = substream->rmidi->private_data;
unsigned long flags;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -225,10 +225,10 @@ static void snd_sb8dsp_midi_output_timer(unsigned long data)
snd_sb8dsp_midi_output_write(substream);
}
-static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- sb_t *chip;
+ struct snd_sb *chip;
chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->open_lock, flags);
@@ -256,23 +256,23 @@ static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream,
*/
-static snd_rawmidi_ops_t snd_sb8dsp_midi_output =
+static struct snd_rawmidi_ops snd_sb8dsp_midi_output =
{
.open = snd_sb8dsp_midi_output_open,
.close = snd_sb8dsp_midi_output_close,
.trigger = snd_sb8dsp_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_sb8dsp_midi_input =
+static struct snd_rawmidi_ops snd_sb8dsp_midi_input =
{
.open = snd_sb8dsp_midi_input_open,
.close = snd_sb8dsp_midi_input_close,
.trigger = snd_sb8dsp_midi_input_trigger,
};
-int snd_sb8dsp_midi(sb_t *chip, int device, snd_rawmidi_t ** rrawmidi)
+int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index 603e923b5d2f..f343a8211d2d 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -41,7 +41,7 @@ MODULE_LICENSE("GPL");
#undef IO_DEBUG
-int snd_sbdsp_command(sb_t *chip, unsigned char val)
+int snd_sbdsp_command(struct snd_sb *chip, unsigned char val)
{
int i;
#ifdef IO_DEBUG
@@ -56,7 +56,7 @@ int snd_sbdsp_command(sb_t *chip, unsigned char val)
return 0;
}
-int snd_sbdsp_get_byte(sb_t *chip)
+int snd_sbdsp_get_byte(struct snd_sb *chip)
{
int val;
int i;
@@ -73,7 +73,7 @@ int snd_sbdsp_get_byte(sb_t *chip)
return -ENODEV;
}
-int snd_sbdsp_reset(sb_t *chip)
+int snd_sbdsp_reset(struct snd_sb *chip)
{
int i;
@@ -92,7 +92,7 @@ int snd_sbdsp_reset(sb_t *chip)
return -ENODEV;
}
-static int snd_sbdsp_version(sb_t * chip)
+static int snd_sbdsp_version(struct snd_sb * chip)
{
unsigned int result = -ENODEV;
@@ -102,7 +102,7 @@ static int snd_sbdsp_version(sb_t * chip)
return result;
}
-static int snd_sbdsp_probe(sb_t * chip)
+static int snd_sbdsp_probe(struct snd_sb * chip)
{
int version;
int major, minor;
@@ -176,7 +176,7 @@ static int snd_sbdsp_probe(sb_t * chip)
return 0;
}
-static int snd_sbdsp_free(sb_t *chip)
+static int snd_sbdsp_free(struct snd_sb *chip)
{
if (chip->res_port)
release_and_free_resource(chip->res_port);
@@ -196,24 +196,24 @@ static int snd_sbdsp_free(sb_t *chip)
return 0;
}
-static int snd_sbdsp_dev_free(snd_device_t *device)
+static int snd_sbdsp_dev_free(struct snd_device *device)
{
- sb_t *chip = device->device_data;
+ struct snd_sb *chip = device->device_data;
return snd_sbdsp_free(chip);
}
-int snd_sbdsp_create(snd_card_t *card,
+int snd_sbdsp_create(struct snd_card *card,
unsigned long port,
int irq,
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *),
int dma8,
int dma16,
unsigned short hardware,
- sb_t **r_chip)
+ struct snd_sb **r_chip)
{
- sb_t *chip;
+ struct snd_sb *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_sbdsp_dev_free,
};
@@ -293,6 +293,10 @@ EXPORT_SYMBOL(snd_sbmixer_write);
EXPORT_SYMBOL(snd_sbmixer_read);
EXPORT_SYMBOL(snd_sbmixer_new);
EXPORT_SYMBOL(snd_sbmixer_add_ctl);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(snd_sbmixer_suspend);
+EXPORT_SYMBOL(snd_sbmixer_resume);
+#endif
/*
* INIT part
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 5a926a452d38..1a6ee344dddb 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -29,7 +29,7 @@
#undef IO_DEBUG
-void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
+void snd_sbmixer_write(struct snd_sb *chip, unsigned char reg, unsigned char data)
{
outb(reg, SBP(chip, MIXER_ADDR));
udelay(10);
@@ -40,7 +40,7 @@ void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
#endif
}
-unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg)
+unsigned char snd_sbmixer_read(struct snd_sb *chip, unsigned char reg)
{
unsigned char result;
@@ -58,7 +58,7 @@ unsigned char snd_sbmixer_read(sb_t *chip, unsigned char reg)
* Single channel mixer element
*/
-static int snd_sbmixer_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sbmixer_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -69,9 +69,9 @@ static int snd_sbmixer_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_sbmixer_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0xff;
@@ -85,9 +85,9 @@ static int snd_sbmixer_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_sbmixer_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sbmixer_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0x07;
@@ -110,7 +110,7 @@ static int snd_sbmixer_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
* Double channel mixer element
*/
-static int snd_sbmixer_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sbmixer_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -121,9 +121,9 @@ static int snd_sbmixer_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_sbmixer_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sbmixer_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -141,9 +141,9 @@ static int snd_sbmixer_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sbmixer_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -181,7 +181,7 @@ static int snd_sbmixer_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
* DT-019x / ALS-007 capture/input switch
*/
-static int snd_dt019x_input_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_dt019x_input_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[5] = {
"CD", "Mic", "Line", "Synth", "Master"
@@ -196,9 +196,9 @@ static int snd_dt019x_input_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_dt019x_input_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dt019x_input_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned char oval;
@@ -232,9 +232,9 @@ static int snd_dt019x_input_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_dt019x_input_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_dt019x_input_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval, oval;
@@ -273,7 +273,7 @@ static int snd_dt019x_input_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
* SBPRO input multiplexer
*/
-static int snd_sb8mixer_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sb8mixer_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {
"Mic", "CD", "Line"
@@ -289,9 +289,9 @@ static int snd_sb8mixer_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
}
-static int snd_sb8mixer_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb8mixer_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned char oval;
@@ -312,9 +312,9 @@ static int snd_sb8mixer_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_sb8mixer_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb8mixer_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int change;
unsigned char nval, oval;
@@ -346,7 +346,7 @@ static int snd_sb8mixer_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
* SB16 input switch
*/
-static int snd_sb16mixer_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sb16mixer_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 4;
@@ -355,9 +355,9 @@ static int snd_sb16mixer_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_sb16mixer_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb16mixer_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff;
@@ -376,9 +376,9 @@ static int snd_sb16mixer_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_sb16mixer_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sb_t *sb = snd_kcontrol_chip(kcontrol);
+ struct snd_sb *sb = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff;
@@ -410,9 +410,9 @@ static int snd_sb16mixer_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
*/
/*
*/
-int snd_sbmixer_add_ctl(sb_t *chip, const char *name, int index, int type, unsigned long value)
+int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value)
{
- static snd_kcontrol_new_t newctls[] = {
+ static struct snd_kcontrol_new newctls[] = {
[SB_MIX_SINGLE] = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_sbmixer_info_single,
@@ -444,7 +444,7 @@ int snd_sbmixer_add_ctl(sb_t *chip, const char *name, int index, int type, unsig
.put = snd_dt019x_input_sw_put,
},
};
- snd_kcontrol_t *ctl;
+ struct snd_kcontrol *ctl;
int err;
ctl = snd_ctl_new1(&newctls[type], chip);
@@ -669,25 +669,34 @@ static unsigned char snd_dt019x_init_values[][2] = {
/*
* ALS4000 specific mixer elements
*/
-/* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl ! */
-static struct sbmix_elem snd_als4000_ctl_mono_output_switch =
- SB_SINGLE("Mono Output Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
-/* FIXME: mono input switch also available on DT019X ? */
-static struct sbmix_elem snd_als4000_ctl_mono_input_switch =
- SB_SINGLE("Mono Input Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
+/* FIXME: SB_ALS4000_MONO_IO_CTRL needs output select ctrl! */
+static struct sbmix_elem snd_als4000_ctl_master_mono_playback_switch =
+ SB_SINGLE("Master Mono Playback Switch", SB_ALS4000_MONO_IO_CTRL, 5, 1);
+static struct sbmix_elem snd_als4000_ctl_master_mono_capture_route =
+ SB_SINGLE("Master Mono Capture Route", SB_ALS4000_MONO_IO_CTRL, 6, 0x03);
+/* FIXME: mono playback switch also available on DT019X? */
+static struct sbmix_elem snd_als4000_ctl_mono_playback_switch =
+ SB_SINGLE("Mono Playback Switch", SB_DT019X_OUTPUT_SW2, 0, 1);
static struct sbmix_elem snd_als4000_ctl_mic_20db_boost =
SB_SINGLE("Mic Boost (+20dB)", SB_ALS4000_MIC_IN_GAIN, 0, 0x03);
-static struct sbmix_elem snd_als4000_ctl_mixer_out_to_in =
- SB_SINGLE("Mixer Out To In", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
-/* FIXME: 3D needs much more sophisticated controls, many more features ! */
-static struct sbmix_elem snd_als4000_ctl_3d_output_switch =
- SB_SINGLE("3D Output Switch", SB_ALS4000_3D_SND_FX, 6, 0x01);
-static struct sbmix_elem snd_als4000_ctl_3d_output_ratio =
- SB_SINGLE("3D Output Ratio", SB_ALS4000_3D_SND_FX, 0, 0x07);
-static struct sbmix_elem snd_als4000_ctl_3d_poweroff_switch =
+static struct sbmix_elem snd_als4000_ctl_mixer_loopback =
+ SB_SINGLE("Analog Loopback", SB_ALS4000_MIC_IN_GAIN, 7, 0x01);
+/* FIXME: functionality of 3D controls might be swapped, I didn't find
+ * a description of how to identify what is supposed to be what */
+static struct sbmix_elem snd_als4000_3d_control_switch =
+ SB_SINGLE("3D Control - Switch", SB_ALS4000_3D_SND_FX, 6, 0x01);
+static struct sbmix_elem snd_als4000_3d_control_ratio =
+ SB_SINGLE("3D Control - Level", SB_ALS4000_3D_SND_FX, 0, 0x07);
+static struct sbmix_elem snd_als4000_3d_control_freq =
+ /* FIXME: maybe there's actually some standard 3D ctrl name for it?? */
+ SB_SINGLE("3D Control - Freq", SB_ALS4000_3D_SND_FX, 4, 0x03);
+static struct sbmix_elem snd_als4000_3d_control_delay =
+ /* FIXME: ALS4000a.pdf mentions BBD (Bucket Brigade Device) time delay,
+ * but what ALSA 3D attribute is that actually? "Center", "Depth",
+ * "Wide" or "Space" or even "Level"? Assuming "Wide" for now... */
+ SB_SINGLE("3D Control - Wide", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
+static struct sbmix_elem snd_als4000_3d_control_poweroff_switch =
SB_SINGLE("3D PowerOff Switch", SB_ALS4000_3D_TIME_DELAY, 4, 0x01);
-static struct sbmix_elem snd_als4000_ctl_3d_delay =
- SB_SINGLE("3D Delay", SB_ALS4000_3D_TIME_DELAY, 0, 0x0f);
#ifdef NOT_AVAILABLE
static struct sbmix_elem snd_als4000_ctl_fmdac =
SB_SINGLE("FMDAC Switch (Option ?)", SB_ALS4000_FMDAC, 0, 0x01);
@@ -716,13 +725,15 @@ static struct sbmix_elem *snd_als4000_controls[] = {
&snd_sb16_ctl_pc_speaker_vol,
&snd_sb16_ctl_capture_vol,
&snd_sb16_ctl_play_vol,
- &snd_als4000_ctl_mono_output_switch,
- &snd_als4000_ctl_mono_input_switch,
- &snd_als4000_ctl_mixer_out_to_in,
- &snd_als4000_ctl_3d_output_switch,
- &snd_als4000_ctl_3d_output_ratio,
- &snd_als4000_ctl_3d_delay,
- &snd_als4000_ctl_3d_poweroff_switch,
+ &snd_als4000_ctl_master_mono_playback_switch,
+ &snd_als4000_ctl_master_mono_capture_route,
+ &snd_als4000_ctl_mono_playback_switch,
+ &snd_als4000_ctl_mixer_loopback,
+ &snd_als4000_3d_control_switch,
+ &snd_als4000_3d_control_ratio,
+ &snd_als4000_3d_control_freq,
+ &snd_als4000_3d_control_delay,
+ &snd_als4000_3d_control_poweroff_switch,
#ifdef NOT_AVAILABLE
&snd_als4000_ctl_fmdac,
&snd_als4000_ctl_qsound,
@@ -747,7 +758,7 @@ static unsigned char snd_als4000_init_values[][2] = {
/*
*/
-static int snd_sbmixer_init(sb_t *chip,
+static int snd_sbmixer_init(struct snd_sb *chip,
struct sbmix_elem **controls,
int controls_count,
unsigned char map[][2],
@@ -755,7 +766,7 @@ static int snd_sbmixer_init(sb_t *chip,
char *name)
{
unsigned long flags;
- snd_card_t *card = chip->card;
+ struct snd_card *card = chip->card;
int idx, err;
/* mixer reset */
@@ -779,9 +790,9 @@ static int snd_sbmixer_init(sb_t *chip,
return 0;
}
-int snd_sbmixer_new(sb_t *chip)
+int snd_sbmixer_new(struct snd_sb *chip)
{
- snd_card_t * card;
+ struct snd_card *card;
int err;
snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
@@ -842,3 +853,140 @@ int snd_sbmixer_new(sb_t *chip)
}
return 0;
}
+
+#ifdef CONFIG_PM
+static unsigned char sb20_saved_regs[] = {
+ SB_DSP20_MASTER_DEV,
+ SB_DSP20_PCM_DEV,
+ SB_DSP20_FM_DEV,
+ SB_DSP20_CD_DEV,
+};
+
+static unsigned char sbpro_saved_regs[] = {
+ SB_DSP_MASTER_DEV,
+ SB_DSP_PCM_DEV,
+ SB_DSP_PLAYBACK_FILT,
+ SB_DSP_FM_DEV,
+ SB_DSP_CD_DEV,
+ SB_DSP_LINE_DEV,
+ SB_DSP_MIC_DEV,
+ SB_DSP_CAPTURE_SOURCE,
+ SB_DSP_CAPTURE_FILT,
+};
+
+static unsigned char sb16_saved_regs[] = {
+ SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
+ SB_DSP4_3DSE,
+ SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1,
+ SB_DSP4_TREBLE_DEV, SB_DSP4_TREBLE_DEV + 1,
+ SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
+ SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
+ SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
+ SB_DSP4_OUTPUT_SW,
+ SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
+ SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
+ SB_DSP4_MIC_DEV,
+ SB_DSP4_SPEAKER_DEV,
+ SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
+ SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
+ SB_DSP4_MIC_AGC
+};
+
+static unsigned char dt019x_saved_regs[] = {
+ SB_DT019X_MASTER_DEV,
+ SB_DT019X_PCM_DEV,
+ SB_DT019X_SYNTH_DEV,
+ SB_DT019X_CD_DEV,
+ SB_DT019X_MIC_DEV,
+ SB_DT019X_SPKR_DEV,
+ SB_DT019X_LINE_DEV,
+ SB_DSP4_OUTPUT_SW,
+ SB_DT019X_OUTPUT_SW2,
+ SB_DT019X_CAPTURE_SW,
+};
+
+static unsigned char als4000_saved_regs[] = {
+ SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
+ SB_DSP4_OUTPUT_SW,
+ SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
+ SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
+ SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
+ SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
+ SB_DSP4_MIC_AGC,
+ SB_DSP4_MIC_DEV,
+ SB_DSP4_SPEAKER_DEV,
+ SB_DSP4_IGAIN_DEV, SB_DSP4_IGAIN_DEV + 1,
+ SB_DSP4_OGAIN_DEV, SB_DSP4_OGAIN_DEV + 1,
+ SB_DT019X_OUTPUT_SW2,
+ SB_ALS4000_MONO_IO_CTRL,
+ SB_ALS4000_MIC_IN_GAIN,
+ SB_ALS4000_3D_SND_FX,
+ SB_ALS4000_3D_TIME_DELAY,
+};
+
+static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
+{
+ unsigned char *val = chip->saved_regs;
+ snd_assert(num_regs > ARRAY_SIZE(chip->saved_regs), return);
+ for (; num_regs; num_regs--)
+ *val++ = snd_sbmixer_read(chip, *regs++);
+}
+
+static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
+{
+ unsigned char *val = chip->saved_regs;
+ snd_assert(num_regs > ARRAY_SIZE(chip->saved_regs), return);
+ for (; num_regs; num_regs--)
+ snd_sbmixer_write(chip, *regs++, *val++);
+}
+
+void snd_sbmixer_suspend(struct snd_sb *chip)
+{
+ switch (chip->hardware) {
+ case SB_HW_20:
+ case SB_HW_201:
+ save_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
+ break;
+ case SB_HW_PRO:
+ save_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
+ break;
+ case SB_HW_16:
+ case SB_HW_ALS100:
+ save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
+ break;
+ case SB_HW_ALS4000:
+ save_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
+ break;
+ case SB_HW_DT019X:
+ save_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
+ break;
+ default:
+ break;
+ }
+}
+
+void snd_sbmixer_resume(struct snd_sb *chip)
+{
+ switch (chip->hardware) {
+ case SB_HW_20:
+ case SB_HW_201:
+ restore_mixer(chip, sb20_saved_regs, ARRAY_SIZE(sb20_saved_regs));
+ break;
+ case SB_HW_PRO:
+ restore_mixer(chip, sbpro_saved_regs, ARRAY_SIZE(sbpro_saved_regs));
+ break;
+ case SB_HW_16:
+ case SB_HW_ALS100:
+ restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs));
+ break;
+ case SB_HW_ALS4000:
+ restore_mixer(chip, als4000_saved_regs, ARRAY_SIZE(als4000_saved_regs));
+ break;
+ case SB_HW_DT019X:
+ restore_mixer(chip, dt019x_saved_regs, ARRAY_SIZE(dt019x_saved_regs));
+ break;
+ default:
+ break;
+ }
+}
+#endif
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 52f2294da62b..0dbbb35b242c 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -22,12 +22,14 @@
*/
#include <sound/driver.h>
-#include <asm/dma.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
+#include <asm/dma.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/ad1848.h>
@@ -62,11 +64,11 @@ MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
module_param_array(dma1, int, NULL, 0444);
MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
+static struct platform_device *devices[SNDRV_CARDS];
+
#define SGALAXY_AUXC_LEFT 18
#define SGALAXY_AUXC_RIGHT 19
-static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
#define PFX "sgalaxy: "
/*
@@ -75,7 +77,7 @@ static snd_card_t *snd_sgalaxy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
-/* from lowlevel/sb/sb.c - to avoid having to allocate a sb_t for the */
+/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
/* short time we actually need it.. */
static int snd_sgalaxy_sbdsp_reset(unsigned long port)
@@ -180,10 +182,10 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7
AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
};
-static int __init snd_sgalaxy_mixer(ad1848_t *chip)
+static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id1, id2;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id1, id2;
unsigned int idx;
int err;
@@ -216,13 +218,14 @@ static int __init snd_sgalaxy_mixer(ad1848_t *chip)
return 0;
}
-static int __init snd_sgalaxy_probe(int dev)
+static int __init snd_sgalaxy_probe(struct platform_device *devptr)
{
+ int dev = devptr->id;
static int possible_irqs[] = {7, 9, 10, 11, -1};
static int possible_dmas[] = {1, 3, 0, -1};
int err, xirq, xdma1;
- snd_card_t *card;
- ad1848_t *chip;
+ struct snd_card *card;
+ struct snd_ad1848 *chip;
if (sbport[dev] == SNDRV_AUTO_PORT) {
snd_printk(KERN_ERR PFX "specify SB port\n");
@@ -260,6 +263,7 @@ static int __init snd_sgalaxy_probe(int dev)
xirq, xdma1,
AD1848_HW_DETECT, &chip)) < 0)
goto _err;
+ card->private_data = chip;
if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
snd_printdd(PFX "error creating new ad1848 PCM device\n");
@@ -279,13 +283,12 @@ 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_set_generic_dev(card)) < 0)
- goto _err;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) < 0)
goto _err;
- snd_sgalaxy_cards[dev] = card;
+ platform_set_drvdata(devptr, card);
return 0;
_err:
@@ -293,30 +296,98 @@ static int __init snd_sgalaxy_probe(int dev)
return err;
}
+static int __devexit snd_sgalaxy_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ chip->suspend(chip);
+ return 0;
+}
+
+static int snd_sgalaxy_resume(struct platform_device *pdev)
+{
+ struct snd_card *card = platform_get_drvdata(pdev);
+ struct snd_ad1848 *chip = card->private_data;
+
+ chip->resume(chip);
+ snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
+ snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+#define SND_SGALAXY_DRIVER "snd_sgalaxy"
+
+static struct platform_driver snd_sgalaxy_driver = {
+ .probe = snd_sgalaxy_probe,
+ .remove = __devexit_p(snd_sgalaxy_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_sgalaxy_suspend,
+ .resume = snd_sgalaxy_resume,
+#endif
+ .driver = {
+ .name = SND_SGALAXY_DRIVER
+ },
+};
+
+static void __init_or_module snd_sgalaxy_unregister_all(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(devices); ++i)
+ platform_device_unregister(devices[i]);
+ platform_driver_unregister(&snd_sgalaxy_driver);
+}
+
static int __init alsa_card_sgalaxy_init(void)
{
- int dev, cards;
+ int i, cards, err;
+
+ err = platform_driver_register(&snd_sgalaxy_driver);
+ if (err < 0)
+ return err;
- for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
- if (snd_sgalaxy_probe(dev) >= 0)
- cards++;
+ cards = 0;
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
+ device = platform_device_register_simple(SND_SGALAXY_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ devices[i] = device;
+ cards++;
}
if (!cards) {
#ifdef MODULE
snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
-
return 0;
+
+ errout:
+ snd_sgalaxy_unregister_all();
+ return err;
}
static void __exit alsa_card_sgalaxy_exit(void)
{
- int idx;
-
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_sgalaxy_cards[idx]);
+ snd_sgalaxy_unregister_all();
}
module_init(alsa_card_sgalaxy_init)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 11588067fa4f..5fb981c0a281 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -23,6 +23,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
@@ -65,6 +67,9 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
module_param_array(dma, int, NULL, 0444);
MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
+
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
#ifdef CONFIG_PNP
static struct pnp_card_device_id sscape_pnpids[] = {
@@ -75,8 +80,6 @@ static struct pnp_card_device_id sscape_pnpids[] = {
MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
#endif
-static snd_card_t *sscape_card[SNDRV_CARDS];
-
#define MPU401_IO(i) ((i) + 0)
#define MIDI_DATA_IO(i) ((i) + 0)
@@ -127,9 +130,9 @@ struct soundscape {
int codec_type;
int ic_type;
struct resource *io_res;
- cs4231_t *chip;
- mpu401_t *mpu;
- snd_hwdep_t *hw;
+ struct snd_cs4231 *chip;
+ struct snd_mpu401 *mpu;
+ struct snd_hwdep *hw;
/*
* The MIDI device won't work until we've loaded
@@ -144,17 +147,17 @@ struct soundscape {
#define INVALID_IRQ ((unsigned)-1)
-static inline struct soundscape *get_card_soundscape(snd_card_t * c)
+static inline struct soundscape *get_card_soundscape(struct snd_card *c)
{
return (struct soundscape *) (c->private_data);
}
-static inline struct soundscape *get_mpu401_soundscape(mpu401_t * mpu)
+static inline struct soundscape *get_mpu401_soundscape(struct snd_mpu401 * mpu)
{
return (struct soundscape *) (mpu->private_data);
}
-static inline struct soundscape *get_hwdep_soundscape(snd_hwdep_t * hw)
+static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep * hw)
{
return (struct soundscape *) (hw->private_data);
}
@@ -308,7 +311,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
*
* NOTE: This check is based upon observation, not documentation.
*/
-static inline int verify_mpu401(const mpu401_t * mpu)
+static inline int verify_mpu401(const struct snd_mpu401 * mpu)
{
return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80);
}
@@ -316,7 +319,7 @@ static inline int verify_mpu401(const mpu401_t * mpu)
/*
* This is apparently the standard way to initailise an MPU-401
*/
-static inline void initialise_mpu401(const mpu401_t * mpu)
+static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
{
outb(0, MIDI_DATA_IO(mpu->port));
}
@@ -335,7 +338,7 @@ static inline void activate_ad1845_unsafe(unsigned io_base)
/*
* Do the necessary ALSA-level cleanup to deallocate our driver ...
*/
-static void soundscape_free(snd_card_t * c)
+static void soundscape_free(struct snd_card *c)
{
register struct soundscape *sscape = get_card_soundscape(c);
release_and_free_resource(sscape->io_res);
@@ -613,7 +616,7 @@ static int sscape_upload_microcode(struct soundscape *sscape,
* simultaneously, and that we can't open it at all if
* someone is using the MIDI device.
*/
-static int sscape_hw_open(snd_hwdep_t * hw, struct file *file)
+static int sscape_hw_open(struct snd_hwdep * hw, struct file *file)
{
register struct soundscape *sscape = get_hwdep_soundscape(hw);
unsigned long flags;
@@ -632,7 +635,7 @@ static int sscape_hw_open(snd_hwdep_t * hw, struct file *file)
return err;
}
-static int sscape_hw_release(snd_hwdep_t * hw, struct file *file)
+static int sscape_hw_release(struct snd_hwdep * hw, struct file *file)
{
register struct soundscape *sscape = get_hwdep_soundscape(hw);
unsigned long flags;
@@ -643,7 +646,7 @@ static int sscape_hw_release(snd_hwdep_t * hw, struct file *file)
return 0;
}
-static int sscape_hw_ioctl(snd_hwdep_t * hw, struct file *file,
+static int sscape_hw_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct soundscape *sscape = get_hwdep_soundscape(hw);
@@ -692,8 +695,8 @@ static int sscape_hw_ioctl(snd_hwdep_t * hw, struct file *file,
/*
* Mixer control for the SoundScape's MIDI device.
*/
-static int sscape_midi_info(snd_kcontrol_t * ctl,
- snd_ctl_elem_info_t * uinfo)
+static int sscape_midi_info(struct snd_kcontrol *ctl,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -702,11 +705,11 @@ static int sscape_midi_info(snd_kcontrol_t * ctl,
return 0;
}
-static int sscape_midi_get(snd_kcontrol_t * kctl,
- snd_ctl_elem_value_t * uctl)
+static int sscape_midi_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl)
{
- cs4231_t *chip = snd_kcontrol_chip(kctl);
- snd_card_t *card = chip->card;
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kctl);
+ struct snd_card *card = chip->card;
register struct soundscape *s = get_card_soundscape(card);
unsigned long flags;
@@ -722,11 +725,11 @@ static int sscape_midi_get(snd_kcontrol_t * kctl,
return 0;
}
-static int sscape_midi_put(snd_kcontrol_t * kctl,
- snd_ctl_elem_value_t * uctl)
+static int sscape_midi_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl)
{
- cs4231_t *chip = snd_kcontrol_chip(kctl);
- snd_card_t *card = chip->card;
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kctl);
+ struct snd_card *card = chip->card;
register struct soundscape *s = get_card_soundscape(card);
unsigned long flags;
int change;
@@ -763,7 +766,7 @@ static int sscape_midi_put(snd_kcontrol_t * kctl,
return change;
}
-static snd_kcontrol_new_t midi_mixer_ctl = {
+static struct snd_kcontrol_new midi_mixer_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "MIDI",
.info = sscape_midi_info,
@@ -849,7 +852,7 @@ static int __devinit detect_sscape(struct soundscape *s)
* to crash the machine. Also check that someone isn't using the hardware
* IOCTL device.
*/
-static int mpu401_open(mpu401_t * mpu)
+static int mpu401_open(struct snd_mpu401 * mpu)
{
int err;
@@ -875,7 +878,7 @@ static int mpu401_open(mpu401_t * mpu)
return err;
}
-static void mpu401_close(mpu401_t * mpu)
+static void mpu401_close(struct snd_mpu401 * mpu)
{
register struct soundscape *sscape = get_mpu401_soundscape(mpu);
unsigned long flags;
@@ -888,10 +891,10 @@ static void mpu401_close(mpu401_t * mpu)
/*
* Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
*/
-static int __devinit create_mpu401(snd_card_t * card, int devnum, unsigned long port, int irq)
+static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned long port, int irq)
{
struct soundscape *sscape = get_card_soundscape(card);
- snd_rawmidi_t *rawmidi;
+ struct snd_rawmidi *rawmidi;
int err;
#define MPU401_SHARE_HARDWARE 1
@@ -900,7 +903,7 @@ static int __devinit create_mpu401(snd_card_t * card, int devnum, unsigned long
port, MPU401_SHARE_HARDWARE,
irq, SA_INTERRUPT,
&rawmidi)) == 0) {
- mpu401_t *mpu = (mpu401_t *) rawmidi->private_data;
+ struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data;
mpu->open_input = mpu401_open;
mpu->open_output = mpu401_open;
mpu->close_input = mpu401_close;
@@ -919,7 +922,7 @@ static int __devinit create_mpu401(snd_card_t * card, int devnum, unsigned long
* Override for the CS4231 playback format function.
* The AD1845 has much simpler format and rate selection.
*/
-static void ad1845_playback_format(cs4231_t * chip, snd_pcm_hw_params_t * params, unsigned char format)
+static void ad1845_playback_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format)
{
unsigned long flags;
unsigned rate = params_rate(params);
@@ -955,7 +958,7 @@ static void ad1845_playback_format(cs4231_t * chip, snd_pcm_hw_params_t * params
* Override for the CS4231 capture format function.
* The AD1845 has much simpler format and rate selection.
*/
-static void ad1845_capture_format(cs4231_t * chip, snd_pcm_hw_params_t * params, unsigned char format)
+static void ad1845_capture_format(struct snd_cs4231 * chip, struct snd_pcm_hw_params *params, unsigned char format)
{
unsigned long flags;
unsigned rate = params_rate(params);
@@ -993,10 +996,10 @@ static void ad1845_capture_format(cs4231_t * chip, snd_pcm_hw_params_t * params,
* try to support at least some of the extra bits by overriding
* some of the CS4231 callback.
*/
-static int __devinit create_ad1845(snd_card_t * card, unsigned port, int irq, int dma1)
+static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq, int dma1)
{
register struct soundscape *sscape = get_card_soundscape(card);
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
int err;
#define CS4231_SHARE_HARDWARE (CS4231_HWSHARE_DMA1 | CS4231_HWSHARE_DMA2)
@@ -1009,7 +1012,7 @@ static int __devinit create_ad1845(snd_card_t * card, unsigned port, int irq, in
CS4231_HW_DETECT,
CS4231_HWSHARE_DMA1, &chip)) == 0) {
unsigned long flags;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
#define AD1845_FREQ_SEL_ENABLE 0x08
@@ -1080,48 +1083,18 @@ static int __devinit create_ad1845(snd_card_t * card, unsigned port, int irq, in
}
-struct params
-{
- int index;
- const char *id;
- unsigned port;
- int irq;
- int mpu_irq;
- int dma1;
-};
-
-
-static inline struct params*
-init_params(struct params *params,
- int index,
- const char *id,
- unsigned port,
- int irq,
- int mpu_irq,
- int dma1)
-{
- params->index = index;
- params->id = id;
- params->port = port;
- params->irq = irq;
- params->mpu_irq = mpu_irq;
- params->dma1 = (dma1 & 0x03);
-
- return params;
-}
-
-
/*
* Create an ALSA soundcard entry for the SoundScape, using
* the given list of port, IRQ and DMA resources.
*/
-static int __devinit create_sscape(const struct params *params, snd_card_t **rcardp)
+static int __devinit create_sscape(int dev, struct snd_card **rcardp)
{
- snd_card_t *card;
+ struct snd_card *card;
register struct soundscape *sscape;
register unsigned dma_cfg;
unsigned irq_cfg;
unsigned mpu_irq_cfg;
+ unsigned xport;
struct resource *io_res;
unsigned long flags;
int err;
@@ -1129,32 +1102,33 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
/*
* Check that the user didn't pass us garbage data ...
*/
- irq_cfg = get_irq_config(params->irq);
+ irq_cfg = get_irq_config(irq[dev]);
if (irq_cfg == INVALID_IRQ) {
- snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->irq);
+ snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
return -ENXIO;
}
- mpu_irq_cfg = get_irq_config(params->mpu_irq);
+ mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
if (mpu_irq_cfg == INVALID_IRQ) {
- printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->mpu_irq);
+ printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
return -ENXIO;
}
+ xport = port[dev];
/*
* Grab IO ports that we will need to probe so that we
* can detect and control this hardware ...
*/
- if ((io_res = request_region(params->port, 8, "SoundScape")) == NULL) {
- snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", params->port);
+ if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) {
+ snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
return -EBUSY;
}
/*
* Grab both DMA channels (OK, only one for now) ...
*/
- if ((err = request_dma(params->dma1, "SoundScape")) < 0) {
- snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", params->dma1);
+ if ((err = request_dma(dma[dev], "SoundScape")) < 0) {
+ snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
goto _release_region;
}
@@ -1162,7 +1136,8 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
* Create a new ALSA sound card entry, in anticipation
* of detecting our hardware ...
*/
- if ((card = snd_card_new(params->index, params->id, THIS_MODULE, sizeof(struct soundscape))) == NULL) {
+ if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
+ sizeof(struct soundscape))) == NULL) {
err = -ENOMEM;
goto _release_dma;
}
@@ -1171,7 +1146,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
spin_lock_init(&sscape->lock);
spin_lock_init(&sscape->fwlock);
sscape->io_res = io_res;
- sscape->io_base = params->port;
+ sscape->io_base = xport;
if (!detect_sscape(sscape)) {
printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
@@ -1180,7 +1155,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
}
printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
- sscape->io_base, params->irq, params->dma1);
+ sscape->io_base, irq[dev], dma[dev]);
/*
* Now create the hardware-specific device so that we can
@@ -1223,7 +1198,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
sscape_write_unsafe(sscape->io_base,
GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
sscape_write_unsafe(sscape->io_base,
- GA_CDCFG_REG, 0x09 | DMA_8BIT | (params->dma1 << 4) | (irq_cfg << 1));
+ GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1));
spin_unlock_irqrestore(&sscape->lock, flags);
@@ -1231,15 +1206,15 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
* We have now enabled the codec chip, and so we should
* detect the AD1845 device ...
*/
- if ((err = create_ad1845(card, CODEC_IO(params->port), params->irq, params->dma1)) < 0) {
+ if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) {
printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n",
- CODEC_IO(params->port), params->irq);
+ CODEC_IO(xport), irq[dev]);
goto _release_card;
}
#define MIDI_DEVNUM 0
- if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(params->port), params->mpu_irq)) < 0) {
+ if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) {
printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n",
- MPU401_IO(params->port));
+ MPU401_IO(xport));
goto _release_card;
}
@@ -1271,7 +1246,7 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
snd_card_free(card);
_release_dma:
- free_dma(params->dma1);
+ free_dma(dma[dev]);
_release_region:
release_and_free_resource(io_res);
@@ -1280,44 +1255,66 @@ static int __devinit create_sscape(const struct params *params, snd_card_t **rca
}
-static int sscape_cards __devinitdata;
-static struct params sscape_params[SNDRV_CARDS] __devinitdata;
+static int __init snd_sscape_probe(struct platform_device *pdev)
+{
+ int dev = pdev->id;
+ struct snd_card *card;
+ int ret;
+
+ dma[dev] &= 0x03;
+ ret = create_sscape(dev, &card);
+ if (ret < 0)
+ return ret;
+ snd_card_set_dev(card, &pdev->dev);
+ if ((ret = snd_card_register(card)) < 0) {
+ printk(KERN_ERR "sscape: Failed to register sound card\n");
+ return ret;
+ }
+ platform_set_drvdata(pdev, card);
+ return 0;
+}
+
+static int __devexit snd_sscape_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define SSCAPE_DRIVER "snd_sscape"
+
+static struct platform_driver snd_sscape_driver = {
+ .probe = snd_sscape_probe,
+ .remove = __devexit_p(snd_sscape_remove),
+ /* FIXME: suspend/resume */
+ .driver = {
+ .name = SSCAPE_DRIVER
+ },
+};
#ifdef CONFIG_PNP
static inline int __devinit get_next_autoindex(int i)
{
- while ((i < SNDRV_CARDS) && (port[i] != SNDRV_AUTO_PORT)) {
+ while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
++i;
- } /* while */
-
return i;
}
-static inline int __devinit is_port_known(unsigned io, struct params *params, int cards)
-{
- while (--cards >= 0) {
- if (params[cards].port == io)
- return 1;
- } /* while */
-
- return 0;
-}
-
static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
const struct pnp_card_device_id *pid)
{
- struct pnp_dev *dev;
static int idx = 0;
+ struct pnp_dev *dev;
+ struct snd_card *card;
int ret;
/*
* Allow this function to fail *quietly* if all the ISA PnP
* devices were configured using module parameters instead.
*/
- if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS) {
+ if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS)
return -ENOSPC;
- }
/*
* We have found a candidate ISA PnP card. Now we
@@ -1339,66 +1336,45 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
/*
* Check that we still have room for another sound card ...
*/
- if (sscape_cards >= SNDRV_CARDS) {
- printk(KERN_ERR "sscape: No room for another ALSA device\n");
- return -ENOSPC;
- }
-
- ret = -ENODEV;
-
dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
- if (dev) {
- struct params *this;
- if (!pnp_is_active(dev)) {
- if (pnp_activate_dev(dev) < 0) {
- printk(KERN_INFO "sscape: device is inactive\n");
- return -EBUSY;
- }
- }
- /*
- * Read the correct parameters off the ISA PnP bus ...
- */
- this = init_params(&sscape_params[sscape_cards],
- index[idx],
- id[idx],
- pnp_port_start(dev, 0),
- pnp_irq(dev, 0),
- pnp_irq(dev, 1),
- pnp_dma(dev, 0));
+ if (! dev)
+ return -ENODEV;
- /*
- * Do we know about this sound card already?
- */
- if ( !is_port_known(this->port, sscape_params, sscape_cards) ) {
- snd_card_t *card;
-
- ret = create_sscape(this, &card);
- 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;
+ if (!pnp_is_active(dev)) {
+ if (pnp_activate_dev(dev) < 0) {
+ printk(KERN_INFO "sscape: device is inactive\n");
+ return -EBUSY;
}
}
+ /*
+ * Read the correct parameters off the ISA PnP bus ...
+ */
+ port[idx] = pnp_port_start(dev, 0);
+ irq[idx] = pnp_irq(dev, 0);
+ mpu_irq[idx] = pnp_irq(dev, 1);
+ dma[idx] = pnp_dma(dev, 0) & 0x03;
+
+ ret = create_sscape(idx, &card);
+ 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);
+ ++idx;
+
return ret;
}
static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
+ snd_card_free(pnp_get_card_drvdata(pcard));
pnp_set_card_drvdata(pcard, NULL);
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
}
static struct pnp_card_driver sscape_pnpc_driver = {
@@ -1411,11 +1387,25 @@ static struct pnp_card_driver sscape_pnpc_driver = {
#endif /* CONFIG_PNP */
-static int __init sscape_manual_probe(struct params *params)
+static void __init_or_module sscape_unregister_all(void)
{
- int ret;
- unsigned i;
- snd_card_t *card;
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_card_driver(&sscape_pnpc_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_sscape_driver);
+}
+
+static int __init sscape_manual_probe(void)
+{
+ struct platform_device *device;
+ int i, ret;
+
+ ret = platform_driver_register(&snd_sscape_driver);
+ if (ret < 0)
+ return ret;
for (i = 0; i < SNDRV_CARDS; ++i) {
/*
@@ -1430,52 +1420,36 @@ static int __init sscape_manual_probe(struct params *params)
/*
* Make sure we were given ALL of the other parameters.
*/
- if ( (irq[i] == SNDRV_AUTO_IRQ) ||
- (mpu_irq[i] == SNDRV_AUTO_IRQ) ||
- (dma[i] == SNDRV_AUTO_DMA) ) {
+ if (irq[i] == SNDRV_AUTO_IRQ ||
+ mpu_irq[i] == SNDRV_AUTO_IRQ ||
+ dma[i] == SNDRV_AUTO_DMA) {
printk(KERN_INFO
"sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
- return -ENXIO;
+ ret = -ENXIO;
+ goto errout;
}
/*
* This cards looks OK ...
*/
- init_params(params, index[i], id[i], port[i], irq[i], mpu_irq[i], dma[i]);
-
- ret = create_sscape(params, &card);
- 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;
+ device = platform_device_register_simple(SSCAPE_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ ret = PTR_ERR(device);
+ goto errout;
}
-
- sscape_card[sscape_cards] = card;
- params++;
- sscape_cards++;
- } /* for */
-
+ platform_devices[i] = device;
+ }
return 0;
-}
+ errout:
+ sscape_unregister_all();
+ return ret;
+}
static void sscape_exit(void)
{
- unsigned i;
-
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&sscape_pnpc_driver);
-#endif
- for (i = 0; i < ARRAY_SIZE(sscape_card); ++i) {
- snd_card_free(sscape_card[i]);
- } /* for */
+ sscape_unregister_all();
}
@@ -1489,24 +1463,11 @@ static int __init sscape_init(void)
* of allocating cards, because the operator is
* S-P-E-L-L-I-N-G it out for us...
*/
- ret = sscape_manual_probe(sscape_params);
- if (ret < 0) {
- int i;
- for (i = 0; i < sscape_cards; ++i)
- snd_card_free(sscape_card[i]);
+ ret = sscape_manual_probe();
+ if (ret < 0)
return ret;
- }
-
-#ifdef CONFIG_PNP
- if (sscape_cards < SNDRV_CARDS) {
- ret = pnp_register_card_driver(&sscape_pnpc_driver);
- if (ret < 0) {
- sscape_exit();
- return ret;
- }
- }
-#endif
-
+ if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0)
+ pnp_registered = 1;
return 0;
}
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 1818f1013c3f..a6dcb2f970ca 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -23,6 +23,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
@@ -81,7 +83,9 @@ MODULE_PARM_DESC(fm_port, "FM port #.");
module_param_array(use_cs4232_midi, bool, NULL, 0444);
MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
-static snd_card_t *snd_wavefront_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct platform_device *platform_devices[SNDRV_CARDS];
+static int pnp_registered;
+
#ifdef CONFIG_PNP
@@ -240,7 +244,7 @@ snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *c
cs4232_mpu_irq[dev] = pnp_irq(pdev, 0);
}
- snd_printk ("CS4232 MPU: port=0x%lx, irq=%i\n",
+ snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n",
cs4232_mpu_port[dev],
cs4232_mpu_irq[dev]);
}
@@ -279,12 +283,12 @@ static irqreturn_t snd_wavefront_ics2115_interrupt(int irq,
return IRQ_HANDLED;
}
-static snd_hwdep_t * __devinit
-snd_wavefront_new_synth (snd_card_t *card,
+static struct snd_hwdep * __devinit
+snd_wavefront_new_synth (struct snd_card *card,
int hw_dev,
snd_wavefront_card_t *acard)
{
- snd_hwdep_t *wavefront_synth;
+ struct snd_hwdep *wavefront_synth;
if (snd_wavefront_detect (acard) < 0) {
return NULL;
@@ -305,17 +309,17 @@ snd_wavefront_new_synth (snd_card_t *card,
return wavefront_synth;
}
-static snd_hwdep_t * __devinit
-snd_wavefront_new_fx (snd_card_t *card,
+static struct snd_hwdep * __devinit
+snd_wavefront_new_fx (struct snd_card *card,
int hw_dev,
snd_wavefront_card_t *acard,
unsigned long port)
{
- snd_hwdep_t *fx_processor;
+ struct snd_hwdep *fx_processor;
if (snd_wavefront_fx_start (&acard->wavefront)) {
- snd_printk ("cannot initialize YSS225 FX processor");
+ snd_printk (KERN_ERR "cannot initialize YSS225 FX processor");
return NULL;
}
@@ -332,22 +336,22 @@ snd_wavefront_new_fx (snd_card_t *card,
static snd_wavefront_mpu_id internal_id = internal_mpu;
static snd_wavefront_mpu_id external_id = external_mpu;
-static snd_rawmidi_t * __devinit
-snd_wavefront_new_midi (snd_card_t *card,
+static struct snd_rawmidi *__devinit
+snd_wavefront_new_midi (struct snd_card *card,
int midi_dev,
snd_wavefront_card_t *acard,
unsigned long port,
snd_wavefront_mpu_id mpu)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
static int first = 1;
if (first) {
first = 0;
acard->wavefront.midi.base = port;
if (snd_wavefront_midi_start (acard)) {
- snd_printk ("cannot initialize MIDI interface\n");
+ snd_printk (KERN_ERR "cannot initialize MIDI interface\n");
return NULL;
}
}
@@ -374,7 +378,7 @@ snd_wavefront_new_midi (snd_card_t *card,
}
static void
-snd_wavefront_free(snd_card_t *card)
+snd_wavefront_free(struct snd_card *card)
{
snd_wavefront_card_t *acard = (snd_wavefront_card_t *)card->private_data;
@@ -385,42 +389,17 @@ snd_wavefront_free(snd_card_t *card)
}
}
-static int __devinit
-snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
- const struct pnp_card_device_id *pid)
+static struct snd_card *snd_wavefront_card_new(int dev)
{
- snd_card_t *card;
+ struct snd_card *card;
snd_wavefront_card_t *acard;
- cs4231_t *chip;
- snd_hwdep_t *wavefront_synth;
- snd_rawmidi_t *ics2115_internal_rmidi = NULL;
- snd_rawmidi_t *ics2115_external_rmidi = NULL;
- snd_hwdep_t *fx_processor;
- int hw_dev = 0, midi_dev = 0, err;
-#ifdef CONFIG_PNP
- if (!isapnp[dev]) {
-#endif
- if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify CS4232 port\n");
- return -EINVAL;
- }
- if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk("specify ICS2115 port\n");
- return -ENODEV;
- }
-#ifdef CONFIG_PNP
- }
-#endif
- card = snd_card_new (index[dev],
- id[dev],
- THIS_MODULE,
+ card = snd_card_new (index[dev], id[dev], THIS_MODULE,
sizeof(snd_wavefront_card_t));
+ if (card == NULL)
+ return NULL;
- if (card == NULL) {
- return -ENOMEM;
- }
- acard = (snd_wavefront_card_t *)card->private_data;
+ acard = card->private_data;
acard->wavefront.irq = -1;
spin_lock_init(&acard->wavefront.irq_lock);
init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
@@ -428,18 +407,19 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
spin_lock_init(&acard->wavefront.midi.virtual);
card->private_free = snd_wavefront_free;
-#ifdef CONFIG_PNP
- if (isapnp[dev]) {
- if (snd_wavefront_pnp (dev, acard, pcard, pid) < 0) {
- if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
- snd_printk ("isapnp detection failed\n");
- snd_card_free (card);
- return -ENODEV;
- }
- }
- snd_card_set_dev(card, &pcard->card->dev);
- }
-#endif /* CONFIG_PNP */
+ return card;
+}
+
+static int __devinit
+snd_wavefront_probe (struct snd_card *card, int dev)
+{
+ snd_wavefront_card_t *acard = card->private_data;
+ struct snd_cs4231 *chip;
+ struct snd_hwdep *wavefront_synth;
+ struct snd_rawmidi *ics2115_internal_rmidi = NULL;
+ struct snd_rawmidi *ics2115_external_rmidi = NULL;
+ struct snd_hwdep *fx_processor;
+ int hw_dev = 0, midi_dev = 0, err;
/* --------- PCM --------------- */
@@ -450,52 +430,46 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
dma1[dev],
dma2[dev],
CS4231_HW_DETECT, 0, &chip)) < 0) {
- snd_card_free(card);
- snd_printk ("can't allocate CS4231 device\n");
+ snd_printk (KERN_ERR "can't allocate CS4231 device\n");
return err;
}
- if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0) {
- snd_card_free(card);
+ if ((err = snd_cs4231_pcm (chip, 0, NULL)) < 0)
return err;
- }
- if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0) {
- snd_card_free(card);
+
+ if ((err = snd_cs4231_timer (chip, 0, NULL)) < 0)
return err;
- }
/* ---------- OPL3 synth --------- */
if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
if ((err = snd_opl3_create(card,
fm_port[dev],
fm_port[dev] + 2,
OPL3_HW_OPL3_CS,
0, &opl3)) < 0) {
- snd_printk ("can't allocate or detect OPL3 synth\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't allocate or detect OPL3 synth\n");
return err;
}
- if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0) {
- snd_card_free(card);
+ if ((err = snd_opl3_hwdep_new(opl3, hw_dev, 1, NULL)) < 0)
return err;
- }
hw_dev++;
}
/* ------- ICS2115 Wavetable synth ------- */
- if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16, "ICS2115")) == NULL) {
- snd_printk("unable to grab ICS2115 i/o region 0x%lx-0x%lx\n", ics2115_port[dev], ics2115_port[dev] + 16 - 1);
- snd_card_free(card);
+ if ((acard->wavefront.res_base = request_region(ics2115_port[dev], 16,
+ "ICS2115")) == NULL) {
+ snd_printk(KERN_ERR "unable to grab ICS2115 i/o region 0x%lx-0x%lx\n",
+ ics2115_port[dev], ics2115_port[dev] + 16 - 1);
return -EBUSY;
}
- if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, SA_INTERRUPT, "ICS2115", (void *)acard)) {
- snd_printk("unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
- snd_card_free(card);
+ if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
+ SA_INTERRUPT, "ICS2115", acard)) {
+ snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
return -EBUSY;
}
@@ -503,8 +477,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
acard->wavefront.base = ics2115_port[dev];
if ((wavefront_synth = snd_wavefront_new_synth (card, hw_dev, acard)) == NULL) {
- snd_printk ("can't create WaveFront synth device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't create WaveFront synth device\n");
return -ENOMEM;
}
@@ -515,8 +488,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
/* --------- Mixer ------------ */
if ((err = snd_cs4231_mixer(chip)) < 0) {
- snd_printk ("can't allocate mixer device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't allocate mixer device\n");
return err;
}
@@ -528,8 +500,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
cs4232_mpu_irq[dev],
SA_INTERRUPT,
NULL)) < 0) {
- snd_printk ("can't allocate CS4232 MPU-401 device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
return err;
}
midi_dev++;
@@ -545,8 +516,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
ics2115_port[dev],
internal_mpu);
if (ics2115_internal_rmidi == NULL) {
- snd_printk ("can't setup ICS2115 internal MIDI device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't setup ICS2115 internal MIDI device\n");
return -ENOMEM;
}
midi_dev++;
@@ -562,8 +532,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
ics2115_port[dev],
external_mpu);
if (ics2115_external_rmidi == NULL) {
- snd_printk ("can't setup ICS2115 external MIDI device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't setup ICS2115 external MIDI device\n");
return -ENOMEM;
}
midi_dev++;
@@ -577,8 +546,7 @@ snd_wavefront_probe (int dev, struct pnp_card_link *pcard,
acard,
ics2115_port[dev]);
if (fx_processor == NULL) {
- snd_printk ("can't setup FX device\n");
- snd_card_free(card);
+ snd_printk (KERN_ERR "can't setup FX device\n");
return -ENOMEM;
}
@@ -619,49 +587,97 @@ 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;
+ return snd_card_register(card);
+}
+
+static int __init snd_wavefront_nonpnp_probe(struct platform_device *pdev)
+{
+ int dev = pdev->id;
+ struct snd_card *card;
+ int err;
+
+ if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk("specify CS4232 port\n");
+ return -EINVAL;
+ }
+ if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk("specify ICS2115 port\n");
+ return -ENODEV;
}
- if ((err = snd_card_register(card)) < 0) {
+ card = snd_wavefront_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+ snd_card_set_dev(card, &pdev->dev);
+ if ((err = snd_wavefront_probe(card, dev)) < 0) {
snd_card_free(card);
return err;
}
- if (pcard)
- pnp_set_card_drvdata(pcard, card);
- else
- snd_wavefront_legacy[dev] = card;
+
+ platform_set_drvdata(pdev, card);
return 0;
-}
+}
+
+static int __devexit snd_wavefront_nonpnp_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#define WAVEFRONT_DRIVER "snd_wavefront"
+
+static struct platform_driver snd_wavefront_driver = {
+ .probe = snd_wavefront_nonpnp_probe,
+ .remove = __devexit_p(snd_wavefront_nonpnp_remove),
+ /* FIXME: suspend, resume */
+ .driver = {
+ .name = WAVEFRONT_DRIVER
+ },
+};
+
#ifdef CONFIG_PNP
-static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *card,
- const struct pnp_card_device_id *id)
+static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
+ const struct pnp_card_device_id *pid)
{
- static int dev;
- int res;
-
- for ( ; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev] || !isapnp[dev])
- continue;
- res = snd_wavefront_probe(dev, card, id);
- if (res < 0)
- return res;
- dev++;
- return 0;
- }
-
- return -ENODEV;
+ static int dev;
+ struct snd_card *card;
+ int res;
+
+ for ( ; dev < SNDRV_CARDS; dev++) {
+ if (enable[dev] && isapnp[dev])
+ break;
+ }
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+
+ card = snd_wavefront_card_new(dev);
+ if (! card)
+ return -ENOMEM;
+
+ if (snd_wavefront_pnp (dev, card->private_data, pcard, pid) < 0) {
+ if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
+ snd_printk (KERN_ERR "isapnp detection failed\n");
+ snd_card_free (card);
+ return -ENODEV;
+ }
+ }
+ snd_card_set_dev(card, &pcard->card->dev);
+
+ if ((res = snd_wavefront_probe(card, dev)) < 0)
+ return res;
+
+ pnp_set_card_drvdata(pcard, card);
+ dev++;
+ return 0;
}
static void __devexit snd_wavefront_pnp_remove(struct pnp_card_link * pcard)
{
- snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
-
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
}
static struct pnp_card_driver wavefront_pnpc_driver = {
@@ -670,48 +686,68 @@ static struct pnp_card_driver wavefront_pnpc_driver = {
.id_table = snd_wavefront_pnpids,
.probe = snd_wavefront_pnp_detect,
.remove = __devexit_p(snd_wavefront_pnp_remove),
+ /* FIXME: suspend,resume */
};
#endif /* CONFIG_PNP */
+static void __init_or_module snd_wavefront_unregister_all(void)
+{
+ int i;
+
+ if (pnp_registered)
+ pnp_unregister_card_driver(&wavefront_pnpc_driver);
+ for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
+ platform_device_unregister(platform_devices[i]);
+ platform_driver_unregister(&snd_wavefront_driver);
+}
+
static int __init alsa_card_wavefront_init(void)
{
- int cards = 0;
- int dev;
- for (dev = 0; dev < SNDRV_CARDS; dev++) {
- if (!enable[dev])
- continue;
+ int i, err, cards = 0;
+
+ if ((err = platform_driver_register(&snd_wavefront_driver)) < 0)
+ return err;
+
+ for (i = 0; i < SNDRV_CARDS && enable[i]; i++) {
+ struct platform_device *device;
#ifdef CONFIG_PNP
- if (isapnp[dev])
+ if (isapnp[i])
continue;
#endif
- if (snd_wavefront_probe(dev, NULL, NULL) >= 0)
- cards++;
+ device = platform_device_register_simple(WAVEFRONT_DRIVER,
+ i, NULL, 0);
+ if (IS_ERR(device)) {
+ err = PTR_ERR(device);
+ goto errout;
+ }
+ platform_devices[i] = device;
+ cards++;
}
-#ifdef CONFIG_PNP
- cards += pnp_register_card_driver(&wavefront_pnpc_driver);
-#endif
+
+ i = pnp_register_card_driver(&wavefront_pnpc_driver);
+ if (i >= 0) {
+ pnp_registered = 1;
+ cards += i;
+ }
+
if (!cards) {
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&wavefront_pnpc_driver);
-#endif
#ifdef MODULE
printk (KERN_ERR "No WaveFront cards found or devices busy\n");
#endif
- return -ENODEV;
+ err = -ENODEV;
+ goto errout;
}
return 0;
+
+ errout:
+ snd_wavefront_unregister_all();
+ return err;
}
static void __exit alsa_card_wavefront_exit(void)
{
- int idx;
-
-#ifdef CONFIG_PNP
- pnp_unregister_card_driver(&wavefront_pnpc_driver);
-#endif
- for (idx = 0; idx < SNDRV_CARDS; idx++)
- snd_card_free(snd_wavefront_legacy[idx]);
+ snd_wavefront_unregister_all();
}
module_init(alsa_card_wavefront_init)
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 32379688eed4..180661c5ffdc 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -460,7 +460,7 @@ snd_wavefront_fx_detect (snd_wavefront_t *dev)
}
int
-snd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_fx_open (struct snd_hwdep *hw, struct file *file)
{
if (!try_module_get(hw->card->module))
@@ -470,7 +470,7 @@ snd_wavefront_fx_open (snd_hwdep_t *hw, struct file *file)
}
int
-snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_fx_release (struct snd_hwdep *hw, struct file *file)
{
module_put(hw->card->module);
@@ -478,11 +478,11 @@ snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
}
int
-snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
+snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
unsigned int cmd, unsigned long arg)
{
- snd_card_t *card;
+ struct snd_card *card;
snd_wavefront_card_t *acard;
snd_wavefront_t *dev;
wavefront_fx_info r;
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 6f51d64fb565..15888ba2169b 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -91,10 +91,10 @@ write_data (snd_wavefront_midi_t *midi, unsigned char byte)
}
static snd_wavefront_midi_t *
-get_wavefront_midi (snd_rawmidi_substream_t *substream)
+get_wavefront_midi (struct snd_rawmidi_substream *substream)
{
- snd_card_t *card;
+ struct snd_card *card;
snd_wavefront_card_t *acard;
if (substream == NULL || substream->rmidi == NULL)
@@ -230,7 +230,7 @@ static void snd_wavefront_midi_output_write(snd_wavefront_card_t *card)
}
}
-static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_wavefront_midi_input_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -252,7 +252,7 @@ static int snd_wavefront_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_wavefront_midi_output_open(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -274,7 +274,7 @@ static int snd_wavefront_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_wavefront_midi_input_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -295,7 +295,7 @@ static int snd_wavefront_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_wavefront_midi_output_close(struct snd_rawmidi_substream *substream)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -315,7 +315,7 @@ static int snd_wavefront_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_wavefront_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_wavefront_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -355,7 +355,7 @@ static void snd_wavefront_midi_output_timer(unsigned long data)
snd_wavefront_midi_output_write(card);
}
-static void snd_wavefront_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_wavefront_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
@@ -401,7 +401,7 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
{
unsigned long flags;
snd_wavefront_midi_t *midi;
- static snd_rawmidi_substream_t *substream = NULL;
+ static struct snd_rawmidi_substream *substream = NULL;
static int mpu = external_mpu;
int max = 128;
unsigned char byte;
@@ -554,14 +554,14 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card)
return 0;
}
-snd_rawmidi_ops_t snd_wavefront_midi_output =
+struct snd_rawmidi_ops snd_wavefront_midi_output =
{
.open = snd_wavefront_midi_output_open,
.close = snd_wavefront_midi_output_close,
.trigger = snd_wavefront_midi_output_trigger,
};
-snd_rawmidi_ops_t snd_wavefront_midi_input =
+struct snd_rawmidi_ops snd_wavefront_midi_input =
{
.open = snd_wavefront_midi_input_open,
.close = snd_wavefront_midi_input_close,
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index abd79b781412..ed81eec6e732 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -115,18 +115,11 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
#ifdef WF_DEBUG
-#if defined(NEW_MACRO_VARARGS) || __GNUC__ >= 3
#define DPRINT(cond, ...) \
if ((dev->debug & (cond)) == (cond)) { \
snd_printk (__VA_ARGS__); \
}
#else
-#define DPRINT(cond, args...) \
- if ((dev->debug & (cond)) == (cond)) { \
- snd_printk (args); \
- }
-#endif
-#else
#define DPRINT(cond, args...)
#endif /* WF_DEBUG */
@@ -144,13 +137,13 @@ MODULE_PARM_DESC(osrun_time, "how many seconds to wait for the ICS2115 OS");
static int wavefront_delete_sample (snd_wavefront_t *, int sampnum);
static int wavefront_find_free_sample (snd_wavefront_t *);
-typedef struct {
+struct wavefront_command {
int cmd;
char *action;
unsigned int read_cnt;
unsigned int write_cnt;
int need_ack;
-} wavefront_command;
+};
static struct {
int errno;
@@ -170,7 +163,7 @@ static struct {
#define NEEDS_ACK 1
-static wavefront_command wavefront_commands[] = {
+static struct wavefront_command wavefront_commands[] = {
{ WFC_SET_SYNTHVOL, "set synthesizer volume", 0, 1, NEEDS_ACK },
{ WFC_GET_SYNTHVOL, "get synthesizer volume", 1, 0, 0},
{ WFC_SET_NVOICES, "set number of voices", 0, 1, NEEDS_ACK },
@@ -249,7 +242,7 @@ wavefront_errorstr (int errnum)
return "Unknown WaveFront error";
}
-static wavefront_command *
+static struct wavefront_command *
wavefront_get_command (int cmd)
{
@@ -261,7 +254,7 @@ wavefront_get_command (int cmd)
}
}
- return (wavefront_command *) 0;
+ return NULL;
}
static inline int
@@ -345,9 +338,9 @@ snd_wavefront_cmd (snd_wavefront_t *dev,
int ack;
unsigned int i;
int c;
- wavefront_command *wfcmd;
+ struct wavefront_command *wfcmd;
- if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
+ if ((wfcmd = wavefront_get_command (cmd)) == NULL) {
snd_printk ("command 0x%x not supported.\n",
cmd);
return 1;
@@ -1625,7 +1618,7 @@ wavefront_synth_control (snd_wavefront_card_t *acard,
}
int
-snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file)
{
if (!try_module_get(hw->card->module))
@@ -1635,7 +1628,7 @@ snd_wavefront_synth_open (snd_hwdep_t *hw, struct file *file)
}
int
-snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
+snd_wavefront_synth_release (struct snd_hwdep *hw, struct file *file)
{
module_put(hw->card->module);
@@ -1643,18 +1636,18 @@ snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
}
int
-snd_wavefront_synth_ioctl (snd_hwdep_t *hw, struct file *file,
+snd_wavefront_synth_ioctl (struct snd_hwdep *hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
- snd_card_t *card;
+ struct snd_card *card;
snd_wavefront_t *dev;
snd_wavefront_card_t *acard;
wavefront_control *wc;
void __user *argp = (void __user *)arg;
int err;
- card = (snd_card_t *) hw->card;
+ card = (struct snd_card *) hw->card;
snd_assert(card != NULL, return -ENODEV);
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
index 2433b7727404..531f8ba96a71 100644
--- a/sound/mips/Kconfig
+++ b/sound/mips/Kconfig
@@ -8,7 +8,6 @@ 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 d08a42b24b1f..6d8f8b3eabd0 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -50,12 +50,7 @@
MODULE_AUTHOR("Charles Eidsness <charles@cooper-street.com>");
MODULE_DESCRIPTION("Au1000 AC'97 ALSA Driver");
MODULE_LICENSE("GPL");
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
MODULE_SUPPORTED_DEVICE("{{AMD,Au1000 AC'97}}");
-#else
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{AMD,Au1000 AC'97}}");
-#endif
#define PLAYBACK 0
#define CAPTURE 1
@@ -68,18 +63,14 @@ MODULE_DEVICES("{{AMD,Au1000 AC'97}}");
#define READ_WAIT 2
#define RW_DONE 3
-DECLARE_WAIT_QUEUE_HEAD(ac97_command_wq);
-
-typedef struct au1000_period au1000_period_t;
struct au1000_period
{
u32 start;
u32 relative_end; /*realtive to start of buffer*/
- au1000_period_t * next;
+ struct au1000_period * next;
};
/*Au1000 AC97 Port Control Reisters*/
-typedef struct au1000_ac97_reg au1000_ac97_reg_t;
struct au1000_ac97_reg {
u32 volatile config;
u32 volatile status;
@@ -88,32 +79,30 @@ struct au1000_ac97_reg {
u32 volatile cntrl;
};
-typedef struct audio_stream audio_stream_t;
struct audio_stream {
- snd_pcm_substream_t * substream;
+ struct snd_pcm_substream *substream;
int dma;
spinlock_t dma_lock;
- au1000_period_t * buffer;
- unsigned long period_size;
+ struct au1000_period * buffer;
+ unsigned int period_size;
+ unsigned int periods;
};
-typedef struct snd_card_au1000 {
- snd_card_t *card;
- au1000_ac97_reg_t volatile *ac97_ioport;
+struct snd_au1000 {
+ struct snd_card *card;
+ struct au1000_ac97_reg volatile *ac97_ioport;
struct resource *ac97_res_port;
spinlock_t ac97_lock;
- ac97_t *ac97;
-
- snd_pcm_t *pcm;
- audio_stream_t *stream[2]; /* playback & capture */
-} au1000_t;
+ struct snd_ac97 *ac97;
-static au1000_t *au1000 = NULL;
+ struct snd_pcm *pcm;
+ struct audio_stream *stream[2]; /* playback & capture */
+};
/*--------------------------- Local Functions --------------------------------*/
static void
-au1000_set_ac97_xmit_slots(long xmit_slots)
+au1000_set_ac97_xmit_slots(struct snd_au1000 *au1000, long xmit_slots)
{
u32 volatile ac97_config;
@@ -126,7 +115,7 @@ au1000_set_ac97_xmit_slots(long xmit_slots)
}
static void
-au1000_set_ac97_recv_slots(long recv_slots)
+au1000_set_ac97_recv_slots(struct snd_au1000 *au1000, long recv_slots)
{
u32 volatile ac97_config;
@@ -140,86 +129,99 @@ au1000_set_ac97_recv_slots(long recv_slots)
static void
-au1000_dma_stop(audio_stream_t *stream)
+au1000_release_dma_link(struct audio_stream *stream)
{
- unsigned long flags;
- au1000_period_t * pointer;
- au1000_period_t * pointer_next;
+ struct au1000_period * pointer;
+ struct au1000_period * pointer_next;
+
+ stream->period_size = 0;
+ stream->periods = 0;
+ pointer = stream->buffer;
+ if (! pointer)
+ return;
+ do {
+ pointer_next = pointer->next;
+ kfree(pointer);
+ pointer = pointer_next;
+ } while (pointer != stream->buffer);
+ stream->buffer = NULL;
+}
+
+static int
+au1000_setup_dma_link(struct audio_stream *stream, unsigned int period_bytes,
+ unsigned int periods)
+{
+ struct snd_pcm_substream *substream = stream->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned long dma_start;
+ int i;
+
+ dma_start = virt_to_phys(runtime->dma_area);
- if (stream->buffer != NULL) {
- spin_lock_irqsave(&stream->dma_lock, flags);
- disable_dma(stream->dma);
- spin_unlock_irqrestore(&stream->dma_lock, flags);
+ if (stream->period_size == period_bytes &&
+ stream->periods == periods)
+ return 0; /* not changed */
- pointer = stream->buffer;
- pointer_next = stream->buffer->next;
+ au1000_release_dma_link(stream);
- do {
- kfree(pointer);
- pointer = pointer_next;
- pointer_next = pointer->next;
- } while (pointer != stream->buffer);
+ stream->period_size = period_bytes;
+ stream->periods = periods;
- stream->buffer = NULL;
+ stream->buffer = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
+ if (! stream->buffer)
+ return -ENOMEM;
+ pointer = stream->buffer;
+ for (i = 0; i < periods; i++) {
+ pointer->start = (u32)(dma_start + (i * period_bytes));
+ pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
+ if (i < periods - 1) {
+ pointer->next = kmalloc(sizeof(struct au1000_period), GFP_KERNEL);
+ if (! pointer->next) {
+ au1000_release_dma_link(stream);
+ return -ENOMEM;
+ }
+ pointer = pointer->next;
+ }
}
+ pointer->next = stream->buffer;
+ return 0;
}
static void
-au1000_dma_start(audio_stream_t *stream)
+au1000_dma_stop(struct audio_stream *stream)
{
- snd_pcm_substream_t *substream = stream->substream;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_assert(stream->buffer, return);
+ disable_dma(stream->dma);
+}
- unsigned long flags, dma_start;
- int i;
- au1000_period_t * pointer;
-
- if (stream->buffer == NULL) {
- dma_start = virt_to_phys(runtime->dma_area);
-
- stream->period_size = frames_to_bytes(runtime,
- runtime->period_size);
- stream->buffer = kmalloc(sizeof(au1000_period_t), GFP_KERNEL);
- pointer = stream->buffer;
- for (i = 0 ; i < runtime->periods ; i++) {
- pointer->start = (u32)(dma_start +
- (i * stream->period_size));
- pointer->relative_end = (u32)
- (((i+1) * stream->period_size) - 0x1);
- if ( i < runtime->periods - 1) {
- pointer->next = kmalloc(sizeof(au1000_period_t)
- , GFP_KERNEL);
- pointer = pointer->next;
- }
- }
- pointer->next = stream->buffer;
-
- spin_lock_irqsave(&stream->dma_lock, flags);
- init_dma(stream->dma);
- if (get_dma_active_buffer(stream->dma) == 0) {
- clear_dma_done0(stream->dma);
- set_dma_addr0(stream->dma, stream->buffer->start);
- set_dma_count0(stream->dma, stream->period_size >> 1);
- set_dma_addr1(stream->dma, stream->buffer->next->start);
- set_dma_count1(stream->dma, stream->period_size >> 1);
- } else {
- clear_dma_done1(stream->dma);
- set_dma_addr1(stream->dma, stream->buffer->start);
- set_dma_count1(stream->dma, stream->period_size >> 1);
- set_dma_addr0(stream->dma, stream->buffer->next->start);
- set_dma_count0(stream->dma, stream->period_size >> 1);
- }
- enable_dma_buffers(stream->dma);
- start_dma(stream->dma);
- spin_unlock_irqrestore(&stream->dma_lock, flags);
+static void
+au1000_dma_start(struct audio_stream *stream)
+{
+ snd_assert(stream->buffer, return);
+
+ init_dma(stream->dma);
+ if (get_dma_active_buffer(stream->dma) == 0) {
+ clear_dma_done0(stream->dma);
+ set_dma_addr0(stream->dma, stream->buffer->start);
+ set_dma_count0(stream->dma, stream->period_size >> 1);
+ set_dma_addr1(stream->dma, stream->buffer->next->start);
+ set_dma_count1(stream->dma, stream->period_size >> 1);
+ } else {
+ clear_dma_done1(stream->dma);
+ set_dma_addr1(stream->dma, stream->buffer->start);
+ set_dma_count1(stream->dma, stream->period_size >> 1);
+ set_dma_addr0(stream->dma, stream->buffer->next->start);
+ set_dma_count0(stream->dma, stream->period_size >> 1);
}
+ enable_dma_buffers(stream->dma);
+ start_dma(stream->dma);
}
static irqreturn_t
au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- audio_stream_t *stream = (audio_stream_t *) dev_id;
- snd_pcm_substream_t *substream = stream->substream;
+ struct audio_stream *stream = (struct audio_stream *) dev_id;
+ struct snd_pcm_substream *substream = stream->substream;
spin_lock(&stream->dma_lock);
switch (get_dma_buffer_done(stream->dma)) {
@@ -238,11 +240,9 @@ au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
enable_dma_buffer1(stream->dma);
break;
case (DMA_D0 | DMA_D1):
- spin_unlock(&stream->dma_lock);
printk(KERN_ERR "DMA %d missed interrupt.\n",stream->dma);
au1000_dma_stop(stream);
au1000_dma_start(stream);
- spin_lock(&stream->dma_lock);
break;
case (~DMA_D0 & ~DMA_D1):
printk(KERN_ERR "DMA %d empty irq.\n",stream->dma);
@@ -255,13 +255,13 @@ au1000_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*-------------------------- PCM Audio Streams -------------------------------*/
static unsigned int rates[] = {8000, 11025, 16000, 22050};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = sizeof(rates) / sizeof(rates[0]),
.list = rates,
.mask = 0,
};
-static snd_pcm_hardware_t snd_au1000 =
+static struct snd_pcm_hardware snd_au1000_hw =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED | \
SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
@@ -281,88 +281,108 @@ static snd_pcm_hardware_t snd_au1000 =
};
static int
-snd_au1000_playback_open(snd_pcm_substream_t * substream)
+snd_au1000_playback_open(struct snd_pcm_substream *substream)
{
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+
au1000->stream[PLAYBACK]->substream = substream;
au1000->stream[PLAYBACK]->buffer = NULL;
substream->private_data = au1000->stream[PLAYBACK];
- substream->runtime->hw = snd_au1000;
+ substream->runtime->hw = snd_au1000_hw;
return (snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
}
static int
-snd_au1000_capture_open(snd_pcm_substream_t * substream)
+snd_au1000_capture_open(struct snd_pcm_substream *substream)
{
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+
au1000->stream[CAPTURE]->substream = substream;
au1000->stream[CAPTURE]->buffer = NULL;
substream->private_data = au1000->stream[CAPTURE];
- substream->runtime->hw = snd_au1000;
+ substream->runtime->hw = snd_au1000_hw;
return (snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates) < 0);
-
}
static int
-snd_au1000_playback_close(snd_pcm_substream_t * substream)
+snd_au1000_playback_close(struct snd_pcm_substream *substream)
{
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+
au1000->stream[PLAYBACK]->substream = NULL;
return 0;
}
static int
-snd_au1000_capture_close(snd_pcm_substream_t * substream)
+snd_au1000_capture_close(struct snd_pcm_substream *substream)
{
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+
au1000->stream[CAPTURE]->substream = NULL;
return 0;
}
static int
-snd_au1000_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+snd_au1000_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- return snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
+ struct audio_stream *stream = substream->private_data;
+ int err;
+
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
+ return err;
+ return au1000_setup_dma_link(stream,
+ params_period_bytes(hw_params),
+ params_periods(hw_params));
}
static int
-snd_au1000_hw_free(snd_pcm_substream_t * substream)
+snd_au1000_hw_free(struct snd_pcm_substream *substream)
{
+ struct audio_stream *stream = substream->private_data;
+ au1000_release_dma_link(stream);
return snd_pcm_lib_free_pages(substream);
}
static int
-snd_au1000_playback_prepare(snd_pcm_substream_t * substream)
+snd_au1000_playback_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->channels == 1 )
- au1000_set_ac97_xmit_slots(AC97_SLOT_4);
+ if (runtime->channels == 1)
+ au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_4);
else
- au1000_set_ac97_xmit_slots(AC97_SLOT_3 | AC97_SLOT_4);
+ au1000_set_ac97_xmit_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
snd_ac97_set_rate(au1000->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
return 0;
}
static int
-snd_au1000_capture_prepare(snd_pcm_substream_t * substream)
+snd_au1000_capture_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_au1000 *au1000 = substream->pcm->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->channels == 1 )
- au1000_set_ac97_recv_slots(AC97_SLOT_4);
+ if (runtime->channels == 1)
+ au1000_set_ac97_recv_slots(au1000, AC97_SLOT_4);
else
- au1000_set_ac97_recv_slots(AC97_SLOT_3 | AC97_SLOT_4);
+ au1000_set_ac97_recv_slots(au1000, AC97_SLOT_3 | AC97_SLOT_4);
snd_ac97_set_rate(au1000->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
return 0;
}
static int
-snd_au1000_trigger(snd_pcm_substream_t * substream, int cmd)
+snd_au1000_trigger(struct snd_pcm_substream *substream, int cmd)
{
- audio_stream_t *stream = substream->private_data;
+ struct audio_stream *stream = substream->private_data;
int err = 0;
+ spin_lock(&stream->dma_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
au1000_dma_start(stream);
@@ -374,27 +394,27 @@ snd_au1000_trigger(snd_pcm_substream_t * substream, int cmd)
err = -EINVAL;
break;
}
+ spin_unlock(&stream->dma_lock);
return err;
}
static snd_pcm_uframes_t
-snd_au1000_pointer(snd_pcm_substream_t * substream)
+snd_au1000_pointer(struct snd_pcm_substream *substream)
{
- audio_stream_t *stream = substream->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
- unsigned long flags;
+ struct audio_stream *stream = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
long location;
- spin_lock_irqsave(&stream->dma_lock, flags);
+ spin_lock(&stream->dma_lock);
location = get_dma_residue(stream->dma);
- spin_unlock_irqrestore(&stream->dma_lock, flags);
+ spin_unlock(&stream->dma_lock);
location = stream->buffer->relative_end - location;
if (location == -1)
location = 0;
return bytes_to_frames(runtime,location);
}
-static snd_pcm_ops_t snd_card_au1000_playback_ops = {
+static struct snd_pcm_ops snd_card_au1000_playback_ops = {
.open = snd_au1000_playback_open,
.close = snd_au1000_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -405,7 +425,7 @@ static snd_pcm_ops_t snd_card_au1000_playback_ops = {
.pointer = snd_au1000_pointer,
};
-static snd_pcm_ops_t snd_card_au1000_capture_ops = {
+static struct snd_pcm_ops snd_card_au1000_capture_ops = {
.open = snd_au1000_capture_open,
.close = snd_au1000_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -417,9 +437,9 @@ static snd_pcm_ops_t snd_card_au1000_capture_ops = {
};
static int __devinit
-snd_au1000_pcm_new(void)
+snd_au1000_pcm_new(struct snd_au1000 *au1000)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
unsigned long flags;
@@ -438,6 +458,9 @@ snd_au1000_pcm_new(void)
pcm->info_flags = 0;
strcpy(pcm->name, "Au1000 AC97 PCM");
+ spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
+ spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
+
flags = claim_dma_lock();
if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
"AC97 TX", au1000_dma_interrupt, SA_INTERRUPT,
@@ -457,8 +480,6 @@ snd_au1000_pcm_new(void)
set_dma_mode(au1000->stream[CAPTURE]->dma,
get_dma_mode(au1000->stream[CAPTURE]->dma) & ~DMA_NC);
release_dma_lock(flags);
- spin_lock_init(&au1000->stream[PLAYBACK]->dma_lock);
- spin_lock_init(&au1000->stream[CAPTURE]->dma_lock);
au1000->pcm = pcm;
return 0;
}
@@ -467,11 +488,13 @@ snd_au1000_pcm_new(void)
/*-------------------------- AC97 CODEC Control ------------------------------*/
static unsigned short
-snd_au1000_ac97_read(ac97_t *ac97, unsigned short reg)
+snd_au1000_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
+ struct snd_au1000 *au1000 = ac97->private_data;
u32 volatile cmd;
u16 volatile data;
int i;
+
spin_lock(&au1000->ac97_lock);
/* would rather use the interupt than this polling but it works and I can't
get the interupt driven case to work efficiently */
@@ -503,10 +526,12 @@ get the interupt driven case to work efficiently */
static void
-snd_au1000_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+snd_au1000_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
+ struct snd_au1000 *au1000 = ac97->private_data;
u32 cmd;
int i;
+
spin_lock(&au1000->ac97_lock);
/* would rather use the interupt than this polling but it works and I can't
get the interupt driven case to work efficiently */
@@ -522,40 +547,27 @@ get the interupt driven case to work efficiently */
au1000->ac97_ioport->cmd = cmd;
spin_unlock(&au1000->ac97_lock);
}
-static void
-snd_au1000_ac97_free(ac97_t *ac97)
-{
- au1000->ac97 = NULL;
-}
static int __devinit
-snd_au1000_ac97_new(void)
+snd_au1000_ac97_new(struct snd_au1000 *au1000)
{
int err;
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- static ac97_bus_ops_t ops = {
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ static struct snd_ac97_bus_ops ops = {
.write = snd_au1000_ac97_write,
.read = snd_au1000_ac97_read,
};
-#else
- ac97_bus_t bus, *pbus;
- ac97_t ac97;
-#endif
if ((au1000->ac97_res_port = request_region(AC97C_CONFIG,
- sizeof(au1000_ac97_reg_t), "Au1x00 AC97")) == NULL) {
+ sizeof(struct au1000_ac97_reg), "Au1x00 AC97")) == NULL) {
snd_printk(KERN_ERR "ALSA AC97: can't grap AC97 port\n");
return -EBUSY;
}
- au1000->ac97_ioport = (au1000_ac97_reg_t *) au1000->ac97_res_port->start;
+ au1000->ac97_ioport = (struct au1000_ac97_reg *) au1000->ac97_res_port->start;
spin_lock_init(&au1000->ac97_lock);
- spin_lock(&au1000->ac97_lock);
-
/* configure pins for AC'97
TODO: move to board_setup.c */
au_writel(au_readl(SYS_PINFUNC) & ~0x02, SYS_PINFUNC);
@@ -572,33 +584,24 @@ snd_au1000_ac97_new(void)
au1000->ac97_ioport->config = 0x0;
mdelay(5);
- spin_unlock(&au1000->ac97_lock);
-
/* Initialise AC97 middle-layer */
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
if ((err = snd_ac97_bus(au1000->card, 0, &ops, au1000, &pbus)) < 0)
return err;
-#else
- memset(&bus, 0, sizeof(bus));
- bus.write = snd_au1000_ac97_write;
- bus.read = snd_au1000_ac97_read;
- if ((err = snd_ac97_bus(au1000->card, &bus, &pbus)) < 0)
- return err;
-#endif
+
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = au1000;
- ac97.private_free = snd_au1000_ac97_free;
if ((err = snd_ac97_mixer(pbus, &ac97, &au1000->ac97)) < 0)
return err;
- return 0;
+ return 0;
}
/*------------------------------ Setup / Destroy ----------------------------*/
void
-snd_au1000_free(snd_card_t *card)
+snd_au1000_free(struct snd_card *card)
{
+ struct snd_au1000 *au1000 = card->private_data;
if (au1000->ac97_res_port) {
/* put internal AC97 block into reset */
@@ -614,73 +617,65 @@ snd_au1000_free(snd_card_t *card)
free_au1000_dma(au1000->stream[CAPTURE]->dma);
kfree(au1000->stream[PLAYBACK]);
- au1000->stream[PLAYBACK] = NULL;
kfree(au1000->stream[CAPTURE]);
- au1000->stream[CAPTURE] = NULL;
- kfree(au1000);
- au1000 = NULL;
-
}
+
+static struct snd_card *au1000_card;
+
static int __init
au1000_init(void)
{
int err;
+ struct snd_card *card;
+ struct snd_au1000 *au1000;
- au1000 = kmalloc(sizeof(au1000_t), GFP_KERNEL);
- if (au1000 == NULL)
- return -ENOMEM;
- au1000->stream[PLAYBACK] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
- if (au1000->stream[PLAYBACK] == NULL)
- return -ENOMEM;
- au1000->stream[CAPTURE] = kmalloc(sizeof(audio_stream_t), GFP_KERNEL);
- if (au1000->stream[CAPTURE] == NULL)
+ card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(struct snd_au1000));
+ if (card == NULL)
return -ENOMEM;
+
+ card->private_free = snd_au1000_free;
+ au1000 = card->private_data;
/* so that snd_au1000_free will work as intended */
+ au1000->card = card;
au1000->stream[PLAYBACK]->dma = -1;
au1000->stream[CAPTURE]->dma = -1;
au1000->ac97_res_port = NULL;
-
- au1000->card = snd_card_new(-1, "AC97", THIS_MODULE, sizeof(au1000_t));
- if (au1000->card == NULL) {
- snd_au1000_free(au1000->card);
+ au1000->stream[PLAYBACK] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
+ au1000->stream[CAPTURE] = kmalloc(sizeof(struct audio_stream), GFP_KERNEL);
+ if (au1000->stream[PLAYBACK] == NULL ||
+ au1000->stream[CAPTURE] == NULL) {
+ snd_card_free(card);
return -ENOMEM;
}
- au1000->card->private_data = (au1000_t *)au1000;
- au1000->card->private_free = snd_au1000_free;
-
- if ((err = snd_au1000_ac97_new()) < 0 ) {
- snd_card_free(au1000->card);
+ if ((err = snd_au1000_ac97_new(au1000)) < 0 ) {
+ snd_card_free(card);
return err;
}
- if ((err = snd_au1000_pcm_new()) < 0) {
- snd_card_free(au1000->card);
+ if ((err = snd_au1000_pcm_new(au1000)) < 0) {
+ snd_card_free(card);
return err;
}
- strcpy(au1000->card->driver, "AMD-Au1000-AC97");
- 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;
- }
+ strcpy(card->driver, "Au1000-AC97");
+ strcpy(card->shortname, "AMD Au1000-AC97");
+ sprintf(card->longname, "AMD Au1000--AC97 ALSA Driver");
- if ((err = snd_card_register(au1000->card)) < 0) {
- snd_card_free(au1000->card);
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
return err;
}
printk( KERN_INFO "ALSA AC97: Driver Initialized\n" );
+ au1000_card = card;
return 0;
}
static void __exit au1000_exit(void)
{
- snd_card_free(au1000->card);
+ snd_card_free(au1000_card);
}
module_init(au1000_init);
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 3f30c57676c1..49796be955f3 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -46,8 +46,6 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/stddef.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/isapnp.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
@@ -105,9 +103,6 @@ typedef struct
int irq_ok;
mixer_ents *mix_devices;
int mixer_output_port;
-
- /* Power management */
- struct pm_dev *pmdev;
} ad1848_info;
typedef struct ad1848_port_info
@@ -201,7 +196,6 @@ static void ad1848_halt(int dev);
static void ad1848_halt_input(int dev);
static void ad1848_halt_output(int dev);
static void ad1848_trigger(int dev, int bits);
-static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data);
#ifndef EXCLUDE_TIMERS
static int ad1848_tmr_install(int dev);
@@ -2027,10 +2021,6 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
nr_ad1848_devs++;
- devc->pmdev = pm_register(PM_ISA_DEV, my_dev, ad1848_pm_callback);
- if (devc->pmdev)
- devc->pmdev->data = devc;
-
ad1848_init_hw(devc);
if (irq > 0)
@@ -2197,9 +2187,6 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
if(mixer>=0)
sound_unload_mixerdev(mixer);
- if (devc->pmdev)
- pm_unregister(devc->pmdev);
-
nr_ad1848_devs--;
for ( ; i < nr_ad1848_devs ; i++)
adev_info[i] = adev_info[i+1];
@@ -2811,85 +2798,6 @@ static int ad1848_tmr_install(int dev)
}
#endif /* EXCLUDE_TIMERS */
-static int ad1848_suspend(ad1848_info *devc)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&devc->lock,flags);
-
- ad_mute(devc);
-
- spin_unlock_irqrestore(&devc->lock,flags);
- return 0;
-}
-
-static int ad1848_resume(ad1848_info *devc)
-{
- int mixer_levels[32], i;
-
- /* Thinkpad is a bit more of PITA than normal. The BIOS tends to
- restore it in a different config to the one we use. Need to
- fix this somehow */
-
- /* store old mixer levels */
- memcpy(mixer_levels, devc->levels, sizeof (mixer_levels));
- ad1848_init_hw(devc);
-
- /* restore mixer levels */
- for (i = 0; i < 32; i++)
- ad1848_mixer_set(devc, devc->dev_no, mixer_levels[i]);
-
- if (!devc->subtype) {
- static signed char interrupt_bits[12] = { -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20 };
- static char dma_bits[4] = { 1, 2, 0, 3 };
- unsigned long flags;
- signed char bits;
- char dma2_bit = 0;
-
- int config_port = devc->base + 0;
-
- bits = interrupt_bits[devc->irq];
- if (bits == -1) {
- printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
- return -1;
- }
-
- spin_lock_irqsave(&devc->lock,flags);
-
- outb((bits | 0x40), config_port);
-
- if (devc->dma2 != -1 && devc->dma2 != devc->dma1)
- if ( (devc->dma1 == 0 && devc->dma2 == 1) ||
- (devc->dma1 == 1 && devc->dma2 == 0) ||
- (devc->dma1 == 3 && devc->dma2 == 0))
- dma2_bit = 0x04;
-
- outb((bits | dma_bits[devc->dma1] | dma2_bit), config_port);
- spin_unlock_irqrestore(&devc->lock,flags);
- }
-
- return 0;
-}
-
-static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- ad1848_info *devc = dev->data;
- if (devc) {
- DEB(printk("ad1848: pm event received: 0x%x\n", rqst));
-
- switch (rqst) {
- case PM_SUSPEND:
- ad1848_suspend(devc);
- break;
- case PM_RESUME:
- ad1848_resume(devc);
- break;
- }
- }
- return 0;
-}
-
-
EXPORT_SYMBOL(ad1848_detect);
EXPORT_SYMBOL(ad1848_init);
EXPORT_SYMBOL(ad1848_unload);
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 2cfd214e4c2a..a0d73f343100 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -1089,7 +1089,7 @@ static struct pci_driver ad1889_driver = {
static int __init ad1889_init_module(void)
{
- return pci_module_init(&ad1889_driver);
+ return pci_register_driver(&ad1889_driver);
}
static void ad1889_exit_module(void)
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index a85093fec7be..4007a5680acb 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -1101,7 +1101,7 @@ static int btaudio_init_module(void)
digital ? "digital" : "",
analog && digital ? "+" : "",
analog ? "analog" : "");
- return pci_module_init(&btaudio_pci_driver);
+ return pci_register_driver(&btaudio_pci_driver);
}
static void btaudio_cleanup_module(void)
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 74dcca78c6c0..7cfbb08db537 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -3366,7 +3366,7 @@ static struct pci_driver cm_driver = {
static int __init init_cmpci(void)
{
printk(KERN_INFO "cmpci: version $Revision: 6.82 $ time " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&cm_driver);
+ return pci_register_driver(&cm_driver);
}
static void __exit cleanup_cmpci(void)
diff --git a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c
index adc689649fe1..0720365f6438 100644
--- a/sound/oss/cs4281/cs4281m.c
+++ b/sound/oss/cs4281/cs4281m.c
@@ -298,7 +298,6 @@ struct cs4281_state {
struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES];
};
-#include <linux/pm_legacy.h>
#include "cs4281pm-24.c"
#if CSDEBUG
@@ -4256,9 +4255,6 @@ static void __devinit cs4281_InitPM(struct cs4281_state *s)
static int __devinit cs4281_probe(struct pci_dev *pcidev,
const struct pci_device_id *pciid)
{
-#ifndef NOT_CS4281_PM
- struct pm_dev *pmdev;
-#endif
struct cs4281_state *s;
dma_addr_t dma_mask;
mm_segment_t fs;
@@ -4374,19 +4370,7 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev,
}
#ifndef NOT_CS4281_PM
cs4281_InitPM(s);
- pmdev = cs_pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), cs4281_pm_callback);
- if (pmdev)
- {
- CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO
- "cs4281: probe() pm_register() succeeded (%p).\n", pmdev));
- pmdev->data = s;
- }
- else
- {
- CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO
- "cs4281: probe() pm_register() failed (%p).\n", pmdev));
- s->pm.flags |= CS4281_PM_NOT_REGISTERED;
- }
+ s->pm.flags |= CS4281_PM_NOT_REGISTERED;
#endif
pci_set_master(pcidev); // enable bus mastering
@@ -4477,7 +4461,7 @@ static int __init cs4281_init_module(void)
printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " "
__DATE__ "\n", CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION,
CS4281_ARCH);
- rtn = pci_module_init(&cs4281_pci_driver);
+ rtn = pci_register_driver(&cs4281_pci_driver);
CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
printk(KERN_INFO "cs4281: cs4281_init_module()- (%d)\n",rtn));
@@ -4487,9 +4471,6 @@ static int __init cs4281_init_module(void)
static void __exit cs4281_cleanup_module(void)
{
pci_unregister_driver(&cs4281_pci_driver);
-#ifndef NOT_CS4281_PM
- cs_pm_unregister_all(cs4281_pm_callback);
-#endif
CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n"));
}
diff --git a/sound/oss/cs4281/cs4281pm-24.c b/sound/oss/cs4281/cs4281pm-24.c
index d2a453aff0aa..90cbd7679534 100644
--- a/sound/oss/cs4281/cs4281pm-24.c
+++ b/sound/oss/cs4281/cs4281pm-24.c
@@ -27,9 +27,6 @@
#ifndef NOT_CS4281_PM
#include <linux/pm.h>
-#define cs_pm_register(a, b, c) pm_register((a), (b), (c));
-#define cs_pm_unregister_all(a) pm_unregister_all((a));
-
static int cs4281_suspend(struct cs4281_state *s);
static int cs4281_resume(struct cs4281_state *s);
/*
@@ -41,42 +38,6 @@ static int cs4281_resume(struct cs4281_state *s);
#define CS4281_SUSPEND_TBL cs4281_suspend_null
#define CS4281_RESUME_TBL cs4281_resume_null
-static int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct cs4281_state *state;
-
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs4281: cs4281_pm_callback dev=%p rqst=0x%x state=%p\n",
- dev,(unsigned)rqst,data));
- state = (struct cs4281_state *) dev->data;
- if (state) {
- switch(rqst) {
- case PM_SUSPEND:
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs4281: PM suspend request\n"));
- if(cs4281_suspend(state))
- {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs4281: PM suspend request refused\n"));
- return 1;
- }
- break;
- case PM_RESUME:
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs4281: PM resume request\n"));
- if(cs4281_resume(state))
- {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs4281: PM resume request refused\n"));
- return 1;
- }
- break;
- }
- }
-
- return 0;
-}
-
#else /* CS4281_PM */
#define CS4281_SUSPEND_TBL cs4281_suspend_null
#define CS4281_RESUME_TBL cs4281_resume_null
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index cb998e8c0fdd..58e25c82eaf2 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -391,10 +391,6 @@ static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type);
static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#ifndef CS46XX_ACPI_SUPPORT
-static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data);
-#endif
-
#if CSDEBUG
/* DEBUG ROUTINES */
@@ -5320,7 +5316,6 @@ static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n";
static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pciid)
{
- struct pm_dev *pmdev;
int i,j;
u16 ss_card, ss_vendor;
struct cs_card *card;
@@ -5530,22 +5525,6 @@ static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
PCI_SET_DMA_MASK(pci_dev, dma_mask);
list_add(&card->list, &cs46xx_devs);
- pmdev = cs_pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), cs46xx_pm_callback);
- if (pmdev)
- {
- CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO
- "cs46xx: probe() pm_register() succeeded (%p).\n",
- pmdev));
- pmdev->data = card;
- }
- else
- {
- CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 2, printk(KERN_INFO
- "cs46xx: probe() pm_register() failed (%p).\n",
- pmdev));
- card->pm.flags |= CS46XX_PM_NOT_REGISTERED;
- }
-
CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n",
(unsigned)card->pm.flags,card));
@@ -5711,7 +5690,7 @@ static int __init cs46xx_init_module(void)
int rtn = 0;
CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
"cs46xx: cs46xx_init_module()+ \n"));
- rtn = pci_module_init(&cs46xx_pci_driver);
+ rtn = pci_register_driver(&cs46xx_pci_driver);
if(rtn == -ENODEV)
{
@@ -5727,7 +5706,6 @@ static int __init cs46xx_init_module(void)
static void __exit cs46xx_cleanup_module(void)
{
pci_unregister_driver(&cs46xx_pci_driver);
- cs_pm_unregister_all(cs46xx_pm_callback);
CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n"));
}
@@ -5735,44 +5713,6 @@ static void __exit cs46xx_cleanup_module(void)
module_init(cs46xx_init_module);
module_exit(cs46xx_cleanup_module);
-#ifndef CS46XX_ACPI_SUPPORT
-static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct cs_card *card;
-
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs46xx: cs46xx_pm_callback dev=%p rqst=0x%x card=%p\n",
- dev,(unsigned)rqst,data));
- card = (struct cs_card *) dev->data;
- if (card) {
- switch(rqst) {
- case PM_SUSPEND:
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs46xx: PM suspend request\n"));
- if(cs46xx_suspend(card, PMSG_SUSPEND))
- {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs46xx: PM suspend request refused\n"));
- return 1;
- }
- break;
- case PM_RESUME:
- CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
- "cs46xx: PM resume request\n"));
- if(cs46xx_resume(card))
- {
- CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
- "cs46xx: PM resume request refused\n"));
- return 1;
- }
- break;
- }
- }
-
- return 0;
-}
-#endif
-
#if CS46XX_ACPI_SUPPORT
static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state)
{
diff --git a/sound/oss/cs46xxpm-24.h b/sound/oss/cs46xxpm-24.h
index e220bd7240f1..ad82db84d013 100644
--- a/sound/oss/cs46xxpm-24.h
+++ b/sound/oss/cs46xxpm-24.h
@@ -38,13 +38,9 @@
*/
static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state);
static int cs46xx_resume_tbl(struct pci_dev *pcidev);
-#define cs_pm_register(a, b, c) NULL
-#define cs_pm_unregister_all(a)
#define CS46XX_SUSPEND_TBL cs46xx_suspend_tbl
#define CS46XX_RESUME_TBL cs46xx_resume_tbl
#else
-#define cs_pm_register(a, b, c) pm_register((a), (b), (c));
-#define cs_pm_unregister_all(a) pm_unregister_all((a));
#define CS46XX_SUSPEND_TBL cs46xx_null
#define CS46XX_RESUME_TBL cs46xx_null
#endif
diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
index 533895eba0eb..7360d8954d60 100644
--- a/sound/oss/dmasound/dac3550a.c
+++ b/sound/oss/dmasound/dac3550a.c
@@ -41,10 +41,10 @@ static int daca_detect_client(struct i2c_adapter *adapter, int address);
static int daca_detach_client(struct i2c_client *client);
struct i2c_driver daca_driver = {
- .owner = THIS_MODULE,
- .name = "DAC3550A driver V " DACA_VERSION,
+ .driver = {
+ .name = "DAC3550A driver V " DACA_VERSION,
+ },
.id = I2C_DRIVERID_DACA,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = daca_attach_adapter,
.detach_client = daca_detach_client,
};
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h
index 222014cafc1a..a1b0b92af4b5 100644
--- a/sound/oss/dmasound/dmasound.h
+++ b/sound/oss/dmasound/dmasound.h
@@ -270,7 +270,6 @@ extern int dmasound_catchRadius;
#define SW_INPUT_VOLUME_SCALE 4
#define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE)
-extern int expand_bal; /* Balance factor for expanding (not volume!) */
extern int expand_read_bal; /* Balance factor for reading */
extern uint software_input_volume; /* software implemented recording volume! */
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index 59eb53f89318..dc31373069a5 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -67,46 +67,46 @@ static int expand_data; /* Data for expanding */
* ++geert: split in even more functions (one per format)
*/
-static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
-static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft);
@@ -151,7 +151,7 @@ static int FalconStateInfo(char *buffer, size_t space);
/*** Translations ************************************************************/
-static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -176,7 +176,7 @@ static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -194,7 +194,7 @@ static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -217,8 +217,9 @@ static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
used = count*2;
while (count > 0) {
u_short data;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
*p++ = data ^ 0x8080;
count--;
}
@@ -228,7 +229,7 @@ static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -240,8 +241,9 @@ static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
used = count*2;
while (count > 0) {
u_short data;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
*p++ = data;
*p++ = data;
count--;
@@ -259,7 +261,7 @@ static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -271,8 +273,9 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
used = count*2;
while (count > 0) {
u_short data;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data ^= 0x8000;
*p++ = data;
*p++ = data;
@@ -284,9 +287,10 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
count = min_t(unsigned long, userCount, frameLeft)>>2;
used = count*4;
while (count > 0) {
- u_long data;
- if (get_user(data, ((u_int *)userPtr)++))
+ u_int data;
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
*p++ = data ^ 0x80008000;
count--;
}
@@ -296,7 +300,7 @@ static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -309,8 +313,9 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
used = count*2;
while (count > 0) {
u_short data;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data = le2be16(data);
*p++ = data;
*p++ = data;
@@ -323,8 +328,9 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
used = count*4;
while (count > 0) {
u_long data;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
data = le2be16dbl(data);
*p++ = data;
count--;
@@ -335,7 +341,7 @@ static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -348,8 +354,9 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
used = count*2;
while (count > 0) {
u_short data;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data = le2be16(data) ^ 0x8000;
*p++ = data;
*p++ = data;
@@ -361,8 +368,9 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
used = count;
while (count > 0) {
u_long data;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
data = le2be16dbl(data) ^ 0x80008000;
*p++ = data;
count--;
@@ -373,7 +381,7 @@ static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -435,7 +443,7 @@ static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -470,8 +478,9 @@ static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
userCount -= 2;
bal += hSpeed;
}
@@ -488,7 +497,7 @@ static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -524,8 +533,9 @@ static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data ^= 0x8080;
userCount -= 2;
bal += hSpeed;
@@ -543,7 +553,7 @@ static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -561,8 +571,9 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
userCount -= 2;
bal += hSpeed;
}
@@ -579,8 +590,9 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 4)
break;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
userCount -= 4;
bal += hSpeed;
}
@@ -597,7 +609,7 @@ static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -615,8 +627,9 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data ^= 0x8000;
userCount -= 2;
bal += hSpeed;
@@ -634,8 +647,9 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 4)
break;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
data ^= 0x80008000;
userCount -= 4;
bal += hSpeed;
@@ -653,7 +667,7 @@ static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -671,8 +685,9 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data = le2be16(data);
userCount -= 2;
bal += hSpeed;
@@ -690,8 +705,9 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 4)
break;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
data = le2be16dbl(data);
userCount -= 4;
bal += hSpeed;
@@ -709,7 +725,7 @@ static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
}
-static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
+static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -727,8 +743,9 @@ static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 2)
break;
- if (get_user(data, ((u_short *)userPtr)++))
+ if (get_user(data, (u_short __user *)userPtr))
return -EFAULT;
+ userPtr += 2;
data = le2be16(data) ^ 0x8000;
userCount -= 2;
bal += hSpeed;
@@ -746,8 +763,9 @@ static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
if (bal < 0) {
if (userCount < 4)
break;
- if (get_user(data, ((u_int *)userPtr)++))
+ if (get_user(data, (u_int __user *)userPtr))
return -EFAULT;
+ userPtr += 4;
data = le2be16dbl(data) ^ 0x80008000;
userCount -= 4;
bal += hSpeed;
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index cebd881b91ae..74f975676ccb 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -125,6 +125,7 @@ static int awacs_rate_index;
static int awacs_subframe;
static struct device_node* awacs_node;
static struct device_node* i2s_node;
+static struct resource awacs_rsrc[3];
static char awacs_name[64];
static int awacs_revision;
@@ -667,9 +668,12 @@ static void PMacIrqCleanup(void)
iounmap(awacs_txdma);
iounmap(awacs_rxdma);
- release_OF_resource(awacs_node, 0);
- release_OF_resource(awacs_node, 1);
- release_OF_resource(awacs_node, 2);
+ release_mem_region(awacs_rsrc[0].start,
+ awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
+ release_mem_region(awacs_rsrc[1].start,
+ awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
+ release_mem_region(awacs_rsrc[2].start,
+ awacs_rsrc[2].end - awacs_rsrc[2].start + 1);
kfree(awacs_tx_cmd_space);
kfree(awacs_rx_cmd_space);
@@ -2863,46 +2867,58 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
* other info if necessary (early AWACS we want to read chip ids)
*/
- if (io->n_addrs < 3 || io->n_intrs < 3) {
+ if (of_get_address(io, 2, NULL, NULL) == NULL || io->n_intrs < 3) {
/* OK - maybe we need to use the 'awacs' node (on earlier
* machines).
- */
+ */
if (awacs_node) {
io = awacs_node ;
- if (io->n_addrs < 3 || io->n_intrs < 3) {
- printk("dmasound_pmac: can't use %s"
- " (%d addrs, %d intrs)\n",
- io->full_name, io->n_addrs, io->n_intrs);
+ if (of_get_address(io, 2, NULL, NULL) == NULL ||
+ io->n_intrs < 3) {
+ printk("dmasound_pmac: can't use %s\n",
+ io->full_name);
return -ENODEV;
}
- } else {
- printk("dmasound_pmac: can't use %s (%d addrs, %d intrs)\n",
- io->full_name, io->n_addrs, io->n_intrs);
- }
+ } else
+ printk("dmasound_pmac: can't use %s\n", io->full_name);
}
- if (!request_OF_resource(io, 0, NULL)) {
+ if (of_address_to_resource(io, 0, &awacs_rsrc[0]) ||
+ request_mem_region(awacs_rsrc[0].start,
+ awacs_rsrc[0].end - awacs_rsrc[0].start + 1,
+ " (IO)") == NULL) {
printk(KERN_ERR "dmasound: can't request IO resource !\n");
return -ENODEV;
}
- if (!request_OF_resource(io, 1, " (tx dma)")) {
- release_OF_resource(io, 0);
- printk(KERN_ERR "dmasound: can't request TX DMA resource !\n");
+ if (of_address_to_resource(io, 1, &awacs_rsrc[1]) ||
+ request_mem_region(awacs_rsrc[1].start,
+ awacs_rsrc[1].end - awacs_rsrc[1].start + 1,
+ " (tx dma)") == NULL) {
+ release_mem_region(awacs_rsrc[0].start,
+ awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
+ printk(KERN_ERR "dmasound: can't request Tx DMA resource !\n");
return -ENODEV;
}
-
- if (!request_OF_resource(io, 2, " (rx dma)")) {
- release_OF_resource(io, 0);
- release_OF_resource(io, 1);
- printk(KERN_ERR "dmasound: can't request RX DMA resource !\n");
+ if (of_address_to_resource(io, 2, &awacs_rsrc[2]) ||
+ request_mem_region(awacs_rsrc[2].start,
+ awacs_rsrc[2].end - awacs_rsrc[2].start + 1,
+ " (rx dma)") == NULL) {
+ release_mem_region(awacs_rsrc[0].start,
+ awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
+ release_mem_region(awacs_rsrc[1].start,
+ awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
+ printk(KERN_ERR "dmasound: can't request Rx DMA resource !\n");
return -ENODEV;
}
awacs_beep_dev = input_allocate_device();
if (!awacs_beep_dev) {
- release_OF_resource(io, 0);
- release_OF_resource(io, 1);
- release_OF_resource(io, 2);
+ release_mem_region(awacs_rsrc[0].start,
+ awacs_rsrc[0].end - awacs_rsrc[0].start + 1);
+ release_mem_region(awacs_rsrc[1].start,
+ awacs_rsrc[1].end - awacs_rsrc[1].start + 1);
+ release_mem_region(awacs_rsrc[2].start,
+ awacs_rsrc[2].end - awacs_rsrc[2].start + 1);
printk(KERN_ERR "dmasound: can't allocate input device !\n");
return -ENOMEM;
}
@@ -2916,11 +2932,11 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n");
/* all OF versions I've seen use this value */
if (i2s_node)
- i2s = ioremap(io->addrs[0].address, 0x1000);
+ i2s = ioremap(awacs_rsrc[0].start, 0x1000);
else
- awacs = ioremap(io->addrs[0].address, 0x1000);
- awacs_txdma = ioremap(io->addrs[1].address, 0x100);
- awacs_rxdma = ioremap(io->addrs[2].address, 0x100);
+ awacs = ioremap(awacs_rsrc[0].start, 0x1000);
+ awacs_txdma = ioremap(awacs_rsrc[1].start, 0x100);
+ awacs_rxdma = ioremap(awacs_rsrc[2].start, 0x100);
/* first of all make sure that the chip is powered up....*/
pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, io, 0, 1);
@@ -3083,9 +3099,10 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
struct device_node* mio;
macio_base = NULL;
for (mio = io->parent; mio; mio = mio->parent) {
- if (strcmp(mio->name, "mac-io") == 0
- && mio->n_addrs > 0) {
- macio_base = ioremap(mio->addrs[0].address, 0x40);
+ if (strcmp(mio->name, "mac-io") == 0) {
+ struct resource r;
+ if (of_address_to_resource(mio, 0, &r) == 0)
+ macio_base = ioremap(r.start, 0x40);
break;
}
}
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index d59f60b26410..494070a3f870 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -34,6 +34,7 @@
#define DMASOUND_PAULA_REVISION 0
#define DMASOUND_PAULA_EDITION 4
+#define custom amiga_custom
/*
* The minimum period for audio depends on htotal (for OCS/ECS/AGA)
* (Imported from arch/m68k/amiga/amisound.c)
@@ -156,7 +157,7 @@ static int AmiStateInfo(char *buffer, size_t space);
* Native format
*/
-static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount,
+static ssize_t ami_ct_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
{
ssize_t count, used;
@@ -189,7 +190,7 @@ static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount,
*/
#define GENERATE_AMI_CT8(funcname, convsample) \
-static ssize_t funcname(const u_char *userPtr, size_t userCount, \
+static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
u_char frame[], ssize_t *frameUsed, \
ssize_t frameLeft) \
{ \
@@ -240,10 +241,11 @@ GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8)
*/
#define GENERATE_AMI_CT_16(funcname, convsample) \
-static ssize_t funcname(const u_char *userPtr, size_t userCount, \
+static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
u_char frame[], ssize_t *frameUsed, \
ssize_t frameLeft) \
{ \
+ const u_short __user *ptr = (const u_short __user *)userPtr; \
ssize_t count, used; \
u_short data; \
\
@@ -253,7 +255,7 @@ static ssize_t funcname(const u_char *userPtr, size_t userCount, \
count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
used = count*2; \
while (count > 0) { \
- if (get_user(data, ((u_short *)userPtr)++)) \
+ if (get_user(data, ptr++)) \
return -EFAULT; \
data = convsample(data); \
*high++ = data>>8; \
@@ -268,12 +270,12 @@ static ssize_t funcname(const u_char *userPtr, size_t userCount, \
count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \
used = count*4; \
while (count > 0) { \
- if (get_user(data, ((u_short *)userPtr)++)) \
+ if (get_user(data, ptr++)) \
return -EFAULT; \
data = convsample(data); \
*lefth++ = data>>8; \
*leftl++ = (data>>2) & 0x3f; \
- if (get_user(data, ((u_short *)userPtr)++)) \
+ if (get_user(data, ptr++)) \
return -EFAULT; \
data = convsample(data); \
*righth++ = data>>8; \
diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c
index 1ddaa6284b08..e2081f32b0c4 100644
--- a/sound/oss/dmasound/dmasound_q40.c
+++ b/sound/oss/dmasound/dmasound_q40.c
@@ -58,7 +58,7 @@ static void Q40Interrupt(void);
/* userCount, frameUsed, frameLeft == byte counts */
-static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ct_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -79,7 +79,7 @@ static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount,
}
-static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ct_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -98,7 +98,7 @@ static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount,
return used;
}
-static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ct_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -114,7 +114,7 @@ static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount,
/* a bit too complicated to optimise right now ..*/
-static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctx_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -152,7 +152,7 @@ static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount,
}
-static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctx_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -189,7 +189,7 @@ static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount,
}
-static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctx_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -224,7 +224,7 @@ static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount,
}
/* compressing versions */
-static ssize_t q40_ctc_law(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctc_law(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -265,7 +265,7 @@ static ssize_t q40_ctc_law(const u_char *userPtr, size_t userCount,
}
-static ssize_t q40_ctc_s8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctc_s8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
@@ -304,7 +304,7 @@ static ssize_t q40_ctc_s8(const u_char *userPtr, size_t userCount,
}
-static ssize_t q40_ctc_u8(const u_char *userPtr, size_t userCount,
+static ssize_t q40_ctc_u8(const u_char __user *userPtr, size_t userCount,
u_char frame[], ssize_t *frameUsed,
ssize_t frameLeft)
{
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
index d36a1fe2fcf3..81315996c0f1 100644
--- a/sound/oss/dmasound/tas_common.c
+++ b/sound/oss/dmasound/tas_common.c
@@ -47,9 +47,9 @@ static int tas_attach_adapter(struct i2c_adapter *);
static int tas_detach_client(struct i2c_client *);
struct i2c_driver tas_driver = {
- .owner = THIS_MODULE,
- .name = "tas",
- .flags = I2C_DF_NOTIFY,
+ .driver = {
+ .name = "tas",
+ },
.attach_adapter = tas_attach_adapter,
.detach_client = tas_detach_client,
};
diff --git a/sound/oss/dmasound/trans_16.c b/sound/oss/dmasound/trans_16.c
index 23562e947806..ca973ac2a30a 100644
--- a/sound/oss/dmasound/trans_16.c
+++ b/sound/oss/dmasound/trans_16.c
@@ -17,6 +17,7 @@
#include <asm/uaccess.h>
#include "dmasound.h"
+extern int expand_bal; /* Balance factor for expanding (not volume!) */
static short dmasound_alaw2dma16[] ;
static short dmasound_ulaw2dma16[] ;
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 9b905bae423e..23241cbdd90f 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -1428,7 +1428,7 @@ static int __init emu10k1_init_module(void)
{
printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&emu10k1_pci_driver);
+ return pci_register_driver(&emu10k1_pci_driver);
}
static void __exit emu10k1_cleanup_module(void)
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c
index 8538085086e7..ae55c536613a 100644
--- a/sound/oss/es1370.c
+++ b/sound/oss/es1370.c
@@ -2779,7 +2779,7 @@ static struct pci_driver es1370_driver = {
static int __init init_es1370(void)
{
printk(KERN_INFO "es1370: version v0.38 time " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&es1370_driver);
+ return pci_register_driver(&es1370_driver);
}
static void __exit cleanup_es1370(void)
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index 12a56d5ab498..5c697f162579 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -3090,7 +3090,7 @@ static struct pci_driver es1371_driver = {
static int __init init_es1371(void)
{
printk(KERN_INFO PFX "version v0.32 time " __TIME__ " " __DATE__ "\n");
- return pci_module_init(&es1371_driver);
+ return pci_register_driver(&es1371_driver);
}
static void __exit cleanup_es1371(void)
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index a4ecab2f0522..849b59f67ef5 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -515,7 +515,7 @@ static inline int prog_dmabuf_adc(struct solo1_state *s)
return 0;
}
-static inline int prog_dmabuf_dac(struct solo1_state *s)
+static int prog_dmabuf_dac(struct solo1_state *s)
{
unsigned long va;
int c;
diff --git a/sound/oss/harmony.c b/sound/oss/harmony.c
index bee9d344cd26..591683c55f27 100644
--- a/sound/oss/harmony.c
+++ b/sound/oss/harmony.c
@@ -1236,7 +1236,7 @@ harmony_driver_probe(struct parisc_device *dev)
}
/* Set the HPA of harmony */
- harmony.hpa = (struct harmony_hpa *)dev->hpa;
+ harmony.hpa = (struct harmony_hpa *)dev->hpa.start;
harmony.dev = dev;
/* Grab the ID and revision from the device */
@@ -1250,7 +1250,7 @@ harmony_driver_probe(struct parisc_device *dev)
printk(KERN_INFO "Lasi Harmony Audio driver " HARMONY_VERSION ", "
"h/w id %i, rev. %i at 0x%lx, IRQ %i\n",
- id, rev, dev->hpa, harmony.dev->irq);
+ id, rev, dev->hpa.start, harmony.dev->irq);
/* Make sure the control bit isn't set, although I don't think it
ever is. */
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index b9a640fe48b1..abc242abd5b1 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -312,7 +312,8 @@ static struct pci_device_id i810_pci_tbl [] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-
+ {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
{0,}
};
@@ -3359,12 +3360,6 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
goto out_region2;
}
- if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
- card_names[pci_id->driver_data], card)) {
- printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq);
- goto out_pio;
- }
-
if (card->use_mmio) {
if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) {
if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */
@@ -3395,10 +3390,8 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
}
/* initialize AC97 codec and register /dev/mixer */
- if (i810_ac97_init(card) <= 0) {
- free_irq(card->irq, card);
+ if (i810_ac97_init(card) <= 0)
goto out_iospace;
- }
pci_set_drvdata(pci_dev, card);
if(clocking == 0) {
@@ -3410,7 +3403,6 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) {
int i;
printk(KERN_ERR "i810_audio: couldn't register DSP device!\n");
- free_irq(card->irq, card);
for (i = 0; i < NR_AC97; i++)
if (card->ac97_codec[i] != NULL) {
unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
@@ -3419,6 +3411,13 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
goto out_iospace;
}
+ if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
+ card_names[pci_id->driver_data], card)) {
+ printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq);
+ goto out_iospace;
+ }
+
+
card->initializing = 0;
return 0;
@@ -3429,7 +3428,6 @@ out_iospace:
release_mem_region(card->ac97base_mmio_phys, 512);
release_mem_region(card->iobase_mmio_phys, 256);
}
-out_pio:
release_region(card->ac97base, 256);
out_region2:
release_region(card->iobase, 64);
diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c
index 26e5944b6ba8..8fd2f9a9e668 100644
--- a/sound/oss/ite8172.c
+++ b/sound/oss/ite8172.c
@@ -2206,7 +2206,7 @@ static struct pci_driver it8172_driver = {
static int __init init_it8172(void)
{
info("version v0.5 time " __TIME__ " " __DATE__);
- return pci_module_init(&it8172_driver);
+ return pci_register_driver(&it8172_driver);
}
static void __exit cleanup_it8172(void)
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c
index 808c5ef969be..2835a7c038ef 100644
--- a/sound/oss/kahlua.c
+++ b/sound/oss/kahlua.c
@@ -218,7 +218,7 @@ static struct pci_driver kahlua_driver = {
static int __init kahlua_init_module(void)
{
printk(KERN_INFO "Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc\n");
- return pci_module_init(&kahlua_driver);
+ return pci_register_driver(&kahlua_driver);
}
static void __devexit kahlua_cleanup_module(void)
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c
index 3abd3541cbc7..d4b569acf764 100644
--- a/sound/oss/maestro.c
+++ b/sound/oss/maestro.c
@@ -230,10 +230,6 @@
#include <asm/page.h>
#include <asm/uaccess.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d);
-
#include "maestro.h"
static struct pci_driver maestro_pci_driver;
@@ -3404,7 +3400,6 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid)
int i, ret;
struct ess_card *card;
struct ess_state *ess;
- struct pm_dev *pmdev;
int num = 0;
/* when built into the kernel, we only print version if device is found */
@@ -3450,11 +3445,6 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid)
memset(card, 0, sizeof(*card));
card->pcidev = pcidev;
- pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev),
- maestro_pm_callback);
- if (pmdev)
- pmdev->data = card;
-
card->iobase = iobase;
card->card_type = card_type;
card->irq = pcidev->irq;
@@ -3634,7 +3624,7 @@ static int __init init_maestro(void)
{
int rc;
- rc = pci_module_init(&maestro_pci_driver);
+ rc = pci_register_driver(&maestro_pci_driver);
if (rc < 0)
return rc;
@@ -3670,7 +3660,6 @@ static int maestro_notifier(struct notifier_block *nb, unsigned long event, void
static void cleanup_maestro(void) {
M_printk("maestro: unloading\n");
pci_unregister_driver(&maestro_pci_driver);
- pm_unregister_all(maestro_pm_callback);
unregister_reboot_notifier(&maestro_nb);
}
@@ -3691,143 +3680,5 @@ check_suspend(struct ess_card *card)
current->state = TASK_RUNNING;
}
-static int
-maestro_suspend(struct ess_card *card)
-{
- unsigned long flags;
- int i,j;
-
- spin_lock_irqsave(&card->lock,flags); /* over-kill */
-
- M_printk("maestro: apm in dev %p\n",card);
-
- /* we have to read from the apu regs, need
- to power it up */
- maestro_power(card,ACPI_D0);
-
- for(i=0;i<NR_DSPS;i++) {
- struct ess_state *s = &card->channels[i];
-
- if(s->dev_audio == -1)
- continue;
-
- M_printk("maestro: stopping apus for device %d\n",i);
- stop_dac(s);
- stop_adc(s);
- for(j=0;j<6;j++)
- card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5);
-
- }
-
- /* get rid of interrupts? */
- if( card->dsps_open > 0)
- stop_bob(&card->channels[0]);
-
- card->in_suspend++;
-
- spin_unlock_irqrestore(&card->lock,flags);
-
- /* we trust in the bios to power down the chip on suspend.
- * XXX I'm also not sure that in_suspend will protect
- * against all reg accesses from here on out.
- */
- return 0;
-}
-static int
-maestro_resume(struct ess_card *card)
-{
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&card->lock,flags); /* over-kill */
-
- card->in_suspend = 0;
-
- M_printk("maestro: resuming card at %p\n",card);
-
- /* restore all our config */
- maestro_config(card);
- /* need to restore the base pointers.. */
- if(card->dmapages)
- set_base_registers(&card->channels[0],card->dmapages);
-
- mixer_push_state(card);
-
- /* set each channels' apu control registers before
- * restoring audio
- */
- for(i=0;i<NR_DSPS;i++) {
- struct ess_state *s = &card->channels[i];
- int chan,reg;
-
- if(s->dev_audio == -1)
- continue;
-
- for(chan = 0 ; chan < 6 ; chan++) {
- wave_set_register(s,s->apu[chan]<<3,s->apu_base[chan]);
- for(reg = 1 ; reg < NR_APU_REGS ; reg++)
- apu_set_register(s,chan,reg,s->card->apu_map[s->apu[chan]][reg]);
- }
- for(chan = 0 ; chan < 6 ; chan++)
- apu_set_register(s,chan,0,s->card->apu_map[s->apu[chan]][0] & 0xFF0F);
- }
-
- /* now we flip on the music */
-
- if( card->dsps_open <= 0) {
- /* this card's idle */
- maestro_power(card,ACPI_D2);
- } else {
- /* ok, we're actually playing things on
- this card */
- maestro_power(card,ACPI_D0);
- start_bob(&card->channels[0]);
- for(i=0;i<NR_DSPS;i++) {
- struct ess_state *s = &card->channels[i];
-
- /* these use the apu_mode, and can handle
- spurious calls */
- start_dac(s);
- start_adc(s);
- }
- }
-
- spin_unlock_irqrestore(&card->lock,flags);
-
- /* all right, we think things are ready,
- wake up people who were using the device
- when we suspended */
- wake_up(&(card->suspend_queue));
-
- return 0;
-}
-
-int
-maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct ess_card *card = (struct ess_card*) dev->data;
-
- if ( ! card ) goto out;
-
- M_printk("maestro: pm event 0x%x received for card %p\n", rqst, card);
-
- switch (rqst) {
- case PM_SUSPEND:
- maestro_suspend(card);
- break;
- case PM_RESUME:
- maestro_resume(card);
- break;
- /*
- * we'd also like to find out about
- * power level changes because some biosen
- * do mean things to the maestro when they
- * change their power state.
- */
- }
-out:
- return 0;
-}
-
module_init(init_maestro);
module_exit(cleanup_maestro);
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
index 9ac4bf7e1e89..fbb9170e8e0a 100644
--- a/sound/oss/nec_vrc5477.c
+++ b/sound/oss/nec_vrc5477.c
@@ -2045,7 +2045,7 @@ static struct pci_driver vrc5477_ac97_driver = {
static int __init init_vrc5477_ac97(void)
{
printk("Vrc5477 AC97 driver: version v0.2 time " __TIME__ " " __DATE__ " by Jun Sun\n");
- return pci_module_init(&vrc5477_ac97_driver);
+ return pci_register_driver(&vrc5477_ac97_driver);
}
static void __exit cleanup_vrc5477_ac97(void)
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index 0ce2c404a730..7de079b202f2 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -24,8 +24,6 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include "sound_config.h"
@@ -49,7 +47,6 @@ static int nm256_grabInterrupt (struct nm256_info *card);
static int nm256_releaseInterrupt (struct nm256_info *card);
static irqreturn_t nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy);
static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
-static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data);
/* These belong in linux/pci.h. */
#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
@@ -992,15 +989,6 @@ nm256_install_mixer (struct nm256_info *card)
return 0;
}
-/* Perform a full reset on the hardware; this is invoked when an APM
- resume event occurs. */
-static void
-nm256_full_reset (struct nm256_info *card)
-{
- nm256_initHw (card);
- ac97_reset (&(card->mdev));
-}
-
/*
* See if the signature left by the NM256 BIOS is intact; if so, we use
* the associated address as the end of our audio buffer in the video
@@ -1053,7 +1041,6 @@ static int __devinit
nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
{
struct nm256_info *card;
- struct pm_dev *pmdev;
int x;
if (pci_enable_device(pcidev))
@@ -1234,43 +1221,10 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
nm256_install_mixer (card);
- pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), handle_pm_event);
- if (pmdev)
- pmdev->data = card;
-
return 1;
}
-/*
- * PM event handler, so the card is properly reinitialized after a power
- * event.
- */
-static int
-handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data)
-{
- struct nm256_info *crd = (struct nm256_info*) dev->data;
- if (crd) {
- switch (rqst) {
- case PM_SUSPEND:
- break;
- case PM_RESUME:
- {
- int playing = crd->playing;
- nm256_full_reset (crd);
- /*
- * A little ugly, but that's ok; pretend the
- * block we were playing is done.
- */
- if (playing)
- DMAbuf_outputintr (crd->dev_for_play, 1);
- }
- break;
- }
- }
- return 0;
-}
-
static int __devinit
nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid)
{
@@ -1690,13 +1644,12 @@ module_param(force_load, bool, 0);
static int __init do_init_nm256(void)
{
printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1p\n");
- return pci_module_init(&nm256_pci_driver);
+ return pci_register_driver(&nm256_pci_driver);
}
static void __exit cleanup_nm256 (void)
{
pci_unregister_driver(&nm256_pci_driver);
- pm_unregister_all (&handle_pm_event);
}
module_init(do_init_nm256);
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
index cd41d0e4706a..0e161c6a0477 100644
--- a/sound/oss/opl3sa2.c
+++ b/sound/oss/opl3sa2.c
@@ -69,8 +69,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
#include "sound_config.h"
#include "ad1848.h"
@@ -139,10 +137,6 @@ typedef struct {
struct pnp_dev* pdev;
int activated; /* Whether said devices have been activated */
#endif
-#ifdef CONFIG_PM_LEGACY
- unsigned int in_suspend;
- struct pm_dev *pmdev;
-#endif
unsigned int card;
int chipset; /* What's my version(s)? */
char *chipset_name;
@@ -341,22 +335,6 @@ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc)
}
}
-/* Currently only used for power management */
-#ifdef CONFIG_PM_LEGACY
-static void opl3sa2_mixer_restore(opl3sa2_state_t* devc)
-{
- if (devc) {
- opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
- opl3sa2_set_mic(devc, devc->mic);
-
- if (devc->chipset == CHIPSET_OPL3SA3) {
- opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
- opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
- }
- }
-}
-#endif /* CONFIG_PM_LEGACY */
-
static inline void arg_to_vol_mono(unsigned int vol, int* value)
{
int left;
@@ -552,7 +530,7 @@ static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct res
if (hw_config->slots[0] != -1) {
/* Did the MSS driver install? */
if(num_mixers == (initial_mixers + 1)) {
- /* The MSS mixer is installed, reroute mixers appropiately */
+ /* The MSS mixer is installed, reroute mixers appropriately */
AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
@@ -832,84 +810,6 @@ static struct pnp_driver opl3sa2_driver = {
/* End of component functions */
-#ifdef CONFIG_PM_LEGACY
-
-static DEFINE_SPINLOCK(opl3sa2_lock);
-
-/* Power Management support functions */
-static int opl3sa2_suspend(struct pm_dev *pdev, unsigned int pm_mode)
-{
- unsigned long flags;
- opl3sa2_state_t *p;
-
- if (!pdev)
- return -EINVAL;
-
- spin_lock_irqsave(&opl3sa2_lock,flags);
-
- p = (opl3sa2_state_t *) pdev->data;
- switch (pm_mode) {
- case 1:
- pm_mode = OPL3SA2_PM_MODE1;
- break;
- case 2:
- pm_mode = OPL3SA2_PM_MODE2;
- break;
- case 3:
- pm_mode = OPL3SA2_PM_MODE3;
- break;
- default:
- /* we don't know howto handle this... */
- spin_unlock_irqrestore(&opl3sa2_lock, flags);
- return -EBUSY;
- }
-
- p->in_suspend = 1;
-
- /* its supposed to automute before suspending, so we won't bother */
- opl3sa2_write(p->cfg_port, OPL3SA2_PM, pm_mode);
- /* wait a while for the clock oscillator to stabilise */
- mdelay(10);
-
- spin_unlock_irqrestore(&opl3sa2_lock,flags);
- return 0;
-}
-
-static int opl3sa2_resume(struct pm_dev *pdev)
-{
- unsigned long flags;
- opl3sa2_state_t *p;
-
- if (!pdev)
- return -EINVAL;
-
- p = (opl3sa2_state_t *) pdev->data;
- spin_lock_irqsave(&opl3sa2_lock,flags);
-
- /* I don't think this is necessary */
- opl3sa2_write(p->cfg_port, OPL3SA2_PM, OPL3SA2_PM_MODE0);
- opl3sa2_mixer_restore(p);
- p->in_suspend = 0;
-
- spin_unlock_irqrestore(&opl3sa2_lock,flags);
- return 0;
-}
-
-static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
-{
- unsigned long mode = (unsigned long)data;
-
- switch (rqst) {
- case PM_SUSPEND:
- return opl3sa2_suspend(pdev, mode);
-
- case PM_RESUME:
- return opl3sa2_resume(pdev);
- }
- return 0;
-}
-#endif /* CONFIG_PM_LEGACY */
-
/*
* Install OPL3-SA2 based card(s).
*
@@ -1021,12 +921,6 @@ static int __init init_opl3sa2(void)
/* ewww =) */
opl3sa2_state[card].card = card;
-#ifdef CONFIG_PM_LEGACY
- /* register our power management capabilities */
- opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback);
- if (opl3sa2_state[card].pmdev)
- opl3sa2_state[card].pmdev->data = &opl3sa2_state[card];
-#endif /* CONFIG_PM_LEGACY */
/*
* Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
@@ -1083,10 +977,6 @@ static void __exit cleanup_opl3sa2(void)
int card;
for(card = 0; card < opl3sa2_cards_num; card++) {
-#ifdef CONFIG_PM_LEGACY
- if (opl3sa2_state[card].pmdev)
- pm_unregister(opl3sa2_state[card].pmdev);
-#endif
if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) {
unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu);
}
diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
index 318dc51009fe..faa0b7919b65 100644
--- a/sound/oss/rme96xx.c
+++ b/sound/oss/rme96xx.c
@@ -1095,7 +1095,7 @@ static int __init init_rme96xx(void)
devices = ((devices-1) & RME96xx_MASK_DEVS) + 1;
printk(KERN_INFO RME_MESS" reserving %d dsp device(s)\n",devices);
numcards = 0;
- return pci_module_init(&rme96xx_driver);
+ return pci_register_driver(&rme96xx_driver);
}
static void __exit cleanup_rme96xx(void)
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
index 17d0e461f8d8..71b05e2f6977 100644
--- a/sound/oss/sonicvibes.c
+++ b/sound/oss/sonicvibes.c
@@ -2765,7 +2765,7 @@ static int __init init_sonicvibes(void)
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
#endif
- return pci_module_init(&sv_driver);
+ return pci_register_driver(&sv_driver);
}
static void __exit cleanup_sonicvibes(void)
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 5f0ad6bb43b9..a21c663e7e12 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -278,16 +278,14 @@ static char *card_names[] = {
};
static struct pci_device_id trident_pci_tbl[] = {
- {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX},
- {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX},
- {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018},
- {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451},
- {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050},
+ {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
+ PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX},
+ {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
+ 0, 0, TRIDENT_4D_NX},
+ {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018},
+ {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050),
+ 0, 0, CYBER5050},
{0,}
};
diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c
index 8dae59bd05a2..f8bd72e46f57 100644
--- a/sound/oss/ymfpci.c
+++ b/sound/oss/ymfpci.c
@@ -2680,7 +2680,7 @@ static struct pci_driver ymfpci_driver = {
static int __init ymf_init_module(void)
{
- return pci_module_init(&ymfpci_driver);
+ return pci_register_driver(&ymfpci_driver);
}
static void __exit ymf_cleanup_module (void)
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index d833349ed518..ce73f3eae78c 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -59,6 +59,14 @@
#include "harmony.h"
+static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for Harmony driver.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for Harmony driver.");
+
+
static struct parisc_device_id snd_harmony_devtable[] = {
/* bushmaster / flounder */
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A },
@@ -91,32 +99,32 @@ static unsigned int rate_bits[14] = {
HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
};
-static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraint_rates = {
.count = ARRAY_SIZE(snd_harmony_rates),
.list = snd_harmony_rates,
.mask = 0,
};
-inline unsigned long
-harmony_read(harmony_t *h, unsigned r)
+static inline unsigned long
+harmony_read(struct snd_harmony *h, unsigned r)
{
return __raw_readl(h->iobase + r);
}
-inline void
-harmony_write(harmony_t *h, unsigned r, unsigned long v)
+static inline void
+harmony_write(struct snd_harmony *h, unsigned r, unsigned long v)
{
__raw_writel(v, h->iobase + r);
}
-static void
-harmony_wait_for_control(harmony_t *h)
+static inline void
+harmony_wait_for_control(struct snd_harmony *h)
{
while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
}
-inline void
-harmony_reset(harmony_t *h)
+static inline void
+harmony_reset(struct snd_harmony *h)
{
harmony_write(h, HARMONY_RESET, 1);
mdelay(50);
@@ -124,7 +132,7 @@ harmony_reset(harmony_t *h)
}
static void
-harmony_disable_interrupts(harmony_t *h)
+harmony_disable_interrupts(struct snd_harmony *h)
{
u32 dstatus;
harmony_wait_for_control(h);
@@ -134,7 +142,7 @@ harmony_disable_interrupts(harmony_t *h)
}
static void
-harmony_enable_interrupts(harmony_t *h)
+harmony_enable_interrupts(struct snd_harmony *h)
{
u32 dstatus;
harmony_wait_for_control(h);
@@ -144,7 +152,7 @@ harmony_enable_interrupts(harmony_t *h)
}
static void
-harmony_mute(harmony_t *h)
+harmony_mute(struct snd_harmony *h)
{
unsigned long flags;
@@ -155,7 +163,7 @@ harmony_mute(harmony_t *h)
}
static void
-harmony_unmute(harmony_t *h)
+harmony_unmute(struct snd_harmony *h)
{
unsigned long flags;
@@ -166,7 +174,7 @@ harmony_unmute(harmony_t *h)
}
static void
-harmony_set_control(harmony_t *h)
+harmony_set_control(struct snd_harmony *h)
{
u32 ctrl;
unsigned long flags;
@@ -188,7 +196,7 @@ static irqreturn_t
snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
{
u32 dstatus;
- harmony_t *h = dev;
+ struct snd_harmony *h = dev;
spin_lock(&h->lock);
harmony_disable_interrupts(h);
@@ -253,7 +261,7 @@ snd_harmony_rate_bits(int rate)
return HARMONY_SR_44KHZ;
}
-static snd_pcm_hardware_t snd_harmony_playback =
+static struct snd_pcm_hardware snd_harmony_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
@@ -274,7 +282,7 @@ static snd_pcm_hardware_t snd_harmony_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_harmony_capture =
+static struct snd_pcm_hardware snd_harmony_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
@@ -296,15 +304,14 @@ static snd_pcm_hardware_t snd_harmony_capture =
};
static int
-snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd)
+snd_harmony_playback_trigger(struct snd_pcm_substream *ss, int cmd)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- unsigned long flags;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
if (h->st.capturing)
return -EBUSY;
- spin_lock_irqsave(&h->lock, flags);
+ spin_lock(&h->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
h->st.playing = 1;
@@ -323,25 +330,24 @@ snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_SUSPEND:
default:
- spin_unlock_irqrestore(&h->lock, flags);
+ spin_unlock(&h->lock);
snd_BUG();
return -EINVAL;
}
- spin_unlock_irqrestore(&h->lock, flags);
+ spin_unlock(&h->lock);
return 0;
}
static int
-snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd)
+snd_harmony_capture_trigger(struct snd_pcm_substream *ss, int cmd)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- unsigned long flags;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
if (h->st.playing)
return -EBUSY;
- spin_lock_irqsave(&h->lock, flags);
+ spin_lock(&h->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
h->st.capturing = 1;
@@ -360,17 +366,17 @@ snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
case SNDRV_PCM_TRIGGER_SUSPEND:
default:
- spin_unlock_irqrestore(&h->lock, flags);
+ spin_unlock(&h->lock);
snd_BUG();
return -EINVAL;
}
- spin_unlock_irqrestore(&h->lock, flags);
+ spin_unlock(&h->lock);
return 0;
}
static int
-snd_harmony_set_data_format(harmony_t *h, int fmt, int force)
+snd_harmony_set_data_format(struct snd_harmony *h, int fmt, int force)
{
int o = h->st.format;
int n;
@@ -400,10 +406,10 @@ snd_harmony_set_data_format(harmony_t *h, int fmt, int force)
}
static int
-snd_harmony_playback_prepare(snd_pcm_substream_t *ss)
+snd_harmony_playback_prepare(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
if (h->st.capturing)
return -EBUSY;
@@ -430,10 +436,10 @@ snd_harmony_playback_prepare(snd_pcm_substream_t *ss)
}
static int
-snd_harmony_capture_prepare(snd_pcm_substream_t *ss)
+snd_harmony_capture_prepare(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
if (h->st.playing)
return -EBUSY;
@@ -460,10 +466,10 @@ snd_harmony_capture_prepare(snd_pcm_substream_t *ss)
}
static snd_pcm_uframes_t
-snd_harmony_playback_pointer(snd_pcm_substream_t *ss)
+snd_harmony_playback_pointer(struct snd_pcm_substream *ss)
{
- snd_pcm_runtime_t *rt = ss->runtime;
- harmony_t *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
unsigned long pcuradd;
unsigned long played;
@@ -489,10 +495,10 @@ snd_harmony_playback_pointer(snd_pcm_substream_t *ss)
}
static snd_pcm_uframes_t
-snd_harmony_capture_pointer(snd_pcm_substream_t *ss)
+snd_harmony_capture_pointer(struct snd_pcm_substream *ss)
{
- snd_pcm_runtime_t *rt = ss->runtime;
- harmony_t *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
unsigned long rcuradd;
unsigned long caught;
@@ -518,10 +524,10 @@ snd_harmony_capture_pointer(snd_pcm_substream_t *ss)
}
static int
-snd_harmony_playback_open(snd_pcm_substream_t *ss)
+snd_harmony_playback_open(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
int err;
h->psubs = ss;
@@ -537,10 +543,10 @@ snd_harmony_playback_open(snd_pcm_substream_t *ss)
}
static int
-snd_harmony_capture_open(snd_pcm_substream_t *ss)
+snd_harmony_capture_open(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
+ struct snd_pcm_runtime *rt = ss->runtime;
int err;
h->csubs = ss;
@@ -556,27 +562,27 @@ snd_harmony_capture_open(snd_pcm_substream_t *ss)
}
static int
-snd_harmony_playback_close(snd_pcm_substream_t *ss)
+snd_harmony_playback_close(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
h->psubs = NULL;
return 0;
}
static int
-snd_harmony_capture_close(snd_pcm_substream_t *ss)
+snd_harmony_capture_close(struct snd_pcm_substream *ss)
{
- harmony_t *h = snd_pcm_substream_chip(ss);
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
h->csubs = NULL;
return 0;
}
static int
-snd_harmony_hw_params(snd_pcm_substream_t *ss,
- snd_pcm_hw_params_t *hw)
+snd_harmony_hw_params(struct snd_pcm_substream *ss,
+ struct snd_pcm_hw_params *hw)
{
int err;
- harmony_t *h = snd_pcm_substream_chip(ss);
+ struct snd_harmony *h = snd_pcm_substream_chip(ss);
err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw));
if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
@@ -586,12 +592,12 @@ snd_harmony_hw_params(snd_pcm_substream_t *ss,
}
static int
-snd_harmony_hw_free(snd_pcm_substream_t *ss)
+snd_harmony_hw_free(struct snd_pcm_substream *ss)
{
return snd_pcm_lib_free_pages(ss);
}
-static snd_pcm_ops_t snd_harmony_playback_ops = {
+static struct snd_pcm_ops snd_harmony_playback_ops = {
.open = snd_harmony_playback_open,
.close = snd_harmony_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -602,7 +608,7 @@ static snd_pcm_ops_t snd_harmony_playback_ops = {
.pointer = snd_harmony_playback_pointer,
};
-static snd_pcm_ops_t snd_harmony_capture_ops = {
+static struct snd_pcm_ops snd_harmony_capture_ops = {
.open = snd_harmony_capture_open,
.close = snd_harmony_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -614,9 +620,9 @@ static snd_pcm_ops_t snd_harmony_capture_ops = {
};
static int
-snd_harmony_pcm_init(harmony_t *h)
+snd_harmony_pcm_init(struct snd_harmony *h)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
harmony_disable_interrupts(h);
@@ -677,15 +683,15 @@ snd_harmony_pcm_init(harmony_t *h)
}
static void
-snd_harmony_set_new_gain(harmony_t *h)
+snd_harmony_set_new_gain(struct snd_harmony *h)
{
harmony_wait_for_control(h);
harmony_write(h, HARMONY_GAINCTL, h->st.gain);
}
static int
-snd_harmony_mixercontrol_info(snd_kcontrol_t *kc,
- snd_ctl_elem_info_t *uinfo)
+snd_harmony_mixercontrol_info(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kc->private_value >> 16) & 0xff;
int left_shift = (kc->private_value) & 0xff;
@@ -701,18 +707,17 @@ snd_harmony_mixercontrol_info(snd_kcontrol_t *kc,
}
static int
-snd_harmony_volume_get(snd_kcontrol_t *kc,
- snd_ctl_elem_value_t *ucontrol)
+snd_harmony_volume_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
{
- harmony_t *h = snd_kcontrol_chip(kc);
+ struct snd_harmony *h = snd_kcontrol_chip(kc);
int shift_left = (kc->private_value) & 0xff;
int shift_right = (kc->private_value >> 8) & 0xff;
int mask = (kc->private_value >> 16) & 0xff;
int invert = (kc->private_value >> 24) & 0xff;
int left, right;
- unsigned long flags;
- spin_lock_irqsave(&h->mixer_lock, flags);
+ spin_lock_irq(&h->mixer_lock);
left = (h->st.gain >> shift_left) & mask;
right = (h->st.gain >> shift_right) & mask;
@@ -725,25 +730,24 @@ snd_harmony_volume_get(snd_kcontrol_t *kc,
if (shift_left != shift_right)
ucontrol->value.integer.value[1] = right;
- spin_unlock_irqrestore(&h->mixer_lock, flags);
+ spin_unlock_irq(&h->mixer_lock);
return 0;
}
static int
-snd_harmony_volume_put(snd_kcontrol_t *kc,
- snd_ctl_elem_value_t *ucontrol)
+snd_harmony_volume_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
{
- harmony_t *h = snd_kcontrol_chip(kc);
+ struct snd_harmony *h = snd_kcontrol_chip(kc);
int shift_left = (kc->private_value) & 0xff;
int shift_right = (kc->private_value >> 8) & 0xff;
int mask = (kc->private_value >> 16) & 0xff;
int invert = (kc->private_value >> 24) & 0xff;
int left, right;
int old_gain = h->st.gain;
- unsigned long flags;
- spin_lock_irqsave(&h->mixer_lock, flags);
+ spin_lock_irq(&h->mixer_lock);
left = ucontrol->value.integer.value[0] & mask;
if (invert)
@@ -761,14 +765,14 @@ snd_harmony_volume_put(snd_kcontrol_t *kc,
snd_harmony_set_new_gain(h);
- spin_unlock_irqrestore(&h->mixer_lock, flags);
+ spin_unlock_irq(&h->mixer_lock);
return h->st.gain != old_gain;
}
static int
-snd_harmony_captureroute_info(snd_kcontrol_t *kc,
- snd_ctl_elem_info_t *uinfo)
+snd_harmony_captureroute_info(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "Line", "Mic" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -782,33 +786,31 @@ snd_harmony_captureroute_info(snd_kcontrol_t *kc,
}
static int
-snd_harmony_captureroute_get(snd_kcontrol_t *kc,
- snd_ctl_elem_value_t *ucontrol)
+snd_harmony_captureroute_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
{
- harmony_t *h = snd_kcontrol_chip(kc);
+ struct snd_harmony *h = snd_kcontrol_chip(kc);
int value;
- unsigned long flags;
- spin_lock_irqsave(&h->mixer_lock, flags);
+ spin_lock_irq(&h->mixer_lock);
value = (h->st.gain >> HARMONY_GAIN_IS_SHIFT) & 1;
ucontrol->value.enumerated.item[0] = value;
- spin_unlock_irqrestore(&h->mixer_lock, flags);
+ spin_unlock_irq(&h->mixer_lock);
return 0;
}
static int
-snd_harmony_captureroute_put(snd_kcontrol_t *kc,
- snd_ctl_elem_value_t *ucontrol)
+snd_harmony_captureroute_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
{
- harmony_t *h = snd_kcontrol_chip(kc);
+ struct snd_harmony *h = snd_kcontrol_chip(kc);
int value;
int old_gain = h->st.gain;
- unsigned long flags;
- spin_lock_irqsave(&h->mixer_lock, flags);
+ spin_lock_irq(&h->mixer_lock);
value = ucontrol->value.enumerated.item[0] & 1;
h->st.gain &= ~HARMONY_GAIN_IS_MASK;
@@ -816,13 +818,12 @@ snd_harmony_captureroute_put(snd_kcontrol_t *kc,
snd_harmony_set_new_gain(h);
- spin_unlock_irqrestore(&h->mixer_lock, flags);
+ spin_unlock_irq(&h->mixer_lock);
return h->st.gain != old_gain;
}
-#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
- sizeof(snd_kcontrol_new_t))
+#define HARMONY_CONTROLS ARRAY_SIZE(snd_harmony_controls)
#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -831,7 +832,7 @@ snd_harmony_captureroute_put(snd_kcontrol_t *kc,
.private_value = ((left_shift) | ((right_shift) << 8) | \
((mask) << 16) | ((invert) << 24)) }
-static snd_kcontrol_new_t snd_harmony_controls[] = {
+static struct snd_kcontrol_new snd_harmony_controls[] = {
HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT,
HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
@@ -854,7 +855,7 @@ static snd_kcontrol_new_t snd_harmony_controls[] = {
};
static void __init
-snd_harmony_mixer_reset(harmony_t *h)
+snd_harmony_mixer_reset(struct snd_harmony *h)
{
harmony_mute(h);
harmony_reset(h);
@@ -863,9 +864,9 @@ snd_harmony_mixer_reset(harmony_t *h)
}
static int __init
-snd_harmony_mixer_init(harmony_t *h)
+snd_harmony_mixer_init(struct snd_harmony *h)
{
- snd_card_t *card = h->card;
+ struct snd_card *card = h->card;
int idx, err;
snd_assert(h != NULL, return -EINVAL);
@@ -884,7 +885,7 @@ snd_harmony_mixer_init(harmony_t *h)
}
static int
-snd_harmony_free(harmony_t *h)
+snd_harmony_free(struct snd_harmony *h)
{
if (h->gdma.addr)
snd_dma_free_pages(&h->gdma);
@@ -904,38 +905,33 @@ snd_harmony_free(harmony_t *h)
}
static int
-snd_harmony_dev_free(snd_device_t *dev)
+snd_harmony_dev_free(struct snd_device *dev)
{
- harmony_t *h = dev->device_data;
+ struct snd_harmony *h = dev->device_data;
return snd_harmony_free(h);
}
static int __devinit
-snd_harmony_create(snd_card_t *card,
+snd_harmony_create(struct snd_card *card,
struct parisc_device *padev,
- harmony_t **rchip)
+ struct snd_harmony **rchip)
{
int err;
- harmony_t *h;
- static snd_device_ops_t ops = {
+ struct snd_harmony *h;
+ static struct snd_device_ops ops = {
.dev_free = snd_harmony_dev_free,
};
*rchip = NULL;
- h = kmalloc(sizeof(*h), GFP_KERNEL);
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
if (h == NULL)
return -ENOMEM;
- memset(&h->st, 0, sizeof(h->st));
- memset(&h->stats, 0, sizeof(h->stats));
- memset(&h->pbuf, 0, sizeof(h->pbuf));
- memset(&h->cbuf, 0, sizeof(h->cbuf));
-
h->hpa = padev->hpa.start;
h->card = card;
h->dev = padev;
- h->irq = padev->irq;
+ h->irq = -1;
h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE);
if (h->iobase == NULL) {
printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
@@ -944,13 +940,14 @@ snd_harmony_create(snd_card_t *card,
goto free_and_ret;
}
- err = request_irq(h->irq, snd_harmony_interrupt, 0,
+ err = request_irq(padev->irq, snd_harmony_interrupt, 0,
"harmony", h);
if (err) {
printk(KERN_ERR PFX "could not obtain interrupt %d",
- h->irq);
+ padev->irq);
goto free_and_ret;
}
+ h->irq = padev->irq;
spin_lock_init(&h->mixer_lock);
spin_lock_init(&h->lock);
@@ -975,35 +972,24 @@ static int __devinit
snd_harmony_probe(struct parisc_device *padev)
{
int err;
- static int dev;
- snd_card_t *card;
- harmony_t *h;
- static int index = SNDRV_DEFAULT_IDX1;
- static char *id = SNDRV_DEFAULT_STR1;
-
- h = parisc_get_drvdata(padev);
- if (h != NULL) {
- return -ENODEV;
- }
+ struct snd_card *card;
+ struct snd_harmony *h;
card = snd_card_new(index, id, THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
err = snd_harmony_create(card, padev, &h);
- if (err < 0) {
+ if (err < 0)
goto free_and_ret;
- }
err = snd_harmony_pcm_init(h);
- if (err < 0) {
+ if (err < 0)
goto free_and_ret;
- }
err = snd_harmony_mixer_init(h);
- if (err < 0) {
+ if (err < 0)
goto free_and_ret;
- }
strcpy(card->driver, "harmony");
strcpy(card->shortname, "Harmony");
@@ -1011,13 +997,10 @@ snd_harmony_probe(struct parisc_device *padev)
card->shortname, h->hpa, h->irq);
err = snd_card_register(card);
- if (err < 0) {
+ if (err < 0)
goto free_and_ret;
- }
-
- dev++;
- parisc_set_drvdata(padev, h);
+ parisc_set_drvdata(padev, card);
return 0;
free_and_ret:
@@ -1028,8 +1011,8 @@ free_and_ret:
static int __devexit
snd_harmony_remove(struct parisc_device *padev)
{
- harmony_t *h = parisc_get_drvdata(padev);
- snd_card_free(h->card);
+ snd_card_free(parisc_get_drvdata(padev));
+ parisc_set_drvdata(padev, NULL);
return 0;
}
@@ -1043,28 +1026,13 @@ static struct parisc_driver snd_harmony_driver = {
static int __init
alsa_harmony_init(void)
{
- int err;
-
- err = register_parisc_driver(&snd_harmony_driver);
- if (err < 0) {
- printk(KERN_ERR PFX "device not found\n");
- return err;
- }
-
- return 0;
+ return register_parisc_driver(&snd_harmony_driver);
}
static void __exit
alsa_harmony_fini(void)
{
- int err;
-
- err = unregister_parisc_driver(&snd_harmony_driver);
- if (err < 0) {
- printk(KERN_ERR PFX "failed to unregister\n");
- }
-
- return;
+ unregister_parisc_driver(&snd_harmony_driver);
}
MODULE_LICENSE("GPL");
diff --git a/sound/parisc/harmony.h b/sound/parisc/harmony.h
index 526c52389de2..2e434523fedf 100644
--- a/sound/parisc/harmony.h
+++ b/sound/parisc/harmony.h
@@ -13,7 +13,7 @@ struct harmony_buffer {
int coherent;
};
-typedef struct snd_card_harmony {
+struct snd_harmony {
int irq;
unsigned long hpa; /* hard physical address */
@@ -44,15 +44,15 @@ typedef struct snd_card_harmony {
unsigned long silence_intr;
} stats;
- snd_pcm_t *pcm;
- snd_card_t *card;
- snd_pcm_substream_t *psubs;
- snd_pcm_substream_t *csubs;
- snd_info_entry_t *proc;
+ struct snd_pcm *pcm;
+ struct snd_card *card;
+ struct snd_pcm_substream *psubs;
+ struct snd_pcm_substream *csubs;
+ struct snd_info_entry *proc;
spinlock_t lock;
spinlock_t mixer_lock;
-} harmony_t;
+};
#define MAX_PCM_DEVICES 1
#define MAX_PCM_SUBSTREAMS 4
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 0fb16cf335ea..1e2e19305e38 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -3,6 +3,31 @@
menu "PCI devices"
depends on SND!=n && PCI
+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
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ Say Y here to include support for soundcards based on Avance Logic
+ ALS4000 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-als4000.
+
config SND_ALI5451
tristate "ALi M5451 PCI Audio Controller"
depends on SND
@@ -119,6 +144,44 @@ config SND_BT87X_OVERCLOCK
Higher sample rates won't hurt your hardware, but audio
quality may suffer.
+config SND_CA0106
+ tristate "SB Audigy LS / Live 24bit"
+ depends on SND
+ select SND_AC97_CODEC
+ select SND_RAWMIDI
+ help
+ Say Y here to include support for the Sound Blaster Audigy LS
+ and Live 24bit.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-ca0106.
+
+config SND_CMIPCI
+ tristate "C-Media 8738, 8338"
+ depends on SND
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_PCM
+ help
+ If you want to use soundcards based on C-Media CMI8338 or CMI8738
+ chips, say Y here and read
+ <file:Documentation/sound/alsa/CMIPCI.txt>.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-cmipci.
+
+config SND_CS4281
+ tristate "Cirrus Logic (Sound Fusion) CS4281"
+ depends on SND
+ select SND_OPL3_LIB
+ select SND_RAWMIDI
+ select SND_AC97_CODEC
+ help
+ Say Y here to include support for Cirrus Logic CS4281 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-cs4281.
+
config SND_CS46XX
tristate "Cirrus Logic (Sound Fusion) CS4280/CS461x/CS462x/CS463x"
depends on SND
@@ -139,17 +202,18 @@ config SND_CS46XX_NEW_DSP
This works better than the old code, so say Y.
-config SND_CS4281
- tristate "Cirrus Logic (Sound Fusion) CS4281"
- depends on SND
- select SND_OPL3_LIB
- select SND_RAWMIDI
+config SND_CS5535AUDIO
+ tristate "CS5535 Audio"
+ depends on SND && X86 && !X86_64
+ select SND_PCM
select SND_AC97_CODEC
help
- Say Y here to include support for Cirrus Logic CS4281 chips.
+ Say Y here to include support for audio on CS5535 chips. It is
+ referred to as NS CS5535 IO or AMD CS5535 IO companion in
+ various literature.
To compile this driver as a module, choose M here: the module
- will be called snd-cs4281.
+ will be called snd-cs5535audio.
config SND_EMU10K1
tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
@@ -180,83 +244,89 @@ config SND_EMU10K1X
To compile this driver as a module, choose M here: the module
will be called snd-emu10k1x.
-config SND_CA0106
- tristate "SB Audigy LS / Live 24bit"
+config SND_ENS1370
+ tristate "(Creative) Ensoniq AudioPCI 1370"
depends on SND
- select SND_AC97_CODEC
select SND_RAWMIDI
+ select SND_PCM
help
- Say Y here to include support for the Sound Blaster Audigy LS
- and Live 24bit.
+ Say Y here to include support for Ensoniq AudioPCI ES1370 chips.
To compile this driver as a module, choose M here: the module
- will be called snd-ca0106.
+ will be called snd-ens1370.
-config SND_KORG1212
- tristate "Korg 1212 IO"
+config SND_ENS1371
+ tristate "(Creative) Ensoniq AudioPCI 1371/1373"
depends on SND
- select SND_PCM
+ select SND_RAWMIDI
+ select SND_AC97_CODEC
help
- Say Y here to include support for Korg 1212IO soundcards.
+ Say Y here to include support for Ensoniq AudioPCI ES1371 chips and
+ Sound Blaster PCI 64 or 128 soundcards.
To compile this driver as a module, choose M here: the module
- will be called snd-korg1212.
+ will be called snd-ens1371.
-config SND_MIXART
- tristate "Digigram miXart"
+config SND_ES1938
+ tristate "ESS ES1938/1946/1969 (Solo-1)"
depends on SND
- select SND_HWDEP
- select SND_PCM
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
help
- If you want to use Digigram miXart soundcards, say Y here and
- read <file:Documentation/sound/alsa/MIXART.txt>.
+ Say Y here to include support for soundcards based on ESS Solo-1
+ (ES1938, ES1946, ES1969) chips.
To compile this driver as a module, choose M here: the module
- will be called snd-mixart.
+ will be called snd-es1938.
-config SND_NM256
- tristate "NeoMagic NM256AV/ZX"
+config SND_ES1968
+ tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
depends on SND
+ select SND_MPU401_UART
select SND_AC97_CODEC
help
- Say Y here to include support for NeoMagic NM256AV/ZX chips.
+ Say Y here to include support for soundcards based on ESS Maestro
+ 1/2/2E chips.
To compile this driver as a module, choose M here: the module
- will be called snd-nm256.
+ will be called snd-es1968.
-config SND_RME32
- tristate "RME Digi32, 32/8, 32 PRO"
+config SND_FM801
+ tristate "ForteMedia FM801"
depends on SND
- select SND_PCM
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
help
- Say Y to include support for RME Digi32, Digi32 PRO and
- Digi32/8 (Sek'd Prodif32, Prodif96 and Prodif Gold) audio
- devices.
+ Say Y here to include support for soundcards based on the ForteMedia
+ FM801 chip.
To compile this driver as a module, choose M here: the module
- will be called snd-rme32.
+ will be called snd-fm801.
-config SND_RME96
- tristate "RME Digi96, 96/8, 96/8 PRO"
- depends on SND
- select SND_PCM
+config SND_FM801_TEA575X
+ tristate "ForteMedia FM801 + TEA5757 tuner"
+ depends on SND_FM801
+ select VIDEO_DEV
help
- Say Y here to include support for RME Digi96, Digi96/8 and
- Digi96/8 PRO/PAD/PST soundcards.
+ Say Y here to include support for soundcards based on the ForteMedia
+ FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
+ Forte SF256-PCS-02).
To compile this driver as a module, choose M here: the module
- will be called snd-rme96.
+ will be called snd-fm801-tea575x.
-config SND_RME9652
- tristate "RME Digi9652 (Hammerfall)"
+config SND_HDA_INTEL
+ tristate "Intel HD Audio"
depends on SND
select SND_PCM
help
- Say Y here to include support for RME Hammerfall (RME
- Digi9652/Digi9636) soundcards.
+ Say Y here to include support for Intel "High Definition
+ Audio" (Azalia) motherboard devices.
To compile this driver as a module, choose M here: the module
- will be called snd-rme9652.
+ will be called snd-hda-intel.
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
@@ -284,117 +354,73 @@ config SND_HDSPM
To compile this driver as a module, choose M here: the module
will be called snd-hdspm.
-config SND_TRIDENT
- tristate "Trident 4D-Wave DX/NX; SiS 7018"
- depends on SND
- select SND_MPU401_UART
- select SND_AC97_CODEC
- help
- Say Y here to include support for soundcards based on Trident
- 4D-Wave DX/NX or SiS 7018 chips.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-trident.
-
-config SND_YMFPCI
- tristate "Yamaha YMF724/740/744/754"
+config SND_ICE1712
+ tristate "ICEnsemble ICE1712 (Envy24)"
depends on SND
- select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
help
- Say Y here to include support for Yamaha PCI audio chips -
- YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
-
- 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.
+ Say Y here to include support for soundcards based on the
+ ICE1712 (Envy24) chip.
-config SND_ALS4000
- tristate "Avance Logic ALS4000"
- depends on SND && ISA_DMA_API
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_PCM
- help
- Say Y here to include support for soundcards based on Avance Logic
- ALS4000 chips.
+ Currently supported hardware is: M-Audio Delta 1010(LT),
+ DiO 2496, 66, 44, 410, Audiophile 24/96; Digigram VX442;
+ TerraTec EWX 24/96, EWS 88MT, 88D, DMX 6Fire, Phase 88;
+ Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8.
To compile this driver as a module, choose M here: the module
- will be called snd-als4000.
+ will be called snd-ice1712.
-config SND_CMIPCI
- tristate "C-Media 8738, 8338"
+config SND_ICE1724
+ tristate "ICE/VT1724/1720 (Envy24HT/PT)"
depends on SND
- select SND_OPL3_LIB
select SND_MPU401_UART
- select SND_PCM
+ select SND_AC97_CODEC
help
- If you want to use soundcards based on C-Media CMI8338 or CMI8738
- chips, say Y here and read
- <file:Documentation/sound/alsa/CMIPCI.txt>.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-cmipci.
+ Say Y here to include support for soundcards based on
+ ICE/VT1724/1720 (Envy24HT/PT) chips.
-config SND_ENS1370
- tristate "(Creative) Ensoniq AudioPCI 1370"
- depends on SND
- select SND_RAWMIDI
- select SND_PCM
- help
- Say Y here to include support for Ensoniq AudioPCI ES1370 chips.
+ Currently supported hardware is: AMP AUDIO2000; M-Audio
+ Revolution 7.1; TerraTec Aureon 5.1 Sky, 7.1 Space/Universe;
+ AudioTrak Prodigy 7.1; Pontis MS300; Albatron K8X800 Pro II;
+ Chaintech ZNF3-150/250.
To compile this driver as a module, choose M here: the module
- will be called snd-ens1370.
+ will be called snd-ice1724.
-config SND_ENS1371
- tristate "(Creative) Ensoniq AudioPCI 1371/1373"
+config SND_INTEL8X0
+ tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
depends on SND
- select SND_RAWMIDI
select SND_AC97_CODEC
help
- Say Y here to include support for Ensoniq AudioPCI ES1371 chips and
- Sound Blaster PCI 64 or 128 soundcards.
+ Say Y here to include support for the integrated AC97 sound
+ device on motherboards with Intel/SiS/nVidia/AMD chipsets, or
+ ALi chipsets using the M5455 Audio Controller. (There is a
+ separate driver for ALi M5451 Audio Controllers.)
To compile this driver as a module, choose M here: the module
- will be called snd-ens1371.
+ will be called snd-intel8x0.
-config SND_ES1938
- tristate "ESS ES1938/1946/1969 (Solo-1)"
- depends on SND
- select SND_OPL3_LIB
- select SND_MPU401_UART
+config SND_INTEL8X0M
+ tristate "Intel/SiS/nVidia/AMD MC97 Modem (EXPERIMENTAL)"
+ depends on SND && EXPERIMENTAL
select SND_AC97_CODEC
help
- Say Y here to include support for soundcards based on ESS Solo-1
- (ES1938, ES1946, ES1969) chips.
+ Say Y here to include support for the integrated MC97 modem on
+ motherboards with Intel/SiS/nVidia/AMD chipsets.
To compile this driver as a module, choose M here: the module
- will be called snd-es1938.
+ will be called snd-intel8x0m.
-config SND_ES1968
- tristate "ESS ES1968/1978 (Maestro-1/2/2E)"
+config SND_KORG1212
+ tristate "Korg 1212 IO"
depends on SND
- select SND_MPU401_UART
- select SND_AC97_CODEC
+ select SND_PCM
help
- Say Y here to include support for soundcards based on ESS Maestro
- 1/2/2E chips.
+ Say Y here to include support for Korg 1212IO soundcards.
To compile this driver as a module, choose M here: the module
- will be called snd-es1968.
+ will be called snd-korg1212.
config SND_MAESTRO3
tristate "ESS Allegro/Maestro3"
@@ -407,88 +433,72 @@ config SND_MAESTRO3
To compile this driver as a module, choose M here: the module
will be called snd-maestro3.
-config SND_FM801
- tristate "ForteMedia FM801"
+config SND_MIXART
+ tristate "Digigram miXart"
depends on SND
- select SND_OPL3_LIB
- select SND_MPU401_UART
- select SND_AC97_CODEC
+ select SND_HWDEP
+ select SND_PCM
help
- Say Y here to include support for soundcards based on the ForteMedia
- FM801 chip.
+ If you want to use Digigram miXart soundcards, say Y here and
+ read <file:Documentation/sound/alsa/MIXART.txt>.
To compile this driver as a module, choose M here: the module
- will be called snd-fm801.
+ will be called snd-mixart.
-config SND_FM801_TEA575X
- tristate "ForteMedia FM801 + TEA5757 tuner"
- depends on SND_FM801
- select VIDEO_DEV
+config SND_NM256
+ tristate "NeoMagic NM256AV/ZX"
+ depends on SND
+ select SND_AC97_CODEC
help
- Say Y here to include support for soundcards based on the ForteMedia
- FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
- Forte SF256-PCS-02).
+ Say Y here to include support for NeoMagic NM256AV/ZX chips.
To compile this driver as a module, choose M here: the module
- will be called snd-fm801-tea575x.
+ will be called snd-nm256.
-config SND_ICE1712
- tristate "ICEnsemble ICE1712 (Envy24)"
+config SND_PCXHR
+ tristate "Digigram PCXHR"
depends on SND
- select SND_MPU401_UART
- select SND_AC97_CODEC
+ select SND_PCM
+ select SND_HWDEP
help
- Say Y here to include support for soundcards based on the
- ICE1712 (Envy24) chip.
-
- Currently supported hardware is: M-Audio Delta 1010(LT),
- DiO 2496, 66, 44, 410, Audiophile 24/96; Digigram VX442;
- TerraTec EWX 24/96, EWS 88MT, 88D, DMX 6Fire, Phase 88;
- Hoontech SoundTrack DSP 24/Value/Media7.1; Event EZ8.
+ Say Y here to include support for Digigram PCXHR boards.
To compile this driver as a module, choose M here: the module
- will be called snd-ice1712.
+ will be called snd-pcxhr.
-config SND_ICE1724
- tristate "ICE/VT1724/1720 (Envy24HT/PT)"
+config SND_RME32
+ tristate "RME Digi32, 32/8, 32 PRO"
depends on SND
- select SND_MPU401_UART
- select SND_AC97_CODEC
+ select SND_PCM
help
- Say Y here to include support for soundcards based on
- ICE/VT1724/1720 (Envy24HT/PT) chips.
-
- Currently supported hardware is: AMP AUDIO2000; M-Audio
- Revolution 7.1; TerraTec Aureon 5.1 Sky, 7.1 Space/Universe;
- AudioTrak Prodigy 7.1; Pontis MS300; Albatron K8X800 Pro II;
- Chaintech ZNF3-150/250.
+ Say Y to include support for RME Digi32, Digi32 PRO and
+ Digi32/8 (Sek'd Prodif32, Prodif96 and Prodif Gold) audio
+ devices.
To compile this driver as a module, choose M here: the module
- will be called snd-ice1724.
+ will be called snd-rme32.
-config SND_INTEL8X0
- tristate "Intel/SiS/nVidia/AMD/ALi AC97 Controller"
+config SND_RME96
+ tristate "RME Digi96, 96/8, 96/8 PRO"
depends on SND
- select SND_AC97_CODEC
+ select SND_PCM
help
- Say Y here to include support for the integrated AC97 sound
- device on motherboards with Intel/SiS/nVidia/AMD chipsets, or
- ALi chipsets using the M5455 Audio Controller. (There is a
- separate driver for ALi M5451 Audio Controllers.)
+ Say Y here to include support for RME Digi96, Digi96/8 and
+ Digi96/8 PRO/PAD/PST soundcards.
To compile this driver as a module, choose M here: the module
- will be called snd-intel8x0.
+ will be called snd-rme96.
-config SND_INTEL8X0M
- tristate "Intel/SiS/nVidia/AMD MC97 Modem (EXPERIMENTAL)"
- depends on SND && EXPERIMENTAL
- select SND_AC97_CODEC
+config SND_RME9652
+ tristate "RME Digi9652 (Hammerfall)"
+ depends on SND
+ select SND_PCM
help
- Say Y here to include support for the integrated MC97 modem on
- motherboards with Intel/SiS/nVidia/AMD chipsets.
+ Say Y here to include support for RME Hammerfall (RME
+ Digi9652/Digi9636) soundcards.
To compile this driver as a module, choose M here: the module
- will be called snd-intel8x0m.
+ will be called snd-rme9652.
config SND_SONICVIBES
tristate "S3 SonicVibes"
@@ -503,6 +513,18 @@ config SND_SONICVIBES
To compile this driver as a module, choose M here: the module
will be called snd-sonicvibes.
+config SND_TRIDENT
+ tristate "Trident 4D-Wave DX/NX; SiS 7018"
+ depends on SND
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
+ help
+ Say Y here to include support for soundcards based on Trident
+ 4D-Wave DX/NX or SiS 7018 chips.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-trident.
+
config SND_VIA82XX
tristate "VIA 82C686A/B, 8233/8235 AC97 Controller"
depends on SND
@@ -536,15 +558,17 @@ config SND_VX222
To compile this driver as a module, choose M here: the module
will be called snd-vx222.
-config SND_HDA_INTEL
- tristate "Intel HD Audio"
+config SND_YMFPCI
+ tristate "Yamaha YMF724/740/744/754"
depends on SND
- select SND_PCM
+ select SND_OPL3_LIB
+ select SND_MPU401_UART
+ select SND_AC97_CODEC
help
- Say Y here to include support for Intel "High Definition
- Audio" (Azalia) motherboard devices.
+ Say Y here to include support for Yamaha PCI audio chips -
+ YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
To compile this driver as a module, choose M here: the module
- will be called snd-hda-intel.
+ will be called snd-ymfpci.
endmenu
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index 42fabfcfc2a9..a6c3cd58fe94 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -54,12 +54,14 @@ obj-$(CONFIG_SND) += \
au88x0/ \
ca0106/ \
cs46xx/ \
+ cs5535audio/ \
emu10k1/ \
hda/ \
ice1712/ \
korg1212/ \
mixart/ \
nm256/ \
+ pcxhr/ \
rme9652/ \
trident/ \
ymfpci/ \
diff --git a/sound/pci/ac97/ac97_bus.c b/sound/pci/ac97/ac97_bus.c
index ec70fadde7d9..66de2c2f1554 100644
--- a/sound/pci/ac97/ac97_bus.c
+++ b/sound/pci/ac97/ac97_bus.c
@@ -18,7 +18,7 @@
/*
* Let drivers decide whether they want to support given codec from their
- * probe method. Drivers have direct access to the ac97_t structure and may
+ * probe method. Drivers have direct access to the struct snd_ac97 structure and may
* decide based on the id field amongst other things.
*/
static int ac97_bus_match(struct device *dev, struct device_driver *drv)
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 9bde76c4c6a2..3020ca2b602b 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -50,16 +50,16 @@ MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
*/
-typedef struct {
+struct ac97_codec_id {
unsigned int id;
unsigned int mask;
const char *name;
- int (*patch)(ac97_t *ac97);
- int (*mpatch)(ac97_t *ac97);
+ int (*patch)(struct snd_ac97 *ac97);
+ int (*mpatch)(struct snd_ac97 *ac97);
unsigned int flags;
-} ac97_codec_id_t;
+};
-static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
+static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = {
{ 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL },
{ 0x41445300, 0xffffff00, "Analog Devices", NULL, NULL },
{ 0x414c4300, 0xffffff00, "Realtek", NULL, NULL },
@@ -86,7 +86,7 @@ static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
{ 0, 0, NULL, NULL, NULL }
};
-static const ac97_codec_id_t snd_ac97_codec_ids[] = {
+static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x414b4d00, 0xffffffff, "AK4540", NULL, NULL },
{ 0x414b4d01, 0xffffffff, "AK4542", NULL, NULL },
{ 0x414b4d02, 0xffffffff, "AK4543", NULL, NULL },
@@ -137,7 +137,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x43585421, 0xffffffff, "HSD11246", NULL, NULL }, // SmartMC II
{ 0x43585428, 0xfffffff8, "Cx20468", patch_conexant, NULL }, // SmartAMC fixme: the mask might be different
{ 0x44543031, 0xfffffff0, "DT0398", NULL, NULL },
-{ 0x454d4328, 0xffffffff, "28028", NULL, NULL }, // same as TR28028?
+{ 0x454d4328, 0xffffffff, "EM28028", NULL, NULL }, // same as TR28028?
{ 0x45838308, 0xffffffff, "ESS1988", NULL, NULL },
{ 0x48525300, 0xffffff00, "HMP9701", NULL, NULL },
{ 0x49434501, 0xffffffff, "ICE1230", NULL, NULL },
@@ -184,48 +184,12 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0, 0, NULL, NULL, NULL }
};
-const char *snd_ac97_stereo_enhancements[] =
-{
- /* 0 */ "No 3D Stereo Enhancement",
- /* 1 */ "Analog Devices Phat Stereo",
- /* 2 */ "Creative Stereo Enhancement",
- /* 3 */ "National Semi 3D Stereo Enhancement",
- /* 4 */ "YAMAHA Ymersion",
- /* 5 */ "BBE 3D Stereo Enhancement",
- /* 6 */ "Crystal Semi 3D Stereo Enhancement",
- /* 7 */ "Qsound QXpander",
- /* 8 */ "Spatializer 3D Stereo Enhancement",
- /* 9 */ "SRS 3D Stereo Enhancement",
- /* 10 */ "Platform Tech 3D Stereo Enhancement",
- /* 11 */ "AKM 3D Audio",
- /* 12 */ "Aureal Stereo Enhancement",
- /* 13 */ "Aztech 3D Enhancement",
- /* 14 */ "Binaura 3D Audio Enhancement",
- /* 15 */ "ESS Technology Stereo Enhancement",
- /* 16 */ "Harman International VMAx",
- /* 17 */ "Nvidea/IC Ensemble/KS Waves 3D Stereo Enhancement",
- /* 18 */ "Philips Incredible Sound",
- /* 19 */ "Texas Instruments 3D Stereo Enhancement",
- /* 20 */ "VLSI Technology 3D Stereo Enhancement",
- /* 21 */ "TriTech 3D Stereo Enhancement",
- /* 22 */ "Realtek 3D Stereo Enhancement",
- /* 23 */ "Samsung 3D Stereo Enhancement",
- /* 24 */ "Wolfson Microelectronics 3D Enhancement",
- /* 25 */ "Delta Integration 3D Enhancement",
- /* 26 */ "SigmaTel 3D Enhancement",
- /* 27 */ "IC Ensemble/KS Waves",
- /* 28 */ "Rockwell 3D Stereo Enhancement",
- /* 29 */ "Reserved 29",
- /* 30 */ "Reserved 30",
- /* 31 */ "Reserved 31"
-};
-
/*
* I/O routines
*/
-static int snd_ac97_valid_reg(ac97_t *ac97, unsigned short reg)
+static int snd_ac97_valid_reg(struct snd_ac97 *ac97, unsigned short reg)
{
if (ac97->limited_regs && ! test_bit(reg, ac97->reg_accessed))
return 0;
@@ -278,7 +242,7 @@ static int snd_ac97_valid_reg(ac97_t *ac97, unsigned short reg)
* #snd_ca97_write_cache(), so use this only when you don't want to
* reflect the change to the suspend/resume state.
*/
-void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value)
+void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{
if (!snd_ac97_valid_reg(ac97, reg))
return;
@@ -301,7 +265,7 @@ void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value)
*
* Returns the read value.
*/
-unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg)
+unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
if (!snd_ac97_valid_reg(ac97, reg))
return 0;
@@ -309,7 +273,7 @@ unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg)
}
/* read a register - return the cached value if already read */
-static inline unsigned short snd_ac97_read_cache(ac97_t *ac97, unsigned short reg)
+static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned short reg)
{
if (! test_bit(reg, ac97->reg_accessed)) {
ac97->regs[reg] = ac97->bus->ops->read(ac97, reg);
@@ -328,7 +292,7 @@ static inline unsigned short snd_ac97_read_cache(ac97_t *ac97, unsigned short re
* cache. The cached values are used for the cached-read and the
* suspend/resume.
*/
-void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value)
+void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{
if (!snd_ac97_valid_reg(ac97, reg))
return;
@@ -351,7 +315,7 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value
* Returns 1 if the value is changed, 0 if no change, or a negative
* code on failure.
*/
-int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
+int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value)
{
int change;
@@ -381,7 +345,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
* Returns 1 if the bits are changed, 0 if no change, or a negative
* code on failure.
*/
-int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value)
+int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value)
{
int change;
@@ -394,7 +358,7 @@ int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask,
}
/* no lock version - see snd_ac97_updat_bits() */
-int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
+int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
unsigned short mask, unsigned short value)
{
int change;
@@ -411,7 +375,7 @@ int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
return change;
}
-static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned short mask, unsigned short value)
+static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, unsigned short mask, unsigned short value)
{
int change;
unsigned short old, new, cfg;
@@ -443,7 +407,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
* Controls
*/
-int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
@@ -457,9 +421,9 @@ int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * ui
return 0;
}
-int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val, bitmask;
@@ -473,9 +437,9 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
return 0;
}
-int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val;
unsigned short mask, bitmask;
@@ -496,7 +460,7 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
}
/* save/restore ac97 v2.3 paging */
-static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol)
+static int snd_ac97_page_save(struct snd_ac97 *ac97, int reg, struct snd_kcontrol *kcontrol)
{
int page_save = -1;
if ((kcontrol->private_value & (1<<25)) &&
@@ -510,7 +474,7 @@ static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol)
return page_save;
}
-static void snd_ac97_page_restore(ac97_t *ac97, int page_save)
+static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save)
{
if (page_save >= 0) {
snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
@@ -519,7 +483,7 @@ static void snd_ac97_page_restore(ac97_t *ac97, int page_save)
}
/* volume and switch controls */
-int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f;
@@ -532,9 +496,9 @@ int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
-int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -555,9 +519,9 @@ int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
return 0;
}
-int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -584,22 +548,22 @@ int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
return err;
}
-static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_master_mono[2] = {
AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_tone[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_tone[2] = {
AC97_SINGLE("Tone Control - Bass", AC97_MASTER_TONE, 8, 15, 1),
AC97_SINGLE("Tone Control - Treble", AC97_MASTER_TONE, 0, 15, 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_pc_beep[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_pc_beep[2] = {
AC97_SINGLE("PC Speaker Playback Switch", AC97_PC_BEEP, 15, 1, 1),
AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_mic_boost =
+static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
@@ -615,18 +579,18 @@ AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, std_mix),
AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, std_mic),
};
-static const snd_kcontrol_new_t snd_ac97_control_capture_src =
+static const struct snd_kcontrol_new snd_ac97_control_capture_src =
AC97_ENUM("Capture Source", std_enum[0]);
-static const snd_kcontrol_new_t snd_ac97_control_capture_vol =
+static const struct snd_kcontrol_new snd_ac97_control_capture_vol =
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
-static const snd_kcontrol_new_t snd_ac97_controls_mic_capture[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_mic_capture[2] = {
AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1),
AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0)
};
-typedef enum {
+enum {
AC97_GENERAL_PCM_OUT = 0,
AC97_GENERAL_STEREO_ENHANCEMENT,
AC97_GENERAL_3D,
@@ -634,9 +598,9 @@ typedef enum {
AC97_GENERAL_MONO,
AC97_GENERAL_MIC,
AC97_GENERAL_LOOPBACK
-} ac97_general_index_t;
+};
-static const snd_kcontrol_new_t snd_ac97_controls_general[7] = {
+static const struct snd_kcontrol_new snd_ac97_controls_general[7] = {
AC97_ENUM("PCM Out Path & Mute", std_enum[1]),
AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),
AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
@@ -646,45 +610,45 @@ AC97_ENUM("Mic Select", std_enum[3]),
AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
};
-const snd_kcontrol_new_t snd_ac97_controls_3d[2] = {
+const struct snd_kcontrol_new snd_ac97_controls_3d[2] = {
AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
};
-static const snd_kcontrol_new_t snd_ac97_controls_center[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_center[2] = {
AC97_SINGLE("Center Playback Switch", AC97_CENTER_LFE_MASTER, 7, 1, 1),
AC97_SINGLE("Center Playback Volume", AC97_CENTER_LFE_MASTER, 0, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_lfe[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_lfe[2] = {
AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),
AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_control_eapd =
+static const struct snd_kcontrol_new snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
-static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_modem_switches[2] = {
AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
};
/* change the existing EAPD control as inverted */
-static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
+static void set_inv_eapd(struct snd_ac97 *ac97, struct snd_kcontrol *kctl)
{
kctl->private_value = AC97_SINGLE_VALUE(AC97_POWERDOWN, 15, 1, 0);
snd_ac97_update_bits(ac97, AC97_POWERDOWN, (1<<15), (1<<15)); /* EAPD up */
ac97->scaps |= AC97_SCAP_INV_EAPD;
}
-static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ac97_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
IEC958_AES0_NONAUDIO |
@@ -696,7 +660,7 @@ static int snd_ac97_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_ac97_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
/* FIXME: AC'97 spec doesn't say which bits are used for what */
ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
@@ -706,9 +670,9 @@ static int snd_ac97_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
down(&ac97->reg_mutex);
ucontrol->value.iec958.status[0] = ac97->spdif_status & 0xff;
@@ -719,9 +683,9 @@ static int snd_ac97_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned int new = 0;
unsigned short val = 0;
int change;
@@ -787,9 +751,9 @@ static int snd_ac97_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return change;
}
-static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -817,7 +781,7 @@ static int snd_ac97_put_spsa(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return change;
}
-const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
+const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -856,9 +820,9 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
.get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
.private_value = (codec) | ((lshift) << 8) | ((rshift) << 12) | ((mask) << 16) }
-static int snd_ac97_ad18xx_pcm_info_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ad18xx_pcm_info_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int mask = (kcontrol->private_value >> 16) & 0x0f;
int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -873,9 +837,9 @@ static int snd_ac97_ad18xx_pcm_info_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ac97_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad18xx_pcm_get_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -887,9 +851,9 @@ static int snd_ac97_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad18xx_pcm_put_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
@@ -910,7 +874,7 @@ static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
.get = snd_ac97_ad18xx_pcm_get_volume, .put = snd_ac97_ad18xx_pcm_put_volume, \
.private_value = codec }
-static int snd_ac97_ad18xx_pcm_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ad18xx_pcm_info_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -919,9 +883,9 @@ static int snd_ac97_ad18xx_pcm_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad18xx_pcm_get_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
down(&ac97->page_mutex);
@@ -931,9 +895,9 @@ static int snd_ac97_ad18xx_pcm_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
return 0;
}
-static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad18xx_pcm_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3;
unsigned short val1, val2;
@@ -942,22 +906,22 @@ static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, 0x1f1f, (val1 << 8) | val2);
}
-static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_pcm[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_pcm[2] = {
AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 7, 1),
AD18XX_PCM_VOLUME("PCM Playback Volume", 0)
};
-static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_surround[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_surround[2] = {
AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 7, 1),
AD18XX_PCM_VOLUME("Surround Playback Volume", 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_center[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_center[2] = {
AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 15, 1),
AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 8, 31)
};
-static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_ad18xx_lfe[2] = {
AD18XX_PCM_BITS("LFE Playback Switch", 2, 7, 7, 1),
AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31)
};
@@ -966,9 +930,9 @@ AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31)
*
*/
-static void snd_ac97_powerdown(ac97_t *ac97);
+static void snd_ac97_powerdown(struct snd_ac97 *ac97);
-static int snd_ac97_bus_free(ac97_bus_t *bus)
+static int snd_ac97_bus_free(struct snd_ac97_bus *bus)
{
if (bus) {
snd_ac97_bus_proc_done(bus);
@@ -980,13 +944,13 @@ static int snd_ac97_bus_free(ac97_bus_t *bus)
return 0;
}
-static int snd_ac97_bus_dev_free(snd_device_t *device)
+static int snd_ac97_bus_dev_free(struct snd_device *device)
{
- ac97_bus_t *bus = device->device_data;
+ struct snd_ac97_bus *bus = device->device_data;
return snd_ac97_bus_free(bus);
}
-static int snd_ac97_free(ac97_t *ac97)
+static int snd_ac97_free(struct snd_ac97 *ac97)
{
if (ac97) {
snd_ac97_proc_done(ac97);
@@ -999,14 +963,14 @@ static int snd_ac97_free(ac97_t *ac97)
return 0;
}
-static int snd_ac97_dev_free(snd_device_t *device)
+static int snd_ac97_dev_free(struct snd_device *device)
{
- ac97_t *ac97 = device->device_data;
+ struct snd_ac97 *ac97 = device->device_data;
snd_ac97_powerdown(ac97); /* for avoiding click noises during shut down */
return snd_ac97_free(ac97);
}
-static int snd_ac97_try_volume_mix(ac97_t * ac97, int reg)
+static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
{
unsigned short val, mask = 0x8000;
@@ -1052,13 +1016,14 @@ static int snd_ac97_try_volume_mix(ac97_t * ac97, int reg)
/* try another test */
snd_ac97_write_cache(ac97, reg, val | mask);
val = snd_ac97_read(ac97, reg);
+ val = snd_ac97_read(ac97, reg);
if (!(val & mask))
return 0; /* nothing here */
}
return 1; /* success, useable */
}
-static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max)
+static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned char *lo_max, unsigned char *hi_max)
{
unsigned short cbit[3] = { 0x20, 0x10, 0x01 };
unsigned char max[3] = { 63, 31, 15 };
@@ -1083,7 +1048,7 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max
}
}
-int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
+int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit)
{
unsigned short mask, val, orig, res;
@@ -1097,7 +1062,7 @@ int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit)
}
/* check the volume resolution of center/lfe */
-static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max)
+static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int shift, unsigned char *max)
{
unsigned short val, val1;
@@ -1123,9 +1088,9 @@ static inline int printable(unsigned int x)
return x;
}
-snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97)
+struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97)
{
- snd_kcontrol_new_t template;
+ struct snd_kcontrol_new template;
memcpy(&template, _template, sizeof(template));
template.index = ac97->num;
return snd_ctl_new1(&template, ac97);
@@ -1134,9 +1099,9 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97
/*
* create mute switch(es) for normal stereo controls
*/
-static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int check_stereo, ac97_t *ac97)
+static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, int check_stereo, struct snd_ac97 *ac97)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
int err;
unsigned short val, val1, mute_mask;
@@ -1153,11 +1118,11 @@ static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int
mute_mask = 0x8080;
}
if (mute_mask == 0x8080) {
- snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
+ struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
} else {
- snd_kcontrol_new_t tmp = AC97_SINGLE(name, reg, 15, 1, 1);
+ struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
}
@@ -1172,22 +1137,22 @@ static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int
/*
* create a volume for normal stereo/mono controls
*/
-static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int lo_max,
- unsigned int hi_max, ac97_t *ac97)
+static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigned int lo_max,
+ unsigned int hi_max, struct snd_ac97 *ac97)
{
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
if (! snd_ac97_valid_reg(ac97, reg))
return 0;
if (hi_max) {
/* invert */
- snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1);
+ struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 8, 0, lo_max, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
} else {
/* invert */
- snd_kcontrol_new_t tmp = AC97_SINGLE(name, reg, 0, lo_max, 1);
+ struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 0, lo_max, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
}
@@ -1203,7 +1168,7 @@ static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int
/*
* create a mute-switch and a volume for normal stereo/mono controls
*/
-static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg, int check_stereo, ac97_t *ac97)
+static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int reg, int check_stereo, struct snd_ac97 *ac97)
{
int err;
char name[44];
@@ -1229,12 +1194,12 @@ static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg,
#define snd_ac97_cmix_new(card, pfx, reg, ac97) snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97)
#define snd_ac97_cmute_new(card, name, reg, ac97) snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97)
-static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
+static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97);
-static int snd_ac97_mixer_build(ac97_t * ac97)
+static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
{
- snd_card_t *card = ac97->bus->card;
- snd_kcontrol_t *kctl;
+ struct snd_card *card = ac97->bus->card;
+ struct snd_kcontrol *kctl;
int err;
unsigned int idx;
unsigned char max;
@@ -1531,7 +1496,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
return 0;
}
-static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
+static int snd_ac97_modem_build(struct snd_card *card, struct snd_ac97 * ac97)
{
int err, idx;
@@ -1555,7 +1520,7 @@ static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
return 0;
}
-static int snd_ac97_test_rate(ac97_t *ac97, int reg, int shadow_reg, int rate)
+static int snd_ac97_test_rate(struct snd_ac97 *ac97, int reg, int shadow_reg, int rate)
{
unsigned short val;
unsigned int tmp;
@@ -1568,7 +1533,7 @@ static int snd_ac97_test_rate(ac97_t *ac97, int reg, int shadow_reg, int rate)
return val == (tmp & 0xffff);
}
-static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsigned int *r_result)
+static void snd_ac97_determine_rates(struct snd_ac97 *ac97, int reg, int shadow_reg, unsigned int *r_result)
{
unsigned int result = 0;
unsigned short saved;
@@ -1628,7 +1593,7 @@ static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsi
}
/* check AC97_SPDIF register to accept which sample rates */
-static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97)
+static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97)
{
unsigned int result = 0;
int i;
@@ -1648,10 +1613,10 @@ static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97)
}
/* look for the codec id table matching with the given id */
-static const ac97_codec_id_t *look_for_codec_id(const ac97_codec_id_t *table,
- unsigned int id)
+static const struct ac97_codec_id *look_for_codec_id(const struct ac97_codec_id *table,
+ unsigned int id)
{
- const ac97_codec_id_t *pid;
+ const struct ac97_codec_id *pid;
for (pid = table; pid->id; pid++)
if (pid->id == (id & pid->mask))
@@ -1659,9 +1624,9 @@ static const ac97_codec_id_t *look_for_codec_id(const ac97_codec_id_t *table,
return NULL;
}
-void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
+void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem)
{
- const ac97_codec_id_t *pid;
+ const struct ac97_codec_id *pid;
sprintf(name, "0x%x %c%c%c", id,
printable(id >> 24),
@@ -1699,9 +1664,9 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
*
* Returns the short identifying name of the codec.
*/
-const char *snd_ac97_get_short_name(ac97_t *ac97)
+const char *snd_ac97_get_short_name(struct snd_ac97 *ac97)
{
- const ac97_codec_id_t *pid;
+ const struct ac97_codec_id *pid;
for (pid = snd_ac97_codec_ids; pid->id; pid++)
if (pid->id == (ac97->id & pid->mask))
@@ -1713,7 +1678,7 @@ const char *snd_ac97_get_short_name(ac97_t *ac97)
/* wait for a while until registers are accessible after RESET
* return 0 if ok, negative not ready
*/
-static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
+static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
{
unsigned long end_time;
unsigned short val;
@@ -1758,7 +1723,7 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
* @private_data: private data pointer for the new instance
* @rbus: the pointer to store the new AC97 bus instance.
*
- * Creates an AC97 bus component. An ac97_bus_t instance is newly
+ * Creates an AC97 bus component. An struct snd_ac97_bus instance is newly
* allocated and initialized.
*
* The ops table must include valid callbacks (at least read and
@@ -1772,12 +1737,12 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
- void *private_data, ac97_bus_t **rbus)
+int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
+ void *private_data, struct snd_ac97_bus **rbus)
{
int err;
- ac97_bus_t *bus;
- static snd_device_ops_t dev_ops = {
+ struct snd_ac97_bus *bus;
+ static struct snd_device_ops dev_ops = {
.dev_free = snd_ac97_bus_dev_free,
};
@@ -1807,15 +1772,17 @@ static void ac97_device_release(struct device * dev)
}
/* register ac97 codec to bus */
-static int snd_ac97_dev_register(snd_device_t *device)
+static int snd_ac97_dev_register(struct snd_device *device)
{
- ac97_t *ac97 = device->device_data;
+ struct snd_ac97 *ac97 = device->device_data;
int err;
ac97->dev.bus = &ac97_bus_type;
ac97->dev.parent = ac97->bus->card->dev;
ac97->dev.release = ac97_device_release;
- snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "card%d-%d", ac97->bus->card->number, ac97->num);
+ snprintf(ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
+ ac97->bus->card->number, ac97->num,
+ snd_ac97_get_short_name(ac97));
if ((err = device_register(&ac97->dev)) < 0) {
snd_printk(KERN_ERR "Can't register ac97 bus\n");
ac97->dev.bus = NULL;
@@ -1825,9 +1792,9 @@ static int snd_ac97_dev_register(snd_device_t *device)
}
/* unregister ac97 codec */
-static int snd_ac97_dev_unregister(snd_device_t *device)
+static int snd_ac97_dev_unregister(struct snd_device *device)
{
- ac97_t *ac97 = device->device_data;
+ struct snd_ac97 *ac97 = device->device_data;
if (ac97->dev.bus)
device_unregister(&ac97->dev);
return snd_ac97_free(ac97);
@@ -1843,7 +1810,7 @@ static struct snd_ac97_build_ops null_build_ops;
* the private data.
* @rac97: the pointer to store the new ac97 instance.
*
- * Creates an Codec97 component. An ac97_t instance is newly
+ * Creates an Codec97 component. An struct snd_ac97 instance is newly
* allocated and initialized from the template. The codec
* is then initialized by the standard procedure.
*
@@ -1855,16 +1822,16 @@ static struct snd_ac97_build_ops null_build_ops;
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
+int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, struct snd_ac97 **rac97)
{
int err;
- ac97_t *ac97;
- snd_card_t *card;
+ struct snd_ac97 *ac97;
+ struct snd_card *card;
char name[64];
unsigned long end_time;
unsigned int reg;
- const ac97_codec_id_t *pid;
- static snd_device_ops_t ops = {
+ const struct ac97_codec_id *pid;
+ static struct snd_device_ops ops = {
.dev_free = snd_ac97_dev_free,
.dev_register = snd_ac97_dev_register,
.dev_unregister = snd_ac97_dev_unregister,
@@ -1892,10 +1859,12 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
init_MUTEX(&ac97->reg_mutex);
init_MUTEX(&ac97->page_mutex);
+#ifdef CONFIG_PCI
if (ac97->pci) {
pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device);
}
+#endif
if (bus->ops->reset) {
bus->ops->reset(ac97);
goto __access_ok;
@@ -2148,7 +2117,7 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
* MASTER and HEADPHONE registers are muted but the register cache values
* are not changed, so that the values can be restored in snd_ac97_resume().
*/
-static void snd_ac97_powerdown(ac97_t *ac97)
+static void snd_ac97_powerdown(struct snd_ac97 *ac97)
{
unsigned short power;
@@ -2181,8 +2150,10 @@ static void snd_ac97_powerdown(ac97_t *ac97)
*
* Suspends the codec, power down the chip.
*/
-void snd_ac97_suspend(ac97_t *ac97)
+void snd_ac97_suspend(struct snd_ac97 *ac97)
{
+ if (! ac97)
+ return;
if (ac97->build_ops->suspend)
ac97->build_ops->suspend(ac97);
snd_ac97_powerdown(ac97);
@@ -2191,7 +2162,7 @@ void snd_ac97_suspend(ac97_t *ac97)
/*
* restore ac97 status
*/
-void snd_ac97_restore_status(ac97_t *ac97)
+void snd_ac97_restore_status(struct snd_ac97 *ac97)
{
int i;
@@ -2212,7 +2183,7 @@ void snd_ac97_restore_status(ac97_t *ac97)
/*
* restore IEC958 status
*/
-void snd_ac97_restore_iec958(ac97_t *ac97)
+void snd_ac97_restore_iec958(struct snd_ac97 *ac97)
{
if (ac97->ext_id & AC97_EI_SPDIF) {
if (ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_SPDIF) {
@@ -2235,10 +2206,13 @@ void snd_ac97_restore_iec958(ac97_t *ac97)
* Do the standard resume procedure, power up and restoring the
* old register values.
*/
-void snd_ac97_resume(ac97_t *ac97)
+void snd_ac97_resume(struct snd_ac97 *ac97)
{
unsigned long end_time;
+ if (! ac97)
+ return;
+
if (ac97->bus->ops->reset) {
ac97->bus->ops->reset(ac97);
goto __reset_ready;
@@ -2301,18 +2275,18 @@ static void set_ctl_name(char *dst, const char *src, const char *suffix)
}
/* remove the control with the given name and optional suffix */
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix)
+int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
set_ctl_name(id.name, name, suffix);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(ac97->bus->card, &id);
}
-static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix)
+static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, const char *suffix)
{
- snd_ctl_elem_id_t sid;
+ struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
set_ctl_name(sid.name, name, suffix);
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -2320,9 +2294,9 @@ static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suff
}
/* rename the control with the given name and optional suffix */
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix)
+int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix)
{
- snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix);
+ struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix);
if (kctl) {
set_ctl_name(kctl->id.name, dst, suffix);
return 0;
@@ -2331,16 +2305,16 @@ int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const ch
}
/* rename both Volume and Switch controls - don't check the return value */
-void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst)
+void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst)
{
snd_ac97_rename_ctl(ac97, src, dst, "Switch");
snd_ac97_rename_ctl(ac97, src, dst, "Volume");
}
/* swap controls */
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix)
+int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix)
{
- snd_kcontrol_t *kctl1, *kctl2;
+ struct snd_kcontrol *kctl1, *kctl2;
kctl1 = ctl_find(ac97, s1, suffix);
kctl2 = ctl_find(ac97, s2, suffix);
if (kctl1 && kctl2) {
@@ -2353,7 +2327,7 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *
#if 1
/* bind hp and master controls instead of using only hp control */
-static int bind_hp_volsw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int bind_hp_volsw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int err = snd_ac97_put_volsw(kcontrol, ucontrol);
if (err > 0) {
@@ -2366,10 +2340,10 @@ static int bind_hp_volsw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
}
/* ac97 tune: bind Master and Headphone controls */
-static int tune_hp_only(ac97_t *ac97)
+static int tune_hp_only(struct snd_ac97 *ac97)
{
- snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL);
- snd_kcontrol_t *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
+ struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+ struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
if (! msw || ! mvol)
return -ENOENT;
msw->put = bind_hp_volsw_put;
@@ -2381,7 +2355,7 @@ static int tune_hp_only(ac97_t *ac97)
#else
/* ac97 tune: use Headphone control as master */
-static int tune_hp_only(ac97_t *ac97)
+static int tune_hp_only(struct snd_ac97 *ac97)
{
if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
return -ENOENT;
@@ -2393,7 +2367,7 @@ static int tune_hp_only(ac97_t *ac97)
#endif
/* ac97 tune: swap Headphone and Master controls */
-static int tune_swap_hp(ac97_t *ac97)
+static int tune_swap_hp(struct snd_ac97 *ac97)
{
if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
return -ENOENT;
@@ -2403,7 +2377,7 @@ static int tune_swap_hp(ac97_t *ac97)
}
/* ac97 tune: swap Surround and Master controls */
-static int tune_swap_surround(ac97_t *ac97)
+static int tune_swap_surround(struct snd_ac97 *ac97)
{
if (snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch") ||
snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume"))
@@ -2412,7 +2386,7 @@ static int tune_swap_surround(ac97_t *ac97)
}
/* ac97 tune: set up mic sharing for AD codecs */
-static int tune_ad_sharing(ac97_t *ac97)
+static int tune_ad_sharing(struct snd_ac97 *ac97)
{
unsigned short scfg;
if ((ac97->id & 0xffffff00) != 0x41445300) {
@@ -2425,11 +2399,11 @@ static int tune_ad_sharing(ac97_t *ac97)
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_alc_jack_detect =
+static const struct snd_kcontrol_new snd_ac97_alc_jack_detect =
AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0);
/* ac97 tune: set up ALC jack-select */
-static int tune_alc_jack(ac97_t *ac97)
+static int tune_alc_jack(struct snd_ac97 *ac97)
{
if ((ac97->id & 0xffffff00) != 0x414c4700) {
snd_printk(KERN_ERR "ac97_quirk ALC_JACK is only for Realtek codecs\n");
@@ -2437,24 +2411,26 @@ static int tune_alc_jack(ac97_t *ac97)
}
snd_ac97_update_bits(ac97, 0x7a, 0x20, 0x20); /* select jack detect function */
snd_ac97_update_bits(ac97, 0x7a, 0x01, 0x01); /* Line-out auto mute */
+ if (ac97->id == AC97_ID_ALC658D)
+ snd_ac97_update_bits(ac97, 0x74, 0x0800, 0x0800);
return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, ac97));
}
/* ac97 tune: inversed EAPD bit */
-static int tune_inv_eapd(ac97_t *ac97)
+static int tune_inv_eapd(struct snd_ac97 *ac97)
{
- snd_kcontrol_t *kctl = ctl_find(ac97, "External Amplifier", NULL);
+ struct snd_kcontrol *kctl = ctl_find(ac97, "External Amplifier", NULL);
if (! kctl)
return -ENOENT;
set_inv_eapd(ac97, kctl);
return 0;
}
-static int master_mute_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int err = snd_ac97_put_volsw(kcontrol, ucontrol);
if (err > 0) {
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int shift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
unsigned short mask;
@@ -2470,9 +2446,9 @@ static int master_mute_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
}
/* ac97 tune: EAPD controls mute LED bound with the master mute */
-static int tune_mute_led(ac97_t *ac97)
+static int tune_mute_led(struct snd_ac97 *ac97)
{
- snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+ struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
if (! msw)
return -ENOENT;
msw->put = master_mute_sw_put;
@@ -2481,9 +2457,44 @@ static int tune_mute_led(ac97_t *ac97)
return 0;
}
+static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int err = bind_hp_volsw_put(kcontrol, ucontrol);
+ if (err > 0) {
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+ int shift = (kcontrol->private_value >> 8) & 0x0f;
+ int rshift = (kcontrol->private_value >> 12) & 0x0f;
+ unsigned short mask;
+ if (shift != rshift)
+ mask = 0x8080;
+ else
+ mask = 0x8000;
+ snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+ (ac97->regs[AC97_MASTER] & mask) == mask ?
+ 0x8000 : 0);
+ }
+ return err;
+}
+
+static int tune_hp_mute_led(struct snd_ac97 *ac97)
+{
+ struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+ struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
+ if (! msw || ! mvol)
+ return -ENOENT;
+ msw->put = hp_master_mute_sw_put;
+ mvol->put = bind_hp_volsw_put;
+ snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
+ snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+ return 0;
+}
+
struct quirk_table {
const char *name;
- int (*func)(ac97_t *);
+ int (*func)(struct snd_ac97 *);
};
static struct quirk_table applicable_quirks[] = {
@@ -2495,10 +2506,11 @@ static struct quirk_table applicable_quirks[] = {
{ "alc_jack", tune_alc_jack },
{ "inv_eapd", tune_inv_eapd },
{ "mute_led", tune_mute_led },
+ { "hp_mute_led", tune_hp_mute_led },
};
/* apply the quirk with the given type */
-static int apply_quirk(ac97_t *ac97, int type)
+static int apply_quirk(struct snd_ac97 *ac97, int type)
{
if (type <= 0)
return 0;
@@ -2510,7 +2522,7 @@ static int apply_quirk(ac97_t *ac97, int type)
}
/* apply the quirk with the given name */
-static int apply_quirk_str(ac97_t *ac97, const char *typestr)
+static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
{
int i;
struct quirk_table *q;
@@ -2539,7 +2551,7 @@ static int apply_quirk_str(ac97_t *ac97, const char *typestr)
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *override)
+int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, const char *override)
{
int result;
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index 536a4d4793af..a6244c720a1d 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -36,6 +36,16 @@
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
.get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
.private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
+
+/* enum control */
+struct ac97_enum {
+ unsigned char reg;
+ unsigned char shift_l;
+ unsigned char shift_r;
+ unsigned short mask;
+ const char **texts;
+};
+
#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
.mask = xmask, .texts = xtexts }
@@ -47,34 +57,33 @@
.private_value = (unsigned long)&xenum }
/* ac97_codec.c */
-extern const char *snd_ac97_stereo_enhancements[];
-extern const snd_kcontrol_new_t snd_ac97_controls_3d[];
-extern const snd_kcontrol_new_t snd_ac97_controls_spdif[];
-snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97);
-void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem);
-int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
-int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix);
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix);
-void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
-void snd_ac97_restore_status(ac97_t *ac97);
-void snd_ac97_restore_iec958(ac97_t *ac97);
-int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
-int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+extern const struct snd_kcontrol_new snd_ac97_controls_3d[];
+extern const struct snd_kcontrol_new snd_ac97_controls_spdif[];
+struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97);
+void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem);
+int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit);
+int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix);
+int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix);
+int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix);
+void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst);
+void snd_ac97_restore_status(struct snd_ac97 *ac97);
+void snd_ac97_restore_iec958(struct snd_ac97 *ac97);
+int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
+int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
unsigned short mask, unsigned short value);
/* ac97_proc.c */
#ifdef CONFIG_PROC_FS
-void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
-void snd_ac97_bus_proc_done(ac97_bus_t * ac97);
-void snd_ac97_proc_init(ac97_t * ac97);
-void snd_ac97_proc_done(ac97_t * ac97);
+void snd_ac97_bus_proc_init(struct snd_ac97_bus * ac97);
+void snd_ac97_bus_proc_done(struct snd_ac97_bus * ac97);
+void snd_ac97_proc_init(struct snd_ac97 * ac97);
+void snd_ac97_proc_done(struct snd_ac97 * ac97);
#else
#define snd_ac97_bus_proc_init(ac97_bus_t) do { } while (0)
#define snd_ac97_bus_proc_done(ac97_bus_t) do { } while (0)
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index de1c72ad2c6b..4aa5fdc5688e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -39,7 +39,7 @@
* Chip specific initialization
*/
-static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *controls, int count)
+static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontrol_new *controls, int count)
{
int idx, err;
@@ -50,7 +50,7 @@ static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *control
}
/* set to the page, update bits and restore the page */
-static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
+static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
{
unsigned short page_save;
int ret;
@@ -67,7 +67,7 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor
/*
* shared line-in/mic controls
*/
-static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo,
+static int ac97_enum_text_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo,
const char **texts, unsigned int nums)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -79,23 +79,23 @@ static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
return 0;
}
-static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int ac97_surround_jack_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static const char *texts[] = { "Shared", "Independent" };
return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
}
-static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ac97_surround_jack_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = ac97->indep_surround;
return 0;
}
-static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned char indep = !!ucontrol->value.enumerated.item[0];
if (indep != ac97->indep_surround) {
@@ -107,7 +107,7 @@ static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static const char *texts[] = { "2ch", "4ch", "6ch" };
if (kcontrol->private_value)
@@ -115,17 +115,17 @@ static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
}
-static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = ac97->channel_mode;
return 0;
}
-static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned char mode = ucontrol->value.enumerated.item[0];
if (mode != ac97->channel_mode) {
@@ -163,22 +163,22 @@ static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
.private_value = 1, \
}
-static inline int is_surround_on(ac97_t *ac97)
+static inline int is_surround_on(struct snd_ac97 *ac97)
{
return ac97->channel_mode >= 1;
}
-static inline int is_clfe_on(ac97_t *ac97)
+static inline int is_clfe_on(struct snd_ac97 *ac97)
{
return ac97->channel_mode >= 2;
}
-static inline int is_shared_linein(ac97_t *ac97)
+static inline int is_shared_linein(struct snd_ac97 *ac97)
{
return ! ac97->indep_surround && is_surround_on(ac97);
}
-static inline int is_shared_micin(ac97_t *ac97)
+static inline int is_shared_micin(struct snd_ac97 *ac97)
{
return ! ac97->indep_surround && is_clfe_on(ac97);
}
@@ -187,7 +187,7 @@ static inline int is_shared_micin(ac97_t *ac97)
/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
-static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ymf753_info_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {
"Standard", "Small", "Smaller"
@@ -202,9 +202,9 @@ static int snd_ac97_ymf753_info_speaker(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_get_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_YMF753_3D_MODE_SEL];
@@ -215,9 +215,9 @@ static int snd_ac97_ymf753_get_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
return 0;
}
-static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_put_speaker(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
if (ucontrol->value.enumerated.item[0] > 2)
@@ -226,7 +226,7 @@ static int snd_ac97_ymf753_put_speaker(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
return snd_ac97_update(ac97, AC97_YMF753_3D_MODE_SEL, val);
}
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
+static const struct snd_kcontrol_new snd_ac97_ymf753_controls_speaker =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Speaker",
@@ -236,7 +236,7 @@ static const snd_kcontrol_new_t snd_ac97_ymf753_controls_speaker =
};
/* It is possible to indicate to the Yamaha YMF753 the source to direct to the S/PDIF output. */
-static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ymf753_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "AC-Link", "A/D Converter" };
@@ -249,9 +249,9 @@ static int snd_ac97_ymf753_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_YMF753_DIT_CTRL2];
@@ -259,9 +259,9 @@ static int snd_ac97_ymf753_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
if (ucontrol->value.enumerated.item[0] > 1)
@@ -274,7 +274,7 @@ static int snd_ac97_ymf753_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_e
The YMF753 will output the S/PDIF signal to pin 43, 47 (EAPD), or 48.
By default, no output pin is selected, and the S/PDIF signal is not output.
There is also a bit to mute S/PDIF output in a vendor-specific register. */
-static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ymf753_spdif_output_pin_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = { "Disabled", "Pin 43", "Pin 48" };
@@ -287,9 +287,9 @@ static int snd_ac97_ymf753_spdif_output_pin_info(snd_kcontrol_t *kcontrol, snd_c
return 0;
}
-static int snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_spdif_output_pin_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_YMF753_DIT_CTRL2];
@@ -297,9 +297,9 @@ static int snd_ac97_ymf753_spdif_output_pin_get(snd_kcontrol_t * kcontrol, snd_c
return 0;
}
-static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ymf753_spdif_output_pin_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
if (ucontrol->value.enumerated.item[0] > 2)
@@ -311,7 +311,7 @@ static int snd_ac97_ymf753_spdif_output_pin_put(snd_kcontrol_t * kcontrol, snd_c
snd_ac97_write_cache(ac97, 0x62, snd_ac97_read(ac97, 0x62) | 0x0008); */
}
-static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
+static const struct snd_kcontrol_new snd_ac97_ymf753_controls_spdif[3] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
@@ -329,9 +329,9 @@ static const snd_kcontrol_new_t snd_ac97_ymf753_controls_spdif[3] = {
AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",NONE,NONE) "Mute", AC97_YMF753_DIT_CTRL2, 2, 1, 1)
};
-static int patch_yamaha_ymf753_3d(ac97_t * ac97)
+static int patch_yamaha_ymf753_3d(struct snd_ac97 * ac97)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
int err;
if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
@@ -345,7 +345,7 @@ static int patch_yamaha_ymf753_3d(ac97_t * ac97)
return 0;
}
-static int patch_yamaha_ymf753_post_spdif(ac97_t * ac97)
+static int patch_yamaha_ymf753_post_spdif(struct snd_ac97 * ac97)
{
int err;
@@ -359,7 +359,7 @@ static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
.build_post_spdif = patch_yamaha_ymf753_post_spdif
};
-int patch_yamaha_ymf753(ac97_t * ac97)
+int patch_yamaha_ymf753(struct snd_ac97 * ac97)
{
/* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
@@ -380,12 +380,12 @@ int patch_yamaha_ymf753(ac97_t * ac97)
* added support for WM9705,WM9708,WM9709,WM9710,WM9711,WM9712 and WM9717.
*/
-static const snd_kcontrol_new_t wm97xx_snd_ac97_controls[] = {
+static const struct snd_kcontrol_new 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)
+static int patch_wolfson_wm9703_specific(struct snd_ac97 * ac97)
{
/* This is known to work for the ViewSonic ViewPad 1000
* Randolph Bentson <bentson@holmsjoen.com>
@@ -405,13 +405,13 @@ static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
.build_specific = patch_wolfson_wm9703_specific,
};
-int patch_wolfson03(ac97_t * ac97)
+int patch_wolfson03(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_wolfson_wm9703_ops;
return 0;
}
-static const snd_kcontrol_new_t wm9704_snd_ac97_controls[] = {
+static const struct snd_kcontrol_new 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),
@@ -420,7 +420,7 @@ 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)
+static int patch_wolfson_wm9704_specific(struct snd_ac97 * ac97)
{
int err, i;
for (i = 0; i < ARRAY_SIZE(wm9704_snd_ac97_controls); i++) {
@@ -436,14 +436,14 @@ static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
.build_specific = patch_wolfson_wm9704_specific,
};
-int patch_wolfson04(ac97_t * ac97)
+int patch_wolfson04(struct snd_ac97 * ac97)
{
/* WM9704M/9704Q */
ac97->build_ops = &patch_wolfson_wm9704_ops;
return 0;
}
-static int patch_wolfson_wm9705_specific(ac97_t * ac97)
+static int patch_wolfson_wm9705_specific(struct snd_ac97 * ac97)
{
int err, i;
for (i = 0; i < ARRAY_SIZE(wm97xx_snd_ac97_controls); i++) {
@@ -458,7 +458,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = {
.build_specific = patch_wolfson_wm9705_specific,
};
-int patch_wolfson05(ac97_t * ac97)
+int patch_wolfson05(struct snd_ac97 * ac97)
{
/* WM9705, WM9710 */
ac97->build_ops = &patch_wolfson_wm9705_ops;
@@ -490,7 +490,7 @@ 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[] = {
+static const struct snd_kcontrol_new 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),
@@ -568,7 +568,7 @@ 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)
+static int patch_wolfson_wm9711_specific(struct snd_ac97 * ac97)
{
int err, i;
@@ -589,7 +589,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
.build_specific = patch_wolfson_wm9711_specific,
};
-int patch_wolfson11(ac97_t * ac97)
+int patch_wolfson11(struct snd_ac97 * ac97)
{
/* WM9711, WM9712 */
ac97->build_ops = &patch_wolfson_wm9711_ops;
@@ -636,7 +636,7 @@ 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[] = {
+static const struct snd_kcontrol_new wm13_snd_ac97_controls[] = {
AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 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),
@@ -728,14 +728,14 @@ 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_3d[] = {
+static const struct snd_kcontrol_new 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 int patch_wolfson_wm9713_3d (ac97_t * ac97)
+static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97)
{
int err, i;
@@ -746,7 +746,7 @@ static int patch_wolfson_wm9713_3d (ac97_t * ac97)
return 0;
}
-static int patch_wolfson_wm9713_specific(ac97_t * ac97)
+static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97)
{
int err, i;
@@ -765,13 +765,13 @@ static int patch_wolfson_wm9713_specific(ac97_t * ac97)
}
#ifdef CONFIG_PM
-static void patch_wolfson_wm9713_suspend (ac97_t * ac97)
+static void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97)
{
snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
}
-static void patch_wolfson_wm9713_resume (ac97_t * ac97)
+static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97)
{
snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
@@ -788,7 +788,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
#endif
};
-int patch_wolfson13(ac97_t * ac97)
+int patch_wolfson13(struct snd_ac97 * ac97)
{
/* WM9713, WM9714 */
ac97->build_ops = &patch_wolfson_wm9713_ops;
@@ -808,7 +808,7 @@ int patch_wolfson13(ac97_t * ac97)
/*
* Tritech codec
*/
-int patch_tritech_tr28028(ac97_t * ac97)
+int patch_tritech_tr28028(struct snd_ac97 * ac97)
{
snd_ac97_write_cache(ac97, 0x26, 0x0300);
snd_ac97_write_cache(ac97, 0x26, 0x0000);
@@ -820,9 +820,9 @@ int patch_tritech_tr28028(ac97_t * ac97)
/*
* Sigmatel STAC97xx codecs
*/
-static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
+static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
int err;
if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
@@ -833,9 +833,9 @@ static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
return 0;
}
-static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
+static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97)
{
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
int err;
if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
@@ -850,18 +850,18 @@ static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_sigmatel_4speaker =
+static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =
AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);
-static const snd_kcontrol_new_t snd_ac97_sigmatel_phaseinvert =
+static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =
AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch", AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);
-static const snd_kcontrol_new_t snd_ac97_sigmatel_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {
AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),
AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)
};
-static int patch_sigmatel_stac97xx_specific(ac97_t * ac97)
+static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97)
{
int err;
@@ -886,15 +886,15 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
.build_specific = patch_sigmatel_stac97xx_specific
};
-int patch_sigmatel_stac9700(ac97_t * ac97)
+int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_sigmatel_stac9700_ops;
return 0;
}
-static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int err;
down(&ac97->page_mutex);
@@ -906,7 +906,7 @@ static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return err;
}
-static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = {
+static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Sigmatel Output Bias Switch",
.info = snd_ac97_info_volsw,
@@ -915,7 +915,7 @@ static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = {
.private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
};
-static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
+static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
{
int err;
@@ -930,7 +930,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
.build_specific = patch_sigmatel_stac9708_specific
};
-int patch_sigmatel_stac9708(ac97_t * ac97)
+int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
{
unsigned int codec72, codec6c;
@@ -956,7 +956,7 @@ int patch_sigmatel_stac9708(ac97_t * ac97)
return 0;
}
-int patch_sigmatel_stac9721(ac97_t * ac97)
+int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_sigmatel_stac9700_ops;
if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
@@ -970,7 +970,7 @@ int patch_sigmatel_stac9721(ac97_t * ac97)
return 0;
}
-int patch_sigmatel_stac9744(ac97_t * ac97)
+int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
{
// patch for SigmaTel
ac97->build_ops = &patch_sigmatel_stac9700_ops;
@@ -982,7 +982,7 @@ int patch_sigmatel_stac9744(ac97_t * ac97)
return 0;
}
-int patch_sigmatel_stac9756(ac97_t * ac97)
+int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
{
// patch for SigmaTel
ac97->build_ops = &patch_sigmatel_stac9700_ops;
@@ -994,7 +994,7 @@ int patch_sigmatel_stac9756(ac97_t * ac97)
return 0;
}
-static int snd_ac97_stac9758_output_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[5] = { "Input/Disabled", "Front Output",
"Rear Output", "Center/LFE Output", "Mixer Output" };
@@ -1008,9 +1008,9 @@ static int snd_ac97_stac9758_output_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_ac97_stac9758_output_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value;
unsigned short val;
@@ -1022,9 +1022,9 @@ static int snd_ac97_stac9758_output_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value;
unsigned short val;
@@ -1038,7 +1038,7 @@ static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_e
7 << shift, val << shift, 0);
}
-static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_stac9758_input_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[7] = { "Mic2 Jack", "Mic1 Jack", "Line In Jack",
"Front Jack", "Rear Jack", "Center/LFE Jack", "Mute" };
@@ -1052,9 +1052,9 @@ static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_stac9758_input_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_stac9758_input_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value;
unsigned short val;
@@ -1063,16 +1063,16 @@ static int snd_ac97_stac9758_input_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_ac97_stac9758_input_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_stac9758_input_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value;
return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
ucontrol->value.enumerated.item[0] << shift, 0);
}
-static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_stac9758_phonesel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = { "None", "Front Jack", "Rear Jack" };
@@ -1085,17 +1085,17 @@ static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_ac97_stac9758_phonesel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_stac9758_phonesel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = ac97->regs[AC97_SIGMATEL_IOMISC] & 3;
return 0;
}
-static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_stac9758_phonesel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
ucontrol->value.enumerated.item[0], 0);
@@ -1113,7 +1113,7 @@ static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
.get = snd_ac97_stac9758_input_jack_get, \
.put = snd_ac97_stac9758_input_jack_put, \
.private_value = shift }
-static const snd_kcontrol_new_t snd_ac97_sigmatel_stac9758_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_sigmatel_stac9758_controls[] = {
STAC9758_OUTPUT_JACK("Mic1 Jack", 1),
STAC9758_OUTPUT_JACK("LineIn Jack", 4),
STAC9758_OUTPUT_JACK("Front Jack", 7),
@@ -1132,7 +1132,7 @@ static const snd_kcontrol_new_t snd_ac97_sigmatel_stac9758_controls[] = {
AC97_SINGLE("Headphone +3dB Boost", AC97_SIGMATEL_IOMISC, 8, 1, 0)
};
-static int patch_sigmatel_stac9758_specific(ac97_t *ac97)
+static int patch_sigmatel_stac9758_specific(struct snd_ac97 *ac97)
{
int err;
@@ -1159,7 +1159,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
.build_specific = patch_sigmatel_stac9758_specific
};
-int patch_sigmatel_stac9758(ac97_t * ac97)
+int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
{
static unsigned short regs[4] = {
AC97_SIGMATEL_OUTSEL,
@@ -1202,12 +1202,12 @@ int patch_sigmatel_stac9758(ac97_t * ac97)
/*
* Cirrus Logic CS42xx codecs
*/
-static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
+static const struct snd_kcontrol_new snd_ac97_cirrus_controls_spdif[2] = {
AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 0),
AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", AC97_CSR_ACMODE, 0, 3, 0)
};
-static int patch_cirrus_build_spdif(ac97_t * ac97)
+static int patch_cirrus_build_spdif(struct snd_ac97 * ac97)
{
int err;
@@ -1233,7 +1233,7 @@ static struct snd_ac97_build_ops patch_cirrus_ops = {
.build_spdif = patch_cirrus_build_spdif
};
-int patch_cirrus_spdif(ac97_t * ac97)
+int patch_cirrus_spdif(struct snd_ac97 * ac97)
{
/* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC? *sigh*
@@ -1254,7 +1254,7 @@ int patch_cirrus_spdif(ac97_t * ac97)
return 0;
}
-int patch_cirrus_cs4299(ac97_t * ac97)
+int patch_cirrus_cs4299(struct snd_ac97 * ac97)
{
/* force the detection of PC Beep */
ac97->flags |= AC97_HAS_PC_BEEP;
@@ -1265,11 +1265,11 @@ int patch_cirrus_cs4299(ac97_t * ac97)
/*
* Conexant codecs
*/
-static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
+static const struct snd_kcontrol_new snd_ac97_conexant_controls_spdif[1] = {
AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 1, 0),
};
-static int patch_conexant_build_spdif(ac97_t * ac97)
+static int patch_conexant_build_spdif(struct snd_ac97 * ac97)
{
int err;
@@ -1290,7 +1290,7 @@ static struct snd_ac97_build_ops patch_conexant_ops = {
.build_spdif = patch_conexant_build_spdif
};
-int patch_conexant(ac97_t * ac97)
+int patch_conexant(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_conexant_ops;
ac97->flags |= AC97_CX_SPDIF;
@@ -1303,7 +1303,7 @@ int patch_conexant(ac97_t * ac97)
* Analog Device AD18xx, AD19xx codecs
*/
#ifdef CONFIG_PM
-static void ad18xx_resume(ac97_t *ac97)
+static void ad18xx_resume(struct snd_ac97 *ac97)
{
static unsigned short setup_regs[] = {
AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
@@ -1367,7 +1367,7 @@ static void ad18xx_resume(ac97_t *ac97)
}
#endif
-int patch_ad1819(ac97_t * ac97)
+int patch_ad1819(struct snd_ac97 * ac97)
{
unsigned short scfg;
@@ -1377,7 +1377,7 @@ int patch_ad1819(ac97_t * ac97)
return 0;
}
-static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned short mask)
+static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, unsigned short mask)
{
unsigned short val;
@@ -1393,7 +1393,7 @@ static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned sh
return mask;
}
-static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bits)
+static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
{
static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
unsigned short val;
@@ -1411,7 +1411,7 @@ static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bi
return 1;
}
-static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, int cidx2)
+static void patch_ad1881_chained(struct snd_ac97 * ac97, int unchained_idx, int cidx1, int cidx2)
{
// already detected?
if (ac97->spec.ad18xx.unchained[cidx1] || ac97->spec.ad18xx.chained[cidx1])
@@ -1441,7 +1441,7 @@ static struct snd_ac97_build_ops patch_ad1881_build_ops = {
#endif
};
-int patch_ad1881(ac97_t * ac97)
+int patch_ad1881(struct snd_ac97 * ac97)
{
static const char cfg_idxs[3][2] = {
{2, 1},
@@ -1500,7 +1500,7 @@ int patch_ad1881(ac97_t * ac97)
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
AC97_SINGLE("Digital Mono Direct", AC97_AD_MISC, 11, 1, 0),
/* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
@@ -1509,7 +1509,7 @@ static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
};
-static int patch_ad1885_specific(ac97_t * ac97)
+static int patch_ad1885_specific(struct snd_ac97 * ac97)
{
int err;
@@ -1525,7 +1525,7 @@ static struct snd_ac97_build_ops patch_ad1885_build_ops = {
#endif
};
-int patch_ad1885(ac97_t * ac97)
+int patch_ad1885(struct snd_ac97 * ac97)
{
patch_ad1881(ac97);
/* This is required to deal with the Intel D815EEAL2 */
@@ -1538,7 +1538,7 @@ int patch_ad1885(ac97_t * ac97)
return 0;
}
-int patch_ad1886(ac97_t * ac97)
+int patch_ad1886(struct snd_ac97 * ac97)
{
patch_ad1881(ac97);
/* Presario700 workaround */
@@ -1569,7 +1569,7 @@ int patch_ad1886(ac97_t * ac97)
#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
-static int snd_ac97_ad198x_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "AC-Link", "A/D Converter" };
@@ -1582,9 +1582,9 @@ static int snd_ac97_ad198x_spdif_source_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_ad198x_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad198x_spdif_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_AD_SERIAL_CFG];
@@ -1592,9 +1592,9 @@ static int snd_ac97_ad198x_spdif_source_get(snd_kcontrol_t * kcontrol, snd_ctl_e
return 0;
}
-static int snd_ac97_ad198x_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_ad198x_spdif_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
if (ucontrol->value.enumerated.item[0] > 1)
@@ -1603,7 +1603,7 @@ static int snd_ac97_ad198x_spdif_source_put(snd_kcontrol_t * kcontrol, snd_ctl_e
return snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x0004, val);
}
-static const snd_kcontrol_new_t snd_ac97_ad198x_spdif_source = {
+static const struct snd_kcontrol_new snd_ac97_ad198x_spdif_source = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
.info = snd_ac97_ad198x_spdif_source_info,
@@ -1611,17 +1611,17 @@ static const snd_kcontrol_new_t snd_ac97_ad198x_spdif_source = {
.put = snd_ac97_ad198x_spdif_source_put,
};
-static int patch_ad198x_post_spdif(ac97_t * ac97)
+static int patch_ad198x_post_spdif(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, &snd_ac97_ad198x_spdif_source, 1);
}
-static const snd_kcontrol_new_t snd_ac97_ad1981x_jack_sense[] = {
+static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 11, 1, 0),
AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
};
-static int patch_ad1981a_specific(ac97_t * ac97)
+static int patch_ad1981a_specific(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_ad1981x_jack_sense,
ARRAY_SIZE(snd_ac97_ad1981x_jack_sense));
@@ -1635,12 +1635,16 @@ static struct snd_ac97_build_ops patch_ad1981a_build_ops = {
#endif
};
-static void check_ad1981_hp_jack_sense(ac97_t *ac97)
+static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
{
u32 subid = ((u32)ac97->subsystem_vendor << 16) | ac97->subsystem_device;
switch (subid) {
+ case 0x0e11005a: /* HP nc4000/4010 */
case 0x103c0890: /* HP nc6000 */
+ case 0x103c0938: /* HP nc4220 */
case 0x103c099c: /* HP nx6110 */
+ case 0x103c0944: /* HP nc6220 */
+ case 0x103c0934: /* HP nc8220 */
case 0x103c006d: /* HP nx9105 */
case 0x17340088: /* FSC Scenic-W */
/* enable headphone jack sense */
@@ -1649,7 +1653,7 @@ static void check_ad1981_hp_jack_sense(ac97_t *ac97)
}
}
-int patch_ad1981a(ac97_t *ac97)
+int patch_ad1981a(struct snd_ac97 *ac97)
{
patch_ad1881(ac97);
ac97->build_ops = &patch_ad1981a_build_ops;
@@ -1659,10 +1663,10 @@ int patch_ad1981a(ac97_t *ac97)
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_ad198x_2cmic =
+static const struct snd_kcontrol_new snd_ac97_ad198x_2cmic =
AC97_SINGLE("Stereo Mic", AC97_AD_MISC, 6, 1, 0);
-static int patch_ad1981b_specific(ac97_t *ac97)
+static int patch_ad1981b_specific(struct snd_ac97 *ac97)
{
int err;
@@ -1680,7 +1684,7 @@ static struct snd_ac97_build_ops patch_ad1981b_build_ops = {
#endif
};
-int patch_ad1981b(ac97_t *ac97)
+int patch_ad1981b(struct snd_ac97 *ac97)
{
patch_ad1881(ac97);
ac97->build_ops = &patch_ad1981b_build_ops;
@@ -1690,7 +1694,7 @@ int patch_ad1981b(ac97_t *ac97)
return 0;
}
-static int snd_ac97_ad1888_lohpsel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_ad1888_lohpsel_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1699,9 +1703,9 @@ static int snd_ac97_ad1888_lohpsel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_ac97_ad1888_lohpsel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_ad1888_lohpsel_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_AD_MISC];
@@ -1709,9 +1713,9 @@ static int snd_ac97_ad1888_lohpsel_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_ac97_ad1888_lohpsel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_ad1888_lohpsel_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = !ucontrol->value.integer.value[0]
@@ -1720,7 +1724,7 @@ static int snd_ac97_ad1888_lohpsel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
AC97_AD198X_LOSEL | AC97_AD198X_HPSEL, val);
}
-static int snd_ac97_ad1888_downmix_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ac97_ad1888_downmix_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {"Off", "6 -> 4", "6 -> 2"};
@@ -1733,9 +1737,9 @@ static int snd_ac97_ad1888_downmix_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_ac97_ad1888_downmix_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t* ucontrol)
+static int snd_ac97_ad1888_downmix_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_AD_MISC];
@@ -1746,9 +1750,9 @@ static int snd_ac97_ad1888_downmix_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ac97_ad1888_downmix_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
if (ucontrol->value.enumerated.item[0] > 2)
@@ -1762,7 +1766,7 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
}
-static void ad1888_update_jacks(ac97_t *ac97)
+static void ad1888_update_jacks(struct snd_ac97 *ac97)
{
unsigned short val = 0;
if (! is_shared_linein(ac97))
@@ -1773,7 +1777,7 @@ static void ad1888_update_jacks(ac97_t *ac97)
snd_ac97_update_bits(ac97, AC97_AD_MISC, (1 << 11) | (1 << 12), val);
}
-static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Exchange Front/Surround",
@@ -1796,7 +1800,7 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
};
-static int patch_ad1888_specific(ac97_t *ac97)
+static int patch_ad1888_specific(struct snd_ac97 *ac97)
{
/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
@@ -1813,7 +1817,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
.update_jacks = ad1888_update_jacks,
};
-int patch_ad1888(ac97_t * ac97)
+int patch_ad1888(struct snd_ac97 * ac97)
{
unsigned short misc;
@@ -1833,7 +1837,7 @@ int patch_ad1888(ac97_t * ac97)
return 0;
}
-static int patch_ad1980_specific(ac97_t *ac97)
+static int patch_ad1980_specific(struct snd_ac97 *ac97)
{
int err;
@@ -1851,25 +1855,25 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = {
.update_jacks = ad1888_update_jacks,
};
-int patch_ad1980(ac97_t * ac97)
+int patch_ad1980(struct snd_ac97 * ac97)
{
patch_ad1888(ac97);
ac97->build_ops = &patch_ad1980_build_ops;
return 0;
}
-static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
};
-static void ad1985_update_jacks(ac97_t *ac97)
+static void ad1985_update_jacks(struct snd_ac97 *ac97)
{
ad1888_update_jacks(ac97);
snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
is_shared_micin(ac97) ? 0 : 1 << 9);
}
-static int patch_ad1985_specific(ac97_t *ac97)
+static int patch_ad1985_specific(struct snd_ac97 *ac97)
{
int err;
@@ -1887,7 +1891,7 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = {
.update_jacks = ad1985_update_jacks,
};
-int patch_ad1985(ac97_t * ac97)
+int patch_ad1985(struct snd_ac97 * ac97)
{
unsigned short misc;
@@ -1916,7 +1920,7 @@ int patch_ad1985(ac97_t * ac97)
/*
* realtek ALC65x/850 codecs
*/
-static void alc650_update_jacks(ac97_t *ac97)
+static void alc650_update_jacks(struct snd_ac97 *ac97)
{
int shared;
@@ -1937,7 +1941,7 @@ static void alc650_update_jacks(ac97_t *ac97)
shared ? 0 : 0x100);
}
-static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = {
AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
AC97_SINGLE("Center/LFE Down Mix", AC97_ALC650_MULTICH, 2, 1, 0),
@@ -1963,14 +1967,14 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
AC97_CHANNEL_MODE_CTL,
};
-static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
+static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
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), */
};
-static int patch_alc650_specific(ac97_t * ac97)
+static int patch_alc650_specific(struct snd_ac97 * ac97)
{
int err;
@@ -1988,7 +1992,7 @@ static struct snd_ac97_build_ops patch_alc650_ops = {
.update_jacks = alc650_update_jacks
};
-int patch_alc650(ac97_t * ac97)
+int patch_alc650(struct snd_ac97 * ac97)
{
unsigned short val;
@@ -2043,7 +2047,7 @@ int patch_alc650(ac97_t * ac97)
return 0;
}
-static void alc655_update_jacks(ac97_t *ac97)
+static void alc655_update_jacks(struct snd_ac97 *ac97)
{
int shared;
@@ -2060,17 +2064,17 @@ static void alc655_update_jacks(ac97_t *ac97)
shared ? (1 << 10) : 0, 0);
}
-static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_alc655[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
};
-static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc655_iec958_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts_655[3] = { "PCM", "Analog In", "IEC958 In" };
static char *texts_658[4] = { "PCM", "Analog1 In", "Analog2 In", "IEC958 In" };
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2084,9 +2088,9 @@ static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc655_iec958_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_ALC650_MULTICH];
@@ -2097,29 +2101,29 @@ static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc655_iec958_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
(unsigned short)ucontrol->value.enumerated.item[0] << 12,
0);
}
-static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
+static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc655[] = {
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 = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
.info = alc655_iec958_route_info,
.get = alc655_iec958_route_get,
.put = alc655_iec958_route_put,
},
};
-static int patch_alc655_specific(ac97_t * ac97)
+static int patch_alc655_specific(struct snd_ac97 * ac97)
{
int err;
@@ -2137,7 +2141,7 @@ static struct snd_ac97_build_ops patch_alc655_ops = {
.update_jacks = alc655_update_jacks
};
-int patch_alc655(ac97_t * ac97)
+int patch_alc655(struct snd_ac97 * ac97)
{
unsigned int val;
@@ -2189,7 +2193,7 @@ int patch_alc655(ac97_t * ac97)
#define AC97_ALC850_JACK_SELECT 0x76
#define AC97_ALC850_MISC1 0x7a
-static void alc850_update_jacks(ac97_t *ac97)
+static void alc850_update_jacks(struct snd_ac97 *ac97)
{
int shared;
@@ -2211,14 +2215,14 @@ static void alc850_update_jacks(ac97_t *ac97)
shared ? (2<<4) : (1<<4));
}
-static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
};
-static int patch_alc850_specific(ac97_t *ac97)
+static int patch_alc850_specific(struct snd_ac97 *ac97)
{
int err;
@@ -2236,7 +2240,7 @@ static struct snd_ac97_build_ops patch_alc850_ops = {
.update_jacks = alc850_update_jacks
};
-int patch_alc850(ac97_t *ac97)
+int patch_alc850(struct snd_ac97 *ac97)
{
ac97->build_ops = &patch_alc850_ops;
@@ -2273,20 +2277,20 @@ int patch_alc850(ac97_t *ac97)
/*
* C-Media CM97xx codecs
*/
-static void cm9738_update_jacks(ac97_t *ac97)
+static void cm9738_update_jacks(struct snd_ac97 *ac97)
{
/* shared Line-In */
snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
is_shared_linein(ac97) ? (1 << 10) : 0);
}
-static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_4CH_CTL,
};
-static int patch_cm9738_specific(ac97_t * ac97)
+static int patch_cm9738_specific(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9738_controls, ARRAY_SIZE(snd_ac97_cm9738_controls));
}
@@ -2296,7 +2300,7 @@ static struct snd_ac97_build_ops patch_cm9738_ops = {
.update_jacks = cm9738_update_jacks
};
-int patch_cm9738(ac97_t * ac97)
+int patch_cm9738(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_cm9738_ops;
/* FIXME: can anyone confirm below? */
@@ -2307,7 +2311,7 @@ int patch_cm9738(ac97_t * ac97)
return 0;
}
-static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ac97_cmedia_spdif_playback_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "Analog", "Digital" };
@@ -2320,9 +2324,9 @@ static int snd_ac97_cmedia_spdif_playback_source_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_cmedia_spdif_playback_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = ac97->regs[AC97_CM9739_SPDIF_CTRL];
@@ -2330,16 +2334,16 @@ static int snd_ac97_cmedia_spdif_playback_source_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ac97_cmedia_spdif_playback_source_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ac97_cmedia_spdif_playback_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
return snd_ac97_update_bits(ac97, AC97_CM9739_SPDIF_CTRL,
0x01 << 1,
(ucontrol->value.enumerated.item[0] & 0x01) << 1);
}
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
+static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
/* BIT 0: SPDI_EN - always true */
{ /* BIT 1: SPDIFS */
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -2357,7 +2361,7 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
/* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
};
-static void cm9739_update_jacks(ac97_t *ac97)
+static void cm9739_update_jacks(struct snd_ac97 *ac97)
{
/* shared Line-In */
snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
@@ -2367,17 +2371,17 @@ static void cm9739_update_jacks(ac97_t *ac97)
is_shared_micin(ac97) ? 0x1000 : 0x2000);
}
-static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
};
-static int patch_cm9739_specific(ac97_t * ac97)
+static int patch_cm9739_specific(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9739_controls, ARRAY_SIZE(snd_ac97_cm9739_controls));
}
-static int patch_cm9739_post_spdif(ac97_t * ac97)
+static int patch_cm9739_post_spdif(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9739_controls_spdif, ARRAY_SIZE(snd_ac97_cm9739_controls_spdif));
}
@@ -2388,7 +2392,7 @@ static struct snd_ac97_build_ops patch_cm9739_ops = {
.update_jacks = cm9739_update_jacks
};
-int patch_cm9739(ac97_t * ac97)
+int patch_cm9739(struct snd_ac97 * ac97)
{
unsigned short val;
@@ -2447,7 +2451,7 @@ int patch_cm9739(ac97_t * ac97)
#define AC97_CM9761_FUNC 0x66
#define AC97_CM9761_SPDIF_CTRL 0x6c
-static void cm9761_update_jacks(ac97_t *ac97)
+static void cm9761_update_jacks(struct snd_ac97 *ac97)
{
/* FIXME: check the bits for each model
* model 83 is confirmed to work
@@ -2482,12 +2486,12 @@ static void cm9761_update_jacks(ac97_t *ac97)
snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
}
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
+static const struct snd_kcontrol_new snd_ac97_cm9761_controls[] = {
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
};
-static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int cm9761_spdif_out_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
@@ -2500,9 +2504,9 @@ static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cm9761_spdif_out_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
@@ -2513,9 +2517,9 @@ static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cm9761_spdif_out_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.enumerated.item[0] == 2)
return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
@@ -2528,7 +2532,7 @@ static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
static const struct ac97_enum cm9761_dac_clock_enum =
AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
+static const struct snd_kcontrol_new snd_ac97_cm9761_controls_spdif[] = {
{ /* BIT 1: SPDIFS */
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
@@ -2546,12 +2550,12 @@ static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
};
-static int patch_cm9761_post_spdif(ac97_t * ac97)
+static int patch_cm9761_post_spdif(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
}
-static int patch_cm9761_specific(ac97_t * ac97)
+static int patch_cm9761_specific(struct snd_ac97 * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
}
@@ -2562,7 +2566,7 @@ static struct snd_ac97_build_ops patch_cm9761_ops = {
.update_jacks = cm9761_update_jacks
};
-int patch_cm9761(ac97_t *ac97)
+int patch_cm9761(struct snd_ac97 *ac97)
{
unsigned short val;
@@ -2641,13 +2645,13 @@ int patch_cm9761(ac97_t *ac97)
static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
static const struct ac97_enum cm9780_ch_select_enum =
AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
-static const snd_kcontrol_new_t cm9780_controls[] = {
+static const struct snd_kcontrol_new cm9780_controls[] = {
AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
};
-static int patch_cm9780_specific(ac97_t *ac97)
+static int patch_cm9780_specific(struct snd_ac97 *ac97)
{
return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
}
@@ -2657,7 +2661,7 @@ static struct snd_ac97_build_ops patch_cm9780_ops = {
.build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
};
-int patch_cm9780(ac97_t *ac97)
+int patch_cm9780(struct snd_ac97 *ac97)
{
unsigned short val;
@@ -2677,14 +2681,14 @@ int patch_cm9780(ac97_t *ac97)
/*
* VIA VT1616 codec
*/
-static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_vt1616[] = {
AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 0),
AC97_SINGLE("Downmix LFE and Center to Front", 0x5a, 12, 1, 0),
AC97_SINGLE("Downmix Surround to Front", 0x5a, 11, 1, 0),
};
-static int patch_vt1616_specific(ac97_t * ac97)
+static int patch_vt1616_specific(struct snd_ac97 * ac97)
{
int err;
@@ -2700,7 +2704,7 @@ static struct snd_ac97_build_ops patch_vt1616_ops = {
.build_specific = patch_vt1616_specific
};
-int patch_vt1616(ac97_t * ac97)
+int patch_vt1616(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_vt1616_ops;
return 0;
@@ -2709,7 +2713,7 @@ int patch_vt1616(ac97_t * ac97)
/*
* VT1617A codec
*/
-int patch_vt1617a(ac97_t * ac97)
+int patch_vt1617a(struct snd_ac97 * 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;
@@ -2718,7 +2722,7 @@ int patch_vt1617a(ac97_t * ac97)
/*
*/
-static void it2646_update_jacks(ac97_t *ac97)
+static void it2646_update_jacks(struct snd_ac97 *ac97)
{
/* shared Line-In */
snd_ac97_update_bits(ac97, 0x76, 1 << 9,
@@ -2728,18 +2732,18 @@ static void it2646_update_jacks(ac97_t *ac97)
is_shared_micin(ac97) ? (1<<10) : 0);
}
-static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
AC97_SURROUND_JACK_MODE_CTL,
AC97_CHANNEL_MODE_CTL,
};
-static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
+static const struct snd_kcontrol_new snd_ac97_spdif_controls_it2646[] = {
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),
};
-static int patch_it2646_specific(ac97_t * ac97)
+static int patch_it2646_specific(struct snd_ac97 * ac97)
{
int err;
if ((err = patch_build_controls(ac97, snd_ac97_controls_it2646, ARRAY_SIZE(snd_ac97_controls_it2646))) < 0)
@@ -2754,7 +2758,7 @@ static struct snd_ac97_build_ops patch_it2646_ops = {
.update_jacks = it2646_update_jacks
};
-int patch_it2646(ac97_t * ac97)
+int patch_it2646(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_it2646_ops;
/* full DAC volume */
@@ -2770,11 +2774,11 @@ int patch_it2646(ac97_t * ac97)
#define AC97_SI3036_CHIP_ID 0x5a
#define AC97_SI3036_LINE_CFG 0x5c
-static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = {
+static const struct snd_kcontrol_new snd_ac97_controls_si3036[] = {
AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
};
-static int patch_si3036_specific(ac97_t * ac97)
+static int patch_si3036_specific(struct snd_ac97 * ac97)
{
int idx, err;
for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_si3036); idx++)
@@ -2787,7 +2791,7 @@ static struct snd_ac97_build_ops patch_si3036_ops = {
.build_specific = patch_si3036_specific,
};
-int mpatch_si3036(ac97_t * ac97)
+int mpatch_si3036(struct snd_ac97 * ac97)
{
ac97->build_ops = &patch_si3036_ops;
snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index ec1811320106..5060cb6f2ec3 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -22,40 +22,40 @@
*
*/
-int patch_yamaha_ymf753(ac97_t * ac97);
-int patch_wolfson00(ac97_t * ac97);
-int patch_wolfson03(ac97_t * ac97);
-int patch_wolfson04(ac97_t * ac97);
-int patch_wolfson05(ac97_t * ac97);
-int patch_wolfson11(ac97_t * ac97);
-int patch_wolfson13(ac97_t * ac97);
-int patch_tritech_tr28028(ac97_t * ac97);
-int patch_sigmatel_stac9700(ac97_t * ac97);
-int patch_sigmatel_stac9708(ac97_t * ac97);
-int patch_sigmatel_stac9721(ac97_t * ac97);
-int patch_sigmatel_stac9744(ac97_t * ac97);
-int patch_sigmatel_stac9756(ac97_t * ac97);
-int patch_sigmatel_stac9758(ac97_t * ac97);
-int patch_cirrus_cs4299(ac97_t * ac97);
-int patch_cirrus_spdif(ac97_t * ac97);
-int patch_conexant(ac97_t * ac97);
-int patch_ad1819(ac97_t * ac97);
-int patch_ad1881(ac97_t * ac97);
-int patch_ad1885(ac97_t * ac97);
-int patch_ad1886(ac97_t * ac97);
-int patch_ad1888(ac97_t * ac97);
-int patch_ad1980(ac97_t * ac97);
-int patch_ad1981a(ac97_t * ac97);
-int patch_ad1981b(ac97_t * ac97);
-int patch_ad1985(ac97_t * ac97);
-int patch_alc650(ac97_t * ac97);
-int patch_alc655(ac97_t * ac97);
-int patch_alc850(ac97_t * ac97);
-int patch_cm9738(ac97_t * ac97);
-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);
+int patch_yamaha_ymf753(struct snd_ac97 * ac97);
+int patch_wolfson00(struct snd_ac97 * ac97);
+int patch_wolfson03(struct snd_ac97 * ac97);
+int patch_wolfson04(struct snd_ac97 * ac97);
+int patch_wolfson05(struct snd_ac97 * ac97);
+int patch_wolfson11(struct snd_ac97 * ac97);
+int patch_wolfson13(struct snd_ac97 * ac97);
+int patch_tritech_tr28028(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9700(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9708(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9721(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9744(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9756(struct snd_ac97 * ac97);
+int patch_sigmatel_stac9758(struct snd_ac97 * ac97);
+int patch_cirrus_cs4299(struct snd_ac97 * ac97);
+int patch_cirrus_spdif(struct snd_ac97 * ac97);
+int patch_conexant(struct snd_ac97 * ac97);
+int patch_ad1819(struct snd_ac97 * ac97);
+int patch_ad1881(struct snd_ac97 * ac97);
+int patch_ad1885(struct snd_ac97 * ac97);
+int patch_ad1886(struct snd_ac97 * ac97);
+int patch_ad1888(struct snd_ac97 * ac97);
+int patch_ad1980(struct snd_ac97 * ac97);
+int patch_ad1981a(struct snd_ac97 * ac97);
+int patch_ad1981b(struct snd_ac97 * ac97);
+int patch_ad1985(struct snd_ac97 * ac97);
+int patch_alc650(struct snd_ac97 * ac97);
+int patch_alc655(struct snd_ac97 * ac97);
+int patch_alc850(struct snd_ac97 * ac97);
+int patch_cm9738(struct snd_ac97 * ac97);
+int patch_cm9739(struct snd_ac97 * ac97);
+int patch_cm9761(struct snd_ac97 * ac97);
+int patch_cm9780(struct snd_ac97 * ac97);
+int patch_vt1616(struct snd_ac97 * ac97);
+int patch_vt1617a(struct snd_ac97 * ac97);
+int patch_it2646(struct snd_ac97 * ac97);
+int mpatch_si3036(struct snd_ac97 * ac97);
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index ded13165d635..c3e590bf7a02 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -170,7 +170,7 @@ static unsigned char get_slot_reg(struct ac97_pcm *pcm, unsigned short cidx,
return rate_cregs[slot - 3];
}
-static int set_spdif_rate(ac97_t *ac97, unsigned short rate)
+static int set_spdif_rate(struct snd_ac97 *ac97, unsigned short rate)
{
unsigned short old, bits, reg, mask;
unsigned int sbits;
@@ -254,7 +254,7 @@ static int set_spdif_rate(ac97_t *ac97, unsigned short rate)
*
* Returns zero if successful, or a negative error code on failure.
*/
-int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate)
+int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate)
{
int dbl;
unsigned int tmp;
@@ -315,7 +315,7 @@ int snd_ac97_set_rate(ac97_t *ac97, int reg, unsigned int rate)
return 0;
}
-static unsigned short get_pslots(ac97_t *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
+static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
{
if (!ac97_is_audio(ac97))
return 0;
@@ -390,7 +390,7 @@ static unsigned short get_pslots(ac97_t *ac97, unsigned char *rate_table, unsign
}
}
-static unsigned short get_cslots(ac97_t *ac97)
+static unsigned short get_cslots(struct snd_ac97 *ac97)
{
unsigned short slots;
@@ -437,7 +437,7 @@ static unsigned int get_rates(struct ac97_pcm *pcm, unsigned int cidx, unsigned
* some slots are available, pcm->xxx.slots and pcm->xxx.rslots[] members
* are reduced and might be zero.
*/
-int snd_ac97_pcm_assign(ac97_bus_t *bus,
+int snd_ac97_pcm_assign(struct snd_ac97_bus *bus,
unsigned short pcms_count,
const struct ac97_pcm *pcms)
{
@@ -449,7 +449,7 @@ int snd_ac97_pcm_assign(ac97_bus_t *bus,
unsigned short tmp, slots;
unsigned short spdif_slots[4];
unsigned int rates;
- ac97_t *codec;
+ struct snd_ac97 *codec;
rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL);
if (rpcms == NULL)
@@ -560,7 +560,7 @@ int snd_ac97_pcm_assign(ac97_bus_t *bus,
int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
enum ac97_pcm_cfg cfg, unsigned short slots)
{
- ac97_bus_t *bus;
+ struct snd_ac97_bus *bus;
int i, cidx, r, ok_flag;
unsigned int reg_ok[4] = {0,0,0,0};
unsigned char reg;
@@ -639,7 +639,7 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate,
*/
int snd_ac97_pcm_close(struct ac97_pcm *pcm)
{
- ac97_bus_t *bus;
+ struct snd_ac97_bus *bus;
unsigned short slots = pcm->aslots;
int i, cidx;
@@ -656,31 +656,31 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm)
return 0;
}
-static int double_rate_hw_constraint_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
if (channels->min > 2) {
- static const snd_interval_t single_rates = {
+ static const struct snd_interval single_rates = {
.min = 1,
.max = 48000,
};
- snd_interval_t *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
return snd_interval_refine(rate, &single_rates);
}
return 0;
}
-static int double_rate_hw_constraint_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int double_rate_hw_constraint_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_interval_t *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (rate->min > 48000) {
- static const snd_interval_t double_rate_channels = {
+ static const struct snd_interval double_rate_channels = {
.min = 2,
.max = 2,
};
- snd_interval_t *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
return snd_interval_refine(channels, &double_rate_channels);
}
return 0;
@@ -693,7 +693,7 @@ static int double_rate_hw_constraint_channels(snd_pcm_hw_params_t *params,
* Installs the hardware constraint rules to prevent using double rates and
* more than two channels at the same time.
*/
-int snd_ac97_pcm_double_rate_rules(snd_pcm_runtime_t *runtime)
+int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime)
{
int err;
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index a040b2666ed7..7134b3f55fb5 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -34,7 +34,7 @@
* proc interface
*/
-static void snd_ac97_proc_read_functions(ac97_t *ac97, snd_info_buffer_t *buffer)
+static void snd_ac97_proc_read_functions(struct snd_ac97 *ac97, struct snd_info_buffer *buffer)
{
int header = 0, function;
unsigned short info, sense_info;
@@ -68,7 +68,43 @@ static void snd_ac97_proc_read_functions(ac97_t *ac97, snd_info_buffer_t *buffer
}
}
-static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
+static const char *snd_ac97_stereo_enhancements[] =
+{
+ /* 0 */ "No 3D Stereo Enhancement",
+ /* 1 */ "Analog Devices Phat Stereo",
+ /* 2 */ "Creative Stereo Enhancement",
+ /* 3 */ "National Semi 3D Stereo Enhancement",
+ /* 4 */ "YAMAHA Ymersion",
+ /* 5 */ "BBE 3D Stereo Enhancement",
+ /* 6 */ "Crystal Semi 3D Stereo Enhancement",
+ /* 7 */ "Qsound QXpander",
+ /* 8 */ "Spatializer 3D Stereo Enhancement",
+ /* 9 */ "SRS 3D Stereo Enhancement",
+ /* 10 */ "Platform Tech 3D Stereo Enhancement",
+ /* 11 */ "AKM 3D Audio",
+ /* 12 */ "Aureal Stereo Enhancement",
+ /* 13 */ "Aztech 3D Enhancement",
+ /* 14 */ "Binaura 3D Audio Enhancement",
+ /* 15 */ "ESS Technology Stereo Enhancement",
+ /* 16 */ "Harman International VMAx",
+ /* 17 */ "Nvidea/IC Ensemble/KS Waves 3D Stereo Enhancement",
+ /* 18 */ "Philips Incredible Sound",
+ /* 19 */ "Texas Instruments 3D Stereo Enhancement",
+ /* 20 */ "VLSI Technology 3D Stereo Enhancement",
+ /* 21 */ "TriTech 3D Stereo Enhancement",
+ /* 22 */ "Realtek 3D Stereo Enhancement",
+ /* 23 */ "Samsung 3D Stereo Enhancement",
+ /* 24 */ "Wolfson Microelectronics 3D Enhancement",
+ /* 25 */ "Delta Integration 3D Enhancement",
+ /* 26 */ "SigmaTel 3D Enhancement",
+ /* 27 */ "IC Ensemble/KS Waves",
+ /* 28 */ "Rockwell 3D Stereo Enhancement",
+ /* 29 */ "Reserved 29",
+ /* 30 */ "Reserved 30",
+ /* 31 */ "Reserved 31"
+};
+
+static void snd_ac97_proc_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
{
char name[64];
unsigned short val, tmp, ext, mext;
@@ -79,9 +115,15 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
snd_ac97_get_name(NULL, ac97->id, name, 0);
snd_iprintf(buffer, "%d-%d/%d: %s\n\n", ac97->addr, ac97->num, subidx, name);
+
if ((ac97->scaps & AC97_SCAP_AUDIO) == 0)
goto __modem;
+ snd_iprintf(buffer, "PCI Subsys Vendor: 0x%04x\n",
+ ac97->subsystem_vendor);
+ snd_iprintf(buffer, "PCI Subsys Device: 0x%04x\n\n",
+ ac97->subsystem_device);
+
if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23) {
val = snd_ac97_read(ac97, AC97_INT_PAGING);
snd_ac97_update_bits(ac97, AC97_INT_PAGING,
@@ -292,9 +334,9 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
}
}
-static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void snd_ac97_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- ac97_t *ac97 = entry->private_data;
+ struct snd_ac97 *ac97 = entry->private_data;
down(&ac97->page_mutex);
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
@@ -327,9 +369,9 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
#ifdef CONFIG_SND_DEBUG
/* direct register write for debugging */
-static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_ac97_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- ac97_t *ac97 = entry->private_data;
+ struct snd_ac97 *ac97 = entry->private_data;
char line[64];
unsigned int reg, val;
down(&ac97->page_mutex);
@@ -344,7 +386,7 @@ static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t
}
#endif
-static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, int subidx)
+static void snd_ac97_proc_regs_read_main(struct snd_ac97 *ac97, struct snd_info_buffer *buffer, int subidx)
{
int reg, val;
@@ -354,10 +396,10 @@ static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffe
}
}
-static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ac97_proc_regs_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ac97_t *ac97 = entry->private_data;
+ struct snd_ac97 *ac97 = entry->private_data;
down(&ac97->page_mutex);
if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) { // Analog Devices AD1881/85/86
@@ -378,9 +420,9 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
up(&ac97->page_mutex);
}
-void snd_ac97_proc_init(ac97_t * ac97)
+void snd_ac97_proc_init(struct snd_ac97 * ac97)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
char name[32];
const char *prefix;
@@ -412,7 +454,7 @@ void snd_ac97_proc_init(ac97_t * ac97)
ac97->proc_regs = entry;
}
-void snd_ac97_proc_done(ac97_t * ac97)
+void snd_ac97_proc_done(struct snd_ac97 * ac97)
{
if (ac97->proc_regs) {
snd_info_unregister(ac97->proc_regs);
@@ -424,9 +466,9 @@ void snd_ac97_proc_done(ac97_t * ac97)
}
}
-void snd_ac97_bus_proc_init(ac97_bus_t * bus)
+void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
char name[32];
sprintf(name, "codec97#%d", bus->num);
@@ -440,7 +482,7 @@ void snd_ac97_bus_proc_init(ac97_bus_t * bus)
bus->proc = entry;
}
-void snd_ac97_bus_proc_done(ac97_bus_t * bus)
+void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus)
{
if (bus->proc) {
snd_info_unregister(bus->proc);
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index 4032c5748370..dcfb5036ff8b 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -30,7 +30,11 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Universal routines for AK4531 codec");
MODULE_LICENSE("GPL");
-static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531);
+#ifdef CONFIG_PROC_FS
+static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531);
+#else
+#define snd_ak4531_proc_init(card,ak)
+#endif
/*
*
@@ -38,7 +42,7 @@ static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531);
#if 0
-static void snd_ak4531_dump(ak4531_t *ak4531)
+static void snd_ak4531_dump(struct snd_ak4531 *ak4531)
{
int idx;
@@ -58,7 +62,7 @@ static void snd_ak4531_dump(ak4531_t *ak4531)
.get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \
.private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) }
-static int snd_ak4531_info_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -69,9 +73,9 @@ static int snd_ak4531_info_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -88,9 +92,9 @@ static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 16) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -117,7 +121,7 @@ static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \
.private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) }
-static int snd_ak4531_info_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -128,9 +132,9 @@ static int snd_ak4531_info_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x07;
@@ -152,9 +156,9 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x07;
@@ -194,7 +198,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_ak4531_get_input_sw, .put = snd_ak4531_put_input_sw, \
.private_value = reg1 | (reg2 << 8) | (left_shift << 16) | (right_shift << 24) }
-static int snd_ak4531_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ak4531_info_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 4;
@@ -203,9 +207,9 @@ static int snd_ak4531_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_get_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x0f;
@@ -220,9 +224,9 @@ static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ak4531_t *ak4531 = snd_kcontrol_chip(kcontrol);
+ struct snd_ak4531 *ak4531 = snd_kcontrol_chip(kcontrol);
int reg1 = kcontrol->private_value & 0xff;
int reg2 = (kcontrol->private_value >> 8) & 0xff;
int left_shift = (kcontrol->private_value >> 16) & 0x0f;
@@ -244,7 +248,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return change;
}
-static snd_kcontrol_new_t snd_ak4531_controls[] = {
+static struct snd_kcontrol_new snd_ak4531_controls[] = {
AK4531_DOUBLE("Master Playback Switch", 0, AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1),
AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1),
@@ -300,7 +304,7 @@ AK4531_SINGLE("AD Input Select", 0, AK4531_AD_IN, 0, 1, 0),
AK4531_SINGLE("Mic Boost (+30dB)", 0, AK4531_MIC_GAIN, 0, 1, 0)
};
-static int snd_ak4531_free(ak4531_t *ak4531)
+static int snd_ak4531_free(struct snd_ak4531 *ak4531)
{
if (ak4531) {
if (ak4531->private_free)
@@ -310,9 +314,9 @@ static int snd_ak4531_free(ak4531_t *ak4531)
return 0;
}
-static int snd_ak4531_dev_free(snd_device_t *device)
+static int snd_ak4531_dev_free(struct snd_device *device)
{
- ak4531_t *ak4531 = device->device_data;
+ struct snd_ak4531 *ak4531 = device->device_data;
return snd_ak4531_free(ak4531);
}
@@ -345,12 +349,13 @@ static u8 snd_ak4531_initial_map[0x19 + 1] = {
0x01 /* 19: Mic Amp Setup */
};
-int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
+int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531,
+ struct snd_ak4531 **rak4531)
{
unsigned int idx;
int err;
- ak4531_t * ak4531;
- static snd_device_ops_t ops = {
+ struct snd_ak4531 *ak4531;
+ static struct snd_device_ops ops = {
.dev_free = snd_ak4531_dev_free,
};
@@ -370,7 +375,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
ak4531->write(ak4531, AK4531_RESET, 0x03); /* no RST, PD */
udelay(100);
ak4531->write(ak4531, AK4531_CLOCK, 0x00); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off LRCLK2 PLL */
- for (idx = 0; idx < 0x19; idx++) {
+ for (idx = 0; idx <= 0x19; idx++) {
if (idx == AK4531_RESET || idx == AK4531_CLOCK)
continue;
ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]); /* recording source is mixer */
@@ -395,13 +400,44 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
}
/*
+ * power management
+ */
+#ifdef CONFIG_PM
+void snd_ak4531_suspend(struct snd_ak4531 *ak4531)
+{
+ /* mute */
+ ak4531->write(ak4531, AK4531_LMASTER, 0x9f);
+ ak4531->write(ak4531, AK4531_RMASTER, 0x9f);
+ /* powerdown */
+ ak4531->write(ak4531, AK4531_RESET, 0x01);
+}
+void snd_ak4531_resume(struct snd_ak4531 *ak4531)
+{
+ int idx;
+
+ /* initialize */
+ ak4531->write(ak4531, AK4531_RESET, 0x03);
+ udelay(100);
+ ak4531->write(ak4531, AK4531_CLOCK, 0x00);
+ /* restore mixer registers */
+ for (idx = 0; idx <= 0x19; idx++) {
+ if (idx == AK4531_RESET || idx == AK4531_CLOCK)
+ continue;
+ ak4531->write(ak4531, idx, ak4531->regs[idx]);
+ }
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+/*
+ * /proc interface
*/
-static void snd_ak4531_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ak4531_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ak4531_t *ak4531 = entry->private_data;
+ struct snd_ak4531 *ak4531 = entry->private_data;
snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
snd_iprintf(buffer, "Recording source : %s\n"
@@ -410,15 +446,20 @@ static void snd_ak4531_proc_read(snd_info_entry_t *entry,
ak4531->regs[AK4531_MIC_GAIN] & 1 ? "+30dB" : "+0dB");
}
-static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531)
+static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak4531)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(card, "ak4531", &entry))
snd_info_set_text_ops(entry, ak4531, 1024, snd_ak4531_proc_read);
}
+#endif
EXPORT_SYMBOL(snd_ak4531_mixer);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(snd_ak4531_suspend);
+EXPORT_SYMBOL(snd_ak4531_resume);
+#endif
/*
* INIT part
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 1fdae678a345..a208075cdc1e 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -50,7 +50,7 @@
#include "ad1889.h"
#include "ac97/ac97_id.h"
-#define AD1889_DRVVER "$Revision: 1.4 $"
+#define AD1889_DRVVER "Version: 1.7"
MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>, Thibaut Varene <t-bone@parisc-linux.org>");
MODULE_DESCRIPTION("Analog Devices AD1889 ALSA sound driver");
@@ -87,20 +87,20 @@ struct ad1889_register_state {
};
struct snd_ad1889 {
- snd_card_t *card;
+ struct snd_card *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;
+ struct snd_ac97 *ac97;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_pcm *pcm;
+ struct snd_info_entry *proc;
- snd_pcm_substream_t *psubs;
- snd_pcm_substream_t *csubs;
+ struct snd_pcm_substream *psubs;
+ struct snd_pcm_substream *csubs;
/* playback register state */
struct ad1889_register_state wave;
@@ -241,14 +241,14 @@ ad1889_channel_reset(struct snd_ad1889 *chip, unsigned int channel)
}
static inline u16
-snd_ad1889_ac97_read(ac97_t *ac97, unsigned short reg)
+snd_ad1889_ac97_read(struct snd_ac97 *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)
+snd_ad1889_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
struct snd_ad1889 *chip = ac97->private_data;
ad1889_writew(chip, AD_AC97_BASE + reg, val);
@@ -273,20 +273,20 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
}
static int
-snd_ad1889_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+snd_ad1889_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *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)
+snd_ad1889_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static snd_pcm_hardware_t snd_ad1889_playback_hw = {
+static struct snd_pcm_hardware 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,
@@ -303,7 +303,7 @@ static snd_pcm_hardware_t snd_ad1889_playback_hw = {
/*.fifo_size = 0,*/
};
-static snd_pcm_hardware_t snd_ad1889_capture_hw = {
+static struct snd_pcm_hardware 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,
@@ -321,10 +321,10 @@ static snd_pcm_hardware_t snd_ad1889_capture_hw = {
};
static int
-snd_ad1889_playback_open(snd_pcm_substream_t *ss)
+snd_ad1889_playback_open(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_pcm_runtime *rt = ss->runtime;
chip->psubs = ss;
rt->hw = snd_ad1889_playback_hw;
@@ -333,10 +333,10 @@ snd_ad1889_playback_open(snd_pcm_substream_t *ss)
}
static int
-snd_ad1889_capture_open(snd_pcm_substream_t *ss)
+snd_ad1889_capture_open(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_pcm_runtime *rt = ss->runtime;
chip->csubs = ss;
rt->hw = snd_ad1889_capture_hw;
@@ -345,7 +345,7 @@ snd_ad1889_capture_open(snd_pcm_substream_t *ss)
}
static int
-snd_ad1889_playback_close(snd_pcm_substream_t *ss)
+snd_ad1889_playback_close(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
chip->psubs = NULL;
@@ -353,7 +353,7 @@ snd_ad1889_playback_close(snd_pcm_substream_t *ss)
}
static int
-snd_ad1889_capture_close(snd_pcm_substream_t *ss)
+snd_ad1889_capture_close(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
chip->csubs = NULL;
@@ -361,10 +361,10 @@ snd_ad1889_capture_close(snd_pcm_substream_t *ss)
}
static int
-snd_ad1889_playback_prepare(snd_pcm_substream_t *ss)
+snd_ad1889_playback_prepare(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_pcm_runtime *rt = ss->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(ss);
unsigned int count = snd_pcm_lib_period_bytes(ss);
u16 reg;
@@ -411,10 +411,10 @@ snd_ad1889_playback_prepare(snd_pcm_substream_t *ss)
}
static int
-snd_ad1889_capture_prepare(snd_pcm_substream_t *ss)
+snd_ad1889_capture_prepare(struct snd_pcm_substream *ss)
{
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
- snd_pcm_runtime_t *rt = ss->runtime;
+ struct snd_pcm_runtime *rt = ss->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(ss);
unsigned int count = snd_pcm_lib_period_bytes(ss);
u16 reg;
@@ -462,7 +462,7 @@ snd_ad1889_capture_prepare(snd_pcm_substream_t *ss)
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)
+snd_ad1889_playback_trigger(struct snd_pcm_substream *ss, int cmd)
{
u16 wsmc;
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
@@ -503,7 +503,7 @@ snd_ad1889_playback_trigger(snd_pcm_substream_t *ss, int cmd)
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)
+snd_ad1889_capture_trigger(struct snd_pcm_substream *ss, int cmd)
{
u16 ramc;
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
@@ -538,7 +538,7 @@ snd_ad1889_capture_trigger(snd_pcm_substream_t *ss, int cmd)
/* Called in atomic context with IRQ disabled */
static snd_pcm_uframes_t
-snd_ad1889_playback_pointer(snd_pcm_substream_t *ss)
+snd_ad1889_playback_pointer(struct snd_pcm_substream *ss)
{
size_t ptr = 0;
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
@@ -556,7 +556,7 @@ snd_ad1889_playback_pointer(snd_pcm_substream_t *ss)
/* Called in atomic context with IRQ disabled */
static snd_pcm_uframes_t
-snd_ad1889_capture_pointer(snd_pcm_substream_t *ss)
+snd_ad1889_capture_pointer(struct snd_pcm_substream *ss)
{
size_t ptr = 0;
struct snd_ad1889 *chip = snd_pcm_substream_chip(ss);
@@ -572,7 +572,7 @@ snd_ad1889_capture_pointer(snd_pcm_substream_t *ss)
return bytes_to_frames(ss->runtime, ptr);
}
-static snd_pcm_ops_t snd_ad1889_playback_ops = {
+static struct snd_pcm_ops snd_ad1889_playback_ops = {
.open = snd_ad1889_playback_open,
.close = snd_ad1889_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -583,7 +583,7 @@ static snd_pcm_ops_t snd_ad1889_playback_ops = {
.pointer = snd_ad1889_playback_pointer,
};
-static snd_pcm_ops_t snd_ad1889_capture_ops = {
+static struct snd_pcm_ops snd_ad1889_capture_ops = {
.open = snd_ad1889_capture_open,
.close = snd_ad1889_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -623,19 +623,11 @@ snd_ad1889_interrupt(int irq,
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)
+snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
if (rpcm)
*rpcm = NULL;
@@ -650,7 +642,6 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, snd_pcm_t **rpcm)
&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);
@@ -675,7 +666,7 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, snd_pcm_t **rpcm)
}
static void
-snd_ad1889_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+snd_ad1889_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct snd_ad1889 *chip = entry->private_data;
u16 reg;
@@ -758,7 +749,7 @@ snd_ad1889_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
static void __devinit
snd_ad1889_proc_init(struct snd_ad1889 *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read);
@@ -800,14 +791,14 @@ snd_ad1889_ac97_xinit(struct snd_ad1889 *chip)
}
static void
-snd_ad1889_ac97_bus_free(ac97_bus_t *bus)
+snd_ad1889_ac97_bus_free(struct snd_ac97_bus *bus)
{
struct snd_ad1889 *chip = bus->private_data;
chip->ac97_bus = NULL;
}
static void
-snd_ad1889_ac97_free(ac97_t *ac97)
+snd_ad1889_ac97_free(struct snd_ac97 *ac97)
{
struct snd_ad1889 *chip = ac97->private_data;
chip->ac97 = NULL;
@@ -817,8 +808,8 @@ 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 = {
+ struct snd_ac97_template ac97;
+ static struct snd_ac97_bus_ops ops = {
.write = snd_ad1889_ac97_write,
.read = snd_ad1889_ac97_read,
};
@@ -882,7 +873,7 @@ skip_hw:
}
static inline int
-snd_ad1889_dev_free(snd_device_t *device)
+snd_ad1889_dev_free(struct snd_device *device)
{
struct snd_ad1889 *chip = device->device_data;
return snd_ad1889_free(chip);
@@ -903,14 +894,14 @@ snd_ad1889_init(struct snd_ad1889 *chip)
}
static int __devinit
-snd_ad1889_create(snd_card_t *card,
+snd_ad1889_create(struct snd_card *card,
struct pci_dev *pci,
struct snd_ad1889 **rchip)
{
int err;
struct snd_ad1889 *chip;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ad1889_dev_free,
};
@@ -994,7 +985,7 @@ snd_ad1889_probe(struct pci_dev *pci,
{
int err;
static int devno;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_ad1889 *chip;
/* (1) */
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index feffbe73387e..bc4d1ef08efa 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -170,10 +170,10 @@ module_param(enable, bool, 0444);
#define MAX_CODECS 2
-typedef struct snd_stru_ali ali_t;
-typedef struct snd_ali_stru_voice snd_ali_voice_t;
+struct snd_ali;
+struct snd_ali_voice;
-typedef struct snd_ali_channel_control {
+struct snd_ali_channel_control {
// register data
struct REGDATA {
unsigned int start;
@@ -192,9 +192,9 @@ typedef struct snd_ali_channel_control {
unsigned int ac97write;
} regs;
-} snd_ali_channel_control_t;
+};
-struct snd_ali_stru_voice {
+struct snd_ali_voice {
unsigned int number;
unsigned int use: 1,
pcm: 1,
@@ -203,9 +203,9 @@ struct snd_ali_stru_voice {
synth: 1;
/* PCM data */
- ali_t *codec;
- snd_pcm_substream_t *substream;
- snd_ali_voice_t *extra;
+ struct snd_ali *codec;
+ struct snd_pcm_substream *substream;
+ struct snd_ali_voice *extra;
unsigned int running: 1;
@@ -219,28 +219,28 @@ struct snd_ali_stru_voice {
};
-typedef struct snd_stru_alidev {
+struct snd_alidev {
- snd_ali_voice_t voices[ALI_CHANNELS];
+ struct snd_ali_voice voices[ALI_CHANNELS];
unsigned int chcnt; /* num of opened channels */
unsigned int chmap; /* bitmap for opened channels */
unsigned int synthcount;
-} alidev_t;
+};
#ifdef CONFIG_PM
#define ALI_GLOBAL_REGS 56
#define ALI_CHANNEL_REGS 8
-typedef struct snd_ali_image {
+struct snd_ali_image {
unsigned long regs[ALI_GLOBAL_REGS];
unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
-} ali_image_t;
+};
#endif
-struct snd_stru_ali {
+struct snd_ali {
unsigned long irq;
unsigned long port;
unsigned char revision;
@@ -252,10 +252,10 @@ struct snd_stru_ali {
struct pci_dev *pci_m1533;
struct pci_dev *pci_m7101;
- snd_card_t *card;
- snd_pcm_t *pcm[MAX_CODECS];
- alidev_t synth;
- snd_ali_channel_control_t chregs;
+ struct snd_card *card;
+ struct snd_pcm *pcm[MAX_CODECS];
+ struct snd_alidev synth;
+ struct snd_ali_channel_control chregs;
/* S/PDIF Mask */
unsigned int spdif_mask;
@@ -265,8 +265,8 @@ struct snd_stru_ali {
unsigned int num_of_codecs;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97[MAX_CODECS];
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97[MAX_CODECS];
unsigned short ac97_ext_id;
unsigned short ac97_ext_status;
@@ -274,7 +274,7 @@ struct snd_stru_ali {
spinlock_t voice_alloc;
#ifdef CONFIG_PM
- ali_image_t *image;
+ struct snd_ali_image *image;
#endif
};
@@ -284,9 +284,9 @@ static struct pci_device_id snd_ali_ids[] = {
};
MODULE_DEVICE_TABLE(pci, snd_ali_ids);
-static void snd_ali_clear_voices(ali_t *, unsigned int, unsigned int);
-static unsigned short snd_ali_codec_peek(ali_t *, int, unsigned short);
-static void snd_ali_codec_poke(ali_t *, int, unsigned short, unsigned short);
+static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int);
+static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short);
+static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short, unsigned short);
/*
* Debug Part
@@ -294,7 +294,7 @@ static void snd_ali_codec_poke(ali_t *, int, unsigned short, unsigned short);
#ifdef ALI_DEBUG
-static void ali_read_regs(ali_t *codec, int channel)
+static void ali_read_regs(struct snd_ali *codec, int channel)
{
int i,j;
unsigned int dwVal;
@@ -344,7 +344,7 @@ static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
}
pci_dev_put(pci_dev);
}
-static void ali_read_ac97regs(ali_t *codec, int secondary)
+static void ali_read_ac97regs(struct snd_ali *codec, int secondary)
{
unsigned short i,j;
unsigned short wVal;
@@ -373,40 +373,38 @@ static void ali_read_ac97regs(ali_t *codec, int secondary)
* AC97 ACCESS
*/
-static inline unsigned int snd_ali_5451_peek(ali_t *codec,
+static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec,
unsigned int port )
{
return (unsigned int)inl(ALI_REG(codec, port));
}
-static inline void snd_ali_5451_poke( ali_t *codec,
+static inline void snd_ali_5451_poke( struct snd_ali *codec,
unsigned int port,
unsigned int val )
{
outl((unsigned int)val, ALI_REG(codec, port));
}
-static int snd_ali_codec_ready( ali_t *codec,
- unsigned int port,
- int sched )
+static int snd_ali_codec_ready( struct snd_ali *codec,
+ unsigned int port )
{
unsigned long end_time;
unsigned int res;
- end_time = jiffies + 10 * msecs_to_jiffies(250);
+ end_time = jiffies + msecs_to_jiffies(250);
do {
res = snd_ali_5451_peek(codec,port);
if (! (res & 0x8000))
return 0;
- if (sched)
- schedule_timeout_uninterruptible(1);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
snd_ali_5451_poke(codec, port, res & ~0x8000);
snd_printdd("ali_codec_ready: codec is not ready.\n ");
return -EIO;
}
-static int snd_ali_stimer_ready(ali_t *codec, int sched)
+static int snd_ali_stimer_ready(struct snd_ali *codec)
{
unsigned long end_time;
unsigned long dwChk1,dwChk2;
@@ -414,19 +412,18 @@ static int snd_ali_stimer_ready(ali_t *codec, int sched)
dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
- end_time = jiffies + 10 * msecs_to_jiffies(250);
+ end_time = jiffies + msecs_to_jiffies(250);
do {
dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
if (dwChk2 != dwChk1)
return 0;
- if (sched)
- schedule_timeout_uninterruptible(1);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n");
return -EIO;
}
-static void snd_ali_codec_poke(ali_t *codec,int secondary,
+static void snd_ali_codec_poke(struct snd_ali *codec,int secondary,
unsigned short reg,
unsigned short val)
{
@@ -440,9 +437,9 @@ static void snd_ali_codec_poke(ali_t *codec,int secondary,
port = codec->chregs.regs.ac97write;
- if (snd_ali_codec_ready(codec, port, 0) < 0)
+ if (snd_ali_codec_ready(codec, port) < 0)
return;
- if (snd_ali_stimer_ready(codec, 0) < 0)
+ if (snd_ali_stimer_ready(codec) < 0)
return;
dwVal = (unsigned int) (reg & 0xff);
@@ -455,7 +452,7 @@ static void snd_ali_codec_poke(ali_t *codec,int secondary,
return ;
}
-static unsigned short snd_ali_codec_peek( ali_t *codec,
+static unsigned short snd_ali_codec_peek( struct snd_ali *codec,
int secondary,
unsigned short reg)
{
@@ -469,9 +466,9 @@ static unsigned short snd_ali_codec_peek( ali_t *codec,
port = codec->chregs.regs.ac97read;
- if (snd_ali_codec_ready(codec, port, 0) < 0)
+ if (snd_ali_codec_ready(codec, port) < 0)
return ~0;
- if (snd_ali_stimer_ready(codec, 0) < 0)
+ if (snd_ali_stimer_ready(codec) < 0)
return ~0;
dwVal = (unsigned int) (reg & 0xff);
@@ -480,19 +477,19 @@ static unsigned short snd_ali_codec_peek( ali_t *codec,
snd_ali_5451_poke(codec, port, dwVal);
- if (snd_ali_stimer_ready(codec, 0) < 0)
+ if (snd_ali_stimer_ready(codec) < 0)
return ~0;
- if (snd_ali_codec_ready(codec, port, 0) < 0)
+ if (snd_ali_codec_ready(codec, port) < 0)
return ~0;
return (snd_ali_5451_peek(codec, port) & 0xffff0000)>>16;
}
-static void snd_ali_codec_write(ac97_t *ac97,
+static void snd_ali_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val )
{
- ali_t *codec = ac97->private_data;
+ struct snd_ali *codec = ac97->private_data;
snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
if(reg == AC97_GPIO_STATUS) {
@@ -505,9 +502,9 @@ static void snd_ali_codec_write(ac97_t *ac97,
}
-static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
- ali_t *codec = ac97->private_data;
+ struct snd_ali *codec = ac97->private_data;
snd_ali_printk("codec_read reg=%xh.\n", reg);
return (snd_ali_codec_peek(codec, ac97->num, reg));
@@ -517,7 +514,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
* AC97 Reset
*/
-static int snd_ali_reset_5451(ali_t *codec)
+static int snd_ali_reset_5451(struct snd_ali *codec)
{
struct pci_dev *pci_dev = NULL;
unsigned short wCount, wReg;
@@ -555,7 +552,7 @@ static int snd_ali_reset_5451(ali_t *codec)
#ifdef CODEC_RESET
-static int snd_ali_reset_codec(ali_t *codec)
+static int snd_ali_reset_codec(struct snd_ali *codec)
{
struct pci_dev *pci_dev = NULL;
unsigned char bVal = 0;
@@ -596,7 +593,7 @@ static int snd_ali_reset_codec(ali_t *codec)
* ALI 5451 Controller
*/
-static void snd_ali_enable_special_channel(ali_t *codec, unsigned int channel)
+static void snd_ali_enable_special_channel(struct snd_ali *codec, unsigned int channel)
{
unsigned long dwVal = 0;
@@ -605,7 +602,7 @@ static void snd_ali_enable_special_channel(ali_t *codec, unsigned int channel)
outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL));
}
-static void snd_ali_disable_special_channel(ali_t *codec, unsigned int channel)
+static void snd_ali_disable_special_channel(struct snd_ali *codec, unsigned int channel)
{
unsigned long dwVal = 0;
@@ -614,7 +611,7 @@ static void snd_ali_disable_special_channel(ali_t *codec, unsigned int channel)
outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL));
}
-static void snd_ali_enable_address_interrupt(ali_t * codec)
+static void snd_ali_enable_address_interrupt(struct snd_ali * codec)
{
unsigned int gc;
@@ -624,7 +621,7 @@ static void snd_ali_enable_address_interrupt(ali_t * codec)
outl( gc, ALI_REG(codec, ALI_GC_CIR));
}
-static void snd_ali_disable_address_interrupt(ali_t * codec)
+static void snd_ali_disable_address_interrupt(struct snd_ali * codec)
{
unsigned int gc;
@@ -635,10 +632,10 @@ static void snd_ali_disable_address_interrupt(ali_t * codec)
}
#if 0 // not used
-static void snd_ali_enable_voice_irq(ali_t *codec, unsigned int channel)
+static void snd_ali_enable_voice_irq(struct snd_ali *codec, unsigned int channel)
{
unsigned int mask;
- snd_ali_channel_control_t *pchregs = &(codec->chregs);
+ struct snd_ali_channel_control *pchregs = &(codec->chregs);
snd_ali_printk("enable_voice_irq channel=%d\n",channel);
@@ -649,10 +646,10 @@ static void snd_ali_enable_voice_irq(ali_t *codec, unsigned int channel)
}
#endif
-static void snd_ali_disable_voice_irq(ali_t *codec, unsigned int channel)
+static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channel)
{
unsigned int mask;
- snd_ali_channel_control_t *pchregs = &(codec->chregs);
+ struct snd_ali_channel_control *pchregs = &(codec->chregs);
snd_ali_printk("disable_voice_irq channel=%d\n",channel);
@@ -662,7 +659,7 @@ static void snd_ali_disable_voice_irq(ali_t *codec, unsigned int channel)
outl(pchregs->data.ainten,ALI_REG(codec,pchregs->regs.ainten));
}
-static int snd_ali_alloc_pcm_channel(ali_t *codec, int channel)
+static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel)
{
unsigned int idx = channel & 0x1f;
@@ -680,7 +677,7 @@ static int snd_ali_alloc_pcm_channel(ali_t *codec, int channel)
return -1;
}
-static int snd_ali_find_free_channel(ali_t * codec, int rec)
+static int snd_ali_find_free_channel(struct snd_ali * codec, int rec)
{
int idx;
int result = -1;
@@ -722,7 +719,7 @@ static int snd_ali_find_free_channel(ali_t * codec, int rec)
return -1;
}
-static void snd_ali_free_channel_pcm(ali_t *codec, int channel)
+static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)
{
unsigned int idx = channel & 0x0000001f;
@@ -741,7 +738,7 @@ static void snd_ali_free_channel_pcm(ali_t *codec, int channel)
}
#if 0 // not used
-static void snd_ali_start_voice(ali_t * codec, unsigned int channel)
+static void snd_ali_start_voice(struct snd_ali * codec, unsigned int channel)
{
unsigned int mask = 1 << (channel & 0x1f);
@@ -750,7 +747,7 @@ static void snd_ali_start_voice(ali_t * codec, unsigned int channel)
}
#endif
-static void snd_ali_stop_voice(ali_t * codec, unsigned int channel)
+static void snd_ali_stop_voice(struct snd_ali * codec, unsigned int channel)
{
unsigned int mask = 1 << (channel & 0x1f);
@@ -762,7 +759,7 @@ static void snd_ali_stop_voice(ali_t * codec, unsigned int channel)
* S/PDIF Part
*/
-static void snd_ali_delay(ali_t *codec,int interval)
+static void snd_ali_delay(struct snd_ali *codec,int interval)
{
unsigned long begintimer,currenttimer;
@@ -770,13 +767,13 @@ static void snd_ali_delay(ali_t *codec,int interval)
currenttimer = inl(ALI_REG(codec, ALI_STIMER));
while (currenttimer < begintimer + interval) {
- if(snd_ali_stimer_ready(codec, 1) < 0)
+ if(snd_ali_stimer_ready(codec) < 0)
break;
currenttimer = inl(ALI_REG(codec, ALI_STIMER));
}
}
-static void snd_ali_detect_spdif_rate(ali_t *codec)
+static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
{
u16 wval = 0;
u16 count = 0;
@@ -830,7 +827,7 @@ static void snd_ali_detect_spdif_rate(ali_t *codec)
}
}
-static unsigned int snd_ali_get_spdif_in_rate(ali_t *codec)
+static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec)
{
u32 dwRate = 0;
u8 bval = 0;
@@ -852,7 +849,7 @@ static unsigned int snd_ali_get_spdif_in_rate(ali_t *codec)
return dwRate;
}
-static void snd_ali_enable_spdif_in(ali_t *codec)
+static void snd_ali_enable_spdif_in(struct snd_ali *codec)
{
unsigned int dwVal;
@@ -867,7 +864,7 @@ static void snd_ali_enable_spdif_in(ali_t *codec)
snd_ali_enable_special_channel(codec, ALI_SPDIF_IN_CHANNEL);
}
-static void snd_ali_disable_spdif_in(ali_t *codec)
+static void snd_ali_disable_spdif_in(struct snd_ali *codec)
{
unsigned int dwVal;
@@ -879,7 +876,7 @@ static void snd_ali_disable_spdif_in(ali_t *codec)
}
-static void snd_ali_set_spdif_out_rate(ali_t *codec, unsigned int rate)
+static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate)
{
unsigned char bVal;
unsigned int dwRate = 0;
@@ -900,7 +897,7 @@ static void snd_ali_set_spdif_out_rate(ali_t *codec, unsigned int rate)
outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2));
}
-static void snd_ali_enable_spdif_out(ali_t *codec)
+static void snd_ali_enable_spdif_out(struct snd_ali *codec)
{
unsigned short wVal;
unsigned char bVal;
@@ -936,7 +933,7 @@ static void snd_ali_enable_spdif_out(ali_t *codec)
}
}
-static void snd_ali_enable_spdif_chnout(ali_t *codec)
+static void snd_ali_enable_spdif_chnout(struct snd_ali *codec)
{
unsigned short wVal = 0;
@@ -954,7 +951,7 @@ static void snd_ali_enable_spdif_chnout(ali_t *codec)
snd_ali_enable_special_channel(codec,ALI_SPDIF_OUT_CHANNEL);
}
-static void snd_ali_disable_spdif_chnout(ali_t *codec)
+static void snd_ali_disable_spdif_chnout(struct snd_ali *codec)
{
unsigned short wVal = 0;
wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
@@ -964,7 +961,7 @@ static void snd_ali_disable_spdif_chnout(ali_t *codec)
snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
}
-static void snd_ali_disable_spdif_out(ali_t *codec)
+static void snd_ali_disable_spdif_out(struct snd_ali *codec)
{
unsigned char bVal;
@@ -974,11 +971,11 @@ static void snd_ali_disable_spdif_out(ali_t *codec)
snd_ali_disable_spdif_chnout(codec);
}
-static void snd_ali_update_ptr(ali_t *codec,int channel)
+static void snd_ali_update_ptr(struct snd_ali *codec,int channel)
{
- snd_ali_voice_t *pvoice = NULL;
- snd_pcm_runtime_t *runtime;
- snd_ali_channel_control_t *pchregs = NULL;
+ struct snd_ali_voice *pvoice = NULL;
+ struct snd_pcm_runtime *runtime;
+ struct snd_ali_channel_control *pchregs = NULL;
unsigned int old, mask;
#ifdef ALI_DEBUG
unsigned int temp, cspf;
@@ -1029,11 +1026,11 @@ static void snd_ali_update_ptr(ali_t *codec,int channel)
pchregs->data.aint = old & (~mask);
}
-static void snd_ali_interrupt(ali_t * codec)
+static void snd_ali_interrupt(struct snd_ali * codec)
{
int channel;
unsigned int audio_int;
- snd_ali_channel_control_t *pchregs = NULL;
+ struct snd_ali_channel_control *pchregs = NULL;
pchregs = &(codec->chregs);
audio_int = inl(ALI_REG(codec, ALI_MISCINT));
@@ -1053,7 +1050,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
void *dev_id,
struct pt_regs *regs)
{
- ali_t *codec = dev_id;
+ struct snd_ali *codec = dev_id;
if (codec == NULL)
return IRQ_NONE;
@@ -1062,38 +1059,37 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
}
-static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
+static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, int type, int rec, int channel)
{
- snd_ali_voice_t *pvoice = NULL;
- unsigned long flags;
+ struct snd_ali_voice *pvoice = NULL;
int idx;
snd_ali_printk("alloc_voice: type=%d rec=%d\n",type,rec);
- spin_lock_irqsave(&codec->voice_alloc, flags);
+ spin_lock_irq(&codec->voice_alloc);
if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
snd_ali_find_free_channel(codec,rec);
if(idx < 0) {
snd_printk(KERN_ERR "ali_alloc_voice: err.\n");
- spin_unlock_irqrestore(&codec->voice_alloc, flags);
+ spin_unlock_irq(&codec->voice_alloc);
return NULL;
}
pvoice = &(codec->synth.voices[idx]);
+ pvoice->codec = codec;
pvoice->use = 1;
pvoice->pcm = 1;
pvoice->mode = rec;
- spin_unlock_irqrestore(&codec->voice_alloc, flags);
+ spin_unlock_irq(&codec->voice_alloc);
return pvoice;
}
- spin_unlock_irqrestore(&codec->voice_alloc, flags);
+ spin_unlock_irq(&codec->voice_alloc);
return NULL;
}
-static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
+static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvoice)
{
- unsigned long flags;
void (*private_free)(void *);
void *private_data;
@@ -1101,7 +1097,7 @@ static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
if (pvoice == NULL || !pvoice->use)
return;
snd_ali_clear_voices(codec, pvoice->number, pvoice->number);
- spin_lock_irqsave(&codec->voice_alloc, flags);
+ spin_lock_irq(&codec->voice_alloc);
private_free = pvoice->private_free;
private_data = pvoice->private_data;
pvoice->private_free = NULL;
@@ -1111,13 +1107,13 @@ static void snd_ali_free_voice(ali_t * codec, snd_ali_voice_t *pvoice)
}
pvoice->use = pvoice->pcm = pvoice->synth = 0;
pvoice->substream = NULL;
- spin_unlock_irqrestore(&codec->voice_alloc, flags);
+ spin_unlock_irq(&codec->voice_alloc);
if (private_free)
private_free(private_data);
}
-static void snd_ali_clear_voices(ali_t * codec,
+static void snd_ali_clear_voices(struct snd_ali * codec,
unsigned int v_min,
unsigned int v_max)
{
@@ -1129,7 +1125,7 @@ static void snd_ali_clear_voices(ali_t * codec,
}
}
-static void snd_ali_write_voice_regs(ali_t * codec,
+static void snd_ali_write_voice_regs(struct snd_ali * codec,
unsigned int Channel,
unsigned int LBA,
unsigned int CSO,
@@ -1196,10 +1192,10 @@ static unsigned int snd_ali_convert_rate(unsigned int rate, int rec)
return delta;
}
-static unsigned int snd_ali_control_mode(snd_pcm_substream_t *substream)
+static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream)
{
unsigned int CTRL;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
/* set ctrl mode
CTRL default: 8-bit (unsigned) mono, loop mode enabled
@@ -1218,21 +1214,21 @@ static unsigned int snd_ali_control_mode(snd_pcm_substream_t *substream)
* PCM part
*/
-static int snd_ali_ioctl(snd_pcm_substream_t * substream,
+static int snd_ali_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static int snd_ali_trigger(snd_pcm_substream_t *substream,
+static int snd_ali_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
unsigned int what, whati, capture_flag;
- snd_ali_voice_t *pvoice = NULL, *evoice = NULL;
+ struct snd_ali_voice *pvoice = NULL, *evoice = NULL;
unsigned int val;
int do_start;
@@ -1250,8 +1246,8 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
what = whati = capture_flag = 0;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
- if ((ali_t *) snd_pcm_substream_chip(s) == codec) {
- pvoice = (snd_ali_voice_t *) s->runtime->private_data;
+ if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) {
+ pvoice = s->runtime->private_data;
evoice = pvoice->extra;
what |= 1 << (pvoice->number & 0x1f);
if (evoice == NULL) {
@@ -1294,13 +1290,13 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
- snd_ali_voice_t *evoice = pvoice->extra;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
+ struct snd_ali_voice *evoice = pvoice->extra;
int err;
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
if (err < 0) return err;
@@ -1325,12 +1321,12 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
- snd_ali_voice_t *evoice = pvoice ? pvoice->extra : NULL;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
+ struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
snd_pcm_lib_free_pages(substream);
if (evoice != NULL) {
@@ -1340,24 +1336,23 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ali_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ali_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ali_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
- snd_ali_voice_t *evoice = pvoice->extra;
- unsigned long flags;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
+ struct snd_ali_voice *evoice = pvoice->extra;
unsigned int LBA;
unsigned int Delta;
@@ -1370,7 +1365,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
snd_ali_printk("playback_prepare ...\n");
- spin_lock_irqsave(&codec->reg_lock, flags);
+ spin_lock_irq(&codec->reg_lock);
/* set Delta (rate) value */
Delta = snd_ali_convert_rate(runtime->rate, 0);
@@ -1435,17 +1430,16 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
CTRL,
EC);
}
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
return 0;
}
-static int snd_ali_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_prepare(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
- unsigned long flags;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
unsigned int LBA;
unsigned int Delta;
unsigned int ESO;
@@ -1456,7 +1450,7 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
unsigned int EC;
u8 bValue;
- spin_lock_irqsave(&codec->reg_lock, flags);
+ spin_lock_irq(&codec->reg_lock);
snd_ali_printk("ali_prepare...\n");
@@ -1471,15 +1465,16 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
unsigned int rate;
- if (codec->revision != ALI_5451_V02) {
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
+ if (codec->revision != ALI_5451_V02)
return -1;
- }
+
rate = snd_ali_get_spdif_in_rate(codec);
if (rate == 0) {
snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n");
rate = 48000;
}
+ spin_lock_irq(&codec->reg_lock);
bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));
if (bValue & 0x10) {
outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));
@@ -1521,17 +1516,17 @@ static int snd_ali_prepare(snd_pcm_substream_t * substream)
EC);
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
return 0;
}
-static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_playback_pointer(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
unsigned int cso;
spin_lock(&codec->reg_lock);
@@ -1548,27 +1543,26 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream
}
-static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice = runtime->private_data;
unsigned int cso;
- unsigned long flags;
- spin_lock_irqsave(&codec->reg_lock, flags);
+ spin_lock(&codec->reg_lock);
if (!pvoice->running) {
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
return 0;
}
outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock(&codec->reg_lock);
return cso;
}
-static snd_pcm_hardware_t snd_ali_playback =
+static struct snd_pcm_hardware snd_ali_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1594,7 +1588,7 @@ static snd_pcm_hardware_t snd_ali_playback =
* Capture support device description
*/
-static snd_pcm_hardware_t snd_ali_capture =
+static struct snd_pcm_hardware snd_ali_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1616,36 +1610,27 @@ static snd_pcm_hardware_t snd_ali_capture =
.fifo_size = 0,
};
-static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
- unsigned long flags;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
- ali_t *codec;
+ struct snd_ali_voice *pvoice = runtime->private_data;
+ struct snd_ali *codec;
if (pvoice) {
codec = pvoice->codec;
- spin_lock_irqsave(&codec->reg_lock, flags);
snd_ali_free_voice(pvoice->codec, pvoice);
- spin_unlock_irqrestore(&codec->reg_lock, flags);
}
}
-static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
- snd_pcm_hardware_t *phw)
+static int snd_ali_open(struct snd_pcm_substream *substream, int rec, int channel,
+ struct snd_pcm_hardware *phw)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice;
- unsigned long flags = 0;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ali_voice *pvoice;
- spin_lock_irqsave(&codec->reg_lock, flags);
pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
- if (pvoice == NULL) {
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ if (pvoice == NULL)
return -EAGAIN;
- }
- pvoice->codec = codec;
- spin_unlock_irqrestore(&codec->reg_lock, flags);
pvoice->substream = substream;
runtime->private_data = pvoice;
@@ -1657,32 +1642,32 @@ static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
return 0;
}
-static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+static int snd_ali_playback_open(struct snd_pcm_substream *substream)
{
return snd_ali_open(substream, 0, -1, &snd_ali_playback);
}
-static int snd_ali_capture_open(snd_pcm_substream_t * substream)
+static int snd_ali_capture_open(struct snd_pcm_substream *substream)
{
return snd_ali_open(substream, 1, -1, &snd_ali_capture);
}
-static int snd_ali_playback_close(snd_pcm_substream_t * substream)
+static int snd_ali_playback_close(struct snd_pcm_substream *substream)
{
return 0;
}
-static int snd_ali_close(snd_pcm_substream_t * substream)
+static int snd_ali_close(struct snd_pcm_substream *substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data;
+ struct snd_ali *codec = snd_pcm_substream_chip(substream);
+ struct snd_ali_voice *pvoice = substream->runtime->private_data;
snd_ali_disable_special_channel(codec,pvoice->number);
return 0;
}
-static snd_pcm_ops_t snd_ali_playback_ops = {
+static struct snd_pcm_ops snd_ali_playback_ops = {
.open = snd_ali_playback_open,
.close = snd_ali_playback_close,
.ioctl = snd_ali_ioctl,
@@ -1693,7 +1678,7 @@ static snd_pcm_ops_t snd_ali_playback_ops = {
.pointer = snd_ali_playback_pointer,
};
-static snd_pcm_ops_t snd_ali_capture_ops = {
+static struct snd_pcm_ops snd_ali_capture_ops = {
.open = snd_ali_capture_open,
.close = snd_ali_close,
.ioctl = snd_ali_ioctl,
@@ -1708,17 +1693,17 @@ static snd_pcm_ops_t snd_ali_capture_ops = {
* Modem PCM
*/
-static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ali_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ali *chip = snd_pcm_substream_chip(substream);
unsigned int modem_num = chip->num_of_codecs - 1;
snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
return snd_ali_hw_params(substream, hw_params);
}
-static snd_pcm_hardware_t snd_ali_modem =
+static struct snd_pcm_hardware snd_ali_modem =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1739,10 +1724,10 @@ static snd_pcm_hardware_t snd_ali_modem =
.fifo_size = 0,
};
-static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel)
+static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, int channel)
{
static unsigned int rates [] = {8000,9600,12000,16000};
- static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+ static struct snd_pcm_hw_constraint_list hw_constraint_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -1754,17 +1739,17 @@ static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int chan
SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
}
-static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream)
+static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream)
{
return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
}
-static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream)
+static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream)
{
return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
}
-static snd_pcm_ops_t snd_ali_modem_playback_ops = {
+static struct snd_pcm_ops snd_ali_modem_playback_ops = {
.open = snd_ali_modem_playback_open,
.close = snd_ali_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1775,7 +1760,7 @@ static snd_pcm_ops_t snd_ali_modem_playback_ops = {
.pointer = snd_ali_pointer,
};
-static snd_pcm_ops_t snd_ali_modem_capture_ops = {
+static struct snd_pcm_ops snd_ali_modem_capture_ops = {
.open = snd_ali_modem_capture_open,
.close = snd_ali_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1791,22 +1776,22 @@ struct ali_pcm_description {
char *name;
unsigned int playback_num;
unsigned int capture_num;
- snd_pcm_ops_t *playback_ops;
- snd_pcm_ops_t *capture_ops;
+ struct snd_pcm_ops *playback_ops;
+ struct snd_pcm_ops *capture_ops;
unsigned short class;
};
-static void snd_ali_pcm_free(snd_pcm_t *pcm)
+static void snd_ali_pcm_free(struct snd_pcm *pcm)
{
- ali_t *codec = pcm->private_data;
+ struct snd_ali *codec = pcm->private_data;
codec->pcm[pcm->device] = NULL;
}
-static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc)
+static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_pcm_description *desc)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(codec->card, desc->name, device,
@@ -1838,7 +1823,7 @@ static struct ali_pcm_description ali_pcms[] = {
{ "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops, SNDRV_PCM_CLASS_MODEM }
};
-static int __devinit snd_ali_build_pcms(ali_t *codec)
+static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
{
int i, err;
for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
@@ -1853,7 +1838,7 @@ static int __devinit snd_ali_build_pcms(ali_t *codec)
.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
.put = snd_ali5451_spdif_put, .private_value = value}
-static int snd_ali5451_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1862,15 +1847,14 @@ static int snd_ali5451_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- unsigned long flags;
- ali_t *codec = kcontrol->private_data;
+ struct snd_ali *codec = kcontrol->private_data;
unsigned int enable;
enable = ucontrol->value.integer.value[0] ? 1 : 0;
- spin_lock_irqsave(&codec->reg_lock, flags);
+ spin_lock_irq(&codec->reg_lock);
switch(kcontrol->private_value) {
case 0:
enable = (codec->spdif_mask & 0x02) ? 1 : 0;
@@ -1885,19 +1869,18 @@ static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
break;
}
ucontrol->value.integer.value[0] = enable;
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
return 0;
}
-static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- unsigned long flags;
- ali_t *codec = kcontrol->private_data;
+ struct snd_ali *codec = kcontrol->private_data;
unsigned int change = 0, enable = 0;
enable = ucontrol->value.integer.value[0] ? 1 : 0;
- spin_lock_irqsave(&codec->reg_lock, flags);
+ spin_lock_irq(&codec->reg_lock);
switch (kcontrol->private_value) {
case 0:
change = (codec->spdif_mask & 0x02) ? 1 : 0;
@@ -1942,12 +1925,12 @@ static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
default:
break;
}
- spin_unlock_irqrestore(&codec->reg_lock, flags);
+ spin_unlock_irq(&codec->reg_lock);
return change;
}
-static snd_kcontrol_new_t snd_ali5451_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
/* spdif aplayback switch */
/* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
@@ -1957,24 +1940,24 @@ static snd_kcontrol_new_t snd_ali5451_mixer_spdif[] __devinitdata = {
ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
};
-static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_ali_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- ali_t *codec = bus->private_data;
+ struct snd_ali *codec = bus->private_data;
codec->ac97_bus = NULL;
}
-static void snd_ali_mixer_free_ac97(ac97_t *ac97)
+static void snd_ali_mixer_free_ac97(struct snd_ac97 *ac97)
{
- ali_t *codec = ac97->private_data;
+ struct snd_ali *codec = ac97->private_data;
codec->ac97[ac97->num] = NULL;
}
-static int __devinit snd_ali_mixer(ali_t * codec)
+static int __devinit snd_ali_mixer(struct snd_ali * codec)
{
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
unsigned int idx;
int i, err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_ali_codec_write,
.read = snd_ali_codec_read,
};
@@ -2008,21 +1991,21 @@ static int __devinit snd_ali_mixer(ali_t * codec)
}
#ifdef CONFIG_PM
-static int ali_suspend(snd_card_t *card, pm_message_t state)
+static int ali_suspend(struct pci_dev *pci, pm_message_t state)
{
- ali_t *chip = card->pm_private_data;
- ali_image_t *im;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ali *chip = card->private_data;
+ struct snd_ali_image *im;
int i, j;
im = chip->image;
if (! im)
return 0;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for(i = 0 ; i < chip->num_of_codecs ; i++) {
- if (chip->pcm[i])
- snd_pcm_suspend_all(chip->pcm[i]);
- if(chip->ac97[i])
- snd_ac97_suspend(chip->ac97[i]);
+ snd_pcm_suspend_all(chip->pcm[i]);
+ snd_ac97_suspend(chip->ac97[i]);
}
spin_lock_irq(&chip->reg_lock);
@@ -2050,21 +2033,24 @@ static int ali_suspend(snd_card_t *card, pm_message_t state)
outl(0xffffffff, ALI_REG(chip, ALI_STOP));
spin_unlock_irq(&chip->reg_lock);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int ali_resume(snd_card_t *card)
+static int ali_resume(struct pci_dev *pci)
{
- ali_t *chip = card->pm_private_data;
- ali_image_t *im;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ali *chip = card->private_data;
+ struct snd_ali_image *im;
int i, j;
im = chip->image;
if (! im)
return 0;
- pci_enable_device(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
spin_lock_irq(&chip->reg_lock);
@@ -2088,14 +2074,14 @@ static int ali_resume(snd_card_t *card)
spin_unlock_irq(&chip->reg_lock);
for(i = 0 ; i < chip->num_of_codecs ; i++)
- if(chip->ac97[i])
- snd_ac97_resume(chip->ac97[i]);
+ snd_ac97_resume(chip->ac97[i]);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_ali_free(ali_t * codec)
+static int snd_ali_free(struct snd_ali * codec)
{
if (codec->hw_initialized)
snd_ali_disable_address_interrupt(codec);
@@ -2115,7 +2101,7 @@ static int snd_ali_free(ali_t * codec)
return 0;
}
-static int snd_ali_chip_init(ali_t *codec)
+static int snd_ali_chip_init(struct snd_ali *codec)
{
unsigned int legacy;
unsigned char temp;
@@ -2174,22 +2160,22 @@ static int snd_ali_chip_init(ali_t *codec)
}
/* proc for register dump */
-static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
+static void snd_ali_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
{
- ali_t *codec = entry->private_data;
+ struct snd_ali *codec = entry->private_data;
int i;
for(i = 0 ; i < 256 ; i+= 4)
snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
}
-static void __devinit snd_ali_proc_init(ali_t *codec)
+static void __devinit snd_ali_proc_init(struct snd_ali *codec)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if(!snd_card_proc_new(codec->card, "ali5451", &entry))
snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
}
-static int __devinit snd_ali_resources(ali_t *codec)
+static int __devinit snd_ali_resources(struct snd_ali *codec)
{
int err;
@@ -2206,27 +2192,24 @@ static int __devinit snd_ali_resources(ali_t *codec)
snd_ali_printk("resouces allocated.\n");
return 0;
}
-static int snd_ali_dev_free(snd_device_t *device)
+static int snd_ali_dev_free(struct snd_device *device)
{
- ali_t *codec=device->device_data;
+ struct snd_ali *codec=device->device_data;
snd_ali_free(codec);
return 0;
}
-static int __devinit snd_ali_create(snd_card_t * card,
+static int __devinit snd_ali_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int spdif_support,
- ali_t ** r_ali)
+ struct snd_ali ** r_ali)
{
- ali_t *codec;
+ struct snd_ali *codec;
int i, err;
- unsigned short cmdw = 0;
- struct pci_dev *pci_dev = NULL;
- static snd_device_ops_t ops = {
- (snd_dev_free_t *)snd_ali_dev_free,
- NULL,
- NULL
+ unsigned short cmdw;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_ali_dev_free,
};
*r_ali = NULL;
@@ -2300,16 +2283,14 @@ static int __devinit snd_ali_create(snd_card_t * card,
codec->chregs.data.ainten = 0x00;
/* M1533: southbridge */
- pci_dev = pci_get_device(0x10b9, 0x1533, NULL);
- codec->pci_m1533 = pci_dev;
+ codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
if (! codec->pci_m1533) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n");
snd_ali_free(codec);
return -ENODEV;
}
/* M7101: power management */
- pci_dev = pci_get_device(0x10b9, 0x7101, NULL);
- codec->pci_m7101 = pci_dev;
+ codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
snd_ali_free(codec);
@@ -2336,8 +2317,6 @@ static int __devinit snd_ali_create(snd_card_t * card,
codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
if (! codec->image)
snd_printk(KERN_WARNING "can't allocate apm buffer\n");
- else
- snd_card_set_pm_callback(card, ali_suspend, ali_resume, codec);
#endif
snd_ali_enable_address_interrupt(codec);
@@ -2351,8 +2330,8 @@ static int __devinit snd_ali_create(snd_card_t * card,
static int __devinit snd_ali_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- ali_t *codec;
+ struct snd_card *card;
+ struct snd_ali *codec;
int err;
snd_ali_printk("probe ...\n");
@@ -2365,6 +2344,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = codec;
snd_ali_printk("mixer building ...\n");
if ((err = snd_ali_mixer(codec)) < 0) {
@@ -2406,7 +2386,10 @@ static struct pci_driver driver = {
.id_table = snd_ali_ids,
.probe = snd_ali_probe,
.remove = __devexit_p(snd_ali_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = ali_suspend,
+ .resume = ali_resume,
+#endif
};
static int __init alsa_card_ali_init(void)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 1904df650265..7b2ff5f4672e 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -6,6 +6,21 @@
*
* Framework borrowed from Massimo Piccioni's card-als100.c.
*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
* NOTES
*
* Since Avance does not provide any meaningful documentation, and I
@@ -43,19 +58,9 @@
* Set KSound:
* - value -> some port 0x0c0d
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * ToDo:
+ * - Proper shared IRQ handling?
+ * - power management? (card can do voice wakeup according to datasheet!!)
*/
#include <sound/driver.h>
@@ -100,13 +105,15 @@ module_param_array(joystick_port, int, NULL, 0444);
MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)");
#endif
-typedef struct {
- struct pci_dev *pci;
+struct snd_card_als4000 {
+ /* most frequent access first */
unsigned long gcr;
+ struct pci_dev *pci;
+ struct snd_sb *chip;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
-} snd_card_als4000_t;
+};
static struct pci_device_id snd_als4000_ids[] = {
{ 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */
@@ -121,7 +128,7 @@ static inline void snd_als4000_gcr_write_addr(unsigned long port, u32 reg, u32 v
outl(val, port+0x08);
}
-static inline void snd_als4000_gcr_write(sb_t *sb, u32 reg, u32 val)
+static inline void snd_als4000_gcr_write(struct snd_sb *sb, u32 reg, u32 val)
{
snd_als4000_gcr_write_addr(sb->alt_port, reg, val);
}
@@ -132,12 +139,12 @@ static inline u32 snd_als4000_gcr_read_addr(unsigned long port, u32 reg)
return inl(port+0x08);
}
-static inline u32 snd_als4000_gcr_read(sb_t *sb, u32 reg)
+static inline u32 snd_als4000_gcr_read(struct snd_sb *sb, u32 reg)
{
return snd_als4000_gcr_read_addr(sb->alt_port, reg);
}
-static void snd_als4000_set_rate(sb_t *chip, unsigned int rate)
+static void snd_als4000_set_rate(struct snd_sb *chip, unsigned int rate)
{
if (!(chip->mode & SB_RATE_LOCK)) {
snd_sbdsp_command(chip, SB_DSP_SAMPLE_RATE_OUT);
@@ -146,13 +153,15 @@ static void snd_als4000_set_rate(sb_t *chip, unsigned int rate)
}
}
-static void snd_als4000_set_capture_dma(sb_t *chip, dma_addr_t addr, unsigned size)
+static inline void snd_als4000_set_capture_dma(struct snd_sb *chip,
+ dma_addr_t addr, unsigned size)
{
snd_als4000_gcr_write(chip, 0xa2, addr);
snd_als4000_gcr_write(chip, 0xa3, (size-1));
}
-static void snd_als4000_set_playback_dma(sb_t *chip, dma_addr_t addr, unsigned size)
+static inline void snd_als4000_set_playback_dma(struct snd_sb *chip,
+ dma_addr_t addr, unsigned size)
{
snd_als4000_gcr_write(chip, 0x91, addr);
snd_als4000_gcr_write(chip, 0x92, (size-1)|0x180000);
@@ -162,7 +171,7 @@ static void snd_als4000_set_playback_dma(sb_t *chip, dma_addr_t addr, unsigned s
#define ALS4000_FORMAT_16BIT (1<<1)
#define ALS4000_FORMAT_STEREO (1<<2)
-static int snd_als4000_get_format(snd_pcm_runtime_t *runtime)
+static int snd_als4000_get_format(struct snd_pcm_runtime *runtime)
{
int result;
@@ -177,7 +186,7 @@ static int snd_als4000_get_format(snd_pcm_runtime_t *runtime)
}
/* structure for setting up playback */
-static struct {
+static const struct {
unsigned char dsp_cmd, dma_on, dma_off, format;
} playback_cmd_vals[]={
/* ALS4000_FORMAT_U8_MONO */
@@ -201,7 +210,7 @@ static struct {
/* structure for setting up capture */
enum { CMD_WIDTH8=0x04, CMD_SIGNED=0x10, CMD_MONO=0x80, CMD_STEREO=0xA0 };
-static unsigned char capture_cmd_vals[]=
+static const unsigned char capture_cmd_vals[]=
{
CMD_WIDTH8|CMD_MONO, /* ALS4000_FORMAT_U8_MONO */
CMD_WIDTH8|CMD_SIGNED|CMD_MONO, /* ALS4000_FORMAT_S8_MONO */
@@ -214,23 +223,22 @@ CMD_SIGNED|CMD_STEREO, /* ALS4000_FORMAT_S16L_STEREO */
};
#define capture_cmd(chip) (capture_cmd_vals[(chip)->capture_format])
-static int snd_als4000_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_als4000_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_als4000_hw_free(snd_pcm_substream_t * substream)
+static int snd_als4000_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_als4000_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream)
{
- unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long size;
unsigned count;
@@ -243,22 +251,21 @@ static int snd_als4000_capture_prepare(snd_pcm_substream_t * substream)
count >>=1;
count--;
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
snd_als4000_set_rate(chip, runtime->rate);
snd_als4000_set_capture_dma(chip, runtime->dma_addr, size);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
- spin_lock_irqsave(&chip->mixer_lock, flags );
+ spin_unlock_irq(&chip->reg_lock);
+ spin_lock_irq(&chip->mixer_lock);
snd_sbmixer_write(chip, 0xdc, count);
snd_sbmixer_write(chip, 0xdd, count>>8);
- spin_unlock_irqrestore(&chip->mixer_lock, flags );
+ spin_unlock_irq(&chip->mixer_lock);
return 0;
}
-static int snd_als4000_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_als4000_playback_prepare(struct snd_pcm_substream *substream)
{
- unsigned long flags;
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long size;
unsigned count;
@@ -277,7 +284,7 @@ static int snd_als4000_playback_prepare(snd_pcm_substream_t *substream)
* reordering, ...). Something seems to get enabled on playback
* that I haven't found out how to disable again, which then causes
* the switching pops to reach the speakers the next time here. */
- spin_lock_irqsave(&chip->reg_lock, flags);
+ spin_lock_irq(&chip->reg_lock);
snd_als4000_set_rate(chip, runtime->rate);
snd_als4000_set_playback_dma(chip, runtime->dma_addr, size);
@@ -288,52 +295,64 @@ static int snd_als4000_playback_prepare(snd_pcm_substream_t *substream)
snd_sbdsp_command(chip, count);
snd_sbdsp_command(chip, count>>8);
snd_sbdsp_command(chip, playback_cmd(chip).dma_off);
- spin_unlock_irqrestore(&chip->reg_lock, flags);
+ spin_unlock_irq(&chip->reg_lock);
return 0;
}
-static int snd_als4000_capture_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_als4000_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
int result = 0;
spin_lock(&chip->mixer_lock);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->mode |= SB_RATE_LOCK_CAPTURE;
snd_sbmixer_write(chip, 0xde, capture_cmd(chip));
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
chip->mode &= ~SB_RATE_LOCK_CAPTURE;
snd_sbmixer_write(chip, 0xde, 0);
- } else {
+ break;
+ default:
result = -EINVAL;
+ break;
}
spin_unlock(&chip->mixer_lock);
return result;
}
-static int snd_als4000_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_als4000_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
int result = 0;
spin_lock(&chip->reg_lock);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->mode |= SB_RATE_LOCK_PLAYBACK;
snd_sbdsp_command(chip, playback_cmd(chip).dma_on);
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
snd_sbdsp_command(chip, playback_cmd(chip).dma_off);
chip->mode &= ~SB_RATE_LOCK_PLAYBACK;
- } else {
+ break;
+ default:
result = -EINVAL;
+ break;
}
spin_unlock(&chip->reg_lock);
return result;
}
-static snd_pcm_uframes_t snd_als4000_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_als4000_capture_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned int result;
spin_lock(&chip->reg_lock);
@@ -342,9 +361,9 @@ static snd_pcm_uframes_t snd_als4000_capture_pointer(snd_pcm_substream_t * subst
return bytes_to_frames( substream->runtime, result );
}
-static snd_pcm_uframes_t snd_als4000_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_als4000_playback_pointer(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
unsigned result;
spin_lock(&chip->reg_lock);
@@ -353,9 +372,21 @@ static snd_pcm_uframes_t snd_als4000_playback_pointer(snd_pcm_substream_t * subs
return bytes_to_frames( substream->runtime, result );
}
+/* FIXME: this IRQ routine doesn't really support IRQ sharing (we always
+ * return IRQ_HANDLED no matter whether we actually had an IRQ flag or not).
+ * ALS4000a.PDF writes that while ACKing IRQ in PCI block will *not* ACK
+ * the IRQ in the SB core, ACKing IRQ in SB block *will* ACK the PCI IRQ
+ * register (alt_port + 0x0e). Probably something could be optimized here to
+ * query/write one register only...
+ * And even if both registers need to be queried, then there's still the
+ * question of whether it's actually correct to ACK PCI IRQ before reading
+ * SB IRQ like we do now, since ALS4000a.PDF mentions that PCI IRQ will *clear*
+ * SB IRQ status.
+ * And do we *really* need the lock here for *reading* SB_DSP4_IRQSTATUS??
+ * */
static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- sb_t *chip = dev_id;
+ struct snd_sb *chip = dev_id;
unsigned gcr_status;
unsigned sb_status;
@@ -388,7 +419,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *
/*****************************************************************/
-static snd_pcm_hardware_t snd_als4000_playback =
+static struct snd_pcm_hardware snd_als4000_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -407,7 +438,7 @@ static snd_pcm_hardware_t snd_als4000_playback =
.fifo_size = 0
};
-static snd_pcm_hardware_t snd_als4000_capture =
+static struct snd_pcm_hardware snd_als4000_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -428,38 +459,38 @@ static snd_pcm_hardware_t snd_als4000_capture =
/*****************************************************************/
-static int snd_als4000_playback_open(snd_pcm_substream_t * substream)
+static int snd_als4000_playback_open(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
chip->playback_substream = substream;
runtime->hw = snd_als4000_playback;
return 0;
}
-static int snd_als4000_playback_close(snd_pcm_substream_t * substream)
+static int snd_als4000_playback_close(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_als4000_capture_open(snd_pcm_substream_t * substream)
+static int snd_als4000_capture_open(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
chip->capture_substream = substream;
runtime->hw = snd_als4000_capture;
return 0;
}
-static int snd_als4000_capture_close(snd_pcm_substream_t * substream)
+static int snd_als4000_capture_close(struct snd_pcm_substream *substream)
{
- sb_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_sb *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
snd_pcm_lib_free_pages(substream);
@@ -468,7 +499,7 @@ static int snd_als4000_capture_close(snd_pcm_substream_t * substream)
/******************************************************************/
-static snd_pcm_ops_t snd_als4000_playback_ops = {
+static struct snd_pcm_ops snd_als4000_playback_ops = {
.open = snd_als4000_playback_open,
.close = snd_als4000_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -479,7 +510,7 @@ static snd_pcm_ops_t snd_als4000_playback_ops = {
.pointer = snd_als4000_playback_pointer
};
-static snd_pcm_ops_t snd_als4000_capture_ops = {
+static struct snd_pcm_ops snd_als4000_capture_ops = {
.open = snd_als4000_capture_open,
.close = snd_als4000_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -490,21 +521,13 @@ static snd_pcm_ops_t snd_als4000_capture_ops = {
.pointer = snd_als4000_capture_pointer
};
-static void snd_als4000_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_als4000_pcm(struct snd_sb *chip, int device)
{
- sb_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_als4000_pcm(sb_t *chip, int device)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "ALS4000 DSP", device, 1, 1, &pcm)) < 0)
return err;
- pcm->private_free = snd_als4000_pcm_free;
pcm->private_data = chip;
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_als4000_playback_ops);
@@ -541,7 +564,7 @@ static void snd_als4000_set_addr(unsigned long gcr,
snd_als4000_gcr_write_addr(gcr, 0xa9, confB);
}
-static void __devinit snd_als4000_configure(sb_t *chip)
+static void snd_als4000_configure(struct snd_sb *chip)
{
unsigned tmp;
int i;
@@ -566,7 +589,7 @@ static void __devinit snd_als4000_configure(sb_t *chip)
}
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev)
+static int __devinit snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev)
{
struct gameport *gp;
struct resource *r;
@@ -612,7 +635,7 @@ static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int
return 0;
}
-static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
+static void snd_als4000_free_gameport(struct snd_card_als4000 *acard)
{
if (acard->gameport) {
struct resource *r = gameport_get_port_data(acard->gameport);
@@ -625,13 +648,13 @@ static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
}
}
#else
-static inline int snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev) { return -ENOSYS; }
-static inline void snd_als4000_free_gameport(snd_card_als4000_t *acard) { }
+static inline int snd_als4000_create_gameport(struct snd_card_als4000 *acard, int dev) { return -ENOSYS; }
+static inline void snd_als4000_free_gameport(struct snd_card_als4000 *acard) { }
#endif
-static void snd_card_als4000_free( snd_card_t *card )
+static void snd_card_als4000_free( struct snd_card *card )
{
- snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data;
+ struct snd_card_als4000 * acard = (struct snd_card_als4000 *)card->private_data;
/* make sure that interrupts are disabled */
snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0);
@@ -645,11 +668,11 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- snd_card_als4000_t *acard;
+ struct snd_card *card;
+ struct snd_card_als4000 *acard;
unsigned long gcr;
- sb_t *chip;
- opl3_t *opl3;
+ struct snd_sb *chip;
+ struct snd_opl3 *opl3;
unsigned short word;
int err;
@@ -683,14 +706,14 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
pci_set_master(pci);
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof( snd_card_als4000_t ) );
+ sizeof( struct snd_card_als4000 ) );
if (card == NULL) {
pci_release_regions(pci);
pci_disable_device(pci);
return -ENOMEM;
}
- acard = (snd_card_als4000_t *)card->private_data;
+ acard = (struct snd_card_als4000 *)card->private_data;
acard->pci = pci;
acard->gcr = gcr;
card->private_free = snd_card_als4000_free;
@@ -706,9 +729,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
-1,
SB_HW_ALS4000,
&chip)) < 0) {
- snd_card_free(card);
- return err;
+ goto out_err;
}
+ acard->chip = chip;
chip->pci = pci;
chip->alt_port = gcr;
@@ -724,40 +747,42 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
gcr+0x30, 1, pci->irq, 0,
&chip->rmidi)) < 0) {
- snd_card_free(card);
- printk(KERN_ERR "als4000: no MPU-401device at 0x%lx ?\n", gcr+0x30);
- return err;
+ printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30);
+ goto out_err;
}
if ((err = snd_als4000_pcm(chip, 0)) < 0) {
- snd_card_free(card);
- return err;
+ goto out_err;
}
if ((err = snd_sbmixer_new(chip)) < 0) {
- snd_card_free(card);
- return err;
+ goto out_err;
}
if (snd_opl3_create(card, gcr+0x10, gcr+0x12,
OPL3_HW_AUTO, 1, &opl3) < 0) {
- printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx ?\n",
+ printk(KERN_ERR "als4000: no OPL device at 0x%lx-0x%lx?\n",
gcr+0x10, gcr+0x12 );
} else {
if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
+ goto out_err;
}
}
snd_als4000_create_gameport(acard, dev);
if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
+ goto out_err;
}
pci_set_drvdata(pci, card);
dev++;
- return 0;
+ err = 0;
+ goto out;
+
+out_err:
+ snd_card_free(card);
+
+out:
+ return err;
}
static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
@@ -766,11 +791,59 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
+#ifdef CONFIG_PM
+static int snd_als4000_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_card_als4000 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_als4000_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_card_als4000 *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_als4000_configure(chip);
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+
+#ifdef SUPPORT_JOYSTICK
+ if (acard->gameport)
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
+#endif
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
+
static struct pci_driver driver = {
.name = "ALS4000",
.id_table = snd_als4000_ids,
.probe = snd_card_als4000_probe,
.remove = __devexit_p(snd_card_als4000_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_als4000_suspend,
+ .resume = snd_als4000_resume,
+#endif
};
static int __init alsa_card_als4000_init(void)
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 8bae10d93529..b7217adaf1d7 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -197,24 +197,18 @@ module_param(enable, bool, 0444);
#define ATI_MAX_DESCRIPTORS 256 /* max number of descriptor packets */
-/*
- */
-
-typedef struct snd_atiixp atiixp_t;
-typedef struct snd_atiixp_dma atiixp_dma_t;
-typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
-
+struct atiixp;
/*
* DMA packate descriptor
*/
-typedef struct atiixp_dma_desc {
+struct atiixp_dma_desc {
u32 addr; /* DMA buffer address */
u16 status; /* status bits */
u16 size; /* size of the packet in dwords */
u32 next; /* address of the next packet descriptor */
-} atiixp_dma_desc_t;
+};
/*
* stream enum
@@ -229,22 +223,25 @@ enum { ATI_PCMDEV_ANALOG, ATI_PCMDEV_DIGITAL, NUM_ATI_PCMDEVS }; /* pcm devices
/*
* constants and callbacks for each DMA type
*/
-struct snd_atiixp_dma_ops {
+struct atiixp_dma_ops {
int type; /* ATI_DMA_XXX */
unsigned int llp_offset; /* LINKPTR offset */
unsigned int dt_cur; /* DT_CUR offset */
- void (*enable_dma)(atiixp_t *chip, int on); /* called from open callback */
- void (*enable_transfer)(atiixp_t *chip, int on); /* called from trigger (START/STOP) */
- void (*flush_dma)(atiixp_t *chip); /* called from trigger (STOP only) */
+ /* called from open callback */
+ void (*enable_dma)(struct atiixp *chip, int on);
+ /* called from trigger (START/STOP) */
+ void (*enable_transfer)(struct atiixp *chip, int on);
+ /* called from trigger (STOP only) */
+ void (*flush_dma)(struct atiixp *chip);
};
/*
* DMA stream
*/
-struct snd_atiixp_dma {
- const atiixp_dma_ops_t *ops;
+struct atiixp_dma {
+ const struct atiixp_dma_ops *ops;
struct snd_dma_buffer desc_buf;
- snd_pcm_substream_t *substream; /* assigned PCM substream */
+ struct snd_pcm_substream *substream; /* assigned PCM substream */
unsigned int buf_addr, buf_bytes; /* DMA buffer address, bytes */
unsigned int period_bytes, periods;
int opened;
@@ -258,22 +255,22 @@ struct snd_atiixp_dma {
/*
* ATI IXP chip
*/
-struct snd_atiixp {
- snd_card_t *card;
+struct atiixp {
+ struct snd_card *card;
struct pci_dev *pci;
unsigned long addr;
void __iomem *remap_addr;
int irq;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97[NUM_ATI_CODECS];
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97[NUM_ATI_CODECS];
spinlock_t reg_lock;
- atiixp_dma_t dmas[NUM_ATI_DMAS];
+ struct atiixp_dma dmas[NUM_ATI_DMAS];
struct ac97_pcm *pcms[NUM_ATI_PCMS];
- snd_pcm_t *pcmdevs[NUM_ATI_PCMDEVS];
+ struct snd_pcm *pcmdevs[NUM_ATI_PCMDEVS];
int max_channels; /* max. channels for PCM out */
@@ -304,7 +301,7 @@ MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
* update the bits of the given register.
* return 1 if the bits changed.
*/
-static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
+static int snd_atiixp_update_bits(struct atiixp *chip, unsigned int reg,
unsigned int mask, unsigned int value)
{
void __iomem *addr = chip->remap_addr + reg;
@@ -328,12 +325,6 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
#define atiixp_update(chip,reg,mask,val) \
snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val)
-/* delay for one tick */
-#define do_delay() do { \
- schedule_timeout_uninterruptible(1); \
-} while (0)
-
-
/*
* handling DMA packets
*
@@ -342,7 +333,7 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
*/
#define ATI_DESC_LIST_SIZE \
- PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(atiixp_dma_desc_t))
+ PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(struct atiixp_dma_desc))
/*
* build packets ring for the given buffer size.
@@ -353,10 +344,10 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
*
* the ring is built in this function, and is set up to the hardware.
*/
-static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
- snd_pcm_substream_t *substream,
- unsigned int periods,
- unsigned int period_bytes)
+static int atiixp_build_dma_packets(struct atiixp *chip, struct atiixp_dma *dma,
+ struct snd_pcm_substream *substream,
+ unsigned int periods,
+ unsigned int period_bytes)
{
unsigned int i;
u32 addr, desc_addr;
@@ -366,8 +357,10 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
return -ENOMEM;
if (dma->desc_buf.area == NULL) {
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
+ ATI_DESC_LIST_SIZE,
+ &dma->desc_buf) < 0)
return -ENOMEM;
dma->period_bytes = dma->periods = 0; /* clear */
}
@@ -386,11 +379,12 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
addr = (u32)substream->runtime->dma_addr;
desc_addr = (u32)dma->desc_buf.addr;
for (i = 0; i < periods; i++) {
- atiixp_dma_desc_t *desc = &((atiixp_dma_desc_t *)dma->desc_buf.area)[i];
+ struct atiixp_dma_desc *desc;
+ desc = &((struct atiixp_dma_desc *)dma->desc_buf.area)[i];
desc->addr = cpu_to_le32(addr);
desc->status = 0;
desc->size = period_bytes >> 2; /* in dwords */
- desc_addr += sizeof(atiixp_dma_desc_t);
+ desc_addr += sizeof(struct atiixp_dma_desc);
if (i == periods - 1)
desc->next = cpu_to_le32((u32)dma->desc_buf.addr);
else
@@ -410,7 +404,8 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
/*
* remove the ring buffer and release it if assigned
*/
-static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_substream_t *substream)
+static void atiixp_clear_dma_packets(struct atiixp *chip, struct atiixp_dma *dma,
+ struct snd_pcm_substream *substream)
{
if (dma->desc_buf.area) {
writel(0, chip->remap_addr + dma->ops->llp_offset);
@@ -422,7 +417,7 @@ static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_
/*
* AC97 interface
*/
-static int snd_atiixp_acquire_codec(atiixp_t *chip)
+static int snd_atiixp_acquire_codec(struct atiixp *chip)
{
int timeout = 1000;
@@ -436,7 +431,7 @@ static int snd_atiixp_acquire_codec(atiixp_t *chip)
return 0;
}
-static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec, unsigned short reg)
+static unsigned short snd_atiixp_codec_read(struct atiixp *chip, unsigned short codec, unsigned short reg)
{
unsigned int data;
int timeout;
@@ -464,7 +459,8 @@ static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec
}
-static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigned short reg, unsigned short val)
+static void snd_atiixp_codec_write(struct atiixp *chip, unsigned short codec,
+ unsigned short reg, unsigned short val)
{
unsigned int data;
@@ -477,23 +473,25 @@ static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigne
}
-static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_atiixp_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
{
- atiixp_t *chip = ac97->private_data;
+ struct atiixp *chip = ac97->private_data;
return snd_atiixp_codec_read(chip, ac97->num, reg);
}
-static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void snd_atiixp_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
{
- atiixp_t *chip = ac97->private_data;
+ struct atiixp *chip = ac97->private_data;
snd_atiixp_codec_write(chip, ac97->num, reg, val);
}
/*
* reset AC link
*/
-static int snd_atiixp_aclink_reset(atiixp_t *chip)
+static int snd_atiixp_aclink_reset(struct atiixp *chip)
{
int timeout;
@@ -513,7 +511,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip)
atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
ATI_REG_CMD_AC_SYNC);
atiixp_read(chip, CMD);
- do_delay();
+ mdelay(1);
atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
if (--timeout) {
snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
@@ -529,7 +527,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip)
}
#ifdef CONFIG_PM
-static int snd_atiixp_aclink_down(atiixp_t *chip)
+static int snd_atiixp_aclink_down(struct atiixp *chip)
{
// if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */
// return -EBUSY;
@@ -554,16 +552,16 @@ static int snd_atiixp_aclink_down(atiixp_t *chip)
ATI_REG_ISR_CODEC2_NOT_READY)
#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
-static int snd_atiixp_codec_detect(atiixp_t *chip)
+static int snd_atiixp_codec_detect(struct atiixp *chip)
{
int timeout;
chip->codec_not_ready_bits = 0;
atiixp_write(chip, IER, CODEC_CHECK_BITS);
/* wait for the interrupts */
- timeout = HZ / 10;
+ timeout = 50;
while (timeout-- > 0) {
- do_delay();
+ mdelay(1);
if (chip->codec_not_ready_bits)
break;
}
@@ -580,7 +578,7 @@ static int snd_atiixp_codec_detect(atiixp_t *chip)
/*
* enable DMA and irqs
*/
-static int snd_atiixp_chip_start(atiixp_t *chip)
+static int snd_atiixp_chip_start(struct atiixp *chip)
{
unsigned int reg;
@@ -610,7 +608,7 @@ static int snd_atiixp_chip_start(atiixp_t *chip)
/*
* disable DMA and IRQs
*/
-static int snd_atiixp_chip_stop(atiixp_t *chip)
+static int snd_atiixp_chip_stop(struct atiixp *chip)
{
/* clear interrupt source */
atiixp_write(chip, ISR, atiixp_read(chip, ISR));
@@ -629,11 +627,11 @@ static int snd_atiixp_chip_stop(atiixp_t *chip)
* position. when SG-buffer is implemented, the offset must be calculated
* correctly...
*/
-static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atiixp_dma *dma = runtime->private_data;
unsigned int curptr;
int timeout = 1000;
@@ -654,7 +652,7 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
/*
* XRUN detected, and stop the PCM substream
*/
-static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
+static void snd_atiixp_xrun_dma(struct atiixp *chip, struct atiixp_dma *dma)
{
if (! dma->substream || ! dma->running)
return;
@@ -665,7 +663,7 @@ static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
/*
* the period ack. update the substream.
*/
-static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
+static void snd_atiixp_update_dma(struct atiixp *chip, struct atiixp_dma *dma)
{
if (! dma->substream || ! dma->running)
return;
@@ -674,7 +672,7 @@ static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
/* set BUS_BUSY interrupt bit if any DMA is running */
/* call with spinlock held */
-static void snd_atiixp_check_bus_busy(atiixp_t *chip)
+static void snd_atiixp_check_bus_busy(struct atiixp *chip)
{
unsigned int bus_busy;
if (atiixp_read(chip, CMD) & (ATI_REG_CMD_SEND_EN |
@@ -689,10 +687,10 @@ static void snd_atiixp_check_bus_busy(atiixp_t *chip)
/* common trigger callback
* calling the lowlevel callbacks in it
*/
-static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
int err = 0;
snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
@@ -736,13 +734,13 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
*/
/* flush FIFO of analog OUT DMA */
-static void atiixp_out_flush_dma(atiixp_t *chip)
+static void atiixp_out_flush_dma(struct atiixp *chip)
{
atiixp_write(chip, FIFO_FLUSH, ATI_REG_FIFO_OUT_FLUSH);
}
/* enable/disable analog OUT DMA */
-static void atiixp_out_enable_dma(atiixp_t *chip, int on)
+static void atiixp_out_enable_dma(struct atiixp *chip, int on)
{
unsigned int data;
data = atiixp_read(chip, CMD);
@@ -757,21 +755,21 @@ static void atiixp_out_enable_dma(atiixp_t *chip, int on)
}
/* start/stop transfer over OUT DMA */
-static void atiixp_out_enable_transfer(atiixp_t *chip, int on)
+static void atiixp_out_enable_transfer(struct atiixp *chip, int on)
{
atiixp_update(chip, CMD, ATI_REG_CMD_SEND_EN,
on ? ATI_REG_CMD_SEND_EN : 0);
}
/* enable/disable analog IN DMA */
-static void atiixp_in_enable_dma(atiixp_t *chip, int on)
+static void atiixp_in_enable_dma(struct atiixp *chip, int on)
{
atiixp_update(chip, CMD, ATI_REG_CMD_IN_DMA_EN,
on ? ATI_REG_CMD_IN_DMA_EN : 0);
}
/* start/stop analog IN DMA */
-static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
+static void atiixp_in_enable_transfer(struct atiixp *chip, int on)
{
if (on) {
unsigned int data = atiixp_read(chip, CMD);
@@ -790,20 +788,20 @@ static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
}
/* flush FIFO of analog IN DMA */
-static void atiixp_in_flush_dma(atiixp_t *chip)
+static void atiixp_in_flush_dma(struct atiixp *chip)
{
atiixp_write(chip, FIFO_FLUSH, ATI_REG_FIFO_IN_FLUSH);
}
/* enable/disable SPDIF OUT DMA */
-static void atiixp_spdif_enable_dma(atiixp_t *chip, int on)
+static void atiixp_spdif_enable_dma(struct atiixp *chip, int on)
{
atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_DMA_EN,
on ? ATI_REG_CMD_SPDF_DMA_EN : 0);
}
/* start/stop SPDIF OUT DMA */
-static void atiixp_spdif_enable_transfer(atiixp_t *chip, int on)
+static void atiixp_spdif_enable_transfer(struct atiixp *chip, int on)
{
unsigned int data;
data = atiixp_read(chip, CMD);
@@ -815,7 +813,7 @@ static void atiixp_spdif_enable_transfer(atiixp_t *chip, int on)
}
/* flush FIFO of SPDIF OUT DMA */
-static void atiixp_spdif_flush_dma(atiixp_t *chip)
+static void atiixp_spdif_flush_dma(struct atiixp *chip)
{
int timeout;
@@ -834,9 +832,9 @@ static void atiixp_spdif_flush_dma(atiixp_t *chip)
}
/* set up slots and formats for SPDIF OUT */
-static int snd_atiixp_spdif_prepare(snd_pcm_substream_t *substream)
+static int snd_atiixp_spdif_prepare(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
if (chip->spdif_over_aclink) {
@@ -861,9 +859,9 @@ static int snd_atiixp_spdif_prepare(snd_pcm_substream_t *substream)
}
/* set up slots and formats for analog OUT */
-static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
unsigned int data;
spin_lock_irq(&chip->reg_lock);
@@ -906,9 +904,9 @@ static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
}
/* set up slots and formats for analog IN */
-static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_prepare(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_IN,
@@ -921,11 +919,11 @@ static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
/*
* hw_params - allocate the buffer and set up buffer descriptors
*/
-static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
int err;
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
@@ -959,10 +957,10 @@ static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
return err;
}
-static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
if (dma->pcm_open_flag) {
struct ac97_pcm *pcm = chip->pcms[dma->ac97_pcm_type];
@@ -978,7 +976,7 @@ static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
/*
* pcm hardware definition, identical for all DMA types
*/
-static snd_pcm_hardware_t snd_atiixp_pcm_hw =
+static struct snd_pcm_hardware snd_atiixp_pcm_hw =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -998,10 +996,11 @@ static snd_pcm_hardware_t snd_atiixp_pcm_hw =
.periods_max = ATI_MAX_DESCRIPTORS,
};
-static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma, int pcm_type)
+static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream,
+ struct atiixp_dma *dma, int pcm_type)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
@@ -1031,9 +1030,10 @@ static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma
return 0;
}
-static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dma)
+static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream,
+ struct atiixp_dma *dma)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
/* disable DMA bits */
snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
spin_lock_irq(&chip->reg_lock);
@@ -1046,9 +1046,9 @@ static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dm
/*
*/
-static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_open(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
@@ -1064,9 +1064,9 @@ static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_close(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]);
@@ -1074,21 +1074,21 @@ static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
return err;
}
-static int snd_atiixp_capture_open(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_open(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1);
}
-static int snd_atiixp_capture_close(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_close(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]);
}
-static int snd_atiixp_spdif_open(snd_pcm_substream_t *substream)
+static int snd_atiixp_spdif_open(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
if (chip->spdif_over_aclink) /* share DMA_PLAYBACK */
@@ -1099,9 +1099,9 @@ static int snd_atiixp_spdif_open(snd_pcm_substream_t *substream)
return err;
}
-static int snd_atiixp_spdif_close(snd_pcm_substream_t *substream)
+static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
if (chip->spdif_over_aclink)
@@ -1113,7 +1113,7 @@ static int snd_atiixp_spdif_close(snd_pcm_substream_t *substream)
}
/* AC97 playback */
-static snd_pcm_ops_t snd_atiixp_playback_ops = {
+static struct snd_pcm_ops snd_atiixp_playback_ops = {
.open = snd_atiixp_playback_open,
.close = snd_atiixp_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1125,7 +1125,7 @@ static snd_pcm_ops_t snd_atiixp_playback_ops = {
};
/* AC97 capture */
-static snd_pcm_ops_t snd_atiixp_capture_ops = {
+static struct snd_pcm_ops snd_atiixp_capture_ops = {
.open = snd_atiixp_capture_open,
.close = snd_atiixp_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1137,7 +1137,7 @@ static snd_pcm_ops_t snd_atiixp_capture_ops = {
};
/* SPDIF playback */
-static snd_pcm_ops_t snd_atiixp_spdif_ops = {
+static struct snd_pcm_ops snd_atiixp_spdif_ops = {
.open = snd_atiixp_spdif_open,
.close = snd_atiixp_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1184,7 +1184,7 @@ static struct ac97_pcm atiixp_pcm_defs[] __devinitdata = {
},
};
-static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
+static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.type = ATI_DMA_PLAYBACK,
.llp_offset = ATI_REG_OUT_DMA_LINKPTR,
.dt_cur = ATI_REG_OUT_DMA_DT_CUR,
@@ -1193,7 +1193,7 @@ static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
.flush_dma = atiixp_out_flush_dma,
};
-static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
+static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.type = ATI_DMA_CAPTURE,
.llp_offset = ATI_REG_IN_DMA_LINKPTR,
.dt_cur = ATI_REG_IN_DMA_DT_CUR,
@@ -1202,7 +1202,7 @@ static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
.flush_dma = atiixp_in_flush_dma,
};
-static atiixp_dma_ops_t snd_atiixp_spdif_dma_ops = {
+static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = {
.type = ATI_DMA_SPDIF,
.llp_offset = ATI_REG_SPDF_DMA_LINKPTR,
.dt_cur = ATI_REG_SPDF_DMA_DT_CUR,
@@ -1212,10 +1212,10 @@ static atiixp_dma_ops_t snd_atiixp_spdif_dma_ops = {
};
-static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
+static int __devinit snd_atiixp_pcm_new(struct atiixp *chip)
{
- snd_pcm_t *pcm;
- ac97_bus_t *pbus = chip->ac97_bus;
+ struct snd_pcm *pcm;
+ struct snd_ac97_bus *pbus = chip->ac97_bus;
int err, i, num_pcms;
/* initialize constants */
@@ -1244,7 +1244,8 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
}
/* PCM #0: analog I/O */
- err = snd_pcm_new(chip->card, "ATI IXP AC97", ATI_PCMDEV_ANALOG, 1, 1, &pcm);
+ err = snd_pcm_new(chip->card, "ATI IXP AC97",
+ ATI_PCMDEV_ANALOG, 1, 1, &pcm);
if (err < 0)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_playback_ops);
@@ -1254,7 +1255,8 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024);
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024);
/* no SPDIF support on codec? */
if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates)
@@ -1265,7 +1267,8 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
chip->pcms[ATI_PCM_SPDIF]->rates = SNDRV_PCM_RATE_48000;
/* PCM #1: spdif playback */
- err = snd_pcm_new(chip->card, "ATI IXP IEC958", ATI_PCMDEV_DIGITAL, 1, 0, &pcm);
+ err = snd_pcm_new(chip->card, "ATI IXP IEC958",
+ ATI_PCMDEV_DIGITAL, 1, 0, &pcm);
if (err < 0)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_atiixp_spdif_ops);
@@ -1277,12 +1280,15 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
chip->pcmdevs[ATI_PCMDEV_DIGITAL] = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024);
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024);
/* pre-select AC97 SPDIF slots 10/11 */
for (i = 0; i < NUM_ATI_CODECS; i++) {
if (chip->ac97[i])
- snd_ac97_update_bits(chip->ac97[i], AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4);
+ snd_ac97_update_bits(chip->ac97[i],
+ AC97_EXTENDED_STATUS,
+ 0x03 << 4, 0x03 << 4);
}
return 0;
@@ -1295,7 +1301,7 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
*/
static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- atiixp_t *chip = dev_id;
+ struct atiixp *chip = dev_id;
unsigned int status;
status = atiixp_read(chip, ISR);
@@ -1347,16 +1353,23 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.name = "HP Pavilion ZV5030US",
.type = AC97_TUNE_MUTE_LED
},
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x308b,
+ .name = "HP nx6125",
+ .type = AC97_TUNE_MUTE_LED
+ },
{ } /* terminator */
};
-static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char *quirk_override)
+static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
+ const char *quirk_override)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int i, err;
int codec_count;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_atiixp_ac97_write,
.read = snd_atiixp_ac97_read,
};
@@ -1408,90 +1421,100 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock, const char
/*
* power management
*/
-static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
+static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state)
{
- atiixp_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct atiixp *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
if (chip->pcmdevs[i]) {
- atiixp_dma_t *dma = &chip->dmas[i];
+ struct atiixp_dma *dma = &chip->dmas[i];
if (dma->substream && dma->running)
- dma->saved_curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+ dma->saved_curptr = readl(chip->remap_addr +
+ dma->ops->dt_cur);
snd_pcm_suspend_all(chip->pcmdevs[i]);
}
for (i = 0; i < NUM_ATI_CODECS; i++)
- if (chip->ac97[i])
- snd_ac97_suspend(chip->ac97[i]);
+ snd_ac97_suspend(chip->ac97[i]);
snd_atiixp_aclink_down(chip);
snd_atiixp_chip_stop(chip);
- pci_set_power_state(chip->pci, PCI_D3hot);
- pci_disable_device(chip->pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_atiixp_resume(snd_card_t *card)
+static int snd_atiixp_resume(struct pci_dev *pci)
{
- atiixp_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct atiixp *chip = card->private_data;
int i;
- pci_enable_device(chip->pci);
- pci_set_power_state(chip->pci, PCI_D0);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
snd_atiixp_aclink_reset(chip);
snd_atiixp_chip_start(chip);
for (i = 0; i < NUM_ATI_CODECS; i++)
- if (chip->ac97[i])
- snd_ac97_resume(chip->ac97[i]);
+ snd_ac97_resume(chip->ac97[i]);
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
if (chip->pcmdevs[i]) {
- atiixp_dma_t *dma = &chip->dmas[i];
+ struct atiixp_dma *dma = &chip->dmas[i];
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);
+ writel(dma->saved_curptr, chip->remap_addr +
+ dma->ops->dt_cur);
}
}
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
+#ifdef CONFIG_PROC_FS
/*
* proc interface for register dump
*/
-static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_atiixp_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- atiixp_t *chip = entry->private_data;
+ struct atiixp *chip = entry->private_data;
int i;
for (i = 0; i < 256; i += 4)
snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
}
-static void __devinit snd_atiixp_proc_init(atiixp_t *chip)
+static void __devinit snd_atiixp_proc_init(struct atiixp *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "atiixp", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
}
-
+#else /* !CONFIG_PROC_FS */
+#define snd_atiixp_proc_init(chip)
+#endif
/*
* destructor
*/
-static int snd_atiixp_free(atiixp_t *chip)
+static int snd_atiixp_free(struct atiixp *chip)
{
if (chip->irq < 0)
goto __hw_end;
@@ -1499,7 +1522,7 @@ static int snd_atiixp_free(atiixp_t *chip)
synchronize_irq(chip->irq);
__hw_end:
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->remap_addr)
iounmap(chip->remap_addr);
pci_release_regions(chip->pci);
@@ -1508,23 +1531,23 @@ static int snd_atiixp_free(atiixp_t *chip)
return 0;
}
-static int snd_atiixp_dev_free(snd_device_t *device)
+static int snd_atiixp_dev_free(struct snd_device *device)
{
- atiixp_t *chip = device->device_data;
+ struct atiixp *chip = device->device_data;
return snd_atiixp_free(chip);
}
/*
* constructor for chip instance
*/
-static int __devinit snd_atiixp_create(snd_card_t *card,
+static int __devinit snd_atiixp_create(struct snd_card *card,
struct pci_dev *pci,
- atiixp_t **r_chip)
+ struct atiixp **r_chip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_atiixp_dev_free,
};
- atiixp_t *chip;
+ struct atiixp *chip;
int err;
if ((err = pci_enable_device(pci)) < 0)
@@ -1554,7 +1577,8 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
return -EIO;
}
- if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+ if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_atiixp_free(chip);
return -EBUSY;
@@ -1578,8 +1602,8 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
static int __devinit snd_atiixp_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- atiixp_t *chip;
+ struct snd_card *card;
+ struct atiixp *chip;
unsigned char revision;
int err;
@@ -1593,6 +1617,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
strcpy(card->shortname, "ATI IXP");
if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
goto __error;
+ card->private_data = chip;
if ((err = snd_atiixp_aclink_reset(chip)) < 0)
goto __error;
@@ -1614,8 +1639,6 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?",
chip->addr, chip->irq);
- snd_card_set_pm_callback(card, snd_atiixp_suspend, snd_atiixp_resume, chip);
-
if ((err = snd_card_register(card)) < 0)
goto __error;
@@ -1638,7 +1661,10 @@ static struct pci_driver driver = {
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_atiixp_suspend,
+ .resume = snd_atiixp_resume,
+#endif
};
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 3174b6625419..8d8fd5a4ed35 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -176,24 +176,18 @@ module_param(enable, bool, 0444);
#define ATI_MAX_DESCRIPTORS 256 /* max number of descriptor packets */
-/*
- */
-
-typedef struct snd_atiixp atiixp_t;
-typedef struct snd_atiixp_dma atiixp_dma_t;
-typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
-
+struct atiixp_modem;
/*
* DMA packate descriptor
*/
-typedef struct atiixp_dma_desc {
+struct atiixp_dma_desc {
u32 addr; /* DMA buffer address */
u16 status; /* status bits */
u16 size; /* size of the packet in dwords */
u32 next; /* address of the next packet descriptor */
-} atiixp_dma_desc_t;
+};
/*
* stream enum
@@ -208,22 +202,25 @@ enum { ATI_PCMDEV_ANALOG, NUM_ATI_PCMDEVS }; /* pcm devices */
/*
* constants and callbacks for each DMA type
*/
-struct snd_atiixp_dma_ops {
+struct atiixp_dma_ops {
int type; /* ATI_DMA_XXX */
unsigned int llp_offset; /* LINKPTR offset */
unsigned int dt_cur; /* DT_CUR offset */
- void (*enable_dma)(atiixp_t *chip, int on); /* called from open callback */
- void (*enable_transfer)(atiixp_t *chip, int on); /* called from trigger (START/STOP) */
- void (*flush_dma)(atiixp_t *chip); /* called from trigger (STOP only) */
+ /* called from open callback */
+ void (*enable_dma)(struct atiixp_modem *chip, int on);
+ /* called from trigger (START/STOP) */
+ void (*enable_transfer)(struct atiixp_modem *chip, int on);
+ /* called from trigger (STOP only) */
+ void (*flush_dma)(struct atiixp_modem *chip);
};
/*
* DMA stream
*/
-struct snd_atiixp_dma {
- const atiixp_dma_ops_t *ops;
+struct atiixp_dma {
+ const struct atiixp_dma_ops *ops;
struct snd_dma_buffer desc_buf;
- snd_pcm_substream_t *substream; /* assigned PCM substream */
+ struct snd_pcm_substream *substream; /* assigned PCM substream */
unsigned int buf_addr, buf_bytes; /* DMA buffer address, bytes */
unsigned int period_bytes, periods;
int opened;
@@ -235,8 +232,8 @@ struct snd_atiixp_dma {
/*
* ATI IXP chip
*/
-struct snd_atiixp {
- snd_card_t *card;
+struct atiixp_modem {
+ struct snd_card *card;
struct pci_dev *pci;
struct resource *res; /* memory i/o */
@@ -244,14 +241,14 @@ struct snd_atiixp {
void __iomem *remap_addr;
int irq;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97[NUM_ATI_CODECS];
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97[NUM_ATI_CODECS];
spinlock_t reg_lock;
- atiixp_dma_t dmas[NUM_ATI_DMAS];
+ struct atiixp_dma dmas[NUM_ATI_DMAS];
struct ac97_pcm *pcms[NUM_ATI_PCMS];
- snd_pcm_t *pcmdevs[NUM_ATI_PCMDEVS];
+ struct snd_pcm *pcmdevs[NUM_ATI_PCMDEVS];
int max_channels; /* max. channels for PCM out */
@@ -281,8 +278,8 @@ MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
* update the bits of the given register.
* return 1 if the bits changed.
*/
-static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
- unsigned int mask, unsigned int value)
+static int snd_atiixp_update_bits(struct atiixp_modem *chip, unsigned int reg,
+ unsigned int mask, unsigned int value)
{
void __iomem *addr = chip->remap_addr + reg;
unsigned int data, old_data;
@@ -305,12 +302,6 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
#define atiixp_update(chip,reg,mask,val) \
snd_atiixp_update_bits(chip, ATI_REG_##reg, mask, val)
-/* delay for one tick */
-#define do_delay() do { \
- schedule_timeout_uninterruptible(1); \
-} while (0)
-
-
/*
* handling DMA packets
*
@@ -319,7 +310,7 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
*/
#define ATI_DESC_LIST_SIZE \
- PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(atiixp_dma_desc_t))
+ PAGE_ALIGN(ATI_MAX_DESCRIPTORS * sizeof(struct atiixp_dma_desc))
/*
* build packets ring for the given buffer size.
@@ -330,10 +321,11 @@ static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
*
* the ring is built in this function, and is set up to the hardware.
*/
-static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
- snd_pcm_substream_t *substream,
- unsigned int periods,
- unsigned int period_bytes)
+static int atiixp_build_dma_packets(struct atiixp_modem *chip,
+ struct atiixp_dma *dma,
+ struct snd_pcm_substream *substream,
+ unsigned int periods,
+ unsigned int period_bytes)
{
unsigned int i;
u32 addr, desc_addr;
@@ -363,11 +355,12 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
addr = (u32)substream->runtime->dma_addr;
desc_addr = (u32)dma->desc_buf.addr;
for (i = 0; i < periods; i++) {
- atiixp_dma_desc_t *desc = &((atiixp_dma_desc_t *)dma->desc_buf.area)[i];
+ struct atiixp_dma_desc *desc;
+ desc = &((struct atiixp_dma_desc *)dma->desc_buf.area)[i];
desc->addr = cpu_to_le32(addr);
desc->status = 0;
desc->size = period_bytes >> 2; /* in dwords */
- desc_addr += sizeof(atiixp_dma_desc_t);
+ desc_addr += sizeof(struct atiixp_dma_desc);
if (i == periods - 1)
desc->next = cpu_to_le32((u32)dma->desc_buf.addr);
else
@@ -387,7 +380,9 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
/*
* remove the ring buffer and release it if assigned
*/
-static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_substream_t *substream)
+static void atiixp_clear_dma_packets(struct atiixp_modem *chip,
+ struct atiixp_dma *dma,
+ struct snd_pcm_substream *substream)
{
if (dma->desc_buf.area) {
writel(0, chip->remap_addr + dma->ops->llp_offset);
@@ -399,7 +394,7 @@ static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_
/*
* AC97 interface
*/
-static int snd_atiixp_acquire_codec(atiixp_t *chip)
+static int snd_atiixp_acquire_codec(struct atiixp_modem *chip)
{
int timeout = 1000;
@@ -413,7 +408,9 @@ static int snd_atiixp_acquire_codec(atiixp_t *chip)
return 0;
}
-static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec, unsigned short reg)
+static unsigned short snd_atiixp_codec_read(struct atiixp_modem *chip,
+ unsigned short codec,
+ unsigned short reg)
{
unsigned int data;
int timeout;
@@ -441,7 +438,9 @@ static unsigned short snd_atiixp_codec_read(atiixp_t *chip, unsigned short codec
}
-static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigned short reg, unsigned short val)
+static void snd_atiixp_codec_write(struct atiixp_modem *chip,
+ unsigned short codec,
+ unsigned short reg, unsigned short val)
{
unsigned int data;
@@ -454,16 +453,18 @@ static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigne
}
-static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_atiixp_ac97_read(struct snd_ac97 *ac97,
+ unsigned short reg)
{
- atiixp_t *chip = ac97->private_data;
+ struct atiixp_modem *chip = ac97->private_data;
return snd_atiixp_codec_read(chip, ac97->num, reg);
}
-static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void snd_atiixp_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
{
- atiixp_t *chip = ac97->private_data;
+ struct atiixp_modem *chip = ac97->private_data;
if (reg == AC97_GPIO_STATUS) {
atiixp_write(chip, MODEM_OUT_GPIO,
(val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN);
@@ -475,7 +476,7 @@ static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned sho
/*
* reset AC link
*/
-static int snd_atiixp_aclink_reset(atiixp_t *chip)
+static int snd_atiixp_aclink_reset(struct atiixp_modem *chip)
{
int timeout;
@@ -495,7 +496,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip)
atiixp_update(chip, CMD, ATI_REG_CMD_AC_SYNC|ATI_REG_CMD_AC_RESET,
ATI_REG_CMD_AC_SYNC);
atiixp_read(chip, CMD);
- do_delay();
+ msleep(1);
atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
if (--timeout) {
snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n");
@@ -511,7 +512,7 @@ static int snd_atiixp_aclink_reset(atiixp_t *chip)
}
#ifdef CONFIG_PM
-static int snd_atiixp_aclink_down(atiixp_t *chip)
+static int snd_atiixp_aclink_down(struct atiixp_modem *chip)
{
// if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */
// return -EBUSY;
@@ -536,16 +537,16 @@ static int snd_atiixp_aclink_down(atiixp_t *chip)
ATI_REG_ISR_CODEC2_NOT_READY)
#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
-static int snd_atiixp_codec_detect(atiixp_t *chip)
+static int snd_atiixp_codec_detect(struct atiixp_modem *chip)
{
int timeout;
chip->codec_not_ready_bits = 0;
atiixp_write(chip, IER, CODEC_CHECK_BITS);
/* wait for the interrupts */
- timeout = HZ / 10;
+ timeout = 50;
while (timeout-- > 0) {
- do_delay();
+ msleep(1);
if (chip->codec_not_ready_bits)
break;
}
@@ -562,7 +563,7 @@ static int snd_atiixp_codec_detect(atiixp_t *chip)
/*
* enable DMA and irqs
*/
-static int snd_atiixp_chip_start(atiixp_t *chip)
+static int snd_atiixp_chip_start(struct atiixp_modem *chip)
{
unsigned int reg;
@@ -587,7 +588,7 @@ static int snd_atiixp_chip_start(atiixp_t *chip)
/*
* disable DMA and IRQs
*/
-static int snd_atiixp_chip_stop(atiixp_t *chip)
+static int snd_atiixp_chip_stop(struct atiixp_modem *chip)
{
/* clear interrupt source */
atiixp_write(chip, ISR, atiixp_read(chip, ISR));
@@ -606,11 +607,11 @@ static int snd_atiixp_chip_stop(atiixp_t *chip)
* position. when SG-buffer is implemented, the offset must be calculated
* correctly...
*/
-static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_atiixp_pcm_pointer(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct atiixp_dma *dma = runtime->private_data;
unsigned int curptr;
int timeout = 1000;
@@ -631,7 +632,8 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
/*
* XRUN detected, and stop the PCM substream
*/
-static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
+static void snd_atiixp_xrun_dma(struct atiixp_modem *chip,
+ struct atiixp_dma *dma)
{
if (! dma->substream || ! dma->running)
return;
@@ -642,7 +644,8 @@ static void snd_atiixp_xrun_dma(atiixp_t *chip, atiixp_dma_t *dma)
/*
* the period ack. update the substream.
*/
-static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
+static void snd_atiixp_update_dma(struct atiixp_modem *chip,
+ struct atiixp_dma *dma)
{
if (! dma->substream || ! dma->running)
return;
@@ -651,7 +654,7 @@ static void snd_atiixp_update_dma(atiixp_t *chip, atiixp_dma_t *dma)
/* set BUS_BUSY interrupt bit if any DMA is running */
/* call with spinlock held */
-static void snd_atiixp_check_bus_busy(atiixp_t *chip)
+static void snd_atiixp_check_bus_busy(struct atiixp_modem *chip)
{
unsigned int bus_busy;
if (atiixp_read(chip, CMD) & (ATI_REG_CMD_MODEM_SEND1_EN |
@@ -665,10 +668,10 @@ static void snd_atiixp_check_bus_busy(atiixp_t *chip)
/* common trigger callback
* calling the lowlevel callbacks in it
*/
-static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_atiixp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
int err = 0;
snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
@@ -706,13 +709,13 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
*/
/* flush FIFO of analog OUT DMA */
-static void atiixp_out_flush_dma(atiixp_t *chip)
+static void atiixp_out_flush_dma(struct atiixp_modem *chip)
{
atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_OUT1_FLUSH);
}
/* enable/disable analog OUT DMA */
-static void atiixp_out_enable_dma(atiixp_t *chip, int on)
+static void atiixp_out_enable_dma(struct atiixp_modem *chip, int on)
{
unsigned int data;
data = atiixp_read(chip, CMD);
@@ -727,21 +730,21 @@ static void atiixp_out_enable_dma(atiixp_t *chip, int on)
}
/* start/stop transfer over OUT DMA */
-static void atiixp_out_enable_transfer(atiixp_t *chip, int on)
+static void atiixp_out_enable_transfer(struct atiixp_modem *chip, int on)
{
atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_SEND1_EN,
on ? ATI_REG_CMD_MODEM_SEND1_EN : 0);
}
/* enable/disable analog IN DMA */
-static void atiixp_in_enable_dma(atiixp_t *chip, int on)
+static void atiixp_in_enable_dma(struct atiixp_modem *chip, int on)
{
atiixp_update(chip, CMD, ATI_REG_CMD_MODEM_IN_DMA_EN,
on ? ATI_REG_CMD_MODEM_IN_DMA_EN : 0);
}
/* start/stop analog IN DMA */
-static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
+static void atiixp_in_enable_transfer(struct atiixp_modem *chip, int on)
{
if (on) {
unsigned int data = atiixp_read(chip, CMD);
@@ -754,15 +757,15 @@ static void atiixp_in_enable_transfer(atiixp_t *chip, int on)
}
/* flush FIFO of analog IN DMA */
-static void atiixp_in_flush_dma(atiixp_t *chip)
+static void atiixp_in_flush_dma(struct atiixp_modem *chip)
{
atiixp_write(chip, MODEM_FIFO_FLUSH, ATI_REG_MODEM_FIFO_IN_FLUSH);
}
/* set up slots and formats for analog OUT */
-static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_prepare(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
unsigned int data;
spin_lock_irq(&chip->reg_lock);
@@ -776,7 +779,7 @@ static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
}
/* set up slots and formats for analog IN */
-static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_prepare(struct snd_pcm_substream *substream)
{
return 0;
}
@@ -784,11 +787,11 @@ static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
/*
* hw_params - allocate the buffer and set up buffer descriptors
*/
-static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
int err;
int i;
@@ -815,10 +818,10 @@ static int snd_atiixp_pcm_hw_params(snd_pcm_substream_t *substream,
return err;
}
-static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_dma *dma = substream->runtime->private_data;
atiixp_clear_dma_packets(chip, dma, substream);
snd_pcm_lib_free_pages(substream);
@@ -829,13 +832,15 @@ static int snd_atiixp_pcm_hw_free(snd_pcm_substream_t * substream)
/*
* pcm hardware definition, identical for all DMA types
*/
-static snd_pcm_hardware_t snd_atiixp_pcm_hw =
+static struct snd_pcm_hardware snd_atiixp_pcm_hw =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_KNOT,
+ .rates = (SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000 |
+ SNDRV_PCM_RATE_KNOT),
.rate_min = 8000,
.rate_max = 16000,
.channels_min = 2,
@@ -847,13 +852,14 @@ static snd_pcm_hardware_t snd_atiixp_pcm_hw =
.periods_max = ATI_MAX_DESCRIPTORS,
};
-static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma, int pcm_type)
+static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream,
+ struct atiixp_dma *dma, int pcm_type)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
static unsigned int rates[] = { 8000, 9600, 12000, 16000 };
- static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -866,9 +872,12 @@ static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma
dma->substream = substream;
runtime->hw = snd_atiixp_pcm_hw;
dma->ac97_pcm_type = pcm_type;
- if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
+ if ((err = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates)) < 0)
return err;
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ if ((err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
runtime->private_data = dma;
@@ -881,9 +890,10 @@ static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma
return 0;
}
-static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dma)
+static int snd_atiixp_pcm_close(struct snd_pcm_substream *substream,
+ struct atiixp_dma *dma)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
/* disable DMA bits */
snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
spin_lock_irq(&chip->reg_lock);
@@ -896,9 +906,9 @@ static int snd_atiixp_pcm_close(snd_pcm_substream_t *substream, atiixp_dma_t *dm
/*
*/
-static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_open(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
@@ -909,9 +919,9 @@ static int snd_atiixp_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
+static int snd_atiixp_playback_close(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
int err;
down(&chip->open_mutex);
err = snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_PLAYBACK]);
@@ -919,21 +929,21 @@ static int snd_atiixp_playback_close(snd_pcm_substream_t *substream)
return err;
}
-static int snd_atiixp_capture_open(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_open(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
return snd_atiixp_pcm_open(substream, &chip->dmas[ATI_DMA_CAPTURE], 1);
}
-static int snd_atiixp_capture_close(snd_pcm_substream_t *substream)
+static int snd_atiixp_capture_close(struct snd_pcm_substream *substream)
{
- atiixp_t *chip = snd_pcm_substream_chip(substream);
+ struct atiixp_modem *chip = snd_pcm_substream_chip(substream);
return snd_atiixp_pcm_close(substream, &chip->dmas[ATI_DMA_CAPTURE]);
}
/* AC97 playback */
-static snd_pcm_ops_t snd_atiixp_playback_ops = {
+static struct snd_pcm_ops snd_atiixp_playback_ops = {
.open = snd_atiixp_playback_open,
.close = snd_atiixp_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -945,7 +955,7 @@ static snd_pcm_ops_t snd_atiixp_playback_ops = {
};
/* AC97 capture */
-static snd_pcm_ops_t snd_atiixp_capture_ops = {
+static struct snd_pcm_ops snd_atiixp_capture_ops = {
.open = snd_atiixp_capture_open,
.close = snd_atiixp_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -956,7 +966,7 @@ static snd_pcm_ops_t snd_atiixp_capture_ops = {
.pointer = snd_atiixp_pcm_pointer,
};
-static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
+static struct atiixp_dma_ops snd_atiixp_playback_dma_ops = {
.type = ATI_DMA_PLAYBACK,
.llp_offset = ATI_REG_MODEM_OUT_DMA1_LINKPTR,
.dt_cur = ATI_REG_MODEM_OUT_DMA1_DT_CUR,
@@ -965,7 +975,7 @@ static atiixp_dma_ops_t snd_atiixp_playback_dma_ops = {
.flush_dma = atiixp_out_flush_dma,
};
-static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
+static struct atiixp_dma_ops snd_atiixp_capture_dma_ops = {
.type = ATI_DMA_CAPTURE,
.llp_offset = ATI_REG_MODEM_IN_DMA_LINKPTR,
.dt_cur = ATI_REG_MODEM_IN_DMA_DT_CUR,
@@ -974,9 +984,9 @@ static atiixp_dma_ops_t snd_atiixp_capture_dma_ops = {
.flush_dma = atiixp_in_flush_dma,
};
-static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
+static int __devinit snd_atiixp_pcm_new(struct atiixp_modem *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
/* initialize constants */
@@ -995,7 +1005,8 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024);
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024);
return 0;
}
@@ -1007,7 +1018,7 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
*/
static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- atiixp_t *chip = dev_id;
+ struct atiixp_modem *chip = dev_id;
unsigned int status;
status = atiixp_read(chip, ISR);
@@ -1046,13 +1057,13 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
* ac97 mixer section
*/
-static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
+static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int i, err;
int codec_count;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_atiixp_ac97_write,
.read = snd_atiixp_ac97_read,
};
@@ -1102,74 +1113,81 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
/*
* power management
*/
-static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
+static int snd_atiixp_suspend(struct pci_dev *pci, pm_message_t state)
{
- atiixp_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct atiixp_modem *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < NUM_ATI_PCMDEVS; i++)
- if (chip->pcmdevs[i])
- snd_pcm_suspend_all(chip->pcmdevs[i]);
+ snd_pcm_suspend_all(chip->pcmdevs[i]);
for (i = 0; i < NUM_ATI_CODECS; i++)
- if (chip->ac97[i])
- snd_ac97_suspend(chip->ac97[i]);
+ snd_ac97_suspend(chip->ac97[i]);
snd_atiixp_aclink_down(chip);
snd_atiixp_chip_stop(chip);
- pci_set_power_state(chip->pci, PCI_D3hot);
- pci_disable_device(chip->pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_atiixp_resume(snd_card_t *card)
+static int snd_atiixp_resume(struct pci_dev *pci)
{
- atiixp_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct atiixp_modem *chip = card->private_data;
int i;
- pci_enable_device(chip->pci);
- pci_set_power_state(chip->pci, PCI_D0);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
snd_atiixp_aclink_reset(chip);
snd_atiixp_chip_start(chip);
for (i = 0; i < NUM_ATI_CODECS; i++)
- if (chip->ac97[i])
- snd_ac97_resume(chip->ac97[i]);
+ snd_ac97_resume(chip->ac97[i]);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
+#ifdef CONFIG_PROC_FS
/*
* proc interface for register dump
*/
-static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_atiixp_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- atiixp_t *chip = entry->private_data;
+ struct atiixp_modem *chip = entry->private_data;
int i;
for (i = 0; i < 256; i += 4)
snd_iprintf(buffer, "%02x: %08x\n", i, readl(chip->remap_addr + i));
}
-static void __devinit snd_atiixp_proc_init(atiixp_t *chip)
+static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
}
-
+#else
+#define snd_atiixp_proc_init(chip)
+#endif
/*
* destructor
*/
-static int snd_atiixp_free(atiixp_t *chip)
+static int snd_atiixp_free(struct atiixp_modem *chip)
{
if (chip->irq < 0)
goto __hw_end;
@@ -1177,7 +1195,7 @@ static int snd_atiixp_free(atiixp_t *chip)
synchronize_irq(chip->irq);
__hw_end:
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->remap_addr)
iounmap(chip->remap_addr);
pci_release_regions(chip->pci);
@@ -1186,23 +1204,23 @@ static int snd_atiixp_free(atiixp_t *chip)
return 0;
}
-static int snd_atiixp_dev_free(snd_device_t *device)
+static int snd_atiixp_dev_free(struct snd_device *device)
{
- atiixp_t *chip = device->device_data;
+ struct atiixp_modem *chip = device->device_data;
return snd_atiixp_free(chip);
}
/*
* constructor for chip instance
*/
-static int __devinit snd_atiixp_create(snd_card_t *card,
- struct pci_dev *pci,
- atiixp_t **r_chip)
+static int __devinit snd_atiixp_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct atiixp_modem **r_chip)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_atiixp_dev_free,
};
- atiixp_t *chip;
+ struct atiixp_modem *chip;
int err;
if ((err = pci_enable_device(pci)) < 0)
@@ -1232,7 +1250,8 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
return -EIO;
}
- if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+ if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_atiixp_free(chip);
return -EBUSY;
@@ -1256,8 +1275,8 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
static int __devinit snd_atiixp_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- atiixp_t *chip;
+ struct snd_card *card;
+ struct atiixp_modem *chip;
unsigned char revision;
int err;
@@ -1271,6 +1290,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
strcpy(card->shortname, "ATI IXP Modem");
if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
goto __error;
+ card->private_data = chip;
if ((err = snd_atiixp_aclink_reset(chip)) < 0)
goto __error;
@@ -1288,8 +1308,6 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
card->shortname, revision, chip->addr, chip->irq);
- snd_card_set_pm_callback(card, snd_atiixp_suspend, snd_atiixp_resume, chip);
-
if ((err = snd_card_register(card)) < 0)
goto __error;
@@ -1312,7 +1330,10 @@ static struct pci_driver driver = {
.id_table = snd_atiixp_ids,
.probe = snd_atiixp_probe,
.remove = __devexit_p(snd_atiixp_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_atiixp_suspend,
+ .resume = snd_atiixp_resume,
+#endif
};
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index d965609d8b38..7d9184f7367a 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -20,6 +20,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/initval.h>
// module parameters (see "Module Parameters")
@@ -118,7 +119,7 @@ static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
// component-destructor
// (see "Management of Cards and Components")
-static int snd_vortex_dev_free(snd_device_t * device)
+static int snd_vortex_dev_free(struct snd_device *device)
{
vortex_t *vortex = device->device_data;
@@ -137,11 +138,11 @@ static int snd_vortex_dev_free(snd_device_t * device)
// chip-specific constructor
// (see "Management of Cards and Components")
static int __devinit
-snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
+snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
{
vortex_t *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_vortex_dev_free,
};
@@ -150,11 +151,10 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
// check PCI availability (DMA).
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (!pci_dma_supported(pci, VORTEX_DMA_MASK)) {
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK)) {
printk(KERN_ERR "error to set DMA mask\n");
return -ENXIO;
}
- pci_set_dma_mask(pci, VORTEX_DMA_MASK);
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -233,7 +233,7 @@ static int __devinit
snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
+ struct snd_card *card;
vortex_t *chip;
int err;
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index b1197cfab3fb..c2ad2674bea7 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -39,8 +39,6 @@
#include "au88x0_wt.h"
#endif
-#define VORTEX_DMA_MASK 0xffffffff
-
#define hwread(x,y) readl((x)+((y)>>2))
#define hwwrite(x,y,z) writel((z),(x)+((y)>>2))
@@ -129,21 +127,21 @@ typedef struct {
/* Virtual page extender stuff */
int nr_periods;
int period_bytes;
- snd_pcm_sgbuf_t *sgbuf; /* DMA Scatter Gather struct */
+ struct snd_sg_buf *sgbuf; /* DMA Scatter Gather struct */
int period_real;
int period_virt;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
} stream_t;
typedef struct snd_vortex vortex_t;
struct snd_vortex {
/* ALSA structs. */
- snd_card_t *card;
- snd_pcm_t *pcm[VORTEX_PCM_LAST];
+ struct snd_card *card;
+ struct snd_pcm *pcm[VORTEX_PCM_LAST];
- snd_rawmidi_t *rmidi; /* Legacy Midi interface. */
- ac97_t *codec;
+ struct snd_rawmidi *rmidi; /* Legacy Midi interface. */
+ struct snd_ac97 *codec;
/* Stream structs. */
stream_t dma_adb[NR_ADB];
@@ -199,7 +197,7 @@ static void vortex_adb_setsrc(vortex_t * vortex, int adbdma,
/* DMA Engines. */
static void vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
- snd_pcm_sgbuf_t * sgbuf, int size,
+ struct snd_sg_buf * sgbuf, int size,
int count);
static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie,
int dir, int fmt, int d,
@@ -207,7 +205,7 @@ static void vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie,
static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb);
#ifndef CHIP_AU8810
static void vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
- snd_pcm_sgbuf_t * sgbuf, int size,
+ struct snd_sg_buf * sgbuf, int size,
int count);
static void vortex_wtdma_setmode(vortex_t * vortex, int wtdma, int ie, int fmt, int d, /*int e, */
unsigned long offset);
@@ -231,9 +229,9 @@ static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma);
/* global stuff. */
static void vortex_codec_init(vortex_t * vortex);
-static void vortex_codec_write(ac97_t * codec, unsigned short addr,
+static void vortex_codec_write(struct snd_ac97 * codec, unsigned short addr,
unsigned short data);
-static unsigned short vortex_codec_read(ac97_t * codec, unsigned short addr);
+static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr);
static void vortex_spdif_init(vortex_t * vortex, int spdif_sr, int spdif_mode);
static int vortex_core_init(vortex_t * card);
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
index d5755db5141f..d215f393ea64 100644
--- a/sound/pci/au88x0/au88x0_a3d.c
+++ b/sound/pci/au88x0/au88x0_a3d.c
@@ -725,7 +725,7 @@ static void vortex_a3d_translate_filter(a3d_atmos_t filter, int *params)
/* ALSA control interface. */
static int
-snd_vortex_a3d_hrtf_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_a3d_hrtf_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 6;
@@ -734,7 +734,7 @@ snd_vortex_a3d_hrtf_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
static int
-snd_vortex_a3d_itd_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_a3d_itd_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -743,7 +743,7 @@ snd_vortex_a3d_itd_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
static int
-snd_vortex_a3d_ild_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_a3d_ild_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -752,8 +752,8 @@ snd_vortex_a3d_ild_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
static int
-snd_vortex_a3d_filter_info(snd_kcontrol_t *
- kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 4;
@@ -763,7 +763,7 @@ snd_vortex_a3d_filter_info(snd_kcontrol_t *
}
static int
-snd_vortex_a3d_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
//a3dsrc_t *a = kcontrol->private_data;
/* No read yet. Would this be really useable/needed ? */
@@ -772,8 +772,8 @@ snd_vortex_a3d_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
}
static int
-snd_vortex_a3d_hrtf_put(snd_kcontrol_t *
- kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
a3dsrc_t *a = kcontrol->private_data;
int changed = 1, i;
@@ -789,8 +789,8 @@ snd_vortex_a3d_hrtf_put(snd_kcontrol_t *
}
static int
-snd_vortex_a3d_itd_put(snd_kcontrol_t *
- kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
a3dsrc_t *a = kcontrol->private_data;
int coord[6];
@@ -808,8 +808,8 @@ snd_vortex_a3d_itd_put(snd_kcontrol_t *
}
static int
-snd_vortex_a3d_ild_put(snd_kcontrol_t *
- kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
a3dsrc_t *a = kcontrol->private_data;
int changed = 1;
@@ -825,8 +825,8 @@ snd_vortex_a3d_ild_put(snd_kcontrol_t *
}
static int
-snd_vortex_a3d_filter_put(snd_kcontrol_t
- * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
a3dsrc_t *a = kcontrol->private_data;
int i, changed = 1;
@@ -845,7 +845,7 @@ snd_vortex_a3d_filter_put(snd_kcontrol_t
return changed;
}
-static snd_kcontrol_new_t vortex_a3d_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_a3d_kcontrol __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Playback PCM advanced processing",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -857,7 +857,7 @@ static snd_kcontrol_new_t vortex_a3d_kcontrol __devinitdata = {
/* Control (un)registration. */
static int vortex_a3d_register_controls(vortex_t * vortex)
{
- snd_kcontrol_t *kcontrol;
+ struct snd_kcontrol *kcontrol;
int err, i;
/* HRTF controls. */
for (i = 0; i < NR_A3D; i++) {
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 5905188d06b5..e3394fe63253 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1097,7 +1097,7 @@ static void vortex_adbdma_setstartbuffer(vortex_t * vortex, int adbdma, int sb)
static void
vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
- snd_pcm_sgbuf_t * sgbuf, int psize, int count)
+ struct snd_sg_buf * sgbuf, int psize, int count)
{
stream_t *dma = &vortex->dma_adb[adbdma];
@@ -1367,7 +1367,7 @@ static void vortex_wtdma_setstartbuffer(vortex_t * vortex, int wtdma, int sb)
static void
vortex_wtdma_setbuffers(vortex_t * vortex, int wtdma,
- snd_pcm_sgbuf_t * sgbuf, int psize, int count)
+ struct snd_sg_buf * sgbuf, int psize, int count)
{
stream_t *dma = &vortex->dma_wt[wtdma];
@@ -2514,7 +2514,7 @@ static void vortex_codec_init(vortex_t * vortex)
}
static void
-vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data)
+vortex_codec_write(struct snd_ac97 * codec, unsigned short addr, unsigned short data)
{
vortex_t *card = (vortex_t *) codec->private_data;
@@ -2539,7 +2539,7 @@ vortex_codec_write(ac97_t * codec, unsigned short addr, unsigned short data)
hwread(card->mmio, VORTEX_CODEC_IO);
}
-static unsigned short vortex_codec_read(ac97_t * codec, unsigned short addr)
+static unsigned short vortex_codec_read(struct snd_ac97 * codec, unsigned short addr)
{
vortex_t *card = (vortex_t *) codec->private_data;
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 9d933cc0ea0b..13bc8ed301c5 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -730,7 +730,7 @@ static void vortex_Eqlzr_shutdown(vortex_t * vortex)
/* Control interface */
static int
-snd_vortex_eqtoggle_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -740,8 +740,8 @@ snd_vortex_eqtoggle_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
}
static int
-snd_vortex_eqtoggle_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
eqlzr_t *eq = &(vortex->eq);
@@ -753,8 +753,8 @@ snd_vortex_eqtoggle_get(snd_kcontrol_t * kcontrol,
}
static int
-snd_vortex_eqtoggle_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
eqlzr_t *eq = &(vortex->eq);
@@ -766,7 +766,7 @@ snd_vortex_eqtoggle_put(snd_kcontrol_t * kcontrol,
return 1; /* Allways changes */
}
-static snd_kcontrol_new_t vortex_eqtoggle_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "EQ Enable",
.index = 0,
@@ -778,7 +778,7 @@ static snd_kcontrol_new_t vortex_eqtoggle_kcontrol __devinitdata = {
};
static int
-snd_vortex_eq_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -788,7 +788,7 @@ snd_vortex_eq_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
}
static int
-snd_vortex_eq_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int i = kcontrol->private_value;
@@ -802,7 +802,7 @@ snd_vortex_eq_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
}
static int
-snd_vortex_eq_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int changed = 0, i = kcontrol->private_value;
@@ -824,7 +824,7 @@ snd_vortex_eq_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
return changed;
}
-static snd_kcontrol_new_t vortex_eq_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = " .",
.index = 0,
@@ -836,7 +836,7 @@ static snd_kcontrol_new_t vortex_eq_kcontrol __devinitdata = {
};
static int
-snd_vortex_peaks_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 20;
@@ -846,7 +846,7 @@ snd_vortex_peaks_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
}
static int
-snd_vortex_peaks_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int i, count;
@@ -863,7 +863,7 @@ snd_vortex_peaks_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
return 0;
}
-static snd_kcontrol_new_t vortex_levels_kcontrol __devinitdata = {
+static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "EQ Peaks",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -888,7 +888,7 @@ static char *EqBandLabels[10] __devinitdata = {
/* ALSA driver entry points. Init and exit. */
static int vortex_eq_init(vortex_t * vortex)
{
- snd_kcontrol_t *kcontrol;
+ struct snd_kcontrol *kcontrol;
int err, i;
vortex_Eqlzr_init(vortex);
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index 86e27d695c37..c96da1dab863 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -13,10 +13,10 @@
static int __devinit snd_vortex_mixer(vortex_t * vortex)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = vortex_codec_write,
.read = vortex_codec_read,
};
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index c0c23466eb0e..8ba6dd36222b 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -44,9 +44,9 @@
static int __devinit snd_vortex_midi(vortex_t * vortex)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int temp, mode;
- mpu401_t *mpu;
+ struct snd_mpu401 *mpu;
int port;
#ifdef VORTEX_MPU401_LEGACY
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 38bd2b5dd434..6a13ca1d545e 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -31,7 +31,7 @@
#define VORTEX_PCM_TYPE(x) (x->name[40])
/* hardware definition */
-static snd_pcm_hardware_t snd_vortex_playback_hw_adb = {
+static struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
.info =
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
@@ -56,7 +56,7 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_adb = {
};
#ifndef CHIP_AU8820
-static snd_pcm_hardware_t snd_vortex_playback_hw_a3d = {
+static struct snd_pcm_hardware snd_vortex_playback_hw_a3d = {
.info =
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
@@ -76,7 +76,7 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_a3d = {
.periods_max = 64,
};
#endif
-static snd_pcm_hardware_t snd_vortex_playback_hw_spdif = {
+static struct snd_pcm_hardware snd_vortex_playback_hw_spdif = {
.info =
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
@@ -99,7 +99,7 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_spdif = {
};
#ifndef CHIP_AU8810
-static snd_pcm_hardware_t snd_vortex_playback_hw_wt = {
+static struct snd_pcm_hardware snd_vortex_playback_hw_wt = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
@@ -117,10 +117,10 @@ static snd_pcm_hardware_t snd_vortex_playback_hw_wt = {
};
#endif
/* open callback */
-static int snd_vortex_pcm_open(snd_pcm_substream_t * substream)
+static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
{
vortex_t *vortex = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
/* Force equal size periods */
@@ -169,7 +169,7 @@ static int snd_vortex_pcm_open(snd_pcm_substream_t * substream)
}
/* close callback */
-static int snd_vortex_pcm_close(snd_pcm_substream_t * substream)
+static int snd_vortex_pcm_close(struct snd_pcm_substream *substream)
{
//vortex_t *chip = snd_pcm_substream_chip(substream);
stream_t *stream = (stream_t *) substream->runtime->private_data;
@@ -185,12 +185,12 @@ static int snd_vortex_pcm_close(snd_pcm_substream_t * substream)
/* hw_params callback */
static int
-snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
vortex_t *chip = snd_pcm_substream_chip(substream);
stream_t *stream = (stream_t *) (substream->runtime->private_data);
- snd_pcm_sgbuf_t *sgbuf;
+ struct snd_sg_buf *sgbuf;
int err;
// Alloc buffer memory.
@@ -200,7 +200,7 @@ snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
printk(KERN_ERR "Vortex: pcm page alloc failed!\n");
return err;
}
- //sgbuf = (snd_pcm_sgbuf_t *) substream->runtime->dma_private;
+ //sgbuf = (struct snd_sg_buf *) substream->runtime->dma_private;
sgbuf = snd_pcm_substream_sgbuf(substream);
/*
printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
@@ -251,7 +251,7 @@ snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
}
/* hw_free callback */
-static int snd_vortex_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
{
vortex_t *chip = snd_pcm_substream_chip(substream);
stream_t *stream = (stream_t *) (substream->runtime->private_data);
@@ -277,10 +277,10 @@ static int snd_vortex_pcm_hw_free(snd_pcm_substream_t * substream)
}
/* prepare callback */
-static int snd_vortex_pcm_prepare(snd_pcm_substream_t * substream)
+static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream)
{
vortex_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
stream_t *stream = (stream_t *) substream->runtime->private_data;
int dma = stream->dma, fmt, dir;
@@ -310,7 +310,7 @@ static int snd_vortex_pcm_prepare(snd_pcm_substream_t * substream)
}
/* trigger callback */
-static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
vortex_t *chip = snd_pcm_substream_chip(substream);
stream_t *stream = (stream_t *) substream->runtime->private_data;
@@ -374,7 +374,7 @@ static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
}
/* pointer callback */
-static snd_pcm_uframes_t snd_vortex_pcm_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substream)
{
vortex_t *chip = snd_pcm_substream_chip(substream);
stream_t *stream = (stream_t *) substream->runtime->private_data;
@@ -395,13 +395,13 @@ static snd_pcm_uframes_t snd_vortex_pcm_pointer(snd_pcm_substream_t * substream)
/* Page callback. */
/*
-static struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset) {
+static struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned long offset) {
}
*/
/* operators */
-static snd_pcm_ops_t snd_vortex_playback_ops = {
+static struct snd_pcm_ops snd_vortex_playback_ops = {
.open = snd_vortex_pcm_open,
.close = snd_vortex_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -434,14 +434,14 @@ static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
/* SPDIF kcontrol */
-static int snd_vortex_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vortex_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vortex_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -450,7 +450,7 @@ static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vortex_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
ucontrol->value.iec958.status[0] = 0x00;
@@ -464,7 +464,7 @@ static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
int spdif_sr = 48000;
@@ -481,7 +481,7 @@ static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
/* spdif controls */
-static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = {
+static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -501,8 +501,8 @@ static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = {
/* create a pcm device */
static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
{
- snd_pcm_t *pcm;
- snd_kcontrol_t *kctl;
+ struct snd_pcm *pcm;
+ struct snd_kcontrol *kctl;
int i;
int err, nr_capt;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index ab737d6df41d..e077eb3fbe2f 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -186,7 +186,7 @@ static int seqtimer_scaling = 128;
module_param(seqtimer_scaling, int, 0444);
MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
-typedef struct _snd_azf3328 {
+struct snd_azf3328 {
/* often-used fields towards beginning, then grouped */
unsigned long codec_port;
unsigned long io2_port;
@@ -196,16 +196,16 @@ typedef struct _snd_azf3328 {
spinlock_t reg_lock;
- snd_timer_t *timer;
+ struct snd_timer *timer;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int is_playing;
unsigned int is_recording;
- snd_card_t *card;
- snd_rawmidi_t *rmidi;
+ struct snd_card *card;
+ struct snd_rawmidi *rmidi;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
@@ -213,7 +213,7 @@ typedef struct _snd_azf3328 {
struct pci_dev *pci;
int irq;
-} azf3328_t;
+};
static const struct pci_device_id snd_azf3328_ids[] = {
{ 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */
@@ -224,61 +224,61 @@ static const struct pci_device_id snd_azf3328_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
static inline void
-snd_azf3328_codec_outb(const azf3328_t *chip, int reg, u8 value)
+snd_azf3328_codec_outb(const struct snd_azf3328 *chip, int reg, u8 value)
{
outb(value, chip->codec_port + reg);
}
static inline u8
-snd_azf3328_codec_inb(const azf3328_t *chip, int reg)
+snd_azf3328_codec_inb(const struct snd_azf3328 *chip, int reg)
{
return inb(chip->codec_port + reg);
}
static inline void
-snd_azf3328_codec_outw(const azf3328_t *chip, int reg, u16 value)
+snd_azf3328_codec_outw(const struct snd_azf3328 *chip, int reg, u16 value)
{
outw(value, chip->codec_port + reg);
}
static inline u16
-snd_azf3328_codec_inw(const azf3328_t *chip, int reg)
+snd_azf3328_codec_inw(const struct snd_azf3328 *chip, int reg)
{
return inw(chip->codec_port + reg);
}
static inline void
-snd_azf3328_codec_outl(const azf3328_t *chip, int reg, u32 value)
+snd_azf3328_codec_outl(const struct snd_azf3328 *chip, int reg, u32 value)
{
outl(value, chip->codec_port + reg);
}
static inline void
-snd_azf3328_io2_outb(const azf3328_t *chip, int reg, u8 value)
+snd_azf3328_io2_outb(const struct snd_azf3328 *chip, int reg, u8 value)
{
outb(value, chip->io2_port + reg);
}
static inline u8
-snd_azf3328_io2_inb(const azf3328_t *chip, int reg)
+snd_azf3328_io2_inb(const struct snd_azf3328 *chip, int reg)
{
return inb(chip->io2_port + reg);
}
static inline void
-snd_azf3328_mixer_outw(const azf3328_t *chip, int reg, u16 value)
+snd_azf3328_mixer_outw(const struct snd_azf3328 *chip, int reg, u16 value)
{
outw(value, chip->mixer_port + reg);
}
static inline u16
-snd_azf3328_mixer_inw(const azf3328_t *chip, int reg)
+snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, int reg)
{
return inw(chip->mixer_port + reg);
}
static void
-snd_azf3328_mixer_set_mute(const azf3328_t *chip, int reg, int do_mute)
+snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, int reg, int do_mute)
{
unsigned long portbase = chip->mixer_port + reg + 1;
unsigned char oldval;
@@ -294,7 +294,7 @@ snd_azf3328_mixer_set_mute(const azf3328_t *chip, int reg, int do_mute)
}
static void
-snd_azf3328_mixer_write_volume_gradually(const azf3328_t *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay)
+snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg, unsigned char dst_vol_left, unsigned char dst_vol_right, int chan_sel, int delay)
{
unsigned long portbase = chip->mixer_port + reg;
unsigned char curr_vol_left = 0, curr_vol_right = 0;
@@ -353,14 +353,14 @@ snd_azf3328_mixer_write_volume_gradually(const azf3328_t *chip, int reg, unsigne
/*
* general mixer element
*/
-typedef struct azf3328_mixer_reg {
+struct azf3328_mixer_reg {
unsigned int reg;
unsigned int lchan_shift, rchan_shift;
unsigned int mask;
unsigned int invert: 1;
unsigned int stereo: 1;
unsigned int enum_c: 4;
-} azf3328_mixer_reg_t;
+};
#define COMPOSE_MIXER_REG(reg,lchan_shift,rchan_shift,mask,invert,stereo,enum_c) \
((reg) | (lchan_shift << 8) | (rchan_shift << 12) | \
@@ -369,7 +369,7 @@ typedef struct azf3328_mixer_reg {
(stereo << 25) | \
(enum_c << 26))
-static void snd_azf3328_mixer_reg_decode(azf3328_mixer_reg_t *r, unsigned long val)
+static void snd_azf3328_mixer_reg_decode(struct azf3328_mixer_reg *r, unsigned long val)
{
r->reg = val & 0xff;
r->lchan_shift = (val >> 8) & 0x0f;
@@ -420,9 +420,10 @@ static void snd_azf3328_mixer_reg_decode(azf3328_mixer_reg_t *r, unsigned long v
}
static int
-snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+snd_azf3328_info_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- azf3328_mixer_reg_t reg;
+ struct azf3328_mixer_reg reg;
snd_azf3328_dbgcallenter();
snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -436,10 +437,11 @@ snd_azf3328_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
}
static int
-snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- azf3328_t *chip = snd_kcontrol_chip(kcontrol);
- azf3328_mixer_reg_t reg;
+ struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
+ struct azf3328_mixer_reg reg;
unsigned int oreg, val;
snd_azf3328_dbgcallenter();
@@ -466,10 +468,11 @@ snd_azf3328_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol
}
static int
-snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- azf3328_t *chip = snd_kcontrol_chip(kcontrol);
- azf3328_mixer_reg_t reg;
+ struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
+ struct azf3328_mixer_reg reg;
unsigned int oreg, nreg, val;
snd_azf3328_dbgcallenter();
@@ -506,7 +509,8 @@ snd_azf3328_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol
}
static int
-snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static const char * const texts1[] = {
"ModemOut1", "ModemOut2"
@@ -518,7 +522,7 @@ snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinf
"Mic", "CD", "Video", "Aux",
"Line", "Mix", "Mix Mono", "Phone"
};
- azf3328_mixer_reg_t reg;
+ struct azf3328_mixer_reg reg;
snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -540,10 +544,11 @@ snd_azf3328_info_mixer_enum(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinf
}
static int
-snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- azf3328_t *chip = snd_kcontrol_chip(kcontrol);
- azf3328_mixer_reg_t reg;
+ struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
+ struct azf3328_mixer_reg reg;
unsigned short val;
snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -563,10 +568,11 @@ snd_azf3328_get_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
}
static int
-snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- azf3328_t *chip = snd_kcontrol_chip(kcontrol);
- azf3328_mixer_reg_t reg;
+ struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
+ struct azf3328_mixer_reg reg;
unsigned int oreg, nreg, val;
snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -594,7 +600,7 @@ snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
return (nreg != oreg);
}
-static const snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = {
+static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
@@ -666,10 +672,10 @@ static const u16 __devinitdata snd_azf3328_init_values[][2] = {
};
static int __devinit
-snd_azf3328_mixer_new(azf3328_t *chip)
+snd_azf3328_mixer_new(struct snd_azf3328 *chip)
{
- snd_card_t *card;
- const snd_kcontrol_new_t *sw;
+ struct snd_card *card;
+ const struct snd_kcontrol_new *sw;
unsigned int idx;
int err;
@@ -702,8 +708,8 @@ snd_azf3328_mixer_new(azf3328_t *chip)
}
static int
-snd_azf3328_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+snd_azf3328_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int res;
snd_azf3328_dbgcallenter();
@@ -713,7 +719,7 @@ snd_azf3328_hw_params(snd_pcm_substream_t * substream,
}
static int
-snd_azf3328_hw_free(snd_pcm_substream_t * substream)
+snd_azf3328_hw_free(struct snd_pcm_substream *substream)
{
snd_azf3328_dbgcallenter();
snd_pcm_lib_free_pages(substream);
@@ -722,7 +728,7 @@ snd_azf3328_hw_free(snd_pcm_substream_t * substream)
}
static void
-snd_azf3328_setfmt(azf3328_t *chip,
+snd_azf3328_setfmt(struct snd_azf3328 *chip,
unsigned int reg,
unsigned int bitrate,
unsigned int format_width,
@@ -796,7 +802,7 @@ snd_azf3328_setfmt(azf3328_t *chip,
}
static void
-snd_azf3328_setdmaa(azf3328_t *chip,
+snd_azf3328_setdmaa(struct snd_azf3328 *chip,
long unsigned int addr,
unsigned int count,
unsigned int size,
@@ -842,11 +848,11 @@ snd_azf3328_setdmaa(azf3328_t *chip,
}
static int
-snd_azf3328_playback_prepare(snd_pcm_substream_t *substream)
+snd_azf3328_playback_prepare(struct snd_pcm_substream *substream)
{
#if 0
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
#endif
@@ -864,11 +870,11 @@ snd_azf3328_playback_prepare(snd_pcm_substream_t *substream)
}
static int
-snd_azf3328_capture_prepare(snd_pcm_substream_t * substream)
+snd_azf3328_capture_prepare(struct snd_pcm_substream *substream)
{
#if 0
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
#endif
@@ -886,10 +892,10 @@ snd_azf3328_capture_prepare(snd_pcm_substream_t * substream)
}
static int
-snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int result = 0;
unsigned int status1;
@@ -998,10 +1004,10 @@ snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd)
/* this is just analogous to playback; I'm not quite sure whether recording
* should actually be triggered like that */
static int
-snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
+snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int result = 0;
unsigned int status1;
@@ -1096,9 +1102,9 @@ snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
}
static snd_pcm_uframes_t
-snd_azf3328_playback_pointer(snd_pcm_substream_t * substream)
+snd_azf3328_playback_pointer(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
unsigned long bufptr, result;
snd_pcm_uframes_t frmres;
@@ -1117,9 +1123,9 @@ snd_azf3328_playback_pointer(snd_pcm_substream_t * substream)
}
static snd_pcm_uframes_t
-snd_azf3328_capture_pointer(snd_pcm_substream_t * substream)
+snd_azf3328_capture_pointer(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
unsigned long bufptr, result;
snd_pcm_uframes_t frmres;
@@ -1140,7 +1146,7 @@ snd_azf3328_capture_pointer(snd_pcm_substream_t * substream)
static irqreturn_t
snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- azf3328_t *chip = dev_id;
+ struct snd_azf3328 *chip = dev_id;
u8 status, which;
static unsigned long irq_count;
@@ -1223,7 +1229,7 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*****************************************************************/
-static const snd_pcm_hardware_t snd_azf3328_playback =
+static const struct snd_pcm_hardware snd_azf3328_playback =
{
/* FIXME!! Correct? */
.info = SNDRV_PCM_INFO_MMAP |
@@ -1251,7 +1257,7 @@ static const snd_pcm_hardware_t snd_azf3328_playback =
.fifo_size = 0,
};
-static const snd_pcm_hardware_t snd_azf3328_capture =
+static const struct snd_pcm_hardware snd_azf3328_capture =
{
/* FIXME */
.info = SNDRV_PCM_INFO_MMAP |
@@ -1280,7 +1286,7 @@ static const snd_pcm_hardware_t snd_azf3328_capture =
static unsigned int snd_azf3328_fixed_rates[] = {
4000, 4800, 5512, 6620, 8000, 9600, 11025, 13240, 16000, 22050, 32000,
44100, 48000, 66200 };
-static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = {
.count = ARRAY_SIZE(snd_azf3328_fixed_rates),
.list = snd_azf3328_fixed_rates,
.mask = 0,
@@ -1289,10 +1295,10 @@ static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = {
/*****************************************************************/
static int
-snd_azf3328_playback_open(snd_pcm_substream_t * substream)
+snd_azf3328_playback_open(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_azf3328_dbgcallenter();
chip->playback_substream = substream;
@@ -1304,10 +1310,10 @@ snd_azf3328_playback_open(snd_pcm_substream_t * substream)
}
static int
-snd_azf3328_capture_open(snd_pcm_substream_t * substream)
+snd_azf3328_capture_open(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_azf3328_dbgcallenter();
chip->capture_substream = substream;
@@ -1319,9 +1325,9 @@ snd_azf3328_capture_open(snd_pcm_substream_t * substream)
}
static int
-snd_azf3328_playback_close(snd_pcm_substream_t * substream)
+snd_azf3328_playback_close(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
snd_azf3328_dbgcallenter();
@@ -1331,9 +1337,9 @@ snd_azf3328_playback_close(snd_pcm_substream_t * substream)
}
static int
-snd_azf3328_capture_close(snd_pcm_substream_t * substream)
+snd_azf3328_capture_close(struct snd_pcm_substream *substream)
{
- azf3328_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
snd_azf3328_dbgcallenter();
chip->capture_substream = NULL;
@@ -1343,7 +1349,7 @@ snd_azf3328_capture_close(snd_pcm_substream_t * substream)
/******************************************************************/
-static snd_pcm_ops_t snd_azf3328_playback_ops = {
+static struct snd_pcm_ops snd_azf3328_playback_ops = {
.open = snd_azf3328_playback_open,
.close = snd_azf3328_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1354,7 +1360,7 @@ static snd_pcm_ops_t snd_azf3328_playback_ops = {
.pointer = snd_azf3328_playback_pointer
};
-static snd_pcm_ops_t snd_azf3328_capture_ops = {
+static struct snd_pcm_ops snd_azf3328_capture_ops = {
.open = snd_azf3328_capture_open,
.close = snd_azf3328_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1365,18 +1371,10 @@ static snd_pcm_ops_t snd_azf3328_capture_ops = {
.pointer = snd_azf3328_capture_pointer
};
-static void
-snd_azf3328_pcm_free(snd_pcm_t *pcm)
-{
- azf3328_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
static int __devinit
-snd_azf3328_pcm(azf3328_t *chip, int device)
+snd_azf3328_pcm(struct snd_azf3328 *chip, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
snd_azf3328_dbgcallenter();
@@ -1386,7 +1384,6 @@ snd_azf3328_pcm(azf3328_t *chip, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_azf3328_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
@@ -1402,7 +1399,7 @@ snd_azf3328_pcm(azf3328_t *chip, int device)
#ifdef SUPPORT_JOYSTICK
static int __devinit
-snd_azf3328_config_joystick(azf3328_t *chip, int dev)
+snd_azf3328_config_joystick(struct snd_azf3328 *chip, int dev)
{
struct gameport *gp;
struct resource *r;
@@ -1437,7 +1434,7 @@ snd_azf3328_config_joystick(azf3328_t *chip, int dev)
}
static void
-snd_azf3328_free_joystick(azf3328_t *chip)
+snd_azf3328_free_joystick(struct snd_azf3328 *chip)
{
if (chip->gameport) {
struct resource *r = gameport_get_port_data(chip->gameport);
@@ -1452,15 +1449,15 @@ snd_azf3328_free_joystick(azf3328_t *chip)
}
#else
static inline int
-snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; }
+snd_azf3328_config_joystick(struct snd_azf3328 *chip, int dev) { return -ENOSYS; }
static inline void
-snd_azf3328_free_joystick(azf3328_t *chip) { }
+snd_azf3328_free_joystick(struct snd_azf3328 *chip) { }
#endif
/******************************************************************/
static int
-snd_azf3328_free(azf3328_t *chip)
+snd_azf3328_free(struct snd_azf3328 *chip)
{
if (chip->irq < 0)
goto __end_hw;
@@ -1486,9 +1483,9 @@ __end_hw:
}
static int
-snd_azf3328_dev_free(snd_device_t *device)
+snd_azf3328_dev_free(struct snd_device *device)
{
- azf3328_t *chip = device->device_data;
+ struct snd_azf3328 *chip = device->device_data;
return snd_azf3328_free(chip);
}
@@ -1504,9 +1501,9 @@ snd_azf3328_dev_free(snd_device_t *device)
***/
static int
-snd_azf3328_timer_start(snd_timer_t *timer)
+snd_azf3328_timer_start(struct snd_timer *timer)
{
- azf3328_t *chip;
+ struct snd_azf3328 *chip;
unsigned long flags;
unsigned int delay;
@@ -1532,9 +1529,9 @@ snd_azf3328_timer_start(snd_timer_t *timer)
}
static int
-snd_azf3328_timer_stop(snd_timer_t *timer)
+snd_azf3328_timer_stop(struct snd_timer *timer)
{
- azf3328_t *chip;
+ struct snd_azf3328 *chip;
unsigned long flags;
snd_azf3328_dbgcallenter();
@@ -1550,7 +1547,7 @@ snd_azf3328_timer_stop(snd_timer_t *timer)
static int
-snd_azf3328_timer_precise_resolution(snd_timer_t *timer,
+snd_azf3328_timer_precise_resolution(struct snd_timer *timer,
unsigned long *num, unsigned long *den)
{
snd_azf3328_dbgcallenter();
@@ -1560,7 +1557,7 @@ snd_azf3328_timer_precise_resolution(snd_timer_t *timer,
return 0;
}
-static struct _snd_timer_hardware snd_azf3328_timer_hw = {
+static struct snd_timer_hardware snd_azf3328_timer_hw = {
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 977, /* 1000000/1024000 = 0.9765625us */
.ticks = 1024000, /* max tick count, defined by the value register; actually it's not 1024000, but 1048576, but we don't care */
@@ -1570,10 +1567,10 @@ static struct _snd_timer_hardware snd_azf3328_timer_hw = {
};
static int __devinit
-snd_azf3328_timer(azf3328_t *chip, int device)
+snd_azf3328_timer(struct snd_azf3328 *chip, int device)
{
- snd_timer_t *timer = NULL;
- snd_timer_id_t tid;
+ struct snd_timer *timer = NULL;
+ struct snd_timer_id tid;
int err;
snd_azf3328_dbgcallenter();
@@ -1626,7 +1623,7 @@ snd_azf3328_test_bit(unsigned int reg, int bit)
#endif
static void
-snd_azf3328_debug_show_ports(const azf3328_t *chip)
+snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
{
#if DEBUG_MISC
u16 tmp;
@@ -1644,14 +1641,14 @@ snd_azf3328_debug_show_ports(const azf3328_t *chip)
}
static int __devinit
-snd_azf3328_create(snd_card_t * card,
+snd_azf3328_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type,
- azf3328_t ** rchip)
+ struct snd_azf3328 ** rchip)
{
- azf3328_t *chip;
+ struct snd_azf3328 *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_azf3328_dev_free,
};
u16 tmp;
@@ -1744,9 +1741,9 @@ static int __devinit
snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- azf3328_t *chip;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct snd_azf3328 *chip;
+ struct snd_opl3 *opl3;
int err;
snd_azf3328_dbgcallenter();
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 8feca228c6d4..dc9cd3079b14 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -147,9 +147,8 @@ MODULE_PARM_DESC(load_all, "Allow to load the non-whitelisted cards");
/* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */
#define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8)
-typedef struct snd_bt87x bt87x_t;
struct snd_bt87x {
- snd_card_t *card;
+ struct snd_card *card;
struct pci_dev *pci;
void __iomem *mmio;
@@ -159,7 +158,7 @@ struct snd_bt87x {
spinlock_t reg_lock;
long opened;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
struct snd_dma_buffer dma_risc;
unsigned int line_bytes;
@@ -175,17 +174,17 @@ struct snd_bt87x {
enum { DEVICE_DIGITAL, DEVICE_ANALOG };
-static inline u32 snd_bt87x_readl(bt87x_t *chip, u32 reg)
+static inline u32 snd_bt87x_readl(struct snd_bt87x *chip, u32 reg)
{
return readl(chip->mmio + reg);
}
-static inline void snd_bt87x_writel(bt87x_t *chip, u32 reg, u32 value)
+static inline void snd_bt87x_writel(struct snd_bt87x *chip, u32 reg, u32 value)
{
writel(value, chip->mmio + reg);
}
-static int snd_bt87x_create_risc(bt87x_t *chip, snd_pcm_substream_t *substream,
+static int snd_bt87x_create_risc(struct snd_bt87x *chip, struct snd_pcm_substream *substream,
unsigned int periods, unsigned int period_bytes)
{
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
@@ -235,7 +234,7 @@ static int snd_bt87x_create_risc(bt87x_t *chip, snd_pcm_substream_t *substream,
return 0;
}
-static void snd_bt87x_free_risc(bt87x_t *chip)
+static void snd_bt87x_free_risc(struct snd_bt87x *chip)
{
if (chip->dma_risc.area) {
snd_dma_free_pages(&chip->dma_risc);
@@ -243,7 +242,7 @@ static void snd_bt87x_free_risc(bt87x_t *chip)
}
}
-static void snd_bt87x_pci_error(bt87x_t *chip, unsigned int status)
+static void snd_bt87x_pci_error(struct snd_bt87x *chip, unsigned int status)
{
u16 pci_status;
@@ -272,7 +271,7 @@ static void snd_bt87x_pci_error(bt87x_t *chip, unsigned int status)
static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- bt87x_t *chip = dev_id;
+ struct snd_bt87x *chip = dev_id;
unsigned int status, irq_status;
status = snd_bt87x_readl(chip, REG_INT_STAT);
@@ -305,7 +304,7 @@ static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
-static snd_pcm_hardware_t snd_bt87x_digital_hw = {
+static struct snd_pcm_hardware snd_bt87x_digital_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -321,7 +320,7 @@ static snd_pcm_hardware_t snd_bt87x_digital_hw = {
.periods_max = 255,
};
-static snd_pcm_hardware_t snd_bt87x_analog_hw = {
+static struct snd_pcm_hardware snd_bt87x_analog_hw = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -339,7 +338,7 @@ static snd_pcm_hardware_t snd_bt87x_analog_hw = {
.periods_max = 255,
};
-static int snd_bt87x_set_digital_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
+static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime)
{
static struct {
int rate;
@@ -368,15 +367,15 @@ static int snd_bt87x_set_digital_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
return 0;
}
-static int snd_bt87x_set_analog_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
+static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime)
{
- static ratnum_t analog_clock = {
+ static struct snd_ratnum analog_clock = {
.num = ANALOG_CLOCK,
.den_min = CLOCK_DIV_MIN,
.den_max = CLOCK_DIV_MAX,
.den_step = 1
};
- static snd_pcm_hw_constraint_ratnums_t constraint_rates = {
+ static struct snd_pcm_hw_constraint_ratnums constraint_rates = {
.nrats = 1,
.rats = &analog_clock
};
@@ -387,10 +386,10 @@ static int snd_bt87x_set_analog_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
&constraint_rates);
}
-static int snd_bt87x_pcm_open(snd_pcm_substream_t *substream)
+static int snd_bt87x_pcm_open(struct snd_pcm_substream *substream)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if (test_and_set_bit(0, &chip->opened))
@@ -416,9 +415,9 @@ _error:
return err;
}
-static int snd_bt87x_close(snd_pcm_substream_t *substream)
+static int snd_bt87x_close(struct snd_pcm_substream *substream)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
chip->substream = NULL;
clear_bit(0, &chip->opened);
@@ -426,10 +425,10 @@ static int snd_bt87x_close(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_bt87x_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_bt87x_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
int err;
err = snd_pcm_lib_malloc_pages(substream,
@@ -441,19 +440,19 @@ static int snd_bt87x_hw_params(snd_pcm_substream_t *substream,
params_period_bytes(hw_params));
}
-static int snd_bt87x_hw_free(snd_pcm_substream_t *substream)
+static int snd_bt87x_hw_free(struct snd_pcm_substream *substream)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
snd_bt87x_free_risc(chip);
snd_pcm_lib_free_pages(substream);
return 0;
}
-static int snd_bt87x_prepare(snd_pcm_substream_t *substream)
+static int snd_bt87x_prepare(struct snd_pcm_substream *substream)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int decimation;
spin_lock_irq(&chip->reg_lock);
@@ -467,7 +466,7 @@ static int snd_bt87x_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_bt87x_start(bt87x_t *chip)
+static int snd_bt87x_start(struct snd_bt87x *chip)
{
spin_lock(&chip->reg_lock);
chip->current_line = 0;
@@ -481,7 +480,7 @@ static int snd_bt87x_start(bt87x_t *chip)
return 0;
}
-static int snd_bt87x_stop(bt87x_t *chip)
+static int snd_bt87x_stop(struct snd_bt87x *chip)
{
spin_lock(&chip->reg_lock);
chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN);
@@ -492,9 +491,9 @@ static int snd_bt87x_stop(bt87x_t *chip)
return 0;
}
-static int snd_bt87x_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_bt87x_trigger(struct snd_pcm_substream *substream, int cmd)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -506,15 +505,15 @@ static int snd_bt87x_trigger(snd_pcm_substream_t *substream, int cmd)
}
}
-static snd_pcm_uframes_t snd_bt87x_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream)
{
- bt87x_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes);
}
-static snd_pcm_ops_t snd_bt87x_pcm_ops = {
+static struct snd_pcm_ops snd_bt87x_pcm_ops = {
.open = snd_bt87x_pcm_open,
.close = snd_bt87x_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -526,7 +525,8 @@ static snd_pcm_ops_t snd_bt87x_pcm_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static int snd_bt87x_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+static int snd_bt87x_capture_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
{
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
info->count = 1;
@@ -535,17 +535,19 @@ static int snd_bt87x_capture_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_bt87x_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
value->value.integer.value[0] = (chip->reg_control & CTL_A_GAIN_MASK) >> CTL_A_GAIN_SHIFT;
return 0;
}
-static int snd_bt87x_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
u32 old_control;
int changed;
@@ -559,7 +561,7 @@ static int snd_bt87x_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
return changed;
}
-static snd_kcontrol_new_t snd_bt87x_capture_volume = {
+static struct snd_kcontrol_new snd_bt87x_capture_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Volume",
.info = snd_bt87x_capture_volume_info,
@@ -567,7 +569,8 @@ static snd_kcontrol_new_t snd_bt87x_capture_volume = {
.put = snd_bt87x_capture_volume_put,
};
-static int snd_bt87x_capture_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+static int snd_bt87x_capture_boost_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
{
info->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
info->count = 1;
@@ -576,17 +579,19 @@ static int snd_bt87x_capture_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_bt87x_capture_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
value->value.integer.value[0] = !! (chip->reg_control & CTL_A_G2X);
return 0;
}
-static int snd_bt87x_capture_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_boost_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
u32 old_control;
int changed;
@@ -600,7 +605,7 @@ static int snd_bt87x_capture_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return changed;
}
-static snd_kcontrol_new_t snd_bt87x_capture_boost = {
+static struct snd_kcontrol_new snd_bt87x_capture_boost = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Boost",
.info = snd_bt87x_capture_boost_info,
@@ -608,7 +613,8 @@ static snd_kcontrol_new_t snd_bt87x_capture_boost = {
.put = snd_bt87x_capture_boost_put,
};
-static int snd_bt87x_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+static int snd_bt87x_capture_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *info)
{
static char *texts[3] = {"TV Tuner", "FM", "Mic/Line"};
@@ -621,17 +627,19 @@ static int snd_bt87x_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_bt87x_capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
value->value.enumerated.item[0] = (chip->reg_control & CTL_A_SEL_MASK) >> CTL_A_SEL_SHIFT;
return 0;
}
-static int snd_bt87x_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_bt87x_capture_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *value)
{
- bt87x_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_bt87x *chip = snd_kcontrol_chip(kcontrol);
u32 old_control;
int changed;
@@ -645,7 +653,7 @@ static int snd_bt87x_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
return changed;
}
-static snd_kcontrol_new_t snd_bt87x_capture_source = {
+static struct snd_kcontrol_new snd_bt87x_capture_source = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = snd_bt87x_capture_source_info,
@@ -653,7 +661,7 @@ static snd_kcontrol_new_t snd_bt87x_capture_source = {
.put = snd_bt87x_capture_source_put,
};
-static int snd_bt87x_free(bt87x_t *chip)
+static int snd_bt87x_free(struct snd_bt87x *chip)
{
if (chip->mmio) {
snd_bt87x_stop(chip);
@@ -670,16 +678,16 @@ static int snd_bt87x_free(bt87x_t *chip)
return 0;
}
-static int snd_bt87x_dev_free(snd_device_t *device)
+static int snd_bt87x_dev_free(struct snd_device *device)
{
- bt87x_t *chip = device->device_data;
+ struct snd_bt87x *chip = device->device_data;
return snd_bt87x_free(chip);
}
-static int __devinit snd_bt87x_pcm(bt87x_t *chip, int device, char *name)
+static int __devinit snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
if (err < 0)
@@ -694,13 +702,13 @@ static int __devinit snd_bt87x_pcm(bt87x_t *chip, int device, char *name)
(255 * 4092 + 1023) & ~1023);
}
-static int __devinit snd_bt87x_create(snd_card_t *card,
+static int __devinit snd_bt87x_create(struct snd_card *card,
struct pci_dev *pci,
- bt87x_t **rchip)
+ struct snd_bt87x **rchip)
{
- bt87x_t *chip;
+ struct snd_bt87x *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_bt87x_dev_free
};
@@ -823,8 +831,8 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- bt87x_t *chip;
+ struct snd_card *card;
+ struct snd_bt87x *chip;
int err, rate;
rate = pci_id->driver_data;
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 9a4b6406f7a5..c8131ea92ed6 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -554,37 +554,36 @@
#include "ca_midi.h"
-typedef struct snd_ca0106_channel ca0106_channel_t;
-typedef struct snd_ca0106 ca0106_t;
-typedef struct snd_ca0106_pcm ca0106_pcm_t;
+struct snd_ca0106;
struct snd_ca0106_channel {
- ca0106_t *emu;
+ struct snd_ca0106 *emu;
int number;
int use;
- void (*interrupt)(ca0106_t *emu, ca0106_channel_t *channel);
- ca0106_pcm_t *epcm;
+ void (*interrupt)(struct snd_ca0106 *emu, struct snd_ca0106_channel *channel);
+ struct snd_ca0106_pcm *epcm;
};
struct snd_ca0106_pcm {
- ca0106_t *emu;
- snd_pcm_substream_t *substream;
+ struct snd_ca0106 *emu;
+ struct snd_pcm_substream *substream;
int channel_id;
unsigned short running;
};
-typedef struct {
+struct snd_ca0106_details {
u32 serial;
char * name;
int ac97;
int gpio_type;
int i2c_adc;
-} ca0106_details_t;
+ int spi_dac;
+};
// definition of the chip-specific record
struct snd_ca0106 {
- snd_card_t *card;
- ca0106_details_t *details;
+ struct snd_card *card;
+ struct snd_ca0106_details *details;
struct pci_dev *pci;
unsigned long port;
@@ -597,11 +596,11 @@ struct snd_ca0106 {
spinlock_t emu_lock;
- ac97_t *ac97;
- snd_pcm_t *pcm;
+ struct snd_ac97 *ac97;
+ struct snd_pcm *pcm;
- ca0106_channel_t playback_channels[4];
- ca0106_channel_t capture_channels[4];
+ struct snd_ca0106_channel playback_channels[4];
+ struct snd_ca0106_channel capture_channels[4];
u32 spdif_bits[4]; /* s/pdif out setup */
int spdif_enable;
int capture_source;
@@ -609,22 +608,22 @@ struct snd_ca0106 {
struct snd_dma_buffer buffer;
- ca_midi_t midi;
- ca_midi_t midi2;
+ struct snd_ca_midi midi;
+ struct snd_ca_midi midi2;
};
-int __devinit snd_ca0106_mixer(ca0106_t *emu);
-int __devinit snd_ca0106_proc_init(ca0106_t * emu);
+int snd_ca0106_mixer(struct snd_ca0106 *emu);
+int snd_ca0106_proc_init(struct snd_ca0106 * emu);
-unsigned int snd_ca0106_ptr_read(ca0106_t * emu,
- unsigned int reg,
- unsigned int chn);
+unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
+ unsigned int reg,
+ unsigned int chn);
-void snd_ca0106_ptr_write(ca0106_t *emu,
- unsigned int reg,
- unsigned int chn,
- unsigned int data);
+void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
+ unsigned int reg,
+ unsigned int chn,
+ unsigned int data);
-int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
+int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 389d967c97f4..6ed7c0bfa091 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -164,7 +164,7 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
#include "ca0106.h"
-static ca0106_details_t ca0106_chip_details[] = {
+static struct snd_ca0106_details ca0106_chip_details[] = {
/* AudigyLS[SB0310] */
{ .serial = 0x10021102,
.name = "AudigyLS [SB0310]",
@@ -183,6 +183,17 @@ static ca0106_details_t ca0106_chip_details[] = {
.name = "Live! 7.1 24bit [SB0413]",
.gpio_type = 1,
.i2c_adc = 1 } ,
+ /* New Audigy SE. Has a different DAC. */
+ /* SB0570:
+ * CTRL:CA0106-DAT
+ * ADC: WM8768GEDS
+ * DAC: WM8775EDS
+ */
+ { .serial = 0x100a1102,
+ .name = "Audigy SE [SB0570]",
+ .gpio_type = 1,
+ .i2c_adc = 1,
+ .spi_dac = 1 } ,
/* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
{ .serial = 0x10091462,
.name = "MSI K8N Diamond MB [SB0438]",
@@ -201,13 +212,14 @@ static ca0106_details_t ca0106_chip_details[] = {
};
/* hardware definition */
-static snd_pcm_hardware_t snd_ca0106_playback_hw = {
+static struct snd_pcm_hardware snd_ca0106_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+ .rates = (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000),
.rate_min = 48000,
.rate_max = 192000,
.channels_min = 2, //1,
@@ -220,13 +232,14 @@ static snd_pcm_hardware_t snd_ca0106_playback_hw = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ca0106_capture_hw = {
+static struct snd_pcm_hardware snd_ca0106_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
- .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+ .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000),
.rate_min = 44100,
.rate_max = 192000,
.channels_min = 2,
@@ -239,7 +252,7 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
.fifo_size = 0,
};
-unsigned int snd_ca0106_ptr_read(ca0106_t * emu,
+unsigned int snd_ca0106_ptr_read(struct snd_ca0106 * emu,
unsigned int reg,
unsigned int chn)
{
@@ -255,7 +268,7 @@ unsigned int snd_ca0106_ptr_read(ca0106_t * emu,
return val;
}
-void snd_ca0106_ptr_write(ca0106_t *emu,
+void snd_ca0106_ptr_write(struct snd_ca0106 *emu,
unsigned int reg,
unsigned int chn,
unsigned int data)
@@ -271,16 +284,47 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-int snd_ca0106_i2c_write(ca0106_t *emu,
+int snd_ca0106_spi_write(struct snd_ca0106 * emu,
+ unsigned int data)
+{
+ unsigned int reset, set;
+ unsigned int reg, tmp;
+ int n, result;
+ reg = SPI;
+ if (data > 0xffff) /* Only 16bit values allowed */
+ return 1;
+ tmp = snd_ca0106_ptr_read(emu, reg, 0);
+ reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
+ set = reset | 0x10000; /* Set xxx1xxxx */
+ snd_ca0106_ptr_write(emu, reg, 0, reset | data);
+ tmp = snd_ca0106_ptr_read(emu, reg, 0); /* write post */
+ snd_ca0106_ptr_write(emu, reg, 0, set | data);
+ result = 1;
+ /* Wait for status bit to return to 0 */
+ for (n = 0; n < 100; n++) {
+ udelay(10);
+ tmp = snd_ca0106_ptr_read(emu, reg, 0);
+ if (!(tmp & 0x10000)) {
+ result = 0;
+ break;
+ }
+ }
+ if (result) /* Timed out */
+ return 1;
+ snd_ca0106_ptr_write(emu, reg, 0, reset | data);
+ tmp = snd_ca0106_ptr_read(emu, reg, 0); /* Write post */
+ return 0;
+}
+
+int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
u32 reg,
u32 value)
{
u32 tmp;
- int timeout=0;
+ int timeout = 0;
int status;
int retry;
- if ((reg > 0x7f) || (value > 0x1ff))
- {
+ if ((reg > 0x7f) || (value > 0x1ff)) {
snd_printk(KERN_ERR "i2c_write: invalid values.\n");
return -EINVAL;
}
@@ -292,8 +336,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
/* This controls the I2C connected to the WM8775 ADC Codec */
snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
- for(retry=0;retry<10;retry++)
- {
+ for (retry = 0; retry < 10; retry++) {
/* Send the data to i2c */
tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
@@ -301,24 +344,22 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
/* Wait till the transaction ends */
- while(1)
- {
+ while (1) {
status = snd_ca0106_ptr_read(emu, I2C_A, 0);
//snd_printk("I2C:status=0x%x\n", status);
timeout++;
- if((status & I2C_A_ADC_START)==0)
+ if ((status & I2C_A_ADC_START) == 0)
break;
- if(timeout>1000)
+ if (timeout > 1000)
break;
}
//Read back and see if the transaction is successful
- if((status & I2C_A_ADC_ABORT)==0)
+ if ((status & I2C_A_ADC_ABORT) == 0)
break;
}
- if(retry==10)
- {
+ if (retry == 10) {
snd_printk(KERN_ERR "Writing to ADC failed!\n");
return -EINVAL;
}
@@ -327,7 +368,7 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
}
-static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
+static void snd_ca0106_intr_enable(struct snd_ca0106 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -338,7 +379,7 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_ca0106_intr_disable(ca0106_t *emu, unsigned int intrenb)
+static void snd_ca0106_intr_disable(struct snd_ca0106 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -350,18 +391,19 @@ static void snd_ca0106_intr_disable(ca0106_t *emu, unsigned int intrenb)
}
-static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
/* open_playback callback */
-static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream, int channel_id)
+static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
+ int channel_id)
{
- ca0106_t *chip = snd_pcm_substream_chip(substream);
- ca0106_channel_t *channel = &(chip->playback_channels[channel_id]);
- ca0106_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
+ struct snd_ca0106_channel *channel = &(chip->playback_channels[channel_id]);
+ struct snd_ca0106_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -380,10 +422,10 @@ static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream,
channel->emu = chip;
channel->number = channel_id;
- channel->use=1;
+ channel->use = 1;
//printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
//channel->interrupt = snd_ca0106_pcm_channel_interrupt;
- channel->epcm=epcm;
+ channel->epcm = epcm;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0)
@@ -392,43 +434,44 @@ static int snd_ca0106_pcm_open_playback_channel(snd_pcm_substream_t *substream,
}
/* close callback */
-static int snd_ca0106_pcm_close_playback(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
{
- ca0106_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
- chip->playback_channels[epcm->channel_id].use=0;
-/* FIXME: maybe zero others */
+ struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
+ chip->playback_channels[epcm->channel_id].use = 0;
+ /* FIXME: maybe zero others */
return 0;
}
-static int snd_ca0106_pcm_open_playback_front(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_playback_front(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
}
-static int snd_ca0106_pcm_open_playback_center_lfe(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_playback_center_lfe(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_playback_channel(substream, PCM_CENTER_LFE_CHANNEL);
}
-static int snd_ca0106_pcm_open_playback_unknown(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_playback_unknown(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_playback_channel(substream, PCM_UNKNOWN_CHANNEL);
}
-static int snd_ca0106_pcm_open_playback_rear(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_playback_rear(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_playback_channel(substream, PCM_REAR_CHANNEL);
}
/* open_capture callback */
-static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
+static int snd_ca0106_pcm_open_capture_channel(struct snd_pcm_substream *substream,
+ int channel_id)
{
- ca0106_t *chip = snd_pcm_substream_chip(substream);
- ca0106_channel_t *channel = &(chip->capture_channels[channel_id]);
- ca0106_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
+ struct snd_ca0106_channel *channel = &(chip->capture_channels[channel_id]);
+ struct snd_ca0106_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -448,10 +491,10 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i
channel->emu = chip;
channel->number = channel_id;
- channel->use=1;
+ channel->use = 1;
//printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
//channel->interrupt = snd_ca0106_pcm_channel_interrupt;
- channel->epcm=epcm;
+ channel->epcm = epcm;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
//snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
@@ -461,70 +504,70 @@ static int snd_ca0106_pcm_open_capture_channel(snd_pcm_substream_t *substream, i
}
/* close callback */
-static int snd_ca0106_pcm_close_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_close_capture(struct snd_pcm_substream *substream)
{
- ca0106_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
- chip->capture_channels[epcm->channel_id].use=0;
-/* FIXME: maybe zero others */
+ struct snd_ca0106 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
+ chip->capture_channels[epcm->channel_id].use = 0;
+ /* FIXME: maybe zero others */
return 0;
}
-static int snd_ca0106_pcm_open_0_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_0_capture(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_capture_channel(substream, 0);
}
-static int snd_ca0106_pcm_open_1_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_1_capture(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_capture_channel(substream, 1);
}
-static int snd_ca0106_pcm_open_2_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_2_capture(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_capture_channel(substream, 2);
}
-static int snd_ca0106_pcm_open_3_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
{
return snd_ca0106_pcm_open_capture_channel(substream, 3);
}
/* hw_params callback */
-static int snd_ca0106_pcm_hw_params_playback(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
/* hw_free callback */
-static int snd_ca0106_pcm_hw_free_playback(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
/* hw_params callback */
-static int snd_ca0106_pcm_hw_params_capture(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
/* hw_free callback */
-static int snd_ca0106_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
/* prepare playback callback */
-static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
int channel = epcm->channel_id;
u32 *table_base = (u32 *)(emu->buffer.area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -593,8 +636,8 @@ static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
/* FIXME: Check emu->buffer.size before actually writing to it. */
for(i=0; i < runtime->periods; i++) {
- table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
- table_base[(i*2)+1]=period_size_bytes<<16;
+ table_base[i*2] = runtime->dma_addr + (i * period_size_bytes);
+ table_base[i*2+1] = period_size_bytes << 16;
}
snd_ca0106_ptr_write(emu, PLAYBACK_LIST_ADDR, channel, emu->buffer.addr+(8*16*channel));
@@ -621,11 +664,11 @@ static int snd_ca0106_pcm_prepare_playback(snd_pcm_substream_t *substream)
}
/* prepare capture callback */
-static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
+static int snd_ca0106_pcm_prepare_capture(struct snd_pcm_substream *substream)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
int channel = epcm->channel_id;
u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
u32 hcfg_set = 0x00000000;
@@ -692,16 +735,16 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
}
/* trigger_playback callback */
-static int snd_ca0106_pcm_trigger_playback(snd_pcm_substream_t *substream,
+static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
int cmd)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime;
- ca0106_pcm_t *epcm;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime;
+ struct snd_ca0106_pcm *epcm;
int channel;
int result = 0;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
u32 basic = 0;
u32 extended = 0;
int running=0;
@@ -745,12 +788,12 @@ static int snd_ca0106_pcm_trigger_playback(snd_pcm_substream_t *substream,
}
/* trigger_capture callback */
-static int snd_ca0106_pcm_trigger_capture(snd_pcm_substream_t *substream,
+static int snd_ca0106_pcm_trigger_capture(struct snd_pcm_substream *substream,
int cmd)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
int channel = epcm->channel_id;
int result = 0;
@@ -774,11 +817,11 @@ static int snd_ca0106_pcm_trigger_capture(snd_pcm_substream_t *substream,
/* pointer_playback callback */
static snd_pcm_uframes_t
-snd_ca0106_pcm_pointer_playback(snd_pcm_substream_t *substream)
+snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
int channel = epcm->channel_id;
@@ -801,11 +844,11 @@ snd_ca0106_pcm_pointer_playback(snd_pcm_substream_t *substream)
/* pointer_capture callback */
static snd_pcm_uframes_t
-snd_ca0106_pcm_pointer_capture(snd_pcm_substream_t *substream)
+snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
{
- ca0106_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ca0106_pcm_t *epcm = runtime->private_data;
+ struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ca0106_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
int channel = channel=epcm->channel_id;
@@ -823,7 +866,7 @@ snd_ca0106_pcm_pointer_capture(snd_pcm_substream_t *substream)
}
/* operators */
-static snd_pcm_ops_t snd_ca0106_playback_front_ops = {
+static struct snd_pcm_ops snd_ca0106_playback_front_ops = {
.open = snd_ca0106_pcm_open_playback_front,
.close = snd_ca0106_pcm_close_playback,
.ioctl = snd_pcm_lib_ioctl,
@@ -834,7 +877,7 @@ static snd_pcm_ops_t snd_ca0106_playback_front_ops = {
.pointer = snd_ca0106_pcm_pointer_playback,
};
-static snd_pcm_ops_t snd_ca0106_capture_0_ops = {
+static struct snd_pcm_ops snd_ca0106_capture_0_ops = {
.open = snd_ca0106_pcm_open_0_capture,
.close = snd_ca0106_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -845,7 +888,7 @@ static snd_pcm_ops_t snd_ca0106_capture_0_ops = {
.pointer = snd_ca0106_pcm_pointer_capture,
};
-static snd_pcm_ops_t snd_ca0106_capture_1_ops = {
+static struct snd_pcm_ops snd_ca0106_capture_1_ops = {
.open = snd_ca0106_pcm_open_1_capture,
.close = snd_ca0106_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -856,7 +899,7 @@ static snd_pcm_ops_t snd_ca0106_capture_1_ops = {
.pointer = snd_ca0106_pcm_pointer_capture,
};
-static snd_pcm_ops_t snd_ca0106_capture_2_ops = {
+static struct snd_pcm_ops snd_ca0106_capture_2_ops = {
.open = snd_ca0106_pcm_open_2_capture,
.close = snd_ca0106_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -867,7 +910,7 @@ static snd_pcm_ops_t snd_ca0106_capture_2_ops = {
.pointer = snd_ca0106_pcm_pointer_capture,
};
-static snd_pcm_ops_t snd_ca0106_capture_3_ops = {
+static struct snd_pcm_ops snd_ca0106_capture_3_ops = {
.open = snd_ca0106_pcm_open_3_capture,
.close = snd_ca0106_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -878,7 +921,7 @@ static snd_pcm_ops_t snd_ca0106_capture_3_ops = {
.pointer = snd_ca0106_pcm_pointer_capture,
};
-static snd_pcm_ops_t snd_ca0106_playback_center_lfe_ops = {
+static struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
.open = snd_ca0106_pcm_open_playback_center_lfe,
.close = snd_ca0106_pcm_close_playback,
.ioctl = snd_pcm_lib_ioctl,
@@ -889,7 +932,7 @@ static snd_pcm_ops_t snd_ca0106_playback_center_lfe_ops = {
.pointer = snd_ca0106_pcm_pointer_playback,
};
-static snd_pcm_ops_t snd_ca0106_playback_unknown_ops = {
+static struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
.open = snd_ca0106_pcm_open_playback_unknown,
.close = snd_ca0106_pcm_close_playback,
.ioctl = snd_pcm_lib_ioctl,
@@ -900,7 +943,7 @@ static snd_pcm_ops_t snd_ca0106_playback_unknown_ops = {
.pointer = snd_ca0106_pcm_pointer_playback,
};
-static snd_pcm_ops_t snd_ca0106_playback_rear_ops = {
+static struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
.open = snd_ca0106_pcm_open_playback_rear,
.close = snd_ca0106_pcm_close_playback,
.ioctl = snd_pcm_lib_ioctl,
@@ -912,10 +955,10 @@ static snd_pcm_ops_t snd_ca0106_playback_rear_ops = {
};
-static unsigned short snd_ca0106_ac97_read(ac97_t *ac97,
+static unsigned short snd_ca0106_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- ca0106_t *emu = ac97->private_data;
+ struct snd_ca0106 *emu = ac97->private_data;
unsigned long flags;
unsigned short val;
@@ -926,10 +969,10 @@ static unsigned short snd_ca0106_ac97_read(ac97_t *ac97,
return val;
}
-static void snd_ca0106_ac97_write(ac97_t *ac97,
+static void snd_ca0106_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- ca0106_t *emu = ac97->private_data;
+ struct snd_ca0106 *emu = ac97->private_data;
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
@@ -938,12 +981,12 @@ static void snd_ca0106_ac97_write(ac97_t *ac97,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static int snd_ca0106_ac97(ca0106_t *chip)
+static int snd_ca0106_ac97(struct snd_ca0106 *chip)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_ca0106_ac97_write,
.read = snd_ca0106_ac97_read,
};
@@ -958,7 +1001,7 @@ static int snd_ca0106_ac97(ca0106_t *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
-static int snd_ca0106_free(ca0106_t *chip)
+static int snd_ca0106_free(struct snd_ca0106 *chip)
{
if (chip->res_port != NULL) { /* avoid access to already used hardware */
// disable interrupts
@@ -991,9 +1034,9 @@ static int snd_ca0106_free(ca0106_t *chip)
return 0;
}
-static int snd_ca0106_dev_free(snd_device_t *device)
+static int snd_ca0106_dev_free(struct snd_device *device)
{
- ca0106_t *chip = device->device_data;
+ struct snd_ca0106 *chip = device->device_data;
return snd_ca0106_free(chip);
}
@@ -1002,19 +1045,13 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
{
unsigned int status;
- ca0106_t *chip = dev_id;
+ struct snd_ca0106 *chip = dev_id;
int i;
int mask;
unsigned int stat76;
- ca0106_channel_t *pchannel;
-
- spin_lock(&chip->emu_lock);
+ struct snd_ca0106_channel *pchannel;
status = inl(chip->port + IPR);
-
- // call updater, unlock before it
- spin_unlock(&chip->emu_lock);
-
if (! status)
return IRQ_NONE;
@@ -1024,11 +1061,11 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
mask = 0x11; /* 0x1 for one half, 0x10 for the other half period. */
for(i = 0; i < 4; i++) {
pchannel = &(chip->playback_channels[i]);
- if(stat76 & mask) {
+ if (stat76 & mask) {
/* FIXME: Select the correct substream for period elapsed */
if(pchannel->use) {
- snd_pcm_period_elapsed(pchannel->epcm->substream);
- //printk(KERN_INFO "interrupt [%d] used\n", i);
+ snd_pcm_period_elapsed(pchannel->epcm->substream);
+ //printk(KERN_INFO "interrupt [%d] used\n", i);
}
}
//printk(KERN_INFO "channel=%p\n",pchannel);
@@ -1038,11 +1075,11 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
mask = 0x110000; /* 0x1 for one half, 0x10 for the other half period. */
for(i = 0; i < 4; i++) {
pchannel = &(chip->capture_channels[i]);
- if(stat76 & mask) {
+ if (stat76 & mask) {
/* FIXME: Select the correct substream for period elapsed */
if(pchannel->use) {
- snd_pcm_period_elapsed(pchannel->epcm->substream);
- //printk(KERN_INFO "interrupt [%d] used\n", i);
+ snd_pcm_period_elapsed(pchannel->epcm->substream);
+ //printk(KERN_INFO "interrupt [%d] used\n", i);
}
}
//printk(KERN_INFO "channel=%p\n",pchannel);
@@ -1051,10 +1088,9 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
}
snd_ca0106_ptr_write(chip, EXTENDED_INT, 0, stat76);
- spin_lock(&chip->emu_lock);
if (chip->midi.dev_id &&
- (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
+ (status & (chip->midi.ipr_tx|chip->midi.ipr_rx))) {
if (chip->midi.interrupt)
chip->midi.interrupt(&chip->midi, status);
else
@@ -1064,22 +1100,13 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id,
// acknowledge the interrupt if necessary
outl(status, chip->port+IPR);
- spin_unlock(&chip->emu_lock);
-
return IRQ_HANDLED;
}
-static void snd_ca0106_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
{
- ca0106_t *emu = pcm->private_data;
- emu->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_ca0106_pcm(ca0106_t *emu, int device, snd_pcm_t **rpcm)
-{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
int err;
if (rpcm)
@@ -1088,7 +1115,6 @@ static int __devinit snd_ca0106_pcm(ca0106_t *emu, int device, snd_pcm_t **rpcm)
return err;
pcm->private_data = emu;
- pcm->private_free = snd_ca0106_pcm_free;
switch (device) {
case 0:
@@ -1140,15 +1166,39 @@ static int __devinit snd_ca0106_pcm(ca0106_t *emu, int device, snd_pcm_t **rpcm)
return 0;
}
-static int __devinit snd_ca0106_create(snd_card_t *card,
+static unsigned int spi_dac_init[] = {
+ 0x00ff,
+ 0x02ff,
+ 0x0400,
+ 0x0520,
+ 0x0600,
+ 0x08ff,
+ 0x0aff,
+ 0x0cff,
+ 0x0eff,
+ 0x10ff,
+ 0x1200,
+ 0x1400,
+ 0x1480,
+ 0x1800,
+ 0x1aff,
+ 0x1cff,
+ 0x1e00,
+ 0x0530,
+ 0x0602,
+ 0x0622,
+ 0x1400,
+};
+
+static int __devinit snd_ca0106_create(struct snd_card *card,
struct pci_dev *pci,
- ca0106_t **rchip)
+ struct snd_ca0106 **rchip)
{
- ca0106_t *chip;
- ca0106_details_t *c;
+ struct snd_ca0106 *chip;
+ struct snd_ca0106_details *c;
int err;
int ch;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ca0106_dev_free,
};
@@ -1210,8 +1260,9 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
strcpy(card->driver, "CA0106");
strcpy(card->shortname, "CA0106");
- for (c=ca0106_chip_details; c->serial; c++) {
- if (c->serial == chip->serial) break;
+ for (c = ca0106_chip_details; c->serial; c++) {
+ if (c->serial == chip->serial)
+ break;
}
chip->details = c;
sprintf(card->longname, "%s at 0x%lx irq %i",
@@ -1320,6 +1371,13 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
}
+ if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
+ int size, n;
+
+ size = ARRAY_SIZE(spi_dac_init);
+ for (n=0; n < size; n++)
+ snd_ca0106_spi_write(chip, spi_dac_init[n]);
+ }
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
chip, &ops)) < 0) {
@@ -1331,43 +1389,44 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
}
-static void ca0106_midi_interrupt_enable(ca_midi_t *midi, int intr)
+static void ca0106_midi_interrupt_enable(struct snd_ca_midi *midi, int intr)
{
- snd_ca0106_intr_enable((ca0106_t *)(midi->dev_id), intr);
+ snd_ca0106_intr_enable((struct snd_ca0106 *)(midi->dev_id), intr);
}
-static void ca0106_midi_interrupt_disable(ca_midi_t *midi, int intr)
+static void ca0106_midi_interrupt_disable(struct snd_ca_midi *midi, int intr)
{
- snd_ca0106_intr_disable((ca0106_t *)(midi->dev_id), intr);
+ snd_ca0106_intr_disable((struct snd_ca0106 *)(midi->dev_id), intr);
}
-static unsigned char ca0106_midi_read(ca_midi_t *midi, int idx)
+static unsigned char ca0106_midi_read(struct snd_ca_midi *midi, int idx)
{
- return (unsigned char)snd_ca0106_ptr_read((ca0106_t *)(midi->dev_id), midi->port + idx, 0);
+ return (unsigned char)snd_ca0106_ptr_read((struct snd_ca0106 *)(midi->dev_id),
+ midi->port + idx, 0);
}
-static void ca0106_midi_write(ca_midi_t *midi, int data, int idx)
+static void ca0106_midi_write(struct snd_ca_midi *midi, int data, int idx)
{
- snd_ca0106_ptr_write((ca0106_t *)(midi->dev_id), midi->port + idx, 0, data);
+ snd_ca0106_ptr_write((struct snd_ca0106 *)(midi->dev_id), midi->port + idx, 0, data);
}
-static snd_card_t *ca0106_dev_id_card(void *dev_id)
+static struct snd_card *ca0106_dev_id_card(void *dev_id)
{
- return ((ca0106_t *)dev_id)->card;
+ return ((struct snd_ca0106 *)dev_id)->card;
}
static int ca0106_dev_id_port(void *dev_id)
{
- return ((ca0106_t *)dev_id)->port;
+ return ((struct snd_ca0106 *)dev_id)->port;
}
-static int __devinit snd_ca0106_midi(ca0106_t *chip, unsigned int channel)
+static int __devinit snd_ca0106_midi(struct snd_ca0106 *chip, unsigned int channel)
{
- ca_midi_t *midi;
+ struct snd_ca_midi *midi;
char *name;
int err;
- if(channel==CA0106_MIDI_CHAN_B) {
+ if (channel == CA0106_MIDI_CHAN_B) {
name = "CA0106 MPU-401 (UART) B";
midi = &chip->midi2;
midi->tx_enable = INTE_MIDI_TX_B;
@@ -1416,8 +1475,8 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- ca0106_t *chip;
+ struct snd_card *card;
+ struct snd_ca0106 *chip;
int err;
if (dev >= SNDRV_CARDS)
@@ -1471,7 +1530,9 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
}
snd_printdd(" done.\n");
+#ifdef CONFIG_PROC_FS
snd_ca0106_proc_init(chip);
+#endif
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
@@ -1507,12 +1568,7 @@ static struct pci_driver driver = {
// initialization of the module
static int __init alsa_card_ca0106_init(void)
{
- int err;
-
- if ((err = pci_register_driver(&driver)) > 0)
- return err;
-
- return 0;
+ return pci_register_driver(&driver);
}
// clean up the module
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index c10e4a54301b..06fe055674fb 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -73,7 +73,8 @@
#include "ca0106.h"
-static int snd_ca0106_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -82,19 +83,19 @@ static int snd_ca0106_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_ca0106_shared_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->spdif_enable;
return 0;
}
-static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
u32 mask;
@@ -125,18 +126,12 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ca0106_shared_spdif __devinitdata =
+static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Out",
- .info = snd_ca0106_shared_spdif_info,
- .get = snd_ca0106_shared_spdif_get,
- .put = snd_ca0106_shared_spdif_put
-};
-
-static int snd_ca0106_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[6] = { "SPDIF out", "i2s mixer out", "SPDIF in", "i2s in", "AC97 in", "SRC out" };
+ static char *texts[6] = {
+ "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
+ };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -147,19 +142,19 @@ static int snd_ca0106_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_ca0106_capture_source_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->capture_source;
return 0;
}
-static int snd_ca0106_capture_source_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
u32 mask;
@@ -176,16 +171,8 @@ static int snd_ca0106_capture_source_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = snd_ca0106_capture_source_info,
- .get = snd_ca0106_capture_source_get,
- .put = snd_ca0106_capture_source_put
-};
-
-static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "Line in", "Mic in" };
@@ -198,19 +185,19 @@ static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl
return 0;
}
-static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
return 0;
}
-static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
u32 tmp;
@@ -235,7 +222,7 @@ static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
+static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic/Line in Capture",
@@ -244,17 +231,18 @@ static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
.put = snd_ca0106_capture_mic_line_in_put
};
-static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ca0106_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
@@ -264,8 +252,8 @@ static int snd_ca0106_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ca0106_spdif_get_mask(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -274,10 +262,10 @@ static int snd_ca0106_spdif_get_mask(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ca0106_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
int change;
unsigned int val;
@@ -294,27 +282,8 @@ static int snd_ca0106_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ca0106_spdif_mask_control =
-{
- .access = SNDRV_CTL_ELEM_ACCESS_READ,
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
- .count = 4,
- .info = snd_ca0106_spdif_info,
- .get = snd_ca0106_spdif_get_mask
-};
-
-static snd_kcontrol_new_t snd_ca0106_spdif_control =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
- .count = 4,
- .info = snd_ca0106_spdif_info,
- .get = snd_ca0106_spdif_get,
- .put = snd_ca0106_spdif_put
-};
-
-static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -323,11 +292,15 @@ static int snd_ca0106_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol, int reg, int channel_id)
+static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int value;
+ int channel_id, reg;
+
+ channel_id = (kcontrol->private_value >> 8) & 0xff;
+ reg = kcontrol->private_value & 0xff;
value = snd_ca0106_ptr_read(emu, reg, channel_id);
ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
@@ -335,237 +308,103 @@ static int snd_ca0106_volume_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ca0106_volume_get_spdif_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_FRONT_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-
-static int snd_ca0106_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_CENTER_LFE_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_UNKNOWN_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_get_spdif_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_REAR_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_get_analog_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- int channel_id = CONTROL_FRONT_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
+ struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int oval, nval;
+ int channel_id, reg;
-static int snd_ca0106_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_CENTER_LFE_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_get_analog_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_UNKNOWN_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_get_analog_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_REAR_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
+ channel_id = (kcontrol->private_value >> 8) & 0xff;
+ reg = kcontrol->private_value & 0xff;
-static int snd_ca0106_volume_get_feedback(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = 1;
- int reg = CAPTURE_CONTROL;
- return snd_ca0106_volume_get(kcontrol, ucontrol, reg, channel_id);
-}
-
-static int snd_ca0106_volume_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol, int reg, int channel_id)
-{
- ca0106_t *emu = snd_kcontrol_chip(kcontrol);
- unsigned int value;
- //value = snd_ca0106_ptr_read(emu, reg, channel_id);
- //value = value & 0xffff;
- value = ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16);
- value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) );
- snd_ca0106_ptr_write(emu, reg, channel_id, value);
- return 1;
-}
-static int snd_ca0106_volume_put_spdif_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_FRONT_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_CENTER_LFE_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_UNKNOWN_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_spdif_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_REAR_CHANNEL;
- int reg = PLAYBACK_VOLUME1;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_analog_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_FRONT_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_CENTER_LFE_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_analog_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_UNKNOWN_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-static int snd_ca0106_volume_put_analog_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = CONTROL_REAR_CHANNEL;
- int reg = PLAYBACK_VOLUME2;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-
-static int snd_ca0106_volume_put_feedback(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int channel_id = 1;
- int reg = CAPTURE_CONTROL;
- return snd_ca0106_volume_put(kcontrol, ucontrol, reg, channel_id);
-}
-
-static snd_kcontrol_new_t snd_ca0106_volume_control_analog_front =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Front Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_analog_front,
- .put = snd_ca0106_volume_put_analog_front
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .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
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Side Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_analog_unknown,
- .put = snd_ca0106_volume_put_analog_unknown
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_analog_rear =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Rear Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_analog_rear,
- .put = snd_ca0106_volume_put_analog_rear
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_front =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Front Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_spdif_front,
- .put = snd_ca0106_volume_put_spdif_front
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_center_lfe =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .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
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_unknown =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Unknown Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_spdif_unknown,
- .put = snd_ca0106_volume_put_spdif_unknown
-};
-static snd_kcontrol_new_t snd_ca0106_volume_control_spdif_rear =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "SPDIF Rear Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_spdif_rear,
- .put = snd_ca0106_volume_put_spdif_rear
-};
-
-static snd_kcontrol_new_t snd_ca0106_volume_control_feedback =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "CAPTURE feedback Playback Volume",
- .info = snd_ca0106_volume_info,
- .get = snd_ca0106_volume_get_feedback,
- .put = snd_ca0106_volume_put_feedback
+ oval = snd_ca0106_ptr_read(emu, reg, channel_id);
+ nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
+ ((0xff - ucontrol->value.integer.value[1]) << 16);
+ nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
+ ((0xff - ucontrol->value.integer.value[1]) );
+ if (oval == nval)
+ return 0;
+ snd_ca0106_ptr_write(emu, reg, channel_id, nval);
+ return 1;
+}
+
+#define CA_VOLUME(xname,chid,reg) \
+{ \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_ca0106_volume_info, \
+ .get = snd_ca0106_volume_get, \
+ .put = snd_ca0106_volume_put, \
+ .private_value = ((chid) << 8) | (reg) \
+}
+
+
+static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
+ CA_VOLUME("Analog Front Playback Volume",
+ CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
+ CA_VOLUME("Analog Rear Playback Volume",
+ CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
+ CA_VOLUME("Analog Center/LFE Playback Volume",
+ CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
+ CA_VOLUME("Analog Side Playback Volume",
+ CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
+
+ CA_VOLUME("IEC958 Front Playback Volume",
+ CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
+ CA_VOLUME("IEC958 Rear Playback Volume",
+ CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
+ CA_VOLUME("IEC958 Center/LFE Playback Volume",
+ CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
+ CA_VOLUME("IEC958 Unknown Playback Volume",
+ CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
+
+ CA_VOLUME("CAPTURE feedback Playback Volume",
+ 1, CAPTURE_CONTROL),
+
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+ .count = 4,
+ .info = snd_ca0106_spdif_info,
+ .get = snd_ca0106_spdif_get_mask
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "IEC958 Playback Switch",
+ .info = snd_ca0106_shared_spdif_info,
+ .get = snd_ca0106_shared_spdif_get,
+ .put = snd_ca0106_shared_spdif_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = snd_ca0106_capture_source_info,
+ .get = snd_ca0106_capture_source_get,
+ .put = snd_ca0106_capture_source_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .count = 4,
+ .info = snd_ca0106_spdif_info,
+ .get = snd_ca0106_spdif_get,
+ .put = snd_ca0106_spdif_put
+ },
};
-
-static int remove_ctl(snd_card_t *card, const char *name)
+static int __devinit remove_ctl(struct snd_card *card, const char *name)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
strcpy(id.name, name);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(card, &id);
}
-static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
+static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
{
- snd_ctl_elem_id_t sid;
+ struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
/* FIXME: strcpy is bad. */
strcpy(sid.name, name);
@@ -573,9 +412,9 @@ static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
return snd_ctl_find_id(card, &sid);
}
-static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
+static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
{
- snd_kcontrol_t *kctl = ctl_find(card, src);
+ struct snd_kcontrol *kctl = ctl_find(card, src);
if (kctl) {
strcpy(kctl->id.name, dst);
return 0;
@@ -583,11 +422,10 @@ static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
return -ENOENT;
}
-int __devinit snd_ca0106_mixer(ca0106_t *emu)
+int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
{
- int err;
- snd_kcontrol_t *kctl;
- snd_card_t *card = emu->card;
+ int i, err;
+ struct snd_card *card = emu->card;
char **c;
static char *ca0106_remove_ctls[] = {
"Master Mono Playback Switch",
@@ -627,70 +465,22 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu)
NULL
};
#if 1
- for (c=ca0106_remove_ctls; *c; c++)
+ for (c = ca0106_remove_ctls; *c; c++)
remove_ctl(card, *c);
- for (c=ca0106_rename_ctls; *c; c += 2)
+ for (c = ca0106_rename_ctls; *c; c += 2)
rename_ctl(card, c[0], c[1]);
#endif
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_front, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_rear, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_center_lfe, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_analog_unknown, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_front, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_rear, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_center_lfe, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_spdif_unknown, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_volume_control_feedback, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_mask_control, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_shared_spdif, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_ca0106_capture_source, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
+ for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) {
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu));
+ if (err < 0)
+ return err;
+ }
if (emu->details->i2c_adc == 1) {
- if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
+ err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
+ if (err < 0)
return err;
}
- if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
return 0;
}
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index 1c9cc821d1b9..63757273bfb7 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -77,6 +77,8 @@
#include "ca0106.h"
+#ifdef CONFIG_PROC_FS
+
struct snd_ca0106_category_str {
int val;
const char *name;
@@ -97,7 +99,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = {
};
-static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
+static void snd_ca0106_proc_dump_iec958( struct snd_info_buffer *buffer, u32 value)
{
int i;
u32 status[4];
@@ -271,10 +273,10 @@ static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
}
}
-static void snd_ca0106_proc_iec958(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_iec958(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
u32 value;
value = snd_ca0106_ptr_read(emu, SAMPLE_RATE_TRACKER_STATUS, 0);
@@ -293,10 +295,10 @@ static void snd_ca0106_proc_iec958(snd_info_entry_t *entry,
snd_iprintf(buffer, "\n");
}
-static void snd_ca0106_proc_reg_write32(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned long flags;
char line[64];
u32 reg, val;
@@ -311,10 +313,10 @@ static void snd_ca0106_proc_reg_write32(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_read32(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_read32(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned long value;
unsigned long flags;
int i;
@@ -327,10 +329,10 @@ static void snd_ca0106_proc_reg_read32(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_read16(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_read16(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned int value;
unsigned long flags;
int i;
@@ -343,10 +345,10 @@ static void snd_ca0106_proc_reg_read16(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_read8(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_read8(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned int value;
unsigned long flags;
int i;
@@ -359,10 +361,10 @@ static void snd_ca0106_proc_reg_read8(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_read1(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_read1(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned long value;
int i,j;
@@ -377,10 +379,10 @@ static void snd_ca0106_proc_reg_read1(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_read2(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_read2(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
unsigned long value;
int i,j;
@@ -395,10 +397,10 @@ static void snd_ca0106_proc_reg_read2(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_reg_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
char line[64];
unsigned int reg, channel_id , val;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
@@ -409,10 +411,10 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry,
}
}
-static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ca0106_proc_i2c_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ca0106_t *emu = entry->private_data;
+ struct snd_ca0106 *emu = entry->private_data;
char line[64];
unsigned int reg, val;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
@@ -424,9 +426,9 @@ static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry,
}
}
-int __devinit snd_ca0106_proc_init(ca0106_t * emu)
+int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if(! snd_card_proc_new(emu->card, "iec958", &entry))
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_iec958);
@@ -459,3 +461,4 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
return 0;
}
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/ca0106/ca_midi.c b/sound/pci/ca0106/ca_midi.c
index 2e08b27b8349..2e6eab1f1189 100644
--- a/sound/pci/ca0106/ca_midi.c
+++ b/sound/pci/ca0106/ca_midi.c
@@ -40,18 +40,20 @@
#define ca_midi_input_avail(midi) (!(ca_midi_read_stat(midi) & midi->input_avail))
#define ca_midi_output_ready(midi) (!(ca_midi_read_stat(midi) & midi->output_ready))
-static void ca_midi_clear_rx(ca_midi_t *midi)
+static void ca_midi_clear_rx(struct snd_ca_midi *midi)
{
int timeout = 100000;
for (; timeout > 0 && ca_midi_input_avail(midi); timeout--)
ca_midi_read_data(midi);
#ifdef CONFIG_SND_DEBUG
if (timeout <= 0)
- snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n", ca_midi_read_stat(midi));
+ snd_printk(KERN_ERR "ca_midi_clear_rx: timeout (status = 0x%x)\n",
+ ca_midi_read_stat(midi));
#endif
}
-static void ca_midi_interrupt(ca_midi_t *midi, unsigned int status) {
+static void ca_midi_interrupt(struct snd_ca_midi *midi, unsigned int status)
+{
unsigned char byte;
if (midi->rmidi == NULL) {
@@ -86,7 +88,7 @@ static void ca_midi_interrupt(ca_midi_t *midi, unsigned int status) {
}
-static void ca_midi_cmd(ca_midi_t *midi, unsigned char cmd, int ack)
+static void ca_midi_cmd(struct snd_ca_midi *midi, unsigned char cmd, int ack)
{
unsigned long flags;
int timeout, ok;
@@ -119,9 +121,9 @@ static void ca_midi_cmd(ca_midi_t *midi, unsigned char cmd, int ack)
ca_midi_read_data(midi));
}
-static int ca_midi_input_open(snd_rawmidi_substream_t * substream)
+static int ca_midi_input_open(struct snd_rawmidi_substream *substream)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
unsigned long flags;
snd_assert(midi->dev_id, return -ENXIO);
@@ -138,9 +140,9 @@ static int ca_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int ca_midi_output_open(snd_rawmidi_substream_t * substream)
+static int ca_midi_output_open(struct snd_rawmidi_substream *substream)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
unsigned long flags;
snd_assert(midi->dev_id, return -ENXIO);
@@ -157,9 +159,9 @@ static int ca_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int ca_midi_input_close(snd_rawmidi_substream_t * substream)
+static int ca_midi_input_close(struct snd_rawmidi_substream *substream)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
unsigned long flags;
snd_assert(midi->dev_id, return -ENXIO);
@@ -176,9 +178,9 @@ static int ca_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int ca_midi_output_close(snd_rawmidi_substream_t * substream)
+static int ca_midi_output_close(struct snd_rawmidi_substream *substream)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
unsigned long flags;
snd_assert(midi->dev_id, return -ENXIO);
@@ -197,9 +199,9 @@ static int ca_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void ca_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void ca_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
snd_assert(midi->dev_id, return);
if (up) {
@@ -209,9 +211,9 @@ static void ca_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
}
}
-static void ca_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void ca_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- ca_midi_t *midi = (ca_midi_t *)substream->rmidi->private_data;
+ struct snd_ca_midi *midi = substream->rmidi->private_data;
unsigned long flags;
snd_assert(midi->dev_id, return);
@@ -246,21 +248,22 @@ static void ca_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
}
}
-static snd_rawmidi_ops_t ca_midi_output =
+static struct snd_rawmidi_ops ca_midi_output =
{
.open = ca_midi_output_open,
.close = ca_midi_output_close,
.trigger = ca_midi_output_trigger,
};
-static snd_rawmidi_ops_t ca_midi_input =
+static struct snd_rawmidi_ops ca_midi_input =
{
.open = ca_midi_input_open,
.close = ca_midi_input_close,
.trigger = ca_midi_input_trigger,
};
-static void ca_midi_free(ca_midi_t *midi) {
+static void ca_midi_free(struct snd_ca_midi *midi)
+{
midi->interrupt = NULL;
midi->interrupt_enable = NULL;
midi->interrupt_disable = NULL;
@@ -271,14 +274,14 @@ static void ca_midi_free(ca_midi_t *midi) {
midi->rmidi = NULL;
}
-static void ca_rmidi_free(snd_rawmidi_t *rmidi)
+static void ca_rmidi_free(struct snd_rawmidi *rmidi)
{
- ca_midi_free((ca_midi_t *)rmidi->private_data);
+ ca_midi_free(rmidi->private_data);
}
-int __devinit ca_midi_init(void *dev_id, ca_midi_t *midi, int device, char *name)
+int __devinit ca_midi_init(void *dev_id, struct snd_ca_midi *midi, int device, char *name)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if ((err = snd_rawmidi_new(midi->get_dev_id_card(midi->dev_id), name, device, 1, 1, &rmidi)) < 0)
diff --git a/sound/pci/ca0106/ca_midi.h b/sound/pci/ca0106/ca_midi.h
index b452cec2bf57..b72c0933bd22 100644
--- a/sound/pci/ca0106/ca_midi.h
+++ b/sound/pci/ca0106/ca_midi.h
@@ -29,12 +29,11 @@
#define CA_MIDI_MODE_INPUT MPU401_MODE_INPUT
#define CA_MIDI_MODE_OUTPUT MPU401_MODE_OUTPUT
-typedef struct ca_midi ca_midi_t;
-struct ca_midi {
+struct snd_ca_midi {
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *substream_input;
- snd_rawmidi_substream_t *substream_output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *substream_input;
+ struct snd_rawmidi_substream *substream_output;
void *dev_id;
@@ -52,18 +51,16 @@ struct ca_midi {
int input_avail, output_ready;
int ack, reset, enter_uart;
- void (*interrupt)(ca_midi_t *midi, unsigned int status);
- void (*interrupt_enable)(ca_midi_t *midi, int intr);
- void (*interrupt_disable)(ca_midi_t *midi, int intr);
+ void (*interrupt)(struct snd_ca_midi *midi, unsigned int status);
+ void (*interrupt_enable)(struct snd_ca_midi *midi, int intr);
+ void (*interrupt_disable)(struct snd_ca_midi *midi, int intr);
- unsigned char (*read)(ca_midi_t *midi, int idx);
- void (*write)(ca_midi_t *midi, int data, int idx);
+ unsigned char (*read)(struct snd_ca_midi *midi, int idx);
+ void (*write)(struct snd_ca_midi *midi, int data, int idx);
/* get info from dev_id */
- snd_card_t *(*get_dev_id_card)(void *dev_id);
+ struct snd_card *(*get_dev_id_card)(void *dev_id);
int (*get_dev_id_port)(void *dev_id);
};
-int __devinit ca_midi_init(void *card, ca_midi_t *midi, int device, char *name);
-
-
+int ca_midi_init(void *card, struct snd_ca_midi *midi, int device, char *name);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index db605373b3bc..c03b0a0a3b27 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -269,6 +269,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_MICGAINZ 0x01 /* mic boost */
#define CM_MICGAINZ_SHIFT 0
+#define CM_REG_MIXER3 0x24
#define CM_REG_AUX_VOL 0x26
#define CM_VAUXL_MASK 0xf0
#define CM_VAUXR_MASK 0x0f
@@ -324,6 +325,7 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#define CM_REG_CH0_FRAME2 0x84
#define CM_REG_CH1_FRAME1 0x88 /* 0-15: count of samples at bus master; buffer size */
#define CM_REG_CH1_FRAME2 0x8C /* 16-31: count of samples at codec; fragment size */
+#define CM_REG_EXT_MISC 0x90
#define CM_REG_MISC_CTRL_8768 0x92 /* reg. name the same as 0x18 */
#define CM_CHB3D8C 0x20 /* 7.1 channels support */
#define CM_SPD32FMT 0x10 /* SPDIF/IN 32k */
@@ -378,11 +380,8 @@ MODULE_PARM_DESC(joystick_port, "Joystick port address.");
* driver data
*/
-typedef struct snd_stru_cmipci cmipci_t;
-typedef struct snd_stru_cmipci_pcm cmipci_pcm_t;
-
-struct snd_stru_cmipci_pcm {
- snd_pcm_substream_t *substream;
+struct cmipci_pcm {
+ struct snd_pcm_substream *substream;
int running; /* dac/adc running? */
unsigned int dma_size; /* in frames */
unsigned int period_size; /* in frames */
@@ -408,8 +407,8 @@ static const struct cmipci_mixer_auto_switches cm_saved_mixer[] = {
};
#define CM_SAVED_MIXERS ARRAY_SIZE(cm_saved_mixer)
-struct snd_stru_cmipci {
- snd_card_t *card;
+struct cmipci {
+ struct snd_card *card;
struct pci_dev *pci;
unsigned int device; /* device ID */
@@ -418,9 +417,9 @@ struct snd_stru_cmipci {
unsigned long iobase;
unsigned int ctrl; /* FUNCTRL0 current value */
- snd_pcm_t *pcm; /* DAC/ADC PCM */
- snd_pcm_t *pcm2; /* 2nd DAC */
- snd_pcm_t *pcm_spdif; /* SPDIF */
+ struct snd_pcm *pcm; /* DAC/ADC PCM */
+ struct snd_pcm *pcm2; /* 2nd DAC */
+ struct snd_pcm *pcm_spdif; /* SPDIF */
int chip_version;
int max_channels;
@@ -437,63 +436,68 @@ struct snd_stru_cmipci {
unsigned int dig_status;
unsigned int dig_pcm_status;
- snd_pcm_hardware_t *hw_info[3]; /* for playbacks */
+ struct snd_pcm_hardware *hw_info[3]; /* for playbacks */
int opened[2]; /* open mode */
struct semaphore open_mutex;
unsigned int mixer_insensitive: 1;
- snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS];
+ struct snd_kcontrol *mixer_res_ctl[CM_SAVED_MIXERS];
int mixer_res_status[CM_SAVED_MIXERS];
- cmipci_pcm_t channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */
+ struct cmipci_pcm channel[2]; /* ch0 - DAC, ch1 - ADC or 2nd DAC */
/* external MIDI */
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
#endif
spinlock_t reg_lock;
+
+#ifdef CONFIG_PM
+ unsigned int saved_regs[0x20];
+ unsigned char saved_mixers[0x20];
+#endif
};
/* read/write operations for dword register */
-static inline void snd_cmipci_write(cmipci_t *cm, unsigned int cmd, unsigned int data)
+static inline void snd_cmipci_write(struct cmipci *cm, unsigned int cmd, unsigned int data)
{
outl(data, cm->iobase + cmd);
}
-static inline unsigned int snd_cmipci_read(cmipci_t *cm, unsigned int cmd)
+static inline unsigned int snd_cmipci_read(struct cmipci *cm, unsigned int cmd)
{
return inl(cm->iobase + cmd);
}
/* read/write operations for word register */
-static inline void snd_cmipci_write_w(cmipci_t *cm, unsigned int cmd, unsigned short data)
+static inline void snd_cmipci_write_w(struct cmipci *cm, unsigned int cmd, unsigned short data)
{
outw(data, cm->iobase + cmd);
}
-static inline unsigned short snd_cmipci_read_w(cmipci_t *cm, unsigned int cmd)
+static inline unsigned short snd_cmipci_read_w(struct cmipci *cm, unsigned int cmd)
{
return inw(cm->iobase + cmd);
}
/* read/write operations for byte register */
-static inline void snd_cmipci_write_b(cmipci_t *cm, unsigned int cmd, unsigned char data)
+static inline void snd_cmipci_write_b(struct cmipci *cm, unsigned int cmd, unsigned char data)
{
outb(data, cm->iobase + cmd);
}
-static inline unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd)
+static inline unsigned char snd_cmipci_read_b(struct cmipci *cm, unsigned int cmd)
{
return inb(cm->iobase + cmd);
}
/* bit operations for dword register */
-static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_set_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag)
{
unsigned int val, oval;
val = oval = inl(cm->iobase + cmd);
@@ -504,7 +508,7 @@ static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
return 1;
}
-static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_clear_bit(struct cmipci *cm, unsigned int cmd, unsigned int flag)
{
unsigned int val, oval;
val = oval = inl(cm->iobase + cmd);
@@ -516,7 +520,7 @@ static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int fla
}
/* bit operations for byte register */
-static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_set_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag)
{
unsigned char val, oval;
val = oval = inb(cm->iobase + cmd);
@@ -527,7 +531,7 @@ static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char fl
return 1;
}
-static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_clear_bit_b(struct cmipci *cm, unsigned int cmd, unsigned char flag)
{
unsigned char val, oval;
val = oval = inb(cm->iobase + cmd);
@@ -608,7 +612,7 @@ out:
* at the register CM_REG_FUNCTRL1 (0x04).
* Problem: other ways are also possible (any information about that?)
*/
-static void snd_cmipci_set_pll(cmipci_t *cm, unsigned int rate, unsigned int slot)
+static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned int slot)
{
unsigned int reg = CM_REG_PLL + slot;
/*
@@ -626,16 +630,16 @@ static void snd_cmipci_set_pll(cmipci_t *cm, unsigned int rate, unsigned int slo
}
#endif /* USE_VAR48KRATE */
-static int snd_cmipci_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cmipci_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_cmipci_playback2_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
if (params_channels(hw_params) > 2) {
down(&cm->open_mutex);
if (cm->opened[CM_CH_PLAY]) {
@@ -649,7 +653,7 @@ static int snd_cmipci_playback2_hw_params(snd_pcm_substream_t * substream,
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static void snd_cmipci_ch_reset(cmipci_t *cm, int ch)
+static void snd_cmipci_ch_reset(struct cmipci *cm, int ch)
{
int reset = CM_RST_CH0 << (cm->channel[ch].ch);
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl | reset);
@@ -657,7 +661,7 @@ static void snd_cmipci_ch_reset(cmipci_t *cm, int ch)
udelay(10);
}
-static int snd_cmipci_hw_free(snd_pcm_substream_t * substream)
+static int snd_cmipci_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
@@ -667,23 +671,23 @@ static int snd_cmipci_hw_free(snd_pcm_substream_t * substream)
*/
static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8};
-static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = {
.count = 3,
.list = hw_channels,
.mask = 0,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_channels_6 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = {
.count = 5,
.list = hw_channels,
.mask = 0,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_channels_8 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = {
.count = 6,
.list = hw_channels,
.mask = 0,
};
-static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
+static int set_dac_channels(struct cmipci *cm, struct cmipci_pcm *rec, int channels)
{
if (channels > 2) {
if (! cm->can_multi_ch)
@@ -737,11 +741,11 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
* prepare playback/capture channel
* channel to be used must have been set in rec->ch.
*/
-static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
- snd_pcm_substream_t *substream)
+static int snd_cmipci_pcm_prepare(struct cmipci *cm, struct cmipci_pcm *rec,
+ struct snd_pcm_substream *substream)
{
unsigned int reg, freq, val;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
rec->fmt = 0;
rec->shift = 0;
@@ -820,8 +824,8 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
/*
* PCM trigger/stop
*/
-static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec,
- snd_pcm_substream_t *substream, int cmd)
+static int snd_cmipci_pcm_trigger(struct cmipci *cm, struct cmipci_pcm *rec,
+ struct snd_pcm_substream *substream, int cmd)
{
unsigned int inthld, chen, reset, pause;
int result = 0;
@@ -852,10 +856,12 @@ static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec,
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl & ~reset);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
cm->ctrl |= pause;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
cm->ctrl &= ~pause;
snd_cmipci_write(cm, CM_REG_FUNCTRL0, cm->ctrl);
break;
@@ -870,8 +876,8 @@ static int snd_cmipci_pcm_trigger(cmipci_t *cm, cmipci_pcm_t *rec,
/*
* return the current pointer
*/
-static snd_pcm_uframes_t snd_cmipci_pcm_pointer(cmipci_t *cm, cmipci_pcm_t *rec,
- snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_cmipci_pcm_pointer(struct cmipci *cm, struct cmipci_pcm *rec,
+ struct snd_pcm_substream *substream)
{
size_t ptr;
unsigned int reg;
@@ -895,16 +901,16 @@ static snd_pcm_uframes_t snd_cmipci_pcm_pointer(cmipci_t *cm, cmipci_pcm_t *rec,
* playback
*/
-static int snd_cmipci_playback_trigger(snd_pcm_substream_t *substream,
+static int snd_cmipci_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_PLAY], substream, cmd);
}
-static snd_pcm_uframes_t snd_cmipci_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_cmipci_playback_pointer(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_PLAY], substream);
}
@@ -914,16 +920,16 @@ static snd_pcm_uframes_t snd_cmipci_playback_pointer(snd_pcm_substream_t *substr
* capture
*/
-static int snd_cmipci_capture_trigger(snd_pcm_substream_t *substream,
+static int snd_cmipci_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_trigger(cm, &cm->channel[CM_CH_CAPT], substream, cmd);
}
-static snd_pcm_uframes_t snd_cmipci_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_cmipci_capture_pointer(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_pointer(cm, &cm->channel[CM_CH_CAPT], substream);
}
@@ -932,18 +938,18 @@ static snd_pcm_uframes_t snd_cmipci_capture_pointer(snd_pcm_substream_t *substre
* hw preparation for spdif
*/
-static int snd_cmipci_spdif_default_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_spdif_default_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cmipci_spdif_default_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int i;
spin_lock_irq(&chip->reg_lock);
@@ -953,10 +959,10 @@ static int snd_cmipci_spdif_default_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cmipci_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int i, change;
unsigned int val;
@@ -970,7 +976,7 @@ static int snd_cmipci_spdif_default_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_cmipci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -979,16 +985,16 @@ static snd_kcontrol_new_t snd_cmipci_spdif_default __devinitdata =
.put = snd_cmipci_spdif_default_put
};
-static int snd_cmipci_spdif_mask_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cmipci_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -997,7 +1003,7 @@ static int snd_cmipci_spdif_mask_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_cmipci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_mask __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1006,18 +1012,18 @@ static snd_kcontrol_new_t snd_cmipci_spdif_mask __devinitdata =
.get = snd_cmipci_spdif_mask_get,
};
-static int snd_cmipci_spdif_stream_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_spdif_stream_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cmipci_spdif_stream_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int i;
spin_lock_irq(&chip->reg_lock);
@@ -1027,10 +1033,10 @@ static int snd_cmipci_spdif_stream_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cmipci_spdif_stream_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int i, change;
unsigned int val;
@@ -1044,7 +1050,7 @@ static int snd_cmipci_spdif_stream_put(snd_kcontrol_t *kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_cmipci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_spdif_stream __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1058,17 +1064,17 @@ static snd_kcontrol_new_t snd_cmipci_spdif_stream __devinitdata =
*/
/* save mixer setting and mute for AC3 playback */
-static int save_mixer_state(cmipci_t *cm)
+static int save_mixer_state(struct cmipci *cm)
{
if (! cm->mixer_insensitive) {
- snd_ctl_elem_value_t *val;
+ struct snd_ctl_elem_value *val;
unsigned int i;
val = kmalloc(sizeof(*val), GFP_ATOMIC);
if (!val)
return -ENOMEM;
for (i = 0; i < CM_SAVED_MIXERS; i++) {
- snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
+ struct snd_kcontrol *ctl = cm->mixer_res_ctl[i];
if (ctl) {
int event;
memset(val, 0, sizeof(*val));
@@ -1092,10 +1098,10 @@ static int save_mixer_state(cmipci_t *cm)
/* restore the previously saved mixer status */
-static void restore_mixer_state(cmipci_t *cm)
+static void restore_mixer_state(struct cmipci *cm)
{
if (cm->mixer_insensitive) {
- snd_ctl_elem_value_t *val;
+ struct snd_ctl_elem_value *val;
unsigned int i;
val = kmalloc(sizeof(*val), GFP_KERNEL);
@@ -1104,7 +1110,7 @@ static void restore_mixer_state(cmipci_t *cm)
cm->mixer_insensitive = 0; /* at first clear this;
otherwise the changes will be ignored */
for (i = 0; i < CM_SAVED_MIXERS; i++) {
- snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
+ struct snd_kcontrol *ctl = cm->mixer_res_ctl[i];
if (ctl) {
int event;
@@ -1125,7 +1131,7 @@ static void restore_mixer_state(cmipci_t *cm)
}
/* spinlock held! */
-static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int rate)
+static void setup_ac3(struct cmipci *cm, struct snd_pcm_substream *subs, int do_ac3, int rate)
{
if (do_ac3) {
/* AC3EN for 037 */
@@ -1172,7 +1178,7 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r
}
}
-static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
+static int setup_spdif_playback(struct cmipci *cm, struct snd_pcm_substream *subs, int up, int do_ac3)
{
int rate, err;
@@ -1214,9 +1220,9 @@ static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up,
*/
/* playback - enable spdif only on the certain condition */
-static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback_prepare(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
int rate = substream->runtime->rate;
int err, do_spdif, do_ac3 = 0;
@@ -1231,9 +1237,9 @@ static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream)
}
/* playback (via device #2) - enable spdif always */
-static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback_spdif_prepare(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
int err, do_ac3;
if (cm->can_ac3_hw)
@@ -1245,25 +1251,25 @@ static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream)
return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
}
-static int snd_cmipci_playback_hw_free(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
setup_spdif_playback(cm, substream, 0, 0);
restore_mixer_state(cm);
return snd_cmipci_hw_free(substream);
}
/* capture */
-static int snd_cmipci_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_cmipci_capture_prepare(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream);
}
/* capture with spdif (via device #2) */
-static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream)
+static int snd_cmipci_capture_spdif_prepare(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
spin_lock_irq(&cm->reg_lock);
snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
@@ -1272,9 +1278,9 @@ static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream)
return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream);
}
-static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs)
+static int snd_cmipci_capture_spdif_hw_free(struct snd_pcm_substream *subs)
{
- cmipci_t *cm = snd_pcm_substream_chip(subs);
+ struct cmipci *cm = snd_pcm_substream_chip(subs);
spin_lock_irq(&cm->reg_lock);
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
@@ -1289,7 +1295,7 @@ static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs)
*/
static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- cmipci_t *cm = dev_id;
+ struct cmipci *cm = dev_id;
unsigned int status, mask = 0;
/* fastpath out, to ease interrupt sharing */
@@ -1324,11 +1330,11 @@ static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *r
*/
/* playback on channel A */
-static snd_pcm_hardware_t snd_cmipci_playback =
+static struct snd_pcm_hardware snd_cmipci_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5512,
@@ -1344,11 +1350,11 @@ static snd_pcm_hardware_t snd_cmipci_playback =
};
/* capture on channel B */
-static snd_pcm_hardware_t snd_cmipci_capture =
+static struct snd_pcm_hardware snd_cmipci_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5512,
@@ -1364,11 +1370,11 @@ static snd_pcm_hardware_t snd_cmipci_capture =
};
/* playback on channel B - stereo 16bit only? */
-static snd_pcm_hardware_t snd_cmipci_playback2 =
+static struct snd_pcm_hardware snd_cmipci_playback2 =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000,
.rate_min = 5512,
@@ -1384,11 +1390,11 @@ static snd_pcm_hardware_t snd_cmipci_playback2 =
};
/* spdif playback on channel A */
-static snd_pcm_hardware_t snd_cmipci_playback_spdif =
+static struct snd_pcm_hardware snd_cmipci_playback_spdif =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100,
@@ -1404,11 +1410,11 @@ static snd_pcm_hardware_t snd_cmipci_playback_spdif =
};
/* spdif playback on channel A (32bit, IEC958 subframes) */
-static snd_pcm_hardware_t snd_cmipci_playback_iec958_subframe =
+static struct snd_pcm_hardware snd_cmipci_playback_iec958_subframe =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100,
@@ -1424,11 +1430,11 @@ static snd_pcm_hardware_t snd_cmipci_playback_iec958_subframe =
};
/* spdif capture on channel B */
-static snd_pcm_hardware_t snd_cmipci_capture_spdif =
+static struct snd_pcm_hardware snd_cmipci_capture_spdif =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100,
@@ -1446,7 +1452,7 @@ static snd_pcm_hardware_t snd_cmipci_capture_spdif =
/*
* check device open/close
*/
-static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
+static int open_device_check(struct cmipci *cm, int mode, struct snd_pcm_substream *subs)
{
int ch = mode & CM_OPEN_CH_MASK;
@@ -1473,7 +1479,7 @@ static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
return 0;
}
-static void close_device_check(cmipci_t *cm, int mode)
+static void close_device_check(struct cmipci *cm, int mode)
{
int ch = mode & CM_OPEN_CH_MASK;
@@ -1499,10 +1505,10 @@ static void close_device_check(cmipci_t *cm, int mode)
/*
*/
-static int snd_cmipci_playback_open(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback_open(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0)
@@ -1514,10 +1520,10 @@ static int snd_cmipci_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cmipci_capture_open(snd_pcm_substream_t *substream)
+static int snd_cmipci_capture_open(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0)
@@ -1531,10 +1537,10 @@ static int snd_cmipci_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback2_open(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = open_device_check(cm, CM_OPEN_PLAYBACK2, substream)) < 0) /* use channel B */
@@ -1557,10 +1563,10 @@ static int snd_cmipci_playback2_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream)
+static int snd_cmipci_playback_spdif_open(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = open_device_check(cm, CM_OPEN_SPDIF_PLAYBACK, substream)) < 0) /* use channel A */
@@ -1577,10 +1583,10 @@ static int snd_cmipci_playback_spdif_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cmipci_capture_spdif_open(snd_pcm_substream_t * substream)
+static int snd_cmipci_capture_spdif_open(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = open_device_check(cm, CM_OPEN_SPDIF_CAPTURE, substream)) < 0) /* use channel B */
@@ -1594,38 +1600,38 @@ static int snd_cmipci_capture_spdif_open(snd_pcm_substream_t * substream)
/*
*/
-static int snd_cmipci_playback_close(snd_pcm_substream_t * substream)
+static int snd_cmipci_playback_close(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
close_device_check(cm, CM_OPEN_PLAYBACK);
return 0;
}
-static int snd_cmipci_capture_close(snd_pcm_substream_t * substream)
+static int snd_cmipci_capture_close(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
close_device_check(cm, CM_OPEN_CAPTURE);
return 0;
}
-static int snd_cmipci_playback2_close(snd_pcm_substream_t * substream)
+static int snd_cmipci_playback2_close(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
close_device_check(cm, CM_OPEN_PLAYBACK2);
close_device_check(cm, CM_OPEN_PLAYBACK_MULTI);
return 0;
}
-static int snd_cmipci_playback_spdif_close(snd_pcm_substream_t * substream)
+static int snd_cmipci_playback_spdif_close(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
close_device_check(cm, CM_OPEN_SPDIF_PLAYBACK);
return 0;
}
-static int snd_cmipci_capture_spdif_close(snd_pcm_substream_t * substream)
+static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream)
{
- cmipci_t *cm = snd_pcm_substream_chip(substream);
+ struct cmipci *cm = snd_pcm_substream_chip(substream);
close_device_check(cm, CM_OPEN_SPDIF_CAPTURE);
return 0;
}
@@ -1634,7 +1640,7 @@ static int snd_cmipci_capture_spdif_close(snd_pcm_substream_t * substream)
/*
*/
-static snd_pcm_ops_t snd_cmipci_playback_ops = {
+static struct snd_pcm_ops snd_cmipci_playback_ops = {
.open = snd_cmipci_playback_open,
.close = snd_cmipci_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1645,7 +1651,7 @@ static snd_pcm_ops_t snd_cmipci_playback_ops = {
.pointer = snd_cmipci_playback_pointer,
};
-static snd_pcm_ops_t snd_cmipci_capture_ops = {
+static struct snd_pcm_ops snd_cmipci_capture_ops = {
.open = snd_cmipci_capture_open,
.close = snd_cmipci_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1656,7 +1662,7 @@ static snd_pcm_ops_t snd_cmipci_capture_ops = {
.pointer = snd_cmipci_capture_pointer,
};
-static snd_pcm_ops_t snd_cmipci_playback2_ops = {
+static struct snd_pcm_ops snd_cmipci_playback2_ops = {
.open = snd_cmipci_playback2_open,
.close = snd_cmipci_playback2_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1667,7 +1673,7 @@ static snd_pcm_ops_t snd_cmipci_playback2_ops = {
.pointer = snd_cmipci_capture_pointer, /* channel B */
};
-static snd_pcm_ops_t snd_cmipci_playback_spdif_ops = {
+static struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
.open = snd_cmipci_playback_spdif_open,
.close = snd_cmipci_playback_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1678,7 +1684,7 @@ static snd_pcm_ops_t snd_cmipci_playback_spdif_ops = {
.pointer = snd_cmipci_playback_pointer,
};
-static snd_pcm_ops_t snd_cmipci_capture_spdif_ops = {
+static struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
.open = snd_cmipci_capture_spdif_open,
.close = snd_cmipci_capture_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1693,14 +1699,9 @@ static snd_pcm_ops_t snd_cmipci_capture_spdif_ops = {
/*
*/
-static void snd_cmipci_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_cmipci_pcm_new(struct cmipci *cm, int device)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm);
@@ -1711,7 +1712,6 @@ static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_ops);
pcm->private_data = cm;
- pcm->private_free = snd_cmipci_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "C-Media PCI DAC/ADC");
cm->pcm = pcm;
@@ -1722,9 +1722,9 @@ static int __devinit snd_cmipci_pcm_new(cmipci_t *cm, int device)
return 0;
}
-static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device)
+static int __devinit snd_cmipci_pcm2_new(struct cmipci *cm, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 0, &pcm);
@@ -1734,7 +1734,6 @@ static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cmipci_playback2_ops);
pcm->private_data = cm;
- pcm->private_free = snd_cmipci_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "C-Media PCI 2nd DAC");
cm->pcm2 = pcm;
@@ -1745,9 +1744,9 @@ static int __devinit snd_cmipci_pcm2_new(cmipci_t *cm, int device)
return 0;
}
-static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device)
+static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(cm->card, cm->card->driver, device, 1, 1, &pcm);
@@ -1758,7 +1757,6 @@ static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cmipci_capture_spdif_ops);
pcm->private_data = cm;
- pcm->private_free = snd_cmipci_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "C-Media PCI IEC958");
cm->pcm_spdif = pcm;
@@ -1778,13 +1776,13 @@ static int __devinit snd_cmipci_pcm_spdif_new(cmipci_t *cm, int device)
* - Output mute switches
*/
-static void snd_cmipci_mixer_write(cmipci_t *s, unsigned char idx, unsigned char data)
+static void snd_cmipci_mixer_write(struct cmipci *s, unsigned char idx, unsigned char data)
{
outb(idx, s->iobase + CM_REG_SB16_ADDR);
outb(data, s->iobase + CM_REG_SB16_DATA);
}
-static unsigned char snd_cmipci_mixer_read(cmipci_t *s, unsigned char idx)
+static unsigned char snd_cmipci_mixer_read(struct cmipci *s, unsigned char idx)
{
unsigned char v;
@@ -1796,13 +1794,13 @@ static unsigned char snd_cmipci_mixer_read(cmipci_t *s, unsigned char idx)
/*
* general mixer element
*/
-typedef struct cmipci_sb_reg {
+struct cmipci_sb_reg {
unsigned int left_reg, right_reg;
unsigned int left_shift, right_shift;
unsigned int mask;
unsigned int invert: 1;
unsigned int stereo: 1;
-} cmipci_sb_reg_t;
+};
#define COMPOSE_SB_REG(lreg,rreg,lshift,rshift,mask,invert,stereo) \
((lreg) | ((rreg) << 8) | (lshift << 16) | (rshift << 19) | (mask << 24) | (invert << 22) | (stereo << 23))
@@ -1819,7 +1817,7 @@ typedef struct cmipci_sb_reg {
#define CMIPCI_SB_SW_STEREO(xname,lshift,rshift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, lshift, rshift, 1, 0, 1)
#define CMIPCI_SB_SW_MONO(xname,shift) CMIPCI_DOUBLE(xname, SB_DSP4_OUTPUT_SW, SB_DSP4_OUTPUT_SW, shift, shift, 1, 0, 0)
-static void cmipci_sb_reg_decode(cmipci_sb_reg_t *r, unsigned long val)
+static void cmipci_sb_reg_decode(struct cmipci_sb_reg *r, unsigned long val)
{
r->left_reg = val & 0xff;
r->right_reg = (val >> 8) & 0xff;
@@ -1830,9 +1828,10 @@ static void cmipci_sb_reg_decode(cmipci_sb_reg_t *r, unsigned long val)
r->mask = (val >> 24) & 0xff;
}
-static int snd_cmipci_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cmipci_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- cmipci_sb_reg_t reg;
+ struct cmipci_sb_reg reg;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -1842,10 +1841,11 @@ static int snd_cmipci_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
int val;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
@@ -1864,10 +1864,11 @@ static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
int change;
int left, right, oleft, oright;
@@ -1912,7 +1913,8 @@ static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.private_value = COMPOSE_SB_REG(SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT, left_shift, right_shift, 1, 0, 1), \
}
-static int snd_cmipci_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cmipci_info_input_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 4;
@@ -1921,10 +1923,11 @@ static int snd_cmipci_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_get_input_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
int val1, val2;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
@@ -1939,10 +1942,11 @@ static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_put_input_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
int change;
int val1, val2, oval1, oval2;
@@ -1995,9 +1999,10 @@ static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
.private_value = COMPOSE_SB_REG(reg, reg, shift, shift, mask, 0, 0), \
}
-static int snd_cmipci_info_native_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_info_native_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- cmipci_sb_reg_t reg;
+ struct cmipci_sb_reg reg;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
uinfo->type = reg.mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -2008,10 +2013,11 @@ static int snd_cmipci_info_native_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
}
-static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_get_native_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
unsigned char oreg, val;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
@@ -2031,10 +2037,11 @@ static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
return 0;
}
-static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cmipci_put_native_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
- cmipci_sb_reg_t reg;
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci_sb_reg reg;
unsigned char oreg, nreg, val;
cmipci_sb_reg_decode(&reg, kcontrol->private_value);
@@ -2060,15 +2067,17 @@ static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
/*
* special case - check mixer sensitivity
*/
-static int snd_cmipci_get_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_get_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- //cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ //struct cmipci *cm = snd_kcontrol_chip(kcontrol);
return snd_cmipci_get_native_mixer(kcontrol, ucontrol);
}
-static int snd_cmipci_put_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
if (cm->mixer_insensitive) {
/* ignored */
return 0;
@@ -2077,7 +2086,7 @@ static int snd_cmipci_put_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_c
}
-static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = {
CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31),
@@ -2119,15 +2128,18 @@ static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = {
* other switches
*/
-typedef struct snd_cmipci_switch_args {
+struct cmipci_switch_args {
int reg; /* register index */
unsigned int mask; /* mask bits */
unsigned int mask_on; /* mask bits to turn on */
unsigned int is_byte: 1; /* byte access? */
- unsigned int ac3_sensitive: 1; /* access forbidden during non-audio operation? */
-} snd_cmipci_switch_args_t;
+ unsigned int ac3_sensitive: 1; /* access forbidden during
+ * non-audio operation?
+ */
+};
-static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_uswitch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2136,10 +2148,12 @@ static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
+static int _snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol,
+ struct cmipci_switch_args *args)
{
unsigned int val;
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&cm->reg_lock);
if (args->ac3_sensitive && cm->mixer_insensitive) {
@@ -2156,18 +2170,22 @@ static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_uswitch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_cmipci_switch_args_t *args = (snd_cmipci_switch_args_t*)kcontrol->private_value;
+ struct cmipci_switch_args *args;
+ args = (struct cmipci_switch_args *)kcontrol->private_value;
snd_assert(args != NULL, return -EINVAL);
return _snd_cmipci_uswitch_get(kcontrol, ucontrol, args);
}
-static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
+static int _snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol,
+ struct cmipci_switch_args *args)
{
unsigned int val;
int change;
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&cm->reg_lock);
if (args->ac3_sensitive && cm->mixer_insensitive) {
@@ -2195,15 +2213,17 @@ static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return change;
}
-static int snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_uswitch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_cmipci_switch_args_t *args = (snd_cmipci_switch_args_t*)kcontrol->private_value;
+ struct cmipci_switch_args *args;
+ args = (struct cmipci_switch_args *)kcontrol->private_value;
snd_assert(args != NULL, return -EINVAL);
return _snd_cmipci_uswitch_put(kcontrol, ucontrol, args);
}
#define DEFINE_SWITCH_ARG(sname, xreg, xmask, xmask_on, xis_byte, xac3) \
-static snd_cmipci_switch_args_t cmipci_switch_arg_##sname = { \
+static struct cmipci_switch_args cmipci_switch_arg_##sname = { \
.reg = xreg, \
.mask = xmask, \
.mask_on = xmask_on, \
@@ -2260,7 +2280,8 @@ DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0
* callbacks for spdif output switch
* needs toggle two registers..
*/
-static int snd_cmipci_spdout_enable_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdout_enable_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int changed;
changed = _snd_cmipci_uswitch_get(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable);
@@ -2268,9 +2289,10 @@ static int snd_cmipci_spdout_enable_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
return changed;
}
-static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_spdout_enable_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cmipci *chip = snd_kcontrol_chip(kcontrol);
int changed;
changed = _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdif_enable);
changed |= _snd_cmipci_uswitch_put(kcontrol, ucontrol, &cmipci_switch_arg_spdo2dac);
@@ -2288,10 +2310,10 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
}
-static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_line_in_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2302,7 +2324,7 @@ static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static inline unsigned int get_line_in_mode(cmipci_t *cm)
+static inline unsigned int get_line_in_mode(struct cmipci *cm)
{
unsigned int val;
if (cm->chip_version >= 39) {
@@ -2316,10 +2338,10 @@ static inline unsigned int get_line_in_mode(cmipci_t *cm)
return 0;
}
-static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_line_in_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&cm->reg_lock);
ucontrol->value.enumerated.item[0] = get_line_in_mode(cm);
@@ -2327,10 +2349,10 @@ static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_line_in_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
int change;
spin_lock_irq(&cm->reg_lock);
@@ -2346,8 +2368,8 @@ static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
return change;
}
-static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cmipci_mic_in_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "Mic-In", "Center/LFE Output" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2359,10 +2381,10 @@ static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_mic_in_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
/* same bit as spdi_phase */
spin_lock_irq(&cm->reg_lock);
ucontrol->value.enumerated.item[0] =
@@ -2371,10 +2393,10 @@ static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ struct cmipci *cm = snd_kcontrol_chip(kcontrol);
int change;
spin_lock_irq(&cm->reg_lock);
@@ -2387,7 +2409,7 @@ static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
}
/* both for CM8338/8738 */
-static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_mixer_switches[] __devinitdata = {
DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
{
.name = "Line-In Mode",
@@ -2399,11 +2421,11 @@ static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
};
/* for non-multichannel chips */
-static snd_kcontrol_new_t snd_cmipci_nomulti_switch __devinitdata =
+static struct snd_kcontrol_new snd_cmipci_nomulti_switch __devinitdata =
DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac);
/* only for CM8738 */
-static snd_kcontrol_new_t snd_cmipci_8738_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] __devinitdata = {
#if 0 /* controlled in pcm device */
DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in),
DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out),
@@ -2425,14 +2447,14 @@ static snd_kcontrol_new_t snd_cmipci_8738_mixer_switches[] __devinitdata = {
};
/* only for model 033/037 */
-static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] __devinitdata = {
DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1),
};
/* only for model 039 or later */
-static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] __devinitdata = {
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
{
@@ -2445,17 +2467,17 @@ static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
};
/* card control switches */
-static snd_kcontrol_new_t snd_cmipci_control_switches[] __devinitdata = {
+static struct snd_kcontrol_new snd_cmipci_control_switches[] __devinitdata = {
// DEFINE_CARD_SWITCH("Joystick", joystick), /* now module option */
DEFINE_CARD_SWITCH("Modem", modem),
};
-static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
+static int __devinit snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
{
- snd_card_t *card;
- snd_kcontrol_new_t *sw;
- snd_kcontrol_t *kctl;
+ struct snd_card *card;
+ struct snd_kcontrol_new *sw;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -2537,8 +2559,8 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
}
for (idx = 0; idx < CM_SAVED_MIXERS; idx++) {
- snd_ctl_elem_id_t id;
- snd_kcontrol_t *ctl;
+ struct snd_ctl_elem_id id;
+ struct snd_kcontrol *ctl;
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(id.name, cm_saved_mixer[idx].name);
@@ -2555,10 +2577,10 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
*/
#ifdef CONFIG_PROC_FS
-static void snd_cmipci_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+static void snd_cmipci_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cmipci_t *cm = entry->private_data;
+ struct cmipci *cm = entry->private_data;
int i;
snd_iprintf(buffer, "%s\n\n", cm->card->longname);
@@ -2574,15 +2596,15 @@ static void snd_cmipci_proc_read(snd_info_entry_t *entry,
}
}
-static void __devinit snd_cmipci_proc_init(cmipci_t *cm)
+static void __devinit snd_cmipci_proc_init(struct cmipci *cm)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(cm->card, "cmipci", &entry))
snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read);
}
#else /* !CONFIG_PROC_FS */
-static inline void snd_cmipci_proc_init(cmipci_t *cm) {}
+static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
#endif
@@ -2600,7 +2622,7 @@ static struct pci_device_id snd_cmipci_ids[] = {
* check chip version and capabilities
* driver name is modified according to the chip model
*/
-static void __devinit query_chip(cmipci_t *cm)
+static void __devinit query_chip(struct cmipci *cm)
{
unsigned int detect;
@@ -2653,7 +2675,7 @@ static void __devinit query_chip(cmipci_t *cm)
}
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
+static int __devinit snd_cmipci_create_gameport(struct cmipci *cm, int dev)
{
static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
struct gameport *gp;
@@ -2699,7 +2721,7 @@ static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
return 0;
}
-static void snd_cmipci_free_gameport(cmipci_t *cm)
+static void snd_cmipci_free_gameport(struct cmipci *cm)
{
if (cm->gameport) {
struct resource *r = gameport_get_port_data(cm->gameport);
@@ -2712,11 +2734,11 @@ static void snd_cmipci_free_gameport(cmipci_t *cm)
}
}
#else
-static inline int snd_cmipci_create_gameport(cmipci_t *cm, int dev) { return -ENOSYS; }
-static inline void snd_cmipci_free_gameport(cmipci_t *cm) { }
+static inline int snd_cmipci_create_gameport(struct cmipci *cm, int dev) { return -ENOSYS; }
+static inline void snd_cmipci_free_gameport(struct cmipci *cm) { }
#endif
-static int snd_cmipci_free(cmipci_t *cm)
+static int snd_cmipci_free(struct cmipci *cm)
{
if (cm->irq >= 0) {
snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_FM_EN);
@@ -2732,7 +2754,7 @@ static int snd_cmipci_free(cmipci_t *cm)
synchronize_irq(cm->irq);
- free_irq(cm->irq, (void *)cm);
+ free_irq(cm->irq, cm);
}
snd_cmipci_free_gameport(cm);
@@ -2742,17 +2764,17 @@ static int snd_cmipci_free(cmipci_t *cm)
return 0;
}
-static int snd_cmipci_dev_free(snd_device_t *device)
+static int snd_cmipci_dev_free(struct snd_device *device)
{
- cmipci_t *cm = device->device_data;
+ struct cmipci *cm = device->device_data;
return snd_cmipci_free(cm);
}
-static int __devinit snd_cmipci_create_fm(cmipci_t *cm, long fm_port)
+static int __devinit snd_cmipci_create_fm(struct cmipci *cm, long fm_port)
{
long iosynth;
unsigned int val;
- opl3_t *opl3;
+ struct snd_opl3 *opl3;
int err;
/* first try FM regs in PCI port range */
@@ -2793,12 +2815,12 @@ static int __devinit snd_cmipci_create_fm(cmipci_t *cm, long fm_port)
return 0;
}
-static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
- int dev, cmipci_t **rcmipci)
+static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
+ int dev, struct cmipci **rcmipci)
{
- cmipci_t *cm;
+ struct cmipci *cm;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_cmipci_dev_free,
};
unsigned int val = 0;
@@ -2838,7 +2860,8 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
}
cm->iobase = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_cmipci_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)cm)) {
+ if (request_irq(pci->irq, snd_cmipci_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, card->driver, cm)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cmipci_free(cm);
return -EBUSY;
@@ -2991,8 +3014,8 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- cmipci_t *cm;
+ struct snd_card *card;
+ struct cmipci *cm;
int err;
if (dev >= SNDRV_CARDS)
@@ -3024,6 +3047,7 @@ static int __devinit snd_cmipci_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = cm;
sprintf(card->shortname, "C-Media PCI %s", card->driver);
sprintf(card->longname, "%s (model %d) at 0x%lx, irq %i",
@@ -3051,11 +3075,93 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci)
}
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static unsigned char saved_regs[] = {
+ CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL,
+ CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL,
+ CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2,
+ CM_REG_CH1_FRAME1, CM_REG_CH1_FRAME2, CM_REG_EXT_MISC,
+ CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0,
+};
+
+static unsigned char saved_mixers[] = {
+ SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
+ SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
+ SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
+ SB_DSP4_CD_DEV, SB_DSP4_CD_DEV + 1,
+ SB_DSP4_LINE_DEV, SB_DSP4_LINE_DEV + 1,
+ SB_DSP4_MIC_DEV, SB_DSP4_SPEAKER_DEV,
+ CM_REG_EXTENT_IND, SB_DSP4_OUTPUT_SW,
+ SB_DSP4_INPUT_LEFT, SB_DSP4_INPUT_RIGHT,
+};
+
+static int snd_cmipci_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cmipci *cm = card->private_data;
+ int i;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ snd_pcm_suspend_all(cm->pcm);
+ snd_pcm_suspend_all(cm->pcm2);
+ snd_pcm_suspend_all(cm->pcm_spdif);
+
+ /* save registers */
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ cm->saved_regs[i] = snd_cmipci_read(cm, saved_regs[i]);
+ for (i = 0; i < ARRAY_SIZE(saved_mixers); i++)
+ cm->saved_mixers[i] = snd_cmipci_mixer_read(cm, saved_mixers[i]);
+
+ /* disable ints */
+ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_cmipci_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cmipci *cm = card->private_data;
+ int i;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ /* reset / initialize to a sane state */
+ snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
+ snd_cmipci_ch_reset(cm, CM_CH_PLAY);
+ snd_cmipci_ch_reset(cm, CM_CH_CAPT);
+ snd_cmipci_mixer_write(cm, 0, 0);
+
+ /* restore registers */
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ snd_cmipci_write(cm, saved_regs[i], cm->saved_regs[i]);
+ for (i = 0; i < ARRAY_SIZE(saved_mixers); i++)
+ snd_cmipci_mixer_write(cm, saved_mixers[i], cm->saved_mixers[i]);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
static struct pci_driver driver = {
.name = "C-Media PCI",
.id_table = snd_cmipci_ids,
.probe = snd_cmipci_probe,
.remove = __devexit_p(snd_cmipci_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_cmipci_suspend,
+ .resume = snd_cmipci_resume,
+#endif
};
static int __init alsa_card_cmipci_init(void)
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 034ff3755a3b..4f65ec56bf35 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -427,11 +427,8 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
*
*/
-typedef struct snd_cs4281 cs4281_t;
-typedef struct snd_cs4281_dma cs4281_dma_t;
-
-struct snd_cs4281_dma {
- snd_pcm_substream_t *substream;
+struct cs4281_dma {
+ struct snd_pcm_substream *substream;
unsigned int regDBA; /* offset to DBA register */
unsigned int regDCA; /* offset to DCA register */
unsigned int regDBC; /* offset to DBC register */
@@ -452,7 +449,7 @@ struct snd_cs4281_dma {
#define SUSPEND_REGISTERS 20
-struct snd_cs4281 {
+struct cs4281 {
int irq;
void __iomem *ba0; /* virtual (accessible) address */
@@ -462,18 +459,18 @@ struct snd_cs4281 {
int dual_codec;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
- ac97_t *ac97_secondary;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
+ struct snd_ac97 *ac97_secondary;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *midi_input;
- snd_rawmidi_substream_t *midi_output;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_input;
+ struct snd_rawmidi_substream *midi_output;
- cs4281_dma_t dma[4];
+ struct cs4281_dma dma[4];
unsigned char src_left_play_slot;
unsigned char src_right_play_slot;
@@ -514,38 +511,18 @@ MODULE_DEVICE_TABLE(pci, snd_cs4281_ids);
* common I/O routines
*/
-static void snd_cs4281_delay(unsigned int delay)
-{
- if (delay > 999) {
- unsigned long end_time;
- delay = (delay * HZ) / 1000000;
- if (delay < 1)
- delay = 1;
- end_time = jiffies + delay;
- do {
- schedule_timeout_uninterruptible(1);
- } while (time_after_eq(end_time, jiffies));
- } else {
- udelay(delay);
- }
-}
-
-static inline void snd_cs4281_delay_long(void)
-{
- schedule_timeout_uninterruptible(1);
-}
-
-static inline void snd_cs4281_pokeBA0(cs4281_t *chip, unsigned long offset, unsigned int val)
+static inline void snd_cs4281_pokeBA0(struct cs4281 *chip, unsigned long offset,
+ unsigned int val)
{
writel(val, chip->ba0 + offset);
}
-static inline unsigned int snd_cs4281_peekBA0(cs4281_t *chip, unsigned long offset)
+static inline unsigned int snd_cs4281_peekBA0(struct cs4281 *chip, unsigned long offset)
{
return readl(chip->ba0 + offset);
}
-static void snd_cs4281_ac97_write(ac97_t *ac97,
+static void snd_cs4281_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
/*
@@ -555,7 +532,7 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
* 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
* 5. if DCV not cleared, break and return error
*/
- cs4281_t *chip = ac97->private_data;
+ struct cs4281 *chip = ac97->private_data;
int count;
/*
@@ -590,15 +567,15 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
snd_printk(KERN_ERR "AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val);
}
-static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
+static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- cs4281_t *chip = ac97->private_data;
+ struct cs4281 *chip = ac97->private_data;
int count;
unsigned short result;
// FIXME: volatile is necessary in the following due to a bug of
// some gcc versions
- volatile int ac97_num = ((volatile ac97_t *)ac97)->num;
+ volatile int ac97_num = ((volatile struct snd_ac97 *)ac97)->num;
/*
* 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
@@ -685,10 +662,10 @@ static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
* PCM part
*/
-static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_cs4281_trigger(struct snd_pcm_substream *substream, int cmd)
{
- cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
- cs4281_t *chip = snd_pcm_substream_chip(substream);
+ struct cs4281_dma *dma = substream->runtime->private_data;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
spin_lock(&chip->reg_lock);
switch (cmd) {
@@ -751,7 +728,9 @@ static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate)
return val;
}
-static void snd_cs4281_mode(cs4281_t *chip, cs4281_dma_t *dma, snd_pcm_runtime_t *runtime, int capture, int src)
+static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma,
+ struct snd_pcm_runtime *runtime,
+ int capture, int src)
{
int rec_mono;
@@ -814,22 +793,22 @@ static void snd_cs4281_mode(cs4281_t *chip, cs4281_dma_t *dma, snd_pcm_runtime_t
snd_cs4281_pokeBA0(chip, dma->regFSIC, 0);
}
-static int snd_cs4281_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cs4281_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_cs4281_hw_free(snd_pcm_substream_t * substream)
+static int snd_cs4281_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_cs4281_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
- cs4281_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cs4281_dma *dma = runtime->private_data;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
snd_cs4281_mode(chip, dma, runtime, 0, 1);
@@ -837,11 +816,11 @@ static int snd_cs4281_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs4281_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_cs4281_capture_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
- cs4281_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cs4281_dma *dma = runtime->private_data;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
snd_cs4281_mode(chip, dma, runtime, 1, 1);
@@ -849,18 +828,18 @@ static int snd_cs4281_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_cs4281_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
- cs4281_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cs4281_dma *dma = runtime->private_data;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
// printk("DCC = 0x%x, buffer_size = 0x%x, jiffies = %li\n", snd_cs4281_peekBA0(chip, dma->regDCC), runtime->buffer_size, jiffies);
return runtime->buffer_size -
snd_cs4281_peekBA0(chip, dma->regDCC) - 1;
}
-static snd_pcm_hardware_t snd_cs4281_playback =
+static struct snd_pcm_hardware snd_cs4281_playback =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -886,7 +865,7 @@ static snd_pcm_hardware_t snd_cs4281_playback =
.fifo_size = CS4281_FIFO_SIZE,
};
-static snd_pcm_hardware_t snd_cs4281_capture =
+static struct snd_pcm_hardware snd_cs4281_capture =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -912,11 +891,11 @@ static snd_pcm_hardware_t snd_cs4281_capture =
.fifo_size = CS4281_FIFO_SIZE,
};
-static int snd_cs4281_playback_open(snd_pcm_substream_t * substream)
+static int snd_cs4281_playback_open(struct snd_pcm_substream *substream)
{
- cs4281_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs4281_dma_t *dma;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cs4281_dma *dma;
dma = &chip->dma[0];
dma->substream = substream;
@@ -932,11 +911,11 @@ static int snd_cs4281_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs4281_capture_open(snd_pcm_substream_t * substream)
+static int snd_cs4281_capture_open(struct snd_pcm_substream *substream)
{
- cs4281_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs4281_dma_t *dma;
+ struct cs4281 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct cs4281_dma *dma;
dma = &chip->dma[1];
dma->substream = substream;
@@ -952,23 +931,23 @@ static int snd_cs4281_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs4281_playback_close(snd_pcm_substream_t * substream)
+static int snd_cs4281_playback_close(struct snd_pcm_substream *substream)
{
- cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
+ struct cs4281_dma *dma = substream->runtime->private_data;
dma->substream = NULL;
return 0;
}
-static int snd_cs4281_capture_close(snd_pcm_substream_t * substream)
+static int snd_cs4281_capture_close(struct snd_pcm_substream *substream)
{
- cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
+ struct cs4281_dma *dma = substream->runtime->private_data;
dma->substream = NULL;
return 0;
}
-static snd_pcm_ops_t snd_cs4281_playback_ops = {
+static struct snd_pcm_ops snd_cs4281_playback_ops = {
.open = snd_cs4281_playback_open,
.close = snd_cs4281_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -979,7 +958,7 @@ static snd_pcm_ops_t snd_cs4281_playback_ops = {
.pointer = snd_cs4281_pointer,
};
-static snd_pcm_ops_t snd_cs4281_capture_ops = {
+static struct snd_pcm_ops snd_cs4281_capture_ops = {
.open = snd_cs4281_capture_open,
.close = snd_cs4281_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -990,16 +969,10 @@ static snd_pcm_ops_t snd_cs4281_capture_ops = {
.pointer = snd_cs4281_pointer,
};
-static void snd_cs4281_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_cs4281_pcm(struct cs4281 * chip, int device,
+ struct snd_pcm ** rpcm)
{
- cs4281_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_cs4281_pcm(cs4281_t * chip, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1012,7 +985,6 @@ static int __devinit snd_cs4281_pcm(cs4281_t * chip, int device, snd_pcm_t ** rp
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4281_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_cs4281_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "CS4281");
chip->pcm = pcm;
@@ -1031,7 +1003,8 @@ static int __devinit snd_cs4281_pcm(cs4281_t * chip, int device, snd_pcm_t ** rp
#define CS_VOL_MASK 0x1f
-static int snd_cs4281_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs4281_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1040,9 +1013,10 @@ static int snd_cs4281_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_cs4281_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4281_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4281_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cs4281 *chip = snd_kcontrol_chip(kcontrol);
int regL = (kcontrol->private_value >> 16) & 0xffff;
int regR = kcontrol->private_value & 0xffff;
int volL, volR;
@@ -1055,9 +1029,10 @@ static int snd_cs4281_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_cs4281_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4281_t *chip = snd_kcontrol_chip(kcontrol);
+ struct cs4281 *chip = snd_kcontrol_chip(kcontrol);
int change = 0;
int regL = (kcontrol->private_value >> 16) & 0xffff;
int regR = kcontrol->private_value & 0xffff;
@@ -1079,7 +1054,7 @@ static int snd_cs4281_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t snd_cs4281_fm_vol =
+static struct snd_kcontrol_new snd_cs4281_fm_vol =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Synth Playback Volume",
@@ -1089,7 +1064,7 @@ static snd_kcontrol_new_t snd_cs4281_fm_vol =
.private_value = ((BA0_FMLVC << 16) | BA0_FMRVC),
};
-static snd_kcontrol_new_t snd_cs4281_pcm_vol =
+static struct snd_kcontrol_new snd_cs4281_pcm_vol =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Stream Playback Volume",
@@ -1099,27 +1074,27 @@ static snd_kcontrol_new_t snd_cs4281_pcm_vol =
.private_value = ((BA0_PPLVC << 16) | BA0_PPRVC),
};
-static void snd_cs4281_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- cs4281_t *chip = bus->private_data;
+ struct cs4281 *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
+static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97)
{
- cs4281_t *chip = ac97->private_data;
+ struct cs4281 *chip = ac97->private_data;
if (ac97->num)
chip->ac97_secondary = NULL;
else
chip->ac97 = NULL;
}
-static int __devinit snd_cs4281_mixer(cs4281_t * chip)
+static int __devinit snd_cs4281_mixer(struct cs4281 * chip)
{
- snd_card_t *card = chip->card;
- ac97_template_t ac97;
+ struct snd_card *card = chip->card;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_cs4281_ac97_write,
.read = snd_cs4281_ac97_read,
};
@@ -1150,22 +1125,23 @@ static int __devinit snd_cs4281_mixer(cs4281_t * chip)
* proc interface
*/
-static void snd_cs4281_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_cs4281_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs4281_t *chip = entry->private_data;
+ struct cs4281 *chip = entry->private_data;
snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");
snd_iprintf(buffer, "Spurious half IRQs : %u\n", chip->spurious_dhtc_irq);
snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq);
}
-static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_cs4281_BA0_read(struct snd_info_entry *entry,
+ void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
long size;
- cs4281_t *chip = entry->private_data;
+ struct cs4281 *chip = entry->private_data;
size = count;
if (pos + size > CS4281_BA0_SIZE)
@@ -1177,12 +1153,13 @@ static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data
return size;
}
-static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_cs4281_BA1_read(struct snd_info_entry *entry,
+ void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
long size;
- cs4281_t *chip = entry->private_data;
+ struct cs4281 *chip = entry->private_data;
size = count;
if (pos + size > CS4281_BA1_SIZE)
@@ -1202,9 +1179,9 @@ static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
.read = snd_cs4281_BA1_read,
};
-static void __devinit snd_cs4281_proc_init(cs4281_t * chip)
+static void __devinit snd_cs4281_proc_init(struct cs4281 * chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "cs4281", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_cs4281_proc_read);
@@ -1230,7 +1207,7 @@ static void __devinit snd_cs4281_proc_init(cs4281_t * chip)
static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{
- cs4281_t *chip = gameport_get_port_data(gameport);
+ struct cs4281 *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
@@ -1238,16 +1215,17 @@ static void snd_cs4281_gameport_trigger(struct gameport *gameport)
static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
{
- cs4281_t *chip = gameport_get_port_data(gameport);
+ struct cs4281 *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return snd_cs4281_peekBA0(chip, BA0_JSPT);
}
#ifdef COOKED_MODE
-static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static int snd_cs4281_gameport_cooked_read(struct gameport *gameport,
+ int *axes, int *buttons)
{
- cs4281_t *chip = gameport_get_port_data(gameport);
+ struct cs4281 *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
snd_assert(chip, return 0);
@@ -1286,7 +1264,7 @@ static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
+static int __devinit snd_cs4281_create_gameport(struct cs4281 *chip)
{
struct gameport *gp;
@@ -1313,7 +1291,7 @@ static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
return 0;
}
-static void snd_cs4281_free_gameport(cs4281_t *chip)
+static void snd_cs4281_free_gameport(struct cs4281 *chip)
{
if (chip->gameport) {
gameport_unregister_port(chip->gameport);
@@ -1321,11 +1299,11 @@ static void snd_cs4281_free_gameport(cs4281_t *chip)
}
}
#else
-static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; }
-static inline void snd_cs4281_free_gameport(cs4281_t *chip) { }
+static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; }
+static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
-static int snd_cs4281_free(cs4281_t *chip)
+static int snd_cs4281_free(struct cs4281 *chip)
{
snd_cs4281_free_gameport(chip);
@@ -1342,7 +1320,7 @@ static int snd_cs4281_free(cs4281_t *chip)
pci_set_power_state(chip->pci, 3);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->ba0)
iounmap(chip->ba0);
if (chip->ba1)
@@ -1354,27 +1332,23 @@ static int snd_cs4281_free(cs4281_t *chip)
return 0;
}
-static int snd_cs4281_dev_free(snd_device_t *device)
+static int snd_cs4281_dev_free(struct snd_device *device)
{
- cs4281_t *chip = device->device_data;
+ struct cs4281 *chip = device->device_data;
return snd_cs4281_free(chip);
}
-static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */
-#ifdef CONFIG_PM
-static int cs4281_suspend(snd_card_t *card, pm_message_t state);
-static int cs4281_resume(snd_card_t *card);
-#endif
+static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */
-static int __devinit snd_cs4281_create(snd_card_t * card,
+static int __devinit snd_cs4281_create(struct snd_card *card,
struct pci_dev *pci,
- cs4281_t ** rchip,
+ struct cs4281 ** rchip,
int dual_codec)
{
- cs4281_t *chip;
+ struct cs4281 *chip;
unsigned int tmp;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_cs4281_dev_free,
};
@@ -1405,7 +1379,8 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
chip->ba0_addr = pci_resource_start(pci, 0);
chip->ba1_addr = pci_resource_start(pci, 1);
- if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", (void *)chip)) {
+ if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "CS4281", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cs4281_free(chip);
return -ENOMEM;
@@ -1432,15 +1407,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
snd_cs4281_proc_init(chip);
- snd_card_set_pm_callback(card, cs4281_suspend, cs4281_resume, chip);
-
snd_card_set_dev(card, &pci->dev);
*rchip = chip;
return 0;
}
-static int snd_cs4281_chip_init(cs4281_t *chip)
+static int snd_cs4281_chip_init(struct cs4281 *chip)
{
unsigned int tmp;
int timeout;
@@ -1501,7 +1474,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
snd_cs4281_pokeBA0(chip, BA0_SPMC, 0);
udelay(50);
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN);
- snd_cs4281_delay(50000);
+ msleep(50);
if (chip->dual_codec)
snd_cs4281_pokeBA0(chip, BA0_SPMC, BA0_SPMC_RSTN | BA0_SPMC_ASDI2E);
@@ -1517,13 +1490,13 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
* Start the DLL Clock logic.
*/
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_DLLP);
- snd_cs4281_delay(50000);
+ msleep(50);
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, BA0_CLKCR1_SWCE | BA0_CLKCR1_DLLP);
/*
* Wait for the DLL ready signal from the clock logic.
*/
- timeout = HZ;
+ timeout = 100;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1531,7 +1504,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_CLKCR1) & BA0_CLKCR1_DLLRDY)
goto __ok0;
- snd_cs4281_delay_long();
+ msleep(1);
} while (timeout-- > 0);
snd_printk(KERN_ERR "DLLRDY not seen\n");
@@ -1549,7 +1522,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
/*
* Wait for the codec ready signal from the AC97 codec.
*/
- timeout = HZ;
+ timeout = 100;
do {
/*
* Read the AC97 status register to see if we've seen a CODEC
@@ -1557,7 +1530,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
*/
if (snd_cs4281_peekBA0(chip, BA0_ACSTS) & BA0_ACSTS_CRDY)
goto __ok1;
- snd_cs4281_delay_long();
+ msleep(1);
} while (timeout-- > 0);
snd_printk(KERN_ERR "never read codec ready from AC'97 (0x%x)\n", snd_cs4281_peekBA0(chip, BA0_ACSTS));
@@ -1565,11 +1538,11 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
__ok1:
if (chip->dual_codec) {
- timeout = HZ;
+ timeout = 100;
do {
if (snd_cs4281_peekBA0(chip, BA0_ACSTS2) & BA0_ACSTS_CRDY)
goto __codec2_ok;
- snd_cs4281_delay_long();
+ msleep(1);
} while (timeout-- > 0);
snd_printk(KERN_INFO "secondary codec doesn't respond. disable it...\n");
chip->dual_codec = 0;
@@ -1588,7 +1561,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
* the codec is pumping ADC data across the AC-link.
*/
- timeout = HZ;
+ timeout = 100;
do {
/*
* Read the input slot valid register and see if input slots 3
@@ -1596,7 +1569,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
*/
if ((snd_cs4281_peekBA0(chip, BA0_ACISV) & (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4))) == (BA0_ACISV_SLV(3) | BA0_ACISV_SLV(4)))
goto __ok2;
- snd_cs4281_delay_long();
+ msleep(1);
} while (timeout-- > 0);
if (--retry_count > 0)
@@ -1616,7 +1589,7 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
* Initialize DMA structures
*/
for (tmp = 0; tmp < 4; tmp++) {
- cs4281_dma_t *dma = &chip->dma[tmp];
+ struct cs4281_dma *dma = &chip->dma[tmp];
dma->regDBA = BA0_DBA0 + (tmp * 0x10);
dma->regDCA = BA0_DCA0 + (tmp * 0x10);
dma->regDBC = BA0_DBC0 + (tmp * 0x10);
@@ -1673,16 +1646,16 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
* MIDI section
*/
-static void snd_cs4281_midi_reset(cs4281_t *chip)
+static void snd_cs4281_midi_reset(struct cs4281 *chip)
{
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr | BA0_MIDCR_MRST);
udelay(100);
snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
-static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream)
{
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->midcr |= BA0_MIDCR_RXE;
@@ -1696,9 +1669,9 @@ static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream)
{
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE);
@@ -1713,9 +1686,9 @@ static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream)
{
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->uartm |= CS4281_MODE_OUTPUT;
@@ -1730,9 +1703,9 @@ static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream)
{
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE);
@@ -1747,10 +1720,10 @@ static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->reg_lock, flags);
if (up) {
@@ -1767,10 +1740,10 @@ static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, i
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- cs4281_t *chip = substream->rmidi->private_data;
+ struct cs4281 *chip = substream->rmidi->private_data;
unsigned char byte;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1797,23 +1770,24 @@ static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream,
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static snd_rawmidi_ops_t snd_cs4281_midi_output =
+static struct snd_rawmidi_ops snd_cs4281_midi_output =
{
.open = snd_cs4281_midi_output_open,
.close = snd_cs4281_midi_output_close,
.trigger = snd_cs4281_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_cs4281_midi_input =
+static struct snd_rawmidi_ops snd_cs4281_midi_input =
{
.open = snd_cs4281_midi_input_open,
.close = snd_cs4281_midi_input_close,
.trigger = snd_cs4281_midi_input_trigger,
};
-static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t **rrawmidi)
+static int __devinit snd_cs4281_midi(struct cs4281 * chip, int device,
+ struct snd_rawmidi **rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
@@ -1837,9 +1811,9 @@ static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- cs4281_t *chip = dev_id;
+ struct cs4281 *chip = dev_id;
unsigned int status, dma, val;
- cs4281_dma_t *cdma;
+ struct cs4281_dma *cdma;
if (chip == NULL)
return IRQ_NONE;
@@ -1909,10 +1883,11 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
/*
* OPL3 command
*/
-static void snd_cs4281_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
+static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
+ unsigned char val)
{
unsigned long flags;
- cs4281_t *chip = opl3->private_data;
+ struct cs4281 *chip = opl3->private_data;
void __iomem *port;
if (cmd & OPL3_RIGHT)
@@ -1935,9 +1910,9 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- cs4281_t *chip;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct cs4281 *chip;
+ struct snd_opl3 *opl3;
int err;
if (dev >= SNDRV_CARDS)
@@ -1955,6 +1930,7 @@ static int __devinit snd_cs4281_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
if ((err = snd_cs4281_mixer(chip)) < 0) {
snd_card_free(card);
@@ -2026,18 +2002,18 @@ static int saved_regs[SUSPEND_REGISTERS] = {
#define CLKCR1_CKRA 0x00010000L
-static int cs4281_suspend(snd_card_t *card, pm_message_t state)
+static int cs4281_suspend(struct pci_dev *pci, pm_message_t state)
{
- cs4281_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cs4281 *chip = card->private_data;
u32 ulCLK;
unsigned int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
- if (chip->ac97)
- snd_ac97_suspend(chip->ac97);
- if (chip->ac97_secondary)
- snd_ac97_suspend(chip->ac97_secondary);
+ snd_ac97_suspend(chip->ac97);
+ snd_ac97_suspend(chip->ac97_secondary);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
@@ -2067,18 +2043,21 @@ static int cs4281_suspend(snd_card_t *card, pm_message_t state)
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int cs4281_resume(snd_card_t *card)
+static int cs4281_resume(struct pci_dev *pci)
{
- cs4281_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct cs4281 *chip = card->private_data;
unsigned int i;
u32 ulCLK;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK |= CLKCR1_CKRA;
@@ -2091,15 +2070,14 @@ static int cs4281_resume(snd_card_t *card)
if (saved_regs[i])
snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
- if (chip->ac97)
- snd_ac97_resume(chip->ac97);
- if (chip->ac97_secondary)
- snd_ac97_resume(chip->ac97_secondary);
+ snd_ac97_resume(chip->ac97);
+ snd_ac97_resume(chip->ac97_secondary);
ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
ulCLK &= ~CLKCR1_CKRA;
snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
@@ -2109,7 +2087,10 @@ static struct pci_driver driver = {
.id_table = snd_cs4281_ids,
.probe = snd_cs4281_probe,
.remove = __devexit_p(snd_cs4281_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = cs4281_suspend,
+ .resume = cs4281_resume,
+#endif
};
static int __init alsa_card_cs4281_init(void)
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index b9fff4ee6f9d..c590602e20cd 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -78,8 +78,8 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- cs46xx_t *chip;
+ struct snd_card *card;
+ struct snd_cs46xx *chip;
int err;
if (dev >= SNDRV_CARDS)
@@ -98,6 +98,7 @@ static int __devinit snd_card_cs46xx_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
chip->accept_valid = mmap_valid[dev];
if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) {
snd_card_free(card);
@@ -166,7 +167,10 @@ static struct pci_driver driver = {
.id_table = snd_cs46xx_ids,
.probe = snd_card_cs46xx_probe,
.remove = __devexit_p(snd_card_cs46xx_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_cs46xx_suspend,
+ .resume = snd_cs46xx_resume,
+#endif
};
static int __init alsa_card_cs46xx_init(void)
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 9b8af5bcbb04..8fb275d6eb77 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -66,23 +66,23 @@
#include "cs46xx_lib.h"
#include "dsp_spos.h"
-static void amp_voyetra(cs46xx_t *chip, int change);
+static void amp_voyetra(struct snd_cs46xx *chip, int change);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static snd_pcm_ops_t snd_cs46xx_playback_rear_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_clfe_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_iec958_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_rear_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops;
#endif
-static snd_pcm_ops_t snd_cs46xx_playback_ops;
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_ops;
-static snd_pcm_ops_t snd_cs46xx_capture_ops;
-static snd_pcm_ops_t snd_cs46xx_capture_indirect_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_ops;
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops;
+static struct snd_pcm_ops snd_cs46xx_capture_ops;
+static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops;
-static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
+static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,
unsigned short reg,
int codec_index)
{
@@ -204,10 +204,10 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
return result;
}
-static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
+static unsigned short snd_cs46xx_ac97_read(struct snd_ac97 * ac97,
unsigned short reg)
{
- cs46xx_t *chip = ac97->private_data;
+ struct snd_cs46xx *chip = ac97->private_data;
unsigned short val;
int codec_index = ac97->num;
@@ -221,7 +221,7 @@ static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
}
-static void snd_cs46xx_codec_write(cs46xx_t *chip,
+static void snd_cs46xx_codec_write(struct snd_cs46xx *chip,
unsigned short reg,
unsigned short val,
int codec_index)
@@ -286,11 +286,11 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip,
chip->active_ctrl(chip, -1);
}
-static void snd_cs46xx_ac97_write(ac97_t *ac97,
+static void snd_cs46xx_ac97_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- cs46xx_t *chip = ac97->private_data;
+ struct snd_cs46xx *chip = ac97->private_data;
int codec_index = ac97->num;
snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
@@ -305,7 +305,7 @@ static void snd_cs46xx_ac97_write(ac97_t *ac97,
* Chip initialization
*/
-int snd_cs46xx_download(cs46xx_t *chip,
+int snd_cs46xx_download(struct snd_cs46xx *chip,
u32 *src,
unsigned long offset,
unsigned long len)
@@ -334,7 +334,7 @@ int snd_cs46xx_download(cs46xx_t *chip,
#include "imgs/cwcbinhack.h"
#include "imgs/cwcdma.h"
-int snd_cs46xx_clear_BA1(cs46xx_t *chip,
+int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip,
unsigned long offset,
unsigned long len)
{
@@ -358,7 +358,7 @@ int snd_cs46xx_clear_BA1(cs46xx_t *chip,
#include "cs46xx_image.h"
-int snd_cs46xx_download_image(cs46xx_t *chip)
+int snd_cs46xx_download_image(struct snd_cs46xx *chip)
{
int idx, err;
unsigned long offset = 0;
@@ -379,7 +379,7 @@ int snd_cs46xx_download_image(cs46xx_t *chip)
* Chip reset
*/
-static void snd_cs46xx_reset(cs46xx_t *chip)
+static void snd_cs46xx_reset(struct snd_cs46xx *chip)
{
int idx;
@@ -408,7 +408,7 @@ static void snd_cs46xx_reset(cs46xx_t *chip)
snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
}
-static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout)
+static int cs46xx_wait_for_fifo(struct snd_cs46xx * chip,int retry_timeout)
{
u32 i, status = 0;
/*
@@ -432,7 +432,7 @@ static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout)
return 0;
}
-static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
+static void snd_cs46xx_clear_serial_FIFOs(struct snd_cs46xx *chip)
{
int idx, powerdown = 0;
unsigned int tmp;
@@ -486,7 +486,7 @@ static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
}
-static void snd_cs46xx_proc_start(cs46xx_t *chip)
+static void snd_cs46xx_proc_start(struct snd_cs46xx *chip)
{
int cnt;
@@ -513,7 +513,7 @@ static void snd_cs46xx_proc_start(cs46xx_t *chip)
snd_printk(KERN_ERR "SPCR_RUNFR never reset\n");
}
-static void snd_cs46xx_proc_stop(cs46xx_t *chip)
+static void snd_cs46xx_proc_stop(struct snd_cs46xx *chip)
{
/*
* Turn off the run, run at frame, and DMA enable bits in the local copy of
@@ -528,7 +528,7 @@ static void snd_cs46xx_proc_stop(cs46xx_t *chip)
#define GOF_PER_SEC 200
-static void snd_cs46xx_set_play_sample_rate(cs46xx_t *chip, unsigned int rate)
+static void snd_cs46xx_set_play_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
{
unsigned long flags;
unsigned int tmp1, tmp2;
@@ -574,7 +574,7 @@ static void snd_cs46xx_set_play_sample_rate(cs46xx_t *chip, unsigned int rate)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate)
+static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned int rate)
{
unsigned long flags;
unsigned int phiIncr, coeffIncr, tmp1, tmp2;
@@ -684,43 +684,43 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
* PCM part
*/
-static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes)
+static void snd_cs46xx_pb_trans_copy(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t * cpcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm * cpcm = runtime->private_data;
memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
}
-static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
+static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t * cpcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm * cpcm = runtime->private_data;
snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
return 0;
}
-static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes)
+static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
memcpy(runtime->dma_area + rec->sw_data,
chip->capt.hw_buf.area + rec->hw_data, bytes);
}
-static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
return 0;
}
-static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
size_t ptr;
- cs46xx_pcm_t *cpcm = substream->runtime->private_data;
+ struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
snd_assert (cpcm->pcm_channel,return -ENXIO);
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -732,11 +732,11 @@ static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t
return ptr >> cpcm->shift;
}
-static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
size_t ptr;
- cs46xx_pcm_t *cpcm = substream->runtime->private_data;
+ struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -748,29 +748,29 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
}
-static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
return ptr >> chip->capt.shift;
}
-static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
}
-static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_cs46xx_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- /*snd_pcm_runtime_t *runtime = substream->runtime;*/
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ /*struct snd_pcm_runtime *runtime = substream->runtime;*/
int result = 0;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- cs46xx_pcm_t *cpcm = substream->runtime->private_data;
+ struct snd_cs46xx_pcm *cpcm = substream->runtime->private_data;
if (! cpcm->pcm_channel) {
return -ENXIO;
}
@@ -827,10 +827,10 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_cs46xx_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
unsigned int tmp;
int result = 0;
@@ -858,7 +858,7 @@ static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
+static int _cs46xx_adjust_sample_rate (struct snd_cs46xx *chip, struct snd_cs46xx_pcm *cpcm,
int sample_rate)
{
@@ -893,14 +893,14 @@ static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
#endif
-static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cs46xx_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t *cpcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm *cpcm;
int err;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
int sample_rate = params_rate(hw_params);
int period_size = params_period_bytes(hw_params);
#endif
@@ -995,11 +995,11 @@ static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_hw_free(struct snd_pcm_substream *substream)
{
- /*cs46xx_t *chip = snd_pcm_substream_chip(substream);*/
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t *cpcm;
+ /*struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);*/
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm *cpcm;
cpcm = runtime->private_data;
@@ -1017,13 +1017,13 @@ static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_prepare(struct snd_pcm_substream *substream)
{
unsigned int tmp;
unsigned int pfie;
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t *cpcm;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm *cpcm;
cpcm = runtime->private_data;
@@ -1087,11 +1087,11 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs46xx_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_cs46xx_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1118,10 +1118,10 @@ static int snd_cs46xx_capture_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_cs46xx_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_cs46xx_capture_hw_free(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->dma_area != chip->capt.hw_buf.area)
snd_pcm_lib_free_pages(substream);
@@ -1132,10 +1132,10 @@ static int snd_cs46xx_capture_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_cs46xx_capture_prepare(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
chip->capt.shift = 2;
@@ -1149,13 +1149,13 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- cs46xx_t *chip = dev_id;
+ struct snd_cs46xx *chip = dev_id;
u32 status1;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
u32 status2;
int i;
- cs46xx_pcm_t *cpcm = NULL;
+ struct snd_cs46xx_pcm *cpcm = NULL;
#endif
/*
@@ -1239,7 +1239,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_HANDLED;
}
-static snd_pcm_hardware_t snd_cs46xx_playback =
+static struct snd_pcm_hardware snd_cs46xx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1261,7 +1261,7 @@ static snd_pcm_hardware_t snd_cs46xx_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_cs46xx_capture =
+static struct snd_pcm_hardware snd_cs46xx_capture =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1285,7 +1285,7 @@ static snd_pcm_hardware_t snd_cs46xx_capture =
static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
-static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
.count = ARRAY_SIZE(period_sizes),
.list = period_sizes,
.mask = 0
@@ -1293,16 +1293,16 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
#endif
-static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_cs46xx_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
-static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
+static int _cs46xx_playback_open_channel (struct snd_pcm_substream *substream,int pcm_channel_id)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- cs46xx_pcm_t * cpcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx_pcm * cpcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
cpcm = kzalloc(sizeof(*cpcm), GFP_KERNEL);
if (cpcm == NULL)
@@ -1340,30 +1340,30 @@ static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pc
return 0;
}
-static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_open(struct snd_pcm_substream *substream)
{
snd_printdd("open front channel\n");
return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_open_rear(struct snd_pcm_substream *substream)
{
snd_printdd("open rear channel\n");
return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
}
-static int snd_cs46xx_playback_open_clfe(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_open_clfe(struct snd_pcm_substream *substream)
{
snd_printdd("open center - LFE channel\n");
return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
}
-static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_open_iec958(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
snd_printdd("open raw iec958 channel\n");
@@ -1374,12 +1374,12 @@ static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream)
return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
}
-static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream);
+static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream);
-static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_close_iec958(struct snd_pcm_substream *substream)
{
int err;
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
snd_printdd("close raw iec958 channel\n");
@@ -1393,9 +1393,9 @@ static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream)
}
#endif
-static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
+static int snd_cs46xx_capture_open(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
PAGE_SIZE, &chip->capt.hw_buf) < 0)
@@ -1416,11 +1416,11 @@ static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
+static int snd_cs46xx_playback_close(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- cs46xx_pcm_t * cpcm;
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_cs46xx_pcm * cpcm;
cpcm = runtime->private_data;
@@ -1445,9 +1445,9 @@ static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
+static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
{
- cs46xx_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
chip->capt.substream = NULL;
snd_dma_free_pages(&chip->capt.hw_buf);
@@ -1457,7 +1457,7 @@ static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
.open = snd_cs46xx_playback_open_rear,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1468,7 +1468,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
.open = snd_cs46xx_playback_open_rear,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1480,7 +1480,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
.ack = snd_cs46xx_playback_transfer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
.open = snd_cs46xx_playback_open_clfe,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1491,7 +1491,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
.open = snd_cs46xx_playback_open_clfe,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1503,7 +1503,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = {
.ack = snd_cs46xx_playback_transfer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
.open = snd_cs46xx_playback_open_iec958,
.close = snd_cs46xx_playback_close_iec958,
.ioctl = snd_pcm_lib_ioctl,
@@ -1514,7 +1514,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
.open = snd_cs46xx_playback_open_iec958,
.close = snd_cs46xx_playback_close_iec958,
.ioctl = snd_pcm_lib_ioctl,
@@ -1528,7 +1528,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
#endif
-static snd_pcm_ops_t snd_cs46xx_playback_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_ops = {
.open = snd_cs46xx_playback_open,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1539,7 +1539,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_ops = {
.pointer = snd_cs46xx_playback_direct_pointer,
};
-static snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
+static struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
.open = snd_cs46xx_playback_open,
.close = snd_cs46xx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1551,7 +1551,7 @@ static snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
.ack = snd_cs46xx_playback_transfer,
};
-static snd_pcm_ops_t snd_cs46xx_capture_ops = {
+static struct snd_pcm_ops snd_cs46xx_capture_ops = {
.open = snd_cs46xx_capture_open,
.close = snd_cs46xx_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1562,7 +1562,7 @@ static snd_pcm_ops_t snd_cs46xx_capture_ops = {
.pointer = snd_cs46xx_capture_direct_pointer,
};
-static snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
+static struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
.open = snd_cs46xx_capture_open,
.close = snd_cs46xx_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1574,43 +1574,15 @@ static snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
.ack = snd_cs46xx_capture_transfer,
};
-static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
-{
- cs46xx_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
-{
- cs46xx_t *chip = pcm->private_data;
- chip->pcm_rear = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
-{
- cs46xx_t *chip = pcm->private_data;
- chip->pcm_center_lfe = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
-{
- cs46xx_t *chip = pcm->private_data;
- chip->pcm_iec958 = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
#define MAX_PLAYBACK_CHANNELS (DSP_MAX_PCM_CHANNELS - 1)
#else
#define MAX_PLAYBACK_CHANNELS 1
#endif
-int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1619,7 +1591,6 @@ int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_cs46xx_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops);
@@ -1640,9 +1611,9 @@ int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1652,7 +1623,6 @@ int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_cs46xx_pcm_rear_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
@@ -1670,9 +1640,9 @@ int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
return 0;
}
-int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1682,7 +1652,6 @@ int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t **
return err;
pcm->private_data = chip;
- pcm->private_free = snd_cs46xx_pcm_center_lfe_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops);
@@ -1700,9 +1669,9 @@ int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t **
return 0;
}
-int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1712,7 +1681,6 @@ int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpc
return err;
pcm->private_data = chip;
- pcm->private_free = snd_cs46xx_pcm_iec958_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
@@ -1734,16 +1702,16 @@ int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpc
/*
* Mixer routines
*/
-static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_cs46xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- cs46xx_t *chip = bus->private_data;
+ struct snd_cs46xx *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
+static void snd_cs46xx_mixer_free_ac97(struct snd_ac97 *ac97)
{
- cs46xx_t *chip = ac97->private_data;
+ struct snd_cs46xx *chip = ac97->private_data;
snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
(ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
@@ -1757,8 +1725,8 @@ static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
}
-static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cs46xx_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1767,9 +1735,9 @@ static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
unsigned int val = snd_cs46xx_peek(chip, reg);
ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
@@ -1777,9 +1745,9 @@ static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 |
(0xffff - ucontrol->value.integer.value[1]));
@@ -1795,9 +1763,9 @@ static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_dac_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
@@ -1805,9 +1773,9 @@ static int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_dac_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int change = 0;
if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
@@ -1822,18 +1790,18 @@ static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
}
#if 0
-static int snd_cs46xx_vol_iec958_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
return 0;
}
-static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_vol_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int change = 0;
if (chip->dsp_spos_instance->spdif_input_volume_left != ucontrol->value.integer.value[0] ||
@@ -1848,8 +1816,8 @@ static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
}
#endif
-static int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_mixer_boolean_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1858,10 +1826,10 @@ static int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_iec958_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
@@ -1872,10 +1840,10 @@ static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int change, res;
switch (kcontrol->private_value) {
@@ -1909,11 +1877,11 @@ static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol,
return res;
}
-static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_adc_capture_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
if (ins->adc_input != NULL)
ucontrol->value.integer.value[0] = 1;
@@ -1923,11 +1891,11 @@ static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_adc_capture_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int change = 0;
if (ucontrol->value.integer.value[0] && !ins->adc_input) {
@@ -1940,11 +1908,11 @@ static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol,
return change;
}
-static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_pcm_capture_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
if (ins->pcm_input != NULL)
ucontrol->value.integer.value[0] = 1;
@@ -1955,11 +1923,11 @@ static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol,
}
-static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_pcm_capture_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int change = 0;
if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
@@ -1973,10 +1941,10 @@ static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol,
return change;
}
-static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_herc_spdif_select_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
@@ -1991,10 +1959,10 @@ static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol,
/*
* Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
*/
-static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_herc_spdif_select_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
@@ -2016,18 +1984,18 @@ static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol,
}
-static int snd_cs46xx_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_cs46xx_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
down (&chip->spos_mutex);
ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
@@ -2039,11 +2007,11 @@ static int snd_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
unsigned int val;
int change;
@@ -2066,8 +2034,8 @@ static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,
return change;
}
-static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -2076,11 +2044,11 @@ static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
down (&chip->spos_mutex);
ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
@@ -2092,11 +2060,11 @@ static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx * chip = snd_kcontrol_chip(kcontrol);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
unsigned int val;
int change;
@@ -2123,8 +2091,8 @@ static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,
#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
-static int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_cs46xx_egpio_select_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2133,19 +2101,19 @@ static int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_egpio_select_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_egpio_select_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = chip->current_gpio;
return 0;
}
-static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_egpio_select_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int change = (chip->current_gpio != ucontrol->value.integer.value[0]);
chip->current_gpio = ucontrol->value.integer.value[0];
@@ -2153,10 +2121,10 @@ static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol,
}
-static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_egpio_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
@@ -2166,10 +2134,10 @@ static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_cs46xx_egpio_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_egpio_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
int val = snd_cs46xx_peekBA0(chip, reg);
int oldval = val;
@@ -2187,7 +2155,7 @@ static int snd_cs46xx_egpio_put(snd_kcontrol_t *kcontrol,
}
#endif /* CONFIG_SND_CS46XX_DEBUG_GPIO */
-static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_cs46xx_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DAC Volume",
@@ -2317,26 +2285,26 @@ static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* set primary cs4294 codec into Extended Audio Mode */
-static int snd_cs46xx_front_dup_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_front_dup_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = snd_ac97_read(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX], AC97_CSR_ACMODE);
ucontrol->value.integer.value[0] = (val & 0x200) ? 0 : 1;
return 0;
}
-static int snd_cs46xx_front_dup_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs46xx *chip = snd_kcontrol_chip(kcontrol);
return snd_ac97_update_bits(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX],
AC97_CSR_ACMODE, 0x200,
ucontrol->value.integer.value[0] ? 0 : 0x200);
}
-static snd_kcontrol_new_t snd_cs46xx_front_dup_ctl = {
+static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Duplicate Front",
.info = snd_mixer_boolean_info,
@@ -2347,7 +2315,7 @@ static snd_kcontrol_new_t snd_cs46xx_front_dup_ctl = {
#ifdef CONFIG_SND_CS46XX_NEW_DSP
/* Only available on the Hercules Game Theater XP soundcard */
-static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_hercules_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Optical/Coaxial SPDIF Input Switch",
@@ -2358,7 +2326,7 @@ static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = {
};
-static void snd_cs46xx_codec_reset (ac97_t * ac97)
+static void snd_cs46xx_codec_reset (struct snd_ac97 * ac97)
{
unsigned long end_time;
int err;
@@ -2407,10 +2375,10 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
}
#endif
-static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
+static int __devinit cs46xx_detect_codec(struct snd_cs46xx *chip, int codec)
{
int idx, err;
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
@@ -2440,13 +2408,13 @@ static int __devinit cs46xx_detect_codec(cs46xx_t *chip, int codec)
return -ENXIO;
}
-int __devinit snd_cs46xx_mixer(cs46xx_t *chip, int spdif_device)
+int __devinit snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
{
- snd_card_t *card = chip->card;
- snd_ctl_elem_id_t id;
+ struct snd_card *card = chip->card;
+ struct snd_ctl_elem_id id;
int err;
unsigned int idx;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
#ifdef CONFIG_SND_CS46XX_NEW_DSP
.reset = snd_cs46xx_codec_reset,
#endif
@@ -2474,7 +2442,7 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip, int spdif_device)
/* add cs4630 mixer controls */
for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *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;
@@ -2516,16 +2484,16 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip, int spdif_device)
* RawMIDI interface
*/
-static void snd_cs46xx_midi_reset(cs46xx_t *chip)
+static void snd_cs46xx_midi_reset(struct snd_cs46xx *chip)
{
snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
udelay(100);
snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
}
-static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_cs46xx_midi_input_open(struct snd_rawmidi_substream *substream)
{
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
chip->active_ctrl(chip, 1);
spin_lock_irq(&chip->reg_lock);
@@ -2541,9 +2509,9 @@ static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_cs46xx_midi_input_close(struct snd_rawmidi_substream *substream)
{
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
@@ -2559,9 +2527,9 @@ static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_cs46xx_midi_output_open(struct snd_rawmidi_substream *substream)
{
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
chip->active_ctrl(chip, 1);
@@ -2578,9 +2546,9 @@ static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_cs46xx_midi_output_close(struct snd_rawmidi_substream *substream)
{
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
spin_lock_irq(&chip->reg_lock);
chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
@@ -2596,10 +2564,10 @@ static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_cs46xx_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
spin_lock_irqsave(&chip->reg_lock, flags);
if (up) {
@@ -2616,10 +2584,10 @@ static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, i
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_cs46xx_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- cs46xx_t *chip = substream->rmidi->private_data;
+ struct snd_cs46xx *chip = substream->rmidi->private_data;
unsigned char byte;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -2646,23 +2614,23 @@ static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream,
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static snd_rawmidi_ops_t snd_cs46xx_midi_output =
+static struct snd_rawmidi_ops snd_cs46xx_midi_output =
{
.open = snd_cs46xx_midi_output_open,
.close = snd_cs46xx_midi_output_close,
.trigger = snd_cs46xx_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_cs46xx_midi_input =
+static struct snd_rawmidi_ops snd_cs46xx_midi_input =
{
.open = snd_cs46xx_midi_input_open,
.close = snd_cs46xx_midi_input_close,
.trigger = snd_cs46xx_midi_input_trigger,
};
-int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi)
+int __devinit snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
@@ -2689,7 +2657,7 @@ int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmi
static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
{
- cs46xx_t *chip = gameport_get_port_data(gameport);
+ struct snd_cs46xx *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
@@ -2697,7 +2665,7 @@ static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
{
- cs46xx_t *chip = gameport_get_port_data(gameport);
+ struct snd_cs46xx *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
@@ -2705,7 +2673,7 @@ static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs46xx_t *chip = gameport_get_port_data(gameport);
+ struct snd_cs46xx *chip = gameport_get_port_data(gameport);
unsigned js1, js2, jst;
snd_assert(chip, return 0);
@@ -2739,7 +2707,7 @@ static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
return 0;
}
-int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
+int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip)
{
struct gameport *gp;
@@ -2767,7 +2735,7 @@ int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
return 0;
}
-static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip)
+static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip)
{
if (chip->gameport) {
gameport_unregister_port(chip->gameport);
@@ -2775,20 +2743,21 @@ static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip)
}
}
#else
-int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { return -ENOSYS; }
-static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) { }
+int __devinit snd_cs46xx_gameport(struct snd_cs46xx *chip) { return -ENOSYS; }
+static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
#endif /* CONFIG_GAMEPORT */
+#ifdef CONFIG_PROC_FS
/*
* proc interface
*/
-static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
long size;
- snd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data;
+ struct snd_cs46xx_region *region = entry->private_data;
size = count;
if (pos + (size_t)size > region->size)
@@ -2804,13 +2773,13 @@ static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
.read = snd_cs46xx_io_read,
};
-static int __devinit snd_cs46xx_proc_init(snd_card_t * card, cs46xx_t *chip)
+static int __devinit snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
int idx;
for (idx = 0; idx < 5; idx++) {
- snd_cs46xx_region_t *region = &chip->region.idx[idx];
+ struct snd_cs46xx_region *region = &chip->region.idx[idx];
if (! snd_card_proc_new(card, region->name, &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = chip;
@@ -2825,18 +2794,22 @@ static int __devinit snd_cs46xx_proc_init(snd_card_t * card, cs46xx_t *chip)
return 0;
}
-static int snd_cs46xx_proc_done(cs46xx_t *chip)
+static int snd_cs46xx_proc_done(struct snd_cs46xx *chip)
{
#ifdef CONFIG_SND_CS46XX_NEW_DSP
cs46xx_dsp_proc_done(chip);
#endif
return 0;
}
+#else /* !CONFIG_PROC_FS */
+#define snd_cs46xx_proc_init(card, chip)
+#define snd_cs46xx_proc_done(chip)
+#endif
/*
* stop the h/w
*/
-static void snd_cs46xx_hw_stop(cs46xx_t *chip)
+static void snd_cs46xx_hw_stop(struct snd_cs46xx *chip)
{
unsigned int tmp;
@@ -2883,7 +2856,7 @@ static void snd_cs46xx_hw_stop(cs46xx_t *chip)
}
-static int snd_cs46xx_free(cs46xx_t *chip)
+static int snd_cs46xx_free(struct snd_cs46xx *chip)
{
int idx;
@@ -2903,13 +2876,13 @@ static int snd_cs46xx_free(cs46xx_t *chip)
snd_cs46xx_hw_stop(chip);
for (idx = 0; idx < 5; idx++) {
- snd_cs46xx_region_t *region = &chip->region.idx[idx];
+ struct snd_cs46xx_region *region = &chip->region.idx[idx];
if (region->remap_addr)
iounmap(region->remap_addr);
release_and_free_resource(region->resource);
}
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->active_ctrl)
chip->active_ctrl(chip, -chip->amplifier);
@@ -2926,16 +2899,16 @@ static int snd_cs46xx_free(cs46xx_t *chip)
return 0;
}
-static int snd_cs46xx_dev_free(snd_device_t *device)
+static int snd_cs46xx_dev_free(struct snd_device *device)
{
- cs46xx_t *chip = device->device_data;
+ struct snd_cs46xx *chip = device->device_data;
return snd_cs46xx_free(chip);
}
/*
* initialize chip
*/
-static int snd_cs46xx_chip_init(cs46xx_t *chip)
+static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
{
int timeout;
@@ -3164,7 +3137,7 @@ static int snd_cs46xx_chip_init(cs46xx_t *chip)
/*
* start and load DSP
*/
-int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
+int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip)
{
unsigned int tmp;
/*
@@ -3266,12 +3239,12 @@ int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
* AMP control - null AMP
*/
-static void amp_none(cs46xx_t *chip, int change)
+static void amp_none(struct snd_cs46xx *chip, int change)
{
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP
-static int voyetra_setup_eapd_slot(cs46xx_t *chip)
+static int voyetra_setup_eapd_slot(struct snd_cs46xx *chip)
{
u32 idx, valid_slots,tmp,powerdown = 0;
@@ -3391,7 +3364,7 @@ static int voyetra_setup_eapd_slot(cs46xx_t *chip)
* Crystal EAPD mode
*/
-static void amp_voyetra(cs46xx_t *chip, int change)
+static void amp_voyetra(struct snd_cs46xx *chip, int change)
{
/* Manage the EAPD bit on the Crystal 4297
and the Analog AD1885 */
@@ -3427,7 +3400,7 @@ static void amp_voyetra(cs46xx_t *chip, int change)
#endif
}
-static void hercules_init(cs46xx_t *chip)
+static void hercules_init(struct snd_cs46xx *chip)
{
/* default: AMP off, and SPDIF input optical */
snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
@@ -3438,7 +3411,7 @@ static void hercules_init(cs46xx_t *chip)
/*
* Game Theatre XP card - EGPIO[2] is used to enable the external amp.
*/
-static void amp_hercules(cs46xx_t *chip, int change)
+static void amp_hercules(struct snd_cs46xx *chip, int change)
{
int old = chip->amplifier;
int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
@@ -3459,7 +3432,7 @@ static void amp_hercules(cs46xx_t *chip, int change)
}
}
-static void voyetra_mixer_init (cs46xx_t *chip)
+static void voyetra_mixer_init (struct snd_cs46xx *chip)
{
snd_printdd ("initializing Voyetra mixer\n");
@@ -3468,12 +3441,12 @@ static void voyetra_mixer_init (cs46xx_t *chip)
snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
}
-static void hercules_mixer_init (cs46xx_t *chip)
+static void hercules_mixer_init (struct snd_cs46xx *chip)
{
#ifdef CONFIG_SND_CS46XX_NEW_DSP
unsigned int idx;
int err;
- snd_card_t *card = chip->card;
+ struct snd_card *card = chip->card;
#endif
/* set EGPIO to default */
@@ -3483,7 +3456,7 @@ static void hercules_mixer_init (cs46xx_t *chip)
#ifdef CONFIG_SND_CS46XX_NEW_DSP
for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
if ((err = snd_ctl_add(card, kctl)) < 0) {
@@ -3500,7 +3473,7 @@ static void hercules_mixer_init (cs46xx_t *chip)
* Untested
*/
-static void amp_voyetra_4294(cs46xx_t *chip, int change)
+static void amp_voyetra_4294(struct snd_cs46xx *chip, int change)
{
chip->amplifier += change;
@@ -3530,7 +3503,7 @@ static void amp_voyetra_4294(cs46xx_t *chip, int change)
* enough to make them useful.
*/
-static void clkrun_hack(cs46xx_t *chip, int change)
+static void clkrun_hack(struct snd_cs46xx *chip, int change)
{
u16 control, nval;
@@ -3555,7 +3528,7 @@ static void clkrun_hack(cs46xx_t *chip, int change)
/*
* detect intel piix4
*/
-static void clkrun_init(cs46xx_t *chip)
+static void clkrun_init(struct snd_cs46xx *chip)
{
struct pci_dev *pdev;
u8 pp;
@@ -3583,10 +3556,10 @@ struct cs_card_type
u16 vendor;
u16 id;
char *name;
- void (*init)(cs46xx_t *);
- void (*amp)(cs46xx_t *, int);
- void (*active)(cs46xx_t *, int);
- void (*mixer_init)(cs46xx_t *);
+ void (*init)(struct snd_cs46xx *);
+ void (*amp)(struct snd_cs46xx *, int);
+ void (*active)(struct snd_cs46xx *, int);
+ void (*mixer_init)(struct snd_cs46xx *);
};
static struct cs_card_type __devinitdata cards[] = {
@@ -3686,18 +3659,19 @@ static struct cs_card_type __devinitdata cards[] = {
* APM support
*/
#ifdef CONFIG_PM
-static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state)
+int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state)
{
- cs46xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_cs46xx *chip = card->private_data;
int amp_saved;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
// chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
// chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
- if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
- snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
+ snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
amp_saved = chip->amplifier;
/* turn off amp */
@@ -3706,17 +3680,20 @@ static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state)
/* disable CLKRUN */
chip->active_ctrl(chip, -chip->amplifier);
chip->amplifier = amp_saved; /* restore the status */
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_cs46xx_resume(snd_card_t *card)
+int snd_cs46xx_resume(struct pci_dev *pci)
{
- cs46xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_cs46xx *chip = card->private_data;
int amp_saved;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
amp_saved = chip->amplifier;
chip->amplifier = 0;
chip->active_ctrl(chip, 1); /* force to on */
@@ -3735,14 +3712,14 @@ static int snd_cs46xx_resume(snd_card_t *card)
#endif
snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
- if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
- snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
+ snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
if (amp_saved)
chip->amplifier_ctrl(chip, 1); /* turn amp on */
else
chip->active_ctrl(chip, -1); /* disable CLKRUN */
chip->amplifier = amp_saved;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
@@ -3751,17 +3728,17 @@ static int snd_cs46xx_resume(snd_card_t *card)
/*
*/
-int __devinit snd_cs46xx_create(snd_card_t * card,
+int __devinit snd_cs46xx_create(struct snd_card *card,
struct pci_dev * pci,
int external_amp, int thinkpad,
- cs46xx_t ** rchip)
+ struct snd_cs46xx ** rchip)
{
- cs46xx_t *chip;
+ struct snd_cs46xx *chip;
int err, idx;
- snd_cs46xx_region_t *region;
+ struct snd_cs46xx_region *region;
struct cs_card_type *cp;
u16 ss_card, ss_vendor;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_cs46xx_dev_free,
};
@@ -3787,7 +3764,8 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
chip->ba1_addr = pci_resource_start(pci, 1);
if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
- snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr);
+ snd_printk(KERN_ERR "wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n",
+ chip->ba0_addr, chip->ba1_addr);
snd_cs46xx_free(chip);
return -ENOMEM;
}
@@ -3857,8 +3835,10 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
for (idx = 0; idx < 5; idx++) {
region = &chip->region.idx[idx];
- if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) {
- snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1);
+ if ((region->resource = request_mem_region(region->base, region->size,
+ region->name)) == NULL) {
+ snd_printk(KERN_ERR "unable to request memory region 0x%lx-0x%lx\n",
+ region->base, region->base + region->size - 1);
snd_cs46xx_free(chip);
return -EBUSY;
}
@@ -3870,7 +3850,8 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
}
}
- if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", (void *) chip)) {
+ if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "CS46XX", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_cs46xx_free(chip);
return -EBUSY;
@@ -3898,8 +3879,6 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
snd_cs46xx_proc_init(card, chip);
- snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip);
-
chip->active_ctrl(chip, -1); /* disable CLKRUN */
snd_card_set_dev(card, &pci->dev);
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
index d7bec096d247..f75750c2bd24 100644
--- a/sound/pci/cs46xx/cs46xx_lib.h
+++ b/sound/pci/cs46xx/cs46xx_lib.h
@@ -57,7 +57,7 @@
* common I/O routines
*/
-static inline void snd_cs46xx_poke(cs46xx_t *chip, unsigned long reg, unsigned int val)
+static inline void snd_cs46xx_poke(struct snd_cs46xx *chip, unsigned long reg, unsigned int val)
{
unsigned int bank = reg >> 16;
unsigned int offset = reg & 0xffff;
@@ -66,117 +66,138 @@ static inline void snd_cs46xx_poke(cs46xx_t *chip, unsigned long reg, unsigned i
writel(val, chip->region.idx[bank+1].remap_addr + offset);
}
-static inline unsigned int snd_cs46xx_peek(cs46xx_t *chip, unsigned long reg)
+static inline unsigned int snd_cs46xx_peek(struct snd_cs46xx *chip, unsigned long reg)
{
unsigned int bank = reg >> 16;
unsigned int offset = reg & 0xffff;
return readl(chip->region.idx[bank+1].remap_addr + offset);
}
-static inline void snd_cs46xx_pokeBA0(cs46xx_t *chip, unsigned long offset, unsigned int val)
+static inline void snd_cs46xx_pokeBA0(struct snd_cs46xx *chip, unsigned long offset, unsigned int val)
{
writel(val, chip->region.name.ba0.remap_addr + offset);
}
-static inline unsigned int snd_cs46xx_peekBA0(cs46xx_t *chip, unsigned long offset)
+static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned long offset)
{
return readl(chip->region.name.ba0.remap_addr + offset);
}
-dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip);
-void cs46xx_dsp_spos_destroy (cs46xx_t * chip);
-int cs46xx_dsp_load_module (cs46xx_t * chip,dsp_module_desc_t * module);
-symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip,char * symbol_name,int symbol_type);
-int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip);
-int cs46xx_dsp_proc_done (cs46xx_t *chip);
-int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip);
-int snd_cs46xx_download (cs46xx_t *chip,u32 *src,unsigned long offset,
- unsigned long len);
-int snd_cs46xx_clear_BA1(cs46xx_t *chip,unsigned long offset,unsigned long len);
-int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip);
-int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip);
-int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip);
-int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip);
-int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip);
-int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip);
-int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip);
-int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip);
-int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip);
-int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data);
-dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest);
-void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb);
-void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb);
-dsp_scb_descriptor_t * cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip);
-dsp_scb_descriptor_t * cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,
- u16 channel_disp,u16 fifo_addr,
- u16 child_scb_addr,
- u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
- u16 channel_disp,u16 fifo_addr,
- u16 sample_buffer_addr,
- u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-void cs46xx_dsp_remove_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb);
-dsp_scb_descriptor_t * cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
- u16 channel_disp,u16 fifo_addr,
- u16 sample_buffer_addr,
- u32 dest,dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
- int sample_rate,
- u16 src_buffer_addr,
- u16 src_delay_buffer_addr,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type,
- int pass_through);
-dsp_scb_descriptor_t * cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
- u16 mix_buffer_addr,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-
-dsp_scb_descriptor_t * cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name,
- u16 vari_buffer_addr0,
- u16 vari_buffer_addr1,
- u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- u16 hfg_scb_address,
- u16 asynch_buffer_address,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
- u16 mix_buffer_addr,u16 writeback_spb,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- u16 snoop_buffer_address,
- dsp_scb_descriptor_t * snoop_scb,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type);
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,u32 sample_rate, void * private_data, u32 hw_dma_addr,
- int pcm_channel_id);
-void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,
- pcm_channel_descriptor_t * pcm_channel);
-int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
-int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel);
-dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
- u16 addr,char * scb_name);
-int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src);
-int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src);
-int cs46xx_iec958_pre_open (cs46xx_t *chip);
-int cs46xx_iec958_post_close (cs46xx_t *chip);
-int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
- pcm_channel_descriptor_t * pcm_channel,
- int period_size);
-int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
- int period_size);
-int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right);
-int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right);
+struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip);
+void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip);
+int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module);
+struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name,
+ int symbol_type);
+#ifdef CONFIG_PROC_FS
+int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip);
+int cs46xx_dsp_proc_done (struct snd_cs46xx *chip);
+#else
+#define cs46xx_dsp_proc_init(card, chip)
+#define cs46xx_dsp_proc_done(chip)
+#endif
+int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip);
+int snd_cs46xx_download (struct snd_cs46xx *chip, u32 *src, unsigned long offset,
+ unsigned long len);
+int snd_cs46xx_clear_BA1(struct snd_cs46xx *chip, unsigned long offset, unsigned long len);
+int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip);
+int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip);
+int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip);
+int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip);
+int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip);
+int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip);
+int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip);
+int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip);
+int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip);
+int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data);
+struct dsp_scb_descriptor * cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name,
+ u32 * scb_data, u32 dest);
+#ifdef CONFIG_PROC_FS
+void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb);
+void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
+ struct dsp_scb_descriptor * scb);
+#else
+#define cs46xx_dsp_proc_free_scb_desc(scb)
+#define cs46xx_dsp_proc_register_scb_desc(chip, scb)
+#endif
+struct dsp_scb_descriptor * cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip,
+ char * codec_name, u16 channel_disp, u16 fifo_addr,
+ u16 child_scb_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
+ u16 channel_disp, u16 fifo_addr,
+ u16 sample_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip,
+ struct dsp_scb_descriptor * scb);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
+ u16 channel_disp, u16 fifo_addr,
+ u16 sample_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
+ int sample_rate, u16 src_buffer_addr,
+ u16 src_delay_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type, int pass_through);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 mix_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 vari_buffer_addr0, u16 vari_buffer_addr1, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name,
+ u32 dest, u16 hfg_scb_address, u16 asynch_buffer_address,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name,
+ u32 dest, u16 snoop_buffer_address,
+ struct dsp_scb_descriptor * snoop_scb,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type);
+struct dsp_pcm_channel_descriptor *
+cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip, u32 sample_rate,
+ void * private_data, u32 hw_dma_addr,
+ int pcm_channel_id);
+void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel);
+int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel);
+int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel);
+struct dsp_scb_descriptor *
+cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
+ u16 addr, char * scb_name);
+int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src);
+int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src);
+int cs46xx_iec958_pre_open (struct snd_cs46xx *chip);
+int cs46xx_iec958_post_close (struct snd_cs46xx *chip);
+int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel,
+ int period_size);
+int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip, int period_size);
+int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right);
+int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right);
#endif /* __CS46XX_LIB_H__ */
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index b66304fc4e4a..445a448949e7 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -37,9 +37,10 @@
#include "cs46xx_lib.h"
#include "dsp_spos.h"
-static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry);
+static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
+ struct dsp_scb_descriptor * fg_entry);
-static wide_opcode_t wide_opcodes[] = {
+static enum wide_opcode wide_opcodes[] = {
WIDE_FOR_BEGIN_LOOP,
WIDE_FOR_BEGIN_LOOP2,
WIDE_COND_GOTO_ADDR,
@@ -54,12 +55,13 @@ static wide_opcode_t wide_opcodes[] = {
WIDE_TBEQ_NCOND_CALL1_ADDR
};
-static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32 overlay_begin_address)
+static int shadow_and_reallocate_code (struct snd_cs46xx * chip, u32 * data, u32 size,
+ u32 overlay_begin_address)
{
unsigned int i = 0, j, nreallocated = 0;
u32 hival,loval,address;
u32 mop_operands,mop_type,wide_op;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert( ((size % 2) == 0), return -EINVAL);
@@ -114,7 +116,7 @@ static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32
return nreallocated;
}
-static segment_desc_t * get_segment_desc (dsp_module_desc_t * module, int seg_type)
+static struct dsp_segment_desc * get_segment_desc (struct dsp_module_desc * module, int seg_type)
{
int i;
for (i = 0;i < module->nsegments; ++i) {
@@ -126,7 +128,7 @@ static segment_desc_t * get_segment_desc (dsp_module_desc_t * module, int seg_ty
return NULL;
};
-static int find_free_symbol_index (dsp_spos_instance_t * ins)
+static int find_free_symbol_index (struct dsp_spos_instance * ins)
{
int index = ins->symbol_table.nsymbols,i;
@@ -140,10 +142,10 @@ static int find_free_symbol_index (dsp_spos_instance_t * ins)
return index;
}
-static int add_symbols (cs46xx_t * chip, dsp_module_desc_t * module)
+static int add_symbols (struct snd_cs46xx * chip, struct dsp_module_desc * module)
{
int i;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
if (module->symbol_table.nsymbols > 0) {
if (!strcmp(module->symbol_table.symbols[0].symbol_name, "OVERLAYBEGINADDRESS") &&
@@ -181,10 +183,11 @@ static int add_symbols (cs46xx_t * chip, dsp_module_desc_t * module)
return 0;
}
-static symbol_entry_t * add_symbol (cs46xx_t * chip, char * symbol_name, u32 address, int type)
+static struct dsp_symbol_entry *
+add_symbol (struct snd_cs46xx * chip, char * symbol_name, u32 address, int type)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- symbol_entry_t * symbol = NULL;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_symbol_entry * symbol = NULL;
int index;
if (ins->symbol_table.nsymbols == (DSP_MAX_SYMBOLS - 1)) {
@@ -217,17 +220,17 @@ static symbol_entry_t * add_symbol (cs46xx_t * chip, char * symbol_name, u32 add
return symbol;
}
-dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
+struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip)
{
- dsp_spos_instance_t * ins = kmalloc(sizeof(dsp_spos_instance_t), GFP_KERNEL);
+ struct dsp_spos_instance * ins = kzalloc(sizeof(struct dsp_spos_instance), GFP_KERNEL);
if (ins == NULL)
return NULL;
- memset(ins, 0, sizeof(*ins));
/* better to use vmalloc for this big table */
ins->symbol_table.nsymbols = 0;
- ins->symbol_table.symbols = vmalloc(sizeof(symbol_entry_t) * DSP_MAX_SYMBOLS);
+ ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) *
+ DSP_MAX_SYMBOLS);
ins->symbol_table.highest_frag_index = 0;
if (ins->symbol_table.symbols == NULL) {
@@ -248,7 +251,7 @@ dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
ins->ntask = 0;
ins->nmodules = 0;
- ins->modules = kmalloc(sizeof(dsp_module_desc_t) * DSP_MAX_MODULES, GFP_KERNEL);
+ ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL);
if (ins->modules == NULL) {
cs46xx_dsp_spos_destroy(chip);
@@ -277,10 +280,10 @@ dsp_spos_instance_t * cs46xx_dsp_spos_create (cs46xx_t * chip)
return ins;
}
-void cs46xx_dsp_spos_destroy (cs46xx_t * chip)
+void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip)
{
int i;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert(ins != NULL, return);
@@ -298,12 +301,12 @@ void cs46xx_dsp_spos_destroy (cs46xx_t * chip)
up(&chip->spos_mutex);
}
-int cs46xx_dsp_load_module (cs46xx_t * chip, dsp_module_desc_t * module)
+int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- segment_desc_t * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
- segment_desc_t * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
- segment_desc_t * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM);
+ struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER);
+ struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE);
u32 doffset, dsize;
if (ins->nmodules == DSP_MAX_MODULES - 1) {
@@ -410,10 +413,11 @@ int cs46xx_dsp_load_module (cs46xx_t * chip, dsp_module_desc_t * module)
return 0;
}
-symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip, char * symbol_name, int symbol_type)
+struct dsp_symbol_entry *
+cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, int symbol_type)
{
int i;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
@@ -435,10 +439,12 @@ symbol_entry_t * cs46xx_dsp_lookup_symbol (cs46xx_t * chip, char * symbol_name,
}
-static symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 address, int symbol_type)
+#ifdef CONFIG_PROC_FS
+static struct dsp_symbol_entry *
+cs46xx_dsp_lookup_symbol_addr (struct snd_cs46xx * chip, u32 address, int symbol_type)
{
int i;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
for ( i = 0; i < ins->symbol_table.nsymbols; ++i ) {
@@ -456,10 +462,11 @@ static symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 addr
}
-static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_symbol_table_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = entry->private_data;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i;
snd_iprintf(buffer, "SYMBOLS:\n");
@@ -483,10 +490,11 @@ static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info
}
-static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_modules_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = entry->private_data;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i,j;
down(&chip->spos_mutex);
@@ -497,7 +505,7 @@ static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buff
snd_iprintf(buffer, " %d fixups\n", ins->modules[i].nfixups);
for (j = 0; j < ins->modules[i].nsegments; ++ j) {
- segment_desc_t * desc = (ins->modules[i].segments + j);
+ struct dsp_segment_desc * desc = (ins->modules[i].segments + j);
snd_iprintf(buffer, " segment %02x offset %08x size %08x\n",
desc->segment_type,desc->offset, desc->size);
}
@@ -505,11 +513,12 @@ static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buff
up(&chip->spos_mutex);
}
-static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_task_tree_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- int i,j,col;
+ struct snd_cs46xx *chip = entry->private_data;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ int i, j, col;
void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
down(&chip->spos_mutex);
@@ -532,10 +541,11 @@ static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_bu
up(&chip->spos_mutex);
}
-static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_scb_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_cs46xx *chip = entry->private_data;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i;
down(&chip->spos_mutex);
@@ -564,13 +574,14 @@ static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t
up(&chip->spos_mutex);
}
-static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_parameter_dump_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
- /*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
- unsigned int i,col = 0;
+ struct snd_cs46xx *chip = entry->private_data;
+ /*struct dsp_spos_instance * ins = chip->dsp_spos_instance; */
+ unsigned int i, col = 0;
void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
- symbol_entry_t * symbol;
+ struct dsp_symbol_entry * symbol;
for (i = 0;i < DSP_PARAMETER_BYTE_SIZE; i += sizeof(u32),col ++) {
if (col == 4) {
@@ -591,9 +602,10 @@ static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_in
}
}
-static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+static void cs46xx_dsp_proc_sample_dump_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- cs46xx_t *chip = entry->private_data;
+ struct snd_cs46xx *chip = entry->private_data;
int i,col = 0;
void __iomem *dst = chip->region.idx[2].remap_addr;
@@ -738,10 +750,10 @@ static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_
snd_iprintf(buffer,"\n");
}
-int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip)
+int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
{
- snd_info_entry_t *entry;
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct snd_info_entry *entry;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i;
ins->snd_card = card;
@@ -852,9 +864,9 @@ int cs46xx_dsp_proc_init (snd_card_t * card, cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_proc_done (cs46xx_t *chip)
+int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int i;
if (ins->proc_sym_info_entry) {
@@ -901,9 +913,11 @@ int cs46xx_dsp_proc_done (cs46xx_t *chip)
return 0;
}
+#endif /* CONFIG_PROC_FS */
static int debug_tree;
-static void _dsp_create_task_tree (cs46xx_t *chip,u32 * task_data, u32 dest, int size)
+static void _dsp_create_task_tree (struct snd_cs46xx *chip, u32 * task_data,
+ u32 dest, int size)
{
void __iomem *spdst = chip->region.idx[1].remap_addr +
DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
@@ -917,7 +931,7 @@ static void _dsp_create_task_tree (cs46xx_t *chip,u32 * task_data, u32 dest, in
}
static int debug_scb;
-static void _dsp_create_scb (cs46xx_t *chip,u32 * scb_data, u32 dest)
+static void _dsp_create_scb (struct snd_cs46xx *chip, u32 * scb_data, u32 dest)
{
void __iomem *spdst = chip->region.idx[1].remap_addr +
DSP_PARAMETER_BYTE_OFFSET + dest * sizeof(u32);
@@ -930,7 +944,7 @@ static void _dsp_create_scb (cs46xx_t *chip,u32 * scb_data, u32 dest)
}
}
-static int find_free_scb_index (dsp_spos_instance_t * ins)
+static int find_free_scb_index (struct dsp_spos_instance * ins)
{
int index = ins->nscb, i;
@@ -944,10 +958,10 @@ static int find_free_scb_index (dsp_spos_instance_t * ins)
return index;
}
-static dsp_scb_descriptor_t * _map_scb (cs46xx_t *chip,char * name,u32 dest)
+static struct dsp_scb_descriptor * _map_scb (struct snd_cs46xx *chip, char * name, u32 dest)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * desc = NULL;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * desc = NULL;
int index;
if (ins->nscb == DSP_MAX_SCB_DESC - 1) {
@@ -977,10 +991,11 @@ static dsp_scb_descriptor_t * _map_scb (cs46xx_t *chip,char * name,u32 dest)
return desc;
}
-static dsp_task_descriptor_t * _map_task_tree (cs46xx_t *chip,char * name,u32 dest,u32 size)
+static struct dsp_task_descriptor *
+_map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_task_descriptor_t * desc = NULL;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_task_descriptor * desc = NULL;
if (ins->ntask == DSP_MAX_TASK_DESC - 1) {
snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n");
@@ -1000,9 +1015,10 @@ static dsp_task_descriptor_t * _map_task_tree (cs46xx_t *chip,char * name,u32 de
return desc;
}
-dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest)
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest)
{
- dsp_scb_descriptor_t * desc;
+ struct dsp_scb_descriptor * desc;
desc = _map_scb (chip,name,dest);
if (desc) {
@@ -1015,9 +1031,11 @@ dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 *
}
-static dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name, u32 * task_data,u32 dest,int size)
+static struct dsp_task_descriptor *
+cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_data,
+ u32 dest, int size)
{
- dsp_task_descriptor_t * desc;
+ struct dsp_task_descriptor * desc;
desc = _map_task_tree (chip,name,dest,size);
if (desc) {
@@ -1029,31 +1047,31 @@ static dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char
return desc;
}
-int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
+int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- symbol_entry_t * fg_task_tree_header_code;
- symbol_entry_t * task_tree_header_code;
- symbol_entry_t * task_tree_thread;
- symbol_entry_t * null_algorithm;
- symbol_entry_t * magic_snoop_task;
-
- dsp_scb_descriptor_t * timing_master_scb;
- dsp_scb_descriptor_t * codec_out_scb;
- dsp_scb_descriptor_t * codec_in_scb;
- dsp_scb_descriptor_t * src_task_scb;
- dsp_scb_descriptor_t * master_mix_scb;
- dsp_scb_descriptor_t * rear_mix_scb;
- dsp_scb_descriptor_t * record_mix_scb;
- dsp_scb_descriptor_t * write_back_scb;
- dsp_scb_descriptor_t * vari_decimate_scb;
- dsp_scb_descriptor_t * rear_codec_out_scb;
- dsp_scb_descriptor_t * clfe_codec_out_scb;
- dsp_scb_descriptor_t * magic_snoop_scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_symbol_entry * fg_task_tree_header_code;
+ struct dsp_symbol_entry * task_tree_header_code;
+ struct dsp_symbol_entry * task_tree_thread;
+ struct dsp_symbol_entry * null_algorithm;
+ struct dsp_symbol_entry * magic_snoop_task;
+
+ struct dsp_scb_descriptor * timing_master_scb;
+ struct dsp_scb_descriptor * codec_out_scb;
+ struct dsp_scb_descriptor * codec_in_scb;
+ struct dsp_scb_descriptor * src_task_scb;
+ struct dsp_scb_descriptor * master_mix_scb;
+ struct dsp_scb_descriptor * rear_mix_scb;
+ struct dsp_scb_descriptor * record_mix_scb;
+ struct dsp_scb_descriptor * write_back_scb;
+ struct dsp_scb_descriptor * vari_decimate_scb;
+ struct dsp_scb_descriptor * rear_codec_out_scb;
+ struct dsp_scb_descriptor * clfe_codec_out_scb;
+ struct dsp_scb_descriptor * magic_snoop_scb;
- int fifo_addr,fifo_span,valid_slots;
+ int fifo_addr, fifo_span, valid_slots;
- static spos_control_block_t sposcb = {
+ static struct dsp_spos_control_block sposcb = {
/* 0 */ HFG_TREE_SCB,HFG_STACK,
/* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
/* 2 */ DSP_SPOS_DC,0,
@@ -1106,7 +1124,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
{
/* create the null SCB */
- static generic_scb_t null_scb = {
+ static struct dsp_generic_scb null_scb = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
NULL_SCB_ADDR, NULL_SCB_ADDR,
@@ -1128,7 +1146,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
{
/* setup foreground task tree */
- static task_tree_control_block_t fg_task_tree_hdr = {
+ static struct dsp_task_tree_control_block fg_task_tree_hdr = {
{ FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
DSP_SPOS_DC_DC,
DSP_SPOS_DC_DC,
@@ -1204,7 +1222,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
{
/* setup foreground task tree */
- static task_tree_control_block_t bg_task_tree_hdr = {
+ static struct dsp_task_tree_control_block bg_task_tree_hdr = {
{ DSP_SPOS_DC_DC,
DSP_SPOS_DC_DC,
DSP_SPOS_DC_DC,
@@ -1313,7 +1331,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
if (!write_back_scb) goto _fail_end;
{
- static mix2_ostream_spb_t mix2_ostream_spb = {
+ static struct dsp_mix2_ostream_spb mix2_ostream_spb = {
0x00020000,
0x0000ffff
};
@@ -1448,13 +1466,14 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
return -EINVAL;
}
-static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry)
+static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
+ struct dsp_scb_descriptor * fg_entry)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- symbol_entry_t * s16_async_codec_input_task;
- symbol_entry_t * spdifo_task;
- symbol_entry_t * spdifi_task;
- dsp_scb_descriptor_t * spdifi_scb_desc,* spdifo_scb_desc,* async_codec_scb_desc;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_symbol_entry * s16_async_codec_input_task;
+ struct dsp_symbol_entry * spdifo_task;
+ struct dsp_symbol_entry * spdifi_task;
+ struct dsp_scb_descriptor * spdifi_scb_desc, * spdifo_scb_desc, * async_codec_scb_desc;
s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE);
if (s16_async_codec_input_task == NULL) {
@@ -1475,7 +1494,7 @@ static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entr
{
/* 0xBC0 */
- spdifoscb_t spdifo_scb = {
+ struct dsp_spdifoscb spdifo_scb = {
/* 0 */ DSP_SPOS_UUUU,
{
/* 1 */ 0xb0,
@@ -1504,7 +1523,7 @@ static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entr
};
/* 0xBB0 */
- spdifiscb_t spdifi_scb = {
+ struct dsp_spdifiscb spdifi_scb = {
/* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI,
/* 1 */ 0,
/* 2 */ 0,
@@ -1529,7 +1548,7 @@ static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entr
};
/* 0xBA0 */
- async_codec_input_scb_t async_codec_input_scb = {
+ struct dsp_async_codec_input_scb async_codec_input_scb = {
/* 0 */ DSP_SPOS_UUUU,
/* 1 */ 0,
/* 2 */ 0,
@@ -1620,9 +1639,9 @@ static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entr
}
-static void cs46xx_dsp_disable_spdif_hw (cs46xx_t *chip)
+static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
/* set SPDIF output FIFO slot */
snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);
@@ -1641,9 +1660,9 @@ static void cs46xx_dsp_disable_spdif_hw (cs46xx_t *chip)
ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED;
}
-int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_hw (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
/* if hw-ctrl already enabled, turn off to reset logic ... */
cs46xx_dsp_disable_spdif_hw (chip);
@@ -1664,9 +1683,9 @@ int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_in (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
/* turn on amplifier */
chip->active_ctrl(chip, 1);
@@ -1724,9 +1743,9 @@ int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip)
+int cs46xx_dsp_disable_spdif_in (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL);
snd_assert (ins->spdif_in_src != NULL,return -EINVAL);
@@ -1750,9 +1769,9 @@ int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip)
+int cs46xx_dsp_enable_pcm_capture (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->pcm_input == NULL,return -EINVAL);
snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL);
@@ -1765,9 +1784,9 @@ int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip)
+int cs46xx_dsp_disable_pcm_capture (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->pcm_input != NULL,return -EINVAL);
@@ -1779,9 +1798,9 @@ int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip)
+int cs46xx_dsp_enable_adc_capture (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->adc_input == NULL,return -EINVAL);
snd_assert (ins->codec_in_scb != NULL,return -EINVAL);
@@ -1794,9 +1813,9 @@ int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip)
+int cs46xx_dsp_disable_adc_capture (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->adc_input != NULL,return -EINVAL);
@@ -1808,7 +1827,7 @@ int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip)
return 0;
}
-int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data)
+int cs46xx_poke_via_dsp (struct snd_cs46xx *chip, u32 address, u32 data)
{
u32 temp;
int i;
@@ -1845,10 +1864,10 @@ int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data)
return 0;
}
-int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right)
+int cs46xx_dsp_set_dac_volume (struct snd_cs46xx * chip, u16 left, u16 right)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb;
down(&chip->spos_mutex);
@@ -1874,8 +1893,9 @@ int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right)
return 0;
}
-int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right) {
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right)
+{
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
down(&chip->spos_mutex);
diff --git a/sound/pci/cs46xx/dsp_spos.h b/sound/pci/cs46xx/dsp_spos.h
index 90871bf9762f..0d246bca4184 100644
--- a/sound/pci/cs46xx/dsp_spos.h
+++ b/sound/pci/cs46xx/dsp_spos.h
@@ -43,7 +43,7 @@
/* this instruction types
needs to be reallocated when load
code into DSP */
-typedef enum {
+enum wide_opcode {
WIDE_FOR_BEGIN_LOOP = 0x20,
WIDE_FOR_BEGIN_LOOP2,
@@ -58,7 +58,7 @@ typedef enum {
WIDE_TBEQ_COND_CALL1_ADDR,
WIDE_TBEQ_NCOND_GOTOI_ADDR,
WIDE_TBEQ_NCOND_CALL1_ADDR,
-} wide_opcode_t;
+};
/* SAMPLE segment */
#define VARI_DECIMATE_BUF1 0x0000
@@ -186,7 +186,8 @@ typedef enum {
#define SP_SPDOUT_CONTROL 0x804D
#define SP_SPDOUT_CSUV 0x808E
-static inline u8 _wrap_all_bits (u8 val) {
+static inline u8 _wrap_all_bits (u8 val)
+{
u8 wrapped;
/* wrap all 8 bits */
@@ -201,11 +202,10 @@ static inline u8 _wrap_all_bits (u8 val) {
((val & 0x80) >> 7);
return wrapped;
-
}
-
-static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descriptor_t * scb)
+static inline void cs46xx_dsp_spos_update_scb (struct snd_cs46xx * chip,
+ struct dsp_scb_descriptor * scb)
{
/* update nextSCB and subListPtr in SCB */
snd_cs46xx_poke(chip,
@@ -214,8 +214,10 @@ static inline void cs46xx_dsp_spos_update_scb (cs46xx_t * chip,dsp_scb_descripto
(scb->next_scb_ptr->address));
}
-static inline void cs46xx_dsp_scb_set_volume (cs46xx_t * chip,dsp_scb_descriptor_t * scb,
- u16 left,u16 right) {
+static inline void cs46xx_dsp_scb_set_volume (struct snd_cs46xx * chip,
+ struct dsp_scb_descriptor * scb,
+ u16 left, u16 right)
+{
unsigned int val = ((0xffff - left) << 16 | (0xffff - right));
snd_cs46xx_poke(chip, (scb->address + SCBVolumeCtrl) << 2, val);
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 92849e1340bb..509aa2b63331 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -36,14 +36,14 @@
#include "cs46xx_lib.h"
#include "dsp_spos.h"
-typedef struct _proc_scb_info_t {
- dsp_scb_descriptor_t * scb_desc;
- cs46xx_t *chip;
-} proc_scb_info_t;
+struct proc_scb_info {
+ struct dsp_scb_descriptor * scb_desc;
+ struct snd_cs46xx *chip;
+};
-static void remove_symbol (cs46xx_t * chip,symbol_entry_t * symbol)
+static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
int symbol_index = (int)(symbol - ins->symbol_table.symbols);
snd_assert(ins->symbol_table.nsymbols > 0,return);
@@ -64,12 +64,14 @@ static void remove_symbol (cs46xx_t * chip,symbol_entry_t * symbol)
}
-static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
+#ifdef CONFIG_PROC_FS
+static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- proc_scb_info_t * scb_info = (proc_scb_info_t *)entry->private_data;
- dsp_scb_descriptor_t * scb = scb_info->scb_desc;
- dsp_spos_instance_t * ins;
- cs46xx_t *chip = scb_info->chip;
+ struct proc_scb_info * scb_info = entry->private_data;
+ struct dsp_scb_descriptor * scb = scb_info->scb_desc;
+ struct dsp_spos_instance * ins;
+ struct snd_cs46xx *chip = scb_info->chip;
int j,col;
void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -105,10 +107,11 @@ static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buf
snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count);
up(&chip->spos_mutex);
}
+#endif
-static void _dsp_unlink_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
+static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
unsigned long flags;
if ( scb->parent_scb_ptr ) {
@@ -160,7 +163,8 @@ static void _dsp_unlink_scb (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
}
}
-static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, int dword_count)
+static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr,
+ int dword_count)
{
void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
int i;
@@ -171,9 +175,9 @@ static void _dsp_clear_sample_buffer (cs46xx_t *chip, u32 sample_buffer_addr, in
}
}
-void cs46xx_dsp_remove_scb (cs46xx_t *chip, dsp_scb_descriptor_t * scb)
+void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
/* check integrety */
snd_assert ( (scb->index >= 0 &&
@@ -218,10 +222,11 @@ void cs46xx_dsp_remove_scb (cs46xx_t *chip, dsp_scb_descriptor_t * scb)
}
-void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb)
+#ifdef CONFIG_PROC_FS
+void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb)
{
if (scb->proc_info) {
- proc_scb_info_t * scb_info = (proc_scb_info_t *)scb->proc_info->private_data;
+ struct proc_scb_info * scb_info = scb->proc_info->private_data;
snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name);
@@ -233,11 +238,12 @@ void cs46xx_dsp_proc_free_scb_desc (dsp_scb_descriptor_t * scb)
}
}
-void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * scb)
+void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
+ struct dsp_scb_descriptor * scb)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- snd_info_entry_t * entry;
- proc_scb_info_t * scb_info;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct snd_info_entry * entry;
+ struct proc_scb_info * scb_info;
/* register to proc */
if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL &&
@@ -245,7 +251,7 @@ void cs46xx_dsp_proc_register_scb_desc (cs46xx_t *chip,dsp_scb_descriptor_t * sc
if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name,
ins->proc_dsp_dir)) != NULL) {
- scb_info = kmalloc(sizeof(proc_scb_info_t), GFP_KERNEL);
+ scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL);
if (!scb_info) {
snd_info_free_entry(entry);
entry = NULL;
@@ -272,15 +278,16 @@ out:
scb->proc_info = entry;
}
}
+#endif /* CONFIG_PROC_FS */
-static dsp_scb_descriptor_t *
-_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
- symbol_entry_t * task_entry,
- dsp_scb_descriptor_t * parent_scb,
+static struct dsp_scb_descriptor *
+_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest,
+ struct dsp_symbol_entry * task_entry,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb;
unsigned long flags;
@@ -342,13 +349,13 @@ _dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
return scb;
}
-static dsp_scb_descriptor_t *
-cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest,
- char * task_entry_name,
- dsp_scb_descriptor_t * parent_scb,
+static struct dsp_scb_descriptor *
+cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data,
+ u32 dest, char * task_entry_name,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- symbol_entry_t * task_entry;
+ struct dsp_symbol_entry * task_entry;
task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name,
SYMBOL_CODE);
@@ -362,12 +369,12 @@ cs46xx_dsp_create_generic_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 de
parent_scb,scb_child_type);
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip)
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- timing_master_scb_t timing_master_scb = {
+ struct dsp_timing_master_scb timing_master_scb = {
{ 0,
0,
0,
@@ -396,16 +403,15 @@ cs46xx_dsp_create_timing_master_scb (cs46xx_t *chip)
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,
- u16 channel_disp,u16 fifo_addr,
- u16 child_scb_addr,
- u32 dest,dsp_scb_descriptor_t * parent_scb,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name,
+ u16 channel_disp, u16 fifo_addr, u16 child_scb_addr,
+ u32 dest, struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- codec_output_scb_t codec_out_scb = {
+ struct dsp_codec_output_scb codec_out_scb = {
{ 0,
0,
0,
@@ -435,16 +441,15 @@ cs46xx_dsp_create_codec_out_scb(cs46xx_t * chip,char * codec_name,
return scb;
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
- u16 channel_disp,u16 fifo_addr,
- u16 sample_buffer_addr,
- u32 dest,dsp_scb_descriptor_t * parent_scb,
- int scb_child_type)
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
+ u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr,
+ u32 dest, struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
- codec_input_scb_t codec_input_scb = {
+ struct dsp_scb_descriptor * scb;
+ struct dsp_codec_input_scb codec_input_scb = {
{ 0,
0,
0,
@@ -481,17 +486,17 @@ cs46xx_dsp_create_codec_in_scb(cs46xx_t * chip,char * codec_name,
}
-static dsp_scb_descriptor_t *
-cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name,
- u16 sample_buffer_addr,u32 dest,
+static struct dsp_scb_descriptor *
+cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 sample_buffer_addr, u32 dest,
int virtual_channel, u32 playback_hw_addr,
- dsp_scb_descriptor_t * parent_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb;
- generic_scb_t pcm_reader_scb = {
+ struct dsp_generic_scb pcm_reader_scb = {
/*
Play DMA Task xfers data from host buffer to SP buffer
@@ -584,18 +589,18 @@ cs46xx_dsp_create_pcm_reader_scb(cs46xx_t * chip,char * scb_name,
#define GOF_PER_SEC 200
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
int rate,
u16 src_buffer_addr,
- u16 src_delay_buffer_addr,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+ u16 src_delay_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type,
int pass_through)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb;
unsigned int tmp1, tmp2;
unsigned int phiIncr;
unsigned int correctionPerGOF, correctionPerSec;
@@ -632,7 +637,7 @@ cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
correctionPerSec = tmp1;
{
- src_task_scb_t src_task_scb = {
+ struct dsp_src_task_scb src_task_scb = {
0x0028,0x00c8,
0x5555,0x0000,
0x0000,0x0000,
@@ -688,14 +693,14 @@ cs46xx_dsp_create_src_task_scb(cs46xx_t * chip,char * scb_name,
}
#if 0 /* not used */
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name,
- u16 buffer_addr,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type) {
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- filter_scb_t filter_scb = {
+ struct dsp_filter_scb filter_scb = {
.a0_right = 0x41a9,
.a0_left = 0x41a9,
.a1_right = 0xb8e4,
@@ -738,15 +743,15 @@ cs46xx_dsp_create_filter_scb(cs46xx_t * chip,char * scb_name,
}
#endif /* not used */
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
- u16 mix_buffer_addr,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 mix_buffer_addr, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- mix_only_scb_t master_mix_scb = {
+ struct dsp_mix_only_scb master_mix_scb = {
/* 0 */ { 0,
/* 1 */ 0,
/* 2 */ mix_buffer_addr,
@@ -778,15 +783,15 @@ cs46xx_dsp_create_mix_only_scb(cs46xx_t * chip,char * scb_name,
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
- u16 mix_buffer_addr,u16 writeback_spb,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
+ u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- mix2_ostream_scb_t mix2_ostream_scb = {
+ struct dsp_mix2_ostream_scb mix2_ostream_scb = {
/* Basic (non scatter/gather) DMA requestor (4 ints) */
{
DMA_RQ_C1_SOURCE_MOD64 +
@@ -832,18 +837,18 @@ cs46xx_dsp_create_mix_to_ostream_scb(cs46xx_t * chip,char * scb_name,
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name,
u16 vari_buffer_addr0,
u16 vari_buffer_addr1,
u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- vari_decimate_scb_t vari_decimate_scb = {
+ struct dsp_vari_decimate_scb vari_decimate_scb = {
0x0028,0x00c8,
0x5555,0x0000,
0x0000,0x0000,
@@ -876,17 +881,17 @@ cs46xx_dsp_create_vari_decimate_scb(cs46xx_t * chip,char * scb_name,
}
-static dsp_scb_descriptor_t *
-cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- dsp_scb_descriptor_t * input_scb,
- dsp_scb_descriptor_t * parent_scb,
+static struct dsp_scb_descriptor *
+cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
+ struct dsp_scb_descriptor * input_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- pcm_serial_input_scb_t pcm_serial_input_scb = {
+ struct dsp_pcm_serial_input_scb pcm_serial_input_scb = {
{ 0,
0,
0,
@@ -919,17 +924,17 @@ cs46xx_dsp_create_pcm_serial_input_scb(cs46xx_t * chip,char * scb_name,u32 dest,
}
-static dsp_scb_descriptor_t *
-cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
+static struct dsp_scb_descriptor *
+cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
u16 hfg_scb_address,
u16 asynch_buffer_address,
- dsp_scb_descriptor_t * parent_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- asynch_fg_tx_scb_t asynch_fg_tx_scb = {
+ struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = {
0xfc00,0x03ff, /* Prototype sample buffer size of 256 dwords */
0x0058,0x0028, /* Min Delta 7 dwords == 28 bytes */
/* : Max delta 25 dwords == 100 bytes */
@@ -966,17 +971,17 @@ cs46xx_dsp_create_asynch_fg_tx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
}
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
u16 hfg_scb_address,
u16 asynch_buffer_address,
- dsp_scb_descriptor_t * parent_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb;
- asynch_fg_rx_scb_t asynch_fg_rx_scb = {
+ struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = {
0xfe00,0x01ff, /* Prototype sample buffer size of 128 dwords */
0x0064,0x001c, /* Min Delta 7 dwords == 28 bytes */
/* : Max delta 25 dwords == 100 bytes */
@@ -1016,17 +1021,17 @@ cs46xx_dsp_create_asynch_fg_rx_scb(cs46xx_t * chip,char * scb_name,u32 dest,
#if 0 /* not used */
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
u16 snoop_buffer_address,
- dsp_scb_descriptor_t * snoop_scb,
- dsp_scb_descriptor_t * parent_scb,
+ struct dsp_scb_descriptor * snoop_scb,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- output_snoop_scb_t output_snoop_scb = {
+ struct dsp_output_snoop_scb output_snoop_scb = {
{ 0, /* not used. Zero */
0,
0,
@@ -1058,14 +1063,14 @@ cs46xx_dsp_create_output_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
#endif /* not used */
-dsp_scb_descriptor_t *
-cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- dsp_scb_descriptor_t * parent_scb,
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
+ struct dsp_scb_descriptor * parent_scb,
int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- spio_write_scb_t spio_write_scb = {
+ struct dsp_spio_write_scb spio_write_scb = {
0,0, /* SPIOWAddress2:SPIOWAddress1; */
0, /* SPIOWData1; */
0, /* SPIOWData2; */
@@ -1094,15 +1099,16 @@ cs46xx_dsp_create_spio_write_scb(cs46xx_t * chip,char * scb_name,u32 dest,
return scb;
}
-dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char * scb_name,u32 dest,
- u16 snoop_buffer_address,
- dsp_scb_descriptor_t * snoop_scb,
- dsp_scb_descriptor_t * parent_scb,
- int scb_child_type)
+struct dsp_scb_descriptor *
+cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
+ u16 snoop_buffer_address,
+ struct dsp_scb_descriptor * snoop_scb,
+ struct dsp_scb_descriptor * parent_scb,
+ int scb_child_type)
{
- dsp_scb_descriptor_t * scb;
+ struct dsp_scb_descriptor * scb;
- magic_snoop_task_t magic_snoop_scb = {
+ struct dsp_magic_snoop_task magic_snoop_scb = {
/* 0 */ 0, /* i0 */
/* 1 */ 0, /* i1 */
/* 2 */ snoop_buffer_address << 0x10,
@@ -1129,10 +1135,11 @@ dsp_scb_descriptor_t * cs46xx_dsp_create_magic_snoop_scb(cs46xx_t * chip,char *
return scb;
}
-static dsp_scb_descriptor_t * find_next_free_scb (cs46xx_t * chip,dsp_scb_descriptor_t * from)
+static struct dsp_scb_descriptor *
+find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * scb = from;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * scb = from;
while (scb->next_scb_ptr != ins->the_null_scb) {
snd_assert (scb->next_scb_ptr != NULL, return NULL);
@@ -1212,18 +1219,19 @@ static u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
0x2B00
};
-pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,
- u32 sample_rate, void * private_data,
- u32 hw_dma_addr,
- int pcm_channel_id)
+struct dsp_pcm_channel_descriptor *
+cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip,
+ u32 sample_rate, void * private_data,
+ u32 hw_dma_addr,
+ int pcm_channel_id)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * src_scb = NULL,* pcm_scb, * mixer_scb = NULL;
- dsp_scb_descriptor_t * src_parent_scb = NULL;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL;
+ struct dsp_scb_descriptor * src_parent_scb = NULL;
- /* dsp_scb_descriptor_t * pcm_parent_scb; */
+ /* struct dsp_scb_descriptor * pcm_parent_scb; */
char scb_name[DSP_MAX_SCB_NAME];
- int i,pcm_index = -1, insert_point, src_index = -1,pass_through = 0;
+ int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0;
unsigned long flags;
switch (pcm_channel_id) {
@@ -1371,8 +1379,8 @@ pcm_channel_descriptor_t * cs46xx_dsp_create_pcm_channel (cs46xx_t * chip,
return (ins->pcm_channels + pcm_index);
}
-int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
- pcm_channel_descriptor_t * pcm_channel,
+int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel,
int period_size)
{
u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2);
@@ -1410,7 +1418,7 @@ int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip,
return 0;
}
-int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
+int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip,
int period_size)
{
u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
@@ -1448,9 +1456,10 @@ int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip,
return 0;
}
-void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
+void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
unsigned long flags;
snd_assert(pcm_channel->active, return );
@@ -1478,9 +1487,10 @@ void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t *
}
}
-int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
+int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
unsigned long flags;
snd_assert(pcm_channel->active,return -EIO);
@@ -1503,11 +1513,12 @@ int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channe
return 0;
}
-int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
+int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
+ struct dsp_pcm_channel_descriptor * pcm_channel)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * parent_scb;
- dsp_scb_descriptor_t * src_scb = pcm_channel->src_scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * parent_scb;
+ struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb;
unsigned long flags;
spin_lock(&pcm_channel->src_scb->lock);
@@ -1544,12 +1555,13 @@ int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel)
return 0;
}
-dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source,
- u16 addr,char * scb_name)
+struct dsp_scb_descriptor *
+cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
+ u16 addr, char * scb_name)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * parent;
- dsp_scb_descriptor_t * pcm_input;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * parent;
+ struct dsp_scb_descriptor * pcm_input;
int insert_point;
snd_assert (ins->record_mixer_scb != NULL,return NULL);
@@ -1569,7 +1581,7 @@ dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descript
return pcm_input;
}
-int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src)
+int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
{
snd_assert (src->parent_scb_ptr != NULL, return -EINVAL );
@@ -1581,10 +1593,10 @@ int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src)
return 0;
}
-int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
+int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
- dsp_scb_descriptor_t * parent_scb;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
+ struct dsp_scb_descriptor * parent_scb;
snd_assert (src->parent_scb_ptr == NULL, return -EINVAL );
snd_assert(ins->master_mix_scb !=NULL, return -EINVAL );
@@ -1605,9 +1617,9 @@ int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
return 0;
}
-int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
+int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
cs46xx_dsp_enable_spdif_hw (chip);
@@ -1653,9 +1665,9 @@ int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip)
return 0;
}
-int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
+int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
/* dont touch anything if SPDIF is open */
if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
@@ -1685,9 +1697,9 @@ int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
return 0;
}
-int cs46xx_iec958_pre_open (cs46xx_t *chip)
+int cs46xx_iec958_pre_open (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
/* remove AsynchFGTxSCB and and PCMSerialInput_II */
@@ -1718,9 +1730,9 @@ int cs46xx_iec958_pre_open (cs46xx_t *chip)
return 0;
}
-int cs46xx_iec958_post_close (cs46xx_t *chip)
+int cs46xx_iec958_post_close (struct snd_cs46xx *chip)
{
- dsp_spos_instance_t * ins = chip->dsp_spos_instance;
+ struct dsp_spos_instance * ins = chip->dsp_spos_instance;
snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
diff --git a/sound/pci/cs46xx/imgs/cwc4630.h b/sound/pci/cs46xx/imgs/cwc4630.h
index 8bed07f9996e..37c4f1318dc5 100644
--- a/sound/pci/cs46xx/imgs/cwc4630.h
+++ b/sound/pci/cs46xx/imgs/cwc4630.h
@@ -3,7 +3,7 @@
#ifndef __HEADER_cwc4630_H__
#define __HEADER_cwc4630_H__
-static symbol_entry_t cwc4630_symbols[] = {
+static struct dsp_symbol_entry cwc4630_symbols[] = {
{ 0x0000, "BEGINADDRESS",0x00 },
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
@@ -302,12 +302,12 @@ static u32 cwc4630_parameter[] = {
}; /* #PARAMETER_END */
-static segment_desc_t cwc4630_segments[] = {
+static struct dsp_segment_desc cwc4630_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000328, cwc4630_code },
{ SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000080, cwc4630_parameter },
};
-static dsp_module_desc_t cwc4630_module = {
+static struct dsp_module_desc cwc4630_module = {
"cwc4630",
{
38,
diff --git a/sound/pci/cs46xx/imgs/cwcasync.h b/sound/pci/cs46xx/imgs/cwcasync.h
index e01a7b66c4ff..70e63e13c2b3 100644
--- a/sound/pci/cs46xx/imgs/cwcasync.h
+++ b/sound/pci/cs46xx/imgs/cwcasync.h
@@ -3,7 +3,7 @@
#ifndef __HEADER_cwcasync_H__
#define __HEADER_cwcasync_H__
-static symbol_entry_t cwcasync_symbols[] = {
+static struct dsp_symbol_entry cwcasync_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
@@ -159,11 +159,11 @@ static u32 cwcasync_code[] = {
};
/* #CODE_END */
-static segment_desc_t cwcasync_segments[] = {
+static struct dsp_segment_desc cwcasync_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x000001b6, cwcasync_code },
};
-static dsp_module_desc_t cwcasync_module = {
+static struct dsp_module_desc cwcasync_module = {
"cwcasync",
{
32,
diff --git a/sound/pci/cs46xx/imgs/cwcbinhack.h b/sound/pci/cs46xx/imgs/cwcbinhack.h
index 436b38bd246c..f4d93689cd49 100644
--- a/sound/pci/cs46xx/imgs/cwcbinhack.h
+++ b/sound/pci/cs46xx/imgs/cwcbinhack.h
@@ -4,7 +4,7 @@
#ifndef __HEADER_cwcbinhack_H__
#define __HEADER_cwcbinhack_H__
-static symbol_entry_t cwcbinhack_symbols[] = {
+static struct dsp_symbol_entry cwcbinhack_symbols[] = {
{ 0x02c8, "OVERLAYBEGINADDRESS",0x00 },
{ 0x02c8, "MAGICSNOOPTASK",0x03 },
{ 0x0308, "#CODE_END",0x00 },
@@ -31,11 +31,11 @@ static u32 cwcbinhack_code[] = {
};
/* #CODE_END */
-static segment_desc_t cwcbinhack_segments[] = {
+static struct dsp_segment_desc cwcbinhack_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 64, cwcbinhack_code },
};
-static dsp_module_desc_t cwcbinhack_module = {
+static struct dsp_module_desc cwcbinhack_module = {
"cwcbinhack",
{
3,
diff --git a/sound/pci/cs46xx/imgs/cwcdma.h b/sound/pci/cs46xx/imgs/cwcdma.h
index 92860435beed..7ff0d4587161 100644
--- a/sound/pci/cs46xx/imgs/cwcdma.h
+++ b/sound/pci/cs46xx/imgs/cwcdma.h
@@ -3,7 +3,7 @@
#ifndef __HEADER_cwcdma_H__
#define __HEADER_cwcdma_H__
-static symbol_entry_t cwcdma_symbols[] = {
+static struct dsp_symbol_entry cwcdma_symbols[] = {
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
{ 0x8003, "EXECCHILD_PUSH1IND",0x03 },
@@ -51,11 +51,11 @@ static u32 cwcdma_code[] = {
/* #CODE_END */
-static segment_desc_t cwcdma_segments[] = {
+static struct dsp_segment_desc cwcdma_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x00000030, cwcdma_code },
};
-static dsp_module_desc_t cwcdma_module = {
+static struct dsp_module_desc cwcdma_module = {
"cwcdma",
{
27,
diff --git a/sound/pci/cs46xx/imgs/cwcemb80.h b/sound/pci/cs46xx/imgs/cwcemb80.h
index 4b13551eae41..a64c6ff9983a 100644
--- a/sound/pci/cs46xx/imgs/cwcemb80.h
+++ b/sound/pci/cs46xx/imgs/cwcemb80.h
@@ -3,7 +3,7 @@
#ifndef __HEADER_cwcemb80_H__
#define __HEADER_cwcemb80_H__
-static symbol_entry_t cwcemb80_symbols[] = {
+static struct dsp_symbol_entry cwcemb80_symbols[] = {
{ 0x0000, "BEGINADDRESS",0x00 },
{ 0x8000, "EXECCHILD",0x03 },
{ 0x8001, "EXECCHILD_98",0x03 },
@@ -1588,13 +1588,13 @@ static u32 cwcemb80_sample[] = {
}; /* #SAMPLE_END */
-static segment_desc_t cwcemb80_segments[] = {
+static struct dsp_segment_desc cwcemb80_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000031c, cwcemb80_code },
{ SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000697, cwcemb80_parameter },
{ SEGTYPE_SP_SAMPLE, 0x00000000, 0x00000e00, cwcemb80_sample },
};
-static dsp_module_desc_t cwcemb80_module = {
+static struct dsp_module_desc cwcemb80_module = {
"cwcemb80",
{
38,
diff --git a/sound/pci/cs46xx/imgs/cwcsnoop.h b/sound/pci/cs46xx/imgs/cwcsnoop.h
index be1162bbcb45..6929d0a5a3f3 100644
--- a/sound/pci/cs46xx/imgs/cwcsnoop.h
+++ b/sound/pci/cs46xx/imgs/cwcsnoop.h
@@ -3,7 +3,7 @@
#ifndef __HEADER_cwcsnoop_H__
#define __HEADER_cwcsnoop_H__
-static symbol_entry_t cwcsnoop_symbols[] = {
+static struct dsp_symbol_entry cwcsnoop_symbols[] = {
{ 0x0500, "OVERLAYBEGINADDRESS",0x00 },
{ 0x0500, "OUTPUTSNOOP",0x03 },
{ 0x051f, "#CODE_END",0x00 },
@@ -29,11 +29,11 @@ static u32 cwcsnoop_code[] = {
};
/* #CODE_END */
-static segment_desc_t cwcsnoop_segments[] = {
+static struct dsp_segment_desc cwcsnoop_segments[] = {
{ SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000003e, cwcsnoop_code },
};
-static dsp_module_desc_t cwcsnoop_module = {
+static struct dsp_module_desc cwcsnoop_module = {
"cwcsnoop",
{
3,
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile
new file mode 100644
index 000000000000..08d8ee6547d3
--- /dev/null
+++ b/sound/pci/cs5535audio/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for cs5535audio
+#
+
+snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o
+
+# Toplevel Module Dependency
+obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
new file mode 100644
index 000000000000..f36ede827479
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -0,0 +1,402 @@
+/*
+ * Driver for audio on multifunction CS5535 companion device
+ * Copyright (C) Jaya Kumar
+ *
+ * Based on Jaroslav Kysela and Takashi Iwai's examples.
+ * This work was sponsored by CIS(M) Sdn Bhd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+#include <sound/ac97_codec.h>
+#include <sound/initval.h>
+#include <sound/asoundef.h>
+#include "cs5535audio.h"
+
+#define DRIVER_NAME "cs5535audio"
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+static struct pci_device_id snd_cs5535audio_ids[] = {
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0, },
+ {}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_cs5535audio_ids);
+
+static void wait_till_cmd_acked(struct cs5535audio *cs5535au, unsigned long timeout)
+{
+ unsigned int tmp;
+ do {
+ tmp = cs_readl(cs5535au, ACC_CODEC_CNTL);
+ if (!(tmp & CMD_NEW))
+ break;
+ msleep(10);
+ } while (--timeout);
+ if (!timeout)
+ snd_printk(KERN_ERR "Failure writing to cs5535 codec\n");
+}
+
+static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au,
+ unsigned short reg)
+{
+ unsigned int regdata;
+ unsigned int timeout;
+ unsigned int val;
+
+ regdata = ((unsigned int) reg) << 24;
+ regdata |= ACC_CODEC_CNTL_RD_CMD;
+ regdata |= CMD_NEW;
+
+ cs_writel(cs5535au, ACC_CODEC_CNTL, regdata);
+ wait_till_cmd_acked(cs5535au, 500);
+
+ timeout = 50;
+ do {
+ val = cs_readl(cs5535au, ACC_CODEC_STATUS);
+ if ((val & STS_NEW) && reg == (val >> 24))
+ break;
+ msleep(10);
+ } while (--timeout);
+ if (!timeout)
+ snd_printk(KERN_ERR "Failure reading cs5535 codec\n");
+
+ return (unsigned short) val;
+}
+
+static void snd_cs5535audio_codec_write(struct cs5535audio *cs5535au,
+ unsigned short reg, unsigned short val)
+{
+ unsigned int regdata;
+
+ regdata = ((unsigned int) reg) << 24;
+ regdata |= val;
+ regdata &= CMD_MASK;
+ regdata |= CMD_NEW;
+ regdata &= ACC_CODEC_CNTL_WR_CMD;
+
+ cs_writel(cs5535au, ACC_CODEC_CNTL, regdata);
+ wait_till_cmd_acked(cs5535au, 50);
+}
+
+static void snd_cs5535audio_ac97_codec_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+{
+ struct cs5535audio *cs5535au = ac97->private_data;
+ snd_cs5535audio_codec_write(cs5535au, reg, val);
+}
+
+static unsigned short snd_cs5535audio_ac97_codec_read(struct snd_ac97 *ac97,
+ unsigned short reg)
+{
+ struct cs5535audio *cs5535au = ac97->private_data;
+ return snd_cs5535audio_codec_read(cs5535au, reg);
+}
+
+static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
+{
+ struct snd_card *card = cs5535au->card;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ int err;
+ static struct snd_ac97_bus_ops ops = {
+ .write = snd_cs5535audio_ac97_codec_write,
+ .read = snd_cs5535audio_ac97_codec_read,
+ };
+
+ if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0)
+ return err;
+
+ memset(&ac97, 0, sizeof(ac97));
+ ac97.scaps = AC97_SCAP_AUDIO|AC97_SCAP_SKIP_MODEM;
+ ac97.private_data = cs5535au;
+ ac97.pci = cs5535au->pci;
+
+ if ((err = snd_ac97_mixer(pbus, &ac97, &cs5535au->ac97)) < 0) {
+ snd_printk(KERN_ERR "mixer failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void process_bm0_irq(struct cs5535audio *cs5535au)
+{
+ u8 bm_stat;
+ spin_lock(&cs5535au->reg_lock);
+ bm_stat = cs_readb(cs5535au, ACC_BM0_STATUS);
+ spin_unlock(&cs5535au->reg_lock);
+ if (bm_stat & EOP) {
+ struct cs5535audio_dma *dma;
+ dma = cs5535au->playback_substream->runtime->private_data;
+ snd_pcm_period_elapsed(cs5535au->playback_substream);
+ } else {
+ snd_printk(KERN_ERR "unexpected bm0 irq src, bm_stat=%x\n",
+ bm_stat);
+ }
+}
+
+static void process_bm1_irq(struct cs5535audio *cs5535au)
+{
+ u8 bm_stat;
+ spin_lock(&cs5535au->reg_lock);
+ bm_stat = cs_readb(cs5535au, ACC_BM1_STATUS);
+ spin_unlock(&cs5535au->reg_lock);
+ if (bm_stat & EOP) {
+ struct cs5535audio_dma *dma;
+ dma = cs5535au->capture_substream->runtime->private_data;
+ snd_pcm_period_elapsed(cs5535au->capture_substream);
+ }
+}
+
+static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ u16 acc_irq_stat;
+ u8 bm_stat;
+ unsigned char count;
+ struct cs5535audio *cs5535au = dev_id;
+
+ if (cs5535au == NULL)
+ return IRQ_NONE;
+
+ acc_irq_stat = cs_readw(cs5535au, ACC_IRQ_STATUS);
+
+ if (!acc_irq_stat)
+ return IRQ_NONE;
+ for (count = 0; count < 10; count++) {
+ if (acc_irq_stat & (1 << count)) {
+ switch (count) {
+ case IRQ_STS:
+ cs_readl(cs5535au, ACC_GPIO_STATUS);
+ break;
+ case WU_IRQ_STS:
+ cs_readl(cs5535au, ACC_GPIO_STATUS);
+ break;
+ case BM0_IRQ_STS:
+ process_bm0_irq(cs5535au);
+ break;
+ case BM1_IRQ_STS:
+ process_bm1_irq(cs5535au);
+ break;
+ case BM2_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM2_STATUS);
+ break;
+ case BM3_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM3_STATUS);
+ break;
+ case BM4_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM4_STATUS);
+ break;
+ case BM5_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM5_STATUS);
+ break;
+ case BM6_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM6_STATUS);
+ break;
+ case BM7_IRQ_STS:
+ bm_stat = cs_readb(cs5535au, ACC_BM7_STATUS);
+ break;
+ default:
+ snd_printk(KERN_ERR "Unexpected irq src\n");
+ break;
+ }
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
+{
+ synchronize_irq(cs5535au->irq);
+ pci_set_power_state(cs5535au->pci, 3);
+
+ if (cs5535au->irq >= 0)
+ free_irq(cs5535au->irq, cs5535au);
+
+ pci_release_regions(cs5535au->pci);
+ pci_disable_device(cs5535au->pci);
+ kfree(cs5535au);
+ return 0;
+}
+
+static int snd_cs5535audio_dev_free(struct snd_device *device)
+{
+ struct cs5535audio *cs5535au = device->device_data;
+ return snd_cs5535audio_free(cs5535au);
+}
+
+static int __devinit snd_cs5535audio_create(struct snd_card *card,
+ struct pci_dev *pci,
+ struct cs5535audio **rcs5535au)
+{
+ struct cs5535audio *cs5535au;
+
+ int err;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_cs5535audio_dev_free,
+ };
+
+ *rcs5535au = NULL;
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
+ printk(KERN_WARNING "unable to get 32bit dma\n");
+ err = -ENXIO;
+ goto pcifail;
+ }
+
+ cs5535au = kzalloc(sizeof(*cs5535au), GFP_KERNEL);
+ if (cs5535au == NULL) {
+ err = -ENOMEM;
+ goto pcifail;
+ }
+
+ spin_lock_init(&cs5535au->reg_lock);
+ cs5535au->card = card;
+ cs5535au->pci = pci;
+ cs5535au->irq = -1;
+
+ if ((err = pci_request_regions(pci, "CS5535 Audio")) < 0) {
+ kfree(cs5535au);
+ goto pcifail;
+ }
+
+ cs5535au->port = pci_resource_start(pci, 0);
+
+ if (request_irq(pci->irq, snd_cs5535audio_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, "CS5535 Audio", cs5535au)) {
+ snd_printk("unable to grab IRQ %d\n", pci->irq);
+ err = -EBUSY;
+ goto sndfail;
+ }
+
+ cs5535au->irq = pci->irq;
+ pci_set_master(pci);
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ cs5535au, &ops)) < 0)
+ goto sndfail;
+
+ snd_card_set_dev(card, &pci->dev);
+
+ *rcs5535au = cs5535au;
+ return 0;
+
+sndfail: /* leave the device alive, just kill the snd */
+ snd_cs5535audio_free(cs5535au);
+ return err;
+
+pcifail:
+ pci_disable_device(pci);
+ return err;
+}
+
+static int __devinit snd_cs5535audio_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct snd_card *card;
+ struct cs5535audio *cs5535au;
+ int err;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ if (card == NULL)
+ return -ENOMEM;
+
+ if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0)
+ goto probefail_out;
+
+ if ((err = snd_cs5535audio_mixer(cs5535au)) < 0)
+ goto probefail_out;
+
+ if ((err = snd_cs5535audio_pcm(cs5535au)) < 0)
+ goto probefail_out;
+
+ strcpy(card->driver, DRIVER_NAME);
+
+ strcpy(card->shortname, "CS5535 Audio");
+ sprintf(card->longname, "%s %s at 0x%lx, irq %i",
+ card->shortname, card->driver,
+ cs5535au->port, cs5535au->irq);
+
+ if ((err = snd_card_register(card)) < 0)
+ goto probefail_out;
+
+ pci_set_drvdata(pci, card);
+ dev++;
+ return 0;
+
+probefail_out:
+ snd_card_free(card);
+ return err;
+}
+
+static void __devexit snd_cs5535audio_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+ .name = DRIVER_NAME,
+ .id_table = snd_cs5535audio_ids,
+ .probe = snd_cs5535audio_probe,
+ .remove = __devexit_p(snd_cs5535audio_remove),
+};
+
+static int __init alsa_card_cs5535audio_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_cs5535audio_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_cs5535audio_init)
+module_exit(alsa_card_cs5535audio_exit)
+
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CS5535 Audio");
+MODULE_SUPPORTED_DEVICE("CS5535 Audio");
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
new file mode 100644
index 000000000000..5e55a1a1ed65
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -0,0 +1,123 @@
+#ifndef __SOUND_CS5535AUDIO_H
+#define __SOUND_CS5535AUDIO_H
+
+#define cs_writel(cs5535au, reg, val) outl(val, (cs5535au)->port + reg)
+#define cs_writeb(cs5535au, reg, val) outb(val, (cs5535au)->port + reg)
+#define cs_readl(cs5535au, reg) inl((cs5535au)->port + reg)
+#define cs_readw(cs5535au, reg) inw((cs5535au)->port + reg)
+#define cs_readb(cs5535au, reg) inb((cs5535au)->port + reg)
+
+#define CS5535AUDIO_MAX_DESCRIPTORS 128
+
+/* acc_codec bar0 reg addrs */
+#define ACC_GPIO_STATUS 0x00
+#define ACC_CODEC_STATUS 0x08
+#define ACC_CODEC_CNTL 0x0C
+#define ACC_IRQ_STATUS 0x12
+#define ACC_BM0_CMD 0x20
+#define ACC_BM1_CMD 0x28
+#define ACC_BM2_CMD 0x30
+#define ACC_BM3_CMD 0x38
+#define ACC_BM4_CMD 0x40
+#define ACC_BM5_CMD 0x48
+#define ACC_BM6_CMD 0x50
+#define ACC_BM7_CMD 0x58
+#define ACC_BM0_PRD 0x24
+#define ACC_BM1_PRD 0x2C
+#define ACC_BM2_PRD 0x34
+#define ACC_BM3_PRD 0x3C
+#define ACC_BM4_PRD 0x44
+#define ACC_BM5_PRD 0x4C
+#define ACC_BM6_PRD 0x54
+#define ACC_BM7_PRD 0x5C
+#define ACC_BM0_STATUS 0x21
+#define ACC_BM1_STATUS 0x29
+#define ACC_BM2_STATUS 0x31
+#define ACC_BM3_STATUS 0x39
+#define ACC_BM4_STATUS 0x41
+#define ACC_BM5_STATUS 0x49
+#define ACC_BM6_STATUS 0x51
+#define ACC_BM7_STATUS 0x59
+#define ACC_BM0_PNTR 0x60
+#define ACC_BM1_PNTR 0x64
+#define ACC_BM2_PNTR 0x68
+#define ACC_BM3_PNTR 0x6C
+#define ACC_BM4_PNTR 0x70
+#define ACC_BM5_PNTR 0x74
+#define ACC_BM6_PNTR 0x78
+#define ACC_BM7_PNTR 0x7C
+/* acc_codec bar0 reg bits */
+/* ACC_IRQ_STATUS */
+#define IRQ_STS 0
+#define WU_IRQ_STS 1
+#define BM0_IRQ_STS 2
+#define BM1_IRQ_STS 3
+#define BM2_IRQ_STS 4
+#define BM3_IRQ_STS 5
+#define BM4_IRQ_STS 6
+#define BM5_IRQ_STS 7
+#define BM6_IRQ_STS 8
+#define BM7_IRQ_STS 9
+/* ACC_BMX_STATUS */
+#define EOP (1<<0)
+#define BM_EOP_ERR (1<<1)
+/* ACC_BMX_CTL */
+#define BM_CTL_EN 0x00000001
+#define BM_CTL_PAUSE 0x00000011
+#define BM_CTL_DIS 0x00000000
+#define BM_CTL_BYTE_ORD_LE 0x00000000
+#define BM_CTL_BYTE_ORD_BE 0x00000100
+/* cs5535 specific ac97 codec register defines */
+#define CMD_MASK 0xFF00FFFF
+#define CMD_NEW 0x00010000
+#define STS_NEW 0x00020000
+#define PRM_RDY_STS 0x00800000
+#define ACC_CODEC_CNTL_WR_CMD (~0x80000000)
+#define ACC_CODEC_CNTL_RD_CMD 0x80000000
+#define PRD_JMP 0x2000
+#define PRD_EOP 0x4000
+#define PRD_EOT 0x8000
+
+enum { CS5535AUDIO_DMA_PLAYBACK, CS5535AUDIO_DMA_CAPTURE, NUM_CS5535AUDIO_DMAS };
+
+struct cs5535audio;
+
+struct cs5535audio_dma_ops {
+ int type;
+ void (*enable_dma)(struct cs5535audio *cs5535au);
+ void (*disable_dma)(struct cs5535audio *cs5535au);
+ void (*pause_dma)(struct cs5535audio *cs5535au);
+ void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr);
+ u32 (*read_dma_pntr)(struct cs5535audio *cs5535au);
+};
+
+struct cs5535audio_dma_desc {
+ u32 addr;
+ u16 size;
+ u16 ctlreserved;
+};
+
+struct cs5535audio_dma {
+ const struct cs5535audio_dma_ops *ops;
+ struct snd_dma_buffer desc_buf;
+ struct snd_pcm_substream *substream;
+ unsigned int buf_addr, buf_bytes;
+ unsigned int period_bytes, periods;
+};
+
+struct cs5535audio {
+ struct snd_card *card;
+ struct snd_ac97 *ac97;
+ int irq;
+ struct pci_dev *pci;
+ unsigned long port;
+ spinlock_t reg_lock;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS];
+};
+
+int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
+
+#endif /* __SOUND_CS5535AUDIO_H */
+
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
new file mode 100644
index 000000000000..60bb82b2ff47
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -0,0 +1,419 @@
+/*
+ * Driver for audio on multifunction CS5535 companion device
+ * Copyright (C) Jaya Kumar
+ *
+ * Based on Jaroslav Kysela and Takashi Iwai's examples.
+ * This work was sponsored by CIS(M) Sdn Bhd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * todo: add be fmt support, spdif, pm
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/asoundef.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include "cs5535audio.h"
+
+static struct snd_pcm_hardware snd_cs5535audio_playback =
+{
+ .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_SYNC_START
+ ),
+ .formats = (
+ SNDRV_PCM_FMTBIT_S16_LE
+ ),
+ .rates = (
+ SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_8000_48000
+ ),
+ .rate_min = 4000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (64*1024 - 16),
+ .periods_min = 1,
+ .periods_max = CS5535AUDIO_MAX_DESCRIPTORS,
+ .fifo_size = 0,
+};
+
+static struct snd_pcm_hardware snd_cs5535audio_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
+ ),
+ .formats = (
+ SNDRV_PCM_FMTBIT_S16_LE
+ ),
+ .rates = (
+ SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_8000_48000
+ ),
+ .rate_min = 4000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = (128*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (64*1024 - 16),
+ .periods_min = 1,
+ .periods_max = CS5535AUDIO_MAX_DESCRIPTORS,
+ .fifo_size = 0,
+};
+
+static int snd_cs5535audio_playback_open(struct snd_pcm_substream *substream)
+{
+ int err;
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw = snd_cs5535audio_playback;
+ cs5535au->playback_substream = substream;
+ runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK]);
+ snd_pcm_set_sync(substream);
+ if ((err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+
+ return 0;
+}
+
+static int snd_cs5535audio_playback_close(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+#define CS5535AUDIO_DESC_LIST_SIZE \
+ PAGE_ALIGN(CS5535AUDIO_MAX_DESCRIPTORS * sizeof(struct cs5535audio_dma_desc))
+
+static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
+ struct cs5535audio_dma *dma,
+ struct snd_pcm_substream *substream,
+ unsigned int periods,
+ unsigned int period_bytes)
+{
+ unsigned int i;
+ u32 addr, desc_addr, jmpprd_addr;
+ struct cs5535audio_dma_desc *lastdesc;
+
+ if (periods > CS5535AUDIO_MAX_DESCRIPTORS)
+ return -ENOMEM;
+
+ if (dma->desc_buf.area == NULL) {
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(cs5535au->pci),
+ CS5535AUDIO_DESC_LIST_SIZE+1,
+ &dma->desc_buf) < 0)
+ return -ENOMEM;
+ dma->period_bytes = dma->periods = 0;
+ }
+
+ if (dma->periods == periods && dma->period_bytes == period_bytes)
+ return 0;
+
+ /* the u32 cast is okay because in snd*create we succesfully told
+ pci alloc that we're only 32 bit capable so the uppper will be 0 */
+ addr = (u32) substream->runtime->dma_addr;
+ desc_addr = (u32) dma->desc_buf.addr;
+ for (i = 0; i < periods; i++) {
+ struct cs5535audio_dma_desc *desc =
+ &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i];
+ desc->addr = cpu_to_le32(addr);
+ desc->size = cpu_to_le32(period_bytes);
+ desc->ctlreserved = cpu_to_le32(PRD_EOP);
+ desc_addr += sizeof(struct cs5535audio_dma_desc);
+ addr += period_bytes;
+ }
+ /* we reserved one dummy descriptor at the end to do the PRD jump */
+ lastdesc = &((struct cs5535audio_dma_desc *) dma->desc_buf.area)[periods];
+ lastdesc->addr = cpu_to_le32((u32) dma->desc_buf.addr);
+ lastdesc->size = 0;
+ lastdesc->ctlreserved = cpu_to_le32(PRD_JMP);
+ jmpprd_addr = cpu_to_le32(lastdesc->addr +
+ (sizeof(struct cs5535audio_dma_desc)*periods));
+
+ dma->period_bytes = period_bytes;
+ dma->periods = periods;
+ spin_lock_irq(&cs5535au->reg_lock);
+ dma->ops->disable_dma(cs5535au);
+ dma->ops->setup_prd(cs5535au, jmpprd_addr);
+ spin_unlock_irq(&cs5535au->reg_lock);
+ return 0;
+}
+
+static void cs5535audio_playback_enable_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM0_CMD, BM_CTL_EN);
+}
+
+static void cs5535audio_playback_disable_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM0_CMD, 0);
+}
+
+static void cs5535audio_playback_pause_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM0_CMD, BM_CTL_PAUSE);
+}
+
+static void cs5535audio_playback_setup_prd(struct cs5535audio *cs5535au,
+ u32 prd_addr)
+{
+ cs_writel(cs5535au, ACC_BM0_PRD, prd_addr);
+}
+
+static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au)
+{
+ return cs_readl(cs5535au, ACC_BM0_PNTR);
+}
+
+static void cs5535audio_capture_enable_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM1_CMD, BM_CTL_EN);
+}
+
+static void cs5535audio_capture_disable_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM1_CMD, 0);
+}
+
+static void cs5535audio_capture_pause_dma(struct cs5535audio *cs5535au)
+{
+ cs_writeb(cs5535au, ACC_BM1_CMD, BM_CTL_PAUSE);
+}
+
+static void cs5535audio_capture_setup_prd(struct cs5535audio *cs5535au,
+ u32 prd_addr)
+{
+ cs_writel(cs5535au, ACC_BM1_PRD, prd_addr);
+}
+
+static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au)
+{
+ return cs_readl(cs5535au, ACC_BM1_PNTR);
+}
+
+static void cs5535audio_clear_dma_packets(struct cs5535audio *cs5535au,
+ struct cs5535audio_dma *dma,
+ struct snd_pcm_substream *substream)
+{
+ snd_dma_free_pages(&dma->desc_buf);
+ dma->desc_buf.area = NULL;
+}
+
+static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ struct cs5535audio_dma *dma = substream->runtime->private_data;
+ int err;
+
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
+ return err;
+ dma->buf_addr = substream->runtime->dma_addr;
+ dma->buf_bytes = params_buffer_bytes(hw_params);
+
+ err = cs5535audio_build_dma_packets(cs5535au, dma, substream,
+ params_periods(hw_params),
+ params_period_bytes(hw_params));
+ return err;
+}
+
+static int snd_cs5535audio_hw_free(struct snd_pcm_substream *substream)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ struct cs5535audio_dma *dma = substream->runtime->private_data;
+
+ cs5535audio_clear_dma_packets(cs5535au, dma, substream);
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int snd_cs5535audio_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_FRONT_DAC_RATE,
+ substream->runtime->rate);
+}
+
+static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ struct cs5535audio_dma *dma = substream->runtime->private_data;
+ int err = 0;
+
+ spin_lock(&cs5535au->reg_lock);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dma->ops->pause_dma(cs5535au);
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dma->ops->enable_dma(cs5535au);
+ break;
+ case SNDRV_PCM_TRIGGER_START:
+ dma->ops->enable_dma(cs5535au);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dma->ops->disable_dma(cs5535au);
+ break;
+ default:
+ snd_printk(KERN_ERR "unhandled trigger\n");
+ err = -EINVAL;
+ break;
+ }
+ spin_unlock(&cs5535au->reg_lock);
+ return err;
+}
+
+static snd_pcm_uframes_t snd_cs5535audio_pcm_pointer(struct snd_pcm_substream
+ *substream)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ u32 curdma;
+ struct cs5535audio_dma *dma;
+
+ dma = substream->runtime->private_data;
+ curdma = dma->ops->read_dma_pntr(cs5535au);
+ if (curdma < dma->buf_addr) {
+ snd_printk(KERN_ERR "curdma=%x < %x bufaddr.\n",
+ curdma, dma->buf_addr);
+ return 0;
+ }
+ curdma -= dma->buf_addr;
+ if (curdma >= dma->buf_bytes) {
+ snd_printk(KERN_ERR "diff=%x >= %x buf_bytes.\n",
+ curdma, dma->buf_bytes);
+ return 0;
+ }
+ return bytes_to_frames(substream->runtime, curdma);
+}
+
+static int snd_cs5535audio_capture_open(struct snd_pcm_substream *substream)
+{
+ int err;
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw = snd_cs5535audio_capture;
+ cs5535au->capture_substream = substream;
+ runtime->private_data = &(cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE]);
+ snd_pcm_set_sync(substream);
+ if ((err = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+ return 0;
+}
+
+static int snd_cs5535audio_capture_close(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct cs5535audio *cs5535au = snd_pcm_substream_chip(substream);
+ return snd_ac97_set_rate(cs5535au->ac97, AC97_PCM_LR_ADC_RATE,
+ substream->runtime->rate);
+}
+
+static struct snd_pcm_ops snd_cs5535audio_playback_ops = {
+ .open = snd_cs5535audio_playback_open,
+ .close = snd_cs5535audio_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs5535audio_hw_params,
+ .hw_free = snd_cs5535audio_hw_free,
+ .prepare = snd_cs5535audio_playback_prepare,
+ .trigger = snd_cs5535audio_trigger,
+ .pointer = snd_cs5535audio_pcm_pointer,
+};
+
+static struct snd_pcm_ops snd_cs5535audio_capture_ops = {
+ .open = snd_cs5535audio_capture_open,
+ .close = snd_cs5535audio_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_cs5535audio_hw_params,
+ .hw_free = snd_cs5535audio_hw_free,
+ .prepare = snd_cs5535audio_capture_prepare,
+ .trigger = snd_cs5535audio_trigger,
+ .pointer = snd_cs5535audio_pcm_pointer,
+};
+
+static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = {
+ .type = CS5535AUDIO_DMA_PLAYBACK,
+ .enable_dma = cs5535audio_playback_enable_dma,
+ .disable_dma = cs5535audio_playback_disable_dma,
+ .setup_prd = cs5535audio_playback_setup_prd,
+ .pause_dma = cs5535audio_playback_pause_dma,
+ .read_dma_pntr = cs5535audio_playback_read_dma_pntr,
+};
+
+static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = {
+ .type = CS5535AUDIO_DMA_CAPTURE,
+ .enable_dma = cs5535audio_capture_enable_dma,
+ .disable_dma = cs5535audio_capture_disable_dma,
+ .setup_prd = cs5535audio_capture_setup_prd,
+ .pause_dma = cs5535audio_capture_pause_dma,
+ .read_dma_pntr = cs5535audio_capture_read_dma_pntr,
+};
+
+int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
+{
+ struct snd_pcm *pcm;
+ int err;
+
+ err = snd_pcm_new(cs5535au->card, "CS5535 Audio", 0, 1, 1, &pcm);
+ if (err < 0)
+ return err;
+
+ cs5535au->dmas[CS5535AUDIO_DMA_PLAYBACK].ops =
+ &snd_cs5535audio_playback_dma_ops;
+ cs5535au->dmas[CS5535AUDIO_DMA_CAPTURE].ops =
+ &snd_cs5535audio_capture_dma_ops;
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_cs5535audio_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_cs5535audio_capture_ops);
+
+ pcm->private_data = cs5535au;
+ pcm->info_flags = 0;
+ strcpy(pcm->name, "CS5535 Audio");
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(cs5535au->pci),
+ 64*1024, 128*1024);
+
+ return 0;
+}
+
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 78270f8710ff..2dfa932f7825 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -101,10 +101,10 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- emu10k1_t *emu;
+ struct snd_card *card;
+ struct snd_emu10k1 *emu;
#ifdef ENABLE_SYNTH
- snd_seq_device_t *wave = NULL;
+ struct snd_seq_device *wave = NULL;
#endif
int err;
@@ -125,72 +125,50 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
if ((err = snd_emu10k1_create(card, pci, extin[dev], extout[dev],
(long)max_buffer_size[dev] * 1024 * 1024,
enable_ir[dev], subsystem[dev],
- &emu)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ &emu)) < 0)
+ goto error;
+ card->private_data = emu;
+ if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0)
+ goto error;
+ if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0)
+ goto error;
+ if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0)
+ goto error;
/* This stores the periods table. */
if (emu->card_capabilities->ca0151_chip) { /* P16V */
- if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &emu->p16v_buffer) < 0) {
- snd_p16v_free(emu);
- return -ENOMEM;
- }
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ 1024, &emu->p16v_buffer)) < 0)
+ goto error;
}
- if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_emu10k1_mixer(emu, 0, 3)) < 0)
+ goto error;
- if ((err = snd_emu10k1_timer(emu, 0)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_emu10k1_timer(emu, 0)) < 0)
+ goto error;
- if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if (emu->card_capabilities->ca0151_chip) { /* P16V */
- if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0)
+ goto error;
+ if (emu->card_capabilities->ca0151_chip) { /* P16V */
+ if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0)
+ goto error;
}
if (emu->audigy) {
- if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_emu10k1_audigy_midi(emu)) < 0)
+ goto error;
} else {
- if ((err = snd_emu10k1_midi(emu)) < 0) {
- snd_card_free(card);
- return err;
- }
- }
- if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0) {
- snd_card_free(card);
- return err;
+ if ((err = snd_emu10k1_midi(emu)) < 0)
+ goto error;
}
+ if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0)
+ goto error;
#ifdef ENABLE_SYNTH
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
- sizeof(snd_emu10k1_synth_arg_t), &wave) < 0 ||
+ sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 ||
wave == NULL) {
snd_printk(KERN_WARNING "can't initialize Emu10k1 wavetable synth\n");
} else {
- snd_emu10k1_synth_arg_t *arg;
+ struct snd_emu10k1_synth_arg *arg;
arg = SNDRV_SEQ_DEVICE_ARGPTR(wave);
strcpy(wave->name, "Emu-10k1 Synth");
arg->hwptr = emu;
@@ -206,13 +184,16 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
"%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
card->shortname, emu->revision, emu->serial, emu->port, emu->irq);
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
- return err;
- }
+ if ((err = snd_card_register(card)) < 0)
+ goto error;
+
pci_set_drvdata(pci, card);
dev++;
return 0;
+
+ error:
+ snd_card_free(card);
+ return err;
}
static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
@@ -221,11 +202,68 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
+
+#ifdef CONFIG_PM
+static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_emu10k1 *emu = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ snd_pcm_suspend_all(emu->pcm);
+ snd_pcm_suspend_all(emu->pcm_mic);
+ snd_pcm_suspend_all(emu->pcm_efx);
+ snd_pcm_suspend_all(emu->pcm_multi);
+ snd_pcm_suspend_all(emu->pcm_p16v);
+
+ snd_ac97_suspend(emu->ac97);
+
+ snd_emu10k1_efx_suspend(emu);
+ snd_emu10k1_suspend_regs(emu);
+ if (emu->card_capabilities->ca0151_chip)
+ snd_p16v_suspend(emu);
+
+ snd_emu10k1_done(emu);
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+int snd_emu10k1_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_emu10k1 *emu = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_emu10k1_resume_init(emu);
+ snd_emu10k1_efx_resume(emu);
+ snd_ac97_resume(emu->ac97);
+ snd_emu10k1_resume_regs(emu);
+
+ if (emu->card_capabilities->ca0151_chip)
+ snd_p16v_resume(emu);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pci_driver driver = {
.name = "EMU10K1_Audigy",
.id_table = snd_emu10k1_ids,
.probe = snd_card_emu10k1_probe,
.remove = __devexit_p(snd_card_emu10k1_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_emu10k1_suspend,
+ .resume = snd_emu10k1_resume,
+#endif
};
static int __init alsa_card_emu10k1_init(void)
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index 6589bf24abcd..01965bd99966 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -27,26 +27,28 @@ enum {
};
/* Keeps track of what we are finding */
-typedef struct best_voice {
+struct best_voice {
unsigned int time;
int voice;
-} best_voice_t;
+};
/*
* prototypes
*/
-static void lookup_voices(snd_emux_t *emu, emu10k1_t *hw, best_voice_t *best, int active_only);
-static snd_emux_voice_t *get_voice(snd_emux_t *emu, snd_emux_port_t *port);
-static int start_voice(snd_emux_voice_t *vp);
-static void trigger_voice(snd_emux_voice_t *vp);
-static void release_voice(snd_emux_voice_t *vp);
-static void update_voice(snd_emux_voice_t *vp, int update);
-static void terminate_voice(snd_emux_voice_t *vp);
-static void free_voice(snd_emux_voice_t *vp);
-
-static void set_fmmod(emu10k1_t *hw, snd_emux_voice_t *vp);
-static void set_fm2frq2(emu10k1_t *hw, snd_emux_voice_t *vp);
-static void set_filterQ(emu10k1_t *hw, snd_emux_voice_t *vp);
+static void lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
+ struct best_voice *best, int active_only);
+static struct snd_emux_voice *get_voice(struct snd_emux *emu,
+ struct snd_emux_port *port);
+static int start_voice(struct snd_emux_voice *vp);
+static void trigger_voice(struct snd_emux_voice *vp);
+static void release_voice(struct snd_emux_voice *vp);
+static void update_voice(struct snd_emux_voice *vp, int update);
+static void terminate_voice(struct snd_emux_voice *vp);
+static void free_voice(struct snd_emux_voice *vp);
+
+static void set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
+static void set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
+static void set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp);
/*
* Ensure a value is between two points
@@ -59,7 +61,7 @@ static void set_filterQ(emu10k1_t *hw, snd_emux_voice_t *vp);
/*
* set up operators
*/
-static snd_emux_operators_t emu10k1_ops = {
+static struct snd_emux_operators emu10k1_ops = {
.owner = THIS_MODULE,
.get_voice = get_voice,
.prepare = start_voice,
@@ -73,7 +75,7 @@ static snd_emux_operators_t emu10k1_ops = {
};
void
-snd_emu10k1_ops_setup(snd_emux_t *emu)
+snd_emu10k1_ops_setup(struct snd_emux *emu)
{
emu->ops = emu10k1_ops;
}
@@ -85,11 +87,11 @@ snd_emu10k1_ops_setup(snd_emux_t *emu)
* terminate most inactive voice and give it as a pcm voice.
*/
int
-snd_emu10k1_synth_get_voice(emu10k1_t *hw)
+snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw)
{
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
- best_voice_t best[V_END];
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
+ struct best_voice best[V_END];
unsigned long flags;
int i;
@@ -123,10 +125,10 @@ snd_emu10k1_synth_get_voice(emu10k1_t *hw)
* turn off the voice (not terminated)
*/
static void
-release_voice(snd_emux_voice_t *vp)
+release_voice(struct snd_emux_voice *vp)
{
int dcysusv;
- emu10k1_t *hw;
+ struct snd_emu10k1 *hw;
hw = vp->hw;
dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
@@ -140,16 +142,16 @@ release_voice(snd_emux_voice_t *vp)
* terminate the voice
*/
static void
-terminate_voice(snd_emux_voice_t *vp)
+terminate_voice(struct snd_emux_voice *vp)
{
- emu10k1_t *hw;
+ struct snd_emu10k1 *hw;
snd_assert(vp, return);
hw = vp->hw;
snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
if (vp->block) {
- emu10k1_memblk_t *emem;
- emem = (emu10k1_memblk_t *)vp->block;
+ struct snd_emu10k1_memblk *emem;
+ emem = (struct snd_emu10k1_memblk *)vp->block;
if (emem->map_locked > 0)
emem->map_locked--;
}
@@ -159,9 +161,9 @@ terminate_voice(snd_emux_voice_t *vp)
* release the voice to system
*/
static void
-free_voice(snd_emux_voice_t *vp)
+free_voice(struct snd_emux_voice *vp)
{
- emu10k1_t *hw;
+ struct snd_emu10k1 *hw;
hw = vp->hw;
if (vp->ch >= 0) {
@@ -181,9 +183,9 @@ free_voice(snd_emux_voice_t *vp)
* update registers
*/
static void
-update_voice(snd_emux_voice_t *vp, int update)
+update_voice(struct snd_emux_voice *vp, int update)
{
- emu10k1_t *hw;
+ struct snd_emu10k1 *hw;
hw = vp->hw;
if (update & SNDRV_EMUX_UPDATE_VOLUME)
@@ -210,10 +212,11 @@ update_voice(snd_emux_voice_t *vp, int update)
*/
/* spinlock held! */
static void
-lookup_voices(snd_emux_t *emu, emu10k1_t *hw, best_voice_t *best, int active_only)
+lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
+ struct best_voice *best, int active_only)
{
- snd_emux_voice_t *vp;
- best_voice_t *bp;
+ struct snd_emux_voice *vp;
+ struct best_voice *bp;
int i;
for (i = 0; i < V_END; i++) {
@@ -274,12 +277,12 @@ lookup_voices(snd_emux_t *emu, emu10k1_t *hw, best_voice_t *best, int active_onl
*
* emu->voice_lock is already held.
*/
-static snd_emux_voice_t *
-get_voice(snd_emux_t *emu, snd_emux_port_t *port)
+static struct snd_emux_voice *
+get_voice(struct snd_emux *emu, struct snd_emux_port *port)
{
- emu10k1_t *hw;
- snd_emux_voice_t *vp;
- best_voice_t best[V_END];
+ struct snd_emu10k1 *hw;
+ struct snd_emux_voice *vp;
+ struct best_voice best[V_END];
int i;
hw = emu->hw;
@@ -290,7 +293,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
vp = &emu->voices[best[i].voice];
if (vp->ch < 0) {
/* allocate a voice */
- emu10k1_voice_t *hwvoice;
+ struct snd_emu10k1_voice *hwvoice;
if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
continue;
vp->ch = hwvoice->number;
@@ -308,21 +311,21 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
* prepare envelopes and LFOs
*/
static int
-start_voice(snd_emux_voice_t *vp)
+start_voice(struct snd_emux_voice *vp)
{
unsigned int temp;
int ch;
unsigned int addr, mapped_offset;
- snd_midi_channel_t *chan;
- emu10k1_t *hw;
- emu10k1_memblk_t *emem;
+ struct snd_midi_channel *chan;
+ struct snd_emu10k1 *hw;
+ struct snd_emu10k1_memblk *emem;
hw = vp->hw;
ch = vp->ch;
snd_assert(ch >= 0, return -EINVAL);
chan = vp->chan;
- emem = (emu10k1_memblk_t *)vp->block;
+ emem = (struct snd_emu10k1_memblk *)vp->block;
if (emem == NULL)
return -EINVAL;
emem->map_locked++;
@@ -463,15 +466,15 @@ start_voice(snd_emux_voice_t *vp)
* Start envelope
*/
static void
-trigger_voice(snd_emux_voice_t *vp)
+trigger_voice(struct snd_emux_voice *vp)
{
unsigned int temp, ptarget;
- emu10k1_t *hw;
- emu10k1_memblk_t *emem;
+ struct snd_emu10k1 *hw;
+ struct snd_emu10k1_memblk *emem;
hw = vp->hw;
- emem = (emu10k1_memblk_t *)vp->block;
+ emem = (struct snd_emu10k1_memblk *)vp->block;
if (! emem || emem->mapped_page < 0)
return; /* not mapped */
@@ -495,7 +498,7 @@ trigger_voice(snd_emux_voice_t *vp)
/* set lfo1 modulation height and cutoff */
static void
-set_fmmod(emu10k1_t *hw, snd_emux_voice_t *vp)
+set_fmmod(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
{
unsigned short fmmod;
short pitch;
@@ -513,7 +516,7 @@ set_fmmod(emu10k1_t *hw, snd_emux_voice_t *vp)
/* set lfo2 pitch & frequency */
static void
-set_fm2frq2(emu10k1_t *hw, snd_emux_voice_t *vp)
+set_fm2frq2(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
{
unsigned short fm2frq2;
short pitch;
@@ -531,7 +534,7 @@ set_fm2frq2(emu10k1_t *hw, snd_emux_voice_t *vp)
/* set filterQ */
static void
-set_filterQ(emu10k1_t *hw, snd_emux_voice_t *vp)
+set_filterQ(struct snd_emu10k1 *hw, struct snd_emux_voice *vp)
{
unsigned int val;
val = snd_emu10k1_ptr_read(hw, CCCA, vp->ch) & ~CCCA_RESONANCE;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 53aeff0b783a..3c7043b7d4c9 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -40,18 +40,14 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
#include "p16v.h"
+#include "tina2.h"
-#if 0
-MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Creative Labs, Inc.");
-MODULE_DESCRIPTION("Routines for control of EMU10K1 chips");
-MODULE_LICENSE("GPL");
-#endif
/*************************************************************************
* EMU10K1 init / done
*************************************************************************/
-void snd_emu10k1_voice_init(emu10k1_t * emu, int ch)
+void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch)
{
snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
snd_emu10k1_ptr_write(emu, IP, ch, 0);
@@ -96,17 +92,38 @@ void snd_emu10k1_voice_init(emu10k1_t * emu, int ch)
}
}
-static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
+static unsigned int spi_dac_init[] = {
+ 0x00ff,
+ 0x02ff,
+ 0x0400,
+ 0x0520,
+ 0x0600,
+ 0x08ff,
+ 0x0aff,
+ 0x0cff,
+ 0x0eff,
+ 0x10ff,
+ 0x1200,
+ 0x1400,
+ 0x1480,
+ 0x1800,
+ 0x1aff,
+ 0x1cff,
+ 0x1e00,
+ 0x0530,
+ 0x0602,
+ 0x0622,
+ 0x1400,
+};
+
+static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
{
- int ch, idx, err;
unsigned int silent_page;
-
- emu->fx8010.itram_size = (16 * 1024)/2;
- emu->fx8010.etram_pages.area = NULL;
- emu->fx8010.etram_pages.bytes = 0;
+ int ch;
/* disable audio and lock cache */
- outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
+ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
+ emu->port + HCFG);
/* reset recording buffers */
snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE);
@@ -127,48 +144,17 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* set SPDIF bypass mode */
snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
/* enable rear left + rear right AC97 slots */
- snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT | AC97SLOT_REAR_LEFT);
+ snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT |
+ AC97SLOT_REAR_LEFT);
}
/* init envelope engine */
- for (ch = 0; ch < NUM_G; ch++) {
- emu->voices[ch].emu = emu;
- emu->voices[ch].number = ch;
+ for (ch = 0; ch < NUM_G; ch++)
snd_emu10k1_voice_init(emu, ch);
- }
- /*
- * Init to 0x02109204 :
- * Clock accuracy = 0 (1000ppm)
- * Sample Rate = 2 (48kHz)
- * Audio Channel = 1 (Left of 2)
- * Source Number = 0 (Unspecified)
- * Generation Status = 1 (Original for Cat Code 12)
- * Cat Code = 12 (Digital Signal Mixer)
- * Mode = 0 (Mode 0)
- * Emphasis = 0 (None)
- * CP = 1 (Copyright unasserted)
- * AN = 0 (Audio data)
- * P = 0 (Consumer)
- */
- snd_emu10k1_ptr_write(emu, SPCS0, 0,
- emu->spdif_bits[0] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- snd_emu10k1_ptr_write(emu, SPCS1, 0,
- emu->spdif_bits[1] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- snd_emu10k1_ptr_write(emu, SPCS2, 0,
- emu->spdif_bits[2] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+ snd_emu10k1_ptr_write(emu, SPCS0, 0, emu->spdif_bits[0]);
+ snd_emu10k1_ptr_write(emu, SPCS1, 0, emu->spdif_bits[1]);
+ snd_emu10k1_ptr_write(emu, SPCS2, 0, emu->spdif_bits[2]);
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
@@ -195,7 +181,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* Hacks for Alice3 to work independent of haP16V driver */
u32 tmp;
- snd_printk(KERN_ERR "Audigy2 value:Special config.\n");
+ snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
//Setup SRCMulti_I2S SamplingRate
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
tmp &= 0xfffff1ff;
@@ -219,15 +205,28 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
outl(tmp, emu->port + A_IOCFG);
}
+ if (emu->card_capabilities->spi_dac) { /* Audigy 2 ZS Notebook with DAC Wolfson WM8768/WM8568 */
+ int size, n;
+
+ size = ARRAY_SIZE(spi_dac_init);
+ for (n=0; n < size; n++)
+ snd_emu10k1_spi_write(emu, spi_dac_init[n]);
+
+ snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10);
+ /* Enable GPIOs
+ * GPIO0: Unknown
+ * GPIO1: Speakers-enabled.
+ * GPIO2: Unknown
+ * GPIO3: Unknown
+ * GPIO4: IEC958 Output on.
+ * GPIO5: Unknown
+ * GPIO6: Unknown
+ * GPIO7: Unknown
+ */
+ outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
-
- /*
- * Clear page with silence & setup all pointers to this page
- */
- memset(emu->silent_page.area, 0, PAGE_SIZE);
- silent_page = emu->silent_page.addr << 1;
- for (idx = 0; idx < MAXPAGES; idx++)
- ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
+ }
+
snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
@@ -264,7 +263,9 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
if (enable_ir) { /* enable IR for SB Live */
- if (emu->audigy) {
+ if ( emu->card_capabilities->emu1212m) {
+ ; /* Disable all access to A_IOCFG for the emu1212m */
+ } else if (emu->audigy) {
unsigned int reg = inl(emu->port + A_IOCFG);
outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
udelay(500);
@@ -281,24 +282,27 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
}
}
- if (emu->audigy) { /* enable analog output */
+ if ( emu->card_capabilities->emu1212m) {
+ ; /* Disable all access to A_IOCFG for the emu1212m */
+ } else if (emu->audigy) { /* enable analog output */
unsigned int reg = inl(emu->port + A_IOCFG);
outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
}
- /*
- * Initialize the effect engine
- */
- if ((err = snd_emu10k1_init_efx(emu)) < 0)
- return err;
+ return 0;
+}
+static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
+{
/*
* Enable the audio bit
*/
outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
/* Enable analog/digital outs on audigy */
- if (emu->audigy) {
+ if ( emu->card_capabilities->emu1212m) {
+ ; /* Disable all access to A_IOCFG for the emu1212m */
+ } else if (emu->audigy) {
outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
@@ -334,15 +338,9 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
#endif
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
-
- emu->reserved_page = (emu10k1_memblk_t *)snd_emu10k1_synth_alloc(emu, 4096);
- if (emu->reserved_page)
- emu->reserved_page->map_locked = 1;
-
- return 0;
}
-static int snd_emu10k1_done(emu10k1_t * emu)
+int snd_emu10k1_done(struct snd_emu10k1 * emu)
{
int ch;
@@ -381,18 +379,10 @@ static int snd_emu10k1_done(emu10k1_t * emu)
snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
- /* remove reserved page */
- if (emu->reserved_page != NULL) {
- snd_emu10k1_synth_free(emu, (snd_util_memblk_t *)emu->reserved_page);
- emu->reserved_page = NULL;
- }
-
/* disable audio and lock cache */
outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
snd_emu10k1_ptr_write(emu, PTB, 0, 0);
- snd_emu10k1_free_efx(emu);
-
return 0;
}
@@ -473,7 +463,7 @@ static int snd_emu10k1_done(emu10k1_t * emu)
* register.
*/
-static void snd_emu10k1_ecard_write(emu10k1_t * emu, unsigned int value)
+static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value)
{
unsigned short count;
unsigned int data;
@@ -511,7 +501,7 @@ static void snd_emu10k1_ecard_write(emu10k1_t * emu, unsigned int value)
* channel.
*/
-static void snd_emu10k1_ecard_setadcgain(emu10k1_t * emu,
+static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
unsigned short gain)
{
unsigned int bit;
@@ -539,7 +529,7 @@ static void snd_emu10k1_ecard_setadcgain(emu10k1_t * emu,
snd_emu10k1_ecard_write(emu, emu->ecard_ctrl);
}
-static int __devinit snd_emu10k1_ecard_init(emu10k1_t * emu)
+static int __devinit snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
{
unsigned int hc_value;
@@ -579,7 +569,7 @@ static int __devinit snd_emu10k1_ecard_init(emu10k1_t * emu)
return 0;
}
-static int __devinit snd_emu10k1_cardbus_init(emu10k1_t * emu)
+static int __devinit snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
{
unsigned long special_port;
unsigned int value;
@@ -600,18 +590,160 @@ static int __devinit snd_emu10k1_cardbus_init(emu10k1_t * emu)
outl(0x0090007f, special_port);
value = inl(special_port);
+ snd_emu10k1_ptr20_write(emu, TINA2_VOLUME, 0, 0xfefefefe); /* Defaults to 0x30303030 */
+ return 0;
+}
+
+static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
+{
+ if (reg<0 || reg>0x3f)
+ return 1;
+ reg+=0x40; /* 0x40 upwards are registers. */
+ if (value<0 || value>0x3f) /* 0 to 0x3f are values */
+ return 1;
+ outl(reg, emu->port + A_IOCFG);
+ outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
+ outl(value, emu->port + A_IOCFG);
+ outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
+
return 0;
}
+static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
+{
+ if (reg<0 || reg>0x3f)
+ return 1;
+ reg+=0x40; /* 0x40 upwards are registers. */
+ outl(reg, emu->port + A_IOCFG);
+ outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
+ *value = inl(emu->port + A_IOCFG);
+
+ return 0;
+}
+
+static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value)
+{
+ snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) );
+ snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) );
+ snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) );
+ snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) );
+
+ return 0;
+}
+
+static int __devinit snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu)
+{
+ unsigned int i;
+ int tmp;
+
+ snd_printk(KERN_ERR "emu1212m: Special config.\n");
+ outl(0x0005a00c, emu->port + HCFG);
+ outl(0x0005a004, emu->port + HCFG);
+ outl(0x0005a000, emu->port + HCFG);
+ outl(0x0005a000, emu->port + HCFG);
+
+ snd_emu1212m_fpga_read(emu, 0x22, &tmp );
+ snd_emu1212m_fpga_read(emu, 0x23, &tmp );
+ snd_emu1212m_fpga_read(emu, 0x24, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x04, 0x01 );
+ snd_emu1212m_fpga_read(emu, 0x0b, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x0b, 0x01 );
+ snd_emu1212m_fpga_read(emu, 0x10, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x10, 0x00 );
+ snd_emu1212m_fpga_read(emu, 0x11, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
+ snd_emu1212m_fpga_read(emu, 0x13, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x13, 0x0f );
+ snd_emu1212m_fpga_read(emu, 0x11, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
+ snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
+ snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
+ snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
+ snd_emu1212m_fpga_write(emu, 0x09, 0x0f );
+ snd_emu1212m_fpga_write(emu, 0x06, 0x00 );
+ snd_emu1212m_fpga_write(emu, 0x05, 0x00 );
+ snd_emu1212m_fpga_write(emu, 0x0e, 0x12 );
+ snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200);
+ snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201);
+ for (i=0;i < 0x20;i++) {
+ snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000);
+ }
+ for (i=0;i < 4;i++) {
+ snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000);
+ }
+ for (i=0;i < 7;i++) {
+ snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000);
+ }
+ for (i=0;i < 7;i++) {
+ snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000);
+ }
+ snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c);
+ snd_emu1212m_fpga_write(emu, 0x07, 0x01 );
+
+ snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+
+ outl(0x0000a000, emu->port + HCFG);
+ outl(0x0000a001, emu->port + HCFG);
+ /* Initial boot complete. Now patches */
+
+ snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
+ snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
+ snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
+ snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
+ snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
+ snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
+
+ snd_emu1212m_fpga_read(emu, 0x20, &tmp );
+ snd_emu1212m_fpga_read(emu, 0x21, &tmp );
+
+ snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302);
+ snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303);
+
+ return 0;
+}
/*
* Create the EMU10K1 instance
*/
-static int snd_emu10k1_free(emu10k1_t *emu)
+#ifdef CONFIG_PM
+static int alloc_pm_buffer(struct snd_emu10k1 *emu);
+static void free_pm_buffer(struct snd_emu10k1 *emu);
+#endif
+
+static int snd_emu10k1_free(struct snd_emu10k1 *emu)
{
if (emu->port) { /* avoid access to already used hardware */
snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu);
+ /* remove reserved page */
+ if (emu->reserved_page) {
+ snd_emu10k1_synth_free(emu, (struct snd_util_memblk *)emu->reserved_page);
+ emu->reserved_page = NULL;
+ }
+ snd_emu10k1_free_efx(emu);
}
if (emu->memhdr)
snd_util_memhdr_free(emu->memhdr);
@@ -621,26 +753,35 @@ static int snd_emu10k1_free(emu10k1_t *emu)
snd_dma_free_pages(&emu->ptb_pages);
vfree(emu->page_ptr_table);
vfree(emu->page_addr_table);
+#ifdef CONFIG_PM
+ free_pm_buffer(emu);
+#endif
if (emu->irq >= 0)
free_irq(emu->irq, (void *)emu);
if (emu->port)
pci_release_regions(emu->pci);
- pci_disable_device(emu->pci);
if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
+ pci_disable_device(emu->pci);
kfree(emu);
return 0;
}
-static int snd_emu10k1_dev_free(snd_device_t *device)
+static int snd_emu10k1_dev_free(struct snd_device *device)
{
- emu10k1_t *emu = device->device_data;
+ struct snd_emu10k1 *emu = device->device_data;
return snd_emu10k1_free(emu);
}
-static emu_chip_details_t emu_chip_details[] = {
+static struct snd_emu_chip_details emu_chip_details[] = {
/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
/* Tested by James@superbug.co.uk 3rd July 2005 */
+ /* DSP: CA0108-IAT
+ * DAC: CS4382-KQ
+ * ADC: Philips 1361T
+ * AC97: STAC9750
+ * CA0151: None
+ */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
.driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
.id = "Audigy2",
@@ -649,14 +790,24 @@ static emu_chip_details_t emu_chip_details[] = {
.spk71 = 1,
.ac97_chip = 1} ,
/* Audigy 2 ZS Notebook Cardbus card.*/
- /* Tested by James@superbug.co.uk 30th October 2005 */
- /* Not working yet, but progressing. */
+ /* Tested by James@superbug.co.uk 22th December 2005 */
+ /* Audio output 7.1/Headphones working.
+ * Digital output working. (AC3 not checked, only PCM)
+ * Audio inputs not tested.
+ */
+ /* DSP: Tiny2
+ * DAC: Wolfson WM8768/WM8568
+ * ADC: Wolfson WM8775
+ * AC97: None
+ * CA0151: None
+ */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
.driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.ca_cardbus_chip = 1,
+ .spi_dac = 1,
.spk71 = 1} ,
{.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
@@ -670,7 +821,7 @@ static emu_chip_details_t emu_chip_details[] = {
.id = "EMU1212m",
.emu10k2_chip = 1,
.ca0102_chip = 1,
- .ecard = 1} ,
+ .emu1212m = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
.driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
@@ -681,6 +832,16 @@ static emu_chip_details_t emu_chip_details[] = {
.spk71 = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
+ /* Tested by shane-alsa@cm.nu 5th Nov 2005 */
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
+ .driver = "Audigy2", .name = "Audigy 2 [2006]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
.driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
.id = "Audigy2",
@@ -699,6 +860,14 @@ static emu_chip_details_t emu_chip_details[] = {
.spk71 = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
+ /* Audigy 2 */
+ /* Tested by James@superbug.co.uk 3rd July 2005 */
+ /* DSP: CA0102-IAT
+ * DAC: CS4382-KQ
+ * ADC: Philips 1361T
+ * AC97: STAC9721
+ * CA0151: Yes
+ */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
.driver = "Audigy2", .name = "Audigy 2 [SB0240]",
.id = "Audigy2",
@@ -714,6 +883,7 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
+ .spk71 = 1,
.spdif_bug = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
.driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
@@ -775,6 +945,14 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
+ /* Tested by ALSA bug#1680 26th December 2005 */
+ /* note: It really has SB0220 written on the card. */
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102,
+ .driver = "EMU10K1", .name = "SB Live 5.1 Dell OEM [SB0220]",
+ .id = "Live",
+ .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]",
@@ -782,6 +960,12 @@ static emu_chip_details_t emu_chip_details[] = {
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102,
+ .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",
@@ -877,21 +1061,22 @@ static emu_chip_details_t emu_chip_details[] = {
{ } /* terminator */
};
-int __devinit snd_emu10k1_create(snd_card_t * card,
+int __devinit snd_emu10k1_create(struct snd_card *card,
struct pci_dev * pci,
unsigned short extin_mask,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
- emu10k1_t ** remu)
+ struct snd_emu10k1 ** remu)
{
- emu10k1_t *emu;
- int err;
+ struct snd_emu10k1 *emu;
+ int idx, err;
int is_audigy;
unsigned char revision;
- const emu_chip_details_t *c;
- static snd_device_ops_t ops = {
+ unsigned int silent_page;
+ const struct snd_emu_chip_details *c;
+ static struct snd_device_ops ops = {
.dev_free = snd_emu10k1_dev_free,
};
@@ -999,36 +1184,37 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_emu10k1_interrupt, SA_INTERRUPT|SA_SHIRQ, "EMU10K1", (void *)emu)) {
- snd_emu10k1_free(emu);
- return -EBUSY;
+ err = -EBUSY;
+ goto error;
}
emu->irq = pci->irq;
emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
32 * 1024, &emu->ptb_pages) < 0) {
- snd_emu10k1_free(emu);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
emu->page_ptr_table = (void **)vmalloc(emu->max_cache_pages * sizeof(void*));
emu->page_addr_table = (unsigned long*)vmalloc(emu->max_cache_pages * sizeof(unsigned long));
if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
- snd_emu10k1_free(emu);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
EMUPAGESIZE, &emu->silent_page) < 0) {
- snd_emu10k1_free(emu);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
emu->memhdr = snd_util_memhdr_new(emu->max_cache_pages * PAGE_SIZE);
if (emu->memhdr == NULL) {
- snd_emu10k1_free(emu);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
- emu->memhdr->block_extra_size = sizeof(emu10k1_memblk_t) - sizeof(snd_util_memblk_t);
+ emu->memhdr->block_extra_size = sizeof(struct snd_emu10k1_memblk) -
+ sizeof(struct snd_util_memblk);
pci_set_master(pci);
@@ -1039,40 +1225,191 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
extout_mask = 0x7fff;
emu->fx8010.extin_mask = extin_mask;
emu->fx8010.extout_mask = extout_mask;
+ emu->enable_ir = enable_ir;
if (emu->card_capabilities->ecard) {
- if ((err = snd_emu10k1_ecard_init(emu)) < 0) {
- snd_emu10k1_free(emu);
- return err;
- }
+ if ((err = snd_emu10k1_ecard_init(emu)) < 0)
+ goto error;
} else if (emu->card_capabilities->ca_cardbus_chip) {
- if ((err = snd_emu10k1_cardbus_init(emu)) < 0) {
- snd_emu10k1_free(emu);
- return err;
- }
+ if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
+ goto error;
+ } else if (emu->card_capabilities->emu1212m) {
+ if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) {
+ snd_emu10k1_free(emu);
+ return err;
+ }
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */
snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
}
- if ((err = snd_emu10k1_init(emu, enable_ir)) < 0) {
- snd_emu10k1_free(emu);
- return err;
- }
+ /* initialize TRAM setup */
+ emu->fx8010.itram_size = (16 * 1024)/2;
+ emu->fx8010.etram_pages.area = NULL;
+ emu->fx8010.etram_pages.bytes = 0;
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0) {
- snd_emu10k1_free(emu);
- return err;
+ /*
+ * Init to 0x02109204 :
+ * Clock accuracy = 0 (1000ppm)
+ * Sample Rate = 2 (48kHz)
+ * Audio Channel = 1 (Left of 2)
+ * Source Number = 0 (Unspecified)
+ * Generation Status = 1 (Original for Cat Code 12)
+ * Cat Code = 12 (Digital Signal Mixer)
+ * Mode = 0 (Mode 0)
+ * Emphasis = 0 (None)
+ * CP = 1 (Copyright unasserted)
+ * AN = 0 (Audio data)
+ * P = 0 (Consumer)
+ */
+ emu->spdif_bits[0] = emu->spdif_bits[1] =
+ emu->spdif_bits[2] = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
+
+ emu->reserved_page = (struct snd_emu10k1_memblk *)
+ snd_emu10k1_synth_alloc(emu, 4096);
+ if (emu->reserved_page)
+ emu->reserved_page->map_locked = 1;
+
+ /* Clear silent pages and set up pointers */
+ memset(emu->silent_page.area, 0, PAGE_SIZE);
+ silent_page = emu->silent_page.addr << 1;
+ for (idx = 0; idx < MAXPAGES; idx++)
+ ((u32 *)emu->ptb_pages.area)[idx] = cpu_to_le32(silent_page | idx);
+
+ /* set up voice indices */
+ for (idx = 0; idx < NUM_G; idx++) {
+ emu->voices[idx].emu = emu;
+ emu->voices[idx].number = idx;
}
+ if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0)
+ goto error;
+#ifdef CONFIG_PM
+ if ((err = alloc_pm_buffer(emu)) < 0)
+ goto error;
+#endif
+
+ /* Initialize the effect engine */
+ if ((err = snd_emu10k1_init_efx(emu)) < 0)
+ goto error;
+ snd_emu10k1_audio_enable(emu);
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0)
+ goto error;
+
+#ifdef CONFIG_PROC_FS
snd_emu10k1_proc_init(emu);
+#endif
snd_card_set_dev(card, &pci->dev);
*remu = emu;
return 0;
+
+ error:
+ snd_emu10k1_free(emu);
+ return err;
}
+#ifdef CONFIG_PM
+static unsigned char saved_regs[] = {
+ CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP,
+ FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL,
+ ATKHLDM, DCYSUSM, LFOVAL2, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2,
+ TEMPENV, ADCCR, FXWC, MICBA, ADCBA, FXBA,
+ MICBS, ADCBS, FXBS, CDCS, GPSCS, SPCS0, SPCS1, SPCS2,
+ SPBYPASS, AC97SLOT, CDSRCS, GPSRCS, ZVSRCS, MICIDX, ADCIDX, FXIDX,
+ 0xff /* end */
+};
+static unsigned char saved_regs_audigy[] = {
+ A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE,
+ A_FXRT2, A_SENDAMOUNTS, A_FXRT1,
+ 0xff /* end */
+};
+
+static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
+{
+ int size;
+
+ size = ARRAY_SIZE(saved_regs);
+ if (emu->audigy)
+ size += ARRAY_SIZE(saved_regs_audigy);
+ emu->saved_ptr = vmalloc(4 * NUM_G * size);
+ if (! emu->saved_ptr)
+ return -ENOMEM;
+ if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0)
+ return -ENOMEM;
+ if (emu->card_capabilities->ca0151_chip &&
+ snd_p16v_alloc_pm_buffer(emu) < 0)
+ return -ENOMEM;
+ return 0;
+}
+
+static void free_pm_buffer(struct snd_emu10k1 *emu)
+{
+ vfree(emu->saved_ptr);
+ snd_emu10k1_efx_free_pm_buffer(emu);
+ if (emu->card_capabilities->ca0151_chip)
+ snd_p16v_free_pm_buffer(emu);
+}
+
+void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu)
+{
+ int i;
+ unsigned char *reg;
+ unsigned int *val;
+
+ val = emu->saved_ptr;
+ for (reg = saved_regs; *reg != 0xff; reg++)
+ for (i = 0; i < NUM_G; i++, val++)
+ *val = snd_emu10k1_ptr_read(emu, *reg, i);
+ if (emu->audigy) {
+ for (reg = saved_regs_audigy; *reg != 0xff; reg++)
+ for (i = 0; i < NUM_G; i++, val++)
+ *val = snd_emu10k1_ptr_read(emu, *reg, i);
+ }
+ if (emu->audigy)
+ emu->saved_a_iocfg = inl(emu->port + A_IOCFG);
+ emu->saved_hcfg = inl(emu->port + HCFG);
+}
+
+void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
+{
+ if (emu->card_capabilities->ecard)
+ snd_emu10k1_ecard_init(emu);
+ else
+ snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
+ snd_emu10k1_init(emu, emu->enable_ir, 1);
+}
+
+void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
+{
+ int i;
+ unsigned char *reg;
+ unsigned int *val;
+
+ snd_emu10k1_audio_enable(emu);
+
+ /* resore for spdif */
+ if (emu->audigy)
+ outl(emu->port + A_IOCFG, emu->saved_a_iocfg);
+ outl(emu->port + HCFG, emu->saved_hcfg);
+
+ val = emu->saved_ptr;
+ for (reg = saved_regs; *reg != 0xff; reg++)
+ for (i = 0; i < NUM_G; i++, val++)
+ snd_emu10k1_ptr_write(emu, *reg, i, *val);
+ if (emu->audigy) {
+ for (reg = saved_regs_audigy; *reg != 0xff; reg++)
+ for (i = 0; i < NUM_G; i++, val++)
+ snd_emu10k1_ptr_write(emu, *reg, i, *val);
+ }
+}
+#endif
+
/* memory.c */
EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
EXPORT_SYMBOL(snd_emu10k1_synth_free);
diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c
index 4df668eb32b4..42bae6f7e9a4 100644
--- a/sound/pci/emu10k1/emu10k1_patch.c
+++ b/sound/pci/emu10k1/emu10k1_patch.c
@@ -35,14 +35,15 @@
* allocate a sample block and copy data from userspace
*/
int
-snd_emu10k1_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
- snd_util_memhdr_t *hdr, const void __user *data, long count)
+snd_emu10k1_sample_new(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *data, long count)
{
int offset;
int truesize, size, loopsize, blocksize;
int loopend, sampleend;
unsigned int start_addr;
- emu10k1_t *emu;
+ struct snd_emu10k1 *emu;
emu = rec->hw;
snd_assert(sp != NULL, return -EINVAL);
@@ -205,10 +206,10 @@ snd_emu10k1_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
* free a sample block
*/
int
-snd_emu10k1_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp,
- snd_util_memhdr_t *hdr)
+snd_emu10k1_sample_free(struct snd_emux *rec, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr)
{
- emu10k1_t *emu;
+ struct snd_emu10k1 *emu;
emu = rec->hw;
snd_assert(sp != NULL, return -EINVAL);
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c
index 8bd58d1dcc26..1fa393f22a99 100644
--- a/sound/pci/emu10k1/emu10k1_synth.c
+++ b/sound/pci/emu10k1/emu10k1_synth.c
@@ -28,11 +28,11 @@ MODULE_LICENSE("GPL");
/*
* create a new hardware dependent device for Emu10k1
*/
-static int snd_emu10k1_synth_new_device(snd_seq_device_t *dev)
+static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev)
{
- snd_emux_t *emu;
- emu10k1_t *hw;
- snd_emu10k1_synth_arg_t *arg;
+ struct snd_emux *emu;
+ struct snd_emu10k1 *hw;
+ struct snd_emu10k1_synth_arg *arg;
unsigned long flags;
arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
@@ -76,10 +76,10 @@ static int snd_emu10k1_synth_new_device(snd_seq_device_t *dev)
return 0;
}
-static int snd_emu10k1_synth_delete_device(snd_seq_device_t *dev)
+static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev)
{
- snd_emux_t *emu;
- emu10k1_t *hw;
+ struct snd_emux *emu;
+ struct snd_emu10k1 *hw;
unsigned long flags;
if (dev->driver_data == NULL)
@@ -104,11 +104,12 @@ static int snd_emu10k1_synth_delete_device(snd_seq_device_t *dev)
static int __init alsa_emu10k1_synth_init(void)
{
- static snd_seq_dev_ops_t ops = {
+ static struct snd_seq_dev_ops ops = {
snd_emu10k1_synth_new_device,
snd_emu10k1_synth_delete_device,
};
- return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops, sizeof(snd_emu10k1_synth_arg_t));
+ return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops,
+ sizeof(struct snd_emu10k1_synth_arg));
}
static void __exit alsa_emu10k1_synth_exit(void)
diff --git a/sound/pci/emu10k1/emu10k1_synth_local.h b/sound/pci/emu10k1/emu10k1_synth_local.h
index 7f50b01ddb76..308ddc84bb4d 100644
--- a/sound/pci/emu10k1/emu10k1_synth_local.h
+++ b/sound/pci/emu10k1/emu10k1_synth_local.h
@@ -26,13 +26,18 @@
#include <sound/emu10k1_synth.h>
/* emu10k1_patch.c */
-int snd_emu10k1_sample_new(snd_emux_t *private_data, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *_data, long count);
-int snd_emu10k1_sample_free(snd_emux_t *private_data, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
-int snd_emu10k1_memhdr_init(snd_emux_t *emu);
+int snd_emu10k1_sample_new(struct snd_emux *private_data,
+ struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *_data, long count);
+int snd_emu10k1_sample_free(struct snd_emux *private_data,
+ struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr);
+int snd_emu10k1_memhdr_init(struct snd_emux *emu);
/* emu10k1_callback.c */
-void snd_emu10k1_ops_setup(snd_emux_t *emu);
-int snd_emu10k1_synth_get_voice(emu10k1_t *hw);
+void snd_emu10k1_ops_setup(struct snd_emux *emu);
+int snd_emu10k1_synth_get_voice(struct snd_emu10k1 *hw);
#endif /* __EMU10K1_SYNTH_LOCAL_H */
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 795577716a5d..1107c8ec7f78 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -195,30 +195,26 @@ MODULE_PARM_DESC(enable, "Enable the EMU10K1X soundcard.");
* playback.
*/
-typedef struct snd_emu10k1x_voice emu10k1x_voice_t;
-typedef struct snd_emu10k1x emu10k1x_t;
-typedef struct snd_emu10k1x_pcm emu10k1x_pcm_t;
-
-struct snd_emu10k1x_voice {
- emu10k1x_t *emu;
+struct emu10k1x_voice {
+ struct emu10k1x *emu;
int number;
int use;
- emu10k1x_pcm_t *epcm;
+ struct emu10k1x_pcm *epcm;
};
-struct snd_emu10k1x_pcm {
- emu10k1x_t *emu;
- snd_pcm_substream_t *substream;
- emu10k1x_voice_t *voice;
+struct emu10k1x_pcm {
+ struct emu10k1x *emu;
+ struct snd_pcm_substream *substream;
+ struct emu10k1x_voice *voice;
unsigned short running;
};
-typedef struct {
- struct snd_emu10k1x *emu;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *substream_input;
- snd_rawmidi_substream_t *substream_output;
+struct emu10k1x_midi {
+ struct emu10k1x *emu;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *substream_input;
+ struct snd_rawmidi_substream *substream_output;
unsigned int midi_mode;
spinlock_t input_lock;
spinlock_t output_lock;
@@ -226,12 +222,12 @@ typedef struct {
int tx_enable, rx_enable;
int port;
int ipr_tx, ipr_rx;
- void (*interrupt)(emu10k1x_t *emu, unsigned int status);
-} emu10k1x_midi_t;
+ void (*interrupt)(struct emu10k1x *emu, unsigned int status);
+};
// definition of the chip-specific record
-struct snd_emu10k1x {
- snd_card_t *card;
+struct emu10k1x {
+ struct snd_card *card;
struct pci_dev *pci;
unsigned long port;
@@ -245,20 +241,20 @@ struct snd_emu10k1x {
spinlock_t emu_lock;
spinlock_t voice_lock;
- ac97_t *ac97;
- snd_pcm_t *pcm;
+ struct snd_ac97 *ac97;
+ struct snd_pcm *pcm;
- emu10k1x_voice_t voices[3];
- emu10k1x_voice_t capture_voice;
+ struct emu10k1x_voice voices[3];
+ struct emu10k1x_voice capture_voice;
u32 spdif_bits[3]; // SPDIF out setup
struct snd_dma_buffer dma_buffer;
- emu10k1x_midi_t midi;
+ struct emu10k1x_midi midi;
};
/* hardware definition */
-static snd_pcm_hardware_t snd_emu10k1x_playback_hw = {
+static struct snd_pcm_hardware snd_emu10k1x_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -277,7 +273,7 @@ static snd_pcm_hardware_t snd_emu10k1x_playback_hw = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_emu10k1x_capture_hw = {
+static struct snd_pcm_hardware snd_emu10k1x_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -296,7 +292,7 @@ static snd_pcm_hardware_t snd_emu10k1x_capture_hw = {
.fifo_size = 0,
};
-static unsigned int snd_emu10k1x_ptr_read(emu10k1x_t * emu,
+static unsigned int snd_emu10k1x_ptr_read(struct emu10k1x * emu,
unsigned int reg,
unsigned int chn)
{
@@ -312,7 +308,7 @@ static unsigned int snd_emu10k1x_ptr_read(emu10k1x_t * emu,
return val;
}
-static void snd_emu10k1x_ptr_write(emu10k1x_t *emu,
+static void snd_emu10k1x_ptr_write(struct emu10k1x *emu,
unsigned int reg,
unsigned int chn,
unsigned int data)
@@ -328,7 +324,7 @@ static void snd_emu10k1x_ptr_write(emu10k1x_t *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_emu10k1x_intr_enable(emu10k1x_t *emu, unsigned int intrenb)
+static void snd_emu10k1x_intr_enable(struct emu10k1x *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -339,7 +335,7 @@ static void snd_emu10k1x_intr_enable(emu10k1x_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_emu10k1x_intr_disable(emu10k1x_t *emu, unsigned int intrenb)
+static void snd_emu10k1x_intr_disable(struct emu10k1x *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -350,7 +346,7 @@ static void snd_emu10k1x_intr_disable(emu10k1x_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value)
+static void snd_emu10k1x_gpio_write(struct emu10k1x *emu, unsigned int value)
{
unsigned long flags;
@@ -359,14 +355,14 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_emu10k1x_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
-static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
+static void snd_emu10k1x_pcm_interrupt(struct emu10k1x *emu, struct emu10k1x_voice *voice)
{
- emu10k1x_pcm_t *epcm;
+ struct emu10k1x_pcm *epcm;
if ((epcm = voice->epcm) == NULL)
return;
@@ -382,11 +378,11 @@ static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
}
/* open callback */
-static int snd_emu10k1x_playback_open(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_playback_open(struct snd_pcm_substream *substream)
{
- emu10k1x_t *chip = snd_pcm_substream_chip(substream);
- emu10k1x_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct emu10k1x *chip = snd_pcm_substream_chip(substream);
+ struct emu10k1x_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
@@ -410,17 +406,17 @@ static int snd_emu10k1x_playback_open(snd_pcm_substream_t *substream)
}
/* close callback */
-static int snd_emu10k1x_playback_close(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_playback_close(struct snd_pcm_substream *substream)
{
return 0;
}
/* hw_params callback */
-static int snd_emu10k1x_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_emu10k1x_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
if (! epcm->voice) {
epcm->voice = &epcm->emu->voices[substream->pcm->device];
@@ -433,10 +429,10 @@ static int snd_emu10k1x_pcm_hw_params(snd_pcm_substream_t *substream,
}
/* hw_free callback */
-static int snd_emu10k1x_pcm_hw_free(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_hw_free(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm;
if (runtime->private_data == NULL)
return 0;
@@ -453,11 +449,11 @@ static int snd_emu10k1x_pcm_hw_free(snd_pcm_substream_t *substream)
}
/* prepare callback */
-static int snd_emu10k1x_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
int voice = epcm->voice->number;
u32 *table_base = (u32 *)(emu->dma_buffer.area+1024*voice);
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -482,12 +478,12 @@ static int snd_emu10k1x_pcm_prepare(snd_pcm_substream_t *substream)
}
/* trigger callback */
-static int snd_emu10k1x_pcm_trigger(snd_pcm_substream_t *substream,
+static int snd_emu10k1x_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
int channel = epcm->voice->number;
int result = 0;
@@ -516,11 +512,11 @@ static int snd_emu10k1x_pcm_trigger(snd_pcm_substream_t *substream,
/* pointer callback */
static snd_pcm_uframes_t
-snd_emu10k1x_pcm_pointer(snd_pcm_substream_t *substream)
+snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
int channel = epcm->voice->number;
snd_pcm_uframes_t ptr = 0, ptr1 = 0, ptr2= 0,ptr3 = 0,ptr4 = 0;
@@ -547,7 +543,7 @@ snd_emu10k1x_pcm_pointer(snd_pcm_substream_t *substream)
}
/* operators */
-static snd_pcm_ops_t snd_emu10k1x_playback_ops = {
+static struct snd_pcm_ops snd_emu10k1x_playback_ops = {
.open = snd_emu10k1x_playback_open,
.close = snd_emu10k1x_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -559,11 +555,11 @@ static snd_pcm_ops_t snd_emu10k1x_playback_ops = {
};
/* open_capture callback */
-static int snd_emu10k1x_pcm_open_capture(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_open_capture(struct snd_pcm_substream *substream)
{
- emu10k1x_t *chip = snd_pcm_substream_chip(substream);
- emu10k1x_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct emu10k1x *chip = snd_pcm_substream_chip(substream);
+ struct emu10k1x_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
@@ -587,17 +583,17 @@ static int snd_emu10k1x_pcm_open_capture(snd_pcm_substream_t *substream)
}
/* close callback */
-static int snd_emu10k1x_pcm_close_capture(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_close_capture(struct snd_pcm_substream *substream)
{
return 0;
}
/* hw_params callback */
-static int snd_emu10k1x_pcm_hw_params_capture(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_emu10k1x_pcm_hw_params_capture(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
if (! epcm->voice) {
if (epcm->emu->capture_voice.use)
@@ -612,11 +608,11 @@ static int snd_emu10k1x_pcm_hw_params_capture(snd_pcm_substream_t *substream,
}
/* hw_free callback */
-static int snd_emu10k1x_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_hw_free_capture(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm;
+ struct emu10k1x_pcm *epcm;
if (runtime->private_data == NULL)
return 0;
@@ -632,10 +628,10 @@ static int snd_emu10k1x_pcm_hw_free_capture(snd_pcm_substream_t *substream)
}
/* prepare capture callback */
-static int snd_emu10k1x_pcm_prepare_capture(snd_pcm_substream_t *substream)
+static int snd_emu10k1x_pcm_prepare_capture(struct snd_pcm_substream *substream)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_emu10k1x_ptr_write(emu, CAPTURE_DMA_ADDR, 0, runtime->dma_addr);
snd_emu10k1x_ptr_write(emu, CAPTURE_BUFFER_SIZE, 0, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
@@ -646,12 +642,12 @@ static int snd_emu10k1x_pcm_prepare_capture(snd_pcm_substream_t *substream)
}
/* trigger_capture callback */
-static int snd_emu10k1x_pcm_trigger_capture(snd_pcm_substream_t *substream,
+static int snd_emu10k1x_pcm_trigger_capture(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
int result = 0;
switch (cmd) {
@@ -676,11 +672,11 @@ static int snd_emu10k1x_pcm_trigger_capture(snd_pcm_substream_t *substream,
/* pointer_capture callback */
static snd_pcm_uframes_t
-snd_emu10k1x_pcm_pointer_capture(snd_pcm_substream_t *substream)
+snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream)
{
- emu10k1x_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1x_pcm_t *epcm = runtime->private_data;
+ struct emu10k1x *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct emu10k1x_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr;
if (!epcm->running)
@@ -693,7 +689,7 @@ snd_emu10k1x_pcm_pointer_capture(snd_pcm_substream_t *substream)
return ptr;
}
-static snd_pcm_ops_t snd_emu10k1x_capture_ops = {
+static struct snd_pcm_ops snd_emu10k1x_capture_ops = {
.open = snd_emu10k1x_pcm_open_capture,
.close = snd_emu10k1x_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -704,10 +700,10 @@ static snd_pcm_ops_t snd_emu10k1x_capture_ops = {
.pointer = snd_emu10k1x_pcm_pointer_capture,
};
-static unsigned short snd_emu10k1x_ac97_read(ac97_t *ac97,
+static unsigned short snd_emu10k1x_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- emu10k1x_t *emu = ac97->private_data;
+ struct emu10k1x *emu = ac97->private_data;
unsigned long flags;
unsigned short val;
@@ -718,10 +714,10 @@ static unsigned short snd_emu10k1x_ac97_read(ac97_t *ac97,
return val;
}
-static void snd_emu10k1x_ac97_write(ac97_t *ac97,
+static void snd_emu10k1x_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- emu10k1x_t *emu = ac97->private_data;
+ struct emu10k1x *emu = ac97->private_data;
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
@@ -730,12 +726,12 @@ static void snd_emu10k1x_ac97_write(ac97_t *ac97,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static int snd_emu10k1x_ac97(emu10k1x_t *chip)
+static int snd_emu10k1x_ac97(struct emu10k1x *chip)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_emu10k1x_ac97_write,
.read = snd_emu10k1x_ac97_read,
};
@@ -750,7 +746,7 @@ static int snd_emu10k1x_ac97(emu10k1x_t *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
-static int snd_emu10k1x_free(emu10k1x_t *chip)
+static int snd_emu10k1x_free(struct emu10k1x *chip)
{
snd_emu10k1x_ptr_write(chip, TRIGGER_CHANNEL, 0, 0);
// disable interrupts
@@ -777,9 +773,9 @@ static int snd_emu10k1x_free(emu10k1x_t *chip)
return 0;
}
-static int snd_emu10k1x_dev_free(snd_device_t *device)
+static int snd_emu10k1x_dev_free(struct snd_device *device)
{
- emu10k1x_t *chip = device->device_data;
+ struct emu10k1x *chip = device->device_data;
return snd_emu10k1x_free(chip);
}
@@ -788,64 +784,56 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id,
{
unsigned int status;
- emu10k1x_t *chip = dev_id;
- emu10k1x_voice_t *pvoice = chip->voices;
+ struct emu10k1x *chip = dev_id;
+ struct emu10k1x_voice *pvoice = chip->voices;
int i;
int mask;
status = inl(chip->port + IPR);
- if(status) {
- // capture interrupt
- if(status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
- emu10k1x_voice_t *pvoice = &chip->capture_voice;
- if(pvoice->use)
- snd_emu10k1x_pcm_interrupt(chip, pvoice);
- else
- snd_emu10k1x_intr_disable(chip,
- INTE_CAP_0_LOOP |
- INTE_CAP_0_HALF_LOOP);
- }
-
- mask = IPR_CH_0_LOOP|IPR_CH_0_HALF_LOOP;
- for(i = 0; i < 3; i++) {
- if(status & mask) {
- if(pvoice->use)
- snd_emu10k1x_pcm_interrupt(chip, pvoice);
- else
- snd_emu10k1x_intr_disable(chip, mask);
- }
- pvoice++;
- mask <<= 1;
- }
+ if (! status)
+ return IRQ_NONE;
+
+ // capture interrupt
+ if (status & (IPR_CAP_0_LOOP | IPR_CAP_0_HALF_LOOP)) {
+ struct emu10k1x_voice *pvoice = &chip->capture_voice;
+ if (pvoice->use)
+ snd_emu10k1x_pcm_interrupt(chip, pvoice);
+ else
+ snd_emu10k1x_intr_disable(chip,
+ INTE_CAP_0_LOOP |
+ INTE_CAP_0_HALF_LOOP);
+ }
- if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) {
- if (chip->midi.interrupt)
- chip->midi.interrupt(chip, status);
- else
- snd_emu10k1x_intr_disable(chip, INTE_MIDITXENABLE|INTE_MIDIRXENABLE);
+ mask = IPR_CH_0_LOOP|IPR_CH_0_HALF_LOOP;
+ for (i = 0; i < 3; i++) {
+ if (status & mask) {
+ if (pvoice->use)
+ snd_emu10k1x_pcm_interrupt(chip, pvoice);
+ else
+ snd_emu10k1x_intr_disable(chip, mask);
}
+ pvoice++;
+ mask <<= 1;
+ }
- // acknowledge the interrupt if necessary
- if(status)
- outl(status, chip->port+IPR);
-
-// snd_printk(KERN_INFO "interrupt %08x\n", status);
+ if (status & (IPR_MIDITRANSBUFEMPTY|IPR_MIDIRECVBUFEMPTY)) {
+ if (chip->midi.interrupt)
+ chip->midi.interrupt(chip, status);
+ else
+ snd_emu10k1x_intr_disable(chip, INTE_MIDITXENABLE|INTE_MIDIRXENABLE);
}
+
+ // acknowledge the interrupt if necessary
+ outl(status, chip->port + IPR);
+ // snd_printk(KERN_INFO "interrupt %08x\n", status);
return IRQ_HANDLED;
}
-static void snd_emu10k1x_pcm_free(snd_pcm_t *pcm)
-{
- emu10k1x_t *emu = pcm->private_data;
- emu->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_emu10k1x_pcm(emu10k1x_t *emu, int device, snd_pcm_t **rpcm)
+static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
int capture = 0;
@@ -858,7 +846,6 @@ static int __devinit snd_emu10k1x_pcm(emu10k1x_t *emu, int device, snd_pcm_t **r
return err;
pcm->private_data = emu;
- pcm->private_free = snd_emu10k1x_pcm_free;
switch(device) {
case 0:
@@ -896,14 +883,14 @@ static int __devinit snd_emu10k1x_pcm(emu10k1x_t *emu, int device, snd_pcm_t **r
return 0;
}
-static int __devinit snd_emu10k1x_create(snd_card_t *card,
+static int __devinit snd_emu10k1x_create(struct snd_card *card,
struct pci_dev *pci,
- emu10k1x_t **rchip)
+ struct emu10k1x **rchip)
{
- emu10k1x_t *chip;
+ struct emu10k1x *chip;
int err;
int ch;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_emu10k1x_dev_free,
};
@@ -1017,10 +1004,10 @@ static int __devinit snd_emu10k1x_create(snd_card_t *card,
return 0;
}
-static void snd_emu10k1x_proc_reg_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1x_proc_reg_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1x_t *emu = entry->private_data;
+ struct emu10k1x *emu = entry->private_data;
unsigned long value,value1,value2;
unsigned long flags;
int i;
@@ -1045,10 +1032,10 @@ static void snd_emu10k1x_proc_reg_read(snd_info_entry_t *entry,
}
}
-static void snd_emu10k1x_proc_reg_write(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1x_t *emu = entry->private_data;
+ struct emu10k1x *emu = entry->private_data;
char line[64];
unsigned int reg, channel_id , val;
@@ -1062,9 +1049,9 @@ static void snd_emu10k1x_proc_reg_write(snd_info_entry_t *entry,
}
}
-static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu)
+static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {
snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
@@ -1077,7 +1064,7 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu)
return 0;
}
-static int snd_emu10k1x_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1x_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1086,20 +1073,20 @@ static int snd_emu10k1x_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_emu10k1x_shared_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1x_shared_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);
+ struct emu10k1x *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (snd_emu10k1x_ptr_read(emu, SPDIF_SELECT, 0) == 0x700) ? 0 : 1;
return 0;
}
-static int snd_emu10k1x_shared_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1x_shared_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);
+ struct emu10k1x *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
@@ -1119,7 +1106,7 @@ static int snd_emu10k1x_shared_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1x_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1x_shared_spdif __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog/Digital Output Jack",
@@ -1128,17 +1115,17 @@ static snd_kcontrol_new_t snd_emu10k1x_shared_spdif __devinitdata =
.put = snd_emu10k1x_shared_spdif_put
};
-static int snd_emu10k1x_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1x_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_emu10k1x_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1x_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);
+ struct emu10k1x *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
@@ -1148,8 +1135,8 @@ static int snd_emu10k1x_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1x_spdif_get_mask(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1x_spdif_get_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -1158,10 +1145,10 @@ static int snd_emu10k1x_spdif_get_mask(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1x_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1x_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1x_t *emu = snd_kcontrol_chip(kcontrol);
+ struct emu10k1x *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
int change;
unsigned int val;
@@ -1178,7 +1165,7 @@ static int snd_emu10k1x_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1x_spdif_mask_control =
+static struct snd_kcontrol_new snd_emu10k1x_spdif_mask_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1188,7 +1175,7 @@ static snd_kcontrol_new_t snd_emu10k1x_spdif_mask_control =
.get = snd_emu10k1x_spdif_get_mask
};
-static snd_kcontrol_new_t snd_emu10k1x_spdif_control =
+static struct snd_kcontrol_new snd_emu10k1x_spdif_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1198,11 +1185,11 @@ static snd_kcontrol_new_t snd_emu10k1x_spdif_control =
.put = snd_emu10k1x_spdif_put
};
-static int __devinit snd_emu10k1x_mixer(emu10k1x_t *emu)
+static int __devinit snd_emu10k1x_mixer(struct emu10k1x *emu)
{
int err;
- snd_kcontrol_t *kctl;
- snd_card_t *card = emu->card;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = emu->card;
if ((kctl = snd_ctl_new1(&snd_emu10k1x_spdif_mask_control, emu)) == NULL)
return -ENOMEM;
@@ -1223,12 +1210,12 @@ static int __devinit snd_emu10k1x_mixer(emu10k1x_t *emu)
#define EMU10K1X_MIDI_MODE_INPUT (1<<0)
#define EMU10K1X_MIDI_MODE_OUTPUT (1<<1)
-static inline unsigned char mpu401_read(emu10k1x_t *emu, emu10k1x_midi_t *mpu, int idx)
+static inline unsigned char mpu401_read(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int idx)
{
return (unsigned char)snd_emu10k1x_ptr_read(emu, mpu->port + idx, 0);
}
-static inline void mpu401_write(emu10k1x_t *emu, emu10k1x_midi_t *mpu, int data, int idx)
+static inline void mpu401_write(struct emu10k1x *emu, struct emu10k1x_midi *mpu, int data, int idx)
{
snd_emu10k1x_ptr_write(emu, mpu->port + idx, 0, data);
}
@@ -1245,7 +1232,7 @@ static inline void mpu401_write(emu10k1x_t *emu, emu10k1x_midi_t *mpu, int data,
#define MPU401_ENTER_UART 0x3f
#define MPU401_ACK 0xfe
-static void mpu401_clear_rx(emu10k1x_t *emu, emu10k1x_midi_t *mpu)
+static void mpu401_clear_rx(struct emu10k1x *emu, struct emu10k1x_midi *mpu)
{
int timeout = 100000;
for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--)
@@ -1260,7 +1247,8 @@ static void mpu401_clear_rx(emu10k1x_t *emu, emu10k1x_midi_t *mpu)
*/
-static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, unsigned int status)
+static void do_emu10k1x_midi_interrupt(struct emu10k1x *emu,
+ struct emu10k1x_midi *midi, unsigned int status)
{
unsigned char byte;
@@ -1293,12 +1281,13 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
spin_unlock(&midi->output_lock);
}
-static void snd_emu10k1x_midi_interrupt(emu10k1x_t *emu, unsigned int status)
+static void snd_emu10k1x_midi_interrupt(struct emu10k1x *emu, unsigned int status)
{
do_emu10k1x_midi_interrupt(emu, &emu->midi, status);
}
-static void snd_emu10k1x_midi_cmd(emu10k1x_t * emu, emu10k1x_midi_t *midi, unsigned char cmd, int ack)
+static void snd_emu10k1x_midi_cmd(struct emu10k1x * emu,
+ struct emu10k1x_midi *midi, unsigned char cmd, int ack)
{
unsigned long flags;
int timeout, ok;
@@ -1330,10 +1319,10 @@ static void snd_emu10k1x_midi_cmd(emu10k1x_t * emu, emu10k1x_midi_t *midi, unsig
mpu401_read_data(emu, midi));
}
-static int snd_emu10k1x_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1x_midi_input_open(struct snd_rawmidi_substream *substream)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -1351,10 +1340,10 @@ static int snd_emu10k1x_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1x_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1x_midi_output_open(struct snd_rawmidi_substream *substream)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -1372,10 +1361,10 @@ static int snd_emu10k1x_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1x_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1x_midi_input_close(struct snd_rawmidi_substream *substream)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -1393,10 +1382,10 @@ static int snd_emu10k1x_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1x_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1x_midi_output_close(struct snd_rawmidi_substream *substream)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -1414,10 +1403,10 @@ static int snd_emu10k1x_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_emu10k1x_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_emu10k1x_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
emu = midi->emu;
snd_assert(emu, return);
@@ -1427,10 +1416,10 @@ static void snd_emu10k1x_midi_input_trigger(snd_rawmidi_substream_t * substream,
snd_emu10k1x_intr_disable(emu, midi->rx_enable);
}
-static void snd_emu10k1x_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_emu10k1x_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- emu10k1x_t *emu;
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)substream->rmidi->private_data;
+ struct emu10k1x *emu;
+ struct emu10k1x_midi *midi = substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -1467,30 +1456,31 @@ static void snd_emu10k1x_midi_output_trigger(snd_rawmidi_substream_t * substream
*/
-static snd_rawmidi_ops_t snd_emu10k1x_midi_output =
+static struct snd_rawmidi_ops snd_emu10k1x_midi_output =
{
.open = snd_emu10k1x_midi_output_open,
.close = snd_emu10k1x_midi_output_close,
.trigger = snd_emu10k1x_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_emu10k1x_midi_input =
+static struct snd_rawmidi_ops snd_emu10k1x_midi_input =
{
.open = snd_emu10k1x_midi_input_open,
.close = snd_emu10k1x_midi_input_close,
.trigger = snd_emu10k1x_midi_input_trigger,
};
-static void snd_emu10k1x_midi_free(snd_rawmidi_t *rmidi)
+static void snd_emu10k1x_midi_free(struct snd_rawmidi *rmidi)
{
- emu10k1x_midi_t *midi = (emu10k1x_midi_t *)rmidi->private_data;
+ struct emu10k1x_midi *midi = rmidi->private_data;
midi->interrupt = NULL;
midi->rmidi = NULL;
}
-static int __devinit emu10k1x_midi_init(emu10k1x_t *emu, emu10k1x_midi_t *midi, int device, char *name)
+static int __devinit emu10k1x_midi_init(struct emu10k1x *emu,
+ struct emu10k1x_midi *midi, int device, char *name)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0)
@@ -1511,9 +1501,9 @@ static int __devinit emu10k1x_midi_init(emu10k1x_t *emu, emu10k1x_midi_t *midi,
return 0;
}
-static int __devinit snd_emu10k1x_midi(emu10k1x_t *emu)
+static int __devinit snd_emu10k1x_midi(struct emu10k1x *emu)
{
- emu10k1x_midi_t *midi = &emu->midi;
+ struct emu10k1x_midi *midi = &emu->midi;
int err;
if ((err = emu10k1x_midi_init(emu, midi, 0, "EMU10K1X MPU-401 (UART)")) < 0)
@@ -1532,8 +1522,8 @@ static int __devinit snd_emu10k1x_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- emu10k1x_t *chip;
+ struct snd_card *card;
+ struct emu10k1x *chip;
int err;
if (dev >= SNDRV_CARDS)
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 03e8c1678952..509837252735 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -27,8 +27,10 @@
#include <sound/driver.h>
#include <linux/pci.h>
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/init.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
@@ -309,9 +311,10 @@ static inline void snd_leave_user(mm_segment_t fs)
* controls
*/
-static int snd_emu10k1_gpr_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_gpr_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
+ struct snd_emu10k1_fx8010_ctl *ctl =
+ (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
if (ctl->min == 0 && ctl->max == 1)
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -323,10 +326,11 @@ static int snd_emu10k1_gpr_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_emu10k1_gpr_ctl_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_gpr_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_fx8010_ctl *ctl =
+ (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
unsigned long flags;
unsigned int i;
@@ -337,10 +341,11 @@ static int snd_emu10k1_gpr_ctl_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_emu10k1_gpr_ctl_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_fx8010_ctl *ctl =
+ (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
unsigned long flags;
unsigned int nval, val;
unsigned int i, j;
@@ -393,9 +398,9 @@ static int snd_emu10k1_gpr_ctl_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
* Interrupt handler
*/
-static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu)
+static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu)
{
- snd_emu10k1_fx8010_irq_t *irq, *nirq;
+ struct snd_emu10k1_fx8010_irq *irq, *nirq;
irq = emu->fx8010.irq_handlers;
while (irq) {
@@ -409,13 +414,13 @@ static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu)
}
}
-int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
- snd_fx8010_irq_handler_t *handler,
- unsigned char gpr_running,
- void *private_data,
- snd_emu10k1_fx8010_irq_t **r_irq)
+int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
+ snd_fx8010_irq_handler_t *handler,
+ unsigned char gpr_running,
+ void *private_data,
+ struct snd_emu10k1_fx8010_irq **r_irq)
{
- snd_emu10k1_fx8010_irq_t *irq;
+ struct snd_emu10k1_fx8010_irq *irq;
unsigned long flags;
irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
@@ -440,10 +445,10 @@ int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
return 0;
}
-int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
- snd_emu10k1_fx8010_irq_t *irq)
+int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_irq *irq)
{
- snd_emu10k1_fx8010_irq_t *tmp;
+ struct snd_emu10k1_fx8010_irq *tmp;
unsigned long flags;
spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
@@ -468,7 +473,8 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
* EMU10K1 effect manager
*************************************************************************/
-static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
+static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode,
+ unsigned int *ptr,
u32 op, u32 r, u32 a, u32 x, u32 y)
{
u_int32_t *code;
@@ -483,7 +489,8 @@ static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr
#define OP(icode, ptr, op, r, a, x, y) \
snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)
-static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
+static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode,
+ unsigned int *ptr,
u32 op, u32 r, u32 a, u32 x, u32 y)
{
u_int32_t *code;
@@ -498,19 +505,20 @@ static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned i
#define A_OP(icode, ptr, op, r, a, x, y) \
snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)
-static void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data)
+static void snd_emu10k1_efx_write(struct snd_emu10k1 *emu, unsigned int pc, unsigned int data)
{
pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
snd_emu10k1_ptr_write(emu, pc, 0, data);
}
-unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc)
+unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc)
{
pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
return snd_emu10k1_ptr_read(emu, pc, 0);
}
-static int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int gpr;
u32 val;
@@ -525,7 +533,8 @@ static int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int gpr;
u32 val;
@@ -539,7 +548,8 @@ static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int tram;
u32 addr, val;
@@ -561,7 +571,8 @@ static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int tram;
u32 val, addr;
@@ -583,7 +594,8 @@ static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
u32 pc, lo, hi;
@@ -599,7 +611,8 @@ static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
u32 pc;
@@ -614,10 +627,11 @@ static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return 0;
}
-static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ctl_elem_id_t *id)
+static struct snd_emu10k1_fx8010_ctl *
+snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
{
- snd_emu10k1_fx8010_ctl_t *ctl;
- snd_kcontrol_t *kcontrol;
+ struct snd_emu10k1_fx8010_ctl *ctl;
+ struct snd_kcontrol *kcontrol;
struct list_head *list;
list_for_each(list, &emu->fx8010.gpr_ctl) {
@@ -631,13 +645,14 @@ static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ct
return NULL;
}
-static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
unsigned int i;
- snd_ctl_elem_id_t __user *_id;
- snd_ctl_elem_id_t id;
- emu10k1_fx8010_control_gpr_t __user *_gctl;
- emu10k1_fx8010_control_gpr_t *gctl;
+ struct snd_ctl_elem_id __user *_id;
+ struct snd_ctl_elem_id id;
+ struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
+ struct snd_emu10k1_fx8010_control_gpr *gctl;
int err;
for (i = 0, _id = icode->gpr_del_controls;
@@ -685,28 +700,29 @@ static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *ic
return err;
}
-static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl)
+static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl)
{
- snd_emu10k1_fx8010_ctl_t *ctl;
+ struct snd_emu10k1_fx8010_ctl *ctl;
- ctl = (snd_emu10k1_fx8010_ctl_t *)kctl->private_value;
+ ctl = (struct snd_emu10k1_fx8010_ctl *) kctl->private_value;
kctl->private_value = 0;
list_del(&ctl->list);
kfree(ctl);
}
-static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
unsigned int i, j;
- emu10k1_fx8010_control_gpr_t __user *_gctl;
- emu10k1_fx8010_control_gpr_t *gctl;
- snd_emu10k1_fx8010_ctl_t *ctl, *nctl;
- snd_kcontrol_new_t knew;
- snd_kcontrol_t *kctl;
- snd_ctl_elem_value_t *val;
+ struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
+ struct snd_emu10k1_fx8010_control_gpr *gctl;
+ struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
+ struct snd_kcontrol_new knew;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_value *val;
int err = 0;
- val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
+ val = kmalloc(sizeof(*val), GFP_KERNEL);
gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
if (!val || !gctl || !nctl) {
@@ -751,7 +767,7 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
nctl->max = gctl->max;
nctl->translation = gctl->translation;
if (ctl == NULL) {
- ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);
+ ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
if (ctl == NULL) {
err = -ENOMEM;
goto __error;
@@ -782,13 +798,14 @@ static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
return err;
}
-static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
unsigned int i;
- snd_ctl_elem_id_t id;
- snd_ctl_elem_id_t __user *_id;
- snd_emu10k1_fx8010_ctl_t *ctl;
- snd_card_t *card = emu->card;
+ struct snd_ctl_elem_id id;
+ struct snd_ctl_elem_id __user *_id;
+ struct snd_emu10k1_fx8010_ctl *ctl;
+ struct snd_card *card = emu->card;
for (i = 0, _id = icode->gpr_del_controls;
i < icode->gpr_del_control_count; i++, _id++) {
@@ -803,14 +820,15 @@ static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode
return 0;
}
-static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
unsigned int i = 0, j;
unsigned int total = 0;
- emu10k1_fx8010_control_gpr_t *gctl;
- emu10k1_fx8010_control_gpr_t __user *_gctl;
- snd_emu10k1_fx8010_ctl_t *ctl;
- snd_ctl_elem_id_t *id;
+ struct snd_emu10k1_fx8010_control_gpr *gctl;
+ struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
+ struct snd_emu10k1_fx8010_ctl *ctl;
+ struct snd_ctl_elem_id *id;
struct list_head *list;
gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
@@ -851,7 +869,8 @@ static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icod
return 0;
}
-static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int err = 0;
@@ -882,7 +901,8 @@ static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return err;
}
-static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
+static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_code *icode)
{
int err;
@@ -900,11 +920,12 @@ static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
return err;
}
-static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
+static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_pcm_rec *ipcm)
{
unsigned int i;
int err = 0;
- snd_emu10k1_fx8010_pcm_t *pcm;
+ struct snd_emu10k1_fx8010_pcm *pcm;
if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
return -EINVAL;
@@ -945,11 +966,12 @@ static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
return err;
}
-static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
+static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_pcm_rec *ipcm)
{
unsigned int i;
int err = 0;
- snd_emu10k1_fx8010_pcm_t *pcm;
+ struct snd_emu10k1_fx8010_pcm *pcm;
if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
return -EINVAL;
@@ -979,7 +1001,9 @@ static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
#define SND_EMU10K1_PLAYBACK_CHANNELS 8
#define SND_EMU10K1_CAPTURE_CHANNELS 4
-static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
+static void __devinit
+snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ const char *name, int gpr, int defval)
{
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, name);
@@ -990,7 +1014,9 @@ static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t
ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
}
-static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
+static void __devinit
+snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ const char *name, int gpr, int defval)
{
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, name);
@@ -1002,7 +1028,9 @@ static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr
ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
}
-static void __devinit snd_emu10k1_init_mono_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
+static void __devinit
+snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ const char *name, int gpr, int defval)
{
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, name);
@@ -1013,7 +1041,9 @@ static void __devinit snd_emu10k1_init_mono_onoff_control(emu10k1_fx8010_control
ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
}
-static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
+static void __devinit
+snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
+ const char *name, int gpr, int defval)
{
ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
strcpy(ctl->id.name, name);
@@ -1030,7 +1060,7 @@ static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_contr
* initial DSP configuration for Audigy
*/
-static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
+static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
{
int err, i, z, gpr, nctl;
const int playback = 10;
@@ -1038,17 +1068,17 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
const int stereo_mix = capture + 2;
const int tmp = 0x88;
u32 ptr;
- emu10k1_fx8010_code_t *icode = NULL;
- emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
+ struct snd_emu10k1_fx8010_code *icode = NULL;
+ struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
u32 *gpr_map;
mm_segment_t seg;
- spin_lock_init(&emu->fx8010.irq_lock);
- INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
-
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) {
+ (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;
}
@@ -1074,6 +1104,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
/* stop FX processor */
snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
+#if 0
+ /* FIX: jcd test */
+ for (z = 0; z < 80; z=z+2) {
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
+ A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
+ }
+#endif /* jcd test */
+#if 1
/* PCM front Playback Volume (independent from stereo mix) */
A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
@@ -1419,6 +1457,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
}
+#endif /* JCD test */
/*
* ok, set up done..
*/
@@ -1434,7 +1473,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
seg = snd_enter_user();
icode->gpr_add_control_count = nctl;
- icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
+ icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
err = snd_emu10k1_icode_poke(emu, icode);
snd_leave_user(seg);
@@ -1454,14 +1493,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
/* when volume = max, then copy only to avoid volume modification */
/* with iMAC0 (negative values) */
-static void __devinit _volume(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
}
-static void __devinit _volume_add(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1469,7 +1508,7 @@ static void __devinit _volume_add(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 ds
OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
OP(icode, ptr, iMAC0, dst, dst, src, vol);
}
-static void __devinit _volume_out(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
+static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
{
OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
@@ -1500,23 +1539,24 @@ static void __devinit _volume_out(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 ds
_SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
-static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
+static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
{
int err, i, z, gpr, tmp, playback, capture;
u32 ptr;
- emu10k1_fx8010_code_t *icode;
- emu10k1_fx8010_pcm_t *ipcm = NULL;
- emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
+ struct snd_emu10k1_fx8010_code *icode;
+ struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL;
+ struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
u32 *gpr_map;
mm_segment_t seg;
- spin_lock_init(&emu->fx8010.irq_lock);
- INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
-
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 ||
+ 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(struct snd_emu10k1_fx8010_control_gpr),
+ GFP_KERNEL)) == NULL ||
(ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
err = -ENOMEM;
goto __err;
@@ -2050,7 +2090,7 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
goto __err;
seg = snd_enter_user();
icode->gpr_add_control_count = i;
- icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
+ icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
err = snd_emu10k1_icode_poke(emu, icode);
snd_leave_user(seg);
if (err >= 0)
@@ -2065,15 +2105,17 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
return err;
}
-int __devinit snd_emu10k1_init_efx(emu10k1_t *emu)
+int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
{
+ spin_lock_init(&emu->fx8010.irq_lock);
+ INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
if (emu->audigy)
return _snd_emu10k1_audigy_init_efx(emu);
else
return _snd_emu10k1_init_efx(emu);
}
-void snd_emu10k1_free_efx(emu10k1_t *emu)
+void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
{
/* stop processor */
if (emu->audigy)
@@ -2083,7 +2125,7 @@ void snd_emu10k1_free_efx(emu10k1_t *emu)
}
#if 0 // FIXME: who use them?
-int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output)
+int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
{
if (output < 0 || output >= 6)
return -EINVAL;
@@ -2091,7 +2133,7 @@ int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output)
return 0;
}
-int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output)
+int snd_emu10k1_fx8010_tone_control_deactivate(struct snd_emu10k1 *emu, int output)
{
if (output < 0 || output >= 6)
return -EINVAL;
@@ -2100,7 +2142,7 @@ int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output)
}
#endif
-int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size)
+int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size)
{
u8 size_reg = 0;
@@ -2136,13 +2178,13 @@ int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size)
snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
spin_lock_irq(&emu->emu_lock);
outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
- spin_unlock_irq(&emu->emu_lock);
+ spin_unlock_irq(&emu->emu_lock);
}
return 0;
}
-static int snd_emu10k1_fx8010_open(snd_hwdep_t * hw, struct file *file)
+static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file)
{
return 0;
}
@@ -2155,7 +2197,8 @@ static void copy_string(char *dst, char *src, char *null, int idx)
strcpy(dst, src);
}
-static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
+static int snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_fx8010_info *info)
{
char **fxbus, **extin, **extout;
unsigned short fxbus_mask, extin_mask, extout_mask;
@@ -2181,19 +2224,19 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
return 0;
}
-static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
+static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
{
- emu10k1_t *emu = hw->private_data;
- emu10k1_fx8010_info_t *info;
- emu10k1_fx8010_code_t *icode;
- emu10k1_fx8010_pcm_t *ipcm;
+ struct snd_emu10k1 *emu = hw->private_data;
+ struct snd_emu10k1_fx8010_info *info;
+ struct snd_emu10k1_fx8010_code *icode;
+ struct snd_emu10k1_fx8010_pcm_rec *ipcm;
unsigned int addr;
void __user *argp = (void __user *)arg;
int res;
switch (cmd) {
case SNDRV_EMU10K1_IOCTL_INFO:
- info = (emu10k1_fx8010_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
@@ -2209,7 +2252,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
case SNDRV_EMU10K1_IOCTL_CODE_POKE:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
+ icode = kmalloc(sizeof(*icode), GFP_KERNEL);
if (icode == NULL)
return -ENOMEM;
if (copy_from_user(icode, argp, sizeof(*icode))) {
@@ -2220,7 +2263,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
- icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
+ icode = kmalloc(sizeof(*icode), GFP_KERNEL);
if (icode == NULL)
return -ENOMEM;
if (copy_from_user(icode, argp, sizeof(*icode))) {
@@ -2235,7 +2278,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_PCM_POKE:
- ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
+ ipcm = kmalloc(sizeof(*ipcm), GFP_KERNEL);
if (ipcm == NULL)
return -ENOMEM;
if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
@@ -2327,14 +2370,14 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
return -ENOTTY;
}
-static int snd_emu10k1_fx8010_release(snd_hwdep_t * hw, struct file *file)
+static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
{
return 0;
}
-int __devinit snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t ** rhwdep)
+int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep)
{
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
int err;
if (rhwdep)
@@ -2351,3 +2394,114 @@ int __devinit snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t **
*rhwdep = hw;
return 0;
}
+
+#ifdef CONFIG_PM
+int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
+{
+ int len;
+
+ len = emu->audigy ? 0x200 : 0x100;
+ emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL);
+ if (! emu->saved_gpr)
+ return -ENOMEM;
+ len = emu->audigy ? 0x100 : 0xa0;
+ emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL);
+ emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL);
+ if (! emu->tram_val_saved || ! emu->tram_addr_saved)
+ return -ENOMEM;
+ len = emu->audigy ? 2 * 1024 : 2 * 512;
+ emu->saved_icode = vmalloc(len * 4);
+ if (! emu->saved_icode)
+ return -ENOMEM;
+ return 0;
+}
+
+void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu)
+{
+ kfree(emu->saved_gpr);
+ kfree(emu->tram_val_saved);
+ kfree(emu->tram_addr_saved);
+ vfree(emu->saved_icode);
+}
+
+/*
+ * save/restore GPR, TRAM and codes
+ */
+void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu)
+{
+ int i, len;
+
+ len = emu->audigy ? 0x200 : 0x100;
+ for (i = 0; i < len; i++)
+ emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0);
+
+ len = emu->audigy ? 0x100 : 0xa0;
+ for (i = 0; i < len; i++) {
+ emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0);
+ emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0);
+ if (emu->audigy) {
+ emu->tram_addr_saved[i] >>= 12;
+ emu->tram_addr_saved[i] |=
+ snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20;
+ }
+ }
+
+ len = emu->audigy ? 2 * 1024 : 2 * 512;
+ for (i = 0; i < len; i++)
+ emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i);
+}
+
+void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu)
+{
+ int i, len;
+
+ /* set up TRAM */
+ if (emu->fx8010.etram_pages.bytes > 0) {
+ unsigned size, size_reg = 0;
+ size = emu->fx8010.etram_pages.bytes / 2;
+ size = (size - 1) >> 13;
+ while (size) {
+ size >>= 1;
+ size_reg++;
+ }
+ outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
+ snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
+ snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
+ outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
+ }
+
+ if (emu->audigy)
+ snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
+ else
+ snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
+
+ len = emu->audigy ? 0x200 : 0x100;
+ for (i = 0; i < len; i++)
+ snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]);
+
+ len = emu->audigy ? 0x100 : 0xa0;
+ for (i = 0; i < len; i++) {
+ snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0,
+ emu->tram_val_saved[i]);
+ if (! emu->audigy)
+ snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
+ emu->tram_addr_saved[i]);
+ else {
+ snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
+ emu->tram_addr_saved[i] << 12);
+ snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
+ emu->tram_addr_saved[i] >> 20);
+ }
+ }
+
+ len = emu->audigy ? 2 * 1024 : 2 * 512;
+ for (i = 0; i < len; i++)
+ snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]);
+
+ /* start FX processor when the DSP code is updated */
+ if (emu->audigy)
+ snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
+ else
+ snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
+}
+#endif
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 7cc831ccd0cb..2e86a901a0a4 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -35,17 +35,17 @@
#define AC97_ID_STAC9758 0x83847658
-static int snd_emu10k1_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_emu10k1_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned long flags;
@@ -58,8 +58,8 @@ static int snd_emu10k1_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -69,7 +69,7 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
}
#if 0
-static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"44100", "48000", "96000"};
@@ -82,10 +82,10 @@ static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int tmp;
unsigned long flags;
@@ -109,10 +109,10 @@ static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int change;
unsigned int reg, val, tmp;
unsigned long flags;
@@ -143,7 +143,7 @@ static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
+static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -155,10 +155,10 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
};
#endif
-static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
int change;
unsigned int val;
@@ -178,7 +178,7 @@ static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control =
+static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -188,7 +188,7 @@ static snd_kcontrol_new_t snd_emu10k1_spdif_mask_control =
.get = snd_emu10k1_spdif_get_mask
};
-static snd_kcontrol_new_t snd_emu10k1_spdif_control =
+static struct snd_kcontrol_new snd_emu10k1_spdif_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -199,7 +199,7 @@ static snd_kcontrol_new_t snd_emu10k1_spdif_control =
};
-static void update_emu10k1_fxrt(emu10k1_t *emu, int voice, unsigned char *route)
+static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
{
if (emu->audigy) {
snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
@@ -212,7 +212,7 @@ static void update_emu10k1_fxrt(emu10k1_t *emu, int voice, unsigned char *route)
}
}
-static void update_emu10k1_send_volume(emu10k1_t *emu, int voice, unsigned char *volume)
+static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
{
snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
@@ -229,9 +229,9 @@ static void update_emu10k1_send_volume(emu10k1_t *emu, int voice, unsigned char
/* PCM stream controls */
-static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = emu->audigy ? 3*8 : 3*4;
uinfo->value.integer.min = 0;
@@ -239,12 +239,13 @@ static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_emu10k1_send_routing_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int voice, idx;
int num_efx = emu->audigy ? 8 : 4;
int mask = emu->audigy ? 0x3f : 0x0f;
@@ -258,12 +259,13 @@ static int snd_emu10k1_send_routing_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int change = 0, voice, idx, val;
int num_efx = emu->audigy ? 8 : 4;
int mask = emu->audigy ? 0x3f : 0x0f;
@@ -292,7 +294,7 @@ static int snd_emu10k1_send_routing_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_send_routing_control =
+static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -303,9 +305,9 @@ static snd_kcontrol_new_t snd_emu10k1_send_routing_control =
.put = snd_emu10k1_send_routing_put
};
-static int snd_emu10k1_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = emu->audigy ? 3*8 : 3*4;
uinfo->value.integer.min = 0;
@@ -313,12 +315,13 @@ static int snd_emu10k1_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_emu10k1_send_volume_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int idx;
int num_efx = emu->audigy ? 8 : 4;
@@ -329,12 +332,13 @@ static int snd_emu10k1_send_volume_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int change = 0, idx, val;
int num_efx = emu->audigy ? 8 : 4;
@@ -361,7 +365,7 @@ static int snd_emu10k1_send_volume_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_send_volume_control =
+static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -372,7 +376,7 @@ static snd_kcontrol_new_t snd_emu10k1_send_volume_control =
.put = snd_emu10k1_send_volume_put
};
-static int snd_emu10k1_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 3;
@@ -381,11 +385,12 @@ static int snd_emu10k1_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_emu10k1_attn_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
unsigned long flags;
int idx;
@@ -396,12 +401,13 @@ static int snd_emu10k1_attn_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int change = 0, idx, val;
spin_lock_irqsave(&emu->reg_lock, flags);
@@ -424,7 +430,7 @@ static int snd_emu10k1_attn_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_attn_control =
+static struct snd_kcontrol_new snd_emu10k1_attn_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -437,9 +443,9 @@ static snd_kcontrol_new_t snd_emu10k1_attn_control =
/* Mutichannel PCM stream controls */
-static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = emu->audigy ? 8 : 4;
uinfo->value.integer.min = 0;
@@ -447,12 +453,13 @@ static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int idx;
int num_efx = emu->audigy ? 8 : 4;
int mask = emu->audigy ? 0x3f : 0x0f;
@@ -465,13 +472,13 @@ static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
int change = 0, idx, val;
int num_efx = emu->audigy ? 8 : 4;
int mask = emu->audigy ? 0x3f : 0x0f;
@@ -495,7 +502,7 @@ static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control =
+static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -506,9 +513,9 @@ static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control =
.put = snd_emu10k1_efx_send_routing_put
};
-static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = emu->audigy ? 8 : 4;
uinfo->value.integer.min = 0;
@@ -516,12 +523,13 @@ static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
int idx;
int num_efx = emu->audigy ? 8 : 4;
@@ -532,13 +540,13 @@ static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
int change = 0, idx, val;
int num_efx = emu->audigy ? 8 : 4;
@@ -561,7 +569,7 @@ static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
}
-static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control =
+static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -572,7 +580,7 @@ static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control =
.put = snd_emu10k1_efx_send_volume_put
};
-static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -581,11 +589,12 @@ static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1_pcm_mixer *mix =
+ &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
unsigned long flags;
spin_lock_irqsave(&emu->reg_lock, flags);
@@ -594,13 +603,13 @@ static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+ struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
int change = 0, val;
spin_lock_irqsave(&emu->reg_lock, flags);
@@ -618,7 +627,7 @@ static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_efx_attn_control =
+static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -629,7 +638,7 @@ static snd_kcontrol_new_t snd_emu10k1_efx_attn_control =
.put = snd_emu10k1_efx_attn_put
};
-static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -638,10 +647,10 @@ static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_emu10k1_shared_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
if (emu->audigy)
ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
@@ -650,11 +659,11 @@ static int snd_emu10k1_shared_spdif_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_emu10k1_shared_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
unsigned long flags;
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int reg, val;
int change = 0;
@@ -681,7 +690,7 @@ static int snd_emu10k1_shared_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SB Live Analog/Digital Output Jack",
@@ -690,7 +699,7 @@ static snd_kcontrol_new_t snd_emu10k1_shared_spdif __devinitdata =
.put = snd_emu10k1_shared_spdif_put
};
-static snd_kcontrol_new_t snd_audigy_shared_spdif __devinitdata =
+static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Audigy Analog/Digital Output Jack",
@@ -701,35 +710,35 @@ static snd_kcontrol_new_t snd_audigy_shared_spdif __devinitdata =
/*
*/
-static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
+static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
{
- emu10k1_t *emu = ac97->private_data;
+ struct snd_emu10k1 *emu = ac97->private_data;
emu->ac97 = NULL;
}
/*
*/
-static int remove_ctl(snd_card_t *card, const char *name)
+static int remove_ctl(struct snd_card *card, const char *name)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
strcpy(id.name, name);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_remove_id(card, &id);
}
-static snd_kcontrol_t *ctl_find(snd_card_t *card, const char *name)
+static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
{
- snd_ctl_elem_id_t sid;
+ struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
strcpy(sid.name, name);
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
return snd_ctl_find_id(card, &sid);
}
-static int rename_ctl(snd_card_t *card, const char *src, const char *dst)
+static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
{
- snd_kcontrol_t *kctl = ctl_find(card, src);
+ struct snd_kcontrol *kctl = ctl_find(card, src);
if (kctl) {
strcpy(kctl->id.name, dst);
return 0;
@@ -737,12 +746,12 @@ 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(struct snd_emu10k1 *emu,
int pcm_device, int multi_device)
{
int err, pcm;
- snd_kcontrol_t *kctl;
- snd_card_t *card = emu->card;
+ struct snd_kcontrol *kctl;
+ struct snd_card *card = emu->card;
char **c;
static char *emu10k1_remove_ctls[] = {
/* no AC97 mono, surround, center/lfe */
@@ -795,9 +804,9 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
};
if (emu->card_capabilities->ac97_chip) {
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- static ac97_bus_ops_t ops = {
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ static struct snd_ac97_bus_ops ops = {
.write = snd_emu10k1_ac97_write,
.read = snd_emu10k1_ac97_read,
};
@@ -857,7 +866,17 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
c = emu10k1_rename_ctls;
for (; *c; c += 2)
rename_ctl(card, c[0], c[1]);
-
+ if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
+ rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
+ rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
+ rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
+ rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
+ remove_ctl(card, "Headphone Playback Switch");
+ remove_ctl(card, "Headphone Playback Volume");
+ remove_ctl(card, "3D Control - Center");
+ remove_ctl(card, "3D Control - Depth");
+ remove_ctl(card, "3D Control - Switch");
+ }
if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
return -ENOMEM;
kctl->id.device = pcm_device;
@@ -894,7 +913,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
/* initialize the routing and volume table for each pcm playback stream */
for (pcm = 0; pcm < 32; pcm++) {
- emu10k1_pcm_mixer_t *mix;
+ struct snd_emu10k1_pcm_mixer *mix;
int v;
mix = &emu->pcm_mixer[pcm];
@@ -914,7 +933,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
/* initialize the routing and volume table for the multichannel playback stream */
for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
- emu10k1_pcm_mixer_t *mix;
+ struct snd_emu10k1_pcm_mixer *mix;
int v;
mix = &emu->efx_pcm_mixer[pcm];
@@ -950,7 +969,9 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu,
return err;
}
- if (emu->audigy) {
+ if ( emu->card_capabilities->emu1212m) {
+ ; /* Disable the snd_audigy_spdif_shared_spdif */
+ } else if (emu->audigy) {
if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index eb57458a9665..d96eb455103f 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -28,7 +28,8 @@
#define EMU10K1_MIDI_MODE_INPUT (1<<0)
#define EMU10K1_MIDI_MODE_OUTPUT (1<<1)
-static inline unsigned char mpu401_read(emu10k1_t *emu, emu10k1_midi_t *mpu, int idx)
+static inline unsigned char mpu401_read(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_midi *mpu, int idx)
{
if (emu->audigy)
return (unsigned char)snd_emu10k1_ptr_read(emu, mpu->port + idx, 0);
@@ -36,7 +37,8 @@ static inline unsigned char mpu401_read(emu10k1_t *emu, emu10k1_midi_t *mpu, int
return inb(emu->port + mpu->port + idx);
}
-static inline void mpu401_write(emu10k1_t *emu, emu10k1_midi_t *mpu, int data, int idx)
+static inline void mpu401_write(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_midi *mpu, int data, int idx)
{
if (emu->audigy)
snd_emu10k1_ptr_write(emu, mpu->port + idx, 0, data);
@@ -56,7 +58,7 @@ static inline void mpu401_write(emu10k1_t *emu, emu10k1_midi_t *mpu, int data, i
#define MPU401_ENTER_UART 0x3f
#define MPU401_ACK 0xfe
-static void mpu401_clear_rx(emu10k1_t *emu, emu10k1_midi_t *mpu)
+static void mpu401_clear_rx(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *mpu)
{
int timeout = 100000;
for (; timeout > 0 && mpu401_input_avail(emu, mpu); timeout--)
@@ -71,7 +73,7 @@ static void mpu401_clear_rx(emu10k1_t *emu, emu10k1_midi_t *mpu)
*/
-static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsigned int status)
+static void do_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, unsigned int status)
{
unsigned char byte;
@@ -104,17 +106,17 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
spin_unlock(&midi->output_lock);
}
-static void snd_emu10k1_midi_interrupt(emu10k1_t *emu, unsigned int status)
+static void snd_emu10k1_midi_interrupt(struct snd_emu10k1 *emu, unsigned int status)
{
do_emu10k1_midi_interrupt(emu, &emu->midi, status);
}
-static void snd_emu10k1_midi_interrupt2(emu10k1_t *emu, unsigned int status)
+static void snd_emu10k1_midi_interrupt2(struct snd_emu10k1 *emu, unsigned int status)
{
do_emu10k1_midi_interrupt(emu, &emu->midi2, status);
}
-static void snd_emu10k1_midi_cmd(emu10k1_t * emu, emu10k1_midi_t *midi, unsigned char cmd, int ack)
+static void snd_emu10k1_midi_cmd(struct snd_emu10k1 * emu, struct snd_emu10k1_midi *midi, unsigned char cmd, int ack)
{
unsigned long flags;
int timeout, ok;
@@ -146,10 +148,10 @@ static void snd_emu10k1_midi_cmd(emu10k1_t * emu, emu10k1_midi_t *midi, unsigned
mpu401_read_data(emu, midi));
}
-static int snd_emu10k1_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1_midi_input_open(struct snd_rawmidi_substream *substream)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -167,10 +169,10 @@ static int snd_emu10k1_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1_midi_output_open(struct snd_rawmidi_substream *substream)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -188,10 +190,10 @@ static int snd_emu10k1_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1_midi_input_close(struct snd_rawmidi_substream *substream)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -209,10 +211,10 @@ static int snd_emu10k1_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_emu10k1_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_emu10k1_midi_output_close(struct snd_rawmidi_substream *substream)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -230,10 +232,10 @@ static int snd_emu10k1_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_emu10k1_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_emu10k1_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
emu = midi->emu;
snd_assert(emu, return);
@@ -243,10 +245,10 @@ static void snd_emu10k1_midi_input_trigger(snd_rawmidi_substream_t * substream,
snd_emu10k1_intr_disable(emu, midi->rx_enable);
}
-static void snd_emu10k1_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_emu10k1_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- emu10k1_t *emu;
- emu10k1_midi_t *midi = (emu10k1_midi_t *)substream->rmidi->private_data;
+ struct snd_emu10k1 *emu;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)substream->rmidi->private_data;
unsigned long flags;
emu = midi->emu;
@@ -283,30 +285,30 @@ static void snd_emu10k1_midi_output_trigger(snd_rawmidi_substream_t * substream,
*/
-static snd_rawmidi_ops_t snd_emu10k1_midi_output =
+static struct snd_rawmidi_ops snd_emu10k1_midi_output =
{
.open = snd_emu10k1_midi_output_open,
.close = snd_emu10k1_midi_output_close,
.trigger = snd_emu10k1_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_emu10k1_midi_input =
+static struct snd_rawmidi_ops snd_emu10k1_midi_input =
{
.open = snd_emu10k1_midi_input_open,
.close = snd_emu10k1_midi_input_close,
.trigger = snd_emu10k1_midi_input_trigger,
};
-static void snd_emu10k1_midi_free(snd_rawmidi_t *rmidi)
+static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
{
- emu10k1_midi_t *midi = (emu10k1_midi_t *)rmidi->private_data;
+ struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)rmidi->private_data;
midi->interrupt = NULL;
midi->rmidi = NULL;
}
-static int __devinit emu10k1_midi_init(emu10k1_t *emu, emu10k1_midi_t *midi, int device, char *name)
+static int __devinit emu10k1_midi_init(struct snd_emu10k1 *emu, struct snd_emu10k1_midi *midi, int device, char *name)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if ((err = snd_rawmidi_new(emu->card, name, device, 1, 1, &rmidi)) < 0)
@@ -327,9 +329,9 @@ static int __devinit emu10k1_midi_init(emu10k1_t *emu, emu10k1_midi_t *midi, int
return 0;
}
-int __devinit snd_emu10k1_midi(emu10k1_t *emu)
+int __devinit snd_emu10k1_midi(struct snd_emu10k1 *emu)
{
- emu10k1_midi_t *midi = &emu->midi;
+ struct snd_emu10k1_midi *midi = &emu->midi;
int err;
if ((err = emu10k1_midi_init(emu, midi, 0, "EMU10K1 MPU-401 (UART)")) < 0)
@@ -344,9 +346,9 @@ int __devinit snd_emu10k1_midi(emu10k1_t *emu)
return 0;
}
-int __devinit snd_emu10k1_audigy_midi(emu10k1_t *emu)
+int __devinit snd_emu10k1_audigy_midi(struct snd_emu10k1 *emu)
{
- emu10k1_midi_t *midi;
+ struct snd_emu10k1_midi *midi;
int err;
midi = &emu->midi;
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index bf7490dae09b..717e92ec9e0a 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -35,9 +35,10 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
-static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
+static void snd_emu10k1_pcm_interrupt(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_voice *voice)
{
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1_pcm *epcm;
if ((epcm = voice->epcm) == NULL)
return;
@@ -52,7 +53,8 @@ static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
snd_pcm_period_elapsed(epcm->substream);
}
-static void snd_emu10k1_pcm_ac97adc_interrupt(emu10k1_t *emu, unsigned int status)
+static void snd_emu10k1_pcm_ac97adc_interrupt(struct snd_emu10k1 *emu,
+ unsigned int status)
{
#if 0
if (status & IPR_ADCBUFHALFFULL) {
@@ -63,7 +65,8 @@ static void snd_emu10k1_pcm_ac97adc_interrupt(emu10k1_t *emu, unsigned int statu
snd_pcm_period_elapsed(emu->pcm_capture_substream);
}
-static void snd_emu10k1_pcm_ac97mic_interrupt(emu10k1_t *emu, unsigned int status)
+static void snd_emu10k1_pcm_ac97mic_interrupt(struct snd_emu10k1 *emu,
+ unsigned int status)
{
#if 0
if (status & IPR_MICBUFHALFFULL) {
@@ -74,7 +77,8 @@ static void snd_emu10k1_pcm_ac97mic_interrupt(emu10k1_t *emu, unsigned int statu
snd_pcm_period_elapsed(emu->pcm_capture_mic_substream);
}
-static void snd_emu10k1_pcm_efx_interrupt(emu10k1_t *emu, unsigned int status)
+static void snd_emu10k1_pcm_efx_interrupt(struct snd_emu10k1 *emu,
+ unsigned int status)
{
#if 0
if (status & IPR_EFXBUFHALFFULL) {
@@ -85,11 +89,11 @@ static void snd_emu10k1_pcm_efx_interrupt(emu10k1_t *emu, unsigned int status)
snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
}
-static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
unsigned int ptr;
if (!epcm->running)
@@ -102,7 +106,7 @@ static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t *
return ptr;
}
-static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
+static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voices)
{
int err, i;
@@ -167,7 +171,7 @@ static unsigned int capture_period_sizes[31] = {
384*128,448*128,512*128
};
-static snd_pcm_hw_constraint_list_t hw_constraints_capture_period_sizes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = {
.count = 31,
.list = capture_period_sizes,
.mask = 0
@@ -177,7 +181,7 @@ static unsigned int capture_rates[8] = {
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraints_capture_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = {
.count = 8,
.list = capture_rates,
.mask = 0
@@ -271,15 +275,15 @@ static inline int emu10k1_ccis(int stereo, int w_16)
}
}
-static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
+static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
int master, int extra,
- emu10k1_voice_t *evoice,
+ struct snd_emu10k1_voice *evoice,
unsigned int start_addr,
unsigned int end_addr,
- emu10k1_pcm_mixer_t *mix)
+ struct snd_emu10k1_pcm_mixer *mix)
{
- snd_pcm_substream_t *substream = evoice->epcm->substream;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_substream *substream = evoice->epcm->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int silent_page, tmp;
int voice, stereo, w_16;
unsigned char attn, send_amount[8];
@@ -392,12 +396,12 @@ static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
spin_unlock_irqrestore(&emu->reg_lock, flags);
}
-static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_emu10k1_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
int err;
if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
@@ -405,24 +409,26 @@ static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
return err;
if (err > 0) { /* change */
- snd_util_memblk_t *memblk;
+ int mapped;
if (epcm->memblk != NULL)
snd_emu10k1_free_pages(emu, epcm->memblk);
- memblk = snd_emu10k1_alloc_pages(emu, substream);
- if ((epcm->memblk = memblk) == NULL || ((emu10k1_memblk_t *)memblk)->mapped_page < 0) {
- epcm->start_addr = 0;
+ epcm->memblk = snd_emu10k1_alloc_pages(emu, substream);
+ epcm->start_addr = 0;
+ if (! epcm->memblk)
return -ENOMEM;
- }
- epcm->start_addr = ((emu10k1_memblk_t *)memblk)->mapped_page << PAGE_SHIFT;
+ mapped = ((struct snd_emu10k1_memblk *)epcm->memblk)->mapped_page;
+ if (mapped < 0)
+ return -ENOMEM;
+ epcm->start_addr = mapped << PAGE_SHIFT;
}
return 0;
}
-static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_emu10k1_playback_hw_free(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm;
if (runtime->private_data == NULL)
return 0;
@@ -448,11 +454,11 @@ static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_efx_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm;
int i;
if (runtime->private_data == NULL)
@@ -477,11 +483,11 @@ static int snd_emu10k1_efx_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_emu10k1_playback_prepare(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
unsigned int start_addr, end_addr;
start_addr = epcm->start_addr;
@@ -505,11 +511,11 @@ static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_emu10k1_efx_playback_prepare(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
unsigned int start_addr, end_addr;
unsigned int channel_size;
int i;
@@ -541,10 +547,11 @@ static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_hardware_t snd_emu10k1_efx_playback =
+static struct snd_pcm_hardware snd_emu10k1_efx_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
@@ -560,22 +567,22 @@ static snd_pcm_hardware_t snd_emu10k1_efx_playback =
.fifo_size = 0,
};
-static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_emu10k1_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_emu10k1_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
int idx;
/* zeroing the buffer size will stop capture */
@@ -618,9 +625,9 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu10k1_voice_t *evoice)
+static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int extra, struct snd_emu10k1_voice *evoice)
{
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_runtime *runtime;
unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
if (evoice == NULL)
@@ -653,12 +660,12 @@ static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu
}
}
-static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice,
+static void snd_emu10k1_playback_prepare_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice,
int master, int extra,
- emu10k1_pcm_mixer_t *mix)
+ struct snd_emu10k1_pcm_mixer *mix)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
unsigned int attn, vattn;
unsigned int voice, tmp;
@@ -678,10 +685,10 @@ static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *
snd_emu10k1_voice_clear_loop_stop(emu, voice);
}
-static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
+static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice, int master, int extra)
{
- snd_pcm_substream_t *substream;
- snd_pcm_runtime_t *runtime;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
unsigned int voice, pitch, pitch_target;
if (evoice == NULL) /* skip second voice for mono */
@@ -700,7 +707,7 @@ static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *
snd_emu10k1_voice_intr_enable(emu, voice);
}
-static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice)
+static void snd_emu10k1_playback_stop_voice(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *evoice)
{
unsigned int voice;
@@ -716,13 +723,13 @@ static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evo
snd_emu10k1_ptr_write(emu, IP, voice, 0);
}
-static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
- emu10k1_pcm_mixer_t *mix;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
+ struct snd_emu10k1_pcm_mixer *mix;
int result = 0;
// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
@@ -733,6 +740,7 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]);
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
mix = &emu->pcm_mixer[substream->number];
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0, mix);
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0, mix);
@@ -744,6 +752,7 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
epcm->running = 0;
snd_emu10k1_playback_stop_voice(emu, epcm->voices[0]);
snd_emu10k1_playback_stop_voice(emu, epcm->voices[1]);
@@ -757,17 +766,18 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
int result = 0;
spin_lock(&emu->reg_lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
// hmm this should cause full and half full interrupt to be raised?
outl(epcm->capture_ipr, emu->port + IPR);
snd_emu10k1_intr_enable(emu, epcm->capture_inte);
@@ -791,6 +801,7 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
epcm->first_ptr = 1;
break;
case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
epcm->running = 0;
snd_emu10k1_intr_disable(emu, epcm->capture_inte);
outl(epcm->capture_ipr, emu->port + IPR);
@@ -817,11 +828,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
return result;
}
-static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
unsigned int ptr;
if (!epcm->running)
@@ -845,12 +856,12 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * subs
}
-static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
int i;
int result = 0;
@@ -865,6 +876,7 @@ static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1, NULL);
snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0,
&emu->efx_pcm_mixer[0]);
@@ -877,6 +889,7 @@ static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0);
epcm->running = 1;
break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
epcm->running = 0;
@@ -894,11 +907,11 @@ static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
}
-static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
unsigned int ptr;
if (!epcm->running)
@@ -915,10 +928,11 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * subst
* Playback support device description
*/
-static snd_pcm_hardware_t snd_emu10k1_playback =
+static struct snd_pcm_hardware snd_emu10k1_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000,
@@ -938,10 +952,11 @@ static snd_pcm_hardware_t snd_emu10k1_playback =
* Capture support device description
*/
-static snd_pcm_hardware_t snd_emu10k1_capture =
+static struct snd_pcm_hardware snd_emu10k1_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
@@ -961,9 +976,9 @@ static snd_pcm_hardware_t snd_emu10k1_capture =
*
*/
-static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl, int idx, int activate)
+static void snd_emu10k1_pcm_mixer_notify1(struct snd_emu10k1 *emu, struct snd_kcontrol *kctl, int idx, int activate)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
if (! kctl)
return;
@@ -976,29 +991,29 @@ static void snd_emu10k1_pcm_mixer_notify1(emu10k1_t *emu, snd_kcontrol_t *kctl,
snd_ctl_build_ioff(&id, kctl, idx));
}
-static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate)
+static void snd_emu10k1_pcm_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate)
{
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_routing, idx, activate);
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_send_volume, idx, activate);
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);
}
-static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activate)
+static void snd_emu10k1_pcm_efx_mixer_notify(struct snd_emu10k1 *emu, int idx, int activate)
{
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate);
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate);
snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);
}
-static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_emu10k1_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
-static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_mixer_t *mix;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm_mixer *mix;
int i;
for (i=0; i < NUM_EFX_PLAYBACK; i++) {
@@ -1009,12 +1024,12 @@ static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_t *epcm;
- emu10k1_pcm_mixer_t *mix;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_emu10k1_pcm_mixer *mix;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int i;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -1042,12 +1057,12 @@ static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_t *epcm;
- emu10k1_pcm_mixer_t *mix;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_emu10k1_pcm_mixer *mix;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int i, err;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -1079,21 +1094,21 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_playback_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm_mixer *mix = &emu->pcm_mixer[substream->number];
mix->epcm = NULL;
snd_emu10k1_pcm_mixer_notify(emu, substream->number, 0);
return 0;
}
-static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
@@ -1116,20 +1131,20 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_capture_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
emu->capture_interrupt = NULL;
emu->pcm_capture_substream = NULL;
return 0;
}
-static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_mic_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
if (epcm == NULL)
@@ -1154,20 +1169,20 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_capture_mic_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_mic_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
emu->capture_interrupt = NULL;
emu->pcm_capture_mic_substream = NULL;
return 0;
}
-static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int nefx = emu->audigy ? 64 : 32;
int idx;
@@ -1204,16 +1219,16 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_capture_efx_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
emu->capture_interrupt = NULL;
emu->pcm_capture_efx_substream = NULL;
return 0;
}
-static snd_pcm_ops_t snd_emu10k1_playback_ops = {
+static struct snd_pcm_ops snd_emu10k1_playback_ops = {
.open = snd_emu10k1_playback_open,
.close = snd_emu10k1_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1225,7 +1240,7 @@ static snd_pcm_ops_t snd_emu10k1_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static snd_pcm_ops_t snd_emu10k1_capture_ops = {
+static struct snd_pcm_ops snd_emu10k1_capture_ops = {
.open = snd_emu10k1_capture_open,
.close = snd_emu10k1_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1237,7 +1252,7 @@ static snd_pcm_ops_t snd_emu10k1_capture_ops = {
};
/* EFX playback */
-static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = {
+static struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
.open = snd_emu10k1_efx_playback_open,
.close = snd_emu10k1_efx_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1249,17 +1264,10 @@ static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
+int __devinit snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
{
- emu10k1_t *emu = pcm->private_data;
- emu->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
int err;
if (rpcm)
@@ -1269,7 +1277,6 @@ int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
return err;
pcm->private_data = emu;
- pcm->private_free = snd_emu10k1_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_ops);
@@ -1292,10 +1299,10 @@ int __devinit snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
return 0;
}
-int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
+int __devinit snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
int err;
if (rpcm)
@@ -1305,14 +1312,13 @@ int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rp
return err;
pcm->private_data = emu;
- pcm->private_free = snd_emu10k1_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops);
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
strcpy(pcm->name, "Multichannel Playback");
- emu->pcm = pcm;
+ emu->pcm_multi = pcm;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
@@ -1325,7 +1331,7 @@ int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rp
}
-static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
+static struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
.open = snd_emu10k1_capture_mic_open,
.close = snd_emu10k1_capture_mic_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1336,16 +1342,9 @@ static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
.pointer = snd_emu10k1_capture_pointer,
};
-static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
+int __devinit snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
{
- emu10k1_t *emu = pcm->private_data;
- emu->pcm_mic = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1355,7 +1354,6 @@ int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
return err;
pcm->private_data = emu;
- pcm->private_free = snd_emu10k1_pcm_mic_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_mic_ops);
@@ -1370,9 +1368,9 @@ int __devinit snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
return 0;
}
-static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_emu10k1_pcm_efx_voices_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int nefx = emu->audigy ? 64 : 32;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = nefx;
@@ -1381,9 +1379,9 @@ static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ct
return 0;
}
-static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_pcm_efx_voices_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
int nefx = emu->audigy ? 64 : 32;
int idx;
@@ -1394,9 +1392,9 @@ static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ct
return 0;
}
-static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_emu10k1_pcm_efx_voices_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int nval[2], bits;
int nefx = emu->audigy ? 64 : 32;
int nefxb = emu->audigy ? 7 : 6;
@@ -1425,7 +1423,7 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ct
return change;
}
-static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
+static struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "Captured FX8010 Outputs",
.info = snd_emu10k1_pcm_efx_voices_mask_info,
@@ -1433,7 +1431,7 @@ static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
.put = snd_emu10k1_pcm_efx_voices_mask_put
};
-static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
+static struct snd_pcm_ops snd_emu10k1_capture_efx_ops = {
.open = snd_emu10k1_capture_efx_open,
.close = snd_emu10k1_capture_efx_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1450,9 +1448,9 @@ static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
#define INITIAL_TRAM_SHIFT 14
#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
-static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+static void snd_emu10k1_fx8010_playback_irq(struct snd_emu10k1 *emu, void *private_data)
{
- snd_pcm_substream_t *substream = private_data;
+ struct snd_pcm_substream *substream = private_data;
snd_pcm_period_elapsed(substream);
}
@@ -1476,11 +1474,11 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
}
}
-static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes)
+static void fx8010_pb_trans_copy(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
unsigned int tram_size = pcm->buffer_size;
unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
unsigned int frames = bytes >> 2, count;
@@ -1505,25 +1503,25 @@ static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
pcm->tram_shift = tram_shift;
}
-static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
return 0;
}
-static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
unsigned int i;
for (i = 0; i < pcm->channels; i++)
@@ -1532,11 +1530,11 @@ static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
unsigned int i;
// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
@@ -1556,10 +1554,10 @@ static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
int result = 0;
spin_lock(&emu->reg_lock);
@@ -1567,6 +1565,7 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
case SNDRV_PCM_TRIGGER_START:
/* follow thru */
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
#ifdef EMU10K1_SET_AC3_IEC958
{
int i;
@@ -1587,6 +1586,7 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
@@ -1601,10 +1601,10 @@ static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream,
return result;
}
-static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
size_t ptr; /* byte pointer */
if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
@@ -1613,9 +1613,10 @@ static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t
return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
}
-static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+static struct snd_pcm_hardware snd_emu10k1_fx8010_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_RESUME |
/* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_48000,
@@ -1631,11 +1632,11 @@ static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
.fifo_size = 0,
};
-static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+static int snd_emu10k1_fx8010_playback_open(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
runtime->hw = snd_emu10k1_fx8010_playback;
runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
@@ -1650,10 +1651,10 @@ static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
spin_lock_irq(&emu->reg_lock);
pcm->opened = 0;
@@ -1661,7 +1662,7 @@ static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+static struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
.open = snd_emu10k1_fx8010_playback_open,
.close = snd_emu10k1_fx8010_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1673,17 +1674,10 @@ static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
.ack = snd_emu10k1_fx8010_playback_transfer,
};
-static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
-{
- emu10k1_t *emu = pcm->private_data;
- emu->pcm_efx = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
+int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
- snd_kcontrol_t *kctl;
+ struct snd_pcm *pcm;
+ struct snd_kcontrol *kctl;
int err;
if (rpcm)
@@ -1693,7 +1687,6 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
return err;
pcm->private_data = emu;
- pcm->private_free = snd_emu10k1_pcm_efx_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index cc22707c91fa..90f1c52703a1 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -32,8 +32,9 @@
#include <sound/emu10k1.h>
#include "p16v.h"
-static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
- snd_info_buffer_t * buffer,
+#ifdef CONFIG_PROC_FS
+static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu,
+ struct snd_info_buffer *buffer,
char *title,
int status_reg,
int rate_reg)
@@ -75,8 +76,8 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
}
-static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
/* FIXME - output names are in emufx.c too */
static char *creative_outs[32] = {
@@ -181,7 +182,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
/* 63 */ "FXBUS2_31"
};
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned int val, val1;
int nefx = emu->audigy ? 64 : 32;
char **outputs = emu->audigy ? audigy_outs : creative_outs;
@@ -232,10 +233,10 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]);
}
-static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
#if 0
@@ -246,11 +247,11 @@ static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry,
#endif
}
-static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned int val, tmp, n;
val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
tmp = (val >> 16) & 0x8;
@@ -261,11 +262,11 @@ static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry,
}
}
-static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
u32 pc;
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name);
snd_iprintf(buffer, " Code dump :\n");
@@ -304,12 +305,13 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
#define TOTAL_SIZE_CODE (0x200*8)
#define A_TOTAL_SIZE_CODE (0x400*8)
-static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
+ void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
long size;
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned int offset;
int tram_addr = 0;
@@ -349,11 +351,11 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_
return 0;
}
-static void snd_emu10k1_proc_voices_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1_t *emu = entry->private_data;
- emu10k1_voice_t *voice;
+ struct snd_emu10k1 *emu = entry->private_data;
+ struct snd_emu10k1_voice *voice;
int idx;
snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n");
@@ -370,10 +372,10 @@ static void snd_emu10k1_proc_voices_read(snd_info_entry_t *entry,
}
#ifdef CONFIG_SND_DEBUG
-static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned long value;
unsigned long flags;
int i;
@@ -386,10 +388,10 @@ static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry,
}
}
-static void snd_emu_proc_io_reg_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned long flags;
char line[64];
u32 reg, val;
@@ -404,7 +406,7 @@ static void snd_emu_proc_io_reg_write(snd_info_entry_t *entry,
}
}
-static unsigned int snd_ptr_read(emu10k1_t * emu,
+static unsigned int snd_ptr_read(struct snd_emu10k1 * emu,
unsigned int iobase,
unsigned int reg,
unsigned int chn)
@@ -421,7 +423,7 @@ static unsigned int snd_ptr_read(emu10k1_t * emu,
return val;
}
-static void snd_ptr_write(emu10k1_t *emu,
+static void snd_ptr_write(struct snd_emu10k1 *emu,
unsigned int iobase,
unsigned int reg,
unsigned int chn,
@@ -439,13 +441,13 @@ static void snd_ptr_write(emu10k1_t *emu,
}
-static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer, int iobase, int offset, int length, int voices)
+static void snd_emu_proc_ptr_reg_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer, int iobase, int offset, int length, int voices)
{
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
unsigned long value;
int i,j;
- if (offset+length > 0x80) {
+ if (offset+length > 0xa0) {
snd_iprintf(buffer, "Input values out of range\n");
return;
}
@@ -463,65 +465,71 @@ static void snd_emu_proc_ptr_reg_read(snd_info_entry_t *entry,
}
}
-static void snd_emu_proc_ptr_reg_write(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer, int iobase)
+static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer, int iobase)
{
- emu10k1_t *emu = entry->private_data;
+ struct snd_emu10k1 *emu = entry->private_data;
char line[64];
unsigned int reg, channel_id , val;
while (!snd_info_get_line(buffer, line, sizeof(line))) {
if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
continue;
- if ((reg < 0x80) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
+ if ((reg < 0xa0) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
snd_ptr_write(emu, iobase, reg, channel_id, val);
}
}
-static void snd_emu_proc_ptr_reg_write00(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_write00(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_write(entry, buffer, 0);
}
-static void snd_emu_proc_ptr_reg_write20(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_write20(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_write(entry, buffer, 0x20);
}
-static void snd_emu_proc_ptr_reg_read00a(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_read00a(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0, 0x40, 64);
}
-static void snd_emu_proc_ptr_reg_read00b(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_read00b(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_read(entry, buffer, 0, 0x40, 0x40, 64);
}
-static void snd_emu_proc_ptr_reg_read20a(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_read20a(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0, 0x40, 4);
}
-static void snd_emu_proc_ptr_reg_read20b(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_emu_proc_ptr_reg_read20b(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x40, 0x40, 4);
}
+
+static void snd_emu_proc_ptr_reg_read20c(struct snd_info_entry *entry,
+ struct snd_info_buffer * buffer)
+{
+ snd_emu_proc_ptr_reg_read(entry, buffer, 0x20, 0x80, 0x20, 4);
+}
#endif
static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
.read = snd_emu10k1_fx8010_read,
};
-int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
+int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
#ifdef CONFIG_SND_DEBUG
if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
@@ -553,6 +561,12 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
entry->mode |= S_IWUSR;
}
+ if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) {
+ snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20c);
+ entry->c.text.write_size = 64;
+ entry->c.text.write = snd_emu_proc_ptr_reg_write20;
+ entry->mode |= S_IWUSR;
+ }
#endif
if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
@@ -607,3 +621,4 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
}
return 0;
}
+#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index b9d3ae0dcab7..ef5304df8c11 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -29,8 +29,9 @@
#include <linux/time.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
+#include <linux/delay.h>
-unsigned int snd_emu10k1_ptr_read(emu10k1_t * emu, unsigned int reg, unsigned int chn)
+unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
{
unsigned long flags;
unsigned int regptr, val;
@@ -61,7 +62,7 @@ unsigned int snd_emu10k1_ptr_read(emu10k1_t * emu, unsigned int reg, unsigned in
}
}
-void snd_emu10k1_ptr_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, unsigned int data)
+void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
{
unsigned int regptr;
unsigned long flags;
@@ -91,7 +92,7 @@ void snd_emu10k1_ptr_write(emu10k1_t *emu, unsigned int reg, unsigned int chn, u
}
}
-unsigned int snd_emu10k1_ptr20_read(emu10k1_t * emu,
+unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu,
unsigned int reg,
unsigned int chn)
{
@@ -107,7 +108,7 @@ unsigned int snd_emu10k1_ptr20_read(emu10k1_t * emu,
return val;
}
-void snd_emu10k1_ptr20_write(emu10k1_t *emu,
+void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu,
unsigned int reg,
unsigned int chn,
unsigned int data)
@@ -123,7 +124,46 @@ void snd_emu10k1_ptr20_write(emu10k1_t *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb)
+int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
+ unsigned int data)
+{
+ unsigned int reset, set;
+ unsigned int reg, tmp;
+ int n, result;
+ if (emu->card_capabilities->ca0108_chip)
+ reg = 0x3c; /* PTR20, reg 0x3c */
+ else {
+ /* For other chip types the SPI register
+ * is currently unknown. */
+ return 1;
+ }
+ if (data > 0xffff) /* Only 16bit values allowed */
+ return 1;
+
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
+ reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
+ set = reset | 0x10000; /* Set xxx1xxxx */
+ snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
+ snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
+ result = 1;
+ /* Wait for status bit to return to 0 */
+ for (n = 0; n < 100; n++) {
+ udelay(10);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
+ if (!(tmp & 0x10000)) {
+ result = 0;
+ break;
+ }
+ }
+ if (result) /* Timed out */
+ return 1;
+ snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
+ tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
+ return 0;
+}
+
+void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -134,7 +174,7 @@ void snd_emu10k1_intr_enable(emu10k1_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_intr_disable(emu10k1_t *emu, unsigned int intrenb)
+void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -145,7 +185,7 @@ void snd_emu10k1_intr_disable(emu10k1_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_intr_enable(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int val;
@@ -165,7 +205,7 @@ void snd_emu10k1_voice_intr_enable(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_intr_disable(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int val;
@@ -185,7 +225,7 @@ void snd_emu10k1_voice_intr_disable(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_intr_ack(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
@@ -202,7 +242,7 @@ void snd_emu10k1_voice_intr_ack(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int val;
@@ -222,7 +262,7 @@ void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicen
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int val;
@@ -242,7 +282,7 @@ void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voice
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
@@ -259,7 +299,7 @@ void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int sol;
@@ -279,7 +319,7 @@ void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_voice_clear_loop_stop(emu10k1_t *emu, unsigned int voicenum)
+void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
{
unsigned long flags;
unsigned int sol;
@@ -299,7 +339,7 @@ void snd_emu10k1_voice_clear_loop_stop(emu10k1_t *emu, unsigned int voicenum)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait)
+void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
{
volatile unsigned count;
unsigned int newtime = 0, curtime;
@@ -318,9 +358,9 @@ void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait)
}
}
-unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
+unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
- emu10k1_t *emu = ac97->private_data;
+ struct snd_emu10k1 *emu = ac97->private_data;
unsigned long flags;
unsigned short val;
@@ -331,9 +371,9 @@ unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
return val;
}
-void snd_emu10k1_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short data)
+void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
{
- emu10k1_t *emu = ac97->private_data;
+ struct snd_emu10k1 *emu = ac97->private_data;
unsigned long flags;
spin_lock_irqsave(&emu->emu_lock, flags);
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 594ea063b140..a8b31286b6db 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -32,7 +32,7 @@
irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- emu10k1_t *emu = dev_id;
+ struct snd_emu10k1 *emu = dev_id;
unsigned int status, status2, orig_status, orig_status2;
int handled = 0;
@@ -56,7 +56,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int voice;
int voice_max = status & IPR_CHANNELNUMBERMASK;
u32 val;
- emu10k1_voice_t *pvoice = emu->voices;
+ struct snd_emu10k1_voice *pvoice = emu->voices;
val = snd_emu10k1_ptr_read(emu, CLIPL, 0);
for (voice = 0; voice <= voice_max; voice++) {
@@ -150,8 +150,8 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & IPR_P16V) {
while ((status2 = inl(emu->port + IPR2)) != 0) {
u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
- emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
- emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice);
+ struct snd_emu10k1_voice *pvoice = &(emu->p16v_voices[0]);
+ struct snd_emu10k1_voice *cvoice = &(emu->p16v_capture_voice);
//printk(KERN_INFO "status2=0x%x\n", status2);
orig_status2 = status2;
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index d42e4aeaa73a..68c795c03109 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -48,7 +48,7 @@
#define set_silent_ptb(emu,page) __set_ptb_entry(emu,page,emu->silent_page.addr)
#else
/* fill PTB entries -- we need to fill UNIT_PAGES entries */
-static inline void set_ptb_entry(emu10k1_t *emu, int page, dma_addr_t addr)
+static inline void set_ptb_entry(struct snd_emu10k1 *emu, int page, dma_addr_t addr)
{
int i;
page *= UNIT_PAGES;
@@ -57,7 +57,7 @@ static inline void set_ptb_entry(emu10k1_t *emu, int page, dma_addr_t addr)
addr += EMUPAGESIZE;
}
}
-static inline void set_silent_ptb(emu10k1_t *emu, int page)
+static inline void set_silent_ptb(struct snd_emu10k1 *emu, int page)
{
int i;
page *= UNIT_PAGES;
@@ -70,14 +70,14 @@ static inline void set_silent_ptb(emu10k1_t *emu, int page)
/*
*/
-static int synth_alloc_pages(emu10k1_t *hw, emu10k1_memblk_t *blk);
-static int synth_free_pages(emu10k1_t *hw, emu10k1_memblk_t *blk);
+static int synth_alloc_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk);
+static int synth_free_pages(struct snd_emu10k1 *hw, struct snd_emu10k1_memblk *blk);
-#define get_emu10k1_memblk(l,member) list_entry(l, emu10k1_memblk_t, member)
+#define get_emu10k1_memblk(l,member) list_entry(l, struct snd_emu10k1_memblk, member)
/* initialize emu10k1 part */
-static void emu10k1_memblk_init(emu10k1_memblk_t *blk)
+static void emu10k1_memblk_init(struct snd_emu10k1_memblk *blk)
{
blk->mapped_page = -1;
INIT_LIST_HEAD(&blk->mapped_link);
@@ -96,7 +96,7 @@ static void emu10k1_memblk_init(emu10k1_memblk_t *blk)
* in nextp
* if not found, return a negative error code.
*/
-static int search_empty_map_area(emu10k1_t *emu, int npages, struct list_head **nextp)
+static int search_empty_map_area(struct snd_emu10k1 *emu, int npages, struct list_head **nextp)
{
int page = 0, found_page = -ENOMEM;
int max_size = npages;
@@ -105,7 +105,7 @@ static int search_empty_map_area(emu10k1_t *emu, int npages, struct list_head **
struct list_head *pos;
list_for_each (pos, &emu->mapped_link_head) {
- emu10k1_memblk_t *blk = get_emu10k1_memblk(pos, mapped_link);
+ struct snd_emu10k1_memblk *blk = get_emu10k1_memblk(pos, mapped_link);
snd_assert(blk->mapped_page >= 0, continue);
size = blk->mapped_page - page;
if (size == npages) {
@@ -134,7 +134,7 @@ static int search_empty_map_area(emu10k1_t *emu, int npages, struct list_head **
*
* call with memblk_lock held
*/
-static int map_memblk(emu10k1_t *emu, emu10k1_memblk_t *blk)
+static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int page, pg;
struct list_head *next;
@@ -161,11 +161,11 @@ static int map_memblk(emu10k1_t *emu, emu10k1_memblk_t *blk)
*
* call with memblk_lock held
*/
-static int unmap_memblk(emu10k1_t *emu, emu10k1_memblk_t *blk)
+static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int start_page, end_page, mpage, pg;
struct list_head *p;
- emu10k1_memblk_t *q;
+ struct snd_emu10k1_memblk *q;
/* calculate the expected size of empty region */
if ((p = blk->mapped_link.prev) != &emu->mapped_link_head) {
@@ -197,11 +197,11 @@ static int unmap_memblk(emu10k1_t *emu, emu10k1_memblk_t *blk)
*
* unlike synth_alloc the memory block is aligned to the page start
*/
-static emu10k1_memblk_t *
-search_empty(emu10k1_t *emu, int size)
+static struct snd_emu10k1_memblk *
+search_empty(struct snd_emu10k1 *emu, int size)
{
struct list_head *p;
- emu10k1_memblk_t *blk;
+ struct snd_emu10k1_memblk *blk;
int page, psize;
psize = get_aligned_page(size + PAGE_SIZE -1);
@@ -217,7 +217,7 @@ search_empty(emu10k1_t *emu, int size)
__found_pages:
/* create a new memory block */
- blk = (emu10k1_memblk_t *)__snd_util_memblk_new(emu->memhdr, psize << PAGE_SHIFT, p->prev);
+ blk = (struct snd_emu10k1_memblk *)__snd_util_memblk_new(emu->memhdr, psize << PAGE_SHIFT, p->prev);
if (blk == NULL)
return NULL;
blk->mem.offset = aligned_page_offset(page); /* set aligned offset */
@@ -229,7 +229,7 @@ __found_pages:
/*
* check if the given pointer is valid for pages
*/
-static int is_valid_page(emu10k1_t *emu, dma_addr_t addr)
+static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr)
{
if (addr & ~emu->dma_mask) {
snd_printk(KERN_ERR "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr);
@@ -248,12 +248,12 @@ static int is_valid_page(emu10k1_t *emu, dma_addr_t addr)
* if no empty pages are found, tries to release unsed memory blocks
* and retry the mapping.
*/
-int snd_emu10k1_memblk_map(emu10k1_t *emu, emu10k1_memblk_t *blk)
+int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int err;
int size;
struct list_head *p, *nextp;
- emu10k1_memblk_t *deleted;
+ struct snd_emu10k1_memblk *deleted;
unsigned long flags;
spin_lock_irqsave(&emu->memblk_lock, flags);
@@ -288,13 +288,13 @@ int snd_emu10k1_memblk_map(emu10k1_t *emu, emu10k1_memblk_t *blk)
/*
* page allocation for DMA
*/
-snd_util_memblk_t *
-snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
+struct snd_util_memblk *
+snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
- snd_util_memhdr_t *hdr;
- emu10k1_memblk_t *blk;
+ struct snd_util_memhdr *hdr;
+ struct snd_emu10k1_memblk *blk;
int page, err, idx;
snd_assert(emu, return NULL);
@@ -336,19 +336,19 @@ snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
blk->map_locked = 1; /* do not unmap this block! */
err = snd_emu10k1_memblk_map(emu, blk);
if (err < 0) {
- __snd_util_mem_free(hdr, (snd_util_memblk_t *)blk);
+ __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk);
up(&hdr->block_mutex);
return NULL;
}
up(&hdr->block_mutex);
- return (snd_util_memblk_t *)blk;
+ return (struct snd_util_memblk *)blk;
}
/*
* release DMA buffer from page table
*/
-int snd_emu10k1_free_pages(emu10k1_t *emu, snd_util_memblk_t *blk)
+int snd_emu10k1_free_pages(struct snd_emu10k1 *emu, struct snd_util_memblk *blk)
{
snd_assert(emu && blk, return -EINVAL);
return snd_emu10k1_synth_free(emu, blk);
@@ -363,26 +363,26 @@ int snd_emu10k1_free_pages(emu10k1_t *emu, snd_util_memblk_t *blk)
/*
* allocate a synth sample area
*/
-snd_util_memblk_t *
-snd_emu10k1_synth_alloc(emu10k1_t *hw, unsigned int size)
+struct snd_util_memblk *
+snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size)
{
- emu10k1_memblk_t *blk;
- snd_util_memhdr_t *hdr = hw->memhdr;
+ struct snd_emu10k1_memblk *blk;
+ struct snd_util_memhdr *hdr = hw->memhdr;
down(&hdr->block_mutex);
- blk = (emu10k1_memblk_t *)__snd_util_mem_alloc(hdr, size);
+ blk = (struct snd_emu10k1_memblk *)__snd_util_mem_alloc(hdr, size);
if (blk == NULL) {
up(&hdr->block_mutex);
return NULL;
}
if (synth_alloc_pages(hw, blk)) {
- __snd_util_mem_free(hdr, (snd_util_memblk_t *)blk);
+ __snd_util_mem_free(hdr, (struct snd_util_memblk *)blk);
up(&hdr->block_mutex);
return NULL;
}
snd_emu10k1_memblk_map(hw, blk);
up(&hdr->block_mutex);
- return (snd_util_memblk_t *)blk;
+ return (struct snd_util_memblk *)blk;
}
@@ -390,10 +390,10 @@ snd_emu10k1_synth_alloc(emu10k1_t *hw, unsigned int size)
* free a synth sample area
*/
int
-snd_emu10k1_synth_free(emu10k1_t *emu, snd_util_memblk_t *memblk)
+snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk)
{
- snd_util_memhdr_t *hdr = emu->memhdr;
- emu10k1_memblk_t *blk = (emu10k1_memblk_t *)memblk;
+ struct snd_util_memhdr *hdr = emu->memhdr;
+ struct snd_emu10k1_memblk *blk = (struct snd_emu10k1_memblk *)memblk;
unsigned long flags;
down(&hdr->block_mutex);
@@ -409,10 +409,12 @@ snd_emu10k1_synth_free(emu10k1_t *emu, snd_util_memblk_t *memblk)
/* check new allocation range */
-static void get_single_page_range(snd_util_memhdr_t *hdr, emu10k1_memblk_t *blk, int *first_page_ret, int *last_page_ret)
+static void get_single_page_range(struct snd_util_memhdr *hdr,
+ struct snd_emu10k1_memblk *blk,
+ int *first_page_ret, int *last_page_ret)
{
struct list_head *p;
- emu10k1_memblk_t *q;
+ struct snd_emu10k1_memblk *q;
int first_page, last_page;
first_page = blk->first_page;
if ((p = blk->mem.list.prev) != &hdr->block) {
@@ -433,7 +435,7 @@ static void get_single_page_range(snd_util_memhdr_t *hdr, emu10k1_memblk_t *blk,
/*
* allocate kernel pages
*/
-static int synth_alloc_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
+static int synth_alloc_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int page, first_page, last_page;
struct snd_dma_buffer dmab;
@@ -472,7 +474,7 @@ __fail:
/*
* free pages
*/
-static int synth_free_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
+static int synth_free_pages(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int page, first_page, last_page;
struct snd_dma_buffer dmab;
@@ -495,7 +497,7 @@ static int synth_free_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
}
/* calculate buffer pointer from offset address */
-static inline void *offset_ptr(emu10k1_t *emu, int page, int offset)
+static inline void *offset_ptr(struct snd_emu10k1 *emu, int page, int offset)
{
char *ptr;
snd_assert(page >= 0 && page < emu->max_cache_pages, return NULL);
@@ -511,11 +513,12 @@ static inline void *offset_ptr(emu10k1_t *emu, int page, int offset)
/*
* bzero(blk + offset, size)
*/
-int snd_emu10k1_synth_bzero(emu10k1_t *emu, snd_util_memblk_t *blk, int offset, int size)
+int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk,
+ int offset, int size)
{
int page, nextofs, end_offset, temp, temp1;
void *ptr;
- emu10k1_memblk_t *p = (emu10k1_memblk_t *)blk;
+ struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk;
offset += blk->offset & (PAGE_SIZE - 1);
end_offset = offset + size;
@@ -538,11 +541,12 @@ int snd_emu10k1_synth_bzero(emu10k1_t *emu, snd_util_memblk_t *blk, int offset,
/*
* copy_from_user(blk + offset, data, size)
*/
-int snd_emu10k1_synth_copy_from_user(emu10k1_t *emu, snd_util_memblk_t *blk, int offset, const char __user *data, int size)
+int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk,
+ int offset, const char __user *data, int size)
{
int page, nextofs, end_offset, temp, temp1;
void *ptr;
- emu10k1_memblk_t *p = (emu10k1_memblk_t *)blk;
+ struct snd_emu10k1_memblk *p = (struct snd_emu10k1_memblk *)blk;
offset += blk->offset & (PAGE_SIZE - 1);
end_offset = offset + size;
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index e27ebb9bb74a..9905651935fb 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -93,6 +93,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -106,11 +107,11 @@
#define PCM_FRONT_CHANNEL 0
#define PCM_REAR_CHANNEL 1
#define PCM_CENTER_LFE_CHANNEL 2
-#define PCM_UNKNOWN_CHANNEL 3
+#define PCM_SIDE_CHANNEL 3
#define CONTROL_FRONT_CHANNEL 0
#define CONTROL_REAR_CHANNEL 3
#define CONTROL_CENTER_LFE_CHANNEL 1
-#define CONTROL_UNKNOWN_CHANNEL 2
+#define CONTROL_SIDE_CHANNEL 2
/* Card IDs:
* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
@@ -121,10 +122,11 @@
*/
/* hardware definition */
-static snd_pcm_hardware_t snd_p16v_playback_hw = {
+static struct snd_pcm_hardware snd_p16v_playback_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
.rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
@@ -140,10 +142,11 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_p16v_capture_hw = {
+static struct snd_pcm_hardware snd_p16v_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
@@ -159,9 +162,9 @@ static snd_pcm_hardware_t snd_p16v_capture_hw = {
.fifo_size = 0,
};
-static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
if (epcm) {
//snd_printk("epcm free: %p\n", epcm);
@@ -170,12 +173,12 @@ static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
}
/* open_playback callback */
-static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, int channel_id)
+static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_voice_t *channel = &(emu->p16v_voices[channel_id]);
- emu10k1_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -206,12 +209,12 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
return 0;
}
/* open_capture callback */
-static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
+static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
- emu10k1_pcm_t *epcm;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice);
+ struct snd_emu10k1_pcm *epcm;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
@@ -244,41 +247,41 @@ static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int
/* close callback */
-static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- //snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ //struct snd_pcm_runtime *runtime = substream->runtime;
+ //struct snd_emu10k1_pcm *epcm = runtime->private_data;
emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
/* FIXME: maybe zero others */
return 0;
}
/* close callback */
-static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- //snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ //struct snd_pcm_runtime *runtime = substream->runtime;
+ //struct snd_emu10k1_pcm *epcm = runtime->private_data;
emu->p16v_capture_voice.use=0;
/* FIXME: maybe zero others */
return 0;
}
-static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream)
{
return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
}
-static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
{
// Only using channel 0 for now, but the card has 2 channels.
return snd_p16v_pcm_open_capture_channel(substream, 0);
}
/* hw_params callback */
-static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int result;
result = snd_pcm_lib_malloc_pages(substream,
@@ -287,8 +290,8 @@ static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
}
/* hw_params callback */
-static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int result;
result = snd_pcm_lib_malloc_pages(substream,
@@ -298,7 +301,7 @@ static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
/* hw_free callback */
-static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream)
{
int result;
result = snd_pcm_lib_free_pages(substream);
@@ -306,7 +309,7 @@ static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
}
/* hw_free callback */
-static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream)
{
int result;
result = snd_pcm_lib_free_pages(substream);
@@ -315,10 +318,10 @@ static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
/* prepare playback callback */
-static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int channel = substream->pcm->device - emu->p16v_device_offset;
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -364,10 +367,10 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
}
/* prepare capture callback */
-static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
+static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int channel = substream->pcm->device - emu->p16v_device_offset;
u32 tmp;
//printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
@@ -398,7 +401,7 @@ static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
return 0;
}
-static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
+static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int enable;
@@ -409,7 +412,7 @@ static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
-static void snd_p16v_intr_disable(emu10k1_t *emu, unsigned int intrenb)
+static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
{
unsigned long flags;
unsigned int disable;
@@ -421,16 +424,16 @@ static void snd_p16v_intr_disable(emu10k1_t *emu, unsigned int intrenb)
}
/* trigger_playback callback */
-static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
+static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime;
- emu10k1_pcm_t *epcm;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime;
+ struct snd_emu10k1_pcm *epcm;
int channel;
int result = 0;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
u32 basic = 0;
u32 inte = 0;
int running=0;
@@ -474,12 +477,12 @@ static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
}
/* trigger_capture callback */
-static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
+static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream,
int cmd)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
int channel = 0;
int result = 0;
u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
@@ -505,11 +508,11 @@ static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
/* pointer_playback callback */
static snd_pcm_uframes_t
-snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
+snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
int channel = substream->pcm->device - emu->p16v_device_offset;
if (!epcm->running)
@@ -530,11 +533,11 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
/* pointer_capture callback */
static snd_pcm_uframes_t
-snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
+snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
{
- emu10k1_t *emu = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- emu10k1_pcm_t *epcm = runtime->private_data;
+ struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_emu10k1_pcm *epcm = runtime->private_data;
snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
int channel = 0;
@@ -554,7 +557,7 @@ snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
}
/* operators */
-static snd_pcm_ops_t snd_p16v_playback_front_ops = {
+static struct snd_pcm_ops snd_p16v_playback_front_ops = {
.open = snd_p16v_pcm_open_playback_front,
.close = snd_p16v_pcm_close_playback,
.ioctl = snd_pcm_lib_ioctl,
@@ -565,7 +568,7 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = {
.pointer = snd_p16v_pcm_pointer_playback,
};
-static snd_pcm_ops_t snd_p16v_capture_ops = {
+static struct snd_pcm_ops snd_p16v_capture_ops = {
.open = snd_p16v_pcm_open_capture,
.close = snd_p16v_pcm_close_capture,
.ioctl = snd_pcm_lib_ioctl,
@@ -577,7 +580,7 @@ static snd_pcm_ops_t snd_p16v_capture_ops = {
};
-int snd_p16v_free(emu10k1_t *chip)
+int snd_p16v_free(struct snd_emu10k1 *chip)
{
// release the data
if (chip->p16v_buffer.area) {
@@ -587,18 +590,10 @@ int snd_p16v_free(emu10k1_t *chip)
return 0;
}
-static void snd_p16v_pcm_free(snd_pcm_t *pcm)
+int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
{
- emu10k1_t *emu = pcm->private_data;
- //snd_printk("snd_p16v_pcm_free pcm: called\n");
- snd_pcm_lib_preallocate_free_for_all(pcm);
- emu->pcm = NULL;
-}
-
-int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
-{
- snd_pcm_t *pcm;
- snd_pcm_substream_t *substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *substream;
int err;
int capture=1;
@@ -611,7 +606,6 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
return err;
pcm->private_data = emu;
- pcm->private_free = snd_p16v_pcm_free;
// Single playback 8 channel device.
// Single capture 2 channel device.
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
@@ -620,7 +614,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
strcpy(pcm->name, "p16v");
- emu->pcm = pcm;
+ emu->pcm_p16v = pcm;
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
@@ -650,7 +644,8 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
return 0;
}
-static int snd_p16v_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -659,241 +654,57 @@ static int snd_p16v_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_p16v_volume_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
+static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- u32 value;
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ int high_low = (kcontrol->private_value >> 8) & 0xff;
+ int reg = kcontrol->private_value & 0xff;
+ u32 value;
- value = snd_emu10k1_ptr20_read(emu, reg, high_low);
- if (high_low == 1) {
- ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
- ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
+ value = snd_emu10k1_ptr20_read(emu, reg, high_low);
+ if (high_low) {
+ ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
+ ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
} else {
- ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
- ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
+ ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
+ ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
}
- return 0;
-}
-
-static int snd_p16v_volume_get_spdif_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER7;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER7;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-static int snd_p16v_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER8;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-static int snd_p16v_volume_get_spdif_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER8;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_get_analog_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER9;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER9;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
-static int snd_p16v_volume_get_analog_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER10;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
+ return 0;
}
-static int snd_p16v_volume_get_analog_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER10;
- return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
-}
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
+ int high_low = (kcontrol->private_value >> 8) & 0xff;
+ int reg = kcontrol->private_value & 0xff;
+ u32 value, oval;
-static int snd_p16v_volume_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
-{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
- u32 value;
- value = snd_emu10k1_ptr20_read(emu, reg, 0);
- //value = value & 0xffff;
+ oval = value = snd_emu10k1_ptr20_read(emu, reg, 0);
if (high_low == 1) {
value &= 0xffff;
- value = value | ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16);
+ value |= ((0xff - ucontrol->value.integer.value[0]) << 24) |
+ ((0xff - ucontrol->value.integer.value[1]) << 16);
} else {
value &= 0xffff0000;
- value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) );
+ value |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
+ ((0xff - ucontrol->value.integer.value[1]) );
}
- snd_emu10k1_ptr20_write(emu, reg, 0, value);
- return 1;
-}
-
-static int snd_p16v_volume_put_spdif_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER7;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER7;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER8;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_spdif_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER8;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_analog_front(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER9;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER9;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_analog_rear(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 1;
- int reg = PLAYBACK_VOLUME_MIXER10;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
-}
-
-static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
-{
- int high_low = 0;
- int reg = PLAYBACK_VOLUME_MIXER10;
- return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
+ if (value != oval) {
+ snd_emu10k1_ptr20_write(emu, reg, 0, value);
+ return 1;
+ }
+ return 0;
}
-static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
+static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Analog Front Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_analog_front,
- .put = snd_p16v_volume_put_analog_front
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Analog Center/LFE Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_analog_center_lfe,
- .put = snd_p16v_volume_put_analog_center_lfe
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Analog Unknown Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_analog_unknown,
- .put = snd_p16v_volume_put_analog_unknown
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD Analog Rear Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_analog_rear,
- .put = snd_p16v_volume_put_analog_rear
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD SPDIF Front Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_spdif_front,
- .put = snd_p16v_volume_put_spdif_front
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD SPDIF Center/LFE Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_spdif_center_lfe,
- .put = snd_p16v_volume_put_spdif_center_lfe
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD SPDIF Unknown Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_spdif_unknown,
- .put = snd_p16v_volume_put_spdif_unknown
-};
-
-static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD SPDIF Rear Playback Volume",
- .info = snd_p16v_volume_info,
- .get = snd_p16v_volume_get_spdif_rear,
- .put = snd_p16v_volume_put_spdif_rear
-};
-
-static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
- static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
+ static char *texts[8] = {
+ "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S",
+ "CDIF", "FX", "AC97"
+ };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -904,19 +715,19 @@ static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
return 0;
}
-static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
u32 mask;
@@ -933,16 +744,8 @@ static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD source Capture",
- .info = snd_p16v_capture_source_info,
- .get = snd_p16v_capture_source_get,
- .put = snd_p16v_capture_source_put
-};
-
-static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = { "0", "1", "2", "3", };
@@ -955,19 +758,19 @@ static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
return 0;
}
-static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
u32 tmp;
@@ -982,60 +785,89 @@ static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "HD channel Capture",
- .info = snd_p16v_capture_channel_info,
- .get = snd_p16v_capture_channel_get,
- .put = snd_p16v_capture_channel_put
+#define P16V_VOL(xname,xreg,xhl) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_p16v_volume_info, \
+ .get = snd_p16v_volume_get, \
+ .put = snd_p16v_volume_put, \
+ .private_value = ((xreg) | ((xhl) << 8)) \
+}
+
+static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
+ P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
+ P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
+ P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
+ P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0),
+ P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0),
+ P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1),
+ P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1),
+ P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD source Capture",
+ .info = snd_p16v_capture_source_info,
+ .get = snd_p16v_capture_source_get,
+ .put = snd_p16v_capture_source_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD channel Capture",
+ .info = snd_p16v_capture_channel_info,
+ .get = snd_p16v_capture_channel_get,
+ .put = snd_p16v_capture_channel_put
+ },
};
-int snd_p16v_mixer(emu10k1_t *emu)
+
+int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
{
- int err;
- snd_kcontrol_t *kctl;
- snd_card_t *card = emu->card;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_front, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_rear, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_center_lfe, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_unknown, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_front, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_rear, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_center_lfe, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_unknown, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
- if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
- return -ENOMEM;
- if ((err = snd_ctl_add(card, kctl)))
- return err;
+ int i, err;
+ struct snd_card *card = emu->card;
+
+ for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) {
+ if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i],
+ emu))) < 0)
+ return err;
+ }
return 0;
}
+#ifdef CONFIG_PM
+
+#define NUM_CHS 1 /* up to 4, but only first channel is used */
+
+int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
+{
+ emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
+ if (! emu->p16v_saved)
+ return -ENOMEM;
+ return 0;
+}
+
+void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu)
+{
+ vfree(emu->p16v_saved);
+}
+
+void snd_p16v_suspend(struct snd_emu10k1 *emu)
+{
+ int i, ch;
+ unsigned int *val;
+
+ val = emu->p16v_saved;
+ for (ch = 0; ch < NUM_CHS; ch++)
+ for (i = 0; i < 0x80; i++, val++)
+ *val = snd_emu10k1_ptr20_read(emu, i, ch);
+}
+
+void snd_p16v_resume(struct snd_emu10k1 *emu)
+{
+ int i, ch;
+ unsigned int *val;
+
+ val = emu->p16v_saved;
+ for (ch = 0; ch < NUM_CHS; ch++)
+ for (i = 0; i < 0x80; i++, val++)
+ snd_emu10k1_ptr20_write(emu, i, ch, *val);
+}
+#endif
diff --git a/sound/pci/emu10k1/timer.c b/sound/pci/emu10k1/timer.c
index d2e364607c1d..6295b2dca785 100644
--- a/sound/pci/emu10k1/timer.c
+++ b/sound/pci/emu10k1/timer.c
@@ -30,9 +30,9 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
-static int snd_emu10k1_timer_start(snd_timer_t *timer)
+static int snd_emu10k1_timer_start(struct snd_timer *timer)
{
- emu10k1_t *emu;
+ struct snd_emu10k1 *emu;
unsigned long flags;
unsigned int delay;
@@ -47,9 +47,9 @@ static int snd_emu10k1_timer_start(snd_timer_t *timer)
return 0;
}
-static int snd_emu10k1_timer_stop(snd_timer_t *timer)
+static int snd_emu10k1_timer_stop(struct snd_timer *timer)
{
- emu10k1_t *emu;
+ struct snd_emu10k1 *emu;
unsigned long flags;
emu = snd_timer_chip(timer);
@@ -59,7 +59,7 @@ static int snd_emu10k1_timer_stop(snd_timer_t *timer)
return 0;
}
-static int snd_emu10k1_timer_precise_resolution(snd_timer_t *timer,
+static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer,
unsigned long *num, unsigned long *den)
{
*num = 1;
@@ -67,7 +67,7 @@ static int snd_emu10k1_timer_precise_resolution(snd_timer_t *timer,
return 0;
}
-static struct _snd_timer_hardware snd_emu10k1_timer_hw = {
+static struct snd_timer_hardware snd_emu10k1_timer_hw = {
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */
.ticks = 1024,
@@ -76,10 +76,10 @@ static struct _snd_timer_hardware snd_emu10k1_timer_hw = {
.precise_resolution = snd_emu10k1_timer_precise_resolution,
};
-int __devinit snd_emu10k1_timer(emu10k1_t *emu, int device)
+int __devinit snd_emu10k1_timer(struct snd_emu10k1 *emu, int device)
{
- snd_timer_t *timer = NULL;
- snd_timer_id_t tid;
+ struct snd_timer *timer = NULL;
+ struct snd_timer_id tid;
int err;
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
diff --git a/sound/pci/emu10k1/tina2.h b/sound/pci/emu10k1/tina2.h
new file mode 100644
index 000000000000..5c43abf03e89
--- /dev/null
+++ b/sound/pci/emu10k1/tina2.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ * Driver p16v chips
+ * Version: 0.21
+ *
+ *
+ * This code was initally based on code from ALSA's emu10k1x.c which is:
+ * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.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
+ *
+ */
+
+/********************************************************************************************************/
+/* Audigy2 Tina2 (notebook) pointer-offset register set, accessed through the PTR2 and DATA2 registers */
+/********************************************************************************************************/
+
+#define TINA2_VOLUME 0x71 /* Attenuate playback volume to prevent distortion. */
+ /* The windows driver does not use this register,
+ * so it must use some other attenuation method.
+ * Without this, the output is 12dB too loud,
+ * resulting in distortion.
+ */
+
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index d251d3440eec..56ffb7dc3ee2 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -45,9 +45,10 @@
* --rlrevell
*/
-static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
+static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
+ struct snd_emu10k1_voice **rvoice)
{
- emu10k1_voice_t *voice;
+ struct snd_emu10k1_voice *voice;
int i, j, k, first_voice, last_voice, skip;
*rvoice = NULL;
@@ -105,7 +106,8 @@ static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, em
return 0;
}
-int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
+int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number,
+ struct snd_emu10k1_voice **rvoice)
{
unsigned long flags;
int result;
@@ -123,7 +125,7 @@ int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int numbe
if (emu->get_synth_voice) {
result = emu->get_synth_voice(emu);
if (result >= 0) {
- emu10k1_voice_t *pvoice = &emu->voices[result];
+ struct snd_emu10k1_voice *pvoice = &emu->voices[result];
pvoice->interrupt = NULL;
pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
pvoice->epcm = NULL;
@@ -137,7 +139,8 @@ int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int numbe
return result;
}
-int snd_emu10k1_voice_free(emu10k1_t *emu, emu10k1_voice_t *pvoice)
+int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
+ struct snd_emu10k1_voice *pvoice)
{
unsigned long flags;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 2daa575f43ff..55aaf110331a 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -19,6 +19,13 @@
*
*/
+/* Power-Management-Code ( CONFIG_PM )
+ * for ens1371 only ( FIXME )
+ * derived from cs4281.c, atiixp.c and via82xx.c
+ * using http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c1540.htm
+ * by Kurt J. Bosch
+ */
+
#include <sound/driver.h>
#include <asm/io.h>
#include <linux/delay.h>
@@ -83,6 +90,10 @@ static int joystick_port[SNDRV_CARDS];
static int joystick[SNDRV_CARDS];
#endif
#endif
+#ifdef CHIP1371
+static int spdif[SNDRV_CARDS];
+static int lineio[SNDRV_CARDS];
+#endif
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard.");
@@ -99,6 +110,12 @@ module_param_array(joystick, bool, NULL, 0444);
MODULE_PARM_DESC(joystick, "Enable joystick.");
#endif
#endif /* SUPPORT_JOYSTICK */
+#ifdef CHIP1371
+module_param_array(spdif, int, NULL, 0444);
+MODULE_PARM_DESC(spdif, "S/PDIF output (-1 = none, 0 = auto, 1 = force).");
+module_param_array(lineio, int, NULL, 0444);
+MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force).");
+#endif
/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
@@ -360,9 +377,7 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
*/
-typedef struct _snd_ensoniq ensoniq_t;
-
-struct _snd_ensoniq {
+struct ensoniq {
spinlock_t reg_lock;
struct semaphore src_mutex;
@@ -385,12 +400,12 @@ struct _snd_ensoniq {
union {
#ifdef CHIP1371
struct {
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
} es1371;
#else
struct {
int pclkdiv_lock;
- ak4531_t *ak4531;
+ struct snd_ak4531 *ak4531;
} es1370;
#endif
} u;
@@ -398,21 +413,21 @@ struct _snd_ensoniq {
struct pci_dev *pci;
unsigned short subsystem_vendor_id;
unsigned short subsystem_device_id;
- snd_card_t *card;
- snd_pcm_t *pcm1; /* DAC1/ADC PCM */
- snd_pcm_t *pcm2; /* DAC2 PCM */
- snd_pcm_substream_t *playback1_substream;
- snd_pcm_substream_t *playback2_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm1; /* DAC1/ADC PCM */
+ struct snd_pcm *pcm2; /* DAC2 PCM */
+ struct snd_pcm_substream *playback1_substream;
+ struct snd_pcm_substream *playback2_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int p1_dma_size;
unsigned int p2_dma_size;
unsigned int c_dma_size;
unsigned int p1_period_size;
unsigned int p2_period_size;
unsigned int c_period_size;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *midi_input;
- snd_rawmidi_substream_t *midi_output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *midi_input;
+ struct snd_rawmidi_substream *midi_output;
unsigned int spdif;
unsigned int spdif_default;
@@ -452,39 +467,39 @@ MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);
#ifdef CHIP1370
static unsigned int snd_es1370_fixed_rates[] =
{5512, 11025, 22050, 44100};
-static snd_pcm_hw_constraint_list_t snd_es1370_hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = {
.count = 4,
.list = snd_es1370_fixed_rates,
.mask = 0,
};
-static ratnum_t es1370_clock = {
+static struct snd_ratnum es1370_clock = {
.num = ES_1370_SRCLOCK,
.den_min = 29,
.den_max = 353,
.den_step = 1,
};
-static snd_pcm_hw_constraint_ratnums_t snd_es1370_hw_constraints_clock = {
+static struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = {
.nrats = 1,
.rats = &es1370_clock,
};
#else
-static ratden_t es1371_dac_clock = {
+static struct snd_ratden es1371_dac_clock = {
.num_min = 3000 * (1 << 15),
.num_max = 48000 * (1 << 15),
.num_step = 3000,
.den = 1 << 15,
};
-static snd_pcm_hw_constraint_ratdens_t snd_es1371_hw_constraints_dac_clock = {
+static struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = {
.nrats = 1,
.rats = &es1371_dac_clock,
};
-static ratnum_t es1371_adc_clock = {
+static struct snd_ratnum es1371_adc_clock = {
.num = 48000 << 15,
.den_min = 32768,
.den_max = 393216,
.den_step = 1,
};
-static snd_pcm_hw_constraint_ratnums_t snd_es1371_hw_constraints_adc_clock = {
+static struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = {
.nrats = 1,
.rats = &es1371_adc_clock,
};
@@ -498,7 +513,7 @@ static const unsigned int snd_ensoniq_sample_shift[] =
#ifdef CHIP1371
-static unsigned int snd_es1371_wait_src_ready(ensoniq_t * ensoniq)
+static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq)
{
unsigned int t, r = 0;
@@ -508,11 +523,12 @@ static unsigned int snd_es1371_wait_src_ready(ensoniq_t * ensoniq)
return r;
cond_resched();
}
- snd_printk(KERN_ERR "wait source ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r);
+ snd_printk(KERN_ERR "wait source ready timeout 0x%lx [0x%x]\n",
+ ES_REG(ensoniq, 1371_SMPRATE), r);
return 0;
}
-static unsigned int snd_es1371_src_read(ensoniq_t * ensoniq, unsigned short reg)
+static unsigned int snd_es1371_src_read(struct ensoniq * ensoniq, unsigned short reg)
{
unsigned int temp, i, orig, r;
@@ -546,7 +562,7 @@ static unsigned int snd_es1371_src_read(ensoniq_t * ensoniq, unsigned short reg)
return temp;
}
-static void snd_es1371_src_write(ensoniq_t * ensoniq,
+static void snd_es1371_src_write(struct ensoniq * ensoniq,
unsigned short reg, unsigned short data)
{
unsigned int r;
@@ -562,14 +578,15 @@ static void snd_es1371_src_write(ensoniq_t * ensoniq,
#ifdef CHIP1370
-static void snd_es1370_codec_write(ak4531_t *ak4531,
+static void snd_es1370_codec_write(struct snd_ak4531 *ak4531,
unsigned short reg, unsigned short val)
{
- ensoniq_t *ensoniq = ak4531->private_data;
+ struct ensoniq *ensoniq = ak4531->private_data;
unsigned long end_time = jiffies + HZ / 10;
#if 0
- printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC));
+ printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n",
+ reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC));
#endif
do {
if (!(inl(ES_REG(ensoniq, STATUS)) & ES_1370_CSTAT)) {
@@ -578,17 +595,18 @@ static void snd_es1370_codec_write(ak4531_t *ak4531,
}
schedule_timeout_uninterruptible(1);
} while (time_after(end_time, jiffies));
- snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS)));
+ snd_printk(KERN_ERR "codec write timeout, status = 0x%x\n",
+ inl(ES_REG(ensoniq, STATUS)));
}
#endif /* CHIP1370 */
#ifdef CHIP1371
-static void snd_es1371_codec_write(ac97_t *ac97,
+static void snd_es1371_codec_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- ensoniq_t *ensoniq = ac97->private_data;
+ struct ensoniq *ensoniq = ac97->private_data;
unsigned int t, x;
down(&ensoniq->src_mutex);
@@ -602,12 +620,14 @@ static void snd_es1371_codec_write(ac97_t *ac97,
/* wait for not busy (state 0) first to avoid
transition states */
for (t = 0; t < POLL_COUNT; t++) {
- if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == 0x00000000)
+ if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+ 0x00000000)
break;
}
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < POLL_COUNT; t++) {
- if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == 0x00010000)
+ if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+ 0x00010000)
break;
}
outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
@@ -619,13 +639,14 @@ static void snd_es1371_codec_write(ac97_t *ac97,
}
}
up(&ensoniq->src_mutex);
- snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk(KERN_ERR "codec write timeout at 0x%lx [0x%x]\n",
+ ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
}
-static unsigned short snd_es1371_codec_read(ac97_t *ac97,
+static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- ensoniq_t *ensoniq = ac97->private_data;
+ struct ensoniq *ensoniq = ac97->private_data;
unsigned int t, x, fail = 0;
__again:
@@ -640,12 +661,14 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97,
/* wait for not busy (state 0) first to avoid
transition states */
for (t = 0; t < POLL_COUNT; t++) {
- if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == 0x00000000)
+ if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+ 0x00000000)
break;
}
/* wait for a SAFE time to write addr/data and then do it, dammit */
for (t = 0; t < POLL_COUNT; t++) {
- if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) == 0x00010000)
+ if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
+ 0x00010000)
break;
}
outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
@@ -666,18 +689,22 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97,
}
up(&ensoniq->src_mutex);
if (++fail > 10) {
- snd_printk(KERN_ERR "codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk(KERN_ERR "codec read timeout (final) "
+ "at 0x%lx, reg = 0x%x [0x%x]\n",
+ ES_REG(ensoniq, 1371_CODEC), reg,
+ inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}
goto __again;
}
}
up(&ensoniq->src_mutex);
- snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
+ snd_printk(KERN_ERR "es1371: codec read timeout at 0x%lx [0x%x]\n",
+ ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}
-static void snd_es1371_codec_wait(ac97_t *ac97)
+static void snd_es1371_codec_wait(struct snd_ac97 *ac97)
{
msleep(750);
snd_es1371_codec_read(ac97, AC97_RESET);
@@ -686,7 +713,7 @@ static void snd_es1371_codec_wait(ac97_t *ac97)
msleep(50);
}
-static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate)
+static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate)
{
unsigned int n, truncm, freq, result;
@@ -709,60 +736,70 @@ static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate)
0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
}
snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
- (snd_es1371_src_read(ensoniq, ES_SMPREG_ADC + ES_SMPREG_INT_REGS) & 0x00ff) |
- ((freq >> 5) & 0xfc00));
+ (snd_es1371_src_read(ensoniq, ES_SMPREG_ADC +
+ ES_SMPREG_INT_REGS) & 0x00ff) |
+ ((freq >> 5) & 0xfc00));
snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8);
snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8);
up(&ensoniq->src_mutex);
}
-static void snd_es1371_dac1_rate(ensoniq_t * ensoniq, unsigned int rate)
+static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate)
{
unsigned int freq, r;
down(&ensoniq->src_mutex);
freq = ((rate << 15) + 1500) / 3000;
- r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | ES_1371_DIS_P1;
+ r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
+ ES_1371_DIS_P2 | ES_1371_DIS_R1)) |
+ ES_1371_DIS_P1;
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS,
- (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS) & 0x00ff) |
+ (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC1 +
+ ES_SMPREG_INT_REGS) & 0x00ff) |
((freq >> 5) & 0xfc00));
snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
- r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1));
+ r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
+ ES_1371_DIS_P2 | ES_1371_DIS_R1));
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
up(&ensoniq->src_mutex);
}
-static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate)
+static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate)
{
unsigned int freq, r;
down(&ensoniq->src_mutex);
freq = ((rate << 15) + 1500) / 3000;
- r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | ES_1371_DIS_P2;
+ r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
+ ES_1371_DIS_P1 | ES_1371_DIS_R1)) |
+ ES_1371_DIS_P2;
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS,
- (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS) & 0x00ff) |
+ (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC2 +
+ ES_SMPREG_INT_REGS) & 0x00ff) |
((freq >> 5) & 0xfc00));
- snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
- r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1));
+ snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC,
+ freq & 0x7fff);
+ r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
+ ES_1371_DIS_P1 | ES_1371_DIS_R1));
outl(r, ES_REG(ensoniq, 1371_SMPRATE));
up(&ensoniq->src_mutex);
}
#endif /* CHIP1371 */
-static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
{
unsigned int what = 0;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == ensoniq->playback1_substream) {
@@ -788,7 +825,7 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
{
unsigned int what = 0;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == ensoniq->playback1_substream) {
@@ -821,21 +858,21 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
* PCM part
*/
-static int snd_ensoniq_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ensoniq_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ensoniq_hw_free(snd_pcm_substream_t * substream)
+static int snd_ensoniq_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback1_prepare(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int mode = 0;
ensoniq->p1_dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -860,7 +897,8 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
ensoniq->sctrl &= ~(ES_P1_LOOP_SEL | ES_P1_PAUSE | ES_P1_SCT_RLD | ES_P1_MODEM);
ensoniq->sctrl |= ES_P1_INT_EN | ES_P1_MODEO(mode);
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- outl((ensoniq->p1_period_size >> snd_ensoniq_sample_shift[mode]) - 1, ES_REG(ensoniq, DAC1_COUNT));
+ outl((ensoniq->p1_period_size >> snd_ensoniq_sample_shift[mode]) - 1,
+ ES_REG(ensoniq, DAC1_COUNT));
#ifdef CHIP1370
ensoniq->ctrl &= ~ES_1370_WTSRSELM;
switch (runtime->rate) {
@@ -879,10 +917,10 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback2_prepare(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int mode = 0;
ensoniq->p2_dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -902,7 +940,8 @@ static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
ensoniq->sctrl |= ES_P2_INT_EN | ES_P2_MODEO(mode) |
ES_P2_END_INCO(mode & 2 ? 2 : 1) | ES_P2_ST_INCO(0);
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- outl((ensoniq->p2_period_size >> snd_ensoniq_sample_shift[mode]) - 1, ES_REG(ensoniq, DAC2_COUNT));
+ outl((ensoniq->p2_period_size >> snd_ensoniq_sample_shift[mode]) - 1,
+ ES_REG(ensoniq, DAC2_COUNT));
#ifdef CHIP1370
if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_CAPTURE)) {
ensoniq->ctrl &= ~ES_1370_PCLKDIVM;
@@ -918,10 +957,10 @@ static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ensoniq_capture_prepare(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int mode = 0;
ensoniq->c_dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -939,7 +978,8 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
ensoniq->sctrl &= ~(ES_R1_LOOP_SEL | ES_R1_MODEM);
ensoniq->sctrl |= ES_R1_INT_EN | ES_R1_MODEO(mode);
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- outl((ensoniq->c_period_size >> snd_ensoniq_sample_shift[mode]) - 1, ES_REG(ensoniq, ADC_COUNT));
+ outl((ensoniq->c_period_size >> snd_ensoniq_sample_shift[mode]) - 1,
+ ES_REG(ensoniq, ADC_COUNT));
#ifdef CHIP1370
if (!(ensoniq->u.es1370.pclkdiv_lock & ES_MODE_PLAY2)) {
ensoniq->ctrl &= ~ES_1370_PCLKDIVM;
@@ -955,9 +995,9 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
@@ -972,9 +1012,9 @@ static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * sub
return ptr;
}
-static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
@@ -989,9 +1029,9 @@ static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * sub
return ptr;
}
-static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ensoniq_capture_pointer(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
@@ -1006,7 +1046,7 @@ static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * subst
return ptr;
}
-static snd_pcm_hardware_t snd_ensoniq_playback1 =
+static struct snd_pcm_hardware snd_ensoniq_playback1 =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1033,7 +1073,7 @@ static snd_pcm_hardware_t snd_ensoniq_playback1 =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ensoniq_playback2 =
+static struct snd_pcm_hardware snd_ensoniq_playback2 =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1053,7 +1093,7 @@ static snd_pcm_hardware_t snd_ensoniq_playback2 =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ensoniq_capture =
+static struct snd_pcm_hardware snd_ensoniq_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1072,10 +1112,10 @@ static snd_pcm_hardware_t snd_ensoniq_capture =
.fifo_size = 0,
};
-static int snd_ensoniq_playback1_open(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback1_open(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
ensoniq->mode |= ES_MODE_PLAY1;
ensoniq->playback1_substream = substream;
@@ -1095,10 +1135,10 @@ static int snd_ensoniq_playback1_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_playback2_open(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback2_open(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
ensoniq->mode |= ES_MODE_PLAY2;
ensoniq->playback2_substream = substream;
@@ -1118,10 +1158,10 @@ static int snd_ensoniq_playback2_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_capture_open(snd_pcm_substream_t * substream)
+static int snd_ensoniq_capture_open(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
ensoniq->mode |= ES_MODE_CAPTURE;
ensoniq->capture_substream = substream;
@@ -1137,18 +1177,18 @@ static int snd_ensoniq_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_playback1_close(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback1_close(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
ensoniq->playback1_substream = NULL;
ensoniq->mode &= ~ES_MODE_PLAY1;
return 0;
}
-static int snd_ensoniq_playback2_close(snd_pcm_substream_t * substream)
+static int snd_ensoniq_playback2_close(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
ensoniq->playback2_substream = NULL;
spin_lock_irq(&ensoniq->reg_lock);
@@ -1160,9 +1200,9 @@ static int snd_ensoniq_playback2_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ensoniq_capture_close(snd_pcm_substream_t * substream)
+static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream)
{
- ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
+ struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
ensoniq->capture_substream = NULL;
spin_lock_irq(&ensoniq->reg_lock);
@@ -1174,7 +1214,7 @@ static int snd_ensoniq_capture_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_ensoniq_playback1_ops = {
+static struct snd_pcm_ops snd_ensoniq_playback1_ops = {
.open = snd_ensoniq_playback1_open,
.close = snd_ensoniq_playback1_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1185,7 +1225,7 @@ static snd_pcm_ops_t snd_ensoniq_playback1_ops = {
.pointer = snd_ensoniq_playback1_pointer,
};
-static snd_pcm_ops_t snd_ensoniq_playback2_ops = {
+static struct snd_pcm_ops snd_ensoniq_playback2_ops = {
.open = snd_ensoniq_playback2_open,
.close = snd_ensoniq_playback2_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1196,7 +1236,7 @@ static snd_pcm_ops_t snd_ensoniq_playback2_ops = {
.pointer = snd_ensoniq_playback2_pointer,
};
-static snd_pcm_ops_t snd_ensoniq_capture_ops = {
+static struct snd_pcm_ops snd_ensoniq_capture_ops = {
.open = snd_ensoniq_capture_open,
.close = snd_ensoniq_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1207,16 +1247,10 @@ static snd_pcm_ops_t snd_ensoniq_capture_ops = {
.pointer = snd_ensoniq_capture_pointer,
};
-static void snd_ensoniq_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device,
+ struct snd_pcm ** rpcm)
{
- ensoniq_t *ensoniq = pcm->private_data;
- ensoniq->pcm1 = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_ensoniq_pcm(ensoniq_t * ensoniq, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1237,7 +1271,6 @@ static int __devinit snd_ensoniq_pcm(ensoniq_t * ensoniq, int device, snd_pcm_t
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ensoniq_capture_ops);
pcm->private_data = ensoniq;
- pcm->private_free = snd_ensoniq_pcm_free;
pcm->info_flags = 0;
#ifdef CHIP1370
strcpy(pcm->name, "ES1370 DAC2/ADC");
@@ -1254,16 +1287,10 @@ static int __devinit snd_ensoniq_pcm(ensoniq_t * ensoniq, int device, snd_pcm_t
return 0;
}
-static void snd_ensoniq_pcm_free2(snd_pcm_t *pcm)
+static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device,
+ struct snd_pcm ** rpcm)
{
- ensoniq_t *ensoniq = pcm->private_data;
- ensoniq->pcm2 = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_ensoniq_pcm2(ensoniq_t * ensoniq, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1282,7 +1309,6 @@ static int __devinit snd_ensoniq_pcm2(ensoniq_t * ensoniq, int device, snd_pcm_t
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ensoniq_playback2_ops);
#endif
pcm->private_data = ensoniq;
- pcm->private_free = snd_ensoniq_pcm_free2;
pcm->info_flags = 0;
#ifdef CHIP1370
strcpy(pcm->name, "ES1370 DAC1");
@@ -1307,17 +1333,18 @@ static int __devinit snd_ensoniq_pcm2(ensoniq_t * ensoniq, int device, snd_pcm_t
* ENS1371 mixer (including SPDIF interface)
*/
#ifdef CHIP1371
-static int snd_ens1373_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ens1373_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ens1373_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ens1373_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&ensoniq->reg_lock);
ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff;
ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff;
@@ -1327,10 +1354,10 @@ static int snd_ens1373_spdif_default_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ens1373_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ens1373_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1341,14 +1368,15 @@ static int snd_ens1373_spdif_default_put(snd_kcontrol_t * kcontrol,
spin_lock_irq(&ensoniq->reg_lock);
change = ensoniq->spdif_default != val;
ensoniq->spdif_default = val;
- if (change && ensoniq->playback1_substream == NULL && ensoniq->playback2_substream == NULL)
+ if (change && ensoniq->playback1_substream == NULL &&
+ ensoniq->playback2_substream == NULL)
outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
spin_unlock_irq(&ensoniq->reg_lock);
return change;
}
-static int snd_ens1373_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ens1373_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -1357,10 +1385,10 @@ static int snd_ens1373_spdif_mask_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ens1373_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ens1373_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&ensoniq->reg_lock);
ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff;
ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff;
@@ -1370,10 +1398,10 @@ static int snd_ens1373_spdif_stream_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ens1373_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1384,7 +1412,8 @@ static int snd_ens1373_spdif_stream_put(snd_kcontrol_t * kcontrol,
spin_lock_irq(&ensoniq->reg_lock);
change = ensoniq->spdif_stream != val;
ensoniq->spdif_stream = val;
- if (change && (ensoniq->playback1_substream != NULL || ensoniq->playback2_substream != NULL))
+ if (change && (ensoniq->playback1_substream != NULL ||
+ ensoniq->playback2_substream != NULL))
outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
spin_unlock_irq(&ensoniq->reg_lock);
return change;
@@ -1394,7 +1423,8 @@ static int snd_ens1373_spdif_stream_put(snd_kcontrol_t * kcontrol,
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_es1371_spdif_info, \
.get = snd_es1371_spdif_get, .put = snd_es1371_spdif_put }
-static int snd_es1371_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_es1371_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1403,9 +1433,10 @@ static int snd_es1371_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_es1371_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&ensoniq->reg_lock);
ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0;
@@ -1413,9 +1444,10 @@ static int snd_es1371_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es1371_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
unsigned int nval1, nval2;
int change;
@@ -1435,7 +1467,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 = {
+static struct snd_kcontrol_new snd_es1371_mixer_spdif[] __devinitdata = {
ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1461,7 +1493,8 @@ static snd_kcontrol_new_t snd_es1371_mixer_spdif[] __devinitdata = {
};
-static int snd_es1373_rear_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_es1373_rear_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1470,28 +1503,33 @@ static int snd_es1373_rear_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return 0;
}
-static int snd_es1373_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
int val = 0;
spin_lock_irq(&ensoniq->reg_lock);
- if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26)
+ if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|
+ ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26)
val = 1;
ucontrol->value.integer.value[0] = val;
spin_unlock_irq(&ensoniq->reg_lock);
return 0;
}
-static int snd_es1373_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
unsigned int nval1;
int change;
- nval1 = ucontrol->value.integer.value[0] ? ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
+ nval1 = ucontrol->value.integer.value[0] ?
+ ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
spin_lock_irq(&ensoniq->reg_lock);
- change = (ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1;
+ change = (ensoniq->cssr & (ES_1373_REAR_BIT27|
+ ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1;
ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24);
ensoniq->cssr |= nval1;
outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
@@ -1499,7 +1537,7 @@ static int snd_es1373_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return change;
}
-static snd_kcontrol_new_t snd_ens1373_rear __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_rear __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 2ch->4ch Copy Switch",
@@ -1508,7 +1546,8 @@ static snd_kcontrol_new_t snd_ens1373_rear __devinitdata =
.put = snd_es1373_rear_put,
};
-static int snd_es1373_line_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_es1373_line_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1517,9 +1556,10 @@ static int snd_es1373_line_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return 0;
}
-static int snd_es1373_line_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1373_line_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
int val = 0;
spin_lock_irq(&ensoniq->reg_lock);
@@ -1530,9 +1570,10 @@ static int snd_es1373_line_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_es1373_line_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
int changed;
unsigned int ctrl;
@@ -1549,7 +1590,7 @@ static int snd_es1373_line_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return changed;
}
-static snd_kcontrol_new_t snd_ens1373_line __devinitdata =
+static struct snd_kcontrol_new snd_ens1373_line __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line In->Rear Out Switch",
@@ -1558,9 +1599,9 @@ static snd_kcontrol_new_t snd_ens1373_line __devinitdata =
.put = snd_es1373_line_put,
};
-static void snd_ensoniq_mixer_free_ac97(ac97_t *ac97)
+static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97)
{
- ensoniq_t *ensoniq = ac97->private_data;
+ struct ensoniq *ensoniq = ac97->private_data;
ensoniq->u.es1371.ac97 = NULL;
}
@@ -1577,13 +1618,13 @@ static struct {
{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
};
-static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
+static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line)
{
- snd_card_t *card = ensoniq->card;
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_card *card = ensoniq->card;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int err, idx;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_es1371_codec_write,
.read = snd_es1371_codec_read,
.wait = snd_es1371_codec_wait,
@@ -1599,13 +1640,17 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
return err;
for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
- if (ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
- ensoniq->pci->device == es1371_spdif_present[idx].did &&
- ensoniq->rev == es1371_spdif_present[idx].rev) {
- snd_kcontrol_t *kctl;
+ if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid &&
+ ensoniq->pci->device == es1371_spdif_present[idx].did &&
+ ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) {
+ struct snd_kcontrol *kctl;
int i, index = 0;
- ensoniq->spdif_default = ensoniq->spdif_stream = SNDRV_PCM_DEFAULT_CON_SPDIF;
+ if (has_spdif < 0)
+ break;
+
+ ensoniq->spdif_default = ensoniq->spdif_stream =
+ SNDRV_PCM_DEFAULT_CON_SPDIF;
outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
@@ -1632,7 +1677,8 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
if (((ensoniq->subsystem_vendor_id == 0x1274) &&
(ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */
((ensoniq->subsystem_vendor_id == 0x1458) &&
- (ensoniq->subsystem_device_id == 0xa000))) { /* GA-8IEXP */
+ (ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */
+ has_line > 0) {
err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq));
if (err < 0)
return err;
@@ -1650,7 +1696,8 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
.get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \
.private_value = mask }
-static int snd_ensoniq_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ensoniq_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1659,9 +1706,10 @@ static int snd_ensoniq_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_ensoniq_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
int mask = kcontrol->private_value;
spin_lock_irq(&ensoniq->reg_lock);
@@ -1670,9 +1718,10 @@ static int snd_ensoniq_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_ensoniq_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
+ struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
int mask = kcontrol->private_value;
unsigned int nval;
int change;
@@ -1691,23 +1740,23 @@ static int snd_ensoniq_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
* ENS1370 mixer
*/
-static snd_kcontrol_new_t snd_es1370_controls[2] __devinitdata = {
+static struct snd_kcontrol_new snd_es1370_controls[2] __devinitdata = {
ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),
ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
};
#define ES1370_CONTROLS ARRAY_SIZE(snd_es1370_controls)
-static void snd_ensoniq_mixer_free_ak4531(ak4531_t *ak4531)
+static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531)
{
- ensoniq_t *ensoniq = ak4531->private_data;
+ struct ensoniq *ensoniq = ak4531->private_data;
ensoniq->u.es1370.ak4531 = NULL;
}
-static int __devinit snd_ensoniq_1370_mixer(ensoniq_t * ensoniq)
+static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq)
{
- snd_card_t *card = ensoniq->card;
- ak4531_t ak4531;
+ struct snd_card *card = ensoniq->card;
+ struct snd_ak4531 ak4531;
unsigned int idx;
int err;
@@ -1761,7 +1810,7 @@ static inline int snd_ensoniq_get_joystick_port(int dev)
}
#endif
-static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
+static int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
{
struct gameport *gp;
int io_port;
@@ -1784,7 +1833,8 @@ static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
default:
if (!request_region(io_port, 8, "ens137x: gameport")) {
- printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port);
+ printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n",
+ io_port);
return -EBUSY;
}
break;
@@ -1814,7 +1864,7 @@ static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
return 0;
}
-static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq)
+static void snd_ensoniq_free_gameport(struct ensoniq *ensoniq)
{
if (ensoniq->gameport) {
int port = ensoniq->gameport->io;
@@ -1827,36 +1877,40 @@ static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq)
}
}
#else
-static inline int snd_ensoniq_create_gameport(ensoniq_t *ensoniq, long port) { return -ENOSYS; }
-static inline void snd_ensoniq_free_gameport(ensoniq_t *ensoniq) { }
+static inline int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, long port) { return -ENOSYS; }
+static inline void snd_ensoniq_free_gameport(struct ensoniq *ensoniq) { }
#endif /* SUPPORT_JOYSTICK */
/*
*/
-static void snd_ensoniq_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ensoniq_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ensoniq_t *ensoniq = entry->private_data;
+ struct ensoniq *ensoniq = entry->private_data;
#ifdef CHIP1370
snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n");
#else
snd_iprintf(buffer, "Ensoniq AudioPCI ES1371\n\n");
#endif
- snd_iprintf(buffer, "Joystick enable : %s\n", ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off");
+ snd_iprintf(buffer, "Joystick enable : %s\n",
+ ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off");
#ifdef CHIP1370
- snd_iprintf(buffer, "MIC +5V bias : %s\n", ensoniq->ctrl & ES_1370_XCTL1 ? "on" : "off");
- snd_iprintf(buffer, "Line In to AOUT : %s\n", ensoniq->ctrl & ES_1370_XCTL0 ? "on" : "off");
+ snd_iprintf(buffer, "MIC +5V bias : %s\n",
+ ensoniq->ctrl & ES_1370_XCTL1 ? "on" : "off");
+ snd_iprintf(buffer, "Line In to AOUT : %s\n",
+ ensoniq->ctrl & ES_1370_XCTL0 ? "on" : "off");
#else
- snd_iprintf(buffer, "Joystick port : 0x%x\n", (ES_1371_JOY_ASELI(ensoniq->ctrl) * 8) + 0x200);
+ snd_iprintf(buffer, "Joystick port : 0x%x\n",
+ (ES_1371_JOY_ASELI(ensoniq->ctrl) * 8) + 0x200);
#endif
}
-static void __devinit snd_ensoniq_proc_init(ensoniq_t * ensoniq)
+static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry))
snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read);
@@ -1866,7 +1920,7 @@ static void __devinit snd_ensoniq_proc_init(ensoniq_t * ensoniq)
*/
-static int snd_ensoniq_free(ensoniq_t *ensoniq)
+static int snd_ensoniq_free(struct ensoniq *ensoniq)
{
snd_ensoniq_free_gameport(ensoniq);
if (ensoniq->irq < 0)
@@ -1886,16 +1940,16 @@ static int snd_ensoniq_free(ensoniq_t *ensoniq)
snd_dma_free_pages(&ensoniq->dma_bug);
#endif
if (ensoniq->irq >= 0)
- free_irq(ensoniq->irq, (void *)ensoniq);
+ free_irq(ensoniq->irq, ensoniq);
pci_release_regions(ensoniq->pci);
pci_disable_device(ensoniq->pci);
kfree(ensoniq);
return 0;
}
-static int snd_ensoniq_dev_free(snd_device_t *device)
+static int snd_ensoniq_dev_free(struct snd_device *device)
{
- ensoniq_t *ensoniq = device->device_data;
+ struct ensoniq *ensoniq = device->device_data;
return snd_ensoniq_free(ensoniq);
}
@@ -1924,18 +1978,132 @@ static struct {
};
#endif
-static int __devinit snd_ensoniq_create(snd_card_t * card,
+static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
+{
+#ifdef CHIP1371
+ int idx;
+ struct pci_dev *pci = ensoniq->pci;
+#endif
+ /* this code was part of snd_ensoniq_create before intruduction
+ * of suspend/resume
+ */
+#ifdef CHIP1370
+ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+ outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
+ outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
+ outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
+ outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
+#else
+ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+ outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
+ outl(0, ES_REG(ensoniq, 1371_LEGACY));
+ for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
+ if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
+ pci->device == es1371_ac97_reset_hack[idx].did &&
+ ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
+ outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+ /* need to delay around 20ms(bleech) to give
+ some CODECs enough time to wakeup */
+ msleep(20);
+ break;
+ }
+ /* AC'97 warm reset to start the bitclk */
+ outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
+ inl(ES_REG(ensoniq, CONTROL));
+ udelay(20);
+ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+ /* Init the sample rate converter */
+ snd_es1371_wait_src_ready(ensoniq);
+ outl(ES_1371_SRC_DISABLE, ES_REG(ensoniq, 1371_SMPRATE));
+ for (idx = 0; idx < 0x80; idx++)
+ snd_es1371_src_write(ensoniq, idx, 0);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, 1 << 12);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, 1 << 12);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1, 1 << 12);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2, 1 << 12);
+ snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
+ snd_es1371_adc_rate(ensoniq, 22050);
+ snd_es1371_dac1_rate(ensoniq, 22050);
+ snd_es1371_dac2_rate(ensoniq, 22050);
+ /* WARNING:
+ * enabling the sample rate converter without properly programming
+ * its parameters causes the chip to lock up (the SRC busy bit will
+ * be stuck high, and I've found no way to rectify this other than
+ * power cycle) - Thomas Sailer
+ */
+ snd_es1371_wait_src_ready(ensoniq);
+ outl(0, ES_REG(ensoniq, 1371_SMPRATE));
+ /* try reset codec directly */
+ outl(ES_1371_CODEC_WRITE(0, 0), ES_REG(ensoniq, 1371_CODEC));
+#endif
+ outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
+ outb(0x00, ES_REG(ensoniq, UART_RES));
+ outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
+ synchronize_irq(ensoniq->irq);
+}
+
+#ifdef CONFIG_PM
+static int snd_ensoniq_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct ensoniq *ensoniq = card->private_data;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ snd_pcm_suspend_all(ensoniq->pcm1);
+ snd_pcm_suspend_all(ensoniq->pcm2);
+
+#ifdef CHIP1371
+ snd_ac97_suspend(ensoniq->u.es1371.ac97);
+#else
+ snd_ak4531_suspend(ensoniq->u.es1370.ak4531);
+#endif
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_ensoniq_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct ensoniq *ensoniq = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_ensoniq_chip_init(ensoniq);
+
+#ifdef CHIP1371
+ snd_ac97_resume(ensoniq->u.es1371.ac97);
+#else
+ snd_ak4531_resume(ensoniq->u.es1370.ak4531);
+#endif
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+static int __devinit snd_ensoniq_create(struct snd_card *card,
struct pci_dev *pci,
- ensoniq_t ** rensoniq)
+ struct ensoniq ** rensoniq)
{
- ensoniq_t *ensoniq;
+ struct ensoniq *ensoniq;
unsigned short cmdw;
unsigned char cmdb;
#ifdef CHIP1371
int idx;
#endif
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ensoniq_dev_free,
};
@@ -1958,7 +2126,8 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
return err;
}
ensoniq->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) {
+ if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "Ensoniq AudioPCI", ensoniq)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_ensoniq_free(ensoniq);
return -EBUSY;
@@ -1981,17 +2150,12 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
ensoniq->subsystem_device_id = cmdw;
#ifdef CHIP1370
#if 0
- ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
+ ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
+ ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
#else /* get microphone working */
ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));
#endif
ensoniq->sctrl = 0;
- /* initialize the chips */
- outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
- outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME));
- outl(0, ES_REG(ensoniq, PHANTOM_COUNT));
#else
ensoniq->ctrl = 0;
ensoniq->sctrl = 0;
@@ -2002,59 +2166,16 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */
break;
}
- /* initialize the chips */
- outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
- outl(0, ES_REG(ensoniq, 1371_LEGACY));
for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
pci->device == es1371_ac97_reset_hack[idx].did &&
ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
ensoniq->cssr |= ES_1371_ST_AC97_RST;
- outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
- /* need to delay around 20ms(bleech) to give
- some CODECs enough time to wakeup */
- msleep(20);
break;
}
- /* AC'97 warm reset to start the bitclk */
- outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
- inl(ES_REG(ensoniq, CONTROL));
- udelay(20);
- outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- /* Init the sample rate converter */
- snd_es1371_wait_src_ready(ensoniq);
- outl(ES_1371_SRC_DISABLE, ES_REG(ensoniq, 1371_SMPRATE));
- for (idx = 0; idx < 0x80; idx++)
- snd_es1371_src_write(ensoniq, idx, 0);
- snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_TRUNC_N, 16 << 4);
- snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS, 16 << 10);
- snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_TRUNC_N, 16 << 4);
- snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS, 16 << 10);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, 1 << 12);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, 1 << 12);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1, 1 << 12);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC1 + 1, 1 << 12);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2, 1 << 12);
- snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_DAC2 + 1, 1 << 12);
- snd_es1371_adc_rate(ensoniq, 22050);
- snd_es1371_dac1_rate(ensoniq, 22050);
- snd_es1371_dac2_rate(ensoniq, 22050);
- /* WARNING:
- * enabling the sample rate converter without properly programming
- * its parameters causes the chip to lock up (the SRC busy bit will
- * be stuck high, and I've found no way to rectify this other than
- * power cycle) - Thomas Sailer
- */
- snd_es1371_wait_src_ready(ensoniq);
- outl(0, ES_REG(ensoniq, 1371_SMPRATE));
- /* try reset codec directly */
- outl(ES_1371_CODEC_WRITE(0, 0), ES_REG(ensoniq, 1371_CODEC));
#endif
- outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
- outb(0x00, ES_REG(ensoniq, UART_RES));
- outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
- synchronize_irq(ensoniq->irq);
+
+ snd_ensoniq_chip_init(ensoniq);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ensoniq, &ops)) < 0) {
snd_ensoniq_free(ensoniq);
@@ -2073,9 +2194,9 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
* MIDI section
*/
-static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
+static void snd_ensoniq_midi_interrupt(struct ensoniq * ensoniq)
{
- snd_rawmidi_t * rmidi = ensoniq->rmidi;
+ struct snd_rawmidi *rmidi = ensoniq->rmidi;
unsigned char status, mask, byte;
if (rmidi == NULL)
@@ -2110,9 +2231,9 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
spin_unlock(&ensoniq->reg_lock);
}
-static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_ensoniq_midi_input_open(struct snd_rawmidi_substream *substream)
{
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
spin_lock_irq(&ensoniq->reg_lock);
ensoniq->uartm |= ES_MODE_INPUT;
@@ -2126,9 +2247,9 @@ static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_ensoniq_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_ensoniq_midi_input_close(struct snd_rawmidi_substream *substream)
{
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
spin_lock_irq(&ensoniq->reg_lock);
if (!(ensoniq->uartm & ES_MODE_OUTPUT)) {
@@ -2143,9 +2264,9 @@ static int snd_ensoniq_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_ensoniq_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_ensoniq_midi_output_open(struct snd_rawmidi_substream *substream)
{
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
spin_lock_irq(&ensoniq->reg_lock);
ensoniq->uartm |= ES_MODE_OUTPUT;
@@ -2159,9 +2280,9 @@ static int snd_ensoniq_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_ensoniq_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_ensoniq_midi_output_close(struct snd_rawmidi_substream *substream)
{
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
spin_lock_irq(&ensoniq->reg_lock);
if (!(ensoniq->uartm & ES_MODE_INPUT)) {
@@ -2176,10 +2297,10 @@ static int snd_ensoniq_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static void snd_ensoniq_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_ensoniq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
int idx;
spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2200,10 +2321,10 @@ static void snd_ensoniq_midi_input_trigger(snd_rawmidi_substream_t * substream,
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
-static void snd_ensoniq_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_ensoniq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
unsigned long flags;
- ensoniq_t *ensoniq = substream->rmidi->private_data;
+ struct ensoniq *ensoniq = substream->rmidi->private_data;
unsigned char byte;
spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2230,23 +2351,24 @@ static void snd_ensoniq_midi_output_trigger(snd_rawmidi_substream_t * substream,
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
-static snd_rawmidi_ops_t snd_ensoniq_midi_output =
+static struct snd_rawmidi_ops snd_ensoniq_midi_output =
{
.open = snd_ensoniq_midi_output_open,
.close = snd_ensoniq_midi_output_close,
.trigger = snd_ensoniq_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_ensoniq_midi_input =
+static struct snd_rawmidi_ops snd_ensoniq_midi_input =
{
.open = snd_ensoniq_midi_input_open,
.close = snd_ensoniq_midi_input_close,
.trigger = snd_ensoniq_midi_input_trigger,
};
-static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmidi_t **rrawmidi)
+static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device,
+ struct snd_rawmidi **rrawmidi)
{
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
int err;
if (rrawmidi)
@@ -2260,7 +2382,8 @@ static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmi
#endif
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input);
- rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
+ rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
rmidi->private_data = ensoniq;
ensoniq->rmidi = rmidi;
if (rrawmidi)
@@ -2274,7 +2397,7 @@ static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmi
static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ensoniq_t *ensoniq = dev_id;
+ struct ensoniq *ensoniq = dev_id;
unsigned int status, sctrl;
if (ensoniq == NULL)
@@ -2311,8 +2434,8 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- ensoniq_t *ensoniq;
+ struct snd_card *card;
+ struct ensoniq *ensoniq;
int err, pcm_devs[2];
if (dev >= SNDRV_CARDS)
@@ -2330,6 +2453,7 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = ensoniq;
pcm_devs[0] = 0; pcm_devs[1] = 1;
#ifdef CHIP1370
@@ -2339,7 +2463,7 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci,
}
#endif
#ifdef CHIP1371
- if ((err = snd_ensoniq_1371_mixer(ensoniq)) < 0) {
+ if ((err = snd_ensoniq_1371_mixer(ensoniq, spdif[dev], lineio[dev])) < 0) {
snd_card_free(card);
return err;
}
@@ -2389,6 +2513,10 @@ static struct pci_driver driver = {
.id_table = snd_audiopci_ids,
.probe = snd_audiopci_probe,
.remove = __devexit_p(snd_audiopci_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_ensoniq_suspend,
+ .resume = snd_ensoniq_resume,
+#endif
};
static int __init alsa_card_ens137x_init(void)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index c134f48152b0..0d556b09ad04 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -191,11 +191,9 @@ MODULE_PARM_DESC(enable, "Enable ESS Solo-1 soundcard.");
*/
-typedef struct _snd_es1938 es1938_t;
-
#define SAVED_REG_SIZE 32 /* max. number of registers to save */
-struct _snd_es1938 {
+struct es1938 {
int irq;
unsigned long io_port;
@@ -208,19 +206,18 @@ struct _snd_es1938 {
unsigned char irqmask;
unsigned char revision;
- snd_kcontrol_t *hw_volume;
- snd_kcontrol_t *hw_switch;
- snd_kcontrol_t *master_volume;
- snd_kcontrol_t *master_switch;
+ struct snd_kcontrol *hw_volume;
+ struct snd_kcontrol *hw_switch;
+ struct snd_kcontrol *master_volume;
+ struct snd_kcontrol *master_switch;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *capture_substream;
- snd_pcm_substream_t *playback1_substream;
- snd_pcm_substream_t *playback2_substream;
- snd_kmixer_t *mixer;
- snd_rawmidi_t *rmidi;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_pcm_substream *playback1_substream;
+ struct snd_pcm_substream *playback2_substream;
+ struct snd_rawmidi *rmidi;
unsigned int dma1_size;
unsigned int dma2_size;
@@ -232,7 +229,7 @@ struct _snd_es1938 {
spinlock_t reg_lock;
spinlock_t mixer_lock;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
@@ -259,7 +256,7 @@ MODULE_DEVICE_TABLE(pci, snd_es1938_ids);
/* -----------------------------------------------------------------
* Write to a mixer register
* -----------------------------------------------------------------*/
-static void snd_es1938_mixer_write(es1938_t *chip, unsigned char reg, unsigned char val)
+static void snd_es1938_mixer_write(struct es1938 *chip, unsigned char reg, unsigned char val)
{
unsigned long flags;
spin_lock_irqsave(&chip->mixer_lock, flags);
@@ -274,7 +271,7 @@ static void snd_es1938_mixer_write(es1938_t *chip, unsigned char reg, unsigned c
/* -----------------------------------------------------------------
* Read from a mixer register
* -----------------------------------------------------------------*/
-static int snd_es1938_mixer_read(es1938_t *chip, unsigned char reg)
+static int snd_es1938_mixer_read(struct es1938 *chip, unsigned char reg)
{
int data;
unsigned long flags;
@@ -291,7 +288,8 @@ static int snd_es1938_mixer_read(es1938_t *chip, unsigned char reg)
/* -----------------------------------------------------------------
* Write to some bits of a mixer register (return old value)
* -----------------------------------------------------------------*/
-static int snd_es1938_mixer_bits(es1938_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+static int snd_es1938_mixer_bits(struct es1938 *chip, unsigned char reg,
+ unsigned char mask, unsigned char val)
{
unsigned long flags;
unsigned char old, new, oval;
@@ -314,7 +312,7 @@ static int snd_es1938_mixer_bits(es1938_t *chip, unsigned char reg, unsigned cha
/* -----------------------------------------------------------------
* Write command to Controller Registers
* -----------------------------------------------------------------*/
-static void snd_es1938_write_cmd(es1938_t *chip, unsigned char cmd)
+static void snd_es1938_write_cmd(struct es1938 *chip, unsigned char cmd)
{
int i;
unsigned char v;
@@ -330,7 +328,7 @@ static void snd_es1938_write_cmd(es1938_t *chip, unsigned char cmd)
/* -----------------------------------------------------------------
* Read the Read Data Buffer
* -----------------------------------------------------------------*/
-static int snd_es1938_get_byte(es1938_t *chip)
+static int snd_es1938_get_byte(struct es1938 *chip)
{
int i;
unsigned char v;
@@ -344,7 +342,7 @@ static int snd_es1938_get_byte(es1938_t *chip)
/* -----------------------------------------------------------------
* Write value cmd register
* -----------------------------------------------------------------*/
-static void snd_es1938_write(es1938_t *chip, unsigned char reg, unsigned char val)
+static void snd_es1938_write(struct es1938 *chip, unsigned char reg, unsigned char val)
{
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -359,7 +357,7 @@ static void snd_es1938_write(es1938_t *chip, unsigned char reg, unsigned char va
/* -----------------------------------------------------------------
* Read data from cmd register and return it
* -----------------------------------------------------------------*/
-static unsigned char snd_es1938_read(es1938_t *chip, unsigned char reg)
+static unsigned char snd_es1938_read(struct es1938 *chip, unsigned char reg)
{
unsigned char val;
unsigned long flags;
@@ -377,7 +375,8 @@ static unsigned char snd_es1938_read(es1938_t *chip, unsigned char reg)
/* -----------------------------------------------------------------
* Write data to cmd register and return old value
* -----------------------------------------------------------------*/
-static int snd_es1938_bits(es1938_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+static int snd_es1938_bits(struct es1938 *chip, unsigned char reg, unsigned char mask,
+ unsigned char val)
{
unsigned long flags;
unsigned char old, new, oval;
@@ -402,7 +401,7 @@ static int snd_es1938_bits(es1938_t *chip, unsigned char reg, unsigned char mask
/* --------------------------------------------------------------------
* Reset the chip
* --------------------------------------------------------------------*/
-static void snd_es1938_reset(es1938_t *chip)
+static void snd_es1938_reset(struct es1938 *chip)
{
int i;
@@ -441,13 +440,13 @@ static void snd_es1938_reset(es1938_t *chip)
/* --------------------------------------------------------------------
* Reset the FIFOs
* --------------------------------------------------------------------*/
-static void snd_es1938_reset_fifo(es1938_t *chip)
+static void snd_es1938_reset_fifo(struct es1938 *chip)
{
outb(2, SLSB_REG(chip, RESET));
outb(0, SLSB_REG(chip, RESET));
}
-static ratnum_t clocks[2] = {
+static struct snd_ratnum clocks[2] = {
{
.num = 793800,
.den_min = 1,
@@ -462,18 +461,18 @@ static ratnum_t clocks[2] = {
}
};
-static snd_pcm_hw_constraint_ratnums_t hw_constraints_clocks = {
+static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = {
.nrats = 2,
.rats = clocks,
};
-static void snd_es1938_rate_set(es1938_t *chip,
- snd_pcm_substream_t *substream,
+static void snd_es1938_rate_set(struct es1938 *chip,
+ struct snd_pcm_substream *substream,
int mode)
{
unsigned int bits, div0;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->rate_num == clocks[0].num)
bits = 128 - runtime->rate_den;
else
@@ -495,7 +494,7 @@ static void snd_es1938_rate_set(es1938_t *chip,
* Configure Solo1 builtin DMA Controller
* --------------------------------------------------------------------*/
-static void snd_es1938_playback1_setdma(es1938_t *chip)
+static void snd_es1938_playback1_setdma(struct es1938 *chip)
{
outb(0x00, SLIO_REG(chip, AUDIO2MODE));
outl(chip->dma2_start, SLIO_REG(chip, AUDIO2DMAADDR));
@@ -503,7 +502,7 @@ static void snd_es1938_playback1_setdma(es1938_t *chip)
outw(chip->dma2_size, SLIO_REG(chip, AUDIO2DMACOUNT));
}
-static void snd_es1938_playback2_setdma(es1938_t *chip)
+static void snd_es1938_playback2_setdma(struct es1938 *chip)
{
/* Enable DMA controller */
outb(0xc4, SLDM_REG(chip, DMACOMMAND));
@@ -518,7 +517,7 @@ static void snd_es1938_playback2_setdma(es1938_t *chip)
outb(0, SLDM_REG(chip, DMAMASK));
}
-static void snd_es1938_capture_setdma(es1938_t *chip)
+static void snd_es1938_capture_setdma(struct es1938 *chip)
{
/* Enable DMA controller */
outb(0xc4, SLDM_REG(chip, DMACOMMAND));
@@ -538,10 +537,10 @@ static void snd_es1938_capture_setdma(es1938_t *chip)
* *** PCM part ***
*/
-static int snd_es1938_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_es1938_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
int val;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -561,10 +560,10 @@ static int snd_es1938_capture_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_es1938_playback1_trigger(snd_pcm_substream_t * substream,
+static int snd_es1938_playback1_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
@@ -591,10 +590,10 @@ static int snd_es1938_playback1_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_es1938_playback2_trigger(snd_pcm_substream_t * substream,
+static int snd_es1938_playback2_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
int val;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -614,7 +613,7 @@ static int snd_es1938_playback2_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_es1938_playback_trigger(snd_pcm_substream_t *substream,
+static int snd_es1938_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
switch (substream->number) {
@@ -630,10 +629,10 @@ static int snd_es1938_playback_trigger(snd_pcm_substream_t *substream,
/* --------------------------------------------------------------------
* First channel for Extended Mode Audio 1 ADC Operation
* --------------------------------------------------------------------*/
-static int snd_es1938_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_es1938_capture_prepare(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int u, is8, mono;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -678,10 +677,10 @@ static int snd_es1938_capture_prepare(snd_pcm_substream_t * substream)
/* ------------------------------------------------------------------------------
* Second Audio channel DAC Operation
* ------------------------------------------------------------------------------*/
-static int snd_es1938_playback1_prepare(snd_pcm_substream_t * substream)
+static int snd_es1938_playback1_prepare(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int u, is8, mono;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -706,7 +705,8 @@ static int snd_es1938_playback1_prepare(snd_pcm_substream_t * substream)
snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2TCOUNTH, count >> 8);
/* initialize and configure Audio 2 DAC */
- snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL2, 0x40 | (u ? 0 : 4) | (mono ? 0 : 2) | (is8 ? 0 : 1));
+ snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL2, 0x40 | (u ? 0 : 4) |
+ (mono ? 0 : 2) | (is8 ? 0 : 1));
/* program DMA */
snd_es1938_playback1_setdma(chip);
@@ -714,10 +714,10 @@ static int snd_es1938_playback1_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1938_playback2_prepare(snd_pcm_substream_t * substream)
+static int snd_es1938_playback2_prepare(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int u, is8, mono;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -756,7 +756,7 @@ static int snd_es1938_playback2_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1938_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_es1938_playback_prepare(struct snd_pcm_substream *substream)
{
switch (substream->number) {
case 0:
@@ -768,9 +768,9 @@ static int snd_es1938_playback_prepare(snd_pcm_substream_t *substream)
return -EINVAL;
}
-static snd_pcm_uframes_t snd_es1938_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es1938_capture_pointer(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
size_t old, new;
#if 1
@@ -785,9 +785,9 @@ static snd_pcm_uframes_t snd_es1938_capture_pointer(snd_pcm_substream_t * substr
return ptr >> chip->dma1_shift;
}
-static snd_pcm_uframes_t snd_es1938_playback1_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es1938_playback1_pointer(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
#if 1
ptr = chip->dma2_size - inw(SLIO_REG(chip, AUDIO2DMACOUNT));
@@ -797,9 +797,9 @@ static snd_pcm_uframes_t snd_es1938_playback1_pointer(snd_pcm_substream_t * subs
return ptr >> chip->dma2_shift;
}
-static snd_pcm_uframes_t snd_es1938_playback2_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_es1938_playback2_pointer(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
size_t old, new;
#if 1
@@ -814,7 +814,7 @@ static snd_pcm_uframes_t snd_es1938_playback2_pointer(snd_pcm_substream_t * subs
return ptr >> chip->dma1_shift;
}
-static snd_pcm_uframes_t snd_es1938_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *substream)
{
switch (substream->number) {
case 0:
@@ -826,14 +826,14 @@ static snd_pcm_uframes_t snd_es1938_playback_pointer(snd_pcm_substream_t *substr
return -EINVAL;
}
-static int snd_es1938_capture_copy(snd_pcm_substream_t *substream,
+static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,
int channel,
snd_pcm_uframes_t pos,
void __user *dst,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
pos <<= chip->dma1_shift;
count <<= chip->dma1_shift;
snd_assert(pos + count <= chip->dma1_size, return -EINVAL);
@@ -852,8 +852,8 @@ static int snd_es1938_capture_copy(snd_pcm_substream_t *substream,
/*
* buffer management
*/
-static int snd_es1938_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_es1938_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int err;
@@ -863,7 +863,7 @@ static int snd_es1938_pcm_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_es1938_pcm_hw_free(snd_pcm_substream_t *substream)
+static int snd_es1938_pcm_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
@@ -871,11 +871,12 @@ static int snd_es1938_pcm_hw_free(snd_pcm_substream_t *substream)
/* ----------------------------------------------------------------------
* Audio1 Capture (ADC)
* ----------------------------------------------------------------------*/
-static snd_pcm_hardware_t snd_es1938_capture =
+static struct snd_pcm_hardware snd_es1938_capture =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER),
- .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE,
+ .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,
.rate_min = 6000,
.rate_max = 48000,
@@ -892,12 +893,13 @@ static snd_pcm_hardware_t snd_es1938_capture =
/* -----------------------------------------------------------------------
* Audio2 Playback (DAC)
* -----------------------------------------------------------------------*/
-static snd_pcm_hardware_t snd_es1938_playback =
+static struct snd_pcm_hardware snd_es1938_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE,
+ .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,
.rate_min = 6000,
.rate_max = 48000,
@@ -911,10 +913,10 @@ static snd_pcm_hardware_t snd_es1938_playback =
.fifo_size = 256,
};
-static int snd_es1938_capture_open(snd_pcm_substream_t * substream)
+static int snd_es1938_capture_open(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (chip->playback2_substream)
return -EAGAIN;
@@ -926,10 +928,10 @@ static int snd_es1938_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1938_playback_open(snd_pcm_substream_t * substream)
+static int snd_es1938_playback_open(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
switch (substream->number) {
case 0:
@@ -951,17 +953,17 @@ static int snd_es1938_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1938_capture_close(snd_pcm_substream_t * substream)
+static int snd_es1938_capture_close(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
return 0;
}
-static int snd_es1938_playback_close(snd_pcm_substream_t * substream)
+static int snd_es1938_playback_close(struct snd_pcm_substream *substream)
{
- es1938_t *chip = snd_pcm_substream_chip(substream);
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
switch (substream->number) {
case 0:
@@ -977,7 +979,7 @@ static int snd_es1938_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_es1938_playback_ops = {
+static struct snd_pcm_ops snd_es1938_playback_ops = {
.open = snd_es1938_playback_open,
.close = snd_es1938_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -988,7 +990,7 @@ static snd_pcm_ops_t snd_es1938_playback_ops = {
.pointer = snd_es1938_playback_pointer,
};
-static snd_pcm_ops_t snd_es1938_capture_ops = {
+static struct snd_pcm_ops snd_es1938_capture_ops = {
.open = snd_es1938_capture_open,
.close = snd_es1938_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1000,14 +1002,9 @@ static snd_pcm_ops_t snd_es1938_capture_ops = {
.copy = snd_es1938_capture_copy,
};
-static void snd_es1938_free_pcm(snd_pcm_t *pcm)
+static int __devinit snd_es1938_new_pcm(struct es1938 *chip, int device)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm)) < 0)
@@ -1016,7 +1013,6 @@ static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es1938_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_es1938_free_pcm;
pcm->info_flags = 0;
strcpy(pcm->name, "ESS Solo-1");
@@ -1032,7 +1028,8 @@ static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device)
* *** Mixer part ***
*/
-static int snd_es1938_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[8] = {
"Mic", "Mic Master", "CD", "AOUT",
@@ -1048,16 +1045,18 @@ static int snd_es1938_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_es1938_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = snd_es1938_mixer_read(chip, 0x1c) & 0x07;
return 0;
}
-static int snd_es1938_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_put_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
unsigned char val = ucontrol->value.enumerated.item[0];
if (val > 7)
@@ -1065,7 +1064,8 @@ static int snd_es1938_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return snd_es1938_mixer_bits(chip, 0x1c, 0x07, val) != val;
}
-static int snd_es1938_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_spatializer_enable(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1074,17 +1074,19 @@ static int snd_es1938_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_es1938_get_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_spatializer_enable(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
unsigned char val = snd_es1938_mixer_read(chip, 0x50);
ucontrol->value.integer.value[0] = !!(val & 8);
return 0;
}
-static int snd_es1938_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_put_spatializer_enable(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
unsigned char oval, nval;
int change;
nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04;
@@ -1097,7 +1099,8 @@ static int snd_es1938_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_
return change;
}
-static int snd_es1938_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_hw_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1106,15 +1109,17 @@ static int snd_es1938_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_es1938_get_hw_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_hw_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = snd_es1938_mixer_read(chip, 0x61) & 0x3f;
ucontrol->value.integer.value[1] = snd_es1938_mixer_read(chip, 0x63) & 0x3f;
return 0;
}
-static int snd_es1938_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_hw_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -1123,24 +1128,25 @@ static int snd_es1938_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_es1938_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_hw_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = !(snd_es1938_mixer_read(chip, 0x61) & 0x40);
ucontrol->value.integer.value[1] = !(snd_es1938_mixer_read(chip, 0x63) & 0x40);
return 0;
}
-static void snd_es1938_hwv_free(snd_kcontrol_t *kcontrol)
+static void snd_es1938_hwv_free(struct snd_kcontrol *kcontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
chip->master_volume = NULL;
chip->master_switch = NULL;
chip->hw_volume = NULL;
chip->hw_switch = NULL;
}
-static int snd_es1938_reg_bits(es1938_t *chip, unsigned char reg,
+static int snd_es1938_reg_bits(struct es1938 *chip, unsigned char reg,
unsigned char mask, unsigned char val)
{
if (reg < 0xa0)
@@ -1149,7 +1155,7 @@ static int snd_es1938_reg_bits(es1938_t *chip, unsigned char reg,
return snd_es1938_bits(chip, reg, mask, val);
}
-static int snd_es1938_reg_read(es1938_t *chip, unsigned char reg)
+static int snd_es1938_reg_read(struct es1938 *chip, unsigned char reg)
{
if (reg < 0xa0)
return snd_es1938_mixer_read(chip, reg);
@@ -1163,7 +1169,8 @@ static int snd_es1938_reg_read(es1938_t *chip, unsigned char reg)
.get = snd_es1938_get_single, .put = snd_es1938_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_es1938_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1174,9 +1181,10 @@ static int snd_es1938_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es1938_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1190,9 +1198,10 @@ static int snd_es1938_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es1938_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1213,7 +1222,8 @@ static int snd_es1938_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_es1938_get_double, .put = snd_es1938_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_es1938_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_es1938_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1224,9 +1234,10 @@ static int snd_es1938_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_es1938_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1249,9 +1260,10 @@ static int snd_es1938_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_es1938_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_es1938_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- es1938_t *chip = snd_kcontrol_chip(kcontrol);
+ struct es1938 *chip = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1284,7 +1296,7 @@ static int snd_es1938_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static snd_kcontrol_new_t snd_es1938_controls[] = {
+static struct snd_kcontrol_new snd_es1938_controls[] = {
ES1938_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
{
@@ -1347,7 +1359,7 @@ ES1938_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0)
/*
* initialize the chip - used by resume callback, too
*/
-static void snd_es1938_chip_init(es1938_t *chip)
+static void snd_es1938_chip_init(struct es1938 *chip)
{
/* reset chip */
snd_es1938_reset(chip);
@@ -1386,11 +1398,13 @@ static unsigned char saved_regs[SAVED_REG_SIZE+1] = {
};
-static int es1938_suspend(snd_card_t *card, pm_message_t state)
+static int es1938_suspend(struct pci_dev *pci, pm_message_t state)
{
- es1938_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct es1938 *chip = card->private_data;
unsigned char *s, *d;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
/* save mixer-related registers */
@@ -1399,20 +1413,23 @@ static int es1938_suspend(snd_card_t *card, pm_message_t state)
outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
- pci_disable_device(chip->pci);
+ free_irq(chip->irq, chip);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int es1938_resume(snd_card_t *card)
+static int es1938_resume(struct pci_dev *pci)
{
- es1938_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct es1938 *chip = card->private_data;
unsigned char *s, *d;
- pci_enable_device(chip->pci);
- request_irq(chip->pci->irq, snd_es1938_interrupt,
- SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip);
- chip->irq = chip->pci->irq;
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ request_irq(pci->irq, snd_es1938_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, "ES1938", chip);
+ chip->irq = pci->irq;
snd_es1938_chip_init(chip);
/* restore mixer-related registers */
@@ -1423,12 +1440,13 @@ static int es1938_resume(snd_card_t *card)
snd_es1938_write(chip, *s, *d);
}
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_es1938_create_gameport(es1938_t *chip)
+static int __devinit snd_es1938_create_gameport(struct es1938 *chip)
{
struct gameport *gp;
@@ -1448,7 +1466,7 @@ static int __devinit snd_es1938_create_gameport(es1938_t *chip)
return 0;
}
-static void snd_es1938_free_gameport(es1938_t *chip)
+static void snd_es1938_free_gameport(struct es1938 *chip)
{
if (chip->gameport) {
gameport_unregister_port(chip->gameport);
@@ -1456,11 +1474,11 @@ static void snd_es1938_free_gameport(es1938_t *chip)
}
}
#else
-static inline int snd_es1938_create_gameport(es1938_t *chip) { return -ENOSYS; }
-static inline void snd_es1938_free_gameport(es1938_t *chip) { }
+static inline int snd_es1938_create_gameport(struct es1938 *chip) { return -ENOSYS; }
+static inline void snd_es1938_free_gameport(struct es1938 *chip) { }
#endif /* SUPPORT_JOYSTICK */
-static int snd_es1938_free(es1938_t *chip)
+static int snd_es1938_free(struct es1938 *chip)
{
/* disable irqs */
outb(0x00, SLIO_REG(chip, IRQCONTROL));
@@ -1470,26 +1488,26 @@ static int snd_es1938_free(es1938_t *chip)
snd_es1938_free_gameport(chip);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
-static int snd_es1938_dev_free(snd_device_t *device)
+static int snd_es1938_dev_free(struct snd_device *device)
{
- es1938_t *chip = device->device_data;
+ struct es1938 *chip = device->device_data;
return snd_es1938_free(chip);
}
-static int __devinit snd_es1938_create(snd_card_t * card,
+static int __devinit snd_es1938_create(struct snd_card *card,
struct pci_dev * pci,
- es1938_t ** rchip)
+ struct es1938 ** rchip)
{
- es1938_t *chip;
+ struct es1938 *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_es1938_dev_free,
};
@@ -1525,7 +1543,8 @@ static int __devinit snd_es1938_create(snd_card_t * card,
chip->vc_port = pci_resource_start(pci, 2);
chip->mpu_port = pci_resource_start(pci, 3);
chip->game_port = pci_resource_start(pci, 4);
- if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip)) {
+ if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "ES1938", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_es1938_free(chip);
return -EBUSY;
@@ -1540,8 +1559,6 @@ static int __devinit snd_es1938_create(snd_card_t * card,
snd_es1938_chip_init(chip);
- snd_card_set_pm_callback(card, es1938_suspend, es1938_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_es1938_free(chip);
return err;
@@ -1558,7 +1575,7 @@ static int __devinit snd_es1938_create(snd_card_t * card,
* -------------------------------------------------------------------- */
static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- es1938_t *chip = dev_id;
+ struct es1938 *chip = dev_id;
unsigned char status, audiostatus;
int handled = 0;
@@ -1571,9 +1588,12 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r
if (status & 0x10) {
#if 0
printk("Es1938debug - AUDIO channel 1 interrupt\n");
- printk("Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n", inw(SLDM_REG(chip, DMACOUNT)));
- printk("Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n", inl(SLDM_REG(chip, DMAADDR)));
- printk("Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n", inl(SLDM_REG(chip, DMASTATUS)));
+ printk("Es1938debug - AUDIO channel 1 DMAC DMA count: %u\n",
+ inw(SLDM_REG(chip, DMACOUNT)));
+ printk("Es1938debug - AUDIO channel 1 DMAC DMA base: %u\n",
+ inl(SLDM_REG(chip, DMAADDR)));
+ printk("Es1938debug - AUDIO channel 1 DMAC DMA status: 0x%x\n",
+ inl(SLDM_REG(chip, DMASTATUS)));
#endif
/* clear irq */
handled = 1;
@@ -1588,8 +1608,10 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r
if (status & 0x20) {
#if 0
printk("Es1938debug - AUDIO channel 2 interrupt\n");
- printk("Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n", inw(SLIO_REG(chip, AUDIO2DMACOUNT)));
- printk("Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n", inl(SLIO_REG(chip, AUDIO2DMAADDR)));
+ printk("Es1938debug - AUDIO channel 2 DMAC DMA count: %u\n",
+ inw(SLIO_REG(chip, AUDIO2DMACOUNT)));
+ printk("Es1938debug - AUDIO channel 2 DMAC DMA base: %u\n",
+ inl(SLIO_REG(chip, AUDIO2DMAADDR)));
#endif
/* clear irq */
@@ -1606,8 +1628,10 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
if (!split) {
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
- snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_switch->id);
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_volume->id);
}
/* ack interrupt */
snd_es1938_mixer_write(chip, 0x66, 0x00);
@@ -1629,9 +1653,9 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r
#define ES1938_DMA_SIZE 64
-static int __devinit snd_es1938_mixer(es1938_t *chip)
+static int __devinit snd_es1938_mixer(struct es1938 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
unsigned int idx;
int err;
@@ -1640,7 +1664,7 @@ static int __devinit snd_es1938_mixer(es1938_t *chip)
strcpy(card->mixername, "ESS Solo-1");
for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es1938_controls[idx], chip);
switch (idx) {
case 0:
@@ -1671,9 +1695,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- es1938_t *chip;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct es1938 *chip;
+ struct snd_opl3 *opl3;
int idx, err;
if (dev >= SNDRV_CARDS)
@@ -1697,6 +1721,7 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
strcpy(card->driver, "ES1938");
strcpy(card->shortname, "ESS ES1938 (Solo-1)");
@@ -1761,7 +1786,10 @@ static struct pci_driver driver = {
.id_table = snd_es1938_ids,
.probe = snd_es1938_probe,
.remove = __devexit_p(snd_es1938_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = es1938_suspend,
+ .resume = es1938_resume,
+#endif
};
static int __init alsa_card_es1938_init(void)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 50079dc90743..3747a436f0cd 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -176,7 +176,7 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
/* Values for the ESM_LEGACY_AUDIO_CONTROL */
-#define ESS_ENABLE_AUDIO 0x8000
+#define ESS_DISABLE_AUDIO 0x8000
#define ESS_ENABLE_SERIAL_IRQ 0x4000
#define IO_ADRESS_ALIAS 0x0020
#define MPU401_IRQ_ENABLE 0x0010
@@ -195,7 +195,7 @@ MODULE_PARM_DESC(joystick, "Enable joystick.");
#define DMA_TDMA 0x0100
#define DMA_PCPCI 0x0200
#define POST_WRITE 0x0080
-#define ISA_TIMING 0x0040
+#define PCI_TIMING 0x0040
#define SWAP_LR 0x0020
#define SUBTR_DECODE 0x0002
@@ -470,10 +470,6 @@ static u16 acpi_state_mask[] = {
};
-typedef struct snd_es1968 es1968_t;
-typedef struct snd_esschan esschan_t;
-typedef struct snd_esm_memory esm_memory_t;
-
/* APU use in the driver */
enum snd_enum_apu_type {
ESM_APU_PCM_PLAY,
@@ -488,23 +484,23 @@ enum {
};
/* DMA Hack! */
-struct snd_esm_memory {
+struct esm_memory {
struct snd_dma_buffer buf;
int empty; /* status */
struct list_head list;
};
/* Playback Channel */
-struct snd_esschan {
+struct esschan {
int running;
u8 apu[4];
u8 apu_mode[4];
/* playback/capture pcm buffer */
- esm_memory_t *memory;
+ struct esm_memory *memory;
/* capture mixer buffer */
- esm_memory_t *mixbuf;
+ struct esm_memory *mixbuf;
unsigned int hwptr; /* current hw pointer in bytes */
unsigned int count; /* sample counter in bytes */
@@ -519,7 +515,7 @@ struct snd_esschan {
int bob_freq; /* required timer frequency */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
/* linked list */
struct list_head list;
@@ -529,7 +525,7 @@ struct snd_esschan {
#endif
};
-struct snd_es1968 {
+struct es1968 {
/* Module Config */
int total_bufsize; /* in bytes */
@@ -550,19 +546,19 @@ struct snd_es1968 {
unsigned long io_port;
int type;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
int do_pm; /* power-management enabled */
/* DMA memory block */
struct list_head buf_list;
/* ALSA Stuff */
- ac97_t *ac97;
- snd_kcontrol_t *master_switch; /* for h/w volume control */
- snd_kcontrol_t *master_volume;
+ struct snd_ac97 *ac97;
+ struct snd_kcontrol *master_switch; /* for h/w volume control */
+ struct snd_kcontrol *master_volume;
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
spinlock_t reg_lock;
spinlock_t ac97_lock;
@@ -610,14 +606,14 @@ MODULE_DEVICE_TABLE(pci, snd_es1968_ids);
*********************/
/* no spinlock */
-static void __maestro_write(es1968_t *chip, u16 reg, u16 data)
+static void __maestro_write(struct es1968 *chip, u16 reg, u16 data)
{
outw(reg, chip->io_port + ESM_INDEX);
outw(data, chip->io_port + ESM_DATA);
chip->maestro_map[reg] = data;
}
-static inline void maestro_write(es1968_t *chip, u16 reg, u16 data)
+static inline void maestro_write(struct es1968 *chip, u16 reg, u16 data)
{
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -626,7 +622,7 @@ static inline void maestro_write(es1968_t *chip, u16 reg, u16 data)
}
/* no spinlock */
-static u16 __maestro_read(es1968_t *chip, u16 reg)
+static u16 __maestro_read(struct es1968 *chip, u16 reg)
{
if (READABLE_MAP & (1 << reg)) {
outw(reg, chip->io_port + ESM_INDEX);
@@ -635,7 +631,7 @@ static u16 __maestro_read(es1968_t *chip, u16 reg)
return chip->maestro_map[reg];
}
-static inline u16 maestro_read(es1968_t *chip, u16 reg)
+static inline u16 maestro_read(struct es1968 *chip, u16 reg)
{
unsigned long flags;
u16 result;
@@ -646,7 +642,7 @@ static inline u16 maestro_read(es1968_t *chip, u16 reg)
}
/* Wait for the codec bus to be free */
-static int snd_es1968_ac97_wait(es1968_t *chip)
+static int snd_es1968_ac97_wait(struct es1968 *chip)
{
int timeout = 100000;
@@ -659,9 +655,9 @@ static int snd_es1968_ac97_wait(es1968_t *chip)
return 1; /* timeout */
}
-static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void snd_es1968_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
- es1968_t *chip = ac97->private_data;
+ struct es1968 *chip = ac97->private_data;
unsigned long flags;
snd_es1968_ac97_wait(chip);
@@ -675,10 +671,10 @@ static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned sho
spin_unlock_irqrestore(&chip->ac97_lock, flags);
}
-static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_es1968_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
u16 data = 0;
- es1968_t *chip = ac97->private_data;
+ struct es1968 *chip = ac97->private_data;
unsigned long flags;
snd_es1968_ac97_wait(chip);
@@ -697,7 +693,7 @@ static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
}
/* no spinlock */
-static void apu_index_set(es1968_t *chip, u16 index)
+static void apu_index_set(struct es1968 *chip, u16 index)
{
int i;
__maestro_write(chip, IDR1_CRAM_POINTER, index);
@@ -708,7 +704,7 @@ static void apu_index_set(es1968_t *chip, u16 index)
}
/* no spinlock */
-static void apu_data_set(es1968_t *chip, u16 data)
+static void apu_data_set(struct es1968 *chip, u16 data)
{
int i;
for (i = 0; i < 1000; i++) {
@@ -720,7 +716,7 @@ static void apu_data_set(es1968_t *chip, u16 data)
}
/* no spinlock */
-static void __apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data)
+static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data)
{
snd_assert(channel < NR_APUS, return);
#ifdef CONFIG_PM
@@ -731,7 +727,7 @@ static void __apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data)
apu_data_set(chip, data);
}
-static inline void apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 data)
+static void apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 data)
{
unsigned long flags;
spin_lock_irqsave(&chip->reg_lock, flags);
@@ -739,7 +735,7 @@ static inline void apu_set_register(es1968_t *chip, u16 channel, u8 reg, u16 dat
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static u16 __apu_get_register(es1968_t *chip, u16 channel, u8 reg)
+static u16 __apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
{
snd_assert(channel < NR_APUS, return 0);
reg |= (channel << 4);
@@ -747,7 +743,7 @@ static u16 __apu_get_register(es1968_t *chip, u16 channel, u8 reg)
return __maestro_read(chip, IDR0_DATA_PORT);
}
-static inline u16 apu_get_register(es1968_t *chip, u16 channel, u8 reg)
+static u16 apu_get_register(struct es1968 *chip, u16 channel, u8 reg)
{
unsigned long flags;
u16 v;
@@ -759,7 +755,7 @@ static inline u16 apu_get_register(es1968_t *chip, u16 channel, u8 reg)
#if 0 /* ASSP is not supported */
-static void assp_set_register(es1968_t *chip, u32 reg, u32 value)
+static void assp_set_register(struct es1968 *chip, u32 reg, u32 value)
{
unsigned long flags;
@@ -769,7 +765,7 @@ static void assp_set_register(es1968_t *chip, u32 reg, u32 value)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static u32 assp_get_register(es1968_t *chip, u32 reg)
+static u32 assp_get_register(struct es1968 *chip, u32 reg)
{
unsigned long flags;
u32 value;
@@ -784,7 +780,7 @@ static u32 assp_get_register(es1968_t *chip, u32 reg)
#endif
-static void wave_set_register(es1968_t *chip, u16 reg, u16 value)
+static void wave_set_register(struct es1968 *chip, u16 reg, u16 value)
{
unsigned long flags;
@@ -794,7 +790,7 @@ static void wave_set_register(es1968_t *chip, u16 reg, u16 value)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static u16 wave_get_register(es1968_t *chip, u16 reg)
+static u16 wave_get_register(struct es1968 *chip, u16 reg)
{
unsigned long flags;
u16 value;
@@ -811,7 +807,7 @@ static u16 wave_get_register(es1968_t *chip, u16 reg)
* Bob the Timer! *
*******************/
-static void snd_es1968_bob_stop(es1968_t *chip)
+static void snd_es1968_bob_stop(struct es1968 *chip)
{
u16 reg;
@@ -823,7 +819,7 @@ static void snd_es1968_bob_stop(es1968_t *chip)
__maestro_write(chip, 0x17, reg);
}
-static void snd_es1968_bob_start(es1968_t *chip)
+static void snd_es1968_bob_start(struct es1968 *chip)
{
int prescale;
int divide;
@@ -863,7 +859,7 @@ static void snd_es1968_bob_start(es1968_t *chip)
}
/* call with substream spinlock */
-static void snd_es1968_bob_inc(es1968_t *chip, int freq)
+static void snd_es1968_bob_inc(struct es1968 *chip, int freq)
{
chip->bobclient++;
if (chip->bobclient == 1) {
@@ -877,7 +873,7 @@ static void snd_es1968_bob_inc(es1968_t *chip, int freq)
}
/* call with substream spinlock */
-static void snd_es1968_bob_dec(es1968_t *chip)
+static void snd_es1968_bob_dec(struct es1968 *chip)
{
chip->bobclient--;
if (chip->bobclient <= 0)
@@ -887,7 +883,7 @@ static void snd_es1968_bob_dec(es1968_t *chip)
struct list_head *p;
int max_freq = ESM_BOB_FREQ;
list_for_each(p, &chip->substream_list) {
- esschan_t *es = list_entry(p, esschan_t, list);
+ struct esschan *es = list_entry(p, struct esschan, list);
if (max_freq < es->bob_freq)
max_freq = es->bob_freq;
}
@@ -900,8 +896,8 @@ static void snd_es1968_bob_dec(es1968_t *chip)
}
static int
-snd_es1968_calc_bob_rate(es1968_t *chip, esschan_t *es,
- snd_pcm_runtime_t *runtime)
+snd_es1968_calc_bob_rate(struct es1968 *chip, struct esschan *es,
+ struct snd_pcm_runtime *runtime)
{
/* we acquire 4 interrupts per period for precise control.. */
int freq = runtime->rate * 4;
@@ -922,7 +918,7 @@ snd_es1968_calc_bob_rate(es1968_t *chip, esschan_t *es,
* PCM Part *
*************/
-static u32 snd_es1968_compute_rate(es1968_t *chip, u32 freq)
+static u32 snd_es1968_compute_rate(struct es1968 *chip, u32 freq)
{
u32 rate = (freq << 16) / chip->clock;
#if 0 /* XXX: do we need this? */
@@ -934,7 +930,7 @@ static u32 snd_es1968_compute_rate(es1968_t *chip, u32 freq)
/* get current pointer */
static inline unsigned int
-snd_es1968_get_dma_ptr(es1968_t *chip, esschan_t *es)
+snd_es1968_get_dma_ptr(struct es1968 *chip, struct esschan *es)
{
unsigned int offset;
@@ -945,7 +941,7 @@ snd_es1968_get_dma_ptr(es1968_t *chip, esschan_t *es)
return (offset & 0xFFFE); /* hardware is in words */
}
-static void snd_es1968_apu_set_freq(es1968_t *chip, int apu, int freq)
+static void snd_es1968_apu_set_freq(struct es1968 *chip, int apu, int freq)
{
apu_set_register(chip, apu, 2,
(apu_get_register(chip, apu, 2) & 0x00FF) |
@@ -954,7 +950,7 @@ static void snd_es1968_apu_set_freq(es1968_t *chip, int apu, int freq)
}
/* spin lock held */
-static inline void snd_es1968_trigger_apu(es1968_t *esm, int apu, int mode)
+static inline void snd_es1968_trigger_apu(struct es1968 *esm, int apu, int mode)
{
/* set the APU mode */
__apu_set_register(esm, apu, 0,
@@ -962,7 +958,7 @@ static inline void snd_es1968_trigger_apu(es1968_t *esm, int apu, int mode)
(mode << 4));
}
-static void snd_es1968_pcm_start(es1968_t *chip, esschan_t *es)
+static void snd_es1968_pcm_start(struct es1968 *chip, struct esschan *es)
{
spin_lock(&chip->reg_lock);
__apu_set_register(chip, es->apu[0], 5, es->base[0]);
@@ -982,7 +978,7 @@ static void snd_es1968_pcm_start(es1968_t *chip, esschan_t *es)
spin_unlock(&chip->reg_lock);
}
-static void snd_es1968_pcm_stop(es1968_t *chip, esschan_t *es)
+static void snd_es1968_pcm_stop(struct es1968 *chip, struct esschan *es)
{
spin_lock(&chip->reg_lock);
snd_es1968_trigger_apu(chip, es->apu[0], 0);
@@ -995,7 +991,7 @@ static void snd_es1968_pcm_stop(es1968_t *chip, esschan_t *es)
}
/* set the wavecache control reg */
-static void snd_es1968_program_wavecache(es1968_t *chip, esschan_t *es,
+static void snd_es1968_program_wavecache(struct es1968 *chip, struct esschan *es,
int channel, u32 addr, int capture)
{
u32 tmpval = (addr - 0x10) & 0xFFF8;
@@ -1016,8 +1012,8 @@ static void snd_es1968_program_wavecache(es1968_t *chip, esschan_t *es,
}
-static void snd_es1968_playback_setup(es1968_t *chip, esschan_t *es,
- snd_pcm_runtime_t *runtime)
+static void snd_es1968_playback_setup(struct es1968 *chip, struct esschan *es,
+ struct snd_pcm_runtime *runtime)
{
u32 pa;
int high_apu = 0;
@@ -1119,7 +1115,7 @@ static void snd_es1968_playback_setup(es1968_t *chip, esschan_t *es,
}
-static void init_capture_apu(es1968_t *chip, esschan_t *es, int channel,
+static void init_capture_apu(struct es1968 *chip, struct esschan *es, int channel,
unsigned int pa, unsigned int bsize,
int mode, int route)
{
@@ -1164,8 +1160,8 @@ static void init_capture_apu(es1968_t *chip, esschan_t *es, int channel,
apu_set_register(chip, apu, 0, 0x400F);
}
-static void snd_es1968_capture_setup(es1968_t *chip, esschan_t *es,
- snd_pcm_runtime_t *runtime)
+static void snd_es1968_capture_setup(struct es1968 *chip, struct esschan *es,
+ struct snd_pcm_runtime *runtime)
{
int size;
u32 freq;
@@ -1233,11 +1229,11 @@ static void snd_es1968_capture_setup(es1968_t *chip, esschan_t *es,
* ALSA Interface *
*******************/
-static int snd_es1968_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_es1968_pcm_prepare(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- esschan_t *es = runtime->private_data;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct esschan *es = runtime->private_data;
es->dma_size = snd_pcm_lib_buffer_bytes(substream);
es->frag_size = snd_pcm_lib_period_bytes(substream);
@@ -1265,10 +1261,10 @@ static int snd_es1968_pcm_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_es1968_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_es1968_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- esschan_t *es = substream->runtime->private_data;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct esschan *es = substream->runtime->private_data;
spin_lock(&chip->substream_lock);
switch (cmd) {
@@ -1295,10 +1291,10 @@ static int snd_es1968_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
return 0;
}
-static snd_pcm_uframes_t snd_es1968_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_es1968_pcm_pointer(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- esschan_t *es = substream->runtime->private_data;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct esschan *es = substream->runtime->private_data;
unsigned int ptr;
ptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift;
@@ -1306,7 +1302,7 @@ static snd_pcm_uframes_t snd_es1968_pcm_pointer(snd_pcm_substream_t *substream)
return bytes_to_frames(substream->runtime, ptr % es->dma_size);
}
-static snd_pcm_hardware_t snd_es1968_playback = {
+static struct snd_pcm_hardware snd_es1968_playback = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1327,7 +1323,7 @@ static snd_pcm_hardware_t snd_es1968_playback = {
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_es1968_capture = {
+static struct snd_pcm_hardware snd_es1968_capture = {
.info = (SNDRV_PCM_INFO_NONINTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1355,14 +1351,14 @@ static snd_pcm_hardware_t snd_es1968_capture = {
/* Because the Maestro can only take addresses relative to the PCM base address
register :( */
-static int calc_available_memory_size(es1968_t *chip)
+static int calc_available_memory_size(struct es1968 *chip)
{
struct list_head *p;
int max_size = 0;
down(&chip->memory_mutex);
list_for_each(p, &chip->buf_list) {
- esm_memory_t *buf = list_entry(p, esm_memory_t, list);
+ struct esm_memory *buf = list_entry(p, struct esm_memory, list);
if (buf->empty && buf->buf.bytes > max_size)
max_size = buf->buf.bytes;
}
@@ -1373,15 +1369,15 @@ static int calc_available_memory_size(es1968_t *chip)
}
/* allocate a new memory chunk with the specified size */
-static esm_memory_t *snd_es1968_new_memory(es1968_t *chip, int size)
+static struct esm_memory *snd_es1968_new_memory(struct es1968 *chip, int size)
{
- esm_memory_t *buf;
+ struct esm_memory *buf;
struct list_head *p;
size = ((size + ESM_MEM_ALIGN - 1) / ESM_MEM_ALIGN) * ESM_MEM_ALIGN;
down(&chip->memory_mutex);
list_for_each(p, &chip->buf_list) {
- buf = list_entry(p, esm_memory_t, list);
+ buf = list_entry(p, struct esm_memory, list);
if (buf->empty && buf->buf.bytes >= size)
goto __found;
}
@@ -1390,7 +1386,7 @@ static esm_memory_t *snd_es1968_new_memory(es1968_t *chip, int size)
__found:
if (buf->buf.bytes > size) {
- esm_memory_t *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
+ struct esm_memory *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
if (chunk == NULL) {
up(&chip->memory_mutex);
return NULL;
@@ -1409,14 +1405,14 @@ __found:
}
/* free a memory chunk */
-static void snd_es1968_free_memory(es1968_t *chip, esm_memory_t *buf)
+static void snd_es1968_free_memory(struct es1968 *chip, struct esm_memory *buf)
{
- esm_memory_t *chunk;
+ struct esm_memory *chunk;
down(&chip->memory_mutex);
buf->empty = 1;
if (buf->list.prev != &chip->buf_list) {
- chunk = list_entry(buf->list.prev, esm_memory_t, list);
+ chunk = list_entry(buf->list.prev, struct esm_memory, list);
if (chunk->empty) {
chunk->buf.bytes += buf->buf.bytes;
list_del(&buf->list);
@@ -1425,7 +1421,7 @@ static void snd_es1968_free_memory(es1968_t *chip, esm_memory_t *buf)
}
}
if (buf->list.next != &chip->buf_list) {
- chunk = list_entry(buf->list.next, esm_memory_t, list);
+ chunk = list_entry(buf->list.next, struct esm_memory, list);
if (chunk->empty) {
buf->buf.bytes += chunk->buf.bytes;
list_del(&chunk->list);
@@ -1435,7 +1431,7 @@ static void snd_es1968_free_memory(es1968_t *chip, esm_memory_t *buf)
up(&chip->memory_mutex);
}
-static void snd_es1968_free_dmabuf(es1968_t *chip)
+static void snd_es1968_free_dmabuf(struct es1968 *chip)
{
struct list_head *p;
@@ -1443,17 +1439,17 @@ static void snd_es1968_free_dmabuf(es1968_t *chip)
return;
snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci));
while ((p = chip->buf_list.next) != &chip->buf_list) {
- esm_memory_t *chunk = list_entry(p, esm_memory_t, list);
+ struct esm_memory *chunk = list_entry(p, struct esm_memory, list);
list_del(p);
kfree(chunk);
}
}
static int __devinit
-snd_es1968_init_dmabuf(es1968_t *chip)
+snd_es1968_init_dmabuf(struct es1968 *chip)
{
int err;
- esm_memory_t *chunk;
+ struct esm_memory *chunk;
chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
@@ -1493,12 +1489,12 @@ snd_es1968_init_dmabuf(es1968_t *chip)
/* setup the dma_areas */
/* buffer is extracted from the pre-allocated memory chunk */
-static int snd_es1968_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_es1968_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- esschan_t *chan = runtime->private_data;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct esschan *chan = runtime->private_data;
int size = params_buffer_bytes(hw_params);
if (chan->memory) {
@@ -1518,11 +1514,11 @@ static int snd_es1968_hw_params(snd_pcm_substream_t *substream,
}
/* remove dma areas if allocated */
-static int snd_es1968_hw_free(snd_pcm_substream_t * substream)
+static int snd_es1968_hw_free(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- esschan_t *chan;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct esschan *chan;
if (runtime->private_data == NULL)
return 0;
@@ -1538,7 +1534,7 @@ static int snd_es1968_hw_free(snd_pcm_substream_t * substream)
/*
* allocate APU pair
*/
-static int snd_es1968_alloc_apu_pair(es1968_t *chip, int type)
+static int snd_es1968_alloc_apu_pair(struct es1968 *chip, int type)
{
int apu;
@@ -1555,7 +1551,7 @@ static int snd_es1968_alloc_apu_pair(es1968_t *chip, int type)
/*
* release APU pair
*/
-static void snd_es1968_free_apu_pair(es1968_t *chip, int apu)
+static void snd_es1968_free_apu_pair(struct es1968 *chip, int apu)
{
chip->apu[apu] = chip->apu[apu + 1] = ESM_APU_FREE;
}
@@ -1565,11 +1561,11 @@ static void snd_es1968_free_apu_pair(es1968_t *chip, int apu)
* PCM open/close *
******************/
-static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
+static int snd_es1968_playback_open(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- esschan_t *es;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct esschan *es;
int apu1;
/* search 2 APUs */
@@ -1606,11 +1602,11 @@ static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
+static int snd_es1968_capture_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- es1968_t *chip = snd_pcm_substream_chip(substream);
- esschan_t *es;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct esschan *es;
int apu1, apu2;
apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
@@ -1665,10 +1661,10 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_es1968_playback_close(snd_pcm_substream_t * substream)
+static int snd_es1968_playback_close(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- esschan_t *es;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct esschan *es;
if (substream->runtime->private_data == NULL)
return 0;
@@ -1682,10 +1678,10 @@ static int snd_es1968_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_es1968_capture_close(snd_pcm_substream_t * substream)
+static int snd_es1968_capture_close(struct snd_pcm_substream *substream)
{
- es1968_t *chip = snd_pcm_substream_chip(substream);
- esschan_t *es;
+ struct es1968 *chip = snd_pcm_substream_chip(substream);
+ struct esschan *es;
if (substream->runtime->private_data == NULL)
return 0;
@@ -1701,7 +1697,7 @@ static int snd_es1968_capture_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_es1968_playback_ops = {
+static struct snd_pcm_ops snd_es1968_playback_ops = {
.open = snd_es1968_playback_open,
.close = snd_es1968_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1712,7 +1708,7 @@ static snd_pcm_ops_t snd_es1968_playback_ops = {
.pointer = snd_es1968_pcm_pointer,
};
-static snd_pcm_ops_t snd_es1968_capture_ops = {
+static struct snd_pcm_ops snd_es1968_capture_ops = {
.open = snd_es1968_capture_open,
.close = snd_es1968_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1729,11 +1725,11 @@ static snd_pcm_ops_t snd_es1968_capture_ops = {
*/
#define CLOCK_MEASURE_BUFSIZE 16768 /* enough large for a single shot */
-static void __devinit es1968_measure_clock(es1968_t *chip)
+static void __devinit es1968_measure_clock(struct es1968 *chip)
{
int i, apu;
unsigned int pa, offset, t;
- esm_memory_t *memory;
+ struct esm_memory *memory;
struct timeval start_time, stop_time;
if (chip->clock == 0)
@@ -1824,17 +1820,17 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
/*
*/
-static void snd_es1968_pcm_free(snd_pcm_t *pcm)
+static void snd_es1968_pcm_free(struct snd_pcm *pcm)
{
- es1968_t *esm = pcm->private_data;
+ struct es1968 *esm = pcm->private_data;
snd_es1968_free_dmabuf(esm);
esm->pcm = NULL;
}
static int __devinit
-snd_es1968_pcm(es1968_t *chip, int device)
+snd_es1968_pcm(struct es1968 *chip, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
/* get DMA buffer */
@@ -1870,11 +1866,11 @@ snd_es1968_pcm(es1968_t *chip, int device)
/*
* update pointer
*/
-static void snd_es1968_update_pcm(es1968_t *chip, esschan_t *es)
+static void snd_es1968_update_pcm(struct es1968 *chip, struct esschan *es)
{
unsigned int hwptr;
unsigned int diff;
- snd_pcm_substream_t *subs = es->substream;
+ struct snd_pcm_substream *subs = es->substream;
if (subs == NULL || !es->running)
return;
@@ -1899,7 +1895,7 @@ static void snd_es1968_update_pcm(es1968_t *chip, esschan_t *es)
*/
static void es1968_update_hw_volume(unsigned long private_data)
{
- es1968_t *chip = (es1968_t *) private_data;
+ struct es1968 *chip = (struct es1968 *) private_data;
int x, val;
unsigned long flags;
@@ -1959,7 +1955,7 @@ static void es1968_update_hw_volume(unsigned long private_data)
*/
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- es1968_t *chip = dev_id;
+ struct es1968 *chip = dev_id;
u32 event;
if (!(event = inb(chip->io_port + 0x1A)))
@@ -1981,7 +1977,7 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *r
struct list_head *p;
spin_lock(&chip->substream_lock);
list_for_each(p, &chip->substream_list) {
- esschan_t *es = list_entry(p, esschan_t, list);
+ struct esschan *es = list_entry(p, struct esschan, list);
if (es->running)
snd_es1968_update_pcm(chip, es);
}
@@ -2002,13 +1998,13 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *r
*/
static int __devinit
-snd_es1968_mixer(es1968_t *chip)
+snd_es1968_mixer(struct es1968 *chip)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- snd_ctl_elem_id_t id;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ struct snd_ctl_elem_id id;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_es1968_ac97_write,
.read = snd_es1968_ac97_read,
};
@@ -2039,7 +2035,7 @@ snd_es1968_mixer(es1968_t *chip)
* reset ac97 codec
*/
-static void snd_es1968_ac97_reset(es1968_t *chip)
+static void snd_es1968_ac97_reset(struct es1968 *chip)
{
unsigned long ioaddr = chip->io_port;
@@ -2144,7 +2140,7 @@ static void snd_es1968_ac97_reset(es1968_t *chip)
outb(0x3f, ioaddr+0xd0);
}
-static void snd_es1968_reset(es1968_t *chip)
+static void snd_es1968_reset(struct es1968 *chip)
{
/* Reset */
outw(ESM_RESET_MAESTRO | ESM_RESET_DIRECTSOUND,
@@ -2157,7 +2153,7 @@ static void snd_es1968_reset(es1968_t *chip)
/*
* power management
*/
-static void snd_es1968_set_acpi(es1968_t *chip, int state)
+static void snd_es1968_set_acpi(struct es1968 *chip, int state)
{
u16 active_mask = acpi_state_mask[state];
@@ -2172,7 +2168,7 @@ static void snd_es1968_set_acpi(es1968_t *chip, int state)
/*
* initialize maestro chip
*/
-static void snd_es1968_chip_init(es1968_t *chip)
+static void snd_es1968_chip_init(struct es1968 *chip)
{
struct pci_dev *pci = chip->pci;
int i;
@@ -2197,14 +2193,11 @@ static void snd_es1968_chip_init(es1968_t *chip)
/* Config Reg A */
pci_read_config_word(pci, ESM_CONFIG_A, &w);
- /* Use TDMA for now. TDMA works on all boards, so while its
- * not the most efficient its the simplest. */
w &= ~DMA_CLEAR; /* Clear DMA bits */
- w |= DMA_TDMA; /* TDMA on */
w &= ~(PIC_SNOOP1 | PIC_SNOOP2); /* Clear Pic Snoop Mode Bits */
w &= ~SAFEGUARD; /* Safeguard off */
w |= POST_WRITE; /* Posted write */
- w |= ISA_TIMING; /* ISA timing on */
+ w |= PCI_TIMING; /* PCI timing on */
/* XXX huh? claims to be reserved.. */
w &= ~SWAP_LR; /* swap left/right
seems to only have effect on SB
@@ -2245,7 +2238,7 @@ static void snd_es1968_chip_init(es1968_t *chip)
pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &w);
- w &= ~ESS_ENABLE_AUDIO; /* Disable Legacy Audio */
+ w |= ESS_DISABLE_AUDIO; /* Disable Legacy Audio */
w &= ~ESS_ENABLE_SERIAL_IRQ; /* Disable SIRQ */
w &= ~(0x1f); /* disable mpu irq/io, game port, fm, SB */
@@ -2369,7 +2362,7 @@ static void snd_es1968_chip_init(es1968_t *chip)
}
/* Enable IRQ's */
-static void snd_es1968_start_irq(es1968_t *chip)
+static void snd_es1968_start_irq(struct es1968 *chip)
{
unsigned short w;
w = ESM_HIRQ_DSIE | ESM_HIRQ_HW_VOLUME;
@@ -2382,33 +2375,38 @@ static void snd_es1968_start_irq(es1968_t *chip)
/*
* PM support
*/
-static int es1968_suspend(snd_card_t *card, pm_message_t state)
+static int es1968_suspend(struct pci_dev *pci, pm_message_t state)
{
- es1968_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct es1968 *chip = card->private_data;
if (! chip->do_pm)
return 0;
chip->in_suspend = 1;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
snd_es1968_bob_stop(chip);
snd_es1968_set_acpi(chip, ACPI_D3);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int es1968_resume(snd_card_t *card)
+static int es1968_resume(struct pci_dev *pci)
{
- es1968_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct es1968 *chip = card->private_data;
struct list_head *p;
if (! chip->do_pm)
return 0;
/* restore all our config */
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
snd_es1968_chip_init(chip);
/* need to restore the base pointers.. */
@@ -2423,7 +2421,7 @@ static int es1968_resume(snd_card_t *card)
snd_ac97_resume(chip->ac97);
list_for_each(p, &chip->substream_list) {
- esschan_t *es = list_entry(p, esschan_t, list);
+ struct esschan *es = list_entry(p, struct esschan, list);
switch (es->mode) {
case ESM_MODE_PLAY:
snd_es1968_playback_setup(chip, es, es->substream->runtime);
@@ -2438,6 +2436,7 @@ static int es1968_resume(snd_card_t *card)
if (chip->bobclient)
snd_es1968_bob_start(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
chip->in_suspend = 0;
return 0;
}
@@ -2445,7 +2444,7 @@ static int es1968_resume(snd_card_t *card)
#ifdef SUPPORT_JOYSTICK
#define JOYSTICK_ADDR 0x200
-static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
+static int __devinit snd_es1968_create_gameport(struct es1968 *chip, int dev)
{
struct gameport *gp;
struct resource *r;
@@ -2479,7 +2478,7 @@ static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
return 0;
}
-static void snd_es1968_free_gameport(es1968_t *chip)
+static void snd_es1968_free_gameport(struct es1968 *chip)
{
if (chip->gameport) {
struct resource *r = gameport_get_port_data(chip->gameport);
@@ -2491,11 +2490,11 @@ static void snd_es1968_free_gameport(es1968_t *chip)
}
}
#else
-static inline int snd_es1968_create_gameport(es1968_t *chip, int dev) { return -ENOSYS; }
-static inline void snd_es1968_free_gameport(es1968_t *chip) { }
+static inline int snd_es1968_create_gameport(struct es1968 *chip, int dev) { return -ENOSYS; }
+static inline void snd_es1968_free_gameport(struct es1968 *chip) { }
#endif
-static int snd_es1968_free(es1968_t *chip)
+static int snd_es1968_free(struct es1968 *chip)
{
if (chip->io_port) {
synchronize_irq(chip->irq);
@@ -2515,9 +2514,9 @@ static int snd_es1968_free(es1968_t *chip)
return 0;
}
-static int snd_es1968_dev_free(snd_device_t *device)
+static int snd_es1968_dev_free(struct snd_device *device)
{
- es1968_t *chip = device->device_data;
+ struct es1968 *chip = device->device_data;
return snd_es1968_free(chip);
}
@@ -2539,19 +2538,19 @@ static struct ess_device_list mpu_blacklist[] __devinitdata = {
{ TYPE_MAESTRO2, 0x125d },
};
-static int __devinit snd_es1968_create(snd_card_t * card,
+static int __devinit snd_es1968_create(struct snd_card *card,
struct pci_dev *pci,
int total_bufsize,
int play_streams,
int capt_streams,
int chip_type,
int do_pm,
- es1968_t **chip_ret)
+ struct es1968 **chip_ret)
{
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_es1968_dev_free,
};
- es1968_t *chip;
+ struct es1968 *chip;
int i, err;
*chip_ret = NULL;
@@ -2635,9 +2634,6 @@ static int __devinit snd_es1968_create(snd_card_t * card,
snd_es1968_chip_init(chip);
- if (chip->do_pm)
- snd_card_set_pm_callback(card, es1968_suspend, es1968_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_es1968_free(chip);
return err;
@@ -2657,8 +2653,8 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- es1968_t *chip;
+ struct snd_card *card;
+ struct es1968 *chip;
unsigned int i;
int err;
@@ -2687,6 +2683,7 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
switch (chip->type) {
case TYPE_MAESTRO2E:
@@ -2764,7 +2761,10 @@ static struct pci_driver driver = {
.id_table = snd_es1968_ids,
.probe = snd_es1968_probe,
.remove = __devexit_p(snd_es1968_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = es1968_suspend,
+ .resume = es1968_resume,
+#endif
};
static int __init alsa_card_es1968_init(void)
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 4e1d3434888d..6ab4aefbccf8 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -103,7 +103,11 @@ MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
#define FM801_OPL3_DATA1 0x6b /* OPL3 Bank 1 Write */
#define FM801_POWERDOWN 0x70 /* Blocks Power Down Control */
-#define FM801_AC97_ADDR_SHIFT 10
+/* codec access */
+#define FM801_AC97_READ (1<<7) /* read=1, write=0 */
+#define FM801_AC97_VALID (1<<8) /* port valid=1 */
+#define FM801_AC97_BUSY (1<<9) /* busy=1 */
+#define FM801_AC97_ADDR_SHIFT 10 /* codec id (2bit) */
/* playback and record control register bits */
#define FM801_BUF1_LAST (1<<1)
@@ -147,9 +151,7 @@ MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
*/
-typedef struct _snd_fm801 fm801_t;
-
-struct _snd_fm801 {
+struct fm801 {
int irq;
unsigned long port; /* I/O port number */
@@ -172,24 +174,28 @@ struct _snd_fm801 {
unsigned int cap_size;
unsigned int cap_pos;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
- ac97_t *ac97_sec;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
+ struct snd_ac97 *ac97_sec;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_rawmidi_t *rmidi;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_rawmidi *rmidi;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int p_dma_size;
unsigned int c_dma_size;
spinlock_t reg_lock;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
#ifdef TEA575X_RADIO
- tea575x_t tea;
+ struct snd_tea575x tea;
+#endif
+
+#ifdef CONFIG_PM
+ u16 saved_regs[0x20];
#endif
};
@@ -205,7 +211,7 @@ MODULE_DEVICE_TABLE(pci, snd_fm801_ids);
* common I/O routines
*/
-static int snd_fm801_update_bits(fm801_t *chip, unsigned short reg,
+static int snd_fm801_update_bits(struct fm801 *chip, unsigned short reg,
unsigned short mask, unsigned short value)
{
int change;
@@ -222,18 +228,18 @@ static int snd_fm801_update_bits(fm801_t *chip, unsigned short reg,
return change;
}
-static void snd_fm801_codec_write(ac97_t *ac97,
+static void snd_fm801_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- fm801_t *chip = ac97->private_data;
+ struct fm801 *chip = ac97->private_data;
int idx;
/*
* Wait until the codec interface is not ready..
*/
for (idx = 0; idx < 100; idx++) {
- if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9)))
+ if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
goto ok1;
udelay(10);
}
@@ -248,23 +254,23 @@ static void snd_fm801_codec_write(ac97_t *ac97,
* Wait until the write command is not completed..
*/
for (idx = 0; idx < 1000; idx++) {
- if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9)))
+ if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
return;
udelay(10);
}
snd_printk(KERN_ERR "AC'97 interface #%d is busy (2)\n", ac97->num);
}
-static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
- fm801_t *chip = ac97->private_data;
+ struct fm801 *chip = ac97->private_data;
int idx;
/*
* Wait until the codec interface is not ready..
*/
for (idx = 0; idx < 100; idx++) {
- if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9)))
+ if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
goto ok1;
udelay(10);
}
@@ -273,9 +279,10 @@ static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg)
ok1:
/* read command */
- outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | (1<<7), FM801_REG(chip, AC97_CMD));
+ outw(reg | (ac97->addr << FM801_AC97_ADDR_SHIFT) | FM801_AC97_READ,
+ FM801_REG(chip, AC97_CMD));
for (idx = 0; idx < 100; idx++) {
- if (!(inw(FM801_REG(chip, AC97_CMD)) & (1<<9)))
+ if (!(inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_BUSY))
goto ok2;
udelay(10);
}
@@ -284,7 +291,7 @@ static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg)
ok2:
for (idx = 0; idx < 1000; idx++) {
- if (inw(FM801_REG(chip, AC97_CMD)) & (1<<8))
+ if (inw(FM801_REG(chip, AC97_CMD)) & FM801_AC97_VALID)
goto ok3;
udelay(10);
}
@@ -301,7 +308,7 @@ static unsigned int rates[] = {
38400, 44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -313,7 +320,7 @@ static unsigned int channels[] = {
#define CHANNELS sizeof(channels) / sizeof(channels[0])
-static snd_pcm_hw_constraint_list_t hw_constraints_channels = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels = {
.count = CHANNELS,
.list = channels,
.mask = 0,
@@ -338,10 +345,10 @@ static unsigned short snd_fm801_rate_bits(unsigned int rate)
* PCM part
*/
-static int snd_fm801_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_fm801_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
spin_lock(&chip->reg_lock);
switch (cmd) {
@@ -356,9 +363,11 @@ static int snd_fm801_playback_trigger(snd_pcm_substream_t * substream,
chip->ply_ctrl &= ~(FM801_START | FM801_PAUSE);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
chip->ply_ctrl |= FM801_PAUSE;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->ply_ctrl &= ~FM801_PAUSE;
break;
default:
@@ -371,10 +380,10 @@ static int snd_fm801_playback_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_fm801_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
spin_lock(&chip->reg_lock);
switch (cmd) {
@@ -389,9 +398,11 @@ static int snd_fm801_capture_trigger(snd_pcm_substream_t * substream,
chip->cap_ctrl &= ~(FM801_START | FM801_PAUSE);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
chip->cap_ctrl |= FM801_PAUSE;
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
chip->cap_ctrl &= ~FM801_PAUSE;
break;
default:
@@ -404,21 +415,21 @@ static int snd_fm801_capture_trigger(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_fm801_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_fm801_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_fm801_hw_free(snd_pcm_substream_t * substream)
+static int snd_fm801_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_fm801_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
chip->ply_size = snd_pcm_lib_buffer_bytes(substream);
chip->ply_count = snd_pcm_lib_period_bytes(substream);
@@ -447,10 +458,10 @@ static int snd_fm801_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_fm801_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_fm801_capture_prepare(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
chip->cap_size = snd_pcm_lib_buffer_bytes(substream);
chip->cap_count = snd_pcm_lib_period_bytes(substream);
@@ -473,9 +484,9 @@ static int snd_fm801_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_fm801_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_fm801_playback_pointer(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->ply_ctrl & FM801_START))
@@ -490,9 +501,9 @@ static snd_pcm_uframes_t snd_fm801_playback_pointer(snd_pcm_substream_t * substr
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_fm801_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_fm801_capture_pointer(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(chip->cap_ctrl & FM801_START))
@@ -509,7 +520,7 @@ static snd_pcm_uframes_t snd_fm801_capture_pointer(snd_pcm_substream_t * substre
static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- fm801_t *chip = dev_id;
+ struct fm801 *chip = dev_id;
unsigned short status;
unsigned int tmp;
@@ -555,11 +566,11 @@ static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *re
return IRQ_HANDLED;
}
-static snd_pcm_hardware_t snd_fm801_playback =
+static struct snd_pcm_hardware snd_fm801_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
@@ -575,11 +586,11 @@ static snd_pcm_hardware_t snd_fm801_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_fm801_capture =
+static struct snd_pcm_hardware snd_fm801_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
@@ -595,55 +606,59 @@ static snd_pcm_hardware_t snd_fm801_capture =
.fifo_size = 0,
};
-static int snd_fm801_playback_open(snd_pcm_substream_t * substream)
+static int snd_fm801_playback_open(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
chip->playback_substream = substream;
runtime->hw = snd_fm801_playback;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
if (chip->multichannel) {
runtime->hw.channels_max = 6;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &hw_constraints_channels);
}
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
return 0;
}
-static int snd_fm801_capture_open(snd_pcm_substream_t * substream)
+static int snd_fm801_capture_open(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
chip->capture_substream = substream;
runtime->hw = snd_fm801_capture;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
return 0;
}
-static int snd_fm801_playback_close(snd_pcm_substream_t * substream)
+static int snd_fm801_playback_close(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
chip->playback_substream = NULL;
return 0;
}
-static int snd_fm801_capture_close(snd_pcm_substream_t * substream)
+static int snd_fm801_capture_close(struct snd_pcm_substream *substream)
{
- fm801_t *chip = snd_pcm_substream_chip(substream);
+ struct fm801 *chip = snd_pcm_substream_chip(substream);
chip->capture_substream = NULL;
return 0;
}
-static snd_pcm_ops_t snd_fm801_playback_ops = {
+static struct snd_pcm_ops snd_fm801_playback_ops = {
.open = snd_fm801_playback_open,
.close = snd_fm801_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -654,7 +669,7 @@ static snd_pcm_ops_t snd_fm801_playback_ops = {
.pointer = snd_fm801_playback_pointer,
};
-static snd_pcm_ops_t snd_fm801_capture_ops = {
+static struct snd_pcm_ops snd_fm801_capture_ops = {
.open = snd_fm801_capture_open,
.close = snd_fm801_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -665,16 +680,9 @@ static snd_pcm_ops_t snd_fm801_capture_ops = {
.pointer = snd_fm801_capture_pointer,
};
-static void snd_fm801_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm ** rpcm)
{
- fm801_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_fm801_pcm(fm801_t *chip, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -686,7 +694,6 @@ static int __devinit snd_fm801_pcm(fm801_t *chip, int device, snd_pcm_t ** rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_fm801_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_fm801_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "FM801");
chip->pcm = pcm;
@@ -711,9 +718,9 @@ static int __devinit snd_fm801_pcm(fm801_t *chip, int device, snd_pcm_t ** rpcm)
#define TEA_256PCS_WRITE_ENABLE 2 /* inverted */
#define TEA_256PCS_BUS_CLOCK 3
-static void snd_fm801_tea575x_256pcs_write(tea575x_t *tea, unsigned int val)
+static void snd_fm801_tea575x_256pcs_write(struct snd_tea575x *tea, unsigned int val)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
int i = 25;
@@ -755,9 +762,9 @@ static void snd_fm801_tea575x_256pcs_write(tea575x_t *tea, unsigned int val)
spin_unlock_irq(&chip->reg_lock);
}
-static unsigned int snd_fm801_tea575x_256pcs_read(tea575x_t *tea)
+static unsigned int snd_fm801_tea575x_256pcs_read(struct snd_tea575x *tea)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
unsigned int val = 0;
int i;
@@ -799,9 +806,9 @@ static unsigned int snd_fm801_tea575x_256pcs_read(tea575x_t *tea)
#define TEA_256PCPR_DATA 1
#define TEA_256PCPR_WRITE_ENABLE 2 /* inverted */
-static void snd_fm801_tea575x_256pcpr_write(tea575x_t *tea, unsigned int val)
+static void snd_fm801_tea575x_256pcpr_write(struct snd_tea575x *tea, unsigned int val)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
int i = 25;
@@ -843,9 +850,9 @@ static void snd_fm801_tea575x_256pcpr_write(tea575x_t *tea, unsigned int val)
spin_unlock_irq(&chip->reg_lock);
}
-static unsigned int snd_fm801_tea575x_256pcpr_read(tea575x_t *tea)
+static unsigned int snd_fm801_tea575x_256pcpr_read(struct snd_tea575x *tea)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
unsigned int val = 0;
int i;
@@ -887,9 +894,9 @@ static unsigned int snd_fm801_tea575x_256pcpr_read(tea575x_t *tea)
#define TEA_64PCR_WRITE_ENABLE 1 /* inverted */
#define TEA_64PCR_DATA 2
-static void snd_fm801_tea575x_64pcr_write(tea575x_t *tea, unsigned int val)
+static void snd_fm801_tea575x_64pcr_write(struct snd_tea575x *tea, unsigned int val)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
int i = 25;
@@ -931,9 +938,9 @@ static void snd_fm801_tea575x_64pcr_write(tea575x_t *tea, unsigned int val)
spin_unlock_irq(&chip->reg_lock);
}
-static unsigned int snd_fm801_tea575x_64pcr_read(tea575x_t *tea)
+static unsigned int snd_fm801_tea575x_64pcr_read(struct snd_tea575x *tea)
{
- fm801_t *chip = tea->private_data;
+ struct fm801 *chip = tea->private_data;
unsigned short reg;
unsigned int val = 0;
int i;
@@ -998,7 +1005,8 @@ static struct snd_tea575x_ops snd_fm801_tea_ops[3] = {
.get = snd_fm801_get_single, .put = snd_fm801_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_fm801_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_fm801_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1009,9 +1017,10 @@ static int snd_fm801_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_fm801_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1023,9 +1032,10 @@ static int snd_fm801_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_fm801_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1043,7 +1053,8 @@ static int snd_fm801_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.get = snd_fm801_get_double, .put = snd_fm801_put_double, \
.private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) }
-static int snd_fm801_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_fm801_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1054,9 +1065,10 @@ static int snd_fm801_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_fm801_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift_left = (kcontrol->private_value >> 8) & 0x0f;
int shift_right = (kcontrol->private_value >> 12) & 0x0f;
@@ -1074,9 +1086,10 @@ static int snd_fm801_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_fm801_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift_left = (kcontrol->private_value >> 8) & 0x0f;
int shift_right = (kcontrol->private_value >> 12) & 0x0f;
@@ -1095,7 +1108,8 @@ static int snd_fm801_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
(val1 << shift_left ) | (val2 << shift_right));
}
-static int snd_fm801_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_fm801_info_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[5] = {
"AC97 Primary", "FM", "I2S", "PCM", "AC97 Secondary"
@@ -1110,9 +1124,10 @@ static int snd_fm801_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * ui
return 0;
}
-static int snd_fm801_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_get_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
unsigned short val;
val = inw(FM801_REG(chip, REC_SRC)) & 7;
@@ -1122,9 +1137,10 @@ static int snd_fm801_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
return 0;
}
-static int snd_fm801_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- fm801_t *chip = snd_kcontrol_chip(kcontrol);
+ struct fm801 *chip = snd_kcontrol_chip(kcontrol);
unsigned short val;
if ((val = ucontrol->value.enumerated.item[0]) > 4)
@@ -1132,9 +1148,9 @@ static int snd_fm801_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val);
}
-#define FM801_CONTROLS (sizeof(snd_fm801_controls)/sizeof(snd_kcontrol_new_t))
+#define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
-static snd_kcontrol_new_t snd_fm801_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = {
FM801_DOUBLE("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1),
FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1),
FM801_DOUBLE("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1),
@@ -1150,9 +1166,9 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
}
};
-#define FM801_CONTROLS_MULTI (sizeof(snd_fm801_controls_multi)/sizeof(snd_kcontrol_new_t))
+#define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi)
-static snd_kcontrol_new_t snd_fm801_controls_multi[] __devinitdata = {
+static struct snd_kcontrol_new 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(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
@@ -1161,15 +1177,15 @@ FM801_SINGLE(SNDRV_CTL_NAME_IEC958("Raw Data ",CAPTURE,SWITCH), FM801_I2S_MODE,
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)
+static void snd_fm801_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- fm801_t *chip = bus->private_data;
+ struct fm801 *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
+static void snd_fm801_mixer_free_ac97(struct snd_ac97 *ac97)
{
- fm801_t *chip = ac97->private_data;
+ struct fm801 *chip = ac97->private_data;
if (ac97->num == 0) {
chip->ac97 = NULL;
} else {
@@ -1177,12 +1193,12 @@ static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
}
}
-static int __devinit snd_fm801_mixer(fm801_t *chip)
+static int __devinit snd_fm801_mixer(struct fm801 *chip)
{
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
unsigned int i;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_fm801_codec_write,
.read = snd_fm801_codec_read,
};
@@ -1215,7 +1231,86 @@ static int __devinit snd_fm801_mixer(fm801_t *chip)
* initialization routines
*/
-static int snd_fm801_free(fm801_t *chip)
+static int wait_for_codec(struct fm801 *chip, unsigned int codec_id,
+ unsigned short reg, unsigned long waits)
+{
+ unsigned long timeout = jiffies + waits;
+
+ outw(FM801_AC97_READ | (codec_id << FM801_AC97_ADDR_SHIFT) | reg,
+ FM801_REG(chip, AC97_CMD));
+ udelay(5);
+ do {
+ if ((inw(FM801_REG(chip, AC97_CMD)) & (FM801_AC97_VALID|FM801_AC97_BUSY))
+ == FM801_AC97_VALID)
+ return 0;
+ schedule_timeout_uninterruptible(1);
+ } while (time_after(timeout, jiffies));
+ return -EIO;
+}
+
+static int snd_fm801_chip_init(struct fm801 *chip, int resume)
+{
+ int id;
+ unsigned short cmdw;
+
+ /* codec cold reset + AC'97 warm reset */
+ outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL));
+ inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */
+ udelay(100);
+ outw(0, FM801_REG(chip, CODEC_CTRL));
+
+ if (wait_for_codec(chip, 0, AC97_RESET, msecs_to_jiffies(750)) < 0) {
+ snd_printk(KERN_ERR "Primary AC'97 codec not found\n");
+ if (! resume)
+ return -EIO;
+ }
+
+ if (chip->multichannel) {
+ if (chip->secondary_addr) {
+ wait_for_codec(chip, chip->secondary_addr,
+ AC97_VENDOR_ID1, msecs_to_jiffies(50));
+ } else {
+ /* my card has the secondary codec */
+ /* at address #3, so the loop is inverted */
+ for (id = 3; id > 0; id--) {
+ if (! wait_for_codec(chip, id, AC97_VENDOR_ID1,
+ msecs_to_jiffies(50))) {
+ cmdw = inw(FM801_REG(chip, AC97_DATA));
+ if (cmdw != 0xffff && cmdw != 0) {
+ chip->secondary = 1;
+ chip->secondary_addr = id;
+ break;
+ }
+ }
+ }
+ }
+
+ /* the recovery phase, it seems that probing for non-existing codec might */
+ /* cause timeout problems */
+ wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750));
+ }
+
+ /* init volume */
+ outw(0x0808, FM801_REG(chip, PCM_VOL));
+ outw(0x9f1f, FM801_REG(chip, FM_VOL));
+ outw(0x8808, FM801_REG(chip, I2S_VOL));
+
+ /* I2S control - I2S mode */
+ outw(0x0003, FM801_REG(chip, I2S_MODE));
+
+ /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */
+ cmdw = inw(FM801_REG(chip, IRQ_MASK));
+ cmdw &= ~0x0083;
+ outw(cmdw, FM801_REG(chip, IRQ_MASK));
+
+ /* interrupt clear */
+ outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS));
+
+ return 0;
+}
+
+
+static int snd_fm801_free(struct fm801 *chip)
{
unsigned short cmdw;
@@ -1232,7 +1327,7 @@ static int snd_fm801_free(fm801_t *chip)
snd_tea575x_exit(&chip->tea);
#endif
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
@@ -1240,23 +1335,21 @@ static int snd_fm801_free(fm801_t *chip)
return 0;
}
-static int snd_fm801_dev_free(snd_device_t *device)
+static int snd_fm801_dev_free(struct snd_device *device)
{
- fm801_t *chip = device->device_data;
+ struct fm801 *chip = device->device_data;
return snd_fm801_free(chip);
}
-static int __devinit snd_fm801_create(snd_card_t * card,
+static int __devinit snd_fm801_create(struct snd_card *card,
struct pci_dev * pci,
int tea575x_tuner,
- fm801_t ** rchip)
+ struct fm801 ** rchip)
{
- fm801_t *chip;
- unsigned char rev, id;
- unsigned short cmdw;
- unsigned long timeout;
+ struct fm801 *chip;
+ unsigned char rev;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_fm801_dev_free,
};
@@ -1278,7 +1371,8 @@ static int __devinit snd_fm801_create(snd_card_t * card,
return err;
}
chip->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", (void *)chip)) {
+ if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "FM801", chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq);
snd_fm801_free(chip);
return -EBUSY;
@@ -1290,80 +1384,7 @@ static int __devinit snd_fm801_create(snd_card_t * card,
if (rev >= 0xb1) /* FM801-AU */
chip->multichannel = 1;
- /* codec cold reset + AC'97 warm reset */
- outw((1<<5)|(1<<6), FM801_REG(chip, CODEC_CTRL));
- inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */
- udelay(100);
- outw(0, FM801_REG(chip, CODEC_CTRL));
-
- timeout = (jiffies + (3 * HZ) / 4) + 1; /* min 750ms */
-
- outw((1<<7) | (0 << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD));
- udelay(5);
- do {
- if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8))
- goto __ac97_secondary;
- schedule_timeout_uninterruptible(1);
- } while (time_after(timeout, jiffies));
- snd_printk(KERN_ERR "Primary AC'97 codec not found\n");
- snd_fm801_free(chip);
- return -EIO;
-
- __ac97_secondary:
- if (!chip->multichannel) /* lookup is not required */
- goto __ac97_ok;
- for (id = 3; id > 0; id--) { /* my card has the secondary codec */
- /* at address #3, so the loop is inverted */
-
- timeout = jiffies + HZ / 20;
-
- outw((1<<7) | (id << FM801_AC97_ADDR_SHIFT) | AC97_VENDOR_ID1, FM801_REG(chip, AC97_CMD));
- udelay(5);
- do {
- if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8)) {
- cmdw = inw(FM801_REG(chip, AC97_DATA));
- if (cmdw != 0xffff && cmdw != 0) {
- chip->secondary = 1;
- chip->secondary_addr = id;
- goto __ac97_ok;
- }
- }
- schedule_timeout_uninterruptible(1);
- } while (time_after(timeout, jiffies));
- }
-
- /* the recovery phase, it seems that probing for non-existing codec might */
- /* cause timeout problems */
- timeout = (jiffies + (3 * HZ) / 4) + 1; /* min 750ms */
-
- outw((1<<7) | (0 << FM801_AC97_ADDR_SHIFT), FM801_REG(chip, AC97_CMD));
- udelay(5);
- do {
- if ((inw(FM801_REG(chip, AC97_CMD)) & (3<<8)) == (1<<8))
- goto __ac97_ok;
- schedule_timeout_uninterruptible(1);
- } while (time_after(timeout, jiffies));
- snd_printk(KERN_ERR "Primary AC'97 codec not responding\n");
- snd_fm801_free(chip);
- return -EIO;
-
- __ac97_ok:
-
- /* init volume */
- outw(0x0808, FM801_REG(chip, PCM_VOL));
- outw(0x9f1f, FM801_REG(chip, FM_VOL));
- outw(0x8808, FM801_REG(chip, I2S_VOL));
-
- /* I2S control - I2S mode */
- outw(0x0003, FM801_REG(chip, I2S_MODE));
-
- /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */
- cmdw = inw(FM801_REG(chip, IRQ_MASK));
- cmdw &= ~0x0083;
- outw(cmdw, FM801_REG(chip, IRQ_MASK));
-
- /* interrupt clear */
- outw(FM801_IRQ_PLAYBACK|FM801_IRQ_CAPTURE|FM801_IRQ_MPU, FM801_REG(chip, IRQ_STATUS));
+ snd_fm801_chip_init(chip, 0);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_fm801_free(chip);
@@ -1391,9 +1412,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- fm801_t *chip;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct fm801 *chip;
+ struct snd_opl3 *opl3;
int err;
if (dev >= SNDRV_CARDS)
@@ -1410,6 +1431,7 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
strcpy(card->driver, "FM801");
strcpy(card->shortname, "ForteMedia FM801-");
@@ -1457,11 +1479,65 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
+#ifdef CONFIG_PM
+static unsigned char saved_regs[] = {
+ FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
+ FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2,
+ FM801_CAP_CTRL, FM801_CAP_COUNT, FM801_CAP_BUF1, FM801_CAP_BUF2,
+ FM801_CODEC_CTRL, FM801_I2S_MODE, FM801_VOLUME, FM801_GEN_CTRL,
+};
+
+static int snd_fm801_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct fm801 *chip = card->private_data;
+ int i;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_ac97_suspend(chip->ac97);
+ snd_ac97_suspend(chip->ac97_sec);
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
+ /* FIXME: tea575x suspend */
+
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return 0;
+}
+
+static int snd_fm801_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct fm801 *chip = card->private_data;
+ int i;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+
+ snd_fm801_chip_init(chip, 1);
+ snd_ac97_resume(chip->ac97);
+ snd_ac97_resume(chip->ac97_sec);
+ for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
+ outw(chip->saved_regs[i], chip->port + saved_regs[i]);
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+#endif
+
static struct pci_driver driver = {
.name = "FM801",
.id_table = snd_fm801_ids,
.probe = snd_card_fm801_probe,
.remove = __devexit_p(snd_card_fm801_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_fm801_suspend,
+ .resume = snd_fm801_resume,
+#endif
};
static int __init alsa_card_fm801_init(void)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0dbeeaf6113a..4a6dd97deba6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -155,8 +155,9 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t *conn_list, int max_conns)
{
unsigned int parm;
- int i, j, conn_len, num_tupples, conns;
+ int i, conn_len, conns;
unsigned int shift, num_elems, mask;
+ hda_nid_t prev_nid;
snd_assert(conn_list && max_conns > 0, return -EINVAL);
@@ -171,7 +172,6 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
num_elems = 4;
}
conn_len = parm & AC_CLIST_LENGTH;
- num_tupples = num_elems / 2;
mask = (1 << (shift-1)) - 1;
if (! conn_len)
@@ -186,40 +186,38 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
/* multi connection */
conns = 0;
- for (i = 0; i < conn_len; i += num_elems) {
- parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, i);
- for (j = 0; j < num_tupples; j++) {
- int range_val;
- hda_nid_t val1, val2, n;
- range_val = parm & (1 << (shift-1)); /* ranges */
- val1 = parm & mask;
- parm >>= shift;
- val2 = parm & mask;
- parm >>= shift;
- if (range_val) {
- /* ranges between val1 and val2 */
- if (val1 > val2) {
- snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", val1, val2);
- continue;
- }
- for (n = val1; n <= val2; n++) {
- if (conns >= max_conns)
- return -EINVAL;
- conn_list[conns++] = n;
- }
- } else {
- if (! val1)
- break;
- if (conns >= max_conns)
- return -EINVAL;
- conn_list[conns++] = val1;
- if (! val2)
- break;
- if (conns >= max_conns)
+ prev_nid = 0;
+ for (i = 0; i < conn_len; i++) {
+ int range_val;
+ hda_nid_t val, n;
+
+ if (i % num_elems == 0)
+ parm = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONNECT_LIST, i);
+ range_val = !! (parm & (1 << (shift-1))); /* ranges */
+ val = parm & mask;
+ parm >>= shift;
+ if (range_val) {
+ /* ranges between the previous and this one */
+ if (! prev_nid || prev_nid >= val) {
+ snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", prev_nid, val);
+ continue;
+ }
+ for (n = prev_nid + 1; n <= val; n++) {
+ if (conns >= max_conns) {
+ snd_printk(KERN_ERR "Too many connections\n");
return -EINVAL;
- conn_list[conns++] = val2;
+ }
+ conn_list[conns++] = n;
+ }
+ } else {
+ if (conns >= max_conns) {
+ snd_printk(KERN_ERR "Too many connections\n");
+ return -EINVAL;
}
+ conn_list[conns++] = val;
}
+ prev_nid = val;
}
return conns;
}
@@ -288,6 +286,9 @@ static int init_unsol_queue(struct hda_bus *bus)
{
struct hda_bus_unsolicited *unsol;
+ if (bus->unsol) /* already initialized */
+ return 0;
+
unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
if (! unsol) {
snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
@@ -329,7 +330,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
return 0;
}
-static int snd_hda_bus_dev_free(snd_device_t *device)
+static int snd_hda_bus_dev_free(struct snd_device *device)
{
struct hda_bus *bus = device->device_data;
return snd_hda_bus_free(bus);
@@ -343,12 +344,12 @@ static int snd_hda_bus_dev_free(snd_device_t *device)
*
* Returns 0 if successful, or a negative error code.
*/
-int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
struct hda_bus **busp)
{
struct hda_bus *bus;
int err;
- static snd_device_ops_t dev_ops = {
+ static struct snd_device_ops dev_ops = {
.dev_free = snd_hda_bus_dev_free,
};
@@ -373,8 +374,6 @@ int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
init_MUTEX(&bus->cmd_mutex);
INIT_LIST_HEAD(&bus->codec_list);
- init_unsol_queue(bus);
-
if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) {
snd_hda_bus_free(bus);
return err;
@@ -455,6 +454,27 @@ static void setup_fg_nodes(struct hda_codec *codec)
}
/*
+ * read widget caps for each widget and store in cache
+ */
+static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
+{
+ int i;
+ hda_nid_t nid;
+
+ codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
+ &codec->start_nid);
+ codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
+ if (! codec->wcaps)
+ return -ENOMEM;
+ nid = codec->start_nid;
+ for (i = 0; i < codec->num_nodes; i++, nid++)
+ codec->wcaps[i] = snd_hda_param_read(codec, nid,
+ AC_PAR_AUDIO_WIDGET_CAP);
+ return 0;
+}
+
+
+/*
* codec destructor
*/
static void snd_hda_codec_free(struct hda_codec *codec)
@@ -465,6 +485,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
+ kfree(codec->amp_info);
+ kfree(codec->wcaps);
kfree(codec);
}
@@ -518,6 +540,12 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
return -ENODEV;
}
+ if (read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg) < 0) {
+ snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
+ snd_hda_codec_free(codec);
+ return -ENOMEM;
+ }
+
if (! codec->subsystem_id) {
hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
codec->subsystem_id = snd_hda_codec_read(codec, nid, 0,
@@ -539,6 +567,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
return err;
}
+ if (codec->patch_ops.unsol_event)
+ init_unsol_queue(bus);
+
snd_hda_codec_proc_new(codec);
sprintf(component, "HDA:%08x", codec->vendor_id);
@@ -586,6 +617,8 @@ static void init_amp_hash(struct hda_codec *codec)
{
memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash));
codec->num_amp_entries = 0;
+ codec->amp_info_size = 0;
+ codec->amp_info = NULL;
}
/* query the hash. allocate an entry if not found. */
@@ -603,9 +636,22 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
}
/* add a new hash entry */
- if (codec->num_amp_entries >= ARRAY_SIZE(codec->amp_info)) {
- snd_printk(KERN_ERR "hda_codec: Tooooo many amps!\n");
- return NULL;
+ if (codec->num_amp_entries >= codec->amp_info_size) {
+ /* reallocate the array */
+ int new_size = codec->amp_info_size + 64;
+ struct hda_amp_info *new_info = kcalloc(new_size, sizeof(struct hda_amp_info),
+ GFP_KERNEL);
+ if (! new_info) {
+ snd_printk(KERN_ERR "hda_codec: can't malloc amp_info\n");
+ return NULL;
+ }
+ if (codec->amp_info) {
+ memcpy(new_info, codec->amp_info,
+ codec->amp_info_size * sizeof(struct hda_amp_info));
+ kfree(codec->amp_info);
+ }
+ codec->amp_info_size = new_size;
+ codec->amp_info = new_info;
}
cur = codec->num_amp_entries++;
info = &codec->amp_info[cur];
@@ -627,7 +673,7 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
if (! info)
return 0;
if (! (info->status & INFO_AMP_CAPS)) {
- if (!(snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_AMP_OVRD))
+ if (! (get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
nid = codec->afg;
info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ?
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
@@ -712,7 +758,7 @@ static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
/* volume */
-int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
u16 nid = get_amp_nid(kcontrol);
@@ -733,7 +779,7 @@ int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
@@ -749,7 +795,7 @@ int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
@@ -771,7 +817,7 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* switch */
-int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int chs = get_amp_channels(kcontrol);
@@ -782,7 +828,7 @@ int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
@@ -798,7 +844,7 @@ int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
@@ -829,7 +875,7 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
#define AMP_VAL_IDX_SHIFT 19
#define AMP_VAL_IDX_MASK (0x0f<<19)
-int snd_hda_mixer_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned long pval;
@@ -844,7 +890,7 @@ int snd_hda_mixer_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return err;
}
-int snd_hda_mixer_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned long pval;
@@ -869,14 +915,14 @@ int snd_hda_mixer_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
* SPDIF out controls
*/
-static int snd_hda_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_hda_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
IEC958_AES0_NONAUDIO |
@@ -887,7 +933,7 @@ static int snd_hda_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
IEC958_AES0_NONAUDIO |
@@ -895,7 +941,7 @@ static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_hda_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -958,7 +1004,7 @@ static unsigned int convert_to_spdif_status(unsigned short val)
return sbits;
}
-static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value;
@@ -984,7 +1030,7 @@ static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
return change;
}
-static int snd_hda_spdif_out_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -993,7 +1039,7 @@ static int snd_hda_spdif_out_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_hda_spdif_out_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -1001,7 +1047,7 @@ static int snd_hda_spdif_out_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
return 0;
}
-static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value;
@@ -1024,7 +1070,7 @@ static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
return change;
}
-static snd_kcontrol_new_t dig_mixes[] = {
+static struct snd_kcontrol_new dig_mixes[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1069,8 +1115,8 @@ static snd_kcontrol_new_t dig_mixes[] = {
int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
{
int err;
- snd_kcontrol_t *kctl;
- snd_kcontrol_new_t *dig_mix;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new *dig_mix;
for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
@@ -1089,7 +1135,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
#define snd_hda_spdif_in_switch_info snd_hda_spdif_out_switch_info
-static int snd_hda_spdif_in_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -1097,7 +1143,7 @@ static int snd_hda_spdif_in_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_hda_spdif_in_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value;
@@ -1114,7 +1160,7 @@ static int snd_hda_spdif_in_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return change;
}
-static int snd_hda_spdif_in_status_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value;
@@ -1130,7 +1176,7 @@ static int snd_hda_spdif_in_status_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static snd_kcontrol_new_t dig_in_ctls[] = {
+static struct snd_kcontrol_new dig_in_ctls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
@@ -1161,8 +1207,8 @@ static snd_kcontrol_new_t dig_in_ctls[] = {
int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
{
int err;
- snd_kcontrol_t *kctl;
- snd_kcontrol_new_t *dig_mix;
+ struct snd_kcontrol *kctl;
+ struct snd_kcontrol_new *dig_mix;
for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
@@ -1175,6 +1221,31 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
}
+/*
+ * set power state of the codec
+ */
+static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
+ unsigned int power_state)
+{
+ hda_nid_t nid, nid_start;
+ int nodes;
+
+ snd_hda_codec_write(codec, fg, 0, AC_VERB_SET_POWER_STATE,
+ power_state);
+
+ nodes = snd_hda_get_sub_nodes(codec, fg, &nid_start);
+ for (nid = nid_start; nid < nodes + nid_start; nid++) {
+ if (get_wcaps(codec, nid) & AC_WCAP_POWER)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_POWER_STATE,
+ power_state);
+ }
+
+ if (power_state == AC_PWRST_D0)
+ msleep(10);
+}
+
+
/**
* snd_hda_build_controls - build mixer controls
* @bus: the BUS
@@ -1202,6 +1273,9 @@ int snd_hda_build_controls(struct hda_bus *bus)
list_for_each(p, &bus->codec_list) {
struct hda_codec *codec = list_entry(p, struct hda_codec, list);
int err;
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D0);
if (! codec->patch_ops.init)
continue;
err = codec->patch_ops.init(codec);
@@ -1320,7 +1394,7 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
val = 0;
if (nid != codec->afg &&
- snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
+ (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
if (val == -1)
return -EIO;
@@ -1342,7 +1416,7 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
unsigned int bps;
unsigned int wcaps;
- wcaps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ wcaps = get_wcaps(codec, nid);
streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
if (streams == -1)
return -EIO;
@@ -1412,7 +1486,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int val = 0, rate, stream;
if (nid != codec->afg &&
- snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
+ (get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD)) {
val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
if (val == -1)
return 0;
@@ -1478,7 +1552,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
*/
static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
return 0;
}
@@ -1487,7 +1561,7 @@ static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
return 0;
@@ -1495,7 +1569,7 @@ static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
return 0;
@@ -1626,30 +1700,90 @@ int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_c
/**
* snd_hda_add_new_ctls - create controls from the array
* @codec: the HDA codec
- * @knew: the array of snd_kcontrol_new_t
+ * @knew: the array of struct snd_kcontrol_new
*
* This helper function creates and add new controls in the given array.
* The array must be terminated with an empty entry as terminator.
*
* Returns 0 if successful, or a negative error code.
*/
-int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
+int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
{
int err;
for (; knew->name; knew++) {
- err = snd_ctl_add(codec->bus->card, snd_ctl_new1(knew, codec));
- if (err < 0)
- return err;
+ struct snd_kcontrol *kctl;
+ kctl = snd_ctl_new1(knew, codec);
+ if (! kctl)
+ return -ENOMEM;
+ err = snd_ctl_add(codec->bus->card, kctl);
+ if (err < 0) {
+ if (! codec->addr)
+ return err;
+ kctl = snd_ctl_new1(knew, codec);
+ if (! kctl)
+ return -ENOMEM;
+ kctl->id.device = codec->addr;
+ if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * Channel mode helper
+ */
+int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo,
+ const struct hda_channel_mode *chmode, int num_chmodes)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = num_chmodes;
+ if (uinfo->value.enumerated.item >= num_chmodes)
+ uinfo->value.enumerated.item = num_chmodes - 1;
+ sprintf(uinfo->value.enumerated.name, "%dch",
+ chmode[uinfo->value.enumerated.item].channels);
+ return 0;
+}
+
+int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode, int num_chmodes,
+ int max_channels)
+{
+ int i;
+
+ for (i = 0; i < num_chmodes; i++) {
+ if (max_channels == chmode[i].channels) {
+ ucontrol->value.enumerated.item[0] = i;
+ break;
+ }
}
return 0;
}
+int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode, int num_chmodes,
+ int *max_channelsp)
+{
+ unsigned int mode;
+
+ mode = ucontrol->value.enumerated.item[0];
+ snd_assert(mode < num_chmodes, return -EINVAL);
+ if (*max_channelsp == chmode[mode].channels && ! codec->in_resume)
+ return 0;
+ /* change the current channel setting */
+ *max_channelsp = chmode[mode].channels;
+ if (chmode[mode].sequence)
+ snd_hda_sequence_write(codec, chmode[mode].sequence);
+ return 1;
+}
/*
* input MUX helper
*/
-int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo)
+int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo)
{
unsigned int index;
@@ -1664,7 +1798,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t
}
int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
- snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
+ struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
unsigned int *cur_val)
{
unsigned int idx;
@@ -1715,7 +1849,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *m
* set up more restrictions for analog out
*/
int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
substream->runtime->hw.channels_max = mout->max_channels;
return snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -1729,7 +1863,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out
int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
hda_nid_t *nids = mout->dac_nids;
int chs = substream->runtime->channels;
@@ -1792,8 +1926,18 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
/*
* Helper for automatic ping configuration
*/
+
+static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
+{
+ for (; *list; list++)
+ if (*list == nid)
+ return 1;
+ return 0;
+}
+
/* parse all pin widgets and store the useful pin nids to cfg */
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg,
+ hda_nid_t *ignore_nids)
{
hda_nid_t nid, nid_start;
int i, j, nodes;
@@ -1806,8 +1950,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
for (nid = nid_start; nid < nodes + nid_start; nid++) {
- unsigned int wid_caps = snd_hda_param_read(codec, nid,
- AC_PAR_AUDIO_WIDGET_CAP);
+ unsigned int wid_caps = get_wcaps(codec, nid);
unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
unsigned int def_conf;
short assoc, loc;
@@ -1815,13 +1958,16 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
/* read all default configuration for pin complex */
if (wid_type != AC_WID_PIN)
continue;
+ /* ignore the given nids (e.g. pc-beep returns error) */
+ if (ignore_nids && is_in_nid_list(nid, ignore_nids))
+ continue;
+
def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
continue;
loc = get_defcfg_location(def_conf);
switch (get_defcfg_device(def_conf)) {
case AC_JACK_LINE_OUT:
- case AC_JACK_SPEAKER:
seq = get_defcfg_sequence(def_conf);
assoc = get_defcfg_association(def_conf);
if (! assoc)
@@ -1836,6 +1982,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
sequences[cfg->line_outs] = seq;
cfg->line_outs++;
break;
+ case AC_JACK_SPEAKER:
+ cfg->speaker_pin = nid;
+ break;
case AC_JACK_HP_OUT:
cfg->hp_pin = nid;
break;
@@ -1902,6 +2051,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
return 0;
}
+/* labels for input pins */
+const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
+ "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
+};
+
+
#ifdef CONFIG_PM
/*
* power management
@@ -1923,6 +2078,9 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
struct hda_codec *codec = list_entry(p, struct hda_codec, list);
if (codec->patch_ops.suspend)
codec->patch_ops.suspend(codec, state);
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D3);
}
return 0;
}
@@ -1940,6 +2098,9 @@ int snd_hda_resume(struct hda_bus *bus)
list_for_each(p, &bus->codec_list) {
struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D0);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
}
@@ -1949,15 +2110,15 @@ int snd_hda_resume(struct hda_bus *bus)
/**
* snd_hda_resume_ctls - resume controls in the new control list
* @codec: the HDA codec
- * @knew: the array of snd_kcontrol_new_t
+ * @knew: the array of struct snd_kcontrol_new
*
- * This function resumes the mixer controls in the snd_kcontrol_new_t array,
+ * This function resumes the mixer controls in the struct snd_kcontrol_new array,
* originally for snd_hda_add_new_ctls().
* The array must be terminated with an empty entry as terminator.
*/
-int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
+int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
{
- snd_ctl_elem_value_t *val;
+ struct snd_ctl_elem_value *val;
val = kmalloc(sizeof(*val), GFP_KERNEL);
if (! val)
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 1179d6cfa82a..63e26c7a2b7a 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -98,7 +98,7 @@ enum {
#define AC_VERB_SET_UNSOLICITED_ENABLE 0x708
#define AC_VERB_SET_PIN_SENSE 0x709
#define AC_VERB_SET_BEEP_CONTROL 0x70a
-#define AC_VERB_SET_EAPD_BTLENALBE 0x70c
+#define AC_VERB_SET_EAPD_BTLENABLE 0x70c
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
@@ -214,6 +214,12 @@ enum {
#define AC_PWRST_D2SUP (1<<2)
#define AC_PWRST_D3SUP (1<<3)
+/* Power state values */
+#define AC_PWRST_D0 0x00
+#define AC_PWRST_D1 0x01
+#define AC_PWRST_D2 0x02
+#define AC_PWRST_D3 0x03
+
/* Processing capabilies */
#define AC_PCAP_BENIGN (1<<0)
#define AC_PCAP_NUM_COEF (0xff<<8)
@@ -376,7 +382,7 @@ enum {
};
/* max. connections to a widget */
-#define HDA_MAX_CONNECTIONS 16
+#define HDA_MAX_CONNECTIONS 32
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS 0x0f
@@ -420,7 +426,7 @@ struct hda_bus_template {
* A hda_bus contains several codecs in the list codec_list.
*/
struct hda_bus {
- snd_card_t *card;
+ struct snd_card *card;
/* copied from template */
void *private_data;
@@ -437,7 +443,7 @@ struct hda_bus {
/* unsolicited event queue */
struct hda_bus_unsolicited *unsol;
- snd_info_entry_t *proc;
+ struct snd_info_entry *proc;
};
/*
@@ -481,14 +487,14 @@ struct hda_amp_info {
/* PCM callbacks */
struct hda_pcm_ops {
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
unsigned int stream_tag, unsigned int format,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
};
/* PCM information for each substream */
@@ -542,10 +548,16 @@ struct hda_codec {
/* codec specific info */
void *spec;
+ /* widget capabilities cache */
+ unsigned int num_nodes;
+ hda_nid_t start_nid;
+ u32 *wcaps;
+
/* hash for amp access */
u16 amp_hash[32];
int num_amp_entries;
- struct hda_amp_info amp_info[128]; /* big enough? */
+ int amp_info_size;
+ struct hda_amp_info *amp_info;
struct semaphore spdif_mutex;
unsigned int spdif_status; /* IEC958 status bits */
@@ -562,7 +574,7 @@ enum {
/*
* constructors
*/
-int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
struct hda_bus **busp);
int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
struct hda_codec **codecp);
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index d0eb9f2250aa..39edfcfd3abd 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -32,7 +32,8 @@
struct hda_gnode {
hda_nid_t nid; /* NID of this widget */
unsigned short nconns; /* number of input connections */
- hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; /* input connections */
+ hda_nid_t *conn_list;
+ hda_nid_t slist[2]; /* temporay list */
unsigned int wid_caps; /* widget capabilities */
unsigned char type; /* widget type */
unsigned char pin_ctl; /* pin controls */
@@ -84,6 +85,8 @@ static void snd_hda_generic_free(struct hda_codec *codec)
/* free all widgets */
list_for_each_safe(p, n, &spec->nid_list) {
struct hda_gnode *node = list_entry(p, struct hda_gnode, list);
+ if (node->conn_list != node->slist)
+ kfree(node->conn_list);
kfree(node);
}
kfree(spec);
@@ -97,18 +100,32 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
{
struct hda_gnode *node;
int nconns;
+ hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
node = kzalloc(sizeof(*node), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
node->nid = nid;
- nconns = snd_hda_get_connections(codec, nid, node->conn_list, HDA_MAX_CONNECTIONS);
+ nconns = snd_hda_get_connections(codec, nid, conn_list,
+ HDA_MAX_CONNECTIONS);
if (nconns < 0) {
kfree(node);
return nconns;
}
+ if (nconns <= ARRAY_SIZE(node->slist))
+ node->conn_list = node->slist;
+ else {
+ node->conn_list = kmalloc(sizeof(hda_nid_t) * nconns,
+ GFP_KERNEL);
+ if (! node->conn_list) {
+ snd_printk(KERN_ERR "hda-generic: cannot malloc\n");
+ kfree(node);
+ return -ENOMEM;
+ }
+ }
+ memcpy(node->conn_list, conn_list, nconns);
node->nconns = nconns;
- node->wid_caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ node->wid_caps = get_wcaps(codec, nid);
node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
if (node->type == AC_WID_PIN) {
@@ -389,14 +406,14 @@ static int parse_output(struct hda_codec *codec)
*/
/* control callbacks */
-static int capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int capture_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gspec *spec = codec->spec;
return snd_hda_input_mux_info(&spec->input_mux, uinfo);
}
-static int capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int capture_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gspec *spec = codec->spec;
@@ -405,7 +422,7 @@ static int capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gspec *spec = codec->spec;
@@ -617,7 +634,7 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
char name[32];
int err;
int created = 0;
- snd_kcontrol_new_t knew;
+ struct snd_kcontrol_new knew;
if (type)
sprintf(name, "%s %s Switch", type, dir_sfx);
@@ -625,14 +642,14 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
sprintf(name, "%s Switch", dir_sfx);
if ((node->wid_caps & AC_WCAP_IN_AMP) &&
(node->amp_in_caps & AC_AMPCAP_MUTE)) {
- knew = (snd_kcontrol_new_t)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
+ knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_MUTE)) {
- knew = (snd_kcontrol_new_t)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
+ knew = (struct snd_kcontrol_new)HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
@@ -645,14 +662,14 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
sprintf(name, "%s Volume", dir_sfx);
if ((node->wid_caps & AC_WCAP_IN_AMP) &&
(node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
- knew = (snd_kcontrol_new_t)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
+ knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
- knew = (snd_kcontrol_new_t)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
+ knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
@@ -667,7 +684,7 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
*/
static int check_existing_control(struct hda_codec *codec, const char *type, const char *dir)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
memset(&id, 0, sizeof(id));
sprintf(id.name, "%s %s Volume", type, dir);
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -710,7 +727,7 @@ static int build_input_controls(struct hda_codec *codec)
/* create input MUX if multiple sources are available */
if (spec->input_mux.num_items > 1) {
- static snd_kcontrol_new_t cap_sel = {
+ static struct snd_kcontrol_new cap_sel = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = capture_source_info,
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index ed525c03c996..a983deba4025 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -37,6 +37,7 @@
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -51,6 +52,7 @@ static int index = SNDRV_DEFAULT_IDX1;
static char *id = SNDRV_DEFAULT_STR1;
static char *model;
static int position_fix;
+static int probe_mask = -1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -60,6 +62,9 @@ module_param(model, charp, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param(position_fix, int, 0444);
MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size).");
+module_param(probe_mask, int, 0444);
+MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
+
/* just for backward compatibility */
static int enable;
@@ -237,11 +242,7 @@ enum {
/*
*/
-typedef struct snd_azx azx_t;
-typedef struct snd_azx_rb azx_rb_t;
-typedef struct snd_azx_dev azx_dev_t;
-
-struct snd_azx_dev {
+struct azx_dev {
u32 *bdl; /* virtual address of the BDL */
dma_addr_t bdl_addr; /* physical address of the BDL */
volatile u32 *posbuf; /* position buffer pointer */
@@ -257,7 +258,7 @@ struct snd_azx_dev {
u32 sd_int_sta_mask; /* stream int status mask */
/* pcm support */
- snd_pcm_substream_t *substream; /* assigned substream, set in PCM open */
+ struct snd_pcm_substream *substream; /* assigned substream, set in PCM open */
unsigned int format_val; /* format value to be set in the controller and the codec */
unsigned char stream_tag; /* assigned stream */
unsigned char index; /* stream index */
@@ -268,7 +269,7 @@ struct snd_azx_dev {
};
/* CORB/RIRB */
-struct snd_azx_rb {
+struct azx_rb {
u32 *buf; /* CORB/RIRB buffer
* Each CORB entry is 4byte, RIRB is 8byte
*/
@@ -279,8 +280,8 @@ struct snd_azx_rb {
u32 res; /* last read value */
};
-struct snd_azx {
- snd_card_t *card;
+struct azx {
+ struct snd_card *card;
struct pci_dev *pci;
/* chip type specific */
@@ -301,19 +302,19 @@ struct snd_azx {
struct semaphore open_mutex;
/* streams (x num_streams) */
- azx_dev_t *azx_dev;
+ struct azx_dev *azx_dev;
/* PCM */
unsigned int pcm_devs;
- snd_pcm_t *pcm[AZX_MAX_PCMS];
+ struct snd_pcm *pcm[AZX_MAX_PCMS];
/* HD codec */
unsigned short codec_mask;
struct hda_bus *bus;
/* CORB/RIRB */
- azx_rb_t corb;
- azx_rb_t rirb;
+ struct azx_rb corb;
+ struct azx_rb rirb;
/* BDL, CORB/RIRB and position buffers */
struct snd_dma_buffer bdl;
@@ -374,7 +375,7 @@ static char *driver_short_names[] __devinitdata = {
readb((dev)->sd_addr + ICH6_REG_##reg)
/* for pcm support */
-#define get_azx_dev(substream) (azx_dev_t*)(substream->runtime->private_data)
+#define get_azx_dev(substream) (substream->runtime->private_data)
/* Get the upper 32bit of the given dma_addr_t
* Compiler should optimize and eliminate the code if dma_addr_t is 32bit
@@ -390,7 +391,7 @@ static char *driver_short_names[] __devinitdata = {
/*
* CORB / RIRB interface
*/
-static int azx_alloc_cmd_io(azx_t *chip)
+static int azx_alloc_cmd_io(struct azx *chip)
{
int err;
@@ -404,7 +405,7 @@ static int azx_alloc_cmd_io(azx_t *chip)
return 0;
}
-static void azx_init_cmd_io(azx_t *chip)
+static void azx_init_cmd_io(struct azx *chip)
{
/* CORB set up */
chip->corb.addr = chip->rb.addr;
@@ -442,7 +443,7 @@ static void azx_init_cmd_io(azx_t *chip)
chip->rirb.rp = chip->rirb.cmds = 0;
}
-static void azx_free_cmd_io(azx_t *chip)
+static void azx_free_cmd_io(struct azx *chip)
{
/* disable ringbuffer DMAs */
azx_writeb(chip, RIRBCTL, 0);
@@ -453,7 +454,7 @@ static void azx_free_cmd_io(azx_t *chip)
static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int para)
{
- azx_t *chip = codec->bus->private_data;
+ struct azx *chip = codec->bus->private_data;
unsigned int wp;
u32 val;
@@ -480,7 +481,7 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
#define ICH6_RIRB_EX_UNSOL_EV (1<<4)
/* retrieve RIRB entry - called from interrupt handler */
-static void azx_update_rirb(azx_t *chip)
+static void azx_update_rirb(struct azx *chip)
{
unsigned int rp, wp;
u32 res, res_ex;
@@ -509,12 +510,14 @@ static void azx_update_rirb(azx_t *chip)
/* receive a response */
static unsigned int azx_get_response(struct hda_codec *codec)
{
- azx_t *chip = codec->bus->private_data;
+ struct azx *chip = codec->bus->private_data;
int timeout = 50;
while (chip->rirb.cmds) {
if (! --timeout) {
- snd_printk(KERN_ERR "azx_get_response timeout\n");
+ if (printk_ratelimit())
+ snd_printk(KERN_ERR
+ "azx_get_response timeout\n");
chip->rirb.rp = azx_readb(chip, RIRBWP);
chip->rirb.cmds = 0;
return -1;
@@ -543,7 +546,7 @@ static unsigned int azx_get_response(struct hda_codec *codec)
static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int para)
{
- azx_t *chip = codec->bus->private_data;
+ struct azx *chip = codec->bus->private_data;
u32 val;
int timeout = 50;
@@ -571,7 +574,7 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
/* receive a response */
static unsigned int azx_get_response(struct hda_codec *codec)
{
- azx_t *chip = codec->bus->private_data;
+ struct azx *chip = codec->bus->private_data;
int timeout = 50;
while (timeout--) {
@@ -589,7 +592,7 @@ static unsigned int azx_get_response(struct hda_codec *codec)
#endif /* USE_CORB_RIRB */
/* reset codec link */
-static int azx_reset(azx_t *chip)
+static int azx_reset(struct azx *chip)
{
int count;
@@ -639,7 +642,7 @@ static int azx_reset(azx_t *chip)
*/
/* enable interrupts */
-static void azx_int_enable(azx_t *chip)
+static void azx_int_enable(struct azx *chip)
{
/* enable controller CIE and GIE */
azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
@@ -647,13 +650,13 @@ static void azx_int_enable(azx_t *chip)
}
/* disable interrupts */
-static void azx_int_disable(azx_t *chip)
+static void azx_int_disable(struct azx *chip)
{
int i;
/* disable interrupts in stream descriptor */
for (i = 0; i < chip->num_streams; i++) {
- azx_dev_t *azx_dev = &chip->azx_dev[i];
+ struct azx_dev *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_CTL,
azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK);
}
@@ -667,13 +670,13 @@ static void azx_int_disable(azx_t *chip)
}
/* clear interrupts */
-static void azx_int_clear(azx_t *chip)
+static void azx_int_clear(struct azx *chip)
{
int i;
/* clear stream status */
for (i = 0; i < chip->num_streams; i++) {
- azx_dev_t *azx_dev = &chip->azx_dev[i];
+ struct azx_dev *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
}
@@ -688,7 +691,7 @@ static void azx_int_clear(azx_t *chip)
}
/* start a stream */
-static void azx_stream_start(azx_t *chip, azx_dev_t *azx_dev)
+static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
{
/* enable SIE */
azx_writeb(chip, INTCTL,
@@ -699,7 +702,7 @@ static void azx_stream_start(azx_t *chip, azx_dev_t *azx_dev)
}
/* stop a stream */
-static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
+static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
{
/* stop DMA */
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
@@ -714,7 +717,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
/*
* initialize the chip
*/
-static void azx_init_chip(azx_t *chip)
+static void azx_init_chip(struct azx *chip)
{
unsigned char reg;
@@ -762,8 +765,8 @@ static void azx_init_chip(azx_t *chip)
*/
static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
{
- azx_t *chip = dev_id;
- azx_dev_t *azx_dev;
+ struct azx *chip = dev_id;
+ struct azx_dev *azx_dev;
u32 status;
int i;
@@ -811,7 +814,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
/*
* set up BDL entries
*/
-static void azx_setup_periods(azx_dev_t *azx_dev)
+static void azx_setup_periods(struct azx_dev *azx_dev)
{
u32 *bdl = azx_dev->bdl;
dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
@@ -840,7 +843,7 @@ static void azx_setup_periods(azx_dev_t *azx_dev)
/*
* set up the SD for streaming
*/
-static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
+static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
{
unsigned char val;
int timeout;
@@ -900,7 +903,7 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
* Codec initialization
*/
-static int __devinit azx_codec_create(azx_t *chip, const char *model)
+static int __devinit azx_codec_create(struct azx *chip, const char *model)
{
struct hda_bus_template bus_temp;
int c, codecs, err;
@@ -917,7 +920,7 @@ static int __devinit azx_codec_create(azx_t *chip, const char *model)
codecs = 0;
for (c = 0; c < AZX_MAX_CODECS; c++) {
- if (chip->codec_mask & (1 << c)) {
+ if ((chip->codec_mask & (1 << c)) & probe_mask) {
err = snd_hda_codec_new(chip->bus, c, NULL);
if (err < 0)
continue;
@@ -938,7 +941,7 @@ 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)
+static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
{
int dev, i, nums;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -957,12 +960,12 @@ static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream)
}
/* release the assigned stream */
-static inline void azx_release_device(azx_dev_t *azx_dev)
+static inline void azx_release_device(struct azx_dev *azx_dev)
{
azx_dev->opened = 0;
}
-static snd_pcm_hardware_t azx_pcm_hw = {
+static struct snd_pcm_hardware azx_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -983,18 +986,18 @@ static snd_pcm_hardware_t azx_pcm_hw = {
};
struct azx_pcm {
- azx_t *chip;
+ struct azx *chip;
struct hda_codec *codec;
struct hda_pcm_stream *hinfo[2];
};
-static int azx_pcm_open(snd_pcm_substream_t *substream)
+static int azx_pcm_open(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
- azx_t *chip = apcm->chip;
- azx_dev_t *azx_dev;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct azx *chip = apcm->chip;
+ struct azx_dev *azx_dev;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
int err;
@@ -1026,12 +1029,12 @@ static int azx_pcm_open(snd_pcm_substream_t *substream)
return 0;
}
-static int azx_pcm_close(snd_pcm_substream_t *substream)
+static int azx_pcm_close(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
- azx_t *chip = apcm->chip;
- azx_dev_t *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
+ struct azx_dev *azx_dev = get_azx_dev(substream);
unsigned long flags;
down(&chip->open_mutex);
@@ -1045,15 +1048,15 @@ static int azx_pcm_close(snd_pcm_substream_t *substream)
return 0;
}
-static int azx_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params)
+static int azx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int azx_pcm_hw_free(snd_pcm_substream_t *substream)
+static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- azx_dev_t *azx_dev = get_azx_dev(substream);
+ struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
/* reset BDL address */
@@ -1066,13 +1069,13 @@ static int azx_pcm_hw_free(snd_pcm_substream_t *substream)
return snd_pcm_lib_free_pages(substream);
}
-static int azx_pcm_prepare(snd_pcm_substream_t *substream)
+static int azx_pcm_prepare(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- azx_t *chip = apcm->chip;
- azx_dev_t *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
+ struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
@@ -1101,11 +1104,11 @@ static int azx_pcm_prepare(snd_pcm_substream_t *substream)
azx_dev->format_val, substream);
}
-static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- azx_dev_t *azx_dev = get_azx_dev(substream);
- azx_t *chip = apcm->chip;
+ struct azx_dev *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
int err = 0;
spin_lock(&chip->reg_lock);
@@ -1136,11 +1139,11 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
return err;
}
-static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
- azx_t *chip = apcm->chip;
- azx_dev_t *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
+ struct azx_dev *azx_dev = get_azx_dev(substream);
unsigned int pos;
if (chip->position_fix == POS_FIX_POSBUF) {
@@ -1151,38 +1154,13 @@ 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;
-#if 0 /* disabled temprarily, auto-correction doesn't work well... */
- 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;
- }
-#else
- else if (chip->position_fix == POS_FIX_AUTO)
- pos += azx_dev->fifo_size;
-#endif
}
if (pos >= azx_dev->bufsize)
pos = 0;
return bytes_to_frames(substream->runtime, pos);
}
-static snd_pcm_ops_t azx_pcm_ops = {
+static struct snd_pcm_ops azx_pcm_ops = {
.open = azx_pcm_open,
.close = azx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1193,16 +1171,16 @@ static snd_pcm_ops_t azx_pcm_ops = {
.pointer = azx_pcm_pointer,
};
-static void azx_pcm_free(snd_pcm_t *pcm)
+static void azx_pcm_free(struct snd_pcm *pcm)
{
kfree(pcm->private_data);
}
-static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec,
+static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
struct hda_pcm *cpcm, int pcm_dev)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
struct azx_pcm *apcm;
snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL);
@@ -1236,7 +1214,7 @@ static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec,
return 0;
}
-static int __devinit azx_pcm_create(azx_t *chip)
+static int __devinit azx_pcm_create(struct azx *chip)
{
struct list_head *p;
struct hda_codec *codec;
@@ -1288,7 +1266,7 @@ static int __devinit azx_pcm_create(azx_t *chip)
/*
* mixer creation - all stuff is implemented in hda module
*/
-static int __devinit azx_mixer_create(azx_t *chip)
+static int __devinit azx_mixer_create(struct azx *chip)
{
return snd_hda_build_controls(chip->bus);
}
@@ -1297,7 +1275,7 @@ static int __devinit azx_mixer_create(azx_t *chip)
/*
* initialize SD streams
*/
-static int __devinit azx_init_stream(azx_t *chip)
+static int __devinit azx_init_stream(struct azx *chip)
{
int i;
@@ -1306,7 +1284,7 @@ static int __devinit azx_init_stream(azx_t *chip)
*/
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];
+ struct azx_dev *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
@@ -1327,28 +1305,33 @@ static int __devinit azx_init_stream(azx_t *chip)
/*
* power management
*/
-static int azx_suspend(snd_card_t *card, pm_message_t state)
+static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
- azx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct azx *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < chip->pcm_devs; i++)
- if (chip->pcm[i])
- snd_pcm_suspend_all(chip->pcm[i]);
+ snd_pcm_suspend_all(chip->pcm[i]);
snd_hda_suspend(chip->bus, state);
azx_free_cmd_io(chip);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int azx_resume(snd_card_t *card)
+static int azx_resume(struct pci_dev *pci)
{
- azx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct azx *chip = card->private_data;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
azx_init_chip(chip);
snd_hda_resume(chip->bus);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
@@ -1357,7 +1340,7 @@ static int azx_resume(snd_card_t *card)
/*
* destructor
*/
-static int azx_free(azx_t *chip)
+static int azx_free(struct azx *chip)
{
if (chip->initialized) {
int i;
@@ -1399,7 +1382,7 @@ static int azx_free(azx_t *chip)
return 0;
}
-static int azx_dev_free(snd_device_t *device)
+static int azx_dev_free(struct snd_device *device)
{
return azx_free(device->device_data);
}
@@ -1407,13 +1390,13 @@ 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, int driver_type,
- azx_t **rchip)
+static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
+ int driver_type,
+ struct azx **rchip)
{
- azx_t *chip;
+ struct azx *chip;
int err = 0;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = azx_dev_free,
};
@@ -1437,7 +1420,7 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
chip->irq = -1;
chip->driver_type = driver_type;
- chip->position_fix = posfix;
+ chip->position_fix = position_fix ? position_fix : POS_FIX_POSBUF;
#if BITS_PER_LONG != 64
/* Fix up base address on ULI M5461 */
@@ -1545,8 +1528,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- azx_t *chip;
+ struct snd_card *card;
+ struct azx *chip;
int err = 0;
card = snd_card_new(index, id, THIS_MODULE, 0);
@@ -1555,11 +1538,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, pci_id->driver_data,
+ if ((err = azx_create(card, pci, pci_id->driver_data,
&chip)) < 0) {
snd_card_free(card);
return err;
}
+ card->private_data = chip;
/* create codec instances */
if ((err = azx_codec_create(chip, model)) < 0) {
@@ -1579,7 +1563,6 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
return err;
}
- snd_card_set_pm_callback(card, azx_suspend, azx_resume, chip);
snd_card_set_dev(card, &pci->dev);
if ((err = snd_card_register(card)) < 0) {
@@ -1619,7 +1602,10 @@ static struct pci_driver driver = {
.id_table = azx_ids,
.probe = azx_probe,
.remove = __devexit_p(azx_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = azx_suspend,
+ .resume = azx_resume,
+#endif
};
static int __init alsa_card_azx_init(void)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index f51a56f813c8..c82d2a72d13e 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -60,12 +60,12 @@
#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
-int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
-int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
-int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
-int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
-int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
-int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
/* mono switch binding multiple inputs */
#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
@@ -78,8 +78,8 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
/* stereo switch binding multiple inputs */
#define HDA_BIND_MUTE(xname,nid,indices,dir) HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir)
-int snd_hda_mixer_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
-int snd_hda_mixer_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid);
int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
@@ -87,7 +87,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
/*
* input MUX helper
*/
-#define HDA_MAX_NUM_INPUTS 8
+#define HDA_MAX_NUM_INPUTS 16
struct hda_input_mux_item {
const char *label;
unsigned int index;
@@ -97,12 +97,29 @@ struct hda_input_mux {
struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS];
};
-int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo);
+int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo);
int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
- snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
+ struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
unsigned int *cur_val);
/*
+ * Channel mode helper
+ */
+struct hda_channel_mode {
+ int channels;
+ const struct hda_verb *sequence;
+};
+
+int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo,
+ const struct hda_channel_mode *chmode, int num_chmodes);
+int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode, int num_chmodes,
+ int max_channels);
+int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
+ const struct hda_channel_mode *chmode, int num_chmodes,
+ int *max_channelsp);
+
+/*
* Multi-channel / digital-out PCM helper
*/
@@ -121,11 +138,11 @@ struct hda_multi_out {
int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout);
int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout);
int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream);
+ struct snd_pcm_substream *substream);
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout);
/*
@@ -153,13 +170,13 @@ struct hda_board_config {
};
int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
-int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
/*
* power management
*/
#ifdef CONFIG_PM
-int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
int snd_hda_resume_spdif_out(struct hda_codec *codec);
int snd_hda_resume_spdif_in(struct hda_codec *codec);
#endif
@@ -194,9 +211,12 @@ enum {
AUTO_PIN_LAST
};
+extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
+
struct auto_pin_cfg {
int line_outs;
- hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
+ hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */
+ hda_nid_t speaker_pin;
hda_nid_t hp_pin;
hda_nid_t input_pins[AUTO_PIN_LAST];
hda_nid_t dig_out_pin;
@@ -209,6 +229,33 @@ struct auto_pin_cfg {
#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg,
+ hda_nid_t *ignore_nids);
+
+/* amp values */
+#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO 0xb000
+/* pinctl values */
+#define PIN_IN 0x20
+#define PIN_VREF80 0x24
+#define PIN_VREF50 0x21
+#define PIN_OUT 0x40
+#define PIN_HP 0xc0
+#define PIN_HP_AMP 0x80
+
+/*
+ * get widget capabilities
+ */
+static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
+{
+ if (nid < codec->start_nid ||
+ nid >= codec->start_nid + codec->num_nodes)
+ return snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ return codec->wcaps[nid - codec->start_nid];
+}
+
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 39ddf1cd9019..ca514a6a5875 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -26,6 +26,7 @@
#include <linux/pci.h>
#include <sound/core.h>
#include "hda_codec.h"
+#include "hda_local.h"
static const char *get_wid_type_name(unsigned int wid_value)
{
@@ -47,7 +48,7 @@ static const char *get_wid_type_name(unsigned int wid_value)
return "UNKOWN Widget";
}
-static void print_amp_caps(snd_info_buffer_t *buffer,
+static void print_amp_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid, int dir)
{
unsigned int caps;
@@ -66,7 +67,7 @@ static void print_amp_caps(snd_info_buffer_t *buffer,
(caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
}
-static void print_amp_vals(snd_info_buffer_t *buffer,
+static void print_amp_vals(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid,
int dir, int stereo, int indices)
{
@@ -91,7 +92,7 @@ static void print_amp_vals(snd_info_buffer_t *buffer,
snd_iprintf(buffer, "\n");
}
-static void print_pcm_caps(snd_info_buffer_t *buffer,
+static void print_pcm_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
@@ -160,7 +161,7 @@ static const char *get_jack_color(u32 cfg)
return "UNKNOWN";
}
-static void print_pin_caps(snd_info_buffer_t *buffer,
+static void print_pin_caps(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
@@ -194,7 +195,7 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
}
-static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct hda_codec *codec = entry->private_data;
char buf[32];
@@ -309,7 +310,7 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
int snd_hda_codec_proc_new(struct hda_codec *codec)
{
char name[32];
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
int err;
snprintf(name, sizeof(name), "codec#%d", codec->addr);
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index d7d636decef8..1ada1b075c9a 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1,5 +1,5 @@
/*
- * HD audio interface patch for AD1981HD, AD1983, AD1986A
+ * HD audio interface patch for AD1981HD, AD1983, AD1986A, AD1988
*
* Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
*
@@ -28,10 +28,10 @@
#include "hda_local.h"
struct ad198x_spec {
- snd_kcontrol_new_t *mixers[5];
+ struct snd_kcontrol_new *mixers[5];
int num_mixers;
- const struct hda_verb *init_verbs[3]; /* initialization verbs
+ const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL termination!
*/
unsigned int num_init_verbs;
@@ -41,6 +41,7 @@ struct ad198x_spec {
* max_channels, dacs must be set
* dig_out_nid and hp_nid are optional
*/
+ unsigned int cur_eapd;
/* capture */
unsigned int num_adc_nids;
@@ -49,10 +50,11 @@ struct ad198x_spec {
/* capture source */
const struct hda_input_mux *input_mux;
+ hda_nid_t *capsrc_nids;
unsigned int cur_mux[3];
/* channel model */
- const struct alc_channel_mode *channel_mode;
+ const struct hda_channel_mode *channel_mode;
int num_channel_mode;
/* PCM information */
@@ -60,12 +62,19 @@ struct ad198x_spec {
struct semaphore amp_mutex; /* PCM volume/mute control mutex */
unsigned int spdif_route;
+
+ /* dynamic controls, init_verbs and input_mux */
+ struct auto_pin_cfg autocfg;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
+ struct hda_input_mux private_imux;
+ hda_nid_t private_dac_nids[4];
};
/*
* input MUX handling (common part)
*/
-static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
@@ -73,7 +82,7 @@ static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return snd_hda_input_mux_info(spec->input_mux, uinfo);
}
-static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
@@ -83,14 +92,15 @@ static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
- spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+ spec->capsrc_nids[adc_idx],
+ &spec->cur_mux[adc_idx]);
}
/*
@@ -135,7 +145,7 @@ static int ad198x_build_controls(struct hda_codec *codec)
*/
static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
@@ -145,7 +155,7 @@ static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
@@ -154,7 +164,7 @@ static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
@@ -165,7 +175,7 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
*/
static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
@@ -173,7 +183,7 @@ static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
@@ -186,7 +196,7 @@ static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
@@ -196,7 +206,7 @@ static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
@@ -281,6 +291,14 @@ static int ad198x_build_pcms(struct hda_codec *codec)
static void ad198x_free(struct hda_codec *codec)
{
+ struct ad198x_spec *spec = codec->spec;
+ unsigned int i;
+
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
kfree(codec->spec);
}
@@ -348,7 +366,7 @@ static struct hda_input_mux ad1986a_capture_source = {
#define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
-static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *ad = codec->spec;
@@ -359,7 +377,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *ad = codec->spec;
@@ -377,7 +395,7 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
-static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *ad = codec->spec;
@@ -388,7 +406,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *ad = codec->spec;
@@ -407,7 +425,7 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
/*
* mixers
*/
-static snd_kcontrol_new_t ad1986a_mixers[] = {
+static struct snd_kcontrol_new ad1986a_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
@@ -535,6 +553,7 @@ static int patch_ad1986a(struct hda_codec *codec)
spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
spec->num_adc_nids = 1;
spec->adc_nids = ad1986a_adc_nids;
+ spec->capsrc_nids = ad1986a_adc_nids;
spec->input_mux = &ad1986a_capture_source;
spec->num_mixers = 1;
spec->mixers[0] = ad1986a_mixers;
@@ -570,7 +589,7 @@ static struct hda_input_mux ad1983_capture_source = {
/*
* SPDIF playback route
*/
-static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "PCM", "ADC" };
@@ -583,7 +602,7 @@ static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
@@ -592,7 +611,7 @@ static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct ad198x_spec *spec = codec->spec;
@@ -606,7 +625,7 @@ static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static snd_kcontrol_new_t ad1983_mixers[] = {
+static struct snd_kcontrol_new ad1983_mixers[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
@@ -698,6 +717,7 @@ static int patch_ad1983(struct hda_codec *codec)
spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
spec->num_adc_nids = 1;
spec->adc_nids = ad1983_adc_nids;
+ spec->capsrc_nids = ad1983_adc_nids;
spec->input_mux = &ad1983_capture_source;
spec->num_mixers = 1;
spec->mixers[0] = ad1983_mixers;
@@ -736,7 +756,7 @@ static struct hda_input_mux ad1981_capture_source = {
},
};
-static snd_kcontrol_new_t ad1981_mixers[] = {
+static struct snd_kcontrol_new ad1981_mixers[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
@@ -843,6 +863,7 @@ static int patch_ad1981(struct hda_codec *codec)
spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
spec->num_adc_nids = 1;
spec->adc_nids = ad1981_adc_nids;
+ spec->capsrc_nids = ad1981_adc_nids;
spec->input_mux = &ad1981_capture_source;
spec->num_mixers = 1;
spec->mixers[0] = ad1981_mixers;
@@ -857,11 +878,1278 @@ static int patch_ad1981(struct hda_codec *codec)
/*
+ * AD1988
+ *
+ * Output pins and routes
+ *
+ * Pin Mix Sel DAC (*)
+ * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
+ * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
+ * port-C 0x15 (mute) <- 0x2c <- 0x31 <- 05/0a
+ * port-D 0x12 (mute/hp) <- 0x29 <- 04
+ * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
+ * port-F 0x16 (mute) <- 0x2a <- 06
+ * port-G 0x24 (mute) <- 0x27 <- 05
+ * port-H 0x25 (mute) <- 0x28 <- 0a
+ * mono 0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
+ *
+ * DAC0 = 03h, DAC1 = 04h, DAC2 = 05h, DAC3 = 06h, DAC4 = 0ah
+ * (*) DAC2/3/4 are swapped to DAC3/4/2 on AD198A rev.2 due to a h/w bug.
+ *
+ * Input pins and routes
+ *
+ * pin boost mix input # / adc input #
+ * port-A 0x11 -> 0x38 -> mix 2, ADC 0
+ * port-B 0x14 -> 0x39 -> mix 0, ADC 1
+ * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
+ * port-D 0x12 -> 0x3d -> mix 3, ADC 8
+ * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
+ * port-F 0x16 -> 0x3b -> mix 5, ADC 3
+ * port-G 0x24 -> N/A -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
+ * port-H 0x25 -> N/A -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
+ *
+ *
+ * DAC assignment
+ * 6stack - front/surr/CLFE/side/opt DACs - 04/06/05/0a/03
+ * 3stack - front/surr/CLFE/opt DACs - 04/05/0a/03
+ *
+ * Inputs of Analog Mix (0x20)
+ * 0:Port-B (front mic)
+ * 1:Port-C/G/H (line-in)
+ * 2:Port-A
+ * 3:Port-D (line-in/2)
+ * 4:Port-E/G/H (mic-in)
+ * 5:Port-F (mic2-in)
+ * 6:CD
+ * 7:Beep
+ *
+ * ADC selection
+ * 0:Port-A
+ * 1:Port-B (front mic-in)
+ * 2:Port-C (line-in)
+ * 3:Port-F (mic2-in)
+ * 4:Port-E (mic-in)
+ * 5:CD
+ * 6:Port-G
+ * 7:Port-H
+ * 8:Port-D (line-in/2)
+ * 9:Mix
+ *
+ * Proposed pin assignments by the datasheet
+ *
+ * 6-stack
+ * Port-A front headphone
+ * B front mic-in
+ * C rear line-in
+ * D rear front-out
+ * E rear mic-in
+ * F rear surround
+ * G rear CLFE
+ * H rear side
+ *
+ * 3-stack
+ * Port-A front headphone
+ * B front mic
+ * C rear line-in/surround
+ * D rear front-out
+ * E rear mic-in/CLFE
+ *
+ * laptop
+ * Port-A headphone
+ * B mic-in
+ * C docking station
+ * D internal speaker (with EAPD)
+ * E/F quad mic array
+ */
+
+
+/* models */
+enum {
+ AD1988_6STACK,
+ AD1988_6STACK_DIG,
+ AD1988_3STACK,
+ AD1988_3STACK_DIG,
+ AD1988_LAPTOP,
+ AD1988_LAPTOP_DIG,
+ AD1988_AUTO,
+ AD1988_MODEL_LAST,
+};
+
+/* reivision id to check workarounds */
+#define AD1988A_REV2 0x100200
+
+
+/*
+ * mixers
+ */
+
+static hda_nid_t ad1988_6stack_dac_nids[4] = {
+ 0x04, 0x06, 0x05, 0x0a
+};
+
+static hda_nid_t ad1988_3stack_dac_nids[3] = {
+ 0x04, 0x05, 0x0a
+};
+
+/* for AD1988A revision-2, DAC2-4 are swapped */
+static hda_nid_t ad1988_6stack_dac_nids_rev2[4] = {
+ 0x04, 0x05, 0x0a, 0x06
+};
+
+static hda_nid_t ad1988_3stack_dac_nids_rev2[3] = {
+ 0x04, 0x0a, 0x06
+};
+
+static hda_nid_t ad1988_adc_nids[3] = {
+ 0x08, 0x09, 0x0f
+};
+
+static hda_nid_t ad1988_capsrc_nids[3] = {
+ 0x0c, 0x0d, 0x0e
+};
+
+#define AD1988_SPDIF_OUT 0x02
+#define AD1988_SPDIF_IN 0x07
+
+static struct hda_input_mux ad1988_6stack_capture_source = {
+ .num_items = 5,
+ .items = {
+ { "Front Mic", 0x0 },
+ { "Line", 0x1 },
+ { "Mic", 0x4 },
+ { "CD", 0x5 },
+ { "Mix", 0x9 },
+ },
+};
+
+static struct hda_input_mux ad1988_laptop_capture_source = {
+ .num_items = 3,
+ .items = {
+ { "Mic/Line", 0x0 },
+ { "CD", 0x5 },
+ { "Mix", 0x9 },
+ },
+};
+
+/*
+ */
+static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
+ spec->num_channel_mode);
+}
+
+static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
+ spec->num_channel_mode, spec->multiout.max_channels);
+}
+
+static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
+ spec->num_channel_mode, &spec->multiout.max_channels);
+}
+
+/*
+ * EAPD control
+ */
+static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
+ return 0;
+}
+
+static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ unsigned int eapd;
+ eapd = ! ucontrol->value.enumerated.item[0];
+ if (eapd == spec->cur_eapd && ! codec->in_resume)
+ return 0;
+ spec->cur_eapd = eapd;
+ snd_hda_codec_write(codec, 0x12 /* port-D */,
+ 0, AC_VERB_SET_EAPD_BTLENABLE,
+ eapd ? 0x02 : 0x00);
+ return 0;
+}
+
+/* 6-stack mode */
+static struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
+};
+
+static struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0a, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+};
+
+static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
+ HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
+
+ { } /* end */
+};
+
+/* 3-stack mode */
+static struct snd_kcontrol_new ad1988_3stack_mixers1[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
+};
+
+static struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x06, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x06, 2, 0x0, HDA_OUTPUT),
+};
+
+static struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
+ HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
+ HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x26, 2, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
+ HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = ad198x_ch_mode_info,
+ .get = ad198x_ch_mode_get,
+ .put = ad198x_ch_mode_put,
+ },
+
+ { } /* end */
+};
+
+/* laptop mode */
+static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
+ HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
+
+ HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
+
+ HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "External Amplifier",
+ .info = ad1988_eapd_info,
+ .get = ad1988_eapd_get,
+ .put = ad1988_eapd_put,
+ },
+
+ { } /* end */
+};
+
+/* capture */
+static struct snd_kcontrol_new ad1988_capture_mixers[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 3,
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static char *texts[] = {
+ "PCM", "ADC1", "ADC2", "ADC3"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item >= 4)
+ uinfo->value.enumerated.item = 3;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int sel;
+
+ sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
+ if (sel > 0) {
+ sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
+ if (sel <= 3)
+ sel++;
+ else
+ sel = 0;
+ }
+ ucontrol->value.enumerated.item[0] = sel;
+ return 0;
+}
+
+static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int sel;
+ int change;
+
+ sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
+ if (! ucontrol->value.enumerated.item[0]) {
+ change = sel != 0;
+ if (change)
+ snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
+ } else {
+ change = sel == 0;
+ if (change)
+ snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
+ sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
+ change |= sel == ucontrol->value.enumerated.item[0];
+ if (change)
+ snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
+ ucontrol->value.enumerated.item[0] - 1);
+ }
+ return change;
+}
+
+static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
+ HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "IEC958 Playback Source",
+ .info = ad1988_spdif_playback_source_info,
+ .get = ad1988_spdif_playback_source_get,
+ .put = ad1988_spdif_playback_source_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
+ HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+
+/*
+ * initialization verbs
+ */
+
+/*
+ * for 6-stack (+dig)
+ */
+static struct hda_verb ad1988_6stack_init_verbs[] = {
+ /* Front, Surround, CLFE, side DAC; unmute as default */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Port-A front headphon path */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Port-D line-out path */
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-F surround path */
+ {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-G CLFE path */
+ {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Port-H side path */
+ {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Mono out path */
+ {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
+ /* Port-B front mic-in path */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* Port-C line-in path */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Port-E mic-in path */
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+ { }
+};
+
+static struct hda_verb ad1988_capture_init_verbs[] = {
+ /* mute analog mix */
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+ /* select ADCs - front-mic */
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
+ /* ADCs; muted */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+
+ { }
+};
+
+static struct hda_verb ad1988_spdif_init_verbs[] = {
+ /* SPDIF out sel */
+ {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
+ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ /* SPDIF out pin */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
+
+ { }
+};
+
+/*
+ * verbs for 3stack (+dig)
+ */
+static struct hda_verb ad1988_3stack_ch2_init[] = {
+ /* set port-C to line-in */
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ /* set port-E to mic-in */
+ { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { } /* end */
+};
+
+static struct hda_verb ad1988_3stack_ch6_init[] = {
+ /* set port-C to surround out */
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ /* set port-E to CLFE out */
+ { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { } /* end */
+};
+
+static struct hda_channel_mode ad1988_3stack_modes[2] = {
+ { 2, ad1988_3stack_ch2_init },
+ { 6, ad1988_3stack_ch6_init },
+};
+
+static struct hda_verb ad1988_3stack_init_verbs[] = {
+ /* Front, Surround, CLFE, side DAC; unmute as default */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Port-A front headphon path */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Port-D line-out path */
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Mono out path */
+ {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
+ /* Port-B front mic-in path */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* Port-C line-in/surround path - 6ch mode as default */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x31, AC_VERB_SET_CONNECT_SEL, 0x0}, /* output sel: DAC 0x05 */
+ {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Port-E mic-in/CLFE path - 6ch mode as default */
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x32, AC_VERB_SET_CONNECT_SEL, 0x1}, /* output sel: DAC 0x0a */
+ {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* mute analog mix */
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+ /* select ADCs - front-mic */
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
+ /* ADCs; muted */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ { }
+};
+
+/*
+ * verbs for laptop mode (+dig)
+ */
+static struct hda_verb ad1988_laptop_hp_on[] = {
+ /* unmute port-A and mute port-D */
+ { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { } /* end */
+};
+static struct hda_verb ad1988_laptop_hp_off[] = {
+ /* mute port-A and unmute port-D */
+ { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { } /* end */
+};
+
+#define AD1988_HP_EVENT 0x01
+
+static struct hda_verb ad1988_laptop_init_verbs[] = {
+ /* Front, Surround, CLFE, side DAC; unmute as default */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Port-A front headphon path */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* unsolicited event for pin-sense */
+ {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
+ /* Port-D line-out path + EAPD */
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
+ /* Mono out path */
+ {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
+ /* Port-B mic-in path */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* Port-C docking station - try to output */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* mute analog mix */
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
+ /* select ADCs - mic */
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
+ {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
+ /* ADCs; muted */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ { }
+};
+
+static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ if ((res >> 26) != AD1988_HP_EVENT)
+ return;
+ if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
+ snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
+ else
+ snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
+}
+
+
+/*
+ * Automatic parse of I/O pins from the BIOS configuration
+ */
+
+#define NUM_CONTROL_ALLOC 32
+#define NUM_VERB_ALLOC 32
+
+enum {
+ AD_CTL_WIDGET_VOL,
+ AD_CTL_WIDGET_MUTE,
+ AD_CTL_BIND_MUTE,
+};
+static struct snd_kcontrol_new ad1988_control_templates[] = {
+ HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+ HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ HDA_BIND_MUTE(NULL, 0, 0, 0),
+};
+
+/* add dynamic controls */
+static int add_control(struct ad198x_spec *spec, int type, const char *name,
+ unsigned long val)
+{
+ struct snd_kcontrol_new *knew;
+
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+ if (! knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
+ *knew = ad1988_control_templates[type];
+ knew->name = kstrdup(name, GFP_KERNEL);
+ if (! knew->name)
+ return -ENOMEM;
+ knew->private_value = val;
+ spec->num_kctl_used++;
+ return 0;
+}
+
+#define AD1988_PIN_CD_NID 0x18
+#define AD1988_PIN_BEEP_NID 0x10
+
+static hda_nid_t ad1988_mixer_nids[8] = {
+ /* A B C D E F G H */
+ 0x22, 0x2b, 0x2c, 0x29, 0x26, 0x2a, 0x27, 0x28
+};
+
+static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
+{
+ static hda_nid_t idx_to_dac[8] = {
+ /* A B C D E F G H */
+ 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
+ };
+ static hda_nid_t idx_to_dac_rev2[8] = {
+ /* A B C D E F G H */
+ 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
+ };
+ if (codec->revision_id == AD1988A_REV2)
+ return idx_to_dac_rev2[idx];
+ else
+ return idx_to_dac[idx];
+}
+
+static hda_nid_t ad1988_boost_nids[8] = {
+ 0x38, 0x39, 0x3a, 0x3d, 0x3c, 0x3b, 0, 0
+};
+
+static int ad1988_pin_idx(hda_nid_t nid)
+{
+ static hda_nid_t ad1988_io_pins[8] = {
+ 0x11, 0x14, 0x15, 0x12, 0x17, 0x16, 0x24, 0x25
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ad1988_io_pins); i++)
+ if (ad1988_io_pins[i] == nid)
+ return i;
+ return 0; /* should be -1 */
+}
+
+static int ad1988_pin_to_loopback_idx(hda_nid_t nid)
+{
+ static int loopback_idx[8] = {
+ 2, 0, 1, 3, 4, 5, 1, 4
+ };
+ switch (nid) {
+ case AD1988_PIN_CD_NID:
+ return 6;
+ default:
+ return loopback_idx[ad1988_pin_idx(nid)];
+ }
+}
+
+static int ad1988_pin_to_adc_idx(hda_nid_t nid)
+{
+ static int adc_idx[8] = {
+ 0, 1, 2, 8, 4, 3, 6, 7
+ };
+ switch (nid) {
+ case AD1988_PIN_CD_NID:
+ return 5;
+ default:
+ return adc_idx[ad1988_pin_idx(nid)];
+ }
+}
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int ad1988_auto_fill_dac_nids(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg)
+{
+ struct ad198x_spec *spec = codec->spec;
+ int i, idx;
+
+ spec->multiout.dac_nids = spec->private_dac_nids;
+
+ /* check the pins hardwired to audio widget */
+ for (i = 0; i < cfg->line_outs; i++) {
+ idx = ad1988_pin_idx(cfg->line_out_pins[i]);
+ spec->multiout.dac_nids[i] = ad1988_idx_to_dac(codec, idx);
+ }
+ spec->multiout.num_dacs = cfg->line_outs;
+ return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int ad1988_auto_create_multi_out_ctls(struct ad198x_spec *spec,
+ const struct auto_pin_cfg *cfg)
+{
+ char name[32];
+ static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+ hda_nid_t nid;
+ int i, err;
+
+ for (i = 0; i < cfg->line_outs; i++) {
+ hda_nid_t dac = spec->multiout.dac_nids[i];
+ if (! dac)
+ continue;
+ nid = ad1988_mixer_nids[ad1988_pin_idx(cfg->line_out_pins[i])];
+ if (i == 2) {
+ /* Center/LFE */
+ err = add_control(spec, AD_CTL_WIDGET_VOL,
+ "Center Playback Volume",
+ HDA_COMPOSE_AMP_VAL(dac, 1, 0, HDA_OUTPUT));
+ if (err < 0)
+ return err;
+ err = add_control(spec, AD_CTL_WIDGET_VOL,
+ "LFE Playback Volume",
+ HDA_COMPOSE_AMP_VAL(dac, 2, 0, HDA_OUTPUT));
+ if (err < 0)
+ return err;
+ err = add_control(spec, AD_CTL_BIND_MUTE,
+ "Center Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT));
+ if (err < 0)
+ return err;
+ err = add_control(spec, AD_CTL_BIND_MUTE,
+ "LFE Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT));
+ if (err < 0)
+ return err;
+ } else {
+ sprintf(name, "%s Playback Volume", chname[i]);
+ err = add_control(spec, AD_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT));
+ if (err < 0)
+ return err;
+ sprintf(name, "%s Playback Switch", chname[i]);
+ err = add_control(spec, AD_CTL_BIND_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
+ if (err < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
+/* add playback controls for speaker and HP outputs */
+static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
+ const char *pfx)
+{
+ struct ad198x_spec *spec = codec->spec;
+ hda_nid_t nid;
+ int idx, err;
+ char name[32];
+
+ if (! pin)
+ return 0;
+
+ idx = ad1988_pin_idx(pin);
+ nid = ad1988_idx_to_dac(codec, idx);
+ if (! spec->multiout.dac_nids[0]) {
+ /* use this as the primary output */
+ spec->multiout.dac_nids[0] = nid;
+ if (! spec->multiout.num_dacs)
+ spec->multiout.num_dacs = 1;
+ } else
+ /* specify the DAC as the extra output */
+ spec->multiout.hp_nid = nid;
+ /* control HP volume/switch on the output mixer amp */
+ sprintf(name, "%s Playback Volume", pfx);
+ if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ nid = ad1988_mixer_nids[idx];
+ sprintf(name, "%s Playback Switch", pfx);
+ if ((err = add_control(spec, AD_CTL_BIND_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+ return err;
+ return 0;
+}
+
+/* create input playback/capture controls for the given pin */
+static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
+ const char *ctlname, int boost)
+{
+ char name[32];
+ int err, idx;
+
+ sprintf(name, "%s Playback Volume", ctlname);
+ idx = ad1988_pin_to_loopback_idx(pin);
+ if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
+ return err;
+ sprintf(name, "%s Playback Switch", ctlname);
+ if ((err = add_control(spec, AD_CTL_WIDGET_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(0x20, 3, idx, HDA_INPUT))) < 0)
+ return err;
+ if (boost) {
+ hda_nid_t bnid;
+ idx = ad1988_pin_idx(pin);
+ bnid = ad1988_boost_nids[idx];
+ if (bnid) {
+ sprintf(name, "%s Boost", ctlname);
+ return add_control(spec, AD_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(bnid, 3, idx, HDA_OUTPUT));
+
+ }
+ }
+ return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec,
+ const struct auto_pin_cfg *cfg)
+{
+ struct hda_input_mux *imux = &spec->private_imux;
+ int i, err;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ err = new_analog_input(spec, cfg->input_pins[i],
+ auto_pin_cfg_labels[i],
+ i <= AUTO_PIN_FRONT_MIC);
+ if (err < 0)
+ return err;
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+ imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
+ imux->num_items++;
+ }
+ imux->items[imux->num_items].label = "Mix";
+ imux->items[imux->num_items].index = 9;
+ imux->num_items++;
+
+ if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
+ "Analog Mix Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, AD_CTL_WIDGET_MUTE,
+ "Analog Mix Playback Switch",
+ HDA_COMPOSE_AMP_VAL(0x21, 3, 0x0, HDA_OUTPUT))) < 0)
+ return err;
+
+ return 0;
+}
+
+static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
+ int dac_idx)
+{
+ /* set as output */
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ switch (nid) {
+ case 0x11: /* port-A - DAC 04 */
+ snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
+ break;
+ case 0x14: /* port-B - DAC 06 */
+ snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
+ break;
+ case 0x15: /* port-C - DAC 05 */
+ snd_hda_codec_write(codec, 0x31, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
+ break;
+ case 0x17: /* port-E - DAC 0a */
+ snd_hda_codec_write(codec, 0x32, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
+ break;
+ case 0x13: /* mono - DAC 04 */
+ snd_hda_codec_write(codec, 0x36, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
+ break;
+ }
+}
+
+static void ad1988_auto_init_multi_out(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->autocfg.line_outs; i++) {
+ hda_nid_t nid = spec->autocfg.line_out_pins[i];
+ ad1988_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+ }
+}
+
+static void ad1988_auto_init_extra_out(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ hda_nid_t pin;
+
+ pin = spec->autocfg.speaker_pin;
+ if (pin) /* connect to front */
+ ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
+ pin = spec->autocfg.hp_pin;
+ if (pin) /* connect to front */
+ ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+static void ad1988_auto_init_analog_input(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ int i, idx;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if (! nid)
+ continue;
+ switch (nid) {
+ case 0x15: /* port-C */
+ snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
+ break;
+ case 0x17: /* port-E */
+ snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
+ break;
+ }
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+ if (nid != AD1988_PIN_CD_NID)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_MUTE);
+ idx = ad1988_pin_idx(nid);
+ if (ad1988_boost_nids[idx])
+ snd_hda_codec_write(codec, ad1988_boost_nids[idx], 0,
+ AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_ZERO);
+ }
+}
+
+/* parse the BIOS configuration and set up the alc_spec */
+/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+static int ad1988_parse_auto_config(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ int err;
+
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
+ return err;
+ if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
+ return err;
+ if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
+ ! spec->autocfg.hp_pin)
+ return 0; /* can't find valid BIOS pin config */
+ if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+ (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin,
+ "Speaker")) < 0 ||
+ (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin,
+ "Headphone")) < 0 ||
+ (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+
+ spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+ if (spec->autocfg.dig_out_pin)
+ spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
+ if (spec->autocfg.dig_in_pin)
+ spec->dig_in_nid = AD1988_SPDIF_IN;
+
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+ spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
+
+ spec->input_mux = &spec->private_imux;
+
+ return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int ad1988_auto_init(struct hda_codec *codec)
+{
+ ad198x_init(codec);
+ ad1988_auto_init_multi_out(codec);
+ ad1988_auto_init_extra_out(codec);
+ ad1988_auto_init_analog_input(codec);
+ return 0;
+}
+
+
+/*
+ */
+
+static struct hda_board_config ad1988_cfg_tbl[] = {
+ { .modelname = "6stack", .config = AD1988_6STACK },
+ { .modelname = "6stack-dig", .config = AD1988_6STACK_DIG },
+ { .modelname = "3stack", .config = AD1988_3STACK },
+ { .modelname = "3stack-dig", .config = AD1988_3STACK_DIG },
+ { .modelname = "laptop", .config = AD1988_LAPTOP },
+ { .modelname = "laptop-dig", .config = AD1988_LAPTOP_DIG },
+ { .modelname = "auto", .config = AD1988_AUTO },
+ {}
+};
+
+static int patch_ad1988(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec;
+ int board_config;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ init_MUTEX(&spec->amp_mutex);
+ codec->spec = spec;
+
+ if (codec->revision_id == AD1988A_REV2)
+ snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
+
+ board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
+ if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
+ printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
+ board_config = AD1988_AUTO;
+ }
+
+ if (board_config == AD1988_AUTO) {
+ /* automatic parse from the BIOS config */
+ int err = ad1988_parse_auto_config(codec);
+ if (err < 0) {
+ ad198x_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 6-stack mode...\n");
+ board_config = AD1988_6STACK;
+ }
+ }
+
+ switch (board_config) {
+ case AD1988_6STACK:
+ case AD1988_6STACK_DIG:
+ spec->multiout.max_channels = 8;
+ spec->multiout.num_dacs = 4;
+ if (codec->revision_id == AD1988A_REV2)
+ spec->multiout.dac_nids = ad1988_6stack_dac_nids_rev2;
+ else
+ spec->multiout.dac_nids = ad1988_6stack_dac_nids;
+ spec->input_mux = &ad1988_6stack_capture_source;
+ spec->num_mixers = 2;
+ if (codec->revision_id == AD1988A_REV2)
+ spec->mixers[0] = ad1988_6stack_mixers1_rev2;
+ else
+ spec->mixers[0] = ad1988_6stack_mixers1;
+ spec->mixers[1] = ad1988_6stack_mixers2;
+ spec->num_init_verbs = 1;
+ spec->init_verbs[0] = ad1988_6stack_init_verbs;
+ if (board_config == AD1988_6STACK_DIG) {
+ spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
+ spec->dig_in_nid = AD1988_SPDIF_IN;
+ }
+ break;
+ case AD1988_3STACK:
+ case AD1988_3STACK_DIG:
+ spec->multiout.max_channels = 6;
+ spec->multiout.num_dacs = 3;
+ if (codec->revision_id == AD1988A_REV2)
+ spec->multiout.dac_nids = ad1988_3stack_dac_nids_rev2;
+ else
+ spec->multiout.dac_nids = ad1988_3stack_dac_nids;
+ spec->input_mux = &ad1988_6stack_capture_source;
+ spec->channel_mode = ad1988_3stack_modes;
+ spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
+ spec->num_mixers = 2;
+ if (codec->revision_id == AD1988A_REV2)
+ spec->mixers[0] = ad1988_3stack_mixers1_rev2;
+ else
+ spec->mixers[0] = ad1988_3stack_mixers1;
+ spec->mixers[1] = ad1988_3stack_mixers2;
+ spec->num_init_verbs = 1;
+ spec->init_verbs[0] = ad1988_3stack_init_verbs;
+ if (board_config == AD1988_3STACK_DIG)
+ spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
+ break;
+ case AD1988_LAPTOP:
+ case AD1988_LAPTOP_DIG:
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = ad1988_3stack_dac_nids;
+ spec->input_mux = &ad1988_laptop_capture_source;
+ spec->num_mixers = 1;
+ spec->mixers[0] = ad1988_laptop_mixers;
+ spec->num_init_verbs = 1;
+ spec->init_verbs[0] = ad1988_laptop_init_verbs;
+ if (board_config == AD1988_LAPTOP_DIG)
+ spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
+ break;
+ }
+
+ spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
+ spec->adc_nids = ad1988_adc_nids;
+ spec->capsrc_nids = ad1988_capsrc_nids;
+ spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
+ spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
+ if (spec->multiout.dig_out_nid) {
+ spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
+ spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
+ }
+ if (spec->dig_in_nid)
+ spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
+
+ codec->patch_ops = ad198x_patch_ops;
+ switch (board_config) {
+ case AD1988_AUTO:
+ codec->patch_ops.init = ad1988_auto_init;
+ break;
+ case AD1988_LAPTOP:
+ case AD1988_LAPTOP_DIG:
+ codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
+ break;
+ }
+
+ return 0;
+}
+
+
+/*
* patch entries
*/
struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
+ { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 523c362ec44d..d38ce22507ae 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -44,7 +44,6 @@ enum {
struct cmi_spec {
int board_config;
- unsigned int surr_switch: 1; /* switchable line,mic */
unsigned int no_line_in: 1; /* no line-in (5-jack) */
unsigned int front_panel: 1; /* has front-panel 2-jack */
@@ -62,9 +61,8 @@ struct cmi_spec {
unsigned int cur_mux[2];
/* channel mode */
- unsigned int num_ch_modes;
- unsigned int cur_ch_mode;
- const struct cmi_channel_mode *channel_modes;
+ int num_channel_modes;
+ const struct hda_channel_mode *channel_modes;
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -78,30 +76,17 @@ struct cmi_spec {
struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
};
-/* amp values */
-#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
-#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
-/* pinctl values */
-#define PIN_IN 0x20
-#define PIN_VREF80 0x24
-#define PIN_VREF50 0x21
-#define PIN_OUT 0x40
-#define PIN_HP 0xc0
-
/*
* input MUX
*/
-static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
return snd_hda_input_mux_info(spec->input_mux, uinfo);
}
-static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
@@ -111,7 +96,7 @@ static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
@@ -158,63 +143,39 @@ static struct hda_verb cmi9880_ch8_init[] = {
{}
};
-struct cmi_channel_mode {
- unsigned int channels;
- const struct hda_verb *sequence;
-};
-
-static struct cmi_channel_mode cmi9880_channel_modes[3] = {
+static struct hda_channel_mode cmi9880_channel_modes[3] = {
{ 2, cmi9880_ch2_init },
{ 6, cmi9880_ch6_init },
{ 8, cmi9880_ch8_init },
};
-static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
-
- snd_assert(spec->channel_modes, return -EINVAL);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = spec->num_ch_modes;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- sprintf(uinfo->value.enumerated.name, "%dch",
- spec->channel_modes[uinfo->value.enumerated.item].channels);
- return 0;
+ return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes,
+ spec->num_channel_modes);
}
-static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_ch_mode;
- return 0;
+ return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes,
+ spec->num_channel_modes, spec->multiout.max_channels);
}
-static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct cmi_spec *spec = codec->spec;
-
- snd_assert(spec->channel_modes, return -EINVAL);
- if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
- ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
- if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
- ! codec->in_resume)
- return 0;
-
- spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
- snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence);
- spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels;
- return 1;
+ return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes,
+ spec->num_channel_modes, &spec->multiout.max_channels);
}
/*
*/
-static snd_kcontrol_new_t cmi9880_basic_mixer[] = {
+static struct snd_kcontrol_new cmi9880_basic_mixer[] = {
/* CMI9880 has no playback volumes! */
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
@@ -246,7 +207,7 @@ static snd_kcontrol_new_t cmi9880_basic_mixer[] = {
/*
* shared I/O pins
*/
-static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = {
+static struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -361,7 +322,7 @@ static int cmi9880_build_controls(struct hda_codec *codec)
err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
if (err < 0)
return err;
- if (spec->surr_switch) {
+ if (spec->channel_modes) {
err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
if (err < 0)
return err;
@@ -475,7 +436,7 @@ static int cmi9880_resume(struct hda_codec *codec)
cmi9880_init(codec);
snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
- if (spec->surr_switch)
+ if (spec->channel_modes)
snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
if (spec->multiout.dig_out_nid)
snd_hda_resume_spdif_out(codec);
@@ -491,7 +452,7 @@ static int cmi9880_resume(struct hda_codec *codec)
*/
static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
@@ -501,7 +462,7 @@ static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
@@ -510,7 +471,7 @@ static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
@@ -521,7 +482,7 @@ static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
*/
static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
@@ -529,7 +490,7 @@ static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
@@ -542,7 +503,7 @@ static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
@@ -553,7 +514,7 @@ static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct cmi_spec *spec = codec->spec;
@@ -685,14 +646,13 @@ static int patch_cmi9880(struct hda_codec *codec)
switch (spec->board_config) {
case CMI_MINIMAL:
case CMI_MIN_FP:
- spec->surr_switch = 1;
+ spec->channel_modes = cmi9880_channel_modes;
if (spec->board_config == CMI_MINIMAL)
- spec->num_ch_modes = 2;
+ spec->num_channel_modes = 2;
else {
spec->front_panel = 1;
- spec->num_ch_modes = 3;
+ spec->num_channel_modes = 3;
}
- spec->channel_modes = cmi9880_channel_modes;
spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
spec->input_mux = &cmi9880_basic_mux;
break;
@@ -727,19 +687,18 @@ static int patch_cmi9880(struct hda_codec *codec)
get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- spec->surr_switch = 1;
+ spec->channel_modes = cmi9880_channel_modes;
/* no front panel */
if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
/* no optional rear panel */
spec->board_config = CMI_MINIMAL;
spec->front_panel = 0;
- spec->num_ch_modes = 2;
+ spec->num_channel_modes = 2;
} else {
spec->board_config = CMI_MIN_FP;
- spec->num_ch_modes = 3;
+ spec->num_channel_modes = 3;
}
- spec->channel_modes = cmi9880_channel_modes;
spec->input_mux = &cmi9880_basic_mux;
spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
} else {
@@ -752,7 +711,7 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->dig_in_nid = CMI_DIG_IN_NID;
spec->multiout.max_channels = 8;
}
- snd_hda_parse_pin_def_config(codec, &cfg);
+ snd_hda_parse_pin_def_config(codec, &cfg, NULL);
if (cfg.line_outs) {
spec->multiout.max_channels = cfg.line_outs * 2;
cmi9880_fill_multi_dac_nids(codec, &cfg);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cffb83fdcff7..ad9e501a9818 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3,7 +3,8 @@
*
* HD audio interface patch for ALC 260/880/882 codecs
*
- * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
+ * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
+ * PeiSen Hou <pshou@realtek.com.tw>
* Takashi Iwai <tiwai@suse.de>
*
* This driver is free software; you can redistribute it and/or modify
@@ -39,17 +40,20 @@ enum {
ALC880_5ST_DIG,
ALC880_W810,
ALC880_Z71V,
- ALC880_AUTO,
ALC880_6ST,
ALC880_6ST_DIG,
ALC880_F1734,
ALC880_ASUS,
ALC880_ASUS_DIG,
ALC880_ASUS_W1V,
+ ALC880_ASUS_DIG2,
ALC880_UNIWILL_DIG,
+ ALC880_CLEVO,
+ ALC880_TCL_S700,
#ifdef CONFIG_SND_DEBUG
ALC880_TEST,
#endif
+ ALC880_AUTO,
ALC880_MODEL_LAST /* last tag */
};
@@ -57,30 +61,45 @@ enum {
enum {
ALC260_BASIC,
ALC260_HP,
- ALC260_FUJITSU_S702x,
+ ALC260_HP_3013,
+ ALC260_FUJITSU_S702X,
+ ALC260_AUTO,
ALC260_MODEL_LAST /* last tag */
};
-/* amp values */
-#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
-#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
-/* pinctl values */
-#define PIN_IN 0x20
-#define PIN_VREF80 0x24
-#define PIN_VREF50 0x21
-#define PIN_OUT 0x40
-#define PIN_HP 0xc0
-#define PIN_HP_AMP 0x80
+/* ALC262 models */
+enum {
+ ALC262_BASIC,
+ ALC262_AUTO,
+ ALC262_MODEL_LAST /* last tag */
+};
+
+/* ALC861 models */
+enum {
+ ALC861_3ST,
+ ALC861_3ST_DIG,
+ ALC861_6ST_DIG,
+ ALC861_AUTO,
+ ALC861_MODEL_LAST,
+};
+
+/* ALC882 models */
+enum {
+ ALC882_3ST_DIG,
+ ALC882_6ST_DIG,
+ ALC882_AUTO,
+ ALC882_MODEL_LAST,
+};
+
+/* for GPIO Poll */
+#define GPIO_MASK 0x03
struct alc_spec {
/* codec parameterization */
- snd_kcontrol_new_t *mixers[3]; /* mixer arrays */
+ struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
unsigned int num_mixers;
- const struct hda_verb *init_verbs[3]; /* initialization verbs
+ const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL termination!
*/
unsigned int num_init_verbs;
@@ -109,7 +128,7 @@ struct alc_spec {
unsigned int cur_mux[3];
/* channel model */
- const struct alc_channel_mode *channel_mode;
+ const struct hda_channel_mode *channel_mode;
int num_channel_mode;
/* PCM information */
@@ -118,23 +137,41 @@ struct alc_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used;
- snd_kcontrol_new_t *kctl_alloc;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
- hda_nid_t private_dac_nids[4];
+ hda_nid_t private_dac_nids[5];
+};
+
+/*
+ * configuration template - to be copied to the spec instance
+ */
+struct alc_config_preset {
+ struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */
+ const struct hda_verb *init_verbs[5];
+ unsigned int num_dacs;
+ hda_nid_t *dac_nids;
+ hda_nid_t dig_out_nid; /* optional */
+ hda_nid_t hp_nid; /* optional */
+ unsigned int num_adc_nids;
+ hda_nid_t *adc_nids;
+ hda_nid_t dig_in_nid;
+ unsigned int num_channel_mode;
+ const struct hda_channel_mode *channel_mode;
+ const struct hda_input_mux *input_mux;
};
/*
* input MUX handling
*/
-static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
return snd_hda_input_mux_info(spec->input_mux, uinfo);
}
-static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
@@ -144,7 +181,7 @@ static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
@@ -157,63 +194,28 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/*
* channel mode setting
*/
-struct alc_channel_mode {
- int channels;
- const struct hda_verb *sequence;
-};
-
-static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
-
- snd_assert(spec->channel_mode, return -ENXIO);
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = items;
- if (uinfo->value.enumerated.item >= items)
- uinfo->value.enumerated.item = items - 1;
- sprintf(uinfo->value.enumerated.name, "%dch",
- spec->channel_mode[uinfo->value.enumerated.item].channels);
- return 0;
+ return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
+ spec->num_channel_mode);
}
-static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
- int i;
-
- snd_assert(spec->channel_mode, return -ENXIO);
- for (i = 0; i < items; i++) {
- if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
- ucontrol->value.enumerated.item[0] = i;
- break;
- }
- }
- return 0;
+ return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
+ spec->num_channel_mode, spec->multiout.max_channels);
}
-static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- int mode;
-
- snd_assert(spec->channel_mode, return -ENXIO);
- mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
- if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
- ! codec->in_resume)
- return 0;
-
- /* change the current channel setting */
- spec->multiout.max_channels = spec->channel_mode[mode].channels;
- if (spec->channel_mode[mode].sequence)
- snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
-
- return 1;
+ return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
+ spec->num_channel_mode, &spec->multiout.max_channels);
}
@@ -222,7 +224,7 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
* supported, so VrefEn can't be controlled using these functions as they
* stand.
*/
-static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc_pinctl_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -231,7 +233,7 @@ static int alc_pinctl_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_pinctl_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value & 0xffff;
@@ -244,7 +246,7 @@ static int alc_pinctl_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_pinctl_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = kcontrol->private_value & 0xffff;
@@ -266,6 +268,36 @@ static int alc_pinctl_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
.put = alc_pinctl_switch_put, \
.private_value = (nid) | (mask<<16) }
+
+/*
+ * set up from the preset table
+ */
+static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
+ spec->mixers[spec->num_mixers++] = preset->mixers[i];
+ for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++)
+ spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
+
+ spec->channel_mode = preset->channel_mode;
+ spec->num_channel_mode = preset->num_channel_mode;
+
+ spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+ spec->multiout.num_dacs = preset->num_dacs;
+ spec->multiout.dac_nids = preset->dac_nids;
+ spec->multiout.dig_out_nid = preset->dig_out_nid;
+ spec->multiout.hp_nid = preset->hp_nid;
+
+ spec->input_mux = preset->input_mux;
+
+ spec->num_adc_nids = preset->num_adc_nids;
+ spec->adc_nids = preset->adc_nids;
+ spec->dig_in_nid = preset->dig_in_nid;
+}
+
/*
* ALC880 3-stack model
*
@@ -286,6 +318,7 @@ static hda_nid_t alc880_adc_nids[3] = {
/* The datasheet says the node 0x07 is connected from inputs,
* but it shows zero connection in the real implementation on some devices.
+ * Note: this is a 915GAV bug, fixed on 915GLV
*/
static hda_nid_t alc880_adc_nids_alt[2] = {
/* ADC1-2 */
@@ -328,12 +361,12 @@ static struct hda_verb alc880_threestack_ch6_init[] = {
{ } /* end */
};
-static struct alc_channel_mode alc880_threestack_modes[2] = {
+static struct hda_channel_mode alc880_threestack_modes[2] = {
{ 2, alc880_threestack_ch2_init },
{ 6, alc880_threestack_ch6_init },
};
-static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
+static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
@@ -356,15 +389,15 @@ static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
},
{ } /* end */
};
/* capture mixer elements */
-static snd_kcontrol_new_t alc880_capture_mixer[] = {
+static struct snd_kcontrol_new alc880_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
@@ -388,7 +421,7 @@ static snd_kcontrol_new_t alc880_capture_mixer[] = {
};
/* capture mixer elements (in case NID 0x07 not available) */
-static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
+static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
@@ -420,7 +453,7 @@ static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
*/
/* additional mixers to alc880_three_stack_mixer */
-static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
{ } /* end */
@@ -443,7 +476,7 @@ static struct hda_verb alc880_fivestack_ch8_init[] = {
{ } /* end */
};
-static struct alc_channel_mode alc880_fivestack_modes[2] = {
+static struct hda_channel_mode alc880_fivestack_modes[2] = {
{ 6, alc880_fivestack_ch6_init },
{ 8, alc880_fivestack_ch8_init },
};
@@ -473,11 +506,11 @@ static struct hda_input_mux alc880_6stack_capture_source = {
};
/* fixed 8-channels */
-static struct alc_channel_mode alc880_sixstack_modes[1] = {
+static struct hda_channel_mode alc880_sixstack_modes[1] = {
{ 8, NULL },
};
-static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
+static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -501,9 +534,9 @@ static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
},
{ } /* end */
};
@@ -540,12 +573,12 @@ static hda_nid_t alc880_w810_dac_nids[3] = {
};
/* fixed 6 channels */
-static struct alc_channel_mode alc880_w810_modes[1] = {
+static struct hda_channel_mode alc880_w810_modes[1] = {
{ 6, NULL }
};
/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -572,11 +605,11 @@ static hda_nid_t alc880_z71v_dac_nids[1] = {
#define ALC880_Z71V_HP_DAC 0x03
/* fixed 2 channels */
-static struct alc_channel_mode alc880_2_jack_modes[1] = {
+static struct hda_channel_mode alc880_2_jack_modes[1] = {
{ 2, NULL }
};
-static snd_kcontrol_new_t alc880_z71v_mixer[] = {
+static struct snd_kcontrol_new alc880_z71v_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -602,7 +635,7 @@ static hda_nid_t alc880_f1734_dac_nids[1] = {
};
#define ALC880_F1734_HP_DAC 0x02
-static snd_kcontrol_new_t alc880_f1734_mixer[] = {
+static struct snd_kcontrol_new alc880_f1734_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -627,7 +660,7 @@ static snd_kcontrol_new_t alc880_f1734_mixer[] = {
#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
-static snd_kcontrol_new_t alc880_asus_mixer[] = {
+static struct snd_kcontrol_new alc880_asus_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -645,9 +678,9 @@ static snd_kcontrol_new_t alc880_asus_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
},
{ } /* end */
};
@@ -662,19 +695,46 @@ static snd_kcontrol_new_t alc880_asus_mixer[] = {
*/
/* additional mixers to alc880_asus_mixer */
-static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
+static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
{ } /* end */
};
/* additional mixers to alc880_asus_mixer */
-static snd_kcontrol_new_t alc880_pcbeep_mixer[] = {
+static struct snd_kcontrol_new 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 */
};
+/* TCL S700 */
+static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
/*
* build control elements
*/
@@ -974,6 +1034,8 @@ static struct hda_verb alc880_gpio1_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+
+ { }
};
/* Enable GPIO mask and set output */
@@ -981,8 +1043,59 @@ static struct hda_verb alc880_gpio2_init_verbs[] = {
{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+
+ { }
};
+/* Clevo m520g init */
+static struct hda_verb alc880_pin_clevo_init_verbs[] = {
+ /* headphone output */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* line-out */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Line-in */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* CD */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Mic1 (rear panel) */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Mic2 (front panel) */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* headphone */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* change to EAPD mode */
+ {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+ {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
+
+ { }
+};
+
+static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
+ /* Headphone output */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ /* Front output*/
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+
+ /* change to EAPD mode */
+ {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+ {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
+
+ { }
+};
/*
*/
@@ -1023,7 +1136,7 @@ static int alc_resume(struct hda_codec *codec)
*/
static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
@@ -1033,7 +1146,7 @@ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
@@ -1042,7 +1155,7 @@ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
@@ -1053,7 +1166,7 @@ static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
*/
static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
@@ -1061,7 +1174,7 @@ static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
@@ -1074,7 +1187,7 @@ static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
@@ -1085,7 +1198,7 @@ static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct alc_spec *spec = codec->spec;
@@ -1147,15 +1260,23 @@ static int alc_build_pcms(struct hda_codec *codec)
codec->pcm_info = info;
info->name = spec->stream_name_analog;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
- for (i = 0; i < spec->num_channel_mode; i++) {
- if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+ if (spec->stream_analog_playback) {
+ snd_assert(spec->multiout.dac_nids, return -EINVAL);
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+ }
+ if (spec->stream_analog_capture) {
+ snd_assert(spec->adc_nids, return -EINVAL);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
+ }
+
+ if (spec->channel_mode) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+ for (i = 0; i < spec->num_channel_mode; i++) {
+ if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+ }
}
}
@@ -1163,11 +1284,13 @@ static int alc_build_pcms(struct hda_codec *codec)
codec->num_pcms++;
info++;
info->name = spec->stream_name_digital;
- if (spec->multiout.dig_out_nid) {
+ if (spec->multiout.dig_out_nid &&
+ spec->stream_digital_playback) {
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
}
- if (spec->dig_in_nid) {
+ if (spec->dig_in_nid &&
+ spec->stream_digital_capture) {
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
}
@@ -1227,14 +1350,14 @@ static struct hda_input_mux alc880_test_capture_source = {
},
};
-static struct alc_channel_mode alc880_test_modes[4] = {
+static struct hda_channel_mode alc880_test_modes[4] = {
{ 2, NULL },
{ 4, NULL },
{ 6, NULL },
{ 8, NULL },
};
-static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"N/A", "Line Out", "HP Out",
@@ -1249,7 +1372,7 @@ static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
@@ -1275,7 +1398,7 @@ static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
@@ -1301,7 +1424,7 @@ static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"Front", "Surround", "CLFE", "Side"
@@ -1315,7 +1438,7 @@ static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
@@ -1326,7 +1449,7 @@ static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
@@ -1359,7 +1482,7 @@ static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
.private_value = nid \
}
-static snd_kcontrol_new_t alc880_test_mixer[] = {
+static struct snd_kcontrol_new alc880_test_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
@@ -1393,9 +1516,9 @@ static snd_kcontrol_new_t alc880_test_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
},
{ } /* end */
};
@@ -1491,6 +1614,8 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
+ /* TCL S700 */
+ { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
/* Back 3 jack, front 2 jack (Internal add Aux-In) */
{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
@@ -1501,6 +1626,8 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .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 },
+ /* Clevo m520G NB */
+ { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO },
/* 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 },
@@ -1538,6 +1665,8 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
{ .modelname = "6stack", .config = ALC880_6ST },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
{ .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
@@ -1545,6 +1674,11 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
{ .modelname = "asus", .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
@@ -1558,37 +1692,26 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
+ { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
{ .modelname = "F1734", .config = ALC880_F1734 },
{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
+ { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
#ifdef CONFIG_SND_DEBUG
{ .modelname = "test", .config = ALC880_TEST },
#endif
+ { .modelname = "auto", .config = ALC880_AUTO },
{}
};
/*
- * configuration template - to be copied to the spec instance
+ * ALC880 codec presets
*/
-struct alc_config_preset {
- snd_kcontrol_new_t *mixers[4];
- const struct hda_verb *init_verbs[4];
- unsigned int num_dacs;
- hda_nid_t *dac_nids;
- hda_nid_t dig_out_nid; /* optional */
- hda_nid_t hp_nid; /* optional */
- unsigned int num_adc_nids;
- hda_nid_t *adc_nids;
- unsigned int num_channel_mode;
- const struct alc_channel_mode *channel_mode;
- const struct hda_input_mux *input_mux;
-};
-
static struct alc_config_preset alc880_presets[] = {
[ALC880_3ST] = {
.mixers = { alc880_three_stack_mixer },
@@ -1609,6 +1732,18 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_threestack_modes,
.input_mux = &alc880_capture_source,
},
+ [ALC880_TCL_S700] = {
+ .mixers = { alc880_tcl_s700_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_pin_tcl_S700_init_verbs,
+ alc880_gpio2_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+ .input_mux = &alc880_capture_source,
+ },
[ALC880_5ST] = {
.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
@@ -1700,6 +1835,17 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_asus_modes,
.input_mux = &alc880_capture_source,
},
+ [ALC880_ASUS_DIG2] = {
+ .mixers = { alc880_asus_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+ alc880_gpio2_init_verbs }, /* use GPIO2 */
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+ .channel_mode = alc880_asus_modes,
+ .input_mux = &alc880_capture_source,
+ },
[ALC880_ASUS_W1V] = {
.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
@@ -1721,6 +1867,17 @@ static struct alc_config_preset alc880_presets[] = {
.channel_mode = alc880_asus_modes,
.input_mux = &alc880_capture_source,
},
+ [ALC880_CLEVO] = {
+ .mixers = { alc880_three_stack_mixer },
+ .init_verbs = { alc880_volume_init_verbs,
+ alc880_pin_clevo_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+ .channel_mode = alc880_threestack_modes,
+ .input_mux = &alc880_capture_source,
+ },
#ifdef CONFIG_SND_DEBUG
[ALC880_TEST] = {
.mixers = { alc880_test_mixer },
@@ -1747,7 +1904,7 @@ enum {
ALC_CTL_WIDGET_MUTE,
ALC_CTL_BIND_MUTE,
};
-static snd_kcontrol_new_t alc880_control_templates[] = {
+static struct snd_kcontrol_new alc880_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_BIND_MUTE(NULL, 0, 0, 0),
@@ -1756,7 +1913,7 @@ static snd_kcontrol_new_t alc880_control_templates[] = {
/* add dynamic controls */
static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
{
- snd_kcontrol_new_t *knew;
+ struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) {
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
@@ -1809,7 +1966,7 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi
nid = cfg->line_out_pins[i];
if (alc880_is_fixed_pin(nid)) {
int idx = alc880_fixed_pin_idx(nid);
- spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
+ spec->multiout.dac_nids[i] = alc880_idx_to_dac(idx);
assigned[idx] = 1;
}
}
@@ -1832,7 +1989,8 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi
}
/* add playback controls from the parsed DAC table */
-static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
{
char name[32];
static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
@@ -1868,15 +2026,16 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct
return err;
}
}
-
return 0;
}
-/* add playback controls for HP output */
-static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+/* add playback controls for speaker and HP outputs */
+static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
+ const char *pfx)
{
hda_nid_t nid;
int err;
+ char name[32];
if (! pin)
return 0;
@@ -1889,14 +2048,16 @@ static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
if (! spec->multiout.num_dacs)
spec->multiout.num_dacs = 1;
} else
- /* specify the DAC as the extra HP output */
+ /* specify the DAC as the extra output */
spec->multiout.hp_nid = nid;
/* control HP volume/switch on the output mixer amp */
nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
- if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+ sprintf(name, "%s Playback Volume", pfx);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
return err;
- if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch",
+ sprintf(name, "%s Playback Switch", pfx);
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
return err;
} else if (alc880_is_multi_pin(pin)) {
@@ -1908,7 +2069,8 @@ static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
spec->multiout.num_dacs = 1;
}
/* we have only a switch on HP-out PIN */
- if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+ sprintf(name, "%s Playback Switch", pfx);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
return err;
}
@@ -1916,38 +2078,39 @@ static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
}
/* create input playback/capture controls for the given pin */
-static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
+ int idx, hda_nid_t mix_nid)
{
char name[32];
- int err, idx;
+ int err;
sprintf(name, "%s Playback Volume", ctlname);
- idx = alc880_input_pin_idx(pin);
if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
- HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+ HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
return err;
sprintf(name, "%s Playback Switch", ctlname);
if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
- HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+ HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
return err;
return 0;
}
/* create playback/capture controls for input pins */
-static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
{
- static char *labels[AUTO_PIN_LAST] = {
- "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
- };
struct hda_input_mux *imux = &spec->private_imux;
- int i, err;
+ int i, err, idx;
for (i = 0; i < AUTO_PIN_LAST; i++) {
if (alc880_is_input_pin(cfg->input_pins[i])) {
- err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
+ idx = alc880_input_pin_idx(cfg->input_pins[i]);
+ err = new_analog_input(spec, cfg->input_pins[i],
+ auto_pin_cfg_labels[i],
+ idx, 0x0b);
if (err < 0)
return err;
- imux->items[imux->num_items].label = labels[i];
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
imux->num_items++;
}
@@ -1955,7 +2118,8 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const str
return 0;
}
-static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
+static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
int dac_idx)
{
/* set as output */
@@ -1982,11 +2146,14 @@ static void alc880_auto_init_multi_out(struct hda_codec *codec)
}
}
-static void alc880_auto_init_hp_out(struct hda_codec *codec)
+static void alc880_auto_init_extra_out(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
hda_nid_t pin;
+ pin = spec->autocfg.speaker_pin;
+ if (pin) /* connect to front */
+ alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
pin = spec->autocfg.hp_pin;
if (pin) /* connect to front */
alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
@@ -2015,15 +2182,21 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int err;
+ static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
- if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+ alc880_ignore)) < 0)
return err;
- if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
- return err;
- if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
+ if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
+ ! spec->autocfg.hp_pin)
return 0; /* can't find valid BIOS pin config */
- if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
- (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+
+ if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
+ (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+ (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
+ "Speaker")) < 0 ||
+ (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
+ "Headphone")) < 0 ||
(err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
return err;
@@ -2049,7 +2222,7 @@ static int alc880_auto_init(struct hda_codec *codec)
{
alc_init(codec);
alc880_auto_init_multi_out(codec);
- alc880_auto_init_hp_out(codec);
+ alc880_auto_init_extra_out(codec);
alc880_auto_init_analog_input(codec);
return 0;
}
@@ -2062,7 +2235,7 @@ static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
int board_config;
- int i, err;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -2088,36 +2261,8 @@ static int patch_alc880(struct hda_codec *codec)
}
}
- if (board_config != ALC880_AUTO) {
- /* set up from the preset table */
- const struct alc_config_preset *preset;
-
- preset = &alc880_presets[board_config];
-
- for (i = 0; preset->mixers[i]; i++) {
- snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
- spec->mixers[spec->num_mixers++] = preset->mixers[i];
- }
- for (i = 0; preset->init_verbs[i]; i++) {
- snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
- spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
- }
-
- spec->channel_mode = preset->channel_mode;
- spec->num_channel_mode = preset->num_channel_mode;
-
- spec->multiout.max_channels = spec->channel_mode[0].channels;
-
- spec->multiout.num_dacs = preset->num_dacs;
- spec->multiout.dac_nids = preset->dac_nids;
- spec->multiout.dig_out_nid = preset->dig_out_nid;
- spec->multiout.hp_nid = preset->hp_nid;
-
- spec->input_mux = preset->input_mux;
-
- spec->num_adc_nids = preset->num_adc_nids;
- spec->adc_nids = preset->adc_nids;
- }
+ if (board_config != ALC880_AUTO)
+ setup_preset(spec, &alc880_presets[board_config]);
spec->stream_name_analog = "ALC880 Analog";
spec->stream_analog_playback = &alc880_pcm_analog_playback;
@@ -2129,8 +2274,7 @@ static int patch_alc880(struct hda_codec *codec)
if (! spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
- unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
- AC_PAR_AUDIO_WIDGET_CAP);
+ unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
if (wcap != AC_WID_AUD_IN) {
spec->adc_nids = alc880_adc_nids_alt;
@@ -2167,11 +2311,16 @@ static hda_nid_t alc260_adc_nids[1] = {
0x04,
};
-static hda_nid_t alc260_hp_adc_nids[1] = {
+static hda_nid_t alc260_adc_nids_alt[1] = {
/* ADC1 */
0x05,
};
+static hda_nid_t alc260_hp_adc_nids[2] = {
+ /* ADC1, 0 */
+ 0x05, 0x04
+};
+
#define ALC260_DIGOUT_NID 0x03
#define ALC260_DIGIN_NID 0x06
@@ -2202,42 +2351,30 @@ static struct hda_input_mux alc260_fujitsu_capture_source = {
* element which allows changing the channel mode, so the verb list is
* never used.
*/
-static struct alc_channel_mode alc260_modes[1] = {
+static struct hda_channel_mode alc260_modes[1] = {
{ 2, NULL },
};
-static snd_kcontrol_new_t alc260_base_mixer[] = {
+
+/* Mixer combinations
+ *
+ * basic: base_output + input + pc_beep + capture
+ * HP: base_output + input + capture_alt
+ * HP_3013: hp_3013 + input + capture
+ * fujitsu: fujitsu + capture
+ */
+
+static struct snd_kcontrol_new alc260_base_output_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{ } /* end */
-};
+};
-static snd_kcontrol_new_t alc260_hp_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+static struct snd_kcontrol_new alc260_input_mixer[] = {
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -2246,23 +2383,28 @@ static snd_kcontrol_new_t alc260_hp_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{ } /* end */
};
-static snd_kcontrol_new_t alc260_fujitsu_mixer[] = {
+static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
+ HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
+ HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP),
@@ -2274,11 +2416,24 @@ static snd_kcontrol_new_t alc260_fujitsu_mixer[] = {
HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
+ { } /* end */
+};
+
+/* capture mixer elements */
+static struct snd_kcontrol_new alc260_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
.info = alc_mux_enum_info,
.get = alc_mux_enum_get,
.put = alc_mux_enum_put,
@@ -2286,6 +2441,28 @@ static snd_kcontrol_new_t alc260_fujitsu_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
+/*
+ * initialization verbs
+ */
static struct hda_verb alc260_init_verbs[] = {
/* Line In pin widget for input */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -2347,6 +2524,100 @@ static struct hda_verb alc260_init_verbs[] = {
{ }
};
+static struct hda_verb alc260_hp_init_verbs[] = {
+ /* Headphone and output */
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+ /* mono output */
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Line In pin widget for input */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Line-2 pin widget for output */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* CD pin widget for input */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* unmute amp left and right */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute Line-Out mixer amp left and right (volume = 0) */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute HP mixer amp left and right (volume = 0) */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+ /* unmute CD */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Headphone out path */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Mono out path */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ { }
+};
+
+static struct hda_verb alc260_hp_3013_init_verbs[] = {
+ /* Line out and output */
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* mono output */
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Mic2 (front panel) pin widget for input and vref at 80% */
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ /* Line In pin widget for input */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* Headphone pin widget for output */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+ /* CD pin widget for input */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ /* unmute amp left and right */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* set connection select to line in (default select for this ADC) */
+ {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* unmute Line-Out mixer amp left and right (volume = 0) */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* unmute HP mixer amp left and right (volume = 0) */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* mute pin widget amp left and right (no gain on this amp) */
+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+ /* unmute CD */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+ /* unmute Line In */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+ /* unmute Mic */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+ /* Unmute Front out path */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Headphone out path */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* Unmute Mono out path */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ { }
+};
+
/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
* laptops.
*/
@@ -2399,6 +2670,8 @@ static struct hda_verb alc260_fujitsu_init_verbs[] = {
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
+
+ { }
};
static struct hda_pcm_stream alc260_pcm_analog_playback = {
@@ -2413,18 +2686,338 @@ static struct hda_pcm_stream alc260_pcm_analog_capture = {
.channels_max = 2,
};
+#define alc260_pcm_digital_playback alc880_pcm_digital_playback
+#define alc260_pcm_digital_capture alc880_pcm_digital_capture
+
+/*
+ * for BIOS auto-configuration
+ */
+
+static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
+ const char *pfx)
+{
+ hda_nid_t nid_vol;
+ unsigned long vol_val, sw_val;
+ char name[32];
+ int err;
+
+ if (nid >= 0x0f && nid < 0x11) {
+ nid_vol = nid - 0x7;
+ vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
+ sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ } else if (nid == 0x11) {
+ nid_vol = nid - 0x7;
+ vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
+ sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
+ } else if (nid >= 0x12 && nid <= 0x15) {
+ nid_vol = 0x08;
+ vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
+ sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ } else
+ return 0; /* N/A */
+
+ snprintf(name, sizeof(name), "%s Playback Volume", pfx);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
+ return err;
+ snprintf(name, sizeof(name), "%s Playback Switch", pfx);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
+ return err;
+ return 1;
+}
+
+/* add playback controls from the parsed DAC table */
+static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
+{
+ hda_nid_t nid;
+ int err;
+
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = spec->private_dac_nids;
+ spec->multiout.dac_nids[0] = 0x02;
+
+ nid = cfg->line_out_pins[0];
+ if (nid) {
+ err = alc260_add_playback_controls(spec, nid, "Front");
+ if (err < 0)
+ return err;
+ }
+
+ nid = cfg->speaker_pin;
+ if (nid) {
+ err = alc260_add_playback_controls(spec, nid, "Speaker");
+ if (err < 0)
+ return err;
+ }
+
+ nid = cfg->hp_pin;
+ if (nid) {
+ err = alc260_add_playback_controls(spec, nid, "Headphone");
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
+{
+ struct hda_input_mux *imux = &spec->private_imux;
+ int i, err, idx;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ if (cfg->input_pins[i] >= 0x12) {
+ idx = cfg->input_pins[i] - 0x12;
+ err = new_analog_input(spec, cfg->input_pins[i],
+ auto_pin_cfg_labels[i], idx, 0x07);
+ if (err < 0)
+ return err;
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+ imux->items[imux->num_items].index = idx;
+ imux->num_items++;
+ }
+ if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
+ idx = cfg->input_pins[i] - 0x09;
+ err = new_analog_input(spec, cfg->input_pins[i],
+ auto_pin_cfg_labels[i], idx, 0x07);
+ if (err < 0)
+ return err;
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+ imux->items[imux->num_items].index = idx;
+ imux->num_items++;
+ }
+ }
+ return 0;
+}
+
+static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
+ int sel_idx)
+{
+ /* set as output */
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ /* need the manual connection? */
+ if (nid >= 0x12) {
+ int idx = nid - 0x12;
+ snd_hda_codec_write(codec, idx + 0x0b, 0,
+ AC_VERB_SET_CONNECT_SEL, sel_idx);
+
+ }
+}
+
+static void alc260_auto_init_multi_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t nid;
+
+ nid = spec->autocfg.line_out_pins[0];
+ if (nid)
+ alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
+
+ nid = spec->autocfg.speaker_pin;
+ if (nid)
+ alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
+
+ nid = spec->autocfg.hp_pin;
+ if (nid)
+ alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
+}
+
+#define ALC260_PIN_CD_NID 0x16
+static void alc260_auto_init_analog_input(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if (nid >= 0x12) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+ if (nid != ALC260_PIN_CD_NID)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_MUTE);
+ }
+ }
+}
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc260_volume_init_verbs[] = {
+ /*
+ * Unmute ADC0-1 and set the default input to mic-in
+ */
+ {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ * Note: PASD motherboards uses the Line In 2 as the input for front panel
+ * mic (mic 2)
+ */
+ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ /*
+ * Set up output mixers (0x08 - 0x0a)
+ */
+ /* set vol=0 to output mixers */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* set up input amps for analog loopback */
+ /* Amp Indices: DAC = 0, mixer = 1 */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ { }
+};
+
+static int alc260_parse_auto_config(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int wcap;
+ int err;
+ static hda_nid_t alc260_ignore[] = { 0x17, 0 };
+
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+ alc260_ignore)) < 0)
+ return err;
+ if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+ if (! spec->kctl_alloc)
+ return 0; /* can't find valid BIOS pin config */
+ if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+
+ spec->multiout.max_channels = 2;
+
+ if (spec->autocfg.dig_out_pin)
+ spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+ spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
+
+ spec->input_mux = &spec->private_imux;
+
+ /* check whether NID 0x04 is valid */
+ wcap = get_wcaps(codec, 0x04);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc260_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
+ } else {
+ spec->adc_nids = alc260_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ spec->mixers[spec->num_mixers] = alc260_capture_mixer;
+ }
+ spec->num_mixers++;
+
+ return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc260_auto_init(struct hda_codec *codec)
+{
+ alc_init(codec);
+ alc260_auto_init_multi_out(codec);
+ alc260_auto_init_analog_input(codec);
+ return 0;
+}
+
+/*
+ * ALC260 configurations
+ */
static struct hda_board_config alc260_cfg_tbl[] = {
+ { .modelname = "basic", .config = ALC260_BASIC },
{ .modelname = "hp", .config = ALC260_HP },
- { .pci_subvendor = 0x103c, .config = ALC260_HP },
- { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x },
- { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
+ { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
+ { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
+ { .modelname = "auto", .config = ALC260_AUTO },
{}
};
+static struct alc_config_preset alc260_presets[] = {
+ [ALC260_BASIC] = {
+ .mixers = { alc260_base_output_mixer,
+ alc260_input_mixer,
+ alc260_pc_beep_mixer,
+ alc260_capture_mixer },
+ .init_verbs = { alc260_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ .dac_nids = alc260_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+ .adc_nids = alc260_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc260_modes),
+ .channel_mode = alc260_modes,
+ .input_mux = &alc260_capture_source,
+ },
+ [ALC260_HP] = {
+ .mixers = { alc260_base_output_mixer,
+ alc260_input_mixer,
+ alc260_capture_alt_mixer },
+ .init_verbs = { alc260_hp_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ .dac_nids = alc260_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
+ .adc_nids = alc260_hp_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc260_modes),
+ .channel_mode = alc260_modes,
+ .input_mux = &alc260_capture_source,
+ },
+ [ALC260_HP_3013] = {
+ .mixers = { alc260_hp_3013_mixer,
+ alc260_input_mixer,
+ alc260_capture_alt_mixer },
+ .init_verbs = { alc260_hp_3013_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ .dac_nids = alc260_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
+ .adc_nids = alc260_hp_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc260_modes),
+ .channel_mode = alc260_modes,
+ .input_mux = &alc260_capture_source,
+ },
+ [ALC260_FUJITSU_S702X] = {
+ .mixers = { alc260_fujitsu_mixer,
+ alc260_capture_mixer },
+ .init_verbs = { alc260_fujitsu_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc260_dac_nids),
+ .dac_nids = alc260_dac_nids,
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+ .adc_nids = alc260_adc_nids,
+ .num_channel_mode = ARRAY_SIZE(alc260_modes),
+ .channel_mode = alc260_modes,
+ .input_mux = &alc260_fujitsu_capture_source,
+ },
+};
+
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
+ int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -2435,60 +3028,35 @@ static int patch_alc260(struct hda_codec *codec)
board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
- board_config = ALC260_BASIC;
+ board_config = ALC260_AUTO;
}
- switch (board_config) {
- case ALC260_HP:
- spec->mixers[spec->num_mixers] = alc260_hp_mixer;
- spec->num_mixers++;
- break;
- case ALC260_FUJITSU_S702x:
- spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer;
- spec->num_mixers++;
- break;
- default:
- spec->mixers[spec->num_mixers] = alc260_base_mixer;
- spec->num_mixers++;
- break;
- }
-
- if (board_config != ALC260_FUJITSU_S702x) {
- spec->init_verbs[0] = alc260_init_verbs;
- spec->num_init_verbs = 1;
- } else {
- spec->init_verbs[0] = alc260_fujitsu_init_verbs;
- spec->num_init_verbs = 1;
+ if (board_config == ALC260_AUTO) {
+ /* automatic parse from the BIOS config */
+ err = alc260_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
+ board_config = ALC260_BASIC;
+ }
}
- spec->channel_mode = alc260_modes;
- spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
+ if (board_config != ALC260_AUTO)
+ setup_preset(spec, &alc260_presets[board_config]);
spec->stream_name_analog = "ALC260 Analog";
spec->stream_analog_playback = &alc260_pcm_analog_playback;
spec->stream_analog_capture = &alc260_pcm_analog_capture;
- spec->multiout.max_channels = spec->channel_mode[0].channels;
- spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
- spec->multiout.dac_nids = alc260_dac_nids;
-
- if (board_config != ALC260_FUJITSU_S702x) {
- spec->input_mux = &alc260_capture_source;
- } else {
- spec->input_mux = &alc260_fujitsu_capture_source;
- }
- switch (board_config) {
- case ALC260_HP:
- spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
- spec->adc_nids = alc260_hp_adc_nids;
- break;
- default:
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
- spec->adc_nids = alc260_adc_nids;
- break;
- }
+ spec->stream_name_digital = "ALC260 Digital";
+ spec->stream_digital_playback = &alc260_pcm_digital_playback;
+ spec->stream_digital_capture = &alc260_pcm_digital_capture;
codec->patch_ops = alc_patch_ops;
+ if (board_config == ALC260_AUTO)
+ codec->patch_ops.init = alc260_auto_init;
return 0;
}
@@ -2505,8 +3073,10 @@ static int patch_alc260(struct hda_codec *codec)
* In addition, an independent DAC for the multi-playback (not used in this
* driver yet).
*/
+#define ALC882_DIGOUT_NID 0x06
+#define ALC882_DIGIN_NID 0x0a
-static struct alc_channel_mode alc882_ch_modes[1] = {
+static struct hda_channel_mode alc882_ch_modes[1] = {
{ 8, NULL }
};
@@ -2515,10 +3085,9 @@ static hda_nid_t alc882_dac_nids[4] = {
0x02, 0x03, 0x04, 0x05
};
-static hda_nid_t alc882_adc_nids[3] = {
- /* ADC0-2 */
- 0x07, 0x08, 0x09,
-};
+/* identical with ALC880 */
+#define alc882_adc_nids alc880_adc_nids
+#define alc882_adc_nids_alt alc880_adc_nids_alt
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
@@ -2536,7 +3105,7 @@ static struct hda_input_mux alc882_capture_source = {
#define alc882_mux_enum_info alc_mux_enum_info
#define alc882_mux_enum_get alc_mux_enum_get
-static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
@@ -2561,10 +3130,37 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 1;
}
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc882_sixstack_ch6_init[] = {
+ { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+ { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { } /* end */
+};
+
+/*
+ * 8ch mode
+ */
+static struct hda_verb alc882_sixstack_ch8_init[] = {
+ { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { } /* end */
+};
+
+static struct hda_channel_mode alc882_sixstack_modes[2] = {
+ { 6, alc882_sixstack_ch6_init },
+ { 8, alc882_sixstack_ch8_init },
+};
+
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
-static snd_kcontrol_new_t alc882_base_mixer[] = {
+static struct snd_kcontrol_new alc882_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
@@ -2604,6 +3200,17 @@ static snd_kcontrol_new_t alc882_base_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc882_chmode_mixer[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
+ },
+ { } /* end */
+};
+
static struct hda_verb alc882_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -2684,9 +3291,264 @@ static struct hda_verb alc882_init_verbs[] = {
{ }
};
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc882_auto_init_verbs[] = {
+ /*
+ * Unmute ADC0-2 and set the default input to mic-in
+ */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ * Note: PASD motherboards uses the Line In 2 as the input for front panel
+ * mic (mic 2)
+ */
+ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ /*
+ * Set up output mixers (0x0c - 0x0f)
+ */
+ /* set vol=0 to output mixers */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* set up input amps for analog loopback */
+ /* Amp Indices: DAC = 0, mixer = 1 */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* FIXME: use matrix-type input source selection */
+ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer2 */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+
+ { }
+};
+
+/* capture mixer elements */
+static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc882_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 3,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
+/* pcm configuration: identiacal with ALC880 */
+#define alc882_pcm_analog_playback alc880_pcm_analog_playback
+#define alc882_pcm_analog_capture alc880_pcm_analog_capture
+#define alc882_pcm_digital_playback alc880_pcm_digital_playback
+#define alc882_pcm_digital_capture alc880_pcm_digital_capture
+
+/*
+ * configuration and preset
+ */
+static struct hda_board_config alc882_cfg_tbl[] = {
+ { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
+ { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */
+ { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
+ { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
+ { .modelname = "auto", .config = ALC861_AUTO },
+ {}
+};
+
+static struct alc_config_preset alc882_presets[] = {
+ [ALC882_3ST_DIG] = {
+ .mixers = { alc882_base_mixer },
+ .init_verbs = { alc882_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .dac_nids = alc882_dac_nids,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ .adc_nids = alc882_adc_nids,
+ .dig_in_nid = ALC882_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
+ .channel_mode = alc882_ch_modes,
+ .input_mux = &alc882_capture_source,
+ },
+ [ALC882_6ST_DIG] = {
+ .mixers = { alc882_base_mixer, alc882_chmode_mixer },
+ .init_verbs = { alc882_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .dac_nids = alc882_dac_nids,
+ .dig_out_nid = ALC882_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
+ .adc_nids = alc882_adc_nids,
+ .dig_in_nid = ALC882_DIGIN_NID,
+ .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
+ .channel_mode = alc882_sixstack_modes,
+ .input_mux = &alc882_capture_source,
+ },
+};
+
+
+/*
+ * BIOS auto configuration
+ */
+static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
+ hda_nid_t nid, int pin_type,
+ int dac_idx)
+{
+ /* set as output */
+ struct alc_spec *spec = codec->spec;
+ int idx;
+
+ if (spec->multiout.dac_nids[dac_idx] == 0x25)
+ idx = 4;
+ else
+ idx = spec->multiout.dac_nids[dac_idx] - 2;
+
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
+
+}
+
+static void alc882_auto_init_multi_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i <= HDA_SIDE; i++) {
+ hda_nid_t nid = spec->autocfg.line_out_pins[i];
+ if (nid)
+ alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+ }
+}
+
+static void alc882_auto_init_hp_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t pin;
+
+ pin = spec->autocfg.hp_pin;
+ if (pin) /* connect to front */
+ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
+}
+
+#define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
+#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
+
+static void alc882_auto_init_analog_input(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if (alc882_is_input_pin(nid)) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+ if (nid != ALC882_PIN_CD_NID)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_MUTE);
+ }
+ }
+}
+
+/* almost identical with ALC880 parser... */
+static int alc882_parse_auto_config(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err = alc880_parse_auto_config(codec);
+
+ if (err < 0)
+ return err;
+ else if (err > 0)
+ /* hack - override the init verbs */
+ spec->init_verbs[0] = alc882_auto_init_verbs;
+ return err;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc882_auto_init(struct hda_codec *codec)
+{
+ alc_init(codec);
+ alc882_auto_init_multi_out(codec);
+ alc882_auto_init_hp_out(codec);
+ alc882_auto_init_analog_input(codec);
+ return 0;
+}
+
+/*
+ * ALC882 Headphone poll in 3.5.1a or 3.5.2
+ */
+
static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
+ int err, board_config;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -2694,35 +3556,1134 @@ static int patch_alc882(struct hda_codec *codec)
codec->spec = spec;
- spec->mixers[spec->num_mixers] = alc882_base_mixer;
- spec->num_mixers++;
+ board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
- spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- spec->dig_in_nid = ALC880_DIGIN_NID;
- spec->init_verbs[0] = alc882_init_verbs;
- spec->num_init_verbs = 1;
+ if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
+ printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
+ board_config = ALC882_AUTO;
+ }
- spec->channel_mode = alc882_ch_modes;
- spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
+ if (board_config == ALC882_AUTO) {
+ /* automatic parse from the BIOS config */
+ err = alc882_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
+ board_config = ALC882_3ST_DIG;
+ }
+ }
+
+ if (board_config != ALC882_AUTO)
+ setup_preset(spec, &alc882_presets[board_config]);
spec->stream_name_analog = "ALC882 Analog";
- spec->stream_analog_playback = &alc880_pcm_analog_playback;
- spec->stream_analog_capture = &alc880_pcm_analog_capture;
+ spec->stream_analog_playback = &alc882_pcm_analog_playback;
+ spec->stream_analog_capture = &alc882_pcm_analog_capture;
spec->stream_name_digital = "ALC882 Digital";
- spec->stream_digital_playback = &alc880_pcm_digital_playback;
- spec->stream_digital_capture = &alc880_pcm_digital_capture;
+ spec->stream_digital_playback = &alc882_pcm_digital_playback;
+ spec->stream_digital_capture = &alc882_pcm_digital_capture;
- spec->multiout.max_channels = spec->channel_mode[0].channels;
- spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
- spec->multiout.dac_nids = alc882_dac_nids;
+ if (! spec->adc_nids && spec->input_mux) {
+ /* check whether NID 0x07 is valid */
+ unsigned int wcap = get_wcaps(codec, 0x07);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc882_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
+ spec->num_mixers++;
+ } else {
+ spec->adc_nids = alc882_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
+ spec->mixers[spec->num_mixers] = alc882_capture_mixer;
+ spec->num_mixers++;
+ }
+ }
+
+ codec->patch_ops = alc_patch_ops;
+ if (board_config == ALC882_AUTO)
+ codec->patch_ops.init = alc882_auto_init;
+
+ return 0;
+}
+
+/*
+ * ALC262 support
+ */
+
+#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
+#define ALC262_DIGIN_NID ALC880_DIGIN_NID
+
+#define alc262_dac_nids alc260_dac_nids
+#define alc262_adc_nids alc882_adc_nids
+#define alc262_adc_nids_alt alc882_adc_nids_alt
+
+#define alc262_modes alc260_modes
+#define alc262_capture_source alc882_capture_source
- spec->input_mux = &alc882_capture_source;
- spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
- spec->adc_nids = alc882_adc_nids;
+static struct snd_kcontrol_new alc262_base_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
+ /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
+#define alc262_capture_mixer alc882_capture_mixer
+#define alc262_capture_alt_mixer alc882_capture_alt_mixer
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc262_init_verbs[] = {
+ /*
+ * Unmute ADC0-2 and set the default input to mic-in
+ */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ * Note: PASD motherboards uses the Line In 2 as the input for front panel
+ * mic (mic 2)
+ */
+ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ /*
+ * Set up output mixers (0x0c - 0x0e)
+ */
+ /* set vol=0 to output mixers */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* set up input amps for analog loopback */
+ /* Amp Indices: DAC = 0, mixer = 1 */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+ {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+
+ /* FIXME: use matrix-type input source selection */
+ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer2 */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+
+ { }
+};
+
+/* add playback controls from the parsed DAC table */
+static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ hda_nid_t nid;
+ int err;
+
+ spec->multiout.num_dacs = 1; /* only use one dac */
+ spec->multiout.dac_nids = spec->private_dac_nids;
+ spec->multiout.dac_nids[0] = 2;
+
+ nid = cfg->line_out_pins[0];
+ if (nid) {
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ }
+
+ nid = cfg->speaker_pin;
+ if (nid) {
+ if (nid == 0x16) {
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ } else {
+ if (! cfg->line_out_pins[0])
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ }
+ }
+ nid = cfg->hp_pin;
+ if (nid) {
+ /* spec->multiout.hp_nid = 2; */
+ if (nid == 0x16) {
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ } else {
+ if (! cfg->line_out_pins[0])
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+ HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
+/* identical with ALC880 */
+#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc262_volume_init_verbs[] = {
+ /*
+ * Unmute ADC0-2 and set the default input to mic-in
+ */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
+ * Note: PASD motherboards uses the Line In 2 as the input for front panel
+ * mic (mic 2)
+ */
+ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ /*
+ * Set up output mixers (0x0c - 0x0f)
+ */
+ /* set vol=0 to output mixers */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+ /* set up input amps for analog loopback */
+ /* Amp Indices: DAC = 0, mixer = 1 */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* FIXME: use matrix-type input source selection */
+ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer2 */
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ /* Input mixer3 */
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+
+ { }
+};
+
+/* pcm configuration: identiacal with ALC880 */
+#define alc262_pcm_analog_playback alc880_pcm_analog_playback
+#define alc262_pcm_analog_capture alc880_pcm_analog_capture
+#define alc262_pcm_digital_playback alc880_pcm_digital_playback
+#define alc262_pcm_digital_capture alc880_pcm_digital_capture
+
+/*
+ * BIOS auto configuration
+ */
+static int alc262_parse_auto_config(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err;
+ static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
+
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+ alc262_ignore)) < 0)
+ return err;
+ if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
+ ! spec->autocfg.hp_pin)
+ return 0; /* can't find valid BIOS pin config */
+ if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+ (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+
+ spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+ if (spec->autocfg.dig_out_pin)
+ spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
+ if (spec->autocfg.dig_in_pin)
+ spec->dig_in_nid = ALC262_DIGIN_NID;
+
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+ spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
+ spec->input_mux = &spec->private_imux;
+
+ return 1;
+}
+
+#define alc262_auto_init_multi_out alc882_auto_init_multi_out
+#define alc262_auto_init_hp_out alc882_auto_init_hp_out
+#define alc262_auto_init_analog_input alc882_auto_init_analog_input
+
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc262_auto_init(struct hda_codec *codec)
+{
+ alc_init(codec);
+ alc262_auto_init_multi_out(codec);
+ alc262_auto_init_hp_out(codec);
+ alc262_auto_init_analog_input(codec);
+ return 0;
+}
+
+/*
+ * configuration and preset
+ */
+static struct hda_board_config alc262_cfg_tbl[] = {
+ { .modelname = "basic", .config = ALC262_BASIC },
+ { .modelname = "auto", .config = ALC262_AUTO },
+ {}
+};
+
+static struct alc_config_preset alc262_presets[] = {
+ [ALC262_BASIC] = {
+ .mixers = { alc262_base_mixer },
+ .init_verbs = { alc262_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc262_dac_nids),
+ .dac_nids = alc262_dac_nids,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc262_modes),
+ .channel_mode = alc262_modes,
+ .input_mux = &alc262_capture_source,
+ },
+};
+
+static int patch_alc262(struct hda_codec *codec)
+{
+ struct alc_spec *spec;
+ int board_config;
+ int err;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+#if 0
+ /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
+ {
+ int tmp;
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
+ tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
+ snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
+ }
+#endif
+
+ board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
+ if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
+ printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
+ board_config = ALC262_AUTO;
+ }
+
+ if (board_config == ALC262_AUTO) {
+ /* automatic parse from the BIOS config */
+ err = alc262_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
+ board_config = ALC262_BASIC;
+ }
+ }
+
+ if (board_config != ALC262_AUTO)
+ setup_preset(spec, &alc262_presets[board_config]);
+
+ spec->stream_name_analog = "ALC262 Analog";
+ spec->stream_analog_playback = &alc262_pcm_analog_playback;
+ spec->stream_analog_capture = &alc262_pcm_analog_capture;
+
+ spec->stream_name_digital = "ALC262 Digital";
+ spec->stream_digital_playback = &alc262_pcm_digital_playback;
+ spec->stream_digital_capture = &alc262_pcm_digital_capture;
+
+ if (! spec->adc_nids && spec->input_mux) {
+ /* check whether NID 0x07 is valid */
+ unsigned int wcap = get_wcaps(codec, 0x07);
+
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc262_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
+ spec->num_mixers++;
+ } else {
+ spec->adc_nids = alc262_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
+ spec->mixers[spec->num_mixers] = alc262_capture_mixer;
+ spec->num_mixers++;
+ }
+ }
codec->patch_ops = alc_patch_ops;
+ if (board_config == ALC262_AUTO)
+ codec->patch_ops.init = alc262_auto_init;
+
+ return 0;
+}
+
+
+/*
+ * ALC861 channel source setting (2/6 channel selection for 3-stack)
+ */
+
+/*
+ * set the path ways for 2 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc861_threestack_ch2_init[] = {
+ /* set pin widget 1Ah (line in) for input */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
+ { } /* end */
+};
+/*
+ * 6ch mode
+ * need to set the codec line out and mic 1 pin widgets to outputs
+ */
+static struct hda_verb alc861_threestack_ch6_init[] = {
+ /* set pin widget 1Ah (line in) for output (Back Surround)*/
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* set pin widget 18h (mic1) for output (CLFE)*/
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+
+ { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
+
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
+ { } /* end */
+};
+
+static struct hda_channel_mode alc861_threestack_modes[2] = {
+ { 2, alc861_threestack_ch2_init },
+ { 6, alc861_threestack_ch6_init },
+};
+
+/* patch-ALC861 */
+
+static struct snd_kcontrol_new alc861_base_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+
+ /*Input mixer control */
+ /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc861_3ST_mixer[] = {
+ /* output mixer control */
+ HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+ /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
+
+ /* Input mixer control */
+ /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc_ch_mode_info,
+ .get = alc_ch_mode_get,
+ .put = alc_ch_mode_put,
+ .private_value = ARRAY_SIZE(alc861_threestack_modes),
+ },
+ { } /* end */
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc861_base_init_verbs[] = {
+ /*
+ * Unmute ADC0 and set the default input to mic-in
+ */
+ /* port-A for surround (rear panel) */
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ /* port-B for mic-in (rear panel) with vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-C for line-in (rear panel) */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* port-D for Front */
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ /* port-E for HP out (front panel) */
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* route front PCM to HP */
+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ /* port-F for mic-in (front panel) with vref */
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-G for CLFE (rear panel) */
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ /* port-H for side (rear panel) */
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ /* CD-in */
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* route front mic to ADC1*/
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute DAC0~3 & spdif out*/
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ /* Unmute Mixer 14 (mic) 1c (Line in)*/
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* Unmute Stereo Mixer 15 */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
+
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+
+ { }
+};
+
+static struct hda_verb alc861_threestack_init_verbs[] = {
+ /*
+ * Unmute ADC0 and set the default input to mic-in
+ */
+ /* port-A for surround (rear panel) */
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+ /* port-B for mic-in (rear panel) with vref */
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-C for line-in (rear panel) */
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* port-D for Front */
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
+ /* port-E for HP out (front panel) */
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* route front PCM to HP */
+ { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
+ /* port-F for mic-in (front panel) with vref */
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* port-G for CLFE (rear panel) */
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+ /* port-H for side (rear panel) */
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+ /* CD-in */
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* route front mic to ADC1*/
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ /* Unmute DAC0~3 & spdif out*/
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ /* Unmute Mixer 14 (mic) 1c (Line in)*/
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* Unmute Stereo Mixer 15 */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
+
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ { }
+};
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc861_auto_init_verbs[] = {
+ /*
+ * Unmute ADC0 and set the default input to mic-in
+ */
+// {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute DAC0~3 & spdif out*/
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ /* Unmute Mixer 14 (mic) 1c (Line in)*/
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ /* Unmute Stereo Mixer 15 */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
+
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1
+
+ { }
+};
+
+/* pcm configuration: identiacal with ALC880 */
+#define alc861_pcm_analog_playback alc880_pcm_analog_playback
+#define alc861_pcm_analog_capture alc880_pcm_analog_capture
+#define alc861_pcm_digital_playback alc880_pcm_digital_playback
+#define alc861_pcm_digital_capture alc880_pcm_digital_capture
+
+
+#define ALC861_DIGOUT_NID 0x07
+
+static struct hda_channel_mode alc861_8ch_modes[1] = {
+ { 8, NULL }
+};
+
+static hda_nid_t alc861_dac_nids[4] = {
+ /* front, surround, clfe, side */
+ 0x03, 0x06, 0x05, 0x04
+};
+
+static hda_nid_t alc861_adc_nids[1] = {
+ /* ADC0-2 */
+ 0x08,
+};
+
+static struct hda_input_mux alc861_capture_source = {
+ .num_items = 5,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x3 },
+ { "Line", 0x1 },
+ { "CD", 0x4 },
+ { "Mixer", 0x5 },
+ },
+};
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ int i;
+ hda_nid_t nid;
+
+ spec->multiout.dac_nids = spec->private_dac_nids;
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ if (nid) {
+ if (i >= ARRAY_SIZE(alc861_dac_nids))
+ continue;
+ spec->multiout.dac_nids[i] = alc861_dac_nids[i];
+ }
+ }
+ spec->multiout.num_dacs = cfg->line_outs;
+ return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
+ const struct auto_pin_cfg *cfg)
+{
+ char name[32];
+ static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+ hda_nid_t nid;
+ int i, idx, err;
+
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = spec->multiout.dac_nids[i];
+ if (! nid)
+ continue;
+ if (nid == 0x05) {
+ /* Center/LFE */
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ } else {
+ for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
+ if (nid == alc861_dac_nids[idx])
+ break;
+ sprintf(name, "%s Playback Switch", chname[idx]);
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ }
+ }
+ return 0;
+}
+
+static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+{
+ int err;
+ hda_nid_t nid;
+
+ if (! pin)
+ return 0;
+ if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
+ nid = 0x03;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ spec->multiout.hp_nid = nid;
+ }
+ return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ struct hda_input_mux *imux = &spec->private_imux;
+ int i, err, idx, idx1;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ switch(cfg->input_pins[i]) {
+ case 0x0c:
+ idx1 = 1;
+ idx = 2; // Line In
+ break;
+ case 0x0f:
+ idx1 = 2;
+ idx = 2; // Line In
+ break;
+ case 0x0d:
+ idx1 = 0;
+ idx = 1; // Mic In
+ break;
+ case 0x10:
+ idx1 = 3;
+ idx = 1; // Mic In
+ break;
+ case 0x11:
+ idx1 = 4;
+ idx = 0; // CD
+ break;
+ default:
+ continue;
+ }
+
+ err = new_analog_input(spec, cfg->input_pins[i],
+ auto_pin_cfg_labels[i], idx, 0x15);
+ if (err < 0)
+ return err;
+
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+ imux->items[imux->num_items].index = idx1;
+ imux->num_items++;
+ }
+ return 0;
+}
+
+static struct snd_kcontrol_new alc861_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ *FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
+ int pin_type, int dac_idx)
+{
+ /* set as output */
+
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+
+}
+
+static void alc861_auto_init_multi_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->autocfg.line_outs; i++) {
+ hda_nid_t nid = spec->autocfg.line_out_pins[i];
+ if (nid)
+ alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
+ }
+}
+
+static void alc861_auto_init_hp_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t pin;
+
+ pin = spec->autocfg.hp_pin;
+ if (pin) /* connect to front */
+ alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
+}
+
+static void alc861_auto_init_analog_input(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if ((nid>=0x0c) && (nid <=0x11)) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+ }
+ }
+}
+
+/* parse the BIOS configuration and set up the alc_spec */
+/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+static int alc861_parse_auto_config(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err;
+ static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
+
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+ alc861_ignore)) < 0)
+ return err;
+ if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
+ ! spec->autocfg.hp_pin)
+ return 0; /* can't find valid BIOS pin config */
+
+ if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
+ (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+ (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+ (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+
+ spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+ if (spec->autocfg.dig_out_pin)
+ spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
+
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+ spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
+
+ spec->input_mux = &spec->private_imux;
+
+ spec->adc_nids = alc861_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
+ spec->mixers[spec->num_mixers] = alc861_capture_mixer;
+ spec->num_mixers++;
+
+ return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc861_auto_init(struct hda_codec *codec)
+{
+ alc_init(codec);
+ alc861_auto_init_multi_out(codec);
+ alc861_auto_init_hp_out(codec);
+ alc861_auto_init_analog_input(codec);
+
+ return 0;
+}
+
+
+/*
+ * configuration and preset
+ */
+static struct hda_board_config alc861_cfg_tbl[] = {
+ { .modelname = "3stack", .config = ALC861_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
+ { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
+ { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
+ { .modelname = "auto", .config = ALC861_AUTO },
+ {}
+};
+
+static struct alc_config_preset alc861_presets[] = {
+ [ALC861_3ST] = {
+ .mixers = { alc861_3ST_mixer },
+ .init_verbs = { alc861_threestack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc861_dac_nids),
+ .dac_nids = alc861_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
+ .channel_mode = alc861_threestack_modes,
+ .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+ .adc_nids = alc861_adc_nids,
+ .input_mux = &alc861_capture_source,
+ },
+ [ALC861_3ST_DIG] = {
+ .mixers = { alc861_base_mixer },
+ .init_verbs = { alc861_threestack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc861_dac_nids),
+ .dac_nids = alc861_dac_nids,
+ .dig_out_nid = ALC861_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
+ .channel_mode = alc861_threestack_modes,
+ .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+ .adc_nids = alc861_adc_nids,
+ .input_mux = &alc861_capture_source,
+ },
+ [ALC861_6ST_DIG] = {
+ .mixers = { alc861_base_mixer },
+ .init_verbs = { alc861_base_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc861_dac_nids),
+ .dac_nids = alc861_dac_nids,
+ .dig_out_nid = ALC861_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
+ .channel_mode = alc861_8ch_modes,
+ .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
+ .adc_nids = alc861_adc_nids,
+ .input_mux = &alc861_capture_source,
+ },
+};
+
+
+static int patch_alc861(struct hda_codec *codec)
+{
+ struct alc_spec *spec;
+ int board_config;
+ int err;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
+ if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
+ printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
+ board_config = ALC861_AUTO;
+ }
+
+ if (board_config == ALC861_AUTO) {
+ /* automatic parse from the BIOS config */
+ err = alc861_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
+ board_config = ALC861_3ST_DIG;
+ }
+ }
+
+ if (board_config != ALC861_AUTO)
+ setup_preset(spec, &alc861_presets[board_config]);
+
+ spec->stream_name_analog = "ALC861 Analog";
+ spec->stream_analog_playback = &alc861_pcm_analog_playback;
+ spec->stream_analog_capture = &alc861_pcm_analog_capture;
+
+ spec->stream_name_digital = "ALC861 Digital";
+ spec->stream_digital_playback = &alc861_pcm_digital_playback;
+ spec->stream_digital_capture = &alc861_pcm_digital_capture;
+
+ codec->patch_ops = alc_patch_ops;
+ if (board_config == ALC861_AUTO)
+ codec->patch_ops.init = alc861_auto_init;
+
return 0;
}
@@ -2731,7 +4692,11 @@ static int patch_alc882(struct hda_codec *codec)
*/
struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
+ { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
+ { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
+ { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
+ { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 9c7fe0b3200a..8f8840e6002b 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -95,8 +95,8 @@ struct si3054_spec {
#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)
+static int si3054_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -105,8 +105,8 @@ static int si3054_switch_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int si3054_switch_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *uvalue)
+static int si3054_switch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
u16 reg = PRIVATE_REG(kcontrol->private_value);
@@ -115,8 +115,8 @@ static int si3054_switch_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int si3054_switch_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *uvalue)
+static int si3054_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *uvalue)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
u16 reg = PRIVATE_REG(kcontrol->private_value);
@@ -138,7 +138,7 @@ static int si3054_switch_put(snd_kcontrol_t *kcontrol,
}
-static snd_kcontrol_new_t si3054_modem_mixer[] = {
+static struct snd_kcontrol_new 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),
{}
@@ -158,7 +158,7 @@ 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)
+ struct snd_pcm_substream *substream)
{
u16 val;
@@ -175,10 +175,10 @@ static int si3054_pcm_prepare(struct hda_pcm_stream *hinfo,
static int si3054_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
static unsigned int rates[] = { 8000, 9600, 16000 };
- static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -295,6 +295,7 @@ static int patch_si3054(struct hda_codec *codec)
* patch entries
*/
struct hda_codec_preset snd_hda_preset_si3054[] = {
+ { .id = 0x163c3055, .name = "Si3054", .patch = patch_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 33a8adaea768..61903848cd43 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4,7 +4,7 @@
* HD audio interface patch for SigmaTel STAC92xx
*
* Copyright (c) 2005 Embedded Alley Solutions, Inc.
- * <matt@embeddedalley.com>
+ * Matt Porter <mporter@embeddedalley.com>
*
* Based on patch_cmedia.c and patch_realtek.c
* Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
@@ -34,17 +34,22 @@
#include "hda_codec.h"
#include "hda_local.h"
-#undef STAC_TEST
-
#define NUM_CONTROL_ALLOC 32
#define STAC_HP_EVENT 0x37
#define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT)
+#define STAC_REF 0
+#define STAC_D945GTP3 1
+#define STAC_D945GTP5 2
+
struct sigmatel_spec {
- snd_kcontrol_new_t *mixers[4];
+ struct snd_kcontrol_new *mixers[4];
unsigned int num_mixers;
+ int board_config;
unsigned int surr_switch: 1;
+ unsigned int line_switch: 1;
+ unsigned int mic_switch: 1;
/* playback */
struct hda_multi_out multiout;
@@ -57,31 +62,28 @@ struct sigmatel_spec {
unsigned int num_muxes;
hda_nid_t dig_in_nid;
-#ifdef STAC_TEST
/* pin widgets */
hda_nid_t *pin_nids;
unsigned int num_pins;
unsigned int *pin_configs;
-#endif
/* codec specific stuff */
struct hda_verb *init;
- snd_kcontrol_new_t *mixer;
+ struct snd_kcontrol_new *mixer;
/* capture source */
struct hda_input_mux *input_mux;
unsigned int cur_mux[2];
- /* channel mode */
- unsigned int num_ch_modes;
- unsigned int cur_ch_mode;
+ /* i/o switches */
+ unsigned int io_switch[2];
struct hda_pcm pcm_rec[2]; /* PCM information */
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
unsigned int num_kctl_alloc, num_kctl_used;
- snd_kcontrol_new_t *kctl_alloc;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
};
@@ -105,7 +107,6 @@ static hda_nid_t stac922x_mux_nids[2] = {
0x12, 0x13,
};
-#ifdef STAC_TEST
static hda_nid_t stac9200_pin_nids[8] = {
0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
};
@@ -114,16 +115,15 @@ static hda_nid_t stac922x_pin_nids[10] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x15, 0x1b,
};
-#endif
-static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
return snd_hda_input_mux_info(spec->input_mux, uinfo);
}
-static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac92xx_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
@@ -133,7 +133,7 @@ static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct sigmatel_spec *spec = codec->spec;
@@ -155,50 +155,7 @@ static struct hda_verb stac922x_core_init[] = {
{}
};
-static int stac922x_channel_modes[3] = {2, 6, 8};
-
-static int stac922x_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = spec->num_ch_modes;
- if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
- uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- sprintf(uinfo->value.enumerated.name, "%dch",
- stac922x_channel_modes[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int stac922x_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_ch_mode;
- return 0;
-}
-
-static int stac922x_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct sigmatel_spec *spec = codec->spec;
-
- if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
- ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
- if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
- ! codec->in_resume)
- return 0;
-
- spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
- spec->multiout.max_channels = stac922x_channel_modes[spec->cur_ch_mode];
-
- return 1;
-}
-
-static snd_kcontrol_new_t stac9200_mixer[] = {
+static struct snd_kcontrol_new stac9200_mixer[] = {
HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
{
@@ -216,7 +173,7 @@ static snd_kcontrol_new_t stac9200_mixer[] = {
};
/* This needs to be generated dynamically based on sequence */
-static snd_kcontrol_new_t stac922x_mixer[] = {
+static struct snd_kcontrol_new stac922x_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Source",
@@ -226,22 +183,10 @@ static snd_kcontrol_new_t stac922x_mixer[] = {
.put = stac92xx_mux_enum_put,
},
HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
{ } /* end */
};
-static snd_kcontrol_new_t stac922x_ch_mode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = stac922x_ch_mode_info,
- .get = stac922x_ch_mode_get,
- .put = stac922x_ch_mode_put,
- },
- { } /* end */
-};
-
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -258,11 +203,6 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
- if (spec->surr_switch) {
- err = snd_hda_add_new_ctls(codec, stac922x_ch_mode_mixer);
- if (err < 0)
- return err;
- }
if (spec->multiout.dig_out_nid) {
err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
if (err < 0)
@@ -276,18 +216,67 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return 0;
}
-#ifdef STAC_TEST
-static unsigned int stac9200_pin_configs[8] = {
+static unsigned int ref9200_pin_configs[8] = {
0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
};
-static unsigned int stac922x_pin_configs[10] = {
- 0x01014010, 0x01014011, 0x01014012, 0x0221401f,
- 0x01813122, 0x01014014, 0x01441030, 0x01c41030,
+static unsigned int *stac9200_brd_tbl[] = {
+ ref9200_pin_configs,
+};
+
+static struct hda_board_config stac9200_cfg_tbl[] = {
+ { .modelname = "ref",
+ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x2668, /* DFI LanParty */
+ .config = STAC_REF },
+ {} /* terminator */
+};
+
+static unsigned int ref922x_pin_configs[10] = {
+ 0x01014010, 0x01016011, 0x01012012, 0x0221401f,
+ 0x01813122, 0x01011014, 0x01441030, 0x01c41030,
0x40000100, 0x40000100,
};
+static unsigned int d945gtp3_pin_configs[10] = {
+ 0x0221401f, 0x01a19022, 0x01813021, 0x01114010,
+ 0x40000100, 0x40000100, 0x40000100, 0x40000100,
+ 0x02a19120, 0x40000100,
+};
+
+static unsigned int d945gtp5_pin_configs[10] = {
+ 0x0221401f, 0x01111012, 0x01813024, 0x01114010,
+ 0x01a19021, 0x01116011, 0x01452130, 0x40000100,
+ 0x02a19320, 0x40000100,
+};
+
+static unsigned int *stac922x_brd_tbl[] = {
+ ref922x_pin_configs,
+ d945gtp3_pin_configs,
+ d945gtp5_pin_configs,
+};
+
+static struct hda_board_config stac922x_cfg_tbl[] = {
+ { .modelname = "ref",
+ .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x2668, /* DFI LanParty */
+ .config = STAC_REF }, /* SigmaTel reference board */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0101,
+ .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0404,
+ .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0303,
+ .config = STAC_D945GTP5 }, /* Intel D945GNT - 5 Stack */
+ { .pci_subvendor = PCI_VENDOR_ID_INTEL,
+ .pci_subdevice = 0x0013,
+ .config = STAC_D945GTP5 }, /* Intel D955XBK - 5 Stack */
+ {} /* terminator */
+};
+
static void stac92xx_set_config_regs(struct hda_codec *codec)
{
int i;
@@ -310,86 +299,34 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
AC_VERB_GET_CONFIG_DEFAULT,
0x00);
- printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
+ snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
}
}
-#endif
/*
* Analog playback callbacks
*/
static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
}
-/*
- * set up the i/o for analog out
- * when the digital out is available, copy the front out to digital out, too.
- */
-static int stac92xx_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- hda_nid_t *nids = mout->dac_nids;
- int chs = substream->runtime->channels;
- int i;
-
- down(&codec->spdif_mutex);
- if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
- if (chs == 2 &&
- snd_hda_is_supported_format(codec, mout->dig_out_nid, format) &&
- ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) {
- mout->dig_out_used = HDA_DIG_ANALOG_DUP;
- /* setup digital receiver */
- snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
- stream_tag, 0, format);
- } else {
- mout->dig_out_used = 0;
- snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
- }
- }
- up(&codec->spdif_mutex);
-
- /* front */
- snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
- if (mout->hp_nid)
- /* headphone out will just decode front left/right (stereo) */
- snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
- /* surrounds */
- if (mout->max_channels > 2)
- for (i = 1; i < mout->num_dacs; i++) {
- if ((mout->max_channels == 6) && (i == 3))
- break;
- if (chs >= (i + 1) * 2) /* independent out */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
- format);
- else /* copy front */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
- format);
- }
- return 0;
-}
-
-
static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
- return stac92xx_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
- format, substream);
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream);
}
static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
@@ -400,7 +337,7 @@ static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
*/
static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
@@ -408,7 +345,7 @@ static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
@@ -422,7 +359,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
@@ -433,7 +370,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+ struct snd_pcm_substream *substream)
{
struct sigmatel_spec *spec = codec->spec;
@@ -511,20 +448,76 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
return 0;
}
+static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
+
+{
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+}
+
+static int stac92xx_io_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int stac92xx_io_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ int io_idx = kcontrol-> private_value & 0xff;
+
+ ucontrol->value.integer.value[0] = spec->io_switch[io_idx];
+ return 0;
+}
+
+static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t nid = kcontrol->private_value >> 8;
+ int io_idx = kcontrol-> private_value & 0xff;
+ unsigned short val = ucontrol->value.integer.value[0];
+
+ spec->io_switch[io_idx] = val;
+
+ if (val)
+ stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ else
+ stac92xx_auto_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+
+ return 1;
+}
+
+#define STAC_CODEC_IO_SWITCH(xname, xpval) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .index = 0, \
+ .info = stac92xx_io_switch_info, \
+ .get = stac92xx_io_switch_get, \
+ .put = stac92xx_io_switch_put, \
+ .private_value = xpval, \
+ }
+
+
enum {
STAC_CTL_WIDGET_VOL,
STAC_CTL_WIDGET_MUTE,
+ STAC_CTL_WIDGET_IO_SWITCH,
};
-static snd_kcontrol_new_t stac92xx_control_templates[] = {
+static struct snd_kcontrol_new stac92xx_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ STAC_CODEC_IO_SWITCH(NULL, 0),
};
/* add dynamic controls */
static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char *name, unsigned long val)
{
- snd_kcontrol_new_t *knew;
+ struct snd_kcontrol_new *knew;
if (spec->num_kctl_used >= spec->num_kctl_alloc) {
int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
@@ -550,6 +543,51 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char
return 0;
}
+/* flag inputs as additional dynamic lineouts */
+static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ switch (cfg->line_outs) {
+ case 3:
+ /* add line-in as side */
+ if (cfg->input_pins[AUTO_PIN_LINE]) {
+ cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE];
+ spec->line_switch = 1;
+ cfg->line_outs++;
+ }
+ break;
+ case 2:
+ /* add line-in as clfe and mic as side */
+ if (cfg->input_pins[AUTO_PIN_LINE]) {
+ cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE];
+ spec->line_switch = 1;
+ cfg->line_outs++;
+ }
+ if (cfg->input_pins[AUTO_PIN_MIC]) {
+ cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC];
+ spec->mic_switch = 1;
+ cfg->line_outs++;
+ }
+ break;
+ case 1:
+ /* add line-in as surr and mic as clfe */
+ if (cfg->input_pins[AUTO_PIN_LINE]) {
+ cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE];
+ spec->line_switch = 1;
+ cfg->line_outs++;
+ }
+ if (cfg->input_pins[AUTO_PIN_MIC]) {
+ cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC];
+ spec->mic_switch = 1;
+ cfg->line_outs++;
+ }
+ break;
+ }
+
+ return 0;
+}
+
/* fill in the dac_nids table from the parsed pin configuration */
static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
{
@@ -578,7 +616,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const
int i, err;
for (i = 0; i < cfg->line_outs; i++) {
- if (! spec->multiout.dac_nids[i])
+ if (!spec->multiout.dac_nids[i])
continue;
nid = spec->multiout.dac_nids[i];
@@ -609,6 +647,14 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const
}
}
+ if (spec->line_switch)
+ if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Line In as Output Switch", cfg->input_pins[AUTO_PIN_LINE] << 8)) < 0)
+ return err;
+
+ if (spec->mic_switch)
+ if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, "Mic as Output Switch", (cfg->input_pins[AUTO_PIN_MIC] << 8) | 1)) < 0)
+ return err;
+
return 0;
}
@@ -624,7 +670,7 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin
if (! pin)
return 0;
- wid_caps = snd_hda_param_read(codec, pin, AC_PAR_AUDIO_WIDGET_CAP);
+ wid_caps = get_wcaps(codec, pin);
if (wid_caps & AC_WCAP_UNSOL_CAP)
/* Enable unsolicited responses on the HP widget */
snd_hda_codec_write(codec, pin, 0,
@@ -656,9 +702,6 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin
static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
{
struct sigmatel_spec *spec = codec->spec;
- static char *labels[AUTO_PIN_LAST] = {
- "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
- };
struct hda_input_mux *imux = &spec->private_imux;
hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
int i, j, k;
@@ -666,7 +709,10 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
for (i = 0; i < AUTO_PIN_LAST; i++) {
int index = -1;
if (cfg->input_pins[i]) {
- imux->items[imux->num_items].label = labels[i];
+ /* Enable active pin widget as an input */
+ stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], AC_PINCTL_IN_EN);
+
+ imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
for (j=0; j<spec->num_muxes; j++) {
int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS);
@@ -686,12 +732,6 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
return 0;
}
-static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
-
-{
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-}
-
static void stac92xx_auto_init_multi_out(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -718,7 +758,9 @@ static int stac922x_parse_auto_config(struct hda_codec *codec)
struct sigmatel_spec *spec = codec->spec;
int err;
- if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
+ return err;
+ if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0)
return err;
if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0)
return err;
@@ -731,15 +773,8 @@ static int stac922x_parse_auto_config(struct hda_codec *codec)
return err;
spec->multiout.max_channels = spec->multiout.num_dacs * 2;
- if (spec->multiout.max_channels > 2) {
+ if (spec->multiout.max_channels > 2)
spec->surr_switch = 1;
- spec->cur_ch_mode = 1;
- spec->num_ch_modes = 2;
- if (spec->multiout.max_channels == 8) {
- spec->cur_ch_mode++;
- spec->num_ch_modes++;
- }
- }
if (spec->autocfg.dig_out_pin) {
spec->multiout.dig_out_nid = 0x08;
@@ -763,7 +798,7 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
struct sigmatel_spec *spec = codec->spec;
int err;
- if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0)
return err;
if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
@@ -786,33 +821,10 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
return 1;
}
-static int stac92xx_init_pstate(struct hda_codec *codec)
-{
- hda_nid_t nid, nid_start;
- int nodes;
-
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_POWER_STATE, 0x00);
-
- nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
- for (nid = nid_start; nid < nodes + nid_start; nid++) {
- unsigned int wid_caps = snd_hda_param_read(codec, nid,
- AC_PAR_AUDIO_WIDGET_CAP);
- if (wid_caps & AC_WCAP_POWER)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_POWER_STATE, 0x00);
- }
-
- mdelay(100);
-
- return 0;
-}
-
static int stac92xx_init(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- stac92xx_init_pstate(codec);
-
snd_hda_sequence_write(codec, spec->init);
stac92xx_auto_init_multi_out(codec);
@@ -924,13 +936,16 @@ static int patch_stac9200(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
+ spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl);
+ if (spec->board_config < 0)
+ snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
+ else {
+ spec->num_pins = 8;
+ spec->pin_nids = stac9200_pin_nids;
+ spec->pin_configs = stac9200_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
+ }
-#ifdef STAC_TEST
- spec->pin_nids = stac9200_pin_nids;
- spec->num_pins = 8;
- spec->pin_configs = stac9200_pin_configs;
- stac92xx_set_config_regs(codec);
-#endif
spec->multiout.max_channels = 2;
spec->multiout.num_dacs = 1;
spec->multiout.dac_nids = stac9200_dac_nids;
@@ -962,13 +977,16 @@ static int patch_stac922x(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
+ spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl);
+ if (spec->board_config < 0)
+ snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n");
+ else {
+ spec->num_pins = 10;
+ spec->pin_nids = stac922x_pin_nids;
+ spec->pin_configs = stac922x_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
+ }
-#ifdef STAC_TEST
- spec->num_pins = 10;
- spec->pin_nids = stac922x_pin_nids;
- spec->pin_configs = stac922x_pin_configs;
- stac92xx_set_config_regs(codec);
-#endif
spec->adc_nids = stac922x_adc_nids;
spec->mux_nids = stac922x_mux_nids;
spec->num_muxes = 2;
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index ae9dc029ba0d..ab00cce2c39f 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -34,16 +34,16 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
MODULE_LICENSE("GPL");
-static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip)
+static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_save_gpio_status(ice);
}
-static void snd_ice1712_akm4xxx_unlock(akm4xxx_t *ak, int chip)
+static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_restore_gpio_status(ice);
}
@@ -51,14 +51,14 @@ static void snd_ice1712_akm4xxx_unlock(akm4xxx_t *ak, int chip)
/*
* write AK4xxx register
*/
-static void snd_ice1712_akm4xxx_write(akm4xxx_t *ak, int chip,
+static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip,
unsigned char addr, unsigned char data)
{
unsigned int tmp;
int idx;
unsigned int addrdata;
struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_assert(chip >= 0 && chip < 4, return);
@@ -119,10 +119,10 @@ static void snd_ice1712_akm4xxx_write(akm4xxx_t *ak, int chip,
}
/*
- * initialize the akm4xxx_t record with the template
+ * initialize the struct snd_akm4xxx record with the template
*/
-int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp,
- const struct snd_ak4xxx_private *_priv, ice1712_t *ice)
+int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp,
+ const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice)
{
struct snd_ak4xxx_private *priv;
@@ -148,13 +148,13 @@ int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp,
return 0;
}
-void snd_ice1712_akm4xxx_free(ice1712_t *ice)
+void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice)
{
unsigned int akidx;
if (ice->akm == NULL)
return;
for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
- akm4xxx_t *ak = &ice->akm[akidx];
+ struct snd_akm4xxx *ak = &ice->akm[akidx];
kfree((void*)ak->private_value[0]);
}
kfree(ice->akm);
@@ -163,13 +163,13 @@ void snd_ice1712_akm4xxx_free(ice1712_t *ice)
/*
* build AK4xxx controls
*/
-int snd_ice1712_akm4xxx_build_controls(ice1712_t *ice)
+int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice)
{
unsigned int akidx;
int err;
for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
- akm4xxx_t *ak = &ice->akm[akidx];
+ struct snd_akm4xxx *ak = &ice->akm[akidx];
err = snd_akm4xxx_build_controls(ak);
if (err < 0)
return err;
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 289b0b5711e4..59c4078ad331 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -33,14 +33,14 @@
#include "envy24ht.h"
#include "amp.h"
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
{
unsigned short cval;
cval = (reg << 9) | val;
snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
}
-static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
+static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits[] = {
WM_ATTEN_L, 0x0000, /* 0 db */
@@ -66,7 +66,7 @@ static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
return 0;
}
-static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice)
+static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
{
/* we use pins 39 and 41 of the VT1616 for left and right read outputs */
snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000);
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index db12b038286b..8809812a1c22 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -22,7 +22,7 @@
*
* NOTES:
*
- * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
+ * - we reuse the struct snd_akm4xxx record for storing the wm8770 codec data.
* both wm and akm codecs are pretty similar, so we can integrate
* both controls in the future, once if wm codecs are reused in
* many boards.
@@ -85,7 +85,7 @@
#define CS8415_C_BUFFER 0x20
#define CS8415_ID 0x7F
-static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
+static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg, unsigned short val) {
unsigned int tmp;
/* Send address to XILINX chip */
@@ -136,7 +136,7 @@ static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short
ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
}
-static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
+static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
{
return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
}
@@ -144,7 +144,7 @@ static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
/*
* Initialize STAC9744 chip
*/
-static int aureon_ac97_init (ice1712_t *ice) {
+static int aureon_ac97_init (struct snd_ice1712 *ice) {
int i;
static unsigned short ac97_defaults[] = {
0x00, 0x9640,
@@ -196,7 +196,7 @@ static int aureon_ac97_init (ice1712_t *ice) {
/*
* AC'97 volume controls
*/
-static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
@@ -205,9 +205,9 @@ static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return 0;
}
-static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short vol;
down(&ice->gpio_mutex);
@@ -221,9 +221,9 @@ static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change;
@@ -248,9 +248,9 @@ static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
*/
#define aureon_ac97_mute_info aureon_mono_bool_info
-static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
@@ -260,9 +260,9 @@ static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change;
@@ -284,9 +284,9 @@ static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
*/
#define aureon_ac97_micboost_info aureon_mono_bool_info
-static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
@@ -296,9 +296,9 @@ static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return 0;
}
-static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change;
@@ -318,7 +318,7 @@ static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
/*
* write data in the SPI mode
*/
-static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
+static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
{
unsigned int tmp;
int i;
@@ -359,7 +359,7 @@ static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data,
/*
* Read data in SPI mode
*/
-static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
+static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
int i, j;
unsigned int tmp;
@@ -409,26 +409,26 @@ static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data,
snd_ice1712_gpio_write(ice, tmp);
}
-static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) {
+static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
unsigned char val;
aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
return val;
}
-static void aureon_cs8415_read(ice1712_t *ice, int reg, unsigned char *buffer, int size) {
+static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
}
-static void aureon_cs8415_put(ice1712_t *ice, int reg, unsigned char val) {
+static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
}
/*
* get the current register value of WM codec
*/
-static unsigned short wm_get(ice1712_t *ice, int reg)
+static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
{
reg <<= 1;
return ((unsigned short)ice->akm[0].images[reg] << 8) |
@@ -438,7 +438,7 @@ static unsigned short wm_get(ice1712_t *ice, int reg)
/*
* set the register value of WM codec
*/
-static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
{
aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
}
@@ -446,7 +446,7 @@ static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
/*
* set the register value of WM codec and remember it
*/
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
{
wm_put_nocache(ice, reg, val);
reg <<= 1;
@@ -456,7 +456,7 @@ static void wm_put(ice1712_t *ice, int reg, unsigned short val)
/*
*/
-static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int aureon_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -470,9 +470,9 @@ static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
*/
#define aureon_ac97_mmute_info aureon_mono_bool_info
-static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
@@ -482,8 +482,8 @@ static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change;
@@ -521,7 +521,7 @@ static unsigned char wm_vol[256] = {
#define WM_VOL_MAX (sizeof(wm_vol) - 1)
#define WM_VOL_MUTE 0x8000
-static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
{
unsigned char nvol;
@@ -539,9 +539,9 @@ static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, u
*/
#define wm_pcm_mute_info aureon_mono_bool_info
-static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
@@ -549,9 +549,9 @@ static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short nval, oval;
int change;
@@ -568,7 +568,7 @@ static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
/*
* Master volume attenuation mixer control
*/
-static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -577,18 +577,18 @@ static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i;
for (i=0; i<2; i++)
ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
return 0;
}
-static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int ch, change = 0;
snd_ice1712_save_gpio_status(ice);
@@ -611,7 +611,7 @@ static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
/*
* DAC volume attenuation mixer control
*/
-static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int voices = kcontrol->private_value >> 8;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -621,9 +621,9 @@ static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, ofs, voices;
voices = kcontrol->private_value >> 8;
@@ -633,9 +633,9 @@ static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
return 0;
}
-static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, idx, ofs, voices;
int change = 0;
@@ -659,7 +659,7 @@ static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
/*
* WM8770 mute control
*/
-static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = kcontrol->private_value >> 8;
uinfo->value.integer.min = 0;
@@ -667,9 +667,9 @@ static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
return 0;
}
-static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int voices, ofs, i;
voices = kcontrol->private_value >> 8;
@@ -680,9 +680,9 @@ static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
return 0;
}
-static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, voices, ofs, i;
voices = kcontrol->private_value >> 8;
@@ -708,7 +708,7 @@ static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
/*
* WM8770 master mute control
*/
-static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
uinfo->value.integer.min = 0;
@@ -716,18 +716,18 @@ static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
return 0;
}
-static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
return 0;
}
-static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, i;
snd_ice1712_save_gpio_status(ice);
@@ -754,7 +754,7 @@ static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
#define PCM_0dB 0xff
#define PCM_RES 128 /* -64dB */
#define PCM_MIN (PCM_0dB - PCM_RES)
-static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -763,9 +763,9 @@ static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
down(&ice->gpio_mutex);
@@ -776,9 +776,9 @@ static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change = 0;
@@ -798,7 +798,7 @@ static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
/*
* ADC mute control
*/
-static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -807,9 +807,9 @@ static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
return 0;
}
-static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
int i;
@@ -822,9 +822,9 @@ static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short new, old;
int i, change = 0;
@@ -845,7 +845,7 @@ static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
/*
* ADC gain mixer control
*/
-static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -854,9 +854,9 @@ static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, idx;
unsigned short vol;
@@ -870,9 +870,9 @@ static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, idx;
unsigned short ovol, nvol;
int change = 0;
@@ -894,7 +894,7 @@ static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
/*
* ADC input mux mixer control
*/
-static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"CD", //AIN1
@@ -913,7 +913,7 @@ static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
"Aux3", //AIN7
"AC97" //AIN8
};
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 2;
@@ -932,9 +932,9 @@ static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
down(&ice->gpio_mutex);
@@ -945,9 +945,9 @@ static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short oval, nval;
int change;
@@ -966,9 +966,9 @@ static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont
/*
* CS8415 Input mux
*/
-static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
static char *aureon_texts[] = {
"CD", //RXP0
"Optical" //RXP1
@@ -989,9 +989,9 @@ static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
//snd_ice1712_save_gpio_status(ice);
//val = aureon_cs8415_get(ice, CS8415_CTRL2);
@@ -1000,9 +1000,9 @@ static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short oval, nval;
int change;
@@ -1018,7 +1018,7 @@ static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static int aureon_cs8415_rate_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -1027,9 +1027,9 @@ static int aureon_cs8415_rate_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char ratio;
ratio = aureon_cs8415_get(ice, CS8415_RATIO);
ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
@@ -1039,25 +1039,25 @@ static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
/*
* CS8415A Mute
*/
-static int aureon_cs8415_mute_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int aureon_cs8415_mute_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
return 0;
}
-static int aureon_cs8415_mute_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
snd_ice1712_save_gpio_status(ice);
ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
snd_ice1712_restore_gpio_status(ice);
return 0;
}
-static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char oval, nval;
int change;
snd_ice1712_save_gpio_status(ice);
@@ -1075,14 +1075,14 @@ static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
/*
* CS8415A Q-Sub info
*/
-static int aureon_cs8415_qsub_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
uinfo->count = 10;
return 0;
}
-static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
snd_ice1712_save_gpio_status(ice);
aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
@@ -1091,19 +1091,19 @@ static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int aureon_cs8415_spdif_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int aureon_cs8415_mask_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
+static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
memset(ucontrol->value.iec958.status, 0xFF, 24);
return 0;
}
-static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
snd_ice1712_save_gpio_status(ice);
aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
@@ -1114,7 +1114,7 @@ static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value
/*
* Headphone Amplifier
*/
-static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
+static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
{
unsigned int tmp, tmp2;
@@ -1130,7 +1130,7 @@ static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
return 0;
}
-static int aureon_get_headphone_amp(ice1712_t *ice)
+static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
{
unsigned int tmp = snd_ice1712_gpio_read(ice);
@@ -1139,18 +1139,18 @@ static int aureon_get_headphone_amp(ice1712_t *ice)
#define aureon_hpamp_info aureon_mono_bool_info
-static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
return 0;
}
-static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
}
@@ -1161,16 +1161,16 @@ static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
#define aureon_deemp_info aureon_mono_bool_info
-static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
return 0;
}
-static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int temp, temp2;
temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
if (ucontrol->value.integer.value[0])
@@ -1187,7 +1187,7 @@ static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/*
* ADC Oversampling
*/
-static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "128x", "64x" };
@@ -1202,17 +1202,17 @@ static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinf
return 0;
}
-static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
return 0;
}
-static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int temp, temp2;
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
temp2 = temp = wm_get(ice, WM_MASTER);
@@ -1232,7 +1232,7 @@ static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
* mixers
*/
-static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -1329,7 +1329,7 @@ static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
}
};
-static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
@@ -1389,7 +1389,7 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = {
}
};
-static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 Playback Switch",
@@ -1479,7 +1479,7 @@ static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
}
};
-static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "AC97 Playback Switch",
@@ -1586,7 +1586,7 @@ static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = {
};
-static snd_kcontrol_new_t cs8415_controls[] __devinitdata = {
+static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
@@ -1632,7 +1632,7 @@ static snd_kcontrol_new_t cs8415_controls[] __devinitdata = {
};
-static int __devinit aureon_add_controls(ice1712_t *ice)
+static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
{
unsigned int i, counts;
int err;
@@ -1677,7 +1677,7 @@ static int __devinit aureon_add_controls(ice1712_t *ice)
snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
else {
for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
if (err < 0)
return err;
@@ -1695,7 +1695,7 @@ static int __devinit aureon_add_controls(ice1712_t *ice)
/*
* initialize the chip
*/
-static int __devinit aureon_init(ice1712_t *ice)
+static int __devinit aureon_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits_aureon[] = {
/* These come first to reduce init pop noise */
@@ -1796,7 +1796,7 @@ static int __devinit aureon_init(ice1712_t *ice)
}
/* to remeber the register values of CS8415 */
- ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), 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 576f69d482c9..9a51d34e6817 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -44,7 +44,7 @@
*/
/* send 8 bits */
-static void ap_cs8427_write_byte(ice1712_t *ice, unsigned char data, unsigned char tmp)
+static void ap_cs8427_write_byte(struct snd_ice1712 *ice, unsigned char data, unsigned char tmp)
{
int idx;
@@ -61,7 +61,7 @@ static void ap_cs8427_write_byte(ice1712_t *ice, unsigned char data, unsigned ch
}
/* read 8 bits */
-static unsigned char ap_cs8427_read_byte(ice1712_t *ice, unsigned char tmp)
+static unsigned char ap_cs8427_read_byte(struct snd_ice1712 *ice, unsigned char tmp)
{
unsigned char data = 0;
int idx;
@@ -80,7 +80,7 @@ static unsigned char ap_cs8427_read_byte(ice1712_t *ice, unsigned char tmp)
}
/* assert chip select */
-static unsigned char ap_cs8427_codec_select(ice1712_t *ice)
+static unsigned char ap_cs8427_codec_select(struct snd_ice1712 *ice)
{
unsigned char tmp;
tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
@@ -105,7 +105,7 @@ static unsigned char ap_cs8427_codec_select(ice1712_t *ice)
}
/* deassert chip select */
-static void ap_cs8427_codec_deassert(ice1712_t *ice, unsigned char tmp)
+static void ap_cs8427_codec_deassert(struct snd_ice1712 *ice, unsigned char tmp)
{
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_DELTA1010LT:
@@ -124,9 +124,9 @@ static void ap_cs8427_codec_deassert(ice1712_t *ice, unsigned char tmp)
}
/* sequential write */
-static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+static int ap_cs8427_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
{
- ice1712_t *ice = device->bus->private_data;
+ struct snd_ice1712 *ice = device->bus->private_data;
int res = count;
unsigned char tmp;
@@ -141,9 +141,9 @@ static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, i
}
/* sequential read */
-static int ap_cs8427_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
+static int ap_cs8427_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
{
- ice1712_t *ice = device->bus->private_data;
+ struct snd_ice1712 *ice = device->bus->private_data;
int res = count;
unsigned char tmp;
@@ -157,14 +157,14 @@ static int ap_cs8427_readbytes(snd_i2c_device_t *device, unsigned char *bytes, i
return res;
}
-static int ap_cs8427_probeaddr(snd_i2c_bus_t *bus, unsigned short addr)
+static int ap_cs8427_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
{
if (addr == 0x10)
return 1;
return -ENOENT;
}
-static snd_i2c_ops_t ap_cs8427_i2c_ops = {
+static struct snd_i2c_ops ap_cs8427_i2c_ops = {
.sendbytes = ap_cs8427_sendbytes,
.readbytes = ap_cs8427_readbytes,
.probeaddr = ap_cs8427_probeaddr,
@@ -173,7 +173,7 @@ static snd_i2c_ops_t ap_cs8427_i2c_ops = {
/*
*/
-static void snd_ice1712_delta_cs8403_spdif_write(ice1712_t *ice, unsigned char bits)
+static void snd_ice1712_delta_cs8403_spdif_write(struct snd_ice1712 *ice, unsigned char bits)
{
unsigned char tmp, mask1, mask2;
int idx;
@@ -198,12 +198,12 @@ static void snd_ice1712_delta_cs8403_spdif_write(ice1712_t *ice, unsigned char b
}
-static void delta_spdif_default_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static void delta_spdif_default_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_bits);
}
-static int delta_spdif_default_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static int delta_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
unsigned int val;
int change;
@@ -221,12 +221,12 @@ static int delta_spdif_default_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontr
return change;
}
-static void delta_spdif_stream_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static void delta_spdif_stream_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
snd_cs8403_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_stream_bits);
}
-static int delta_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static int delta_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
unsigned int val;
int change;
@@ -248,10 +248,10 @@ static int delta_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontro
/*
* AK4524 on Delta 44 and 66 to choose the chip mask
*/
-static void delta_ak4524_lock(akm4xxx_t *ak, int chip)
+static void delta_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_save_gpio_status(ice);
priv->cs_mask =
@@ -262,10 +262,10 @@ static void delta_ak4524_lock(akm4xxx_t *ak, int chip)
/*
* AK4524 on Delta1010LT to choose the chip address
*/
-static void delta1010lt_ak4524_lock(akm4xxx_t *ak, int chip)
+static void delta1010lt_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_save_gpio_status(ice);
priv->cs_mask = ICE1712_DELTA_1010LT_CS;
@@ -275,10 +275,10 @@ static void delta1010lt_ak4524_lock(akm4xxx_t *ak, int chip)
/*
* AK4528 on VX442 to choose the chip mask
*/
-static void vx442_ak4524_lock(akm4xxx_t *ak, int chip)
+static void vx442_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_save_gpio_status(ice);
priv->cs_mask =
@@ -289,7 +289,7 @@ static void vx442_ak4524_lock(akm4xxx_t *ak, int chip)
/*
* change the DFS bit according rate for Delta1010
*/
-static void delta_1010_set_rate_val(ice1712_t *ice, unsigned int rate)
+static void delta_1010_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
{
unsigned char tmp, tmp2;
@@ -309,10 +309,10 @@ static void delta_1010_set_rate_val(ice1712_t *ice, unsigned int rate)
/*
* change the rate of AK4524 on Delta 44/66, AP, 1010LT
*/
-static void delta_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+static void delta_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
{
unsigned char tmp, tmp2;
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
if (rate == 0) /* no hint - S/PDIF input is master, simply return */
return;
@@ -341,7 +341,7 @@ static void delta_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate)
/*
* change the rate of AK4524 on VX442
*/
-static void vx442_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+static void vx442_ak4524_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
{
unsigned char val;
@@ -361,13 +361,13 @@ static void vx442_ak4524_set_rate_val(akm4xxx_t *ak, unsigned int rate)
*/
/* open callback */
-static void delta_open_spdif(ice1712_t *ice, snd_pcm_substream_t * substream)
+static void delta_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream *substream)
{
ice->spdif.cs8403_stream_bits = ice->spdif.cs8403_bits;
}
/* set up */
-static void delta_setup_spdif(ice1712_t *ice, int rate)
+static void delta_setup_spdif(struct snd_ice1712 *ice, int rate)
{
unsigned long flags;
unsigned int tmp;
@@ -396,7 +396,7 @@ static void delta_setup_spdif(ice1712_t *ice, int rate)
* initialize the chips on M-Audio cards
*/
-static akm4xxx_t akm_audiophile __devinitdata = {
+static struct snd_akm4xxx akm_audiophile __devinitdata = {
.type = SND_AK4528,
.num_adcs = 2,
.num_dacs = 2,
@@ -417,7 +417,7 @@ static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_delta410 __devinitdata = {
+static struct snd_akm4xxx akm_delta410 __devinitdata = {
.type = SND_AK4529,
.num_adcs = 2,
.num_dacs = 8,
@@ -438,7 +438,7 @@ static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_delta1010lt __devinitdata = {
+static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
.type = SND_AK4524,
.num_adcs = 8,
.num_dacs = 8,
@@ -460,7 +460,7 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_delta44 __devinitdata = {
+static struct snd_akm4xxx akm_delta44 __devinitdata = {
.type = SND_AK4524,
.num_adcs = 4,
.num_dacs = 4,
@@ -482,7 +482,7 @@ static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_vx442 __devinitdata = {
+static struct snd_akm4xxx akm_vx442 __devinitdata = {
.type = SND_AK4524,
.num_adcs = 4,
.num_dacs = 4,
@@ -504,10 +504,10 @@ static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
.mask_flags = 0,
};
-static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
+static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
{
int err;
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
/* determine I2C, DACs and ADCs */
switch (ice->eeprom.subvendor) {
@@ -582,7 +582,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
}
/* second stage of initialization, analog parts and others */
- ak = ice->akm = kmalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -617,19 +617,19 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
* additional controls for M-Audio cards
*/
-static snd_kcontrol_new_t snd_ice1712_delta1010_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
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 =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
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 =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
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 =
+static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
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 =
+static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
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)
+static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
{
int err;
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h
index f7878020eaa3..b58afcda9ed6 100644
--- a/sound/pci/ice1712/envy24ht.h
+++ b/sound/pci/ice1712/envy24ht.h
@@ -209,7 +209,7 @@ enum {
#define VT1724_MT_PDMA1_COUNT 0x76 /* word */
-unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr);
-void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data);
+unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr);
+void snd_vt1724_write_i2c(struct snd_ice1712 *ice, unsigned char dev, unsigned char addr, unsigned char data);
#endif /* __SOUND_VT1724_H */
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index c8ec5cac3c17..2c529e741384 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -50,9 +50,9 @@ enum {
*/
/* send SDA and SCL */
-static void ewx_i2c_setlines(snd_i2c_bus_t *bus, int clk, int data)
+static void ewx_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
unsigned char tmp = 0;
if (clk)
tmp |= ICE1712_EWX2496_SERIAL_CLOCK;
@@ -62,15 +62,15 @@ static void ewx_i2c_setlines(snd_i2c_bus_t *bus, int clk, int data)
udelay(5);
}
-static int ewx_i2c_getclock(snd_i2c_bus_t *bus)
+static int ewx_i2c_getclock(struct snd_i2c_bus *bus)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_EWX2496_SERIAL_CLOCK ? 1 : 0;
}
-static int ewx_i2c_getdata(snd_i2c_bus_t *bus, int ack)
+static int ewx_i2c_getdata(struct snd_i2c_bus *bus, int ack)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
int bit;
/* set RW pin to low */
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~ICE1712_EWX2496_RW);
@@ -85,9 +85,9 @@ static int ewx_i2c_getdata(snd_i2c_bus_t *bus, int ack)
return bit;
}
-static void ewx_i2c_start(snd_i2c_bus_t *bus)
+static void ewx_i2c_start(struct snd_i2c_bus *bus)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
unsigned char mask;
snd_ice1712_save_gpio_status(ice);
@@ -104,15 +104,15 @@ static void ewx_i2c_start(snd_i2c_bus_t *bus)
snd_ice1712_gpio_write_bits(ice, mask, mask);
}
-static void ewx_i2c_stop(snd_i2c_bus_t *bus)
+static void ewx_i2c_stop(struct snd_i2c_bus *bus)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
snd_ice1712_restore_gpio_status(ice);
}
-static void ewx_i2c_direction(snd_i2c_bus_t *bus, int clock, int data)
+static void ewx_i2c_direction(struct snd_i2c_bus *bus, int clock, int data)
{
- ice1712_t *ice = bus->private_data;
+ struct snd_ice1712 *ice = bus->private_data;
unsigned char mask = 0;
if (clock)
@@ -125,7 +125,7 @@ static void ewx_i2c_direction(snd_i2c_bus_t *bus, int clock, int data)
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~mask);
}
-static snd_i2c_bit_ops_t snd_ice1712_ewx_cs8427_bit_ops = {
+static struct snd_i2c_bit_ops snd_ice1712_ewx_cs8427_bit_ops = {
.start = ewx_i2c_start,
.stop = ewx_i2c_stop,
.direction = ewx_i2c_direction,
@@ -140,7 +140,7 @@ static snd_i2c_bit_ops_t snd_ice1712_ewx_cs8427_bit_ops = {
*/
/* AK4524 chip select; address 0x48 bit 0-3 */
-static int snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask)
+static int snd_ice1712_ews88mt_chip_select(struct snd_ice1712 *ice, int chip_mask)
{
unsigned char data, ndata;
@@ -162,9 +162,9 @@ static int snd_ice1712_ews88mt_chip_select(ice1712_t *ice, int chip_mask)
}
/* start callback for EWS88MT, needs to select a certain chip mask */
-static void ews88mt_ak4524_lock(akm4xxx_t *ak, int chip)
+static void ews88mt_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
unsigned char tmp;
/* assert AK4524 CS */
if (snd_ice1712_ews88mt_chip_select(ice, ~(1 << chip) & 0x0f) < 0)
@@ -179,18 +179,18 @@ static void ews88mt_ak4524_lock(akm4xxx_t *ak, int chip)
}
/* stop callback for EWS88MT, needs to deselect chip mask */
-static void ews88mt_ak4524_unlock(akm4xxx_t *ak, int chip)
+static void ews88mt_ak4524_unlock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_ice1712_restore_gpio_status(ice);
udelay(1);
snd_ice1712_ews88mt_chip_select(ice, 0x0f);
}
/* start callback for EWX24/96 */
-static void ewx2496_ak4524_lock(akm4xxx_t *ak, int chip)
+static void ewx2496_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
unsigned char tmp;
snd_ice1712_save_gpio_status(ice);
tmp = ICE1712_EWX2496_SERIAL_DATA |
@@ -203,10 +203,10 @@ static void ewx2496_ak4524_lock(akm4xxx_t *ak, int chip)
}
/* start callback for DMX 6fire */
-static void dmx6fire_ak4524_lock(akm4xxx_t *ak, int chip)
+static void dmx6fire_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
unsigned char tmp;
snd_ice1712_save_gpio_status(ice);
tmp = priv->cs_mask = priv->cs_addr = (1 << chip) & ICE1712_6FIRE_AK4524_CS_MASK;
@@ -222,7 +222,7 @@ static void dmx6fire_ak4524_lock(akm4xxx_t *ak, int chip)
* CS8404 interface on EWS88MT/D
*/
-static void snd_ice1712_ews_cs8404_spdif_write(ice1712_t *ice, unsigned char bits)
+static void snd_ice1712_ews_cs8404_spdif_write(struct snd_ice1712 *ice, unsigned char bits)
{
unsigned char bytes[2];
@@ -251,12 +251,12 @@ static void snd_ice1712_ews_cs8404_spdif_write(ice1712_t *ice, unsigned char bit
/*
*/
-static void ews88_spdif_default_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static void ews88_spdif_default_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
snd_cs8404_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_bits);
}
-static int ews88_spdif_default_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static int ews88_spdif_default_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
unsigned int val;
int change;
@@ -274,12 +274,12 @@ static int ews88_spdif_default_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontr
return change;
}
-static void ews88_spdif_stream_get(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static void ews88_spdif_stream_get(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
snd_cs8404_decode_spdif_bits(&ucontrol->value.iec958, ice->spdif.cs8403_stream_bits);
}
-static int ews88_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontrol)
+static int ews88_spdif_stream_put(struct snd_ice1712 *ice, struct snd_ctl_elem_value *ucontrol)
{
unsigned int val;
int change;
@@ -299,13 +299,13 @@ static int ews88_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontro
/* open callback */
-static void ews88_open_spdif(ice1712_t *ice, snd_pcm_substream_t * substream)
+static void ews88_open_spdif(struct snd_ice1712 *ice, struct snd_pcm_substream *substream)
{
ice->spdif.cs8403_stream_bits = ice->spdif.cs8403_bits;
}
/* set up SPDIF for EWS88MT / EWS88D */
-static void ews88_setup_spdif(ice1712_t *ice, int rate)
+static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
{
unsigned long flags;
unsigned char tmp;
@@ -332,7 +332,7 @@ static void ews88_setup_spdif(ice1712_t *ice, int rate)
/*
*/
-static akm4xxx_t akm_ews88mt __devinitdata = {
+static struct snd_akm4xxx akm_ews88mt __devinitdata = {
.num_adcs = 8,
.num_dacs = 8,
.type = SND_AK4524,
@@ -354,7 +354,7 @@ static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_ewx2496 __devinitdata = {
+static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
.num_adcs = 2,
.num_dacs = 2,
.type = SND_AK4524,
@@ -375,7 +375,7 @@ static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_6fire __devinitdata = {
+static struct snd_akm4xxx akm_6fire __devinitdata = {
.num_adcs = 6,
.num_dacs = 6,
.type = SND_AK4524,
@@ -406,12 +406,12 @@ static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
#define PCF9554_REG_POLARITY 2
#define PCF9554_REG_CONFIG 3
-static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char reg, unsigned char data);
+static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data);
-static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
+static int __devinit snd_ice1712_ews_init(struct snd_ice1712 *ice)
{
int err;
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
/* set the analog DACs */
switch (ice->eeprom.subvendor) {
@@ -507,7 +507,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
}
/* analog section */
- ak = ice->akm = kmalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -536,7 +536,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
*/
/* i/o sensitivity - this callback is shared among other devices, too */
-static int snd_ice1712_ewx_io_sense_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){
+static int snd_ice1712_ewx_io_sense_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){
static char *texts[2] = {
"+4dBu", "-10dBV",
@@ -550,9 +550,9 @@ static int snd_ice1712_ewx_io_sense_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ice1712_ewx_io_sense_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_ewx_io_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
snd_ice1712_save_gpio_status(ice);
@@ -561,9 +561,9 @@ static int snd_ice1712_ewx_io_sense_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ice1712_ewx_io_sense_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
int val, nval;
@@ -578,7 +578,7 @@ static int snd_ice1712_ewx_io_sense_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return val != nval;
}
-static snd_kcontrol_new_t snd_ice1712_ewx2496_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Sensitivity Switch",
@@ -602,9 +602,9 @@ static snd_kcontrol_new_t snd_ice1712_ewx2496_controls[] __devinitdata = {
* EWS88MT specific controls
*/
/* analog output sensitivity;; address 0x48 bit 6 */
-static int snd_ice1712_ews88mt_output_sense_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_ews88mt_output_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char data;
snd_i2c_lock(ice->i2c);
@@ -618,9 +618,9 @@ static int snd_ice1712_ews88mt_output_sense_get(snd_kcontrol_t *kcontrol, snd_ct
}
/* analog output sensitivity;; address 0x48 bit 6 */
-static int snd_ice1712_ews88mt_output_sense_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_ews88mt_output_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char data, ndata;
snd_i2c_lock(ice->i2c);
@@ -638,9 +638,9 @@ static int snd_ice1712_ews88mt_output_sense_put(snd_kcontrol_t *kcontrol, snd_ct
}
/* analog input sensitivity; address 0x46 */
-static int snd_ice1712_ews88mt_input_sense_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_ews88mt_input_sense_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned char data;
@@ -657,9 +657,9 @@ static int snd_ice1712_ews88mt_input_sense_get(snd_kcontrol_t *kcontrol, snd_ctl
}
/* analog output sensitivity; address 0x46 */
-static int snd_ice1712_ews88mt_input_sense_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int channel = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned char data, ndata;
@@ -678,7 +678,7 @@ static int snd_ice1712_ews88mt_input_sense_put(snd_kcontrol_t *kcontrol, snd_ctl
return ndata != data;
}
-static snd_kcontrol_new_t snd_ice1712_ews88mt_input_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Sensitivity Switch",
.info = snd_ice1712_ewx_io_sense_info,
@@ -687,7 +687,7 @@ static snd_kcontrol_new_t snd_ice1712_ews88mt_input_sense __devinitdata = {
.count = 8,
};
-static snd_kcontrol_new_t snd_ice1712_ews88mt_output_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Output Sensitivity Switch",
.info = snd_ice1712_ewx_io_sense_info,
@@ -700,7 +700,7 @@ static snd_kcontrol_new_t snd_ice1712_ews88mt_output_sense __devinitdata = {
* EWS88D specific controls
*/
-static int snd_ice1712_ews88d_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ice1712_ews88d_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -709,9 +709,9 @@ static int snd_ice1712_ews88d_control_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_ice1712_ews88d_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_ews88d_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
unsigned char data[2];
@@ -729,9 +729,9 @@ static int snd_ice1712_ews88d_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
unsigned char data[2], ndata[2];
@@ -769,7 +769,7 @@ static int snd_ice1712_ews88d_control_put(snd_kcontrol_t * kcontrol, snd_ctl_ele
.private_value = xshift | (xinvert << 8),\
}
-static snd_kcontrol_new_t snd_ice1712_ews88d_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -782,7 +782,7 @@ static snd_kcontrol_new_t snd_ice1712_ews88d_controls[] __devinitdata = {
* DMX 6Fire specific controls
*/
-static int snd_ice1712_6fire_read_pca(ice1712_t *ice, unsigned char reg)
+static int snd_ice1712_6fire_read_pca(struct snd_ice1712 *ice, unsigned char reg)
{
unsigned char byte;
snd_i2c_lock(ice->i2c);
@@ -798,7 +798,7 @@ static int snd_ice1712_6fire_read_pca(ice1712_t *ice, unsigned char reg)
return byte;
}
-static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char reg, unsigned char data)
+static int snd_ice1712_6fire_write_pca(struct snd_ice1712 *ice, unsigned char reg, unsigned char data)
{
unsigned char bytes[2];
snd_i2c_lock(ice->i2c);
@@ -812,7 +812,7 @@ static int snd_ice1712_6fire_write_pca(ice1712_t *ice, unsigned char reg, unsign
return 0;
}
-static int snd_ice1712_6fire_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ice1712_6fire_control_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -821,9 +821,9 @@ static int snd_ice1712_6fire_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_ice1712_6fire_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_6fire_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
int data;
@@ -837,9 +837,9 @@ static int snd_ice1712_6fire_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ice1712_6fire_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_6fire_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value >> 8) & 1;
int data, ndata;
@@ -858,7 +858,7 @@ static int snd_ice1712_6fire_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_ice1712_6fire_select_input_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ice1712_6fire_select_input_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Internal", "Front Input", "Rear Input", "Wave Table"
@@ -872,9 +872,9 @@ static int snd_ice1712_6fire_select_input_info(snd_kcontrol_t *kcontrol, snd_ctl
return 0;
}
-static int snd_ice1712_6fire_select_input_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_6fire_select_input_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int data;
if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0)
@@ -883,9 +883,9 @@ static int snd_ice1712_6fire_select_input_get(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_ice1712_6fire_select_input_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int data, ndata;
if ((data = snd_ice1712_6fire_read_pca(ice, PCF9554_REG_OUTPUT)) < 0)
@@ -909,7 +909,7 @@ static int snd_ice1712_6fire_select_input_put(snd_kcontrol_t *kcontrol, snd_ctl_
.private_value = xshift | (xinvert << 8),\
}
-static snd_kcontrol_new_t snd_ice1712_6fire_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Analog Input Select",
@@ -917,7 +917,7 @@ static snd_kcontrol_new_t snd_ice1712_6fire_controls[] __devinitdata = {
.get = snd_ice1712_6fire_select_input_get,
.put = snd_ice1712_6fire_select_input_put,
},
- DMX6FIRE_CONTROL("Front Digital Input Switch", 2, 0),
+ DMX6FIRE_CONTROL("Front Digital Input Switch", 2, 1),
// DMX6FIRE_CONTROL("Master Clock Select", 3, 0),
DMX6FIRE_CONTROL("Optical Digital Input Switch", 4, 0),
DMX6FIRE_CONTROL("Phono Analog Input Switch", 5, 0),
@@ -925,7 +925,7 @@ static snd_kcontrol_new_t snd_ice1712_6fire_controls[] __devinitdata = {
};
-static int __devinit snd_ice1712_ews_add_controls(ice1712_t *ice)
+static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
{
unsigned int idx;
int err;
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index ab5fbd0bdfad..3f2f918536f5 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -33,7 +33,7 @@
#include "hoontech.h"
-static void __devinit snd_ice1712_stdsp24_gpio_write(ice1712_t *ice, unsigned char byte)
+static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
{
byte |= ICE1712_STDSP24_CLOCK_BIT;
udelay(100);
@@ -46,7 +46,7 @@ static void __devinit snd_ice1712_stdsp24_gpio_write(ice1712_t *ice, unsigned ch
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
}
-static void __devinit snd_ice1712_stdsp24_darear(ice1712_t *ice, int activate)
+static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
{
down(&ice->gpio_mutex);
ICE1712_STDSP24_0_DAREAR(ice->spec.hoontech.boxbits, activate);
@@ -54,7 +54,7 @@ static void __devinit snd_ice1712_stdsp24_darear(ice1712_t *ice, int activate)
up(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_mute(ice1712_t *ice, int activate)
+static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
{
down(&ice->gpio_mutex);
ICE1712_STDSP24_3_MUTE(ice->spec.hoontech.boxbits, activate);
@@ -62,7 +62,7 @@ static void __devinit snd_ice1712_stdsp24_mute(ice1712_t *ice, int activate)
up(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_insel(ice1712_t *ice, int activate)
+static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
{
down(&ice->gpio_mutex);
ICE1712_STDSP24_3_INSEL(ice->spec.hoontech.boxbits, activate);
@@ -70,7 +70,7 @@ static void __devinit snd_ice1712_stdsp24_insel(ice1712_t *ice, int activate)
up(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_box_channel(ice1712_t *ice, int box, int chn, int activate)
+static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
{
down(&ice->gpio_mutex);
@@ -118,7 +118,7 @@ static void __devinit snd_ice1712_stdsp24_box_channel(ice1712_t *ice, int box, i
up(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_box_midi(ice1712_t *ice, int box, int master)
+static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
{
down(&ice->gpio_mutex);
@@ -144,7 +144,7 @@ static void __devinit snd_ice1712_stdsp24_box_midi(ice1712_t *ice, int box, int
up(&ice->gpio_mutex);
}
-static void __devinit snd_ice1712_stdsp24_midi2(ice1712_t *ice, int activate)
+static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
{
down(&ice->gpio_mutex);
ICE1712_STDSP24_3_MIDI2(ice->spec.hoontech.boxbits, activate);
@@ -152,7 +152,7 @@ static void __devinit snd_ice1712_stdsp24_midi2(ice1712_t *ice, int activate)
up(&ice->gpio_mutex);
}
-static int __devinit snd_ice1712_hoontech_init(ice1712_t *ice)
+static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
{
int box, chn;
@@ -221,9 +221,9 @@ static int __devinit snd_ice1712_hoontech_init(ice1712_t *ice)
*/
/* start callback for STDSP24 with modified hardware */
-static void stdsp24_ak4524_lock(akm4xxx_t *ak, int chip)
+static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
unsigned char tmp;
snd_ice1712_save_gpio_status(ice);
tmp = ICE1712_STDSP24_SERIAL_DATA |
@@ -234,10 +234,10 @@ static void stdsp24_ak4524_lock(akm4xxx_t *ak, int chip)
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
}
-static int __devinit snd_ice1712_value_init(ice1712_t *ice)
+static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
{
/* Hoontech STDSP24 with modified hardware */
- static akm4xxx_t akm_stdsp24_mv __devinitdata = {
+ static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
.num_adcs = 2,
.num_dacs = 2,
.type = SND_AK4524,
@@ -258,7 +258,7 @@ static int __devinit snd_ice1712_value_init(ice1712_t *ice)
};
int err;
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
/* set the analog DACs */
ice->num_total_dacs = 2;
@@ -267,7 +267,7 @@ static int __devinit snd_ice1712_value_init(ice1712_t *ice)
ice->num_total_adcs = 2;
/* analog section */
- ak = ice->akm = kmalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -284,7 +284,7 @@ static int __devinit snd_ice1712_value_init(ice1712_t *ice)
return 0;
}
-static int __devinit snd_ice1712_ez8_init(ice1712_t *ice)
+static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
{
ice->gpio.write_mask = ice->eeprom.gpiomask;
ice->gpio.direction = ice->eeprom.gpiodir;
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index bd71bf424549..ef6f18558c95 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -108,8 +108,8 @@ static struct pci_device_id snd_ice1712_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_ice1712_ids);
-static int snd_ice1712_build_pro_mixer(ice1712_t *ice);
-static int snd_ice1712_build_controls(ice1712_t *ice);
+static int snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice);
+static int snd_ice1712_build_controls(struct snd_ice1712 *ice);
static int PRO_RATE_LOCKED;
static int PRO_RATE_RESET = 1;
@@ -120,33 +120,33 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
*/
/* check whether the clock mode is spdif-in */
-static inline int is_spdif_master(ice1712_t *ice)
+static inline int is_spdif_master(struct snd_ice1712 *ice)
{
return (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER) ? 1 : 0;
}
-static inline int is_pro_rate_locked(ice1712_t *ice)
+static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
{
return is_spdif_master(ice) || PRO_RATE_LOCKED;
}
-static inline void snd_ice1712_ds_write(ice1712_t * ice, u8 channel, u8 addr, u32 data)
+static inline void snd_ice1712_ds_write(struct snd_ice1712 * ice, u8 channel, u8 addr, u32 data)
{
outb((channel << 4) | addr, ICEDS(ice, INDEX));
outl(data, ICEDS(ice, DATA));
}
-static inline u32 snd_ice1712_ds_read(ice1712_t * ice, u8 channel, u8 addr)
+static inline u32 snd_ice1712_ds_read(struct snd_ice1712 * ice, u8 channel, u8 addr)
{
outb((channel << 4) | addr, ICEDS(ice, INDEX));
return inl(ICEDS(ice, DATA));
}
-static void snd_ice1712_ac97_write(ac97_t *ac97,
+static void snd_ice1712_ac97_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
int tm;
unsigned char old_cmd = 0;
@@ -167,10 +167,10 @@ static void snd_ice1712_ac97_write(ac97_t *ac97,
break;
}
-static unsigned short snd_ice1712_ac97_read(ac97_t *ac97,
+static unsigned short snd_ice1712_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
int tm;
unsigned char old_cmd = 0;
@@ -196,11 +196,11 @@ static unsigned short snd_ice1712_ac97_read(ac97_t *ac97,
* pro ac97 section
*/
-static void snd_ice1712_pro_ac97_write(ac97_t *ac97,
+static void snd_ice1712_pro_ac97_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
int tm;
unsigned char old_cmd = 0;
@@ -222,10 +222,10 @@ static void snd_ice1712_pro_ac97_write(ac97_t *ac97,
}
-static unsigned short snd_ice1712_pro_ac97_read(ac97_t *ac97,
+static unsigned short snd_ice1712_pro_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
int tm;
unsigned char old_cmd = 0;
@@ -250,7 +250,7 @@ static unsigned short snd_ice1712_pro_ac97_read(ac97_t *ac97,
/*
* consumer ac97 digital mix
*/
-static int snd_ice1712_digmix_route_ac97_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ice1712_digmix_route_ac97_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -259,17 +259,17 @@ static int snd_ice1712_digmix_route_ac97_info(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_ice1712_digmix_route_ac97_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_digmix_route_ac97_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = inb(ICEMT(ice, MONITOR_ROUTECTRL)) & ICE1712_ROUTE_AC97 ? 1 : 0;
return 0;
}
-static int snd_ice1712_digmix_route_ac97_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char val, nval;
spin_lock_irq(&ice->reg_lock);
@@ -281,7 +281,7 @@ static int snd_ice1712_digmix_route_ac97_put(snd_kcontrol_t *kcontrol, snd_ctl_e
return val != nval;
}
-static snd_kcontrol_new_t snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Digital Mixer To AC97",
.info = snd_ice1712_digmix_route_ac97_info,
@@ -293,24 +293,24 @@ static snd_kcontrol_new_t snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
/*
* gpio operations
*/
-static void snd_ice1712_set_gpio_dir(ice1712_t *ice, unsigned int data)
+static void snd_ice1712_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)
{
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, data);
inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
}
-static void snd_ice1712_set_gpio_mask(ice1712_t *ice, unsigned int data)
+static void snd_ice1712_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
{
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, data);
inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
}
-static unsigned int snd_ice1712_get_gpio_data(ice1712_t *ice)
+static unsigned int snd_ice1712_get_gpio_data(struct snd_ice1712 *ice)
{
return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
}
-static void snd_ice1712_set_gpio_data(ice1712_t *ice, unsigned int val)
+static void snd_ice1712_set_gpio_data(struct snd_ice1712 *ice, unsigned int val)
{
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, val);
inb(ICEREG(ice, DATA)); /* dummy read for pci-posting */
@@ -327,7 +327,7 @@ static void snd_ice1712_set_gpio_data(ice1712_t *ice, unsigned int val)
* change the input clock selection
* spdif_clock = 1 - IEC958 input, 0 - Envy24
*/
-static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
+static int snd_ice1712_cs8427_set_input_clock(struct snd_ice1712 *ice, int spdif_clock)
{
unsigned char reg[2] = { 0x80 | 4, 0 }; /* CS8427 auto increment | register number 4 + data */
unsigned char val, nval;
@@ -362,17 +362,17 @@ static int snd_ice1712_cs8427_set_input_clock(ice1712_t *ice, int spdif_clock)
/*
* spdif callbacks
*/
-static void open_cs8427(ice1712_t *ice, snd_pcm_substream_t * substream)
+static void open_cs8427(struct snd_ice1712 *ice, struct snd_pcm_substream *substream)
{
snd_cs8427_iec958_active(ice->cs8427, 1);
}
-static void close_cs8427(ice1712_t *ice, snd_pcm_substream_t * substream)
+static void close_cs8427(struct snd_ice1712 *ice, struct snd_pcm_substream *substream)
{
snd_cs8427_iec958_active(ice->cs8427, 0);
}
-static void setup_cs8427(ice1712_t *ice, int rate)
+static void setup_cs8427(struct snd_ice1712 *ice, int rate)
{
snd_cs8427_iec958_pcm(ice->cs8427, rate);
}
@@ -380,7 +380,7 @@ static void setup_cs8427(ice1712_t *ice, int rate)
/*
* create and initialize callbacks for cs8427 interface
*/
-int __devinit snd_ice1712_init_cs8427(ice1712_t *ice, int addr)
+int __devinit snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr)
{
int err;
@@ -403,7 +403,7 @@ int __devinit snd_ice1712_init_cs8427(ice1712_t *ice, int addr)
static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ice1712_t *ice = dev_id;
+ struct snd_ice1712 *ice = dev_id;
unsigned char status;
int handled = 0;
@@ -444,7 +444,7 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *
if (status & ICE1712_IRQ_PBKDS) {
u32 idx;
u16 pbkstatus;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
pbkstatus = inw(ICEDS(ice, INTSTAT));
//printk("pbkstatus = 0x%x\n", pbkstatus);
for (idx = 0; idx < 6; idx++) {
@@ -475,13 +475,13 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *
* PCM part - misc
*/
-static int snd_ice1712_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ice1712_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ice1712_hw_free(snd_pcm_substream_t * substream)
+static int snd_ice1712_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
@@ -490,10 +490,10 @@ static int snd_ice1712_hw_free(snd_pcm_substream_t * substream)
* PCM part - consumer I/O
*/
-static int snd_ice1712_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_ice1712_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int result = 0;
u32 tmp;
@@ -515,10 +515,10 @@ static int snd_ice1712_playback_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_ice1712_playback_ds_trigger(snd_pcm_substream_t * substream,
+static int snd_ice1712_playback_ds_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int result = 0;
u32 tmp;
@@ -540,10 +540,10 @@ static int snd_ice1712_playback_ds_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_ice1712_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_ice1712_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int result = 0;
u8 tmp;
@@ -561,10 +561,10 @@ static int snd_ice1712_capture_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
u32 period_size, buf_size, rate, tmp;
period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1;
@@ -594,10 +594,10 @@ static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_ds_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
u32 period_size, buf_size, rate, tmp, chn;
period_size = snd_pcm_lib_period_bytes(substream) - 1;
@@ -629,10 +629,10 @@ static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
u32 period_size, buf_size;
u8 tmp;
@@ -654,10 +654,10 @@ static int snd_ice1712_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_ice1712_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ice1712_playback_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
size_t ptr;
if (!(snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL) & 1))
@@ -668,9 +668,9 @@ static snd_pcm_uframes_t snd_ice1712_playback_pointer(snd_pcm_substream_t * subs
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
u8 addr;
size_t ptr;
@@ -687,9 +687,9 @@ static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(snd_pcm_substream_t * s
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_ice1712_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ice1712_capture_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL) & 1))
@@ -700,7 +700,7 @@ static snd_pcm_uframes_t snd_ice1712_capture_pointer(snd_pcm_substream_t * subst
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_hardware_t snd_ice1712_playback =
+static struct snd_pcm_hardware snd_ice1712_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -720,7 +720,7 @@ static snd_pcm_hardware_t snd_ice1712_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ice1712_playback_ds =
+static struct snd_pcm_hardware snd_ice1712_playback_ds =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -740,7 +740,7 @@ static snd_pcm_hardware_t snd_ice1712_playback_ds =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ice1712_capture =
+static struct snd_pcm_hardware snd_ice1712_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -759,20 +759,20 @@ static snd_pcm_hardware_t snd_ice1712_capture =
.fifo_size = 0,
};
-static int snd_ice1712_playback_open(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->playback_con_substream = substream;
runtime->hw = snd_ice1712_playback;
return 0;
}
-static int snd_ice1712_playback_ds_open(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_ds_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
u32 tmp;
ice->playback_con_substream_ds[substream->number] = substream;
@@ -784,10 +784,10 @@ static int snd_ice1712_playback_ds_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_open(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->capture_con_substream = substream;
runtime->hw = snd_ice1712_capture;
@@ -797,17 +797,17 @@ static int snd_ice1712_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_playback_close(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->playback_con_substream = NULL;
return 0;
}
-static int snd_ice1712_playback_ds_close(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_ds_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
u32 tmp;
spin_lock_irq(&ice->reg_lock);
@@ -818,15 +818,15 @@ static int snd_ice1712_playback_ds_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_close(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->capture_con_substream = NULL;
return 0;
}
-static snd_pcm_ops_t snd_ice1712_playback_ops = {
+static struct snd_pcm_ops snd_ice1712_playback_ops = {
.open = snd_ice1712_playback_open,
.close = snd_ice1712_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -837,7 +837,7 @@ static snd_pcm_ops_t snd_ice1712_playback_ops = {
.pointer = snd_ice1712_playback_pointer,
};
-static snd_pcm_ops_t snd_ice1712_playback_ds_ops = {
+static struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
.open = snd_ice1712_playback_ds_open,
.close = snd_ice1712_playback_ds_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -848,7 +848,7 @@ static snd_pcm_ops_t snd_ice1712_playback_ds_ops = {
.pointer = snd_ice1712_playback_ds_pointer,
};
-static snd_pcm_ops_t snd_ice1712_capture_ops = {
+static struct snd_pcm_ops snd_ice1712_capture_ops = {
.open = snd_ice1712_capture_open,
.close = snd_ice1712_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -859,16 +859,9 @@ static snd_pcm_ops_t snd_ice1712_capture_ops = {
.pointer = snd_ice1712_capture_pointer,
};
-static void snd_ice1712_pcm_free(snd_pcm_t *pcm)
+static int __devinit snd_ice1712_pcm(struct snd_ice1712 * ice, int device, struct snd_pcm ** rpcm)
{
- ice1712_t *ice = pcm->private_data;
- ice->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -881,7 +874,6 @@ static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** r
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ice1712_capture_ops);
pcm->private_data = ice;
- pcm->private_free = snd_ice1712_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "ICE1712 consumer");
ice->pcm = pcm;
@@ -897,16 +889,9 @@ static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** r
return 0;
}
-static void snd_ice1712_pcm_free_ds(snd_pcm_t *pcm)
+static int __devinit snd_ice1712_pcm_ds(struct snd_ice1712 * ice, int device, struct snd_pcm ** rpcm)
{
- ice1712_t *ice = pcm->private_data;
- ice->pcm_ds = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_ice1712_pcm_ds(ice1712_t * ice, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -918,7 +903,6 @@ static int __devinit snd_ice1712_pcm_ds(ice1712_t * ice, int device, snd_pcm_t *
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_ds_ops);
pcm->private_data = ice;
- pcm->private_free = snd_ice1712_pcm_free_ds;
pcm->info_flags = 0;
strcpy(pcm->name, "ICE1712 consumer (DS)");
ice->pcm_ds = pcm;
@@ -939,16 +923,16 @@ static int __devinit snd_ice1712_pcm_ds(ice1712_t * ice, int device, snd_pcm_t *
static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 64000, 88200, 96000 };
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
-static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream,
+static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -975,7 +959,7 @@ static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream,
unsigned int what = 0;
unsigned int old;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
@@ -1005,7 +989,7 @@ static int snd_ice1712_pro_trigger(snd_pcm_substream_t *substream,
/*
*/
-static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
+static void snd_ice1712_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate, int force)
{
unsigned long flags;
unsigned char val, old;
@@ -1059,9 +1043,9 @@ static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int forc
ice->spdif.ops.setup_rate(ice, rate);
}
-static int snd_ice1712_playback_pro_prepare(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_pro_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->playback_pro_size = snd_pcm_lib_buffer_bytes(substream);
spin_lock_irq(&ice->reg_lock);
@@ -1073,18 +1057,18 @@ static int snd_ice1712_playback_pro_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_playback_pro_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ice1712_playback_pro_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0);
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ice1712_capture_pro_prepare(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_pro_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->capture_pro_size = snd_pcm_lib_buffer_bytes(substream);
spin_lock_irq(&ice->reg_lock);
@@ -1095,18 +1079,18 @@ static int snd_ice1712_capture_pro_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_pro_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ice1712_capture_pro_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0);
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_PLAYBACK_START))
@@ -1117,9 +1101,9 @@ static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(snd_pcm_substream_t *
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(inl(ICEMT(ice, PLAYBACK_CONTROL)) & ICE1712_CAPTURE_START_SHADOW))
@@ -1130,7 +1114,7 @@ static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(snd_pcm_substream_t * s
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_hardware_t snd_ice1712_playback_pro =
+static struct snd_pcm_hardware snd_ice1712_playback_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1150,7 +1134,7 @@ static snd_pcm_hardware_t snd_ice1712_playback_pro =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ice1712_capture_pro =
+static struct snd_pcm_hardware snd_ice1712_capture_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1170,10 +1154,10 @@ static snd_pcm_hardware_t snd_ice1712_capture_pro =
.fifo_size = 0,
};
-static int snd_ice1712_playback_pro_open(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_pro_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
ice->playback_pro_substream = substream;
runtime->hw = snd_ice1712_playback_pro;
@@ -1187,10 +1171,10 @@ static int snd_ice1712_playback_pro_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_pro_open(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_pro_open(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
ice->capture_pro_substream = substream;
runtime->hw = snd_ice1712_capture_pro;
@@ -1200,9 +1184,9 @@ static int snd_ice1712_capture_pro_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_playback_pro_close(snd_pcm_substream_t * substream)
+static int snd_ice1712_playback_pro_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -1213,9 +1197,9 @@ static int snd_ice1712_playback_pro_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ice1712_capture_pro_close(snd_pcm_substream_t * substream)
+static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_ice1712_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -1223,14 +1207,7 @@ static int snd_ice1712_capture_pro_close(snd_pcm_substream_t * substream)
return 0;
}
-static void snd_ice1712_pcm_profi_free(snd_pcm_t *pcm)
-{
- ice1712_t *ice = pcm->private_data;
- ice->pcm_pro = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static snd_pcm_ops_t snd_ice1712_playback_pro_ops = {
+static struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
.open = snd_ice1712_playback_pro_open,
.close = snd_ice1712_playback_pro_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1241,7 +1218,7 @@ static snd_pcm_ops_t snd_ice1712_playback_pro_ops = {
.pointer = snd_ice1712_playback_pro_pointer,
};
-static snd_pcm_ops_t snd_ice1712_capture_pro_ops = {
+static struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
.open = snd_ice1712_capture_pro_open,
.close = snd_ice1712_capture_pro_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1252,9 +1229,9 @@ static snd_pcm_ops_t snd_ice1712_capture_pro_ops = {
.pointer = snd_ice1712_capture_pro_pointer,
};
-static int __devinit snd_ice1712_pcm_profi(ice1712_t * ice, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_ice1712_pcm_profi(struct snd_ice1712 * ice, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1267,7 +1244,6 @@ static int __devinit snd_ice1712_pcm_profi(ice1712_t * ice, int device, snd_pcm_
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ice1712_capture_pro_ops);
pcm->private_data = ice;
- pcm->private_free = snd_ice1712_pcm_profi_free;
pcm->info_flags = 0;
strcpy(pcm->name, "ICE1712 multi");
@@ -1296,7 +1272,7 @@ static int __devinit snd_ice1712_pcm_profi(ice1712_t * ice, int device, snd_pcm_
* Mixer section
*/
-static void snd_ice1712_update_volume(ice1712_t *ice, int index)
+static void snd_ice1712_update_volume(struct snd_ice1712 *ice, int index)
{
unsigned int vol = ice->pro_volumes[index];
unsigned short val = 0;
@@ -1307,7 +1283,7 @@ static void snd_ice1712_update_volume(ice1712_t *ice, int index)
outw(val, ICEMT(ice, MONITOR_VOLUME));
}
-static int snd_ice1712_pro_mixer_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_mixer_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -1316,9 +1292,9 @@ static int snd_ice1712_pro_mixer_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_mixer_switch_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_mixer_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
spin_lock_irq(&ice->reg_lock);
@@ -1328,9 +1304,9 @@ static int snd_ice1712_pro_mixer_switch_get(snd_kcontrol_t * kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_mixer_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_mixer_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
unsigned int nval, change;
@@ -1345,7 +1321,7 @@ static int snd_ice1712_pro_mixer_switch_put(snd_kcontrol_t * kcontrol, snd_ctl_e
return change;
}
-static int snd_ice1712_pro_mixer_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_mixer_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1354,9 +1330,9 @@ static int snd_ice1712_pro_mixer_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_mixer_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_mixer_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
spin_lock_irq(&ice->reg_lock);
@@ -1366,9 +1342,9 @@ static int snd_ice1712_pro_mixer_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_mixer_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int index = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + kcontrol->private_value;
unsigned int nval, change;
@@ -1384,7 +1360,7 @@ static int snd_ice1712_pro_mixer_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_e
}
-static snd_kcontrol_new_t snd_ice1712_multi_playback_ctrls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Playback Switch",
@@ -1405,7 +1381,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_playback_ctrls[] __devinitdata = {
},
};
-static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Multi Capture Switch",
.info = snd_ice1712_pro_mixer_switch_info,
@@ -1414,7 +1390,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_switch __devinitdata
.private_value = 10,
};
-static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH),
.info = snd_ice1712_pro_mixer_switch_info,
@@ -1424,7 +1400,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_switch __devinitdata =
.count = 2,
};
-static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Multi Capture Volume",
.info = snd_ice1712_pro_mixer_volume_info,
@@ -1433,7 +1409,7 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_analog_volume __devinitdata
.private_value = 10,
};
-static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME),
.info = snd_ice1712_pro_mixer_volume_info,
@@ -1443,9 +1419,9 @@ static snd_kcontrol_new_t snd_ice1712_multi_capture_spdif_volume __devinitdata =
.count = 2,
};
-static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
+static int __devinit snd_ice1712_build_pro_mixer(struct snd_ice1712 *ice)
{
- snd_card_t * card = ice->card;
+ struct snd_card *card = ice->card;
unsigned int idx;
int err;
@@ -1457,7 +1433,7 @@ static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
}
if (ice->num_total_adcs > 0) {
- snd_kcontrol_new_t tmp = snd_ice1712_multi_capture_analog_switch;
+ struct snd_kcontrol_new tmp = snd_ice1712_multi_capture_analog_switch;
tmp.count = ice->num_total_adcs;
err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice));
if (err < 0)
@@ -1469,7 +1445,7 @@ static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
return err;
if (ice->num_total_adcs > 0) {
- snd_kcontrol_new_t tmp = snd_ice1712_multi_capture_analog_volume;
+ struct snd_kcontrol_new tmp = snd_ice1712_multi_capture_analog_volume;
tmp.count = ice->num_total_adcs;
err = snd_ctl_add(card, snd_ctl_new1(&tmp, ice));
if (err < 0)
@@ -1496,22 +1472,22 @@ static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
return 0;
}
-static void snd_ice1712_mixer_free_ac97(ac97_t *ac97)
+static void snd_ice1712_mixer_free_ac97(struct snd_ac97 *ac97)
{
- ice1712_t *ice = ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
ice->ac97 = NULL;
}
-static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice)
+static int __devinit snd_ice1712_ac97_mixer(struct snd_ice1712 * ice)
{
int err, bus_num = 0;
- ac97_template_t ac97;
- ac97_bus_t *pbus;
- static ac97_bus_ops_t con_ops = {
+ struct snd_ac97_template ac97;
+ struct snd_ac97_bus *pbus;
+ static struct snd_ac97_bus_ops con_ops = {
.write = snd_ice1712_ac97_write,
.read = snd_ice1712_ac97_read,
};
- static ac97_bus_ops_t pro_ops = {
+ static struct snd_ac97_bus_ops pro_ops = {
.write = snd_ice1712_pro_ac97_write,
.read = snd_ice1712_pro_ac97_read,
};
@@ -1551,15 +1527,15 @@ static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice)
*
*/
-static inline unsigned int eeprom_double(ice1712_t *ice, int idx)
+static inline unsigned int eeprom_double(struct snd_ice1712 *ice, int idx)
{
return (unsigned int)ice->eeprom.data[idx] | ((unsigned int)ice->eeprom.data[idx + 1] << 8);
}
-static void snd_ice1712_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ice1712_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ice1712_t *ice = entry->private_data;
+ struct snd_ice1712 *ice = entry->private_data;
unsigned int idx;
snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -1593,9 +1569,9 @@ static void snd_ice1712_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, " RATE : 0x%02x\n", (unsigned)inb(ICEMT(ice, RATE)));
}
-static void __devinit snd_ice1712_proc_init(ice1712_t * ice)
+static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(ice->card, "ice1712", &entry))
snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read);
@@ -1605,22 +1581,24 @@ static void __devinit snd_ice1712_proc_init(ice1712_t * ice)
*
*/
-static int snd_ice1712_eeprom_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_eeprom_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = sizeof(ice1712_eeprom_t);
+ uinfo->count = sizeof(struct snd_ice1712_eeprom);
return 0;
}
-static int snd_ice1712_eeprom_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom));
return 0;
}
-static snd_kcontrol_new_t snd_ice1712_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "ICE1712 EEPROM",
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1630,32 +1608,33 @@ static snd_kcontrol_new_t snd_ice1712_eeprom __devinitdata = {
/*
*/
-static int snd_ice1712_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ice1712_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.default_get)
ice->spdif.ops.default_get(ice, ucontrol);
return 0;
}
-static int snd_ice1712_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.default_put)
return ice->spdif.ops.default_put(ice, ucontrol);
return 0;
}
-static snd_kcontrol_new_t snd_ice1712_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1664,10 +1643,10 @@ static snd_kcontrol_new_t snd_ice1712_spdif_default __devinitdata =
.put = snd_ice1712_spdif_default_put
};
-static int snd_ice1712_spdif_maskc_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_maskc_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.default_get) {
ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO |
IEC958_AES0_PROFESSIONAL |
@@ -1686,10 +1665,10 @@ static int snd_ice1712_spdif_maskc_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ice1712_spdif_maskp_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.default_get) {
ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO |
IEC958_AES0_PROFESSIONAL |
@@ -1706,7 +1685,7 @@ static int snd_ice1712_spdif_maskp_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1715,7 +1694,7 @@ static snd_kcontrol_new_t snd_ice1712_spdif_maskc __devinitdata =
.get = snd_ice1712_spdif_maskc_get,
};
-static snd_kcontrol_new_t snd_ice1712_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1724,27 +1703,28 @@ static snd_kcontrol_new_t snd_ice1712_spdif_maskp __devinitdata =
.get = snd_ice1712_spdif_maskp_get,
};
-static int snd_ice1712_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.stream_get)
ice->spdif.ops.stream_get(ice, ucontrol);
return 0;
}
-static int snd_ice1712_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
if (ice->spdif.ops.stream_put)
return ice->spdif.ops.stream_put(ice, ucontrol);
return 0;
}
-static snd_kcontrol_new_t snd_ice1712_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
{
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE),
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
.info = snd_ice1712_spdif_info,
@@ -1752,7 +1732,8 @@ static snd_kcontrol_new_t snd_ice1712_spdif_stream __devinitdata =
.put = snd_ice1712_spdif_stream_put
};
-int snd_ice1712_gpio_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1761,21 +1742,24 @@ int snd_ice1712_gpio_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
-int snd_ice1712_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0;
snd_ice1712_save_gpio_status(ice);
- ucontrol->value.integer.value[0] = (snd_ice1712_gpio_read(ice) & mask ? 1 : 0) ^ invert;
+ ucontrol->value.integer.value[0] =
+ (snd_ice1712_gpio_read(ice) & mask ? 1 : 0) ^ invert;
snd_ice1712_restore_gpio_status(ice);
return 0;
}
-int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char mask = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? mask : 0;
unsigned int val, nval;
@@ -1795,7 +1779,8 @@ int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucont
/*
* rate
*/
-static int snd_ice1712_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"8000", /* 0: 6 */
@@ -1822,9 +1807,10 @@ static int snd_ice1712_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl
return 0;
}
-static int snd_ice1712_pro_internal_clock_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
static unsigned char xlate[16] = {
9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 255, 255, 255, 10
};
@@ -1845,9 +1831,10 @@ static int snd_ice1712_pro_internal_clock_get(snd_kcontrol_t * kcontrol, snd_ctl
return 0;
}
-static int snd_ice1712_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
static unsigned int xrate[13] = {
8000, 9600, 11025, 12000, 1600, 22050, 24000,
32000, 44100, 48000, 64000, 88200, 96000
@@ -1868,7 +1855,8 @@ static int snd_ice1712_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl
change = inb(ICEMT(ice, RATE)) != oval;
spin_unlock_irq(&ice->reg_lock);
- if ((oval & ICE1712_SPDIF_MASTER) != (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) {
+ if ((oval & ICE1712_SPDIF_MASTER) !=
+ (inb(ICEMT(ice, RATE)) & ICE1712_SPDIF_MASTER)) {
/* change CS8427 clock source too */
if (ice->cs8427) {
snd_ice1712_cs8427_set_input_clock(ice, is_spdif_master(ice));
@@ -1886,7 +1874,7 @@ static int snd_ice1712_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl
return change;
}
-static snd_kcontrol_new_t snd_ice1712_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock",
.info = snd_ice1712_pro_internal_clock_info,
@@ -1894,7 +1882,8 @@ static snd_kcontrol_new_t snd_ice1712_pro_internal_clock __devinitdata = {
.put = snd_ice1712_pro_internal_clock_put
};
-static int snd_ice1712_pro_internal_clock_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_internal_clock_default_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"8000", /* 0: 6 */
@@ -1921,7 +1910,8 @@ static int snd_ice1712_pro_internal_clock_default_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ice1712_pro_internal_clock_default_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int val;
static unsigned int xrate[13] = {
@@ -1938,7 +1928,8 @@ static int snd_ice1712_pro_internal_clock_default_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ice1712_pro_internal_clock_default_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
static unsigned int xrate[13] = {
8000, 9600, 11025, 12000, 1600, 22050, 24000,
@@ -1954,7 +1945,7 @@ static int snd_ice1712_pro_internal_clock_default_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ice1712_pro_internal_clock_default __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock Default",
.info = snd_ice1712_pro_internal_clock_default_info,
@@ -1962,7 +1953,8 @@ static snd_kcontrol_new_t snd_ice1712_pro_internal_clock_default __devinitdata =
.put = snd_ice1712_pro_internal_clock_default_put
};
-static int snd_ice1712_pro_rate_locking_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_rate_locking_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1971,15 +1963,17 @@ static int snd_ice1712_pro_rate_locking_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_rate_locking_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_rate_locking_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = PRO_RATE_LOCKED;
return 0;
}
-static int snd_ice1712_pro_rate_locking_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, nval;
nval = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1990,7 +1984,7 @@ static int snd_ice1712_pro_rate_locking_put(snd_kcontrol_t * kcontrol, snd_ctl_e
return change;
}
-static snd_kcontrol_new_t snd_ice1712_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Locking",
.info = snd_ice1712_pro_rate_locking_info,
@@ -1998,7 +1992,8 @@ static snd_kcontrol_new_t snd_ice1712_pro_rate_locking __devinitdata = {
.put = snd_ice1712_pro_rate_locking_put
};
-static int snd_ice1712_pro_rate_reset_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_rate_reset_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2007,15 +2002,17 @@ static int snd_ice1712_pro_rate_reset_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_ice1712_pro_rate_reset_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_rate_reset_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = PRO_RATE_RESET;
return 0;
}
-static int snd_ice1712_pro_rate_reset_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, nval;
nval = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -2026,7 +2023,7 @@ static int snd_ice1712_pro_rate_reset_put(snd_kcontrol_t * kcontrol, snd_ctl_ele
return change;
}
-static snd_kcontrol_new_t snd_ice1712_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Reset",
.info = snd_ice1712_pro_rate_reset_info,
@@ -2037,7 +2034,8 @@ static snd_kcontrol_new_t snd_ice1712_pro_rate_reset __devinitdata = {
/*
* routing
*/
-static int snd_ice1712_pro_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_route_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"PCM Out", /* 0 */
@@ -2049,16 +2047,18 @@ static int snd_ice1712_pro_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = snd_ctl_get_ioffidx(kcontrol, &uinfo->id) < 2 ? 12 : 11;
+ uinfo->value.enumerated.items =
+ snd_ctl_get_ioffidx(kcontrol, &uinfo->id) < 2 ? 12 : 11;
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
return 0;
}
-static int snd_ice1712_pro_route_analog_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_pro_route_analog_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned int val, cval;
@@ -2081,9 +2081,10 @@ static int snd_ice1712_pro_route_analog_get(snd_kcontrol_t * kcontrol, snd_ctl_e
return 0;
}
-static int snd_ice1712_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_pro_route_analog_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change, shift;
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned int val, old_val, nval;
@@ -2130,9 +2131,10 @@ static int snd_ice1712_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_e
return change;
}
-static int snd_ice1712_pro_route_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_pro_route_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned int val, cval;
val = inw(ICEMT(ice, ROUTE_SPDOUT));
@@ -2149,9 +2151,10 @@ static int snd_ice1712_pro_route_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_el
return 0;
}
-static int snd_ice1712_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change, shift;
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
unsigned int val, old_val, nval;
@@ -2187,7 +2190,7 @@ static int snd_ice1712_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_el
return change;
}
-static snd_kcontrol_new_t snd_ice1712_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
.info = snd_ice1712_pro_route_info,
@@ -2195,7 +2198,7 @@ static snd_kcontrol_new_t snd_ice1712_mixer_pro_analog_route __devinitdata = {
.put = snd_ice1712_pro_route_analog_put,
};
-static snd_kcontrol_new_t snd_ice1712_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = snd_ice1712_pro_route_info,
@@ -2205,7 +2208,8 @@ static snd_kcontrol_new_t snd_ice1712_mixer_pro_spdif_route __devinitdata = {
};
-static int snd_ice1712_pro_volume_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_volume_rate_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2214,17 +2218,19 @@ static int snd_ice1712_pro_volume_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_ice1712_pro_volume_rate_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_volume_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = inb(ICEMT(ice, MONITOR_RATE));
return 0;
}
-static int snd_ice1712_pro_volume_rate_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change;
spin_lock_irq(&ice->reg_lock);
@@ -2234,7 +2240,7 @@ static int snd_ice1712_pro_volume_rate_put(snd_kcontrol_t * kcontrol, snd_ctl_el
return change;
}
-static snd_kcontrol_new_t snd_ice1712_mixer_pro_volume_rate __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Volume Rate",
.info = snd_ice1712_pro_volume_rate_info,
@@ -2242,7 +2248,8 @@ static snd_kcontrol_new_t snd_ice1712_mixer_pro_volume_rate __devinitdata = {
.put = snd_ice1712_pro_volume_rate_put
};
-static int snd_ice1712_pro_peak_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ice1712_pro_peak_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 22;
@@ -2251,9 +2258,10 @@ static int snd_ice1712_pro_peak_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_ice1712_pro_peak_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx;
spin_lock_irq(&ice->reg_lock);
@@ -2265,7 +2273,7 @@ static int snd_ice1712_pro_peak_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return 0;
}
-static snd_kcontrol_new_t snd_ice1712_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Peak",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2287,7 +2295,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
NULL,
};
-static unsigned char __devinit snd_ice1712_read_i2c(ice1712_t *ice,
+static unsigned char __devinit snd_ice1712_read_i2c(struct snd_ice1712 *ice,
unsigned char dev,
unsigned char addr)
{
@@ -2299,7 +2307,8 @@ static unsigned char __devinit snd_ice1712_read_i2c(ice1712_t *ice,
return inb(ICEREG(ice, I2C_DATA));
}
-static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelname)
+static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
+ const char *modelname)
{
int dev = 0xa0; /* EEPROM device address */
unsigned int i, size;
@@ -2312,7 +2321,8 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelna
(snd_ice1712_read_i2c(ice, dev, 0x01) << 8) |
(snd_ice1712_read_i2c(ice, dev, 0x02) << 16) |
(snd_ice1712_read_i2c(ice, dev, 0x03) << 24);
- if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {
+ if (ice->eeprom.subvendor == 0 ||
+ ice->eeprom.subvendor == (unsigned int)-1) {
/* invalid subvendor from EEPROM, try the PCI subststem ID instead */
u16 vendor, device;
pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
@@ -2341,7 +2351,8 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelna
goto read_skipped;
}
}
- printk(KERN_WARNING "ice1712: No matching model found for ID 0x%x\n", ice->eeprom.subvendor);
+ printk(KERN_WARNING "ice1712: No matching model found for ID 0x%x\n",
+ ice->eeprom.subvendor);
found:
ice->eeprom.size = snd_ice1712_read_i2c(ice, dev, 0x04);
@@ -2353,7 +2364,8 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelna
}
ice->eeprom.version = snd_ice1712_read_i2c(ice, dev, 0x05);
if (ice->eeprom.version != 1) {
- snd_printk(KERN_ERR "invalid EEPROM version %i\n", ice->eeprom.version);
+ snd_printk(KERN_ERR "invalid EEPROM version %i\n",
+ ice->eeprom.version);
/* return -EIO; */
}
size = ice->eeprom.size - 6;
@@ -2370,7 +2382,7 @@ static int __devinit snd_ice1712_read_eeprom(ice1712_t *ice, const char *modelna
-static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
+static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice)
{
outb(ICE1712_RESET | ICE1712_NATIVE, ICEREG(ice, CONTROL));
udelay(200);
@@ -2383,15 +2395,19 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
if (ice->eeprom.subvendor != ICE1712_SUBDEVICE_STDSP24) {
ice->gpio.write_mask = ice->eeprom.gpiomask;
ice->gpio.direction = ice->eeprom.gpiodir;
- snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
- snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
- snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
+ snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK,
+ ice->eeprom.gpiomask);
+ snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
+ ice->eeprom.gpiodir);
+ snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA,
+ ice->eeprom.gpiostate);
} else {
ice->gpio.write_mask = 0xc0;
ice->gpio.direction = 0xff;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, 0xc0);
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, 0xff);
- snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ICE1712_STDSP24_CLOCK_BIT);
+ snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA,
+ ICE1712_STDSP24_CLOCK_BIT);
}
snd_ice1712_write(ice, ICE1712_IREG_PRO_POWERDOWN, 0);
if (!(ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97)) {
@@ -2406,10 +2422,10 @@ static int __devinit snd_ice1712_chip_init(ice1712_t *ice)
return 0;
}
-int __devinit snd_ice1712_spdif_build_controls(ice1712_t *ice)
+int __devinit snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
{
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
snd_assert(ice->pcm_pro != NULL, return -EIO);
err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice));
@@ -2433,7 +2449,7 @@ int __devinit snd_ice1712_spdif_build_controls(ice1712_t *ice)
}
-static int __devinit snd_ice1712_build_controls(ice1712_t *ice)
+static int __devinit snd_ice1712_build_controls(struct snd_ice1712 *ice)
{
int err;
@@ -2455,7 +2471,7 @@ static int __devinit snd_ice1712_build_controls(ice1712_t *ice)
return err;
if (ice->num_total_dacs > 0) {
- snd_kcontrol_new_t tmp = snd_ice1712_mixer_pro_analog_route;
+ struct snd_kcontrol_new tmp = snd_ice1712_mixer_pro_analog_route;
tmp.count = ice->num_total_dacs;
err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice));
if (err < 0)
@@ -2476,7 +2492,7 @@ static int __devinit snd_ice1712_build_controls(ice1712_t *ice)
return 0;
}
-static int snd_ice1712_free(ice1712_t *ice)
+static int snd_ice1712_free(struct snd_ice1712 *ice)
{
if (! ice->port)
goto __hw_end;
@@ -2487,7 +2503,7 @@ static int snd_ice1712_free(ice1712_t *ice)
__hw_end:
if (ice->irq >= 0) {
synchronize_irq(ice->irq);
- free_irq(ice->irq, (void *) ice);
+ free_irq(ice->irq, ice);
}
if (ice->port)
pci_release_regions(ice->pci);
@@ -2497,22 +2513,22 @@ static int snd_ice1712_free(ice1712_t *ice)
return 0;
}
-static int snd_ice1712_dev_free(snd_device_t *device)
+static int snd_ice1712_dev_free(struct snd_device *device)
{
- ice1712_t *ice = device->device_data;
+ struct snd_ice1712 *ice = device->device_data;
return snd_ice1712_free(ice);
}
-static int __devinit snd_ice1712_create(snd_card_t * card,
+static int __devinit snd_ice1712_create(struct snd_card *card,
struct pci_dev *pci,
const char *modelname,
int omni,
int cs8427_timeout,
- ice1712_t ** r_ice1712)
+ struct snd_ice1712 ** r_ice1712)
{
- ice1712_t *ice;
+ struct snd_ice1712 *ice;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ice1712_dev_free,
};
@@ -2572,7 +2588,8 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
ice->dmapath_port = pci_resource_start(pci, 2);
ice->profi_port = pci_resource_start(pci, 3);
- if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) {
+ if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "ICE1712", ice)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_ice1712_free(ice);
return -EIO;
@@ -2590,8 +2607,10 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
}
/* unmask used interrupts */
- outb((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ? ICE1712_IRQ_MPU2 : 0 |
- (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ? ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0,
+ outb(((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) == 0 ?
+ ICE1712_IRQ_MPU2 : 0) |
+ ((ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_NO_CON_AC97) ?
+ ICE1712_IRQ_PBKDS | ICE1712_IRQ_CONCAP | ICE1712_IRQ_CONPBK : 0),
ICEREG(ice, IRQMASK));
outb(0x00, ICEMT(ice, IRQ));
@@ -2619,8 +2638,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- ice1712_t *ice;
+ struct snd_card *card;
+ struct snd_ice1712 *ice;
int pcm_dev = 0, err;
struct snd_ice1712_card_info **tbl, *c;
@@ -2638,7 +2657,8 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
strcpy(card->driver, "ICE1712");
strcpy(card->shortname, "ICEnsemble ICE1712");
- if ((err = snd_ice1712_create(card, pci, model[dev], omni[dev], cs8427_timeout[dev], &ice)) < 0) {
+ if ((err = snd_ice1712_create(card, pci, model[dev], omni[dev],
+ cs8427_timeout[dev], &ice)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 5ad4728daa7b..ce96b3bb6531 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -215,9 +215,9 @@
*
*/
-typedef struct _snd_ice1712 ice1712_t;
+struct snd_ice1712;
-typedef struct {
+struct snd_ice1712_eeprom {
unsigned int subvendor; /* PCI[2c-2f] */
unsigned char size; /* size of EEPROM image in bytes */
unsigned char version; /* must be 1 (or 2 for vt1724) */
@@ -225,7 +225,7 @@ typedef struct {
unsigned int gpiomask;
unsigned int gpiostate;
unsigned int gpiodir;
-} ice1712_eeprom_t;
+};
enum {
ICE_EEP1_CODEC = 0, /* 06 */
@@ -266,28 +266,28 @@ struct snd_ak4xxx_private {
unsigned int add_flags; /* additional bits at init */
unsigned int mask_flags; /* total mask bits */
struct snd_akm4xxx_ops {
- void (*set_rate_val)(akm4xxx_t *ak, unsigned int rate);
+ void (*set_rate_val)(struct snd_akm4xxx *ak, unsigned int rate);
} ops;
};
struct snd_ice1712_spdif {
unsigned char cs8403_bits;
unsigned char cs8403_stream_bits;
- snd_kcontrol_t *stream_ctl;
+ struct snd_kcontrol *stream_ctl;
struct snd_ice1712_spdif_ops {
- void (*open)(ice1712_t *, snd_pcm_substream_t *);
- void (*setup_rate)(ice1712_t *, int rate);
- void (*close)(ice1712_t *, snd_pcm_substream_t *);
- void (*default_get)(ice1712_t *, snd_ctl_elem_value_t * ucontrol);
- int (*default_put)(ice1712_t *, snd_ctl_elem_value_t * ucontrol);
- void (*stream_get)(ice1712_t *, snd_ctl_elem_value_t * ucontrol);
- int (*stream_put)(ice1712_t *, snd_ctl_elem_value_t * ucontrol);
+ void (*open)(struct snd_ice1712 *, struct snd_pcm_substream *);
+ void (*setup_rate)(struct snd_ice1712 *, int rate);
+ void (*close)(struct snd_ice1712 *, struct snd_pcm_substream *);
+ void (*default_get)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol);
+ int (*default_put)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol);
+ void (*stream_get)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol);
+ int (*stream_put)(struct snd_ice1712 *, struct snd_ctl_elem_value *ucontrol);
} ops;
};
-struct _snd_ice1712 {
+struct snd_ice1712 {
unsigned long conp_dma_size;
unsigned long conc_dma_size;
unsigned long prop_dma_size;
@@ -300,28 +300,28 @@ struct _snd_ice1712 {
unsigned long profi_port;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_t *pcm_ds;
- snd_pcm_t *pcm_pro;
- snd_pcm_substream_t *playback_con_substream;
- snd_pcm_substream_t *playback_con_substream_ds[6];
- snd_pcm_substream_t *capture_con_substream;
- snd_pcm_substream_t *playback_pro_substream;
- snd_pcm_substream_t *capture_pro_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm *pcm_ds;
+ struct snd_pcm *pcm_pro;
+ struct snd_pcm_substream *playback_con_substream;
+ struct snd_pcm_substream *playback_con_substream_ds[6];
+ struct snd_pcm_substream *capture_con_substream;
+ struct snd_pcm_substream *playback_pro_substream;
+ struct snd_pcm_substream *capture_pro_substream;
unsigned int playback_pro_size;
unsigned int capture_pro_size;
unsigned int playback_con_virt_addr[6];
unsigned int playback_con_active_buf[6];
unsigned int capture_con_virt_addr;
unsigned int ac97_ext_id;
- ac97_t *ac97;
- snd_rawmidi_t *rmidi[2];
+ struct snd_ac97 *ac97;
+ struct snd_rawmidi *rmidi[2];
spinlock_t reg_lock;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
- ice1712_eeprom_t eeprom;
+ struct snd_ice1712_eeprom eeprom;
unsigned int pro_volumes[20];
unsigned int omni: 1; /* Delta Omni I/O */
@@ -335,16 +335,16 @@ struct _snd_ice1712 {
unsigned int cur_rate; /* current rate */
struct semaphore open_mutex;
- snd_pcm_substream_t *pcm_reserved[4];
- snd_pcm_hw_constraint_list_t *hw_rates; /* card-specific rate constraints */
+ struct snd_pcm_substream *pcm_reserved[4];
+ struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */
unsigned int akm_codecs;
- akm4xxx_t *akm;
+ struct snd_akm4xxx *akm;
struct snd_ice1712_spdif spdif;
struct semaphore i2c_mutex; /* I2C mutex for ICE1724 registers */
- snd_i2c_bus_t *i2c; /* I2C bus */
- snd_i2c_device_t *cs8427; /* CS8427 I2C device */
+ struct snd_i2c_bus *i2c; /* I2C bus */
+ struct snd_i2c_device *cs8427; /* CS8427 I2C device */
unsigned int cs8427_timeout; /* CS8427 reset timeout in HZ/100 */
struct ice1712_gpio {
@@ -352,20 +352,20 @@ struct _snd_ice1712 {
unsigned int write_mask; /* current mask bits */
unsigned int saved[2]; /* for ewx_i2c */
/* operators */
- void (*set_mask)(ice1712_t *ice, unsigned int data);
- void (*set_dir)(ice1712_t *ice, unsigned int data);
- void (*set_data)(ice1712_t *ice, unsigned int data);
- unsigned int (*get_data)(ice1712_t *ice);
+ void (*set_mask)(struct snd_ice1712 *ice, unsigned int data);
+ void (*set_dir)(struct snd_ice1712 *ice, unsigned int data);
+ void (*set_data)(struct snd_ice1712 *ice, unsigned int data);
+ unsigned int (*get_data)(struct snd_ice1712 *ice);
/* misc operators - move to another place? */
- void (*set_pro_rate)(ice1712_t *ice, unsigned int rate);
- void (*i2s_mclk_changed)(ice1712_t *ice);
+ void (*set_pro_rate)(struct snd_ice1712 *ice, unsigned int rate);
+ void (*i2s_mclk_changed)(struct snd_ice1712 *ice);
} gpio;
struct semaphore gpio_mutex;
/* other board-specific data */
union {
/* additional i2c devices for EWS boards */
- snd_i2c_device_t *i2cdevs[3];
+ struct snd_i2c_device *i2cdevs[3];
/* AC97 register cache for Aureon */
struct aureon_spec {
unsigned short stac9744[64];
@@ -385,7 +385,7 @@ struct _snd_ice1712 {
unsigned short boxconfig[4];
} hoontech;
struct {
- ak4114_t *ak4114;
+ struct ak4114 *ak4114;
unsigned int analog: 1;
} juli;
} spec;
@@ -396,22 +396,22 @@ struct _snd_ice1712 {
/*
* gpio access functions
*/
-static inline void snd_ice1712_gpio_set_dir(ice1712_t *ice, unsigned int bits)
+static inline void snd_ice1712_gpio_set_dir(struct snd_ice1712 *ice, unsigned int bits)
{
ice->gpio.set_dir(ice, bits);
}
-static inline void snd_ice1712_gpio_set_mask(ice1712_t *ice, unsigned int bits)
+static inline void snd_ice1712_gpio_set_mask(struct snd_ice1712 *ice, unsigned int bits)
{
ice->gpio.set_mask(ice, bits);
}
-static inline void snd_ice1712_gpio_write(ice1712_t *ice, unsigned int val)
+static inline void snd_ice1712_gpio_write(struct snd_ice1712 *ice, unsigned int val)
{
ice->gpio.set_data(ice, val);
}
-static inline unsigned int snd_ice1712_gpio_read(ice1712_t *ice)
+static inline unsigned int snd_ice1712_gpio_read(struct snd_ice1712 *ice)
{
return ice->gpio.get_data(ice);
}
@@ -421,14 +421,14 @@ static inline unsigned int snd_ice1712_gpio_read(ice1712_t *ice)
* The access to gpio will be protected by mutex, so don't forget to
* restore!
*/
-static inline void snd_ice1712_save_gpio_status(ice1712_t *ice)
+static inline void snd_ice1712_save_gpio_status(struct snd_ice1712 *ice)
{
down(&ice->gpio_mutex);
ice->gpio.saved[0] = ice->gpio.direction;
ice->gpio.saved[1] = ice->gpio.write_mask;
}
-static inline void snd_ice1712_restore_gpio_status(ice1712_t *ice)
+static inline void snd_ice1712_restore_gpio_status(struct snd_ice1712 *ice)
{
ice->gpio.set_dir(ice, ice->gpio.saved[0]);
ice->gpio.set_mask(ice, ice->gpio.saved[1]);
@@ -443,14 +443,15 @@ static inline void snd_ice1712_restore_gpio_status(ice1712_t *ice)
.get = snd_ice1712_gpio_get, .put = snd_ice1712_gpio_put, \
.private_value = mask | (invert << 24) }
-int snd_ice1712_gpio_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
-int snd_ice1712_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ice1712_gpio_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_ice1712_gpio_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
/*
* set gpio direction, write mask and data
*/
-static inline void snd_ice1712_gpio_write_bits(ice1712_t *ice, unsigned int mask, unsigned int bits)
+static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
+ unsigned int mask, unsigned int bits)
{
ice->gpio.direction |= mask;
snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
@@ -458,21 +459,22 @@ static inline void snd_ice1712_gpio_write_bits(ice1712_t *ice, unsigned int mask
snd_ice1712_gpio_write(ice, mask & bits);
}
-int snd_ice1712_spdif_build_controls(ice1712_t *ice);
+int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice);
-int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *template, const struct snd_ak4xxx_private *priv, ice1712_t *ice);
-void snd_ice1712_akm4xxx_free(ice1712_t *ice);
-int snd_ice1712_akm4xxx_build_controls(ice1712_t *ice);
+int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template,
+ const struct snd_ak4xxx_private *priv, struct snd_ice1712 *ice);
+void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice);
+int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice);
-int snd_ice1712_init_cs8427(ice1712_t *ice, int addr);
+int snd_ice1712_init_cs8427(struct snd_ice1712 *ice, int addr);
-static inline void snd_ice1712_write(ice1712_t * ice, u8 addr, u8 data)
+static inline void snd_ice1712_write(struct snd_ice1712 * ice, u8 addr, u8 data)
{
outb(addr, ICEREG(ice, INDEX));
outb(data, ICEREG(ice, DATA));
}
-static inline u8 snd_ice1712_read(ice1712_t * ice, u8 addr)
+static inline u8 snd_ice1712_read(struct snd_ice1712 * ice, u8 addr)
{
outb(addr, ICEREG(ice, INDEX));
return inb(ICEREG(ice, DATA));
@@ -488,8 +490,8 @@ struct snd_ice1712_card_info {
char *name;
char *model;
char *driver;
- int (*chip_init)(ice1712_t *);
- int (*build_controls)(ice1712_t *);
+ int (*chip_init)(struct snd_ice1712 *);
+ int (*build_controls)(struct snd_ice1712 *);
unsigned int no_mpu401: 1;
unsigned int eeprom_size;
unsigned char *eeprom_data;
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 0b5389ee26d5..71f08c036019 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -102,12 +102,12 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
*/
/* check whether the clock mode is spdif-in */
-static inline int is_spdif_master(ice1712_t *ice)
+static inline int is_spdif_master(struct snd_ice1712 *ice)
{
return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
}
-static inline int is_pro_rate_locked(ice1712_t *ice)
+static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
{
return is_spdif_master(ice) || PRO_RATE_LOCKED;
}
@@ -116,7 +116,7 @@ static inline int is_pro_rate_locked(ice1712_t *ice)
* ac97 section
*/
-static unsigned char snd_vt1724_ac97_ready(ice1712_t *ice)
+static unsigned char snd_vt1724_ac97_ready(struct snd_ice1712 *ice)
{
unsigned char old_cmd;
int tm;
@@ -132,7 +132,7 @@ static unsigned char snd_vt1724_ac97_ready(ice1712_t *ice)
return old_cmd;
}
-static int snd_vt1724_ac97_wait_bit(ice1712_t *ice, unsigned char bit)
+static int snd_vt1724_ac97_wait_bit(struct snd_ice1712 *ice, unsigned char bit)
{
int tm;
for (tm = 0; tm < 0x10000; tm++)
@@ -142,11 +142,11 @@ static int snd_vt1724_ac97_wait_bit(ice1712_t *ice, unsigned char bit)
return -EIO;
}
-static void snd_vt1724_ac97_write(ac97_t *ac97,
+static void snd_vt1724_ac97_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
unsigned char old_cmd;
old_cmd = snd_vt1724_ac97_ready(ice);
@@ -158,9 +158,9 @@ static void snd_vt1724_ac97_write(ac97_t *ac97,
snd_vt1724_ac97_wait_bit(ice, VT1724_AC97_WRITE);
}
-static unsigned short snd_vt1724_ac97_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_vt1724_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
- ice1712_t *ice = (ice1712_t *)ac97->private_data;
+ struct snd_ice1712 *ice = ac97->private_data;
unsigned char old_cmd;
old_cmd = snd_vt1724_ac97_ready(ice);
@@ -179,14 +179,14 @@ static unsigned short snd_vt1724_ac97_read(ac97_t *ac97, unsigned short reg)
*/
/* set gpio direction 0 = read, 1 = write */
-static void snd_vt1724_set_gpio_dir(ice1712_t *ice, unsigned int data)
+static void snd_vt1724_set_gpio_dir(struct snd_ice1712 *ice, unsigned int data)
{
outl(data, ICEREG1724(ice, GPIO_DIRECTION));
inw(ICEREG1724(ice, GPIO_DIRECTION)); /* dummy read for pci-posting */
}
/* set the gpio mask (0 = writable) */
-static void snd_vt1724_set_gpio_mask(ice1712_t *ice, unsigned int data)
+static void snd_vt1724_set_gpio_mask(struct snd_ice1712 *ice, unsigned int data)
{
outw(data, ICEREG1724(ice, GPIO_WRITE_MASK));
if (! ice->vt1720) /* VT1720 supports only 16 GPIO bits */
@@ -194,7 +194,7 @@ static void snd_vt1724_set_gpio_mask(ice1712_t *ice, unsigned int data)
inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */
}
-static void snd_vt1724_set_gpio_data(ice1712_t *ice, unsigned int data)
+static void snd_vt1724_set_gpio_data(struct snd_ice1712 *ice, unsigned int data)
{
outw(data, ICEREG1724(ice, GPIO_DATA));
if (! ice->vt1720)
@@ -202,7 +202,7 @@ static void snd_vt1724_set_gpio_data(ice1712_t *ice, unsigned int data)
inw(ICEREG1724(ice, GPIO_DATA)); /* dummy read for pci-posting */
}
-static unsigned int snd_vt1724_get_gpio_data(ice1712_t *ice)
+static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
{
unsigned int data;
if (! ice->vt1720)
@@ -219,7 +219,7 @@ static unsigned int snd_vt1724_get_gpio_data(ice1712_t *ice)
static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ice1712_t *ice = dev_id;
+ struct snd_ice1712 *ice = dev_id;
unsigned char status;
int handled = 0;
@@ -229,8 +229,10 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *r
break;
handled = 1;
- /* these should probably be separated at some point,
- but as we don't currently have MPU support on the board I will leave it */
+ /* these should probably be separated at some point,
+ * but as we don't currently have MPU support on the board
+ * I will leave it
+ */
if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
if (ice->rmidi[0])
snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
@@ -303,19 +305,19 @@ static unsigned int rates[] = {
176400, 192000,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates_96 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = {
.count = ARRAY_SIZE(rates) - 2, /* up to 96000 */
.list = rates,
.mask = 0,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates_48 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = {
.count = ARRAY_SIZE(rates) - 5, /* up to 48000 */
.list = rates,
.mask = 0,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates_192 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -328,13 +330,13 @@ struct vt1724_pcm_reg {
unsigned int start; /* start & pause bit */
};
-static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
unsigned char what;
unsigned char old;
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
what = 0;
snd_pcm_group_for_each(pos, substream) {
@@ -384,7 +386,7 @@ static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
#define DMA_PAUSES (VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
-static int get_max_rate(ice1712_t *ice)
+static int get_max_rate(struct snd_ice1712 *ice)
{
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
@@ -395,7 +397,8 @@ static int get_max_rate(ice1712_t *ice)
return 48000;
}
-static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
+static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
+ int force)
{
unsigned long flags;
unsigned char val, old;
@@ -477,10 +480,10 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
ice->spdif.ops.setup_rate(ice, rate);
}
-static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int i, chs;
chs = params_channels(hw_params);
@@ -490,7 +493,8 @@ static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
/* PDMA0 can be multi-channel up to 8 */
chs = chs / 2 - 1;
for (i = 0; i < chs; i++) {
- if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {
+ if (ice->pcm_reserved[i] &&
+ ice->pcm_reserved[i] != substream) {
up(&ice->open_mutex);
return -EBUSY;
}
@@ -504,7 +508,8 @@ static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
for (i = 0; i < 3; i++) {
/* check individual playback stream */
if (ice->playback_con_substream_ds[i] == substream) {
- if (ice->pcm_reserved[i] && ice->pcm_reserved[i] != substream) {
+ if (ice->pcm_reserved[i] &&
+ ice->pcm_reserved[i] != substream) {
up(&ice->open_mutex);
return -EBUSY;
}
@@ -518,9 +523,9 @@ static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_vt1724_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int i;
down(&ice->open_mutex);
@@ -532,9 +537,9 @@ static int snd_vt1724_pcm_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
-static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
unsigned char val;
unsigned int size;
@@ -559,9 +564,9 @@ static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & VT1724_PDMA0_START))
@@ -575,7 +580,8 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * s
ptr -= substream->runtime->dma_addr;
ptr = bytes_to_frames(substream->runtime, ptr);
if (ptr >= substream->runtime->buffer_size) {
- snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->period_size);
+ snd_printd("ice1724: invalid ptr %d (size=%d)\n",
+ (int)ptr, (int)substream->runtime->period_size);
return 0;
}
#else /* read PLAYBACK_SIZE */
@@ -587,29 +593,32 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * s
else if (ptr <= substream->runtime->buffer_size)
ptr = substream->runtime->buffer_size - ptr;
else {
- snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
+ snd_printd("ice1724: invalid ptr %d (size=%d)\n",
+ (int)ptr, (int)substream->runtime->buffer_size);
ptr = 0;
}
#endif
return ptr;
}
-static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
struct vt1724_pcm_reg *reg = substream->runtime->private_data;
spin_lock_irq(&ice->reg_lock);
outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);
- outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, ice->profi_port + reg->size);
- outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ice->profi_port + reg->count);
+ outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1,
+ ice->profi_port + reg->size);
+ outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1,
+ ice->profi_port + reg->count);
spin_unlock_irq(&ice->reg_lock);
return 0;
}
-static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
struct vt1724_pcm_reg *reg = substream->runtime->private_data;
size_t ptr;
@@ -628,7 +637,8 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream)
else if (ptr <= substream->runtime->buffer_size)
ptr = substream->runtime->buffer_size - ptr;
else {
- snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
+ snd_printd("ice1724: invalid ptr %d (size=%d)\n",
+ (int)ptr, (int)substream->runtime->buffer_size);
ptr = 0;
}
return ptr;
@@ -649,7 +659,7 @@ static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
.start = VT1724_RDMA0_START,
};
-static snd_pcm_hardware_t snd_vt1724_playback_pro =
+static struct snd_pcm_hardware snd_vt1724_playback_pro =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -668,7 +678,7 @@ static snd_pcm_hardware_t snd_vt1724_playback_pro =
.periods_max = 1024,
};
-static snd_pcm_hardware_t snd_vt1724_spdif =
+static struct snd_pcm_hardware snd_vt1724_spdif =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -690,7 +700,7 @@ static snd_pcm_hardware_t snd_vt1724_spdif =
.periods_max = 1024,
};
-static snd_pcm_hardware_t snd_vt1724_2ch_stereo =
+static struct snd_pcm_hardware snd_vt1724_2ch_stereo =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -712,31 +722,41 @@ static snd_pcm_hardware_t snd_vt1724_2ch_stereo =
/*
* set rate constraints
*/
-static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
+static int set_rate_constraints(struct snd_ice1712 *ice,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (ice->hw_rates) {
/* hardware specific */
runtime->hw.rate_min = ice->hw_rates->list[0];
runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
- return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, ice->hw_rates);
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ ice->hw_rates);
}
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
/* I2S */
/* VT1720 doesn't support more than 96kHz */
if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
- return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates_192);
else {
- runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000;
+ runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
+ SNDRV_PCM_RATE_8000_96000;
runtime->hw.rate_max = 96000;
- return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_96);
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates_96);
}
} else if (ice->ac97) {
/* ACLINK */
runtime->hw.rate_max = 48000;
runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
- return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates_48);
}
return 0;
}
@@ -746,10 +766,10 @@ static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
*/
#define VT1724_BUFFER_ALIGN 0x20
-static int snd_vt1724_playback_pro_open(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
int chs;
runtime->private_data = &vt1724_playback_pro_reg;
@@ -776,10 +796,10 @@ static int snd_vt1724_playback_pro_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_vt1724_capture_pro_open(snd_pcm_substream_t * substream)
+static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->private_data = &vt1724_capture_pro_reg;
ice->capture_pro_substream = substream;
@@ -794,9 +814,9 @@ static int snd_vt1724_capture_pro_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_vt1724_playback_pro_close(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -805,9 +825,9 @@ static int snd_vt1724_playback_pro_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_vt1724_capture_pro_close(snd_pcm_substream_t * substream)
+static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -815,7 +835,7 @@ static int snd_vt1724_capture_pro_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_vt1724_playback_pro_ops = {
+static struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
.open = snd_vt1724_playback_pro_open,
.close = snd_vt1724_playback_pro_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -826,7 +846,7 @@ static snd_pcm_ops_t snd_vt1724_playback_pro_ops = {
.pointer = snd_vt1724_playback_pro_pointer,
};
-static snd_pcm_ops_t snd_vt1724_capture_pro_ops = {
+static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
.open = snd_vt1724_capture_pro_open,
.close = snd_vt1724_capture_pro_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -837,9 +857,9 @@ static snd_pcm_ops_t snd_vt1724_capture_pro_ops = {
.pointer = snd_vt1724_pcm_pointer,
};
-static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device)
+static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 * ice, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(ice->card, "ICE1724", device, 1, 1, &pcm);
@@ -854,7 +874,8 @@ static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device)
strcpy(pcm->name, "ICE1724");
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(ice->pci), 256*1024, 256*1024);
+ snd_dma_pci_data(ice->pci),
+ 256*1024, 256*1024);
ice->pcm_pro = pcm;
@@ -881,7 +902,7 @@ static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
};
/* update spdif control bits; call with reg_lock */
-static void update_spdif_bits(ice1712_t *ice, unsigned int val)
+static void update_spdif_bits(struct snd_ice1712 *ice, unsigned int val)
{
unsigned char cbit, disabled;
@@ -896,7 +917,7 @@ static void update_spdif_bits(ice1712_t *ice, unsigned int val)
}
/* update SPDIF control bits according to the given rate */
-static void update_spdif_rate(ice1712_t *ice, unsigned int rate)
+static void update_spdif_rate(struct snd_ice1712 *ice, unsigned int rate)
{
unsigned int val, nval;
unsigned long flags;
@@ -918,18 +939,18 @@ static void update_spdif_rate(ice1712_t *ice, unsigned int rate)
spin_unlock_irqrestore(&ice->reg_lock, flags);
}
-static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_spdif_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (! ice->force_pdma4)
update_spdif_rate(ice, substream->runtime->rate);
return snd_vt1724_pcm_prepare(substream);
}
-static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
+static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->private_data = &vt1724_playback_spdif_reg;
ice->playback_con_substream = substream;
@@ -947,9 +968,9 @@ static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_vt1724_playback_spdif_close(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -958,10 +979,10 @@ static int snd_vt1724_playback_spdif_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_vt1724_capture_spdif_open(snd_pcm_substream_t *substream)
+static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
runtime->private_data = &vt1724_capture_spdif_reg;
ice->capture_con_substream = substream;
@@ -979,9 +1000,9 @@ static int snd_vt1724_capture_spdif_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_vt1724_capture_spdif_close(snd_pcm_substream_t * substream)
+static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -990,7 +1011,7 @@ static int snd_vt1724_capture_spdif_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_vt1724_playback_spdif_ops = {
+static struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
.open = snd_vt1724_playback_spdif_open,
.close = snd_vt1724_playback_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1001,7 +1022,7 @@ static snd_pcm_ops_t snd_vt1724_playback_spdif_ops = {
.pointer = snd_vt1724_pcm_pointer,
};
-static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {
+static struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
.open = snd_vt1724_capture_spdif_open,
.close = snd_vt1724_capture_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1013,10 +1034,10 @@ static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {
};
-static int __devinit snd_vt1724_pcm_spdif(ice1712_t * ice, int device)
+static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 * ice, int device)
{
char *name;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int play, capt;
int err;
@@ -1055,7 +1076,8 @@ static int __devinit snd_vt1724_pcm_spdif(ice1712_t * ice, int device)
strcpy(pcm->name, name);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(ice->pci), 64*1024, 64*1024);
+ snd_dma_pci_data(ice->pci),
+ 64*1024, 64*1024);
ice->pcm = pcm;
@@ -1088,9 +1110,9 @@ static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
},
};
-static int snd_vt1724_playback_indep_prepare(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_indep_prepare(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
unsigned char val;
spin_lock_irq(&ice->reg_lock);
@@ -1101,10 +1123,10 @@ static int snd_vt1724_playback_indep_prepare(snd_pcm_substream_t * substream)
return snd_vt1724_pcm_prepare(substream);
}
-static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
+static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
down(&ice->open_mutex);
/* already used by PDMA0? */
@@ -1122,9 +1144,9 @@ static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_vt1724_playback_indep_close(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
{
- ice1712_t *ice = snd_pcm_substream_chip(substream);
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
@@ -1134,7 +1156,7 @@ static int snd_vt1724_playback_indep_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_vt1724_playback_indep_ops = {
+static struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
.open = snd_vt1724_playback_indep_open,
.close = snd_vt1724_playback_indep_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1146,9 +1168,9 @@ static snd_pcm_ops_t snd_vt1724_playback_indep_ops = {
};
-static int __devinit snd_vt1724_pcm_indep(ice1712_t * ice, int device)
+static int __devinit snd_vt1724_pcm_indep(struct snd_ice1712 * ice, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int play;
int err;
@@ -1168,7 +1190,8 @@ static int __devinit snd_vt1724_pcm_indep(ice1712_t * ice, int device)
strcpy(pcm->name, "ICE1724 Surround PCM");
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(ice->pci), 64*1024, 64*1024);
+ snd_dma_pci_data(ice->pci),
+ 64*1024, 64*1024);
ice->pcm_ds = pcm;
@@ -1180,14 +1203,14 @@ static int __devinit snd_vt1724_pcm_indep(ice1712_t * ice, int device)
* Mixer section
*/
-static int __devinit snd_vt1724_ac97_mixer(ice1712_t * ice)
+static int __devinit snd_vt1724_ac97_mixer(struct snd_ice1712 * ice)
{
int err;
if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) {
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- static ac97_bus_ops_t ops = {
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ static struct snd_ac97_bus_ops ops = {
.write = snd_vt1724_ac97_write,
.read = snd_vt1724_ac97_read,
};
@@ -1215,17 +1238,17 @@ static int __devinit snd_vt1724_ac97_mixer(ice1712_t * ice)
*
*/
-static inline unsigned int eeprom_triple(ice1712_t *ice, int idx)
+static inline unsigned int eeprom_triple(struct snd_ice1712 *ice, int idx)
{
return (unsigned int)ice->eeprom.data[idx] | \
((unsigned int)ice->eeprom.data[idx + 1] << 8) | \
((unsigned int)ice->eeprom.data[idx + 2] << 16);
}
-static void snd_vt1724_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_vt1724_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ice1712_t *ice = entry->private_data;
+ struct snd_ice1712 *ice = entry->private_data;
unsigned int idx;
snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -1234,28 +1257,39 @@ static void snd_vt1724_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, " Subvendor : 0x%x\n", ice->eeprom.subvendor);
snd_iprintf(buffer, " Size : %i bytes\n", ice->eeprom.size);
snd_iprintf(buffer, " Version : %i\n", ice->eeprom.version);
- snd_iprintf(buffer, " System Config : 0x%x\n", ice->eeprom.data[ICE_EEP2_SYSCONF]);
- snd_iprintf(buffer, " ACLink : 0x%x\n", ice->eeprom.data[ICE_EEP2_ACLINK]);
- snd_iprintf(buffer, " I2S : 0x%x\n", ice->eeprom.data[ICE_EEP2_I2S]);
- snd_iprintf(buffer, " S/PDIF : 0x%x\n", ice->eeprom.data[ICE_EEP2_SPDIF]);
- snd_iprintf(buffer, " GPIO direction : 0x%x\n", ice->eeprom.gpiodir);
- snd_iprintf(buffer, " GPIO mask : 0x%x\n", ice->eeprom.gpiomask);
- snd_iprintf(buffer, " GPIO state : 0x%x\n", ice->eeprom.gpiostate);
+ snd_iprintf(buffer, " System Config : 0x%x\n",
+ ice->eeprom.data[ICE_EEP2_SYSCONF]);
+ snd_iprintf(buffer, " ACLink : 0x%x\n",
+ ice->eeprom.data[ICE_EEP2_ACLINK]);
+ snd_iprintf(buffer, " I2S : 0x%x\n",
+ ice->eeprom.data[ICE_EEP2_I2S]);
+ snd_iprintf(buffer, " S/PDIF : 0x%x\n",
+ ice->eeprom.data[ICE_EEP2_SPDIF]);
+ snd_iprintf(buffer, " GPIO direction : 0x%x\n",
+ ice->eeprom.gpiodir);
+ snd_iprintf(buffer, " GPIO mask : 0x%x\n",
+ ice->eeprom.gpiomask);
+ snd_iprintf(buffer, " GPIO state : 0x%x\n",
+ ice->eeprom.gpiostate);
for (idx = 0x12; idx < ice->eeprom.size; idx++)
- snd_iprintf(buffer, " Extra #%02i : 0x%x\n", idx, ice->eeprom.data[idx]);
+ snd_iprintf(buffer, " Extra #%02i : 0x%x\n",
+ idx, ice->eeprom.data[idx]);
snd_iprintf(buffer, "\nRegisters:\n");
- snd_iprintf(buffer, " PSDOUT03 : 0x%08x\n", (unsigned)inl(ICEMT1724(ice, ROUTE_PLAYBACK)));
+ snd_iprintf(buffer, " PSDOUT03 : 0x%08x\n",
+ (unsigned)inl(ICEMT1724(ice, ROUTE_PLAYBACK)));
for (idx = 0x0; idx < 0x20 ; idx++)
- snd_iprintf(buffer, " CCS%02x : 0x%02x\n", idx, inb(ice->port+idx));
+ snd_iprintf(buffer, " CCS%02x : 0x%02x\n",
+ idx, inb(ice->port+idx));
for (idx = 0x0; idx < 0x30 ; idx++)
- snd_iprintf(buffer, " MT%02x : 0x%02x\n", idx, inb(ice->profi_port+idx));
+ snd_iprintf(buffer, " MT%02x : 0x%02x\n",
+ idx, inb(ice->profi_port+idx));
}
-static void __devinit snd_vt1724_proc_init(ice1712_t * ice)
+static void __devinit snd_vt1724_proc_init(struct snd_ice1712 * ice)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(ice->card, "ice1724", &entry))
snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read);
@@ -1265,22 +1299,24 @@ static void __devinit snd_vt1724_proc_init(ice1712_t * ice)
*
*/
-static int snd_vt1724_eeprom_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_eeprom_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = sizeof(ice1712_eeprom_t);
+ uinfo->count = sizeof(struct snd_ice1712_eeprom);
return 0;
}
-static int snd_vt1724_eeprom_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
memcpy(ucontrol->value.bytes.data, &ice->eeprom, sizeof(ice->eeprom));
return 0;
}
-static snd_kcontrol_new_t snd_vt1724_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "ICE1724 EEPROM",
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1290,21 +1326,23 @@ static snd_kcontrol_new_t snd_vt1724_eeprom __devinitdata = {
/*
*/
-static int snd_vt1724_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga)
+static unsigned int encode_spdif_bits(struct snd_aes_iec958 *diga)
{
unsigned int val, rbits;
val = diga->status[0] & 0x03; /* professional, non-audio */
if (val & 0x01) {
/* professional */
- if ((diga->status[0] & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)
+ if ((diga->status[0] & IEC958_AES0_PRO_EMPHASIS) ==
+ IEC958_AES0_PRO_EMPHASIS_5015)
val |= 1U << 3;
rbits = (diga->status[4] >> 3) & 0x0f;
if (rbits) {
@@ -1329,7 +1367,8 @@ static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga)
} else {
/* consumer */
val |= diga->status[1] & 0x04; /* copyright */
- if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS)== IEC958_AES0_CON_EMPHASIS_5015)
+ if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS) ==
+ IEC958_AES0_CON_EMPHASIS_5015)
val |= 1U << 3;
val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */
val |= (unsigned int)(diga->status[3] & IEC958_AES3_CON_FS) << 12; /* fs */
@@ -1337,7 +1376,7 @@ static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga)
return val;
}
-static void decode_spdif_bits(snd_aes_iec958_t *diga, unsigned int val)
+static void decode_spdif_bits(struct snd_aes_iec958 *diga, unsigned int val)
{
memset(diga->status, 0, sizeof(diga->status));
diga->status[0] = val & 0x03; /* professional, non-audio */
@@ -1365,20 +1404,20 @@ static void decode_spdif_bits(snd_aes_iec958_t *diga, unsigned int val)
}
}
-static int snd_vt1724_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned int val;
val = inw(ICEMT1724(ice, SPDIF_CTRL));
decode_spdif_bits(&ucontrol->value.iec958, val);
return 0;
}
-static int snd_vt1724_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned int val, old;
val = encode_spdif_bits(&ucontrol->value.iec958);
@@ -1390,7 +1429,7 @@ static int snd_vt1724_spdif_default_put(snd_kcontrol_t * kcontrol,
return (val != old);
}
-static snd_kcontrol_new_t snd_vt1724_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1399,8 +1438,8 @@ static snd_kcontrol_new_t snd_vt1724_spdif_default __devinitdata =
.put = snd_vt1724_spdif_default_put
};
-static int snd_vt1724_spdif_maskc_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_maskc_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO |
IEC958_AES0_PROFESSIONAL |
@@ -1412,8 +1451,8 @@ static int snd_vt1724_spdif_maskc_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_vt1724_spdif_maskp_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO |
IEC958_AES0_PROFESSIONAL |
@@ -1422,7 +1461,7 @@ static int snd_vt1724_spdif_maskp_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_vt1724_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1431,7 +1470,7 @@ static snd_kcontrol_new_t snd_vt1724_spdif_maskc __devinitdata =
.get = snd_vt1724_spdif_maskc_get,
};
-static snd_kcontrol_new_t snd_vt1724_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1440,7 +1479,8 @@ static snd_kcontrol_new_t snd_vt1724_spdif_maskp __devinitdata =
.get = snd_vt1724_spdif_maskp_get,
};
-static int snd_vt1724_spdif_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_spdif_sw_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1449,16 +1489,19 @@ static int snd_vt1724_spdif_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_vt1724_spdif_sw_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = inb(ICEREG1724(ice, SPDIF_CFG)) & VT1724_CFG_SPDIF_OUT_EN ? 1 : 0;
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = inb(ICEREG1724(ice, SPDIF_CFG)) &
+ VT1724_CFG_SPDIF_OUT_EN ? 1 : 0;
return 0;
}
-static int snd_vt1724_spdif_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char old, val;
spin_lock_irq(&ice->reg_lock);
@@ -1472,7 +1515,7 @@ static int snd_vt1724_spdif_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
return old != val;
}
-static snd_kcontrol_new_t snd_vt1724_spdif_switch __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* FIXME: the following conflict with IEC958 Playback Route */
@@ -1489,7 +1532,8 @@ static snd_kcontrol_new_t snd_vt1724_spdif_switch __devinitdata =
* GPIO access from extern
*/
-int snd_vt1724_gpio_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_vt1724_gpio_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1498,21 +1542,24 @@ int snd_vt1724_gpio_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
return 0;
}
-int snd_vt1724_gpio_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_vt1724_gpio_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? 1 : 0;
snd_ice1712_save_gpio_status(ice);
- ucontrol->value.integer.value[0] = (snd_ice1712_gpio_read(ice) & (1 << shift) ? 1 : 0) ^ invert;
+ ucontrol->value.integer.value[0] =
+ (snd_ice1712_gpio_read(ice) & (1 << shift) ? 1 : 0) ^ invert;
snd_ice1712_restore_gpio_status(ice);
return 0;
}
-int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int shift = kcontrol->private_value & 0xff;
int invert = (kcontrol->private_value & (1<<24)) ? mask : 0;
unsigned int val, nval;
@@ -1533,7 +1580,8 @@ int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucont
/*
* rate
*/
-static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts_1724[] = {
"8000", /* 0: 6 */
@@ -1569,7 +1617,7 @@ static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_
"96000", /* 12: 7 */
"IEC958 Input", /* 13: -- */
};
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1582,9 +1630,10 @@ static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_vt1724_pro_internal_clock_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
static unsigned char xlate[16] = {
9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
};
@@ -1605,9 +1654,10 @@ static int snd_vt1724_pro_internal_clock_get(snd_kcontrol_t * kcontrol, snd_ctl_
return 0;
}
-static int snd_vt1724_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char oval;
int rate;
int change = 0;
@@ -1629,7 +1679,8 @@ static int snd_vt1724_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_
change = inb(ICEMT1724(ice, RATE)) != oval;
spin_unlock_irq(&ice->reg_lock);
- if ((oval & VT1724_SPDIF_MASTER) != (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
+ if ((oval & VT1724_SPDIF_MASTER) !=
+ (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
/* notify akm chips as well */
if (is_spdif_master(ice)) {
unsigned int i;
@@ -1642,7 +1693,7 @@ static int snd_vt1724_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_
return change;
}
-static snd_kcontrol_new_t snd_vt1724_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Internal Clock",
.info = snd_vt1724_pro_internal_clock_info,
@@ -1650,7 +1701,8 @@ static snd_kcontrol_new_t snd_vt1724_pro_internal_clock __devinitdata = {
.put = snd_vt1724_pro_internal_clock_put
};
-static int snd_vt1724_pro_rate_locking_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_pro_rate_locking_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1659,15 +1711,17 @@ static int snd_vt1724_pro_rate_locking_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_vt1724_pro_rate_locking_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_rate_locking_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = PRO_RATE_LOCKED;
return 0;
}
-static int snd_vt1724_pro_rate_locking_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, nval;
nval = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1678,7 +1732,7 @@ static int snd_vt1724_pro_rate_locking_put(snd_kcontrol_t * kcontrol, snd_ctl_el
return change;
}
-static snd_kcontrol_new_t snd_vt1724_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Locking",
.info = snd_vt1724_pro_rate_locking_info,
@@ -1686,7 +1740,8 @@ static snd_kcontrol_new_t snd_vt1724_pro_rate_locking __devinitdata = {
.put = snd_vt1724_pro_rate_locking_put
};
-static int snd_vt1724_pro_rate_reset_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_pro_rate_reset_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1695,15 +1750,17 @@ static int snd_vt1724_pro_rate_reset_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_vt1724_pro_rate_reset_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_rate_reset_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = PRO_RATE_RESET ? 1 : 0;
return 0;
}
-static int snd_vt1724_pro_rate_reset_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, nval;
nval = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1714,7 +1771,7 @@ static int snd_vt1724_pro_rate_reset_put(snd_kcontrol_t * kcontrol, snd_ctl_elem
return change;
}
-static snd_kcontrol_new_t snd_vt1724_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Rate Reset",
.info = snd_vt1724_pro_rate_reset_info,
@@ -1726,7 +1783,8 @@ static snd_kcontrol_new_t snd_vt1724_pro_rate_reset __devinitdata = {
/*
* routing
*/
-static int snd_vt1724_pro_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_pro_route_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"PCM Out", /* 0 */
@@ -1753,7 +1811,7 @@ static inline int digital_route_shift(int idx)
return idx * 3;
}
-static int get_route_val(ice1712_t *ice, int shift)
+static int get_route_val(struct snd_ice1712 *ice, int shift)
{
unsigned long val;
unsigned char eitem;
@@ -1772,7 +1830,7 @@ static int get_route_val(ice1712_t *ice, int shift)
return eitem;
}
-static int put_route_val(ice1712_t *ice, unsigned int val, int shift)
+static int put_route_val(struct snd_ice1712 *ice, unsigned int val, int shift)
{
unsigned int old_val, nval;
int change;
@@ -1794,39 +1852,45 @@ static int put_route_val(ice1712_t *ice, unsigned int val, int shift)
return change;
}
-static int snd_vt1724_pro_route_analog_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_vt1724_pro_route_analog_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- ucontrol->value.enumerated.item[0] = get_route_val(ice, analog_route_shift(idx));
+ ucontrol->value.enumerated.item[0] =
+ get_route_val(ice, analog_route_shift(idx));
return 0;
}
-static int snd_vt1724_pro_route_analog_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_vt1724_pro_route_analog_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
return put_route_val(ice, ucontrol->value.enumerated.item[0],
analog_route_shift(idx));
}
-static int snd_vt1724_pro_route_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_vt1724_pro_route_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- ucontrol->value.enumerated.item[0] = get_route_val(ice, digital_route_shift(idx));
+ ucontrol->value.enumerated.item[0] =
+ get_route_val(ice, digital_route_shift(idx));
return 0;
}
-static int snd_vt1724_pro_route_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
return put_route_val(ice, ucontrol->value.enumerated.item[0],
digital_route_shift(idx));
}
-static snd_kcontrol_new_t snd_vt1724_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
.info = snd_vt1724_pro_route_info,
@@ -1834,7 +1898,7 @@ static snd_kcontrol_new_t snd_vt1724_mixer_pro_analog_route __devinitdata = {
.put = snd_vt1724_pro_route_analog_put,
};
-static snd_kcontrol_new_t snd_vt1724_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
.info = snd_vt1724_pro_route_info,
@@ -1844,7 +1908,8 @@ static snd_kcontrol_new_t snd_vt1724_mixer_pro_spdif_route __devinitdata = {
};
-static int snd_vt1724_pro_peak_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_vt1724_pro_peak_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 22; /* FIXME: for compatibility with ice1712... */
@@ -1853,21 +1918,23 @@ static int snd_vt1724_pro_peak_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_vt1724_pro_peak_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx;
spin_lock_irq(&ice->reg_lock);
for (idx = 0; idx < 22; idx++) {
outb(idx, ICEMT1724(ice, MONITOR_PEAKINDEX));
- ucontrol->value.integer.value[idx] = inb(ICEMT1724(ice, MONITOR_PEAKDATA));
+ ucontrol->value.integer.value[idx] =
+ inb(ICEMT1724(ice, MONITOR_PEAKDATA));
}
spin_unlock_irq(&ice->reg_lock);
return 0;
}
-static snd_kcontrol_new_t snd_vt1724_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Multi Track Peak",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1897,7 +1964,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
/*
*/
-static void wait_i2c_busy(ice1712_t *ice)
+static void wait_i2c_busy(struct snd_ice1712 *ice)
{
int t = 0x10000;
while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)
@@ -1906,7 +1973,8 @@ static void wait_i2c_busy(ice1712_t *ice)
printk(KERN_ERR "ice1724: i2c busy timeout\n");
}
-unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
+unsigned char snd_vt1724_read_i2c(struct snd_ice1712 *ice,
+ unsigned char dev, unsigned char addr)
{
unsigned char val;
@@ -1920,7 +1988,8 @@ unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned ch
return val;
}
-void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data)
+void snd_vt1724_write_i2c(struct snd_ice1712 *ice,
+ unsigned char dev, unsigned char addr, unsigned char data)
{
down(&ice->i2c_mutex);
wait_i2c_busy(ice);
@@ -1932,7 +2001,8 @@ void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr,
up(&ice->i2c_mutex);
}
-static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname)
+static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
+ const char *modelname)
{
const int dev = 0xa0; /* EEPROM device address */
unsigned int i, size;
@@ -1946,13 +2016,19 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam
(snd_vt1724_read_i2c(ice, dev, 0x01) << 8) |
(snd_vt1724_read_i2c(ice, dev, 0x02) << 16) |
(snd_vt1724_read_i2c(ice, dev, 0x03) << 24);
- if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {
- /* invalid subvendor from EEPROM, try the PCI subststem ID instead */
+ if (ice->eeprom.subvendor == 0 ||
+ ice->eeprom.subvendor == (unsigned int)-1) {
+ /* invalid subvendor from EEPROM, try the PCI
+ * subststem ID instead
+ */
u16 vendor, device;
- pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
+ pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID,
+ &vendor);
pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device);
- ice->eeprom.subvendor = ((unsigned int)swab16(vendor) << 16) | swab16(device);
- if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {
+ ice->eeprom.subvendor =
+ ((unsigned int)swab16(vendor) << 16) | swab16(device);
+ if (ice->eeprom.subvendor == 0 ||
+ ice->eeprom.subvendor == (unsigned int)-1) {
printk(KERN_ERR "ice1724: No valid ID is found\n");
return -ENXIO;
}
@@ -1960,8 +2036,10 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam
}
for (tbl = card_tables; *tbl; tbl++) {
for (c = *tbl; c->subvendor; c++) {
- if (modelname && c->model && ! strcmp(modelname, c->model)) {
- printk(KERN_INFO "ice1724: Using board model %s\n", c->name);
+ if (modelname && c->model &&
+ ! strcmp(modelname, c->model)) {
+ printk(KERN_INFO "ice1724: Using board model %s\n",
+ c->name);
ice->eeprom.subvendor = c->subvendor;
} else if (c->subvendor != ice->eeprom.subvendor)
continue;
@@ -1975,19 +2053,22 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam
goto read_skipped;
}
}
- printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n", ice->eeprom.subvendor);
+ printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n",
+ ice->eeprom.subvendor);
found:
ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04);
if (ice->eeprom.size < 6)
ice->eeprom.size = 32;
else if (ice->eeprom.size > 32) {
- printk(KERN_ERR "ice1724: Invalid EEPROM (size = %i)\n", ice->eeprom.size);
+ printk(KERN_ERR "ice1724: Invalid EEPROM (size = %i)\n",
+ ice->eeprom.size);
return -EIO;
}
ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05);
if (ice->eeprom.version != 2)
- printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n", ice->eeprom.version);
+ printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n",
+ ice->eeprom.version);
size = ice->eeprom.size - 6;
for (i = 0; i < size; i++)
ice->eeprom.data[i] = snd_vt1724_read_i2c(ice, dev, i + 6);
@@ -2002,7 +2083,7 @@ static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelnam
-static int __devinit snd_vt1724_chip_init(ice1712_t *ice)
+static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
{
outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
udelay(200);
@@ -2024,10 +2105,10 @@ static int __devinit snd_vt1724_chip_init(ice1712_t *ice)
return 0;
}
-static int __devinit snd_vt1724_spdif_build_controls(ice1712_t *ice)
+static int __devinit snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
{
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
snd_assert(ice->pcm != NULL, return -EIO);
@@ -2062,7 +2143,7 @@ static int __devinit snd_vt1724_spdif_build_controls(ice1712_t *ice)
}
-static int __devinit snd_vt1724_build_controls(ice1712_t *ice)
+static int __devinit snd_vt1724_build_controls(struct snd_ice1712 *ice)
{
int err;
@@ -2081,7 +2162,7 @@ static int __devinit snd_vt1724_build_controls(ice1712_t *ice)
return err;
if (ice->num_total_dacs > 0) {
- snd_kcontrol_new_t tmp = snd_vt1724_mixer_pro_analog_route;
+ struct snd_kcontrol_new tmp = snd_vt1724_mixer_pro_analog_route;
tmp.count = ice->num_total_dacs;
if (ice->vt1720 && tmp.count > 2)
tmp.count = 2;
@@ -2097,7 +2178,7 @@ static int __devinit snd_vt1724_build_controls(ice1712_t *ice)
return 0;
}
-static int snd_vt1724_free(ice1712_t *ice)
+static int snd_vt1724_free(struct snd_ice1712 *ice)
{
if (! ice->port)
goto __hw_end;
@@ -2108,7 +2189,7 @@ static int snd_vt1724_free(ice1712_t *ice)
__hw_end:
if (ice->irq >= 0) {
synchronize_irq(ice->irq);
- free_irq(ice->irq, (void *) ice);
+ free_irq(ice->irq, ice);
}
pci_release_regions(ice->pci);
snd_ice1712_akm4xxx_free(ice);
@@ -2117,21 +2198,21 @@ static int snd_vt1724_free(ice1712_t *ice)
return 0;
}
-static int snd_vt1724_dev_free(snd_device_t *device)
+static int snd_vt1724_dev_free(struct snd_device *device)
{
- ice1712_t *ice = device->device_data;
+ struct snd_ice1712 *ice = device->device_data;
return snd_vt1724_free(ice);
}
-static int __devinit snd_vt1724_create(snd_card_t * card,
+static int __devinit snd_vt1724_create(struct snd_card *card,
struct pci_dev *pci,
const char *modelname,
- ice1712_t ** r_ice1712)
+ struct snd_ice1712 ** r_ice1712)
{
- ice1712_t *ice;
+ struct snd_ice1712 *ice;
int err;
unsigned char mask;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_vt1724_dev_free,
};
@@ -2170,7 +2251,8 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
ice->port = pci_resource_start(pci, 0);
ice->profi_port = pci_resource_start(pci, 1);
- if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) {
+ if (request_irq(pci->irq, snd_vt1724_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, "ICE1724", ice)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_vt1724_free(ice);
return -EIO;
@@ -2193,7 +2275,9 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
else
mask = 0;
outb(mask, ICEREG1724(ice, IRQMASK));
- /* don't handle FIFO overrun/underruns (just yet), since they cause machine lockups */
+ /* don't handle FIFO overrun/underruns (just yet),
+ * since they cause machine lockups
+ */
outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK));
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops)) < 0) {
@@ -2218,8 +2302,8 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- ice1712_t *ice;
+ struct snd_card *card;
+ struct snd_ice1712 *ice;
int pcm_dev = 0, err;
struct snd_ice1712_card_info **tbl, *c;
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 2437876a44e4..5176b41ea9d3 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -65,30 +65,30 @@
static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
{
- snd_vt1724_write_i2c((ice1712_t *)private_data, AK4114_ADDR, reg, val);
+ snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, reg, val);
}
static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
{
- return snd_vt1724_read_i2c((ice1712_t *)private_data, AK4114_ADDR, reg);
+ return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, AK4114_ADDR, reg);
}
/*
* AK4358 section
*/
-static void juli_akm_lock(akm4xxx_t *ak, int chip)
+static void juli_akm_lock(struct snd_akm4xxx *ak, int chip)
{
}
-static void juli_akm_unlock(akm4xxx_t *ak, int chip)
+static void juli_akm_unlock(struct snd_akm4xxx *ak, int chip)
{
}
-static void juli_akm_write(akm4xxx_t *ak, int chip,
+static void juli_akm_write(struct snd_akm4xxx *ak, int chip,
unsigned char addr, unsigned char data)
{
- ice1712_t *ice = ak->private_data[0];
+ struct snd_ice1712 *ice = ak->private_data[0];
snd_assert(chip == 0, return);
snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data);
@@ -97,7 +97,7 @@ static void juli_akm_write(akm4xxx_t *ak, int chip,
/*
* change the rate of envy24HT, AK4358
*/
-static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
{
unsigned char old, tmp, dfs;
@@ -125,7 +125,7 @@ static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate)
snd_akm4xxx_reset(ak, 0);
}
-static akm4xxx_t akm_juli_dac __devinitdata = {
+static struct snd_akm4xxx akm_juli_dac __devinitdata = {
.type = SND_AK4358,
.num_dacs = 2,
.ops = {
@@ -136,7 +136,7 @@ static akm4xxx_t akm_juli_dac __devinitdata = {
}
};
-static int __devinit juli_add_controls(ice1712_t *ice)
+static int __devinit juli_add_controls(struct snd_ice1712 *ice)
{
return snd_ice1712_akm4xxx_build_controls(ice);
}
@@ -144,7 +144,7 @@ static int __devinit juli_add_controls(ice1712_t *ice)
/*
* initialize the chip
*/
-static int __devinit juli_init(ice1712_t *ice)
+static int __devinit juli_init(struct snd_ice1712 *ice)
{
static unsigned char ak4114_init_vals[] = {
/* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
@@ -158,7 +158,7 @@ static int __devinit juli_init(ice1712_t *ice)
0x41, 0x02, 0x2c, 0x00, 0x00
};
int err;
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
#if 0
for (err = 0; err < 0x20; err++)
@@ -175,14 +175,21 @@ static int __devinit juli_init(ice1712_t *ice)
if (err < 0)
return err;
- ice->spec.juli.analog = ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT;
+#if 0
+ /* it seems that the analog doughter board detection does not work
+ reliably, so force the analog flag; it should be very rare
+ to use Juli@ without the analog doughter board */
+ ice->spec.juli.analog = (ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT) ? 0 : 1;
+#else
+ ice->spec.juli.analog = 1;
+#endif
if (ice->spec.juli.analog) {
printk(KERN_INFO "juli@: analog I/O detected\n");
ice->num_total_dacs = 2;
ice->num_total_adcs = 2;
- ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), 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 dcf1e8ca3f66..ec3757834b93 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -86,7 +86,7 @@ static unsigned char wm_vol[256] = {
#define WM_VOL_MAX (sizeof(wm_vol) - 1)
#define WM_VOL_MUTE 0x8000
-static akm4xxx_t akm_phase22 __devinitdata = {
+static struct snd_akm4xxx akm_phase22 __devinitdata = {
.type = SND_AK4524,
.num_dacs = 2,
.num_adcs = 2,
@@ -104,9 +104,9 @@ static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
.mask_flags = 0,
};
-static int __devinit phase22_init(ice1712_t *ice)
+static int __devinit phase22_init(struct snd_ice1712 *ice)
{
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
int err;
// Configure DAC/ADC description for generic part of ice1724
@@ -122,7 +122,7 @@ static int __devinit phase22_init(ice1712_t *ice)
}
// Initialize analog chips
- ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -136,7 +136,7 @@ static int __devinit phase22_init(ice1712_t *ice)
return 0;
}
-static int __devinit phase22_add_controls(ice1712_t *ice)
+static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
{
int err = 0;
@@ -184,7 +184,7 @@ static unsigned char phase28_eeprom[] __devinitdata = {
/*
* write data in the SPI mode
*/
-static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
+static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
{
unsigned int tmp;
int i;
@@ -225,7 +225,7 @@ static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data
/*
* get the current register value of WM codec
*/
-static unsigned short wm_get(ice1712_t *ice, int reg)
+static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
{
reg <<= 1;
return ((unsigned short)ice->akm[0].images[reg] << 8) |
@@ -235,7 +235,7 @@ static unsigned short wm_get(ice1712_t *ice, int reg)
/*
* set the register value of WM codec
*/
-static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
{
phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
}
@@ -243,7 +243,7 @@ static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
/*
* set the register value of WM codec and remember it
*/
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
{
wm_put_nocache(ice, reg, val);
reg <<= 1;
@@ -251,7 +251,7 @@ static void wm_put(ice1712_t *ice, int reg, unsigned short val)
ice->akm[0].images[reg + 1] = val;
}
-static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
{
unsigned char nvol;
@@ -269,9 +269,9 @@ static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, u
*/
#define wm_pcm_mute_info phase28_mono_bool_info
-static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
@@ -279,9 +279,9 @@ static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short nval, oval;
int change;
@@ -298,7 +298,7 @@ static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
/*
* Master volume attenuation mixer control
*/
-static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -307,18 +307,18 @@ static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i;
for (i=0; i<2; i++)
ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
return 0;
}
-static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int ch, change = 0;
snd_ice1712_save_gpio_status(ice);
@@ -338,7 +338,7 @@ static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return change;
}
-static int __devinit phase28_init(ice1712_t *ice)
+static int __devinit phase28_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits_phase28[] = {
/* These come first to reduce init pop noise */
@@ -378,7 +378,7 @@ static int __devinit phase28_init(ice1712_t *ice)
};
unsigned int tmp;
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
unsigned short *p;
int i;
@@ -386,7 +386,7 @@ static int __devinit phase28_init(ice1712_t *ice)
ice->num_total_adcs = 2;
// Initialize analog chips
- ak = ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (!ak)
return -ENOMEM;
ice->akm_codecs = 1;
@@ -427,7 +427,7 @@ static int __devinit phase28_init(ice1712_t *ice)
/*
* DAC volume attenuation mixer control
*/
-static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int voices = kcontrol->private_value >> 8;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -437,9 +437,9 @@ static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, ofs, voices;
voices = kcontrol->private_value >> 8;
@@ -449,9 +449,9 @@ static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
return 0;
}
-static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, idx, ofs, voices;
int change = 0;
@@ -475,7 +475,7 @@ static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
/*
* WM8770 mute control
*/
-static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = kcontrol->private_value >> 8;
uinfo->value.integer.min = 0;
@@ -483,9 +483,9 @@ static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
return 0;
}
-static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int voices, ofs, i;
voices = kcontrol->private_value >> 8;
@@ -496,9 +496,9 @@ static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
return 0;
}
-static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, voices, ofs, i;
voices = kcontrol->private_value >> 8;
@@ -524,7 +524,7 @@ static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontro
/*
* WM8770 master mute control
*/
-static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
uinfo->value.integer.min = 0;
@@ -532,18 +532,18 @@ static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
return 0;
}
-static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
return 0;
}
-static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int change = 0, i;
snd_ice1712_save_gpio_status(ice);
@@ -570,7 +570,7 @@ static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
#define PCM_0dB 0xff
#define PCM_RES 128 /* -64dB */
#define PCM_MIN (PCM_0dB - PCM_RES)
-static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -579,9 +579,9 @@ static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
down(&ice->gpio_mutex);
@@ -592,9 +592,9 @@ static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int change = 0;
@@ -613,7 +613,7 @@ static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
/*
*/
-static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -627,16 +627,16 @@ static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
*/
#define phase28_deemp_info phase28_mono_bool_info
-static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
return 0;
}
-static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int phase28_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int temp, temp2;
temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
if (ucontrol->value.integer.value[0])
@@ -653,7 +653,7 @@ static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
/*
* ADC Oversampling
*/
-static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int phase28_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "128x", "64x" };
@@ -668,17 +668,17 @@ static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uin
return 0;
}
-static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int phase28_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
return 0;
}
-static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int temp, temp2;
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
temp2 = temp = wm_get(ice, WM_MASTER);
@@ -694,7 +694,7 @@ static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return 0;
}
-static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -791,7 +791,7 @@ static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
}
};
-static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
@@ -822,7 +822,7 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = {
}
};
-static int __devinit phase28_add_controls(ice1712_t *ice)
+static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
{
unsigned int i, counts;
int err;
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 773a1ecb75ce..0dccd7707a4b 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -76,7 +76,7 @@
/*
* get the current register value of WM codec
*/
-static unsigned short wm_get(ice1712_t *ice, int reg)
+static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
{
reg <<= 1;
return ((unsigned short)ice->akm[0].images[reg] << 8) |
@@ -86,14 +86,14 @@ static unsigned short wm_get(ice1712_t *ice, int reg)
/*
* set the register value of WM codec and remember it
*/
-static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
{
unsigned short cval;
cval = (reg << 9) | val;
snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
}
-static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
{
wm_put_nocache(ice, reg, val);
reg <<= 1;
@@ -109,7 +109,7 @@ static void wm_put(ice1712_t *ice, int reg, unsigned short val)
#define DAC_RES 128
#define DAC_MIN (DAC_0dB - DAC_RES)
-static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -118,9 +118,9 @@ static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
int i;
@@ -134,9 +134,9 @@ static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short oval, nval;
int i, idx, change = 0;
@@ -164,7 +164,7 @@ static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
#define ADC_RES 128
#define ADC_MIN (ADC_0dB - ADC_RES)
-static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -173,9 +173,9 @@ static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val;
int i;
@@ -189,9 +189,9 @@ static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short ovol, nvol;
int i, idx, change = 0;
@@ -213,7 +213,7 @@ static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
/*
* ADC input mux mixer control
*/
-static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -222,9 +222,9 @@ static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int bit = kcontrol->private_value;
down(&ice->gpio_mutex);
@@ -233,9 +233,9 @@ static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int bit = kcontrol->private_value;
unsigned short oval, nval;
int change;
@@ -257,7 +257,7 @@ static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucont
/*
* Analog bypass (In -> Out)
*/
-static int wm_bypass_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_bypass_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -266,9 +266,9 @@ static int wm_bypass_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_bypass_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_bypass_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
@@ -276,9 +276,9 @@ static int wm_bypass_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_bypass_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_bypass_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val, oval;
int change = 0;
@@ -299,7 +299,7 @@ static int wm_bypass_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontr
/*
* Left/Right swap
*/
-static int wm_chswap_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int wm_chswap_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -308,9 +308,9 @@ static int wm_chswap_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int wm_chswap_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_chswap_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
@@ -318,9 +318,9 @@ static int wm_chswap_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-static int wm_chswap_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int wm_chswap_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned short val, oval;
int change = 0;
@@ -343,7 +343,7 @@ static int wm_chswap_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontr
/*
* write data in the SPI mode
*/
-static void set_gpio_bit(ice1712_t *ice, unsigned int bit, int val)
+static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)
{
unsigned int tmp = snd_ice1712_gpio_read(ice);
if (val)
@@ -353,7 +353,7 @@ static void set_gpio_bit(ice1712_t *ice, unsigned int bit, int val)
snd_ice1712_gpio_write(ice, tmp);
}
-static void spi_send_byte(ice1712_t *ice, unsigned char data)
+static void spi_send_byte(struct snd_ice1712 *ice, unsigned char data)
{
int i;
for (i = 0; i < 8; i++) {
@@ -367,7 +367,7 @@ static void spi_send_byte(ice1712_t *ice, unsigned char data)
}
}
-static unsigned int spi_read_byte(ice1712_t *ice)
+static unsigned int spi_read_byte(struct snd_ice1712 *ice)
{
int i;
unsigned int val = 0;
@@ -386,7 +386,7 @@ static unsigned int spi_read_byte(ice1712_t *ice)
}
-static void spi_write(ice1712_t *ice, unsigned int dev, unsigned int reg, unsigned int data)
+static void spi_write(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg, unsigned int data)
{
snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
snd_ice1712_gpio_set_mask(ice, ~(PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK));
@@ -402,7 +402,7 @@ static void spi_write(ice1712_t *ice, unsigned int dev, unsigned int reg, unsign
snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
}
-static unsigned int spi_read(ice1712_t *ice, unsigned int dev, unsigned int reg)
+static unsigned int spi_read(struct snd_ice1712 *ice, unsigned int dev, unsigned int reg)
{
unsigned int val;
snd_ice1712_gpio_set_dir(ice, PONTIS_CS_CS|PONTIS_CS_WDATA|PONTIS_CS_CLK);
@@ -429,7 +429,7 @@ static unsigned int spi_read(ice1712_t *ice, unsigned int dev, unsigned int reg)
/*
* SPDIF input source
*/
-static int cs_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {
"Coax", /* RXP0 */
@@ -445,9 +445,9 @@ static int cs_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int cs_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cs_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
ucontrol->value.enumerated.item[0] = ice->gpio.saved[0];
@@ -455,9 +455,9 @@ static int cs_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro
return 0;
}
-static int cs_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int cs_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char val;
int change = 0;
@@ -476,7 +476,7 @@ static int cs_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontro
/*
* GPIO controls
*/
-static int pontis_gpio_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int pontis_gpio_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -485,9 +485,9 @@ static int pontis_gpio_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int pontis_gpio_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
/* 4-7 reserved */
ucontrol->value.integer.value[0] = (~ice->gpio.write_mask & 0xffff) | 0x00f0;
@@ -495,9 +495,9 @@ static int pontis_gpio_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int pontis_gpio_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_mask_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned int val;
int changed;
down(&ice->gpio_mutex);
@@ -509,9 +509,9 @@ static int pontis_gpio_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return changed;
}
-static int pontis_gpio_dir_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_dir_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
/* 4-7 reserved */
ucontrol->value.integer.value[0] = ice->gpio.direction & 0xff0f;
@@ -519,9 +519,9 @@ static int pontis_gpio_dir_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int pontis_gpio_dir_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_dir_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned int val;
int changed;
down(&ice->gpio_mutex);
@@ -533,9 +533,9 @@ static int pontis_gpio_dir_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return changed;
}
-static int pontis_gpio_data_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
down(&ice->gpio_mutex);
snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
@@ -544,9 +544,9 @@ static int pontis_gpio_data_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int pontis_gpio_data_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned int val, nval;
int changed = 0;
down(&ice->gpio_mutex);
@@ -566,7 +566,7 @@ static int pontis_gpio_data_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
* mixers
*/
-static snd_kcontrol_new_t pontis_controls[] __devinitdata = {
+static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
@@ -646,9 +646,9 @@ static snd_kcontrol_new_t pontis_controls[] __devinitdata = {
/*
* WM codec registers
*/
-static void wm_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- ice1712_t *ice = (ice1712_t *)entry->private_data;
+ struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
char line[64];
unsigned int reg, val;
down(&ice->gpio_mutex);
@@ -661,9 +661,9 @@ static void wm_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffe
up(&ice->gpio_mutex);
}
-static void wm_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- ice1712_t *ice = (ice1712_t *)entry->private_data;
+ struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
int reg, val;
down(&ice->gpio_mutex);
@@ -674,9 +674,9 @@ static void wm_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer
up(&ice->gpio_mutex);
}
-static void wm_proc_init(ice1712_t *ice)
+static void wm_proc_init(struct snd_ice1712 *ice)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read);
entry->mode |= S_IWUSR;
@@ -685,9 +685,9 @@ static void wm_proc_init(ice1712_t *ice)
}
}
-static void cs_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- ice1712_t *ice = (ice1712_t *)entry->private_data;
+ struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data;
int reg, val;
down(&ice->gpio_mutex);
@@ -700,16 +700,16 @@ static void cs_proc_regs_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer
up(&ice->gpio_mutex);
}
-static void cs_proc_init(ice1712_t *ice)
+static void cs_proc_init(struct snd_ice1712 *ice)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) {
snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read);
}
}
-static int __devinit pontis_add_controls(ice1712_t *ice)
+static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -730,7 +730,7 @@ static int __devinit pontis_add_controls(ice1712_t *ice)
/*
* initialize the chip
*/
-static int __devinit pontis_init(ice1712_t *ice)
+static int __devinit pontis_init(struct snd_ice1712 *ice)
{
static unsigned short wm_inits[] = {
/* These come first to reduce init pop noise */
@@ -781,7 +781,7 @@ static int __devinit pontis_init(ice1712_t *ice)
ice->num_total_adcs = 2;
/* to remeber the register values */
- ice->akm = kzalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+ ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ice->akm)
return -ENOMEM;
ice->akm_codecs = 1;
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index d2c5963795d7..fdb5cb8fac97 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -36,12 +36,12 @@
#include "prodigy192.h"
#include "stac946x.h"
-static inline void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
+static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val)
{
snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
}
-static inline unsigned char stac9460_get(ice1712_t *ice, int reg)
+static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
{
return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
}
@@ -49,7 +49,7 @@ static inline unsigned char stac9460_get(ice1712_t *ice, int reg)
/*
* DAC mute control
*/
-static int stac9460_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -58,9 +58,9 @@ static int stac9460_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int stac9460_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char val;
int idx;
@@ -73,9 +73,9 @@ static int stac9460_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int stac9460_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char new, old;
int idx;
int change;
@@ -96,7 +96,7 @@ static int stac9460_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/*
* DAC volume attenuation mixer control
*/
-static int stac9460_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -105,9 +105,9 @@ static int stac9460_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int stac9460_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx;
unsigned char vol;
@@ -121,9 +121,9 @@ static int stac9460_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int stac9460_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int idx;
unsigned char tmp, ovol, nvol;
int change;
@@ -145,7 +145,7 @@ static int stac9460_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
/*
* ADC mute control
*/
-static int stac9460_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -154,9 +154,9 @@ static int stac9460_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int stac9460_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char val;
int i;
@@ -168,9 +168,9 @@ static int stac9460_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int stac9460_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
unsigned char new, old;
int i, reg;
int change;
@@ -190,7 +190,7 @@ static int stac9460_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/*
* ADC gain mixer control
*/
-static int stac9460_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -199,9 +199,9 @@ static int stac9460_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int stac9460_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, reg;
unsigned char vol;
@@ -214,9 +214,9 @@ static int stac9460_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int stac9460_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int i, reg;
unsigned char ovol, nvol;
int change;
@@ -237,7 +237,7 @@ static int stac9460_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *
/*
* Headphone Amplifier
*/
-static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
+static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
{
unsigned int tmp, tmp2;
@@ -253,14 +253,14 @@ static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
return 0;
}
-static int aureon_get_headphone_amp(ice1712_t *ice)
+static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
{
unsigned int tmp = snd_ice1712_gpio_read(ice);
return ( tmp & AUREON_HP_SEL )!= 0;
}
-static int aureon_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int aureon_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -269,18 +269,18 @@ static int aureon_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
return 0;
}
-static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
}
@@ -288,16 +288,16 @@ static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/*
* Deemphasis
*/
-static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
return 0;
}
-static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
int temp, temp2;
temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
if (ucontrol->value.integer.value[0])
@@ -314,7 +314,7 @@ static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/*
* ADC Oversampling
*/
-static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = { "128x", "64x" };
@@ -329,17 +329,17 @@ static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinf
return 0;
}
-static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
return 0;
}
-static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int temp, temp2;
- ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
temp2 = temp = wm_get(ice, WM_MASTER);
@@ -360,7 +360,7 @@ static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
* mixers
*/
-static snd_kcontrol_new_t stac_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
@@ -442,7 +442,7 @@ static snd_kcontrol_new_t stac_controls[] __devinitdata = {
#endif
};
-static int __devinit prodigy192_add_controls(ice1712_t *ice)
+static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
{
unsigned int i;
int err;
@@ -459,7 +459,7 @@ static int __devinit prodigy192_add_controls(ice1712_t *ice)
/*
* initialize the chip
*/
-static int __devinit prodigy192_init(ice1712_t *ice)
+static int __devinit prodigy192_init(struct snd_ice1712 *ice)
{
static unsigned short stac_inits_prodigy[] = {
STAC946X_RESET, 0,
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 1fe21009ca84..b5754b32b802 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -33,7 +33,7 @@
#include "envy24ht.h"
#include "revo.h"
-static void revo_i2s_mclk_changed(ice1712_t *ice)
+static void revo_i2s_mclk_changed(struct snd_ice1712 *ice)
{
/* assert PRST# to converters; MT05 bit 7 */
outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
@@ -45,7 +45,7 @@ static void revo_i2s_mclk_changed(ice1712_t *ice)
/*
* change the rate of envy24HT, AK4355 and AK4381
*/
-static void revo_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
{
unsigned char old, tmp, dfs;
int reg, shift;
@@ -61,7 +61,7 @@ static void revo_set_rate_val(akm4xxx_t *ak, unsigned int rate)
else
dfs = 0;
- if (ak->type == SND_AK4355) {
+ if (ak->type == SND_AK4355 || ak->type == SND_AK4358) {
reg = 2;
shift = 4;
} else {
@@ -87,7 +87,7 @@ static void revo_set_rate_val(akm4xxx_t *ak, unsigned int rate)
* initialize the chips on M-Audio Revolution cards
*/
-static akm4xxx_t akm_revo_front __devinitdata = {
+static struct snd_akm4xxx akm_revo_front __devinitdata = {
.type = SND_AK4381,
.num_dacs = 2,
.ops = {
@@ -107,7 +107,7 @@ static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
.mask_flags = 0,
};
-static akm4xxx_t akm_revo_surround __devinitdata = {
+static struct snd_akm4xxx akm_revo_surround __devinitdata = {
.type = SND_AK4355,
.idx_offset = 1,
.num_dacs = 6,
@@ -128,9 +128,29 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
.mask_flags = 0,
};
-static int __devinit revo_init(ice1712_t *ice)
+static struct snd_akm4xxx akm_revo51 __devinitdata = {
+ .type = SND_AK4358,
+ .num_dacs = 6,
+ .ops = {
+ .set_rate_val = revo_set_rate_val
+ }
+};
+
+static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+ .caddr = 2,
+ .cif = 0,
+ .data_mask = VT1724_REVO_CDOUT,
+ .clk_mask = VT1724_REVO_CCLK,
+ .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
+ .cs_addr = 0,
+ .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2,
+ .add_flags = VT1724_REVO_CCLK, /* high at init */
+ .mask_flags = 0,
+};
+
+static int __devinit revo_init(struct snd_ice1712 *ice)
{
- akm4xxx_t *ak;
+ struct snd_akm4xxx *ak;
int err;
/* determine I2C, DACs and ADCs */
@@ -138,21 +158,25 @@ static int __devinit revo_init(ice1712_t *ice)
case VT1724_SUBDEVICE_REVOLUTION71:
ice->num_total_dacs = 8;
ice->num_total_adcs = 2;
+ ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed;
+ break;
+ case VT1724_SUBDEVICE_REVOLUTION51:
+ ice->num_total_dacs = 6;
+ ice->num_total_adcs = 2;
break;
default:
snd_BUG();
return -EINVAL;
}
- ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed;
-
/* second stage of initialization, analog parts and others */
- ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL);
+ ak = ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL);
if (! ak)
return -ENOMEM;
ice->akm_codecs = 2;
switch (ice->eeprom.subvendor) {
case VT1724_SUBDEVICE_REVOLUTION71:
+ ice->akm_codecs = 2;
if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo_front, &akm_revo_front_priv, ice)) < 0)
return err;
if ((err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo_surround, &akm_revo_surround_priv, ice)) < 0)
@@ -160,18 +184,26 @@ static int __devinit revo_init(ice1712_t *ice)
/* unmute all codecs */
snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE);
break;
+ case VT1724_SUBDEVICE_REVOLUTION51:
+ ice->akm_codecs = 1;
+ if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0)
+ return err;
+ /* unmute all codecs - needed! */
+ snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE);
+ break;
}
return 0;
}
-static int __devinit revo_add_controls(ice1712_t *ice)
+static int __devinit revo_add_controls(struct snd_ice1712 *ice)
{
int err;
switch (ice->eeprom.subvendor) {
case VT1724_SUBDEVICE_REVOLUTION71:
+ case VT1724_SUBDEVICE_REVOLUTION51:
err = snd_ice1712_akm4xxx_build_controls(ice);
if (err < 0)
return err;
@@ -188,5 +220,12 @@ struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
.chip_init = revo_init,
.build_controls = revo_add_controls,
},
+ {
+ .subvendor = VT1724_SUBDEVICE_REVOLUTION51,
+ .name = "M Audio Revolution-5.1",
+ .model = "revo51",
+ .chip_init = revo_init,
+ .build_controls = revo_add_controls,
+ },
{ } /* terminator */
};
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h
index ca4420b5e3ec..dea52ea219df 100644
--- a/sound/pci/ice1712/revo.h
+++ b/sound/pci/ice1712/revo.h
@@ -25,9 +25,11 @@
*/
#define REVO_DEVICE_DESC \
- "{MidiMan M Audio,Revolution 7.1},"
+ "{MidiMan M Audio,Revolution 7.1},"\
+ "{MidiMan M Audio,Revolution 5.1},"
#define VT1724_SUBDEVICE_REVOLUTION71 0x12143036
+#define VT1724_SUBDEVICE_REVOLUTION51 0x12143136
/* entry point */
extern struct snd_ice1712_card_info snd_vt1724_revo_cards[];
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 90c85cd95479..7ca263c13091 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -33,7 +33,7 @@
#include "vt1720_mobo.h"
-static int __devinit k8x800_init(ice1712_t *ice)
+static int __devinit k8x800_init(struct snd_ice1712 *ice)
{
ice->vt1720 = 1;
@@ -47,7 +47,7 @@ static int __devinit k8x800_init(ice1712_t *ice)
return 0;
}
-static int __devinit k8x800_add_controls(ice1712_t *ice)
+static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
{
/* FIXME: needs some quirks for VT1616? */
return 0;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index cf7801d2dd10..5466b1fa0cd5 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -272,7 +272,8 @@ enum {
#define ALI_INT_CPRAIS (1<<7) /* command port available */
#define ALI_INT_SPRAIS (1<<5) /* status port available */
#define ALI_INT_GPIO (1<<1)
-#define ALI_INT_MASK (ALI_INT_SPDIFOUT|ALI_INT_CODECSPDIFOUT|ALI_INT_MICIN|ALI_INT_PCMOUT|ALI_INT_PCMIN)
+#define ALI_INT_MASK (ALI_INT_SPDIFOUT|ALI_INT_CODECSPDIFOUT|\
+ ALI_INT_MICIN|ALI_INT_PCMOUT|ALI_INT_PCMIN)
#define ICH_ALI_SC_RESET (1<<31) /* master reset */
#define ICH_ALI_SC_AC97_DBL (1<<30)
@@ -303,18 +304,40 @@ enum {
*
*/
-enum { ICHD_PCMIN, ICHD_PCMOUT, ICHD_MIC, ICHD_MIC2, ICHD_PCM2IN, ICHD_SPBAR, ICHD_LAST = ICHD_SPBAR };
-enum { NVD_PCMIN, NVD_PCMOUT, NVD_MIC, NVD_SPBAR, NVD_LAST = NVD_SPBAR };
-enum { ALID_PCMIN, ALID_PCMOUT, ALID_MIC, ALID_AC97SPDIFOUT, ALID_SPDIFIN, ALID_SPDIFOUT, ALID_LAST = ALID_SPDIFOUT };
+enum {
+ ICHD_PCMIN,
+ ICHD_PCMOUT,
+ ICHD_MIC,
+ ICHD_MIC2,
+ ICHD_PCM2IN,
+ ICHD_SPBAR,
+ ICHD_LAST = ICHD_SPBAR
+};
+enum {
+ NVD_PCMIN,
+ NVD_PCMOUT,
+ NVD_MIC,
+ NVD_SPBAR,
+ NVD_LAST = NVD_SPBAR
+};
+enum {
+ ALID_PCMIN,
+ ALID_PCMOUT,
+ ALID_MIC,
+ ALID_AC97SPDIFOUT,
+ ALID_SPDIFIN,
+ ALID_SPDIFOUT,
+ ALID_LAST = ALID_SPDIFOUT
+};
-#define get_ichdev(substream) (ichdev_t *)(substream->runtime->private_data)
+#define get_ichdev(substream) (substream->runtime->private_data)
-typedef struct {
+struct ichdev {
unsigned int ichd; /* ich device number */
unsigned long reg_offset; /* offset to bmaddr */
u32 *bdbar; /* CPU address (32bit) */
unsigned int bdbar_addr; /* PCI bus address (32bit) */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
unsigned int physbuf; /* physical address (32bit) */
unsigned int size;
unsigned int fragsize;
@@ -336,11 +359,9 @@ typedef struct {
int pcm_open_flag;
unsigned int page_attr_changed: 1;
unsigned int suspended: 1;
-} ichdev_t;
-
-typedef struct _snd_intel8x0 intel8x0_t;
+};
-struct _snd_intel8x0 {
+struct intel8x0 {
unsigned int device_type;
int irq;
@@ -353,11 +374,11 @@ struct _snd_intel8x0 {
void __iomem *remap_bmaddr;
struct pci_dev *pci;
- snd_card_t *card;
+ struct snd_card *card;
int pcm_devs;
- snd_pcm_t *pcm[6];
- ichdev_t ichd[6];
+ struct snd_pcm *pcm[6];
+ struct ichdev ichd[6];
unsigned multi4: 1,
multi6: 1,
@@ -374,8 +395,8 @@ struct _snd_intel8x0 {
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
unsigned int sdm_saved; /* SDM reg value */
- ac97_bus_t *ac97_bus;
- ac97_t *ac97[3];
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97[3];
unsigned int ac97_sdin[3];
spinlock_t reg_lock;
@@ -418,7 +439,7 @@ MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids);
* Lowlevel I/O - busmaster
*/
-static u8 igetbyte(intel8x0_t *chip, u32 offset)
+static u8 igetbyte(struct intel8x0 *chip, u32 offset)
{
if (chip->bm_mmio)
return readb(chip->remap_bmaddr + offset);
@@ -426,7 +447,7 @@ static u8 igetbyte(intel8x0_t *chip, u32 offset)
return inb(chip->bmaddr + offset);
}
-static u16 igetword(intel8x0_t *chip, u32 offset)
+static u16 igetword(struct intel8x0 *chip, u32 offset)
{
if (chip->bm_mmio)
return readw(chip->remap_bmaddr + offset);
@@ -434,7 +455,7 @@ static u16 igetword(intel8x0_t *chip, u32 offset)
return inw(chip->bmaddr + offset);
}
-static u32 igetdword(intel8x0_t *chip, u32 offset)
+static u32 igetdword(struct intel8x0 *chip, u32 offset)
{
if (chip->bm_mmio)
return readl(chip->remap_bmaddr + offset);
@@ -442,7 +463,7 @@ static u32 igetdword(intel8x0_t *chip, u32 offset)
return inl(chip->bmaddr + offset);
}
-static void iputbyte(intel8x0_t *chip, u32 offset, u8 val)
+static void iputbyte(struct intel8x0 *chip, u32 offset, u8 val)
{
if (chip->bm_mmio)
writeb(val, chip->remap_bmaddr + offset);
@@ -450,7 +471,7 @@ static void iputbyte(intel8x0_t *chip, u32 offset, u8 val)
outb(val, chip->bmaddr + offset);
}
-static void iputword(intel8x0_t *chip, u32 offset, u16 val)
+static void iputword(struct intel8x0 *chip, u32 offset, u16 val)
{
if (chip->bm_mmio)
writew(val, chip->remap_bmaddr + offset);
@@ -458,7 +479,7 @@ static void iputword(intel8x0_t *chip, u32 offset, u16 val)
outw(val, chip->bmaddr + offset);
}
-static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
+static void iputdword(struct intel8x0 *chip, u32 offset, u32 val)
{
if (chip->bm_mmio)
writel(val, chip->remap_bmaddr + offset);
@@ -470,7 +491,7 @@ static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
* Lowlevel I/O - AC'97 registers
*/
-static u16 iagetword(intel8x0_t *chip, u32 offset)
+static u16 iagetword(struct intel8x0 *chip, u32 offset)
{
if (chip->mmio)
return readw(chip->remap_addr + offset);
@@ -478,7 +499,7 @@ static u16 iagetword(intel8x0_t *chip, u32 offset)
return inw(chip->addr + offset);
}
-static void iaputword(intel8x0_t *chip, u32 offset, u16 val)
+static void iaputword(struct intel8x0 *chip, u32 offset, u16 val)
{
if (chip->mmio)
writew(val, chip->remap_addr + offset);
@@ -495,7 +516,7 @@ static void iaputword(intel8x0_t *chip, u32 offset, u16 val)
*/
/* return the GLOB_STA bit for the corresponding codec */
-static unsigned int get_ich_codec_bit(intel8x0_t *chip, unsigned int codec)
+static unsigned int get_ich_codec_bit(struct intel8x0 *chip, unsigned int codec)
{
static unsigned int codec_bit[3] = {
ICH_PCR, ICH_SCR, ICH_TCR
@@ -506,7 +527,7 @@ static unsigned int get_ich_codec_bit(intel8x0_t *chip, unsigned int codec)
return codec_bit[codec];
}
-static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
+static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int codec)
{
int time;
@@ -545,11 +566,11 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
return -EBUSY;
}
-static void snd_intel8x0_codec_write(ac97_t *ac97,
+static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0 *chip = ac97->private_data;
if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
@@ -558,10 +579,10 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
iaputword(chip, reg + ac97->num * 0x80, val);
}
-static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
+static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0 *chip = ac97->private_data;
unsigned short res;
unsigned int tmp;
@@ -573,7 +594,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
res = iagetword(chip, reg + ac97->num * 0x80);
if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
/* reset RCS and preserve other R/WC bits */
- iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
+ iputdword(chip, ICHREG(GLOB_STA), tmp &
+ ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
if (! chip->in_ac97_init)
snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg);
res = 0xffff;
@@ -582,7 +604,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
return res;
}
-static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec)
+static void snd_intel8x0_codec_read_test(struct intel8x0 *chip, unsigned int codec)
{
unsigned int tmp;
@@ -590,7 +612,8 @@ static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec)
iagetword(chip, codec * 0x80);
if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
/* reset RCS and preserve other R/WC bits */
- iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
+ iputdword(chip, ICHREG(GLOB_STA), tmp &
+ ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
}
}
}
@@ -598,7 +621,7 @@ static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec)
/*
* access to AC97 for Ali5455
*/
-static int snd_intel8x0_ali_codec_ready(intel8x0_t *chip, int mask)
+static int snd_intel8x0_ali_codec_ready(struct intel8x0 *chip, int mask)
{
int count = 0;
for (count = 0; count < 0x7f; count++) {
@@ -611,7 +634,7 @@ static int snd_intel8x0_ali_codec_ready(intel8x0_t *chip, int mask)
return -EBUSY;
}
-static int snd_intel8x0_ali_codec_semaphore(intel8x0_t *chip)
+static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip)
{
int time = 100;
if (chip->buggy_semaphore)
@@ -623,9 +646,9 @@ static int snd_intel8x0_ali_codec_semaphore(intel8x0_t *chip)
return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY);
}
-static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_intel8x0_ali_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0 *chip = ac97->private_data;
unsigned short data = 0xffff;
if (snd_intel8x0_ali_codec_semaphore(chip))
@@ -641,9 +664,10 @@ static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short r
return data;
}
-static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+static void snd_intel8x0_ali_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short val)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0 *chip = ac97->private_data;
if (snd_intel8x0_ali_codec_semaphore(chip))
return;
@@ -658,7 +682,7 @@ static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsig
/*
* DMA I/O
*/
-static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
+static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ichdev)
{
int idx;
u32 *bdbar = ichdev->bdbar;
@@ -681,10 +705,15 @@ static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
ichdev->ack_reload = ichdev->ack = 1;
ichdev->fragsize1 = ichdev->fragsize;
for (idx = 0; idx < (ICH_REG_LVI_MASK + 1) * 2; idx += 2) {
- bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf + (((idx >> 1) * ichdev->fragsize) % ichdev->size));
+ bdbar[idx + 0] = cpu_to_le32(ichdev->physbuf +
+ (((idx >> 1) * ichdev->fragsize) %
+ ichdev->size));
bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */
ichdev->fragsize >> ichdev->pos_shift);
- // printk("bdbar[%i] = 0x%x [0x%x]\n", idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
+#if 0
+ printk("bdbar[%i] = 0x%x [0x%x]\n",
+ idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
+#endif
}
ichdev->frags = ichdev->size / ichdev->fragsize;
}
@@ -722,7 +751,7 @@ static void fill_nocache(void *buf, int size, int nocache)
* Interrupt handler
*/
-static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
+static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ichdev)
{
unsigned long port = ichdev->reg_offset;
int status, civ, i, step;
@@ -757,7 +786,12 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
ichdev->lvi_frag++;
ichdev->lvi_frag %= ichdev->frags;
ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
- // printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR));
+#if 0
+ printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+ ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
+ ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
+ inl(port + 4), inb(port + ICH_REG_OFF_CR));
+#endif
if (--ichdev->ack == 0) {
ichdev->ack = ichdev->ack_reload;
ack = 1;
@@ -773,8 +807,8 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- intel8x0_t *chip = dev_id;
- ichdev_t *ichdev;
+ struct intel8x0 *chip = dev_id;
+ struct ichdev *ichdev;
unsigned int status;
unsigned int i;
@@ -808,10 +842,10 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs
* PCM part
*/
-static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
unsigned char val = 0;
unsigned long port = ichdev->reg_offset;
@@ -847,12 +881,14 @@ static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
return 0;
}
-static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
unsigned long port = ichdev->reg_offset;
- static int fiforeg[] = { ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3) };
+ static int fiforeg[] = {
+ ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3)
+ };
unsigned int val, fifo;
val = igetdword(chip, ICHREG(ALI_DMACR));
@@ -871,14 +907,16 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
}
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */
- iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */
+ /* start DMA */
+ iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot));
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
ichdev->suspended = 1;
/* fallthru */
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */
+ /* pause */
+ iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16)));
iputbyte(chip, port + ICH_REG_OFF_CR, 0);
while (igetbyte(chip, port + ICH_REG_OFF_CR))
;
@@ -887,7 +925,8 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
/* reset whole DMA things */
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
/* clear interrupts */
- iputbyte(chip, port + ICH_REG_OFF_SR, igetbyte(chip, port + ICH_REG_OFF_SR) | 0x1e);
+ iputbyte(chip, port + ICH_REG_OFF_SR,
+ igetbyte(chip, port + ICH_REG_OFF_SR) | 0x1e);
iputdword(chip, ICHREG(ALI_INTERRUPTSR),
igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & ichdev->int_sta_mask);
break;
@@ -897,12 +936,12 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
return 0;
}
-static int snd_intel8x0_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int dbl = params_rate(hw_params) > 48000;
int err;
@@ -930,15 +969,16 @@ static int snd_intel8x0_hw_params(snd_pcm_substream_t * substream,
ichdev->pcm_open_flag = 1;
/* Force SPDIF setting */
if (ichdev->ichd == ICHD_PCMOUT && chip->spdif_idx < 0)
- snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, params_rate(hw_params));
+ snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF,
+ params_rate(hw_params));
}
return err;
}
-static int snd_intel8x0_hw_free(snd_pcm_substream_t * substream)
+static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
@@ -951,8 +991,8 @@ static int snd_intel8x0_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
-static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
- snd_pcm_runtime_t *runtime)
+static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
+ struct snd_pcm_runtime *runtime)
{
unsigned int cnt;
int dbl = runtime->rate > 48000;
@@ -1004,11 +1044,11 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
spin_unlock_irq(&chip->reg_lock);
}
-static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
+static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct ichdev *ichdev = get_ichdev(substream);
ichdev->physbuf = runtime->dma_addr;
ichdev->size = snd_pcm_lib_buffer_bytes(substream);
@@ -1022,10 +1062,10 @@ static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
size_t ptr1, ptr;
int civ, timeout = 100;
unsigned int position;
@@ -1052,7 +1092,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_hardware_t snd_intel8x0_stream =
+static struct snd_pcm_hardware snd_intel8x0_stream =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1077,7 +1117,7 @@ static unsigned int channels4[] = {
2, 4,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_channels4 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels4 = {
.count = ARRAY_SIZE(channels4),
.list = channels4,
.mask = 0,
@@ -1087,16 +1127,16 @@ static unsigned int channels6[] = {
2, 4, 6,
};
-static snd_pcm_hw_constraint_list_t hw_constraints_channels6 = {
+static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
.count = ARRAY_SIZE(channels6),
.list = channels6,
.mask = 0,
};
-static int snd_intel8x0_pcm_open(snd_pcm_substream_t * substream, ichdev_t *ichdev)
+static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
ichdev->substream = substream;
@@ -1113,10 +1153,10 @@ static int snd_intel8x0_pcm_open(snd_pcm_substream_t * substream, ichdev_t *ichd
return 0;
}
-static int snd_intel8x0_playback_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
err = snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCMOUT]);
@@ -1125,10 +1165,12 @@ static int snd_intel8x0_playback_open(snd_pcm_substream_t * substream)
if (chip->multi6) {
runtime->hw.channels_max = 6;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels6);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &hw_constraints_channels6);
} else if (chip->multi4) {
runtime->hw.channels_max = 4;
- snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels4);
+ snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ &hw_constraints_channels4);
}
if (chip->dra) {
snd_ac97_pcm_double_rate_rules(runtime);
@@ -1140,94 +1182,94 @@ static int snd_intel8x0_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_intel8x0_playback_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_playback_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_PCMOUT].substream = NULL;
return 0;
}
-static int snd_intel8x0_capture_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_capture_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCMIN]);
}
-static int snd_intel8x0_capture_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_capture_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_PCMIN].substream = NULL;
return 0;
}
-static int snd_intel8x0_mic_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_mic_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_MIC]);
}
-static int snd_intel8x0_mic_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_mic_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_MIC].substream = NULL;
return 0;
}
-static int snd_intel8x0_mic2_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_mic2_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_MIC2]);
}
-static int snd_intel8x0_mic2_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_mic2_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_MIC2].substream = NULL;
return 0;
}
-static int snd_intel8x0_capture2_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_capture2_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ICHD_PCM2IN]);
}
-static int snd_intel8x0_capture2_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_capture2_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_PCM2IN].substream = NULL;
return 0;
}
-static int snd_intel8x0_spdif_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_spdif_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
int idx = chip->device_type == DEVICE_NFORCE ? NVD_SPBAR : ICHD_SPBAR;
return snd_intel8x0_pcm_open(substream, &chip->ichd[idx]);
}
-static int snd_intel8x0_spdif_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_spdif_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
int idx = chip->device_type == DEVICE_NFORCE ? NVD_SPBAR : ICHD_SPBAR;
chip->ichd[idx].substream = NULL;
return 0;
}
-static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_ac97spdifout_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
unsigned int val;
spin_lock_irq(&chip->reg_lock);
@@ -1240,9 +1282,9 @@ static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]);
}
-static int snd_intel8x0_ali_ac97spdifout_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
unsigned int val;
chip->ichd[ALID_AC97SPDIFOUT].substream = NULL;
@@ -1255,39 +1297,39 @@ static int snd_intel8x0_ali_ac97spdifout_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_intel8x0_ali_spdifin_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_SPDIFIN]);
}
-static int snd_intel8x0_ali_spdifin_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ALID_SPDIFIN].substream = NULL;
return 0;
}
#if 0 // NYI
-static int snd_intel8x0_ali_spdifout_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_SPDIFOUT]);
}
-static int snd_intel8x0_ali_spdifout_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0_ali_spdifout_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0 *chip = snd_pcm_substream_chip(substream);
chip->ichd[ALID_SPDIFOUT].substream = NULL;
return 0;
}
#endif
-static snd_pcm_ops_t snd_intel8x0_playback_ops = {
+static struct snd_pcm_ops snd_intel8x0_playback_ops = {
.open = snd_intel8x0_playback_open,
.close = snd_intel8x0_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1298,7 +1340,7 @@ static snd_pcm_ops_t snd_intel8x0_playback_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_capture_ops = {
+static struct snd_pcm_ops snd_intel8x0_capture_ops = {
.open = snd_intel8x0_capture_open,
.close = snd_intel8x0_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1309,7 +1351,7 @@ static snd_pcm_ops_t snd_intel8x0_capture_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_capture_mic_ops = {
+static struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
.open = snd_intel8x0_mic_open,
.close = snd_intel8x0_mic_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1320,7 +1362,7 @@ static snd_pcm_ops_t snd_intel8x0_capture_mic_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_capture_mic2_ops = {
+static struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
.open = snd_intel8x0_mic2_open,
.close = snd_intel8x0_mic2_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1331,7 +1373,7 @@ static snd_pcm_ops_t snd_intel8x0_capture_mic2_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_capture2_ops = {
+static struct snd_pcm_ops snd_intel8x0_capture2_ops = {
.open = snd_intel8x0_capture2_open,
.close = snd_intel8x0_capture2_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1342,7 +1384,7 @@ static snd_pcm_ops_t snd_intel8x0_capture2_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_spdif_ops = {
+static struct snd_pcm_ops snd_intel8x0_spdif_ops = {
.open = snd_intel8x0_spdif_open,
.close = snd_intel8x0_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1353,7 +1395,7 @@ static snd_pcm_ops_t snd_intel8x0_spdif_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_ali_playback_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
.open = snd_intel8x0_playback_open,
.close = snd_intel8x0_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1364,7 +1406,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_playback_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_ali_capture_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
.open = snd_intel8x0_capture_open,
.close = snd_intel8x0_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1375,7 +1417,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_capture_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_ali_capture_mic_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
.open = snd_intel8x0_mic_open,
.close = snd_intel8x0_mic_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1386,7 +1428,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_capture_mic_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_ali_ac97spdifout_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
.open = snd_intel8x0_ali_ac97spdifout_open,
.close = snd_intel8x0_ali_ac97spdifout_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1397,7 +1439,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_ac97spdifout_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0_ali_spdifin_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.open = snd_intel8x0_ali_spdifin_open,
.close = snd_intel8x0_ali_spdifin_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1409,7 +1451,7 @@ static snd_pcm_ops_t snd_intel8x0_ali_spdifin_ops = {
};
#if 0 // NYI
-static snd_pcm_ops_t snd_intel8x0_ali_spdifout_ops = {
+static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
.open = snd_intel8x0_ali_spdifout_open,
.close = snd_intel8x0_ali_spdifout_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1423,16 +1465,17 @@ static snd_pcm_ops_t snd_intel8x0_ali_spdifout_ops = {
struct ich_pcm_table {
char *suffix;
- snd_pcm_ops_t *playback_ops;
- snd_pcm_ops_t *capture_ops;
+ struct snd_pcm_ops *playback_ops;
+ struct snd_pcm_ops *capture_ops;
size_t prealloc_size;
size_t prealloc_max_size;
int ac97_idx;
};
-static int __devinit snd_intel8x0_pcm1(intel8x0_t *chip, int device, struct ich_pcm_table *rec)
+static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
+ struct ich_pcm_table *rec)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
char name[32];
@@ -1459,7 +1502,8 @@ static int __devinit snd_intel8x0_pcm1(intel8x0_t *chip, int device, struct ich_
strcpy(pcm->name, chip->card->shortname);
chip->pcm[device] = pcm;
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->pci),
rec->prealloc_size, rec->prealloc_max_size);
return 0;
@@ -1557,7 +1601,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
#endif
};
-static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
+static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
{
int i, tblsize, device, err;
struct ich_pcm_table *tbl, *rec;
@@ -1604,15 +1648,15 @@ static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
* Mixer part
*/
-static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- intel8x0_t *chip = bus->private_data;
+ struct intel8x0 *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
+static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0 *chip = ac97->private_data;
chip->ac97[ac97->num] = NULL;
}
@@ -1815,6 +1859,30 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x103c,
+ .subdevice = 0x0938,
+ .name = "HP nc4200",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x099c,
+ .name = "HP nc6120",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x0944,
+ .name = "HP nc6220",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x0934,
+ .name = "HP nc8220",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
.subdevice = 0x12f1,
.name = "HP xw8200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
@@ -1868,6 +1936,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.type = AC97_TUNE_HP_ONLY
},
{
+ .subvendor = 0x10cf,
+ .subdevice = 0x12f2,
+ .name = "Fujitsu-Siemens Celsius H320",
+ .type = AC97_TUNE_SWAP_HP
+ },
+ {
.subvendor = 0x10f1,
.subdevice = 0x2665,
.name = "Fujitsu-Siemens Celsius", /* AD1981? */
@@ -1961,19 +2035,20 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
{ } /* terminator */
};
-static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const char *quirk_override)
+static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
+ const char *quirk_override)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int err;
unsigned int i, codecs;
unsigned int glob_sta = 0;
- ac97_bus_ops_t *ops;
- static ac97_bus_ops_t standard_bus_ops = {
+ struct snd_ac97_bus_ops *ops;
+ static struct snd_ac97_bus_ops standard_bus_ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
};
- static ac97_bus_ops_t ali_bus_ops = {
+ static struct snd_ac97_bus_ops ali_bus_ops = {
.write = snd_intel8x0_ali_codec_write,
.read = snd_intel8x0_ali_codec_read,
};
@@ -2128,7 +2203,8 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const
__err:
/* clear the cold-reset bit for the next chance */
if (chip->device_type != DEVICE_ALI)
- iputdword(chip, ICHREG(GLOB_CNT), igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);
+ iputdword(chip, ICHREG(GLOB_CNT),
+ igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);
return err;
}
@@ -2137,7 +2213,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const
*
*/
-static void do_ali_reset(intel8x0_t *chip)
+static void do_ali_reset(struct intel8x0 *chip)
{
iputdword(chip, ICHREG(ALI_SCR), ICH_ALI_SC_RESET);
iputdword(chip, ICHREG(ALI_FIFOCR1), 0x83838383);
@@ -2149,11 +2225,7 @@ static void do_ali_reset(intel8x0_t *chip)
iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
}
-#define do_delay(chip) do {\
- schedule_timeout_uninterruptible(1);\
-} while (0)
-
-static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
+static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
{
unsigned long end_time;
unsigned int cnt, status, nstatus;
@@ -2176,9 +2248,10 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
do {
if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
goto __ok;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT)));
+ snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
+ igetdword(chip, ICHREG(GLOB_CNT)));
return -EIO;
__ok:
@@ -2189,14 +2262,16 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
*/
end_time = jiffies + HZ;
do {
- status = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ status = igetdword(chip, ICHREG(GLOB_STA)) &
+ (ICH_PCR | ICH_SCR | ICH_TCR);
if (status)
break;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
if (! status) {
/* no codec is found */
- snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA)));
+ snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n",
+ igetdword(chip, ICHREG(GLOB_STA)));
return -EIO;
}
@@ -2210,7 +2285,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
/* wait for other codecs ready status. */
end_time = jiffies + HZ / 4;
while (status != nstatus && time_after_eq(end_time, jiffies)) {
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus;
}
@@ -2224,10 +2299,11 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
/* wait until all the probed codecs are ready */
end_time = jiffies + HZ;
do {
- nstatus = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ nstatus = igetdword(chip, ICHREG(GLOB_STA)) &
+ (ICH_PCR | ICH_SCR | ICH_TCR);
if (status == nstatus)
break;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
}
@@ -2245,7 +2321,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
return 0;
}
-static int snd_intel8x0_ali_chip_init(intel8x0_t *chip, int probing)
+static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing)
{
u32 reg;
int i = 0;
@@ -2261,7 +2337,7 @@ static int snd_intel8x0_ali_chip_init(intel8x0_t *chip, int probing)
for (i = 0; i < HZ / 2; i++) {
if (! (igetdword(chip, ICHREG(ALI_INTERRUPTSR)) & ALI_INT_GPIO))
goto __ok;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
}
snd_printk(KERN_ERR "AC'97 reset failed.\n");
if (probing)
@@ -2273,14 +2349,14 @@ static int snd_intel8x0_ali_chip_init(intel8x0_t *chip, int probing)
if (reg & 0x80) /* primary codec */
break;
iputdword(chip, ICHREG(ALI_RTSR), reg | 0x80);
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
}
do_ali_reset(chip);
return 0;
}
-static int snd_intel8x0_chip_init(intel8x0_t *chip, int probing)
+static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
{
unsigned int i;
int err;
@@ -2302,11 +2378,12 @@ static int snd_intel8x0_chip_init(intel8x0_t *chip, int probing)
iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
/* initialize Buffer Descriptor Lists */
for (i = 0; i < chip->bdbars_count; i++)
- iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, chip->ichd[i].bdbar_addr);
+ iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset,
+ chip->ichd[i].bdbar_addr);
return 0;
}
-static int snd_intel8x0_free(intel8x0_t *chip)
+static int snd_intel8x0_free(struct intel8x0 *chip)
{
unsigned int i;
@@ -2329,7 +2406,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
synchronize_irq(chip->irq);
__hw_end:
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
if (chip->bdbars.area) {
if (chip->fix_nocache)
fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
@@ -2349,44 +2426,50 @@ static int snd_intel8x0_free(intel8x0_t *chip)
/*
* power management
*/
-static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
+static int intel8x0_suspend(struct pci_dev *pci, pm_message_t state)
{
- intel8x0_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct intel8x0 *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < chip->pcm_devs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
/* clear nocache */
if (chip->fix_nocache) {
for (i = 0; i < chip->bdbars_count; i++) {
- ichdev_t *ichdev = &chip->ichd[i];
+ struct ichdev *ichdev = &chip->ichd[i];
if (ichdev->substream && ichdev->page_attr_changed) {
- snd_pcm_runtime_t *runtime = ichdev->substream->runtime;
+ struct snd_pcm_runtime *runtime = ichdev->substream->runtime;
if (runtime->dma_area)
fill_nocache(runtime->dma_area, runtime->dma_bytes, 0);
}
}
}
for (i = 0; i < 3; i++)
- if (chip->ac97[i])
- snd_ac97_suspend(chip->ac97[i]);
+ snd_ac97_suspend(chip->ac97[i]);
if (chip->device_type == DEVICE_INTEL_ICH4)
chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
- pci_disable_device(chip->pci);
+ free_irq(chip->irq, chip);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int intel8x0_resume(snd_card_t *card)
+static int intel8x0_resume(struct pci_dev *pci)
{
- intel8x0_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct intel8x0 *chip = card->private_data;
int i;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
- request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
+ request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, chip);
+ chip->irq = pci->irq;
synchronize_irq(chip->irq);
snd_intel8x0_chip_init(chip, 1);
@@ -2405,15 +2488,14 @@ static int intel8x0_resume(snd_card_t *card)
fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1);
for (i = 0; i < 3; i++)
- if (chip->ac97[i])
- snd_ac97_resume(chip->ac97[i]);
+ snd_ac97_resume(chip->ac97[i]);
/* refill nocache */
if (chip->fix_nocache) {
for (i = 0; i < chip->bdbars_count; i++) {
- ichdev_t *ichdev = &chip->ichd[i];
+ struct ichdev *ichdev = &chip->ichd[i];
if (ichdev->substream && ichdev->page_attr_changed) {
- snd_pcm_runtime_t *runtime = ichdev->substream->runtime;
+ struct snd_pcm_runtime *runtime = ichdev->substream->runtime;
if (runtime->dma_area)
fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
}
@@ -2422,7 +2504,7 @@ static int intel8x0_resume(snd_card_t *card)
/* resume status */
for (i = 0; i < chip->bdbars_count; i++) {
- ichdev_t *ichdev = &chip->ichd[i];
+ struct ichdev *ichdev = &chip->ichd[i];
unsigned long port = ichdev->reg_offset;
if (! ichdev->substream || ! ichdev->suspended)
continue;
@@ -2434,16 +2516,17 @@ static int intel8x0_resume(snd_card_t *card)
iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
}
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
#define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */
-static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
+static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
{
- snd_pcm_substream_t *subs;
- ichdev_t *ichdev;
+ struct snd_pcm_substream *subs;
+ struct ichdev *ichdev;
unsigned long port;
unsigned long pos, t;
struct timeval start_time, stop_time;
@@ -2520,10 +2603,11 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock);
}
-static void snd_intel8x0_proc_read(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
+#ifdef CONFIG_PROC_FS
+static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
{
- intel8x0_t *chip = entry->private_data;
+ struct intel8x0 *chip = entry->private_data;
unsigned int tmp;
snd_iprintf(buffer, "Intel8x0\n\n");
@@ -2546,17 +2630,20 @@ static void snd_intel8x0_proc_read(snd_info_entry_t * entry,
chip->ac97_sdin[2]);
}
-static void __devinit snd_intel8x0_proc_init(intel8x0_t * chip)
+static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "intel8x0", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0_proc_read);
}
+#else
+#define snd_intel8x0_proc_init(x)
+#endif
-static int snd_intel8x0_dev_free(snd_device_t *device)
+static int snd_intel8x0_dev_free(struct snd_device *device)
{
- intel8x0_t *chip = device->device_data;
+ struct intel8x0 *chip = device->device_data;
return snd_intel8x0_free(chip);
}
@@ -2565,17 +2652,17 @@ struct ich_reg_info {
unsigned int offset;
};
-static int __devinit snd_intel8x0_create(snd_card_t * card,
+static int __devinit snd_intel8x0_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type,
- intel8x0_t ** r_intel8x0)
+ struct intel8x0 ** r_intel8x0)
{
- intel8x0_t *chip;
+ struct intel8x0 *chip;
int err;
unsigned int i;
unsigned int int_sta_masks;
- ichdev_t *ichdev;
- static snd_device_ops_t ops = {
+ struct ichdev *ichdev;
+ static struct snd_device_ops ops = {
.dev_free = snd_intel8x0_dev_free,
};
@@ -2738,7 +2825,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
/* request irq after initializaing int_sta_mask, etc */
if (request_irq(pci->irq, snd_intel8x0_interrupt,
- SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+ SA_INTERRUPT|SA_SHIRQ, card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_intel8x0_free(chip);
return -EBUSY;
@@ -2752,8 +2839,6 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
return err;
}
- snd_card_set_pm_callback(card, intel8x0_suspend, intel8x0_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_intel8x0_free(chip);
return err;
@@ -2797,8 +2882,8 @@ static struct shortname_table {
static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- intel8x0_t *chip;
+ struct snd_card *card;
+ struct intel8x0 *chip;
int err;
struct shortname_table *name;
@@ -2841,6 +2926,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) {
snd_card_free(card);
@@ -2879,7 +2965,10 @@ static struct pci_driver driver = {
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
.remove = __devexit_p(snd_intel8x0_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = intel8x0_suspend,
+ .resume = intel8x0_resume,
+#endif
};
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index a42091860da7..47e26aaa9ad7 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -38,7 +38,8 @@
#include <sound/initval.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7013; NVidia MCP/2/2S/3 modems");
+MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; "
+ "SiS 7013; NVidia MCP/2/2S/3 modems");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
"{Intel,82901AB-ICH0},"
@@ -163,14 +164,14 @@ DEFINE_REGSET(OFF, 0); /* offset */
enum { ICHD_MDMIN, ICHD_MDMOUT, ICHD_MDMLAST = ICHD_MDMOUT };
enum { ALID_MDMIN, ALID_MDMOUT, ALID_MDMLAST = ALID_MDMOUT };
-#define get_ichdev(substream) (ichdev_t *)(substream->runtime->private_data)
+#define get_ichdev(substream) (substream->runtime->private_data)
-typedef struct {
+struct ichdev {
unsigned int ichd; /* ich device number */
unsigned long reg_offset; /* offset to bmaddr */
u32 *bdbar; /* CPU address (32bit) */
unsigned int bdbar_addr; /* PCI bus address (32bit) */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
unsigned int physbuf; /* physical address (32bit) */
unsigned int size;
unsigned int fragsize;
@@ -187,12 +188,10 @@ typedef struct {
unsigned int roff_picb;
unsigned int int_sta_mask; /* interrupt status mask */
unsigned int ali_slot; /* ALI DMA slot */
- ac97_t *ac97;
-} ichdev_t;
-
-typedef struct _snd_intel8x0m intel8x0_t;
+ struct snd_ac97 *ac97;
+};
-struct _snd_intel8x0m {
+struct intel8x0m {
unsigned int device_type;
int irq;
@@ -205,16 +204,16 @@ struct _snd_intel8x0m {
void __iomem *remap_bmaddr;
struct pci_dev *pci;
- snd_card_t *card;
+ struct snd_card *card;
int pcm_devs;
- snd_pcm_t *pcm[2];
- ichdev_t ichd[2];
+ struct snd_pcm *pcm[2];
+ struct ichdev ichd[2];
unsigned int in_ac97_init: 1;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
spinlock_t reg_lock;
@@ -254,7 +253,7 @@ MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
* Lowlevel I/O - busmaster
*/
-static u8 igetbyte(intel8x0_t *chip, u32 offset)
+static u8 igetbyte(struct intel8x0m *chip, u32 offset)
{
if (chip->bm_mmio)
return readb(chip->remap_bmaddr + offset);
@@ -262,7 +261,7 @@ static u8 igetbyte(intel8x0_t *chip, u32 offset)
return inb(chip->bmaddr + offset);
}
-static u16 igetword(intel8x0_t *chip, u32 offset)
+static u16 igetword(struct intel8x0m *chip, u32 offset)
{
if (chip->bm_mmio)
return readw(chip->remap_bmaddr + offset);
@@ -270,7 +269,7 @@ static u16 igetword(intel8x0_t *chip, u32 offset)
return inw(chip->bmaddr + offset);
}
-static u32 igetdword(intel8x0_t *chip, u32 offset)
+static u32 igetdword(struct intel8x0m *chip, u32 offset)
{
if (chip->bm_mmio)
return readl(chip->remap_bmaddr + offset);
@@ -278,7 +277,7 @@ static u32 igetdword(intel8x0_t *chip, u32 offset)
return inl(chip->bmaddr + offset);
}
-static void iputbyte(intel8x0_t *chip, u32 offset, u8 val)
+static void iputbyte(struct intel8x0m *chip, u32 offset, u8 val)
{
if (chip->bm_mmio)
writeb(val, chip->remap_bmaddr + offset);
@@ -286,7 +285,7 @@ static void iputbyte(intel8x0_t *chip, u32 offset, u8 val)
outb(val, chip->bmaddr + offset);
}
-static void iputword(intel8x0_t *chip, u32 offset, u16 val)
+static void iputword(struct intel8x0m *chip, u32 offset, u16 val)
{
if (chip->bm_mmio)
writew(val, chip->remap_bmaddr + offset);
@@ -294,7 +293,7 @@ static void iputword(intel8x0_t *chip, u32 offset, u16 val)
outw(val, chip->bmaddr + offset);
}
-static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
+static void iputdword(struct intel8x0m *chip, u32 offset, u32 val)
{
if (chip->bm_mmio)
writel(val, chip->remap_bmaddr + offset);
@@ -306,7 +305,7 @@ static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
* Lowlevel I/O - AC'97 registers
*/
-static u16 iagetword(intel8x0_t *chip, u32 offset)
+static u16 iagetword(struct intel8x0m *chip, u32 offset)
{
if (chip->mmio)
return readw(chip->remap_addr + offset);
@@ -314,7 +313,7 @@ static u16 iagetword(intel8x0_t *chip, u32 offset)
return inw(chip->addr + offset);
}
-static void iaputword(intel8x0_t *chip, u32 offset, u16 val)
+static void iaputword(struct intel8x0m *chip, u32 offset, u16 val)
{
if (chip->mmio)
writew(val, chip->remap_addr + offset);
@@ -331,7 +330,7 @@ static void iaputword(intel8x0_t *chip, u32 offset, u16 val)
*/
/* return the GLOB_STA bit for the corresponding codec */
-static unsigned int get_ich_codec_bit(intel8x0_t *chip, unsigned int codec)
+static unsigned int get_ich_codec_bit(struct intel8x0m *chip, unsigned int codec)
{
static unsigned int codec_bit[3] = {
ICH_PCR, ICH_SCR, ICH_TCR
@@ -340,7 +339,7 @@ static unsigned int get_ich_codec_bit(intel8x0_t *chip, unsigned int codec)
return codec_bit[codec];
}
-static int snd_intel8x0m_codec_semaphore(intel8x0_t *chip, unsigned int codec)
+static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int codec)
{
int time;
@@ -370,11 +369,11 @@ static int snd_intel8x0m_codec_semaphore(intel8x0_t *chip, unsigned int codec)
return -EBUSY;
}
-static void snd_intel8x0_codec_write(ac97_t *ac97,
+static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0m *chip = ac97->private_data;
if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
@@ -383,10 +382,10 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
iaputword(chip, reg + ac97->num * 0x80, val);
}
-static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
+static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
unsigned short reg)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0m *chip = ac97->private_data;
unsigned short res;
unsigned int tmp;
@@ -398,7 +397,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
res = iagetword(chip, reg + ac97->num * 0x80);
if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
/* reset RCS and preserve other R/WC bits */
- iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
+ iputdword(chip, ICHREG(GLOB_STA),
+ tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
if (! chip->in_ac97_init)
snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg);
res = 0xffff;
@@ -413,7 +413,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
/*
* DMA I/O
*/
-static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
+static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev)
{
int idx;
u32 *bdbar = ichdev->bdbar;
@@ -460,7 +460,7 @@ static void snd_intel8x0_setup_periods(intel8x0_t *chip, ichdev_t *ichdev)
* Interrupt handler
*/
-static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
+static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ichdev)
{
unsigned long port = ichdev->reg_offset;
int civ, i, step;
@@ -489,8 +489,15 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
for (i = 0; i < step; i++) {
ichdev->lvi_frag++;
ichdev->lvi_frag %= ichdev->frags;
- ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
- // printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n", ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2], ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port), inl(port + 4), inb(port + ICH_REG_OFF_CR));
+ ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf +
+ ichdev->lvi_frag *
+ ichdev->fragsize1);
+#if 0
+ printk("new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+ ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
+ ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
+ inl(port + 4), inb(port + ICH_REG_OFF_CR));
+#endif
if (--ichdev->ack == 0) {
ichdev->ack = ichdev->ack_reload;
ack = 1;
@@ -506,8 +513,8 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- intel8x0_t *chip = dev_id;
- ichdev_t *ichdev;
+ struct intel8x0m *chip = dev_id;
+ struct ichdev *ichdev;
unsigned int status;
unsigned int i;
@@ -541,10 +548,10 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs
* PCM part
*/
-static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
unsigned char val = 0;
unsigned long port = ichdev->reg_offset;
@@ -576,21 +583,21 @@ static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
return 0;
}
-static int snd_intel8x0_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_intel8x0_hw_free(snd_pcm_substream_t * substream)
+static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
+ struct ichdev *ichdev = get_ichdev(substream);
size_t ptr1, ptr;
ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << chip->pcm_pos_shift;
@@ -604,11 +611,11 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
return bytes_to_frames(substream->runtime, ptr);
}
-static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
+static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ichdev_t *ichdev = get_ichdev(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct ichdev *ichdev = get_ichdev(substream);
ichdev->physbuf = runtime->dma_addr;
ichdev->size = snd_pcm_lib_buffer_bytes(substream);
@@ -619,7 +626,7 @@ static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_hardware_t snd_intel8x0m_stream =
+static struct snd_pcm_hardware snd_intel8x0m_stream =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -641,58 +648,59 @@ static snd_pcm_hardware_t snd_intel8x0m_stream =
};
-static int snd_intel8x0m_pcm_open(snd_pcm_substream_t * substream, ichdev_t *ichdev)
+static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
{
static unsigned int rates[] = { 8000, 9600, 12000, 16000 };
- static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
};
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
ichdev->substream = substream;
runtime->hw = snd_intel8x0m_stream;
- err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
+ err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates);
if ( err < 0 )
return err;
runtime->private_data = ichdev;
return 0;
}
-static int snd_intel8x0m_playback_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0m_playback_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMOUT]);
}
-static int snd_intel8x0m_playback_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0m_playback_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_MDMOUT].substream = NULL;
return 0;
}
-static int snd_intel8x0m_capture_open(snd_pcm_substream_t * substream)
+static int snd_intel8x0m_capture_open(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
return snd_intel8x0m_pcm_open(substream, &chip->ichd[ICHD_MDMIN]);
}
-static int snd_intel8x0m_capture_close(snd_pcm_substream_t * substream)
+static int snd_intel8x0m_capture_close(struct snd_pcm_substream *substream)
{
- intel8x0_t *chip = snd_pcm_substream_chip(substream);
+ struct intel8x0m *chip = snd_pcm_substream_chip(substream);
chip->ichd[ICHD_MDMIN].substream = NULL;
return 0;
}
-static snd_pcm_ops_t snd_intel8x0m_playback_ops = {
+static struct snd_pcm_ops snd_intel8x0m_playback_ops = {
.open = snd_intel8x0m_playback_open,
.close = snd_intel8x0m_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -703,7 +711,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static snd_pcm_ops_t snd_intel8x0m_capture_ops = {
+static struct snd_pcm_ops snd_intel8x0m_capture_ops = {
.open = snd_intel8x0m_capture_open,
.close = snd_intel8x0m_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -717,16 +725,17 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = {
struct ich_pcm_table {
char *suffix;
- snd_pcm_ops_t *playback_ops;
- snd_pcm_ops_t *capture_ops;
+ struct snd_pcm_ops *playback_ops;
+ struct snd_pcm_ops *capture_ops;
size_t prealloc_size;
size_t prealloc_max_size;
int ac97_idx;
};
-static int __devinit snd_intel8x0_pcm1(intel8x0_t *chip, int device, struct ich_pcm_table *rec)
+static int __devinit snd_intel8x0_pcm1(struct intel8x0m *chip, int device,
+ struct ich_pcm_table *rec)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
char name[32];
@@ -772,7 +781,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
},
};
-static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
+static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
{
int i, tblsize, device, err;
struct ich_pcm_table *tbl, *rec;
@@ -819,27 +828,27 @@ static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
* Mixer part
*/
-static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- intel8x0_t *chip = bus->private_data;
+ struct intel8x0m *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
+static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
{
- intel8x0_t *chip = ac97->private_data;
+ struct intel8x0m *chip = ac97->private_data;
chip->ac97 = NULL;
}
-static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
+static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- ac97_t *x97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ struct snd_ac97 *x97;
int err;
unsigned int glob_sta = 0;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
};
@@ -880,7 +889,8 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
__err:
/* clear the cold-reset bit for the next chance */
if (chip->device_type != DEVICE_ALI)
- iputdword(chip, ICHREG(GLOB_CNT), igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);
+ iputdword(chip, ICHREG(GLOB_CNT),
+ igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_AC97COLD);
return err;
}
@@ -889,11 +899,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
*
*/
-#define do_delay(chip) do {\
- schedule_timeout_uninterruptible(1);\
-} while (0)
-
-static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
+static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
{
unsigned long end_time;
unsigned int cnt, status, nstatus;
@@ -914,9 +920,10 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
do {
if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
goto __ok;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT)));
+ snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
+ igetdword(chip, ICHREG(GLOB_CNT)));
return -EIO;
__ok:
@@ -927,14 +934,16 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
*/
end_time = jiffies + HZ;
do {
- status = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ status = igetdword(chip, ICHREG(GLOB_STA)) &
+ (ICH_PCR | ICH_SCR | ICH_TCR);
if (status)
break;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
if (! status) {
/* no codec is found */
- snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n", igetdword(chip, ICHREG(GLOB_STA)));
+ snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n",
+ igetdword(chip, ICHREG(GLOB_STA)));
return -EIO;
}
@@ -944,7 +953,7 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
/* wait for other codecs ready status. */
end_time = jiffies + HZ / 4;
while (status != nstatus && time_after_eq(end_time, jiffies)) {
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus;
}
@@ -956,10 +965,11 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
/* wait until all the probed codecs are ready */
end_time = jiffies + HZ;
do {
- nstatus = igetdword(chip, ICHREG(GLOB_STA)) & (ICH_PCR | ICH_SCR | ICH_TCR);
+ nstatus = igetdword(chip, ICHREG(GLOB_STA)) &
+ (ICH_PCR | ICH_SCR | ICH_TCR);
if (status == nstatus)
break;
- do_delay(chip);
+ schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
}
@@ -971,7 +981,7 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
return 0;
}
-static int snd_intel8x0_chip_init(intel8x0_t *chip, int probing)
+static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing)
{
unsigned int i;
int err;
@@ -992,7 +1002,7 @@ static int snd_intel8x0_chip_init(intel8x0_t *chip, int probing)
return 0;
}
-static int snd_intel8x0_free(intel8x0_t *chip)
+static int snd_intel8x0_free(struct intel8x0m *chip)
{
unsigned int i;
@@ -1014,7 +1024,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
if (chip->remap_bmaddr)
iounmap(chip->remap_bmaddr);
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
@@ -1025,43 +1035,50 @@ static int snd_intel8x0_free(intel8x0_t *chip)
/*
* power management
*/
-static int intel8x0m_suspend(snd_card_t *card, pm_message_t state)
+static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state)
{
- intel8x0_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct intel8x0m *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < chip->pcm_devs; i++)
snd_pcm_suspend_all(chip->pcm[i]);
- if (chip->ac97)
- snd_ac97_suspend(chip->ac97);
- pci_disable_device(chip->pci);
+ snd_ac97_suspend(chip->ac97);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int intel8x0m_resume(snd_card_t *card)
+static int intel8x0m_resume(struct pci_dev *pci)
{
- intel8x0_t *chip = card->pm_private_data;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct intel8x0m *chip = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
snd_intel8x0_chip_init(chip, 0);
- if (chip->ac97)
- snd_ac97_resume(chip->ac97);
+ snd_ac97_resume(chip->ac97);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static void snd_intel8x0m_proc_read(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
+#ifdef CONFIG_PROC_FS
+static void snd_intel8x0m_proc_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
{
- intel8x0_t *chip = entry->private_data;
+ struct intel8x0m *chip = entry->private_data;
unsigned int tmp;
snd_iprintf(buffer, "Intel8x0m\n\n");
if (chip->device_type == DEVICE_ALI)
return;
tmp = igetdword(chip, ICHREG(GLOB_STA));
- snd_iprintf(buffer, "Global control : 0x%08x\n", igetdword(chip, ICHREG(GLOB_CNT)));
+ snd_iprintf(buffer, "Global control : 0x%08x\n",
+ igetdword(chip, ICHREG(GLOB_CNT)));
snd_iprintf(buffer, "Global status : 0x%08x\n", tmp);
snd_iprintf(buffer, "AC'97 codecs ready :%s%s%s%s\n",
tmp & ICH_PCR ? " primary" : "",
@@ -1070,17 +1087,21 @@ static void snd_intel8x0m_proc_read(snd_info_entry_t * entry,
(tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : "");
}
-static void __devinit snd_intel8x0m_proc_init(intel8x0_t * chip)
+static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "intel8x0m", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0m_proc_read);
}
+#else /* !CONFIG_PROC_FS */
+#define snd_intel8x0m_proc_init(chip)
+#endif /* CONFIG_PROC_FS */
+
-static int snd_intel8x0_dev_free(snd_device_t *device)
+static int snd_intel8x0_dev_free(struct snd_device *device)
{
- intel8x0_t *chip = device->device_data;
+ struct intel8x0m *chip = device->device_data;
return snd_intel8x0_free(chip);
}
@@ -1089,17 +1110,17 @@ struct ich_reg_info {
unsigned int offset;
};
-static int __devinit snd_intel8x0m_create(snd_card_t * card,
+static int __devinit snd_intel8x0m_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type,
- intel8x0_t ** r_intel8x0)
+ struct intel8x0m ** r_intel8x0)
{
- intel8x0_t *chip;
+ struct intel8x0m *chip;
int err;
unsigned int i;
unsigned int int_sta_masks;
- ichdev_t *ichdev;
- static snd_device_ops_t ops = {
+ struct ichdev *ichdev;
+ static struct snd_device_ops ops = {
.dev_free = snd_intel8x0_dev_free,
};
static struct ich_reg_info intel_regs[2] = {
@@ -1164,7 +1185,8 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
}
port_inited:
- if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+ if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card->shortname, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_intel8x0_free(chip);
return -EBUSY;
@@ -1221,8 +1243,6 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
return err;
}
- snd_card_set_pm_callback(card, intel8x0m_suspend, intel8x0m_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_intel8x0_free(chip);
return err;
@@ -1263,8 +1283,8 @@ static struct shortname_table {
static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- intel8x0_t *chip;
+ struct snd_card *card;
+ struct intel8x0m *chip;
int err;
struct shortname_table *name;
@@ -1286,6 +1306,7 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = chip;
if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) {
snd_card_free(card);
@@ -1320,7 +1341,10 @@ static struct pci_driver driver = {
.id_table = snd_intel8x0m_ids,
.probe = snd_intel8x0m_probe,
.remove = __devexit_p(snd_intel8x0m_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = intel8x0m_suspend,
+ .resume = intel8x0m_resume,
+#endif
};
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index a110d664f626..4eddb512c12f 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -41,8 +41,16 @@
// Debug Stuff
// ----------------------------------------------------------------------------
#define K1212_DEBUG_LEVEL 0
-#define K1212_DEBUG_PRINTK printk
-//#define K1212_DEBUG_PRINTK(x...) printk("<0>" x)
+#if K1212_DEBUG_LEVEL > 0
+#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args)
+#else
+#define K1212_DEBUG_PRINTK(fmt,...)
+#endif
+#if K1212_DEBUG_LEVEL > 1
+#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args)
+#else
+#define K1212_DEBUG_PRINTK_VERBOSE(fmt,...)
+#endif
// ----------------------------------------------------------------------------
// Record/Play Buffer Allocation Method. If K1212_LARGEALLOC is defined all
@@ -53,7 +61,7 @@
// ----------------------------------------------------------------------------
// Valid states of the Korg 1212 I/O card.
// ----------------------------------------------------------------------------
-typedef enum {
+enum CardState {
K1212_STATE_NONEXISTENT, // there is no card here
K1212_STATE_UNINITIALIZED, // the card is awaiting DSP download
K1212_STATE_DSP_IN_PROCESS, // the card is currently downloading its DSP code
@@ -69,13 +77,13 @@ typedef enum {
K1212_STATE_ERRORSTOP, // the card has stopped itself because of an error and we
// are in the process of cleaning things up.
K1212_STATE_MAX_STATE // state values of this and beyond are invalid
-} CardState;
+};
// ----------------------------------------------------------------------------
// The following enumeration defines the constants written to the card's
// host-to-card doorbell to initiate a command.
// ----------------------------------------------------------------------------
-typedef enum {
+enum korg1212_dbcnst {
K1212_DB_RequestForData = 0, // sent by the card to request a buffer fill.
K1212_DB_TriggerPlay = 1, // starts playback/record on the card.
K1212_DB_SelectPlayMode = 2, // select monitor, playback setup, or stop.
@@ -93,14 +101,14 @@ typedef enum {
K1212_DB_DSPDownloadDone = 0xAE, // sent by the card to indicate the download has
// completed.
K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware.
-} korg1212_dbcnst_t;
+};
// ----------------------------------------------------------------------------
// The following enumeration defines return codes
// to the Korg 1212 I/O driver.
// ----------------------------------------------------------------------------
-typedef enum {
+enum snd_korg1212rc {
K1212_CMDRET_Success = 0, // command was successfully placed
K1212_CMDRET_DIOCFailure, // the DeviceIoControl call failed
K1212_CMDRET_PMFailure, // the protected mode call failed
@@ -118,27 +126,27 @@ typedef enum {
K1212_CMDRET_BadDevice, // the specified wave device was out of range
K1212_CMDRET_BadFormat // the specified wave format is unsupported
-} snd_korg1212rc;
+};
// ----------------------------------------------------------------------------
// The following enumeration defines the constants used to select the play
// mode for the card in the SelectPlayMode command.
// ----------------------------------------------------------------------------
-typedef enum {
+enum PlayModeSelector {
K1212_MODE_SetupPlay = 0x00000001, // provides card with pre-play information
K1212_MODE_MonitorOn = 0x00000002, // tells card to turn on monitor mode
K1212_MODE_MonitorOff = 0x00000004, // tells card to turn off monitor mode
K1212_MODE_StopPlay = 0x00000008 // stops playback on the card
-} PlayModeSelector;
+};
// ----------------------------------------------------------------------------
// The following enumeration defines the constants used to select the monitor
// mode for the card in the SetMonitorMode command.
// ----------------------------------------------------------------------------
-typedef enum {
+enum MonitorModeSelector {
K1212_MONMODE_Off = 0, // tells card to turn off monitor mode
K1212_MONMODE_On // tells card to turn on monitor mode
-} MonitorModeSelector;
+};
#define MAILBOX0_OFFSET 0x40 // location of mailbox 0 relative to base address
#define MAILBOX1_OFFSET 0x44 // location of mailbox 1 relative to base address
@@ -180,7 +188,7 @@ typedef enum {
#define K1212_CHANNELS (K1212_ADAT_CHANNELS + K1212_ANALOG_CHANNELS)
#define K1212_MIN_CHANNELS 1
#define K1212_MAX_CHANNELS K1212_CHANNELS
-#define K1212_FRAME_SIZE (sizeof(KorgAudioFrame))
+#define K1212_FRAME_SIZE (sizeof(struct KorgAudioFrame))
#define K1212_MAX_SAMPLES (kPlayBufferFrames*kNumBuffers)
#define K1212_PERIODS (kNumBuffers)
#define K1212_PERIOD_BYTES (K1212_FRAME_SIZE*kPlayBufferFrames)
@@ -256,14 +264,7 @@ typedef enum {
#include "korg1212-firmware.h"
-typedef struct _snd_korg1212 korg1212_t;
-
-typedef u16 K1212Sample; // channels 0-9 use 16 bit samples
-typedef u32 K1212SpdifSample; // channels 10-11 use 32 bits - only 20 are sent
- // across S/PDIF.
-typedef u32 K1212TimeCodeSample; // holds the ADAT timecode value
-
-typedef enum {
+enum ClockSourceIndex {
K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz
K1212_CLKIDX_AdatAt48K, // selects source as ADAT at 48 kHz
K1212_CLKIDX_WordAt44_1K, // selects source as S/PDIF at 44.1 kHz
@@ -271,36 +272,36 @@ typedef enum {
K1212_CLKIDX_LocalAt44_1K, // selects source as local clock at 44.1 kHz
K1212_CLKIDX_LocalAt48K, // selects source as local clock at 48 kHz
K1212_CLKIDX_Invalid // used to check validity of the index
-} ClockSourceIndex;
+};
-typedef enum {
+enum ClockSourceType {
K1212_CLKIDX_Adat = 0, // selects source as ADAT
K1212_CLKIDX_Word, // selects source as S/PDIF
K1212_CLKIDX_Local // selects source as local clock
-} ClockSourceType;
+};
-typedef struct KorgAudioFrame {
- K1212Sample frameData16[k16BitChannels];
- K1212SpdifSample frameData32[k32BitChannels];
- K1212TimeCodeSample timeCodeVal;
-} KorgAudioFrame;
+struct KorgAudioFrame {
+ u16 frameData16[k16BitChannels]; /* channels 0-9 use 16 bit samples */
+ u32 frameData32[k32BitChannels]; /* channels 10-11 use 32 bits - only 20 are sent across S/PDIF */
+ u32 timeCodeVal; /* holds the ADAT timecode value */
+};
-typedef struct KorgAudioBuffer {
- KorgAudioFrame bufferData[kPlayBufferFrames]; /* buffer definition */
-} KorgAudioBuffer;
+struct KorgAudioBuffer {
+ struct KorgAudioFrame bufferData[kPlayBufferFrames]; /* buffer definition */
+};
-typedef struct KorgSharedBuffer {
+struct KorgSharedBuffer {
#ifdef K1212_LARGEALLOC
- KorgAudioBuffer playDataBufs[kNumBuffers];
- KorgAudioBuffer recordDataBufs[kNumBuffers];
+ struct KorgAudioBuffer playDataBufs[kNumBuffers];
+ struct KorgAudioBuffer recordDataBufs[kNumBuffers];
#endif
short volumeData[kAudioChannels];
u32 cardCommand;
u16 routeData [kAudioChannels];
u32 AdatTimeCode; // ADAT timecode value
-} KorgSharedBuffer;
+};
-typedef struct SensBits {
+struct SensBits {
union {
struct {
unsigned int leftChanVal:8;
@@ -315,12 +316,12 @@ typedef struct SensBits {
} v;
u16 rightSensBits;
} r;
-} SensBits;
+};
-struct _snd_korg1212 {
- snd_card_t *card;
+struct snd_korg1212 {
+ struct snd_card *card;
struct pci_dev *pci;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int irq;
spinlock_t lock;
@@ -347,10 +348,10 @@ struct _snd_korg1212 {
u32 DataBufsSize;
- KorgAudioBuffer * playDataBufsPtr;
- KorgAudioBuffer * recordDataBufsPtr;
+ struct KorgAudioBuffer * playDataBufsPtr;
+ struct KorgAudioBuffer * recordDataBufsPtr;
- KorgSharedBuffer * sharedBufferPtr;
+ struct KorgSharedBuffer * sharedBufferPtr;
u32 RecDataPhy;
u32 PlayDataPhy;
@@ -374,20 +375,20 @@ struct _snd_korg1212 {
int channels;
int currentBuffer;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
pid_t capture_pid;
pid_t playback_pid;
- CardState cardState;
+ enum CardState cardState;
int running;
int idleMonitorOn; // indicates whether the card is in idle monitor mode.
u32 cmdRetryCount; // tracks how many times we have retried sending to the card.
- ClockSourceIndex clkSrcRate; // sample rate and clock source
+ enum ClockSourceIndex clkSrcRate; // sample rate and clock source
- ClockSourceType clkSource; // clock source
+ enum ClockSourceType clkSource; // clock source
int clkRate; // clock rate
int volumePhase[kAudioChannels];
@@ -432,60 +433,58 @@ static struct pci_device_id snd_korg1212_ids[] = {
{ 0, },
};
-static char* stateName[] = {
- "Non-existent",
- "Uninitialized",
- "DSP download in process",
- "DSP download complete",
- "Ready",
- "Open",
- "Setup for play",
- "Playing",
- "Monitor mode on",
- "Calibrating",
- "Invalid"
+MODULE_DEVICE_TABLE(pci, snd_korg1212_ids);
+
+static char *stateName[] = {
+ "Non-existent",
+ "Uninitialized",
+ "DSP download in process",
+ "DSP download complete",
+ "Ready",
+ "Open",
+ "Setup for play",
+ "Playing",
+ "Monitor mode on",
+ "Calibrating",
+ "Invalid"
};
-static char* clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" };
+static char *clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" };
-static char* clockSourceName[] = {
- "ADAT at 44.1 kHz",
- "ADAT at 48 kHz",
- "S/PDIF at 44.1 kHz",
- "S/PDIF at 48 kHz",
- "local clock at 44.1 kHz",
- "local clock at 48 kHz"
+static char *clockSourceName[] = {
+ "ADAT at 44.1 kHz",
+ "ADAT at 48 kHz",
+ "S/PDIF at 44.1 kHz",
+ "S/PDIF at 48 kHz",
+ "local clock at 44.1 kHz",
+ "local clock at 48 kHz"
};
-static char* channelName[] = {
- "ADAT-1",
- "ADAT-2",
- "ADAT-3",
- "ADAT-4",
- "ADAT-5",
- "ADAT-6",
- "ADAT-7",
- "ADAT-8",
- "Analog-L",
- "Analog-R",
- "SPDIF-L",
- "SPDIF-R",
+static char *channelName[] = {
+ "ADAT-1",
+ "ADAT-2",
+ "ADAT-3",
+ "ADAT-4",
+ "ADAT-5",
+ "ADAT-6",
+ "ADAT-7",
+ "ADAT-8",
+ "Analog-L",
+ "Analog-R",
+ "SPDIF-L",
+ "SPDIF-R",
};
-static u16 ClockSourceSelector[] =
- {0x8000, // selects source as ADAT at 44.1 kHz
- 0x0000, // selects source as ADAT at 48 kHz
- 0x8001, // selects source as S/PDIF at 44.1 kHz
- 0x0001, // selects source as S/PDIF at 48 kHz
- 0x8002, // selects source as local clock at 44.1 kHz
- 0x0002 // selects source as local clock at 48 kHz
- };
-
-static snd_korg1212rc rc;
-
-MODULE_DEVICE_TABLE(pci, snd_korg1212_ids);
+static u16 ClockSourceSelector[] = {
+ 0x8000, // selects source as ADAT at 44.1 kHz
+ 0x0000, // selects source as ADAT at 48 kHz
+ 0x8001, // selects source as S/PDIF at 44.1 kHz
+ 0x0001, // selects source as S/PDIF at 48 kHz
+ 0x8002, // selects source as local clock at 44.1 kHz
+ 0x0002 // selects source as local clock at 48 kHz
+};
-typedef union swap_u32 { unsigned char c[4]; u32 i; } swap_u32;
+union swap_u32 { unsigned char c[4]; u32 i; };
#ifdef SNDRV_BIG_ENDIAN
static u32 LowerWordSwap(u32 swappee)
@@ -493,7 +492,7 @@ static u32 LowerWordSwap(u32 swappee)
static u32 UpperWordSwap(u32 swappee)
#endif
{
- swap_u32 retVal, swapper;
+ union swap_u32 retVal, swapper;
swapper.i = swappee;
retVal.c[2] = swapper.c[3];
@@ -510,7 +509,7 @@ static u32 UpperWordSwap(u32 swappee)
static u32 LowerWordSwap(u32 swappee)
#endif
{
- swap_u32 retVal, swapper;
+ union swap_u32 retVal, swapper;
swapper.i = swappee;
retVal.c[2] = swapper.c[2];
@@ -521,45 +520,27 @@ static u32 LowerWordSwap(u32 swappee)
return retVal.i;
}
-#if 0 /* not used */
-
-static u32 EndianSwap(u32 swappee)
-{
- swap_u32 retVal, swapper;
-
- swapper.i = swappee;
- retVal.c[0] = swapper.c[3];
- retVal.c[1] = swapper.c[2];
- retVal.c[2] = swapper.c[1];
- retVal.c[3] = swapper.c[0];
-
- return retVal.i;
-}
-
-#endif /* not used */
-
#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition)
#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition)
#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition)
#define ClearBitInDWord(theWord,bitPosition) (*theWord) &= ~(0x00000001 << bitPosition)
-static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg1212_dbcnst_t doorbellVal,
- u32 mailBox0Val, u32 mailBox1Val, u32 mailBox2Val, u32 mailBox3Val)
+static int snd_korg1212_Send1212Command(struct snd_korg1212 *korg1212,
+ enum korg1212_dbcnst doorbellVal,
+ u32 mailBox0Val, u32 mailBox1Val,
+ u32 mailBox2Val, u32 mailBox3Val)
{
u32 retryCount;
u16 mailBox3Lo;
- snd_korg1212rc rc = K1212_CMDRET_Success;
+ int rc = K1212_CMDRET_Success;
if (!korg1212->outDoorbellPtr) {
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: CardUninitialized\n");
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: CardUninitialized\n");
return K1212_CMDRET_CardUninitialized;
}
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n", doorbellVal, mailBox0Val, stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n",
+ doorbellVal, mailBox0Val, stateName[korg1212->cardState]);
for (retryCount = 0; retryCount < MAX_COMMAND_RETRIES; retryCount++) {
writel(mailBox3Val, korg1212->mailbox3Ptr);
writel(mailBox2Val, korg1212->mailbox2Ptr);
@@ -586,9 +567,7 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121
mailBox3Lo = readl(korg1212->mailbox3Ptr);
if (mailBox3Lo & COMMAND_ACK_MASK) {
if ((mailBox3Lo & DOORBELL_VAL_MASK) == (doorbellVal & DOORBELL_VAL_MASK)) {
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- Success\n");
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- Success\n");
rc = K1212_CMDRET_Success;
break;
}
@@ -597,9 +576,7 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121
korg1212->cmdRetryCount += retryCount;
if (retryCount >= MAX_COMMAND_RETRIES) {
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- NoAckFromCard\n");
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- NoAckFromCard\n");
rc = K1212_CMDRET_NoAckFromCard;
}
@@ -607,7 +584,7 @@ static snd_korg1212rc snd_korg1212_Send1212Command(korg1212_t *korg1212, korg121
}
/* spinlock already held */
-static void snd_korg1212_SendStop(korg1212_t *korg1212)
+static void snd_korg1212_SendStop(struct snd_korg1212 *korg1212)
{
if (! korg1212->stop_pending_cnt) {
korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
@@ -618,7 +595,7 @@ static void snd_korg1212_SendStop(korg1212_t *korg1212)
}
}
-static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212)
+static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212)
{
unsigned long flags;
spin_lock_irqsave(&korg1212->lock, flags);
@@ -631,17 +608,17 @@ static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212)
/* timer callback for checking the ack of stop request */
static void snd_korg1212_timer_func(unsigned long data)
{
- korg1212_t *korg1212 = (korg1212_t *) data;
+ struct snd_korg1212 *korg1212 = (struct snd_korg1212 *) data;
+ unsigned long flags;
- spin_lock(&korg1212->lock);
+ spin_lock_irqsave(&korg1212->lock, flags);
if (korg1212->sharedBufferPtr->cardCommand == 0) {
/* ack'ed */
korg1212->stop_pending_cnt = 0;
korg1212->dsp_stop_is_processed = 1;
wake_up(&korg1212->wait);
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Stop ack'ed [%s]\n",
+ stateName[korg1212->cardState]);
} else {
if (--korg1212->stop_pending_cnt > 0) {
/* reprogram timer */
@@ -652,17 +629,17 @@ static void snd_korg1212_timer_func(unsigned long data)
korg1212->sharedBufferPtr->cardCommand = 0;
korg1212->dsp_stop_is_processed = 1;
wake_up(&korg1212->wait);
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n",
+ stateName[korg1212->cardState]);
}
}
- spin_unlock(&korg1212->lock);
+ spin_unlock_irqrestore(&korg1212->lock, flags);
}
-static void snd_korg1212_TurnOnIdleMonitor(korg1212_t *korg1212)
+static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212)
{
unsigned long flags;
+ int rc;
udelay(INTERCOMMAND_DELAY);
spin_lock_irqsave(&korg1212->lock, flags);
@@ -670,9 +647,10 @@ static void snd_korg1212_TurnOnIdleMonitor(korg1212_t *korg1212)
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
K1212_MODE_MonitorOn, 0, 0, 0);
spin_unlock_irqrestore(&korg1212->lock, flags);
+ return rc;
}
-static void snd_korg1212_TurnOffIdleMonitor(korg1212_t *korg1212)
+static void snd_korg1212_TurnOffIdleMonitor(struct snd_korg1212 *korg1212)
{
if (korg1212->idleMonitorOn) {
snd_korg1212_SendStopAndWait(korg1212);
@@ -680,16 +658,15 @@ static void snd_korg1212_TurnOffIdleMonitor(korg1212_t *korg1212)
}
}
-static inline void snd_korg1212_setCardState(korg1212_t * korg1212, CardState csState)
+static inline void snd_korg1212_setCardState(struct snd_korg1212 * korg1212, enum CardState csState)
{
korg1212->cardState = csState;
}
-static int snd_korg1212_OpenCard(korg1212_t * korg1212)
+static int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n",
+ stateName[korg1212->cardState], korg1212->opencnt);
down(&korg1212->open_mutex);
if (korg1212->opencnt++ == 0) {
snd_korg1212_TurnOffIdleMonitor(korg1212);
@@ -700,11 +677,10 @@ static int snd_korg1212_OpenCard(korg1212_t * korg1212)
return 1;
}
-static int snd_korg1212_CloseCard(korg1212_t * korg1212)
+static int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", stateName[korg1212->cardState], korg1212->opencnt);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n",
+ stateName[korg1212->cardState], korg1212->opencnt);
down(&korg1212->open_mutex);
if (--(korg1212->opencnt)) {
@@ -713,12 +689,11 @@ static int snd_korg1212_CloseCard(korg1212_t * korg1212)
}
if (korg1212->cardState == K1212_STATE_SETUP) {
- rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
+ int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
K1212_MODE_StopPlay, 0, 0, 0);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
-
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
if (rc != K1212_CMDRET_Success) {
up(&korg1212->open_mutex);
return 0;
@@ -737,11 +712,12 @@ static int snd_korg1212_CloseCard(korg1212_t * korg1212)
}
/* spinlock already held */
-static int snd_korg1212_SetupForPlay(korg1212_t * korg1212)
+static int snd_korg1212_SetupForPlay(struct snd_korg1212 * korg1212)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay [%s] %d\n", stateName[korg1212->cardState], korg1212->setcnt);
-#endif
+ int rc;
+
+ K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay [%s] %d\n",
+ stateName[korg1212->cardState], korg1212->setcnt);
if (korg1212->setcnt++)
return 0;
@@ -749,10 +725,9 @@ static int snd_korg1212_SetupForPlay(korg1212_t * korg1212)
snd_korg1212_setCardState(korg1212, K1212_STATE_SETUP);
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
K1212_MODE_SetupPlay, 0, 0, 0);
-
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
if (rc != K1212_CMDRET_Success) {
return 1;
}
@@ -760,22 +735,21 @@ static int snd_korg1212_SetupForPlay(korg1212_t * korg1212)
}
/* spinlock already held */
-static int snd_korg1212_TriggerPlay(korg1212_t * korg1212)
+static int snd_korg1212_TriggerPlay(struct snd_korg1212 * korg1212)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay [%s] %d\n", stateName[korg1212->cardState], korg1212->playcnt);
-#endif
+ int rc;
+
+ K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay [%s] %d\n",
+ stateName[korg1212->cardState], korg1212->playcnt);
if (korg1212->playcnt++)
return 0;
snd_korg1212_setCardState(korg1212, K1212_STATE_PLAYING);
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_TriggerPlay, 0, 0, 0, 0);
-
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
-
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
if (rc != K1212_CMDRET_Success) {
return 1;
}
@@ -783,11 +757,10 @@ static int snd_korg1212_TriggerPlay(korg1212_t * korg1212)
}
/* spinlock already held */
-static int snd_korg1212_StopPlay(korg1212_t * korg1212)
+static int snd_korg1212_StopPlay(struct snd_korg1212 * korg1212)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: StopPlay [%s] %d\n", stateName[korg1212->cardState], korg1212->playcnt);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: StopPlay [%s] %d\n",
+ stateName[korg1212->cardState], korg1212->playcnt);
if (--(korg1212->playcnt))
return 0;
@@ -801,7 +774,7 @@ static int snd_korg1212_StopPlay(korg1212_t * korg1212)
return 0;
}
-static void snd_korg1212_EnableCardInterrupts(korg1212_t * korg1212)
+static void snd_korg1212_EnableCardInterrupts(struct snd_korg1212 * korg1212)
{
writel(PCI_INT_ENABLE_BIT |
PCI_DOORBELL_INT_ENABLE_BIT |
@@ -813,37 +786,37 @@ static void snd_korg1212_EnableCardInterrupts(korg1212_t * korg1212)
#if 0 /* not used */
-static int snd_korg1212_SetMonitorMode(korg1212_t *korg1212, MonitorModeSelector mode)
+static int snd_korg1212_SetMonitorMode(struct snd_korg1212 *korg1212,
+ enum MonitorModeSelector mode)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: SetMonitorMode [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: SetMonitorMode [%s]\n",
+ stateName[korg1212->cardState]);
switch (mode) {
- case K1212_MONMODE_Off:
- if (korg1212->cardState != K1212_STATE_MONITOR) {
- return 0;
- } else {
- snd_korg1212_SendStopAndWait(korg1212);
- snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
- }
- break;
-
- case K1212_MONMODE_On:
- if (korg1212->cardState != K1212_STATE_OPEN) {
- return 0;
- } else {
- snd_korg1212_setCardState(korg1212, K1212_STATE_MONITOR);
- rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
- K1212_MODE_MonitorOn, 0, 0, 0);
- if (rc != K1212_CMDRET_Success) {
- return 0;
- }
- }
- break;
+ case K1212_MONMODE_Off:
+ if (korg1212->cardState != K1212_STATE_MONITOR)
+ return 0;
+ else {
+ snd_korg1212_SendStopAndWait(korg1212);
+ snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN);
+ }
+ break;
+
+ case K1212_MONMODE_On:
+ if (korg1212->cardState != K1212_STATE_OPEN)
+ return 0;
+ else {
+ int rc;
+ snd_korg1212_setCardState(korg1212, K1212_STATE_MONITOR);
+ rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
+ K1212_MODE_MonitorOn, 0, 0, 0);
+ if (rc != K1212_CMDRET_Success)
+ return 0;
+ }
+ break;
- default:
- return 0;
+ default:
+ return 0;
}
return 1;
@@ -851,44 +824,44 @@ static int snd_korg1212_SetMonitorMode(korg1212_t *korg1212, MonitorModeSelector
#endif /* not used */
-static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212)
+static inline int snd_korg1212_use_is_exclusive(struct snd_korg1212 *korg1212)
{
- int ret = 1;
+ if (korg1212->playback_pid != korg1212->capture_pid &&
+ korg1212->playback_pid >= 0 && korg1212->capture_pid >= 0)
+ return 0;
- if ((korg1212->playback_pid != korg1212->capture_pid) &&
- (korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) {
- ret = 0;
- }
- return ret;
+ return 1;
}
-static int snd_korg1212_SetRate(korg1212_t *korg1212, int rate)
+static int snd_korg1212_SetRate(struct snd_korg1212 *korg1212, int rate)
{
- static ClockSourceIndex s44[] = { K1212_CLKIDX_AdatAt44_1K,
- K1212_CLKIDX_WordAt44_1K,
- K1212_CLKIDX_LocalAt44_1K };
- static ClockSourceIndex s48[] = {
- K1212_CLKIDX_AdatAt48K,
- K1212_CLKIDX_WordAt48K,
- K1212_CLKIDX_LocalAt48K };
- int parm;
+ static enum ClockSourceIndex s44[] = {
+ K1212_CLKIDX_AdatAt44_1K,
+ K1212_CLKIDX_WordAt44_1K,
+ K1212_CLKIDX_LocalAt44_1K
+ };
+ static enum ClockSourceIndex s48[] = {
+ K1212_CLKIDX_AdatAt48K,
+ K1212_CLKIDX_WordAt48K,
+ K1212_CLKIDX_LocalAt48K
+ };
+ int parm, rc;
- if (!snd_korg1212_use_is_exclusive (korg1212)) {
- return -EBUSY;
- }
+ if (!snd_korg1212_use_is_exclusive (korg1212))
+ return -EBUSY;
- switch(rate) {
- case 44100:
- parm = s44[korg1212->clkSource];
- break;
+ switch (rate) {
+ case 44100:
+ parm = s44[korg1212->clkSource];
+ break;
- case 48000:
- parm = s48[korg1212->clkSource];
- break;
+ case 48000:
+ parm = s48[korg1212->clkSource];
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
+ }
korg1212->clkSrcRate = parm;
korg1212->clkRate = rate;
@@ -897,19 +870,18 @@ static int snd_korg1212_SetRate(korg1212_t *korg1212, int rate)
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate,
ClockSourceSelector[korg1212->clkSrcRate],
0, 0, 0);
-
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
return 0;
}
-static int snd_korg1212_SetClockSource(korg1212_t *korg1212, int source)
+static int snd_korg1212_SetClockSource(struct snd_korg1212 *korg1212, int source)
{
- if (source<0 || source >2)
- return -EINVAL;
+ if (source < 0 || source > 2)
+ return -EINVAL;
korg1212->clkSource = source;
@@ -918,14 +890,14 @@ static int snd_korg1212_SetClockSource(korg1212_t *korg1212, int source)
return 0;
}
-static void snd_korg1212_DisableCardInterrupts(korg1212_t *korg1212)
+static void snd_korg1212_DisableCardInterrupts(struct snd_korg1212 *korg1212)
{
writel(0, korg1212->statusRegPtr);
}
-static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
+static int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212)
{
- SensBits sensVals;
+ struct SensBits sensVals;
int bitPosition;
int channel;
int clkIs48K;
@@ -935,9 +907,8 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
u16 count;
unsigned long flags;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n",
+ stateName[korg1212->cardState]);
// ----------------------------------------------------------------------------
// initialize things. The local init bit is always set when writing to the
@@ -1006,19 +977,17 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
udelay(LOADSHIFT_DELAY);
for (bitPosition = 15; bitPosition >= 0; bitPosition--) { // for all the bits
- if (channel == 0) {
- if (sensVals.l.leftSensBits & (0x0001 << bitPosition)) {
+ if (channel == 0) {
+ if (sensVals.l.leftSensBits & (0x0001 << bitPosition))
SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high
- } else {
- ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low
- }
- } else {
- if (sensVals.r.rightSensBits & (0x0001 << bitPosition)) {
- SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high
- } else {
- ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low
- }
- }
+ else
+ ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low
+ } else {
+ if (sensVals.r.rightSensBits & (0x0001 << bitPosition))
+ SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high
+ else
+ ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low
+ }
ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS);
writew(controlValue, korg1212->sensRegPtr); // clock goes low
@@ -1059,12 +1028,11 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
udelay(SENSCLKPULSE_WIDTH);
if (monModeSet) {
- rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
+ int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode,
K1212_MODE_MonitorOn, 0, 0, 0);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
-
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
}
spin_unlock_irqrestore(&korg1212->lock, flags);
@@ -1072,23 +1040,22 @@ static int snd_korg1212_WriteADCSensitivity(korg1212_t *korg1212)
return 1;
}
-static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
+static void snd_korg1212_OnDSPDownloadComplete(struct snd_korg1212 *korg1212)
{
- int channel;
+ int channel, rc;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is complete. [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is complete. [%s]\n",
+ stateName[korg1212->cardState]);
// ----------------------------------------------------
// tell the card to boot
// ----------------------------------------------------
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_BootFromDSPPage4, 0, 0, 0, 0);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Boot from Page 4 - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
- mdelay(DSP_BOOT_DELAY_IN_MS);
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Boot from Page 4 - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
+ msleep(DSP_BOOT_DELAY_IN_MS);
// --------------------------------------------------------------------------------
// Let the card know where all the buffers are.
@@ -1102,9 +1069,9 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
0
);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
udelay(INTERCOMMAND_DELAY);
@@ -1116,10 +1083,9 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
0
);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Misc Memory - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
-
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Misc Memory - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
// --------------------------------------------------------------------------------
// Initialize the routing and volume tables, then update the card's state.
@@ -1138,16 +1104,16 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate,
ClockSourceSelector[korg1212->clkSrcRate],
0, 0, 0);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
- snd_korg1212_TurnOnIdleMonitor(korg1212);
+ rc = snd_korg1212_TurnOnIdleMonitor(korg1212);
snd_korg1212_setCardState(korg1212, K1212_STATE_READY);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE);
}
@@ -1155,7 +1121,7 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
u32 doorbellValue;
- korg1212_t *korg1212 = dev_id;
+ struct snd_korg1212 *korg1212 = dev_id;
if(irq != korg1212->irq)
return IRQ_NONE;
@@ -1176,9 +1142,9 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
switch (doorbellValue) {
case K1212_DB_DSPDownloadDone:
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n",
+ korg1212->irqcount, doorbellValue,
+ stateName[korg1212->cardState]);
if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) {
korg1212->dsp_is_loaded = 1;
wake_up(&korg1212->wait);
@@ -1189,10 +1155,10 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
// an error occurred - stop the card
// ------------------------------------------------------------------------
case K1212_DB_DMAERROR:
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
-#endif
- snd_printk(KERN_ERR "korg1212: DMA Error\n");
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n",
+ korg1212->irqcount, doorbellValue,
+ stateName[korg1212->cardState]);
+ snd_printk(KERN_ERR "korg1212: DMA Error\n");
korg1212->errorcnt++;
korg1212->totalerrorcnt++;
korg1212->sharedBufferPtr->cardCommand = 0;
@@ -1204,17 +1170,16 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
// the semaphore in case someone is waiting for this.
// ------------------------------------------------------------------------
case K1212_DB_CARDSTOPPED:
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n",
+ korg1212->irqcount, doorbellValue,
+ stateName[korg1212->cardState]);
korg1212->sharedBufferPtr->cardCommand = 0;
break;
default:
-#if K1212_DEBUG_LEVEL > 3
- K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].\n", korg1212->irqcount, doorbellValue,
- korg1212->currentBuffer, stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].\n",
+ korg1212->irqcount, doorbellValue,
+ korg1212->currentBuffer, stateName[korg1212->cardState]);
if ((korg1212->cardState > K1212_STATE_SETUP) || korg1212->idleMonitorOn) {
korg1212->currentBuffer++;
@@ -1246,19 +1211,18 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs
return IRQ_HANDLED;
}
-static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
+static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212)
{
+ int rc;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is starting... [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is starting... [%s]\n",
+ stateName[korg1212->cardState]);
// ---------------------------------------------------------------
// verify the state of the card before proceeding.
// ---------------------------------------------------------------
- if (korg1212->cardState >= K1212_STATE_DSP_IN_PROCESS) {
+ if (korg1212->cardState >= K1212_STATE_DSP_IN_PROCESS)
return 1;
- }
snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
@@ -1267,10 +1231,9 @@ static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
UpperWordSwap(korg1212->dma_dsp.addr),
0, 0, 0);
-
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n",
+ rc, stateName[korg1212->cardState]);
korg1212->dsp_is_loaded = 0;
wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT);
@@ -1282,7 +1245,7 @@ static int snd_korg1212_downloadDSPCode(korg1212_t *korg1212)
return 0;
}
-static snd_pcm_hardware_t snd_korg1212_playback_info =
+static struct snd_pcm_hardware snd_korg1212_playback_info =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1302,7 +1265,7 @@ static snd_pcm_hardware_t snd_korg1212_playback_info =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_korg1212_capture_info =
+static struct snd_pcm_hardware snd_korg1212_capture_info =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1322,21 +1285,21 @@ static snd_pcm_hardware_t snd_korg1212_capture_info =
.fifo_size = 0,
};
-static int snd_korg1212_silence(korg1212_t *korg1212, int pos, int count, int offset, int size)
+static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int count, int offset, int size)
{
- KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos;
+ struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos;
int i;
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", pos, offset, size, count);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n",
+ pos, offset, size, count);
snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL);
for (i=0; i < count; i++) {
#if K1212_DEBUG_LEVEL > 0
if ( (void *) dst < (void *) korg1212->playDataBufsPtr ||
(void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", dst, i);
+ printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n",
+ dst, i);
return -EFAULT;
}
#endif
@@ -1347,29 +1310,26 @@ static int snd_korg1212_silence(korg1212_t *korg1212, int pos, int count, int of
return 0;
}
-static int snd_korg1212_copy_to(korg1212_t *korg1212, void __user *dst, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size)
{
- KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos;
+ struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos;
int i, rc;
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", pos, offset, size);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n",
+ pos, offset, size);
snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL);
for (i=0; i < count; i++) {
#if K1212_DEBUG_LEVEL > 0
if ( (void *) src < (void *) korg1212->recordDataBufsPtr ||
(void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i);
+ printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i);
return -EFAULT;
}
#endif
rc = copy_to_user(dst + offset, src, size);
if (rc) {
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
-#endif
return -EFAULT;
}
src++;
@@ -1379,14 +1339,13 @@ static int snd_korg1212_copy_to(korg1212_t *korg1212, void __user *dst, int pos,
return 0;
}
-static int snd_korg1212_copy_from(korg1212_t *korg1212, void __user *src, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size)
{
- KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos;
+ struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos;
int i, rc;
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", pos, offset, size, count);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n",
+ pos, offset, size, count);
snd_assert(pos + count <= K1212_MAX_SAMPLES, return -EINVAL);
@@ -1394,15 +1353,13 @@ static int snd_korg1212_copy_from(korg1212_t *korg1212, void __user *src, int po
#if K1212_DEBUG_LEVEL > 0
if ( (void *) dst < (void *) korg1212->playDataBufsPtr ||
(void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i);
+ printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i);
return -EFAULT;
}
#endif
rc = copy_from_user((void*) dst + offset, src, size);
if (rc) {
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
-#endif
return -EFAULT;
}
dst++;
@@ -1412,26 +1369,24 @@ static int snd_korg1212_copy_from(korg1212_t *korg1212, void __user *src, int po
return 0;
}
-static void snd_korg1212_free_pcm(snd_pcm_t *pcm)
+static void snd_korg1212_free_pcm(struct snd_pcm *pcm)
{
- korg1212_t *korg1212 = (korg1212_t *) pcm->private_data;
+ struct snd_korg1212 *korg1212 = pcm->private_data;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_free_pcm [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_free_pcm [%s]\n",
+ stateName[korg1212->cardState]);
korg1212->pcm = NULL;
}
-static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
+static int snd_korg1212_playback_open(struct snd_pcm_substream *substream)
{
unsigned long flags;
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n",
+ stateName[korg1212->cardState]);
snd_pcm_set_sync(substream); // ???
@@ -1455,15 +1410,14 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
}
-static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
+static int snd_korg1212_capture_open(struct snd_pcm_substream *substream)
{
unsigned long flags;
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n",
+ stateName[korg1212->cardState]);
snd_pcm_set_sync(substream);
@@ -1481,18 +1435,18 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
spin_unlock_irqrestore(&korg1212->lock, flags);
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, kPlayBufferFrames, kPlayBufferFrames);
+ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ kPlayBufferFrames, kPlayBufferFrames);
return 0;
}
-static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
+static int snd_korg1212_playback_close(struct snd_pcm_substream *substream)
{
unsigned long flags;
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n",
+ stateName[korg1212->cardState]);
snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2);
@@ -1508,14 +1462,13 @@ static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_korg1212_capture_close(snd_pcm_substream_t *substream)
+static int snd_korg1212_capture_close(struct snd_pcm_substream *substream)
{
unsigned long flags;
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n",
+ stateName[korg1212->cardState]);
spin_lock_irqsave(&korg1212->lock, flags);
@@ -1529,39 +1482,34 @@ static int snd_korg1212_capture_close(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_korg1212_ioctl(snd_pcm_substream_t *substream,
+static int snd_korg1212_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_ioctl: cmd=%d\n", cmd);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_ioctl: cmd=%d\n", cmd);
if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) {
- snd_pcm_channel_info_t *info = arg;
+ struct snd_pcm_channel_info *info = arg;
info->offset = 0;
info->first = info->channel * 16;
info->step = 256;
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: channel_info %d:, offset=%ld, first=%d, step=%d\n", info->channel, info->offset, info->first, info->step);
-#endif
return 0;
}
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static int snd_korg1212_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int snd_korg1212_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
unsigned long flags;
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
int err;
pid_t this_pid;
pid_t other_pid;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n",
+ stateName[korg1212->cardState]);
spin_lock_irqsave(&korg1212->lock, flags);
@@ -1603,22 +1551,20 @@ static int snd_korg1212_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
+static int snd_korg1212_prepare(struct snd_pcm_substream *substream)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
int rc;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n",
+ stateName[korg1212->cardState]);
spin_lock_irq(&korg1212->lock);
/* FIXME: we should wait for ack! */
if (korg1212->stop_pending_cnt > 0) {
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n",
+ stateName[korg1212->cardState]);
spin_unlock_irq(&korg1212->lock);
return -EAGAIN;
/*
@@ -1637,24 +1583,21 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
return rc ? -EINVAL : 0;
}
-static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
+static int snd_korg1212_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
int rc;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n", stateName[korg1212->cardState], cmd);
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n",
+ stateName[korg1212->cardState], cmd);
spin_lock(&korg1212->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
/*
if (korg1212->running) {
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger: Already running?\n");
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already running?\n");
break;
}
*/
@@ -1665,9 +1608,7 @@ static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
case SNDRV_PCM_TRIGGER_STOP:
/*
if (!korg1212->running) {
-#if K1212_DEBUG_LEVEL > 1
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n");
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n");
break;
}
*/
@@ -1683,82 +1624,75 @@ static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
return rc ? -EINVAL : 0;
}
-static snd_pcm_uframes_t snd_korg1212_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_korg1212_playback_pointer(struct snd_pcm_substream *substream)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
snd_pcm_uframes_t pos;
pos = korg1212->currentBuffer * kPlayBufferFrames;
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld\n",
- stateName[korg1212->cardState], pos);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld\n",
+ stateName[korg1212->cardState], pos);
return pos;
}
-static snd_pcm_uframes_t snd_korg1212_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream *substream)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
snd_pcm_uframes_t pos;
pos = korg1212->currentBuffer * kPlayBufferFrames;
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld\n",
- stateName[korg1212->cardState], pos);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld\n",
+ stateName[korg1212->cardState], pos);
return pos;
}
-static int snd_korg1212_playback_copy(snd_pcm_substream_t *substream,
+static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src,
snd_pcm_uframes_t count)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n",
+ stateName[korg1212->cardState], pos, count);
return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2);
}
-static int snd_korg1212_playback_silence(snd_pcm_substream_t *substream,
+static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", stateName[korg1212->cardState]);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n",
+ stateName[korg1212->cardState]);
return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2);
}
-static int snd_korg1212_capture_copy(snd_pcm_substream_t *substream,
+static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *dst,
snd_pcm_uframes_t count)
{
- korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-#if K1212_DEBUG_LEVEL > 2
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
-#endif
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n",
+ stateName[korg1212->cardState], pos, count);
return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2);
}
-static snd_pcm_ops_t snd_korg1212_playback_ops = {
+static struct snd_pcm_ops snd_korg1212_playback_ops = {
.open = snd_korg1212_playback_open,
.close = snd_korg1212_playback_close,
.ioctl = snd_korg1212_ioctl,
@@ -1770,7 +1704,7 @@ static snd_pcm_ops_t snd_korg1212_playback_ops = {
.silence = snd_korg1212_playback_silence,
};
-static snd_pcm_ops_t snd_korg1212_capture_ops = {
+static struct snd_pcm_ops snd_korg1212_capture_ops = {
.open = snd_korg1212_capture_open,
.close = snd_korg1212_capture_close,
.ioctl = snd_korg1212_ioctl,
@@ -1785,16 +1719,18 @@ static snd_pcm_ops_t snd_korg1212_capture_ops = {
* Control Interface
*/
-static int snd_korg1212_control_phase_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_korg1212_control_phase_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1;
return 0;
}
-static int snd_korg1212_control_phase_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_phase_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int i = kcontrol->private_value;
spin_lock_irq(&korg1212->lock);
@@ -1809,9 +1745,10 @@ static int snd_korg1212_control_phase_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_korg1212_control_phase_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int change = 0;
int i, val;
@@ -1846,7 +1783,8 @@ static int snd_korg1212_control_phase_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
return change;
}
-static int snd_korg1212_control_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_korg1212_control_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1;
@@ -1855,9 +1793,10 @@ static int snd_korg1212_control_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_korg1212_control_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int i;
spin_lock_irq(&korg1212->lock);
@@ -1873,9 +1812,10 @@ static int snd_korg1212_control_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_korg1212_control_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int change = 0;
int i;
int val;
@@ -1905,7 +1845,8 @@ static int snd_korg1212_control_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_ele
return change;
}
-static int snd_korg1212_control_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_korg1212_control_route_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1;
@@ -1917,9 +1858,10 @@ static int snd_korg1212_control_route_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_korg1212_control_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int i;
spin_lock_irq(&korg1212->lock);
@@ -1935,9 +1877,10 @@ static int snd_korg1212_control_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int change = 0, i;
spin_lock_irq(&korg1212->lock);
@@ -1961,7 +1904,8 @@ static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
return change;
}
-static int snd_korg1212_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_korg1212_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1970,9 +1914,10 @@ static int snd_korg1212_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_korg1212_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&korg1212->lock);
@@ -1984,9 +1929,10 @@ static int snd_korg1212_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return 0;
}
-static int snd_korg1212_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+static int snd_korg1212_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *u)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
int change = 0;
spin_lock_irq(&korg1212->lock);
@@ -2008,7 +1954,8 @@ static int snd_korg1212_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
return change;
}
-static int snd_korg1212_control_sync_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_korg1212_control_sync_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2020,9 +1967,10 @@ static int snd_korg1212_control_sync_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_korg1212_control_sync_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_korg1212_control_sync_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&korg1212->lock);
@@ -2032,9 +1980,10 @@ static int snd_korg1212_control_sync_get(snd_kcontrol_t * kcontrol, snd_ctl_elem
return 0;
}
-static int snd_korg1212_control_sync_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
+ struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2075,7 +2024,7 @@ static int snd_korg1212_control_sync_put(snd_kcontrol_t * kcontrol, snd_ctl_elem
.private_value = ord, \
}
-static snd_kcontrol_new_t snd_korg1212_controls[] = {
+static struct snd_kcontrol_new snd_korg1212_controls[] = {
MON_MIXER(8, "Analog"),
MON_MIXER(10, "SPDIF"),
MON_MIXER(0, "ADAT-1"), MON_MIXER(1, "ADAT-2"), MON_MIXER(2, "ADAT-3"), MON_MIXER(3, "ADAT-4"),
@@ -2102,10 +2051,11 @@ static snd_kcontrol_new_t snd_korg1212_controls[] = {
* proc interface
*/
-static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_korg1212_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
int n;
- korg1212_t *korg1212 = (korg1212_t *)entry->private_data;
+ struct snd_korg1212 *korg1212 = entry->private_data;
snd_iprintf(buffer, korg1212->card->longname);
snd_iprintf(buffer, " (index #%d)\n", korg1212->card->number + 1);
@@ -2129,23 +2079,23 @@ static void snd_korg1212_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *b
snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt);
}
-static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212)
+static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(korg1212->card, "korg1212", &entry))
snd_info_set_text_ops(entry, korg1212, 1024, snd_korg1212_proc_read);
}
static int
-snd_korg1212_free(korg1212_t *korg1212)
+snd_korg1212_free(struct snd_korg1212 *korg1212)
{
snd_korg1212_TurnOffIdleMonitor(korg1212);
if (korg1212->irq >= 0) {
synchronize_irq(korg1212->irq);
snd_korg1212_DisableCardInterrupts(korg1212);
- free_irq(korg1212->irq, (void *)korg1212);
+ free_irq(korg1212->irq, korg1212);
korg1212->irq = -1;
}
@@ -2194,25 +2144,23 @@ snd_korg1212_free(korg1212_t *korg1212)
return 0;
}
-static int snd_korg1212_dev_free(snd_device_t *device)
+static int snd_korg1212_dev_free(struct snd_device *device)
{
- korg1212_t *korg1212 = device->device_data;
-#if K1212_DEBUG_LEVEL > 0
+ struct snd_korg1212 *korg1212 = device->device_data;
K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
-#endif
return snd_korg1212_free(korg1212);
}
-static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
- korg1212_t ** rchip)
+static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
+ struct snd_korg1212 ** rchip)
{
- int err;
+ int err, rc;
unsigned int i;
unsigned ioport_size, iomem_size, iomem2_size;
- korg1212_t * korg1212;
+ struct snd_korg1212 * korg1212;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_korg1212_dev_free,
};
@@ -2270,7 +2218,6 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
ioport_size = pci_resource_len(korg1212->pci, 1);
iomem2_size = pci_resource_len(korg1212->pci, 2);
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: resources:\n"
" iomem = 0x%lx (%d)\n"
" ioport = 0x%lx (%d)\n"
@@ -2280,7 +2227,6 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
korg1212->ioport, ioport_size,
korg1212->iomem2, iomem2_size,
stateName[korg1212->cardState]);
-#endif
if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) {
snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
@@ -2291,7 +2237,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
err = request_irq(pci->irq, snd_korg1212_interrupt,
SA_INTERRUPT|SA_SHIRQ,
- "korg1212", (void *) korg1212);
+ "korg1212", korg1212);
if (err) {
snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
@@ -2314,7 +2260,6 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
korg1212->sensRegPtr = (u16 __iomem *) (korg1212->iobase + SENS_CONTROL_OFFSET);
korg1212->idRegPtr = (u32 __iomem *) (korg1212->iobase + DEV_VEND_ID_OFFSET);
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: card registers:\n"
" Status register = 0x%p\n"
" OutDoorbell = 0x%p\n"
@@ -2338,24 +2283,21 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
korg1212->sensRegPtr,
korg1212->idRegPtr,
stateName[korg1212->cardState]);
-#endif
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
- snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
+ sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) {
+ snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(struct KorgSharedBuffer));
snd_korg1212_free(korg1212);
return -ENOMEM;
}
- korg1212->sharedBufferPtr = (KorgSharedBuffer *)korg1212->dma_shared.area;
+ korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area;
korg1212->sharedBufferPhy = korg1212->dma_shared.addr;
-#if K1212_DEBUG_LEVEL > 0
- K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(KorgSharedBuffer));
-#endif
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer));
#ifndef K1212_LARGEALLOC
- korg1212->DataBufsSize = sizeof(KorgAudioBuffer) * kNumBuffers;
+ korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers;
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
@@ -2363,13 +2305,11 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
snd_korg1212_free(korg1212);
return -ENOMEM;
}
- korg1212->playDataBufsPtr = (KorgAudioBuffer *)korg1212->dma_play.area;
+ korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area;
korg1212->PlayDataPhy = korg1212->dma_play.addr;
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n",
korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
-#endif
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
@@ -2377,31 +2317,29 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
snd_korg1212_free(korg1212);
return -ENOMEM;
}
- korg1212->recordDataBufsPtr = (KorgAudioBuffer *)korg1212->dma_rec.area;
+ korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area;
korg1212->RecDataPhy = korg1212->dma_rec.addr;
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n",
korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize);
-#endif
#else // K1212_LARGEALLOC
korg1212->recordDataBufsPtr = korg1212->sharedBufferPtr->recordDataBufs;
korg1212->playDataBufsPtr = korg1212->sharedBufferPtr->playDataBufs;
- korg1212->PlayDataPhy = (u32) &((KorgSharedBuffer *) korg1212->sharedBufferPhy)->playDataBufs;
- korg1212->RecDataPhy = (u32) &((KorgSharedBuffer *) korg1212->sharedBufferPhy)->recordDataBufs;
+ korg1212->PlayDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->playDataBufs;
+ korg1212->RecDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->recordDataBufs;
#endif // K1212_LARGEALLOC
korg1212->dspCodeSize = sizeof (dspCode);
korg1212->VolumeTablePhy = korg1212->sharedBufferPhy +
- offsetof(KorgSharedBuffer, volumeData);
+ offsetof(struct KorgSharedBuffer, volumeData);
korg1212->RoutingTablePhy = korg1212->sharedBufferPhy +
- offsetof(KorgSharedBuffer, routeData);
+ offsetof(struct KorgSharedBuffer, routeData);
korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
- offsetof(KorgSharedBuffer, AdatTimeCode);
+ offsetof(struct KorgSharedBuffer, AdatTimeCode);
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
@@ -2410,17 +2348,14 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
return -ENOMEM;
}
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
korg1212->dma_dsp.area, korg1212->dma_dsp.addr, korg1212->dspCodeSize,
stateName[korg1212->cardState]);
-#endif
rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0);
-#if K1212_DEBUG_LEVEL > 0
- if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
-#endif
+ if (rc)
+ K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops)) < 0) {
snd_korg1212_free(korg1212);
@@ -2434,8 +2369,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
if (snd_korg1212_downloadDSPCode(korg1212))
return -EBUSY;
- snd_printk(KERN_ERR
- "korg1212: dspMemPhy = %08x U[%08x], "
+ K1212_DEBUG_PRINTK("korg1212: dspMemPhy = %08x U[%08x], "
"PlayDataPhy = %08x L[%08x]\n"
"korg1212: RecDataPhy = %08x L[%08x], "
"VolumeTablePhy = %08x L[%08x]\n"
@@ -2461,9 +2395,6 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
korg1212->pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
- //snd_pcm_lib_preallocate_pages_for_all(korg1212->pcm,
- // K1212_MAX_BUF_SIZE, K1212_MAX_BUF_SIZE, GFP_KERNEL);
-
for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) {
err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212));
if (err < 0)
@@ -2488,8 +2419,8 @@ snd_korg1212_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- korg1212_t *korg1212;
- snd_card_t *card;
+ struct snd_korg1212 *korg1212;
+ struct snd_card *card;
int err;
if (dev >= SNDRV_CARDS) {
@@ -2513,9 +2444,7 @@ snd_korg1212_probe(struct pci_dev *pci,
sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname,
korg1212->iomem, korg1212->irq);
-#if K1212_DEBUG_LEVEL > 0
K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname);
-#endif
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index ede7a75bfe08..d3ef0cc6c4f9 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -767,9 +767,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)");
/*
*/
-typedef struct snd_m3_dma m3_dma_t;
-typedef struct snd_m3 m3_t;
-
/* quirk lists */
struct m3_quirk {
const char *name; /* device name */
@@ -791,11 +788,10 @@ struct m3_list {
int max;
};
-struct snd_m3_dma {
+struct m3_dma {
int number;
- m3_t *chip;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
struct assp_instance {
unsigned short code, data;
@@ -821,16 +817,16 @@ struct snd_m3_dma {
struct snd_m3 {
- snd_card_t *card;
+ struct snd_card *card;
unsigned long iobase;
int irq;
unsigned int allegro_flag : 1;
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
struct pci_dev *pci;
struct m3_quirk *quirk;
@@ -851,17 +847,17 @@ struct snd_m3 {
int amp_gpio;
/* midi */
- snd_rawmidi_t *rmidi;
+ struct snd_rawmidi *rmidi;
/* pcm streams */
int num_substreams;
- m3_dma_t *substreams;
+ struct m3_dma *substreams;
spinlock_t reg_lock;
spinlock_t ac97_lock;
- snd_kcontrol_t *master_switch;
- snd_kcontrol_t *master_volume;
+ struct snd_kcontrol *master_switch;
+ struct snd_kcontrol *master_volume;
struct tasklet_struct hwvol_tq;
#ifdef CONFIG_PM
@@ -1021,22 +1017,22 @@ static struct m3_hv_quirk m3_hv_quirk_list[] = {
* lowlevel functions
*/
-static inline void snd_m3_outw(m3_t *chip, u16 value, unsigned long reg)
+static inline void snd_m3_outw(struct snd_m3 *chip, u16 value, unsigned long reg)
{
outw(value, chip->iobase + reg);
}
-static inline u16 snd_m3_inw(m3_t *chip, unsigned long reg)
+static inline u16 snd_m3_inw(struct snd_m3 *chip, unsigned long reg)
{
return inw(chip->iobase + reg);
}
-static inline void snd_m3_outb(m3_t *chip, u8 value, unsigned long reg)
+static inline void snd_m3_outb(struct snd_m3 *chip, u8 value, unsigned long reg)
{
outb(value, chip->iobase + reg);
}
-static inline u8 snd_m3_inb(m3_t *chip, unsigned long reg)
+static inline u8 snd_m3_inb(struct snd_m3 *chip, unsigned long reg)
{
return inb(chip->iobase + reg);
}
@@ -1045,28 +1041,28 @@ static inline u8 snd_m3_inb(m3_t *chip, unsigned long reg)
* access 16bit words to the code or data regions of the dsp's memory.
* index addresses 16bit words.
*/
-static u16 snd_m3_assp_read(m3_t *chip, u16 region, u16 index)
+static u16 snd_m3_assp_read(struct snd_m3 *chip, u16 region, u16 index)
{
snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);
snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX);
return snd_m3_inw(chip, DSP_PORT_MEMORY_DATA);
}
-static void snd_m3_assp_write(m3_t *chip, u16 region, u16 index, u16 data)
+static void snd_m3_assp_write(struct snd_m3 *chip, u16 region, u16 index, u16 data)
{
snd_m3_outw(chip, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);
snd_m3_outw(chip, index, DSP_PORT_MEMORY_INDEX);
snd_m3_outw(chip, data, DSP_PORT_MEMORY_DATA);
}
-static void snd_m3_assp_halt(m3_t *chip)
+static void snd_m3_assp_halt(struct snd_m3 *chip)
{
chip->reset_state = snd_m3_inb(chip, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;
msleep(10);
snd_m3_outb(chip, chip->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
}
-static void snd_m3_assp_continue(m3_t *chip)
+static void snd_m3_assp_continue(struct snd_m3 *chip)
{
snd_m3_outb(chip, chip->reset_state | REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
}
@@ -1080,7 +1076,7 @@ static void snd_m3_assp_continue(m3_t *chip)
* by the binary code images.
*/
-static int snd_m3_add_list(m3_t *chip, struct m3_list *list, u16 val)
+static int snd_m3_add_list(struct snd_m3 *chip, struct m3_list *list, u16 val)
{
snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,
list->mem_addr + list->curlen,
@@ -1088,7 +1084,7 @@ static int snd_m3_add_list(m3_t *chip, struct m3_list *list, u16 val)
return list->curlen++;
}
-static void snd_m3_remove_list(m3_t *chip, struct m3_list *list, int index)
+static void snd_m3_remove_list(struct snd_m3 *chip, struct m3_list *list, int index)
{
u16 val;
int lastindex = list->curlen - 1;
@@ -1108,7 +1104,7 @@ static void snd_m3_remove_list(m3_t *chip, struct m3_list *list, int index)
list->curlen--;
}
-static void snd_m3_inc_timer_users(m3_t *chip)
+static void snd_m3_inc_timer_users(struct snd_m3 *chip)
{
chip->timer_users++;
if (chip->timer_users != 1)
@@ -1127,7 +1123,7 @@ static void snd_m3_inc_timer_users(m3_t *chip)
HOST_INT_CTRL);
}
-static void snd_m3_dec_timer_users(m3_t *chip)
+static void snd_m3_dec_timer_users(struct snd_m3 *chip)
{
chip->timer_users--;
if (chip->timer_users > 0)
@@ -1151,7 +1147,8 @@ static void snd_m3_dec_timer_users(m3_t *chip)
*/
/* spinlock held! */
-static int snd_m3_pcm_start(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+static int snd_m3_pcm_start(struct snd_m3 *chip, struct m3_dma *s,
+ struct snd_pcm_substream *subs)
{
if (! s || ! subs)
return -EINVAL;
@@ -1167,7 +1164,7 @@ static int snd_m3_pcm_start(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
chip->dacs_active);
break;
case SNDRV_PCM_STREAM_CAPTURE:
- snd_m3_assp_write(s->chip, MEMTYPE_INTERNAL_DATA,
+ snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,
KDATA_ADC1_REQUEST, 1);
snd_m3_assp_write(chip, MEMTYPE_INTERNAL_DATA,
s->inst.data + CDATA_INSTANCE_READY, 1);
@@ -1177,7 +1174,8 @@ static int snd_m3_pcm_start(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
}
/* spinlock held! */
-static int snd_m3_pcm_stop(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+static int snd_m3_pcm_stop(struct snd_m3 *chip, struct m3_dma *s,
+ struct snd_pcm_substream *subs)
{
if (! s || ! subs)
return -EINVAL;
@@ -1201,10 +1199,10 @@ static int snd_m3_pcm_stop(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
}
static int
-snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
+snd_m3_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
- m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
+ struct m3_dma *s = subs->runtime->private_data;
int err = -EINVAL;
snd_assert(s != NULL, return -ENXIO);
@@ -1238,10 +1236,10 @@ snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
* setup
*/
static void
-snd_m3_pcm_setup1(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+snd_m3_pcm_setup1(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs)
{
int dsp_in_size, dsp_out_size, dsp_in_buffer, dsp_out_buffer;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (subs->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
@@ -1323,7 +1321,8 @@ snd_m3_pcm_setup1(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
dsp_out_buffer);
}
-static void snd_m3_pcm_setup2(m3_t *chip, m3_dma_t *s, snd_pcm_runtime_t *runtime)
+static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,
+ struct snd_pcm_runtime *runtime)
{
u32 freq;
@@ -1389,7 +1388,8 @@ static struct play_vals {
/* the mode passed should be already shifted and masked */
static void
-snd_m3_playback_setup(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+snd_m3_playback_setup(struct snd_m3 *chip, struct m3_dma *s,
+ struct snd_pcm_substream *subs)
{
unsigned int i;
@@ -1455,7 +1455,7 @@ static struct rec_vals {
};
static void
-snd_m3_capture_setup(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+snd_m3_capture_setup(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs)
{
unsigned int i;
@@ -1481,10 +1481,10 @@ snd_m3_capture_setup(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
s->inst.data + rv[i].addr, rv[i].val);
}
-static int snd_m3_pcm_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- m3_dma_t *s = (m3_dma_t*) substream->runtime->private_data;
+ struct m3_dma *s = substream->runtime->private_data;
int err;
if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -1498,24 +1498,24 @@ static int snd_m3_pcm_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_m3_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_m3_pcm_hw_free(struct snd_pcm_substream *substream)
{
- m3_dma_t *s;
+ struct m3_dma *s;
if (substream->runtime->private_data == NULL)
return 0;
- s = (m3_dma_t*) substream->runtime->private_data;
+ s = substream->runtime->private_data;
snd_pcm_lib_free_pages(substream);
s->buffer_addr = 0;
return 0;
}
static int
-snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
+snd_m3_pcm_prepare(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
- m3_dma_t *s = (m3_dma_t*)runtime->private_data;
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct m3_dma *s = runtime->private_data;
snd_assert(s != NULL, return -ENXIO);
@@ -1546,7 +1546,7 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
* get current pointer
*/
static unsigned int
-snd_m3_get_pointer(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
+snd_m3_get_pointer(struct snd_m3 *chip, struct m3_dma *s, struct snd_pcm_substream *subs)
{
u16 hi = 0, lo = 0;
int retry = 10;
@@ -1571,11 +1571,11 @@ snd_m3_get_pointer(m3_t *chip, m3_dma_t *s, snd_pcm_substream_t *subs)
}
static snd_pcm_uframes_t
-snd_m3_pcm_pointer(snd_pcm_substream_t * subs)
+snd_m3_pcm_pointer(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
unsigned int ptr;
- m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
+ struct m3_dma *s = subs->runtime->private_data;
snd_assert(s != NULL, return 0);
spin_lock(&chip->reg_lock);
@@ -1587,9 +1587,9 @@ snd_m3_pcm_pointer(snd_pcm_substream_t * subs)
/* update pointer */
/* spinlock held! */
-static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
+static void snd_m3_update_ptr(struct snd_m3 *chip, struct m3_dma *s)
{
- snd_pcm_substream_t *subs = s->substream;
+ struct snd_pcm_substream *subs = s->substream;
unsigned int hwptr;
int diff;
@@ -1610,7 +1610,7 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
static void snd_m3_update_hw_volume(unsigned long private_data)
{
- m3_t *chip = (m3_t *) private_data;
+ struct snd_m3 *chip = (struct snd_m3 *) private_data;
int x, val;
unsigned long flags;
@@ -1673,7 +1673,7 @@ static void snd_m3_update_hw_volume(unsigned long private_data)
static irqreturn_t
snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- m3_t *chip = dev_id;
+ struct snd_m3 *chip = dev_id;
u8 status;
int i;
@@ -1698,7 +1698,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* update adc/dac info if it was a timer int */
spin_lock(&chip->reg_lock);
for (i = 0; i < chip->num_substreams; i++) {
- m3_dma_t *s = &chip->substreams[i];
+ struct m3_dma *s = &chip->substreams[i];
if (s->running)
snd_m3_update_ptr(chip, s);
}
@@ -1722,7 +1722,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/*
*/
-static snd_pcm_hardware_t snd_m3_playback =
+static struct snd_pcm_hardware snd_m3_playback =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1743,7 +1743,7 @@ static snd_pcm_hardware_t snd_m3_playback =
.periods_max = 1024,
};
-static snd_pcm_hardware_t snd_m3_capture =
+static struct snd_pcm_hardware snd_m3_capture =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -1769,10 +1769,10 @@ static snd_pcm_hardware_t snd_m3_capture =
*/
static int
-snd_m3_substream_open(m3_t *chip, snd_pcm_substream_t *subs)
+snd_m3_substream_open(struct snd_m3 *chip, struct snd_pcm_substream *subs)
{
int i;
- m3_dma_t *s;
+ struct m3_dma *s;
spin_lock_irq(&chip->reg_lock);
for (i = 0; i < chip->num_substreams; i++) {
@@ -1802,9 +1802,9 @@ __found:
}
static void
-snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
+snd_m3_substream_close(struct snd_m3 *chip, struct snd_pcm_substream *subs)
{
- m3_dma_t *s = (m3_dma_t*) subs->runtime->private_data;
+ struct m3_dma *s = subs->runtime->private_data;
if (s == NULL)
return; /* not opened properly */
@@ -1824,10 +1824,10 @@ snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
}
static int
-snd_m3_playback_open(snd_pcm_substream_t *subs)
+snd_m3_playback_open(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
int err;
if ((err = snd_m3_substream_open(chip, subs)) < 0)
@@ -1840,19 +1840,19 @@ snd_m3_playback_open(snd_pcm_substream_t *subs)
}
static int
-snd_m3_playback_close(snd_pcm_substream_t *subs)
+snd_m3_playback_close(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
snd_m3_substream_close(chip, subs);
return 0;
}
static int
-snd_m3_capture_open(snd_pcm_substream_t *subs)
+snd_m3_capture_open(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
int err;
if ((err = snd_m3_substream_open(chip, subs)) < 0)
@@ -1865,9 +1865,9 @@ snd_m3_capture_open(snd_pcm_substream_t *subs)
}
static int
-snd_m3_capture_close(snd_pcm_substream_t *subs)
+snd_m3_capture_close(struct snd_pcm_substream *subs)
{
- m3_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_m3 *chip = snd_pcm_substream_chip(subs);
snd_m3_substream_close(chip, subs);
return 0;
@@ -1877,7 +1877,7 @@ snd_m3_capture_close(snd_pcm_substream_t *subs)
* create pcm instance
*/
-static snd_pcm_ops_t snd_m3_playback_ops = {
+static struct snd_pcm_ops snd_m3_playback_ops = {
.open = snd_m3_playback_open,
.close = snd_m3_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1888,7 +1888,7 @@ static snd_pcm_ops_t snd_m3_playback_ops = {
.pointer = snd_m3_pcm_pointer,
};
-static snd_pcm_ops_t snd_m3_capture_ops = {
+static struct snd_pcm_ops snd_m3_capture_ops = {
.open = snd_m3_capture_open,
.close = snd_m3_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1900,9 +1900,9 @@ static snd_pcm_ops_t snd_m3_capture_ops = {
};
static int __devinit
-snd_m3_pcm(m3_t * chip, int device)
+snd_m3_pcm(struct snd_m3 * chip, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(chip->card, chip->card->driver, device,
@@ -1933,7 +1933,7 @@ snd_m3_pcm(m3_t * chip, int device)
* Wait for the ac97 serial bus to be free.
* return nonzero if the bus is still busy.
*/
-static int snd_m3_ac97_wait(m3_t *chip)
+static int snd_m3_ac97_wait(struct snd_m3 *chip)
{
int i = 10000;
@@ -1947,9 +1947,9 @@ static int snd_m3_ac97_wait(m3_t *chip)
}
static unsigned short
-snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
+snd_m3_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
- m3_t *chip = ac97->private_data;
+ struct snd_m3 *chip = ac97->private_data;
unsigned long flags;
unsigned short data;
@@ -1965,9 +1965,9 @@ snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
}
static void
-snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+snd_m3_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val)
{
- m3_t *chip = ac97->private_data;
+ struct snd_m3 *chip = ac97->private_data;
unsigned long flags;
if (snd_m3_ac97_wait(chip))
@@ -1994,7 +1994,7 @@ static void snd_m3_remote_codec_config(int io, int isremote)
/*
* hack, returns non zero on err
*/
-static int snd_m3_try_read_vendor(m3_t *chip)
+static int snd_m3_try_read_vendor(struct snd_m3 *chip)
{
u16 ret;
@@ -2011,7 +2011,7 @@ static int snd_m3_try_read_vendor(m3_t *chip)
return (ret == 0) || (ret == 0xffff);
}
-static void snd_m3_ac97_reset(m3_t *chip)
+static void snd_m3_ac97_reset(struct snd_m3 *chip)
{
u16 dir;
int delay1 = 0, delay2 = 0, i;
@@ -2078,13 +2078,13 @@ static void snd_m3_ac97_reset(m3_t *chip)
#endif
}
-static int __devinit snd_m3_mixer(m3_t *chip)
+static int __devinit snd_m3_mixer(struct snd_m3 *chip)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
- snd_ctl_elem_id_t id;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
+ struct snd_ctl_elem_id id;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_m3_ac97_write,
.read = snd_m3_ac97_read,
};
@@ -2254,7 +2254,7 @@ static u16 minisrc_lpf[MINISRC_LPF_LEN] __devinitdata = {
0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
};
-static void __devinit snd_m3_assp_init(m3_t *chip)
+static void __devinit snd_m3_assp_init(struct snd_m3 *chip)
{
unsigned int i;
@@ -2343,7 +2343,7 @@ static void __devinit snd_m3_assp_init(m3_t *chip)
}
-static int __devinit snd_m3_assp_client_init(m3_t *chip, m3_dma_t *s, int index)
+static int __devinit snd_m3_assp_client_init(struct snd_m3 *chip, struct m3_dma *s, int index)
{
int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 +
MINISRC_IN_BUFFER_SIZE / 2 +
@@ -2389,7 +2389,7 @@ static int __devinit snd_m3_assp_client_init(m3_t *chip, m3_dma_t *s, int index)
* this needs more magic for 4 speaker, but..
*/
static void
-snd_m3_amp_enable(m3_t *chip, int enable)
+snd_m3_amp_enable(struct snd_m3 *chip, int enable)
{
int io = chip->iobase;
u16 gpo, polarity;
@@ -2413,7 +2413,7 @@ snd_m3_amp_enable(m3_t *chip, int enable)
}
static int
-snd_m3_chip_init(m3_t *chip)
+snd_m3_chip_init(struct snd_m3 *chip)
{
struct pci_dev *pcidev = chip->pci;
unsigned long io = chip->iobase;
@@ -2486,7 +2486,7 @@ snd_m3_chip_init(m3_t *chip)
}
static void
-snd_m3_enable_ints(m3_t *chip)
+snd_m3_enable_ints(struct snd_m3 *chip)
{
unsigned long io = chip->iobase;
unsigned short val;
@@ -2504,9 +2504,9 @@ snd_m3_enable_ints(m3_t *chip)
/*
*/
-static int snd_m3_free(m3_t *chip)
+static int snd_m3_free(struct snd_m3 *chip)
{
- m3_dma_t *s;
+ struct m3_dma *s;
int i;
if (chip->substreams) {
@@ -2530,7 +2530,7 @@ static int snd_m3_free(m3_t *chip)
if (chip->irq >= 0) {
synchronize_irq(chip->irq);
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
}
if (chip->iobase)
@@ -2546,14 +2546,16 @@ static int snd_m3_free(m3_t *chip)
* APM support
*/
#ifdef CONFIG_PM
-static int m3_suspend(snd_card_t *card, pm_message_t state)
+static int m3_suspend(struct pci_dev *pci, pm_message_t state)
{
- m3_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_m3 *chip = card->private_data;
int i, index;
if (chip->suspend_mem == NULL)
return 0;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
@@ -2574,20 +2576,23 @@ static int m3_suspend(snd_card_t *card, pm_message_t state)
snd_m3_outw(chip, 0xffff, 0x54);
snd_m3_outw(chip, 0xffff, 0x56);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int m3_resume(snd_card_t *card)
+static int m3_resume(struct pci_dev *pci)
{
- m3_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_m3 *chip = card->private_data;
int i, index;
if (chip->suspend_mem == NULL)
return 0;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
/* first lets just bring everything back. .*/
snd_m3_outw(chip, 0, 0x54);
@@ -2617,6 +2622,7 @@ static int m3_resume(snd_card_t *card)
snd_m3_enable_ints(chip);
snd_m3_amp_enable(chip, 1);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
@@ -2625,23 +2631,23 @@ static int m3_resume(snd_card_t *card)
/*
*/
-static int snd_m3_dev_free(snd_device_t *device)
+static int snd_m3_dev_free(struct snd_device *device)
{
- m3_t *chip = device->device_data;
+ struct snd_m3 *chip = device->device_data;
return snd_m3_free(chip);
}
static int __devinit
-snd_m3_create(snd_card_t *card, struct pci_dev *pci,
+snd_m3_create(struct snd_card *card, struct pci_dev *pci,
int enable_amp,
int amp_gpio,
- m3_t **chip_ret)
+ struct snd_m3 **chip_ret)
{
- m3_t *chip;
+ struct snd_m3 *chip;
int i, err;
struct m3_quirk *quirk;
struct m3_hv_quirk *hv_quirk;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_m3_dev_free,
};
@@ -2710,13 +2716,13 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
chip->amp_gpio = GPO_EXT_AMP_M3;
chip->num_substreams = NR_DSPS;
- chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
+ chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
+ GFP_KERNEL);
if (chip->substreams == NULL) {
kfree(chip);
pci_disable_device(pci);
return -ENOMEM;
}
- memset(chip->substreams, 0, sizeof(m3_dma_t) * chip->num_substreams);
if ((err = pci_request_regions(pci, card->driver)) < 0) {
snd_m3_free(chip);
@@ -2737,7 +2743,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ,
- card->driver, (void *)chip)) {
+ card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_m3_free(chip);
return -ENOMEM;
@@ -2748,8 +2754,6 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH));
if (chip->suspend_mem == NULL)
snd_printk(KERN_WARNING "can't allocate apm buffer\n");
- else
- snd_card_set_pm_callback(card, m3_suspend, m3_resume, chip);
#endif
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
@@ -2761,8 +2765,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return err;
for (i = 0; i < chip->num_substreams; i++) {
- m3_dma_t *s = &chip->substreams[i];
- s->chip = chip;
+ struct m3_dma *s = &chip->substreams[i];
if ((err = snd_m3_assp_client_init(chip, s, i)) < 0)
return err;
}
@@ -2786,8 +2789,8 @@ static int __devinit
snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- m3_t *chip;
+ struct snd_card *card;
+ struct snd_m3 *chip;
int err;
/* don't pick up modems */
@@ -2826,6 +2829,7 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_card_free(card);
return err;
}
+ card->private_data = chip;
sprintf(card->shortname, "ESS %s PCI", card->driver);
sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2861,7 +2865,10 @@ static struct pci_driver driver = {
.id_table = snd_m3_ids,
.probe = snd_m3_probe,
.remove = __devexit_p(snd_m3_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = m3_suspend,
+ .resume = m3_resume,
+#endif
};
static int __init alsa_card_m3_init(void)
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index b3090a13edab..b218e1d20c78 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -66,11 +66,12 @@ static struct pci_device_id snd_mixart_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
-static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int start)
+static int mixart_set_pipe_state(struct mixart_mgr *mgr,
+ struct mixart_pipe *pipe, int start)
{
- mixart_group_state_req_t group_state;
- mixart_group_state_resp_t group_state_resp;
- mixart_msg_t request;
+ struct mixart_group_state_req group_state;
+ struct mixart_group_state_resp group_state_resp;
+ struct mixart_msg request;
int err;
u32 system_msg_uid;
@@ -92,7 +93,7 @@ static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int sta
/* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &system_msg_uid;
request.size = sizeof(system_msg_uid);
@@ -113,7 +114,7 @@ static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int sta
else
request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
- request.uid = pipe->group_uid; /*(mixart_uid_t){0,0};*/
+ request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/
request.data = &group_state;
request.size = sizeof(group_state);
@@ -137,7 +138,7 @@ static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int sta
/* in case of start send a synchro top */
request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = NULL;
request.size = 0;
@@ -156,11 +157,12 @@ static int mixart_set_pipe_state(mixart_mgr_t *mgr, mixart_pipe_t* pipe, int sta
}
-static int mixart_set_clock(mixart_mgr_t *mgr, mixart_pipe_t *pipe, unsigned int rate)
+static int mixart_set_clock(struct mixart_mgr *mgr,
+ struct mixart_pipe *pipe, unsigned int rate)
{
- mixart_msg_t request;
- mixart_clock_properties_t clock_properties;
- mixart_clock_properties_resp_t clock_prop_resp;
+ struct mixart_msg request;
+ struct mixart_clock_properties clock_properties;
+ struct mixart_clock_properties_resp clock_prop_resp;
int err;
switch(pipe->status) {
@@ -208,11 +210,13 @@ static int mixart_set_clock(mixart_mgr_t *mgr, mixart_pipe_t *pipe, unsigned int
/*
* Allocate or reference output pipe for analog IOs (pcmp0/1)
*/
-mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capture, int monitoring)
+struct mixart_pipe *
+snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture,
+ int monitoring)
{
int stream_count;
- mixart_pipe_t *pipe;
- mixart_msg_t request;
+ struct mixart_pipe *pipe;
+ struct mixart_msg request;
if(capture) {
if (pcm_number == MIXART_PCM_ANALOG) {
@@ -241,8 +245,8 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
if( pipe->status == PIPE_UNDEFINED ) {
int err, i;
struct {
- mixart_streaming_group_req_t sgroup_req;
- mixart_streaming_group_t sgroup_resp;
+ struct mixart_streaming_group_req sgroup_req;
+ struct mixart_streaming_group sgroup_resp;
} *buf;
snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
@@ -251,7 +255,7 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
if (!buf)
return NULL;
- request.uid = (mixart_uid_t){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */
+ request.uid = (struct mixart_uid){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */
request.data = &buf->sgroup_req;
request.size = sizeof(buf->sgroup_req);
@@ -279,7 +283,7 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
buf->sgroup_req.flow_entry[i] = j;
flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
- flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(mixart_bufferinfo_t));
+ flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo));
flowinfo[j].bufferinfo_count = 1; /* 1 will set the miXart to ring-buffer mode ! */
bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
@@ -315,7 +319,8 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
}
-int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monitoring)
+int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr,
+ struct mixart_pipe *pipe, int monitoring)
{
int err = 0;
@@ -329,8 +334,8 @@ int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monito
if((pipe->references <= 0) && (pipe->monitoring == 0)) {
- mixart_msg_t request;
- mixart_delete_group_resp_t delete_resp;
+ struct mixart_msg request;
+ struct mixart_delete_group_resp delete_resp;
/* release the clock */
err = mixart_set_clock( mgr, pipe, 0);
@@ -345,7 +350,7 @@ int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monito
}
request.message_id = MSG_STREAM_DELETE_GROUP;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &pipe->group_uid; /* the streaming group ! */
request.size = sizeof(pipe->group_uid);
@@ -355,7 +360,7 @@ int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monito
snd_printk(KERN_ERR "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n", err, delete_resp.status);
}
- pipe->group_uid = (mixart_uid_t){0,0};
+ pipe->group_uid = (struct mixart_uid){0,0};
pipe->stream_count = 0;
pipe->status = PIPE_UNDEFINED;
}
@@ -363,11 +368,11 @@ int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monito
return err;
}
-static int mixart_set_stream_state(mixart_stream_t *stream, int start)
+static int mixart_set_stream_state(struct mixart_stream *stream, int start)
{
- mixart_t *chip;
- mixart_stream_state_req_t stream_state_req;
- mixart_msg_t request;
+ struct snd_mixart *chip;
+ struct mixart_stream_state_req stream_state_req;
+ struct mixart_msg request;
if(!stream->substream)
return -EINVAL;
@@ -382,7 +387,7 @@ static int mixart_set_stream_state(mixart_stream_t *stream, int start)
else
request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &stream_state_req;
request.size = sizeof(stream_state_req);
@@ -399,9 +404,9 @@ static int mixart_set_stream_state(mixart_stream_t *stream, int start)
* Trigger callback
*/
-static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd)
+static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd)
{
- mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+ struct mixart_stream *stream = subs->runtime->private_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -443,7 +448,7 @@ static int snd_mixart_trigger(snd_pcm_substream_t *subs, int cmd)
return 0;
}
-static int mixart_sync_nonblock_events(mixart_mgr_t *mgr)
+static int mixart_sync_nonblock_events(struct mixart_mgr *mgr)
{
unsigned long timeout = jiffies + HZ;
while (atomic_read(&mgr->msg_processed) > 0) {
@@ -459,10 +464,10 @@ static int mixart_sync_nonblock_events(mixart_mgr_t *mgr)
/*
* prepare callback for all pcms
*/
-static int snd_mixart_prepare(snd_pcm_substream_t *subs)
+static int snd_mixart_prepare(struct snd_pcm_substream *subs)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
- mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
+ struct mixart_stream *stream = subs->runtime->private_data;
/* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
@@ -485,13 +490,13 @@ static int snd_mixart_prepare(snd_pcm_substream_t *subs)
}
-static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format)
+static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format)
{
int err;
- mixart_t *chip;
- mixart_msg_t request;
- mixart_stream_param_desc_t stream_param;
- mixart_return_uid_t resp;
+ struct snd_mixart *chip;
+ struct mixart_msg request;
+ struct mixart_stream_param_desc stream_param;
+ struct mixart_return_uid resp;
chip = snd_pcm_substream_chip(stream->substream);
@@ -552,7 +557,7 @@ static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format)
stream_param.stream_desc[0].stream_idx = stream->substream->number;
request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &stream_param;
request.size = sizeof(stream_param);
@@ -568,12 +573,12 @@ static int mixart_set_format(mixart_stream_t *stream, snd_pcm_format_t format)
/*
* HW_PARAMS callback for all pcms
*/
-static int snd_mixart_hw_params(snd_pcm_substream_t *subs,
- snd_pcm_hw_params_t *hw)
+static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
- mixart_mgr_t *mgr = chip->mgr;
- mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
+ struct mixart_mgr *mgr = chip->mgr;
+ struct mixart_stream *stream = subs->runtime->private_data;
snd_pcm_format_t format;
int err;
int channels;
@@ -628,9 +633,9 @@ static int snd_mixart_hw_params(snd_pcm_substream_t *subs,
return err;
}
-static int snd_mixart_hw_free(snd_pcm_substream_t *subs)
+static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
snd_pcm_lib_free_pages(subs);
mixart_sync_nonblock_events(chip->mgr);
return 0;
@@ -641,7 +646,7 @@ static int snd_mixart_hw_free(snd_pcm_substream_t *subs)
/*
* TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
*/
-static snd_pcm_hardware_t snd_mixart_analog_caps =
+static struct snd_pcm_hardware snd_mixart_analog_caps =
{
.info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
@@ -662,7 +667,7 @@ static snd_pcm_hardware_t snd_mixart_analog_caps =
.periods_max = (32*1024/256),
};
-static snd_pcm_hardware_t snd_mixart_digital_caps =
+static struct snd_pcm_hardware snd_mixart_digital_caps =
{
.info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
@@ -684,14 +689,14 @@ static snd_pcm_hardware_t snd_mixart_digital_caps =
};
-static int snd_mixart_playback_open(snd_pcm_substream_t *subs)
+static int snd_mixart_playback_open(struct snd_pcm_substream *subs)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
- mixart_mgr_t *mgr = chip->mgr;
- snd_pcm_runtime_t *runtime = subs->runtime;
- snd_pcm_t *pcm = subs->pcm;
- mixart_stream_t *stream;
- mixart_pipe_t *pipe;
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
+ struct mixart_mgr *mgr = chip->mgr;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct snd_pcm *pcm = subs->pcm;
+ struct mixart_stream *stream;
+ struct mixart_pipe *pipe;
int err = 0;
int pcm_number;
@@ -759,14 +764,14 @@ static int snd_mixart_playback_open(snd_pcm_substream_t *subs)
}
-static int snd_mixart_capture_open(snd_pcm_substream_t *subs)
+static int snd_mixart_capture_open(struct snd_pcm_substream *subs)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
- mixart_mgr_t *mgr = chip->mgr;
- snd_pcm_runtime_t *runtime = subs->runtime;
- snd_pcm_t *pcm = subs->pcm;
- mixart_stream_t *stream;
- mixart_pipe_t *pipe;
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
+ struct mixart_mgr *mgr = chip->mgr;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct snd_pcm *pcm = subs->pcm;
+ struct mixart_stream *stream;
+ struct mixart_pipe *pipe;
int err = 0;
int pcm_number;
@@ -838,11 +843,11 @@ static int snd_mixart_capture_open(snd_pcm_substream_t *subs)
-static int snd_mixart_close(snd_pcm_substream_t *subs)
+static int snd_mixart_close(struct snd_pcm_substream *subs)
{
- mixart_t *chip = snd_pcm_substream_chip(subs);
- mixart_mgr_t *mgr = chip->mgr;
- mixart_stream_t *stream = (mixart_stream_t*)subs->runtime->private_data;
+ struct snd_mixart *chip = snd_pcm_substream_chip(subs);
+ struct mixart_mgr *mgr = chip->mgr;
+ struct mixart_stream *stream = subs->runtime->private_data;
down(&mgr->setup_mutex);
@@ -868,17 +873,17 @@ static int snd_mixart_close(snd_pcm_substream_t *subs)
}
-static snd_pcm_uframes_t snd_mixart_stream_pointer(snd_pcm_substream_t * subs)
+static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- mixart_stream_t *stream = (mixart_stream_t*)runtime->private_data;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct mixart_stream *stream = runtime->private_data;
return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
}
-static snd_pcm_ops_t snd_mixart_playback_ops = {
+static struct snd_pcm_ops snd_mixart_playback_ops = {
.open = snd_mixart_playback_open,
.close = snd_mixart_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -889,7 +894,7 @@ static snd_pcm_ops_t snd_mixart_playback_ops = {
.pointer = snd_mixart_stream_pointer,
};
-static snd_pcm_ops_t snd_mixart_capture_ops = {
+static struct snd_pcm_ops snd_mixart_capture_ops = {
.open = snd_mixart_capture_open,
.close = snd_mixart_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -900,10 +905,10 @@ static snd_pcm_ops_t snd_mixart_capture_ops = {
.pointer = snd_mixart_stream_pointer,
};
-static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
+static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
{
#if 0
- snd_pcm_substream_t *subs;
+ struct snd_pcm_substream *subs;
int stream;
for (stream = 0; stream < 2; stream++) {
@@ -921,10 +926,10 @@ static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
/*
*/
-static int snd_mixart_pcm_analog(mixart_t *chip)
+static int snd_mixart_pcm_analog(struct snd_mixart *chip)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
char name[32];
sprintf(name, "miXart analog %d", chip->chip_idx);
@@ -952,10 +957,10 @@ static int snd_mixart_pcm_analog(mixart_t *chip)
/*
*/
-static int snd_mixart_pcm_digital(mixart_t *chip)
+static int snd_mixart_pcm_digital(struct snd_mixart *chip)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
char name[32];
sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
@@ -980,26 +985,26 @@ static int snd_mixart_pcm_digital(mixart_t *chip)
return 0;
}
-static int snd_mixart_chip_free(mixart_t *chip)
+static int snd_mixart_chip_free(struct snd_mixart *chip)
{
kfree(chip);
return 0;
}
-static int snd_mixart_chip_dev_free(snd_device_t *device)
+static int snd_mixart_chip_dev_free(struct snd_device *device)
{
- mixart_t *chip = device->device_data;
+ struct snd_mixart *chip = device->device_data;
return snd_mixart_chip_free(chip);
}
/*
*/
-static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int idx)
+static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
{
int err;
- mixart_t *chip;
- static snd_device_ops_t ops = {
+ struct snd_mixart *chip;
+ static struct snd_device_ops ops = {
.dev_free = snd_mixart_chip_dev_free,
};
@@ -1023,7 +1028,7 @@ static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int
return 0;
}
-int snd_mixart_create_pcm(mixart_t* chip)
+int snd_mixart_create_pcm(struct snd_mixart* chip)
{
int err;
@@ -1044,7 +1049,7 @@ int snd_mixart_create_pcm(mixart_t* chip)
/*
* release all the cards assigned to a manager instance
*/
-static int snd_mixart_free(mixart_mgr_t *mgr)
+static int snd_mixart_free(struct mixart_mgr *mgr)
{
unsigned int i;
@@ -1092,7 +1097,7 @@ static int snd_mixart_free(mixart_mgr_t *mgr)
/*
* proc interface
*/
-static long long snd_mixart_BA0_llseek(snd_info_entry_t *entry,
+static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry,
void *private_file_data,
struct file *file,
long long offset,
@@ -1118,7 +1123,7 @@ static long long snd_mixart_BA0_llseek(snd_info_entry_t *entry,
return file->f_pos;
}
-static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry,
+static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry,
void *private_file_data,
struct file *file,
long long offset,
@@ -1147,11 +1152,11 @@ static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry,
/*
mixart_BA0 proc interface for BAR 0 - read callback
*/
-static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
- mixart_mgr_t *mgr = entry->private_data;
+ struct mixart_mgr *mgr = entry->private_data;
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
if(count <= 0)
@@ -1166,11 +1171,11 @@ static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data
/*
mixart_BA1 proc interface for BAR 1 - read callback
*/
-static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data,
+static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private_data,
struct file *file, char __user *buf,
unsigned long count, unsigned long pos)
{
- mixart_mgr_t *mgr = entry->private_data;
+ struct mixart_mgr *mgr = entry->private_data;
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
if(count <= 0)
@@ -1193,10 +1198,10 @@ static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
};
-static void snd_mixart_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_mixart_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- mixart_t *chip = entry->private_data;
+ struct snd_mixart *chip = entry->private_data;
u32 ref;
snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
@@ -1229,9 +1234,9 @@ static void snd_mixart_proc_read(snd_info_entry_t *entry,
} /* endif elf loaded */
}
-static void __devinit snd_mixart_proc_init(mixart_t *chip)
+static void __devinit snd_mixart_proc_init(struct snd_mixart *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
/* text interface to read perf and temp meters */
if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
@@ -1263,7 +1268,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- mixart_mgr_t *mgr;
+ struct mixart_mgr *mgr;
unsigned int i;
int err;
size_t size;
@@ -1338,12 +1343,12 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
init_MUTEX(&mgr->setup_mutex);
/* init message taslket */
- tasklet_init( &mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
+ tasklet_init(&mgr->msg_taskq, snd_mixart_msg_tasklet, (unsigned long) mgr);
/* card assignment */
mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */
for (i = 0; i < mgr->num_cards; i++) {
- snd_card_t *card;
+ struct snd_card *card;
char tmpid[16];
int idx;
@@ -1384,7 +1389,8 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
/* create array of streaminfo */
- size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_flowinfo_t)) );
+ size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
+ sizeof(struct mixart_flowinfo)) );
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &mgr->flowinfo) < 0) {
snd_mixart_free(mgr);
@@ -1394,7 +1400,8 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
memset(mgr->flowinfo.area, 0, size);
/* create array of bufferinfo */
- size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_bufferinfo_t)) );
+ size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
+ sizeof(struct mixart_bufferinfo)) );
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
size, &mgr->bufferinfo) < 0) {
snd_mixart_free(mgr);
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index f87152f94c0e..3e84863ca02c 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -32,21 +32,7 @@
/*
*/
-#define mixart_t_magic 0xa17a3e01
-#define mixart_mgr_t_magic 0xa17a3e02
-
-typedef struct snd_mixart mixart_t;
-typedef struct snd_mixart_mgr mixart_mgr_t;
-
-typedef struct snd_mixart_stream mixart_stream_t;
-typedef struct snd_mixart_pipe mixart_pipe_t;
-
-typedef struct mixart_bufferinfo mixart_bufferinfo_t;
-typedef struct mixart_flowinfo mixart_flowinfo_t;
-typedef struct mixart_uid mixart_uid_t;
-
-struct mixart_uid
-{
+struct mixart_uid {
u32 object_id;
u32 desc;
};
@@ -58,7 +44,6 @@ struct mem_area {
};
-typedef struct mixart_route mixart_route_t;
struct mixart_route {
unsigned char connected;
unsigned char phase_inv;
@@ -77,9 +62,9 @@ struct mixart_route {
#define MIXART_MAX_PHYS_CONNECTORS (MIXART_MAX_CARDS * 2 * 2) /* 4 * stereo * (analog+digital) */
-struct snd_mixart_mgr {
+struct mixart_mgr {
unsigned int num_cards;
- mixart_t *chip[MIXART_MAX_CARDS];
+ struct snd_mixart *chip[MIXART_MAX_CARDS];
struct pci_dev *pci;
@@ -118,7 +103,7 @@ struct snd_mixart_mgr {
struct snd_dma_buffer flowinfo;
struct snd_dma_buffer bufferinfo;
- mixart_uid_t uid_console_manager;
+ struct mixart_uid uid_console_manager;
int sample_rate;
int ref_count_rate;
@@ -151,9 +136,9 @@ struct snd_mixart_mgr {
#define MIXART_NOTIFY_SUBS_MASK 0x007F
-struct snd_mixart_stream {
- snd_pcm_substream_t *substream;
- mixart_pipe_t *pipe;
+struct mixart_stream {
+ struct snd_pcm_substream *substream;
+ struct mixart_pipe *pipe;
int pcm_number;
int status; /* nothing, running, draining */
@@ -173,11 +158,11 @@ enum mixart_pipe_status {
PIPE_CLOCK_SET
};
-struct snd_mixart_pipe {
- mixart_uid_t group_uid; /* id of the pipe, as returned by embedded */
+struct mixart_pipe {
+ struct mixart_uid group_uid; /* id of the pipe, as returned by embedded */
int stream_count;
- mixart_uid_t uid_left_connector; /* UID's for the audio connectors */
- mixart_uid_t uid_right_connector;
+ struct mixart_uid uid_left_connector; /* UID's for the audio connectors */
+ struct mixart_uid uid_right_connector;
enum mixart_pipe_status status;
int references; /* number of subs openned */
int monitoring; /* pipe used for monitoring issue */
@@ -185,28 +170,28 @@ struct snd_mixart_pipe {
struct snd_mixart {
- snd_card_t *card;
- mixart_mgr_t *mgr;
+ struct snd_card *card;
+ struct mixart_mgr *mgr;
int chip_idx; /* zero based */
- snd_hwdep_t *hwdep; /* DSP loader, only for the first card */
+ struct snd_hwdep *hwdep; /* DSP loader, only for the first card */
- snd_pcm_t *pcm; /* PCM analog i/o */
- snd_pcm_t *pcm_dig; /* PCM digital i/o */
+ struct snd_pcm *pcm; /* PCM analog i/o */
+ struct snd_pcm *pcm_dig; /* PCM digital i/o */
/* allocate stereo pipe for instance */
- mixart_pipe_t pipe_in_ana;
- mixart_pipe_t pipe_out_ana;
+ struct mixart_pipe pipe_in_ana;
+ struct mixart_pipe pipe_out_ana;
/* if AES/EBU daughter board is available, additional pipes possible on pcm_dig */
- mixart_pipe_t pipe_in_dig;
- mixart_pipe_t pipe_out_dig;
+ struct mixart_pipe pipe_in_dig;
+ struct mixart_pipe pipe_out_dig;
- mixart_stream_t playback_stream[MIXART_PCM_TOTAL][MIXART_PLAYBACK_STREAMS]; /* 0 = pcm, 1 = pcm_dig */
- mixart_stream_t capture_stream[MIXART_PCM_TOTAL]; /* 0 = pcm, 1 = pcm_dig */
+ struct mixart_stream playback_stream[MIXART_PCM_TOTAL][MIXART_PLAYBACK_STREAMS]; /* 0 = pcm, 1 = pcm_dig */
+ struct mixart_stream capture_stream[MIXART_PCM_TOTAL]; /* 0 = pcm, 1 = pcm_dig */
/* UID's for the physical io's */
- mixart_uid_t uid_out_analog_physio;
- mixart_uid_t uid_in_analog_physio;
+ struct mixart_uid uid_out_analog_physio;
+ struct mixart_uid uid_in_analog_physio;
int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */
int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
@@ -235,8 +220,8 @@ struct mixart_flowinfo
};
/* exported */
-int snd_mixart_create_pcm(mixart_t* chip);
-mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capture, int monitoring);
-int snd_mixart_kill_ref_pipe( mixart_mgr_t *mgr, mixart_pipe_t *pipe, int monitoring);
+int snd_mixart_create_pcm(struct snd_mixart * chip);
+struct mixart_pipe *snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture, int monitoring);
+int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr, struct mixart_pipe *pipe, int monitoring);
#endif /* __SOUND_MIXART_H */
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index ba0027f50944..07c707d7ebbf 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -44,7 +44,7 @@
#define MSG_CANCEL_NOTIFY_MASK 0x80000000 /* this bit is set for a notification that has been canceled */
-static int retrieve_msg_frame(mixart_mgr_t *mgr, u32 *msg_frame)
+static int retrieve_msg_frame(struct mixart_mgr *mgr, u32 *msg_frame)
{
/* read the message frame fifo */
u32 headptr, tailptr;
@@ -69,7 +69,8 @@ static int retrieve_msg_frame(mixart_mgr_t *mgr, u32 *msg_frame)
return 1;
}
-static int get_msg(mixart_mgr_t *mgr, mixart_msg_t *resp, u32 msg_frame_address )
+static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp,
+ u32 msg_frame_address )
{
unsigned long flags;
u32 headptr;
@@ -137,8 +138,8 @@ static int get_msg(mixart_mgr_t *mgr, mixart_msg_t *resp, u32 msg_frame_address
* send a message to miXart. return: the msg_frame used for this message
*/
/* call with mgr->msg_lock held! */
-static int send_msg( mixart_mgr_t *mgr,
- mixart_msg_t *msg,
+static int send_msg( struct mixart_mgr *mgr,
+ struct mixart_msg *msg,
int max_answersize,
int mark_pending,
u32 *msg_event)
@@ -230,9 +231,9 @@ static int send_msg( mixart_mgr_t *mgr,
}
-int snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_size, void *resp_data)
+int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data)
{
- mixart_msg_t resp;
+ struct mixart_msg resp;
u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */
int err;
wait_queue_t wait;
@@ -264,9 +265,9 @@ int snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_s
return -EIO;
}
- /* retrieve the answer into the same mixart_msg_t */
+ /* retrieve the answer into the same struct mixart_msg */
resp.message_id = 0;
- resp.uid = (mixart_uid_t){0,0};
+ resp.uid = (struct mixart_uid){0,0};
resp.data = resp_data;
resp.size = max_resp_size;
@@ -280,7 +281,8 @@ int snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_s
}
-int snd_mixart_send_msg_wait_notif(mixart_mgr_t *mgr, mixart_msg_t *request, u32 notif_event)
+int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr,
+ struct mixart_msg *request, u32 notif_event)
{
int err;
wait_queue_t wait;
@@ -321,7 +323,7 @@ int snd_mixart_send_msg_wait_notif(mixart_mgr_t *mgr, mixart_msg_t *request, u32
}
-int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request)
+int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request)
{
u32 message_frame;
unsigned long flags;
@@ -332,7 +334,7 @@ int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request)
err = send_msg(mgr, request, MSG_DEFAULT_SIZE, 0, &message_frame);
spin_unlock_irqrestore(&mgr->msg_lock, flags);
- /* the answer will be handled by snd_mixart_msg_tasklet() */
+ /* the answer will be handled by snd_struct mixart_msgasklet() */
atomic_inc(&mgr->msg_processed);
return err;
@@ -343,10 +345,10 @@ int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request)
static u32 mixart_msg_data[MSG_DEFAULT_SIZE / 4];
-void snd_mixart_msg_tasklet( unsigned long arg)
+void snd_mixart_msg_tasklet(unsigned long arg)
{
- mixart_mgr_t *mgr = ( mixart_mgr_t*)(arg);
- mixart_msg_t resp;
+ struct mixart_mgr *mgr = ( struct mixart_mgr*)(arg);
+ struct mixart_msg resp;
u32 msg, addr, type;
int err;
@@ -406,9 +408,9 @@ void snd_mixart_msg_tasklet( unsigned long arg)
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- mixart_mgr_t *mgr = dev_id;
+ struct mixart_mgr *mgr = dev_id;
int err;
- mixart_msg_t resp;
+ struct mixart_msg resp;
u32 msg;
u32 it_reg;
@@ -448,7 +450,8 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if(resp.message_id == MSG_SERVICES_TIMER_NOTIFY) {
int i;
- mixart_timer_notify_t *notify = (mixart_timer_notify_t*)mixart_msg_data;
+ struct mixart_timer_notify *notify;
+ notify = (struct mixart_timer_notify *)mixart_msg_data;
for(i=0; i<notify->stream_count; i++) {
@@ -458,8 +461,8 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned int sub_number = buffer_id & MIXART_NOTIFY_SUBS_MASK; /* 0 to MIXART_PLAYBACK_STREAMS */
unsigned int is_capture = ((buffer_id & MIXART_NOTIFY_CAPT_MASK) != 0); /* playback == 0 / capture == 1 */
- mixart_t *chip = mgr->chip[chip_number];
- mixart_stream_t *stream;
+ struct snd_mixart *chip = mgr->chip[chip_number];
+ struct mixart_stream *stream;
if ((chip_number >= mgr->num_cards) || (pcm_number >= MIXART_PCM_TOTAL) || (sub_number >= MIXART_PLAYBACK_STREAMS)) {
snd_printk(KERN_ERR "error MSG_SERVICES_TIMER_NOTIFY buffer_id (%x) pos(%d)\n",
@@ -473,7 +476,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
stream = &chip->playback_stream[pcm_number][sub_number];
if (stream->substream && (stream->status == MIXART_STREAM_STATUS_RUNNING)) {
- snd_pcm_runtime_t *runtime = stream->substream->runtime;
+ struct snd_pcm_runtime *runtime = stream->substream->runtime;
int elapsed = 0;
u64 sample_count = ((u64)notify->streams[i].sample_pos_high_part) << 32;
sample_count |= notify->streams[i].sample_pos_low_part;
@@ -561,7 +564,7 @@ irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
-void snd_mixart_init_mailbox(mixart_mgr_t *mgr)
+void snd_mixart_init_mailbox(struct mixart_mgr *mgr)
{
writel( 0, MIXART_MEM( mgr, MSG_HOST_RSC_PROTECTION ) );
writel( 0, MIXART_MEM( mgr, MSG_AGENT_RSC_PROTECTION ) );
@@ -573,14 +576,14 @@ void snd_mixart_init_mailbox(mixart_mgr_t *mgr)
return;
}
-void snd_mixart_exit_mailbox(mixart_mgr_t *mgr)
+void snd_mixart_exit_mailbox(struct mixart_mgr *mgr)
{
/* no more interrupts on outbound messagebox */
writel_le( MIXART_HOST_ALL_INTERRUPT_MASKED, MIXART_REG( mgr, MIXART_PCI_OMIMR_OFFSET));
return;
}
-void snd_mixart_reset_board(mixart_mgr_t *mgr)
+void snd_mixart_reset_board(struct mixart_mgr *mgr)
{
/* reset miXart */
writel_be( 1, MIXART_REG(mgr, MIXART_BA1_BRUTAL_RESET_OFFSET) );
diff --git a/sound/pci/mixart/mixart_core.h b/sound/pci/mixart/mixart_core.h
index 99450eba15c0..1fe2bcfcc57c 100644
--- a/sound/pci/mixart/mixart_core.h
+++ b/sound/pci/mixart/mixart_core.h
@@ -63,25 +63,23 @@ enum mixart_message_id {
};
-typedef struct mixart_msg mixart_msg_t;
struct mixart_msg
{
u32 message_id;
- mixart_uid_t uid;
+ struct mixart_uid uid;
void* data;
size_t size;
};
/* structs used to communicate with miXart */
-typedef struct mixart_enum_connector_resp mixart_enum_connector_resp_t;
struct mixart_enum_connector_resp
{
u32 error_code;
u32 first_uid_offset;
u32 uid_count;
u32 current_uid_index;
- mixart_uid_t uid[MIXART_MAX_PHYS_CONNECTORS];
+ struct mixart_uid uid[MIXART_MAX_PHYS_CONNECTORS];
} __attribute__((packed));
@@ -90,7 +88,6 @@ struct mixart_enum_connector_resp
#define MIXART_FLOAT_M_20_0_TO_HEX 0xc1a00000 /* -20.0f */
#define MIXART_FLOAT____0_0_TO_HEX 0x00000000 /* 0.0f */
-typedef struct mixart_audio_info_req mixart_audio_info_req_t;
struct mixart_audio_info_req
{
u32 line_max_level; /* float */
@@ -98,7 +95,6 @@ struct mixart_audio_info_req
u32 cd_max_level; /* float */
} __attribute__((packed));
-typedef struct mixart_analog_hw_info mixart_analog_hw_info_t;
struct mixart_analog_hw_info
{
u32 is_present;
@@ -111,7 +107,6 @@ struct mixart_analog_hw_info
u32 zero_var; /* float */
} __attribute__((packed));
-typedef struct mixart_digital_hw_info mixart_digital_hw_info_t;
struct mixart_digital_hw_info
{
u32 hw_connection_type;
@@ -120,37 +115,33 @@ struct mixart_digital_hw_info
u32 reserved;
} __attribute__((packed));
-typedef struct mixart_analog_info mixart_analog_info_t;
struct mixart_analog_info
{
u32 type_mask;
- mixart_analog_hw_info_t micro_info;
- mixart_analog_hw_info_t line_info;
- mixart_analog_hw_info_t cd_info;
+ struct mixart_analog_hw_info micro_info;
+ struct mixart_analog_hw_info line_info;
+ struct mixart_analog_hw_info cd_info;
u32 analog_level_present;
} __attribute__((packed));
-typedef struct mixart_digital_info mixart_digital_info_t;
struct mixart_digital_info
{
u32 type_mask;
- mixart_digital_hw_info_t aes_info;
- mixart_digital_hw_info_t adat_info;
+ struct mixart_digital_hw_info aes_info;
+ struct mixart_digital_hw_info adat_info;
} __attribute__((packed));
-typedef struct mixart_audio_info mixart_audio_info_t;
struct mixart_audio_info
{
u32 clock_type_mask;
- mixart_analog_info_t analog_info;
- mixart_digital_info_t digital_info;
+ struct mixart_analog_info analog_info;
+ struct mixart_digital_info digital_info;
} __attribute__((packed));
-typedef struct mixart_audio_info_resp mixart_audio_info_resp_t;
struct mixart_audio_info_resp
{
u32 txx_status;
- mixart_audio_info_t info;
+ struct mixart_audio_info info;
} __attribute__((packed));
@@ -158,7 +149,6 @@ struct mixart_audio_info_resp
#define MIXART_FLOAT_P__4_0_TO_HEX 0x40800000 /* +4.0f */
#define MIXART_FLOAT_P__8_0_TO_HEX 0x41000000 /* +8.0f */
-typedef struct mixart_stream_info mixart_stream_info_t;
struct mixart_stream_info
{
u32 size_max_byte_frame;
@@ -169,7 +159,6 @@ struct mixart_stream_info
/* MSG_STREAM_ADD_INPUT_GROUP */
/* MSG_STREAM_ADD_OUTPUT_GROUP */
-typedef struct mixart_streaming_group_req mixart_streaming_group_req_t;
struct mixart_streaming_group_req
{
u32 stream_count;
@@ -177,33 +166,30 @@ struct mixart_streaming_group_req
u32 user_grp_number;
u32 first_phys_audio;
u32 latency;
- mixart_stream_info_t stream_info[32];
- mixart_uid_t connector;
+ struct mixart_stream_info stream_info[32];
+ struct mixart_uid connector;
u32 flow_entry[32];
} __attribute__((packed));
-typedef struct mixart_stream_desc mixart_stream_desc_t;
struct mixart_stream_desc
{
- mixart_uid_t stream_uid;
+ struct mixart_uid stream_uid;
u32 stream_desc;
} __attribute__((packed));
-typedef struct mixart_streaming_group mixart_streaming_group_t;
struct mixart_streaming_group
{
u32 status;
- mixart_uid_t group;
+ struct mixart_uid group;
u32 pipe_desc;
u32 stream_count;
- mixart_stream_desc_t stream[32];
+ struct mixart_stream_desc stream[32];
} __attribute__((packed));
/* MSG_STREAM_DELETE_GROUP */
/* request : mixart_uid_t group */
-typedef struct mixart_delete_group_resp mixart_delete_group_resp_t;
struct mixart_delete_group_resp
{
u32 status;
@@ -217,55 +203,49 @@ struct mixart_delete_group_resp
MSG_STREAM_STOP_OUTPUT_STAGE_PACKET = 0x130000 + 11,
*/
-typedef struct mixart_fx_couple_uid mixart_fx_couple_uid_t;
struct mixart_fx_couple_uid
{
- mixart_uid_t uid_fx_code;
- mixart_uid_t uid_fx_data;
+ struct mixart_uid uid_fx_code;
+ struct mixart_uid uid_fx_data;
} __attribute__((packed));
-typedef struct mixart_txx_stream_desc mixart_txx_stream_desc_t;
struct mixart_txx_stream_desc
{
- mixart_uid_t uid_pipe;
+ struct mixart_uid uid_pipe;
u32 stream_idx;
u32 fx_number;
- mixart_fx_couple_uid_t uid_fx[4];
+ struct mixart_fx_couple_uid uid_fx[4];
} __attribute__((packed));
-typedef struct mixart_flow_info mixart_flow_info_t;
struct mixart_flow_info
{
- mixart_txx_stream_desc_t stream_desc;
+ struct mixart_txx_stream_desc stream_desc;
u32 flow_entry;
u32 flow_phy_addr;
} __attribute__((packed));
-typedef struct mixart_stream_state_req mixart_stream_state_req_t;
struct mixart_stream_state_req
{
u32 delayed;
u64 scheduler;
u32 reserved4np[3];
u32 stream_count; /* set to 1 for instance */
- mixart_flow_info_t stream_info; /* could be an array[stream_count] */
+ struct mixart_flow_info stream_info; /* could be an array[stream_count] */
} __attribute__((packed));
/* MSG_STREAM_START_STREAM_GRP_PACKET = 0x130000 + 6
MSG_STREAM_STOP_STREAM_GRP_PACKET = 0x130000 + 9
*/
-typedef struct mixart_group_state_req mixart_group_state_req_t;
struct mixart_group_state_req
{
u32 delayed;
u64 scheduler;
u32 reserved4np[2];
u32 pipe_count; /* set to 1 for instance */
- mixart_uid_t pipe_uid[1]; /* could be an array[pipe_count] */
+ struct mixart_uid pipe_uid[1]; /* could be an array[pipe_count] */
} __attribute__((packed));
-typedef struct mixart_group_state_resp mixart_group_state_resp_t;
struct mixart_group_state_resp
{
u32 txx_status;
@@ -276,7 +256,6 @@ struct mixart_group_state_resp
/* Structures used by the MSG_SERVICES_TIMER_NOTIFY command */
-typedef struct mixart_sample_pos mixart_sample_pos_t;
struct mixart_sample_pos
{
u32 buffer_id;
@@ -285,11 +264,10 @@ struct mixart_sample_pos
u32 sample_pos_low_part;
} __attribute__((packed));
-typedef struct mixart_timer_notify mixart_timer_notify_t;
struct mixart_timer_notify
{
u32 stream_count;
- mixart_sample_pos_t streams[MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS];
+ struct mixart_sample_pos streams[MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS];
} __attribute__((packed));
@@ -298,11 +276,10 @@ struct mixart_timer_notify
/* request is a uid with desc = MSG_CONSOLE_MANAGER | cardindex */
-typedef struct mixart_return_uid mixart_return_uid_t;
struct mixart_return_uid
{
u32 error_code;
- mixart_uid_t uid;
+ struct mixart_uid uid;
} __attribute__((packed));
/* MSG_CLOCK_CHECK_PROPERTIES = 0x200001,
@@ -327,7 +304,6 @@ enum mixart_clock_mode {
};
-typedef struct mixart_clock_properties mixart_clock_properties_t;
struct mixart_clock_properties
{
u32 error_code;
@@ -336,17 +312,16 @@ struct mixart_clock_properties
u32 reference_frequency;
u32 clock_generic_type;
u32 clock_mode;
- mixart_uid_t uid_clock_source;
- mixart_uid_t uid_event_source;
+ struct mixart_uid uid_clock_source;
+ struct mixart_uid uid_event_source;
u32 event_mode;
u32 synchro_signal_presence;
u32 format;
u32 board_mask;
u32 nb_callers; /* set to 1 (see below) */
- mixart_uid_t uid_caller[1];
+ struct mixart_uid uid_caller[1];
} __attribute__((packed));
-typedef struct mixart_clock_properties_resp mixart_clock_properties_resp_t;
struct mixart_clock_properties_resp
{
u32 status;
@@ -388,7 +363,6 @@ enum mixart_sample_type {
ST_INTEGER_32LE
};
-typedef struct mixart_stream_param_desc mixart_stream_param_desc_t;
struct mixart_stream_param_desc
{
u32 coding_type; /* use enum mixart_coding_type */
@@ -432,7 +406,7 @@ struct mixart_stream_param_desc
u32 reserved4np[3];
u32 pipe_count; /* set to 1 (array size !) */
u32 stream_count; /* set to 1 (array size !) */
- mixart_txx_stream_desc_t stream_desc[1]; /* only one stream per command, but this could be an array */
+ struct mixart_txx_stream_desc stream_desc[1]; /* only one stream per command, but this could be an array */
} __attribute__((packed));
@@ -441,7 +415,6 @@ struct mixart_stream_param_desc
*/
-typedef struct mixart_get_out_audio_level mixart_get_out_audio_level_t;
struct mixart_get_out_audio_level
{
u32 txx_status;
@@ -465,7 +438,6 @@ struct mixart_get_out_audio_level
#define MIXART_AUDIO_LEVEL_MUTE_M1_MASK 0x10
#define MIXART_AUDIO_LEVEL_MUTE_M2_MASK 0x20
-typedef struct mixart_set_out_audio_level mixart_set_out_audio_level_t;
struct mixart_set_out_audio_level
{
u32 delayed;
@@ -487,14 +459,13 @@ struct mixart_set_out_audio_level
#define MIXART_MAX_PHYS_IO (MIXART_MAX_CARDS * 2 * 2) /* 4 * (analog+digital) * (playback+capture) */
-typedef struct mixart_uid_enumeration mixart_uid_enumeration_t;
struct mixart_uid_enumeration
{
u32 error_code;
u32 first_uid_offset;
u32 nb_uid;
u32 current_uid_index;
- mixart_uid_t uid[MIXART_MAX_PHYS_IO];
+ struct mixart_uid uid[MIXART_MAX_PHYS_IO];
} __attribute__((packed));
@@ -502,42 +473,38 @@ struct mixart_uid_enumeration
MSG_PHYSICALIO_GET_LEVEL = 0x0F000C,
*/
-typedef struct mixart_io_channel_level mixart_io_channel_level_t;
struct mixart_io_channel_level
{
u32 analog_level; /* float */
u32 unused[2];
} __attribute__((packed));
-typedef struct mixart_io_level mixart_io_level_t;
struct mixart_io_level
{
s32 channel; /* 0=left, 1=right, -1=both, -2=both same */
- mixart_io_channel_level_t level[2];
+ struct mixart_io_channel_level level[2];
} __attribute__((packed));
/* MSG_STREAM_SET_IN_AUDIO_LEVEL = 0x130015,
*/
-typedef struct mixart_in_audio_level_info mixart_in_audio_level_info_t;
struct mixart_in_audio_level_info
{
- mixart_uid_t connector;
+ struct mixart_uid connector;
u32 valid_mask1;
u32 valid_mask2;
u32 digital_level;
u32 analog_level;
} __attribute__((packed));
-typedef struct mixart_set_in_audio_level_req mixart_set_in_audio_level_req_t;
struct mixart_set_in_audio_level_req
{
u32 delayed;
u64 scheduler;
u32 audio_count; /* set to <= 2 */
u32 reserved4np;
- mixart_in_audio_level_info_t level[2];
+ struct mixart_in_audio_level_info level[2];
} __attribute__((packed));
/* response is a 32 bit status */
@@ -556,7 +523,6 @@ struct mixart_set_in_audio_level_req
#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_1 0x40
#define MIXART_OUT_STREAM_SET_LEVEL_MUTE_2 0x80
-typedef struct mixart_out_stream_level_info mixart_out_stream_level_info_t;
struct mixart_out_stream_level_info
{
u32 valid_mask1;
@@ -571,37 +537,35 @@ struct mixart_out_stream_level_info
u32 mute2;
} __attribute__((packed));
-typedef struct mixart_set_out_stream_level mixart_set_out_stream_level_t;
struct mixart_set_out_stream_level
{
- mixart_txx_stream_desc_t desc;
- mixart_out_stream_level_info_t out_level;
+ struct mixart_txx_stream_desc desc;
+ struct mixart_out_stream_level_info out_level;
} __attribute__((packed));
-typedef struct mixart_set_out_stream_level_req mixart_set_out_stream_level_req_t;
struct mixart_set_out_stream_level_req
{
u32 delayed;
u64 scheduler;
u32 reserved4np[2];
u32 nb_of_stream; /* set to 1 */
- mixart_set_out_stream_level_t stream_level; /* could be an array */
+ struct mixart_set_out_stream_level stream_level; /* could be an array */
} __attribute__((packed));
/* response to this request is a u32 status value */
/* exported */
-void snd_mixart_init_mailbox(mixart_mgr_t *mgr);
-void snd_mixart_exit_mailbox(mixart_mgr_t *mgr);
+void snd_mixart_init_mailbox(struct mixart_mgr *mgr);
+void snd_mixart_exit_mailbox(struct mixart_mgr *mgr);
-int snd_mixart_send_msg(mixart_mgr_t *mgr, mixart_msg_t *request, int max_resp_size, void *resp_data);
-int snd_mixart_send_msg_wait_notif(mixart_mgr_t *mgr, mixart_msg_t *request, u32 notif_event);
-int snd_mixart_send_msg_nonblock(mixart_mgr_t *mgr, mixart_msg_t *request);
+int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int max_resp_size, void *resp_data);
+int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *request, u32 notif_event);
+int snd_mixart_send_msg_nonblock(struct mixart_mgr *mgr, struct mixart_msg *request);
irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-void snd_mixart_msg_tasklet( unsigned long arg);
+void snd_mixart_msg_tasklet(unsigned long arg);
-void snd_mixart_reset_board(mixart_mgr_t *mgr);
+void snd_mixart_reset_board(struct mixart_mgr *mgr);
#endif /* __SOUND_MIXART_CORE_H */
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index edd1599fe45e..ca05075c67c6 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -40,7 +40,9 @@
* @param value value
* @param timeout timeout in centisenconds
*/
-static int mixart_wait_nice_for_register_value(mixart_mgr_t *mgr, u32 offset, int is_egal, u32 value, unsigned long timeout)
+static int mixart_wait_nice_for_register_value(struct mixart_mgr *mgr,
+ u32 offset, int is_egal,
+ u32 value, unsigned long timeout)
{
unsigned long end_time = jiffies + (timeout * HZ / 100);
u32 read;
@@ -66,8 +68,6 @@ static int mixart_wait_nice_for_register_value(mixart_mgr_t *mgr, u32 offset, in
/*
structures needed to upload elf code packets
*/
-typedef struct snd_mixart_elf32_ehdr snd_mixart_elf32_ehdr_t;
-
struct snd_mixart_elf32_ehdr {
u8 e_ident[16];
u16 e_type;
@@ -85,8 +85,6 @@ struct snd_mixart_elf32_ehdr {
u16 e_shstrndx;
};
-typedef struct snd_mixart_elf32_phdr snd_mixart_elf32_phdr_t;
-
struct snd_mixart_elf32_phdr {
u32 p_type;
u32 p_offset;
@@ -98,19 +96,19 @@ struct snd_mixart_elf32_phdr {
u32 p_align;
};
-static int mixart_load_elf(mixart_mgr_t *mgr, const struct firmware *dsp )
+static int mixart_load_elf(struct mixart_mgr *mgr, const struct firmware *dsp )
{
char elf32_magic_number[4] = {0x7f,'E','L','F'};
- snd_mixart_elf32_ehdr_t *elf_header;
+ struct snd_mixart_elf32_ehdr *elf_header;
int i;
- elf_header = (snd_mixart_elf32_ehdr_t *)dsp->data;
+ elf_header = (struct snd_mixart_elf32_ehdr *)dsp->data;
for( i=0; i<4; i++ )
if ( elf32_magic_number[i] != elf_header->e_ident[i] )
return -EINVAL;
if( elf_header->e_phoff != 0 ) {
- snd_mixart_elf32_phdr_t elf_programheader;
+ struct snd_mixart_elf32_phdr elf_programheader;
for( i=0; i < be16_to_cpu(elf_header->e_phnum); i++ ) {
u32 pos = be32_to_cpu(elf_header->e_phoff) + (u32)(i * be16_to_cpu(elf_header->e_phentsize));
@@ -137,14 +135,14 @@ static int mixart_load_elf(mixart_mgr_t *mgr, const struct firmware *dsp )
#define MIXART_FIRST_ANA_AUDIO_ID 0
#define MIXART_FIRST_DIG_AUDIO_ID 8
-static int mixart_enum_connectors(mixart_mgr_t *mgr)
+static int mixart_enum_connectors(struct mixart_mgr *mgr)
{
u32 k;
int err;
- mixart_msg_t request;
- mixart_enum_connector_resp_t *connector;
- mixart_audio_info_req_t *audio_info_req;
- mixart_audio_info_resp_t *audio_info;
+ struct mixart_msg request;
+ struct mixart_enum_connector_resp *connector;
+ struct mixart_audio_info_req *audio_info_req;
+ struct mixart_audio_info_resp *audio_info;
connector = kmalloc(sizeof(*connector), GFP_KERNEL);
audio_info_req = kmalloc(sizeof(*audio_info_req), GFP_KERNEL);
@@ -159,7 +157,7 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
audio_info_req->cd_max_level = MIXART_FLOAT____0_0_TO_HEX;
request.message_id = MSG_SYSTEM_ENUM_PLAY_CONNECTOR;
- request.uid = (mixart_uid_t){0,0}; /* board num = 0 */
+ request.uid = (struct mixart_uid){0,0}; /* board num = 0 */
request.data = NULL;
request.size = 0;
@@ -171,7 +169,7 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
}
for(k=0; k < connector->uid_count; k++) {
- mixart_pipe_t* pipe;
+ struct mixart_pipe *pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
pipe = &mgr->chip[k/2]->pipe_out_ana;
@@ -201,7 +199,7 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
}
request.message_id = MSG_SYSTEM_ENUM_RECORD_CONNECTOR;
- request.uid = (mixart_uid_t){0,0}; /* board num = 0 */
+ request.uid = (struct mixart_uid){0,0}; /* board num = 0 */
request.data = NULL;
request.size = 0;
@@ -213,7 +211,7 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
}
for(k=0; k < connector->uid_count; k++) {
- mixart_pipe_t* pipe;
+ struct mixart_pipe *pipe;
if(k < MIXART_FIRST_DIG_AUDIO_ID) {
pipe = &mgr->chip[k/2]->pipe_in_ana;
@@ -251,14 +249,14 @@ static int mixart_enum_connectors(mixart_mgr_t *mgr)
return err;
}
-static int mixart_enum_physio(mixart_mgr_t *mgr)
+static int mixart_enum_physio(struct mixart_mgr *mgr)
{
u32 k;
int err;
- mixart_msg_t request;
- mixart_uid_t get_console_mgr;
- mixart_return_uid_t console_mgr;
- mixart_uid_enumeration_t phys_io;
+ struct mixart_msg request;
+ struct mixart_uid get_console_mgr;
+ struct mixart_return_uid console_mgr;
+ struct mixart_uid_enumeration phys_io;
/* get the uid for the console manager */
get_console_mgr.object_id = 0;
@@ -280,7 +278,7 @@ static int mixart_enum_physio(mixart_mgr_t *mgr)
mgr->uid_console_manager = console_mgr.uid;
request.message_id = MSG_SYSTEM_ENUM_PHYSICAL_IO;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &console_mgr.uid;
request.size = sizeof(console_mgr.uid);
@@ -301,11 +299,11 @@ static int mixart_enum_physio(mixart_mgr_t *mgr)
}
-static int mixart_first_init(mixart_mgr_t *mgr)
+static int mixart_first_init(struct mixart_mgr *mgr)
{
u32 k;
int err;
- mixart_msg_t request;
+ struct mixart_msg request;
if((err = mixart_enum_connectors(mgr)) < 0) return err;
@@ -314,7 +312,7 @@ static int mixart_first_init(mixart_mgr_t *mgr)
/* send a synchro command to card (necessary to do this before first MSG_STREAM_START_STREAM_GRP_PACKET) */
/* though why not here */
request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = NULL;
request.size = 0;
/* this command has no data. response is a 32 bit status */
@@ -331,7 +329,7 @@ static int mixart_first_init(mixart_mgr_t *mgr)
/* firmware base addresses (when hard coded) */
#define MIXART_MOTHERBOARD_XLX_BASE_ADDRESS 0x00600000
-static int mixart_dsp_load(mixart_mgr_t* mgr, int index, const struct firmware *dsp)
+static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmware *dsp)
{
int err, card_index;
u32 status_xilinx, status_elf, status_daught;
@@ -513,7 +511,7 @@ static int mixart_dsp_load(mixart_mgr_t* mgr, int index, const struct firmware *
/* create devices and mixer in accordance with HW options*/
for (card_index = 0; card_index < mgr->num_cards; card_index++) {
- mixart_t *chip = mgr->chip[card_index];
+ struct snd_mixart *chip = mgr->chip[card_index];
if ((err = snd_mixart_create_pcm(chip)) < 0)
return err;
@@ -541,7 +539,7 @@ static int mixart_dsp_load(mixart_mgr_t* mgr, int index, const struct firmware *
#ifdef SND_MIXART_FW_LOADER
-int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
+int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
{
static char *fw_files[3] = {
"miXart8.xlx", "miXart8.elf", "miXart8AES.xlx"
@@ -573,19 +571,20 @@ int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
/* miXart hwdep interface id string */
#define SND_MIXART_HWDEP_ID "miXart Loader"
-static int mixart_hwdep_open(snd_hwdep_t *hw, struct file *file)
+static int mixart_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int mixart_hwdep_release(snd_hwdep_t *hw, struct file *file)
+static int mixart_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+static int mixart_hwdep_dsp_status(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_status *info)
{
- mixart_mgr_t *mgr = hw->private_data;
+ struct mixart_mgr *mgr = hw->private_data;
strcpy(info->id, "miXart");
info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
@@ -597,9 +596,10 @@ static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info
return 0;
}
-static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+static int mixart_hwdep_dsp_load(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image *dsp)
{
- mixart_mgr_t* mgr = hw->private_data;
+ struct mixart_mgr* mgr = hw->private_data;
struct firmware fw;
int err;
@@ -622,10 +622,10 @@ static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
return err;
}
-int snd_mixart_setup_firmware(mixart_mgr_t *mgr)
+int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
{
int err;
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
/* only create hwdep interface for first cardX (see "index" module parameter)*/
if ((err = snd_hwdep_new(mgr->chip[0]->card, SND_MIXART_HWDEP_ID, 0, &hw)) < 0)
diff --git a/sound/pci/mixart/mixart_hwdep.h b/sound/pci/mixart/mixart_hwdep.h
index 25190cc88cf8..a46f5083db99 100644
--- a/sound/pci/mixart/mixart_hwdep.h
+++ b/sound/pci/mixart/mixart_hwdep.h
@@ -140,6 +140,6 @@
#define MIXART_OIDI 0x008 /* 0000 0000 1000 */
-int snd_mixart_setup_firmware(mixart_mgr_t *mgr);
+int snd_mixart_setup_firmware(struct mixart_mgr *mgr);
#endif /* __SOUND_MIXART_HWDEP_H */
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index 39c15416fc80..36a7e9ddfb15 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -298,12 +298,12 @@ static u32 mixart_analog_level[256] = {
#define MIXART_ANALOG_PLAYBACK_LEVEL_MAX 192 /* 0.0 dB + 1.5 dB = 1.5 dB */
#define MIXART_ANALOG_PLAYBACK_ZERO_LEVEL 189 /* -1.5 dB + 1.5 dB = 0.0 dB */
-static int mixart_update_analog_audio_level(mixart_t* chip, int is_capture)
+static int mixart_update_analog_audio_level(struct snd_mixart* chip, int is_capture)
{
int i, err;
- mixart_msg_t request;
- mixart_io_level_t io_level;
- mixart_return_uid_t resp;
+ struct mixart_msg request;
+ struct mixart_io_level io_level;
+ struct mixart_return_uid resp;
memset(&io_level, 0, sizeof(io_level));
io_level.channel = -1; /* left and right */
@@ -336,7 +336,7 @@ static int mixart_update_analog_audio_level(mixart_t* chip, int is_capture)
/*
* analog level control
*/
-static int mixart_analog_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -350,9 +350,9 @@ static int mixart_analog_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int mixart_analog_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mgr->mixer_mutex);
if(kcontrol->private_value == 0) { /* playback */
ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
@@ -365,9 +365,9 @@ static int mixart_analog_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int mixart_analog_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
int is_capture, i;
@@ -386,7 +386,7 @@ static int mixart_analog_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return changed;
}
-static snd_kcontrol_new_t mixart_control_analog_level = {
+static struct snd_kcontrol_new mixart_control_analog_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* name will be filled later */
.info = mixart_analog_vol_info,
@@ -395,7 +395,7 @@ static snd_kcontrol_new_t mixart_control_analog_level = {
};
/* shared */
-static int mixart_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int mixart_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -404,9 +404,9 @@ static int mixart_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-static int mixart_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_audio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mgr->mixer_mutex);
ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
@@ -415,9 +415,9 @@ static int mixart_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return 0;
}
-static int mixart_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_audio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int i, changed = 0;
down(&chip->mgr->mixer_mutex);
for(i=0; i<2; i++) {
@@ -431,7 +431,7 @@ static int mixart_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
return changed;
}
-static snd_kcontrol_new_t mixart_control_output_switch = {
+static struct snd_kcontrol_new mixart_control_output_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.info = mixart_sw_info, /* shared */
@@ -703,14 +703,14 @@ static u32 mixart_digital_level[256] = {
#define MIXART_DIGITAL_ZERO_LEVEL 219 /* 0.0 dB */
-int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx)
+int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx)
{
int err, i;
int volume[2];
- mixart_msg_t request;
- mixart_set_out_stream_level_req_t set_level;
+ struct mixart_msg request;
+ struct mixart_set_out_stream_level_req set_level;
u32 status;
- mixart_pipe_t *pipe;
+ struct mixart_pipe *pipe;
memset(&set_level, 0, sizeof(set_level));
set_level.nb_of_stream = 1;
@@ -741,7 +741,7 @@ int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx)
set_level.stream_level.out_level.right_to_out2_level = mixart_digital_level[volume[1]];
request.message_id = MSG_STREAM_SET_OUT_STREAM_LEVEL;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &set_level;
request.size = sizeof(set_level);
@@ -753,12 +753,12 @@ int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx)
return 0;
}
-int mixart_update_capture_stream_level(mixart_t* chip, int is_aes)
+int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes)
{
int err, i, idx;
- mixart_pipe_t* pipe;
- mixart_msg_t request;
- mixart_set_in_audio_level_req_t set_level;
+ struct mixart_pipe *pipe;
+ struct mixart_msg request;
+ struct mixart_set_in_audio_level_req set_level;
u32 status;
if(is_aes) {
@@ -784,7 +784,7 @@ int mixart_update_capture_stream_level(mixart_t* chip, int is_aes)
}
request.message_id = MSG_STREAM_SET_IN_AUDIO_LEVEL;
- request.uid = (mixart_uid_t){0,0};
+ request.uid = (struct mixart_uid){0,0};
request.data = &set_level;
request.size = sizeof(set_level);
@@ -798,7 +798,7 @@ int mixart_update_capture_stream_level(mixart_t* chip, int is_aes)
/* shared */
-static int mixart_digital_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int mixart_digital_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -810,9 +810,9 @@ static int mixart_digital_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
#define MIXART_VOL_REC_MASK 1
#define MIXART_VOL_AES_MASK 2
-static int mixart_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int *stored_volume;
int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK;
@@ -832,9 +832,9 @@ static int mixart_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static int mixart_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int changed = 0;
int is_capture = kcontrol->private_value & MIXART_VOL_REC_MASK;
@@ -864,7 +864,7 @@ static int mixart_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return changed;
}
-static snd_kcontrol_new_t snd_mixart_pcm_vol =
+static struct snd_kcontrol_new snd_mixart_pcm_vol =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* name will be filled later */
@@ -875,9 +875,9 @@ static snd_kcontrol_new_t snd_mixart_pcm_vol =
};
-static int mixart_pcm_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_pcm_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
snd_assert ( idx < MIXART_PLAYBACK_STREAMS );
down(&chip->mgr->mixer_mutex);
@@ -889,9 +889,9 @@ static int mixart_pcm_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return 0;
}
-static int mixart_pcm_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
int is_aes = kcontrol->private_value & MIXART_VOL_AES_MASK;
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
@@ -911,7 +911,7 @@ static int mixart_pcm_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return changed;
}
-static snd_kcontrol_new_t mixart_control_pcm_switch = {
+static struct snd_kcontrol_new mixart_control_pcm_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* name will be filled later */
.count = MIXART_PLAYBACK_STREAMS,
@@ -920,11 +920,11 @@ static snd_kcontrol_new_t mixart_control_pcm_switch = {
.put = mixart_pcm_sw_put
};
-static int mixart_update_monitoring(mixart_t* chip, int channel)
+static int mixart_update_monitoring(struct snd_mixart* chip, int channel)
{
int err;
- mixart_msg_t request;
- mixart_set_out_audio_level_t audio_level;
+ struct mixart_msg request;
+ struct mixart_set_out_audio_level audio_level;
u32 resp;
if(chip->pipe_out_ana.status == PIPE_UNDEFINED)
@@ -953,9 +953,9 @@ static int mixart_update_monitoring(mixart_t* chip, int channel)
* monitoring level control
*/
-static int mixart_monitor_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_monitor_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mgr->mixer_mutex);
ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
@@ -963,9 +963,9 @@ static int mixart_monitor_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int mixart_monitor_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
int i;
down(&chip->mgr->mixer_mutex);
@@ -980,7 +980,7 @@ static int mixart_monitor_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return changed;
}
-static snd_kcontrol_new_t mixart_control_monitor_vol = {
+static struct snd_kcontrol_new mixart_control_monitor_vol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Volume",
.info = mixart_digital_vol_info, /* shared */
@@ -992,9 +992,9 @@ static snd_kcontrol_new_t mixart_control_monitor_vol = {
* monitoring switch control
*/
-static int mixart_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_monitor_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
down(&chip->mgr->mixer_mutex);
ucontrol->value.integer.value[0] = chip->monitoring_active[0];
ucontrol->value.integer.value[1] = chip->monitoring_active[1];
@@ -1002,9 +1002,9 @@ static int mixart_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int mixart_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixart_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- mixart_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
int i;
down(&chip->mgr->mixer_mutex);
@@ -1033,7 +1033,7 @@ static int mixart_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return (changed != 0);
}
-static snd_kcontrol_new_t mixart_control_monitor_sw = {
+static struct snd_kcontrol_new mixart_control_monitor_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Switch",
.info = mixart_sw_info, /* shared */
@@ -1042,7 +1042,7 @@ static snd_kcontrol_new_t mixart_control_monitor_sw = {
};
-static void mixart_reset_audio_levels(mixart_t *chip)
+static void mixart_reset_audio_levels(struct snd_mixart *chip)
{
/* analog volumes can be set even if there is no pipe */
mixart_update_analog_audio_level(chip, 0);
@@ -1054,15 +1054,15 @@ static void mixart_reset_audio_levels(mixart_t *chip)
}
-int snd_mixart_create_mixer(mixart_mgr_t *mgr)
+int snd_mixart_create_mixer(struct mixart_mgr *mgr)
{
- mixart_t *chip;
+ struct snd_mixart *chip;
int err, i;
init_MUTEX(&mgr->mixer_mutex); /* can be in another place */
for(i=0; i<mgr->num_cards; i++) {
- snd_kcontrol_new_t temp;
+ struct snd_kcontrol_new temp;
chip = mgr->chip[i];
/* analog output level control */
diff --git a/sound/pci/mixart/mixart_mixer.h b/sound/pci/mixart/mixart_mixer.h
index b4d9535087c4..04aa24e35c3f 100644
--- a/sound/pci/mixart/mixart_mixer.h
+++ b/sound/pci/mixart/mixart_mixer.h
@@ -24,8 +24,8 @@
#define __SOUND_MIXART_MIXER_H
/* exported */
-int mixart_update_playback_stream_level(mixart_t* chip, int is_aes, int idx);
-int mixart_update_capture_stream_level(mixart_t* chip, int is_aes);
-int snd_mixart_create_mixer(mixart_mgr_t* mgr);
+int mixart_update_playback_stream_level(struct snd_mixart* chip, int is_aes, int idx);
+int mixart_update_capture_stream_level(struct snd_mixart* chip, int is_aes);
+int snd_mixart_create_mixer(struct mixart_mgr* mgr);
#endif /* __SOUND_MIXART_MIXER_H */
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 089d23b4a002..0d0ff54f0fc6 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -183,17 +183,10 @@ module_param(enable, bool, 0444);
#define NM_PBUFFER_WMARK (NM_PLAYBACK_REG_OFFSET + 0xc)
#define NM_PBUFFER_CURRP (NM_PLAYBACK_REG_OFFSET + 0x8)
-/*
- * type definitions
- */
-
-typedef struct snd_nm256 nm256_t;
-typedef struct snd_nm256_stream nm256_stream_t;
+struct nm256_stream {
-struct snd_nm256_stream {
-
- nm256_t *chip;
- snd_pcm_substream_t *substream;
+ struct nm256 *chip;
+ struct snd_pcm_substream *substream;
int running;
int suspended;
@@ -210,9 +203,9 @@ struct snd_nm256_stream {
};
-struct snd_nm256 {
+struct nm256 {
- snd_card_t *card;
+ struct snd_card *card;
void __iomem *cport; /* control port */
struct resource *res_cport; /* its resource */
@@ -244,11 +237,11 @@ struct snd_nm256 {
int badintrcount; /* counter to check bogus interrupts */
struct semaphore irq_mutex;
- nm256_stream_t streams[2];
+ struct nm256_stream streams[2];
- ac97_t *ac97;
+ struct snd_ac97 *ac97;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
struct pci_dev *pci;
@@ -281,48 +274,49 @@ MODULE_DEVICE_TABLE(pci, snd_nm256_ids);
*/
static inline u8
-snd_nm256_readb(nm256_t *chip, int offset)
+snd_nm256_readb(struct nm256 *chip, int offset)
{
return readb(chip->cport + offset);
}
static inline u16
-snd_nm256_readw(nm256_t *chip, int offset)
+snd_nm256_readw(struct nm256 *chip, int offset)
{
return readw(chip->cport + offset);
}
static inline u32
-snd_nm256_readl(nm256_t *chip, int offset)
+snd_nm256_readl(struct nm256 *chip, int offset)
{
return readl(chip->cport + offset);
}
static inline void
-snd_nm256_writeb(nm256_t *chip, int offset, u8 val)
+snd_nm256_writeb(struct nm256 *chip, int offset, u8 val)
{
writeb(val, chip->cport + offset);
}
static inline void
-snd_nm256_writew(nm256_t *chip, int offset, u16 val)
+snd_nm256_writew(struct nm256 *chip, int offset, u16 val)
{
writew(val, chip->cport + offset);
}
static inline void
-snd_nm256_writel(nm256_t *chip, int offset, u32 val)
+snd_nm256_writel(struct nm256 *chip, int offset, u32 val)
{
writel(val, chip->cport + offset);
}
static inline void
-snd_nm256_write_buffer(nm256_t *chip, void *src, int offset, int size)
+snd_nm256_write_buffer(struct nm256 *chip, void *src, int offset, int size)
{
offset -= chip->buffer_start;
#ifdef CONFIG_SND_DEBUG
if (offset < 0 || offset >= chip->buffer_size) {
- snd_printk(KERN_ERR "write_buffer invalid offset = %d size = %d\n", offset, size);
+ snd_printk(KERN_ERR "write_buffer invalid offset = %d size = %d\n",
+ offset, size);
return;
}
#endif
@@ -343,7 +337,7 @@ snd_nm256_get_start_offset(int which)
}
static void
-snd_nm256_load_one_coefficient(nm256_t *chip, int stream, u32 port, int which)
+snd_nm256_load_one_coefficient(struct nm256 *chip, int stream, u32 port, int which)
{
u32 coeff_buf = chip->coeff_buf[stream];
u16 offset = snd_nm256_get_start_offset(which);
@@ -358,13 +352,15 @@ snd_nm256_load_one_coefficient(nm256_t *chip, int stream, u32 port, int which)
}
static void
-snd_nm256_load_coefficient(nm256_t *chip, int stream, int number)
+snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number)
{
/* The enable register for the specified engine. */
- u32 poffset = (stream == SNDRV_PCM_STREAM_CAPTURE ? NM_RECORD_ENABLE_REG : NM_PLAYBACK_ENABLE_REG);
+ u32 poffset = (stream == SNDRV_PCM_STREAM_CAPTURE ?
+ NM_RECORD_ENABLE_REG : NM_PLAYBACK_ENABLE_REG);
u32 addr = NM_COEFF_START_OFFSET;
- addr += (stream == SNDRV_PCM_STREAM_CAPTURE ? NM_RECORD_REG_OFFSET : NM_PLAYBACK_REG_OFFSET);
+ addr += (stream == SNDRV_PCM_STREAM_CAPTURE ?
+ NM_RECORD_REG_OFFSET : NM_PLAYBACK_REG_OFFSET);
if (snd_nm256_readb(chip, poffset) & 1) {
snd_printd("NM256: Engine was enabled while loading coefficients!\n");
@@ -400,7 +396,7 @@ snd_nm256_load_coefficient(nm256_t *chip, int stream, int number)
static unsigned int samplerates[8] = {
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
};
-static snd_pcm_hw_constraint_list_t constraints_rates = {
+static struct snd_pcm_hw_constraint_list constraints_rates = {
.count = ARRAY_SIZE(samplerates),
.list = samplerates,
.mask = 0,
@@ -425,9 +421,10 @@ snd_nm256_fixed_rate(unsigned int rate)
* set sample rate and format
*/
static void
-snd_nm256_set_format(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *substream)
+snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int rate_index = snd_nm256_fixed_rate(runtime->rate);
unsigned char ratebits = (rate_index << 4) & NM_RATE_MASK;
@@ -460,12 +457,12 @@ 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)
+static int snd_nm256_acquire_irq(struct nm256 *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)) {
+ chip->card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq);
up(&chip->irq_mutex);
return -EBUSY;
@@ -478,13 +475,13 @@ static int snd_nm256_acquire_irq(nm256_t *chip)
}
/* release interrupt */
-static void snd_nm256_release_irq(nm256_t *chip)
+static void snd_nm256_release_irq(struct nm256 *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);
+ free_irq(chip->irq, chip);
chip->irq = -1;
}
up(&chip->irq_mutex);
@@ -495,7 +492,7 @@ static void snd_nm256_release_irq(nm256_t *chip)
*/
/* update the watermark (current period) */
-static void snd_nm256_pcm_mark(nm256_t *chip, nm256_stream_t *s, int reg)
+static void snd_nm256_pcm_mark(struct nm256 *chip, struct nm256_stream *s, int reg)
{
s->cur_period++;
s->cur_period %= s->periods;
@@ -506,7 +503,8 @@ static void snd_nm256_pcm_mark(nm256_t *chip, nm256_stream_t *s, int reg)
#define snd_nm256_capture_mark(chip, s) snd_nm256_pcm_mark(chip, s, NM_RBUFFER_WMARK)
static void
-snd_nm256_playback_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *substream)
+snd_nm256_playback_start(struct nm256 *chip, struct nm256_stream *s,
+ struct snd_pcm_substream *substream)
{
/* program buffer pointers */
snd_nm256_writel(chip, NM_PBUFFER_START, s->buf);
@@ -522,7 +520,8 @@ snd_nm256_playback_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *
}
static void
-snd_nm256_capture_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *substream)
+snd_nm256_capture_start(struct nm256 *chip, struct nm256_stream *s,
+ struct snd_pcm_substream *substream)
{
/* program buffer pointers */
snd_nm256_writel(chip, NM_RBUFFER_START, s->buf);
@@ -537,7 +536,7 @@ snd_nm256_capture_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *s
/* Stop the play engine. */
static void
-snd_nm256_playback_stop(nm256_t *chip)
+snd_nm256_playback_stop(struct nm256 *chip)
{
/* Shut off sound from both channels. */
snd_nm256_writew(chip, NM_AUDIO_MUTE_REG,
@@ -547,17 +546,17 @@ snd_nm256_playback_stop(nm256_t *chip)
}
static void
-snd_nm256_capture_stop(nm256_t *chip)
+snd_nm256_capture_stop(struct nm256 *chip)
{
/* Disable recording engine. */
snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, 0);
}
static int
-snd_nm256_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+snd_nm256_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
- nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
+ struct nm256_stream *s = substream->runtime->private_data;
int err = 0;
snd_assert(s != NULL, return -ENXIO);
@@ -591,10 +590,10 @@ snd_nm256_playback_trigger(snd_pcm_substream_t *substream, int cmd)
}
static int
-snd_nm256_capture_trigger(snd_pcm_substream_t *substream, int cmd)
+snd_nm256_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
- nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
+ struct nm256_stream *s = substream->runtime->private_data;
int err = 0;
snd_assert(s != NULL, return -ENXIO);
@@ -627,11 +626,11 @@ snd_nm256_capture_trigger(snd_pcm_substream_t *substream, int cmd)
/*
* prepare playback/capture channel
*/
-static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_nm256_pcm_prepare(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
snd_assert(s, return -ENXIO);
s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);
@@ -652,10 +651,10 @@ static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream)
* get the current pointer
*/
static snd_pcm_uframes_t
-snd_nm256_playback_pointer(snd_pcm_substream_t * substream)
+snd_nm256_playback_pointer(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
- nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
+ struct nm256_stream *s = substream->runtime->private_data;
unsigned long curp;
snd_assert(s, return 0);
@@ -665,10 +664,10 @@ snd_nm256_playback_pointer(snd_pcm_substream_t * substream)
}
static snd_pcm_uframes_t
-snd_nm256_capture_pointer(snd_pcm_substream_t * substream)
+snd_nm256_capture_pointer(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
- nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
+ struct nm256_stream *s = substream->runtime->private_data;
unsigned long curp;
snd_assert(s != NULL, return 0);
@@ -684,13 +683,13 @@ snd_nm256_capture_pointer(snd_pcm_substream_t * substream)
* silence / copy for playback
*/
static int
-snd_nm256_playback_silence(snd_pcm_substream_t *substream,
+snd_nm256_playback_silence(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
count = frames_to_bytes(runtime, count);
pos = frames_to_bytes(runtime, pos);
memset_io(s->bufptr + pos, 0, count);
@@ -698,14 +697,14 @@ snd_nm256_playback_silence(snd_pcm_substream_t *substream,
}
static int
-snd_nm256_playback_copy(snd_pcm_substream_t *substream,
+snd_nm256_playback_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
count = frames_to_bytes(runtime, count);
pos = frames_to_bytes(runtime, pos);
if (copy_from_user_toio(s->bufptr + pos, src, count))
@@ -717,14 +716,14 @@ snd_nm256_playback_copy(snd_pcm_substream_t *substream,
* copy to user
*/
static int
-snd_nm256_capture_copy(snd_pcm_substream_t *substream,
+snd_nm256_capture_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *dst,
snd_pcm_uframes_t count)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
count = frames_to_bytes(runtime, count);
pos = frames_to_bytes(runtime, pos);
if (copy_to_user_fromio(dst, s->bufptr + pos, count))
@@ -741,9 +740,9 @@ snd_nm256_capture_copy(snd_pcm_substream_t *substream,
/* spinlock held! */
static void
-snd_nm256_playback_update(nm256_t *chip)
+snd_nm256_playback_update(struct nm256 *chip)
{
- nm256_stream_t *s;
+ struct nm256_stream *s;
s = &chip->streams[SNDRV_PCM_STREAM_PLAYBACK];
if (s->running && s->substream) {
@@ -756,9 +755,9 @@ snd_nm256_playback_update(nm256_t *chip)
/* spinlock held! */
static void
-snd_nm256_capture_update(nm256_t *chip)
+snd_nm256_capture_update(struct nm256 *chip)
{
- nm256_stream_t *s;
+ struct nm256_stream *s;
s = &chip->streams[SNDRV_PCM_STREAM_CAPTURE];
if (s->running && s->substream) {
@@ -772,7 +771,7 @@ snd_nm256_capture_update(nm256_t *chip)
/*
* hardware info
*/
-static snd_pcm_hardware_t snd_nm256_playback =
+static struct snd_pcm_hardware snd_nm256_playback =
{
.info = SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -791,7 +790,7 @@ static snd_pcm_hardware_t snd_nm256_playback =
.period_bytes_max = 128 * 1024,
};
-static snd_pcm_hardware_t snd_nm256_capture =
+static struct snd_pcm_hardware snd_nm256_capture =
{
.info = SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -812,7 +811,8 @@ static snd_pcm_hardware_t snd_nm256_capture =
/* set dma transfer size */
-static int snd_nm256_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params)
+static int snd_nm256_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
/* area and addr are already set and unchanged */
substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
@@ -822,11 +822,11 @@ static int snd_nm256_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_pa
/*
* open
*/
-static void snd_nm256_setup_stream(nm256_t *chip, nm256_stream_t *s,
- snd_pcm_substream_t *substream,
- snd_pcm_hardware_t *hw_ptr)
+static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hardware *hw_ptr)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
s->running = 0;
runtime->hw = *hw_ptr;
@@ -844,9 +844,9 @@ static void snd_nm256_setup_stream(nm256_t *chip, nm256_stream_t *s,
}
static int
-snd_nm256_playback_open(snd_pcm_substream_t *substream)
+snd_nm256_playback_open(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
if (snd_nm256_acquire_irq(chip) < 0)
return -EBUSY;
@@ -856,9 +856,9 @@ snd_nm256_playback_open(snd_pcm_substream_t *substream)
}
static int
-snd_nm256_capture_open(snd_pcm_substream_t *substream)
+snd_nm256_capture_open(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
if (snd_nm256_acquire_irq(chip) < 0)
return -EBUSY;
@@ -871,9 +871,9 @@ snd_nm256_capture_open(snd_pcm_substream_t *substream)
* close - we don't have to do special..
*/
static int
-snd_nm256_playback_close(snd_pcm_substream_t *substream)
+snd_nm256_playback_close(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
snd_nm256_release_irq(chip);
return 0;
@@ -881,9 +881,9 @@ snd_nm256_playback_close(snd_pcm_substream_t *substream)
static int
-snd_nm256_capture_close(snd_pcm_substream_t *substream)
+snd_nm256_capture_close(struct snd_pcm_substream *substream)
{
- nm256_t *chip = snd_pcm_substream_chip(substream);
+ struct nm256 *chip = snd_pcm_substream_chip(substream);
snd_nm256_release_irq(chip);
return 0;
@@ -892,7 +892,7 @@ snd_nm256_capture_close(snd_pcm_substream_t *substream)
/*
* create a pcm instance
*/
-static snd_pcm_ops_t snd_nm256_playback_ops = {
+static struct snd_pcm_ops snd_nm256_playback_ops = {
.open = snd_nm256_playback_open,
.close = snd_nm256_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -907,7 +907,7 @@ static snd_pcm_ops_t snd_nm256_playback_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_nm256_capture_ops = {
+static struct snd_pcm_ops snd_nm256_capture_ops = {
.open = snd_nm256_capture_open,
.close = snd_nm256_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -922,13 +922,13 @@ static snd_pcm_ops_t snd_nm256_capture_ops = {
};
static int __devinit
-snd_nm256_pcm(nm256_t *chip, int device)
+snd_nm256_pcm(struct nm256 *chip, int device)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int i, err;
for (i = 0; i < 2; i++) {
- nm256_stream_t *s = &chip->streams[i];
+ struct nm256_stream *s = &chip->streams[i];
s->bufptr = chip->buffer + (s->buf - chip->buffer_start);
s->bufptr_addr = chip->buffer_addr + (s->buf - chip->buffer_start);
}
@@ -953,7 +953,7 @@ snd_nm256_pcm(nm256_t *chip, int device)
* Initialize the hardware.
*/
static void
-snd_nm256_init_chip(nm256_t *chip)
+snd_nm256_init_chip(struct nm256 *chip)
{
/* Reset everything. */
snd_nm256_writeb(chip, 0x0, 0x11);
@@ -965,7 +965,7 @@ snd_nm256_init_chip(nm256_t *chip)
static irqreturn_t
-snd_nm256_intr_check(nm256_t *chip)
+snd_nm256_intr_check(struct nm256 *chip)
{
if (chip->badintrcount++ > 1000) {
/*
@@ -1002,7 +1002,7 @@ snd_nm256_intr_check(nm256_t *chip)
static irqreturn_t
snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
{
- nm256_t *chip = dev_id;
+ struct nm256 *chip = dev_id;
u16 status;
u8 cbyte;
@@ -1067,7 +1067,7 @@ snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
static irqreturn_t
snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
{
- nm256_t *chip = dev_id;
+ struct nm256 *chip = dev_id;
u32 status;
u8 cbyte;
@@ -1131,7 +1131,7 @@ snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
* if it timed out.
*/
static int
-snd_nm256_ac97_ready(nm256_t *chip)
+snd_nm256_ac97_ready(struct nm256 *chip)
{
int timeout = 10;
u32 testaddr;
@@ -1154,9 +1154,9 @@ snd_nm256_ac97_ready(nm256_t *chip)
/*
*/
static unsigned short
-snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg)
+snd_nm256_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
{
- nm256_t *chip = ac97->private_data;
+ struct nm256 *chip = ac97->private_data;
int res;
if (reg >= 128)
@@ -1173,10 +1173,10 @@ snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg)
/*
*/
static void
-snd_nm256_ac97_write(ac97_t *ac97,
+snd_nm256_ac97_write(struct snd_ac97 *ac97,
unsigned short reg, unsigned short val)
{
- nm256_t *chip = ac97->private_data;
+ struct nm256 *chip = ac97->private_data;
int tries = 2;
u32 base;
@@ -1196,9 +1196,9 @@ snd_nm256_ac97_write(ac97_t *ac97,
/* initialize the ac97 into a known state */
static void
-snd_nm256_ac97_reset(ac97_t *ac97)
+snd_nm256_ac97_reset(struct snd_ac97 *ac97)
{
- nm256_t *chip = ac97->private_data;
+ struct nm256 *chip = ac97->private_data;
/* Reset the mixer. 'Tis magic! */
snd_nm256_writeb(chip, 0x6c0, 1);
@@ -1215,12 +1215,12 @@ snd_nm256_ac97_reset(ac97_t *ac97)
/* create an ac97 mixer interface */
static int __devinit
-snd_nm256_mixer(nm256_t *chip)
+snd_nm256_mixer(struct nm256 *chip)
{
- ac97_bus_t *pbus;
- ac97_template_t ac97;
+ struct snd_ac97_bus *pbus;
+ struct snd_ac97_template ac97;
int i, err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.reset = snd_nm256_ac97_reset,
.write = snd_nm256_ac97_write,
.read = snd_nm256_ac97_read,
@@ -1263,7 +1263,7 @@ snd_nm256_mixer(nm256_t *chip)
*/
static int __devinit
-snd_nm256_peek_for_sig(nm256_t *chip)
+snd_nm256_peek_for_sig(struct nm256 *chip)
{
/* The signature is located 1K below the end of video RAM. */
void __iomem *temp;
@@ -1292,7 +1292,8 @@ snd_nm256_peek_for_sig(nm256_t *chip)
return -ENODEV;
} else {
pointer_found = pointer;
- printk(KERN_INFO "nm256: found card signature in video RAM: 0x%x\n", pointer);
+ printk(KERN_INFO "nm256: found card signature in video RAM: 0x%x\n",
+ pointer);
}
}
@@ -1307,31 +1308,36 @@ snd_nm256_peek_for_sig(nm256_t *chip)
* APM event handler, so the card is properly reinitialized after a power
* event.
*/
-static int nm256_suspend(snd_card_t *card, pm_message_t state)
+static int nm256_suspend(struct pci_dev *pci, pm_message_t state)
{
- nm256_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct nm256 *chip = card->private_data;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
snd_ac97_suspend(chip->ac97);
chip->coeffs_current = 0;
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int nm256_resume(snd_card_t *card)
+static int nm256_resume(struct pci_dev *pci)
{
- nm256_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct nm256 *chip = card->private_data;
int i;
/* Perform a full reset on the hardware */
- pci_enable_device(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
snd_nm256_init_chip(chip);
/* restore ac97 */
snd_ac97_resume(chip->ac97);
for (i = 0; i < 2; i++) {
- nm256_stream_t *s = &chip->streams[i];
+ struct nm256_stream *s = &chip->streams[i];
if (s->substream && s->suspended) {
spin_lock_irq(&chip->reg_lock);
snd_nm256_set_format(chip, s, s->substream);
@@ -1339,11 +1345,12 @@ static int nm256_resume(snd_card_t *card)
}
}
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_nm256_free(nm256_t *chip)
+static int snd_nm256_free(struct nm256 *chip)
{
if (chip->streams[SNDRV_PCM_STREAM_PLAYBACK].running)
snd_nm256_playback_stop(chip);
@@ -1360,30 +1367,26 @@ static int snd_nm256_free(nm256_t *chip)
release_and_free_resource(chip->res_cport);
release_and_free_resource(chip->res_buffer);
if (chip->irq >= 0)
- free_irq(chip->irq, (void*)chip);
+ free_irq(chip->irq, chip);
pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
-static int snd_nm256_dev_free(snd_device_t *device)
+static int snd_nm256_dev_free(struct snd_device *device)
{
- nm256_t *chip = device->device_data;
+ struct nm256 *chip = device->device_data;
return snd_nm256_free(chip);
}
static int __devinit
-snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
- int play_bufsize, int capt_bufsize,
- int force_load,
- u32 buffertop,
- int usecache,
- nm256_t **chip_ret)
+snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
+ struct nm256 **chip_ret)
{
- nm256_t *chip;
+ struct nm256 *chip;
int err, pval;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_nm256_dev_free,
};
u32 addr;
@@ -1401,13 +1404,14 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->card = card;
chip->pci = pci;
- chip->use_cache = usecache;
+ chip->use_cache = use_cache;
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;
+ /* store buffer sizes in bytes */
+ chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize = playback_bufsize * 1024;
+ chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize = capture_bufsize * 1024;
/*
* The NM256 has two memory ports. The first port is nothing
@@ -1440,9 +1444,10 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
/* Ok, try to see if this is a non-AC97 version of the hardware. */
pval = snd_nm256_readw(chip, NM_MIXER_PRESENCE);
if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
- if (! force_load) {
+ if (! force_ac97) {
printk(KERN_ERR "nm256: no ac97 is found!\n");
- printk(KERN_ERR " force the driver to load by passing in the module parameter\n");
+ printk(KERN_ERR " force the driver to load by "
+ "passing in the module parameter\n");
printk(KERN_ERR " force_ac97=1\n");
printk(KERN_ERR " or try sb16 or cs423x drivers instead.\n");
err = -ENXIO;
@@ -1465,14 +1470,15 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->mixer_status_mask = NM2_MIXER_READY_MASK;
}
- chip->buffer_size = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize + chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize;
+ chip->buffer_size = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].bufsize +
+ chip->streams[SNDRV_PCM_STREAM_CAPTURE].bufsize;
if (chip->use_cache)
chip->buffer_size += NM_TOTAL_COEFF_COUNT * 4;
else
chip->buffer_size += NM_MAX_PLAYBACK_COEF_SIZE + NM_MAX_RECORD_COEF_SIZE;
- if (buffertop >= chip->buffer_size && buffertop < chip->buffer_end)
- chip->buffer_end = buffertop;
+ if (buffer_top >= chip->buffer_size && buffer_top < chip->buffer_end)
+ chip->buffer_end = buffer_top;
else {
/* get buffer end pointer from signature */
if ((err = snd_nm256_peek_for_sig(chip)) < 0)
@@ -1524,8 +1530,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
// pci_set_master(pci); /* needed? */
- snd_card_set_pm_callback(card, nm256_suspend, nm256_resume, chip);
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
goto __error;
@@ -1564,10 +1568,9 @@ static struct nm256_quirk nm256_quirks[] __devinitdata = {
static int __devinit snd_nm256_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- nm256_t *chip;
+ struct snd_card *card;
+ struct nm256 *chip;
int err;
- unsigned int xbuffer_top;
struct nm256_quirk *q;
u16 subsystem_vendor, subsystem_device;
@@ -1578,7 +1581,8 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
if (q->vendor == subsystem_vendor && q->device == subsystem_device) {
switch (q->type) {
case NM_BLACKLISTED:
- printk(KERN_INFO "nm256: The device is blacklisted. Loading stopped\n");
+ printk(KERN_INFO "nm256: The device is blacklisted. "
+ "Loading stopped\n");
return -ENODEV;
case NM_RESET_WORKAROUND_2:
reset_workaround_2 = 1;
@@ -1611,9 +1615,7 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
}
if (vaio_hack)
- xbuffer_top = 0x25a800; /* this avoids conflicts with XFree86 server */
- else
- xbuffer_top = buffer_top;
+ buffer_top = 0x25a800; /* this avoids conflicts with XFree86 server */
if (playback_bufsize < 4)
playback_bufsize = 4;
@@ -1623,16 +1625,11 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
capture_bufsize = 4;
if (capture_bufsize > 128)
capture_bufsize = 128;
- if ((err = snd_nm256_create(card, pci,
- playback_bufsize * 1024, /* in bytes */
- capture_bufsize * 1024, /* in bytes */
- force_ac97,
- xbuffer_top,
- use_cache,
- &chip)) < 0) {
+ if ((err = snd_nm256_create(card, pci, &chip)) < 0) {
snd_card_free(card);
return err;
}
+ card->private_data = chip;
if (reset_workaround) {
snd_printdd(KERN_INFO "nm256: reset_workaround activated\n");
@@ -1676,7 +1673,10 @@ static struct pci_driver driver = {
.id_table = snd_nm256_ids,
.probe = snd_nm256_probe,
.remove = __devexit_p(snd_nm256_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = nm256_suspend,
+ .resume = nm256_resume,
+#endif
};
diff --git a/sound/pci/pcxhr/Makefile b/sound/pci/pcxhr/Makefile
new file mode 100644
index 000000000000..10473c05918d
--- /dev/null
+++ b/sound/pci/pcxhr/Makefile
@@ -0,0 +1,2 @@
+snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o
+obj-$(CONFIG_SND_PCXHR) += snd-pcxhr.o
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
new file mode 100644
index 000000000000..b8c0853a8278
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -0,0 +1,1367 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * main file with alsa callbacks
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "pcxhr.h"
+#include "pcxhr_mixer.h"
+#include "pcxhr_hwdep.h"
+#include "pcxhr_core.h"
+
+#define DRIVER_NAME "pcxhr"
+
+MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>");
+MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING);
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
+
+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 */
+static int mono[SNDRV_CARDS]; /* capture in mono only */
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Digigram " DRIVER_NAME " soundcard");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Digigram " DRIVER_NAME " soundcard");
+module_param_array(mono, bool, NULL, 0444);
+MODULE_PARM_DESC(mono, "Mono capture mode (default is stereo)");
+
+enum {
+ PCI_ID_VX882HR,
+ PCI_ID_PCX882HR,
+ PCI_ID_VX881HR,
+ PCI_ID_PCX881HR,
+ PCI_ID_PCX1222HR,
+ PCI_ID_PCX1221HR,
+ PCI_ID_LAST
+};
+
+static struct pci_device_id pcxhr_ids[] = {
+ { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, }, /* PCX881HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, /* PCX1222HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, /* PCX1221HR */
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, pcxhr_ids);
+
+struct board_parameters {
+ char* board_name;
+ short playback_chips;
+ short capture_chips;
+ short firmware_num;
+};
+static struct board_parameters pcxhr_board_params[] = {
+[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 41, },
+[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 41, },
+[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 41, },
+[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 41, },
+[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 42, },
+[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 42, },
+};
+
+
+static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
+ unsigned int* realfreq)
+{
+ unsigned int reg;
+
+ if (freq < 6900 || freq > 110250)
+ return -EINVAL;
+ reg = (28224000 * 10) / freq;
+ reg = (reg + 5) / 10;
+ if (reg < 0x200)
+ *pllreg = reg + 0x800;
+ else if (reg < 0x400)
+ *pllreg = reg & 0x1ff;
+ else if (reg < 0x800) {
+ *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
+ reg &= ~1;
+ } else {
+ *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
+ reg &= ~3;
+ }
+ if (realfreq)
+ *realfreq = ((28224000 * 10) / reg + 5) / 10;
+ return 0;
+}
+
+
+#define PCXHR_FREQ_REG_MASK 0x1f
+#define PCXHR_FREQ_QUARTZ_48000 0x00
+#define PCXHR_FREQ_QUARTZ_24000 0x01
+#define PCXHR_FREQ_QUARTZ_12000 0x09
+#define PCXHR_FREQ_QUARTZ_32000 0x08
+#define PCXHR_FREQ_QUARTZ_16000 0x04
+#define PCXHR_FREQ_QUARTZ_8000 0x0c
+#define PCXHR_FREQ_QUARTZ_44100 0x02
+#define PCXHR_FREQ_QUARTZ_22050 0x0a
+#define PCXHR_FREQ_QUARTZ_11025 0x06
+#define PCXHR_FREQ_PLL 0x05
+#define PCXHR_FREQ_QUARTZ_192000 0x10
+#define PCXHR_FREQ_QUARTZ_96000 0x18
+#define PCXHR_FREQ_QUARTZ_176400 0x14
+#define PCXHR_FREQ_QUARTZ_88200 0x1c
+#define PCXHR_FREQ_QUARTZ_128000 0x12
+#define PCXHR_FREQ_QUARTZ_64000 0x1a
+
+#define PCXHR_FREQ_WORD_CLOCK 0x0f
+#define PCXHR_FREQ_SYNC_AES 0x0e
+#define PCXHR_FREQ_AES_1 0x07
+#define PCXHR_FREQ_AES_2 0x0b
+#define PCXHR_FREQ_AES_3 0x03
+#define PCXHR_FREQ_AES_4 0x0d
+
+#define PCXHR_MODIFY_CLOCK_S_BIT 0x04
+
+#define PCXHR_IRQ_TIMER_FREQ 92000
+#define PCXHR_IRQ_TIMER_PERIOD 48
+
+static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
+ unsigned int *reg, unsigned int *freq)
+{
+ unsigned int val, realfreq, pllreg;
+ struct pcxhr_rmh rmh;
+ int err;
+
+ realfreq = rate;
+ switch (mgr->use_clock_type) {
+ case PCXHR_CLOCK_TYPE_INTERNAL : /* clock by quartz or pll */
+ switch (rate) {
+ case 48000 : val = PCXHR_FREQ_QUARTZ_48000; break;
+ case 24000 : val = PCXHR_FREQ_QUARTZ_24000; break;
+ case 12000 : val = PCXHR_FREQ_QUARTZ_12000; break;
+ case 32000 : val = PCXHR_FREQ_QUARTZ_32000; break;
+ case 16000 : val = PCXHR_FREQ_QUARTZ_16000; break;
+ case 8000 : val = PCXHR_FREQ_QUARTZ_8000; break;
+ case 44100 : val = PCXHR_FREQ_QUARTZ_44100; break;
+ case 22050 : val = PCXHR_FREQ_QUARTZ_22050; break;
+ case 11025 : val = PCXHR_FREQ_QUARTZ_11025; break;
+ case 192000 : val = PCXHR_FREQ_QUARTZ_192000; break;
+ case 96000 : val = PCXHR_FREQ_QUARTZ_96000; break;
+ case 176400 : val = PCXHR_FREQ_QUARTZ_176400; break;
+ case 88200 : val = PCXHR_FREQ_QUARTZ_88200; break;
+ case 128000 : val = PCXHR_FREQ_QUARTZ_128000; break;
+ case 64000 : val = PCXHR_FREQ_QUARTZ_64000; break;
+ default :
+ val = PCXHR_FREQ_PLL;
+ /* get the value for the pll register */
+ err = pcxhr_pll_freq_register(rate, &pllreg, &realfreq);
+ if (err)
+ return err;
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd[0] |= IO_NUM_REG_GENCLK;
+ rmh.cmd[1] = pllreg & MASK_DSP_WORD;
+ rmh.cmd[2] = pllreg >> 24;
+ rmh.cmd_len = 3;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err < 0) {
+ snd_printk(KERN_ERR
+ "error CMD_ACCESS_IO_WRITE for PLL register : %x!\n",
+ err );
+ return err;
+ }
+ }
+ break;
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK : val = PCXHR_FREQ_WORD_CLOCK; break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC : val = PCXHR_FREQ_SYNC_AES; break;
+ case PCXHR_CLOCK_TYPE_AES_1 : val = PCXHR_FREQ_AES_1; break;
+ case PCXHR_CLOCK_TYPE_AES_2 : val = PCXHR_FREQ_AES_2; break;
+ case PCXHR_CLOCK_TYPE_AES_3 : val = PCXHR_FREQ_AES_3; break;
+ case PCXHR_CLOCK_TYPE_AES_4 : val = PCXHR_FREQ_AES_4; break;
+ default : return -EINVAL;
+ }
+ *reg = val;
+ *freq = realfreq;
+ return 0;
+}
+
+
+int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
+{
+ unsigned int val, realfreq, speed;
+ struct pcxhr_rmh rmh;
+ int err, changed;
+
+ if (rate == 0)
+ return 0; /* nothing to do */
+
+ err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq);
+ if (err)
+ return err;
+
+ /* codec speed modes */
+ if (rate < 55000)
+ speed = 0; /* single speed */
+ else if (rate < 100000)
+ speed = 1; /* dual speed */
+ else
+ speed = 2; /* quad speed */
+ if (mgr->codec_speed != speed) {
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
+ rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
+ rmh.cmd[0] |= IO_NUM_SPEED_RATIO;
+ rmh.cmd[1] = speed;
+ rmh.cmd_len = 2;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ }
+ /* set the new frequency */
+ snd_printdd("clock register : set %x\n", val);
+ err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, val, &changed);
+ if (err)
+ return err;
+ mgr->sample_rate_real = realfreq;
+ mgr->cur_clock_type = mgr->use_clock_type;
+
+ /* unmute after codec speed modes */
+ if (mgr->codec_speed != speed) {
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
+ rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ mgr->codec_speed = speed; /* save new codec speed */
+ }
+
+ if (changed) {
+ pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK);
+ rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
+ if (rate < PCXHR_IRQ_TIMER_FREQ)
+ rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD;
+ else
+ rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD * 2;
+ rmh.cmd[2] = rate;
+ rmh.cmd_len = 3;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ }
+ snd_printdd("pcxhr_set_clock to %dHz (realfreq=%d)\n", rate, realfreq);
+ return 0;
+}
+
+
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type,
+ int *sample_rate)
+{
+ struct pcxhr_rmh rmh;
+ unsigned char reg;
+ int err, rate;
+
+ switch (clock_type) {
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK : reg = REG_STATUS_WORD_CLOCK; break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC : reg = REG_STATUS_AES_SYNC; break;
+ case PCXHR_CLOCK_TYPE_AES_1 : reg = REG_STATUS_AES_1; break;
+ case PCXHR_CLOCK_TYPE_AES_2 : reg = REG_STATUS_AES_2; break;
+ case PCXHR_CLOCK_TYPE_AES_3 : reg = REG_STATUS_AES_3; break;
+ case PCXHR_CLOCK_TYPE_AES_4 : reg = REG_STATUS_AES_4; break;
+ default : return -EINVAL;
+ }
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
+ rmh.cmd_len = 2;
+ rmh.cmd[0] |= IO_NUM_REG_STATUS;
+ if (mgr->last_reg_stat != reg) {
+ rmh.cmd[1] = reg;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
+ mgr->last_reg_stat = reg;
+ }
+ rmh.cmd[1] = REG_STATUS_CURRENT;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ switch (rmh.stat[1] & 0x0f) {
+ case REG_STATUS_SYNC_32000 : rate = 32000; break;
+ case REG_STATUS_SYNC_44100 : rate = 44100; break;
+ case REG_STATUS_SYNC_48000 : rate = 48000; break;
+ case REG_STATUS_SYNC_64000 : rate = 64000; break;
+ case REG_STATUS_SYNC_88200 : rate = 88200; break;
+ case REG_STATUS_SYNC_96000 : rate = 96000; break;
+ case REG_STATUS_SYNC_128000 : rate = 128000; break;
+ case REG_STATUS_SYNC_176400 : rate = 176400; break;
+ case REG_STATUS_SYNC_192000 : rate = 192000; break;
+ default: rate = 0;
+ }
+ snd_printdd("External clock is at %d Hz\n", rate);
+ *sample_rate = rate;
+ return 0;
+}
+
+
+/*
+ * start or stop playback/capture substream
+ */
+static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
+{
+ int err;
+ struct snd_pcxhr *chip;
+ struct pcxhr_rmh rmh;
+ int stream_mask, start;
+
+ if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN)
+ start = 1;
+ else {
+ if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state CANNOT be stopped\n");
+ return -EINVAL;
+ }
+ start = 0;
+ }
+ if (!stream->substream)
+ return -EINVAL;
+
+ stream->timer_abs_periods = 0;
+ stream->timer_period_frag = 0; /* reset theoretical stream pos */
+ stream->timer_buf_periods = 0;
+ stream->timer_is_synced = 0;
+
+ stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
+
+ pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM);
+ pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
+ stream->pipe->first_audio, 0, stream_mask);
+
+ chip = snd_pcm_substream_chip(stream->substream);
+
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", err);
+ stream->status = start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
+ return err;
+}
+
+#define HEADER_FMT_BASE_LIN 0xfed00000
+#define HEADER_FMT_BASE_FLOAT 0xfad00000
+#define HEADER_FMT_INTEL 0x00008000
+#define HEADER_FMT_24BITS 0x00004000
+#define HEADER_FMT_16BITS 0x00002000
+#define HEADER_FMT_UPTO11 0x00000200
+#define HEADER_FMT_UPTO32 0x00000100
+#define HEADER_FMT_MONO 0x00000080
+
+static int pcxhr_set_format(struct pcxhr_stream *stream)
+{
+ int err, is_capture, sample_rate, stream_num;
+ struct snd_pcxhr *chip;
+ struct pcxhr_rmh rmh;
+ unsigned int header;
+
+ switch (stream->format) {
+ case SNDRV_PCM_FORMAT_U8:
+ header = HEADER_FMT_BASE_LIN;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS | HEADER_FMT_INTEL;
+ break;
+ case SNDRV_PCM_FORMAT_S16_BE:
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS | HEADER_FMT_INTEL;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3BE:
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS;
+ break;
+ case SNDRV_PCM_FORMAT_FLOAT_LE:
+ header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL;
+ break;
+ default:
+ snd_printk(KERN_ERR "error pcxhr_set_format() : unknown format\n");
+ return -EINVAL;
+ }
+ chip = snd_pcm_substream_chip(stream->substream);
+
+ sample_rate = chip->mgr->sample_rate;
+ if (sample_rate <= 32000 && sample_rate !=0) {
+ if (sample_rate <= 11025)
+ header |= HEADER_FMT_UPTO11;
+ else
+ header |= HEADER_FMT_UPTO32;
+ }
+ if (stream->channels == 1)
+ header |= HEADER_FMT_MONO;
+
+ is_capture = stream->pipe->is_capture;
+ stream_num = is_capture ? 0 : stream->substream->number;
+
+ pcxhr_init_rmh(&rmh, is_capture ? CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
+ if (is_capture)
+ rmh.cmd[0] |= 1<<12;
+ rmh.cmd[1] = 0;
+ rmh.cmd[2] = header >> 8;
+ rmh.cmd[3] = (header & 0xff) << 16;
+ rmh.cmd_len = 4;
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err);
+ return err;
+}
+
+static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
+{
+ int err, is_capture, stream_num;
+ struct pcxhr_rmh rmh;
+ struct snd_pcm_substream *subs = stream->substream;
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+
+ is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
+ stream_num = is_capture ? 0 : subs->number;
+
+ snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%x) subs(%d)\n",
+ is_capture ? 'c' : 'p',
+ chip->chip_idx, (void*)subs->runtime->dma_addr,
+ subs->runtime->dma_bytes, subs->number);
+
+ pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
+
+ snd_assert(subs->runtime->dma_bytes < 0x200000); /* max buffer size is 2 MByte */
+ rmh.cmd[1] = subs->runtime->dma_bytes * 8; /* size in bits */
+ rmh.cmd[2] = subs->runtime->dma_addr >> 24; /* most significant byte */
+ rmh.cmd[2] |= 1<<19; /* this is a circular buffer */
+ rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD; /* least 3 significant bytes */
+ rmh.cmd_len = 4;
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ snd_printk(KERN_ERR "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
+ return err;
+}
+
+
+#if 0
+static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream, snd_pcm_uframes_t *sample_count)
+{
+ struct pcxhr_rmh rmh;
+ int err;
+ pcxhr_t *chip = snd_pcm_substream_chip(stream->substream);
+ pcxhr_init_rmh(&rmh, CMD_PIPE_SAMPLE_COUNT);
+ pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, 0, 0,
+ 1<<stream->pipe->first_audio);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err == 0) {
+ *sample_count = ((snd_pcm_uframes_t)rmh.stat[0]) << 24;
+ *sample_count += (snd_pcm_uframes_t)rmh.stat[1];
+ }
+ snd_printdd("PIPE_SAMPLE_COUNT = %lx\n", *sample_count);
+ return err;
+}
+#endif
+
+static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream,
+ struct pcxhr_pipe **pipe)
+{
+ if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN) {
+ *pipe = stream->pipe;
+ return 1;
+ }
+ return 0;
+}
+
+static void pcxhr_trigger_tasklet(unsigned long arg)
+{
+ unsigned long flags;
+ int i, j, err;
+ struct pcxhr_pipe *pipe;
+ struct snd_pcxhr *chip;
+ struct pcxhr_mgr *mgr = (struct pcxhr_mgr*)(arg);
+ int capture_mask = 0;
+ int playback_mask = 0;
+
+#ifdef CONFIG_SND_DEBUG_DETECT
+ struct timeval my_tv1, my_tv2;
+ do_gettimeofday(&my_tv1);
+#endif
+ down(&mgr->setup_mutex);
+
+ /* check the pipes concerned and build pipe_array */
+ for (i = 0; i < mgr->num_cards; i++) {
+ chip = mgr->chip[i];
+ for (j = 0; j < chip->nb_streams_capt; j++) {
+ if (pcxhr_stream_scheduled_get_pipe(&chip->capture_stream[j], &pipe))
+ capture_mask |= (1 << pipe->first_audio);
+ }
+ for (j = 0; j < chip->nb_streams_play; j++) {
+ if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) {
+ playback_mask |= (1 << pipe->first_audio);
+ break; /* add only once, as all playback streams of
+ * one chip use the same pipe
+ */
+ }
+ }
+ }
+ if (capture_mask == 0 && playback_mask == 0) {
+ up(&mgr->setup_mutex);
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : no pipes\n");
+ return;
+ }
+
+ snd_printdd("pcxhr_trigger_tasklet : playback_mask=%x capture_mask=%x\n",
+ playback_mask, capture_mask);
+
+ /* synchronous stop of all the pipes concerned */
+ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
+ if (err) {
+ up(&mgr->setup_mutex);
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n",
+ playback_mask, capture_mask);
+ return;
+ }
+
+ /* unfortunately the dsp lost format and buffer info with the stop pipe */
+ for (i = 0; i < mgr->num_cards; i++) {
+ struct pcxhr_stream *stream;
+ chip = mgr->chip[i];
+ for (j = 0; j < chip->nb_streams_capt; j++) {
+ stream = &chip->capture_stream[j];
+ if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) {
+ err = pcxhr_set_format(stream);
+ err = pcxhr_update_r_buffer(stream);
+ }
+ }
+ for (j = 0; j < chip->nb_streams_play; j++) {
+ stream = &chip->playback_stream[j];
+ if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) {
+ err = pcxhr_set_format(stream);
+ err = pcxhr_update_r_buffer(stream);
+ }
+ }
+ }
+ /* start all the streams */
+ for (i = 0; i < mgr->num_cards; i++) {
+ struct pcxhr_stream *stream;
+ chip = mgr->chip[i];
+ for (j = 0; j < chip->nb_streams_capt; j++) {
+ stream = &chip->capture_stream[j];
+ if (pcxhr_stream_scheduled_get_pipe(stream, &pipe))
+ err = pcxhr_set_stream_state(stream);
+ }
+ for (j = 0; j < chip->nb_streams_play; j++) {
+ stream = &chip->playback_stream[j];
+ if (pcxhr_stream_scheduled_get_pipe(stream, &pipe))
+ err = pcxhr_set_stream_state(stream);
+ }
+ }
+
+ /* synchronous start of all the pipes concerned */
+ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
+ if (err) {
+ up(&mgr->setup_mutex);
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n",
+ playback_mask, capture_mask);
+ return;
+ }
+
+ /* put the streams into the running state now (increment pointer by interrupt) */
+ spin_lock_irqsave(&mgr->lock, flags);
+ for ( i =0; i < mgr->num_cards; i++) {
+ struct pcxhr_stream *stream;
+ chip = mgr->chip[i];
+ for(j = 0; j < chip->nb_streams_capt; j++) {
+ stream = &chip->capture_stream[j];
+ if(stream->status == PCXHR_STREAM_STATUS_STARTED)
+ stream->status = PCXHR_STREAM_STATUS_RUNNING;
+ }
+ for (j = 0; j < chip->nb_streams_play; j++) {
+ stream = &chip->playback_stream[j];
+ if (stream->status == PCXHR_STREAM_STATUS_STARTED) {
+ /* playback will already have advanced ! */
+ stream->timer_period_frag += PCXHR_GRANULARITY;
+ stream->status = PCXHR_STREAM_STATUS_RUNNING;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&mgr->lock, flags);
+
+ up(&mgr->setup_mutex);
+
+#ifdef CONFIG_SND_DEBUG_DETECT
+ do_gettimeofday(&my_tv2);
+ snd_printdd("***TRIGGER TASKLET*** TIME = %ld (err = %x)\n",
+ my_tv2.tv_usec - my_tv1.tv_usec, err);
+#endif
+}
+
+
+/*
+ * trigger callback
+ */
+static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
+{
+ struct pcxhr_stream *stream;
+ struct list_head *pos;
+ struct snd_pcm_substream *s;
+ int i;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ snd_printdd("SNDRV_PCM_TRIGGER_START\n");
+ i = 0;
+ snd_pcm_group_for_each(pos, subs) {
+ s = snd_pcm_group_substream_entry(pos);
+ stream = s->runtime->private_data;
+ stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN;
+ snd_pcm_trigger_done(s, subs);
+ i++;
+ }
+ if (i==1) {
+ snd_printdd("Only one Substream %c %d\n",
+ stream->pipe->is_capture ? 'C' : 'P',
+ stream->pipe->first_audio);
+ if (pcxhr_set_format(stream))
+ return -EINVAL;
+ if (pcxhr_update_r_buffer(stream))
+ return -EINVAL;
+
+ if (pcxhr_set_stream_state(stream))
+ return -EINVAL;
+ stream->status = PCXHR_STREAM_STATUS_RUNNING;
+ } else {
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ tasklet_hi_schedule(&chip->mgr->trigger_taskq);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
+ snd_pcm_group_for_each(pos, subs) {
+ s = snd_pcm_group_substream_entry(pos);
+ stream = s->runtime->private_data;
+ stream->status = PCXHR_STREAM_STATUS_SCHEDULE_STOP;
+ if (pcxhr_set_stream_state(stream))
+ return -EINVAL;
+ snd_pcm_trigger_done(s, subs);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ /* TODO */
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
+{
+ struct pcxhr_rmh rmh;
+ int err;
+
+ pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT);
+ if (start) {
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; /* last dsp time invalid */
+ rmh.cmd[0] |= PCXHR_GRANULARITY;
+ }
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err < 0)
+ snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", err);
+ return err;
+}
+
+/*
+ * prepare callback for all pcms
+ */
+static int pcxhr_prepare(struct snd_pcm_substream *subs)
+{
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ struct pcxhr_mgr *mgr = chip->mgr;
+ /*
+ struct pcxhr_stream *stream = (pcxhr_stream_t*)subs->runtime->private_data;
+ */
+ int err = 0;
+
+ snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
+ subs->runtime->period_size, subs->runtime->periods,
+ subs->runtime->buffer_size);
+
+ /*
+ if(subs->runtime->period_size <= PCXHR_GRANULARITY) {
+ snd_printk(KERN_ERR "pcxhr_prepare : error period_size too small (%x)\n",
+ (unsigned int)subs->runtime->period_size);
+ return -EINVAL;
+ }
+ */
+
+ down(&mgr->setup_mutex);
+
+ do {
+ /* if the stream was stopped before, format and buffer were reset */
+ /*
+ if(stream->status == PCXHR_STREAM_STATUS_STOPPED) {
+ err = pcxhr_set_format(stream);
+ if(err) break;
+ err = pcxhr_update_r_buffer(stream);
+ if(err) break;
+ }
+ */
+
+ /* only the first stream can choose the sample rate */
+ /* the further opened streams will be limited to its frequency (see open) */
+ /* set the clock only once (first stream) */
+ if (mgr->sample_rate == 0) {
+ err = pcxhr_set_clock(mgr, subs->runtime->rate);
+ if (err)
+ break;
+ mgr->sample_rate = subs->runtime->rate;
+
+ err = pcxhr_hardware_timer(mgr, 1); /* start the DSP-timer */
+ }
+ } while(0); /* do only once (so we can use break instead of goto) */
+
+ up(&mgr->setup_mutex);
+
+ return err;
+}
+
+
+/*
+ * HW_PARAMS callback for all pcms
+ */
+static int pcxhr_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw)
+{
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ struct pcxhr_mgr *mgr = chip->mgr;
+ struct pcxhr_stream *stream = subs->runtime->private_data;
+ snd_pcm_format_t format;
+ int err;
+ int channels;
+
+ /* set up channels */
+ channels = params_channels(hw);
+
+ /* set up format for the stream */
+ format = params_format(hw);
+
+ down(&mgr->setup_mutex);
+
+ stream->channels = channels;
+ stream->format = format;
+
+ /* set the format to the board */
+ /*
+ err = pcxhr_set_format(stream);
+ if(err) {
+ up(&mgr->setup_mutex);
+ return err;
+ }
+ */
+ /* allocate buffer */
+ err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
+
+ /*
+ if (err > 0) {
+ err = pcxhr_update_r_buffer(stream);
+ }
+ */
+ up(&mgr->setup_mutex);
+
+ return err;
+}
+
+static int pcxhr_hw_free(struct snd_pcm_substream *subs)
+{
+ snd_pcm_lib_free_pages(subs);
+ return 0;
+}
+
+
+/*
+ * CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
+ */
+static struct snd_pcm_hardware pcxhr_caps =
+{
+ .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+ 0 /*SNDRV_PCM_INFO_PAUSE*/),
+ .formats = ( SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE ),
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = (32*1024),
+ /* 1 byte == 1 frame U8 mono (PCXHR_GRANULARITY is frames!) */
+ .period_bytes_min = (2*PCXHR_GRANULARITY),
+ .period_bytes_max = (16*1024),
+ .periods_min = 2,
+ .periods_max = (32*1024/PCXHR_GRANULARITY),
+};
+
+
+static int pcxhr_open(struct snd_pcm_substream *subs)
+{
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ struct pcxhr_mgr *mgr = chip->mgr;
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct pcxhr_stream *stream;
+ int is_capture;
+
+ down(&mgr->setup_mutex);
+
+ /* copy the struct snd_pcm_hardware struct */
+ runtime->hw = pcxhr_caps;
+
+ if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
+ snd_printdd("pcxhr_open playback chip%d subs%d\n",
+ chip->chip_idx, subs->number);
+ is_capture = 0;
+ stream = &chip->playback_stream[subs->number];
+ } else {
+ snd_printdd("pcxhr_open capture chip%d subs%d\n",
+ chip->chip_idx, subs->number);
+ is_capture = 1;
+ if (mgr->mono_capture)
+ runtime->hw.channels_max = 1;
+ else
+ runtime->hw.channels_min = 2;
+ stream = &chip->capture_stream[subs->number];
+ }
+ if (stream->status != PCXHR_STREAM_STATUS_FREE){
+ /* streams in use */
+ snd_printk(KERN_ERR "pcxhr_open chip%d subs%d in use\n",
+ chip->chip_idx, subs->number);
+ up(&mgr->setup_mutex);
+ return -EBUSY;
+ }
+
+ /* if a sample rate is already used or fixed by external clock,
+ * the stream cannot change
+ */
+ if (mgr->sample_rate)
+ runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
+ else {
+ if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) {
+ int external_rate;
+ if (pcxhr_get_external_clock(mgr, mgr->use_clock_type,
+ &external_rate) ||
+ external_rate == 0) {
+ /* cannot detect the external clock rate */
+ up(&mgr->setup_mutex);
+ return -EBUSY;
+ }
+ runtime->hw.rate_min = runtime->hw.rate_max = external_rate;
+ }
+ }
+
+ stream->status = PCXHR_STREAM_STATUS_OPEN;
+ stream->substream = subs;
+ stream->channels = 0; /* not configured yet */
+
+ runtime->private_data = stream;
+
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
+
+ mgr->ref_count_rate++;
+
+ up(&mgr->setup_mutex);
+ return 0;
+}
+
+
+static int pcxhr_close(struct snd_pcm_substream *subs)
+{
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ struct pcxhr_mgr *mgr = chip->mgr;
+ struct pcxhr_stream *stream = subs->runtime->private_data;
+
+ down(&mgr->setup_mutex);
+
+ snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number);
+
+ /* sample rate released */
+ if (--mgr->ref_count_rate == 0) {
+ mgr->sample_rate = 0; /* the sample rate is no more locked */
+ pcxhr_hardware_timer(mgr, 0); /* stop the DSP-timer */
+ }
+
+ stream->status = PCXHR_STREAM_STATUS_FREE;
+ stream->substream = NULL;
+
+ up(&mgr->setup_mutex);
+
+ return 0;
+}
+
+
+static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
+{
+ unsigned long flags;
+ u_int32_t timer_period_frag;
+ int timer_buf_periods;
+ struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct pcxhr_stream *stream = runtime->private_data;
+
+ spin_lock_irqsave(&chip->mgr->lock, flags);
+
+ /* get the period fragment and the nb of periods in the buffer */
+ timer_period_frag = stream->timer_period_frag;
+ timer_buf_periods = stream->timer_buf_periods;
+
+ spin_unlock_irqrestore(&chip->mgr->lock, flags);
+
+ return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +
+ timer_period_frag);
+}
+
+
+static struct snd_pcm_ops pcxhr_ops = {
+ .open = pcxhr_open,
+ .close = pcxhr_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .prepare = pcxhr_prepare,
+ .hw_params = pcxhr_hw_params,
+ .hw_free = pcxhr_hw_free,
+ .trigger = pcxhr_trigger,
+ .pointer = pcxhr_stream_pointer,
+};
+
+/*
+ */
+int pcxhr_create_pcm(struct snd_pcxhr *chip)
+{
+ int err;
+ struct snd_pcm *pcm;
+ char name[32];
+
+ sprintf(name, "pcxhr %d", chip->chip_idx);
+ if ((err = snd_pcm_new(chip->card, name, 0,
+ chip->nb_streams_play,
+ chip->nb_streams_capt, &pcm)) < 0) {
+ snd_printk(KERN_ERR "cannot create pcm %s\n", name);
+ return err;
+ }
+ pcm->private_data = chip;
+
+ if (chip->nb_streams_play)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcxhr_ops);
+ if (chip->nb_streams_capt)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);
+
+ pcm->info_flags = 0;
+ strcpy(pcm->name, name);
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+ snd_dma_pci_data(chip->mgr->pci),
+ 32*1024, 32*1024);
+ chip->pcm = pcm;
+ return 0;
+}
+
+static int pcxhr_chip_free(struct snd_pcxhr *chip)
+{
+ kfree(chip);
+ return 0;
+}
+
+static int pcxhr_chip_dev_free(struct snd_device *device)
+{
+ struct snd_pcxhr *chip = device->device_data;
+ return pcxhr_chip_free(chip);
+}
+
+
+/*
+ */
+static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, int idx)
+{
+ int err;
+ struct snd_pcxhr *chip;
+ static struct snd_device_ops ops = {
+ .dev_free = pcxhr_chip_dev_free,
+ };
+
+ mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (! chip) {
+ snd_printk(KERN_ERR "cannot allocate chip\n");
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ chip->chip_idx = idx;
+ chip->mgr = mgr;
+
+ if (idx < mgr->playback_chips)
+ /* stereo or mono streams */
+ chip->nb_streams_play = PCXHR_PLAYBACK_STREAMS;
+
+ if (idx < mgr->capture_chips) {
+ if (mgr->mono_capture)
+ chip->nb_streams_capt = 2; /* 2 mono streams (left+right) */
+ else
+ chip->nb_streams_capt = 1; /* or 1 stereo stream */
+ }
+
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
+ pcxhr_chip_free(chip);
+ return err;
+ }
+
+ snd_card_set_dev(card, &mgr->pci->dev);
+
+ return 0;
+}
+
+/* proc interface */
+static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+{
+ struct snd_pcxhr *chip = entry->private_data;
+ struct pcxhr_mgr *mgr = chip->mgr;
+
+ snd_iprintf(buffer, "\n%s\n", mgr->longname);
+
+ /* stats available when embedded DSP is running */
+ if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
+ struct pcxhr_rmh rmh;
+ short ver_maj = (mgr->dsp_version >> 16) & 0xff;
+ short ver_min = (mgr->dsp_version >> 8) & 0xff;
+ short ver_build = mgr->dsp_version & 0xff;
+ snd_iprintf(buffer, "module version %s\n", PCXHR_DRIVER_VERSION_STRING);
+ snd_iprintf(buffer, "dsp version %d.%d.%d\n", ver_maj, ver_min, ver_build);
+ if (mgr->board_has_analog)
+ snd_iprintf(buffer, "analog io available\n");
+ else
+ snd_iprintf(buffer, "digital only board\n");
+
+ /* calc cpu load of the dsp */
+ pcxhr_init_rmh(&rmh, CMD_GET_DSP_RESOURCES);
+ if( ! pcxhr_send_msg(mgr, &rmh) ) {
+ int cur = rmh.stat[0];
+ int ref = rmh.stat[1];
+ if (ref > 0) {
+ if (mgr->sample_rate_real != 0 &&
+ mgr->sample_rate_real != 48000) {
+ ref = (ref * 48000) / mgr->sample_rate_real;
+ if (mgr->sample_rate_real >= PCXHR_IRQ_TIMER_FREQ)
+ ref *= 2;
+ }
+ cur = 100 - (100 * cur) / ref;
+ snd_iprintf(buffer, "cpu load %d%%\n", cur);
+ snd_iprintf(buffer, "buffer pool %d/%d kWords\n",
+ rmh.stat[2], rmh.stat[3]);
+ }
+ }
+ snd_iprintf(buffer, "dma granularity : %d\n", PCXHR_GRANULARITY);
+ snd_iprintf(buffer, "dsp time errors : %d\n", mgr->dsp_time_err);
+ snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",
+ mgr->async_err_pipe_xrun);
+ snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",
+ mgr->async_err_stream_xrun);
+ snd_iprintf(buffer, "dsp async last other error : %x\n",
+ mgr->async_err_other_last);
+ /* debug zone dsp */
+ rmh.cmd[0] = 0x4200 + PCXHR_SIZE_MAX_STATUS;
+ rmh.cmd_len = 1;
+ rmh.stat_len = PCXHR_SIZE_MAX_STATUS;
+ rmh.dsp_stat = 0;
+ rmh.cmd_idx = CMD_LAST_INDEX;
+ if( ! pcxhr_send_msg(mgr, &rmh) ) {
+ int i;
+ for (i = 0; i < rmh.stat_len; i++)
+ snd_iprintf(buffer, "debug[%02d] = %06x\n", i, rmh.stat[i]);
+ }
+ } else
+ snd_iprintf(buffer, "no firmware loaded\n");
+ snd_iprintf(buffer, "\n");
+}
+static void pcxhr_proc_sync(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+{
+ struct snd_pcxhr *chip = entry->private_data;
+ struct pcxhr_mgr *mgr = chip->mgr;
+ static char *texts[7] = {
+ "Internal", "Word", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
+ };
+
+ snd_iprintf(buffer, "\n%s\n", mgr->longname);
+ snd_iprintf(buffer, "Current Sample Clock\t: %s\n", texts[mgr->cur_clock_type]);
+ snd_iprintf(buffer, "Current Sample Rate\t= %d\n", mgr->sample_rate_real);
+
+ /* commands available when embedded DSP is running */
+ if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
+ int i, err, sample_rate;
+ for (i = PCXHR_CLOCK_TYPE_WORD_CLOCK; i< (3 + mgr->capture_chips); i++) {
+ err = pcxhr_get_external_clock(mgr, i, &sample_rate);
+ if (err)
+ break;
+ snd_iprintf(buffer, "%s Clock\t\t= %d\n", texts[i], sample_rate);
+ }
+ } else
+ snd_iprintf(buffer, "no firmware loaded\n");
+ snd_iprintf(buffer, "\n");
+}
+
+static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip)
+{
+ struct snd_info_entry *entry;
+
+ if (! snd_card_proc_new(chip->card, "info", &entry))
+ snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info);
+ if (! snd_card_proc_new(chip->card, "sync", &entry))
+ snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync);
+}
+/* end of proc interface */
+
+/*
+ * release all the cards assigned to a manager instance
+ */
+static int pcxhr_free(struct pcxhr_mgr *mgr)
+{
+ unsigned int i;
+
+ for (i = 0; i < mgr->num_cards; i++) {
+ if (mgr->chip[i])
+ snd_card_free(mgr->chip[i]->card);
+ }
+
+ /* reset board if some firmware was loaded */
+ if(mgr->dsp_loaded) {
+ pcxhr_reset_board(mgr);
+ snd_printdd("reset pcxhr !\n");
+ }
+
+ /* release irq */
+ if (mgr->irq >= 0)
+ free_irq(mgr->irq, mgr);
+
+ pci_release_regions(mgr->pci);
+
+ /* free hostport purgebuffer */
+ if (mgr->hostport.area) {
+ snd_dma_free_pages(&mgr->hostport);
+ mgr->hostport.area = NULL;
+ }
+
+ kfree(mgr->prmh);
+
+ pci_disable_device(mgr->pci);
+ kfree(mgr);
+ return 0;
+}
+
+/*
+ * probe function - creates the card manager
+ */
+static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+ static int dev;
+ struct pcxhr_mgr *mgr;
+ unsigned int i;
+ int err;
+ size_t size;
+ char *card_name;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (! enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ /* enable PCI device */
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+ pci_set_master(pci);
+
+ /* check if we can restrict PCI DMA transfers to 32 bits */
+ if (pci_set_dma_mask(pci, 0xffffffff) < 0) {
+ snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ /* alloc card manager */
+ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+ if (! mgr) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ snd_assert(pci_id->driver_data < PCI_ID_LAST, return -ENODEV);
+ card_name = pcxhr_board_params[pci_id->driver_data].board_name;
+ mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;
+ mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips;
+ mgr->firmware_num = pcxhr_board_params[pci_id->driver_data].firmware_num;
+ mgr->mono_capture = mono[dev];
+
+ /* resource assignment */
+ if ((err = pci_request_regions(pci, card_name)) < 0) {
+ kfree(mgr);
+ pci_disable_device(pci);
+ return err;
+ }
+ for (i = 0; i < 3; i++)
+ mgr->port[i] = pci_resource_start(pci, i);
+
+ mgr->pci = pci;
+ mgr->irq = -1;
+
+ if (request_irq(pci->irq, pcxhr_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ card_name, mgr)) {
+ snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+ pcxhr_free(mgr);
+ return -EBUSY;
+ }
+ mgr->irq = pci->irq;
+
+ sprintf(mgr->shortname, "Digigram %s", card_name);
+ sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", mgr->shortname,
+ mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
+
+ /* ISR spinlock */
+ spin_lock_init(&mgr->lock);
+ spin_lock_init(&mgr->msg_lock);
+
+ /* init setup mutex*/
+ init_MUTEX(&mgr->setup_mutex);
+
+ /* init taslket */
+ tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr);
+ tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, (unsigned long) mgr);
+ mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
+ sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - PCXHR_SIZE_MAX_STATUS),
+ GFP_KERNEL);
+ if (! mgr->prmh) {
+ pcxhr_free(mgr);
+ return -ENOMEM;
+ }
+
+ for (i=0; i < PCXHR_MAX_CARDS; i++) {
+ struct snd_card *card;
+ char tmpid[16];
+ int idx;
+
+ if (i >= max(mgr->playback_chips, mgr->capture_chips))
+ break;
+ mgr->num_cards++;
+
+ if (index[dev] < 0)
+ idx = index[dev];
+ else
+ idx = index[dev] + i;
+
+ snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i);
+ card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
+
+ if (! card) {
+ snd_printk(KERN_ERR "cannot allocate the card %d\n", i);
+ pcxhr_free(mgr);
+ return -ENOMEM;
+ }
+
+ strcpy(card->driver, DRIVER_NAME);
+ sprintf(card->shortname, "%s [PCM #%d]", mgr->shortname, i);
+ sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
+
+ if ((err = pcxhr_create(mgr, card, i)) < 0) {
+ pcxhr_free(mgr);
+ return err;
+ }
+
+ if (i == 0)
+ /* init proc interface only for chip0 */
+ pcxhr_proc_init(mgr->chip[i]);
+
+ if ((err = snd_card_register(card)) < 0) {
+ pcxhr_free(mgr);
+ return err;
+ }
+ }
+
+ /* create hostport purgebuffer */
+ size = PAGE_ALIGN(sizeof(struct pcxhr_hostport));
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, &mgr->hostport) < 0) {
+ pcxhr_free(mgr);
+ return -ENOMEM;
+ }
+ /* init purgebuffer */
+ memset(mgr->hostport.area, 0, size);
+
+ /* create a DSP loader */
+ err = pcxhr_setup_firmware(mgr);
+ if (err < 0) {
+ pcxhr_free(mgr);
+ return err;
+ }
+
+ pci_set_drvdata(pci, mgr);
+ dev++;
+ return 0;
+}
+
+static void __devexit pcxhr_remove(struct pci_dev *pci)
+{
+ pcxhr_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+ .name = "Digigram pcxhr",
+ .id_table = pcxhr_ids,
+ .probe = pcxhr_probe,
+ .remove = __devexit_p(pcxhr_remove),
+};
+
+static int __init pcxhr_module_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit pcxhr_module_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(pcxhr_module_init)
+module_exit(pcxhr_module_exit)
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
new file mode 100644
index 000000000000..049f2b3f2867
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -0,0 +1,188 @@
+/*
+ * Driver for Digigram pcxhr soundcards
+ *
+ * main header file
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 __SOUND_PCXHR_H
+#define __SOUND_PCXHR_H
+
+#include <linux/interrupt.h>
+#include <sound/pcm.h>
+
+#define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */
+#define PCXHR_DRIVER_VERSION_STRING "0.8.4" /* 0.8.4 */
+
+
+#define PCXHR_MAX_CARDS 6
+#define PCXHR_PLAYBACK_STREAMS 4
+
+#define PCXHR_GRANULARITY 96 /* transfer granularity (should be min 96 and multiple of 48) */
+#define PCXHR_GRANULARITY_MIN 96 /* transfer granularity of pipes and the dsp time (MBOX4) */
+
+struct snd_pcxhr;
+struct pcxhr_mgr;
+
+struct pcxhr_stream;
+struct pcxhr_pipe;
+
+enum pcxhr_clock_type {
+ PCXHR_CLOCK_TYPE_INTERNAL = 0,
+ PCXHR_CLOCK_TYPE_WORD_CLOCK,
+ PCXHR_CLOCK_TYPE_AES_SYNC,
+ PCXHR_CLOCK_TYPE_AES_1,
+ PCXHR_CLOCK_TYPE_AES_2,
+ PCXHR_CLOCK_TYPE_AES_3,
+ PCXHR_CLOCK_TYPE_AES_4,
+};
+
+struct pcxhr_mgr {
+ unsigned int num_cards;
+ struct snd_pcxhr *chip[PCXHR_MAX_CARDS];
+
+ struct pci_dev *pci;
+
+ int irq;
+
+ /* card access with 1 mem bar and 2 io bar's */
+ unsigned long port[3];
+
+ /* share the name */
+ char shortname[32]; /* short name of this soundcard */
+ char longname[96]; /* name of this soundcard */
+
+ /* message tasklet */
+ struct tasklet_struct msg_taskq;
+ struct pcxhr_rmh *prmh;
+ /* trigger tasklet */
+ struct tasklet_struct trigger_taskq;
+
+ spinlock_t lock; /* interrupt spinlock */
+ spinlock_t msg_lock; /* message spinlock */
+
+ struct semaphore setup_mutex; /* mutex used in hw_params, open and close */
+ struct semaphore mixer_mutex; /* mutex for mixer */
+
+ /* hardware interface */
+ unsigned int dsp_loaded; /* bit flags of loaded dsp indices */
+ unsigned int dsp_version; /* read from embedded once firmware is loaded */
+ int board_has_analog; /* if 0 the board is digital only */
+ int mono_capture; /* if 1 the board does mono capture */
+ int playback_chips; /* 4 or 6 */
+ int capture_chips; /* 4 or 1 */
+ int firmware_num; /* 41 or 42 */
+
+ struct snd_dma_buffer hostport;
+
+ enum pcxhr_clock_type use_clock_type; /* clock type selected by mixer */
+ enum pcxhr_clock_type cur_clock_type; /* current clock type synced */
+ int sample_rate;
+ int ref_count_rate;
+ int timer_toggle; /* timer interrupt toggles between the two values 0x200 and 0x300 */
+ int dsp_time_last; /* the last dsp time (read by interrupt) */
+ int dsp_time_err; /* dsp time errors */
+ unsigned int src_it_dsp; /* dsp interrupt source */
+ unsigned int io_num_reg_cont; /* backup of IO_NUM_REG_CONT */
+ unsigned int codec_speed; /* speed mode of the codecs */
+ unsigned int sample_rate_real; /* current real sample rate */
+ int last_reg_stat;
+ int async_err_stream_xrun;
+ int async_err_pipe_xrun;
+ int async_err_other_last;
+};
+
+
+enum pcxhr_stream_status {
+ PCXHR_STREAM_STATUS_FREE,
+ PCXHR_STREAM_STATUS_OPEN,
+ PCXHR_STREAM_STATUS_SCHEDULE_RUN,
+ PCXHR_STREAM_STATUS_STARTED,
+ PCXHR_STREAM_STATUS_RUNNING,
+ PCXHR_STREAM_STATUS_SCHEDULE_STOP,
+ PCXHR_STREAM_STATUS_STOPPED,
+ PCXHR_STREAM_STATUS_PAUSED
+};
+
+struct pcxhr_stream {
+ struct snd_pcm_substream *substream;
+ snd_pcm_format_t format;
+ struct pcxhr_pipe *pipe;
+
+ enum pcxhr_stream_status status; /* free, open, running, draining, pause */
+
+ u_int64_t timer_abs_periods; /* timer: samples elapsed since TRIGGER_START (multiple of period_size) */
+ u_int32_t timer_period_frag; /* timer: samples elapsed since last call to snd_pcm_period_elapsed (0..period_size) */
+ u_int32_t timer_buf_periods; /* nb of periods in the buffer that have already elapsed */
+ int timer_is_synced; /* if(0) : timer needs to be resynced with real hardware pointer */
+
+ int channels;
+};
+
+
+enum pcxhr_pipe_status {
+ PCXHR_PIPE_UNDEFINED,
+ PCXHR_PIPE_DEFINED
+};
+
+struct pcxhr_pipe {
+ enum pcxhr_pipe_status status;
+ int is_capture; /* this is a capture pipe */
+ int first_audio; /* first audio num */
+};
+
+
+struct snd_pcxhr {
+ struct snd_card *card;
+ struct pcxhr_mgr *mgr;
+ int chip_idx; /* zero based */
+
+ struct snd_pcm *pcm; /* PCM */
+
+ struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */
+ struct pcxhr_pipe capture_pipe[2]; /* 1 stereo pipe or 2 mono pipes */
+
+ struct pcxhr_stream playback_stream[PCXHR_PLAYBACK_STREAMS];
+ struct pcxhr_stream capture_stream[2]; /* 1 stereo stream or 2 mono streams */
+ int nb_streams_play;
+ int nb_streams_capt;
+
+ int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */
+ int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
+ int analog_capture_volume[2]; /* Mixer : Master Capture Volume */
+ int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Active [streams][stereo]*/
+ int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Volume [streams][stereo]*/
+ int digital_capture_volume[2]; /* Mixer : Digital Capture Volume [stereo] */
+ int monitoring_active[2]; /* Mixer : Monitoring Active */
+ int monitoring_volume[2]; /* Mixer : Monitoring Volume */
+ int audio_capture_source; /* Mixer : Audio Capture Source */
+ unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */
+};
+
+struct pcxhr_hostport
+{
+ char purgebuffer[6];
+ char reserved[2];
+};
+
+/* exported */
+int pcxhr_create_pcm(struct snd_pcxhr *chip);
+int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate);
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type, int *sample_rate);
+
+#endif /* __SOUND_PCXHR_H */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
new file mode 100644
index 000000000000..fa0d27e2c79b
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -0,0 +1,1214 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * low level interface with interrupt and message handling implementation
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 <sound/driver.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include "pcxhr.h"
+#include "pcxhr_mixer.h"
+#include "pcxhr_hwdep.h"
+#include "pcxhr_core.h"
+
+
+/* registers used on the PLX (port 1) */
+#define PCXHR_PLX_OFFSET_MIN 0x40
+#define PCXHR_PLX_MBOX0 0x40
+#define PCXHR_PLX_MBOX1 0x44
+#define PCXHR_PLX_MBOX2 0x48
+#define PCXHR_PLX_MBOX3 0x4C
+#define PCXHR_PLX_MBOX4 0x50
+#define PCXHR_PLX_MBOX5 0x54
+#define PCXHR_PLX_MBOX6 0x58
+#define PCXHR_PLX_MBOX7 0x5C
+#define PCXHR_PLX_L2PCIDB 0x64
+#define PCXHR_PLX_IRQCS 0x68
+#define PCXHR_PLX_CHIPSC 0x6C
+
+/* registers used on the DSP (port 2) */
+#define PCXHR_DSP_ICR 0x00
+#define PCXHR_DSP_CVR 0x04
+#define PCXHR_DSP_ISR 0x08
+#define PCXHR_DSP_IVR 0x0C
+#define PCXHR_DSP_RXH 0x14
+#define PCXHR_DSP_TXH 0x14
+#define PCXHR_DSP_RXM 0x18
+#define PCXHR_DSP_TXM 0x18
+#define PCXHR_DSP_RXL 0x1C
+#define PCXHR_DSP_TXL 0x1C
+#define PCXHR_DSP_RESET 0x20
+#define PCXHR_DSP_OFFSET_MAX 0x20
+
+/* access to the card */
+#define PCXHR_PLX 1
+#define PCXHR_DSP 2
+
+#if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN)
+#undef PCXHR_REG_TO_PORT(x)
+#else
+#define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP)
+#endif
+#define PCXHR_INPB(mgr,x) inb((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x))
+#define PCXHR_INPL(mgr,x) inl((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x))
+#define PCXHR_OUTPB(mgr,x,data) outb((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x))
+#define PCXHR_OUTPL(mgr,x,data) outl((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x))
+/* attention : access the PCXHR_DSP_* registers with inb and outb only ! */
+
+/* params used with PCXHR_PLX_MBOX0 */
+#define PCXHR_MBOX0_HF5 (1 << 0)
+#define PCXHR_MBOX0_HF4 (1 << 1)
+#define PCXHR_MBOX0_BOOT_HERE (1 << 23)
+/* params used with PCXHR_PLX_IRQCS */
+#define PCXHR_IRQCS_ENABLE_PCIIRQ (1 << 8)
+#define PCXHR_IRQCS_ENABLE_PCIDB (1 << 9)
+#define PCXHR_IRQCS_ACTIVE_PCIDB (1 << 13)
+/* params used with PCXHR_PLX_CHIPSC */
+#define PCXHR_CHIPSC_INIT_VALUE 0x100D767E
+#define PCXHR_CHIPSC_RESET_XILINX (1 << 16)
+#define PCXHR_CHIPSC_GPI_USERI (1 << 17)
+#define PCXHR_CHIPSC_DATA_CLK (1 << 24)
+#define PCXHR_CHIPSC_DATA_IN (1 << 26)
+
+/* params used with PCXHR_DSP_ICR */
+#define PCXHR_ICR_HI08_RREQ 0x01
+#define PCXHR_ICR_HI08_TREQ 0x02
+#define PCXHR_ICR_HI08_HDRQ 0x04
+#define PCXHR_ICR_HI08_HF0 0x08
+#define PCXHR_ICR_HI08_HF1 0x10
+#define PCXHR_ICR_HI08_HLEND 0x20
+#define PCXHR_ICR_HI08_INIT 0x80
+/* params used with PCXHR_DSP_CVR */
+#define PCXHR_CVR_HI08_HC 0x80
+/* params used with PCXHR_DSP_ISR */
+#define PCXHR_ISR_HI08_RXDF 0x01
+#define PCXHR_ISR_HI08_TXDE 0x02
+#define PCXHR_ISR_HI08_TRDY 0x04
+#define PCXHR_ISR_HI08_ERR 0x08
+#define PCXHR_ISR_HI08_CHK 0x10
+#define PCXHR_ISR_HI08_HREQ 0x80
+
+
+/* constants used for delay in msec */
+#define PCXHR_WAIT_DEFAULT 2
+#define PCXHR_WAIT_IT 25
+#define PCXHR_WAIT_IT_EXTRA 65
+
+/*
+ * pcxhr_check_reg_bit - wait for the specified bit is set/reset on a register
+ * @reg: register to check
+ * @mask: bit mask
+ * @bit: resultant bit to be checked
+ * @time: time-out of loop in msec
+ *
+ * returns zero if a bit matches, or a negative error code.
+ */
+static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg,
+ unsigned char mask, unsigned char bit, int time,
+ unsigned char* read)
+{
+ int i = 0;
+ unsigned long end_time = jiffies + (time * HZ + 999) / 1000;
+ do {
+ *read = PCXHR_INPB(mgr, reg);
+ if ((*read & mask) == bit) {
+ if (i > 100)
+ snd_printdd("ATTENTION! check_reg(%x) loopcount=%d\n",
+ reg, i);
+ return 0;
+ }
+ i++;
+ } while (time_after_eq(end_time, jiffies));
+ snd_printk(KERN_ERR "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=0x%x\n",
+ reg, mask, *read);
+ return -EIO;
+}
+
+/* constants used with pcxhr_check_reg_bit() */
+#define PCXHR_TIMEOUT_DSP 200
+
+
+#define PCXHR_MASK_EXTRA_INFO 0x0000FE
+#define PCXHR_MASK_IT_HF0 0x000100
+#define PCXHR_MASK_IT_HF1 0x000200
+#define PCXHR_MASK_IT_NO_HF0_HF1 0x000400
+#define PCXHR_MASK_IT_MANAGE_HF5 0x000800
+#define PCXHR_MASK_IT_WAIT 0x010000
+#define PCXHR_MASK_IT_WAIT_EXTRA 0x020000
+
+#define PCXHR_IT_SEND_BYTE_XILINX (0x0000003C | PCXHR_MASK_IT_HF0)
+#define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \
+ PCXHR_MASK_IT_MANAGE_HF5)
+#define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+#define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT_EXTRA)
+#define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+#define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1)
+#define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1)
+#define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1)
+#define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1)
+#define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1)
+
+static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atomic)
+{
+ int err;
+ unsigned char reg;
+
+ if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
+ /* clear hf5 bit */
+ PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0,
+ PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5);
+ }
+ if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) {
+ reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
+ if (itdsp & PCXHR_MASK_IT_HF0)
+ reg |= PCXHR_ICR_HI08_HF0;
+ if (itdsp & PCXHR_MASK_IT_HF1)
+ reg |= PCXHR_ICR_HI08_HF1;
+ PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
+ }
+ reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | PCXHR_CVR_HI08_HC);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg);
+ if (itdsp & PCXHR_MASK_IT_WAIT) {
+ if (atomic)
+ mdelay(PCXHR_WAIT_IT);
+ else
+ msleep(PCXHR_WAIT_IT);
+ }
+ if (itdsp & PCXHR_MASK_IT_WAIT_EXTRA) {
+ if (atomic)
+ mdelay(PCXHR_WAIT_IT_EXTRA);
+ else
+ msleep(PCXHR_WAIT_IT);
+ }
+ /* wait for CVR_HI08_HC == 0 */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0,
+ PCXHR_TIMEOUT_DSP, &reg);
+ if (err) {
+ snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT CVR\n");
+ return err;
+ }
+ if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
+ /* wait for hf5 bit */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,
+ PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &reg);
+ if (err) {
+ snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT HF5\n");
+ return err;
+ }
+ }
+ return 0; /* retry not handled here */
+}
+
+void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr)
+{
+ /* reset second xilinx */
+ PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC,
+ PCXHR_CHIPSC_INIT_VALUE & ~PCXHR_CHIPSC_RESET_XILINX);
+}
+
+static void pcxhr_enable_irq(struct pcxhr_mgr *mgr, int enable)
+{
+ unsigned int reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
+ /* enable/disable interrupts */
+ if (enable)
+ reg |= (PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB);
+ else
+ reg &= ~(PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB);
+ PCXHR_OUTPL(mgr, PCXHR_PLX_IRQCS, reg);
+}
+
+void pcxhr_reset_dsp(struct pcxhr_mgr *mgr)
+{
+ /* disable interrupts */
+ pcxhr_enable_irq(mgr, 0);
+
+ /* let's reset the DSP */
+ PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 0);
+ msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */
+ PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 3);
+ msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */
+
+ /* reset mailbox */
+ PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 0);
+}
+
+void pcxhr_enable_dsp(struct pcxhr_mgr *mgr)
+{
+ /* enable interrupts */
+ pcxhr_enable_irq(mgr, 1);
+}
+
+/*
+ * load the xilinx image
+ */
+int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second)
+{
+ unsigned int i;
+ unsigned int chipsc;
+ unsigned char data;
+ unsigned char mask;
+ unsigned char *image;
+
+ /* test first xilinx */
+ chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
+ if (!second) {
+ if (chipsc & PCXHR_CHIPSC_GPI_USERI) {
+ snd_printdd("no need to load first xilinx\n");
+ return 0; /* first xilinx is already present and cannot be reset */
+ }
+ } else {
+ if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
+ snd_printk(KERN_ERR "error loading first xilinx\n");
+ return -EINVAL;
+ }
+ /* activate second xilinx */
+ chipsc |= PCXHR_CHIPSC_RESET_XILINX;
+ PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
+ msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */
+ }
+ image = xilinx->data;
+ for (i = 0; i < xilinx->size; i++, image++) {
+ data = *image;
+ mask = 0x80;
+ while (mask) {
+ chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN);
+ if (data & mask)
+ chipsc |= PCXHR_CHIPSC_DATA_IN;
+ PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
+ chipsc |= PCXHR_CHIPSC_DATA_CLK;
+ PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
+ mask >>= 1;
+ }
+ /* don't take too much time in this loop... */
+ cond_resched();
+ }
+ chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN);
+ PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
+ /* wait 2 msec (time to boot the xilinx before any access) */
+ msleep( PCXHR_WAIT_DEFAULT );
+ return 0;
+}
+
+/*
+ * send an executable file to the DSP
+ */
+static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp)
+{
+ int err;
+ unsigned int i;
+ unsigned int len;
+ unsigned char *data;
+ unsigned char dummy;
+ /* check the length of boot image */
+ snd_assert(dsp->size > 0, return -EINVAL);
+ snd_assert(dsp->size % 3 == 0, return -EINVAL);
+ snd_assert(dsp->data, return -EINVAL);
+ /* transfert data buffer from PC to DSP */
+ for (i = 0; i < dsp->size; i += 3) {
+ data = dsp->data + i;
+ if (i == 0) {
+ /* test data header consistency */
+ len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]);
+ snd_assert((len==0) || (dsp->size == (len+2)*3), return -EINVAL);
+ }
+ /* wait DSP ready for new transfer */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy);
+ if (err) {
+ snd_printk(KERN_ERR "dsp loading error at position %d\n", i);
+ return err;
+ }
+ /* send host data */
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, data[0]);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, data[1]);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, data[2]);
+
+ /* don't take too much time in this loop... */
+ cond_resched();
+ }
+ /* give some time to boot the DSP */
+ msleep(PCXHR_WAIT_DEFAULT);
+ return 0;
+}
+
+/*
+ * load the eeprom image
+ */
+int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom)
+{
+ int err;
+ unsigned char reg;
+
+ /* init value of the ICR register */
+ reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
+ if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) {
+ /* no need to load the eeprom binary, but init the HI08 interface */
+ PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT);
+ msleep(PCXHR_WAIT_DEFAULT);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
+ msleep(PCXHR_WAIT_DEFAULT);
+ snd_printdd("no need to load eeprom boot\n");
+ return 0;
+ }
+ PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
+
+ err = pcxhr_download_dsp(mgr, eeprom);
+ if (err)
+ return err;
+ /* wait for chk bit */
+ return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &reg);
+}
+
+/*
+ * load the boot image
+ */
+int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot)
+{
+ int err;
+ unsigned int physaddr = mgr->hostport.addr;
+ unsigned char dummy;
+
+ /* send the hostport address to the DSP (only the upper 24 bit !) */
+ snd_assert((physaddr & 0xff) == 0, return -EINVAL);
+ PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX1, (physaddr >> 8));
+
+ err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_BOOT, 0);
+ if (err)
+ return err;
+ /* clear hf5 bit */
+ PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0,
+ PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5);
+
+ err = pcxhr_download_dsp(mgr, boot);
+ if (err)
+ return err;
+ /* wait for hf5 bit */
+ return pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,
+ PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &dummy);
+}
+
+/*
+ * load the final dsp image
+ */
+int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp)
+{
+ int err;
+ unsigned char dummy;
+ err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_BOARD_FUNC, 0);
+ if (err)
+ return err;
+ err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_DSP, 0);
+ if (err)
+ return err;
+ err = pcxhr_download_dsp(mgr, dsp);
+ if (err)
+ return err;
+ /* wait for chk bit */
+ return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy);
+}
+
+
+struct pcxhr_cmd_info {
+ u32 opcode; /* command word */
+ u16 st_length; /* status length */
+ u16 st_type; /* status type (RMH_SSIZE_XXX) */
+};
+
+/* RMH status type */
+enum {
+ RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */
+ RMH_SSIZE_ARG = 1, /* status size given in the LSB byte (used with st_length = 1) */
+ RMH_SSIZE_MASK = 2, /* status size given in bitmask (used with st_length = 1) */
+};
+
+/*
+ * Array of DSP commands
+ */
+static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
+[CMD_VERSION] = { 0x010000, 1, RMH_SSIZE_FIXED },
+[CMD_SUPPORTED] = { 0x020000, 4, RMH_SSIZE_FIXED },
+[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED },
+[CMD_SEND_IRQA] = { 0x070001, 0, RMH_SSIZE_FIXED },
+[CMD_ACCESS_IO_WRITE] = { 0x090000, 1, RMH_SSIZE_ARG },
+[CMD_ACCESS_IO_READ] = { 0x094000, 1, RMH_SSIZE_ARG },
+[CMD_ASYNC] = { 0x0a0000, 1, RMH_SSIZE_ARG },
+[CMD_MODIFY_CLOCK] = { 0x0d0000, 0, RMH_SSIZE_FIXED },
+[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 0, RMH_SSIZE_FIXED },
+[CMD_GET_DSP_RESOURCES] = { 0x100000, 4, RMH_SSIZE_FIXED },
+[CMD_SET_TIMER_INTERRUPT] = { 0x110000, 0, RMH_SSIZE_FIXED },
+[CMD_RES_PIPE] = { 0x400000, 0, RMH_SSIZE_FIXED },
+[CMD_FREE_PIPE] = { 0x410000, 0, RMH_SSIZE_FIXED },
+[CMD_CONF_PIPE] = { 0x422101, 0, RMH_SSIZE_FIXED },
+[CMD_STOP_PIPE] = { 0x470004, 0, RMH_SSIZE_FIXED },
+[CMD_PIPE_SAMPLE_COUNT] = { 0x49a000, 2, RMH_SSIZE_FIXED },
+[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED },
+[CMD_START_STREAM] = { 0x802000, 0, RMH_SSIZE_FIXED },
+[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x822000, 0, RMH_SSIZE_FIXED },
+[CMD_STOP_STREAM] = { 0x832000, 0, RMH_SSIZE_FIXED },
+[CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED },
+[CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED },
+[CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED },
+[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, /* stat_len = nb_streams * 2 */
+[CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED },
+};
+
+#ifdef CONFIG_SND_DEBUG_DETECT
+static char* cmd_names[] = {
+[CMD_VERSION] = "CMD_VERSION",
+[CMD_SUPPORTED] = "CMD_SUPPORTED",
+[CMD_TEST_IT] = "CMD_TEST_IT",
+[CMD_SEND_IRQA] = "CMD_SEND_IRQA",
+[CMD_ACCESS_IO_WRITE] = "CMD_ACCESS_IO_WRITE",
+[CMD_ACCESS_IO_READ] = "CMD_ACCESS_IO_READ",
+[CMD_ASYNC] = "CMD_ASYNC",
+[CMD_MODIFY_CLOCK] = "CMD_MODIFY_CLOCK",
+[CMD_RESYNC_AUDIO_INPUTS] = "CMD_RESYNC_AUDIO_INPUTS",
+[CMD_GET_DSP_RESOURCES] = "CMD_GET_DSP_RESOURCES",
+[CMD_SET_TIMER_INTERRUPT] = "CMD_SET_TIMER_INTERRUPT",
+[CMD_RES_PIPE] = "CMD_RES_PIPE",
+[CMD_FREE_PIPE] = "CMD_FREE_PIPE",
+[CMD_CONF_PIPE] = "CMD_CONF_PIPE",
+[CMD_STOP_PIPE] = "CMD_STOP_PIPE",
+[CMD_PIPE_SAMPLE_COUNT] = "CMD_PIPE_SAMPLE_COUNT",
+[CMD_CAN_START_PIPE] = "CMD_CAN_START_PIPE",
+[CMD_START_STREAM] = "CMD_START_STREAM",
+[CMD_STREAM_OUT_LEVEL_ADJUST] = "CMD_STREAM_OUT_LEVEL_ADJUST",
+[CMD_STOP_STREAM] = "CMD_STOP_STREAM",
+[CMD_UPDATE_R_BUFFERS] = "CMD_UPDATE_R_BUFFERS",
+[CMD_FORMAT_STREAM_OUT] = "CMD_FORMAT_STREAM_OUT",
+[CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN",
+[CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT",
+[CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST",
+};
+#endif
+
+
+static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
+{
+ int err;
+ int i;
+ u32 data;
+ u32 size_mask;
+ unsigned char reg;
+ int max_stat_len;
+
+ if (rmh->stat_len < PCXHR_SIZE_MAX_STATUS)
+ max_stat_len = PCXHR_SIZE_MAX_STATUS;
+ else max_stat_len = rmh->stat_len;
+
+ for (i = 0; i < rmh->stat_len; i++) {
+ /* wait for receiver full */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+ if (err) {
+ snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n",
+ reg, i);
+ return err;
+ }
+ /* read data */
+ data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;
+ data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;
+ data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
+
+ /* need to update rmh->stat_len on the fly ?? */
+ if (i==0) {
+ if (rmh->dsp_stat != RMH_SSIZE_FIXED) {
+ if (rmh->dsp_stat == RMH_SSIZE_ARG) {
+ rmh->stat_len = (u16)(data & 0x0000ff) + 1;
+ data &= 0xffff00;
+ } else {
+ /* rmh->dsp_stat == RMH_SSIZE_MASK */
+ rmh->stat_len = 1;
+ size_mask = data;
+ while (size_mask) {
+ if (size_mask & 1)
+ rmh->stat_len++;
+ size_mask >>= 1;
+ }
+ }
+ }
+ }
+#ifdef CONFIG_SND_DEBUG_DETECT
+ if (rmh->cmd_idx < CMD_LAST_INDEX)
+ snd_printdd(" stat[%d]=%x\n", i, data);
+#endif
+ if (i < max_stat_len)
+ rmh->stat[i] = data;
+ }
+ if (rmh->stat_len > max_stat_len) {
+ snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len);
+ rmh->stat_len = max_stat_len;
+ }
+ return 0;
+}
+
+static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
+{
+ int err;
+ int i;
+ u32 data;
+ unsigned char reg;
+
+ snd_assert(rmh->cmd_len<PCXHR_SIZE_MAX_CMD, return -EINVAL);
+ err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1);
+ if (err) {
+ snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n");
+ return err;
+ }
+ /* wait for chk bit */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+ /* reset irq chk */
+ err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_CHK, 1);
+ if (err)
+ return err;
+ /* wait for chk bit == 0*/
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 0,
+ PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+
+ data = rmh->cmd[0];
+
+ if (rmh->cmd_len > 1)
+ data |= 0x008000; /* MASK_MORE_THAN_1_WORD_COMMAND */
+ else
+ data &= 0xff7fff; /* MASK_1_WORD_COMMAND */
+#ifdef CONFIG_SND_DEBUG_DETECT
+ if (rmh->cmd_idx < CMD_LAST_INDEX)
+ snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
+#endif
+
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));
+
+ if (rmh->cmd_len > 1) {
+ /* send length */
+ data = rmh->cmd_len - 1;
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));
+
+ for (i=1; i < rmh->cmd_len; i++) {
+ /* send other words */
+ data = rmh->cmd[i];
+#ifdef CONFIG_SND_DEBUG_DETECT
+ if (rmh->cmd_idx < CMD_LAST_INDEX)
+ snd_printdd(" cmd[%d]=%x\n", i, data);
+#endif
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY,
+ PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);
+ PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));
+ }
+ }
+ /* wait for chk bit */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &reg);
+ if (err)
+ return err;
+ /* test status ISR */
+ if (reg & PCXHR_ISR_HI08_ERR) {
+ /* ERROR, wait for receiver full */
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+ if (err) {
+ snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg);
+ return err;
+ }
+ /* read error code */
+ data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;
+ data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;
+ data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
+ snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data);
+ err = -EINVAL;
+ } else {
+ /* read the response data */
+ err = pcxhr_read_rmh_status(mgr, rmh);
+ }
+ /* reset semaphore */
+ if (pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_SEMAPHORE, 1) < 0)
+ return -EIO;
+ return err;
+}
+
+
+/**
+ * pcxhr_init_rmh - initialize the RMH instance
+ * @rmh: the rmh pointer to be initialized
+ * @cmd: the rmh command to be set
+ */
+void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd)
+{
+ snd_assert(cmd < CMD_LAST_INDEX, return);
+ rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode;
+ rmh->cmd_len = 1;
+ rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length;
+ rmh->dsp_stat = pcxhr_dsp_cmds[cmd].st_type;
+ rmh->cmd_idx = cmd;
+}
+
+
+void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,
+ unsigned int param1, unsigned int param2,
+ unsigned int param3)
+{
+ snd_assert(param1 <= MASK_FIRST_FIELD);
+ if (capture)
+ rmh->cmd[0] |= 0x800; /* COMMAND_RECORD_MASK */
+ if (param1)
+ rmh->cmd[0] |= (param1 << FIELD_SIZE);
+ if (param2) {
+ snd_assert(param2 <= MASK_FIRST_FIELD);
+ rmh->cmd[0] |= param2;
+ }
+ if(param3) {
+ snd_assert(param3 <= MASK_DSP_WORD);
+ rmh->cmd[1] = param3;
+ rmh->cmd_len = 2;
+ }
+}
+
+/*
+ * pcxhr_send_msg - send a DSP message with spinlock
+ * @rmh: the rmh record to send and receive
+ *
+ * returns 0 if successful, or a negative error code.
+ */
+int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
+{
+ unsigned long flags;
+ int err;
+ spin_lock_irqsave(&mgr->msg_lock, flags);
+ err = pcxhr_send_msg_nolock(mgr, rmh);
+ spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ return err;
+}
+
+static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
+{
+ int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2);
+ /* least segnificant 12 bits are the pipe states for the playback audios */
+ /* next 12 bits are the pipe states for the capture audios
+ * (PCXHR_PIPE_STATE_CAPTURE_OFFSET)
+ */
+ start_mask &= 0xffffff;
+ snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask);
+ return start_mask;
+}
+
+#define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12
+#define MAX_WAIT_FOR_DSP 20
+
+static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry)
+{
+ struct pcxhr_rmh rmh;
+ int err;
+ int audio = 0;
+
+ *retry = 0;
+ while (audio_mask) {
+ if (audio_mask & 1) {
+ pcxhr_init_rmh(&rmh, CMD_CAN_START_PIPE);
+ if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) {
+ /* can start playback pipe */
+ pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0);
+ } else {
+ /* can start capture pipe */
+ pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
+ }
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err) {
+ snd_printk(KERN_ERR
+ "error pipe start (CMD_CAN_START_PIPE) err=%x!\n",
+ err);
+ return err;
+ }
+ /* if the pipe couldn't be prepaired for start, retry it later */
+ if (rmh.stat[0] == 0)
+ *retry |= (1<<audio);
+ }
+ audio_mask>>=1;
+ audio++;
+ }
+ return 0;
+}
+
+static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask)
+{
+ struct pcxhr_rmh rmh;
+ int err;
+ int audio = 0;
+
+ while (audio_mask) {
+ if (audio_mask & 1) {
+ pcxhr_init_rmh(&rmh, CMD_STOP_PIPE);
+ if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) {
+ /* stop playback pipe */
+ pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0);
+ } else {
+ /* stop capture pipe */
+ pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
+ }
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err) {
+ snd_printk(KERN_ERR
+ "error pipe stop (CMD_STOP_PIPE) err=%x!\n",
+ err);
+ return err;
+ }
+ }
+ audio_mask>>=1;
+ audio++;
+ }
+ return 0;
+}
+
+static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
+{
+ struct pcxhr_rmh rmh;
+ int err;
+ int audio = 0;
+
+ while (audio_mask) {
+ if (audio_mask & 1) {
+ pcxhr_init_rmh(&rmh, CMD_CONF_PIPE);
+ if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET)
+ pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 1 << audio);
+ else
+ pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0,
+ 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET));
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err) {
+ snd_printk(KERN_ERR
+ "error pipe start (CMD_CONF_PIPE) err=%x!\n",
+ err);
+ return err;
+ }
+ }
+ audio_mask>>=1;
+ audio++;
+ }
+ /* now fire the interrupt on the card */
+ pcxhr_init_rmh(&rmh, CMD_SEND_IRQA);
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err) {
+ snd_printk(KERN_ERR "error pipe start (CMD_SEND_IRQA) err=%x!\n", err );
+ return err;
+ }
+ return 0;
+}
+
+
+
+int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start)
+{
+ int state, i, err;
+ int audio_mask;
+
+#ifdef CONFIG_SND_DEBUG_DETECT
+ struct timeval my_tv1, my_tv2;
+ do_gettimeofday(&my_tv1);
+#endif
+ audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
+ /* current pipe state (playback + record) */
+ state = pcxhr_pipes_running(mgr);
+ snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n",
+ start ? "START" : "STOP", audio_mask, state);
+ if (start) {
+ audio_mask &= ~state; /* start only pipes that are not yet started */
+ state = audio_mask;
+ for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
+ err = pcxhr_prepair_pipe_start(mgr, state, &state);
+ if (err)
+ return err;
+ if (state == 0)
+ break; /* success, all pipes prepaired for start */
+ mdelay(1); /* otherwise wait 1 millisecond and retry */
+ }
+ } else {
+ audio_mask &= state; /* stop only pipes that are started */
+ }
+ if (audio_mask == 0)
+ return 0;
+
+ err = pcxhr_toggle_pipes(mgr, audio_mask);
+ if (err)
+ return err;
+
+ i = 0;
+ while (1) {
+ state = pcxhr_pipes_running(mgr);
+ /* have all pipes the new state ? */
+ if ((state & audio_mask) == (start ? audio_mask : 0))
+ break;
+ if (++i >= MAX_WAIT_FOR_DSP * 100) {
+ snd_printk(KERN_ERR "error pipe start/stop (ED_NO_RESPONSE_AT_IRQA)\n");
+ return -EBUSY;
+ }
+ udelay(10); /* wait 10 microseconds */
+ }
+ if (!start) {
+ err = pcxhr_stop_pipes(mgr, audio_mask);
+ if (err)
+ return err;
+ }
+#ifdef CONFIG_SND_DEBUG_DETECT
+ do_gettimeofday(&my_tv2);
+ snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n",
+ my_tv2.tv_usec - my_tv1.tv_usec, err);
+#endif
+ return 0;
+}
+
+int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
+ unsigned int value, int *changed)
+{
+ struct pcxhr_rmh rmh;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&mgr->msg_lock, flags);
+ if ((mgr->io_num_reg_cont & mask) == value) {
+ snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value);
+ if (changed)
+ *changed = 0;
+ spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ return 0; /* already programmed */
+ }
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd[0] |= IO_NUM_REG_CONT;
+ rmh.cmd[1] = mask;
+ rmh.cmd[2] = value;
+ rmh.cmd_len = 3;
+ err = pcxhr_send_msg_nolock(mgr, &rmh);
+ if (err == 0) {
+ mgr->io_num_reg_cont &= ~mask;
+ mgr->io_num_reg_cont |= value;
+ if (changed)
+ *changed = 1;
+ }
+ spin_unlock_irqrestore(&mgr->msg_lock, flags);
+ return err;
+}
+
+#define PCXHR_IRQ_TIMER 0x000300
+#define PCXHR_IRQ_FREQ_CHANGE 0x000800
+#define PCXHR_IRQ_TIME_CODE 0x001000
+#define PCXHR_IRQ_NOTIFY 0x002000
+#define PCXHR_IRQ_ASYNC 0x008000
+#define PCXHR_IRQ_MASK 0x00bb00
+#define PCXHR_FATAL_DSP_ERR 0xff0000
+
+enum pcxhr_async_err_src {
+ PCXHR_ERR_PIPE,
+ PCXHR_ERR_STREAM,
+ PCXHR_ERR_AUDIO
+};
+
+static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
+ enum pcxhr_async_err_src err_src, int pipe,
+ int is_capture)
+{
+#ifdef CONFIG_SND_DEBUG_DETECT
+ static char* err_src_name[] = {
+ [PCXHR_ERR_PIPE] = "Pipe",
+ [PCXHR_ERR_STREAM] = "Stream",
+ [PCXHR_ERR_AUDIO] = "Audio"
+ };
+#endif
+ if (err & 0xfff)
+ err &= 0xfff;
+ else
+ err = ((err >> 12) & 0xfff);
+ if (!err)
+ return 0;
+ snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src],
+ is_capture ? "Record" : "Play", pipe, err);
+ if (err == 0xe01)
+ mgr->async_err_stream_xrun++;
+ else if (err == 0xe10)
+ mgr->async_err_pipe_xrun++;
+ else
+ mgr->async_err_other_last = (int)err;
+ return 1;
+}
+
+
+void pcxhr_msg_tasklet(unsigned long arg)
+{
+ struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg);
+ struct pcxhr_rmh *prmh = mgr->prmh;
+ int err;
+ int i, j;
+
+ if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE)
+ snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occured\n");
+ if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE)
+ snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n");
+ if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
+ snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n");
+ if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
+ snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n");
+
+ pcxhr_init_rmh(prmh, CMD_ASYNC);
+ prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */
+ /* this is the only one extra long response command */
+ prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
+ err = pcxhr_send_msg(mgr, prmh);
+ if (err)
+ snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", err);
+ i = 1;
+ while (i < prmh->stat_len) {
+ int nb_audio = (prmh->stat[i] >> FIELD_SIZE) & MASK_FIRST_FIELD;
+ int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
+ int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
+ int is_capture = prmh->stat[i] & 0x400000;
+ u32 err;
+
+ if (prmh->stat[i] & 0x800000) { /* if BIT_END */
+ snd_printdd("TASKLET : End%sPipe %d\n",
+ is_capture ? "Record" : "Play", pipe);
+ }
+ i++;
+ err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+ if (err)
+ pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE,
+ pipe, is_capture);
+ i += 2;
+ for (j = 0; j < nb_stream; j++) {
+ err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+ if (err)
+ pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM,
+ pipe, is_capture);
+ i += 2;
+ }
+ for (j = 0; j < nb_audio; j++) {
+ err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
+ if (err)
+ pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO,
+ pipe, is_capture);
+ i += 2;
+ }
+ }
+ }
+}
+
+static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr,
+ struct pcxhr_stream *stream)
+{
+ u_int64_t hw_sample_count;
+ struct pcxhr_rmh rmh;
+ int err, stream_mask;
+
+ stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
+
+ /* get sample count for one stream */
+ pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
+ pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
+ stream->pipe->first_audio, 0, stream_mask);
+ /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
+
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return 0;
+
+ hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24;
+ hw_sample_count += (u_int64_t)rmh.stat[1];
+
+ snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n",
+ stream->pipe->is_capture ? 'C':'P', stream->substream->number,
+ (long unsigned int)hw_sample_count,
+ (long unsigned int)(stream->timer_abs_periods +
+ stream->timer_period_frag + PCXHR_GRANULARITY));
+
+ return hw_sample_count;
+}
+
+static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
+ struct pcxhr_stream *stream, int samples_to_add)
+{
+ if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
+ u_int64_t new_sample_count;
+ int elapsed = 0;
+ int hardware_read = 0;
+ struct snd_pcm_runtime *runtime = stream->substream->runtime;
+
+ if (samples_to_add < 0) {
+ stream->timer_is_synced = 0;
+ /* add default if no hardware_read possible */
+ samples_to_add = PCXHR_GRANULARITY;
+ }
+
+ if (!stream->timer_is_synced) {
+ if (stream->timer_abs_periods != 0 ||
+ stream->timer_period_frag + PCXHR_GRANULARITY >=
+ runtime->period_size) {
+ new_sample_count = pcxhr_stream_read_position(mgr, stream);
+ hardware_read = 1;
+ if (new_sample_count >= PCXHR_GRANULARITY_MIN) {
+ /* sub security offset because of jitter and
+ * finer granularity of dsp time (MBOX4)
+ */
+ new_sample_count -= PCXHR_GRANULARITY_MIN;
+ stream->timer_is_synced = 1;
+ }
+ }
+ }
+ if (!hardware_read) {
+ /* if we didn't try to sync the position, increment it
+ * by PCXHR_GRANULARITY every timer interrupt
+ */
+ new_sample_count = stream->timer_abs_periods +
+ stream->timer_period_frag + samples_to_add;
+ }
+ while (1) {
+ u_int64_t new_elapse_pos = stream->timer_abs_periods +
+ runtime->period_size;
+ if (new_elapse_pos > new_sample_count)
+ break;
+ elapsed = 1;
+ stream->timer_buf_periods++;
+ if (stream->timer_buf_periods >= runtime->periods)
+ stream->timer_buf_periods = 0;
+ stream->timer_abs_periods = new_elapse_pos;
+ }
+ if (new_sample_count >= stream->timer_abs_periods)
+ stream->timer_period_frag = (u_int32_t)(new_sample_count -
+ stream->timer_abs_periods);
+ else
+ snd_printk(KERN_ERR "ERROR new_sample_count too small ??? %lx\n",
+ (long unsigned int)new_sample_count);
+
+ if (elapsed) {
+ spin_unlock(&mgr->lock);
+ snd_pcm_period_elapsed(stream->substream);
+ spin_lock(&mgr->lock);
+ }
+ }
+}
+
+
+irqreturn_t pcxhr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct pcxhr_mgr *mgr = dev_id;
+ unsigned int reg;
+ int i, j;
+ struct snd_pcxhr *chip;
+
+ spin_lock(&mgr->lock);
+
+ reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
+ if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
+ spin_unlock(&mgr->lock);
+ return IRQ_NONE; /* this device did not cause the interrupt */
+ }
+
+ /* clear interrupt */
+ reg = PCXHR_INPL(mgr, PCXHR_PLX_L2PCIDB);
+ PCXHR_OUTPL(mgr, PCXHR_PLX_L2PCIDB, reg);
+
+ /* timer irq occured */
+ if (reg & PCXHR_IRQ_TIMER) {
+ int timer_toggle = reg & PCXHR_IRQ_TIMER;
+ /* is a 24 bit counter */
+ int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
+ int dsp_time_diff = dsp_time_new - mgr->dsp_time_last;
+
+ if (dsp_time_diff < 0 && mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID) {
+ snd_printdd("ERROR DSP TIME old(%d) new(%d) -> "
+ "resynchronize all streams\n",
+ mgr->dsp_time_last, dsp_time_new);
+ mgr->dsp_time_err++;
+ }
+#ifdef CONFIG_SND_DEBUG_DETECT
+ if (dsp_time_diff == 0)
+ snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
+ else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
+ snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n",
+ mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last);
+#endif
+ mgr->dsp_time_last = dsp_time_new;
+
+ if (timer_toggle == mgr->timer_toggle)
+ snd_printk(KERN_ERR "ERROR TIMER TOGGLE\n");
+ mgr->timer_toggle = timer_toggle;
+
+ reg &= ~PCXHR_IRQ_TIMER;
+ for (i = 0; i < mgr->num_cards; i++) {
+ chip = mgr->chip[i];
+ for (j = 0; j < chip->nb_streams_capt; j++)
+ pcxhr_update_timer_pos(mgr, &chip->capture_stream[j],
+ dsp_time_diff);
+ }
+ for (i = 0; i < mgr->num_cards; i++) {
+ chip = mgr->chip[i];
+ for (j = 0; j < chip->nb_streams_play; j++)
+ pcxhr_update_timer_pos(mgr, &chip->playback_stream[j],
+ dsp_time_diff);
+ }
+ }
+ /* other irq's handled in the tasklet */
+ if (reg & PCXHR_IRQ_MASK) {
+
+ /* as we didn't request any notifications, some kind of xrun error
+ * will probably occured
+ */
+ /* better resynchronize all streams next interrupt : */
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+
+ mgr->src_it_dsp = reg;
+ tasklet_hi_schedule(&mgr->msg_taskq);
+ }
+#ifdef CONFIG_SND_DEBUG_DETECT
+ if (reg & PCXHR_FATAL_DSP_ERR)
+ snd_printdd("FATAL DSP ERROR : %x\n", reg);
+#endif
+ spin_unlock(&mgr->lock);
+ return IRQ_HANDLED; /* this device caused the interrupt */
+}
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
new file mode 100644
index 000000000000..e7415d6d1826
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -0,0 +1,200 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * low level interface with interrupt ans message handling
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 __SOUND_PCXHR_CORE_H
+#define __SOUND_PCXHR_CORE_H
+
+struct firmware;
+struct pcxhr_mgr;
+
+/* init and firmware download commands */
+void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr);
+void pcxhr_reset_dsp(struct pcxhr_mgr *mgr);
+void pcxhr_enable_dsp(struct pcxhr_mgr *mgr);
+int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second);
+int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom);
+int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot);
+int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp);
+
+/* DSP time available on MailBox4 register : 24 bit time samples() */
+#define PCXHR_DSP_TIME_MASK 0x00ffffff
+#define PCXHR_DSP_TIME_INVALID 0x10000000
+
+
+#define PCXHR_SIZE_MAX_CMD 8
+#define PCXHR_SIZE_MAX_STATUS 16
+#define PCXHR_SIZE_MAX_LONG_STATUS 256
+
+struct pcxhr_rmh {
+ u16 cmd_len; /* length of the command to send (WORDs) */
+ u16 stat_len; /* length of the status received (WORDs) */
+ u16 dsp_stat; /* status type, RMP_SSIZE_XXX */
+ u16 cmd_idx; /* index of the command */
+ u32 cmd[PCXHR_SIZE_MAX_CMD];
+ u32 stat[PCXHR_SIZE_MAX_STATUS];
+};
+
+enum {
+ CMD_VERSION, /* cmd_len = 2 stat_len = 1 */
+ CMD_SUPPORTED, /* cmd_len = 1 stat_len = 4 */
+ CMD_TEST_IT, /* cmd_len = 1 stat_len = 1 */
+ CMD_SEND_IRQA, /* cmd_len = 1 stat_len = 0 */
+ CMD_ACCESS_IO_WRITE, /* cmd_len >= 1 stat_len >= 1 */
+ CMD_ACCESS_IO_READ, /* cmd_len >= 1 stat_len >= 1 */
+ CMD_ASYNC, /* cmd_len = 1 stat_len = 1 */
+ CMD_MODIFY_CLOCK, /* cmd_len = 3 stat_len = 0 */
+ CMD_RESYNC_AUDIO_INPUTS, /* cmd_len = 1 stat_len = 0 */
+ CMD_GET_DSP_RESOURCES, /* cmd_len = 1 stat_len = 4 */
+ CMD_SET_TIMER_INTERRUPT, /* cmd_len = 1 stat_len = 0 */
+ CMD_RES_PIPE, /* cmd_len = 2 stat_len = 0 */
+ CMD_FREE_PIPE, /* cmd_len = 1 stat_len = 0 */
+ CMD_CONF_PIPE, /* cmd_len = 2 stat_len = 0 */
+ CMD_STOP_PIPE, /* cmd_len = 1 stat_len = 0 */
+ CMD_PIPE_SAMPLE_COUNT, /* cmd_len = 2 stat_len = 2 */
+ CMD_CAN_START_PIPE, /* cmd_len >= 1 stat_len = 1 */
+ CMD_START_STREAM, /* cmd_len = 2 stat_len = 0 */
+ CMD_STREAM_OUT_LEVEL_ADJUST, /* cmd_len >= 1 stat_len = 0 */
+ CMD_STOP_STREAM, /* cmd_len = 2 stat_len = 0 */
+ CMD_UPDATE_R_BUFFERS, /* cmd_len = 4 stat_len = 0 */
+ CMD_FORMAT_STREAM_OUT, /* cmd_len >= 2 stat_len = 0 */
+ CMD_FORMAT_STREAM_IN, /* cmd_len >= 4 stat_len = 0 */
+ CMD_STREAM_SAMPLE_COUNT, /* cmd_len = 2 stat_len = (2 * nb_stream) */
+ CMD_AUDIO_LEVEL_ADJUST, /* cmd_len = 3 stat_len = 0 */
+ CMD_LAST_INDEX
+};
+
+#define MASK_DSP_WORD 0x00ffffff
+#define MASK_ALL_STREAM 0x00ffffff
+#define MASK_DSP_WORD_LEVEL 0x000001ff
+#define MASK_FIRST_FIELD 0x0000001f
+#define FIELD_SIZE 5
+
+/*
+ init the rmh struct; by default cmd_len is set to 1
+ */
+void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd);
+
+void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh* rmh, int capture, unsigned int param1,
+ unsigned int param2, unsigned int param3);
+
+/*
+ send the rmh
+ */
+int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh);
+
+
+/* values used for CMD_ACCESS_IO_WRITE and CMD_ACCESS_IO_READ */
+#define IO_NUM_REG_CONT 0
+#define IO_NUM_REG_GENCLK 1
+#define IO_NUM_REG_MUTE_OUT 2
+#define IO_NUM_SPEED_RATIO 4
+#define IO_NUM_REG_STATUS 5
+#define IO_NUM_REG_CUER 10
+#define IO_NUM_UER_CHIP_REG 11
+#define IO_NUM_REG_OUT_ANA_LEVEL 20
+#define IO_NUM_REG_IN_ANA_LEVEL 21
+
+
+#define REG_CONT_UNMUTE_INPUTS 0x020000
+
+/* parameters used with register IO_NUM_REG_STATUS */
+#define REG_STATUS_OPTIONS 0
+#define REG_STATUS_AES_SYNC 8
+#define REG_STATUS_AES_1 9
+#define REG_STATUS_AES_2 10
+#define REG_STATUS_AES_3 11
+#define REG_STATUS_AES_4 12
+#define REG_STATUS_WORD_CLOCK 13
+#define REG_STATUS_INTER_SYNC 14
+#define REG_STATUS_CURRENT 0x80
+/* results */
+#define REG_STATUS_OPT_NO_VIDEO_SIGNAL 0x01
+#define REG_STATUS_OPT_DAUGHTER_MASK 0x1c
+#define REG_STATUS_OPT_ANALOG_BOARD 0x00
+#define REG_STATUS_OPT_NO_DAUGHTER 0x1c
+#define REG_STATUS_OPT_COMPANION_MASK 0xe0
+#define REG_STATUS_OPT_NO_COMPANION 0xe0
+#define REG_STATUS_SYNC_32000 0x00
+#define REG_STATUS_SYNC_44100 0x01
+#define REG_STATUS_SYNC_48000 0x02
+#define REG_STATUS_SYNC_64000 0x03
+#define REG_STATUS_SYNC_88200 0x04
+#define REG_STATUS_SYNC_96000 0x05
+#define REG_STATUS_SYNC_128000 0x06
+#define REG_STATUS_SYNC_176400 0x07
+#define REG_STATUS_SYNC_192000 0x08
+
+int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start);
+
+int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
+ unsigned int value, int *changed);
+
+/* codec parameters */
+#define CS8416_RUN 0x200401
+#define CS8416_FORMAT_DETECT 0x200b00
+#define CS8416_CSB0 0x201900
+#define CS8416_CSB1 0x201a00
+#define CS8416_CSB2 0x201b00
+#define CS8416_CSB3 0x201c00
+#define CS8416_CSB4 0x201d00
+#define CS8416_VERSION 0x207f00
+
+#define CS8420_DATA_FLOW_CTL 0x200301
+#define CS8420_CLOCK_SRC_CTL 0x200401
+#define CS8420_RECEIVER_ERRORS 0x201000
+#define CS8420_SRC_RATIO 0x201e00
+#define CS8420_CSB0 0x202000
+#define CS8420_CSB1 0x202100
+#define CS8420_CSB2 0x202200
+#define CS8420_CSB3 0x202300
+#define CS8420_CSB4 0x202400
+#define CS8420_VERSION 0x207f00
+
+#define CS4271_MODE_CTL_1 0x200101
+#define CS4271_DAC_CTL 0x200201
+#define CS4271_VOLMIX 0x200301
+#define CS4271_VOLMUTE_LEFT 0x200401
+#define CS4271_VOLMUTE_RIGHT 0x200501
+#define CS4271_ADC_CTL 0x200601
+#define CS4271_MODE_CTL_2 0x200701
+
+#define CHIP_SIG_AND_MAP_SPI 0xff7f00
+
+/* codec selection */
+#define CS4271_01_CS 0x160018
+#define CS4271_23_CS 0x160019
+#define CS4271_45_CS 0x16001a
+#define CS4271_67_CS 0x16001b
+#define CS4271_89_CS 0x16001c
+#define CS4271_AB_CS 0x16001d
+#define CS8420_01_CS 0x080090
+#define CS8420_23_CS 0x080092
+#define CS8420_45_CS 0x080094
+#define CS8420_67_CS 0x080096
+#define CS8416_01_CS 0x080098
+
+
+/* interrupt handling */
+irqreturn_t pcxhr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void pcxhr_msg_tasklet(unsigned long arg);
+
+#endif /* __SOUND_PCXHR_CORE_H */
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
new file mode 100644
index 000000000000..03517c10e99c
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -0,0 +1,438 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * hwdep device manager
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 <sound/driver.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <sound/core.h>
+#include <sound/hwdep.h>
+#include "pcxhr.h"
+#include "pcxhr_mixer.h"
+#include "pcxhr_hwdep.h"
+#include "pcxhr_core.h"
+
+
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
+#if !defined(CONFIG_USE_PCXHRLOADER) && !defined(CONFIG_SND_PCXHR) /* built-in kernel */
+#define SND_PCXHR_FW_LOADER /* use the standard firmware loader */
+#endif
+#endif
+
+
+/*
+ * get basic information and init pcxhr card
+ */
+
+static int pcxhr_init_board(struct pcxhr_mgr *mgr)
+{
+ int err;
+ struct pcxhr_rmh rmh;
+ int card_streams;
+
+ /* calc the number of all streams used */
+ if (mgr->mono_capture)
+ card_streams = mgr->capture_chips * 2;
+ else
+ card_streams = mgr->capture_chips;
+ card_streams += mgr->playback_chips * PCXHR_PLAYBACK_STREAMS;
+
+ /* enable interrupts */
+ pcxhr_enable_dsp(mgr);
+
+ pcxhr_init_rmh(&rmh, CMD_SUPPORTED);
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ /* test 8 or 12 phys out */
+ snd_assert((rmh.stat[0] & MASK_FIRST_FIELD) == mgr->playback_chips*2,
+ return -EINVAL);
+ /* test 8 or 2 phys in */
+ snd_assert(((rmh.stat[0] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD) ==
+ mgr->capture_chips * 2, return -EINVAL);
+ /* test max nb substream per board */
+ snd_assert((rmh.stat[1] & 0x5F) >= card_streams, return -EINVAL);
+ /* test max nb substream per pipe */
+ snd_assert(((rmh.stat[1]>>7)&0x5F) >= PCXHR_PLAYBACK_STREAMS, return -EINVAL);
+
+ pcxhr_init_rmh(&rmh, CMD_VERSION);
+ /* firmware num for DSP */
+ rmh.cmd[0] |= mgr->firmware_num;
+ /* transfer granularity in samples (should be multiple of 48) */
+ rmh.cmd[1] = (1<<23) + PCXHR_GRANULARITY;
+ rmh.cmd_len = 2;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+ snd_printdd("PCXHR DSP version is %d.%d.%d\n",
+ (rmh.stat[0]>>16)&0xff, (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
+ mgr->dsp_version = rmh.stat[0];
+
+ /* get options */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
+ rmh.cmd[0] |= IO_NUM_REG_STATUS;
+ rmh.cmd[1] = REG_STATUS_OPTIONS;
+ rmh.cmd_len = 2;
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err)
+ return err;
+
+ if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) == REG_STATUS_OPT_ANALOG_BOARD)
+ mgr->board_has_analog = 1; /* analog addon board available */
+ else
+ /* analog addon board not available -> no support for instance */
+ return -EINVAL;
+
+ /* unmute inputs */
+ err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
+ REG_CONT_UNMUTE_INPUTS, NULL);
+ if (err)
+ return err;
+ /* unmute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* a write to IO_NUM_REG_MUTE_OUT mutes! */
+ rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ err = pcxhr_send_msg(mgr, &rmh);
+ return err;
+}
+
+void pcxhr_reset_board(struct pcxhr_mgr *mgr)
+{
+ struct pcxhr_rmh rmh;
+
+ if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
+ /* mute outputs */
+ /* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+ pcxhr_send_msg(mgr, &rmh);
+ /* mute inputs */
+ pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, 0, NULL);
+ }
+ /* reset pcxhr dsp */
+ if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
+ pcxhr_reset_dsp(mgr);
+ /* reset second xilinx */
+ if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_XLX_COM_INDEX))
+ pcxhr_reset_xilinx_com(mgr);
+ return;
+}
+
+
+/*
+ * allocate a playback/capture pipe (pcmp0/pcmc0)
+ */
+static int pcxhr_dsp_allocate_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe,
+ int is_capture, int pin)
+{
+ int stream_count, audio_count;
+ int err;
+ struct pcxhr_rmh rmh;
+
+ if (is_capture) {
+ stream_count = 1;
+ if (mgr->mono_capture)
+ audio_count = 1;
+ else
+ audio_count = 2;
+ } else {
+ stream_count = PCXHR_PLAYBACK_STREAMS;
+ audio_count = 2; /* always stereo */
+ }
+ snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", pin, is_capture ? 'c' : 'p');
+ pipe->is_capture = is_capture;
+ pipe->first_audio = pin;
+ /* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
+ pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin, audio_count, stream_count);
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err < 0) {
+ snd_printk(KERN_ERR "error pipe allocation (CMD_RES_PIPE) err=%x!\n", err );
+ return err;
+ }
+ pipe->status = PCXHR_PIPE_DEFINED;
+
+ return 0;
+}
+
+/*
+ * free playback/capture pipe (pcmp0/pcmc0)
+ */
+#if 0
+static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
+{
+ struct pcxhr_rmh rmh;
+ int capture_mask = 0;
+ int playback_mask = 0;
+ int err = 0;
+
+ if (pipe->is_capture)
+ capture_mask = (1 << pipe->first_audio);
+ else
+ playback_mask = (1 << pipe->first_audio);
+
+ /* stop one pipe */
+ err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
+ if (err < 0)
+ snd_printk(KERN_ERR "error stopping pipe!\n");
+ /* release the pipe */
+ pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
+ pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, 0, 0);
+ err = pcxhr_send_msg(mgr, &rmh);
+ if (err < 0)
+ snd_printk(KERN_ERR "error pipe release (CMD_FREE_PIPE) err(%x)\n", err);
+ pipe->status = PCXHR_PIPE_UNDEFINED;
+ return err;
+}
+#endif
+
+
+static int pcxhr_config_pipes(struct pcxhr_mgr *mgr)
+{
+ int err, i, j;
+ struct snd_pcxhr *chip;
+ struct pcxhr_pipe *pipe;
+
+ /* allocate the pipes on the dsp */
+ for (i = 0; i < mgr->num_cards; i++) {
+ chip = mgr->chip[i];
+ if (chip->nb_streams_play) {
+ pipe = &chip->playback_pipe;
+ err = pcxhr_dsp_allocate_pipe( mgr, pipe, 0, i*2);
+ if (err)
+ return err;
+ for(j = 0; j < chip->nb_streams_play; j++)
+ chip->playback_stream[j].pipe = pipe;
+ }
+ for (j = 0; j < chip->nb_streams_capt; j++) {
+ pipe = &chip->capture_pipe[j];
+ err = pcxhr_dsp_allocate_pipe(mgr, pipe, 1, i*2 + j);
+ if (err)
+ return err;
+ chip->capture_stream[j].pipe = pipe;
+ }
+ }
+ return 0;
+}
+
+static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
+{
+ int i, j;
+ struct snd_pcxhr *chip;
+ int playback_mask = 0;
+ int capture_mask = 0;
+
+ /* start all the pipes on the dsp */
+ for (i = 0; i < mgr->num_cards; i++) {
+ chip = mgr->chip[i];
+ if (chip->nb_streams_play)
+ playback_mask |= (1 << chip->playback_pipe.first_audio);
+ for (j = 0; j < chip->nb_streams_capt; j++)
+ capture_mask |= (1 << chip->capture_pipe[j].first_audio);
+ }
+ return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
+}
+
+
+static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, const struct firmware *dsp)
+{
+ int err, card_index;
+
+ snd_printdd("loading dsp [%d] size = %Zd\n", index, dsp->size);
+
+ switch (index) {
+ case PCXHR_FIRMWARE_XLX_INT_INDEX:
+ pcxhr_reset_xilinx_com(mgr);
+ return pcxhr_load_xilinx_binary(mgr, dsp, 0);
+
+ case PCXHR_FIRMWARE_XLX_COM_INDEX:
+ pcxhr_reset_xilinx_com(mgr);
+ return pcxhr_load_xilinx_binary(mgr, dsp, 1);
+
+ case PCXHR_FIRMWARE_DSP_EPRM_INDEX:
+ pcxhr_reset_dsp(mgr);
+ return pcxhr_load_eeprom_binary(mgr, dsp);
+
+ case PCXHR_FIRMWARE_DSP_BOOT_INDEX:
+ return pcxhr_load_boot_binary(mgr, dsp);
+
+ case PCXHR_FIRMWARE_DSP_MAIN_INDEX:
+ err = pcxhr_load_dsp_binary(mgr, dsp);
+ if (err)
+ return err;
+ break; /* continue with first init */
+ default:
+ snd_printk(KERN_ERR "wrong file index\n");
+ return -EFAULT;
+ } /* end of switch file index*/
+
+ /* first communication with embedded */
+ err = pcxhr_init_board(mgr);
+ if (err < 0) {
+ snd_printk(KERN_ERR "pcxhr could not be set up\n");
+ return err;
+ }
+ err = pcxhr_config_pipes(mgr);
+ if (err < 0) {
+ snd_printk(KERN_ERR "pcxhr pipes could not be set up\n");
+ return err;
+ }
+ /* create devices and mixer in accordance with HW options*/
+ for (card_index = 0; card_index < mgr->num_cards; card_index++) {
+ struct snd_pcxhr *chip = mgr->chip[card_index];
+
+ if ((err = pcxhr_create_pcm(chip)) < 0)
+ return err;
+
+ if (card_index == 0) {
+ if ((err = pcxhr_create_mixer(chip->mgr)) < 0)
+ return err;
+ }
+ if ((err = snd_card_register(chip->card)) < 0)
+ return err;
+ }
+ err = pcxhr_start_pipes(mgr);
+ if (err < 0) {
+ snd_printk(KERN_ERR "pcxhr pipes could not be started\n");
+ return err;
+ }
+ snd_printdd("pcxhr firmware downloaded and successfully set up\n");
+
+ return 0;
+}
+
+/*
+ * fw loader entry
+ */
+#ifdef SND_PCXHR_FW_LOADER
+
+int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
+{
+ static char *fw_files[5] = {
+ "xi_1_882.dat",
+ "xc_1_882.dat",
+ "e321_512.e56",
+ "b321_512.b56",
+ "d321_512.d56"
+ };
+ char path[32];
+
+ const struct firmware *fw_entry;
+ int i, err;
+
+ for (i = 0; i < ARRAY_SIZE(fw_files); i++) {
+ sprintf(path, "pcxhr/%s", fw_files[i]);
+ if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
+ snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", path);
+ return -ENOENT;
+ }
+ /* fake hwdep dsp record */
+ err = pcxhr_dsp_load(mgr, i, fw_entry);
+ release_firmware(fw_entry);
+ if (err < 0)
+ return err;
+ mgr->dsp_loaded |= 1 << i;
+ }
+ return 0;
+}
+
+#else /* old style firmware loading */
+
+/* pcxhr hwdep interface id string */
+#define PCXHR_HWDEP_ID "pcxhr loader"
+
+
+static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_status *info)
+{
+ strcpy(info->id, "pcxhr");
+ info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
+
+ if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
+ info->chip_ready = 1;
+
+ info->version = PCXHR_DRIVER_VERSION;
+ return 0;
+}
+
+static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image *dsp)
+{
+ struct pcxhr_mgr *mgr = hw->private_data;
+ int err;
+ struct firmware fw;
+
+ fw.size = dsp->length;
+ fw.data = vmalloc(fw.size);
+ if (! fw.data) {
+ snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%d bytes)\n",
+ fw.size);
+ return -ENOMEM;
+ }
+ if (copy_from_user(fw.data, dsp->image, dsp->length)) {
+ vfree(fw.data);
+ return -EFAULT;
+ }
+ err = pcxhr_dsp_load(mgr, dsp->index, &fw);
+ vfree(fw.data);
+ if (err < 0)
+ return err;
+ mgr->dsp_loaded |= 1 << dsp->index;
+ return 0;
+}
+
+static int pcxhr_hwdep_open(struct snd_hwdep *hw, struct file *file)
+{
+ return 0;
+}
+
+static int pcxhr_hwdep_release(struct snd_hwdep *hw, struct file *file)
+{
+ return 0;
+}
+
+int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
+{
+ int err;
+ struct snd_hwdep *hw;
+
+ /* only create hwdep interface for first cardX (see "index" module parameter)*/
+ if ((err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw)) < 0)
+ return err;
+
+ hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
+ hw->private_data = mgr;
+ hw->ops.open = pcxhr_hwdep_open;
+ hw->ops.release = pcxhr_hwdep_release;
+ hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
+ hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
+ hw->exclusive = 1;
+ mgr->dsp_loaded = 0;
+ sprintf(hw->name, PCXHR_HWDEP_ID);
+
+ if ((err = snd_card_register(mgr->chip[0]->card)) < 0)
+ return err;
+ return 0;
+}
+
+#endif /* SND_PCXHR_FW_LOADER */
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.h b/sound/pci/pcxhr/pcxhr_hwdep.h
new file mode 100644
index 000000000000..f561909dc05f
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_hwdep.h
@@ -0,0 +1,40 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * definitions and makros for basic card access
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 __SOUND_PCXHR_HWDEP_H
+#define __SOUND_PCXHR_HWDEP_H
+
+
+/* firmware status codes */
+#define PCXHR_FIRMWARE_XLX_INT_INDEX 0
+#define PCXHR_FIRMWARE_XLX_COM_INDEX 1
+#define PCXHR_FIRMWARE_DSP_EPRM_INDEX 2
+#define PCXHR_FIRMWARE_DSP_BOOT_INDEX 3
+#define PCXHR_FIRMWARE_DSP_MAIN_INDEX 4
+#define PCXHR_FIRMWARE_FILES_MAX_INDEX 5
+
+
+/* exported */
+int pcxhr_setup_firmware(struct pcxhr_mgr *mgr);
+void pcxhr_reset_board(struct pcxhr_mgr *mgr);
+
+#endif /* __SOUND_PCXHR_HWDEP_H */
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
new file mode 100644
index 000000000000..760e733ac25e
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -0,0 +1,1020 @@
+#define __NO_VERSION__
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * mixer callbacks
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 <sound/driver.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include "pcxhr.h"
+#include "pcxhr_hwdep.h"
+#include "pcxhr_core.h"
+#include <sound/control.h>
+#include <sound/asoundef.h>
+#include "pcxhr_mixer.h"
+
+
+#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */
+#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */
+#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */
+
+#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */
+#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
+#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
+
+static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
+{
+ int err, vol;
+ struct pcxhr_rmh rmh;
+
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ if (is_capture) {
+ rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL;
+ rmh.cmd[2] = chip->analog_capture_volume[channel];
+ } else {
+ rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL;
+ if (chip->analog_playback_active[channel])
+ vol = chip->analog_playback_volume[channel];
+ else
+ vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;
+ rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */
+ }
+ rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
+ rmh.cmd_len = 3;
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err < 0) {
+ snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "
+ "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * analog level control
+ */
+static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ if (kcontrol->private_value == 0) { /* playback */
+ uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */
+ uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */
+ } else { /* capture */
+ uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */
+ uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */
+ }
+ return 0;
+}
+
+static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ down(&chip->mgr->mixer_mutex);
+ if (kcontrol->private_value == 0) { /* playback */
+ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
+ } else { /* capture */
+ ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
+ }
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ int is_capture, i;
+
+ down(&chip->mgr->mixer_mutex);
+ is_capture = (kcontrol->private_value != 0);
+ for (i = 0; i < 2; i++) {
+ int new_volume = ucontrol->value.integer.value[i];
+ int* stored_volume = is_capture ? &chip->analog_capture_volume[i] :
+ &chip->analog_playback_volume[i];
+ if (*stored_volume != new_volume) {
+ *stored_volume = new_volume;
+ changed = 1;
+ pcxhr_update_analog_audio_level(chip, is_capture, i);
+ }
+ }
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new pcxhr_control_analog_level = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* name will be filled later */
+ .info = pcxhr_analog_vol_info,
+ .get = pcxhr_analog_vol_get,
+ .put = pcxhr_analog_vol_put,
+};
+
+/* shared */
+static int pcxhr_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+
+ down(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
+ ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int i, changed = 0;
+ down(&chip->mgr->mixer_mutex);
+ for(i = 0; i < 2; i++) {
+ if (chip->analog_playback_active[i] != ucontrol->value.integer.value[i]) {
+ chip->analog_playback_active[i] = ucontrol->value.integer.value[i];
+ changed = 1;
+ pcxhr_update_analog_audio_level(chip, 0, i); /* update playback levels */
+ }
+ }
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new pcxhr_control_output_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = pcxhr_sw_info, /* shared */
+ .get = pcxhr_audio_sw_get,
+ .put = pcxhr_audio_sw_put
+};
+
+
+#define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */
+#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
+#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
+
+
+#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
+#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
+#define VALID_STREAM_LEVEL_MASK 0x400000
+#define VALID_STREAM_LEVEL_1_MASK 0x200000
+#define VALID_STREAM_LEVEL_2_MASK 0x100000
+
+static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
+{
+ int err;
+ struct pcxhr_rmh rmh;
+ struct pcxhr_pipe *pipe = &chip->playback_pipe;
+ int left, right;
+
+ if (chip->digital_playback_active[idx][0])
+ left = chip->digital_playback_volume[idx][0];
+ else
+ left = PCXHR_DIGITAL_LEVEL_MIN;
+ if (chip->digital_playback_active[idx][1])
+ right = chip->digital_playback_volume[idx][1];
+ else
+ right = PCXHR_DIGITAL_LEVEL_MIN;
+
+ pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);
+ /* add pipe and stream mask */
+ pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);
+ /* volume left->left / right->right panoramic level */
+ rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;
+ rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;
+ rmh.cmd[2] |= (left << 10);
+ rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;
+ rmh.cmd[3] |= right;
+ rmh.cmd_len = 4;
+
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err < 0) {
+ snd_printk(KERN_DEBUG "error update_playback_stream_level "
+ "card(%d) err(%x)\n", chip->chip_idx, err);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+#define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
+#define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000
+#define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001
+#define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002
+#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
+#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
+
+static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
+{
+ int err;
+ struct pcxhr_rmh rmh;
+ struct pcxhr_pipe *pipe;
+
+ if (capture)
+ pipe = &chip->capture_pipe[0];
+ else
+ pipe = &chip->playback_pipe;
+
+ pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
+ /* add channel mask */
+ pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
+ /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
+ * will be programmed to the same params
+ */
+ if (capture) {
+ rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
+ /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
+ rmh.cmd[2] = chip->digital_capture_volume[channel];
+ } else {
+ rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
+ /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
+ * handled (playback pipe level)
+ */
+ rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
+ if (chip->monitoring_active[channel] == 0)
+ rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;
+ }
+ rmh.cmd_len = 3;
+
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if(err<0) {
+ snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
+ chip->chip_idx, err);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+/* shared */
+static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */
+ uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */
+ return 0;
+}
+
+
+static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int *stored_volume;
+ int is_capture = kcontrol->private_value;
+
+ down(&chip->mgr->mixer_mutex);
+ if (is_capture)
+ stored_volume = chip->digital_capture_volume; /* digital capture */
+ else
+ stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
+ ucontrol->value.integer.value[0] = stored_volume[0];
+ ucontrol->value.integer.value[1] = stored_volume[1];
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int changed = 0;
+ int is_capture = kcontrol->private_value;
+ int *stored_volume;
+ int i;
+
+ down(&chip->mgr->mixer_mutex);
+ if (is_capture)
+ stored_volume = chip->digital_capture_volume; /* digital capture */
+ else
+ stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
+ for (i = 0; i < 2; i++) {
+ if (stored_volume[i] != ucontrol->value.integer.value[i]) {
+ stored_volume[i] = ucontrol->value.integer.value[i];
+ changed = 1;
+ if (is_capture) /* update capture volume */
+ pcxhr_update_audio_pipe_level(chip, 1, i);
+ }
+ }
+ if (! is_capture && changed)
+ pcxhr_update_playback_stream_level(chip, idx); /* update playback volume */
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new snd_pcxhr_pcm_vol =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* name will be filled later */
+ /* count will be filled later */
+ .info = pcxhr_digital_vol_info, /* shared */
+ .get = pcxhr_pcm_vol_get,
+ .put = pcxhr_pcm_vol_put,
+};
+
+
+static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+
+ down(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
+ ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int i, j;
+
+ down(&chip->mgr->mixer_mutex);
+ j = idx;
+ for (i = 0; i < 2; i++) {
+ if (chip->digital_playback_active[j][i] != ucontrol->value.integer.value[i]) {
+ chip->digital_playback_active[j][i] = ucontrol->value.integer.value[i];
+ changed = 1;
+ }
+ }
+ if (changed)
+ pcxhr_update_playback_stream_level(chip, idx);
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new pcxhr_control_pcm_switch = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .count = PCXHR_PLAYBACK_STREAMS,
+ .info = pcxhr_sw_info, /* shared */
+ .get = pcxhr_pcm_sw_get,
+ .put = pcxhr_pcm_sw_put
+};
+
+
+/*
+ * monitoring level control
+ */
+
+static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ down(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
+ ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ int i;
+
+ down(&chip->mgr->mixer_mutex);
+ for (i = 0; i < 2; i++) {
+ if (chip->monitoring_volume[i] != ucontrol->value.integer.value[i]) {
+ chip->monitoring_volume[i] = ucontrol->value.integer.value[i];
+ if(chip->monitoring_active[i]) /* do only when monitoring is unmuted */
+ /* update monitoring volume and mute */
+ pcxhr_update_audio_pipe_level(chip, 0, i);
+ changed = 1;
+ }
+ }
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitoring Volume",
+ .info = pcxhr_digital_vol_info, /* shared */
+ .get = pcxhr_monitor_vol_get,
+ .put = pcxhr_monitor_vol_put,
+};
+
+/*
+ * monitoring switch control
+ */
+
+static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ down(&chip->mgr->mixer_mutex);
+ ucontrol->value.integer.value[0] = chip->monitoring_active[0];
+ ucontrol->value.integer.value[1] = chip->monitoring_active[1];
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+ int i;
+
+ down(&chip->mgr->mixer_mutex);
+ for (i = 0; i < 2; i++) {
+ if (chip->monitoring_active[i] != ucontrol->value.integer.value[i]) {
+ chip->monitoring_active[i] = ucontrol->value.integer.value[i];
+ changed |= (1<<i); /* mask 0x01 and 0x02 */
+ }
+ }
+ if(changed & 0x01)
+ /* update left monitoring volume and mute */
+ pcxhr_update_audio_pipe_level(chip, 0, 0);
+ if(changed & 0x02)
+ /* update right monitoring volume and mute */
+ pcxhr_update_audio_pipe_level(chip, 0, 1);
+
+ up(&chip->mgr->mixer_mutex);
+ return (changed != 0);
+}
+
+static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Monitoring Switch",
+ .info = pcxhr_sw_info, /* shared */
+ .get = pcxhr_monitor_sw_get,
+ .put = pcxhr_monitor_sw_put
+};
+
+
+
+/*
+ * audio source select
+ */
+#define PCXHR_SOURCE_AUDIO01_UER 0x000100
+#define PCXHR_SOURCE_AUDIO01_SYNC 0x000200
+#define PCXHR_SOURCE_AUDIO23_UER 0x000400
+#define PCXHR_SOURCE_AUDIO45_UER 0x001000
+#define PCXHR_SOURCE_AUDIO67_UER 0x040000
+
+static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
+{
+ struct pcxhr_rmh rmh;
+ unsigned int mask, reg;
+ unsigned int codec;
+ int err, use_src, changed;
+
+ switch (chip->chip_idx) {
+ case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
+ case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break;
+ case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break;
+ case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
+ default: return -EINVAL;
+ }
+ reg = 0; /* audio source from analog plug */
+ use_src = 0; /* do not activate codec SRC */
+
+ if (chip->audio_capture_source != 0) {
+ reg = mask; /* audio source from digital plug */
+ if (chip->audio_capture_source == 2)
+ use_src = 1;
+ }
+ /* set the input source */
+ pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
+ /* resync them (otherwise channel inversion possible) */
+ if (changed) {
+ pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
+ rmh.cmd[0] |= (1 << chip->chip_idx);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ return err;
+ }
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
+ rmh.cmd_len = 3;
+ rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
+ rmh.cmd[1] = codec;
+ rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if(err)
+ return err;
+ rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ return err;
+}
+
+static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item > 2)
+ uinfo->value.enumerated.item = 2;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
+ return 0;
+}
+
+static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int ret = 0;
+
+ down(&chip->mgr->mixer_mutex);
+ if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
+ chip->audio_capture_source = ucontrol->value.enumerated.item[0];
+ pcxhr_set_audio_source(chip);
+ ret = 1;
+ }
+ up(&chip->mgr->mixer_mutex);
+ return ret;
+}
+
+static struct snd_kcontrol_new pcxhr_control_audio_src = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = pcxhr_audio_src_info,
+ .get = pcxhr_audio_src_get,
+ .put = pcxhr_audio_src_put,
+};
+
+
+/*
+ * clock type selection
+ * enum pcxhr_clock_type {
+ * PCXHR_CLOCK_TYPE_INTERNAL = 0,
+ * PCXHR_CLOCK_TYPE_WORD_CLOCK,
+ * PCXHR_CLOCK_TYPE_AES_SYNC,
+ * PCXHR_CLOCK_TYPE_AES_1,
+ * PCXHR_CLOCK_TYPE_AES_2,
+ * PCXHR_CLOCK_TYPE_AES_3,
+ * PCXHR_CLOCK_TYPE_AES_4,
+ * };
+ */
+
+static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static char *texts[7] = {
+ "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
+ };
+ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ int clock_items = 3 + mgr->capture_chips;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = clock_items;
+ if (uinfo->value.enumerated.item >= clock_items)
+ uinfo->value.enumerated.item = clock_items-1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
+ return 0;
+}
+
+static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ int rate, ret = 0;
+
+ down(&mgr->mixer_mutex);
+ if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
+ down(&mgr->setup_mutex);
+ mgr->use_clock_type = ucontrol->value.enumerated.item[0];
+ if (mgr->use_clock_type)
+ pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
+ else
+ rate = mgr->sample_rate;
+ if (rate) {
+ pcxhr_set_clock(mgr, rate);
+ if (mgr->sample_rate)
+ mgr->sample_rate = rate;
+ }
+ up(&mgr->setup_mutex);
+ ret = 1; /* return 1 even if the set was not done. ok ? */
+ }
+ up(&mgr->mixer_mutex);
+ return ret;
+}
+
+static struct snd_kcontrol_new pcxhr_control_clock_type = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Clock Mode",
+ .info = pcxhr_clock_type_info,
+ .get = pcxhr_clock_type_get,
+ .put = pcxhr_clock_type_put,
+};
+
+/*
+ * clock rate control
+ * specific control that scans the sample rates on the external plugs
+ */
+static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 3 + mgr->capture_chips;
+ uinfo->value.integer.min = 0; /* clock not present */
+ uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */
+ return 0;
+}
+
+static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ int i, err, rate;
+
+ down(&mgr->mixer_mutex);
+ for(i = 0; i < 3 + mgr->capture_chips; i++) {
+ if (i == PCXHR_CLOCK_TYPE_INTERNAL)
+ rate = mgr->sample_rate_real;
+ else {
+ err = pcxhr_get_external_clock(mgr, i, &rate);
+ if (err)
+ break;
+ }
+ ucontrol->value.integer.value[i] = rate;
+ }
+ up(&mgr->mixer_mutex);
+ return 0;
+}
+
+static struct snd_kcontrol_new pcxhr_control_clock_rate = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .name = "Clock Rates",
+ .info = pcxhr_clock_rate_info,
+ .get = pcxhr_clock_rate_get,
+};
+
+/*
+ * IEC958 status bits
+ */
+static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+ uinfo->count = 1;
+ return 0;
+}
+
+static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
+{
+ int i, err;
+ unsigned char temp;
+ struct pcxhr_rmh rmh;
+
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
+ rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
+ switch (chip->chip_idx) {
+ case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
+ case 1: rmh.cmd[1] = CS8420_23_CS; break;
+ case 2: rmh.cmd[1] = CS8420_45_CS; break;
+ case 3: rmh.cmd[1] = CS8420_67_CS; break;
+ default: return -EINVAL;
+ }
+ switch (aes_idx) {
+ case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
+ case 1: rmh.cmd[2] = CS8420_CSB1; break;
+ case 2: rmh.cmd[2] = CS8420_CSB2; break;
+ case 3: rmh.cmd[2] = CS8420_CSB3; break;
+ case 4: rmh.cmd[2] = CS8420_CSB4; break;
+ default: return -EINVAL;
+ }
+ rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
+ rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
+ rmh.cmd_len = 3;
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ return err;
+ temp = 0;
+ for (i = 0; i < 8; i++) {
+ /* attention : reversed bit order (not with CS8416_01_CS) */
+ temp <<= 1;
+ if (rmh.stat[1] & (1 << i))
+ temp |= 1;
+ }
+ snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
+ *aes_bits = temp;
+ return 0;
+}
+
+static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ unsigned char aes_bits;
+ int i, err;
+
+ down(&chip->mgr->mixer_mutex);
+ for(i = 0; i < 5; i++) {
+ if (kcontrol->private_value == 0) /* playback */
+ aes_bits = chip->aes_bits[i];
+ else { /* capture */
+ err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
+ if (err)
+ break;
+ }
+ ucontrol->value.iec958.status[i] = aes_bits;
+ }
+ up(&chip->mgr->mixer_mutex);
+ return 0;
+}
+
+static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ for (i = 0; i < 5; i++)
+ ucontrol->value.iec958.status[i] = 0xff;
+ return 0;
+}
+
+static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
+{
+ int i, err, cmd;
+ unsigned char new_bits = aes_bits;
+ unsigned char old_bits = chip->aes_bits[aes_idx];
+ struct pcxhr_rmh rmh;
+
+ for (i = 0; i < 8; i++) {
+ if ((old_bits & 0x01) != (new_bits & 0x01)) {
+ cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
+ if(chip->chip_idx > 3)
+ /* new bit used if chip_idx>3 (PCX1222HR) */
+ cmd |= 1 << 22;
+ cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
+ cmd |= (new_bits & 0x01) << 23; /* add bit value */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
+ rmh.cmd[0] |= IO_NUM_REG_CUER;
+ rmh.cmd[1] = cmd;
+ rmh.cmd_len = 2;
+ snd_printdd("write iec958 AES %d byte %d bit %d (cmd %x)\n",
+ chip->chip_idx, aes_idx, i, cmd);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if (err)
+ return err;
+ }
+ old_bits >>= 1;
+ new_bits >>= 1;
+ }
+ chip->aes_bits[aes_idx] = aes_bits;
+ return 0;
+}
+
+static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ int i, changed = 0;
+
+ /* playback */
+ down(&chip->mgr->mixer_mutex);
+ for (i = 0; i < 5; i++) {
+ if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
+ pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
+ changed = 1;
+ }
+ }
+ up(&chip->mgr->mixer_mutex);
+ return changed;
+}
+
+static struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+ .info = pcxhr_iec958_info,
+ .get = pcxhr_iec958_mask_get
+};
+static struct snd_kcontrol_new pcxhr_control_playback_iec958 = {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .info = pcxhr_iec958_info,
+ .get = pcxhr_iec958_get,
+ .put = pcxhr_iec958_put,
+ .private_value = 0 /* playback */
+};
+
+static struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
+ .info = pcxhr_iec958_info,
+ .get = pcxhr_iec958_mask_get
+};
+static struct snd_kcontrol_new pcxhr_control_capture_iec958 = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+ .info = pcxhr_iec958_info,
+ .get = pcxhr_iec958_get,
+ .private_value = 1 /* capture */
+};
+
+static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
+{
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ if (chip->nb_streams_play) {
+ int j;
+ /* at boot time the digital volumes are unmuted 0dB */
+ for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
+ chip->digital_playback_active[j][i] = 1;
+ chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
+ }
+ /* after boot, only two bits are set on the uer interface */
+ chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
+/* only for test purpose, remove later */
+#ifdef CONFIG_SND_DEBUG
+ /* analog volumes for playback (is LEVEL_MIN after boot) */
+ chip->analog_playback_active[i] = 1;
+ chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 0, i);
+#endif
+/* test end */
+ }
+ if (chip->nb_streams_capt) {
+ /* at boot time the digital volumes are unmuted 0dB */
+ chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
+/* only for test purpose, remove later */
+#ifdef CONFIG_SND_DEBUG
+ /* analog volumes for playback (is LEVEL_MIN after boot) */
+ chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 1, i);
+#endif
+/* test end */
+ }
+ }
+
+ return;
+}
+
+
+int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
+{
+ struct snd_pcxhr *chip;
+ int err, i;
+
+ init_MUTEX(&mgr->mixer_mutex); /* can be in another place */
+
+ for (i = 0; i < mgr->num_cards; i++) {
+ struct snd_kcontrol_new temp;
+ chip = mgr->chip[i];
+
+ if (chip->nb_streams_play) {
+ /* analog output level control */
+ temp = pcxhr_control_analog_level;
+ temp.name = "Master Playback Volume";
+ temp.private_value = 0; /* playback */
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ return err;
+ /* output mute controls */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_output_switch,
+ chip))) < 0)
+ return err;
+
+ temp = snd_pcxhr_pcm_vol;
+ temp.name = "PCM Playback Volume";
+ temp.count = PCXHR_PLAYBACK_STREAMS;
+ temp.private_value = 0; /* playback */
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ return err;
+
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_pcm_switch,
+ chip))) < 0)
+ return err;
+
+ /* IEC958 controls */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
+ chip))) < 0)
+ return err;
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958,
+ chip))) < 0)
+ return err;
+ }
+ if (chip->nb_streams_capt) {
+ /* analog input level control only on first two chips !*/
+ temp = pcxhr_control_analog_level;
+ temp.name = "Master Capture Volume";
+ temp.private_value = 1; /* capture */
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ return err;
+
+ temp = snd_pcxhr_pcm_vol;
+ temp.name = "PCM Capture Volume";
+ temp.count = 1;
+ temp.private_value = 1; /* capture */
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
+ return err;
+ /* Audio source */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_audio_src,
+ chip))) < 0)
+ return err;
+ /* IEC958 controls */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
+ chip))) < 0)
+ return err;
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958,
+ chip))) < 0)
+ return err;
+ }
+ /* monitoring only if playback and capture device available */
+ if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
+ /* monitoring */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_vol,
+ chip))) < 0)
+ return err;
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_sw,
+ chip))) < 0)
+ return err;
+ }
+
+ if (i == 0) {
+ /* clock mode only one control per pcxhr */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_type,
+ mgr))) < 0)
+ return err;
+ /* non standard control used to scan the external clock presence/frequencies */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_rate,
+ mgr))) < 0)
+ return err;
+ }
+
+ /* init values for the mixer data */
+ pcxhr_init_audio_levels(chip);
+ }
+
+ return 0;
+}
diff --git a/sound/pci/pcxhr/pcxhr_mixer.h b/sound/pci/pcxhr/pcxhr_mixer.h
new file mode 100644
index 000000000000..4348d0e55ba3
--- /dev/null
+++ b/sound/pci/pcxhr/pcxhr_mixer.h
@@ -0,0 +1,29 @@
+/*
+ * Driver for Digigram pcxhr compatible soundcards
+ *
+ * include file for mixer
+ *
+ * Copyright (c) 2004 by Digigram <alsa@digigram.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 __SOUND_PCXHR_MIXER_H
+#define __SOUND_PCXHR_MIXER_H
+
+/* exported */
+int pcxhr_create_mixer(struct pcxhr_mgr *mgr);
+
+#endif /* __SOUND_PCXHR_MIXER_H */
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 783df7625c1c..0cbef5fe6c63 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -192,7 +192,7 @@ MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
#define RME32_PRO_REVISION_WITH_8414 150
-typedef struct snd_rme32 {
+struct rme32 {
spinlock_t lock;
int irq;
unsigned long port;
@@ -205,8 +205,8 @@ typedef struct snd_rme32 {
u8 rev; /* card revision number */
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
int playback_frlog; /* log2 of framesize */
int capture_frlog;
@@ -217,15 +217,15 @@ typedef struct snd_rme32 {
unsigned int fullduplex_mode;
int running;
- snd_pcm_indirect_t playback_pcm;
- snd_pcm_indirect_t capture_pcm;
+ struct snd_pcm_indirect playback_pcm;
+ struct snd_pcm_indirect capture_pcm;
- snd_card_t *card;
- snd_pcm_t *spdif_pcm;
- snd_pcm_t *adat_pcm;
+ struct snd_card *card;
+ struct snd_pcm *spdif_pcm;
+ struct snd_pcm *adat_pcm;
struct pci_dev *pci;
- snd_kcontrol_t *spdif_ctl;
-} rme32_t;
+ struct snd_kcontrol *spdif_ctl;
+};
static struct pci_device_id snd_rme32_ids[] = {
{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
@@ -242,17 +242,17 @@ MODULE_DEVICE_TABLE(pci, snd_rme32_ids);
#define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START)
#define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414)
-static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream);
+static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream);
-static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream);
+static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream);
-static int snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd);
+static int snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd);
-static void snd_rme32_proc_init(rme32_t * rme32);
+static void snd_rme32_proc_init(struct rme32 * rme32);
-static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32);
+static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32);
-static inline unsigned int snd_rme32_pcm_byteptr(rme32_t * rme32)
+static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32)
{
return (readl(rme32->iobase + RME32_IO_GET_POS)
& RME32_RCR_AUDIO_ADDR_MASK);
@@ -272,11 +272,11 @@ static int snd_rme32_ratecode(int rate)
}
/* silence callback for halfduplex mode */
-static int snd_rme32_playback_silence(snd_pcm_substream_t * substream, int channel, /* not used (interleaved data) */
+static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
count <<= rme32->playback_frlog;
pos <<= rme32->playback_frlog;
memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
@@ -284,11 +284,11 @@ static int snd_rme32_playback_silence(snd_pcm_substream_t * substream, int chann
}
/* copy callback for halfduplex mode */
-static int snd_rme32_playback_copy(snd_pcm_substream_t * substream, int channel, /* not used (interleaved data) */
+static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src, snd_pcm_uframes_t count)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
count <<= rme32->playback_frlog;
pos <<= rme32->playback_frlog;
if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
@@ -298,11 +298,11 @@ static int snd_rme32_playback_copy(snd_pcm_substream_t * substream, int channel,
}
/* copy callback for halfduplex mode */
-static int snd_rme32_capture_copy(snd_pcm_substream_t * substream, int channel, /* not used (interleaved data) */
+static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *dst, snd_pcm_uframes_t count)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
count <<= rme32->capture_frlog;
pos <<= rme32->capture_frlog;
if (copy_to_user_fromio(dst,
@@ -315,7 +315,7 @@ static int snd_rme32_capture_copy(snd_pcm_substream_t * substream, int channel,
/*
* SPDIF I/O capabilites (half-duplex mode)
*/
-static snd_pcm_hardware_t snd_rme32_spdif_info = {
+static struct snd_pcm_hardware snd_rme32_spdif_info = {
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -341,7 +341,7 @@ static snd_pcm_hardware_t snd_rme32_spdif_info = {
/*
* ADAT I/O capabilites (half-duplex mode)
*/
-static snd_pcm_hardware_t snd_rme32_adat_info =
+static struct snd_pcm_hardware snd_rme32_adat_info =
{
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -366,7 +366,7 @@ static snd_pcm_hardware_t snd_rme32_adat_info =
/*
* SPDIF I/O capabilites (full-duplex mode)
*/
-static snd_pcm_hardware_t snd_rme32_spdif_fd_info = {
+static struct snd_pcm_hardware snd_rme32_spdif_fd_info = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
@@ -392,7 +392,7 @@ static snd_pcm_hardware_t snd_rme32_spdif_fd_info = {
/*
* ADAT I/O capabilites (full-duplex mode)
*/
-static snd_pcm_hardware_t snd_rme32_adat_fd_info =
+static struct snd_pcm_hardware snd_rme32_adat_fd_info =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -414,14 +414,14 @@ static snd_pcm_hardware_t snd_rme32_adat_fd_info =
.fifo_size = 0,
};
-static void snd_rme32_reset_dac(rme32_t *rme32)
+static void snd_rme32_reset_dac(struct rme32 *rme32)
{
writel(rme32->wcreg | RME32_WCR_PD,
rme32->iobase + RME32_IO_CONTROL_REGISTER);
writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
}
-static int snd_rme32_playback_getrate(rme32_t * rme32)
+static int snd_rme32_playback_getrate(struct rme32 * rme32)
{
int rate;
@@ -443,7 +443,7 @@ static int snd_rme32_playback_getrate(rme32_t * rme32)
return (rme32->wcreg & RME32_WCR_DS_BM) ? rate << 1 : rate;
}
-static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
+static int snd_rme32_capture_getrate(struct rme32 * rme32, int *is_adat)
{
int n;
@@ -505,7 +505,7 @@ static int snd_rme32_capture_getrate(rme32_t * rme32, int *is_adat)
return -1;
}
-static int snd_rme32_playback_setrate(rme32_t * rme32, int rate)
+static int snd_rme32_playback_setrate(struct rme32 * rme32, int rate)
{
int ds;
@@ -561,7 +561,7 @@ static int snd_rme32_playback_setrate(rme32_t * rme32, int rate)
return 0;
}
-static int snd_rme32_setclockmode(rme32_t * rme32, int mode)
+static int snd_rme32_setclockmode(struct rme32 * rme32, int mode)
{
switch (mode) {
case RME32_CLOCKMODE_SLAVE:
@@ -591,13 +591,13 @@ static int snd_rme32_setclockmode(rme32_t * rme32, int mode)
return 0;
}
-static int snd_rme32_getclockmode(rme32_t * rme32)
+static int snd_rme32_getclockmode(struct rme32 * rme32)
{
return ((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_0) & 1) +
(((rme32->wcreg >> RME32_WCR_BITPOS_FREQ_1) & 1) << 1);
}
-static int snd_rme32_setinputtype(rme32_t * rme32, int type)
+static int snd_rme32_setinputtype(struct rme32 * rme32, int type)
{
switch (type) {
case RME32_INPUT_OPTICAL:
@@ -623,14 +623,14 @@ static int snd_rme32_setinputtype(rme32_t * rme32, int type)
return 0;
}
-static int snd_rme32_getinputtype(rme32_t * rme32)
+static int snd_rme32_getinputtype(struct rme32 * rme32)
{
return ((rme32->wcreg >> RME32_WCR_BITPOS_INP_0) & 1) +
(((rme32->wcreg >> RME32_WCR_BITPOS_INP_1) & 1) << 1);
}
static void
-snd_rme32_setframelog(rme32_t * rme32, int n_channels, int is_playback)
+snd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback)
{
int frlog;
@@ -649,7 +649,7 @@ snd_rme32_setframelog(rme32_t * rme32, int n_channels, int is_playback)
}
}
-static int snd_rme32_setformat(rme32_t * rme32, int format)
+static int snd_rme32_setformat(struct rme32 * rme32, int format)
{
switch (format) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -666,12 +666,12 @@ static int snd_rme32_setformat(rme32_t * rme32, int format)
}
static int
-snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * params)
+snd_rme32_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
int err, rate, dummy;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (rme32->fullduplex_mode) {
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
@@ -721,12 +721,12 @@ snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
}
static int
-snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * params)
+snd_rme32_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
int err, isadat, rate;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (rme32->fullduplex_mode) {
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
@@ -782,15 +782,15 @@ snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_rme32_pcm_hw_free(snd_pcm_substream_t * substream)
+static int snd_rme32_pcm_hw_free(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
if (! rme32->fullduplex_mode)
return 0;
return snd_pcm_lib_free_pages(substream);
}
-static void snd_rme32_pcm_start(rme32_t * rme32, int from_pause)
+static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause)
{
if (!from_pause) {
writel(0, rme32->iobase + RME32_IO_RESET_POS);
@@ -800,7 +800,7 @@ static void snd_rme32_pcm_start(rme32_t * rme32, int from_pause)
writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
}
-static void snd_rme32_pcm_stop(rme32_t * rme32, int to_pause)
+static void snd_rme32_pcm_stop(struct rme32 * rme32, int to_pause)
{
/*
* Check if there is an unconfirmed IRQ, if so confirm it, or else
@@ -821,7 +821,7 @@ static void snd_rme32_pcm_stop(rme32_t * rme32, int to_pause)
static irqreturn_t
snd_rme32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- rme32_t *rme32 = (rme32_t *) dev_id;
+ struct rme32 *rme32 = (struct rme32 *) dev_id;
rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);
if (!(rme32->rcreg & RME32_RCR_IRQ)) {
@@ -841,13 +841,13 @@ snd_rme32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static unsigned int period_bytes[] = { RME32_BLOCK_SIZE };
-static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = {
.count = ARRAY_SIZE(period_bytes),
.list = period_bytes,
.mask = 0
};
-static void snd_rme32_set_buffer_constraint(rme32_t *rme32, snd_pcm_runtime_t *runtime)
+static void snd_rme32_set_buffer_constraint(struct rme32 *rme32, struct snd_pcm_runtime *runtime)
{
if (! rme32->fullduplex_mode) {
snd_pcm_hw_constraint_minmax(runtime,
@@ -859,11 +859,11 @@ static void snd_rme32_set_buffer_constraint(rme32_t *rme32, snd_pcm_runtime_t *r
}
}
-static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
+static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream)
{
int rate, dummy;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -902,11 +902,11 @@ static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
+static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream)
{
int isadat, rate;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -941,11 +941,11 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
}
static int
-snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
+snd_rme32_playback_adat_open(struct snd_pcm_substream *substream)
{
int rate, dummy;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -976,11 +976,11 @@ snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
}
static int
-snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
+snd_rme32_capture_adat_open(struct snd_pcm_substream *substream)
{
int isadat, rate;
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (rme32->fullduplex_mode)
runtime->hw = snd_rme32_adat_fd_info;
@@ -1009,9 +1009,9 @@ snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
+static int snd_rme32_playback_close(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
int spdif = 0;
spin_lock_irq(&rme32->lock);
@@ -1028,9 +1028,9 @@ static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_rme32_capture_close(snd_pcm_substream_t * substream)
+static int snd_rme32_capture_close(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme32->lock);
rme32->capture_substream = NULL;
@@ -1039,9 +1039,9 @@ static int snd_rme32_capture_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme32->lock);
if (rme32->fullduplex_mode) {
@@ -1058,9 +1058,9 @@ static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme32->lock);
if (rme32->fullduplex_mode) {
@@ -1076,11 +1076,11 @@ static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream)
}
static int
-snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
spin_lock(&rme32->lock);
snd_pcm_group_for_each(pos, substream) {
@@ -1144,33 +1144,33 @@ snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
/* pointer callback for halfduplex mode */
static snd_pcm_uframes_t
-snd_rme32_playback_pointer(snd_pcm_substream_t * substream)
+snd_rme32_playback_pointer(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog;
}
static snd_pcm_uframes_t
-snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
+snd_rme32_capture_pointer(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog;
}
/* ack and pointer callbacks for fullduplex mode */
-static void snd_rme32_pb_trans_copy(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes)
+static void snd_rme32_pb_trans_copy(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
substream->runtime->dma_area + rec->sw_data, bytes);
}
-static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
+static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_indirect_t *rec, *cprec;
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_indirect *rec, *cprec;
rec = &rme32->playback_pcm;
cprec = &rme32->capture_pcm;
@@ -1184,41 +1184,41 @@ static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
return 0;
}
-static void snd_rme32_cp_trans_copy(snd_pcm_substream_t *substream,
- snd_pcm_indirect_t *rec, size_t bytes)
+static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream,
+ struct snd_pcm_indirect *rec, size_t bytes)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
memcpy_fromio(substream->runtime->dma_area + rec->sw_data,
rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
bytes);
}
-static int snd_rme32_capture_fd_ack(snd_pcm_substream_t *substream)
+static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,
snd_rme32_cp_trans_copy);
return 0;
}
static snd_pcm_uframes_t
-snd_rme32_playback_fd_pointer(snd_pcm_substream_t * substream)
+snd_rme32_playback_fd_pointer(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm,
snd_rme32_pcm_byteptr(rme32));
}
static snd_pcm_uframes_t
-snd_rme32_capture_fd_pointer(snd_pcm_substream_t * substream)
+snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream)
{
- rme32_t *rme32 = snd_pcm_substream_chip(substream);
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm,
snd_rme32_pcm_byteptr(rme32));
}
/* for halfduplex mode */
-static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
+static struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
.open = snd_rme32_playback_spdif_open,
.close = snd_rme32_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1232,7 +1232,7 @@ static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
+static struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
.open = snd_rme32_capture_spdif_open,
.close = snd_rme32_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1245,7 +1245,7 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
+static struct snd_pcm_ops snd_rme32_playback_adat_ops = {
.open = snd_rme32_playback_adat_open,
.close = snd_rme32_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1258,7 +1258,7 @@ static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
+static struct snd_pcm_ops snd_rme32_capture_adat_ops = {
.open = snd_rme32_capture_adat_open,
.close = snd_rme32_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1271,7 +1271,7 @@ static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
};
/* for fullduplex mode */
-static snd_pcm_ops_t snd_rme32_playback_spdif_fd_ops = {
+static struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
.open = snd_rme32_playback_spdif_open,
.close = snd_rme32_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1283,7 +1283,7 @@ static snd_pcm_ops_t snd_rme32_playback_spdif_fd_ops = {
.ack = snd_rme32_playback_fd_ack,
};
-static snd_pcm_ops_t snd_rme32_capture_spdif_fd_ops = {
+static struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
.open = snd_rme32_capture_spdif_open,
.close = snd_rme32_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1295,7 +1295,7 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_fd_ops = {
.ack = snd_rme32_capture_fd_ack,
};
-static snd_pcm_ops_t snd_rme32_playback_adat_fd_ops = {
+static struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
.open = snd_rme32_playback_adat_open,
.close = snd_rme32_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1306,7 +1306,7 @@ static snd_pcm_ops_t snd_rme32_playback_adat_fd_ops = {
.ack = snd_rme32_playback_fd_ack,
};
-static snd_pcm_ops_t snd_rme32_capture_adat_fd_ops = {
+static struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
.open = snd_rme32_capture_adat_open,
.close = snd_rme32_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1319,7 +1319,7 @@ static snd_pcm_ops_t snd_rme32_capture_adat_fd_ops = {
static void snd_rme32_free(void *private_data)
{
- rme32_t *rme32 = (rme32_t *) private_data;
+ struct rme32 *rme32 = (struct rme32 *) private_data;
if (rme32 == NULL) {
return;
@@ -1340,20 +1340,20 @@ static void snd_rme32_free(void *private_data)
pci_disable_device(rme32->pci);
}
-static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm)
+static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm)
{
- rme32_t *rme32 = (rme32_t *) pcm->private_data;
+ struct rme32 *rme32 = (struct rme32 *) pcm->private_data;
rme32->spdif_pcm = NULL;
}
static void
-snd_rme32_free_adat_pcm(snd_pcm_t *pcm)
+snd_rme32_free_adat_pcm(struct snd_pcm *pcm)
{
- rme32_t *rme32 = (rme32_t *) pcm->private_data;
+ struct rme32 *rme32 = (struct rme32 *) pcm->private_data;
rme32->adat_pcm = NULL;
}
-static int __devinit snd_rme32_create(rme32_t * rme32)
+static int __devinit snd_rme32_create(struct rme32 * rme32)
{
struct pci_dev *pci = rme32->pci;
int err;
@@ -1479,10 +1479,10 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
*/
static void
-snd_rme32_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
{
int n;
- rme32_t *rme32 = (rme32_t *) entry->private_data;
+ struct rme32 *rme32 = (struct rme32 *) entry->private_data;
rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);
@@ -1573,9 +1573,9 @@ snd_rme32_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
}
}
-static void __devinit snd_rme32_proc_init(rme32_t * rme32)
+static void __devinit snd_rme32_proc_init(struct rme32 * rme32)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(rme32->card, "rme32", &entry))
snd_info_set_text_ops(entry, rme32, 1024, snd_rme32_proc_read);
@@ -1586,8 +1586,8 @@ static void __devinit snd_rme32_proc_init(rme32_t * rme32)
*/
static int
-snd_rme32_info_loopback_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+snd_rme32_info_loopback_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1596,10 +1596,10 @@ snd_rme32_info_loopback_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_get_loopback_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme32->lock);
ucontrol->value.integer.value[0] =
@@ -1608,10 +1608,10 @@ snd_rme32_get_loopback_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_put_loopback_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1630,10 +1630,10 @@ snd_rme32_put_loopback_control(snd_kcontrol_t * kcontrol,
}
static int
-snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+snd_rme32_info_inputtype_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1660,10 +1660,10 @@ snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
unsigned int items = 3;
spin_lock_irq(&rme32->lock);
@@ -1689,10 +1689,10 @@ snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change, items = 3;
@@ -1718,8 +1718,8 @@ snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
}
static int
-snd_rme32_info_clockmode_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+snd_rme32_info_clockmode_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = { "AutoSync",
"Internal 32.0kHz",
@@ -1737,10 +1737,10 @@ snd_rme32_info_clockmode_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_get_clockmode_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme32->lock);
ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32);
@@ -1748,10 +1748,10 @@ snd_rme32_get_clockmode_control(snd_kcontrol_t * kcontrol,
return 0;
}
static int
-snd_rme32_put_clockmode_control(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+snd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1763,7 +1763,7 @@ snd_rme32_put_clockmode_control(snd_kcontrol_t * kcontrol,
return change;
}
-static u32 snd_rme32_convert_from_aes(snd_aes_iec958_t * aes)
+static u32 snd_rme32_convert_from_aes(struct snd_aes_iec958 * aes)
{
u32 val = 0;
val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME32_WCR_PRO : 0;
@@ -1774,7 +1774,7 @@ static u32 snd_rme32_convert_from_aes(snd_aes_iec958_t * aes)
return val;
}
-static void snd_rme32_convert_to_aes(snd_aes_iec958_t * aes, u32 val)
+static void snd_rme32_convert_to_aes(struct snd_aes_iec958 * aes, u32 val)
{
aes->status[0] = ((val & RME32_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0);
if (val & RME32_WCR_PRO)
@@ -1783,28 +1783,28 @@ static void snd_rme32_convert_to_aes(snd_aes_iec958_t * aes, u32 val)
aes->status[0] |= (val & RME32_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
}
-static int snd_rme32_control_spdif_info(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_rme32_control_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme32_control_spdif_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_rme32_control_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
snd_rme32_convert_to_aes(&ucontrol->value.iec958,
rme32->wcreg_spdif);
return 0;
}
-static int snd_rme32_control_spdif_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -1816,30 +1816,30 @@ static int snd_rme32_control_spdif_put(snd_kcontrol_t * kcontrol,
return change;
}
-static int snd_rme32_control_spdif_stream_info(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_rme32_control_spdif_stream_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme32_control_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_rme32_control_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
snd_rme32_convert_to_aes(&ucontrol->value.iec958,
rme32->wcreg_spdif_stream);
return 0;
}
-static int snd_rme32_control_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
- rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
+ struct rme32 *rme32 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -1854,23 +1854,23 @@ static int snd_rme32_control_spdif_stream_put(snd_kcontrol_t * kcontrol,
return change;
}
-static int snd_rme32_control_spdif_mask_info(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_rme32_control_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme32_control_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
ucontrol->value.iec958.status[0] = kcontrol->private_value;
return 0;
}
-static snd_kcontrol_new_t snd_rme32_controls[] = {
+static struct snd_kcontrol_new snd_rme32_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1925,10 +1925,10 @@ static snd_kcontrol_new_t snd_rme32_controls[] = {
}
};
-static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32)
+static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32)
{
int idx, err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0)
@@ -1944,7 +1944,7 @@ static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32)
* Card initialisation
*/
-static void snd_rme32_card_free(snd_card_t * card)
+static void snd_rme32_card_free(struct snd_card *card)
{
snd_rme32_free(card->private_data);
}
@@ -1953,8 +1953,8 @@ static int __devinit
snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
- rme32_t *rme32;
- snd_card_t *card;
+ struct rme32 *rme32;
+ struct snd_card *card;
int err;
if (dev >= SNDRV_CARDS) {
@@ -1966,10 +1966,10 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
}
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(rme32_t))) == NULL)
+ sizeof(struct rme32))) == NULL)
return -ENOMEM;
card->private_free = snd_rme32_card_free;
- rme32 = (rme32_t *) card->private_data;
+ rme32 = (struct rme32 *) card->private_data;
rme32->card = card;
rme32->pci = pci;
snd_card_set_dev(card, &pci->dev);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 6d422ef64999..0e694b011dcc 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -201,7 +201,7 @@ MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
#define RME96_AD1855_VOL_BITS 10
-typedef struct snd_rme96 {
+struct rme96 {
spinlock_t lock;
int irq;
unsigned long port;
@@ -216,8 +216,8 @@ typedef struct snd_rme96 {
u8 rev; /* card revision number */
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
int playback_frlog; /* log2 of framesize */
int capture_frlog;
@@ -225,12 +225,12 @@ typedef struct snd_rme96 {
size_t playback_periodsize; /* in bytes, zero if not used */
size_t capture_periodsize; /* in bytes, zero if not used */
- snd_card_t *card;
- snd_pcm_t *spdif_pcm;
- snd_pcm_t *adat_pcm;
+ struct snd_card *card;
+ struct snd_pcm *spdif_pcm;
+ struct snd_pcm *adat_pcm;
struct pci_dev *pci;
- snd_kcontrol_t *spdif_ctl;
-} rme96_t;
+ struct snd_kcontrol *spdif_ctl;
+};
static struct pci_device_id snd_rme96_ids[] = {
{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
@@ -257,44 +257,44 @@ MODULE_DEVICE_TABLE(pci, snd_rme96_ids);
#define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1)
static int
-snd_rme96_playback_prepare(snd_pcm_substream_t *substream);
+snd_rme96_playback_prepare(struct snd_pcm_substream *substream);
static int
-snd_rme96_capture_prepare(snd_pcm_substream_t *substream);
+snd_rme96_capture_prepare(struct snd_pcm_substream *substream);
static int
-snd_rme96_playback_trigger(snd_pcm_substream_t *substream,
+snd_rme96_playback_trigger(struct snd_pcm_substream *substream,
int cmd);
static int
-snd_rme96_capture_trigger(snd_pcm_substream_t *substream,
+snd_rme96_capture_trigger(struct snd_pcm_substream *substream,
int cmd);
static snd_pcm_uframes_t
-snd_rme96_playback_pointer(snd_pcm_substream_t *substream);
+snd_rme96_playback_pointer(struct snd_pcm_substream *substream);
static snd_pcm_uframes_t
-snd_rme96_capture_pointer(snd_pcm_substream_t *substream);
+snd_rme96_capture_pointer(struct snd_pcm_substream *substream);
static void __devinit
-snd_rme96_proc_init(rme96_t *rme96);
+snd_rme96_proc_init(struct rme96 *rme96);
static int
-snd_rme96_create_switches(snd_card_t *card,
- rme96_t *rme96);
+snd_rme96_create_switches(struct snd_card *card,
+ struct rme96 *rme96);
static int
-snd_rme96_getinputtype(rme96_t *rme96);
+snd_rme96_getinputtype(struct rme96 *rme96);
static inline unsigned int
-snd_rme96_playback_ptr(rme96_t *rme96)
+snd_rme96_playback_ptr(struct rme96 *rme96)
{
return (readl(rme96->iobase + RME96_IO_GET_PLAY_POS)
& RME96_RCR_AUDIO_ADDR_MASK) >> rme96->playback_frlog;
}
static inline unsigned int
-snd_rme96_capture_ptr(rme96_t *rme96)
+snd_rme96_capture_ptr(struct rme96 *rme96)
{
return (readl(rme96->iobase + RME96_IO_GET_REC_POS)
& RME96_RCR_AUDIO_ADDR_MASK) >> rme96->capture_frlog;
@@ -315,12 +315,12 @@ snd_rme96_ratecode(int rate)
}
static int
-snd_rme96_playback_silence(snd_pcm_substream_t *substream,
+snd_rme96_playback_silence(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
count <<= rme96->playback_frlog;
pos <<= rme96->playback_frlog;
memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
@@ -329,13 +329,13 @@ snd_rme96_playback_silence(snd_pcm_substream_t *substream,
}
static int
-snd_rme96_playback_copy(snd_pcm_substream_t *substream,
+snd_rme96_playback_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src,
snd_pcm_uframes_t count)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
count <<= rme96->playback_frlog;
pos <<= rme96->playback_frlog;
copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
@@ -344,13 +344,13 @@ snd_rme96_playback_copy(snd_pcm_substream_t *substream,
}
static int
-snd_rme96_capture_copy(snd_pcm_substream_t *substream,
+snd_rme96_capture_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *dst,
snd_pcm_uframes_t count)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
count <<= rme96->capture_frlog;
pos <<= rme96->capture_frlog;
copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
@@ -361,7 +361,7 @@ snd_rme96_capture_copy(snd_pcm_substream_t *substream,
/*
* Digital output capabilites (S/PDIF)
*/
-static snd_pcm_hardware_t snd_rme96_playback_spdif_info =
+static struct snd_pcm_hardware snd_rme96_playback_spdif_info =
{
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -390,7 +390,7 @@ static snd_pcm_hardware_t snd_rme96_playback_spdif_info =
/*
* Digital input capabilites (S/PDIF)
*/
-static snd_pcm_hardware_t snd_rme96_capture_spdif_info =
+static struct snd_pcm_hardware snd_rme96_capture_spdif_info =
{
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -419,7 +419,7 @@ static snd_pcm_hardware_t snd_rme96_capture_spdif_info =
/*
* Digital output capabilites (ADAT)
*/
-static snd_pcm_hardware_t snd_rme96_playback_adat_info =
+static struct snd_pcm_hardware snd_rme96_playback_adat_info =
{
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -444,7 +444,7 @@ static snd_pcm_hardware_t snd_rme96_playback_adat_info =
/*
* Digital input capabilites (ADAT)
*/
-static snd_pcm_hardware_t snd_rme96_capture_adat_info =
+static struct snd_pcm_hardware snd_rme96_capture_adat_info =
{
.info = (SNDRV_PCM_INFO_MMAP_IOMEM |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -479,7 +479,7 @@ static snd_pcm_hardware_t snd_rme96_capture_adat_info =
* the volume.
*/
static void
-snd_rme96_write_SPI(rme96_t *rme96, u16 val)
+snd_rme96_write_SPI(struct rme96 *rme96, u16 val)
{
int i;
@@ -506,7 +506,7 @@ snd_rme96_write_SPI(rme96_t *rme96, u16 val)
}
static void
-snd_rme96_apply_dac_volume(rme96_t *rme96)
+snd_rme96_apply_dac_volume(struct rme96 *rme96)
{
if (RME96_DAC_IS_1852(rme96)) {
snd_rme96_write_SPI(rme96, (rme96->vol[0] << 2) | 0x0);
@@ -518,7 +518,7 @@ snd_rme96_apply_dac_volume(rme96_t *rme96)
}
static void
-snd_rme96_reset_dac(rme96_t *rme96)
+snd_rme96_reset_dac(struct rme96 *rme96)
{
writel(rme96->wcreg | RME96_WCR_PD,
rme96->iobase + RME96_IO_CONTROL_REGISTER);
@@ -526,14 +526,14 @@ snd_rme96_reset_dac(rme96_t *rme96)
}
static int
-snd_rme96_getmontracks(rme96_t *rme96)
+snd_rme96_getmontracks(struct rme96 *rme96)
{
return ((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_0) & 1) +
(((rme96->wcreg >> RME96_WCR_BITPOS_MONITOR_1) & 1) << 1);
}
static int
-snd_rme96_setmontracks(rme96_t *rme96,
+snd_rme96_setmontracks(struct rme96 *rme96,
int montracks)
{
if (montracks & 1) {
@@ -551,14 +551,14 @@ snd_rme96_setmontracks(rme96_t *rme96,
}
static int
-snd_rme96_getattenuation(rme96_t *rme96)
+snd_rme96_getattenuation(struct rme96 *rme96)
{
return ((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_0) & 1) +
(((rme96->wcreg >> RME96_WCR_BITPOS_GAIN_1) & 1) << 1);
}
static int
-snd_rme96_setattenuation(rme96_t *rme96,
+snd_rme96_setattenuation(struct rme96 *rme96,
int attenuation)
{
switch (attenuation) {
@@ -586,7 +586,7 @@ snd_rme96_setattenuation(rme96_t *rme96,
}
static int
-snd_rme96_capture_getrate(rme96_t *rme96,
+snd_rme96_capture_getrate(struct rme96 *rme96,
int *is_adat)
{
int n, rate;
@@ -649,7 +649,7 @@ snd_rme96_capture_getrate(rme96_t *rme96,
}
static int
-snd_rme96_playback_getrate(rme96_t *rme96)
+snd_rme96_playback_getrate(struct rme96 *rme96)
{
int rate, dummy;
@@ -679,7 +679,7 @@ snd_rme96_playback_getrate(rme96_t *rme96)
}
static int
-snd_rme96_playback_setrate(rme96_t *rme96,
+snd_rme96_playback_setrate(struct rme96 *rme96,
int rate)
{
int ds;
@@ -731,7 +731,7 @@ snd_rme96_playback_setrate(rme96_t *rme96,
}
static int
-snd_rme96_capture_analog_setrate(rme96_t *rme96,
+snd_rme96_capture_analog_setrate(struct rme96 *rme96,
int rate)
{
switch (rate) {
@@ -773,7 +773,7 @@ snd_rme96_capture_analog_setrate(rme96_t *rme96,
}
static int
-snd_rme96_setclockmode(rme96_t *rme96,
+snd_rme96_setclockmode(struct rme96 *rme96,
int mode)
{
switch (mode) {
@@ -801,7 +801,7 @@ snd_rme96_setclockmode(rme96_t *rme96,
}
static int
-snd_rme96_getclockmode(rme96_t *rme96)
+snd_rme96_getclockmode(struct rme96 *rme96)
{
if (rme96->areg & RME96_AR_WSEL) {
return RME96_CLOCKMODE_WORDCLOCK;
@@ -811,7 +811,7 @@ snd_rme96_getclockmode(rme96_t *rme96)
}
static int
-snd_rme96_setinputtype(rme96_t *rme96,
+snd_rme96_setinputtype(struct rme96 *rme96,
int type)
{
int n;
@@ -872,7 +872,7 @@ snd_rme96_setinputtype(rme96_t *rme96,
}
static int
-snd_rme96_getinputtype(rme96_t *rme96)
+snd_rme96_getinputtype(struct rme96 *rme96)
{
if (rme96->areg & RME96_AR_ANALOG) {
return RME96_INPUT_ANALOG;
@@ -882,7 +882,7 @@ snd_rme96_getinputtype(rme96_t *rme96)
}
static void
-snd_rme96_setframelog(rme96_t *rme96,
+snd_rme96_setframelog(struct rme96 *rme96,
int n_channels,
int is_playback)
{
@@ -904,7 +904,7 @@ snd_rme96_setframelog(rme96_t *rme96,
}
static int
-snd_rme96_playback_setformat(rme96_t *rme96,
+snd_rme96_playback_setformat(struct rme96 *rme96,
int format)
{
switch (format) {
@@ -922,7 +922,7 @@ snd_rme96_playback_setformat(rme96_t *rme96,
}
static int
-snd_rme96_capture_setformat(rme96_t *rme96,
+snd_rme96_capture_setformat(struct rme96 *rme96,
int format)
{
switch (format) {
@@ -940,7 +940,7 @@ snd_rme96_capture_setformat(rme96_t *rme96,
}
static void
-snd_rme96_set_period_properties(rme96_t *rme96,
+snd_rme96_set_period_properties(struct rme96 *rme96,
size_t period_bytes)
{
switch (period_bytes) {
@@ -959,11 +959,11 @@ snd_rme96_set_period_properties(rme96_t *rme96,
}
static int
-snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err, rate, dummy;
runtime->dma_area = (void __force *)(rme96->iobase +
@@ -1012,11 +1012,11 @@ snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
}
static int
-snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+snd_rme96_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err, isadat, rate;
runtime->dma_area = (void __force *)(rme96->iobase +
@@ -1066,7 +1066,7 @@ snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
}
static void
-snd_rme96_playback_start(rme96_t *rme96,
+snd_rme96_playback_start(struct rme96 *rme96,
int from_pause)
{
if (!from_pause) {
@@ -1078,7 +1078,7 @@ snd_rme96_playback_start(rme96_t *rme96,
}
static void
-snd_rme96_capture_start(rme96_t *rme96,
+snd_rme96_capture_start(struct rme96 *rme96,
int from_pause)
{
if (!from_pause) {
@@ -1090,7 +1090,7 @@ snd_rme96_capture_start(rme96_t *rme96,
}
static void
-snd_rme96_playback_stop(rme96_t *rme96)
+snd_rme96_playback_stop(struct rme96 *rme96)
{
/*
* Check if there is an unconfirmed IRQ, if so confirm it, or else
@@ -1105,7 +1105,7 @@ snd_rme96_playback_stop(rme96_t *rme96)
}
static void
-snd_rme96_capture_stop(rme96_t *rme96)
+snd_rme96_capture_stop(struct rme96 *rme96)
{
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
if (rme96->rcreg & RME96_RCR_IRQ_2) {
@@ -1120,7 +1120,7 @@ snd_rme96_interrupt(int irq,
void *dev_id,
struct pt_regs *regs)
{
- rme96_t *rme96 = (rme96_t *)dev_id;
+ struct rme96 *rme96 = (struct rme96 *)dev_id;
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
/* fastpath out, to ease interrupt sharing */
@@ -1145,18 +1145,18 @@ snd_rme96_interrupt(int irq,
static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE };
-static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = {
.count = ARRAY_SIZE(period_bytes),
.list = period_bytes,
.mask = 0
};
static int
-snd_rme96_playback_spdif_open(snd_pcm_substream_t *substream)
+snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
{
int rate, dummy;
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -1191,11 +1191,11 @@ snd_rme96_playback_spdif_open(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
+snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream)
{
int isadat, rate;
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -1226,11 +1226,11 @@ snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_playback_adat_open(snd_pcm_substream_t *substream)
+snd_rme96_playback_adat_open(struct snd_pcm_substream *substream)
{
int rate, dummy;
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -1260,11 +1260,11 @@ snd_rme96_playback_adat_open(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
+snd_rme96_capture_adat_open(struct snd_pcm_substream *substream)
{
int isadat, rate;
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_set_sync(substream);
@@ -1297,9 +1297,9 @@ snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_playback_close(snd_pcm_substream_t *substream)
+snd_rme96_playback_close(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
int spdif = 0;
spin_lock_irq(&rme96->lock);
@@ -1319,9 +1319,9 @@ snd_rme96_playback_close(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_capture_close(snd_pcm_substream_t *substream)
+snd_rme96_capture_close(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme96->lock);
if (RME96_ISRECORDING(rme96)) {
@@ -1334,9 +1334,9 @@ snd_rme96_capture_close(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_playback_prepare(snd_pcm_substream_t *substream)
+snd_rme96_playback_prepare(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme96->lock);
if (RME96_ISPLAYING(rme96)) {
@@ -1348,9 +1348,9 @@ snd_rme96_playback_prepare(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_capture_prepare(snd_pcm_substream_t *substream)
+snd_rme96_capture_prepare(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme96->lock);
if (RME96_ISRECORDING(rme96)) {
@@ -1362,10 +1362,10 @@ snd_rme96_capture_prepare(snd_pcm_substream_t *substream)
}
static int
-snd_rme96_playback_trigger(snd_pcm_substream_t *substream,
+snd_rme96_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -1405,10 +1405,10 @@ snd_rme96_playback_trigger(snd_pcm_substream_t *substream,
}
static int
-snd_rme96_capture_trigger(snd_pcm_substream_t *substream,
+snd_rme96_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -1449,20 +1449,20 @@ snd_rme96_capture_trigger(snd_pcm_substream_t *substream,
}
static snd_pcm_uframes_t
-snd_rme96_playback_pointer(snd_pcm_substream_t *substream)
+snd_rme96_playback_pointer(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
return snd_rme96_playback_ptr(rme96);
}
static snd_pcm_uframes_t
-snd_rme96_capture_pointer(snd_pcm_substream_t *substream)
+snd_rme96_capture_pointer(struct snd_pcm_substream *substream)
{
- rme96_t *rme96 = snd_pcm_substream_chip(substream);
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
return snd_rme96_capture_ptr(rme96);
}
-static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
+static struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
.open = snd_rme96_playback_spdif_open,
.close = snd_rme96_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1475,7 +1475,7 @@ static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme96_capture_spdif_ops = {
+static struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
.open = snd_rme96_capture_spdif_open,
.close = snd_rme96_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1487,7 +1487,7 @@ static snd_pcm_ops_t snd_rme96_capture_spdif_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme96_playback_adat_ops = {
+static struct snd_pcm_ops snd_rme96_playback_adat_ops = {
.open = snd_rme96_playback_adat_open,
.close = snd_rme96_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1500,7 +1500,7 @@ static snd_pcm_ops_t snd_rme96_playback_adat_ops = {
.mmap = snd_pcm_lib_mmap_iomem,
};
-static snd_pcm_ops_t snd_rme96_capture_adat_ops = {
+static struct snd_pcm_ops snd_rme96_capture_adat_ops = {
.open = snd_rme96_capture_adat_open,
.close = snd_rme96_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1515,7 +1515,7 @@ static snd_pcm_ops_t snd_rme96_capture_adat_ops = {
static void
snd_rme96_free(void *private_data)
{
- rme96_t *rme96 = (rme96_t *)private_data;
+ struct rme96 *rme96 = (struct rme96 *)private_data;
if (rme96 == NULL) {
return;
@@ -1540,21 +1540,21 @@ snd_rme96_free(void *private_data)
}
static void
-snd_rme96_free_spdif_pcm(snd_pcm_t *pcm)
+snd_rme96_free_spdif_pcm(struct snd_pcm *pcm)
{
- rme96_t *rme96 = (rme96_t *) pcm->private_data;
+ struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
rme96->spdif_pcm = NULL;
}
static void
-snd_rme96_free_adat_pcm(snd_pcm_t *pcm)
+snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
{
- rme96_t *rme96 = (rme96_t *) pcm->private_data;
+ struct rme96 *rme96 = (struct rme96 *) pcm->private_data;
rme96->adat_pcm = NULL;
}
static int __devinit
-snd_rme96_create(rme96_t *rme96)
+snd_rme96_create(struct rme96 *rme96)
{
struct pci_dev *pci = rme96->pci;
int err;
@@ -1671,10 +1671,10 @@ snd_rme96_create(rme96_t *rme96)
*/
static void
-snd_rme96_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
int n;
- rme96_t *rme96 = (rme96_t *)entry->private_data;
+ struct rme96 *rme96 = (struct rme96 *)entry->private_data;
rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
@@ -1800,9 +1800,9 @@ snd_rme96_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
}
static void __devinit
-snd_rme96_proc_init(rme96_t *rme96)
+snd_rme96_proc_init(struct rme96 *rme96)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(rme96->card, "rme96", &entry))
snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read);
@@ -1813,7 +1813,7 @@ snd_rme96_proc_init(rme96_t *rme96)
*/
static int
-snd_rme96_info_loopback_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_info_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1822,9 +1822,9 @@ snd_rme96_info_loopback_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
static int
-snd_rme96_get_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_get_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme96->lock);
ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1;
@@ -1832,9 +1832,9 @@ snd_rme96_get_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
static int
-snd_rme96_put_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_put_loopback_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1849,10 +1849,10 @@ snd_rme96_put_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
}
static int
-snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_info_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" };
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1886,9 +1886,9 @@ snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
static int
-snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_get_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int items = 3;
spin_lock_irq(&rme96->lock);
@@ -1925,9 +1925,9 @@ snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
static int
-snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_put_inputtype_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change, items = 3;
@@ -1967,7 +1967,7 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
static int
-snd_rme96_info_clockmode_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_info_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = { "AutoSync", "Internal", "Word" };
@@ -1981,9 +1981,9 @@ snd_rme96_info_clockmode_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
static int
-snd_rme96_get_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_get_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme96->lock);
ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96);
@@ -1991,9 +1991,9 @@ snd_rme96_get_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
static int
-snd_rme96_put_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_put_clockmode_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2006,7 +2006,7 @@ snd_rme96_put_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
static int
-snd_rme96_info_attenuation_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_info_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = { "0 dB", "-6 dB", "-12 dB", "-18 dB" };
@@ -2020,9 +2020,9 @@ snd_rme96_info_attenuation_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
static int
-snd_rme96_get_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_get_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme96->lock);
ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96);
@@ -2030,9 +2030,9 @@ snd_rme96_get_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
static int
-snd_rme96_put_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_put_attenuation_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2046,7 +2046,7 @@ snd_rme96_put_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
}
static int
-snd_rme96_info_montracks_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_info_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = { "1+2", "3+4", "5+6", "7+8" };
@@ -2060,9 +2060,9 @@ snd_rme96_info_montracks_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
static int
-snd_rme96_get_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_get_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme96->lock);
ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96);
@@ -2070,9 +2070,9 @@ snd_rme96_get_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
static int
-snd_rme96_put_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+snd_rme96_put_montracks_control(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2084,7 +2084,7 @@ snd_rme96_put_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return change;
}
-static u32 snd_rme96_convert_from_aes(snd_aes_iec958_t *aes)
+static u32 snd_rme96_convert_from_aes(struct snd_aes_iec958 *aes)
{
u32 val = 0;
val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME96_WCR_PRO : 0;
@@ -2096,7 +2096,7 @@ static u32 snd_rme96_convert_from_aes(snd_aes_iec958_t *aes)
return val;
}
-static void snd_rme96_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
+static void snd_rme96_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
{
aes->status[0] = ((val & RME96_WCR_PRO) ? IEC958_AES0_PROFESSIONAL : 0) |
((val & RME96_WCR_DOLBY) ? IEC958_AES0_NONAUDIO : 0);
@@ -2106,24 +2106,24 @@ static void snd_rme96_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
aes->status[0] |= (val & RME96_WCR_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
}
-static int snd_rme96_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme96_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme96_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme96_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif);
return 0;
}
-static int snd_rme96_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme96_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -2135,24 +2135,24 @@ static int snd_rme96_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
return change;
}
-static int snd_rme96_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme96_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme96_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme96_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream);
return 0;
}
-static int snd_rme96_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme96_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -2167,23 +2167,23 @@ static int snd_rme96_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl
return change;
}
-static int snd_rme96_control_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme96_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme96_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme96_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = kcontrol->private_value;
return 0;
}
static int
-snd_rme96_dac_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+snd_rme96_dac_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -2193,9 +2193,9 @@ snd_rme96_dac_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
}
static int
-snd_rme96_dac_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+snd_rme96_dac_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme96->lock);
u->value.integer.value[0] = rme96->vol[0];
@@ -2206,9 +2206,9 @@ snd_rme96_dac_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
}
static int
-snd_rme96_dac_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
+snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u)
{
- rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
+ struct rme96 *rme96 = snd_kcontrol_chip(kcontrol);
int change = 0;
if (!RME96_HAS_ANALOG_OUT(rme96)) {
@@ -2231,7 +2231,7 @@ snd_rme96_dac_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
return change;
}
-static snd_kcontrol_new_t snd_rme96_controls[] = {
+static struct snd_kcontrol_new snd_rme96_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -2312,11 +2312,11 @@ static snd_kcontrol_new_t snd_rme96_controls[] = {
};
static int
-snd_rme96_create_switches(snd_card_t *card,
- rme96_t *rme96)
+snd_rme96_create_switches(struct snd_card *card,
+ struct rme96 *rme96)
{
int idx, err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
for (idx = 0; idx < 7; idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme96_controls[idx], rme96))) < 0)
@@ -2338,7 +2338,7 @@ snd_rme96_create_switches(snd_card_t *card,
* Card initialisation
*/
-static void snd_rme96_card_free(snd_card_t *card)
+static void snd_rme96_card_free(struct snd_card *card)
{
snd_rme96_free(card->private_data);
}
@@ -2348,8 +2348,8 @@ snd_rme96_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- rme96_t *rme96;
- snd_card_t *card;
+ struct rme96 *rme96;
+ struct snd_card *card;
int err;
u8 val;
@@ -2361,10 +2361,10 @@ snd_rme96_probe(struct pci_dev *pci,
return -ENOENT;
}
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(rme96_t))) == NULL)
+ sizeof(struct rme96))) == NULL)
return -ENOMEM;
card->private_free = snd_rme96_card_free;
- rme96 = (rme96_t *)card->private_data;
+ rme96 = (struct rme96 *)card->private_data;
rme96->card = card;
rme96->pci = pci;
snd_card_set_dev(card, &pci->dev);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index d15ffb3e9b0a..ebf7a2b86c23 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -394,11 +394,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
#endif
#endif
-typedef struct _hdsp hdsp_t;
-typedef struct _hdsp_midi hdsp_midi_t;
-typedef struct _hdsp_9632_meters hdsp_9632_meters_t;
-
-struct _hdsp_9632_meters {
+struct hdsp_9632_meters {
u32 input_peak[16];
u32 playback_peak[16];
u32 output_peak[16];
@@ -414,23 +410,23 @@ struct _hdsp_9632_meters {
u32 xxx_rms_high[16];
};
-struct _hdsp_midi {
- hdsp_t *hdsp;
+struct hdsp_midi {
+ struct hdsp *hdsp;
int id;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *input;
- snd_rawmidi_substream_t *output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *input;
+ struct snd_rawmidi_substream *output;
char istimer; /* timer in use */
struct timer_list timer;
spinlock_t lock;
int pending;
};
-struct _hdsp {
+struct hdsp {
spinlock_t lock;
- snd_pcm_substream_t *capture_substream;
- snd_pcm_substream_t *playback_substream;
- hdsp_midi_t midi[2];
+ struct snd_pcm_substream *capture_substream;
+ struct snd_pcm_substream *playback_substream;
+ struct hdsp_midi midi[2];
struct tasklet_struct midi_tasklet;
int use_midi_tasklet;
int precise_ptr;
@@ -440,7 +436,7 @@ struct _hdsp {
u32 creg_spdif_stream;
int clock_source_locked;
char *card_name; /* digiface/multiface */
- HDSP_IO_Type io_type; /* ditto, but for code use */
+ enum HDSP_IO_Type io_type; /* ditto, but for code use */
unsigned short firmware_rev;
unsigned short state; /* stores state bits */
u32 firmware_cache[24413]; /* this helps recover from accidental iobox power failure */
@@ -467,11 +463,11 @@ struct _hdsp {
int irq;
unsigned long port;
void __iomem *iobase;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_hwdep_t *hwdep;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_hwdep *hwdep;
struct pci_dev *pci;
- snd_kcontrol_t *spdif_ctl;
+ struct snd_kcontrol *spdif_ctl;
unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
};
@@ -585,17 +581,17 @@ static struct pci_device_id snd_hdsp_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
/* prototypes */
-static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
-static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
-static int snd_hdsp_enable_io (hdsp_t *hdsp);
-static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
-static void snd_hdsp_initialize_channels (hdsp_t *hdsp);
-static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
-static int hdsp_autosync_ref(hdsp_t *hdsp);
-static int snd_hdsp_set_defaults(hdsp_t *hdsp);
-static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
-
-static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp);
+static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp);
+static int snd_hdsp_enable_io (struct hdsp *hdsp);
+static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp);
+static void snd_hdsp_initialize_channels (struct hdsp *hdsp);
+static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout);
+static int hdsp_autosync_ref(struct hdsp *hdsp);
+static int snd_hdsp_set_defaults(struct hdsp *hdsp);
+static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp);
+
+static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
{
switch (hdsp->firmware_rev) {
case 0xa:
@@ -608,7 +604,7 @@ static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
}
}
-static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
{
switch (hdsp->firmware_rev) {
case 0xa:
@@ -621,17 +617,17 @@ static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
}
}
-static void hdsp_write(hdsp_t *hdsp, int reg, int val)
+static void hdsp_write(struct hdsp *hdsp, int reg, int val)
{
writel(val, hdsp->iobase + reg);
}
-static unsigned int hdsp_read(hdsp_t *hdsp, int reg)
+static unsigned int hdsp_read(struct hdsp *hdsp, int reg)
{
return readl (hdsp->iobase + reg);
}
-static int hdsp_check_for_iobox (hdsp_t *hdsp)
+static int hdsp_check_for_iobox (struct hdsp *hdsp)
{
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
@@ -644,7 +640,7 @@ static int hdsp_check_for_iobox (hdsp_t *hdsp)
}
-static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
+static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
int i;
unsigned long flags;
@@ -699,7 +695,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
return 0;
}
-static int hdsp_get_iobox_version (hdsp_t *hdsp)
+static int hdsp_get_iobox_version (struct hdsp *hdsp)
{
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
@@ -730,7 +726,7 @@ static int hdsp_get_iobox_version (hdsp_t *hdsp)
}
-static int hdsp_check_for_firmware (hdsp_t *hdsp, int show_err)
+static int hdsp_check_for_firmware (struct hdsp *hdsp, int show_err)
{
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
@@ -751,7 +747,7 @@ static int hdsp_check_for_firmware (hdsp_t *hdsp, int show_err)
}
-static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
+static int hdsp_fifo_wait(struct hdsp *hdsp, int count, int timeout)
{
int i;
@@ -776,7 +772,7 @@ static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
return -1;
}
-static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
+static int hdsp_read_gain (struct hdsp *hdsp, unsigned int addr)
{
if (addr >= HDSP_MATRIX_MIXER_SIZE)
return 0;
@@ -784,7 +780,7 @@ static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
return hdsp->mixer_matrix[addr];
}
-static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
+static int hdsp_write_gain(struct hdsp *hdsp, unsigned int addr, unsigned short data)
{
unsigned int ad;
@@ -844,7 +840,7 @@ static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
return 0;
}
-static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
+static int snd_hdsp_use_is_exclusive(struct hdsp *hdsp)
{
unsigned long flags;
int ret = 1;
@@ -857,7 +853,7 @@ static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
return ret;
}
-static int hdsp_external_sample_rate (hdsp_t *hdsp)
+static int hdsp_external_sample_rate (struct hdsp *hdsp)
{
unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
@@ -874,7 +870,7 @@ static int hdsp_external_sample_rate (hdsp_t *hdsp)
}
}
-static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
+static int hdsp_spdif_sample_rate(struct hdsp *hdsp)
{
unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
@@ -905,12 +901,12 @@ static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
return 0;
}
-static void hdsp_compute_period_size(hdsp_t *hdsp)
+static void hdsp_compute_period_size(struct hdsp *hdsp)
{
hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
}
-static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp)
+static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
{
int position;
@@ -925,29 +921,29 @@ static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp)
return position;
}
-static void hdsp_reset_hw_pointer(hdsp_t *hdsp)
+static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
{
hdsp_write (hdsp, HDSP_resetPointer, 0);
}
-static void hdsp_start_audio(hdsp_t *s)
+static void hdsp_start_audio(struct hdsp *s)
{
s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
hdsp_write(s, HDSP_controlRegister, s->control_register);
}
-static void hdsp_stop_audio(hdsp_t *s)
+static void hdsp_stop_audio(struct hdsp *s)
{
s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
hdsp_write(s, HDSP_controlRegister, s->control_register);
}
-static void hdsp_silence_playback(hdsp_t *hdsp)
+static void hdsp_silence_playback(struct hdsp *hdsp)
{
memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
}
-static int hdsp_set_interrupt_interval(hdsp_t *s, unsigned int frames)
+static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
{
int n;
@@ -972,7 +968,7 @@ static int hdsp_set_interrupt_interval(hdsp_t *s, unsigned int frames)
return 0;
}
-static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
+static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
{
int reject_if_open = 0;
int current_rate;
@@ -1114,7 +1110,7 @@ static int hdsp_set_rate(hdsp_t *hdsp, int rate, int called_internally)
MIDI
----------------------------------------------------------------------------*/
-static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
+static unsigned char snd_hdsp_midi_read_byte (struct hdsp *hdsp, int id)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -1123,7 +1119,7 @@ static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
return hdsp_read(hdsp, HDSP_midiDataIn0);
}
-static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
+static void snd_hdsp_midi_write_byte (struct hdsp *hdsp, int id, int val)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -1132,7 +1128,7 @@ static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
hdsp_write(hdsp, HDSP_midiDataOut0, val);
}
-static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_input_available (struct hdsp *hdsp, int id)
{
if (id)
return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
@@ -1140,7 +1136,7 @@ static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
return (hdsp_read(hdsp, HDSP_midiStatusIn0) & 0xff);
}
-static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id)
{
int fifo_bytes_used;
@@ -1155,13 +1151,13 @@ static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
return 0;
}
-static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
+static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id)
{
while (snd_hdsp_midi_input_available (hdsp, id))
snd_hdsp_midi_read_byte (hdsp, id);
}
-static int snd_hdsp_midi_output_write (hdsp_midi_t *hmidi)
+static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi)
{
unsigned long flags;
int n_pending;
@@ -1189,7 +1185,7 @@ static int snd_hdsp_midi_output_write (hdsp_midi_t *hmidi)
return 0;
}
-static int snd_hdsp_midi_input_read (hdsp_midi_t *hmidi)
+static int snd_hdsp_midi_input_read (struct hdsp_midi *hmidi)
{
unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
unsigned long flags;
@@ -1221,14 +1217,14 @@ static int snd_hdsp_midi_input_read (hdsp_midi_t *hmidi)
return snd_hdsp_midi_output_write (hmidi);
}
-static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_hdsp_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- hdsp_t *hdsp;
- hdsp_midi_t *hmidi;
+ struct hdsp *hdsp;
+ struct hdsp_midi *hmidi;
unsigned long flags;
u32 ie;
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
hdsp = hmidi->hdsp;
ie = hmidi->id ? HDSP_Midi1InterruptEnable : HDSP_Midi0InterruptEnable;
spin_lock_irqsave (&hdsp->lock, flags);
@@ -1248,7 +1244,7 @@ static void snd_hdsp_midi_input_trigger(snd_rawmidi_substream_t * substream, int
static void snd_hdsp_midi_output_timer(unsigned long data)
{
- hdsp_midi_t *hmidi = (hdsp_midi_t *) data;
+ struct hdsp_midi *hmidi = (struct hdsp_midi *) data;
unsigned long flags;
snd_hdsp_midi_output_write(hmidi);
@@ -1268,12 +1264,12 @@ static void snd_hdsp_midi_output_timer(unsigned long data)
spin_unlock_irqrestore (&hmidi->lock, flags);
}
-static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_hdsp_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- hdsp_midi_t *hmidi;
+ struct hdsp_midi *hmidi;
unsigned long flags;
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
spin_lock_irqsave (&hmidi->lock, flags);
if (up) {
if (!hmidi->istimer) {
@@ -1293,11 +1289,11 @@ static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, in
snd_hdsp_midi_output_write(hmidi);
}
-static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_hdsp_midi_input_open(struct snd_rawmidi_substream *substream)
{
- hdsp_midi_t *hmidi;
+ struct hdsp_midi *hmidi;
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
hmidi->input = substream;
@@ -1306,11 +1302,11 @@ static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_hdsp_midi_output_open(struct snd_rawmidi_substream *substream)
{
- hdsp_midi_t *hmidi;
+ struct hdsp_midi *hmidi;
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = substream;
spin_unlock_irq (&hmidi->lock);
@@ -1318,13 +1314,13 @@ static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_hdsp_midi_input_close(struct snd_rawmidi_substream *substream)
{
- hdsp_midi_t *hmidi;
+ struct hdsp_midi *hmidi;
snd_hdsp_midi_input_trigger (substream, 0);
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->input = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1332,13 +1328,13 @@ static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_hdsp_midi_output_close(struct snd_rawmidi_substream *substream)
{
- hdsp_midi_t *hmidi;
+ struct hdsp_midi *hmidi;
snd_hdsp_midi_output_trigger (substream, 0);
- hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdsp_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1346,21 +1342,21 @@ static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static snd_rawmidi_ops_t snd_hdsp_midi_output =
+static struct snd_rawmidi_ops snd_hdsp_midi_output =
{
.open = snd_hdsp_midi_output_open,
.close = snd_hdsp_midi_output_close,
.trigger = snd_hdsp_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_hdsp_midi_input =
+static struct snd_rawmidi_ops snd_hdsp_midi_input =
{
.open = snd_hdsp_midi_input_open,
.close = snd_hdsp_midi_input_close,
.trigger = snd_hdsp_midi_input_trigger,
};
-static int __devinit snd_hdsp_create_midi (snd_card_t *card, hdsp_t *hdsp, int id)
+static int __devinit snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int id)
{
char buf[32];
@@ -1394,7 +1390,7 @@ static int __devinit snd_hdsp_create_midi (snd_card_t *card, hdsp_t *hdsp, int i
Control Interface
----------------------------------------------------------------------------*/
-static u32 snd_hdsp_convert_from_aes(snd_aes_iec958_t *aes)
+static u32 snd_hdsp_convert_from_aes(struct snd_aes_iec958 *aes)
{
u32 val = 0;
val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? HDSP_SPDIFProfessional : 0;
@@ -1406,7 +1402,7 @@ static u32 snd_hdsp_convert_from_aes(snd_aes_iec958_t *aes)
return val;
}
-static void snd_hdsp_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
+static void snd_hdsp_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
{
aes->status[0] = ((val & HDSP_SPDIFProfessional) ? IEC958_AES0_PROFESSIONAL : 0) |
((val & HDSP_SPDIFNonAudio) ? IEC958_AES0_NONAUDIO : 0);
@@ -1416,24 +1412,24 @@ static void snd_hdsp_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
aes->status[0] |= (val & HDSP_SPDIFEmphasis) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
}
-static int snd_hdsp_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
return 0;
}
-static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -1445,24 +1441,24 @@ static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
return change;
}
-static int snd_hdsp_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
return 0;
}
-static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -1476,14 +1472,14 @@ static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_
return change;
}
-static int snd_hdsp_control_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_hdsp_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = kcontrol->private_value;
return 0;
@@ -1497,12 +1493,12 @@ static int snd_hdsp_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_el
.get = snd_hdsp_get_spdif_in, \
.put = snd_hdsp_put_spdif_in }
-static unsigned int hdsp_spdif_in(hdsp_t *hdsp)
+static unsigned int hdsp_spdif_in(struct hdsp *hdsp)
{
return hdsp_decode_spdif_in(hdsp->control_register & HDSP_SPDIFInputMask);
}
-static int hdsp_set_spdif_input(hdsp_t *hdsp, int in)
+static int hdsp_set_spdif_input(struct hdsp *hdsp, int in)
{
hdsp->control_register &= ~HDSP_SPDIFInputMask;
hdsp->control_register |= hdsp_encode_spdif_in(in);
@@ -1510,10 +1506,10 @@ static int hdsp_set_spdif_input(hdsp_t *hdsp, int in)
return 0;
}
-static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1524,17 +1520,17 @@ static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
return 0;
}
-static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1554,12 +1550,12 @@ static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_out, .put = snd_hdsp_put_spdif_out }
-static int hdsp_spdif_out(hdsp_t *hdsp)
+static int hdsp_spdif_out(struct hdsp *hdsp)
{
return (hdsp->control_register & HDSP_SPDIFOpticalOut) ? 1 : 0;
}
-static int hdsp_set_spdif_output(hdsp_t *hdsp, int out)
+static int hdsp_set_spdif_output(struct hdsp *hdsp, int out)
{
if (out)
hdsp->control_register |= HDSP_SPDIFOpticalOut;
@@ -1569,7 +1565,7 @@ static int hdsp_set_spdif_output(hdsp_t *hdsp, int out)
return 0;
}
-static int snd_hdsp_info_spdif_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_spdif_bits(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1578,17 +1574,17 @@ static int snd_hdsp_info_spdif_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
return 0;
}
-static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1607,12 +1603,12 @@ static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_professional, .put = snd_hdsp_put_spdif_professional }
-static int hdsp_spdif_professional(hdsp_t *hdsp)
+static int hdsp_spdif_professional(struct hdsp *hdsp)
{
return (hdsp->control_register & HDSP_SPDIFProfessional) ? 1 : 0;
}
-static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val)
+static int hdsp_set_spdif_professional(struct hdsp *hdsp, int val)
{
if (val)
hdsp->control_register |= HDSP_SPDIFProfessional;
@@ -1622,17 +1618,17 @@ static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val)
return 0;
}
-static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
return 0;
}
-static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_spdif_professional(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1651,12 +1647,12 @@ static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_el
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_emphasis, .put = snd_hdsp_put_spdif_emphasis }
-static int hdsp_spdif_emphasis(hdsp_t *hdsp)
+static int hdsp_spdif_emphasis(struct hdsp *hdsp)
{
return (hdsp->control_register & HDSP_SPDIFEmphasis) ? 1 : 0;
}
-static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val)
+static int hdsp_set_spdif_emphasis(struct hdsp *hdsp, int val)
{
if (val)
hdsp->control_register |= HDSP_SPDIFEmphasis;
@@ -1666,17 +1662,17 @@ static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val)
return 0;
}
-static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
return 0;
}
-static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_spdif_emphasis(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1695,12 +1691,12 @@ static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
.info = snd_hdsp_info_spdif_bits, \
.get = snd_hdsp_get_spdif_nonaudio, .put = snd_hdsp_put_spdif_nonaudio }
-static int hdsp_spdif_nonaudio(hdsp_t *hdsp)
+static int hdsp_spdif_nonaudio(struct hdsp *hdsp)
{
return (hdsp->control_register & HDSP_SPDIFNonAudio) ? 1 : 0;
}
-static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val)
+static int hdsp_set_spdif_nonaudio(struct hdsp *hdsp, int val)
{
if (val)
hdsp->control_register |= HDSP_SPDIFNonAudio;
@@ -1710,17 +1706,17 @@ static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val)
return 0;
}
-static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
return 0;
}
-static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_spdif_nonaudio(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1743,10 +1739,10 @@ static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
.get = snd_hdsp_get_spdif_sample_rate \
}
-static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1757,9 +1753,9 @@ static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
switch (hdsp_spdif_sample_rate(hdsp)) {
case 32000:
@@ -1804,16 +1800,16 @@ static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_ele
.get = snd_hdsp_get_system_sample_rate \
}
-static int snd_hdsp_info_system_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
return 0;
}
-static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_system_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
return 0;
@@ -1828,9 +1824,9 @@ static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_el
.get = snd_hdsp_get_autosync_sample_rate \
}
-static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1841,9 +1837,9 @@ static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_
return 0;
}
-static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
switch (hdsp_external_sample_rate(hdsp)) {
case 32000:
@@ -1888,7 +1884,7 @@ static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_
.get = snd_hdsp_get_system_clock_mode \
}
-static int hdsp_system_clock_mode(hdsp_t *hdsp)
+static int hdsp_system_clock_mode(struct hdsp *hdsp)
{
if (hdsp->control_register & HDSP_ClockModeMaster)
return 0;
@@ -1897,7 +1893,7 @@ static int hdsp_system_clock_mode(hdsp_t *hdsp)
return 1;
}
-static int snd_hdsp_info_system_clock_mode(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"Master", "Slave" };
@@ -1910,9 +1906,9 @@ static int snd_hdsp_info_system_clock_mode(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_system_clock_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
return 0;
@@ -1927,7 +1923,7 @@ static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_ele
.put = snd_hdsp_put_clock_source \
}
-static int hdsp_clock_source(hdsp_t *hdsp)
+static int hdsp_clock_source(struct hdsp *hdsp)
{
if (hdsp->control_register & HDSP_ClockModeMaster) {
switch (hdsp->system_sample_rate) {
@@ -1957,7 +1953,7 @@ static int hdsp_clock_source(hdsp_t *hdsp)
}
}
-static int hdsp_set_clock_source(hdsp_t *hdsp, int mode)
+static int hdsp_set_clock_source(struct hdsp *hdsp, int mode)
{
int rate;
switch (mode) {
@@ -2006,10 +2002,10 @@ static int hdsp_set_clock_source(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2023,17 +2019,17 @@ static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
return 0;
}
-static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_clock_source(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2057,7 +2053,7 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return change;
}
-static int snd_hdsp_info_clock_source_lock(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2066,17 +2062,17 @@ static int snd_hdsp_info_clock_source_lock(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_hdsp_get_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = hdsp->clock_source_locked;
return 0;
}
-static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_clock_source_lock(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
change = (int)ucontrol->value.integer.value[0] != hdsp->clock_source_locked;
@@ -2094,7 +2090,7 @@ static int snd_hdsp_put_clock_source_lock(snd_kcontrol_t * kcontrol, snd_ctl_ele
.put = snd_hdsp_put_da_gain \
}
-static int hdsp_da_gain(hdsp_t *hdsp)
+static int hdsp_da_gain(struct hdsp *hdsp)
{
switch (hdsp->control_register & HDSP_DAGainMask) {
case HDSP_DAGainHighGain:
@@ -2108,7 +2104,7 @@ static int hdsp_da_gain(hdsp_t *hdsp)
}
}
-static int hdsp_set_da_gain(hdsp_t *hdsp, int mode)
+static int hdsp_set_da_gain(struct hdsp *hdsp, int mode)
{
hdsp->control_register &= ~HDSP_DAGainMask;
switch (mode) {
@@ -2129,7 +2125,7 @@ static int hdsp_set_da_gain(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_da_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"Hi Gain", "+4 dBu", "-10 dbV"};
@@ -2142,17 +2138,17 @@ static int snd_hdsp_info_da_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
return 0;
}
-static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_da_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2179,7 +2175,7 @@ static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.put = snd_hdsp_put_ad_gain \
}
-static int hdsp_ad_gain(hdsp_t *hdsp)
+static int hdsp_ad_gain(struct hdsp *hdsp)
{
switch (hdsp->control_register & HDSP_ADGainMask) {
case HDSP_ADGainMinus10dBV:
@@ -2193,7 +2189,7 @@ static int hdsp_ad_gain(hdsp_t *hdsp)
}
}
-static int hdsp_set_ad_gain(hdsp_t *hdsp, int mode)
+static int hdsp_set_ad_gain(struct hdsp *hdsp, int mode)
{
hdsp->control_register &= ~HDSP_ADGainMask;
switch (mode) {
@@ -2214,7 +2210,7 @@ static int hdsp_set_ad_gain(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_ad_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"-10 dBV", "+4 dBu", "Lo Gain"};
@@ -2227,17 +2223,17 @@ static int snd_hdsp_info_ad_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
return 0;
}
-static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_ad_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2264,7 +2260,7 @@ static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.put = snd_hdsp_put_phone_gain \
}
-static int hdsp_phone_gain(hdsp_t *hdsp)
+static int hdsp_phone_gain(struct hdsp *hdsp)
{
switch (hdsp->control_register & HDSP_PhoneGainMask) {
case HDSP_PhoneGain0dB:
@@ -2278,7 +2274,7 @@ static int hdsp_phone_gain(hdsp_t *hdsp)
}
}
-static int hdsp_set_phone_gain(hdsp_t *hdsp, int mode)
+static int hdsp_set_phone_gain(struct hdsp *hdsp, int mode)
{
hdsp->control_register &= ~HDSP_PhoneGainMask;
switch (mode) {
@@ -2299,7 +2295,7 @@ static int hdsp_set_phone_gain(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_phone_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"0 dB", "-6 dB", "-12 dB"};
@@ -2312,17 +2308,17 @@ static int snd_hdsp_info_phone_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
return 0;
}
-static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_phone_gain(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2349,14 +2345,14 @@ static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
.put = snd_hdsp_put_xlr_breakout_cable \
}
-static int hdsp_xlr_breakout_cable(hdsp_t *hdsp)
+static int hdsp_xlr_breakout_cable(struct hdsp *hdsp)
{
if (hdsp->control_register & HDSP_XLRBreakoutCable)
return 1;
return 0;
}
-static int hdsp_set_xlr_breakout_cable(hdsp_t *hdsp, int mode)
+static int hdsp_set_xlr_breakout_cable(struct hdsp *hdsp, int mode)
{
if (mode)
hdsp->control_register |= HDSP_XLRBreakoutCable;
@@ -2366,7 +2362,7 @@ static int hdsp_set_xlr_breakout_cable(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_xlr_breakout_cable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2375,17 +2371,17 @@ static int snd_hdsp_info_xlr_breakout_cable(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
return 0;
}
-static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_xlr_breakout_cable(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2412,14 +2408,14 @@ static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_el
.put = snd_hdsp_put_aeb \
}
-static int hdsp_aeb(hdsp_t *hdsp)
+static int hdsp_aeb(struct hdsp *hdsp)
{
if (hdsp->control_register & HDSP_AnalogExtensionBoard)
return 1;
return 0;
}
-static int hdsp_set_aeb(hdsp_t *hdsp, int mode)
+static int hdsp_set_aeb(struct hdsp *hdsp, int mode)
{
if (mode)
hdsp->control_register |= HDSP_AnalogExtensionBoard;
@@ -2429,7 +2425,7 @@ static int hdsp_set_aeb(hdsp_t *hdsp, int mode)
return 0;
}
-static int snd_hdsp_info_aeb(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2438,17 +2434,17 @@ static int snd_hdsp_info_aeb(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uin
return 0;
}
-static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
return 0;
}
-static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_aeb(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -2471,7 +2467,7 @@ static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uc
.put = snd_hdsp_put_pref_sync_ref \
}
-static int hdsp_pref_sync_ref(hdsp_t *hdsp)
+static int hdsp_pref_sync_ref(struct hdsp *hdsp)
{
/* Notice that this looks at the requested sync source,
not the one actually in use.
@@ -2496,7 +2492,7 @@ static int hdsp_pref_sync_ref(hdsp_t *hdsp)
return 0;
}
-static int hdsp_set_pref_sync_ref(hdsp_t *hdsp, int pref)
+static int hdsp_set_pref_sync_ref(struct hdsp *hdsp, int pref)
{
hdsp->control_register &= ~HDSP_SyncRefMask;
switch (pref) {
@@ -2525,10 +2521,10 @@ static int hdsp_set_pref_sync_ref(hdsp_t *hdsp, int pref)
return 0;
}
-static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2555,17 +2551,17 @@ static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
return 0;
}
-static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change, max;
unsigned int val;
@@ -2604,7 +2600,7 @@ static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
.get = snd_hdsp_get_autosync_ref, \
}
-static int hdsp_autosync_ref(hdsp_t *hdsp)
+static int hdsp_autosync_ref(struct hdsp *hdsp)
{
/* This looks at the autosync selected sync reference */
unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
@@ -2630,7 +2626,7 @@ static int hdsp_autosync_ref(hdsp_t *hdsp)
return 0;
}
-static int snd_hdsp_info_autosync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"Word", "ADAT Sync", "IEC958", "None", "ADAT1", "ADAT2", "ADAT3" };
@@ -2643,9 +2639,9 @@ static int snd_hdsp_info_autosync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_autosync_ref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_autosync_ref(hdsp);
return 0;
@@ -2660,12 +2656,12 @@ static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
.put = snd_hdsp_put_line_out \
}
-static int hdsp_line_out(hdsp_t *hdsp)
+static int hdsp_line_out(struct hdsp *hdsp)
{
return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
}
-static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+static int hdsp_set_line_output(struct hdsp *hdsp, int out)
{
if (out)
hdsp->control_register |= HDSP_LineOut;
@@ -2675,7 +2671,7 @@ static int hdsp_set_line_output(hdsp_t *hdsp, int out)
return 0;
}
-static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2684,9 +2680,9 @@ static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
@@ -2694,9 +2690,9 @@ static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_line_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -2719,7 +2715,7 @@ static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.put = snd_hdsp_put_precise_pointer \
}
-static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise)
+static int hdsp_set_precise_pointer(struct hdsp *hdsp, int precise)
{
if (precise)
hdsp->precise_ptr = 1;
@@ -2728,7 +2724,7 @@ static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise)
return 0;
}
-static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2737,9 +2733,9 @@ static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp->precise_ptr;
@@ -2747,9 +2743,9 @@ static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_precise_pointer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -2772,7 +2768,7 @@ static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_
.put = snd_hdsp_put_use_midi_tasklet \
}
-static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet)
+static int hdsp_set_use_midi_tasklet(struct hdsp *hdsp, int use_tasklet)
{
if (use_tasklet)
hdsp->use_midi_tasklet = 1;
@@ -2781,7 +2777,7 @@ static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet)
return 0;
}
-static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2790,9 +2786,9 @@ static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdsp->lock);
ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
@@ -2800,9 +2796,9 @@ static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem
return 0;
}
-static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_use_midi_tasklet(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -2828,7 +2824,7 @@ static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem
.put = snd_hdsp_put_mixer \
}
-static int snd_hdsp_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 3;
@@ -2838,9 +2834,9 @@ static int snd_hdsp_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
return 0;
}
-static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int source;
int destination;
int addr;
@@ -2859,9 +2855,9 @@ static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
return 0;
}
-static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
int change;
int source;
int destination;
@@ -2898,7 +2894,7 @@ static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
.get = snd_hdsp_get_wc_sync_check \
}
-static int snd_hdsp_info_sync_check(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = {"No Lock", "Lock", "Sync" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2910,7 +2906,7 @@ static int snd_hdsp_info_sync_check(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
return 0;
}
-static int hdsp_wc_sync_check(hdsp_t *hdsp)
+static int hdsp_wc_sync_check(struct hdsp *hdsp)
{
int status2 = hdsp_read(hdsp, HDSP_status2Register);
if (status2 & HDSP_wc_lock) {
@@ -2923,9 +2919,9 @@ static int hdsp_wc_sync_check(hdsp_t *hdsp)
return 0;
}
-static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_wc_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
return 0;
@@ -2940,7 +2936,7 @@ static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
.get = snd_hdsp_get_spdif_sync_check \
}
-static int hdsp_spdif_sync_check(hdsp_t *hdsp)
+static int hdsp_spdif_sync_check(struct hdsp *hdsp)
{
int status = hdsp_read(hdsp, HDSP_statusRegister);
if (status & HDSP_SPDIFErrorFlag)
@@ -2954,9 +2950,9 @@ static int hdsp_spdif_sync_check(hdsp_t *hdsp)
return 0;
}
-static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_spdif_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
return 0;
@@ -2971,7 +2967,7 @@ static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem
.get = snd_hdsp_get_adatsync_sync_check \
}
-static int hdsp_adatsync_sync_check(hdsp_t *hdsp)
+static int hdsp_adatsync_sync_check(struct hdsp *hdsp)
{
int status = hdsp_read(hdsp, HDSP_statusRegister);
if (status & HDSP_TimecodeLock) {
@@ -2983,9 +2979,9 @@ static int hdsp_adatsync_sync_check(hdsp_t *hdsp)
return 0;
}
-static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_adatsync_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
return 0;
@@ -2998,7 +2994,7 @@ static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_e
.get = snd_hdsp_get_adat_sync_check \
}
-static int hdsp_adat_sync_check(hdsp_t *hdsp, int idx)
+static int hdsp_adat_sync_check(struct hdsp *hdsp, int idx)
{
int status = hdsp_read(hdsp, HDSP_statusRegister);
@@ -3011,10 +3007,10 @@ static int hdsp_adat_sync_check(hdsp_t *hdsp, int idx)
return 0;
}
-static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int offset;
- hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+ struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
offset = ucontrol->id.index - 1;
snd_assert(offset >= 0);
@@ -3038,14 +3034,14 @@ static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_
return 0;
}
-static snd_kcontrol_new_t snd_hdsp_9632_controls[] = {
+static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
HDSP_DA_GAIN("DA Gain", 0),
HDSP_AD_GAIN("AD Gain", 0),
HDSP_PHONE_GAIN("Phones Gain", 0),
HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
};
-static snd_kcontrol_new_t snd_hdsp_controls[] = {
+static struct snd_kcontrol_new snd_hdsp_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -3111,14 +3107,14 @@ HDSP_PRECISE_POINTER("Precise Pointer", 0),
HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
};
-static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
-static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
+static struct snd_kcontrol_new snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
+static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
-static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
+static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
{
unsigned int idx;
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0)
@@ -3162,9 +3158,9 @@ static int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
------------------------------------------------------------*/
static void
-snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- hdsp_t *hdsp = (hdsp_t *) entry->private_data;
+ struct hdsp *hdsp = (struct hdsp *) entry->private_data;
unsigned int status;
unsigned int status2;
char *pref_sync_ref;
@@ -3469,21 +3465,21 @@ snd_hdsp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
}
-static void __devinit snd_hdsp_proc_init(hdsp_t *hdsp)
+static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read);
}
-static void snd_hdsp_free_buffers(hdsp_t *hdsp)
+static void snd_hdsp_free_buffers(struct hdsp *hdsp)
{
snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
}
-static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp)
+static int __devinit snd_hdsp_initialize_memory(struct hdsp *hdsp)
{
unsigned long pb_bus, cb_bus;
@@ -3511,7 +3507,7 @@ static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp)
return 0;
}
-static int snd_hdsp_set_defaults(hdsp_t *hdsp)
+static int snd_hdsp_set_defaults(struct hdsp *hdsp)
{
unsigned int i;
@@ -3576,7 +3572,7 @@ static int snd_hdsp_set_defaults(hdsp_t *hdsp)
static void hdsp_midi_tasklet(unsigned long arg)
{
- hdsp_t *hdsp = (hdsp_t *)arg;
+ struct hdsp *hdsp = (struct hdsp *)arg;
if (hdsp->midi[0].pending)
snd_hdsp_midi_input_read (&hdsp->midi[0]);
@@ -3586,7 +3582,7 @@ static void hdsp_midi_tasklet(unsigned long arg)
static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- hdsp_t *hdsp = (hdsp_t *) dev_id;
+ struct hdsp *hdsp = (struct hdsp *) dev_id;
unsigned int status;
int audio;
int midi0;
@@ -3644,13 +3640,13 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_hdsp_hw_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_hdsp_hw_pointer(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
return hdsp_hw_pointer(hdsp);
}
-static char *hdsp_channel_buffer_location(hdsp_t *hdsp,
+static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
int stream,
int channel)
@@ -3668,10 +3664,10 @@ static char *hdsp_channel_buffer_location(hdsp_t *hdsp,
return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
}
-static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
+static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3683,10 +3679,10 @@ static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
return count;
}
-static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
+static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3698,10 +3694,10 @@ static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
return count;
}
-static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
+static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
@@ -3710,11 +3706,11 @@ static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
return count;
}
-static int snd_hdsp_reset(snd_pcm_substream_t *substream)
+static int snd_hdsp_reset(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
other = hdsp->capture_substream;
else
@@ -3725,8 +3721,8 @@ static int snd_hdsp_reset(snd_pcm_substream_t *substream)
runtime->status->hw_ptr = 0;
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
- snd_pcm_runtime_t *oruntime = other->runtime;
+ struct snd_pcm_substream *s;
+ struct snd_pcm_runtime *oruntime = other->runtime;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -3738,10 +3734,10 @@ static int snd_hdsp_reset(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int snd_hdsp_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
int err;
pid_t this_pid;
pid_t other_pid;
@@ -3813,10 +3809,10 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_hdsp_channel_info(snd_pcm_substream_t *substream,
- snd_pcm_channel_info_t *info)
+static int snd_hdsp_channel_info(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info *info)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
int mapped_channel;
snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
@@ -3830,7 +3826,7 @@ static int snd_hdsp_channel_info(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_hdsp_ioctl(snd_pcm_substream_t *substream,
+static int snd_hdsp_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -3845,10 +3841,10 @@ static int snd_hdsp_ioctl(snd_pcm_substream_t *substream,
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
int running;
if (hdsp_check_for_iobox (hdsp))
@@ -3878,7 +3874,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -3915,9 +3911,9 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
return 0;
}
-static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
+static int snd_hdsp_prepare(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
int result = 0;
if (hdsp_check_for_iobox (hdsp))
@@ -3933,7 +3929,7 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
return result;
}
-static snd_pcm_hardware_t snd_hdsp_playback_subinfo =
+static struct snd_pcm_hardware snd_hdsp_playback_subinfo =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -3963,7 +3959,7 @@ static snd_pcm_hardware_t snd_hdsp_playback_subinfo =
.fifo_size = 0
};
-static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
+static struct snd_pcm_hardware snd_hdsp_capture_subinfo =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -3994,7 +3990,7 @@ static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
-static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = {
+static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = {
.count = ARRAY_SIZE(hdsp_period_sizes),
.list = hdsp_period_sizes,
.mask = 0
@@ -4002,17 +3998,17 @@ static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = {
static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
-static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_9632_sample_rates = {
+static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = {
.count = ARRAY_SIZE(hdsp_9632_sample_rates),
.list = hdsp_9632_sample_rates,
.mask = 0
};
-static int snd_hdsp_hw_rule_in_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_in_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
if (hdsp->io_type == H9632) {
unsigned int list[3];
list[0] = hdsp->qs_in_channels;
@@ -4027,12 +4023,12 @@ static int snd_hdsp_hw_rule_in_channels(snd_pcm_hw_params_t *params,
}
}
-static int snd_hdsp_hw_rule_out_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_out_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned int list[3];
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
if (hdsp->io_type == H9632) {
list[0] = hdsp->qs_out_channels;
list[1] = hdsp->ds_out_channels;
@@ -4045,28 +4041,28 @@ static int snd_hdsp_hw_rule_out_channels(snd_pcm_hw_params_t *params,
return snd_interval_list(c, 2, list, 0);
}
-static int snd_hdsp_hw_rule_in_channels_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (r->min > 96000 && hdsp->io_type == H9632) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->qs_in_channels,
.max = hdsp->qs_in_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->min > 48000 && r->max <= 96000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->ds_in_channels,
.max = hdsp->ds_in_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->max < 64000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->ss_in_channels,
.max = hdsp->ss_in_channels,
.integer = 1,
@@ -4076,28 +4072,28 @@ static int snd_hdsp_hw_rule_in_channels_rate(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_hdsp_hw_rule_out_channels_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (r->min > 96000 && hdsp->io_type == H9632) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->qs_out_channels,
.max = hdsp->qs_out_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->min > 48000 && r->max <= 96000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->ds_out_channels,
.max = hdsp->ds_out_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->max < 64000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = hdsp->ss_out_channels,
.max = hdsp->ss_out_channels,
.integer = 1,
@@ -4107,28 +4103,28 @@ static int snd_hdsp_hw_rule_out_channels_rate(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_hdsp_hw_rule_rate_out_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (c->min >= hdsp->ss_out_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 32000,
.max = 48000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= hdsp->qs_out_channels && hdsp->io_type == H9632) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 128000,
.max = 192000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= hdsp->ds_out_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 64000,
.max = 96000,
.integer = 1,
@@ -4138,28 +4134,28 @@ static int snd_hdsp_hw_rule_rate_out_channels(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_hdsp_hw_rule_rate_in_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_hdsp_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- hdsp_t *hdsp = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct hdsp *hdsp = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (c->min >= hdsp->ss_in_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 32000,
.max = 48000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= hdsp->qs_in_channels && hdsp->io_type == H9632) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 128000,
.max = 192000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= hdsp->ds_in_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 64000,
.max = 96000,
.integer = 1,
@@ -4169,10 +4165,10 @@ static int snd_hdsp_hw_rule_rate_in_channels(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
+static int snd_hdsp_playback_open(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (hdsp_check_for_iobox (hdsp))
return -EIO;
@@ -4224,9 +4220,9 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
+static int snd_hdsp_playback_release(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
spin_lock_irq(&hdsp->lock);
@@ -4242,10 +4238,10 @@ static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
}
-static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
+static int snd_hdsp_capture_open(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (hdsp_check_for_iobox (hdsp))
return -EIO;
@@ -4287,9 +4283,9 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_hdsp_capture_release(snd_pcm_substream_t *substream)
+static int snd_hdsp_capture_release(struct snd_pcm_substream *substream)
{
- hdsp_t *hdsp = snd_pcm_substream_chip(substream);
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
spin_lock_irq(&hdsp->lock);
@@ -4300,7 +4296,7 @@ static int snd_hdsp_capture_release(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_hdsp_hwdep_dummy_op(snd_hwdep_t *hw, struct file *file)
+static int snd_hdsp_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
{
/* we have nothing to initialize but the call is required */
return 0;
@@ -4334,7 +4330,7 @@ static inline int copy_u48_le(void __user *dest, void __iomem *src_low, void __i
return copy_to_user(dest, &rms, 8);
}
-static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+static int hdsp_9652_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
{
int doublespeed = 0;
int i, j, channels, ofs;
@@ -4371,15 +4367,15 @@ static int hdsp_9652_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
return 0;
}
-static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+static int hdsp_9632_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
{
int i, j;
- hdsp_9632_meters_t __iomem *m;
+ struct hdsp_9632_meters __iomem *m;
int doublespeed = 0;
if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DoubleSpeedStatus)
doublespeed = 1;
- m = (hdsp_9632_meters_t __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
+ m = (struct hdsp_9632_meters __iomem *)(hdsp->iobase+HDSP_9632_metersBase);
for (i = 0, j = 0; i < 16; ++i, ++j) {
if (copy_u32_le(&peak_rms->input_peaks[i], &m->input_peak[j]))
return -EFAULT;
@@ -4401,7 +4397,7 @@ static int hdsp_9632_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
return 0;
}
-static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
+static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rms)
{
int i;
@@ -4431,14 +4427,14 @@ static int hdsp_get_peak(hdsp_t *hdsp, hdsp_peak_rms_t __user *peak_rms)
return 0;
}
-static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int cmd, unsigned long arg)
+static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
{
- hdsp_t *hdsp = (hdsp_t *)hw->private_data;
+ struct hdsp *hdsp = (struct hdsp *)hw->private_data;
void __user *argp = (void __user *)arg;
switch (cmd) {
case SNDRV_HDSP_IOCTL_GET_PEAK_RMS: {
- hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
+ struct hdsp_peak_rms __user *peak_rms = (struct hdsp_peak_rms __user *)arg;
if (!(hdsp->state & HDSP_FirmwareLoaded)) {
snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
@@ -4455,7 +4451,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
}
}
case SNDRV_HDSP_IOCTL_GET_CONFIG_INFO: {
- hdsp_config_info_t info;
+ struct hdsp_config_info info;
unsigned long flags;
int i;
@@ -4498,7 +4494,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
break;
}
case SNDRV_HDSP_IOCTL_GET_9632_AEB: {
- hdsp_9632_aeb_t h9632_aeb;
+ struct hdsp_9632_aeb h9632_aeb;
if (hdsp->io_type != H9632) return -EINVAL;
h9632_aeb.aebi = hdsp->ss_in_channels - H9632_SS_CHANNELS;
@@ -4508,7 +4504,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
break;
}
case SNDRV_HDSP_IOCTL_GET_VERSION: {
- hdsp_version_t hdsp_version;
+ struct hdsp_version hdsp_version;
int err;
if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return -EINVAL;
@@ -4523,7 +4519,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
break;
}
case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
- hdsp_firmware_t __user *firmware;
+ struct hdsp_firmware __user *firmware;
u32 __user *firmware_data;
int err;
@@ -4535,7 +4531,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
return -EBUSY;
snd_printk(KERN_INFO "Hammerfall-DSP: initializing firmware upload\n");
- firmware = (hdsp_firmware_t __user *)argp;
+ firmware = (struct hdsp_firmware __user *)argp;
if (get_user(firmware_data, &firmware->firmware_data))
return -EFAULT;
@@ -4566,7 +4562,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
break;
}
case SNDRV_HDSP_IOCTL_GET_MIXER: {
- hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp;
+ struct hdsp_mixer __user *mixer = (struct hdsp_mixer __user *)argp;
if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
return -EFAULT;
break;
@@ -4577,7 +4573,7 @@ static int snd_hdsp_hwdep_ioctl(snd_hwdep_t *hw, struct file *file, unsigned int
return 0;
}
-static snd_pcm_ops_t snd_hdsp_playback_ops = {
+static struct snd_pcm_ops snd_hdsp_playback_ops = {
.open = snd_hdsp_playback_open,
.close = snd_hdsp_playback_release,
.ioctl = snd_hdsp_ioctl,
@@ -4589,7 +4585,7 @@ static snd_pcm_ops_t snd_hdsp_playback_ops = {
.silence = snd_hdsp_hw_silence,
};
-static snd_pcm_ops_t snd_hdsp_capture_ops = {
+static struct snd_pcm_ops snd_hdsp_capture_ops = {
.open = snd_hdsp_capture_open,
.close = snd_hdsp_capture_release,
.ioctl = snd_hdsp_ioctl,
@@ -4600,10 +4596,10 @@ static snd_pcm_ops_t snd_hdsp_capture_ops = {
.copy = snd_hdsp_capture_copy,
};
-static int __devinit snd_hdsp_create_hwdep(snd_card_t *card,
- hdsp_t *hdsp)
+static int __devinit snd_hdsp_create_hwdep(struct snd_card *card,
+ struct hdsp *hdsp)
{
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
int err;
if ((err = snd_hwdep_new(card, "HDSP hwdep", 0, &hw)) < 0)
@@ -4620,9 +4616,9 @@ static int __devinit snd_hdsp_create_hwdep(snd_card_t *card,
return 0;
}
-static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp)
+static int snd_hdsp_create_pcm(struct snd_card *card, struct hdsp *hdsp)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(card, hdsp->card_name, 0, 1, 1, &pcm)) < 0)
@@ -4640,13 +4636,13 @@ static int snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp)
return 0;
}
-static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
+static void snd_hdsp_9652_enable_mixer (struct hdsp *hdsp)
{
hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
}
-static int snd_hdsp_enable_io (hdsp_t *hdsp)
+static int snd_hdsp_enable_io (struct hdsp *hdsp)
{
int i;
@@ -4663,7 +4659,7 @@ static int snd_hdsp_enable_io (hdsp_t *hdsp)
return 0;
}
-static void snd_hdsp_initialize_channels(hdsp_t *hdsp)
+static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
{
int status, aebi_channels, aebo_channels;
@@ -4706,13 +4702,13 @@ static void snd_hdsp_initialize_channels(hdsp_t *hdsp)
}
}
-static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
+static void snd_hdsp_initialize_midi_flush (struct hdsp *hdsp)
{
snd_hdsp_flush_midi_input (hdsp, 0);
snd_hdsp_flush_midi_input (hdsp, 1);
}
-static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
+static int snd_hdsp_create_alsa_devices(struct snd_card *card, struct hdsp *hdsp)
{
int err;
@@ -4769,7 +4765,7 @@ static int snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp)
#ifdef HDSP_FW_LOADER
/* load firmware via hotplug fw loader */
-static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
+static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp)
{
const char *fwfile;
const struct firmware *fw;
@@ -4842,8 +4838,8 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
}
#endif
-static int __devinit snd_hdsp_create(snd_card_t *card,
- hdsp_t *hdsp)
+static int __devinit snd_hdsp_create(struct snd_card *card,
+ struct hdsp *hdsp)
{
struct pci_dev *pci = hdsp->pci;
int err;
@@ -4980,7 +4976,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
return 0;
}
-static int snd_hdsp_free(hdsp_t *hdsp)
+static int snd_hdsp_free(struct hdsp *hdsp)
{
if (hdsp->port) {
/* stop the audio, and cancel all interrupts */
@@ -5004,9 +5000,9 @@ static int snd_hdsp_free(hdsp_t *hdsp)
return 0;
}
-static void snd_hdsp_card_free(snd_card_t *card)
+static void snd_hdsp_card_free(struct snd_card *card)
{
- hdsp_t *hdsp = (hdsp_t *) card->private_data;
+ struct hdsp *hdsp = (struct hdsp *) card->private_data;
if (hdsp)
snd_hdsp_free(hdsp);
@@ -5016,8 +5012,8 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- hdsp_t *hdsp;
- snd_card_t *card;
+ struct hdsp *hdsp;
+ struct snd_card *card;
int err;
if (dev >= SNDRV_CARDS)
@@ -5027,10 +5023,10 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
return -ENOENT;
}
- if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(hdsp_t))))
+ if (!(card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct hdsp))))
return -ENOMEM;
- hdsp = (hdsp_t *) card->private_data;
+ hdsp = (struct hdsp *) card->private_data;
card->private_free = snd_hdsp_card_free;
hdsp->dev = dev;
hdsp->pci = pci;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index a1aef6f6767e..3dec616bad6b 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -318,25 +318,22 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
-typedef struct _hdspm hdspm_t;
-typedef struct _hdspm_midi hdspm_midi_t;
-
-struct _hdspm_midi {
- hdspm_t *hdspm;
+struct hdspm_midi {
+ struct hdspm *hdspm;
int id;
- snd_rawmidi_t *rmidi;
- snd_rawmidi_substream_t *input;
- snd_rawmidi_substream_t *output;
+ struct snd_rawmidi *rmidi;
+ struct snd_rawmidi_substream *input;
+ struct snd_rawmidi_substream *output;
char istimer; /* timer in use */
struct timer_list timer;
spinlock_t lock;
int pending;
};
-struct _hdspm {
+struct hdspm {
spinlock_t lock;
- snd_pcm_substream_t *capture_substream; /* only one playback */
- snd_pcm_substream_t *playback_substream; /* and/or capture stream */
+ struct snd_pcm_substream *capture_substream; /* only one playback */
+ struct snd_pcm_substream *playback_substream; /* and/or capture stream */
char *card_name; /* for procinfo */
unsigned short firmware_rev; /* dont know if relevant */
@@ -347,7 +344,7 @@ struct _hdspm {
u32 control_register; /* cached value */
u32 control2_register; /* cached value */
- hdspm_midi_t midi[2];
+ struct hdspm_midi midi[2];
struct tasklet_struct midi_tasklet;
size_t period_bytes;
@@ -375,15 +372,15 @@ struct _hdspm {
int irq_count; /* for debug */
- snd_card_t *card; /* one card */
- snd_pcm_t *pcm; /* has one pcm */
- snd_hwdep_t *hwdep; /* and a hwdep for additional ioctl */
+ struct snd_card *card; /* one card */
+ struct snd_pcm *pcm; /* has one pcm */
+ struct snd_hwdep *hwdep; /* and a hwdep for additional ioctl */
struct pci_dev *pci; /* and an pci info */
/* Mixer vars */
- snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
- snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
- hdspm_mixer_t *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
+ struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
+ struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
+ struct hdspm_mixer *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
};
@@ -444,28 +441,28 @@ static struct pci_device_id snd_hdspm_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
/* prototypes */
-static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
- hdspm_t * hdspm);
-static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
- hdspm_t * hdspm);
-
-static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm);
-static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm);
-static int hdspm_autosync_ref(hdspm_t * hdspm);
-static int snd_hdspm_set_defaults(hdspm_t * hdspm);
-static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
+ struct hdspm * hdspm);
+static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
+ struct hdspm * hdspm);
+
+static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm);
+static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm);
+static int hdspm_autosync_ref(struct hdspm * hdspm);
+static int snd_hdspm_set_defaults(struct hdspm * hdspm);
+static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
unsigned int reg, int channels);
/* Write/read to/from HDSPM with Adresses in Bytes
not words but only 32Bit writes are allowed */
-static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg,
+static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
unsigned int val)
{
writel(val, hdspm->iobase + reg);
}
-static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
+static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
{
return readl(hdspm->iobase + reg);
}
@@ -474,7 +471,7 @@ static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
mixer is write only on hardware so we have to cache him for read
each fader is a u32, but uses only the first 16 bit */
-static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
+static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
unsigned int in)
{
if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS)
@@ -483,7 +480,7 @@ static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
return hdspm->mixer->ch[chan].in[in];
}
-static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
+static inline int hdspm_read_pb_gain(struct hdspm * hdspm, unsigned int chan,
unsigned int pb)
{
if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS)
@@ -491,7 +488,7 @@ static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
return hdspm->mixer->ch[chan].pb[pb];
}
-static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
+static inline int hdspm_write_in_gain(struct hdspm * hdspm, unsigned int chan,
unsigned int in, unsigned short data)
{
if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
@@ -504,7 +501,7 @@ static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
return 0;
}
-static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
+static inline int hdspm_write_pb_gain(struct hdspm * hdspm, unsigned int chan,
unsigned int pb, unsigned short data)
{
if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
@@ -519,18 +516,18 @@ static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
/* enable DMA for specific channels, now available for DSP-MADI */
-static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v)
+static inline void snd_hdspm_enable_in(struct hdspm * hdspm, int i, int v)
{
hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
}
-static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v)
+static inline void snd_hdspm_enable_out(struct hdspm * hdspm, int i, int v)
{
hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
}
/* check if same process is writing and reading */
-static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
+static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
{
unsigned long flags;
int ret = 1;
@@ -545,7 +542,7 @@ static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
}
/* check for external sample rate */
-static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
+static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
{
unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
@@ -630,13 +627,13 @@ static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
}
/* Latency function */
-static inline void hdspm_compute_period_size(hdspm_t * hdspm)
+static inline void hdspm_compute_period_size(struct hdspm * hdspm)
{
hdspm->period_bytes =
1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
}
-static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
+static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
{
int position;
@@ -660,20 +657,20 @@ static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
}
-static inline void hdspm_start_audio(hdspm_t * s)
+static inline void hdspm_start_audio(struct hdspm * s)
{
s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
hdspm_write(s, HDSPM_controlRegister, s->control_register);
}
-static inline void hdspm_stop_audio(hdspm_t * s)
+static inline void hdspm_stop_audio(struct hdspm * s)
{
s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
hdspm_write(s, HDSPM_controlRegister, s->control_register);
}
/* should I silence all or only opened ones ? doit all for first even is 4MB*/
-static inline void hdspm_silence_playback(hdspm_t * hdspm)
+static inline void hdspm_silence_playback(struct hdspm * hdspm)
{
int i;
int n = hdspm->period_bytes;
@@ -687,7 +684,7 @@ static inline void hdspm_silence_playback(hdspm_t * hdspm)
}
}
-static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
+static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
{
int n;
@@ -713,7 +710,7 @@ static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
/* dummy set rate lets see what happens */
-static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
+static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
{
int reject_if_open = 0;
int current_rate;
@@ -838,7 +835,7 @@ static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
}
/* mainly for init to 0 on load */
-static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
+static void all_in_all_mixer(struct hdspm * hdspm, int sgain)
{
int i, j;
unsigned int gain =
@@ -855,7 +852,7 @@ static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
MIDI
----------------------------------------------------------------------------*/
-static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
+static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, int id)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -864,7 +861,7 @@ static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
return hdspm_read(hdspm, HDSPM_midiDataIn0);
}
-static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
+static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, int val)
{
/* the hardware already does the relevant bit-mask with 0xff */
if (id)
@@ -873,7 +870,7 @@ static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
}
-static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
+static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
{
if (id)
return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
@@ -881,7 +878,7 @@ static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
}
-static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
+static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
{
int fifo_bytes_used;
@@ -896,13 +893,13 @@ static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
return 0;
}
-static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id)
+static inline void snd_hdspm_flush_midi_input (struct hdspm *hdspm, int id)
{
while (snd_hdspm_midi_input_available (hdspm, id))
snd_hdspm_midi_read_byte (hdspm, id);
}
-static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
+static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
{
unsigned long flags;
int n_pending;
@@ -930,7 +927,7 @@ static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
return 0;
}
-static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
+static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
{
unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
unsigned long flags;
@@ -967,14 +964,14 @@ static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
return snd_hdspm_midi_output_write (hmidi);
}
-static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- hdspm_t *hdspm;
- hdspm_midi_t *hmidi;
+ struct hdspm *hdspm;
+ struct hdspm_midi *hmidi;
unsigned long flags;
u32 ie;
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
hdspm = hmidi->hdspm;
ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
spin_lock_irqsave (&hdspm->lock, flags);
@@ -993,7 +990,7 @@ static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, in
static void snd_hdspm_midi_output_timer(unsigned long data)
{
- hdspm_midi_t *hmidi = (hdspm_midi_t *) data;
+ struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
unsigned long flags;
snd_hdspm_midi_output_write(hmidi);
@@ -1013,12 +1010,12 @@ static void snd_hdspm_midi_output_timer(unsigned long data)
spin_unlock_irqrestore (&hmidi->lock, flags);
}
-static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+static void snd_hdspm_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- hdspm_midi_t *hmidi;
+ struct hdspm_midi *hmidi;
unsigned long flags;
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
spin_lock_irqsave (&hmidi->lock, flags);
if (up) {
if (!hmidi->istimer) {
@@ -1039,11 +1036,11 @@ static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, i
snd_hdspm_midi_output_write(hmidi);
}
-static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
+static int snd_hdspm_midi_input_open(struct snd_rawmidi_substream *substream)
{
- hdspm_midi_t *hmidi;
+ struct hdspm_midi *hmidi;
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
hmidi->input = substream;
@@ -1052,11 +1049,11 @@ static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
+static int snd_hdspm_midi_output_open(struct snd_rawmidi_substream *substream)
{
- hdspm_midi_t *hmidi;
+ struct hdspm_midi *hmidi;
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = substream;
spin_unlock_irq (&hmidi->lock);
@@ -1064,13 +1061,13 @@ static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
+static int snd_hdspm_midi_input_close(struct snd_rawmidi_substream *substream)
{
- hdspm_midi_t *hmidi;
+ struct hdspm_midi *hmidi;
snd_hdspm_midi_input_trigger (substream, 0);
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->input = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1078,13 +1075,13 @@ static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
+static int snd_hdspm_midi_output_close(struct snd_rawmidi_substream *substream)
{
- hdspm_midi_t *hmidi;
+ struct hdspm_midi *hmidi;
snd_hdspm_midi_output_trigger (substream, 0);
- hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hmidi = (struct hdspm_midi *) substream->rmidi->private_data;
spin_lock_irq (&hmidi->lock);
hmidi->output = NULL;
spin_unlock_irq (&hmidi->lock);
@@ -1092,21 +1089,21 @@ static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
return 0;
}
-static snd_rawmidi_ops_t snd_hdspm_midi_output =
+static struct snd_rawmidi_ops snd_hdspm_midi_output =
{
.open = snd_hdspm_midi_output_open,
.close = snd_hdspm_midi_output_close,
.trigger = snd_hdspm_midi_output_trigger,
};
-static snd_rawmidi_ops_t snd_hdspm_midi_input =
+static struct snd_rawmidi_ops snd_hdspm_midi_input =
{
.open = snd_hdspm_midi_input_open,
.close = snd_hdspm_midi_input_close,
.trigger = snd_hdspm_midi_input_trigger,
};
-static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id)
+static int __devinit snd_hdspm_create_midi (struct snd_card *card, struct hdspm *hdspm, int id)
{
int err;
char buf[32];
@@ -1140,7 +1137,7 @@ static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, in
static void hdspm_midi_tasklet(unsigned long arg)
{
- hdspm_t *hdspm = (hdspm_t *)arg;
+ struct hdspm *hdspm = (struct hdspm *)arg;
if (hdspm->midi[0].pending)
snd_hdspm_midi_input_read (&hdspm->midi[0]);
@@ -1164,19 +1161,19 @@ static void hdspm_midi_tasklet(unsigned long arg)
.get = snd_hdspm_get_system_sample_rate \
}
-static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
return 0;
}
-static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
return 0;
@@ -1191,8 +1188,8 @@ static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
.get = snd_hdspm_get_autosync_sample_rate \
}
-static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "32000", "44100", "48000",
"64000", "88200", "96000",
@@ -1210,11 +1207,11 @@ static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
switch (hdspm_external_sample_rate(hdspm)) {
case 32000:
@@ -1262,7 +1259,7 @@ static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
-static int hdspm_system_clock_mode(hdspm_t * hdspm)
+static int hdspm_system_clock_mode(struct hdspm * hdspm)
{
/* Always reflect the hardware info, rme is never wrong !!!! */
@@ -1271,8 +1268,8 @@ static int hdspm_system_clock_mode(hdspm_t * hdspm)
return 1;
}
-static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "Master", "Slave" };
@@ -1287,10 +1284,10 @@ static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] =
hdspm_system_clock_mode(hdspm);
@@ -1306,7 +1303,7 @@ static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_clock_source \
}
-static int hdspm_clock_source(hdspm_t * hdspm)
+static int hdspm_clock_source(struct hdspm * hdspm)
{
if (hdspm->control_register & HDSPM_ClockModeMaster) {
switch (hdspm->system_sample_rate) {
@@ -1336,7 +1333,7 @@ static int hdspm_clock_source(hdspm_t * hdspm)
}
}
-static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
+static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
{
int rate;
switch (mode) {
@@ -1386,8 +1383,8 @@ static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
return 0;
}
-static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "AutoSync",
"Internal 32.0 kHz", "Internal 44.1 kHz",
@@ -1412,19 +1409,19 @@ static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_clock_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
return 0;
}
-static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
int val;
@@ -1453,7 +1450,7 @@ static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_pref_sync_ref \
}
-static int hdspm_pref_sync_ref(hdspm_t * hdspm)
+static int hdspm_pref_sync_ref(struct hdspm * hdspm)
{
/* Notice that this looks at the requested sync source,
not the one actually in use.
@@ -1468,7 +1465,7 @@ static int hdspm_pref_sync_ref(hdspm_t * hdspm)
return HDSPM_SYNC_FROM_WORD;
}
-static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
+static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
{
hdspm->control_register &= ~HDSPM_SyncRefMask;
@@ -1486,8 +1483,8 @@ static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
return 0;
}
-static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "Word", "MADI" };
@@ -1504,19 +1501,19 @@ static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
return 0;
}
-static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change, max;
unsigned int val;
@@ -1543,7 +1540,7 @@ static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
.get = snd_hdspm_get_autosync_ref, \
}
-static int hdspm_autosync_ref(hdspm_t * hdspm)
+static int hdspm_autosync_ref(struct hdspm * hdspm)
{
/* This looks at the autosync selected sync reference */
unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
@@ -1566,8 +1563,8 @@ static int hdspm_autosync_ref(hdspm_t * hdspm)
return 0;
}
-static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "WordClock", "MADI", "None" };
@@ -1582,10 +1579,10 @@ static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
return 0;
@@ -1600,13 +1597,13 @@ static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_line_out \
}
-static int hdspm_line_out(hdspm_t * hdspm)
+static int hdspm_line_out(struct hdspm * hdspm)
{
return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
}
-static int hdspm_set_line_output(hdspm_t * hdspm, int out)
+static int hdspm_set_line_output(struct hdspm * hdspm, int out)
{
if (out)
hdspm->control_register |= HDSPM_LineOut;
@@ -1617,8 +1614,8 @@ static int hdspm_set_line_output(hdspm_t * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_line_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1627,10 +1624,10 @@ static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_line_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdspm->lock);
ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
@@ -1638,10 +1635,10 @@ static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1664,12 +1661,12 @@ static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_tx_64 \
}
-static int hdspm_tx_64(hdspm_t * hdspm)
+static int hdspm_tx_64(struct hdspm * hdspm)
{
return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
}
-static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
+static int hdspm_set_tx_64(struct hdspm * hdspm, int out)
{
if (out)
hdspm->control_register |= HDSPM_TX_64ch;
@@ -1680,8 +1677,8 @@ static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_tx_64(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1690,10 +1687,10 @@ static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_tx_64(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdspm->lock);
ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
@@ -1701,10 +1698,10 @@ static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1727,12 +1724,12 @@ static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_c_tms \
}
-static int hdspm_c_tms(hdspm_t * hdspm)
+static int hdspm_c_tms(struct hdspm * hdspm)
{
return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
}
-static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
+static int hdspm_set_c_tms(struct hdspm * hdspm, int out)
{
if (out)
hdspm->control_register |= HDSPM_clr_tms;
@@ -1743,8 +1740,8 @@ static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_c_tms(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1753,10 +1750,10 @@ static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_c_tms(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdspm->lock);
ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
@@ -1764,10 +1761,10 @@ static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1790,12 +1787,12 @@ static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_safe_mode \
}
-static int hdspm_safe_mode(hdspm_t * hdspm)
+static int hdspm_safe_mode(struct hdspm * hdspm)
{
return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
}
-static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
+static int hdspm_set_safe_mode(struct hdspm * hdspm, int out)
{
if (out)
hdspm->control_register |= HDSPM_AutoInp;
@@ -1806,8 +1803,8 @@ static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_safe_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1816,10 +1813,10 @@ static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_safe_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdspm->lock);
ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
@@ -1827,10 +1824,10 @@ static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1853,12 +1850,12 @@ static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_input_select \
}
-static int hdspm_input_select(hdspm_t * hdspm)
+static int hdspm_input_select(struct hdspm * hdspm)
{
return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
}
-static int hdspm_set_input_select(hdspm_t * hdspm, int out)
+static int hdspm_set_input_select(struct hdspm * hdspm, int out)
{
if (out)
hdspm->control_register |= HDSPM_InputSelect0;
@@ -1869,8 +1866,8 @@ static int hdspm_set_input_select(hdspm_t * hdspm, int out)
return 0;
}
-static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_input_select(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "optical", "coaxial" };
@@ -1887,10 +1884,10 @@ static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_input_select(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&hdspm->lock);
ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
@@ -1898,10 +1895,10 @@ static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1937,8 +1934,8 @@ static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_mixer \
}
-static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 3;
@@ -1948,10 +1945,10 @@ static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int source;
int destination;
@@ -1981,10 +1978,10 @@ static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
int source;
int destination;
@@ -2041,8 +2038,8 @@ static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
.put = snd_hdspm_put_playback_mixer \
}
-static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2052,10 +2049,10 @@ static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int channel;
int mapped_channel;
@@ -2079,10 +2076,10 @@ static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
int change;
int channel;
int mapped_channel;
@@ -2121,8 +2118,8 @@ static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
.get = snd_hdspm_get_wc_sync_check \
}
-static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[] = { "No Lock", "Lock", "Sync" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2136,7 +2133,7 @@ static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
return 0;
}
-static int hdspm_wc_sync_check(hdspm_t * hdspm)
+static int hdspm_wc_sync_check(struct hdspm * hdspm)
{
int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
if (status2 & HDSPM_wcLock) {
@@ -2148,10 +2145,10 @@ static int hdspm_wc_sync_check(hdspm_t * hdspm)
return 0;
}
-static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
return 0;
@@ -2167,7 +2164,7 @@ static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
.get = snd_hdspm_get_madisync_sync_check \
}
-static int hdspm_madisync_sync_check(hdspm_t * hdspm)
+static int hdspm_madisync_sync_check(struct hdspm * hdspm)
{
int status = hdspm_read(hdspm, HDSPM_statusRegister);
if (status & HDSPM_madiLock) {
@@ -2179,11 +2176,11 @@ static int hdspm_madisync_sync_check(hdspm_t * hdspm)
return 0;
}
-static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t *
+static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *
ucontrol)
{
- hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
ucontrol->value.enumerated.item[0] =
hdspm_madisync_sync_check(hdspm);
@@ -2193,7 +2190,7 @@ static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
-static snd_kcontrol_new_t snd_hdspm_controls[] = {
+static struct snd_kcontrol_new snd_hdspm_controls[] = {
HDSPM_MIXER("Mixer", 0),
/* 'Sample Clock Source' complies with the alsa control naming scheme */
@@ -2214,10 +2211,10 @@ static snd_kcontrol_new_t snd_hdspm_controls[] = {
HDSPM_INPUT_SELECT("Input Select", 0),
};
-static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
+static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
-static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
+static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
{
int i;
@@ -2241,11 +2238,11 @@ static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
}
-static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
+static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
{
unsigned int idx, limit;
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
/* add control list first */
@@ -2292,9 +2289,9 @@ static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
------------------------------------------------------------*/
static void
-snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
{
- hdspm_t *hdspm = (hdspm_t *) entry->private_data;
+ struct hdspm *hdspm = (struct hdspm *) entry->private_data;
unsigned int status;
unsigned int status2;
char *pref_sync_ref;
@@ -2487,9 +2484,9 @@ snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
snd_iprintf(buffer, "\n");
}
-static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
+static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
snd_info_set_text_ops(entry, hdspm, 1024,
@@ -2500,7 +2497,7 @@ static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
hdspm intitialize
------------------------------------------------------------*/
-static int snd_hdspm_set_defaults(hdspm_t * hdspm)
+static int snd_hdspm_set_defaults(struct hdspm * hdspm)
{
unsigned int i;
@@ -2562,7 +2559,7 @@ static int snd_hdspm_set_defaults(hdspm_t * hdspm)
static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- hdspm_t *hdspm = (hdspm_t *) dev_id;
+ struct hdspm *hdspm = (struct hdspm *) dev_id;
unsigned int status;
int audio;
int midi0;
@@ -2627,14 +2624,14 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
------------------------------------------------------------*/
-static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t *
+static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
substream)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
return hdspm_hw_pointer(hdspm);
}
-static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
+static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
int stream, int channel)
{
int mapped_channel;
@@ -2656,11 +2653,11 @@ static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
/* dont know why need it ??? */
-static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
+static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
int channel, snd_pcm_uframes_t pos,
void __user *src, snd_pcm_uframes_t count)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
@@ -2675,11 +2672,11 @@ static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
return copy_from_user(channel_buf + pos * 4, src, count * 4);
}
-static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
+static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
int channel, snd_pcm_uframes_t pos,
void __user *dst, snd_pcm_uframes_t count)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
@@ -2692,11 +2689,11 @@ static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
return copy_to_user(dst, channel_buf + pos * 4, count * 4);
}
-static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
+static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
int channel, snd_pcm_uframes_t pos,
snd_pcm_uframes_t count)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
char *channel_buf;
channel_buf =
@@ -2707,11 +2704,11 @@ static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_hdspm_reset(snd_pcm_substream_t * substream)
+static int snd_hdspm_reset(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
other = hdspm->capture_substream;
@@ -2724,8 +2721,8 @@ static int snd_hdspm_reset(snd_pcm_substream_t * substream)
runtime->status->hw_ptr = 0;
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
- snd_pcm_runtime_t *oruntime = other->runtime;
+ struct snd_pcm_substream *s;
+ struct snd_pcm_runtime *oruntime = other->runtime;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -2738,10 +2735,10 @@ static int snd_hdspm_reset(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * params)
+static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
int err;
int i;
pid_t this_pid;
@@ -2839,10 +2836,10 @@ static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
+static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
{
int i;
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -2865,10 +2862,10 @@ static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
- snd_pcm_channel_info_t * info)
+static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info * info)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
int mapped_channel;
snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
@@ -2882,7 +2879,7 @@ static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
+static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -2893,7 +2890,7 @@ static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
{
- snd_pcm_channel_info_t *info = arg;
+ struct snd_pcm_channel_info *info = arg;
return snd_hdspm_channel_info(substream, info);
}
default:
@@ -2903,10 +2900,10 @@ static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
int running;
spin_lock(&hdspm->lock);
@@ -2930,7 +2927,7 @@ static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -2968,7 +2965,7 @@ static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
return 0;
}
-static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
+static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
{
return 0;
}
@@ -2976,7 +2973,7 @@ static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
static unsigned int period_sizes[] =
{ 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
-static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
+static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_NONINTERLEAVED |
@@ -3000,7 +2997,7 @@ static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
.fifo_size = 0
};
-static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
+static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_NONINTERLEAVED |
@@ -3024,31 +3021,31 @@ static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
.fifo_size = 0
};
-static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
.count = ARRAY_SIZE(period_sizes),
.list = period_sizes,
.mask = 0
};
-static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
- snd_pcm_hw_rule_t * rule)
+static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule * rule)
{
- hdspm_t *hdspm = rule->private;
- snd_interval_t *c =
+ struct hdspm *hdspm = rule->private;
+ struct snd_interval *c =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r =
+ struct snd_interval *r =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (r->min > 48000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 1,
.max = hdspm->ds_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->max < 64000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 1,
.max = hdspm->ss_channels,
.integer = 1,
@@ -3058,24 +3055,24 @@ static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
return 0;
}
-static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
- snd_pcm_hw_rule_t * rule)
+static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule * rule)
{
- hdspm_t *hdspm = rule->private;
- snd_interval_t *c =
+ struct hdspm *hdspm = rule->private;
+ struct snd_interval *c =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r =
+ struct snd_interval *r =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (c->min <= hdspm->ss_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 32000,
.max = 48000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max > hdspm->ss_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 64000,
.max = 96000,
.integer = 1,
@@ -3086,10 +3083,10 @@ static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
return 0;
}
-static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
+static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_printdd("Open device substream %d\n", substream->stream);
@@ -3124,9 +3121,9 @@ static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
+static int snd_hdspm_playback_release(struct snd_pcm_substream *substream)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
spin_lock_irq(&hdspm->lock);
@@ -3139,10 +3136,10 @@ static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
}
-static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
+static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
spin_lock_irq(&hdspm->lock);
snd_pcm_set_sync(substream);
@@ -3171,9 +3168,9 @@ static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
+static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
{
- hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ struct hdspm *hdspm = snd_pcm_substream_chip(substream);
spin_lock_irq(&hdspm->lock);
@@ -3184,21 +3181,21 @@ static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file)
+static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep * hw, struct file *file)
{
/* we have nothing to initialize but the call is required */
return 0;
}
-static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
+static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
unsigned int cmd, unsigned long arg)
{
- hdspm_t *hdspm = (hdspm_t *) hw->private_data;
- struct sndrv_hdspm_mixer_ioctl mixer;
- hdspm_config_info_t info;
- hdspm_version_t hdspm_version;
- struct sndrv_hdspm_peak_rms_ioctl rms;
+ struct hdspm *hdspm = (struct hdspm *) hw->private_data;
+ struct hdspm_mixer_ioctl mixer;
+ struct hdspm_config_info info;
+ struct hdspm_version hdspm_version;
+ struct hdspm_peak_rms_ioctl rms;
switch (cmd) {
@@ -3209,7 +3206,7 @@ static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
/* maybe there is a chance to memorymap in future so dont touch just copy */
if(copy_to_user_fromio((void __user *)rms.peak,
hdspm->iobase+HDSPM_MADI_peakrmsbase,
- sizeof(hdspm_peak_rms_t)) != 0 )
+ sizeof(struct hdspm_peak_rms)) != 0 )
return -EFAULT;
break;
@@ -3250,7 +3247,7 @@ static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
return -EFAULT;
if (copy_to_user
- ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t)))
+ ((void __user *)mixer.mixer, hdspm->mixer, sizeof(struct hdspm_mixer)))
return -EFAULT;
break;
@@ -3260,7 +3257,7 @@ static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
return 0;
}
-static snd_pcm_ops_t snd_hdspm_playback_ops = {
+static struct snd_pcm_ops snd_hdspm_playback_ops = {
.open = snd_hdspm_playback_open,
.close = snd_hdspm_playback_release,
.ioctl = snd_hdspm_ioctl,
@@ -3274,7 +3271,7 @@ static snd_pcm_ops_t snd_hdspm_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static snd_pcm_ops_t snd_hdspm_capture_ops = {
+static struct snd_pcm_ops snd_hdspm_capture_ops = {
.open = snd_hdspm_capture_open,
.close = snd_hdspm_capture_release,
.ioctl = snd_hdspm_ioctl,
@@ -3287,10 +3284,10 @@ static snd_pcm_ops_t snd_hdspm_capture_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
- hdspm_t * hdspm)
+static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
+ struct hdspm * hdspm)
{
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
int err;
if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
@@ -3311,10 +3308,10 @@ static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
/*------------------------------------------------------------
memory interface
------------------------------------------------------------*/
-static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
+static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
{
int err;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
size_t wanted;
pcm = hdspm->pcm;
@@ -3336,16 +3333,7 @@ static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
return 0;
}
-static int snd_hdspm_memory_free(hdspm_t * hdspm)
-{
- snd_printdd("memory_free_for_all %p\n", hdspm->pcm);
-
- snd_pcm_lib_preallocate_free_for_all(hdspm->pcm);
- return 0;
-}
-
-
-static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
unsigned int reg, int channels)
{
int i;
@@ -3356,10 +3344,10 @@ static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
}
/* ------------- ALSA Devices ---------------------------- */
-static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
- hdspm_t * hdspm)
+static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
+ struct hdspm * hdspm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
@@ -3382,14 +3370,14 @@ static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
return 0;
}
-static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm)
+static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
{
snd_hdspm_flush_midi_input(hdspm, 0);
snd_hdspm_flush_midi_input(hdspm, 1);
}
-static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
- hdspm_t * hdspm)
+static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
+ struct hdspm * hdspm)
{
int err;
@@ -3439,7 +3427,7 @@ static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
return 0;
}
-static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
+static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdspm,
int precise_ptr, int enable_monitor)
{
struct pci_dev *pci = hdspm->pci;
@@ -3523,12 +3511,11 @@ static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
hdspm->monitor_outs = enable_monitor;
snd_printdd("kmalloc Mixer memory of %d Bytes\n",
- sizeof(hdspm_mixer_t));
- if ((hdspm->mixer =
- (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL))
+ sizeof(struct hdspm_mixer));
+ if ((hdspm->mixer = kmalloc(sizeof(struct hdspm_mixer), GFP_KERNEL))
== NULL) {
snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
- (int)sizeof(hdspm_mixer_t));
+ (int)sizeof(struct hdspm_mixer));
return err;
}
@@ -3545,7 +3532,7 @@ static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
return 0;
}
-static int snd_hdspm_free(hdspm_t * hdspm)
+static int snd_hdspm_free(struct hdspm * hdspm)
{
if (hdspm->port) {
@@ -3568,8 +3555,6 @@ static int snd_hdspm_free(hdspm_t * hdspm)
if (hdspm->iobase)
iounmap(hdspm->iobase);
- snd_hdspm_memory_free(hdspm);
-
if (hdspm->port)
pci_release_regions(hdspm->pci);
@@ -3577,9 +3562,9 @@ static int snd_hdspm_free(hdspm_t * hdspm)
return 0;
}
-static void snd_hdspm_card_free(snd_card_t * card)
+static void snd_hdspm_card_free(struct snd_card *card)
{
- hdspm_t *hdspm = (hdspm_t *) card->private_data;
+ struct hdspm *hdspm = (struct hdspm *) card->private_data;
if (hdspm)
snd_hdspm_free(hdspm);
@@ -3589,8 +3574,8 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- hdspm_t *hdspm;
- snd_card_t *card;
+ struct hdspm *hdspm;
+ struct snd_card *card;
int err;
if (dev >= SNDRV_CARDS)
@@ -3601,10 +3586,10 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
}
if (!(card = snd_card_new(index[dev], id[dev],
- THIS_MODULE, sizeof(hdspm_t))))
+ THIS_MODULE, sizeof(struct hdspm))))
return -ENOMEM;
- hdspm = (hdspm_t *) card->private_data;
+ hdspm = (struct hdspm *) card->private_data;
card->private_free = snd_hdspm_card_free;
hdspm->dev = dev;
hdspm->pci = pci;
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index f9d0c126c213..a687eb63236f 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -198,7 +198,7 @@ MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall},"
#define RME9652_DMA_AREA_BYTES ((RME9652_NCHANNELS+1) * RME9652_CHANNEL_BUFFER_BYTES)
#define RME9652_DMA_AREA_KILOBYTES (RME9652_DMA_AREA_BYTES/1024)
-typedef struct snd_rme9652 {
+struct snd_rme9652 {
int dev;
spinlock_t lock;
@@ -234,8 +234,8 @@ typedef struct snd_rme9652 {
pid_t capture_pid;
pid_t playback_pid;
- snd_pcm_substream_t *capture_substream;
- snd_pcm_substream_t *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_pcm_substream *playback_substream;
int running;
int passthru; /* non-zero if doing pass-thru */
@@ -246,12 +246,12 @@ typedef struct snd_rme9652 {
char *channel_map;
- snd_card_t *card;
- snd_pcm_t *pcm;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
struct pci_dev *pci;
- snd_kcontrol_t *spdif_ctl;
+ struct snd_kcontrol *spdif_ctl;
-} rme9652_t;
+};
/* These tables map the ALSA channels 1..N to the channels that we
need to use in order to find the relevant channel buffer. RME
@@ -327,17 +327,17 @@ static struct pci_device_id snd_rme9652_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_rme9652_ids);
-static inline void rme9652_write(rme9652_t *rme9652, int reg, int val)
+static inline void rme9652_write(struct snd_rme9652 *rme9652, int reg, int val)
{
writel(val, rme9652->iobase + reg);
}
-static inline unsigned int rme9652_read(rme9652_t *rme9652, int reg)
+static inline unsigned int rme9652_read(struct snd_rme9652 *rme9652, int reg)
{
return readl(rme9652->iobase + reg);
}
-static inline int snd_rme9652_use_is_exclusive(rme9652_t *rme9652)
+static inline int snd_rme9652_use_is_exclusive(struct snd_rme9652 *rme9652)
{
unsigned long flags;
int ret = 1;
@@ -351,7 +351,7 @@ static inline int snd_rme9652_use_is_exclusive(rme9652_t *rme9652)
return ret;
}
-static inline int rme9652_adat_sample_rate(rme9652_t *rme9652)
+static inline int rme9652_adat_sample_rate(struct snd_rme9652 *rme9652)
{
if (rme9652_running_double_speed(rme9652)) {
return (rme9652_read(rme9652, RME9652_status_register) &
@@ -362,7 +362,7 @@ static inline int rme9652_adat_sample_rate(rme9652_t *rme9652)
}
}
-static inline void rme9652_compute_period_size(rme9652_t *rme9652)
+static inline void rme9652_compute_period_size(struct snd_rme9652 *rme9652)
{
unsigned int i;
@@ -373,7 +373,7 @@ static inline void rme9652_compute_period_size(rme9652_t *rme9652)
rme9652->max_jitter = 80;
}
-static snd_pcm_uframes_t rme9652_hw_pointer(rme9652_t *rme9652)
+static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652)
{
int status;
unsigned int offset, frag;
@@ -420,7 +420,7 @@ static snd_pcm_uframes_t rme9652_hw_pointer(rme9652_t *rme9652)
return offset;
}
-static inline void rme9652_reset_hw_pointer(rme9652_t *rme9652)
+static inline void rme9652_reset_hw_pointer(struct snd_rme9652 *rme9652)
{
int i;
@@ -437,19 +437,19 @@ static inline void rme9652_reset_hw_pointer(rme9652_t *rme9652)
rme9652->prev_hw_offset = 0;
}
-static inline void rme9652_start(rme9652_t *s)
+static inline void rme9652_start(struct snd_rme9652 *s)
{
s->control_register |= (RME9652_IE | RME9652_start_bit);
rme9652_write(s, RME9652_control_register, s->control_register);
}
-static inline void rme9652_stop(rme9652_t *s)
+static inline void rme9652_stop(struct snd_rme9652 *s)
{
s->control_register &= ~(RME9652_start_bit | RME9652_IE);
rme9652_write(s, RME9652_control_register, s->control_register);
}
-static int rme9652_set_interrupt_interval(rme9652_t *s,
+static int rme9652_set_interrupt_interval(struct snd_rme9652 *s,
unsigned int frames)
{
int restart = 0;
@@ -483,7 +483,7 @@ static int rme9652_set_interrupt_interval(rme9652_t *s,
return 0;
}
-static int rme9652_set_rate(rme9652_t *rme9652, int rate)
+static int rme9652_set_rate(struct snd_rme9652 *rme9652, int rate)
{
int restart;
int reject_if_open = 0;
@@ -571,7 +571,7 @@ static int rme9652_set_rate(rme9652_t *rme9652, int rate)
return 0;
}
-static void rme9652_set_thru(rme9652_t *rme9652, int channel, int enable)
+static void rme9652_set_thru(struct snd_rme9652 *rme9652, int channel, int enable)
{
int i;
@@ -612,7 +612,7 @@ static void rme9652_set_thru(rme9652_t *rme9652, int channel, int enable)
}
}
-static int rme9652_set_passthru(rme9652_t *rme9652, int onoff)
+static int rme9652_set_passthru(struct snd_rme9652 *rme9652, int onoff)
{
if (onoff) {
rme9652_set_thru(rme9652, -1, 1);
@@ -640,7 +640,7 @@ static int rme9652_set_passthru(rme9652_t *rme9652, int onoff)
return 0;
}
-static void rme9652_spdif_set_bit (rme9652_t *rme9652, int mask, int onoff)
+static void rme9652_spdif_set_bit (struct snd_rme9652 *rme9652, int mask, int onoff)
{
if (onoff)
rme9652->control_register |= mask;
@@ -650,7 +650,7 @@ static void rme9652_spdif_set_bit (rme9652_t *rme9652, int mask, int onoff)
rme9652_write(rme9652, RME9652_control_register, rme9652->control_register);
}
-static void rme9652_spdif_write_byte (rme9652_t *rme9652, const int val)
+static void rme9652_spdif_write_byte (struct snd_rme9652 *rme9652, const int val)
{
long mask;
long i;
@@ -666,7 +666,7 @@ static void rme9652_spdif_write_byte (rme9652_t *rme9652, const int val)
}
}
-static int rme9652_spdif_read_byte (rme9652_t *rme9652)
+static int rme9652_spdif_read_byte (struct snd_rme9652 *rme9652)
{
long mask;
long val;
@@ -684,7 +684,7 @@ static int rme9652_spdif_read_byte (rme9652_t *rme9652)
return val;
}
-static void rme9652_write_spdif_codec (rme9652_t *rme9652, const int address, const int data)
+static void rme9652_write_spdif_codec (struct snd_rme9652 *rme9652, const int address, const int data)
{
rme9652_spdif_set_bit (rme9652, RME9652_SPDIF_SELECT, 1);
rme9652_spdif_write_byte (rme9652, 0x20);
@@ -694,7 +694,7 @@ static void rme9652_write_spdif_codec (rme9652_t *rme9652, const int address, co
}
-static int rme9652_spdif_read_codec (rme9652_t *rme9652, const int address)
+static int rme9652_spdif_read_codec (struct snd_rme9652 *rme9652, const int address)
{
int ret;
@@ -711,7 +711,7 @@ static int rme9652_spdif_read_codec (rme9652_t *rme9652, const int address)
return ret;
}
-static void rme9652_initialize_spdif_receiver (rme9652_t *rme9652)
+static void rme9652_initialize_spdif_receiver (struct snd_rme9652 *rme9652)
{
/* XXX what unsets this ? */
@@ -722,7 +722,7 @@ static void rme9652_initialize_spdif_receiver (rme9652_t *rme9652)
rme9652_write_spdif_codec (rme9652, 6, 0x02);
}
-static inline int rme9652_spdif_sample_rate(rme9652_t *s)
+static inline int rme9652_spdif_sample_rate(struct snd_rme9652 *s)
{
unsigned int rate_bits;
@@ -790,7 +790,7 @@ static inline int rme9652_spdif_sample_rate(rme9652_t *s)
Control Interface
----------------------------------------------------------------------------*/
-static u32 snd_rme9652_convert_from_aes(snd_aes_iec958_t *aes)
+static u32 snd_rme9652_convert_from_aes(struct snd_aes_iec958 *aes)
{
u32 val = 0;
val |= (aes->status[0] & IEC958_AES0_PROFESSIONAL) ? RME9652_PRO : 0;
@@ -802,7 +802,7 @@ static u32 snd_rme9652_convert_from_aes(snd_aes_iec958_t *aes)
return val;
}
-static void snd_rme9652_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
+static void snd_rme9652_convert_to_aes(struct snd_aes_iec958 *aes, u32 val)
{
aes->status[0] = ((val & RME9652_PRO) ? IEC958_AES0_PROFESSIONAL : 0) |
((val & RME9652_Dolby) ? IEC958_AES0_NONAUDIO : 0);
@@ -812,24 +812,24 @@ static void snd_rme9652_convert_to_aes(snd_aes_iec958_t *aes, u32 val)
aes->status[0] |= (val & RME9652_EMP) ? IEC958_AES0_CON_EMPHASIS_5015 : 0;
}
-static int snd_rme9652_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_control_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme9652_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_control_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif);
return 0;
}
-static int snd_rme9652_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_control_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -841,24 +841,24 @@ static int snd_rme9652_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem
return change;
}
-static int snd_rme9652_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_control_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme9652_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_control_spdif_stream_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream);
return 0;
}
-static int snd_rme9652_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_control_spdif_stream_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
u32 val;
@@ -872,14 +872,14 @@ static int snd_rme9652_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_c
return change;
}
-static int snd_rme9652_control_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_control_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_rme9652_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_control_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = kcontrol->private_value;
return 0;
@@ -891,14 +891,14 @@ static int snd_rme9652_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl
.get = snd_rme9652_get_adat1_in, \
.put = snd_rme9652_put_adat1_in }
-static unsigned int rme9652_adat1_in(rme9652_t *rme9652)
+static unsigned int rme9652_adat1_in(struct snd_rme9652 *rme9652)
{
if (rme9652->control_register & RME9652_ADAT1_INTERNAL)
return 1;
return 0;
}
-static int rme9652_set_adat1_input(rme9652_t *rme9652, int internal)
+static int rme9652_set_adat1_input(struct snd_rme9652 *rme9652, int internal)
{
int restart = 0;
@@ -923,7 +923,7 @@ static int rme9652_set_adat1_input(rme9652_t *rme9652, int internal)
return 0;
}
-static int snd_rme9652_info_adat1_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = {"ADAT1", "Internal"};
@@ -936,9 +936,9 @@ static int snd_rme9652_info_adat1_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_rme9652_get_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652);
@@ -946,9 +946,9 @@ static int snd_rme9652_get_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_rme9652_put_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_adat1_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -968,13 +968,13 @@ static int snd_rme9652_put_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
.info = snd_rme9652_info_spdif_in, \
.get = snd_rme9652_get_spdif_in, .put = snd_rme9652_put_spdif_in }
-static unsigned int rme9652_spdif_in(rme9652_t *rme9652)
+static unsigned int rme9652_spdif_in(struct snd_rme9652 *rme9652)
{
return rme9652_decode_spdif_in(rme9652->control_register &
RME9652_inp);
}
-static int rme9652_set_spdif_input(rme9652_t *rme9652, int in)
+static int rme9652_set_spdif_input(struct snd_rme9652 *rme9652, int in)
{
int restart = 0;
@@ -994,7 +994,7 @@ static int rme9652_set_spdif_input(rme9652_t *rme9652, int in)
return 0;
}
-static int snd_rme9652_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {"ADAT1", "Coaxial", "Internal"};
@@ -1007,9 +1007,9 @@ static int snd_rme9652_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_rme9652_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652);
@@ -1017,9 +1017,9 @@ static int snd_rme9652_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_rme9652_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_spdif_in(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1039,12 +1039,12 @@ static int snd_rme9652_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
.info = snd_rme9652_info_spdif_out, \
.get = snd_rme9652_get_spdif_out, .put = snd_rme9652_put_spdif_out }
-static int rme9652_spdif_out(rme9652_t *rme9652)
+static int rme9652_spdif_out(struct snd_rme9652 *rme9652)
{
return (rme9652->control_register & RME9652_opt_out) ? 1 : 0;
}
-static int rme9652_set_spdif_output(rme9652_t *rme9652, int out)
+static int rme9652_set_spdif_output(struct snd_rme9652 *rme9652, int out)
{
int restart = 0;
@@ -1067,7 +1067,7 @@ static int rme9652_set_spdif_output(rme9652_t *rme9652, int out)
return 0;
}
-static int snd_rme9652_info_spdif_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1076,9 +1076,9 @@ static int snd_rme9652_info_spdif_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_rme9652_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652);
@@ -1086,9 +1086,9 @@ static int snd_rme9652_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_rme9652_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_spdif_out(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1107,7 +1107,7 @@ static int snd_rme9652_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
.info = snd_rme9652_info_sync_mode, \
.get = snd_rme9652_get_sync_mode, .put = snd_rme9652_put_sync_mode }
-static int rme9652_sync_mode(rme9652_t *rme9652)
+static int rme9652_sync_mode(struct snd_rme9652 *rme9652)
{
if (rme9652->control_register & RME9652_wsel) {
return 2;
@@ -1118,7 +1118,7 @@ static int rme9652_sync_mode(rme9652_t *rme9652)
}
}
-static int rme9652_set_sync_mode(rme9652_t *rme9652, int mode)
+static int rme9652_set_sync_mode(struct snd_rme9652 *rme9652, int mode)
{
int restart = 0;
@@ -1150,7 +1150,7 @@ static int rme9652_set_sync_mode(rme9652_t *rme9652, int mode)
return 0;
}
-static int snd_rme9652_info_sync_mode(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[3] = {"AutoSync", "Master", "Word Clock"};
@@ -1163,9 +1163,9 @@ static int snd_rme9652_info_sync_mode(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_rme9652_get_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652);
@@ -1173,9 +1173,9 @@ static int snd_rme9652_get_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_rme9652_put_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_sync_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
@@ -1192,7 +1192,7 @@ static int snd_rme9652_put_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
.info = snd_rme9652_info_sync_pref, \
.get = snd_rme9652_get_sync_pref, .put = snd_rme9652_put_sync_pref }
-static int rme9652_sync_pref(rme9652_t *rme9652)
+static int rme9652_sync_pref(struct snd_rme9652 *rme9652)
{
switch (rme9652->control_register & RME9652_SyncPref_Mask) {
case RME9652_SyncPref_ADAT1:
@@ -1208,7 +1208,7 @@ static int rme9652_sync_pref(rme9652_t *rme9652)
return 0;
}
-static int rme9652_set_sync_pref(rme9652_t *rme9652, int pref)
+static int rme9652_set_sync_pref(struct snd_rme9652 *rme9652, int pref)
{
int restart;
@@ -1241,10 +1241,10 @@ static int rme9652_set_sync_pref(rme9652_t *rme9652, int pref)
return 0;
}
-static int snd_rme9652_info_sync_pref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {"IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In"};
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -1255,9 +1255,9 @@ static int snd_rme9652_info_sync_pref(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_rme9652_get_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652);
@@ -1265,9 +1265,9 @@ static int snd_rme9652_get_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_rme9652_put_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_sync_pref(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change, max;
unsigned int val;
@@ -1282,9 +1282,9 @@ static int snd_rme9652_put_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return change;
}
-static int snd_rme9652_info_thru(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = rme9652->ss_channels;
uinfo->value.integer.min = 0;
@@ -1292,9 +1292,9 @@ static int snd_rme9652_info_thru(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-static int snd_rme9652_get_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
unsigned int k;
u32 thru_bits = rme9652->thru_bits;
@@ -1304,9 +1304,9 @@ static int snd_rme9652_get_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_thru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int chn;
u32 thru_bits = 0;
@@ -1338,7 +1338,7 @@ static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
.put = snd_rme9652_put_passthru, \
.get = snd_rme9652_get_passthru }
-static int snd_rme9652_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1347,9 +1347,9 @@ static int snd_rme9652_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_rme9652_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.integer.value[0] = rme9652->passthru;
@@ -1357,9 +1357,9 @@ static int snd_rme9652_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_put_passthru(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
int change;
unsigned int val;
int err = 0;
@@ -1384,7 +1384,7 @@ static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
.info = snd_rme9652_info_spdif_rate, \
.get = snd_rme9652_get_spdif_rate }
-static int snd_rme9652_info_spdif_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -1393,9 +1393,9 @@ static int snd_rme9652_info_spdif_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_rme9652_get_spdif_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_spdif_rate(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&rme9652->lock);
ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652);
@@ -1409,7 +1409,7 @@ static int snd_rme9652_get_spdif_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
.info = snd_rme9652_info_adat_sync, \
.get = snd_rme9652_get_adat_sync, .private_value = xidx }
-static int snd_rme9652_info_adat_sync(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {"No Lock", "Lock", "No Lock Sync", "Lock Sync"};
@@ -1422,9 +1422,9 @@ static int snd_rme9652_info_adat_sync(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_rme9652_get_adat_sync(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_adat_sync(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
unsigned int mask1, mask2, val;
switch (kcontrol->private_value) {
@@ -1445,7 +1445,7 @@ static int snd_rme9652_get_adat_sync(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
.info = snd_rme9652_info_tc_valid, \
.get = snd_rme9652_get_tc_valid }
-static int snd_rme9652_info_tc_valid(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_rme9652_info_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1454,9 +1454,9 @@ static int snd_rme9652_info_tc_valid(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
return 0;
}
-static int snd_rme9652_get_tc_valid(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_rme9652_get_tc_valid(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
+ struct snd_rme9652 *rme9652 = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] =
(rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0;
@@ -1471,7 +1471,7 @@ static int snd_rme9652_get_tc_value(void *private_data,
snd_kswitch_t *kswitch,
snd_switch_t *uswitch)
{
- rme9652_t *s = (rme9652_t *) private_data;
+ struct snd_rme9652 *s = (struct snd_rme9652 *) private_data;
u32 value;
int i;
@@ -1520,7 +1520,7 @@ static int snd_rme9652_get_tc_value(void *private_data,
#endif /* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */
-static snd_kcontrol_new_t snd_rme9652_controls[] = {
+static struct snd_kcontrol_new snd_rme9652_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1575,17 +1575,17 @@ RME9652_TC_VALID("Timecode Valid", 0),
RME9652_PASSTHRU("Passthru", 0)
};
-static snd_kcontrol_new_t snd_rme9652_adat3_check =
+static struct snd_kcontrol_new snd_rme9652_adat3_check =
RME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2);
-static snd_kcontrol_new_t snd_rme9652_adat1_input =
+static struct snd_kcontrol_new snd_rme9652_adat1_input =
RME9652_ADAT1_IN("ADAT1 Input Source", 0);
-static int snd_rme9652_create_controls(snd_card_t *card, rme9652_t *rme9652)
+static int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 *rme9652)
{
unsigned int idx;
int err;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) {
if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652))) < 0)
@@ -1610,9 +1610,9 @@ static int snd_rme9652_create_controls(snd_card_t *card, rme9652_t *rme9652)
------------------------------------------------------------*/
static void
-snd_rme9652_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+snd_rme9652_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- rme9652_t *rme9652 = (rme9652_t *) entry->private_data;
+ struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) entry->private_data;
u32 thru_bits = rme9652->thru_bits;
int show_auto_sync_source = 0;
int i;
@@ -1782,21 +1782,21 @@ snd_rme9652_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, "\n");
}
-static void __devinit snd_rme9652_proc_init(rme9652_t *rme9652)
+static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(rme9652->card, "rme9652", &entry))
snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read);
}
-static void snd_rme9652_free_buffers(rme9652_t *rme9652)
+static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
{
snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
}
-static int snd_rme9652_free(rme9652_t *rme9652)
+static int snd_rme9652_free(struct snd_rme9652 *rme9652)
{
if (rme9652->irq >= 0)
rme9652_stop(rme9652);
@@ -1813,7 +1813,7 @@ static int snd_rme9652_free(rme9652_t *rme9652)
return 0;
}
-static int __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652)
+static int __devinit snd_rme9652_initialize_memory(struct snd_rme9652 *rme9652)
{
unsigned long pb_bus, cb_bus;
@@ -1841,7 +1841,7 @@ static int __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652)
return 0;
}
-static void snd_rme9652_set_defaults(rme9652_t *rme9652)
+static void snd_rme9652_set_defaults(struct snd_rme9652 *rme9652)
{
unsigned int k;
@@ -1884,7 +1884,7 @@ static void snd_rme9652_set_defaults(rme9652_t *rme9652)
static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- rme9652_t *rme9652 = (rme9652_t *) dev_id;
+ struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) dev_id;
if (!(rme9652_read(rme9652, RME9652_status_register) & RME9652_IRQ)) {
return IRQ_NONE;
@@ -1902,13 +1902,13 @@ static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *
return IRQ_HANDLED;
}
-static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_rme9652_hw_pointer(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
return rme9652_hw_pointer(rme9652);
}
-static char *rme9652_channel_buffer_location(rme9652_t *rme9652,
+static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652,
int stream,
int channel)
@@ -1930,10 +1930,10 @@ static char *rme9652_channel_buffer_location(rme9652_t *rme9652,
}
}
-static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel,
+static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -1947,10 +1947,10 @@ static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel
return count;
}
-static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,
+static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -1964,10 +1964,10 @@ static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,
return count;
}
-static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,
+static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1978,11 +1978,11 @@ static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,
return count;
}
-static int snd_rme9652_reset(snd_pcm_substream_t *substream)
+static int snd_rme9652_reset(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
other = rme9652->capture_substream;
else
@@ -1993,8 +1993,8 @@ static int snd_rme9652_reset(snd_pcm_substream_t *substream)
runtime->status->hw_ptr = 0;
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
- snd_pcm_runtime_t *oruntime = other->runtime;
+ struct snd_pcm_substream *s;
+ struct snd_pcm_runtime *oruntime = other->runtime;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -2006,10 +2006,10 @@ static int snd_rme9652_reset(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int snd_rme9652_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
int err;
pid_t this_pid;
pid_t other_pid;
@@ -2071,10 +2071,10 @@ static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_rme9652_channel_info(snd_pcm_substream_t *substream,
- snd_pcm_channel_info_t *info)
+static int snd_rme9652_channel_info(struct snd_pcm_substream *substream,
+ struct snd_pcm_channel_info *info)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
int chn;
snd_assert(info->channel < RME9652_NCHANNELS, return -EINVAL);
@@ -2089,7 +2089,7 @@ static int snd_rme9652_channel_info(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_rme9652_ioctl(snd_pcm_substream_t *substream,
+static int snd_rme9652_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
switch (cmd) {
@@ -2099,7 +2099,7 @@ static int snd_rme9652_ioctl(snd_pcm_substream_t *substream,
}
case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
{
- snd_pcm_channel_info_t *info = arg;
+ struct snd_pcm_channel_info *info = arg;
return snd_rme9652_channel_info(substream, info);
}
default:
@@ -2109,16 +2109,16 @@ static int snd_rme9652_ioctl(snd_pcm_substream_t *substream,
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
-static void rme9652_silence_playback(rme9652_t *rme9652)
+static void rme9652_silence_playback(struct snd_rme9652 *rme9652)
{
memset(rme9652->playback_buffer, 0, RME9652_DMA_AREA_BYTES);
}
-static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
+static int snd_rme9652_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
- snd_pcm_substream_t *other;
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_substream *other;
int running;
spin_lock(&rme9652->lock);
running = rme9652->running;
@@ -2141,7 +2141,7 @@ static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
if (other) {
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
if (s == other) {
@@ -2178,9 +2178,9 @@ static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_rme9652_prepare(snd_pcm_substream_t *substream)
+static int snd_rme9652_prepare(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
unsigned long flags;
int result = 0;
@@ -2191,7 +2191,7 @@ static int snd_rme9652_prepare(snd_pcm_substream_t *substream)
return result;
}
-static snd_pcm_hardware_t snd_rme9652_playback_subinfo =
+static struct snd_pcm_hardware snd_rme9652_playback_subinfo =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -2215,7 +2215,7 @@ static snd_pcm_hardware_t snd_rme9652_playback_subinfo =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_rme9652_capture_subinfo =
+static struct snd_pcm_hardware snd_rme9652_capture_subinfo =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -2240,36 +2240,36 @@ static snd_pcm_hardware_t snd_rme9652_capture_subinfo =
static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
-static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
.count = ARRAY_SIZE(period_sizes),
.list = period_sizes,
.mask = 0
};
-static int snd_rme9652_hw_rule_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_rme9652_hw_rule_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- rme9652_t *rme9652 = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_rme9652 *rme9652 = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
unsigned int list[2] = { rme9652->ds_channels, rme9652->ss_channels };
return snd_interval_list(c, 2, list, 0);
}
-static int snd_rme9652_hw_rule_channels_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_rme9652_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- rme9652_t *rme9652 = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_rme9652 *rme9652 = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (r->min > 48000) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = rme9652->ds_channels,
.max = rme9652->ds_channels,
.integer = 1,
};
return snd_interval_refine(c, &t);
} else if (r->max < 88200) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = rme9652->ss_channels,
.max = rme9652->ss_channels,
.integer = 1,
@@ -2279,21 +2279,21 @@ static int snd_rme9652_hw_rule_channels_rate(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_rme9652_hw_rule_rate_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_rme9652_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- rme9652_t *rme9652 = rule->private;
- snd_interval_t *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_interval_t *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_rme9652 *rme9652 = rule->private;
+ struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
if (c->min >= rme9652->ss_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 44100,
.max = 48000,
.integer = 1,
};
return snd_interval_refine(r, &t);
} else if (c->max <= rme9652->ds_channels) {
- snd_interval_t t = {
+ struct snd_interval t = {
.min = 88200,
.max = 96000,
.integer = 1,
@@ -2303,10 +2303,10 @@ static int snd_rme9652_hw_rule_rate_channels(snd_pcm_hw_params_t *params,
return 0;
}
-static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
+static int snd_rme9652_playback_open(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
spin_lock_irq(&rme9652->lock);
@@ -2345,9 +2345,9 @@ static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_rme9652_playback_release(snd_pcm_substream_t *substream)
+static int snd_rme9652_playback_release(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme9652->lock);
@@ -2363,10 +2363,10 @@ static int snd_rme9652_playback_release(snd_pcm_substream_t *substream)
}
-static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
+static int snd_rme9652_capture_open(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
spin_lock_irq(&rme9652->lock);
@@ -2400,9 +2400,9 @@ static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_rme9652_capture_release(snd_pcm_substream_t *substream)
+static int snd_rme9652_capture_release(struct snd_pcm_substream *substream)
{
- rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
spin_lock_irq(&rme9652->lock);
@@ -2413,7 +2413,7 @@ static int snd_rme9652_capture_release(snd_pcm_substream_t *substream)
return 0;
}
-static snd_pcm_ops_t snd_rme9652_playback_ops = {
+static struct snd_pcm_ops snd_rme9652_playback_ops = {
.open = snd_rme9652_playback_open,
.close = snd_rme9652_playback_release,
.ioctl = snd_rme9652_ioctl,
@@ -2425,7 +2425,7 @@ static snd_pcm_ops_t snd_rme9652_playback_ops = {
.silence = snd_rme9652_hw_silence,
};
-static snd_pcm_ops_t snd_rme9652_capture_ops = {
+static struct snd_pcm_ops snd_rme9652_capture_ops = {
.open = snd_rme9652_capture_open,
.close = snd_rme9652_capture_release,
.ioctl = snd_rme9652_ioctl,
@@ -2436,10 +2436,10 @@ static snd_pcm_ops_t snd_rme9652_capture_ops = {
.copy = snd_rme9652_capture_copy,
};
-static int __devinit snd_rme9652_create_pcm(snd_card_t *card,
- rme9652_t *rme9652)
+static int __devinit snd_rme9652_create_pcm(struct snd_card *card,
+ struct snd_rme9652 *rme9652)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(card,
@@ -2460,8 +2460,8 @@ static int __devinit snd_rme9652_create_pcm(snd_card_t *card,
return 0;
}
-static int __devinit snd_rme9652_create(snd_card_t *card,
- rme9652_t *rme9652,
+static int __devinit snd_rme9652_create(struct snd_card *card,
+ struct snd_rme9652 *rme9652,
int precise_ptr)
{
struct pci_dev *pci = rme9652->pci;
@@ -2591,9 +2591,9 @@ static int __devinit snd_rme9652_create(snd_card_t *card,
return 0;
}
-static void snd_rme9652_card_free(snd_card_t *card)
+static void snd_rme9652_card_free(struct snd_card *card)
{
- rme9652_t *rme9652 = (rme9652_t *) card->private_data;
+ struct snd_rme9652 *rme9652 = (struct snd_rme9652 *) card->private_data;
if (rme9652)
snd_rme9652_free(rme9652);
@@ -2603,8 +2603,8 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- rme9652_t *rme9652;
- snd_card_t *card;
+ struct snd_rme9652 *rme9652;
+ struct snd_card *card;
int err;
if (dev >= SNDRV_CARDS)
@@ -2615,12 +2615,12 @@ static int __devinit snd_rme9652_probe(struct pci_dev *pci,
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(rme9652_t));
+ sizeof(struct snd_rme9652));
if (!card)
return -ENOMEM;
- rme9652 = (rme9652_t *) card->private_data;
+ rme9652 = (struct snd_rme9652 *) card->private_data;
card->private_free = snd_rme9652_card_free;
rme9652->dev = dev;
rme9652->pci = pci;
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index e92ef3ae2ca1..7bbea3738b8a 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -195,9 +195,7 @@ MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
*/
-typedef struct _snd_sonicvibes sonicvibes_t;
-
-struct _snd_sonicvibes {
+struct sonicvibes {
unsigned long dma1size;
unsigned long dma2size;
int irq;
@@ -224,20 +222,20 @@ struct _snd_sonicvibes {
unsigned int mode;
struct pci_dev *pci;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
- snd_rawmidi_t *rmidi;
- snd_hwdep_t *fmsynth; /* S3FM */
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
+ struct snd_rawmidi *rmidi;
+ struct snd_hwdep *fmsynth; /* S3FM */
spinlock_t reg_lock;
unsigned int p_dma_size;
unsigned int c_dma_size;
- snd_kcontrol_t *master_mute;
- snd_kcontrol_t *master_volume;
+ struct snd_kcontrol *master_mute;
+ struct snd_kcontrol *master_volume;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
@@ -251,13 +249,13 @@ static struct pci_device_id snd_sonic_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_sonic_ids);
-static ratden_t sonicvibes_adc_clock = {
+static struct snd_ratden sonicvibes_adc_clock = {
.num_min = 4000 * 65536,
.num_max = 48000UL * 65536,
.num_step = 1,
.den = 65536,
};
-static snd_pcm_hw_constraint_ratdens_t snd_sonicvibes_hw_constraints_adc_clock = {
+static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = {
.nrats = 1,
.rats = &sonicvibes_adc_clock,
};
@@ -266,7 +264,7 @@ static snd_pcm_hw_constraint_ratdens_t snd_sonicvibes_hw_constraints_adc_clock =
* common I/O routines
*/
-static inline void snd_sonicvibes_setdmaa(sonicvibes_t * sonic,
+static inline void snd_sonicvibes_setdmaa(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{
@@ -279,7 +277,7 @@ static inline void snd_sonicvibes_setdmaa(sonicvibes_t * sonic,
#endif
}
-static inline void snd_sonicvibes_setdmac(sonicvibes_t * sonic,
+static inline void snd_sonicvibes_setdmac(struct sonicvibes * sonic,
unsigned int addr,
unsigned int count)
{
@@ -294,18 +292,18 @@ static inline void snd_sonicvibes_setdmac(sonicvibes_t * sonic,
#endif
}
-static inline unsigned int snd_sonicvibes_getdmaa(sonicvibes_t * sonic)
+static inline unsigned int snd_sonicvibes_getdmaa(struct sonicvibes * sonic)
{
return (inl(sonic->dmaa_port + SV_DMA_COUNT0) & 0xffffff) + 1;
}
-static inline unsigned int snd_sonicvibes_getdmac(sonicvibes_t * sonic)
+static inline unsigned int snd_sonicvibes_getdmac(struct sonicvibes * sonic)
{
/* note: dmac is working in word mode!!! */
return ((inl(sonic->dmac_port + SV_DMA_COUNT0) & 0xffffff) + 1) << 1;
}
-static void snd_sonicvibes_out1(sonicvibes_t * sonic,
+static void snd_sonicvibes_out1(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{
@@ -315,7 +313,7 @@ static void snd_sonicvibes_out1(sonicvibes_t * sonic,
udelay(10);
}
-static void snd_sonicvibes_out(sonicvibes_t * sonic,
+static void snd_sonicvibes_out(struct sonicvibes * sonic,
unsigned char reg,
unsigned char value)
{
@@ -329,7 +327,7 @@ static void snd_sonicvibes_out(sonicvibes_t * sonic,
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static unsigned char snd_sonicvibes_in1(sonicvibes_t * sonic, unsigned char reg)
+static unsigned char snd_sonicvibes_in1(struct sonicvibes * sonic, unsigned char reg)
{
unsigned char value;
@@ -340,7 +338,7 @@ static unsigned char snd_sonicvibes_in1(sonicvibes_t * sonic, unsigned char reg)
return value;
}
-static unsigned char snd_sonicvibes_in(sonicvibes_t * sonic, unsigned char reg)
+static unsigned char snd_sonicvibes_in(struct sonicvibes * sonic, unsigned char reg)
{
unsigned long flags;
unsigned char value;
@@ -355,7 +353,7 @@ static unsigned char snd_sonicvibes_in(sonicvibes_t * sonic, unsigned char reg)
}
#if 0
-static void snd_sonicvibes_debug(sonicvibes_t * sonic)
+static void snd_sonicvibes_debug(struct sonicvibes * sonic)
{
printk("SV REGS: INDEX = 0x%02x ", inb(SV_REG(sonic, INDEX)));
printk(" STATUS = 0x%02x\n", inb(SV_REG(sonic, STATUS)));
@@ -427,7 +425,7 @@ static void snd_sonicvibes_debug(sonicvibes_t * sonic)
#endif
-static void snd_sonicvibes_setfmt(sonicvibes_t * sonic,
+static void snd_sonicvibes_setfmt(struct sonicvibes * sonic,
unsigned char mask,
unsigned char value)
{
@@ -483,7 +481,7 @@ static void snd_sonicvibes_pll(unsigned int rate,
#endif
}
-static void snd_sonicvibes_setpll(sonicvibes_t * sonic,
+static void snd_sonicvibes_setpll(struct sonicvibes * sonic,
unsigned char reg,
unsigned int rate)
{
@@ -499,7 +497,7 @@ static void snd_sonicvibes_setpll(sonicvibes_t * sonic,
}
}
-static void snd_sonicvibes_set_adc_rate(sonicvibes_t * sonic, unsigned int rate)
+static void snd_sonicvibes_set_adc_rate(struct sonicvibes * sonic, unsigned int rate)
{
unsigned long flags;
unsigned int div;
@@ -520,8 +518,8 @@ static void snd_sonicvibes_set_adc_rate(sonicvibes_t * sonic, unsigned int rate)
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static int snd_sonicvibes_hw_constraint_dac_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_sonicvibes_hw_constraint_dac_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
unsigned int rate, div, r, m, n;
@@ -545,7 +543,7 @@ static int snd_sonicvibes_hw_constraint_dac_rate(snd_pcm_hw_params_t *params,
return 0;
}
-static void snd_sonicvibes_set_dac_rate(sonicvibes_t * sonic, unsigned int rate)
+static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int rate)
{
unsigned int div;
unsigned long flags;
@@ -559,7 +557,7 @@ static void snd_sonicvibes_set_dac_rate(sonicvibes_t * sonic, unsigned int rate)
spin_unlock_irqrestore(&sonic->reg_lock, flags);
}
-static int snd_sonicvibes_trigger(sonicvibes_t * sonic, int what, int cmd)
+static int snd_sonicvibes_trigger(struct sonicvibes * sonic, int what, int cmd)
{
int result = 0;
@@ -583,7 +581,7 @@ static int snd_sonicvibes_trigger(sonicvibes_t * sonic, int what, int cmd)
static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- sonicvibes_t *sonic = dev_id;
+ struct sonicvibes *sonic = dev_id;
unsigned char status;
status = inb(SV_REG(sonic, STATUS));
@@ -646,35 +644,35 @@ static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_reg
* PCM part
*/
-static int snd_sonicvibes_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_sonicvibes_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
return snd_sonicvibes_trigger(sonic, 1, cmd);
}
-static int snd_sonicvibes_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
return snd_sonicvibes_trigger(sonic, 2, cmd);
}
-static int snd_sonicvibes_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_sonicvibes_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_sonicvibes_hw_free(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char fmt = 0;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -695,10 +693,10 @@ static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_prepare(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned char fmt = 0;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned int count = snd_pcm_lib_period_bytes(substream);
@@ -720,9 +718,9 @@ static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(sonic->enable & 1))
@@ -731,9 +729,9 @@ static snd_pcm_uframes_t snd_sonicvibes_playback_pointer(snd_pcm_substream_t * s
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(sonic->enable & 2))
return 0;
@@ -741,7 +739,7 @@ static snd_pcm_uframes_t snd_sonicvibes_capture_pointer(snd_pcm_substream_t * su
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_hardware_t snd_sonicvibes_playback =
+static struct snd_pcm_hardware snd_sonicvibes_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -760,7 +758,7 @@ static snd_pcm_hardware_t snd_sonicvibes_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_sonicvibes_capture =
+static struct snd_pcm_hardware snd_sonicvibes_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -779,10 +777,10 @@ static snd_pcm_hardware_t snd_sonicvibes_capture =
.fifo_size = 0,
};
-static int snd_sonicvibes_playback_open(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_open(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
sonic->mode |= SV_MODE_PLAY;
sonic->playback_substream = substream;
@@ -791,10 +789,10 @@ static int snd_sonicvibes_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sonicvibes_capture_open(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_open(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
sonic->mode |= SV_MODE_CAPTURE;
sonic->capture_substream = substream;
@@ -804,25 +802,25 @@ static int snd_sonicvibes_capture_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_sonicvibes_playback_close(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_playback_close(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
sonic->playback_substream = NULL;
sonic->mode &= ~SV_MODE_PLAY;
return 0;
}
-static int snd_sonicvibes_capture_close(snd_pcm_substream_t * substream)
+static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
{
- sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
+ struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
sonic->capture_substream = NULL;
sonic->mode &= ~SV_MODE_CAPTURE;
return 0;
}
-static snd_pcm_ops_t snd_sonicvibes_playback_ops = {
+static struct snd_pcm_ops snd_sonicvibes_playback_ops = {
.open = snd_sonicvibes_playback_open,
.close = snd_sonicvibes_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -833,7 +831,7 @@ static snd_pcm_ops_t snd_sonicvibes_playback_ops = {
.pointer = snd_sonicvibes_playback_pointer,
};
-static snd_pcm_ops_t snd_sonicvibes_capture_ops = {
+static struct snd_pcm_ops snd_sonicvibes_capture_ops = {
.open = snd_sonicvibes_capture_open,
.close = snd_sonicvibes_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -844,16 +842,9 @@ static snd_pcm_ops_t snd_sonicvibes_capture_ops = {
.pointer = snd_sonicvibes_capture_pointer,
};
-static void snd_sonicvibes_pcm_free(snd_pcm_t *pcm)
-{
- sonicvibes_t *sonic = pcm->private_data;
- sonic->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __devinit snd_sonicvibes_pcm(sonicvibes_t * sonic, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_sonicvibes_pcm(struct sonicvibes * sonic, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(sonic->card, "s3_86c617", device, 1, 1, &pcm)) < 0)
@@ -864,7 +855,6 @@ static int __devinit snd_sonicvibes_pcm(sonicvibes_t * sonic, int device, snd_pc
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sonicvibes_capture_ops);
pcm->private_data = sonic;
- pcm->private_free = snd_sonicvibes_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, "S3 SonicVibes");
sonic->pcm = pcm;
@@ -886,7 +876,7 @@ static int __devinit snd_sonicvibes_pcm(sonicvibes_t * sonic, int device, snd_pc
.info = snd_sonicvibes_info_mux, \
.get = snd_sonicvibes_get_mux, .put = snd_sonicvibes_put_mux }
-static int snd_sonicvibes_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[7] = {
"CD", "PCM", "Aux1", "Line", "Aux0", "Mic", "Mix"
@@ -901,9 +891,9 @@ static int snd_sonicvibes_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_sonicvibes_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&sonic->reg_lock);
ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
@@ -912,9 +902,9 @@ static int snd_sonicvibes_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
unsigned short left, right, oval1, oval2;
int change;
@@ -941,7 +931,7 @@ static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
.get = snd_sonicvibes_get_single, .put = snd_sonicvibes_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-static int snd_sonicvibes_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -952,9 +942,9 @@ static int snd_sonicvibes_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -968,9 +958,9 @@ static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -997,7 +987,7 @@ static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
.get = snd_sonicvibes_get_double, .put = snd_sonicvibes_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static int snd_sonicvibes_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_sonicvibes_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1008,9 +998,9 @@ static int snd_sonicvibes_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1029,9 +1019,9 @@ static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1061,7 +1051,7 @@ static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
return change;
}
-static snd_kcontrol_new_t snd_sonicvibes_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_controls[] __devinitdata = {
SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
@@ -1085,17 +1075,17 @@ SONICVIBES_SINGLE("Loopback Capture Volume", 0, SV_IREG_ADC_OUTPUT_CTRL, 2, 63,
SONICVIBES_MUX("Capture Source", 0)
};
-static void snd_sonicvibes_master_free(snd_kcontrol_t *kcontrol)
+static void snd_sonicvibes_master_free(struct snd_kcontrol *kcontrol)
{
- sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
+ struct sonicvibes *sonic = snd_kcontrol_chip(kcontrol);
sonic->master_mute = NULL;
sonic->master_volume = NULL;
}
-static int __devinit snd_sonicvibes_mixer(sonicvibes_t * sonic)
+static int __devinit snd_sonicvibes_mixer(struct sonicvibes * sonic)
{
- snd_card_t *card;
- snd_kcontrol_t *kctl;
+ struct snd_card *card;
+ struct snd_kcontrol *kctl;
unsigned int idx;
int err;
@@ -1118,10 +1108,10 @@ static int __devinit snd_sonicvibes_mixer(sonicvibes_t * sonic)
*/
-static void snd_sonicvibes_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_sonicvibes_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- sonicvibes_t *sonic = entry->private_data;
+ struct sonicvibes *sonic = entry->private_data;
unsigned char tmp;
tmp = sonic->srs_space & 0x0f;
@@ -1148,9 +1138,9 @@ static void snd_sonicvibes_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "MIDI to ext. Tx : %s\n", tmp & 0x04 ? "on" : "off");
}
-static void __devinit snd_sonicvibes_proc_init(sonicvibes_t * sonic)
+static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read);
@@ -1161,10 +1151,10 @@ static void __devinit snd_sonicvibes_proc_init(sonicvibes_t * sonic)
*/
#ifdef SUPPORT_JOYSTICK
-static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata =
+static struct snd_kcontrol_new snd_sonicvibes_game_control __devinitdata =
SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
-static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
+static int __devinit snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
{
struct gameport *gp;
@@ -1186,7 +1176,7 @@ static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
return 0;
}
-static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic)
+static void snd_sonicvibes_free_gameport(struct sonicvibes *sonic)
{
if (sonic->gameport) {
gameport_unregister_port(sonic->gameport);
@@ -1194,11 +1184,11 @@ static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic)
}
}
#else
-static inline int snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { return -ENOSYS; }
-static inline void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) { }
+static inline int snd_sonicvibes_create_gameport(struct sonicvibes *sonic) { return -ENOSYS; }
+static inline void snd_sonicvibes_free_gameport(struct sonicvibes *sonic) { }
#endif
-static int snd_sonicvibes_free(sonicvibes_t *sonic)
+static int snd_sonicvibes_free(struct sonicvibes *sonic)
{
snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
@@ -1213,22 +1203,22 @@ static int snd_sonicvibes_free(sonicvibes_t *sonic)
return 0;
}
-static int snd_sonicvibes_dev_free(snd_device_t *device)
+static int snd_sonicvibes_dev_free(struct snd_device *device)
{
- sonicvibes_t *sonic = device->device_data;
+ struct sonicvibes *sonic = device->device_data;
return snd_sonicvibes_free(sonic);
}
-static int __devinit snd_sonicvibes_create(snd_card_t * card,
+static int __devinit snd_sonicvibes_create(struct snd_card *card,
struct pci_dev *pci,
int reverb,
int mge,
- sonicvibes_t ** rsonic)
+ struct sonicvibes ** rsonic)
{
- sonicvibes_t *sonic;
+ struct sonicvibes *sonic;
unsigned int dmaa, dmac;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_sonicvibes_dev_free,
};
@@ -1373,7 +1363,7 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
* MIDI section
*/
-static snd_kcontrol_new_t snd_sonicvibes_midi_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] __devinitdata = {
SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
@@ -1381,24 +1371,25 @@ SONICVIBES_SINGLE("SonicVibes External Rx to Synth", 0, SV_IREG_MPU401, 1, 1, 0)
SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0)
};
-static int snd_sonicvibes_midi_input_open(mpu401_t * mpu)
+static int snd_sonicvibes_midi_input_open(struct snd_mpu401 * mpu)
{
- sonicvibes_t *sonic = mpu->private_data;
+ struct sonicvibes *sonic = mpu->private_data;
outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
return 0;
}
-static void snd_sonicvibes_midi_input_close(mpu401_t * mpu)
+static void snd_sonicvibes_midi_input_close(struct snd_mpu401 * mpu)
{
- sonicvibes_t *sonic = mpu->private_data;
+ struct sonicvibes *sonic = mpu->private_data;
outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
}
-static int __devinit snd_sonicvibes_midi(sonicvibes_t * sonic, snd_rawmidi_t * rmidi)
+static int __devinit snd_sonicvibes_midi(struct sonicvibes * sonic,
+ struct snd_rawmidi *rmidi)
{
- mpu401_t * mpu = rmidi->private_data;
- snd_card_t *card = sonic->card;
- snd_rawmidi_str_t *dir;
+ struct snd_mpu401 * mpu = rmidi->private_data;
+ struct snd_card *card = sonic->card;
+ struct snd_rawmidi_str *dir;
unsigned int idx;
int err;
@@ -1416,10 +1407,10 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- sonicvibes_t *sonic;
- snd_rawmidi_t *midi_uart;
- opl3_t *opl3;
+ struct snd_card *card;
+ struct sonicvibes *sonic;
+ struct snd_rawmidi *midi_uart;
+ struct snd_opl3 *opl3;
int idx, err;
if (dev >= SNDRV_CARDS)
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 940d531575c0..2b21df16ad6a 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -76,8 +76,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
- trident_t *trident;
+ struct snd_card *card;
+ struct snd_trident *trident;
const char *str;
int err, pcm_dev = 0;
@@ -100,6 +100,7 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = trident;
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
@@ -180,7 +181,10 @@ static struct pci_driver driver = {
.id_table = snd_trident_ids,
.probe = snd_trident_probe,
.remove = __devexit_p(snd_trident_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_trident_suspend,
+ .resume = snd_trident_resume,
+#endif
};
static int __init alsa_card_trident_init(void)
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index b9b93c7faafd..83b7d8aba9e6 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -44,17 +44,19 @@
#include <asm/io.h>
-static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
-static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
-static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-#ifdef CONFIG_PM
-static int snd_trident_suspend(snd_card_t *card, pm_message_t state);
-static int snd_trident_resume(snd_card_t *card);
-#endif
-static int snd_trident_sis_reset(trident_t *trident);
-
-static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max);
-static int snd_trident_free(trident_t *trident);
+static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
+ struct snd_trident_voice * voice,
+ struct snd_pcm_substream *substream);
+static int snd_trident_pcm_mixer_free(struct snd_trident *trident,
+ struct snd_trident_voice * voice,
+ struct snd_pcm_substream *substream);
+static irqreturn_t snd_trident_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs);
+static int snd_trident_sis_reset(struct snd_trident *trident);
+
+static void snd_trident_clear_voices(struct snd_trident * trident,
+ unsigned short v_min, unsigned short v_max);
+static int snd_trident_free(struct snd_trident *trident);
/*
* common I/O routines
@@ -62,7 +64,7 @@ static int snd_trident_free(trident_t *trident);
#if 0
-static void snd_trident_print_voice_regs(trident_t *trident, int voice)
+static void snd_trident_print_voice_regs(struct snd_trident *trident, int voice)
{
unsigned int val, tmp;
@@ -104,7 +106,7 @@ static void snd_trident_print_voice_regs(trident_t *trident, int voice)
#endif
/*---------------------------------------------------------------------------
- unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
+ unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
Description: This routine will do all of the reading from the external
CODEC (AC97).
@@ -115,12 +117,12 @@ static void snd_trident_print_voice_regs(trident_t *trident, int voice)
returns: 16 bit value read from the AC97.
---------------------------------------------------------------------------*/
-static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_trident_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
unsigned int data = 0, treg;
unsigned short count = 0xffff;
unsigned long flags;
- trident_t *trident = ac97->private_data;
+ struct snd_trident *trident = ac97->private_data;
spin_lock_irqsave(&trident->reg_lock, flags);
if (trident->device == TRIDENT_DEVICE_ID_DX) {
@@ -153,7 +155,8 @@ static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
}
if (count == 0 && !trident->ac97_detect) {
- snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n", reg, data);
+ snd_printk(KERN_ERR "ac97 codec read TIMEOUT [0x%x/0x%x]!!!\n",
+ reg, data);
data = 0;
}
@@ -162,7 +165,8 @@ static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
}
/*---------------------------------------------------------------------------
- void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
+ void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short wdata)
Description: This routine will do all of the writing to the external
CODEC (AC97).
@@ -174,12 +178,13 @@ static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
returns: TRUE if everything went ok, else FALSE.
---------------------------------------------------------------------------*/
-static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned short wdata)
+static void snd_trident_codec_write(struct snd_ac97 *ac97, unsigned short reg,
+ unsigned short wdata)
{
unsigned int address, data;
unsigned short count = 0xffff;
unsigned long flags;
- trident_t *trident = ac97->private_data;
+ struct snd_trident *trident = ac97->private_data;
data = ((unsigned long) wdata) << 16;
@@ -230,7 +235,7 @@ static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned s
}
/*---------------------------------------------------------------------------
- void snd_trident_enable_eso(trident_t *trident)
+ void snd_trident_enable_eso(struct snd_trident *trident)
Description: This routine will enable end of loop interrupts.
End of loop interrupts will occur when a running
@@ -241,7 +246,7 @@ static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned s
---------------------------------------------------------------------------*/
-static void snd_trident_enable_eso(trident_t * trident)
+static void snd_trident_enable_eso(struct snd_trident * trident)
{
unsigned int val;
@@ -254,7 +259,7 @@ static void snd_trident_enable_eso(trident_t * trident)
}
/*---------------------------------------------------------------------------
- void snd_trident_disable_eso(trident_t *trident)
+ void snd_trident_disable_eso(struct snd_trident *trident)
Description: This routine will disable end of loop interrupts.
End of loop interrupts will occur when a running
@@ -268,7 +273,7 @@ static void snd_trident_enable_eso(trident_t * trident)
---------------------------------------------------------------------------*/
-static void snd_trident_disable_eso(trident_t * trident)
+static void snd_trident_disable_eso(struct snd_trident * trident)
{
unsigned int tmp;
@@ -279,7 +284,7 @@ static void snd_trident_disable_eso(trident_t * trident)
}
/*---------------------------------------------------------------------------
- void snd_trident_start_voice(trident_t * trident, unsigned int voice)
+ void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
Description: Start a voice, any channel 0 thru 63.
This routine automatically handles the fact that there are
@@ -292,7 +297,7 @@ static void snd_trident_disable_eso(trident_t * trident)
---------------------------------------------------------------------------*/
-void snd_trident_start_voice(trident_t * trident, unsigned int voice)
+void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice)
{
unsigned int mask = 1 << (voice & 0x1f);
unsigned int reg = (voice & 0x20) ? T4D_START_B : T4D_START_A;
@@ -301,7 +306,7 @@ void snd_trident_start_voice(trident_t * trident, unsigned int voice)
}
/*---------------------------------------------------------------------------
- void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
+ void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
Description: Stop a voice, any channel 0 thru 63.
This routine automatically handles the fact that there are
@@ -314,7 +319,7 @@ void snd_trident_start_voice(trident_t * trident, unsigned int voice)
---------------------------------------------------------------------------*/
-void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
+void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
{
unsigned int mask = 1 << (voice & 0x1f);
unsigned int reg = (voice & 0x20) ? T4D_STOP_B : T4D_STOP_A;
@@ -323,7 +328,7 @@ void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
}
/*---------------------------------------------------------------------------
- int snd_trident_allocate_pcm_channel(trident_t *trident)
+ int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
Description: Allocate hardware channel in Bank B (32-63).
@@ -333,7 +338,7 @@ void snd_trident_stop_voice(trident_t * trident, unsigned int voice)
---------------------------------------------------------------------------*/
-static int snd_trident_allocate_pcm_channel(trident_t * trident)
+static int snd_trident_allocate_pcm_channel(struct snd_trident * trident)
{
int idx;
@@ -361,7 +366,7 @@ static int snd_trident_allocate_pcm_channel(trident_t * trident)
---------------------------------------------------------------------------*/
-static void snd_trident_free_pcm_channel(trident_t *trident, int channel)
+static void snd_trident_free_pcm_channel(struct snd_trident *trident, int channel)
{
if (channel < 32 || channel > 63)
return;
@@ -383,7 +388,7 @@ static void snd_trident_free_pcm_channel(trident_t *trident, int channel)
---------------------------------------------------------------------------*/
-static int snd_trident_allocate_synth_channel(trident_t * trident)
+static int snd_trident_allocate_synth_channel(struct snd_trident * trident)
{
int idx;
@@ -409,7 +414,7 @@ static int snd_trident_allocate_synth_channel(trident_t * trident)
---------------------------------------------------------------------------*/
-static void snd_trident_free_synth_channel(trident_t *trident, int channel)
+static void snd_trident_free_synth_channel(struct snd_trident *trident, int channel)
{
if (channel < 0 || channel > 31)
return;
@@ -432,8 +437,8 @@ static void snd_trident_free_synth_channel(trident_t *trident, int channel)
---------------------------------------------------------------------------*/
-void snd_trident_write_voice_regs(trident_t * trident,
- snd_trident_voice_t * voice)
+void snd_trident_write_voice_regs(struct snd_trident * trident,
+ struct snd_trident_voice * voice)
{
unsigned int FmcRvolCvol;
unsigned int regs[5];
@@ -452,14 +457,16 @@ void snd_trident_write_voice_regs(trident_t * trident,
(voice->Vol & 0x000003ff) :
((voice->Vol & 0x00003fc) << (16-2)) |
(voice->EC & 0x00000fff);
- regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
+ regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
+ (voice->FMS & 0x0000000f);
regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
regs[3] = (voice->Attribute << 16) | FmcRvolCvol;
break;
case TRIDENT_DEVICE_ID_DX:
regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
(voice->EC & 0x00000fff);
- regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) | (voice->FMS & 0x0000000f);
+ regs[0] = (voice->CSO << 16) | ((voice->Alpha & 0x00000fff) << 4) |
+ (voice->FMS & 0x0000000f);
regs[2] = (voice->ESO << 16) | (voice->Delta & 0x0ffff);
regs[3] = FmcRvolCvol;
break;
@@ -467,8 +474,10 @@ void snd_trident_write_voice_regs(trident_t * trident,
regs[4] |= ((voice->Vol & 0x000003fc) << (16-2)) |
(voice->EC & 0x00000fff);
regs[0] = (voice->Delta << 24) | (voice->CSO & 0x00ffffff);
- regs[2] = ((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff);
- regs[3] = (voice->Alpha << 20) | ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
+ regs[2] = ((voice->Delta << 16) & 0xff000000) |
+ (voice->ESO & 0x00ffffff);
+ regs[3] = (voice->Alpha << 20) |
+ ((voice->FMS & 0x0000000f) << 16) | FmcRvolCvol;
break;
default:
snd_BUG();
@@ -504,14 +513,17 @@ void snd_trident_write_voice_regs(trident_t * trident,
---------------------------------------------------------------------------*/
-static void snd_trident_write_cso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CSO)
+static void snd_trident_write_cso_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int CSO)
{
voice->CSO = CSO;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
if (trident->device != TRIDENT_DEVICE_ID_NX) {
outw(voice->CSO, TRID_REG(trident, CH_DX_CSO_ALPHA_FMS) + 2);
} else {
- outl((voice->Delta << 24) | (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
+ outl((voice->Delta << 24) |
+ (voice->CSO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_CSO));
}
}
@@ -527,14 +539,17 @@ static void snd_trident_write_cso_reg(trident_t * trident, snd_trident_voice_t *
---------------------------------------------------------------------------*/
-static void snd_trident_write_eso_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int ESO)
+static void snd_trident_write_eso_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int ESO)
{
voice->ESO = ESO;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
if (trident->device != TRIDENT_DEVICE_ID_NX) {
outw(voice->ESO, TRID_REG(trident, CH_DX_ESO_DELTA) + 2);
} else {
- outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff), TRID_REG(trident, CH_NX_DELTA_ESO));
+ outl(((voice->Delta << 16) & 0xff000000) | (voice->ESO & 0x00ffffff),
+ TRID_REG(trident, CH_NX_DELTA_ESO));
}
}
@@ -550,7 +565,9 @@ static void snd_trident_write_eso_reg(trident_t * trident, snd_trident_voice_t *
---------------------------------------------------------------------------*/
-static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Vol)
+static void snd_trident_write_vol_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int Vol)
{
voice->Vol = Vol;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
@@ -561,7 +578,8 @@ static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t *
break;
case TRIDENT_DEVICE_ID_SI7018:
// printk("voice->Vol = 0x%x\n", voice->Vol);
- outw((voice->CTRL << 12) | voice->Vol, TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
+ outw((voice->CTRL << 12) | voice->Vol,
+ TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC));
break;
}
}
@@ -578,11 +596,14 @@ static void snd_trident_write_vol_reg(trident_t * trident, snd_trident_voice_t *
---------------------------------------------------------------------------*/
-static void snd_trident_write_pan_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int Pan)
+static void snd_trident_write_pan_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int Pan)
{
voice->Pan = Pan;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
- outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f), TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
+ outb(((voice->GVSel & 0x01) << 7) | (voice->Pan & 0x7f),
+ TRID_REG(trident, CH_GVSEL_PAN_VOL_CTRL_EC + 3));
}
/*---------------------------------------------------------------------------
@@ -597,12 +618,16 @@ static void snd_trident_write_pan_reg(trident_t * trident, snd_trident_voice_t *
---------------------------------------------------------------------------*/
-static void snd_trident_write_rvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int RVol)
+static void snd_trident_write_rvol_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int RVol)
{
voice->RVol = RVol;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
- outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
- TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
+ outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
+ (voice->CVol & 0x007f),
+ TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
+ CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
}
/*---------------------------------------------------------------------------
@@ -617,12 +642,16 @@ static void snd_trident_write_rvol_reg(trident_t * trident, snd_trident_voice_t
---------------------------------------------------------------------------*/
-static void snd_trident_write_cvol_reg(trident_t * trident, snd_trident_voice_t * voice, unsigned int CVol)
+static void snd_trident_write_cvol_reg(struct snd_trident * trident,
+ struct snd_trident_voice * voice,
+ unsigned int CVol)
{
voice->CVol = CVol;
outb(voice->number, TRID_REG(trident, T4D_LFO_GC_CIR));
- outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) | (voice->CVol & 0x007f),
- TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ? CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
+ outw(((voice->FMC & 0x0003) << 14) | ((voice->RVol & 0x007f) << 7) |
+ (voice->CVol & 0x007f),
+ TRID_REG(trident, trident->device == TRIDENT_DEVICE_ID_NX ?
+ CH_NX_ALPHA_FMS_FMC_RVOL_CVOL : CH_DX_FMC_RVOL_CVOL));
}
/*---------------------------------------------------------------------------
@@ -696,7 +725,8 @@ static unsigned int snd_trident_convert_adc_rate(unsigned int rate)
Returns: Delta value.
---------------------------------------------------------------------------*/
-static unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned int period_size)
+static unsigned int snd_trident_spurious_threshold(unsigned int rate,
+ unsigned int period_size)
{
unsigned int res = (rate * period_size) / 48000;
if (res < 64)
@@ -717,10 +747,10 @@ static unsigned int snd_trident_spurious_threshold(unsigned int rate, unsigned i
Returns: Control value.
---------------------------------------------------------------------------*/
-static unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream)
+static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream)
{
unsigned int CTRL;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
/* set ctrl mode
CTRL default: 8-bit (unsigned) mono, loop mode enabled
@@ -752,7 +782,7 @@ static unsigned int snd_trident_control_mode(snd_pcm_substream_t *substream)
---------------------------------------------------------------------------*/
-static int snd_trident_ioctl(snd_pcm_substream_t * substream,
+static int snd_trident_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd,
void *arg)
{
@@ -774,12 +804,12 @@ static int snd_trident_ioctl(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
int err;
if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -808,13 +838,13 @@ static int snd_trident_allocate_pcm_mem(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_allocate_evoice(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_allocate_evoice(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice->extra;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice->extra;
/* voice management */
@@ -848,8 +878,8 @@ static int snd_trident_allocate_evoice(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int err;
@@ -870,12 +900,12 @@ static int snd_trident_hw_params(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_hw_free(snd_pcm_substream_t * substream)
+static int snd_trident_hw_free(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
if (trident->tlb.entries) {
if (voice && voice->memblk) {
@@ -902,13 +932,13 @@ static int snd_trident_hw_free(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_trident_playback_prepare(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice->extra;
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice->extra;
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
spin_lock_irq(&trident->reg_lock);
@@ -988,8 +1018,8 @@ static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_trident_allocate_pcm_mem(substream, hw_params);
}
@@ -1005,11 +1035,11 @@ static int snd_trident_capture_hw_params(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
unsigned int val, ESO_bytes;
spin_lock_irq(&trident->reg_lock);
@@ -1097,8 +1127,8 @@ static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_si7018_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int err;
@@ -1119,12 +1149,12 @@ static int snd_trident_si7018_capture_hw_params(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_si7018_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice ? voice->extra : NULL;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
snd_pcm_lib_free_pages(substream);
if (evoice != NULL) {
@@ -1145,12 +1175,12 @@ static int snd_trident_si7018_capture_hw_free(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_si7018_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_trident_si7018_capture_prepare(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice->extra;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice->extra;
spin_lock_irq(&trident->reg_lock);
@@ -1216,12 +1246,12 @@ static int snd_trident_si7018_capture_prepare(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_foldback_prepare(snd_pcm_substream_t * substream)
+static int snd_trident_foldback_prepare(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice->extra;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice->extra;
spin_lock_irq(&trident->reg_lock);
@@ -1294,10 +1324,10 @@ static int snd_trident_foldback_prepare(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_trident_spdif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
unsigned int old_bits = 0, change = 0;
int err;
@@ -1359,13 +1389,13 @@ static int snd_trident_spdif_hw_params(snd_pcm_substream_t * substream,
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream)
+static int snd_trident_spdif_prepare(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- snd_trident_voice_t *evoice = voice->extra;
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident_voice *evoice = voice->extra;
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[substream->number];
unsigned int RESO, LBAO;
unsigned int temp;
@@ -1498,15 +1528,15 @@ static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_trigger(snd_pcm_substream_t *substream,
+static int snd_trident_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
struct list_head *pos;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
unsigned int what, whati, capture_flag, spdif_flag;
- snd_trident_voice_t *voice, *evoice;
+ struct snd_trident_voice *voice, *evoice;
unsigned int val, go;
switch (cmd) {
@@ -1528,8 +1558,8 @@ static int snd_trident_trigger(snd_pcm_substream_t *substream,
val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
snd_pcm_group_for_each(pos, substream) {
s = snd_pcm_group_substream_entry(pos);
- if ((trident_t *) snd_pcm_substream_chip(s) == trident) {
- voice = (snd_trident_voice_t *) s->runtime->private_data;
+ if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) {
+ voice = s->runtime->private_data;
evoice = voice->extra;
what |= 1 << (voice->number & 0x1f);
if (evoice == NULL) {
@@ -1596,11 +1626,11 @@ static int snd_trident_trigger(snd_pcm_substream_t *substream,
---------------------------------------------------------------------------*/
-static snd_pcm_uframes_t snd_trident_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_trident_playback_pointer(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
unsigned int cso;
if (!voice->running)
@@ -1635,11 +1665,11 @@ static snd_pcm_uframes_t snd_trident_playback_pointer(snd_pcm_substream_t * subs
---------------------------------------------------------------------------*/
-static snd_pcm_uframes_t snd_trident_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_trident_capture_pointer(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
unsigned int result;
if (!voice->running)
@@ -1665,11 +1695,11 @@ static snd_pcm_uframes_t snd_trident_capture_pointer(snd_pcm_substream_t * subst
---------------------------------------------------------------------------*/
-static snd_pcm_uframes_t snd_trident_spdif_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_trident_spdif_pointer(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
unsigned int result;
if (!voice->running)
@@ -1684,7 +1714,7 @@ static snd_pcm_uframes_t snd_trident_spdif_pointer(snd_pcm_substream_t * substre
* Playback support device description
*/
-static snd_pcm_hardware_t snd_trident_playback =
+static struct snd_pcm_hardware snd_trident_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1709,7 +1739,7 @@ static snd_pcm_hardware_t snd_trident_playback =
* Capture support device description
*/
-static snd_pcm_hardware_t snd_trident_capture =
+static struct snd_pcm_hardware snd_trident_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1734,7 +1764,7 @@ static snd_pcm_hardware_t snd_trident_capture =
* Foldback capture support device description
*/
-static snd_pcm_hardware_t snd_trident_foldback =
+static struct snd_pcm_hardware snd_trident_foldback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1758,7 +1788,7 @@ static snd_pcm_hardware_t snd_trident_foldback =
* SPDIF playback support device description
*/
-static snd_pcm_hardware_t snd_trident_spdif =
+static struct snd_pcm_hardware snd_trident_spdif =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1779,7 +1809,7 @@ static snd_pcm_hardware_t snd_trident_spdif =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_trident_spdif_7018 =
+static struct snd_pcm_hardware snd_trident_spdif_7018 =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1799,10 +1829,10 @@ static snd_pcm_hardware_t snd_trident_spdif_7018 =
.fifo_size = 0,
};
-static void snd_trident_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_trident_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
- trident_t *trident;
+ struct snd_trident_voice *voice = runtime->private_data;
+ struct snd_trident *trident;
if (voice) {
trident = voice->trident;
@@ -1810,11 +1840,11 @@ static void snd_trident_pcm_free_substream(snd_pcm_runtime_t *runtime)
}
}
-static int snd_trident_playback_open(snd_pcm_substream_t * substream)
+static int snd_trident_playback_open(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL)
@@ -1838,11 +1868,11 @@ static int snd_trident_playback_open(snd_pcm_substream_t * substream)
Parameters: substream - PCM substream class
---------------------------------------------------------------------------*/
-static int snd_trident_playback_close(snd_pcm_substream_t * substream)
+static int snd_trident_playback_close(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_trident_voice *voice = runtime->private_data;
snd_trident_pcm_mixer_free(trident, voice, substream);
return 0;
@@ -1859,11 +1889,11 @@ static int snd_trident_playback_close(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_open(snd_pcm_substream_t * substream)
+static int snd_trident_spdif_open(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_trident_voice_t *voice;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident_voice *voice;
+ struct snd_pcm_runtime *runtime = substream->runtime;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL)
@@ -1900,9 +1930,9 @@ static int snd_trident_spdif_open(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_close(snd_pcm_substream_t * substream)
+static int snd_trident_spdif_close(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
unsigned int temp;
spin_lock_irq(&trident->reg_lock);
@@ -1938,11 +1968,11 @@ static int snd_trident_spdif_close(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_capture_open(snd_pcm_substream_t * substream)
+static int snd_trident_capture_open(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_trident_voice_t *voice;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident_voice *voice;
+ struct snd_pcm_runtime *runtime = substream->runtime;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL)
@@ -1966,7 +1996,7 @@ static int snd_trident_capture_open(snd_pcm_substream_t * substream)
Parameters: substream - PCM substream class
---------------------------------------------------------------------------*/
-static int snd_trident_capture_close(snd_pcm_substream_t * substream)
+static int snd_trident_capture_close(struct snd_pcm_substream *substream)
{
return 0;
}
@@ -1982,11 +2012,11 @@ static int snd_trident_capture_close(snd_pcm_substream_t * substream)
---------------------------------------------------------------------------*/
-static int snd_trident_foldback_open(snd_pcm_substream_t * substream)
+static int snd_trident_foldback_open(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_trident_voice_t *voice;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident_voice *voice;
+ struct snd_pcm_runtime *runtime = substream->runtime;
voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_PCM, 0, 0);
if (voice == NULL)
@@ -2009,12 +2039,12 @@ static int snd_trident_foldback_open(snd_pcm_substream_t * substream)
Parameters: substream - PCM substream class
---------------------------------------------------------------------------*/
-static int snd_trident_foldback_close(snd_pcm_substream_t * substream)
+static int snd_trident_foldback_close(struct snd_pcm_substream *substream)
{
- trident_t *trident = snd_pcm_substream_chip(substream);
- snd_trident_voice_t *voice;
- snd_pcm_runtime_t *runtime = substream->runtime;
- voice = (snd_trident_voice_t *) runtime->private_data;
+ struct snd_trident *trident = snd_pcm_substream_chip(substream);
+ struct snd_trident_voice *voice;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ voice = runtime->private_data;
/* stop capture channel */
spin_lock_irq(&trident->reg_lock);
@@ -2027,7 +2057,7 @@ static int snd_trident_foldback_close(snd_pcm_substream_t * substream)
PCM operations
---------------------------------------------------------------------------*/
-static snd_pcm_ops_t snd_trident_playback_ops = {
+static struct snd_pcm_ops snd_trident_playback_ops = {
.open = snd_trident_playback_open,
.close = snd_trident_playback_close,
.ioctl = snd_trident_ioctl,
@@ -2038,7 +2068,7 @@ static snd_pcm_ops_t snd_trident_playback_ops = {
.pointer = snd_trident_playback_pointer,
};
-static snd_pcm_ops_t snd_trident_nx_playback_ops = {
+static struct snd_pcm_ops snd_trident_nx_playback_ops = {
.open = snd_trident_playback_open,
.close = snd_trident_playback_close,
.ioctl = snd_trident_ioctl,
@@ -2050,7 +2080,7 @@ static snd_pcm_ops_t snd_trident_nx_playback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static snd_pcm_ops_t snd_trident_capture_ops = {
+static struct snd_pcm_ops snd_trident_capture_ops = {
.open = snd_trident_capture_open,
.close = snd_trident_capture_close,
.ioctl = snd_trident_ioctl,
@@ -2061,7 +2091,7 @@ static snd_pcm_ops_t snd_trident_capture_ops = {
.pointer = snd_trident_capture_pointer,
};
-static snd_pcm_ops_t snd_trident_si7018_capture_ops = {
+static struct snd_pcm_ops snd_trident_si7018_capture_ops = {
.open = snd_trident_capture_open,
.close = snd_trident_capture_close,
.ioctl = snd_trident_ioctl,
@@ -2072,7 +2102,7 @@ static snd_pcm_ops_t snd_trident_si7018_capture_ops = {
.pointer = snd_trident_playback_pointer,
};
-static snd_pcm_ops_t snd_trident_foldback_ops = {
+static struct snd_pcm_ops snd_trident_foldback_ops = {
.open = snd_trident_foldback_open,
.close = snd_trident_foldback_close,
.ioctl = snd_trident_ioctl,
@@ -2083,7 +2113,7 @@ static snd_pcm_ops_t snd_trident_foldback_ops = {
.pointer = snd_trident_playback_pointer,
};
-static snd_pcm_ops_t snd_trident_nx_foldback_ops = {
+static struct snd_pcm_ops snd_trident_nx_foldback_ops = {
.open = snd_trident_foldback_open,
.close = snd_trident_foldback_close,
.ioctl = snd_trident_ioctl,
@@ -2095,7 +2125,7 @@ static snd_pcm_ops_t snd_trident_nx_foldback_ops = {
.page = snd_pcm_sgbuf_ops_page,
};
-static snd_pcm_ops_t snd_trident_spdif_ops = {
+static struct snd_pcm_ops snd_trident_spdif_ops = {
.open = snd_trident_spdif_open,
.close = snd_trident_spdif_close,
.ioctl = snd_trident_ioctl,
@@ -2106,7 +2136,7 @@ static snd_pcm_ops_t snd_trident_spdif_ops = {
.pointer = snd_trident_spdif_pointer,
};
-static snd_pcm_ops_t snd_trident_spdif_7018_ops = {
+static struct snd_pcm_ops snd_trident_spdif_7018_ops = {
.open = snd_trident_spdif_open,
.close = snd_trident_spdif_close,
.ioctl = snd_trident_ioctl,
@@ -2118,37 +2148,6 @@ static snd_pcm_ops_t snd_trident_spdif_7018_ops = {
};
/*---------------------------------------------------------------------------
- snd_trident_pcm_free
-
- Description: This routine release the 4DWave private data.
-
- Paramters: private_data - pointer to 4DWave device info.
-
- Returns: None
-
- ---------------------------------------------------------------------------*/
-static void snd_trident_pcm_free(snd_pcm_t *pcm)
-{
- trident_t *trident = pcm->private_data;
- trident->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static void snd_trident_foldback_pcm_free(snd_pcm_t *pcm)
-{
- trident_t *trident = pcm->private_data;
- trident->foldback = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
-{
- trident_t *trident = pcm->private_data;
- trident->spdif = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-/*---------------------------------------------------------------------------
snd_trident_pcm
Description: This routine registers the 4DWave device for PCM support.
@@ -2159,9 +2158,10 @@ static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
---------------------------------------------------------------------------*/
-int __devinit snd_trident_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
+int __devinit snd_trident_pcm(struct snd_trident * trident,
+ int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -2170,7 +2170,6 @@ int __devinit snd_trident_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm
return err;
pcm->private_data = trident;
- pcm->private_free = snd_trident_pcm_free;
if (trident->tlb.entries) {
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_nx_playback_ops);
@@ -2188,7 +2187,7 @@ int __devinit snd_trident_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm
trident->pcm = pcm;
if (trident->tlb.entries) {
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(trident->pci),
@@ -2217,12 +2216,13 @@ int __devinit snd_trident_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm
---------------------------------------------------------------------------*/
-int __devinit snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
+int __devinit snd_trident_foldback_pcm(struct snd_trident * trident,
+ int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *foldback;
+ struct snd_pcm *foldback;
int err;
int num_chan = 3;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
if (rpcm)
*rpcm = NULL;
@@ -2232,7 +2232,6 @@ int __devinit snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_
return err;
foldback->private_data = trident;
- foldback->private_free = snd_trident_foldback_pcm_free;
if (trident->tlb.entries)
snd_pcm_set_ops(foldback, SNDRV_PCM_STREAM_CAPTURE, &snd_trident_nx_foldback_ops);
else
@@ -2274,9 +2273,10 @@ int __devinit snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_
---------------------------------------------------------------------------*/
-int __devinit snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t ** rpcm)
+int __devinit snd_trident_spdif_pcm(struct snd_trident * trident,
+ int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *spdif;
+ struct snd_pcm *spdif;
int err;
if (rpcm)
@@ -2285,7 +2285,6 @@ int __devinit snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t *
return err;
spdif->private_data = trident;
- spdif->private_free = snd_trident_spdif_pcm_free;
if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
snd_pcm_set_ops(spdif, SNDRV_PCM_STREAM_PLAYBACK, &snd_trident_spdif_ops);
} else {
@@ -2313,7 +2312,8 @@ int __devinit snd_trident_spdif_pcm(trident_t * trident, int device, snd_pcm_t *
Description: enable/disable S/PDIF out from ac97 mixer
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_spdif_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2322,10 +2322,10 @@ static int snd_trident_spdif_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_trident_spdif_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned char val;
spin_lock_irq(&trident->reg_lock);
@@ -2335,10 +2335,10 @@ static int snd_trident_spdif_control_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned char val;
int change;
@@ -2366,7 +2366,7 @@ static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_spdif_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
@@ -2382,17 +2382,18 @@ static snd_kcontrol_new_t snd_trident_spdif_control __devinitdata =
Description: put/get the S/PDIF default settings
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_spdif_default_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_trident_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&trident->reg_lock);
ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
@@ -2403,10 +2404,10 @@ static int snd_trident_spdif_default_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2428,7 +2429,7 @@ static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -2443,15 +2444,16 @@ static snd_kcontrol_new_t snd_trident_spdif_default __devinitdata =
Description: put/get the S/PDIF mask
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_spdif_mask_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_trident_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.iec958.status[0] = 0xff;
ucontrol->value.iec958.status[1] = 0xff;
@@ -2460,7 +2462,7 @@ static int snd_trident_spdif_mask_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_trident_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_mask __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2475,17 +2477,18 @@ static snd_kcontrol_new_t snd_trident_spdif_mask __devinitdata =
Description: put/get the S/PDIF stream settings
---------------------------------------------------------------------------*/
-static int snd_trident_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_spdif_stream_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_trident_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&trident->reg_lock);
ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
@@ -2496,10 +2499,10 @@ static int snd_trident_spdif_stream_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -2521,7 +2524,7 @@ static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_trident_spdif_stream __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -2537,7 +2540,8 @@ static snd_kcontrol_new_t snd_trident_spdif_stream __devinitdata =
Description: enable/disable rear path for ac97
---------------------------------------------------------------------------*/
-static int snd_trident_ac97_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_ac97_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -2546,10 +2550,10 @@ static int snd_trident_ac97_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_trident_ac97_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_ac97_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned char val;
spin_lock_irq(&trident->reg_lock);
@@ -2559,10 +2563,10 @@ static int snd_trident_ac97_control_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_ac97_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_ac97_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned char val;
int change = 0;
@@ -2578,7 +2582,7 @@ static int snd_trident_ac97_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_ac97_rear_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_ac97_rear_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Rear Path",
@@ -2594,7 +2598,8 @@ static snd_kcontrol_new_t snd_trident_ac97_rear_control __devinitdata =
Description: wave & music volume control
---------------------------------------------------------------------------*/
-static int snd_trident_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_vol_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -2603,10 +2608,10 @@ static int snd_trident_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_trident_vol_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned int val;
val = trident->musicvol_wavevol;
@@ -2615,10 +2620,10 @@ static int snd_trident_vol_control_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
@@ -2633,7 +2638,7 @@ static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_vol_music_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Music Playback Volume",
@@ -2643,7 +2648,7 @@ static snd_kcontrol_new_t snd_trident_vol_music_control __devinitdata =
.private_value = 16,
};
-static snd_kcontrol_new_t snd_trident_vol_wave_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Wave Playback Volume",
@@ -2659,9 +2664,10 @@ static snd_kcontrol_new_t snd_trident_vol_wave_control __devinitdata =
Description: PCM front volume control
---------------------------------------------------------------------------*/
-static int snd_trident_pcm_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_pcm_vol_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2672,11 +2678,11 @@ static int snd_trident_pcm_vol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_trident_pcm_vol_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_vol_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
ucontrol->value.integer.value[0] = 1023 - mix->vol;
@@ -2686,11 +2692,11 @@ static int snd_trident_pcm_vol_control_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_vol_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
unsigned int val;
int change = 0;
@@ -2708,7 +2714,7 @@ static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_pcm_vol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Front Playback Volume",
@@ -2725,7 +2731,8 @@ static snd_kcontrol_new_t snd_trident_pcm_vol_control __devinitdata =
Description: PCM front pan control
---------------------------------------------------------------------------*/
-static int snd_trident_pcm_pan_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_pcm_pan_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2734,11 +2741,11 @@ static int snd_trident_pcm_pan_control_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_trident_pcm_pan_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_pan_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
ucontrol->value.integer.value[0] = mix->pan;
if (ucontrol->value.integer.value[0] & 0x40) {
@@ -2749,11 +2756,11 @@ static int snd_trident_pcm_pan_control_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_pan_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
unsigned char val;
int change = 0;
@@ -2770,7 +2777,7 @@ static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_pcm_pan_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_pan_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Pan Playback Control",
@@ -2787,7 +2794,8 @@ static snd_kcontrol_new_t snd_trident_pcm_pan_control __devinitdata =
Description: PCM reverb volume control
---------------------------------------------------------------------------*/
-static int snd_trident_pcm_rvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_pcm_rvol_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2796,21 +2804,21 @@ static int snd_trident_pcm_rvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_trident_pcm_rvol_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_rvol_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
ucontrol->value.integer.value[0] = 127 - mix->rvol;
return 0;
}
-static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
unsigned short val;
int change = 0;
@@ -2824,7 +2832,7 @@ static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_pcm_rvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Reverb Playback Volume",
@@ -2841,7 +2849,8 @@ static snd_kcontrol_new_t snd_trident_pcm_rvol_control __devinitdata =
Description: PCM chorus volume control
---------------------------------------------------------------------------*/
-static int snd_trident_pcm_cvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_trident_pcm_cvol_control_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -2850,21 +2859,21 @@ static int snd_trident_pcm_cvol_control_info(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_trident_pcm_cvol_control_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_cvol_control_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
ucontrol->value.integer.value[0] = 127 - mix->cvol;
return 0;
}
-static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_trident_pcm_cvol_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- trident_t *trident = snd_kcontrol_chip(kcontrol);
- snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
+ struct snd_trident *trident = snd_kcontrol_chip(kcontrol);
+ struct snd_trident_pcm_mixer *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
unsigned short val;
int change = 0;
@@ -2878,7 +2887,7 @@ static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_trident_pcm_cvol_control __devinitdata =
+static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Chorus Playback Volume",
@@ -2889,9 +2898,11 @@ static snd_kcontrol_new_t snd_trident_pcm_cvol_control __devinitdata =
.put = snd_trident_pcm_cvol_control_put,
};
-static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kctl, int num, int activate)
+static void snd_trident_notify_pcm_change1(struct snd_card *card,
+ struct snd_kcontrol *kctl,
+ int num, int activate)
{
- snd_ctl_elem_id_t id;
+ struct snd_ctl_elem_id id;
if (! kctl)
return;
@@ -2904,7 +2915,9 @@ static void snd_trident_notify_pcm_change1(snd_card_t * card, snd_kcontrol_t *kc
snd_ctl_build_ioff(&id, kctl, num));
}
-static void snd_trident_notify_pcm_change(trident_t *trident, snd_trident_pcm_mixer_t *tmix, int num, int activate)
+static void snd_trident_notify_pcm_change(struct snd_trident *trident,
+ struct snd_trident_pcm_mixer *tmix,
+ int num, int activate)
{
snd_trident_notify_pcm_change1(trident->card, trident->ctl_vol, num, activate);
snd_trident_notify_pcm_change1(trident->card, trident->ctl_pan, num, activate);
@@ -2912,9 +2925,11 @@ static void snd_trident_notify_pcm_change(trident_t *trident, snd_trident_pcm_mi
snd_trident_notify_pcm_change1(trident->card, trident->ctl_cvol, num, activate);
}
-static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
+static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
+ struct snd_trident_voice *voice,
+ struct snd_pcm_substream *substream)
{
- snd_trident_pcm_mixer_t *tmix;
+ struct snd_trident_pcm_mixer *tmix;
snd_assert(trident != NULL && voice != NULL && substream != NULL, return -EINVAL);
tmix = &trident->pcm_mixer[substream->number];
@@ -2927,9 +2942,9 @@ static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t *
return 0;
}
-static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t *voice, snd_pcm_substream_t *substream)
+static int snd_trident_pcm_mixer_free(struct snd_trident *trident, struct snd_trident_voice *voice, struct snd_pcm_substream *substream)
{
- snd_trident_pcm_mixer_t *tmix;
+ struct snd_trident_pcm_mixer *tmix;
snd_assert(trident != NULL && substream != NULL, return -EINVAL);
tmix = &trident->pcm_mixer[substream->number];
@@ -2949,14 +2964,14 @@ static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t *v
---------------------------------------------------------------------------*/
-static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
+static int __devinit snd_trident_mixer(struct snd_trident * trident, int pcm_spdif_device)
{
- ac97_template_t _ac97;
- snd_card_t * card = trident->card;
- snd_kcontrol_t *kctl;
- snd_ctl_elem_value_t *uctl;
+ struct snd_ac97_template _ac97;
+ struct snd_card *card = trident->card;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_value *uctl;
int idx, err, retries = 2;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_trident_codec_write,
.read = snd_trident_codec_read,
};
@@ -2993,7 +3008,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
snd_printk(KERN_ERR "SI7018: the secondary codec - invalid access\n");
#if 0 // only for my testing purpose --jk
{
- ac97_t *mc97;
+ struct snd_ac97 *mc97;
err = snd_ac97_modem(trident->card, &_ac97, &mc97);
if (err < 0)
snd_printk(KERN_ERR "snd_ac97_modem returned error %i\n", err);
@@ -3016,7 +3031,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
}
for (idx = 0; idx < 32; idx++) {
- snd_trident_pcm_mixer_t *tmix;
+ struct snd_trident_pcm_mixer *tmix;
tmix = &trident->pcm_mixer[idx];
tmix->voice = NULL;
@@ -3114,7 +3129,7 @@ static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device
static unsigned char snd_trident_gameport_read(struct gameport *gameport)
{
- trident_t *chip = gameport_get_port_data(gameport);
+ struct snd_trident *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
return inb(TRID_REG(chip, GAMEPORT_LEGACY));
@@ -3122,7 +3137,7 @@ static unsigned char snd_trident_gameport_read(struct gameport *gameport)
static void snd_trident_gameport_trigger(struct gameport *gameport)
{
- trident_t *chip = gameport_get_port_data(gameport);
+ struct snd_trident *chip = gameport_get_port_data(gameport);
snd_assert(chip, return);
outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
@@ -3130,7 +3145,7 @@ static void snd_trident_gameport_trigger(struct gameport *gameport)
static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- trident_t *chip = gameport_get_port_data(gameport);
+ struct snd_trident *chip = gameport_get_port_data(gameport);
int i;
snd_assert(chip, return 0);
@@ -3147,7 +3162,7 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes
static int snd_trident_gameport_open(struct gameport *gameport, int mode)
{
- trident_t *chip = gameport_get_port_data(gameport);
+ struct snd_trident *chip = gameport_get_port_data(gameport);
snd_assert(chip, return 0);
@@ -3164,7 +3179,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
}
}
-int __devinit snd_trident_create_gameport(trident_t *chip)
+int __devinit snd_trident_create_gameport(struct snd_trident *chip)
{
struct gameport *gp;
@@ -3190,7 +3205,7 @@ int __devinit snd_trident_create_gameport(trident_t *chip)
return 0;
}
-static inline void snd_trident_free_gameport(trident_t *chip)
+static inline void snd_trident_free_gameport(struct snd_trident *chip)
{
if (chip->gameport) {
gameport_unregister_port(chip->gameport);
@@ -3198,14 +3213,14 @@ static inline void snd_trident_free_gameport(trident_t *chip)
}
}
#else
-int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; }
-static inline void snd_trident_free_gameport(trident_t *chip) { }
+int __devinit snd_trident_create_gameport(struct snd_trident *chip) { return -ENOSYS; }
+static inline void snd_trident_free_gameport(struct snd_trident *chip) { }
#endif /* CONFIG_GAMEPORT */
/*
* delay for 1 tick
*/
-static inline void do_delay(trident_t *chip)
+static inline void do_delay(struct snd_trident *chip)
{
schedule_timeout_uninterruptible(1);
}
@@ -3214,7 +3229,7 @@ static inline void do_delay(trident_t *chip)
* SiS reset routine
*/
-static int snd_trident_sis_reset(trident_t *trident)
+static int snd_trident_sis_reset(struct snd_trident *trident)
{
unsigned long end_time;
unsigned int i;
@@ -3267,10 +3282,10 @@ static int snd_trident_sis_reset(trident_t *trident)
* /proc interface
*/
-static void snd_trident_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_trident_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- trident_t *trident = entry->private_data;
+ struct snd_trident *trident = entry->private_data;
char *s;
switch (trident->device) {
@@ -3308,9 +3323,9 @@ static void snd_trident_proc_read(snd_info_entry_t *entry,
#endif
}
-static void __devinit snd_trident_proc_init(trident_t * trident)
+static void __devinit snd_trident_proc_init(struct snd_trident * trident)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
const char *s = "trident";
if (trident->device == TRIDENT_DEVICE_ID_SI7018)
@@ -3319,9 +3334,9 @@ static void __devinit snd_trident_proc_init(trident_t * trident)
snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read);
}
-static int snd_trident_dev_free(snd_device_t *device)
+static int snd_trident_dev_free(struct snd_device *device)
{
- trident_t *trident = device->device_data;
+ struct snd_trident *trident = device->device_data;
return snd_trident_free(trident);
}
@@ -3337,7 +3352,7 @@ static int snd_trident_dev_free(snd_device_t *device)
---------------------------------------------------------------------------*/
-static int __devinit snd_trident_tlb_alloc(trident_t *trident)
+static int __devinit snd_trident_tlb_alloc(struct snd_trident *trident)
{
int i;
@@ -3352,7 +3367,7 @@ static int __devinit snd_trident_tlb_alloc(trident_t *trident)
trident->tlb.entries = (unsigned int*)(((unsigned long)trident->tlb.buffer.area + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1));
trident->tlb.entries_dmaaddr = (trident->tlb.buffer.addr + SNDRV_TRIDENT_MAX_PAGES * 4 - 1) & ~(SNDRV_TRIDENT_MAX_PAGES * 4 - 1);
/* allocate shadow TLB page table (virtual addresses) */
- trident->tlb.shadow_entries = (unsigned long *)vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
+ trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
if (trident->tlb.shadow_entries == NULL) {
snd_printk(KERN_ERR "trident: unable to allocate shadow TLB entries\n");
return -ENOMEM;
@@ -3374,7 +3389,7 @@ static int __devinit snd_trident_tlb_alloc(trident_t *trident)
if (trident->tlb.memhdr == NULL)
return -ENOMEM;
- trident->tlb.memhdr->block_extra_size = sizeof(snd_trident_memblk_arg_t);
+ trident->tlb.memhdr->block_extra_size = sizeof(struct snd_trident_memblk_arg);
return 0;
}
@@ -3382,7 +3397,7 @@ static int __devinit snd_trident_tlb_alloc(trident_t *trident)
* initialize 4D DX chip
*/
-static void snd_trident_stop_all_voices(trident_t *trident)
+static void snd_trident_stop_all_voices(struct snd_trident *trident)
{
outl(0xffffffff, TRID_REG(trident, T4D_STOP_A));
outl(0xffffffff, TRID_REG(trident, T4D_STOP_B));
@@ -3390,7 +3405,7 @@ static void snd_trident_stop_all_voices(trident_t *trident)
outl(0, TRID_REG(trident, T4D_AINTEN_B));
}
-static int snd_trident_4d_dx_init(trident_t *trident)
+static int snd_trident_4d_dx_init(struct snd_trident *trident)
{
struct pci_dev *pci = trident->pci;
unsigned long end_time;
@@ -3430,7 +3445,7 @@ static int snd_trident_4d_dx_init(trident_t *trident)
/*
* initialize 4D NX chip
*/
-static int snd_trident_4d_nx_init(trident_t *trident)
+static int snd_trident_4d_nx_init(struct snd_trident *trident)
{
struct pci_dev *pci = trident->pci;
unsigned long end_time;
@@ -3487,7 +3502,7 @@ static int snd_trident_4d_nx_init(trident_t *trident)
/*
* initialize sis7018 chip
*/
-static int snd_trident_sis_init(trident_t *trident)
+static int snd_trident_sis_init(struct snd_trident *trident)
{
int err;
@@ -3518,18 +3533,18 @@ static int snd_trident_sis_init(trident_t *trident)
---------------------------------------------------------------------------*/
-int __devinit snd_trident_create(snd_card_t * card,
+int __devinit snd_trident_create(struct snd_card *card,
struct pci_dev *pci,
int pcm_streams,
int pcm_spdif_device,
int max_wavetable_size,
- trident_t ** rtrident)
+ struct snd_trident ** rtrident)
{
- trident_t *trident;
+ struct snd_trident *trident;
int i, err;
- snd_trident_voice_t *voice;
- snd_trident_pcm_mixer_t *tmix;
- static snd_device_ops_t ops = {
+ struct snd_trident_voice *voice;
+ struct snd_trident_pcm_mixer *tmix;
+ static struct snd_device_ops ops = {
.dev_free = snd_trident_dev_free,
};
@@ -3577,7 +3592,8 @@ int __devinit snd_trident_create(snd_card_t * card,
}
trident->port = pci_resource_start(pci, 0);
- if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) {
+ if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ,
+ "Trident Audio", trident)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_trident_free(trident);
return -EBUSY;
@@ -3641,8 +3657,6 @@ int __devinit snd_trident_create(snd_card_t * card,
snd_trident_enable_eso(trident);
-
- snd_card_set_pm_callback(card, snd_trident_suspend, snd_trident_resume, trident);
snd_trident_proc_init(trident);
snd_card_set_dev(card, &pci->dev);
*rtrident = trident;
@@ -3661,7 +3675,7 @@ int __devinit snd_trident_create(snd_card_t * card,
---------------------------------------------------------------------------*/
-static int snd_trident_free(trident_t *trident)
+static int snd_trident_free(struct snd_trident *trident)
{
snd_trident_free_gameport(trident);
snd_trident_disable_eso(trident);
@@ -3681,7 +3695,7 @@ static int snd_trident_free(trident_t *trident)
snd_dma_free_pages(&trident->tlb.buffer);
}
if (trident->irq >= 0)
- free_irq(trident->irq, (void *)trident);
+ free_irq(trident->irq, trident);
pci_release_regions(trident->pci);
pci_disable_device(trident->pci);
kfree(trident);
@@ -3708,10 +3722,10 @@ static int snd_trident_free(trident_t *trident)
static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- trident_t *trident = dev_id;
+ struct snd_trident *trident = dev_id;
unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
int delta;
- snd_trident_voice_t *voice;
+ struct snd_trident_voice *voice;
audio_int = inl(TRID_REG(trident, T4D_MISCINT));
if ((audio_int & (ADDRESS_IRQ|MPU401_IRQ)) == 0)
@@ -3813,21 +3827,21 @@ static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *
Returns: None.
---------------------------------------------------------------------------*/
-int snd_trident_attach_synthesizer(trident_t *trident)
+int snd_trident_attach_synthesizer(struct snd_trident *trident)
{
#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
if (snd_seq_device_new(trident->card, 1, SNDRV_SEQ_DEV_ID_TRIDENT,
- sizeof(trident_t*), &trident->seq_dev) >= 0) {
+ sizeof(struct snd_trident *), &trident->seq_dev) >= 0) {
strcpy(trident->seq_dev->name, "4DWave");
- *(trident_t**)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident;
+ *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(trident->seq_dev) = trident;
}
#endif
return 0;
}
-snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int client, int port)
+struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type, int client, int port)
{
- snd_trident_voice_t *pvoice;
+ struct snd_trident_voice *pvoice;
unsigned long flags;
int idx;
@@ -3869,10 +3883,10 @@ snd_trident_voice_t *snd_trident_alloc_voice(trident_t * trident, int type, int
return NULL;
}
-void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice)
+void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
{
unsigned long flags;
- void (*private_free)(snd_trident_voice_t *);
+ void (*private_free)(struct snd_trident_voice *);
void *private_data;
if (voice == NULL || !voice->use)
@@ -3897,7 +3911,7 @@ void snd_trident_free_voice(trident_t * trident, snd_trident_voice_t *voice)
private_free(voice);
}
-static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigned short v_max)
+static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
{
unsigned int i, val, mask[2] = { 0, 0 };
@@ -3918,20 +3932,19 @@ static void snd_trident_clear_voices(trident_t * trident, unsigned short v_min,
}
#ifdef CONFIG_PM
-static int snd_trident_suspend(snd_card_t *card, pm_message_t state)
+int snd_trident_suspend(struct pci_dev *pci, pm_message_t state)
{
- trident_t *trident = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_trident *trident = card->private_data;
trident->in_suspend = 1;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(trident->pcm);
- if (trident->foldback)
- snd_pcm_suspend_all(trident->foldback);
- if (trident->spdif)
- snd_pcm_suspend_all(trident->spdif);
+ snd_pcm_suspend_all(trident->foldback);
+ snd_pcm_suspend_all(trident->spdif);
snd_ac97_suspend(trident->ac97);
- if (trident->ac97_sec)
- snd_ac97_suspend(trident->ac97_sec);
+ snd_ac97_suspend(trident->ac97_sec);
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
@@ -3940,19 +3953,19 @@ static int snd_trident_suspend(snd_card_t *card, pm_message_t state)
case TRIDENT_DEVICE_ID_SI7018:
break;
}
- pci_disable_device(trident->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_trident_resume(snd_card_t *card)
+int snd_trident_resume(struct pci_dev *pci)
{
- trident_t *trident = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_trident *trident = card->private_data;
- pci_enable_device(trident->pci);
- if (pci_set_dma_mask(trident->pci, 0x3fffffff) < 0 ||
- pci_set_consistent_dma_mask(trident->pci, 0x3fffffff) < 0)
- snd_printk(KERN_WARNING "trident: can't set the proper DMA mask\n");
- pci_set_master(trident->pci); /* to be sure */
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci); /* to be sure */
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX:
@@ -3967,14 +3980,14 @@ static int snd_trident_resume(snd_card_t *card)
}
snd_ac97_resume(trident->ac97);
- if (trident->ac97_sec)
- snd_ac97_resume(trident->ac97_sec);
+ snd_ac97_resume(trident->ac97_sec);
/* restore some registers */
outl(trident->musicvol_wavevol, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
snd_trident_enable_eso(trident);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
trident->in_suspend = 0;
return 0;
}
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index f3e6c546af74..cf09ea99755c 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -68,13 +68,14 @@
#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) << 1)
/* fill TLB entries -- we need to fill two entries */
-static inline void set_tlb_bus(trident_t *trident, int page, unsigned long ptr, dma_addr_t addr)
+static inline void set_tlb_bus(struct snd_trident *trident, int page,
+ unsigned long ptr, dma_addr_t addr)
{
page <<= 1;
__set_tlb_bus(trident, page, ptr, addr);
__set_tlb_bus(trident, page+1, ptr + SNDRV_TRIDENT_PAGE_SIZE, addr + SNDRV_TRIDENT_PAGE_SIZE);
}
-static inline void set_silent_tlb(trident_t *trident, int page)
+static inline void set_silent_tlb(struct snd_trident *trident, int page)
{
page <<= 1;
__set_tlb_bus(trident, page, (unsigned long)trident->tlb.silent_page.area, trident->tlb.silent_page.addr);
@@ -97,7 +98,8 @@ static inline void set_silent_tlb(trident_t *trident, int page)
#define page_to_addr(trident,page) __tlb_to_addr(trident, (page) * UNIT_PAGES)
/* fill TLB entries -- UNIT_PAGES entries must be filled */
-static inline void set_tlb_bus(trident_t *trident, int page, unsigned long ptr, dma_addr_t addr)
+static inline void set_tlb_bus(struct snd_trident *trident, int page,
+ unsigned long ptr, dma_addr_t addr)
{
int i;
page *= UNIT_PAGES;
@@ -107,7 +109,7 @@ static inline void set_tlb_bus(trident_t *trident, int page, unsigned long ptr,
addr += SNDRV_TRIDENT_PAGE_SIZE;
}
}
-static inline void set_silent_tlb(trident_t *trident, int page)
+static inline void set_silent_tlb(struct snd_trident *trident, int page)
{
int i;
page *= UNIT_PAGES;
@@ -118,7 +120,7 @@ static inline void set_silent_tlb(trident_t *trident, int page)
#endif /* PAGE_SIZE */
/* calculate buffer pointer from offset address */
-static inline void *offset_ptr(trident_t *trident, int offset)
+static inline void *offset_ptr(struct snd_trident *trident, int offset)
{
char *ptr;
ptr = page_to_ptr(trident, get_aligned_page(offset));
@@ -127,16 +129,16 @@ static inline void *offset_ptr(trident_t *trident, int offset)
}
/* first and last (aligned) pages of memory block */
-#define firstpg(blk) (((snd_trident_memblk_arg_t*)snd_util_memblk_argptr(blk))->first_page)
-#define lastpg(blk) (((snd_trident_memblk_arg_t*)snd_util_memblk_argptr(blk))->last_page)
+#define firstpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->first_page)
+#define lastpg(blk) (((struct snd_trident_memblk_arg *)snd_util_memblk_argptr(blk))->last_page)
/*
* search empty pages which may contain given size
*/
-static snd_util_memblk_t *
-search_empty(snd_util_memhdr_t *hdr, int size)
+static struct snd_util_memblk *
+search_empty(struct snd_util_memhdr *hdr, int size)
{
- snd_util_memblk_t *blk, *prev;
+ struct snd_util_memblk *blk, *prev;
int page, psize;
struct list_head *p;
@@ -144,7 +146,7 @@ search_empty(snd_util_memhdr_t *hdr, int size)
prev = NULL;
page = 0;
list_for_each(p, &hdr->block) {
- blk = list_entry(p, snd_util_memblk_t, list);
+ blk = list_entry(p, struct snd_util_memblk, list);
if (page + psize <= firstpg(blk))
goto __found_pages;
page = lastpg(blk) + 1;
@@ -183,12 +185,13 @@ static int is_valid_page(unsigned long ptr)
/*
* page allocation for DMA (Scatter-Gather version)
*/
-static snd_util_memblk_t *
-snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
+static struct snd_util_memblk *
+snd_trident_alloc_sg_pages(struct snd_trident *trident,
+ struct snd_pcm_substream *substream)
{
- snd_util_memhdr_t *hdr;
- snd_util_memblk_t *blk;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_util_memhdr *hdr;
+ struct snd_util_memblk *blk;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int idx, page;
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
@@ -230,13 +233,14 @@ snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
/*
* page allocation for DMA (contiguous version)
*/
-static snd_util_memblk_t *
-snd_trident_alloc_cont_pages(trident_t *trident, snd_pcm_substream_t *substream)
+static struct snd_util_memblk *
+snd_trident_alloc_cont_pages(struct snd_trident *trident,
+ struct snd_pcm_substream *substream)
{
- snd_util_memhdr_t *hdr;
- snd_util_memblk_t *blk;
+ struct snd_util_memhdr *hdr;
+ struct snd_util_memblk *blk;
int page;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
dma_addr_t addr;
unsigned long ptr;
@@ -270,8 +274,9 @@ snd_trident_alloc_cont_pages(trident_t *trident, snd_pcm_substream_t *substream)
/*
* page allocation for DMA
*/
-snd_util_memblk_t *
-snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
+struct snd_util_memblk *
+snd_trident_alloc_pages(struct snd_trident *trident,
+ struct snd_pcm_substream *substream)
{
snd_assert(trident != NULL, return NULL);
snd_assert(substream != NULL, return NULL);
@@ -285,9 +290,10 @@ snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
/*
* release DMA buffer from page table
*/
-int snd_trident_free_pages(trident_t *trident, snd_util_memblk_t *blk)
+int snd_trident_free_pages(struct snd_trident *trident,
+ struct snd_util_memblk *blk)
{
- snd_util_memhdr_t *hdr;
+ struct snd_util_memhdr *hdr;
int page;
snd_assert(trident != NULL, return -EINVAL);
@@ -314,17 +320,17 @@ int snd_trident_free_pages(trident_t *trident, snd_util_memblk_t *blk)
/*
*/
-static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk);
-static int synth_free_pages(trident_t *hw, snd_util_memblk_t *blk);
+static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
+static int synth_free_pages(struct snd_trident *hw, struct snd_util_memblk *blk);
/*
* allocate a synth sample area
*/
-snd_util_memblk_t *
-snd_trident_synth_alloc(trident_t *hw, unsigned int size)
+struct snd_util_memblk *
+snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size)
{
- snd_util_memblk_t *blk;
- snd_util_memhdr_t *hdr = hw->tlb.memhdr;
+ struct snd_util_memblk *blk;
+ struct snd_util_memhdr *hdr = hw->tlb.memhdr;
down(&hdr->block_mutex);
blk = __snd_util_mem_alloc(hdr, size);
@@ -346,9 +352,9 @@ snd_trident_synth_alloc(trident_t *hw, unsigned int size)
* free a synth sample area
*/
int
-snd_trident_synth_free(trident_t *hw, snd_util_memblk_t *blk)
+snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk)
{
- snd_util_memhdr_t *hdr = hw->tlb.memhdr;
+ struct snd_util_memhdr *hdr = hw->tlb.memhdr;
down(&hdr->block_mutex);
synth_free_pages(hw, blk);
@@ -361,7 +367,7 @@ snd_trident_synth_free(trident_t *hw, snd_util_memblk_t *blk)
/*
* reset TLB entry and free kernel page
*/
-static void clear_tlb(trident_t *trident, int page)
+static void clear_tlb(struct snd_trident *trident, int page)
{
void *ptr = page_to_ptr(trident, page);
dma_addr_t addr = page_to_addr(trident, page);
@@ -378,20 +384,22 @@ static void clear_tlb(trident_t *trident, int page)
}
/* check new allocation range */
-static void get_single_page_range(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk, int *first_page_ret, int *last_page_ret)
+static void get_single_page_range(struct snd_util_memhdr *hdr,
+ struct snd_util_memblk *blk,
+ int *first_page_ret, int *last_page_ret)
{
struct list_head *p;
- snd_util_memblk_t *q;
+ struct snd_util_memblk *q;
int first_page, last_page;
first_page = firstpg(blk);
if ((p = blk->list.prev) != &hdr->block) {
- q = list_entry(p, snd_util_memblk_t, list);
+ q = list_entry(p, struct snd_util_memblk, list);
if (lastpg(q) == first_page)
first_page++; /* first page was already allocated */
}
last_page = lastpg(blk);
if ((p = blk->list.next) != &hdr->block) {
- q = list_entry(p, snd_util_memblk_t, list);
+ q = list_entry(p, struct snd_util_memblk, list);
if (firstpg(q) == last_page)
last_page--; /* last page was already allocated */
}
@@ -402,7 +410,7 @@ static void get_single_page_range(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk
/*
* allocate kernel pages and assign them to TLB
*/
-static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk)
+static int synth_alloc_pages(struct snd_trident *hw, struct snd_util_memblk *blk)
{
int page, first_page, last_page;
struct snd_dma_buffer dmab;
@@ -438,7 +446,7 @@ __fail:
/*
* free pages
*/
-static int synth_free_pages(trident_t *trident, snd_util_memblk_t *blk)
+static int synth_free_pages(struct snd_trident *trident, struct snd_util_memblk *blk)
{
int page, first_page, last_page;
@@ -452,7 +460,9 @@ static int synth_free_pages(trident_t *trident, snd_util_memblk_t *blk)
/*
* copy_from_user(blk + offset, data, size)
*/
-int snd_trident_synth_copy_from_user(trident_t *trident, snd_util_memblk_t *blk, int offset, const char __user *data, int size)
+int snd_trident_synth_copy_from_user(struct snd_trident *trident,
+ struct snd_util_memblk *blk,
+ int offset, const char __user *data, int size)
{
int page, nextofs, end_offset, temp, temp1;
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
index 5d5a719b0585..cc7af8bc55a0 100644
--- a/sound/pci/trident/trident_synth.c
+++ b/sound/pci/trident/trident_synth.c
@@ -192,15 +192,15 @@ static unsigned short log_from_linear( unsigned short value )
* Sample handling operations
*/
-static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position);
-static void sample_stop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_stop_mode_t mode);
-static void sample_freq(trident_t * trident, snd_trident_voice_t * voice, snd_seq_frequency_t freq);
-static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_volume_t * volume);
-static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_loop_t * loop);
-static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position);
-static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, unsigned char *data);
-
-static snd_trident_sample_ops_t sample_ops =
+static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position);
+static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode);
+static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq);
+static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume);
+static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop);
+static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position);
+static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data);
+
+static struct snd_trident_sample_ops sample_ops =
{
sample_start,
sample_stop,
@@ -211,7 +211,7 @@ static snd_trident_sample_ops_t sample_ops =
sample_private1
};
-static void snd_trident_simple_init(snd_trident_voice_t * voice)
+static void snd_trident_simple_init(struct snd_trident_voice * voice)
{
//voice->handler_wave = interrupt_wave;
//voice->handler_volume = interrupt_volume;
@@ -220,10 +220,10 @@ static void snd_trident_simple_init(snd_trident_voice_t * voice)
voice->sample_ops = &sample_ops;
}
-static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position)
+static void sample_start(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
{
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
unsigned long flags;
unsigned int loop_start, loop_end, sample_start, sample_end, start_offset;
unsigned int value;
@@ -305,7 +305,7 @@ static void sample_start(trident_t * trident, snd_trident_voice_t * voice, snd_s
snd_seq_instr_free_use(trident->synth.ilist, instr);
}
-static void sample_stop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_stop_mode_t mode)
+static void sample_stop(struct snd_trident * trident, struct snd_trident_voice * voice, int mode)
{
unsigned long flags;
@@ -329,7 +329,7 @@ static void sample_stop(trident_t * trident, snd_trident_voice_t * voice, snd_se
}
}
-static void sample_freq(trident_t * trident, snd_trident_voice_t * voice, snd_seq_frequency_t freq)
+static void sample_freq(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_frequency_t freq)
{
unsigned long flags;
freq >>= 4;
@@ -355,7 +355,7 @@ static void sample_freq(trident_t * trident, snd_trident_voice_t * voice, snd_se
spin_unlock_irqrestore(&trident->reg_lock, flags);
}
-static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_volume_t * volume)
+static void sample_volume(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_volume * volume)
{
unsigned long flags;
unsigned short value;
@@ -407,11 +407,11 @@ static void sample_volume(trident_t * trident, snd_trident_voice_t * voice, snd_
spin_unlock_irqrestore(&trident->reg_lock, flags);
}
-static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_seq_ev_loop_t * loop)
+static void sample_loop(struct snd_trident * trident, struct snd_trident_voice * voice, struct snd_seq_ev_loop * loop)
{
unsigned long flags;
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
unsigned int loop_start, loop_end;
instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
@@ -446,11 +446,11 @@ static void sample_loop(trident_t * trident, snd_trident_voice_t * voice, snd_se
snd_seq_instr_free_use(trident->synth.ilist, instr);
}
-static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq_position_t position)
+static void sample_pos(struct snd_trident * trident, struct snd_trident_voice * voice, snd_seq_position_t position)
{
unsigned long flags;
- simple_instrument_t *simple;
- snd_seq_kinstr_t *instr;
+ struct simple_instrument *simple;
+ struct snd_seq_kinstr *instr;
unsigned int value;
instr = snd_seq_instr_find(trident->synth.ilist, &voice->instr, 0, 1);
@@ -496,7 +496,7 @@ static void sample_pos(trident_t * trident, snd_trident_voice_t * voice, snd_seq
snd_seq_instr_free_use(trident->synth.ilist, instr);
}
-static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, unsigned char *data)
+static void sample_private1(struct snd_trident * trident, struct snd_trident_voice * voice, unsigned char *data)
{
}
@@ -504,10 +504,11 @@ static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, un
* Memory management / sample loading
*/
-static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,
+static int snd_trident_simple_put_sample(void *private_data,
+ struct simple_instrument * instr,
char __user *data, long len, int atomic)
{
- trident_t *trident = private_data;
+ struct snd_trident *trident = private_data;
int size = instr->size;
int shift = 0;
@@ -529,7 +530,7 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
return -EFAULT;
if (trident->tlb.entries) {
- snd_util_memblk_t *memblk;
+ struct snd_util_memblk *memblk;
memblk = snd_trident_synth_alloc(trident, size);
if (memblk == NULL)
return -ENOMEM;
@@ -557,10 +558,11 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
return 0;
}
-static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,
+static int snd_trident_simple_get_sample(void *private_data,
+ struct simple_instrument * instr,
char __user *data, long len, int atomic)
{
- //trident_t *trident = private_data;
+ //struct snd_trident *trident = private_data;
int size = instr->size;
int shift = 0;
@@ -578,10 +580,11 @@ static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t
return -EBUSY;
}
-static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,
+static int snd_trident_simple_remove_sample(void *private_data,
+ struct simple_instrument * instr,
int atomic)
{
- trident_t *trident = private_data;
+ struct snd_trident *trident = private_data;
int size = instr->size;
if (instr->format & SIMPLE_WAVE_16BIT)
@@ -590,7 +593,7 @@ static int snd_trident_simple_remove_sample(void *private_data, simple_instrumen
size <<= 1;
if (trident->tlb.entries) {
- snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;
+ struct snd_util_memblk *memblk = (struct snd_util_memblk *)instr->address.ptr;
if (memblk)
snd_trident_synth_free(trident, memblk);
else
@@ -612,9 +615,9 @@ static int snd_trident_simple_remove_sample(void *private_data, simple_instrumen
return 0;
}
-static void select_instrument(trident_t * trident, snd_trident_voice_t * v)
+static void select_instrument(struct snd_trident * trident, struct snd_trident_voice * v)
{
- snd_seq_kinstr_t *instr;
+ struct snd_seq_kinstr *instr;
instr = snd_seq_instr_find(trident->synth.ilist, &v->instr, 0, 1);
if (instr != NULL) {
if (instr->ops) {
@@ -629,7 +632,7 @@ static void select_instrument(trident_t * trident, snd_trident_voice_t * v)
*/
-static void event_sample(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_sample(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
@@ -643,7 +646,7 @@ static void event_sample(snd_seq_event_t * ev, snd_trident_port_t * p, snd_tride
select_instrument(p->trident, v);
}
-static void event_cluster(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_cluster(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->trident, v, SAMPLE_STOP_IMMEDIATELY);
@@ -651,49 +654,49 @@ static void event_cluster(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trid
select_instrument(p->trident, v);
}
-static void event_start(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_start(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_start)
v->sample_ops->sample_start(p->trident, v, ev->data.sample.param.position);
}
-static void event_stop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_stop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_stop)
v->sample_ops->sample_stop(p->trident, v, ev->data.sample.param.stop_mode);
}
-static void event_freq(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_freq(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_freq)
v->sample_ops->sample_freq(p->trident, v, ev->data.sample.param.frequency);
}
-static void event_volume(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_volume(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_volume)
v->sample_ops->sample_volume(p->trident, v, &ev->data.sample.param.volume);
}
-static void event_loop(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_loop(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_loop)
v->sample_ops->sample_loop(p->trident, v, &ev->data.sample.param.loop);
}
-static void event_position(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_position(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_pos)
v->sample_ops->sample_pos(p->trident, v, ev->data.sample.param.position);
}
-static void event_private1(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v)
+static void event_private1(struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v)
{
if (v->sample_ops && v->sample_ops->sample_private1)
v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8);
}
-typedef void (trident_sample_event_handler_t) (snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v);
+typedef void (trident_sample_event_handler_t) (struct snd_seq_event * ev, struct snd_trident_port * p, struct snd_trident_voice * v);
static trident_sample_event_handler_t *trident_sample_event_handlers[9] =
{
@@ -708,11 +711,11 @@ static trident_sample_event_handler_t *trident_sample_event_handlers[9] =
event_private1
};
-static void snd_trident_sample_event(snd_seq_event_t * ev, snd_trident_port_t * p)
+static void snd_trident_sample_event(struct snd_seq_event * ev, struct snd_trident_port * p)
{
int idx, voice;
- trident_t *trident = p->trident;
- snd_trident_voice_t *v;
+ struct snd_trident *trident = p->trident;
+ struct snd_trident_voice *v;
unsigned long flags;
idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;
@@ -735,10 +738,10 @@ static void snd_trident_sample_event(snd_seq_event_t * ev, snd_trident_port_t *
*/
-static void snd_trident_synth_free_voices(trident_t * trident, int client, int port)
+static void snd_trident_synth_free_voices(struct snd_trident * trident, int client, int port)
{
int idx;
- snd_trident_voice_t *voice;
+ struct snd_trident_voice *voice;
for (idx = 0; idx < 32; idx++) {
voice = &trident->synth.voices[idx];
@@ -747,11 +750,11 @@ static void snd_trident_synth_free_voices(trident_t * trident, int client, int p
}
}
-static int snd_trident_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
+static int snd_trident_synth_use(void *private_data, struct snd_seq_port_subscribe * info)
{
- snd_trident_port_t *port = (snd_trident_port_t *) private_data;
- trident_t *trident = port->trident;
- snd_trident_voice_t *voice;
+ struct snd_trident_port *port = private_data;
+ struct snd_trident *trident = port->trident;
+ struct snd_trident_voice *voice;
unsigned int idx;
unsigned long flags;
@@ -786,10 +789,10 @@ static int snd_trident_synth_use(void *private_data, snd_seq_port_subscribe_t *
return 0;
}
-static int snd_trident_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
+static int snd_trident_synth_unuse(void *private_data, struct snd_seq_port_subscribe * info)
{
- snd_trident_port_t *port = (snd_trident_port_t *) private_data;
- trident_t *trident = port->trident;
+ struct snd_trident_port *port = private_data;
+ struct snd_trident *trident = port->trident;
unsigned long flags;
spin_lock_irqsave(&trident->reg_lock, flags);
@@ -802,18 +805,18 @@ static int snd_trident_synth_unuse(void *private_data, snd_seq_port_subscribe_t
*/
-static void snd_trident_synth_free_private_instruments(snd_trident_port_t * p, int client)
+static void snd_trident_synth_free_private_instruments(struct snd_trident_port * p, int client)
{
- snd_seq_instr_header_t ifree;
+ struct snd_seq_instr_header ifree;
memset(&ifree, 0, sizeof(ifree));
ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;
snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0);
}
-static int snd_trident_synth_event_input(snd_seq_event_t * ev, int direct, void *private_data, int atomic, int hop)
+static int snd_trident_synth_event_input(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
{
- snd_trident_port_t *p = (snd_trident_port_t *) private_data;
+ struct snd_trident_port *p = (struct snd_trident_port *) private_data;
if (p == NULL)
return -EINVAL;
@@ -841,12 +844,12 @@ static int snd_trident_synth_event_input(snd_seq_event_t * ev, int direct, void
}
static void snd_trident_synth_instr_notify(void *private_data,
- snd_seq_kinstr_t * instr,
+ struct snd_seq_kinstr * instr,
int what)
{
int idx;
- trident_t *trident = private_data;
- snd_trident_voice_t *pvoice;
+ struct snd_trident *trident = private_data;
+ struct snd_trident_voice *pvoice;
unsigned long flags;
spin_lock_irqsave(&trident->event_lock, flags);
@@ -870,16 +873,16 @@ static void snd_trident_synth_instr_notify(void *private_data,
static void snd_trident_synth_free_port(void *private_data)
{
- snd_trident_port_t *p = (snd_trident_port_t *) private_data;
+ struct snd_trident_port *p = (struct snd_trident_port *) private_data;
if (p)
snd_midi_channel_free_set(p->chset);
}
-static int snd_trident_synth_create_port(trident_t * trident, int idx)
+static int snd_trident_synth_create_port(struct snd_trident * trident, int idx)
{
- snd_trident_port_t *p;
- snd_seq_port_callback_t callbacks;
+ struct snd_trident_port *p;
+ struct snd_seq_port_callback callbacks;
char name[32];
char *str;
int result;
@@ -927,43 +930,31 @@ static int snd_trident_synth_create_port(trident_t * trident, int idx)
*/
-static int snd_trident_synth_new_device(snd_seq_device_t *dev)
+static int snd_trident_synth_new_device(struct snd_seq_device *dev)
{
- trident_t *trident;
+ struct snd_trident *trident;
int client, i;
- snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
- snd_seq_port_subscribe_t sub;
- snd_simple_ops_t *simpleops;
+ struct snd_seq_port_subscribe sub;
+ struct snd_simple_ops *simpleops;
char *str;
- trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (trident == NULL)
return -EINVAL;
trident->synth.seq_client = -1;
/* allocate new client */
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = trident;
- callbacks.allow_output = callbacks.allow_input = 1;
- client = trident->synth.seq_client =
- snd_seq_create_kernel_client(trident->card, 1, &callbacks);
- if (client < 0)
- return client;
-
- /* change name of client */
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client;
- cinfo.type = KERNEL_CLIENT;
str = "???";
switch (trident->device) {
case TRIDENT_DEVICE_ID_DX: str = "Trident 4DWave-DX"; break;
case TRIDENT_DEVICE_ID_NX: str = "Trident 4DWave-NX"; break;
case TRIDENT_DEVICE_ID_SI7018: str = "SiS 7018"; break;
}
- sprintf(cinfo.name, str);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
+ client = trident->synth.seq_client =
+ snd_seq_create_kernel_client(trident->card, 1, str);
+ if (client < 0)
+ return client;
for (i = 0; i < 4; i++)
snd_trident_synth_create_port(trident, i);
@@ -993,11 +984,11 @@ static int snd_trident_synth_new_device(snd_seq_device_t *dev)
return 0;
}
-static int snd_trident_synth_delete_device(snd_seq_device_t *dev)
+static int snd_trident_synth_delete_device(struct snd_seq_device *dev)
{
- trident_t *trident;
+ struct snd_trident *trident;
- trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
+ trident = *(struct snd_trident **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
if (trident == NULL)
return -EINVAL;
@@ -1012,14 +1003,14 @@ static int snd_trident_synth_delete_device(snd_seq_device_t *dev)
static int __init alsa_trident_synth_init(void)
{
- static snd_seq_dev_ops_t ops =
+ static struct snd_seq_dev_ops ops =
{
snd_trident_synth_new_device,
snd_trident_synth_delete_device
};
return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops,
- sizeof(trident_t*));
+ sizeof(struct snd_trident *));
}
static void __exit alsa_trident_synth_exit(void)
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index fad2a2413bf6..ed26a155c344 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -303,12 +303,6 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
/*
- */
-
-typedef struct _snd_via82xx via82xx_t;
-typedef struct via_dev viadev_t;
-
-/*
* pcm stream
*/
@@ -319,11 +313,11 @@ struct snd_via_sg_table {
#define VIA_TABLE_SIZE 255
-struct via_dev {
+struct viadev {
unsigned int reg_offset;
unsigned long port;
int direction; /* playback = 0, capture = 1 */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int running;
unsigned int tbl_entries; /* # descriptors */
struct snd_dma_buffer table;
@@ -350,7 +344,7 @@ struct via_rate_lock {
int used;
};
-struct _snd_via82xx {
+struct via82xx {
int irq;
unsigned long port;
@@ -374,27 +368,27 @@ struct _snd_via82xx {
unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
struct pci_dev *pci;
- snd_card_t *card;
+ struct snd_card *card;
unsigned int num_devs;
unsigned int playback_devno, multi_devno, capture_devno;
- viadev_t devs[VIA_MAX_DEVS];
+ struct viadev devs[VIA_MAX_DEVS];
struct via_rate_lock rates[2]; /* playback and capture */
unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */
unsigned int no_vra: 1; /* no need to set VRA on DXS channels */
unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */
unsigned int spdif_on: 1; /* only spdif rates work to external DACs */
- snd_pcm_t *pcms[2];
- snd_rawmidi_t *rmidi;
+ struct snd_pcm *pcms[2];
+ struct snd_rawmidi *rmidi;
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
unsigned int ac97_clock;
unsigned int ac97_secondary; /* secondary AC'97 codec is present */
spinlock_t reg_lock;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
#ifdef SUPPORT_JOYSTICK
struct gameport *gameport;
@@ -419,12 +413,12 @@ MODULE_DEVICE_TABLE(pci, snd_via82xx_ids);
* periods = number of periods
* fragsize = period size in bytes
*/
-static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
+static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci,
unsigned int periods, unsigned int fragsize)
{
unsigned int i, idx, ofs, rest;
- via82xx_t *chip = snd_pcm_substream_chip(substream);
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
if (dev->table.area == NULL) {
@@ -487,7 +481,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
}
-static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
+static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci)
{
if (dev->table.area) {
@@ -503,17 +497,17 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
* Basic I/O
*/
-static inline unsigned int snd_via82xx_codec_xread(via82xx_t *chip)
+static inline unsigned int snd_via82xx_codec_xread(struct via82xx *chip)
{
return inl(VIAREG(chip, AC97));
}
-static inline void snd_via82xx_codec_xwrite(via82xx_t *chip, unsigned int val)
+static inline void snd_via82xx_codec_xwrite(struct via82xx *chip, unsigned int val)
{
outl(val, VIAREG(chip, AC97));
}
-static int snd_via82xx_codec_ready(via82xx_t *chip, int secondary)
+static int snd_via82xx_codec_ready(struct via82xx *chip, int secondary)
{
unsigned int timeout = 1000; /* 1ms */
unsigned int val;
@@ -523,11 +517,12 @@ static int snd_via82xx_codec_ready(via82xx_t *chip, int secondary)
if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY))
return val & 0xffff;
}
- snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_via82xx_codec_xread(chip));
+ snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n",
+ secondary, snd_via82xx_codec_xread(chip));
return -EIO;
}
-static int snd_via82xx_codec_valid(via82xx_t *chip, int secondary)
+static int snd_via82xx_codec_valid(struct via82xx *chip, int secondary)
{
unsigned int timeout = 1000; /* 1ms */
unsigned int val, val1;
@@ -544,20 +539,20 @@ static int snd_via82xx_codec_valid(via82xx_t *chip, int secondary)
return -EIO;
}
-static void snd_via82xx_codec_wait(ac97_t *ac97)
+static void snd_via82xx_codec_wait(struct snd_ac97 *ac97)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx *chip = ac97->private_data;
int err;
err = snd_via82xx_codec_ready(chip, ac97->num);
/* here we need to wait fairly for long time.. */
msleep(500);
}
-static void snd_via82xx_codec_write(ac97_t *ac97,
+static void snd_via82xx_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx *chip = ac97->private_data;
unsigned int xval;
xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
@@ -568,9 +563,9 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
snd_via82xx_codec_ready(chip, ac97->num);
}
-static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx *chip = ac97->private_data;
unsigned int xval, val = 0xffff;
int again = 0;
@@ -580,7 +575,8 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT;
while (1) {
if (again++ > 3) {
- snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip));
+ snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n",
+ ac97->num, snd_via82xx_codec_xread(chip));
return 0xffff;
}
snd_via82xx_codec_xwrite(chip, xval);
@@ -594,7 +590,7 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
return val & 0xffff;
}
-static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev)
+static void snd_via82xx_channel_reset(struct via82xx *chip, struct viadev *viadev)
{
outb(VIA_REG_CTRL_PAUSE | VIA_REG_CTRL_TERMINATE | VIA_REG_CTRL_RESET,
VIADEV_REG(viadev, OFFSET_CONTROL));
@@ -617,7 +613,7 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev)
*/
static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- via82xx_t *chip = dev_id;
+ struct via82xx *chip = dev_id;
unsigned int status;
unsigned int i;
@@ -632,7 +628,7 @@ static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *r
/* check status for each stream */
spin_lock(&chip->reg_lock);
for (i = 0; i < chip->num_devs; i++) {
- viadev_t *viadev = &chip->devs[i];
+ struct viadev *viadev = &chip->devs[i];
unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
if (! (c_status & (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED)))
continue;
@@ -663,7 +659,7 @@ static irqreturn_t snd_via686_interrupt(int irq, void *dev_id, struct pt_regs *r
*/
static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- via82xx_t *chip = dev_id;
+ struct via82xx *chip = dev_id;
unsigned int status;
unsigned int i;
int irqreturn = 0;
@@ -673,8 +669,8 @@ static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *
status = inl(VIAREG(chip, SGD_SHADOW));
for (i = 0; i < chip->num_devs; i++) {
- viadev_t *viadev = &chip->devs[i];
- snd_pcm_substream_t *substream;
+ struct viadev *viadev = &chip->devs[i];
+ struct snd_pcm_substream *substream;
unsigned char c_status, shadow_status;
shadow_status = (status >> viadev->shadow_shift) &
@@ -719,10 +715,10 @@ static irqreturn_t snd_via8233_interrupt(int irq, void *dev_id, struct pt_regs *
/*
* trigger callback
*/
-static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
unsigned char val;
if (chip->chip_type != TYPE_VIA686)
@@ -766,9 +762,11 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
*/
#define check_invalid_pos(viadev,pos) \
- ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))
+ ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\
+ viadev->lastpos < viadev->bufsize2))
-static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count)
+static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx,
+ unsigned int count)
{
unsigned int size, base, res;
@@ -780,7 +778,8 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
/* check the validity of the calculated position */
if (size < count) {
- snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count);
+ snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n",
+ (int)size, (int)count);
res = viadev->lastpos;
} else {
if (! count) {
@@ -796,12 +795,18 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
}
if (check_invalid_pos(viadev, res)) {
#ifdef POINTER_DEBUG
- printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count);
+ printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, "
+ "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, "
+ "count = 0x%x\n", idx, viadev->tbl_entries,
+ viadev->lastpos, viadev->bufsize2,
+ viadev->idx_table[idx].offset,
+ viadev->idx_table[idx].size, count);
#endif
/* count register returns full size when end of buffer is reached */
res = base + size;
if (check_invalid_pos(viadev, res)) {
- snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n");
+ snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), "
+ "using last valid pointer\n");
res = viadev->lastpos;
}
}
@@ -812,10 +817,10 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
/*
* get the current pointer on via686
*/
-static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
unsigned int idx, ptr, count, res;
snd_assert(viadev->tbl_entries, return 0);
@@ -842,10 +847,10 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream)
/*
* get the current pointer on via823x
*/
-static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
unsigned int idx, count, res;
int status;
@@ -865,7 +870,8 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(snd_pcm_substream_t *substream)
idx = count >> 24;
if (idx >= viadev->tbl_entries) {
#ifdef POINTER_DEBUG
- printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx, viadev->tbl_entries);
+ printk(KERN_DEBUG "fail: invalid idx = %i/%i\n", idx,
+ viadev->tbl_entries);
#endif
res = viadev->lastpos;
} else {
@@ -895,11 +901,11 @@ unlock:
* hw_params callback:
* allocate the buffer and build up the buffer description table
*/
-static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
int err;
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
@@ -918,10 +924,10 @@ static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
* hw_free callback:
* clean up the buffer description table and release the buffer
*/
-static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
+static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
clean_via_table(viadev, substream, chip->pci);
snd_pcm_lib_free_pages(substream);
@@ -932,7 +938,7 @@ static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
/*
* set up the table pointer
*/
-static void snd_via82xx_set_table_ptr(via82xx_t *chip, viadev_t *viadev)
+static void snd_via82xx_set_table_ptr(struct via82xx *chip, struct viadev *viadev)
{
snd_via82xx_codec_ready(chip, 0);
outl((u32)viadev->table.addr, VIADEV_REG(viadev, OFFSET_TABLE_PTR));
@@ -943,7 +949,8 @@ static void snd_via82xx_set_table_ptr(via82xx_t *chip, viadev_t *viadev)
/*
* prepare callback for playback and capture on via686
*/
-static void via686_setup_format(via82xx_t *chip, viadev_t *viadev, snd_pcm_runtime_t *runtime)
+static void via686_setup_format(struct via82xx *chip, struct viadev *viadev,
+ struct snd_pcm_runtime *runtime)
{
snd_via82xx_channel_reset(chip, viadev);
/* this must be set after channel_reset */
@@ -956,11 +963,11 @@ static void via686_setup_format(via82xx_t *chip, viadev_t *viadev, snd_pcm_runti
VIA_REG_TYPE_INT_FLAG, VIADEV_REG(viadev, OFFSET_TYPE));
}
-static int snd_via686_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_via686_playback_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE, runtime->rate);
snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
@@ -968,11 +975,11 @@ static int snd_via686_playback_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_via686_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_via686_capture_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
via686_setup_format(chip, viadev, runtime);
@@ -1002,11 +1009,11 @@ static int via_lock_rate(struct via_rate_lock *rec, int rate)
/*
* prepare callback for DSX playback on via823x
*/
-static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_via8233_playback_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
int rate_changed;
u32 rbits;
@@ -1022,12 +1029,15 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
if (runtime->rate == 48000)
rbits = 0xfffff;
else
- rbits = (0x100000 / 48000) * runtime->rate + ((0x100000 % 48000) * runtime->rate) / 48000;
+ rbits = (0x100000 / 48000) * runtime->rate +
+ ((0x100000 % 48000) * runtime->rate) / 48000;
snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
snd_via82xx_channel_reset(chip, viadev);
snd_via82xx_set_table_ptr(chip, viadev);
- outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
- outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
+ outb(chip->playback_volume[viadev->reg_offset / 0x10][0],
+ VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
+ outb(chip->playback_volume[viadev->reg_offset / 0x10][1],
+ VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */
(runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */
rbits | /* rate */
@@ -1041,11 +1051,11 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
/*
* prepare callback for multi-channel playback on via823x
*/
-static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
+static int snd_via8233_multi_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int slots;
int fmt;
@@ -1058,7 +1068,8 @@ static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
snd_via82xx_channel_reset(chip, viadev);
snd_via82xx_set_table_ptr(chip, viadev);
- fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ? VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT;
+ fmt = (runtime->format == SNDRV_PCM_FORMAT_S16_LE) ?
+ VIA_REG_MULTPLAY_FMT_16BIT : VIA_REG_MULTPLAY_FMT_8BIT;
fmt |= runtime->channels << 4;
outb(fmt, VIADEV_REG(viadev, OFS_MULTPLAY_FORMAT));
#if 0
@@ -1089,11 +1100,11 @@ static int snd_via8233_multi_prepare(snd_pcm_substream_t *substream)
/*
* prepare callback for capture on via823x
*/
-static int snd_via8233_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_via8233_capture_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (via_lock_rate(&chip->rates[1], runtime->rate) < 0)
return -EINVAL;
@@ -1114,7 +1125,7 @@ static int snd_via8233_capture_prepare(snd_pcm_substream_t *substream)
/*
* pcm hardware definition, identical for both playback and capture
*/
-static snd_pcm_hardware_t snd_via82xx_hw =
+static struct snd_pcm_hardware snd_via82xx_hw =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1139,9 +1150,10 @@ static snd_pcm_hardware_t snd_via82xx_hw =
/*
* open callback skeleton
*/
-static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_substream_t * substream)
+static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
struct via_rate_lock *ratep;
@@ -1191,10 +1203,10 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
/*
* open callback for playback on via686 and via823x DSX
*/
-static int snd_via82xx_playback_open(snd_pcm_substream_t * substream)
+static int snd_via82xx_playback_open(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = &chip->devs[chip->playback_devno + substream->number];
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number];
int err;
if ((err = snd_via82xx_pcm_open(chip, viadev, substream)) < 0)
@@ -1205,10 +1217,10 @@ static int snd_via82xx_playback_open(snd_pcm_substream_t * substream)
/*
* open callback for playback on via823x multi-channel
*/
-static int snd_via8233_multi_open(snd_pcm_substream_t * substream)
+static int snd_via8233_multi_open(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = &chip->devs[chip->multi_devno];
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = &chip->devs[chip->multi_devno];
int err;
/* channels constraint for VIA8233A
* 3 and 5 channels are not supported
@@ -1216,7 +1228,7 @@ static int snd_via8233_multi_open(snd_pcm_substream_t * substream)
static unsigned int channels[] = {
1, 2, 4, 6
};
- static snd_pcm_hw_constraint_list_t hw_constraints_channels = {
+ static struct snd_pcm_hw_constraint_list hw_constraints_channels = {
.count = ARRAY_SIZE(channels),
.list = channels,
.mask = 0,
@@ -1226,17 +1238,19 @@ static int snd_via8233_multi_open(snd_pcm_substream_t * substream)
return err;
substream->runtime->hw.channels_max = 6;
if (chip->revision == VIA_REV_8233A)
- snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels);
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ &hw_constraints_channels);
return 0;
}
/*
* open callback for capture on via686 and via823x
*/
-static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
+static int snd_via82xx_capture_open(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = &chip->devs[chip->capture_devno + substream->pcm->device];
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = &chip->devs[chip->capture_devno + substream->pcm->device];
return snd_via82xx_pcm_open(chip, viadev, substream);
}
@@ -1244,10 +1258,10 @@ static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
/*
* close callback
*/
-static int snd_via82xx_pcm_close(snd_pcm_substream_t * substream)
+static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
struct via_rate_lock *ratep;
/* release the rate lock */
@@ -1264,7 +1278,7 @@ static int snd_via82xx_pcm_close(snd_pcm_substream_t * substream)
/* via686 playback callbacks */
-static snd_pcm_ops_t snd_via686_playback_ops = {
+static struct snd_pcm_ops snd_via686_playback_ops = {
.open = snd_via82xx_playback_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1277,7 +1291,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = {
};
/* via686 capture callbacks */
-static snd_pcm_ops_t snd_via686_capture_ops = {
+static struct snd_pcm_ops snd_via686_capture_ops = {
.open = snd_via82xx_capture_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1290,7 +1304,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = {
};
/* via823x DSX playback callbacks */
-static snd_pcm_ops_t snd_via8233_playback_ops = {
+static struct snd_pcm_ops snd_via8233_playback_ops = {
.open = snd_via82xx_playback_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1303,7 +1317,7 @@ static snd_pcm_ops_t snd_via8233_playback_ops = {
};
/* via823x multi-channel playback callbacks */
-static snd_pcm_ops_t snd_via8233_multi_ops = {
+static struct snd_pcm_ops snd_via8233_multi_ops = {
.open = snd_via8233_multi_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1316,7 +1330,7 @@ static snd_pcm_ops_t snd_via8233_multi_ops = {
};
/* via823x capture callbacks */
-static snd_pcm_ops_t snd_via8233_capture_ops = {
+static struct snd_pcm_ops snd_via8233_capture_ops = {
.open = snd_via82xx_capture_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1329,7 +1343,8 @@ static snd_pcm_ops_t snd_via8233_capture_ops = {
};
-static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int shadow_pos, int direction)
+static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,
+ int shadow_pos, int direction)
{
chip->devs[idx].reg_offset = reg_offset;
chip->devs[idx].shadow_shift = shadow_pos * 4;
@@ -1340,9 +1355,9 @@ static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int s
/*
* create pcm instances for VIA8233, 8233C and 8235 (not 8233A)
*/
-static int __devinit snd_via8233_pcm_new(via82xx_t *chip)
+static int __devinit snd_via8233_pcm_new(struct via82xx *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int i, err;
chip->playback_devno = 0; /* x 4 */
@@ -1367,7 +1382,8 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip)
init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
/* PCM #1: multi-channel playback and 2nd capture */
@@ -1385,7 +1401,8 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip)
init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
return 0;
@@ -1394,9 +1411,9 @@ static int __devinit snd_via8233_pcm_new(via82xx_t *chip)
/*
* create pcm instances for VIA8233A
*/
-static int __devinit snd_via8233a_pcm_new(via82xx_t *chip)
+static int __devinit snd_via8233a_pcm_new(struct via82xx *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
chip->multi_devno = 0;
@@ -1420,7 +1437,8 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip)
init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
/* SPDIF supported? */
@@ -1439,7 +1457,8 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip)
init_viadev(chip, chip->playback_devno, 0x30, 3, 0);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
return 0;
@@ -1448,9 +1467,9 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip)
/*
* create a pcm instance for via686a/b
*/
-static int __devinit snd_via686_pcm_new(via82xx_t *chip)
+static int __devinit snd_via686_pcm_new(struct via82xx *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
chip->playback_devno = 0;
@@ -1470,7 +1489,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip)
init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
return 0;
@@ -1481,7 +1501,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip)
* Mixer part
*/
-static int snd_via8233_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_via8233_capture_source_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
/* formerly they were "Line" and "Mic", but it looks like that they
* have nothing to do with the actual physical connections...
@@ -1498,17 +1519,19 @@ static int snd_via8233_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_via8233_capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_capture_source_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);
ucontrol->value.enumerated.item[0] = inb(port) & VIA_REG_CAPTURE_CHANNEL_MIC ? 1 : 0;
return 0;
}
-static int snd_via8233_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);
u8 val, oval;
@@ -1523,7 +1546,7 @@ static int snd_via8233_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
return val != oval;
}
-static snd_kcontrol_new_t snd_via8233_capture_source __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {
.name = "Input Source Select",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_capture_source_info,
@@ -1531,7 +1554,8 @@ static snd_kcontrol_new_t snd_via8233_capture_source __devinitdata = {
.put = snd_via8233_capture_source_put,
};
-static int snd_via8233_dxs3_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_via8233_dxs3_spdif_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1540,9 +1564,10 @@ static int snd_via8233_dxs3_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_via8233_dxs3_spdif_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
u8 val;
pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
@@ -1550,9 +1575,10 @@ static int snd_via8233_dxs3_spdif_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_via8233_dxs3_spdif_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
u8 val, oval;
pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &oval);
@@ -1568,7 +1594,7 @@ static int snd_via8233_dxs3_spdif_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return 0;
}
-static snd_kcontrol_new_t snd_via8233_dxs3_spdif_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = {
.name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_dxs3_spdif_info,
@@ -1576,7 +1602,8 @@ static snd_kcontrol_new_t snd_via8233_dxs3_spdif_control __devinitdata = {
.put = snd_via8233_dxs3_spdif_put,
};
-static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_via8233_dxs_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1585,9 +1612,10 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_dxs_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0];
@@ -1595,17 +1623,19 @@ static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_via8233_pcmdxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_pcmdxs_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0];
ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1];
return 0;
}
-static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_dxs_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
unsigned long port = chip->port + 0x10 * idx;
unsigned char val;
@@ -1625,9 +1655,10 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return change;
}
-static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- via82xx_t *chip = snd_kcontrol_chip(kcontrol);
+ struct via82xx *chip = snd_kcontrol_chip(kcontrol);
unsigned int idx;
unsigned char val;
int i, change = 0;
@@ -1650,7 +1681,7 @@ static int snd_via8233_pcmdxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return change;
}
-static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
.name = "PCM Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_via8233_dxs_volume_info,
@@ -1658,7 +1689,7 @@ static snd_kcontrol_new_t snd_via8233_pcmdxs_volume_control __devinitdata = {
.put = snd_via8233_pcmdxs_volume_put,
};
-static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
+static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = {
.name = "VIA DXS Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.count = 4,
@@ -1670,15 +1701,15 @@ static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
/*
*/
-static void snd_via82xx_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- via82xx_t *chip = bus->private_data;
+ struct via82xx *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
+static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx *chip = ac97->private_data;
chip->ac97 = NULL;
}
@@ -1732,14 +1763,20 @@ static struct ac97_quirk ac97_quirks[] = {
.name = "Arima Notebook",
.type = AC97_TUNE_HP_ONLY,
},
+ {
+ .subvendor = 0x161f,
+ .subdevice = 0x2032,
+ .name = "Targa Traveller 811",
+ .type = AC97_TUNE_HP_ONLY,
+ },
{ } /* terminator */
};
-static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_override)
+static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override)
{
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_via82xx_codec_write,
.read = snd_via82xx_codec_read,
.wait = snd_via82xx_codec_wait,
@@ -1770,7 +1807,7 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, const char *quirk_ov
#ifdef SUPPORT_JOYSTICK
#define JOYSTICK_ADDR 0x200
-static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy)
+static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{
struct gameport *gp;
struct resource *r;
@@ -1780,7 +1817,8 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char *
r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
if (!r) {
- printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", JOYSTICK_ADDR);
+ printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n",
+ JOYSTICK_ADDR);
return -EBUSY;
}
@@ -1806,7 +1844,7 @@ static int __devinit snd_via686_create_gameport(via82xx_t *chip, unsigned char *
return 0;
}
-static void snd_via686_free_gameport(via82xx_t *chip)
+static void snd_via686_free_gameport(struct via82xx *chip)
{
if (chip->gameport) {
struct resource *r = gameport_get_port_data(chip->gameport);
@@ -1817,11 +1855,11 @@ static void snd_via686_free_gameport(via82xx_t *chip)
}
}
#else
-static inline int snd_via686_create_gameport(via82xx_t *chip, unsigned char *legacy)
+static inline int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy)
{
return -ENOSYS;
}
-static inline void snd_via686_free_gameport(via82xx_t *chip) { }
+static inline void snd_via686_free_gameport(struct via82xx *chip) { }
#endif
@@ -1829,7 +1867,7 @@ static inline void snd_via686_free_gameport(via82xx_t *chip) { }
*
*/
-static int __devinit snd_via8233_init_misc(via82xx_t *chip)
+static int __devinit snd_via8233_init_misc(struct via82xx *chip)
{
int i, err, caps;
unsigned char val;
@@ -1850,7 +1888,7 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip)
/* when no h/w PCM volume control is found, use DXS volume control
* as the PCM vol control
*/
- snd_ctl_elem_id_t sid;
+ struct snd_ctl_elem_id sid;
memset(&sid, 0, sizeof(sid));
strcpy(sid.name, "PCM Playback Volume");
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -1877,7 +1915,7 @@ static int __devinit snd_via8233_init_misc(via82xx_t *chip)
return 0;
}
-static int __devinit snd_via686_init_misc(via82xx_t *chip)
+static int __devinit snd_via686_init_misc(struct via82xx *chip)
{
unsigned char legacy, legacy_cfg;
int rev_h = 0;
@@ -1954,9 +1992,10 @@ static int __devinit snd_via686_init_misc(via82xx_t *chip)
/*
* proc interface
*/
-static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_via82xx_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- via82xx_t *chip = entry->private_data;
+ struct via82xx *chip = entry->private_data;
int i;
snd_iprintf(buffer, "%s\n\n", chip->card->longname);
@@ -1965,9 +2004,9 @@ static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
}
}
-static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
+static void __devinit snd_via82xx_proc_init(struct via82xx *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "via82xx", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read);
@@ -1977,7 +2016,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
*
*/
-static int snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(struct via82xx *chip)
{
unsigned int val;
unsigned long end_time;
@@ -2080,7 +2119,8 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
unsigned long port = chip->port + 0x10 * idx;
for (i = 0; i < 2; i++) {
chip->playback_volume[idx][i]=chip->playback_volume_c[i];
- outb(chip->playback_volume_c[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+ outb(chip->playback_volume_c[i],
+ port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
}
}
}
@@ -2092,14 +2132,15 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
/*
* power management
*/
-static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
+static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state)
{
- via82xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct via82xx *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < 2; i++)
- if (chip->pcms[i])
- snd_pcm_suspend_all(chip->pcms[i]);
+ snd_pcm_suspend_all(chip->pcms[i]);
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
synchronize_irq(chip->irq);
@@ -2112,18 +2153,21 @@ static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
}
- pci_set_power_state(chip->pci, 3);
- pci_disable_device(chip->pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_via82xx_resume(snd_card_t *card)
+static int snd_via82xx_resume(struct pci_dev *pci)
{
- via82xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct via82xx *chip = card->private_data;
int i;
- pci_enable_device(chip->pci);
- pci_set_power_state(chip->pci, 0);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
snd_via82xx_chip_init(chip);
@@ -2143,11 +2187,12 @@ static int snd_via82xx_resume(snd_card_t *card)
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_via82xx_free(via82xx_t *chip)
+static int snd_via82xx_free(struct via82xx *chip)
{
unsigned int i;
@@ -2159,7 +2204,7 @@ static int snd_via82xx_free(via82xx_t *chip)
synchronize_irq(chip->irq);
__end_hw:
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
release_and_free_resource(chip->mpu_res);
pci_release_regions(chip->pci);
@@ -2173,22 +2218,22 @@ static int snd_via82xx_free(via82xx_t *chip)
return 0;
}
-static int snd_via82xx_dev_free(snd_device_t *device)
+static int snd_via82xx_dev_free(struct snd_device *device)
{
- via82xx_t *chip = device->device_data;
+ struct via82xx *chip = device->device_data;
return snd_via82xx_free(chip);
}
-static int __devinit snd_via82xx_create(snd_card_t * card,
+static int __devinit snd_via82xx_create(struct snd_card *card,
struct pci_dev *pci,
int chip_type,
int revision,
unsigned int ac97_clock,
- via82xx_t ** r_via)
+ struct via82xx ** r_via)
{
- via82xx_t *chip;
+ struct via82xx *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_via82xx_dev_free,
};
@@ -2225,7 +2270,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
chip_type == TYPE_VIA8233 ?
snd_via8233_interrupt : snd_via686_interrupt,
SA_INTERRUPT|SA_SHIRQ,
- card->driver, (void *)chip)) {
+ card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_via82xx_free(chip);
return -EBUSY;
@@ -2307,6 +2352,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .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 = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */
{ .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 */
@@ -2326,6 +2372,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
{ .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+ { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
{ .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
{ .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */
{ } /* terminator */
@@ -2362,8 +2409,8 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
static int __devinit snd_via82xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- via82xx_t *chip;
+ struct snd_card *card;
+ struct via82xx *chip;
unsigned char revision;
int chip_type = 0, card_type;
unsigned int i;
@@ -2418,6 +2465,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
if ((err = snd_via82xx_create(card, pci, chip_type, revision,
ac97_clock, &chip)) < 0)
goto __error;
+ card->private_data = chip;
if ((err = snd_via82xx_mixer_new(chip, ac97_quirk)) < 0)
goto __error;
@@ -2446,8 +2494,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
goto __error;
}
- snd_card_set_pm_callback(card, snd_via82xx_suspend, snd_via82xx_resume, chip);
-
/* disable interrupts */
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
@@ -2481,7 +2527,10 @@ static struct pci_driver driver = {
.id_table = snd_via82xx_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_via82xx_suspend,
+ .resume = snd_via82xx_resume,
+#endif
};
static int __init alsa_card_via82xx_init(void)
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index b83660bd05b0..22ce4d309929 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -206,9 +206,6 @@ DEFINE_VIA_REGSET(MI, 0x50);
VIA_MC97_CTRL_SECONDARY)
-typedef struct _snd_via82xx_modem via82xx_t;
-typedef struct via_dev viadev_t;
-
/*
* pcm stream
*/
@@ -220,11 +217,11 @@ struct snd_via_sg_table {
#define VIA_TABLE_SIZE 255
-struct via_dev {
+struct viadev {
unsigned int reg_offset;
unsigned long port;
int direction; /* playback = 0, capture = 1 */
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
int running;
unsigned int tbl_entries; /* # descriptors */
struct snd_dma_buffer table;
@@ -239,7 +236,7 @@ enum { TYPE_CARD_VIA82XX_MODEM = 1 };
#define VIA_MAX_MODEM_DEVS 2
-struct _snd_via82xx_modem {
+struct via82xx_modem {
int irq;
unsigned long port;
@@ -247,21 +244,21 @@ struct _snd_via82xx_modem {
unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
struct pci_dev *pci;
- snd_card_t *card;
+ struct snd_card *card;
unsigned int num_devs;
unsigned int playback_devno, capture_devno;
- viadev_t devs[VIA_MAX_MODEM_DEVS];
+ struct viadev devs[VIA_MAX_MODEM_DEVS];
- snd_pcm_t *pcms[2];
+ struct snd_pcm *pcms[2];
- ac97_bus_t *ac97_bus;
- ac97_t *ac97;
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97 *ac97;
unsigned int ac97_clock;
unsigned int ac97_secondary; /* secondary AC'97 codec is present */
spinlock_t reg_lock;
- snd_info_entry_t *proc_entry;
+ struct snd_info_entry *proc_entry;
};
static struct pci_device_id snd_via82xx_modem_ids[] = {
@@ -279,12 +276,12 @@ MODULE_DEVICE_TABLE(pci, snd_via82xx_modem_ids);
* periods = number of periods
* fragsize = period size in bytes
*/
-static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
+static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci,
unsigned int periods, unsigned int fragsize)
{
unsigned int i, idx, ofs, rest;
- via82xx_t *chip = snd_pcm_substream_chip(substream);
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
if (dev->table.area == NULL) {
@@ -346,7 +343,7 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
}
-static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
+static int clean_via_table(struct viadev *dev, struct snd_pcm_substream *substream,
struct pci_dev *pci)
{
if (dev->table.area) {
@@ -362,17 +359,17 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
* Basic I/O
*/
-static inline unsigned int snd_via82xx_codec_xread(via82xx_t *chip)
+static inline unsigned int snd_via82xx_codec_xread(struct via82xx_modem *chip)
{
return inl(VIAREG(chip, AC97));
}
-static inline void snd_via82xx_codec_xwrite(via82xx_t *chip, unsigned int val)
+static inline void snd_via82xx_codec_xwrite(struct via82xx_modem *chip, unsigned int val)
{
outl(val, VIAREG(chip, AC97));
}
-static int snd_via82xx_codec_ready(via82xx_t *chip, int secondary)
+static int snd_via82xx_codec_ready(struct via82xx_modem *chip, int secondary)
{
unsigned int timeout = 1000; /* 1ms */
unsigned int val;
@@ -382,11 +379,12 @@ static int snd_via82xx_codec_ready(via82xx_t *chip, int secondary)
if (!((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY))
return val & 0xffff;
}
- snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n", secondary, snd_via82xx_codec_xread(chip));
+ snd_printk(KERN_ERR "codec_ready: codec %i is not ready [0x%x]\n",
+ secondary, snd_via82xx_codec_xread(chip));
return -EIO;
}
-static int snd_via82xx_codec_valid(via82xx_t *chip, int secondary)
+static int snd_via82xx_codec_valid(struct via82xx_modem *chip, int secondary)
{
unsigned int timeout = 1000; /* 1ms */
unsigned int val, val1;
@@ -403,20 +401,20 @@ static int snd_via82xx_codec_valid(via82xx_t *chip, int secondary)
return -EIO;
}
-static void snd_via82xx_codec_wait(ac97_t *ac97)
+static void snd_via82xx_codec_wait(struct snd_ac97 *ac97)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx_modem *chip = ac97->private_data;
int err;
err = snd_via82xx_codec_ready(chip, ac97->num);
/* here we need to wait fairly for long time.. */
msleep(500);
}
-static void snd_via82xx_codec_write(ac97_t *ac97,
+static void snd_via82xx_codec_write(struct snd_ac97 *ac97,
unsigned short reg,
unsigned short val)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx_modem *chip = ac97->private_data;
unsigned int xval;
if(reg == AC97_GPIO_STATUS) {
outl(val, VIAREG(chip, GPI_STATUS));
@@ -430,9 +428,9 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
snd_via82xx_codec_ready(chip, ac97->num);
}
-static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
+static unsigned short snd_via82xx_codec_read(struct snd_ac97 *ac97, unsigned short reg)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx_modem *chip = ac97->private_data;
unsigned int xval, val = 0xffff;
int again = 0;
@@ -442,7 +440,8 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
xval |= (reg & 0x7f) << VIA_REG_AC97_CMD_SHIFT;
while (1) {
if (again++ > 3) {
- snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n", ac97->num, snd_via82xx_codec_xread(chip));
+ snd_printk(KERN_ERR "codec_read: codec %i is not valid [0x%x]\n",
+ ac97->num, snd_via82xx_codec_xread(chip));
return 0xffff;
}
snd_via82xx_codec_xwrite(chip, xval);
@@ -456,7 +455,7 @@ static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
return val & 0xffff;
}
-static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev)
+static void snd_via82xx_channel_reset(struct via82xx_modem *chip, struct viadev *viadev)
{
outb(VIA_REG_CTRL_PAUSE | VIA_REG_CTRL_TERMINATE | VIA_REG_CTRL_RESET,
VIADEV_REG(viadev, OFFSET_CONTROL));
@@ -478,7 +477,7 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev)
static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- via82xx_t *chip = dev_id;
+ struct via82xx_modem *chip = dev_id;
unsigned int status;
unsigned int i;
@@ -491,7 +490,7 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *
/* check status for each stream */
spin_lock(&chip->reg_lock);
for (i = 0; i < chip->num_devs; i++) {
- viadev_t *viadev = &chip->devs[i];
+ struct viadev *viadev = &chip->devs[i];
unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
c_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED);
if (! c_status)
@@ -514,10 +513,10 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *
/*
* trigger callback
*/
-static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_via82xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
unsigned char val = 0;
switch (cmd) {
@@ -555,9 +554,11 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
*/
#define check_invalid_pos(viadev,pos) \
- ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))
+ ((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 ||\
+ viadev->lastpos < viadev->bufsize2))
-static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count)
+static inline unsigned int calc_linear_pos(struct viadev *viadev, unsigned int idx,
+ unsigned int count)
{
unsigned int size, res;
@@ -566,24 +567,33 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
/* check the validity of the calculated position */
if (size < count) {
- snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count);
+ snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n",
+ (int)size, (int)count);
res = viadev->lastpos;
} else if (check_invalid_pos(viadev, res)) {
#ifdef POINTER_DEBUG
- printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count);
+ printk(KERN_DEBUG "fail: idx = %i/%i, lastpos = 0x%x, "
+ "bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, "
+ "count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos,
+ viadev->bufsize2, viadev->idx_table[idx].offset,
+ viadev->idx_table[idx].size, count);
#endif
if (count && size < count) {
- snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n");
+ snd_printd(KERN_ERR "invalid via82xx_cur_ptr, "
+ "using last valid pointer\n");
res = viadev->lastpos;
} else {
if (! count)
/* bogus count 0 on the DMA boundary? */
res = viadev->idx_table[idx].offset;
else
- /* count register returns full size when end of buffer is reached */
+ /* count register returns full size
+ * when end of buffer is reached
+ */
res = viadev->idx_table[idx].offset + size;
if (check_invalid_pos(viadev, res)) {
- snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n");
+ snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), "
+ "using last valid pointer\n");
res = viadev->lastpos;
}
}
@@ -597,10 +607,10 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
/*
* get the current pointer on via686
*/
-static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_via686_pcm_pointer(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
unsigned int idx, ptr, count, res;
snd_assert(viadev->tbl_entries, return 0);
@@ -616,7 +626,8 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream)
if (ptr <= (unsigned int)viadev->table.addr)
idx = 0;
else /* CURR_PTR holds the address + 8 */
- idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) % viadev->tbl_entries;
+ idx = ((ptr - (unsigned int)viadev->table.addr) / 8 - 1) %
+ viadev->tbl_entries;
res = calc_linear_pos(viadev, idx, count);
spin_unlock(&chip->reg_lock);
@@ -627,11 +638,11 @@ static snd_pcm_uframes_t snd_via686_pcm_pointer(snd_pcm_substream_t *substream)
* hw_params callback:
* allocate the buffer and build up the buffer description table
*/
-static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
int err;
err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
@@ -653,10 +664,10 @@ static int snd_via82xx_hw_params(snd_pcm_substream_t * substream,
* hw_free callback:
* clean up the buffer description table and release the buffer
*/
-static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
+static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
clean_via_table(viadev, substream, chip->pci);
snd_pcm_lib_free_pages(substream);
@@ -667,7 +678,7 @@ static int snd_via82xx_hw_free(snd_pcm_substream_t * substream)
/*
* set up the table pointer
*/
-static void snd_via82xx_set_table_ptr(via82xx_t *chip, viadev_t *viadev)
+static void snd_via82xx_set_table_ptr(struct via82xx_modem *chip, struct viadev *viadev)
{
snd_via82xx_codec_ready(chip, chip->ac97_secondary);
outl((u32)viadev->table.addr, VIADEV_REG(viadev, OFFSET_TABLE_PTR));
@@ -678,10 +689,10 @@ static void snd_via82xx_set_table_ptr(via82xx_t *chip, viadev_t *viadev)
/*
* prepare callback for playback and capture
*/
-static int snd_via82xx_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_via82xx_pcm_prepare(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = substream->runtime->private_data;
snd_via82xx_channel_reset(chip, viadev);
/* this must be set after channel_reset */
@@ -694,7 +705,7 @@ static int snd_via82xx_pcm_prepare(snd_pcm_substream_t *substream)
/*
* pcm hardware definition, identical for both playback and capture
*/
-static snd_pcm_hardware_t snd_via82xx_hw =
+static struct snd_pcm_hardware snd_via82xx_hw =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -719,12 +730,13 @@ static snd_pcm_hardware_t snd_via82xx_hw =
/*
* open callback skeleton
*/
-static int snd_via82xx_modem_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_substream_t * substream)
+static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev *viadev,
+ struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
static unsigned int rates[] = { 8000, 9600, 12000, 16000 };
- static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+ static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = ARRAY_SIZE(rates),
.list = rates,
.mask = 0,
@@ -732,7 +744,8 @@ static int snd_via82xx_modem_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm
runtime->hw = snd_via82xx_hw;
- if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
+ if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ &hw_constraints_rates)) < 0)
return err;
/* we may remove following constaint when we modify table entries
@@ -750,10 +763,10 @@ static int snd_via82xx_modem_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm
/*
* open callback for playback
*/
-static int snd_via82xx_playback_open(snd_pcm_substream_t * substream)
+static int snd_via82xx_playback_open(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = &chip->devs[chip->playback_devno + substream->number];
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = &chip->devs[chip->playback_devno + substream->number];
return snd_via82xx_modem_pcm_open(chip, viadev, substream);
}
@@ -761,10 +774,10 @@ static int snd_via82xx_playback_open(snd_pcm_substream_t * substream)
/*
* open callback for capture
*/
-static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
+static int snd_via82xx_capture_open(struct snd_pcm_substream *substream)
{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- viadev_t *viadev = &chip->devs[chip->capture_devno + substream->pcm->device];
+ struct via82xx_modem *chip = snd_pcm_substream_chip(substream);
+ struct viadev *viadev = &chip->devs[chip->capture_devno + substream->pcm->device];
return snd_via82xx_modem_pcm_open(chip, viadev, substream);
}
@@ -772,9 +785,9 @@ static int snd_via82xx_capture_open(snd_pcm_substream_t * substream)
/*
* close callback
*/
-static int snd_via82xx_pcm_close(snd_pcm_substream_t * substream)
+static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
{
- viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
+ struct viadev *viadev = substream->runtime->private_data;
viadev->substream = NULL;
return 0;
@@ -782,7 +795,7 @@ static int snd_via82xx_pcm_close(snd_pcm_substream_t * substream)
/* via686 playback callbacks */
-static snd_pcm_ops_t snd_via686_playback_ops = {
+static struct snd_pcm_ops snd_via686_playback_ops = {
.open = snd_via82xx_playback_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -795,7 +808,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = {
};
/* via686 capture callbacks */
-static snd_pcm_ops_t snd_via686_capture_ops = {
+static struct snd_pcm_ops snd_via686_capture_ops = {
.open = snd_via82xx_capture_open,
.close = snd_via82xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -808,7 +821,8 @@ static snd_pcm_ops_t snd_via686_capture_ops = {
};
-static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int direction)
+static void init_viadev(struct via82xx_modem *chip, int idx, unsigned int reg_offset,
+ int direction)
{
chip->devs[idx].reg_offset = reg_offset;
chip->devs[idx].direction = direction;
@@ -818,9 +832,9 @@ static void init_viadev(via82xx_t *chip, int idx, unsigned int reg_offset, int d
/*
* create a pcm instance for via686a/b
*/
-static int __devinit snd_via686_pcm_new(via82xx_t *chip)
+static int __devinit snd_via686_pcm_new(struct via82xx_modem *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
chip->playback_devno = 0;
@@ -841,7 +855,8 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip)
init_viadev(chip, 1, VIA_REG_MI_STATUS, 1);
if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
- snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
+ snd_dma_pci_data(chip->pci),
+ 64*1024, 128*1024)) < 0)
return err;
return 0;
@@ -853,24 +868,24 @@ static int __devinit snd_via686_pcm_new(via82xx_t *chip)
*/
-static void snd_via82xx_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- via82xx_t *chip = bus->private_data;
+ struct via82xx_modem *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
+static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97)
{
- via82xx_t *chip = ac97->private_data;
+ struct via82xx_modem *chip = ac97->private_data;
chip->ac97 = NULL;
}
-static int __devinit snd_via82xx_mixer_new(via82xx_t *chip)
+static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
{
- ac97_template_t ac97;
+ struct snd_ac97_template ac97;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_via82xx_codec_write,
.read = snd_via82xx_codec_read,
.wait = snd_via82xx_codec_wait,
@@ -898,9 +913,9 @@ static int __devinit snd_via82xx_mixer_new(via82xx_t *chip)
/*
* proc interface
*/
-static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void snd_via82xx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- via82xx_t *chip = entry->private_data;
+ struct via82xx_modem *chip = entry->private_data;
int i;
snd_iprintf(buffer, "%s\n\n", chip->card->longname);
@@ -909,9 +924,9 @@ static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
}
}
-static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
+static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "via82xx", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read);
@@ -921,7 +936,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
*
*/
-static int snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(struct via82xx_modem *chip)
{
unsigned int val;
unsigned long end_time;
@@ -1004,31 +1019,35 @@ static int snd_via82xx_chip_init(via82xx_t *chip)
/*
* power management
*/
-static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
+static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state)
{
- via82xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct via82xx_modem *chip = card->private_data;
int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
for (i = 0; i < 2; i++)
- if (chip->pcms[i])
- snd_pcm_suspend_all(chip->pcms[i]);
+ snd_pcm_suspend_all(chip->pcms[i]);
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
synchronize_irq(chip->irq);
snd_ac97_suspend(chip->ac97);
- pci_set_power_state(chip->pci, 3);
- pci_disable_device(chip->pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_via82xx_resume(snd_card_t *card)
+static int snd_via82xx_resume(struct pci_dev *pci)
{
- via82xx_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct via82xx_modem *chip = card->private_data;
int i;
- pci_enable_device(chip->pci);
- pci_set_power_state(chip->pci, 0);
- pci_set_master(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
snd_via82xx_chip_init(chip);
@@ -1037,11 +1056,12 @@ static int snd_via82xx_resume(snd_card_t *card)
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-static int snd_via82xx_free(via82xx_t *chip)
+static int snd_via82xx_free(struct via82xx_modem *chip)
{
unsigned int i;
@@ -1053,29 +1073,29 @@ static int snd_via82xx_free(via82xx_t *chip)
synchronize_irq(chip->irq);
__end_hw:
if (chip->irq >= 0)
- free_irq(chip->irq, (void *)chip);
+ free_irq(chip->irq, chip);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
return 0;
}
-static int snd_via82xx_dev_free(snd_device_t *device)
+static int snd_via82xx_dev_free(struct snd_device *device)
{
- via82xx_t *chip = device->device_data;
+ struct via82xx_modem *chip = device->device_data;
return snd_via82xx_free(chip);
}
-static int __devinit snd_via82xx_create(snd_card_t * card,
+static int __devinit snd_via82xx_create(struct snd_card *card,
struct pci_dev *pci,
int chip_type,
int revision,
unsigned int ac97_clock,
- via82xx_t ** r_via)
+ struct via82xx_modem ** r_via)
{
- via82xx_t *chip;
+ struct via82xx_modem *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_via82xx_dev_free,
};
@@ -1099,7 +1119,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
}
chip->port = pci_resource_start(pci, 0);
if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ,
- card->driver, (void *)chip)) {
+ card->driver, chip)) {
snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
snd_via82xx_free(chip);
return -EBUSY;
@@ -1134,8 +1154,8 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
static int __devinit snd_via82xx_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
- snd_card_t *card;
- via82xx_t *chip;
+ struct snd_card *card;
+ struct via82xx_modem *chip;
unsigned char revision;
int chip_type = 0, card_type;
unsigned int i;
@@ -1161,14 +1181,13 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
if ((err = snd_via82xx_create(card, pci, chip_type, revision,
ac97_clock, &chip)) < 0)
goto __error;
+ card->private_data = chip;
if ((err = snd_via82xx_mixer_new(chip)) < 0)
goto __error;
if ((err = snd_via686_pcm_new(chip)) < 0 )
goto __error;
- snd_card_set_pm_callback(card, snd_via82xx_suspend, snd_via82xx_resume, chip);
-
/* disable interrupts */
for (i = 0; i < chip->num_devs; i++)
snd_via82xx_channel_reset(chip, &chip->devs[i]);
@@ -1201,7 +1220,10 @@ static struct pci_driver driver = {
.id_table = snd_via82xx_modem_ids,
.probe = snd_via82xx_probe,
.remove = __devexit_p(snd_via82xx_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_via82xx_suspend,
+ .resume = snd_via82xx_resume,
+#endif
};
static int __init alsa_card_via82xx_init(void)
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index dca6bd2c7580..c816ddf1b215 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -108,7 +108,7 @@ static struct snd_vx_hardware vx222_mic_hw = {
/*
*/
-static int snd_vx222_free(vx_core_t *chip)
+static int snd_vx222_free(struct vx_core *chip)
{
struct snd_vx222 *vx = (struct snd_vx222 *)chip;
@@ -121,21 +121,21 @@ static int snd_vx222_free(vx_core_t *chip)
return 0;
}
-static int snd_vx222_dev_free(snd_device_t *device)
+static int snd_vx222_dev_free(struct snd_device *device)
{
- vx_core_t *chip = device->device_data;
+ struct vx_core *chip = device->device_data;
return snd_vx222_free(chip);
}
-static int __devinit snd_vx222_create(snd_card_t *card, struct pci_dev *pci,
+static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
struct snd_vx_hardware *hw,
struct snd_vx222 **rchip)
{
- vx_core_t *chip;
+ struct vx_core *chip;
struct snd_vx222 *vx;
int i, err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_vx222_dev_free,
};
struct snd_vx_ops *vx_ops;
@@ -147,7 +147,7 @@ static int __devinit snd_vx222_create(snd_card_t *card, struct pci_dev *pci,
vx_ops = hw->type == VX_TYPE_BOARD ? &vx222_old_ops : &vx222_ops;
chip = snd_vx_create(card, hw, vx_ops,
- sizeof(struct snd_vx222) - sizeof(vx_core_t));
+ sizeof(struct snd_vx222) - sizeof(struct vx_core));
if (! chip) {
pci_disable_device(pci);
return -ENOMEM;
@@ -186,7 +186,7 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
+ struct snd_card *card;
struct snd_vx_hardware *hw;
struct snd_vx222 *vx;
int err;
@@ -218,6 +218,7 @@ static int __devinit snd_vx222_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
+ card->private_data = vx;
vx->core.ibl.size = ibl[dev];
sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %i",
@@ -250,12 +251,42 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
+#ifdef CONFIG_PM
+static int snd_vx222_suspend(struct pci_dev *pci, pm_message_t state)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_vx222 *vx = card->private_data;
+ int err;
+
+ err = snd_vx_suspend(&vx->core, state);
+ pci_set_power_state(pci, PCI_D3hot);
+ pci_disable_device(pci);
+ pci_save_state(pci);
+ return err;
+}
+
+static int snd_vx222_resume(struct pci_dev *pci)
+{
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_vx222 *vx = card->private_data;
+
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_power_state(pci, PCI_D0);
+ pci_set_master(pci);
+ return snd_vx_resume(&vx->core);
+}
+#endif
+
static struct pci_driver driver = {
.name = "Digigram VX222",
.id_table = snd_vx222_ids,
.probe = snd_vx222_probe,
.remove = __devexit_p(snd_vx222_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_vx222_suspend,
+ .resume = snd_vx222_resume,
+#endif
};
static int __init alsa_card_vx222_init(void)
diff --git a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h
index 18478ae124a9..2f0d78f609a6 100644
--- a/sound/pci/vx222/vx222.h
+++ b/sound/pci/vx222/vx222.h
@@ -25,7 +25,7 @@
struct snd_vx222 {
- vx_core_t core;
+ struct vx_core core;
/* h/w config; for PLX and for DSP */
struct pci_dev *pci;
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 967bd5e6b23c..c705af409b0f 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -82,7 +82,7 @@ static int vx2_reg_index[VX_REG_MAX] = {
[VX_GPIOC] = 0, /* on the PLX */
};
-static inline unsigned long vx2_reg_addr(vx_core_t *_chip, int reg)
+static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg];
@@ -92,7 +92,7 @@ static inline unsigned long vx2_reg_addr(vx_core_t *_chip, int reg)
* snd_vx_inb - read a byte from the register
* @offset: register enum
*/
-static unsigned char vx2_inb(vx_core_t *chip, int offset)
+static unsigned char vx2_inb(struct vx_core *chip, int offset)
{
return inb(vx2_reg_addr(chip, offset));
}
@@ -102,7 +102,7 @@ static unsigned char vx2_inb(vx_core_t *chip, int offset)
* @offset: the register offset
* @val: the value to write
*/
-static void vx2_outb(vx_core_t *chip, int offset, unsigned char val)
+static void vx2_outb(struct vx_core *chip, int offset, unsigned char val)
{
outb(val, vx2_reg_addr(chip, offset));
//printk("outb: %x -> %x\n", val, vx2_reg_addr(chip, offset));
@@ -112,7 +112,7 @@ static void vx2_outb(vx_core_t *chip, int offset, unsigned char val)
* snd_vx_inl - read a 32bit word from the register
* @offset: register enum
*/
-static unsigned int vx2_inl(vx_core_t *chip, int offset)
+static unsigned int vx2_inl(struct vx_core *chip, int offset)
{
return inl(vx2_reg_addr(chip, offset));
}
@@ -122,7 +122,7 @@ static unsigned int vx2_inl(vx_core_t *chip, int offset)
* @offset: the register enum
* @val: the value to write
*/
-static void vx2_outl(vx_core_t *chip, int offset, unsigned int val)
+static void vx2_outl(struct vx_core *chip, int offset, unsigned int val)
{
// printk("outl: %x -> %x\n", val, vx2_reg_addr(chip, offset));
outl(val, vx2_reg_addr(chip, offset));
@@ -132,13 +132,13 @@ static void vx2_outl(vx_core_t *chip, int offset, unsigned int val)
* redefine macros to call directly
*/
#undef vx_inb
-#define vx_inb(chip,reg) vx2_inb((vx_core_t*)(chip), VX_##reg)
+#define vx_inb(chip,reg) vx2_inb((struct vx_core*)(chip), VX_##reg)
#undef vx_outb
-#define vx_outb(chip,reg,val) vx2_outb((vx_core_t*)(chip), VX_##reg, val)
+#define vx_outb(chip,reg,val) vx2_outb((struct vx_core*)(chip), VX_##reg, val)
#undef vx_inl
-#define vx_inl(chip,reg) vx2_inl((vx_core_t*)(chip), VX_##reg)
+#define vx_inl(chip,reg) vx2_inl((struct vx_core*)(chip), VX_##reg)
#undef vx_outl
-#define vx_outl(chip,reg,val) vx2_outl((vx_core_t*)(chip), VX_##reg, val)
+#define vx_outl(chip,reg,val) vx2_outl((struct vx_core*)(chip), VX_##reg, val)
/*
@@ -147,14 +147,14 @@ static void vx2_outl(vx_core_t *chip, int offset, unsigned int val)
#define XX_DSP_RESET_WAIT_TIME 2 /* ms */
-static void vx2_reset_dsp(vx_core_t *_chip)
+static void vx2_reset_dsp(struct vx_core *_chip)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
/* set the reset dsp bit to 0 */
vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK);
- snd_vx_delay(_chip, XX_DSP_RESET_WAIT_TIME);
+ mdelay(XX_DSP_RESET_WAIT_TIME);
chip->regCDSP |= VX_CDSP_DSP_RESET_MASK;
/* set the reset dsp bit to 1 */
@@ -162,7 +162,7 @@ static void vx2_reset_dsp(vx_core_t *_chip)
}
-static int vx2_test_xilinx(vx_core_t *_chip)
+static int vx2_test_xilinx(struct vx_core *_chip)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
unsigned int data;
@@ -219,7 +219,7 @@ static int vx2_test_xilinx(vx_core_t *_chip)
* vx_setup_pseudo_dma - set up the pseudo dma read/write mode.
* @do_write: 0 = read, 1 = set up for DMA write
*/
-static void vx2_setup_pseudo_dma(vx_core_t *chip, int do_write)
+static void vx2_setup_pseudo_dma(struct vx_core *chip, int do_write)
{
/* Interrupt mode and HREQ pin enabled for host transmit data transfers
* (in case of the use of the pseudo-dma facility).
@@ -235,7 +235,7 @@ static void vx2_setup_pseudo_dma(vx_core_t *chip, int do_write)
/*
* vx_release_pseudo_dma - disable the pseudo-DMA mode
*/
-static inline void vx2_release_pseudo_dma(vx_core_t *chip)
+static inline void vx2_release_pseudo_dma(struct vx_core *chip)
{
/* HREQ pin disabled. */
vx_outl(chip, ICR, 0);
@@ -244,8 +244,8 @@ static inline void vx2_release_pseudo_dma(vx_core_t *chip)
/* pseudo-dma write */
-static void vx2_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
unsigned long port = vx2_reg_addr(chip, VX_DMA);
int offset = pipe->hw_ptr;
@@ -282,8 +282,8 @@ static void vx2_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
/* pseudo dma read */
-static void vx2_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
int offset = pipe->hw_ptr;
u32 *addr = (u32 *)(runtime->dma_area + offset);
@@ -321,7 +321,7 @@ static void vx2_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
/*
* transfer counts bits to PLX
*/
-static int put_xilinx_data(vx_core_t *chip, unsigned int port, unsigned int counts, unsigned char data)
+static int put_xilinx_data(struct vx_core *chip, unsigned int port, unsigned int counts, unsigned char data)
{
unsigned int i;
@@ -353,7 +353,7 @@ static int put_xilinx_data(vx_core_t *chip, unsigned int port, unsigned int coun
/*
* load the xilinx image
*/
-static int vx2_load_xilinx_binary(vx_core_t *chip, const struct firmware *xilinx)
+static int vx2_load_xilinx_binary(struct vx_core *chip, const struct firmware *xilinx)
{
unsigned int i;
unsigned int port;
@@ -362,10 +362,10 @@ static int vx2_load_xilinx_binary(vx_core_t *chip, const struct firmware *xilinx
/* XILINX reset (wait at least 1 milisecond between reset on and off). */
vx_outl(chip, CNTRL, VX_CNTRL_REGISTER_VALUE | VX_XILINX_RESET_MASK);
vx_inl(chip, CNTRL);
- snd_vx_delay(chip, 10);
+ msleep(10);
vx_outl(chip, CNTRL, VX_CNTRL_REGISTER_VALUE);
vx_inl(chip, CNTRL);
- snd_vx_delay(chip, 10);
+ msleep(10);
if (chip->type == VX_TYPE_BOARD)
port = VX_CNTRL;
@@ -381,7 +381,7 @@ static int vx2_load_xilinx_binary(vx_core_t *chip, const struct firmware *xilinx
}
put_xilinx_data(chip, port, 4, 0xff); /* end signature */
- snd_vx_delay(chip, 200);
+ msleep(200);
/* test after loading (is buggy with VX222) */
if (chip->type != VX_TYPE_BOARD) {
@@ -400,7 +400,7 @@ static int vx2_load_xilinx_binary(vx_core_t *chip, const struct firmware *xilinx
/*
* load the boot/dsp images
*/
-static int vx2_load_dsp(vx_core_t *vx, int index, const struct firmware *dsp)
+static int vx2_load_dsp(struct vx_core *vx, int index, const struct firmware *dsp)
{
int err;
@@ -432,7 +432,7 @@ static int vx2_load_dsp(vx_core_t *vx, int index, const struct firmware *dsp)
*
* spinlock held!
*/
-static int vx2_test_and_ack(vx_core_t *chip)
+static int vx2_test_and_ack(struct vx_core *chip)
{
/* not booted yet? */
if (! (chip->chip_status & VX_STAT_XILINX_LOADED))
@@ -463,7 +463,7 @@ static int vx2_test_and_ack(vx_core_t *chip)
/*
* vx_validate_irq - enable/disable IRQ
*/
-static void vx2_validate_irq(vx_core_t *_chip, int enable)
+static void vx2_validate_irq(struct vx_core *_chip, int enable)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
@@ -484,7 +484,7 @@ static void vx2_validate_irq(vx_core_t *_chip, int enable)
/*
* write an AKM codec data (24bit)
*/
-static void vx2_write_codec_reg(vx_core_t *chip, unsigned int data)
+static void vx2_write_codec_reg(struct vx_core *chip, unsigned int data)
{
unsigned int i;
@@ -660,7 +660,7 @@ static const u8 vx2_akm_gains_lut[VX2_AKM_LEVEL_MAX+1] = {
/*
* pseudo-codec write entry
*/
-static void vx2_write_akm(vx_core_t *chip, int reg, unsigned int data)
+static void vx2_write_akm(struct vx_core *chip, int reg, unsigned int data)
{
unsigned int val;
@@ -695,7 +695,7 @@ static void vx2_write_akm(vx_core_t *chip, int reg, unsigned int data)
/*
* write codec bit for old VX222 board
*/
-static void vx2_old_write_codec_bit(vx_core_t *chip, int codec, unsigned int data)
+static void vx2_old_write_codec_bit(struct vx_core *chip, int codec, unsigned int data)
{
int i;
@@ -713,24 +713,24 @@ static void vx2_old_write_codec_bit(vx_core_t *chip, int codec, unsigned int dat
/*
* reset codec bit
*/
-static void vx2_reset_codec(vx_core_t *_chip)
+static void vx2_reset_codec(struct vx_core *_chip)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
/* Set the reset CODEC bit to 0. */
vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK);
vx_inl(chip, CDSP);
- snd_vx_delay(_chip, 10);
+ msleep(10);
/* Set the reset CODEC bit to 1. */
chip->regCDSP |= VX_CDSP_CODEC_RESET_MASK;
vx_outl(chip, CDSP, chip->regCDSP);
vx_inl(chip, CDSP);
if (_chip->type == VX_TYPE_BOARD) {
- snd_vx_delay(_chip, 1);
+ msleep(1);
return;
}
- snd_vx_delay(_chip, 5); /* additionnel wait time for AKM's */
+ msleep(5); /* additionnel wait time for AKM's */
vx2_write_codec_reg(_chip, AKM_CODEC_POWER_CONTROL_CMD); /* DAC power up, ADC power up, Vref power down */
@@ -755,7 +755,7 @@ static void vx2_reset_codec(vx_core_t *_chip)
/*
* change the audio source
*/
-static void vx2_change_audio_source(vx_core_t *_chip, int src)
+static void vx2_change_audio_source(struct vx_core *_chip, int src)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
@@ -774,7 +774,7 @@ static void vx2_change_audio_source(vx_core_t *_chip, int src)
/*
* set the clock source
*/
-static void vx2_set_clock_source(vx_core_t *_chip, int source)
+static void vx2_set_clock_source(struct vx_core *_chip, int source)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
@@ -788,7 +788,7 @@ static void vx2_set_clock_source(vx_core_t *_chip, int source)
/*
* reset the board
*/
-static void vx2_reset_board(vx_core_t *_chip, int cold_reset)
+static void vx2_reset_board(struct vx_core *_chip, int cold_reset)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
@@ -848,7 +848,7 @@ static void vx2_set_input_level(struct snd_vx222 *chip)
*/
/* input levels */
-static int vx_input_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_input_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -857,9 +857,9 @@ static int vx_input_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
return 0;
}
-static int vx_input_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
down(&_chip->mixer_mutex);
ucontrol->value.integer.value[0] = chip->input_level[0];
@@ -868,9 +868,9 @@ static int vx_input_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static int vx_input_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
down(&_chip->mixer_mutex);
if (chip->input_level[0] != ucontrol->value.integer.value[0] ||
@@ -886,7 +886,7 @@ static int vx_input_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
}
/* mic level */
-static int vx_mic_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -895,17 +895,17 @@ static int vx_mic_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int vx_mic_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
-static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
down(&_chip->mixer_mutex);
if (chip->mic_level != ucontrol->value.integer.value[0]) {
@@ -918,7 +918,7 @@ static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static snd_kcontrol_new_t vx_control_input_level = {
+static struct snd_kcontrol_new vx_control_input_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Volume",
.info = vx_input_level_info,
@@ -926,7 +926,7 @@ static snd_kcontrol_new_t vx_control_input_level = {
.put = vx_input_level_put,
};
-static snd_kcontrol_new_t vx_control_mic_level = {
+static struct snd_kcontrol_new vx_control_mic_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Capture Volume",
.info = vx_mic_level_info,
@@ -938,7 +938,7 @@ static snd_kcontrol_new_t vx_control_mic_level = {
* FIXME: compressor/limiter implementation is missing yet...
*/
-static int vx2_add_mic_controls(vx_core_t *_chip)
+static int vx2_add_mic_controls(struct vx_core *_chip)
{
struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
int err;
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index d013237205d8..dab9b8310341 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -31,7 +31,7 @@
#include <sound/initval.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Yamaha DS-XG PCI");
+MODULE_DESCRIPTION("Yamaha DS-1 PCI");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
"{Yamaha,YMF724F},"
@@ -51,11 +51,11 @@ static long joystick_port[SNDRV_CARDS];
static int rear_switch[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for the Yamaha DS-XG PCI soundcard.");
+MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard.");
module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for the Yamaha DS-XG PCI soundcard.");
+MODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard.");
module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Yamaha DS-XG soundcard.");
+MODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard.");
module_param_array(mpu_port, long, NULL, 0444);
MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
module_param_array(fm_port, long, NULL, 0444);
@@ -80,7 +80,7 @@ static struct pci_device_id snd_ymfpci_ids[] = {
MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
#ifdef SUPPORT_JOYSTICK
-static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
+static int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
int legacy_ctrl, int legacy_ctrl2)
{
struct gameport *gp;
@@ -152,7 +152,7 @@ static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
return 0;
}
-void snd_ymfpci_free_gameport(ymfpci_t *chip)
+void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
{
if (chip->gameport) {
struct resource *r = gameport_get_port_data(chip->gameport);
@@ -164,20 +164,20 @@ void snd_ymfpci_free_gameport(ymfpci_t *chip)
}
}
#else
-static inline int snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, int l, int l2) { return -ENOSYS; }
-void snd_ymfpci_free_gameport(ymfpci_t *chip) { }
+static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, int l, int l2) { return -ENOSYS; }
+void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
#endif /* SUPPORT_JOYSTICK */
static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
+ struct snd_card *card;
struct resource *fm_res = NULL;
struct resource *mpu_res = NULL;
- ymfpci_t *chip;
- opl3_t *opl3;
- char *str;
+ struct snd_ymfpci *chip;
+ struct snd_opl3 *opl3;
+ const char *str, *model;
int err;
u16 legacy_ctrl, legacy_ctrl2, old_legacy_ctrl;
@@ -193,13 +193,13 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
return -ENOMEM;
switch (pci_id->device) {
- case 0x0004: str = "YMF724"; break;
- case 0x000d: str = "YMF724F"; break;
- case 0x000a: str = "YMF740"; break;
- case 0x000c: str = "YMF740C"; break;
- case 0x0010: str = "YMF744"; break;
- case 0x0012: str = "YMF754"; break;
- default: str = "???"; break;
+ case 0x0004: str = "YMF724"; model = "DS-1"; break;
+ case 0x000d: str = "YMF724F"; model = "DS-1"; break;
+ case 0x000a: str = "YMF740"; model = "DS-1L"; break;
+ case 0x000c: str = "YMF740C"; model = "DS-1L"; break;
+ case 0x0010: str = "YMF744"; model = "DS-1S"; break;
+ case 0x0012: str = "YMF754"; model = "DS-1E"; break;
+ default: model = str = "???"; break;
}
legacy_ctrl = 0;
@@ -271,8 +271,10 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
}
chip->fm_res = fm_res;
chip->mpu_res = mpu_res;
+ card->private_data = chip;
+
strcpy(card->driver, str);
- sprintf(card->shortname, "Yamaha DS-XG (%s)", str);
+ sprintf(card->shortname, "Yamaha %s (%s)", model, str);
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname,
chip->reg_area_phys,
@@ -343,11 +345,14 @@ static void __devexit snd_card_ymfpci_remove(struct pci_dev *pci)
}
static struct pci_driver driver = {
- .name = "Yamaha DS-XG PCI",
+ .name = "Yamaha DS-1 PCI",
.id_table = snd_ymfpci_ids,
.probe = snd_card_ymfpci_probe,
.remove = __devexit_p(snd_card_ymfpci_remove),
- SND_PCI_PM_CALLBACKS
+#ifdef CONFIG_PM
+ .suspend = snd_ymfpci_suspend,
+ .resume = snd_ymfpci_resume,
+#endif
};
static int __init alsa_card_ymfpci_init(void)
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 88a43e091d77..1dfc7233c6a8 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -50,39 +50,39 @@
* common I/O routines
*/
-static void snd_ymfpci_irq_wait(ymfpci_t *chip);
+static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip);
-static inline u8 snd_ymfpci_readb(ymfpci_t *chip, u32 offset)
+static inline u8 snd_ymfpci_readb(struct snd_ymfpci *chip, u32 offset)
{
return readb(chip->reg_area_virt + offset);
}
-static inline void snd_ymfpci_writeb(ymfpci_t *chip, u32 offset, u8 val)
+static inline void snd_ymfpci_writeb(struct snd_ymfpci *chip, u32 offset, u8 val)
{
writeb(val, chip->reg_area_virt + offset);
}
-static inline u16 snd_ymfpci_readw(ymfpci_t *chip, u32 offset)
+static inline u16 snd_ymfpci_readw(struct snd_ymfpci *chip, u32 offset)
{
return readw(chip->reg_area_virt + offset);
}
-static inline void snd_ymfpci_writew(ymfpci_t *chip, u32 offset, u16 val)
+static inline void snd_ymfpci_writew(struct snd_ymfpci *chip, u32 offset, u16 val)
{
writew(val, chip->reg_area_virt + offset);
}
-static inline u32 snd_ymfpci_readl(ymfpci_t *chip, u32 offset)
+static inline u32 snd_ymfpci_readl(struct snd_ymfpci *chip, u32 offset)
{
return readl(chip->reg_area_virt + offset);
}
-static inline void snd_ymfpci_writel(ymfpci_t *chip, u32 offset, u32 val)
+static inline void snd_ymfpci_writel(struct snd_ymfpci *chip, u32 offset, u32 val)
{
writel(val, chip->reg_area_virt + offset);
}
-static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary)
+static int snd_ymfpci_codec_ready(struct snd_ymfpci *chip, int secondary)
{
unsigned long end_time;
u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR;
@@ -98,9 +98,9 @@ static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary)
return -EBUSY;
}
-static void snd_ymfpci_codec_write(ac97_t *ac97, u16 reg, u16 val)
+static void snd_ymfpci_codec_write(struct snd_ac97 *ac97, u16 reg, u16 val)
{
- ymfpci_t *chip = ac97->private_data;
+ struct snd_ymfpci *chip = ac97->private_data;
u32 cmd;
snd_ymfpci_codec_ready(chip, 0);
@@ -108,9 +108,9 @@ static void snd_ymfpci_codec_write(ac97_t *ac97, u16 reg, u16 val)
snd_ymfpci_writel(chip, YDSXGR_AC97CMDDATA, cmd);
}
-static u16 snd_ymfpci_codec_read(ac97_t *ac97, u16 reg)
+static u16 snd_ymfpci_codec_read(struct snd_ac97 *ac97, u16 reg)
{
- ymfpci_t *chip = ac97->private_data;
+ struct snd_ymfpci *chip = ac97->private_data;
if (snd_ymfpci_codec_ready(chip, 0))
return ~0;
@@ -182,7 +182,7 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate)
* Hardware start management
*/
-static void snd_ymfpci_hw_start(ymfpci_t *chip)
+static void snd_ymfpci_hw_start(struct snd_ymfpci *chip)
{
unsigned long flags;
@@ -196,7 +196,7 @@ static void snd_ymfpci_hw_start(ymfpci_t *chip)
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-static void snd_ymfpci_hw_stop(ymfpci_t *chip)
+static void snd_ymfpci_hw_stop(struct snd_ymfpci *chip)
{
unsigned long flags;
long timeout = 1000;
@@ -222,9 +222,11 @@ static void snd_ymfpci_hw_stop(ymfpci_t *chip)
* Playback voice management
*/
-static int voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice)
+static int voice_alloc(struct snd_ymfpci *chip,
+ enum snd_ymfpci_voice_type type, int pair,
+ struct snd_ymfpci_voice **rvoice)
{
- ymfpci_voice_t *voice, *voice2;
+ struct snd_ymfpci_voice *voice, *voice2;
int idx;
*rvoice = NULL;
@@ -258,7 +260,9 @@ static int voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpc
return -ENOMEM;
}
-static int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice)
+static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip,
+ enum snd_ymfpci_voice_type type, int pair,
+ struct snd_ymfpci_voice **rvoice)
{
unsigned long flags;
int result;
@@ -278,7 +282,7 @@ static int snd_ymfpci_voice_alloc(ymfpci_t *chip, ymfpci_voice_type_t type, int
return result;
}
-static int snd_ymfpci_voice_free(ymfpci_t *chip, ymfpci_voice_t *pvoice)
+static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voice *pvoice)
{
unsigned long flags;
@@ -296,9 +300,9 @@ static int snd_ymfpci_voice_free(ymfpci_t *chip, ymfpci_voice_t *pvoice)
* PCM part
*/
-static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
+static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice)
{
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci_pcm *ypcm;
u32 pos, delta;
if ((ypcm = voice->ypcm) == NULL)
@@ -325,7 +329,7 @@ static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
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;
+ struct snd_ymfpci_playback_bank *bank;
u32 volume;
bank = &voice->bank[next_bank];
@@ -345,11 +349,11 @@ static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
spin_unlock(&chip->reg_lock);
}
-static void snd_ymfpci_pcm_capture_interrupt(snd_pcm_substream_t *substream)
+static void snd_ymfpci_pcm_capture_interrupt(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
- ymfpci_t *chip = ypcm->chip;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
+ struct snd_ymfpci *chip = ypcm->chip;
u32 pos, delta;
spin_lock(&chip->reg_lock);
@@ -372,11 +376,11 @@ static void snd_ymfpci_pcm_capture_interrupt(snd_pcm_substream_t *substream)
spin_unlock(&chip->reg_lock);
}
-static int snd_ymfpci_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- ymfpci_pcm_t *ypcm = substream->runtime->private_data;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
int result = 0;
spin_lock(&chip->reg_lock);
@@ -409,11 +413,11 @@ static int snd_ymfpci_playback_trigger(snd_pcm_substream_t * substream,
spin_unlock(&chip->reg_lock);
return result;
}
-static int snd_ymfpci_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- ymfpci_pcm_t *ypcm = substream->runtime->private_data;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
int result = 0;
u32 tmp;
@@ -441,7 +445,7 @@ static int snd_ymfpci_capture_trigger(snd_pcm_substream_t * substream,
return result;
}
-static int snd_ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
+static int snd_ymfpci_pcm_voice_alloc(struct snd_ymfpci_pcm *ypcm, int voices)
{
int err;
@@ -471,16 +475,16 @@ static int snd_ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices)
return 0;
}
-static void snd_ymfpci_pcm_init_voice(ymfpci_pcm_t *ypcm, unsigned int voiceidx,
- snd_pcm_runtime_t *runtime,
+static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int voiceidx,
+ struct snd_pcm_runtime *runtime,
int has_pcm_volume)
{
- ymfpci_voice_t *voice = ypcm->voices[voiceidx];
+ struct snd_ymfpci_voice *voice = ypcm->voices[voiceidx];
u32 format;
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;
+ struct snd_ymfpci_playback_bank *bank;
unsigned int nbank;
u32 vol_left, vol_right;
u8 use_left, use_right;
@@ -544,7 +548,7 @@ static void snd_ymfpci_pcm_init_voice(ymfpci_pcm_t *ypcm, unsigned int voiceidx,
}
}
-static int __devinit snd_ymfpci_ac3_init(ymfpci_t *chip)
+static int __devinit snd_ymfpci_ac3_init(struct snd_ymfpci *chip)
{
if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
4096, &chip->ac3_tmp_base) < 0)
@@ -566,7 +570,7 @@ static int __devinit snd_ymfpci_ac3_init(ymfpci_t *chip)
return 0;
}
-static int snd_ymfpci_ac3_done(ymfpci_t *chip)
+static int snd_ymfpci_ac3_done(struct snd_ymfpci *chip)
{
spin_lock_irq(&chip->reg_lock);
snd_ymfpci_writel(chip, YDSXGR_MAPOFEFFECT,
@@ -580,11 +584,11 @@ static int snd_ymfpci_ac3_done(ymfpci_t *chip)
return 0;
}
-static int snd_ymfpci_playback_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ymfpci_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
int err;
if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -594,11 +598,11 @@ static int snd_ymfpci_playback_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_hw_free(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
if (runtime->private_data == NULL)
return 0;
@@ -618,11 +622,11 @@ static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
unsigned int nvoice;
ypcm->period_size = runtime->period_size;
@@ -635,27 +639,27 @@ static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ymfpci_capture_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_ymfpci_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ymfpci_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_ymfpci_capture_hw_free(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
/* wait, until the PCI operations are not finished */
snd_ymfpci_irq_wait(chip);
return snd_pcm_lib_free_pages(substream);
}
-static int snd_ymfpci_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ymfpci_capture_prepare(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
- snd_ymfpci_capture_bank_t * bank;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
+ struct snd_ymfpci_capture_bank * bank;
int nbank;
u32 rate, format;
@@ -694,30 +698,30 @@ static int snd_ymfpci_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_ymfpci_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ymfpci_playback_pointer(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
- ymfpci_voice_t *voice = ypcm->voices[0];
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
+ struct snd_ymfpci_voice *voice = ypcm->voices[0];
if (!(ypcm->running && voice))
return 0;
return le32_to_cpu(voice->bank[chip->active_bank].start);
}
-static snd_pcm_uframes_t snd_ymfpci_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_ymfpci_capture_pointer(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
if (!ypcm->running)
return 0;
return le32_to_cpu(chip->bank_capture[ypcm->capture_bank_number][chip->active_bank]->start) >> ypcm->shift;
}
-static void snd_ymfpci_irq_wait(ymfpci_t *chip)
+static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip)
{
wait_queue_t wait;
int loops = 4;
@@ -735,9 +739,9 @@ static void snd_ymfpci_irq_wait(ymfpci_t *chip)
static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- ymfpci_t *chip = dev_id;
+ struct snd_ymfpci *chip = dev_id;
u32 status, nvoice, mode;
- ymfpci_voice_t *voice;
+ struct snd_ymfpci_voice *voice;
status = snd_ymfpci_readl(chip, YDSXGR_STATUS);
if (status & 0x80000000) {
@@ -783,7 +787,7 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *r
return IRQ_HANDLED;
}
-static snd_pcm_hardware_t snd_ymfpci_playback =
+static struct snd_pcm_hardware snd_ymfpci_playback =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -805,7 +809,7 @@ static snd_pcm_hardware_t snd_ymfpci_playback =
.fifo_size = 0,
};
-static snd_pcm_hardware_t snd_ymfpci_capture =
+static struct snd_pcm_hardware snd_ymfpci_capture =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -827,16 +831,16 @@ static snd_pcm_hardware_t snd_ymfpci_capture =
.fifo_size = 0,
};
-static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
+static void snd_ymfpci_pcm_free_substream(struct snd_pcm_runtime *runtime)
{
kfree(runtime->private_data);
}
-static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
@@ -853,7 +857,7 @@ static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
}
/* call with spinlock held */
-static void ymfpci_open_extension(ymfpci_t *chip)
+static void ymfpci_open_extension(struct snd_ymfpci *chip)
{
if (! chip->rear_opened) {
if (! chip->spdif_opened) /* set AC3 */
@@ -866,7 +870,7 @@ static void ymfpci_open_extension(ymfpci_t *chip)
}
/* call with spinlock held */
-static void ymfpci_close_extension(ymfpci_t *chip)
+static void ymfpci_close_extension(struct snd_ymfpci *chip)
{
if (! chip->rear_opened) {
if (! chip->spdif_opened)
@@ -877,12 +881,12 @@ static void ymfpci_close_extension(ymfpci_t *chip)
}
}
-static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
- snd_kcontrol_t *kctl;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
+ struct snd_kcontrol *kctl;
int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -903,11 +907,11 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ymfpci_playback_spdif_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_spdif_open(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -930,11 +934,11 @@ static int snd_ymfpci_playback_spdif_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ymfpci_playback_4ch_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_4ch_open(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
@@ -949,12 +953,12 @@ static int snd_ymfpci_playback_4ch_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,
+static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream,
u32 capture_bank_number)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm;
ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
@@ -973,26 +977,26 @@ static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_ymfpci_capture_rec_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_capture_rec_open(struct snd_pcm_substream *substream)
{
return snd_ymfpci_capture_open(substream, 0);
}
-static int snd_ymfpci_capture_ac97_open(snd_pcm_substream_t * substream)
+static int snd_ymfpci_capture_ac97_open(struct snd_pcm_substream *substream)
{
return snd_ymfpci_capture_open(substream, 1);
}
-static int snd_ymfpci_playback_close_1(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_close_1(struct snd_pcm_substream *substream)
{
return 0;
}
-static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- ymfpci_pcm_t *ypcm = substream->runtime->private_data;
- snd_kcontrol_t *kctl;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
+ struct snd_kcontrol *kctl;
spin_lock_irq(&chip->reg_lock);
if (ypcm->output_rear && chip->rear_opened > 0) {
@@ -1006,9 +1010,9 @@ static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
return snd_ymfpci_playback_close_1(substream);
}
-static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_spdif_close(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
chip->spdif_opened = 0;
@@ -1023,9 +1027,9 @@ static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
return snd_ymfpci_playback_close_1(substream);
}
-static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream)
+static int snd_ymfpci_playback_4ch_close(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
spin_lock_irq(&chip->reg_lock);
if (chip->rear_opened > 0) {
@@ -1036,11 +1040,11 @@ static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream)
return snd_ymfpci_playback_close_1(substream);
}
-static int snd_ymfpci_capture_close(snd_pcm_substream_t * substream)
+static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream)
{
- ymfpci_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- ymfpci_pcm_t *ypcm = runtime->private_data;
+ struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_ymfpci_pcm *ypcm = runtime->private_data;
if (ypcm != NULL) {
chip->capture_substream[ypcm->capture_bank_number] = NULL;
@@ -1049,7 +1053,7 @@ static int snd_ymfpci_capture_close(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_ops_t snd_ymfpci_playback_ops = {
+static struct snd_pcm_ops snd_ymfpci_playback_ops = {
.open = snd_ymfpci_playback_open,
.close = snd_ymfpci_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1060,7 +1064,7 @@ static snd_pcm_ops_t snd_ymfpci_playback_ops = {
.pointer = snd_ymfpci_playback_pointer,
};
-static snd_pcm_ops_t snd_ymfpci_capture_rec_ops = {
+static struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
.open = snd_ymfpci_capture_rec_open,
.close = snd_ymfpci_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1071,16 +1075,9 @@ static snd_pcm_ops_t snd_ymfpci_capture_rec_ops = {
.pointer = snd_ymfpci_capture_pointer,
};
-static void snd_ymfpci_pcm_free(snd_pcm_t *pcm)
+int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
{
- ymfpci_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1088,7 +1085,6 @@ int __devinit snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_ymfpci_pcm_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_rec_ops);
@@ -1106,7 +1102,7 @@ int __devinit snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
return 0;
}
-static snd_pcm_ops_t snd_ymfpci_capture_ac97_ops = {
+static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
.open = snd_ymfpci_capture_ac97_open,
.close = snd_ymfpci_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1117,16 +1113,9 @@ static snd_pcm_ops_t snd_ymfpci_capture_ac97_ops = {
.pointer = snd_ymfpci_capture_pointer,
};
-static void snd_ymfpci_pcm2_free(snd_pcm_t *pcm)
-{
- ymfpci_t *chip = pcm->private_data;
- chip->pcm2 = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1134,7 +1123,6 @@ int __devinit snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_ymfpci_pcm2_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ymfpci_capture_ac97_ops);
@@ -1152,7 +1140,7 @@ int __devinit snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
return 0;
}
-static snd_pcm_ops_t snd_ymfpci_playback_spdif_ops = {
+static struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
.open = snd_ymfpci_playback_spdif_open,
.close = snd_ymfpci_playback_spdif_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1163,16 +1151,9 @@ static snd_pcm_ops_t snd_ymfpci_playback_spdif_ops = {
.pointer = snd_ymfpci_playback_pointer,
};
-static void snd_ymfpci_pcm_spdif_free(snd_pcm_t *pcm)
+int __devinit snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
{
- ymfpci_t *chip = pcm->private_data;
- chip->pcm_spdif = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1180,7 +1161,6 @@ int __devinit snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t ** rpcm
if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_ymfpci_pcm_spdif_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_spdif_ops);
@@ -1197,7 +1177,7 @@ int __devinit snd_ymfpci_pcm_spdif(ymfpci_t *chip, int device, snd_pcm_t ** rpcm
return 0;
}
-static snd_pcm_ops_t snd_ymfpci_playback_4ch_ops = {
+static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = {
.open = snd_ymfpci_playback_4ch_open,
.close = snd_ymfpci_playback_4ch_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1208,16 +1188,9 @@ static snd_pcm_ops_t snd_ymfpci_playback_4ch_ops = {
.pointer = snd_ymfpci_playback_pointer,
};
-static void snd_ymfpci_pcm_4ch_free(snd_pcm_t *pcm)
-{
- ymfpci_t *chip = pcm->private_data;
- chip->pcm_4ch = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __devinit snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
+int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if (rpcm)
@@ -1225,7 +1198,6 @@ int __devinit snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0)
return err;
pcm->private_data = chip;
- pcm->private_free = snd_ymfpci_pcm_4ch_free;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ymfpci_playback_4ch_ops);
@@ -1242,17 +1214,17 @@ int __devinit snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t ** rpcm)
return 0;
}
-static int snd_ymfpci_spdif_default_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ymfpci_spdif_default_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ymfpci_spdif_default_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_spdif_default_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&chip->reg_lock);
ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff;
@@ -1261,10 +1233,10 @@ static int snd_ymfpci_spdif_default_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ymfpci_spdif_default_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_spdif_default_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1279,7 +1251,7 @@ static int snd_ymfpci_spdif_default_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ymfpci_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_default __devinitdata =
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1288,17 +1260,17 @@ static snd_kcontrol_new_t snd_ymfpci_spdif_default __devinitdata =
.put = snd_ymfpci_spdif_default_put
};
-static int snd_ymfpci_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ymfpci_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ymfpci_spdif_mask_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_spdif_mask_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&chip->reg_lock);
ucontrol->value.iec958.status[0] = 0x3e;
@@ -1307,7 +1279,7 @@ static int snd_ymfpci_spdif_mask_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_ymfpci_spdif_mask __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_mask __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1316,17 +1288,17 @@ static snd_kcontrol_new_t snd_ymfpci_spdif_mask __devinitdata =
.get = snd_ymfpci_spdif_mask_get,
};
-static int snd_ymfpci_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ymfpci_spdif_stream_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int snd_ymfpci_spdif_stream_get(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_spdif_stream_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
spin_lock_irq(&chip->reg_lock);
ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff;
@@ -1335,10 +1307,10 @@ static int snd_ymfpci_spdif_stream_get(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_ymfpci_spdif_stream_put(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_spdif_stream_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change;
@@ -1353,7 +1325,7 @@ static int snd_ymfpci_spdif_stream_put(snd_kcontrol_t * kcontrol,
return change;
}
-static snd_kcontrol_new_t snd_ymfpci_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ymfpci_spdif_stream __devinitdata =
{
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1363,7 +1335,7 @@ static snd_kcontrol_new_t snd_ymfpci_spdif_stream __devinitdata =
.put = snd_ymfpci_spdif_stream_put
};
-static int snd_ymfpci_drec_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info)
+static int snd_ymfpci_drec_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info)
{
static char *texts[3] = {"AC'97", "IEC958", "ZV Port"};
@@ -1376,9 +1348,9 @@ static int snd_ymfpci_drec_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_ymfpci_drec_source_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
u16 reg;
spin_lock_irq(&chip->reg_lock);
@@ -1391,9 +1363,9 @@ static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return 0;
}
-static int snd_ymfpci_drec_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
+static int snd_ymfpci_drec_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *value)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
u16 reg, old_reg;
spin_lock_irq(&chip->reg_lock);
@@ -1407,7 +1379,7 @@ static int snd_ymfpci_drec_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
return reg != old_reg;
}
-static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_drec_source __devinitdata = {
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Direct Recording Source",
@@ -1426,8 +1398,8 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {
.get = snd_ymfpci_get_single, .put = snd_ymfpci_put_single, \
.private_value = ((reg) | ((shift) << 16)) }
-static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ymfpci_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int reg = kcontrol->private_value & 0xffff;
@@ -1443,10 +1415,10 @@ static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ymfpci_get_single(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xffff;
unsigned int shift = (kcontrol->private_value >> 16) & 0xff;
unsigned int mask = 1;
@@ -1461,10 +1433,10 @@ static int snd_ymfpci_get_single(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ymfpci_put_single(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xffff;
unsigned int shift = (kcontrol->private_value >> 16) & 0xff;
unsigned int mask = 1;
@@ -1493,7 +1465,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t *kcontrol,
.get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \
.private_value = reg }
-static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ymfpci_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
unsigned int reg = kcontrol->private_value;
@@ -1506,9 +1478,9 @@ static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
unsigned int shift_left = 0, shift_right = 16, mask = 16383;
unsigned int val;
@@ -1523,9 +1495,9 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
unsigned int shift_left = 0, shift_right = 16, mask = 16383;
int change;
@@ -1549,7 +1521,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
/*
* 4ch duplication
*/
-static int snd_ymfpci_info_dup4ch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_ymfpci_info_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1558,16 +1530,16 @@ static int snd_ymfpci_info_dup4ch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ymfpci_get_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_get_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = chip->mode_dup4ch;
return 0;
}
-static int snd_ymfpci_put_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
int change;
change = (ucontrol->value.integer.value[0] != chip->mode_dup4ch);
if (change)
@@ -1576,7 +1548,7 @@ static int snd_ymfpci_put_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
}
-static snd_kcontrol_new_t snd_ymfpci_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL),
YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),
YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL),
@@ -1607,7 +1579,7 @@ YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4)
* GPIO
*/
-static int snd_ymfpci_get_gpio_out(ymfpci_t *chip, int pin)
+static int snd_ymfpci_get_gpio_out(struct snd_ymfpci *chip, int pin)
{
u16 reg, mode;
unsigned long flags;
@@ -1627,7 +1599,7 @@ static int snd_ymfpci_get_gpio_out(ymfpci_t *chip, int pin)
return (mode >> pin) & 1;
}
-static int snd_ymfpci_set_gpio_out(ymfpci_t *chip, int pin, int enable)
+static int snd_ymfpci_set_gpio_out(struct snd_ymfpci *chip, int pin, int enable)
{
u16 reg;
unsigned long flags;
@@ -1644,7 +1616,7 @@ static int snd_ymfpci_set_gpio_out(ymfpci_t *chip, int pin, int enable)
return 0;
}
-static int snd_ymfpci_gpio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_ymfpci_gpio_sw_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1653,17 +1625,17 @@ static int snd_ymfpci_gpio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_ymfpci_gpio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_gpio_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
int pin = (int)kcontrol->private_value;
ucontrol->value.integer.value[0] = snd_ymfpci_get_gpio_out(chip, pin);
return 0;
}
-static int snd_ymfpci_gpio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_gpio_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
int pin = (int)kcontrol->private_value;
if (snd_ymfpci_get_gpio_out(chip, pin) != ucontrol->value.integer.value[0]) {
@@ -1674,7 +1646,7 @@ static int snd_ymfpci_gpio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_rear_shared __devinitdata = {
.name = "Shared Rear/Line-In Switch",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ymfpci_gpio_sw_info,
@@ -1687,8 +1659,8 @@ static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {
* PCM voice volume
*/
-static int snd_ymfpci_pcm_vol_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+static int snd_ymfpci_pcm_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -1697,10 +1669,10 @@ static int snd_ymfpci_pcm_vol_info(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ymfpci_pcm_vol_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_pcm_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int subs = kcontrol->id.subdevice;
ucontrol->value.integer.value[0] = chip->pcm_mixer[subs].left;
@@ -1708,12 +1680,12 @@ static int snd_ymfpci_pcm_vol_get(snd_kcontrol_t *kcontrol,
return 0;
}
-static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int subs = kcontrol->id.subdevice;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
unsigned long flags;
if (ucontrol->value.integer.value[0] != chip->pcm_mixer[subs].left ||
@@ -1721,10 +1693,10 @@ static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,
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;
+ substream = (struct snd_pcm_substream *)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;
+ struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
ypcm->update_pcm_vol = 2;
}
spin_unlock_irqrestore(&chip->voice_lock, flags);
@@ -1733,7 +1705,7 @@ static int snd_ymfpci_pcm_vol_put(snd_kcontrol_t *kcontrol,
return 0;
}
-static snd_kcontrol_new_t snd_ymfpci_pcm_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ymfpci_pcm_volume __devinitdata = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = "PCM Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -1748,26 +1720,26 @@ static snd_kcontrol_new_t snd_ymfpci_pcm_volume __devinitdata = {
* Mixer routines
*/
-static void snd_ymfpci_mixer_free_ac97_bus(ac97_bus_t *bus)
+static void snd_ymfpci_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{
- ymfpci_t *chip = bus->private_data;
+ struct snd_ymfpci *chip = bus->private_data;
chip->ac97_bus = NULL;
}
-static void snd_ymfpci_mixer_free_ac97(ac97_t *ac97)
+static void snd_ymfpci_mixer_free_ac97(struct snd_ac97 *ac97)
{
- ymfpci_t *chip = ac97->private_data;
+ struct snd_ymfpci *chip = ac97->private_data;
chip->ac97 = NULL;
}
-int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
+int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
{
- ac97_template_t ac97;
- snd_kcontrol_t *kctl;
- snd_pcm_substream_t *substream;
+ struct snd_ac97_template ac97;
+ struct snd_kcontrol *kctl;
+ struct snd_pcm_substream *substream;
unsigned int idx;
int err;
- static ac97_bus_ops_t ops = {
+ static struct snd_ac97_bus_ops ops = {
.write = snd_ymfpci_codec_write,
.read = snd_ymfpci_codec_read,
};
@@ -1843,9 +1815,9 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
* timer
*/
-static int snd_ymfpci_timer_start(snd_timer_t *timer)
+static int snd_ymfpci_timer_start(struct snd_timer *timer)
{
- ymfpci_t *chip;
+ struct snd_ymfpci *chip;
unsigned long flags;
unsigned int count;
@@ -1858,9 +1830,9 @@ static int snd_ymfpci_timer_start(snd_timer_t *timer)
return 0;
}
-static int snd_ymfpci_timer_stop(snd_timer_t *timer)
+static int snd_ymfpci_timer_stop(struct snd_timer *timer)
{
- ymfpci_t *chip;
+ struct snd_ymfpci *chip;
unsigned long flags;
chip = snd_timer_chip(timer);
@@ -1870,7 +1842,7 @@ static int snd_ymfpci_timer_stop(snd_timer_t *timer)
return 0;
}
-static int snd_ymfpci_timer_precise_resolution(snd_timer_t *timer,
+static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer,
unsigned long *num, unsigned long *den)
{
*num = 1;
@@ -1878,7 +1850,7 @@ static int snd_ymfpci_timer_precise_resolution(snd_timer_t *timer,
return 0;
}
-static struct _snd_timer_hardware snd_ymfpci_timer_hw = {
+static struct snd_timer_hardware snd_ymfpci_timer_hw = {
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 20833, /* 1/fs = 20.8333...us */
.ticks = 0x8000,
@@ -1887,10 +1859,10 @@ static struct _snd_timer_hardware snd_ymfpci_timer_hw = {
.precise_resolution = snd_ymfpci_timer_precise_resolution,
};
-int __devinit snd_ymfpci_timer(ymfpci_t *chip, int device)
+int __devinit snd_ymfpci_timer(struct snd_ymfpci *chip, int device)
{
- snd_timer_t *timer = NULL;
- snd_timer_id_t tid;
+ struct snd_timer *timer = NULL;
+ struct snd_timer_id tid;
int err;
tid.dev_class = SNDRV_TIMER_CLASS_CARD;
@@ -1912,10 +1884,10 @@ int __devinit snd_ymfpci_timer(ymfpci_t *chip, int device)
* proc interface
*/
-static void snd_ymfpci_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t * buffer)
+static void snd_ymfpci_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
- ymfpci_t *chip = entry->private_data;
+ struct snd_ymfpci *chip = entry->private_data;
int i;
snd_iprintf(buffer, "YMFPCI\n\n");
@@ -1923,9 +1895,9 @@ static void snd_ymfpci_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "%04x: %04x\n", i, snd_ymfpci_readl(chip, i));
}
-static int __devinit snd_ymfpci_proc_init(snd_card_t * card, ymfpci_t *chip)
+static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfpci *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(card, "ymfpci", &entry))
snd_info_set_text_ops(entry, chip, 1024, snd_ymfpci_proc_read);
@@ -1954,12 +1926,12 @@ static void snd_ymfpci_aclink_reset(struct pci_dev * pci)
#endif
}
-static void snd_ymfpci_enable_dsp(ymfpci_t *chip)
+static void snd_ymfpci_enable_dsp(struct snd_ymfpci *chip)
{
snd_ymfpci_writel(chip, YDSXGR_CONFIG, 0x00000001);
}
-static void snd_ymfpci_disable_dsp(ymfpci_t *chip)
+static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip)
{
u32 val;
int timeout = 1000;
@@ -1976,7 +1948,7 @@ static void snd_ymfpci_disable_dsp(ymfpci_t *chip)
#include "ymfpci_image.h"
-static void snd_ymfpci_download_image(ymfpci_t *chip)
+static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
{
int i;
u16 ctrl;
@@ -2016,7 +1988,7 @@ static void snd_ymfpci_download_image(ymfpci_t *chip)
snd_ymfpci_enable_dsp(chip);
}
-static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
+static int __devinit snd_ymfpci_memalloc(struct snd_ymfpci *chip)
{
long size, playback_ctrl_size;
int voice, bank, reg;
@@ -2051,10 +2023,10 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
ptr_addr += (playback_ctrl_size + 0x00ff) & ~0x00ff;
for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) {
chip->voices[voice].number = voice;
- chip->voices[voice].bank = (snd_ymfpci_playback_bank_t *)ptr;
+ chip->voices[voice].bank = (struct snd_ymfpci_playback_bank *)ptr;
chip->voices[voice].bank_addr = ptr_addr;
for (bank = 0; bank < 2; bank++) {
- chip->bank_playback[voice][bank] = (snd_ymfpci_playback_bank_t *)ptr;
+ chip->bank_playback[voice][bank] = (struct snd_ymfpci_playback_bank *)ptr;
ptr += chip->bank_size_playback;
ptr_addr += chip->bank_size_playback;
}
@@ -2065,7 +2037,7 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
chip->bank_base_capture_addr = ptr_addr;
for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++)
for (bank = 0; bank < 2; bank++) {
- chip->bank_capture[voice][bank] = (snd_ymfpci_capture_bank_t *)ptr;
+ chip->bank_capture[voice][bank] = (struct snd_ymfpci_capture_bank *)ptr;
ptr += chip->bank_size_capture;
ptr_addr += chip->bank_size_capture;
}
@@ -2075,7 +2047,7 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
chip->bank_base_effect_addr = ptr_addr;
for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++)
for (bank = 0; bank < 2; bank++) {
- chip->bank_effect[voice][bank] = (snd_ymfpci_effect_bank_t *)ptr;
+ chip->bank_effect[voice][bank] = (struct snd_ymfpci_effect_bank *)ptr;
ptr += chip->bank_size_effect;
ptr_addr += chip->bank_size_effect;
}
@@ -2114,7 +2086,7 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
return 0;
}
-static int snd_ymfpci_free(ymfpci_t *chip)
+static int snd_ymfpci_free(struct snd_ymfpci *chip)
{
u16 ctrl;
@@ -2167,9 +2139,9 @@ static int snd_ymfpci_free(ymfpci_t *chip)
return 0;
}
-static int snd_ymfpci_dev_free(snd_device_t *device)
+static int snd_ymfpci_dev_free(struct snd_device *device)
{
- ymfpci_t *chip = device->device_data;
+ struct snd_ymfpci *chip = device->device_data;
return snd_ymfpci_free(chip);
}
@@ -2203,11 +2175,13 @@ static int saved_regs_index[] = {
};
#define YDSXGR_NUM_SAVED_REGS ARRAY_SIZE(saved_regs_index)
-static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state)
+int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
{
- ymfpci_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ymfpci *chip = card->private_data;
unsigned int i;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
snd_pcm_suspend_all(chip->pcm2);
snd_pcm_suspend_all(chip->pcm_spdif);
@@ -2218,18 +2192,21 @@ static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state)
chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
snd_ymfpci_disable_dsp(chip);
- pci_disable_device(chip->pci);
+ pci_disable_device(pci);
+ pci_save_state(pci);
return 0;
}
-static int snd_ymfpci_resume(snd_card_t *card)
+int snd_ymfpci_resume(struct pci_dev *pci)
{
- ymfpci_t *chip = card->pm_private_data;
+ struct snd_card *card = pci_get_drvdata(pci);
+ struct snd_ymfpci *chip = card->private_data;
unsigned int i;
- pci_enable_device(chip->pci);
- pci_set_master(chip->pci);
- snd_ymfpci_aclink_reset(chip->pci);
+ pci_restore_state(pci);
+ pci_enable_device(pci);
+ pci_set_master(pci);
+ snd_ymfpci_aclink_reset(pci);
snd_ymfpci_codec_ready(chip, 0);
snd_ymfpci_download_image(chip);
udelay(100);
@@ -2246,18 +2223,19 @@ static int snd_ymfpci_resume(snd_card_t *card)
chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT);
spin_unlock_irq(&chip->reg_lock);
}
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif /* CONFIG_PM */
-int __devinit snd_ymfpci_create(snd_card_t * card,
+int __devinit snd_ymfpci_create(struct snd_card *card,
struct pci_dev * pci,
unsigned short old_legacy_ctrl,
- ymfpci_t ** rchip)
+ struct snd_ymfpci ** rchip)
{
- ymfpci_t *chip;
+ struct snd_ymfpci *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_ymfpci_dev_free,
};
@@ -2324,7 +2302,6 @@ int __devinit snd_ymfpci_create(snd_card_t * card,
snd_ymfpci_free(chip);
return -ENOMEM;
}
- snd_card_set_pm_callback(card, snd_ymfpci_suspend, snd_ymfpci_resume, chip);
#endif
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index d6918b453f28..77caf43a3109 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -52,16 +52,13 @@ MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
/*
*/
-static dev_info_t dev_info = "snd-pdaudiocf";
-static snd_card_t *card_list[SNDRV_CARDS];
-static dev_link_t *dev_list;
+static struct snd_card *card_list[SNDRV_CARDS];
/*
* prototypes
*/
static void pdacf_config(dev_link_t *link);
-static int pdacf_event(event_t event, int priority, event_callback_args_t *args);
-static void snd_pdacf_detach(dev_link_t *link);
+static void snd_pdacf_detach(struct pcmcia_device *p_dev);
static void pdacf_release(dev_link_t *link)
{
@@ -77,16 +74,12 @@ static void pdacf_release(dev_link_t *link)
/*
* destructor
*/
-static int snd_pdacf_free(pdacf_t *pdacf)
+static int snd_pdacf_free(struct snd_pdacf *pdacf)
{
dev_link_t *link = &pdacf->link;
pdacf_release(link);
- /* Break the link with Card Services */
- if (link->handle)
- pcmcia_deregister_client(link->handle);
-
card_list[pdacf->index] = NULL;
pdacf->card = NULL;
@@ -94,23 +87,22 @@ static int snd_pdacf_free(pdacf_t *pdacf)
return 0;
}
-static int snd_pdacf_dev_free(snd_device_t *device)
+static int snd_pdacf_dev_free(struct snd_device *device)
{
- pdacf_t *chip = device->device_data;
+ struct snd_pdacf *chip = device->device_data;
return snd_pdacf_free(chip);
}
/*
* snd_pdacf_attach - attach callback for cs
*/
-static dev_link_t *snd_pdacf_attach(void)
+static int snd_pdacf_attach(struct pcmcia_device *p_dev)
{
- client_reg_t client_reg; /* Register with cardmgr */
- dev_link_t *link; /* Info for cardmgr */
- int i, ret;
- pdacf_t *pdacf;
- snd_card_t *card;
- static snd_device_ops_t ops = {
+ int i;
+ dev_link_t *link; /* Info for cardmgr */
+ struct snd_pdacf *pdacf;
+ struct snd_card *card;
+ static struct snd_device_ops ops = {
.dev_free = snd_pdacf_dev_free,
};
@@ -122,26 +114,26 @@ static dev_link_t *snd_pdacf_attach(void)
}
if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "pdacf: too many cards found\n");
- return NULL;
+ return -EINVAL;
}
if (! enable[i])
- return NULL; /* disabled explicitly */
+ return -ENODEV; /* disabled explicitly */
/* ok, create a card instance */
card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (card == NULL) {
snd_printk(KERN_ERR "pdacf: cannot create a card instance\n");
- return NULL;
+ return -ENOMEM;
}
pdacf = snd_pdacf_create(card);
if (! pdacf)
- return NULL;
+ return -EIO;
if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) {
kfree(pdacf);
snd_card_free(card);
- return NULL;
+ return -ENODEV;
}
pdacf->index = i;
@@ -165,22 +157,12 @@ static dev_link_t *snd_pdacf_attach(void)
link->conf.Present = PRESENT_OPTION;
/* Chain drivers */
- link->next = dev_list;
- dev_list = link;
-
- /* Register with Card Services */
- 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);
- snd_pdacf_detach(link);
- return NULL;
- }
+ link->next = NULL;
- return link;
+ link->handle = p_dev;
+ pdacf_config(link);
+
+ return 0;
}
@@ -194,10 +176,10 @@ static dev_link_t *snd_pdacf_attach(void)
*
* returns 0 if successful, or a negative error code.
*/
-static int snd_pdacf_assign_resources(pdacf_t *pdacf, int port, int irq)
+static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq)
{
int err;
- snd_card_t *card = pdacf->card;
+ struct snd_card *card = pdacf->card;
snd_printdd(KERN_DEBUG "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq);
pdacf->port = port;
@@ -217,8 +199,6 @@ static int snd_pdacf_assign_resources(pdacf_t *pdacf, int port, int irq)
if (err < 0)
return err;
- snd_card_set_pm_callback(card, snd_pdacf_suspend, snd_pdacf_resume, pdacf);
-
if ((err = snd_card_register(card)) < 0)
return err;
@@ -229,21 +209,13 @@ static int snd_pdacf_assign_resources(pdacf_t *pdacf, int port, int irq)
/*
* snd_pdacf_detach - detach callback for cs
*/
-static void snd_pdacf_detach(dev_link_t *link)
+static void snd_pdacf_detach(struct pcmcia_device *p_dev)
{
- pdacf_t *chip = link->priv;
+ dev_link_t *link = dev_to_instance(p_dev);
+ struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "pdacf_detach called\n");
- /* Remove the interface data from the linked list */
- {
- dev_link_t **linkp;
- /* Locate device structure */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link)
- break;
- if (*linkp)
- *linkp = link->next;
- }
+
if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED)
snd_pdacf_powerdown(chip);
chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */
@@ -261,7 +233,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static void pdacf_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
- pdacf_t *pdacf = link->priv;
+ struct snd_pdacf *pdacf = link->priv;
tuple_t tuple;
cisparse_t *parse = NULL;
config_info_t conf;
@@ -312,62 +284,51 @@ failed:
pcmcia_release_irq(link->handle, &link->irq);
}
-/*
- * event callback
- */
-static int pdacf_event(event_t event, int priority, event_callback_args_t *args)
-{
- dev_link_t *link = args->client_data;
- pdacf_t *chip = link->priv;
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n");
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG) {
- chip->chip_status |= PDAUDIOCF_STAT_IS_STALE;
- }
- break;
- case CS_EVENT_CARD_INSERTION:
- snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
- link->state |= DEV_PRESENT;
- pdacf_config(link);
- break;
#ifdef CONFIG_PM
- case CS_EVENT_PM_SUSPEND:
- snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
+
+static int pdacf_suspend(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ struct snd_pdacf *chip = link->priv;
+
+ snd_printdd(KERN_DEBUG "SUSPEND\n");
+ link->state |= DEV_SUSPEND;
+ if (chip) {
+ snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
+ snd_pdacf_suspend(chip, PMSG_SUSPEND);
+ }
+
+ snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int pdacf_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ struct snd_pdacf *chip = link->priv;
+
+ snd_printdd(KERN_DEBUG "RESUME\n");
+ link->state &= ~DEV_SUSPEND;
+
+ snd_printdd(KERN_DEBUG "CARD_RESET\n");
+ if (DEV_OK(link)) {
+ snd_printdd(KERN_DEBUG "requestconfig...\n");
+ pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
- snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
- snd_pdacf_suspend(chip->card, PMSG_SUSPEND);
- }
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
- if (chip) {
- snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
- snd_pdacf_resume(chip->card);
- }
+ snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
+ snd_pdacf_resume(chip);
}
- snd_printdd(KERN_DEBUG "resume done!\n");
- break;
-#endif
}
+ snd_printdd(KERN_DEBUG "resume done!\n");
+
return 0;
}
+#endif
+
/*
* Module entry points
*/
@@ -382,10 +343,14 @@ static struct pcmcia_driver pdacf_cs_driver = {
.drv = {
.name = "snd-pdaudiocf",
},
- .attach = snd_pdacf_attach,
- .event = pdacf_event,
- .detach = snd_pdacf_detach,
+ .probe = snd_pdacf_attach,
+ .remove = snd_pdacf_detach,
.id_table = snd_pdacf_ids,
+#ifdef CONFIG_PM
+ .suspend = pdacf_suspend,
+ .resume = pdacf_resume,
+#endif
+
};
static int __init init_pdacf(void)
@@ -396,7 +361,6 @@ static int __init init_pdacf(void)
static void __exit exit_pdacf(void)
{
pcmcia_unregister_driver(&pdacf_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_pdacf);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index c7a9628256ee..2744f189a613 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -83,8 +83,8 @@
#define PDAUDIOCF_STAT_IS_CONFIGURED (1<<1)
#define PDAUDIOCF_STAT_IS_SUSPENDED (1<<2)
-typedef struct {
- snd_card_t *card;
+struct snd_pdacf {
+ struct snd_card *card;
int index;
unsigned long port;
@@ -96,12 +96,12 @@ typedef struct {
struct tasklet_struct tq;
spinlock_t ak4117_lock;
- ak4117_t *ak4117;
+ struct ak4117 *ak4117;
unsigned int chip_status;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *pcm_substream;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *pcm_substream;
unsigned int pcm_running: 1;
unsigned int pcm_channels;
unsigned int pcm_swab;
@@ -118,28 +118,28 @@ typedef struct {
/* pcmcia stuff */
dev_link_t link;
dev_node_t node;
-} pdacf_t;
+};
-static inline void pdacf_reg_write(pdacf_t *chip, unsigned char reg, unsigned short val)
+static inline void pdacf_reg_write(struct snd_pdacf *chip, unsigned char reg, unsigned short val)
{
outw(chip->regmap[reg>>1] = val, chip->port + reg);
}
-static inline unsigned short pdacf_reg_read(pdacf_t *chip, unsigned char reg)
+static inline unsigned short pdacf_reg_read(struct snd_pdacf *chip, unsigned char reg)
{
return inw(chip->port + reg);
}
-pdacf_t *snd_pdacf_create(snd_card_t *card);
-int snd_pdacf_ak4117_create(pdacf_t *pdacf);
-void snd_pdacf_powerdown(pdacf_t *chip);
+struct snd_pdacf *snd_pdacf_create(struct snd_card *card);
+int snd_pdacf_ak4117_create(struct snd_pdacf *pdacf);
+void snd_pdacf_powerdown(struct snd_pdacf *chip);
#ifdef CONFIG_PM
-int snd_pdacf_suspend(snd_card_t *card, pm_message_t state);
-int snd_pdacf_resume(snd_card_t *card);
+int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state);
+int snd_pdacf_resume(struct snd_pdacf *chip);
#endif
-int snd_pdacf_pcm_new(pdacf_t *chip);
+int snd_pdacf_pcm_new(struct snd_pdacf *chip);
irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs);
void pdacf_tasklet(unsigned long private_data);
-void pdacf_reinit(pdacf_t *chip, int resume);
+void pdacf_reinit(struct snd_pdacf *chip, int resume);
#endif /* __PDAUDIOCF_H */
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index 0208c54896b3..bd0d70ff3019 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -30,7 +30,7 @@
*/
static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
{
- pdacf_t *chip = private_data;
+ struct snd_pdacf *chip = private_data;
unsigned long timeout;
unsigned long flags;
unsigned char res;
@@ -62,7 +62,7 @@ static unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val)
{
- pdacf_t *chip = private_data;
+ struct snd_pdacf *chip = private_data;
unsigned long timeout;
unsigned long flags;
@@ -81,7 +81,7 @@ static void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned c
}
#if 0
-void pdacf_dump(pdacf_t *chip)
+void pdacf_dump(struct snd_pdacf *chip)
{
printk("PDAUDIOCF DUMP (0x%lx):\n", chip->port);
printk("WPD : 0x%x\n", inw(chip->port + PDAUDIOCF_REG_WDP));
@@ -94,7 +94,7 @@ void pdacf_dump(pdacf_t *chip)
}
#endif
-static int pdacf_reset(pdacf_t *chip, int powerdown)
+static int pdacf_reset(struct snd_pdacf *chip, int powerdown)
{
u16 val;
@@ -117,7 +117,7 @@ static int pdacf_reset(pdacf_t *chip, int powerdown)
return 0;
}
-void pdacf_reinit(pdacf_t *chip, int resume)
+void pdacf_reinit(struct snd_pdacf *chip, int resume)
{
pdacf_reset(chip, 0);
if (resume)
@@ -127,10 +127,10 @@ void pdacf_reinit(pdacf_t *chip, int resume)
pdacf_reg_write(chip, PDAUDIOCF_REG_IER, chip->regmap[PDAUDIOCF_REG_IER>>1]);
}
-static void pdacf_proc_read(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
+static void pdacf_proc_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
{
- pdacf_t *chip = entry->private_data;
+ struct snd_pdacf *chip = entry->private_data;
u16 tmp;
snd_iprintf(buffer, "PDAudioCF\n\n");
@@ -139,17 +139,17 @@ static void pdacf_proc_read(snd_info_entry_t * entry,
}
-static void pdacf_proc_init(pdacf_t *chip)
+static void pdacf_proc_init(struct snd_pdacf *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry))
snd_info_set_text_ops(entry, chip, 1024, pdacf_proc_read);
}
-pdacf_t *snd_pdacf_create(snd_card_t *card)
+struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
{
- pdacf_t *chip;
+ struct snd_pdacf *chip;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -164,9 +164,9 @@ pdacf_t *snd_pdacf_create(snd_card_t *card)
return chip;
}
-static void snd_pdacf_ak4117_change(ak4117_t *ak4117, unsigned char c0, unsigned char c1)
+static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
{
- pdacf_t *chip = ak4117->change_callback_private;
+ struct snd_pdacf *chip = ak4117->change_callback_private;
unsigned long flags;
u16 val;
@@ -182,7 +182,7 @@ static void snd_pdacf_ak4117_change(ak4117_t *ak4117, unsigned char c0, unsigned
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
-int snd_pdacf_ak4117_create(pdacf_t *chip)
+int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
{
int err;
u16 val;
@@ -238,7 +238,7 @@ int snd_pdacf_ak4117_create(pdacf_t *chip)
return 0;
}
-void snd_pdacf_powerdown(pdacf_t *chip)
+void snd_pdacf_powerdown(struct snd_pdacf *chip)
{
u16 val;
@@ -255,11 +255,11 @@ void snd_pdacf_powerdown(pdacf_t *chip)
#ifdef CONFIG_PM
-int snd_pdacf_suspend(snd_card_t *card, pm_message_t state)
+int snd_pdacf_suspend(struct snd_pdacf *chip, pm_message_t state)
{
- pdacf_t *chip = card->pm_private_data;
u16 val;
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
snd_pcm_suspend_all(chip->pcm);
/* disable interrupts, but use direct write to preserve old register value in chip->regmap */
val = inw(chip->port + PDAUDIOCF_REG_IER);
@@ -270,14 +270,13 @@ int snd_pdacf_suspend(snd_card_t *card, pm_message_t state)
return 0;
}
-static inline int check_signal(pdacf_t *chip)
+static inline int check_signal(struct snd_pdacf *chip)
{
return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0;
}
-int snd_pdacf_resume(snd_card_t *card)
+int snd_pdacf_resume(struct snd_pdacf *chip)
{
- pdacf_t *chip = card->pm_private_data;
int timeout = 40;
pdacf_reinit(chip, 1);
@@ -286,6 +285,7 @@ int snd_pdacf_resume(snd_card_t *card)
(snd_ak4117_external_rate(chip->ak4117) <= 0 || !check_signal(chip)))
mdelay(1);
chip->chip_status &= ~PDAUDIOCF_STAT_IS_SUSPENDED;
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
return 0;
}
#endif
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index 255b63444b5d..7c5f21e45cb4 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -28,7 +28,7 @@
*/
irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs)
{
- pdacf_t *chip = dev;
+ struct snd_pdacf *chip = dev;
unsigned short stat;
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
@@ -204,7 +204,7 @@ static inline void pdacf_transfer_stereo24be(u8 *dst, u32 xor, unsigned int size
}
}
-static void pdacf_transfer(pdacf_t *chip, unsigned int size, unsigned int off)
+static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned int off)
{
unsigned long rdp_port = chip->port + PDAUDIOCF_REG_MD;
unsigned int xor = chip->pcm_xor;
@@ -258,7 +258,7 @@ static void pdacf_transfer(pdacf_t *chip, unsigned int size, unsigned int off)
void pdacf_tasklet(unsigned long private_data)
{
- pdacf_t *chip = (pdacf_t *) private_data;
+ struct snd_pdacf *chip = (struct snd_pdacf *) private_data;
int size, off, cont, rdp, wdp;
if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 20b86d8df7a3..962e6d525564 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -34,7 +34,7 @@
*/
/* get the physical page pointer on the given offset */
-static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned long offset)
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, unsigned long offset)
{
void *pageptr = subs->runtime->dma_area + offset;
return vmalloc_to_page(pageptr);
@@ -44,9 +44,9 @@ static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned
* hw_params callback
* NOTE: this may be called not only once per pcm open!
*/
-static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
if (runtime->dma_bytes >= size)
return 0; /* already enough large */
@@ -63,9 +63,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
* hw_free callback
* NOTE: this may be called not only once per pcm open!
*/
-static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
+static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
vfree(runtime->dma_area);
runtime->dma_area = NULL;
@@ -76,7 +76,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
/*
* clear the SRAM contents
*/
-static int pdacf_pcm_clear_sram(pdacf_t *chip)
+static int pdacf_pcm_clear_sram(struct snd_pdacf *chip)
{
int max_loop = 64 * 1024;
@@ -91,10 +91,10 @@ static int pdacf_pcm_clear_sram(pdacf_t *chip)
/*
* pdacf_pcm_trigger - trigger callback for capture
*/
-static int pdacf_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
+static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
{
- pdacf_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
int inc, ret = 0, rate;
unsigned short mask, val, tmp;
@@ -146,8 +146,8 @@ static int pdacf_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
/*
* pdacf_pcm_hw_params - hw_params callback for playback and capture
*/
-static int pdacf_pcm_hw_params(snd_pcm_substream_t *subs,
- snd_pcm_hw_params_t *hw_params)
+static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params));
}
@@ -155,7 +155,7 @@ static int pdacf_pcm_hw_params(snd_pcm_substream_t *subs,
/*
* pdacf_pcm_hw_free - hw_free callback for playback and capture
*/
-static int pdacf_pcm_hw_free(snd_pcm_substream_t *subs)
+static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs)
{
return snd_pcm_free_vmalloc_buffer(subs);
}
@@ -163,10 +163,10 @@ static int pdacf_pcm_hw_free(snd_pcm_substream_t *subs)
/*
* pdacf_pcm_prepare - prepare callback for playback and capture
*/
-static int pdacf_pcm_prepare(snd_pcm_substream_t *subs)
+static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
{
- pdacf_t *chip = snd_pcm_substream_chip(subs);
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
u16 val, nval, aval;
if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
@@ -209,7 +209,7 @@ static int pdacf_pcm_prepare(snd_pcm_substream_t *subs)
case SNDRV_PCM_FORMAT_S24_3LE:
case SNDRV_PCM_FORMAT_S24_3BE:
chip->pcm_sample = 3;
- /* fall trough */
+ /* fall through */
default: /* 24-bit */
aval = AK4117_DIF_24R;
chip->pcm_frame = 3;
@@ -239,7 +239,7 @@ static int pdacf_pcm_prepare(snd_pcm_substream_t *subs)
* capture hw information
*/
-static snd_pcm_hardware_t pdacf_pcm_capture_hw = {
+static struct snd_pcm_hardware pdacf_pcm_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_MMAP_VALID),
@@ -269,10 +269,10 @@ static snd_pcm_hardware_t pdacf_pcm_capture_hw = {
/*
* pdacf_pcm_capture_open - open callback for capture
*/
-static int pdacf_pcm_capture_open(snd_pcm_substream_t *subs)
+static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
- pdacf_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pcm_runtime *runtime = subs->runtime;
+ struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
return -EBUSY;
@@ -287,9 +287,9 @@ static int pdacf_pcm_capture_open(snd_pcm_substream_t *subs)
/*
* pdacf_pcm_capture_close - close callback for capture
*/
-static int pdacf_pcm_capture_close(snd_pcm_substream_t *subs)
+static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs)
{
- pdacf_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
if (!chip)
return -EINVAL;
@@ -302,16 +302,16 @@ static int pdacf_pcm_capture_close(snd_pcm_substream_t *subs)
/*
* pdacf_pcm_capture_pointer - pointer callback for capture
*/
-static snd_pcm_uframes_t pdacf_pcm_capture_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs)
{
- pdacf_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
return chip->pcm_hwptr;
}
/*
* operators for PCM capture
*/
-static snd_pcm_ops_t pdacf_pcm_capture_ops = {
+static struct snd_pcm_ops pdacf_pcm_capture_ops = {
.open = pdacf_pcm_capture_open,
.close = pdacf_pcm_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -325,20 +325,11 @@ static snd_pcm_ops_t pdacf_pcm_capture_ops = {
/*
- * free callback for pcm
- */
-static void snd_pdacf_pcm_free(snd_pcm_t *pcm)
-{
- pdacf_t *chip = pcm->private_data;
- chip->pcm = NULL;
-}
-
-/*
* snd_pdacf_pcm_new - create and initialize a pcm
*/
-int snd_pdacf_pcm_new(pdacf_t *chip)
+int snd_pdacf_pcm_new(struct snd_pdacf *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm);
@@ -348,7 +339,6 @@ int snd_pdacf_pcm_new(pdacf_t *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops);
pcm->private_data = chip;
- pcm->private_free = snd_pdacf_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index aeaef3d81801..9450149b931c 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -31,7 +31,7 @@
/*
* mic level control (for VXPocket)
*/
-static int vx_mic_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -40,17 +40,17 @@ static int vx_mic_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int vx_mic_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
-static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
down(&_chip->mixer_mutex);
if (chip->mic_level != ucontrol->value.integer.value[0]) {
@@ -63,7 +63,7 @@ static int vx_mic_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static snd_kcontrol_new_t vx_control_mic_level = {
+static struct snd_kcontrol_new vx_control_mic_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Capture Volume",
.info = vx_mic_level_info,
@@ -74,7 +74,7 @@ static snd_kcontrol_new_t vx_control_mic_level = {
/*
* mic boost level control (for VXP440)
*/
-static int vx_mic_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int vx_mic_boost_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -83,17 +83,17 @@ static int vx_mic_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int vx_mic_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
-static int vx_mic_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- vx_core_t *_chip = snd_kcontrol_chip(kcontrol);
+ struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
down(&_chip->mixer_mutex);
if (chip->mic_level != ucontrol->value.integer.value[0]) {
@@ -106,7 +106,7 @@ static int vx_mic_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
return 0;
}
-static snd_kcontrol_new_t vx_control_mic_boost = {
+static struct snd_kcontrol_new vx_control_mic_boost = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost",
.info = vx_mic_boost_info,
@@ -115,7 +115,7 @@ static snd_kcontrol_new_t vx_control_mic_boost = {
};
-int vxp_add_mic_controls(vx_core_t *_chip)
+int vxp_add_mic_controls(struct vx_core *_chip)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
int err;
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 6f15c3d03ab5..7f82f619f9f4 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -49,7 +49,7 @@ static int vxp_reg_offset[VX_REG_MAX] = {
};
-static inline unsigned long vxp_reg_addr(vx_core_t *_chip, int reg)
+static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
return chip->port + vxp_reg_offset[reg];
@@ -59,7 +59,7 @@ static inline unsigned long vxp_reg_addr(vx_core_t *_chip, int reg)
* snd_vx_inb - read a byte from the register
* @offset: register offset
*/
-static unsigned char vxp_inb(vx_core_t *chip, int offset)
+static unsigned char vxp_inb(struct vx_core *chip, int offset)
{
return inb(vxp_reg_addr(chip, offset));
}
@@ -69,7 +69,7 @@ static unsigned char vxp_inb(vx_core_t *chip, int offset)
* @offset: the register offset
* @val: the value to write
*/
-static void vxp_outb(vx_core_t *chip, int offset, unsigned char val)
+static void vxp_outb(struct vx_core *chip, int offset, unsigned char val)
{
outb(val, vxp_reg_addr(chip, offset));
}
@@ -78,9 +78,9 @@ static void vxp_outb(vx_core_t *chip, int offset, unsigned char val)
* redefine macros to call directly
*/
#undef vx_inb
-#define vx_inb(chip,reg) vxp_inb((vx_core_t*)(chip), VX_##reg)
+#define vx_inb(chip,reg) vxp_inb((struct vx_core *)(chip), VX_##reg)
#undef vx_outb
-#define vx_outb(chip,reg,val) vxp_outb((vx_core_t*)(chip), VX_##reg,val)
+#define vx_outb(chip,reg,val) vxp_outb((struct vx_core *)(chip), VX_##reg,val)
/*
@@ -88,7 +88,7 @@ static void vxp_outb(vx_core_t *chip, int offset, unsigned char val)
*
* returns zero if a magic word is detected, or a negative error code.
*/
-static int vx_check_magic(vx_core_t *chip)
+static int vx_check_magic(struct vx_core *chip)
{
unsigned long end_time = jiffies + HZ / 5;
int c;
@@ -96,7 +96,7 @@ static int vx_check_magic(vx_core_t *chip)
c = vx_inb(chip, CDSP);
if (c == CDSP_MAGIC)
return 0;
- snd_vx_delay(chip, 10);
+ msleep(10);
} while (time_after_eq(end_time, jiffies));
snd_printk(KERN_ERR "cannot find xilinx magic word (%x)\n", c);
return -EIO;
@@ -109,7 +109,7 @@ static int vx_check_magic(vx_core_t *chip)
#define XX_DSP_RESET_WAIT_TIME 2 /* ms */
-static void vxp_reset_dsp(vx_core_t *_chip)
+static void vxp_reset_dsp(struct vx_core *_chip)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -127,26 +127,26 @@ static void vxp_reset_dsp(vx_core_t *_chip)
/*
* reset codec bit
*/
-static void vxp_reset_codec(vx_core_t *_chip)
+static void vxp_reset_codec(struct vx_core *_chip)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
/* Set the reset CODEC bit to 1. */
vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK);
vx_inb(chip, CDSP);
- snd_vx_delay(_chip, 10);
+ msleep(10);
/* Set the reset CODEC bit to 0. */
chip->regCDSP &= ~VXP_CDSP_CODEC_RESET_MASK;
vx_outb(chip, CDSP, chip->regCDSP);
vx_inb(chip, CDSP);
- snd_vx_delay(_chip, 1);
+ msleep(1);
}
/*
* vx_load_xilinx_binary - load the xilinx binary image
* the binary image is the binary array converted from the bitstream file.
*/
-static int vxp_load_xilinx_binary(vx_core_t *_chip, const struct firmware *fw)
+static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
unsigned int i;
@@ -207,7 +207,7 @@ static int vxp_load_xilinx_binary(vx_core_t *_chip, const struct firmware *fw)
vx_outb(chip, ICR, ICR_HF0);
/* TEMPO 250ms : wait until Xilinx is downloaded */
- snd_vx_delay(_chip, 300);
+ msleep(300);
/* test magical word */
if (vx_check_magic(_chip) < 0)
@@ -221,7 +221,7 @@ static int vxp_load_xilinx_binary(vx_core_t *_chip, const struct firmware *fw)
chip->regDIALOG |= VXP_DLG_XILINX_REPROG_MASK;
vx_outb(chip, DIALOG, chip->regDIALOG);
vx_inb(chip, DIALOG);
- snd_vx_delay(_chip, 10);
+ msleep(10);
chip->regDIALOG &= ~VXP_DLG_XILINX_REPROG_MASK;
vx_outb(chip, DIALOG, chip->regDIALOG);
vx_inb(chip, DIALOG);
@@ -244,7 +244,7 @@ static int vxp_load_xilinx_binary(vx_core_t *_chip, const struct firmware *fw)
/*
* vxp_load_dsp - load_dsp callback
*/
-static int vxp_load_dsp(vx_core_t *vx, int index, const struct firmware *fw)
+static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw)
{
int err;
@@ -279,7 +279,7 @@ static int vxp_load_dsp(vx_core_t *vx, int index, const struct firmware *fw)
*
* spinlock held!
*/
-static int vxp_test_and_ack(vx_core_t *_chip)
+static int vxp_test_and_ack(struct vx_core *_chip)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -306,7 +306,7 @@ static int vxp_test_and_ack(vx_core_t *_chip)
/*
* vx_validate_irq - enable/disable IRQ
*/
-static void vxp_validate_irq(vx_core_t *_chip, int enable)
+static void vxp_validate_irq(struct vx_core *_chip, int enable)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -322,7 +322,7 @@ static void vxp_validate_irq(vx_core_t *_chip, int enable)
* vx_setup_pseudo_dma - set up the pseudo dma read/write mode.
* @do_write: 0 = read, 1 = set up for DMA write
*/
-static void vx_setup_pseudo_dma(vx_core_t *_chip, int do_write)
+static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -342,7 +342,7 @@ static void vx_setup_pseudo_dma(vx_core_t *_chip, int do_write)
/*
* vx_release_pseudo_dma - disable the pseudo-DMA mode
*/
-static void vx_release_pseudo_dma(vx_core_t *_chip)
+static void vx_release_pseudo_dma(struct vx_core *_chip)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -362,8 +362,8 @@ static void vx_release_pseudo_dma(vx_core_t *_chip)
* data size must be aligned to 6 bytes to ensure the 24bit alignment on DSP.
* NB: call with a certain lock!
*/
-static void vxp_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
long port = vxp_reg_addr(chip, VX_DMA);
int offset = pipe->hw_ptr;
@@ -401,8 +401,8 @@ static void vxp_dma_write(vx_core_t *chip, snd_pcm_runtime_t *runtime,
* the read length must be aligned to 6 bytes, as well as write.
* NB: call with a certain lock!
*/
-static void vxp_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
- vx_pipe_t *pipe, int count)
+static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
+ struct vx_pipe *pipe, int count)
{
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
long port = vxp_reg_addr(chip, VX_DMA);
@@ -442,7 +442,7 @@ static void vxp_dma_read(vx_core_t *chip, snd_pcm_runtime_t *runtime,
/*
* write a codec data (24bit)
*/
-static void vxp_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
+static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int data)
{
int i;
@@ -465,7 +465,7 @@ static void vxp_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
* vx_set_mic_boost - set mic boost level (on vxp440 only)
* @boost: 0 = 20dB, 1 = +38dB
*/
-void vx_set_mic_boost(vx_core_t *chip, int boost)
+void vx_set_mic_boost(struct vx_core *chip, int boost)
{
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
unsigned long flags;
@@ -508,7 +508,7 @@ static int vx_compute_mic_level(int level)
* vx_set_mic_level - set mic level (on vxpocket only)
* @level: the mic level = 0 - 8 (max)
*/
-void vx_set_mic_level(vx_core_t *chip, int level)
+void vx_set_mic_level(struct vx_core *chip, int level)
{
struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
unsigned long flags;
@@ -528,7 +528,7 @@ void vx_set_mic_level(vx_core_t *chip, int level)
/*
* change the input audio source
*/
-static void vxp_change_audio_source(vx_core_t *_chip, int src)
+static void vxp_change_audio_source(struct vx_core *_chip, int src)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -568,7 +568,7 @@ static void vxp_change_audio_source(vx_core_t *_chip, int src)
* change the clock source
* source = INTERNAL_QUARTZ or UER_SYNC
*/
-static void vxp_set_clock_source(vx_core_t *_chip, int source)
+static void vxp_set_clock_source(struct vx_core *_chip, int source)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
@@ -583,7 +583,7 @@ static void vxp_set_clock_source(vx_core_t *_chip, int source)
/*
* reset the board
*/
-static void vxp_reset_board(vx_core_t *_chip, int cold_reset)
+static void vxp_reset_board(struct vx_core *_chip, int cold_reset)
{
struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 1e8f16b4c073..66900d20a42f 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -55,11 +55,6 @@ MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard.");
*/
static unsigned int card_alloc;
-static dev_link_t *dev_list; /* Linked list of devices */
-static dev_info_t dev_info = "snd-vxpocket";
-
-
-static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
/*
@@ -73,19 +68,14 @@ static void vxpocket_release(dev_link_t *link)
pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
}
- if (link->handle) {
- /* Break the link with Card Services */
- pcmcia_deregister_client(link->handle);
- link->handle = NULL;
- }
}
/*
* destructor, called from snd_card_free_in_thread()
*/
-static int snd_vxpocket_dev_free(snd_device_t *device)
+static int snd_vxpocket_dev_free(struct snd_device *device)
{
- vx_core_t *chip = device->device_data;
+ struct vx_core *chip = device->device_data;
snd_vx_free_firmware(chip);
kfree(chip);
@@ -142,19 +132,17 @@ static struct snd_vx_hardware vxp440_hw = {
/*
* create vxpocket instance
*/
-static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl)
+static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
{
- client_reg_t client_reg; /* Register with cardmgr */
dev_link_t *link; /* Info for cardmgr */
- vx_core_t *chip;
+ struct vx_core *chip;
struct snd_vxpocket *vxp;
- int ret;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_vxpocket_dev_free,
};
chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
- sizeof(struct snd_vxpocket) - sizeof(vx_core_t));
+ sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
if (! chip)
return NULL;
@@ -184,26 +172,6 @@ static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl)
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
- /* Register with Card Services */
- memset(&client_reg, 0, sizeof(client_reg));
- client_reg.dev_info = &dev_info;
- client_reg.EventMask =
- CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
-#ifdef CONFIG_PM
- | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
- | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
-#endif
- ;
- client_reg.event_handler = &vxpocket_event;
- 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);
- return NULL;
- }
-
return vxp;
}
@@ -218,10 +186,10 @@ static struct snd_vxpocket *snd_vxpocket_new(snd_card_t *card, int ibl)
*
* returns 0 if successful, or a negative error code.
*/
-static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
+static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq)
{
int err;
- snd_card_t *card = chip->card;
+ struct snd_card *card = chip->card;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
@@ -250,7 +218,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static void vxpocket_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
- vx_core_t *chip = link->priv;
+ struct vx_core *chip = link->priv;
struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
tuple_t tuple;
cisparse_t *parse;
@@ -317,69 +285,57 @@ failed:
kfree(parse);
}
+#ifdef CONFIG_PM
-/*
- * event callback
- */
-static int vxpocket_event(event_t event, int priority, event_callback_args_t *args)
+static int vxp_suspend(struct pcmcia_device *dev)
{
- dev_link_t *link = args->client_data;
- vx_core_t *chip = link->priv;
-
- switch (event) {
- case CS_EVENT_CARD_REMOVAL:
- snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n");
- link->state &= ~DEV_PRESENT;
- if (link->state & DEV_CONFIG)
- chip->chip_status |= VX_STAT_IS_STALE;
- break;
- case CS_EVENT_CARD_INSERTION:
- snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- vxpocket_config(link);
- break;
-#ifdef CONFIG_PM
- case CS_EVENT_PM_SUSPEND:
- snd_printdd(KERN_DEBUG "SUSPEND\n");
- link->state |= DEV_SUSPEND;
- if (chip && chip->card->pm_suspend) {
- snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
- chip->card->pm_suspend(chip->card, PMSG_SUSPEND);
- }
- /* Fall through... */
- case CS_EVENT_RESET_PHYSICAL:
- snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
- if (link->state & DEV_CONFIG)
- pcmcia_release_configuration(link->handle);
- break;
- case CS_EVENT_PM_RESUME:
- snd_printdd(KERN_DEBUG "RESUME\n");
- link->state &= ~DEV_SUSPEND;
- /* Fall through... */
- case CS_EVENT_CARD_RESET:
- snd_printdd(KERN_DEBUG "CARD_RESET\n");
- if (DEV_OK(link)) {
- //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
- snd_printdd(KERN_DEBUG "requestconfig...\n");
- pcmcia_request_configuration(link->handle, &link->conf);
- if (chip && chip->card->pm_resume) {
- snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
- chip->card->pm_resume(chip->card);
- }
+ dev_link_t *link = dev_to_instance(dev);
+ struct vx_core *chip = link->priv;
+
+ snd_printdd(KERN_DEBUG "SUSPEND\n");
+ link->state |= DEV_SUSPEND;
+ if (chip) {
+ snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
+ snd_vx_suspend(chip, PMSG_SUSPEND);
+ }
+ snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+
+ return 0;
+}
+
+static int vxp_resume(struct pcmcia_device *dev)
+{
+ dev_link_t *link = dev_to_instance(dev);
+ struct vx_core *chip = link->priv;
+
+ snd_printdd(KERN_DEBUG "RESUME\n");
+ link->state &= ~DEV_SUSPEND;
+
+ snd_printdd(KERN_DEBUG "CARD_RESET\n");
+ if (DEV_OK(link)) {
+ //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
+ snd_printdd(KERN_DEBUG "requestconfig...\n");
+ pcmcia_request_configuration(link->handle, &link->conf);
+ if (chip) {
+ snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
+ snd_vx_resume(chip);
}
- snd_printdd(KERN_DEBUG "resume done!\n");
- break;
-#endif
}
+ snd_printdd(KERN_DEBUG "resume done!\n");
+
return 0;
}
+#endif
+
/*
*/
-static dev_link_t *vxpocket_attach(void)
+static int vxpocket_attach(struct pcmcia_device *p_dev)
{
- snd_card_t *card;
+ struct snd_card *card;
struct snd_vxpocket *vxp;
int i;
@@ -390,54 +346,52 @@ static dev_link_t *vxpocket_attach(void)
}
if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "vxpocket: too many cards found\n");
- return NULL;
+ return -EINVAL;
}
if (! enable[i])
- return NULL; /* disabled explicitly */
+ return -ENODEV; /* disabled explicitly */
/* ok, create a card instance */
card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (card == NULL) {
snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
- return NULL;
+ return -ENOMEM;
}
vxp = snd_vxpocket_new(card, ibl[i]);
if (! vxp) {
snd_card_free(card);
- return NULL;
+ return -ENODEV;
}
+ card->private_data = vxp;
vxp->index = i;
card_alloc |= 1 << i;
/* Chain drivers */
- vxp->link.next = dev_list;
- dev_list = &vxp->link;
+ vxp->link.next = NULL;
+
+ vxp->link.handle = p_dev;
+ vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ p_dev->instance = &vxp->link;
+ vxpocket_config(&vxp->link);
- return &vxp->link;
+ return 0;
}
-static void vxpocket_detach(dev_link_t *link)
+static void vxpocket_detach(struct pcmcia_device *p_dev)
{
+ dev_link_t *link = dev_to_instance(p_dev);
struct snd_vxpocket *vxp;
- vx_core_t *chip;
- dev_link_t **linkp;
+ struct vx_core *chip;
if (! link)
return;
vxp = link->priv;
- chip = (vx_core_t *)vxp;
+ chip = (struct vx_core *)vxp;
card_alloc &= ~(1 << vxp->index);
- /* Remove the interface data from the linked list */
- for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
- if (*linkp == link) {
- *linkp = link->next;
- break;
- }
-
chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */
snd_card_disconnect(chip->card);
vxpocket_release(link);
@@ -459,10 +413,13 @@ static struct pcmcia_driver vxp_cs_driver = {
.drv = {
.name = "snd-vxpocket",
},
- .attach = vxpocket_attach,
- .detach = vxpocket_detach,
- .event = vxpocket_event,
+ .probe = vxpocket_attach,
+ .remove = vxpocket_detach,
.id_table = vxp_ids,
+#ifdef CONFIG_PM
+ .suspend = vxp_suspend,
+ .resume = vxp_resume,
+#endif
};
static int __init init_vxpocket(void)
@@ -473,7 +430,6 @@ static int __init init_vxpocket(void)
static void __exit exit_vxpocket(void)
{
pcmcia_unregister_driver(&vxp_cs_driver);
- BUG_ON(dev_list != NULL);
}
module_init(init_vxpocket);
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 70754aa3dd11..67efae3f6c8d 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -30,7 +30,7 @@
struct snd_vxpocket {
- vx_core_t core;
+ struct vx_core core;
unsigned long port;
@@ -48,10 +48,10 @@ struct snd_vxpocket {
extern struct snd_vx_ops snd_vxpocket_ops;
-void vx_set_mic_boost(vx_core_t *chip, int boost);
-void vx_set_mic_level(vx_core_t *chip, int level);
+void vx_set_mic_boost(struct vx_core *chip, int boost);
+void vx_set_mic_level(struct vx_core *chip, int level);
-int vxp_add_mic_controls(vx_core_t *chip);
+int vxp_add_mic_controls(struct vx_core *chip);
/* Constants used to access the CDSP register (0x08). */
#define CDSP_MAGIC 0xA7 /* magic value (for read) */
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 206b9333f91f..a3fb1496e4dc 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -13,7 +13,6 @@ 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.
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 758ca1bcbcf2..82d791be7499 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -35,18 +35,18 @@
#endif
#ifdef PMAC_AMP_AVAIL
-typedef struct awacs_amp {
+struct awacs_amp {
unsigned char amp_master;
unsigned char amp_vol[2][2];
unsigned char amp_tone[2];
-} awacs_amp_t;
+};
#define CHECK_CUDA_AMP() (sys_ctrler == SYS_CTRLER_CUDA)
#endif /* PMAC_AMP_AVAIL */
-static void snd_pmac_screamer_wait(pmac_t *chip)
+static void snd_pmac_screamer_wait(struct snd_pmac *chip)
{
long timeout = 2000;
while (!(in_le32(&chip->awacs->codec_stat) & MASK_VALID)) {
@@ -62,7 +62,7 @@ static void snd_pmac_screamer_wait(pmac_t *chip)
* write AWACS register
*/
static void
-snd_pmac_awacs_write(pmac_t *chip, int val)
+snd_pmac_awacs_write(struct snd_pmac *chip, int val)
{
long timeout = 5000000;
@@ -78,21 +78,21 @@ snd_pmac_awacs_write(pmac_t *chip, int val)
}
static void
-snd_pmac_awacs_write_reg(pmac_t *chip, int reg, int val)
+snd_pmac_awacs_write_reg(struct snd_pmac *chip, int reg, int val)
{
snd_pmac_awacs_write(chip, val | (reg << 12));
chip->awacs_reg[reg] = val;
}
static void
-snd_pmac_awacs_write_noreg(pmac_t *chip, int reg, int val)
+snd_pmac_awacs_write_noreg(struct snd_pmac *chip, int reg, int val)
{
snd_pmac_awacs_write(chip, val | (reg << 12));
}
#ifdef CONFIG_PM
/* Recalibrate chip */
-static void screamer_recalibrate(pmac_t *chip)
+static void screamer_recalibrate(struct snd_pmac *chip)
{
if (chip->model != PMAC_SCREAMER)
return;
@@ -105,7 +105,8 @@ static void screamer_recalibrate(pmac_t *chip)
/* delay for broken crystal part */
msleep(750);
snd_pmac_awacs_write_noreg(chip, 1,
- chip->awacs_reg[1] | MASK_RECALIBRATE | MASK_CMUTE | MASK_AMUTE);
+ chip->awacs_reg[1] | MASK_RECALIBRATE |
+ MASK_CMUTE | MASK_AMUTE);
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
snd_pmac_awacs_write_noreg(chip, 6, chip->awacs_reg[6]);
}
@@ -118,7 +119,7 @@ static void screamer_recalibrate(pmac_t *chip)
/*
* additional callback to set the pcm format
*/
-static void snd_pmac_awacs_set_format(pmac_t *chip)
+static void snd_pmac_awacs_set_format(struct snd_pmac *chip)
{
chip->awacs_reg[1] &= ~MASK_SAMPLERATE;
chip->awacs_reg[1] |= chip->rate_index << 3;
@@ -132,7 +133,8 @@ static void snd_pmac_awacs_set_format(pmac_t *chip)
/*
* volumes: 0-15 stereo
*/
-static int snd_pmac_awacs_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_awacs_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -141,9 +143,10 @@ static int snd_pmac_awacs_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int snd_pmac_awacs_get_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int lshift = (kcontrol->private_value >> 8) & 0xff;
int inverted = (kcontrol->private_value >> 16) & 1;
@@ -163,9 +166,10 @@ static int snd_pmac_awacs_get_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_pmac_awacs_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int lshift = (kcontrol->private_value >> 8) & 0xff;
int inverted = (kcontrol->private_value >> 16) & 1;
@@ -203,9 +207,10 @@ static int snd_pmac_awacs_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
/*
* mute master/ogain for AWACS: mono
*/
-static int snd_pmac_awacs_get_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int invert = (kcontrol->private_value >> 16) & 1;
@@ -221,9 +226,10 @@ static int snd_pmac_awacs_get_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
return 0;
}
-static int snd_pmac_awacs_put_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int invert = (kcontrol->private_value >> 16) & 1;
@@ -268,7 +274,7 @@ static void awacs_set_cuda(int reg, int val)
/*
* level = 0 - 14, 7 = 0 dB
*/
-static void awacs_amp_set_tone(awacs_amp_t *amp, int bass, int treble)
+static void awacs_amp_set_tone(struct awacs_amp *amp, int bass, int treble)
{
amp->amp_tone[0] = bass;
amp->amp_tone[1] = treble;
@@ -282,7 +288,8 @@ static void awacs_amp_set_tone(awacs_amp_t *amp, int bass, int treble)
/*
* vol = 0 - 31 (attenuation), 32 = mute bit, stereo
*/
-static int awacs_amp_set_vol(awacs_amp_t *amp, int index, int lvol, int rvol, int do_check)
+static int awacs_amp_set_vol(struct awacs_amp *amp, int index, int lvol, int rvol,
+ int do_check)
{
if (do_check && amp->amp_vol[index][0] == lvol &&
amp->amp_vol[index][1] == rvol)
@@ -297,7 +304,7 @@ static int awacs_amp_set_vol(awacs_amp_t *amp, int index, int lvol, int rvol, in
/*
* 0 = -79 dB, 79 = 0 dB, 99 = +20 dB
*/
-static void awacs_amp_set_master(awacs_amp_t *amp, int vol)
+static void awacs_amp_set_master(struct awacs_amp *amp, int vol)
{
amp->amp_master = vol;
if (vol <= 79)
@@ -307,9 +314,9 @@ static void awacs_amp_set_master(awacs_amp_t *amp, int vol)
awacs_set_cuda(1, vol);
}
-static void awacs_amp_free(pmac_t *chip)
+static void awacs_amp_free(struct snd_pmac *chip)
{
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return);
kfree(amp);
chip->mixer_data = NULL;
@@ -320,7 +327,8 @@ static void awacs_amp_free(pmac_t *chip)
/*
* mixer controls
*/
-static int snd_pmac_awacs_info_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_awacs_info_volume_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -329,11 +337,12 @@ static int snd_pmac_awacs_info_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_pmac_awacs_get_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_volume_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
ucontrol->value.integer.value[0] = 31 - (amp->amp_vol[index][0] & 31);
@@ -341,12 +350,13 @@ static int snd_pmac_awacs_get_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_pmac_awacs_put_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_volume_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
int vol[2];
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
@@ -355,11 +365,12 @@ static int snd_pmac_awacs_put_volume_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
}
-static int snd_pmac_awacs_get_switch_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_switch_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
ucontrol->value.integer.value[0] = (amp->amp_vol[index][0] & 32) ? 0 : 1;
@@ -367,12 +378,13 @@ static int snd_pmac_awacs_get_switch_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_pmac_awacs_put_switch_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_switch_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
int vol[2];
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
@@ -381,7 +393,8 @@ static int snd_pmac_awacs_put_switch_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return awacs_amp_set_vol(amp, index, vol[0], vol[1], 1);
}
-static int snd_pmac_awacs_info_tone_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_awacs_info_tone_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -390,22 +403,24 @@ static int snd_pmac_awacs_info_tone_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
return 0;
}
-static int snd_pmac_awacs_get_tone_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_tone_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
ucontrol->value.integer.value[0] = amp->amp_tone[index];
return 0;
}
-static int snd_pmac_awacs_put_tone_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_tone_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
snd_assert(index >= 0 && index <= 1, return -EINVAL);
if (ucontrol->value.integer.value[0] != amp->amp_tone[index]) {
@@ -416,7 +431,8 @@ static int snd_pmac_awacs_put_tone_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
return 0;
}
-static int snd_pmac_awacs_info_master_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_awacs_info_master_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -425,19 +441,21 @@ static int snd_pmac_awacs_info_master_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem
return 0;
}
-static int snd_pmac_awacs_get_master_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_get_master_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- awacs_amp_t *amp = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
ucontrol->value.integer.value[0] = amp->amp_master;
return 0;
}
-static int snd_pmac_awacs_put_master_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- awacs_amp_t *amp = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct awacs_amp *amp = chip->mixer_data;
snd_assert(amp, return -EINVAL);
if (ucontrol->value.integer.value[0] != amp->amp_master) {
amp->amp_master = ucontrol->value.integer.value[0];
@@ -450,7 +468,7 @@ static int snd_pmac_awacs_put_master_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_
#define AMP_CH_SPK 0
#define AMP_CH_HD 1
-static snd_kcontrol_new_t snd_pmac_awacs_amp_vol[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] __initdata = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PC Speaker Playback Volume",
.info = snd_pmac_awacs_info_volume_amp,
@@ -487,7 +505,7 @@ static snd_kcontrol_new_t snd_pmac_awacs_amp_vol[] __initdata = {
},
};
-static snd_kcontrol_new_t snd_pmac_awacs_amp_hp_sw __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -496,7 +514,7 @@ static snd_kcontrol_new_t snd_pmac_awacs_amp_hp_sw __initdata = {
.private_value = AMP_CH_HD,
};
-static snd_kcontrol_new_t snd_pmac_awacs_amp_spk_sw __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PC Speaker Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -511,7 +529,8 @@ static snd_kcontrol_new_t snd_pmac_awacs_amp_spk_sw __initdata = {
/*
* mic boost for screamer
*/
-static int snd_pmac_screamer_mic_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_screamer_mic_boost_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -520,9 +539,10 @@ static int snd_pmac_screamer_mic_boost_info(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_pmac_screamer_mic_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_screamer_mic_boost_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int val;
unsigned long flags;
@@ -538,9 +558,10 @@ static int snd_pmac_screamer_mic_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_ele
return 0;
}
-static int snd_pmac_screamer_mic_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
int val0, val6;
unsigned long flags;
@@ -568,7 +589,7 @@ static int snd_pmac_screamer_mic_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_ele
/*
* lists of mixer elements
*/
-static snd_kcontrol_new_t snd_pmac_awacs_mixers[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers[] __initdata = {
AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
AWACS_VOLUME("Capture Volume", 0, 4, 0),
@@ -578,24 +599,24 @@ static snd_kcontrol_new_t snd_pmac_awacs_mixers[] __initdata = {
/* FIXME: is this correct order?
* screamer (powerbook G3 pismo) seems to have different bits...
*/
-static snd_kcontrol_new_t snd_pmac_awacs_mixers2[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] __initdata = {
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
};
-static snd_kcontrol_new_t snd_pmac_screamer_mixers2[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] __initdata = {
AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
};
-static snd_kcontrol_new_t snd_pmac_awacs_master_sw __initdata =
+static struct snd_kcontrol_new snd_pmac_awacs_master_sw __initdata =
AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
-static snd_kcontrol_new_t snd_pmac_awacs_mic_boost[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] __initdata = {
AWACS_SWITCH("Mic Boost", 0, SHIFT_GAINLINE, 0),
};
-static snd_kcontrol_new_t snd_pmac_screamer_mic_boost[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] __initdata = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost",
.info = snd_pmac_screamer_mic_boost_info,
@@ -604,17 +625,17 @@ static snd_kcontrol_new_t snd_pmac_screamer_mic_boost[] __initdata = {
},
};
-static snd_kcontrol_new_t snd_pmac_awacs_speaker_vol[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] __initdata = {
AWACS_VOLUME("PC Speaker Playback Volume", 4, 6, 1),
};
-static snd_kcontrol_new_t snd_pmac_awacs_speaker_sw __initdata =
+static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw __initdata =
AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
/*
* add new mixer elements to the card
*/
-static int build_mixers(pmac_t *chip, int nums, snd_kcontrol_new_t *mixers)
+static int build_mixers(struct snd_pmac *chip, int nums, struct snd_kcontrol_new *mixers)
{
int i, err;
@@ -629,7 +650,7 @@ static int build_mixers(pmac_t *chip, int nums, snd_kcontrol_new_t *mixers)
/*
* restore all registers
*/
-static void awacs_restore_all_regs(pmac_t *chip)
+static void awacs_restore_all_regs(struct snd_pmac *chip)
{
snd_pmac_awacs_write_noreg(chip, 0, chip->awacs_reg[0]);
snd_pmac_awacs_write_noreg(chip, 1, chip->awacs_reg[1]);
@@ -643,13 +664,13 @@ static void awacs_restore_all_regs(pmac_t *chip)
}
#ifdef CONFIG_PM
-static void snd_pmac_awacs_suspend(pmac_t *chip)
+static void snd_pmac_awacs_suspend(struct snd_pmac *chip)
{
snd_pmac_awacs_write_noreg(chip, 1, (chip->awacs_reg[1]
| MASK_AMUTE | MASK_CMUTE));
}
-static void snd_pmac_awacs_resume(pmac_t *chip)
+static void snd_pmac_awacs_resume(struct snd_pmac *chip)
{
if (machine_is_compatible("PowerBook3,1")
|| machine_is_compatible("PowerBook3,2")) {
@@ -668,7 +689,7 @@ static void snd_pmac_awacs_resume(pmac_t *chip)
screamer_recalibrate(chip);
#ifdef PMAC_AMP_AVAIL
if (chip->mixer_data) {
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
awacs_amp_set_vol(amp, 0, amp->amp_vol[0][0], amp->amp_vol[0][1], 0);
awacs_amp_set_vol(amp, 1, amp->amp_vol[1][0], amp->amp_vol[1][1], 0);
awacs_amp_set_tone(amp, amp->amp_tone[0], amp->amp_tone[1]);
@@ -682,13 +703,13 @@ static void snd_pmac_awacs_resume(pmac_t *chip)
/*
* auto-mute stuffs
*/
-static int snd_pmac_awacs_detect_headphone(pmac_t *chip)
+static int snd_pmac_awacs_detect_headphone(struct snd_pmac *chip)
{
return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
}
#ifdef PMAC_AMP_AVAIL
-static int toggle_amp_mute(awacs_amp_t *amp, int index, int mute)
+static int toggle_amp_mute(struct awacs_amp *amp, int index, int mute)
{
int vol[2];
vol[0] = amp->amp_vol[index][0] & 31;
@@ -701,12 +722,12 @@ static int toggle_amp_mute(awacs_amp_t *amp, int index, int mute)
}
#endif
-static void snd_pmac_awacs_update_automute(pmac_t *chip, int do_notify)
+static void snd_pmac_awacs_update_automute(struct snd_pmac *chip, int do_notify)
{
if (chip->auto_mute) {
#ifdef PMAC_AMP_AVAIL
if (chip->mixer_data) {
- awacs_amp_t *amp = chip->mixer_data;
+ struct awacs_amp *amp = chip->mixer_data;
int changed;
if (snd_pmac_awacs_detect_headphone(chip)) {
changed = toggle_amp_mute(amp, AMP_CH_HD, 0);
@@ -746,7 +767,7 @@ static void snd_pmac_awacs_update_automute(pmac_t *chip, int do_notify)
* initialize chip
*/
int __init
-snd_pmac_awacs_init(pmac_t *chip)
+snd_pmac_awacs_init(struct snd_pmac *chip)
{
int err, vol;
@@ -780,7 +801,7 @@ snd_pmac_awacs_init(pmac_t *chip)
chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
#ifdef PMAC_AMP_AVAIL
if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {
- awacs_amp_t *amp = kmalloc(sizeof(*amp), GFP_KERNEL);
+ struct awacs_amp *amp = kmalloc(sizeof(*amp), GFP_KERNEL);
if (! amp)
return -ENOMEM;
chip->mixer_data = amp;
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index d4ec6cc3f1c5..5fec1e58f310 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -30,7 +30,7 @@
#include <sound/control.h>
#include "pmac.h"
-struct snd_pmac_beep {
+struct pmac_beep {
int running; /* boolean */
int volume; /* mixer volume: 0-100 */
int volume_play; /* currently playing volume */
@@ -44,9 +44,9 @@ struct snd_pmac_beep {
/*
* stop beep if running
*/
-void snd_pmac_beep_stop(pmac_t *chip)
+void snd_pmac_beep_stop(struct snd_pmac *chip)
{
- pmac_beep_t *beep = chip->beep;
+ struct pmac_beep *beep = chip->beep;
if (beep && beep->running) {
beep->running = 0;
snd_pmac_beep_dma_stop(chip);
@@ -97,10 +97,11 @@ static short beep_wform[256] = {
#define BEEP_BUFLEN 512
#define BEEP_VOLUME 15 /* 0 - 100 */
-static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz)
+static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int hz)
{
- pmac_t *chip;
- pmac_beep_t *beep;
+ struct snd_pmac *chip;
+ struct pmac_beep *beep;
unsigned long flags;
int beep_speed = 0;
int srate;
@@ -171,7 +172,8 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigne
* beep volume mixer
*/
-static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_info_beep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
@@ -180,17 +182,19 @@ static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uin
return 0;
}
-static int snd_pmac_get_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_get_beep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
snd_assert(chip->beep, return -ENXIO);
ucontrol->value.integer.value[0] = chip->beep->volume;
return 0;
}
-static int snd_pmac_put_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int oval;
snd_assert(chip->beep, return -ENXIO);
oval = chip->beep->volume;
@@ -198,7 +202,7 @@ static int snd_pmac_put_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uco
return oval != chip->beep->volume;
}
-static snd_kcontrol_new_t snd_pmac_beep_mixer = {
+static struct snd_kcontrol_new snd_pmac_beep_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Beep Playback Volume",
.info = snd_pmac_info_beep,
@@ -207,9 +211,9 @@ static snd_kcontrol_new_t snd_pmac_beep_mixer = {
};
/* Initialize beep stuff */
-int __init snd_pmac_attach_beep(pmac_t *chip)
+int __init snd_pmac_attach_beep(struct snd_pmac *chip)
{
- pmac_beep_t *beep;
+ struct pmac_beep *beep;
struct input_dev *input_dev;
void *dmabuf;
int err = -ENOMEM;
@@ -255,7 +259,7 @@ int __init snd_pmac_attach_beep(pmac_t *chip)
return err;
}
-void snd_pmac_detach_beep(pmac_t *chip)
+void snd_pmac_detach_beep(struct snd_pmac *chip)
{
if (chip->beep) {
input_unregister_device(chip->beep->dev);
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index edbc0484e22a..e02263fe44dc 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -31,7 +31,7 @@
/* Waits for busy flag to clear */
static inline void
-snd_pmac_burgundy_busy_wait(pmac_t *chip)
+snd_pmac_burgundy_busy_wait(struct snd_pmac *chip)
{
int timeout = 50;
while ((in_le32(&chip->awacs->codec_ctrl) & MASK_NEWECMD) && timeout--)
@@ -41,7 +41,7 @@ snd_pmac_burgundy_busy_wait(pmac_t *chip)
}
static inline void
-snd_pmac_burgundy_extend_wait(pmac_t *chip)
+snd_pmac_burgundy_extend_wait(struct snd_pmac *chip)
{
int timeout;
timeout = 50;
@@ -57,7 +57,7 @@ snd_pmac_burgundy_extend_wait(pmac_t *chip)
}
static void
-snd_pmac_burgundy_wcw(pmac_t *chip, unsigned addr, unsigned val)
+snd_pmac_burgundy_wcw(struct snd_pmac *chip, unsigned addr, unsigned val)
{
out_le32(&chip->awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
snd_pmac_burgundy_busy_wait(chip);
@@ -70,7 +70,7 @@ snd_pmac_burgundy_wcw(pmac_t *chip, unsigned addr, unsigned val)
}
static unsigned
-snd_pmac_burgundy_rcw(pmac_t *chip, unsigned addr)
+snd_pmac_burgundy_rcw(struct snd_pmac *chip, unsigned addr)
{
unsigned val = 0;
unsigned long flags;
@@ -103,14 +103,14 @@ snd_pmac_burgundy_rcw(pmac_t *chip, unsigned addr)
}
static void
-snd_pmac_burgundy_wcb(pmac_t *chip, unsigned int addr, unsigned int val)
+snd_pmac_burgundy_wcb(struct snd_pmac *chip, unsigned int addr, unsigned int val)
{
out_le32(&chip->awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
snd_pmac_burgundy_busy_wait(chip);
}
static unsigned
-snd_pmac_burgundy_rcb(pmac_t *chip, unsigned int addr)
+snd_pmac_burgundy_rcb(struct snd_pmac *chip, unsigned int addr)
{
unsigned val = 0;
unsigned long flags;
@@ -131,7 +131,8 @@ snd_pmac_burgundy_rcb(pmac_t *chip, unsigned int addr)
* Burgundy volume: 0 - 100, stereo
*/
static void
-snd_pmac_burgundy_write_volume(pmac_t *chip, unsigned int address, long *volume, int shift)
+snd_pmac_burgundy_write_volume(struct snd_pmac *chip, unsigned int address,
+ long *volume, int shift)
{
int hardvolume, lvolume, rvolume;
@@ -146,7 +147,8 @@ snd_pmac_burgundy_write_volume(pmac_t *chip, unsigned int address, long *volume,
}
static void
-snd_pmac_burgundy_read_volume(pmac_t *chip, unsigned int address, long *volume, int shift)
+snd_pmac_burgundy_read_volume(struct snd_pmac *chip, unsigned int address,
+ long *volume, int shift)
{
int wvolume;
@@ -171,7 +173,8 @@ snd_pmac_burgundy_read_volume(pmac_t *chip, unsigned int address, long *volume,
#define BASE2ADDR(base) ((base) << 12)
#define ADDR2BASE(addr) ((addr) >> 12)
-static int snd_pmac_burgundy_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_burgundy_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -180,23 +183,27 @@ static int snd_pmac_burgundy_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_
return 0;
}
-static int snd_pmac_burgundy_get_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
int shift = (kcontrol->private_value >> 8) & 0xff;
- snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value, shift);
+ snd_pmac_burgundy_read_volume(chip, addr, ucontrol->value.integer.value,
+ shift);
return 0;
}
-static int snd_pmac_burgundy_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
int shift = (kcontrol->private_value >> 8) & 0xff;
long nvoices[2];
- snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value, shift);
+ snd_pmac_burgundy_write_volume(chip, addr, ucontrol->value.integer.value,
+ shift);
snd_pmac_burgundy_read_volume(chip, addr, nvoices, shift);
return (nvoices[0] != ucontrol->value.integer.value[0] ||
nvoices[1] != ucontrol->value.integer.value[1]);
@@ -211,7 +218,8 @@ static int snd_pmac_burgundy_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
/* lineout/speaker */
-static int snd_pmac_burgundy_info_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_burgundy_info_switch_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int stereo = (kcontrol->private_value >> 24) & 1;
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -221,9 +229,10 @@ static int snd_pmac_burgundy_info_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_pmac_burgundy_get_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_get_switch_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int lmask = kcontrol->private_value & 0xff;
int rmask = (kcontrol->private_value >> 8) & 0xff;
int stereo = (kcontrol->private_value >> 24) & 1;
@@ -234,9 +243,10 @@ static int snd_pmac_burgundy_get_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_pmac_burgundy_put_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_put_switch_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
int lmask = kcontrol->private_value & 0xff;
int rmask = (kcontrol->private_value >> 8) & 0xff;
int stereo = (kcontrol->private_value >> 24) & 1;
@@ -259,7 +269,8 @@ static int snd_pmac_burgundy_put_switch_out(snd_kcontrol_t *kcontrol, snd_ctl_el
.private_value = ((lmask) | ((rmask) << 8) | ((stereo) << 24)) }
/* line/speaker output volume */
-static int snd_pmac_burgundy_info_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_pmac_burgundy_info_volume_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int stereo = (kcontrol->private_value >> 24) & 1;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -269,9 +280,10 @@ static int snd_pmac_burgundy_info_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_e
return 0;
}
-static int snd_pmac_burgundy_get_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_get_volume_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
int stereo = (kcontrol->private_value >> 24) & 1;
int oval;
@@ -283,9 +295,10 @@ static int snd_pmac_burgundy_get_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_el
return 0;
}
-static int snd_pmac_burgundy_put_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_pmac_burgundy_put_volume_out(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
unsigned int addr = BASE2ADDR(kcontrol->private_value & 0xff);
int stereo = (kcontrol->private_value >> 24) & 1;
int oval, val;
@@ -308,7 +321,7 @@ static int snd_pmac_burgundy_put_volume_out(snd_kcontrol_t *kcontrol, snd_ctl_el
.put = snd_pmac_burgundy_put_volume_out,\
.private_value = (ADDR2BASE(addr) | ((stereo) << 24)) }
-static snd_kcontrol_new_t snd_pmac_burgundy_mixers[] __initdata = {
+static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] __initdata = {
BURGUNDY_VOLUME("Master Playback Volume", 0, MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
BURGUNDY_VOLUME("Line Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLLINE, 16),
BURGUNDY_VOLUME("CD Playback Volume", 0, MASK_ADDR_BURGUNDY_VOLCD, 16),
@@ -317,9 +330,9 @@ static snd_kcontrol_new_t snd_pmac_burgundy_mixers[] __initdata = {
/*BURGUNDY_OUTPUT_VOLUME("PCM Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENLINEOUT, 1),*/
BURGUNDY_OUTPUT_VOLUME("Headphone Playback Volume", 0, MASK_ADDR_BURGUNDY_ATTENSPEAKER, 1),
};
-static snd_kcontrol_new_t snd_pmac_burgundy_master_sw __initdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_master_sw __initdata =
BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static snd_kcontrol_new_t snd_pmac_burgundy_speaker_sw __initdata =
+static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw __initdata =
BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
@@ -327,12 +340,12 @@ BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN,
/*
* auto-mute stuffs
*/
-static int snd_pmac_burgundy_detect_headphone(pmac_t *chip)
+static int snd_pmac_burgundy_detect_headphone(struct snd_pmac *chip)
{
return (in_le32(&chip->awacs->codec_stat) & chip->hp_stat_mask) ? 1 : 0;
}
-static void snd_pmac_burgundy_update_automute(pmac_t *chip, int do_notify)
+static void snd_pmac_burgundy_update_automute(struct snd_pmac *chip, int do_notify)
{
if (chip->auto_mute) {
int reg, oreg;
@@ -361,7 +374,7 @@ static void snd_pmac_burgundy_update_automute(pmac_t *chip, int do_notify)
/*
* initialize burgundy
*/
-int __init snd_pmac_burgundy_init(pmac_t *chip)
+int __init snd_pmac_burgundy_init(struct snd_pmac *chip)
{
int i, err;
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index a737f298e77d..08cde51177d7 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -40,18 +40,18 @@
#define DACA_VOL_MAX 0x38
-typedef struct pmac_daca_t {
- pmac_keywest_t i2c;
+struct pmac_daca {
+ struct pmac_keywest i2c;
int left_vol, right_vol;
unsigned int deemphasis : 1;
unsigned int amp_on : 1;
-} pmac_daca_t;
+};
/*
* initialize / detect DACA
*/
-static int daca_init_client(pmac_keywest_t *i2c)
+static int daca_init_client(struct pmac_keywest *i2c)
{
unsigned short wdata = 0x00;
/* SR: no swap, 1bit delay, 32-48kHz */
@@ -66,7 +66,7 @@ static int daca_init_client(pmac_keywest_t *i2c)
/*
* update volume
*/
-static int daca_set_volume(pmac_daca_t *mix)
+static int daca_set_volume(struct pmac_daca *mix)
{
unsigned char data[2];
@@ -92,7 +92,8 @@ static int daca_set_volume(pmac_daca_t *mix)
/* deemphasis switch */
-static int daca_info_deemphasis(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int daca_info_deemphasis(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -101,20 +102,22 @@ static int daca_info_deemphasis(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *u
return 0;
}
-static int daca_get_deemphasis(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_get_deemphasis(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0;
return 0;
}
-static int daca_put_deemphasis(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_put_deemphasis(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -128,7 +131,8 @@ static int daca_put_deemphasis(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
}
/* output volume */
-static int daca_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int daca_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -137,10 +141,11 @@ static int daca_info_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
return 0;
}
-static int daca_get_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->left_vol;
@@ -148,10 +153,11 @@ static int daca_get_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int daca_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -169,20 +175,22 @@ static int daca_put_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
/* amplifier switch */
#define daca_info_amp daca_info_deemphasis
-static int daca_get_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_get_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0;
return 0;
}
-static int daca_put_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int daca_put_amp(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_daca_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_daca *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -196,7 +204,7 @@ static int daca_put_amp(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol
return change;
}
-static snd_kcontrol_new_t daca_mixers[] = {
+static struct snd_kcontrol_new daca_mixers[] = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Deemphasis Switch",
.info = daca_info_deemphasis,
@@ -219,9 +227,9 @@ static snd_kcontrol_new_t daca_mixers[] = {
#ifdef CONFIG_PM
-static void daca_resume(pmac_t *chip)
+static void daca_resume(struct snd_pmac *chip)
{
- pmac_daca_t *mix = chip->mixer_data;
+ struct pmac_daca *mix = chip->mixer_data;
i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08);
i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
mix->amp_on ? 0x05 : 0x04);
@@ -230,9 +238,9 @@ static void daca_resume(pmac_t *chip)
#endif /* CONFIG_PM */
-static void daca_cleanup(pmac_t *chip)
+static void daca_cleanup(struct snd_pmac *chip)
{
- pmac_daca_t *mix = chip->mixer_data;
+ struct pmac_daca *mix = chip->mixer_data;
if (! mix)
return;
snd_pmac_keywest_cleanup(&mix->i2c);
@@ -241,10 +249,10 @@ static void daca_cleanup(pmac_t *chip)
}
/* exported */
-int __init snd_pmac_daca_init(pmac_t *chip)
+int __init snd_pmac_daca_init(struct snd_pmac *chip)
{
int i, err;
- pmac_daca_t *mix;
+ struct pmac_daca *mix;
#ifdef CONFIG_KMOD
if (current->fs->root)
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index df073a05b5d7..6058c2dd1b7f 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -32,7 +32,7 @@
* we have to keep a static variable here since i2c attach_adapter
* callback cannot pass a private data.
*/
-static pmac_keywest_t *keywest_ctx;
+static struct pmac_keywest *keywest_ctx;
#define I2C_DRIVERID_KEYWEST 0xFEBA
@@ -41,9 +41,10 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter);
static int keywest_detach_client(struct i2c_client *client);
struct i2c_driver keywest_driver = {
- .name = "PMac Keywest Audio",
+ .driver = {
+ .name = "PMac Keywest Audio",
+ },
.id = I2C_DRIVERID_KEYWEST,
- .flags = I2C_DF_NOTIFY,
.attach_adapter = &keywest_attach_adapter,
.detach_client = &keywest_detach_client,
};
@@ -106,7 +107,7 @@ static int keywest_detach_client(struct i2c_client *client)
}
/* exported */
-void snd_pmac_keywest_cleanup(pmac_keywest_t *i2c)
+void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
{
if (keywest_ctx && keywest_ctx == i2c) {
i2c_del_driver(&keywest_driver);
@@ -126,7 +127,7 @@ int __init snd_pmac_tumbler_post_init(void)
}
/* exported */
-int __init snd_pmac_keywest_init(pmac_keywest_t *i2c)
+int __init snd_pmac_keywest_init(struct pmac_keywest *i2c)
{
int err;
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index db2f1815fc30..a642e4cfcf45 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -36,14 +36,6 @@
#include <asm/pci-bridge.h>
-#ifdef CONFIG_PM
-static int snd_pmac_register_sleep_notifier(pmac_t *chip);
-static int snd_pmac_unregister_sleep_notifier(pmac_t *chip);
-static int snd_pmac_suspend(snd_card_t *card, pm_message_t state);
-static int snd_pmac_resume(snd_card_t *card);
-#endif
-
-
/* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */
static int awacs_freqs[8] = {
44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
@@ -56,7 +48,7 @@ static int tumbler_freqs[1] = {
/*
* allocate DBDMA command arrays
*/
-static int snd_pmac_dbdma_alloc(pmac_t *chip, pmac_dbdma_t *rec, int size)
+static int snd_pmac_dbdma_alloc(struct snd_pmac *chip, struct pmac_dbdma *rec, int size)
{
unsigned int rsize = sizeof(struct dbdma_cmd) * (size + 1);
@@ -72,7 +64,7 @@ static int snd_pmac_dbdma_alloc(pmac_t *chip, pmac_dbdma_t *rec, int size)
return 0;
}
-static void snd_pmac_dbdma_free(pmac_t *chip, pmac_dbdma_t *rec)
+static void snd_pmac_dbdma_free(struct snd_pmac *chip, struct pmac_dbdma *rec)
{
if (rec) {
unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1);
@@ -90,7 +82,7 @@ static void snd_pmac_dbdma_free(pmac_t *chip, pmac_dbdma_t *rec)
* look up frequency table
*/
-unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate)
+unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate)
{
int i, ok, found;
@@ -119,8 +111,8 @@ static inline int another_stream(int stream)
/*
* allocate buffers
*/
-static int snd_pmac_pcm_hw_params(snd_pcm_substream_t *subs,
- snd_pcm_hw_params_t *hw_params)
+static int snd_pmac_pcm_hw_params(struct snd_pcm_substream *subs,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params));
}
@@ -128,7 +120,7 @@ static int snd_pmac_pcm_hw_params(snd_pcm_substream_t *subs,
/*
* release buffers
*/
-static int snd_pmac_pcm_hw_free(snd_pcm_substream_t *subs)
+static int snd_pmac_pcm_hw_free(struct snd_pcm_substream *subs)
{
snd_pcm_lib_free_pages(subs);
return 0;
@@ -137,7 +129,7 @@ static int snd_pmac_pcm_hw_free(snd_pcm_substream_t *subs)
/*
* get a stream of the opposite direction
*/
-static pmac_stream_t *snd_pmac_get_stream(pmac_t *chip, int stream)
+static struct pmac_stream *snd_pmac_get_stream(struct snd_pmac *chip, int stream)
{
switch (stream) {
case SNDRV_PCM_STREAM_PLAYBACK:
@@ -154,7 +146,7 @@ static pmac_stream_t *snd_pmac_get_stream(pmac_t *chip, int stream)
* wait while run status is on
*/
static inline void
-snd_pmac_wait_ack(pmac_stream_t *rec)
+snd_pmac_wait_ack(struct pmac_stream *rec)
{
int timeout = 50000;
while ((in_le32(&rec->dma->status) & RUN) && timeout-- > 0)
@@ -165,7 +157,7 @@ snd_pmac_wait_ack(pmac_stream_t *rec)
* set the format and rate to the chip.
* call the lowlevel function if defined (e.g. for AWACS).
*/
-static void snd_pmac_pcm_set_format(pmac_t *chip)
+static void snd_pmac_pcm_set_format(struct snd_pmac *chip)
{
/* set up frequency and format */
out_le32(&chip->awacs->control, chip->control_mask | (chip->rate_index << 8));
@@ -177,7 +169,7 @@ static void snd_pmac_pcm_set_format(pmac_t *chip)
/*
* stop the DMA transfer
*/
-static inline void snd_pmac_dma_stop(pmac_stream_t *rec)
+static inline void snd_pmac_dma_stop(struct pmac_stream *rec)
{
out_le32(&rec->dma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
snd_pmac_wait_ack(rec);
@@ -186,7 +178,7 @@ static inline void snd_pmac_dma_stop(pmac_stream_t *rec)
/*
* set the command pointer address
*/
-static inline void snd_pmac_dma_set_command(pmac_stream_t *rec, pmac_dbdma_t *cmd)
+static inline void snd_pmac_dma_set_command(struct pmac_stream *rec, struct pmac_dbdma *cmd)
{
out_le32(&rec->dma->cmdptr, cmd->addr);
}
@@ -194,7 +186,7 @@ static inline void snd_pmac_dma_set_command(pmac_stream_t *rec, pmac_dbdma_t *cm
/*
* start the DMA
*/
-static inline void snd_pmac_dma_run(pmac_stream_t *rec, int status)
+static inline void snd_pmac_dma_run(struct pmac_stream *rec, int status)
{
out_le32(&rec->dma->control, status | (status << 16));
}
@@ -203,14 +195,14 @@ static inline void snd_pmac_dma_run(pmac_stream_t *rec, int status)
/*
* prepare playback/capture stream
*/
-static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream_t *subs)
+static int snd_pmac_pcm_prepare(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs)
{
int i;
volatile struct dbdma_cmd __iomem *cp;
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
int rate_index;
long offset;
- pmac_stream_t *astr;
+ struct pmac_stream *astr;
rec->dma_size = snd_pcm_lib_buffer_bytes(subs);
rec->period_size = snd_pcm_lib_period_bytes(subs);
@@ -267,8 +259,8 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr
/*
* PCM trigger/stop
*/
-static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
- snd_pcm_substream_t *subs, int cmd)
+static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec,
+ struct snd_pcm_substream *subs, int cmd)
{
volatile struct dbdma_cmd __iomem *cp;
int i, command;
@@ -314,8 +306,9 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
* return the current pointer
*/
inline
-static snd_pcm_uframes_t snd_pmac_pcm_pointer(pmac_t *chip, pmac_stream_t *rec,
- snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t snd_pmac_pcm_pointer(struct snd_pmac *chip,
+ struct pmac_stream *rec,
+ struct snd_pcm_substream *subs)
{
int count = 0;
@@ -338,22 +331,22 @@ static snd_pcm_uframes_t snd_pmac_pcm_pointer(pmac_t *chip, pmac_stream_t *rec,
* playback
*/
-static int snd_pmac_playback_prepare(snd_pcm_substream_t *subs)
+static int snd_pmac_playback_prepare(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_prepare(chip, &chip->playback, subs);
}
-static int snd_pmac_playback_trigger(snd_pcm_substream_t *subs,
+static int snd_pmac_playback_trigger(struct snd_pcm_substream *subs,
int cmd)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_trigger(chip, &chip->playback, subs, cmd);
}
-static snd_pcm_uframes_t snd_pmac_playback_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t snd_pmac_playback_pointer(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_pointer(chip, &chip->playback, subs);
}
@@ -362,22 +355,22 @@ static snd_pcm_uframes_t snd_pmac_playback_pointer(snd_pcm_substream_t *subs)
* capture
*/
-static int snd_pmac_capture_prepare(snd_pcm_substream_t *subs)
+static int snd_pmac_capture_prepare(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_prepare(chip, &chip->capture, subs);
}
-static int snd_pmac_capture_trigger(snd_pcm_substream_t *subs,
+static int snd_pmac_capture_trigger(struct snd_pcm_substream *subs,
int cmd)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_trigger(chip, &chip->capture, subs, cmd);
}
-static snd_pcm_uframes_t snd_pmac_capture_pointer(snd_pcm_substream_t *subs)
+static snd_pcm_uframes_t snd_pmac_capture_pointer(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_pointer(chip, &chip->capture, subs);
}
@@ -385,7 +378,7 @@ static snd_pcm_uframes_t snd_pmac_capture_pointer(snd_pcm_substream_t *subs)
/*
* update playback/capture pointer from interrupts
*/
-static void snd_pmac_pcm_update(pmac_t *chip, pmac_stream_t *rec)
+static void snd_pmac_pcm_update(struct snd_pmac *chip, struct pmac_stream *rec)
{
volatile struct dbdma_cmd __iomem *cp;
int c;
@@ -421,7 +414,7 @@ static void snd_pmac_pcm_update(pmac_t *chip, pmac_stream_t *rec)
* hw info
*/
-static snd_pcm_hardware_t snd_pmac_playback =
+static struct snd_pcm_hardware snd_pmac_playback =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
@@ -440,7 +433,7 @@ static snd_pcm_hardware_t snd_pmac_playback =
.periods_max = PMAC_MAX_FRAGS,
};
-static snd_pcm_hardware_t snd_pmac_capture =
+static struct snd_pcm_hardware snd_pmac_capture =
{
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
@@ -461,11 +454,11 @@ static snd_pcm_hardware_t snd_pmac_capture =
#if 0 // NYI
-static int snd_pmac_hw_rule_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pmac_hw_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- pmac_t *chip = rule->private;
- pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]);
+ struct snd_pmac *chip = rule->private;
+ struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]);
int i, freq_table[8], num_freqs;
if (! rec)
@@ -480,11 +473,11 @@ static int snd_pmac_hw_rule_rate(snd_pcm_hw_params_t *params,
num_freqs, freq_table, 0);
}
-static int snd_pmac_hw_rule_format(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int snd_pmac_hw_rule_format(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- pmac_t *chip = rule->private;
- pmac_stream_t *rec = snd_pmac_get_stream(chip, rule->deps[0]);
+ struct snd_pmac *chip = rule->private;
+ struct pmac_stream *rec = snd_pmac_get_stream(chip, rule->deps[0]);
if (! rec)
return -EINVAL;
@@ -493,9 +486,10 @@ static int snd_pmac_hw_rule_format(snd_pcm_hw_params_t *params,
}
#endif // NYI
-static int snd_pmac_pcm_open(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream_t *subs)
+static int snd_pmac_pcm_open(struct snd_pmac *chip, struct pmac_stream *rec,
+ struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
int i, j, fflags;
static int typical_freqs[] = {
44100,
@@ -565,9 +559,10 @@ static int snd_pmac_pcm_open(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream
return 0;
}
-static int snd_pmac_pcm_close(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream_t *subs)
+static int snd_pmac_pcm_close(struct snd_pmac *chip, struct pmac_stream *rec,
+ struct snd_pcm_substream *subs)
{
- pmac_stream_t *astr;
+ struct pmac_stream *astr;
snd_pmac_dma_stop(rec);
@@ -582,32 +577,32 @@ static int snd_pmac_pcm_close(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substrea
return 0;
}
-static int snd_pmac_playback_open(snd_pcm_substream_t *subs)
+static int snd_pmac_playback_open(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
subs->runtime->hw = snd_pmac_playback;
return snd_pmac_pcm_open(chip, &chip->playback, subs);
}
-static int snd_pmac_capture_open(snd_pcm_substream_t *subs)
+static int snd_pmac_capture_open(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
subs->runtime->hw = snd_pmac_capture;
return snd_pmac_pcm_open(chip, &chip->capture, subs);
}
-static int snd_pmac_playback_close(snd_pcm_substream_t *subs)
+static int snd_pmac_playback_close(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_close(chip, &chip->playback, subs);
}
-static int snd_pmac_capture_close(snd_pcm_substream_t *subs)
+static int snd_pmac_capture_close(struct snd_pcm_substream *subs)
{
- pmac_t *chip = snd_pcm_substream_chip(subs);
+ struct snd_pmac *chip = snd_pcm_substream_chip(subs);
return snd_pmac_pcm_close(chip, &chip->capture, subs);
}
@@ -615,7 +610,7 @@ static int snd_pmac_capture_close(snd_pcm_substream_t *subs)
/*
*/
-static snd_pcm_ops_t snd_pmac_playback_ops = {
+static struct snd_pcm_ops snd_pmac_playback_ops = {
.open = snd_pmac_playback_open,
.close = snd_pmac_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -626,7 +621,7 @@ static snd_pcm_ops_t snd_pmac_playback_ops = {
.pointer = snd_pmac_playback_pointer,
};
-static snd_pcm_ops_t snd_pmac_capture_ops = {
+static struct snd_pcm_ops snd_pmac_capture_ops = {
.open = snd_pmac_capture_open,
.close = snd_pmac_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -637,14 +632,9 @@ static snd_pcm_ops_t snd_pmac_capture_ops = {
.pointer = snd_pmac_capture_pointer,
};
-static void pmac_pcm_free(snd_pcm_t *pcm)
+int __init snd_pmac_pcm_new(struct snd_pmac *chip)
{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int __init snd_pmac_pcm_new(pmac_t *chip)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
int num_captures = 1;
@@ -659,7 +649,6 @@ int __init snd_pmac_pcm_new(pmac_t *chip)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_pmac_capture_ops);
pcm->private_data = chip;
- pcm->private_free = pmac_pcm_free;
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
@@ -682,7 +671,7 @@ int __init snd_pmac_pcm_new(pmac_t *chip)
}
-static void snd_pmac_dbdma_reset(pmac_t *chip)
+static void snd_pmac_dbdma_reset(struct snd_pmac *chip)
{
out_le32(&chip->playback.dma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
snd_pmac_wait_ack(&chip->playback);
@@ -694,9 +683,9 @@ static void snd_pmac_dbdma_reset(pmac_t *chip)
/*
* handling beep
*/
-void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed)
+void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed)
{
- pmac_stream_t *rec = &chip->playback;
+ struct pmac_stream *rec = &chip->playback;
snd_pmac_dma_stop(rec);
st_le16(&chip->extra_dma.cmds->req_count, bytes);
@@ -712,7 +701,7 @@ void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int sp
snd_pmac_dma_run(rec, RUN);
}
-void snd_pmac_beep_dma_stop(pmac_t *chip)
+void snd_pmac_beep_dma_stop(struct snd_pmac *chip)
{
snd_pmac_dma_stop(&chip->playback);
st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
@@ -726,7 +715,7 @@ void snd_pmac_beep_dma_stop(pmac_t *chip)
static irqreturn_t
snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
{
- pmac_t *chip = devid;
+ struct snd_pmac *chip = devid;
snd_pmac_pcm_update(chip, &chip->playback);
return IRQ_HANDLED;
}
@@ -735,7 +724,7 @@ snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
static irqreturn_t
snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
{
- pmac_t *chip = devid;
+ struct snd_pmac *chip = devid;
snd_pmac_pcm_update(chip, &chip->capture);
return IRQ_HANDLED;
}
@@ -744,7 +733,7 @@ snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
static irqreturn_t
snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
{
- pmac_t *chip = devid;
+ struct snd_pmac *chip = devid;
int ctrl = in_le32(&chip->awacs->control);
/*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/
@@ -767,7 +756,7 @@ snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
/*
* a wrapper to feature call for compatibility
*/
-static void snd_pmac_sound_feature(pmac_t *chip, int enable)
+static void snd_pmac_sound_feature(struct snd_pmac *chip, int enable)
{
if (ppc_md.feature_call)
ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable);
@@ -777,7 +766,7 @@ static void snd_pmac_sound_feature(pmac_t *chip, int enable)
* release resources
*/
-static int snd_pmac_free(pmac_t *chip)
+static int snd_pmac_free(struct snd_pmac *chip)
{
/* stop sounds */
if (chip->initialized) {
@@ -787,9 +776,6 @@ static int snd_pmac_free(pmac_t *chip)
}
snd_pmac_sound_feature(chip, 0);
-#ifdef CONFIG_PM
- snd_pmac_unregister_sleep_notifier(chip);
-#endif
/* clean up mixer if any */
if (chip->mixer_free)
@@ -817,21 +803,17 @@ static int snd_pmac_free(pmac_t *chip)
iounmap(chip->playback.dma);
if (chip->capture.dma)
iounmap(chip->capture.dma);
-#ifndef CONFIG_PPC64
+
if (chip->node) {
int i;
-
for (i = 0; i < 3; i++) {
- if (chip->of_requested & (1 << i)) {
- if (chip->is_k2)
- release_OF_resource(chip->node->parent,
- i);
- else
- release_OF_resource(chip->node, i);
- }
+ if (chip->requested & (1 << i))
+ release_mem_region(chip->rsrc[i].start,
+ chip->rsrc[i].end -
+ chip->rsrc[i].start + 1);
}
}
-#endif /* CONFIG_PPC64 */
+
if (chip->pdev)
pci_dev_put(chip->pdev);
kfree(chip);
@@ -842,9 +824,9 @@ static int snd_pmac_free(pmac_t *chip)
/*
* free the device
*/
-static int snd_pmac_dev_free(snd_device_t *device)
+static int snd_pmac_dev_free(struct snd_device *device)
{
- pmac_t *chip = device->device_data;
+ struct snd_pmac *chip = device->device_data;
return snd_pmac_free(chip);
}
@@ -853,7 +835,7 @@ static int snd_pmac_dev_free(snd_device_t *device)
* check the machine support byteswap (little-endian)
*/
-static void __init detect_byte_swap(pmac_t *chip)
+static void __init detect_byte_swap(struct snd_pmac *chip)
{
struct device_node *mio;
@@ -879,7 +861,7 @@ static void __init detect_byte_swap(pmac_t *chip)
/*
* detect a sound chip
*/
-static int __init snd_pmac_detect(pmac_t *chip)
+static int __init snd_pmac_detect(struct snd_pmac *chip)
{
struct device_node *sound = NULL;
unsigned int *prop, l;
@@ -987,11 +969,11 @@ static int __init snd_pmac_detect(pmac_t *chip)
* single frequency until proper i2s control is implemented
*/
switch(layout_id) {
- case 0x48:
- case 0x46:
- case 0x33:
- case 0x29:
case 0x24:
+ case 0x29:
+ case 0x33:
+ case 0x46:
+ case 0x48:
case 0x50:
case 0x5c:
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
@@ -1005,6 +987,11 @@ static int __init snd_pmac_detect(pmac_t *chip)
chip->can_byte_swap = 0; /* FIXME: check this */
chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
break;
+ default:
+ printk(KERN_ERR "snd: Unknown layout ID 0x%x\n",
+ layout_id);
+ return -ENODEV;
+
}
}
prop = (unsigned int *)get_property(sound, "device-id", NULL);
@@ -1067,8 +1054,8 @@ static int __init snd_pmac_detect(pmac_t *chip)
/*
* exported - boolean info callbacks for ease of programming
*/
-int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -1077,8 +1064,8 @@ int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol,
return 0;
}
-int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
+int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1091,16 +1078,18 @@ int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol,
/*
* auto-mute
*/
-static int pmac_auto_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pmac_auto_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = chip->auto_mute;
return 0;
}
-static int pmac_auto_mute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pmac_auto_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
if (ucontrol->value.integer.value[0] != chip->auto_mute) {
chip->auto_mute = ucontrol->value.integer.value[0];
if (chip->update_automute)
@@ -1110,9 +1099,10 @@ static int pmac_auto_mute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static int pmac_hp_detect_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
if (chip->detect_headphone)
ucontrol->value.integer.value[0] = chip->detect_headphone(chip);
else
@@ -1120,7 +1110,7 @@ static int pmac_hp_detect_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static snd_kcontrol_new_t auto_mute_controls[] __initdata = {
+static struct snd_kcontrol_new auto_mute_controls[] __initdata = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Auto Mute Switch",
.info = snd_pmac_boolean_mono_info,
@@ -1135,7 +1125,7 @@ static snd_kcontrol_new_t auto_mute_controls[] __initdata = {
},
};
-int __init snd_pmac_add_automute(pmac_t *chip)
+int __init snd_pmac_add_automute(struct snd_pmac *chip)
{
int err;
chip->auto_mute = 1;
@@ -1152,13 +1142,13 @@ int __init snd_pmac_add_automute(pmac_t *chip)
/*
* create and detect a pmac chip record
*/
-int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
+int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
{
- pmac_t *chip;
+ struct snd_pmac *chip;
struct device_node *np;
int i, err;
unsigned long ctrl_addr, txdma_addr, rxdma_addr;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_pmac_dev_free,
};
@@ -1186,46 +1176,69 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
}
np = chip->node;
+ chip->requested = 0;
if (chip->is_k2) {
- if (np->parent->n_addrs < 2 || np->n_intrs < 3) {
+ static char *rnames[] = {
+ "Sound Control", "Sound DMA" };
+ if (np->n_intrs < 3) {
err = -ENODEV;
goto __error;
}
- for (i = 0; i < 2; i++) {
-#ifndef CONFIG_PPC64
- static char *name[2] = { "- Control", "- DMA" };
- if (! request_OF_resource(np->parent, i, name[i])) {
- snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i);
+ for (i = 0; i < 2; i ++) {
+ if (of_address_to_resource(np->parent, i,
+ &chip->rsrc[i])) {
+ printk(KERN_ERR "snd: can't translate rsrc "
+ " %d (%s)\n", i, rnames[i]);
err = -ENODEV;
goto __error;
}
- chip->of_requested |= (1 << i);
-#endif /* CONFIG_PPC64 */
- ctrl_addr = np->parent->addrs[0].address;
- txdma_addr = np->parent->addrs[1].address;
- rxdma_addr = txdma_addr + 0x100;
+ if (request_mem_region(chip->rsrc[i].start,
+ chip->rsrc[i].end -
+ chip->rsrc[i].start + 1,
+ rnames[i]) == NULL) {
+ printk(KERN_ERR "snd: can't request rsrc "
+ " %d (%s: 0x%08lx:%08lx)\n",
+ i, rnames[i], chip->rsrc[i].start,
+ chip->rsrc[i].end);
+ err = -ENODEV;
+ goto __error;
+ }
+ chip->requested |= (1 << i);
}
-
+ ctrl_addr = chip->rsrc[0].start;
+ txdma_addr = chip->rsrc[1].start;
+ rxdma_addr = txdma_addr + 0x100;
} else {
- if (np->n_addrs < 3 || np->n_intrs < 3) {
+ static char *rnames[] = {
+ "Sound Control", "Sound Tx DMA", "Sound Rx DMA" };
+ if (np->n_intrs < 3) {
err = -ENODEV;
goto __error;
}
-
- for (i = 0; i < 3; i++) {
-#ifndef CONFIG_PPC64
- static char *name[3] = { "- Control", "- Tx DMA", "- Rx DMA" };
- if (! request_OF_resource(np, i, name[i])) {
- snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i);
+ for (i = 0; i < 3; i ++) {
+ if (of_address_to_resource(np->parent, i,
+ &chip->rsrc[i])) {
+ printk(KERN_ERR "snd: can't translate rsrc "
+ " %d (%s)\n", i, rnames[i]);
+ err = -ENODEV;
+ goto __error;
+ }
+ if (request_mem_region(chip->rsrc[i].start,
+ chip->rsrc[i].end -
+ chip->rsrc[i].start + 1,
+ rnames[i]) == NULL) {
+ printk(KERN_ERR "snd: can't request rsrc "
+ " %d (%s: 0x%08lx:%08lx)\n",
+ i, rnames[i], chip->rsrc[i].start,
+ chip->rsrc[i].end);
err = -ENODEV;
goto __error;
}
- chip->of_requested |= (1 << i);
-#endif /* CONFIG_PPC64 */
- ctrl_addr = np->addrs[0].address;
- txdma_addr = np->addrs[1].address;
- rxdma_addr = np->addrs[2].address;
+ chip->requested |= (1 << i);
}
+ ctrl_addr = chip->rsrc[0].start;
+ txdma_addr = chip->rsrc[1].start;
+ rxdma_addr = chip->rsrc[2].start;
}
chip->awacs = ioremap(ctrl_addr, 0x1000);
@@ -1277,9 +1290,11 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
} else if (chip->is_pbook_G3) {
struct device_node* mio;
for (mio = chip->node->parent; mio; mio = mio->parent) {
- if (strcmp(mio->name, "mac-io") == 0
- && mio->n_addrs > 0) {
- chip->macio_base = ioremap(mio->addrs[0].address, 0x40);
+ if (strcmp(mio->name, "mac-io") == 0) {
+ struct resource r;
+ if (of_address_to_resource(mio, 0, &r) == 0)
+ chip->macio_base =
+ ioremap(r.start, 0x40);
break;
}
}
@@ -1298,12 +1313,6 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
/* Reset dbdma channels */
snd_pmac_dbdma_reset(chip);
-#ifdef CONFIG_PM
- /* add sleep notifier */
- if (! snd_pmac_register_sleep_notifier(chip))
- snd_card_set_pm_callback(chip->card, snd_pmac_suspend, snd_pmac_resume, chip);
-#endif
-
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
goto __error;
@@ -1328,11 +1337,11 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
* Save state when going to sleep, restore it afterwards.
*/
-static int snd_pmac_suspend(snd_card_t *card, pm_message_t state)
+void snd_pmac_suspend(struct snd_pmac *chip)
{
- pmac_t *chip = card->pm_private_data;
unsigned long flags;
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
if (chip->suspend)
chip->suspend(chip);
snd_pcm_suspend_all(chip->pcm);
@@ -1346,22 +1355,18 @@ static int snd_pmac_suspend(snd_card_t *card, pm_message_t state)
if (chip->rx_irq >= 0)
disable_irq(chip->rx_irq);
snd_pmac_sound_feature(chip, 0);
- return 0;
}
-static int snd_pmac_resume(snd_card_t *card)
+void snd_pmac_resume(struct snd_pmac *chip)
{
- pmac_t *chip = card->pm_private_data;
-
snd_pmac_sound_feature(chip, 1);
if (chip->resume)
chip->resume(chip);
/* enable CD sound input */
- if (chip->macio_base && chip->is_pbook_G3) {
+ if (chip->macio_base && chip->is_pbook_G3)
out_8(chip->macio_base + 0x37, 3);
- } else if (chip->is_pbook_3400) {
+ else if (chip->is_pbook_3400)
in_8(chip->latch_base + 0x190);
- }
snd_pmac_pcm_set_format(chip);
@@ -1372,53 +1377,7 @@ static int snd_pmac_resume(snd_card_t *card)
if (chip->rx_irq >= 0)
enable_irq(chip->rx_irq);
- return 0;
-}
-
-/* the chip is stored statically by snd_pmac_register_sleep_notifier
- * because we can't have any private data for notify callback.
- */
-static pmac_t *sleeping_pmac = NULL;
-
-static int snd_pmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
- pmac_t *chip;
-
- chip = sleeping_pmac;
- if (! chip)
- return 0;
-
- switch (when) {
- case PBOOK_SLEEP_NOW:
- snd_pmac_suspend(chip->card, PMSG_SUSPEND);
- break;
- case PBOOK_WAKE:
- snd_pmac_resume(chip->card);
- break;
- }
- return PBOOK_SLEEP_OK;
-}
-
-static struct pmu_sleep_notifier snd_pmac_sleep_notifier = {
- snd_pmac_sleep_notify, SLEEP_LEVEL_SOUND,
-};
-
-static int __init snd_pmac_register_sleep_notifier(pmac_t *chip)
-{
- /* should be protected here.. */
- snd_assert(! sleeping_pmac, return -EBUSY);
- sleeping_pmac = chip;
- pmu_register_sleep_notifier(&snd_pmac_sleep_notifier);
- return 0;
-}
-
-static int snd_pmac_unregister_sleep_notifier(pmac_t *chip)
-{
- /* should be protected here.. */
- snd_assert(sleeping_pmac == chip, return -ENODEV);
- pmu_unregister_sleep_notifier(&snd_pmac_sleep_notifier);
- sleeping_pmac = NULL;
- return 0;
+ snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
}
#endif /* CONFIG_PM */
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index bfff788e9847..3a9bd4dbb9a6 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -47,18 +47,9 @@
#define PMAC_SUPPORT_AUTOMUTE
/*
- * typedefs
- */
-typedef struct snd_pmac pmac_t;
-typedef struct snd_pmac_stream pmac_stream_t;
-typedef struct snd_pmac_beep pmac_beep_t;
-typedef struct snd_pmac_dbdma pmac_dbdma_t;
-
-
-/*
* DBDMA space
*/
-struct snd_pmac_dbdma {
+struct pmac_dbdma {
dma_addr_t dma_base;
dma_addr_t addr;
struct dbdma_cmd __iomem *cmds;
@@ -69,7 +60,7 @@ struct snd_pmac_dbdma {
/*
* playback/capture stream
*/
-struct snd_pmac_stream {
+struct pmac_stream {
int running; /* boolean */
int stream; /* PLAYBACK/CAPTURE */
@@ -79,10 +70,10 @@ struct snd_pmac_stream {
int buffer_size; /* in kbytes */
int nperiods, cur_period;
- pmac_dbdma_t cmd;
+ struct pmac_dbdma cmd;
volatile struct dbdma_regs __iomem *dma;
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
unsigned int cur_freqs; /* currently available frequencies */
unsigned int cur_formats; /* currently available formats */
@@ -98,7 +89,7 @@ enum snd_pmac_model {
};
struct snd_pmac {
- snd_card_t *card;
+ struct snd_card *card;
/* h/w info */
struct device_node *node;
@@ -122,7 +113,8 @@ struct snd_pmac {
unsigned int initialized : 1;
unsigned int feature_is_set : 1;
- unsigned int of_requested;
+ unsigned int requested;
+ struct resource rsrc[3];
int num_freqs;
int *freq_table;
@@ -140,75 +132,80 @@ struct snd_pmac {
unsigned char __iomem *latch_base;
unsigned char __iomem *macio_base;
- pmac_stream_t playback;
- pmac_stream_t capture;
+ struct pmac_stream playback;
+ struct pmac_stream capture;
- pmac_dbdma_t extra_dma;
+ struct pmac_dbdma extra_dma;
int irq, tx_irq, rx_irq;
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
- pmac_beep_t *beep;
+ struct pmac_beep *beep;
unsigned int control_mask; /* control mask */
/* mixer stuffs */
void *mixer_data;
- void (*mixer_free)(pmac_t *);
- snd_kcontrol_t *master_sw_ctl;
- snd_kcontrol_t *speaker_sw_ctl;
- snd_kcontrol_t *drc_sw_ctl; /* only used for tumbler -ReneR */
- snd_kcontrol_t *hp_detect_ctl;
- snd_kcontrol_t *lineout_sw_ctl;
+ void (*mixer_free)(struct snd_pmac *);
+ struct snd_kcontrol *master_sw_ctl;
+ struct snd_kcontrol *speaker_sw_ctl;
+ struct snd_kcontrol *drc_sw_ctl; /* only used for tumbler -ReneR */
+ struct snd_kcontrol *hp_detect_ctl;
+ struct snd_kcontrol *lineout_sw_ctl;
/* lowlevel callbacks */
- void (*set_format)(pmac_t *chip);
- void (*update_automute)(pmac_t *chip, int do_notify);
- int (*detect_headphone)(pmac_t *chip);
+ void (*set_format)(struct snd_pmac *chip);
+ void (*update_automute)(struct snd_pmac *chip, int do_notify);
+ int (*detect_headphone)(struct snd_pmac *chip);
#ifdef CONFIG_PM
- void (*suspend)(pmac_t *chip);
- void (*resume)(pmac_t *chip);
+ void (*suspend)(struct snd_pmac *chip);
+ void (*resume)(struct snd_pmac *chip);
#endif
};
/* exported functions */
-int snd_pmac_new(snd_card_t *card, pmac_t **chip_return);
-int snd_pmac_pcm_new(pmac_t *chip);
-int snd_pmac_attach_beep(pmac_t *chip);
-void snd_pmac_detach_beep(pmac_t *chip);
-void snd_pmac_beep_stop(pmac_t *chip);
-unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate);
+int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return);
+int snd_pmac_pcm_new(struct snd_pmac *chip);
+int snd_pmac_attach_beep(struct snd_pmac *chip);
+void snd_pmac_detach_beep(struct snd_pmac *chip);
+void snd_pmac_beep_stop(struct snd_pmac *chip);
+unsigned int snd_pmac_rate_index(struct snd_pmac *chip, struct pmac_stream *rec, unsigned int rate);
-void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed);
-void snd_pmac_beep_dma_stop(pmac_t *chip);
+void snd_pmac_beep_dma_start(struct snd_pmac *chip, int bytes, unsigned long addr, int speed);
+void snd_pmac_beep_dma_stop(struct snd_pmac *chip);
+
+#ifdef CONFIG_PM
+void snd_pmac_suspend(struct snd_pmac *chip);
+void snd_pmac_resume(struct snd_pmac *chip);
+#endif
/* initialize mixer */
-int snd_pmac_awacs_init(pmac_t *chip);
-int snd_pmac_burgundy_init(pmac_t *chip);
-int snd_pmac_daca_init(pmac_t *chip);
-int snd_pmac_tumbler_init(pmac_t *chip);
+int snd_pmac_awacs_init(struct snd_pmac *chip);
+int snd_pmac_burgundy_init(struct snd_pmac *chip);
+int snd_pmac_daca_init(struct snd_pmac *chip);
+int snd_pmac_tumbler_init(struct snd_pmac *chip);
int snd_pmac_tumbler_post_init(void);
-int snd_pmac_toonie_init(pmac_t *chip);
+int snd_pmac_toonie_init(struct snd_pmac *chip);
/* i2c functions */
-typedef struct snd_pmac_keywest {
+struct pmac_keywest {
int addr;
struct i2c_client *client;
int id;
- int (*init_client)(struct snd_pmac_keywest *i2c);
+ int (*init_client)(struct pmac_keywest *i2c);
char *name;
-} pmac_keywest_t;
+};
-int snd_pmac_keywest_init(pmac_keywest_t *i2c);
-void snd_pmac_keywest_cleanup(pmac_keywest_t *i2c);
+int snd_pmac_keywest_init(struct pmac_keywest *i2c);
+void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c);
/* misc */
-int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
-int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
+int snd_pmac_boolean_stereo_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
+int snd_pmac_boolean_mono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_pmac_add_automute(pmac_t *chip);
+int snd_pmac_add_automute(struct snd_pmac *chip);
#endif /* __PMAC_H */
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index a6d8cbf4064f..f4902a219e50 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -20,6 +20,8 @@
#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -44,20 +46,16 @@ MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip.");
module_param(enable_beep, bool, 0444);
MODULE_PARM_DESC(enable_beep, "Enable beep using PCM.");
+static struct platform_device *device;
-/*
- * card entry
- */
-
-static snd_card_t *snd_pmac_card = NULL;
/*
*/
-static int __init snd_pmac_probe(void)
+static int __init snd_pmac_probe(struct platform_device *devptr)
{
- snd_card_t *card;
- pmac_t *chip;
+ struct snd_card *card;
+ struct snd_pmac *chip;
char *name_ext;
int err;
@@ -67,6 +65,7 @@ static int __init snd_pmac_probe(void)
if ((err = snd_pmac_new(card, &chip)) < 0)
goto __error;
+ card->private_data = chip;
switch (chip->model) {
case PMAC_BURGUNDY:
@@ -131,13 +130,12 @@ 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;
+ snd_card_set_dev(card, &devptr->dev);
if ((err = snd_card_register(card)) < 0)
goto __error;
- snd_pmac_card = card;
+ platform_set_drvdata(devptr, card);
return 0;
__error:
@@ -146,23 +144,62 @@ __error:
}
-/*
- * MODULE stuff
- */
+static int __devexit snd_pmac_remove(struct platform_device *devptr)
+{
+ snd_card_free(platform_get_drvdata(devptr));
+ platform_set_drvdata(devptr, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int snd_pmac_driver_suspend(struct platform_device *devptr, pm_message_t state)
+{
+ struct snd_card *card = platform_get_drvdata(devptr);
+ snd_pmac_suspend(card->private_data);
+ return 0;
+}
+
+static int snd_pmac_driver_resume(struct platform_device *devptr)
+{
+ struct snd_card *card = platform_get_drvdata(devptr);
+ snd_pmac_resume(card->private_data);
+ return 0;
+}
+#endif
+
+#define SND_PMAC_DRIVER "snd_powermac"
+
+static struct platform_driver snd_pmac_driver = {
+ .probe = snd_pmac_probe,
+ .remove = __devexit_p(snd_pmac_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_pmac_driver_suspend,
+ .resume = snd_pmac_driver_resume,
+#endif
+ .driver = {
+ .name = SND_PMAC_DRIVER
+ },
+};
static int __init alsa_card_pmac_init(void)
{
int err;
- if ((err = snd_pmac_probe()) < 0)
+
+ if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
return err;
+ device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0);
+ if (IS_ERR(device)) {
+ platform_driver_unregister(&snd_pmac_driver);
+ return PTR_ERR(device);
+ }
return 0;
}
static void __exit alsa_card_pmac_exit(void)
{
- if (snd_pmac_card)
- snd_card_free(snd_pmac_card);
+ platform_device_unregister(device);
+ platform_driver_unregister(&snd_pmac_driver);
}
module_init(alsa_card_pmac_init)
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
index 082bc4babab5..053b8f24e4dc 100644
--- a/sound/ppc/toonie.c
+++ b/sound/ppc/toonie.c
@@ -101,10 +101,10 @@ static int read_audio_gpio(struct pmac_gpio *gp)
enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP };
-static int toonie_get_mute_switch(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
struct pmac_toonie *mix = chip->mixer_data;
struct pmac_gpio *gp;
@@ -124,10 +124,10 @@ static int toonie_get_mute_switch(snd_kcontrol_t *kcontrol,
return 0;
}
-static int toonie_put_mute_switch(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
+static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
struct pmac_toonie *mix = chip->mixer_data;
struct pmac_gpio *gp;
int val;
@@ -156,7 +156,7 @@ static int toonie_put_mute_switch(snd_kcontrol_t *kcontrol,
return 0;
}
-static snd_kcontrol_new_t toonie_hp_sw __initdata = {
+static struct snd_kcontrol_new toonie_hp_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -164,7 +164,7 @@ static snd_kcontrol_new_t toonie_hp_sw __initdata = {
.put = toonie_put_mute_switch,
.private_value = TOONIE_MUTE_HP,
};
-static snd_kcontrol_new_t toonie_speaker_sw __initdata = {
+static struct snd_kcontrol_new toonie_speaker_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PC Speaker Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -176,7 +176,7 @@ static snd_kcontrol_new_t toonie_speaker_sw __initdata = {
/*
* auto-mute stuffs
*/
-static int toonie_detect_headphone(pmac_t *chip)
+static int toonie_detect_headphone(struct snd_pmac *chip)
{
struct pmac_toonie *mix = chip->mixer_data;
int detect = 0;
@@ -186,8 +186,8 @@ static int toonie_detect_headphone(pmac_t *chip)
return detect;
}
-static void toonie_check_mute(pmac_t *chip, struct pmac_gpio *gp, int val,
- int do_notify, snd_kcontrol_t *sw)
+static void toonie_check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val,
+ int do_notify, struct snd_kcontrol *sw)
{
if (check_audio_gpio(gp) != val) {
write_audio_gpio(gp, val);
@@ -199,7 +199,7 @@ static void toonie_check_mute(pmac_t *chip, struct pmac_gpio *gp, int val,
static void toonie_detect_handler(void *self)
{
- pmac_t *chip = (pmac_t*) self;
+ struct snd_pmac *chip = (struct snd_pmac *) self;
struct pmac_toonie *mix;
int headphone;
@@ -232,7 +232,7 @@ static void toonie_detect_handler(void *self)
}
}
-static void toonie_update_automute(pmac_t *chip, int do_notify)
+static void toonie_update_automute(struct snd_pmac *chip, int do_notify)
{
if (chip->auto_mute) {
struct pmac_toonie *mix;
@@ -246,7 +246,7 @@ static void toonie_update_automute(pmac_t *chip, int do_notify)
/* interrupt - headphone plug changed */
static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs)
{
- pmac_t *chip = devid;
+ struct snd_pmac *chip = devid;
if (chip->update_automute && chip->initialized) {
chip->update_automute(chip, 1);
@@ -325,7 +325,7 @@ static int find_audio_gpio(const char *name, const char *platform,
return (np->n_intrs > 0) ? np->intrs[0].line : 0;
}
-static void toonie_cleanup(pmac_t *chip)
+static void toonie_cleanup(struct snd_pmac *chip)
{
struct pmac_toonie *mix = chip->mixer_data;
if (! mix)
@@ -336,7 +336,7 @@ static void toonie_cleanup(pmac_t *chip)
chip->mixer_data = NULL;
}
-int snd_pmac_toonie_init(pmac_t *chip)
+int snd_pmac_toonie_init(struct snd_pmac *chip)
{
struct pmac_toonie *mix;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index d74bfabe5300..15c63cb2ccba 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -82,21 +82,21 @@ enum {
VOL_IDX_LAST_MIX
};
-typedef struct pmac_gpio {
+struct pmac_gpio {
unsigned int addr;
u8 active_val;
u8 inactive_val;
u8 active_state;
-} pmac_gpio_t;
-
-typedef struct pmac_tumbler_t {
- pmac_keywest_t i2c;
- pmac_gpio_t audio_reset;
- pmac_gpio_t amp_mute;
- pmac_gpio_t line_mute;
- pmac_gpio_t line_detect;
- pmac_gpio_t hp_mute;
- pmac_gpio_t hp_detect;
+};
+
+struct pmac_tumbler {
+ struct pmac_keywest i2c;
+ struct pmac_gpio audio_reset;
+ struct pmac_gpio amp_mute;
+ struct pmac_gpio line_mute;
+ struct pmac_gpio line_detect;
+ struct pmac_gpio hp_mute;
+ struct pmac_gpio hp_detect;
int headphone_irq;
int lineout_irq;
unsigned int save_master_vol[2];
@@ -112,13 +112,13 @@ typedef struct pmac_tumbler_t {
int auto_mute_notify;
int reset_on_sleep;
u8 acs;
-} pmac_tumbler_t;
+};
/*
*/
-static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs)
+static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs)
{
while (*regs > 0) {
int err, count = 10;
@@ -138,7 +138,7 @@ static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs)
}
-static int tumbler_init_client(pmac_keywest_t *i2c)
+static int tumbler_init_client(struct pmac_keywest *i2c)
{
static unsigned int regs[] = {
/* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
@@ -149,7 +149,7 @@ static int tumbler_init_client(pmac_keywest_t *i2c)
return send_init_client(i2c, regs);
}
-static int snapper_init_client(pmac_keywest_t *i2c)
+static int snapper_init_client(struct pmac_keywest *i2c)
{
static unsigned int regs[] = {
/* normal operation, SCLK=64fps, i2s output, 16bit width */
@@ -173,7 +173,7 @@ static int snapper_init_client(pmac_keywest_t *i2c)
pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
#define tumbler_gpio_free(gp) /* NOP */
-static void write_audio_gpio(pmac_gpio_t *gp, int active)
+static void write_audio_gpio(struct pmac_gpio *gp, int active)
{
if (! gp->addr)
return;
@@ -182,7 +182,7 @@ static void write_audio_gpio(pmac_gpio_t *gp, int active)
DBG("(I) gpio %x write %d\n", gp->addr, active);
}
-static int check_audio_gpio(pmac_gpio_t *gp)
+static int check_audio_gpio(struct pmac_gpio *gp)
{
int ret;
@@ -194,7 +194,7 @@ static int check_audio_gpio(pmac_gpio_t *gp)
return (ret & 0xd) == (gp->active_val & 0xd);
}
-static int read_audio_gpio(pmac_gpio_t *gp)
+static int read_audio_gpio(struct pmac_gpio *gp)
{
int ret;
if (! gp->addr)
@@ -206,7 +206,7 @@ static int read_audio_gpio(pmac_gpio_t *gp)
/*
* update master volume
*/
-static int tumbler_set_master_volume(pmac_tumbler_t *mix)
+static int tumbler_set_master_volume(struct pmac_tumbler *mix)
{
unsigned char block[6];
unsigned int left_vol, right_vol;
@@ -249,7 +249,8 @@ static int tumbler_set_master_volume(pmac_tumbler_t *mix)
/* output volume */
-static int tumbler_info_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int tumbler_info_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -258,20 +259,22 @@ static int tumbler_info_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
return 0;
}
-static int tumbler_get_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
snd_assert(mix, return -ENODEV);
ucontrol->value.integer.value[0] = mix->master_vol[0];
ucontrol->value.integer.value[1] = mix->master_vol[1];
return 0;
}
-static int tumbler_put_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_master_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
int change;
snd_assert(mix, return -ENODEV);
@@ -286,20 +289,22 @@ static int tumbler_put_master_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
}
/* output switch */
-static int tumbler_get_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
snd_assert(mix, return -ENODEV);
ucontrol->value.integer.value[0] = mix->master_switch[0];
ucontrol->value.integer.value[1] = mix->master_switch[1];
return 0;
}
-static int tumbler_put_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_master_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
int change;
snd_assert(mix, return -ENODEV);
@@ -320,7 +325,7 @@ static int tumbler_put_master_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
#define TAS3001_DRC_MAX 0x5f
-static int tumbler_set_drc(pmac_tumbler_t *mix)
+static int tumbler_set_drc(struct pmac_tumbler *mix)
{
unsigned char val[2];
@@ -354,7 +359,7 @@ static int tumbler_set_drc(pmac_tumbler_t *mix)
#define TAS3004_DRC_MAX 0xef
-static int snapper_set_drc(pmac_tumbler_t *mix)
+static int snapper_set_drc(struct pmac_tumbler *mix)
{
unsigned char val[6];
@@ -384,9 +389,10 @@ static int snapper_set_drc(pmac_tumbler_t *mix)
return 0;
}
-static int tumbler_info_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int tumbler_info_drc_value(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
@@ -395,20 +401,22 @@ static int tumbler_info_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int tumbler_get_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_drc_value(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->drc_range;
return 0;
}
-static int tumbler_put_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_drc_value(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -424,20 +432,22 @@ static int tumbler_put_drc_value(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return change;
}
-static int tumbler_get_drc_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_drc_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->drc_enable;
return 0;
}
-static int tumbler_put_drc_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_drc_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -466,7 +476,8 @@ struct tumbler_mono_vol {
unsigned int *table;
};
-static int tumbler_set_mono_volume(pmac_tumbler_t *mix, struct tumbler_mono_vol *info)
+static int tumbler_set_mono_volume(struct pmac_tumbler *mix,
+ struct tumbler_mono_vol *info)
{
unsigned char block[4];
unsigned int vol;
@@ -489,7 +500,8 @@ static int tumbler_set_mono_volume(pmac_tumbler_t *mix, struct tumbler_mono_vol
return 0;
}
-static int tumbler_info_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int tumbler_info_mono(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
@@ -500,22 +512,24 @@ static int tumbler_info_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
return 0;
}
-static int tumbler_get_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_mono(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->mono_vol[info->index];
return 0;
}
-static int tumbler_put_mono(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_mono(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
struct tumbler_mono_vol *info = (struct tumbler_mono_vol *)kcontrol->private_value;
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -594,7 +608,7 @@ static struct tumbler_mono_vol snapper_treble_vol_info = {
* snapper mixer volumes
*/
-static int snapper_set_mix_vol1(pmac_tumbler_t *mix, int idx, int ch, int reg)
+static int snapper_set_mix_vol1(struct pmac_tumbler *mix, int idx, int ch, int reg)
{
int i, j, vol;
unsigned char block[9];
@@ -618,7 +632,7 @@ static int snapper_set_mix_vol1(pmac_tumbler_t *mix, int idx, int ch, int reg)
return 0;
}
-static int snapper_set_mix_vol(pmac_tumbler_t *mix, int idx)
+static int snapper_set_mix_vol(struct pmac_tumbler *mix, int idx)
{
if (! mix->i2c.client)
return -ENODEV;
@@ -628,7 +642,8 @@ static int snapper_set_mix_vol(pmac_tumbler_t *mix, int idx)
return 0;
}
-static int snapper_info_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snapper_info_mix(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -637,11 +652,12 @@ static int snapper_info_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
return 0;
}
-static int snapper_get_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snapper_get_mix(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int idx = (int)kcontrol->private_value;
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
if (! (mix = chip->mixer_data))
return -ENODEV;
ucontrol->value.integer.value[0] = mix->mix_vol[idx][0];
@@ -649,11 +665,12 @@ static int snapper_get_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
return 0;
}
-static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snapper_put_mix(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int idx = (int)kcontrol->private_value;
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
int change;
if (! (mix = chip->mixer_data))
@@ -676,11 +693,12 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE };
-static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_get_mute_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
- pmac_gpio_t *gp;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
+ struct pmac_gpio *gp;
if (! (mix = chip->mixer_data))
return -ENODEV;
switch(kcontrol->private_value) {
@@ -699,11 +717,12 @@ static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int tumbler_put_mute_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix;
- pmac_gpio_t *gp;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix;
+ struct pmac_gpio *gp;
int val;
#ifdef PMAC_SUPPORT_AUTOMUTE
if (chip->update_automute && chip->auto_mute)
@@ -731,7 +750,7 @@ static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return 0;
}
-static int snapper_set_capture_source(pmac_tumbler_t *mix)
+static int snapper_set_capture_source(struct pmac_tumbler *mix)
{
if (! mix->i2c.client)
return -ENODEV;
@@ -742,7 +761,8 @@ static int snapper_set_capture_source(pmac_tumbler_t *mix)
return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
}
-static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snapper_info_capture_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[2] = {
"Line", "Mic"
@@ -756,20 +776,22 @@ static int snapper_info_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
return 0;
}
-static int snapper_get_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snapper_get_capture_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
snd_assert(mix, return -ENODEV);
ucontrol->value.integer.value[0] = mix->capture_source;
return 0;
}
-static int snapper_put_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- pmac_t *chip = snd_kcontrol_chip(kcontrol);
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
+ struct pmac_tumbler *mix = chip->mixer_data;
int change;
snd_assert(mix, return -ENODEV);
@@ -794,7 +816,7 @@ static int snapper_put_capture_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
/*
*/
-static snd_kcontrol_new_t tumbler_mixers[] __initdata = {
+static struct snd_kcontrol_new tumbler_mixers[] __initdata = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.info = tumbler_info_master_volume,
@@ -818,7 +840,7 @@ static snd_kcontrol_new_t tumbler_mixers[] __initdata = {
},
};
-static snd_kcontrol_new_t snapper_mixers[] __initdata = {
+static struct snd_kcontrol_new snapper_mixers[] __initdata = {
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.info = tumbler_info_master_volume,
@@ -850,7 +872,7 @@ static snd_kcontrol_new_t snapper_mixers[] __initdata = {
},
};
-static snd_kcontrol_new_t tumbler_hp_sw __initdata = {
+static struct snd_kcontrol_new tumbler_hp_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -858,7 +880,7 @@ static snd_kcontrol_new_t tumbler_hp_sw __initdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_HP,
};
-static snd_kcontrol_new_t tumbler_speaker_sw __initdata = {
+static struct snd_kcontrol_new tumbler_speaker_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PC Speaker Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -866,7 +888,7 @@ static snd_kcontrol_new_t tumbler_speaker_sw __initdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_AMP,
};
-static snd_kcontrol_new_t tumbler_lineout_sw __initdata = {
+static struct snd_kcontrol_new tumbler_lineout_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Out Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -874,7 +896,7 @@ static snd_kcontrol_new_t tumbler_lineout_sw __initdata = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_LINE,
};
-static snd_kcontrol_new_t tumbler_drc_sw __initdata = {
+static struct snd_kcontrol_new tumbler_drc_sw __initdata = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Switch",
.info = snd_pmac_boolean_mono_info,
@@ -887,9 +909,9 @@ static snd_kcontrol_new_t tumbler_drc_sw __initdata = {
/*
* auto-mute stuffs
*/
-static int tumbler_detect_headphone(pmac_t *chip)
+static int tumbler_detect_headphone(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
int detect = 0;
if (mix->hp_detect.addr)
@@ -897,9 +919,9 @@ static int tumbler_detect_headphone(pmac_t *chip)
return detect;
}
-static int tumbler_detect_lineout(pmac_t *chip)
+static int tumbler_detect_lineout(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
int detect = 0;
if (mix->line_detect.addr)
@@ -907,7 +929,8 @@ static int tumbler_detect_lineout(pmac_t *chip)
return detect;
}
-static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw)
+static void check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, int do_notify,
+ struct snd_kcontrol *sw)
{
if (check_audio_gpio(gp) != val) {
write_audio_gpio(gp, val);
@@ -921,8 +944,8 @@ static struct work_struct device_change;
static void device_change_handler(void *self)
{
- pmac_t *chip = (pmac_t*) self;
- pmac_tumbler_t *mix;
+ struct snd_pmac *chip = self;
+ struct pmac_tumbler *mix;
int headphone, lineout;
if (!chip)
@@ -979,10 +1002,10 @@ static void device_change_handler(void *self)
tumbler_set_master_volume(mix);
}
-static void tumbler_update_automute(pmac_t *chip, int do_notify)
+static void tumbler_update_automute(struct snd_pmac *chip, int do_notify)
{
if (chip->auto_mute) {
- pmac_tumbler_t *mix;
+ struct pmac_tumbler *mix;
mix = chip->mixer_data;
snd_assert(mix, return);
mix->auto_mute_notify = do_notify;
@@ -995,7 +1018,7 @@ static void tumbler_update_automute(pmac_t *chip, int do_notify)
/* interrupt - headphone plug changed */
static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs)
{
- pmac_t *chip = devid;
+ struct snd_pmac *chip = devid;
if (chip->update_automute && chip->initialized) {
chip->update_automute(chip, 1);
return IRQ_HANDLED;
@@ -1035,7 +1058,8 @@ static struct device_node *find_compatible_audio_device(const char *name)
}
/* find an audio device and get its address */
-static long tumbler_find_device(const char *device, const char *platform, pmac_gpio_t *gp, int is_compatible)
+static long tumbler_find_device(const char *device, const char *platform,
+ struct pmac_gpio *gp, int is_compatible)
{
struct device_node *node;
u32 *base, addr;
@@ -1101,9 +1125,9 @@ static long tumbler_find_device(const char *device, const char *platform, pmac_g
}
/* reset audio */
-static void tumbler_reset_audio(pmac_t *chip)
+static void tumbler_reset_audio(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
if (mix->anded_reset) {
DBG("(I) codec anded reset !\n");
@@ -1130,9 +1154,9 @@ static void tumbler_reset_audio(pmac_t *chip)
#ifdef CONFIG_PM
/* suspend mixer */
-static void tumbler_suspend(pmac_t *chip)
+static void tumbler_suspend(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
if (mix->headphone_irq >= 0)
disable_irq(mix->headphone_irq);
@@ -1160,9 +1184,9 @@ static void tumbler_suspend(pmac_t *chip)
}
/* resume mixer */
-static void tumbler_resume(pmac_t *chip)
+static void tumbler_resume(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
snd_assert(mix, return);
@@ -1208,10 +1232,10 @@ static void tumbler_resume(pmac_t *chip)
#endif
/* initialize tumbler */
-static int __init tumbler_init(pmac_t *chip)
+static int __init tumbler_init(struct snd_pmac *chip)
{
int irq;
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
snd_assert(mix, return -EINVAL);
if (tumbler_find_device("audio-hw-reset",
@@ -1259,9 +1283,9 @@ static int __init tumbler_init(pmac_t *chip)
return 0;
}
-static void tumbler_cleanup(pmac_t *chip)
+static void tumbler_cleanup(struct snd_pmac *chip)
{
- pmac_tumbler_t *mix = chip->mixer_data;
+ struct pmac_tumbler *mix = chip->mixer_data;
if (! mix)
return;
@@ -1279,10 +1303,10 @@ static void tumbler_cleanup(pmac_t *chip)
}
/* exported */
-int __init snd_pmac_tumbler_init(pmac_t *chip)
+int __init snd_pmac_tumbler_init(struct snd_pmac *chip)
{
int i, err;
- pmac_tumbler_t *mix;
+ struct pmac_tumbler *mix;
u32 *paddr;
struct device_node *tas_node, *np;
char *chipname;
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
index ef022a846b06..079e22af074c 100644
--- a/sound/sparc/Kconfig
+++ b/sound/sparc/Kconfig
@@ -7,7 +7,6 @@ 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.
@@ -18,7 +17,6 @@ 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.
@@ -29,7 +27,6 @@ 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 46d504ba7e03..55493340f467 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -311,7 +311,7 @@ struct amd7930_map {
#define AMR_PP_PPCR2 0xC8
#define AMR_PP_PPCR3 0xC9
-typedef struct snd_amd7930 {
+struct snd_amd7930 {
spinlock_t lock;
void __iomem *regs;
u32 flags;
@@ -320,10 +320,10 @@ typedef struct snd_amd7930 {
struct amd7930_map map;
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
- snd_pcm_substream_t *capture_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
+ struct snd_pcm_substream *capture_substream;
/* Playback/Capture buffer state. */
unsigned char *p_orig, *p_cur;
@@ -339,12 +339,12 @@ typedef struct snd_amd7930 {
unsigned int irq;
unsigned int regs_size;
struct snd_amd7930 *next;
-} amd7930_t;
+};
-static amd7930_t *amd7930_list;
+static struct snd_amd7930 *amd7930_list;
/* Idle the AMD7930 chip. The amd->lock is not held. */
-static __inline__ void amd7930_idle(amd7930_t *amd)
+static __inline__ void amd7930_idle(struct snd_amd7930 *amd)
{
unsigned long flags;
@@ -355,7 +355,7 @@ static __inline__ void amd7930_idle(amd7930_t *amd)
}
/* Enable chip interrupts. The amd->lock is not held. */
-static __inline__ void amd7930_enable_ints(amd7930_t *amd)
+static __inline__ void amd7930_enable_ints(struct snd_amd7930 *amd)
{
unsigned long flags;
@@ -366,7 +366,7 @@ static __inline__ void amd7930_enable_ints(amd7930_t *amd)
}
/* Disable chip interrupts. The amd->lock is not held. */
-static __inline__ void amd7930_disable_ints(amd7930_t *amd)
+static __inline__ void amd7930_disable_ints(struct snd_amd7930 *amd)
{
unsigned long flags;
@@ -379,7 +379,7 @@ static __inline__ void amd7930_disable_ints(amd7930_t *amd)
/* Commit amd7930_map settings to the hardware.
* The amd->lock is held and local interrupts are disabled.
*/
-static void __amd7930_write_map(amd7930_t *amd)
+static void __amd7930_write_map(struct snd_amd7930 *amd)
{
struct amd7930_map *map = &amd->map;
@@ -473,7 +473,7 @@ static __const__ __u16 ger_coeff[] = {
/* Update amd7930_map settings and program them into the hardware.
* The amd->lock is held and local interrupts are disabled.
*/
-static void __amd7930_update_map(amd7930_t *amd)
+static void __amd7930_update_map(struct snd_amd7930 *amd)
{
struct amd7930_map *map = &amd->map;
int level;
@@ -493,7 +493,7 @@ static void __amd7930_update_map(amd7930_t *amd)
static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- amd7930_t *amd = dev_id;
+ struct snd_amd7930 *amd = dev_id;
unsigned int elapsed;
u8 ir;
@@ -534,7 +534,7 @@ static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *
return IRQ_HANDLED;
}
-static int snd_amd7930_trigger(amd7930_t *amd, unsigned int flag, int cmd)
+static int snd_amd7930_trigger(struct snd_amd7930 *amd, unsigned int flag, int cmd)
{
unsigned long flags;
int result = 0;
@@ -564,24 +564,24 @@ static int snd_amd7930_trigger(amd7930_t *amd, unsigned int flag, int cmd)
return result;
}
-static int snd_amd7930_playback_trigger(snd_pcm_substream_t * substream,
+static int snd_amd7930_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
return snd_amd7930_trigger(amd, AMD7930_FLAG_PLAYBACK, cmd);
}
-static int snd_amd7930_capture_trigger(snd_pcm_substream_t * substream,
+static int snd_amd7930_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
return snd_amd7930_trigger(amd, AMD7930_FLAG_CAPTURE, cmd);
}
-static int snd_amd7930_playback_prepare(snd_pcm_substream_t * substream)
+static int snd_amd7930_playback_prepare(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned long flags;
u8 new_mmr1;
@@ -610,10 +610,10 @@ static int snd_amd7930_playback_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_amd7930_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_amd7930_capture_prepare(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int size = snd_pcm_lib_buffer_bytes(substream);
unsigned long flags;
u8 new_mmr1;
@@ -642,9 +642,9 @@ static int snd_amd7930_capture_prepare(snd_pcm_substream_t * substream)
return 0;
}
-static snd_pcm_uframes_t snd_amd7930_playback_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_amd7930_playback_pointer(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(amd->flags & AMD7930_FLAG_PLAYBACK))
@@ -653,9 +653,9 @@ static snd_pcm_uframes_t snd_amd7930_playback_pointer(snd_pcm_substream_t * subs
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_amd7930_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_amd7930_capture_pointer(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
size_t ptr;
if (!(amd->flags & AMD7930_FLAG_CAPTURE))
@@ -666,7 +666,7 @@ static snd_pcm_uframes_t snd_amd7930_capture_pointer(snd_pcm_substream_t * subst
}
/* Playback and capture have identical properties. */
-static snd_pcm_hardware_t snd_amd7930_pcm_hw =
+static struct snd_pcm_hardware snd_amd7930_pcm_hw =
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -686,54 +686,54 @@ static snd_pcm_hardware_t snd_amd7930_pcm_hw =
.periods_max = 1024,
};
-static int snd_amd7930_playback_open(snd_pcm_substream_t * substream)
+static int snd_amd7930_playback_open(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
amd->playback_substream = substream;
runtime->hw = snd_amd7930_pcm_hw;
return 0;
}
-static int snd_amd7930_capture_open(snd_pcm_substream_t * substream)
+static int snd_amd7930_capture_open(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
amd->capture_substream = substream;
runtime->hw = snd_amd7930_pcm_hw;
return 0;
}
-static int snd_amd7930_playback_close(snd_pcm_substream_t * substream)
+static int snd_amd7930_playback_close(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
amd->playback_substream = NULL;
return 0;
}
-static int snd_amd7930_capture_close(snd_pcm_substream_t * substream)
+static int snd_amd7930_capture_close(struct snd_pcm_substream *substream)
{
- amd7930_t *amd = snd_pcm_substream_chip(substream);
+ struct snd_amd7930 *amd = snd_pcm_substream_chip(substream);
amd->capture_substream = NULL;
return 0;
}
-static int snd_amd7930_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_amd7930_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_amd7930_hw_free(snd_pcm_substream_t * substream)
+static int snd_amd7930_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static snd_pcm_ops_t snd_amd7930_playback_ops = {
+static struct snd_pcm_ops snd_amd7930_playback_ops = {
.open = snd_amd7930_playback_open,
.close = snd_amd7930_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -744,7 +744,7 @@ static snd_pcm_ops_t snd_amd7930_playback_ops = {
.pointer = snd_amd7930_playback_pointer,
};
-static snd_pcm_ops_t snd_amd7930_capture_ops = {
+static struct snd_pcm_ops snd_amd7930_capture_ops = {
.open = snd_amd7930_capture_open,
.close = snd_amd7930_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -755,17 +755,9 @@ static snd_pcm_ops_t snd_amd7930_capture_ops = {
.pointer = snd_amd7930_capture_pointer,
};
-static void snd_amd7930_pcm_free(snd_pcm_t *pcm)
+static int __init snd_amd7930_pcm(struct snd_amd7930 *amd)
{
- amd7930_t *amd = pcm->private_data;
-
- amd->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-static int __init snd_amd7930_pcm(amd7930_t *amd)
-{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(amd->card,
@@ -780,7 +772,6 @@ static int __init snd_amd7930_pcm(amd7930_t *amd)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_amd7930_capture_ops);
pcm->private_data = amd;
- pcm->private_free = snd_amd7930_pcm_free;
pcm->info_flags = 0;
strcpy(pcm->name, amd->card->shortname);
amd->pcm = pcm;
@@ -796,7 +787,7 @@ static int __init snd_amd7930_pcm(amd7930_t *amd)
#define VOLUME_CAPTURE 1
#define VOLUME_PLAYBACK 2
-static int snd_amd7930_info_volume(snd_kcontrol_t *kctl, snd_ctl_elem_info_t *uinfo)
+static int snd_amd7930_info_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
{
int type = kctl->private_value;
@@ -813,9 +804,9 @@ static int snd_amd7930_info_volume(snd_kcontrol_t *kctl, snd_ctl_elem_info_t *ui
return 0;
}
-static int snd_amd7930_get_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *ucontrol)
+static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
{
- amd7930_t *amd = snd_kcontrol_chip(kctl);
+ struct snd_amd7930 *amd = snd_kcontrol_chip(kctl);
int type = kctl->private_value;
int *swval;
@@ -841,9 +832,9 @@ static int snd_amd7930_get_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *uc
return 0;
}
-static int snd_amd7930_put_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *ucontrol)
+static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
{
- amd7930_t *amd = snd_kcontrol_chip(kctl);
+ struct snd_amd7930 *amd = snd_kcontrol_chip(kctl);
unsigned long flags;
int type = kctl->private_value;
int *swval, change;
@@ -879,7 +870,7 @@ static int snd_amd7930_put_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *uc
return change;
}
-static snd_kcontrol_new_t amd7930_controls[] __initdata = {
+static struct snd_kcontrol_new amd7930_controls[] __initdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitor Volume",
@@ -909,9 +900,9 @@ static snd_kcontrol_new_t amd7930_controls[] __initdata = {
},
};
-static int __init snd_amd7930_mixer(amd7930_t *amd)
+static int __init snd_amd7930_mixer(struct snd_amd7930 *amd)
{
- snd_card_t *card;
+ struct snd_card *card;
int idx, err;
snd_assert(amd != NULL && amd->card != NULL, return -EINVAL);
@@ -928,7 +919,7 @@ static int __init snd_amd7930_mixer(amd7930_t *amd)
return 0;
}
-static int snd_amd7930_free(amd7930_t *amd)
+static int snd_amd7930_free(struct snd_amd7930 *amd)
{
amd7930_idle(amd);
@@ -943,27 +934,27 @@ static int snd_amd7930_free(amd7930_t *amd)
return 0;
}
-static int snd_amd7930_dev_free(snd_device_t *device)
+static int snd_amd7930_dev_free(struct snd_device *device)
{
- amd7930_t *amd = device->device_data;
+ struct snd_amd7930 *amd = device->device_data;
return snd_amd7930_free(amd);
}
-static snd_device_ops_t snd_amd7930_dev_ops = {
+static struct snd_device_ops snd_amd7930_dev_ops = {
.dev_free = snd_amd7930_dev_free,
};
-static int __init snd_amd7930_create(snd_card_t *card,
+static int __init snd_amd7930_create(struct snd_card *card,
struct sbus_dev *sdev,
struct resource *rp,
unsigned int reg_size,
struct linux_prom_irqs *irq_prop,
int dev,
- amd7930_t **ramd)
+ struct snd_amd7930 **ramd)
{
unsigned long flags;
- amd7930_t *amd;
+ struct snd_amd7930 *amd;
int err;
*ramd = NULL;
@@ -1032,8 +1023,8 @@ static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
struct linux_prom_registers reg_prop;
struct linux_prom_irqs irq_prop;
struct resource res, *rp;
- snd_card_t *card;
- amd7930_t *amd;
+ struct snd_card *card;
+ struct snd_amd7930 *amd;
int err;
if (dev >= SNDRV_CARDS)
@@ -1088,9 +1079,6 @@ 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;
@@ -1132,10 +1120,10 @@ static int __init amd7930_init(void)
static void __exit amd7930_exit(void)
{
- amd7930_t *p = amd7930_list;
+ struct snd_amd7930 *p = amd7930_list;
while (p != NULL) {
- amd7930_t *next = p->next;
+ struct snd_amd7930 *next = p->next;
snd_card_free(p->card);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 1f8d27a6152e..fd6543998788 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -62,49 +62,48 @@ MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
#ifdef SBUS_SUPPORT
-typedef struct sbus_dma_info {
+struct sbus_dma_info {
spinlock_t lock;
int dir;
void __iomem *regs;
-} sbus_dma_info_t;
+};
#endif
-typedef struct snd_cs4231 cs4231_t;
-
-typedef struct cs4231_dma_control {
+struct snd_cs4231;
+struct cs4231_dma_control {
void (*prepare)(struct cs4231_dma_control *dma_cont, int dir);
void (*enable)(struct cs4231_dma_control *dma_cont, int on);
int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len);
unsigned int (*address)(struct cs4231_dma_control *dma_cont);
- void (*reset)(cs4231_t *chip);
- void (*preallocate)(cs4231_t *chip, snd_pcm_t *pcm);
+ void (*reset)(struct snd_cs4231 *chip);
+ void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm);
#ifdef EBUS_SUPPORT
struct ebus_dma_info ebus_info;
#endif
#ifdef SBUS_SUPPORT
struct sbus_dma_info sbus_info;
#endif
-} cs4231_dma_control_t;
+};
struct snd_cs4231 {
spinlock_t lock;
void __iomem *port;
- cs4231_dma_control_t p_dma;
- cs4231_dma_control_t c_dma;
+ struct cs4231_dma_control p_dma;
+ struct cs4231_dma_control c_dma;
u32 flags;
#define CS4231_FLAG_EBUS 0x00000001
#define CS4231_FLAG_PLAYBACK 0x00000002
#define CS4231_FLAG_CAPTURE 0x00000004
- snd_card_t *card;
- snd_pcm_t *pcm;
- snd_pcm_substream_t *playback_substream;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_pcm_substream *playback_substream;
unsigned int p_periods_sent;
- snd_pcm_substream_t *capture_substream;
+ struct snd_pcm_substream *capture_substream;
unsigned int c_periods_sent;
- snd_timer_t *timer;
+ struct snd_timer *timer;
unsigned short mode;
#define CS4231_MODE_NONE 0x0000
@@ -132,7 +131,7 @@ struct snd_cs4231 {
struct snd_cs4231 *next;
};
-static cs4231_t *cs4231_list;
+static struct snd_cs4231 *cs4231_list;
/* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for
* now.... -DaveM
@@ -341,12 +340,12 @@ static unsigned int rates[14] = {
27042, 32000, 33075, 37800, 44100, 48000
};
-static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
+static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
.count = 14,
.list = rates,
};
-static int snd_cs4231_xrate(snd_pcm_runtime_t *runtime)
+static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
{
return snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
@@ -389,7 +388,7 @@ static unsigned char snd_cs4231_original_image[32] =
0x00, /* 1f/31 - cbrl */
};
-static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
+static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr)
{
#ifdef EBUS_SUPPORT
if (cp->flags & CS4231_FLAG_EBUS) {
@@ -404,7 +403,7 @@ static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
#endif
}
-static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
+static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr)
{
#ifdef EBUS_SUPPORT
if (cp->flags & CS4231_FLAG_EBUS) {
@@ -423,7 +422,7 @@ static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
* Basic I/O functions
*/
-static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
+static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,
unsigned char mask, unsigned char value)
{
int timeout;
@@ -450,7 +449,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
}
}
-static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
{
int timeout;
@@ -467,7 +466,7 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
mb();
}
-static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
+static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value)
{
int timeout;
@@ -485,7 +484,7 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu
mb();
}
-static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
+static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)
{
int timeout;
unsigned char ret;
@@ -508,7 +507,7 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
* CS4231 detection / MCE routines
*/
-static void snd_cs4231_busy_wait(cs4231_t *chip)
+static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)
{
int timeout;
@@ -523,7 +522,7 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
udelay(1000);
}
-static void snd_cs4231_mce_up(cs4231_t *chip)
+static void snd_cs4231_mce_up(struct snd_cs4231 *chip)
{
unsigned long flags;
int timeout;
@@ -544,7 +543,7 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static void snd_cs4231_mce_down(cs4231_t *chip)
+static void snd_cs4231_mce_down(struct snd_cs4231 *chip)
{
unsigned long flags;
int timeout;
@@ -602,9 +601,11 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_substream_t *substream, unsigned int *periods_sent)
+static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,
+ struct snd_pcm_substream *substream,
+ unsigned int *periods_sent)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
while (1) {
unsigned int period_size = snd_pcm_lib_period_bytes(substream);
@@ -619,10 +620,11 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, snd_pcm_
}
}
-static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on)
+static void cs4231_dma_trigger(struct snd_pcm_substream *substream,
+ unsigned int what, int on)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- cs4231_dma_control_t *dma_cont;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct cs4231_dma_control *dma_cont;
if (what & CS4231_PLAYBACK_ENABLE) {
dma_cont = &chip->p_dma;
@@ -650,9 +652,9 @@ static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what
}
}
-static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
int result = 0;
switch (cmd) {
@@ -660,7 +662,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
case SNDRV_PCM_TRIGGER_STOP:
{
unsigned int what = 0;
- snd_pcm_substream_t *s;
+ struct snd_pcm_substream *s;
struct list_head *pos;
unsigned long flags;
@@ -711,7 +713,7 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate)
return freq_bits[13];
}
-static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int channels)
+static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels)
{
unsigned char rformat;
@@ -728,7 +730,7 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann
return rformat;
}
-static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
+static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)
{
unsigned long flags;
@@ -768,7 +770,7 @@ static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
spin_unlock_irqrestore(&chip->lock, flags);
}
-static void snd_cs4231_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
+static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
unsigned char pdfr)
{
unsigned long flags;
@@ -791,7 +793,7 @@ static void snd_cs4231_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *para
up(&chip->mce_mutex);
}
-static void snd_cs4231_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
+static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params,
unsigned char cdfr)
{
unsigned long flags;
@@ -824,18 +826,18 @@ static void snd_cs4231_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *param
* Timer interface
*/
-static unsigned long snd_cs4231_timer_resolution(snd_timer_t *timer)
+static unsigned long snd_cs4231_timer_resolution(struct snd_timer *timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
}
-static int snd_cs4231_timer_start(snd_timer_t *timer)
+static int snd_cs4231_timer_start(struct snd_timer *timer)
{
unsigned long flags;
unsigned int ticks;
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->lock, flags);
ticks = timer->sticks;
@@ -856,10 +858,10 @@ static int snd_cs4231_timer_start(snd_timer_t *timer)
return 0;
}
-static int snd_cs4231_timer_stop(snd_timer_t *timer)
+static int snd_cs4231_timer_stop(struct snd_timer *timer)
{
unsigned long flags;
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
@@ -869,7 +871,7 @@ static int snd_cs4231_timer_stop(snd_timer_t *timer)
return 0;
}
-static void snd_cs4231_init(cs4231_t *chip)
+static void __init snd_cs4231_init(struct snd_cs4231 *chip)
{
unsigned long flags;
@@ -927,7 +929,7 @@ static void snd_cs4231_init(cs4231_t *chip)
#endif
}
-static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
+static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)
{
unsigned long flags;
@@ -962,7 +964,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
return 0;
}
-static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
+static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)
{
unsigned long flags;
@@ -1013,21 +1015,21 @@ static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
* timer open/close
*/
-static int snd_cs4231_timer_open(snd_timer_t *timer)
+static int snd_cs4231_timer_open(struct snd_timer *timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
snd_cs4231_open(chip, CS4231_MODE_TIMER);
return 0;
}
-static int snd_cs4231_timer_close(snd_timer_t * timer)
+static int snd_cs4231_timer_close(struct snd_timer * timer)
{
- cs4231_t *chip = snd_timer_chip(timer);
+ struct snd_cs4231 *chip = snd_timer_chip(timer);
snd_cs4231_close(chip, CS4231_MODE_TIMER);
return 0;
}
-static struct _snd_timer_hardware snd_cs4231_timer_table =
+static struct snd_timer_hardware snd_cs4231_timer_table =
{
.flags = SNDRV_TIMER_HW_AUTO,
.resolution = 9945,
@@ -1043,10 +1045,10 @@ static struct _snd_timer_hardware snd_cs4231_timer_table =
* ok.. exported functions..
*/
-static int snd_cs4231_playback_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
unsigned char new_pdfr;
int err;
@@ -1061,15 +1063,15 @@ static int snd_cs4231_playback_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -1086,10 +1088,10 @@ static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cs4231_capture_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
unsigned char new_cdfr;
int err;
@@ -1104,14 +1106,14 @@ static int snd_cs4231_capture_hw_params(snd_pcm_substream_t *substream,
return 0;
}
-static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
-static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -1125,7 +1127,7 @@ static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static void snd_cs4231_overrange(cs4231_t *chip)
+static void snd_cs4231_overrange(struct snd_cs4231 *chip)
{
unsigned long flags;
unsigned char res;
@@ -1138,10 +1140,8 @@ static void snd_cs4231_overrange(cs4231_t *chip)
chip->capture_substream->runtime->overrange++;
}
-static void snd_cs4231_play_callback(cs4231_t *cookie)
+static void snd_cs4231_play_callback(struct snd_cs4231 *chip)
{
- cs4231_t *chip = cookie;
-
if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
snd_pcm_period_elapsed(chip->playback_substream);
snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream,
@@ -1149,10 +1149,8 @@ static void snd_cs4231_play_callback(cs4231_t *cookie)
}
}
-static void snd_cs4231_capture_callback(cs4231_t *cookie)
+static void snd_cs4231_capture_callback(struct snd_cs4231 *chip)
{
- cs4231_t *chip = cookie;
-
if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
snd_pcm_period_elapsed(chip->capture_substream);
snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream,
@@ -1160,10 +1158,10 @@ static void snd_cs4231_capture_callback(cs4231_t *cookie)
}
}
-static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- cs4231_dma_control_t *dma_cont = &chip->p_dma;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct cs4231_dma_control *dma_cont = &chip->p_dma;
size_t ptr;
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
@@ -1175,10 +1173,10 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr
return bytes_to_frames(substream->runtime, ptr);
}
-static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- cs4231_dma_control_t *dma_cont = &chip->c_dma;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct cs4231_dma_control *dma_cont = &chip->c_dma;
size_t ptr;
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
@@ -1194,7 +1192,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
*/
-static int snd_cs4231_probe(cs4231_t *chip)
+static int __init snd_cs4231_probe(struct snd_cs4231 *chip)
{
unsigned long flags;
int i, id, vers;
@@ -1259,7 +1257,7 @@ static int snd_cs4231_probe(cs4231_t *chip)
return 0; /* all things are ok.. */
}
-static snd_pcm_hardware_t snd_cs4231_playback =
+static struct snd_pcm_hardware snd_cs4231_playback =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
@@ -1279,7 +1277,7 @@ static snd_pcm_hardware_t snd_cs4231_playback =
.periods_max = 1024,
};
-static snd_pcm_hardware_t snd_cs4231_capture =
+static struct snd_pcm_hardware snd_cs4231_capture =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
@@ -1299,10 +1297,10 @@ static snd_pcm_hardware_t snd_cs4231_capture =
.periods_max = 1024,
};
-static int snd_cs4231_playback_open(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
runtime->hw = snd_cs4231_playback;
@@ -1319,10 +1317,10 @@ static int snd_cs4231_playback_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cs4231_capture_open(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int err;
runtime->hw = snd_cs4231_capture;
@@ -1339,9 +1337,9 @@ static int snd_cs4231_capture_open(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cs4231_playback_close(snd_pcm_substream_t *substream)
+static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
snd_cs4231_close(chip, CS4231_MODE_PLAY);
chip->playback_substream = NULL;
@@ -1349,9 +1347,9 @@ static int snd_cs4231_playback_close(snd_pcm_substream_t *substream)
return 0;
}
-static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
+static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
{
- cs4231_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
snd_cs4231_close(chip, CS4231_MODE_RECORD);
chip->capture_substream = NULL;
@@ -1363,7 +1361,7 @@ static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
* XXX the audio AUXIO register...
*/
-static snd_pcm_ops_t snd_cs4231_playback_ops = {
+static struct snd_pcm_ops snd_cs4231_playback_ops = {
.open = snd_cs4231_playback_open,
.close = snd_cs4231_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1374,7 +1372,7 @@ static snd_pcm_ops_t snd_cs4231_playback_ops = {
.pointer = snd_cs4231_playback_pointer,
};
-static snd_pcm_ops_t snd_cs4231_capture_ops = {
+static struct snd_pcm_ops snd_cs4231_capture_ops = {
.open = snd_cs4231_capture_open,
.close = snd_cs4231_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1385,16 +1383,9 @@ static snd_pcm_ops_t snd_cs4231_capture_ops = {
.pointer = snd_cs4231_capture_pointer,
};
-static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
-{
- cs4231_t *chip = pcm->private_data;
- chip->pcm = NULL;
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_cs4231_pcm(cs4231_t *chip)
+static int __init snd_cs4231_pcm(struct snd_cs4231 *chip)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0)
@@ -1405,7 +1396,6 @@ int snd_cs4231_pcm(cs4231_t *chip)
/* global setup */
pcm->private_data = chip;
- pcm->private_free = snd_cs4231_pcm_free;
pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
strcpy(pcm->name, "CS4231");
@@ -1416,16 +1406,10 @@ int snd_cs4231_pcm(cs4231_t *chip)
return 0;
}
-static void snd_cs4231_timer_free(snd_timer_t *timer)
-{
- cs4231_t *chip = timer->private_data;
- chip->timer = NULL;
-}
-
-int snd_cs4231_timer(cs4231_t *chip)
+static int __init snd_cs4231_timer(struct snd_cs4231 *chip)
{
- snd_timer_t *timer;
- snd_timer_id_t tid;
+ struct snd_timer *timer;
+ struct snd_timer_id tid;
int err;
/* Timer initialization */
@@ -1438,7 +1422,6 @@ int snd_cs4231_timer(cs4231_t *chip)
return err;
strcpy(timer->name, "CS4231");
timer->private_data = chip;
- timer->private_free = snd_cs4231_timer_free;
timer->hw = snd_cs4231_timer_table;
chip->timer = timer;
@@ -1449,12 +1432,13 @@ int snd_cs4231_timer(cs4231_t *chip)
* MIXER part
*/
-static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Line", "CD", "Mic", "Mix"
};
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
snd_assert(chip->card != NULL, return -EINVAL);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1467,9 +1451,10 @@ static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *ui
return 0;
}
-static int snd_cs4231_get_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
@@ -1482,9 +1467,10 @@ static int snd_cs4231_get_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return 0;
}
-static int snd_cs4231_put_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short left, right;
int change;
@@ -1509,7 +1495,8 @@ static int snd_cs4231_put_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
return change;
}
-int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1522,9 +1509,10 @@ int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-int snd_cs4231_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1544,9 +1532,10 @@ int snd_cs4231_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-int snd_cs4231_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -1571,7 +1560,8 @@ int snd_cs4231_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return change;
}
-int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_cs4231_info_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;
@@ -1584,9 +1574,10 @@ int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
return 0;
}
-int snd_cs4231_get_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1612,9 +1603,10 @@ int snd_cs4231_get_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
return 0;
}
-int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- cs4231_t *chip = snd_kcontrol_chip(kcontrol);
+ struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
@@ -1659,7 +1651,7 @@ int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
.get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-static snd_kcontrol_new_t snd_cs4231_controls[] = {
+static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = {
CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
@@ -1688,9 +1680,9 @@ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
};
-int snd_cs4231_mixer(cs4231_t *chip)
+static int __init snd_cs4231_mixer(struct snd_cs4231 *chip)
{
- snd_card_t *card;
+ struct snd_card *card;
int err, idx;
snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
@@ -1710,9 +1702,9 @@ int snd_cs4231_mixer(cs4231_t *chip)
static int dev;
-static int cs4231_attach_begin(snd_card_t **rcard)
+static int __init cs4231_attach_begin(struct snd_card **rcard)
{
- snd_card_t *card;
+ struct snd_card *card;
*rcard = NULL;
@@ -1735,7 +1727,7 @@ static int cs4231_attach_begin(snd_card_t **rcard)
return 0;
}
-static int cs4231_attach_finish(snd_card_t *card, cs4231_t *chip)
+static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip)
{
int err;
@@ -1748,9 +1740,6 @@ 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;
@@ -1772,7 +1761,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re
unsigned long flags;
unsigned char status;
u32 csr;
- cs4231_t *chip = dev_id;
+ struct snd_cs4231 *chip = dev_id;
/*This is IRQ is not raised by the cs4231*/
if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
@@ -1817,12 +1806,12 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re
* SBUS DMA routines
*/
-int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
{
unsigned long flags;
u32 test, csr;
int err;
- sbus_dma_info_t *base = &dma_cont->sbus_info;
+ struct sbus_dma_info *base = &dma_cont->sbus_info;
if (len >= (1 << 24))
return -EINVAL;
@@ -1849,11 +1838,11 @@ out:
return err;
}
-void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
+static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
{
unsigned long flags;
u32 csr, test;
- sbus_dma_info_t *base = &dma_cont->sbus_info;
+ struct sbus_dma_info *base = &dma_cont->sbus_info;
spin_lock_irqsave(&base->lock, flags);
csr = sbus_readl(base->regs + APCCSR);
@@ -1868,11 +1857,11 @@ void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)
spin_unlock_irqrestore(&base->lock, flags);
}
-void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
+static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
{
unsigned long flags;
u32 csr, shift;
- sbus_dma_info_t *base = &dma_cont->sbus_info;
+ struct sbus_dma_info *base = &dma_cont->sbus_info;
spin_lock_irqsave(&base->lock, flags);
if (!on) {
@@ -1905,14 +1894,14 @@ void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
spin_unlock_irqrestore(&base->lock, flags);
}
-unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)
+static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)
{
- sbus_dma_info_t *base = &dma_cont->sbus_info;
+ struct sbus_dma_info *base = &dma_cont->sbus_info;
return sbus_readl(base->regs + base->dir + APCVA);
}
-void sbus_dma_reset(cs4231_t *chip)
+static void sbus_dma_reset(struct snd_cs4231 *chip)
{
sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
sbus_writel(0x00, chip->port + APCCSR);
@@ -1929,7 +1918,7 @@ void sbus_dma_reset(cs4231_t *chip)
chip->port + APCCSR);
}
-void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
+static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
snd_dma_sbus_data(chip->dev_u.sdev),
@@ -1940,7 +1929,7 @@ void sbus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
* Init and exit routines
*/
-static int snd_cs4231_sbus_free(cs4231_t *chip)
+static int snd_cs4231_sbus_free(struct snd_cs4231 *chip)
{
if (chip->irq[0])
free_irq(chip->irq[0], chip);
@@ -1948,31 +1937,28 @@ static int snd_cs4231_sbus_free(cs4231_t *chip)
if (chip->port)
sbus_iounmap(chip->port, chip->regs_size);
- if (chip->timer)
- snd_device_free(chip->card, chip->timer);
-
kfree(chip);
return 0;
}
-static int snd_cs4231_sbus_dev_free(snd_device_t *device)
+static int snd_cs4231_sbus_dev_free(struct snd_device *device)
{
- cs4231_t *cp = device->device_data;
+ struct snd_cs4231 *cp = device->device_data;
return snd_cs4231_sbus_free(cp);
}
-static snd_device_ops_t snd_cs4231_sbus_dev_ops = {
+static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
.dev_free = snd_cs4231_sbus_dev_free,
};
-static int __init snd_cs4231_sbus_create(snd_card_t *card,
+static int __init snd_cs4231_sbus_create(struct snd_card *card,
struct sbus_dev *sdev,
int dev,
- cs4231_t **rchip)
+ struct snd_cs4231 **rchip)
{
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
int err;
*rchip = NULL;
@@ -2043,11 +2029,11 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
return 0;
}
-static int cs4231_sbus_attach(struct sbus_dev *sdev)
+static int __init cs4231_sbus_attach(struct sbus_dev *sdev)
{
struct resource *rp = &sdev->resource[0];
- cs4231_t *cp;
- snd_card_t *card;
+ struct snd_cs4231 *cp;
+ struct snd_card *card;
int err;
err = cs4231_attach_begin(&card);
@@ -2073,14 +2059,14 @@ static int cs4231_sbus_attach(struct sbus_dev *sdev)
static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
{
- cs4231_t *chip = cookie;
+ struct snd_cs4231 *chip = cookie;
snd_cs4231_play_callback(chip);
}
static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
{
- cs4231_t *chip = cookie;
+ struct snd_cs4231 *chip = cookie;
snd_cs4231_capture_callback(chip);
}
@@ -2089,32 +2075,32 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event,
* EBUS DMA wrappers
*/
-int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
+static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len)
{
return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len);
}
-void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
+static void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on)
{
ebus_dma_enable(&dma_cont->ebus_info, on);
}
-void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir)
+static void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir)
{
ebus_dma_prepare(&dma_cont->ebus_info, dir);
}
-unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont)
+static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont)
{
return ebus_dma_addr(&dma_cont->ebus_info);
}
-void _ebus_dma_reset(cs4231_t *chip)
+static void _ebus_dma_reset(struct snd_cs4231 *chip)
{
return;
}
-void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
+static void _ebus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(chip->dev_u.pdev),
@@ -2125,7 +2111,7 @@ void _ebus_dma_preallocate(cs4231_t *chip, snd_pcm_t *pcm)
* Init and exit routines
*/
-static int snd_cs4231_ebus_free(cs4231_t *chip)
+static int snd_cs4231_ebus_free(struct snd_cs4231 *chip)
{
if (chip->c_dma.ebus_info.regs) {
ebus_dma_unregister(&chip->c_dma.ebus_info);
@@ -2138,31 +2124,29 @@ static int snd_cs4231_ebus_free(cs4231_t *chip)
if (chip->port)
iounmap(chip->port);
- if (chip->timer)
- snd_device_free(chip->card, chip->timer);
kfree(chip);
return 0;
}
-static int snd_cs4231_ebus_dev_free(snd_device_t *device)
+static int snd_cs4231_ebus_dev_free(struct snd_device *device)
{
- cs4231_t *cp = device->device_data;
+ struct snd_cs4231 *cp = device->device_data;
return snd_cs4231_ebus_free(cp);
}
-static snd_device_ops_t snd_cs4231_ebus_dev_ops = {
+static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
.dev_free = snd_cs4231_ebus_dev_free,
};
-static int __init snd_cs4231_ebus_create(snd_card_t *card,
+static int __init snd_cs4231_ebus_create(struct snd_card *card,
struct linux_ebus_device *edev,
int dev,
- cs4231_t **rchip)
+ struct snd_cs4231 **rchip)
{
- cs4231_t *chip;
+ struct snd_cs4231 *chip;
int err;
*rchip = NULL;
@@ -2252,10 +2236,10 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
return 0;
}
-static int cs4231_ebus_attach(struct linux_ebus_device *edev)
+static int __init cs4231_ebus_attach(struct linux_ebus_device *edev)
{
- snd_card_t *card;
- cs4231_t *chip;
+ struct snd_card *card;
+ struct snd_cs4231 *chip;
int err;
err = cs4231_attach_begin(&card);
@@ -2328,10 +2312,10 @@ static int __init cs4231_init(void)
static void __exit cs4231_exit(void)
{
- cs4231_t *p = cs4231_list;
+ struct snd_cs4231 *p = cs4231_list;
while (p != NULL) {
- cs4231_t *next = p->next;
+ struct snd_cs4231 *next = p->next;
snd_card_free(p->card);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 59a771294709..2164b7d290c7 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -299,8 +299,8 @@ struct dbri_desc {
};
/* Per stream (playback or record) information */
-typedef struct dbri_streaminfo {
- snd_pcm_substream_t *substream;
+struct dbri_streaminfo {
+ struct snd_pcm_substream *substream;
u32 dvma_buffer; /* Device view of Alsa DMA buffer */
int left; /* # of bytes left in DMA buffer */
int size; /* Size of DMA buffer */
@@ -309,12 +309,12 @@ typedef struct dbri_streaminfo {
int left_gain; /* mixer elements */
int right_gain;
int balance;
-} dbri_streaminfo_t;
+};
/* This structure holds the information for both chips (DBRI & CS4215) */
-typedef struct snd_dbri {
- snd_card_t *card; /* ALSA card */
- snd_pcm_t *pcm;
+struct snd_dbri {
+ struct snd_card *card; /* ALSA card */
+ struct snd_pcm *pcm;
int regs_size, irq; /* Needed for unload */
struct sbus_dev *sdev; /* SBUS device info */
@@ -341,7 +341,7 @@ typedef struct snd_dbri {
struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
struct snd_dbri *next;
-} snd_dbri_t;
+};
#define DBRI_MAX_VOLUME 63 /* Output volume */
#define DBRI_MAX_GAIN 15 /* Input gain */
@@ -593,7 +593,7 @@ typedef struct snd_dbri {
/* Return a pointer to dbri_streaminfo */
#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)]
-static snd_dbri_t *dbri_list = NULL; /* All DBRI devices */
+static struct snd_dbri *dbri_list = NULL; /* All DBRI devices */
/*
* Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
@@ -652,12 +652,12 @@ to the DBRI.
*/
-static void dbri_process_interrupt_buffer(snd_dbri_t * dbri);
+static void dbri_process_interrupt_buffer(struct snd_dbri * dbri);
-enum dbri_lock_t { NoGetLock, GetLock };
+enum dbri_lock { NoGetLock, GetLock };
#define MAXLOOPS 10
-static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
+static volatile s32 *dbri_cmdlock(struct snd_dbri * dbri, enum dbri_lock get)
{
int maxloops = MAXLOOPS;
@@ -687,7 +687,7 @@ static volatile s32 *dbri_cmdlock(snd_dbri_t * dbri, enum dbri_lock_t get)
return &dbri->dma->cmd[0];
}
-static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
+static void dbri_cmdsend(struct snd_dbri * dbri, volatile s32 * cmd)
{
volatile s32 *ptr;
u32 reg;
@@ -717,7 +717,7 @@ static void dbri_cmdsend(snd_dbri_t * dbri, volatile s32 * cmd)
}
/* Lock must be held when calling this */
-static void dbri_reset(snd_dbri_t * dbri)
+static void dbri_reset(struct snd_dbri * dbri)
{
int i;
@@ -732,7 +732,7 @@ static void dbri_reset(snd_dbri_t * dbri)
}
/* Lock must not be held before calling this */
-static void dbri_initialize(snd_dbri_t * dbri)
+static void dbri_initialize(struct snd_dbri * dbri)
{
volatile s32 *cmd;
u32 dma_addr, tmp;
@@ -795,7 +795,7 @@ list ordering, among other things. The transmit and receive functions
here interface closely with the transmit and receive interrupt code.
*/
-static int pipe_active(snd_dbri_t * dbri, int pipe)
+static int pipe_active(struct snd_dbri * dbri, int pipe)
{
return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1));
}
@@ -805,7 +805,7 @@ static int pipe_active(snd_dbri_t * dbri, int pipe)
* Called on an in-use pipe to clear anything being transmitted or received
* Lock must be held before calling this.
*/
-static void reset_pipe(snd_dbri_t * dbri, int pipe)
+static void reset_pipe(struct snd_dbri * dbri, int pipe)
{
int sdp;
int desc;
@@ -838,7 +838,7 @@ static void reset_pipe(snd_dbri_t * dbri, int pipe)
}
/* FIXME: direction as an argument? */
-static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
+static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp)
{
if (pipe < 0 || pipe > 31) {
printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n");
@@ -869,7 +869,7 @@ static void setup_pipe(snd_dbri_t * dbri, int pipe, int sdp)
}
/* FIXME: direction not needed */
-static void link_time_slot(snd_dbri_t * dbri, int pipe,
+static void link_time_slot(struct snd_dbri * dbri, int pipe,
enum in_or_out direction, int basepipe,
int length, int cycle)
{
@@ -959,7 +959,7 @@ static void link_time_slot(snd_dbri_t * dbri, int pipe,
dbri_cmdsend(dbri, cmd);
}
-static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
+static void unlink_time_slot(struct snd_dbri * dbri, int pipe,
enum in_or_out direction, int prevpipe,
int nextpipe)
{
@@ -1003,7 +1003,7 @@ static void unlink_time_slot(snd_dbri_t * dbri, int pipe,
* in the low-order 8 bits, filled either MSB-first or LSB-first,
* depending on the settings passed to setup_pipe()
*/
-static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
+static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data)
{
volatile s32 *cmd;
@@ -1040,7 +1040,7 @@ static void xmit_fixed(snd_dbri_t * dbri, int pipe, unsigned int data)
dbri_cmdsend(dbri, cmd);
}
-static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
+static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr)
{
if (pipe < 16 || pipe > 31) {
printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n");
@@ -1072,9 +1072,9 @@ static void recv_fixed(snd_dbri_t * dbri, int pipe, volatile __u32 * ptr)
* data buffers. Buffers too large for a single descriptor will
* be spread across multiple descriptors.
*/
-static int setup_descs(snd_dbri_t * dbri, int streamno, unsigned int period)
+static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period)
{
- dbri_streaminfo_t *info = &dbri->stream_info[streamno];
+ struct dbri_streaminfo *info = &dbri->stream_info[streamno];
__u32 dvma_buffer;
int desc = 0;
int len;
@@ -1207,7 +1207,7 @@ multiplexed serial interface which the DBRI can operate in either master
enum master_or_slave { CHImaster, CHIslave };
-static void reset_chi(snd_dbri_t * dbri, enum master_or_slave master_or_slave,
+static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave,
int bits_per_frame)
{
volatile s32 *cmd;
@@ -1308,7 +1308,7 @@ In the standard SPARC audio configuration, the CS4215 codec is attached
to the DBRI via the CHI interface and few of the DBRI's PIO pins.
*/
-static void cs4215_setup_pipes(snd_dbri_t * dbri)
+static void cs4215_setup_pipes(struct snd_dbri * dbri)
{
/*
* Data mode:
@@ -1369,7 +1369,7 @@ static int cs4215_init_data(struct cs4215 *mm)
return 0;
}
-static void cs4215_setdata(snd_dbri_t * dbri, int muted)
+static void cs4215_setdata(struct snd_dbri * dbri, int muted)
{
if (muted) {
dbri->mm.data[0] |= 63;
@@ -1378,7 +1378,7 @@ static void cs4215_setdata(snd_dbri_t * dbri, int muted)
dbri->mm.data[3] &= ~15;
} else {
/* Start by setting the playback attenuation. */
- dbri_streaminfo_t *info = &dbri->stream_info[DBRI_PLAY];
+ struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY];
int left_gain = info->left_gain % 64;
int right_gain = info->right_gain % 64;
@@ -1409,7 +1409,7 @@ static void cs4215_setdata(snd_dbri_t * dbri, int muted)
/*
* Set the CS4215 to data mode.
*/
-static void cs4215_open(snd_dbri_t * dbri)
+static void cs4215_open(struct snd_dbri * dbri)
{
int data_width;
u32 tmp;
@@ -1471,7 +1471,7 @@ static void cs4215_open(snd_dbri_t * dbri)
/*
* Send the control information (i.e. audio format)
*/
-static int cs4215_setctrl(snd_dbri_t * dbri)
+static int cs4215_setctrl(struct snd_dbri * dbri)
{
int i, val;
u32 tmp;
@@ -1570,7 +1570,7 @@ static int cs4215_setctrl(snd_dbri_t * dbri)
* As part of the process we resend the settings for the data
* timeslots as well.
*/
-static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate,
+static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate,
snd_pcm_format_t format, unsigned int channels)
{
int freq_idx;
@@ -1628,7 +1628,7 @@ static int cs4215_prepare(snd_dbri_t * dbri, unsigned int rate,
/*
*
*/
-static int cs4215_init(snd_dbri_t * dbri)
+static int cs4215_init(struct snd_dbri * dbri)
{
u32 reg2 = sbus_readl(dbri->regs + REG2);
dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
@@ -1697,8 +1697,8 @@ even if we're running cli'ed.
*/
static void xmit_descs(unsigned long data)
{
- snd_dbri_t *dbri = (snd_dbri_t *) data;
- dbri_streaminfo_t *info;
+ struct snd_dbri *dbri = (struct snd_dbri *) data;
+ struct dbri_streaminfo *info;
volatile s32 *cmd;
unsigned long flags;
int first_td;
@@ -1780,9 +1780,9 @@ static DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0);
* done by the xmit_descs() tasklet above since that could take longer.
*/
-static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
+static void transmission_complete_intr(struct snd_dbri * dbri, int pipe)
{
- dbri_streaminfo_t *info;
+ struct dbri_streaminfo *info;
int td;
int status;
@@ -1830,9 +1830,9 @@ static void transmission_complete_intr(snd_dbri_t * dbri, int pipe)
snd_pcm_period_elapsed(info->substream);
}
-static void reception_complete_intr(snd_dbri_t * dbri, int pipe)
+static void reception_complete_intr(struct snd_dbri * dbri, int pipe)
{
- dbri_streaminfo_t *info;
+ struct dbri_streaminfo *info;
int rd = dbri->pipes[pipe].desc;
s32 status;
@@ -1874,7 +1874,7 @@ static void reception_complete_intr(snd_dbri_t * dbri, int pipe)
snd_pcm_period_elapsed(info->substream);
}
-static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
+static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x)
{
int val = D_INTR_GETVAL(x);
int channel = D_INTR_GETCHAN(x);
@@ -1950,7 +1950,7 @@ static void dbri_process_one_interrupt(snd_dbri_t * dbri, int x)
* order is important since we might recurse back into this function
* and need to make sure the pointer has been advanced first.
*/
-static void dbri_process_interrupt_buffer(snd_dbri_t * dbri)
+static void dbri_process_interrupt_buffer(struct snd_dbri * dbri)
{
s32 x;
@@ -1969,7 +1969,7 @@ static void dbri_process_interrupt_buffer(snd_dbri_t * dbri)
static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- snd_dbri_t *dbri = dev_id;
+ struct snd_dbri *dbri = dev_id;
static int errcnt = 0;
int x;
@@ -2030,7 +2030,7 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id,
/****************************************************************************
PCM Interface
****************************************************************************/
-static snd_pcm_hardware_t snd_dbri_pcm_hw = {
+static struct snd_pcm_hardware snd_dbri_pcm_hw = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -2051,11 +2051,11 @@ static snd_pcm_hardware_t snd_dbri_pcm_hw = {
.periods_max = 1024,
};
-static int snd_dbri_open(snd_pcm_substream_t * substream)
+static int snd_dbri_open(struct snd_pcm_substream *substream)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
unsigned long flags;
dprintk(D_USR, "open audio output.\n");
@@ -2074,10 +2074,10 @@ static int snd_dbri_open(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_dbri_close(snd_pcm_substream_t * substream)
+static int snd_dbri_close(struct snd_pcm_substream *substream)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
dprintk(D_USR, "close audio output.\n");
info->substream = NULL;
@@ -2087,12 +2087,12 @@ static int snd_dbri_close(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
- snd_pcm_hw_params_t * hw_params)
+static int snd_dbri_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
int direction;
int ret;
@@ -2129,10 +2129,10 @@ static int snd_dbri_hw_params(snd_pcm_substream_t * substream,
return 0;
}
-static int snd_dbri_hw_free(snd_pcm_substream_t * substream)
+static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
int direction;
dprintk(D_USR, "hw_free.\n");
@@ -2153,11 +2153,11 @@ static int snd_dbri_hw_free(snd_pcm_substream_t * substream)
return snd_pcm_lib_free_pages(substream);
}
-static int snd_dbri_prepare(snd_pcm_substream_t * substream)
+static int snd_dbri_prepare(struct snd_pcm_substream *substream)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
info->size = snd_pcm_lib_buffer_bytes(substream);
@@ -2184,10 +2184,10 @@ static int snd_dbri_prepare(snd_pcm_substream_t * substream)
return ret;
}
-static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd)
+static int snd_dbri_trigger(struct snd_pcm_substream *substream, int cmd)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
int ret = 0;
switch (cmd) {
@@ -2211,10 +2211,10 @@ static int snd_dbri_trigger(snd_pcm_substream_t * substream, int cmd)
return ret;
}
-static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t snd_dbri_pointer(struct snd_pcm_substream *substream)
{
- snd_dbri_t *dbri = snd_pcm_substream_chip(substream);
- dbri_streaminfo_t *info = DBRI_STREAM(dbri, substream);
+ struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
+ struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
snd_pcm_uframes_t ret;
ret = bytes_to_frames(substream->runtime, info->offset)
@@ -2224,7 +2224,7 @@ static snd_pcm_uframes_t snd_dbri_pointer(snd_pcm_substream_t * substream)
return ret;
}
-static snd_pcm_ops_t snd_dbri_ops = {
+static struct snd_pcm_ops snd_dbri_ops = {
.open = snd_dbri_open,
.close = snd_dbri_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -2235,9 +2235,9 @@ static snd_pcm_ops_t snd_dbri_ops = {
.pointer = snd_dbri_pointer,
};
-static int __devinit snd_dbri_pcm(snd_dbri_t * dbri)
+static int __devinit snd_dbri_pcm(struct snd_dbri * dbri)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(dbri->card,
@@ -2270,8 +2270,8 @@ static int __devinit snd_dbri_pcm(snd_dbri_t * dbri)
Mixer interface
*****************************************************************************/
-static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
@@ -2284,11 +2284,11 @@ static int snd_cs4215_info_volume(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_get_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
- dbri_streaminfo_t *info;
+ struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
+ struct dbri_streaminfo *info;
snd_assert(dbri != NULL, return -EINVAL);
info = &dbri->stream_info[kcontrol->private_value];
snd_assert(info != NULL, return -EINVAL);
@@ -2298,11 +2298,11 @@ static int snd_cs4215_get_volume(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
- dbri_streaminfo_t *info = &dbri->stream_info[kcontrol->private_value];
+ struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
+ struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value];
unsigned long flags;
int changed = 0;
@@ -2329,8 +2329,8 @@ static int snd_cs4215_put_volume(snd_kcontrol_t * kcontrol,
return changed;
}
-static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_info_t * uinfo)
+static int snd_cs4215_info_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -2342,10 +2342,10 @@ static int snd_cs4215_info_single(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
+ struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
int elem = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -2367,10 +2367,10 @@ static int snd_cs4215_get_single(snd_kcontrol_t * kcontrol,
return 0;
}
-static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol,
- snd_ctl_elem_value_t * ucontrol)
+static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- snd_dbri_t *dbri = snd_kcontrol_chip(kcontrol);
+ struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int elem = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
@@ -2425,7 +2425,7 @@ static int snd_cs4215_put_single(snd_kcontrol_t * kcontrol,
.get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \
.private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) },
-static snd_kcontrol_new_t dbri_controls[] __devinitdata = {
+static struct snd_kcontrol_new dbri_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Playback Volume",
@@ -2452,11 +2452,11 @@ static snd_kcontrol_new_t dbri_controls[] __devinitdata = {
CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
};
-#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(snd_kcontrol_new_t))
+#define NUM_CS4215_CONTROLS (sizeof(dbri_controls)/sizeof(struct snd_kcontrol_new))
-static int __init snd_dbri_mixer(snd_dbri_t * dbri)
+static int __init snd_dbri_mixer(struct snd_dbri * dbri)
{
- snd_card_t *card;
+ struct snd_card *card;
int idx, err;
snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL);
@@ -2482,9 +2482,9 @@ static int __init snd_dbri_mixer(snd_dbri_t * dbri)
/****************************************************************************
/proc interface
****************************************************************************/
-static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
{
- snd_dbri_t *dbri = entry->private_data;
+ struct snd_dbri *dbri = entry->private_data;
snd_iprintf(buffer, "REG0: 0x%x\n", sbus_readl(dbri->regs + REG0));
snd_iprintf(buffer, "REG2: 0x%x\n", sbus_readl(dbri->regs + REG2));
@@ -2493,10 +2493,10 @@ static void dbri_regs_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
}
#ifdef DBRI_DEBUG
-static void dbri_debug_read(snd_info_entry_t * entry,
- snd_info_buffer_t * buffer)
+static void dbri_debug_read(struct snd_info_entry * entry,
+ struct snd_info_buffer *buffer)
{
- snd_dbri_t *dbri = entry->private_data;
+ struct snd_dbri *dbri = entry->private_data;
int pipe;
snd_iprintf(buffer, "debug=%d\n", dbri_debug);
@@ -2516,18 +2516,18 @@ static void dbri_debug_read(snd_info_entry_t * entry,
}
#endif
-void snd_dbri_proc(snd_dbri_t * dbri)
+void snd_dbri_proc(struct snd_dbri * dbri)
{
- snd_info_entry_t *entry;
- int err;
+ struct snd_info_entry *entry;
- err = snd_card_proc_new(dbri->card, "regs", &entry);
- snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read);
+ if (! snd_card_proc_new(dbri->card, "regs", &entry))
+ snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read);
#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; /* Readable only. */
+ if (! 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; /* Readable only. */
+ }
#endif
}
@@ -2536,13 +2536,13 @@ void snd_dbri_proc(snd_dbri_t * dbri)
**************************** Initialization ********************************
****************************************************************************
*/
-static void snd_dbri_free(snd_dbri_t * dbri);
+static void snd_dbri_free(struct snd_dbri * dbri);
-static int __init snd_dbri_create(snd_card_t * card,
+static int __init snd_dbri_create(struct snd_card *card,
struct sbus_dev *sdev,
struct linux_prom_irqs *irq, int dev)
{
- snd_dbri_t *dbri = card->private_data;
+ struct snd_dbri *dbri = card->private_data;
int err;
spin_lock_init(&dbri->lock);
@@ -2593,7 +2593,7 @@ static int __init snd_dbri_create(snd_card_t * card,
return 0;
}
-static void snd_dbri_free(snd_dbri_t * dbri)
+static void snd_dbri_free(struct snd_dbri * dbri)
{
dprintk(D_GEN, "snd_dbri_free\n");
dbri_reset(dbri);
@@ -2611,10 +2611,10 @@ static void snd_dbri_free(snd_dbri_t * dbri)
static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
{
- snd_dbri_t *dbri;
+ struct snd_dbri *dbri;
struct linux_prom_irqs irq;
struct resource *rp;
- snd_card_t *card;
+ struct snd_card *card;
static int dev = 0;
int err;
@@ -2638,7 +2638,7 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
}
card = snd_card_new(index[dev], id[dev], THIS_MODULE,
- sizeof(snd_dbri_t));
+ sizeof(struct snd_dbri));
if (card == NULL)
return -ENOMEM;
@@ -2654,7 +2654,7 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
return err;
}
- dbri = (snd_dbri_t *) card->private_data;
+ dbri = card->private_data;
if ((err = snd_dbri_pcm(dbri)) < 0)
goto _err;
@@ -2664,9 +2664,6 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev)
/* /proc file handling */
snd_dbri_proc(dbri);
- if ((err = snd_card_set_generic_dev(card)) < 0)
- goto _err;
-
if ((err = snd_card_register(card)) < 0)
goto _err;
@@ -2709,11 +2706,11 @@ static int __init dbri_init(void)
static void __exit dbri_exit(void)
{
- snd_dbri_t *this = dbri_list;
+ struct snd_dbri *this = dbri_list;
while (this != NULL) {
- snd_dbri_t *next = this->next;
- snd_card_t *card = this->card;
+ struct snd_dbri *next = this->next;
+ struct snd_card *card = this->card;
snd_dbri_free(this);
snd_card_free(card);
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 9e2b4c0c8a8a..7c8e328fae62 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -35,9 +35,9 @@ MODULE_LICENSE("GPL");
/*
* create a new hardware dependent device for Emu8000/Emu10k1
*/
-int snd_emux_new(snd_emux_t **remu)
+int snd_emux_new(struct snd_emux **remu)
{
- snd_emux_t *emu;
+ struct snd_emux *emu;
*remu = NULL;
emu = kzalloc(sizeof(*emu), GFP_KERNEL);
@@ -66,10 +66,33 @@ int snd_emux_new(snd_emux_t **remu)
/*
*/
-int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
+static int sf_sample_new(void *private_data, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr,
+ const void __user *buf, long count)
+{
+ struct snd_emux *emu = private_data;
+ return emu->ops.sample_new(emu, sp, hdr, buf, count);
+
+}
+
+static int sf_sample_free(void *private_data, struct snd_sf_sample *sp,
+ struct snd_util_memhdr *hdr)
+{
+ struct snd_emux *emu = private_data;
+ return emu->ops.sample_free(emu, sp, hdr);
+
+}
+
+static void sf_sample_reset(void *private_data)
+{
+ struct snd_emux *emu = private_data;
+ emu->ops.sample_reset(emu);
+}
+
+int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name)
{
int err;
- snd_sf_callback_t sf_cb;
+ struct snd_sf_callback sf_cb;
snd_assert(emu->hw != NULL, return -EINVAL);
snd_assert(emu->max_voices > 0, return -EINVAL);
@@ -78,16 +101,20 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
emu->card = card;
emu->name = kstrdup(name, GFP_KERNEL);
- emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
+ emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice),
+ GFP_KERNEL);
if (emu->voices == NULL)
return -ENOMEM;
/* create soundfont list */
memset(&sf_cb, 0, sizeof(sf_cb));
sf_cb.private_data = emu;
- sf_cb.sample_new = (snd_sf_sample_new_t)emu->ops.sample_new;
- sf_cb.sample_free = (snd_sf_sample_free_t)emu->ops.sample_free;
- sf_cb.sample_reset = (snd_sf_sample_reset_t)emu->ops.sample_reset;
+ if (emu->ops.sample_new)
+ sf_cb.sample_new = sf_sample_new;
+ if (emu->ops.sample_free)
+ sf_cb.sample_free = sf_sample_free;
+ if (emu->ops.sample_reset)
+ sf_cb.sample_reset = sf_sample_reset;
emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
if (emu->sflist == NULL)
return -ENOMEM;
@@ -112,7 +139,7 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
/*
*/
-int snd_emux_free(snd_emux_t *emu)
+int snd_emux_free(struct snd_emux *emu)
{
unsigned long flags;
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
index 4764940f11a0..a447218b6160 100644
--- a/sound/synth/emux/emux_effect.c
+++ b/sound/synth/emux/emux_effect.c
@@ -32,7 +32,7 @@
#define xoffsetof(type,tag) ((long)(&((type)NULL)->tag) - (long)(NULL))
-#define parm_offset(tag) xoffsetof(soundfont_voice_parm_t*, tag)
+#define parm_offset(tag) xoffsetof(struct soundfont_voice_parm *, tag)
#define PARM_IS_BYTE (1 << 0)
#define PARM_IS_WORD (1 << 1)
@@ -97,10 +97,10 @@ static struct emux_parm_defs {
/* set byte effect value */
static void
-effect_set_byte(unsigned char *valp, snd_midi_channel_t *chan, int type)
+effect_set_byte(unsigned char *valp, struct snd_midi_channel *chan, int type)
{
short effect;
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
effect = fx->val[type];
if (fx->flag[type] == EMUX_FX_FLAG_ADD) {
@@ -118,10 +118,10 @@ effect_set_byte(unsigned char *valp, snd_midi_channel_t *chan, int type)
/* set word effect value */
static void
-effect_set_word(unsigned short *valp, snd_midi_channel_t *chan, int type)
+effect_set_word(unsigned short *valp, struct snd_midi_channel *chan, int type)
{
int effect;
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
effect = *(unsigned short*)&fx->val[type];
if (fx->flag[type] == EMUX_FX_FLAG_ADD)
@@ -135,10 +135,10 @@ effect_set_word(unsigned short *valp, snd_midi_channel_t *chan, int type)
/* address offset */
static int
-effect_get_offset(snd_midi_channel_t *chan, int lo, int hi, int mode)
+effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode)
{
int addr = 0;
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
if (fx->flag[hi])
addr = (short)fx->val[hi];
@@ -153,7 +153,8 @@ effect_get_offset(snd_midi_channel_t *chan, int lo, int hi, int mode)
#ifdef CONFIG_SND_SEQUENCER_OSS
/* change effects - for OSS sequencer compatibility */
void
-snd_emux_send_effect_oss(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val)
+snd_emux_send_effect_oss(struct snd_emux_port *port,
+ struct snd_midi_channel *chan, int type, int val)
{
int mode;
@@ -173,13 +174,14 @@ snd_emux_send_effect_oss(snd_emux_port_t *port, snd_midi_channel_t *chan, int ty
* if update is necessary, call emu8000_control
*/
void
-snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val, int mode)
+snd_emux_send_effect(struct snd_emux_port *port, struct snd_midi_channel *chan,
+ int type, int val, int mode)
{
int i;
int offset;
unsigned char *srcp, *origp;
- snd_emux_t *emu;
- snd_emux_effect_table_t *fx;
+ struct snd_emux *emu;
+ struct snd_emux_effect_table *fx;
unsigned long flags;
emu = port->emu;
@@ -206,7 +208,7 @@ snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type,
/* modify the register values */
spin_lock_irqsave(&emu->voice_lock, flags);
for (i = 0; i < emu->max_voices; i++) {
- snd_emux_voice_t *vp = &emu->voices[i];
+ struct snd_emux_voice *vp = &emu->voices[i];
if (!STATE_IS_PLAYING(vp->state) || vp->chan != chan)
continue;
srcp = (unsigned char*)&vp->reg.parm + offset;
@@ -228,10 +230,10 @@ snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type,
/* copy wavetable registers to voice table */
void
-snd_emux_setup_effect(snd_emux_voice_t *vp)
+snd_emux_setup_effect(struct snd_emux_voice *vp)
{
- snd_midi_channel_t *chan = vp->chan;
- snd_emux_effect_table_t *fx;
+ struct snd_midi_channel *chan = vp->chan;
+ struct snd_emux_effect_table *fx;
unsigned char *srcp;
int i;
@@ -275,10 +277,11 @@ snd_emux_setup_effect(snd_emux_voice_t *vp)
* effect table
*/
void
-snd_emux_create_effect(snd_emux_port_t *p)
+snd_emux_create_effect(struct snd_emux_port *p)
{
int i;
- p->effect = kcalloc(p->chset.max_channels, sizeof(snd_emux_effect_table_t), GFP_KERNEL);
+ p->effect = kcalloc(p->chset.max_channels,
+ sizeof(struct snd_emux_effect_table), GFP_KERNEL);
if (p->effect) {
for (i = 0; i < p->chset.max_channels; i++)
p->chset.channels[i].private = p->effect + i;
@@ -289,17 +292,18 @@ snd_emux_create_effect(snd_emux_port_t *p)
}
void
-snd_emux_delete_effect(snd_emux_port_t *p)
+snd_emux_delete_effect(struct snd_emux_port *p)
{
kfree(p->effect);
p->effect = NULL;
}
void
-snd_emux_clear_effect(snd_emux_port_t *p)
+snd_emux_clear_effect(struct snd_emux_port *p)
{
if (p->effect) {
- memset(p->effect, 0, sizeof(snd_emux_effect_table_t) * p->chset.max_channels);
+ memset(p->effect, 0, sizeof(struct snd_emux_effect_table) *
+ p->chset.max_channels);
}
}
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index 4182b44eb47e..9b63814c3f64 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -29,7 +29,7 @@
* open the hwdep device
*/
static int
-snd_emux_hwdep_open(snd_hwdep_t *hw, struct file *file)
+snd_emux_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
@@ -39,7 +39,7 @@ snd_emux_hwdep_open(snd_hwdep_t *hw, struct file *file)
* close the device
*/
static int
-snd_emux_hwdep_release(snd_hwdep_t *hw, struct file *file)
+snd_emux_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
@@ -51,10 +51,10 @@ snd_emux_hwdep_release(snd_hwdep_t *hw, struct file *file)
* load patch
*/
static int
-snd_emux_hwdep_load_patch(snd_emux_t *emu, void __user *arg)
+snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg)
{
int err;
- soundfont_patch_info_t patch;
+ struct soundfont_patch_info patch;
if (copy_from_user(&patch, arg, sizeof(patch)))
return -EFAULT;
@@ -77,9 +77,9 @@ snd_emux_hwdep_load_patch(snd_emux_t *emu, void __user *arg)
* set misc mode
*/
static int
-snd_emux_hwdep_misc_mode(snd_emux_t *emu, void __user *arg)
+snd_emux_hwdep_misc_mode(struct snd_emux *emu, void __user *arg)
{
- struct sndrv_emux_misc_mode info;
+ struct snd_emux_misc_mode info;
int i;
if (copy_from_user(&info, arg, sizeof(info)))
@@ -102,9 +102,10 @@ snd_emux_hwdep_misc_mode(snd_emux_t *emu, void __user *arg)
* ioctl
*/
static int
-snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
+snd_emux_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
- snd_emux_t *emu = hw->private_data;
+ struct snd_emux *emu = hw->private_data;
switch (cmd) {
case SNDRV_EMUX_IOCTL_VERSION:
@@ -136,9 +137,9 @@ snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsi
*/
int
-snd_emux_init_hwdep(snd_emux_t *emu)
+snd_emux_init_hwdep(struct snd_emux *emu)
{
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
int err;
if ((err = snd_hwdep_new(emu->card, SNDRV_EMUX_HWDEP_NAME, emu->hwdep_idx, &hw)) < 0)
@@ -162,7 +163,7 @@ snd_emux_init_hwdep(snd_emux_t *emu)
* unregister
*/
void
-snd_emux_delete_hwdep(snd_emux_t *emu)
+snd_emux_delete_hwdep(struct snd_emux *emu)
{
if (emu->hwdep) {
snd_device_free(emu->card, emu->hwdep);
diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
index 25edff9e1fc2..c6917ba2c934 100644
--- a/sound/synth/emux/emux_nrpn.c
+++ b/sound/synth/emux/emux_nrpn.c
@@ -27,11 +27,11 @@
*/
/* NRPN / CC -> Emu8000 parameter converter */
-typedef struct {
+struct nrpn_conv_table {
int control;
int effect;
int (*convert)(int val);
-} nrpn_conv_table;
+};
/* effect sensitivity */
@@ -48,8 +48,9 @@ typedef struct {
* convert NRPN/control values
*/
-static int send_converted_effect(nrpn_conv_table *table, int num_tables,
- snd_emux_port_t *port, snd_midi_channel_t *chan,
+static int send_converted_effect(struct nrpn_conv_table *table, int num_tables,
+ struct snd_emux_port *port,
+ struct snd_midi_channel *chan,
int type, int val, int mode)
{
int i, cval;
@@ -178,7 +179,7 @@ static int fx_conv_Q(int val)
}
-static nrpn_conv_table awe_effects[] =
+static struct nrpn_conv_table awe_effects[] =
{
{ 0, EMUX_FX_LFO1_DELAY, fx_lfo1_delay},
{ 1, EMUX_FX_LFO1_FREQ, fx_lfo1_freq},
@@ -265,7 +266,7 @@ static int gs_vib_delay(int val)
return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
}
-static nrpn_conv_table gs_effects[] =
+static struct nrpn_conv_table gs_effects[] =
{
{32, EMUX_FX_CUTOFF, gs_cutoff},
{33, EMUX_FX_FILTERQ, gs_filterQ},
@@ -282,9 +283,10 @@ static nrpn_conv_table gs_effects[] =
* NRPN events
*/
void
-snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
+snd_emux_nrpn(void *p, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset)
{
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL, return);
@@ -348,7 +350,7 @@ static int xg_release(int val)
return -(val - 64) * xg_sense[FX_RELEASE] / 64;
}
-static nrpn_conv_table xg_effects[] =
+static struct nrpn_conv_table xg_effects[] =
{
{71, EMUX_FX_CUTOFF, xg_cutoff},
{74, EMUX_FX_FILTERQ, xg_filterQ},
@@ -357,7 +359,8 @@ static nrpn_conv_table xg_effects[] =
};
int
-snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
+snd_emux_xg_control(struct snd_emux_port *port, struct snd_midi_channel *chan,
+ int param)
{
return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
port, chan, param,
@@ -369,10 +372,11 @@ snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
* receive sysex
*/
void
-snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset)
+snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed,
+ struct snd_midi_channel_set *chset)
{
- snd_emux_port_t *port;
- snd_emux_t *emu;
+ struct snd_emux_port *port;
+ struct snd_emux *emu;
port = p;
snd_assert(port != NULL, return);
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index 5272f4ac8afd..dfbfcfbe5dd2 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -31,19 +31,25 @@
#include "emux_voice.h"
#include <sound/asoundef.h>
-static int snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure);
-static int snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg);
-static int snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg);
-static int snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format, const char __user *buf, int offs, int count);
-static int snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg);
-static int snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop);
-static void reset_port_mode(snd_emux_port_t *port, int midi_mode);
-static void emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd, unsigned char *event, int atomic, int hop);
-static void gusspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd, unsigned char *event, int atomic, int hop);
-static void fake_event(snd_emux_t *emu, snd_emux_port_t *port, int ch, int param, int val, int atomic, int hop);
+static int snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure);
+static int snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg);
+static int snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
+ unsigned long ioarg);
+static int snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
+ const char __user *buf, int offs, int count);
+static int snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg);
+static int snd_emux_event_oss_input(struct snd_seq_event *ev, int direct,
+ void *private, int atomic, int hop);
+static void reset_port_mode(struct snd_emux_port *port, int midi_mode);
+static void emuspec_control(struct snd_emux *emu, struct snd_emux_port *port,
+ int cmd, unsigned char *event, int atomic, int hop);
+static void gusspec_control(struct snd_emux *emu, struct snd_emux_port *port,
+ int cmd, unsigned char *event, int atomic, int hop);
+static void fake_event(struct snd_emux *emu, struct snd_emux_port *port,
+ int ch, int param, int val, int atomic, int hop);
/* operators */
-static snd_seq_oss_callback_t oss_callback = {
+static struct snd_seq_oss_callback oss_callback = {
.owner = THIS_MODULE,
.open = snd_emux_open_seq_oss,
.close = snd_emux_close_seq_oss,
@@ -58,13 +64,13 @@ static snd_seq_oss_callback_t oss_callback = {
*/
void
-snd_emux_init_seq_oss(snd_emux_t *emu)
+snd_emux_init_seq_oss(struct snd_emux *emu)
{
- snd_seq_oss_reg_t *arg;
- snd_seq_device_t *dev;
+ struct snd_seq_oss_reg *arg;
+ struct snd_seq_device *dev;
if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS,
- sizeof(snd_seq_oss_reg_t), &dev) < 0)
+ sizeof(struct snd_seq_oss_reg), &dev) < 0)
return;
emu->oss_synth = dev;
@@ -85,7 +91,7 @@ snd_emux_init_seq_oss(snd_emux_t *emu)
* unregister
*/
void
-snd_emux_detach_seq_oss(snd_emux_t *emu)
+snd_emux_detach_seq_oss(struct snd_emux *emu)
{
if (emu->oss_synth) {
snd_device_free(emu->card, emu->oss_synth);
@@ -101,11 +107,11 @@ snd_emux_detach_seq_oss(snd_emux_t *emu)
* open port for OSS sequencer
*/
static int
-snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
+snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
{
- snd_emux_t *emu;
- snd_emux_port_t *p;
- snd_seq_port_callback_t callback;
+ struct snd_emux *emu;
+ struct snd_emux_port *p;
+ struct snd_seq_port_callback callback;
char tmpname[64];
emu = closure;
@@ -153,7 +159,7 @@ snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
* reset port mode
*/
static void
-reset_port_mode(snd_emux_port_t *port, int midi_mode)
+reset_port_mode(struct snd_emux_port *port, int midi_mode)
{
if (midi_mode) {
port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_MIDI;
@@ -173,10 +179,10 @@ reset_port_mode(snd_emux_port_t *port, int midi_mode)
* close port
*/
static int
-snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg)
+snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
{
- snd_emux_t *emu;
- snd_emux_port_t *p;
+ struct snd_emux *emu;
+ struct snd_emux_port *p;
snd_assert(arg != NULL, return -ENXIO);
p = arg->private_data;
@@ -200,11 +206,11 @@ snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg)
* load patch
*/
static int
-snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
+snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
const char __user *buf, int offs, int count)
{
- snd_emux_t *emu;
- snd_emux_port_t *p;
+ struct snd_emux *emu;
+ struct snd_emux_port *p;
int rc;
snd_assert(arg != NULL, return -ENXIO);
@@ -218,7 +224,7 @@ snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
rc = snd_soundfont_load_guspatch(emu->sflist, buf, count,
SF_CLIENT_NO(p->chset.port));
else if (format == SNDRV_OSS_SOUNDFONT_PATCH) {
- soundfont_patch_info_t patch;
+ struct soundfont_patch_info patch;
if (count < (int)sizeof(patch))
rc = -EINVAL;
if (copy_from_user(&patch, buf, sizeof(patch)))
@@ -242,10 +248,10 @@ snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
* ioctl
*/
static int
-snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg)
+snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg)
{
- snd_emux_port_t *p;
- snd_emux_t *emu;
+ struct snd_emux_port *p;
+ struct snd_emux *emu;
snd_assert(arg != NULL, return -ENXIO);
p = arg->private_data;
@@ -273,9 +279,9 @@ snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long i
* reset device
*/
static int
-snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg)
+snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg)
{
- snd_emux_port_t *p;
+ struct snd_emux_port *p;
snd_assert(arg != NULL, return -ENXIO);
p = arg->private_data;
@@ -289,11 +295,11 @@ snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg)
* receive raw events: only SEQ_PRIVATE is accepted.
*/
static int
-snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private_data,
+snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, void *private_data,
int atomic, int hop)
{
- snd_emux_t *emu;
- snd_emux_port_t *p;
+ struct snd_emux *emu;
+ struct snd_emux_port *p;
unsigned char cmd, *data;
p = private_data;
@@ -320,14 +326,14 @@ snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private_data,
* OSS/AWE driver specific h/w controls
*/
static void
-emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
+emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd,
unsigned char *event, int atomic, int hop)
{
int voice;
unsigned short p1;
short p2;
int i;
- snd_midi_channel_t *chan;
+ struct snd_midi_channel *chan;
voice = event[3];
if (voice < 0 || voice >= port->chset.max_channels)
@@ -415,14 +421,14 @@ emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
#include <linux/ultrasound.h>
static void
-gusspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
+gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd,
unsigned char *event, int atomic, int hop)
{
int voice;
unsigned short p1;
short p2;
int plong;
- snd_midi_channel_t *chan;
+ struct snd_midi_channel *chan;
if (port->port_mode != SNDRV_EMUX_PORT_MODE_OSS_SYNTH)
return;
@@ -483,9 +489,9 @@ gusspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
* send an event to midi emulation
*/
static void
-fake_event(snd_emux_t *emu, snd_emux_port_t *port, int ch, int param, int val, int atomic, int hop)
+fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, int val, int atomic, int hop)
{
- snd_seq_event_t ev;
+ struct snd_seq_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
ev.data.control.channel = ch;
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index 0f155d68de0d..a70a179f6947 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -30,10 +30,10 @@
#ifdef CONFIG_PROC_FS
static void
-snd_emux_proc_info_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buf)
+snd_emux_proc_info_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buf)
{
- snd_emux_t *emu;
+ struct snd_emux *emu;
int i;
emu = entry->private_data;
@@ -66,7 +66,7 @@ snd_emux_proc_info_read(snd_info_entry_t *entry,
}
#if 0 /* debug */
if (emu->voices[0].state != SNDRV_EMUX_ST_OFF && emu->voices[0].ch >= 0) {
- snd_emux_voice_t *vp = &emu->voices[0];
+ struct snd_emux_voice *vp = &emu->voices[0];
snd_iprintf(buf, "voice 0: on\n");
snd_iprintf(buf, "mod delay=%x, atkhld=%x, dcysus=%x, rel=%x\n",
vp->reg.parm.moddelay,
@@ -107,9 +107,9 @@ snd_emux_proc_info_read(snd_info_entry_t *entry,
}
-void snd_emux_proc_init(snd_emux_t *emu, snd_card_t *card, int device)
+void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
char name[64];
sprintf(name, "wavetableD%d", device);
@@ -127,7 +127,7 @@ void snd_emux_proc_init(snd_emux_t *emu, snd_card_t *card, int device)
emu->proc = entry;
}
-void snd_emux_proc_free(snd_emux_t *emu)
+void snd_emux_proc_free(struct snd_emux *emu)
{
if (emu->proc) {
snd_info_unregister(emu->proc);
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 8ccd33f4aa57..1a973d7a90f8 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -25,15 +25,14 @@
/* Prototypes for static functions */
static void free_port(void *private);
-static void snd_emux_init_port(snd_emux_port_t *p);
-static int snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info);
-static int snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info);
-static int get_client(snd_card_t *card, int index, char *name);
+static void snd_emux_init_port(struct snd_emux_port *p);
+static int snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info);
+static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info);
/*
* MIDI emulation operators
*/
-static snd_midi_op_t emux_ops = {
+static struct snd_midi_op emux_ops = {
snd_emux_note_on,
snd_emux_note_off,
snd_emux_key_press,
@@ -65,14 +64,14 @@ static snd_midi_op_t emux_ops = {
* can connect to these ports to play midi data.
*/
int
-snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index)
+snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index)
{
int i;
- snd_seq_port_callback_t pinfo;
+ struct snd_seq_port_callback pinfo;
char tmpname[64];
- sprintf(tmpname, "%s WaveTable", emu->name);
- emu->client = get_client(card, index, tmpname);
+ emu->client = snd_seq_create_kernel_client(card, index,
+ "%s WaveTable", emu->name);
if (emu->client < 0) {
snd_printk("can't create client\n");
return -ENODEV;
@@ -94,7 +93,7 @@ snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index)
pinfo.event_input = snd_emux_event_input;
for (i = 0; i < emu->num_ports; i++) {
- snd_emux_port_t *p;
+ struct snd_emux_port *p;
sprintf(tmpname, "%s Port %d", emu->name, i);
p = snd_emux_create_port(emu, tmpname, MIDI_CHANNELS,
@@ -119,7 +118,7 @@ snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index)
* destroy the kernel client.
*/
void
-snd_emux_detach_seq(snd_emux_t *emu)
+snd_emux_detach_seq(struct snd_emux *emu)
{
if (emu->voices)
snd_emux_terminate_all(emu);
@@ -137,12 +136,12 @@ snd_emux_detach_seq(snd_emux_t *emu)
* create a sequencer port and channel_set
*/
-snd_emux_port_t *
-snd_emux_create_port(snd_emux_t *emu, char *name,
- int max_channels, int oss_port,
- snd_seq_port_callback_t *callback)
+struct snd_emux_port *
+snd_emux_create_port(struct snd_emux *emu, char *name,
+ int max_channels, int oss_port,
+ struct snd_seq_port_callback *callback)
{
- snd_emux_port_t *p;
+ struct snd_emux_port *p;
int i, type, cap;
/* Allocate structures for this channel */
@@ -150,7 +149,7 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
snd_printk("no memory\n");
return NULL;
}
- p->chset.channels = kcalloc(max_channels, sizeof(snd_midi_channel_t), GFP_KERNEL);
+ p->chset.channels = kcalloc(max_channels, sizeof(struct snd_midi_channel), GFP_KERNEL);
if (p->chset.channels == NULL) {
snd_printk("no memory\n");
kfree(p);
@@ -190,7 +189,7 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
static void
free_port(void *private_data)
{
- snd_emux_port_t *p;
+ struct snd_emux_port *p;
p = private_data;
if (p) {
@@ -209,7 +208,7 @@ free_port(void *private_data)
* initialize the port specific parameters
*/
static void
-snd_emux_init_port(snd_emux_port_t *p)
+snd_emux_init_port(struct snd_emux_port *p)
{
p->drum_flags = DEFAULT_DRUM_FLAGS;
p->volume_atten = 0;
@@ -222,7 +221,7 @@ snd_emux_init_port(snd_emux_port_t *p)
* reset port
*/
void
-snd_emux_reset_port(snd_emux_port_t *port)
+snd_emux_reset_port(struct snd_emux_port *port)
{
int i;
@@ -241,7 +240,7 @@ snd_emux_reset_port(snd_emux_port_t *port)
port->ctrls[EMUX_MD_REALTIME_PAN] = 1;
for (i = 0; i < port->chset.max_channels; i++) {
- snd_midi_channel_t *chan = port->chset.channels + i;
+ struct snd_midi_channel *chan = port->chset.channels + i;
chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0;
}
}
@@ -251,10 +250,10 @@ snd_emux_reset_port(snd_emux_port_t *port)
* input sequencer event
*/
int
-snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private_data,
+snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private_data,
int atomic, int hop)
{
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = private_data;
snd_assert(port != NULL && ev != NULL, return -EINVAL);
@@ -269,7 +268,7 @@ snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private_data,
* increment usage count
*/
int
-snd_emux_inc_count(snd_emux_t *emu)
+snd_emux_inc_count(struct snd_emux *emu)
{
emu->used++;
if (!try_module_get(emu->ops.owner))
@@ -288,7 +287,7 @@ snd_emux_inc_count(snd_emux_t *emu)
* decrease usage count
*/
void
-snd_emux_dec_count(snd_emux_t *emu)
+snd_emux_dec_count(struct snd_emux *emu)
{
module_put(emu->card->module);
emu->used--;
@@ -302,10 +301,10 @@ snd_emux_dec_count(snd_emux_t *emu)
* Routine that is called upon a first use of a particular port
*/
static int
-snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info)
+snd_emux_use(void *private_data, struct snd_seq_port_subscribe *info)
{
- snd_emux_port_t *p;
- snd_emux_t *emu;
+ struct snd_emux_port *p;
+ struct snd_emux *emu;
p = private_data;
snd_assert(p != NULL, return -EINVAL);
@@ -323,10 +322,10 @@ snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info)
* Routine that is called upon the last unuse() of a particular port.
*/
static int
-snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info)
+snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
- snd_emux_port_t *p;
- snd_emux_t *emu;
+ struct snd_emux_port *p;
+ struct snd_emux *emu;
p = private_data;
snd_assert(p != NULL, return -EINVAL);
@@ -342,39 +341,9 @@ snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info)
/*
- * Create a sequencer client
- */
-static int
-get_client(snd_card_t *card, int index, char *name)
-{
- snd_seq_client_callback_t callbacks;
- snd_seq_client_info_t cinfo;
- int client;
-
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.private_data = NULL;
- callbacks.allow_input = 1;
- callbacks.allow_output = 1;
-
- /* Find a free client, start from 1 as the MPU expects to use 0 */
- client = snd_seq_create_kernel_client(card, index, &callbacks);
- if (client < 0)
- return client;
-
- memset(&cinfo, 0, sizeof(cinfo));
- cinfo.client = client;
- cinfo.type = KERNEL_CLIENT;
- strcpy(cinfo.name, name);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
-
- return client;
-}
-
-
-/*
* attach virtual rawmidi devices
*/
-int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
+int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card)
{
int i;
@@ -382,13 +351,13 @@ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
if (emu->midi_ports <= 0)
return 0;
- emu->vmidi = kcalloc(emu->midi_ports, sizeof(snd_rawmidi_t*), GFP_KERNEL);
+ emu->vmidi = kcalloc(emu->midi_ports, sizeof(struct snd_rawmidi *), GFP_KERNEL);
if (emu->vmidi == NULL)
return -ENOMEM;
for (i = 0; i < emu->midi_ports; i++) {
- snd_rawmidi_t *rmidi;
- snd_virmidi_dev_t *rdev;
+ struct snd_rawmidi *rmidi;
+ struct snd_virmidi_dev *rdev;
if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0)
goto __error;
rdev = rmidi->private_data;
@@ -411,7 +380,7 @@ __error:
return -ENOMEM;
}
-int snd_emux_delete_virmidi(snd_emux_t *emu)
+int snd_emux_delete_virmidi(struct snd_emux *emu)
{
int i;
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index bd71b73be657..24705d15ebd8 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -36,30 +36,34 @@
#define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
#define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
-static int get_zone(snd_emux_t *emu, snd_emux_port_t *port, int *notep, int vel, snd_midi_channel_t *chan, snd_sf_zone_t **table);
-static int get_bank(snd_emux_port_t *port, snd_midi_channel_t *chan);
-static void terminate_note1(snd_emux_t *emu, int note, snd_midi_channel_t *chan, int free);
-static void exclusive_note_off(snd_emux_t *emu, snd_emux_port_t *port, int exclass);
-static void terminate_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int free);
-static void update_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int update);
-static void setup_voice(snd_emux_voice_t *vp);
-static int calc_pan(snd_emux_voice_t *vp);
-static int calc_volume(snd_emux_voice_t *vp);
-static int calc_pitch(snd_emux_voice_t *vp);
+static int get_zone(struct snd_emux *emu, struct snd_emux_port *port,
+ int *notep, int vel, struct snd_midi_channel *chan,
+ struct snd_sf_zone **table);
+static int get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan);
+static void terminate_note1(struct snd_emux *emu, int note,
+ struct snd_midi_channel *chan, int free);
+static void exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port,
+ int exclass);
+static void terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free);
+static void update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update);
+static void setup_voice(struct snd_emux_voice *vp);
+static int calc_pan(struct snd_emux_voice *vp);
+static int calc_volume(struct snd_emux_voice *vp);
+static int calc_pitch(struct snd_emux_voice *vp);
/*
* Start a note.
*/
void
-snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
+snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
{
- snd_emux_t *emu;
+ struct snd_emux *emu;
int i, key, nvoices;
- snd_emux_voice_t *vp;
- snd_sf_zone_t *table[SNDRV_EMUX_MAX_MULTI_VOICES];
+ struct snd_emux_voice *vp;
+ struct snd_sf_zone *table[SNDRV_EMUX_MAX_MULTI_VOICES];
unsigned long flags;
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL && chan != NULL, return);
@@ -76,7 +80,7 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
/* exclusive note off */
for (i = 0; i < nvoices; i++) {
- snd_sf_zone_t *zp = table[i];
+ struct snd_sf_zone *zp = table[i];
if (zp && zp->v.exclusiveClass)
exclusive_note_off(emu, port, zp->v.exclusiveClass);
}
@@ -138,7 +142,7 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
if (port->port_mode == SNDRV_EMUX_PORT_MODE_OSS_SYNTH) {
/* clear voice position for the next note on this channel */
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
if (fx) {
fx->flag[EMUX_FX_SAMPLE_START] = 0;
fx->flag[EMUX_FX_COARSE_SAMPLE_START] = 0;
@@ -151,13 +155,13 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
* Release a note in response to a midi note off.
*/
void
-snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
+snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan)
{
int ch;
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
unsigned long flags;
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL && chan != NULL, return);
@@ -199,11 +203,12 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
*/
void snd_emux_timer_callback(unsigned long data)
{
- snd_emux_t *emu = (snd_emux_t*) data;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu = (struct snd_emux *) data;
+ struct snd_emux_voice *vp;
+ unsigned long flags;
int ch, do_again = 0;
- spin_lock(&emu->voice_lock);
+ spin_lock_irqsave(&emu->voice_lock, flags);
for (ch = 0; ch < emu->max_voices; ch++) {
vp = &emu->voices[ch];
if (vp->state == SNDRV_EMUX_ST_PENDING) {
@@ -221,20 +226,20 @@ void snd_emux_timer_callback(unsigned long data)
emu->timer_active = 1;
} else
emu->timer_active = 0;
- spin_unlock(&emu->voice_lock);
+ spin_unlock_irqrestore(&emu->voice_lock, flags);
}
/*
* key pressure change
*/
void
-snd_emux_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
+snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan)
{
int ch;
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
unsigned long flags;
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL && chan != NULL, return);
@@ -260,10 +265,10 @@ snd_emux_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
* Modulate the voices which belong to the channel
*/
void
-snd_emux_update_channel(snd_emux_port_t *port, snd_midi_channel_t *chan, int update)
+snd_emux_update_channel(struct snd_emux_port *port, struct snd_midi_channel *chan, int update)
{
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
int i;
unsigned long flags;
@@ -287,10 +292,10 @@ snd_emux_update_channel(snd_emux_port_t *port, snd_midi_channel_t *chan, int upd
* Modulate all the voices which belong to the port.
*/
void
-snd_emux_update_port(snd_emux_port_t *port, int update)
+snd_emux_update_port(struct snd_emux_port *port, int update)
{
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
int i;
unsigned long flags;
@@ -316,9 +321,9 @@ snd_emux_update_port(snd_emux_port_t *port, int update)
* control events, not just the midi controllers
*/
void
-snd_emux_control(void *p, int type, snd_midi_channel_t *chan)
+snd_emux_control(void *p, int type, struct snd_midi_channel *chan)
{
- snd_emux_port_t *port;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL && chan != NULL, return);
@@ -364,10 +369,10 @@ snd_emux_control(void *p, int type, snd_midi_channel_t *chan)
* terminate note - if free flag is true, free the terminated voice
*/
static void
-terminate_note1(snd_emux_t *emu, int note, snd_midi_channel_t *chan, int free)
+terminate_note1(struct snd_emux *emu, int note, struct snd_midi_channel *chan, int free)
{
int i;
- snd_emux_voice_t *vp;
+ struct snd_emux_voice *vp;
unsigned long flags;
spin_lock_irqsave(&emu->voice_lock, flags);
@@ -385,10 +390,10 @@ terminate_note1(snd_emux_t *emu, int note, snd_midi_channel_t *chan, int free)
* terminate note - exported for midi emulation
*/
void
-snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan)
+snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan)
{
- snd_emux_t *emu;
- snd_emux_port_t *port;
+ struct snd_emux *emu;
+ struct snd_emux_port *port;
port = p;
snd_assert(port != NULL && chan != NULL, return);
@@ -405,10 +410,10 @@ snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan)
* Terminate all the notes
*/
void
-snd_emux_terminate_all(snd_emux_t *emu)
+snd_emux_terminate_all(struct snd_emux *emu)
{
int i;
- snd_emux_voice_t *vp;
+ struct snd_emux_voice *vp;
unsigned long flags;
spin_lock_irqsave(&emu->voice_lock, flags);
@@ -434,11 +439,11 @@ snd_emux_terminate_all(snd_emux_t *emu)
* Terminate all voices associated with the given port
*/
void
-snd_emux_sounds_off_all(snd_emux_port_t *port)
+snd_emux_sounds_off_all(struct snd_emux_port *port)
{
int i;
- snd_emux_t *emu;
- snd_emux_voice_t *vp;
+ struct snd_emux *emu;
+ struct snd_emux_voice *vp;
unsigned long flags;
snd_assert(port != NULL, return);
@@ -468,9 +473,9 @@ snd_emux_sounds_off_all(snd_emux_port_t *port)
* is mainly for drums.
*/
static void
-exclusive_note_off(snd_emux_t *emu, snd_emux_port_t *port, int exclass)
+exclusive_note_off(struct snd_emux *emu, struct snd_emux_port *port, int exclass)
{
- snd_emux_voice_t *vp;
+ struct snd_emux_voice *vp;
int i;
unsigned long flags;
@@ -490,7 +495,7 @@ exclusive_note_off(snd_emux_t *emu, snd_emux_port_t *port, int exclass)
* if free flag is true, call free_voice after termination
*/
static void
-terminate_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int free)
+terminate_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int free)
{
emu->ops.terminate(vp);
vp->time = emu->use_time++;
@@ -508,7 +513,7 @@ terminate_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int free)
* Modulate the voice
*/
static void
-update_voice(snd_emux_t *emu, snd_emux_voice_t *vp, int update)
+update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
{
if (!STATE_IS_PLAYING(vp->state))
return;
@@ -543,9 +548,9 @@ static unsigned short voltarget[16] = {
* will be needed later.
*/
static void
-setup_voice(snd_emux_voice_t *vp)
+setup_voice(struct snd_emux_voice *vp)
{
- soundfont_voice_parm_t *parm;
+ struct soundfont_voice_parm *parm;
int pitch;
/* copy the original register values */
@@ -636,9 +641,9 @@ static unsigned char pan_volumes[256] = {
};
static int
-calc_pan(snd_emux_voice_t *vp)
+calc_pan(struct snd_emux_voice *vp)
{
- snd_midi_channel_t *chan = vp->chan;
+ struct snd_midi_channel *chan = vp->chan;
int pan;
/* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
@@ -737,12 +742,12 @@ static unsigned char expressiontab[128] = {
* voice and channels parameters.
*/
static int
-calc_volume(snd_emux_voice_t *vp)
+calc_volume(struct snd_emux_voice *vp)
{
int vol;
int main_vol, expression_vol, master_vol;
- snd_midi_channel_t *chan = vp->chan;
- snd_emux_port_t *port = vp->port;
+ struct snd_midi_channel *chan = vp->chan;
+ struct snd_emux_port *port = vp->port;
expression_vol = chan->control[MIDI_CTL_MSB_EXPRESSION];
LIMITMAX(vp->velocity, 127);
@@ -775,7 +780,7 @@ calc_volume(snd_emux_voice_t *vp)
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
if (chan->private) {
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
vol += fx->val[EMUX_FX_ATTEN];
}
#endif
@@ -808,9 +813,9 @@ calc_volume(snd_emux_voice_t *vp)
*/
static int
-calc_pitch(snd_emux_voice_t *vp)
+calc_pitch(struct snd_emux_voice *vp)
{
- snd_midi_channel_t *chan = vp->chan;
+ struct snd_midi_channel *chan = vp->chan;
int offset;
/* calculate offset */
@@ -837,7 +842,7 @@ calc_pitch(snd_emux_voice_t *vp)
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
/* add initial pitch correction */
if (chan->private) {
- snd_emux_effect_table_t *fx = chan->private;
+ struct snd_emux_effect_table *fx = chan->private;
if (fx->flag[EMUX_FX_INIT_PITCH])
offset += fx->val[EMUX_FX_INIT_PITCH];
}
@@ -857,7 +862,7 @@ calc_pitch(snd_emux_voice_t *vp)
* Get the bank number assigned to the channel
*/
static int
-get_bank(snd_emux_port_t *port, snd_midi_channel_t *chan)
+get_bank(struct snd_emux_port *port, struct snd_midi_channel *chan)
{
int val;
@@ -886,8 +891,9 @@ get_bank(snd_emux_port_t *port, snd_midi_channel_t *chan)
* The resultant zones are stored on table.
*/
static int
-get_zone(snd_emux_t *emu, snd_emux_port_t *port,
- int *notep, int vel, snd_midi_channel_t *chan, snd_sf_zone_t **table)
+get_zone(struct snd_emux *emu, struct snd_emux_port *port,
+ int *notep, int vel, struct snd_midi_channel *chan,
+ struct snd_sf_zone **table)
{
int preset, bank, def_preset, def_bank;
@@ -910,9 +916,9 @@ get_zone(snd_emux_t *emu, snd_emux_port_t *port,
/*
*/
void
-snd_emux_init_voices(snd_emux_t *emu)
+snd_emux_init_voices(struct snd_emux *emu)
{
- snd_emux_voice_t *vp;
+ struct snd_emux_voice *vp;
int i;
unsigned long flags;
@@ -932,7 +938,7 @@ snd_emux_init_voices(snd_emux_t *emu)
/*
*/
-void snd_emux_lock_voice(snd_emux_t *emu, int voice)
+void snd_emux_lock_voice(struct snd_emux *emu, int voice)
{
unsigned long flags;
@@ -947,7 +953,7 @@ void snd_emux_lock_voice(snd_emux_t *emu, int voice)
/*
*/
-void snd_emux_unlock_voice(snd_emux_t *emu, int voice)
+void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
{
unsigned long flags;
diff --git a/sound/synth/emux/emux_voice.h b/sound/synth/emux/emux_voice.h
index 67eb55348cdf..0a56ca18b165 100644
--- a/sound/synth/emux/emux_voice.h
+++ b/sound/synth/emux/emux_voice.h
@@ -29,60 +29,69 @@
#include <sound/emux_synth.h>
/* Prototypes for emux_seq.c */
-int snd_emux_init_seq(snd_emux_t *emu, snd_card_t *card, int index);
-void snd_emux_detach_seq(snd_emux_t *emu);
-snd_emux_port_t *snd_emux_create_port(snd_emux_t *emu, char *name, int max_channels, int type, snd_seq_port_callback_t *callback);
-void snd_emux_reset_port(snd_emux_port_t *port);
-int snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private, int atomic, int hop);
-int snd_emux_inc_count(snd_emux_t *emu);
-void snd_emux_dec_count(snd_emux_t *emu);
-int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card);
-int snd_emux_delete_virmidi(snd_emux_t *emu);
+int snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index);
+void snd_emux_detach_seq(struct snd_emux *emu);
+struct snd_emux_port *snd_emux_create_port(struct snd_emux *emu, char *name,
+ int max_channels, int type,
+ struct snd_seq_port_callback *callback);
+void snd_emux_reset_port(struct snd_emux_port *port);
+int snd_emux_event_input(struct snd_seq_event *ev, int direct, void *private,
+ int atomic, int hop);
+int snd_emux_inc_count(struct snd_emux *emu);
+void snd_emux_dec_count(struct snd_emux *emu);
+int snd_emux_init_virmidi(struct snd_emux *emu, struct snd_card *card);
+int snd_emux_delete_virmidi(struct snd_emux *emu);
/* Prototypes for emux_synth.c */
-void snd_emux_init_voices(snd_emux_t *emu);
+void snd_emux_init_voices(struct snd_emux *emu);
void snd_emux_note_on(void *p, int note, int vel, struct snd_midi_channel *chan);
void snd_emux_note_off(void *p, int note, int vel, struct snd_midi_channel *chan);
void snd_emux_key_press(void *p, int note, int vel, struct snd_midi_channel *chan);
-void snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan);
+void snd_emux_terminate_note(void *p, int note, struct snd_midi_channel *chan);
void snd_emux_control(void *p, int type, struct snd_midi_channel *chan);
-void snd_emux_sounds_off_all(snd_emux_port_t *port);
-void snd_emux_update_channel(snd_emux_port_t *port, snd_midi_channel_t *chan, int update);
-void snd_emux_update_port(snd_emux_port_t *port, int update);
+void snd_emux_sounds_off_all(struct snd_emux_port *port);
+void snd_emux_update_channel(struct snd_emux_port *port,
+ struct snd_midi_channel *chan, int update);
+void snd_emux_update_port(struct snd_emux_port *port, int update);
void snd_emux_timer_callback(unsigned long data);
/* emux_effect.c */
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
-void snd_emux_create_effect(snd_emux_port_t *p);
-void snd_emux_delete_effect(snd_emux_port_t *p);
-void snd_emux_clear_effect(snd_emux_port_t *p);
-void snd_emux_setup_effect(snd_emux_voice_t *vp);
-void snd_emux_send_effect_oss(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val);
-void snd_emux_send_effect(snd_emux_port_t *port, snd_midi_channel_t *chan, int type, int val, int mode);
+void snd_emux_create_effect(struct snd_emux_port *p);
+void snd_emux_delete_effect(struct snd_emux_port *p);
+void snd_emux_clear_effect(struct snd_emux_port *p);
+void snd_emux_setup_effect(struct snd_emux_voice *vp);
+void snd_emux_send_effect_oss(struct snd_emux_port *port,
+ struct snd_midi_channel *chan, int type, int val);
+void snd_emux_send_effect(struct snd_emux_port *port,
+ struct snd_midi_channel *chan, int type, int val, int mode);
#endif
/* emux_nrpn.c */
-void snd_emux_sysex(void *private_data, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
-int snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param);
-void snd_emux_nrpn(void *private_data, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
+void snd_emux_sysex(void *private_data, unsigned char *buf, int len,
+ int parsed, struct snd_midi_channel_set *chset);
+int snd_emux_xg_control(struct snd_emux_port *port,
+ struct snd_midi_channel *chan, int param);
+void snd_emux_nrpn(void *private_data, struct snd_midi_channel *chan,
+ struct snd_midi_channel_set *chset);
/* emux_oss.c */
-void snd_emux_init_seq_oss(snd_emux_t *emu);
-void snd_emux_detach_seq_oss(snd_emux_t *emu);
+void snd_emux_init_seq_oss(struct snd_emux *emu);
+void snd_emux_detach_seq_oss(struct snd_emux *emu);
/* emux_proc.c */
#ifdef CONFIG_PROC_FS
-void snd_emux_proc_init(snd_emux_t *emu, snd_card_t *card, int device);
-void snd_emux_proc_free(snd_emux_t *emu);
+void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device);
+void snd_emux_proc_free(struct snd_emux *emu);
#endif
#define STATE_IS_PLAYING(s) ((s) & SNDRV_EMUX_ST_ON)
/* emux_hwdep.c */
-int snd_emux_init_hwdep(snd_emux_t *emu);
-void snd_emux_delete_hwdep(snd_emux_t *emu);
+int snd_emux_init_hwdep(struct snd_emux *emu);
+void snd_emux_delete_hwdep(struct snd_emux *emu);
#endif
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index d0925ea50838..4c5754d4a2e8 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -34,38 +34,49 @@
/* Prototypes for static functions */
-static int open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client);
-static snd_soundfont_t *newsf(snd_sf_list_t *sflist, int type, char *name);
-static int is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name);
-static int close_patch(snd_sf_list_t *sflist);
-static int probe_data(snd_sf_list_t *sflist, int sample_id);
-static void set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp);
-static snd_sf_zone_t *sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
-static void set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
-static snd_sf_sample_t *sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf);
-static void sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp);
-static int load_map(snd_sf_list_t *sflist, const void __user *data, int count);
-static int load_info(snd_sf_list_t *sflist, const void __user *data, long count);
-static int remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr);
-static void init_voice_info(soundfont_voice_info_t *avp);
-static void init_voice_parm(soundfont_voice_parm_t *pp);
-static snd_sf_sample_t *set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp);
-static snd_sf_sample_t *find_sample(snd_soundfont_t *sf, int sample_id);
-static int load_data(snd_sf_list_t *sflist, const void __user *data, long count);
-static void rebuild_presets(snd_sf_list_t *sflist);
-static void add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur);
-static void delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp);
-static snd_sf_zone_t *search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key);
-static int search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level);
+static int open_patch(struct snd_sf_list *sflist, const char __user *data,
+ int count, int client);
+static struct snd_soundfont *newsf(struct snd_sf_list *sflist, int type, char *name);
+static int is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name);
+static int close_patch(struct snd_sf_list *sflist);
+static int probe_data(struct snd_sf_list *sflist, int sample_id);
+static void set_zone_counter(struct snd_sf_list *sflist,
+ struct snd_soundfont *sf, struct snd_sf_zone *zp);
+static struct snd_sf_zone *sf_zone_new(struct snd_sf_list *sflist,
+ struct snd_soundfont *sf);
+static void set_sample_counter(struct snd_sf_list *sflist,
+ struct snd_soundfont *sf, struct snd_sf_sample *sp);
+static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist,
+ struct snd_soundfont *sf);
+static void sf_sample_delete(struct snd_sf_list *sflist,
+ struct snd_soundfont *sf, struct snd_sf_sample *sp);
+static int load_map(struct snd_sf_list *sflist, const void __user *data, int count);
+static int load_info(struct snd_sf_list *sflist, const void __user *data, long count);
+static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
+ int bank, int instr);
+static void init_voice_info(struct soundfont_voice_info *avp);
+static void init_voice_parm(struct soundfont_voice_parm *pp);
+static struct snd_sf_sample *set_sample(struct snd_soundfont *sf,
+ struct soundfont_voice_info *avp);
+static struct snd_sf_sample *find_sample(struct snd_soundfont *sf, int sample_id);
+static int load_data(struct snd_sf_list *sflist, const void __user *data, long count);
+static void rebuild_presets(struct snd_sf_list *sflist);
+static void add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur);
+static void delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp);
+static struct snd_sf_zone *search_first_zone(struct snd_sf_list *sflist,
+ int bank, int preset, int key);
+static int search_zones(struct snd_sf_list *sflist, int *notep, int vel,
+ int preset, int bank, struct snd_sf_zone **table,
+ int max_layers, int level);
static int get_index(int bank, int instr, int key);
-static void snd_sf_init(snd_sf_list_t *sflist);
-static void snd_sf_clear(snd_sf_list_t *sflist);
+static void snd_sf_init(struct snd_sf_list *sflist);
+static void snd_sf_clear(struct snd_sf_list *sflist);
/*
* lock access to sflist
*/
static void
-lock_preset(snd_sf_list_t *sflist)
+lock_preset(struct snd_sf_list *sflist)
{
unsigned long flags;
down(&sflist->presets_mutex);
@@ -79,7 +90,7 @@ lock_preset(snd_sf_list_t *sflist)
* remove lock
*/
static void
-unlock_preset(snd_sf_list_t *sflist)
+unlock_preset(struct snd_sf_list *sflist)
{
unsigned long flags;
spin_lock_irqsave(&sflist->lock, flags);
@@ -93,7 +104,7 @@ unlock_preset(snd_sf_list_t *sflist)
* close the patch if the patch was opened by this client.
*/
int
-snd_soundfont_close_check(snd_sf_list_t *sflist, int client)
+snd_soundfont_close_check(struct snd_sf_list *sflist, int client)
{
unsigned long flags;
spin_lock_irqsave(&sflist->lock, flags);
@@ -115,9 +126,10 @@ snd_soundfont_close_check(snd_sf_list_t *sflist, int client)
* it wants to do with it.
*/
int
-snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, int client)
+snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data,
+ long count, int client)
{
- soundfont_patch_info_t patch;
+ struct soundfont_patch_info patch;
unsigned long flags;
int rc;
@@ -215,10 +227,11 @@ is_special_type(int type)
/* open patch; create sf list */
static int
-open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client)
+open_patch(struct snd_sf_list *sflist, const char __user *data,
+ int count, int client)
{
- soundfont_open_parm_t parm;
- snd_soundfont_t *sf;
+ struct soundfont_open_parm parm;
+ struct snd_soundfont *sf;
unsigned long flags;
spin_lock_irqsave(&sflist->lock, flags);
@@ -251,10 +264,10 @@ open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client
/*
* Allocate a new soundfont structure.
*/
-static snd_soundfont_t *
-newsf(snd_sf_list_t *sflist, int type, char *name)
+static struct snd_soundfont *
+newsf(struct snd_sf_list *sflist, int type, char *name)
{
- snd_soundfont_t *sf;
+ struct snd_soundfont *sf;
/* check the shared fonts */
if (type & SNDRV_SFNT_PAT_SHARED) {
@@ -287,7 +300,7 @@ newsf(snd_sf_list_t *sflist, int type, char *name)
/* check if the given name matches to the existing list */
static int
-is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
+is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name)
{
return ((sf->type & SNDRV_SFNT_PAT_SHARED) &&
(sf->type & 0x0f) == (type & 0x0f) &&
@@ -299,7 +312,7 @@ is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
* Close the current patch.
*/
static int
-close_patch(snd_sf_list_t *sflist)
+close_patch(struct snd_sf_list *sflist)
{
unsigned long flags;
@@ -316,7 +329,7 @@ close_patch(snd_sf_list_t *sflist)
/* probe sample in the current list -- nothing to be loaded */
static int
-probe_data(snd_sf_list_t *sflist, int sample_id)
+probe_data(struct snd_sf_list *sflist, int sample_id)
{
/* patch must be opened */
if (sflist->currsf) {
@@ -331,7 +344,8 @@ probe_data(snd_sf_list_t *sflist, int sample_id)
* increment zone counter
*/
static void
-set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp)
+set_zone_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
+ struct snd_sf_zone *zp)
{
zp->counter = sflist->zone_counter++;
if (sf->type & SNDRV_SFNT_PAT_LOCKED)
@@ -341,10 +355,10 @@ set_zone_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_zone_t *zp)
/*
* allocate a new zone record
*/
-static snd_sf_zone_t *
-sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
+static struct snd_sf_zone *
+sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
{
- snd_sf_zone_t *zp;
+ struct snd_sf_zone *zp;
if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
return NULL;
@@ -362,7 +376,8 @@ sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
* increment sample couter
*/
static void
-set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
+set_sample_counter(struct snd_sf_list *sflist, struct snd_soundfont *sf,
+ struct snd_sf_sample *sp)
{
sp->counter = sflist->sample_counter++;
if (sf->type & SNDRV_SFNT_PAT_LOCKED)
@@ -372,10 +387,10 @@ set_sample_counter(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *
/*
* allocate a new sample list record
*/
-static snd_sf_sample_t *
-sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
+static struct snd_sf_sample *
+sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf)
{
- snd_sf_sample_t *sp;
+ struct snd_sf_sample *sp;
if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
return NULL;
@@ -392,7 +407,8 @@ sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
* only the last allocated sample can be deleted.
*/
static void
-sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp)
+sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf,
+ struct snd_sf_sample *sp)
{
/* only last sample is accepted */
if (sp == sf->samples) {
@@ -404,11 +420,11 @@ sf_sample_delete(snd_sf_list_t *sflist, snd_soundfont_t *sf, snd_sf_sample_t *sp
/* load voice map */
static int
-load_map(snd_sf_list_t *sflist, const void __user *data, int count)
+load_map(struct snd_sf_list *sflist, const void __user *data, int count)
{
- snd_sf_zone_t *zp, *prevp;
- snd_soundfont_t *sf;
- soundfont_voice_map_t map;
+ struct snd_sf_zone *zp, *prevp;
+ struct snd_soundfont *sf;
+ struct soundfont_voice_map map;
/* get the link info */
if (count < (int)sizeof(map))
@@ -469,9 +485,10 @@ load_map(snd_sf_list_t *sflist, const void __user *data, int count)
/* remove the present instrument layers */
static int
-remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr)
+remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf,
+ int bank, int instr)
{
- snd_sf_zone_t *prev, *next, *p;
+ struct snd_sf_zone *prev, *next, *p;
int removed = 0;
prev = NULL;
@@ -500,11 +517,11 @@ remove_info(snd_sf_list_t *sflist, snd_soundfont_t *sf, int bank, int instr)
* open soundfont.
*/
static int
-load_info(snd_sf_list_t *sflist, const void __user *data, long count)
+load_info(struct snd_sf_list *sflist, const void __user *data, long count)
{
- snd_soundfont_t *sf;
- snd_sf_zone_t *zone;
- soundfont_voice_rec_hdr_t hdr;
+ struct snd_soundfont *sf;
+ struct snd_sf_zone *zone;
+ struct soundfont_voice_rec_hdr hdr;
int i;
/* patch must be opened */
@@ -529,7 +546,7 @@ load_info(snd_sf_list_t *sflist, const void __user *data, long count)
return -EINVAL;
}
- if (count < (long)sizeof(soundfont_voice_info_t)*hdr.nvoices) {
+ if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) {
printk("Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n",
count, hdr.nvoices);
return -EINVAL;
@@ -553,7 +570,7 @@ load_info(snd_sf_list_t *sflist, const void __user *data, long count)
}
for (i = 0; i < hdr.nvoices; i++) {
- snd_sf_zone_t tmpzone;
+ struct snd_sf_zone tmpzone;
/* copy awe_voice_info parameters */
if (copy_from_user(&tmpzone.v, data, sizeof(tmpzone.v))) {
@@ -590,7 +607,7 @@ load_info(snd_sf_list_t *sflist, const void __user *data, long count)
/* initialize voice_info record */
static void
-init_voice_info(soundfont_voice_info_t *avp)
+init_voice_info(struct soundfont_voice_info *avp)
{
memset(avp, 0, sizeof(*avp));
@@ -614,7 +631,7 @@ init_voice_info(soundfont_voice_info_t *avp)
* Chorus and Reverb effects are zero.
*/
static void
-init_voice_parm(soundfont_voice_parm_t *pp)
+init_voice_parm(struct soundfont_voice_parm *pp)
{
memset(pp, 0, sizeof(*pp));
@@ -635,10 +652,10 @@ init_voice_parm(soundfont_voice_parm_t *pp)
}
/* search the specified sample */
-static snd_sf_sample_t *
-set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp)
+static struct snd_sf_sample *
+set_sample(struct snd_soundfont *sf, struct soundfont_voice_info *avp)
{
- snd_sf_sample_t *sample;
+ struct snd_sf_sample *sample;
sample = find_sample(sf, avp->sample);
if (sample == NULL)
@@ -661,10 +678,10 @@ set_sample(snd_soundfont_t *sf, soundfont_voice_info_t *avp)
}
/* find the sample pointer with the given id in the soundfont */
-static snd_sf_sample_t *
-find_sample(snd_soundfont_t *sf, int sample_id)
+static struct snd_sf_sample *
+find_sample(struct snd_soundfont *sf, int sample_id)
{
- snd_sf_sample_t *p;
+ struct snd_sf_sample *p;
if (sf == NULL)
return NULL;
@@ -684,11 +701,11 @@ find_sample(snd_soundfont_t *sf, int sample_id)
* routine.
*/
static int
-load_data(snd_sf_list_t *sflist, const void __user *data, long count)
+load_data(struct snd_sf_list *sflist, const void __user *data, long count)
{
- snd_soundfont_t *sf;
- soundfont_sample_info_t sample_info;
- snd_sf_sample_t *sp;
+ struct snd_soundfont *sf;
+ struct soundfont_sample_info sample_info;
+ struct snd_sf_sample *sp;
long off;
/* patch must be opened */
@@ -922,12 +939,13 @@ int snd_sf_vol_table[128] = {
/* load GUS patch */
static int
-load_guspatch(snd_sf_list_t *sflist, const char __user *data, long count, int client)
+load_guspatch(struct snd_sf_list *sflist, const char __user *data,
+ long count, int client)
{
struct patch_info patch;
- snd_soundfont_t *sf;
- snd_sf_zone_t *zone;
- snd_sf_sample_t *smp;
+ struct snd_soundfont *sf;
+ struct snd_sf_zone *zone;
+ struct snd_sf_sample *smp;
int note, sample_id;
int rc;
@@ -992,7 +1010,8 @@ load_guspatch(snd_sf_list_t *sflist, const char __user *data, long count, int cl
*/
if (sflist->callback.sample_new) {
rc = sflist->callback.sample_new
- (sflist->callback.private_data, smp, sflist->memhdr, data, count);
+ (sflist->callback.private_data, smp, sflist->memhdr,
+ data, count);
if (rc < 0) {
sf_sample_delete(sflist, sf, smp);
return rc;
@@ -1095,7 +1114,7 @@ load_guspatch(snd_sf_list_t *sflist, const char __user *data, long count, int cl
/* load GUS patch */
int
-snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
+snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
long count, int client)
{
int rc;
@@ -1114,10 +1133,10 @@ snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
* bank/key combination).
*/
static void
-rebuild_presets(snd_sf_list_t *sflist)
+rebuild_presets(struct snd_sf_list *sflist)
{
- snd_soundfont_t *sf;
- snd_sf_zone_t *cur;
+ struct snd_soundfont *sf;
+ struct snd_sf_zone *cur;
/* clear preset table */
memset(sflist->presets, 0, sizeof(sflist->presets));
@@ -1142,15 +1161,15 @@ rebuild_presets(snd_sf_list_t *sflist)
* add the given zone to preset table
*/
static void
-add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur)
+add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur)
{
- snd_sf_zone_t *zone;
+ struct snd_sf_zone *zone;
int index;
zone = search_first_zone(sflist, cur->bank, cur->instr, cur->v.low);
if (zone && zone->v.sf_id != cur->v.sf_id) {
/* different instrument was already defined */
- snd_sf_zone_t *p;
+ struct snd_sf_zone *p;
/* compare the allocated time */
for (p = zone; p; p = p->next_zone) {
if (p->counter > cur->counter)
@@ -1174,10 +1193,10 @@ add_preset(snd_sf_list_t *sflist, snd_sf_zone_t *cur)
* delete the given zones from preset_table
*/
static void
-delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp)
+delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp)
{
int index;
- snd_sf_zone_t *p;
+ struct snd_sf_zone *p;
if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0)
return;
@@ -1200,10 +1219,10 @@ delete_preset(snd_sf_list_t *sflist, snd_sf_zone_t *zp)
* This function returns the number of found zones. 0 if not found.
*/
int
-snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
+snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel,
int preset, int bank,
int def_preset, int def_bank,
- snd_sf_zone_t **table, int max_layers)
+ struct snd_sf_zone **table, int max_layers)
{
int nvoices;
unsigned long flags;
@@ -1217,10 +1236,13 @@ snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
spin_unlock_irqrestore(&sflist->lock, flags);
return 0;
}
- nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
+ nvoices = search_zones(sflist, notep, vel, preset, bank,
+ table, max_layers, 0);
if (! nvoices) {
if (preset != def_preset || bank != def_bank)
- nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
+ nvoices = search_zones(sflist, notep, vel,
+ def_preset, def_bank,
+ table, max_layers, 0);
}
spin_unlock_irqrestore(&sflist->lock, flags);
return nvoices;
@@ -1230,11 +1252,11 @@ snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
/*
* search the first matching zone
*/
-static snd_sf_zone_t *
-search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key)
+static struct snd_sf_zone *
+search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key)
{
int index;
- snd_sf_zone_t *zp;
+ struct snd_sf_zone *zp;
if ((index = get_index(bank, preset, key)) < 0)
return NULL;
@@ -1250,9 +1272,11 @@ search_first_zone(snd_sf_list_t *sflist, int bank, int preset, int key)
* search matching zones from sflist. can be called recursively.
*/
static int
-search_zones(snd_sf_list_t *sflist, int *notep, int vel, int preset, int bank, snd_sf_zone_t **table, int max_layers, int level)
+search_zones(struct snd_sf_list *sflist, int *notep, int vel,
+ int preset, int bank, struct snd_sf_zone **table,
+ int max_layers, int level)
{
- snd_sf_zone_t *zp;
+ struct snd_sf_zone *zp;
int nvoices;
zp = search_first_zone(sflist, bank, preset, *notep);
@@ -1310,7 +1334,7 @@ get_index(int bank, int instr, int key)
* Initialise the sflist structure.
*/
static void
-snd_sf_init(snd_sf_list_t *sflist)
+snd_sf_init(struct snd_sf_list *sflist)
{
memset(sflist->presets, 0, sizeof(sflist->presets));
@@ -1329,11 +1353,11 @@ snd_sf_init(snd_sf_list_t *sflist)
* Release all list records
*/
static void
-snd_sf_clear(snd_sf_list_t *sflist)
+snd_sf_clear(struct snd_sf_list *sflist)
{
- snd_soundfont_t *sf, *nextsf;
- snd_sf_zone_t *zp, *nextzp;
- snd_sf_sample_t *sp, *nextsp;
+ struct snd_soundfont *sf, *nextsf;
+ struct snd_sf_zone *zp, *nextzp;
+ struct snd_sf_sample *sp, *nextsp;
for (sf = sflist->fonts; sf; sf = nextsf) {
nextsf = sf->next;
@@ -1344,7 +1368,8 @@ snd_sf_clear(snd_sf_list_t *sflist)
for (sp = sf->samples; sp; sp = nextsp) {
nextsp = sp->next;
if (sflist->callback.sample_free)
- sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
+ sflist->callback.sample_free(sflist->callback.private_data,
+ sp, sflist->memhdr);
kfree(sp);
}
kfree(sf);
@@ -1357,10 +1382,10 @@ snd_sf_clear(snd_sf_list_t *sflist)
/*
* Create a new sflist structure
*/
-snd_sf_list_t *
-snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
+struct snd_sf_list *
+snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr)
{
- snd_sf_list_t *sflist;
+ struct snd_sf_list *sflist;
if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL)
return NULL;
@@ -1381,7 +1406,7 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
* Free everything allocated off the sflist structure.
*/
void
-snd_sf_free(snd_sf_list_t *sflist)
+snd_sf_free(struct snd_sf_list *sflist)
{
if (sflist == NULL)
return;
@@ -1400,7 +1425,7 @@ snd_sf_free(snd_sf_list_t *sflist)
* The soundcard should be silet before calling this function.
*/
int
-snd_soundfont_remove_samples(snd_sf_list_t *sflist)
+snd_soundfont_remove_samples(struct snd_sf_list *sflist)
{
lock_preset(sflist);
if (sflist->callback.sample_reset)
@@ -1416,11 +1441,11 @@ snd_soundfont_remove_samples(snd_sf_list_t *sflist)
* The soundcard should be silent before calling this function.
*/
int
-snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
+snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
{
- snd_soundfont_t *sf;
- snd_sf_zone_t *zp, *nextzp;
- snd_sf_sample_t *sp, *nextsp;
+ struct snd_soundfont *sf;
+ struct snd_sf_zone *zp, *nextzp;
+ struct snd_sf_sample *sp, *nextsp;
lock_preset(sflist);
@@ -1446,7 +1471,8 @@ snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
sf->samples = nextsp;
sflist->mem_used -= sp->v.truesize;
if (sflist->callback.sample_free)
- sflist->callback.sample_free(sflist->callback.private_data, sp, sflist->memhdr);
+ sflist->callback.sample_free(sflist->callback.private_data,
+ sp, sflist->memhdr);
kfree(sp);
}
}
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 5f75bf31bc36..217e8e552a42 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -28,15 +28,15 @@ MODULE_AUTHOR("Takashi Iwai");
MODULE_DESCRIPTION("Generic memory management routines for soundcard memory allocation");
MODULE_LICENSE("GPL");
-#define get_memblk(p) list_entry(p, snd_util_memblk_t, list)
+#define get_memblk(p) list_entry(p, struct snd_util_memblk, list)
/*
* create a new memory manager
*/
-snd_util_memhdr_t *
+struct snd_util_memhdr *
snd_util_memhdr_new(int memsize)
{
- snd_util_memhdr_t *hdr;
+ struct snd_util_memhdr *hdr;
hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
if (hdr == NULL)
@@ -51,7 +51,7 @@ snd_util_memhdr_new(int memsize)
/*
* free a memory manager
*/
-void snd_util_memhdr_free(snd_util_memhdr_t *hdr)
+void snd_util_memhdr_free(struct snd_util_memhdr *hdr)
{
struct list_head *p;
@@ -67,11 +67,11 @@ void snd_util_memhdr_free(snd_util_memhdr_t *hdr)
/*
* allocate a memory block (without mutex)
*/
-snd_util_memblk_t *
-__snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
+struct snd_util_memblk *
+__snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
{
- snd_util_memblk_t *blk;
- snd_util_unit_t units, prev_offset;
+ struct snd_util_memblk *blk;
+ unsigned int units, prev_offset;
struct list_head *p;
snd_assert(hdr != NULL, return NULL);
@@ -104,20 +104,21 @@ __found:
* create a new memory block with the given size
* the block is linked next to prev
*/
-snd_util_memblk_t *
-__snd_util_memblk_new(snd_util_memhdr_t *hdr, snd_util_unit_t units,
+struct snd_util_memblk *
+__snd_util_memblk_new(struct snd_util_memhdr *hdr, unsigned int units,
struct list_head *prev)
{
- snd_util_memblk_t *blk;
+ struct snd_util_memblk *blk;
- blk = kmalloc(sizeof(snd_util_memblk_t) + hdr->block_extra_size, GFP_KERNEL);
+ blk = kmalloc(sizeof(struct snd_util_memblk) + hdr->block_extra_size,
+ GFP_KERNEL);
if (blk == NULL)
return NULL;
if (! prev || prev == &hdr->block)
blk->offset = 0;
else {
- snd_util_memblk_t *p = get_memblk(prev);
+ struct snd_util_memblk *p = get_memblk(prev);
blk->offset = p->offset + p->size;
}
blk->size = units;
@@ -131,10 +132,10 @@ __snd_util_memblk_new(snd_util_memhdr_t *hdr, snd_util_unit_t units,
/*
* allocate a memory block (with mutex)
*/
-snd_util_memblk_t *
-snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
+struct snd_util_memblk *
+snd_util_mem_alloc(struct snd_util_memhdr *hdr, int size)
{
- snd_util_memblk_t *blk;
+ struct snd_util_memblk *blk;
down(&hdr->block_mutex);
blk = __snd_util_mem_alloc(hdr, size);
up(&hdr->block_mutex);
@@ -147,7 +148,7 @@ snd_util_mem_alloc(snd_util_memhdr_t *hdr, int size)
* (without mutex)
*/
void
-__snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
+__snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
{
list_del(&blk->list);
hdr->nblocks--;
@@ -158,7 +159,7 @@ __snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
/*
* free a memory block (with mutex)
*/
-int snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
+int snd_util_mem_free(struct snd_util_memhdr *hdr, struct snd_util_memblk *blk)
{
snd_assert(hdr && blk, return -EINVAL);
@@ -171,7 +172,7 @@ int snd_util_mem_free(snd_util_memhdr_t *hdr, snd_util_memblk_t *blk)
/*
* return available memory size
*/
-int snd_util_mem_avail(snd_util_memhdr_t *hdr)
+int snd_util_mem_avail(struct snd_util_memhdr *hdr)
{
unsigned int size;
down(&hdr->block_mutex);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 99dae024b640..a1bd8040dea4 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -102,10 +102,6 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
#define SYNC_URBS 4 /* always four urbs for sync */
#define MIN_PACKS_URB 1 /* minimum 1 packet per urb */
-typedef struct snd_usb_substream snd_usb_substream_t;
-typedef struct snd_usb_stream snd_usb_stream_t;
-typedef struct snd_urb_ctx snd_urb_ctx_t;
-
struct audioformat {
struct list_head list;
snd_pcm_format_t format; /* format type */
@@ -125,25 +121,27 @@ struct audioformat {
unsigned int *rate_table; /* rate table */
};
+struct snd_usb_substream;
+
struct snd_urb_ctx {
struct urb *urb;
unsigned int buffer_size; /* size of data buffer, if data URB */
- snd_usb_substream_t *subs;
+ struct snd_usb_substream *subs;
int index; /* index for urb array */
int packets; /* number of packets per urb */
};
struct snd_urb_ops {
- int (*prepare)(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *u);
- int (*retire)(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *u);
- int (*prepare_sync)(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *u);
- int (*retire_sync)(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime, struct urb *u);
+ int (*prepare)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
+ int (*retire)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
+ int (*prepare_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
+ int (*retire_sync)(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime, struct urb *u);
};
struct snd_usb_substream {
- snd_usb_stream_t *stream;
+ struct snd_usb_stream *stream;
struct usb_device *dev;
- snd_pcm_substream_t *pcm_substream;
+ struct snd_pcm_substream *pcm_substream;
int direction; /* playback or capture */
int interface; /* current interface */
int endpoint; /* assigned endpoint */
@@ -175,8 +173,8 @@ struct snd_usb_substream {
unsigned long unlink_mask; /* bitmask of unlinked urbs */
unsigned int nurbs; /* # urbs */
- snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
- snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */
+ struct snd_urb_ctx dataurb[MAX_URBS]; /* data urb table */
+ struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */
char *syncbuf; /* sync buffer for all sync URBs */
dma_addr_t sync_dma; /* DMA address of syncbuf */
@@ -190,11 +188,11 @@ struct snd_usb_substream {
struct snd_usb_stream {
- snd_usb_audio_t *chip;
- snd_pcm_t *pcm;
+ struct snd_usb_audio *chip;
+ struct snd_pcm *pcm;
int pcm_index;
unsigned int fmt_type; /* USB audio format type (1-3) */
- snd_usb_substream_t substream[2];
+ struct snd_usb_substream substream[2];
struct list_head list;
};
@@ -205,7 +203,7 @@ struct snd_usb_stream {
*/
static DECLARE_MUTEX(register_mutex);
-static snd_usb_audio_t *usb_chip[SNDRV_CARDS];
+static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
/*
@@ -245,12 +243,12 @@ static inline unsigned get_high_speed_hz(unsigned int usb_rate)
* fill the length and offset of each urb descriptor.
* the fixed 10.14 frequency is passed through the pipe.
*/
-static int prepare_capture_sync_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->iso_frame_desc[0].length = 3;
@@ -267,12 +265,12 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs,
* fill the length and offset of each urb descriptor.
* the fixed 12.13 frequency is passed as 16.16 through the pipe.
*/
-static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned char *cp = urb->transfer_buffer;
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->iso_frame_desc[0].length = 4;
@@ -288,8 +286,8 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs,
* process after capture sync complete
* - nothing to do
*/
-static int retire_capture_sync_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int retire_capture_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
return 0;
@@ -305,12 +303,12 @@ static int retire_capture_sync_urb(snd_usb_substream_t *subs,
* write onto the pcm buffer directly... the data is thus copied
* later at complete callback to the global buffer.
*/
-static int prepare_capture_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_capture_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
int i, offs;
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
offs = 0;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
@@ -340,8 +338,8 @@ static int prepare_capture_urb(snd_usb_substream_t *subs,
* copy the data from each desctiptor to the pcm buffer, and
* update the current position.
*/
-static int retire_capture_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int retire_capture_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned long flags;
@@ -395,11 +393,11 @@ static int retire_capture_urb(snd_usb_substream_t *subs,
* set up the offset and length to receive the current frequency.
*/
-static int prepare_playback_sync_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->iso_frame_desc[0].length = 3;
@@ -413,11 +411,11 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs,
* set up the offset and length to receive the current frequency.
*/
-static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
urb->iso_frame_desc[0].length = 4;
@@ -431,8 +429,8 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs,
* retrieve the current 10.14 frequency from pipe, and set it.
* the value is referred in prepare_playback_urb().
*/
-static int retire_playback_sync_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int retire_playback_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned int f;
@@ -457,8 +455,8 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs,
* retrieve the current 12.13 frequency from pipe, and set it.
* the value is referred in prepare_playback_urb().
*/
-static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int retire_playback_sync_urb_hs(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned int f;
@@ -482,12 +480,12 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
*
* We don't care about (or have) any data, so we just send a transfer delimiter.
*/
-static int prepare_startup_playback_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int prepare_startup_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
unsigned int i;
- snd_urb_ctx_t *ctx = urb->context;
+ struct snd_urb_ctx *ctx = urb->context;
urb->dev = ctx->subs->dev;
urb->number_of_packets = subs->packs_per_ms;
@@ -507,15 +505,15 @@ static int prepare_startup_playback_urb(snd_usb_substream_t *subs,
* 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,
+static int prepare_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
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;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
stride = runtime->frame_bits >> 3;
@@ -597,8 +595,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
* process after playback data complete
* - nothing to do
*/
-static int retire_playback_urb(snd_usb_substream_t *subs,
- snd_pcm_runtime_t *runtime,
+static int retire_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
struct urb *urb)
{
return 0;
@@ -642,9 +640,9 @@ static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
*/
static void snd_complete_urb(struct urb *urb, struct pt_regs *regs)
{
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- snd_usb_substream_t *subs = ctx->subs;
- snd_pcm_substream_t *substream = ctx->subs->pcm_substream;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+ struct snd_usb_substream *subs = ctx->subs;
+ struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
int err = 0;
if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
@@ -665,9 +663,9 @@ static void snd_complete_urb(struct urb *urb, struct pt_regs *regs)
*/
static void snd_complete_sync_urb(struct urb *urb, struct pt_regs *regs)
{
- snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- snd_usb_substream_t *subs = ctx->subs;
- snd_pcm_substream_t *substream = ctx->subs->pcm_substream;
+ struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context;
+ struct snd_usb_substream *subs = ctx->subs;
+ struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
int err = 0;
if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
@@ -684,7 +682,7 @@ 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,
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
unsigned long offset)
{
void *pageptr = subs->runtime->dma_area + offset;
@@ -692,9 +690,9 @@ static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs,
}
/* allocate virtual buffer; may be called more than once */
-static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
if (runtime->dma_bytes >= size)
return 0; /* already large enough */
@@ -708,9 +706,9 @@ static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
}
/* free virtual buffer; may be called more than once */
-static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
+static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
{
- snd_pcm_runtime_t *runtime = subs->runtime;
+ struct snd_pcm_runtime *runtime = subs->runtime;
if (runtime->dma_area) {
vfree(runtime->dma_area);
runtime->dma_area = NULL;
@@ -722,7 +720,7 @@ static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
/*
* unlink active urbs.
*/
-static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
+static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
{
unsigned int i;
int async;
@@ -768,7 +766,7 @@ static int deactivate_urbs(snd_usb_substream_t *subs, int force, int can_sleep)
/*
* set up and start data/sync urbs
*/
-static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
+static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
{
unsigned int i;
int err;
@@ -824,7 +822,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
/*
* wait until all urbs are processed.
*/
-static int wait_clear_urbs(snd_usb_substream_t *subs)
+static int wait_clear_urbs(struct snd_usb_substream *subs)
{
unsigned long end_time = jiffies + msecs_to_jiffies(1000);
unsigned int i;
@@ -855,12 +853,12 @@ static int wait_clear_urbs(snd_usb_substream_t *subs)
/*
* return the current pcm pointer. just return the hwptr_done value.
*/
-static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream)
{
- snd_usb_substream_t *subs;
+ struct snd_usb_substream *subs;
snd_pcm_uframes_t hwptr_done;
- subs = (snd_usb_substream_t *)substream->runtime->private_data;
+ subs = (struct snd_usb_substream *)substream->runtime->private_data;
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
spin_unlock(&subs->lock);
@@ -871,10 +869,10 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(snd_pcm_substream_t *substream)
/*
* start/stop playback substream
*/
-static int snd_usb_pcm_playback_trigger(snd_pcm_substream_t *substream,
+static int snd_usb_pcm_playback_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- snd_usb_substream_t *subs = substream->runtime->private_data;
+ struct snd_usb_substream *subs = substream->runtime->private_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -890,10 +888,10 @@ static int snd_usb_pcm_playback_trigger(snd_pcm_substream_t *substream,
/*
* start/stop capture substream
*/
-static int snd_usb_pcm_capture_trigger(snd_pcm_substream_t *substream,
+static int snd_usb_pcm_capture_trigger(struct snd_pcm_substream *substream,
int cmd)
{
- snd_usb_substream_t *subs = substream->runtime->private_data;
+ struct snd_usb_substream *subs = substream->runtime->private_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -909,7 +907,7 @@ static int snd_usb_pcm_capture_trigger(snd_pcm_substream_t *substream,
/*
* release a urb data
*/
-static void release_urb_ctx(snd_urb_ctx_t *u)
+static void release_urb_ctx(struct snd_urb_ctx *u)
{
if (u->urb) {
if (u->buffer_size)
@@ -924,7 +922,7 @@ static void release_urb_ctx(snd_urb_ctx_t *u)
/*
* release a substream
*/
-static void release_substream_urbs(snd_usb_substream_t *subs, int force)
+static void release_substream_urbs(struct snd_usb_substream *subs, int force)
{
int i;
@@ -945,7 +943,7 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
/*
* initialize a substream for plaback/capture
*/
-static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_bytes,
+static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int period_bytes,
unsigned int rate, unsigned int frame_bits)
{
unsigned int maxsize, n, i;
@@ -1045,7 +1043,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
/* allocate and initialize data urbs */
for (i = 0; i < subs->nurbs; i++) {
- snd_urb_ctx_t *u = &subs->dataurb[i];
+ struct snd_urb_ctx *u = &subs->dataurb[i];
u->index = i;
u->subs = subs;
u->packets = npacks[i];
@@ -1074,7 +1072,7 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
if (! subs->syncbuf)
goto out_of_memory;
for (i = 0; i < SYNC_URBS; i++) {
- snd_urb_ctx_t *u = &subs->syncurb[i];
+ struct snd_urb_ctx *u = &subs->syncurb[i];
u->index = i;
u->subs = subs;
u->packets = 1;
@@ -1104,7 +1102,7 @@ out_of_memory:
/*
* find a matching audio format
*/
-static struct audioformat *find_format(snd_usb_substream_t *subs, unsigned int format,
+static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format,
unsigned int rate, unsigned int channels)
{
struct list_head *p;
@@ -1229,7 +1227,7 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
/*
* find a matching format and set up the interface
*/
-static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
+static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
{
struct usb_device *dev = subs->dev;
struct usb_host_interface *alts;
@@ -1358,10 +1356,10 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
* if sg buffer is supported on the later version of alsa, we'll follow
* that.
*/
-static int snd_usb_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
- snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data;
+ struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data;
struct audioformat *fmt;
unsigned int channels, rate, format;
int ret, changed;
@@ -1415,9 +1413,9 @@ static int snd_usb_hw_params(snd_pcm_substream_t *substream,
*
* reset the audio format and release the buffer
*/
-static int snd_usb_hw_free(snd_pcm_substream_t *substream)
+static int snd_usb_hw_free(struct snd_pcm_substream *substream)
{
- snd_usb_substream_t *subs = (snd_usb_substream_t *)substream->runtime->private_data;
+ struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data;
subs->cur_audiofmt = NULL;
subs->cur_rate = 0;
@@ -1431,10 +1429,10 @@ static int snd_usb_hw_free(snd_pcm_substream_t *substream)
*
* only a few subtle things...
*/
-static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usb_substream_t *subs = runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usb_substream *subs = runtime->private_data;
if (! subs->cur_audiofmt) {
snd_printk(KERN_ERR "usbaudio: no format is specified!\n");
@@ -1463,7 +1461,7 @@ static int snd_usb_pcm_prepare(snd_pcm_substream_t *substream)
return 0;
}
-static snd_pcm_hardware_t snd_usb_playback =
+static struct snd_pcm_hardware snd_usb_playback =
{
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1477,7 +1475,7 @@ static snd_pcm_hardware_t snd_usb_playback =
.periods_max = 1024,
};
-static snd_pcm_hardware_t snd_usb_capture =
+static struct snd_pcm_hardware snd_usb_capture =
{
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -1501,11 +1499,11 @@ static snd_pcm_hardware_t snd_usb_capture =
#define hwc_debug(fmt, args...) /**/
#endif
-static int hw_check_valid_format(snd_pcm_hw_params_t *params, struct audioformat *fp)
+static int hw_check_valid_format(struct snd_pcm_hw_params *params, struct audioformat *fp)
{
- snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
- snd_interval_t *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
- snd_mask_t *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *ct = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_mask *fmts = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
/* check the format */
if (! snd_mask_test(fmts, fp->format)) {
@@ -1529,12 +1527,12 @@ static int hw_check_valid_format(snd_pcm_hw_params_t *params, struct audioformat
return 1;
}
-static int hw_rule_rate(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int hw_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_usb_substream_t *subs = rule->private;
+ struct snd_usb_substream *subs = rule->private;
struct list_head *p;
- snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
unsigned int rmin, rmax;
int changed;
@@ -1583,12 +1581,12 @@ static int hw_rule_rate(snd_pcm_hw_params_t *params,
}
-static int hw_rule_channels(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int hw_rule_channels(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_usb_substream_t *subs = rule->private;
+ struct snd_usb_substream *subs = rule->private;
struct list_head *p;
- snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
unsigned int rmin, rmax;
int changed;
@@ -1636,12 +1634,12 @@ static int hw_rule_channels(snd_pcm_hw_params_t *params,
return changed;
}
-static int hw_rule_format(snd_pcm_hw_params_t *params,
- snd_pcm_hw_rule_t *rule)
+static int hw_rule_format(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
{
- snd_usb_substream_t *subs = rule->private;
+ struct snd_usb_substream *subs = rule->private;
struct list_head *p;
- snd_mask_t *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
u64 fbits;
u32 oldbits[2];
int changed;
@@ -1674,7 +1672,7 @@ static int hw_rule_format(snd_pcm_hw_params_t *params,
/*
* check whether the registered audio formats need special hw-constraints
*/
-static int check_hw_params_convention(snd_usb_substream_t *subs)
+static int check_hw_params_convention(struct snd_usb_substream *subs)
{
int i;
u32 *channels;
@@ -1758,7 +1756,7 @@ static int check_hw_params_convention(snd_usb_substream_t *subs)
* set up the runtime hardware information.
*/
-static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
+static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs)
{
struct list_head *p;
int err;
@@ -1819,12 +1817,12 @@ static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
return 0;
}
-static int snd_usb_pcm_open(snd_pcm_substream_t *substream, int direction,
- snd_pcm_hardware_t *hw)
+static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction,
+ struct snd_pcm_hardware *hw)
{
- snd_usb_stream_t *as = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usb_substream_t *subs = &as->substream[direction];
+ struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usb_substream *subs = &as->substream[direction];
subs->interface = -1;
subs->format = 0;
@@ -1834,10 +1832,10 @@ static int snd_usb_pcm_open(snd_pcm_substream_t *substream, int direction,
return setup_hw_info(runtime, subs);
}
-static int snd_usb_pcm_close(snd_pcm_substream_t *substream, int direction)
+static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
{
- snd_usb_stream_t *as = snd_pcm_substream_chip(substream);
- snd_usb_substream_t *subs = &as->substream[direction];
+ struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
+ struct snd_usb_substream *subs = &as->substream[direction];
if (subs->interface >= 0) {
usb_set_interface(subs->dev, subs->interface, 0);
@@ -1847,27 +1845,27 @@ static int snd_usb_pcm_close(snd_pcm_substream_t *substream, int direction)
return 0;
}
-static int snd_usb_playback_open(snd_pcm_substream_t *substream)
+static int snd_usb_playback_open(struct snd_pcm_substream *substream)
{
return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_playback);
}
-static int snd_usb_playback_close(snd_pcm_substream_t *substream)
+static int snd_usb_playback_close(struct snd_pcm_substream *substream)
{
return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_PLAYBACK);
}
-static int snd_usb_capture_open(snd_pcm_substream_t *substream)
+static int snd_usb_capture_open(struct snd_pcm_substream *substream)
{
return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_capture);
}
-static int snd_usb_capture_close(snd_pcm_substream_t *substream)
+static int snd_usb_capture_close(struct snd_pcm_substream *substream)
{
return snd_usb_pcm_close(substream, SNDRV_PCM_STREAM_CAPTURE);
}
-static snd_pcm_ops_t snd_usb_playback_ops = {
+static struct snd_pcm_ops snd_usb_playback_ops = {
.open = snd_usb_playback_open,
.close = snd_usb_playback_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1879,7 +1877,7 @@ static snd_pcm_ops_t snd_usb_playback_ops = {
.page = snd_pcm_get_vmalloc_page,
};
-static snd_pcm_ops_t snd_usb_capture_ops = {
+static struct snd_pcm_ops snd_usb_capture_ops = {
.open = snd_usb_capture_open,
.close = snd_usb_capture_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -1996,7 +1994,6 @@ static struct usb_device_id usb_audio_ids [] = {
MODULE_DEVICE_TABLE (usb, usb_audio_ids);
static struct usb_driver usb_audio_driver = {
- .owner = THIS_MODULE,
.name = "snd-usb-audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,
@@ -2007,7 +2004,7 @@ static struct usb_driver usb_audio_driver = {
/*
* proc interface for list the supported pcm formats
*/
-static void proc_dump_substream_formats(snd_usb_substream_t *subs, snd_info_buffer_t *buffer)
+static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
{
struct list_head *p;
static char *sync_types[4] = {
@@ -2043,7 +2040,7 @@ static void proc_dump_substream_formats(snd_usb_substream_t *subs, snd_info_buff
}
}
-static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffer_t *buffer)
+static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
{
if (subs->running) {
unsigned int i;
@@ -2065,9 +2062,9 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe
}
}
-static void proc_pcm_format_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- snd_usb_stream_t *stream = entry->private_data;
+ struct snd_usb_stream *stream = entry->private_data;
snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
@@ -2083,11 +2080,11 @@ static void proc_pcm_format_read(snd_info_entry_t *entry, snd_info_buffer_t *buf
}
}
-static void proc_pcm_format_add(snd_usb_stream_t *stream)
+static void proc_pcm_format_add(struct snd_usb_stream *stream)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
char name[32];
- snd_card_t *card = stream->chip->card;
+ struct snd_card *card = stream->chip->card;
sprintf(name, "stream%d", stream->pcm_index);
if (! snd_card_proc_new(card, name, &entry))
@@ -2099,9 +2096,9 @@ static void proc_pcm_format_add(snd_usb_stream_t *stream)
* initialize the substream instance.
*/
-static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat *fp)
+static void init_substream(struct snd_usb_stream *as, int stream, struct audioformat *fp)
{
- snd_usb_substream_t *subs = &as->substream[stream];
+ struct snd_usb_substream *subs = &as->substream[stream];
INIT_LIST_HEAD(&subs->fmt_list);
spin_lock_init(&subs->lock);
@@ -2128,7 +2125,7 @@ static void init_substream(snd_usb_stream_t *as, int stream, struct audioformat
/*
* free a substream
*/
-static void free_substream(snd_usb_substream_t *subs)
+static void free_substream(struct snd_usb_substream *subs)
{
struct list_head *p, *n;
@@ -2145,7 +2142,7 @@ static void free_substream(snd_usb_substream_t *subs)
/*
* free a usb stream instance
*/
-static void snd_usb_audio_stream_free(snd_usb_stream_t *stream)
+static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
{
free_substream(&stream->substream[0]);
free_substream(&stream->substream[1]);
@@ -2153,9 +2150,9 @@ static void snd_usb_audio_stream_free(snd_usb_stream_t *stream)
kfree(stream);
}
-static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
+static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
{
- snd_usb_stream_t *stream = pcm->private_data;
+ struct snd_usb_stream *stream = pcm->private_data;
if (stream) {
stream->pcm = NULL;
snd_usb_audio_stream_free(stream);
@@ -2168,16 +2165,16 @@ static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
* if a stream with the same endpoint already exists, append to it.
* if not, create a new pcm stream.
*/
-static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audioformat *fp)
+static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp)
{
struct list_head *p;
- snd_usb_stream_t *as;
- snd_usb_substream_t *subs;
- snd_pcm_t *pcm;
+ struct snd_usb_stream *as;
+ struct snd_usb_substream *subs;
+ struct snd_pcm *pcm;
int err;
list_for_each(p, &chip->pcm_list) {
- as = list_entry(p, snd_usb_stream_t, list);
+ as = list_entry(p, struct snd_usb_stream, list);
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream];
@@ -2192,7 +2189,7 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
}
/* look for an empty stream */
list_for_each(p, &chip->pcm_list) {
- as = list_entry(p, snd_usb_stream_t, list);
+ as = list_entry(p, struct snd_usb_stream, list);
if (as->fmt_type != fp->fmt_type)
continue;
subs = &as->substream[stream];
@@ -2244,7 +2241,7 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
/*
* check if the device uses big-endian samples
*/
-static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
+static int is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
{
switch (chip->usb_id) {
case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
@@ -2266,7 +2263,7 @@ static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
* @format: the format tag (wFormatTag)
* @fmt: the format type descriptor
*/
-static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_i_type(struct snd_usb_audio *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2349,7 +2346,7 @@ static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *
* @offset: the start offset of descriptor pointing the rate type
* (7 for type I and II, 8 for type II)
*/
-static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioformat *fp,
unsigned char *fmt, int offset)
{
int nr_rates = fmt[offset];
@@ -2402,7 +2399,7 @@ static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *f
/*
* parse the format type I and III descriptors
*/
-static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_i(struct snd_usb_audio *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2431,7 +2428,7 @@ static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
/*
* prase the format type II descriptor
*/
-static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format_ii(struct snd_usb_audio *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int brate, framesize;
@@ -2458,7 +2455,7 @@ static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
}
-static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
+static int parse_audio_format(struct snd_usb_audio *chip, struct audioformat *fp,
int format, unsigned char *fmt, int stream)
{
int err;
@@ -2495,7 +2492,7 @@ static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
return 0;
}
-static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
+static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
{
struct usb_device *dev;
struct usb_interface *iface;
@@ -2646,10 +2643,10 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
static void snd_usb_stream_disconnect(struct list_head *head)
{
int idx;
- snd_usb_stream_t *as;
- snd_usb_substream_t *subs;
+ struct snd_usb_stream *as;
+ struct snd_usb_substream *subs;
- as = list_entry(head, snd_usb_stream_t, list);
+ as = list_entry(head, struct snd_usb_stream, list);
for (idx = 0; idx < 2; idx++) {
subs = &as->substream[idx];
if (!subs->num_formats)
@@ -2662,7 +2659,7 @@ static void snd_usb_stream_disconnect(struct list_head *head)
/*
* parse audio control descriptor and create pcm/midi streams
*/
-static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif)
+static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
{
struct usb_device *dev = chip->dev;
struct usb_host_interface *host_iface;
@@ -2729,9 +2726,9 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif)
/*
* create a stream for an endpoint/altsetting without proper descriptors
*/
-static int create_fixed_stream_quirk(snd_usb_audio_t *chip,
+static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
struct audioformat *fp;
struct usb_host_interface *alts;
@@ -2778,9 +2775,9 @@ static int create_fixed_stream_quirk(snd_usb_audio_t *chip,
/*
* create a stream for an interface with proper descriptors
*/
-static int create_standard_audio_quirk(snd_usb_audio_t *chip,
+static int create_standard_audio_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
@@ -2803,9 +2800,9 @@ static int create_standard_audio_quirk(snd_usb_audio_t *chip,
* Create a stream for an Edirol UA-700/UA-25 interface. The only way
* to detect the sample rate is by looking at wMaxPacketSize.
*/
-static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
+static int create_ua700_ua25_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
static const struct audioformat ua_format = {
.format = SNDRV_PCM_FORMAT_S24_3LE,
@@ -2827,19 +2824,19 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
altsd = get_iface_desc(alts);
if (altsd->bNumEndpoints == 2) {
- static const snd_usb_midi_endpoint_info_t ua700_ep = {
+ static const struct snd_usb_midi_endpoint_info ua700_ep = {
.out_cables = 0x0003,
.in_cables = 0x0003
};
- static const snd_usb_audio_quirk_t ua700_quirk = {
+ static const struct snd_usb_audio_quirk ua700_quirk = {
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &ua700_ep
};
- static const snd_usb_midi_endpoint_info_t ua25_ep = {
+ static const struct snd_usb_midi_endpoint_info ua25_ep = {
.out_cables = 0x0001,
.in_cables = 0x0001
};
- static const snd_usb_audio_quirk_t ua25_quirk = {
+ static const struct snd_usb_audio_quirk ua25_quirk = {
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &ua25_ep
};
@@ -2896,9 +2893,9 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
/*
* Create a stream for an Edirol UA-1000 interface.
*/
-static int create_ua1000_quirk(snd_usb_audio_t *chip,
+static int create_ua1000_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
static const struct audioformat ua1000_format = {
.format = SNDRV_PCM_FORMAT_S32_LE,
@@ -2945,16 +2942,16 @@ static int create_ua1000_quirk(snd_usb_audio_t *chip,
return 0;
}
-static int snd_usb_create_quirk(snd_usb_audio_t *chip,
+static int snd_usb_create_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk);
+ const struct snd_usb_audio_quirk *quirk);
/*
* handle the quirks for the contained interfaces
*/
-static int create_composite_quirk(snd_usb_audio_t *chip,
+static int create_composite_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber;
int err;
@@ -2975,9 +2972,9 @@ static int create_composite_quirk(snd_usb_audio_t *chip,
return 0;
}
-static int ignore_interface_quirk(snd_usb_audio_t *chip,
+static int ignore_interface_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
return 0;
}
@@ -3040,12 +3037,12 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
* after this.
* returns a negative value at error.
*/
-static int snd_usb_create_quirk(snd_usb_audio_t *chip,
+static int snd_usb_create_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
- const snd_usb_audio_quirk_t *quirk)
+ const struct snd_usb_audio_quirk *quirk)
{
- typedef int (*quirk_func_t)(snd_usb_audio_t *, struct usb_interface *,
- const snd_usb_audio_quirk_t *);
+ typedef int (*quirk_func_t)(struct snd_usb_audio *, struct usb_interface *,
+ const struct snd_usb_audio_quirk *);
static const quirk_func_t quirk_funcs[] = {
[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
[QUIRK_COMPOSITE] = create_composite_quirk,
@@ -3075,25 +3072,25 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
/*
* common proc files to show the usb device info
*/
-static void proc_audio_usbbus_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- snd_usb_audio_t *chip = entry->private_data;
+ struct snd_usb_audio *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
}
-static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
- snd_usb_audio_t *chip = entry->private_data;
+ struct snd_usb_audio *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%04x:%04x\n",
USB_ID_VENDOR(chip->usb_id),
USB_ID_PRODUCT(chip->usb_id));
}
-static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
+static void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
{
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if (! snd_card_proc_new(chip->card, "usbbus", &entry))
snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read);
if (! snd_card_proc_new(chip->card, "usbid", &entry))
@@ -3107,15 +3104,15 @@ static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
*
*/
-static int snd_usb_audio_free(snd_usb_audio_t *chip)
+static int snd_usb_audio_free(struct snd_usb_audio *chip)
{
kfree(chip);
return 0;
}
-static int snd_usb_audio_dev_free(snd_device_t *device)
+static int snd_usb_audio_dev_free(struct snd_device *device)
{
- snd_usb_audio_t *chip = device->device_data;
+ struct snd_usb_audio *chip = device->device_data;
return snd_usb_audio_free(chip);
}
@@ -3124,14 +3121,14 @@ static int snd_usb_audio_dev_free(snd_device_t *device)
* create a chip instance and set its names.
*/
static int snd_usb_audio_create(struct usb_device *dev, int idx,
- const snd_usb_audio_quirk_t *quirk,
- snd_usb_audio_t **rchip)
+ const struct snd_usb_audio_quirk *quirk,
+ struct snd_usb_audio **rchip)
{
- snd_card_t *card;
- snd_usb_audio_t *chip;
+ struct snd_card *card;
+ struct snd_usb_audio *chip;
int err, len;
char component[14];
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_usb_audio_dev_free,
};
@@ -3235,9 +3232,9 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
struct usb_interface *intf,
const struct usb_device_id *usb_id)
{
- const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)usb_id->driver_info;
+ const struct snd_usb_audio_quirk *quirk = (const struct snd_usb_audio_quirk *)usb_id->driver_info;
int i, err;
- snd_usb_audio_t *chip;
+ struct snd_usb_audio *chip;
struct usb_host_interface *alts;
int ifnum;
u32 id;
@@ -3338,8 +3335,8 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
*/
static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
{
- snd_usb_audio_t *chip;
- snd_card_t *card;
+ struct snd_usb_audio *chip;
+ struct snd_card *card;
struct list_head *p;
if (ptr == (void *)-1L)
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index b5802022bb19..ecd724bfe5a5 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -126,12 +126,10 @@
/*
*/
-typedef struct snd_usb_audio snd_usb_audio_t;
-
struct snd_usb_audio {
int index;
struct usb_device *dev;
- snd_card_t *card;
+ struct snd_card *card;
u32 usb_id;
int shutdown;
int num_interfaces;
@@ -172,9 +170,6 @@ enum quirk_type {
QUIRK_TYPE_COUNT
};
-typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
-typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
-
struct snd_usb_audio_quirk {
const char *vendor_name;
const char *product_name;
@@ -228,12 +223,15 @@ unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size);
void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype);
void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype);
-int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
+int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout);
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif);
void snd_usb_mixer_disconnect(struct list_head *p);
-int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
+int snd_usb_create_midi_interface(struct snd_usb_audio *chip, struct usb_interface *iface,
+ const struct snd_usb_audio_quirk *quirk);
void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
void snd_usbmidi_disconnect(struct list_head *p);
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index f8aa662562a0..f15b021c3ce8 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -84,39 +84,36 @@ struct usb_ms_endpoint_descriptor {
__u8 baAssocJackID[0];
} __attribute__ ((packed));
-typedef struct snd_usb_midi snd_usb_midi_t;
-typedef struct snd_usb_midi_endpoint snd_usb_midi_endpoint_t;
-typedef struct snd_usb_midi_out_endpoint snd_usb_midi_out_endpoint_t;
-typedef struct snd_usb_midi_in_endpoint snd_usb_midi_in_endpoint_t;
-typedef struct usbmidi_out_port usbmidi_out_port_t;
-typedef struct usbmidi_in_port usbmidi_in_port_t;
+struct snd_usb_midi_in_endpoint;
+struct snd_usb_midi_out_endpoint;
+struct snd_usb_midi_endpoint;
struct usb_protocol_ops {
- void (*input)(snd_usb_midi_in_endpoint_t*, uint8_t*, int);
- void (*output)(snd_usb_midi_out_endpoint_t*);
+ void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int);
+ void (*output)(struct snd_usb_midi_out_endpoint*);
void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t);
- void (*init_out_endpoint)(snd_usb_midi_out_endpoint_t*);
- void (*finish_out_endpoint)(snd_usb_midi_out_endpoint_t*);
+ void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*);
+ void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*);
};
struct snd_usb_midi {
- snd_usb_audio_t *chip;
+ struct snd_usb_audio *chip;
struct usb_interface *iface;
- const snd_usb_audio_quirk_t *quirk;
- snd_rawmidi_t* rmidi;
+ const struct snd_usb_audio_quirk *quirk;
+ struct snd_rawmidi *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;
- snd_usb_midi_in_endpoint_t *in;
+ struct snd_usb_midi_out_endpoint *out;
+ struct snd_usb_midi_in_endpoint *in;
} endpoints[MIDI_MAX_ENDPOINTS];
unsigned long input_triggered;
};
struct snd_usb_midi_out_endpoint {
- snd_usb_midi_t* umidi;
+ struct snd_usb_midi* umidi;
struct urb* urb;
int urb_active;
int max_transfer; /* size of urb buffer */
@@ -125,8 +122,8 @@ struct snd_usb_midi_out_endpoint {
spinlock_t buffer_lock;
struct usbmidi_out_port {
- snd_usb_midi_out_endpoint_t* ep;
- snd_rawmidi_substream_t* substream;
+ struct snd_usb_midi_out_endpoint* ep;
+ struct snd_rawmidi_substream *substream;
int active;
uint8_t cable; /* cable number << 4 */
uint8_t state;
@@ -143,17 +140,17 @@ struct snd_usb_midi_out_endpoint {
};
struct snd_usb_midi_in_endpoint {
- snd_usb_midi_t* umidi;
+ struct snd_usb_midi* umidi;
struct urb* urb;
struct usbmidi_in_port {
- snd_rawmidi_substream_t* substream;
+ struct snd_rawmidi_substream *substream;
} ports[0x10];
u8 seen_f5;
u8 error_resubmit;
int current_port;
};
-static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep);
+static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep);
static const uint8_t snd_usbmidi_cin_length[] = {
0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
@@ -196,10 +193,10 @@ static int snd_usbmidi_urb_error(int status)
/*
* Receives a chunk of MIDI data.
*/
-static void snd_usbmidi_input_data(snd_usb_midi_in_endpoint_t* ep, int portidx,
+static void snd_usbmidi_input_data(struct snd_usb_midi_in_endpoint* ep, int portidx,
uint8_t* data, int length)
{
- usbmidi_in_port_t* port = &ep->ports[portidx];
+ struct usbmidi_in_port* port = &ep->ports[portidx];
if (!port->substream) {
snd_printd("unexpected port %d!\n", portidx);
@@ -227,7 +224,7 @@ static void dump_urb(const char *type, const u8 *data, int length)
*/
static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
{
- snd_usb_midi_in_endpoint_t* ep = urb->context;
+ struct snd_usb_midi_in_endpoint* ep = urb->context;
if (urb->status == 0) {
dump_urb("received", urb->transfer_buffer, urb->actual_length);
@@ -251,7 +248,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
{
- snd_usb_midi_out_endpoint_t* ep = urb->context;
+ struct snd_usb_midi_out_endpoint* ep = urb->context;
spin_lock(&ep->buffer_lock);
ep->urb_active = 0;
@@ -272,7 +269,7 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
* This is called when some data should be transferred to the device
* (from one or more substreams).
*/
-static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
{
struct urb* urb = ep->urb;
unsigned long flags;
@@ -297,7 +294,7 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
static void snd_usbmidi_out_tasklet(unsigned long data)
{
- snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+ struct snd_usb_midi_out_endpoint* ep = (struct snd_usb_midi_out_endpoint *) data;
snd_usbmidi_do_output(ep);
}
@@ -305,11 +302,11 @@ static void snd_usbmidi_out_tasklet(unsigned long data)
/* 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;
+ struct snd_usb_midi *umidi = (struct snd_usb_midi *)data;
int i;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
- snd_usb_midi_in_endpoint_t *in = umidi->endpoints[i].in;
+ struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in;
if (in && in->error_resubmit) {
in->error_resubmit = 0;
in->urb->dev = umidi->chip->dev;
@@ -321,7 +318,7 @@ static void snd_usbmidi_error_timer(unsigned long data)
}
/* helper function to send static data that may not DMA-able */
-static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
+static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
const void *data, int len)
{
int err;
@@ -342,7 +339,7 @@ static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
* fourth byte in each packet, and uses length instead of CIN.
*/
-static void snd_usbmidi_standard_input(snd_usb_midi_in_endpoint_t* ep,
+static void snd_usbmidi_standard_input(struct snd_usb_midi_in_endpoint* ep,
uint8_t* buffer, int buffer_length)
{
int i;
@@ -355,7 +352,7 @@ static void snd_usbmidi_standard_input(snd_usb_midi_in_endpoint_t* ep,
}
}
-static void snd_usbmidi_midiman_input(snd_usb_midi_in_endpoint_t* ep,
+static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep,
uint8_t* buffer, int buffer_length)
{
int i;
@@ -401,7 +398,7 @@ static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0,
/*
* Converts MIDI commands to USB MIDI packets.
*/
-static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
+static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port,
uint8_t b, struct urb* urb)
{
uint8_t p0 = port->cable;
@@ -495,14 +492,14 @@ static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
}
}
-static void snd_usbmidi_standard_output(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep)
{
struct urb* urb = ep->urb;
int p;
/* FIXME: lower-numbered ports can starve higher-numbered ports */
for (p = 0; p < 0x10; ++p) {
- usbmidi_out_port_t* port = &ep->ports[p];
+ struct usbmidi_out_port* port = &ep->ports[p];
if (!port->active)
continue;
while (urb->transfer_buffer_length + 3 < ep->max_transfer) {
@@ -534,7 +531,7 @@ static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
* at the third byte.
*/
-static void snd_usbmidi_novation_input(snd_usb_midi_in_endpoint_t* ep,
+static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep,
uint8_t* buffer, int buffer_length)
{
if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1)
@@ -542,7 +539,7 @@ static void snd_usbmidi_novation_input(snd_usb_midi_in_endpoint_t* ep,
snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
}
-static void snd_usbmidi_novation_output(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep)
{
uint8_t* transfer_buffer;
int count;
@@ -571,13 +568,13 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
* "raw" protocol: used by the MOTU FastLane.
*/
-static void snd_usbmidi_raw_input(snd_usb_midi_in_endpoint_t* ep,
+static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
uint8_t* buffer, int buffer_length)
{
snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
}
-static void snd_usbmidi_raw_output(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep)
{
int count;
@@ -602,7 +599,7 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
* Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching.
*/
-static void snd_usbmidi_emagic_init_out(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_emagic_init_out(struct snd_usb_midi_out_endpoint* ep)
{
static const u8 init_data[] = {
/* initialization magic: "get version" */
@@ -619,7 +616,7 @@ static void snd_usbmidi_emagic_init_out(snd_usb_midi_out_endpoint_t* ep)
send_bulk_static_data(ep, init_data, sizeof(init_data));
}
-static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_emagic_finish_out(struct snd_usb_midi_out_endpoint* ep)
{
static const u8 finish_data[] = {
/* switch to patch mode with last preset */
@@ -635,7 +632,7 @@ static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep)
send_bulk_static_data(ep, finish_data, sizeof(finish_data));
}
-static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep,
+static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep,
uint8_t* buffer, int buffer_length)
{
int i;
@@ -679,7 +676,7 @@ static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep,
}
}
-static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep)
{
int port0 = ep->current_port;
uint8_t* buf = ep->urb->transfer_buffer;
@@ -689,7 +686,7 @@ static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep)
for (i = 0; i < 0x10; ++i) {
/* round-robin, starting at the last current port */
int portnum = (port0 + i) & 15;
- usbmidi_out_port_t* port = &ep->ports[portnum];
+ struct usbmidi_out_port* port = &ep->ports[portnum];
if (!port->active)
continue;
@@ -733,10 +730,10 @@ static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
};
-static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
+static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
{
- snd_usb_midi_t* umidi = substream->rmidi->private_data;
- usbmidi_out_port_t* port = NULL;
+ struct snd_usb_midi* umidi = substream->rmidi->private_data;
+ struct usbmidi_out_port* port = NULL;
int i, j;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
@@ -755,14 +752,14 @@ static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
return 0;
}
-static int snd_usbmidi_output_close(snd_rawmidi_substream_t* substream)
+static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
{
return 0;
}
-static void snd_usbmidi_output_trigger(snd_rawmidi_substream_t* substream, int up)
+static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{
- usbmidi_out_port_t* port = (usbmidi_out_port_t*)substream->runtime->private_data;
+ struct usbmidi_out_port* port = (struct usbmidi_out_port*)substream->runtime->private_data;
port->active = up;
if (up) {
@@ -777,19 +774,19 @@ static void snd_usbmidi_output_trigger(snd_rawmidi_substream_t* substream, int u
}
}
-static int snd_usbmidi_input_open(snd_rawmidi_substream_t* substream)
+static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
{
return 0;
}
-static int snd_usbmidi_input_close(snd_rawmidi_substream_t* substream)
+static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
{
return 0;
}
-static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up)
+static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{
- snd_usb_midi_t* umidi = substream->rmidi->private_data;
+ struct snd_usb_midi* umidi = substream->rmidi->private_data;
if (up)
set_bit(substream->number, &umidi->input_triggered);
@@ -797,13 +794,13 @@ static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up
clear_bit(substream->number, &umidi->input_triggered);
}
-static snd_rawmidi_ops_t snd_usbmidi_output_ops = {
+static struct snd_rawmidi_ops snd_usbmidi_output_ops = {
.open = snd_usbmidi_output_open,
.close = snd_usbmidi_output_close,
.trigger = snd_usbmidi_output_trigger,
};
-static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
+static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
.open = snd_usbmidi_input_open,
.close = snd_usbmidi_input_close,
.trigger = snd_usbmidi_input_trigger
@@ -813,7 +810,7 @@ static snd_rawmidi_ops_t snd_usbmidi_input_ops = {
* Frees an input endpoint.
* May be called when ep hasn't been initialized completely.
*/
-static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
+static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep)
{
if (ep->urb) {
usb_buffer_free(ep->umidi->chip->dev,
@@ -828,11 +825,11 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
/*
* Creates an input endpoint.
*/
-static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* ep_info,
- snd_usb_midi_endpoint_t* rep)
+static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* ep_info,
+ struct snd_usb_midi_endpoint* rep)
{
- snd_usb_midi_in_endpoint_t* ep;
+ struct snd_usb_midi_in_endpoint* ep;
void* buffer;
unsigned int pipe;
int length;
@@ -885,7 +882,7 @@ static unsigned int snd_usbmidi_count_bits(unsigned int x)
* Frees an output endpoint.
* May be called when ep hasn't been initialized completely.
*/
-static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
+static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep)
{
if (ep->urb) {
usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer,
@@ -899,11 +896,11 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
/*
* Creates an output endpoint, and initializes output ports.
*/
-static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* ep_info,
- snd_usb_midi_endpoint_t* rep)
+static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* ep_info,
+ struct snd_usb_midi_endpoint* rep)
{
- snd_usb_midi_out_endpoint_t* ep;
+ struct snd_usb_midi_out_endpoint* ep;
int i;
unsigned int pipe;
void* buffer;
@@ -951,12 +948,12 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
/*
* Frees everything.
*/
-static void snd_usbmidi_free(snd_usb_midi_t* umidi)
+static void snd_usbmidi_free(struct snd_usb_midi* umidi)
{
int i;
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
- snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+ struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
if (ep->out)
snd_usbmidi_out_endpoint_delete(ep->out);
if (ep->in)
@@ -970,13 +967,13 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
*/
void snd_usbmidi_disconnect(struct list_head* p)
{
- snd_usb_midi_t* umidi;
+ struct snd_usb_midi* umidi;
int i;
- umidi = list_entry(p, snd_usb_midi_t, list);
+ umidi = list_entry(p, struct snd_usb_midi, list);
del_timer_sync(&umidi->error_timer);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
- snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+ struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
if (ep->out)
tasklet_kill(&ep->out->tasklet);
if (ep->out && ep->out->urb) {
@@ -989,19 +986,19 @@ void snd_usbmidi_disconnect(struct list_head* p)
}
}
-static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
+static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
{
- snd_usb_midi_t* umidi = rmidi->private_data;
+ struct snd_usb_midi* umidi = rmidi->private_data;
snd_usbmidi_free(umidi);
}
-static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi,
+static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
int stream, int number)
{
struct list_head* list;
list_for_each(list, &umidi->rmidi->streams[stream].substreams) {
- snd_rawmidi_substream_t* substream = list_entry(list, snd_rawmidi_substream_t, list);
+ struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
if (substream->number == number)
return substream;
}
@@ -1097,14 +1094,14 @@ static struct {
{ USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
};
-static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
+static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
int stream, int number,
- snd_rawmidi_substream_t** rsubstream)
+ struct snd_rawmidi_substream ** rsubstream)
{
int i;
const char *name_format;
- snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
+ struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number);
if (!substream) {
snd_printd(KERN_ERR "substream %d:%d not found\n", stream, number);
return;
@@ -1128,8 +1125,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
/*
* Creates the endpoints and their ports.
*/
-static int snd_usbmidi_create_endpoints(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoints)
+static int snd_usbmidi_create_endpoints(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoints)
{
int i, j, err;
int out_ports = 0, in_ports = 0;
@@ -1169,8 +1166,8 @@ static int snd_usbmidi_create_endpoints(snd_usb_midi_t* umidi,
/*
* Returns MIDIStreaming device capabilities.
*/
-static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoints)
+static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoints)
{
struct usb_interface* intf;
struct usb_host_interface *hostif;
@@ -1244,7 +1241,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
* On Roland devices, use the second alternate setting to be able to use
* the interrupt input endpoint.
*/
-static void snd_usbmidi_switch_roland_altsetting(snd_usb_midi_t* umidi)
+static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
{
struct usb_interface* intf;
struct usb_host_interface *hostif;
@@ -1270,8 +1267,8 @@ static void snd_usbmidi_switch_roland_altsetting(snd_usb_midi_t* umidi)
/*
* Try to find any usable endpoints in the interface.
*/
-static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoint,
+static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoint,
int max_endpoints)
{
struct usb_interface* intf;
@@ -1318,8 +1315,8 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
/*
* Detects the endpoints for one-port-per-endpoint protocols.
*/
-static int snd_usbmidi_detect_per_port_endpoints(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoints)
+static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoints)
{
int err, i;
@@ -1336,8 +1333,8 @@ static int snd_usbmidi_detect_per_port_endpoints(snd_usb_midi_t* umidi,
/*
* Detects the endpoints and ports of Yamaha devices.
*/
-static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoint)
+static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoint)
{
struct usb_interface* intf;
struct usb_host_interface *hostif;
@@ -1375,10 +1372,10 @@ static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
/*
* Creates the endpoints and their ports for Midiman devices.
*/
-static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi,
- snd_usb_midi_endpoint_info_t* endpoint)
+static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
+ struct snd_usb_midi_endpoint_info* endpoint)
{
- snd_usb_midi_endpoint_info_t ep_info;
+ struct snd_usb_midi_endpoint_info ep_info;
struct usb_interface* intf;
struct usb_host_interface *hostif;
struct usb_interface_descriptor* intfd;
@@ -1458,10 +1455,10 @@ static int snd_usbmidi_create_endpoints_midiman(snd_usb_midi_t* umidi,
return 0;
}
-static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
+static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
int out_ports, int in_ports)
{
- snd_rawmidi_t* rmidi;
+ struct snd_rawmidi *rmidi;
int err;
err = snd_rawmidi_new(umidi->chip->card, "USB MIDI",
@@ -1487,18 +1484,18 @@ static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
*/
void snd_usbmidi_input_stop(struct list_head* p)
{
- snd_usb_midi_t* umidi;
+ struct snd_usb_midi* umidi;
int i;
- umidi = list_entry(p, snd_usb_midi_t, list);
+ umidi = list_entry(p, struct snd_usb_midi, list);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
- snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+ struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
if (ep->in)
usb_kill_urb(ep->in->urb);
}
}
-static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
{
if (ep) {
struct urb* urb = ep->urb;
@@ -1512,10 +1509,10 @@ static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
*/
void snd_usbmidi_input_start(struct list_head* p)
{
- snd_usb_midi_t* umidi;
+ struct snd_usb_midi* umidi;
int i;
- umidi = list_entry(p, snd_usb_midi_t, list);
+ umidi = list_entry(p, struct snd_usb_midi, list);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
}
@@ -1523,12 +1520,12 @@ void snd_usbmidi_input_start(struct list_head* p)
/*
* Creates and registers everything needed for a MIDI streaming interface.
*/
-int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
+int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
struct usb_interface* iface,
- const snd_usb_audio_quirk_t* quirk)
+ const struct snd_usb_audio_quirk* quirk)
{
- snd_usb_midi_t* umidi;
- snd_usb_midi_endpoint_info_t endpoints[MIDI_MAX_ENDPOINTS];
+ struct snd_usb_midi* umidi;
+ struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
int out_ports, in_ports;
int i, err;
@@ -1551,7 +1548,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
break;
case QUIRK_MIDI_FIXED_ENDPOINT:
memcpy(&endpoints[0], quirk->data,
- sizeof(snd_usb_midi_endpoint_info_t));
+ sizeof(struct snd_usb_midi_endpoint_info));
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_YAMAHA:
@@ -1560,7 +1557,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
case QUIRK_MIDI_MIDIMAN:
umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
memcpy(&endpoints[0], quirk->data,
- sizeof(snd_usb_midi_endpoint_info_t));
+ sizeof(struct snd_usb_midi_endpoint_info));
err = 0;
break;
case QUIRK_MIDI_NOVATION:
@@ -1574,7 +1571,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
case QUIRK_MIDI_EMAGIC:
umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops;
memcpy(&endpoints[0], quirk->data,
- sizeof(snd_usb_midi_endpoint_info_t));
+ sizeof(struct snd_usb_midi_endpoint_info));
err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
break;
case QUIRK_MIDI_MIDITECH:
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index e570d140258d..678dac2d4dba 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -46,18 +46,13 @@
/* ignore error from controls - for debugging */
/* #define IGNORE_CTL_ERROR */
-typedef struct usb_mixer_build mixer_build_t;
-typedef struct usb_audio_term usb_audio_term_t;
-typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
-
-
struct usb_mixer_interface {
- snd_usb_audio_t *chip;
+ struct snd_usb_audio *chip;
unsigned int ctrlif;
struct list_head list;
unsigned int ignore_ctl_error;
struct urb *urb;
- usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */
+ struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
/* Sound Blaster remote control stuff */
enum {
@@ -86,21 +81,21 @@ struct usb_audio_term {
struct usbmix_name_map;
-struct usb_mixer_build {
- snd_usb_audio_t *chip;
+struct mixer_build {
+ struct snd_usb_audio *chip;
struct usb_mixer_interface *mixer;
unsigned char *buffer;
unsigned int buflen;
DECLARE_BITMAP(unitbitmap, 256);
- usb_audio_term_t oterm;
+ struct usb_audio_term oterm;
const struct usbmix_name_map *map;
const struct usbmix_selector_map *selector_map;
};
struct usb_mixer_elem_info {
struct usb_mixer_interface *mixer;
- usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */
- snd_ctl_elem_id_t *elem_id;
+ struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */
+ struct snd_ctl_elem_id *elem_id;
unsigned int id;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
@@ -179,7 +174,7 @@ enum {
#include "usbmixer_maps.c"
/* get the mapped name if the unit matches */
-static int check_mapped_name(mixer_build_t *state, int unitid, int control, char *buf, int buflen)
+static int check_mapped_name(struct mixer_build *state, int unitid, int control, char *buf, int buflen)
{
const struct usbmix_name_map *p;
@@ -197,7 +192,7 @@ static int check_mapped_name(mixer_build_t *state, int unitid, int control, char
}
/* check whether the control should be ignored */
-static int check_ignored_ctl(mixer_build_t *state, int unitid, int control)
+static int check_ignored_ctl(struct mixer_build *state, int unitid, int control)
{
const struct usbmix_name_map *p;
@@ -214,7 +209,7 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control)
}
/* get the mapped selector source name */
-static int check_mapped_selector_name(mixer_build_t *state, int unitid,
+static int check_mapped_selector_name(struct mixer_build *state, int unitid,
int index, char *buf, int buflen)
{
const struct usbmix_selector_map *p;
@@ -231,7 +226,7 @@ static int check_mapped_selector_name(mixer_build_t *state, int unitid,
/*
* find an audio control unit with the given unit id
*/
-static void *find_audio_control_unit(mixer_build_t *state, unsigned char unit)
+static void *find_audio_control_unit(struct mixer_build *state, unsigned char unit)
{
unsigned char *p;
@@ -248,7 +243,7 @@ static void *find_audio_control_unit(mixer_build_t *state, unsigned char unit)
/*
* copy a string with the given id
*/
-static int snd_usb_copy_string_desc(mixer_build_t *state, int index, char *buf, int maxlen)
+static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen)
{
int len = usb_string(state->chip->dev, index, buf, maxlen - 1);
buf[len] = 0;
@@ -258,7 +253,7 @@ static int snd_usb_copy_string_desc(mixer_build_t *state, int index, char *buf,
/*
* convert from the byte/word on usb descriptor to the zero-based integer
*/
-static int convert_signed_value(usb_mixer_elem_info_t *cval, int val)
+static int convert_signed_value(struct usb_mixer_elem_info *cval, int val)
{
switch (cval->val_type) {
case USB_MIXER_BOOLEAN:
@@ -288,7 +283,7 @@ static int convert_signed_value(usb_mixer_elem_info_t *cval, int val)
/*
* convert from the zero-based int to the byte/word for usb descriptor
*/
-static int convert_bytes_value(usb_mixer_elem_info_t *cval, int val)
+static int convert_bytes_value(struct usb_mixer_elem_info *cval, int val)
{
switch (cval->val_type) {
case USB_MIXER_BOOLEAN:
@@ -305,7 +300,7 @@ static int convert_bytes_value(usb_mixer_elem_info_t *cval, int val)
return 0; /* not reached */
}
-static int get_relative_value(usb_mixer_elem_info_t *cval, int val)
+static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
{
if (! cval->res)
cval->res = 1;
@@ -317,7 +312,7 @@ static int get_relative_value(usb_mixer_elem_info_t *cval, int val)
return (val - cval->min) / cval->res;
}
-static int get_abs_value(usb_mixer_elem_info_t *cval, int val)
+static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
{
if (val < 0)
return cval->min;
@@ -335,7 +330,7 @@ static int get_abs_value(usb_mixer_elem_info_t *cval, int val)
* retrieve a mixer value
*/
-static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, int *value_ret)
+static int get_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
{
unsigned char buf[2];
int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -357,13 +352,13 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
return -EINVAL;
}
-static int get_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int *value)
+static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int *value)
{
return get_ctl_value(cval, GET_CUR, validx, value);
}
/* channel = 0: master, 1 = first channel */
-static inline int get_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int *value)
+static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value)
{
return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value);
}
@@ -372,7 +367,7 @@ static inline int get_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, in
* set a mixer value
*/
-static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, int value_set)
+static int set_ctl_value(struct usb_mixer_elem_info *cval, int request, int validx, int value_set)
{
unsigned char buf[2];
int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -394,12 +389,12 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
return -EINVAL;
}
-static int set_cur_ctl_value(usb_mixer_elem_info_t *cval, int validx, int value)
+static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
{
return set_ctl_value(cval, SET_CUR, validx, value);
}
-static inline int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, int value)
+static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value)
{
return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value);
}
@@ -409,7 +404,7 @@ static inline int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, in
* parser routines begin here...
*/
-static int parse_audio_unit(mixer_build_t *state, int unitid);
+static int parse_audio_unit(struct mixer_build *state, int unitid);
/*
@@ -430,9 +425,9 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
* if failed, give up and free the control instance.
*/
-static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
+static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl)
{
- usb_mixer_elem_info_t *cval = kctl->private_data;
+ struct usb_mixer_elem_info *cval = kctl->private_data;
int err;
while (snd_ctl_find_id(state->chip->card, &kctl->id))
@@ -496,7 +491,7 @@ static struct iterm_name_combo {
{ 0 },
};
-static int get_term_name(mixer_build_t *state, usb_audio_term_t *iterm,
+static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm,
unsigned char *name, int maxlen, int term_only)
{
struct iterm_name_combo *names;
@@ -546,7 +541,7 @@ static int get_term_name(mixer_build_t *state, usb_audio_term_t *iterm,
* parse the source unit recursively until it reaches to a terminal
* or a branched unit.
*/
-static int check_input_term(mixer_build_t *state, int id, usb_audio_term_t *term)
+static int check_input_term(struct mixer_build *state, int id, struct usb_audio_term *term)
{
unsigned char *p1;
@@ -621,7 +616,7 @@ static struct usb_feature_control_info audio_feature_info[] = {
/* private_free callback */
-static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
+static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
{
kfree(kctl->private_data);
kctl->private_data = NULL;
@@ -635,7 +630,7 @@ static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
/*
* retrieve the minimum and maximum values for the specified control
*/
-static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
+static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
{
/* for failsafe */
cval->min = default_min;
@@ -683,9 +678,9 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
/* get a feature/mixer unit info */
-static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
if (cval->val_type == USB_MIXER_BOOLEAN ||
cval->val_type == USB_MIXER_INV_BOOLEAN)
@@ -707,9 +702,9 @@ static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
}
/* get the current value from feature/mixer unit */
-static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int c, cnt, val, err;
if (cval->cmask) {
@@ -748,9 +743,9 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* put the current value to feature/mixer unit */
-static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int c, cnt, val, oval, err;
int changed = 0;
@@ -791,7 +786,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return changed;
}
-static snd_kcontrol_new_t usb_feature_unit_ctl = {
+static struct snd_kcontrol_new usb_feature_unit_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later manually */
.info = mixer_ctl_feature_info,
@@ -804,15 +799,15 @@ static snd_kcontrol_new_t usb_feature_unit_ctl = {
* build a feature control
*/
-static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
+static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
unsigned int ctl_mask, int control,
- usb_audio_term_t *iterm, int unitid)
+ struct usb_audio_term *iterm, int unitid)
{
unsigned int len = 0;
int mapped_name = 0;
int nameid = desc[desc[0] - 1];
- snd_kcontrol_t *kctl;
- usb_mixer_elem_info_t *cval;
+ struct snd_kcontrol *kctl;
+ struct usb_mixer_elem_info *cval;
control++; /* change from zero-based to 1-based value */
@@ -928,10 +923,10 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
*
* most of controlls are defined here.
*/
-static int parse_audio_feature_unit(mixer_build_t *state, int unitid, unsigned char *ftr)
+static int parse_audio_feature_unit(struct mixer_build *state, int unitid, unsigned char *ftr)
{
int channels, i, j;
- usb_audio_term_t iterm;
+ struct usb_audio_term iterm;
unsigned int master_bits, first_ch_bits;
int err, csize;
@@ -984,15 +979,15 @@ static int parse_audio_feature_unit(mixer_build_t *state, int unitid, unsigned c
* input channel number (zero based) is given in control field instead.
*/
-static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
+static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
int in_pin, int in_ch, int unitid,
- usb_audio_term_t *iterm)
+ struct usb_audio_term *iterm)
{
- usb_mixer_elem_info_t *cval;
+ struct usb_mixer_elem_info *cval;
unsigned int input_pins = desc[4];
unsigned int num_outs = desc[5 + input_pins];
unsigned int i, len;
- snd_kcontrol_t *kctl;
+ struct snd_kcontrol *kctl;
if (check_ignored_ctl(state, unitid, 0))
return;
@@ -1039,9 +1034,9 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
/*
* parse a mixer unit
*/
-static int parse_audio_mixer_unit(mixer_build_t *state, int unitid, unsigned char *desc)
+static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
- usb_audio_term_t iterm;
+ struct usb_audio_term iterm;
int input_pins, num_ins, num_outs;
int pin, ich, err;
@@ -1089,9 +1084,9 @@ static int parse_audio_mixer_unit(mixer_build_t *state, int unitid, unsigned cha
*/
/* get callback for processing/extension unit */
-static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int err, val;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
@@ -1107,9 +1102,9 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* put callback for processing/extension unit */
-static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
@@ -1128,7 +1123,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* alsa control interface for processing/extension unit */
-static snd_kcontrol_new_t mixer_procunit_ctl = {
+static struct snd_kcontrol_new mixer_procunit_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later */
.info = mixer_ctl_feature_info,
@@ -1205,11 +1200,11 @@ static struct procunit_info procunits[] = {
/*
* build a processing/extension unit
*/
-static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char *dsc, struct procunit_info *list, char *name)
+static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned char *dsc, struct procunit_info *list, char *name)
{
int num_ins = dsc[6];
- usb_mixer_elem_info_t *cval;
- snd_kcontrol_t *kctl;
+ struct usb_mixer_elem_info *cval;
+ struct snd_kcontrol *kctl;
int i, err, nameid, type, len;
struct procunit_info *info;
struct procunit_value_info *valinfo;
@@ -1297,12 +1292,12 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
}
-static int parse_audio_processing_unit(mixer_build_t *state, int unitid, unsigned char *desc)
+static int parse_audio_processing_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
return build_audio_procunit(state, unitid, desc, procunits, "Processing Unit");
}
-static int parse_audio_extension_unit(mixer_build_t *state, int unitid, unsigned char *desc)
+static int parse_audio_extension_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
return build_audio_procunit(state, unitid, desc, NULL, "Extension Unit");
}
@@ -1315,9 +1310,9 @@ static int parse_audio_extension_unit(mixer_build_t *state, int unitid, unsigned
/* info callback for selector unit
* use an enumerator type for routing
*/
-static int mixer_ctl_selector_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
char **itemlist = (char **)kcontrol->private_value;
snd_assert(itemlist, return -EINVAL);
@@ -1331,9 +1326,9 @@ static int mixer_ctl_selector_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
}
/* get callback for selector unit */
-static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, err;
err = get_cur_ctl_value(cval, 0, &val);
@@ -1350,9 +1345,9 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* put callback for selector unit */
-static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- usb_mixer_elem_info_t *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
int val, oval, err;
err = get_cur_ctl_value(cval, 0, &oval);
@@ -1371,7 +1366,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/* alsa control interface for selector unit */
-static snd_kcontrol_new_t mixer_selectunit_ctl = {
+static struct snd_kcontrol_new mixer_selectunit_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later */
.info = mixer_ctl_selector_info,
@@ -1383,12 +1378,12 @@ static snd_kcontrol_new_t mixer_selectunit_ctl = {
/* private free callback.
* free both private_data and private_value
*/
-static void usb_mixer_selector_elem_free(snd_kcontrol_t *kctl)
+static void usb_mixer_selector_elem_free(struct snd_kcontrol *kctl)
{
int i, num_ins = 0;
if (kctl->private_data) {
- usb_mixer_elem_info_t *cval = kctl->private_data;
+ struct usb_mixer_elem_info *cval = kctl->private_data;
num_ins = cval->max;
kfree(cval);
kctl->private_data = NULL;
@@ -1405,13 +1400,13 @@ static void usb_mixer_selector_elem_free(snd_kcontrol_t *kctl)
/*
* parse a selector unit
*/
-static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned char *desc)
+static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsigned char *desc)
{
unsigned int num_ins = desc[4];
unsigned int i, nameid, len;
int err;
- usb_mixer_elem_info_t *cval;
- snd_kcontrol_t *kctl;
+ struct usb_mixer_elem_info *cval;
+ struct snd_kcontrol *kctl;
char **namelist;
if (! num_ins || desc[0] < 6 + num_ins) {
@@ -1452,7 +1447,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
}
#define MAX_ITEM_NAME_LEN 64
for (i = 0; i < num_ins; i++) {
- usb_audio_term_t iterm;
+ struct usb_audio_term iterm;
len = 0;
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
if (! namelist[i]) {
@@ -1511,7 +1506,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
* parse an audio unit recursively
*/
-static int parse_audio_unit(mixer_build_t *state, int unitid)
+static int parse_audio_unit(struct mixer_build *state, int unitid)
{
unsigned char *p1;
@@ -1556,7 +1551,7 @@ static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
kfree(mixer);
}
-static int snd_usb_mixer_dev_free(snd_device_t *device)
+static int snd_usb_mixer_dev_free(struct snd_device *device)
{
struct usb_mixer_interface *mixer = device->device_data;
snd_usb_mixer_free(mixer);
@@ -1571,7 +1566,7 @@ static int snd_usb_mixer_dev_free(snd_device_t *device)
static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
{
unsigned char *desc;
- mixer_build_t state;
+ struct mixer_build state;
int err;
const struct usbmix_ctl_map *map;
struct usb_host_interface *hostif;
@@ -1611,7 +1606,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
int unitid)
{
- usb_mixer_elem_info_t *info;
+ struct usb_mixer_elem_info *info;
for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -1725,7 +1720,7 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb,
wake_up(&mixer->rc_waitq);
}
-static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
+static int snd_usb_sbrc_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
struct usb_mixer_interface *mixer = hw->private_data;
@@ -1734,7 +1729,7 @@ static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
return 0;
}
-static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
+static int snd_usb_sbrc_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
struct usb_mixer_interface *mixer = hw->private_data;
@@ -1743,7 +1738,7 @@ static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
return 0;
}
-static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
+static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
long count, loff_t *offset)
{
struct usb_mixer_interface *mixer = hw->private_data;
@@ -1763,7 +1758,7 @@ static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
return err < 0 ? err : count;
}
-static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
+static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
poll_table *wait)
{
struct usb_mixer_interface *mixer = hw->private_data;
@@ -1774,7 +1769,7 @@ static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
{
- snd_hwdep_t *hwdep;
+ struct snd_hwdep *hwdep;
int err, len;
switch (mixer->chip->usb_id) {
@@ -1825,7 +1820,7 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
return 0;
}
-static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+static int snd_audigy2nx_led_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
@@ -1834,7 +1829,7 @@ static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
return 0;
}
-static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
@@ -1843,7 +1838,7 @@ static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return 0;
}
-static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
int index = kcontrol->private_value;
@@ -1863,7 +1858,7 @@ static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
return changed;
}
-static snd_kcontrol_new_t snd_audigy2nx_controls[] = {
+static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "CMSS LED Switch",
@@ -1904,8 +1899,8 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
-static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
- snd_info_buffer_t *buffer)
+static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
{
static const struct {
int unitid;
@@ -1935,9 +1930,9 @@ static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
}
}
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif)
{
- static snd_device_ops_t dev_ops = {
+ static struct snd_device_ops dev_ops = {
.dev_free = snd_usb_mixer_dev_free
};
struct usb_mixer_interface *mixer;
@@ -1967,7 +1962,7 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
goto _error;
if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) {
- snd_info_entry_t *entry;
+ struct snd_info_entry *entry;
if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
goto _error;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index ba506c3871f4..6190ada00e38 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -45,7 +45,7 @@
#define YAMAHA_DEVICE(id, name) { \
USB_DEVICE(0x0499, id), \
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { \
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
.vendor_name = "Yamaha", \
.product_name = name, \
.ifnum = QUIRK_ANY_INTERFACE, \
@@ -54,7 +54,7 @@
}
#define YAMAHA_INTERFACE(id, intf, name) { \
USB_DEVICE_VENDOR_SPEC(0x0499, id), \
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) { \
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \
.vendor_name = "Yamaha", \
.product_name = name, \
.ifnum = intf, \
@@ -149,12 +149,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
*/
{
USB_DEVICE(0x0582, 0x0000),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "UA-100",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
@@ -192,7 +192,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0007,
.in_cables = 0x0007
}
@@ -205,12 +205,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0002),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-4",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -222,7 +222,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x000f,
.in_cables = 0x000f
}
@@ -235,12 +235,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0003),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "SC-8850",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -252,7 +252,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x003f,
.in_cables = 0x003f
}
@@ -265,12 +265,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0004),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "U-8",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -282,7 +282,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0005,
.in_cables = 0x0005
}
@@ -296,12 +296,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* a later revision uses ID 0x0099 */
USB_DEVICE(0x0582, 0x0005),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-2",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -313,7 +313,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0003
}
@@ -326,12 +326,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0007),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "SC-8820",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -343,7 +343,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0013,
.in_cables = 0x0013
}
@@ -356,12 +356,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0008),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "PC-300",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -373,7 +373,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -387,12 +387,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* a later revision uses ID 0x009d */
USB_DEVICE(0x0582, 0x0009),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-1",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -404,7 +404,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -417,12 +417,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x000b),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "SK-500",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -434,7 +434,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0013,
.in_cables = 0x0013
}
@@ -449,12 +449,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* thanks to Emiliano Grilli <emillo@libero.it>
* for helping researching this data */
USB_DEVICE(0x0582, 0x000c),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "SC-D70",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
@@ -492,7 +492,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0007,
.in_cables = 0x0007
}
@@ -513,12 +513,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* the 96kHz sample rate.
*/
USB_DEVICE(0x0582, 0x0010),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UA-5",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
@@ -536,12 +536,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0013 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0012),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "XV-5050",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -550,12 +550,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0015 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0014),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-880",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x01ff,
.in_cables = 0x01ff
}
@@ -564,12 +564,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0017 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0016),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "SD-90",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -581,7 +581,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x000f,
.in_cables = 0x000f
}
@@ -595,12 +595,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x001c when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x001b),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "MMP-2",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -612,7 +612,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 2,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -626,12 +626,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x001e when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x001d),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "V-SYNTH",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -640,12 +640,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0024 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0023),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-550",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x003f,
.in_cables = 0x003f
}
@@ -658,23 +658,57 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* and no MIDI.
*/
USB_DEVICE(0x0582, 0x0025),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UA-20",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
{
.ifnum = 1,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = & (const struct audioformat) {
+ .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .channels = 2,
+ .iface = 1,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = 0,
+ .endpoint = 0x01,
+ .ep_attr = 0x01,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 44100,
+ .rate_max = 44100,
+ }
},
{
.ifnum = 2,
- .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = & (const struct audioformat) {
+ .format = SNDRV_PCM_FORMAT_S24_3LE,
+ .channels = 2,
+ .iface = 2,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = 0,
+ .endpoint = 0x82,
+ .ep_attr = 0x01,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 44100,
+ .rate_max = 44100,
+ }
},
{
.ifnum = 3,
- .type = QUIRK_MIDI_STANDARD_INTERFACE
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
},
{
.ifnum = -1
@@ -685,12 +719,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0028 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0027),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "SD-20",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0007
}
@@ -699,12 +733,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x002a when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0029),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "SD-80",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x000f,
.in_cables = 0x000f
}
@@ -717,12 +751,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* but offers only 16-bit PCM and no MIDI.
*/
USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UA-700",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 1,
.type = QUIRK_AUDIO_EDIROL_UA700_UA25
@@ -744,12 +778,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x002e when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x002d),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "XV-2020",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -758,12 +792,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0030 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x002f),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "VariOS",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0007,
.in_cables = 0x0007
}
@@ -772,12 +806,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0034 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0033),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "PCR",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0007
}
@@ -790,12 +824,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* later revisions use IDs 0x0054 and 0x00a2.
*/
USB_DEVICE(0x0582, 0x0037),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "Digital Piano",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -808,12 +842,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* and no MIDI.
*/
USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "BOSS",
.product_name = "GS-10",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = & (const snd_usb_audio_quirk_t[]) {
+ .data = & (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
@@ -835,12 +869,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0041 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0040),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "GI-20",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -849,12 +883,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0043 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0042),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "RS-70",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -862,12 +896,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0044),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "UA-1000",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 1,
.type = QUIRK_AUDIO_EDIROL_UA1000
@@ -879,7 +913,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 3,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0003
}
@@ -893,12 +927,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x004a when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0048),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UR-80",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0007
}
@@ -908,12 +942,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x004f when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x004d),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "PCR-A",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0007
}
@@ -925,12 +959,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* is standard compliant, but has only 16-bit PCM.
*/
USB_DEVICE(0x0582, 0x0050),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UA-3FX",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 1,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
@@ -947,7 +981,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x0582, 0x0052),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UM-1SX",
.ifnum = 0,
@@ -958,12 +992,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0067 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0065),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "PCR-1",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0003
}
@@ -972,12 +1006,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x006b when not in "Advanced Driver" mode */
USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "SP-606",
.ifnum = 3,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -986,12 +1020,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x006e when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x006d),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
.product_name = "FANTOM-X",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1004,12 +1038,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* offers only 16-bit PCM at 44.1 kHz and no MIDI.
*/
USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "EDIROL",
.product_name = "UA-25",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = (const snd_usb_audio_quirk_t[]) {
+ .data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_EDIROL_UA700_UA25
@@ -1031,12 +1065,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x0076 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0075),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "BOSS",
.product_name = "DR-880",
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1045,12 +1079,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* has ID 0x007b when not in "Advanced Driver" mode */
USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Roland",
/* "RD" or "RD-700SX"? */
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0003
}
@@ -1066,12 +1100,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* compliant USB MIDI ports for external MIDI and controls.
*/
USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Hercules",
.product_name = "DJ Console (WE)",
.ifnum = 4,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1090,12 +1124,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* Midiman/M-Audio devices */
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 2x2",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0003,
.in_cables = 0x0003
}
@@ -1103,12 +1137,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 1x1",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1116,12 +1150,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "Keystation",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1129,12 +1163,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 4x4",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x000f,
.in_cables = 0x000f
}
@@ -1147,12 +1181,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
* Thanks to Olaf Giesbrecht <Olaf_Giesbrecht@yahoo.de>
*/
USB_DEVICE_VER(0x0763, 0x1031, 0x0100, 0x0109),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 8x8",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x01ff,
.in_cables = 0x01ff
}
@@ -1160,12 +1194,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 8x8",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x01ff,
.in_cables = 0x01ff
}
@@ -1173,12 +1207,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x1041),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "MidiSport 2x4",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x000f,
.in_cables = 0x0003
}
@@ -1186,12 +1220,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "Quattro",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = & (const snd_usb_audio_quirk_t[]) {
+ .data = & (const struct snd_usb_audio_quirk[]) {
/*
* Interfaces 0-2 are "Windows-compatible", 16-bit only,
* and share endpoints with the other interfaces.
@@ -1237,7 +1271,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 9,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1250,12 +1284,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "AudioPhile",
.ifnum = 6,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1263,12 +1297,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "Ozone",
.ifnum = 3,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1276,12 +1310,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0763, 0x200d),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "M-Audio",
.product_name = "OmniStudio",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = & (const snd_usb_audio_quirk_t[]) {
+ .data = & (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
@@ -1321,7 +1355,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
.ifnum = 9,
.type = QUIRK_MIDI_MIDIMAN,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
@@ -1342,12 +1376,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.idVendor = 0x07fd,
.idProduct = 0x0001,
.bDeviceSubClass = 2,
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "MOTU",
.product_name = "Fastlane",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
- .data = & (const snd_usb_audio_quirk_t[]) {
+ .data = & (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_MIDI_RAW
@@ -1366,7 +1400,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
/* Creative Sound Blaster MP3+ */
USB_DEVICE(0x041e, 0x3010),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Creative Labs",
.product_name = "Sound Blaster MP3+",
.ifnum = QUIRK_NO_INTERFACE
@@ -1377,12 +1411,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* Emagic devices */
{
USB_DEVICE(0x086a, 0x0001),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Emagic",
/* .product_name = "Unitor8", */
.ifnum = 2,
.type = QUIRK_MIDI_EMAGIC,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x80ff,
.in_cables = 0x80ff
}
@@ -1390,12 +1424,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x086a, 0x0002),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Emagic",
/* .product_name = "AMT8", */
.ifnum = 2,
.type = QUIRK_MIDI_EMAGIC,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x80ff,
.in_cables = 0x80ff
}
@@ -1403,12 +1437,12 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x086a, 0x0003),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Emagic",
/* .product_name = "MT4", */
.ifnum = 2,
.type = QUIRK_MIDI_EMAGIC,
- .data = & (const snd_usb_midi_endpoint_info_t) {
+ .data = & (const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x800f,
.in_cables = 0x8003
}
@@ -1418,7 +1452,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* TerraTec devices */
{
USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "TerraTec",
.product_name = "PHASE 26",
.ifnum = 3,
@@ -1427,7 +1461,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "TerraTec",
.product_name = "PHASE 26",
.ifnum = 3,
@@ -1438,7 +1472,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
/* Novation EMS devices */
{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Novation",
.product_name = "ReMOTE Audio/XStation",
.ifnum = 4,
@@ -1447,7 +1481,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Novation",
.product_name = "Speedio",
.ifnum = 3,
@@ -1456,7 +1490,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Novation",
.product_name = "ReMOTE25",
.ifnum = 0,
@@ -1466,7 +1500,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
{
USB_DEVICE(0x4752, 0x0011),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Miditech",
.product_name = "Midistart-2",
.ifnum = 0,
@@ -1475,7 +1509,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
},
{
USB_DEVICE(0x7104, 0x2202),
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Miditech",
.product_name = "MidiStudio-2",
.ifnum = 0,
@@ -1492,7 +1526,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
USB_DEVICE_ID_MATCH_INT_SUBCLASS,
.bInterfaceClass = USB_CLASS_AUDIO,
.bInterfaceSubClass = USB_SUBCLASS_MIDI_STREAMING,
- .driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_MIDI_STANDARD_INTERFACE
}
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 8abe08611df6..4b52d18dcd53 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -31,7 +31,7 @@
#include "usbusx2y.h"
#include "usX2Yhwdep.h"
-int usX2Y_hwdep_pcm_new(snd_card_t* card);
+int usX2Y_hwdep_pcm_new(struct snd_card *card);
static struct page * snd_us428ctls_vm_nopage(struct vm_area_struct *area, unsigned long address, int *type)
@@ -49,7 +49,7 @@ static struct page * snd_us428ctls_vm_nopage(struct vm_area_struct *area, unsign
offset = area->vm_pgoff << PAGE_SHIFT;
offset += address - area->vm_start;
snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
- vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->us428ctls_sharedmem + offset;
+ vaddr = (char*)((struct usX2Ydev *)area->vm_private_data)->us428ctls_sharedmem + offset;
page = virt_to_page(vaddr);
get_page(page);
snd_printdd( "vaddr=%p made us428ctls_vm_nopage() return %p; offset=%lX\n", vaddr, page, offset);
@@ -64,27 +64,27 @@ static struct vm_operations_struct us428ctls_vm_ops = {
.nopage = snd_us428ctls_vm_nopage,
};
-static int snd_us428ctls_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_area_struct *area)
+static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area)
{
unsigned long size = (unsigned long)(area->vm_end - area->vm_start);
- usX2Ydev_t *us428 = (usX2Ydev_t*)hw->private_data;
+ struct usX2Ydev *us428 = hw->private_data;
// FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs?
// so as long as the device isn't fully initialised yet we return -EBUSY here.
- if (!(((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT))
+ if (!(us428->chip_status & USX2Y_STAT_CHIP_INIT))
return -EBUSY;
/* if userspace tries to mmap beyond end of our buffer, fail */
- if (size > ((PAGE_SIZE - 1 + sizeof(us428ctls_sharedmem_t)) / PAGE_SIZE) * PAGE_SIZE) {
- snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(us428ctls_sharedmem_t));
+ if (size > PAGE_ALIGN(sizeof(struct us428ctls_sharedmem))) {
+ snd_printd( "%lu > %lu\n", size, (unsigned long)sizeof(struct us428ctls_sharedmem));
return -EINVAL;
}
if (!us428->us428ctls_sharedmem) {
init_waitqueue_head(&us428->us428ctls_wait_queue_head);
- if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(us428ctls_sharedmem_t), GFP_KERNEL)))
+ if(!(us428->us428ctls_sharedmem = snd_malloc_pages(sizeof(struct us428ctls_sharedmem), GFP_KERNEL)))
return -ENOMEM;
- memset(us428->us428ctls_sharedmem, -1, sizeof(us428ctls_sharedmem_t));
+ memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem));
us428->us428ctls_sharedmem->CtlSnapShotLast = -2;
}
area->vm_ops = &us428ctls_vm_ops;
@@ -93,11 +93,11 @@ static int snd_us428ctls_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_are
return 0;
}
-static unsigned int snd_us428ctls_poll(snd_hwdep_t *hw, struct file *file, poll_table *wait)
+static unsigned int snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait)
{
unsigned int mask = 0;
- usX2Ydev_t *us428 = (usX2Ydev_t*)hw->private_data;
- us428ctls_sharedmem_t *shm = us428->us428ctls_sharedmem;
+ struct usX2Ydev *us428 = hw->private_data;
+ struct us428ctls_sharedmem *shm = us428->us428ctls_sharedmem;
if (us428->chip_status & USX2Y_STAT_CHIP_HUP)
return POLLHUP;
@@ -110,26 +110,28 @@ static unsigned int snd_us428ctls_poll(snd_hwdep_t *hw, struct file *file, poll_
}
-static int snd_usX2Y_hwdep_open(snd_hwdep_t *hw, struct file *file)
+static int snd_usX2Y_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int snd_usX2Y_hwdep_release(snd_hwdep_t *hw, struct file *file)
+static int snd_usX2Y_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
return 0;
}
-static int snd_usX2Y_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
+static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_status *info)
{
static char *type_ids[USX2Y_TYPE_NUMS] = {
[USX2Y_TYPE_122] = "us122",
[USX2Y_TYPE_224] = "us224",
[USX2Y_TYPE_428] = "us428",
};
+ struct usX2Ydev *us428 = hw->private_data;
int id = -1;
- switch (le16_to_cpu(((usX2Ydev_t*)hw->private_data)->chip.dev->descriptor.idProduct)) {
+ switch (le16_to_cpu(us428->chip.dev->descriptor.idProduct)) {
case USB_ID_US122:
id = USX2Y_TYPE_122;
break;
@@ -144,35 +146,35 @@ static int snd_usX2Y_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *i
return -ENODEV;
strcpy(info->id, type_ids[id]);
info->num_dsps = 2; // 0: Prepad Data, 1: FPGA Code
- if (((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT)
+ if (us428->chip_status & USX2Y_STAT_CHIP_INIT)
info->chip_ready = 1;
info->version = USX2Y_DRIVER_VERSION;
return 0;
}
-static int usX2Y_create_usbmidi(snd_card_t* card )
+static int usX2Y_create_usbmidi(struct snd_card *card)
{
- static snd_usb_midi_endpoint_info_t quirk_data_1 = {
- .out_ep =0x06,
+ static struct snd_usb_midi_endpoint_info quirk_data_1 = {
+ .out_ep = 0x06,
.in_ep = 0x06,
.out_cables = 0x001,
.in_cables = 0x001
};
- static snd_usb_audio_quirk_t quirk_1 = {
+ static struct snd_usb_audio_quirk quirk_1 = {
.vendor_name = "TASCAM",
.product_name = NAME_ALLCAPS,
.ifnum = 0,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &quirk_data_1
};
- static snd_usb_midi_endpoint_info_t quirk_data_2 = {
- .out_ep =0x06,
+ static struct snd_usb_midi_endpoint_info quirk_data_2 = {
+ .out_ep = 0x06,
.in_ep = 0x06,
.out_cables = 0x003,
.in_cables = 0x003
};
- static snd_usb_audio_quirk_t quirk_2 = {
+ static struct snd_usb_audio_quirk quirk_2 = {
.vendor_name = "TASCAM",
.product_name = "US428",
.ifnum = 0,
@@ -181,13 +183,15 @@ static int usX2Y_create_usbmidi(snd_card_t* card )
};
struct usb_device *dev = usX2Y(card)->chip.dev;
struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
- snd_usb_audio_quirk_t *quirk = le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1;
+ struct snd_usb_audio_quirk *quirk =
+ le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ?
+ &quirk_2 : &quirk_1;
snd_printdd("usX2Y_create_usbmidi \n");
return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk);
}
-static int usX2Y_create_alsa_devices(snd_card_t* card)
+static int usX2Y_create_alsa_devices(struct snd_card *card)
{
int err;
@@ -207,9 +211,10 @@ static int usX2Y_create_alsa_devices(snd_card_t* card)
return err;
}
-static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
+static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw,
+ struct snd_hwdep_dsp_image *dsp)
{
- usX2Ydev_t *priv = hw->private_data;
+ struct usX2Ydev *priv = hw->private_data;
int lret, err = -EINVAL;
snd_printdd( "dsp_load %s\n", dsp->name);
@@ -256,10 +261,10 @@ static int snd_usX2Y_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
}
-int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device)
+int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device)
{
int err;
- snd_hwdep_t *hw;
+ struct snd_hwdep *hw;
if ((err = snd_hwdep_new(card, SND_USX2Y_LOADER_ID, 0, &hw)) < 0)
return err;
diff --git a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h
index d612a26eb77c..c095d5bf1220 100644
--- a/sound/usb/usx2y/usX2Yhwdep.h
+++ b/sound/usb/usx2y/usX2Yhwdep.h
@@ -1,6 +1,6 @@
#ifndef USX2YHWDEP_H
#define USX2YHWDEP_H
-int usX2Y_hwdep_new(snd_card_t* card, struct usb_device* device);
+int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device);
#endif
diff --git a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h
index 6af16438d2c7..b864e7e262e5 100644
--- a/sound/usb/usx2y/usbus428ctldefs.h
+++ b/sound/usb/usx2y/usbus428ctldefs.h
@@ -51,7 +51,7 @@ enum E_In84{
#define T_NULL 0x80
-struct us428_ctls{
+struct us428_ctls {
unsigned char Fader[9];
unsigned char Transport;
unsigned char Modifier;
@@ -63,46 +63,42 @@ struct us428_ctls{
unsigned char Wheel[5];
};
-typedef struct us428_ctls us428_ctls_t;
-
-typedef struct us428_setByte{
+struct us428_setByte {
unsigned char Offset,
Value;
-}us428_setByte_t;
+};
enum {
eLT_Volume = 0,
eLT_Light
};
-typedef struct usX2Y_volume {
+struct usX2Y_volume {
unsigned char Channel,
LH,
LL,
RH,
RL;
-} usX2Y_volume_t;
+};
-struct us428_lights{
- us428_setByte_t Light[7];
+struct us428_lights {
+ struct us428_setByte Light[7];
};
-typedef struct us428_lights us428_lights_t;
-typedef struct {
+struct us428_p4out {
char type;
union {
- usX2Y_volume_t vol;
- us428_lights_t lights;
+ struct usX2Y_volume vol;
+ struct us428_lights lights;
} val;
-} us428_p4out_t;
+};
#define N_us428_ctl_BUFS 16
#define N_us428_p4out_BUFS 16
struct us428ctls_sharedmem{
- us428_ctls_t CtlSnapShot[N_us428_ctl_BUFS];
- int CtlSnapShotDiffersAt[N_us428_ctl_BUFS];
- int CtlSnapShotLast, CtlSnapShotRed;
- us428_p4out_t p4out[N_us428_p4out_BUFS];
- int p4outLast, p4outSent;
+ struct us428_ctls CtlSnapShot[N_us428_ctl_BUFS];
+ int CtlSnapShotDiffersAt[N_us428_ctl_BUFS];
+ int CtlSnapShotLast, CtlSnapShotRed;
+ struct us428_p4out p4out[N_us428_p4out_BUFS];
+ int p4outLast, p4outSent;
};
-typedef struct us428ctls_sharedmem us428ctls_sharedmem_t;
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cf77313c609d..e0abb56bbe49 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -167,28 +167,28 @@ MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
static int snd_usX2Y_card_used[SNDRV_CARDS];
static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr);
-static void snd_usX2Y_card_private_free(snd_card_t *card);
+static void snd_usX2Y_card_private_free(struct snd_card *card);
/*
* pipe 4 is used for switching the lamps, setting samplerate, volumes ....
*/
-static void i_usX2Y_Out04Int(struct urb* urb, struct pt_regs *regs)
+static void i_usX2Y_Out04Int(struct urb *urb, struct pt_regs *regs)
{
#ifdef CONFIG_SND_DEBUG
if (urb->status) {
int i;
- usX2Ydev_t* usX2Y = urb->context;
+ struct usX2Ydev *usX2Y = urb->context;
for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++);
snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status);
}
#endif
}
-static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs)
+static void i_usX2Y_In04Int(struct urb *urb, struct pt_regs *regs)
{
int err = 0;
- usX2Ydev_t *usX2Y = urb->context;
- us428ctls_sharedmem_t *us428ctls = usX2Y->us428ctls_sharedmem;
+ struct usX2Ydev *usX2Y = urb->context;
+ struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem;
usX2Y->In04IntCalls++;
@@ -239,10 +239,10 @@ static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs)
send = 0;
for (j = 0; j < URBS_AsyncSeq && !err; ++j)
if (0 == usX2Y->AS04.urb[j]->status) {
- us428_p4out_t *p4out = us428ctls->p4out + send; // FIXME if more then 1 p4out is new, 1 gets lost.
+ struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more then 1 p4out is new, 1 gets lost.
usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol,
- p4out->type == eLT_Light ? sizeof(us428_lights_t) : 5,
+ p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5,
i_usX2Y_Out04Int, usX2Y);
err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
us428ctls->p4outSent = send;
@@ -261,7 +261,7 @@ static void i_usX2Y_In04Int(struct urb* urb, struct pt_regs *regs)
/*
* Prepare some urbs
*/
-int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y)
+int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
{
int err = 0,
i;
@@ -283,9 +283,8 @@ int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y)
return err;
}
-int usX2Y_In04_init(usX2Ydev_t* usX2Y)
+int usX2Y_In04_init(struct usX2Ydev *usX2Y)
{
- int err = 0;
if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
return -ENOMEM;
@@ -299,11 +298,10 @@ int usX2Y_In04_init(usX2Ydev_t* usX2Y)
usX2Y->In04Buf, 21,
i_usX2Y_In04Int, usX2Y,
10);
- err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
- return err;
+ return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
}
-static void usX2Y_unlinkSeq(snd_usX2Y_AsyncSeq_t* S)
+static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S)
{
int i;
for (i = 0; i < URBS_AsyncSeq; ++i) {
@@ -336,16 +334,16 @@ static struct usb_device_id snd_usX2Y_usb_id_table[] = {
{ /* terminator */ }
};
-static snd_card_t* usX2Y_create_card(struct usb_device* device)
+static struct snd_card *usX2Y_create_card(struct usb_device *device)
{
int dev;
- snd_card_t* card;
+ struct snd_card * card;
for (dev = 0; dev < SNDRV_CARDS; ++dev)
if (enable[dev] && !snd_usX2Y_card_used[dev])
break;
if (dev >= SNDRV_CARDS)
return NULL;
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(usX2Ydev_t));
+ card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev));
if (!card)
return NULL;
snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
@@ -369,10 +367,10 @@ static snd_card_t* usX2Y_create_card(struct usb_device* device)
}
-static void* usX2Y_usb_probe(struct usb_device* device, struct usb_interface *intf, const struct usb_device_id* device_id)
+static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id)
{
int err;
- snd_card_t* card;
+ struct snd_card * card;
if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
(le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
@@ -409,14 +407,13 @@ static void snd_usX2Y_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
static struct usb_driver snd_usX2Y_usb_driver = {
- .owner = THIS_MODULE,
.name = "snd-usb-usx2y",
.probe = snd_usX2Y_probe,
.disconnect = snd_usX2Y_disconnect,
.id_table = snd_usX2Y_usb_id_table,
};
-static void snd_usX2Y_card_private_free(snd_card_t *card)
+static void snd_usX2Y_card_private_free(struct snd_card *card)
{
kfree(usX2Y(card)->In04Buf);
usb_free_urb(usX2Y(card)->In04urb);
@@ -429,23 +426,24 @@ static void snd_usX2Y_card_private_free(snd_card_t *card)
/*
* Frees the device.
*/
-static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
+static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
{
if (ptr) {
- usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr);
- struct list_head* p;
+ struct snd_card *card = ptr;
+ struct usX2Ydev *usX2Y = usX2Y(card);
+ struct list_head *p;
usX2Y->chip.shutdown = 1;
usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
usX2Y_unlinkSeq(&usX2Y->AS04);
usb_kill_urb(usX2Y->In04urb);
- snd_card_disconnect((snd_card_t*)ptr);
+ snd_card_disconnect(card);
/* release the midi resources */
list_for_each(p, &usX2Y->chip.midi_list) {
snd_usbmidi_disconnect(p);
}
if (usX2Y->us428ctls_sharedmem)
wake_up(&usX2Y->us428ctls_wait_queue_head);
- snd_card_free((snd_card_t*)ptr);
+ snd_card_free(card);
}
}
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
index f65f3a7194ca..435c1feda9df 100644
--- a/sound/usb/usx2y/usbusx2y.h
+++ b/sound/usb/usx2y/usbusx2y.h
@@ -8,47 +8,46 @@
#define URBS_AsyncSeq 10
#define URB_DataLen_AsyncSeq 32
-typedef struct {
- struct urb* urb[URBS_AsyncSeq];
- char* buffer;
-} snd_usX2Y_AsyncSeq_t;
+struct snd_usX2Y_AsyncSeq {
+ struct urb *urb[URBS_AsyncSeq];
+ char *buffer;
+};
-typedef struct {
+struct snd_usX2Y_urbSeq {
int submitted;
int len;
- struct urb* urb[0];
-} snd_usX2Y_urbSeq_t;
+ struct urb *urb[0];
+};
-typedef struct snd_usX2Y_substream snd_usX2Y_substream_t;
#include "usx2yhwdeppcm.h"
-typedef struct {
- snd_usb_audio_t chip;
+struct usX2Ydev {
+ struct snd_usb_audio chip;
int stride;
struct urb *In04urb;
void *In04Buf;
char In04Last[24];
unsigned In04IntCalls;
- snd_usX2Y_urbSeq_t *US04;
+ struct snd_usX2Y_urbSeq *US04;
wait_queue_head_t In04WaitQueue;
- snd_usX2Y_AsyncSeq_t AS04;
+ struct snd_usX2Y_AsyncSeq AS04;
unsigned int rate,
format;
int chip_status;
struct semaphore prepare_mutex;
- us428ctls_sharedmem_t *us428ctls_sharedmem;
+ struct us428ctls_sharedmem *us428ctls_sharedmem;
int wait_iso_frame;
wait_queue_head_t us428ctls_wait_queue_head;
- snd_usX2Y_hwdep_pcm_shm_t *hwdep_pcm_shm;
- snd_usX2Y_substream_t *subs[4];
- snd_usX2Y_substream_t * volatile prepare_subs;
+ struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm;
+ struct snd_usX2Y_substream *subs[4];
+ struct snd_usX2Y_substream * volatile prepare_subs;
wait_queue_head_t prepare_wait_queue;
-} usX2Ydev_t;
+};
struct snd_usX2Y_substream {
- usX2Ydev_t *usX2Y;
- snd_pcm_substream_t *pcm_substream;
+ struct usX2Ydev *usX2Y;
+ struct snd_pcm_substream *pcm_substream;
int endpoint;
unsigned int maxpacksize; /* max packet size in bytes */
@@ -72,12 +71,12 @@ struct snd_usX2Y_substream {
};
-#define usX2Y(c) ((usX2Ydev_t*)(c)->private_data)
+#define usX2Y(c) ((struct usX2Ydev *)(c)->private_data)
-int usX2Y_audio_create(snd_card_t* card);
+int usX2Y_audio_create(struct snd_card *card);
-int usX2Y_AsyncSeq04_init(usX2Ydev_t* usX2Y);
-int usX2Y_In04_init(usX2Ydev_t* usX2Y);
+int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y);
+int usX2Y_In04_init(struct usX2Ydev *usX2Y);
#define NAME_ALLCAPS "US-X2Y"
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index affda973cece..a6bbc7a6348f 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -67,18 +67,20 @@
#endif
-static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
+static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs)
{
struct urb *urb = subs->completed_urb;
- snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
unsigned char *cp;
int i, len, lens = 0, hwptr_done = subs->hwptr_done;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
for (i = 0; i < nr_of_packs(); i++) {
cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
- snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status);
+ snd_printk(KERN_ERR "active frame status %i. "
+ "Most propably some hardware problem.\n",
+ urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status;
}
len = urb->iso_frame_desc[i].actual_length / usX2Y->stride;
@@ -94,7 +96,8 @@ static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen);
memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen);
} else {
- memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, len * usX2Y->stride);
+ memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp,
+ len * usX2Y->stride);
}
lens += len;
if ((hwptr_done += len) >= runtime->buffer_size)
@@ -120,13 +123,13 @@ static int usX2Y_urb_capt_retire(snd_usX2Y_substream_t *subs)
* it directly from the buffer. thus the data is once copied to
* a temporary buffer and urb points to that.
*/
-static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
+static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs,
struct urb *cap_urb,
struct urb *urb)
{
int count, counts, pack;
- usX2Ydev_t* usX2Y = subs->usX2Y;
- snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
count = 0;
for (pack = 0; pack < nr_of_packs(); pack++) {
@@ -139,7 +142,8 @@ static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
}
/* set up descriptor */
urb->iso_frame_desc[pack].offset = pack ?
- urb->iso_frame_desc[pack - 1].offset + urb->iso_frame_desc[pack - 1].length :
+ urb->iso_frame_desc[pack - 1].offset +
+ urb->iso_frame_desc[pack - 1].length :
0;
urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length;
}
@@ -151,8 +155,10 @@ static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
int len;
len = runtime->buffer_size - subs->hwptr;
urb->transfer_buffer = subs->tmpbuf;
- memcpy(subs->tmpbuf, runtime->dma_area + subs->hwptr * usX2Y->stride, len * usX2Y->stride);
- memcpy(subs->tmpbuf + len * usX2Y->stride, runtime->dma_area, (count - len) * usX2Y->stride);
+ memcpy(subs->tmpbuf, runtime->dma_area +
+ subs->hwptr * usX2Y->stride, len * usX2Y->stride);
+ memcpy(subs->tmpbuf + len * usX2Y->stride,
+ runtime->dma_area, (count - len) * usX2Y->stride);
subs->hwptr += count;
subs->hwptr -= runtime->buffer_size;
} else {
@@ -172,9 +178,9 @@ static int usX2Y_urb_play_prepare(snd_usX2Y_substream_t *subs,
*
* update the current position and call callback if a period is processed.
*/
-static void usX2Y_urb_play_retire(snd_usX2Y_substream_t *subs, struct urb *urb)
+static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb *urb)
{
- snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
int len = urb->actual_length / subs->usX2Y->stride;
subs->transfer_done += len;
@@ -187,7 +193,7 @@ static void usX2Y_urb_play_retire(snd_usX2Y_substream_t *subs, struct urb *urb)
}
}
-static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int frame)
+static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, int frame)
{
int err;
if (!urb)
@@ -202,50 +208,47 @@ static int usX2Y_urb_submit(snd_usX2Y_substream_t *subs, struct urb *urb, int fr
return 0;
}
-static inline int usX2Y_usbframe_complete(snd_usX2Y_substream_t *capsubs, snd_usX2Y_substream_t *playbacksubs, int frame)
+static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs,
+ struct snd_usX2Y_substream *playbacksubs,
+ int frame)
{
int err, state;
- {
- struct urb *urb = playbacksubs->completed_urb;
-
- state = atomic_read(&playbacksubs->state);
- if (NULL != urb) {
- if (state == state_RUNNING)
- usX2Y_urb_play_retire(playbacksubs, urb);
- else
- if (state >= state_PRERUNNING) {
- atomic_inc(&playbacksubs->state);
- }
- } else {
- switch (state) {
- case state_STARTING1:
- urb = playbacksubs->urb[0];
- atomic_inc(&playbacksubs->state);
- break;
- case state_STARTING2:
- urb = playbacksubs->urb[1];
- atomic_inc(&playbacksubs->state);
- break;
- }
+ struct urb *urb = playbacksubs->completed_urb;
+
+ state = atomic_read(&playbacksubs->state);
+ if (NULL != urb) {
+ if (state == state_RUNNING)
+ usX2Y_urb_play_retire(playbacksubs, urb);
+ else if (state >= state_PRERUNNING)
+ atomic_inc(&playbacksubs->state);
+ } else {
+ switch (state) {
+ case state_STARTING1:
+ urb = playbacksubs->urb[0];
+ atomic_inc(&playbacksubs->state);
+ break;
+ case state_STARTING2:
+ urb = playbacksubs->urb[1];
+ atomic_inc(&playbacksubs->state);
+ break;
}
- if (urb) {
- if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) ||
- (err = usX2Y_urb_submit(playbacksubs, urb, frame))) {
- return err;
- }
+ }
+ if (urb) {
+ if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) ||
+ (err = usX2Y_urb_submit(playbacksubs, urb, frame))) {
+ return err;
}
-
- playbacksubs->completed_urb = NULL;
}
+
+ playbacksubs->completed_urb = NULL;
+
state = atomic_read(&capsubs->state);
if (state >= state_PREPARED) {
if (state == state_RUNNING) {
if ((err = usX2Y_urb_capt_retire(capsubs)))
return err;
- } else
- if (state >= state_PRERUNNING) {
- atomic_inc(&capsubs->state);
- }
+ } else if (state >= state_PRERUNNING)
+ atomic_inc(&capsubs->state);
if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame)))
return err;
}
@@ -254,18 +257,19 @@ static inline int usX2Y_usbframe_complete(snd_usX2Y_substream_t *capsubs, snd_us
}
-static void usX2Y_clients_stop(usX2Ydev_t *usX2Y)
+static void usX2Y_clients_stop(struct usX2Ydev *usX2Y)
{
int s, u;
+
for (s = 0; s < 4; s++) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[s];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[s];
if (subs) {
snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state));
atomic_set(&subs->state, state_STOPPED);
}
}
for (s = 0; s < 4; s++) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[s];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[s];
if (subs) {
if (atomic_read(&subs->state) >= state_PRERUNNING) {
snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
@@ -273,7 +277,8 @@ static void usX2Y_clients_stop(usX2Ydev_t *usX2Y)
for (u = 0; u < NRURBS; u++) {
struct urb *urb = subs->urb[u];
if (NULL != urb)
- snd_printdd("%i status=%i start_frame=%i\n", u, urb->status, urb->start_frame);
+ snd_printdd("%i status=%i start_frame=%i\n",
+ u, urb->status, urb->start_frame);
}
}
}
@@ -281,30 +286,36 @@ static void usX2Y_clients_stop(usX2Ydev_t *usX2Y)
wake_up(&usX2Y->prepare_wait_queue);
}
-static void usX2Y_error_urb_status(usX2Ydev_t *usX2Y, snd_usX2Y_substream_t *subs, struct urb *urb)
+static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y,
+ struct snd_usX2Y_substream *subs, struct urb *urb)
{
snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status);
urb->status = 0;
usX2Y_clients_stop(usX2Y);
}
-static void usX2Y_error_sequence(usX2Ydev_t *usX2Y, snd_usX2Y_substream_t *subs, struct urb *urb)
+static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
+ struct snd_usX2Y_substream *subs, struct urb *urb)
{
snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
KERN_ERR "Most propably some urb of usb-frame %i is still missing.\n"
KERN_ERR "Cause could be too long delays in usb-hcd interrupt handling.\n",
usb_get_current_frame_number(usX2Y->chip.dev),
- subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
+ subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
+ usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
usX2Y_clients_stop(usX2Y);
}
static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *subs = urb->context;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
- snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", usb_get_current_frame_number(usX2Y->chip.dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame);
+ snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
+ usb_get_current_frame_number(usX2Y->chip.dev),
+ subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
+ urb->status, urb->start_frame);
return;
}
if (unlikely(urb->status)) {
@@ -318,10 +329,12 @@ static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
return;
}
{
- snd_usX2Y_substream_t *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE],
+ struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE],
*playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
- if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
- (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
+ if (capsubs->completed_urb &&
+ atomic_read(&capsubs->state) >= state_PREPARED &&
+ (playbacksubs->completed_urb ||
+ atomic_read(&playbacksubs->state) < state_PREPARED)) {
if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) {
if (nr_of_packs() <= urb->start_frame &&
urb->start_frame <= (2 * nr_of_packs() - 1)) // uhci and ohci
@@ -336,11 +349,12 @@ static void i_usX2Y_urb_complete(struct urb *urb, struct pt_regs *regs)
}
}
-static void usX2Y_urbs_set_complete(usX2Ydev_t * usX2Y, void (*complete)(struct urb *, struct pt_regs *))
+static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y,
+ void (*complete)(struct urb *, struct pt_regs *))
{
int s, u;
for (s = 0; s < 4; s++) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[s];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[s];
if (NULL != subs)
for (u = 0; u < NRURBS; u++) {
struct urb * urb = subs->urb[u];
@@ -350,7 +364,7 @@ static void usX2Y_urbs_set_complete(usX2Ydev_t * usX2Y, void (*complete)(struct
}
}
-static void usX2Y_subs_startup_finish(usX2Ydev_t * usX2Y)
+static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y)
{
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_urb_complete);
usX2Y->prepare_subs = NULL;
@@ -358,9 +372,9 @@ static void usX2Y_subs_startup_finish(usX2Ydev_t * usX2Y)
static void i_usX2Y_subs_startup(struct urb *urb, struct pt_regs *regs)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
- usX2Ydev_t *usX2Y = subs->usX2Y;
- snd_usX2Y_substream_t *prepare_subs = usX2Y->prepare_subs;
+ struct snd_usX2Y_substream *subs = urb->context;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs;
if (NULL != prepare_subs)
if (urb->start_frame == prepare_subs->urb[0]->start_frame) {
usX2Y_subs_startup_finish(usX2Y);
@@ -371,9 +385,10 @@ static void i_usX2Y_subs_startup(struct urb *urb, struct pt_regs *regs)
i_usX2Y_urb_complete(urb, regs);
}
-static void usX2Y_subs_prepare(snd_usX2Y_substream_t *subs)
+static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs)
{
- snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", subs, subs->endpoint, subs->urb[0], subs->urb[1]);
+ snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n",
+ subs, subs->endpoint, subs->urb[0], subs->urb[1]);
/* reset the pointer */
subs->hwptr = 0;
subs->hwptr_done = 0;
@@ -381,7 +396,7 @@ static void usX2Y_subs_prepare(snd_usX2Y_substream_t *subs)
}
-static void usX2Y_urb_release(struct urb** urb, int free_tb)
+static void usX2Y_urb_release(struct urb **urb, int free_tb)
{
if (*urb) {
usb_kill_urb(*urb);
@@ -394,12 +409,13 @@ static void usX2Y_urb_release(struct urb** urb, int free_tb)
/*
* release a substreams urbs
*/
-static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
+static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs)
{
int i;
snd_printdd("usX2Y_urbs_release() %i\n", subs->endpoint);
for (i = 0; i < NRURBS; i++)
- usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
+ usX2Y_urb_release(subs->urb + i,
+ subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
kfree(subs->tmpbuf);
subs->tmpbuf = NULL;
@@ -407,7 +423,7 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
/*
* initialize a substream's urbs
*/
-static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
+static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs)
{
int i;
unsigned int pipe;
@@ -429,7 +445,7 @@ static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
}
/* allocate and initialize data urbs */
for (i = 0; i < NRURBS; i++) {
- struct urb** purb = subs->urb + i;
+ struct urb **purb = subs->urb + i;
if (*purb) {
usb_kill_urb(*purb);
continue;
@@ -457,70 +473,68 @@ static int usX2Y_urbs_allocate(snd_usX2Y_substream_t *subs)
return 0;
}
-static void usX2Y_subs_startup(snd_usX2Y_substream_t *subs)
+static void usX2Y_subs_startup(struct snd_usX2Y_substream *subs)
{
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
usX2Y->prepare_subs = subs;
subs->urb[0]->start_frame = -1;
wmb();
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_subs_startup);
}
-static int usX2Y_urbs_start(snd_usX2Y_substream_t *subs)
+static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
{
int i, err;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
if ((err = usX2Y_urbs_allocate(subs)) < 0)
return err;
subs->completed_urb = NULL;
for (i = 0; i < 4; i++) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[i];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[i];
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
goto start;
}
usX2Y->wait_iso_frame = -1;
+
start:
- {
- usX2Y_subs_startup(subs);
- for (i = 0; i < NRURBS; i++) {
- struct urb *urb = subs->urb[i];
- if (usb_pipein(urb->pipe)) {
- unsigned long pack;
- if (0 == i)
- atomic_set(&subs->state, state_STARTING3);
- urb->dev = usX2Y->chip.dev;
- urb->transfer_flags = URB_ISO_ASAP;
- for (pack = 0; pack < nr_of_packs(); pack++) {
- urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
- urb->iso_frame_desc[pack].length = subs->maxpacksize;
- }
- urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs();
- if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
- err = -EPIPE;
- goto cleanup;
- } else {
- if (0 > usX2Y->wait_iso_frame)
- usX2Y->wait_iso_frame = urb->start_frame;
- }
- urb->transfer_flags = 0;
+ usX2Y_subs_startup(subs);
+ for (i = 0; i < NRURBS; i++) {
+ struct urb *urb = subs->urb[i];
+ if (usb_pipein(urb->pipe)) {
+ unsigned long pack;
+ if (0 == i)
+ atomic_set(&subs->state, state_STARTING3);
+ urb->dev = usX2Y->chip.dev;
+ urb->transfer_flags = URB_ISO_ASAP;
+ for (pack = 0; pack < nr_of_packs(); pack++) {
+ urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
+ urb->iso_frame_desc[pack].length = subs->maxpacksize;
+ }
+ urb->transfer_buffer_length = subs->maxpacksize * nr_of_packs();
+ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ snd_printk (KERN_ERR "cannot submit datapipe for urb %d, err = %d\n", i, err);
+ err = -EPIPE;
+ goto cleanup;
} else {
- atomic_set(&subs->state, state_STARTING1);
- break;
+ if (0 > usX2Y->wait_iso_frame)
+ usX2Y->wait_iso_frame = urb->start_frame;
}
+ urb->transfer_flags = 0;
+ } else {
+ atomic_set(&subs->state, state_STARTING1);
+ break;
}
- err = 0;
- wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs);
- if (atomic_read(&subs->state) != state_PREPARED) {
- err = -EPIPE;
- }
-
- cleanup:
- if (err) {
- usX2Y_subs_startup_finish(usX2Y);
- usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything
- }
+ }
+ err = 0;
+ wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs);
+ if (atomic_read(&subs->state) != state_PREPARED)
+ err = -EPIPE;
+
+ cleanup:
+ if (err) {
+ usX2Y_subs_startup_finish(usX2Y);
+ usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything
}
return err;
}
@@ -528,17 +542,17 @@ static int usX2Y_urbs_start(snd_usX2Y_substream_t *subs)
/*
* return the current pcm pointer. just return the hwptr_done value.
*/
-static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(struct snd_pcm_substream *substream)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+ struct snd_usX2Y_substream *subs = substream->runtime->private_data;
return subs->hwptr_done;
}
/*
* start/stop substream
*/
-static int snd_usX2Y_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)substream->runtime->private_data;
+ struct snd_usX2Y_substream *subs = substream->runtime->private_data;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -649,9 +663,9 @@ static struct s_c2 SetRate48000[] =
};
#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000)
-static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs)
+static void i_usX2Y_04Int(struct urb *urb, struct pt_regs *regs)
{
- usX2Ydev_t* usX2Y = urb->context;
+ struct usX2Ydev *usX2Y = urb->context;
if (urb->status)
snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status);
@@ -659,21 +673,20 @@ static void i_usX2Y_04Int(struct urb* urb, struct pt_regs *regs)
wake_up(&usX2Y->In04WaitQueue);
}
-static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
+static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
{
int err = 0, i;
- snd_usX2Y_urbSeq_t *us = NULL;
+ struct snd_usX2Y_urbSeq *us = NULL;
int *usbdata = NULL;
struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100;
if (usX2Y->rate != rate) {
- us = kmalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
+ us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
if (NULL == us) {
err = -ENOMEM;
goto cleanup;
}
- memset(us, 0, sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS);
- usbdata = kmalloc(sizeof(int)*NOOF_SETRATE_URBS, GFP_KERNEL);
+ usbdata = kmalloc(sizeof(int) * NOOF_SETRATE_URBS, GFP_KERNEL);
if (NULL == usbdata) {
err = -ENOMEM;
goto cleanup;
@@ -713,9 +726,8 @@ static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
usX2Y->US04 = NULL;
kfree(usbdata);
kfree(us);
- if (!err) {
+ if (!err)
usX2Y->rate = rate;
- }
}
}
@@ -723,7 +735,7 @@ static int usX2Y_rate_set(usX2Ydev_t *usX2Y, int rate)
}
-static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
+static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format)
{
int alternate, err;
struct list_head* p;
@@ -753,40 +765,40 @@ static int usX2Y_format_set(usX2Ydev_t *usX2Y, snd_pcm_format_t format)
}
-static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *hw_params)
+static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
{
int err = 0;
unsigned int rate = params_rate(hw_params);
snd_pcm_format_t format = params_format(hw_params);
- snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
+ struct snd_card *card = substream->pstr->pcm->card;
+ struct list_head *list;
- { // all pcm substreams off one usX2Y have to operate at the same rate & format
- snd_card_t *card = substream->pstr->pcm->card;
- struct list_head *list;
- list_for_each(list, &card->devices) {
- snd_device_t *dev;
- snd_pcm_t *pcm;
- int s;
- dev = snd_device(list);
- if (dev->type != SNDRV_DEV_PCM)
- continue;
- pcm = dev->device_data;
- for (s = 0; s < 2; ++s) {
- snd_pcm_substream_t *test_substream;
- test_substream = pcm->streams[s].substream;
- if (test_substream && test_substream != substream &&
- test_substream->runtime &&
- ((test_substream->runtime->format &&
- test_substream->runtime->format != format) ||
- (test_substream->runtime->rate &&
- test_substream->runtime->rate != rate)))
- return -EINVAL;
- }
+ snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params);
+ // all pcm substreams off one usX2Y have to operate at the same rate & format
+ list_for_each(list, &card->devices) {
+ struct snd_device *dev;
+ struct snd_pcm *pcm;
+ int s;
+ dev = snd_device(list);
+ if (dev->type != SNDRV_DEV_PCM)
+ continue;
+ pcm = dev->device_data;
+ for (s = 0; s < 2; ++s) {
+ struct snd_pcm_substream *test_substream;
+ test_substream = pcm->streams[s].substream;
+ if (test_substream && test_substream != substream &&
+ test_substream->runtime &&
+ ((test_substream->runtime->format &&
+ test_substream->runtime->format != format) ||
+ (test_substream->runtime->rate &&
+ test_substream->runtime->rate != rate)))
+ return -EINVAL;
}
}
if (0 > (err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)))) {
- snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n", substream, params_buffer_bytes(hw_params), err);
+ snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n",
+ substream, params_buffer_bytes(hw_params), err);
return err;
}
return 0;
@@ -795,15 +807,15 @@ static int snd_usX2Y_pcm_hw_params(snd_pcm_substream_t *substream,
/*
* free the buffer
*/
-static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
+static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data;
down(&subs->usX2Y->prepare_mutex);
snd_printdd("snd_usX2Y_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
- snd_usX2Y_substream_t *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
+ struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
atomic_set(&subs->state, state_STOPPED);
usX2Y_urbs_release(subs);
if (!cap_subs->pcm_substream ||
@@ -814,7 +826,7 @@ static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
usX2Y_urbs_release(cap_subs);
}
} else {
- snd_usX2Y_substream_t *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
+ struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
if (atomic_read(&playback_subs->state) < state_PREPARED) {
atomic_set(&subs->state, state_STOPPED);
usX2Y_urbs_release(subs);
@@ -828,12 +840,12 @@ static int snd_usX2Y_pcm_hw_free(snd_pcm_substream_t *substream)
*
* set format and initialize urbs
*/
-static int snd_usX2Y_pcm_prepare(snd_pcm_substream_t *substream)
+static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
- usX2Ydev_t *usX2Y = subs->usX2Y;
- snd_usX2Y_substream_t *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
int err = 0;
snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
@@ -861,7 +873,7 @@ static int snd_usX2Y_pcm_prepare(snd_pcm_substream_t *substream)
return err;
}
-static snd_pcm_hardware_t snd_usX2Y_2c =
+static struct snd_pcm_hardware snd_usX2Y_2c =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -882,11 +894,11 @@ static snd_pcm_hardware_t snd_usX2Y_2c =
-static int snd_usX2Y_pcm_open(snd_pcm_substream_t *substream)
+static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream)
{
- snd_usX2Y_substream_t *subs = ((snd_usX2Y_substream_t **)
+ struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **)
snd_pcm_substream_chip(substream))[substream->stream];
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)
return -EBUSY;
@@ -900,19 +912,18 @@ static int snd_usX2Y_pcm_open(snd_pcm_substream_t *substream)
-static int snd_usX2Y_pcm_close(snd_pcm_substream_t *substream)
+static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
- int err = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data;
subs->pcm_substream = NULL;
- return err;
+ return 0;
}
-static snd_pcm_ops_t snd_usX2Y_pcm_ops =
+static struct snd_pcm_ops snd_usX2Y_pcm_ops =
{
.open = snd_usX2Y_pcm_open,
.close = snd_usX2Y_pcm_close,
@@ -928,7 +939,7 @@ static snd_pcm_ops_t snd_usX2Y_pcm_ops =
/*
* free a usb stream instance
*/
-static void usX2Y_audio_stream_free(snd_usX2Y_substream_t **usX2Y_substream)
+static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream)
{
if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) {
kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]);
@@ -938,25 +949,23 @@ static void usX2Y_audio_stream_free(snd_usX2Y_substream_t **usX2Y_substream)
usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL;
}
-static void snd_usX2Y_pcm_private_free(snd_pcm_t *pcm)
+static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm)
{
- snd_usX2Y_substream_t **usX2Y_stream = pcm->private_data;
- if (usX2Y_stream) {
- snd_pcm_lib_preallocate_free_for_all(pcm);
+ struct snd_usX2Y_substream **usX2Y_stream = pcm->private_data;
+ if (usX2Y_stream)
usX2Y_audio_stream_free(usX2Y_stream);
- }
}
-static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int capture_endpoint)
+static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint)
{
- snd_pcm_t *pcm;
+ struct snd_pcm *pcm;
int err, i;
- snd_usX2Y_substream_t **usX2Y_substream =
+ struct snd_usX2Y_substream **usX2Y_substream =
usX2Y(card)->subs + 2 * usX2Y(card)->chip.pcm_devs;
for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
- usX2Y_substream[i] = kzalloc(sizeof(snd_usX2Y_substream_t), GFP_KERNEL);
+ usX2Y_substream[i] = kzalloc(sizeof(struct snd_usX2Y_substream), GFP_KERNEL);
if (NULL == usX2Y_substream[i]) {
snd_printk(KERN_ERR "cannot malloc\n");
return -ENOMEM;
@@ -1006,7 +1015,7 @@ static int usX2Y_audio_stream_new(snd_card_t *card, int playback_endpoint, int c
/*
* create a chip instance and set its names.
*/
-int usX2Y_audio_create(snd_card_t* card)
+int usX2Y_audio_create(struct snd_card *card)
{
int err = 0;
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index c9136a98755f..796a7dcef09d 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -58,12 +58,12 @@
#include <sound/hwdep.h>
-static int usX2Y_usbpcm_urb_capt_retire(snd_usX2Y_substream_t *subs)
+static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
{
struct urb *urb = subs->completed_urb;
- snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
int i, lens = 0, hwptr_done = subs->hwptr_done;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME
int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1;
if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso))
@@ -90,7 +90,8 @@ static int usX2Y_usbpcm_urb_capt_retire(snd_usX2Y_substream_t *subs)
return 0;
}
-static inline int usX2Y_iso_frames_per_buffer(snd_pcm_runtime_t *runtime, usX2Ydev_t * usX2Y)
+static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime,
+ struct usX2Ydev * usX2Y)
{
return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ?
}
@@ -105,13 +106,13 @@ static inline int usX2Y_iso_frames_per_buffer(snd_pcm_runtime_t *runtime, usX2Yd
* it directly from the buffer. thus the data is once copied to
* a temporary buffer and urb points to that.
*/
-static int usX2Y_hwdep_urb_play_prepare(snd_usX2Y_substream_t *subs,
- struct urb *urb)
+static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs,
+ struct urb *urb)
{
int count, counts, pack;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm;
- snd_pcm_runtime_t *runtime = subs->pcm_substream->runtime;
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
if (0 > shm->playback_iso_start) {
shm->playback_iso_start = shm->captured_iso_head -
@@ -144,13 +145,14 @@ static int usX2Y_hwdep_urb_play_prepare(snd_usX2Y_substream_t *subs,
}
-static inline void usX2Y_usbpcm_urb_capt_iso_advance(snd_usX2Y_substream_t *subs, struct urb *urb)
+static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs,
+ struct urb *urb)
{
int pack;
for (pack = 0; pack < nr_of_packs(); ++pack) {
struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack;
if (NULL != subs) {
- snd_usX2Y_hwdep_pcm_shm_t *shm = subs->usX2Y->hwdep_pcm_shm;
+ struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm;
int head = shm->captured_iso_head + 1;
if (head >= ARRAY_SIZE(shm->captured_iso))
head = 0;
@@ -166,9 +168,10 @@ static inline void usX2Y_usbpcm_urb_capt_iso_advance(snd_usX2Y_substream_t *subs
}
}
-static inline int usX2Y_usbpcm_usbframe_complete(snd_usX2Y_substream_t *capsubs,
- snd_usX2Y_substream_t *capsubs2,
- snd_usX2Y_substream_t *playbacksubs, int frame)
+static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs,
+ struct snd_usX2Y_substream *capsubs2,
+ struct snd_usX2Y_substream *playbacksubs,
+ int frame)
{
int err, state;
struct urb *urb = playbacksubs->completed_urb;
@@ -177,10 +180,8 @@ static inline int usX2Y_usbpcm_usbframe_complete(snd_usX2Y_substream_t *capsubs,
if (NULL != urb) {
if (state == state_RUNNING)
usX2Y_urb_play_retire(playbacksubs, urb);
- else
- if (state >= state_PRERUNNING) {
- atomic_inc(&playbacksubs->state);
- }
+ else if (state >= state_PRERUNNING)
+ atomic_inc(&playbacksubs->state);
} else {
switch (state) {
case state_STARTING1:
@@ -207,10 +208,8 @@ static inline int usX2Y_usbpcm_usbframe_complete(snd_usX2Y_substream_t *capsubs,
if (state == state_RUNNING) {
if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs)))
return err;
- } else {
- if (state >= state_PRERUNNING)
- atomic_inc(&capsubs->state);
- }
+ } else if (state >= state_PRERUNNING)
+ atomic_inc(&capsubs->state);
usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb);
if (NULL != capsubs2)
usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb);
@@ -229,12 +228,15 @@ static inline int usX2Y_usbpcm_usbframe_complete(snd_usX2Y_substream_t *capsubs,
static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
- usX2Ydev_t *usX2Y = subs->usX2Y;
- snd_usX2Y_substream_t *capsubs, *capsubs2, *playbacksubs;
+ struct snd_usX2Y_substream *subs = urb->context;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs;
if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
- snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", usb_get_current_frame_number(usX2Y->chip.dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame);
+ snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
+ usb_get_current_frame_number(usX2Y->chip.dev),
+ subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
+ urb->status, urb->start_frame);
return;
}
if (unlikely(urb->status)) {
@@ -268,7 +270,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
}
-static void usX2Y_hwdep_urb_release(struct urb** urb)
+static void usX2Y_hwdep_urb_release(struct urb **urb)
{
usb_kill_urb(*urb);
usb_free_urb(*urb);
@@ -278,7 +280,7 @@ static void usX2Y_hwdep_urb_release(struct urb** urb)
/*
* release a substream
*/
-static void usX2Y_usbpcm_urbs_release(snd_usX2Y_substream_t *subs)
+static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs)
{
int i;
snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint);
@@ -286,7 +288,7 @@ static void usX2Y_usbpcm_urbs_release(snd_usX2Y_substream_t *subs)
usX2Y_hwdep_urb_release(subs->urb + i);
}
-static void usX2Y_usbpcm_subs_startup_finish(usX2Ydev_t * usX2Y)
+static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y)
{
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete);
usX2Y->prepare_subs = NULL;
@@ -294,14 +296,14 @@ static void usX2Y_usbpcm_subs_startup_finish(usX2Ydev_t * usX2Y)
static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs)
{
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t*)urb->context;
- usX2Ydev_t *usX2Y = subs->usX2Y;
- snd_usX2Y_substream_t *prepare_subs = usX2Y->prepare_subs;
+ struct snd_usX2Y_substream *subs = urb->context;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs;
if (NULL != prepare_subs &&
urb->start_frame == prepare_subs->urb[0]->start_frame) {
atomic_inc(&prepare_subs->state);
if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) {
- snd_usX2Y_substream_t *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
+ struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
if (cap_subs2 != NULL)
atomic_inc(&cap_subs2->state);
}
@@ -315,7 +317,7 @@ static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs)
/*
* initialize a substream's urbs
*/
-static int usX2Y_usbpcm_urbs_allocate(snd_usX2Y_substream_t *subs)
+static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs)
{
int i;
unsigned int pipe;
@@ -330,7 +332,7 @@ static int usX2Y_usbpcm_urbs_allocate(snd_usX2Y_substream_t *subs)
/* allocate and initialize data urbs */
for (i = 0; i < NRURBS; i++) {
- struct urb** purb = subs->urb + i;
+ struct urb **purb = subs->urb + i;
if (*purb) {
usb_kill_urb(*purb);
continue;
@@ -359,16 +361,16 @@ static int usX2Y_usbpcm_urbs_allocate(snd_usX2Y_substream_t *subs)
/*
* free the buffer
*/
-static int snd_usX2Y_usbpcm_hw_free(snd_pcm_substream_t *substream)
+static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data,
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data,
*cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2];
down(&subs->usX2Y->prepare_mutex);
snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) {
- snd_usX2Y_substream_t *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
+ struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
atomic_set(&subs->state, state_STOPPED);
usX2Y_usbpcm_urbs_release(subs);
if (!cap_subs->pcm_substream ||
@@ -383,7 +385,7 @@ static int snd_usX2Y_usbpcm_hw_free(snd_pcm_substream_t *substream)
usX2Y_usbpcm_urbs_release(cap_subs2);
}
} else {
- snd_usX2Y_substream_t *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
+ struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
if (atomic_read(&playback_subs->state) < state_PREPARED) {
atomic_set(&subs->state, state_STOPPED);
if (NULL != cap_subs2)
@@ -397,20 +399,20 @@ static int snd_usX2Y_usbpcm_hw_free(snd_pcm_substream_t *substream)
return snd_pcm_lib_free_pages(substream);
}
-static void usX2Y_usbpcm_subs_startup(snd_usX2Y_substream_t *subs)
+static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
{
- usX2Ydev_t * usX2Y = subs->usX2Y;
+ struct usX2Ydev * usX2Y = subs->usX2Y;
usX2Y->prepare_subs = subs;
subs->urb[0]->start_frame = -1;
smp_wmb(); // Make shure above modifications are seen by i_usX2Y_subs_startup()
usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup);
}
-static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs)
+static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
{
int p, u, err,
stream = subs->pcm_substream->stream;
- usX2Ydev_t *usX2Y = subs->usX2Y;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
if (SNDRV_PCM_STREAM_CAPTURE == stream) {
usX2Y->hwdep_pcm_shm->captured_iso_head = -1;
@@ -418,7 +420,7 @@ static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs)
}
for (p = 0; 3 >= (stream + p); p += 2) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[stream + p];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p];
if (subs != NULL) {
if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0)
return err;
@@ -427,7 +429,7 @@ static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs)
}
for (p = 0; p < 4; p++) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[p];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[p];
if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
goto start;
}
@@ -437,7 +439,7 @@ static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs)
usX2Y_usbpcm_subs_startup(subs);
for (u = 0; u < NRURBS; u++) {
for (p = 0; 3 >= (stream + p); p += 2) {
- snd_usX2Y_substream_t *subs = usX2Y->subs[stream + p];
+ struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p];
if (subs != NULL) {
struct urb *urb = subs->urb[u];
if (usb_pipein(urb->pipe)) {
@@ -486,19 +488,19 @@ static int usX2Y_usbpcm_urbs_start(snd_usX2Y_substream_t *subs)
*
* set format and initialize urbs
*/
-static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
+static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
- usX2Ydev_t *usX2Y = subs->usX2Y;
- snd_usX2Y_substream_t *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data;
+ struct usX2Ydev *usX2Y = subs->usX2Y;
+ struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE];
int err = 0;
snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream);
if (NULL == usX2Y->hwdep_pcm_shm) {
- if (NULL == (usX2Y->hwdep_pcm_shm = snd_malloc_pages(sizeof(snd_usX2Y_hwdep_pcm_shm_t), GFP_KERNEL)))
+ if (NULL == (usX2Y->hwdep_pcm_shm = snd_malloc_pages(sizeof(struct snd_usX2Y_hwdep_pcm_shm), GFP_KERNEL)))
return -ENOMEM;
- memset(usX2Y->hwdep_pcm_shm, 0, sizeof(snd_usX2Y_hwdep_pcm_shm_t));
+ memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
}
down(&usX2Y->prepare_mutex);
@@ -512,7 +514,8 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
if (usX2Y->rate != runtime->rate)
if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0)
goto up_prepare_mutex;
- snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe");
+ snd_printdd("starting capture pipe for %s\n", subs == capsubs ?
+ "self" : "playpipe");
if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs)))
goto up_prepare_mutex;
}
@@ -520,8 +523,12 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
if (subs != capsubs) {
usX2Y->hwdep_pcm_shm->playback_iso_start = -1;
if (atomic_read(&subs->state) < state_PREPARED) {
- while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > usX2Y->hwdep_pcm_shm->captured_iso_frames) {
- snd_printd("Wait: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames);
+ while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) >
+ usX2Y->hwdep_pcm_shm->captured_iso_frames) {
+ snd_printdd("Wait: iso_frames_per_buffer=%i,"
+ "captured_iso_frames=%i\n",
+ usX2Y_iso_frames_per_buffer(runtime, usX2Y),
+ usX2Y->hwdep_pcm_shm->captured_iso_frames);
if (msleep_interruptible(10)) {
err = -ERESTARTSYS;
goto up_prepare_mutex;
@@ -530,7 +537,9 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
if (0 > (err = usX2Y_usbpcm_urbs_start(subs)))
goto up_prepare_mutex;
}
- snd_printd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", usX2Y_iso_frames_per_buffer(runtime, usX2Y), usX2Y->hwdep_pcm_shm->captured_iso_frames);
+ snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n",
+ usX2Y_iso_frames_per_buffer(runtime, usX2Y),
+ usX2Y->hwdep_pcm_shm->captured_iso_frames);
} else
usX2Y->hwdep_pcm_shm->capture_iso_start = -1;
@@ -539,7 +548,7 @@ static int snd_usX2Y_usbpcm_prepare(snd_pcm_substream_t *substream)
return err;
}
-static snd_pcm_hardware_t snd_usX2Y_4c =
+static struct snd_pcm_hardware snd_usX2Y_4c =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -560,11 +569,11 @@ static snd_pcm_hardware_t snd_usX2Y_4c =
-static int snd_usX2Y_usbpcm_open(snd_pcm_substream_t *substream)
+static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream)
{
- snd_usX2Y_substream_t *subs = ((snd_usX2Y_substream_t **)
+ struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **)
snd_pcm_substream_chip(substream))[substream->stream];
- snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS))
return -EBUSY;
@@ -578,18 +587,17 @@ static int snd_usX2Y_usbpcm_open(snd_pcm_substream_t *substream)
}
-static int snd_usX2Y_usbpcm_close(snd_pcm_substream_t *substream)
+static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream)
{
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_usX2Y_substream_t *subs = (snd_usX2Y_substream_t *)runtime->private_data;
- int err = 0;
- snd_printd("\n");
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_usX2Y_substream *subs = runtime->private_data;
+
subs->pcm_substream = NULL;
- return err;
+ return 0;
}
-static snd_pcm_ops_t snd_usX2Y_usbpcm_ops =
+static struct snd_pcm_ops snd_usX2Y_usbpcm_ops =
{
.open = snd_usX2Y_usbpcm_open,
.close = snd_usX2Y_usbpcm_close,
@@ -602,11 +610,11 @@ static snd_pcm_ops_t snd_usX2Y_usbpcm_ops =
};
-static int usX2Y_pcms_lock_check(snd_card_t *card)
+static int usX2Y_pcms_lock_check(struct snd_card *card)
{
struct list_head *list;
- snd_device_t *dev;
- snd_pcm_t *pcm;
+ struct snd_device *dev;
+ struct snd_pcm *pcm;
int err = 0;
list_for_each(list, &card->devices) {
dev = snd_device(list);
@@ -622,7 +630,7 @@ static int usX2Y_pcms_lock_check(snd_card_t *card)
continue;
pcm = dev->device_data;
for (s = 0; s < 2; ++s) {
- snd_pcm_substream_t *substream;
+ struct snd_pcm_substream *substream;
substream = pcm->streams[s].substream;
if (substream && substream->ffile != NULL)
err = -EBUSY;
@@ -632,11 +640,11 @@ static int usX2Y_pcms_lock_check(snd_card_t *card)
}
-static void usX2Y_pcms_unlock(snd_card_t *card)
+static void usX2Y_pcms_unlock(struct snd_card *card)
{
struct list_head *list;
- snd_device_t *dev;
- snd_pcm_t *pcm;
+ struct snd_device *dev;
+ struct snd_pcm *pcm;
list_for_each(list, &card->devices) {
dev = snd_device(list);
if (dev->type != SNDRV_DEV_PCM)
@@ -647,10 +655,10 @@ static void usX2Y_pcms_unlock(snd_card_t *card)
}
-static int snd_usX2Y_hwdep_pcm_open(snd_hwdep_t *hw, struct file *file)
+static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file)
{
// we need to be the first
- snd_card_t *card = hw->card;
+ struct snd_card *card = hw->card;
int err = usX2Y_pcms_lock_check(card);
if (0 == err)
usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS;
@@ -659,9 +667,9 @@ static int snd_usX2Y_hwdep_pcm_open(snd_hwdep_t *hw, struct file *file)
}
-static int snd_usX2Y_hwdep_pcm_release(snd_hwdep_t *hw, struct file *file)
+static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file)
{
- snd_card_t *card = hw->card;
+ struct snd_card *card = hw->card;
int err = usX2Y_pcms_lock_check(card);
if (0 == err)
usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS;
@@ -689,7 +697,7 @@ static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area,
offset = area->vm_pgoff << PAGE_SHIFT;
offset += address - area->vm_start;
snd_assert((offset % PAGE_SIZE) == 0, return NOPAGE_OOM);
- vaddr = (char*)((usX2Ydev_t*)area->vm_private_data)->hwdep_pcm_shm + offset;
+ vaddr = (char*)((struct usX2Ydev *)area->vm_private_data)->hwdep_pcm_shm + offset;
page = virt_to_page(vaddr);
get_page(page);
@@ -707,17 +715,17 @@ static struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = {
};
-static int snd_usX2Y_hwdep_pcm_mmap(snd_hwdep_t * hw, struct file *filp, struct vm_area_struct *area)
+static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area)
{
unsigned long size = (unsigned long)(area->vm_end - area->vm_start);
- usX2Ydev_t *usX2Y = (usX2Ydev_t*)hw->private_data;
+ struct usX2Ydev *usX2Y = hw->private_data;
- if (!(((usX2Ydev_t*)hw->private_data)->chip_status & USX2Y_STAT_CHIP_INIT))
+ if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT))
return -EBUSY;
/* if userspace tries to mmap beyond end of our buffer, fail */
- if (size > PAGE_ALIGN(sizeof(snd_usX2Y_hwdep_pcm_shm_t))) {
- snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(snd_usX2Y_hwdep_pcm_shm_t));
+ if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) {
+ snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm));
return -EINVAL;
}
@@ -726,39 +734,31 @@ static int snd_usX2Y_hwdep_pcm_mmap(snd_hwdep_t * hw, struct file *filp, struct
}
area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;
area->vm_flags |= VM_RESERVED;
- snd_printd("vm_flags=0x%lX\n", area->vm_flags);
area->vm_private_data = hw->private_data;
return 0;
}
-static void snd_usX2Y_hwdep_pcm_private_free(snd_hwdep_t *hwdep)
+static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep)
{
- usX2Ydev_t *usX2Y = (usX2Ydev_t *)hwdep->private_data;
+ struct usX2Ydev *usX2Y = hwdep->private_data;
if (NULL != usX2Y->hwdep_pcm_shm)
- snd_free_pages(usX2Y->hwdep_pcm_shm, sizeof(snd_usX2Y_hwdep_pcm_shm_t));
+ snd_free_pages(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm));
}
-static void snd_usX2Y_usbpcm_private_free(snd_pcm_t *pcm)
-{
- snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-
-int usX2Y_hwdep_pcm_new(snd_card_t* card)
+int usX2Y_hwdep_pcm_new(struct snd_card *card)
{
int err;
- snd_hwdep_t *hw;
- snd_pcm_t *pcm;
+ struct snd_hwdep *hw;
+ struct snd_pcm *pcm;
struct usb_device *dev = usX2Y(card)->chip.dev;
if (1 != nr_of_packs())
return 0;
- if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0) {
- snd_printd("\n");
+ if ((err = snd_hwdep_new(card, SND_USX2Y_USBPCM_ID, 1, &hw)) < 0)
return err;
- }
+
hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM;
hw->private_data = usX2Y(card);
hw->private_free = snd_usX2Y_hwdep_pcm_private_free;
@@ -776,7 +776,6 @@ int usX2Y_hwdep_pcm_new(snd_card_t* card)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops);
pcm->private_data = usX2Y(card)->subs;
- pcm->private_free = snd_usX2Y_usbpcm_private_free;
pcm->info_flags = 0;
sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");
@@ -788,7 +787,6 @@ int usX2Y_hwdep_pcm_new(snd_card_t* card)
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
64*1024, 128*1024))) {
- snd_usX2Y_usbpcm_private_free(pcm);
return err;
}
@@ -798,7 +796,7 @@ int usX2Y_hwdep_pcm_new(snd_card_t* card)
#else
-int usX2Y_hwdep_pcm_new(snd_card_t* card)
+int usX2Y_hwdep_pcm_new(struct snd_card *card)
{
return 0;
}
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h
index d68f0cbdbbe2..c3382fdc386b 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.h
+++ b/sound/usb/usx2y/usx2yhwdeppcm.h
@@ -18,4 +18,3 @@ struct snd_usX2Y_hwdep_pcm_shm {
volatile unsigned captured_iso_frames;
int capture_iso_start;
};
-typedef struct snd_usX2Y_hwdep_pcm_shm snd_usX2Y_hwdep_pcm_shm_t;